Repository: tink-crypto/tink Branch: master Commit: 1f4cd38874ec Files: 3712 Total size: 39.5 MB Directory structure: gitextract_6vi1w9d7/ ├── .bazelversion ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.md │ │ ├── config.yml │ │ └── feature_request.md │ └── workflows/ │ └── codeql-analysis.yml ├── .gitignore ├── BUILD.bazel ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cc/ │ ├── .bazelignore │ ├── .bazelrc │ ├── .bazelversion │ ├── BUILD.bazel │ ├── CMakeLists.txt │ ├── WORKSPACE │ ├── aead/ │ │ ├── BUILD.bazel │ │ ├── CMakeLists.txt │ │ ├── aead_config.cc │ │ ├── aead_config.h │ │ ├── aead_config_test.cc │ │ ├── aead_factory.cc │ │ ├── aead_factory.h │ │ ├── aead_factory_test.cc │ │ ├── aead_key.h │ │ ├── aead_key_templates.cc │ │ ├── aead_key_templates.h │ │ ├── aead_key_templates_test.cc │ │ ├── aead_parameters.h │ │ ├── aead_wrapper.cc │ │ ├── aead_wrapper.h │ │ ├── aead_wrapper_test.cc │ │ ├── aes_ctr_hmac_aead_key.cc │ │ ├── aes_ctr_hmac_aead_key.h │ │ ├── aes_ctr_hmac_aead_key_manager.cc │ │ ├── aes_ctr_hmac_aead_key_manager.h │ │ ├── aes_ctr_hmac_aead_key_manager_test.cc │ │ ├── aes_ctr_hmac_aead_key_test.cc │ │ ├── aes_ctr_hmac_aead_parameters.cc │ │ ├── aes_ctr_hmac_aead_parameters.h │ │ ├── aes_ctr_hmac_aead_parameters_test.cc │ │ ├── aes_ctr_hmac_aead_proto_serialization.cc │ │ ├── aes_ctr_hmac_aead_proto_serialization.h │ │ ├── aes_ctr_hmac_aead_proto_serialization_test.cc │ │ ├── aes_eax_key.cc │ │ ├── aes_eax_key.h │ │ ├── aes_eax_key_manager.h │ │ ├── aes_eax_key_manager_test.cc │ │ ├── aes_eax_key_test.cc │ │ ├── aes_eax_parameters.cc │ │ ├── aes_eax_parameters.h │ │ ├── aes_eax_parameters_test.cc │ │ ├── aes_eax_proto_serialization.cc │ │ ├── aes_eax_proto_serialization.h │ │ ├── aes_eax_proto_serialization_test.cc │ │ ├── aes_gcm_key.cc │ │ ├── aes_gcm_key.h │ │ ├── aes_gcm_key_manager.h │ │ ├── aes_gcm_key_manager_test.cc │ │ ├── aes_gcm_key_test.cc │ │ ├── aes_gcm_parameters.cc │ │ ├── aes_gcm_parameters.h │ │ ├── aes_gcm_parameters_test.cc │ │ ├── aes_gcm_proto_serialization.cc │ │ ├── aes_gcm_proto_serialization.h │ │ ├── aes_gcm_proto_serialization_test.cc │ │ ├── aes_gcm_siv_key.cc │ │ ├── aes_gcm_siv_key.h │ │ ├── aes_gcm_siv_key_manager.h │ │ ├── aes_gcm_siv_key_manager_test.cc │ │ ├── aes_gcm_siv_key_test.cc │ │ ├── aes_gcm_siv_parameters.cc │ │ ├── aes_gcm_siv_parameters.h │ │ ├── aes_gcm_siv_parameters_test.cc │ │ ├── aes_gcm_siv_proto_serialization.cc │ │ ├── aes_gcm_siv_proto_serialization.h │ │ ├── aes_gcm_siv_proto_serialization_test.cc │ │ ├── chacha20_poly1305_key.cc │ │ ├── chacha20_poly1305_key.h │ │ ├── chacha20_poly1305_key_test.cc │ │ ├── chacha20_poly1305_parameters.cc │ │ ├── chacha20_poly1305_parameters.h │ │ ├── chacha20_poly1305_parameters_test.cc │ │ ├── chacha20_poly1305_proto_serialization.cc │ │ ├── chacha20_poly1305_proto_serialization.h │ │ ├── chacha20_poly1305_proto_serialization_test.cc │ │ ├── config_v0.cc │ │ ├── config_v0.h │ │ ├── config_v0_test.cc │ │ ├── cord_aead.h │ │ ├── cord_aead_wrapper.cc │ │ ├── cord_aead_wrapper.h │ │ ├── cord_aead_wrapper_test.cc │ │ ├── failing_aead.cc │ │ ├── failing_aead.h │ │ ├── failing_aead_test.cc │ │ ├── internal/ │ │ │ ├── BUILD.bazel │ │ │ ├── CMakeLists.txt │ │ │ ├── aead_from_zero_copy.cc │ │ │ ├── aead_from_zero_copy.h │ │ │ ├── aead_from_zero_copy_test.cc │ │ │ ├── aead_util.cc │ │ │ ├── aead_util.h │ │ │ ├── aead_util_test.cc │ │ │ ├── config_v0.cc │ │ │ ├── config_v0.h │ │ │ ├── config_v0_test.cc │ │ │ ├── cord_aes_gcm_boringssl.cc │ │ │ ├── cord_aes_gcm_boringssl.h │ │ │ ├── cord_aes_gcm_boringssl_test.cc │ │ │ ├── key_gen_config_v0.cc │ │ │ ├── key_gen_config_v0.h │ │ │ ├── mock_zero_copy_aead.h │ │ │ ├── ssl_aead.cc │ │ │ ├── ssl_aead.h │ │ │ ├── ssl_aead_large_inputs_test.cc │ │ │ ├── ssl_aead_test.cc │ │ │ ├── wycheproof_aead.cc │ │ │ ├── wycheproof_aead.h │ │ │ ├── zero_copy_aead.h │ │ │ ├── zero_copy_aead_wrapper.cc │ │ │ ├── zero_copy_aead_wrapper.h │ │ │ ├── zero_copy_aead_wrapper_test.cc │ │ │ ├── zero_copy_aes_gcm_boringssl.cc │ │ │ ├── zero_copy_aes_gcm_boringssl.h │ │ │ └── zero_copy_aes_gcm_boringssl_test.cc │ │ ├── key_gen_config_v0.cc │ │ ├── key_gen_config_v0.h │ │ ├── kms_aead_key_manager.h │ │ ├── kms_aead_key_manager_test.cc │ │ ├── kms_envelope_aead.cc │ │ ├── kms_envelope_aead.h │ │ ├── kms_envelope_aead_key_manager.cc │ │ ├── kms_envelope_aead_key_manager.h │ │ ├── kms_envelope_aead_key_manager_test.cc │ │ ├── kms_envelope_aead_test.cc │ │ ├── mock_aead.h │ │ ├── subtle/ │ │ │ ├── BUILD.bazel │ │ │ └── CMakeLists.txt │ │ ├── xchacha20_poly1305_key.cc │ │ ├── xchacha20_poly1305_key.h │ │ ├── xchacha20_poly1305_key_manager.h │ │ ├── xchacha20_poly1305_key_manager_test.cc │ │ ├── xchacha20_poly1305_key_test.cc │ │ ├── xchacha20_poly1305_parameters.cc │ │ ├── xchacha20_poly1305_parameters.h │ │ ├── xchacha20_poly1305_parameters_test.cc │ │ ├── xchacha20_poly1305_proto_serialization.cc │ │ ├── xchacha20_poly1305_proto_serialization.h │ │ └── xchacha20_poly1305_proto_serialization_test.cc │ ├── aead.h │ ├── aead_config.h │ ├── aead_factory.h │ ├── aead_key_templates.h │ ├── big_integer.h │ ├── binary_keyset_reader.h │ ├── binary_keyset_writer.h │ ├── chunked_mac.h │ ├── cleartext_keyset_handle.h │ ├── config/ │ │ ├── BUILD.bazel │ │ ├── CMakeLists.txt │ │ ├── config_util.cc │ │ ├── config_util.h │ │ ├── config_util_test.cc │ │ ├── fips_140_2.cc │ │ ├── fips_140_2.h │ │ ├── fips_140_2_test.cc │ │ ├── global_registry.cc │ │ ├── global_registry.h │ │ ├── global_registry_test.cc │ │ ├── internal/ │ │ │ ├── BUILD.bazel │ │ │ └── CMakeLists.txt │ │ ├── key_gen_fips_140_2.cc │ │ ├── key_gen_fips_140_2.h │ │ ├── key_gen_fips_140_2_test.cc │ │ ├── key_gen_v0.cc │ │ ├── key_gen_v0.h │ │ ├── tink_config.cc │ │ ├── tink_config.h │ │ ├── tink_config_test.cc │ │ ├── tink_fips.cc │ │ ├── tink_fips.h │ │ ├── tink_fips_test.cc │ │ ├── v0.cc │ │ ├── v0.h │ │ └── v0_test.cc │ ├── configuration.h │ ├── core/ │ │ ├── big_integer.cc │ │ ├── big_integer_test.cc │ │ ├── binary_keyset_reader.cc │ │ ├── binary_keyset_reader_test.cc │ │ ├── binary_keyset_writer.cc │ │ ├── binary_keyset_writer_test.cc │ │ ├── cleartext_keyset_handle.cc │ │ ├── cleartext_keyset_handle_test.cc │ │ ├── crypto_format.cc │ │ ├── crypto_format_test.cc │ │ ├── ec_point_test.cc │ │ ├── json_keyset_reader.cc │ │ ├── json_keyset_reader_test.cc │ │ ├── json_keyset_writer.cc │ │ ├── json_keyset_writer_test.cc │ │ ├── key_access_test.cc │ │ ├── key_manager.cc │ │ ├── key_manager_impl.h │ │ ├── key_manager_impl_test.cc │ │ ├── key_manager_test.cc │ │ ├── key_type_manager.h │ │ ├── key_type_manager_test.cc │ │ ├── keyset_handle.cc │ │ ├── keyset_handle_builder.cc │ │ ├── keyset_handle_builder_test.cc │ │ ├── keyset_handle_test.cc │ │ ├── keyset_manager.cc │ │ ├── keyset_manager_test.cc │ │ ├── kms_clients.cc │ │ ├── kms_clients_test.cc │ │ ├── partial_key_access_token_test.cc │ │ ├── primitive_set_test.cc │ │ ├── private_key_manager_impl.h │ │ ├── private_key_manager_impl_test.cc │ │ ├── private_key_type_manager.h │ │ ├── restricted_big_integer.cc │ │ ├── restricted_big_integer_test.cc │ │ ├── restricted_data.cc │ │ ├── restricted_data_test.cc │ │ ├── template_util.h │ │ ├── template_util_test.cc │ │ ├── version.cc │ │ └── version_test.cc │ ├── crypto_format.h │ ├── daead/ │ │ ├── BUILD.bazel │ │ ├── CMakeLists.txt │ │ ├── aes_siv_key.cc │ │ ├── aes_siv_key.h │ │ ├── aes_siv_key_manager.h │ │ ├── aes_siv_key_manager_test.cc │ │ ├── aes_siv_key_test.cc │ │ ├── aes_siv_parameters.cc │ │ ├── aes_siv_parameters.h │ │ ├── aes_siv_parameters_test.cc │ │ ├── aes_siv_proto_serialization.cc │ │ ├── aes_siv_proto_serialization.h │ │ ├── aes_siv_proto_serialization_test.cc │ │ ├── config_v0.cc │ │ ├── config_v0.h │ │ ├── config_v0_test.cc │ │ ├── deterministic_aead_config.cc │ │ ├── deterministic_aead_config.h │ │ ├── deterministic_aead_config_test.cc │ │ ├── deterministic_aead_factory.cc │ │ ├── deterministic_aead_factory.h │ │ ├── deterministic_aead_factory_test.cc │ │ ├── deterministic_aead_key.h │ │ ├── deterministic_aead_key_templates.cc │ │ ├── deterministic_aead_key_templates.h │ │ ├── deterministic_aead_key_templates_test.cc │ │ ├── deterministic_aead_parameters.h │ │ ├── deterministic_aead_wrapper.cc │ │ ├── deterministic_aead_wrapper.h │ │ ├── deterministic_aead_wrapper_test.cc │ │ ├── failing_daead.cc │ │ ├── failing_daead.h │ │ ├── failing_daead_test.cc │ │ ├── internal/ │ │ │ ├── BUILD.bazel │ │ │ ├── CMakeLists.txt │ │ │ ├── config_v0.cc │ │ │ ├── config_v0.h │ │ │ ├── config_v0_test.cc │ │ │ ├── key_gen_config_v0.cc │ │ │ └── key_gen_config_v0.h │ │ ├── key_gen_config_v0.cc │ │ ├── key_gen_config_v0.h │ │ └── subtle/ │ │ ├── BUILD.bazel │ │ ├── CMakeLists.txt │ │ ├── aead_or_daead.cc │ │ ├── aead_or_daead.h │ │ └── aead_or_daead_test.cc │ ├── deterministic_aead.h │ ├── deterministic_aead_config.h │ ├── deterministic_aead_factory.h │ ├── deterministic_aead_key_templates.h │ ├── ec_point.h │ ├── examples/ │ │ ├── .bazelrc │ │ ├── .bazelversion │ │ ├── CMakeLists.txt │ │ ├── WORKSPACE │ │ ├── aead/ │ │ │ ├── BUILD.bazel │ │ │ ├── CMakeLists.txt │ │ │ ├── aead_cli.cc │ │ │ ├── aead_cli_test.sh │ │ │ └── aead_test_keyset.json │ │ ├── daead/ │ │ │ ├── BUILD.bazel │ │ │ ├── CMakeLists.txt │ │ │ ├── deterministic_aead_cli.cc │ │ │ ├── deterministic_aead_cli_test.sh │ │ │ └── deterministic_aead_test_keyset.json │ │ ├── digital_signatures/ │ │ │ ├── BUILD.bazel │ │ │ ├── CMakeLists.txt │ │ │ ├── digital_signature_private_keyset.json │ │ │ ├── digital_signature_public_keyset.json │ │ │ ├── digital_signatures_cli.cc │ │ │ └── digital_signatures_cli_test.sh │ │ ├── hybrid_encryption/ │ │ │ ├── BUILD.bazel │ │ │ ├── CMakeLists.txt │ │ │ ├── hybrid_cli.cc │ │ │ ├── hybrid_cli_test.sh │ │ │ └── testdata/ │ │ │ ├── BUILD.bazel │ │ │ ├── hpke_test_private_keyset.json │ │ │ ├── hpke_test_public_keyset.json │ │ │ ├── hybrid_test_private_keyset.json │ │ │ └── hybrid_test_public_keyset.json │ │ ├── jwt/ │ │ │ ├── BUILD.bazel │ │ │ ├── CMakeLists.txt │ │ │ ├── jwt_generate_public_jwk_set.cc │ │ │ ├── jwt_sign.cc │ │ │ ├── jwt_signature_cli_test.sh │ │ │ ├── jwt_signature_private_keyset.json │ │ │ ├── jwt_signature_public_keyset.json │ │ │ └── jwt_verify.cc │ │ ├── key_derivation/ │ │ │ ├── BUILD.bazel │ │ │ ├── CMakeLists.txt │ │ │ ├── key_derivation_cli.cc │ │ │ ├── key_derivation_cli_test.sh │ │ │ └── keyset.json │ │ ├── mac/ │ │ │ ├── BUILD.bazel │ │ │ ├── CMakeLists.txt │ │ │ ├── mac_cli.cc │ │ │ ├── mac_cli_test.sh │ │ │ └── mac_test_keyset.json │ │ ├── util/ │ │ │ ├── BUILD.bazel │ │ │ ├── CMakeLists.txt │ │ │ ├── util.cc │ │ │ └── util.h │ │ └── walkthrough/ │ │ ├── BUILD.bazel │ │ ├── CMakeLists.txt │ │ ├── create_keyset.cc │ │ ├── create_keyset.h │ │ ├── create_keyset_test.cc │ │ ├── load_cleartext_keyset.cc │ │ ├── load_cleartext_keyset.h │ │ ├── load_cleartext_keyset_test.cc │ │ ├── load_encrypted_keyset.cc │ │ ├── load_encrypted_keyset.h │ │ ├── load_encrypted_keyset_test.cc │ │ ├── obtain_and_use_a_primitive.cc │ │ ├── obtain_and_use_a_primitive.h │ │ ├── obtain_and_use_a_primitive_test.cc │ │ ├── test_util.cc │ │ ├── test_util.h │ │ ├── write_cleartext_keyset.cc │ │ ├── write_cleartext_keyset.h │ │ ├── write_cleartext_keyset_test.cc │ │ ├── write_keyset.cc │ │ ├── write_keyset.h │ │ └── write_keyset_test.cc │ ├── experimental/ │ │ └── pqcrypto/ │ │ ├── README.md │ │ ├── kem/ │ │ │ ├── BUILD.bazel │ │ │ ├── cecpq2_aead_hkdf_dem_helper.cc │ │ │ ├── cecpq2_aead_hkdf_dem_helper.h │ │ │ ├── cecpq2_aead_hkdf_dem_helper_test.cc │ │ │ ├── cecpq2_aead_hkdf_private_key_manager.cc │ │ │ ├── cecpq2_aead_hkdf_private_key_manager.h │ │ │ ├── cecpq2_aead_hkdf_private_key_manager_test.cc │ │ │ ├── cecpq2_aead_hkdf_public_key_manager.cc │ │ │ ├── cecpq2_aead_hkdf_public_key_manager.h │ │ │ ├── cecpq2_aead_hkdf_public_key_manager_test.cc │ │ │ ├── cecpq2_hybrid_config.cc │ │ │ ├── cecpq2_hybrid_config.h │ │ │ ├── cecpq2_hybrid_config_test.cc │ │ │ ├── cecpq2_hybrid_key_templates.cc │ │ │ ├── cecpq2_hybrid_key_templates.h │ │ │ ├── cecpq2_hybrid_key_templates_test.cc │ │ │ ├── subtle/ │ │ │ │ ├── BUILD.bazel │ │ │ │ ├── cecpq2_aead_hkdf_hybrid_decrypt.cc │ │ │ │ ├── cecpq2_aead_hkdf_hybrid_decrypt.h │ │ │ │ ├── cecpq2_aead_hkdf_hybrid_decrypt_test.cc │ │ │ │ ├── cecpq2_aead_hkdf_hybrid_encrypt.cc │ │ │ │ ├── cecpq2_aead_hkdf_hybrid_encrypt.h │ │ │ │ ├── cecpq2_aead_hkdf_hybrid_encrypt_test.cc │ │ │ │ ├── cecpq2_hkdf_recipient_kem_boringssl.cc │ │ │ │ ├── cecpq2_hkdf_recipient_kem_boringssl.h │ │ │ │ ├── cecpq2_hkdf_recipient_kem_boringssl_test.cc │ │ │ │ ├── cecpq2_hkdf_sender_kem_boringssl.cc │ │ │ │ ├── cecpq2_hkdf_sender_kem_boringssl.h │ │ │ │ ├── cecpq2_hkdf_sender_kem_boringssl_test.cc │ │ │ │ ├── cecpq2_subtle_boringssl_util.cc │ │ │ │ ├── cecpq2_subtle_boringssl_util.h │ │ │ │ └── cecpq2_subtle_boringssl_util_test.cc │ │ │ └── util/ │ │ │ ├── BUILD.bazel │ │ │ ├── test_util.cc │ │ │ ├── test_util.h │ │ │ └── test_util_test.cc │ │ ├── proto/ │ │ │ └── BUILD.bazel │ │ └── signature/ │ │ ├── dilithium_key_template.cc │ │ ├── dilithium_key_template.h │ │ ├── dilithium_key_template_test.cc │ │ ├── dilithium_sign_key_manager.cc │ │ ├── dilithium_sign_key_manager.h │ │ ├── dilithium_sign_key_manager_test.cc │ │ ├── dilithium_verify_key_manager.cc │ │ ├── dilithium_verify_key_manager.h │ │ ├── dilithium_verify_key_manager_test.cc │ │ ├── falcon_key_template.cc │ │ ├── falcon_key_template.h │ │ ├── falcon_key_template_test.cc │ │ ├── falcon_sign_key_manager.cc │ │ ├── falcon_sign_key_manager.h │ │ ├── falcon_sign_key_manager_test.cc │ │ ├── falcon_verify_key_manager.cc │ │ ├── falcon_verify_key_manager.h │ │ ├── falcon_verify_key_manager_test.cc │ │ ├── signature_config.cc │ │ ├── signature_config.h │ │ ├── signature_config_test.cc │ │ ├── signature_config_util_test.cc │ │ ├── slh_dsa_parameters.cc │ │ ├── slh_dsa_parameters.h │ │ ├── slh_dsa_parameters_test.cc │ │ ├── slh_dsa_private_key.cc │ │ ├── slh_dsa_private_key.h │ │ ├── slh_dsa_private_key_test.cc │ │ ├── slh_dsa_proto_serialization.cc │ │ ├── slh_dsa_proto_serialization.h │ │ ├── slh_dsa_proto_serialization_test.cc │ │ ├── slh_dsa_public_key.cc │ │ ├── slh_dsa_public_key.h │ │ ├── slh_dsa_public_key_test.cc │ │ ├── sphincs_key_template.cc │ │ ├── sphincs_key_template.h │ │ ├── sphincs_key_template_test.cc │ │ ├── sphincs_sign_key_manager.cc │ │ ├── sphincs_sign_key_manager.h │ │ ├── sphincs_sign_key_manager_test.cc │ │ ├── sphincs_verify_key_manager.cc │ │ ├── sphincs_verify_key_manager.h │ │ ├── sphincs_verify_key_manager_test.cc │ │ ├── subtle/ │ │ │ ├── dilithium_avx2_sign.cc │ │ │ ├── dilithium_avx2_sign.h │ │ │ ├── dilithium_avx2_sign_test.cc │ │ │ ├── dilithium_avx2_verify.cc │ │ │ ├── dilithium_avx2_verify.h │ │ │ ├── dilithium_avx2_verify_test.cc │ │ │ ├── dilithium_key.cc │ │ │ ├── dilithium_key.h │ │ │ ├── dilithium_key_test.cc │ │ │ ├── falcon_sign.cc │ │ │ ├── falcon_sign.h │ │ │ ├── falcon_sign_test.cc │ │ │ ├── falcon_subtle_utils.cc │ │ │ ├── falcon_subtle_utils.h │ │ │ ├── falcon_subtle_utils_test.cc │ │ │ ├── falcon_verify.cc │ │ │ ├── falcon_verify.h │ │ │ ├── falcon_verify_test.cc │ │ │ ├── sphincs_helper_pqclean.cc │ │ │ ├── sphincs_helper_pqclean.h │ │ │ ├── sphincs_sign.cc │ │ │ ├── sphincs_sign.h │ │ │ ├── sphincs_sign_test.cc │ │ │ ├── sphincs_subtle_utils.cc │ │ │ ├── sphincs_subtle_utils.h │ │ │ ├── sphincs_subtle_utils_test.cc │ │ │ ├── sphincs_verify.cc │ │ │ ├── sphincs_verify.h │ │ │ └── sphincs_verify_test.cc │ │ └── util/ │ │ ├── enums.cc │ │ ├── enums.h │ │ └── enums_test.cc │ ├── exported_symbols.lds │ ├── hybrid/ │ │ ├── BUILD.bazel │ │ ├── CMakeLists.txt │ │ ├── config_v0.cc │ │ ├── config_v0.h │ │ ├── config_v0_test.cc │ │ ├── ecies_aead_hkdf_dem_helper.cc │ │ ├── ecies_aead_hkdf_dem_helper.h │ │ ├── ecies_aead_hkdf_dem_helper_test.cc │ │ ├── ecies_aead_hkdf_hybrid_decrypt.cc │ │ ├── ecies_aead_hkdf_hybrid_decrypt.h │ │ ├── ecies_aead_hkdf_hybrid_decrypt_test.cc │ │ ├── ecies_aead_hkdf_hybrid_encrypt.cc │ │ ├── ecies_aead_hkdf_hybrid_encrypt.h │ │ ├── ecies_aead_hkdf_hybrid_encrypt_test.cc │ │ ├── ecies_aead_hkdf_private_key_manager.cc │ │ ├── ecies_aead_hkdf_private_key_manager.h │ │ ├── ecies_aead_hkdf_private_key_manager_test.cc │ │ ├── ecies_aead_hkdf_public_key_manager.cc │ │ ├── ecies_aead_hkdf_public_key_manager.h │ │ ├── ecies_aead_hkdf_public_key_manager_test.cc │ │ ├── ecies_parameters.cc │ │ ├── ecies_parameters.h │ │ ├── ecies_parameters_test.cc │ │ ├── ecies_private_key.cc │ │ ├── ecies_private_key.h │ │ ├── ecies_private_key_test.cc │ │ ├── ecies_proto_serialization.cc │ │ ├── ecies_proto_serialization.h │ │ ├── ecies_proto_serialization_test.cc │ │ ├── ecies_public_key.cc │ │ ├── ecies_public_key.h │ │ ├── ecies_public_key_test.cc │ │ ├── failing_hybrid.cc │ │ ├── failing_hybrid.h │ │ ├── failing_hybrid_test.cc │ │ ├── hpke_config.cc │ │ ├── hpke_config.h │ │ ├── hpke_config_test.cc │ │ ├── hpke_parameters.cc │ │ ├── hpke_parameters.h │ │ ├── hpke_parameters_test.cc │ │ ├── hpke_private_key.cc │ │ ├── hpke_private_key.h │ │ ├── hpke_private_key_test.cc │ │ ├── hpke_proto_serialization.cc │ │ ├── hpke_proto_serialization.h │ │ ├── hpke_proto_serialization_test.cc │ │ ├── hpke_public_key.cc │ │ ├── hpke_public_key.h │ │ ├── hpke_public_key_test.cc │ │ ├── hybrid_config.cc │ │ ├── hybrid_config.h │ │ ├── hybrid_config_test.cc │ │ ├── hybrid_decrypt_factory.cc │ │ ├── hybrid_decrypt_factory.h │ │ ├── hybrid_decrypt_factory_test.cc │ │ ├── hybrid_decrypt_wrapper.cc │ │ ├── hybrid_decrypt_wrapper.h │ │ ├── hybrid_decrypt_wrapper_test.cc │ │ ├── hybrid_encrypt_factory.cc │ │ ├── hybrid_encrypt_factory.h │ │ ├── hybrid_encrypt_factory_test.cc │ │ ├── hybrid_encrypt_wrapper.cc │ │ ├── hybrid_encrypt_wrapper.h │ │ ├── hybrid_encrypt_wrapper_test.cc │ │ ├── hybrid_key_templates.cc │ │ ├── hybrid_key_templates.h │ │ ├── hybrid_key_templates_test.cc │ │ ├── hybrid_parameters.h │ │ ├── hybrid_private_key.h │ │ ├── hybrid_public_key.h │ │ ├── internal/ │ │ │ ├── BUILD.bazel │ │ │ ├── CMakeLists.txt │ │ │ ├── config_v0.cc │ │ │ ├── config_v0.h │ │ │ ├── config_v0_test.cc │ │ │ ├── hpke_context.cc │ │ │ ├── hpke_context.h │ │ │ ├── hpke_context_boringssl.cc │ │ │ ├── hpke_context_boringssl.h │ │ │ ├── hpke_context_boringssl_test.cc │ │ │ ├── hpke_context_test.cc │ │ │ ├── hpke_decrypt.cc │ │ │ ├── hpke_decrypt.h │ │ │ ├── hpke_decrypt_boringssl.cc │ │ │ ├── hpke_decrypt_boringssl.h │ │ │ ├── hpke_decrypt_boringssl_test.cc │ │ │ ├── hpke_decrypt_test.cc │ │ │ ├── hpke_encrypt.cc │ │ │ ├── hpke_encrypt.h │ │ │ ├── hpke_encrypt_boringssl.cc │ │ │ ├── hpke_encrypt_boringssl.h │ │ │ ├── hpke_encrypt_boringssl_test.cc │ │ │ ├── hpke_encrypt_test.cc │ │ │ ├── hpke_key_boringssl.cc │ │ │ ├── hpke_key_boringssl.h │ │ │ ├── hpke_key_boringssl_test.cc │ │ │ ├── hpke_key_manager_util.cc │ │ │ ├── hpke_key_manager_util.h │ │ │ ├── hpke_key_manager_util_test.cc │ │ │ ├── hpke_private_key_manager.cc │ │ │ ├── hpke_private_key_manager.h │ │ │ ├── hpke_private_key_manager_test.cc │ │ │ ├── hpke_public_key_manager.cc │ │ │ ├── hpke_public_key_manager.h │ │ │ ├── hpke_public_key_manager_test.cc │ │ │ ├── hpke_test_util.cc │ │ │ ├── hpke_test_util.h │ │ │ ├── hpke_util.cc │ │ │ ├── hpke_util.h │ │ │ ├── hpke_util_boringssl.cc │ │ │ ├── hpke_util_boringssl.h │ │ │ ├── hpke_util_boringssl_test.cc │ │ │ ├── hpke_util_test.cc │ │ │ ├── key_gen_config_v0.cc │ │ │ ├── key_gen_config_v0.h │ │ │ ├── test_hpke_context_boringssl.cc │ │ │ └── test_hpke_context_boringssl.h │ │ ├── key_gen_config_v0.cc │ │ ├── key_gen_config_v0.h │ │ └── subtle/ │ │ ├── BUILD.bazel │ │ └── CMakeLists.txt │ ├── hybrid_config.h │ ├── hybrid_decrypt.h │ ├── hybrid_decrypt_factory.h │ ├── hybrid_encrypt.h │ ├── hybrid_encrypt_factory.h │ ├── hybrid_key_templates.h │ ├── input_stream.h │ ├── insecure_secret_key_access.h │ ├── integration/ │ │ ├── awskms/ │ │ │ ├── .bazelrc │ │ │ ├── .bazelversion │ │ │ ├── BUILD.bazel │ │ │ ├── WORKSPACE │ │ │ ├── aws_kms_aead.cc │ │ │ ├── aws_kms_aead.h │ │ │ ├── aws_kms_aead_integration_test.cc │ │ │ ├── aws_kms_client.cc │ │ │ ├── aws_kms_client.h │ │ │ ├── aws_kms_client_test.cc │ │ │ ├── internal/ │ │ │ │ ├── BUILD.bazel │ │ │ │ ├── test_file_util.h │ │ │ │ └── test_file_util_bazel.cc │ │ │ ├── template_rule.bzl │ │ │ ├── testdata/ │ │ │ │ └── aws/ │ │ │ │ ├── BUILD.bazel │ │ │ │ ├── README.md │ │ │ │ ├── access_keys_bad.csv │ │ │ │ ├── credentials.cred │ │ │ │ ├── credentials.csv │ │ │ │ ├── credentials.ini │ │ │ │ ├── credentials_bad.csv │ │ │ │ ├── credentials_bad.ini │ │ │ │ ├── key_arn.txt │ │ │ │ └── key_arn_bad.txt │ │ │ ├── third_party/ │ │ │ │ ├── aws_c_common.BUILD.bazel │ │ │ │ ├── aws_c_event_stream.BUILD.bazel │ │ │ │ ├── aws_checksums.BUILD.bazel │ │ │ │ ├── aws_sdk_cpp.BUILD.bazel │ │ │ │ ├── curl.BUILD.bazel │ │ │ │ └── zlib.BUILD.bazel │ │ │ └── tink_cc_awskms_deps.bzl │ │ └── gcpkms/ │ │ ├── .bazelrc │ │ ├── .bazelversion │ │ ├── BUILD.bazel │ │ ├── WORKSPACE │ │ ├── gcp_kms_aead.cc │ │ ├── gcp_kms_aead.h │ │ ├── gcp_kms_aead_integration_test.cc │ │ ├── gcp_kms_aead_test.cc │ │ ├── gcp_kms_client.cc │ │ ├── gcp_kms_client.h │ │ ├── gcp_kms_client_test.cc │ │ ├── gcp_kms_public_key_sign.cc │ │ ├── gcp_kms_public_key_sign.h │ │ ├── gcp_kms_public_key_sign_test.cc │ │ ├── testdata/ │ │ │ └── gcp/ │ │ │ ├── BUILD.bazel │ │ │ ├── README.md │ │ │ ├── credential.json │ │ │ ├── credential_bad.json │ │ │ ├── key_name.txt │ │ │ └── key_name_bad.txt │ │ ├── tink_cc_gcpkms_deps.bzl │ │ └── tink_cc_gcpkms_deps_init.bzl │ ├── internal/ │ │ ├── BUILD.bazel │ │ ├── CMakeLists.txt │ │ ├── aes_util.cc │ │ ├── aes_util.h │ │ ├── aes_util_test.cc │ │ ├── bn_encoding_util.cc │ │ ├── bn_encoding_util.h │ │ ├── bn_encoding_util_test.cc │ │ ├── bn_util.cc │ │ ├── bn_util.h │ │ ├── bn_util_test.cc │ │ ├── call_with_core_dump_protection.h │ │ ├── call_with_core_dump_protection_test.cc │ │ ├── configuration_impl.h │ │ ├── configuration_impl_test.cc │ │ ├── ec_util.cc │ │ ├── ec_util.h │ │ ├── ec_util_test.cc │ │ ├── err_util.cc │ │ ├── err_util.h │ │ ├── err_util_test.cc │ │ ├── fips_utils.cc │ │ ├── fips_utils.h │ │ ├── fips_utils_test.cc │ │ ├── key_gen_configuration_impl.h │ │ ├── key_gen_configuration_impl_test.cc │ │ ├── key_info.cc │ │ ├── key_info.h │ │ ├── key_info_test.cc │ │ ├── key_parser.h │ │ ├── key_parser_test.cc │ │ ├── key_serializer.h │ │ ├── key_serializer_test.cc │ │ ├── key_status_util.cc │ │ ├── key_status_util.h │ │ ├── key_status_util_test.cc │ │ ├── key_type_info_store.cc │ │ ├── key_type_info_store.h │ │ ├── key_type_info_store_test.cc │ │ ├── keyset_handle_builder_entry.cc │ │ ├── keyset_handle_builder_entry.h │ │ ├── keyset_handle_builder_entry_test.cc │ │ ├── keyset_wrapper.h │ │ ├── keyset_wrapper_impl.h │ │ ├── keyset_wrapper_impl_test.cc │ │ ├── keyset_wrapper_store.h │ │ ├── keyset_wrapper_store_test.cc │ │ ├── legacy_proto_key.cc │ │ ├── legacy_proto_key.h │ │ ├── legacy_proto_key_test.cc │ │ ├── legacy_proto_parameters.cc │ │ ├── legacy_proto_parameters.h │ │ ├── legacy_proto_parameters_test.cc │ │ ├── md_util.cc │ │ ├── md_util.h │ │ ├── md_util_test.cc │ │ ├── monitoring_util.h │ │ ├── monitoring_util_test.cc │ │ ├── mutable_serialization_registry.cc │ │ ├── mutable_serialization_registry.h │ │ ├── mutable_serialization_registry_test.cc │ │ ├── parameters_parser.h │ │ ├── parameters_parser_test.cc │ │ ├── parameters_serializer.h │ │ ├── parameters_serializer_test.cc │ │ ├── parser_index.h │ │ ├── parser_index_test.cc │ │ ├── proto_key_serialization.cc │ │ ├── proto_key_serialization.h │ │ ├── proto_key_serialization_test.cc │ │ ├── proto_parameters_serialization.cc │ │ ├── proto_parameters_serialization.h │ │ ├── proto_parameters_serialization_test.cc │ │ ├── registry_impl.cc │ │ ├── registry_impl.h │ │ ├── registry_impl_test.cc │ │ ├── rsa_util.cc │ │ ├── rsa_util.h │ │ ├── rsa_util_test.cc │ │ ├── safe_stringops.h │ │ ├── safe_stringops_test.cc │ │ ├── serialization.h │ │ ├── serialization_registry.cc │ │ ├── serialization_registry.h │ │ ├── serialization_registry_test.cc │ │ ├── serialization_test_util.h │ │ ├── serialization_test_util_test.cc │ │ ├── serializer_index.h │ │ ├── serializer_index_test.cc │ │ ├── ssl_unique_ptr.h │ │ ├── ssl_util.h │ │ ├── test_file_util.cc │ │ ├── test_file_util.h │ │ ├── test_file_util_bazel.cc │ │ ├── test_file_util_cmake.cc │ │ ├── test_random_access_stream.cc │ │ ├── test_random_access_stream.h │ │ ├── test_random_access_stream_test.cc │ │ ├── util.cc │ │ ├── util.h │ │ └── util_test.cc │ ├── json_keyset_reader.h │ ├── json_keyset_writer.h │ ├── jwt/ │ │ ├── BUILD.bazel │ │ ├── CMakeLists.txt │ │ ├── internal/ │ │ │ ├── BUILD.bazel │ │ │ ├── CMakeLists.txt │ │ │ ├── json_util.cc │ │ │ ├── json_util.h │ │ │ ├── json_util_test.cc │ │ │ ├── jwt_ecdsa_sign_key_manager.cc │ │ │ ├── jwt_ecdsa_sign_key_manager.h │ │ │ ├── jwt_ecdsa_sign_verify_key_manager_test.cc │ │ │ ├── jwt_ecdsa_verify_key_manager.cc │ │ │ ├── jwt_ecdsa_verify_key_manager.h │ │ │ ├── jwt_format.cc │ │ │ ├── jwt_format.h │ │ │ ├── jwt_format_test.cc │ │ │ ├── jwt_hmac_key_manager.cc │ │ │ ├── jwt_hmac_key_manager.h │ │ │ ├── jwt_hmac_key_manager_test.cc │ │ │ ├── jwt_mac_impl.cc │ │ │ ├── jwt_mac_impl.h │ │ │ ├── jwt_mac_impl_test.cc │ │ │ ├── jwt_mac_internal.h │ │ │ ├── jwt_mac_wrapper.cc │ │ │ ├── jwt_mac_wrapper.h │ │ │ ├── jwt_mac_wrapper_test.cc │ │ │ ├── jwt_public_key_sign_impl.cc │ │ │ ├── jwt_public_key_sign_impl.h │ │ │ ├── jwt_public_key_sign_internal.h │ │ │ ├── jwt_public_key_sign_verify_impl_test.cc │ │ │ ├── jwt_public_key_sign_wrapper.cc │ │ │ ├── jwt_public_key_sign_wrapper.h │ │ │ ├── jwt_public_key_verify_impl.cc │ │ │ ├── jwt_public_key_verify_impl.h │ │ │ ├── jwt_public_key_verify_internal.h │ │ │ ├── jwt_public_key_verify_wrapper.cc │ │ │ ├── jwt_public_key_verify_wrapper.h │ │ │ ├── jwt_public_key_wrappers_test.cc │ │ │ ├── jwt_rsa_ssa_pkcs1_sign_key_manager.cc │ │ │ ├── jwt_rsa_ssa_pkcs1_sign_key_manager.h │ │ │ ├── jwt_rsa_ssa_pkcs1_sign_verify_key_manager_test.cc │ │ │ ├── jwt_rsa_ssa_pkcs1_verify_key_manager.cc │ │ │ ├── jwt_rsa_ssa_pkcs1_verify_key_manager.h │ │ │ ├── jwt_rsa_ssa_pss_sign_key_manager.cc │ │ │ ├── jwt_rsa_ssa_pss_sign_key_manager.h │ │ │ ├── jwt_rsa_ssa_pss_sign_verify_key_manager_test.cc │ │ │ ├── jwt_rsa_ssa_pss_verify_key_manager.cc │ │ │ ├── jwt_rsa_ssa_pss_verify_key_manager.h │ │ │ ├── raw_jwt_ecdsa_sign_key_manager.cc │ │ │ ├── raw_jwt_ecdsa_sign_key_manager.h │ │ │ ├── raw_jwt_ecdsa_sign_key_manager_test.cc │ │ │ ├── raw_jwt_ecdsa_verify_key_manager.cc │ │ │ ├── raw_jwt_ecdsa_verify_key_manager.h │ │ │ ├── raw_jwt_ecdsa_verify_key_manager_test.cc │ │ │ ├── raw_jwt_hmac_key_manager.cc │ │ │ ├── raw_jwt_hmac_key_manager.h │ │ │ ├── raw_jwt_hmac_key_manager_test.cc │ │ │ ├── raw_jwt_rsa_ssa_pkcs1_sign_key_manager.cc │ │ │ ├── raw_jwt_rsa_ssa_pkcs1_sign_key_manager.h │ │ │ ├── raw_jwt_rsa_ssa_pkcs1_sign_key_manager_test.cc │ │ │ ├── raw_jwt_rsa_ssa_pkcs1_verify_key_manager.cc │ │ │ ├── raw_jwt_rsa_ssa_pkcs1_verify_key_manager.h │ │ │ ├── raw_jwt_rsa_ssa_pkcs1_verify_key_manager_test.cc │ │ │ ├── raw_jwt_rsa_ssa_pss_sign_key_manager.cc │ │ │ ├── raw_jwt_rsa_ssa_pss_sign_key_manager.h │ │ │ ├── raw_jwt_rsa_ssa_pss_sign_key_manager_test.cc │ │ │ ├── raw_jwt_rsa_ssa_pss_verify_key_manager.cc │ │ │ ├── raw_jwt_rsa_ssa_pss_verify_key_manager.h │ │ │ └── raw_jwt_rsa_ssa_pss_verify_key_manager_test.cc │ │ ├── jwk_set_converter.cc │ │ ├── jwk_set_converter.h │ │ ├── jwk_set_converter_test.cc │ │ ├── jwt_hmac_key.cc │ │ ├── jwt_hmac_key.h │ │ ├── jwt_hmac_key_test.cc │ │ ├── jwt_hmac_parameters.cc │ │ ├── jwt_hmac_parameters.h │ │ ├── jwt_hmac_parameters_test.cc │ │ ├── jwt_hmac_proto_serialization.cc │ │ ├── jwt_hmac_proto_serialization.h │ │ ├── jwt_hmac_proto_serialization_test.cc │ │ ├── jwt_key_templates.cc │ │ ├── jwt_key_templates.h │ │ ├── jwt_key_templates_test.cc │ │ ├── jwt_mac.h │ │ ├── jwt_mac_config.cc │ │ ├── jwt_mac_config.h │ │ ├── jwt_mac_config_test.cc │ │ ├── jwt_mac_key.h │ │ ├── jwt_mac_parameters.h │ │ ├── jwt_public_key_sign.h │ │ ├── jwt_public_key_verify.h │ │ ├── jwt_signature_config.cc │ │ ├── jwt_signature_config.h │ │ ├── jwt_signature_config_test.cc │ │ ├── jwt_signature_parameters.h │ │ ├── jwt_signature_private_key.h │ │ ├── jwt_signature_public_key.h │ │ ├── jwt_validator.cc │ │ ├── jwt_validator.h │ │ ├── jwt_validator_test.cc │ │ ├── raw_jwt.cc │ │ ├── raw_jwt.h │ │ ├── raw_jwt_test.cc │ │ ├── verified_jwt.cc │ │ ├── verified_jwt.h │ │ └── verified_jwt_test.cc │ ├── kem/ │ │ └── internal/ │ │ ├── BUILD.bazel │ │ ├── CMakeLists.txt │ │ ├── raw_kem_decapsulate.h │ │ └── raw_kem_encapsulate.h │ ├── key.h │ ├── key_access.h │ ├── key_gen_configuration.h │ ├── key_manager.h │ ├── key_status.h │ ├── keyderivation/ │ │ ├── BUILD.bazel │ │ ├── CMakeLists.txt │ │ ├── internal/ │ │ │ ├── BUILD.bazel │ │ │ ├── CMakeLists.txt │ │ │ ├── config_prf_for_deriver.h │ │ │ ├── config_prf_for_deriver_test.cc │ │ │ ├── key_derivers.cc │ │ │ ├── key_derivers.h │ │ │ ├── key_derivers_test.cc │ │ │ ├── prf_based_deriver.cc │ │ │ ├── prf_based_deriver.h │ │ │ ├── prf_based_deriver_key_manager.h │ │ │ ├── prf_based_deriver_key_manager_test.cc │ │ │ └── prf_based_deriver_test.cc │ │ ├── key_derivation_config.cc │ │ ├── key_derivation_config.h │ │ ├── key_derivation_config_test.cc │ │ ├── key_derivation_key_templates.cc │ │ ├── key_derivation_key_templates.h │ │ ├── key_derivation_key_templates_test.cc │ │ ├── keyset_deriver.h │ │ ├── keyset_deriver_test.cc │ │ ├── keyset_deriver_wrapper.cc │ │ ├── keyset_deriver_wrapper.h │ │ ├── keyset_deriver_wrapper_test.cc │ │ └── subtle/ │ │ ├── BUILD.bazel │ │ └── CMakeLists.txt │ ├── keyset_handle.h │ ├── keyset_handle_builder.h │ ├── keyset_manager.h │ ├── keyset_reader.h │ ├── keyset_writer.h │ ├── kms_client.h │ ├── kms_clients.h │ ├── mac/ │ │ ├── BUILD.bazel │ │ ├── CMakeLists.txt │ │ ├── aes_cmac_key.cc │ │ ├── aes_cmac_key.h │ │ ├── aes_cmac_key_manager.h │ │ ├── aes_cmac_key_manager_test.cc │ │ ├── aes_cmac_key_test.cc │ │ ├── aes_cmac_parameters.cc │ │ ├── aes_cmac_parameters.h │ │ ├── aes_cmac_parameters_test.cc │ │ ├── aes_cmac_proto_serialization.cc │ │ ├── aes_cmac_proto_serialization.h │ │ ├── aes_cmac_proto_serialization_test.cc │ │ ├── config_v0.cc │ │ ├── config_v0.h │ │ ├── config_v0_test.cc │ │ ├── failing_mac.cc │ │ ├── failing_mac.h │ │ ├── failing_mac_test.cc │ │ ├── hmac_key.cc │ │ ├── hmac_key.h │ │ ├── hmac_key_manager.cc │ │ ├── hmac_key_manager.h │ │ ├── hmac_key_manager_test.cc │ │ ├── hmac_key_test.cc │ │ ├── hmac_parameters.cc │ │ ├── hmac_parameters.h │ │ ├── hmac_parameters_test.cc │ │ ├── hmac_proto_serialization.cc │ │ ├── hmac_proto_serialization.h │ │ ├── hmac_proto_serialization_test.cc │ │ ├── internal/ │ │ │ ├── BUILD.bazel │ │ │ ├── CMakeLists.txt │ │ │ ├── chunked_mac_impl.cc │ │ │ ├── chunked_mac_impl.h │ │ │ ├── chunked_mac_impl_test.cc │ │ │ ├── chunked_mac_test.cc │ │ │ ├── chunked_mac_wrapper.cc │ │ │ ├── chunked_mac_wrapper.h │ │ │ ├── chunked_mac_wrapper_test.cc │ │ │ ├── config_v0.cc │ │ │ ├── config_v0.h │ │ │ ├── config_v0_test.cc │ │ │ ├── key_gen_config_v0.cc │ │ │ └── key_gen_config_v0.h │ │ ├── key_gen_config_v0.cc │ │ ├── key_gen_config_v0.h │ │ ├── mac_config.cc │ │ ├── mac_config.h │ │ ├── mac_config_test.cc │ │ ├── mac_factory.cc │ │ ├── mac_factory.h │ │ ├── mac_factory_test.cc │ │ ├── mac_key.h │ │ ├── mac_key_templates.cc │ │ ├── mac_key_templates.h │ │ ├── mac_key_templates_test.cc │ │ ├── mac_parameters.h │ │ ├── mac_wrapper.cc │ │ ├── mac_wrapper.h │ │ ├── mac_wrapper_test.cc │ │ └── subtle/ │ │ ├── BUILD.bazel │ │ └── CMakeLists.txt │ ├── mac.h │ ├── mac_config.h │ ├── mac_factory.h │ ├── mac_key_templates.h │ ├── monitoring/ │ │ ├── BUILD.bazel │ │ ├── CMakeLists.txt │ │ ├── monitoring.h │ │ └── monitoring_client_mocks.h │ ├── output_stream.h │ ├── output_stream_with_result.h │ ├── parameters.h │ ├── partial_key_access.h │ ├── partial_key_access_token.h │ ├── prf/ │ │ ├── BUILD.bazel │ │ ├── CMakeLists.txt │ │ ├── aes_cmac_prf_key_manager.h │ │ ├── aes_cmac_prf_key_manager_test.cc │ │ ├── config_v0.cc │ │ ├── config_v0.h │ │ ├── config_v0_test.cc │ │ ├── failing_prfset.cc │ │ ├── failing_prfset.h │ │ ├── failing_prfset_test.cc │ │ ├── hkdf_prf_key_manager.h │ │ ├── hkdf_prf_key_manager_test.cc │ │ ├── hmac_prf_key_manager.cc │ │ ├── hmac_prf_key_manager.h │ │ ├── hmac_prf_key_manager_test.cc │ │ ├── internal/ │ │ │ ├── BUILD.bazel │ │ │ ├── CMakeLists.txt │ │ │ ├── config_v0.cc │ │ │ ├── config_v0.h │ │ │ ├── config_v0_test.cc │ │ │ ├── key_gen_config_v0.cc │ │ │ └── key_gen_config_v0.h │ │ ├── key_gen_config_v0.cc │ │ ├── key_gen_config_v0.h │ │ ├── prf_config.cc │ │ ├── prf_config.h │ │ ├── prf_config_test.cc │ │ ├── prf_key_templates.cc │ │ ├── prf_key_templates.h │ │ ├── prf_key_templates_test.cc │ │ ├── prf_set.cc │ │ ├── prf_set.h │ │ ├── prf_set_test.cc │ │ ├── prf_set_wrapper.cc │ │ ├── prf_set_wrapper.h │ │ ├── prf_set_wrapper_test.cc │ │ └── subtle/ │ │ ├── BUILD.bazel │ │ └── CMakeLists.txt │ ├── primitive_set.h │ ├── primitive_wrapper.h │ ├── private_key.h │ ├── proto/ │ │ ├── BUILD.bazel │ │ ├── aes_cmac.proto │ │ ├── aes_cmac_prf.proto │ │ ├── aes_ctr.proto │ │ ├── aes_ctr_hmac_aead.proto │ │ ├── aes_ctr_hmac_streaming.proto │ │ ├── aes_eax.proto │ │ ├── aes_gcm.proto │ │ ├── aes_gcm_hkdf_streaming.proto │ │ ├── aes_gcm_siv.proto │ │ ├── aes_siv.proto │ │ ├── chacha20_poly1305.proto │ │ ├── common.proto │ │ ├── config.proto │ │ ├── ecdsa.proto │ │ ├── ecies_aead_hkdf.proto │ │ ├── ed25519.proto │ │ ├── empty.proto │ │ ├── experimental/ │ │ │ └── pqcrypto/ │ │ │ ├── BUILD.bazel │ │ │ ├── cecpq2_aead_hkdf.proto │ │ │ ├── dilithium.proto │ │ │ ├── falcon.proto │ │ │ ├── slh_dsa.proto │ │ │ └── sphincs.proto │ │ ├── hkdf_prf.proto │ │ ├── hmac.proto │ │ ├── hmac_prf.proto │ │ ├── hpke.proto │ │ ├── jwt_ecdsa.proto │ │ ├── jwt_hmac.proto │ │ ├── jwt_rsa_ssa_pkcs1.proto │ │ ├── jwt_rsa_ssa_pss.proto │ │ ├── kms_aead.proto │ │ ├── kms_envelope.proto │ │ ├── prf_based_deriver.proto │ │ ├── rsa_ssa_pkcs1.proto │ │ ├── rsa_ssa_pss.proto │ │ ├── test_proto.proto │ │ ├── tink.proto │ │ └── xchacha20_poly1305.proto │ ├── proto_keyset_format.cc │ ├── proto_keyset_format.h │ ├── proto_keyset_format_test.cc │ ├── public_key_sign.h │ ├── public_key_sign_factory.h │ ├── public_key_verify.h │ ├── public_key_verify_factory.h │ ├── random_access_stream.h │ ├── registry.h │ ├── restricted_big_integer.h │ ├── restricted_data.h │ ├── secret_key_access.h │ ├── secret_key_access_token.h │ ├── signature/ │ │ ├── BUILD.bazel │ │ ├── CMakeLists.txt │ │ ├── config_v0.cc │ │ ├── config_v0.h │ │ ├── config_v0_test.cc │ │ ├── ecdsa_parameters.cc │ │ ├── ecdsa_parameters.h │ │ ├── ecdsa_parameters_test.cc │ │ ├── ecdsa_private_key.cc │ │ ├── ecdsa_private_key.h │ │ ├── ecdsa_private_key_test.cc │ │ ├── ecdsa_proto_serialization.cc │ │ ├── ecdsa_proto_serialization.h │ │ ├── ecdsa_proto_serialization_test.cc │ │ ├── ecdsa_public_key.cc │ │ ├── ecdsa_public_key.h │ │ ├── ecdsa_public_key_test.cc │ │ ├── ecdsa_sign_key_manager.cc │ │ ├── ecdsa_sign_key_manager.h │ │ ├── ecdsa_sign_key_manager_test.cc │ │ ├── ecdsa_verify_key_manager.cc │ │ ├── ecdsa_verify_key_manager.h │ │ ├── ecdsa_verify_key_manager_test.cc │ │ ├── ed25519_parameters.cc │ │ ├── ed25519_parameters.h │ │ ├── ed25519_parameters_test.cc │ │ ├── ed25519_private_key.cc │ │ ├── ed25519_private_key.h │ │ ├── ed25519_private_key_test.cc │ │ ├── ed25519_proto_serialization.cc │ │ ├── ed25519_proto_serialization.h │ │ ├── ed25519_proto_serialization_test.cc │ │ ├── ed25519_public_key.cc │ │ ├── ed25519_public_key.h │ │ ├── ed25519_public_key_test.cc │ │ ├── ed25519_sign_key_manager.cc │ │ ├── ed25519_sign_key_manager.h │ │ ├── ed25519_sign_key_manager_test.cc │ │ ├── ed25519_verify_key_manager.cc │ │ ├── ed25519_verify_key_manager.h │ │ ├── ed25519_verify_key_manager_test.cc │ │ ├── failing_signature.cc │ │ ├── failing_signature.h │ │ ├── failing_signature_test.cc │ │ ├── internal/ │ │ │ ├── BUILD.bazel │ │ │ ├── CMakeLists.txt │ │ │ ├── config_fips_140_2.cc │ │ │ ├── config_fips_140_2.h │ │ │ ├── config_fips_140_2_test.cc │ │ │ ├── config_v0.cc │ │ │ ├── config_v0.h │ │ │ ├── config_v0_test.cc │ │ │ ├── ecdsa_raw_sign_boringssl.cc │ │ │ ├── ecdsa_raw_sign_boringssl.h │ │ │ ├── ecdsa_raw_sign_boringssl_test.cc │ │ │ ├── key_gen_config_v0.cc │ │ │ └── key_gen_config_v0.h │ │ ├── key_gen_config_v0.cc │ │ ├── key_gen_config_v0.h │ │ ├── public_key_sign_factory.cc │ │ ├── public_key_sign_factory.h │ │ ├── public_key_sign_factory_test.cc │ │ ├── public_key_sign_wrapper.cc │ │ ├── public_key_sign_wrapper.h │ │ ├── public_key_sign_wrapper_test.cc │ │ ├── public_key_verify_factory.cc │ │ ├── public_key_verify_factory.h │ │ ├── public_key_verify_factory_test.cc │ │ ├── public_key_verify_wrapper.cc │ │ ├── public_key_verify_wrapper.h │ │ ├── public_key_verify_wrapper_test.cc │ │ ├── rsa_ssa_pkcs1_parameters.cc │ │ ├── rsa_ssa_pkcs1_parameters.h │ │ ├── rsa_ssa_pkcs1_parameters_test.cc │ │ ├── rsa_ssa_pkcs1_private_key.cc │ │ ├── rsa_ssa_pkcs1_private_key.h │ │ ├── rsa_ssa_pkcs1_private_key_test.cc │ │ ├── rsa_ssa_pkcs1_proto_serialization.cc │ │ ├── rsa_ssa_pkcs1_proto_serialization.h │ │ ├── rsa_ssa_pkcs1_proto_serialization_test.cc │ │ ├── rsa_ssa_pkcs1_public_key.cc │ │ ├── rsa_ssa_pkcs1_public_key.h │ │ ├── rsa_ssa_pkcs1_public_key_test.cc │ │ ├── rsa_ssa_pkcs1_sign_key_manager.cc │ │ ├── rsa_ssa_pkcs1_sign_key_manager.h │ │ ├── rsa_ssa_pkcs1_sign_key_manager_test.cc │ │ ├── rsa_ssa_pkcs1_verify_key_manager.cc │ │ ├── rsa_ssa_pkcs1_verify_key_manager.h │ │ ├── rsa_ssa_pkcs1_verify_key_manager_test.cc │ │ ├── rsa_ssa_pss_parameters.cc │ │ ├── rsa_ssa_pss_parameters.h │ │ ├── rsa_ssa_pss_parameters_test.cc │ │ ├── rsa_ssa_pss_private_key.cc │ │ ├── rsa_ssa_pss_private_key.h │ │ ├── rsa_ssa_pss_private_key_test.cc │ │ ├── rsa_ssa_pss_proto_serialization.cc │ │ ├── rsa_ssa_pss_proto_serialization.h │ │ ├── rsa_ssa_pss_proto_serialization_test.cc │ │ ├── rsa_ssa_pss_public_key.cc │ │ ├── rsa_ssa_pss_public_key.h │ │ ├── rsa_ssa_pss_public_key_test.cc │ │ ├── rsa_ssa_pss_sign_key_manager.cc │ │ ├── rsa_ssa_pss_sign_key_manager.h │ │ ├── rsa_ssa_pss_sign_key_manager_test.cc │ │ ├── rsa_ssa_pss_verify_key_manager.cc │ │ ├── rsa_ssa_pss_verify_key_manager.h │ │ ├── rsa_ssa_pss_verify_key_manager_test.cc │ │ ├── sig_util.cc │ │ ├── sig_util.h │ │ ├── signature_config.cc │ │ ├── signature_config.h │ │ ├── signature_config_test.cc │ │ ├── signature_key_templates.cc │ │ ├── signature_key_templates.h │ │ ├── signature_key_templates_test.cc │ │ ├── signature_parameters.h │ │ ├── signature_pem_keyset_reader.cc │ │ ├── signature_pem_keyset_reader.h │ │ ├── signature_pem_keyset_reader_test.cc │ │ ├── signature_private_key.h │ │ ├── signature_public_key.h │ │ └── subtle/ │ │ ├── BUILD.bazel │ │ └── CMakeLists.txt │ ├── signature_config.h │ ├── signature_key_templates.h │ ├── streaming_aead.h │ ├── streaming_aead_config.h │ ├── streaming_aead_key_templates.h │ ├── streaming_mac.h │ ├── streamingaead/ │ │ ├── BUILD.bazel │ │ ├── CMakeLists.txt │ │ ├── aes_ctr_hmac_streaming_key_manager.cc │ │ ├── aes_ctr_hmac_streaming_key_manager.h │ │ ├── aes_ctr_hmac_streaming_key_manager_test.cc │ │ ├── aes_gcm_hkdf_streaming_key_manager.cc │ │ ├── aes_gcm_hkdf_streaming_key_manager.h │ │ ├── aes_gcm_hkdf_streaming_key_manager_test.cc │ │ ├── buffered_input_stream.cc │ │ ├── buffered_input_stream.h │ │ ├── buffered_input_stream_test.cc │ │ ├── config_v0.cc │ │ ├── config_v0.h │ │ ├── config_v0_test.cc │ │ ├── decrypting_input_stream.cc │ │ ├── decrypting_input_stream.h │ │ ├── decrypting_input_stream_test.cc │ │ ├── decrypting_random_access_stream.cc │ │ ├── decrypting_random_access_stream.h │ │ ├── decrypting_random_access_stream_test.cc │ │ ├── internal/ │ │ │ ├── BUILD.bazel │ │ │ ├── CMakeLists.txt │ │ │ ├── config_v0.cc │ │ │ ├── config_v0.h │ │ │ ├── config_v0_test.cc │ │ │ ├── key_gen_config_v0.cc │ │ │ └── key_gen_config_v0.h │ │ ├── key_gen_config_v0.cc │ │ ├── key_gen_config_v0.h │ │ ├── shared_input_stream.h │ │ ├── shared_input_stream_test.cc │ │ ├── shared_random_access_stream.h │ │ ├── shared_random_access_stream_test.cc │ │ ├── streaming_aead_config.cc │ │ ├── streaming_aead_config.h │ │ ├── streaming_aead_config_test.cc │ │ ├── streaming_aead_key_templates.cc │ │ ├── streaming_aead_key_templates.h │ │ ├── streaming_aead_key_templates_test.cc │ │ ├── streaming_aead_wrapper.cc │ │ ├── streaming_aead_wrapper.h │ │ ├── streaming_aead_wrapper_test.cc │ │ └── subtle/ │ │ ├── BUILD.bazel │ │ └── CMakeLists.txt │ ├── subtle/ │ │ ├── BUILD.bazel │ │ ├── CMakeLists.txt │ │ ├── aead_test_util.cc │ │ ├── aead_test_util.h │ │ ├── aead_test_util_test.cc │ │ ├── aes_cmac_boringssl.cc │ │ ├── aes_cmac_boringssl.h │ │ ├── aes_cmac_boringssl_test.cc │ │ ├── aes_ctr_boringssl.cc │ │ ├── aes_ctr_boringssl.h │ │ ├── aes_ctr_boringssl_test.cc │ │ ├── aes_ctr_hmac_streaming.cc │ │ ├── aes_ctr_hmac_streaming.h │ │ ├── aes_ctr_hmac_streaming_test.cc │ │ ├── aes_eax_boringssl.cc │ │ ├── aes_eax_boringssl.h │ │ ├── aes_eax_boringssl_test.cc │ │ ├── aes_gcm_boringssl.cc │ │ ├── aes_gcm_boringssl.h │ │ ├── aes_gcm_boringssl_test.cc │ │ ├── aes_gcm_hkdf_stream_segment_decrypter.cc │ │ ├── aes_gcm_hkdf_stream_segment_decrypter.h │ │ ├── aes_gcm_hkdf_stream_segment_decrypter_test.cc │ │ ├── aes_gcm_hkdf_stream_segment_encrypter.cc │ │ ├── aes_gcm_hkdf_stream_segment_encrypter.h │ │ ├── aes_gcm_hkdf_stream_segment_encrypter_test.cc │ │ ├── aes_gcm_hkdf_streaming.cc │ │ ├── aes_gcm_hkdf_streaming.h │ │ ├── aes_gcm_hkdf_streaming_test.cc │ │ ├── aes_gcm_siv_boringssl.cc │ │ ├── aes_gcm_siv_boringssl.h │ │ ├── aes_gcm_siv_boringssl_test.cc │ │ ├── aes_siv_boringssl.cc │ │ ├── aes_siv_boringssl.h │ │ ├── aes_siv_boringssl_test.cc │ │ ├── common_enums.cc │ │ ├── common_enums.h │ │ ├── common_enums_test.cc │ │ ├── decrypting_random_access_stream.cc │ │ ├── decrypting_random_access_stream.h │ │ ├── decrypting_random_access_stream_test.cc │ │ ├── ec_util.h │ │ ├── ecdsa_sign_boringssl.cc │ │ ├── ecdsa_sign_boringssl.h │ │ ├── ecdsa_sign_boringssl_test.cc │ │ ├── ecdsa_verify_boringssl.cc │ │ ├── ecdsa_verify_boringssl.h │ │ ├── ecdsa_verify_boringssl_test.cc │ │ ├── ecies_hkdf_recipient_kem_boringssl.cc │ │ ├── ecies_hkdf_recipient_kem_boringssl.h │ │ ├── ecies_hkdf_recipient_kem_boringssl_test.cc │ │ ├── ecies_hkdf_sender_kem_boringssl.cc │ │ ├── ecies_hkdf_sender_kem_boringssl.h │ │ ├── ecies_hkdf_sender_kem_boringssl_test.cc │ │ ├── ed25519_sign_boringssl.cc │ │ ├── ed25519_sign_boringssl.h │ │ ├── ed25519_sign_boringssl_test.cc │ │ ├── ed25519_verify_boringssl.cc │ │ ├── ed25519_verify_boringssl.h │ │ ├── ed25519_verify_boringssl_test.cc │ │ ├── encrypt_then_authenticate.cc │ │ ├── encrypt_then_authenticate.h │ │ ├── encrypt_then_authenticate_test.cc │ │ ├── hkdf.cc │ │ ├── hkdf.h │ │ ├── hkdf_test.cc │ │ ├── hmac_boringssl.cc │ │ ├── hmac_boringssl.h │ │ ├── hmac_boringssl_test.cc │ │ ├── hybrid_test_util.cc │ │ ├── hybrid_test_util.h │ │ ├── hybrid_test_util_test.cc │ │ ├── ind_cpa_cipher.h │ │ ├── mac/ │ │ │ ├── BUILD.bazel │ │ │ ├── CMakeLists.txt │ │ │ └── stateful_mac.h │ │ ├── nonce_based_streaming_aead.cc │ │ ├── nonce_based_streaming_aead.h │ │ ├── pem_parser_boringssl.cc │ │ ├── pem_parser_boringssl.h │ │ ├── pem_parser_boringssl_test.cc │ │ ├── prf/ │ │ │ ├── BUILD.bazel │ │ │ ├── CMakeLists.txt │ │ │ ├── hkdf_streaming_prf.cc │ │ │ ├── hkdf_streaming_prf.h │ │ │ ├── hkdf_streaming_prf_test.cc │ │ │ ├── prf_set_util.cc │ │ │ ├── prf_set_util.h │ │ │ ├── prf_set_util_test.cc │ │ │ ├── streaming_prf.h │ │ │ ├── streaming_prf_wrapper.cc │ │ │ ├── streaming_prf_wrapper.h │ │ │ └── streaming_prf_wrapper_test.cc │ │ ├── random.cc │ │ ├── random.h │ │ ├── random_test.cc │ │ ├── rsa_ssa_pkcs1_sign_boringssl.cc │ │ ├── rsa_ssa_pkcs1_sign_boringssl.h │ │ ├── rsa_ssa_pkcs1_sign_boringssl_test.cc │ │ ├── rsa_ssa_pkcs1_verify_boringssl.cc │ │ ├── rsa_ssa_pkcs1_verify_boringssl.h │ │ ├── rsa_ssa_pkcs1_verify_boringssl_test.cc │ │ ├── rsa_ssa_pss_sign_boringssl.cc │ │ ├── rsa_ssa_pss_sign_boringssl.h │ │ ├── rsa_ssa_pss_sign_boringssl_test.cc │ │ ├── rsa_ssa_pss_verify_boringssl.cc │ │ ├── rsa_ssa_pss_verify_boringssl.h │ │ ├── rsa_ssa_pss_verify_boringssl_test.cc │ │ ├── stateful_cmac_boringssl.cc │ │ ├── stateful_cmac_boringssl.h │ │ ├── stateful_cmac_boringssl_test.cc │ │ ├── stateful_hmac_boringssl.cc │ │ ├── stateful_hmac_boringssl.h │ │ ├── stateful_hmac_boringssl_test.cc │ │ ├── stream_segment_decrypter.h │ │ ├── stream_segment_encrypter.h │ │ ├── streaming_aead_decrypting_stream.cc │ │ ├── streaming_aead_decrypting_stream.h │ │ ├── streaming_aead_decrypting_stream_test.cc │ │ ├── streaming_aead_encrypting_stream.cc │ │ ├── streaming_aead_encrypting_stream.h │ │ ├── streaming_aead_encrypting_stream_test.cc │ │ ├── streaming_aead_test_util.cc │ │ ├── streaming_aead_test_util.h │ │ ├── streaming_aead_test_util_test.cc │ │ ├── streaming_mac_impl.cc │ │ ├── streaming_mac_impl.h │ │ ├── streaming_mac_impl_test.cc │ │ ├── subtle_util.cc │ │ ├── subtle_util.h │ │ ├── subtle_util_boringssl.h │ │ ├── subtle_util_test.cc │ │ ├── test_util.cc │ │ ├── test_util.h │ │ ├── wycheproof_util.cc │ │ ├── wycheproof_util.h │ │ ├── xchacha20_poly1305_boringssl.cc │ │ ├── xchacha20_poly1305_boringssl.h │ │ └── xchacha20_poly1305_boringssl_test.cc │ ├── template_rule.bzl │ ├── testvectors/ │ │ └── BUILD.bazel │ ├── third_party/ │ │ ├── BUILD.bazel │ │ ├── boringssl_fips/ │ │ │ ├── BUILD.bazel │ │ │ ├── README.md │ │ │ ├── WORKSPACE │ │ │ └── boringssl_fips.sh │ │ └── rapidjson.BUILD.bazel │ ├── tink_cc_deps.bzl │ ├── tink_cc_deps_init.bzl │ ├── tink_config.h │ ├── tink_version.bzl │ ├── util/ │ │ ├── BUILD.bazel │ │ ├── CMakeLists.txt │ │ ├── buffer.cc │ │ ├── buffer.h │ │ ├── buffer_test.cc │ │ ├── constants.cc │ │ ├── constants.h │ │ ├── enums.cc │ │ ├── enums.h │ │ ├── enums_test.cc │ │ ├── errors.h │ │ ├── errors_test.cc │ │ ├── fake_kms_client.cc │ │ ├── fake_kms_client.h │ │ ├── fake_kms_client_test.cc │ │ ├── file_input_stream.cc │ │ ├── file_input_stream.h │ │ ├── file_input_stream_test.cc │ │ ├── file_output_stream.cc │ │ ├── file_output_stream.h │ │ ├── file_output_stream_test.cc │ │ ├── file_random_access_stream.cc │ │ ├── file_random_access_stream.h │ │ ├── file_random_access_stream_test.cc │ │ ├── input_stream_util.cc │ │ ├── input_stream_util.h │ │ ├── input_stream_util_test.cc │ │ ├── istream_input_stream.cc │ │ ├── istream_input_stream.h │ │ ├── istream_input_stream_test.cc │ │ ├── keyset_util.cc │ │ ├── keyset_util.h │ │ ├── ostream_output_stream.cc │ │ ├── ostream_output_stream.h │ │ ├── ostream_output_stream_test.cc │ │ ├── protobuf_helper.h │ │ ├── secret_data.h │ │ ├── secret_data_internal.h │ │ ├── secret_data_test.cc │ │ ├── secret_proto.h │ │ ├── secret_proto_test.cc │ │ ├── status.h │ │ ├── statusor.h │ │ ├── test_keyset_handle.cc │ │ ├── test_keyset_handle.h │ │ ├── test_matchers.h │ │ ├── test_util.cc │ │ ├── test_util.h │ │ ├── test_util_test.cc │ │ ├── validation.cc │ │ ├── validation.h │ │ └── validation_test.cc │ ├── version.h.templ │ └── version_script.lds ├── cmake/ │ ├── HttpArchive.cmake │ ├── TinkBuildRules.cmake │ ├── TinkUtil.cmake │ └── TinkWorkspace.cmake ├── docs/ │ ├── CMAKE-HOWTO.md │ ├── CONTRIBUTING.md │ ├── CPP-HOWTO.md │ ├── FIPS.md │ ├── GOLANG-HOWTO.md │ ├── JAVA-HOWTO.md │ ├── JWT-HOWTO.md │ ├── KEY-MANAGEMENT.md │ ├── KNOWN-ISSUES.md │ ├── OBJC-HOWTO.md │ ├── PRIMITIVES.md │ ├── PYTHON-HOWTO.md │ ├── SECURITY-USABILITY.md │ ├── SECURITY.md │ ├── TINKEY.md │ └── WIRE-FORMAT.md ├── go/ │ ├── .bazelversion │ ├── BUILD.bazel │ ├── README.md │ ├── WORKSPACE │ ├── aead/ │ │ ├── BUILD.bazel │ │ ├── aead.go │ │ ├── aead_benchmark_test.go │ │ ├── aead_factory.go │ │ ├── aead_factory_test.go │ │ ├── aead_init_test.go │ │ ├── aead_key_templates.go │ │ ├── aead_key_templates_test.go │ │ ├── aead_test.go │ │ ├── aes_ctr_hmac_aead_key_manager.go │ │ ├── aes_ctr_hmac_aead_key_manager_test.go │ │ ├── aes_gcm_key_manager.go │ │ ├── aes_gcm_key_manager_test.go │ │ ├── aes_gcm_siv_key_manager.go │ │ ├── aes_gcm_siv_key_manager_test.go │ │ ├── chacha20poly1305_key_manager.go │ │ ├── chacha20poly1305_key_manager_test.go │ │ ├── internal/ │ │ │ ├── BUILD.bazel │ │ │ └── testing/ │ │ │ ├── BUILD.bazel │ │ │ └── kmsaead/ │ │ │ ├── BUILD.bazel │ │ │ ├── key_manager.go │ │ │ └── key_manager_test.go │ │ ├── kms_envelope_aead.go │ │ ├── kms_envelope_aead_example_test.go │ │ ├── kms_envelope_aead_key_manager.go │ │ ├── kms_envelope_aead_key_manager_test.go │ │ ├── kms_envelope_aead_test.go │ │ ├── subtle/ │ │ │ ├── BUILD.bazel │ │ │ ├── aes_ctr.go │ │ │ ├── aes_ctr_test.go │ │ │ ├── aes_gcm.go │ │ │ ├── aes_gcm_siv.go │ │ │ ├── aes_gcm_siv_test.go │ │ │ ├── aes_gcm_test.go │ │ │ ├── chacha20poly1305.go │ │ │ ├── chacha20poly1305_test.go │ │ │ ├── chacha20poly1305_vectors_test.go │ │ │ ├── encrypt_then_authenticate.go │ │ │ ├── encrypt_then_authenticate_test.go │ │ │ ├── ind_cpa.go │ │ │ ├── polyval.go │ │ │ ├── polyval_test.go │ │ │ ├── subtle.go │ │ │ ├── subtle_test.go │ │ │ ├── xchacha20poly1305.go │ │ │ ├── xchacha20poly1305_test.go │ │ │ └── xchacha20poly1305_vectors_test.go │ │ ├── xchacha20poly1305_key_manager.go │ │ └── xchacha20poly1305_key_manager_test.go │ ├── core/ │ │ ├── cryptofmt/ │ │ │ ├── BUILD.bazel │ │ │ ├── cryptofmt.go │ │ │ └── cryptofmt_test.go │ │ ├── primitiveset/ │ │ │ ├── BUILD.bazel │ │ │ ├── primitiveset.go │ │ │ └── primitiveset_test.go │ │ └── registry/ │ │ ├── BUILD.bazel │ │ ├── custom_key_manager_test.go │ │ ├── key_manager.go │ │ ├── kms_client.go │ │ ├── private_key_manager.go │ │ ├── registry.go │ │ └── registry_test.go │ ├── daead/ │ │ ├── BUILD.bazel │ │ ├── aes_siv_key_manager.go │ │ ├── aes_siv_key_manager_test.go │ │ ├── daead.go │ │ ├── daead_benchmark_test.go │ │ ├── daead_factory.go │ │ ├── daead_factory_test.go │ │ ├── daead_init_test.go │ │ ├── daead_key_templates.go │ │ ├── daead_key_templates_test.go │ │ ├── daead_test.go │ │ └── subtle/ │ │ ├── BUILD.bazel │ │ ├── aes_siv.go │ │ └── aes_siv_test.go │ ├── deps.bzl │ ├── go.mod │ ├── go.sum │ ├── hybrid/ │ │ ├── BUILD.bazel │ │ ├── ecies_aead_hkdf_dem_helper.go │ │ ├── ecies_aead_hkdf_dem_helper_test.go │ │ ├── ecies_aead_hkdf_hybrid_decrypt_test.go │ │ ├── ecies_aead_hkdf_hybrid_encrypt_test.go │ │ ├── ecies_aead_hkdf_private_key_manager.go │ │ ├── ecies_aead_hkdf_private_key_manager_test.go │ │ ├── ecies_aead_hkdf_public_key_manager.go │ │ ├── ecies_aead_hkdf_public_key_manager_test.go │ │ ├── ecies_aead_hkdf_test.go │ │ ├── hpke_private_key_manager.go │ │ ├── hpke_private_key_manager_test.go │ │ ├── hpke_public_key_manager.go │ │ ├── hpke_public_key_manager_test.go │ │ ├── hybrid.go │ │ ├── hybrid_benchmark_test.go │ │ ├── hybrid_decrypt_factory.go │ │ ├── hybrid_encrypt_factory.go │ │ ├── hybrid_factory_test.go │ │ ├── hybrid_key_templates.go │ │ ├── hybrid_key_templates_test.go │ │ ├── hybrid_test.go │ │ ├── internal/ │ │ │ └── hpke/ │ │ │ ├── BUILD.bazel │ │ │ ├── aead.go │ │ │ ├── aes_gcm_aead.go │ │ │ ├── aes_gcm_aead_test.go │ │ │ ├── chacha20poly1305_aead.go │ │ │ ├── chacha20poly1305_aead_test.go │ │ │ ├── context.go │ │ │ ├── context_test.go │ │ │ ├── decrypt.go │ │ │ ├── encrypt.go │ │ │ ├── encrypt_decrypt_test.go │ │ │ ├── hkdf_kdf.go │ │ │ ├── hkdf_kdf_test.go │ │ │ ├── hpke.go │ │ │ ├── hpke_test.go │ │ │ ├── kdf.go │ │ │ ├── kem.go │ │ │ ├── primitive_factory.go │ │ │ ├── primitive_factory_test.go │ │ │ ├── x25519_kem.go │ │ │ └── x25519_kem_test.go │ │ └── subtle/ │ │ ├── BUILD.bazel │ │ ├── ecies_aead_hkdf_dem_helper.go │ │ ├── ecies_aead_hkdf_hybrid_decrypt.go │ │ ├── ecies_aead_hkdf_hybrid_encrypt.go │ │ ├── ecies_hkdf_recipient_kem.go │ │ ├── ecies_hkdf_sender_kem.go │ │ ├── elliptic_curves.go │ │ ├── elliptic_curves_test.go │ │ ├── public_key.go │ │ ├── public_key_test.go │ │ ├── subtle.go │ │ └── subtle_test.go │ ├── insecurecleartextkeyset/ │ │ ├── BUILD.bazel │ │ ├── example_test.go │ │ ├── insecurecleartextkeyset.go │ │ └── insecurecleartextkeyset_test.go │ ├── integration/ │ │ ├── awskms/ │ │ │ ├── BUILD.bazel │ │ │ ├── aws_kms_aead.go │ │ │ ├── aws_kms_client.go │ │ │ ├── aws_kms_client_test.go │ │ │ ├── aws_kms_integration_test.go │ │ │ └── internal/ │ │ │ └── fakeawskms/ │ │ │ ├── BUILD.bazel │ │ │ ├── fakeawskms.go │ │ │ └── fakeawskms_test.go │ │ ├── gcpkms/ │ │ │ ├── BUILD.bazel │ │ │ ├── gcp_kms_aead.go │ │ │ ├── gcp_kms_aead_test.go │ │ │ ├── gcp_kms_client.go │ │ │ ├── gcp_kms_client_test.go │ │ │ └── gcp_kms_integration_test.go │ │ └── hcvault/ │ │ ├── BUILD.bazel │ │ ├── hcvault_aead.go │ │ ├── hcvault_aead_internal_test.go │ │ ├── hcvault_aead_test.go │ │ ├── hcvault_client.go │ │ └── hcvault_client_test.go │ ├── internal/ │ │ ├── BUILD.bazel │ │ ├── aead/ │ │ │ ├── BUILD.bazel │ │ │ ├── aead.go │ │ │ ├── aead_test.go │ │ │ ├── aes_gcm_insecure_iv.go │ │ │ ├── aes_gcm_insecure_iv_test.go │ │ │ ├── chacha20poly1305_insecure_nonce.go │ │ │ ├── chacha20poly1305_insecure_nonce_test.go │ │ │ └── chacha20poly1305_insecure_nonce_vectors_test.go │ │ ├── internal.go │ │ ├── internalapi/ │ │ │ ├── BUILD.bazel │ │ │ └── token.go │ │ ├── internalregistry/ │ │ │ ├── BUILD.bazel │ │ │ ├── derivable_key_manager.go │ │ │ ├── internal_registry.go │ │ │ ├── internal_registry_test.go │ │ │ ├── key_derivation.go │ │ │ └── key_derivation_test.go │ │ ├── monitoringutil/ │ │ │ ├── BUILD.bazel │ │ │ ├── monitoring_util.go │ │ │ └── monitoring_util_test.go │ │ ├── registryconfig/ │ │ │ ├── BUILD.bazel │ │ │ ├── registry_config.go │ │ │ └── registry_config_test.go │ │ ├── signature/ │ │ │ ├── BUILD.bazel │ │ │ ├── rsa.go │ │ │ ├── rsa_test.go │ │ │ ├── rsassapkcs1_signer.go │ │ │ ├── rsassapkcs1_signer_verifier_test.go │ │ │ ├── rsassapkcs1_verifier.go │ │ │ ├── rsassapss_signer.go │ │ │ ├── rsassapss_signer_verifier_test.go │ │ │ ├── rsassapss_verifier.go │ │ │ └── signature.go │ │ ├── testing/ │ │ │ └── stubkeymanager/ │ │ │ ├── BUILD.bazel │ │ │ ├── stubkeymanager.go │ │ │ └── stubkeymanager_test.go │ │ └── tinkerror/ │ │ ├── BUILD.bazel │ │ ├── doc.go │ │ ├── tinkerror.go │ │ ├── tinkerror_test.go │ │ └── tinkerrortest/ │ │ ├── BUILD.bazel │ │ ├── doc.go │ │ └── tinkerrortest.go │ ├── jwt/ │ │ ├── BUILD.bazel │ │ ├── jwk_converter.go │ │ ├── jwk_converter_test.go │ │ ├── jwt.go │ │ ├── jwt_ecdsa_signer_key_manager.go │ │ ├── jwt_ecdsa_signer_key_manager_test.go │ │ ├── jwt_ecdsa_verifier_key_manager.go │ │ ├── jwt_ecdsa_verifier_key_manager_test.go │ │ ├── jwt_encoding.go │ │ ├── jwt_encoding_test.go │ │ ├── jwt_hmac_key_manager.go │ │ ├── jwt_hmac_key_manager_test.go │ │ ├── jwt_key_templates.go │ │ ├── jwt_key_templates_test.go │ │ ├── jwt_mac.go │ │ ├── jwt_mac_factory.go │ │ ├── jwt_mac_factory_test.go │ │ ├── jwt_mac_kid.go │ │ ├── jwt_mac_kid_test.go │ │ ├── jwt_rsa_ssa_pkcs1_signer_key_manager.go │ │ ├── jwt_rsa_ssa_pkcs1_signer_key_manager_test.go │ │ ├── jwt_rsa_ssa_pkcs1_verifier_key_manager.go │ │ ├── jwt_rsa_ssa_pkcs1_verifier_key_manager_test.go │ │ ├── jwt_rsa_ssa_pss_signer_key_manager.go │ │ ├── jwt_rsa_ssa_pss_signer_key_manager_test.go │ │ ├── jwt_rsa_ssa_pss_verify_key_manager.go │ │ ├── jwt_rsa_ssa_pss_verify_key_manager_test.go │ │ ├── jwt_signer.go │ │ ├── jwt_signer_factory.go │ │ ├── jwt_signer_kid.go │ │ ├── jwt_signer_verifier_factory_test.go │ │ ├── jwt_signer_verifier_kid_test.go │ │ ├── jwt_test.go │ │ ├── jwt_validator.go │ │ ├── jwt_validator_test.go │ │ ├── jwt_verifier.go │ │ ├── jwt_verifier_factory.go │ │ ├── jwt_verifier_kid.go │ │ ├── raw_jwt.go │ │ ├── raw_jwt_test.go │ │ ├── verified_jwt.go │ │ └── verified_jwt_test.go │ ├── keyderivation/ │ │ ├── BUILD.bazel │ │ ├── internal/ │ │ │ └── streamingprf/ │ │ │ ├── BUILD.bazel │ │ │ ├── hkdf_streaming_prf.go │ │ │ ├── hkdf_streaming_prf_key_manager.go │ │ │ ├── hkdf_streaming_prf_key_manager_test.go │ │ │ ├── hkdf_streaming_prf_test.go │ │ │ ├── streaming_prf.go │ │ │ ├── streaming_prf_factory.go │ │ │ ├── streaming_prf_factory_test.go │ │ │ └── streaming_prf_test.go │ │ ├── keyderivation.go │ │ ├── keyderivation_key_templates.go │ │ ├── keyderivation_key_templates_test.go │ │ ├── keyderivation_test.go │ │ ├── keyset_deriver.go │ │ ├── keyset_deriver_factory.go │ │ ├── keyset_deriver_factory_test.go │ │ ├── keyset_deriver_factory_x_test.go │ │ ├── prf_based_deriver.go │ │ ├── prf_based_deriver_key_manager.go │ │ ├── prf_based_deriver_key_manager_test.go │ │ └── prf_based_deriver_test.go │ ├── keyset/ │ │ ├── BUILD.bazel │ │ ├── binary_io.go │ │ ├── binary_io_test.go │ │ ├── handle.go │ │ ├── handle_test.go │ │ ├── json_io.go │ │ ├── json_io_test.go │ │ ├── keyset.go │ │ ├── keyset_test.go │ │ ├── manager.go │ │ ├── manager_test.go │ │ ├── mem_io.go │ │ ├── mem_io_test.go │ │ ├── option.go │ │ ├── reader.go │ │ ├── validation.go │ │ ├── validation_test.go │ │ └── writer.go │ ├── kwp/ │ │ └── subtle/ │ │ ├── BUILD.bazel │ │ ├── kwp.go │ │ └── kwp_test.go │ ├── mac/ │ │ ├── BUILD.bazel │ │ ├── aes_cmac_key_manager.go │ │ ├── aes_cmac_key_manager_test.go │ │ ├── hmac_key_manager.go │ │ ├── hmac_key_manager_test.go │ │ ├── internal/ │ │ │ └── mactest/ │ │ │ ├── BUILD.bazel │ │ │ ├── mactest.go │ │ │ └── mactest_test.go │ │ ├── mac.go │ │ ├── mac_benchmark_test.go │ │ ├── mac_factory.go │ │ ├── mac_factory_test.go │ │ ├── mac_init_test.go │ │ ├── mac_key_templates.go │ │ ├── mac_key_templates_test.go │ │ ├── mac_test.go │ │ └── subtle/ │ │ ├── BUILD.bazel │ │ ├── cmac.go │ │ ├── cmac_test.go │ │ ├── hmac.go │ │ └── hmac_test.go │ ├── monitoring/ │ │ ├── BUILD.bazel │ │ └── monitoring.go │ ├── prf/ │ │ ├── BUILD.bazel │ │ ├── aes_cmac_prf_key_manager.go │ │ ├── aes_cmac_prf_key_manager_test.go │ │ ├── hkdf_prf_key_manager.go │ │ ├── hkdf_prf_key_manager_test.go │ │ ├── hmac_prf_key_manager.go │ │ ├── hmac_prf_key_manager_test.go │ │ ├── prf_benchmark_test.go │ │ ├── prf_key_templates.go │ │ ├── prf_key_templates_test.go │ │ ├── prf_set.go │ │ ├── prf_set_factory.go │ │ ├── prf_set_factory_test.go │ │ ├── prf_test.go │ │ └── subtle/ │ │ ├── BUILD.bazel │ │ ├── aes_cmac.go │ │ ├── aes_cmac_test.go │ │ ├── hkdf.go │ │ ├── hkdf_test.go │ │ ├── hmac.go │ │ ├── hmac_test.go │ │ ├── subtle.go │ │ └── subtle_test.go │ ├── proto/ │ │ ├── aes_cmac_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── aes_cmac.pb.go │ │ ├── aes_cmac_prf_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── aes_cmac_prf.pb.go │ │ ├── aes_ctr_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── aes_ctr.pb.go │ │ ├── aes_ctr_hmac_aead_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── aes_ctr_hmac_aead.pb.go │ │ ├── aes_ctr_hmac_streaming_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── aes_ctr_hmac_streaming.pb.go │ │ ├── aes_gcm_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── aes_gcm.pb.go │ │ ├── aes_gcm_hkdf_streaming_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── aes_gcm_hkdf_streaming.pb.go │ │ ├── aes_gcm_siv_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── aes_gcm_siv.pb.go │ │ ├── aes_siv_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── aes_siv.pb.go │ │ ├── chacha20_poly1305_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── chacha20_poly1305.pb.go │ │ ├── common_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── common.pb.go │ │ ├── ecdsa_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── ecdsa.pb.go │ │ ├── ecies_aead_hkdf_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── ecies_aead_hkdf.pb.go │ │ ├── ed25519_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── ed25519.pb.go │ │ ├── hkdf_prf_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── hkdf_prf.pb.go │ │ ├── hmac_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── hmac.pb.go │ │ ├── hmac_prf_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── hmac_prf.pb.go │ │ ├── hpke_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── hpke.pb.go │ │ ├── jwt_ecdsa_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── jwt_ecdsa.pb.go │ │ ├── jwt_hmac_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── jwt_hmac.pb.go │ │ ├── jwt_rsa_ssa_pkcs1_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── jwt_rsa_ssa_pkcs1.pb.go │ │ ├── jwt_rsa_ssa_pss_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── jwt_rsa_ssa_pss.pb.go │ │ ├── kms_aead_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── kms_aead.pb.go │ │ ├── kms_envelope_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── kms_envelope.pb.go │ │ ├── prf_based_deriver_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── prf_based_deriver.pb.go │ │ ├── rsa_ssa_pkcs1_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── rsa_ssa_pkcs1.pb.go │ │ ├── rsa_ssa_pss_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── rsa_ssa_pss.pb.go │ │ ├── tink_go_proto/ │ │ │ ├── BUILD.bazel │ │ │ └── tink.pb.go │ │ └── xchacha20_poly1305_go_proto/ │ │ ├── BUILD.bazel │ │ └── xchacha20_poly1305.pb.go │ ├── signature/ │ │ ├── BUILD.bazel │ │ ├── ecdsa_signer_key_manager.go │ │ ├── ecdsa_signer_key_manager_test.go │ │ ├── ecdsa_verifier_key_manager.go │ │ ├── ecdsa_verifier_key_manager_test.go │ │ ├── ed25519_signer_key_manager.go │ │ ├── ed25519_signer_key_manager_test.go │ │ ├── ed25519_verifier_key_manager.go │ │ ├── ed25519_verifier_key_manager_test.go │ │ ├── proto.go │ │ ├── rsa.go │ │ ├── rsassapkcs1_signer_key_manager.go │ │ ├── rsassapkcs1_signer_key_manager_test.go │ │ ├── rsassapkcs1_verifier_key_manager.go │ │ ├── rsassapkcs1_verifier_key_manager_test.go │ │ ├── rsassapss_signer_key_manager.go │ │ ├── rsassapss_signer_key_manager_test.go │ │ ├── rsassapss_verifier_key_manager.go │ │ ├── rsassapss_verifier_key_manager_test.go │ │ ├── signature.go │ │ ├── signature_benchmark_test.go │ │ ├── signature_factory_test.go │ │ ├── signature_init_test.go │ │ ├── signature_key_templates.go │ │ ├── signature_key_templates_test.go │ │ ├── signature_test.go │ │ ├── signer_factory.go │ │ ├── subtle/ │ │ │ ├── BUILD.bazel │ │ │ ├── ecdsa.go │ │ │ ├── ecdsa_signer.go │ │ │ ├── ecdsa_signer_verifier_test.go │ │ │ ├── ecdsa_test.go │ │ │ ├── ecdsa_verifier.go │ │ │ ├── ed25519_signer.go │ │ │ ├── ed25519_signer_verifier_test.go │ │ │ ├── ed25519_verifier.go │ │ │ ├── encoding.go │ │ │ ├── subtle.go │ │ │ └── subtle_test.go │ │ └── verifier_factory.go │ ├── streamingaead/ │ │ ├── BUILD.bazel │ │ ├── aes_ctr_hmac_key_manager.go │ │ ├── aes_ctr_hmac_key_manager_test.go │ │ ├── aes_gcm_hkdf_key_manager.go │ │ ├── aes_gcm_hkdf_key_manager_test.go │ │ ├── decrypt_reader.go │ │ ├── decrypt_reader_test.go │ │ ├── streamingaead.go │ │ ├── streamingaead_factory.go │ │ ├── streamingaead_factory_test.go │ │ ├── streamingaead_key_templates.go │ │ ├── streamingaead_key_templates_test.go │ │ ├── streamingaead_test.go │ │ └── subtle/ │ │ ├── BUILD.bazel │ │ ├── aes_ctr_hmac.go │ │ ├── aes_ctr_hmac_test.go │ │ ├── aes_gcm_hkdf.go │ │ ├── aes_gcm_hkdf_test.go │ │ ├── noncebased/ │ │ │ ├── BUILD.bazel │ │ │ ├── noncebased.go │ │ │ └── noncebased_test.go │ │ ├── subtle.go │ │ └── subtle_test.go │ ├── subtle/ │ │ ├── BUILD.bazel │ │ ├── hkdf.go │ │ ├── hkdf_test.go │ │ ├── random/ │ │ │ ├── BUILD.bazel │ │ │ ├── random.go │ │ │ └── random_test.go │ │ ├── subtle.go │ │ ├── subtle_test.go │ │ ├── x25519.go │ │ └── x25519_test.go │ ├── testdata/ │ │ ├── BUILD.bazel │ │ ├── aws/ │ │ │ ├── BUILD.bazel │ │ │ ├── README.md │ │ │ ├── access_keys_bad.csv │ │ │ ├── credentials.cred │ │ │ ├── credentials.csv │ │ │ ├── credentials.ini │ │ │ ├── credentials_bad.csv │ │ │ ├── credentials_bad.ini │ │ │ ├── key_arn.txt │ │ │ └── key_arn_bad.txt │ │ ├── gcp/ │ │ │ ├── BUILD.bazel │ │ │ ├── README.md │ │ │ ├── credential.json │ │ │ ├── credential_bad.json │ │ │ ├── key_name.txt │ │ │ └── key_name_bad.txt │ │ ├── keysets/ │ │ │ └── BUILD.bazel │ │ └── testvectors/ │ │ ├── BUILD.bazel │ │ └── hpke_boringssl.json │ ├── testing/ │ │ ├── fakekms/ │ │ │ ├── BUILD.bazel │ │ │ ├── fakekms.go │ │ │ └── fakekms_test.go │ │ └── fakemonitoring/ │ │ ├── BUILD.bazel │ │ ├── fakemonitoring.go │ │ └── fakemonitoring_test.go │ ├── testkeyset/ │ │ ├── BUILD.bazel │ │ ├── testkeyset.go │ │ └── testkeyset_test.go │ ├── testutil/ │ │ ├── BUILD.bazel │ │ ├── constant.go │ │ ├── hybrid/ │ │ │ ├── BUILD.bazel │ │ │ ├── private_key.go │ │ │ └── private_key_test.go │ │ ├── testutil.go │ │ ├── testutil_test.go │ │ ├── wycheproofutil.go │ │ └── wycheproofutil_test.go │ ├── tink/ │ │ ├── BUILD.bazel │ │ ├── aead.go │ │ ├── deterministic_aead.go │ │ ├── hybrid_decrypt.go │ │ ├── hybrid_encrypt.go │ │ ├── mac.go │ │ ├── signer.go │ │ ├── streamingaead.go │ │ ├── tink.go │ │ ├── verifier.go │ │ └── version.go │ └── tink_version.bzl ├── java_src/ │ ├── .bazelignore │ ├── .bazelrc │ ├── .bazelversion │ ├── BUILD.bazel │ ├── WORKSPACE │ ├── examples/ │ │ ├── .bazelignore │ │ ├── .bazelrc │ │ ├── .bazelversion │ │ ├── BUILD.bazel │ │ ├── WORKSPACE │ │ ├── aead/ │ │ │ ├── AeadExample.java │ │ │ ├── BUILD.bazel │ │ │ ├── README.md │ │ │ ├── aead_example_test.sh │ │ │ └── aead_test_keyset.json │ │ ├── android/ │ │ │ └── helloworld/ │ │ │ ├── README.md │ │ │ ├── app/ │ │ │ │ ├── build.gradle │ │ │ │ ├── maven_local.gradle │ │ │ │ ├── maven_snapshot.gradle │ │ │ │ └── src/ │ │ │ │ └── main/ │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── java/ │ │ │ │ │ └── com/ │ │ │ │ │ └── helloworld/ │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ └── TinkApplication.java │ │ │ │ └── res/ │ │ │ │ ├── layout/ │ │ │ │ │ └── activity_main.xml │ │ │ │ └── values/ │ │ │ │ ├── colors.xml │ │ │ │ ├── dimens.xml │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ │ ├── build.gradle │ │ │ ├── gradle/ │ │ │ │ └── wrapper/ │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ └── gradle-wrapper.properties │ │ │ ├── gradle.properties │ │ │ ├── gradlew │ │ │ ├── gradlew.bat │ │ │ └── settings.gradle │ │ ├── cleartextkeyset/ │ │ │ ├── BUILD.bazel │ │ │ ├── CleartextKeysetExample.java │ │ │ ├── README.md │ │ │ └── cleartext_keyset_example_test.sh │ │ ├── deterministicaead/ │ │ │ ├── BUILD.bazel │ │ │ ├── DeterministicAeadExample.java │ │ │ ├── README.md │ │ │ ├── deterministic_aead_test.sh │ │ │ └── deterministic_aead_test_keyset.json │ │ ├── encryptedkeyset/ │ │ │ ├── BUILD.bazel │ │ │ ├── EncryptedKeysetExample.java │ │ │ ├── README.md │ │ │ └── encrypted_keyset_example_test.sh │ │ ├── envelopeaead/ │ │ │ ├── BUILD.bazel │ │ │ ├── EnvelopeAeadExample.java │ │ │ ├── README.md │ │ │ └── envelope_aead_example_test.sh │ │ ├── gcs/ │ │ │ ├── BUILD.bazel │ │ │ ├── GcsEnvelopeAeadExample.java │ │ │ ├── README.md │ │ │ └── gcs_envelope_aead_example_test.sh │ │ ├── hybrid/ │ │ │ ├── BUILD.bazel │ │ │ ├── HybridExample.java │ │ │ ├── README.md │ │ │ ├── hybrid_example_test.sh │ │ │ ├── hybrid_test_private_keyset.json │ │ │ └── hybrid_test_public_keyset.json │ │ ├── jwt/ │ │ │ ├── BUILD.bazel │ │ │ ├── JwtGeneratePublicJwkSet.java │ │ │ ├── JwtSign.java │ │ │ ├── JwtVerify.java │ │ │ ├── README.md │ │ │ ├── jwt_signature_example_test.sh │ │ │ └── jwt_signature_test_private_keyset.json │ │ ├── mac/ │ │ │ ├── BUILD.bazel │ │ │ ├── MacExample.java │ │ │ ├── README.md │ │ │ ├── mac_example_test.sh │ │ │ └── mac_test_keyset.json │ │ ├── signature/ │ │ │ ├── BUILD.bazel │ │ │ ├── README.md │ │ │ ├── SignatureExample.java │ │ │ ├── signature_example_test.sh │ │ │ ├── signature_test_private_keyset.json │ │ │ └── signature_test_public_keyset.json │ │ ├── streamingaead/ │ │ │ ├── BUILD.bazel │ │ │ ├── README.md │ │ │ ├── StreamingAeadExample.java │ │ │ ├── streaming_aead_example_test.sh │ │ │ └── streaming_aead_test_keyset.json │ │ ├── testdata/ │ │ │ └── gcp/ │ │ │ ├── BUILD.bazel │ │ │ ├── README.md │ │ │ ├── credential.json │ │ │ ├── credential_bad.json │ │ │ ├── key_name.txt │ │ │ └── key_name_bad.txt │ │ └── walkthrough/ │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── walkthrough/ │ │ │ ├── BUILD.bazel │ │ │ ├── CreateKeysetExample.java │ │ │ ├── ObtainAndUseAeadPrimitiveExample.java │ │ │ ├── ReadCleartextKeysetExample.java │ │ │ ├── ReadKeysetExample.java │ │ │ ├── WriteCleartextKeysetExample.java │ │ │ └── WriteKeysetExample.java │ │ └── test/ │ │ └── java/ │ │ └── walkthrough/ │ │ ├── BUILD.bazel │ │ ├── CreateKesetExampleTest.java │ │ ├── ObtainAndUseAeadPrimitiveExampleTest.java │ │ ├── ReadCleartextKeysetExampleTest.java │ │ ├── ReadKeysetExampleTest.java │ │ ├── WriteCleartextKeysetExampleTest.java │ │ └── WriteKeysetExampleTest.java │ ├── jar_jar_rules.txt │ ├── proto/ │ │ ├── BUILD.bazel │ │ ├── aes_cmac.proto │ │ ├── aes_cmac_prf.proto │ │ ├── aes_ctr.proto │ │ ├── aes_ctr_hmac_aead.proto │ │ ├── aes_ctr_hmac_streaming.proto │ │ ├── aes_eax.proto │ │ ├── aes_gcm.proto │ │ ├── aes_gcm_hkdf_streaming.proto │ │ ├── aes_gcm_siv.proto │ │ ├── aes_siv.proto │ │ ├── chacha20_poly1305.proto │ │ ├── common.proto │ │ ├── config.proto │ │ ├── ecdsa.proto │ │ ├── ecies_aead_hkdf.proto │ │ ├── ed25519.proto │ │ ├── empty.proto │ │ ├── hkdf_prf.proto │ │ ├── hmac.proto │ │ ├── hmac_prf.proto │ │ ├── hpke.proto │ │ ├── jwt_ecdsa.proto │ │ ├── jwt_hmac.proto │ │ ├── jwt_rsa_ssa_pkcs1.proto │ │ ├── jwt_rsa_ssa_pss.proto │ │ ├── kms_aead.proto │ │ ├── kms_envelope.proto │ │ ├── prf_based_deriver.proto │ │ ├── rsa_ssa_pkcs1.proto │ │ ├── rsa_ssa_pss.proto │ │ ├── test_proto.proto │ │ ├── tink.proto │ │ └── xchacha20_poly1305.proto │ ├── src/ │ │ ├── main/ │ │ │ ├── java/ │ │ │ │ └── com/ │ │ │ │ └── google/ │ │ │ │ └── crypto/ │ │ │ │ └── tink/ │ │ │ │ ├── AccessesPartialKey.java │ │ │ │ ├── Aead.java │ │ │ │ ├── BUILD.bazel │ │ │ │ ├── BinaryKeysetReader.java │ │ │ │ ├── BinaryKeysetWriter.java │ │ │ │ ├── Catalogue.java │ │ │ │ ├── CleartextKeysetHandle.java │ │ │ │ ├── Config.java │ │ │ │ ├── Configuration.java │ │ │ │ ├── ConfigurationFips140v2.java │ │ │ │ ├── ConfigurationV0.java │ │ │ │ ├── CryptoFormat.java │ │ │ │ ├── DeterministicAead.java │ │ │ │ ├── HybridDecrypt.java │ │ │ │ ├── HybridEncrypt.java │ │ │ │ ├── InsecureSecretKeyAccess.java │ │ │ │ ├── JsonKeysetReader.java │ │ │ │ ├── JsonKeysetWriter.java │ │ │ │ ├── Key.java │ │ │ │ ├── KeyManager.java │ │ │ │ ├── KeyStatus.java │ │ │ │ ├── KeyTemplate.java │ │ │ │ ├── KeyTemplates.java │ │ │ │ ├── KeyWrap.java │ │ │ │ ├── KeysetHandle.java │ │ │ │ ├── KeysetManager.java │ │ │ │ ├── KeysetReader.java │ │ │ │ ├── KeysetWriter.java │ │ │ │ ├── KmsClient.java │ │ │ │ ├── KmsClients.java │ │ │ │ ├── KmsClientsTestUtil.java │ │ │ │ ├── LegacyKeysetSerialization.java │ │ │ │ ├── Mac.java │ │ │ │ ├── NoSecretKeysetHandle.java │ │ │ │ ├── Parameters.java │ │ │ │ ├── PemKeyType.java │ │ │ │ ├── PrimitiveWrapper.java │ │ │ │ ├── PrivateKey.java │ │ │ │ ├── PrivateKeyManager.java │ │ │ │ ├── PublicKeySign.java │ │ │ │ ├── PublicKeyVerify.java │ │ │ │ ├── Registry.java │ │ │ │ ├── RegistryConfiguration.java │ │ │ │ ├── SecretKeyAccess.java │ │ │ │ ├── StreamingAead.java │ │ │ │ ├── TinkJsonProtoKeysetFormat.java │ │ │ │ ├── TinkProtoKeysetFormat.java │ │ │ │ ├── TinkProtoParametersFormat.java │ │ │ │ ├── Util.java │ │ │ │ ├── Version.java.templ │ │ │ │ ├── aead/ │ │ │ │ │ ├── AeadConfig.java │ │ │ │ │ ├── AeadFactory.java │ │ │ │ │ ├── AeadKey.java │ │ │ │ │ ├── AeadKeyTemplates.java │ │ │ │ │ ├── AeadParameters.java │ │ │ │ │ ├── AeadWrapper.java │ │ │ │ │ ├── AesCtrHmacAeadKey.java │ │ │ │ │ ├── AesCtrHmacAeadKeyManager.java │ │ │ │ │ ├── AesCtrHmacAeadParameters.java │ │ │ │ │ ├── AesEaxKey.java │ │ │ │ │ ├── AesEaxKeyManager.java │ │ │ │ │ ├── AesEaxParameters.java │ │ │ │ │ ├── AesGcmKey.java │ │ │ │ │ ├── AesGcmKeyManager.java │ │ │ │ │ ├── AesGcmParameters.java │ │ │ │ │ ├── AesGcmSivKey.java │ │ │ │ │ ├── AesGcmSivKeyManager.java │ │ │ │ │ ├── AesGcmSivParameters.java │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── ChaCha20Poly1305Key.java │ │ │ │ │ ├── ChaCha20Poly1305KeyManager.java │ │ │ │ │ ├── ChaCha20Poly1305Parameters.java │ │ │ │ │ ├── KmsAeadKeyManager.java │ │ │ │ │ ├── KmsEnvelopeAead.java │ │ │ │ │ ├── KmsEnvelopeAeadKeyManager.java │ │ │ │ │ ├── LegacyKmsAeadKey.java │ │ │ │ │ ├── LegacyKmsAeadParameters.java │ │ │ │ │ ├── LegacyKmsAeadProtoSerialization.java │ │ │ │ │ ├── LegacyKmsEnvelopeAeadKey.java │ │ │ │ │ ├── LegacyKmsEnvelopeAeadParameters.java │ │ │ │ │ ├── LegacyKmsEnvelopeAeadProtoSerialization.java │ │ │ │ │ ├── PredefinedAeadParameters.java │ │ │ │ │ ├── XChaCha20Poly1305Key.java │ │ │ │ │ ├── XChaCha20Poly1305KeyManager.java │ │ │ │ │ ├── XChaCha20Poly1305Parameters.java │ │ │ │ │ ├── internal/ │ │ │ │ │ │ ├── AesCtrHmacAeadProtoSerialization.java │ │ │ │ │ │ ├── AesEaxProtoSerialization.java │ │ │ │ │ │ ├── AesGcmProtoSerialization.java │ │ │ │ │ │ ├── AesGcmSivProtoSerialization.java │ │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ │ ├── ChaCha20Poly1305Jce.java │ │ │ │ │ │ ├── ChaCha20Poly1305ProtoSerialization.java │ │ │ │ │ │ ├── ChaCha20Util.java │ │ │ │ │ │ ├── InsecureNonceAesGcmJce.java │ │ │ │ │ │ ├── InsecureNonceChaCha20.java │ │ │ │ │ │ ├── InsecureNonceChaCha20Base.java │ │ │ │ │ │ ├── InsecureNonceChaCha20Poly1305.java │ │ │ │ │ │ ├── InsecureNonceChaCha20Poly1305Base.java │ │ │ │ │ │ ├── InsecureNonceChaCha20Poly1305Jce.java │ │ │ │ │ │ ├── InsecureNonceXChaCha20.java │ │ │ │ │ │ ├── InsecureNonceXChaCha20Poly1305.java │ │ │ │ │ │ ├── LegacyAesCtrHmacTestKeyManager.java │ │ │ │ │ │ ├── LegacyFullAead.java │ │ │ │ │ │ ├── Poly1305.java │ │ │ │ │ │ ├── XChaCha20Poly1305Jce.java │ │ │ │ │ │ └── XChaCha20Poly1305ProtoSerialization.java │ │ │ │ │ └── subtle/ │ │ │ │ │ ├── AeadFactory.java │ │ │ │ │ ├── AesGcmFactory.java │ │ │ │ │ ├── AesGcmSiv.java │ │ │ │ │ └── BUILD.bazel │ │ │ │ ├── annotations/ │ │ │ │ │ ├── Alpha.java │ │ │ │ │ └── BUILD.bazel │ │ │ │ ├── config/ │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── TinkConfig.java │ │ │ │ │ ├── TinkFips.java │ │ │ │ │ └── internal/ │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── TinkFipsDisabled.java │ │ │ │ │ ├── TinkFipsEnabled.java │ │ │ │ │ └── TinkFipsUtil.java │ │ │ │ ├── daead/ │ │ │ │ │ ├── AesSivKey.java │ │ │ │ │ ├── AesSivKeyManager.java │ │ │ │ │ ├── AesSivParameters.java │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── DeterministicAeadConfig.java │ │ │ │ │ ├── DeterministicAeadFactory.java │ │ │ │ │ ├── DeterministicAeadKey.java │ │ │ │ │ ├── DeterministicAeadKeyTemplates.java │ │ │ │ │ ├── DeterministicAeadParameters.java │ │ │ │ │ ├── DeterministicAeadWrapper.java │ │ │ │ │ ├── PredefinedDeterministicAeadParameters.java │ │ │ │ │ └── internal/ │ │ │ │ │ ├── AesSivProtoSerialization.java │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── LegacyFullDeterministicAead.java │ │ │ │ │ └── testing/ │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ └── LegacyAesSivTestKeyManager.java │ │ │ │ ├── hybrid/ │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── EciesAeadHkdfPrivateKeyManager.java │ │ │ │ │ ├── EciesAeadHkdfPublicKeyManager.java │ │ │ │ │ ├── EciesParameters.java │ │ │ │ │ ├── EciesPrivateKey.java │ │ │ │ │ ├── EciesPublicKey.java │ │ │ │ │ ├── HpkeParameters.java │ │ │ │ │ ├── HpkePrivateKey.java │ │ │ │ │ ├── HpkeProtoSerialization.java │ │ │ │ │ ├── HpkePublicKey.java │ │ │ │ │ ├── HybridConfig.java │ │ │ │ │ ├── HybridDecryptConfig.java │ │ │ │ │ ├── HybridDecryptFactory.java │ │ │ │ │ ├── HybridDecryptWrapper.java │ │ │ │ │ ├── HybridEncryptConfig.java │ │ │ │ │ ├── HybridEncryptFactory.java │ │ │ │ │ ├── HybridEncryptWrapper.java │ │ │ │ │ ├── HybridKeyTemplates.java │ │ │ │ │ ├── HybridParameters.java │ │ │ │ │ ├── HybridPrivateKey.java │ │ │ │ │ ├── HybridPublicKey.java │ │ │ │ │ ├── HybridUtil.java │ │ │ │ │ ├── PredefinedHybridParameters.java │ │ │ │ │ ├── internal/ │ │ │ │ │ │ ├── AesGcmHpkeAead.java │ │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ │ ├── ChaCha20Poly1305HpkeAead.java │ │ │ │ │ │ ├── EciesProtoSerialization.java │ │ │ │ │ │ ├── HkdfHpkeKdf.java │ │ │ │ │ │ ├── HpkeAead.java │ │ │ │ │ │ ├── HpkeContext.java │ │ │ │ │ │ ├── HpkeDecrypt.java │ │ │ │ │ │ ├── HpkeEncrypt.java │ │ │ │ │ │ ├── HpkeKdf.java │ │ │ │ │ │ ├── HpkeKem.java │ │ │ │ │ │ ├── HpkeKemEncapOutput.java │ │ │ │ │ │ ├── HpkeKemKeyFactory.java │ │ │ │ │ │ ├── HpkeKemPrivateKey.java │ │ │ │ │ │ ├── HpkePrimitiveFactory.java │ │ │ │ │ │ ├── HpkePrivateKeyManager.java │ │ │ │ │ │ ├── HpkePublicKeyManager.java │ │ │ │ │ │ ├── HpkeUtil.java │ │ │ │ │ │ ├── LegacyFullHybridDecrypt.java │ │ │ │ │ │ ├── LegacyFullHybridEncrypt.java │ │ │ │ │ │ ├── NistCurvesHpkeKem.java │ │ │ │ │ │ ├── NistCurvesHpkeKemPrivateKey.java │ │ │ │ │ │ ├── X25519HpkeKem.java │ │ │ │ │ │ ├── X25519HpkeKemPrivateKey.java │ │ │ │ │ │ └── testing/ │ │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ │ ├── EciesAeadHkdfTestUtil.java │ │ │ │ │ │ ├── HpkeTestUtil.java │ │ │ │ │ │ ├── HybridTestVector.java │ │ │ │ │ │ ├── LegacyHybridDecryptKeyManager.java │ │ │ │ │ │ └── LegacyHybridEncryptKeyManager.java │ │ │ │ │ └── subtle/ │ │ │ │ │ ├── AeadOrDaead.java │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── RsaKem.java │ │ │ │ │ ├── RsaKemHybridDecrypt.java │ │ │ │ │ └── RsaKemHybridEncrypt.java │ │ │ │ ├── integration/ │ │ │ │ │ ├── android/ │ │ │ │ │ │ ├── AndroidKeysetManager.java │ │ │ │ │ │ ├── AndroidKeystoreAesGcm.java │ │ │ │ │ │ ├── AndroidKeystoreKmsClient.java │ │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ │ ├── SharedPrefKeysetReader.java │ │ │ │ │ │ ├── SharedPrefKeysetWriter.java │ │ │ │ │ │ └── internal/ │ │ │ │ │ │ └── FakeAndroidKeystoreProvider.java │ │ │ │ │ ├── awskms/ │ │ │ │ │ │ ├── AwsKmsAead.java │ │ │ │ │ │ ├── AwsKmsClient.java │ │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ │ └── FakeAwsKms.java │ │ │ │ │ ├── gcpkms/ │ │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ │ ├── FakeCloudKms.java │ │ │ │ │ │ ├── FakeKeyManagementServiceClient.java │ │ │ │ │ │ ├── GcpKmsAead.java │ │ │ │ │ │ └── GcpKmsClient.java │ │ │ │ │ └── hcvault/ │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── FakeHcVault.java │ │ │ │ │ └── HcVaultAead.java │ │ │ │ ├── internal/ │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── BigIntegerEncoding.java │ │ │ │ │ ├── BuildDispatchedCode.java │ │ │ │ │ ├── Curve25519.java │ │ │ │ │ ├── Ed25519.java │ │ │ │ │ ├── Ed25519Constants.java │ │ │ │ │ ├── EllipticCurvesUtil.java │ │ │ │ │ ├── EnumTypeProtoConverter.java │ │ │ │ │ ├── Field25519.java │ │ │ │ │ ├── InternalConfiguration.java │ │ │ │ │ ├── JsonParser.java │ │ │ │ │ ├── KeyManagerRegistry.java │ │ │ │ │ ├── KeyParser.java │ │ │ │ │ ├── KeySerializer.java │ │ │ │ │ ├── KeyStatusTypeProtoConverter.java │ │ │ │ │ ├── KeyTemplateProtoConverter.java │ │ │ │ │ ├── KeyTester.java │ │ │ │ │ ├── LegacyKeyManagerImpl.java │ │ │ │ │ ├── LegacyProtoKey.java │ │ │ │ │ ├── LegacyProtoParameters.java │ │ │ │ │ ├── MonitoringUtil.java │ │ │ │ │ ├── MutableKeyCreationRegistry.java │ │ │ │ │ ├── MutableKeyDerivationRegistry.java │ │ │ │ │ ├── MutableMonitoringRegistry.java │ │ │ │ │ ├── MutableParametersRegistry.java │ │ │ │ │ ├── MutablePrimitiveRegistry.java │ │ │ │ │ ├── MutableSerializationRegistry.java │ │ │ │ │ ├── OutputPrefixUtil.java │ │ │ │ │ ├── ParametersParser.java │ │ │ │ │ ├── ParametersSerializer.java │ │ │ │ │ ├── PrimitiveConstructor.java │ │ │ │ │ ├── PrimitiveFactory.java │ │ │ │ │ ├── PrimitiveRegistry.java │ │ │ │ │ ├── PrimitiveSet.java │ │ │ │ │ ├── ProtoKeySerialization.java │ │ │ │ │ ├── ProtoParametersSerialization.java │ │ │ │ │ ├── Random.java │ │ │ │ │ ├── RegistryConfiguration.java │ │ │ │ │ ├── Serialization.java │ │ │ │ │ ├── SerializationRegistry.java │ │ │ │ │ ├── SlowInputStream.java │ │ │ │ │ ├── TinkBugException.java │ │ │ │ │ ├── Util.java │ │ │ │ │ └── testing/ │ │ │ │ │ ├── Asserts.java │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── BigIntegerTestUtil.java │ │ │ │ │ ├── FakeMonitoringClient.java │ │ │ │ │ ├── KeyWithSerialization.java │ │ │ │ │ └── ParametersWithSerialization.java │ │ │ │ ├── jwt/ │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── JsonUtil.java │ │ │ │ │ ├── JwkSetConverter.java │ │ │ │ │ ├── JwtEcdsaParameters.java │ │ │ │ │ ├── JwtEcdsaPrivateKey.java │ │ │ │ │ ├── JwtEcdsaProtoSerialization.java │ │ │ │ │ ├── JwtEcdsaPublicKey.java │ │ │ │ │ ├── JwtEcdsaSignKeyManager.java │ │ │ │ │ ├── JwtEcdsaVerifyKeyManager.java │ │ │ │ │ ├── JwtFormat.java │ │ │ │ │ ├── JwtHmacKey.java │ │ │ │ │ ├── JwtHmacKeyManager.java │ │ │ │ │ ├── JwtHmacParameters.java │ │ │ │ │ ├── JwtHmacProtoSerialization.java │ │ │ │ │ ├── JwtInvalidException.java │ │ │ │ │ ├── JwtMac.java │ │ │ │ │ ├── JwtMacConfig.java │ │ │ │ │ ├── JwtMacKey.java │ │ │ │ │ ├── JwtMacParameters.java │ │ │ │ │ ├── JwtMacWrapper.java │ │ │ │ │ ├── JwtNames.java │ │ │ │ │ ├── JwtPublicKeySign.java │ │ │ │ │ ├── JwtPublicKeySignInternal.java │ │ │ │ │ ├── JwtPublicKeySignWrapper.java │ │ │ │ │ ├── JwtPublicKeyVerify.java │ │ │ │ │ ├── JwtPublicKeyVerifyInternal.java │ │ │ │ │ ├── JwtPublicKeyVerifyWrapper.java │ │ │ │ │ ├── JwtRsaSsaPkcs1Parameters.java │ │ │ │ │ ├── JwtRsaSsaPkcs1PrivateKey.java │ │ │ │ │ ├── JwtRsaSsaPkcs1ProtoSerialization.java │ │ │ │ │ ├── JwtRsaSsaPkcs1PublicKey.java │ │ │ │ │ ├── JwtRsaSsaPkcs1SignKeyManager.java │ │ │ │ │ ├── JwtRsaSsaPkcs1VerifyKeyManager.java │ │ │ │ │ ├── JwtRsaSsaPssParameters.java │ │ │ │ │ ├── JwtRsaSsaPssPrivateKey.java │ │ │ │ │ ├── JwtRsaSsaPssProtoSerialization.java │ │ │ │ │ ├── JwtRsaSsaPssPublicKey.java │ │ │ │ │ ├── JwtRsaSsaPssSignKeyManager.java │ │ │ │ │ ├── JwtRsaSsaPssVerifyKeyManager.java │ │ │ │ │ ├── JwtSignatureConfig.java │ │ │ │ │ ├── JwtSignatureParameters.java │ │ │ │ │ ├── JwtSignaturePrivateKey.java │ │ │ │ │ ├── JwtSignaturePublicKey.java │ │ │ │ │ ├── JwtValidator.java │ │ │ │ │ ├── RawJwt.java │ │ │ │ │ └── VerifiedJwt.java │ │ │ │ ├── keyderivation/ │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── KeyDerivationConfig.java │ │ │ │ │ ├── KeyDerivationKey.java │ │ │ │ │ ├── KeyDerivationParameters.java │ │ │ │ │ ├── KeysetDeriver.java │ │ │ │ │ ├── KeysetDeriverWrapper.java │ │ │ │ │ ├── PrfBasedKeyDerivationKey.java │ │ │ │ │ ├── PrfBasedKeyDerivationParameters.java │ │ │ │ │ └── internal/ │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── KeyDeriver.java │ │ │ │ │ ├── KeysetDeriverWrapper.java │ │ │ │ │ ├── PrfBasedDeriverKeyManager.java │ │ │ │ │ ├── PrfBasedKeyDerivationKeyProtoSerialization.java │ │ │ │ │ └── PrfBasedKeyDeriver.java │ │ │ │ ├── mac/ │ │ │ │ │ ├── AesCmacKey.java │ │ │ │ │ ├── AesCmacKeyManager.java │ │ │ │ │ ├── AesCmacParameters.java │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── ChunkedMac.java │ │ │ │ │ ├── ChunkedMacComputation.java │ │ │ │ │ ├── ChunkedMacVerification.java │ │ │ │ │ ├── ChunkedMacWrapper.java │ │ │ │ │ ├── HmacKey.java │ │ │ │ │ ├── HmacKeyManager.java │ │ │ │ │ ├── HmacParameters.java │ │ │ │ │ ├── MacConfig.java │ │ │ │ │ ├── MacFactory.java │ │ │ │ │ ├── MacKey.java │ │ │ │ │ ├── MacKeyTemplates.java │ │ │ │ │ ├── MacParameters.java │ │ │ │ │ ├── MacWrapper.java │ │ │ │ │ ├── PredefinedMacParameters.java │ │ │ │ │ └── internal/ │ │ │ │ │ ├── AesCmacProtoSerialization.java │ │ │ │ │ ├── AesCmacTestUtil.java │ │ │ │ │ ├── AesUtil.java │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── ChunkedAesCmacComputation.java │ │ │ │ │ ├── ChunkedAesCmacImpl.java │ │ │ │ │ ├── ChunkedAesCmacVerification.java │ │ │ │ │ ├── ChunkedHmacComputation.java │ │ │ │ │ ├── ChunkedHmacImpl.java │ │ │ │ │ ├── ChunkedHmacVerification.java │ │ │ │ │ ├── HmacProtoSerialization.java │ │ │ │ │ ├── HmacTestUtil.java │ │ │ │ │ ├── LegacyFullMac.java │ │ │ │ │ └── LegacyHmacTestKeyManager.java │ │ │ │ ├── monitoring/ │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── MonitoringAnnotations.java │ │ │ │ │ ├── MonitoringClient.java │ │ │ │ │ └── MonitoringKeysetInfo.java │ │ │ │ ├── prf/ │ │ │ │ │ ├── AesCmacPrfKey.java │ │ │ │ │ ├── AesCmacPrfKeyManager.java │ │ │ │ │ ├── AesCmacPrfParameters.java │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── HkdfPrfKey.java │ │ │ │ │ ├── HkdfPrfKeyManager.java │ │ │ │ │ ├── HkdfPrfParameters.java │ │ │ │ │ ├── HmacPrfKey.java │ │ │ │ │ ├── HmacPrfKeyManager.java │ │ │ │ │ ├── HmacPrfParameters.java │ │ │ │ │ ├── PredefinedPrfParameters.java │ │ │ │ │ ├── Prf.java │ │ │ │ │ ├── PrfConfig.java │ │ │ │ │ ├── PrfKey.java │ │ │ │ │ ├── PrfKeyTemplates.java │ │ │ │ │ ├── PrfParameters.java │ │ │ │ │ ├── PrfSet.java │ │ │ │ │ ├── PrfSetWrapper.java │ │ │ │ │ └── internal/ │ │ │ │ │ ├── AesCmacPrfProtoSerialization.java │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── HkdfPrfProtoSerialization.java │ │ │ │ │ ├── HmacPrfProtoSerialization.java │ │ │ │ │ ├── LegacyFullPrf.java │ │ │ │ │ ├── LegacyHmacPrfTestKeyManager.java │ │ │ │ │ └── LegacyHmacPrfTestUtil.java │ │ │ │ ├── signature/ │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── EcdsaParameters.java │ │ │ │ │ ├── EcdsaPrivateKey.java │ │ │ │ │ ├── EcdsaPublicKey.java │ │ │ │ │ ├── EcdsaSignKeyManager.java │ │ │ │ │ ├── EcdsaVerifyKeyManager.java │ │ │ │ │ ├── Ed25519Parameters.java │ │ │ │ │ ├── Ed25519PrivateKey.java │ │ │ │ │ ├── Ed25519PrivateKeyManager.java │ │ │ │ │ ├── Ed25519PublicKey.java │ │ │ │ │ ├── Ed25519PublicKeyManager.java │ │ │ │ │ ├── PredefinedSignatureParameters.java │ │ │ │ │ ├── PublicKeySignConfig.java │ │ │ │ │ ├── PublicKeySignFactory.java │ │ │ │ │ ├── PublicKeySignWrapper.java │ │ │ │ │ ├── PublicKeyVerifyConfig.java │ │ │ │ │ ├── PublicKeyVerifyFactory.java │ │ │ │ │ ├── PublicKeyVerifyWrapper.java │ │ │ │ │ ├── RsaSsaPkcs1Parameters.java │ │ │ │ │ ├── RsaSsaPkcs1PrivateKey.java │ │ │ │ │ ├── RsaSsaPkcs1PublicKey.java │ │ │ │ │ ├── RsaSsaPkcs1SignKeyManager.java │ │ │ │ │ ├── RsaSsaPkcs1VerifyKeyManager.java │ │ │ │ │ ├── RsaSsaPssParameters.java │ │ │ │ │ ├── RsaSsaPssPrivateKey.java │ │ │ │ │ ├── RsaSsaPssPublicKey.java │ │ │ │ │ ├── RsaSsaPssSignKeyManager.java │ │ │ │ │ ├── RsaSsaPssVerifyKeyManager.java │ │ │ │ │ ├── SignatureConfig.java │ │ │ │ │ ├── SignatureKeyTemplates.java │ │ │ │ │ ├── SignatureParameters.java │ │ │ │ │ ├── SignaturePemKeysetReader.java │ │ │ │ │ ├── SignaturePrivateKey.java │ │ │ │ │ ├── SignaturePublicKey.java │ │ │ │ │ └── internal/ │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── EcdsaProtoSerialization.java │ │ │ │ │ ├── Ed25519ProtoSerialization.java │ │ │ │ │ ├── LegacyFullSign.java │ │ │ │ │ ├── LegacyFullVerify.java │ │ │ │ │ ├── RsaSsaPkcs1ProtoSerialization.java │ │ │ │ │ ├── RsaSsaPssProtoSerialization.java │ │ │ │ │ ├── SigUtil.java │ │ │ │ │ └── testing/ │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── EcdsaTestUtil.java │ │ │ │ │ ├── Ed25519TestUtil.java │ │ │ │ │ ├── LegacyPublicKeySignKeyManager.java │ │ │ │ │ ├── LegacyPublicKeyVerifyKeyManager.java │ │ │ │ │ ├── RsaSsaPkcs1TestUtil.java │ │ │ │ │ ├── RsaSsaPssTestUtil.java │ │ │ │ │ └── SignatureTestVector.java │ │ │ │ ├── streamingaead/ │ │ │ │ │ ├── AesCtrHmacStreamingKey.java │ │ │ │ │ ├── AesCtrHmacStreamingKeyManager.java │ │ │ │ │ ├── AesCtrHmacStreamingParameters.java │ │ │ │ │ ├── AesGcmHkdfStreamingKey.java │ │ │ │ │ ├── AesGcmHkdfStreamingKeyManager.java │ │ │ │ │ ├── AesGcmHkdfStreamingParameters.java │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── InputStreamDecrypter.java │ │ │ │ │ ├── PredefinedStreamingAeadParameters.java │ │ │ │ │ ├── ReadableByteChannelDecrypter.java │ │ │ │ │ ├── SeekableByteChannelDecrypter.java │ │ │ │ │ ├── StreamingAeadConfig.java │ │ │ │ │ ├── StreamingAeadFactory.java │ │ │ │ │ ├── StreamingAeadHelper.java │ │ │ │ │ ├── StreamingAeadKey.java │ │ │ │ │ ├── StreamingAeadKeyTemplates.java │ │ │ │ │ ├── StreamingAeadParameters.java │ │ │ │ │ ├── StreamingAeadUtil.java │ │ │ │ │ ├── StreamingAeadWrapper.java │ │ │ │ │ └── internal/ │ │ │ │ │ ├── AesCtrHmacStreamingProtoSerialization.java │ │ │ │ │ ├── AesGcmHkdfStreamingProtoSerialization.java │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── LegacyAesGcmHkdfStreamingTestKeyManager.java │ │ │ │ │ └── LegacyFullStreamingAead.java │ │ │ │ ├── subtle/ │ │ │ │ │ ├── AesCtrHmacStreaming.java │ │ │ │ │ ├── AesCtrJceCipher.java │ │ │ │ │ ├── AesEaxJce.java │ │ │ │ │ ├── AesGcmHkdfStreaming.java │ │ │ │ │ ├── AesGcmJce.java │ │ │ │ │ ├── AesSiv.java │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── Base64.java │ │ │ │ │ ├── Bytes.java │ │ │ │ │ ├── ChaCha20.java │ │ │ │ │ ├── ChaCha20Poly1305.java │ │ │ │ │ ├── EcdsaSignJce.java │ │ │ │ │ ├── EcdsaVerifyJce.java │ │ │ │ │ ├── EciesAeadHkdfDemHelper.java │ │ │ │ │ ├── EciesAeadHkdfHybridDecrypt.java │ │ │ │ │ ├── EciesAeadHkdfHybridEncrypt.java │ │ │ │ │ ├── EciesHkdfRecipientKem.java │ │ │ │ │ ├── EciesHkdfSenderKem.java │ │ │ │ │ ├── Ed25519Sign.java │ │ │ │ │ ├── Ed25519Verify.java │ │ │ │ │ ├── EllipticCurves.java │ │ │ │ │ ├── EncryptThenAuthenticate.java │ │ │ │ │ ├── EngineFactory.java │ │ │ │ │ ├── EngineWrapper.java │ │ │ │ │ ├── Enums.java │ │ │ │ │ ├── Hex.java │ │ │ │ │ ├── Hkdf.java │ │ │ │ │ ├── IndCpaCipher.java │ │ │ │ │ ├── Kwp.java │ │ │ │ │ ├── NonceBasedStreamingAead.java │ │ │ │ │ ├── PemKeyType.java │ │ │ │ │ ├── PrfAesCmac.java │ │ │ │ │ ├── PrfHmacJce.java │ │ │ │ │ ├── PrfMac.java │ │ │ │ │ ├── Random.java │ │ │ │ │ ├── RewindableReadableByteChannel.java │ │ │ │ │ ├── RsaSsaPkcs1SignJce.java │ │ │ │ │ ├── RsaSsaPkcs1VerifyJce.java │ │ │ │ │ ├── RsaSsaPssSignJce.java │ │ │ │ │ ├── RsaSsaPssVerifyJce.java │ │ │ │ │ ├── SelfKeyTestValidators.java │ │ │ │ │ ├── StreamSegmentDecrypter.java │ │ │ │ │ ├── StreamSegmentEncrypter.java │ │ │ │ │ ├── StreamingAeadDecryptingChannel.java │ │ │ │ │ ├── StreamingAeadDecryptingStream.java │ │ │ │ │ ├── StreamingAeadEncryptingChannel.java │ │ │ │ │ ├── StreamingAeadEncryptingStream.java │ │ │ │ │ ├── StreamingAeadSeekableDecryptingChannel.java │ │ │ │ │ ├── SubtleUtil.java │ │ │ │ │ ├── Validators.java │ │ │ │ │ ├── X25519.java │ │ │ │ │ ├── XChaCha20.java │ │ │ │ │ ├── XChaCha20Poly1305.java │ │ │ │ │ └── prf/ │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── HkdfStreamingPrf.java │ │ │ │ │ ├── PrfImpl.java │ │ │ │ │ └── StreamingPrf.java │ │ │ │ ├── testing/ │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── FakeKmsClient.java │ │ │ │ │ ├── HpkeTestEncryption.java │ │ │ │ │ ├── HpkeTestId.java │ │ │ │ │ ├── HpkeTestSetup.java │ │ │ │ │ ├── HpkeTestUtil.java │ │ │ │ │ ├── HpkeTestVector.java │ │ │ │ │ ├── StreamingTestUtil.java │ │ │ │ │ ├── TestUtil.java │ │ │ │ │ └── WycheproofTestUtil.java │ │ │ │ ├── tinkkey/ │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── KeyAccess.java │ │ │ │ │ ├── KeyHandle.java │ │ │ │ │ ├── SecretKeyAccess.java │ │ │ │ │ ├── TinkKey.java │ │ │ │ │ └── internal/ │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── InternalKeyHandle.java │ │ │ │ │ └── ProtoKey.java │ │ │ │ └── util/ │ │ │ │ ├── BUILD.bazel │ │ │ │ ├── Bytes.java │ │ │ │ ├── KeysDownloader.java │ │ │ │ ├── SecretBigInteger.java │ │ │ │ └── SecretBytes.java │ │ │ └── resources/ │ │ │ └── META-INF/ │ │ │ └── proguard/ │ │ │ └── protobuf.pro │ │ └── test/ │ │ ├── BUILD.bazel │ │ └── java/ │ │ └── com/ │ │ └── google/ │ │ └── crypto/ │ │ └── tink/ │ │ ├── BUILD.bazel │ │ ├── BinaryKeysetReaderTest.java │ │ ├── CleartextKeysetHandleTest.java │ │ ├── ConfigTest.java │ │ ├── ConfigurationFips140v2Test.java │ │ ├── ConfigurationFips140v2WithoutConscryptTest.java │ │ ├── ConfigurationV0Test.java │ │ ├── CryptoFormatTest.java │ │ ├── IntegrationTest.java │ │ ├── JsonKeysetReaderTest.java │ │ ├── JsonKeysetWriterTest.java │ │ ├── KeyTemplateTest.java │ │ ├── KeyTemplatesAsParametersTest.java │ │ ├── KeyTemplatesTest.java │ │ ├── KeysetHandleFullPrimitiveTest.java │ │ ├── KeysetHandleTest.java │ │ ├── KeysetManagerTest.java │ │ ├── LateRegistrationTest.java │ │ ├── LegacyKeysetSerializationTest.java │ │ ├── MonitoringUtilTest.java │ │ ├── NoSecretKeysetHandleTest.java │ │ ├── PemKeyTypeTest.java │ │ ├── RegistryConfigurationTest.java │ │ ├── RegistryMultithreadTest.java │ │ ├── RegistryTest.java │ │ ├── SecretKeyAccessTest.java │ │ ├── TinkJsonProtoKeysetFormatTest.java │ │ ├── TinkProtoKeysetFormatTest.java │ │ ├── TinkProtoParametersFormatTest.java │ │ ├── TinkProtoTest.java │ │ ├── UtilTest.java │ │ ├── VersionTest.java │ │ ├── aead/ │ │ │ ├── AeadConfigTest.java │ │ │ ├── AeadFactoryTest.java │ │ │ ├── AeadFactoryWithoutWrapperRegisteredTest.java │ │ │ ├── AeadKeyTemplatesTest.java │ │ │ ├── AeadTest.java │ │ │ ├── AeadWrapperTest.java │ │ │ ├── AesCtrHmacAeadKeyManagerTest.java │ │ │ ├── AesCtrHmacAeadKeyTest.java │ │ │ ├── AesCtrHmacAeadParametersTest.java │ │ │ ├── AesEaxKeyManagerTest.java │ │ │ ├── AesEaxKeyTest.java │ │ │ ├── AesEaxParametersTest.java │ │ │ ├── AesGcmKeyManagerTest.java │ │ │ ├── AesGcmKeyTest.java │ │ │ ├── AesGcmParametersTest.java │ │ │ ├── AesGcmSivKeyManagerTest.java │ │ │ ├── AesGcmSivKeyTest.java │ │ │ ├── AesGcmSivParametersTest.java │ │ │ ├── BUILD.bazel │ │ │ ├── ChaCha20Poly1305KeyManagerTest.java │ │ │ ├── ChaCha20Poly1305KeyTest.java │ │ │ ├── ChaCha20Poly1305ParametersTest.java │ │ │ ├── KmsAeadKeyManagerTest.java │ │ │ ├── KmsEnvelopeAeadKeyManagerTest.java │ │ │ ├── KmsEnvelopeAeadTest.java │ │ │ ├── LegacyKmsAeadKeyTest.java │ │ │ ├── LegacyKmsAeadParametersTest.java │ │ │ ├── LegacyKmsAeadProtoSerializationTest.java │ │ │ ├── LegacyKmsEnvelopeAeadKeyTest.java │ │ │ ├── LegacyKmsEnvelopeAeadParametersTest.java │ │ │ ├── LegacyKmsEnvelopeAeadProtoSerializationTest.java │ │ │ ├── PredefinedAeadParametersTest.java │ │ │ ├── XChaCha20Poly1305KeyManagerTest.java │ │ │ ├── XChaCha20Poly1305KeyTest.java │ │ │ ├── XChaCha20Poly1305ParametersTest.java │ │ │ ├── internal/ │ │ │ │ ├── AesCtrHmacAeadProtoSerializationTest.java │ │ │ │ ├── AesEaxProtoSerializationTest.java │ │ │ │ ├── AesGcmProtoSerializationTest.java │ │ │ │ ├── AesGcmSivProtoSerializationTest.java │ │ │ │ ├── BUILD.bazel │ │ │ │ ├── ChaCha20Poly1305JceTest.java │ │ │ │ ├── ChaCha20Poly1305ProtoSerializationTest.java │ │ │ │ ├── ChaCha20UtilTest.java │ │ │ │ ├── InsecureNonceAesGcmJceTest.java │ │ │ │ ├── InsecureNonceChaCha20Poly1305JceTest.java │ │ │ │ ├── InsecureNonceChaCha20Poly1305Test.java │ │ │ │ ├── InsecureNonceChaCha20Test.java │ │ │ │ ├── InsecureNonceXChaCha20Poly1305Test.java │ │ │ │ ├── InsecureNonceXChaCha20Test.java │ │ │ │ ├── LegacyAesCtrHmacTestKeyManagerTest.java │ │ │ │ ├── LegacyFullAeadIntegrationTest.java │ │ │ │ ├── LegacyFullAeadTest.java │ │ │ │ ├── Poly1305Test.java │ │ │ │ ├── XChaCha20Poly1305JceTest.java │ │ │ │ └── XChaCha20Poly1305ProtoSerializationTest.java │ │ │ └── subtle/ │ │ │ ├── AesGcmSivTest.java │ │ │ └── BUILD.bazel │ │ ├── config/ │ │ │ ├── BUILD.bazel │ │ │ ├── TinkConfigTest.java │ │ │ ├── TinkFipsTest.java │ │ │ └── internal/ │ │ │ ├── BUILD.bazel │ │ │ └── TinkFipsUtilTest.java │ │ ├── custom/ │ │ │ ├── BUILD.bazel │ │ │ └── CustomAeadKeyManagerTest.java │ │ ├── daead/ │ │ │ ├── AesSivKeyManagerTest.java │ │ │ ├── AesSivKeyTest.java │ │ │ ├── AesSivParametersTest.java │ │ │ ├── BUILD.bazel │ │ │ ├── DaeadTest.java │ │ │ ├── DeterministicAeadConfigTest.java │ │ │ ├── DeterministicAeadFactoryTest.java │ │ │ ├── DeterministicAeadFactoryWithoutWrapperRegisteredTest.java │ │ │ ├── DeterministicAeadKeyTemplatesTest.java │ │ │ ├── DeterministicAeadWrapperTest.java │ │ │ ├── KeyManagerIntegrationTest.java │ │ │ ├── PredefinedDeterministicAeadParametersTest.java │ │ │ └── internal/ │ │ │ ├── AesSivProtoSerializationTest.java │ │ │ ├── BUILD.bazel │ │ │ ├── LegacyFullDeterministicAeadTest.java │ │ │ └── testing/ │ │ │ ├── BUILD.bazel │ │ │ └── LegacyAesSivTestKeyManagerTest.java │ │ ├── hybrid/ │ │ │ ├── BUILD.bazel │ │ │ ├── EciesAeadHkdfHybridDecryptTest.java │ │ │ ├── EciesAeadHkdfHybridEncryptTest.java │ │ │ ├── EciesAeadHkdfPrivateKeyManagerTest.java │ │ │ ├── EciesParametersTest.java │ │ │ ├── EciesPrivateKeyTest.java │ │ │ ├── EciesPublicKeyTest.java │ │ │ ├── HpkeParametersTest.java │ │ │ ├── HpkePrivateKeyTest.java │ │ │ ├── HpkeProtoSerializationTest.java │ │ │ ├── HpkePublicKeyTest.java │ │ │ ├── HybridConfigTest.java │ │ │ ├── HybridDecryptFactoryTest.java │ │ │ ├── HybridDecryptWrapperTest.java │ │ │ ├── HybridEncryptDecryptFactoryWithoutWrapperRegisteredTest.java │ │ │ ├── HybridEncryptFactoryTest.java │ │ │ ├── HybridEncryptWrapperTest.java │ │ │ ├── HybridKeyTemplatesTest.java │ │ │ ├── HybridTest.java │ │ │ ├── KeyManagerIntegrationTest.java │ │ │ ├── PredefinedHybridParametersTest.java │ │ │ ├── internal/ │ │ │ │ ├── AesGcmHpkeAeadTest.java │ │ │ │ ├── BUILD.bazel │ │ │ │ ├── ChaCha20Poly1305HpkeAeadTest.java │ │ │ │ ├── EciesProtoSerializationTest.java │ │ │ │ ├── HkdfHpkeKdfTest.java │ │ │ │ ├── HpkeContextTest.java │ │ │ │ ├── HpkeEncryptDecryptTest.java │ │ │ │ ├── HpkeKemKeyFactoryTest.java │ │ │ │ ├── HpkePrimitiveFactoryTest.java │ │ │ │ ├── HpkePrivateKeyManagerTest.java │ │ │ │ ├── HpkeUtilTest.java │ │ │ │ ├── LegacyFullHybridDecryptTest.java │ │ │ │ ├── LegacyFullHybridEncryptTest.java │ │ │ │ ├── NistCurvesHpkeKemTest.java │ │ │ │ ├── X25519HpkeKemPrivateKeyTest.java │ │ │ │ ├── X25519HpkeKemTest.java │ │ │ │ └── testing/ │ │ │ │ ├── BUILD.bazel │ │ │ │ ├── LegacyHybridDecryptKeyManagerTest.java │ │ │ │ └── LegacyHybridEncryptKeyManagerTest.java │ │ │ └── subtle/ │ │ │ ├── AeadOrDaeadTest.java │ │ │ ├── BUILD.bazel │ │ │ ├── RsaKemHybridDecryptTest.java │ │ │ ├── RsaKemHybridEncryptTest.java │ │ │ └── RsaKemTest.java │ │ ├── integration/ │ │ │ ├── awskms/ │ │ │ │ ├── AwsKmsAeadTest.java │ │ │ │ ├── AwsKmsClientTest.java │ │ │ │ ├── BUILD.bazel │ │ │ │ └── FakeAwsKmsTest.java │ │ │ ├── gcpkms/ │ │ │ │ ├── BUILD.bazel │ │ │ │ ├── FakeCloudKmsTest.java │ │ │ │ ├── GcpKmsAeadTest.java │ │ │ │ ├── GcpKmsClientTest.java │ │ │ │ └── GcpKmsIntegrationTest.java │ │ │ └── hcvault/ │ │ │ ├── BUILD.bazel │ │ │ ├── FakeHcVaultTest.java │ │ │ └── HcVaultAeadTest.java │ │ ├── internal/ │ │ │ ├── BUILD.bazel │ │ │ ├── BigIntegerEncodingTest.java │ │ │ ├── Curve25519Test.java │ │ │ ├── Ed25519Test.java │ │ │ ├── EllipticCurvesUtilTest.java │ │ │ ├── EnumTypeProtoConverterTest.java │ │ │ ├── Field25519Test.java │ │ │ ├── InternalConfigurationTest.java │ │ │ ├── JsonParserTest.java │ │ │ ├── KeyManagerRegistryTest.java │ │ │ ├── KeyParserTest.java │ │ │ ├── KeySerializerTest.java │ │ │ ├── KeyTemplateProtoConverterTest.java │ │ │ ├── KeyTesterTest.java │ │ │ ├── LegacyKeyManagerImplTest.java │ │ │ ├── LegacyProtoKeyTest.java │ │ │ ├── LegacyProtoParametersTest.java │ │ │ ├── MutableKeyCreationRegistryTest.java │ │ │ ├── MutableKeyDerivationRegistryTest.java │ │ │ ├── MutableMonitoringRegistryTest.java │ │ │ ├── MutableParametersRegistryTest.java │ │ │ ├── MutablePrimitiveRegistryMultithreadTest.java │ │ │ ├── MutablePrimitiveRegistryTest.java │ │ │ ├── MutableSerializationRegistryMultithreadTest.java │ │ │ ├── MutableSerializationRegistryTest.java │ │ │ ├── OutputPrefixUtilTest.java │ │ │ ├── ParametersParserTest.java │ │ │ ├── ParametersSerializerTest.java │ │ │ ├── PrimitiveConstructorTest.java │ │ │ ├── PrimitiveRegistryTest.java │ │ │ ├── PrimitiveSetTest.java │ │ │ ├── ProtoKeySerializationTest.java │ │ │ ├── ProtoParametersSerializationTest.java │ │ │ ├── RandomTest.java │ │ │ ├── RandomWithoutConscryptTest.java │ │ │ ├── RandomWithoutInstallingConscryptTest.java │ │ │ ├── RegistryConfigurationTest.java │ │ │ ├── SerializationRegistryTest.java │ │ │ ├── SlowInputStreamTest.java │ │ │ ├── TinkBugExceptionTest.java │ │ │ ├── UtilTest.java │ │ │ └── testing/ │ │ │ ├── AssertsTest.java │ │ │ ├── BUILD.bazel │ │ │ ├── BigIntegerTestUtilTest.java │ │ │ ├── FakeMonitoringClientTest.java │ │ │ ├── KeyWithSerializationTest.java │ │ │ └── ParametersWithSerializationTest.java │ │ ├── jwt/ │ │ │ ├── BUILD.bazel │ │ │ ├── JsonUtilTest.java │ │ │ ├── JwkSetConverterTest.java │ │ │ ├── JwtEcdsaParametersTest.java │ │ │ ├── JwtEcdsaPrivateKeyTest.java │ │ │ ├── JwtEcdsaProtoSerializationTest.java │ │ │ ├── JwtEcdsaPublicKeyTest.java │ │ │ ├── JwtEcdsaSignKeyManagerTest.java │ │ │ ├── JwtEcdsaVerifyKeyManagerTest.java │ │ │ ├── JwtFormatTest.java │ │ │ ├── JwtHmacKeyManagerTest.java │ │ │ ├── JwtHmacKeyTest.java │ │ │ ├── JwtHmacParametersTest.java │ │ │ ├── JwtHmacProtoSerializationTest.java │ │ │ ├── JwtMacConfigTest.java │ │ │ ├── JwtMacWrapperTest.java │ │ │ ├── JwtPublicKeySignVerifyWrappersTest.java │ │ │ ├── JwtRsaSsaPkcs1ParametersTest.java │ │ │ ├── JwtRsaSsaPkcs1PrivateKeyTest.java │ │ │ ├── JwtRsaSsaPkcs1ProtoSerializationTest.java │ │ │ ├── JwtRsaSsaPkcs1PublicKeyTest.java │ │ │ ├── JwtRsaSsaPkcs1SignKeyManagerTest.java │ │ │ ├── JwtRsaSsaPssParametersTest.java │ │ │ ├── JwtRsaSsaPssPrivateKeyTest.java │ │ │ ├── JwtRsaSsaPssProtoSerializationTest.java │ │ │ ├── JwtRsaSsaPssPublicKeyTest.java │ │ │ ├── JwtRsaSsaPssSignKeyManagerTest.java │ │ │ ├── JwtRsaSsaPssVerifyKeyManagerTest.java │ │ │ ├── JwtSignatureConfigTest.java │ │ │ ├── JwtSignatureTest.java │ │ │ ├── JwtTest.java │ │ │ ├── JwtValidatorTest.java │ │ │ ├── RawJwtTest.java │ │ │ └── VerifiedJwtTest.java │ │ ├── keyderivation/ │ │ │ ├── BUILD.bazel │ │ │ ├── KeyDerivationConfigTest.java │ │ │ ├── KeyDerivationTest.java │ │ │ ├── KeysetDeriverWrapperTest.java │ │ │ ├── PrfBasedKeyDerivationKeyTest.java │ │ │ ├── PrfBasedKeyDerivationParametersTest.java │ │ │ └── internal/ │ │ │ ├── BUILD.bazel │ │ │ ├── KeysetDeriverWrapperTest.java │ │ │ ├── PrfBasedDeriverKeyManagerTest.java │ │ │ ├── PrfBasedDeriverSecondTest.java │ │ │ ├── PrfBasedKeyDerivationKeyProtoSerializationTest.java │ │ │ └── PrfBasedKeyDeriverTest.java │ │ ├── mac/ │ │ │ ├── AesCmacKeyManagerTest.java │ │ │ ├── AesCmacKeyTest.java │ │ │ ├── AesCmacParametersTest.java │ │ │ ├── BUILD.bazel │ │ │ ├── ChunkedMacTest.java │ │ │ ├── ChunkedMacWrapperTest.java │ │ │ ├── HmacKeyManagerTest.java │ │ │ ├── HmacKeyTest.java │ │ │ ├── HmacParametersTest.java │ │ │ ├── MacConfigTest.java │ │ │ ├── MacFactoryTest.java │ │ │ ├── MacFactoryWithoutWrapperRegisteredTest.java │ │ │ ├── MacKeyTemplatesTest.java │ │ │ ├── MacTest.java │ │ │ ├── MacWrapperTest.java │ │ │ ├── PredefinedMacParametersTest.java │ │ │ └── internal/ │ │ │ ├── AesCmacProtoSerializationTest.java │ │ │ ├── AesUtilTest.java │ │ │ ├── BUILD.bazel │ │ │ ├── ChunkedAesCmacTest.java │ │ │ ├── ChunkedHmacTest.java │ │ │ ├── HmacProtoSerializationTest.java │ │ │ ├── LegacyFullMacIntegrationTest.java │ │ │ └── LegacyFullMacTest.java │ │ ├── monitoring/ │ │ │ ├── BUILD.bazel │ │ │ ├── MonitoringAnnotationsTest.java │ │ │ └── MonitoringKeysetInfoTest.java │ │ ├── prf/ │ │ │ ├── AesCmacPrfKeyManagerTest.java │ │ │ ├── AesCmacPrfKeyTest.java │ │ │ ├── AesCmacPrfParametersTest.java │ │ │ ├── BUILD.bazel │ │ │ ├── HkdfPrfKeyManagerTest.java │ │ │ ├── HkdfPrfKeyTest.java │ │ │ ├── HkdfPrfParametersTest.java │ │ │ ├── HmacPrfKeyManagerTest.java │ │ │ ├── HmacPrfKeyTest.java │ │ │ ├── HmacPrfParametersTest.java │ │ │ ├── PredefinedPrfParametersTest.java │ │ │ ├── PrfConfigTest.java │ │ │ ├── PrfKeyTemplatesTest.java │ │ │ ├── PrfSetWrapperTest.java │ │ │ ├── PrfTest.java │ │ │ └── internal/ │ │ │ ├── AesCmacPrfProtoSerializationTest.java │ │ │ ├── BUILD.bazel │ │ │ ├── HkdfPrfProtoSerializationTest.java │ │ │ ├── HmacPrfProtoSerializationTest.java │ │ │ ├── LegacyFullPrfIntegrationTest.java │ │ │ ├── LegacyFullPrfTest.java │ │ │ └── LegacyHmacPrfTestKeyManagerTest.java │ │ ├── signature/ │ │ │ ├── BUILD.bazel │ │ │ ├── EcdsaParametersTest.java │ │ │ ├── EcdsaPrivateKeyTest.java │ │ │ ├── EcdsaPublicKeyTest.java │ │ │ ├── EcdsaSignKeyManagerTest.java │ │ │ ├── EcdsaVerifyKeyManagerTest.java │ │ │ ├── Ed25519ParametersTest.java │ │ │ ├── Ed25519PrivateKeyManagerTest.java │ │ │ ├── Ed25519PrivateKeyTest.java │ │ │ ├── Ed25519PublicKeyManagerTest.java │ │ │ ├── Ed25519PublicKeyTest.java │ │ │ ├── KeyConversionTest.java │ │ │ ├── KeyManagerIntegrationTest.java │ │ │ ├── PredefinedSignatureParametersTest.java │ │ │ ├── PublicKeySignFactoryTest.java │ │ │ ├── PublicKeySignVerifyFactoryWithoutWrapperRegisteredTest.java │ │ │ ├── PublicKeySignWrapperTest.java │ │ │ ├── PublicKeyVerifyFactoryTest.java │ │ │ ├── PublicKeyVerifyWrapperTest.java │ │ │ ├── RsaSsaPkcs1ParametersTest.java │ │ │ ├── RsaSsaPkcs1PrivateKeyTest.java │ │ │ ├── RsaSsaPkcs1PublicKeyTest.java │ │ │ ├── RsaSsaPkcs1SignKeyManagerTest.java │ │ │ ├── RsaSsaPkcs1VerifyKeyManagerTest.java │ │ │ ├── RsaSsaPssParametersTest.java │ │ │ ├── RsaSsaPssPrivateKeyTest.java │ │ │ ├── RsaSsaPssPublicKeyTest.java │ │ │ ├── RsaSsaPssSignKeyManagerTest.java │ │ │ ├── RsaSsaPssVerifyKeyManagerTest.java │ │ │ ├── SignatureConfigTest.java │ │ │ ├── SignatureKeyTemplatesTest.java │ │ │ ├── SignaturePemKeysetReaderTest.java │ │ │ ├── SignatureTest.java │ │ │ └── internal/ │ │ │ ├── BUILD.bazel │ │ │ ├── EcdsaProtoSerializationTest.java │ │ │ ├── Ed25519ProtoSerializationTest.java │ │ │ ├── LegacyFullSignTest.java │ │ │ ├── LegacyFullVerifyTest.java │ │ │ ├── RsaSsaPkcs1ProtoSerializationTest.java │ │ │ ├── RsaSsaPssProtoSerializationTest.java │ │ │ ├── SigUtilTest.java │ │ │ └── testing/ │ │ │ ├── BUILD.bazel │ │ │ ├── LegacyPublicKeySignKeyManagerTest.java │ │ │ └── LegacyPublicKeyVerifyKeyManagerTest.java │ │ ├── streamingaead/ │ │ │ ├── AesCtrHmacStreamingKeyManagerTest.java │ │ │ ├── AesCtrHmacStreamingKeyTest.java │ │ │ ├── AesCtrHmacStreamingParametersTest.java │ │ │ ├── AesGcmHkdfStreamingKeyManagerTest.java │ │ │ ├── AesGcmHkdfStreamingKeyTest.java │ │ │ ├── AesGcmHkdfStreamingParametersTest.java │ │ │ ├── BUILD.bazel │ │ │ ├── PredefinedStreamingAeadParametersTest.java │ │ │ ├── StreamingAeadConfigTest.java │ │ │ ├── StreamingAeadFactoryTest.java │ │ │ ├── StreamingAeadFactoryWithoutWrapperRegisteredTest.java │ │ │ ├── StreamingAeadKeyTemplatesTest.java │ │ │ ├── StreamingAeadTest.java │ │ │ ├── StreamingAeadUtilTest.java │ │ │ ├── StreamingAeadWrapperLegacyTest.java │ │ │ ├── StreamingAeadWrapperTest.java │ │ │ └── internal/ │ │ │ ├── AesCtrHmacStreamingProtoSerializationTest.java │ │ │ ├── AesGcmHkdfStreamingProtoSerializationTest.java │ │ │ ├── BUILD.bazel │ │ │ ├── LegacyAesGcmHkdfStreamingTestKeyManagerTest.java │ │ │ ├── LegacyFullStreamingAeadIntegrationTest.java │ │ │ └── LegacyFullStreamingAeadTest.java │ │ ├── subtle/ │ │ │ ├── AeadThreadSafetyTest.java │ │ │ ├── AesCtrHmacStreamingTest.java │ │ │ ├── AesCtrJceCipherTest.java │ │ │ ├── AesEaxJceTest.java │ │ │ ├── AesGcmHkdfStreamingTest.java │ │ │ ├── AesGcmJceTest.java │ │ │ ├── AesSivTest.java │ │ │ ├── BUILD.bazel │ │ │ ├── Base64Test.java │ │ │ ├── BytesTest.java │ │ │ ├── ChaCha20Poly1305Test.java │ │ │ ├── ChaCha20Test.java │ │ │ ├── DaeadThreadSafetyTest.java │ │ │ ├── EcdsaSignJceTest.java │ │ │ ├── EcdsaVerifyJceTest.java │ │ │ ├── Ed25519SignTest.java │ │ │ ├── Ed25519VerifyTest.java │ │ │ ├── EllipticCurvesTest.java │ │ │ ├── EncryptThenAuthenticateTest.java │ │ │ ├── EngineFactoryFipsTest.java │ │ │ ├── EngineFactoryTest.java │ │ │ ├── HkdfTest.java │ │ │ ├── KwpTest.java │ │ │ ├── PemKeyTypeTest.java │ │ │ ├── PrfAesCmacTest.java │ │ │ ├── PrfHmacJceTest.java │ │ │ ├── PrfMacTest.java │ │ │ ├── RandomTest.java │ │ │ ├── RewindableReadableByteChannelTest.java │ │ │ ├── RsaSsaPkcs1SignJceTest.java │ │ │ ├── RsaSsaPkcs1VerifyJceTest.java │ │ │ ├── RsaSsaPssSignJceTest.java │ │ │ ├── RsaSsaPssVerifyJceTest.java │ │ │ ├── SelfKeyTestValidatorsTest.java │ │ │ ├── SignatureThreadSafetyTest.java │ │ │ ├── StreamingAeadThreadSafetyTest.java │ │ │ ├── SubtleUtilTest.java │ │ │ ├── ValidatorsTest.java │ │ │ ├── X25519Test.java │ │ │ ├── XChaCha20Poly1305Test.java │ │ │ ├── XChaCha20Test.java │ │ │ └── prf/ │ │ │ ├── BUILD.bazel │ │ │ ├── HkdfStreamingPrfTest.java │ │ │ └── PrfImplTest.java │ │ ├── testing/ │ │ │ ├── BUILD.bazel │ │ │ ├── FakeKmsClientTest.java │ │ │ ├── HpkeTestUtilTest.java │ │ │ └── TestUtilTest.java │ │ ├── tinkkey/ │ │ │ ├── BUILD.bazel │ │ │ ├── KeyAccessTest.java │ │ │ ├── KeyHandleTest.java │ │ │ ├── SecretKeyAccessTest.java │ │ │ └── internal/ │ │ │ ├── BUILD.bazel │ │ │ └── ProtoKeyTest.java │ │ └── util/ │ │ ├── BUILD.bazel │ │ ├── BytesTest.java │ │ ├── KeysDownloaderTest.java │ │ ├── SecretBigIntegerTest.java │ │ └── SecretBytesTest.java │ ├── src_android/ │ │ └── main/ │ │ └── java/ │ │ └── com/ │ │ └── google/ │ │ └── crypto/ │ │ └── tink/ │ │ └── internal/ │ │ ├── BUILD.bazel │ │ └── BuildDispatchedCode.java │ ├── template_rule.bzl │ ├── testdata/ │ │ ├── BUILD.bazel │ │ ├── aws/ │ │ │ ├── BUILD.bazel │ │ │ ├── README.md │ │ │ ├── access_keys_bad.csv │ │ │ ├── credentials.cred │ │ │ ├── credentials.csv │ │ │ ├── credentials.ini │ │ │ ├── credentials_bad.csv │ │ │ ├── credentials_bad.ini │ │ │ ├── key_arn.txt │ │ │ └── key_arn_bad.txt │ │ ├── gcp/ │ │ │ ├── BUILD.bazel │ │ │ ├── README.md │ │ │ ├── credential.json │ │ │ ├── credential_bad.json │ │ │ ├── key_name.txt │ │ │ └── key_name_bad.txt │ │ ├── keysets/ │ │ │ └── BUILD.bazel │ │ └── testvectors/ │ │ ├── BUILD.bazel │ │ └── hpke_boringssl.json │ ├── tink_java_deps.bzl │ ├── tink_java_deps_init.bzl │ ├── tink_version.bzl │ └── tools/ │ ├── BUILD.bazel │ ├── check_deps.bzl │ ├── gen_java_test_rules.bzl │ ├── gen_maven_jar_rules.bzl │ ├── jar_jar.bzl │ ├── java_single_jar.bzl │ ├── javadoc.bzl │ └── refaster/ │ ├── README.md │ └── java/ │ └── com/ │ └── google/ │ ├── tink1_templates/ │ │ └── AllChanges.java │ └── tinkuser/ │ ├── TinkUser.java │ └── TinkUser.java_expected ├── kokoro/ │ ├── README.md │ ├── gcp_ubuntu_per_language/ │ │ ├── cc/ │ │ │ ├── bazel/ │ │ │ │ └── run_tests.sh │ │ │ ├── bazel_fips/ │ │ │ │ └── run_tests.sh │ │ │ ├── cmake/ │ │ │ │ └── run_tests.sh │ │ │ ├── cmake_openssl/ │ │ │ │ └── run_tests.sh │ │ │ └── examples/ │ │ │ ├── cmake/ │ │ │ │ └── run_tests.sh │ │ │ └── cmake_openssl/ │ │ │ └── run_tests.sh │ │ ├── go/ │ │ │ ├── bazel/ │ │ │ │ └── run_tests.sh │ │ │ └── gomod/ │ │ │ └── run_tests.sh │ │ ├── java_src/ │ │ │ └── run_tests.sh │ │ └── python/ │ │ └── pip/ │ │ └── run_tests.sh │ ├── macos_external/ │ │ ├── cc/ │ │ │ ├── bazel/ │ │ │ │ └── run_tests.sh │ │ │ ├── cmake/ │ │ │ │ └── run_tests.sh │ │ │ └── examples/ │ │ │ └── cmake/ │ │ │ └── run_tests.sh │ │ ├── go/ │ │ │ ├── bazel/ │ │ │ │ └── run_tests.sh │ │ │ └── gomod/ │ │ │ └── run_tests.sh │ │ ├── java_src/ │ │ │ └── run_tests.sh │ │ ├── python/ │ │ │ └── pip/ │ │ │ └── run_tests.sh │ │ └── tools/ │ │ └── run_tests.sh │ ├── run_tests.sh │ └── testutils/ │ ├── check_go_generated_files_up_to_date.sh │ ├── copy_credentials.sh │ ├── create_main_build_file.py │ ├── install_cmake.sh │ ├── install_go.sh │ ├── install_openssl.sh │ ├── install_protoc.sh │ ├── install_python3.sh │ ├── install_tink_via_pip.sh │ ├── install_vault.sh │ ├── run_bazel_tests.sh │ ├── run_cmake_tests.sh │ ├── run_go_mod_tests.sh │ ├── run_hcvault_test_server.sh │ ├── test_utils.sh │ ├── update_android_sdk.sh │ └── upgrade_gcc.sh ├── passing_test.sh ├── proto/ │ ├── BUILD.bazel │ ├── CMakeLists.txt │ ├── aes_cmac.proto │ ├── aes_cmac_prf.proto │ ├── aes_ctr.proto │ ├── aes_ctr_hmac_aead.proto │ ├── aes_ctr_hmac_streaming.proto │ ├── aes_eax.proto │ ├── aes_gcm.proto │ ├── aes_gcm_hkdf_streaming.proto │ ├── aes_gcm_siv.proto │ ├── aes_siv.proto │ ├── chacha20_poly1305.proto │ ├── common.proto │ ├── config.proto │ ├── ecdsa.proto │ ├── ecies_aead_hkdf.proto │ ├── ed25519.proto │ ├── empty.proto │ ├── experimental/ │ │ └── pqcrypto/ │ │ ├── BUILD.bazel │ │ ├── cecpq2_aead_hkdf.proto │ │ ├── dilithium.proto │ │ ├── falcon.proto │ │ ├── slh_dsa.proto │ │ └── sphincs.proto │ ├── hkdf_prf.proto │ ├── hmac.proto │ ├── hmac_prf.proto │ ├── hpke.proto │ ├── jwt_ecdsa.proto │ ├── jwt_hmac.proto │ ├── jwt_rsa_ssa_pkcs1.proto │ ├── jwt_rsa_ssa_pss.proto │ ├── kms_aead.proto │ ├── kms_envelope.proto │ ├── prf_based_deriver.proto │ ├── rsa_ssa_pkcs1.proto │ ├── rsa_ssa_pss.proto │ ├── test_proto.proto │ ├── tink.proto │ └── xchacha20_poly1305.proto ├── python/ │ ├── .bazelignore │ ├── .bazelrc │ ├── .bazelversion │ ├── BUILD.bazel │ ├── MANIFEST.in │ ├── README.md │ ├── VERSION │ ├── WORKSPACE │ ├── examples/ │ │ ├── .bazelrc │ │ ├── .bazelversion │ │ ├── BUILD.bazel │ │ ├── WORKSPACE │ │ ├── aead/ │ │ │ ├── BUILD.bazel │ │ │ ├── README.md │ │ │ ├── aead_basic.py │ │ │ ├── aead_basic_test.py │ │ │ ├── aead_cli.py │ │ │ ├── aead_cli_test.sh │ │ │ └── aead_test_keyset.json │ │ ├── cleartext_keyset/ │ │ │ ├── BUILD.bazel │ │ │ ├── README.md │ │ │ ├── cleartext_keyset_cli.py │ │ │ └── cleartext_keyset_cli_test.sh │ │ ├── deterministic_aead/ │ │ │ ├── BUILD.bazel │ │ │ ├── README.md │ │ │ ├── deterministic_aead_basic.py │ │ │ ├── deterministic_aead_basic_test.py │ │ │ ├── deterministic_aead_cli.py │ │ │ ├── deterministic_aead_cli_test.sh │ │ │ └── deterministic_aead_test_keyset.json │ │ ├── encrypted_keyset/ │ │ │ ├── BUILD.bazel │ │ │ ├── README.md │ │ │ ├── encrypted_keyset_cli.py │ │ │ └── encrypted_keyset_cli_test.sh │ │ ├── envelope_aead/ │ │ │ ├── BUILD.bazel │ │ │ ├── README.md │ │ │ ├── envelope_cli.py │ │ │ └── envelope_cli_test.sh │ │ ├── gcs/ │ │ │ ├── BUILD.bazel │ │ │ ├── README.md │ │ │ ├── gcs_envelope_aead_cli.py │ │ │ └── gcs_envelope_aead_cli_test.sh │ │ ├── hybrid/ │ │ │ ├── BUILD.bazel │ │ │ ├── README.md │ │ │ ├── hybrid_basic.py │ │ │ ├── hybrid_basic_test.py │ │ │ ├── hybrid_cli.py │ │ │ ├── hybrid_cli_test.sh │ │ │ ├── hybrid_test_private_keyset.json │ │ │ └── hybrid_test_public_keyset.json │ │ ├── jwt/ │ │ │ ├── BUILD.bazel │ │ │ ├── README.md │ │ │ ├── jwt_generate_public_jwk_set.py │ │ │ ├── jwt_sign_cli.py │ │ │ ├── jwt_signature_test.sh │ │ │ ├── jwt_test_private_keyset.json │ │ │ ├── jwt_test_public_keyset.json │ │ │ └── jwt_verify_cli.py │ │ ├── mac/ │ │ │ ├── BUILD.bazel │ │ │ ├── README.md │ │ │ ├── mac_basic.py │ │ │ ├── mac_basic_test.py │ │ │ ├── mac_cli.py │ │ │ ├── mac_cli_test.sh │ │ │ └── mac_test_keyset.json │ │ ├── requirements.in │ │ ├── requirements.txt │ │ ├── signature/ │ │ │ ├── BUILD.bazel │ │ │ ├── README.md │ │ │ ├── signature_basic.py │ │ │ ├── signature_basic_test.py │ │ │ ├── signature_cli.py │ │ │ ├── signature_cli_test.sh │ │ │ ├── signature_test_private_keyset.json │ │ │ └── signature_test_public_keyset.json │ │ ├── streaming_aead/ │ │ │ ├── BUILD.bazel │ │ │ ├── README.md │ │ │ ├── streaming_aead_cli.py │ │ │ ├── streaming_aead_cli_test.sh │ │ │ └── streaming_aead_keyset.json │ │ ├── testdata/ │ │ │ └── gcp/ │ │ │ ├── BUILD.bazel │ │ │ ├── README.md │ │ │ ├── credential.json │ │ │ ├── credential_bad.json │ │ │ ├── key_name.txt │ │ │ └── key_name_bad.txt │ │ └── walkthrough/ │ │ ├── BUILD.bazel │ │ ├── create_keyset.py │ │ ├── create_keyset_test.py │ │ ├── load_cleartext_keyset.py │ │ ├── load_cleartext_keyset_test.py │ │ ├── load_encrypted_keyset.py │ │ ├── load_encrypted_keyset_test.py │ │ ├── obtain_and_use_a_primitive.py │ │ ├── obtain_and_use_a_primitive_test.py │ │ ├── write_cleartext_keyset.py │ │ ├── write_cleartext_keyset_test.py │ │ ├── write_keyset.py │ │ └── write_keyset_test.py │ ├── requirements.in │ ├── requirements.txt │ ├── requirements_all.txt │ ├── requirements_awskms.in │ ├── requirements_gcpkms.in │ ├── requirements_hcvault.in │ ├── setup.py │ ├── testdata/ │ │ ├── aws/ │ │ │ ├── BUILD.bazel │ │ │ ├── README.md │ │ │ ├── access_keys_bad.csv │ │ │ ├── credentials.cred │ │ │ ├── credentials.csv │ │ │ ├── credentials.ini │ │ │ ├── credentials_bad.csv │ │ │ ├── credentials_bad.ini │ │ │ ├── key_arn.txt │ │ │ └── key_arn_bad.txt │ │ └── gcp/ │ │ ├── BUILD.bazel │ │ ├── README.md │ │ ├── credential.json │ │ ├── credential_bad.json │ │ ├── key_name.txt │ │ └── key_name_bad.txt │ ├── tink/ │ │ ├── BUILD.bazel │ │ ├── __init__.py │ │ ├── _insecure_keyset_handle.py │ │ ├── _insecure_keyset_handle_test.py │ │ ├── _json_proto_keyset_format.py │ │ ├── _json_proto_keyset_format_test.py │ │ ├── _keyset_handle.py │ │ ├── _keyset_handle_test.py │ │ ├── _keyset_reader.py │ │ ├── _keyset_reader_test.py │ │ ├── _keyset_writer.py │ │ ├── _keyset_writer_test.py │ │ ├── _kms_clients.py │ │ ├── _kms_clients_test.py │ │ ├── _proto_keyset_format.py │ │ ├── _proto_keyset_format_test.py │ │ ├── _secret_key_access.py │ │ ├── aead/ │ │ │ ├── BUILD.bazel │ │ │ ├── __init__.py │ │ │ ├── _aead.py │ │ │ ├── _aead_key_manager.py │ │ │ ├── _aead_key_manager_test.py │ │ │ ├── _aead_key_templates.py │ │ │ ├── _aead_key_templates_test.py │ │ │ ├── _aead_wrapper.py │ │ │ ├── _aead_wrapper_test.py │ │ │ ├── _kms_aead_key_manager.py │ │ │ ├── _kms_aead_key_manager_test.py │ │ │ ├── _kms_envelope_aead.py │ │ │ └── _kms_envelope_aead_test.py │ │ ├── cc/ │ │ │ ├── BUILD.bazel │ │ │ ├── cc_hpke_config.cc │ │ │ ├── cc_hpke_config.h │ │ │ ├── cc_jwt_config.cc │ │ │ ├── cc_jwt_config.h │ │ │ ├── cc_key_manager.h │ │ │ ├── cc_streaming_aead_wrappers.cc │ │ │ ├── cc_streaming_aead_wrappers.h │ │ │ ├── cc_streaming_aead_wrappers_test.cc │ │ │ ├── cc_tink_config.cc │ │ │ ├── cc_tink_config.h │ │ │ ├── input_stream_adapter.cc │ │ │ ├── input_stream_adapter.h │ │ │ ├── input_stream_adapter_test.cc │ │ │ ├── output_stream_adapter.cc │ │ │ ├── output_stream_adapter.h │ │ │ ├── output_stream_adapter_test.cc │ │ │ ├── pybind/ │ │ │ │ ├── BUILD.bazel │ │ │ │ ├── aead.cc │ │ │ │ ├── aead.h │ │ │ │ ├── cc_hpke_config.cc │ │ │ │ ├── cc_hpke_config.h │ │ │ │ ├── cc_jwt_config.cc │ │ │ │ ├── cc_jwt_config.h │ │ │ │ ├── cc_key_manager.cc │ │ │ │ ├── cc_key_manager.h │ │ │ │ ├── cc_key_manager_test.py │ │ │ │ ├── cc_streaming_aead_wrappers.cc │ │ │ │ ├── cc_streaming_aead_wrappers.h │ │ │ │ ├── cc_tink_config.cc │ │ │ │ ├── cc_tink_config.h │ │ │ │ ├── cc_tink_config_test.py │ │ │ │ ├── deterministic_aead.cc │ │ │ │ ├── deterministic_aead.h │ │ │ │ ├── hybrid_decrypt.cc │ │ │ │ ├── hybrid_decrypt.h │ │ │ │ ├── hybrid_encrypt.cc │ │ │ │ ├── hybrid_encrypt.h │ │ │ │ ├── import_helper.cc │ │ │ │ ├── import_helper.h │ │ │ │ ├── input_stream_adapter.cc │ │ │ │ ├── input_stream_adapter.h │ │ │ │ ├── mac.cc │ │ │ │ ├── mac.h │ │ │ │ ├── output_stream_adapter.cc │ │ │ │ ├── output_stream_adapter.h │ │ │ │ ├── prf.cc │ │ │ │ ├── prf.h │ │ │ │ ├── public_key_sign.cc │ │ │ │ ├── public_key_sign.h │ │ │ │ ├── public_key_verify.cc │ │ │ │ ├── public_key_verify.h │ │ │ │ ├── python_file_object_adapter.cc │ │ │ │ ├── python_file_object_adapter.h │ │ │ │ ├── streaming_aead.cc │ │ │ │ ├── streaming_aead.h │ │ │ │ ├── tink_bindings.cc │ │ │ │ └── tink_exception.h │ │ │ ├── python_file_object_adapter.h │ │ │ ├── python_input_stream.cc │ │ │ ├── python_input_stream.h │ │ │ ├── python_input_stream_test.cc │ │ │ ├── python_output_stream.cc │ │ │ ├── python_output_stream.h │ │ │ ├── python_output_stream_test.cc │ │ │ └── test_util.h │ │ ├── cleartext_keyset_handle.py │ │ ├── cleartext_keyset_handle_test.py │ │ ├── core/ │ │ │ ├── BUILD.bazel │ │ │ ├── __init__.py │ │ │ ├── _crypto_format.py │ │ │ ├── _crypto_format_test.py │ │ │ ├── _key_manager.py │ │ │ ├── _primitive_set.py │ │ │ ├── _primitive_set_test.py │ │ │ ├── _primitive_wrapper.py │ │ │ ├── _registry.py │ │ │ ├── _registry_test.py │ │ │ └── _tink_error.py │ │ ├── daead/ │ │ │ ├── BUILD.bazel │ │ │ ├── __init__.py │ │ │ ├── _deterministic_aead.py │ │ │ ├── _deterministic_aead_key_manager.py │ │ │ ├── _deterministic_aead_key_manager_test.py │ │ │ ├── _deterministic_aead_key_templates.py │ │ │ ├── _deterministic_aead_key_templates_test.py │ │ │ ├── _deterministic_aead_wrapper.py │ │ │ └── _deterministic_aead_wrapper_test.py │ │ ├── hybrid/ │ │ │ ├── BUILD.bazel │ │ │ ├── __init__.py │ │ │ ├── _hybrid_decrypt.py │ │ │ ├── _hybrid_encrypt.py │ │ │ ├── _hybrid_key_manager.py │ │ │ ├── _hybrid_key_manager_test.py │ │ │ ├── _hybrid_key_templates.py │ │ │ ├── _hybrid_key_templates_test.py │ │ │ ├── _hybrid_wrapper.py │ │ │ └── _hybrid_wrapper_test.py │ │ ├── integration/ │ │ │ ├── __init__.py │ │ │ ├── awskms/ │ │ │ │ ├── BUILD.bazel │ │ │ │ ├── __init__.py │ │ │ │ ├── _aws_kms_client.py │ │ │ │ ├── _aws_kms_client_test.py │ │ │ │ └── _aws_kms_integration_test.py │ │ │ ├── gcpkms/ │ │ │ │ ├── BUILD.bazel │ │ │ │ ├── __init__.py │ │ │ │ ├── _gcp_kms_aead_test.py │ │ │ │ ├── _gcp_kms_client.py │ │ │ │ ├── _gcp_kms_client_integration_test.py │ │ │ │ ├── _gcp_kms_client_test.py │ │ │ │ └── _gcp_kms_integration_test.py │ │ │ └── hcvault/ │ │ │ ├── BUILD.bazel │ │ │ ├── __init__.py │ │ │ ├── _hcvault_kms_aead.py │ │ │ ├── _hcvault_kms_aead_test.py │ │ │ └── _hcvault_kms_integration_test.py │ │ ├── internal/ │ │ │ ├── BUILD.bazel │ │ │ ├── __init__.py │ │ │ ├── big_integer_util.py │ │ │ └── big_integer_util_test.py │ │ ├── jwt/ │ │ │ ├── BUILD.bazel │ │ │ ├── __init__.py │ │ │ ├── _json_util.py │ │ │ ├── _json_util_test.py │ │ │ ├── _jwk_set_converter.py │ │ │ ├── _jwk_set_converter_test.py │ │ │ ├── _jwt_error.py │ │ │ ├── _jwt_format.py │ │ │ ├── _jwt_format_test.py │ │ │ ├── _jwt_hmac_key_manager.py │ │ │ ├── _jwt_hmac_key_manager_test.py │ │ │ ├── _jwt_key_templates.py │ │ │ ├── _jwt_key_templates_test.py │ │ │ ├── _jwt_mac.py │ │ │ ├── _jwt_mac_wrapper.py │ │ │ ├── _jwt_mac_wrapper_test.py │ │ │ ├── _jwt_public_key_sign.py │ │ │ ├── _jwt_public_key_verify.py │ │ │ ├── _jwt_signature_key_manager.py │ │ │ ├── _jwt_signature_key_manager_test.py │ │ │ ├── _jwt_signature_wrappers.py │ │ │ ├── _jwt_signature_wrappers_test.py │ │ │ ├── _jwt_validator.py │ │ │ ├── _jwt_validator_test.py │ │ │ ├── _raw_jwt.py │ │ │ ├── _raw_jwt_test.py │ │ │ ├── _verified_jwt.py │ │ │ └── _verified_jwt_test.py │ │ ├── mac/ │ │ │ ├── BUILD.bazel │ │ │ ├── __init__.py │ │ │ ├── _mac.py │ │ │ ├── _mac_key_manager.py │ │ │ ├── _mac_key_manager_test.py │ │ │ ├── _mac_key_templates.py │ │ │ ├── _mac_key_templates_test.py │ │ │ ├── _mac_wrapper.py │ │ │ └── _mac_wrapper_test.py │ │ ├── prf/ │ │ │ ├── BUILD.bazel │ │ │ ├── __init__.py │ │ │ ├── _prf_key_manager.py │ │ │ ├── _prf_key_manager_test.py │ │ │ ├── _prf_key_templates.py │ │ │ ├── _prf_set.py │ │ │ ├── _prf_set_wrapper.py │ │ │ └── _prf_set_wrapper_test.py │ │ ├── proto/ │ │ │ ├── BUILD.bazel │ │ │ ├── __init__.py │ │ │ ├── aes_cmac.proto │ │ │ ├── aes_cmac_prf.proto │ │ │ ├── aes_ctr.proto │ │ │ ├── aes_ctr_hmac_aead.proto │ │ │ ├── aes_ctr_hmac_streaming.proto │ │ │ ├── aes_eax.proto │ │ │ ├── aes_gcm.proto │ │ │ ├── aes_gcm_hkdf_streaming.proto │ │ │ ├── aes_gcm_siv.proto │ │ │ ├── aes_siv.proto │ │ │ ├── chacha20_poly1305.proto │ │ │ ├── common.proto │ │ │ ├── config.proto │ │ │ ├── ecdsa.proto │ │ │ ├── ecies_aead_hkdf.proto │ │ │ ├── ed25519.proto │ │ │ ├── empty.proto │ │ │ ├── hkdf_prf.proto │ │ │ ├── hmac.proto │ │ │ ├── hmac_prf.proto │ │ │ ├── hpke.proto │ │ │ ├── jwt_ecdsa.proto │ │ │ ├── jwt_hmac.proto │ │ │ ├── jwt_rsa_ssa_pkcs1.proto │ │ │ ├── jwt_rsa_ssa_pss.proto │ │ │ ├── kms_aead.proto │ │ │ ├── kms_envelope.proto │ │ │ ├── prf_based_deriver.proto │ │ │ ├── rsa_ssa_pkcs1.proto │ │ │ ├── rsa_ssa_pss.proto │ │ │ ├── test_proto.proto │ │ │ ├── tink.proto │ │ │ └── xchacha20_poly1305.proto │ │ ├── secret_key_access.py │ │ ├── secret_key_access_import_test.py │ │ ├── secret_key_access_test.py │ │ ├── signature/ │ │ │ ├── BUILD.bazel │ │ │ ├── __init__.py │ │ │ ├── _public_key_sign.py │ │ │ ├── _public_key_verify.py │ │ │ ├── _signature_key_manager.py │ │ │ ├── _signature_key_manager_test.py │ │ │ ├── _signature_key_templates.py │ │ │ ├── _signature_wrapper.py │ │ │ └── _signature_wrapper_test.py │ │ ├── streaming_aead/ │ │ │ ├── BUILD.bazel │ │ │ ├── __init__.py │ │ │ ├── _decrypting_stream.py │ │ │ ├── _decrypting_stream_test.py │ │ │ ├── _encrypting_stream.py │ │ │ ├── _encrypting_stream_test.py │ │ │ ├── _file_object_adapter.py │ │ │ ├── _file_object_adapter_test.py │ │ │ ├── _pybind11_python_file_object_adapter_test.py │ │ │ ├── _raw_streaming_aead.py │ │ │ ├── _rewindable_input_stream.py │ │ │ ├── _rewindable_input_stream_test.py │ │ │ ├── _streaming_aead.py │ │ │ ├── _streaming_aead_key_manager.py │ │ │ ├── _streaming_aead_key_manager_test.py │ │ │ ├── _streaming_aead_key_templates.py │ │ │ ├── _streaming_aead_key_templates_test.py │ │ │ ├── _streaming_aead_test.py │ │ │ ├── _streaming_aead_wrapper.py │ │ │ └── _streaming_aead_wrapper_test.py │ │ ├── testing/ │ │ │ ├── BUILD.bazel │ │ │ ├── __init__.py │ │ │ ├── bytes_io.py │ │ │ ├── bytes_io_test.py │ │ │ ├── fake_kms.py │ │ │ ├── fake_kms_test.py │ │ │ ├── helper.py │ │ │ ├── helper_test.py │ │ │ ├── keyset_builder.py │ │ │ └── keyset_builder_test.py │ │ ├── tink_config.py │ │ └── tink_config_test.py │ ├── tink_py_deps.bzl │ ├── tink_py_deps_init.bzl │ └── tools/ │ ├── BUILD.bazel │ └── distribution/ │ ├── README.md │ ├── build_linux_binary_wheels.sh │ ├── create_release.sh │ ├── requirements.in │ ├── requirements.txt │ └── test_linux_binary_wheels.sh ├── testdata/ │ ├── BUILD.bazel │ ├── aws/ │ │ ├── BUILD.bazel │ │ ├── README.md │ │ ├── access_keys_bad.csv │ │ ├── credentials.cred │ │ ├── credentials.csv │ │ ├── credentials.ini │ │ ├── credentials_bad.csv │ │ ├── credentials_bad.ini │ │ ├── key_arn.txt │ │ └── key_arn_bad.txt │ ├── gcp/ │ │ ├── BUILD.bazel │ │ ├── README.md │ │ ├── credential.json │ │ ├── credential_bad.json │ │ ├── key_name.txt │ │ └── key_name_bad.txt │ ├── keysets/ │ │ └── BUILD.bazel │ └── testvectors/ │ ├── BUILD.bazel │ └── hpke_boringssl.json ├── testing/ │ └── cross_language/ │ └── testdata/ │ ├── aws/ │ │ ├── BUILD.bazel │ │ ├── README.md │ │ ├── access_keys_bad.csv │ │ ├── credentials.cred │ │ ├── credentials.csv │ │ ├── credentials.ini │ │ ├── credentials_bad.csv │ │ ├── credentials_bad.ini │ │ ├── key_arn.txt │ │ └── key_arn_bad.txt │ └── gcp/ │ ├── BUILD.bazel │ ├── README.md │ ├── credential.json │ ├── credential_bad.json │ ├── key_name.txt │ └── key_name_bad.txt ├── tinkey.rb └── tools/ ├── .bazelrc ├── .bazelversion ├── BUILD.bazel ├── WORKSPACE ├── build_defs/ │ └── BUILD.bazel ├── coverage.sh ├── release_tinkey.sh ├── requirements.txt └── tinkey/ ├── BUILD.bazel ├── README.md └── src/ ├── main/ │ └── java/ │ └── com/ │ └── google/ │ └── crypto/ │ └── tink/ │ └── tinkey/ │ ├── AddKeyCommand.java │ ├── AddRotateOptions.java │ ├── BUILD.bazel │ ├── Command.java │ ├── ConvertKeysetCommand.java │ ├── ConvertKeysetOptions.java │ ├── CreateKeysetCommand.java │ ├── CreateKeysetOptions.java │ ├── CreatePublicKeysetCommand.java │ ├── DeleteKeyCommand.java │ ├── DestroyKeyCommand.java │ ├── DisableKeyCommand.java │ ├── EnableKeyCommand.java │ ├── HelpCommand.java │ ├── InOptions.java │ ├── InputStreamHandler.java │ ├── KeyIdHandler.java │ ├── KeyIdOptions.java │ ├── KeyTemplateHandler.java │ ├── KmsClientsFactory.java │ ├── ListKeyTemplatesCommand.java │ ├── ListKeysetCommand.java │ ├── OutOptions.java │ ├── OutputStreamHandler.java │ ├── PromoteKeyCommand.java │ ├── RotateKeysetCommand.java │ ├── Tinkey.java │ ├── TinkeyCommands.java │ ├── TinkeyKeyTemplates.java │ ├── TinkeyTestKmsClient.java │ └── TinkeyUtil.java └── test/ └── java/ └── com/ └── google/ └── crypto/ └── tink/ └── tinkey/ ├── AddKeyCommandTest.java ├── BUILD.bazel ├── ConvertKeysetCommandTest.java ├── CreateKeysetCommandTest.java ├── CreatePublicKeysetCommandTest.java ├── KmsClientsFactoryTest.java ├── RotateKeysetCommandTest.java └── TinkeyTestKmsClientTest.java ================================================ FILE CONTENTS ================================================ ================================================ FILE: .bazelversion ================================================ 6.4.0 ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.md ================================================ --- name: Bug report about: Create a report to help us improve Tink --- > **NOTE**: **Tink moved to github.com/tink-crypto!** > > We split Tink into multiple focused repositories. > Please create this issue in the appropriate repository in > github.com/tink-crypto instead: > > * [Tink Java](https://github.com/tink-crypto/tink-java/issues/new?template=bug_report.md) > * [Tink Java AWS KMS extension](https://github.com/tink-crypto/tink-java-awskms/issues/new?template=bug_report.md) > * [Tink Java Google Cloud KMS extension](https://github.com/tink-crypto/tink-java-gcpkms/issues/new?template=bug_report.md) > * [Tink Java apps extension](https://github.com/tink-crypto/tink-java-apps/issues/new?template=bug_report.md) > * [Tink C++](https://github.com/tink-crypto/tink-cc/issues/new?template=bug_report.md) > * [Tink C++ AWS KMS extension](https://github.com/tink-crypto/tink-cc-awskms/issues/new?template=bug_report.md) > * [Tink C++ Google Cloud KMS extension](https://github.com/tink-crypto/tink-cc-gcpkms/issues/new?template=bug_report.md) > * [Tink Go](https://github.com/tink-crypto/tink-go/issues/new?template=bug_report.md) > * [Tink Go AWS KMS extension](https://github.com/tink-crypto/tink-go-awskms/issues/new?template=bug_report.md) > * [Tink Go Google Cloud KMS extension](https://github.com/tink-crypto/tink-go-gcpkms/issues/new?template=bug_report.md) > * [Tink Go HashiCorp Vault KMS extension](https://github.com/tink-crypto/tink-go-hcvault/issues/new?template=bug_report.md) > * [Tink Objc](https://github.com/tink-crypto/tink-objc/issues/new?template=bug_report.md) > * [Tink Python](https://github.com/tink-crypto/tink-py/issues/new?template=bug_report.md) > * [Tink Tinkey](https://github.com/tink-crypto/tink-tinkey/issues/new?template=bug_report.md) ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: false ================================================ FILE: .github/ISSUE_TEMPLATE/feature_request.md ================================================ --- name: Feature request about: Suggest an idea for Tink --- > **NOTE**: **Tink moved to github.com/tink-crypto!** > > We split Tink into multiple focused repositories. > Please create this issue in the appropriate repository in > github.com/tink-crypto instead: > > * [Tink Java](https://github.com/tink-crypto/tink-java/issues/new?template=feature_request.md) > * [Tink Java AWS KMS extension](https://github.com/tink-crypto/tink-java-awskms/issues/new?template=feature_request.md) > * [Tink Java Google Cloud KMS extension](https://github.com/tink-crypto/tink-java-gcpkms/issues/new?template=feature_request.md) > * [Tink Java apps extension](https://github.com/tink-crypto/tink-java-apps/issues/new?template=feature_request.md) > * [Tink C++](https://github.com/tink-crypto/tink-cc/issues/new?template=feature_request.md) > * [Tink C++ AWS KMS extension](https://github.com/tink-crypto/tink-cc-awskms/issues/new?template=feature_request.md) > * [Tink C++ Google Cloud KMS extension](https://github.com/tink-crypto/tink-cc-gcpkms/issues/new?template=feature_request.md) > * [Tink Go](https://github.com/tink-crypto/tink-go/issues/new?template=feature_request.md) > * [Tink Go AWS KMS extension](https://github.com/tink-crypto/tink-go-awskms/issues/new?template=feature_request.md) > * [Tink Go Google Cloud KMS extension](https://github.com/tink-crypto/tink-go-gcpkms/issues/new?template=feature_request.md) > * [Tink Go HashiCorp Vault KMS extension](https://github.com/tink-crypto/tink-go-hcvault/issues/new?template=feature_request.md) > * [Tink Objc](https://github.com/tink-crypto/tink-objc/issues/new?template=feature_request.md) > * [Tink Python](https://github.com/tink-crypto/tink-py/issues/new?template=feature_request.md) > * [Tink Tinkey](https://github.com/tink-crypto/tink-tinkey/issues/new?template=feature_request.md) ================================================ FILE: .github/workflows/codeql-analysis.yml ================================================ # For most projects, this workflow file will not need changing; you simply need # to commit it to your repository. # # You may wish to alter this file to override the set of languages analyzed, # or to provide custom queries or build logic. name: "CodeQL" on: push: branches: [master, 1.5] pull_request: # The branches below must be a subset of the branches above branches: [master, 1.5] schedule: - cron: '0 13 * * 0' jobs: analyze: name: Analyze runs-on: ubuntu-latest strategy: fail-fast: false matrix: # Override automatic language detection by changing the below list # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] # # TODO: Re-enable Java with a Bazel build solution. language: ['cpp', 'go', 'python', 'javascript'] # Learn more... # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection steps: - name: Checkout repository uses: actions/checkout@v3 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. fetch-depth: 2 # If this run was triggered by a pull request event, then checkout # the head of the pull request instead of the merge commit. - run: git checkout HEAD^2 if: ${{ github.event_name == 'pull_request' }} # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. # By default, queries listed here will override any specified in a config file. # Prefix the list here with "+" to use these queries and those in the config file. # queries: ./path/to/local/query, your-org/your-repo/queries@main # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild uses: github/codeql-action/autobuild@v2 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines # and modify them (or add more) to build your code if your project # uses a compiled language #- run: | # make bootstrap # make release - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 ================================================ FILE: .gitignore ================================================ .DS_Store bazel-* *.swp *~ **/target .idea *.iml *.tulsiconf-user tulsi-* tulsigen-* *.iml .gradle **/local.properties **/build/** .externalNativeBuild node_modules ================================================ FILE: BUILD.bazel ================================================ # Description: # Tink (https://github.com/google/tink) is a small crypto library that # provides a safe, simple, agile and fast way to accomplish some common # crypto tasks. package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) exports_files([ "LICENSE", "README.md", "__init__.py", ]) filegroup( name = "tink_version", srcs = ["tink_version.bzl"], visibility = ["//visibility:public"], ) ================================================ FILE: CMakeLists.txt ================================================ cmake_minimum_required(VERSION 3.13) project(Tink VERSION 2.1.2 LANGUAGES CXX) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") option(TINK_BUILD_TESTS "Build Tink tests" OFF) option(TINK_USE_SYSTEM_OPENSSL "Build Tink linking to OpenSSL installed in the system" OFF) option(TINK_USE_INSTALLED_ABSEIL "Build Tink linking to Abseil installed in the system" OFF) option(TINK_USE_INSTALLED_GOOGLETEST "Build Tink linking to GTest installed in the system" OFF) option(TINK_USE_INSTALLED_PROTOBUF "Build Tink linking to Protobuf installed in the system" OFF) option(USE_ONLY_FIPS "Enables the FIPS only mode in Tink" OFF) set(CPACK_GENERATOR TGZ) set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION}) include(CPack) include(TinkWorkspace) include(TinkBuildRules) include(TinkUtil) # Bazel rewrites import paths so that "cc/example/foo.h" can be included as # "tink/example/foo.h". The following lines simulate this behaviour by creating # a symlink to cc/ called tink/, and placing it in a separate subdirectory, # which is then specified as a global include path. # # It's important to create a separate directory and not just drop the link in # CMAKE_CURRENT_BINARY_DIR, since adding that to the include paths will # make the whole contents of that directory visible to the compiled files, # which may result in undeclared dependencies that nevertheless happen to work. # set(TINK_INCLUDE_ALIAS_DIR "${CMAKE_CURRENT_BINARY_DIR}/__include_alias") add_directory_alias( "${CMAKE_CURRENT_SOURCE_DIR}/cc" "${TINK_INCLUDE_ALIAS_DIR}/tink") list(APPEND TINK_INCLUDE_DIRS "${TINK_INCLUDE_ALIAS_DIR}") add_subdirectory(cc) add_subdirectory(proto) ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ # Tink > **NOTE**: **Tink moved to github.com/tink-crypto and this repo is no longer > active!** > > As planned, we have split Tink into > [multiple GitHub repositories][split_repo_roadmap_url] that are hosted at > [github.com/tink-crypto](https://github.com/tink-crypto). As a consequence, we > made this repository read-only and it is not going to be maintained moving > forward. > *A multi-language, cross-platform library that provides cryptographic APIs that are secure, easy to use correctly, and hard(er) to misuse. See also: https://developers.google.com/tink*. [split_repo_roadmap_url]: https://developers.google.com/tink/roadmap#splitting_tink_into_multiple_github_repositories [tink_mailing_list_url]: https://groups.google.com/forum/#!forum/tink-users ## Index 1. [Introduction](#introduction) 2. [Current status](#current-status) 3. [Getting started](#getting-started) 4. [Learn more](#learn-more) 5. [Contact and mailing list](#contact-and-mailing-list) 6. [Maintainers](#maintainers) ## Introduction Using crypto in your application [shouldn't have to][devs_are_users_too_slides] feel like juggling chainsaws in the dark. Tink is a crypto library written by a group of cryptographers and security engineers at Google. It was born out of our extensive experience working with Google's product teams, [fixing weaknesses in implementations](https://github.com/google/wycheproof), and providing simple APIs that can be used safely without needing a crypto background. Tink provides secure APIs that are easy to use correctly and hard(er) to misuse. It reduces common crypto pitfalls with user-centered design, careful implementation and code reviews, and extensive testing. At Google, Tink is one of the standard crypto libraries, and has been deployed in hundreds of products and systems. To get a quick overview of Tink design please take a look at [slides][tink_talk_slides] from [a talk about Tink][tink_talk_recording] presented at [Real World Crypto 2019](https://rwc.iacr.org/2019/). [devs_are_users_too_slides]: https://www.usenix.org/sites/default/files/conference/protected-files/hotsec15_slides_green.pdf [tink_talk_slides]: docs/Tink-a_cryptographic_library--RealWorldCrypto2019.pdf [tink_talk_recording]: https://www.youtube.com/watch?v=pqev9r3rUJs&t=9665 ## Current status [Java/Android](docs/JAVA-HOWTO.md), [C++](docs/CPP-HOWTO.md), [Obj-C](docs/OBJC-HOWTO.md), [Go](docs/GOLANG-HOWTO.md), and [Python](docs/PYTHON-HOWTO.md) are field tested and ready for production. The latest version is [1.7.0](https://github.com/google/tink/releases/tag/v1.7.0), released on 2022-08-09. Javascript/Typescript is in an alpha state and should only be used for testing. Please see the intent to remove statement [here](https://github.com/google/tink/issues/689). **`Ubuntu`** | **`macOS`** ----------------------------------- | --------------------------------- [![Kokoro Ubuntu][ubuntu_badge]](#) | [![Kokoro macOS][macos_badge]](#) [ubuntu_badge]: https://storage.googleapis.com/tink-kokoro-build-badges/tink-ubuntu.png [macos_badge]: https://storage.googleapis.com/tink-kokoro-build-badges/tink-macos.png ## Getting started Documentation for the project is located at https://developers.google.com/tink. Currently, it details a variety of common usage scenarios and covers the Java and Python implementations. The site will be populated with more content over time. Alternatively, you can look at all of the [`examples`] which demonstrate performing simple tasks using Tink in a variety of languages. [`examples`]: https://github.com/google/tink/tree/master/examples * Python ```sh pip3 install tink ``` * Golang ```sh go get github.com/google/tink/go/... ``` * Java ```xml com.google.crypto.tink tink 1.7.0 ``` * Android ``` dependencies { implementation 'com.google.crypto.tink:tink-android:1.7.0' } ``` * Objective-C/iOS ```sh cd /path/to/your/Xcode project/ pod init pod 'Tink', '1.7.0' pod install ``` ## Learn more * [Java HOW-TO](docs/JAVA-HOWTO.md) * [C++ HOW-TO](docs/CPP-HOWTO.md) * [Obj-C HOW-TO](docs/OBJC-HOWTO.md) * [Go HOW-TO](docs/GOLANG-HOWTO.md) * [Python HOW-TO](docs/PYTHON-HOWTO.md) * [Security and Usability Design Goals](docs/SECURITY-USABILITY.md) * [Supported Crypto Primitives](docs/PRIMITIVES.md) * [Key Management](docs/KEY-MANAGEMENT.md) * [Managing keys with Tinkey](docs/TINKEY.md) * [Known Issues](docs/KNOWN-ISSUES.md) ## Community-driven ports Out of the box Tink supports a wide range of languages, but it still doesn't support every language. Fortunately, some users like Tink so much that they've ported it to their favorite languages! Below you can find notable ports. **WARNING** While we usually review these ports, until further notice, we do not maintain them and have no plan to support them in the foreseeable future. * [Clojure](https://github.com/perkss/tinklj) ## Contact and mailing list If you want to contribute, please read [CONTRIBUTING](docs/CONTRIBUTING.md) and send us pull requests. You can also report bugs or file feature requests. If you'd like to talk to the developers or get notified about major product updates, you may want to subscribe to our [mailing list][tink_mailing_list_url]. ## Maintainers Tink is maintained by (A-Z): - Moreno Ambrosin - Taymon Beal - Daniel Bleichenbacher - William Conner - Thai Duong - Thomas Holenstein - Stefan Kölbl - Charles Lee - Cindy Lin - Fernando Lobato Meeser - Atul Luykx - Rafael Misoczki - Sophie Schmieg - Laurent Simon - Elizaveta Tretiakova - Jürg Wullschleger Alumni: - Haris Andrianakis - Tanuj Dhir - Quan Nguyen - Bartosz Przydatek - Enzo Puig - Veronika Slívová - Paula Vidas - Cathie Yun - Federico Zalcberg ================================================ FILE: cc/.bazelignore ================================================ # Ignore AWS-KMS and Cloud KMS integrations which are in thier own WORKSPACEs. integration/awskms integration/gcpkms # Ignore examples. examples ================================================ FILE: cc/.bazelrc ================================================ # Enables automatic per-platform configs. common --enable_platform_specific_config # Minumum C++ version. Override it building this project with # `bazel build --cxxopt='-std=c++' --host_cxxopt='c++' ...` # (Both -std and --host_cxxopt must be set to force the desired version.) build:linux --cxxopt='-std=c++14' --host_cxxopt='-std=c++14' build:macos --cxxopt='-std=c++14' --host_cxxopt='-std=c++14' build:windows --cxxopt='/std:c++14' --host_cxxopt='/std:c++14' ================================================ FILE: cc/.bazelversion ================================================ 6.4.0 ================================================ FILE: cc/BUILD.bazel ================================================ load("//:template_rule.bzl", "template_rule") load("//:tink_version.bzl", "TINK_VERSION_LABEL") package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) # public libraries alias( name = "secret_key_access_testonly", testonly = 1, actual = ":secret_key_access", visibility = ["//visibility:public"], ) cc_library( name = "tink_cc", hdrs = [ "aead.h", "aead_config.h", "aead_factory.h", "aead_key_templates.h", "binary_keyset_reader.h", "binary_keyset_writer.h", "deterministic_aead.h", "deterministic_aead_config.h", "deterministic_aead_factory.h", "deterministic_aead_key_templates.h", "hybrid_config.h", "hybrid_decrypt.h", "hybrid_decrypt_factory.h", "hybrid_encrypt.h", "hybrid_encrypt_factory.h", "hybrid_key_templates.h", "input_stream.h", "json_keyset_reader.h", "json_keyset_writer.h", "key_manager.h", "keyset_handle.h", "keyset_manager.h", "keyset_reader.h", "keyset_writer.h", "kms_client.h", "mac.h", "mac_config.h", "mac_factory.h", "mac_key_templates.h", "output_stream.h", "output_stream_with_result.h", "public_key_sign.h", "public_key_sign_factory.h", "public_key_verify.h", "public_key_verify_factory.h", "random_access_stream.h", "registry.h", "signature_config.h", "signature_key_templates.h", "streaming_aead.h", "streaming_aead_config.h", "streaming_aead_key_templates.h", "streaming_mac.h", "tink_config.h", "version.h", ], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ ":aead", ":binary_keyset_reader", ":binary_keyset_writer", ":deterministic_aead", ":hybrid_decrypt", ":hybrid_encrypt", ":input_stream", ":json_keyset_reader", ":json_keyset_writer", ":key", ":key_manager", ":keyset_handle", ":keyset_manager", ":keyset_reader", ":keyset_writer", ":kms_client", ":mac", ":output_stream", ":output_stream_with_result", ":primitive_set", ":public_key_sign", ":public_key_verify", ":random_access_stream", ":registry", ":streaming_aead", ":streaming_mac", ":version", "//aead:aead_config", "//aead:aead_factory", "//aead:aead_key_templates", "//config:tink_config", "//daead:deterministic_aead_config", "//daead:deterministic_aead_factory", "//daead:deterministic_aead_key_templates", "//hybrid:hybrid_config", "//hybrid:hybrid_decrypt_factory", "//hybrid:hybrid_encrypt_factory", "//hybrid:hybrid_key_templates", "//internal:key_info", "//internal:registry_impl", "//mac:mac_config", "//mac:mac_factory", "//mac:mac_key_templates", "//proto:config_cc_proto", "//proto:tink_cc_proto", "//signature:public_key_sign_factory", "//signature:public_key_verify_factory", "//signature:signature_config", "//signature:signature_key_templates", "//streamingaead:streaming_aead_config", "//streamingaead:streaming_aead_key_templates", "//util:buffer", "//util:errors", "//util:protobuf_helper", "//util:secret_proto", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/synchronization", ], ) cc_library( name = "input_stream", hdrs = ["input_stream.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ "//util:status", "//util:statusor", ], ) cc_library( name = "output_stream", hdrs = ["output_stream.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ "//util:status", "//util:statusor", ], ) cc_library( name = "random_access_stream", hdrs = ["random_access_stream.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ "//util:buffer", "//util:status", "//util:statusor", ], ) cc_library( name = "output_stream_with_result", hdrs = ["output_stream_with_result.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ ":output_stream", "//util:status", "//util:statusor", "@com_google_absl//absl/status", ], ) cc_library( name = "aead", hdrs = ["aead.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ "//util:statusor", "@com_google_absl//absl/strings", ], ) cc_library( name = "deterministic_aead", hdrs = ["deterministic_aead.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ "//util:statusor", "@com_google_absl//absl/strings", ], ) cc_library( name = "streaming_aead", hdrs = ["streaming_aead.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ ":input_stream", ":output_stream", ":random_access_stream", "//util:statusor", "@com_google_absl//absl/strings", ], ) cc_library( name = "streaming_mac", hdrs = ["streaming_mac.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ ":output_stream_with_result", "//util:status", "//util:statusor", "@com_google_absl//absl/strings", ], ) cc_library( name = "chunked_mac", hdrs = ["chunked_mac.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ "//util:status", "//util:statusor", "@com_google_absl//absl/strings", ], ) cc_library( name = "hybrid_decrypt", hdrs = ["hybrid_decrypt.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ "//util:statusor", "@com_google_absl//absl/strings", ], ) cc_library( name = "hybrid_encrypt", hdrs = ["hybrid_encrypt.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ "//util:statusor", "@com_google_absl//absl/strings", ], ) cc_library( name = "mac", hdrs = ["mac.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ "//util:status", "//util:statusor", "@com_google_absl//absl/strings", ], ) cc_library( name = "public_key_sign", hdrs = ["public_key_sign.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ "//util:statusor", "@com_google_absl//absl/strings", ], ) cc_library( name = "public_key_verify", hdrs = ["public_key_verify.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ "//util:status", "@com_google_absl//absl/strings", ], ) cc_library( name = "keyset_reader", hdrs = ["keyset_reader.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ "//proto:tink_cc_proto", "//util:statusor", ], ) cc_library( name = "keyset_writer", hdrs = ["keyset_writer.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ "//proto:tink_cc_proto", "//util:status", ], ) cc_library( name = "binary_keyset_reader", srcs = ["core/binary_keyset_reader.cc"], hdrs = ["binary_keyset_reader.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ ":keyset_reader", "//proto:tink_cc_proto", "//util:errors", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "binary_keyset_writer", srcs = ["core/binary_keyset_writer.cc"], hdrs = ["binary_keyset_writer.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ ":keyset_writer", "//proto:tink_cc_proto", "//util:protobuf_helper", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "json_keyset_reader", srcs = ["core/json_keyset_reader.cc"], hdrs = ["json_keyset_reader.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ ":keyset_reader", "//proto:tink_cc_proto", "//util:enums", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@rapidjson", ], ) cc_library( name = "json_keyset_writer", srcs = ["core/json_keyset_writer.cc"], hdrs = ["json_keyset_writer.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ ":keyset_writer", "//proto:tink_cc_proto", "//util:enums", "//util:errors", "//util:protobuf_helper", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@rapidjson", ], ) cc_library( name = "crypto_format", srcs = ["core/crypto_format.cc"], hdrs = ["crypto_format.h"], include_prefix = "tink", deps = [ "//proto:tink_cc_proto", "//util:errors", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "primitive_set", srcs = ["primitive_set.h"], hdrs = ["primitive_set.h"], include_prefix = "tink", deps = [ ":crypto_format", "//proto:tink_cc_proto", "//util:errors", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/synchronization", ], ) cc_library( name = "primitive_wrapper", hdrs = ["primitive_wrapper.h"], include_prefix = "tink", deps = [ ":primitive_set", "//util:statusor", ], ) cc_library( name = "registry", hdrs = ["registry.h"], include_prefix = "tink", deps = [ ":key_manager", ":primitive_set", "//internal:registry_impl", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/strings", ], ) template_rule( name = "version_h", src = "version.h.templ", out = "version.h", substitutions = { "@TINK_VERSION_LABEL@": "%s" % TINK_VERSION_LABEL, }, ) cc_library( name = "version", srcs = ["core/version.cc"], hdrs = [":version_h"], include_prefix = "tink", visibility = ["//visibility:public"], ) cc_library( name = "keyset_handle", srcs = ["core/keyset_handle.cc"], hdrs = ["keyset_handle.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ ":aead", ":configuration", ":insecure_secret_key_access", ":key", ":key_gen_configuration", ":key_manager", ":key_status", ":keyset_reader", ":keyset_writer", ":primitive_set", ":registry", ":restricted_data", ":secret_key_access_token", "//config:global_registry", "//internal:configuration_impl", "//internal:key_gen_configuration_impl", "//internal:key_info", "//internal:key_status_util", "//internal:key_type_info_store", "//internal:keyset_wrapper", "//internal:keyset_wrapper_store", "//internal:mutable_serialization_registry", "//internal:proto_key_serialization", "//internal:registry_impl", "//internal:util", "//proto:tink_cc_proto", "//util:errors", "//util:keyset_util", "//util:secret_data", "//util:secret_proto", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/log:check", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "keyset_handle_builder", srcs = ["core/keyset_handle_builder.cc"], hdrs = ["keyset_handle_builder.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ ":key", ":key_status", ":keyset_handle", ":parameters", "//internal:keyset_handle_builder_entry", "//proto:tink_cc_proto", "//subtle:random", "//util:secret_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/log:check", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:str_format", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "cleartext_keyset_handle", srcs = ["core/cleartext_keyset_handle.cc"], hdrs = ["cleartext_keyset_handle.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ ":keyset_handle", ":keyset_reader", ":keyset_writer", "//proto:tink_cc_proto", "//util:errors", "//util:secret_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", ], ) cc_library( name = "key_manager", srcs = ["core/key_manager.cc"], hdrs = ["key_manager.h"], include_prefix = "tink", deps = [ "//proto:tink_cc_proto", "//util:errors", "//util:protobuf_helper", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/strings", ], ) cc_library( name = "keyset_manager", srcs = ["core/keyset_manager.cc"], hdrs = ["keyset_manager.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ ":key_gen_configuration", ":keyset_handle", "//internal:key_gen_configuration_impl", "//proto:tink_cc_proto", "//util:enums", "//util:errors", "//util:secret_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/synchronization", ], ) cc_library( name = "kms_client", hdrs = ["kms_client.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ ":aead", "//util:statusor", "@com_google_absl//absl/strings", ], ) cc_library( name = "kms_clients", srcs = ["core/kms_clients.cc"], hdrs = ["kms_clients.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ ":kms_client", "//util:errors", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/synchronization", ], ) cc_library( name = "core/template_util", hdrs = ["core/template_util.h"], include_prefix = "tink", deps = ["@com_google_absl//absl/meta:type_traits"], ) cc_library( name = "core/key_type_manager", hdrs = ["core/key_type_manager.h"], include_prefix = "tink", deps = [ ":core/template_util", ":input_stream", "//internal:fips_utils", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "core/key_manager_impl", hdrs = ["core/key_manager_impl.h"], include_prefix = "tink", deps = [ ":core/key_type_manager", ":core/template_util", ":input_stream", ":key_manager", "//proto:tink_cc_proto", "//util:constants", "//util:errors", "//util:secret_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/base", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "core/private_key_type_manager", hdrs = ["core/private_key_type_manager.h"], include_prefix = "tink", deps = [ ":core/key_type_manager", ":core/template_util", "//util:statusor", ], ) cc_library( name = "core/private_key_manager_impl", hdrs = ["core/private_key_manager_impl.h"], include_prefix = "tink", deps = [ ":core/key_manager_impl", ":core/key_type_manager", ":core/private_key_type_manager", ":key_manager", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "key_access", hdrs = ["key_access.h"], include_prefix = "tink", ) cc_library( name = "secret_key_access", hdrs = ["secret_key_access.h"], include_prefix = "tink", deps = [":key_access"], ) cc_library( name = "parameters", hdrs = ["parameters.h"], include_prefix = "tink", ) cc_library( name = "key", hdrs = ["key.h"], include_prefix = "tink", deps = [ ":parameters", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "private_key", hdrs = ["private_key.h"], include_prefix = "tink", deps = [":key"], ) cc_library( name = "partial_key_access_token", hdrs = ["partial_key_access_token.h"], include_prefix = "tink", ) cc_library( name = "partial_key_access", hdrs = ["partial_key_access.h"], include_prefix = "tink", deps = [":partial_key_access_token"], ) cc_library( name = "secret_key_access_token", hdrs = ["secret_key_access_token.h"], include_prefix = "tink", ) cc_library( name = "insecure_secret_key_access", hdrs = ["insecure_secret_key_access.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [":secret_key_access_token"], ) cc_library( name = "restricted_data", srcs = ["core/restricted_data.cc"], hdrs = ["restricted_data.h"], include_prefix = "tink", deps = [ ":secret_key_access_token", "//subtle:random", "//util:secret_data", "@boringssl//:crypto", "@com_google_absl//absl/log:check", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "key_status", hdrs = ["key_status.h"], include_prefix = "tink", visibility = ["//visibility:public"], ) cc_library( name = "configuration", hdrs = ["configuration.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ "//internal:key_type_info_store", "//internal:keyset_wrapper_store", ], ) cc_library( name = "key_gen_configuration", hdrs = ["key_gen_configuration.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = ["//internal:key_type_info_store"], ) cc_library( name = "big_integer", srcs = ["core/big_integer.cc"], hdrs = ["big_integer.h"], include_prefix = "tink", deps = [ "@boringssl//:crypto", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "restricted_big_integer", srcs = ["core/restricted_big_integer.cc"], hdrs = ["restricted_big_integer.h"], include_prefix = "tink", deps = [ ":secret_key_access_token", "//util:secret_data", "@boringssl//:crypto", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "ec_point", hdrs = ["ec_point.h"], include_prefix = "tink", deps = [":big_integer"], ) # tests cc_test( name = "version_test", size = "small", srcs = ["core/version_test.cc"], deps = [ ":version", "//internal:util", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "binary_keyset_reader_test", size = "small", srcs = ["core/binary_keyset_reader_test.cc"], deps = [ ":binary_keyset_reader", "//proto:tink_cc_proto", "//util:test_util", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "binary_keyset_writer_test", size = "small", srcs = ["core/binary_keyset_writer_test.cc"], deps = [ ":binary_keyset_writer", ":insecure_secret_key_access", ":proto_keyset_format", ":tink_cc", "//aead:aead_config", "//config:global_registry", "//proto:tink_cc_proto", "//util:secret_data", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "json_keyset_reader_test", size = "small", srcs = ["core/json_keyset_reader_test.cc"], deps = [ ":json_keyset_reader", ":keyset_reader", "//proto:aes_eax_cc_proto", "//proto:aes_gcm_cc_proto", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "json_keyset_writer_test", size = "small", srcs = ["core/json_keyset_writer_test.cc"], deps = [ ":json_keyset_reader", ":json_keyset_writer", "//proto:aes_eax_cc_proto", "//proto:aes_gcm_cc_proto", "//proto:tink_cc_proto", "//util:protobuf_helper", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", "@rapidjson", ], ) cc_test( name = "crypto_format_test", size = "small", srcs = ["core/crypto_format_test.cc"], deps = [ ":crypto_format", "//proto:tink_cc_proto", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "keyset_handle_test", size = "small", srcs = ["core/keyset_handle_test.cc"], deps = [ ":binary_keyset_reader", ":cleartext_keyset_handle", ":configuration", ":core/key_manager_impl", ":core/key_type_manager", ":core/template_util", ":json_keyset_reader", ":json_keyset_writer", ":key_gen_configuration", ":key_status", ":keyset_handle", ":primitive_set", ":primitive_wrapper", ":tink_cc", "//aead:aead_key_templates", "//aead:aead_wrapper", "//aead:aes_gcm_key_manager", "//config:fips_140_2", "//config:global_registry", "//config:key_gen_fips_140_2", "//config:tink_config", "//internal:configuration_impl", "//internal:fips_utils", "//internal:key_gen_configuration_impl", "//proto:aes_gcm_cc_proto", "//proto:aes_gcm_siv_cc_proto", "//proto:ecdsa_cc_proto", "//proto:tink_cc_proto", "//signature:ecdsa_sign_key_manager", "//signature:ecdsa_verify_key_manager", "//signature:signature_key_templates", "//subtle:random", "//util:status", "//util:statusor", "//util:test_keyset_handle", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "keyset_handle_builder_test", srcs = ["core/keyset_handle_builder_test.cc"], deps = [ ":aead", ":core/key_type_manager", ":core/template_util", ":input_stream", ":insecure_secret_key_access", ":key_status", ":keyset_handle", ":keyset_handle_builder", ":mac", ":partial_key_access", ":primitive_set", ":primitive_wrapper", ":registry", ":restricted_data", "//aead:aes_gcm_parameters", "//config:global_registry", "//config:tink_config", "//internal:legacy_proto_key", "//internal:legacy_proto_parameters", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//mac:aes_cmac_key", "//mac:aes_cmac_parameters", "//mac:mac_key_templates", "//proto:aes_cmac_cc_proto", "//proto:aes_gcm_cc_proto", "//proto:tink_cc_proto", "//subtle:random", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "key_manager_test", size = "small", srcs = ["core/key_manager_test.cc"], deps = [ ":key_manager", "//proto:empty_cc_proto", "//util:status", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "keyset_manager_test", size = "small", srcs = ["core/keyset_manager_test.cc"], deps = [ ":keyset_handle", ":keyset_manager", "//aead:aead_config", "//aead:aes_gcm_key_manager", "//proto:aes_gcm_cc_proto", "//proto:tink_cc_proto", "//util:test_keyset_handle", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "cleartext_keyset_handle_test", size = "small", srcs = ["core/cleartext_keyset_handle_test.cc"], deps = [ ":binary_keyset_reader", ":cleartext_keyset_handle", ":keyset_handle", "//proto:tink_cc_proto", "//util:status", "//util:test_keyset_handle", "//util:test_util", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "primitive_set_test", size = "small", srcs = ["core/primitive_set_test.cc"], deps = [ ":crypto_format", ":mac", ":primitive_set", "//keyderivation:keyset_deriver", "//proto:tink_cc_proto", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "kms_clients_test", size = "small", srcs = ["core/kms_clients_test.cc"], deps = [ ":aead", ":kms_client", ":kms_clients", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "core/template_util_test", srcs = ["core/template_util_test.cc"], deps = [ ":core/template_util", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "core/key_type_manager_test", srcs = ["core/key_type_manager_test.cc"], deps = [ ":aead", ":core/key_type_manager", ":core/template_util", "//proto:aes_gcm_cc_proto", "//subtle", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "core/key_manager_impl_test", srcs = ["core/key_manager_impl_test.cc"], deps = [ ":aead", ":core/key_manager_impl", "//proto:aes_gcm_cc_proto", "//subtle", "//util:input_stream_util", "//util:istream_input_stream", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "//util:validation", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "core/private_key_manager_impl_test", srcs = ["core/private_key_manager_impl_test.cc"], deps = [ ":core/key_manager_impl", ":core/key_type_manager", ":core/private_key_manager_impl", ":core/private_key_type_manager", ":core/template_util", ":key_manager", ":registry", "//proto:ecdsa_cc_proto", "//subtle:aes_gcm_boringssl", "//subtle:random", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "core/key_access_test", srcs = ["core/key_access_test.cc"], deps = [ ":key_access", ":secret_key_access_testonly", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "core/partial_key_access_token_test", srcs = ["core/partial_key_access_token_test.cc"], deps = [ ":partial_key_access", ":partial_key_access_token", "@com_google_absl//absl/base:core_headers", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "core/restricted_data_test", srcs = ["core/restricted_data_test.cc"], deps = [ ":insecure_secret_key_access", ":restricted_data", "//subtle:random", "//util:secret_data", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "proto_keyset_format", srcs = ["proto_keyset_format.cc"], hdrs = ["proto_keyset_format.h"], include_prefix = "tink", visibility = ["//visibility:public"], deps = [ ":binary_keyset_reader", ":binary_keyset_writer", ":cleartext_keyset_handle", ":keyset_handle", ":secret_key_access_token", "//proto:tink_cc_proto", "//util:secret_data", "//util:secret_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_test( name = "proto_keyset_format_test", srcs = ["proto_keyset_format_test.cc"], deps = [ ":insecure_secret_key_access", ":key_status", ":keyset_handle", ":keyset_handle_builder", ":mac", ":proto_keyset_format", "//config:global_registry", "//config:tink_config", "//internal:legacy_proto_parameters", "//internal:proto_parameters_serialization", "//mac:mac_key_templates", "//signature:signature_key_templates", "//util:secret_data", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "core/big_integer_test", srcs = ["core/big_integer_test.cc"], deps = [ ":big_integer", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "core/restricted_big_integer_test", srcs = ["core/restricted_big_integer_test.cc"], deps = [ ":insecure_secret_key_access", ":restricted_big_integer", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "core/ec_point_test", srcs = ["core/ec_point_test.cc"], deps = [ ":big_integer", ":ec_point", "//subtle:random", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/CMakeLists.txt ================================================ add_subdirectory(aead) add_subdirectory(config) add_subdirectory(daead) add_subdirectory(hybrid) add_subdirectory(internal) add_subdirectory(mac) add_subdirectory(monitoring) add_subdirectory(jwt) add_subdirectory(keyderivation) add_subdirectory(prf) add_subdirectory(signature) add_subdirectory(streamingaead) add_subdirectory(subtle) add_subdirectory(util) tink_module(core) # Configuration settings for the build. if(USE_ONLY_FIPS) target_compile_definitions(tink_internal_fips_utils PUBLIC TINK_USE_ONLY_FIPS) endif() # Public libraries. set(TINK_VERSION_H "${TINK_GENFILE_DIR}/tink/version.h") tink_cc_library( NAME cc SRCS aead.h aead_config.h aead_factory.h aead_key_templates.h binary_keyset_reader.h binary_keyset_writer.h cleartext_keyset_handle.h deterministic_aead.h deterministic_aead_config.h deterministic_aead_factory.h deterministic_aead_key_templates.h hybrid_config.h hybrid_decrypt.h hybrid_decrypt_factory.h hybrid_encrypt.h hybrid_encrypt_factory.h hybrid_key_templates.h input_stream.h json_keyset_reader.h json_keyset_writer.h key_manager.h keyset_handle.h keyset_manager.h keyset_reader.h keyset_writer.h kms_client.h mac.h mac_config.h mac_factory.h mac_key_templates.h output_stream.h output_stream_with_result.h public_key_sign.h public_key_sign_factory.h public_key_verify.h public_key_verify_factory.h random_access_stream.h registry.h signature_config.h signature_key_templates.h streaming_aead.h streaming_aead_config.h streaming_aead_key_templates.h streaming_mac.h tink_config.h "${TINK_VERSION_H}" DEPS tink::core::aead tink::core::binary_keyset_reader tink::core::binary_keyset_writer tink::core::cleartext_keyset_handle tink::core::deterministic_aead tink::core::hybrid_decrypt tink::core::hybrid_encrypt tink::core::input_stream tink::core::json_keyset_reader tink::core::json_keyset_writer tink::core::key tink::core::key_manager tink::core::keyset_handle tink::core::keyset_manager tink::core::keyset_reader tink::core::keyset_writer tink::core::kms_client tink::core::mac tink::core::output_stream tink::core::output_stream_with_result tink::core::primitive_set tink::core::public_key_sign tink::core::public_key_verify tink::core::random_access_stream tink::core::registry tink::core::streaming_aead tink::core::streaming_mac tink::core::version absl::core_headers absl::flat_hash_map absl::memory absl::status absl::strings absl::synchronization tink::aead::aead_config tink::aead::aead_factory tink::aead::aead_key_templates tink::config::tink_config tink::daead::deterministic_aead_config tink::daead::deterministic_aead_factory tink::daead::deterministic_aead_key_templates tink::hybrid::hybrid_config tink::hybrid::hybrid_decrypt_factory tink::hybrid::hybrid_encrypt_factory tink::hybrid::hybrid_key_templates tink::internal::key_info tink::internal::registry_impl tink::mac::mac_config tink::mac::mac_factory tink::mac::mac_key_templates tink::signature::public_key_sign_factory tink::signature::public_key_verify_factory tink::signature::signature_config tink::signature::signature_key_templates tink::streamingaead::streaming_aead_config tink::streamingaead::streaming_aead_key_templates tink::util::buffer tink::util::errors tink::util::protobuf_helper tink::util::secret_proto tink::util::status tink::util::statusor tink::util::validation tink::proto::config_cc_proto tink::proto::tink_cc_proto PUBLIC ) add_library(tink::static ALIAS tink_core_cc) tink_cc_library( NAME input_stream SRCS input_stream.h DEPS tink::util::status tink::util::statusor ) tink_cc_library( NAME output_stream SRCS output_stream.h DEPS tink::util::status tink::util::statusor ) tink_cc_library( NAME random_access_stream SRCS random_access_stream.h DEPS tink::util::buffer tink::util::status tink::util::statusor ) tink_cc_library( NAME output_stream_with_result SRCS output_stream_with_result.h DEPS tink::core::output_stream absl::status tink::util::status tink::util::statusor ) tink_cc_library( NAME aead SRCS aead.h DEPS absl::strings tink::util::statusor ) tink_cc_library( NAME deterministic_aead SRCS deterministic_aead.h DEPS absl::strings tink::util::statusor ) tink_cc_library( NAME streaming_aead SRCS streaming_aead.h DEPS tink::core::input_stream tink::core::output_stream tink::core::random_access_stream absl::strings tink::util::statusor ) tink_cc_library( NAME streaming_mac SRCS streaming_mac.h DEPS tink::core::output_stream_with_result absl::strings tink::util::status tink::util::statusor ) tink_cc_library( NAME chunked_mac SRCS chunked_mac.h DEPS absl::strings tink::util::status tink::util::statusor ) tink_cc_library( NAME hybrid_decrypt SRCS hybrid_decrypt.h DEPS absl::strings tink::util::statusor ) tink_cc_library( NAME hybrid_encrypt SRCS hybrid_encrypt.h DEPS absl::strings tink::util::statusor ) tink_cc_library( NAME mac SRCS mac.h DEPS absl::strings tink::util::status tink::util::statusor ) tink_cc_library( NAME public_key_sign SRCS public_key_sign.h DEPS absl::strings tink::util::statusor ) tink_cc_library( NAME public_key_verify SRCS public_key_verify.h DEPS absl::strings tink::util::status ) tink_cc_library( NAME keyset_reader SRCS keyset_reader.h DEPS tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME keyset_writer SRCS keyset_writer.h DEPS tink::util::status tink::proto::tink_cc_proto ) tink_cc_library( NAME binary_keyset_reader SRCS core/binary_keyset_reader.cc binary_keyset_reader.h DEPS tink::core::keyset_reader absl::memory absl::status absl::strings tink::util::errors tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME binary_keyset_writer SRCS core/binary_keyset_writer.cc binary_keyset_writer.h DEPS tink::core::keyset_writer absl::memory absl::status absl::strings tink::util::protobuf_helper tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME json_keyset_reader SRCS core/json_keyset_reader.cc json_keyset_reader.h DEPS tink::core::keyset_reader absl::memory absl::status absl::strings rapidjson tink::util::enums tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME json_keyset_writer SRCS core/json_keyset_writer.cc json_keyset_writer.h DEPS tink::core::keyset_writer absl::status absl::strings rapidjson tink::util::enums tink::util::errors tink::util::protobuf_helper tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME crypto_format SRCS core/crypto_format.cc crypto_format.h DEPS absl::status absl::string_view tink::util::errors tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME primitive_set SRCS primitive_set.h primitive_set.h DEPS tink::core::crypto_format absl::core_headers absl::flat_hash_map absl::memory absl::status absl::string_view absl::synchronization tink::util::errors tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME primitive_wrapper SRCS primitive_wrapper.h DEPS tink::core::primitive_set tink::util::statusor ) tink_cc_library( NAME registry SRCS registry.h DEPS tink::core::key_manager tink::core::primitive_set absl::strings tink::internal::registry_impl tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) # Generate TINK_VERSION_H from version.h.templ. TINK_VERSION_LABEL is # substituted in version.h.templ with the value of PROJECT_VERSION. set(TINK_VERSION_LABEL "${PROJECT_VERSION}") configure_file(version.h.templ "${TINK_VERSION_H}") tink_cc_library( NAME version SRCS core/version.cc "${TINK_VERSION_H}" ) tink_cc_library( NAME keyset_handle SRCS core/keyset_handle.cc keyset_handle.h DEPS tink::core::aead tink::core::configuration tink::core::insecure_secret_key_access tink::core::key tink::core::key_gen_configuration tink::core::key_manager tink::core::key_status tink::core::keyset_reader tink::core::keyset_writer tink::core::primitive_set tink::core::registry tink::core::restricted_data tink::core::secret_key_access_token absl::core_headers absl::flat_hash_map absl::check absl::memory absl::status absl::strings absl::optional tink::config::global_registry tink::internal::configuration_impl tink::internal::key_gen_configuration_impl tink::internal::key_info tink::internal::key_status_util tink::internal::key_type_info_store tink::internal::keyset_wrapper tink::internal::keyset_wrapper_store tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::registry_impl tink::internal::util tink::util::errors tink::util::keyset_util tink::util::secret_data tink::util::secret_proto tink::util::status tink::util::statusor tink::util::validation tink::proto::tink_cc_proto ) tink_cc_library( NAME keyset_handle_builder SRCS core/keyset_handle_builder.cc keyset_handle_builder.h DEPS tink::core::key tink::core::key_status tink::core::keyset_handle tink::core::parameters absl::flat_hash_map absl::check absl::memory absl::status absl::strings absl::str_format absl::optional tink::internal::keyset_handle_builder_entry tink::subtle::random tink::util::secret_proto tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME cleartext_keyset_handle SRCS core/cleartext_keyset_handle.cc cleartext_keyset_handle.h DEPS tink::core::keyset_handle tink::core::keyset_reader tink::core::keyset_writer absl::flat_hash_map absl::memory absl::status tink::util::errors tink::util::secret_proto tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME key_manager SRCS core/key_manager.cc key_manager.h DEPS absl::memory absl::strings tink::util::errors tink::util::protobuf_helper tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME keyset_manager SRCS core/keyset_manager.cc keyset_manager.h DEPS tink::core::key_gen_configuration tink::core::keyset_handle absl::core_headers absl::memory absl::status absl::synchronization tink::internal::key_gen_configuration_impl tink::util::enums tink::util::errors tink::util::secret_proto tink::util::status tink::util::statusor tink::proto::tink_cc_proto PUBLIC ) tink_cc_library( NAME kms_client SRCS kms_client.h DEPS tink::core::aead absl::strings tink::util::statusor ) tink_cc_library( NAME kms_clients SRCS core/kms_clients.cc kms_clients.h DEPS tink::core::kms_client absl::core_headers absl::status absl::strings absl::synchronization tink::util::errors tink::util::status tink::util::statusor ) tink_cc_library( NAME template_util SRCS core/template_util.h DEPS absl::type_traits ) tink_cc_library( NAME key_type_manager SRCS core/key_type_manager.h DEPS tink::core::template_util tink::core::input_stream absl::status absl::strings tink::internal::fips_utils tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME key_manager_impl SRCS core/key_manager_impl.h DEPS tink::core::key_type_manager tink::core::template_util tink::core::input_stream tink::core::key_manager absl::base absl::memory absl::status absl::strings tink::util::constants tink::util::errors tink::util::secret_proto tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME private_key_type_manager SRCS core/private_key_type_manager.h DEPS tink::core::key_type_manager tink::core::template_util tink::util::statusor ) tink_cc_library( NAME private_key_manager_impl SRCS core/private_key_manager_impl.h DEPS tink::core::key_manager_impl tink::core::key_type_manager tink::core::private_key_type_manager tink::core::key_manager absl::memory absl::status absl::string_view tink::util::status tink::util::statusor tink::util::validation ) tink_cc_library( NAME key_access SRCS key_access.h ) tink_cc_library( NAME secret_key_access SRCS secret_key_access.h DEPS tink::core::key_access ) add_library(tink::core::secret_key_access_testonly ALIAS tink_internal_core_secret_key_access) tink_cc_library( NAME parameters SRCS parameters.h ) tink_cc_library( NAME key SRCS key.h DEPS tink::core::parameters absl::optional ) tink_cc_library( NAME private_key SRCS private_key.h DEPS tink::core::key ) tink_cc_library( NAME partial_key_access_token SRCS partial_key_access_token.h ) tink_cc_library( NAME partial_key_access SRCS partial_key_access.h DEPS tink::core::partial_key_access_token ) tink_cc_library( NAME secret_key_access_token SRCS secret_key_access_token.h ) tink_cc_library( NAME insecure_secret_key_access SRCS insecure_secret_key_access.h DEPS tink::core::secret_key_access_token ) tink_cc_library( NAME restricted_data SRCS core/restricted_data.cc restricted_data.h DEPS tink::core::secret_key_access_token absl::check absl::string_view crypto tink::subtle::random tink::util::secret_data ) tink_cc_library( NAME key_status SRCS key_status.h ) tink_cc_library( NAME configuration SRCS configuration.h DEPS tink::internal::key_type_info_store tink::internal::keyset_wrapper_store ) tink_cc_library( NAME key_gen_configuration SRCS key_gen_configuration.h DEPS tink::internal::key_type_info_store ) tink_cc_library( NAME big_integer SRCS core/big_integer.cc big_integer.h DEPS absl::string_view crypto ) tink_cc_library( NAME restricted_big_integer SRCS core/restricted_big_integer.cc restricted_big_integer.h DEPS tink::core::secret_key_access_token absl::string_view crypto tink::util::secret_data ) tink_cc_library( NAME ec_point SRCS ec_point.h DEPS tink::core::big_integer ) # tests tink_cc_test( NAME version_test SRCS core/version_test.cc DEPS tink::core::version gmock tink::internal::util ) tink_cc_test( NAME binary_keyset_reader_test SRCS core/binary_keyset_reader_test.cc DEPS tink::core::binary_keyset_reader gmock absl::status tink::util::test_util tink::proto::tink_cc_proto ) tink_cc_test( NAME binary_keyset_writer_test SRCS core/binary_keyset_writer_test.cc DEPS tink::core::binary_keyset_writer tink::core::cc tink::core::insecure_secret_key_access tink::core::proto_keyset_format gmock absl::memory absl::status tink::aead::aead_config tink::config::global_registry tink::util::secret_data tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::tink_cc_proto ) tink_cc_test( NAME json_keyset_reader_test SRCS core/json_keyset_reader_test.cc DEPS tink::core::json_keyset_reader tink::core::keyset_reader gmock absl::status absl::strings tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::aes_eax_cc_proto tink::proto::aes_gcm_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME json_keyset_writer_test SRCS core/json_keyset_writer_test.cc DEPS tink::core::json_keyset_reader tink::core::json_keyset_writer gmock absl::status absl::strings rapidjson tink::util::protobuf_helper tink::util::test_matchers tink::util::test_util tink::proto::aes_eax_cc_proto tink::proto::aes_gcm_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME crypto_format_test SRCS core/crypto_format_test.cc DEPS tink::core::crypto_format gmock tink::proto::tink_cc_proto ) tink_cc_test( NAME keyset_handle_test SRCS core/keyset_handle_test.cc DEPS tink::core::binary_keyset_reader tink::core::cc tink::core::cleartext_keyset_handle tink::core::configuration tink::core::key_manager_impl tink::core::key_type_manager tink::core::template_util tink::core::json_keyset_reader tink::core::json_keyset_writer tink::core::key_gen_configuration tink::core::key_status tink::core::keyset_handle tink::core::primitive_set tink::core::primitive_wrapper gmock absl::flat_hash_map absl::memory absl::status absl::strings absl::optional tink::aead::aead_key_templates tink::aead::aead_wrapper tink::aead::aes_gcm_key_manager tink::config::fips_140_2 tink::config::global_registry tink::config::key_gen_fips_140_2 tink::config::tink_config tink::internal::configuration_impl tink::internal::fips_utils tink::internal::key_gen_configuration_impl tink::signature::ecdsa_sign_key_manager tink::signature::ecdsa_verify_key_manager tink::signature::signature_key_templates tink::subtle::random tink::util::status tink::util::statusor tink::util::test_keyset_handle tink::util::test_matchers tink::util::test_util tink::proto::aes_gcm_cc_proto tink::proto::aes_gcm_siv_cc_proto tink::proto::ecdsa_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME keyset_handle_builder_test SRCS core/keyset_handle_builder_test.cc DEPS tink::core::aead tink::core::key_type_manager tink::core::template_util tink::core::input_stream tink::core::insecure_secret_key_access tink::core::key_status tink::core::keyset_handle tink::core::keyset_handle_builder tink::core::mac tink::core::partial_key_access tink::core::primitive_set tink::core::primitive_wrapper tink::core::registry tink::core::restricted_data gmock absl::flat_hash_map absl::memory absl::status absl::strings tink::aead::aes_gcm_parameters tink::config::global_registry tink::config::tink_config tink::internal::legacy_proto_key tink::internal::legacy_proto_parameters tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::mac::aes_cmac_key tink::mac::aes_cmac_parameters tink::mac::mac_key_templates tink::subtle::random tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::aes_cmac_cc_proto tink::proto::aes_gcm_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME key_manager_test SRCS core/key_manager_test.cc DEPS tink::core::key_manager gmock absl::status tink::util::status tink::util::test_matchers tink::proto::empty_cc_proto ) tink_cc_test( NAME keyset_manager_test SRCS core/keyset_manager_test.cc DEPS tink::core::keyset_handle tink::core::keyset_manager gmock absl::status tink::aead::aead_config tink::aead::aes_gcm_key_manager tink::util::test_keyset_handle tink::proto::aes_gcm_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME cleartext_keyset_handle_test SRCS core/cleartext_keyset_handle_test.cc DEPS tink::core::binary_keyset_reader tink::core::cleartext_keyset_handle tink::core::keyset_handle gmock absl::status tink::util::status tink::util::test_keyset_handle tink::util::test_util tink::proto::tink_cc_proto ) tink_cc_test( NAME primitive_set_test SRCS core/primitive_set_test.cc DEPS tink::core::crypto_format tink::core::mac tink::core::primitive_set gmock absl::memory absl::status absl::strings absl::string_view tink::keyderivation::keyset_deriver tink::util::test_matchers tink::util::test_util tink::proto::tink_cc_proto ) tink_cc_test( NAME kms_clients_test SRCS core/kms_clients_test.cc DEPS tink::core::aead tink::core::kms_client tink::core::kms_clients gmock absl::status absl::strings tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util ) tink_cc_test( NAME template_util_test SRCS core/template_util_test.cc DEPS tink::core::template_util gmock ) tink_cc_test( NAME key_type_manager_test SRCS core/key_type_manager_test.cc DEPS tink::core::aead tink::core::key_type_manager tink::core::template_util gmock absl::memory absl::status tink::subtle::subtle tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::util::validation tink::proto::aes_gcm_cc_proto ) tink_cc_test( NAME key_manager_impl_test SRCS core/key_manager_impl_test.cc DEPS tink::core::aead tink::core::key_manager_impl gmock absl::status tink::subtle::subtle tink::util::input_stream_util tink::util::istream_input_stream tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::util::validation tink::proto::aes_gcm_cc_proto ) tink_cc_test( NAME private_key_manager_impl_test SRCS core/private_key_manager_impl_test.cc DEPS tink::core::key_manager_impl tink::core::key_type_manager tink::core::private_key_manager_impl tink::core::private_key_type_manager tink::core::template_util tink::core::key_manager tink::core::registry gmock absl::memory absl::status tink::subtle::aes_gcm_boringssl tink::subtle::random tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::util::validation tink::proto::ecdsa_cc_proto ) tink_cc_test( NAME key_access_test SRCS core/key_access_test.cc DEPS tink::core::key_access tink::core::secret_key_access_testonly gmock ) tink_cc_test( NAME partial_key_access_token_test SRCS core/partial_key_access_token_test.cc DEPS tink::core::partial_key_access tink::core::partial_key_access_token gmock absl::core_headers ) tink_cc_test( NAME restricted_data_test SRCS core/restricted_data_test.cc DEPS tink::core::insecure_secret_key_access tink::core::restricted_data gmock tink::subtle::random tink::util::secret_data ) tink_cc_library( NAME proto_keyset_format SRCS proto_keyset_format.cc proto_keyset_format.h DEPS tink::core::binary_keyset_reader tink::core::binary_keyset_writer tink::core::cleartext_keyset_handle tink::core::keyset_handle tink::core::secret_key_access_token absl::status absl::strings tink::util::secret_data tink::util::secret_proto tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_test( NAME proto_keyset_format_test SRCS proto_keyset_format_test.cc DEPS tink::core::insecure_secret_key_access tink::core::key_status tink::core::keyset_handle tink::core::keyset_handle_builder tink::core::mac tink::core::proto_keyset_format gmock absl::strings tink::config::global_registry tink::config::tink_config tink::internal::legacy_proto_parameters tink::internal::proto_parameters_serialization tink::mac::mac_key_templates tink::signature::signature_key_templates tink::util::secret_data tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME big_integer_test SRCS core/big_integer_test.cc DEPS tink::core::big_integer gmock absl::strings absl::string_view ) tink_cc_test( NAME restricted_big_integer_test SRCS core/restricted_big_integer_test.cc DEPS tink::core::insecure_secret_key_access tink::core::restricted_big_integer gmock absl::strings absl::string_view ) tink_cc_test( NAME ec_point_test SRCS core/ec_point_test.cc DEPS tink::core::big_integer tink::core::ec_point gmock tink::subtle::random ) ================================================ FILE: cc/WORKSPACE ================================================ workspace(name = "tink_cc") # Use this repository if you want to build the FIPS module for BoringSSL # local_repository( # name = "boringssl", # path = "third_party/boringssl_fips/", # ) load("@tink_cc//:tink_cc_deps.bzl", "tink_cc_deps", "tink_cc_testonly_deps") tink_cc_deps() tink_cc_testonly_deps() load("@tink_cc//:tink_cc_deps_init.bzl", "tink_cc_deps_init") tink_cc_deps_init() ================================================ FILE: cc/aead/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "aead_wrapper", srcs = ["aead_wrapper.cc"], hdrs = ["aead_wrapper.h"], include_prefix = "tink/aead", deps = [ "//:aead", "//:crypto_format", "//:primitive_set", "//:primitive_wrapper", "//internal:monitoring_util", "//internal:registry_impl", "//internal:util", "//monitoring", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "cord_aead_wrapper", srcs = ["cord_aead_wrapper.cc"], hdrs = ["cord_aead_wrapper.h"], include_prefix = "tink/aead", deps = [ ":cord_aead", "//:crypto_format", "//:primitive_set", "//:primitive_wrapper", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:cord", ], ) cc_library( name = "cord_aead", hdrs = ["cord_aead.h"], include_prefix = "tink/aead", visibility = ["//visibility:public"], deps = [ "//util:statusor", "@com_google_absl//absl/strings:cord", ], ) cc_library( name = "aead_config", srcs = ["aead_config.cc"], hdrs = ["aead_config.h"], include_prefix = "tink/aead", visibility = ["//visibility:public"], deps = [ ":aead_wrapper", ":aes_ctr_hmac_aead_key_manager", ":aes_ctr_hmac_aead_proto_serialization", ":aes_eax_key_manager", ":aes_eax_proto_serialization", ":aes_gcm_key_manager", ":aes_gcm_proto_serialization", ":aes_gcm_siv_key_manager", ":aes_gcm_siv_proto_serialization", ":kms_aead_key_manager", ":kms_envelope_aead_key_manager", ":xchacha20_poly1305_key_manager", ":xchacha20_poly1305_proto_serialization", "//:registry", "//config:tink_fips", "//mac:mac_config", "//proto:config_cc_proto", "//util:status", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", ], ) cc_library( name = "aead_factory", srcs = ["aead_factory.cc"], hdrs = ["aead_factory.h"], include_prefix = "tink/aead", deps = [ ":aead_wrapper", "//:aead", "//:key_manager", "//:keyset_handle", "//:registry", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/memory", ], ) cc_library( name = "aead_key_templates", srcs = ["aead_key_templates.cc"], hdrs = ["aead_key_templates.h"], include_prefix = "tink/aead", visibility = ["//visibility:public"], deps = [ "//proto:aes_ctr_cc_proto", "//proto:aes_ctr_hmac_aead_cc_proto", "//proto:aes_eax_cc_proto", "//proto:aes_gcm_cc_proto", "//proto:aes_gcm_siv_cc_proto", "//proto:common_cc_proto", "//proto:hmac_cc_proto", "//proto:kms_envelope_cc_proto", "//proto:tink_cc_proto", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/strings", ], ) cc_library( name = "aes_eax_key_manager", hdrs = ["aes_eax_key_manager.h"], include_prefix = "tink/aead", deps = [ "//:aead", "//:core/key_type_manager", "//:core/template_util", "//proto:aes_eax_cc_proto", "//proto:tink_cc_proto", "//subtle:aes_eax_boringssl", "//subtle:random", "//util:constants", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "aes_gcm_key_manager", hdrs = ["aes_gcm_key_manager.h"], include_prefix = "tink/aead", visibility = ["//visibility:public"], deps = [ ":cord_aead", "//:aead", "//:core/key_type_manager", "//:core/template_util", "//:input_stream", "//aead/internal:cord_aes_gcm_boringssl", "//internal:fips_utils", "//proto:aes_gcm_cc_proto", "//proto:tink_cc_proto", "//subtle:aes_gcm_boringssl", "//subtle:random", "//util:constants", "//util:input_stream_util", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "aes_gcm_siv_key_manager", hdrs = ["aes_gcm_siv_key_manager.h"], include_prefix = "tink/aead", deps = [ "//:aead", "//:core/key_type_manager", "//:core/template_util", "//proto:aes_gcm_siv_cc_proto", "//proto:tink_cc_proto", "//subtle:aes_gcm_siv_boringssl", "//subtle:random", "//util:constants", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/strings", ], ) cc_library( name = "aes_ctr_hmac_aead_key_manager", srcs = ["aes_ctr_hmac_aead_key_manager.cc"], hdrs = ["aes_ctr_hmac_aead_key_manager.h"], include_prefix = "tink/aead", visibility = ["//visibility:public"], deps = [ "//:aead", "//:core/key_type_manager", "//:core/template_util", "//:input_stream", "//:mac", "//internal:fips_utils", "//mac:hmac_key_manager", "//proto:aes_ctr_cc_proto", "//proto:aes_ctr_hmac_aead_cc_proto", "//proto:common_cc_proto", "//proto:hmac_cc_proto", "//proto:tink_cc_proto", "//subtle:aes_ctr_boringssl", "//subtle:encrypt_then_authenticate", "//subtle:ind_cpa_cipher", "//subtle:random", "//util:constants", "//util:enums", "//util:input_stream_util", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", ], ) cc_library( name = "xchacha20_poly1305_key_manager", hdrs = ["xchacha20_poly1305_key_manager.h"], include_prefix = "tink/aead", visibility = ["//visibility:public"], deps = [ "//:aead", "//:core/key_type_manager", "//:core/template_util", "//:input_stream", "//proto:tink_cc_proto", "//proto:xchacha20_poly1305_cc_proto", "//subtle", "//subtle:xchacha20_poly1305_boringssl", "//util:constants", "//util:input_stream_util", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "kms_aead_key_manager", hdrs = ["kms_aead_key_manager.h"], include_prefix = "tink/aead", deps = [ "//:aead", "//:core/key_type_manager", "//:core/template_util", "//:kms_client", "//:kms_clients", "//proto:kms_aead_cc_proto", "//proto:tink_cc_proto", "//util:constants", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "kms_envelope_aead", srcs = ["kms_envelope_aead.cc"], hdrs = ["kms_envelope_aead.h"], include_prefix = "tink/aead", visibility = ["//visibility:public"], deps = [ "//:aead", "//:registry", "//aead/internal:aead_util", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/base:endian", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "kms_envelope_aead_key_manager", srcs = ["kms_envelope_aead_key_manager.cc"], hdrs = ["kms_envelope_aead_key_manager.h"], include_prefix = "tink/aead", deps = [ ":kms_envelope_aead", "//:aead", "//:core/key_type_manager", "//:core/template_util", "//:kms_client", "//:kms_clients", "//aead/internal:aead_util", "//internal:fips_utils", "//proto:kms_envelope_cc_proto", "//proto:tink_cc_proto", "//util:constants", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "mock_aead", testonly = 1, hdrs = ["mock_aead.h"], include_prefix = "tink/aead", visibility = ["//visibility:public"], deps = [ "//:aead", "//util:statusor", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest", ], ) cc_library( name = "failing_aead", testonly = 1, srcs = ["failing_aead.cc"], hdrs = ["failing_aead.h"], include_prefix = "tink/aead", visibility = ["//visibility:public"], deps = [ "//:aead", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "aead_parameters", hdrs = ["aead_parameters.h"], include_prefix = "tink/aead", deps = ["//:parameters"], ) cc_library( name = "aead_key", hdrs = ["aead_key.h"], include_prefix = "tink/aead", deps = [ ":aead_parameters", "//:key", "@com_google_absl//absl/strings", ], ) cc_library( name = "aes_gcm_parameters", srcs = ["aes_gcm_parameters.cc"], hdrs = ["aes_gcm_parameters.h"], include_prefix = "tink/aead", deps = [ ":aead_parameters", "//:parameters", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "aes_gcm_key", srcs = ["aes_gcm_key.cc"], hdrs = ["aes_gcm_key.h"], include_prefix = "tink/aead", deps = [ ":aead_key", ":aes_gcm_parameters", "//:key", "//:partial_key_access_token", "//:restricted_data", "//subtle:subtle_util", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "aes_gcm_proto_serialization", srcs = ["aes_gcm_proto_serialization.cc"], hdrs = ["aes_gcm_proto_serialization.h"], include_prefix = "tink/aead", deps = [ ":aes_gcm_key", ":aes_gcm_parameters", "//:partial_key_access", "//:restricted_data", "//:secret_key_access_token", "//internal:key_parser", "//internal:key_serializer", "//internal:mutable_serialization_registry", "//internal:parameters_parser", "//internal:parameters_serializer", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//proto:aes_gcm_cc_proto", "//proto:tink_cc_proto", "//util:secret_data", "//util:secret_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "aes_gcm_siv_parameters", srcs = ["aes_gcm_siv_parameters.cc"], hdrs = ["aes_gcm_siv_parameters.h"], include_prefix = "tink/aead", deps = [ ":aead_parameters", "//:parameters", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "aes_gcm_siv_key", srcs = ["aes_gcm_siv_key.cc"], hdrs = ["aes_gcm_siv_key.h"], include_prefix = "tink/aead", deps = [ ":aead_key", ":aes_gcm_siv_parameters", "//:key", "//:partial_key_access_token", "//:restricted_data", "//subtle:subtle_util", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "aes_gcm_siv_proto_serialization", srcs = ["aes_gcm_siv_proto_serialization.cc"], hdrs = ["aes_gcm_siv_proto_serialization.h"], include_prefix = "tink/aead", deps = [ ":aes_gcm_siv_key", ":aes_gcm_siv_parameters", "//:partial_key_access", "//:restricted_data", "//:secret_key_access_token", "//internal:key_parser", "//internal:key_serializer", "//internal:mutable_serialization_registry", "//internal:parameters_parser", "//internal:parameters_serializer", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//proto:aes_gcm_siv_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "config_v0", srcs = ["config_v0.cc"], hdrs = ["config_v0.h"], include_prefix = "tink/aead", deps = [ "//:configuration", "//aead/internal:config_v0", "@com_google_absl//absl/log:check", ], ) cc_library( name = "key_gen_config_v0", srcs = ["key_gen_config_v0.cc"], hdrs = ["key_gen_config_v0.h"], include_prefix = "tink/aead", deps = [ "//:key_gen_configuration", "//aead/internal:key_gen_config_v0", "@com_google_absl//absl/log:check", ], ) cc_library( name = "aes_eax_parameters", srcs = ["aes_eax_parameters.cc"], hdrs = ["aes_eax_parameters.h"], include_prefix = "tink/aead", deps = [ ":aead_parameters", "//:parameters", "//util:status", "//util:statusor", "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "aes_eax_key", srcs = ["aes_eax_key.cc"], hdrs = ["aes_eax_key.h"], include_prefix = "tink/aead", deps = [ ":aead_key", ":aes_eax_parameters", "//:key", "//:partial_key_access_token", "//:restricted_data", "//subtle:subtle_util", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "aes_eax_proto_serialization", srcs = ["aes_eax_proto_serialization.cc"], hdrs = ["aes_eax_proto_serialization.h"], include_prefix = "tink/aead", deps = [ ":aes_eax_key", ":aes_eax_parameters", "//:partial_key_access", "//:restricted_data", "//:secret_key_access_token", "//internal:key_parser", "//internal:key_serializer", "//internal:mutable_serialization_registry", "//internal:parameters_parser", "//internal:parameters_serializer", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//proto:aes_eax_cc_proto", "//proto:tink_cc_proto", "//util:secret_data", "//util:secret_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "xchacha20_poly1305_parameters", srcs = ["xchacha20_poly1305_parameters.cc"], hdrs = ["xchacha20_poly1305_parameters.h"], include_prefix = "tink/aead", deps = [ ":aead_parameters", "//:parameters", "//util:status", "//util:statusor", "@com_google_absl//absl/status", ], ) cc_library( name = "xchacha20_poly1305_key", srcs = ["xchacha20_poly1305_key.cc"], hdrs = ["xchacha20_poly1305_key.h"], include_prefix = "tink/aead", deps = [ ":aead_key", ":xchacha20_poly1305_parameters", "//:key", "//:partial_key_access_token", "//:restricted_data", "//subtle:subtle_util", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "xchacha20_poly1305_proto_serialization", srcs = ["xchacha20_poly1305_proto_serialization.cc"], hdrs = ["xchacha20_poly1305_proto_serialization.h"], include_prefix = "tink/aead", deps = [ ":xchacha20_poly1305_key", ":xchacha20_poly1305_parameters", "//:partial_key_access", "//:restricted_data", "//:secret_key_access_token", "//internal:key_parser", "//internal:key_serializer", "//internal:mutable_serialization_registry", "//internal:parameters_parser", "//internal:parameters_serializer", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//proto:tink_cc_proto", "//proto:xchacha20_poly1305_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "chacha20_poly1305_parameters", srcs = ["chacha20_poly1305_parameters.cc"], hdrs = ["chacha20_poly1305_parameters.h"], include_prefix = "tink/aead", deps = [ ":aead_parameters", "//:parameters", "//util:status", "//util:statusor", "@com_google_absl//absl/status", ], ) cc_library( name = "chacha20_poly1305_key", srcs = ["chacha20_poly1305_key.cc"], hdrs = ["chacha20_poly1305_key.h"], include_prefix = "tink/aead", deps = [ ":aead_key", ":chacha20_poly1305_parameters", "//:key", "//:partial_key_access_token", "//:restricted_data", "//subtle:subtle_util", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "chacha20_poly1305_proto_serialization", srcs = ["chacha20_poly1305_proto_serialization.cc"], hdrs = ["chacha20_poly1305_proto_serialization.h"], include_prefix = "tink/aead", deps = [ ":chacha20_poly1305_key", ":chacha20_poly1305_parameters", "//:partial_key_access", "//:restricted_data", "//:secret_key_access_token", "//internal:key_parser", "//internal:key_serializer", "//internal:mutable_serialization_registry", "//internal:parameters_parser", "//internal:parameters_serializer", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//proto:chacha20_poly1305_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "aes_ctr_hmac_aead_parameters", srcs = ["aes_ctr_hmac_aead_parameters.cc"], hdrs = ["aes_ctr_hmac_aead_parameters.h"], include_prefix = "tink/aead", deps = [ ":aead_parameters", "//:parameters", "//util:status", "//util:statusor", "@com_google_absl//absl/algorithm:container", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "aes_ctr_hmac_aead_key", srcs = ["aes_ctr_hmac_aead_key.cc"], hdrs = ["aes_ctr_hmac_aead_key.h"], include_prefix = "tink/aead", deps = [ ":aead_key", ":aes_ctr_hmac_aead_parameters", "//:key", "//:partial_key_access_token", "//:restricted_data", "//subtle:subtle_util", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "aes_ctr_hmac_aead_proto_serialization", srcs = ["aes_ctr_hmac_aead_proto_serialization.cc"], hdrs = ["aes_ctr_hmac_aead_proto_serialization.h"], include_prefix = "tink/aead", deps = [ ":aes_ctr_hmac_aead_key", ":aes_ctr_hmac_aead_parameters", "//:partial_key_access", "//:restricted_data", "//:secret_key_access_token", "//internal:key_parser", "//internal:key_serializer", "//internal:mutable_serialization_registry", "//internal:parameters_parser", "//internal:parameters_serializer", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//proto:aes_ctr_cc_proto", "//proto:aes_ctr_hmac_aead_cc_proto", "//proto:common_cc_proto", "//proto:hmac_cc_proto", "//proto:tink_cc_proto", "//util:secret_data", "//util:secret_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) # tests cc_test( name = "aead_wrapper_test", size = "small", srcs = ["aead_wrapper_test.cc"], deps = [ ":aead_wrapper", ":mock_aead", "//:aead", "//:crypto_format", "//:primitive_set", "//:registry", "//internal:registry_impl", "//monitoring", "//monitoring:monitoring_client_mocks", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aead_config_test", size = "small", srcs = ["aead_config_test.cc"], tags = ["fips"], deps = [ ":aead_config", ":aead_key_templates", ":aes_ctr_hmac_aead_key", ":aes_ctr_hmac_aead_parameters", ":aes_eax_key", ":aes_eax_parameters", ":aes_gcm_key", ":aes_gcm_key_manager", ":aes_gcm_parameters", ":aes_gcm_siv_key", ":aes_gcm_siv_parameters", ":key_gen_config_v0", ":xchacha20_poly1305_key", ":xchacha20_poly1305_parameters", "//:aead", "//:insecure_secret_key_access", "//:key", "//:key_status", "//:keyset_handle", "//:keyset_handle_builder", "//:parameters", "//:partial_key_access", "//:registry", "//:restricted_data", "//config:global_registry", "//config:tink_fips", "//internal:fips_utils", "//internal:legacy_proto_key", "//internal:mutable_serialization_registry", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//internal:serialization", "//proto:aes_eax_cc_proto", "//proto:aes_gcm_cc_proto", "//proto:aes_gcm_siv_cc_proto", "//proto:tink_cc_proto", "//proto:xchacha20_poly1305_cc_proto", "//subtle:random", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aead_factory_test", size = "small", srcs = ["aead_factory_test.cc"], deps = [ ":aead_config", ":aead_factory", ":aes_gcm_key_manager", "//:aead", "//:crypto_format", "//:keyset_handle", "//internal:key_info", "//proto:aes_gcm_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_keyset_handle", "//util:test_util", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aead_key_templates_test", size = "small", srcs = ["aead_key_templates_test.cc"], deps = [ ":aead_config", ":aead_key_templates", ":aes_ctr_hmac_aead_key_manager", ":aes_eax_key_manager", ":aes_gcm_key_manager", ":aes_gcm_siv_key_manager", ":kms_envelope_aead_key_manager", ":xchacha20_poly1305_key_manager", "//:aead", "//:core/key_manager_impl", "//:key_manager", "//:keyset_handle", "//config:global_registry", "//proto:aes_ctr_cc_proto", "//proto:aes_ctr_hmac_aead_cc_proto", "//proto:aes_eax_cc_proto", "//proto:aes_gcm_cc_proto", "//proto:aes_gcm_siv_cc_proto", "//proto:common_cc_proto", "//proto:hmac_cc_proto", "//proto:kms_envelope_cc_proto", "//proto:tink_cc_proto", "//proto:xchacha20_poly1305_cc_proto", "//subtle:aead_test_util", "//util:fake_kms_client", "//util:status", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_eax_key_manager_test", size = "small", srcs = ["aes_eax_key_manager_test.cc"], deps = [ ":aes_eax_key_manager", "//:aead", "//proto:aes_eax_cc_proto", "//proto:tink_cc_proto", "//subtle:aead_test_util", "//subtle:aes_eax_boringssl", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_gcm_key_manager_test", size = "small", srcs = ["aes_gcm_key_manager_test.cc"], deps = [ ":aes_gcm_key_manager", ":cord_aead", "//:aead", "//aead/internal:cord_aes_gcm_boringssl", "//proto:aes_gcm_cc_proto", "//proto:tink_cc_proto", "//subtle:aead_test_util", "//subtle:aes_gcm_boringssl", "//util:istream_input_stream", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_gcm_siv_key_manager_test", size = "small", srcs = ["aes_gcm_siv_key_manager_test.cc"], deps = [ ":aes_gcm_siv_key_manager", "//:aead", "//internal:ssl_util", "//proto:aes_gcm_siv_cc_proto", "//proto:tink_cc_proto", "//subtle:aead_test_util", "//subtle:aes_gcm_siv_boringssl", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_ctr_hmac_aead_key_manager_test", size = "small", srcs = ["aes_ctr_hmac_aead_key_manager_test.cc"], deps = [ ":aes_ctr_hmac_aead_key_manager", "//:aead", "//proto:aes_ctr_cc_proto", "//proto:aes_ctr_hmac_aead_cc_proto", "//proto:common_cc_proto", "//proto:hmac_cc_proto", "//proto:tink_cc_proto", "//subtle", "//subtle:aead_test_util", "//subtle:aes_ctr_boringssl", "//util:enums", "//util:istream_input_stream", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "xchacha20_poly1305_key_manager_test", size = "small", srcs = ["xchacha20_poly1305_key_manager_test.cc"], deps = [ ":xchacha20_poly1305_key_manager", "//:aead", "//internal:ssl_util", "//proto:tink_cc_proto", "//proto:xchacha20_poly1305_cc_proto", "//subtle:aead_test_util", "//subtle:xchacha20_poly1305_boringssl", "//util:istream_input_stream", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "kms_aead_key_manager_test", size = "small", srcs = ["kms_aead_key_manager_test.cc"], deps = [ ":kms_aead_key_manager", "//:aead", "//:kms_client", "//:kms_clients", "//proto:kms_aead_cc_proto", "//proto:tink_cc_proto", "//subtle:aead_test_util", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "kms_envelope_aead_test", size = "small", srcs = ["kms_envelope_aead_test.cc"], deps = [ ":aead_config", ":aead_key_templates", ":kms_envelope_aead", "//:aead", "//:keyset_handle", "//:registry", "//config:global_registry", "//internal:ssl_util", "//mac:mac_key_templates", "//proto:aes_gcm_cc_proto", "//proto:tink_cc_proto", "//util:fake_kms_client", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/base:endian", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "kms_envelope_aead_key_manager_test", size = "small", srcs = ["kms_envelope_aead_key_manager_test.cc"], deps = [ ":aead_config", ":aead_key_templates", ":aes_eax_key_manager", ":kms_envelope_aead", ":kms_envelope_aead_key_manager", "//:aead", "//:keyset_handle", "//:kms_client", "//:kms_clients", "//:registry", "//config:global_registry", "//mac:mac_key_templates", "//proto:kms_envelope_cc_proto", "//proto:tink_cc_proto", "//subtle:aead_test_util", "//util:fake_kms_client", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "cord_aead_wrapper_test", size = "small", srcs = ["cord_aead_wrapper_test.cc"], deps = [ ":cord_aead", ":cord_aead_wrapper", "//:primitive_set", "//proto:tink_cc_proto", "//util:status", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:cord", "@com_google_absl//absl/strings:cord_test_helpers", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "failing_aead_test", srcs = ["failing_aead_test.cc"], deps = [ ":failing_aead", "//:aead", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_gcm_parameters_test", srcs = ["aes_gcm_parameters_test.cc"], deps = [ ":aes_gcm_parameters", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_gcm_key_test", srcs = ["aes_gcm_key_test.cc"], deps = [ ":aes_gcm_key", ":aes_gcm_parameters", "//:partial_key_access", "//:restricted_data", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_gcm_proto_serialization_test", size = "small", srcs = ["aes_gcm_proto_serialization_test.cc"], deps = [ ":aes_gcm_key", ":aes_gcm_parameters", ":aes_gcm_proto_serialization", "//:insecure_secret_key_access", "//:key", "//:parameters", "//:partial_key_access", "//:restricted_data", "//internal:mutable_serialization_registry", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//internal:serialization", "//proto:aes_gcm_cc_proto", "//proto:tink_cc_proto", "//subtle:random", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_gcm_siv_parameters_test", srcs = ["aes_gcm_siv_parameters_test.cc"], deps = [ ":aes_gcm_siv_parameters", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_gcm_siv_key_test", srcs = ["aes_gcm_siv_key_test.cc"], deps = [ ":aes_gcm_siv_key", ":aes_gcm_siv_parameters", "//:partial_key_access", "//:restricted_data", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_gcm_siv_proto_serialization_test", size = "small", srcs = ["aes_gcm_siv_proto_serialization_test.cc"], deps = [ ":aes_gcm_siv_key", ":aes_gcm_siv_parameters", ":aes_gcm_siv_proto_serialization", "//:insecure_secret_key_access", "//:key", "//:parameters", "//:partial_key_access", "//:restricted_data", "//internal:mutable_serialization_registry", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//internal:serialization", "//proto:aes_gcm_siv_cc_proto", "//proto:tink_cc_proto", "//subtle:random", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "config_v0_test", srcs = ["config_v0_test.cc"], deps = [ ":aead_key_templates", ":config_v0", ":key_gen_config_v0", "//:aead", "//:keyset_handle", "//internal:ssl_util", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_eax_parameters_test", srcs = ["aes_eax_parameters_test.cc"], deps = [ ":aes_eax_parameters", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_eax_key_test", srcs = ["aes_eax_key_test.cc"], deps = [ ":aes_eax_key", ":aes_eax_parameters", "//:partial_key_access", "//:restricted_data", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_eax_proto_serialization_test", srcs = ["aes_eax_proto_serialization_test.cc"], deps = [ ":aes_eax_key", ":aes_eax_parameters", ":aes_eax_proto_serialization", "//:insecure_secret_key_access", "//:key", "//:parameters", "//:partial_key_access", "//:restricted_data", "//internal:mutable_serialization_registry", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//internal:serialization", "//proto:aes_eax_cc_proto", "//proto:tink_cc_proto", "//subtle:random", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "xchacha20_poly1305_parameters_test", srcs = ["xchacha20_poly1305_parameters_test.cc"], deps = [ ":xchacha20_poly1305_parameters", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "xchacha20_poly1305_key_test", srcs = ["xchacha20_poly1305_key_test.cc"], deps = [ ":xchacha20_poly1305_key", ":xchacha20_poly1305_parameters", "//:partial_key_access", "//:restricted_data", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "xchacha20_poly1305_proto_serialization_test", srcs = ["xchacha20_poly1305_proto_serialization_test.cc"], deps = [ ":xchacha20_poly1305_key", ":xchacha20_poly1305_parameters", ":xchacha20_poly1305_proto_serialization", "//:insecure_secret_key_access", "//:key", "//:parameters", "//:partial_key_access", "//:restricted_data", "//internal:mutable_serialization_registry", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//internal:serialization", "//proto:tink_cc_proto", "//proto:xchacha20_poly1305_cc_proto", "//subtle:random", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "chacha20_poly1305_parameters_test", srcs = ["chacha20_poly1305_parameters_test.cc"], deps = [ ":chacha20_poly1305_parameters", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "chacha20_poly1305_key_test", srcs = ["chacha20_poly1305_key_test.cc"], deps = [ ":chacha20_poly1305_key", ":chacha20_poly1305_parameters", "//:partial_key_access", "//:restricted_data", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "chacha20_poly1305_proto_serialization_test", srcs = ["chacha20_poly1305_proto_serialization_test.cc"], deps = [ ":chacha20_poly1305_key", ":chacha20_poly1305_parameters", ":chacha20_poly1305_proto_serialization", "//:insecure_secret_key_access", "//:key", "//:parameters", "//:partial_key_access", "//:restricted_data", "//internal:mutable_serialization_registry", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//internal:serialization", "//proto:chacha20_poly1305_cc_proto", "//proto:tink_cc_proto", "//subtle:random", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_ctr_hmac_aead_parameters_test", srcs = ["aes_ctr_hmac_aead_parameters_test.cc"], deps = [ ":aes_ctr_hmac_aead_parameters", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_ctr_hmac_aead_key_test", srcs = ["aes_ctr_hmac_aead_key_test.cc"], deps = [ ":aes_ctr_hmac_aead_key", ":aes_ctr_hmac_aead_parameters", "//:partial_key_access", "//:restricted_data", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_ctr_hmac_aead_proto_serialization_test", srcs = ["aes_ctr_hmac_aead_proto_serialization_test.cc"], deps = [ ":aes_ctr_hmac_aead_key", ":aes_ctr_hmac_aead_parameters", ":aes_ctr_hmac_aead_proto_serialization", "//:insecure_secret_key_access", "//:key", "//:parameters", "//:partial_key_access", "//:restricted_data", "//internal:mutable_serialization_registry", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//internal:serialization", "//proto:aes_ctr_cc_proto", "//proto:aes_ctr_hmac_aead_cc_proto", "//proto:common_cc_proto", "//proto:hmac_cc_proto", "//proto:tink_cc_proto", "//subtle:random", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/aead/CMakeLists.txt ================================================ tink_module(aead) add_subdirectory(internal) tink_cc_library( NAME aead_wrapper SRCS aead_wrapper.cc aead_wrapper.h DEPS absl::memory absl::status absl::strings tink::core::aead tink::core::crypto_format tink::core::primitive_set tink::core::primitive_wrapper tink::internal::monitoring_util tink::internal::registry_impl tink::internal::util tink::monitoring::monitoring tink::util::status tink::util::statusor ) tink_cc_library( NAME cord_aead SRCS cord_aead.h DEPS absl::cord tink::util::statusor ) tink_cc_library( NAME cord_aead_wrapper SRCS cord_aead_wrapper.cc cord_aead_wrapper.h DEPS tink::aead::cord_aead absl::status absl::cord tink::core::crypto_format tink::core::primitive_set tink::core::primitive_wrapper tink::util::status tink::util::statusor ) tink_cc_library( NAME aead_config SRCS aead_config.cc aead_config.h DEPS tink::aead::aead_wrapper tink::aead::aes_ctr_hmac_aead_key_manager tink::aead::aes_ctr_hmac_aead_proto_serialization tink::aead::aes_eax_key_manager tink::aead::aes_eax_proto_serialization tink::aead::aes_gcm_key_manager tink::aead::aes_gcm_proto_serialization tink::aead::aes_gcm_siv_key_manager tink::aead::aes_gcm_siv_proto_serialization tink::aead::kms_aead_key_manager tink::aead::kms_envelope_aead_key_manager tink::aead::xchacha20_poly1305_key_manager tink::aead::xchacha20_poly1305_proto_serialization absl::core_headers absl::memory absl::status tink::core::registry tink::config::tink_fips tink::mac::mac_config tink::util::status tink::proto::config_cc_proto ) tink_cc_library( NAME aead_factory SRCS aead_factory.cc aead_factory.h DEPS tink::aead::aead_wrapper absl::core_headers absl::memory tink::core::aead tink::core::key_manager tink::core::keyset_handle tink::core::registry tink::util::status tink::util::statusor ) tink_cc_library( NAME aead_key_templates SRCS aead_key_templates.cc aead_key_templates.h DEPS absl::core_headers absl::strings tink::proto::aes_ctr_cc_proto tink::proto::aes_ctr_hmac_aead_cc_proto tink::proto::aes_eax_cc_proto tink::proto::aes_gcm_cc_proto tink::proto::aes_gcm_siv_cc_proto tink::proto::common_cc_proto tink::proto::hmac_cc_proto tink::proto::kms_envelope_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME aes_eax_key_manager SRCS aes_eax_key_manager.h DEPS absl::memory absl::status absl::strings tink::core::aead tink::core::key_type_manager tink::core::template_util tink::subtle::aes_eax_boringssl tink::subtle::random tink::util::constants tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::aes_eax_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME aes_gcm_key_manager SRCS aes_gcm_key_manager.h DEPS tink::aead::cord_aead absl::memory absl::status absl::strings tink::core::aead tink::core::key_type_manager tink::core::template_util tink::core::input_stream tink::aead::internal::cord_aes_gcm_boringssl tink::internal::fips_utils tink::subtle::aes_gcm_boringssl tink::subtle::random tink::util::constants tink::util::input_stream_util tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::aes_gcm_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME aes_gcm_siv_key_manager SRCS aes_gcm_siv_key_manager.h DEPS absl::memory absl::strings tink::core::aead tink::core::key_type_manager tink::core::template_util tink::subtle::aes_gcm_siv_boringssl tink::subtle::random tink::util::constants tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::aes_gcm_siv_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME aes_ctr_hmac_aead_key_manager SRCS aes_ctr_hmac_aead_key_manager.cc aes_ctr_hmac_aead_key_manager.h DEPS absl::memory absl::status absl::statusor absl::strings tink::core::aead tink::core::key_type_manager tink::core::template_util tink::core::input_stream tink::core::mac tink::internal::fips_utils tink::mac::hmac_key_manager tink::subtle::aes_ctr_boringssl tink::subtle::encrypt_then_authenticate tink::subtle::ind_cpa_cipher tink::subtle::random tink::util::constants tink::util::enums tink::util::input_stream_util tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::aes_ctr_cc_proto tink::proto::aes_ctr_hmac_aead_cc_proto tink::proto::common_cc_proto tink::proto::hmac_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME xchacha20_poly1305_key_manager SRCS xchacha20_poly1305_key_manager.h DEPS absl::memory absl::status absl::strings tink::core::aead tink::core::key_type_manager tink::core::template_util tink::core::input_stream tink::subtle::subtle tink::subtle::xchacha20_poly1305_boringssl tink::util::constants tink::util::input_stream_util tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::tink_cc_proto tink::proto::xchacha20_poly1305_cc_proto ) tink_cc_library( NAME kms_aead_key_manager SRCS kms_aead_key_manager.h DEPS absl::memory absl::status absl::strings tink::core::aead tink::core::key_type_manager tink::core::template_util tink::core::kms_client tink::core::kms_clients tink::util::constants tink::util::status tink::util::statusor tink::util::validation tink::proto::kms_aead_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME kms_envelope_aead SRCS kms_envelope_aead.cc kms_envelope_aead.h DEPS absl::endian absl::memory absl::status absl::strings tink::core::aead tink::core::registry tink::aead::internal::aead_util tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME kms_envelope_aead_key_manager SRCS kms_envelope_aead_key_manager.cc kms_envelope_aead_key_manager.h DEPS tink::aead::kms_envelope_aead absl::memory absl::status absl::strings tink::core::aead tink::core::key_type_manager tink::core::template_util tink::core::kms_client tink::core::kms_clients tink::aead::internal::aead_util tink::internal::fips_utils tink::util::constants tink::util::status tink::util::statusor tink::util::validation tink::proto::kms_envelope_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME mock_aead SRCS mock_aead.h DEPS gmock absl::strings tink::core::aead tink::util::statusor TESTONLY ) tink_cc_library( NAME failing_aead SRCS failing_aead.cc failing_aead.h DEPS absl::memory absl::status absl::strings tink::core::aead tink::util::status tink::util::statusor TESTONLY ) tink_cc_library( NAME aead_parameters SRCS aead_parameters.h DEPS tink::core::parameters ) tink_cc_library( NAME aead_key SRCS aead_key.h DEPS tink::aead::aead_parameters absl::strings tink::core::key ) tink_cc_library( NAME aes_gcm_parameters SRCS aes_gcm_parameters.cc aes_gcm_parameters.h DEPS tink::aead::aead_parameters absl::status absl::strings tink::core::parameters tink::util::status tink::util::statusor ) tink_cc_library( NAME aes_gcm_key SRCS aes_gcm_key.cc aes_gcm_key.h DEPS tink::aead::aead_key tink::aead::aes_gcm_parameters absl::status absl::strings absl::optional tink::core::key tink::core::partial_key_access_token tink::core::restricted_data tink::subtle::subtle_util tink::util::status tink::util::statusor ) tink_cc_library( NAME aes_gcm_proto_serialization SRCS aes_gcm_proto_serialization.cc aes_gcm_proto_serialization.h DEPS tink::aead::aes_gcm_key tink::aead::aes_gcm_parameters absl::core_headers absl::status absl::string_view absl::optional tink::core::partial_key_access tink::core::restricted_data tink::core::secret_key_access_token tink::internal::key_parser tink::internal::key_serializer tink::internal::mutable_serialization_registry tink::internal::parameters_parser tink::internal::parameters_serializer tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::util::secret_data tink::util::secret_proto tink::util::status tink::util::statusor tink::proto::aes_gcm_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME aes_gcm_siv_parameters SRCS aes_gcm_siv_parameters.cc aes_gcm_siv_parameters.h DEPS tink::aead::aead_parameters absl::status absl::strings tink::core::parameters tink::util::status tink::util::statusor ) tink_cc_library( NAME aes_gcm_siv_key SRCS aes_gcm_siv_key.cc aes_gcm_siv_key.h DEPS tink::aead::aead_key tink::aead::aes_gcm_siv_parameters absl::status absl::strings absl::optional tink::core::key tink::core::partial_key_access_token tink::core::restricted_data tink::subtle::subtle_util tink::util::status tink::util::statusor ) tink_cc_library( NAME aes_gcm_siv_proto_serialization SRCS aes_gcm_siv_proto_serialization.cc aes_gcm_siv_proto_serialization.h DEPS tink::aead::aes_gcm_siv_key tink::aead::aes_gcm_siv_parameters absl::core_headers absl::status absl::string_view absl::optional tink::core::partial_key_access tink::core::restricted_data tink::core::secret_key_access_token tink::internal::key_parser tink::internal::key_serializer tink::internal::mutable_serialization_registry tink::internal::parameters_parser tink::internal::parameters_serializer tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::util::status tink::util::statusor tink::proto::aes_gcm_siv_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME config_v0 SRCS config_v0.cc config_v0.h DEPS absl::check tink::core::configuration tink::aead::internal::config_v0 ) tink_cc_library( NAME key_gen_config_v0 SRCS key_gen_config_v0.cc key_gen_config_v0.h DEPS absl::check tink::core::key_gen_configuration tink::aead::internal::key_gen_config_v0 ) tink_cc_library( NAME aes_eax_parameters SRCS aes_eax_parameters.cc aes_eax_parameters.h DEPS tink::aead::aead_parameters absl::flat_hash_set absl::status absl::strings absl::optional tink::core::parameters tink::util::status tink::util::statusor ) tink_cc_library( NAME aes_eax_key SRCS aes_eax_key.cc aes_eax_key.h DEPS tink::aead::aead_key tink::aead::aes_eax_parameters absl::status absl::strings absl::string_view absl::optional tink::core::key tink::core::partial_key_access_token tink::core::restricted_data tink::subtle::subtle_util tink::util::status tink::util::statusor ) tink_cc_library( NAME aes_eax_proto_serialization SRCS aes_eax_proto_serialization.cc aes_eax_proto_serialization.h DEPS tink::aead::aes_eax_key tink::aead::aes_eax_parameters absl::core_headers absl::status absl::strings absl::string_view absl::optional tink::core::partial_key_access tink::core::restricted_data tink::core::secret_key_access_token tink::internal::key_parser tink::internal::key_serializer tink::internal::mutable_serialization_registry tink::internal::parameters_parser tink::internal::parameters_serializer tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::util::secret_data tink::util::secret_proto tink::util::status tink::util::statusor tink::proto::aes_eax_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME xchacha20_poly1305_parameters SRCS xchacha20_poly1305_parameters.cc xchacha20_poly1305_parameters.h DEPS tink::aead::aead_parameters absl::status tink::core::parameters tink::util::status tink::util::statusor ) tink_cc_library( NAME xchacha20_poly1305_key SRCS xchacha20_poly1305_key.cc xchacha20_poly1305_key.h DEPS tink::aead::aead_key tink::aead::xchacha20_poly1305_parameters absl::status absl::strings absl::optional tink::core::key tink::core::partial_key_access_token tink::core::restricted_data tink::subtle::subtle_util tink::util::status tink::util::statusor ) tink_cc_library( NAME xchacha20_poly1305_proto_serialization SRCS xchacha20_poly1305_proto_serialization.cc xchacha20_poly1305_proto_serialization.h DEPS tink::aead::xchacha20_poly1305_key tink::aead::xchacha20_poly1305_parameters absl::core_headers absl::status absl::string_view absl::optional tink::core::partial_key_access tink::core::restricted_data tink::core::secret_key_access_token tink::internal::key_parser tink::internal::key_serializer tink::internal::mutable_serialization_registry tink::internal::parameters_parser tink::internal::parameters_serializer tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::util::status tink::util::statusor tink::proto::tink_cc_proto tink::proto::xchacha20_poly1305_cc_proto ) tink_cc_library( NAME chacha20_poly1305_parameters SRCS chacha20_poly1305_parameters.cc chacha20_poly1305_parameters.h DEPS tink::aead::aead_parameters absl::status tink::core::parameters tink::util::status tink::util::statusor ) tink_cc_library( NAME chacha20_poly1305_key SRCS chacha20_poly1305_key.cc chacha20_poly1305_key.h DEPS tink::aead::aead_key tink::aead::chacha20_poly1305_parameters absl::status absl::strings absl::optional tink::core::key tink::core::partial_key_access_token tink::core::restricted_data tink::subtle::subtle_util tink::util::status tink::util::statusor ) tink_cc_library( NAME chacha20_poly1305_proto_serialization SRCS chacha20_poly1305_proto_serialization.cc chacha20_poly1305_proto_serialization.h DEPS tink::aead::chacha20_poly1305_key tink::aead::chacha20_poly1305_parameters absl::core_headers absl::status absl::string_view absl::optional tink::core::partial_key_access tink::core::restricted_data tink::core::secret_key_access_token tink::internal::key_parser tink::internal::key_serializer tink::internal::mutable_serialization_registry tink::internal::parameters_parser tink::internal::parameters_serializer tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::util::status tink::util::statusor tink::proto::chacha20_poly1305_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME aes_ctr_hmac_aead_parameters SRCS aes_ctr_hmac_aead_parameters.cc aes_ctr_hmac_aead_parameters.h DEPS tink::aead::aead_parameters absl::algorithm_container absl::flat_hash_map absl::status absl::strings absl::optional tink::core::parameters tink::util::status tink::util::statusor ) tink_cc_library( NAME aes_ctr_hmac_aead_key SRCS aes_ctr_hmac_aead_key.cc aes_ctr_hmac_aead_key.h DEPS tink::aead::aead_key tink::aead::aes_ctr_hmac_aead_parameters absl::status absl::strings absl::string_view absl::optional tink::core::key tink::core::partial_key_access_token tink::core::restricted_data tink::subtle::subtle_util tink::util::status tink::util::statusor ) tink_cc_library( NAME aes_ctr_hmac_aead_proto_serialization SRCS aes_ctr_hmac_aead_proto_serialization.cc aes_ctr_hmac_aead_proto_serialization.h DEPS tink::aead::aes_ctr_hmac_aead_key tink::aead::aes_ctr_hmac_aead_parameters absl::core_headers absl::status absl::strings absl::string_view absl::optional tink::core::partial_key_access tink::core::restricted_data tink::core::secret_key_access_token tink::internal::key_parser tink::internal::key_serializer tink::internal::mutable_serialization_registry tink::internal::parameters_parser tink::internal::parameters_serializer tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::util::secret_data tink::util::secret_proto tink::util::status tink::util::statusor tink::proto::aes_ctr_cc_proto tink::proto::aes_ctr_hmac_aead_cc_proto tink::proto::common_cc_proto tink::proto::hmac_cc_proto tink::proto::tink_cc_proto ) # tests tink_cc_test( NAME aead_wrapper_test SRCS aead_wrapper_test.cc DEPS tink::aead::aead_wrapper tink::aead::mock_aead gmock absl::flat_hash_map absl::memory absl::status absl::statusor absl::strings tink::core::aead tink::core::crypto_format tink::core::primitive_set tink::core::registry tink::internal::registry_impl tink::monitoring::monitoring tink::monitoring::monitoring_client_mocks tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::tink_cc_proto ) tink_cc_test( NAME aead_config_test SRCS aead_config_test.cc DEPS tink::aead::aead_config tink::aead::aead_key_templates tink::aead::aes_ctr_hmac_aead_key tink::aead::aes_ctr_hmac_aead_parameters tink::aead::aes_eax_key tink::aead::aes_eax_parameters tink::aead::aes_gcm_key tink::aead::aes_gcm_key_manager tink::aead::aes_gcm_parameters tink::aead::aes_gcm_siv_key tink::aead::aes_gcm_siv_parameters tink::aead::key_gen_config_v0 tink::aead::xchacha20_poly1305_key tink::aead::xchacha20_poly1305_parameters gmock absl::status tink::core::aead tink::core::insecure_secret_key_access tink::core::key tink::core::key_status tink::core::keyset_handle tink::core::keyset_handle_builder tink::core::parameters tink::core::partial_key_access tink::core::registry tink::core::restricted_data tink::config::global_registry tink::config::tink_fips tink::internal::fips_utils tink::internal::legacy_proto_key tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::internal::serialization tink::subtle::random tink::util::statusor tink::util::test_matchers tink::proto::aes_eax_cc_proto tink::proto::aes_gcm_cc_proto tink::proto::aes_gcm_siv_cc_proto tink::proto::tink_cc_proto tink::proto::xchacha20_poly1305_cc_proto ) tink_cc_test( NAME aead_factory_test SRCS aead_factory_test.cc DEPS tink::aead::aead_config tink::aead::aead_factory tink::aead::aes_gcm_key_manager gmock absl::status absl::strings tink::core::aead tink::core::crypto_format tink::core::keyset_handle tink::internal::key_info tink::util::status tink::util::statusor tink::util::test_keyset_handle tink::util::test_util tink::proto::aes_gcm_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME aead_key_templates_test SRCS aead_key_templates_test.cc DEPS tink::aead::aead_config tink::aead::aead_key_templates tink::aead::aes_ctr_hmac_aead_key_manager tink::aead::aes_eax_key_manager tink::aead::aes_gcm_key_manager tink::aead::aes_gcm_siv_key_manager tink::aead::kms_envelope_aead_key_manager tink::aead::xchacha20_poly1305_key_manager gmock absl::status absl::statusor tink::core::aead tink::core::key_manager_impl tink::core::key_manager tink::core::keyset_handle tink::config::global_registry tink::subtle::aead_test_util tink::util::fake_kms_client tink::util::status tink::util::test_matchers tink::proto::aes_ctr_cc_proto tink::proto::aes_ctr_hmac_aead_cc_proto tink::proto::aes_eax_cc_proto tink::proto::aes_gcm_cc_proto tink::proto::aes_gcm_siv_cc_proto tink::proto::common_cc_proto tink::proto::hmac_cc_proto tink::proto::kms_envelope_cc_proto tink::proto::tink_cc_proto tink::proto::xchacha20_poly1305_cc_proto ) tink_cc_test( NAME aes_eax_key_manager_test SRCS aes_eax_key_manager_test.cc DEPS tink::aead::aes_eax_key_manager gmock tink::core::aead tink::subtle::aead_test_util tink::subtle::aes_eax_boringssl tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::aes_eax_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME aes_gcm_key_manager_test SRCS aes_gcm_key_manager_test.cc DEPS tink::aead::aes_gcm_key_manager tink::aead::cord_aead gmock absl::memory absl::status tink::core::aead tink::aead::internal::cord_aes_gcm_boringssl tink::subtle::aead_test_util tink::subtle::aes_gcm_boringssl tink::util::istream_input_stream tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::aes_gcm_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME aes_gcm_siv_key_manager_test SRCS aes_gcm_siv_key_manager_test.cc DEPS tink::aead::aes_gcm_siv_key_manager gmock absl::status tink::core::aead tink::internal::ssl_util tink::subtle::aead_test_util tink::subtle::aes_gcm_siv_boringssl tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::aes_gcm_siv_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME aes_ctr_hmac_aead_key_manager_test SRCS aes_ctr_hmac_aead_key_manager_test.cc DEPS tink::aead::aes_ctr_hmac_aead_key_manager gmock absl::memory absl::status tink::core::aead tink::subtle::subtle tink::subtle::aead_test_util tink::subtle::aes_ctr_boringssl tink::util::enums tink::util::istream_input_stream tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::aes_ctr_cc_proto tink::proto::aes_ctr_hmac_aead_cc_proto tink::proto::common_cc_proto tink::proto::hmac_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME xchacha20_poly1305_key_manager_test SRCS xchacha20_poly1305_key_manager_test.cc DEPS tink::aead::xchacha20_poly1305_key_manager gmock absl::memory absl::status tink::core::aead tink::internal::ssl_util tink::subtle::aead_test_util tink::subtle::xchacha20_poly1305_boringssl tink::util::istream_input_stream tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto tink::proto::xchacha20_poly1305_cc_proto ) tink_cc_test( NAME kms_aead_key_manager_test SRCS kms_aead_key_manager_test.cc DEPS tink::aead::kms_aead_key_manager gmock absl::memory absl::status tink::core::aead tink::core::kms_client tink::core::kms_clients tink::subtle::aead_test_util tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::kms_aead_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME kms_envelope_aead_test SRCS kms_envelope_aead_test.cc DEPS tink::aead::aead_config tink::aead::aead_key_templates tink::aead::kms_envelope_aead gmock absl::endian absl::memory absl::status absl::strings tink::core::aead tink::core::keyset_handle tink::core::registry tink::config::global_registry tink::internal::ssl_util tink::mac::mac_key_templates tink::util::fake_kms_client tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::aes_gcm_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME kms_envelope_aead_key_manager_test SRCS kms_envelope_aead_key_manager_test.cc DEPS tink::aead::aead_config tink::aead::aead_key_templates tink::aead::aes_eax_key_manager tink::aead::kms_envelope_aead tink::aead::kms_envelope_aead_key_manager gmock absl::memory absl::status tink::core::aead tink::core::keyset_handle tink::core::kms_client tink::core::kms_clients tink::core::registry tink::config::global_registry tink::mac::mac_key_templates tink::subtle::aead_test_util tink::util::fake_kms_client tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::kms_envelope_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME cord_aead_wrapper_test SRCS cord_aead_wrapper_test.cc DEPS tink::aead::cord_aead tink::aead::cord_aead_wrapper gmock absl::memory absl::status absl::strings absl::cord tink::core::primitive_set tink::util::status tink::util::test_matchers tink::util::test_util tink::proto::tink_cc_proto ) tink_cc_test( NAME failing_aead_test SRCS failing_aead_test.cc DEPS tink::aead::failing_aead gmock absl::status tink::core::aead tink::util::test_matchers ) tink_cc_test( NAME aes_gcm_parameters_test SRCS aes_gcm_parameters_test.cc DEPS tink::aead::aes_gcm_parameters gmock absl::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME aes_gcm_key_test SRCS aes_gcm_key_test.cc DEPS tink::aead::aes_gcm_key tink::aead::aes_gcm_parameters gmock absl::status absl::optional tink::core::partial_key_access tink::core::restricted_data tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME aes_gcm_proto_serialization_test SRCS aes_gcm_proto_serialization_test.cc DEPS tink::aead::aes_gcm_key tink::aead::aes_gcm_parameters tink::aead::aes_gcm_proto_serialization gmock absl::status absl::optional tink::core::insecure_secret_key_access tink::core::key tink::core::parameters tink::core::partial_key_access tink::core::restricted_data tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::internal::serialization tink::subtle::random tink::util::statusor tink::util::test_matchers tink::proto::aes_gcm_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME aes_gcm_siv_parameters_test SRCS aes_gcm_siv_parameters_test.cc DEPS tink::aead::aes_gcm_siv_parameters gmock absl::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME aes_gcm_siv_key_test SRCS aes_gcm_siv_key_test.cc DEPS tink::aead::aes_gcm_siv_key tink::aead::aes_gcm_siv_parameters gmock absl::status absl::optional tink::core::partial_key_access tink::core::restricted_data tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME aes_gcm_siv_proto_serialization_test SRCS aes_gcm_siv_proto_serialization_test.cc DEPS tink::aead::aes_gcm_siv_key tink::aead::aes_gcm_siv_parameters tink::aead::aes_gcm_siv_proto_serialization gmock absl::status absl::optional tink::core::insecure_secret_key_access tink::core::key tink::core::parameters tink::core::partial_key_access tink::core::restricted_data tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::internal::serialization tink::subtle::random tink::util::statusor tink::util::test_matchers tink::proto::aes_gcm_siv_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME config_v0_test SRCS config_v0_test.cc DEPS tink::aead::aead_key_templates tink::aead::config_v0 tink::aead::key_gen_config_v0 gmock tink::core::aead tink::core::keyset_handle tink::internal::ssl_util tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) tink_cc_test( NAME aes_eax_parameters_test SRCS aes_eax_parameters_test.cc DEPS tink::aead::aes_eax_parameters gmock absl::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME aes_eax_key_test SRCS aes_eax_key_test.cc DEPS tink::aead::aes_eax_key tink::aead::aes_eax_parameters gmock absl::status absl::optional tink::core::partial_key_access tink::core::restricted_data tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME aes_eax_proto_serialization_test SRCS aes_eax_proto_serialization_test.cc DEPS tink::aead::aes_eax_key tink::aead::aes_eax_parameters tink::aead::aes_eax_proto_serialization gmock absl::status absl::string_view absl::optional tink::core::insecure_secret_key_access tink::core::key tink::core::parameters tink::core::partial_key_access tink::core::restricted_data tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::internal::serialization tink::subtle::random tink::util::statusor tink::util::test_matchers tink::proto::aes_eax_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME xchacha20_poly1305_parameters_test SRCS xchacha20_poly1305_parameters_test.cc DEPS tink::aead::xchacha20_poly1305_parameters gmock absl::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME xchacha20_poly1305_key_test SRCS xchacha20_poly1305_key_test.cc DEPS tink::aead::xchacha20_poly1305_key tink::aead::xchacha20_poly1305_parameters gmock absl::status absl::optional tink::core::partial_key_access tink::core::restricted_data tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME xchacha20_poly1305_proto_serialization_test SRCS xchacha20_poly1305_proto_serialization_test.cc DEPS tink::aead::xchacha20_poly1305_key tink::aead::xchacha20_poly1305_parameters tink::aead::xchacha20_poly1305_proto_serialization gmock absl::status absl::string_view absl::optional tink::core::insecure_secret_key_access tink::core::key tink::core::parameters tink::core::partial_key_access tink::core::restricted_data tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::internal::serialization tink::subtle::random tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto tink::proto::xchacha20_poly1305_cc_proto ) tink_cc_test( NAME chacha20_poly1305_parameters_test SRCS chacha20_poly1305_parameters_test.cc DEPS tink::aead::chacha20_poly1305_parameters gmock absl::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME chacha20_poly1305_key_test SRCS chacha20_poly1305_key_test.cc DEPS tink::aead::chacha20_poly1305_key tink::aead::chacha20_poly1305_parameters gmock absl::status absl::optional tink::core::partial_key_access tink::core::restricted_data tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME chacha20_poly1305_proto_serialization_test SRCS chacha20_poly1305_proto_serialization_test.cc DEPS tink::aead::chacha20_poly1305_key tink::aead::chacha20_poly1305_parameters tink::aead::chacha20_poly1305_proto_serialization gmock absl::status absl::string_view absl::optional tink::core::insecure_secret_key_access tink::core::key tink::core::parameters tink::core::partial_key_access tink::core::restricted_data tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::internal::serialization tink::subtle::random tink::util::statusor tink::util::test_matchers tink::proto::chacha20_poly1305_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME aes_ctr_hmac_aead_parameters_test SRCS aes_ctr_hmac_aead_parameters_test.cc DEPS tink::aead::aes_ctr_hmac_aead_parameters gmock absl::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME aes_ctr_hmac_aead_key_test SRCS aes_ctr_hmac_aead_key_test.cc DEPS tink::aead::aes_ctr_hmac_aead_key tink::aead::aes_ctr_hmac_aead_parameters gmock absl::status absl::optional tink::core::partial_key_access tink::core::restricted_data tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME aes_ctr_hmac_aead_proto_serialization_test SRCS aes_ctr_hmac_aead_proto_serialization_test.cc DEPS tink::aead::aes_ctr_hmac_aead_key tink::aead::aes_ctr_hmac_aead_parameters tink::aead::aes_ctr_hmac_aead_proto_serialization gmock absl::status absl::string_view absl::optional tink::core::insecure_secret_key_access tink::core::key tink::core::parameters tink::core::partial_key_access tink::core::restricted_data tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::internal::serialization tink::subtle::random tink::util::statusor tink::util::test_matchers tink::proto::aes_ctr_cc_proto tink::proto::aes_ctr_hmac_aead_cc_proto tink::proto::common_cc_proto tink::proto::hmac_cc_proto tink::proto::tink_cc_proto ) ================================================ FILE: cc/aead/aead_config.cc ================================================ // Copyright 2017 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aead_config.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/aead/aead_wrapper.h" #include "tink/aead/aes_ctr_hmac_aead_key_manager.h" #include "tink/aead/aes_ctr_hmac_aead_proto_serialization.h" #include "tink/aead/aes_eax_key_manager.h" #include "tink/aead/aes_eax_proto_serialization.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/aead/aes_gcm_proto_serialization.h" #include "tink/aead/aes_gcm_siv_key_manager.h" #include "tink/aead/aes_gcm_siv_proto_serialization.h" #include "tink/aead/kms_aead_key_manager.h" #include "tink/aead/kms_envelope_aead_key_manager.h" #include "tink/aead/xchacha20_poly1305_key_manager.h" #include "tink/aead/xchacha20_poly1305_proto_serialization.h" #include "tink/config/tink_fips.h" #include "tink/mac/mac_config.h" #include "tink/registry.h" #include "tink/util/status.h" #include "proto/config.pb.h" namespace crypto { namespace tink { // static util::Status AeadConfig::Register() { auto status = MacConfig::Register(); if (!status.ok()) { return status; } // Register primitive wrapper. status = Registry::RegisterPrimitiveWrapper(absl::make_unique()); if (!status.ok()) { return status; } // Register key managers which utilize the FIPS validated BoringCrypto // implementations. status = Registry::RegisterKeyTypeManager( absl::make_unique(), true); if (!status.ok()) { return status; } status = Registry::RegisterKeyTypeManager( absl::make_unique(), true); if (!status.ok()) { return status; } status = RegisterAesCtrHmacAeadProtoSerialization(); if (!status.ok()) { return status; } status = RegisterAesGcmProtoSerialization(); if (!status.ok()) { return status; } if (IsFipsModeEnabled()) { return util::OkStatus(); } // Register all the other key managers. status = Registry::RegisterKeyTypeManager( absl::make_unique(), true); if (!status.ok()) { return status; } status = Registry::RegisterKeyTypeManager( absl::make_unique(), true); if (!status.ok()) { return status; } status = Registry::RegisterKeyTypeManager( absl::make_unique(), true); if (!status.ok()) { return status; } status = Registry::RegisterKeyTypeManager( absl::make_unique(), true); if (!status.ok()) { return status; } status = Registry::RegisterKeyTypeManager( absl::make_unique(), true); if (!status.ok()) { return status; } status = RegisterAesGcmSivProtoSerialization(); if (!status.ok()) { return status; } status = RegisterAesEaxProtoSerialization(); if (!status.ok()) { return status; } status = RegisterXChaCha20Poly1305ProtoSerialization(); if (!status.ok()) { return status; } return util::OkStatus(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aead_config.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_AEAD_CONFIG_H_ #define TINK_AEAD_AEAD_CONFIG_H_ #include "absl/base/attributes.h" #include "tink/util/status.h" #include "proto/config.pb.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Static methods and constants for registering with the Registry // all instances of Aead key types supported in a particular release of Tink. // // To register all Aead key types from the current Tink release one can do: // // auto status = AeadConfig::Register(); // class AeadConfig { public: // Registers Aead primitive wrapper and key managers for all Aead key types // from the current Tink release. static crypto::tink::util::Status Register(); private: AeadConfig() {} }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_AEAD_CONFIG_H_ ================================================ FILE: cc/aead/aead_config_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aead_config.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/aead.h" #include "tink/aead/aead_key_templates.h" #include "tink/aead/aes_ctr_hmac_aead_key.h" #include "tink/aead/aes_ctr_hmac_aead_parameters.h" #include "tink/aead/aes_eax_key.h" #include "tink/aead/aes_eax_parameters.h" #include "tink/aead/aes_gcm_key.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/aead/aes_gcm_parameters.h" #include "tink/aead/aes_gcm_siv_key.h" #include "tink/aead/aes_gcm_siv_parameters.h" #include "tink/aead/key_gen_config_v0.h" #include "tink/aead/xchacha20_poly1305_key.h" #include "tink/aead/xchacha20_poly1305_parameters.h" #include "tink/config/global_registry.h" #include "tink/config/tink_fips.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/fips_utils.h" #include "tink/internal/legacy_proto_key.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/key_status.h" #include "tink/keyset_handle.h" #include "tink/keyset_handle_builder.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/registry.h" #include "tink/restricted_data.h" #include "tink/subtle/random.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/aes_eax.pb.h" #include "proto/aes_gcm.pb.h" #include "proto/aes_gcm_siv.pb.h" #include "proto/tink.pb.h" #include "proto/xchacha20_poly1305.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::OutputPrefixType; using ::testing::HasSubstr; using ::testing::IsNull; using ::testing::Not; using ::testing::Test; class AeadConfigTest : public Test { protected: void SetUp() override { Registry::Reset(); internal::MutableSerializationRegistry::GlobalInstance().Reset(); } }; TEST_F(AeadConfigTest, RegisterWorks) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT(Registry::get_key_manager(AesGcmKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT(AeadConfig::Register(), IsOk()); EXPECT_THAT(Registry::get_key_manager(AesGcmKeyManager().get_key_type()) .status(), IsOk()); } // Tests that the AeadWrapper has been properly registered and we can wrap // primitives. TEST_F(AeadConfigTest, WrappersRegistered) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } ASSERT_THAT(AeadConfig::Register(), IsOk()); StatusOr> keyset_handle = KeysetHandle::GenerateNew(AeadKeyTemplates::Aes128Gcm(), KeyGenConfigGlobalRegistry()); ASSERT_THAT(keyset_handle.status(), IsOk()); StatusOr> aead = (*keyset_handle) ->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(aead.status(), IsOk()); ASSERT_THAT(*aead, Not(IsNull())); } // FIPS-only mode tests TEST_F(AeadConfigTest, RegisterNonFipsTemplates) { if (!IsFipsModeEnabled() || !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only supported in FIPS-only mode with BoringCrypto."; } ASSERT_THAT(AeadConfig::Register(), IsOk()); std::list non_fips_key_templates = { AeadKeyTemplates::Aes128Eax(), AeadKeyTemplates::Aes256Eax(), AeadKeyTemplates::Aes128GcmSiv(), AeadKeyTemplates::Aes256GcmSiv(), AeadKeyTemplates::XChaCha20Poly1305(), }; for (auto key_template : non_fips_key_templates) { auto new_keyset_handle_result = KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()); EXPECT_THAT(new_keyset_handle_result.status(), StatusIs(absl::StatusCode::kNotFound)); } } TEST_F(AeadConfigTest, RegisterFipsValidTemplates) { if (!IsFipsModeEnabled() || !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only supported in FIPS-only mode with BoringCrypto."; } EXPECT_THAT(AeadConfig::Register(), IsOk()); std::list fips_key_templates = { AeadKeyTemplates::Aes128Gcm(), AeadKeyTemplates::Aes256Gcm(), AeadKeyTemplates::Aes128CtrHmacSha256(), AeadKeyTemplates::Aes256CtrHmacSha256(), }; for (auto key_template : fips_key_templates) { auto new_keyset_handle_result = KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()); EXPECT_THAT(new_keyset_handle_result, IsOk()); } } TEST_F(AeadConfigTest, RegisterFailsIfBoringCryptoNotAvailable) { if (!IsFipsModeEnabled() || internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only supported in FIPS-only mode with BoringCrypto not available."; } EXPECT_THAT(Registry::get_key_manager(AesGcmKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT(AeadConfig::Register(), StatusIs(absl::StatusCode::kInternal)); } TEST_F(AeadConfigTest, AesGcmProtoParamsSerializationRegistered) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::StatusOr proto_params_serialization = internal::ProtoParametersSerialization::Create( AeadKeyTemplates::Aes256Gcm()); ASSERT_THAT(proto_params_serialization, IsOk()); util::StatusOr> parsed_params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr params = AesGcmParameters::Builder() .SetVariant(AesGcmParameters::Variant::kTink) .SetKeySizeInBytes(32) .SetIvSizeInBytes(12) .SetTagSizeInBytes(16) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr> serialized_params = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params.status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(AeadConfig::Register(), IsOk()); util::StatusOr> parsed_params2 = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params2, IsOk()); util::StatusOr> serialized_params2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params2, IsOk()); } TEST_F(AeadConfigTest, AesGcmProtoKeySerializationRegistered) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } google::crypto::tink::AesGcmKey key_proto; key_proto.set_version(0); key_proto.set_key_value(subtle::Random::GetRandomBytes(32)); util::StatusOr proto_key_serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesGcmKey", RestrictedData(key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()), KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/123); ASSERT_THAT(proto_key_serialization, IsOk()); util::StatusOr> parsed_key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr params = AesGcmParameters::Builder() .SetVariant(AesGcmParameters::Variant::kTink) .SetKeySizeInBytes(32) .SetIvSizeInBytes(12) .SetTagSizeInBytes(16) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr key = AesGcmKey::Create(*params, RestrictedData(subtle::Random::GetRandomBytes(32), InsecureSecretKeyAccess::Get()), /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialized_key = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key.status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(AeadConfig::Register(), IsOk()); util::StatusOr> parsed_key2 = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key2, IsOk()); util::StatusOr> serialized_key2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key2, IsOk()); } TEST_F(AeadConfigTest, AesGcmSivProtoParamsSerializationRegistered) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::StatusOr proto_params_serialization = internal::ProtoParametersSerialization::Create( AeadKeyTemplates::Aes256GcmSiv()); ASSERT_THAT(proto_params_serialization, IsOk()); util::StatusOr> parsed_params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr params = AesGcmSivParameters::Create( /*key_size_in_bytes=*/32, AesGcmSivParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); util::StatusOr> serialized_params = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params.status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(AeadConfig::Register(), IsOk()); util::StatusOr> parsed_params2 = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params2, IsOk()); util::StatusOr> serialized_params2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params2, IsOk()); } TEST_F(AeadConfigTest, AesGcmSivProtoKeySerializationRegistered) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } google::crypto::tink::AesGcmSivKey key_proto; key_proto.set_version(0); key_proto.set_key_value(subtle::Random::GetRandomBytes(32)); util::StatusOr proto_key_serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesGcmSivKey", RestrictedData(key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()), KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/123); ASSERT_THAT(proto_key_serialization, IsOk()); util::StatusOr> parsed_key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr params = AesGcmSivParameters::Create( /*key_size_in_bytes=*/32, AesGcmSivParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); util::StatusOr key = AesGcmSivKey::Create(*params, RestrictedData(subtle::Random::GetRandomBytes(32), InsecureSecretKeyAccess::Get()), /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialized_key = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key.status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(AeadConfig::Register(), IsOk()); util::StatusOr> parsed_key2 = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key2, IsOk()); util::StatusOr> serialized_key2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key2, IsOk()); } TEST_F(AeadConfigTest, AesEaxProtoParamsSerializationRegistered) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::StatusOr proto_params_serialization = internal::ProtoParametersSerialization::Create( AeadKeyTemplates::Aes256Eax()); ASSERT_THAT(proto_params_serialization, IsOk()); util::StatusOr> parsed_params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr params = AesEaxParameters::Builder() .SetVariant(AesEaxParameters::Variant::kTink) .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr> serialized_params = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params.status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(AeadConfig::Register(), IsOk()); util::StatusOr> parsed_params2 = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params2, IsOk()); util::StatusOr> serialized_params2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params2, IsOk()); } TEST_F(AeadConfigTest, AesEaxProtoKeySerializationRegistered) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } google::crypto::tink::AesEaxKey key_proto; key_proto.set_version(0); key_proto.mutable_params()->set_iv_size(16); key_proto.set_key_value(subtle::Random::GetRandomBytes(32)); util::StatusOr proto_key_serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesEaxKey", RestrictedData(key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()), KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/123); ASSERT_THAT(proto_key_serialization, IsOk()); util::StatusOr> parsed_key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr params = AesEaxParameters::Builder() .SetVariant(AesEaxParameters::Variant::kTink) .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr key = AesEaxKey::Create(*params, RestrictedData(subtle::Random::GetRandomBytes(32), InsecureSecretKeyAccess::Get()), /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialized_key = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key.status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(AeadConfig::Register(), IsOk()); util::StatusOr> parsed_key2 = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key2, IsOk()); util::StatusOr> serialized_key2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key2, IsOk()); } TEST_F(AeadConfigTest, XChaCha20Poly1305ProtoParamsSerializationRegistered) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } // TODO: b/325507124 - Rewrite tests using parameters proto format API. util::StatusOr proto_params_serialization = internal::ProtoParametersSerialization::Create( AeadKeyTemplates::XChaCha20Poly1305()); ASSERT_THAT(proto_params_serialization, IsOk()); util::StatusOr> parsed_params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr params = XChaCha20Poly1305Parameters::Create( XChaCha20Poly1305Parameters::Variant::kTink); ASSERT_THAT(params, IsOk()); util::StatusOr> serialized_params = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params.status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(AeadConfig::Register(), IsOk()); util::StatusOr> parsed_params2 = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params2, IsOk()); util::StatusOr> serialized_params2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params2, IsOk()); } TEST_F(AeadConfigTest, XChaCha20Poly1305ProtoKeySerializationRegistered) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::StatusOr> handle = KeysetHandle::GenerateNew(AeadKeyTemplates::XChaCha20Poly1305(), KeyGenConfigAeadV0()); ASSERT_THAT(handle, IsOk()); // Fails to parse this key type, so falls back to legacy proto key. const internal::LegacyProtoKey* legacy_proto_key_from_handle = reinterpret_cast( (*handle)->GetPrimary().GetKey().get()); EXPECT_THAT(legacy_proto_key_from_handle, Not(IsNull())); util::StatusOr key = XChaCha20Poly1305Key::Create( XChaCha20Poly1305Parameters::Variant::kTink, RestrictedData(subtle::Random::GetRandomBytes(32), InsecureSecretKeyAccess::Get()), /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); // Fails to serialize this key type. EXPECT_THAT(KeysetHandleBuilder() .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableKey( *key, KeyStatus::kEnabled, /*is_primary=*/true)) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Failed to serialize"))); ASSERT_THAT(AeadConfig::Register(), IsOk()); const XChaCha20Poly1305Key* key_from_handle = reinterpret_cast( (*handle)->GetPrimary().GetKey().get()); EXPECT_THAT(key_from_handle, Not(IsNull())); EXPECT_THAT(KeysetHandleBuilder() .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableKey( *key, KeyStatus::kEnabled, /*is_primary=*/true)) .Build(), IsOk()); } TEST_F(AeadConfigTest, AesCtrHmacAeadProtoParamsSerializationRegistered) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } // TODO: b/325507124 - Rewrite tests using parameters proto format API. util::StatusOr proto_params_serialization = internal::ProtoParametersSerialization::Create( AeadKeyTemplates::Aes256CtrHmacSha256()); ASSERT_THAT(proto_params_serialization, IsOk()); util::StatusOr> parsed_params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr params = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(32) .SetHmacKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesCtrHmacAeadParameters::Variant::kTink) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr> serialized_params = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params.status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(AeadConfig::Register(), IsOk()); util::StatusOr> parsed_params2 = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params2, IsOk()); util::StatusOr> serialized_params2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params2, IsOk()); } TEST_F(AeadConfigTest, AesCtrHmacAeadProtoKeySerializationRegistered) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::StatusOr> handle = KeysetHandle::GenerateNew(AeadKeyTemplates::Aes256CtrHmacSha256(), KeyGenConfigAeadV0()); ASSERT_THAT(handle, IsOk()); // Failed to parse this key type, so fell back to legacy proto key. EXPECT_THAT(dynamic_cast( (*handle)->GetPrimary().GetKey().get()), Not(IsNull())); util::StatusOr params = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(32) .SetHmacKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesCtrHmacAeadParameters::Variant::kTink) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr key = AesCtrHmacAeadKey::Builder() .SetParameters(*params) .SetAesKeyBytes(RestrictedData(subtle::Random::GetRandomBytes(32), InsecureSecretKeyAccess::Get())) .SetHmacKeyBytes(RestrictedData(subtle::Random::GetRandomBytes(32), InsecureSecretKeyAccess::Get())) .SetIdRequirement(123) .Build(GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); // Fails to serialize this key type. EXPECT_THAT(KeysetHandleBuilder() .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableKey( *key, KeyStatus::kEnabled, /*is_primary=*/true)) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Failed to serialize"))); ASSERT_THAT(AeadConfig::Register(), IsOk()); util::StatusOr> handle2 = KeysetHandle::GenerateNew(AeadKeyTemplates::Aes256CtrHmacSha256(), KeyGenConfigAeadV0()); ASSERT_THAT(handle2, IsOk()); // Parsing now creates the right key type. EXPECT_THAT(dynamic_cast( (*handle2)->GetPrimary().GetKey().get()), Not(IsNull())); EXPECT_THAT(KeysetHandleBuilder() .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableKey( *key, KeyStatus::kEnabled, /*is_primary=*/true)) .Build(), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aead_factory.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aead_factory.h" #include #include "absl/memory/memory.h" #include "tink/aead.h" #include "tink/aead/aead_wrapper.h" #include "tink/key_manager.h" #include "tink/keyset_handle.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // NOLINTBEGIN(whitespace/line_length) (Formatted when commented in) // TINK-PENDING-REMOVAL-IN-3.0.0-START // static util::StatusOr> AeadFactory::GetPrimitive( const KeysetHandle& keyset_handle) { util::Status status = Registry::RegisterPrimitiveWrapper(absl::make_unique()); if (!status.ok()) { return status; } return keyset_handle.GetPrimitive(ConfigGlobalRegistry()); } // static util::StatusOr> AeadFactory::GetPrimitive( const KeysetHandle& keyset_handle, const KeyManager* custom_key_manager) { util::Status status = Registry::RegisterPrimitiveWrapper(absl::make_unique()); if (!status.ok()) { return status; } return keyset_handle.GetPrimitive(custom_key_manager); } // TINK-PENDING-REMOVAL-IN-3.0.0-END // NOLINTEND(whitespace/line_length) } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aead_factory.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_AEAD_FACTORY_H_ #define TINK_AEAD_AEAD_FACTORY_H_ #include #include "absl/base/attributes.h" #include "tink/aead.h" #include "tink/key_manager.h" #include "tink/keyset_handle.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // This class is deprecated. Call keyset_handle->GetPrimitive() instead. // // Note that in order to for this change to be safe, the AeadSetWrapper has to // be registered in your binary before this call. This happens automatically if // you call one of // * AeadConfig::Register() // * HybridConfig::Register() // * TinkConfig::Register() // NOLINTBEGIN(whitespace/line_length) (Formatted when commented in) // TINK-PENDING-REMOVAL-IN-3.0.0-START class ABSL_DEPRECATED( "Call GetPrimitive() on the keyset_handle after registering the " "AeadWrapper instead.") AeadFactory { public: // Returns an Aead-primitive that uses key material from the keyset // specified via 'keyset_handle'. static crypto::tink::util::StatusOr> GetPrimitive( const KeysetHandle& keyset_handle); // Returns an Aead-primitive that uses key material from the keyset // specified via 'keyset_handle' and is instantiated by the given // 'custom_key_manager' (instead of the key manager from the Registry). static crypto::tink::util::StatusOr> GetPrimitive( const KeysetHandle& keyset_handle, const KeyManager* custom_key_manager); private: AeadFactory() {} }; // TINK-PENDING-REMOVAL-IN-3.0.0-END // NOLINTEND(whitespace/line_length) } // namespace tink } // namespace crypto #endif // TINK_AEAD_AEAD_FACTORY_H_ ================================================ FILE: cc/aead/aead_factory_test.cc ================================================ // Copyright 2017 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aead_factory.h" #include #include #include #include #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/aead/aead_config.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/crypto_format.h" #include "tink/internal/key_info.h" #include "tink/keyset_handle.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_keyset_handle.h" #include "tink/util/test_util.h" #include "proto/aes_gcm.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { // NOLINTBEGIN(whitespace/line_length) (Formatted when commented in) // TINK-PENDING-REMOVAL-IN-3.0.0-START using crypto::tink::test::AddRawKey; using crypto::tink::test::AddTinkKey; using google::crypto::tink::AesGcmKey; using google::crypto::tink::AesGcmKeyFormat; using google::crypto::tink::KeyData; using google::crypto::tink::Keyset; using google::crypto::tink::KeyStatusType; class AeadFactoryTest : public ::testing::Test { }; TEST_F(AeadFactoryTest, testBasic) { Keyset keyset; auto aead_result = AeadFactory::GetPrimitive(*TestKeysetHandle::GetKeysetHandle(keyset)); EXPECT_FALSE(aead_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, aead_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "at least one key", std::string(aead_result.status().message())); } TEST_F(AeadFactoryTest, testPrimitive) { // Prepare a template for generating keys for a Keyset. std::string key_type = AesGcmKeyManager().get_key_type(); AesGcmKeyFormat key_format; key_format.set_key_size(16); // Prepare a Keyset. Keyset keyset; uint32_t key_id_1 = 1234543; AesGcmKey new_key = AesGcmKeyManager().CreateKey(key_format).value(); AddTinkKey(key_type, key_id_1, new_key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); uint32_t key_id_2 = 726329; new_key = AesGcmKeyManager().CreateKey(key_format).value(); AddRawKey(key_type, key_id_2, new_key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); uint32_t key_id_3 = 7213743; new_key = AesGcmKeyManager().CreateKey(key_format).value(); AddTinkKey(key_type, key_id_3, new_key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(key_id_3); // Initialize the registry. ASSERT_TRUE(AeadConfig::Register().ok());; // Create a KeysetHandle and use it with the factory. auto aead_result = AeadFactory::GetPrimitive(*TestKeysetHandle::GetKeysetHandle(keyset)); EXPECT_TRUE(aead_result.ok()) << aead_result.status(); auto aead = std::move(aead_result.value()); // Test the resulting Aead-instance. std::string plaintext = "some_plaintext"; std::string aad = "some_aad"; auto encrypt_result = aead->Encrypt(plaintext, aad); EXPECT_TRUE(encrypt_result.ok()) << encrypt_result.status(); std::string ciphertext = encrypt_result.value(); std::string prefix = CryptoFormat::GetOutputPrefix(KeyInfoFromKey(keyset.key(2))).value(); EXPECT_PRED_FORMAT2(testing::IsSubstring, prefix, ciphertext); auto decrypt_result = aead->Decrypt(ciphertext, aad); EXPECT_TRUE(decrypt_result.ok()) << decrypt_result.status(); EXPECT_EQ(plaintext, decrypt_result.value()); decrypt_result = aead->Decrypt("some bad ciphertext", aad); EXPECT_FALSE(decrypt_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, decrypt_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "decryption failed", std::string(decrypt_result.status().message())); // Create raw ciphertext with 2nd key, and decrypt with Aead-instance. AesGcmKey raw_key; EXPECT_TRUE(raw_key.ParseFromString(keyset.key(1).key_data().value())); auto raw_aead = std::move(AesGcmKeyManager().GetPrimitive(raw_key).value()); std::string raw_ciphertext = raw_aead->Encrypt(plaintext, aad).value(); decrypt_result = aead->Decrypt(ciphertext, aad); EXPECT_TRUE(decrypt_result.ok()) << decrypt_result.status(); EXPECT_EQ(plaintext, decrypt_result.value()); } // TINK-PENDING-REMOVAL-IN-3.0.0-END // NOLINTEND(whitespace/line_length) } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aead_key.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_AEAD_KEY_H_ #define TINK_AEAD_AEAD_KEY_H_ #include "absl/strings/string_view.h" #include "tink/aead/aead_parameters.h" #include "tink/key.h" namespace crypto { namespace tink { // Represents a function to encrypt and decrypt data using authenticated // encryption with associated data (AEAD). class AeadKey : public Key { public: // Returns the bytes prefixed to every ciphertext generated by this key. // // In order to make key rotation more efficient, Tink allows every AEAD key to // have an associated ciphertext output prefix. When decrypting a ciphertext, // only keys with a matching prefix have to be tried. // // See https://developers.google.com/tink/wire-format#tink_output_prefix for // more background information on Tink output prefixes. virtual absl::string_view GetOutputPrefix() const = 0; const AeadParameters& GetParameters() const override = 0; bool operator==(const Key& other) const override = 0; }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_AEAD_KEY_H_ ================================================ FILE: cc/aead/aead_key_templates.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aead_key_templates.h" #include #include "absl/strings/string_view.h" #include "proto/aes_ctr.pb.h" #include "proto/aes_ctr_hmac_aead.pb.h" #include "proto/aes_eax.pb.h" #include "proto/aes_gcm.pb.h" #include "proto/aes_gcm_siv.pb.h" #include "proto/common.pb.h" #include "proto/hmac.pb.h" #include "proto/kms_envelope.pb.h" #include "proto/tink.pb.h" using google::crypto::tink::AesCtrHmacAeadKeyFormat; using google::crypto::tink::AesEaxKeyFormat; using google::crypto::tink::AesGcmKeyFormat; using google::crypto::tink::AesGcmSivKeyFormat; using google::crypto::tink::HashType; using google::crypto::tink::KeyTemplate; using google::crypto::tink::KmsEnvelopeAeadKeyFormat; using google::crypto::tink::OutputPrefixType; namespace crypto { namespace tink { namespace { KeyTemplate* NewAesEaxKeyTemplate(int key_size_in_bytes, int iv_size_in_bytes) { KeyTemplate* key_template = new KeyTemplate; key_template->set_type_url( "type.googleapis.com/google.crypto.tink.AesEaxKey"); key_template->set_output_prefix_type(OutputPrefixType::TINK); AesEaxKeyFormat key_format; key_format.set_key_size(key_size_in_bytes); key_format.mutable_params()->set_iv_size(iv_size_in_bytes); key_format.SerializeToString(key_template->mutable_value()); return key_template; } KeyTemplate* NewAesGcmKeyTemplate(int key_size_in_bytes, OutputPrefixType output_prefix_type) { KeyTemplate* key_template = new KeyTemplate; key_template->set_type_url( "type.googleapis.com/google.crypto.tink.AesGcmKey"); key_template->set_output_prefix_type(output_prefix_type); AesGcmKeyFormat key_format; key_format.set_key_size(key_size_in_bytes); key_format.SerializeToString(key_template->mutable_value()); return key_template; } KeyTemplate* NewAesGcmSivKeyTemplate(int key_size_in_bytes) { KeyTemplate* key_template = new KeyTemplate; key_template->set_type_url( "type.googleapis.com/google.crypto.tink.AesGcmSivKey"); key_template->set_output_prefix_type(OutputPrefixType::TINK); AesGcmSivKeyFormat key_format; key_format.set_key_size(key_size_in_bytes); key_format.SerializeToString(key_template->mutable_value()); return key_template; } KeyTemplate* NewAesCtrHmacAeadKeyTemplate(int aes_key_size_in_bytes, int iv_size_in_bytes, int hmac_key_size_in_bytes, int tag_size_in_bytes, HashType hash_type) { KeyTemplate* key_template = new KeyTemplate; key_template->set_type_url( "type.googleapis.com/google.crypto.tink.AesCtrHmacAeadKey"); key_template->set_output_prefix_type(OutputPrefixType::TINK); AesCtrHmacAeadKeyFormat key_format; auto aes_ctr_key_format = key_format.mutable_aes_ctr_key_format(); aes_ctr_key_format->set_key_size(aes_key_size_in_bytes); aes_ctr_key_format->mutable_params()->set_iv_size(iv_size_in_bytes); auto hmac_key_format = key_format.mutable_hmac_key_format(); hmac_key_format->set_key_size(hmac_key_size_in_bytes); hmac_key_format->mutable_params()->set_hash(hash_type); hmac_key_format->mutable_params()->set_tag_size(tag_size_in_bytes); key_format.SerializeToString(key_template->mutable_value()); return key_template; } KeyTemplate* NewXChaCha20Poly1305KeyTemplate() { KeyTemplate* key_template = new KeyTemplate; key_template->set_type_url( "type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key"); key_template->set_output_prefix_type(OutputPrefixType::TINK); return key_template; } } // anonymous namespace // static const KeyTemplate& AeadKeyTemplates::Aes128Eax() { static const KeyTemplate* key_template = NewAesEaxKeyTemplate(/* key_size_in_bytes= */ 16, /* iv_size_in_bytes= */ 16); return *key_template; } // static const KeyTemplate& AeadKeyTemplates::Aes256Eax() { static const KeyTemplate* key_template = NewAesEaxKeyTemplate(/* key_size_in_bytes= */ 32, /* iv_size_in_bytes= */ 16); return *key_template; } // static const KeyTemplate& AeadKeyTemplates::Aes128Gcm() { static const KeyTemplate* key_template = NewAesGcmKeyTemplate(/* key_size_in_bytes= */ 16, OutputPrefixType::TINK); return *key_template; } // static const KeyTemplate& AeadKeyTemplates::Aes128GcmNoPrefix() { static const KeyTemplate* key_template = NewAesGcmKeyTemplate(/* key_size_in_bytes= */ 16, OutputPrefixType::RAW); return *key_template; } // static const KeyTemplate& AeadKeyTemplates::Aes256Gcm() { static const KeyTemplate* key_template = NewAesGcmKeyTemplate(/* key_size_in_bytes= */ 32, OutputPrefixType::TINK); return *key_template; } // static const KeyTemplate& AeadKeyTemplates::Aes256GcmNoPrefix() { static const KeyTemplate* key_template = NewAesGcmKeyTemplate(/* key_size_in_bytes= */ 32, OutputPrefixType::RAW); return *key_template; } // static const KeyTemplate& AeadKeyTemplates::Aes128GcmSiv() { static const KeyTemplate* key_template = NewAesGcmSivKeyTemplate(/* key_size_in_bytes= */ 16); return *key_template; } // static const KeyTemplate& AeadKeyTemplates::Aes256GcmSiv() { static const KeyTemplate* key_template = NewAesGcmSivKeyTemplate(/* key_size_in_bytes= */ 32); return *key_template; } // static const KeyTemplate& AeadKeyTemplates::Aes128CtrHmacSha256() { static const KeyTemplate* key_template = NewAesCtrHmacAeadKeyTemplate( /* aes_key_size_in_bytes= */ 16, /* iv_size_in_bytes= */ 16, /* hmac_key_size_in_bytes= */ 32, /* tag_size_in_bytes= */ 16, HashType::SHA256); return *key_template; } // static const KeyTemplate& AeadKeyTemplates::Aes256CtrHmacSha256() { static const KeyTemplate* key_template = NewAesCtrHmacAeadKeyTemplate( /* aes_key_size_in_bytes= */ 32, /* iv_size_in_bytes= */ 16, /* hmac_key_size_in_bytes= */ 32, /* tag_size_in_bytes= */ 32, HashType::SHA256); return *key_template; } // static const KeyTemplate& AeadKeyTemplates::XChaCha20Poly1305() { static const KeyTemplate* key_template = NewXChaCha20Poly1305KeyTemplate(); return *key_template; } // static KeyTemplate AeadKeyTemplates::KmsEnvelopeAead(absl::string_view kek_uri, const KeyTemplate& dek_template) { KeyTemplate key_template; key_template.set_type_url( "type.googleapis.com/google.crypto.tink.KmsEnvelopeAeadKey"); key_template.set_output_prefix_type(OutputPrefixType::RAW); KmsEnvelopeAeadKeyFormat key_format; key_format.set_kek_uri(std::string(kek_uri)); key_format.mutable_dek_template()->MergeFrom(dek_template); key_format.SerializeToString(key_template.mutable_value()); return key_template; } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aead_key_templates.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_AEAD_KEY_TEMPLATES_H_ #define TINK_AEAD_AEAD_KEY_TEMPLATES_H_ #include "absl/base/attributes.h" #include "absl/strings/string_view.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Pre-generated KeyTemplate for Aead key types. One can use these templates // to generate new KeysetHandle object with fresh keys. // To generate a new keyset that contains a single AesGcmKey, one can do: // // auto status = AeadConfig::Register(); // if (!status.ok()) { /* fail with error */ } // auto handle_result = // KeysetHandle::GenerateNew(AeadKeyTemplates::Aes128Gcm()); // if (!handle_result.ok()) { /* fail with error */ } // auto keyset_handle = std::move(handle_result.value()); class AeadKeyTemplates { public: // Returns a KeyTemplate that generates new instances of AesEaxKey // with the following parameters: // - key size: 16 bytes // - IV size: 16 bytes // - tag size: 16 bytes // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& Aes128Eax(); // Returns a KeyTemplate that generates new instances of AesEaxKey // with the following parameters: // - key size: 32 bytes // - IV size: 16 bytes // - tag size: 16 bytes // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& Aes256Eax(); // Returns a KeyTemplate that generates new instances of AesGcmKey // with the following parameters: // - key size: 16 bytes // - IV size: 12 bytes // - tag size: 16 bytes // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& Aes128Gcm(); // Returns a KeyTemplate that generates new instances of AesGcmKey // with the following parameters: // - key size: 16 bytes // - IV size: 12 bytes // - tag size: 16 bytes // - OutputPrefixType: RAW static const google::crypto::tink::KeyTemplate& Aes128GcmNoPrefix(); // Returns a KeyTemplate that generates new instances of AesGcmKey // with the following parameters: // - key size: 32 bytes // - IV size: 12 bytes // - tag size: 16 bytes // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& Aes256Gcm(); // Returns a KeyTemplate that generates new instances of AesGcmKey // with the following parameters: // - key size: 32 bytes // - IV size: 12 bytes // - tag size: 16 bytes // - OutputPrefixType: RAW static const google::crypto::tink::KeyTemplate& Aes256GcmNoPrefix(); // Returns a KeyTemplate that generates new instances of AesGcmSivKey // with the following parameters: // - key size: 16 bytes // - IV size: 12 bytes // - tag size: 16 bytes // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& Aes128GcmSiv(); // Returns a KeyTemplate that generates new instances of AesGcmSivKey // with the following parameters: // - key size: 32 bytes // - IV size: 12 bytes // - tag size: 16 bytes // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& Aes256GcmSiv(); // Returns a KeyTemplate that generates new instances of AesCtrHmacAeadKey // with the following parameters: // - AES key size: 16 bytes // - AES IV size: 16 bytes // - HMAC key size: 32 bytes // - HMAC tag size: 16 bytes // - HMAC hash function: SHA256 // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& Aes128CtrHmacSha256(); // Returns a KeyTemplate that generates new instances of AesCtrHmacAeadKey // with the following parameters: // - AES key size: 32 bytes // - AES IV size: 16 bytes // - HMAC key size: 32 bytes // - HMAC tag size: 32 bytes // - HMAC hash function: SHA256 // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& Aes256CtrHmacSha256(); // Returns a KeyTemplate that generates new instances of XChaCha20Poly1305Key // with the following parameters: // - XChacha20 key size: 32 bytes // - IV size: 24 bytes // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& XChaCha20Poly1305(); // Returns a KeyTemplate that generates new instances of KmsEnvelopeAeadKey // with the following parameters: // - KEK is pointing to kek_uri // - DEK template is dek_template // - OutputPrefixType: RAW. This uses RAW output prefix to make it // compatible with the remote KMS' encrypt/decrypt operations. Unlike other // templates, when you generate new keys with this template, Tink does not // generate new key material, but only creates a reference to the remote // KEK. ABSL_DEPRECATED( "AeadKeyTemplates::KmsEnvelopeAead is deprecated. Instead, get the remote" "AEAD with KmsClient::GetAead, and then create the envelope AEAD using " "KmsEnvelopeAead::New without registering the KmsClient object.") static google::crypto::tink::KeyTemplate KmsEnvelopeAead( absl::string_view kek_uri, const google::crypto::tink::KeyTemplate& dek_template); }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_AEAD_KEY_TEMPLATES_H_ ================================================ FILE: cc/aead/aead_key_templates_test.cc ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aead_key_templates.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/status/statusor.h" #include "tink/aead.h" #include "tink/aead/aead_config.h" #include "tink/aead/aes_ctr_hmac_aead_key_manager.h" #include "tink/aead/aes_eax_key_manager.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/aead/aes_gcm_siv_key_manager.h" #include "tink/aead/kms_envelope_aead_key_manager.h" #include "tink/aead/xchacha20_poly1305_key_manager.h" #include "tink/config/global_registry.h" #include "tink/core/key_manager_impl.h" #include "tink/key_manager.h" #include "tink/keyset_handle.h" #include "tink/subtle/aead_test_util.h" #include "tink/util/fake_kms_client.h" #include "tink/util/status.h" #include "tink/util/test_matchers.h" #include "proto/aes_ctr.pb.h" #include "proto/aes_ctr_hmac_aead.pb.h" #include "proto/aes_eax.pb.h" #include "proto/aes_gcm.pb.h" #include "proto/aes_gcm_siv.pb.h" #include "proto/common.pb.h" #include "proto/hmac.pb.h" #include "proto/kms_envelope.pb.h" #include "proto/tink.pb.h" #include "proto/xchacha20_poly1305.pb.h" using google::crypto::tink::AesCtrHmacAeadKeyFormat; using google::crypto::tink::AesEaxKeyFormat; using google::crypto::tink::AesGcmKeyFormat; using google::crypto::tink::AesGcmSivKeyFormat; using google::crypto::tink::HashType; using google::crypto::tink::KeyTemplate; using google::crypto::tink::KmsEnvelopeAeadKeyFormat; using google::crypto::tink::OutputPrefixType; namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::testing::Eq; using ::testing::Ref; TEST(AeadKeyTemplatesTest, testAesEaxKeyTemplates) { std::string type_url = "type.googleapis.com/google.crypto.tink.AesEaxKey"; { // Test Aes128Eax(). // Check that returned template is correct. const KeyTemplate& key_template = AeadKeyTemplates::Aes128Eax(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); AesEaxKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(16, key_format.key_size()); EXPECT_EQ(16, key_format.params().iv_size()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = AeadKeyTemplates::Aes128Eax(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. AesEaxKeyManager key_type_manager; auto key_manager = internal::MakeKeyManager(&key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_template.value()); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } { // Test Aes256Eax(). // Check that returned template is correct. const KeyTemplate& key_template = AeadKeyTemplates::Aes256Eax(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); AesEaxKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(32, key_format.key_size()); EXPECT_EQ(16, key_format.params().iv_size()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = AeadKeyTemplates::Aes256Eax(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. AesEaxKeyManager key_type_manager; auto key_manager = internal::MakeKeyManager(&key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_template.value()); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } } TEST(Aes128GcmNoPrefix, Basics) { EXPECT_THAT(AeadKeyTemplates::Aes128GcmNoPrefix().type_url(), Eq("type.googleapis.com/google.crypto.tink.AesGcmKey")); EXPECT_THAT(AeadKeyTemplates::Aes128GcmNoPrefix().type_url(), Eq(AesGcmKeyManager().get_key_type())); } TEST(Aes128GcmNoPrefix, OutputPrefixType) { EXPECT_THAT(AeadKeyTemplates::Aes128GcmNoPrefix().output_prefix_type(), Eq(OutputPrefixType::RAW)); } TEST(Aes128GcmNoPrefix, MultipleCallsSameReference) { EXPECT_THAT(AeadKeyTemplates::Aes128GcmNoPrefix(), Ref(AeadKeyTemplates::Aes128GcmNoPrefix())); } TEST(Aes128GcmNoPrefix, WorksWithKeyTypeManager) { const KeyTemplate& key_template = AeadKeyTemplates::Aes128GcmNoPrefix(); AesGcmKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(AesGcmKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(Aes128GcmNoPrefix, CheckValues) { const KeyTemplate& key_template = AeadKeyTemplates::Aes128GcmNoPrefix(); AesGcmKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(key_format.key_size(), Eq(16)); } TEST(Aes256GcmNoPrefix, Basics) { EXPECT_THAT(AeadKeyTemplates::Aes256GcmNoPrefix().type_url(), Eq("type.googleapis.com/google.crypto.tink.AesGcmKey")); EXPECT_THAT(AeadKeyTemplates::Aes256GcmNoPrefix().type_url(), Eq(AesGcmKeyManager().get_key_type())); } TEST(Aes256GcmNoPrefix, OutputPrefixType) { EXPECT_THAT(AeadKeyTemplates::Aes256GcmNoPrefix().output_prefix_type(), Eq(OutputPrefixType::RAW)); } TEST(Aes256GcmNoPrefix, MultipleCallsSameReference) { EXPECT_THAT(AeadKeyTemplates::Aes256GcmNoPrefix(), Ref(AeadKeyTemplates::Aes256GcmNoPrefix())); } TEST(Aes256GcmNoPrefix, WorksWithKeyTypeManager) { const KeyTemplate& key_template = AeadKeyTemplates::Aes256GcmNoPrefix(); AesGcmKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(AesGcmKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(Aes256GcmNoPrefix, CheckValues) { const KeyTemplate& key_template = AeadKeyTemplates::Aes256GcmNoPrefix(); AesGcmKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(key_format.key_size(), Eq(32)); } TEST(Aes256Gcm, Basics) { EXPECT_THAT(AeadKeyTemplates::Aes256Gcm().type_url(), Eq("type.googleapis.com/google.crypto.tink.AesGcmKey")); EXPECT_THAT(AeadKeyTemplates::Aes256Gcm().type_url(), Eq(AesGcmKeyManager().get_key_type())); } TEST(Aes256Gcm, OutputPrefixType) { EXPECT_THAT(AeadKeyTemplates::Aes256Gcm().output_prefix_type(), Eq(OutputPrefixType::TINK)); } TEST(Aes256Gcm, MultipleCallsSameReference) { EXPECT_THAT(AeadKeyTemplates::Aes256Gcm(), Ref(AeadKeyTemplates::Aes256Gcm())); } TEST(Aes256Gcm, WorksWithKeyTypeManager) { const KeyTemplate& key_template = AeadKeyTemplates::Aes256Gcm(); AesGcmKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(AesGcmKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(Aes256Gcm, CheckValues) { const KeyTemplate& key_template = AeadKeyTemplates::Aes256Gcm(); AesGcmKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(key_format.key_size(), Eq(32)); } TEST(Aes128Gcm, Basics) { EXPECT_THAT(AeadKeyTemplates::Aes128Gcm().type_url(), Eq("type.googleapis.com/google.crypto.tink.AesGcmKey")); EXPECT_THAT(AeadKeyTemplates::Aes128Gcm().type_url(), Eq(AesGcmKeyManager().get_key_type())); } TEST(Aes128Gcm, OutputPrefixType) { EXPECT_THAT(AeadKeyTemplates::Aes128Gcm().output_prefix_type(), Eq(OutputPrefixType::TINK)); } TEST(Aes128Gcm, MultipleCallsSameReference) { EXPECT_THAT(AeadKeyTemplates::Aes128Gcm(), Ref(AeadKeyTemplates::Aes128Gcm())); } TEST(Aes128Gcm, WorksWithKeyTypeManager) { const KeyTemplate& key_template = AeadKeyTemplates::Aes128Gcm(); AesGcmKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(AesGcmKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(Aes128Gcm, CheckValues) { const KeyTemplate& key_template = AeadKeyTemplates::Aes128Gcm(); AesGcmKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(key_format.key_size(), Eq(16)); } TEST(AeadKeyTemplatesTest, testAesGcmSivKeyTemplates) { std::string type_url = "type.googleapis.com/google.crypto.tink.AesGcmSivKey"; { // Test Aes128GcmSiv(). // Check that returned template is correct. const KeyTemplate& key_template = AeadKeyTemplates::Aes128GcmSiv(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); AesGcmSivKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(16, key_format.key_size()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = AeadKeyTemplates::Aes128GcmSiv(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. AesGcmSivKeyManager key_type_manager; auto key_manager = internal::MakeKeyManager(&key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_template.value()); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } { // Test Aes256GcmSiv(). // Check that returned template is correct. const KeyTemplate& key_template = AeadKeyTemplates::Aes256GcmSiv(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); AesGcmSivKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(32, key_format.key_size()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = AeadKeyTemplates::Aes256GcmSiv(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. AesGcmSivKeyManager key_type_manager; auto key_manager = internal::MakeKeyManager(&key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_template.value()); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } } TEST(AeadKeyTemplatesTest, testAesCtrHmacAeadKeyTemplates) { std::string type_url = "type.googleapis.com/google.crypto.tink.AesCtrHmacAeadKey"; { // Test Aes128CtrHmacSha256(). // Check that returned template is correct. const KeyTemplate& key_template = AeadKeyTemplates::Aes128CtrHmacSha256(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); AesCtrHmacAeadKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(16, key_format.aes_ctr_key_format().key_size()); EXPECT_EQ(16, key_format.aes_ctr_key_format().params().iv_size()); EXPECT_EQ(32, key_format.hmac_key_format().key_size()); EXPECT_EQ(16, key_format.hmac_key_format().params().tag_size()); EXPECT_EQ(HashType::SHA256, key_format.hmac_key_format().params().hash()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = AeadKeyTemplates::Aes128CtrHmacSha256(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. AesCtrHmacAeadKeyManager key_type_manager; auto key_manager = internal::MakeKeyManager(&key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_template.value()); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } { // Test Aes256CtrHmacSha256(). // Check that returned template is correct. const KeyTemplate& key_template = AeadKeyTemplates::Aes256CtrHmacSha256(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); AesCtrHmacAeadKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(32, key_format.aes_ctr_key_format().key_size()); EXPECT_EQ(16, key_format.aes_ctr_key_format().params().iv_size()); EXPECT_EQ(32, key_format.hmac_key_format().key_size()); EXPECT_EQ(32, key_format.hmac_key_format().params().tag_size()); EXPECT_EQ(HashType::SHA256, key_format.hmac_key_format().params().hash()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = AeadKeyTemplates::Aes256CtrHmacSha256(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. AesCtrHmacAeadKeyManager key_type_manager; auto key_manager = internal::MakeKeyManager(&key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_template.value()); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } } TEST(AeadKeyTemplatesTest, testXChaCha20Poly1305KeyTemplates) { std::string type_url = "type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key"; // Check that returned template is correct. const KeyTemplate& key_template = AeadKeyTemplates::XChaCha20Poly1305(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = AeadKeyTemplates::XChaCha20Poly1305(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. XChaCha20Poly1305KeyManager key_type_manager; auto key_manager = internal::MakeKeyManager(&key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_template.value()); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } TEST(AeadKeyTemplatesTest, testKmsEnvelopeAead) { std::string type_url = "type.googleapis.com/google.crypto.tink.KmsEnvelopeAeadKey"; std::string kek_uri = "foo/bar"; const KeyTemplate& dek_template = AeadKeyTemplates::Aes128Gcm(); // Check that returned template is correct. const KeyTemplate& key_template = AeadKeyTemplates::KmsEnvelopeAead(kek_uri, dek_template); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::RAW, key_template.output_prefix_type()); KmsEnvelopeAeadKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(kek_uri, key_format.kek_uri()); EXPECT_EQ(dek_template.type_url(), key_format.dek_template().type_url()); EXPECT_EQ(dek_template.value(), key_format.dek_template().value()); // Check that the template works with the key manager. KmsEnvelopeAeadKeyManager key_type_manager; auto key_manager = internal::MakeKeyManager(&key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_template.value()); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } TEST(AeadKeyTemplatesTest, testKmsEnvelopeAeadMultipleKeysSameKek) { // Initialize the registry. ASSERT_TRUE(AeadConfig::Register().ok()); auto kek_uri_result = test::FakeKmsClient::CreateFakeKeyUri(); EXPECT_TRUE(kek_uri_result.ok()) << kek_uri_result.status(); std::string kek_uri = kek_uri_result.value(); auto register_fake_kms_client_status = test::FakeKmsClient::RegisterNewClient( kek_uri, /* credentials_path= */ ""); std::string type_url = "type.googleapis.com/google.crypto.tink.KmsEnvelopeAeadKey"; const KeyTemplate& dek_template = AeadKeyTemplates::Aes128Gcm(); const KeyTemplate& key_template1 = AeadKeyTemplates::KmsEnvelopeAead(kek_uri, dek_template); auto handle_result1 = KeysetHandle::GenerateNew(key_template1, KeyGenConfigGlobalRegistry()); EXPECT_TRUE(handle_result1.ok()); auto handle1 = std::move(handle_result1.value()); auto aead_result1 = handle1->GetPrimitive(ConfigGlobalRegistry()); EXPECT_TRUE(aead_result1.ok()); auto aead1 = std::move(aead_result1.value()); const KeyTemplate& key_template2 = AeadKeyTemplates::KmsEnvelopeAead(kek_uri, dek_template); auto handle_result2 = KeysetHandle::GenerateNew(key_template2, KeyGenConfigGlobalRegistry()); EXPECT_TRUE(handle_result2.ok()); auto handle2 = std::move(handle_result2.value()); auto aead_result2 = handle2->GetPrimitive(ConfigGlobalRegistry()); EXPECT_TRUE(aead_result2.ok()); auto aead2 = std::move(aead_result2.value()); EXPECT_THAT(EncryptThenDecrypt(*aead1, *aead2, "message", "aad"), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aead_parameters.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_AEAD_PARAMETERS_H_ #define TINK_AEAD_AEAD_PARAMETERS_H_ #include "tink/parameters.h" namespace crypto { namespace tink { // Describes an `AeadKey` (e.g., key attributes), excluding the randomly chosen // key material. class AeadParameters : public Parameters {}; } // namespace tink } // namespace crypto #endif // TINK_AEAD_AEAD_PARAMETERS_H_ ================================================ FILE: cc/aead/aead_wrapper.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aead_wrapper.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/crypto_format.h" #include "tink/internal/monitoring_util.h" #include "tink/internal/registry_impl.h" #include "tink/internal/util.h" #include "tink/monitoring/monitoring.h" #include "tink/primitive_set.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { constexpr absl::string_view kPrimitive = "aead"; constexpr absl::string_view kEncryptApi = "encrypt"; constexpr absl::string_view kDecryptApi = "decrypt"; util::Status Validate(PrimitiveSet* aead_set) { if (aead_set == nullptr) { return util::Status(absl::StatusCode::kInternal, "aead_set must be non-NULL"); } if (aead_set->get_primary() == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "aead_set has no primary"); } return util::OkStatus(); } // The actual wrapper. class AeadSetWrapper : public Aead { public: explicit AeadSetWrapper( std::unique_ptr> aead_set, std::unique_ptr monitoring_encryption_client = nullptr, std::unique_ptr monitoring_decryption_client = nullptr) : aead_set_(std::move(aead_set)), monitoring_encryption_client_(std::move(monitoring_encryption_client)), monitoring_decryption_client_(std::move(monitoring_decryption_client)) { } util::StatusOr Encrypt( absl::string_view plaintext, absl::string_view associated_data) const override; util::StatusOr Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const override; private: std::unique_ptr> aead_set_; std::unique_ptr monitoring_encryption_client_; std::unique_ptr monitoring_decryption_client_; }; util::StatusOr AeadSetWrapper::Encrypt( absl::string_view plaintext, absl::string_view associated_data) const { associated_data = internal::EnsureStringNonNull(associated_data); const Aead& primitive = aead_set_->get_primary()->get_primitive(); util::StatusOr ciphertext = primitive.Encrypt(plaintext, associated_data); if (!ciphertext.ok()) { if (monitoring_encryption_client_ != nullptr) { monitoring_encryption_client_->LogFailure(); } return ciphertext.status(); } if (monitoring_encryption_client_ != nullptr) { monitoring_encryption_client_->Log(aead_set_->get_primary()->get_key_id(), plaintext.size()); } const std::string& key_id = aead_set_->get_primary()->get_identifier(); return absl::StrCat(key_id, *ciphertext); } util::StatusOr AeadSetWrapper::Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const { // BoringSSL expects a non-null pointer for plaintext and associated_data, // regardless of whether the size is 0. associated_data = internal::EnsureStringNonNull(associated_data); if (ciphertext.length() > CryptoFormat::kNonRawPrefixSize) { absl::string_view key_id = ciphertext.substr(0, CryptoFormat::kNonRawPrefixSize); util::StatusOr::Primitives*> primitives = aead_set_->get_primitives(key_id); if (primitives.ok()) { absl::string_view raw_ciphertext = ciphertext.substr(CryptoFormat::kNonRawPrefixSize); for (const std::unique_ptr::Entry>& aead_entry : **primitives) { Aead& aead = aead_entry->get_primitive(); util::StatusOr plaintext = aead.Decrypt(raw_ciphertext, associated_data); if (plaintext.ok()) { if (monitoring_decryption_client_ != nullptr) { monitoring_decryption_client_->Log(aead_entry->get_key_id(), raw_ciphertext.size()); } return plaintext; } } } } // No matching key succeeded with decryption, try all RAW keys. util::StatusOr::Primitives*> raw_primitives = aead_set_->get_raw_primitives(); if (raw_primitives.ok()) { for (const std::unique_ptr::Entry>& aead_entry : **raw_primitives) { Aead& aead = aead_entry->get_primitive(); util::StatusOr plaintext = aead.Decrypt(ciphertext, associated_data); if (plaintext.ok()) { if (monitoring_decryption_client_ != nullptr) { monitoring_decryption_client_->Log(aead_entry->get_key_id(), ciphertext.size()); } return plaintext; } } } if (monitoring_decryption_client_ != nullptr) { monitoring_decryption_client_->LogFailure(); } return util::Status(absl::StatusCode::kInvalidArgument, "decryption failed"); } } // namespace util::StatusOr> AeadWrapper::Wrap( std::unique_ptr> aead_set) const { util::Status status = Validate(aead_set.get()); if (!status.ok()) { return status; } MonitoringClientFactory* const monitoring_factory = internal::RegistryImpl::GlobalInstance().GetMonitoringClientFactory(); // Monitoring is not enabled. Create a wrapper without monitoring clients. if (monitoring_factory == nullptr) { return {absl::make_unique(std::move(aead_set))}; } util::StatusOr keyset_info = internal::MonitoringKeySetInfoFromPrimitiveSet(*aead_set); if (!keyset_info.ok()) { return keyset_info.status(); } util::StatusOr> monitoring_encryption_client = monitoring_factory->New( MonitoringContext(kPrimitive, kEncryptApi, *keyset_info)); if (!monitoring_encryption_client.ok()) { return monitoring_encryption_client.status(); } util::StatusOr> monitoring_decryption_client = monitoring_factory->New( MonitoringContext(kPrimitive, kDecryptApi, *keyset_info)); if (!monitoring_decryption_client.ok()) { return monitoring_decryption_client.status(); } return {absl::make_unique( std::move(aead_set), *std::move(monitoring_encryption_client), *std::move(monitoring_decryption_client))}; } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aead_wrapper.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_AEAD_WRAPPER_H_ #define TINK_AEAD_AEAD_WRAPPER_H_ #include #include "tink/aead.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Wraps a set of Aead-instances that correspond to a keyset, // and combines them into a single Aead-primitive, that uses the provided // instances, depending on the context: // * Aead::Encrypt(...) uses the primary instance from the set // * Aead::Decrypt(...) uses the instance that matches the ciphertext prefix. class AeadWrapper : public PrimitiveWrapper { public: // Returns an Aead-primitive that uses Aead-instances provided in 'aead_set', // which must be non-NULL and must contain a primary instance. util::StatusOr> Wrap( std::unique_ptr> aead_set) const override; }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_AEAD_WRAPPER_H_ ================================================ FILE: cc/aead/aead_wrapper_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aead_wrapper.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_map.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/aead/mock_aead.h" #include "tink/crypto_format.h" #include "tink/internal/registry_impl.h" #include "tink/monitoring/monitoring.h" #include "tink/monitoring/monitoring_client_mocks.h" #include "tink/primitive_set.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::DummyAead; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::KeysetInfo; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::OutputPrefixType; using ::testing::_; using ::testing::ByMove; using ::testing::HasSubstr; using ::testing::IsNull; using ::testing::IsSubstring; using ::testing::Not; using ::testing::Return; using ::testing::StrictMock; using ::testing::Test; void PopulateKeyInfo(KeysetInfo::KeyInfo* key_info, uint32_t key_id, OutputPrefixType out_prefix_type, KeyStatusType status) { key_info->set_output_prefix_type(out_prefix_type); key_info->set_key_id(key_id); key_info->set_status(status); } // Creates a test keyset info object. KeysetInfo CreateTestKeysetInfo() { KeysetInfo keyset_info; PopulateKeyInfo(keyset_info.add_key_info(), /*key_id=*/1234543, OutputPrefixType::TINK, /*status=*/KeyStatusType::ENABLED); PopulateKeyInfo(keyset_info.add_key_info(), /*key_id=*/726329, OutputPrefixType::LEGACY, /*status=*/KeyStatusType::ENABLED); PopulateKeyInfo(keyset_info.add_key_info(), /*key_id=*/7213743, OutputPrefixType::TINK, /*status=*/KeyStatusType::ENABLED); return keyset_info; } TEST(AeadSetWrapperTest, WrapNullptr) { AeadWrapper wrapper; util::StatusOr> aead = wrapper.Wrap(nullptr); EXPECT_THAT(aead, Not(IsOk())); EXPECT_THAT(aead.status(), StatusIs(absl::StatusCode::kInternal)); EXPECT_PRED_FORMAT2(IsSubstring, "non-NULL", std::string(aead.status().message())); } TEST(AeadSetWrapperTest, WrapEmpty) { AeadWrapper wrapper; util::StatusOr> aead = wrapper.Wrap(absl::make_unique>()); EXPECT_THAT(aead, Not(IsOk())); EXPECT_THAT(aead.status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_PRED_FORMAT2(IsSubstring, "no primary", std::string(aead.status().message())); } TEST(AeadSetWrapperTest, Basic) { KeysetInfo keyset_info = CreateTestKeysetInfo(); std::string aead_name_0 = "aead0"; std::string aead_name_1 = "aead1"; std::string aead_name_2 = "aead2"; auto aead_set = absl::make_unique>(); std::unique_ptr aead = absl::make_unique(aead_name_0); util::StatusOr::Entry*> aead_entry = aead_set->AddPrimitive(std::move(aead), keyset_info.key_info(0)); EXPECT_THAT(aead_entry, IsOk()); aead = absl::make_unique(aead_name_1); aead_entry = aead_set->AddPrimitive(std::move(aead), keyset_info.key_info(1)); EXPECT_THAT(aead_entry, IsOk()); aead = absl::make_unique(aead_name_2); aead_entry = aead_set->AddPrimitive(std::move(aead), keyset_info.key_info(2)); EXPECT_THAT(aead_entry, IsOk()); // The last key is the primary. EXPECT_THAT(aead_set->set_primary(*aead_entry), IsOk()); // Wrap aead_set and test the resulting Aead. AeadWrapper wrapper; util::StatusOr> aead_result = wrapper.Wrap(std::move(aead_set)); EXPECT_THAT(aead_result, IsOk()); aead = std::move(*aead_result); std::string plaintext = "some_plaintext"; std::string aad = "some_aad"; util::StatusOr encrypt_result = aead->Encrypt(plaintext, aad); EXPECT_THAT(encrypt_result, IsOk()); std::string ciphertext = *encrypt_result; EXPECT_PRED_FORMAT2(testing::IsSubstring, aead_name_2, ciphertext); util::StatusOr resulting_plaintext = aead->Decrypt(ciphertext, aad); EXPECT_THAT(resulting_plaintext, IsOk()); EXPECT_EQ(*resulting_plaintext, plaintext); resulting_plaintext = aead->Decrypt("some bad ciphertext", aad); EXPECT_THAT(resulting_plaintext, Not(IsOk())); EXPECT_THAT(resulting_plaintext.status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_PRED_FORMAT2(IsSubstring, "decryption failed", std::string(resulting_plaintext.status().message())); } TEST(AeadSetWrapperTest, DecryptNonPrimary) { KeysetInfo keyset_info = CreateTestKeysetInfo(); std::string aead_name_0 = "aead0"; std::string aead_name_1 = "aead1"; std::string aead_name_2 = "aead2"; std::unique_ptr> aead_set(new PrimitiveSet()); std::unique_ptr aead = absl::make_unique(aead_name_0); // Encrypt some message with the first aead.s std::string plaintext = "some_plaintext"; std::string aad = "some_aad"; util::StatusOr ciphertext = aead->Encrypt(plaintext, aad); EXPECT_THAT(ciphertext, IsOk()); util::StatusOr::Entry*> aead_entry = aead_set->AddPrimitive(std::move(aead), keyset_info.key_info(0)); ASSERT_THAT(aead_entry, IsOk()); EXPECT_THAT(aead_set->set_primary(*aead_entry), IsOk()); // The complete ciphertext is of the form: | key_id | ciphertext |. std::string complete_ciphertext = absl::StrCat(aead_set->get_primary()->get_identifier(), *ciphertext); aead = absl::make_unique(aead_name_1); aead_entry = aead_set->AddPrimitive(std::move(aead), keyset_info.key_info(1)); EXPECT_THAT(aead_entry, IsOk()); aead = absl::make_unique(aead_name_2); aead_entry = aead_set->AddPrimitive(std::move(aead), keyset_info.key_info(2)); EXPECT_THAT(aead_entry, IsOk()); // The last key is the primary. EXPECT_THAT(aead_set->set_primary(*aead_entry), IsOk()); // Wrap aead_set and test the resulting Aead. AeadWrapper wrapper; util::StatusOr> aead_wrapped = wrapper.Wrap(std::move(aead_set)); EXPECT_THAT(aead_wrapped, IsOk()); aead = std::move(*aead_wrapped); EXPECT_THAT(complete_ciphertext, HasSubstr(aead_name_0)); // Primary key is different from the one we used to encrypt. This // should still be decryptable as we have the correct key in the set. util::StatusOr decrypted_plaintext = aead->Decrypt(complete_ciphertext, aad); EXPECT_THAT(decrypted_plaintext, IsOk()); } // Tests with monitoring enabled. class AeadSetWrapperTestWithMonitoring : public Test { protected: // Perform some common initialization: reset the global registry, set expected // calls for the mock monitoring factory and the returned clients. void SetUp() override { Registry::Reset(); auto monitoring_client_factory = absl::make_unique(); auto encryption_monitoring_client = absl::make_unique>(); encryption_monitoring_client_ptr_ = encryption_monitoring_client.get(); auto decryption_monitoring_client = absl::make_unique>(); decryption_monitoring_client_ptr_ = decryption_monitoring_client.get(); EXPECT_CALL(*monitoring_client_factory, New(_)) .WillOnce( Return(ByMove(util::StatusOr>( std::move(encryption_monitoring_client))))) .WillOnce( Return(ByMove(util::StatusOr>( std::move(decryption_monitoring_client))))); ASSERT_THAT(internal::RegistryImpl::GlobalInstance() .RegisterMonitoringClientFactory( std::move(monitoring_client_factory)), IsOk()); ASSERT_THAT( internal::RegistryImpl::GlobalInstance().GetMonitoringClientFactory(), Not(IsNull())); } // Cleanup the registry to avoid mock leaks. void TearDown() override { Registry::Reset(); } MockMonitoringClient* encryption_monitoring_client_ptr_; MockMonitoringClient* decryption_monitoring_client_ptr_; }; // Test that successful encrypt/decrypt operations are logged. TEST_F(AeadSetWrapperTestWithMonitoring, WrapKeysetWithMonitoringEncryptDecryptSuccess) { // Populate a primitive set. KeysetInfo keyset_info = CreateTestKeysetInfo(); const absl::flat_hash_map kAnnotations = { {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}}; auto aead_primitive_set = absl::make_unique>(kAnnotations); ASSERT_THAT(aead_primitive_set ->AddPrimitive(absl::make_unique("aead0"), keyset_info.key_info(0)) .status(), IsOk()); ASSERT_THAT(aead_primitive_set ->AddPrimitive(absl::make_unique("aead1"), keyset_info.key_info(1)) .status(), IsOk()); // Set the last as primary. util::StatusOr::Entry*> last = aead_primitive_set->AddPrimitive(absl::make_unique("aead2"), keyset_info.key_info(2)); ASSERT_THAT(last, IsOk()); ASSERT_THAT(aead_primitive_set->set_primary(*last), IsOk()); // Record the ID of the primary key. const uint32_t kPrimaryKeyId = keyset_info.key_info(2).key_id(); util::StatusOr> aead = AeadWrapper().Wrap(std::move(aead_primitive_set)); ASSERT_THAT(aead, IsOk()); constexpr absl::string_view kPlaintext = "This is some plaintext!"; constexpr absl::string_view kAssociatedData = "Some associated data!"; EXPECT_CALL(*encryption_monitoring_client_ptr_, Log(kPrimaryKeyId, kPlaintext.size())); util::StatusOr ciphertext = (*aead)->Encrypt(kPlaintext, kAssociatedData); ASSERT_THAT(ciphertext, IsOk()); // In the log expect the size of the ciphertext without the non-raw prefix. auto raw_ciphertext = absl::string_view(*ciphertext).substr(CryptoFormat::kNonRawPrefixSize); EXPECT_CALL(*decryption_monitoring_client_ptr_, Log(kPrimaryKeyId, raw_ciphertext.size())); EXPECT_THAT((*aead)->Decrypt(*ciphertext, kAssociatedData), IsOk()); } // Test that monitoring logs encryption and decryption failures correctly. TEST_F(AeadSetWrapperTestWithMonitoring, WrapKeysetWithMonitoringEncryptDecryptFailures) { // Populate a primitive set. KeysetInfo keyset_info = CreateTestKeysetInfo(); const absl::flat_hash_map kAnnotations = { {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}}; auto aead_primitive_set = absl::make_unique>(kAnnotations); // Assume encryption and decryption always fail. auto mock_aead = absl::make_unique(); constexpr absl::string_view kPlaintext = "A plaintext!!"; constexpr absl::string_view kCiphertext = "A ciphertext!"; constexpr absl::string_view kAssociatedData = "Some associated data!"; ON_CALL(*mock_aead, Encrypt(kPlaintext, kAssociatedData)) .WillByDefault(Return(util::Status(absl::StatusCode::kInternal, "Oh no encryption failed :(!"))); ON_CALL(*mock_aead, Decrypt(kCiphertext, kAssociatedData)) .WillByDefault(Return(util::Status(absl::StatusCode::kInternal, "Oh no decryption failed :(!"))); util::StatusOr::Entry*> primary = aead_primitive_set->AddPrimitive(std::move(mock_aead), keyset_info.key_info(2)); ASSERT_THAT(primary, IsOk()); // Set the only primitive as primary. ASSERT_THAT(aead_primitive_set->set_primary(*primary), IsOk()); util::StatusOr> aead = AeadWrapper().Wrap(std::move(aead_primitive_set)); ASSERT_THAT(aead, IsOk()); // Expect encryption failure gets logged. EXPECT_CALL(*encryption_monitoring_client_ptr_, LogFailure()); util::StatusOr ciphertext = (*aead)->Encrypt(kPlaintext, kAssociatedData); EXPECT_THAT(ciphertext, Not(IsOk())); // We must prepend the identifier to the ciphertext to make sure our mock gets // called. util::StatusOr key_identifier = CryptoFormat::GetOutputPrefix(keyset_info.key_info(2)); ASSERT_THAT(key_identifier, IsOk()); std::string ciphertext_with_key_id = absl::StrCat(*key_identifier, kCiphertext); // Expect decryption failure gets logged. EXPECT_CALL(*decryption_monitoring_client_ptr_, LogFailure()); EXPECT_THAT( (*aead)->Decrypt(ciphertext_with_key_id, kAssociatedData).status(), Not(IsOk())); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_ctr_hmac_aead_key.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_ctr_hmac_aead_key.h" #include #include #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/types/optional.h" #include "tink/aead/aes_ctr_hmac_aead_parameters.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { util::StatusOr ComputeOutputPrefix( const AesCtrHmacAeadParameters& parameters, absl::optional id_requirement) { switch (parameters.GetVariant()) { case AesCtrHmacAeadParameters::Variant::kNoPrefix: return std::string(""); // Empty prefix. case AesCtrHmacAeadParameters::Variant::kCrunchy: if (!id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "ID requirement must not be empty with kCrunchy or kLegacy"); } return absl::StrCat(absl::HexStringToBytes("00"), subtle::BigEndian32(*id_requirement)); case AesCtrHmacAeadParameters::Variant::kTink: if (!id_requirement.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "ID requirement must not be empty with kTink"); } return absl::StrCat(absl::HexStringToBytes("01"), subtle::BigEndian32(*id_requirement)); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid variant: ", parameters.GetVariant())); } } } // namespace AesCtrHmacAeadKey::Builder& AesCtrHmacAeadKey::Builder::SetParameters( const AesCtrHmacAeadParameters& parameters) { parameters_ = parameters; return *this; } AesCtrHmacAeadKey::Builder& AesCtrHmacAeadKey::Builder::SetAesKeyBytes( const RestrictedData& aes_key_bytes) { aes_key_bytes_ = aes_key_bytes; return *this; } AesCtrHmacAeadKey::Builder& AesCtrHmacAeadKey::Builder::SetHmacKeyBytes( const RestrictedData& hmac_key_bytes) { hmac_key_bytes_ = hmac_key_bytes; return *this; } AesCtrHmacAeadKey::Builder& AesCtrHmacAeadKey::Builder::SetIdRequirement( absl::optional id_requirement) { id_requirement_ = id_requirement; return *this; } util::StatusOr AesCtrHmacAeadKey::Builder::Build( PartialKeyAccessToken token) { if (!parameters_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Cannot build without setting the parameters"); } if (!aes_key_bytes_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Cannot build without AES key material"); } if (!hmac_key_bytes_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Cannot build without HMAC key material"); } if (parameters_->GetAesKeySizeInBytes() != aes_key_bytes_->size()) { return util::Status(absl::StatusCode::kInvalidArgument, "AES key size does not match " "AesCtrHmacAeadParameters::GetAesKeySizeInBytes"); } if (parameters_->GetHmacKeySizeInBytes() != hmac_key_bytes_->size()) { return util::Status(absl::StatusCode::kInvalidArgument, "HMAC key size does not match " "AesCtrHmacAeadParameters::GetHmacKeySizeInBytes"); } if (parameters_->HasIdRequirement() && !id_requirement_.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key without ID requirement with parameters with ID " "requirement"); } if (!parameters_->HasIdRequirement() && id_requirement_.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key with ID requirement with parameters without ID " "requirement"); } util::StatusOr output_prefix = ComputeOutputPrefix(*parameters_, id_requirement_); if (!output_prefix.ok()) { return output_prefix.status(); } return AesCtrHmacAeadKey(*parameters_, *aes_key_bytes_, *hmac_key_bytes_, id_requirement_, *std::move(output_prefix)); } bool AesCtrHmacAeadKey::operator==(const Key& other) const { const AesCtrHmacAeadKey* that = dynamic_cast(&other); if (that == nullptr) return false; return GetParameters() == that->GetParameters() && aes_key_bytes_ == that->aes_key_bytes_ && hmac_key_bytes_ == that->hmac_key_bytes_ && id_requirement_ == that->id_requirement_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_ctr_hmac_aead_key.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_AES_CTR_HMAC_AEAD_KEY_H_ #define TINK_AEAD_AES_CTR_HMAC_AEAD_KEY_H_ #include #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/aead/aead_key.h" #include "tink/aead/aes_ctr_hmac_aead_parameters.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Represents an AEAD that uses AES-CTR_HMAC. class AesCtrHmacAeadKey : public AeadKey { public: // Copyable and movable. AesCtrHmacAeadKey(const AesCtrHmacAeadKey& other) = default; AesCtrHmacAeadKey& operator=(const AesCtrHmacAeadKey& other) = default; AesCtrHmacAeadKey(AesCtrHmacAeadKey&& other) = default; AesCtrHmacAeadKey& operator=(AesCtrHmacAeadKey&& other) = default; // Creates an AES-CTR-HMAC-AEAD key instance. class Builder { public: // Copyable and movable. Builder(const Builder& other) = default; Builder& operator=(const Builder& other) = default; Builder(Builder&& other) = default; Builder& operator=(Builder&& other) = default; // Creates initially empty private key builder. Builder() = default; Builder& SetParameters(const AesCtrHmacAeadParameters& parameters); Builder& SetAesKeyBytes(const RestrictedData& aes_key_bytes); Builder& SetHmacKeyBytes(const RestrictedData& hmac_key_bytes); Builder& SetIdRequirement(absl::optional id_requirement); // Creates an AES-CTR-HMAC-AEAD key object from this builder. util::StatusOr Build(PartialKeyAccessToken token); private: absl::optional parameters_; absl::optional aes_key_bytes_; absl::optional hmac_key_bytes_; absl::optional id_requirement_; }; // Returns the underlying AES key bytes. const RestrictedData& GetAesKeyBytes(PartialKeyAccessToken token) const { return aes_key_bytes_; } // Returns the underlying HMAC key bytes. const RestrictedData& GetHmacKeyBytes(PartialKeyAccessToken token) const { return hmac_key_bytes_; } absl::string_view GetOutputPrefix() const override { return output_prefix_; } const AesCtrHmacAeadParameters& GetParameters() const override { return parameters_; } absl::optional GetIdRequirement() const override { return id_requirement_; } bool operator==(const Key& other) const override; private: AesCtrHmacAeadKey(const AesCtrHmacAeadParameters& parameters, const RestrictedData& aes_key_bytes, const RestrictedData& hmac_key_bytes, absl::optional id_requirement, std::string output_prefix) : parameters_(parameters), aes_key_bytes_(aes_key_bytes), hmac_key_bytes_(hmac_key_bytes), id_requirement_(id_requirement), output_prefix_(std::move(output_prefix)) {} AesCtrHmacAeadParameters parameters_; RestrictedData aes_key_bytes_; RestrictedData hmac_key_bytes_; absl::optional id_requirement_; std::string output_prefix_; }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_AES_CTR_HMAC_AEAD_KEY_H_ ================================================ FILE: cc/aead/aes_ctr_hmac_aead_key_manager.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_ctr_hmac_aead_key_manager.h" #include #include #include #include #include #include #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/str_cat.h" #include "tink/aead.h" #include "tink/input_stream.h" #include "tink/mac.h" #include "tink/mac/hmac_key_manager.h" #include "tink/subtle/aes_ctr_boringssl.h" #include "tink/subtle/encrypt_then_authenticate.h" #include "tink/subtle/ind_cpa_cipher.h" #include "tink/subtle/random.h" #include "tink/util/enums.h" #include "tink/util/input_stream_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/aes_ctr.pb.h" #include "proto/aes_ctr_hmac_aead.pb.h" #include "proto/common.pb.h" #include "proto/hmac.pb.h" namespace crypto { namespace tink { namespace { constexpr int kMinKeySizeInBytes = 16; constexpr int kMinIvSizeInBytes = 12; constexpr int kMinTagSizeInBytes = 10; } using ::crypto::tink::util::Enums; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::AesCtrHmacAeadKey; using ::google::crypto::tink::AesCtrHmacAeadKeyFormat; using ::google::crypto::tink::AesCtrKey; using ::google::crypto::tink::HashType; using ::google::crypto::tink::HmacKey; StatusOr AesCtrHmacAeadKeyManager::CreateKey( const AesCtrHmacAeadKeyFormat& aes_ctr_hmac_aead_key_format) const { AesCtrHmacAeadKey aes_ctr_hmac_aead_key; aes_ctr_hmac_aead_key.set_version(get_version()); // Generate AesCtrKey. auto aes_ctr_key = aes_ctr_hmac_aead_key.mutable_aes_ctr_key(); aes_ctr_key->set_version(get_version()); *(aes_ctr_key->mutable_params()) = aes_ctr_hmac_aead_key_format.aes_ctr_key_format().params(); aes_ctr_key->set_key_value(subtle::Random::GetRandomBytes( aes_ctr_hmac_aead_key_format.aes_ctr_key_format().key_size())); // Generate HmacKey. auto hmac_key_or = HmacKeyManager().CreateKey( aes_ctr_hmac_aead_key_format.hmac_key_format()); if (!hmac_key_or.status().ok()) { return hmac_key_or.status(); } *aes_ctr_hmac_aead_key.mutable_hmac_key() = hmac_key_or.value(); return aes_ctr_hmac_aead_key; } StatusOr> AesCtrHmacAeadKeyManager::AeadFactory::Create( const AesCtrHmacAeadKey& key) const { auto aes_ctr_result = subtle::AesCtrBoringSsl::New( util::SecretDataFromStringView(key.aes_ctr_key().key_value()), key.aes_ctr_key().params().iv_size()); if (!aes_ctr_result.ok()) return aes_ctr_result.status(); auto hmac_result = HmacKeyManager().GetPrimitive(key.hmac_key()); if (!hmac_result.ok()) return hmac_result.status(); auto cipher_res = subtle::EncryptThenAuthenticate::New( std::move(aes_ctr_result.value()), std::move(hmac_result.value()), key.hmac_key().params().tag_size()); if (!cipher_res.ok()) { return cipher_res.status(); } return std::move(cipher_res.value()); } Status AesCtrHmacAeadKeyManager::ValidateKey( const AesCtrHmacAeadKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; status = ValidateVersion(key.aes_ctr_key().version(), get_version()); if (!status.ok()) return status; // Validate AesCtrKey. auto aes_ctr_key = key.aes_ctr_key(); uint32_t aes_key_size = aes_ctr_key.key_value().size(); status = ValidateAesKeySize(aes_key_size); if (!status.ok()) { return status; } if (aes_ctr_key.params().iv_size() < kMinIvSizeInBytes || aes_ctr_key.params().iv_size() > 16) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid AesCtrHmacAeadKey: IV size out of range."); } return HmacKeyManager().ValidateKey(key.hmac_key()); } Status AesCtrHmacAeadKeyManager::ValidateKeyFormat( const AesCtrHmacAeadKeyFormat& key_format) const { // Validate AesCtrKeyFormat. auto aes_ctr_key_format = key_format.aes_ctr_key_format(); auto status = ValidateAesKeySize(aes_ctr_key_format.key_size()); if (!status.ok()) { return status; } if (aes_ctr_key_format.params().iv_size() < kMinIvSizeInBytes || aes_ctr_key_format.params().iv_size() > 16) { return util::Status( absl::StatusCode::kInvalidArgument, "Invalid AesCtrHmacAeadKeyFormat: IV size out of range."); } // Validate HmacKeyFormat. auto hmac_key_format = key_format.hmac_key_format(); if (hmac_key_format.key_size() < kMinKeySizeInBytes) { return util::Status( absl::StatusCode::kInvalidArgument, "Invalid AesCtrHmacAeadKeyFormat: HMAC key_size is too small."); } auto params = hmac_key_format.params(); if (params.tag_size() < kMinTagSizeInBytes) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid HmacParams: tag_size ", params.tag_size(), " is too small.")); } std::map max_tag_size = {{HashType::SHA1, 20}, {HashType::SHA224, 28}, {HashType::SHA256, 32}, {HashType::SHA384, 48}, {HashType::SHA512, 64}}; if (max_tag_size.find(params.hash()) == max_tag_size.end()) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid HmacParams: HashType '", Enums::HashName(params.hash()), "' not supported.")); } else { if (params.tag_size() > max_tag_size[params.hash()]) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid HmacParams: tag_size ", params.tag_size(), " is too big for HashType '", Enums::HashName(params.hash()), "'.")); } } return HmacKeyManager().ValidateKeyFormat(key_format.hmac_key_format()); } // To ensure the resulting key can provide key commitment, the AES-CTR key must // be derived first, then the HMAC key. This avoids situation where it's // possible to brute force raw key material so that the 32th byte of the // keystream is a 0 Give party A a key with this raw key material, saying that // the size of the HMAC key is 32 bytes and the size of the AES key is 16 bytes. // Give party B a key with this raw key material, saying that the size of the // HMAC key is 31 bytes and the size of the AES key is 16 bytes. Since HMAC will // pad the key with zeroes, this leads to both parties using the same HMAC key, // but a different AES key (offset by 1 byte) StatusOr AesCtrHmacAeadKeyManager::DeriveKey( const AesCtrHmacAeadKeyFormat& key_format, InputStream* input_stream) const { Status status = ValidateKeyFormat(key_format); if (!status.ok()) { return status; } StatusOr aes_ctr_randomness = ReadBytesFromStream( key_format.aes_ctr_key_format().key_size(), input_stream); if (!aes_ctr_randomness.ok()) { if (absl::IsOutOfRange(aes_ctr_randomness.status())) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, "Could not get enough pseudorandomness from input stream"); } return aes_ctr_randomness.status(); } StatusOr hmac_key = HmacKeyManager().DeriveKey(key_format.hmac_key_format(), input_stream); if (!hmac_key.ok()) { return hmac_key.status(); } google::crypto::tink::AesCtrHmacAeadKey key; key.set_version(get_version()); *key.mutable_hmac_key() = hmac_key.value(); AesCtrKey* aes_ctr_key = key.mutable_aes_ctr_key(); aes_ctr_key->set_version(get_version()); aes_ctr_key->set_key_value(aes_ctr_randomness.value()); *aes_ctr_key->mutable_params() = key_format.aes_ctr_key_format().params(); status = ValidateKey(key); if (!status.ok()) { return status; } return key; } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_ctr_hmac_aead_key_manager.h ================================================ // Copyright 2017 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_AES_CTR_HMAC_AEAD_KEY_MANAGER_H_ #define TINK_AEAD_AES_CTR_HMAC_AEAD_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/aead.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/input_stream.h" #include "tink/internal/fips_utils.h" #include "tink/util/constants.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/aes_ctr_hmac_aead.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class AesCtrHmacAeadKeyManager : public KeyTypeManager> { public: class AeadFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::AesCtrHmacAeadKey& key) const override; }; AesCtrHmacAeadKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::SYMMETRIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::AesCtrHmacAeadKey& key) const override; crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::AesCtrHmacAeadKeyFormat& key) const override; crypto::tink::util::StatusOr CreateKey(const google::crypto::tink::AesCtrHmacAeadKeyFormat& key_format) const override; crypto::tink::util::StatusOr DeriveKey(const google::crypto::tink::AesCtrHmacAeadKeyFormat& key_format, InputStream* input_stream) const override; internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: const std::string key_type_ = absl::StrCat(kTypeGoogleapisCom, google::crypto::tink::AesCtrHmacAeadKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_AES_CTR_HMAC_AEAD_KEY_MANAGER_H_ ================================================ FILE: cc/aead/aes_ctr_hmac_aead_key_manager_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_ctr_hmac_aead_key_manager.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/aead.h" #include "tink/subtle/aead_test_util.h" #include "tink/subtle/aes_ctr_boringssl.h" #include "tink/subtle/encrypt_then_authenticate.h" #include "tink/subtle/hmac_boringssl.h" #include "tink/subtle/ind_cpa_cipher.h" #include "tink/util/enums.h" #include "tink/util/istream_input_stream.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/aes_ctr.pb.h" #include "proto/aes_ctr_hmac_aead.pb.h" #include "proto/common.pb.h" #include "proto/hmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::IstreamInputStream; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::AesCtrHmacAeadKey; using ::google::crypto::tink::AesCtrHmacAeadKeyFormat; using ::google::crypto::tink::HashType; using ::testing::Eq; using ::testing::Not; using ::testing::SizeIs; namespace { TEST(AesCtrHmacAeadKeyManagerTest, Basics) { EXPECT_THAT(AesCtrHmacAeadKeyManager().get_version(), Eq(0)); EXPECT_THAT(AesCtrHmacAeadKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.AesCtrHmacAeadKey")); EXPECT_THAT(AesCtrHmacAeadKeyManager().key_material_type(), Eq(google::crypto::tink::KeyData::SYMMETRIC)); } TEST(AesCtrHmacAeadKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(AesCtrHmacAeadKeyManager().ValidateKey(AesCtrHmacAeadKey()), StatusIs(absl::StatusCode::kInvalidArgument)); } AesCtrHmacAeadKey CreateValidKey() { AesCtrHmacAeadKey key; key.set_version(0); auto aes_ctr_key = key.mutable_aes_ctr_key(); aes_ctr_key->set_key_value(std::string(16, 'a')); aes_ctr_key->mutable_params()->set_iv_size(12); auto hmac_key = key.mutable_hmac_key(); hmac_key->set_key_value(std::string(16, 'b')); hmac_key->mutable_params()->set_hash(HashType::SHA1); hmac_key->mutable_params()->set_tag_size(10); return key; } TEST(AesCtrHmacAeadKeyManagerTest, ValidKey) { EXPECT_THAT(AesCtrHmacAeadKeyManager().ValidateKey(CreateValidKey()), IsOk()); } TEST(AesCtrHmacAeadKeyManagerTest, AesKeySizes) { AesCtrHmacAeadKey key = CreateValidKey(); for (int len = 0; len < 42; len++) { key.mutable_aes_ctr_key()->set_key_value(std::string(len, 'a')); if (len == 16 || len == 32) { EXPECT_THAT(AesCtrHmacAeadKeyManager().ValidateKey(key), IsOk()) << " for length " << len; } else { EXPECT_THAT(AesCtrHmacAeadKeyManager().ValidateKey(key), Not(IsOk())) << " for length " << len; } } } TEST(AesCtrHmacAeadKeyManagerTest, HmacKeySizes) { AesCtrHmacAeadKey key = CreateValidKey(); for (int len = 0; len < 42; len++) { key.mutable_hmac_key()->set_key_value(std::string(len, 'b')); if (len >= 16) { EXPECT_THAT(AesCtrHmacAeadKeyManager().ValidateKey(key), IsOk()) << " for length " << len; } else { EXPECT_THAT(AesCtrHmacAeadKeyManager().ValidateKey(key), Not(IsOk())) << " for length " << len; } } } AesCtrHmacAeadKeyFormat CreateValidKeyFormat() { AesCtrHmacAeadKeyFormat key_format; auto aes_ctr_key_format = key_format.mutable_aes_ctr_key_format(); aes_ctr_key_format->set_key_size(16); aes_ctr_key_format->mutable_params()->set_iv_size(16); auto hmac_key_format = key_format.mutable_hmac_key_format(); hmac_key_format->set_key_size(21); hmac_key_format->mutable_params()->set_hash(HashType::SHA256); hmac_key_format->mutable_params()->set_tag_size(16); return key_format; } TEST(AesCtrHmacAeadKeyManagerTest, ValidateKeyFormat) { AesCtrHmacAeadKeyFormat key_format = CreateValidKeyFormat(); EXPECT_THAT( AesCtrHmacAeadKeyManager().ValidateKeyFormat(CreateValidKeyFormat()), IsOk()); } TEST(AesCtrHmacAeadKeyManagerTest, ValidateEmptyKeyFormat) { EXPECT_THAT( AesCtrHmacAeadKeyManager().ValidateKeyFormat(AesCtrHmacAeadKeyFormat()), Not(IsOk())); } TEST(AesCtrHmacAeadKeyManagerTest, ValidateKeyFormatKeySizes) { AesCtrHmacAeadKeyFormat key_format = CreateValidKeyFormat(); for (int len = 0; len < 42; ++len) { key_format.mutable_aes_ctr_key_format()->set_key_size(len); IstreamInputStream input_stream{absl::make_unique( "0123456789abcde0123456789abcdefghijklmnopqrztuvwxyz0123456789abcde01" "23456789abcdefghijklmnopqrztuvwxyz0123456789abcde0123456789abcdefghi" "jklmnopqrztuvwxyz")}; if (len == 16 || len == 32) { EXPECT_THAT(AesCtrHmacAeadKeyManager().ValidateKeyFormat(key_format), IsOk()) << "for length " << len; EXPECT_THAT( AesCtrHmacAeadKeyManager().DeriveKey(key_format, &input_stream), IsOk()); } else { EXPECT_THAT(AesCtrHmacAeadKeyManager().ValidateKeyFormat(key_format), Not(IsOk())) << "for length " << len; EXPECT_THAT( AesCtrHmacAeadKeyManager().DeriveKey(key_format, &input_stream), Not(IsOk())); } } } TEST(AesCtrHmacAeadKeyManagerTest, ValidateKeyFormatHmacKeySizes) { AesCtrHmacAeadKeyFormat key_format = CreateValidKeyFormat(); for (int len = 0; len < 42; ++len) { key_format.mutable_hmac_key_format()->set_key_size(len); IstreamInputStream input_stream{absl::make_unique( "0123456789abcde0123456789abcdefghijklmnopqrztuvwxyz0123456789abcde01" "23456789abcdefghijklmnopqrztuvwxyz0123456789abcde0123456789abcdefghi" "jklmnopqrztuvwxyz")}; if (len >= 16) { EXPECT_THAT(AesCtrHmacAeadKeyManager().ValidateKeyFormat(key_format), IsOk()) << "for length " << len; EXPECT_THAT( AesCtrHmacAeadKeyManager().DeriveKey(key_format, &input_stream), IsOk()); } else { EXPECT_THAT(AesCtrHmacAeadKeyManager().ValidateKeyFormat(key_format), Not(IsOk())) << "for length " << len; EXPECT_THAT( AesCtrHmacAeadKeyManager().DeriveKey(key_format, &input_stream), Not(IsOk())); } } } TEST(AesCtrHmacAeadKeyManagerTest, CreateKey) { AesCtrHmacAeadKeyFormat key_format = CreateValidKeyFormat(); StatusOr key_or = AesCtrHmacAeadKeyManager().CreateKey(key_format); ASSERT_THAT(key_or, IsOk()); const AesCtrHmacAeadKey& key = key_or.value(); EXPECT_THAT(AesCtrHmacAeadKeyManager().ValidateKey(key), IsOk()); EXPECT_THAT(key.aes_ctr_key().params().iv_size(), Eq(key_format.aes_ctr_key_format().params().iv_size())); EXPECT_THAT(key.aes_ctr_key().key_value(), SizeIs(key_format.aes_ctr_key_format().key_size())); EXPECT_THAT(key.hmac_key().params().hash(), Eq(key_format.hmac_key_format().params().hash())); EXPECT_THAT(key.hmac_key().params().tag_size(), Eq(key_format.hmac_key_format().params().tag_size())); EXPECT_THAT(key.hmac_key().key_value(), SizeIs(key_format.hmac_key_format().key_size())); } TEST(AesCtrHmacAeadKeyManagerTest, CreateAead) { AesCtrHmacAeadKey key = CreateValidKey(); StatusOr> aead_or = AesCtrHmacAeadKeyManager().GetPrimitive(key); ASSERT_THAT(aead_or, IsOk()); auto direct_aes_ctr_or = subtle::AesCtrBoringSsl::New( util::SecretDataFromStringView(key.aes_ctr_key().key_value()), key.aes_ctr_key().params().iv_size()); ASSERT_THAT(direct_aes_ctr_or, IsOk()); auto direct_hmac_or = subtle::HmacBoringSsl::New( util::Enums::ProtoToSubtle(key.hmac_key().params().hash()), key.hmac_key().params().tag_size(), util::SecretDataFromStringView(key.hmac_key().key_value())); ASSERT_THAT(direct_hmac_or, IsOk()); auto direct_aead_or = subtle::EncryptThenAuthenticate::New( std::move(direct_aes_ctr_or.value()), std::move(direct_hmac_or.value()), key.hmac_key().params().tag_size()); ASSERT_THAT(direct_aead_or, IsOk()); EXPECT_THAT(EncryptThenDecrypt(*aead_or.value(), *direct_aead_or.value(), "message", "aad"), IsOk()); } TEST(AesCtrHmacAeadKeyManagerTest, Derive16ByteKey) { AesCtrHmacAeadKeyFormat key_format; key_format.mutable_aes_ctr_key_format()->set_key_size(16); key_format.mutable_aes_ctr_key_format()->mutable_params()->set_iv_size(16); key_format.mutable_hmac_key_format()->set_key_size(16); key_format.mutable_hmac_key_format()->mutable_params()->set_tag_size(16); key_format.mutable_hmac_key_format()->mutable_params()->set_hash( google::crypto::tink::SHA256); key_format.mutable_hmac_key_format()->set_version(0); IstreamInputStream input_stream{absl::make_unique( "0123456789abcde_YELLOW_SUBMARINE_EXTRA")}; StatusOr derived_key = AesCtrHmacAeadKeyManager().DeriveKey(key_format, &input_stream); ASSERT_THAT(derived_key, IsOk()); EXPECT_THAT(derived_key.value().aes_ctr_key().key_value(), Eq("0123456789abcde_")); EXPECT_THAT(derived_key.value().hmac_key().key_value(), Eq("YELLOW_SUBMARINE")); EXPECT_THAT(derived_key.value().hmac_key().params().hash(), key_format.hmac_key_format().params().hash()); EXPECT_THAT(derived_key.value().hmac_key().params().tag_size(), key_format.hmac_key_format().params().tag_size()); EXPECT_THAT(derived_key.value().aes_ctr_key().params().iv_size(), Eq(key_format.aes_ctr_key_format().params().iv_size())); } TEST(AesCtrHmacAeadKeyManagerTest, Derive32ByteKey) { AesCtrHmacAeadKeyFormat format; format.mutable_aes_ctr_key_format()->set_key_size(32); format.mutable_aes_ctr_key_format()->mutable_params()->set_iv_size(16); format.mutable_hmac_key_format()->set_key_size(32); format.mutable_hmac_key_format()->mutable_params()->set_tag_size(16); format.mutable_hmac_key_format()->mutable_params()->set_hash( google::crypto::tink::SHA256); format.mutable_hmac_key_format()->set_version(0); IstreamInputStream input_stream{absl::make_unique( "0123456789abcde0123456789abcdef_YELLOW_SUBMARINE_YELLOW_SUBMARIN")}; StatusOr derived_key = AesCtrHmacAeadKeyManager().DeriveKey(format, &input_stream); ASSERT_THAT(derived_key, IsOk()); EXPECT_THAT(derived_key.value().aes_ctr_key().key_value(), Eq("0123456789abcde0123456789abcdef_")); EXPECT_THAT(derived_key.value().hmac_key().key_value(), Eq("YELLOW_SUBMARINE_YELLOW_SUBMARIN")); } TEST(AesCtrHmacAeadKeyManagerTest, DeriveKeyNotEnoughRandomnessForAesCtrKey) { AesCtrHmacAeadKeyFormat format; format.mutable_aes_ctr_key_format()->set_key_size(32); format.mutable_aes_ctr_key_format()->mutable_params()->set_iv_size(16); format.mutable_hmac_key_format()->set_key_size(32); format.mutable_hmac_key_format()->mutable_params()->set_tag_size(16); format.mutable_hmac_key_format()->mutable_params()->set_hash( google::crypto::tink::SHA256); format.mutable_hmac_key_format()->set_version(0); IstreamInputStream input_stream{ absl::make_unique("0123456789")}; ASSERT_THAT( AesCtrHmacAeadKeyManager().DeriveKey(format, &input_stream).status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesCtrHmacAeadKeyManagerTest, DeriveKeyNotEnoughRandomnessForHmacKey) { AesCtrHmacAeadKeyFormat format; format.mutable_aes_ctr_key_format()->set_key_size(16); format.mutable_aes_ctr_key_format()->mutable_params()->set_iv_size(16); format.mutable_hmac_key_format()->set_key_size(32); format.mutable_hmac_key_format()->mutable_params()->set_tag_size(16); format.mutable_hmac_key_format()->mutable_params()->set_hash( google::crypto::tink::SHA256); format.mutable_hmac_key_format()->set_version(0); IstreamInputStream input_stream{ absl::make_unique("YELLOW_SUBMARINE")}; ASSERT_THAT( AesCtrHmacAeadKeyManager().DeriveKey(format, &input_stream).status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_ctr_hmac_aead_key_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_ctr_hmac_aead_key.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/aead/aes_ctr_hmac_aead_parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { int aes_key_size; int hmac_key_size; int iv_size; int tag_size; AesCtrHmacAeadParameters::HashType hash_type; AesCtrHmacAeadParameters::Variant variant; absl::optional id_requirement; std::string output_prefix; }; using AesCtrHmacAeadKeyTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( AesCtrHmacAeadKeyBuildTestSuite, AesCtrHmacAeadKeyTest, Values(TestCase{/*aes_key_size=*/16, /*hmac_key_size=*/16, /*iv_size=*/12, /*tag_size=*/28, AesCtrHmacAeadParameters::HashType::kSha256, AesCtrHmacAeadParameters::Variant::kTink, /*id_requirement=*/0x02030400, std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{/*aes_key_size=*/24, /*hmac_key_size=*/32, /*iv_size=*/16, /*tag_size=*/32, AesCtrHmacAeadParameters::HashType::kSha384, AesCtrHmacAeadParameters::Variant::kCrunchy, /*id_requirement=*/0x01030005, std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{/*aes_key_size=*/32, /*hmac_key_size=*/16, /*iv_size=*/16, /*tag_size=*/48, AesCtrHmacAeadParameters::HashType::kSha512, AesCtrHmacAeadParameters::Variant::kNoPrefix, /*id_requirement=*/absl::nullopt, ""})); TEST_P(AesCtrHmacAeadKeyTest, BuildKeySucceeds) { TestCase test_case = GetParam(); util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(test_case.aes_key_size) .SetHmacKeySizeInBytes(test_case.hmac_key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(test_case.tag_size) .SetHashType(test_case.hash_type) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); RestrictedData aes_secret = RestrictedData(test_case.aes_key_size); RestrictedData hmac_secret = RestrictedData(test_case.hmac_key_size); util::StatusOr key = AesCtrHmacAeadKey::Builder() .SetParameters(*parameters) .SetAesKeyBytes(aes_secret) .SetHmacKeyBytes(hmac_secret) .SetIdRequirement(test_case.id_requirement) .Build(GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); EXPECT_THAT(key->GetParameters(), Eq(*parameters)); EXPECT_THAT(key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(key->GetOutputPrefix(), Eq(test_case.output_prefix)); EXPECT_THAT(key->GetAesKeyBytes(GetPartialKeyAccess()), Eq(aes_secret)); EXPECT_THAT(key->GetHmacKeyBytes(GetPartialKeyAccess()), Eq(hmac_secret)); } TEST(AesCtrHmacAeadKeyTest, BuildKeyWithMismatchedAesKeySizeFails) { // AES key size parameter is 32 bytes. util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(32) .SetHmacKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(32) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); // AES key material size is 16 bytes (also a valid key length). RestrictedData aes_secret = RestrictedData(/*num_random_bytes=*/16); RestrictedData hmac_secret = RestrictedData(/*num_random_bytes=*/32); EXPECT_THAT(AesCtrHmacAeadKey::Builder() .SetParameters(*parameters) .SetAesKeyBytes(aes_secret) .SetHmacKeyBytes(hmac_secret) .SetIdRequirement(123) .Build(GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("AES key size does not match"))); } TEST(AesCtrHmacAeadKeyTest, BuildKeyWithoutSettingAParametersFails) { RestrictedData aes_secret = RestrictedData(/*num_random_bytes=*/32); RestrictedData hmac_secret = RestrictedData(/*num_random_bytes=*/32); EXPECT_THAT( AesCtrHmacAeadKey::Builder() .SetAesKeyBytes(aes_secret) .SetHmacKeyBytes(hmac_secret) .SetIdRequirement(123) .Build(GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Cannot build without setting the parameters"))); } TEST(AesCtrHmacAeadKeyTest, BuildKeyWithoutSettingAesKeySizeFails) { util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(32) .SetHmacKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(32) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); RestrictedData hmac_secret = RestrictedData(/*num_random_bytes=*/32); EXPECT_THAT(AesCtrHmacAeadKey::Builder() .SetParameters(*parameters) .SetHmacKeyBytes(hmac_secret) .SetIdRequirement(123) .Build(GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Cannot build without AES key material"))); } TEST(AesCtrHmacAeadKeyTest, BuildKeyWithoutSettingHmacKeySizeFails) { util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(32) .SetHmacKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(32) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); RestrictedData aes_secret = RestrictedData(/*num_random_bytes=*/32); EXPECT_THAT( AesCtrHmacAeadKey::Builder() .SetParameters(*parameters) .SetAesKeyBytes(aes_secret) .SetIdRequirement(123) .Build(GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Cannot build without HMAC key material"))); } TEST(AesCtrHmacAeadKeyTest, BuildKeyWithMismatchedHmacKeySizeFails) { // HMAC key size parameter is 32 bytes. util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(32) .SetHmacKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(32) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); // HMAC key material size is 16 bytes (also a valid key length). RestrictedData aes_secret = RestrictedData(/*num_random_bytes=*/32); RestrictedData hmac_secret = RestrictedData(/*num_random_bytes=*/16); EXPECT_THAT(AesCtrHmacAeadKey::Builder() .SetParameters(*parameters) .SetAesKeyBytes(aes_secret) .SetHmacKeyBytes(hmac_secret) .SetIdRequirement(123) .Build(GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("HMAC key size does not match"))); } TEST(AesCtrHmacAeadKeyTest, BuildNoPrefixKeyWithIdRequirementFails) { util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(32) .SetHmacKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(32) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); RestrictedData aes_secret = RestrictedData(/*num_random_bytes=*/32); RestrictedData hmac_secret = RestrictedData(/*num_random_bytes=*/32); EXPECT_THAT( AesCtrHmacAeadKey::Builder() .SetParameters(*parameters) .SetAesKeyBytes(aes_secret) .SetHmacKeyBytes(hmac_secret) .SetIdRequirement(123) .Build(GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Cannot create key with ID requirement with " "parameters without ID requirement"))); } TEST(AesCtrHmacAeadKeyTest, BuildTinkKeyWithoutIdRequirementFails) { util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(32) .SetHmacKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(32) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); RestrictedData aes_secret = RestrictedData(/*num_random_bytes=*/32); RestrictedData hmac_secret = RestrictedData(/*num_random_bytes=*/32); EXPECT_THAT(AesCtrHmacAeadKey::Builder() .SetParameters(*parameters) .SetAesKeyBytes(aes_secret) .SetHmacKeyBytes(hmac_secret) .Build(GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Cannot create key without ID requirement " "with parameters with ID requirement"))); } TEST_P(AesCtrHmacAeadKeyTest, KeyEquals) { TestCase test_case = GetParam(); util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(test_case.aes_key_size) .SetHmacKeySizeInBytes(test_case.hmac_key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(test_case.tag_size) .SetHashType(test_case.hash_type) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); RestrictedData aes_secret = RestrictedData(test_case.aes_key_size); RestrictedData hmac_secret = RestrictedData(test_case.hmac_key_size); util::StatusOr key = AesCtrHmacAeadKey::Builder() .SetParameters(*parameters) .SetAesKeyBytes(aes_secret) .SetHmacKeyBytes(hmac_secret) .SetIdRequirement(test_case.id_requirement) .Build(GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = AesCtrHmacAeadKey::Builder() .SetParameters(*parameters) .SetAesKeyBytes(aes_secret) .SetHmacKeyBytes(hmac_secret) .SetIdRequirement(test_case.id_requirement) .Build(GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key == *other_key); EXPECT_TRUE(*other_key == *key); EXPECT_FALSE(*key != *other_key); EXPECT_FALSE(*other_key != *key); } TEST(AesCtrHmacAeadKeyTest, DifferentParametersKeysNotEqual) { util::StatusOr tink_parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(32) .SetHmacKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(32) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kTink) .Build(); ASSERT_THAT(tink_parameters, IsOk()); util::StatusOr crunchy_parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(32) .SetHmacKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(32) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kCrunchy) .Build(); ASSERT_THAT(crunchy_parameters, IsOk()); RestrictedData aes_secret = RestrictedData(/*num_random_bytes=*/32); RestrictedData hmac_secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr tink_key = AesCtrHmacAeadKey::Builder() .SetParameters(*tink_parameters) .SetAesKeyBytes(aes_secret) .SetHmacKeyBytes(hmac_secret) .SetIdRequirement(0x01020304) .Build(GetPartialKeyAccess()); ASSERT_THAT(tink_key, IsOk()); util::StatusOr crunchy_key = AesCtrHmacAeadKey::Builder() .SetParameters(*crunchy_parameters) .SetAesKeyBytes(aes_secret) .SetHmacKeyBytes(hmac_secret) .SetIdRequirement(0x01020304) .Build(GetPartialKeyAccess()); ASSERT_THAT(crunchy_key, IsOk()); EXPECT_TRUE(*tink_key != *crunchy_key); EXPECT_TRUE(*crunchy_key != *tink_key); EXPECT_FALSE(*tink_key == *crunchy_key); EXPECT_FALSE(*crunchy_key == *tink_key); } TEST(AesCtrHmacAeadKeyTest, DifferentAesKeyMaterialNotEqual) { util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(32) .SetHmacKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(32) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); RestrictedData aes_secret1 = RestrictedData(/*num_random_bytes=*/32); RestrictedData aes_secret2 = RestrictedData(/*num_random_bytes=*/32); RestrictedData hmac_secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = AesCtrHmacAeadKey::Builder() .SetParameters(*parameters) .SetAesKeyBytes(aes_secret1) .SetHmacKeyBytes(hmac_secret) .SetIdRequirement(0x01020304) .Build(GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = AesCtrHmacAeadKey::Builder() .SetParameters(*parameters) .SetAesKeyBytes(aes_secret2) .SetHmacKeyBytes(hmac_secret) .SetIdRequirement(0x01020304) .Build(GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST(AesCtrHmacAeadKeyTest, DifferentHmacKeyMaterialNotEqual) { util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(32) .SetHmacKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(32) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); RestrictedData aes_secret = RestrictedData(/*num_random_bytes=*/32); RestrictedData hmac_secret1 = RestrictedData(/*num_random_bytes=*/32); RestrictedData hmac_secret2 = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = AesCtrHmacAeadKey::Builder() .SetParameters(*parameters) .SetAesKeyBytes(aes_secret) .SetHmacKeyBytes(hmac_secret1) .SetIdRequirement(0x01020304) .Build(GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = AesCtrHmacAeadKey::Builder() .SetParameters(*parameters) .SetAesKeyBytes(aes_secret) .SetHmacKeyBytes(hmac_secret2) .SetIdRequirement(0x01020304) .Build(GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST(AesCtrHmacAeadKeyTest, DifferentIdRequirementKeysNotEqual) { util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(32) .SetHmacKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(32) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); RestrictedData aes_secret = RestrictedData(/*num_random_bytes=*/32); RestrictedData hmac_secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = AesCtrHmacAeadKey::Builder() .SetParameters(*parameters) .SetAesKeyBytes(aes_secret) .SetHmacKeyBytes(hmac_secret) .SetIdRequirement(0x01020304) .Build(GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = AesCtrHmacAeadKey::Builder() .SetParameters(*parameters) .SetAesKeyBytes(aes_secret) .SetHmacKeyBytes(hmac_secret) .SetIdRequirement(0x02030405) .Build(GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_ctr_hmac_aead_parameters.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_ctr_hmac_aead_parameters.h" #include #include "absl/algorithm/container.h" #include "absl/container/flat_hash_map.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/parameters.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { AesCtrHmacAeadParameters::Builder& AesCtrHmacAeadParameters::Builder::SetAesKeySizeInBytes(int aes_key_size) { aes_key_size_in_bytes_ = aes_key_size; return *this; } AesCtrHmacAeadParameters::Builder& AesCtrHmacAeadParameters::Builder::SetHmacKeySizeInBytes(int hmac_key_size) { hmac_key_size_in_bytes_ = hmac_key_size; return *this; } AesCtrHmacAeadParameters::Builder& AesCtrHmacAeadParameters::Builder::SetIvSizeInBytes(int iv_size) { iv_size_in_bytes_ = iv_size; return *this; } AesCtrHmacAeadParameters::Builder& AesCtrHmacAeadParameters::Builder::SetTagSizeInBytes(int tag_size) { tag_size_in_bytes_ = tag_size; return *this; } AesCtrHmacAeadParameters::Builder& AesCtrHmacAeadParameters::Builder::SetHashType(HashType hash_type) { hash_type_ = hash_type; return *this; } AesCtrHmacAeadParameters::Builder& AesCtrHmacAeadParameters::Builder::SetVariant(Variant variant) { variant_ = variant; return *this; } util::StatusOr AesCtrHmacAeadParameters::Builder::Build() { if (!aes_key_size_in_bytes_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "AES key size is not set."); } if (!hmac_key_size_in_bytes_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "HMAC key size is not set."); } if (!iv_size_in_bytes_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "IV size is not set."); } if (!tag_size_in_bytes_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Tag size is not set."); } if (!hash_type_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Hash type is not set."); } if (!variant_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Variant is not set."); } if (*aes_key_size_in_bytes_ != 16 && *aes_key_size_in_bytes_ != 24 && *aes_key_size_in_bytes_ != 32) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("AES key size should be 16, 24, or 32 bytes, got ", *aes_key_size_in_bytes_, " bytes.")); } if (*hmac_key_size_in_bytes_ < 16) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("HMAC key size should have at least 16 bytes, got ", *hmac_key_size_in_bytes_, " bytes.")); } if (*iv_size_in_bytes_ < 12 || *iv_size_in_bytes_ > 16) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("IV size should be betwwen 12 and 16 bytes, got ", *iv_size_in_bytes_, " bytes.")); } if (*tag_size_in_bytes_ < 10) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Tag size should have at least 10 bytes, got ", *tag_size_in_bytes_, " bytes.")); } // The maximum allowed value of the tag size is limited by the hash type used. static const absl::flat_hash_map* kMaxTagSizes = new absl::flat_hash_map{{HashType::kSha1, 20}, {HashType::kSha224, 28}, {HashType::kSha256, 32}, {HashType::kSha384, 48}, {HashType::kSha512, 64}}; if (kMaxTagSizes->find(*hash_type_) == kMaxTagSizes->end()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create AesCtrHmacAeadParameters with unknown hash type."); } else { if (*tag_size_in_bytes_ > kMaxTagSizes->at(*hash_type_)) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Tag size ", *tag_size_in_bytes_, " is too big for given hash type.")); } } static constexpr Variant kSupportedVariants[] = { Variant::kTink, Variant::kCrunchy, Variant::kNoPrefix}; if (!absl::c_linear_search(kSupportedVariants, *variant_)) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create AesCtrHmacAeadParameters with unknown Variant."); } return AesCtrHmacAeadParameters(*aes_key_size_in_bytes_, *hmac_key_size_in_bytes_, *iv_size_in_bytes_, *tag_size_in_bytes_, *hash_type_, *variant_); } bool AesCtrHmacAeadParameters::operator==(const Parameters& other) const { const AesCtrHmacAeadParameters* that = dynamic_cast(&other); if (that == nullptr) return false; return aes_key_size_in_bytes_ == that->aes_key_size_in_bytes_ && hmac_key_size_in_bytes_ == that->hmac_key_size_in_bytes_ && iv_size_in_bytes_ == that->iv_size_in_bytes_ && tag_size_in_bytes_ == that->tag_size_in_bytes_ && hash_type_ == that->hash_type_ && variant_ == that->variant_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_ctr_hmac_aead_parameters.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_AES_CTR_HMAC_AEAD_PARAMETERS_H_ #define TINK_AEAD_AES_CTR_HMAC_AEAD_PARAMETERS_H_ #include #include "absl/types/optional.h" #include "tink/aead/aead_parameters.h" #include "tink/parameters.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Describes the parameters of an `AesCtrHmacAead`. // // The choices for the parameters values are restricted to a certain set of // options: // - The AES key size accepts values of 16, 24, or 32 bytes. Current // implementation only offers support for 16-byte and 32-byte keys. // - The HMAC key size must be at least 16 bytes. // - The IV size accepts values between 12 and 16 bytes. // - The tag size accepts values between 10 and 64 bytes and depends on the // corresponding hash function as follows: // - SHA1 - at most 20 bytes tag size // - SHA224 - at most 28 bytes tag size // - SHA256 - at most 32 bytes tag size // - SHA384 - at most 48 bytes tag size // - SHA512 - at most 64 bytes tag size // // WARNING: Some of the values accepted by this class may // actually be a superset of what is currently supported by the key type // implementations. Specifying a larger set of value (i.e. 24-byte AES keys) // aligns with a future possibility to add support for such parameters, if // needed. class AesCtrHmacAeadParameters : public AeadParameters { public: // Describes the output prefix prepended to the ciphertext. enum class Variant : int { // Prepends '0x01' to the ciphertext. kTink = 1, // Prepends '0x00' to the ciphertext. kCrunchy = 2, // Does not prepend any prefix (i.e., keys must have no ID requirement). kNoPrefix = 3, // Added to guard from failures that may be caused by future expansions. kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Describes the hash algorithm used. enum class HashType : int { kSha1 = 1, kSha224 = 2, kSha256 = 3, kSha384 = 4, kSha512 = 5, kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Creates AES-CTR-HMAC-AEAD parameters instances. class Builder { public: // Copyable and movable. Builder(const Builder& other) = default; Builder& operator=(const Builder& other) = default; Builder(Builder&& other) = default; Builder& operator=(Builder&& other) = default; // Creates initially empty parameters builder. Builder() = default; Builder& SetAesKeySizeInBytes(int aes_key_size); Builder& SetHmacKeySizeInBytes(int hmac_key_size); Builder& SetIvSizeInBytes(int iv_size); Builder& SetTagSizeInBytes(int tag_size); Builder& SetHashType(HashType hash_type); Builder& SetVariant(Variant variant); // Creates AES-CTR-HMAC-AEAD parameters object from this builder. util::StatusOr Build(); private: absl::optional aes_key_size_in_bytes_; absl::optional hmac_key_size_in_bytes_; absl::optional iv_size_in_bytes_; absl::optional tag_size_in_bytes_; absl::optional hash_type_; absl::optional variant_; }; // Copyable and movable. AesCtrHmacAeadParameters(const AesCtrHmacAeadParameters& other) = default; AesCtrHmacAeadParameters& operator=(const AesCtrHmacAeadParameters& other) = default; AesCtrHmacAeadParameters(AesCtrHmacAeadParameters&& other) = default; AesCtrHmacAeadParameters& operator=(AesCtrHmacAeadParameters&& other) = default; int GetAesKeySizeInBytes() const { return aes_key_size_in_bytes_; } int GetHmacKeySizeInBytes() const { return hmac_key_size_in_bytes_; } int GetIvSizeInBytes() const { return iv_size_in_bytes_; } int GetTagSizeInBytes() const { return tag_size_in_bytes_; } HashType GetHashType() const { return hash_type_; } Variant GetVariant() const { return variant_; } // Returns the size of the tag plus the size of the IV and of // the prefix with which this key prefixes every ciphertext. int CiphertextOverheadSizeInBytes() const; bool HasIdRequirement() const override { return variant_ != Variant::kNoPrefix; } bool operator==(const Parameters& other) const override; private: AesCtrHmacAeadParameters(int aes_key_size_in_bytes, int hmac_key_size_in_bytes, int iv_size_in_bytes, int tag_size_in_bytes, HashType hash_type, Variant variant) : aes_key_size_in_bytes_(aes_key_size_in_bytes), hmac_key_size_in_bytes_(hmac_key_size_in_bytes), iv_size_in_bytes_(iv_size_in_bytes), tag_size_in_bytes_(tag_size_in_bytes), hash_type_(hash_type), variant_(variant) {} int aes_key_size_in_bytes_; int hmac_key_size_in_bytes_; int iv_size_in_bytes_; int tag_size_in_bytes_; HashType hash_type_; Variant variant_; }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_AES_CTR_HMAC_AEAD_PARAMETERS_H_ ================================================ FILE: cc/aead/aes_ctr_hmac_aead_parameters_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_ctr_hmac_aead_parameters.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::TestWithParam; using ::testing::Values; struct BuildTestCase { int aes_key_size; int hmac_key_size; int iv_size; int tag_size; AesCtrHmacAeadParameters::HashType hash_type; AesCtrHmacAeadParameters::Variant variant; bool has_id_requirement; }; using AesCtrHmacAeadParametersTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( AesCtrHmacAeadParametersBuildTestSuite, AesCtrHmacAeadParametersTest, Values(BuildTestCase{/*aes_key_size=*/16, /*hmac_key_size=*/16, /*iv_size=*/12, /*tag_size=*/28, AesCtrHmacAeadParameters::HashType::kSha256, AesCtrHmacAeadParameters::Variant::kTink, /*has_id_requirement=*/true}, BuildTestCase{/*aes_key_size=*/24, /*hmac_key_size=*/32, /*iv_size=*/16, /*tag_size=*/32, AesCtrHmacAeadParameters::HashType::kSha384, AesCtrHmacAeadParameters::Variant::kCrunchy, /*has_id_requirement=*/true}, BuildTestCase{/*aes_key_size=*/32, /*hmac_key_size=*/16, /*iv_size=*/16, /*tag_size=*/48, AesCtrHmacAeadParameters::HashType::kSha512, AesCtrHmacAeadParameters::Variant::kNoPrefix, /*has_id_requirement=*/false})); TEST_P(AesCtrHmacAeadParametersTest, BuildParametersSucceeds) { BuildTestCase test_case = GetParam(); util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(test_case.aes_key_size) .SetHmacKeySizeInBytes(test_case.hmac_key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(test_case.tag_size) .SetHashType(test_case.hash_type) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetAesKeySizeInBytes(), Eq(test_case.aes_key_size)); EXPECT_THAT(parameters->GetHmacKeySizeInBytes(), Eq(test_case.hmac_key_size)); EXPECT_THAT(parameters->GetIvSizeInBytes(), Eq(test_case.iv_size)); EXPECT_THAT(parameters->GetTagSizeInBytes(), Eq(test_case.tag_size)); EXPECT_THAT(parameters->GetHashType(), Eq(test_case.hash_type)); EXPECT_THAT(parameters->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(parameters->HasIdRequirement(), Eq(test_case.has_id_requirement)); } TEST(AesCtrHmacAeadParametersTest, BuildWithoutSettingAesKeySizeFails) { EXPECT_THAT(AesCtrHmacAeadParameters::Builder() .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(32) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("AES key size is not set"))); } TEST(AesCtrHmacAeadParametersTest, BuildWithInvalidAesKeySizeFails) { EXPECT_THAT( AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(17) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(32) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("AES key size should be 16, 24, or 32 bytes"))); } TEST(AesCtrHmacAeadParametersTest, BuildWithoutSettingAHmacKeySizeFails) { EXPECT_THAT(AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(32) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("HMAC key size is not set"))); } TEST(AesCtrHmacAeadParametersTest, BuildWithInvalidHmacKeySizeFails) { EXPECT_THAT( AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(15) .SetIvSizeInBytes(16) .SetTagSizeInBytes(32) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("HMAC key size should have at least 16 bytes"))); } TEST(AesCtrHmacAeadParametersTest, BuildWithoutSettingIvSizeFails) { EXPECT_THAT(AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetTagSizeInBytes(32) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("IV size is not set"))); } TEST(AesCtrHmacAeadParametersTest, BuildWithTooSmallIvSizeFails) { EXPECT_THAT(AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(11) .SetTagSizeInBytes(32) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("IV size should be betwwen 12 and 16 bytes"))); } TEST(AesCtrHmacAeadParametersTest, BuildWithTooBigIvSizeFails) { EXPECT_THAT(AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(17) .SetTagSizeInBytes(32) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("IV size should be betwwen 12 and 16 bytes"))); } TEST(AesCtrHmacAeadParametersTest, BuildWithoutSettingTagSizeFails) { EXPECT_THAT(AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Tag size is not set"))); } TEST(AesCtrHmacAeadParametersTest, BuildWithTooSmallTagSizeFails) { EXPECT_THAT(AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(9) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Tag size should have at least 10 bytes"))); } TEST(AesCtrHmacAeadParametersTest, BuildWithTooBigTagSizeSHA1Fails) { EXPECT_THAT( AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(21) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha1) .SetVariant(AesCtrHmacAeadParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Tag size 21 is too big for given hash type"))); } TEST(AesCtrHmacAeadParametersTest, BuildWithTooBigTagSizeSHA224Fails) { EXPECT_THAT( AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(29) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha224) .SetVariant(AesCtrHmacAeadParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Tag size 29 is too big for given hash type"))); } TEST(AesCtrHmacAeadParametersTest, BuildWithTooBigTagSizeSHA256Fails) { EXPECT_THAT( AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(33) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Tag size 33 is too big for given hash type"))); } TEST(AesCtrHmacAeadParametersTest, BuildWithTooBigTagSizeSHA384Fails) { EXPECT_THAT( AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(49) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha384) .SetVariant(AesCtrHmacAeadParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Tag size 49 is too big for given hash type"))); } TEST(AesCtrHmacAeadParametersTest, BuildWithTooBigTagSizeSHA512Fails) { EXPECT_THAT(AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(65) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha512) .SetVariant(AesCtrHmacAeadParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesCtrHmacAeadParametersTest, BuildWithoutSettingHashTypeFails) { EXPECT_THAT(AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(32) .SetVariant(AesCtrHmacAeadParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Hash type is not set"))); } TEST(AesCtrHmacAeadParametersTest, BuildWithInvalidHashTypeFails) { EXPECT_THAT(AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(32) .SetHashType( AesCtrHmacAeadParameters::HashType:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .SetVariant(AesCtrHmacAeadParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("unknown hash type"))); } TEST(AesCtrHmacAeadParametersTest, BuildWithoutSettingVariantFails) { EXPECT_THAT(AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(32) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Variant is not set"))); } TEST(AesCtrHmacAeadParametersTest, BuildWithInvalidVariantFails) { EXPECT_THAT( AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(32) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("unknown Variant"))); } TEST_P(AesCtrHmacAeadParametersTest, CopyConstructor) { BuildTestCase test_case = GetParam(); util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(test_case.aes_key_size) .SetHmacKeySizeInBytes(test_case.hmac_key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(test_case.tag_size) .SetHashType(test_case.hash_type) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); AesCtrHmacAeadParameters copy(*parameters); EXPECT_THAT(copy.GetAesKeySizeInBytes(), Eq(test_case.aes_key_size)); EXPECT_THAT(copy.GetHmacKeySizeInBytes(), Eq(test_case.hmac_key_size)); EXPECT_THAT(copy.GetIvSizeInBytes(), Eq(test_case.iv_size)); EXPECT_THAT(copy.GetTagSizeInBytes(), Eq(test_case.tag_size)); EXPECT_THAT(copy.GetHashType(), Eq(test_case.hash_type)); EXPECT_THAT(copy.GetVariant(), Eq(test_case.variant)); EXPECT_THAT(copy.HasIdRequirement(), test_case.has_id_requirement); } TEST_P(AesCtrHmacAeadParametersTest, CopyAssignment) { BuildTestCase test_case = GetParam(); util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(test_case.aes_key_size) .SetHmacKeySizeInBytes(test_case.hmac_key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(test_case.tag_size) .SetHashType(test_case.hash_type) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); AesCtrHmacAeadParameters copy = *parameters; EXPECT_THAT(copy.GetAesKeySizeInBytes(), Eq(test_case.aes_key_size)); EXPECT_THAT(copy.GetHmacKeySizeInBytes(), Eq(test_case.hmac_key_size)); EXPECT_THAT(copy.GetIvSizeInBytes(), Eq(test_case.iv_size)); EXPECT_THAT(copy.GetTagSizeInBytes(), Eq(test_case.tag_size)); EXPECT_THAT(copy.GetHashType(), Eq(test_case.hash_type)); EXPECT_THAT(copy.GetVariant(), Eq(test_case.variant)); EXPECT_THAT(copy.HasIdRequirement(), test_case.has_id_requirement); } TEST_P(AesCtrHmacAeadParametersTest, SameParametersEquals) { BuildTestCase test_case = GetParam(); util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(test_case.aes_key_size) .SetHmacKeySizeInBytes(test_case.hmac_key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(test_case.tag_size) .SetHashType(test_case.hash_type) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(test_case.aes_key_size) .SetHmacKeySizeInBytes(test_case.hmac_key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(test_case.tag_size) .SetHashType(test_case.hash_type) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters == *other_parameters); EXPECT_TRUE(*other_parameters == *parameters); EXPECT_FALSE(*parameters != *other_parameters); EXPECT_FALSE(*other_parameters != *parameters); } TEST(AesCtrHmacAeadParametersTest, DifferentAesKeySizeNotEqual) { util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(24) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kTink) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(AesCtrHmacAeadParametersTest, DifferentHmacKeySizeNotEqual) { util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kTink) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(AesCtrHmacAeadParametersTest, DifferentIvSizeNotEqual) { util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(12) .SetTagSizeInBytes(16) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kTink) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(AesCtrHmacAeadParametersTest, DifferentTagSizeNotEqual) { util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(12) .SetTagSizeInBytes(16) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(12) .SetTagSizeInBytes(32) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kTink) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(AesCtrHmacAeadParametersTest, DifferentHashTypeNotEqual) { util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(12) .SetTagSizeInBytes(16) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(12) .SetTagSizeInBytes(16) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha512) .SetVariant(AesCtrHmacAeadParameters::Variant::kTink) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(AesCtrHmacAeadParametersTest, DifferentVariantNotEqual) { util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(12) .SetTagSizeInBytes(16) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(12) .SetTagSizeInBytes(16) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kCrunchy) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_ctr_hmac_aead_proto_serialization.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_ctr_hmac_aead_proto_serialization.h" #include "absl/base/attributes.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/aead/aes_ctr_hmac_aead_key.h" #include "tink/aead/aes_ctr_hmac_aead_parameters.h" #include "tink/internal/key_parser.h" #include "tink/internal/key_serializer.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/parameters_parser.h" #include "tink/internal/parameters_serializer.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/secret_key_access_token.h" #include "tink/util/secret_data.h" #include "tink/util/secret_proto.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/aes_ctr.pb.h" #include "proto/aes_ctr_hmac_aead.pb.h" #include "proto/common.pb.h" #include "proto/hmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::util::SecretData; using ::crypto::tink::util::SecretDataAsStringView; using ::crypto::tink::util::SecretProto; using ::google::crypto::tink::AesCtrHmacAeadKeyFormat; using ::google::crypto::tink::AesCtrKeyFormat; using ::google::crypto::tink::AesCtrParams; using ::google::crypto::tink::HashType; using ::google::crypto::tink::HmacKeyFormat; using ::google::crypto::tink::HmacParams; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using AesCtrHmacAeadProtoParametersParserImpl = internal::ParametersParserImpl; using AesCtrHmacAeadProtoParametersSerializerImpl = internal::ParametersSerializerImpl; using AesCtrHmacAeadProtoKeyParserImpl = internal::KeyParserImpl; using AesCtrHmacAeadProtoKeySerializerImpl = internal::KeySerializerImpl; constexpr absl::string_view kTypeUrl = "type.googleapis.com/google.crypto.tink.AesCtrHmacAeadKey"; util::StatusOr ToVariant( OutputPrefixType output_prefix_type) { switch (output_prefix_type) { case OutputPrefixType::LEGACY: ABSL_FALLTHROUGH_INTENDED; // Parse LEGACY output prefix as CRUNCHY. case OutputPrefixType::CRUNCHY: return AesCtrHmacAeadParameters::Variant::kCrunchy; case OutputPrefixType::RAW: return AesCtrHmacAeadParameters::Variant::kNoPrefix; case OutputPrefixType::TINK: return AesCtrHmacAeadParameters::Variant::kTink; default: return util::Status( absl::StatusCode::kInvalidArgument, "Could not determine AesCtrHmacAeadParameters::Variant"); } } util::StatusOr ToOutputPrefixType( AesCtrHmacAeadParameters::Variant variant) { switch (variant) { case AesCtrHmacAeadParameters::Variant::kCrunchy: return OutputPrefixType::CRUNCHY; case AesCtrHmacAeadParameters::Variant::kNoPrefix: return OutputPrefixType::RAW; case AesCtrHmacAeadParameters::Variant::kTink: return OutputPrefixType::TINK; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine output prefix type"); } } util::StatusOr ToHashType( HashType hash_type) { switch (hash_type) { case HashType::SHA1: return AesCtrHmacAeadParameters::HashType::kSha1; case HashType::SHA224: return AesCtrHmacAeadParameters::HashType::kSha224; case HashType::SHA256: return AesCtrHmacAeadParameters::HashType::kSha256; case HashType::SHA384: return AesCtrHmacAeadParameters::HashType::kSha384; case HashType::SHA512: return AesCtrHmacAeadParameters::HashType::kSha512; default: return util::Status( absl::StatusCode::kInvalidArgument, "Could not determine AesCtrHmacAeadParameters::HashType"); } } util::StatusOr ToProtoHashType( AesCtrHmacAeadParameters::HashType hash_type) { switch (hash_type) { case AesCtrHmacAeadParameters::HashType::kSha1: return HashType::SHA1; case AesCtrHmacAeadParameters::HashType::kSha224: return HashType::SHA224; case AesCtrHmacAeadParameters::HashType::kSha256: return HashType::SHA256; case AesCtrHmacAeadParameters::HashType::kSha384: return HashType::SHA384; case AesCtrHmacAeadParameters::HashType::kSha512: return HashType::SHA512; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine HashType"); } } util::StatusOr GetHmacProtoParams( const AesCtrHmacAeadParameters& parameters) { util::StatusOr proto_hash_type = ToProtoHashType(parameters.GetHashType()); if (!proto_hash_type.ok()) return proto_hash_type.status(); HmacParams hmac_params; hmac_params.set_tag_size(parameters.GetTagSizeInBytes()); hmac_params.set_hash(*proto_hash_type); return hmac_params; } util::StatusOr ParseParameters( const internal::ProtoParametersSerialization& serialization) { if (serialization.GetKeyTemplate().type_url() != kTypeUrl) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Wrong type URL when parsing AesCtrHmacAeadParameters: ", serialization.GetKeyTemplate().type_url())); } AesCtrHmacAeadKeyFormat proto_key_format; if (!proto_key_format.ParseFromString( serialization.GetKeyTemplate().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse AesCtrHmacAeadKeyFormat proto"); } if (proto_key_format.hmac_key_format().version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse hmac key format: only version 0 " "is accepted."); } util::StatusOr variant = ToVariant(serialization.GetKeyTemplate().output_prefix_type()); if (!variant.ok()) { return variant.status(); } util::StatusOr hash_type = ToHashType(proto_key_format.hmac_key_format().params().hash()); if (!hash_type.ok()) { return hash_type.status(); } return AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(proto_key_format.aes_ctr_key_format().key_size()) .SetHmacKeySizeInBytes(proto_key_format.hmac_key_format().key_size()) .SetIvSizeInBytes( proto_key_format.aes_ctr_key_format().params().iv_size()) .SetTagSizeInBytes(proto_key_format.hmac_key_format().params().tag_size()) .SetHashType(*hash_type) .SetVariant(*variant) .Build(); } util::StatusOr SerializeParameters( const AesCtrHmacAeadParameters& parameters) { util::StatusOr output_prefix_type = ToOutputPrefixType(parameters.GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } AesCtrHmacAeadKeyFormat aes_ctr_hmac_aead_key_format; HmacKeyFormat& hmac_key_format = *aes_ctr_hmac_aead_key_format.mutable_hmac_key_format(); AesCtrKeyFormat& aes_ctr_key_format = *aes_ctr_hmac_aead_key_format.mutable_aes_ctr_key_format(); util::StatusOr hmac_params = GetHmacProtoParams(parameters); if (!hmac_params.ok()) { return hmac_params.status(); } *hmac_key_format.mutable_params() = *hmac_params; hmac_key_format.set_key_size(parameters.GetHmacKeySizeInBytes()); AesCtrParams& aes_ctr_params = *aes_ctr_key_format.mutable_params(); aes_ctr_params.set_iv_size(parameters.GetIvSizeInBytes()); aes_ctr_key_format.set_key_size(parameters.GetAesKeySizeInBytes()); return internal::ProtoParametersSerialization::Create( kTypeUrl, *output_prefix_type, aes_ctr_hmac_aead_key_format.SerializeAsString()); } util::StatusOr ParseKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (serialization.TypeUrl() != kTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing AesCtrHmacAeadKey."); } if (!token.has_value()) { return util::Status(absl::StatusCode::kPermissionDenied, "SecretKeyAccess is required"); } SecretProto proto_key; RestrictedData restricted_data = serialization.SerializedKeyProto(); if (!proto_key->ParseFromString(restricted_data.GetSecret(*token))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse AesCtrHmacAeadKey proto"); } if (proto_key->version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } if (proto_key->aes_ctr_key().version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys inner AES CTR keys are accepted."); } if (proto_key->hmac_key().version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys inner HMAC keys are accepted."); } util::StatusOr variant = ToVariant(serialization.GetOutputPrefixType()); if (!variant.ok()) { return variant.status(); } util::StatusOr hash_type = ToHashType(proto_key->hmac_key().params().hash()); if (!hash_type.ok()) { return hash_type.status(); } util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(proto_key->aes_ctr_key().key_value().size()) .SetHmacKeySizeInBytes(proto_key->hmac_key().key_value().size()) .SetIvSizeInBytes(proto_key->aes_ctr_key().params().iv_size()) .SetTagSizeInBytes(proto_key->hmac_key().params().tag_size()) .SetHashType(*hash_type) .SetVariant(*variant) .Build(); if (!parameters.ok()) return parameters.status(); return AesCtrHmacAeadKey::Builder() .SetParameters(*parameters) .SetAesKeyBytes( RestrictedData(proto_key->aes_ctr_key().key_value(), *token)) .SetHmacKeyBytes( RestrictedData(proto_key->hmac_key().key_value(), *token)) .SetIdRequirement(serialization.IdRequirement()) .Build(GetPartialKeyAccess()); } util::StatusOr SerializeKey( const AesCtrHmacAeadKey& key, absl::optional token) { if (!token.has_value()) { return util::Status(absl::StatusCode::kPermissionDenied, "SecretKeyAccess is required"); } util::StatusOr restricted_aes_input = key.GetAesKeyBytes(GetPartialKeyAccess()); if (!restricted_aes_input.ok()) { return restricted_aes_input.status(); } util::StatusOr restricted_hmac_input = key.GetHmacKeyBytes(GetPartialKeyAccess()); if (!restricted_hmac_input.ok()) { return restricted_hmac_input.status(); } SecretProto aes_ctr_proto_key; aes_ctr_proto_key->set_version(0); aes_ctr_proto_key->set_key_value(restricted_aes_input->GetSecret(*token)); aes_ctr_proto_key->mutable_params()->set_iv_size( key.GetParameters().GetIvSizeInBytes()); util::StatusOr hmac_params = GetHmacProtoParams(key.GetParameters()); if (!hmac_params.ok()) { return hmac_params.status(); } SecretProto hmac_proto_key; hmac_proto_key->set_version(0); hmac_proto_key->set_key_value(restricted_hmac_input->GetSecret(*token)); *hmac_proto_key->mutable_params() = *hmac_params; SecretProto aes_ctr_hmac_aead_proto_key; aes_ctr_hmac_aead_proto_key->set_version(0); *aes_ctr_hmac_aead_proto_key->mutable_aes_ctr_key() = *aes_ctr_proto_key; *aes_ctr_hmac_aead_proto_key->mutable_hmac_key() = *hmac_proto_key; util::StatusOr serialized_proto = aes_ctr_hmac_aead_proto_key.SerializeAsSecretData(); if (!serialized_proto.ok()) return serialized_proto.status(); RestrictedData restricted_output = RestrictedData(SecretDataAsStringView(*serialized_proto), *token); util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetParameters().GetVariant()); if (!output_prefix_type.ok()) return output_prefix_type.status(); return internal::ProtoKeySerialization::Create( kTypeUrl, restricted_output, KeyData::SYMMETRIC, *output_prefix_type, key.GetIdRequirement()); } AesCtrHmacAeadProtoParametersParserImpl& AesCtrHmacAeadProtoParametersParser() { static auto* parser = new AesCtrHmacAeadProtoParametersParserImpl(kTypeUrl, ParseParameters); return *parser; } AesCtrHmacAeadProtoParametersSerializerImpl& AesCtrHmacAeadProtoParametersSerializer() { static auto* serializer = new AesCtrHmacAeadProtoParametersSerializerImpl( kTypeUrl, SerializeParameters); return *serializer; } AesCtrHmacAeadProtoKeyParserImpl& AesCtrHmacAeadProtoKeyParser() { static auto* parser = new AesCtrHmacAeadProtoKeyParserImpl(kTypeUrl, ParseKey); return *parser; } AesCtrHmacAeadProtoKeySerializerImpl& AesCtrHmacAeadProtoKeySerializer() { static auto* serializer = new AesCtrHmacAeadProtoKeySerializerImpl(SerializeKey); return *serializer; } } // namespace util::Status RegisterAesCtrHmacAeadProtoSerialization() { util::Status status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersParser(&AesCtrHmacAeadProtoParametersParser()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersSerializer( &AesCtrHmacAeadProtoParametersSerializer()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(&AesCtrHmacAeadProtoKeyParser()); if (!status.ok()) { return status; } return internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(&AesCtrHmacAeadProtoKeySerializer()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_ctr_hmac_aead_proto_serialization.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_AES_CTR_HMAC_AEAD_PROTO_SERIALIZATION_H_ #define TINK_AEAD_AES_CTR_HMAC_AEAD_PROTO_SERIALIZATION_H_ #include "tink/util/status.h" namespace crypto { namespace tink { // Registers proto parsers and serializers for AES-CTR-HMAC-AEAD parameters and // keys. crypto::tink::util::Status RegisterAesCtrHmacAeadProtoSerialization(); } // namespace tink } // namespace crypto #endif // TINK_AEAD_AES_CTR_HMAC_AEAD_PROTO_SERIALIZATION_H_ ================================================ FILE: cc/aead/aes_ctr_hmac_aead_proto_serialization_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_ctr_hmac_aead_proto_serialization.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/aead/aes_ctr_hmac_aead_key.h" #include "tink/aead/aes_ctr_hmac_aead_parameters.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/subtle/random.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/aes_ctr.pb.h" #include "proto/aes_ctr_hmac_aead.pb.h" #include "proto/common.pb.h" #include "proto/hmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::subtle::Random; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::AesCtrHmacAeadKeyFormat; using ::google::crypto::tink::AesCtrKey; using ::google::crypto::tink::AesCtrKeyFormat; using ::google::crypto::tink::AesCtrParams; using ::google::crypto::tink::HashType; using ::google::crypto::tink::HmacKey; using ::google::crypto::tink::HmacKeyFormat; using ::google::crypto::tink::HmacParams; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::IsTrue; using ::testing::NotNull; using ::testing::TestWithParam; using ::testing::Values; const absl::string_view kTypeUrl = "type.googleapis.com/google.crypto.tink.AesCtrHmacAeadKey"; struct TestCase { int aes_key_size; int hmac_key_size; int iv_size; int tag_size; AesCtrHmacAeadParameters::HashType hash_type; HashType proto_hash_type; AesCtrHmacAeadParameters::Variant variant; OutputPrefixType output_prefix_type; absl::optional id_requirement; std::string output_prefix; }; class AesCtrHmacAeadProtoSerializationTest : public TestWithParam { protected: AesCtrHmacAeadProtoSerializationTest() { internal::MutableSerializationRegistry::GlobalInstance().Reset(); } }; INSTANTIATE_TEST_SUITE_P( AesCtrHmacAeadKeyBuildTestSuite, AesCtrHmacAeadProtoSerializationTest, Values(TestCase{/*aes_key_size=*/16, /*hmac_key_size=*/16, /*iv_size=*/12, /*tag_size=*/28, AesCtrHmacAeadParameters::HashType::kSha256, HashType::SHA256, AesCtrHmacAeadParameters::Variant::kTink, OutputPrefixType::TINK, /*id_requirement=*/0x02030400, std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{/*aes_key_size=*/24, /*hmac_key_size=*/32, /*iv_size=*/16, /*tag_size=*/32, AesCtrHmacAeadParameters::HashType::kSha384, HashType::SHA384, AesCtrHmacAeadParameters::Variant::kCrunchy, OutputPrefixType::CRUNCHY, /*id_requirement=*/0x01030005, std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{/*aes_key_size=*/32, /*hmac_key_size=*/16, /*iv_size=*/16, /*tag_size=*/48, AesCtrHmacAeadParameters::HashType::kSha512, HashType::SHA512, AesCtrHmacAeadParameters::Variant::kNoPrefix, OutputPrefixType::RAW, /*id_requirement=*/absl::nullopt, ""})); AesCtrHmacAeadKeyFormat BuildAesCtrHmacAeadKeyFormat(int aes_key_size, int hmac_key_size, int iv_size, int tag_size, HashType proto_hash_type, int hmac_version) { AesCtrHmacAeadKeyFormat aes_ctr_hmac_aead_key_format; HmacKeyFormat& hmac_key_format = *aes_ctr_hmac_aead_key_format.mutable_hmac_key_format(); AesCtrKeyFormat& aes_ctr_key_format = *aes_ctr_hmac_aead_key_format.mutable_aes_ctr_key_format(); AesCtrParams& aes_ctr_params = *aes_ctr_key_format.mutable_params(); aes_ctr_params.set_iv_size(iv_size); aes_ctr_key_format.set_key_size(aes_key_size); HmacParams& hmac_params = *hmac_key_format.mutable_params(); hmac_params.set_hash(proto_hash_type); hmac_params.set_tag_size(tag_size); hmac_key_format.set_key_size(hmac_key_size); hmac_key_format.set_version(hmac_version); return aes_ctr_hmac_aead_key_format; } google::crypto::tink::AesCtrHmacAeadKey BuildAesCtrHmacAeadKey( absl::string_view aes_key_bytes, absl::string_view hmac_key_bytes, int iv_size, int tag_size, HashType proto_hash_type, int aes_ctr_version, int hmac_version) { google::crypto::tink::AesCtrHmacAeadKey aes_ctr_hmac_aead_key; HmacKey& hmac_key = *aes_ctr_hmac_aead_key.mutable_hmac_key(); AesCtrKey& aes_ctr_key = *aes_ctr_hmac_aead_key.mutable_aes_ctr_key(); AesCtrParams& aes_ctr_params = *aes_ctr_key.mutable_params(); aes_ctr_params.set_iv_size(iv_size); aes_ctr_key.set_key_value(aes_key_bytes); aes_ctr_key.set_version(aes_ctr_version); HmacParams& hmac_params = *hmac_key.mutable_params(); hmac_params.set_hash(proto_hash_type); hmac_params.set_tag_size(tag_size); hmac_key.set_key_value(hmac_key_bytes); hmac_key.set_version(hmac_version); return aes_ctr_hmac_aead_key; } TEST_F(AesCtrHmacAeadProtoSerializationTest, RegisterTwiceSucceeds) { ASSERT_THAT(RegisterAesCtrHmacAeadProtoSerialization(), IsOk()); ASSERT_THAT(RegisterAesCtrHmacAeadProtoSerialization(), IsOk()); } TEST_P(AesCtrHmacAeadProtoSerializationTest, ParseParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesCtrHmacAeadProtoSerialization(), IsOk()); AesCtrHmacAeadKeyFormat aes_ctr_hmac_aead_key_format = BuildAesCtrHmacAeadKeyFormat( test_case.aes_key_size, test_case.hmac_key_size, test_case.iv_size, test_case.tag_size, test_case.proto_hash_type, /*hmac_version=*/0); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kTypeUrl, test_case.output_prefix_type, aes_ctr_hmac_aead_key_format.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parsed_parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(parsed_parameters, IsOk()); EXPECT_THAT((*parsed_parameters)->HasIdRequirement(), Eq(test_case.id_requirement.has_value())); util::StatusOr expected_parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(test_case.aes_key_size) .SetHmacKeySizeInBytes(test_case.hmac_key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(test_case.tag_size) .SetHashType(test_case.hash_type) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(expected_parameters, IsOk()); EXPECT_THAT(**parsed_parameters, Eq(*expected_parameters)); } TEST_F(AesCtrHmacAeadProtoSerializationTest, ParseParametersWithInvalidSerializationFails) { ASSERT_THAT(RegisterAesCtrHmacAeadProtoSerialization(), IsOk()); AesCtrHmacAeadKeyFormat key_format_proto = BuildAesCtrHmacAeadKeyFormat( /*aes_key_size=*/16, /*hmac_key_size=*/16, /*iv_size=*/16, /*tag_size=*/16, HashType::SHA256, /*hmac_version=*/0); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kTypeUrl, OutputPrefixType::RAW, "invalid_serialization"); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT( internal::MutableSerializationRegistry::GlobalInstance() .ParseParameters(*serialization) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Failed to parse AesCtrHmacAeadKeyFormat proto"))); } TEST_F(AesCtrHmacAeadProtoSerializationTest, ParseParametersWithUnkownOutputPrefixFails) { ASSERT_THAT(RegisterAesCtrHmacAeadProtoSerialization(), IsOk()); AesCtrHmacAeadKeyFormat key_format_proto = BuildAesCtrHmacAeadKeyFormat( /*aes_key_size=*/16, /*hmac_key_size=*/16, /*iv_size=*/16, /*tag_size=*/16, HashType::SHA256, /*hmac_version=*/0); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kTypeUrl, OutputPrefixType::UNKNOWN_PREFIX, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT( internal::MutableSerializationRegistry::GlobalInstance() .ParseParameters(*serialization) .status(), StatusIs( absl::StatusCode::kInvalidArgument, HasSubstr("Could not determine AesCtrHmacAeadParameters::Variant"))); } TEST_F(AesCtrHmacAeadProtoSerializationTest, ParseParametersWithUnkownHashTypeFails) { ASSERT_THAT(RegisterAesCtrHmacAeadProtoSerialization(), IsOk()); AesCtrHmacAeadKeyFormat key_format_proto = BuildAesCtrHmacAeadKeyFormat( /*aes_key_size=*/16, /*hmac_key_size=*/16, /*iv_size=*/16, /*tag_size=*/16, HashType::UNKNOWN_HASH, /*hmac_version=*/0); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kTypeUrl, OutputPrefixType::RAW, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT( internal::MutableSerializationRegistry::GlobalInstance() .ParseParameters(*serialization) .status(), StatusIs( absl::StatusCode::kInvalidArgument, HasSubstr("Could not determine AesCtrHmacAeadParameters::HashType"))); } TEST_F(AesCtrHmacAeadProtoSerializationTest, ParseParametersWithInvalidHmacVersionFails) { ASSERT_THAT(RegisterAesCtrHmacAeadProtoSerialization(), IsOk()); AesCtrHmacAeadKeyFormat key_format_proto = BuildAesCtrHmacAeadKeyFormat( /*aes_key_size=*/16, /*hmac_key_size=*/16, /*iv_size=*/16, /*tag_size=*/16, HashType::SHA256, /*hmac_version=*/1); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kTypeUrl, OutputPrefixType::RAW, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT(internal::MutableSerializationRegistry::GlobalInstance() .ParseParameters(*serialization) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("only version 0 is accepted"))); } TEST_P(AesCtrHmacAeadProtoSerializationTest, SerializeParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesCtrHmacAeadProtoSerialization(), IsOk()); util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(test_case.aes_key_size) .SetHmacKeySizeInBytes(test_case.hmac_key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(test_case.tag_size) .SetHashType(test_case.hash_type) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( *parameters); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kTypeUrl)); const internal::ProtoParametersSerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->GetKeyTemplate().type_url(), Eq(kTypeUrl)); EXPECT_THAT(proto_serialization->GetKeyTemplate().output_prefix_type(), Eq(test_case.output_prefix_type)); AesCtrHmacAeadKeyFormat aes_ctr_hmac_aead_key_format; ASSERT_THAT(aes_ctr_hmac_aead_key_format.ParseFromString( proto_serialization->GetKeyTemplate().value()), IsTrue()); ASSERT_THAT(aes_ctr_hmac_aead_key_format.aes_ctr_key_format().key_size(), Eq(test_case.aes_key_size)); ASSERT_THAT( aes_ctr_hmac_aead_key_format.aes_ctr_key_format().params().iv_size(), Eq(test_case.iv_size)); ASSERT_THAT(aes_ctr_hmac_aead_key_format.hmac_key_format().key_size(), Eq(test_case.hmac_key_size)); ASSERT_THAT( aes_ctr_hmac_aead_key_format.hmac_key_format().params().tag_size(), Eq(test_case.tag_size)); ASSERT_THAT(aes_ctr_hmac_aead_key_format.hmac_key_format().params().hash(), Eq(test_case.proto_hash_type)); } TEST_P(AesCtrHmacAeadProtoSerializationTest, ParseKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesCtrHmacAeadProtoSerialization(), IsOk()); std::string aes_key_bytes = Random::GetRandomBytes(test_case.aes_key_size); std::string hmac_key_bytes = Random::GetRandomBytes(test_case.hmac_key_size); google::crypto::tink::AesCtrHmacAeadKey key_proto = BuildAesCtrHmacAeadKey( aes_key_bytes, hmac_key_bytes, test_case.iv_size, test_case.tag_size, test_case.proto_hash_type, /*aes_ctr_version=*/0, /*hmac_version=*/0); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kTypeUrl, serialized_key, KeyData::SYMMETRIC, test_case.output_prefix_type, test_case.id_requirement); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); EXPECT_THAT((*key)->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT((*key)->GetParameters().HasIdRequirement(), Eq(test_case.id_requirement.has_value())); util::StatusOr expected_parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(test_case.aes_key_size) .SetHmacKeySizeInBytes(test_case.hmac_key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(test_case.tag_size) .SetHashType(test_case.hash_type) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(expected_parameters, IsOk()); util::StatusOr expected_key = AesCtrHmacAeadKey::Builder() .SetParameters(*expected_parameters) .SetAesKeyBytes( RestrictedData(aes_key_bytes, InsecureSecretKeyAccess::Get())) .SetHmacKeyBytes( RestrictedData(hmac_key_bytes, InsecureSecretKeyAccess::Get())) .SetIdRequirement(test_case.id_requirement) .Build(GetPartialKeyAccess()); ASSERT_THAT(expected_key, IsOk()); EXPECT_THAT(**key, Eq(*expected_key)); } TEST_F(AesCtrHmacAeadProtoSerializationTest, ParseLegacyKeyAsCrunchy) { ASSERT_THAT(RegisterAesCtrHmacAeadProtoSerialization(), IsOk()); std::string aes_key_bytes = Random::GetRandomBytes(16); std::string hmac_key_bytes = Random::GetRandomBytes(16); google::crypto::tink::AesCtrHmacAeadKey key_proto = BuildAesCtrHmacAeadKey( aes_key_bytes, hmac_key_bytes, /*iv_size=*/16, /*tag_size=*/16, HashType::SHA256, /*aes_ctr_version=*/0, /*hmac_version=*/0); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::LEGACY, /*id_requirement=*/123); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); const AesCtrHmacAeadKey* aes_ctr_hmac_aead_key = dynamic_cast(key->get()); ASSERT_THAT(aes_ctr_hmac_aead_key, NotNull()); EXPECT_THAT(aes_ctr_hmac_aead_key->GetParameters().GetVariant(), Eq(AesCtrHmacAeadParameters::Variant::kCrunchy)); } TEST_F(AesCtrHmacAeadProtoSerializationTest, ParseKeyWithInvalidSerializationFails) { ASSERT_THAT(RegisterAesCtrHmacAeadProtoSerialization(), IsOk()); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Failed to parse AesCtrHmacAeadKey proto"))); } TEST_F(AesCtrHmacAeadProtoSerializationTest, ParseKeyNoSecretKeyAccessFails) { ASSERT_THAT(RegisterAesCtrHmacAeadProtoSerialization(), IsOk()); std::string aes_key_bytes = Random::GetRandomBytes(16); std::string hmac_key_bytes = Random::GetRandomBytes(16); google::crypto::tink::AesCtrHmacAeadKey key_proto = BuildAesCtrHmacAeadKey( aes_key_bytes, hmac_key_bytes, /*iv_size=*/16, /*tag_size=*/16, HashType::SHA256, /*aes_ctr_version=*/0, /*hmac_version=*/0); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kPermissionDenied, HasSubstr("SecretKeyAccess is required"))); } TEST_F(AesCtrHmacAeadProtoSerializationTest, ParseKeyWithInvalidVersionFails) { ASSERT_THAT(RegisterAesCtrHmacAeadProtoSerialization(), IsOk()); std::string aes_key_bytes = Random::GetRandomBytes(16); std::string hmac_key_bytes = Random::GetRandomBytes(16); google::crypto::tink::AesCtrHmacAeadKey key_proto = BuildAesCtrHmacAeadKey( aes_key_bytes, hmac_key_bytes, /*iv_size=*/16, /*tag_size=*/16, HashType::SHA256, /*aes_ctr_version=*/0, /*hmac_version=*/0); key_proto.set_version(1); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Only version 0 keys are accepted"))); } TEST_F(AesCtrHmacAeadProtoSerializationTest, ParseKeyWithInvalidAesCtrKeyVersionFails) { ASSERT_THAT(RegisterAesCtrHmacAeadProtoSerialization(), IsOk()); std::string aes_key_bytes = Random::GetRandomBytes(16); std::string hmac_key_bytes = Random::GetRandomBytes(16); google::crypto::tink::AesCtrHmacAeadKey key_proto = BuildAesCtrHmacAeadKey( aes_key_bytes, hmac_key_bytes, /*iv_size=*/16, /*tag_size=*/16, HashType::SHA256, /*aes_ctr_version=*/1, /*hmac_version=*/0); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT( key.status(), StatusIs( absl::StatusCode::kInvalidArgument, HasSubstr("Only version 0 keys inner AES CTR keys are accepted"))); } TEST_F(AesCtrHmacAeadProtoSerializationTest, ParseKeyWithInvalidHmacKeyVersionFails) { ASSERT_THAT(RegisterAesCtrHmacAeadProtoSerialization(), IsOk()); std::string aes_key_bytes = Random::GetRandomBytes(16); std::string hmac_key_bytes = Random::GetRandomBytes(16); google::crypto::tink::AesCtrHmacAeadKey key_proto = BuildAesCtrHmacAeadKey( aes_key_bytes, hmac_key_bytes, /*iv_size=*/16, /*tag_size=*/16, HashType::SHA256, /*aes_ctr_version=*/0, /*hmac_version=*/1); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT( key.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Only version 0 keys inner HMAC keys are accepted"))); } TEST_P(AesCtrHmacAeadProtoSerializationTest, SerializeKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesCtrHmacAeadProtoSerialization(), IsOk()); std::string aes_key_bytes = Random::GetRandomBytes(test_case.aes_key_size); std::string hmac_key_bytes = Random::GetRandomBytes(test_case.hmac_key_size); util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(test_case.aes_key_size) .SetHmacKeySizeInBytes(test_case.hmac_key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(test_case.tag_size) .SetHashType(test_case.hash_type) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr key = AesCtrHmacAeadKey::Builder() .SetParameters(*parameters) .SetAesKeyBytes( RestrictedData(aes_key_bytes, InsecureSecretKeyAccess::Get())) .SetHmacKeyBytes( RestrictedData(hmac_key_bytes, InsecureSecretKeyAccess::Get())) .SetIdRequirement(test_case.id_requirement) .Build(GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kTypeUrl)); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq(kTypeUrl)); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::SYMMETRIC)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id_requirement)); google::crypto::tink::AesCtrHmacAeadKey proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.aes_ctr_key().key_value(), Eq(aes_key_bytes)); EXPECT_THAT(proto_key.aes_ctr_key().params().iv_size(), Eq(test_case.iv_size)); EXPECT_THAT(proto_key.hmac_key().key_value(), Eq(hmac_key_bytes)); EXPECT_THAT(proto_key.hmac_key().params().tag_size(), Eq(test_case.tag_size)); EXPECT_THAT(proto_key.hmac_key().params().hash(), Eq(test_case.proto_hash_type)); } TEST_F(AesCtrHmacAeadProtoSerializationTest, SerializeKeyNoSecretKeyAccessFails) { ASSERT_THAT(RegisterAesCtrHmacAeadProtoSerialization(), IsOk()); std::string aes_key_bytes = Random::GetRandomBytes(16); std::string hmac_key_bytes = Random::GetRandomBytes(16); util::StatusOr parameters = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(16) .SetHmacKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr key = AesCtrHmacAeadKey::Builder() .SetParameters(*parameters) .SetAesKeyBytes( RestrictedData(aes_key_bytes, InsecureSecretKeyAccess::Get())) .SetHmacKeyBytes( RestrictedData(hmac_key_bytes, InsecureSecretKeyAccess::Get())) .SetIdRequirement(0x23456789) .Build(GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey(*key, absl::nullopt); EXPECT_THAT(serialization.status(), StatusIs(absl::StatusCode::kPermissionDenied, HasSubstr("SecretKeyAccess is required"))); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_eax_key.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_eax_key.h" #include #include #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/types/optional.h" #include "tink/aead/aes_eax_parameters.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { util::StatusOr ComputeOutputPrefix( const AesEaxParameters& parameters, absl::optional id_requirement) { switch (parameters.GetVariant()) { case AesEaxParameters::Variant::kNoPrefix: return std::string(""); // Empty prefix. case AesEaxParameters::Variant::kCrunchy: if (!id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "ID requirement must not be empty with kCrunchy or kLegacy"); } return absl::StrCat(absl::HexStringToBytes("00"), subtle::BigEndian32(*id_requirement)); case AesEaxParameters::Variant::kTink: if (!id_requirement.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "ID requirement must not be empty with kTink"); } return absl::StrCat(absl::HexStringToBytes("01"), subtle::BigEndian32(*id_requirement)); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid variant: ", parameters.GetVariant())); } } } // namespace util::StatusOr AesEaxKey::Create(const AesEaxParameters& parameters, const RestrictedData& key_bytes, absl::optional id_requirement, PartialKeyAccessToken token) { if (parameters.GetKeySizeInBytes() != key_bytes.size()) { return util::Status( absl::StatusCode::kInvalidArgument, "Key size does not match AesEaxParameters::GetKeySizeInBytes"); } if (parameters.HasIdRequirement() && !id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key without ID requirement with parameters with ID " "requirement"); } if (!parameters.HasIdRequirement() && id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key with ID requirement with parameters without ID " "requirement"); } util::StatusOr output_prefix = ComputeOutputPrefix(parameters, id_requirement); if (!output_prefix.ok()) { return output_prefix.status(); } return AesEaxKey(parameters, key_bytes, id_requirement, *std::move(output_prefix)); } bool AesEaxKey::operator==(const Key& other) const { const AesEaxKey* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (GetParameters() != that->GetParameters()) { return false; } if (id_requirement_ != that->id_requirement_) { return false; } return key_bytes_ == that->key_bytes_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_eax_key.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_AES_EAX_KEY_H_ #define TINK_AEAD_AES_EAX_KEY_H_ #include #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/aead/aead_key.h" #include "tink/aead/aes_eax_parameters.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Represents an AEAD that uses AES-EAX. class AesEaxKey : public AeadKey { public: // Copyable and movable. AesEaxKey(const AesEaxKey& other) = default; AesEaxKey& operator=(const AesEaxKey& other) = default; AesEaxKey(AesEaxKey&& other) = default; AesEaxKey& operator=(AesEaxKey&& other) = default; // Creates a new AES-EAX key. If the parameters specify a variant that uses // a prefix, then the id is used to compute this prefix. static util::StatusOr Create(const AesEaxParameters& parameters, const RestrictedData& key_bytes, absl::optional id_requirement, PartialKeyAccessToken token); // Returns the underlying AES key. const RestrictedData& GetKeyBytes(PartialKeyAccessToken token) const { return key_bytes_; } absl::string_view GetOutputPrefix() const override { return output_prefix_; } const AesEaxParameters& GetParameters() const override { return parameters_; } absl::optional GetIdRequirement() const override { return id_requirement_; } bool operator==(const Key& other) const override; private: AesEaxKey(const AesEaxParameters& parameters, const RestrictedData& key_bytes, absl::optional id_requirement, std::string output_prefix) : parameters_(parameters), key_bytes_(key_bytes), id_requirement_(id_requirement), output_prefix_(std::move(output_prefix)) {} AesEaxParameters parameters_; RestrictedData key_bytes_; absl::optional id_requirement_; std::string output_prefix_; }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_AES_EAX_KEY_H_ ================================================ FILE: cc/aead/aes_eax_key_manager.h ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_AES_EAX_KEY_MANAGER_H_ #define TINK_AEAD_AES_EAX_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/aead.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/subtle/aes_eax_boringssl.h" #include "tink/subtle/random.h" #include "tink/util/constants.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/aes_eax.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class AesEaxKeyManager : public KeyTypeManager> { public: class AeadFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::AesEaxKey& key) const override { return subtle::AesEaxBoringSsl::New( util::SecretDataFromStringView(key.key_value()), key.params().iv_size()); } }; AesEaxKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::SYMMETRIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::AesEaxKey& key) const override { crypto::tink::util::Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; status = ValidateKeySize(key.key_value().size()); if (!status.ok()) return status; return ValidateIvSize(key.params().iv_size()); } crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::AesEaxKeyFormat& key_format) const override { crypto::tink::util::Status status = ValidateKeySize(key_format.key_size()); if (!status.ok()) return status; return ValidateIvSize(key_format.params().iv_size()); } crypto::tink::util::StatusOr CreateKey( const google::crypto::tink::AesEaxKeyFormat& key_format) const override { google::crypto::tink::AesEaxKey aes_eax_key; aes_eax_key.set_version(get_version()); aes_eax_key.set_key_value( subtle::Random::GetRandomBytes(key_format.key_size())); aes_eax_key.mutable_params()->set_iv_size( key_format.params().iv_size()); return aes_eax_key; } private: crypto::tink::util::Status ValidateKeySize(uint32_t key_size) const { if (key_size != 16 && key_size != 32) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid key size: ", key_size, " bytes, expected 16 or 32 bytes.")); } return crypto::tink::util::OkStatus(); } crypto::tink::util::Status ValidateIvSize(uint32_t iv_size) const { if (iv_size != 12 && iv_size != 16) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid IV size: ", iv_size, " bytes, expected 12 or 16 bytes.")); } return crypto::tink::util::OkStatus(); } const std::string key_type_ = absl::StrCat( kTypeGoogleapisCom, google::crypto::tink::AesEaxKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_AES_EAX_KEY_MANAGER_H_ ================================================ FILE: cc/aead/aes_eax_key_manager_test.cc ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_eax_key_manager.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/aead.h" #include "tink/subtle/aead_test_util.h" #include "tink/subtle/aes_eax_boringssl.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/aes_eax.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::crypto::tink::test::IsOk; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::AesEaxKey; using ::google::crypto::tink::AesEaxKeyFormat; using ::testing::Eq; using ::testing::Ne; using ::testing::Not; using ::testing::SizeIs; namespace { TEST(AesEaxKeyManagerTest, Basics) { EXPECT_THAT(AesEaxKeyManager().get_version(), Eq(0)); EXPECT_THAT(AesEaxKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.AesEaxKey")); EXPECT_THAT(AesEaxKeyManager().key_material_type(), Eq(google::crypto::tink::KeyData::SYMMETRIC)); } TEST(AesEaxKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(AesEaxKeyManager().ValidateKey(AesEaxKey()), Not(IsOk())); } TEST(AesEaxKeyManagerTest, ValidateEmptyKeyFormat) { EXPECT_THAT(AesEaxKeyManager().ValidateKeyFormat(AesEaxKeyFormat()), Not(IsOk())); } TEST(AesEaxKeyManagerTest, ValidKeyFormat) { AesEaxKeyFormat format; format.set_key_size(32); format.mutable_params()->set_iv_size(16); EXPECT_THAT(AesEaxKeyManager().ValidateKeyFormat(format), IsOk()); } TEST(AesEaxKeyManagerTest, ValidKeyFormatKeySize) { AesEaxKeyFormat format; format.mutable_params()->set_iv_size(16); for (int len = 0; len < 200; ++len) { format.set_key_size(len); if (len == 16 || len == 32) { EXPECT_THAT(AesEaxKeyManager().ValidateKeyFormat(format), IsOk()) << "for len = " << len; } else { EXPECT_THAT(AesEaxKeyManager().ValidateKeyFormat(format), Not(IsOk())) << "for len = " << len; } } } TEST(AesEaxKeyManagerTest, ValidKeyFormatIvSize) { AesEaxKeyFormat format; format.set_key_size(32); for (int iv_size = 0; iv_size < 200; ++iv_size) { format.mutable_params()->set_iv_size(iv_size); if (iv_size == 12 || iv_size == 16) { EXPECT_THAT(AesEaxKeyManager().ValidateKeyFormat(format), IsOk()) << "for iv_size = " << iv_size; } else { EXPECT_THAT(AesEaxKeyManager().ValidateKeyFormat(format), Not(IsOk())) << "for iv_size = " << iv_size; } } } TEST(AesEaxKeyManagerTest, CreateKey) { AesEaxKeyFormat format; format.set_key_size(32); format.mutable_params()->set_iv_size(16); auto key_or = AesEaxKeyManager().CreateKey(format); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().key_value(), SizeIs(format.key_size())); EXPECT_THAT(key_or.value().params().iv_size(), Eq(format.params().iv_size())); } TEST(AesEaxKeyManagerTest, CreateKeyIsValid) { AesEaxKeyFormat format; format.set_key_size(32); format.mutable_params()->set_iv_size(16); auto key_or = AesEaxKeyManager().CreateKey(format); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(AesEaxKeyManager().ValidateKey(key_or.value()), IsOk()); } TEST(AesEaxKeyManagerTest, MultipleCreateCallsCreateDifferentKeys) { AesEaxKeyFormat format; AesEaxKeyManager manager; format.set_key_size(32); format.mutable_params()->set_iv_size(16); auto key1_or = manager.CreateKey(format); ASSERT_THAT(key1_or, IsOk()); auto key2_or = manager.CreateKey(format); ASSERT_THAT(key2_or, IsOk()); EXPECT_THAT(key1_or.value().key_value(), Ne(key2_or.value().key_value())); } TEST(AesEaxKeyManagerTest, ValidKey) { AesEaxKey key; key.set_key_value(std::string(32, 'a')); key.mutable_params()->set_iv_size(16); EXPECT_THAT(AesEaxKeyManager().ValidateKey(key), IsOk()); } TEST(AesEaxKeyManagerTest, ValidateKeyKeyLength) { AesEaxKey key; key.mutable_params()->set_iv_size(16); for (int len = 0; len < 200; ++len) { key.set_key_value(std::string(len, 'a')); if (len == 16 || len == 32) { EXPECT_THAT(AesEaxKeyManager().ValidateKey(key), IsOk()) << "for len = " << len; } else { EXPECT_THAT(AesEaxKeyManager().ValidateKey(key), Not(IsOk())) << "for len = " << len; } } } TEST(AesEaxKeyManagerTest, ValidateKeyIvLength) { AesEaxKey key; key.set_key_value(std::string(32, 'a')); for (int iv_len = 0; iv_len < 200; ++iv_len) { key.mutable_params()->set_iv_size(iv_len); if (iv_len == 12 || iv_len == 16) { EXPECT_THAT(AesEaxKeyManager().ValidateKey(key), IsOk()) << "for iv_size = " << iv_len; } else { EXPECT_THAT(AesEaxKeyManager().ValidateKey(key), Not(IsOk())) << "for iv_size = " << iv_len; } } } TEST(AesGcmKeyManagerTest, CreateAead) { AesEaxKeyFormat format; format.set_key_size(32); format.mutable_params()->set_iv_size(16); StatusOr key_or = AesEaxKeyManager().CreateKey(format); ASSERT_THAT(key_or, IsOk()); StatusOr> aead_or = AesEaxKeyManager().GetPrimitive(key_or.value()); ASSERT_THAT(aead_or, IsOk()); StatusOr> boring_ssl_aead_or = subtle::AesEaxBoringSsl::New( util::SecretDataFromStringView(key_or.value().key_value()), key_or.value().params().iv_size()); ASSERT_THAT(boring_ssl_aead_or, IsOk()); ASSERT_THAT(EncryptThenDecrypt(*aead_or.value(), *boring_ssl_aead_or.value(), "message", "aad"), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_eax_key_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_eax_key.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/aead/aes_eax_parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { int key_size; int iv_size; int tag_size; AesEaxParameters::Variant variant; absl::optional id_requirement; std::string output_prefix; }; using AesEaxKeyTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( AesEaxParametersBuildTestSuite, AesEaxKeyTest, Values(TestCase{/*key_size=*/16, /*iv_size=*/12, /*tag_size=*/12, AesEaxParameters::Variant::kTink, 0x02030400, std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{/*key_size=*/24, /*iv_size=*/16, /*tag_size=*/14, AesEaxParameters::Variant::kCrunchy, 0x01030005, std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{/*key_size=*/32, /*iv_size=*/16, /*tag_size=*/16, AesEaxParameters::Variant::kNoPrefix, absl::nullopt, ""})); TEST_P(AesEaxKeyTest, CreateSucceeds) { TestCase test_case = GetParam(); util::StatusOr parameters = AesEaxParameters::Builder() .SetKeySizeInBytes(test_case.key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(test_case.tag_size) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); RestrictedData secret = RestrictedData(test_case.key_size); util::StatusOr key = AesEaxKey::Create( *parameters, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); EXPECT_THAT(key->GetParameters(), Eq(*parameters)); EXPECT_THAT(key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(key->GetOutputPrefix(), Eq(test_case.output_prefix)); EXPECT_THAT(key->GetKeyBytes(GetPartialKeyAccess()), Eq(secret)); } TEST(AesEaxKeyTest, CreateKeyWithMismatchedKeySizeFails) { // Key size parameter is 32 bytes. util::StatusOr parameters = AesEaxParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); // Key material is 16 bytes (also a valid key length). RestrictedData mismatched_secret = RestrictedData(/*num_random_bytes=*/16); EXPECT_THAT(AesEaxKey::Create(*parameters, mismatched_secret, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesEaxKeyTest, CreateKeyWithInvalidIdRequirementFails) { util::StatusOr no_prefix_parameters = AesEaxParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(no_prefix_parameters, IsOk()); util::StatusOr tink_parameters = AesEaxParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kTink) .Build(); ASSERT_THAT(tink_parameters, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); // Creating a key with with ID requirement with parameters without ID // requirement fails */ EXPECT_THAT(AesEaxKey::Create(*no_prefix_parameters, secret, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); // Creating a key with without ID requirement with parameters with ID // requirement fails */ EXPECT_THAT( AesEaxKey::Create(*tink_parameters, secret, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(AesEaxKeyTest, KeyEquals) { TestCase test_case = GetParam(); util::StatusOr parameters = AesEaxParameters::Builder() .SetKeySizeInBytes(test_case.key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(test_case.tag_size) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); RestrictedData secret = RestrictedData(test_case.key_size); util::StatusOr key = AesEaxKey::Create( *parameters, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = AesEaxKey::Create( *parameters, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key == *other_key); EXPECT_TRUE(*other_key == *key); EXPECT_FALSE(*key != *other_key); EXPECT_FALSE(*other_key != *key); } TEST(AesEaxKeyTest, DifferentParametersKeysNotEqual) { util::StatusOr crunchy_parameters = AesEaxParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kCrunchy) .Build(); ASSERT_THAT(crunchy_parameters, IsOk()); util::StatusOr tink_parameters = AesEaxParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kTink) .Build(); ASSERT_THAT(tink_parameters, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = AesEaxKey::Create(*crunchy_parameters, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = AesEaxKey::Create(*tink_parameters, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST(AesEaxKeyTest, DifferentSecretDataKeysNotEqual) { util::StatusOr parameters = AesEaxParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); RestrictedData secret1 = RestrictedData(/*num_random_bytes=*/32); RestrictedData secret2 = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = AesEaxKey::Create(*parameters, secret1, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = AesEaxKey::Create(*parameters, secret2, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST(AesEaxKeyTest, DifferentIdRequirementKeysNotEqual) { util::StatusOr parameters = AesEaxParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = AesEaxKey::Create(*parameters, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = AesEaxKey::Create(*parameters, secret, /*id_requirement=*/0x02030405, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_eax_parameters.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_eax_parameters.h" #include "absl/container/flat_hash_set.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/parameters.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { AesEaxParameters::Builder& AesEaxParameters::Builder::SetKeySizeInBytes( int key_size) { key_size_in_bytes_ = key_size; return *this; } AesEaxParameters::Builder& AesEaxParameters::Builder::SetIvSizeInBytes( int iv_size) { iv_size_in_bytes_ = iv_size; return *this; } AesEaxParameters::Builder& AesEaxParameters::Builder::SetTagSizeInBytes( int tag_size) { tag_size_in_bytes_ = tag_size; return *this; } AesEaxParameters::Builder& AesEaxParameters::Builder::SetVariant( Variant variant) { variant_ = variant; return *this; } util::StatusOr AesEaxParameters::Builder::Build() { if (!key_size_in_bytes_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Key size is not set."); } if (!iv_size_in_bytes_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "IV size is not set."); } if (!tag_size_in_bytes_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Tag size is not set."); } if (!variant_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Variant is not set."); } if (*key_size_in_bytes_ != 16 && *key_size_in_bytes_ != 24 && *key_size_in_bytes_ != 32) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Key size should be 16, 24, or 32 bytes, got ", *key_size_in_bytes_, " bytes.")); } if (*iv_size_in_bytes_ != 12 && *iv_size_in_bytes_ != 16) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("IV size should be 12 or 16 bytes, got ", *iv_size_in_bytes_, " bytes.")); } if (*tag_size_in_bytes_ < 0 || *tag_size_in_bytes_ > 16) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Tag size should be positive and at most 16 bytes, got ", *tag_size_in_bytes_, " bytes.")); } static const auto* kSupportedVariants = new absl::flat_hash_set( {Variant::kTink, Variant::kCrunchy, Variant::kNoPrefix}); if (!kSupportedVariants->contains(*variant_)) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create AES-EAX parameters with unknown variant."); } return AesEaxParameters(*key_size_in_bytes_, *iv_size_in_bytes_, *tag_size_in_bytes_, *variant_); } bool AesEaxParameters::operator==(const Parameters& other) const { const AesEaxParameters* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (key_size_in_bytes_ != that->key_size_in_bytes_) { return false; } if (iv_size_in_bytes_ != that->iv_size_in_bytes_) { return false; } if (tag_size_in_bytes_ != that->tag_size_in_bytes_) { return false; } if (variant_ != that->variant_) { return false; } return true; } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_eax_parameters.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_AES_EAX_PARAMETERS_H_ #define TINK_AEAD_AES_EAX_PARAMETERS_H_ #include "absl/types/optional.h" #include "tink/aead/aead_parameters.h" #include "tink/parameters.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Describes the parameters of an `AesEaxKey`. // // The choices for the parameters values are restricted to a certain set of // options, in accordance to http://web.cs.ucdavis.edu/~rogaway/papers/eax.pdf. // - The key size accepts values of 16, 24, or 32 bytes. Current implementation // only offers support for 16-byte and 32-byte keys. // - The IV size accepts values of 12 or 16 bytes. // - The tag size accepts values between 0 and 16 bytes. Current implementation // is restricted to 16 bytes only. // // WARNING: As seen above, some of the values accepted by this class may // actually be a superset of what is currently supported by the key type // implementations. Specifying a larger set of value (i.e. 24-byte keys) aligns // with a future possibility to add support for such parameters, if needed. class AesEaxParameters : public AeadParameters { public: // Description of the output prefix prepended to the ciphertext. enum class Variant : int { // Prepends '0x01' to the ciphertext. kTink = 1, // Prepends '0x00' to the ciphertext. kCrunchy = 2, // Does not prepend any prefix (i.e., keys must have no ID requirement). kNoPrefix = 3, // Added to guard from failures that may be caused by future expansions. kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Creates AES-EAX parameters instances. class Builder { public: // Copyable and movable. Builder(const Builder& other) = default; Builder& operator=(const Builder& other) = default; Builder(Builder&& other) = default; Builder& operator=(Builder&& other) = default; // Creates initially empty parameters builder. Builder() = default; Builder& SetKeySizeInBytes(int key_size); Builder& SetIvSizeInBytes(int iv_size); Builder& SetTagSizeInBytes(int tag_size); Builder& SetVariant(Variant variant); // Creates AES-EAX parameters object from this builder. util::StatusOr Build(); private: absl::optional key_size_in_bytes_ = absl::nullopt; absl::optional iv_size_in_bytes_ = absl::nullopt; absl::optional tag_size_in_bytes_ = absl::nullopt; absl::optional variant_ = absl::nullopt; }; // Copyable and movable. AesEaxParameters(const AesEaxParameters& other) = default; AesEaxParameters& operator=(const AesEaxParameters& other) = default; AesEaxParameters(AesEaxParameters&& other) = default; AesEaxParameters& operator=(AesEaxParameters&& other) = default; int GetKeySizeInBytes() const { return key_size_in_bytes_; } int GetIvSizeInBytes() const { return iv_size_in_bytes_; } int GetTagSizeInBytes() const { return tag_size_in_bytes_; } Variant GetVariant() const { return variant_; } bool HasIdRequirement() const override { return variant_ != Variant::kNoPrefix; } bool operator==(const Parameters& other) const override; private: AesEaxParameters(int key_size_in_bytes, int iv_size_in_bytes, int tag_size_in_bytes, Variant variant) : key_size_in_bytes_(key_size_in_bytes), iv_size_in_bytes_(iv_size_in_bytes), tag_size_in_bytes_(tag_size_in_bytes), variant_(variant) {} int key_size_in_bytes_; int iv_size_in_bytes_; int tag_size_in_bytes_; Variant variant_; }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_AES_EAX_PARAMETERS_H_ ================================================ FILE: cc/aead/aes_eax_parameters_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_eax_parameters.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::TestWithParam; using ::testing::Values; struct BuildTestCase { int key_size; int iv_size; int tag_size; AesEaxParameters::Variant variant; bool has_id_requirement; }; using AesEaxParametersTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( AesEaxParametersBuildTestSuite, AesEaxParametersTest, Values(BuildTestCase{/*key_size=*/16, /*iv_size=*/12, /*tag_size=*/12, AesEaxParameters::Variant::kTink, /*has_id_requirement=*/true}, BuildTestCase{/*key_size=*/24, /*iv_size=*/16, /*tag_size=*/14, AesEaxParameters::Variant::kCrunchy, /*has_id_requirement=*/true}, BuildTestCase{/*key_size=*/32, /*iv_size=*/16, /*tag_size=*/16, AesEaxParameters::Variant::kNoPrefix, /*has_id_requirement=*/false})); TEST_P(AesEaxParametersTest, BuildParametersSucceeds) { BuildTestCase test_case = GetParam(); util::StatusOr parameters = AesEaxParameters::Builder() .SetKeySizeInBytes(test_case.key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(test_case.tag_size) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetKeySizeInBytes(), Eq(test_case.key_size)); EXPECT_THAT(parameters->GetIvSizeInBytes(), Eq(test_case.iv_size)); EXPECT_THAT(parameters->GetTagSizeInBytes(), Eq(test_case.tag_size)); EXPECT_THAT(parameters->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(parameters->HasIdRequirement(), Eq(test_case.has_id_requirement)); } TEST(AesEaxParametersTest, BuildWithoutSettingVariantFails) { EXPECT_THAT(AesEaxParameters::Builder() .SetKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesEaxParametersTest, BuildWithInvalidVariantFails) { EXPECT_THAT( AesEaxParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesEaxParametersTest, BuildWithoutSettingKeySizeFails) { EXPECT_THAT(AesEaxParameters::Builder() .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesEaxParametersTest, BuildWithInvalidKeySizeFails) { EXPECT_THAT(AesEaxParameters::Builder() .SetKeySizeInBytes(15) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesEaxParameters::Builder() .SetKeySizeInBytes(17) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesEaxParameters::Builder() .SetKeySizeInBytes(23) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesEaxParameters::Builder() .SetKeySizeInBytes(25) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesEaxParameters::Builder() .SetKeySizeInBytes(31) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesEaxParameters::Builder() .SetKeySizeInBytes(33) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesEaxParametersTest, BuildWithoutSettingIvSizeFails) { EXPECT_THAT(AesEaxParameters::Builder() .SetKeySizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesEaxParametersTest, BuildWithInvalidIvSizeFails) { EXPECT_THAT(AesEaxParameters::Builder() .SetKeySizeInBytes(16) .SetIvSizeInBytes(11) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesEaxParameters::Builder() .SetKeySizeInBytes(16) .SetIvSizeInBytes(13) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesEaxParameters::Builder() .SetKeySizeInBytes(16) .SetIvSizeInBytes(11) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesEaxParameters::Builder() .SetKeySizeInBytes(16) .SetIvSizeInBytes(13) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesEaxParameters::Builder() .SetKeySizeInBytes(16) .SetIvSizeInBytes(15) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesEaxParameters::Builder() .SetKeySizeInBytes(16) .SetIvSizeInBytes(17) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesEaxParametersTest, BuildWithoutSettingTagSizeFails) { EXPECT_THAT(AesEaxParameters::Builder() .SetKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesEaxParametersTest, BuildWithInvalidTagSizeFails) { // Negative value. EXPECT_THAT(AesEaxParameters::Builder() .SetKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(-16) .SetVariant(AesEaxParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); // Too big. EXPECT_THAT(AesEaxParameters::Builder() .SetKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(17) .SetVariant(AesEaxParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(AesEaxParametersTest, CopyConstructor) { BuildTestCase test_case = GetParam(); util::StatusOr parameters = AesEaxParameters::Builder() .SetKeySizeInBytes(test_case.key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(test_case.tag_size) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); AesEaxParameters copy(*parameters); EXPECT_THAT(copy.GetKeySizeInBytes(), Eq(test_case.key_size)); EXPECT_THAT(copy.GetIvSizeInBytes(), Eq(test_case.iv_size)); EXPECT_THAT(copy.GetTagSizeInBytes(), Eq(test_case.tag_size)); EXPECT_THAT(copy.GetVariant(), Eq(test_case.variant)); EXPECT_THAT(copy.HasIdRequirement(), test_case.has_id_requirement); } TEST_P(AesEaxParametersTest, CopyAssignment) { BuildTestCase test_case = GetParam(); util::StatusOr parameters = AesEaxParameters::Builder() .SetKeySizeInBytes(test_case.key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(test_case.tag_size) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); AesEaxParameters copy = *parameters; EXPECT_THAT(copy.GetKeySizeInBytes(), Eq(test_case.key_size)); EXPECT_THAT(copy.GetIvSizeInBytes(), Eq(test_case.iv_size)); EXPECT_THAT(copy.GetTagSizeInBytes(), Eq(test_case.tag_size)); EXPECT_THAT(copy.GetVariant(), Eq(test_case.variant)); EXPECT_THAT(copy.HasIdRequirement(), test_case.has_id_requirement); } TEST_P(AesEaxParametersTest, SameParametersEquals) { BuildTestCase test_case = GetParam(); util::StatusOr parameters = AesEaxParameters::Builder() .SetKeySizeInBytes(test_case.key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(test_case.tag_size) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesEaxParameters::Builder() .SetKeySizeInBytes(test_case.key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(test_case.tag_size) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters == *other_parameters); EXPECT_TRUE(*other_parameters == *parameters); EXPECT_FALSE(*parameters != *other_parameters); EXPECT_FALSE(*other_parameters != *parameters); } TEST(AesEaxParametersTest, DifferentKeySizeNotEqual) { util::StatusOr parameters = AesEaxParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesEaxParameters::Builder() .SetKeySizeInBytes(24) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kTink) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(AesEaxParametersTest, DifferentIvSizeNotEqual) { util::StatusOr parameters = AesEaxParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(12) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesEaxParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kTink) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(AesEaxParametersTest, DifferentTagSizeNotEqual) { util::StatusOr parameters = AesEaxParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(14) .SetVariant(AesEaxParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesEaxParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kTink) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(AesEaxParametersTest, DifferentVariantNotEqual) { util::StatusOr parameters = AesEaxParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesEaxParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesEaxParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_eax_proto_serialization.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_eax_proto_serialization.h" #include #include "absl/base/attributes.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/aead/aes_eax_key.h" #include "tink/aead/aes_eax_parameters.h" #include "tink/internal/key_parser.h" #include "tink/internal/key_serializer.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/parameters_parser.h" #include "tink/internal/parameters_serializer.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/secret_key_access_token.h" #include "tink/util/secret_data.h" #include "tink/util/secret_proto.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/aes_eax.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::util::SecretData; using ::crypto::tink::util::SecretDataAsStringView; using ::crypto::tink::util::SecretProto; using ::google::crypto::tink::AesEaxKeyFormat; using ::google::crypto::tink::AesEaxParams; using ::google::crypto::tink::OutputPrefixType; using AesEaxProtoParametersParserImpl = internal::ParametersParserImpl; using AesEaxProtoParametersSerializerImpl = internal::ParametersSerializerImpl; using AesEaxProtoKeyParserImpl = internal::KeyParserImpl; using AesEaxProtoKeySerializerImpl = internal::KeySerializerImpl; constexpr absl::string_view kTypeUrl = "type.googleapis.com/google.crypto.tink.AesEaxKey"; util::StatusOr ToVariant( OutputPrefixType output_prefix_type) { switch (output_prefix_type) { case OutputPrefixType::LEGACY: ABSL_FALLTHROUGH_INTENDED; // Parse LEGACY output prefix as CRUNCHY. case OutputPrefixType::CRUNCHY: return AesEaxParameters::Variant::kCrunchy; case OutputPrefixType::RAW: return AesEaxParameters::Variant::kNoPrefix; case OutputPrefixType::TINK: return AesEaxParameters::Variant::kTink; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine AesEaxParameters::Variant"); } } util::StatusOr ToOutputPrefixType( AesEaxParameters::Variant variant) { switch (variant) { case AesEaxParameters::Variant::kCrunchy: return OutputPrefixType::CRUNCHY; case AesEaxParameters::Variant::kNoPrefix: return OutputPrefixType::RAW; case AesEaxParameters::Variant::kTink: return OutputPrefixType::TINK; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine output prefix type"); } } util::StatusOr GetProtoParams( const AesEaxParameters& parameters) { // Legacy Tink AES-EAX key proto format assumes 16-byte tags. if (parameters.GetTagSizeInBytes() != 16) { return util::Status( absl::StatusCode::kInvalidArgument, "Tink currently restricts AES-EAX tag size to 16 bytes."); } AesEaxParams params; params.set_iv_size(parameters.GetIvSizeInBytes()); return params; } util::StatusOr ParseParameters( const internal::ProtoParametersSerialization& serialization) { if (serialization.GetKeyTemplate().type_url() != kTypeUrl) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Wrong type URL when parsing AesEaxParameters: ", serialization.GetKeyTemplate().type_url())); } AesEaxKeyFormat proto_key_format; if (!proto_key_format.ParseFromString( serialization.GetKeyTemplate().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse AesEaxKeyFormat proto"); } util::StatusOr variant = ToVariant(serialization.GetKeyTemplate().output_prefix_type()); if (!variant.ok()) return variant.status(); // Legacy Tink AES-EAX key proto format assumes 16-byte tags only. return AesEaxParameters::Builder() .SetVariant(*variant) .SetKeySizeInBytes(proto_key_format.key_size()) .SetIvSizeInBytes(proto_key_format.params().iv_size()) .SetTagSizeInBytes(16) .Build(); } util::StatusOr SerializeParameters( const AesEaxParameters& parameters) { util::StatusOr params = GetProtoParams(parameters); if (!params.ok()) return params.status(); util::StatusOr output_prefix_type = ToOutputPrefixType(parameters.GetVariant()); if (!output_prefix_type.ok()) return output_prefix_type.status(); AesEaxKeyFormat proto_key_format; *proto_key_format.mutable_params() = *params; proto_key_format.set_key_size(parameters.GetKeySizeInBytes()); return internal::ProtoParametersSerialization::Create( kTypeUrl, *output_prefix_type, proto_key_format.SerializeAsString()); } util::StatusOr ParseKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (serialization.TypeUrl() != kTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing AesEaxKey."); } if (!token.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "SecretKeyAccess is required"); } SecretProto proto_key; const RestrictedData& restricted_data = serialization.SerializedKeyProto(); if (!proto_key->ParseFromString(restricted_data.GetSecret(*token))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse AesEaxKey proto"); } if (proto_key->version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } util::StatusOr variant = ToVariant(serialization.GetOutputPrefixType()); if (!variant.ok()) return variant.status(); util::StatusOr parameters = AesEaxParameters::Builder() .SetVariant(*variant) .SetKeySizeInBytes(proto_key->key_value().length()) .SetIvSizeInBytes(proto_key->params().iv_size()) // Legacy AES-EAX key proto format assumes 16-byte tags. .SetTagSizeInBytes(16) .Build(); if (!parameters.ok()) return parameters.status(); return AesEaxKey::Create( *parameters, RestrictedData(proto_key->key_value(), *token), serialization.IdRequirement(), GetPartialKeyAccess()); } util::StatusOr SerializeKey( const AesEaxKey& key, absl::optional token) { util::StatusOr params = GetProtoParams(key.GetParameters()); if (!params.ok()) return params.status(); util::StatusOr restricted_input = key.GetKeyBytes(GetPartialKeyAccess()); if (!restricted_input.ok()) return restricted_input.status(); if (!token.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "SecretKeyAccess is required"); } SecretProto proto_key; proto_key->set_version(0); proto_key->set_key_value(restricted_input->GetSecret(*token)); *proto_key->mutable_params() = *params; util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetParameters().GetVariant()); if (!output_prefix_type.ok()) return output_prefix_type.status(); util::StatusOr serialized_proto = proto_key.SerializeAsSecretData(); if (!serialized_proto.ok()) return serialized_proto.status(); RestrictedData restricted_output = RestrictedData(SecretDataAsStringView(*serialized_proto), *token); return internal::ProtoKeySerialization::Create( kTypeUrl, restricted_output, google::crypto::tink::KeyData::SYMMETRIC, *output_prefix_type, key.GetIdRequirement()); } AesEaxProtoParametersParserImpl* AesEaxProtoParametersParser() { static auto* parser = new AesEaxProtoParametersParserImpl(kTypeUrl, ParseParameters); return parser; } AesEaxProtoParametersSerializerImpl* AesEaxProtoParametersSerializer() { static auto* serializer = new AesEaxProtoParametersSerializerImpl(kTypeUrl, SerializeParameters); return serializer; } AesEaxProtoKeyParserImpl* AesEaxProtoKeyParser() { static auto* parser = new AesEaxProtoKeyParserImpl(kTypeUrl, ParseKey); return parser; } AesEaxProtoKeySerializerImpl* AesEaxProtoKeySerializer() { static auto* serializer = new AesEaxProtoKeySerializerImpl(SerializeKey); return serializer; } } // namespace util::Status RegisterAesEaxProtoSerialization() { util::Status status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersParser(AesEaxProtoParametersParser()); if (!status.ok()) return status; status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersSerializer(AesEaxProtoParametersSerializer()); if (!status.ok()) return status; status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(AesEaxProtoKeyParser()); if (!status.ok()) return status; return internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(AesEaxProtoKeySerializer()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_eax_proto_serialization.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_AES_EAX_PROTO_SERIALIZATION_H_ #define TINK_AEAD_AES_EAX_PROTO_SERIALIZATION_H_ #include "tink/util/status.h" namespace crypto { namespace tink { // Registers proto parsers and serializers for AES-EAX parameters and keys. crypto::tink::util::Status RegisterAesEaxProtoSerialization(); } // namespace tink } // namespace crypto #endif // TINK_AEAD_AES_EAX_PROTO_SERIALIZATION_H_ ================================================ FILE: cc/aead/aes_eax_proto_serialization_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_eax_proto_serialization.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/aead/aes_eax_key.h" #include "tink/aead/aes_eax_parameters.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/subtle/random.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/aes_eax.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::subtle::Random; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::AesEaxKeyFormat; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::IsTrue; using ::testing::NotNull; using ::testing::TestWithParam; using ::testing::Values; const absl::string_view kAesEaxTypeUrl = "type.googleapis.com/google.crypto.tink.AesEaxKey"; struct TestCase { int key_size; int iv_size; AesEaxParameters::Variant variant; OutputPrefixType output_prefix_type; absl::optional id; std::string output_prefix; }; class AesEaxProtoSerializationTest : public TestWithParam { protected: AesEaxProtoSerializationTest() { internal::MutableSerializationRegistry::GlobalInstance().Reset(); } }; TEST_F(AesEaxProtoSerializationTest, RegisterTwiceSucceeds) { ASSERT_THAT(RegisterAesEaxProtoSerialization(), IsOk()); ASSERT_THAT(RegisterAesEaxProtoSerialization(), IsOk()); } INSTANTIATE_TEST_SUITE_P( AesEaxProtoSerializationTestSuite, AesEaxProtoSerializationTest, Values(TestCase{/*key_size=*/16, /*iv_size=*/12, AesEaxParameters::Variant::kTink, OutputPrefixType::TINK, /*id=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{/*key_size=*/24, /*iv_size=*/12, AesEaxParameters::Variant::kCrunchy, OutputPrefixType::CRUNCHY, /*id=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{/*key_size=*/32, /*iv_size=*/16, AesEaxParameters::Variant::kNoPrefix, OutputPrefixType::RAW, /*id=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(AesEaxProtoSerializationTest, ParseParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesEaxProtoSerialization(), IsOk()); AesEaxKeyFormat key_format_proto; key_format_proto.set_key_size(test_case.key_size); key_format_proto.mutable_params()->set_iv_size(test_case.iv_size); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kAesEaxTypeUrl, test_case.output_prefix_type, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parsed_parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(parsed_parameters, IsOk()); EXPECT_THAT((*parsed_parameters)->HasIdRequirement(), Eq(test_case.id.has_value())); util::StatusOr expected_parameters = AesEaxParameters::Builder() .SetKeySizeInBytes(test_case.key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(16) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(expected_parameters, IsOk()); EXPECT_THAT(**parsed_parameters, Eq(*expected_parameters)); } TEST_F(AesEaxProtoSerializationTest, ParseParametersWithInvalidSerializationFails) { ASSERT_THAT(RegisterAesEaxProtoSerialization(), IsOk()); AesEaxKeyFormat key_format_proto; key_format_proto.set_key_size(16); key_format_proto.mutable_params()->set_iv_size(16); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kAesEaxTypeUrl, OutputPrefixType::RAW, "invalid_serialization"); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT(internal::MutableSerializationRegistry::GlobalInstance() .ParseParameters(*serialization) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(AesEaxProtoSerializationTest, ParseParametersWithUnkownOutputPrefixFails) { ASSERT_THAT(RegisterAesEaxProtoSerialization(), IsOk()); AesEaxKeyFormat key_format_proto; key_format_proto.set_key_size(16); key_format_proto.mutable_params()->set_iv_size(16); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kAesEaxTypeUrl, OutputPrefixType::UNKNOWN_PREFIX, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT(internal::MutableSerializationRegistry::GlobalInstance() .ParseParameters(*serialization) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(AesEaxProtoSerializationTest, SerializeParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesEaxProtoSerialization(), IsOk()); // Tink currently restricts AES-EAX tag size to 16 bytes. util::StatusOr parameters = AesEaxParameters::Builder() .SetVariant(test_case.variant) .SetKeySizeInBytes(test_case.key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(16) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( *parameters); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kAesEaxTypeUrl)); const internal::ProtoParametersSerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->GetKeyTemplate().type_url(), Eq(kAesEaxTypeUrl)); EXPECT_THAT(proto_serialization->GetKeyTemplate().output_prefix_type(), Eq(test_case.output_prefix_type)); AesEaxKeyFormat key_format; ASSERT_THAT( key_format.ParseFromString(proto_serialization->GetKeyTemplate().value()), IsTrue()); EXPECT_THAT(key_format.key_size(), Eq(test_case.key_size)); EXPECT_THAT(key_format.params().iv_size(), Eq(test_case.iv_size)); } TEST_F(AesEaxProtoSerializationTest, SerializeParametersWithDisallowedTagSizeFails) { ASSERT_THAT(RegisterAesEaxProtoSerialization(), IsOk()); util::StatusOr parameters = AesEaxParameters::Builder() .SetVariant(AesEaxParameters::Variant::kNoPrefix) .SetKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(14) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( *parameters); EXPECT_THAT(serialization.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(AesEaxProtoSerializationTest, ParseKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesEaxProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(test_case.key_size); google::crypto::tink::AesEaxKey key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); key_proto.mutable_params()->set_iv_size(test_case.iv_size); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kAesEaxTypeUrl, serialized_key, KeyData::SYMMETRIC, test_case.output_prefix_type, test_case.id); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); EXPECT_THAT((*key)->GetIdRequirement(), Eq(test_case.id)); EXPECT_THAT((*key)->GetParameters().HasIdRequirement(), test_case.id.has_value()); util::StatusOr expected_parameters = AesEaxParameters::Builder() .SetVariant(test_case.variant) .SetKeySizeInBytes(test_case.key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(16) .Build(); ASSERT_THAT(expected_parameters, IsOk()); util::StatusOr expected_key = AesEaxKey::Create( *expected_parameters, RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(expected_key, IsOk()); EXPECT_THAT(**key, Eq(*expected_key)); } TEST_F(AesEaxProtoSerializationTest, ParseLegacyKeyAsCrunchy) { ASSERT_THAT(RegisterAesEaxProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); google::crypto::tink::AesEaxKey key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); key_proto.mutable_params()->set_iv_size(16); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kAesEaxTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::LEGACY, /*id_requirement=*/123); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); const AesEaxKey* aes_eax_key = dynamic_cast(key->get()); ASSERT_THAT(aes_eax_key, NotNull()); EXPECT_THAT(aes_eax_key->GetParameters().GetVariant(), Eq(AesEaxParameters::Variant::kCrunchy)); } TEST_F(AesEaxProtoSerializationTest, ParseKeyWithInvalidSerializationFails) { ASSERT_THAT(RegisterAesEaxProtoSerialization(), IsOk()); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kAesEaxTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(AesEaxProtoSerializationTest, ParseKeyNoSecretKeyAccessFails) { ASSERT_THAT(RegisterAesEaxProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(16); google::crypto::tink::AesEaxKey key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); key_proto.mutable_params()->set_iv_size(16); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kAesEaxTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(AesEaxProtoSerializationTest, ParseKeyWithInvalidVersionFails) { ASSERT_THAT(RegisterAesEaxProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(16); google::crypto::tink::AesEaxKey key_proto; key_proto.set_version(1); // Invalid version number. key_proto.set_key_value(raw_key_bytes); key_proto.mutable_params()->set_iv_size(16); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kAesEaxTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(AesEaxProtoSerializationTest, SerializeKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesEaxProtoSerialization(), IsOk()); // Tink currently restricts AES-EAX tag size to 16 bytes. util::StatusOr parameters = AesEaxParameters::Builder() .SetVariant(test_case.variant) .SetKeySizeInBytes(test_case.key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(16) .Build(); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(test_case.key_size); util::StatusOr key = AesEaxKey::Create( *parameters, RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kAesEaxTypeUrl)); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq(kAesEaxTypeUrl)); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::SYMMETRIC)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id)); google::crypto::tink::AesEaxKey proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.key_value().size(), Eq(test_case.key_size)); EXPECT_THAT(proto_key.key_value(), Eq(raw_key_bytes)); EXPECT_THAT(proto_key.params().iv_size(), Eq(test_case.iv_size)); } TEST_F(AesEaxProtoSerializationTest, SerializeKeyWithDisallowedTagSizeFails) { ASSERT_THAT(RegisterAesEaxProtoSerialization(), IsOk()); util::StatusOr parameters = AesEaxParameters::Builder() .SetVariant(AesEaxParameters::Variant::kNoPrefix) .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(12) .Build(); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); util::StatusOr key = AesEaxKey::Create( *parameters, RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); EXPECT_THAT(serialization.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(AesEaxProtoSerializationTest, SerializeKeyNoSecretKeyAccessFails) { ASSERT_THAT(RegisterAesEaxProtoSerialization(), IsOk()); util::StatusOr parameters = AesEaxParameters::Builder() .SetVariant(AesEaxParameters::Variant::kNoPrefix) .SetKeySizeInBytes(16) .SetIvSizeInBytes(12) .SetTagSizeInBytes(16) .Build(); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(16); util::StatusOr key = AesEaxKey::Create( *parameters, RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey(*key, absl::nullopt); EXPECT_THAT(serialization.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_gcm_key.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_gcm_key.h" #include #include #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/types/optional.h" #include "tink/aead/aes_gcm_parameters.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { util::StatusOr ComputeOutputPrefix( const AesGcmParameters& parameters, absl::optional id_requirement) { switch (parameters.GetVariant()) { case AesGcmParameters::Variant::kNoPrefix: return std::string(""); // Empty prefix. case AesGcmParameters::Variant::kCrunchy: if (!id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "id requirement must have value with kCrunchy or kLegacy"); } return absl::StrCat(absl::HexStringToBytes("00"), subtle::BigEndian32(*id_requirement)); case AesGcmParameters::Variant::kTink: if (!id_requirement.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "id requirement must have value with kTink"); } return absl::StrCat(absl::HexStringToBytes("01"), subtle::BigEndian32(*id_requirement)); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid variant: ", parameters.GetVariant())); } } } // namespace util::StatusOr AesGcmKey::Create(const AesGcmParameters& parameters, const RestrictedData& key_bytes, absl::optional id_requirement, PartialKeyAccessToken token) { if (parameters.KeySizeInBytes() != key_bytes.size()) { return util::Status(absl::StatusCode::kInvalidArgument, "Key size does not match AES-GCM parameters"); } if (parameters.HasIdRequirement() && !id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key without ID requirement with parameters with ID " "requirement"); } if (!parameters.HasIdRequirement() && id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key with ID requirement with parameters without ID " "requirement"); } util::StatusOr output_prefix = ComputeOutputPrefix(parameters, id_requirement); if (!output_prefix.ok()) { return output_prefix.status(); } return AesGcmKey(parameters, key_bytes, id_requirement, *std::move(output_prefix)); } bool AesGcmKey::operator==(const Key& other) const { const AesGcmKey* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (GetParameters() != that->GetParameters()) { return false; } if (id_requirement_ != that->id_requirement_) { return false; } return key_bytes_ == that->key_bytes_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_gcm_key.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_AES_GCM_KEY_H_ #define TINK_AEAD_AES_GCM_KEY_H_ #include #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/aead/aead_key.h" #include "tink/aead/aes_gcm_parameters.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Represents an AEAD that uses AES-GCM. class AesGcmKey : public AeadKey { public: // Copyable and movable. AesGcmKey(const AesGcmKey& other) = default; AesGcmKey& operator=(const AesGcmKey& other) = default; AesGcmKey(AesGcmKey&& other) = default; AesGcmKey& operator=(AesGcmKey&& other) = default; // Creates a new AES-GCM key. If the parameters specify a variant that uses // a prefix, then the id is used to compute this prefix. static util::StatusOr Create(const AesGcmParameters& parameters, const RestrictedData& key_bytes, absl::optional id_requirement, PartialKeyAccessToken token); // Returns the underlying AES key. const RestrictedData& GetKeyBytes(PartialKeyAccessToken token) const { return key_bytes_; } absl::string_view GetOutputPrefix() const override { return output_prefix_; } const AesGcmParameters& GetParameters() const override { return parameters_; } absl::optional GetIdRequirement() const override { return id_requirement_; } bool operator==(const Key& other) const override; private: AesGcmKey(const AesGcmParameters& parameters, const RestrictedData& key_bytes, absl::optional id_requirement, std::string output_prefix) : parameters_(parameters), key_bytes_(key_bytes), id_requirement_(id_requirement), output_prefix_(std::move(output_prefix)) {} AesGcmParameters parameters_; RestrictedData key_bytes_; absl::optional id_requirement_; std::string output_prefix_; }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_AES_GCM_KEY_H_ ================================================ FILE: cc/aead/aes_gcm_key_manager.h ================================================ // Copyright 2017 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_AES_GCM_KEY_MANAGER_H_ #define TINK_AEAD_AES_GCM_KEY_MANAGER_H_ #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/aead/cord_aead.h" #include "tink/aead/internal/cord_aes_gcm_boringssl.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/input_stream.h" #include "tink/internal/fips_utils.h" #include "tink/subtle/aes_gcm_boringssl.h" #include "tink/subtle/random.h" #include "tink/util/constants.h" #include "tink/util/input_stream_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/aes_gcm.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class AesGcmKeyManager : public KeyTypeManager> { public: class AeadFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::AesGcmKey& key) const override { auto aes_gcm_result = subtle::AesGcmBoringSsl::New( util::SecretDataFromStringView(key.key_value())); if (!aes_gcm_result.ok()) return aes_gcm_result.status(); return {std::move(aes_gcm_result.value())}; } }; class CordAeadFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::AesGcmKey& key) const override { auto cord_aes_gcm_result = crypto::tink::internal::CordAesGcmBoringSsl::New( util::SecretDataFromStringView(key.key_value())); if (!cord_aes_gcm_result.ok()) return cord_aes_gcm_result.status(); return {std::move(cord_aes_gcm_result.value())}; } }; AesGcmKeyManager() : KeyTypeManager(absl::make_unique(), absl::make_unique()) { } // Returns the version of this key manager. uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::SYMMETRIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::AesGcmKey& key) const override { crypto::tink::util::Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; return ValidateAesKeySize(key.key_value().size()); } crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::AesGcmKeyFormat& key_format) const override { return ValidateAesKeySize(key_format.key_size()); } crypto::tink::util::StatusOr CreateKey( const google::crypto::tink::AesGcmKeyFormat& key_format) const override { google::crypto::tink::AesGcmKey key; key.set_version(get_version()); key.set_key_value( crypto::tink::subtle::Random::GetRandomBytes(key_format.key_size())); return key; } crypto::tink::util::StatusOr DeriveKey( const google::crypto::tink::AesGcmKeyFormat& key_format, InputStream* input_stream) const override { crypto::tink::util::Status status = ValidateVersion(key_format.version(), get_version()); if (!status.ok()) return status; crypto::tink::util::StatusOr randomness = ReadBytesFromStream(key_format.key_size(), input_stream); if (!randomness.ok()) { if (randomness.status().code() == absl::StatusCode::kOutOfRange) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, "Could not get enough pseudorandomness from input stream"); } return randomness.status(); } google::crypto::tink::AesGcmKey key; key.set_version(get_version()); key.set_key_value(randomness.value()); return key; } internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: const std::string key_type_ = absl::StrCat( kTypeGoogleapisCom, google::crypto::tink::AesGcmKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_AES_GCM_KEY_MANAGER_H_ ================================================ FILE: cc/aead/aes_gcm_key_manager_test.cc ================================================ // Copyright 2017 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_gcm_key_manager.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/aead.h" #include "tink/aead/cord_aead.h" #include "tink/aead/internal/cord_aes_gcm_boringssl.h" #include "tink/subtle/aead_test_util.h" #include "tink/subtle/aes_gcm_boringssl.h" #include "tink/util/istream_input_stream.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/aes_gcm.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::internal::CordAesGcmBoringSsl; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::IstreamInputStream; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::AesGcmKey; using ::google::crypto::tink::AesGcmKeyFormat; using ::testing::Eq; using ::testing::HasSubstr; TEST(AesGcmKeyManagerTest, Basics) { EXPECT_THAT(AesGcmKeyManager().get_version(), Eq(0)); EXPECT_THAT(AesGcmKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.AesGcmKey")); EXPECT_THAT(AesGcmKeyManager().key_material_type(), Eq(google::crypto::tink::KeyData::SYMMETRIC)); } TEST(AesGcmKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(AesGcmKeyManager().ValidateKey(AesGcmKey()), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmKeyManagerTest, ValidateValid16ByteKey) { AesGcmKey key; key.set_version(0); key.set_key_value("0123456789abcdef"); EXPECT_THAT(AesGcmKeyManager().ValidateKey(key), IsOk()); } TEST(AesGcmKeyManagerTest, ValidateValid32ByteKey) { AesGcmKey key; key.set_version(0); key.set_key_value("01234567890123456789012345678901"); EXPECT_THAT(AesGcmKeyManager().ValidateKey(key), IsOk()); } TEST(AesGcmKeyManagerTest, InvalidKeySizes15Bytes) { AesGcmKey key; key.set_version(0); key.set_key_value("0123456789abcde"); EXPECT_THAT(AesGcmKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmKeyManagerTest, InvalidKeySizes17Bytes) { AesGcmKey key; key.set_version(0); key.set_key_value("0123456789abcdefg"); EXPECT_THAT(AesGcmKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmKeyManagerTest, InvalidKeySizes24Bytes) { AesGcmKey key; key.set_version(0); key.set_key_value("01234567890123"); EXPECT_THAT(AesGcmKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmKeyManagerTest, InvalidKeySizes31Bytes) { AesGcmKey key; key.set_version(0); key.set_key_value("0123456789012345678901234567890"); EXPECT_THAT(AesGcmKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmKeyManagerTest, InvalidKeySizes33Bytes) { AesGcmKey key; key.set_version(0); key.set_key_value("012345678901234567890123456789012"); EXPECT_THAT(AesGcmKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmKeyManagerTest, ValidateKeyFormat) { AesGcmKeyFormat format; format.set_key_size(0); EXPECT_THAT(AesGcmKeyManager().ValidateKeyFormat(format), StatusIs(absl::StatusCode::kInvalidArgument)); format.set_key_size(1); EXPECT_THAT(AesGcmKeyManager().ValidateKeyFormat(format), StatusIs(absl::StatusCode::kInvalidArgument)); format.set_key_size(15); EXPECT_THAT(AesGcmKeyManager().ValidateKeyFormat(format), StatusIs(absl::StatusCode::kInvalidArgument)); format.set_key_size(16); EXPECT_THAT(AesGcmKeyManager().ValidateKeyFormat(format), IsOk()); format.set_key_size(17); EXPECT_THAT(AesGcmKeyManager().ValidateKeyFormat(format), StatusIs(absl::StatusCode::kInvalidArgument)); format.set_key_size(31); EXPECT_THAT(AesGcmKeyManager().ValidateKeyFormat(format), StatusIs(absl::StatusCode::kInvalidArgument)); format.set_key_size(32); EXPECT_THAT(AesGcmKeyManager().ValidateKeyFormat(format), IsOk()); format.set_key_size(33); EXPECT_THAT(AesGcmKeyManager().ValidateKeyFormat(format), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmKeyManagerTest, Create16ByteKey) { AesGcmKeyFormat format; format.set_key_size(16); StatusOr key_or = AesGcmKeyManager().CreateKey(format); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().key_value().size(), Eq(format.key_size())); } TEST(AesGcmKeyManagerTest, Create32ByteKey) { AesGcmKeyFormat format; format.set_key_size(32); StatusOr key_or = AesGcmKeyManager().CreateKey(format); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().key_value().size(), Eq(format.key_size())); } TEST(AesGcmKeyManagerTest, CreateAead) { AesGcmKeyFormat format; format.set_key_size(32); StatusOr key_or = AesGcmKeyManager().CreateKey(format); ASSERT_THAT(key_or, IsOk()); StatusOr> aead_or = AesGcmKeyManager().GetPrimitive(key_or.value()); ASSERT_THAT(aead_or, IsOk()); StatusOr> boring_ssl_aead_or = subtle::AesGcmBoringSsl::New( util::SecretDataFromStringView(key_or.value().key_value())); ASSERT_THAT(boring_ssl_aead_or, IsOk()); ASSERT_THAT(EncryptThenDecrypt(*aead_or.value(), *boring_ssl_aead_or.value(), "message", "aad"), IsOk()); } TEST(AesGcmKeyManagerTest, CreateCordAead) { AesGcmKeyFormat format; format.set_key_size(32); StatusOr key_or = AesGcmKeyManager().CreateKey(format); ASSERT_THAT(key_or, IsOk()); StatusOr> aead_or = AesGcmKeyManager().GetPrimitive(key_or.value()); ASSERT_THAT(aead_or, IsOk()); StatusOr> boring_ssl_aead_or = CordAesGcmBoringSsl::New( util::SecretDataFromStringView(key_or.value().key_value())); ASSERT_THAT(boring_ssl_aead_or, IsOk()); ASSERT_THAT(EncryptThenDecrypt(*aead_or.value(), *boring_ssl_aead_or.value(), "message", "aad"), IsOk()); } TEST(AesGcmKeyManagerTest, DeriveShortKey) { AesGcmKeyFormat format; format.set_key_size(16); format.set_version(0); IstreamInputStream input_stream{ absl::make_unique("0123456789abcdefghijklmnop")}; StatusOr key_or = AesGcmKeyManager().DeriveKey(format, &input_stream); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().key_value(), Eq("0123456789abcdef")); } TEST(AesGcmKeyManagerTest, DeriveLongKey) { AesGcmKeyFormat format; format.set_key_size(32); format.set_version(0); IstreamInputStream input_stream{absl::make_unique( "0123456789abcdef0123456789abcdefXXX")}; StatusOr key_or = AesGcmKeyManager().DeriveKey(format, &input_stream); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().key_value(), Eq("0123456789abcdef0123456789abcdef")); } TEST(AesGcmKeyManagerTest, DeriveKeyNotEnoughRandomness) { AesGcmKeyFormat format; format.set_key_size(16); format.set_version(0); IstreamInputStream input_stream{ absl::make_unique("0123456789")}; ASSERT_THAT(AesGcmKeyManager().DeriveKey(format, &input_stream).status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmKeyManagerTest, DeriveKeyWrongVersion) { AesGcmKeyFormat format; format.set_key_size(16); format.set_version(1); IstreamInputStream input_stream{ absl::make_unique("0123456789abcdefghijklmnop")}; ASSERT_THAT( AesGcmKeyManager().DeriveKey(format, &input_stream).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("version"))); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_gcm_key_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_gcm_key.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/aead/aes_gcm_parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Combine; using ::testing::Eq; using ::testing::Range; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { AesGcmParameters::Variant variant; absl::optional id_requirement; std::string output_prefix; }; using AesGcmKeyTest = TestWithParam>; INSTANTIATE_TEST_SUITE_P( AesGcmKeyTestSuite, AesGcmKeyTest, Combine(Values(16, 24, 32), Range(12, 16), Values(TestCase{AesGcmParameters::Variant::kTink, 0x02030400, std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{AesGcmParameters::Variant::kCrunchy, 0x01030005, std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{AesGcmParameters::Variant::kNoPrefix, absl::nullopt, ""}))); TEST_P(AesGcmKeyTest, CreateSucceeds) { int key_size; int iv_and_tag_size; // NOTE: There's no requirement for IV size == tag size. TestCase test_case; std::tie(key_size, iv_and_tag_size, test_case) = GetParam(); util::StatusOr params = AesGcmParameters::Builder() .SetKeySizeInBytes(key_size) .SetIvSizeInBytes(iv_and_tag_size) .SetTagSizeInBytes(iv_and_tag_size) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(key_size); util::StatusOr key = AesGcmKey::Create( *params, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); EXPECT_THAT(key->GetParameters(), Eq(*params)); EXPECT_THAT(key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(key->GetOutputPrefix(), Eq(test_case.output_prefix)); } TEST(AesGcmKeyTest, CreateKeyWithMismatchedKeySizeFails) { // Key size parameter is 32 bytes. util::StatusOr params = AesGcmParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kTink) .Build(); ASSERT_THAT(params, IsOk()); // Key material is 16 bytes (another valid key length). RestrictedData mismatched_secret = RestrictedData(/*num_random_bytes=*/16); EXPECT_THAT(AesGcmKey::Create(*params, mismatched_secret, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmKeyTest, CreateKeyWithInvalidIdRequirementFails) { util::StatusOr no_prefix_params = AesGcmParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(no_prefix_params, IsOk()); util::StatusOr tink_params = AesGcmParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kTink) .Build(); ASSERT_THAT(tink_params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); EXPECT_THAT(AesGcmKey::Create(*no_prefix_params, secret, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT( AesGcmKey::Create(*tink_params, secret, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(AesGcmKeyTest, GetKeyBytes) { int key_size; int iv_and_tag_size; // NOTE: There's no requirement for IV size == tag size. TestCase test_case; std::tie(key_size, iv_and_tag_size, test_case) = GetParam(); util::StatusOr params = AesGcmParameters::Builder() .SetKeySizeInBytes(key_size) .SetIvSizeInBytes(iv_and_tag_size) .SetTagSizeInBytes(iv_and_tag_size) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(key_size); util::StatusOr key = AesGcmKey::Create( *params, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); EXPECT_THAT(key->GetKeyBytes(GetPartialKeyAccess()), Eq(secret)); } TEST_P(AesGcmKeyTest, KeyEquals) { int key_size; int iv_and_tag_size; // NOTE: There's no requirement for IV size == tag size. TestCase test_case; std::tie(key_size, iv_and_tag_size, test_case) = GetParam(); util::StatusOr params = AesGcmParameters::Builder() .SetKeySizeInBytes(key_size) .SetIvSizeInBytes(iv_and_tag_size) .SetTagSizeInBytes(iv_and_tag_size) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(key_size); util::StatusOr key = AesGcmKey::Create( *params, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = AesGcmKey::Create( *params, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key == *other_key); EXPECT_TRUE(*other_key == *key); EXPECT_FALSE(*key != *other_key); EXPECT_FALSE(*other_key != *key); } TEST(AesGcmKeyTest, DifferentVariantNotEqual) { util::StatusOr crunchy_params = AesGcmParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kCrunchy) .Build(); ASSERT_THAT(crunchy_params, IsOk()); util::StatusOr tink_params = AesGcmParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kTink) .Build(); ASSERT_THAT(tink_params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = AesGcmKey::Create(*crunchy_params, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = AesGcmKey::Create(*tink_params, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST(AesGcmKeyTest, DifferentSecretDataNotEqual) { util::StatusOr params = AesGcmParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kTink) .Build(); ASSERT_THAT(params, IsOk()); RestrictedData secret1 = RestrictedData(/*num_random_bytes=*/32); RestrictedData secret2 = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = AesGcmKey::Create( *params, secret1, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = AesGcmKey::Create( *params, secret2, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST(AesGcmKeyTest, DifferentIdRequirementNotEqual) { util::StatusOr params = AesGcmParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kTink) .Build(); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = AesGcmKey::Create( *params, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = AesGcmKey::Create( *params, secret, /*id_requirement=*/0x02030405, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_gcm_parameters.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_gcm_parameters.h" #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/parameters.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { AesGcmParameters::Builder& AesGcmParameters::Builder::SetKeySizeInBytes( int key_size) { key_size_in_bytes_ = key_size; return *this; } AesGcmParameters::Builder& AesGcmParameters::Builder::SetIvSizeInBytes( int iv_size) { iv_size_in_bytes_ = iv_size; return *this; } AesGcmParameters::Builder& AesGcmParameters::Builder::SetTagSizeInBytes( int tag_size) { tag_size_in_bytes_ = tag_size; return *this; } AesGcmParameters::Builder& AesGcmParameters::Builder::SetVariant( Variant variant) { variant_ = variant; return *this; } util::StatusOr AesGcmParameters::Builder::Build() { if (key_size_in_bytes_ != 16 && key_size_in_bytes_ != 24 && key_size_in_bytes_ != 32) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Key size should be 16, 24, or 32 bytes, got ", key_size_in_bytes_, " bytes.")); } if (iv_size_in_bytes_ <= 0) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("IV size should be positive, got ", iv_size_in_bytes_, " bytes.")); } if (tag_size_in_bytes_ < 12 || tag_size_in_bytes_ > 16) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Tag size should be between 12 and 16 bytes, got ", tag_size_in_bytes_, " bytes.")); } static const std::set* supported_variants = new std::set( {Variant::kTink, Variant::kCrunchy, Variant::kNoPrefix}); if (supported_variants->find(variant_) == supported_variants->end()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create AES-GCM parameters with unknown variant."); } return AesGcmParameters(key_size_in_bytes_, iv_size_in_bytes_, tag_size_in_bytes_, variant_); } bool AesGcmParameters::operator==(const Parameters& other) const { const AesGcmParameters* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (key_size_in_bytes_ != that->key_size_in_bytes_) { return false; } if (iv_size_in_bytes_ != that->iv_size_in_bytes_) { return false; } if (tag_size_in_bytes_ != that->tag_size_in_bytes_) { return false; } if (variant_ != that->variant_) { return false; } return true; } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_gcm_parameters.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_AES_GCM_PARAMETERS_H_ #define TINK_AEAD_AES_GCM_PARAMETERS_H_ #include "tink/aead/aead_parameters.h" #include "tink/parameters.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Describes the parameters of an `AesGcmKey`. class AesGcmParameters : public AeadParameters { public: // Description of the output prefix prepended to the ciphertext. enum class Variant : int { // Prepends '0x01' to the ciphertext. kTink = 1, // Prepends '0x00' to the ciphertext. kCrunchy = 2, // Does not prepend any prefix (i.e., keys must have no ID requirement). kNoPrefix = 3, // Added to guard from failures that may be caused by future expansions. kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Creates AES-GCM parameters instances. class Builder { public: // Copyable and movable. Builder(const Builder& other) = default; Builder& operator=(const Builder& other) = default; Builder(Builder&& other) = default; Builder& operator=(Builder&& other) = default; // Creates initially empty parameters builder. Builder() = default; Builder& SetKeySizeInBytes(int key_size); Builder& SetIvSizeInBytes(int iv_size); Builder& SetTagSizeInBytes(int tag_size); Builder& SetVariant(Variant variant); // Creates AES-GCM parameters object from this builder. util::StatusOr Build(); private: int key_size_in_bytes_; int iv_size_in_bytes_; int tag_size_in_bytes_; Variant variant_; }; // Copyable and movable. AesGcmParameters(const AesGcmParameters& other) = default; AesGcmParameters& operator=(const AesGcmParameters& other) = default; AesGcmParameters(AesGcmParameters&& other) = default; AesGcmParameters& operator=(AesGcmParameters&& other) = default; int KeySizeInBytes() const { return key_size_in_bytes_; } int IvSizeInBytes() const { return iv_size_in_bytes_; } int TagSizeInBytes() const { return tag_size_in_bytes_; } Variant GetVariant() const { return variant_; } bool HasIdRequirement() const override { return variant_ != Variant::kNoPrefix; } bool operator==(const Parameters& other) const override; private: AesGcmParameters(int key_size_in_bytes, int iv_size_in_bytes, int tag_size_in_bytes, Variant variant) : key_size_in_bytes_(key_size_in_bytes), iv_size_in_bytes_(iv_size_in_bytes), tag_size_in_bytes_(tag_size_in_bytes), variant_(variant) {} int key_size_in_bytes_; int iv_size_in_bytes_; int tag_size_in_bytes_; Variant variant_; }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_AES_GCM_PARAMETERS_H_ ================================================ FILE: cc/aead/aes_gcm_parameters_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_gcm_parameters.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Combine; using ::testing::Eq; using ::testing::IsTrue; using ::testing::Range; using ::testing::TestWithParam; using ::testing::Values; struct BuildTestCase { AesGcmParameters::Variant variant; int key_size; int iv_size; int tag_size; bool has_id_requirement; }; using AesGcmParametersBuildTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( AesGcmParametersBuildTestSuite, AesGcmParametersBuildTest, Values(BuildTestCase{AesGcmParameters::Variant::kTink, /*key_size=*/16, /*iv_size=*/12, /*tag_size=*/12, /*has_id_requirement=*/true}, BuildTestCase{AesGcmParameters::Variant::kCrunchy, /*key_size=*/24, /*iv_size=*/14, /*tag_size=*/14, /*has_id_requirement=*/true}, BuildTestCase{AesGcmParameters::Variant::kNoPrefix, /*key_size=*/32, /*iv_size=*/16, /*tag_size=*/16, /*has_id_requirement=*/false})); TEST_P(AesGcmParametersBuildTest, Build) { BuildTestCase test_case = GetParam(); util::StatusOr parameters = AesGcmParameters::Builder() .SetKeySizeInBytes(test_case.key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(test_case.tag_size) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->KeySizeInBytes(), Eq(test_case.key_size)); EXPECT_THAT(parameters->IvSizeInBytes(), Eq(test_case.iv_size)); EXPECT_THAT(parameters->TagSizeInBytes(), Eq(test_case.tag_size)); EXPECT_THAT(parameters->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(parameters->HasIdRequirement(), Eq(test_case.has_id_requirement)); } TEST(AesGcmParametersTest, BuildWithoutSettingVariantFails) { EXPECT_THAT(AesGcmParameters::Builder() .SetKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmParametersTest, BuildWithInvalidVariantFails) { EXPECT_THAT( AesGcmParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmParametersTest, BuildWithoutSettingKeySizeFails) { EXPECT_THAT(AesGcmParameters::Builder() .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmParametersTest, BuildWithInvalidKeySizeFails) { EXPECT_THAT(AesGcmParameters::Builder() .SetKeySizeInBytes(15) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesGcmParameters::Builder() .SetKeySizeInBytes(17) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesGcmParameters::Builder() .SetKeySizeInBytes(23) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesGcmParameters::Builder() .SetKeySizeInBytes(25) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesGcmParameters::Builder() .SetKeySizeInBytes(31) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesGcmParameters::Builder() .SetKeySizeInBytes(33) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmParametersTest, BuildWithoutSettingIvSizeFails) { EXPECT_THAT(AesGcmParameters::Builder() .SetKeySizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmParametersTest, BuildWithInvalidIvSizeFails) { EXPECT_THAT(AesGcmParameters::Builder() .SetKeySizeInBytes(16) .SetIvSizeInBytes(0) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmParametersTest, BuildWithoutSettingTagSizeFails) { EXPECT_THAT(AesGcmParameters::Builder() .SetKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmParametersTest, BuildWithInvalidTagSizeFails) { // Too small. EXPECT_THAT(AesGcmParameters::Builder() .SetKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(11) .SetVariant(AesGcmParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); // Too big. EXPECT_THAT(AesGcmParameters::Builder() .SetKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(17) .SetVariant(AesGcmParameters::Variant::kNoPrefix) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmParametersTest, CopyConstructor) { util::StatusOr parameters = AesGcmParameters::Builder() .SetKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); AesGcmParameters copy(*parameters); EXPECT_THAT(copy.KeySizeInBytes(), Eq(16)); EXPECT_THAT(copy.IvSizeInBytes(), Eq(16)); EXPECT_THAT(copy.TagSizeInBytes(), Eq(16)); EXPECT_THAT(copy.GetVariant(), Eq(AesGcmParameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); } TEST(AesGcmParametersTest, CopyAssignment) { util::StatusOr parameters = AesGcmParameters::Builder() .SetKeySizeInBytes(16) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); AesGcmParameters copy = *parameters; EXPECT_THAT(copy.KeySizeInBytes(), Eq(16)); EXPECT_THAT(copy.IvSizeInBytes(), Eq(16)); EXPECT_THAT(copy.TagSizeInBytes(), Eq(16)); EXPECT_THAT(copy.GetVariant(), Eq(AesGcmParameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); } using AesGcmParametersVariantTest = TestWithParam>; INSTANTIATE_TEST_SUITE_P(AesGcmParametersVariantTestSuite, AesGcmParametersVariantTest, Combine(Values(16, 24, 32), Range(12, 16), Values(AesGcmParameters::Variant::kTink, AesGcmParameters::Variant::kCrunchy, AesGcmParameters::Variant::kNoPrefix))); TEST_P(AesGcmParametersVariantTest, ParametersEquals) { int key_size; int iv_and_tag_size; AesGcmParameters::Variant variant; std::tie(key_size, iv_and_tag_size, variant) = GetParam(); util::StatusOr parameters = AesGcmParameters::Builder() .SetKeySizeInBytes(key_size) .SetIvSizeInBytes(iv_and_tag_size) .SetTagSizeInBytes(iv_and_tag_size) .SetVariant(variant) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesGcmParameters::Builder() .SetKeySizeInBytes(key_size) .SetIvSizeInBytes(iv_and_tag_size) .SetTagSizeInBytes(iv_and_tag_size) .SetVariant(variant) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters == *other_parameters); EXPECT_TRUE(*other_parameters == *parameters); EXPECT_FALSE(*parameters != *other_parameters); EXPECT_FALSE(*other_parameters != *parameters); } TEST(AesGcmParametersTest, KeySizeNotEqual) { util::StatusOr parameters = AesGcmParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesGcmParameters::Builder() .SetKeySizeInBytes(24) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kTink) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(AesGcmParametersTest, IvSizeNotEqual) { util::StatusOr parameters = AesGcmParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesGcmParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(12) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kTink) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(AesGcmParametersTest, TagSizeNotEqual) { util::StatusOr parameters = AesGcmParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesGcmParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(14) .SetVariant(AesGcmParameters::Variant::kTink) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(AesGcmParametersTest, VariantNotEqual) { util::StatusOr parameters = AesGcmParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesGcmParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_gcm_proto_serialization.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_gcm_proto_serialization.h" #include #include "absl/base/attributes.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/aead/aes_gcm_key.h" #include "tink/aead/aes_gcm_parameters.h" #include "tink/internal/key_parser.h" #include "tink/internal/key_serializer.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/parameters_parser.h" #include "tink/internal/parameters_serializer.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/secret_key_access_token.h" #include "tink/util/secret_data.h" #include "tink/util/secret_proto.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/aes_gcm.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::util::SecretData; using ::crypto::tink::util::SecretProto; using ::google::crypto::tink::AesGcmKeyFormat; using ::google::crypto::tink::OutputPrefixType; using AesGcmProtoParametersParserImpl = internal::ParametersParserImpl; using AesGcmProtoParametersSerializerImpl = internal::ParametersSerializerImpl; using AesGcmProtoKeyParserImpl = internal::KeyParserImpl; using AesGcmProtoKeySerializerImpl = internal::KeySerializerImpl; const absl::string_view kTypeUrl = "type.googleapis.com/google.crypto.tink.AesGcmKey"; util::StatusOr ToVariant( OutputPrefixType output_prefix_type) { switch (output_prefix_type) { case OutputPrefixType::LEGACY: ABSL_FALLTHROUGH_INTENDED; // Parse LEGACY output prefix as CRUNCHY. case OutputPrefixType::CRUNCHY: return AesGcmParameters::Variant::kCrunchy; case OutputPrefixType::RAW: return AesGcmParameters::Variant::kNoPrefix; case OutputPrefixType::TINK: return AesGcmParameters::Variant::kTink; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine AesGcmParameters::Variant"); } } util::StatusOr ToOutputPrefixType( AesGcmParameters::Variant variant) { switch (variant) { case AesGcmParameters::Variant::kCrunchy: return OutputPrefixType::CRUNCHY; case AesGcmParameters::Variant::kNoPrefix: return OutputPrefixType::RAW; case AesGcmParameters::Variant::kTink: return OutputPrefixType::TINK; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine output prefix type"); } } // Legacy Tink AES-GCM key proto format assumes 12-byte random IVs and 16-byte // tags. util::Status ValidateParamsForProto(const AesGcmParameters& params) { if (params.IvSizeInBytes() != 12) { return util::Status( absl::StatusCode::kInvalidArgument, "Tink currently restricts AES-GCM IV size to 12 bytes."); } if (params.TagSizeInBytes() != 16) { return util::Status( absl::StatusCode::kInvalidArgument, "Tink currently restricts AES-GCM tag size to 16 bytes."); } return util::OkStatus(); } util::StatusOr ParseParameters( const internal::ProtoParametersSerialization& serialization) { if (serialization.GetKeyTemplate().type_url() != kTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing AesGcmParameters."); } AesGcmKeyFormat proto_key_format; if (!proto_key_format.ParseFromString( serialization.GetKeyTemplate().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse AesGcmKeyFormat proto"); } if (proto_key_format.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } util::StatusOr variant = ToVariant(serialization.GetKeyTemplate().output_prefix_type()); if (!variant.ok()) return variant.status(); // Legacy Tink AES-GCM key proto format assumes 12-byte random IVs and 16-byte // tags. return AesGcmParameters::Builder() .SetVariant(*variant) .SetKeySizeInBytes(proto_key_format.key_size()) .SetIvSizeInBytes(12) .SetTagSizeInBytes(16) .Build(); } util::StatusOr SerializeParameters( const AesGcmParameters& parameters) { util::Status valid_params = ValidateParamsForProto(parameters); if (!valid_params.ok()) return valid_params; util::StatusOr output_prefix_type = ToOutputPrefixType(parameters.GetVariant()); if (!output_prefix_type.ok()) return output_prefix_type.status(); AesGcmKeyFormat proto_key_format; proto_key_format.set_key_size(parameters.KeySizeInBytes()); return internal::ProtoParametersSerialization::Create( kTypeUrl, *output_prefix_type, proto_key_format.SerializeAsString()); } util::StatusOr ParseKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (serialization.TypeUrl() != kTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing AesGcmKey."); } if (!token.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "SecretKeyAccess is required"); } SecretProto proto_key; const RestrictedData& restricted_data = serialization.SerializedKeyProto(); if (!proto_key->ParseFromString(restricted_data.GetSecret(*token))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse AesGcmKey proto"); } if (proto_key->version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } util::StatusOr variant = ToVariant(serialization.GetOutputPrefixType()); if (!variant.ok()) return variant.status(); // Legacy AES-GCM key proto format assumes 12-byte random IVs and 16-byte // tags. util::StatusOr parameters = AesGcmParameters::Builder() .SetVariant(*variant) .SetKeySizeInBytes(proto_key->key_value().length()) .SetIvSizeInBytes(12) .SetTagSizeInBytes(16) .Build(); if (!parameters.ok()) return parameters.status(); return AesGcmKey::Create( *parameters, RestrictedData(proto_key->key_value(), *token), serialization.IdRequirement(), GetPartialKeyAccess()); } util::StatusOr SerializeKey( const AesGcmKey& key, absl::optional token) { util::Status valid_params = ValidateParamsForProto(key.GetParameters()); if (!valid_params.ok()) return valid_params; util::StatusOr restricted_input = key.GetKeyBytes(GetPartialKeyAccess()); if (!restricted_input.ok()) return restricted_input.status(); if (!token.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "SecretKeyAccess is required"); } SecretProto proto_key; proto_key->set_version(0); proto_key->set_key_value(restricted_input->GetSecret(*token)); util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetParameters().GetVariant()); if (!output_prefix_type.ok()) return output_prefix_type.status(); util::StatusOr serialized_key = proto_key.SerializeAsSecretData(); if (!serialized_key.ok()) { return serialized_key.status(); } RestrictedData restricted_output = RestrictedData(util::SecretDataAsStringView(*serialized_key), *token); return internal::ProtoKeySerialization::Create( kTypeUrl, restricted_output, google::crypto::tink::KeyData::SYMMETRIC, *output_prefix_type, key.GetIdRequirement()); } AesGcmProtoParametersParserImpl* AesGcmProtoParametersParser() { static auto* parser = new AesGcmProtoParametersParserImpl(kTypeUrl, ParseParameters); return parser; } AesGcmProtoParametersSerializerImpl* AesGcmProtoParametersSerializer() { static auto* serializer = new AesGcmProtoParametersSerializerImpl(kTypeUrl, SerializeParameters); return serializer; } AesGcmProtoKeyParserImpl* AesGcmProtoKeyParser() { static auto* parser = new AesGcmProtoKeyParserImpl(kTypeUrl, ParseKey); return parser; } AesGcmProtoKeySerializerImpl* AesGcmProtoKeySerializer() { static auto* serializer = new AesGcmProtoKeySerializerImpl(SerializeKey); return serializer; } } // namespace util::Status RegisterAesGcmProtoSerialization() { util::Status status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersParser(AesGcmProtoParametersParser()); if (!status.ok()) return status; status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersSerializer(AesGcmProtoParametersSerializer()); if (!status.ok()) return status; status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(AesGcmProtoKeyParser()); if (!status.ok()) return status; return internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(AesGcmProtoKeySerializer()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_gcm_proto_serialization.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_AES_GCM_PROTO_SERIALIZATION_H_ #define TINK_AEAD_AES_GCM_PROTO_SERIALIZATION_H_ #include "tink/util/status.h" namespace crypto { namespace tink { // Registers proto parsers and serializers for AES-GCM parameters and keys. crypto::tink::util::Status RegisterAesGcmProtoSerialization(); } // namespace tink } // namespace crypto #endif // TINK_AEAD_AES_GCM_PROTO_SERIALIZATION_H_ ================================================ FILE: cc/aead/aes_gcm_proto_serialization_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_gcm_proto_serialization.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/aead/aes_gcm_key.h" #include "tink/aead/aes_gcm_parameters.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/subtle/random.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/aes_gcm.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::subtle::Random; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::AesGcmKeyFormat; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::IsTrue; using ::testing::NotNull; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { AesGcmParameters::Variant variant; OutputPrefixType output_prefix_type; int key_size; int iv_size; int tag_size; absl::optional id; std::string output_prefix; }; class AesGcmProtoSerializationTest : public TestWithParam { protected: void SetUp() override { internal::MutableSerializationRegistry::GlobalInstance().Reset(); } }; TEST_F(AesGcmProtoSerializationTest, RegisterTwiceSucceeds) { ASSERT_THAT(RegisterAesGcmProtoSerialization(), IsOk()); ASSERT_THAT(RegisterAesGcmProtoSerialization(), IsOk()); } INSTANTIATE_TEST_SUITE_P( AesGcmProtoSerializationTestSuite, AesGcmProtoSerializationTest, Values(TestCase{AesGcmParameters::Variant::kTink, OutputPrefixType::TINK, /*key_size=*/16, /*iv_size=*/12, /*tag_size=*/16, /*id=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{AesGcmParameters::Variant::kCrunchy, OutputPrefixType::CRUNCHY, /*key_size=*/16, /*iv_size=*/12, /*tag_size=*/16, /*id=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{AesGcmParameters::Variant::kNoPrefix, OutputPrefixType::RAW, /*key_size=*/32, /*iv_size=*/12, /*tag_size=*/16, /*id=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(AesGcmProtoSerializationTest, ParseParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesGcmProtoSerialization(), IsOk()); AesGcmKeyFormat key_format_proto; key_format_proto.set_version(0); key_format_proto.set_key_size(test_case.key_size); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.AesGcmKey", test_case.output_prefix_type, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(params, IsOk()); EXPECT_THAT((*params)->HasIdRequirement(), test_case.id.has_value()); const AesGcmParameters* gcm_params = dynamic_cast(params->get()); ASSERT_THAT(gcm_params, NotNull()); EXPECT_THAT(gcm_params->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(gcm_params->KeySizeInBytes(), Eq(test_case.key_size)); EXPECT_THAT(gcm_params->IvSizeInBytes(), Eq(test_case.iv_size)); EXPECT_THAT(gcm_params->TagSizeInBytes(), Eq(test_case.tag_size)); } TEST_F(AesGcmProtoSerializationTest, ParseParametersWithInvalidSerialization) { ASSERT_THAT(RegisterAesGcmProtoSerialization(), IsOk()); AesGcmKeyFormat key_format_proto; key_format_proto.set_version(0); key_format_proto.set_key_size(16); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.AesGcmKey", OutputPrefixType::RAW, "invalid_serialization"); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(AesGcmProtoSerializationTest, ParseParametersWithUnkownOutputPrefix) { ASSERT_THAT(RegisterAesGcmProtoSerialization(), IsOk()); AesGcmKeyFormat key_format_proto; key_format_proto.set_version(0); key_format_proto.set_key_size(16); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.AesGcmKey", OutputPrefixType::UNKNOWN_PREFIX, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(AesGcmProtoSerializationTest, ParseParametersWithInvalidVersion) { ASSERT_THAT(RegisterAesGcmProtoSerialization(), IsOk()); AesGcmKeyFormat key_format_proto; key_format_proto.set_version(1); key_format_proto.set_key_size(16); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.AesGcmKey", OutputPrefixType::RAW, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(AesGcmProtoSerializationTest, SerializeParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesGcmProtoSerialization(), IsOk()); util::StatusOr parameters = AesGcmParameters::Builder() .SetVariant(test_case.variant) .SetKeySizeInBytes(test_case.key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(test_case.tag_size) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( *parameters); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq("type.googleapis.com/google.crypto.tink.AesGcmKey")); const internal::ProtoParametersSerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->GetKeyTemplate().type_url(), Eq("type.googleapis.com/google.crypto.tink.AesGcmKey")); EXPECT_THAT(proto_serialization->GetKeyTemplate().output_prefix_type(), Eq(test_case.output_prefix_type)); AesGcmKeyFormat key_format; ASSERT_THAT( key_format.ParseFromString(proto_serialization->GetKeyTemplate().value()), IsTrue()); EXPECT_THAT(key_format.key_size(), Eq(test_case.key_size)); } TEST_F(AesGcmProtoSerializationTest, SerializeParametersWithDisallowedIvSize) { ASSERT_THAT(RegisterAesGcmProtoSerialization(), IsOk()); util::StatusOr parameters = AesGcmParameters::Builder() .SetVariant(AesGcmParameters::Variant::kNoPrefix) .SetKeySizeInBytes(16) .SetIvSizeInBytes(14) .SetTagSizeInBytes(16) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( *parameters); EXPECT_THAT(serialization.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(AesGcmProtoSerializationTest, SerializeParametersWithDisallowedTagSize) { ASSERT_THAT(RegisterAesGcmProtoSerialization(), IsOk()); util::StatusOr parameters = AesGcmParameters::Builder() .SetVariant(AesGcmParameters::Variant::kNoPrefix) .SetKeySizeInBytes(16) .SetIvSizeInBytes(12) .SetTagSizeInBytes(14) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( *parameters); EXPECT_THAT(serialization.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(AesGcmProtoSerializationTest, ParseKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesGcmProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(test_case.key_size); google::crypto::tink::AesGcmKey key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesGcmKey", serialized_key, KeyData::SYMMETRIC, test_case.output_prefix_type, test_case.id); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); EXPECT_THAT((*key)->GetIdRequirement(), Eq(test_case.id)); EXPECT_THAT((*key)->GetParameters().HasIdRequirement(), test_case.id.has_value()); util::StatusOr expected_parameters = AesGcmParameters::Builder() .SetVariant(test_case.variant) .SetKeySizeInBytes(test_case.key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(test_case.tag_size) .Build(); ASSERT_THAT(expected_parameters, IsOk()); util::StatusOr expected_key = AesGcmKey::Create( *expected_parameters, RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(expected_key, IsOk()); EXPECT_THAT(**key, Eq(*expected_key)); } TEST_F(AesGcmProtoSerializationTest, ParseLegacyKeyAsCrunchy) { ASSERT_THAT(RegisterAesGcmProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); google::crypto::tink::AesGcmKey key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesGcmKey", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::LEGACY, /*id_requirement=*/123); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); const AesGcmKey* aes_gcm_key = dynamic_cast(key->get()); ASSERT_THAT(aes_gcm_key, NotNull()); EXPECT_THAT(aes_gcm_key->GetParameters().GetVariant(), Eq(AesGcmParameters::Variant::kCrunchy)); } TEST_F(AesGcmProtoSerializationTest, ParseKeyWithInvalidSerialization) { ASSERT_THAT(RegisterAesGcmProtoSerialization(), IsOk()); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesGcmKey", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(AesGcmProtoSerializationTest, ParseKeyNoSecretKeyAccess) { ASSERT_THAT(RegisterAesGcmProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(16); google::crypto::tink::AesGcmKey key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesGcmKey", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(AesGcmProtoSerializationTest, ParseKeyWithInvalidVersion) { ASSERT_THAT(RegisterAesGcmProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(16); google::crypto::tink::AesGcmKey key_proto; key_proto.set_version(1); // Invalid version number. key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesGcmKey", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(AesGcmProtoSerializationTest, SerializeKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesGcmProtoSerialization(), IsOk()); util::StatusOr parameters = AesGcmParameters::Builder() .SetVariant(test_case.variant) .SetKeySizeInBytes(test_case.key_size) .SetIvSizeInBytes(test_case.iv_size) .SetTagSizeInBytes(test_case.tag_size) .Build(); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(test_case.key_size); util::StatusOr key = AesGcmKey::Create( *parameters, RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq("type.googleapis.com/google.crypto.tink.AesGcmKey")); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq("type.googleapis.com/google.crypto.tink.AesGcmKey")); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::SYMMETRIC)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id)); google::crypto::tink::AesGcmKey proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.key_value().size(), Eq(test_case.key_size)); } TEST_F(AesGcmProtoSerializationTest, SerializeKeyWithDisallowedIvSize) { ASSERT_THAT(RegisterAesGcmProtoSerialization(), IsOk()); util::StatusOr parameters = AesGcmParameters::Builder() .SetVariant(AesGcmParameters::Variant::kNoPrefix) .SetKeySizeInBytes(32) .SetIvSizeInBytes(14) .SetTagSizeInBytes(16) .Build(); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); util::StatusOr key = AesGcmKey::Create( *parameters, RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); EXPECT_THAT(serialization.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(AesGcmProtoSerializationTest, SerializeKeyWithDisallowedTagSize) { ASSERT_THAT(RegisterAesGcmProtoSerialization(), IsOk()); util::StatusOr parameters = AesGcmParameters::Builder() .SetVariant(AesGcmParameters::Variant::kNoPrefix) .SetKeySizeInBytes(32) .SetIvSizeInBytes(12) .SetTagSizeInBytes(14) .Build(); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); util::StatusOr key = AesGcmKey::Create( *parameters, RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); EXPECT_THAT(serialization.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(AesGcmProtoSerializationTest, SerializeKeyNoSecretKeyAccess) { ASSERT_THAT(RegisterAesGcmProtoSerialization(), IsOk()); util::StatusOr parameters = AesGcmParameters::Builder() .SetVariant(AesGcmParameters::Variant::kNoPrefix) .SetKeySizeInBytes(16) .SetIvSizeInBytes(12) .SetTagSizeInBytes(16) .Build(); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(16); util::StatusOr key = AesGcmKey::Create( *parameters, RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey(*key, absl::nullopt); EXPECT_THAT(serialization.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_gcm_siv_key.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_gcm_siv_key.h" #include #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/escaping.h" #include "absl/types/optional.h" #include "tink/aead/aes_gcm_siv_parameters.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { util::StatusOr ComputeOutputPrefix( const AesGcmSivParameters& parameters, absl::optional id_requirement) { switch (parameters.GetVariant()) { case AesGcmSivParameters::Variant::kNoPrefix: return std::string(""); // Empty prefix. case AesGcmSivParameters::Variant::kCrunchy: if (!id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "id requirement must have value with kCrunchy or kLegacy"); } return absl::StrCat(absl::HexStringToBytes("00"), subtle::BigEndian32(*id_requirement)); case AesGcmSivParameters::Variant::kTink: if (!id_requirement.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "id requirement must have value with kTink"); } return absl::StrCat(absl::HexStringToBytes("01"), subtle::BigEndian32(*id_requirement)); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid variant: ", parameters.GetVariant())); } } } // namespace util::StatusOr AesGcmSivKey::Create( const AesGcmSivParameters& parameters, const RestrictedData& key_bytes, absl::optional id_requirement, PartialKeyAccessToken token) { if (parameters.KeySizeInBytes() != key_bytes.size()) { return util::Status(absl::StatusCode::kInvalidArgument, "Key size does not match AES-GCM parameters"); } if (parameters.HasIdRequirement() && !id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key without ID requirement with parameters with ID " "requirement"); } if (!parameters.HasIdRequirement() && id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key with ID requirement with parameters without ID " "requirement"); } util::StatusOr output_prefix = ComputeOutputPrefix(parameters, id_requirement); if (!output_prefix.ok()) { return output_prefix.status(); } return AesGcmSivKey(parameters, key_bytes, id_requirement, *std::move(output_prefix)); } bool AesGcmSivKey::operator==(const Key& other) const { const AesGcmSivKey* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (GetParameters() != that->GetParameters()) { return false; } if (id_requirement_ != that->id_requirement_) { return false; } return key_bytes_ == that->key_bytes_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_gcm_siv_key.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_AES_GCM_SIV_KEY_H_ #define TINK_AEAD_AES_GCM_SIV_KEY_H_ #include #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/aead/aead_key.h" #include "tink/aead/aes_gcm_siv_parameters.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Represents an AEAD that uses AES-GCM-SIV. class AesGcmSivKey : public AeadKey { public: // Copyable and movable. AesGcmSivKey(const AesGcmSivKey& other) = default; AesGcmSivKey& operator=(const AesGcmSivKey& other) = default; AesGcmSivKey(AesGcmSivKey&& other) = default; AesGcmSivKey& operator=(AesGcmSivKey&& other) = default; // Creates a new AES-GCM-SIV key. If the parameters specify a variant // that uses a prefix, then the id is used to compute this prefix. static util::StatusOr Create( const AesGcmSivParameters& parameters, const RestrictedData& key_bytes, absl::optional id_requirement, PartialKeyAccessToken token); // Returns the underlying AES key. const RestrictedData& GetKeyBytes(PartialKeyAccessToken token) const { return key_bytes_; } absl::string_view GetOutputPrefix() const override { return output_prefix_; } const AesGcmSivParameters& GetParameters() const override { return parameters_; } absl::optional GetIdRequirement() const override { return id_requirement_; } bool operator==(const Key& other) const override; private: AesGcmSivKey(const AesGcmSivParameters& parameters, const RestrictedData& key_bytes, absl::optional id_requirement, std::string output_prefix) : parameters_(parameters), key_bytes_(key_bytes), id_requirement_(id_requirement), output_prefix_(std::move(output_prefix)) {} AesGcmSivParameters parameters_; RestrictedData key_bytes_; absl::optional id_requirement_; std::string output_prefix_; }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_AES_GCM_SIV_KEY_H_ ================================================ FILE: cc/aead/aes_gcm_siv_key_manager.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_AES_GCM_SIV_KEY_MANAGER_H_ #define TINK_AEAD_AES_GCM_SIV_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/aead.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/subtle/aes_gcm_siv_boringssl.h" #include "tink/subtle/random.h" #include "tink/util/constants.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/aes_gcm_siv.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class AesGcmSivKeyManager : public KeyTypeManager> { public: class AeadFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::AesGcmSivKey& key) const override { return subtle::AesGcmSivBoringSsl::New( util::SecretDataFromStringView(key.key_value())); } }; AesGcmSivKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::SYMMETRIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::AesGcmSivKey& key) const override { crypto::tink::util::Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; return ValidateAesKeySize(key.key_value().size()); } crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::AesGcmSivKeyFormat& format) const override { return ValidateAesKeySize(format.key_size()); } crypto::tink::util::StatusOr CreateKey( const google::crypto::tink::AesGcmSivKeyFormat& format) const override { google::crypto::tink::AesGcmSivKey key; key.set_version(get_version()); key.set_key_value(subtle::Random::GetRandomBytes(format.key_size())); return key; } private: const std::string key_type_ = absl::StrCat( kTypeGoogleapisCom, google::crypto::tink::AesGcmSivKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_AES_GCM_SIV_KEY_MANAGER_H_ ================================================ FILE: cc/aead/aes_gcm_siv_key_manager_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_gcm_siv_key_manager.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/aead.h" #include "tink/internal/ssl_util.h" #include "tink/subtle/aead_test_util.h" #include "tink/subtle/aes_gcm_siv_boringssl.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/aes_gcm_siv.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::AesGcmSivKey; using ::google::crypto::tink::AesGcmSivKeyFormat; using ::testing::Eq; using ::testing::Not; TEST(AesGcmSivKeyManagerTest, Basics) { EXPECT_THAT(AesGcmSivKeyManager().get_version(), Eq(0)); EXPECT_THAT(AesGcmSivKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.AesGcmSivKey")); EXPECT_THAT(AesGcmSivKeyManager().key_material_type(), Eq(google::crypto::tink::KeyData::SYMMETRIC)); } TEST(AesGcmSivKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(AesGcmSivKeyManager().ValidateKey(AesGcmSivKey()), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmSivKeyManagerTest, ValidateValid16ByteKey) { AesGcmSivKey key; key.set_version(0); key.set_key_value("0123456789abcdef"); EXPECT_THAT(AesGcmSivKeyManager().ValidateKey(key), IsOk()); } TEST(AesGcmSivKeyManagerTest, ValidateValid32ByteKey) { AesGcmSivKey key; key.set_version(0); key.set_key_value("01234567890123456789012345678901"); EXPECT_THAT(AesGcmSivKeyManager().ValidateKey(key), IsOk()); } TEST(AesGcmSivKeyManagerTest, InvalidKeySizes17Bytes) { AesGcmSivKey key; key.set_version(0); key.set_key_value("0123456789abcdefg"); EXPECT_THAT(AesGcmSivKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmSivKeyManagerTest, InvalidKeySizes24Bytes) { AesGcmSivKey key; key.set_version(0); key.set_key_value("01234567890123"); EXPECT_THAT(AesGcmSivKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmSivKeyManagerTest, InvalidKeySizes31Bytes) { AesGcmSivKey key; key.set_version(0); key.set_key_value("0123456789012345678901234567890"); EXPECT_THAT(AesGcmSivKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmSivKeyManagerTest, InvalidKeySizes33Bytes) { AesGcmSivKey key; key.set_version(0); key.set_key_value("012345678901234567890123456789012"); EXPECT_THAT(AesGcmSivKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmSivKeyManagerTest, ValidateKeyFormat) { AesGcmSivKeyFormat format; format.set_key_size(0); EXPECT_THAT(AesGcmSivKeyManager().ValidateKeyFormat(format), StatusIs(absl::StatusCode::kInvalidArgument)); format.set_key_size(1); EXPECT_THAT(AesGcmSivKeyManager().ValidateKeyFormat(format), StatusIs(absl::StatusCode::kInvalidArgument)); format.set_key_size(15); EXPECT_THAT(AesGcmSivKeyManager().ValidateKeyFormat(format), StatusIs(absl::StatusCode::kInvalidArgument)); format.set_key_size(16); EXPECT_THAT(AesGcmSivKeyManager().ValidateKeyFormat(format), IsOk()); format.set_key_size(17); EXPECT_THAT(AesGcmSivKeyManager().ValidateKeyFormat(format), StatusIs(absl::StatusCode::kInvalidArgument)); format.set_key_size(31); EXPECT_THAT(AesGcmSivKeyManager().ValidateKeyFormat(format), StatusIs(absl::StatusCode::kInvalidArgument)); format.set_key_size(32); EXPECT_THAT(AesGcmSivKeyManager().ValidateKeyFormat(format), IsOk()); format.set_key_size(33); EXPECT_THAT(AesGcmSivKeyManager().ValidateKeyFormat(format), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmSivKeyManagerTest, Create16ByteKey) { AesGcmSivKeyFormat format; format.set_key_size(16); StatusOr key_or = AesGcmSivKeyManager().CreateKey(format); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().key_value().size(), Eq(format.key_size())); } TEST(AesGcmSivKeyManagerTest, Create32ByteKey) { AesGcmSivKeyFormat format; format.set_key_size(32); StatusOr key_or = AesGcmSivKeyManager().CreateKey(format); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().key_value().size(), Eq(format.key_size())); } TEST(AesGcmSivKeyManagerTest, CreateAeadFailsWithOpenSsl) { if (internal::IsBoringSsl()) { GTEST_SKIP() << "OpenSSL-only test, skipping because Tink uses BoringSSL"; } AesGcmSivKeyFormat format; format.set_key_size(32); StatusOr key = AesGcmSivKeyManager().CreateKey(format); ASSERT_THAT(key, IsOk()); EXPECT_THAT(AesGcmSivKeyManager().GetPrimitive(*key).status(), Not(IsOk())); EXPECT_THAT(subtle::AesGcmSivBoringSsl::New( util::SecretDataFromStringView(key->key_value())) .status(), Not(IsOk())); } TEST(AesGcmSivKeyManagerTest, CreateAeadSucceedsWithBoringSsl) { if (!internal::IsBoringSsl()) { GTEST_SKIP() << "AES-GCM-SIV is not supported when OpenSSL is used"; } AesGcmSivKeyFormat format; format.set_key_size(32); StatusOr key = AesGcmSivKeyManager().CreateKey(format); ASSERT_THAT(key, IsOk()); StatusOr> aead = AesGcmSivKeyManager().GetPrimitive(*key); ASSERT_THAT(aead, IsOk()); StatusOr> boring_ssl_aead = subtle::AesGcmSivBoringSsl::New( util::SecretDataFromStringView(key->key_value())); ASSERT_THAT(boring_ssl_aead, IsOk()); EXPECT_THAT(EncryptThenDecrypt(**aead, **boring_ssl_aead, "message", "aad"), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_gcm_siv_key_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_gcm_siv_key.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/aead/aes_gcm_siv_parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Combine; using ::testing::Eq; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { AesGcmSivParameters::Variant variant; absl::optional id_requirement; std::string output_prefix; }; using AesGcmSivKeyTest = TestWithParam>; INSTANTIATE_TEST_SUITE_P( AesGcmSivKeyTestSuite, AesGcmSivKeyTest, Combine(Values(16, 32), Values(TestCase{AesGcmSivParameters::Variant::kTink, 0x02030400, std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{AesGcmSivParameters::Variant::kCrunchy, 0x01030005, std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{AesGcmSivParameters::Variant::kNoPrefix, absl::nullopt, ""}))); TEST_P(AesGcmSivKeyTest, CreateSucceeds) { int key_size; TestCase test_case; std::tie(key_size, test_case) = GetParam(); util::StatusOr params = AesGcmSivParameters::Create(key_size, test_case.variant); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(key_size); util::StatusOr key = AesGcmSivKey::Create( *params, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); EXPECT_THAT(key->GetParameters(), Eq(*params)); EXPECT_THAT(key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(key->GetOutputPrefix(), Eq(test_case.output_prefix)); } TEST(AesGcmSivKeyTest, CreateKeyWithMismatchedKeySizeFails) { // Key size parameter is 32 bytes. util::StatusOr params = AesGcmSivParameters::Create( /*key_size_in_bytes=*/32, AesGcmSivParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); // Key material is 16 bytes (another valid key length). RestrictedData mismatched_secret = RestrictedData(/*num_random_bytes=*/16); EXPECT_THAT( AesGcmSivKey::Create(*params, mismatched_secret, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmSivKeyTest, CreateKeyWithInvalidIdRequirementFails) { util::StatusOr no_prefix_params = AesGcmSivParameters::Create(/*key_size_in_bytes=*/32, AesGcmSivParameters::Variant::kNoPrefix); ASSERT_THAT(no_prefix_params, IsOk()); util::StatusOr tink_params = AesGcmSivParameters::Create( /*key_size_in_bytes=*/32, AesGcmSivParameters::Variant::kTink); ASSERT_THAT(tink_params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); EXPECT_THAT( AesGcmSivKey::Create(*no_prefix_params, secret, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesGcmSivKey::Create(*tink_params, secret, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(AesGcmSivKeyTest, GetKeyBytes) { int key_size; TestCase test_case; std::tie(key_size, test_case) = GetParam(); util::StatusOr params = AesGcmSivParameters::Create(key_size, test_case.variant); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(key_size); util::StatusOr key = AesGcmSivKey::Create( *params, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); EXPECT_THAT(key->GetKeyBytes(GetPartialKeyAccess()), Eq(secret)); } TEST_P(AesGcmSivKeyTest, KeyEquals) { int key_size; TestCase test_case; std::tie(key_size, test_case) = GetParam(); util::StatusOr params = AesGcmSivParameters::Create(key_size, test_case.variant); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(key_size); util::StatusOr key = AesGcmSivKey::Create( *params, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = AesGcmSivKey::Create( *params, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key == *other_key); EXPECT_TRUE(*other_key == *key); EXPECT_FALSE(*key != *other_key); EXPECT_FALSE(*other_key != *key); } TEST(AesGcmSivKeyTest, DifferentVariantNotEqual) { util::StatusOr crunchy_params = AesGcmSivParameters::Create(/*key_size_in_bytes=*/32, AesGcmSivParameters::Variant::kCrunchy); ASSERT_THAT(crunchy_params, IsOk()); util::StatusOr tink_params = AesGcmSivParameters::Create( /*key_size_in_bytes=*/32, AesGcmSivParameters::Variant::kTink); ASSERT_THAT(tink_params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = AesGcmSivKey::Create( *crunchy_params, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = AesGcmSivKey::Create(*tink_params, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST(AesGcmSivKeyTest, DifferentSecretDataNotEqual) { util::StatusOr params = AesGcmSivParameters::Create( /*key_size_in_bytes=*/32, AesGcmSivParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); RestrictedData secret1 = RestrictedData(/*num_random_bytes=*/32); RestrictedData secret2 = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = AesGcmSivKey::Create( *params, secret1, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = AesGcmSivKey::Create( *params, secret2, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST(AesGcmSivKeyTest, DifferentIdRequirementNotEqual) { util::StatusOr params = AesGcmSivParameters::Create( /*key_size_in_bytes=*/32, AesGcmSivParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = AesGcmSivKey::Create( *params, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = AesGcmSivKey::Create( *params, secret, /*id_requirement=*/0x02030405, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_gcm_siv_parameters.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_gcm_siv_parameters.h" #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/parameters.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { util::StatusOr AesGcmSivParameters::Create( int key_size_in_bytes, Variant variant) { // AES-GCM-SIV key sizes specified in // https://www.rfc-editor.org/rfc/rfc8452.html#section-6. if (key_size_in_bytes != 16 && key_size_in_bytes != 32) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Key size should be either 16 or 32 bytes, got ", key_size_in_bytes, " bytes.")); } static const std::set* supported_variants = new std::set( {Variant::kTink, Variant::kCrunchy, Variant::kNoPrefix}); if (supported_variants->find(variant) == supported_variants->end()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create AES-GCM-SIV parameters with unknown variant."); } return AesGcmSivParameters(key_size_in_bytes, variant); } bool AesGcmSivParameters::operator==(const Parameters& other) const { const AesGcmSivParameters* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (key_size_in_bytes_ != that->key_size_in_bytes_) { return false; } if (variant_ != that->variant_) { return false; } return true; } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_gcm_siv_parameters.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_AES_GCM_SIV_PARAMETERS_H_ #define TINK_AEAD_AES_GCM_SIV_PARAMETERS_H_ #include "tink/aead/aead_parameters.h" #include "tink/parameters.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Describes the parameters of an `AesGcmSivKey`. class AesGcmSivParameters : public AeadParameters { public: // Description of the output prefix prepended to the ciphertext. enum class Variant : int { // Prepends '0x01' to the ciphertext. kTink = 1, // Prepends '0x00' to the ciphertext. kCrunchy = 2, // Does not prepend any prefix (i.e., keys must have no ID requirement). kNoPrefix = 3, // Added to guard from failures that may be caused by future expansions. kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Copyable and movable. AesGcmSivParameters(const AesGcmSivParameters& other) = default; AesGcmSivParameters& operator=(const AesGcmSivParameters& other) = default; AesGcmSivParameters(AesGcmSivParameters&& other) = default; AesGcmSivParameters& operator=(AesGcmSivParameters&& other) = default; // Creates a new AES-GCM-SIV parameters object. Returns an error if either // `key_size_in_bytes` or `variant` is invalid. static util::StatusOr Create(int key_size_in_bytes, Variant variant); int KeySizeInBytes() const { return key_size_in_bytes_; } Variant GetVariant() const { return variant_; } bool HasIdRequirement() const override { return variant_ != Variant::kNoPrefix; } bool operator==(const Parameters& other) const override; private: AesGcmSivParameters(int key_size_in_bytes, Variant variant) : key_size_in_bytes_(key_size_in_bytes), variant_(variant) {} int key_size_in_bytes_; Variant variant_; }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_AES_GCM_SIV_PARAMETERS_H_ ================================================ FILE: cc/aead/aes_gcm_siv_parameters_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_gcm_siv_parameters.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Combine; using ::testing::Eq; using ::testing::IsTrue; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { AesGcmSivParameters::Variant variant; int key_size; bool has_id_requirement; }; using AesGcmSivParametersCreateTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( AesGcmSivParametersCreateTestSuite, AesGcmSivParametersCreateTest, Values(TestCase{AesGcmSivParameters::Variant::kTink, /*key_size=*/16, /*has_id_requirement=*/true}, TestCase{AesGcmSivParameters::Variant::kCrunchy, /*key_size=*/32, /*has_id_requirement=*/true}, TestCase{AesGcmSivParameters::Variant::kNoPrefix, /*key_size=*/32, /*has_id_requirement=*/false})); TEST_P(AesGcmSivParametersCreateTest, Create) { TestCase test_case = GetParam(); util::StatusOr parameters = AesGcmSivParameters::Create(test_case.key_size, test_case.variant); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->KeySizeInBytes(), Eq(test_case.key_size)); EXPECT_THAT(parameters->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(parameters->HasIdRequirement(), Eq(test_case.has_id_requirement)); } TEST(AesGcmSivParametersTest, CreateWithInvalidVariantFails) { EXPECT_THAT(AesGcmSivParameters::Create( /*key_size_in_bytes=*/32, AesGcmSivParameters::Variant:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmSivParametersTest, CreateWithInvalidKeySizeFails) { EXPECT_THAT( AesGcmSivParameters::Create(/*key_size_in_bytes=*/15, AesGcmSivParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT( AesGcmSivParameters::Create(/*key_size_in_bytes=*/17, AesGcmSivParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT( AesGcmSivParameters::Create(/*key_size_in_bytes=*/31, AesGcmSivParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT( AesGcmSivParameters::Create(/*key_size_in_bytes=*/33, AesGcmSivParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmParametersTest, CopyConstructor) { util::StatusOr parameters = AesGcmSivParameters::Create( /*key_size_in_bytes=*/16, AesGcmSivParameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); AesGcmSivParameters copy(*parameters); EXPECT_THAT(copy.KeySizeInBytes(), Eq(16)); EXPECT_THAT(copy.GetVariant(), Eq(AesGcmSivParameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); } TEST(AesGcmParametersTest, CopyAssignment) { util::StatusOr parameters = AesGcmSivParameters::Create( /*key_size_in_bytes=*/32, AesGcmSivParameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); AesGcmSivParameters copy = *parameters; EXPECT_THAT(copy.KeySizeInBytes(), Eq(32)); EXPECT_THAT(copy.GetVariant(), Eq(AesGcmSivParameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); } using AesGcmSivParametersVariantTest = TestWithParam>; INSTANTIATE_TEST_SUITE_P( AesGcmSivParametersVariantTestSuite, AesGcmSivParametersVariantTest, Combine(Values(16, 32), Values(AesGcmSivParameters::Variant::kTink, AesGcmSivParameters::Variant::kCrunchy, AesGcmSivParameters::Variant::kNoPrefix))); TEST_P(AesGcmSivParametersVariantTest, ParametersEquals) { int key_size; AesGcmSivParameters::Variant variant; std::tie(key_size, variant) = GetParam(); util::StatusOr parameters = AesGcmSivParameters::Create(key_size, variant); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesGcmSivParameters::Create(key_size, variant); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters == *other_parameters); EXPECT_TRUE(*other_parameters == *parameters); EXPECT_FALSE(*parameters != *other_parameters); EXPECT_FALSE(*other_parameters != *parameters); } TEST(AesGcmParametersTest, KeySizeNotEqual) { util::StatusOr parameters = AesGcmSivParameters::Create( /*key_size_in_bytes=*/16, AesGcmSivParameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesGcmSivParameters::Create(/*key_size_in_bytes=*/32, AesGcmSivParameters::Variant::kTink); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(AesGcmParametersTest, VariantNotEqual) { util::StatusOr parameters = AesGcmSivParameters::Create( /*key_size_in_bytes=*/32, AesGcmSivParameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesGcmSivParameters::Create(/*key_size_in_bytes=*/32, AesGcmSivParameters::Variant::kNoPrefix); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_gcm_siv_proto_serialization.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_gcm_siv_proto_serialization.h" #include #include "absl/base/attributes.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/aead/aes_gcm_siv_key.h" #include "tink/aead/aes_gcm_siv_parameters.h" #include "tink/internal/key_parser.h" #include "tink/internal/key_serializer.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/parameters_parser.h" #include "tink/internal/parameters_serializer.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/secret_key_access_token.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/aes_gcm_siv.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::google::crypto::tink::AesGcmSivKeyFormat; using ::google::crypto::tink::OutputPrefixType; using AesGcmSivProtoParametersParserImpl = internal::ParametersParserImpl; using AesGcmSivProtoParametersSerializerImpl = internal::ParametersSerializerImpl; using AesGcmSivProtoKeyParserImpl = internal::KeyParserImpl; using AesGcmSivProtoKeySerializerImpl = internal::KeySerializerImpl; const absl::string_view kTypeUrl = "type.googleapis.com/google.crypto.tink.AesGcmSivKey"; util::StatusOr ToVariant( OutputPrefixType output_prefix_type) { switch (output_prefix_type) { case OutputPrefixType::LEGACY: ABSL_FALLTHROUGH_INTENDED; // Parse LEGACY output prefix as CRUNCHY. case OutputPrefixType::CRUNCHY: return AesGcmSivParameters::Variant::kCrunchy; case OutputPrefixType::RAW: return AesGcmSivParameters::Variant::kNoPrefix; case OutputPrefixType::TINK: return AesGcmSivParameters::Variant::kTink; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine AesGcmSivParameters::Variant"); } } util::StatusOr ToOutputPrefixType( AesGcmSivParameters::Variant variant) { switch (variant) { case AesGcmSivParameters::Variant::kCrunchy: return OutputPrefixType::CRUNCHY; case AesGcmSivParameters::Variant::kNoPrefix: return OutputPrefixType::RAW; case AesGcmSivParameters::Variant::kTink: return OutputPrefixType::TINK; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine output prefix type"); } } util::StatusOr ParseParameters( const internal::ProtoParametersSerialization& serialization) { if (serialization.GetKeyTemplate().type_url() != kTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing AesGcmSivParameters."); } AesGcmSivKeyFormat proto_key_format; if (!proto_key_format.ParseFromString( serialization.GetKeyTemplate().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse AesGcmSivKeyFormat proto"); } if (proto_key_format.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } util::StatusOr variant = ToVariant(serialization.GetKeyTemplate().output_prefix_type()); if (!variant.ok()) { return variant.status(); } return AesGcmSivParameters::Create(proto_key_format.key_size(), *variant); } util::StatusOr SerializeParameters( const AesGcmSivParameters& parameters) { util::StatusOr output_prefix_type = ToOutputPrefixType(parameters.GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } AesGcmSivKeyFormat proto_key_format; proto_key_format.set_version(0); proto_key_format.set_key_size(parameters.KeySizeInBytes()); return internal::ProtoParametersSerialization::Create( kTypeUrl, *output_prefix_type, proto_key_format.SerializeAsString()); } util::StatusOr ParseKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (!token.has_value()) { return util::Status(absl::StatusCode::kPermissionDenied, "SecretKeyAccess is required"); } if (serialization.TypeUrl() != kTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing AesGcmSivKey."); } google::crypto::tink::AesGcmSivKey proto_key; const RestrictedData& restricted_data = serialization.SerializedKeyProto(); if (!proto_key.ParseFromString(restricted_data.GetSecret(*token))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse AesGcmSivKey proto"); } if (proto_key.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } util::StatusOr variant = ToVariant(serialization.GetOutputPrefixType()); if (!variant.ok()) { return variant.status(); } util::StatusOr parameters = AesGcmSivParameters::Create(proto_key.key_value().length(), *variant); if (!parameters.ok()) { return parameters.status(); } return AesGcmSivKey::Create( *parameters, RestrictedData(proto_key.key_value(), *token), serialization.IdRequirement(), GetPartialKeyAccess()); } util::StatusOr SerializeKey( const AesGcmSivKey& key, absl::optional token) { if (!token.has_value()) { return util::Status(absl::StatusCode::kPermissionDenied, "SecretKeyAccess is required"); } util::StatusOr restricted_input = key.GetKeyBytes(GetPartialKeyAccess()); if (!restricted_input.ok()) { return restricted_input.status(); } google::crypto::tink::AesGcmSivKey proto_key; proto_key.set_version(0); // OSS proto library complains if input is not converted to a string. proto_key.set_key_value(std::string(restricted_input->GetSecret(*token))); util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetParameters().GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } RestrictedData restricted_output = RestrictedData(proto_key.SerializeAsString(), *token); return internal::ProtoKeySerialization::Create( kTypeUrl, restricted_output, google::crypto::tink::KeyData::SYMMETRIC, *output_prefix_type, key.GetIdRequirement()); } AesGcmSivProtoParametersParserImpl* AesGcmSivProtoParametersParser() { static auto* parser = new AesGcmSivProtoParametersParserImpl(kTypeUrl, ParseParameters); return parser; } AesGcmSivProtoParametersSerializerImpl* AesGcmSivProtoParametersSerializer() { static auto* serializer = new AesGcmSivProtoParametersSerializerImpl(kTypeUrl, SerializeParameters); return serializer; } AesGcmSivProtoKeyParserImpl* AesGcmSivProtoKeyParser() { static auto* parser = new AesGcmSivProtoKeyParserImpl(kTypeUrl, ParseKey); return parser; } AesGcmSivProtoKeySerializerImpl* AesGcmSivProtoKeySerializer() { static auto* serializer = new AesGcmSivProtoKeySerializerImpl(SerializeKey); return serializer; } } // namespace util::Status RegisterAesGcmSivProtoSerialization() { util::Status status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersParser(AesGcmSivProtoParametersParser()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersSerializer(AesGcmSivProtoParametersSerializer()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(AesGcmSivProtoKeyParser()); if (!status.ok()) { return status; } return internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(AesGcmSivProtoKeySerializer()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/aes_gcm_siv_proto_serialization.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_AES_GCM_SIV_PROTO_SERIALIZATION_H_ #define TINK_AEAD_AES_GCM_SIV_PROTO_SERIALIZATION_H_ #include "tink/util/status.h" namespace crypto { namespace tink { // Registers proto parsers and serializers for AES-GCM-SIV parameters and keys. crypto::tink::util::Status RegisterAesGcmSivProtoSerialization(); } // namespace tink } // namespace crypto #endif // TINK_AEAD_AES_GCM_SIV_PROTO_SERIALIZATION_H_ ================================================ FILE: cc/aead/aes_gcm_siv_proto_serialization_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/aes_gcm_siv_proto_serialization.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/aead/aes_gcm_siv_key.h" #include "tink/aead/aes_gcm_siv_parameters.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/subtle/random.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/aes_gcm_siv.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::subtle::Random; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::AesGcmSivKeyFormat; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::IsTrue; using ::testing::NotNull; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { AesGcmSivParameters::Variant variant; OutputPrefixType output_prefix_type; int key_size; absl::optional id; std::string output_prefix; }; class AesGcmSivProtoSerializationTest : public TestWithParam { protected: void SetUp() override { internal::MutableSerializationRegistry::GlobalInstance().Reset(); } }; TEST_F(AesGcmSivProtoSerializationTest, RegisterTwiceSucceeds) { ASSERT_THAT(RegisterAesGcmSivProtoSerialization(), IsOk()); ASSERT_THAT(RegisterAesGcmSivProtoSerialization(), IsOk()); } INSTANTIATE_TEST_SUITE_P( AesGcmSivProtoSerializationTestSuite, AesGcmSivProtoSerializationTest, Values( TestCase{AesGcmSivParameters::Variant::kTink, OutputPrefixType::TINK, /*key_size=*/16, /*id=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{AesGcmSivParameters::Variant::kCrunchy, OutputPrefixType::CRUNCHY, /*key_size=*/16, /*id=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{AesGcmSivParameters::Variant::kNoPrefix, OutputPrefixType::RAW, /*key_size=*/32, /*id=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(AesGcmSivProtoSerializationTest, ParseParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesGcmSivProtoSerialization(), IsOk()); AesGcmSivKeyFormat key_format_proto; key_format_proto.set_version(0); key_format_proto.set_key_size(test_case.key_size); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.AesGcmSivKey", test_case.output_prefix_type, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(params, IsOk()); EXPECT_THAT((*params)->HasIdRequirement(), test_case.id.has_value()); const AesGcmSivParameters* gcm_siv_params = dynamic_cast(params->get()); ASSERT_THAT(gcm_siv_params, NotNull()); EXPECT_THAT(gcm_siv_params->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(gcm_siv_params->KeySizeInBytes(), Eq(test_case.key_size)); } TEST_F(AesGcmSivProtoSerializationTest, ParseParametersWithInvalidSerialization) { ASSERT_THAT(RegisterAesGcmSivProtoSerialization(), IsOk()); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.AesGcmSivKey", OutputPrefixType::RAW, "invalid_serialization"); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(AesGcmSivProtoSerializationTest, ParseParametersWithUnkownOutputPrefix) { ASSERT_THAT(RegisterAesGcmSivProtoSerialization(), IsOk()); AesGcmSivKeyFormat key_format_proto; key_format_proto.set_version(0); key_format_proto.set_key_size(16); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.AesGcmSivKey", OutputPrefixType::UNKNOWN_PREFIX, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(AesGcmSivProtoSerializationTest, ParseParametersWithInvalidVersion) { ASSERT_THAT(RegisterAesGcmSivProtoSerialization(), IsOk()); AesGcmSivKeyFormat key_format_proto; key_format_proto.set_version(1); key_format_proto.set_key_size(16); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.AesGcmSivKey", OutputPrefixType::RAW, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(AesGcmSivProtoSerializationTest, SerializeParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesGcmSivProtoSerialization(), IsOk()); util::StatusOr parameters = AesGcmSivParameters::Create(test_case.key_size, test_case.variant); ASSERT_THAT(parameters, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( *parameters); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq("type.googleapis.com/google.crypto.tink.AesGcmSivKey")); const internal::ProtoParametersSerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->GetKeyTemplate().type_url(), Eq("type.googleapis.com/google.crypto.tink.AesGcmSivKey")); EXPECT_THAT(proto_serialization->GetKeyTemplate().output_prefix_type(), Eq(test_case.output_prefix_type)); AesGcmSivKeyFormat key_format; ASSERT_THAT( key_format.ParseFromString(proto_serialization->GetKeyTemplate().value()), IsTrue()); EXPECT_THAT(key_format.key_size(), Eq(test_case.key_size)); } TEST_P(AesGcmSivProtoSerializationTest, ParseKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesGcmSivProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(test_case.key_size); google::crypto::tink::AesGcmSivKey key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesGcmSivKey", serialized_key, KeyData::SYMMETRIC, test_case.output_prefix_type, test_case.id); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); EXPECT_THAT((*key)->GetIdRequirement(), Eq(test_case.id)); EXPECT_THAT((*key)->GetParameters().HasIdRequirement(), test_case.id.has_value()); util::StatusOr expected_parameters = AesGcmSivParameters::Create(test_case.key_size, test_case.variant); ASSERT_THAT(expected_parameters, IsOk()); util::StatusOr expected_key = AesGcmSivKey::Create( *expected_parameters, RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(expected_key, IsOk()); EXPECT_THAT(**key, Eq(*expected_key)); } TEST_F(AesGcmSivProtoSerializationTest, ParseLegacyKeyAsCrunchy) { ASSERT_THAT(RegisterAesGcmSivProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); google::crypto::tink::AesGcmSivKey key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesGcmSivKey", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::LEGACY, /*id_requirement=*/123); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); const AesGcmSivKey* aes_gcm_siv_key = dynamic_cast(key->get()); ASSERT_THAT(aes_gcm_siv_key, NotNull()); EXPECT_THAT(aes_gcm_siv_key->GetParameters().GetVariant(), Eq(AesGcmSivParameters::Variant::kCrunchy)); } TEST_F(AesGcmSivProtoSerializationTest, ParseKeyWithInvalidSerialization) { ASSERT_THAT(RegisterAesGcmSivProtoSerialization(), IsOk()); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesGcmSivKey", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(AesGcmSivProtoSerializationTest, ParseKeyNoSecretKeyAccess) { ASSERT_THAT(RegisterAesGcmSivProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(16); google::crypto::tink::AesGcmSivKey key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesGcmSivKey", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kPermissionDenied)); } TEST_F(AesGcmSivProtoSerializationTest, ParseKeyWithInvalidVersion) { ASSERT_THAT(RegisterAesGcmSivProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(16); google::crypto::tink::AesGcmSivKey key_proto; key_proto.set_version(1); // Invalid version number. key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesGcmSivKey", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(AesGcmSivProtoSerializationTest, SerializeKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesGcmSivProtoSerialization(), IsOk()); util::StatusOr parameters = AesGcmSivParameters::Create(test_case.key_size, test_case.variant); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(test_case.key_size); util::StatusOr key = AesGcmSivKey::Create( *parameters, RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq("type.googleapis.com/google.crypto.tink.AesGcmSivKey")); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq("type.googleapis.com/google.crypto.tink.AesGcmSivKey")); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::SYMMETRIC)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id)); google::crypto::tink::AesGcmSivKey proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.key_value().size(), Eq(test_case.key_size)); } TEST_F(AesGcmSivProtoSerializationTest, SerializeKeyNoSecretKeyAccess) { ASSERT_THAT(RegisterAesGcmSivProtoSerialization(), IsOk()); util::StatusOr parameters = AesGcmSivParameters::Create( /*key_size_in_bytes=*/16, AesGcmSivParameters::Variant::kNoPrefix); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(16); util::StatusOr key = AesGcmSivKey::Create( *parameters, RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, /*token=*/absl::nullopt); EXPECT_THAT(serialization.status(), StatusIs(absl::StatusCode::kPermissionDenied)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/chacha20_poly1305_key.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/chacha20_poly1305_key.h" #include #include #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/types/optional.h" #include "tink/aead/chacha20_poly1305_parameters.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { util::StatusOr ComputeOutputPrefix( ChaCha20Poly1305Parameters::Variant variant, absl::optional id_requirement) { switch (variant) { case ChaCha20Poly1305Parameters::Variant::kNoPrefix: return std::string(""); // Empty prefix. case ChaCha20Poly1305Parameters::Variant::kCrunchy: if (!id_requirement.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "id requirement must have value with kCrunchy"); } return absl::StrCat(absl::HexStringToBytes("00"), subtle::BigEndian32(*id_requirement)); case ChaCha20Poly1305Parameters::Variant::kTink: if (!id_requirement.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "id requirement must have value with kTink"); } return absl::StrCat(absl::HexStringToBytes("01"), subtle::BigEndian32(*id_requirement)); default: return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid variant: ", variant)); } } } // namespace util::StatusOr ChaCha20Poly1305Key::Create( ChaCha20Poly1305Parameters::Variant variant, const RestrictedData& key_bytes, absl::optional id_requirement, PartialKeyAccessToken token) { if (key_bytes.size() != 32) { return util::Status(absl::StatusCode::kInvalidArgument, "ChaCha20-Poly1305 key length must be 32 bytes"); } if (variant != ChaCha20Poly1305Parameters::Variant::kNoPrefix && !id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key without ID requirement with variant with ID " "requirement"); } if (variant == ChaCha20Poly1305Parameters::Variant::kNoPrefix && id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key with ID requirement with variant without ID " "requirement"); } util::StatusOr parameters = ChaCha20Poly1305Parameters::Create(variant); if (!parameters.ok()) { return parameters.status(); } util::StatusOr output_prefix = ComputeOutputPrefix(variant, id_requirement); if (!output_prefix.ok()) { return output_prefix.status(); } return ChaCha20Poly1305Key(*parameters, key_bytes, id_requirement, *std::move(output_prefix)); } bool ChaCha20Poly1305Key::operator==(const Key& other) const { const ChaCha20Poly1305Key* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (GetParameters() != that->GetParameters()) { return false; } if (id_requirement_ != that->id_requirement_) { return false; } return key_bytes_ == that->key_bytes_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/chacha20_poly1305_key.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_CHACHA20_POLY1305_KEY_H_ #define TINK_AEAD_CHACHA20_POLY1305_KEY_H_ #include #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/aead/aead_key.h" #include "tink/aead/chacha20_poly1305_parameters.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Represents an AEAD that uses ChaCha20-Poly1305. class ChaCha20Poly1305Key : public AeadKey { public: // Copyable and movable. ChaCha20Poly1305Key(const ChaCha20Poly1305Key& other) = default; ChaCha20Poly1305Key& operator=(const ChaCha20Poly1305Key& other) = default; ChaCha20Poly1305Key(ChaCha20Poly1305Key&& other) = default; ChaCha20Poly1305Key& operator=(ChaCha20Poly1305Key&& other) = default; // Creates a new ChaCha20-Poly1305 key. If `variant` uses a prefix, then the // id is used to compute this prefix. static util::StatusOr Create( ChaCha20Poly1305Parameters::Variant variant, const RestrictedData& key_bytes, absl::optional id_requirement, PartialKeyAccessToken token); // Returns the underlying ChaCha20-Poly1305 key material. const RestrictedData& GetKeyBytes(PartialKeyAccessToken token) const { return key_bytes_; } absl::string_view GetOutputPrefix() const override { return output_prefix_; } const ChaCha20Poly1305Parameters& GetParameters() const override { return parameters_; } absl::optional GetIdRequirement() const override { return id_requirement_; } bool operator==(const Key& other) const override; private: ChaCha20Poly1305Key(const ChaCha20Poly1305Parameters& parameters, const RestrictedData& key_bytes, absl::optional id_requirement, std::string output_prefix) : parameters_(parameters), key_bytes_(key_bytes), id_requirement_(id_requirement), output_prefix_(std::move(output_prefix)) {} ChaCha20Poly1305Parameters parameters_; RestrictedData key_bytes_; absl::optional id_requirement_; std::string output_prefix_; }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_CHACHA20_POLY1305_KEY_H_ ================================================ FILE: cc/aead/chacha20_poly1305_key_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/chacha20_poly1305_key.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/aead/chacha20_poly1305_parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { ChaCha20Poly1305Parameters::Variant variant; absl::optional id_requirement; std::string output_prefix; }; using ChaCha20Poly1305KeyTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( ChaCha20Poly1305KeyTestSuite, ChaCha20Poly1305KeyTest, Values(TestCase{ChaCha20Poly1305Parameters::Variant::kTink, 0x02030400, std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{ChaCha20Poly1305Parameters::Variant::kCrunchy, 0x01030005, std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{ChaCha20Poly1305Parameters::Variant::kNoPrefix, absl::nullopt, ""})); TEST_P(ChaCha20Poly1305KeyTest, CreateSucceeds) { TestCase test_case = GetParam(); util::StatusOr params = ChaCha20Poly1305Parameters::Create(test_case.variant); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = ChaCha20Poly1305Key::Create( test_case.variant, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); EXPECT_THAT(key->GetKeyBytes(GetPartialKeyAccess()), Eq(secret)); EXPECT_THAT(key->GetParameters(), Eq(*params)); EXPECT_THAT(key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(key->GetOutputPrefix(), Eq(test_case.output_prefix)); } TEST(ChaCha20Poly1305KeyTest, CreateKeyWithInvalidVariantFails) { EXPECT_THAT(ChaCha20Poly1305Key::Create( ChaCha20Poly1305Parameters::Variant:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements, /*key_bytes=*/RestrictedData(/*num_random_bytes=*/32), /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(ChaCha20Poly1305KeyTest, CreateKeyWithInvalidKeySizeFails) { // Key material must be 32 bytes. RestrictedData invalid_secret = RestrictedData(/*num_random_bytes=*/16); EXPECT_THAT(ChaCha20Poly1305Key::Create( ChaCha20Poly1305Parameters::Variant::kTink, invalid_secret, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(ChaCha20Poly1305KeyTest, CreateKeyWithInvalidIdRequirementFails) { RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); EXPECT_THAT(ChaCha20Poly1305Key::Create( ChaCha20Poly1305Parameters::Variant::kNoPrefix, secret, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(ChaCha20Poly1305Key::Create( ChaCha20Poly1305Parameters::Variant::kTink, secret, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(ChaCha20Poly1305KeyTest, KeyEquals) { TestCase test_case = GetParam(); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = ChaCha20Poly1305Key::Create( test_case.variant, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = ChaCha20Poly1305Key::Create( test_case.variant, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key == *other_key); EXPECT_TRUE(*other_key == *key); EXPECT_FALSE(*key != *other_key); EXPECT_FALSE(*other_key != *key); } TEST(ChaCha20Poly1305KeyTest, DifferentVariantNotEqual) { RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = ChaCha20Poly1305Key::Create( ChaCha20Poly1305Parameters::Variant::kCrunchy, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = ChaCha20Poly1305Key::Create( ChaCha20Poly1305Parameters::Variant::kTink, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST(ChaCha20Poly1305KeyTest, DifferentSecretDataNotEqual) { RestrictedData secret1 = RestrictedData(/*num_random_bytes=*/32); RestrictedData secret2 = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = ChaCha20Poly1305Key::Create( ChaCha20Poly1305Parameters::Variant::kTink, secret1, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = ChaCha20Poly1305Key::Create( ChaCha20Poly1305Parameters::Variant::kTink, secret2, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST(ChaCha20Poly1305KeyTest, DifferentIdRequirementNotEqual) { RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = ChaCha20Poly1305Key::Create( ChaCha20Poly1305Parameters::Variant::kTink, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = ChaCha20Poly1305Key::Create( ChaCha20Poly1305Parameters::Variant::kTink, secret, /*id_requirement=*/0x02030405, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/chacha20_poly1305_parameters.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/chacha20_poly1305_parameters.h" #include #include "absl/status/status.h" #include "tink/parameters.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { util::StatusOr ChaCha20Poly1305Parameters::Create( Variant variant) { static const std::set* kSupportedVariants = new std::set( {Variant::kTink, Variant::kCrunchy, Variant::kNoPrefix}); if (kSupportedVariants->find(variant) == kSupportedVariants->end()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create ChaCha20-Poly1305 parameters with unknown variant."); } return ChaCha20Poly1305Parameters(variant); } bool ChaCha20Poly1305Parameters::operator==(const Parameters& other) const { const ChaCha20Poly1305Parameters* that = dynamic_cast(&other); return that != nullptr && variant_ == that->variant_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/chacha20_poly1305_parameters.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_CHACHA20_POLY1305_PARAMETERS_H_ #define TINK_AEAD_CHACHA20_POLY1305_PARAMETERS_H_ #include "tink/aead/aead_parameters.h" #include "tink/parameters.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Describes the parameters of a `ChaCha20Poly1305Key`. class ChaCha20Poly1305Parameters : public AeadParameters { public: // Description of the output prefix prepended to the ciphertext. enum class Variant : int { // Prepends '0x01' to the ciphertext. kTink = 1, // Prepends '0x00' to the ciphertext. kCrunchy = 2, // Does not prepend any prefix (i.e., keys must have no ID requirement). kNoPrefix = 3, // Added to guard from failures that may be caused by future expansions. kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Copyable and movable. ChaCha20Poly1305Parameters(const ChaCha20Poly1305Parameters& other) = default; ChaCha20Poly1305Parameters& operator=( const ChaCha20Poly1305Parameters& other) = default; ChaCha20Poly1305Parameters(ChaCha20Poly1305Parameters&& other) = default; ChaCha20Poly1305Parameters& operator=(ChaCha20Poly1305Parameters&& other) = default; // Creates a new ChaCha20-Poly1305 parameters object. Returns an error if // `variant` is invalid. static util::StatusOr Create(Variant variant); Variant GetVariant() const { return variant_; } bool HasIdRequirement() const override { return variant_ != Variant::kNoPrefix; } bool operator==(const Parameters& other) const override; private: explicit ChaCha20Poly1305Parameters(Variant variant) : variant_(variant) {} Variant variant_; }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_CHACHA20_POLY1305_PARAMETERS_H_ ================================================ FILE: cc/aead/chacha20_poly1305_parameters_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/chacha20_poly1305_parameters.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::IsTrue; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { ChaCha20Poly1305Parameters::Variant variant; bool has_id_requirement; }; using ChaCha20Poly1305ParametersTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( ChaCha20Poly1305ParametersTestSuite, ChaCha20Poly1305ParametersTest, Values(TestCase{ChaCha20Poly1305Parameters::Variant::kTink, /*has_id_requirement=*/true}, TestCase{ChaCha20Poly1305Parameters::Variant::kCrunchy, /*has_id_requirement=*/true}, TestCase{ChaCha20Poly1305Parameters::Variant::kNoPrefix, /*has_id_requirement=*/false})); TEST_P(ChaCha20Poly1305ParametersTest, Create) { TestCase test_case = GetParam(); util::StatusOr parameters = ChaCha20Poly1305Parameters::Create(test_case.variant); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(parameters->HasIdRequirement(), Eq(test_case.has_id_requirement)); } TEST(ChaCha20Poly1305ParametersTest, CreateWithInvalidVariantFails) { EXPECT_THAT(ChaCha20Poly1305Parameters::Create( ChaCha20Poly1305Parameters::Variant:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(ChaCha20Poly1305ParametersTest, CopyConstructor) { util::StatusOr parameters = ChaCha20Poly1305Parameters::Create( ChaCha20Poly1305Parameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); ChaCha20Poly1305Parameters copy(*parameters); EXPECT_THAT(copy.GetVariant(), Eq(ChaCha20Poly1305Parameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); } TEST(ChaCha20Poly1305ParametersTest, CopyAssignment) { util::StatusOr parameters = ChaCha20Poly1305Parameters::Create( ChaCha20Poly1305Parameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); ChaCha20Poly1305Parameters copy = *parameters; EXPECT_THAT(copy.GetVariant(), Eq(ChaCha20Poly1305Parameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); } TEST_P(ChaCha20Poly1305ParametersTest, ParametersEquals) { TestCase test_case = GetParam(); util::StatusOr parameters = ChaCha20Poly1305Parameters::Create(test_case.variant); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = ChaCha20Poly1305Parameters::Create(test_case.variant); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters == *other_parameters); EXPECT_TRUE(*other_parameters == *parameters); EXPECT_FALSE(*parameters != *other_parameters); EXPECT_FALSE(*other_parameters != *parameters); } TEST(ChaCha20Poly1305ParametersTest, DifferentVariantNotEqual) { util::StatusOr parameters = ChaCha20Poly1305Parameters::Create( ChaCha20Poly1305Parameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = ChaCha20Poly1305Parameters::Create( ChaCha20Poly1305Parameters::Variant::kNoPrefix); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/chacha20_poly1305_proto_serialization.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/chacha20_poly1305_proto_serialization.h" #include "absl/base/attributes.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/aead/chacha20_poly1305_key.h" #include "tink/aead/chacha20_poly1305_parameters.h" #include "tink/internal/key_parser.h" #include "tink/internal/key_serializer.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/parameters_parser.h" #include "tink/internal/parameters_serializer.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/secret_key_access_token.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/chacha20_poly1305.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::google::crypto::tink::ChaCha20Poly1305KeyFormat; using ::google::crypto::tink::OutputPrefixType; using ChaCha20Poly1305ProtoParametersParserImpl = internal::ParametersParserImpl; using ChaCha20Poly1305ProtoParametersSerializerImpl = internal::ParametersSerializerImpl; using ChaCha20Poly1305ProtoKeyParserImpl = internal::KeyParserImpl; using ChaCha20Poly1305ProtoKeySerializerImpl = internal::KeySerializerImpl; const absl::string_view kTypeUrl = "type.googleapis.com/google.crypto.tink.ChaCha20Poly1305Key"; util::StatusOr ToVariant( OutputPrefixType output_prefix_type) { switch (output_prefix_type) { case OutputPrefixType::LEGACY: ABSL_FALLTHROUGH_INTENDED; // Parse LEGACY output prefix as CRUNCHY. case OutputPrefixType::CRUNCHY: return ChaCha20Poly1305Parameters::Variant::kCrunchy; case OutputPrefixType::RAW: return ChaCha20Poly1305Parameters::Variant::kNoPrefix; case OutputPrefixType::TINK: return ChaCha20Poly1305Parameters::Variant::kTink; default: return util::Status( absl::StatusCode::kInvalidArgument, "Could not determine ChaCha20Poly1305Parameters::Variant"); } } util::StatusOr ToOutputPrefixType( ChaCha20Poly1305Parameters::Variant variant) { switch (variant) { case ChaCha20Poly1305Parameters::Variant::kCrunchy: return OutputPrefixType::CRUNCHY; case ChaCha20Poly1305Parameters::Variant::kNoPrefix: return OutputPrefixType::RAW; case ChaCha20Poly1305Parameters::Variant::kTink: return OutputPrefixType::TINK; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine output prefix type"); } } util::StatusOr ParseParameters( const internal::ProtoParametersSerialization& serialization) { if (serialization.GetKeyTemplate().type_url() != kTypeUrl) { return util::Status( absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing ChaCha20Poly1305Parameters."); } ChaCha20Poly1305KeyFormat proto_key_format; if (!proto_key_format.ParseFromString( serialization.GetKeyTemplate().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse ChaCha20Poly1305KeyFormat proto"); } util::StatusOr variant = ToVariant(serialization.GetKeyTemplate().output_prefix_type()); if (!variant.ok()) return variant.status(); return ChaCha20Poly1305Parameters::Create(*variant); } util::StatusOr SerializeParameters( const ChaCha20Poly1305Parameters& parameters) { util::StatusOr output_prefix_type = ToOutputPrefixType(parameters.GetVariant()); if (!output_prefix_type.ok()) return output_prefix_type.status(); return internal::ProtoParametersSerialization::Create( kTypeUrl, *output_prefix_type, ChaCha20Poly1305KeyFormat().SerializeAsString()); } util::StatusOr ParseKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (serialization.TypeUrl() != kTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing ChaCha20Poly1305Key."); } if (!token.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "SecretKeyAccess is required"); } google::crypto::tink::ChaCha20Poly1305Key proto_key; const RestrictedData& restricted_data = serialization.SerializedKeyProto(); if (!proto_key.ParseFromString(restricted_data.GetSecret(*token))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse ChaCha20Poly1305Key proto"); } if (proto_key.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } util::StatusOr variant = ToVariant(serialization.GetOutputPrefixType()); if (!variant.ok()) return variant.status(); util::StatusOr parameters = ChaCha20Poly1305Parameters::Create(*variant); if (!parameters.ok()) return parameters.status(); return ChaCha20Poly1305Key::Create( parameters->GetVariant(), RestrictedData(proto_key.key_value(), *token), serialization.IdRequirement(), GetPartialKeyAccess()); } util::StatusOr SerializeKey( const ChaCha20Poly1305Key& key, absl::optional token) { util::StatusOr restricted_input = key.GetKeyBytes(GetPartialKeyAccess()); if (!restricted_input.ok()) return restricted_input.status(); if (!token.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "SecretKeyAccess is required"); } google::crypto::tink::ChaCha20Poly1305Key proto_key; proto_key.set_version(0); proto_key.set_key_value(restricted_input->GetSecret(*token)); util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetParameters().GetVariant()); if (!output_prefix_type.ok()) return output_prefix_type.status(); RestrictedData restricted_output = RestrictedData(proto_key.SerializeAsString(), *token); return internal::ProtoKeySerialization::Create( kTypeUrl, restricted_output, google::crypto::tink::KeyData::SYMMETRIC, *output_prefix_type, key.GetIdRequirement()); } ChaCha20Poly1305ProtoParametersParserImpl* ChaCha20Poly1305ProtoParametersParser() { static auto* parser = new ChaCha20Poly1305ProtoParametersParserImpl(kTypeUrl, ParseParameters); return parser; } ChaCha20Poly1305ProtoParametersSerializerImpl* ChaCha20Poly1305ProtoParametersSerializer() { static auto* serializer = new ChaCha20Poly1305ProtoParametersSerializerImpl( kTypeUrl, SerializeParameters); return serializer; } ChaCha20Poly1305ProtoKeyParserImpl* ChaCha20Poly1305ProtoKeyParser() { static auto* parser = new ChaCha20Poly1305ProtoKeyParserImpl(kTypeUrl, ParseKey); return parser; } ChaCha20Poly1305ProtoKeySerializerImpl* ChaCha20Poly1305ProtoKeySerializer() { static auto* serializer = new ChaCha20Poly1305ProtoKeySerializerImpl(SerializeKey); return serializer; } } // namespace util::Status RegisterChaCha20Poly1305ProtoSerialization() { util::Status status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersParser(ChaCha20Poly1305ProtoParametersParser()); if (!status.ok()) return status; status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersSerializer( ChaCha20Poly1305ProtoParametersSerializer()); if (!status.ok()) return status; status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(ChaCha20Poly1305ProtoKeyParser()); if (!status.ok()) return status; return internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(ChaCha20Poly1305ProtoKeySerializer()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/chacha20_poly1305_proto_serialization.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_CHACHA20_POLY1305_PROTO_SERIALIZATION_H_ #define TINK_AEAD_CHACHA20_POLY1305_PROTO_SERIALIZATION_H_ #include "tink/util/status.h" namespace crypto { namespace tink { // Registers proto parsers and serializers for ChaCha20-Poly1305 parameters and // keys. crypto::tink::util::Status RegisterChaCha20Poly1305ProtoSerialization(); } // namespace tink } // namespace crypto #endif // TINK_AEAD_CHACHA20_POLY1305_PROTO_SERIALIZATION_H_ ================================================ FILE: cc/aead/chacha20_poly1305_proto_serialization_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/chacha20_poly1305_proto_serialization.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/aead/chacha20_poly1305_key.h" #include "tink/aead/chacha20_poly1305_parameters.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/subtle/random.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/chacha20_poly1305.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::subtle::Random; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::ChaCha20Poly1305KeyFormat; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::IsTrue; using ::testing::NotNull; using ::testing::TestWithParam; using ::testing::Values; constexpr absl::string_view kTypeUrl = "type.googleapis.com/google.crypto.tink.ChaCha20Poly1305Key"; struct TestCase { ChaCha20Poly1305Parameters::Variant variant; OutputPrefixType output_prefix_type; absl::optional id; std::string output_prefix; }; class ChaCha20Poly1305ProtoSerializationTest : public TestWithParam { protected: ChaCha20Poly1305ProtoSerializationTest() { internal::MutableSerializationRegistry::GlobalInstance().Reset(); } }; TEST_F(ChaCha20Poly1305ProtoSerializationTest, RegisterTwiceSucceeds) { ASSERT_THAT(RegisterChaCha20Poly1305ProtoSerialization(), IsOk()); ASSERT_THAT(RegisterChaCha20Poly1305ProtoSerialization(), IsOk()); } INSTANTIATE_TEST_SUITE_P( ChaCha20Poly1305ProtoSerializationTestSuite, ChaCha20Poly1305ProtoSerializationTest, Values(TestCase{ChaCha20Poly1305Parameters::Variant::kTink, OutputPrefixType::TINK, /*id=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{ChaCha20Poly1305Parameters::Variant::kCrunchy, OutputPrefixType::CRUNCHY, /*id=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{ChaCha20Poly1305Parameters::Variant::kNoPrefix, OutputPrefixType::RAW, /*id=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(ChaCha20Poly1305ProtoSerializationTest, ParseParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterChaCha20Poly1305ProtoSerialization(), IsOk()); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kTypeUrl, test_case.output_prefix_type, ChaCha20Poly1305KeyFormat().SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(params, IsOk()); EXPECT_THAT((*params)->HasIdRequirement(), test_case.id.has_value()); const ChaCha20Poly1305Parameters* chacha20_poly1305_params = dynamic_cast(params->get()); ASSERT_THAT(chacha20_poly1305_params, NotNull()); EXPECT_THAT(chacha20_poly1305_params->GetVariant(), Eq(test_case.variant)); } TEST_F(ChaCha20Poly1305ProtoSerializationTest, ParseParametersWithInvalidSerialization) { ASSERT_THAT(RegisterChaCha20Poly1305ProtoSerialization(), IsOk()); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kTypeUrl, OutputPrefixType::RAW, "invalid_serialization"); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(ChaCha20Poly1305ProtoSerializationTest, ParseParametersWithUnkownOutputPrefix) { ASSERT_THAT(RegisterChaCha20Poly1305ProtoSerialization(), IsOk()); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kTypeUrl, OutputPrefixType::UNKNOWN_PREFIX, ChaCha20Poly1305KeyFormat().SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(ChaCha20Poly1305ProtoSerializationTest, SerializeParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterChaCha20Poly1305ProtoSerialization(), IsOk()); util::StatusOr parameters = ChaCha20Poly1305Parameters::Create(test_case.variant); ASSERT_THAT(parameters, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( *parameters); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kTypeUrl)); const internal::ProtoParametersSerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->GetKeyTemplate().type_url(), Eq(kTypeUrl)); EXPECT_THAT(proto_serialization->GetKeyTemplate().output_prefix_type(), Eq(test_case.output_prefix_type)); ChaCha20Poly1305KeyFormat key_format; ASSERT_THAT( key_format.ParseFromString(proto_serialization->GetKeyTemplate().value()), IsTrue()); } TEST_P(ChaCha20Poly1305ProtoSerializationTest, ParseKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterChaCha20Poly1305ProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); google::crypto::tink::ChaCha20Poly1305Key key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kTypeUrl, serialized_key, KeyData::SYMMETRIC, test_case.output_prefix_type, test_case.id); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); EXPECT_THAT((*key)->GetIdRequirement(), Eq(test_case.id)); EXPECT_THAT((*key)->GetParameters().HasIdRequirement(), test_case.id.has_value()); util::StatusOr expected_parameters = ChaCha20Poly1305Parameters::Create(test_case.variant); ASSERT_THAT(expected_parameters, IsOk()); util::StatusOr expected_key = ChaCha20Poly1305Key::Create( expected_parameters->GetVariant(), RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(expected_key, IsOk()); EXPECT_THAT(**key, Eq(*expected_key)); } TEST_F(ChaCha20Poly1305ProtoSerializationTest, ParseLegacyKeyAsCrunchy) { ASSERT_THAT(RegisterChaCha20Poly1305ProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); google::crypto::tink::ChaCha20Poly1305Key key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::LEGACY, /*id_requirement=*/123); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); const ChaCha20Poly1305Key* chacha20_poly1305_key = dynamic_cast(key->get()); ASSERT_THAT(chacha20_poly1305_key, NotNull()); EXPECT_THAT(chacha20_poly1305_key->GetParameters().GetVariant(), Eq(ChaCha20Poly1305Parameters::Variant::kCrunchy)); } TEST_F(ChaCha20Poly1305ProtoSerializationTest, ParseKeyWithInvalidSerialization) { ASSERT_THAT(RegisterChaCha20Poly1305ProtoSerialization(), IsOk()); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(ChaCha20Poly1305ProtoSerializationTest, ParseKeyNoSecretKeyAccess) { ASSERT_THAT(RegisterChaCha20Poly1305ProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(64); google::crypto::tink::ChaCha20Poly1305Key key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(ChaCha20Poly1305ProtoSerializationTest, ParseKeyWithInvalidVersion) { ASSERT_THAT(RegisterChaCha20Poly1305ProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(64); google::crypto::tink::ChaCha20Poly1305Key key_proto; key_proto.set_version(1); // Invalid version number. key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(ChaCha20Poly1305ProtoSerializationTest, SerializeKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterChaCha20Poly1305ProtoSerialization(), IsOk()); util::StatusOr parameters = ChaCha20Poly1305Parameters::Create(test_case.variant); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); util::StatusOr key = ChaCha20Poly1305Key::Create( parameters->GetVariant(), RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kTypeUrl)); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq(kTypeUrl)); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::SYMMETRIC)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id)); google::crypto::tink::ChaCha20Poly1305Key proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.key_value().size(), Eq(32)); } TEST_F(ChaCha20Poly1305ProtoSerializationTest, SerializeKeyNoSecretKeyAccess) { ASSERT_THAT(RegisterChaCha20Poly1305ProtoSerialization(), IsOk()); util::StatusOr parameters = ChaCha20Poly1305Parameters::Create( ChaCha20Poly1305Parameters::Variant::kNoPrefix); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); util::StatusOr key = ChaCha20Poly1305Key::Create( parameters->GetVariant(), RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey(*key, absl::nullopt); EXPECT_THAT(serialization.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/config_v0.h" #include "absl/log/check.h" #include "tink/aead/internal/config_v0.h" #include "tink/configuration.h" namespace crypto { namespace tink { const Configuration& ConfigAeadV0() { static const Configuration* instance = [] { static Configuration* config = new Configuration(); CHECK_OK(internal::AddAeadV0(*config)); return config; }(); return *instance; } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_CONFIG_V0_H_ #define TINK_AEAD_CONFIG_V0_H_ #include "tink/configuration.h" namespace crypto { namespace tink { // Configuration used to generate AEAD primitives with recommended key managers. const Configuration& ConfigAeadV0(); } // namespace tink } // namespace crypto #endif // TINK_AEAD_CONFIG_V0_H_ ================================================ FILE: cc/aead/config_v0_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/config_v0.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/aead.h" #include "tink/aead/aead_key_templates.h" #include "tink/aead/key_gen_config_v0.h" #include "tink/internal/ssl_util.h" #include "tink/keyset_handle.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::google::crypto::tink::KeyTemplate; using ::testing::Not; using ::testing::TestWithParam; using ::testing::Values; using ConfigV0Test = TestWithParam; using ConfigV0BoringSslTest = TestWithParam; // For key type support when using BoringSSL or OpenSSL, see // https://developers.google.com/tink/supported-key-types#aead. INSTANTIATE_TEST_SUITE_P(ConfigV0TestSuite, ConfigV0Test, Values(AeadKeyTemplates::Aes128CtrHmacSha256(), AeadKeyTemplates::Aes128Eax(), AeadKeyTemplates::Aes128Gcm())); INSTANTIATE_TEST_SUITE_P(ConfigV0BoringSslTestSuite, ConfigV0BoringSslTest, Values(AeadKeyTemplates::Aes128GcmSiv(), AeadKeyTemplates::XChaCha20Poly1305())); TEST_P(ConfigV0Test, GetPrimitive) { util::StatusOr> handle = KeysetHandle::GenerateNew(GetParam(), KeyGenConfigAeadV0()); ASSERT_THAT(handle, IsOk()); util::StatusOr> aead = (*handle)->GetPrimitive(ConfigAeadV0()); ASSERT_THAT(aead, IsOk()); std::string plaintext = "plaintext"; util::StatusOr ciphertext = (*aead)->Encrypt(plaintext, "ad"); ASSERT_THAT(ciphertext, IsOk()); EXPECT_THAT((*aead)->Decrypt(*ciphertext, "ad"), IsOkAndHolds(plaintext)); } TEST_P(ConfigV0BoringSslTest, GetPrimitive) { util::StatusOr> handle = KeysetHandle::GenerateNew(GetParam(), KeyGenConfigAeadV0()); ASSERT_THAT(handle, IsOk()); // Fails if using OpenSSL. if (!internal::IsBoringSsl()) { EXPECT_THAT((*handle)->GetPrimitive(ConfigAeadV0()), Not(IsOk())); return; } util::StatusOr> aead = (*handle)->GetPrimitive(ConfigAeadV0()); ASSERT_THAT(aead, IsOk()); std::string plaintext = "plaintext"; util::StatusOr ciphertext = (*aead)->Encrypt(plaintext, "ad"); ASSERT_THAT(ciphertext, IsOk()); EXPECT_THAT((*aead)->Decrypt(*ciphertext, "ad"), IsOkAndHolds(plaintext)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/cord_aead.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_CORD_AEAD_H_ #define TINK_AEAD_CORD_AEAD_H_ #include "absl/strings/cord.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // The interface for authenticated encryption with associated data. // Implementations of this interface are secure against adaptive // chosen ciphertext attacks. Encryption with associated data ensures // authenticity and integrity of that data, but not its secrecy. // (see RFC 5116, https://tools.ietf.org/html/rfc5116) // // Implementations are expected to be thread safe. class CordAead { public: // Encrypts 'plaintext' with 'associated_data' as associated data, // and returns the resulting ciphertext. // The ciphertext allows for checking authenticity and integrity // of the associated data, but does not guarantee its secrecy. // The ciphertext is returned as a Cord and protects the secrecy, authenticity // and integrity of the plaintext. // An implementation of this interface must ensure that the Cord-structure // of the returned ciphertext gives no information about the Cord-structure // of the given plaintext. virtual crypto::tink::util::StatusOr Encrypt( absl::Cord plaintext, absl::Cord associated_data) const = 0; // Decrypts 'ciphertext' with 'associated_data' as associated data, // and returns the resulting plaintext. // The decryption verifies the authenticity and integrity // of the associated data, but there are no guarantees wrt. secrecy // of that data. // The plaintext is returned as a Cord. The structure of the Cord // might differ from the original plaintext Cord, but the content will be the // same. virtual crypto::tink::util::StatusOr Decrypt( absl::Cord ciphertext, absl::Cord associated_data) const = 0; virtual ~CordAead() = default; }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_CORD_AEAD_H_ ================================================ FILE: cc/aead/cord_aead_wrapper.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/aead/cord_aead_wrapper.h" #include #include #include #include "absl/status/status.h" #include "absl/strings/cord.h" #include "tink/aead/cord_aead.h" #include "tink/crypto_format.h" #include "tink/primitive_set.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { util::Status Validate(PrimitiveSet* aead_set) { if (aead_set == nullptr) { return util::Status(absl::StatusCode::kInternal, "aead_set must be non-NULL"); } if (aead_set->get_primary() == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "aead_set has no primary"); } return util::OkStatus(); } class CordAeadSetWrapper : public CordAead { public: explicit CordAeadSetWrapper(std::unique_ptr> aead_set) : aead_set_(std::move(aead_set)) {} crypto::tink::util::StatusOr Encrypt( absl::Cord plaintext, absl::Cord associated_data) const override; crypto::tink::util::StatusOr Decrypt( absl::Cord ciphertext, absl::Cord associated_data) const override; ~CordAeadSetWrapper() override = default; private: std::unique_ptr> aead_set_; }; util::StatusOr CordAeadSetWrapper::Encrypt( absl::Cord plaintext, absl::Cord associated_data) const { auto encrypt_result = aead_set_->get_primary()->get_primitive().Encrypt( plaintext, associated_data); if (!encrypt_result.ok()) return encrypt_result.status(); absl::Cord result; result.Append(aead_set_->get_primary()->get_identifier()); result.Append(encrypt_result.value()); return result; } util::StatusOr CordAeadSetWrapper::Decrypt( absl::Cord ciphertext, absl::Cord associated_data) const { if (ciphertext.size() > CryptoFormat::kNonRawPrefixSize) { std::string key_id = std::string(ciphertext.Subcord(0, CryptoFormat::kNonRawPrefixSize)); auto primitives_result = aead_set_->get_primitives(key_id); if (primitives_result.ok()) { auto raw_ciphertext = ciphertext.Subcord(key_id.size(), ciphertext.size()); for (auto& aead_entry : *(primitives_result.value())) { CordAead& aead = aead_entry->get_primitive(); auto decrypt_result = aead.Decrypt(raw_ciphertext, associated_data); if (decrypt_result.ok()) { return std::move(decrypt_result.value()); } } } } // No matching key succeeded with decryption, try all RAW keys. auto raw_primitives_result = aead_set_->get_raw_primitives(); if (raw_primitives_result.ok()) { for (auto& aead_entry : *(raw_primitives_result.value())) { CordAead& aead = aead_entry->get_primitive(); auto decrypt_result = aead.Decrypt(ciphertext, associated_data); if (decrypt_result.ok()) { return std::move(decrypt_result.value()); } } } return util::Status(absl::StatusCode::kInvalidArgument, "decryption failed"); } } // anonymous namespace util::StatusOr> CordAeadWrapper::Wrap( std::unique_ptr> aead_set) const { util::Status status = Validate(aead_set.get()); if (!status.ok()) return status; std::unique_ptr aead(new CordAeadSetWrapper(std::move(aead_set))); return std::move(aead); } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/cord_aead_wrapper.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_CORD_AEAD_WRAPPER_H_ #define TINK_AEAD_CORD_AEAD_WRAPPER_H_ #include #include "tink/aead/cord_aead.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Wraps a set of AeadCord-instances that correspond to a keyset, // and combines them into a single AeadCord-primitive, that uses the provided // instances, depending on the context: // * CordAead::Encrypt(...) uses the primary instance from the set // * CordAead::Decrypt(...) uses the instance that matches the ciphertext // prefix. class CordAeadWrapper : public PrimitiveWrapper { public: // Returns an Aead-primitive that uses Aead-instances provided in 'aead_set', // which must be non-NULL and must contain a primary instance. util::StatusOr> Wrap( std::unique_ptr> aead_set) const override; }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_CORD_AEAD_WRAPPER_H_ ================================================ FILE: cc/aead/cord_aead_wrapper_test.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/cord_aead_wrapper.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/cord.h" #include "absl/strings/cord_test_helpers.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "tink/aead/cord_aead.h" #include "tink/primitive_set.h" #include "tink/util/status.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" using ::crypto::tink::test::DummyCordAead; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::KeysetInfo; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::OutputPrefixType; namespace crypto { namespace tink { namespace { TEST(AeadSetWrapperTest, WrapNullptr) { CordAeadWrapper wrapper; auto aead_result = wrapper.Wrap(nullptr); EXPECT_FALSE(aead_result.ok()); EXPECT_EQ(absl::StatusCode::kInternal, aead_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "non-NULL", std::string(aead_result.status().message())); } TEST(AeadSetWrapperTest, WrapEmpty) { CordAeadWrapper wrapper; auto aead_result = wrapper.Wrap(absl::make_unique>()); EXPECT_FALSE(aead_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, aead_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "no primary", std::string(aead_result.status().message())); } std::unique_ptr> setup_keyset() { KeysetInfo::KeyInfo* key_info; KeysetInfo keyset_info; uint32_t key_id_0 = 1234543; key_info = keyset_info.add_key_info(); key_info->set_output_prefix_type(OutputPrefixType::TINK); key_info->set_key_id(key_id_0); key_info->set_status(KeyStatusType::ENABLED); std::string aead_name_0 = "aead0"; std::unique_ptr> aead_set( new PrimitiveSet()); std::unique_ptr aead = absl::make_unique(aead_name_0); auto entry_result = aead_set->AddPrimitive(std::move(aead), keyset_info.key_info(0)); auto aead_set_result = aead_set->set_primary(entry_result.value()); return aead_set; } TEST(AeadSetWrapperTest, WrapperEncryptDecrypt) { // Wrap aead_set and test the resulting Aead. auto aead_set = setup_keyset(); CordAeadWrapper wrapper; auto aead_result = wrapper.Wrap(std::move(aead_set)); ASSERT_THAT(aead_result, IsOk()); auto aead = std::move(aead_result.value()); absl::Cord plaintext; plaintext.Append("some_plaintext"); absl::Cord aad; aad.Append("some_aad"); auto encrypt_result = aead->Encrypt(plaintext, aad); EXPECT_TRUE(encrypt_result.ok()) << encrypt_result.status(); absl::Cord ciphertext = encrypt_result.value(); auto decrypt_result = aead->Decrypt(ciphertext, aad); EXPECT_TRUE(decrypt_result.ok()) << decrypt_result.status(); EXPECT_EQ(plaintext, decrypt_result.value()); } TEST(AeadSetWrapperTest, WrapperEncryptDecryptMultipleKeys) { // Wrap aead_set and test the resulting Aead. auto aead_set = setup_keyset(); // Encrypt with the primary key absl::Cord plaintext; plaintext.Append("some_plaintext"); absl::Cord aad; aad.Append("some_aad"); auto encrypt_result = aead_set->get_primary()->get_primitive().Encrypt(plaintext, aad); EXPECT_TRUE(encrypt_result.ok()) << encrypt_result.status(); absl::Cord ciphertext; ciphertext.Append(aead_set->get_primary()->get_identifier()); ciphertext.Append(encrypt_result.value()); // Add a second key KeysetInfo::KeyInfo* key_info; KeysetInfo keyset_info; uint32_t key_id = 42; key_info = keyset_info.add_key_info(); key_info->set_output_prefix_type(OutputPrefixType::TINK); key_info->set_key_id(key_id); key_info->set_status(KeyStatusType::ENABLED); std::string aead_name = "aead1"; std::unique_ptr aead = absl::make_unique(aead_name); auto entry_result = aead_set->AddPrimitive(std::move(aead), keyset_info.key_info(0)); EXPECT_TRUE(entry_result.ok()) << entry_result.status(); // Wrap the primitive set CordAeadWrapper wrapper; auto aead_result = wrapper.Wrap(std::move(aead_set)); ASSERT_THAT(aead_result, IsOk()); aead = std::move(aead_result.value()); // Encrypt with the wrapped AEAD and check if result was equal to the // encryption with the primary key. auto encrypt_wrap_result = aead->Encrypt(plaintext, aad); EXPECT_TRUE(encrypt_wrap_result.ok()) << encrypt_wrap_result.status(); EXPECT_EQ(ciphertext, encrypt_wrap_result.value()); } TEST(AeadSetWrapperTest, WrapperEncryptDecryptManyChunks) { // Wrap aead_set and test the resulting Aead. auto aead_set = setup_keyset(); CordAeadWrapper wrapper; auto aead_result = wrapper.Wrap(std::move(aead_set)); ASSERT_THAT(aead_result, IsOk()); auto aead = std::move(aead_result.value()); std::string plaintext = ""; for (int i = 0; i < 1000; i++) { plaintext += "chunk" + std::to_string(i); } absl::Cord plaintext_cord = absl::MakeFragmentedCord(absl::StrSplit(plaintext, absl::ByLength(5))); absl::Cord aad; aad.Append("some_aad"); auto encrypt_result = aead->Encrypt(plaintext_cord, aad); EXPECT_TRUE(encrypt_result.ok()) << encrypt_result.status(); absl::Cord ciphertext = encrypt_result.value(); auto decrypt_result = aead->Decrypt(ciphertext, aad); EXPECT_TRUE(decrypt_result.ok()) << decrypt_result.status(); EXPECT_EQ(plaintext, decrypt_result.value()); } TEST(AeadSetWrapperTest, WrapperEncryptBadDecrypt) { // Wrap aead_set and test the resulting Aead. auto aead_set = setup_keyset(); CordAeadWrapper wrapper; auto aead_result = wrapper.Wrap(std::move(aead_set)); ASSERT_THAT(aead_result, IsOk()); auto aead = std::move(aead_result.value()); absl::Cord plaintext; plaintext.Append("some_plaintext"); absl::Cord aad; aad.Append("some_aad"); absl::Cord bad_ciphertext; bad_ciphertext.Append("some bad ciphertext"); auto decrypt_result = aead->Decrypt(bad_ciphertext, aad); EXPECT_FALSE(decrypt_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, decrypt_result.status().code()); EXPECT_THAT(decrypt_result.status(), StatusIs(absl::StatusCode::kInvalidArgument, testing::HasSubstr("decryption failed"))); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/failing_aead.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/aead/failing_aead.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { // An AEAD that always returns a kInternal status on API calls. class AlwaysFailAead : public Aead { public: explicit AlwaysFailAead(std::string message) : message_(std::move(message)) {} util::StatusOr Encrypt( absl::string_view plaintext, absl::string_view associated_data) const override { return util::Status( absl::StatusCode::kInternal, absl::StrCat( "AlwaysFailAead will always fail on encrypt (msg=", message_, ")")); } util::StatusOr Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const override { return util::Status( absl::StatusCode::kInternal, absl::StrCat( "AlwaysFailAead will always fail on decrypt (msg=", message_, ")")); } private: const std::string message_; }; } // namespace std::unique_ptr CreateAlwaysFailingAead(absl::string_view message) { return absl::make_unique(std::string(message)); } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/failing_aead.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_FAILING_AEAD_H_ #define TINK_AEAD_FAILING_AEAD_H_ #include #include #include "absl/strings/string_view.h" #include "tink/aead.h" namespace crypto { namespace tink { // Returns an AEAD that always returns an error when calling Encrypt or Decrypt. // The error message will contain `message`. std::unique_ptr CreateAlwaysFailingAead(absl::string_view message = ""); } // namespace tink } // namespace crypto #endif // TINK_AEAD_FAILING_AEAD_H_ ================================================ FILE: cc/aead/failing_aead_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/aead/failing_aead.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/aead.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::StatusIs; using ::testing::HasSubstr; TEST(AlwaysFailAead, EncryptFails) { std::unique_ptr failing_aead = CreateAlwaysFailingAead(); EXPECT_THAT(failing_aead->Encrypt("plaintext", "associated_data").status(), StatusIs(absl::StatusCode::kInternal)); } TEST(AlwaysFailAead, EncryptFailsContainsMessage) { const std::string expected_message = "expected_message"; std::unique_ptr failing_aead = CreateAlwaysFailingAead(expected_message); EXPECT_THAT( failing_aead->Encrypt("plaintext", "associated_data").status(), StatusIs(absl::StatusCode::kInternal, HasSubstr(expected_message))); } TEST(AlwaysFailAead, DecryptFails) { std::unique_ptr failing_aead = CreateAlwaysFailingAead(); EXPECT_THAT(failing_aead->Decrypt("ciphertext", "associated_data").status(), StatusIs(absl::StatusCode::kInternal)); } TEST(AlwaysFailAead, DecryptFailsContainsMessage) { const std::string expected_message = "expected_message"; std::unique_ptr failing_aead = CreateAlwaysFailingAead(expected_message); EXPECT_THAT( failing_aead->Decrypt("ciphertext", "associated_data").status(), StatusIs(absl::StatusCode::kInternal, HasSubstr(expected_message))); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/internal/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "aead_util", srcs = ["aead_util.cc"], hdrs = ["aead_util.h"], include_prefix = "tink/aead/internal", deps = [ "//util:errors", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "wycheproof_aead", testonly = 1, srcs = ["wycheproof_aead.cc"], hdrs = ["wycheproof_aead.h"], include_prefix = "tink/aead/internal", deps = [ "//subtle:wycheproof_util", "//util:statusor", "@com_google_absl//absl/strings", ], ) cc_library( name = "ssl_aead", srcs = ["ssl_aead.cc"], hdrs = ["ssl_aead.h"], include_prefix = "tink/aead/internal", deps = [ ":aead_util", "//internal:call_with_core_dump_protection", "//internal:err_util", "//internal:ssl_unique_ptr", "//internal:util", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/cleanup", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", ], ) cc_library( name = "cord_aes_gcm_boringssl", srcs = ["cord_aes_gcm_boringssl.cc"], hdrs = ["cord_aes_gcm_boringssl.h"], include_prefix = "tink/aead/internal", deps = [ ":aead_util", "//aead:cord_aead", "//internal:ssl_unique_ptr", "//subtle:random", "//subtle:subtle_util", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:cord", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "zero_copy_aead", hdrs = ["zero_copy_aead.h"], include_prefix = "tink/aead/internal", deps = [ "//util:statusor", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", ], ) cc_library( name = "mock_zero_copy_aead", testonly = 1, hdrs = ["mock_zero_copy_aead.h"], include_prefix = "tink/aead/internal", deps = [ ":zero_copy_aead", "//util:statusor", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", "@com_google_googletest//:gtest", ], ) cc_library( name = "aead_from_zero_copy", srcs = ["aead_from_zero_copy.cc"], hdrs = ["aead_from_zero_copy.h"], include_prefix = "tink/aead/internal", deps = [ ":zero_copy_aead", "//:aead", "//subtle:subtle_util", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:span", ], ) cc_library( name = "zero_copy_aead_wrapper", srcs = ["zero_copy_aead_wrapper.cc"], hdrs = ["zero_copy_aead_wrapper.h"], include_prefix = "tink/aead/internal", deps = [ ":zero_copy_aead", "//:aead", "//:crypto_format", "//:primitive_set", "//:primitive_wrapper", "//subtle:subtle_util", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", ], ) cc_library( name = "zero_copy_aes_gcm_boringssl", srcs = ["zero_copy_aes_gcm_boringssl.cc"], hdrs = ["zero_copy_aes_gcm_boringssl.h"], include_prefix = "tink/aead/internal", deps = [ ":aead_util", ":ssl_aead", ":zero_copy_aead", "//internal:util", "//subtle:random", "//subtle:subtle_util", "//util:secret_data", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", ], ) cc_library( name = "key_gen_config_v0", srcs = ["key_gen_config_v0.cc"], hdrs = ["key_gen_config_v0.h"], include_prefix = "tink/aead/internal", deps = [ "//:key_gen_configuration", "//aead:aes_ctr_hmac_aead_key_manager", "//aead:aes_eax_key_manager", "//aead:aes_gcm_key_manager", "//aead:aes_gcm_siv_key_manager", "//aead:xchacha20_poly1305_key_manager", "//internal:key_gen_configuration_impl", "//util:status", "@com_google_absl//absl/memory", ], ) cc_library( name = "config_v0", srcs = ["config_v0.cc"], hdrs = ["config_v0.h"], include_prefix = "tink/aead/internal", deps = [ "//:configuration", "//aead:aead_wrapper", "//aead:aes_ctr_hmac_aead_key_manager", "//aead:aes_eax_key_manager", "//aead:aes_gcm_key_manager", "//aead:aes_gcm_siv_key_manager", "//aead:xchacha20_poly1305_key_manager", "//internal:configuration_impl", "//util:status", "@com_google_absl//absl/memory", ], ) cc_test( name = "cord_aes_gcm_boringssl_test", size = "small", srcs = ["cord_aes_gcm_boringssl_test.cc"], data = ["//testvectors:aes_gcm"], deps = [ ":cord_aes_gcm_boringssl", "//:aead", "//aead:cord_aead", "//subtle:aes_gcm_boringssl", "//subtle:wycheproof_util", "//util:secret_data", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:cord", "@com_google_absl//absl/strings:cord_test_helpers", "@com_google_googletest//:gtest_main", "@rapidjson", ], ) cc_test( name = "aead_util_test", size = "small", srcs = ["aead_util_test.cc"], deps = [ ":aead_util", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "zero_copy_aead_wrapper_test", srcs = ["zero_copy_aead_wrapper_test.cc"], deps = [ ":mock_zero_copy_aead", ":zero_copy_aead", ":zero_copy_aead_wrapper", "//:aead", "//:crypto_format", "//:primitive_set", "//proto:tink_cc_proto", "//subtle:subtle_util", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:span", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "zero_copy_aes_gcm_boringssl_test", srcs = ["zero_copy_aes_gcm_boringssl_test.cc"], data = ["//testvectors:aes_gcm"], deps = [ ":wycheproof_aead", ":zero_copy_aead", ":zero_copy_aes_gcm_boringssl", "//subtle:subtle_util", "//util:secret_data", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aead_from_zero_copy_test", srcs = ["aead_from_zero_copy_test.cc"], deps = [ ":aead_from_zero_copy", ":mock_zero_copy_aead", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ssl_aead_test", srcs = ["ssl_aead_test.cc"], data = [ "//testvectors:aes_gcm", "//testvectors:aes_gcm_siv", "//testvectors:chacha20_poly1305", ], deps = [ ":ssl_aead", ":wycheproof_aead", "//internal:fips_utils", "//internal:ssl_util", "//subtle:subtle_util", "//util:secret_data", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ssl_aead_large_inputs_test", size = "enormous", srcs = ["ssl_aead_large_inputs_test.cc"], deps = [ ":ssl_aead", "//config:tink_fips", "//internal:ssl_util", "//internal:util", "//subtle:subtle_util", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "config_v0_test", srcs = ["config_v0_test.cc"], deps = [ ":config_v0", ":key_gen_config_v0", "//:aead", "//:configuration", "//:key_gen_configuration", "//:keyset_handle", "//aead:aead_key_templates", "//aead:aes_ctr_hmac_aead_key_manager", "//aead:aes_eax_key_manager", "//aead:aes_gcm_key_manager", "//aead:aes_gcm_siv_key_manager", "//aead:xchacha20_poly1305_key_manager", "//internal:configuration_impl", "//internal:key_gen_configuration_impl", "//internal:key_type_info_store", "//internal:keyset_wrapper_store", "//internal:ssl_util", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/aead/internal/CMakeLists.txt ================================================ tink_module(aead::internal) tink_cc_library( NAME aead_util SRCS aead_util.cc aead_util.h DEPS absl::flat_hash_set absl::status absl::string_view crypto tink::util::errors tink::util::statusor ) tink_cc_library( NAME wycheproof_aead SRCS wycheproof_aead.cc wycheproof_aead.h DEPS absl::strings tink::subtle::wycheproof_util tink::util::statusor TESTONLY ) tink_cc_library( NAME ssl_aead SRCS ssl_aead.cc ssl_aead.h DEPS tink::aead::internal::aead_util absl::core_headers absl::cleanup absl::memory absl::status absl::strings absl::span crypto tink::internal::call_with_core_dump_protection tink::internal::err_util tink::internal::ssl_unique_ptr tink::internal::util tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME cord_aes_gcm_boringssl SRCS cord_aes_gcm_boringssl.cc cord_aes_gcm_boringssl.h DEPS tink::aead::internal::aead_util absl::memory absl::status absl::cord absl::string_view crypto tink::aead::cord_aead tink::internal::ssl_unique_ptr tink::subtle::random tink::subtle::subtle_util tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME mock_zero_copy_aead SRCS mock_zero_copy_aead.h DEPS tink::aead::internal::zero_copy_aead gmock absl::strings absl::span tink::util::statusor TESTONLY ) tink_cc_library( NAME aead_from_zero_copy SRCS aead_from_zero_copy.cc aead_from_zero_copy.h DEPS tink::aead::internal::zero_copy_aead absl::memory absl::status absl::string_view absl::span tink::core::aead tink::subtle::subtle_util tink::util::status tink::util::statusor ) tink_cc_library( NAME zero_copy_aead SRCS zero_copy_aead.h DEPS absl::strings absl::span tink::util::statusor ) tink_cc_library( NAME zero_copy_aead_wrapper SRCS zero_copy_aead_wrapper.cc zero_copy_aead_wrapper.h DEPS tink::aead::internal::zero_copy_aead absl::memory absl::status absl::strings absl::span tink::core::aead tink::core::crypto_format tink::core::primitive_set tink::core::primitive_wrapper tink::subtle::subtle_util tink::util::status tink::util::statusor ) tink_cc_library( NAME zero_copy_aes_gcm_boringssl SRCS zero_copy_aes_gcm_boringssl.cc zero_copy_aes_gcm_boringssl.h DEPS tink::aead::internal::aead_util tink::aead::internal::ssl_aead tink::aead::internal::zero_copy_aead absl::core_headers absl::memory absl::status absl::strings absl::span tink::internal::util tink::subtle::random tink::subtle::subtle_util tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME key_gen_config_v0 SRCS key_gen_config_v0.cc key_gen_config_v0.h DEPS absl::memory tink::core::key_gen_configuration tink::aead::aes_ctr_hmac_aead_key_manager tink::aead::aes_eax_key_manager tink::aead::aes_gcm_key_manager tink::aead::aes_gcm_siv_key_manager tink::aead::xchacha20_poly1305_key_manager tink::internal::key_gen_configuration_impl tink::util::status ) tink_cc_library( NAME config_v0 SRCS config_v0.cc config_v0.h DEPS absl::memory tink::core::configuration tink::aead::aead_wrapper tink::aead::aes_ctr_hmac_aead_key_manager tink::aead::aes_eax_key_manager tink::aead::aes_gcm_key_manager tink::aead::aes_gcm_siv_key_manager tink::aead::xchacha20_poly1305_key_manager tink::internal::configuration_impl tink::util::status ) tink_cc_test( NAME aead_util_test SRCS aead_util_test.cc DEPS tink::aead::internal::aead_util gmock crypto tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME ssl_aead_test SRCS ssl_aead_test.cc DATA wycheproof::testvectors DEPS tink::aead::internal::ssl_aead tink::aead::internal::wycheproof_aead gmock absl::flat_hash_set absl::status absl::strings absl::span tink::internal::fips_utils tink::internal::ssl_util tink::subtle::subtle_util tink::util::secret_data tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME cord_aes_gcm_boringssl_test SRCS cord_aes_gcm_boringssl_test.cc DATA wycheproof::testvectors DEPS tink::subtle::aes_gcm_boringssl tink::subtle::wycheproof_util tink::aead::cord_aead tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_util tink::util::test_matchers absl::strings absl::cord rapidjson ) tink_cc_test( NAME aead_from_zero_copy_test SRCS aead_from_zero_copy_test.cc DEPS tink::aead::internal::aead_from_zero_copy tink::aead::internal::mock_zero_copy_aead gmock absl::memory absl::status absl::strings absl::span tink::util::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME zero_copy_aes_gcm_boringssl_test SRCS zero_copy_aes_gcm_boringssl_test.cc DATA wycheproof::testvectors DEPS tink::aead::internal::wycheproof_aead tink::aead::internal::zero_copy_aead tink::aead::internal::zero_copy_aes_gcm_boringssl gmock absl::status absl::strings absl::span crypto tink::subtle::subtle_util tink::util::secret_data tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME ssl_aead_large_inputs_test SRCS ssl_aead_large_inputs_test.cc DEPS tink::aead::internal::ssl_aead gmock absl::flat_hash_set absl::memory absl::status absl::strings absl::span tink::config::tink_fips tink::internal::ssl_util tink::internal::util tink::subtle::subtle_util tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME zero_copy_aead_wrapper_test SRCS zero_copy_aead_wrapper_test.cc DEPS tink::aead::internal::mock_zero_copy_aead tink::aead::internal::zero_copy_aead tink::aead::internal::zero_copy_aead_wrapper gmock absl::memory absl::status absl::string_view absl::span tink::core::aead tink::core::crypto_format tink::core::primitive_set tink::subtle::subtle_util tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) tink_cc_test( NAME config_v0_test SRCS config_v0_test.cc DEPS tink::aead::internal::config_v0 tink::aead::internal::key_gen_config_v0 gmock tink::core::aead tink::core::configuration tink::core::key_gen_configuration tink::core::keyset_handle tink::aead::aead_key_templates tink::aead::aes_ctr_hmac_aead_key_manager tink::aead::aes_eax_key_manager tink::aead::aes_gcm_key_manager tink::aead::aes_gcm_siv_key_manager tink::aead::xchacha20_poly1305_key_manager tink::internal::configuration_impl tink::internal::key_gen_configuration_impl tink::internal::key_type_info_store tink::internal::keyset_wrapper_store tink::internal::ssl_util tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) ================================================ FILE: cc/aead/internal/aead_from_zero_copy.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/aead/internal/aead_from_zero_copy.h" #include #include #include "absl/memory/memory.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "tink/aead/internal/zero_copy_aead.h" #include "tink/subtle/subtle_util.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { util::StatusOr AeadFromZeroCopy::Encrypt( absl::string_view plaintext, absl::string_view associated_data) const { std::string result; subtle::ResizeStringUninitialized(&result, aead_->MaxEncryptionSize(plaintext.size())); util::StatusOr written_bytes = aead_->Encrypt( plaintext, associated_data, absl::MakeSpan(&result[0], result.size())); if (!written_bytes.ok()) { return written_bytes.status(); } result.resize(*written_bytes); return result; } util::StatusOr AeadFromZeroCopy::Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const { std::string result; subtle::ResizeStringUninitialized( &result, aead_->MaxDecryptionSize(ciphertext.size())); util::StatusOr bytes_written = aead_->Decrypt( ciphertext, associated_data, absl::MakeSpan(&result[0], result.size())); if (!bytes_written.ok()) { return bytes_written.status(); } result.resize(*bytes_written); return result; } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/internal/aead_from_zero_copy.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_INTERNAL_AEAD_FROM_ZERO_COPY_H_ #define TINK_AEAD_INTERNAL_AEAD_FROM_ZERO_COPY_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/aead/internal/zero_copy_aead.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { // Aead cipher form a zero-copy one. Given a zero-copy AEAD implementation e.g., // FooAeadZeroCopy, one can simply have: // // std::unique_ptr aead = // std::make_unique(std::move(zero_copy_aead)); class AeadFromZeroCopy : public Aead { public: explicit AeadFromZeroCopy(std::unique_ptr aead) : aead_(std::move(aead)) {} crypto::tink::util::StatusOr Encrypt( absl::string_view plaintext, absl::string_view associated_data) const override; crypto::tink::util::StatusOr Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const override; private: const std::unique_ptr aead_; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_AEAD_INTERNAL_AEAD_FROM_ZERO_COPY_H_ ================================================ FILE: cc/aead/internal/aead_from_zero_copy_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/aead/internal/aead_from_zero_copy.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "tink/aead/internal/mock_zero_copy_aead.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace internal { namespace { constexpr absl::string_view kPlaintext = "Some data to encrypt."; constexpr absl::string_view kAssociatedData = "Some associated data."; constexpr absl::string_view kCiphertext = "37ajhgdahjsdg8653821218236182631"; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; using ::testing::_; using ::testing::Invoke; using ::testing::Return; using ::testing::Unused; TEST(AeadFromZeroCopyTest, EncryptSucceeds) { auto mock_zero_copy_aead = std::make_unique(); EXPECT_CALL(*mock_zero_copy_aead, MaxEncryptionSize(kPlaintext.size())) .WillOnce(Return(kCiphertext.size())); EXPECT_CALL(*mock_zero_copy_aead, Encrypt(kPlaintext, kAssociatedData, _)) .WillOnce(Invoke([&](Unused, Unused, absl::Span buffer) { memcpy(buffer.data(), kCiphertext.data(), kCiphertext.size()); return kCiphertext.size(); })); AeadFromZeroCopy aead(std::move(mock_zero_copy_aead)); StatusOr ciphertext = aead.Encrypt(kPlaintext, kAssociatedData); ASSERT_THAT(ciphertext, IsOk()); EXPECT_EQ(*ciphertext, kCiphertext); } TEST(AeadFromZeroCopyTest, EncryptFailsIfZeroCopyEncryptFails) { auto mock_zero_copy_aead = std::make_unique(); EXPECT_CALL(*mock_zero_copy_aead, MaxEncryptionSize(kPlaintext.size())) .WillOnce(Return(kCiphertext.size())); EXPECT_CALL(*mock_zero_copy_aead, Encrypt(kPlaintext, kAssociatedData, _)) .WillOnce( Return(Status(absl::StatusCode::kInternal, "Some error happened!"))); AeadFromZeroCopy aead(std::move(mock_zero_copy_aead)); EXPECT_THAT(aead.Encrypt(kPlaintext, kAssociatedData).status(), StatusIs(absl::StatusCode::kInternal)); } TEST(AeadFromZeroCopyTest, DecryptSucceeds) { auto mock_zero_copy_aead = std::make_unique(); EXPECT_CALL(*mock_zero_copy_aead, MaxDecryptionSize(kCiphertext.size())) .WillOnce(Return(kPlaintext.size())); EXPECT_CALL(*mock_zero_copy_aead, Decrypt(kCiphertext, kAssociatedData, _)) .WillOnce(Invoke([&](Unused, Unused, absl::Span buffer) { memcpy(buffer.data(), kPlaintext.data(), kPlaintext.size()); return kPlaintext.size(); })); AeadFromZeroCopy aead(std::move(mock_zero_copy_aead)); StatusOr plaintext = aead.Decrypt(kCiphertext, kAssociatedData); ASSERT_THAT(plaintext, IsOk()); EXPECT_EQ(*plaintext, kPlaintext); } TEST(AeadFromZeroCopyTest, EncryptFailsIfZeroCopyDecryptFails) { auto mock_zero_copy_aead = std::make_unique(); EXPECT_CALL(*mock_zero_copy_aead, MaxDecryptionSize(kCiphertext.size())) .WillOnce(Return(kPlaintext.size())); EXPECT_CALL(*mock_zero_copy_aead, Decrypt(kCiphertext, kAssociatedData, _)) .WillOnce( Return(Status(absl::StatusCode::kInternal, "Some error happened!"))); AeadFromZeroCopy aead(std::move(mock_zero_copy_aead)); EXPECT_THAT(aead.Decrypt(kCiphertext, kAssociatedData).status(), StatusIs(absl::StatusCode::kInternal)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/internal/aead_util.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/aead/internal/aead_util.h" #include #include #include "absl/container/flat_hash_set.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "tink/util/errors.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { bool IsSupportedKmsEnvelopeAeadDekKeyType(absl::string_view key_type) { static const auto *kSupportedDekKeyTypes = new absl::flat_hash_set({ "type.googleapis.com/google.crypto.tink.AesGcmKey", "type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key", "type.googleapis.com/google.crypto.tink.AesCtrHmacAeadKey", "type.googleapis.com/google.crypto.tink.AesEaxKey", "type.googleapis.com/google.crypto.tink.AesGcmSivKey", }); return kSupportedDekKeyTypes->contains(key_type); } util::StatusOr GetAesGcmCipherForKeySize( uint32_t key_size_in_bytes) { switch (key_size_in_bytes) { case 16: return EVP_aes_128_gcm(); case 32: return EVP_aes_256_gcm(); default: return ToStatusF(absl::StatusCode::kInvalidArgument, "Invalid key size %d", key_size_in_bytes); } } #ifdef OPENSSL_IS_BORINGSSL util::StatusOr GetAesGcmAeadForKeySize( uint32_t key_size_in_bytes) { switch (key_size_in_bytes) { case 16: return EVP_aead_aes_128_gcm(); case 32: return EVP_aead_aes_256_gcm(); default: return ToStatusF(absl::StatusCode::kInvalidArgument, "Invalid key size %d", key_size_in_bytes); } } util::StatusOr GetAesGcmSivAeadCipherForKeySize( int key_size_in_bytes) { switch (key_size_in_bytes) { case 16: return EVP_aead_aes_128_gcm_siv(); case 32: return EVP_aead_aes_256_gcm_siv(); default: return ToStatusF( absl::StatusCode::kInvalidArgument, "Invalid key size; valid values are {16, 32} bytes, got %d", key_size_in_bytes); } } #endif } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/internal/aead_util.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_INTERNAL_AEAD_UTIL_H_ #define TINK_AEAD_INTERNAL_AEAD_UTIL_H_ #include #include #include "absl/container/flat_hash_set.h" #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { bool IsSupportedKmsEnvelopeAeadDekKeyType(absl::string_view key_type); // Returns a pointer to an AES-GCM EVP_CIPHER for the given key size. util::StatusOr GetAesGcmCipherForKeySize( uint32_t key_size_in_bytes); #ifdef OPENSSL_IS_BORINGSSL // Returns a pointer to an AES-GCM EVP_AEAD for the given key size. util::StatusOr GetAesGcmAeadForKeySize( uint32_t key_size_in_bytes); // Returns a pointer to an AES-GCM-SIV EVP_AEAD for `key_size_in_bytes` or an // error if `key_size_in_bytes` is invalid. util::StatusOr GetAesGcmSivAeadCipherForKeySize( int key_size_in_bytes); #endif } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_AEAD_INTERNAL_AEAD_UTIL_H_ ================================================ FILE: cc/aead/internal/aead_util_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/aead/internal/aead_util.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "openssl/evp.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::testing::IsFalse; using ::testing::IsTrue; using ::testing::Not; TEST(AeadUtilTest, GetAesGcmCipherForKeySize) { for (int i = 0; i < 64; i++) { util::StatusOr cipher = GetAesGcmCipherForKeySize(i); if (i == 16) { EXPECT_THAT(cipher, IsOkAndHolds(EVP_aes_128_gcm())); } else if (i == 32) { EXPECT_THAT(cipher, IsOkAndHolds(EVP_aes_256_gcm())); } else { EXPECT_THAT(cipher, Not(IsOk())); } } } TEST(AeadUtilTest, SupportedKmsEnvelopeAeadDekKeyTypes) { EXPECT_THAT(IsSupportedKmsEnvelopeAeadDekKeyType( "type.googleapis.com/google.crypto.tink.AesGcmKey"), IsTrue()); EXPECT_THAT(IsSupportedKmsEnvelopeAeadDekKeyType( "type.googleapis.com/google.crypto.tink.KmsEnvelopeAeadKey"), IsFalse()); } #ifdef OPENSSL_IS_BORINGSSL TEST(AeadUtilTest, GetAesAeadForKeySize) { for (int i = 0; i < 64; i++) { util::StatusOr cipher = GetAesGcmAeadForKeySize(i); if (i == 16) { EXPECT_THAT(cipher, IsOkAndHolds(EVP_aead_aes_128_gcm())); } else if (i == 32) { EXPECT_THAT(cipher, IsOkAndHolds(EVP_aead_aes_256_gcm())); } else { EXPECT_THAT(cipher, Not(IsOk())); } } } TEST(AeadUtilTest, GetAesGcmSivAeadCipherForKeySize) { for (int i = 0; i < 64; i++) { util::StatusOr cipher = GetAesGcmSivAeadCipherForKeySize(i); if (i == 16) { EXPECT_THAT(cipher, IsOkAndHolds(EVP_aead_aes_128_gcm_siv())); } else if (i == 32) { EXPECT_THAT(cipher, IsOkAndHolds(EVP_aead_aes_256_gcm_siv())); } else { EXPECT_THAT(cipher, Not(IsOk())); } } } #endif } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/internal/config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/internal/config_v0.h" #include "absl/memory/memory.h" #include "tink/aead/aead_wrapper.h" #include "tink/aead/aes_ctr_hmac_aead_key_manager.h" #include "tink/aead/aes_eax_key_manager.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/aead/aes_gcm_siv_key_manager.h" #include "tink/aead/xchacha20_poly1305_key_manager.h" #include "tink/configuration.h" #include "tink/internal/configuration_impl.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { util::Status AddAeadV0(Configuration& config) { util::Status status = ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config); if (!status.ok()) { return status; } status = ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); if (!status.ok()) { return status; } status = ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); if (!status.ok()) { return status; } status = ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); if (!status.ok()) { return status; } status = ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); if (!status.ok()) { return status; } return ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/internal/config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_INTERNAL_CONFIG_V0_H_ #define TINK_AEAD_INTERNAL_CONFIG_V0_H_ #include "tink/configuration.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { // Add recommended AEAD primitive wrappers and key managers to `config`, used to // generate primitives. util::Status AddAeadV0(Configuration& config); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_AEAD_INTERNAL_CONFIG_V0_H_ ================================================ FILE: cc/aead/internal/config_v0_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/internal/config_v0.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/aead.h" #include "tink/aead/aead_key_templates.h" #include "tink/aead/aes_ctr_hmac_aead_key_manager.h" #include "tink/aead/aes_eax_key_manager.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/aead/aes_gcm_siv_key_manager.h" #include "tink/aead/internal/key_gen_config_v0.h" #include "tink/aead/xchacha20_poly1305_key_manager.h" #include "tink/configuration.h" #include "tink/internal/configuration_impl.h" #include "tink/internal/key_gen_configuration_impl.h" #include "tink/internal/key_type_info_store.h" #include "tink/internal/keyset_wrapper_store.h" #include "tink/internal/ssl_util.h" #include "tink/key_gen_configuration.h" #include "tink/keyset_handle.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::google::crypto::tink::KeyTemplate; using ::testing::Not; using ::testing::TestWithParam; using ::testing::Values; TEST(AeadV0Test, PrimitiveWrappers) { Configuration config; ASSERT_THAT(AddAeadV0(config), IsOk()); util::StatusOr store = ConfigurationImpl::GetKeysetWrapperStore(config); ASSERT_THAT(store, IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); } TEST(AeadV0Test, KeyManagers) { Configuration config; ASSERT_THAT(AddAeadV0(config), IsOk()); util::StatusOr store = ConfigurationImpl::GetKeyTypeInfoStore(config); ASSERT_THAT(store, IsOk()); KeyGenConfiguration key_gen_config; ASSERT_THAT(AddAeadKeyGenV0(key_gen_config), IsOk()); util::StatusOr key_gen_store = KeyGenConfigurationImpl::GetKeyTypeInfoStore(key_gen_config); ASSERT_THAT(key_gen_store, IsOk()); for (const KeyTypeInfoStore* s : {*store, *key_gen_store}) { EXPECT_THAT(s->Get(AesCtrHmacAeadKeyManager().get_key_type()), IsOk()); EXPECT_THAT(s->Get(AesEaxKeyManager().get_key_type()), IsOk()); EXPECT_THAT(s->Get(AesGcmKeyManager().get_key_type()), IsOk()); EXPECT_THAT(s->Get(AesGcmSivKeyManager().get_key_type()), IsOk()); EXPECT_THAT(s->Get(XChaCha20Poly1305KeyManager().get_key_type()), IsOk()); } } using AeadV0KeyTypesTest = TestWithParam; using AeadV0BoringSslKeyTypesTest = TestWithParam; // For key type support when using BoringSSL or OpenSSL, see // https://developers.google.com/tink/supported-key-types#aead. INSTANTIATE_TEST_SUITE_P(AeadV0KeyTypesTestSuite, AeadV0KeyTypesTest, Values(AeadKeyTemplates::Aes128CtrHmacSha256(), AeadKeyTemplates::Aes128Eax(), AeadKeyTemplates::Aes128Gcm())); INSTANTIATE_TEST_SUITE_P(AeadV0BoringSslKeyTypesTestSuite, AeadV0BoringSslKeyTypesTest, Values(AeadKeyTemplates::Aes128GcmSiv(), AeadKeyTemplates::XChaCha20Poly1305())); TEST_P(AeadV0KeyTypesTest, GetPrimitive) { KeyGenConfiguration key_gen_config; ASSERT_THAT(AddAeadKeyGenV0(key_gen_config), IsOk()); Configuration config; ASSERT_THAT(AddAeadV0(config), IsOk()); util::StatusOr> handle = KeysetHandle::GenerateNew(GetParam(), key_gen_config); ASSERT_THAT(handle, IsOk()); util::StatusOr> aead = (*handle)->GetPrimitive(config); ASSERT_THAT(aead, IsOk()); std::string plaintext = "plaintext"; util::StatusOr ciphertext = (*aead)->Encrypt(plaintext, "ad"); ASSERT_THAT(ciphertext, IsOk()); EXPECT_THAT((*aead)->Decrypt(*ciphertext, "ad"), IsOkAndHolds(plaintext)); } TEST_P(AeadV0BoringSslKeyTypesTest, GetPrimitive) { KeyGenConfiguration key_gen_config; ASSERT_THAT(AddAeadKeyGenV0(key_gen_config), IsOk()); Configuration config; ASSERT_THAT(AddAeadV0(config), IsOk()); util::StatusOr> handle = KeysetHandle::GenerateNew(GetParam(), key_gen_config); ASSERT_THAT(handle, IsOk()); // Fails if using OpenSSL. if (!IsBoringSsl()) { EXPECT_THAT((*handle)->GetPrimitive(config), Not(IsOk())); return; } util::StatusOr> aead = (*handle)->GetPrimitive(config); ASSERT_THAT(aead, IsOk()); std::string plaintext = "plaintext"; util::StatusOr ciphertext = (*aead)->Encrypt(plaintext, "ad"); ASSERT_THAT(ciphertext, IsOk()); EXPECT_THAT((*aead)->Decrypt(*ciphertext, "ad"), IsOkAndHolds(plaintext)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/internal/cord_aes_gcm_boringssl.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/aead/internal/cord_aes_gcm_boringssl.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/cord.h" #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "tink/aead/cord_aead.h" #include "tink/aead/internal/aead_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/subtle/random.h" #include "tink/subtle/subtle_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { namespace { constexpr int kIvSizeInBytes = 12; constexpr int kTagSizeInBytes = 16; // Set the IV `iv` for the given `context`. if `encryption` is true, set the // context for encryption, and for decryption otherwise. util::Status SetIvAndDirection(EVP_CIPHER_CTX* context, absl::string_view iv, bool encryption) { const int encryption_flag = encryption ? 1 : 0; // Set the IV size. if (EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_SET_IVLEN, iv.size(), /*ptr=*/nullptr) <= 0) { return util::Status(absl::StatusCode::kInternal, "Failed to set the IV size"); } // Finally set the IV bytes. if (EVP_CipherInit_ex(context, /*cipher=*/nullptr, /*engine=*/nullptr, /*key=*/nullptr, reinterpret_cast(&iv[0]), /*enc=*/encryption_flag) <= 0) { return util::Status(absl::StatusCode::kInternal, "Failed to set the IV"); } return util::OkStatus(); } #if defined(OPENSSL_IS_BORINGSSL) || OPENSSL_VERSION_NUMBER < 0x30000000L // Returns a new EVP_CIPHER_CTX for encryption (`encryption` == true) or // decryption (`encryption` == false). It tries to skip part of the // initialization copying `partial_context`. util::StatusOr> NewContextFromPartial( EVP_CIPHER_CTX* partial_context, absl::string_view iv, bool encryption) { internal::SslUniquePtr context(EVP_CIPHER_CTX_new()); if (context == nullptr) { return util::Status(absl::StatusCode::kInternal, "EVP_CIPHER_CTX_new failed"); } // Try making a copy of `partial_context` to skip some pre-computations. // // NOTE: With BoringSSL and OpenSSL 1.1.1 EVP_CIPHER_CTX_copy makes a copy // of the `cipher_data` field of `context` as well, which contains the key // material and IV (see [1] and [2]). // // [1]https://github.com/google/boringssl/blob/4c8bcf0da2951cacd8ed8eaa7fd2df4b22fca23b/crypto/fipsmodule/cipher/cipher.c#L116 // [2]https://github.com/openssl/openssl/blob/830bf8e1e4749ad65c51b6a1d0d769ae689404ba/crypto/evp/evp_enc.c#L703 if (EVP_CIPHER_CTX_copy(context.get(), partial_context) <= 0) { return util::Status(absl::StatusCode::kInternal, "EVP_CIPHER_CTX_copy failed"); } util::Status res = SetIvAndDirection(context.get(), iv, /*encryption=*/encryption); if (!res.ok()) { return res; } return std::move(context); } #else // Returns a new EVP_CIPHER_CTX for encryption (`encryption` == true) or // decryption (`encryption` == false) with given `key` and `iv`. // // NOTE: Copying the context fails with OpenSSL 3.0, which doesn't provide a // `dupctx` function for aead ciphers (see [1], [2]). // // [1]https://github.com/openssl/openssl/blob/eb52450f5151e8e78743ab05de21a344823316f5/crypto/evp/evp_enc.c#L1427 // [2]https://github.com/openssl/openssl/blob/cac250755efd0c40cc6127a0e4baceb8d226c7e3/providers/implementations/include/prov/ciphercommon_aead.h#L30 util::StatusOr> NewContext( const util::SecretData& key, absl::string_view iv, bool encryption) { internal::SslUniquePtr context(EVP_CIPHER_CTX_new()); if (context == nullptr) { return util::Status(absl::StatusCode::kInternal, "EVP_CIPHER_CTX_new failed"); } util::StatusOr cipher = internal::GetAesGcmCipherForKeySize(key.size()); if (!cipher.ok()) { return cipher.status(); } if (EVP_CipherInit_ex(context.get(), *cipher, /*impl=*/nullptr, reinterpret_cast(key.data()), /*iv=*/nullptr, /*enc=*/1) <= 0) { return util::Status(absl::StatusCode::kInternal, "Context initialization failed"); } util::Status res = SetIvAndDirection(context.get(), iv, /*encryption=*/encryption); if (!res.ok()) { return res; } return std::move(context); } #endif } // namespace util::StatusOr> CordAesGcmBoringSsl::New( const util::SecretData& key_value) { util::StatusOr cipher = internal::GetAesGcmCipherForKeySize(key_value.size()); if (!cipher.ok()) { return cipher.status(); } internal::SslUniquePtr partial_context(EVP_CIPHER_CTX_new()); // Initialize a partial context for the cipher to allow OpenSSL/BoringSSL // making some precomputations on the key. Encrypt and Decrypt will try making // a copy of this context to avoid doing the same initializations again and to // guarantee thread safety. // // NOTE: It doesn't matter at this point if we set the direction to encryption // or decryption, it will be overwritten later any time we call // EVP_CipherInit_ex. if (EVP_CipherInit_ex(partial_context.get(), *cipher, /*engine=*/nullptr, reinterpret_cast(&key_value[0]), /*iv=*/nullptr, /*enc=*/1) <= 0) { return util::Status(absl::StatusCode::kInternal, "Context initialization failed"); } std::unique_ptr aead = absl::WrapUnique( new CordAesGcmBoringSsl(std::move(partial_context), key_value)); return std::move(aead); } util::StatusOr CordAesGcmBoringSsl::Encrypt( absl::Cord plaintext, absl::Cord associated_data) const { std::string iv = subtle::Random::GetRandomBytes(kIvSizeInBytes); #if defined(OPENSSL_IS_BORINGSSL) || OPENSSL_VERSION_NUMBER < 0x30000000L util::StatusOr> context = NewContextFromPartial(partial_context_.get(), iv, /*encryption=*/true); #else util::StatusOr> context = NewContext(key_, iv, /*encryption=*/true); #endif if (!context.ok()) { return context.status(); } int len = 0; // Process AAD. for (auto ad_chunk : associated_data.Chunks()) { if (!EVP_EncryptUpdate(context->get(), /*out=*/nullptr, &len, reinterpret_cast(ad_chunk.data()), ad_chunk.size())) { return util::Status(absl::StatusCode::kInternal, "Encryption failed"); } } char* buffer = std::allocator().allocate(plaintext.size()); absl::Cord ciphertext_buffer = absl::MakeCordFromExternal( absl::string_view(buffer, plaintext.size()), [](absl::string_view sv) { std::allocator().deallocate(const_cast(sv.data()), sv.size()); }); uint64_t ciphertext_buffer_offset = 0; for (auto plaintext_chunk : plaintext.Chunks()) { if (!EVP_EncryptUpdate( context->get(), reinterpret_cast(&(buffer[ciphertext_buffer_offset])), &len, reinterpret_cast(plaintext_chunk.data()), plaintext_chunk.size())) { return util::Status(absl::StatusCode::kInternal, "Encryption failed"); } ciphertext_buffer_offset += plaintext_chunk.size(); } if (!EVP_EncryptFinal_ex(context->get(), nullptr, &len)) { return util::Status(absl::StatusCode::kInternal, "Encryption failed"); } std::string tag; subtle::ResizeStringUninitialized(&tag, kTagSizeInBytes); if (!EVP_CIPHER_CTX_ctrl(context->get(), EVP_CTRL_GCM_GET_TAG, kTagSizeInBytes, reinterpret_cast(&tag[0]))) { return util::Status(absl::StatusCode::kInternal, "Encryption failed"); } // Create result cord absl::Cord result; result.Append(iv); result.Append(ciphertext_buffer); result.Append(tag); return result; } util::StatusOr CordAesGcmBoringSsl::Decrypt( absl::Cord ciphertext, absl::Cord associated_data) const { if (ciphertext.size() < kIvSizeInBytes + kTagSizeInBytes) { return util::Status(absl::StatusCode::kInternal, "Ciphertext too short"); } // First bytes contain the IV. std::string iv = std::string(ciphertext.Subcord(0, kIvSizeInBytes)); absl::Cord raw_ciphertext = ciphertext.Subcord( kIvSizeInBytes, ciphertext.size() - kIvSizeInBytes - kTagSizeInBytes); #if defined(OPENSSL_IS_BORINGSSL) || OPENSSL_VERSION_NUMBER < 0x30000000L util::StatusOr> context = NewContextFromPartial(partial_context_.get(), iv, /*encryption=*/false); #else util::StatusOr> context = NewContext(key_, iv, /*encryption=*/false); #endif if (!context.ok()) { return context.status(); } int len = 0; // Process associated data. for (auto ad_chunk : associated_data.Chunks()) { if (!EVP_DecryptUpdate(context->get(), /*out=*/nullptr, &len, reinterpret_cast(ad_chunk.data()), ad_chunk.size())) { return util::Status(absl::StatusCode::kInternal, "Decryption failed"); } } uint64_t plaintext_len = ciphertext.size() - kIvSizeInBytes - kTagSizeInBytes; char* plaintext_buffer = std::allocator().allocate(plaintext_len); uint64_t plaintext_buffer_offset = 0; absl::Cord result = absl::MakeCordFromExternal( absl::string_view(plaintext_buffer, plaintext_len), [](absl::string_view sv) { std::allocator().deallocate(const_cast(sv.data()), sv.size()); }); for (auto ct_chunk : raw_ciphertext.Chunks()) { if (!EVP_DecryptUpdate(context->get(), reinterpret_cast( &plaintext_buffer[plaintext_buffer_offset]), &len, reinterpret_cast(ct_chunk.data()), ct_chunk.size())) { return util::Status(absl::StatusCode::kInternal, "Decryption failed"); } plaintext_buffer_offset += ct_chunk.size(); } // Set expected tag value to last chunk in ciphertext Cord. std::string tag = std::string( ciphertext.Subcord(ciphertext.size() - kTagSizeInBytes, kTagSizeInBytes)); if (!EVP_CIPHER_CTX_ctrl(context->get(), EVP_CTRL_GCM_SET_TAG, kTagSizeInBytes, &tag[0])) { return util::Status(absl::StatusCode::kInternal, "Could not set authentication tag"); } // Verify authentication tag. if (!EVP_DecryptFinal_ex(context->get(), nullptr, &len)) { return util::Status(absl::StatusCode::kInternal, "Authentication failed"); } return result; } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/internal/cord_aes_gcm_boringssl.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_INTERNAL_CORD_AES_GCM_BORINGSSL_H_ #define TINK_AEAD_INTERNAL_CORD_AES_GCM_BORINGSSL_H_ #include #include #include "absl/strings/cord.h" #include "openssl/evp.h" #include "tink/aead/cord_aead.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { class CordAesGcmBoringSsl : public CordAead { public: static crypto::tink::util::StatusOr> New( const util::SecretData& key_value); crypto::tink::util::StatusOr Encrypt( absl::Cord plaintext, absl::Cord associated_data) const override; crypto::tink::util::StatusOr Decrypt( absl::Cord ciphertext, absl::Cord associated_data) const override; private: explicit CordAesGcmBoringSsl( internal::SslUniquePtr partial_context, const util::SecretData& key) : partial_context_(std::move(partial_context)), key_(key) {} // Partially-initialized EVP_CIPHER_CTX context that is copied for every // Encrypt/Decrypt operation. internal::SslUniquePtr partial_context_; util::SecretData key_; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_AEAD_INTERNAL_CORD_AES_GCM_BORINGSSL_H_ ================================================ FILE: cc/aead/internal/cord_aes_gcm_boringssl_test.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/internal/cord_aes_gcm_boringssl.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/cord.h" #include "absl/strings/cord_test_helpers.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "openssl/err.h" #include "include/rapidjson/document.h" #include "tink/aead.h" #include "tink/aead/cord_aead.h" #include "tink/subtle/aes_gcm_boringssl.h" #include "tink/subtle/wycheproof_util.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace internal { namespace { constexpr absl::string_view key_128 = "000102030405060708090a0b0c0d0e0f"; constexpr absl::string_view kMessage = "Some data to encrypt."; constexpr absl::string_view kLongMessage = "This is some long message which will be fragmented."; constexpr absl::string_view kAssociatedData = "Some associated data."; using ::crypto::tink::test::IsOk; using ::testing::Eq; using ::testing::Not; using ::testing::SizeIs; using ::testing::Test; class CordAesGcmBoringSslTest : public Test { protected: void SetUp() override { key_ = util::SecretDataFromStringView(absl::HexStringToBytes(key_128)); util::StatusOr> res = CordAesGcmBoringSsl::New(key_); ASSERT_THAT(res, IsOk()); cipher_ = std::move(*res); } util::SecretData key_; std::unique_ptr cipher_; }; TEST_F(CordAesGcmBoringSslTest, EncryptDecryptCord) { absl::Cord message_cord = absl::Cord(kMessage); absl::Cord associated_data_cord = absl::Cord(kAssociatedData); util::StatusOr ct = cipher_->Encrypt(message_cord, associated_data_cord); ASSERT_THAT(ct, IsOk()); EXPECT_THAT(*ct, SizeIs(message_cord.size() + 12 + 16)); util::StatusOr pt = cipher_->Decrypt(*ct, associated_data_cord); ASSERT_THAT(pt, IsOk()); EXPECT_EQ(*pt, message_cord.Flatten()); } TEST_F(CordAesGcmBoringSslTest, ChunkyCordEncrypt) { absl::Cord message_cord = absl::MakeFragmentedCord(absl::StrSplit(kLongMessage, absl::ByLength(3))); absl::Cord associated_data_cord = absl::Cord(kAssociatedData); util::StatusOr ct = cipher_->Encrypt(message_cord, associated_data_cord); ASSERT_THAT(ct, IsOk()); EXPECT_THAT(*ct, SizeIs(message_cord.size() + 12 + 16)); util::StatusOr pt = cipher_->Decrypt(*ct, associated_data_cord); ASSERT_THAT(pt, IsOk()); EXPECT_THAT(*pt, Eq(kLongMessage)); } TEST_F(CordAesGcmBoringSslTest, ChunkyCordDecrypt) { absl::Cord message_cord = absl::Cord(kLongMessage); absl::Cord associated_data_cord = absl::Cord(kAssociatedData); util::StatusOr ct = cipher_->Encrypt(message_cord, associated_data_cord); ASSERT_THAT(ct, IsOk()); absl::Cord fragmented_ct = absl::MakeFragmentedCord( absl::StrSplit(ct->Flatten(), absl::ByLength(3))); util::StatusOr pt = cipher_->Decrypt(fragmented_ct, associated_data_cord); ASSERT_THAT(pt, IsOk()); EXPECT_THAT(*pt, Eq(kLongMessage)); } TEST_F(CordAesGcmBoringSslTest, CanDecryptWithStringAead) { absl::Cord message_cord = absl::Cord(kMessage); absl::Cord associated_data_cord = absl::Cord(kAssociatedData); util::StatusOr ct = cipher_->Encrypt(message_cord, associated_data_cord); ASSERT_THAT(ct, IsOk()); EXPECT_EQ(ct->size(), message_cord.size() + 12 + 16); util::StatusOr pt = cipher_->Decrypt(*ct, associated_data_cord); ASSERT_THAT(pt, IsOk()); EXPECT_EQ(*pt, message_cord.Flatten()); // Decrypt as string and check if it gives same result. util::StatusOr> string_aead = subtle::AesGcmBoringSsl::New(key_); ASSERT_THAT(string_aead, IsOk()); util::StatusOr plaintext = (*string_aead) ->Decrypt(ct.value().Flatten(), associated_data_cord.Flatten()); ASSERT_THAT(plaintext, IsOk()); EXPECT_EQ(*plaintext, kMessage); } TEST_F(CordAesGcmBoringSslTest, ModifiedCord) { absl::Cord message = absl::Cord(kMessage); absl::Cord ad = absl::Cord(kAssociatedData); util::StatusOr ct = cipher_->Encrypt(message, ad); ASSERT_THAT(ct, IsOk()); util::StatusOr plaintext = cipher_->Decrypt(*ct, ad); ASSERT_THAT(plaintext, IsOk()); EXPECT_EQ(*plaintext, message); // Modify the ciphertext. for (size_t i = 0; i < ct->size() * 8; i++) { std::string modified_ct = std::string(ct->Flatten()); modified_ct[i / 8] ^= 1 << (i % 8); absl::Cord modified_ct_cord; modified_ct_cord = absl::Cord(modified_ct); EXPECT_THAT(cipher_->Decrypt(modified_ct_cord, ad), Not(IsOk())) << i; } // Modify the associated data. for (size_t i = 0; i < ad.size() * 8; i++) { std::string modified_ad = std::string(ad.Flatten()); modified_ad[i / 8] ^= 1 << (i % 8); absl::Cord modified_associated_data_cord; modified_associated_data_cord = absl::Cord(modified_ad); util::StatusOr decrypted = cipher_->Decrypt(*ct, modified_associated_data_cord); EXPECT_THAT(decrypted, Not(IsOk())) << i << " pt: " << *decrypted; } // Truncate the ciphertext. for (size_t i = 0; i < ct->size(); i++) { std::string truncated_ct(std::string(ct->Flatten()), 0, i); absl::Cord truncated_ct_cord; truncated_ct_cord = absl::Cord(truncated_ct); EXPECT_THAT(cipher_->Decrypt(truncated_ct_cord, ad), Not(IsOk())) << i; } } static std::string GetError() { auto err = ERR_peek_last_error(); // Sometimes there is no error message on the stack. if (err == 0) { return ""; } std::string lib(ERR_lib_error_string(err)); std::string func(ERR_func_error_string(err)); std::string reason(ERR_reason_error_string(err)); return lib + ":" + func + ":" + reason; } // Test with test vectors from Wycheproof project. bool WycheproofTest(const rapidjson::Document& root) { int errors = 0; for (const rapidjson::Value& test_group : root["testGroups"].GetArray()) { const size_t iv_size = test_group["ivSize"].GetInt(); const size_t key_size = test_group["keySize"].GetInt(); const size_t tag_size = test_group["tagSize"].GetInt(); // CordAesGcmBoringSsl only supports 12-byte IVs and 16-byte // authentication tag. Also 24-byte keys are not supported. if (iv_size != 96 || tag_size != 128 || key_size == 192) { // Not supported continue; } for (const rapidjson::Value& test : test_group["tests"].GetArray()) { std::string comment = test["comment"].GetString(); std::string key = subtle::WycheproofUtil::GetBytes(test["key"]); std::string iv = subtle::WycheproofUtil::GetBytes(test["iv"]); std::string msg = subtle::WycheproofUtil::GetBytes(test["msg"]); std::string ct = subtle::WycheproofUtil::GetBytes(test["ct"]); std::string ad = subtle::WycheproofUtil::GetBytes(test["aad"]); std::string tag = subtle::WycheproofUtil::GetBytes(test["tag"]); std::string id = absl::StrCat(test["tcId"].GetInt()); std::string expected = test["result"].GetString(); std::unique_ptr cipher = std::move( *CordAesGcmBoringSsl::New(util::SecretDataFromStringView(key))); // Convert the ciphertext to cord. absl::Cord ct_cord = absl::Cord(iv + ct + tag); absl::Cord associated_data_cord = absl::Cord(ad); util::StatusOr result = cipher->Decrypt(ct_cord, associated_data_cord); if (result.ok()) { std::string decrypted = std::string(result->Flatten()); if (expected == "invalid") { ADD_FAILURE() << "Decrypted invalid ciphertext:" << id; errors++; } else if (msg != decrypted) { ADD_FAILURE() << "Incorrect decryption:" << id; errors++; } } else { if (expected == "valid" || expected == "acceptable") { ADD_FAILURE() << "Could not decrypt test with tcId:" << id << " iv_size:" << iv_size << " tag_size:" << tag_size << " key_size:" << key_size << " error:" << GetError(); errors++; } } } } return errors == 0; } TEST(CordAesGcmBoringSslWycheproofTest, TestVectors) { std::unique_ptr root = subtle::WycheproofUtil::ReadTestVectors("aes_gcm_test.json"); ASSERT_TRUE(WycheproofTest(*root)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/internal/key_gen_config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/internal/key_gen_config_v0.h" #include "absl/memory/memory.h" #include "tink/aead/aes_ctr_hmac_aead_key_manager.h" #include "tink/aead/aes_eax_key_manager.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/aead/aes_gcm_siv_key_manager.h" #include "tink/aead/xchacha20_poly1305_key_manager.h" #include "tink/internal/key_gen_configuration_impl.h" #include "tink/key_gen_configuration.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { util::Status AddAeadKeyGenV0(KeyGenConfiguration& config) { // TODO(b/296630956): Alphabetize in all AEAD config files. util::Status status = internal::KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); if (!status.ok()) { return status; } status = internal::KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); if (!status.ok()) { return status; } status = internal::KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); if (!status.ok()) { return status; } status = internal::KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); if (!status.ok()) { return status; } return internal::KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/internal/key_gen_config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_INTERNAL_KEY_GEN_CONFIG_V0_H_ #define TINK_AEAD_INTERNAL_KEY_GEN_CONFIG_V0_H_ #include "tink/key_gen_configuration.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { // Add recommended AEAD key managers to `config`, used to generate keys. util::Status AddAeadKeyGenV0(KeyGenConfiguration& config); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_AEAD_INTERNAL_KEY_GEN_CONFIG_V0_H_ ================================================ FILE: cc/aead/internal/mock_zero_copy_aead.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_INTERNAL_MOCK_ZERO_COPY_AEAD_H_ #define TINK_AEAD_INTERNAL_MOCK_ZERO_COPY_AEAD_H_ #include #include "gmock/gmock.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "tink/aead/internal/zero_copy_aead.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { class MockZeroCopyAead : public ZeroCopyAead { public: ~MockZeroCopyAead() override = default; MOCK_METHOD(int64_t, MaxEncryptionSize, (int64_t plaintext_size), (const, override)); MOCK_METHOD(crypto::tink::util::StatusOr, Encrypt, (absl::string_view plaintext, absl::string_view associated_data, absl::Span buffer), (const, override)); MOCK_METHOD(int64_t, MaxDecryptionSize, (int64_t ciphertext_size), (const, override)); MOCK_METHOD(crypto::tink::util::StatusOr, Decrypt, (absl::string_view ciphertext, absl::string_view associated_data, absl::Span buffer), (const, override)); }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_AEAD_INTERNAL_MOCK_ZERO_COPY_AEAD_H_ ================================================ FILE: cc/aead/internal/ssl_aead.cc ================================================ // Copyright 2021 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/aead/internal/ssl_aead.h" #include #include #include #include #include #include #include #include "absl/base/attributes.h" #include "absl/cleanup/cleanup.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "openssl/crypto.h" #include "openssl/evp.h" #include "tink/aead/internal/aead_util.h" #include "tink/internal/call_with_core_dump_protection.h" #include "tink/internal/err_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/internal/util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { ABSL_CONST_INIT const int kXchacha20Poly1305TagSizeInBytes = 16; ABSL_CONST_INIT const int kAesGcmTagSizeInBytes = 16; ABSL_CONST_INIT const int kAesGcmSivTagSizeInBytes = 16; namespace { // Encrypts/Decrypts `data` and writes the result into `out`. The direction // (encrypt/decrypt) is given by `context`. `out` is assumed to be large enough // to hold the encrypted/decrypted content. util::StatusOr UpdateCipher(EVP_CIPHER_CTX *context, absl::string_view data, absl::Span out) { // We encrypt/decrypt in chunks of at most MAX int. const int64_t kMaxChunkSize = std::numeric_limits::max(); // Keep track of the bytes written to out. int64_t total_written_bytes = 0; // In practical cases data.size() is assumed to fit into a int64_t. int64_t left_to_update = data.size(); while (left_to_update > 0) { const int chunk_size = std::min(kMaxChunkSize, left_to_update); auto *buffer_ptr = reinterpret_cast(out.data() + total_written_bytes); absl::string_view data_chunk = data.substr(total_written_bytes, chunk_size); int written_bytes = 0; if (EVP_CipherUpdate(context, buffer_ptr, &written_bytes, reinterpret_cast(data_chunk.data()), data_chunk.size()) <= 0) { const bool is_encrypting = EVP_CIPHER_CTX_encrypting(context) == 1; return util::Status( absl::StatusCode::kInternal, absl::StrCat(is_encrypting ? "Encryption" : "Decryption", " failed")); } left_to_update -= written_bytes; total_written_bytes += written_bytes; } return total_written_bytes; } class OpenSslOneShotAeadImpl : public SslOneShotAead { public: explicit OpenSslOneShotAeadImpl(const util::SecretData &key, const EVP_CIPHER *cipher, size_t tag_size) : key_(key), cipher_(cipher), tag_size_(tag_size) {} util::StatusOr Encrypt(absl::string_view plaintext, absl::string_view associated_data, absl::string_view iv, absl::Span out) const override { absl::string_view plaintext_data = internal::EnsureStringNonNull(plaintext); absl::string_view ad = internal::EnsureStringNonNull(associated_data); const int64_t min_out_buff_size = CiphertextSize(plaintext.size()); if (out.size() < min_out_buff_size) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Encryption buffer too small; expected at least ", min_out_buff_size, " bytes, got ", out.size())); } if (BuffersOverlap(plaintext, absl::string_view(out.data(), out.size()))) { return util::Status(absl::StatusCode::kInvalidArgument, "Plaintext and output buffer must not overlap"); } if (associated_data.size() > std::numeric_limits::max()) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Associated data too large; expected at most ", std::numeric_limits::max(), " got ", associated_data.size())); } return internal::CallWithCoreDumpProtection( [&]() { return EncryptSensitive(plaintext_data, ad, iv, out); }); } util::StatusOr Decrypt(absl::string_view ciphertext, absl::string_view associated_data, absl::string_view iv, absl::Span out) const override { absl::string_view ad = internal::EnsureStringNonNull(associated_data); if (ciphertext.size() < tag_size_) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Ciphertext buffer too small; expected at least ", tag_size_, " got ", ciphertext.size())); } const int64_t min_out_buff_size = PlaintextSize(ciphertext.size()); if (out.size() < min_out_buff_size) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Output buffer too small; expected at least ", min_out_buff_size, " got ", out.size())); } if (BuffersOverlap(ciphertext, absl::string_view(out.data(), out.size()))) { return util::Status(absl::StatusCode::kInvalidArgument, "Ciphertext and output buffer must not overlap"); } if (associated_data.size() > std::numeric_limits::max()) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Associated data too large; expected at most ", std::numeric_limits::max(), " got ", associated_data.size())); } return internal::CallWithCoreDumpProtection( [&]() { return DecryptSensitive(ciphertext, ad, iv, out); }); } int64_t CiphertextSize(int64_t plaintext_length) const override { return plaintext_length + tag_size_; } int64_t PlaintextSize(int64_t ciphertext_length) const override { if (ciphertext_length < tag_size_) { return 0; } return ciphertext_length - tag_size_; } private: util::StatusOr EncryptSensitive(absl::string_view plaintext_data, absl::string_view ad, absl::string_view iv, absl::Span out) const { util::StatusOr> context = GetContext(iv, /*encryption=*/true); if (!context.ok()) { return context.status(); } // Set the associated data. int len = 0; if (EVP_EncryptUpdate(context->get(), /*out=*/nullptr, &len, reinterpret_cast(ad.data()), ad.size()) <= 0) { return util::Status(absl::StatusCode::kInternal, "Failed to set associated data"); } util::StatusOr raw_ciphertext_bytes = UpdateCipher(context->get(), plaintext_data, out); if (!raw_ciphertext_bytes.ok()) { return raw_ciphertext_bytes.status(); } if (EVP_EncryptFinal_ex(context->get(), /*out=*/nullptr, &len) <= 0) { return util::Status(absl::StatusCode::kInternal, "Finalization failed"); } // Write the tag after the ciphertext. absl::Span tag = out.subspan(*raw_ciphertext_bytes, tag_size_); if (EVP_CIPHER_CTX_ctrl(context->get(), EVP_CTRL_AEAD_GET_TAG, tag_size_, reinterpret_cast(tag.data())) <= 0) { return util::Status(absl::StatusCode::kInternal, "Failed to get the tag"); } return *raw_ciphertext_bytes + tag_size_; } util::StatusOr DecryptSensitive(absl::string_view ciphertext, absl::string_view ad, absl::string_view iv, absl::Span out) const { util::StatusOr> context = GetContext(iv, /*encryption=*/false); if (!context.ok()) { return context.status(); } int len = 0; // Add the associated data. if (EVP_DecryptUpdate(context->get(), /*out=*/nullptr, &len, reinterpret_cast(ad.data()), ad.size()) <= 0) { return util::Status(absl::StatusCode::kInternal, "Failed to set associated_data"); } const int64_t raw_ciphertext_size = ciphertext.size() - tag_size_; // "Unpack" the ciphertext. absl::string_view raw_ciphertext = ciphertext.substr(0, raw_ciphertext_size); // This copy is needed since EVP_CIPHER_CTX_ctrl requires a non-const // pointer even if the EVP_CTRL_AEAD_SET_TAG operation doesn't modify the // content of the buffer. auto tag = std::string(ciphertext.substr(raw_ciphertext_size, tag_size_)); // Set the tag. if (EVP_CIPHER_CTX_ctrl(context->get(), EVP_CTRL_AEAD_SET_TAG, tag_size_, reinterpret_cast(&tag[0])) <= 0) { return util::Status(absl::StatusCode::kInternal, "Could not set authentication tag"); } // If out.empty() accessing the 0th element would result in an out of // bound violation. This makes sure we pass a pointer to at least one byte // when calling into OpenSSL. char buffer_if_size_is_zero = '\0'; auto out_buffer = absl::Span(&buffer_if_size_is_zero, /*length=*/1); if (!out.empty()) { const int64_t min_out_buff_size = PlaintextSize(ciphertext.size()); out_buffer = out.subspan(0, min_out_buff_size - tag_size_); } // Zero the plaintext buffer in case decryption fails before returning an // error. auto output_eraser = absl::MakeCleanup([out] { OPENSSL_cleanse(out.data(), out.size()); }); util::StatusOr written_bytes = UpdateCipher(context->get(), raw_ciphertext, out_buffer); if (!written_bytes.ok()) { return written_bytes.status(); } if (!EVP_DecryptFinal_ex(context->get(), /*out=*/nullptr, &len)) { return util::Status(absl::StatusCode::kInternal, "Authentication failed"); } // Decryption executed correctly, cancel cleanup on the output buffer. std::move(output_eraser).Cancel(); return *written_bytes; } // Returns a new EVP_CIPHER_CTX for encryption (`ecryption` == true) or // decryption (`encryption` == false). util::StatusOr> GetContext( absl::string_view iv, bool encryption) const { internal::SslUniquePtr context(EVP_CIPHER_CTX_new()); if (context == nullptr) { return util::Status(absl::StatusCode::kInternal, "EVP_CIPHER_CTX_new failed"); } const int encryption_flag = encryption ? 1 : 0; if (EVP_CipherInit_ex(context.get(), cipher_, /*impl=*/nullptr, /*key=*/nullptr, /*iv=*/nullptr, encryption_flag) <= 0) { return util::Status( absl::StatusCode::kInternal, absl::StrCat("Failed initializializing context for ", encryption ? "encryption" : "decryption")); } // Set the size for IV first, then set the IV bytes. if (EVP_CIPHER_CTX_ctrl(context.get(), EVP_CTRL_AEAD_SET_IVLEN, iv.size(), /*ptr=*/nullptr) <= 0) { return util::Status( absl::StatusCode::kInternal, absl::StrCat("Failed stting size of the IV to ", iv.size())); } if (EVP_CipherInit_ex(context.get(), /*cipher=*/nullptr, /*impl=*/nullptr, reinterpret_cast(key_.data()), reinterpret_cast(iv.data()), encryption_flag) <= 0) { return util::Status( absl::StatusCode::kInternal, absl::StrCat("Failed to set key of size ", key_.size(), "and IV of size ", iv.size())); } return std::move(context); } const util::SecretData key_; const EVP_CIPHER *cipher_; const size_t tag_size_; }; #ifdef OPENSSL_IS_BORINGSSL // Implementation of the one-shot AEAD cypter. This is purposely internal to // an anonymous namespace to disallow direct use of this class other than // through the Create* functions below. class BoringSslOneShotAeadImpl : public SslOneShotAead { public: explicit BoringSslOneShotAeadImpl( internal::SslUniquePtr context, size_t tag_size) : context_(std::move(context)), tag_size_(tag_size) {} util::StatusOr Encrypt(absl::string_view plaintext, absl::string_view associated_data, absl::string_view iv, absl::Span out) const override { // BoringSSL expects a non-null pointer for associated_data, // regardless of whether the size is 0. plaintext = internal::EnsureStringNonNull(plaintext); associated_data = internal::EnsureStringNonNull(associated_data); iv = internal::EnsureStringNonNull(iv); if (BuffersOverlap(plaintext, absl::string_view(out.data(), out.size()))) { return util::Status(absl::StatusCode::kInvalidArgument, "Plaintext and output buffer must not overlap"); } const int64_t min_out_buff_size = CiphertextSize(plaintext.size()); if (out.size() < min_out_buff_size) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Output buffer too small; expected at least ", min_out_buff_size, " got ", out.size())); } return internal::CallWithCoreDumpProtection([&]() { return EncryptSensitive(plaintext, associated_data, iv, out); }); } util::StatusOr EncryptSensitive(absl::string_view plaintext, absl::string_view associated_data, absl::string_view iv, absl::Span out) const { size_t out_len = 0; if (!EVP_AEAD_CTX_seal( context_.get(), reinterpret_cast(&out[0]), &out_len, out.size(), reinterpret_cast(iv.data()), iv.size(), reinterpret_cast(plaintext.data()), plaintext.size(), /*ad=*/ reinterpret_cast(associated_data.data()), /*ad_len=*/associated_data.size())) { return util::Status( absl::StatusCode::kInternal, absl::StrCat("Encryption failed: ", internal::GetSslErrors())); } return out_len; } util::StatusOr Decrypt(absl::string_view ciphertext, absl::string_view associated_data, absl::string_view iv, absl::Span out) const override { ciphertext = internal::EnsureStringNonNull(ciphertext); associated_data = internal::EnsureStringNonNull(associated_data); iv = internal::EnsureStringNonNull(iv); if (BuffersOverlap(ciphertext, absl::string_view(out.data(), out.size()))) { return util::Status(absl::StatusCode::kInvalidArgument, "Ciphertext and output buffer must not overlap"); } if (ciphertext.size() < tag_size_) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Ciphertext buffer too small; expected at least ", tag_size_, " got ", ciphertext.size())); } const int64_t min_out_buff_size = PlaintextSize(ciphertext.size()); if (out.size() < min_out_buff_size) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Output buffer too small; expected at least ", min_out_buff_size, " got ", out.size())); } return internal::CallWithCoreDumpProtection([&]() { return DecryptSensitive(ciphertext, associated_data, iv, out); }); } util::StatusOr DecryptSensitive(absl::string_view ciphertext, absl::string_view associated_data, absl::string_view iv, absl::Span out) const { // If out.empty() accessing the 0th element would result in an out of // bound violation. This makes sure we pass a pointer to at least one byte // when calling into OpenSSL. uint8_t buffer_if_size_is_zero; uint8_t *buffer_ptr = &buffer_if_size_is_zero; if (!out.empty()) { buffer_ptr = reinterpret_cast(&out[0]); } size_t out_len = 0; if (!EVP_AEAD_CTX_open( context_.get(), buffer_ptr, &out_len, out.size(), reinterpret_cast(iv.data()), iv.size(), reinterpret_cast(ciphertext.data()), ciphertext.size(), /*ad=*/ reinterpret_cast(associated_data.data()), /*ad_len=*/associated_data.size())) { return util::Status( absl::StatusCode::kInternal, absl::StrCat("Authentication failed: ", internal::GetSslErrors())); } return out_len; } int64_t CiphertextSize(int64_t plaintext_length) const override { return plaintext_length + tag_size_; } int64_t PlaintextSize(int64_t ciphertext_length) const override { if (ciphertext_length < tag_size_) { return 0; } return ciphertext_length - tag_size_; } private: const internal::SslUniquePtr context_; const size_t tag_size_; }; #endif } // namespace util::StatusOr> CreateAesGcmOneShotCrypter( const util::SecretData &key) { #ifdef OPENSSL_IS_BORINGSSL util::StatusOr aead_cipher = GetAesGcmAeadForKeySize(key.size()); if (!aead_cipher.ok()) { return aead_cipher.status(); } internal::SslUniquePtr context( internal::CallWithCoreDumpProtection([&]() { return EVP_AEAD_CTX_new(*aead_cipher, key.data(), key.size(), kAesGcmTagSizeInBytes); })); if (context == nullptr) { return util::Status( absl::StatusCode::kInternal, absl::StrCat("EVP_AEAD_CTX_new failed: ", internal::GetSslErrors())); } return {absl::make_unique(std::move(context), kAesGcmTagSizeInBytes)}; #else util::StatusOr aead_cipher = GetAesGcmCipherForKeySize(key.size()); if (!aead_cipher.ok()) { return aead_cipher.status(); } return absl::make_unique(key, *aead_cipher, kAesGcmTagSizeInBytes); #endif } util::StatusOr> CreateAesGcmSivOneShotCrypter( const util::SecretData &key) { #ifdef OPENSSL_IS_BORINGSSL util::StatusOr aead_cipher = GetAesGcmSivAeadCipherForKeySize(key.size()); if (!aead_cipher.ok()) { return aead_cipher.status(); } internal::SslUniquePtr context( internal::CallWithCoreDumpProtection([&]() { return EVP_AEAD_CTX_new(*aead_cipher, key.data(), key.size(), kAesGcmTagSizeInBytes); })); if (context == nullptr) { return util::Status(absl::StatusCode::kInternal, absl::StrCat("EVP_AEAD_CTX_new initialization Failed: ", internal::GetSslErrors())); } return {absl::make_unique( std::move(context), kAesGcmSivTagSizeInBytes)}; #else return util::Status(absl::StatusCode::kUnimplemented, "AES-GCM-SIV is unimplemented for OpenSSL"); #endif } util::StatusOr> CreateXchacha20Poly1305OneShotCrypter(const util::SecretData &key) { #ifdef OPENSSL_IS_BORINGSSL if (key.size() != 32) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid key size; valid values are {32} bytes, got ", key.size())); } internal::SslUniquePtr context( internal::CallWithCoreDumpProtection([&]() { return EVP_AEAD_CTX_new(EVP_aead_xchacha20_poly1305(), key.data(), key.size(), kAesGcmTagSizeInBytes); })); if (context == nullptr) { return util::Status(absl::StatusCode::kInternal, absl::StrCat("EVP_AEAD_CTX_new initialization Failed: ", internal::GetSslErrors())); } return {absl::make_unique( std::move(context), kXchacha20Poly1305TagSizeInBytes)}; #else return util::Status(absl::StatusCode::kUnimplemented, "Xchacha20-Poly1305 is unimplemented for OpenSSL"); #endif } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/internal/ssl_aead.h ================================================ // Copyright 2021 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_INTERNAL_SSL_AEAD_H_ #define TINK_AEAD_INTERNAL_SSL_AEAD_H_ #include #include #include "absl/base/attributes.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { // Tag sizes. ABSL_CONST_INIT extern const int kXchacha20Poly1305TagSizeInBytes; ABSL_CONST_INIT extern const int kAesGcmTagSizeInBytes; ABSL_CONST_INIT extern const int kAesGcmSivTagSizeInBytes; // Interface for one-shot AEAD crypters. class SslOneShotAead { public: virtual ~SslOneShotAead() = default; // Returns the size of the ciphertext from `plaintext_length`. virtual int64_t CiphertextSize(int64_t plaintext_length) const = 0; // Encrypts `plaintext` with `associated_data` and `iv`, and writes the output // to `out`. The implementation places both the raw ciphertext and the // resulting tag in `out`, so the caller must make sure it has sufficient // capacity. There should be no overlap between `plaintext` and `out`. In // particular, in-place encryption is not supported. virtual util::StatusOr Encrypt(absl::string_view plaintext, absl::string_view associated_data, absl::string_view iv, absl::Span out) const = 0; // Returns the size of the plaintext given `ciphertext_length`. This is always // >= 0. virtual int64_t PlaintextSize(int64_t ciphertext_length) const = 0; // Decrypts `ciphertext` with `associated_data` and `iv`, and writes the // plaintext to `out`. `ciphertext` contains the raw ciphertext and the tag. // There should be no overlap between `ciphertext` and `out`. In particular, // in-place decryption is not supported. virtual util::StatusOr Decrypt(absl::string_view ciphertext, absl::string_view associated_data, absl::string_view iv, absl::Span out) const = 0; }; // Create one-shot crypters for the supported algorithms. util::StatusOr> CreateAesGcmOneShotCrypter( const util::SecretData &key); util::StatusOr> CreateAesGcmSivOneShotCrypter( const util::SecretData &key); util::StatusOr> CreateXchacha20Poly1305OneShotCrypter(const util::SecretData &key); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_AEAD_INTERNAL_SSL_AEAD_H_ ================================================ FILE: cc/aead/internal/ssl_aead_large_inputs_test.cc ================================================ // Copyright 2021 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_set.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "tink/aead/internal/ssl_aead.h" #include "tink/config/tink_fips.h" #include "tink/internal/ssl_util.h" #include "tink/internal/util.h" #include "tink/subtle/subtle_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" // We test SslOneShotAead implementations against a very large input. namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::testing::TestWithParam; constexpr absl::string_view kAad = "Some data to authenticate."; // 128 bits key. constexpr absl::string_view k128Key = "000102030405060708090a0b0c0d0e0f"; // 256 bits key. constexpr absl::string_view k256Key = "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"; // 12 bytes IV. constexpr absl::string_view kAesGcmIvHex = "0123456789012345678901234"; // 24 bytes IV. constexpr absl::string_view kXchacha20Poly1305IvHex = "012345678901234567890123456789012345678901234567"; struct TestParams { std::string test_name; std::string cipher; int tag_size; absl::string_view iv_hex; absl::string_view key_hex; }; // Returns a SslOneShotAead from `cipher_name` and `key`. util::StatusOr> CipherFromName( absl::string_view cipher, const util::SecretData& key) { if (cipher == "aes_gcm") { return CreateAesGcmOneShotCrypter(key); } if (cipher == "aes_gcm_siv") { return CreateAesGcmSivOneShotCrypter(key); } if (cipher == "xchacha20_poly1305") { return CreateXchacha20Poly1305OneShotCrypter(key); } return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid cipher ", cipher)); } using SslOneShotAeadLargeInputsTest = TestWithParam; // Encrypt/decrypt with an input larger than a MAX int. TEST_P(SslOneShotAeadLargeInputsTest, EncryptDecryptLargeInput) { if (IsWindows()) { GTEST_SKIP() << "Skipping on Windows: this currently times out"; } const int64_t buff_size = static_cast(std::numeric_limits::max()) + 1024; std::string large_input(buff_size, '0'); TestParams test_param = GetParam(); util::StatusOr> aead = CipherFromName( test_param.cipher, util::SecretDataFromStringView( absl::HexStringToBytes(test_param.key_hex))); ASSERT_THAT(aead, IsOk()); std::string iv = absl::HexStringToBytes(test_param.iv_hex); std::string ciphertext_buffer; // Length of the message + tag. subtle::ResizeStringUninitialized( &ciphertext_buffer, (*aead)->CiphertextSize(large_input.size())); // Encrypt. ASSERT_GE(ciphertext_buffer.size(), large_input.size() + test_param.tag_size); util::StatusOr res = (*aead)->Encrypt( large_input, kAad, iv, absl::MakeSpan(ciphertext_buffer)); ASSERT_THAT(res, IsOk()); EXPECT_EQ(*res, large_input.size() + test_param.tag_size); // Decrypt. std::string plaintext_buff; subtle::ResizeStringUninitialized(&plaintext_buff, large_input.size()); util::StatusOr written_bytes = (*aead)->Decrypt( ciphertext_buffer, kAad, iv, absl::MakeSpan(plaintext_buff)); ASSERT_THAT(written_bytes, IsOk()); EXPECT_EQ(*written_bytes, large_input.size()); EXPECT_EQ(plaintext_buff, large_input); } std::vector GetTestParams() { std::vector params = { {/*test_name=*/"AesGcm256", /*cipher=*/"aes_gcm", /*tag_size=*/kAesGcmTagSizeInBytes, /*iv_hex=*/kAesGcmIvHex, /*key_hex=*/k256Key}, {/*test_name=*/"AesGcm128", /*cipher=*/"aes_gcm", /*tag_size=*/kAesGcmTagSizeInBytes, /*iv_hex=*/kAesGcmIvHex, /*key_hex=*/k128Key}}; if (IsBoringSsl()) { params.push_back({/*test_name=*/"AesGcmSiv256", /*cipher=*/"aes_gcm_siv", /*tag_size=*/kAesGcmTagSizeInBytes, /*iv_hex=*/kAesGcmIvHex, /*key_hex=*/k256Key}); params.push_back({/*test_name=*/"AesGcmSiv128", /*cipher=*/"aes_gcm_siv", /*tag_size=*/kAesGcmTagSizeInBytes, /*iv_hex=*/kAesGcmIvHex, /*key_hex=*/k128Key}); params.push_back({/*test_name=*/"Xchacha20Poly1305", /*cipher=*/"xchacha20_poly1305", /*tag_size=*/kXchacha20Poly1305TagSizeInBytes, /*iv_hex=*/kXchacha20Poly1305IvHex, /*key_hex=*/k256Key}); } return params; } INSTANTIATE_TEST_SUITE_P( SslOneShotAeadLargeInputsTests, SslOneShotAeadLargeInputsTest, testing::ValuesIn(GetTestParams()), [](const testing::TestParamInfo& info) { return info.param.test_name; }); } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/internal/ssl_aead_test.cc ================================================ // Copyright 2021 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/aead/internal/ssl_aead.h" #include #include #include #include #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_set.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "tink/aead/internal/wycheproof_aead.h" #include "tink/internal/fips_utils.h" #include "tink/internal/ssl_util.h" #include "tink/subtle/subtle_util.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::AllOf; using ::testing::Eq; using ::testing::Not; using ::testing::TestParamInfo; using ::testing::TestWithParam; using ::testing::ValuesIn; constexpr absl::string_view kMessage = "Some data to encrypt."; constexpr absl::string_view kAssociatedData = "Some associated data."; // 128 bits key. constexpr absl::string_view k128Key = "000102030405060708090a0b0c0d0e0f"; // 256 bits key. constexpr absl::string_view k256Key = "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"; // 12 bytes IV. constexpr absl::string_view kAesGcmIvHex = "0123456789012345678901234"; // 24 bytes IV. constexpr absl::string_view kXchacha20Poly1305IvHex = "012345678901234567890123456789012345678901234567"; enum CipherType { kAesGcm, kAesGcmSiv, kXchacha20Poly1305, }; struct SslOneShotAeadTestParams { std::string test_name; CipherType cipher; int tag_size; absl::string_view iv_hex; absl::string_view key_hex; }; // Returns a SslOneShotAead from `cipher_name` and `key`. util::StatusOr> CipherFromName( CipherType cipher, const util::SecretData& key) { switch (cipher) { case CipherType::kAesGcm: { return CreateAesGcmOneShotCrypter(key); } case CipherType::kAesGcmSiv: { return CreateAesGcmSivOneShotCrypter(key); } case CipherType::kXchacha20Poly1305: { return CreateXchacha20Poly1305OneShotCrypter(key); } } } using SslOneShotAeadTest = TestWithParam; TEST_P(SslOneShotAeadTest, CiphertextPlaintextSize) { SslOneShotAeadTestParams test_param = GetParam(); util::StatusOr> aead = CipherFromName( test_param.cipher, util::SecretDataFromStringView( absl::HexStringToBytes(test_param.key_hex))); ASSERT_THAT(aead, IsOk()); EXPECT_EQ((*aead)->CiphertextSize(kMessage.size()), kMessage.size() + test_param.tag_size); EXPECT_EQ((*aead)->PlaintextSize(kMessage.size() + test_param.tag_size), kMessage.size()); // Minimum size. EXPECT_EQ((*aead)->PlaintextSize(test_param.tag_size), 0); // Smaller than the minumum. EXPECT_EQ((*aead)->PlaintextSize(0), 0); } // Tests that encryption of `message` with `associated_data`, and `iv` succeeds; // writes the result in `ciphertext_buffer`. void DoTestEncrypt(SslOneShotAead* aead, absl::string_view message, absl::string_view associated_data, size_t tag_size, absl::string_view iv, absl::Span ciphertext_buffer) { ASSERT_GE(ciphertext_buffer.size(), message.size() + tag_size); util::StatusOr res = aead->Encrypt( message, associated_data, iv, absl::MakeSpan(ciphertext_buffer)); ASSERT_THAT(res, IsOk()); EXPECT_EQ(*res, message.size() + tag_size); } // Tests that decryption of `ciphertext_buffer` with `associated_data` and `iv` // succeeds and equals `message`. void DoTestDecrypt(SslOneShotAead* aead, absl::string_view message, absl::string_view associated_data, absl::string_view iv, absl::string_view ciphertext_buffer) { std::string plaintext_buff; subtle::ResizeStringUninitialized(&plaintext_buff, message.size()); util::StatusOr written_bytes = aead->Decrypt( ciphertext_buffer, associated_data, iv, absl::MakeSpan(plaintext_buff)); ASSERT_THAT(written_bytes, IsOk()); EXPECT_EQ(*written_bytes, message.size()); EXPECT_EQ(plaintext_buff, message); } TEST_P(SslOneShotAeadTest, EncryptDecrypt) { SslOneShotAeadTestParams test_param = GetParam(); util::StatusOr> aead = CipherFromName( test_param.cipher, util::SecretDataFromStringView( absl::HexStringToBytes(test_param.key_hex))); ASSERT_THAT(aead, IsOk()); std::string iv = absl::HexStringToBytes(test_param.iv_hex); std::string ciphertext_buffer; // Length of the message + tag. subtle::ResizeStringUninitialized(&ciphertext_buffer, (*aead)->CiphertextSize(kMessage.size())); DoTestEncrypt(aead->get(), kMessage, kAssociatedData, test_param.tag_size, iv, absl::MakeSpan(ciphertext_buffer)); DoTestDecrypt(aead->get(), kMessage, kAssociatedData, iv, ciphertext_buffer); } // Calculates a new string with the `position`'s byte modified. std::string ModifyString(absl::string_view input_str, int position) { std::string modified(input_str.data(), input_str.size()); modified[position / 8] ^= 1 << (position % 8); return modified; } // Tests encryption/decryption with a modified ciphertext. void DoTestEncryptDecryptWithModifiedCiphertext(SslOneShotAead* aead, size_t tag_size, absl::string_view iv) { std::string ciphertext_buffer; // Length of the message + tag. subtle::ResizeStringUninitialized(&ciphertext_buffer, kMessage.size() + tag_size); util::StatusOr written_bytes = aead->Encrypt( kMessage, kAssociatedData, iv, absl::MakeSpan(ciphertext_buffer)); ASSERT_THAT(written_bytes, IsOk()); EXPECT_EQ(*written_bytes, kMessage.size() + tag_size); std::string plaintext_buffer; subtle::ResizeStringUninitialized(&plaintext_buffer, kMessage.size()); // Modify the ciphertext. for (size_t i = 0; i < ciphertext_buffer.size() * 8; i++) { EXPECT_THAT( aead->Decrypt(ModifyString(ciphertext_buffer, i), kAssociatedData, iv, absl::MakeSpan(plaintext_buffer)) .status(), Not(IsOk())) << i; } // Modify the associated data. for (size_t i = 0; i < kAssociatedData.size() * 8; i++) { EXPECT_THAT( aead->Decrypt(ciphertext_buffer, ModifyString(kAssociatedData, i), iv, absl::MakeSpan(plaintext_buffer)) .status(), Not(IsOk())) << i; } // Truncate the ciphertext. for (size_t i = 0; i < ciphertext_buffer.size(); i++) { std::string truncated_ct(ciphertext_buffer, 0, i); EXPECT_THAT(aead->Decrypt(truncated_ct, kAssociatedData, iv, absl::MakeSpan(plaintext_buffer)) .status(), Not(IsOk())) << i; } } TEST_P(SslOneShotAeadTest, TestModification) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } SslOneShotAeadTestParams test_param = GetParam(); util::StatusOr> aead = CipherFromName( test_param.cipher, util::SecretDataFromStringView( absl::HexStringToBytes(test_param.key_hex))); ASSERT_THAT(aead, IsOk()); DoTestEncryptDecryptWithModifiedCiphertext( aead->get(), test_param.tag_size, absl::HexStringToBytes(test_param.iv_hex)); } // Make sure that the buffer passed in to the Decrypt routine is cleared if // decryption fails. TEST_P(SslOneShotAeadTest, TestBufferClearsIfDecryptionFails) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } SslOneShotAeadTestParams test_param = GetParam(); util::StatusOr> aead = CipherFromName( test_param.cipher, util::SecretDataFromStringView( absl::HexStringToBytes(test_param.key_hex))); ASSERT_THAT(aead, IsOk()); const int64_t kCiphertextSize = kMessage.size() + test_param.tag_size; std::string ciphertext_buffer; // Length of the message + tag. subtle::ResizeStringUninitialized(&ciphertext_buffer, kCiphertextSize); std::string iv = absl::HexStringToBytes(test_param.iv_hex); util::StatusOr written_bytes = (*aead)->Encrypt( kMessage, kAssociatedData, iv, absl::MakeSpan(ciphertext_buffer)); ASSERT_THAT(written_bytes, IsOk()); EXPECT_EQ(*written_bytes, kCiphertextSize); std::string plaintext_buffer; subtle::ResizeStringUninitialized(&plaintext_buffer, kMessage.size()); const std::string kExpectedClearedPlaintext(plaintext_buffer.size(), '\0'); // Alter the tag. for (int i = kCiphertextSize - test_param.tag_size; i < kCiphertextSize; i++) { std::string modified_ciphertext = ModifyString(ciphertext_buffer, i); EXPECT_THAT((*aead) ->Decrypt(modified_ciphertext, kAssociatedData, iv, absl::MakeSpan(plaintext_buffer)) .status(), Not(IsOk())); EXPECT_EQ(plaintext_buffer, kExpectedClearedPlaintext); } } void TestDecryptWithEmptyAssociatedData(SslOneShotAead* aead, absl::string_view ciphertext, absl::string_view iv) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } std::string plaintext_buffer; subtle::ResizeStringUninitialized(&plaintext_buffer, kMessage.size()); const absl::string_view empty_associated_data; std::vector values = {empty_associated_data, absl::string_view(), ""}; for (auto& associated_data : values) { DoTestDecrypt(aead, kMessage, associated_data, iv, ciphertext); } } void DoTestWithEmptyAssociatedData(SslOneShotAead* aead, absl::string_view iv, size_t tag_size) { const absl::string_view empty_associated_data; std::vector values = {empty_associated_data, absl::string_view(), ""}; for (auto& associated_data : values) { std::string ciphertext_buffer; subtle::ResizeStringUninitialized(&ciphertext_buffer, kMessage.size() + tag_size); DoTestEncrypt(aead, kMessage, associated_data, tag_size, iv, absl::MakeSpan(ciphertext_buffer)); TestDecryptWithEmptyAssociatedData(aead, ciphertext_buffer, iv); } } TEST_P(SslOneShotAeadTest, EmptyAssociatedData) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } SslOneShotAeadTestParams test_param = GetParam(); util::StatusOr> aead = CipherFromName( test_param.cipher, util::SecretDataFromStringView( absl::HexStringToBytes(test_param.key_hex))); ASSERT_THAT(aead, IsOk()); DoTestWithEmptyAssociatedData(aead->get(), absl::HexStringToBytes(test_param.iv_hex), test_param.tag_size); } // string_views, with `iv` and `associated_data`. void DoTestEmptyMessageEncryptDecrypt( SslOneShotAead* aead, absl::string_view iv, size_t tag_size, absl::string_view associated_data = kAssociatedData) { std::string ciphertext_buffer; subtle::ResizeStringUninitialized(&ciphertext_buffer, tag_size); { // Message is a null string_view. const absl::string_view message; DoTestEncrypt(aead, message, associated_data, tag_size, iv, absl::MakeSpan(ciphertext_buffer)); DoTestDecrypt(aead, "", associated_data, iv, ciphertext_buffer); } { // Message is an empty string. const std::string message = ""; DoTestEncrypt(aead, message, associated_data, tag_size, iv, absl::MakeSpan(ciphertext_buffer)); DoTestDecrypt(aead, "", associated_data, iv, ciphertext_buffer); } { // Message is a default-constructed string_view. DoTestEncrypt(aead, absl::string_view(), associated_data, tag_size, iv, absl::MakeSpan(ciphertext_buffer)); DoTestDecrypt(aead, "", associated_data, iv, ciphertext_buffer); } } TEST_P(SslOneShotAeadTest, EmptyMessage) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } SslOneShotAeadTestParams test_param = GetParam(); util::StatusOr> aead = CipherFromName( test_param.cipher, util::SecretDataFromStringView( absl::HexStringToBytes(test_param.key_hex))); ASSERT_THAT(aead, IsOk()); std::string iv = absl::HexStringToBytes(test_param.iv_hex); DoTestEmptyMessageEncryptDecrypt(aead->get(), iv, test_param.tag_size); } TEST_P(SslOneShotAeadTest, EmptyMessageAndAssociatedData) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } SslOneShotAeadTestParams test_param = GetParam(); util::StatusOr> aead = CipherFromName( test_param.cipher, util::SecretDataFromStringView( absl::HexStringToBytes(test_param.key_hex))); ASSERT_THAT(aead, IsOk()); std::string iv = absl::HexStringToBytes(test_param.iv_hex); const absl::string_view default_associated_data; const absl::string_view empty_associated_data = ""; DoTestEmptyMessageEncryptDecrypt(aead->get(), iv, test_param.tag_size, default_associated_data); DoTestEmptyMessageEncryptDecrypt(aead->get(), iv, test_param.tag_size, /*associated_data=*/absl::string_view()); DoTestEmptyMessageEncryptDecrypt(aead->get(), iv, test_param.tag_size, empty_associated_data); } TEST_P(SslOneShotAeadTest, BufferOverlapEncryptFails) { SslOneShotAeadTestParams test_param = GetParam(); util::StatusOr> aead = CipherFromName( test_param.cipher, util::SecretDataFromStringView( absl::HexStringToBytes(test_param.key_hex))); ASSERT_THAT(aead, IsOk()); std::string ciphertext_buffer(kMessage.data(), kMessage.size()); subtle::ResizeStringUninitialized(&ciphertext_buffer, (*aead)->CiphertextSize(kMessage.size())); EXPECT_THAT( (*aead) ->Encrypt( absl::string_view(ciphertext_buffer).substr(0, kMessage.size()), kAssociatedData, test_param.iv_hex, absl::MakeSpan(ciphertext_buffer)) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(SslOneShotAeadTest, BufferOverlapDecryptFails) { SslOneShotAeadTestParams test_param = GetParam(); util::StatusOr> aead = CipherFromName( test_param.cipher, util::SecretDataFromStringView( absl::HexStringToBytes(test_param.key_hex))); ASSERT_THAT(aead, IsOk()); std::string iv = absl::HexStringToBytes(test_param.iv_hex); std::string ciphertext_buffer; // Length of the message + tag. subtle::ResizeStringUninitialized(&ciphertext_buffer, (*aead)->CiphertextSize(kMessage.size())); DoTestEncrypt(aead->get(), kMessage, kAssociatedData, test_param.tag_size, iv, absl::MakeSpan(ciphertext_buffer)); EXPECT_THAT( (*aead) ->Decrypt( ciphertext_buffer, kAssociatedData, iv, absl::MakeSpan(ciphertext_buffer).subspan(0, kMessage.size())) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } std::vector GetSslOneShotAeadTestParams() { std::vector params = { {/*test_name=*/"AesGcm256", /*cipher=*/CipherType::kAesGcm, /*tag_size=*/kAesGcmTagSizeInBytes, /*iv_hex=*/kAesGcmIvHex, /*key_hex=*/k256Key}, {/*test_name=*/"AesGcm128", /*cipher=*/CipherType::kAesGcm, /*tag_size=*/kAesGcmTagSizeInBytes, /*iv_hex=*/kAesGcmIvHex, /*key_hex=*/k128Key}}; if (IsBoringSsl()) { params.push_back({/*test_name=*/"AesGcmSiv256", /*cipher=*/CipherType::kAesGcmSiv, /*tag_size=*/kAesGcmTagSizeInBytes, /*iv_hex=*/kAesGcmIvHex, /*key_hex=*/k256Key}); params.push_back({/*test_name=*/"AesGcmSiv128", /*cipher=*/CipherType::kAesGcmSiv, /*tag_size=*/kAesGcmTagSizeInBytes, /*iv_hex=*/kAesGcmIvHex, /*key_hex=*/k128Key}); params.push_back({/*test_name=*/"Xchacha20Poly1305", /*cipher=*/CipherType::kXchacha20Poly1305, /*tag_size=*/kXchacha20Poly1305TagSizeInBytes, /*iv_hex=*/kXchacha20Poly1305IvHex, /*key_hex=*/k256Key}); } return params; } INSTANTIATE_TEST_SUITE_P( SslOneShotAeadTests, SslOneShotAeadTest, testing::ValuesIn(GetSslOneShotAeadTestParams()), [](const TestParamInfo& info) { return info.param.test_name; }); TEST(SslOneShotAeadTest, AesGcmTestInvalidKeySizes) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } for (int keysize = 0; keysize < 65; keysize++) { util::SecretData key(keysize, 'x'); util::StatusOr> aead = CreateAesGcmOneShotCrypter(key); if (keysize == 16 || keysize == 32) { EXPECT_THAT(aead, IsOk()) << "with key size " << keysize; } else { EXPECT_THAT(aead, Not(IsOk())) << "with key size " << keysize; } } } TEST(SslOneShotAeadTest, AesGcmSivTestInvalidKeySizes) { if (!IsBoringSsl()) { GTEST_SKIP() << "AES-GCM-SIV not supported with OpenSSL"; } if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } for (int keysize = 0; keysize < 65; keysize++) { util::SecretData key(keysize, 'x'); util::StatusOr> aead = CreateAesGcmSivOneShotCrypter(key); if (keysize == 16 || keysize == 32) { EXPECT_THAT(aead, IsOk()) << "with key size " << keysize; } else { EXPECT_THAT(aead, Not(IsOk())) << "with key size " << keysize; } } } TEST(SslOneShotAeadTest, Xchacha20Poly1305TestInvalidKeySizes) { if (!IsBoringSsl()) { GTEST_SKIP() << "Xchacha20-Poly1305 not supported with OpenSSL"; } if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } for (int keysize = 0; keysize < 65; keysize++) { util::SecretData key(keysize, 'x'); util::StatusOr> aead = CreateXchacha20Poly1305OneShotCrypter(key); if (keysize == 32) { EXPECT_THAT(aead, IsOk()) << "with key size " << keysize; } else { EXPECT_THAT(aead, Not(IsOk())) << "with key size " << keysize; } } } TEST(SslOneShotAeadTest, Xchacha20Poly1305TestFipsOnly) { if (!IsBoringSsl()) { GTEST_SKIP() << "Xchacha20-Poly1305 not supported with OpenSSL"; } if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Only supported in FIPS-only mode"; } util::StatusOr> aead = CreateXchacha20Poly1305OneShotCrypter( util::SecretDataFromStringView(absl::HexStringToBytes(k256Key))); EXPECT_THAT(aead.status(), StatusIs(absl::StatusCode::kInternal)); } TEST(SslOneShotAeadTest, AesGcmTestFipsOnly) { if (IsFipsModeEnabled() && !IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test should not run in FIPS mode when BoringCrypto is " "unavailable."; } util::SecretData key_128 = util::SecretDataFromStringView(absl::HexStringToBytes(k128Key)); util::SecretData key_256 = util::SecretDataFromStringView(absl::HexStringToBytes(k256Key)); EXPECT_THAT(CreateAesGcmOneShotCrypter(key_128), IsOk()); EXPECT_THAT(CreateAesGcmOneShotCrypter(key_256), IsOk()); } TEST(SslOneShotAeadTest, AesGcmTestTestFipsFailWithoutBoringCrypto) { if (!IsFipsModeEnabled() || IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test assumes kOnlyUseFips but BoringCrypto is unavailable."; } util::SecretData key_128 = util::SecretDataFromStringView(absl::HexStringToBytes(k128Key)); util::SecretData key_256 = util::SecretDataFromStringView(absl::HexStringToBytes(k256Key)); EXPECT_THAT(CreateAesGcmOneShotCrypter(key_128).status(), StatusIs(absl::StatusCode::kInternal)); EXPECT_THAT(CreateAesGcmOneShotCrypter(key_256).status(), StatusIs(absl::StatusCode::kInternal)); } TEST(AesGcmSivBoringSslTest, AesGcmTestSivTestFipsOnly) { if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Only supported in FIPS-only mode"; } util::SecretData key_128 = util::SecretDataFromStringView(absl::HexStringToBytes(k128Key)); util::SecretData key_256 = util::SecretDataFromStringView(absl::HexStringToBytes(k256Key)); EXPECT_THAT(CreateAesGcmSivOneShotCrypter(key_128).status(), StatusIs(absl::StatusCode::kInternal)); EXPECT_THAT(CreateAesGcmSivOneShotCrypter(key_256).status(), StatusIs(absl::StatusCode::kInternal)); } // Parameters for SslOneShotAeadWycheproofTest. struct SslOneShotAeadWycheproofTestParams { std::string test_name; CipherType cipher; int nonce_size; int tag_size; absl::flat_hash_set key_sizes; WycheproofTestVector test_vector; }; class SslOneShotAeadWycheproofTest : public TestWithParam { public: void SetUp() override { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } SslOneShotAeadWycheproofTestParams params = GetParam(); const WycheproofTestVector& test_vector = params.test_vector; if (!params.key_sizes.contains(test_vector.key.size()) || test_vector.nonce.size() != params.nonce_size || test_vector.tag.size() != params.tag_size) { GTEST_SKIP() << "Unsupported parameters; key size: " << test_vector.key.size() << " nonce size: " << test_vector.nonce.size() << " tag size: " << test_vector.tag.size(); } } }; TEST_P(SslOneShotAeadWycheproofTest, Encrypt) { SslOneShotAeadWycheproofTestParams params = GetParam(); const WycheproofTestVector& test_vector = params.test_vector; util::SecretData key = util::SecretDataFromStringView(test_vector.key); util::StatusOr> aead = CipherFromName(params.cipher, key); ASSERT_THAT(aead, IsOk()); std::string ciphertext_and_tag = absl::StrCat(test_vector.ct, test_vector.tag); std::string ciphertext_buffer; subtle::ResizeStringUninitialized( &ciphertext_buffer, (*aead)->CiphertextSize(test_vector.msg.size())); util::StatusOr written_bytes = (*aead)->Encrypt(test_vector.msg, test_vector.aad, test_vector.nonce, absl::MakeSpan(ciphertext_buffer)); std::string expected_ciphertext = absl::StrCat(test_vector.ct, test_vector.tag); std::cout << test_vector.expected << "\n"; if (test_vector.expected == "valid" || test_vector.expected == "acceptable") { ASSERT_THAT(written_bytes, IsOk()); EXPECT_EQ(ciphertext_buffer, expected_ciphertext); } else { // invalid. // In this case, if the resulting ciphertext/tag are different, the // testcase is correct. if (written_bytes.ok()) { EXPECT_THAT(ciphertext_buffer, Not(Eq(expected_ciphertext))); } else { GTEST_SUCCEED(); } } } TEST_P(SslOneShotAeadWycheproofTest, Decrypt) { SslOneShotAeadWycheproofTestParams params = GetParam(); const WycheproofTestVector& test_vector = params.test_vector; util::SecretData key = util::SecretDataFromStringView(test_vector.key); util::StatusOr> aead = CipherFromName(params.cipher, key); ASSERT_THAT(aead, IsOk()); std::string ciphertext_and_tag = absl::StrCat(test_vector.ct, test_vector.tag); std::string plaintext_buffer; subtle::ResizeStringUninitialized( &plaintext_buffer, (*aead)->PlaintextSize(ciphertext_and_tag.size())); util::StatusOr written_bytes = (*aead)->Decrypt( absl::StrCat(test_vector.ct, test_vector.tag), test_vector.aad, test_vector.nonce, absl::MakeSpan(plaintext_buffer)); if (written_bytes.ok()) { EXPECT_NE(test_vector.expected, "invalid"); EXPECT_EQ(plaintext_buffer, test_vector.msg); } else { EXPECT_THAT(test_vector.expected, Not(AllOf(Eq("valid"), Eq("acceptable")))) << "Could not decrypt valid/acceptable tId: " << test_vector.id << " iv_size: " << test_vector.nonce.size() << " tag_size: " << test_vector.tag.size() << " key_size: " << key.size() << "; error: " << written_bytes.status(); } } std::vector GetWycheproofTestParams() { std::vector params; for (const WycheproofTestVector& test_vector : ReadWycheproofTestVectors("aes_gcm_test.json")) { params.push_back({/*test_name=*/"AesGcm", /*cipher_name=*/CipherType::kAesGcm, /*nonce_size=*/12, /*tag_size=*/16, /*key_sizes=*/{16, 32}, test_vector}); } if (IsBoringSsl()) { for (const WycheproofTestVector& test_vector : ReadWycheproofTestVectors("aes_gcm_siv_test.json")) { params.push_back({/*test_name=*/"AesGcmSiv", /*cipher_name=*/CipherType::kAesGcmSiv, /*nonce_size=*/12, /*tag_size=*/16, /*key_sizes=*/{16, 32}, test_vector}); } for (const WycheproofTestVector& test_vector : ReadWycheproofTestVectors("xchacha20_poly1305_test.json")) { params.push_back({/*test_name=*/"Xchacha20Poly1305", /*cipher_name=*/CipherType::kXchacha20Poly1305, /*nonce_size=*/24, /*tag_size=*/16, /*key_sizes=*/{32}, test_vector}); } } return params; } INSTANTIATE_TEST_SUITE_P( SslOneShotAeadWycheproofTests, SslOneShotAeadWycheproofTest, ValuesIn(GetWycheproofTestParams()), [](const TestParamInfo& info) { return absl::StrCat(info.param.test_name, "Tid", info.param.test_vector.id); }); } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/internal/wycheproof_aead.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/aead/internal/wycheproof_aead.h" #include #include #include #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/subtle/wycheproof_util.h" namespace crypto { namespace tink { namespace internal { using ::crypto::tink::subtle::WycheproofUtil; std::vector ReadWycheproofTestVectors( absl::string_view file_name) { std::unique_ptr root = WycheproofUtil::ReadTestVectors(std::string(file_name)); std::vector test_vectors; for (const rapidjson::Value& test_group : (*root)["testGroups"].GetArray()) { for (const rapidjson::Value& test : test_group["tests"].GetArray()) { test_vectors.push_back(WycheproofTestVector{ test["comment"].GetString(), WycheproofUtil::GetBytes(test["key"]), WycheproofUtil::GetBytes(test["iv"]), WycheproofUtil::GetBytes(test["msg"]), WycheproofUtil::GetBytes(test["ct"]), WycheproofUtil::GetBytes(test["aad"]), WycheproofUtil::GetBytes(test["tag"]), absl::StrCat(test["tcId"].GetInt()), test["result"].GetString(), }); } } return test_vectors; } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/internal/wycheproof_aead.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_INTERNAL_WYCHEPROOF_AEAD_H_ #define TINK_AEAD_INTERNAL_WYCHEPROOF_AEAD_H_ #include #include #include "absl/strings/string_view.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { // Struct representing a Wycheproof test vector. struct WycheproofTestVector { std::string comment; std::string key; std::string nonce; std::string msg; std::string ct; std::string aad; std::string tag; std::string id; std::string expected; }; // Read test vectors from the Wycheproof project that are rooted at `root`. std::vector ReadWycheproofTestVectors( absl::string_view file_name); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_AEAD_INTERNAL_WYCHEPROOF_AEAD_H_ ================================================ FILE: cc/aead/internal/zero_copy_aead.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_INTERNAL_ZERO_COPY_AEAD_H_ #define TINK_AEAD_INTERNAL_ZERO_COPY_AEAD_H_ #include #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { /////////////////////////////////////////////////////////////////////////////// // The interface for authenticated encryption with associated data. // Implementations of this interface are secure against adaptive // chosen ciphertext attacks. Encryption with associated data ensures // authenticity and integrity of that data, but not its secrecy. // (see RFC 5116, https://tools.ietf.org/html/rfc5116) // // This implementation expects the user to provide a contiguous block // of memory and writes the Encrypt and Decrypt results in the block. // This requires the user to avoid mutating this block during calls to // Encrypt and Decrypt and aims to reduce the latency associated with // copying strings from one location to another. class ZeroCopyAead { public: virtual ~ZeroCopyAead() = default; // Returns the maximum buffer size needed for encryption. The actual // size of the written cypertext may be smaller. virtual int64_t MaxEncryptionSize(int64_t plaintext_size) const = 0; // Encrypts `plaintext` with `associated_data` as associated data, // and returns the size of the ciphertext that is written in `buffer`. // `buffer` size must be at least MaxEncryptionSize to guarantee // enough space for encryption. // The ciphertext allows for checking authenticity and integrity // of the associated data, but does not guarantee its secrecy. virtual crypto::tink::util::StatusOr Encrypt( absl::string_view plaintext, absl::string_view associated_data, absl::Span buffer) const = 0; // Returns an upper bound on the size of the plaintext based on // `ciphertext_size`. The actual size of the written plaintext may be smaller. // The returned value is always >= 0. virtual int64_t MaxDecryptionSize(int64_t ciphertext_size) const = 0; // Decrypts `ciphertext` with `associated_data` as associated data, // and returns the size of the plaintext that is written in `buffer`. // `buffer` size must be at least MaxDecryptionSize to guarantee // enough space for decryption. // If the authentication tag does not validate, `buffer` is zeroed. // The decryption verifies the authenticity and integrity of the // associated data, but there are no guarantees wrt. secrecy of // that data. virtual crypto::tink::util::StatusOr Decrypt( absl::string_view ciphertext, absl::string_view associated_data, absl::Span buffer) const = 0; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_AEAD_INTERNAL_ZERO_COPY_AEAD_H_ ================================================ FILE: cc/aead/internal/zero_copy_aead_wrapper.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/aead/internal/zero_copy_aead_wrapper.h" #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "tink/aead.h" #include "tink/aead/internal/zero_copy_aead.h" #include "tink/crypto_format.h" #include "tink/primitive_set.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { namespace { typedef crypto::tink::PrimitiveSet::Entry ZeroCopyAeadEntry; util::Status Validate(PrimitiveSet* aead_set) { if (aead_set == nullptr) { return util::Status(absl::StatusCode::kInternal, "aead_set must be non-NULL"); } if (aead_set->get_primary() == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "aead_set has no primary"); } return util::OkStatus(); } class ZeroCopyAeadSetWrapper : public Aead { public: explicit ZeroCopyAeadSetWrapper( std::unique_ptr> aead_set) : aead_set_(std::move(aead_set)) {} util::StatusOr Encrypt( absl::string_view plaintext, absl::string_view associated_data) const override; util::StatusOr Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const override; ~ZeroCopyAeadSetWrapper() override = default; private: std::unique_ptr> aead_set_; }; util::StatusOr ZeroCopyAeadSetWrapper::Encrypt( absl::string_view plaintext, absl::string_view associated_data) const { std::string ciphertext = aead_set_->get_primary()->get_identifier(); int64_t key_id_size = ciphertext.size(); ZeroCopyAead& aead = aead_set_->get_primary()->get_primitive(); subtle::ResizeStringUninitialized( &ciphertext, key_id_size + aead.MaxEncryptionSize(plaintext.size())); // Write ciphertext at position ciphertext + CryptoFormat::kNonRawPrefixSize. util::StatusOr ciphertext_size = aead.Encrypt(plaintext, associated_data, absl::MakeSpan(ciphertext).subspan(key_id_size)); if (!ciphertext_size.ok()) return ciphertext_size.status(); ciphertext.resize(key_id_size + *ciphertext_size); return ciphertext; } util::StatusOr ZeroCopyAeadSetWrapper::Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const { if (ciphertext.size() > CryptoFormat::kNonRawPrefixSize) { std::string key_id = std::string(ciphertext.substr(0, CryptoFormat::kNonRawPrefixSize)); util::StatusOr>*> primitives = aead_set_->get_primitives(key_id); if (primitives.ok() && *primitives != nullptr) { absl::string_view raw_ciphertext = ciphertext.substr(key_id.size(), ciphertext.size()); for (const std::unique_ptr& entry : **primitives) { ZeroCopyAead& aead = entry->get_primitive(); std::string plaintext; subtle::ResizeStringUninitialized( &plaintext, aead.MaxDecryptionSize(raw_ciphertext.size())); util::StatusOr plaintext_size = entry->get_primitive().Decrypt( raw_ciphertext, associated_data, absl::MakeSpan(plaintext)); if (plaintext_size.ok()) { plaintext.resize(*plaintext_size); return plaintext; } } } } // Try raw keys because matching keys failed to decrypt. util::StatusOr>*> raw_primitives = aead_set_->get_raw_primitives(); if (raw_primitives.ok() && *raw_primitives != nullptr) { for (const std::unique_ptr& entry : **raw_primitives) { ZeroCopyAead& aead = entry->get_primitive(); std::string plaintext; subtle::ResizeStringUninitialized( &plaintext, aead.MaxDecryptionSize(ciphertext.size())); util::StatusOr plaintext_size = aead.Decrypt(ciphertext, associated_data, absl::MakeSpan(plaintext)); if (plaintext_size.ok()) { plaintext.resize(*plaintext_size); return plaintext; } } } return util::Status(absl::StatusCode::kInvalidArgument, "Decryption failed"); } } // anonymous namespace util::StatusOr> ZeroCopyAeadWrapper::Wrap( std::unique_ptr> aead_set) const { util::Status status = Validate(aead_set.get()); if (!status.ok()) return status; std::unique_ptr aead = absl::make_unique(std::move(aead_set)); return std::move(aead); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/internal/zero_copy_aead_wrapper.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_INTERNAL_ZERO_COPY_AEAD_WRAPPER_H_ #define TINK_AEAD_INTERNAL_ZERO_COPY_AEAD_WRAPPER_H_ #include #include "tink/aead.h" #include "tink/aead/internal/zero_copy_aead.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { // Wraps a set of ZeroCopyAead-instances that correspond to a keyset and // combines them into a single Aead-primitive that uses the provided instances, // depending on the context: // * ZeroCopyAeadSetWrapper::Encrypt(...) uses the primary instance from the // set. // * ZeroCopyAeadSetWrapper::Decrypt(...) uses the instance that matches the // ciphertext prefix. class ZeroCopyAeadWrapper : public PrimitiveWrapper { public: // Returns an Aead-primitive that uses ZeroCopyAead-instances provided in // 'aead_set', which must be non-NULL and must contain a primary instance. util::StatusOr> Wrap( std::unique_ptr> aead_set) const override; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_AEAD_INTERNAL_ZERO_COPY_AEAD_WRAPPER_H_ ================================================ FILE: cc/aead/internal/zero_copy_aead_wrapper_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/internal/zero_copy_aead_wrapper.h" #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "tink/aead.h" #include "tink/aead/internal/mock_zero_copy_aead.h" #include "tink/aead/internal/zero_copy_aead.h" #include "tink/crypto_format.h" #include "tink/primitive_set.h" #include "tink/subtle/subtle_util.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::PrimitiveSet; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::KeysetInfo; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::OutputPrefixType; using ::testing::_; using ::testing::HasSubstr; using ::testing::Invoke; using ::testing::Return; using ::testing::Unused; constexpr absl::string_view kPlaintext = "Some data to encrypt."; constexpr absl::string_view kAad = "Some data to authenticate."; constexpr absl::string_view kCiphertext = "iv:Some data to encrypt.:tag"; using ZeroCopyAeadEntry = crypto::tink::PrimitiveSet::Entry; TEST(ZeroCopyAeadWrapperEmptyTest, Nullptr) { ZeroCopyAeadWrapper wrapper; StatusOr> aead_set = wrapper.Wrap(nullptr); EXPECT_THAT(aead_set.status(), StatusIs(absl::StatusCode::kInternal, HasSubstr("non-NULL"))); } TEST(ZeroCopyAeadWrapperEmptyTest, Empty) { ZeroCopyAeadWrapper wrapper; StatusOr> aead_set = wrapper.Wrap(absl::make_unique>()); EXPECT_THAT(aead_set.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("no primary"))); } class ZeroCopyAeadWrapperTest : public testing::Test { protected: void SetUp() override { // Defines a Tink-type key. KeysetInfo::KeyInfo key_info; key_info.set_output_prefix_type(OutputPrefixType::TINK); key_info.set_key_id(1234543); key_info.set_status(KeyStatusType::ENABLED); // Creates a new AEAD set, adds a mock AEAD corresponding to the above key, // and stores the set as aead_set_. std::unique_ptr> aead_set( new PrimitiveSet()); auto entry = aead_set->AddPrimitive(SetUpMockZeroCopyAead(), key_info); ASSERT_THAT(entry, IsOk()); ASSERT_THAT(aead_set->set_primary(*entry), IsOk()); aead_set_ = std::move(aead_set); } // Returns an AEAD with expected return values for all its functions set via // EXPECT_CALL. All values are derived from constants kPlaintext, kAad, and // kCiphertext. std::unique_ptr SetUpMockZeroCopyAead() { auto aead = absl::make_unique(); EXPECT_CALL(*aead, MaxEncryptionSize(kPlaintext.size())) .WillRepeatedly(Return(kCiphertext.size())); EXPECT_CALL(*aead, Encrypt(kPlaintext, kAad, _)) .WillRepeatedly(Invoke([&](Unused, Unused, absl::Span buffer) { memcpy(buffer.data(), kCiphertext.data(), kCiphertext.size()); return kCiphertext.size(); })); EXPECT_CALL(*aead, MaxDecryptionSize(kCiphertext.size())) .WillRepeatedly(Return(kPlaintext.size())); EXPECT_CALL(*aead, Decrypt(kCiphertext, kAad, _)) .WillRepeatedly(Invoke([&](Unused, Unused, absl::Span buffer) { std::memcpy(buffer.data(), kPlaintext.data(), kPlaintext.size()); return kPlaintext.size(); })); return aead; } std::unique_ptr> aead_set_; }; TEST_F(ZeroCopyAeadWrapperTest, EncryptDecrypt) { ZeroCopyAeadWrapper wrapper; StatusOr> aead_set = wrapper.Wrap(std::move(aead_set_)); ASSERT_THAT(aead_set, IsOk()); StatusOr ciphertext = (*aead_set)->Encrypt(kPlaintext, kAad); ASSERT_THAT(ciphertext, IsOk()); StatusOr plaintext = (*aead_set)->Decrypt(*ciphertext, kAad); ASSERT_THAT(plaintext, IsOk()); EXPECT_EQ(*plaintext, kPlaintext); } TEST_F(ZeroCopyAeadWrapperTest, EncryptMultipleKeys) { // Manually encrypt with the primary key. ZeroCopyAead& aead = aead_set_->get_primary()->get_primitive(); std::string ciphertext; subtle::ResizeStringUninitialized( &ciphertext, CryptoFormat::kNonRawPrefixSize + aead.MaxEncryptionSize(kPlaintext.size())); StatusOr ciphertext_size = aead.Encrypt( kPlaintext, kAad, absl::MakeSpan(ciphertext) .subspan(CryptoFormat::kNonRawPrefixSize, ciphertext.size())); ASSERT_THAT(ciphertext_size, IsOk()); const std::string& key_id = aead_set_->get_primary()->get_identifier(); std::memcpy(&ciphertext[0], key_id.data(), key_id.size()); ciphertext.resize(key_id.size() + *ciphertext_size); // Add a second key. KeysetInfo::KeyInfo key_info; key_info.set_output_prefix_type(OutputPrefixType::TINK); key_info.set_key_id(42); key_info.set_status(KeyStatusType::ENABLED); std::unique_ptr aead1 = absl::make_unique(); ASSERT_THAT(aead_set_->AddPrimitive(std::move(aead1), key_info).status(), IsOk()); ZeroCopyAeadWrapper wrapper; StatusOr> aead_set = wrapper.Wrap(std::move(aead_set_)); ASSERT_THAT(aead_set, IsOk()); // Encrypt with the wrapped AEAD and check that the result is equal to // encrypting directly with the primary key. StatusOr wrap_ciphertext = (*aead_set)->Encrypt(kPlaintext, kAad); ASSERT_THAT(wrap_ciphertext, IsOk()); EXPECT_EQ(*wrap_ciphertext, ciphertext); } TEST_F(ZeroCopyAeadWrapperTest, EncryptDecryptRawKey) { // Add raw key to AEAD set. KeysetInfo::KeyInfo key_info; key_info.set_output_prefix_type(OutputPrefixType::RAW); key_info.set_key_id(1234); key_info.set_status(KeyStatusType::ENABLED); auto entry = aead_set_->AddPrimitive(SetUpMockZeroCopyAead(), key_info); ASSERT_THAT(entry, IsOk()); ASSERT_THAT(aead_set_->set_primary(*entry), IsOk()); // Manually encrypt with the raw key. util::StatusOr>*> raw_primitives = aead_set_->get_raw_primitives(); ASSERT_THAT(raw_primitives, IsOk()); EXPECT_EQ((*raw_primitives)->size(), 1); ZeroCopyAead& aead = (*raw_primitives)->front()->get_primitive(); std::string ciphertext; subtle::ResizeStringUninitialized(&ciphertext, aead.MaxEncryptionSize(kPlaintext.size())); util::StatusOr ciphertext_size = aead.Encrypt(kPlaintext, kAad, absl::MakeSpan(ciphertext)); ASSERT_THAT(ciphertext_size, IsOk()); ciphertext.resize(*ciphertext_size); // Encrypt with the wrapped AEAD and check that the result is equal to // encrypting directly with the raw key. ZeroCopyAeadWrapper wrapper; StatusOr> aead_set = wrapper.Wrap(std::move(aead_set_)); ASSERT_THAT(aead_set, IsOk()); StatusOr wrap_ciphertext = (*aead_set)->Encrypt(kPlaintext, kAad); ASSERT_THAT(wrap_ciphertext, IsOk()); EXPECT_EQ(*wrap_ciphertext, ciphertext); // Manually decrypt with the raw key. std::string plaintext; subtle::ResizeStringUninitialized(&plaintext, aead.MaxDecryptionSize(ciphertext.size())); util::StatusOr plaintext_size = aead.Decrypt(ciphertext, kAad, absl::MakeSpan(plaintext)); ASSERT_THAT(plaintext_size, IsOk()); plaintext.resize(*plaintext_size); EXPECT_EQ(plaintext, kPlaintext); // Decrypt with the wrapped AEAD. StatusOr wrap_plaintext = (*aead_set)->Decrypt(ciphertext, kAad); ASSERT_THAT(wrap_plaintext, IsOk()); EXPECT_EQ(*wrap_plaintext, kPlaintext); } TEST_F(ZeroCopyAeadWrapperTest, EncryptBadDecrypt) { ZeroCopyAeadWrapper wrapper; StatusOr> aead_set = wrapper.Wrap(std::move(aead_set_)); ASSERT_THAT(aead_set, IsOk()); StatusOr plaintext = (*aead_set)->Decrypt("some bad ciphertext", kAad); EXPECT_EQ(plaintext.status().code(), absl::StatusCode::kInvalidArgument); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/internal/zero_copy_aes_gcm_boringssl.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/aead/internal/zero_copy_aes_gcm_boringssl.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "tink/aead/internal/aead_util.h" #include "tink/aead/internal/ssl_aead.h" #include "tink/aead/internal/zero_copy_aead.h" #include "tink/internal/util.h" #include "tink/subtle/random.h" #include "tink/subtle/subtle_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { constexpr int kIvSizeInBytes = 12; constexpr int kTagSizeInBytes = 16; util::StatusOr> ZeroCopyAesGcmBoringSsl::New( const util::SecretData &key) { util::StatusOr> aead = internal::CreateAesGcmOneShotCrypter(key); if (!aead.ok()) { return aead.status(); } return {absl::WrapUnique(new ZeroCopyAesGcmBoringSsl(*std::move(aead)))}; } int64_t ZeroCopyAesGcmBoringSsl::MaxEncryptionSize( int64_t plaintext_size) const { return kIvSizeInBytes + aead_->CiphertextSize(plaintext_size); } util::StatusOr ZeroCopyAesGcmBoringSsl::Encrypt( absl::string_view plaintext, absl::string_view associated_data, absl::Span buffer) const { const int64_t max_encryption_size = MaxEncryptionSize(plaintext.size()); if (buffer.size() < max_encryption_size) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Encryption buffer too small; expected at least ", max_encryption_size, " bytes, got ", buffer.size())); } absl::string_view buffer_string(buffer.data(), buffer.size()); if (BuffersOverlap(plaintext, buffer_string)) { return util::Status( absl::StatusCode::kFailedPrecondition, "Plaintext and ciphertext buffers overlap; this is disallowed"); } util::Status res = subtle::Random::GetRandomBytes(buffer.subspan(0, kIvSizeInBytes)); if (!res.ok()) { return res; } absl::string_view iv = buffer_string.substr(0, kIvSizeInBytes); absl::Span raw_cipher_and_tag_buffer = buffer.subspan(kIvSizeInBytes); util::StatusOr written_bytes = aead_->Encrypt(plaintext, associated_data, iv, raw_cipher_and_tag_buffer); if (!written_bytes.ok()) { return written_bytes.status(); } return kIvSizeInBytes + *written_bytes; } int64_t ZeroCopyAesGcmBoringSsl::MaxDecryptionSize( int64_t ciphertext_size) const { const int64_t size = ciphertext_size - kIvSizeInBytes - kTagSizeInBytes; if (size <= 0) { return 0; } return size; } util::StatusOr ZeroCopyAesGcmBoringSsl::Decrypt( absl::string_view ciphertext, absl::string_view associated_data, absl::Span buffer) const { const size_t min_ciphertext_size = kIvSizeInBytes + kTagSizeInBytes; if (ciphertext.size() < min_ciphertext_size) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Ciphertext too short; expected at least ", min_ciphertext_size, " bytes, got ", ciphertext.size())); } const int64_t max_decryption_size = MaxDecryptionSize(ciphertext.size()); if (buffer.size() < max_decryption_size) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Decryption buffer too small; expected at least ", max_decryption_size, " bytes, got ", buffer.size())); } absl::string_view buffer_string(buffer.data(), buffer.size()); if (BuffersOverlap(ciphertext, buffer_string)) { return util::Status( absl::StatusCode::kFailedPrecondition, "Plaintext and ciphertext buffers overlap; this is disallowed"); } auto iv = ciphertext.substr(0, kIvSizeInBytes); auto ciphertext_and_tag = ciphertext.substr(kIvSizeInBytes, ciphertext.size() - kIvSizeInBytes); return aead_->Decrypt(ciphertext_and_tag, associated_data, iv, buffer); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/internal/zero_copy_aes_gcm_boringssl.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_INTERNAL_ZERO_COPY_AES_GCM_BORINGSSL_H_ #define TINK_AEAD_INTERNAL_ZERO_COPY_AES_GCM_BORINGSSL_H_ #include #include #include #include "absl/base/macros.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "tink/aead/internal/ssl_aead.h" #include "tink/aead/internal/zero_copy_aead.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { class ZeroCopyAesGcmBoringSsl : public ZeroCopyAead { public: static crypto::tink::util::StatusOr> New( const util::SecretData &key); int64_t MaxEncryptionSize(int64_t plaintext_size) const override; crypto::tink::util::StatusOr Encrypt( absl::string_view plaintext, absl::string_view associated_data, absl::Span buffer) const override; int64_t MaxDecryptionSize(int64_t ciphertext_size) const override; crypto::tink::util::StatusOr Decrypt( absl::string_view ciphertext, absl::string_view associated_data, absl::Span buffer) const override; private: explicit ZeroCopyAesGcmBoringSsl(std::unique_ptr aead) : aead_(std::move(aead)) {} const std::unique_ptr aead_; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_AEAD_INTERNAL_ZERO_COPY_AES_GCM_BORINGSSL_H_ ================================================ FILE: cc/aead/internal/zero_copy_aes_gcm_boringssl_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/aead/internal/zero_copy_aes_gcm_boringssl.h" #include #include #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "tink/aead/internal/wycheproof_aead.h" #include "tink/aead/internal/zero_copy_aead.h" #include "tink/subtle/subtle_util.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::AllOf; using ::testing::Eq; using ::testing::Not; using ::testing::TestWithParam; using ::testing::ValuesIn; constexpr absl::string_view kKey128Hex = "000102030405060708090a0b0c0d0e0f"; constexpr absl::string_view kMessage = "Some data to encrypt."; constexpr absl::string_view kAssociatedData = "Some data to authenticate."; constexpr int kIvSizeInBytes = 12; constexpr int kTagSizeInBytes = 16; // The MaxSizes test verifies these constants. constexpr int64_t kMaxEncryptionSize = kMessage.size() + kIvSizeInBytes + kTagSizeInBytes; // kMaxEncryptionSize - kIvSize - kTagSize. constexpr int64_t kMaxDecryptionSize = kMessage.size(); // Encoded ciphertext of kMessage with kAssociatedData and kKey128Hex. constexpr absl::string_view kEncodedCiphertext = "22889553081aa27f0f62ed2f32b068331cb3d8103e121c8b0c898cf70b613e334b7e913323" "128429226950dd2f4d42a6fc"; class ZeroCopyAesGcmBoringSslTest : public testing::Test { protected: void SetUp() override { util::SecretData key = util::SecretDataFromStringView(absl::HexStringToBytes(kKey128Hex)); util::StatusOr> cipher = ZeroCopyAesGcmBoringSsl::New(key); ASSERT_THAT(cipher, IsOk()); cipher_ = std::move(*cipher); } std::unique_ptr cipher_; }; TEST_F(ZeroCopyAesGcmBoringSslTest, MaxDecryptionSizeOfMaxEncryptionSizeOfMessageIsMessageSize) { // Check i == MaxDecryptionSize(MaxEncryptionSize(i)). EXPECT_EQ(kMessage.size(), cipher_->MaxDecryptionSize( cipher_->MaxEncryptionSize(kMessage.size()))); } TEST_F(ZeroCopyAesGcmBoringSslTest, EncryptDecrypt) { std::string ciphertext; subtle::ResizeStringUninitialized( &ciphertext, cipher_->MaxEncryptionSize(kMessage.size())); util::StatusOr ciphertext_size = cipher_->Encrypt(kMessage, kAssociatedData, absl::MakeSpan(ciphertext)); ASSERT_THAT(ciphertext_size, IsOk()); EXPECT_EQ(*ciphertext_size, kIvSizeInBytes + kMessage.size() + kTagSizeInBytes); std::string plaintext; subtle::ResizeStringUninitialized( &plaintext, cipher_->MaxDecryptionSize(ciphertext.size())); util::StatusOr plaintext_size = cipher_->Decrypt(ciphertext, kAssociatedData, absl::MakeSpan(plaintext)); ASSERT_THAT(plaintext_size, IsOk()); EXPECT_EQ(plaintext, kMessage); } TEST_F(ZeroCopyAesGcmBoringSslTest, DecryptEncodedCiphertext) { std::string plaintext; subtle::ResizeStringUninitialized(&plaintext, kMaxDecryptionSize); util::StatusOr plaintext_size = cipher_->Decrypt(absl::HexStringToBytes(kEncodedCiphertext), kAssociatedData, absl::MakeSpan(plaintext)); ASSERT_THAT(plaintext_size, IsOk()); EXPECT_EQ(plaintext.substr(0, *plaintext_size), kMessage); } TEST_F(ZeroCopyAesGcmBoringSslTest, EncryptBufferTooSmall) { const int64_t kMaxEncryptionSize = kMessage.size() + kIvSizeInBytes + kTagSizeInBytes; std::string ciphertext; subtle::ResizeStringUninitialized(&ciphertext, kMaxEncryptionSize - 1); EXPECT_THAT( cipher_->Encrypt(kMessage, kAssociatedData, absl::MakeSpan(ciphertext)) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(ZeroCopyAesGcmBoringSslTest, DecryptBufferTooSmall) { const int64_t kMaxDecryptionSize = kMessage.size(); std::string plaintext; subtle::ResizeStringUninitialized(&plaintext, kMaxDecryptionSize - 1); EXPECT_THAT(cipher_ ->Decrypt(absl::HexStringToBytes(kEncodedCiphertext), kAssociatedData, absl::MakeSpan(plaintext)) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(ZeroCopyAesGcmBoringSslTest, EncryptOverlappingPlaintextCiphertext) { std::string buffer(1024, '\0'); // Copy the kMessage at the beginning of the buffer. std::copy(kMessage.begin(), kMessage.end(), std::back_inserter(buffer)); auto plaintext = absl::string_view(buffer).substr(0, kMessage.size()); // The output buffer overlaps with a portion of the plaintext, in particular // the last kIvSizeInBytes bytes. auto cipher_buff = absl::MakeSpan(buffer).subspan(kMessage.size() - kIvSizeInBytes); EXPECT_THAT( cipher_->Encrypt(plaintext, kAssociatedData, cipher_buff).status(), StatusIs(absl::StatusCode::kFailedPrecondition)); } TEST_F(ZeroCopyAesGcmBoringSslTest, DecryptOverlappingPlaintextCiphertext) { std::string buffer(1024, '\0'); // Plaintext's buffer starts at the beginning of the buffer. auto out_buffer = absl::MakeSpan(buffer).subspan(0, kMessage.size()); std::string ciphertext_data = absl::HexStringToBytes(kEncodedCiphertext); // Copy the ciphertext into buffer such that the IV part will overlap with the // end of the plaintext output buffer. int ciphertext_start = kMessage.size() - kIvSizeInBytes; memcpy(&buffer[0] + ciphertext_start, ciphertext_data.data(), ciphertext_data.size()); auto ciphertext = absl::string_view(buffer).substr(ciphertext_start, ciphertext_data.size()); EXPECT_THAT( cipher_->Decrypt(ciphertext, kAssociatedData, out_buffer).status(), StatusIs(absl::StatusCode::kFailedPrecondition)); } class ZeroCopyAesGcmBoringSslWycheproofTest : public TestWithParam { void SetUp() override { WycheproofTestVector test_vector = GetParam(); if ((test_vector.key.size() != 16 && test_vector.key.size() != 32) || test_vector.nonce.size() != 12 || test_vector.tag.size() != 16) { GTEST_SKIP() << "Unsupported parameters: key size " << test_vector.key.size() << " nonce size: " << test_vector.nonce.size() << " tag size: " << test_vector.tag.size(); } } }; TEST_P(ZeroCopyAesGcmBoringSslWycheproofTest, Decrypt) { WycheproofTestVector test_vector = GetParam(); util::SecretData key = util::SecretDataFromStringView(test_vector.key); util::StatusOr> cipher = ZeroCopyAesGcmBoringSsl::New(key); ASSERT_THAT(cipher, IsOk()); std::string ciphertext = absl::StrCat(test_vector.nonce, test_vector.ct, test_vector.tag); std::string plaintext; subtle::ResizeStringUninitialized( &plaintext, (*cipher)->MaxDecryptionSize(ciphertext.size())); util::StatusOr written_bytes = (*cipher)->Decrypt( ciphertext, test_vector.aad, absl::MakeSpan(plaintext)); if (written_bytes.ok()) { EXPECT_NE(test_vector.expected, "invalid"); EXPECT_EQ(plaintext, test_vector.msg); } else { EXPECT_THAT(test_vector.expected, Not(AllOf(Eq("valid"), Eq("acceptable")))) << "Could not decrypt test with tcId: " << test_vector.id << " iv_size: " << test_vector.nonce.size() << " tag_size: " << test_vector.tag.size() << " key_size: " << key.size() << "; error: " << written_bytes.status(); } } INSTANTIATE_TEST_SUITE_P(ZeroCopyAesGcmBoringSslWycheproofTests, ZeroCopyAesGcmBoringSslWycheproofTest, ValuesIn(ReadWycheproofTestVectors( /*file_name=*/"aes_gcm_test.json"))); } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/key_gen_config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/key_gen_config_v0.h" #include "absl/log/check.h" #include "tink/aead/internal/key_gen_config_v0.h" #include "tink/key_gen_configuration.h" namespace crypto { namespace tink { const KeyGenConfiguration& KeyGenConfigAeadV0() { static const KeyGenConfiguration* instance = [] { static KeyGenConfiguration* config = new KeyGenConfiguration(); CHECK_OK(internal::AddAeadKeyGenV0(*config)); return config; }(); return *instance; } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/key_gen_config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_KEY_GEN_CONFIG_V0_H_ #define TINK_AEAD_KEY_GEN_CONFIG_V0_H_ #include "tink/key_gen_configuration.h" namespace crypto { namespace tink { // KeyGenConfiguration used to generate AEAD keys with recommended key managers. const KeyGenConfiguration& KeyGenConfigAeadV0(); } // namespace tink } // namespace crypto #endif // TINK_AEAD_KEY_GEN_CONFIG_V0_H_ ================================================ FILE: cc/aead/kms_aead_key_manager.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_KMS_AEAD_KEY_MANAGER_H_ #define TINK_AEAD_KMS_AEAD_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/aead.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/kms_client.h" #include "tink/kms_clients.h" #include "tink/util/constants.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/kms_aead.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class KmsAeadKeyManager : public KeyTypeManager> { public: class AeadFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::KmsAeadKey& kms_aead_key) const override { const auto& key_uri = kms_aead_key.params().key_uri(); auto kms_client_result = KmsClients::Get(key_uri); if (!kms_client_result.ok()) return kms_client_result.status(); return kms_client_result.value()->GetAead(key_uri); } }; KmsAeadKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::REMOTE; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::KmsAeadKey& key) const override { crypto::tink::util::Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; return ValidateKeyFormat(key.params()); } crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::KmsAeadKeyFormat& key_format) const override { if (key_format.key_uri().empty()) { return crypto::tink::util::Status(absl::StatusCode::kInvalidArgument, "Missing key_uri."); } return util::OkStatus(); } crypto::tink::util::StatusOr CreateKey( const google::crypto::tink::KmsAeadKeyFormat& key_format) const override { google::crypto::tink::KmsAeadKey kms_aead_key; kms_aead_key.set_version(get_version()); *(kms_aead_key.mutable_params()) = key_format; return kms_aead_key; } private: const std::string key_type_ = absl::StrCat( kTypeGoogleapisCom, google::crypto::tink::KmsAeadKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_KMS_AEAD_KEY_MANAGER_H_ ================================================ FILE: cc/aead/kms_aead_key_manager_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/kms_aead_key_manager.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/aead.h" #include "tink/kms_client.h" #include "tink/kms_clients.h" #include "tink/subtle/aead_test_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/kms_aead.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::crypto::tink::test::DummyAead; using ::crypto::tink::test::DummyKmsClient; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::KmsAeadKey; using ::google::crypto::tink::KmsAeadKeyFormat; using ::testing::Eq; using ::testing::Not; namespace { TEST(KmsAeadKeyManagerTest, Basics) { EXPECT_THAT(KmsAeadKeyManager().get_version(), Eq(0)); EXPECT_THAT(KmsAeadKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.KmsAeadKey")); EXPECT_THAT(KmsAeadKeyManager().key_material_type(), Eq(google::crypto::tink::KeyData::REMOTE)); } TEST(KmsAeadKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(KmsAeadKeyManager().ValidateKey(KmsAeadKey()), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(KmsAeadKeyManagerTest, ValidateValidKey) { KmsAeadKey key; key.set_version(0); key.mutable_params()->set_key_uri("Some uri"); EXPECT_THAT(KmsAeadKeyManager().ValidateKey(key), IsOk()); } TEST(KmsAeadKeyManagerTest, ValidateWrongVersion) { KmsAeadKey key; key.set_version(1); key.mutable_params()->set_key_uri("Some uri"); EXPECT_THAT(KmsAeadKeyManager().ValidateKey(key), Not(IsOk())); } TEST(KmsAeadKeyManagerTest, ValidateNoUri) { KmsAeadKey key; key.set_version(0); EXPECT_THAT(KmsAeadKeyManager().ValidateKey(key), Not(IsOk())); } TEST(KmsAeadKeyManagerTest, ValidateKeyFormatEmptyKey) { EXPECT_THAT(KmsAeadKeyManager().ValidateKeyFormat(KmsAeadKeyFormat()), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(KmsAeadKeyManagerTest, ValidateKeyFormatValidKey) { KmsAeadKeyFormat key_format; key_format.set_key_uri("Some uri"); EXPECT_THAT(KmsAeadKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(KmsAeadKeyManagerTest, ValidateKeyFormatNoUri) { KmsAeadKeyFormat key_format; EXPECT_THAT(KmsAeadKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(KmsAeadKeyManagerTest, CreateKey) { KmsAeadKeyFormat key_format; key_format.set_key_uri("Some uri"); auto key_or = KmsAeadKeyManager().CreateKey(key_format); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().params().key_uri(), Eq(key_format.key_uri())); } class KmsAeadKeyManagerCreateTest : public ::testing::Test { public: // The KmsClients class has a global variable which keeps the registered // clients. To reflect that in the test, we set them up in the SetUpTestSuite // function. static void SetUpTestSuite() { if (!KmsClients::Add( absl::make_unique("prefix1", "prefix1:some_key1")) .ok()) abort(); if (!KmsClients::Add(absl::make_unique("prefix2", "")).ok()) abort(); } }; TEST_F(KmsAeadKeyManagerCreateTest, CreateAead) { KmsAeadKey key; key.set_version(0); key.mutable_params()->set_key_uri("prefix1:some_key1"); auto kms_aead = KmsAeadKeyManager().GetPrimitive(key); ASSERT_THAT(kms_aead, IsOk()); DummyAead direct_aead("prefix1:some_key1"); EXPECT_THAT( EncryptThenDecrypt(*kms_aead.value(), direct_aead, "plaintext", "aad"), IsOk()); } TEST_F(KmsAeadKeyManagerCreateTest, CreateAeadWrongKeyName) { KmsAeadKey key; key.set_version(0); key.mutable_params()->set_key_uri("prefix1:some_other_key"); auto kms_aead = KmsAeadKeyManager().GetPrimitive(key); ASSERT_THAT(kms_aead, Not(IsOk())); } TEST_F(KmsAeadKeyManagerCreateTest, CreateAeadWrongPrefix) { KmsAeadKey key; key.set_version(0); key.mutable_params()->set_key_uri("non-existing-prefix:some_key1"); auto kms_aead = KmsAeadKeyManager().GetPrimitive(key); ASSERT_THAT(kms_aead, Not(IsOk())); } TEST_F(KmsAeadKeyManagerCreateTest, CreateAeadUnboundKey) { KmsAeadKey key; key.set_version(0); key.mutable_params()->set_key_uri("prefix2:some_key2"); auto kms_aead = KmsAeadKeyManager().GetPrimitive(key); ASSERT_THAT(kms_aead, IsOk()); DummyAead direct_aead("prefix2:some_key2"); EXPECT_THAT( EncryptThenDecrypt(*kms_aead.value(), direct_aead, "plaintext", "aad"), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/kms_envelope_aead.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/aead/kms_envelope_aead.h" #include #include #include #include #include "absl/base/internal/endian.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/aead/internal/aead_util.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { const int kEncryptedDekPrefixSize = 4; const char* kEmptyAssociatedData = ""; // Constructs a ciphertext of KMS envelope encryption. // The format of the ciphertext is the following: // 4-byte-prefix | encrypted_dek | encrypted_plaintext // where 4-byte-prefix is the length of encrypted_dek in big-endian format // (for compatibility with Java) std::string GetEnvelopeCiphertext(absl::string_view encrypted_dek, absl::string_view encrypted_plaintext) { uint8_t enc_dek_size[kEncryptedDekPrefixSize]; absl::big_endian::Store32(enc_dek_size, encrypted_dek.size()); return absl::StrCat(std::string(reinterpret_cast(enc_dek_size), kEncryptedDekPrefixSize), encrypted_dek, encrypted_plaintext); } } // namespace // static util::StatusOr> KmsEnvelopeAead::New( const google::crypto::tink::KeyTemplate& dek_template, std::unique_ptr remote_aead) { if (!internal::IsSupportedKmsEnvelopeAeadDekKeyType( dek_template.type_url())) { return util::Status(absl::StatusCode::kInvalidArgument, "unsupported key type"); } if (remote_aead == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "remote_aead must be non-null"); } auto km_result = Registry::get_key_manager(dek_template.type_url()); if (!km_result.ok()) return km_result.status(); return absl::WrapUnique( new KmsEnvelopeAead(dek_template, std::move(remote_aead))); } util::StatusOr KmsEnvelopeAead::Encrypt( absl::string_view plaintext, absl::string_view associated_data) const { // Generate DEK. auto dek_result = Registry::NewKeyData(dek_template_); if (!dek_result.ok()) return dek_result.status(); auto dek = std::move(dek_result.value()); // Wrap DEK key values with remote. auto dek_encrypt_result = remote_aead_->Encrypt(dek->value(), kEmptyAssociatedData); if (!dek_encrypt_result.ok()) return dek_encrypt_result.status(); // Encrypt plaintext using DEK. auto aead_result = Registry::GetPrimitive(*dek); if (!aead_result.ok()) return aead_result.status(); auto aead = std::move(aead_result.value()); auto encrypt_result = aead->Encrypt(plaintext, associated_data); if (!encrypt_result.ok()) return encrypt_result.status(); // Build and return ciphertext. return GetEnvelopeCiphertext(dek_encrypt_result.value(), encrypt_result.value()); } util::StatusOr KmsEnvelopeAead::Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const { // Parse the ciphertext. if (ciphertext.size() < kEncryptedDekPrefixSize) { return util::Status(absl::StatusCode::kInvalidArgument, "ciphertext too short"); } auto enc_dek_size = absl::big_endian::Load32( reinterpret_cast(ciphertext.data())); if (enc_dek_size > ciphertext.size() - kEncryptedDekPrefixSize || enc_dek_size < 0) { return util::Status(absl::StatusCode::kInvalidArgument, "invalid ciphertext"); } // Decrypt the DEK with remote. auto dek_decrypt_result = remote_aead_->Decrypt( ciphertext.substr(kEncryptedDekPrefixSize, enc_dek_size), kEmptyAssociatedData); if (!dek_decrypt_result.ok()) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("invalid ciphertext: ", dek_decrypt_result.status().message())); } // Create AEAD from DEK. google::crypto::tink::KeyData dek; dek.set_type_url(dek_template_.type_url()); dek.set_value(dek_decrypt_result.value()); dek.set_key_material_type(google::crypto::tink::KeyData::SYMMETRIC); // Encrypt plaintext using DEK. auto aead_result = Registry::GetPrimitive(dek); if (!aead_result.ok()) return aead_result.status(); auto aead = std::move(aead_result.value()); return aead->Decrypt( ciphertext.substr(kEncryptedDekPrefixSize + enc_dek_size), associated_data); } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/kms_envelope_aead.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_KMS_ENVELOPE_AEAD_H_ #define TINK_AEAD_KMS_ENVELOPE_AEAD_H_ #include #include #include #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // An implementation of KMS Envelope AEAD encryption // (https://cloud.google.com/kms/docs/data-encryption-keys). // // In envelope encryption user generates a data encryption key (DEK) locally, // encrypts data with DEK, sends DEK to a KMS to be encrypted (with a key // managed by KMS), and stores encrypted DEK with encrypted data; at a later // point user can retrieve encrypted data and DEK, use KMS to decrypt DEK, // and use decrypted DEK to decrypt the data. // // The ciphertext structure is as follows: // - Length of encrypted DEK: 4 bytes (big endian) // - Encrypted DEK: variable length that is equal to the value // specified in the last 4 bytes. // - AEAD payload: variable length. class KmsEnvelopeAead : public Aead { public: static crypto::tink::util::StatusOr> New( const google::crypto::tink::KeyTemplate& dek_template, std::unique_ptr remote_aead); crypto::tink::util::StatusOr Encrypt( absl::string_view plaintext, absl::string_view associated_data) const override; crypto::tink::util::StatusOr Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const override; ~KmsEnvelopeAead() override = default; private: KmsEnvelopeAead(const google::crypto::tink::KeyTemplate& dek_template, std::unique_ptr remote_aead) : dek_template_(dek_template), remote_aead_(std::move(remote_aead)) {} google::crypto::tink::KeyTemplate dek_template_; std::unique_ptr remote_aead_; }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_KMS_ENVELOPE_AEAD_H_ ================================================ FILE: cc/aead/kms_envelope_aead_key_manager.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/aead/kms_envelope_aead_key_manager.h" #include #include #include #include "tink/aead.h" #include "tink/aead/kms_envelope_aead.h" #include "tink/kms_client.h" #include "tink/kms_clients.h" #include "tink/util/statusor.h" #include "proto/kms_envelope.pb.h" namespace crypto { namespace tink { using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::KmsEnvelopeAeadKey; StatusOr> KmsEnvelopeAeadKeyManager::AeadFactory::Create( const KmsEnvelopeAeadKey& key) const { const auto& kek_uri = key.params().kek_uri(); auto kms_client_result = KmsClients::Get(kek_uri); if (!kms_client_result.ok()) return kms_client_result.status(); auto aead_result = kms_client_result.value()->GetAead(kek_uri); if (!aead_result.ok()) return aead_result.status(); return KmsEnvelopeAead::New(key.params().dek_template(), std::move(aead_result.value())); } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/kms_envelope_aead_key_manager.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_KMS_ENVELOPE_AEAD_KEY_MANAGER_H_ #define TINK_AEAD_KMS_ENVELOPE_AEAD_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/aead.h" #include "tink/aead/internal/aead_util.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/internal/fips_utils.h" #include "tink/util/constants.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/kms_envelope.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class KmsEnvelopeAeadKeyManager : public KeyTypeManager> { public: class AeadFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::KmsEnvelopeAeadKey& key) const override; }; KmsEnvelopeAeadKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::REMOTE; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::KmsEnvelopeAeadKey& key) const override { crypto::tink::util::Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; return ValidateKeyFormat(key.params()); } crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::KmsEnvelopeAeadKeyFormat& format) const override { if (format.kek_uri().empty()) { return crypto::tink::util::Status(absl::StatusCode::kInvalidArgument, "Missing kek_uri."); } if (!internal::IsSupportedKmsEnvelopeAeadDekKeyType( format.dek_template().type_url())) { return util::Status(absl::StatusCode::kInvalidArgument, "unsupported dek key type"); } return util::OkStatus(); } crypto::tink::util::StatusOr CreateKey(const google::crypto::tink::KmsEnvelopeAeadKeyFormat& key_format) const override { google::crypto::tink::KmsEnvelopeAeadKey key; key.set_version(get_version()); *(key.mutable_params()) = key_format; return key; } internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kNotFips; } private: const std::string key_type_ = absl::StrCat(kTypeGoogleapisCom, google::crypto::tink::KmsEnvelopeAeadKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_KMS_ENVELOPE_AEAD_KEY_MANAGER_H_ ================================================ FILE: cc/aead/kms_envelope_aead_key_manager_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/kms_envelope_aead_key_manager.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/aead.h" #include "tink/aead/aead_config.h" #include "tink/aead/aead_key_templates.h" #include "tink/aead/aes_eax_key_manager.h" #include "tink/aead/kms_envelope_aead.h" #include "tink/config/global_registry.h" #include "tink/keyset_handle.h" #include "tink/kms_client.h" #include "tink/kms_clients.h" #include "tink/mac/mac_key_templates.h" #include "tink/registry.h" #include "tink/subtle/aead_test_util.h" #include "tink/util/fake_kms_client.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/kms_envelope.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::crypto::tink::test::DummyAead; using ::crypto::tink::test::DummyKmsClient; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::KmsEnvelopeAeadKey; using ::google::crypto::tink::KmsEnvelopeAeadKeyFormat; using ::testing::Eq; using ::testing::Not; namespace { TEST(KmsEnvelopeAeadKeyManagerTest, Basics) { EXPECT_THAT(KmsEnvelopeAeadKeyManager().get_version(), Eq(0)); EXPECT_THAT(KmsEnvelopeAeadKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.KmsEnvelopeAeadKey")); EXPECT_THAT(KmsEnvelopeAeadKeyManager().key_material_type(), Eq(google::crypto::tink::KeyData::REMOTE)); } TEST(KmsEnvelopeAeadKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(KmsEnvelopeAeadKeyManager().ValidateKey(KmsEnvelopeAeadKey()), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(KmsEnvelopeAeadKeyManagerTest, ValidateValidKey) { KmsEnvelopeAeadKey key; key.set_version(0); key.mutable_params()->set_kek_uri("Some uri"); *(key.mutable_params()->mutable_dek_template()) = AeadKeyTemplates::Aes128Eax(); EXPECT_THAT(KmsEnvelopeAeadKeyManager().ValidateKey(key), IsOk()); } TEST(KmsEnvelopeAeadKeyManagerTest, ValidateWrongVersion) { KmsEnvelopeAeadKey key; key.set_version(1); key.mutable_params()->set_kek_uri("Some uri"); *(key.mutable_params()->mutable_dek_template()) = AeadKeyTemplates::Aes128Eax(); EXPECT_THAT(KmsEnvelopeAeadKeyManager().ValidateKey(key), Not(IsOk())); } TEST(KmsEnvelopeAeadKeyManagerTest, ValidateNoUri) { KmsEnvelopeAeadKey key; key.set_version(1); *(key.mutable_params()->mutable_dek_template()) = AeadKeyTemplates::Aes128Eax(); EXPECT_THAT(KmsEnvelopeAeadKeyManager().ValidateKey(key), Not(IsOk())); } TEST(KmsEnvelopeAeadKeyManagerTest, ValidateKeyFormatEmptyKey) { EXPECT_THAT( KmsEnvelopeAeadKeyManager().ValidateKeyFormat(KmsEnvelopeAeadKeyFormat()), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(KmsEnvelopeAeadKeyManagerTest, ValidateKeyFormatValidKey) { KmsEnvelopeAeadKeyFormat key_format; key_format.set_kek_uri("Some uri"); *key_format.mutable_dek_template() = AeadKeyTemplates::Aes128Eax(); EXPECT_THAT(KmsEnvelopeAeadKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(KmsEnvelopeAeadKeyManagerTest, ValidateKeyFormatNoUri) { KmsEnvelopeAeadKeyFormat key_format; *key_format.mutable_dek_template() = AeadKeyTemplates::Aes128Eax(); EXPECT_THAT(KmsEnvelopeAeadKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(KmsEnvelopeAeadKeyManagerTest, ValidateKeyFormatNoTemplate) { KmsEnvelopeAeadKeyFormat key_format; key_format.set_kek_uri("Some uri"); EXPECT_THAT(KmsEnvelopeAeadKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(KmsEnvelopeAeadKeyManagerTest, ValidateKeyFormatInvalidDekTemplate) { KmsEnvelopeAeadKeyFormat key_format; key_format.set_kek_uri("Some uri"); *key_format.mutable_dek_template() = MacKeyTemplates::HmacSha256(); EXPECT_THAT(KmsEnvelopeAeadKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(KmsEnvelopeAeadKeyManagerTest, CreateKey) { KmsEnvelopeAeadKeyFormat key_format; key_format.set_kek_uri("Some uri"); *key_format.mutable_dek_template() = AeadKeyTemplates::Aes128Eax(); auto key_or = KmsEnvelopeAeadKeyManager().CreateKey(key_format); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().params().kek_uri(), Eq(key_format.kek_uri())); EXPECT_THAT(key_or.value().params().dek_template().value(), Eq(key_format.dek_template().value())); } class KmsEnvelopeAeadKeyManagerCreateTest : public ::testing::Test { public: // The KmsClients class has a global variable which keeps the registered // clients. To reflect that in the test, we set them up in the SetUpTestSuite // function. static void SetUpTestSuite() { if (!KmsClients::Add( absl::make_unique("prefix1", "prefix1:some_key1")) .ok()) abort(); if (!KmsClients::Add(absl::make_unique("prefix2", "")).ok()) abort(); if (!Registry::RegisterKeyTypeManager(absl::make_unique(), true) .ok()) abort(); } }; TEST_F(KmsEnvelopeAeadKeyManagerCreateTest, CreateAead) { KmsEnvelopeAeadKey key; key.set_version(0); key.mutable_params()->set_kek_uri("prefix1:some_key1"); *(key.mutable_params()->mutable_dek_template()) = AeadKeyTemplates::Aes128Eax(); auto kms_aead = KmsEnvelopeAeadKeyManager().GetPrimitive(key); ASSERT_THAT(kms_aead, IsOk()); auto direct_aead = KmsEnvelopeAead::New(key.params().dek_template(), absl::make_unique("prefix1:some_key1")); ASSERT_THAT(direct_aead, IsOk()); EXPECT_THAT(EncryptThenDecrypt(*kms_aead.value(), *direct_aead.value(), "plaintext", "aad"), IsOk()); } TEST_F(KmsEnvelopeAeadKeyManagerCreateTest, CreateAeadWrongKeyName) { KmsEnvelopeAeadKey key; key.set_version(0); key.mutable_params()->set_kek_uri("prefix1:some_other_key"); *(key.mutable_params()->mutable_dek_template()) = AeadKeyTemplates::Aes128Eax(); auto kms_aead = KmsEnvelopeAeadKeyManager().GetPrimitive(key); ASSERT_THAT(kms_aead, Not(IsOk())); } TEST_F(KmsEnvelopeAeadKeyManagerCreateTest, CreateAeadWrongTypeUrl) { KmsEnvelopeAeadKey key; key.set_version(0); key.mutable_params()->set_kek_uri("prefix1:some_other_key"); *(key.mutable_params()->mutable_dek_template()) = AeadKeyTemplates::Aes128Eax(); key.mutable_params()->mutable_dek_template()->set_type_url( "Some unkonwn type url"); auto kms_aead = KmsEnvelopeAeadKeyManager().GetPrimitive(key); ASSERT_THAT(kms_aead, Not(IsOk())); } TEST_F(KmsEnvelopeAeadKeyManagerCreateTest, CreateAeadWrongPrefix) { KmsEnvelopeAeadKey key; key.set_version(0); key.mutable_params()->set_kek_uri("non-existing-prefix:some_key1"); *(key.mutable_params()->mutable_dek_template()) = AeadKeyTemplates::Aes128Eax(); auto kms_aead = KmsEnvelopeAeadKeyManager().GetPrimitive(key); ASSERT_THAT(kms_aead, Not(IsOk())); } TEST_F(KmsEnvelopeAeadKeyManagerCreateTest, CreateAeadUnboundKey) { KmsEnvelopeAeadKey key; key.set_version(0); key.mutable_params()->set_kek_uri("prefix2:some_key2"); *(key.mutable_params()->mutable_dek_template()) = AeadKeyTemplates::Aes128Eax(); auto kms_aead = KmsEnvelopeAeadKeyManager().GetPrimitive(key); ASSERT_THAT(kms_aead, IsOk()); auto direct_aead = KmsEnvelopeAead::New(key.params().dek_template(), absl::make_unique("prefix2:some_key2")); ASSERT_THAT(direct_aead, IsOk()); EXPECT_THAT(EncryptThenDecrypt(*kms_aead.value(), *direct_aead.value(), "plaintext", "aad"), IsOk()); } class KmsEnvelopeAeadKeyManagerDekTemplatesTest : public testing::TestWithParam { void SetUp() override { ASSERT_THAT(AeadConfig::Register(), IsOk()); } }; TEST_P(KmsEnvelopeAeadKeyManagerDekTemplatesTest, EncryptDecryp) { util::StatusOr kek_uri_result = test::FakeKmsClient::CreateFakeKeyUri(); ASSERT_THAT(kek_uri_result, IsOk()); std::string kek_uri = kek_uri_result.value(); util::Status register_fake_kms_client_status = test::FakeKmsClient::RegisterNewClient(kek_uri, /*credentials_path=*/""); ASSERT_THAT(register_fake_kms_client_status, IsOk()); KeyTemplate dek_template = GetParam(); KeyTemplate env_template = AeadKeyTemplates::KmsEnvelopeAead(kek_uri, dek_template); util::StatusOr> handle = KeysetHandle::GenerateNew(env_template, KeyGenConfigGlobalRegistry()); ASSERT_THAT(handle, IsOk()); util::StatusOr> envelope_aead = (*handle)->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(envelope_aead, IsOk()); std::string plaintext = "plaintext"; std::string associated_data = "associated_data"; util::StatusOr ciphertext = (*envelope_aead)->Encrypt(plaintext, associated_data); ASSERT_THAT(ciphertext, IsOk()); util::StatusOr decrypted = (*envelope_aead)->Decrypt(ciphertext.value(), associated_data); EXPECT_THAT(decrypted, IsOkAndHolds(plaintext)); std::string invalid_associated_data = "invalid_associated_data"; util::StatusOr decrypted_with_invalid_associated_data = (*envelope_aead)->Decrypt(ciphertext.value(), invalid_associated_data); EXPECT_THAT(decrypted_with_invalid_associated_data.status(), Not(IsOk())); } INSTANTIATE_TEST_SUITE_P( KmsEnvelopeAeadKeyManagerDekTemplatesTest, KmsEnvelopeAeadKeyManagerDekTemplatesTest, testing::Values(AeadKeyTemplates::Aes128Gcm(), AeadKeyTemplates::Aes256Gcm(), AeadKeyTemplates::Aes128CtrHmacSha256(), AeadKeyTemplates::Aes128Eax(), AeadKeyTemplates::Aes128GcmNoPrefix())); } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/kms_envelope_aead_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/kms_envelope_aead.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/base/internal/endian.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/aead/aead_config.h" #include "tink/aead/aead_key_templates.h" #include "tink/config/global_registry.h" #include "tink/internal/ssl_util.h" #include "tink/keyset_handle.h" #include "tink/mac/mac_key_templates.h" #include "tink/registry.h" #include "tink/util/fake_kms_client.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_gcm.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::Aead; using ::crypto::tink::test::DummyAead; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::KeyTemplate; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::Not; using ::testing::SizeIs; using ::testing::Test; constexpr int kEncryptedDekPrefixSize = 4; constexpr absl::string_view kRemoteAeadName = "kms-backed-aead"; class KmsEnvelopeAeadTest : public Test { protected: void SetUp() override { ASSERT_THAT(AeadConfig::Register(), IsOk()); } }; TEST_F(KmsEnvelopeAeadTest, EncryptDecryptSucceed) { // Use an AES-128-GCM primitive as the remote one. util::StatusOr> keyset_handle = KeysetHandle::GenerateNew(AeadKeyTemplates::Aes128Gcm(), KeyGenConfigGlobalRegistry()); ASSERT_THAT(keyset_handle, IsOk()); KeyTemplate dek_template = AeadKeyTemplates::Aes128Eax(); util::StatusOr> remote_aead = (*keyset_handle) ->GetPrimitive(ConfigGlobalRegistry()); util::StatusOr> envelope_aead = KmsEnvelopeAead::New(dek_template, *std::move(remote_aead)); ASSERT_THAT(envelope_aead, IsOk()); std::string message = "Some data to encrypt."; std::string aad = "Some associated data."; util::StatusOr encrypt_result = (*envelope_aead)->Encrypt(message, aad); ASSERT_THAT(encrypt_result, IsOk()); util::StatusOr decrypt_result = (*envelope_aead)->Decrypt(encrypt_result.value(), aad); EXPECT_THAT(decrypt_result, IsOkAndHolds(message)); } TEST_F(KmsEnvelopeAeadTest, NewFailsIfReamoteAeadIsNull) { KeyTemplate dek_template = AeadKeyTemplates::Aes128Eax(); EXPECT_THAT( KmsEnvelopeAead::New(dek_template, /*remote_aead=*/nullptr).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("non-null"))); } TEST_F(KmsEnvelopeAeadTest, NewFailsIfDekKeyManagerIsNotRegistered) { Registry::Reset(); KeyTemplate dek_template = AeadKeyTemplates::Aes128Eax(); auto remote_aead = absl::make_unique(kRemoteAeadName); EXPECT_THAT( KmsEnvelopeAead::New(dek_template, std::move(remote_aead)).status(), StatusIs(absl::StatusCode::kNotFound, HasSubstr("AesEaxKey"))); } TEST_F(KmsEnvelopeAeadTest, NewFailsIfUsingDekTemplateOfUnsupportedKeyType) { KeyTemplate dek_template = MacKeyTemplates::HmacSha256(); auto remote_aead = absl::make_unique(kRemoteAeadName); EXPECT_THAT( KmsEnvelopeAead::New(dek_template, std::move(remote_aead)).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("unsupported key type"))); } TEST_F(KmsEnvelopeAeadTest, DecryptFailsWithInvalidCiphertextOrAad) { KeyTemplate dek_template = AeadKeyTemplates::Aes128Gcm(); auto remote_aead = absl::make_unique(kRemoteAeadName); util::StatusOr> aead = KmsEnvelopeAead::New(dek_template, std::move(remote_aead)); ASSERT_THAT(aead, IsOk()); std::string message = "Some data to encrypt."; std::string aad = "Some associated data."; util::StatusOr encrypt_result = (*aead)->Encrypt(message, aad); ASSERT_THAT(encrypt_result, IsOk()); auto ciphertext = absl::string_view(*encrypt_result); // Ciphertext has size zero or smaller than 4 bytes. EXPECT_THAT( (*aead)->Decrypt(/*ciphertext=*/"", aad).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("too short"))); EXPECT_THAT( (*aead)->Decrypt(/*ciphertext=*/"sh", aad).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("too short"))); // Ciphertext is smaller than the size of the key. const int dek_encrypted_key_size = absl::big_endian::Load32( reinterpret_cast(ciphertext.data())); // We leave only key size and key truncated by one. EXPECT_THAT( (*aead) ->Decrypt(ciphertext.substr(0, 4 + dek_encrypted_key_size - 1), aad) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("invalid"))); std::string corrupted_ciphertext = *encrypt_result; // Corrupt the serialized DEK. corrupted_ciphertext[4] = 'a'; EXPECT_THAT( (*aead)->Decrypt(corrupted_ciphertext, aad).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("invalid"))); // Wrong associated data. EXPECT_THAT((*aead)->Decrypt(ciphertext, "wrong aad").status(), StatusIs(absl::StatusCode::kInternal, HasSubstr("Authentication failed"))); } TEST_F(KmsEnvelopeAeadTest, DekMaintainsCorrectKeyFormat) { KeyTemplate dek_template = AeadKeyTemplates::Aes128Gcm(); auto kms_remote_aead = absl::make_unique(kRemoteAeadName); util::StatusOr> aead = KmsEnvelopeAead::New(dek_template, std::move(kms_remote_aead)); ASSERT_THAT(aead, IsOk()); std::string message = "Some data to encrypt."; std::string aad = "Some associated data."; util::StatusOr ciphertext = (*aead)->Encrypt(message, aad); ASSERT_THAT(ciphertext, IsOk()); // Recover DEK from ciphertext (see // https://developers.google.com/tink/wire-format#envelope_encryption). auto enc_dek_size = absl::big_endian::Load32( reinterpret_cast(ciphertext->data())); DummyAead remote_aead = DummyAead(kRemoteAeadName); absl::string_view encrypted_dek = absl::string_view(*ciphertext) .substr(kEncryptedDekPrefixSize, enc_dek_size); util::StatusOr dek_proto_bytes = remote_aead.Decrypt(encrypted_dek, /*associated_data=*/""); ASSERT_THAT(dek_proto_bytes, IsOk()); // Check if we can deserialize a GCM key proto from the decrypted DEK. google::crypto::tink::AesGcmKey key; EXPECT_TRUE(key.ParseFromString(dek_proto_bytes.value())); EXPECT_THAT(key.key_value(), SizeIs(16)); } TEST_F(KmsEnvelopeAeadTest, MultipleEncryptionsProduceDifferentDeks) { KeyTemplate dek_template = AeadKeyTemplates::Aes128Gcm(); auto kms_remote_aead = absl::make_unique(kRemoteAeadName); util::StatusOr> aead = KmsEnvelopeAead::New(dek_template, std::move(kms_remote_aead)); ASSERT_THAT(aead, IsOk()); std::string message = "Some data to encrypt."; std::string aad = "Some associated data."; constexpr int kNumIterations = 2; std::vector ciphertexts; ciphertexts.reserve(kNumIterations); for (int i = 0; i < kNumIterations; i++) { util::StatusOr ciphertext = (*aead)->Encrypt(message, aad); ASSERT_THAT(ciphertext, IsOk()); auto enc_dek_size = absl::big_endian::Load32( reinterpret_cast(ciphertext->data())); DummyAead remote_aead = DummyAead(kRemoteAeadName); util::StatusOr dek_proto_bytes = remote_aead.Decrypt( ciphertext->substr(kEncryptedDekPrefixSize, enc_dek_size), /*associated_data=*/""); ASSERT_THAT(dek_proto_bytes, IsOk()); google::crypto::tink::AesGcmKey key; ASSERT_TRUE(key.ParseFromString(dek_proto_bytes.value())); ASSERT_THAT(key.key_value(), SizeIs(16)); ciphertexts.push_back(key); } for (int i = 0; i < ciphertexts.size() - 1; i++) { for (int j = i + 1; j < ciphertexts.size(); j++) { EXPECT_THAT(ciphertexts[i].SerializeAsString(), Not(Eq(ciphertexts[j].SerializeAsString()))); } } } class KmsEnvelopeAeadDekTemplatesTest : public testing::TestWithParam { void SetUp() override { ASSERT_THAT(AeadConfig::Register(), IsOk()); } }; TEST_P(KmsEnvelopeAeadDekTemplatesTest, EncryptDecrypt) { // Use an AES-128-GCM primitive as the remote AEAD. util::StatusOr> keyset_handle = KeysetHandle::GenerateNew(AeadKeyTemplates::Aes128Gcm(), KeyGenConfigGlobalRegistry()); ASSERT_THAT(keyset_handle, IsOk()); util::StatusOr> remote_aead = (*keyset_handle) ->GetPrimitive(ConfigGlobalRegistry()); KeyTemplate dek_template = GetParam(); util::StatusOr> envelope_aead = KmsEnvelopeAead::New(dek_template, *std::move(remote_aead)); ASSERT_THAT(envelope_aead, IsOk()); std::string plaintext = "plaintext"; std::string associated_data = "associated_data"; util::StatusOr ciphertext = (*envelope_aead)->Encrypt(plaintext, associated_data); ASSERT_THAT(ciphertext, IsOk()); util::StatusOr decrypted = (*envelope_aead)->Decrypt(ciphertext.value(), associated_data); EXPECT_THAT(decrypted, IsOkAndHolds(plaintext)); } std::vector GetTestTemplates() { std::vector templates = { AeadKeyTemplates::Aes128Gcm(), AeadKeyTemplates::Aes256Gcm(), AeadKeyTemplates::Aes128CtrHmacSha256(), AeadKeyTemplates::Aes128Eax(), AeadKeyTemplates::Aes128GcmNoPrefix() }; if (internal::IsBoringSsl()) { templates.push_back(AeadKeyTemplates::XChaCha20Poly1305()); templates.push_back(AeadKeyTemplates::Aes256GcmSiv()); } return templates; } INSTANTIATE_TEST_SUITE_P( KmsEnvelopeAeadDekTemplatesTest, KmsEnvelopeAeadDekTemplatesTest, testing::ValuesIn(GetTestTemplates())); TEST_F(KmsEnvelopeAeadTest, PrimitiveFromTemplateAndFromNewAreCompatible) { util::StatusOr kek_uri_result = test::FakeKmsClient::CreateFakeKeyUri(); ASSERT_THAT(kek_uri_result, IsOk()); std::string kek_uri = *kek_uri_result; KeyTemplate dek_template = AeadKeyTemplates::Aes128Gcm(); // Create a KmsEnvelopeAead primitive from a KmsEnvelopeAeadKey template. util::Status register_status = test::FakeKmsClient::RegisterNewClient(kek_uri, /*credentials_path=*/""); ASSERT_THAT(register_status, IsOk()); // Create a KmsEnvelopeAeadKey template. KeyTemplate env_template = AeadKeyTemplates::KmsEnvelopeAead(kek_uri, dek_template); // Get KMS envelope AEAD primitive. util::StatusOr> handle = KeysetHandle::GenerateNew(env_template, KeyGenConfigGlobalRegistry()); ASSERT_THAT(handle, IsOk()); util::StatusOr> envelope_aead_from_template = (*handle)->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(envelope_aead_from_template, IsOk()); // Create a KmsEnvelopeAead primitive form KmsEnvelopeAead::New. util::StatusOr> client = test::FakeKmsClient::New(/*key_uri=*/"", /*credentials_path=*/""); ASSERT_THAT(client, IsOk()); util::StatusOr> remote_aead = (*client)->GetAead(kek_uri); ASSERT_THAT(remote_aead, IsOk()); // Get KMS envelope AEAD primitive. util::StatusOr> envelope_aead_from_new = KmsEnvelopeAead::New(dek_template, *std::move(remote_aead)); ASSERT_THAT(envelope_aead_from_new, IsOk()); // Check that envelope_aead_from_template and envelope_aead_from_new are the // same primitive by encrypting with envelope_aead_from_template and // decrypting with envelope_aead_from_new and vice versa. std::string plaintext = "plaintext"; std::string associated_data = "associated_data"; { util::StatusOr ciphertext = (*envelope_aead_from_template)->Encrypt(plaintext, associated_data); ASSERT_THAT(ciphertext, IsOk()); util::StatusOr decrypted = (*envelope_aead_from_new)->Decrypt(ciphertext.value(), associated_data); EXPECT_THAT(decrypted, IsOkAndHolds(plaintext)); } { util::StatusOr ciphertext = (*envelope_aead_from_new)->Encrypt(plaintext, associated_data); ASSERT_THAT(ciphertext, IsOk()); util::StatusOr decrypted = (*envelope_aead_from_template) ->Decrypt(ciphertext.value(), associated_data); EXPECT_THAT(decrypted, IsOkAndHolds(plaintext)); } } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/mock_aead.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_MOCK_AEAD_H_ #define TINK_AEAD_MOCK_AEAD_H_ #include #include "gmock/gmock.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { class MockAead : public Aead { public: MOCK_METHOD(util::StatusOr, Encrypt, (absl::string_view plaintext, absl::string_view associated_data), (const, override)); MOCK_METHOD(util::StatusOr, Decrypt, (absl::string_view ciphertext, absl::string_view associated_data), (const, override)); }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_MOCK_AEAD_H_ ================================================ FILE: cc/aead/subtle/BUILD.bazel ================================================ licenses(["notice"]) ================================================ FILE: cc/aead/subtle/CMakeLists.txt ================================================ ================================================ FILE: cc/aead/xchacha20_poly1305_key.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/xchacha20_poly1305_key.h" #include #include #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/types/optional.h" #include "tink/aead/xchacha20_poly1305_parameters.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { util::StatusOr ComputeOutputPrefix( XChaCha20Poly1305Parameters::Variant variant, absl::optional id_requirement) { switch (variant) { case XChaCha20Poly1305Parameters::Variant::kNoPrefix: return std::string(""); // Empty prefix. case XChaCha20Poly1305Parameters::Variant::kCrunchy: if (!id_requirement.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "id requirement must have value with kCrunchy"); } return absl::StrCat(absl::HexStringToBytes("00"), subtle::BigEndian32(*id_requirement)); case XChaCha20Poly1305Parameters::Variant::kTink: if (!id_requirement.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "id requirement must have value with kTink"); } return absl::StrCat(absl::HexStringToBytes("01"), subtle::BigEndian32(*id_requirement)); default: return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid variant: ", variant)); } } } // namespace util::StatusOr XChaCha20Poly1305Key::Create( XChaCha20Poly1305Parameters::Variant variant, const RestrictedData& key_bytes, absl::optional id_requirement, PartialKeyAccessToken token) { if (key_bytes.size() != 32) { return util::Status(absl::StatusCode::kInvalidArgument, "XChaCha20-Poly1305 key length must be 32 bytes"); } if (variant != XChaCha20Poly1305Parameters::Variant::kNoPrefix && !id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key without ID requirement with variant with ID " "requirement"); } if (variant == XChaCha20Poly1305Parameters::Variant::kNoPrefix && id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key with ID requirement with variant without ID " "requirement"); } util::StatusOr parameters = XChaCha20Poly1305Parameters::Create(variant); if (!parameters.ok()) { return parameters.status(); } util::StatusOr output_prefix = ComputeOutputPrefix(variant, id_requirement); if (!output_prefix.ok()) { return output_prefix.status(); } return XChaCha20Poly1305Key(*parameters, key_bytes, id_requirement, *std::move(output_prefix)); } bool XChaCha20Poly1305Key::operator==(const Key& other) const { const XChaCha20Poly1305Key* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (GetParameters() != that->GetParameters()) { return false; } if (id_requirement_ != that->id_requirement_) { return false; } return key_bytes_ == that->key_bytes_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/xchacha20_poly1305_key.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_XCHACHA20_POLY1305_KEY_H_ #define TINK_AEAD_XCHACHA20_POLY1305_KEY_H_ #include #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/aead/aead_key.h" #include "tink/aead/xchacha20_poly1305_parameters.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Represents an AEAD that uses XChaCha20-Poly1305. class XChaCha20Poly1305Key : public AeadKey { public: // Copyable and movable. XChaCha20Poly1305Key(const XChaCha20Poly1305Key& other) = default; XChaCha20Poly1305Key& operator=(const XChaCha20Poly1305Key& other) = default; XChaCha20Poly1305Key(XChaCha20Poly1305Key&& other) = default; XChaCha20Poly1305Key& operator=(XChaCha20Poly1305Key&& other) = default; // Creates a new XChaCha20-Poly1305 key. If `variant` uses a prefix, then the // id is used to compute this prefix. static util::StatusOr Create( XChaCha20Poly1305Parameters::Variant variant, const RestrictedData& key_bytes, absl::optional id_requirement, PartialKeyAccessToken token); // Returns the underlying XChaCha20-Poly1305 key material. const RestrictedData& GetKeyBytes(PartialKeyAccessToken token) const { return key_bytes_; } absl::string_view GetOutputPrefix() const override { return output_prefix_; } const XChaCha20Poly1305Parameters& GetParameters() const override { return parameters_; } absl::optional GetIdRequirement() const override { return id_requirement_; } bool operator==(const Key& other) const override; private: XChaCha20Poly1305Key(const XChaCha20Poly1305Parameters& parameters, const RestrictedData& key_bytes, absl::optional id_requirement, std::string output_prefix) : parameters_(parameters), key_bytes_(key_bytes), id_requirement_(id_requirement), output_prefix_(std::move(output_prefix)) {} XChaCha20Poly1305Parameters parameters_; RestrictedData key_bytes_; absl::optional id_requirement_; std::string output_prefix_; }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_XCHACHA20_POLY1305_KEY_H_ ================================================ FILE: cc/aead/xchacha20_poly1305_key_manager.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_XCHACHA20_POLY1305_KEY_MANAGER_H_ #define TINK_AEAD_XCHACHA20_POLY1305_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/aead.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/input_stream.h" #include "tink/subtle/random.h" #include "tink/subtle/xchacha20_poly1305_boringssl.h" #include "tink/util/constants.h" #include "tink/util/input_stream_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/tink.pb.h" #include "proto/xchacha20_poly1305.pb.h" namespace crypto { namespace tink { class XChaCha20Poly1305KeyManager : public KeyTypeManager> { public: class AeadFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::XChaCha20Poly1305Key& key) const override { return subtle::XChacha20Poly1305BoringSsl::New( util::SecretDataFromStringView(key.key_value())); } }; XChaCha20Poly1305KeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::SYMMETRIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::XChaCha20Poly1305Key& key) const override { crypto::tink::util::Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; uint32_t key_size = key.key_value().size(); if (key.key_value().size() != kKeySizeInBytes) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid XChaCha20Poly1305Key: key_value has ", key_size, " bytes; supported size: ", kKeySizeInBytes, " bytes.")); } return crypto::tink::util::OkStatus(); } crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::XChaCha20Poly1305KeyFormat& key_format) const override { return crypto::tink::util::OkStatus(); } crypto::tink::util::StatusOr CreateKey(const google::crypto::tink::XChaCha20Poly1305KeyFormat& key_format) const override { google::crypto::tink::XChaCha20Poly1305Key result; result.set_version(get_version()); result.set_key_value(subtle::Random::GetRandomBytes(kKeySizeInBytes)); return result; } crypto::tink::util::StatusOr DeriveKey(const google::crypto::tink::XChaCha20Poly1305KeyFormat& key_format, InputStream* input_stream) const override { crypto::tink::util::Status status = ValidateVersion(key_format.version(), get_version()); if (!status.ok()) return status; crypto::tink::util::StatusOr randomness = ReadBytesFromStream(kKeySizeInBytes, input_stream); if (!randomness.ok()) { if (randomness.status().code() == absl::StatusCode::kOutOfRange) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, "Could not get enough pseudorandomness from input stream"); } return randomness.status(); } google::crypto::tink::XChaCha20Poly1305Key key; key.set_version(get_version()); key.set_key_value(randomness.value()); return key; } private: const std::string key_type_ = absl::StrCat(kTypeGoogleapisCom, google::crypto::tink::XChaCha20Poly1305Key().GetTypeName()); const int kKeySizeInBytes = 32; }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_XCHACHA20_POLY1305_KEY_MANAGER_H_ ================================================ FILE: cc/aead/xchacha20_poly1305_key_manager_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/xchacha20_poly1305_key_manager.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/aead.h" #include "tink/internal/ssl_util.h" #include "tink/subtle/aead_test_util.h" #include "tink/subtle/xchacha20_poly1305_boringssl.h" #include "tink/util/istream_input_stream.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" #include "proto/xchacha20_poly1305.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::XChaCha20Poly1305Key; using ::google::crypto::tink::XChaCha20Poly1305KeyFormat; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::Not; using ::testing::SizeIs; TEST(XChaCha20Poly1305KeyManagerTest, Basics) { EXPECT_THAT(XChaCha20Poly1305KeyManager().get_version(), Eq(0)); EXPECT_THAT( XChaCha20Poly1305KeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key")); EXPECT_THAT(XChaCha20Poly1305KeyManager().key_material_type(), Eq(google::crypto::tink::KeyData::SYMMETRIC)); } TEST(XChaCha20Poly1305KeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(XChaCha20Poly1305KeyManager().ValidateKey(XChaCha20Poly1305Key()), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(XChaCha20Poly1305KeyManagerTest, ValidateValid32ByteKey) { XChaCha20Poly1305Key key; key.set_version(0); key.set_key_value("01234567890123456789012345678901"); EXPECT_THAT(XChaCha20Poly1305KeyManager().ValidateKey(key), IsOk()); } TEST(XChaCha20Poly1305KeyManagerTest, ValidateInvalid16ByteKey) { XChaCha20Poly1305Key key; key.set_version(0); key.set_key_value("0123456789012345"); EXPECT_THAT(XChaCha20Poly1305KeyManager().ValidateKey(key), Not(IsOk())); } TEST(XChaCha20Poly1305KeyManagerTest, ValidateInvalid31ByteKey) { XChaCha20Poly1305Key key; key.set_version(0); key.set_key_value("0123456789012345678901234567890"); EXPECT_THAT(XChaCha20Poly1305KeyManager().ValidateKey(key), Not(IsOk())); } TEST(XChaCha20Poly1305KeyManagerTest, ValidateInvalid33ByteKey) { XChaCha20Poly1305Key key; key.set_version(0); key.set_key_value("012345678901234567890123456789012"); EXPECT_THAT(XChaCha20Poly1305KeyManager().ValidateKey(key), Not(IsOk())); } TEST(XChaCha20Poly1305KeyManagerTest, ValidateInvalidVersion) { XChaCha20Poly1305Key key; key.set_version(1); key.set_key_value("01234567890123456789012345678901"); EXPECT_THAT(XChaCha20Poly1305KeyManager().ValidateKey(key), Not(IsOk())); } TEST(XChaCha20Poly1305KeyManagerTest, ValidateKeyFormat) { EXPECT_THAT(XChaCha20Poly1305KeyManager().ValidateKeyFormat( XChaCha20Poly1305KeyFormat()), IsOk()); } TEST(XChaCha20Poly1305KeyManagerTest, CreateKey) { StatusOr key_or = XChaCha20Poly1305KeyManager().CreateKey(XChaCha20Poly1305KeyFormat()); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().key_value(), SizeIs(32)); EXPECT_THAT(key_or.value().version(), Eq(0)); } TEST(XChaCha20Poly1305KeyManagerTest, DeriveKey) { util::IstreamInputStream input_stream{ absl::make_unique("0123456789abcdef0123456789abcdef")}; XChaCha20Poly1305KeyFormat format; format.set_version(0); StatusOr key_or = XChaCha20Poly1305KeyManager().DeriveKey(format, &input_stream); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().key_value(), SizeIs(32)); EXPECT_THAT(key_or.value().version(), Eq(0)); } TEST(XChaCha20Poly1305KeyManagerTest, DeriveKeyFromLongSeed) { util::IstreamInputStream input_stream{absl::make_unique( "0123456789abcdef0123456789abcdefXXX")}; XChaCha20Poly1305KeyFormat format; format.set_version(0); auto key_or = XChaCha20Poly1305KeyManager().DeriveKey(format, &input_stream); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().key_value(), Eq("0123456789abcdef0123456789abcdef")); } TEST(XChaCha20Poly1305KeyManagerTest, DeriveKeyWithoutEnoughEntropy) { util::IstreamInputStream input_stream{ absl::make_unique("0")}; XChaCha20Poly1305KeyFormat format; format.set_version(0); StatusOr key_or = XChaCha20Poly1305KeyManager().DeriveKey(format, &input_stream); ASSERT_THAT(key_or.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("pseudorandomness"))); } TEST(XChaCha20Poly1305KeyManagerTest, DeriveKeyWrongVersion) { util::IstreamInputStream input_stream{ absl::make_unique("0123456789abcdef0123456789abcdef")}; XChaCha20Poly1305KeyFormat format; format.set_version(1); StatusOr key_or = XChaCha20Poly1305KeyManager().DeriveKey(format, &input_stream); ASSERT_THAT(key_or.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("version"))); } TEST(XChaCha20Poly1305KeyManagerTest, CreateKeyValid) { StatusOr key_or = XChaCha20Poly1305KeyManager().CreateKey(XChaCha20Poly1305KeyFormat()); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(XChaCha20Poly1305KeyManager().ValidateKey(key_or.value()), IsOk()); } TEST(XChaCha20Poly1305KeyManagerTest, CreateAeadFailsWithOpenSsl) { if (internal::IsBoringSsl()) { GTEST_SKIP() << "OpenSSL-only test, skipping because Tink uses BoringSSL"; } StatusOr key = XChaCha20Poly1305KeyManager().CreateKey(XChaCha20Poly1305KeyFormat()); ASSERT_THAT(key, IsOk()); EXPECT_THAT(XChaCha20Poly1305KeyManager().GetPrimitive(*key).status(), Not(IsOk())); EXPECT_THAT(subtle::XChacha20Poly1305BoringSsl::New( util::SecretDataFromStringView(key->key_value())) .status(), Not(IsOk())); } TEST(XChaCha20Poly1305KeyManagerTest, CreateAeadSucceedsWithBoringSsl) { if (!internal::IsBoringSsl()) { GTEST_SKIP() << "XChaCha20-Poly1305 is not supported when OpenSSL is used"; } StatusOr key = XChaCha20Poly1305KeyManager().CreateKey(XChaCha20Poly1305KeyFormat()); ASSERT_THAT(key, IsOk()); StatusOr> aead = XChaCha20Poly1305KeyManager().GetPrimitive(*key); ASSERT_THAT(aead, IsOk()); StatusOr> direct_aead = subtle::XChacha20Poly1305BoringSsl::New( util::SecretDataFromStringView(key->key_value())); ASSERT_THAT(direct_aead, IsOk()); EXPECT_THAT(EncryptThenDecrypt(**aead, **direct_aead, "message", "aad"), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/xchacha20_poly1305_key_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/xchacha20_poly1305_key.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/aead/xchacha20_poly1305_parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { XChaCha20Poly1305Parameters::Variant variant; absl::optional id_requirement; std::string output_prefix; }; using XChaCha20Poly1305KeyTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( XChaCha20Poly1305KeyTestSuite, XChaCha20Poly1305KeyTest, Values(TestCase{XChaCha20Poly1305Parameters::Variant::kTink, 0x02030400, std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{XChaCha20Poly1305Parameters::Variant::kCrunchy, 0x01030005, std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{XChaCha20Poly1305Parameters::Variant::kNoPrefix, absl::nullopt, ""})); TEST_P(XChaCha20Poly1305KeyTest, CreateSucceeds) { TestCase test_case = GetParam(); util::StatusOr params = XChaCha20Poly1305Parameters::Create(test_case.variant); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = XChaCha20Poly1305Key::Create( test_case.variant, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); EXPECT_THAT(key->GetKeyBytes(GetPartialKeyAccess()), Eq(secret)); EXPECT_THAT(key->GetParameters(), Eq(*params)); EXPECT_THAT(key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(key->GetOutputPrefix(), Eq(test_case.output_prefix)); } TEST(XChaCha20Poly1305KeyTest, CreateKeyWithInvalidVariantFails) { EXPECT_THAT(XChaCha20Poly1305Key::Create( XChaCha20Poly1305Parameters::Variant:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements, /*key_bytes=*/RestrictedData(/*num_random_bytes=*/32), /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(XChaCha20Poly1305KeyTest, CreateKeyWithInvalidKeySizeFails) { // Key material must be 32 bytes. RestrictedData invalid_secret = RestrictedData(/*num_random_bytes=*/16); EXPECT_THAT(XChaCha20Poly1305Key::Create( XChaCha20Poly1305Parameters::Variant::kTink, invalid_secret, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(XChaCha20Poly1305KeyTest, CreateKeyWithInvalidIdRequirementFails) { RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); EXPECT_THAT(XChaCha20Poly1305Key::Create( XChaCha20Poly1305Parameters::Variant::kNoPrefix, secret, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(XChaCha20Poly1305Key::Create( XChaCha20Poly1305Parameters::Variant::kTink, secret, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(XChaCha20Poly1305KeyTest, KeyEquals) { TestCase test_case = GetParam(); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = XChaCha20Poly1305Key::Create( test_case.variant, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = XChaCha20Poly1305Key::Create( test_case.variant, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key == *other_key); EXPECT_TRUE(*other_key == *key); EXPECT_FALSE(*key != *other_key); EXPECT_FALSE(*other_key != *key); } TEST(XChaCha20Poly1305KeyTest, DifferentVariantNotEqual) { RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = XChaCha20Poly1305Key::Create( XChaCha20Poly1305Parameters::Variant::kCrunchy, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = XChaCha20Poly1305Key::Create( XChaCha20Poly1305Parameters::Variant::kTink, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST(XChaCha20Poly1305KeyTest, DifferentSecretDataNotEqual) { RestrictedData secret1 = RestrictedData(/*num_random_bytes=*/32); RestrictedData secret2 = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = XChaCha20Poly1305Key::Create( XChaCha20Poly1305Parameters::Variant::kTink, secret1, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = XChaCha20Poly1305Key::Create( XChaCha20Poly1305Parameters::Variant::kTink, secret2, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST(XChaCha20Poly1305KeyTest, DifferentIdRequirementNotEqual) { RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = XChaCha20Poly1305Key::Create( XChaCha20Poly1305Parameters::Variant::kTink, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = XChaCha20Poly1305Key::Create( XChaCha20Poly1305Parameters::Variant::kTink, secret, /*id_requirement=*/0x02030405, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/xchacha20_poly1305_parameters.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/xchacha20_poly1305_parameters.h" #include #include "absl/status/status.h" #include "tink/parameters.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { util::StatusOr XChaCha20Poly1305Parameters::Create( Variant variant) { static const std::set* kSupportedVariants = new std::set( {Variant::kTink, Variant::kCrunchy, Variant::kNoPrefix}); if (kSupportedVariants->find(variant) == kSupportedVariants->end()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create XChaCha20-Poly1305 parameters with unknown variant."); } return XChaCha20Poly1305Parameters(variant); } bool XChaCha20Poly1305Parameters::operator==(const Parameters& other) const { const XChaCha20Poly1305Parameters* that = dynamic_cast(&other); return that != nullptr && variant_ == that->variant_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/xchacha20_poly1305_parameters.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_XCHACHA20_POLY1305_PARAMETERS_H_ #define TINK_AEAD_XCHACHA20_POLY1305_PARAMETERS_H_ #include "tink/aead/aead_parameters.h" #include "tink/parameters.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Describes the parameters of an `XChaCha20Poly1305Key`. class XChaCha20Poly1305Parameters : public AeadParameters { public: // Description of the output prefix prepended to the ciphertext. enum class Variant : int { // Prepends '0x01' to the ciphertext. kTink = 1, // Prepends '0x00' to the ciphertext. kCrunchy = 2, // Does not prepend any prefix (i.e., keys must have no ID requirement). kNoPrefix = 3, // Added to guard from failures that may be caused by future expansions. kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Copyable and movable. XChaCha20Poly1305Parameters(const XChaCha20Poly1305Parameters& other) = default; XChaCha20Poly1305Parameters& operator=( const XChaCha20Poly1305Parameters& other) = default; XChaCha20Poly1305Parameters(XChaCha20Poly1305Parameters&& other) = default; XChaCha20Poly1305Parameters& operator=(XChaCha20Poly1305Parameters&& other) = default; // Creates a new XChaCha20-Poly1305 parameters object. Returns an error if // `variant` is invalid. static util::StatusOr Create(Variant variant); Variant GetVariant() const { return variant_; } bool HasIdRequirement() const override { return variant_ != Variant::kNoPrefix; } bool operator==(const Parameters& other) const override; private: explicit XChaCha20Poly1305Parameters(Variant variant) : variant_(variant) {} Variant variant_; }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_XCHACHA20_POLY1305_PARAMETERS_H_ ================================================ FILE: cc/aead/xchacha20_poly1305_parameters_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/xchacha20_poly1305_parameters.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::IsTrue; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { XChaCha20Poly1305Parameters::Variant variant; bool has_id_requirement; }; using XChaCha20Poly1305ParametersTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( XChaCha20Poly1305ParametersTestSuite, XChaCha20Poly1305ParametersTest, Values(TestCase{XChaCha20Poly1305Parameters::Variant::kTink, /*has_id_requirement=*/true}, TestCase{XChaCha20Poly1305Parameters::Variant::kCrunchy, /*has_id_requirement=*/true}, TestCase{XChaCha20Poly1305Parameters::Variant::kNoPrefix, /*has_id_requirement=*/false})); TEST_P(XChaCha20Poly1305ParametersTest, Create) { TestCase test_case = GetParam(); util::StatusOr parameters = XChaCha20Poly1305Parameters::Create(test_case.variant); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(parameters->HasIdRequirement(), Eq(test_case.has_id_requirement)); } TEST(XChaCha20Poly1305ParametersTest, CreateWithInvalidVariantFails) { EXPECT_THAT(XChaCha20Poly1305Parameters::Create( XChaCha20Poly1305Parameters::Variant:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(XChaCha20Poly1305ParametersTest, CopyConstructor) { util::StatusOr parameters = XChaCha20Poly1305Parameters::Create( XChaCha20Poly1305Parameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); XChaCha20Poly1305Parameters copy(*parameters); EXPECT_THAT(copy.GetVariant(), Eq(XChaCha20Poly1305Parameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); } TEST(XChaCha20Poly1305ParametersTest, CopyAssignment) { util::StatusOr parameters = XChaCha20Poly1305Parameters::Create( XChaCha20Poly1305Parameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); XChaCha20Poly1305Parameters copy = *parameters; EXPECT_THAT(copy.GetVariant(), Eq(XChaCha20Poly1305Parameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); } TEST_P(XChaCha20Poly1305ParametersTest, ParametersEquals) { TestCase test_case = GetParam(); util::StatusOr parameters = XChaCha20Poly1305Parameters::Create(test_case.variant); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = XChaCha20Poly1305Parameters::Create(test_case.variant); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters == *other_parameters); EXPECT_TRUE(*other_parameters == *parameters); EXPECT_FALSE(*parameters != *other_parameters); EXPECT_FALSE(*other_parameters != *parameters); } TEST(XChaCha20Poly1305ParametersTest, DifferentVariantNotEqual) { util::StatusOr parameters = XChaCha20Poly1305Parameters::Create( XChaCha20Poly1305Parameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = XChaCha20Poly1305Parameters::Create( XChaCha20Poly1305Parameters::Variant::kNoPrefix); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/xchacha20_poly1305_proto_serialization.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/xchacha20_poly1305_proto_serialization.h" #include #include "absl/base/attributes.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/aead/xchacha20_poly1305_key.h" #include "tink/aead/xchacha20_poly1305_parameters.h" #include "tink/internal/key_parser.h" #include "tink/internal/key_serializer.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/parameters_parser.h" #include "tink/internal/parameters_serializer.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/secret_key_access_token.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" #include "proto/xchacha20_poly1305.pb.h" namespace crypto { namespace tink { namespace { using ::google::crypto::tink::OutputPrefixType; using ::google::crypto::tink::XChaCha20Poly1305KeyFormat; using XChaCha20Poly1305ProtoParametersParserImpl = internal::ParametersParserImpl; using XChaCha20Poly1305ProtoParametersSerializerImpl = internal::ParametersSerializerImpl; using XChaCha20Poly1305ProtoKeyParserImpl = internal::KeyParserImpl; using XChaCha20Poly1305ProtoKeySerializerImpl = internal::KeySerializerImpl; const absl::string_view kTypeUrl = "type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key"; util::StatusOr ToVariant( OutputPrefixType output_prefix_type) { switch (output_prefix_type) { case OutputPrefixType::LEGACY: ABSL_FALLTHROUGH_INTENDED; // Parse LEGACY output prefix as CRUNCHY. case OutputPrefixType::CRUNCHY: return XChaCha20Poly1305Parameters::Variant::kCrunchy; case OutputPrefixType::RAW: return XChaCha20Poly1305Parameters::Variant::kNoPrefix; case OutputPrefixType::TINK: return XChaCha20Poly1305Parameters::Variant::kTink; default: return util::Status( absl::StatusCode::kInvalidArgument, "Could not determine XChaCha20Poly1305Parameters::Variant"); } } util::StatusOr ToOutputPrefixType( XChaCha20Poly1305Parameters::Variant variant) { switch (variant) { case XChaCha20Poly1305Parameters::Variant::kCrunchy: return OutputPrefixType::CRUNCHY; case XChaCha20Poly1305Parameters::Variant::kNoPrefix: return OutputPrefixType::RAW; case XChaCha20Poly1305Parameters::Variant::kTink: return OutputPrefixType::TINK; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine output prefix type"); } } util::StatusOr ParseParameters( const internal::ProtoParametersSerialization& serialization) { if (serialization.GetKeyTemplate().type_url() != kTypeUrl) { return util::Status( absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing XChaCha20Poly1305Parameters."); } XChaCha20Poly1305KeyFormat proto_key_format; if (!proto_key_format.ParseFromString( serialization.GetKeyTemplate().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse XChaCha20Poly1305KeyFormat proto"); } if (proto_key_format.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } util::StatusOr variant = ToVariant(serialization.GetKeyTemplate().output_prefix_type()); if (!variant.ok()) return variant.status(); return XChaCha20Poly1305Parameters::Create(*variant); } util::StatusOr SerializeParameters( const XChaCha20Poly1305Parameters& parameters) { util::StatusOr output_prefix_type = ToOutputPrefixType(parameters.GetVariant()); if (!output_prefix_type.ok()) return output_prefix_type.status(); XChaCha20Poly1305KeyFormat proto_key_format; proto_key_format.set_version(0); return internal::ProtoParametersSerialization::Create( kTypeUrl, *output_prefix_type, proto_key_format.SerializeAsString()); } util::StatusOr ParseKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (serialization.TypeUrl() != kTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing XChaCha20Poly1305Key."); } if (!token.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "SecretKeyAccess is required"); } google::crypto::tink::XChaCha20Poly1305Key proto_key; const RestrictedData& restricted_data = serialization.SerializedKeyProto(); if (!proto_key.ParseFromString(restricted_data.GetSecret(*token))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse XChaCha20Poly1305Key proto"); } if (proto_key.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } util::StatusOr variant = ToVariant(serialization.GetOutputPrefixType()); if (!variant.ok()) return variant.status(); util::StatusOr parameters = XChaCha20Poly1305Parameters::Create(*variant); if (!parameters.ok()) return parameters.status(); return XChaCha20Poly1305Key::Create( parameters->GetVariant(), RestrictedData(proto_key.key_value(), *token), serialization.IdRequirement(), GetPartialKeyAccess()); } util::StatusOr SerializeKey( const XChaCha20Poly1305Key& key, absl::optional token) { util::StatusOr restricted_input = key.GetKeyBytes(GetPartialKeyAccess()); if (!restricted_input.ok()) return restricted_input.status(); if (!token.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "SecretKeyAccess is required"); } google::crypto::tink::XChaCha20Poly1305Key proto_key; proto_key.set_version(0); proto_key.set_key_value(restricted_input->GetSecret(*token)); util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetParameters().GetVariant()); if (!output_prefix_type.ok()) return output_prefix_type.status(); RestrictedData restricted_output = RestrictedData(proto_key.SerializeAsString(), *token); return internal::ProtoKeySerialization::Create( kTypeUrl, restricted_output, google::crypto::tink::KeyData::SYMMETRIC, *output_prefix_type, key.GetIdRequirement()); } XChaCha20Poly1305ProtoParametersParserImpl* XChaCha20Poly1305ProtoParametersParser() { static auto* parser = new XChaCha20Poly1305ProtoParametersParserImpl(kTypeUrl, ParseParameters); return parser; } XChaCha20Poly1305ProtoParametersSerializerImpl* XChaCha20Poly1305ProtoParametersSerializer() { static auto* serializer = new XChaCha20Poly1305ProtoParametersSerializerImpl( kTypeUrl, SerializeParameters); return serializer; } XChaCha20Poly1305ProtoKeyParserImpl* XChaCha20Poly1305ProtoKeyParser() { static auto* parser = new XChaCha20Poly1305ProtoKeyParserImpl(kTypeUrl, ParseKey); return parser; } XChaCha20Poly1305ProtoKeySerializerImpl* XChaCha20Poly1305ProtoKeySerializer() { static auto* serializer = new XChaCha20Poly1305ProtoKeySerializerImpl(SerializeKey); return serializer; } } // namespace util::Status RegisterXChaCha20Poly1305ProtoSerialization() { util::Status status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersParser(XChaCha20Poly1305ProtoParametersParser()); if (!status.ok()) return status; status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersSerializer( XChaCha20Poly1305ProtoParametersSerializer()); if (!status.ok()) return status; status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(XChaCha20Poly1305ProtoKeyParser()); if (!status.ok()) return status; return internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(XChaCha20Poly1305ProtoKeySerializer()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/aead/xchacha20_poly1305_proto_serialization.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_XCHACHA20_POLY1305_PROTO_SERIALIZATION_H_ #define TINK_AEAD_XCHACHA20_POLY1305_PROTO_SERIALIZATION_H_ #include "tink/util/status.h" namespace crypto { namespace tink { // Registers proto parsers and serializers for XChaCha20-Poly1305 parameters and // keys. crypto::tink::util::Status RegisterXChaCha20Poly1305ProtoSerialization(); } // namespace tink } // namespace crypto #endif // TINK_AEAD_XCHACHA20_POLY1305_PROTO_SERIALIZATION_H_ ================================================ FILE: cc/aead/xchacha20_poly1305_proto_serialization_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/aead/xchacha20_poly1305_proto_serialization.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/aead/xchacha20_poly1305_key.h" #include "tink/aead/xchacha20_poly1305_parameters.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/subtle/random.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" #include "proto/xchacha20_poly1305.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::subtle::Random; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::google::crypto::tink::XChaCha20Poly1305KeyFormat; using ::testing::Eq; using ::testing::IsTrue; using ::testing::NotNull; using ::testing::TestWithParam; using ::testing::Values; constexpr absl::string_view kTypeUrl = "type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key"; struct TestCase { XChaCha20Poly1305Parameters::Variant variant; OutputPrefixType output_prefix_type; absl::optional id; std::string output_prefix; }; class XChaCha20Poly1305ProtoSerializationTest : public TestWithParam { protected: void SetUp() override { internal::MutableSerializationRegistry::GlobalInstance().Reset(); } }; TEST_F(XChaCha20Poly1305ProtoSerializationTest, RegisterTwiceSucceeds) { ASSERT_THAT(RegisterXChaCha20Poly1305ProtoSerialization(), IsOk()); ASSERT_THAT(RegisterXChaCha20Poly1305ProtoSerialization(), IsOk()); } INSTANTIATE_TEST_SUITE_P( XChaCha20Poly1305ProtoSerializationTestSuite, XChaCha20Poly1305ProtoSerializationTest, Values(TestCase{XChaCha20Poly1305Parameters::Variant::kTink, OutputPrefixType::TINK, /*id=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{XChaCha20Poly1305Parameters::Variant::kCrunchy, OutputPrefixType::CRUNCHY, /*id=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{XChaCha20Poly1305Parameters::Variant::kNoPrefix, OutputPrefixType::RAW, /*id=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(XChaCha20Poly1305ProtoSerializationTest, ParseParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterXChaCha20Poly1305ProtoSerialization(), IsOk()); XChaCha20Poly1305KeyFormat key_format_proto; key_format_proto.set_version(0); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kTypeUrl, test_case.output_prefix_type, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(params, IsOk()); EXPECT_THAT((*params)->HasIdRequirement(), test_case.id.has_value()); const XChaCha20Poly1305Parameters* xchacha20_poly1305_params = dynamic_cast(params->get()); ASSERT_THAT(xchacha20_poly1305_params, NotNull()); EXPECT_THAT(xchacha20_poly1305_params->GetVariant(), Eq(test_case.variant)); } TEST_F(XChaCha20Poly1305ProtoSerializationTest, ParseParametersWithInvalidSerialization) { ASSERT_THAT(RegisterXChaCha20Poly1305ProtoSerialization(), IsOk()); XChaCha20Poly1305KeyFormat key_format_proto; key_format_proto.set_version(0); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kTypeUrl, OutputPrefixType::RAW, "invalid_serialization"); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(XChaCha20Poly1305ProtoSerializationTest, ParseParametersWithUnkownOutputPrefix) { ASSERT_THAT(RegisterXChaCha20Poly1305ProtoSerialization(), IsOk()); XChaCha20Poly1305KeyFormat key_format_proto; key_format_proto.set_version(0); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kTypeUrl, OutputPrefixType::UNKNOWN_PREFIX, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(XChaCha20Poly1305ProtoSerializationTest, ParseParametersWithInvalidVersion) { ASSERT_THAT(RegisterXChaCha20Poly1305ProtoSerialization(), IsOk()); XChaCha20Poly1305KeyFormat key_format_proto; key_format_proto.set_version(1); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kTypeUrl, OutputPrefixType::RAW, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(XChaCha20Poly1305ProtoSerializationTest, SerializeParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterXChaCha20Poly1305ProtoSerialization(), IsOk()); util::StatusOr parameters = XChaCha20Poly1305Parameters::Create(test_case.variant); ASSERT_THAT(parameters, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( *parameters); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kTypeUrl)); const internal::ProtoParametersSerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->GetKeyTemplate().type_url(), Eq(kTypeUrl)); EXPECT_THAT(proto_serialization->GetKeyTemplate().output_prefix_type(), Eq(test_case.output_prefix_type)); XChaCha20Poly1305KeyFormat key_format; ASSERT_THAT( key_format.ParseFromString(proto_serialization->GetKeyTemplate().value()), IsTrue()); EXPECT_THAT(key_format.version(), Eq(0)); } TEST_P(XChaCha20Poly1305ProtoSerializationTest, ParseKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterXChaCha20Poly1305ProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); google::crypto::tink::XChaCha20Poly1305Key key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kTypeUrl, serialized_key, KeyData::SYMMETRIC, test_case.output_prefix_type, test_case.id); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); EXPECT_THAT((*key)->GetIdRequirement(), Eq(test_case.id)); EXPECT_THAT((*key)->GetParameters().HasIdRequirement(), test_case.id.has_value()); util::StatusOr expected_parameters = XChaCha20Poly1305Parameters::Create(test_case.variant); ASSERT_THAT(expected_parameters, IsOk()); util::StatusOr expected_key = XChaCha20Poly1305Key::Create( expected_parameters->GetVariant(), RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(expected_key, IsOk()); EXPECT_THAT(**key, Eq(*expected_key)); } TEST_F(XChaCha20Poly1305ProtoSerializationTest, ParseLegacyKeyAsCrunchy) { ASSERT_THAT(RegisterXChaCha20Poly1305ProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); google::crypto::tink::XChaCha20Poly1305Key key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::LEGACY, /*id_requirement=*/123); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); const XChaCha20Poly1305Key* xchacha20_poly1305_key = dynamic_cast(key->get()); ASSERT_THAT(xchacha20_poly1305_key, NotNull()); EXPECT_THAT(xchacha20_poly1305_key->GetParameters().GetVariant(), Eq(XChaCha20Poly1305Parameters::Variant::kCrunchy)); } TEST_F(XChaCha20Poly1305ProtoSerializationTest, ParseKeyWithInvalidSerialization) { ASSERT_THAT(RegisterXChaCha20Poly1305ProtoSerialization(), IsOk()); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(XChaCha20Poly1305ProtoSerializationTest, ParseKeyNoSecretKeyAccess) { ASSERT_THAT(RegisterXChaCha20Poly1305ProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(64); google::crypto::tink::XChaCha20Poly1305Key key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(XChaCha20Poly1305ProtoSerializationTest, ParseKeyWithInvalidVersion) { ASSERT_THAT(RegisterXChaCha20Poly1305ProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(64); google::crypto::tink::XChaCha20Poly1305Key key_proto; key_proto.set_version(1); // Invalid version number. key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(XChaCha20Poly1305ProtoSerializationTest, SerializeKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterXChaCha20Poly1305ProtoSerialization(), IsOk()); util::StatusOr parameters = XChaCha20Poly1305Parameters::Create(test_case.variant); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); util::StatusOr key = XChaCha20Poly1305Key::Create( parameters->GetVariant(), RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kTypeUrl)); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq(kTypeUrl)); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::SYMMETRIC)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id)); google::crypto::tink::XChaCha20Poly1305Key proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.key_value().size(), Eq(32)); } TEST_F(XChaCha20Poly1305ProtoSerializationTest, SerializeKeyNoSecretKeyAccess) { ASSERT_THAT(RegisterXChaCha20Poly1305ProtoSerialization(), IsOk()); util::StatusOr parameters = XChaCha20Poly1305Parameters::Create( XChaCha20Poly1305Parameters::Variant::kNoPrefix); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); util::StatusOr key = XChaCha20Poly1305Key::Create( parameters->GetVariant(), RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey(*key, absl::nullopt); EXPECT_THAT(serialization.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/aead.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_H_ #define TINK_AEAD_H_ #include #include "absl/strings/string_view.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // The interface for authenticated encryption with associated data. // Implementations of this interface are secure against adaptive // chosen ciphertext attacks. Encryption with associated data ensures // authenticity and integrity of that data, but not its secrecy. // (see RFC 5116, https://tools.ietf.org/html/rfc5116) // // Implementations are expected to be thread safe. class Aead { public: // Encrypts 'plaintext' with 'associated_data' as associated data, // and returns the resulting ciphertext. // The ciphertext allows for checking authenticity and integrity // of the associated data, but does not guarantee its secrecy. virtual crypto::tink::util::StatusOr Encrypt( absl::string_view plaintext, absl::string_view associated_data) const = 0; // Decrypts 'ciphertext' with 'associated_data' as associated data, // and returns the resulting plaintext. // The decryption verifies the authenticity and integrity // of the associated data, but there are no guarantees wrt. secrecy // of that data. virtual crypto::tink::util::StatusOr Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const = 0; virtual ~Aead() = default; }; } // namespace tink } // namespace crypto #endif // TINK_AEAD_H_ ================================================ FILE: cc/aead_config.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_CONFIG_H_ #define TINK_AEAD_CONFIG_H_ #include "tink/aead/aead_config.h" // IWYU pragma: export #endif // TINK_AEAD_CONFIG_H_ ================================================ FILE: cc/aead_factory.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_FACTORY_H_ #define TINK_AEAD_FACTORY_H_ #include "tink/aead/aead_factory.h" // IWYU pragma: export #endif // TINK_AEAD_FACTORY_H_ ================================================ FILE: cc/aead_key_templates.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_AEAD_KEY_TEMPLATES_H_ #define TINK_AEAD_KEY_TEMPLATES_H_ #include "tink/aead/aead_key_templates.h" // IWYU pragma: export #endif // TINK_AEAD_KEY_TEMPLATES_H_ ================================================ FILE: cc/big_integer.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_BIG_INTEGER_H_ #define TINK_BIG_INTEGER_H_ #include #include #include "absl/strings/string_view.h" namespace crypto { namespace tink { // Stores a BigInteger value as a big endian encoded string. Removes leading // zeros prior to creation. This class is particularly useful for working with // certain primitives which use big integers types for the parameters and key // material. class BigInteger { public: // Copyable and movable. BigInteger(const BigInteger& other) = default; BigInteger& operator=(const BigInteger& other) = default; BigInteger(BigInteger&& other) = default; BigInteger& operator=(BigInteger&& other) = default; // Creates a new BigInteger object that wraps a big endian encoded // string and removes leading zeros. explicit BigInteger(absl::string_view big_integer); // Returns the value of this BigInteger object. absl::string_view GetValue() const { return value_; } int64_t SizeInBytes() const { return value_.size(); } // Constant-time comparison operators. bool operator==(const BigInteger& other) const; bool operator!=(const BigInteger& other) const { return !(*this == other); } private: std::string value_; }; } // namespace tink } // namespace crypto #endif // TINK_BIG_INTEGER_H_ ================================================ FILE: cc/binary_keyset_reader.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_BINARY_KEYSET_READER_H_ #define TINK_BINARY_KEYSET_READER_H_ #include #include #include #include "absl/strings/string_view.h" #include "tink/keyset_reader.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // A KeysetReader that can read from some source cleartext or // encrypted keysets in proto binary wire format, cf. // https://developers.google.com/protocol-buffers/docs/encoding class BinaryKeysetReader : public KeysetReader { public: static crypto::tink::util::StatusOr> New( std::unique_ptr keyset_stream); static crypto::tink::util::StatusOr> New( absl::string_view serialized_keyset); crypto::tink::util::StatusOr> Read() override; crypto::tink::util::StatusOr< std::unique_ptr> ReadEncrypted() override; private: explicit BinaryKeysetReader(absl::string_view serialized_keyset) : serialized_keyset_(serialized_keyset) {} std::string serialized_keyset_; }; } // namespace tink } // namespace crypto #endif // TINK_BINARY_KEYSET_READER_H_ ================================================ FILE: cc/binary_keyset_writer.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_BINARY_KEYSET_WRITER_H_ #define TINK_BINARY_KEYSET_WRITER_H_ #include #include #include #include "absl/strings/string_view.h" #include "tink/keyset_writer.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // A KeysetWriter that can write to some destination cleartext // or encrypted keysets in proto binary wire format, cf. // https://developers.google.com/protocol-buffers/docs/encoding class BinaryKeysetWriter : public KeysetWriter { public: static crypto::tink::util::StatusOr> New( std::unique_ptr destination_stream); crypto::tink::util::Status Write(const google::crypto::tink::Keyset& keyset) override; crypto::tink::util::Status Write(const google::crypto::tink::EncryptedKeyset& encrypted_keyset) override; private: explicit BinaryKeysetWriter(std::unique_ptr destination_stream) : destination_stream_(std::move(destination_stream)) {} std::unique_ptr destination_stream_; }; } // namespace tink } // namespace crypto #endif // TINK_BINARY_KEYSET_WRITER_H_ ================================================ FILE: cc/chunked_mac.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_CHUNKED_MAC_H_ #define TINK_CHUNKED_MAC_H_ #include #include #include "absl/strings/string_view.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Interface for a single Chunked MAC computation. // // WARNING: Although implementations of this interface are thread-compatible, // they are not thread-safe. Thread-safety must be enforced by the caller. class ChunkedMacComputation { public: // Incrementally processes input `data` to update the internal state of the // MAC computation. Requires exclusive access. // // Note that the following two update sequences are equivalent (i.e., // arbitrary slicing of the input data is allowed): // 1. Update("ab"), Update("cd"), Update("ef") // 2. Update("abc"), Update("def") virtual util::Status Update(absl::string_view data) = 0; // Finalizes the MAC computation and returns the authentication tag. // After this method has been called, this object can no longer be used. // Requires exclusive access. virtual util::StatusOr ComputeMac() = 0; virtual ~ChunkedMacComputation() = default; }; // Interface for a single Chunked MAC verification. // // WARNING: Although implementations of this interface are thread-compatible, // they are not thread-safe. Thread-safety must be enforced by the caller. class ChunkedMacVerification { public: // Incrementally processes input `data` to update the internal state of the // MAC verification. Requires exclusive access. // // Note that the following two update sequences are equivalent (i.e., // arbitrary slicing of the input data is allowed): // 1. Update("ab"), Update("cd"), Update("ef") // 2. Update("abc"), Update("def") virtual util::Status Update(absl::string_view data) = 0; // Finalizes the MAC computation and returns OK if the tag is successfully // verified. Otherwise, returns an error status. After this method has been // called, this object can no longer be used. Requires exclusive access. virtual util::Status VerifyMac() = 0; virtual ~ChunkedMacVerification() = default; }; // Interface for Chunked MACs (Message Authentication Codes). // This interface should only be used for authentication. It should NOT // be used for other purposes (e.g., generating pseudorandom bytes). class ChunkedMac { public: // Creates an instance of a single Chunked MAC computation. Note that a // `ChunkedMac` object does not need to outlive the `ChunkedMacComputation` // objects that it creates. virtual util::StatusOr> CreateComputation() const = 0; // Creates an instance of a single Chunked MAC verification. Note that a // `ChunkedMac` object does not need to outlive the `ChunkedMacVerification` // objects that it creates. virtual util::StatusOr> CreateVerification(absl::string_view tag) const = 0; virtual ~ChunkedMac() = default; }; } // namespace tink } // namespace crypto #endif // TINK_CHUNKED_MAC_H_ ================================================ FILE: cc/cleartext_keyset_handle.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_CLEARTEXT_KEYSET_HANDLE_H_ #define TINK_CLEARTEXT_KEYSET_HANDLE_H_ #include #include #include #include #include "absl/container/flat_hash_map.h" #include "tink/keyset_handle.h" #include "tink/keyset_reader.h" #include "tink/keyset_writer.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // Creates keyset handles from cleartext keysets. This API allows // loading cleartext keysets, thus its usage should be restricted. class CleartextKeysetHandle { public: // Creates a KeysetHandle with a keyset obtained via `reader`. Optionally // allows to pass monitoring_annotations to attach additional data to the // resulting KeysetHandle, which will be used for monitoring. static crypto::tink::util::StatusOr> Read( std::unique_ptr reader, const absl::flat_hash_map& monitoring_annotations = {}); // Writes the keyset in the given `keyset_handle` to the `writer` which must // be non-null. static crypto::tink::util::Status Write(KeysetWriter* writer, const KeysetHandle& keyset_handle); // Creates a KeysetHandle object for the given 'keyset'. static std::unique_ptr GetKeysetHandle( const google::crypto::tink::Keyset& keyset); // Returns a Keyset-proto from the given 'keyset_handle'. static const google::crypto::tink::Keyset& GetKeyset( const KeysetHandle& keyset_handle); private: CleartextKeysetHandle() {} }; } // namespace tink } // namespace crypto #endif // TINK_CLEARTEXT_KEYSET_HANDLE_H_ ================================================ FILE: cc/config/BUILD.bazel ================================================ load("@bazel_skylib//rules:common_settings.bzl", "bool_flag") package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "tink_config", srcs = ["tink_config.cc"], hdrs = ["tink_config.h"], include_prefix = "tink/config", visibility = ["//visibility:public"], deps = [ "//:key_manager", "//:registry", "//daead:deterministic_aead_config", "//hybrid:hybrid_config", "//prf:prf_config", "//proto:config_cc_proto", "//signature:signature_config", "//streamingaead:streaming_aead_config", "//util:status", "@com_google_absl//absl/base:core_headers", ], ) cc_library( name = "config_util", srcs = ["config_util.cc"], hdrs = ["config_util.h"], include_prefix = "tink/config", deps = ["//proto:config_cc_proto"], ) bool_flag( name = "use_only_fips", build_setting_default = False, ) cc_library( name = "tink_fips", srcs = ["tink_fips.cc"], hdrs = ["tink_fips.h"], include_prefix = "tink/config", visibility = ["//visibility:public"], deps = [ "//internal:fips_utils", "//internal:registry_impl", "//util:status", "@boringssl//:crypto", "@com_google_absl//absl/base:core_headers", ], ) cc_library( name = "global_registry", srcs = ["global_registry.cc"], hdrs = ["global_registry.h"], include_prefix = "tink/config", visibility = ["//visibility:public"], deps = [ "//:configuration", "//:key_gen_configuration", "//internal:configuration_impl", "//internal:key_gen_configuration_impl", "@com_google_absl//absl/log:check", ], ) cc_library( name = "fips_140_2", srcs = ["fips_140_2.cc"], hdrs = ["fips_140_2.h"], include_prefix = "tink/config", visibility = ["//visibility:public"], deps = [ "//:configuration", "//aead:aead_wrapper", "//aead:aes_ctr_hmac_aead_key_manager", "//aead:aes_gcm_key_manager", "//internal:configuration_impl", "//internal:fips_utils", "//mac:hmac_key_manager", "//mac:mac_wrapper", "//mac/internal:chunked_mac_wrapper", "//prf:hmac_prf_key_manager", "//prf:prf_set_wrapper", "//signature:ecdsa_sign_key_manager", "//signature:ecdsa_verify_key_manager", "//signature:public_key_sign_wrapper", "//signature:public_key_verify_wrapper", "//signature:rsa_ssa_pkcs1_sign_key_manager", "//signature:rsa_ssa_pkcs1_verify_key_manager", "//signature:rsa_ssa_pss_sign_key_manager", "//signature:rsa_ssa_pss_verify_key_manager", "@com_google_absl//absl/log:check", ], ) cc_library( name = "key_gen_fips_140_2", srcs = ["key_gen_fips_140_2.cc"], hdrs = ["key_gen_fips_140_2.h"], include_prefix = "tink/config", visibility = ["//visibility:public"], deps = [ "//:key_gen_configuration", "//aead:aes_ctr_hmac_aead_key_manager", "//aead:aes_gcm_key_manager", "//internal:fips_utils", "//internal:key_gen_configuration_impl", "//mac:hmac_key_manager", "//prf:hmac_prf_key_manager", "//signature:ecdsa_sign_key_manager", "//signature:ecdsa_verify_key_manager", "//signature:rsa_ssa_pkcs1_sign_key_manager", "//signature:rsa_ssa_pkcs1_verify_key_manager", "//signature:rsa_ssa_pss_sign_key_manager", "//signature:rsa_ssa_pss_verify_key_manager", "@com_google_absl//absl/log:check", ], ) cc_library( name = "v0", srcs = ["v0.cc"], hdrs = ["v0.h"], include_prefix = "tink/config", tags = ["requires_boringcrypto_update"], deps = [ "//:configuration", "//aead/internal:config_v0", "//daead/internal:config_v0", "//hybrid/internal:config_v0", "//internal:configuration_impl", "//mac/internal:config_v0", "//prf/internal:config_v0", "//signature/internal:config_v0", "//streamingaead/internal:config_v0", "@com_google_absl//absl/log:check", ], ) cc_library( name = "key_gen_v0", srcs = ["key_gen_v0.cc"], hdrs = ["key_gen_v0.h"], include_prefix = "tink/config", tags = ["requires_boringcrypto_update"], deps = [ "//:key_gen_configuration", "//aead/internal:key_gen_config_v0", "//daead/internal:key_gen_config_v0", "//hybrid/internal:key_gen_config_v0", "//mac/internal:key_gen_config_v0", "//prf/internal:key_gen_config_v0", "//signature/internal:key_gen_config_v0", "//streamingaead/internal:key_gen_config_v0", "@com_google_absl//absl/log:check", ], ) # tests cc_test( name = "tink_config_test", size = "small", srcs = ["tink_config_test.cc"], deps = [ ":tink_config", "//:aead", "//:deterministic_aead", "//:hybrid_decrypt", "//:hybrid_encrypt", "//:mac", "//:registry", "//:streaming_aead", "//:tink_cc", "//aead:aes_gcm_key_manager", "//util:status", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "config_util_test", size = "small", srcs = ["config_util_test.cc"], deps = [ ":config_util", "//proto:config_cc_proto", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "tink_fips_test", size = "small", srcs = ["tink_fips_test.cc"], tags = ["fips"], deps = [ ":tink_fips", "//:registry", "//aead:aead_config", "//internal:fips_utils", "//util:status", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "global_registry_test", srcs = ["global_registry_test.cc"], deps = [ ":global_registry", "//:core/key_type_manager", "//:core/template_util", "//:input_stream", "//:keyset_handle", "//:primitive_set", "//:primitive_wrapper", "//:registry", "//proto:aes_gcm_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "fips_140_2_test", srcs = ["fips_140_2_test.cc"], deps = [ ":fips_140_2", ":key_gen_fips_140_2", "//:aead", "//:chunked_mac", "//:keyset_handle", "//:mac", "//:public_key_sign", "//:public_key_verify", "//aead:aead_key_templates", "//aead:aes_ctr_hmac_aead_key_manager", "//aead:aes_gcm_key_manager", "//internal:configuration_impl", "//internal:fips_utils", "//internal:key_type_info_store", "//internal:keyset_wrapper_store", "//mac:aes_cmac_key_manager", "//mac:hmac_key_manager", "//prf:hmac_prf_key_manager", "//prf:prf_set", "//signature:ecdsa_verify_key_manager", "//signature:rsa_ssa_pkcs1_verify_key_manager", "//signature:rsa_ssa_pss_verify_key_manager", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "key_gen_fips_140_2_test", srcs = ["key_gen_fips_140_2_test.cc"], deps = [ ":key_gen_fips_140_2", "//:keyset_handle", "//aead:aead_key_templates", "//aead:aes_ctr_hmac_aead_key_manager", "//aead:aes_gcm_key_manager", "//internal:fips_utils", "//internal:key_gen_configuration_impl", "//internal:key_type_info_store", "//mac:aes_cmac_key_manager", "//mac:hmac_key_manager", "//prf:hmac_prf_key_manager", "//signature:ecdsa_verify_key_manager", "//signature:rsa_ssa_pkcs1_verify_key_manager", "//signature:rsa_ssa_pss_verify_key_manager", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "v0_test", srcs = ["v0_test.cc"], tags = ["requires_boringcrypto_update"], deps = [ ":key_gen_v0", ":v0", "//:aead", "//:chunked_mac", "//:configuration", "//:deterministic_aead", "//:hybrid_decrypt", "//:hybrid_encrypt", "//:keyset_handle", "//:mac", "//:public_key_sign", "//:public_key_verify", "//:streaming_aead", "//aead:aead_key_templates", "//aead:aes_ctr_hmac_aead_key_manager", "//aead:aes_eax_key_manager", "//aead:aes_gcm_key_manager", "//aead:aes_gcm_siv_key_manager", "//aead:xchacha20_poly1305_key_manager", "//daead:aes_siv_key_manager", "//hybrid:ecies_aead_hkdf_public_key_manager", "//hybrid/internal:hpke_public_key_manager", "//internal:configuration_impl", "//internal:key_gen_configuration_impl", "//internal:key_type_info_store", "//internal:keyset_wrapper_store", "//mac:aes_cmac_key_manager", "//mac:hmac_key_manager", "//prf:aes_cmac_prf_key_manager", "//prf:hkdf_prf_key_manager", "//prf:hmac_prf_key_manager", "//prf:prf_set", "//signature:ecdsa_verify_key_manager", "//signature:ed25519_verify_key_manager", "//signature:rsa_ssa_pkcs1_verify_key_manager", "//signature:rsa_ssa_pss_verify_key_manager", "//streamingaead:aes_ctr_hmac_streaming_key_manager", "//streamingaead:aes_gcm_hkdf_streaming_key_manager", "//util:statusor", "//util:test_matchers", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/config/CMakeLists.txt ================================================ tink_module(config) add_subdirectory(internal) tink_cc_library( NAME tink_config SRCS tink_config.cc tink_config.h DEPS absl::core_headers tink::core::key_manager tink::core::registry tink::daead::deterministic_aead_config tink::hybrid::hybrid_config tink::prf::prf_config tink::signature::signature_config tink::streamingaead::streaming_aead_config tink::util::status tink::proto::config_cc_proto ) tink_cc_library( NAME config_util SRCS config_util.cc config_util.h DEPS tink::proto::config_cc_proto ) tink_cc_library( NAME tink_fips SRCS tink_fips.cc tink_fips.h DEPS absl::core_headers crypto tink::internal::fips_utils tink::internal::registry_impl tink::util::status ) tink_cc_library( NAME global_registry SRCS global_registry.cc global_registry.h DEPS absl::check tink::core::configuration tink::core::key_gen_configuration tink::internal::configuration_impl tink::internal::key_gen_configuration_impl ) tink_cc_library( NAME fips_140_2 SRCS fips_140_2.cc fips_140_2.h DEPS absl::check absl::memory tink::core::configuration tink::aead::aead_wrapper tink::aead::aes_ctr_hmac_aead_key_manager tink::aead::aes_gcm_key_manager tink::internal::configuration_impl tink::internal::fips_utils tink::mac::hmac_key_manager tink::mac::mac_wrapper tink::mac::internal::chunked_mac_wrapper tink::prf::hmac_prf_key_manager tink::prf::prf_set_wrapper tink::signature::ecdsa_verify_key_manager tink::signature::public_key_sign_wrapper tink::signature::public_key_verify_wrapper tink::signature::rsa_ssa_pkcs1_sign_key_manager tink::signature::rsa_ssa_pkcs1_verify_key_manager tink::signature::rsa_ssa_pss_sign_key_manager tink::signature::rsa_ssa_pss_verify_key_manager tink::util::status tink::signature::ecdsa_sign_key_manager ) tink_cc_library( NAME key_gen_fips_140_2 SRCS key_gen_fips_140_2.cc key_gen_fips_140_2.h DEPS absl::check absl::memory tink::core::key_gen_configuration tink::aead::aes_ctr_hmac_aead_key_manager tink::aead::aes_gcm_key_manager tink::internal::fips_utils tink::internal::key_gen_configuration_impl tink::mac::hmac_key_manager tink::prf::hmac_prf_key_manager tink::signature::ecdsa_verify_key_manager tink::signature::rsa_ssa_pkcs1_sign_key_manager tink::signature::rsa_ssa_pkcs1_verify_key_manager tink::signature::rsa_ssa_pss_sign_key_manager tink::signature::rsa_ssa_pss_verify_key_manager tink::util::status tink::signature::ecdsa_sign_key_manager ) tink_cc_library( NAME v0 SRCS v0.cc v0.h DEPS absl::check tink::core::configuration tink::aead::internal::config_v0 tink::daead::internal::config_v0 tink::hybrid::internal::config_v0 tink::internal::configuration_impl tink::mac::internal::config_v0 tink::prf::internal::config_v0 tink::signature::internal::config_v0 tink::streamingaead::internal::config_v0 TAGS exclude_if_openssl ) tink_cc_library( NAME key_gen_v0 SRCS key_gen_v0.cc key_gen_v0.h DEPS absl::check tink::core::key_gen_configuration tink::aead::internal::key_gen_config_v0 tink::daead::internal::key_gen_config_v0 tink::hybrid::internal::key_gen_config_v0 tink::mac::internal::key_gen_config_v0 tink::prf::internal::key_gen_config_v0 tink::signature::internal::key_gen_config_v0 tink::streamingaead::internal::key_gen_config_v0 TAGS exclude_if_openssl ) # tests tink_cc_test( NAME tink_config_test SRCS tink_config_test.cc DEPS tink::config::tink_config gmock absl::status tink::core::cc tink::core::aead tink::core::deterministic_aead tink::core::hybrid_decrypt tink::core::hybrid_encrypt tink::core::mac tink::core::registry tink::core::streaming_aead tink::aead::aes_gcm_key_manager tink::util::status tink::util::test_matchers ) tink_cc_test( NAME config_util_test SRCS config_util_test.cc DEPS tink::config::config_util gmock tink::proto::config_cc_proto ) tink_cc_test( NAME tink_fips_test SRCS tink_fips_test.cc DEPS tink::config::tink_fips gmock absl::status crypto tink::core::registry tink::aead::aead_config tink::internal::fips_utils tink::util::status tink::util::test_matchers ) tink_cc_test( NAME global_registry_test SRCS global_registry_test.cc DEPS tink::config::global_registry gmock absl::memory absl::status tink::core::key_type_manager tink::core::template_util tink::core::input_stream tink::core::keyset_handle tink::core::primitive_set tink::core::primitive_wrapper tink::core::registry tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::aes_gcm_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME fips_140_2_test SRCS fips_140_2_test.cc DEPS tink::config::fips_140_2 tink::config::key_gen_fips_140_2 gmock absl::status tink::core::aead tink::core::chunked_mac tink::core::keyset_handle tink::core::mac tink::core::public_key_sign tink::core::public_key_verify tink::aead::aead_key_templates tink::aead::aes_ctr_hmac_aead_key_manager tink::aead::aes_gcm_key_manager tink::internal::configuration_impl tink::internal::fips_utils tink::internal::key_type_info_store tink::internal::keyset_wrapper_store tink::mac::aes_cmac_key_manager tink::mac::hmac_key_manager tink::prf::hmac_prf_key_manager tink::prf::prf_set tink::signature::ecdsa_verify_key_manager tink::signature::rsa_ssa_pkcs1_verify_key_manager tink::signature::rsa_ssa_pss_verify_key_manager tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME key_gen_fips_140_2_test SRCS key_gen_fips_140_2_test.cc DEPS tink::config::key_gen_fips_140_2 gmock absl::status tink::core::keyset_handle tink::aead::aead_key_templates tink::aead::aes_ctr_hmac_aead_key_manager tink::aead::aes_gcm_key_manager tink::internal::fips_utils tink::internal::key_gen_configuration_impl tink::internal::key_type_info_store tink::mac::aes_cmac_key_manager tink::mac::hmac_key_manager tink::prf::hmac_prf_key_manager tink::signature::ecdsa_verify_key_manager tink::signature::rsa_ssa_pkcs1_verify_key_manager tink::signature::rsa_ssa_pss_verify_key_manager tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME v0_test SRCS v0_test.cc DEPS tink::config::key_gen_v0 tink::config::v0 gmock tink::core::aead tink::core::chunked_mac tink::core::configuration tink::core::deterministic_aead tink::core::hybrid_decrypt tink::core::hybrid_encrypt tink::core::keyset_handle tink::core::mac tink::core::public_key_sign tink::core::public_key_verify tink::core::streaming_aead tink::aead::aead_key_templates tink::aead::aes_ctr_hmac_aead_key_manager tink::aead::aes_eax_key_manager tink::aead::aes_gcm_key_manager tink::aead::aes_gcm_siv_key_manager tink::aead::xchacha20_poly1305_key_manager tink::daead::aes_siv_key_manager tink::hybrid::ecies_aead_hkdf_public_key_manager tink::hybrid::internal::hpke_public_key_manager tink::internal::configuration_impl tink::internal::key_gen_configuration_impl tink::internal::key_type_info_store tink::internal::keyset_wrapper_store tink::mac::aes_cmac_key_manager tink::mac::hmac_key_manager tink::prf::aes_cmac_prf_key_manager tink::prf::hkdf_prf_key_manager tink::prf::hmac_prf_key_manager tink::prf::prf_set tink::signature::ecdsa_verify_key_manager tink::signature::ed25519_verify_key_manager tink::signature::rsa_ssa_pkcs1_verify_key_manager tink::signature::rsa_ssa_pss_verify_key_manager tink::streamingaead::aes_ctr_hmac_streaming_key_manager tink::streamingaead::aes_gcm_hkdf_streaming_key_manager tink::util::statusor tink::util::test_matchers TAGS exclude_if_openssl ) ================================================ FILE: cc/config/config_util.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/config/config_util.h" #include namespace crypto { namespace tink { google::crypto::tink::KeyTypeEntry CreateTinkKeyTypeEntry( const std::string& catalogue_name, const std::string& primitive_name, const std::string& key_proto_name, int key_manager_version, bool new_key_allowed) { std::string prefix = "type.googleapis.com/google.crypto.tink."; google::crypto::tink::KeyTypeEntry entry; entry.set_catalogue_name(catalogue_name); entry.set_primitive_name(primitive_name); entry.set_type_url(prefix.append(key_proto_name)); entry.set_key_manager_version(key_manager_version); entry.set_new_key_allowed(new_key_allowed); return entry; } } // namespace tink } // namespace crypto ================================================ FILE: cc/config/config_util.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_CONFIG_CONFIG_UTIL_H_ #define TINK_CONFIG_CONFIG_UTIL_H_ #include #include "proto/config.pb.h" namespace crypto { namespace tink { google::crypto::tink::KeyTypeEntry CreateTinkKeyTypeEntry( const std::string& catalogue_name, const std::string& primitive_name, const std::string& key_proto_name, int key_manager_version, bool new_key_allowed); } // namespace tink } // namespace crypto #endif // TINK_CONFIG_CONFIG_UTIL_H_ ================================================ FILE: cc/config/config_util_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/config/config_util.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "proto/config.pb.h" using ::testing::Eq; namespace crypto { namespace tink { TEST(CreateKeyTypeEntry, Simple) { google::crypto::tink::KeyTypeEntry entry = CreateTinkKeyTypeEntry( "catalogue", "primitive_name", "key_proto_name", 12, true); EXPECT_THAT(entry.primitive_name(), Eq("primitive_name")); EXPECT_THAT(entry.type_url(), Eq("type.googleapis.com/google.crypto.tink.key_proto_name")); EXPECT_THAT(entry.key_manager_version(), Eq(12)); EXPECT_THAT(entry.new_key_allowed(), Eq(true)); EXPECT_THAT(entry.catalogue_name(), Eq("catalogue")); } } // namespace tink } // namespace crypto ================================================ FILE: cc/config/fips_140_2.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/config/fips_140_2.h" #include "absl/log/check.h" #include "absl/memory/memory.h" #include "tink/aead/aead_wrapper.h" #include "tink/aead/aes_ctr_hmac_aead_key_manager.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/configuration.h" #include "tink/internal/configuration_impl.h" #include "tink/internal/fips_utils.h" #include "tink/mac/hmac_key_manager.h" #include "tink/mac/internal/chunked_mac_wrapper.h" #include "tink/mac/mac_wrapper.h" #include "tink/prf/hmac_prf_key_manager.h" #include "tink/prf/prf_set_wrapper.h" #include "tink/signature/ecdsa_verify_key_manager.h" #include "tink/signature/public_key_sign_wrapper.h" #include "tink/signature/public_key_verify_wrapper.h" #include "tink/signature/rsa_ssa_pkcs1_sign_key_manager.h" #include "tink/signature/rsa_ssa_pkcs1_verify_key_manager.h" #include "tink/signature/rsa_ssa_pss_sign_key_manager.h" #include "tink/signature/rsa_ssa_pss_verify_key_manager.h" #include "tink/util/status.h" #include "tink/signature/ecdsa_sign_key_manager.h" namespace crypto { namespace tink { namespace { util::Status AddMac(Configuration& config) { util::Status status = internal::ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config); if (!status.ok()) { return status; } status = internal::ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config); if (!status.ok()) { return status; } return internal::ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); } util::Status AddAead(Configuration& config) { util::Status status = internal::ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config); if (!status.ok()) { return status; } status = internal::ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); if (!status.ok()) { return status; } return internal::ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); } util::Status AddPrf(Configuration& config) { util::Status status = internal::ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config); if (!status.ok()) { return status; } return internal::ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); } util::Status AddSignature(Configuration& config) { util::Status status = internal::ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config); if (!status.ok()) { return status; } status = internal::ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config); if (!status.ok()) { return status; } status = internal::ConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config); if (!status.ok()) { return status; } status = internal::ConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config); if (!status.ok()) { return status; } return internal::ConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config); } } // namespace const Configuration& ConfigFips140_2() { static const Configuration* instance = [] { internal::SetFipsRestricted(); static Configuration* config = new Configuration(); CHECK_OK(AddMac(*config)); CHECK_OK(AddAead(*config)); CHECK_OK(AddPrf(*config)); CHECK_OK(AddSignature(*config)); return config; }(); return *instance; } } // namespace tink } // namespace crypto ================================================ FILE: cc/config/fips_140_2.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_CONFIG_FIPS_140_2_H_ #define TINK_CONFIG_FIPS_140_2_H_ #include "tink/configuration.h" namespace crypto { namespace tink { // Configuration used to generate primitives for key types that are compliant // with FIPS 140-2, https://csrc.nist.gov/pubs/fips/140-2/upd2/final. // Importing this Configuration restricts Tink to FIPS globally and // requires BoringSSL to be built with the BoringCrypto module. const Configuration& ConfigFips140_2(); } // namespace tink } // namespace crypto #endif // TINK_CONFIG_FIPS_140_2_H_ ================================================ FILE: cc/config/fips_140_2_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/config/fips_140_2.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/aead.h" #include "tink/aead/aead_key_templates.h" #include "tink/aead/aes_ctr_hmac_aead_key_manager.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/chunked_mac.h" #include "tink/config/key_gen_fips_140_2.h" #include "tink/internal/configuration_impl.h" #include "tink/internal/fips_utils.h" #include "tink/internal/key_type_info_store.h" #include "tink/internal/keyset_wrapper_store.h" #include "tink/keyset_handle.h" #include "tink/mac.h" #include "tink/mac/aes_cmac_key_manager.h" #include "tink/mac/hmac_key_manager.h" #include "tink/prf/hmac_prf_key_manager.h" #include "tink/prf/prf_set.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/signature/ecdsa_verify_key_manager.h" #include "tink/signature/rsa_ssa_pkcs1_verify_key_manager.h" #include "tink/signature/rsa_ssa_pss_verify_key_manager.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; class Fips1402Test : public ::testing::Test { protected: void TearDown() override { internal::UnSetFipsRestricted(); } }; TEST_F(Fips1402Test, PrimitiveWrappers) { if (!internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only test in FIPS mode"; } util::StatusOr store = internal::ConfigurationImpl::GetKeysetWrapperStore(ConfigFips140_2()); ASSERT_THAT(store, IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); } TEST_F(Fips1402Test, KeyManagers) { if (!internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only test in FIPS mode"; } util::StatusOr store = internal::ConfigurationImpl::GetKeyTypeInfoStore(ConfigFips140_2()); ASSERT_THAT(store, IsOk()); EXPECT_THAT((*store)->Get(HmacKeyManager().get_key_type()), IsOk()); EXPECT_THAT((*store)->Get(AesCtrHmacAeadKeyManager().get_key_type()), IsOk()); EXPECT_THAT((*store)->Get(AesGcmKeyManager().get_key_type()), IsOk()); EXPECT_THAT((*store)->Get(HmacPrfKeyManager().get_key_type()), IsOk()); EXPECT_THAT((*store)->Get(EcdsaVerifyKeyManager().get_key_type()), IsOk()); EXPECT_THAT((*store)->Get(RsaSsaPssVerifyKeyManager().get_key_type()), IsOk()); EXPECT_THAT((*store)->Get(RsaSsaPkcs1VerifyKeyManager().get_key_type()), IsOk()); } TEST_F(Fips1402Test, FailsInNonFipsMode) { if (internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only test in non-FIPS mode"; } EXPECT_DEATH_IF_SUPPORTED( ConfigFips140_2(), "BoringSSL not built with the BoringCrypto module."); } TEST_F(Fips1402Test, NonFipsTypeNotPresent) { if (!internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only test in FIPS mode"; } util::StatusOr store = internal::ConfigurationImpl::GetKeyTypeInfoStore(ConfigFips140_2()); ASSERT_THAT(store, IsOk()); EXPECT_THAT((*store)->Get(AesCmacKeyManager().get_key_type()).status(), StatusIs(absl::StatusCode::kNotFound)); } TEST_F(Fips1402Test, GetPrimitive) { if (!internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only test in FIPS mode"; } util::StatusOr> handle = KeysetHandle::GenerateNew(AeadKeyTemplates::Aes128Gcm(), KeyGenConfigFips140_2()); ASSERT_THAT(handle, IsOk()); util::StatusOr> aead = (*handle)->GetPrimitive(ConfigFips140_2()); ASSERT_THAT(aead, IsOk()); std::string plaintext = "plaintext"; std::string ad = "ad"; util::StatusOr ciphertext = (*aead)->Encrypt(plaintext, ad); ASSERT_THAT(ciphertext, IsOk()); EXPECT_THAT((*aead)->Decrypt(*ciphertext, ad), IsOkAndHolds(plaintext)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/config/global_registry.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/config/global_registry.h" #include "absl/log/check.h" #include "tink/configuration.h" #include "tink/internal/configuration_impl.h" #include "tink/internal/key_gen_configuration_impl.h" #include "tink/key_gen_configuration.h" namespace crypto { namespace tink { const Configuration& ConfigGlobalRegistry() { static const Configuration* instance = [] { static Configuration* config = new Configuration(); CHECK_OK(internal::ConfigurationImpl::SetGlobalRegistryMode(*config)); return config; }(); return *instance; } const KeyGenConfiguration& KeyGenConfigGlobalRegistry() { static const KeyGenConfiguration* instance = [] { static KeyGenConfiguration* config = new KeyGenConfiguration(); CHECK_OK(internal::KeyGenConfigurationImpl::SetGlobalRegistryMode(*config)); return config; }(); return *instance; } } // namespace tink } // namespace crypto ================================================ FILE: cc/config/global_registry.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_CONFIG_GLOBAL_REGISTRY_H_ #define TINK_CONFIG_GLOBAL_REGISTRY_H_ #include "tink/configuration.h" #include "tink/key_gen_configuration.h" namespace crypto { namespace tink { // Used to generate primitives and keys using the global crypto::tink::Registry. const crypto::tink::Configuration& ConfigGlobalRegistry(); const crypto::tink::KeyGenConfiguration& KeyGenConfigGlobalRegistry(); } // namespace tink } // namespace crypto #endif // TINK_CONFIG_GLOBAL_REGISTRY_H_ ================================================ FILE: cc/config/global_registry_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/config/global_registry.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/input_stream.h" #include "tink/keyset_handle.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/aes_gcm.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::AesGcmKey; using ::google::crypto::tink::AesGcmKeyFormat; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::OutputPrefixType; class FakePrimitive { public: explicit FakePrimitive(std::string s) : s_(s) {} std::string get() { return s_; } private: std::string s_; }; class FakeKeyTypeManager : public KeyTypeManager> { public: class FakePrimitiveFactory : public PrimitiveFactory { public: util::StatusOr> Create( const AesGcmKey& key) const override { return absl::make_unique(key.key_value()); } }; FakeKeyTypeManager() : KeyTypeManager(absl::make_unique()) {} KeyData::KeyMaterialType key_material_type() const override { return KeyData::SYMMETRIC; } uint32_t get_version() const override { return 0; } const std::string& get_key_type() const override { return key_type_; } util::Status ValidateKey(const AesGcmKey& key) const override { return util::OkStatus(); } util::Status ValidateKeyFormat( const AesGcmKeyFormat& key_format) const override { return util::OkStatus(); } util::StatusOr CreateKey( const AesGcmKeyFormat& key_format) const override { return AesGcmKey(); } util::StatusOr DeriveKey( const AesGcmKeyFormat& key_format, InputStream* input_stream) const override { return AesGcmKey(); } private: const std::string key_type_ = "type.googleapis.com/google.crypto.tink.AesGcmKey"; }; class FakePrimitiveWrapper : public PrimitiveWrapper { public: util::StatusOr> Wrap( std::unique_ptr> primitive_set) const override { return absl::make_unique( primitive_set->get_primary()->get_primitive().get()); } }; TEST(GlobalRegistryTest, GenerateNewKeysetHandleFromKeyGenConfig) { Registry::Reset(); KeyTemplate templ; templ.set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey"); templ.set_output_prefix_type(OutputPrefixType::TINK); EXPECT_THAT( KeysetHandle::GenerateNew(templ, KeyGenConfigGlobalRegistry()).status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT( Registry::RegisterKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/true), IsOk()); EXPECT_THAT( KeysetHandle::GenerateNew(templ, KeyGenConfigGlobalRegistry()).status(), IsOk()); } TEST(GlobalRegistryTest, GetPrimitiveFromConfig) { Registry::Reset(); ASSERT_THAT( Registry::RegisterKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/true), IsOk()); KeyTemplate templ; templ.set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey"); templ.set_output_prefix_type(OutputPrefixType::TINK); util::StatusOr> handle = KeysetHandle::GenerateNew(templ, KeyGenConfigGlobalRegistry()); ASSERT_THAT(handle, IsOk()); EXPECT_THAT( (*handle)->GetPrimitive(ConfigGlobalRegistry()).status(), StatusIs(absl::StatusCode::kNotFound)); Registry::Reset(); ASSERT_THAT( Registry::RegisterKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/true), IsOk()); ASSERT_THAT(Registry::RegisterPrimitiveWrapper( absl::make_unique()), IsOk()); EXPECT_THAT((*handle)->GetPrimitive(ConfigGlobalRegistry()), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/config/internal/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) ================================================ FILE: cc/config/internal/CMakeLists.txt ================================================ tink_module(config::internal) ================================================ FILE: cc/config/key_gen_fips_140_2.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/config/key_gen_fips_140_2.h" #include "absl/log/check.h" #include "absl/memory/memory.h" #include "tink/aead/aes_ctr_hmac_aead_key_manager.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/internal/fips_utils.h" #include "tink/internal/key_gen_configuration_impl.h" #include "tink/key_gen_configuration.h" #include "tink/mac/hmac_key_manager.h" #include "tink/prf/hmac_prf_key_manager.h" #include "tink/signature/ecdsa_verify_key_manager.h" #include "tink/signature/rsa_ssa_pkcs1_sign_key_manager.h" #include "tink/signature/rsa_ssa_pkcs1_verify_key_manager.h" #include "tink/signature/rsa_ssa_pss_sign_key_manager.h" #include "tink/signature/rsa_ssa_pss_verify_key_manager.h" #include "tink/util/status.h" #include "tink/signature/ecdsa_sign_key_manager.h" namespace crypto { namespace tink { namespace { util::Status AddMac(KeyGenConfiguration& config) { return internal::KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); } util::Status AddAead(KeyGenConfiguration& config) { util::Status status = internal::KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); if (!status.ok()) { return status; } return internal::KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); } util::Status AddPrf(KeyGenConfiguration& config) { return internal::KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); } util::Status AddSignature(KeyGenConfiguration& config) { util::Status status = internal::KeyGenConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config); if (!status.ok()) { return status; } status = internal::KeyGenConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config); if (!status.ok()) { return status; } return internal::KeyGenConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config); } } // namespace const KeyGenConfiguration& KeyGenConfigFips140_2() { static const KeyGenConfiguration* instance = [] { internal::SetFipsRestricted(); static KeyGenConfiguration* config = new KeyGenConfiguration(); CHECK_OK(AddMac(*config)); CHECK_OK(AddAead(*config)); CHECK_OK(AddPrf(*config)); CHECK_OK(AddSignature(*config)); return config; }(); return *instance; } } // namespace tink } // namespace crypto ================================================ FILE: cc/config/key_gen_fips_140_2.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_CONFIG_KEY_GEN_FIPS_140_2_H_ #define TINK_CONFIG_KEY_GEN_FIPS_140_2_H_ #include "tink/key_gen_configuration.h" namespace crypto { namespace tink { // KeyGenConfiguration used to generate keys using FIPS 140-2-compliant key // types. Importing this KeyGenConfiguration restricts Tink to FIPS globally and // requires BoringSSL to be built with the BoringCrypto module. const KeyGenConfiguration& KeyGenConfigFips140_2(); } // namespace tink } // namespace crypto #endif // TINK_CONFIG_KEY_GEN_FIPS_140_2_H_ ================================================ FILE: cc/config/key_gen_fips_140_2_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/config/key_gen_fips_140_2.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/aead/aead_key_templates.h" #include "tink/aead/aes_ctr_hmac_aead_key_manager.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/internal/fips_utils.h" #include "tink/internal/key_gen_configuration_impl.h" #include "tink/internal/key_type_info_store.h" #include "tink/keyset_handle.h" #include "tink/mac/aes_cmac_key_manager.h" #include "tink/mac/hmac_key_manager.h" #include "tink/prf/hmac_prf_key_manager.h" #include "tink/signature/ecdsa_verify_key_manager.h" #include "tink/signature/rsa_ssa_pkcs1_verify_key_manager.h" #include "tink/signature/rsa_ssa_pss_verify_key_manager.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; class KeyGenFips1402Test : public testing::Test { protected: void TearDown() override { internal::UnSetFipsRestricted(); } }; TEST_F(KeyGenFips1402Test, KeyManagers) { if (!internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only test in FIPS mode"; } util::StatusOr store = internal::KeyGenConfigurationImpl::GetKeyTypeInfoStore( KeyGenConfigFips140_2()); ASSERT_THAT(store, IsOk()); EXPECT_THAT((*store)->Get(HmacKeyManager().get_key_type()), IsOk()); EXPECT_THAT((*store)->Get(AesCtrHmacAeadKeyManager().get_key_type()), IsOk()); EXPECT_THAT((*store)->Get(AesGcmKeyManager().get_key_type()), IsOk()); EXPECT_THAT((*store)->Get(HmacPrfKeyManager().get_key_type()), IsOk()); EXPECT_THAT((*store)->Get(EcdsaVerifyKeyManager().get_key_type()), IsOk()); EXPECT_THAT((*store)->Get(RsaSsaPssVerifyKeyManager().get_key_type()), IsOk()); EXPECT_THAT((*store)->Get(RsaSsaPkcs1VerifyKeyManager().get_key_type()), IsOk()); } TEST_F(KeyGenFips1402Test, FailsInNonFipsMode) { if (internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only test in non-FIPS mode"; } EXPECT_DEATH_IF_SUPPORTED( KeyGenConfigFips140_2(), "BoringSSL not built with the BoringCrypto module."); } TEST_F(KeyGenFips1402Test, NonFipsTypeNotPresent) { if (!internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only test in FIPS mode"; } util::StatusOr store = internal::KeyGenConfigurationImpl::GetKeyTypeInfoStore( KeyGenConfigFips140_2()); ASSERT_THAT(store, IsOk()); EXPECT_THAT((*store)->Get(AesCmacKeyManager().get_key_type()).status(), StatusIs(absl::StatusCode::kNotFound)); } TEST_F(KeyGenFips1402Test, GenerateNewKeysetHandle) { if (!internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only test in FIPS mode"; } EXPECT_THAT(KeysetHandle::GenerateNew(AeadKeyTemplates::Aes128Gcm(), KeyGenConfigFips140_2()), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/config/key_gen_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/config/key_gen_v0.h" #include "absl/log/check.h" #include "tink/aead/internal/key_gen_config_v0.h" #include "tink/daead/internal/key_gen_config_v0.h" #include "tink/hybrid/internal/key_gen_config_v0.h" #include "tink/key_gen_configuration.h" #include "tink/mac/internal/key_gen_config_v0.h" #include "tink/prf/internal/key_gen_config_v0.h" #include "tink/signature/internal/key_gen_config_v0.h" #include "tink/streamingaead/internal/key_gen_config_v0.h" namespace crypto { namespace tink { const KeyGenConfiguration& KeyGenConfigV0() { static const KeyGenConfiguration* instance = [] { static KeyGenConfiguration* config = new KeyGenConfiguration(); CHECK_OK(internal::AddMacKeyGenV0(*config)); CHECK_OK(internal::AddAeadKeyGenV0(*config)); CHECK_OK(internal::AddDeterministicAeadKeyGenV0(*config)); CHECK_OK(internal::AddStreamingAeadKeyGenV0(*config)); CHECK_OK(internal::AddHybridKeyGenV0(*config)); CHECK_OK(internal::AddPrfKeyGenV0(*config)); CHECK_OK(internal::AddSignatureKeyGenV0(*config)); return config; }(); return *instance; } } // namespace tink } // namespace crypto ================================================ FILE: cc/config/key_gen_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_CONFIG_KEY_GEN_V0_H_ #define TINK_CONFIG_KEY_GEN_V0_H_ #include "tink/key_gen_configuration.h" namespace crypto { namespace tink { // KeyGenConfiguration used to generate keys with recommended key managers. const KeyGenConfiguration& KeyGenConfigV0(); } // namespace tink } // namespace crypto #endif // TINK_CONFIG_KEY_GEN_V0_H_ ================================================ FILE: cc/config/tink_config.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/config/tink_config.h" #include "tink/daead/deterministic_aead_config.h" #include "tink/hybrid/hybrid_config.h" #include "tink/key_manager.h" #include "tink/prf/prf_config.h" #include "tink/registry.h" #include "tink/signature/signature_config.h" #include "tink/streamingaead/streaming_aead_config.h" #include "tink/util/status.h" #include "proto/config.pb.h" using google::crypto::tink::RegistryConfig; namespace crypto { namespace tink { // static const RegistryConfig& TinkConfig::Latest() { static const RegistryConfig* config = new RegistryConfig(); return *config; } // static util::Status TinkConfig::Register() { auto status = HybridConfig::Register(); // includes Mac & Aead if (!status.ok()) return status; status = PrfConfig::Register(); if (!status.ok()) return status; status = SignatureConfig::Register(); if (!status.ok()) return status; status = DeterministicAeadConfig::Register(); if (!status.ok()) return status; return StreamingAeadConfig::Register(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/config/tink_config.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_CONFIG_TINK_CONFIG_H_ #define TINK_CONFIG_TINK_CONFIG_H_ #include "absl/base/attributes.h" #include "absl/base/macros.h" #include "tink/util/status.h" #include "proto/config.pb.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Static methods and constants for registering with the Registry // all instances of Tink key types supported in a particular release of Tink. // // To register all Tink key types from the current Tink release one can do: // // auto status = TinkConfig::Register(); // class TinkConfig { public: // Returns config of implementations of all primitives supported // in the current Tink release. ABSL_DEPRECATED("This is not supported anymore.") static const google::crypto::tink::RegistryConfig& Latest(); // Registers all primitive wrappers and all key managers for all primitives // supported in the current Tink release. static crypto::tink::util::Status Register(); private: TinkConfig() {} }; } // namespace tink } // namespace crypto #endif // TINK_CONFIG_TINK_CONFIG_H_ ================================================ FILE: cc/config/tink_config_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/config/tink_config.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/aead.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/deterministic_aead.h" #include "tink/hybrid_decrypt.h" #include "tink/hybrid_encrypt.h" #include "tink/mac.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/registry.h" #include "tink/streaming_aead.h" #include "tink/util/status.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; TEST(TinkConfigTest, RegisterWorks) { EXPECT_THAT(Registry::get_key_manager(AesGcmKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT(TinkConfig::Register(), IsOk()); EXPECT_THAT(Registry::get_key_manager(AesGcmKeyManager().get_key_type()) .status(), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/config/tink_fips.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/config/tink_fips.h" #include "tink/internal/fips_utils.h" #include "tink/internal/registry_impl.h" #include "tink/util/status.h" namespace crypto { namespace tink { bool IsFipsModeEnabled() { return internal::IsFipsModeEnabled(); } crypto::tink::util::Status RestrictToFips() { return internal::RegistryImpl::GlobalInstance().RestrictToFipsIfEmpty(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/config/tink_fips.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_CONFIG_TINK_FIPS_H_ #define TINK_CONFIG_TINK_FIPS_H_ #include "absl/base/attributes.h" #include "openssl/crypto.h" #include "tink/internal/fips_utils.h" #include "tink/util/status.h" namespace crypto { namespace tink { // This function will return true if Tink has been built in FIPS mode or if // the FIPS restrictions have been enabled at runtime. bool IsFipsModeEnabled(); // Enables the FIPS restrictions for the registry and subtle primitives. If Tink // has been built in FIPS this is redundant. This method must be called before // handling any key material or calling any of the functions in subtle. crypto::tink::util::Status RestrictToFips(); } // namespace tink } // namespace crypto #endif // TINK_CONFIG_TINK_FIPS_H_ ================================================ FILE: cc/config/tink_fips_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/config/tink_fips.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "openssl/crypto.h" #include "tink/aead/aead_config.h" #include "tink/internal/fips_utils.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using testing::Eq; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; class FipsIncompatible { public: static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kNotFips; }; class FipsCompatibleWithBoringCrypto { public: static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kRequiresBoringCrypto; }; TEST(TinkFipsTest, FipsEnabledWhenBuiltInFipsMode) { // Check if the built flag is set. if (!internal::kUseOnlyFips) { GTEST_SKIP() << "Only supported in FIPS-only mode"; } EXPECT_THAT(IsFipsModeEnabled(), Eq(true)); } TEST(TinkFipsTest, FipsDisabledWhenNotBuildInFipsMode) { // Check if the built flag is set. if (internal::kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT(IsFipsModeEnabled(), Eq(false)); } TEST(TinkFipsTest, CompatibilityChecksWithBoringCrypto) { if (!internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test only run if BoringCrypto module is available."; } Registry::Reset(); // Tink is not build in FIPS mode, but the FIPS mode is enabled at runtime. EXPECT_THAT(crypto::tink::RestrictToFips(), IsOk()); // In FIPS only mode compatibility checks should disallow algorithms // with the FipsCompatibility::kNone flag. EXPECT_THAT(internal::CheckFipsCompatibility(), StatusIs(absl::StatusCode::kInternal)); // FIPS validated implementations should still be allowed. EXPECT_THAT( internal::CheckFipsCompatibility(), IsOk()); internal::UnSetFipsRestricted(); } TEST(TinkFipsTest, CompatibilityChecksWithoutBoringCrypto) { if (internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test only run if BoringCrypto module is not available."; } Registry::Reset(); // Tink is not build in FIPS mode, but the FIPS mode is enabled at runtime. EXPECT_THAT(crypto::tink::RestrictToFips(), IsOk()); // In FIPS only mode compatibility checks should disallow algorithms // with the FipsCompatibility::kNone flag. EXPECT_THAT(internal::CheckFipsCompatibility(), StatusIs(absl::StatusCode::kInternal)); // FIPS validated implementations are not allowed if BoringCrypto is not // available. EXPECT_THAT( internal::CheckFipsCompatibility(), StatusIs(absl::StatusCode::kInternal)); internal::UnSetFipsRestricted(); } TEST(TinkFipsTest, FailIfRegistryNotEmpty) { if (internal::kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } Registry::Reset(); internal::UnSetFipsRestricted(); EXPECT_THAT(AeadConfig::Register(), IsOk()); EXPECT_THAT(crypto::tink::RestrictToFips(), StatusIs(absl::StatusCode::kInternal)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/config/v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/config/v0.h" #include "absl/log/check.h" #include "tink/aead/internal/config_v0.h" #include "tink/configuration.h" #include "tink/daead/internal/config_v0.h" #include "tink/hybrid/internal/config_v0.h" #include "tink/internal/configuration_impl.h" #include "tink/mac/internal/config_v0.h" #include "tink/prf/internal/config_v0.h" #include "tink/signature/internal/config_v0.h" #include "tink/streamingaead/internal/config_v0.h" namespace crypto { namespace tink { const Configuration& ConfigV0() { static const Configuration* instance = [] { static Configuration* config = new Configuration(); CHECK_OK(internal::AddMacV0(*config)); CHECK_OK(internal::AddAeadV0(*config)); CHECK_OK(internal::AddDeterministicAeadV0(*config)); CHECK_OK(internal::AddStreamingAeadV0(*config)); CHECK_OK(internal::AddHybridV0(*config)); CHECK_OK(internal::AddPrfV0(*config)); CHECK_OK(internal::AddSignatureV0(*config)); return config; }(); return *instance; } } // namespace tink } // namespace crypto ================================================ FILE: cc/config/v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_CONFIG_V0_H_ #define TINK_CONFIG_V0_H_ #include "tink/configuration.h" namespace crypto { namespace tink { // Configuration used to generate recommended primitives with recommended key // managers. const Configuration& ConfigV0(); } // namespace tink } // namespace crypto #endif // TINK_CONFIG_V0_H_ ================================================ FILE: cc/config/v0_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/config/v0.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/aead.h" #include "tink/aead/aead_key_templates.h" #include "tink/aead/aes_ctr_hmac_aead_key_manager.h" #include "tink/aead/aes_eax_key_manager.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/aead/aes_gcm_siv_key_manager.h" #include "tink/aead/xchacha20_poly1305_key_manager.h" #include "tink/chunked_mac.h" #include "tink/config/key_gen_v0.h" #include "tink/configuration.h" #include "tink/daead/aes_siv_key_manager.h" #include "tink/deterministic_aead.h" #include "tink/hybrid/ecies_aead_hkdf_public_key_manager.h" #include "tink/hybrid/internal/hpke_public_key_manager.h" #include "tink/hybrid_decrypt.h" #include "tink/hybrid_encrypt.h" #include "tink/internal/configuration_impl.h" #include "tink/internal/key_gen_configuration_impl.h" #include "tink/internal/key_type_info_store.h" #include "tink/internal/keyset_wrapper_store.h" #include "tink/keyset_handle.h" #include "tink/mac.h" #include "tink/mac/aes_cmac_key_manager.h" #include "tink/mac/hmac_key_manager.h" #include "tink/prf/aes_cmac_prf_key_manager.h" #include "tink/prf/hkdf_prf_key_manager.h" #include "tink/prf/hmac_prf_key_manager.h" #include "tink/prf/prf_set.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/signature/ecdsa_verify_key_manager.h" #include "tink/signature/ed25519_verify_key_manager.h" #include "tink/signature/rsa_ssa_pkcs1_verify_key_manager.h" #include "tink/signature/rsa_ssa_pss_verify_key_manager.h" #include "tink/streaming_aead.h" #include "tink/streamingaead/aes_ctr_hmac_streaming_key_manager.h" #include "tink/streamingaead/aes_gcm_hkdf_streaming_key_manager.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::testing::TestWithParam; using ::testing::Values; TEST(V0Test, PrimitiveWrappers) { util::StatusOr store = internal::ConfigurationImpl::GetKeysetWrapperStore(ConfigV0()); ASSERT_THAT(store, IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); } using V0KeyTypesTest = TestWithParam>; INSTANTIATE_TEST_SUITE_P( V0KeyTypesTestSuite, V0KeyTypesTest, Values(internal::ConfigurationImpl::GetKeyTypeInfoStore(ConfigV0()), internal::KeyGenConfigurationImpl::GetKeyTypeInfoStore( KeyGenConfigV0()))); TEST_P(V0KeyTypesTest, KeyManagers) { ASSERT_THAT(GetParam(), IsOk()); const crypto::tink::internal::KeyTypeInfoStore* store = GetParam().value(); EXPECT_THAT(store->Get(HmacKeyManager().get_key_type()), IsOk()); EXPECT_THAT(store->Get(AesCmacKeyManager().get_key_type()), IsOk()); EXPECT_THAT(store->Get(AesCtrHmacAeadKeyManager().get_key_type()), IsOk()); EXPECT_THAT(store->Get(AesGcmKeyManager().get_key_type()), IsOk()); EXPECT_THAT(store->Get(AesGcmSivKeyManager().get_key_type()), IsOk()); EXPECT_THAT(store->Get(AesEaxKeyManager().get_key_type()), IsOk()); EXPECT_THAT(store->Get(XChaCha20Poly1305KeyManager().get_key_type()), IsOk()); EXPECT_THAT(store->Get(AesSivKeyManager().get_key_type()), IsOk()); EXPECT_THAT(store->Get(AesGcmHkdfStreamingKeyManager().get_key_type()), IsOk()); EXPECT_THAT(store->Get(AesCtrHmacStreamingKeyManager().get_key_type()), IsOk()); EXPECT_THAT(store->Get(EciesAeadHkdfPublicKeyManager().get_key_type()), IsOk()); EXPECT_THAT(store->Get(internal::HpkePublicKeyManager().get_key_type()), IsOk()); EXPECT_THAT(store->Get(HmacPrfKeyManager().get_key_type()), IsOk()); EXPECT_THAT(store->Get(HkdfPrfKeyManager().get_key_type()), IsOk()); EXPECT_THAT(store->Get(AesCmacPrfKeyManager().get_key_type()), IsOk()); EXPECT_THAT(store->Get(EcdsaVerifyKeyManager().get_key_type()), IsOk()); EXPECT_THAT(store->Get(RsaSsaPssVerifyKeyManager().get_key_type()), IsOk()); EXPECT_THAT(store->Get(RsaSsaPkcs1VerifyKeyManager().get_key_type()), IsOk()); EXPECT_THAT(store->Get(Ed25519VerifyKeyManager().get_key_type()), IsOk()); } TEST(V0Test, GetPrimitive) { util::StatusOr> handle = KeysetHandle::GenerateNew(AeadKeyTemplates::Aes128Gcm(), KeyGenConfigV0()); ASSERT_THAT(handle, IsOk()); util::StatusOr> aead = (*handle)->GetPrimitive(ConfigV0()); ASSERT_THAT(aead, IsOk()); std::string plaintext = "plaintext"; std::string ad = "ad"; util::StatusOr ciphertext = (*aead)->Encrypt(plaintext, ad); ASSERT_THAT(ciphertext, IsOk()); EXPECT_THAT((*aead)->Decrypt(*ciphertext, ad), IsOkAndHolds(plaintext)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/configuration.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_CONFIGURATION_H_ #define TINK_CONFIGURATION_H_ #include "tink/internal/key_type_info_store.h" #include "tink/internal/keyset_wrapper_store.h" namespace crypto { namespace tink { namespace internal { class ConfigurationImpl; } // Configuration used to generate primitives using stored primitive wrappers and // key type managers. class Configuration { public: Configuration() = default; // Not copyable or movable. Configuration(const Configuration&) = delete; Configuration& operator=(const Configuration&) = delete; private: friend class internal::ConfigurationImpl; // When true, Configuration is in global registry mode. For `some_fn(config)` // with a `config` parameter, this indicates to `some_fn` to use // crypto::tink::Registry directly. bool global_registry_mode_ = false; crypto::tink::internal::KeyTypeInfoStore key_type_info_store_; crypto::tink::internal::KeysetWrapperStore keyset_wrapper_store_; }; } // namespace tink } // namespace crypto #endif // TINK_CONFIGURATION_H_ ================================================ FILE: cc/core/big_integer.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/big_integer.h" #include #include "absl/strings/string_view.h" #include "openssl/crypto.h" namespace crypto { namespace tink { BigInteger::BigInteger(absl::string_view big_integer) { int padding_pos = big_integer.find_first_not_of('\0'); if (padding_pos != std::string::npos) { value_ = std::string(big_integer.substr(padding_pos)); } else { value_ = ""; } } bool BigInteger::operator==(const BigInteger& other) const { if (value_.size() != other.value_.size()) { return false; } return CRYPTO_memcmp(value_.data(), other.value_.data(), value_.size()) == 0; } } // namespace tink } // namespace crypto ================================================ FILE: cc/core/big_integer_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/big_integer.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/escaping.h" #include "absl/strings/string_view.h" namespace crypto { namespace tink { using ::testing::Eq; constexpr absl::string_view kHexBigInt = "b3510a2bcd4ce644c5b594ae5059e12b2f054b658d5da5959a2fdf1871b808bc3df3e628" "d2792e51aad5c124b43bda453dca5cde4bcf28e7bd4effba0cb4b742bbb6d5a013cb63d1aa" "3a89e02627ef5398b52c0cfd97d208abeb8d7c9bce0bbeb019a86ddb589beb29a5b74bf861" "075c677c81d430f030c265247af9d3c9140ccb65309d07e0adc1efd15cf17e7b055d7da386" "8e4648cc3a180f0ee7f8e1e7b18098a3391b4ce7161e98d57af8a947e201a463e2d6bbca80" "59e5706e9dfed8f4856465ffa712ed1aa18e888d12dc6aa09ce95ecfca83cc5b0b15db09c8" "647f5d524c0f2e7620a3416b9623cadc0f097af573261c98c8400aa12af38e43cad84d"; constexpr absl::string_view kHexBigIntPadded = "0000b3510a2bcd4ce644c5b594ae5059e12b2f054b658d5da5959a2fdf1871b808bc3df3" "e628d2792e51aad5c124b43bda453dca5cde4bcf28e7bd4effba0cb4b742bbb6d5a013cb63" "d1aa3a89e02627ef5398b52c0cfd97d208abeb8d7c9bce0bbeb019a86ddb589beb29a5b74b" "f861075c677c81d430f030c265247af9d3c9140ccb65309d07e0adc1efd15cf17e7b055d7d" "a3868e4648cc3a180f0ee7f8e1e7b18098a3391b4ce7161e98d57af8a947e201a463e2d6bb" "ca8059e5706e9dfed8f4856465ffa712ed1aa18e888d12dc6aa09ce95ecfca83cc5b0b15db" "09c8647f5d524c0f2e7620a3416b9623cadc0f097af573261c98c8400aa12af38e43cad84" "d"; TEST(BigIntegerTest, CreateAndGet) { const std::string big_integer_bytes = absl::HexStringToBytes(kHexBigInt); BigInteger big_integer(big_integer_bytes); EXPECT_THAT(big_integer.SizeInBytes(), Eq(256)); EXPECT_THAT(big_integer.GetValue(), Eq(big_integer_bytes)); } TEST(BigIntegerTest, CreateAndGetPadded) { const std::string big_integer_bytes = absl::HexStringToBytes(kHexBigInt); const std::string padded_big_integer_bytes = absl::HexStringToBytes(kHexBigIntPadded); BigInteger from_padded_big_integer(padded_big_integer_bytes); EXPECT_THAT(from_padded_big_integer.SizeInBytes(), Eq(256)); EXPECT_FALSE(from_padded_big_integer.GetValue() == padded_big_integer_bytes); EXPECT_THAT(from_padded_big_integer.GetValue(), Eq(big_integer_bytes)); } TEST(BigIntegerTest, CreateAndGetEmptyStringWorks) { const std::string empty_string = ""; BigInteger big_integer(empty_string); EXPECT_THAT(big_integer.SizeInBytes(), Eq(0)); EXPECT_THAT(big_integer.GetValue(), Eq("")); } TEST(BigIntegerTest, CreateAndGetNullCharactersWorks) { const std::string empty_string = "\0\0\0"; BigInteger big_integer(empty_string); EXPECT_THAT(big_integer.SizeInBytes(), Eq(0)); EXPECT_THAT(big_integer.GetValue(), Eq("")); } TEST(BigIntegerTest, Equals) { const std::string big_integer_bytes = absl::HexStringToBytes(kHexBigInt); BigInteger big_integer(big_integer_bytes); BigInteger same_big_integer(big_integer_bytes); EXPECT_TRUE(big_integer == same_big_integer); EXPECT_TRUE(same_big_integer == big_integer); EXPECT_FALSE(big_integer != same_big_integer); EXPECT_FALSE(same_big_integer != big_integer); } TEST(BigIntegerTest, EqualsPadded) { BigInteger big_integer(absl::HexStringToBytes(kHexBigInt)); BigInteger padded_big_integer(absl::HexStringToBytes(kHexBigIntPadded)); EXPECT_TRUE(big_integer == padded_big_integer); EXPECT_TRUE(padded_big_integer == big_integer); EXPECT_FALSE(big_integer != padded_big_integer); EXPECT_FALSE(padded_big_integer != big_integer); } TEST(BigIntegerTest, NotEquals) { const std::string other_big_integer_value_256 = absl::HexStringToBytes( "00c2410a2bcd4ce644c5b594ae5059e12b2f054b658d5da5959a2fdf1871b808bc3df3e6" "28d2792e51aad5c124b43bda453dca5cde4bcf28e7bd4effba0cb4b742bbb6d5a013cb63" "d1aa3a89e02627ef5398b52c0cfd97d208abeb8d7c9bce0bbeb019a86ddb589beb29a5b7" "4bf861075c677c81d430f030c265247af9d3c9140ccb65309d07e0adc1efd15cf17e7b05" "5d7da3868e4648cc3a180f0ee7f8e1e7b18098a3391b4ce7161e98d57af8a947e201a463" "e2d6bbca8059e5706e9dfed8f4856465ffa712ed1aa18e888d12dc6aa09ce95ecfca83cc" "5b0b15db09c8647f5d524c0f2e7620a3416b9623cadc0f097af573261c98c8400aa12af3" "8e43cad84d"); BigInteger big_integer(absl::HexStringToBytes(kHexBigInt)); BigInteger diff_big_integer(other_big_integer_value_256); EXPECT_THAT(big_integer.SizeInBytes(), Eq(256)); EXPECT_THAT(diff_big_integer.SizeInBytes(), Eq(256)); EXPECT_FALSE(big_integer == diff_big_integer); EXPECT_FALSE(diff_big_integer == big_integer); EXPECT_TRUE(big_integer != diff_big_integer); EXPECT_TRUE(diff_big_integer != big_integer); } TEST(BigIntegerTest, NotEqualsDifferentSize) { constexpr absl::string_view other_big_integer_value = "b3510a2bcd4ce644c5b594ae5059e12b2f054b658d5da5959a2fdf1871b808bc3df3e628" "d2792e51aad5c124b43bda453dca5cde4bcf28e7bd4effba0cb4b742bbb6d5a013cb63d1" "aa3a89e02627ef5398b52c0cfd97d208abeb8d7c9bce0bbeb019a86ddb589beb29a5b74b" "f861075c677c81d430f030c265247af9d3c9140ccb65309d07e0adc1efd15cf17e7b055d" "7da3868e4648cc3a180f0ee7f8e1e7b18098a3391b4ce7161e98d57af8a947e201a463e2" "d6bbca8059e5706e9dfed8f4856465ffa712ed1aa18e888d12dc6aa09ce95ecfca83cc5b" "0b15db09c8647f5d524c0f2e7620a3416b9623cadc0f097af573261c98c8400aa12af38e" "43cad84dbfff"; BigInteger big_integer(absl::HexStringToBytes(kHexBigInt)); BigInteger diff_big_integer(absl::HexStringToBytes(other_big_integer_value)); EXPECT_THAT(big_integer.SizeInBytes(), Eq(256)); EXPECT_THAT(diff_big_integer.SizeInBytes(), Eq(258)); EXPECT_FALSE(big_integer == diff_big_integer); EXPECT_FALSE(diff_big_integer == big_integer); EXPECT_TRUE(big_integer != diff_big_integer); EXPECT_TRUE(diff_big_integer != big_integer); } TEST(BigIntegerTest, CopyConstructor) { BigInteger big_integer(absl::HexStringToBytes(kHexBigInt)); BigInteger copy(big_integer); EXPECT_THAT(copy.SizeInBytes(), Eq(256)); EXPECT_THAT(copy.GetValue(), Eq(big_integer.GetValue())); } TEST(BigIntegerTest, CopyAssignment) { BigInteger big_integer(absl::HexStringToBytes(kHexBigInt)); BigInteger copy = big_integer; EXPECT_THAT(copy.SizeInBytes(), Eq(256)); EXPECT_THAT(copy.GetValue(), Eq(big_integer.GetValue())); } TEST(BigIntegerTest, MoveConstructor) { BigInteger big_integer(absl::HexStringToBytes(kHexBigInt)); BigInteger move(std::move(big_integer)); EXPECT_THAT(move.SizeInBytes(), Eq(256)); EXPECT_THAT(move.GetValue(), Eq(absl::HexStringToBytes(kHexBigInt))); } TEST(BigIntegerTest, MoveAssignment) { BigInteger big_integer(absl::HexStringToBytes(kHexBigInt)); BigInteger move = std::move(big_integer); EXPECT_THAT(move.SizeInBytes(), Eq(256)); EXPECT_THAT(move.GetValue(), Eq(absl::HexStringToBytes(kHexBigInt))); } } // namespace tink } // namespace crypto ================================================ FILE: cc/core/binary_keyset_reader.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/binary_keyset_reader.h" #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/keyset_reader.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using google::crypto::tink::EncryptedKeyset; using google::crypto::tink::Keyset; // static util::StatusOr> BinaryKeysetReader::New( std::unique_ptr keyset_stream) { if (keyset_stream == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "keyset_stream must be non-null."); } std::stringstream buffer; buffer << keyset_stream->rdbuf(); return New(buffer.str()); } // static util::StatusOr> BinaryKeysetReader::New( absl::string_view serialized_keyset) { std::unique_ptr reader( new BinaryKeysetReader(serialized_keyset)); return std::move(reader); } util::StatusOr> BinaryKeysetReader::Read() { auto keyset = absl::make_unique(); if (!keyset->ParseFromString(serialized_keyset_)) { return util::Status(absl::StatusCode::kInvalidArgument, "Could not parse the input stream as a Keyset-proto."); } return std::move(keyset); } util::StatusOr> BinaryKeysetReader::ReadEncrypted() { auto enc_keyset = absl::make_unique(); if (!enc_keyset->ParseFromString(serialized_keyset_)) { return util::Status( absl::StatusCode::kInvalidArgument, "Could not parse the input stream as an EncryptedKeyset-proto."); } return std::move(enc_keyset); } } // namespace tink } // namespace crypto ================================================ FILE: cc/core/binary_keyset_reader_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/binary_keyset_reader.h" #include #include #include #include #include #include #include #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" using crypto::tink::test::AddRawKey; using crypto::tink::test::AddTinkKey; using google::crypto::tink::EncryptedKeyset; using google::crypto::tink::KeyData; using google::crypto::tink::Keyset; using google::crypto::tink::KeyStatusType; namespace crypto { namespace tink { namespace { class BinaryKeysetReaderTest : public ::testing::Test { protected: void SetUp() override { Keyset::Key key; AddTinkKey("some key type", 42, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset_); AddRawKey("some other key type", 711, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset_); keyset_.set_primary_key_id(42); good_serialized_keyset_ = keyset_.SerializeAsString(); bad_serialized_keyset_ = "some weird string"; encrypted_keyset_.set_encrypted_keyset("some ciphertext with keyset"); auto keyset_info = encrypted_keyset_.mutable_keyset_info(); keyset_info->set_primary_key_id(42); auto key_info = keyset_info->add_key_info(); key_info->set_type_url("some type_url"); key_info->set_key_id(42); good_serialized_encrypted_keyset_ = encrypted_keyset_.SerializeAsString(); } EncryptedKeyset encrypted_keyset_; Keyset keyset_; std::string bad_serialized_keyset_; std::string good_serialized_keyset_; std::string good_serialized_encrypted_keyset_; }; TEST_F(BinaryKeysetReaderTest, testReaderCreation) { { // Input stream is null. std::unique_ptr null_stream(nullptr); auto reader_result = BinaryKeysetReader::New(std::move(null_stream)); EXPECT_FALSE(reader_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, reader_result.status().code()); } { // Good serialized keyset. auto reader_result = BinaryKeysetReader::New(good_serialized_keyset_); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); } { // Stream with good keyset. std::unique_ptr good_keyset_stream(new std::stringstream( std::string(good_serialized_keyset_), std::ios_base::in)); auto reader_result = BinaryKeysetReader::New(std::move(good_keyset_stream)); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); } { // Bad serialized keyset. auto reader_result = BinaryKeysetReader::New(bad_serialized_keyset_); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); } { // Stream with bad keyset. std::unique_ptr bad_keyset_stream(new std::stringstream( std::string(bad_serialized_keyset_), std::ios_base::in)); auto reader_result = BinaryKeysetReader::New(std::move(bad_keyset_stream)); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); } } TEST_F(BinaryKeysetReaderTest, testReadFromString) { { // Good string. auto reader_result = BinaryKeysetReader::New(good_serialized_keyset_); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); auto reader = std::move(reader_result.value()); auto read_result = reader->Read(); EXPECT_TRUE(read_result.ok()) << read_result.status(); auto keyset = std::move(read_result.value()); EXPECT_EQ(good_serialized_keyset_, keyset->SerializeAsString()); } { // Bad string. auto reader_result = BinaryKeysetReader::New(bad_serialized_keyset_); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); auto reader = std::move(reader_result.value()); auto read_result = reader->Read(); EXPECT_FALSE(read_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, read_result.status().code()); } } TEST_F(BinaryKeysetReaderTest, testReadFromStream) { { // Good stream. std::unique_ptr good_keyset_stream(new std::stringstream( std::string(good_serialized_keyset_), std::ios_base::in)); auto reader_result = BinaryKeysetReader::New(std::move(good_keyset_stream)); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); auto reader = std::move(reader_result.value()); auto read_result = reader->Read(); EXPECT_TRUE(read_result.ok()) << read_result.status(); auto keyset = std::move(read_result.value()); EXPECT_EQ(good_serialized_keyset_, keyset->SerializeAsString()); } { // Bad stream. std::unique_ptr bad_keyset_stream(new std::stringstream( std::string(bad_serialized_keyset_), std::ios_base::in)); auto reader_result = BinaryKeysetReader::New(std::move(bad_keyset_stream)); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); auto reader = std::move(reader_result.value()); auto read_result = reader->Read(); EXPECT_FALSE(read_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, read_result.status().code()); } } TEST_F(BinaryKeysetReaderTest, testReadEncryptedFromString) { { // Good string. auto reader_result = BinaryKeysetReader::New(good_serialized_encrypted_keyset_); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); auto reader = std::move(reader_result.value()); auto read_encrypted_result = reader->ReadEncrypted(); EXPECT_TRUE(read_encrypted_result.ok()) << read_encrypted_result.status(); auto encrypted_keyset = std::move(read_encrypted_result.value()); EXPECT_EQ(good_serialized_encrypted_keyset_, encrypted_keyset->SerializeAsString()); } { // Bad string. auto reader_result = BinaryKeysetReader::New(bad_serialized_keyset_); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); auto reader = std::move(reader_result.value()); auto read_encrypted_result = reader->ReadEncrypted(); EXPECT_FALSE(read_encrypted_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, read_encrypted_result.status().code()); } } TEST_F(BinaryKeysetReaderTest, testReadEncryptedFromStream) { { // Good stream. std::unique_ptr good_encrypted_keyset_stream( new std::stringstream(std::string(good_serialized_encrypted_keyset_), std::ios_base::in)); auto reader_result = BinaryKeysetReader::New(std::move(good_encrypted_keyset_stream)); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); auto reader = std::move(reader_result.value()); auto read_encrypted_result = reader->ReadEncrypted(); EXPECT_TRUE(read_encrypted_result.ok()) << read_encrypted_result.status(); auto encrypted_keyset = std::move(read_encrypted_result.value()); EXPECT_EQ(good_serialized_encrypted_keyset_, encrypted_keyset->SerializeAsString()); } { // Bad string. std::unique_ptr bad_keyset_stream(new std::stringstream( std::string(bad_serialized_keyset_), std::ios_base::in)); auto reader_result = BinaryKeysetReader::New(std::move(bad_keyset_stream)); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); auto reader = std::move(reader_result.value()); auto read_encrypted_result = reader->ReadEncrypted(); EXPECT_FALSE(read_encrypted_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, read_encrypted_result.status().code()); } } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/core/binary_keyset_writer.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/binary_keyset_writer.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" using google::crypto::tink::EncryptedKeyset; using google::crypto::tink::Keyset; namespace crypto { namespace tink { namespace { util::Status WriteProto(const portable_proto::MessageLite& proto, std::ostream* destination) { if (!proto.SerializeToOstream(destination)) { return util::Status(absl::StatusCode::kUnknown, "Error serializing to the destination stream."); } if (destination->fail()) { return util::Status(absl::StatusCode::kUnknown, "Error writing to the destination stream."); } return util::OkStatus(); } } // anonymous namespace // static util::StatusOr> BinaryKeysetWriter::New( std::unique_ptr destination_stream) { if (destination_stream == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "destination_stream must be non-null."); } return absl::WrapUnique( new BinaryKeysetWriter(std::move(destination_stream))); } util::Status BinaryKeysetWriter::Write(const Keyset& keyset) { return WriteProto(keyset, destination_stream_.get()); } util::Status BinaryKeysetWriter::Write( const EncryptedKeyset& encrypted_keyset) { return WriteProto(encrypted_keyset, destination_stream_.get()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/core/binary_keyset_writer_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/binary_keyset_writer.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/aead.h" #include "tink/aead/aead_config.h" #include "tink/aead_key_templates.h" #include "tink/config/global_registry.h" #include "tink/insecure_secret_key_access.h" #include "tink/keyset_handle.h" #include "tink/proto_keyset_format.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" using crypto::tink::test::AddRawKey; using crypto::tink::test::AddTinkKey; using ::crypto::tink::test::IsOk; using google::crypto::tink::EncryptedKeyset; using google::crypto::tink::KeyData; using google::crypto::tink::Keyset; using google::crypto::tink::KeyStatusType; using testing::Le; using testing::SizeIs; namespace crypto { namespace tink { namespace { class BinaryKeysetWriterTest : public ::testing::Test { protected: void SetUp() override { ASSERT_THAT(AeadConfig::Register(), IsOk()); Keyset::Key key; AddTinkKey("some key type", 42, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset_); AddRawKey("some other key type", 711, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset_); keyset_.set_primary_key_id(42); binary_keyset_ = keyset_.SerializeAsString(); encrypted_keyset_.set_encrypted_keyset("some ciphertext with keyset"); auto keyset_info = encrypted_keyset_.mutable_keyset_info(); keyset_info->set_primary_key_id(42); auto key_info = keyset_info->add_key_info(); key_info->set_type_url("some type_url"); key_info->set_key_id(42); binary_encrypted_keyset_ = encrypted_keyset_.SerializeAsString(); } EncryptedKeyset encrypted_keyset_; Keyset keyset_; std::string binary_keyset_; std::string binary_encrypted_keyset_; }; TEST_F(BinaryKeysetWriterTest, testWriterCreation) { { // Input stream is null. std::unique_ptr null_stream(nullptr); auto writer_result = BinaryKeysetWriter::New(std::move(null_stream)); EXPECT_FALSE(writer_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, writer_result.status().code()); } { // Stream with good keyset. std::unique_ptr destination_stream(new std::stringstream()); auto writer_result = BinaryKeysetWriter::New(std::move(destination_stream)); EXPECT_TRUE(writer_result.ok()) << writer_result.status(); } } TEST_F(BinaryKeysetWriterTest, testWriteKeyset) { std::stringbuf buffer; std::unique_ptr destination_stream(new std::ostream(&buffer)); auto writer_result = BinaryKeysetWriter::New(std::move(destination_stream)); ASSERT_TRUE(writer_result.ok()) << writer_result.status(); auto writer = std::move(writer_result.value()); auto status = writer->Write(keyset_); EXPECT_TRUE(status.ok()) << status; EXPECT_EQ(binary_keyset_, buffer.str()); } TEST_F(BinaryKeysetWriterTest, testWriteEncryptedKeyset) { std::stringbuf buffer; std::unique_ptr destination_stream(new std::ostream(&buffer)); auto writer_result = BinaryKeysetWriter::New(std::move(destination_stream)); ASSERT_TRUE(writer_result.ok()) << writer_result.status(); auto writer = std::move(writer_result.value()); auto status = writer->Write(encrypted_keyset_); EXPECT_TRUE(status.ok()) << status; EXPECT_EQ(binary_encrypted_keyset_, buffer.str()); } TEST_F(BinaryKeysetWriterTest, testDestinationStreamErrors) { std::stringbuf buffer; std::unique_ptr destination_stream(new std::ostream(&buffer)); destination_stream->setstate(std::ostream::badbit); auto writer_result = BinaryKeysetWriter::New(std::move(destination_stream)); ASSERT_TRUE(writer_result.ok()) << writer_result.status(); auto writer = std::move(writer_result.value()); { // Write keyset. auto status = writer->Write(keyset_); EXPECT_FALSE(status.ok()) << status; EXPECT_EQ(absl::StatusCode::kUnknown, status.code()); } { // Write encrypted keyset. auto status = writer->Write(encrypted_keyset_); EXPECT_FALSE(status.ok()) << status; EXPECT_EQ(absl::StatusCode::kUnknown, status.code()); } } TEST_F(BinaryKeysetWriterTest, EncryptedKeysetOverhead) { util::StatusOr> keysetEncryptionHandle = KeysetHandle::GenerateNew(AeadKeyTemplates::Aes128Gcm(), KeyGenConfigGlobalRegistry()); ASSERT_THAT(keysetEncryptionHandle, IsOk()); util::StatusOr> keyset_encryption_aead = (*keysetEncryptionHandle)->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(keyset_encryption_aead, IsOk()); util::StatusOr> handle = KeysetHandle::GenerateNew(AeadKeyTemplates::Aes128Gcm(), KeyGenConfigGlobalRegistry()); ASSERT_THAT(handle, IsOk()); crypto::tink::util::StatusOr serialized_keyset = SerializeKeysetToProtoKeysetFormat(**handle, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_keyset, IsOk()); util::StatusOr raw_encrypted_keyset = (*keyset_encryption_aead) ->Encrypt(util::SecretDataAsStringView(*serialized_keyset), ""); ASSERT_THAT(raw_encrypted_keyset, IsOk()); std::stringbuf encrypted_keyset; crypto::tink::util::StatusOr> writer = BinaryKeysetWriter::New( absl::make_unique(&encrypted_keyset)); ASSERT_THAT(writer, IsOk()); auto status = (*handle)->Write(writer->get(), **keyset_encryption_aead); ASSERT_THAT(status, IsOk()); // encrypted_keyset is a serialized protocol buffer that only contains // raw_encrypted_keyset in a field. So it should only be slightly larger than // raw_encrypted_keyset. EXPECT_THAT(encrypted_keyset.str(), SizeIs(Le(raw_encrypted_keyset->size() + 6))); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/core/cleartext_keyset_handle.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/cleartext_keyset_handle.h" #include #include #include #include #include #include "absl/container/flat_hash_map.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/keyset_handle.h" #include "tink/keyset_reader.h" #include "tink/keyset_writer.h" #include "tink/util/errors.h" #include "tink/util/secret_proto.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" using google::crypto::tink::Keyset; namespace crypto { namespace tink { // static util::StatusOr> CleartextKeysetHandle::Read( std::unique_ptr reader, const absl::flat_hash_map& monitoring_annotations) { util::StatusOr> keyset_result = reader->Read(); if (!keyset_result.ok()) { return ToStatusF(absl::StatusCode::kInvalidArgument, "Error reading keyset data: %s", keyset_result.status().message()); } util::StatusOr>> entries = KeysetHandle::GetEntriesFromKeyset(**keyset_result); if (!entries.ok()) { return entries.status(); } if (entries->size() != (*keyset_result)->key_size()) { return util::Status(absl::StatusCode::kInternal, "Error converting keyset proto into key entries."); } std::unique_ptr handle( new KeysetHandle(util::SecretProto(**keyset_result), *entries, monitoring_annotations)); return std::move(handle); } // static crypto::tink::util::Status CleartextKeysetHandle::Write( KeysetWriter* writer, const KeysetHandle& keyset_handle) { if (!writer) { return util::Status(absl::StatusCode::kInvalidArgument, "Error KeysetWriter cannot be null"); } return writer->Write(keyset_handle.get_keyset()); } // static std::unique_ptr CleartextKeysetHandle::GetKeysetHandle( const Keyset& keyset) { std::unique_ptr handle = absl::WrapUnique(new KeysetHandle(util::SecretProto(keyset))); return handle; } // static const Keyset& CleartextKeysetHandle::GetKeyset( const KeysetHandle& keyset_handle) { return keyset_handle.get_keyset(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/core/cleartext_keyset_handle_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/cleartext_keyset_handle.h" #include #include #include #include #include #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/binary_keyset_reader.h" #include "tink/keyset_handle.h" #include "tink/util/status.h" #include "tink/util/test_keyset_handle.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" using crypto::tink::test::AddRawKey; using crypto::tink::test::AddTinkKey; using google::crypto::tink::KeyData; using google::crypto::tink::Keyset; using google::crypto::tink::KeyStatusType; namespace crypto { namespace tink { namespace { class CleartextKeysetHandleTest : public ::testing::Test { protected: }; TEST_F(CleartextKeysetHandleTest, testRead) { Keyset keyset; Keyset::Key key; AddTinkKey("some_key_type", 42, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); AddRawKey("some_other_key_type", 711, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(42); { // Reader that reads a valid keyset. auto reader = std::move(BinaryKeysetReader::New(keyset.SerializeAsString()).value()); auto result = CleartextKeysetHandle::Read(std::move(reader)); EXPECT_TRUE(result.ok()) << result.status(); auto handle = std::move(result.value()); EXPECT_EQ(keyset.SerializeAsString(), TestKeysetHandle::GetKeyset(*handle).SerializeAsString()); } { // Reader that fails upon read. auto reader = std::move(BinaryKeysetReader::New("invalid serialized keyset").value()); auto result = CleartextKeysetHandle::Read(std::move(reader)); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); } } TEST_F(CleartextKeysetHandleTest, testWrite) { Keyset keyset; Keyset::Key key; AddTinkKey("some_key_type", 42, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); AddRawKey("some_other_key_type", 711, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(42); auto handle = TestKeysetHandle::GetKeysetHandle(keyset); std::stringbuf buffer; std::unique_ptr destination_stream(new std::ostream(&buffer)); auto writer = test::DummyKeysetWriter::New(std::move(destination_stream)).value(); // Write a valid keyset. EXPECT_EQ(CleartextKeysetHandle::Write(writer.get(), *(handle.get())), util::OkStatus()); // Null writer. EXPECT_NE(CleartextKeysetHandle::Write(nullptr, *(handle.get())), util::OkStatus()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/core/crypto_format.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/crypto_format.h" #include #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" using google::crypto::tink::OutputPrefixType; namespace crypto { namespace tink { namespace { // Writes bytes of 'value' in Big Endian order to 'buf'. // 'buf' must have at least 4 bytes allocated. void uint32_as_big_endian(uint32_t value, char* buf) { buf[0] = 0xff & (value >> 24); buf[1] = 0xff & (value >> 16); buf[2] = 0xff & (value >> 8); buf[3] = 0xff & (value >> 0); } } // anonymous namespace const int CryptoFormat::kNonRawPrefixSize; const int CryptoFormat::kLegacyPrefixSize; const uint8_t CryptoFormat::kLegacyStartByte; const int CryptoFormat::kTinkPrefixSize; const uint8_t CryptoFormat::kTinkStartByte; const int CryptoFormat::kRawPrefixSize; const absl::string_view CryptoFormat::kRawPrefix = ""; // static crypto::tink::util::StatusOr CryptoFormat::GetOutputPrefix( const google::crypto::tink::KeysetInfo::KeyInfo& key_info) { static_assert(sizeof(key_info.key_id() == sizeof(uint32_t )), ""); switch (key_info.output_prefix_type()) { case OutputPrefixType::TINK: { static_assert(kTinkPrefixSize == 1 + sizeof(uint32_t), ""); std::string prefix(kTinkPrefixSize, '\0'); prefix[0] = kTinkStartByte; uint32_as_big_endian(key_info.key_id(), &prefix[1]); return prefix; } case OutputPrefixType::CRUNCHY: // FALLTHROUGH case OutputPrefixType::LEGACY: { static_assert(kLegacyPrefixSize == 1 + sizeof(uint32_t), ""); std::string prefix(kLegacyPrefixSize, '\0'); prefix[0] = kLegacyStartByte; uint32_as_big_endian(key_info.key_id(), &prefix[1]); return prefix; } case OutputPrefixType::RAW: return std::string(kRawPrefix); default: return util::Status(absl::StatusCode::kInvalidArgument, "The given key has invalid OutputPrefixType."); } } } // namespace tink } // namespace crypto ================================================ FILE: cc/core/crypto_format_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/crypto_format.h" #include #include "gtest/gtest.h" #include "proto/tink.pb.h" using google::crypto::tink::KeysetInfo; using google::crypto::tink::OutputPrefixType; namespace crypto { namespace tink { namespace { // static void TestNonRawPrefix(const KeysetInfo::KeyInfo& key_info, int prefix_size, uint8_t prefix_first_byte) { auto prefix_result = CryptoFormat::GetOutputPrefix(key_info); EXPECT_TRUE(prefix_result.ok()) << prefix_result.status(); auto prefix = prefix_result.value(); EXPECT_EQ(prefix_size, prefix.length()); EXPECT_EQ(prefix_first_byte, prefix[0]); // key_id should follow in BigEndian order for (int i = 1; i <= 4; i++) { EXPECT_EQ(0xff & (key_info.key_id() >> ((4 - i) * 8)), 0xff & prefix[i]) << "Failed at byte " << i << "."; } } class CryptoFormatTest : public ::testing::Test { }; TEST_F(CryptoFormatTest, testConstants) { EXPECT_EQ(5, CryptoFormat::kNonRawPrefixSize); EXPECT_EQ(0, CryptoFormat::kRawPrefixSize); EXPECT_EQ(0x01, CryptoFormat::kTinkStartByte); EXPECT_EQ(0x00, CryptoFormat::kLegacyStartByte); EXPECT_EQ("", CryptoFormat::kRawPrefix); } TEST_F(CryptoFormatTest, testTinkPrefix) { uint32_t key_id = 263829; KeysetInfo::KeyInfo key_info; key_info.set_output_prefix_type(OutputPrefixType::TINK); key_info.set_key_id(key_id); TestNonRawPrefix(key_info, CryptoFormat::kNonRawPrefixSize, CryptoFormat::kTinkStartByte); } TEST_F(CryptoFormatTest, testLegacyPrefix) { uint32_t key_id = 8327256; KeysetInfo::KeyInfo key_info; key_info.set_output_prefix_type(OutputPrefixType::LEGACY); key_info.set_key_id(key_id); TestNonRawPrefix(key_info, CryptoFormat::kNonRawPrefixSize, CryptoFormat::kLegacyStartByte); } TEST_F(CryptoFormatTest, testCrunchyPrefix) { uint32_t key_id = 1223345; KeysetInfo::KeyInfo key_info; key_info.set_output_prefix_type(OutputPrefixType::CRUNCHY); key_info.set_key_id(key_id); TestNonRawPrefix(key_info, CryptoFormat::kNonRawPrefixSize, CryptoFormat::kLegacyStartByte); } TEST_F(CryptoFormatTest, testRawPrefix) { uint32_t key_id = 7662387; KeysetInfo::KeyInfo key_info; key_info.set_output_prefix_type(OutputPrefixType::RAW); key_info.set_key_id(key_id); auto prefix_result = CryptoFormat::GetOutputPrefix(key_info); EXPECT_TRUE(prefix_result.ok()) << prefix_result.status(); auto prefix = prefix_result.value(); EXPECT_EQ(CryptoFormat::kRawPrefixSize, prefix.length()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/core/ec_point_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/ec_point.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/big_integer.h" #include "tink/subtle/random.h" namespace crypto { namespace tink { namespace { using ::testing::Eq; TEST(EcPointTest, Create) { BigInteger x = BigInteger(subtle::Random::GetRandomBytes(32)); BigInteger y = BigInteger(subtle::Random::GetRandomBytes(32)); EcPoint point(x, y); ASSERT_THAT(point.GetX(), Eq(x)); ASSERT_THAT(point.GetY(), Eq(y)); } TEST(EcPointTest, CopyConstructor) { BigInteger x = BigInteger(subtle::Random::GetRandomBytes(32)); BigInteger y = BigInteger(subtle::Random::GetRandomBytes(32)); EcPoint point(x, y); EcPoint copy(point); ASSERT_THAT(copy.GetX(), Eq(x)); ASSERT_THAT(copy.GetY(), Eq(y)); } TEST(EcPointTest, CopyAssignment) { BigInteger x = BigInteger(subtle::Random::GetRandomBytes(32)); BigInteger y = BigInteger(subtle::Random::GetRandomBytes(32)); EcPoint point(x, y); EcPoint copy = point; ASSERT_THAT(copy.GetX(), Eq(x)); ASSERT_THAT(copy.GetY(), Eq(y)); } TEST(EcPointTest, MoveConstructor) { BigInteger x = BigInteger(subtle::Random::GetRandomBytes(32)); BigInteger y = BigInteger(subtle::Random::GetRandomBytes(32)); EcPoint point(x, y); EcPoint moved(std::move(point)); ASSERT_THAT(moved.GetX(), Eq(x)); ASSERT_THAT(moved.GetY(), Eq(y)); } TEST(EcPointTest, MoveAssignment) { BigInteger x = BigInteger(subtle::Random::GetRandomBytes(32)); BigInteger y = BigInteger(subtle::Random::GetRandomBytes(32)); EcPoint point(x, y); EcPoint moved = std::move(point); ASSERT_THAT(moved.GetX(), Eq(x)); ASSERT_THAT(moved.GetY(), Eq(y)); } TEST(EcPointTest, Equals) { BigInteger x = BigInteger(subtle::Random::GetRandomBytes(32)); BigInteger y = BigInteger(subtle::Random::GetRandomBytes(32)); EcPoint point(x, y); EcPoint other_point(x, y); EXPECT_TRUE(point == other_point); EXPECT_TRUE(other_point == point); EXPECT_FALSE(point != other_point); EXPECT_FALSE(other_point != point); } TEST(EcPointTest, DifferentXNotEqual) { BigInteger x = BigInteger(subtle::Random::GetRandomBytes(32)); BigInteger other_x = BigInteger(subtle::Random::GetRandomBytes(32)); BigInteger y = BigInteger(subtle::Random::GetRandomBytes(32)); EcPoint point(x, y); EcPoint other_point(other_x, y); EXPECT_TRUE(point != other_point); EXPECT_TRUE(other_point != point); EXPECT_FALSE(point == other_point); EXPECT_FALSE(other_point == point); } TEST(EcPointTest, DifferentYNotEqual) { BigInteger x = BigInteger(subtle::Random::GetRandomBytes(32)); BigInteger y = BigInteger(subtle::Random::GetRandomBytes(32)); BigInteger other_y = BigInteger(subtle::Random::GetRandomBytes(32)); EcPoint point(x, y); EcPoint other_point(x, other_y); EXPECT_TRUE(point != other_point); EXPECT_TRUE(other_point != point); EXPECT_FALSE(point == other_point); EXPECT_FALSE(other_point == point); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/core/json_keyset_reader.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/json_keyset_reader.h" #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "include/rapidjson/document.h" #include "include/rapidjson/error/en.h" #include "include/rapidjson/rapidjson.h" #include "include/rapidjson/reader.h" #include "tink/keyset_reader.h" #include "tink/util/enums.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using crypto::tink::util::Enums; using google::crypto::tink::EncryptedKeyset; using google::crypto::tink::KeyData; using google::crypto::tink::Keyset; using google::crypto::tink::KeysetInfo; namespace { // Helpers for validating and parsing JSON strings with EncryptedKeyset-protos. util::Status ValidateEncryptedKeyset(const rapidjson::Document& json_doc) { if (!json_doc.HasMember("encryptedKeyset") || !json_doc["encryptedKeyset"].IsString() || (json_doc.HasMember("keysetInfo") && !json_doc["keysetInfo"].IsObject())) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid JSON EncryptedKeyset"); } return util::OkStatus(); } util::Status ValidateKeysetInfo(const rapidjson::Value& json_value) { if (!json_value.HasMember("primaryKeyId") || !json_value["primaryKeyId"].IsUint() || !json_value.HasMember("keyInfo") || !json_value["keyInfo"].IsArray() || json_value["keyInfo"].Size() < 1) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid JSON KeysetInfo"); } return util::OkStatus(); } util::Status ValidateKeyInfo(const rapidjson::Value& json_value) { if (!json_value.HasMember("typeUrl") || !json_value["typeUrl"].IsString() || !json_value.HasMember("status") || !json_value["status"].IsString() || !json_value.HasMember("keyId") || !json_value["keyId"].IsUint() || !json_value.HasMember("outputPrefixType") || !json_value["outputPrefixType"].IsString()) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid JSON KeyInfo"); } return util::OkStatus(); } util::StatusOr> KeyInfoFromJson( const rapidjson::Value& json_value) { auto status = ValidateKeyInfo(json_value); if (!status.ok()) return status; auto key_info = absl::make_unique(); key_info->set_type_url(json_value["typeUrl"].GetString()); key_info->set_status(Enums::KeyStatus(json_value["status"].GetString())); key_info->set_key_id(json_value["keyId"].GetUint()); key_info->set_output_prefix_type( Enums::OutputPrefix(json_value["outputPrefixType"].GetString())); return std::move(key_info); } util::StatusOr> KeysetInfoFromJson( const rapidjson::Value& json_value) { auto status = ValidateKeysetInfo(json_value); if (!status.ok()) return status; auto keyset_info = absl::make_unique(); keyset_info->set_primary_key_id(json_value["primaryKeyId"].GetUint()); for (const auto& json_key_info : json_value["keyInfo"].GetArray()) { auto key_info_result = KeyInfoFromJson(json_key_info); if (!key_info_result.ok()) return key_info_result.status(); *(keyset_info->add_key_info()) = *(key_info_result.value()); } return std::move(keyset_info); } util::StatusOr> EncryptedKeysetFromJson( const rapidjson::Document& json_doc) { auto status = ValidateEncryptedKeyset(json_doc); if (!status.ok()) return status; std::string enc_keyset; if (!absl::Base64Unescape(json_doc["encryptedKeyset"].GetString(), &enc_keyset)) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid JSON EncryptedKeyset"); } auto encrypted_keyset = absl::make_unique(); encrypted_keyset->set_encrypted_keyset(enc_keyset); if (json_doc.HasMember("keysetInfo")) { auto keyset_info_result = KeysetInfoFromJson(json_doc["keysetInfo"]); if (!keyset_info_result.ok()) { return keyset_info_result.status(); } *(encrypted_keyset->mutable_keyset_info()) = *(keyset_info_result.value()); } return std::move(encrypted_keyset); } // Helpers for validating and parsing JSON strings with Keyset-protos. util::Status ValidateKeyset(const rapidjson::Document& json_doc) { if (!json_doc.HasMember("primaryKeyId") || !json_doc["primaryKeyId"].IsUint() || !json_doc.HasMember("key") || !json_doc["key"].IsArray() || json_doc["key"].Size() < 1) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid JSON Keyset"); } return util::OkStatus(); } util::Status ValidateKey(const rapidjson::Value& json_value) { if (!json_value.HasMember("keyData") || !json_value["keyData"].IsObject() || !json_value.HasMember("status") || !json_value["status"].IsString() || !json_value.HasMember("keyId") || !json_value["keyId"].IsUint() || !json_value.HasMember("outputPrefixType") || !json_value["outputPrefixType"].IsString()) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid JSON Key"); } return util::OkStatus(); } util::Status ValidateKeyData(const rapidjson::Value& json_value) { if (!json_value.HasMember("typeUrl") || !json_value["typeUrl"].IsString() || !json_value.HasMember("value") || !json_value["value"].IsString() || !json_value.HasMember("keyMaterialType") || !json_value["keyMaterialType"].IsString()) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid JSON KeyData"); } return util::OkStatus(); } util::StatusOr> KeyDataFromJson( const rapidjson::Value& json_value) { auto status = ValidateKeyData(json_value); if (!status.ok()) return status; std::string value_field; if (!absl::Base64Unescape(json_value["value"].GetString(), &value_field)) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid JSON KeyData"); } auto key_data = absl::make_unique(); key_data->set_type_url(json_value["typeUrl"].GetString()); key_data->set_value(value_field); key_data->set_key_material_type( Enums::KeyMaterial(json_value["keyMaterialType"].GetString())); return std::move(key_data); } util::StatusOr> KeyFromJson( const rapidjson::Value& json_value) { auto status = ValidateKey(json_value); if (!status.ok()) return status; auto key_data_result = KeyDataFromJson(json_value["keyData"]); if (!key_data_result.ok()) return key_data_result.status(); auto key = absl::make_unique(); key->set_key_id(json_value["keyId"].GetUint()); key->set_status(Enums::KeyStatus(json_value["status"].GetString())); key->set_output_prefix_type( Enums::OutputPrefix(json_value["outputPrefixType"].GetString())); *(key->mutable_key_data()) = *(key_data_result.value()); return std::move(key); } util::StatusOr> KeysetFromJson( const rapidjson::Document& json_doc) { auto status = ValidateKeyset(json_doc); if (!status.ok()) return status; auto keyset = absl::make_unique(); keyset->set_primary_key_id(json_doc["primaryKeyId"].GetUint()); for (const auto& json_key : json_doc["key"].GetArray()) { auto key_result = KeyFromJson(json_key); if (!key_result.ok()) return key_result.status(); *(keyset->add_key()) = *(key_result.value()); } return std::move(keyset); } } // namespace // static util::StatusOr> JsonKeysetReader::New( std::unique_ptr keyset_stream) { if (keyset_stream == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "keyset_stream must be non-null."); } return absl::WrapUnique(new JsonKeysetReader(std::move(keyset_stream))); } // static util::StatusOr> JsonKeysetReader::New( absl::string_view serialized_keyset) { return absl::WrapUnique(new JsonKeysetReader(serialized_keyset)); } util::StatusOr> JsonKeysetReader::Read() { std::string serialized_keyset_from_stream; std::string* serialized_keyset; if (keyset_stream_ == nullptr) { serialized_keyset = &serialized_keyset_; } else { serialized_keyset_from_stream = std::string(std::istreambuf_iterator(*keyset_stream_), {}); serialized_keyset = &serialized_keyset_from_stream; } rapidjson::Document json_doc(rapidjson::kObjectType); if (json_doc.Parse(serialized_keyset->c_str()) .HasParseError()) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat( "Invalid JSON Keyset: Error (offset ", json_doc.GetErrorOffset(), "): ", rapidjson::GetParseError_En(json_doc.GetParseError()))); } if (!json_doc.IsObject()) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid JSON Keyset: Expected object."); } return KeysetFromJson(json_doc); } util::StatusOr> JsonKeysetReader::ReadEncrypted() { std::string serialized_keyset_from_stream; std::string* serialized_keyset; if (keyset_stream_ == nullptr) { serialized_keyset = &serialized_keyset_; } else { serialized_keyset_from_stream = std::string(std::istreambuf_iterator(*keyset_stream_), {}); serialized_keyset = &serialized_keyset_from_stream; } rapidjson::Document json_doc; if (json_doc.Parse(serialized_keyset->c_str()) .HasParseError()) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid JSON EncryptedKeyset: Error (offset ", json_doc.GetErrorOffset(), "): ", rapidjson::GetParseError_En(json_doc.GetParseError()))); } return EncryptedKeysetFromJson(json_doc); } } // namespace tink } // namespace crypto ================================================ FILE: cc/core/json_keyset_reader_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/json_keyset_reader.h" #include #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/substitute.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_eax.pb.h" #include "proto/aes_gcm.pb.h" #include "proto/tink.pb.h" #include "tink/keyset_reader.h" namespace crypto { namespace tink { using ::crypto::tink::test::AddRawKey; using ::crypto::tink::test::AddTinkKey; using ::crypto::tink::test::IsOk; using ::google::crypto::tink::AesEaxKey; using ::google::crypto::tink::AesGcmKey; using ::google::crypto::tink::EncryptedKeyset; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::Keyset; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::Not; namespace { class JsonKeysetReaderTest : public ::testing::Test { protected: void SetUp() override { gcm_key_.set_key_value("some gcm key value"); gcm_key_.set_version(0); eax_key_.set_key_value("some eax key value"); eax_key_.set_version(0); eax_key_.mutable_params()->set_iv_size(16); AddTinkKey("type.googleapis.com/google.crypto.tink.AesGcmKey", 42, gcm_key_, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset_); AddRawKey("type.googleapis.com/google.crypto.tink.AesEaxKey", 711, eax_key_, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset_); keyset_.set_primary_key_id(42); good_json_keyset_ = absl::Substitute( R"( { "primaryKeyId":42, "key":[ { "keyData":{ "typeUrl":"type.googleapis.com/google.crypto.tink.AesGcmKey", "keyMaterialType":"SYMMETRIC", "value": "$0" }, "outputPrefixType":"TINK", "keyId":42, "status":"ENABLED" }, { "keyData":{ "typeUrl":"type.googleapis.com/google.crypto.tink.AesEaxKey", "keyMaterialType":"SYMMETRIC", "value":"$1" }, "outputPrefixType":"RAW", "keyId":711, "status":"ENABLED" } ] })", absl::Base64Escape(gcm_key_.SerializeAsString()), absl::Base64Escape(eax_key_.SerializeAsString())); bad_json_keyset_ = "some weird string"; std::string enc_keyset = "some ciphertext with keyset"; encrypted_keyset_.set_encrypted_keyset(enc_keyset); std::string enc_keyset_base64; absl::Base64Escape(enc_keyset, &enc_keyset_base64); auto keyset_info = encrypted_keyset_.mutable_keyset_info(); keyset_info->set_primary_key_id(42); auto key_info = keyset_info->add_key_info(); key_info->set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey"); key_info->set_key_id(42); key_info->set_output_prefix_type(OutputPrefixType::TINK); key_info->set_status(KeyStatusType::ENABLED); good_json_encrypted_keyset_ = "{" "\"encryptedKeyset\": \"" + enc_keyset_base64 + "\", " "\"keysetInfo\": {" " \"primaryKeyId\": 42," " \"keyInfo\": [" " {" " \"typeUrl\":" " \"type.googleapis.com/google.crypto.tink.AesGcmKey\"," " \"outputPrefixType\": \"TINK\"," " \"keyId\": 42," " \"status\": \"ENABLED\"" " }" " ]" "}}"; } EncryptedKeyset encrypted_keyset_; Keyset keyset_; std::string bad_json_keyset_; std::string good_json_keyset_; std::string good_json_encrypted_keyset_; // Some prepopulated keys. AesGcmKey gcm_key_; AesEaxKey eax_key_; }; TEST_F(JsonKeysetReaderTest, testReaderCreation) { { // Input stream is null. std::unique_ptr null_stream(nullptr); auto reader_result = JsonKeysetReader::New(std::move(null_stream)); EXPECT_FALSE(reader_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, reader_result.status().code()); } { // Good serialized keyset. auto reader_result = JsonKeysetReader::New(good_json_keyset_); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); } { // Stream with good keyset. std::unique_ptr good_keyset_stream(new std::stringstream( std::string(good_json_keyset_), std::ios_base::in)); auto reader_result = JsonKeysetReader::New(std::move(good_keyset_stream)); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); } { // Bad serialized keyset. auto reader_result = JsonKeysetReader::New(bad_json_keyset_); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); } { // Stream with bad keyset. std::unique_ptr bad_keyset_stream(new std::stringstream( std::string(bad_json_keyset_), std::ios_base::in)); auto reader_result = JsonKeysetReader::New(std::move(bad_keyset_stream)); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); } } TEST_F(JsonKeysetReaderTest, testReadFromString) { { // Good string. auto reader_result = JsonKeysetReader::New(good_json_keyset_); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); auto reader = std::move(reader_result.value()); auto read_result = reader->Read(); EXPECT_TRUE(read_result.ok()) << read_result.status(); auto keyset = std::move(read_result.value()); EXPECT_EQ(keyset_.SerializeAsString(), keyset->SerializeAsString()); } { // Bad string. auto reader_result = JsonKeysetReader::New(bad_json_keyset_); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); auto reader = std::move(reader_result.value()); auto read_result = reader->Read(); EXPECT_FALSE(read_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, read_result.status().code()); } { // A valid JSON value, but not a JSON object. auto reader_result = JsonKeysetReader::New("124"); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); auto reader = std::move(reader_result.value()); auto read_result = reader->Read(); EXPECT_FALSE(read_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, read_result.status().code()); } } TEST_F(JsonKeysetReaderTest, testReadFromStream) { { // Good stream. std::unique_ptr good_keyset_stream(new std::stringstream( std::string(good_json_keyset_), std::ios_base::in)); auto reader_result = JsonKeysetReader::New(std::move(good_keyset_stream)); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); auto reader = std::move(reader_result.value()); auto read_result = reader->Read(); EXPECT_TRUE(read_result.ok()) << read_result.status(); auto keyset = std::move(read_result.value()); EXPECT_EQ(keyset_.SerializeAsString(), keyset->SerializeAsString()); } { // Bad stream. std::unique_ptr bad_keyset_stream(new std::stringstream( std::string(bad_json_keyset_), std::ios_base::in)); auto reader_result = JsonKeysetReader::New(std::move(bad_keyset_stream)); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); auto reader = std::move(reader_result.value()); auto read_result = reader->Read(); EXPECT_FALSE(read_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, read_result.status().code()); } } TEST_F(JsonKeysetReaderTest, testReadEncryptedFromString) { { // Good string. auto reader_result = JsonKeysetReader::New(good_json_encrypted_keyset_); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); auto reader = std::move(reader_result.value()); auto read_encrypted_result = reader->ReadEncrypted(); EXPECT_TRUE(read_encrypted_result.ok()) << read_encrypted_result.status(); auto encrypted_keyset = std::move(read_encrypted_result.value()); EXPECT_EQ(encrypted_keyset_.SerializeAsString(), encrypted_keyset->SerializeAsString()); } { // Bad string. auto reader_result = JsonKeysetReader::New(bad_json_keyset_); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); auto reader = std::move(reader_result.value()); auto read_encrypted_result = reader->ReadEncrypted(); EXPECT_FALSE(read_encrypted_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, read_encrypted_result.status().code()); } } TEST_F(JsonKeysetReaderTest, testReadEncryptedFromStream) { { // Good stream. std::unique_ptr good_encrypted_keyset_stream( new std::stringstream(std::string(good_json_encrypted_keyset_), std::ios_base::in)); auto reader_result = JsonKeysetReader::New(std::move(good_encrypted_keyset_stream)); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); auto reader = std::move(reader_result.value()); auto read_encrypted_result = reader->ReadEncrypted(); EXPECT_TRUE(read_encrypted_result.ok()) << read_encrypted_result.status(); auto encrypted_keyset = std::move(read_encrypted_result.value()); EXPECT_EQ(encrypted_keyset_.SerializeAsString(), encrypted_keyset->SerializeAsString()); } { // Bad string. std::unique_ptr bad_keyset_stream(new std::stringstream( std::string(bad_json_keyset_), std::ios_base::in)); auto reader_result = JsonKeysetReader::New(std::move(bad_keyset_stream)); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); auto reader = std::move(reader_result.value()); auto read_encrypted_result = reader->ReadEncrypted(); EXPECT_FALSE(read_encrypted_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, read_encrypted_result.status().code()); } } TEST_F(JsonKeysetReaderTest, ReadLargeKeyId) { std::string json_serialization = absl::Substitute(R"( { "primaryKeyId": 4294967275, "key":[ { "keyData":{ "typeUrl":"type.googleapis.com/google.crypto.tink.AesGcmKey", "keyMaterialType":"SYMMETRIC", "value": "$0" }, "outputPrefixType":"TINK", "keyId": 4294967275, "status":"ENABLED" }, { "keyData":{ "typeUrl":"type.googleapis.com/google.crypto.tink.AesEaxKey", "keyMaterialType":"SYMMETRIC", "value":"$1" }, "outputPrefixType":"RAW", "keyId":711, "status":"ENABLED" } ] })", absl::Base64Escape(gcm_key_.SerializeAsString()), absl::Base64Escape(eax_key_.SerializeAsString())); auto reader_result = JsonKeysetReader::New(json_serialization); ASSERT_THAT(reader_result, IsOk()); auto reader = std::move(reader_result.value()); auto read_result = reader->Read(); ASSERT_THAT(read_result, IsOk()); auto keyset = std::move(read_result.value()); EXPECT_THAT(keyset->primary_key_id(), Eq(4294967275)); } TEST_F(JsonKeysetReaderTest, RejectsNegativeKeyIds) { std::string json_serialization = absl::Substitute(R"( { "primaryKeyId": 711, "key":[ { "keyData":{ "typeUrl":"type.googleapis.com/google.crypto.tink.AesGcmKey", "keyMaterialType":"SYMMETRIC", "value": "$0" }, "outputPrefixType":"TINK", "keyId": -21, "status":"ENABLED" }, { "keyData":{ "typeUrl":"type.googleapis.com/google.crypto.tink.AesEaxKey", "keyMaterialType":"SYMMETRIC", "value":"$1" }, "outputPrefixType":"RAW", "keyId":711, "status":"ENABLED" } ] })", absl::Base64Escape(gcm_key_.SerializeAsString()), absl::Base64Escape(eax_key_.SerializeAsString())); auto reader_result = JsonKeysetReader::New(json_serialization); ASSERT_THAT(reader_result, IsOk()); auto reader = std::move(reader_result.value()); auto read_result = reader->Read(); EXPECT_THAT(read_result, Not(IsOk())); } TEST_F(JsonKeysetReaderTest, RejectsKeyIdLargerThanUint32) { // 4294967296 = 2^32, which is too large for uint32. std::string json_serialization = absl::Substitute(R"( { "primaryKeyId": 711, "key":[ { "keyData":{ "typeUrl":"type.googleapis.com/google.crypto.tink.AesGcmKey", "keyMaterialType":"SYMMETRIC", "value": "$0" }, "outputPrefixType":"TINK", "keyId": 4294967296, "status":"ENABLED" }, { "keyData":{ "typeUrl":"type.googleapis.com/google.crypto.tink.AesEaxKey", "keyMaterialType":"SYMMETRIC", "value":"$1" }, "outputPrefixType":"RAW", "keyId":711, "status":"ENABLED" } ] })", absl::Base64Escape(gcm_key_.SerializeAsString()), absl::Base64Escape(eax_key_.SerializeAsString())); auto reader_result = JsonKeysetReader::New(json_serialization); ASSERT_THAT(reader_result, IsOk()); auto reader = std::move(reader_result.value()); auto read_result = reader->Read(); EXPECT_THAT(read_result, Not(IsOk())); } TEST_F(JsonKeysetReaderTest, parseRecursiveJsonStringFails) { std::string recursive_json; for (int i = 0; i < 1000000; i++) { recursive_json.append("{\"a\":"); } recursive_json.append("1"); for (int i = 0; i < 1000000; i++) { recursive_json.append("}"); } util::StatusOr> reader = JsonKeysetReader::New(recursive_json); ASSERT_THAT(reader, IsOk()); util::StatusOr> keyset = (*reader)->Read(); EXPECT_THAT(keyset, Not(IsOk())); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/core/json_keyset_writer.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/json_keyset_writer.h" #include #include #include #include #include #include #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/string_view.h" #include "include/rapidjson/document.h" #include "include/rapidjson/prettywriter.h" #include "include/rapidjson/rapidjson.h" #include "include/rapidjson/stringbuffer.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using google::crypto::tink::EncryptedKeyset; using google::crypto::tink::KeyData; using google::crypto::tink::Keyset; using google::crypto::tink::KeysetInfo; using util::Enums; namespace { // Helpers for transoforming Keyset-protos to JSON strings. util::Status ToJson(const KeyData& key_data, rapidjson::Value* json_key_data, rapidjson::Document::AllocatorType* allocator) { rapidjson::Value type_url(rapidjson::kStringType); type_url.SetString(key_data.type_url().c_str(), *allocator); json_key_data->AddMember("typeUrl", type_url, *allocator); rapidjson::Value material_type(rapidjson::kStringType); material_type.SetString(Enums::KeyMaterialName(key_data.key_material_type()), *allocator); json_key_data->AddMember("keyMaterialType", material_type, *allocator); std::string base64_string; absl::Base64Escape(key_data.value(), &base64_string); rapidjson::Value key_value(rapidjson::kStringType); key_value.SetString(base64_string.c_str(), *allocator); json_key_data->AddMember("value", key_value, *allocator); return util::OkStatus(); } util::Status ToJson(const Keyset::Key& key, rapidjson::Value* json_key, rapidjson::Document::AllocatorType* allocator) { rapidjson::Value key_id(rapidjson::kNumberType); key_id.SetUint(key.key_id()); json_key->AddMember("keyId", key_id, *allocator); rapidjson::Value key_status(rapidjson::kStringType); key_status.SetString(Enums::KeyStatusName(key.status()), *allocator); json_key->AddMember("status", key_status, *allocator); rapidjson::Value prefix_type(rapidjson::kStringType); prefix_type.SetString(Enums::OutputPrefixName(key.output_prefix_type()), *allocator); json_key->AddMember("outputPrefixType", prefix_type, *allocator); rapidjson::Value json_key_data(rapidjson::kObjectType); auto status = ToJson(key.key_data(), &json_key_data, allocator); if (!status.ok()) return status; json_key->AddMember("keyData", json_key_data, *allocator); return util::OkStatus(); } util::StatusOr ToJsonString(const Keyset& keyset) { rapidjson::Document json_doc(rapidjson::kObjectType); auto& allocator = json_doc.GetAllocator(); rapidjson::Value primary_key_id(rapidjson::kNumberType); primary_key_id.SetUint(keyset.primary_key_id()); json_doc.AddMember("primaryKeyId", primary_key_id, allocator); rapidjson::Value key_array(rapidjson::kArrayType); for (const Keyset::Key& key : keyset.key()) { rapidjson::Value json_key(rapidjson::kObjectType); auto status = ToJson(key, &json_key, &allocator); if (!status.ok()) return status; key_array.PushBack(json_key, allocator); } json_doc.AddMember("key", key_array, allocator); rapidjson::StringBuffer string_buffer; rapidjson::PrettyWriter writer(string_buffer); json_doc.Accept(writer); return std::string(string_buffer.GetString()); } util::Status ToJson(const KeysetInfo::KeyInfo& key_info, rapidjson::Value* json_key_info, rapidjson::Document::AllocatorType* allocator) { rapidjson::Value type_url(rapidjson::kStringType); type_url.SetString(key_info.type_url().c_str(), *allocator); json_key_info->AddMember("typeUrl", type_url, *allocator); rapidjson::Value key_id(rapidjson::kNumberType); key_id.SetUint(key_info.key_id()); json_key_info->AddMember("keyId", key_id, *allocator); rapidjson::Value key_status(rapidjson::kStringType); key_status.SetString(Enums::KeyStatusName(key_info.status()), *allocator); json_key_info->AddMember("status", key_status, *allocator); rapidjson::Value prefix_type(rapidjson::kStringType); prefix_type.SetString(Enums::OutputPrefixName(key_info.output_prefix_type()), *allocator); json_key_info->AddMember("outputPrefixType", prefix_type, *allocator); return util::OkStatus(); } util::Status ToJson(const KeysetInfo& keyset_info, rapidjson::Value* json_keyset_info, rapidjson::Document::AllocatorType* allocator) { rapidjson::Value primary_key_id(rapidjson::kNumberType); primary_key_id.SetUint(keyset_info.primary_key_id()); json_keyset_info->AddMember("primaryKeyId", primary_key_id, *allocator); rapidjson::Value key_info_array(rapidjson::kArrayType); for (const KeysetInfo::KeyInfo& key_info : keyset_info.key_info()) { rapidjson::Value json_key_info(rapidjson::kObjectType); auto status = ToJson(key_info, &json_key_info, allocator); if (!status.ok()) return status; key_info_array.PushBack(json_key_info, *allocator); } json_keyset_info->AddMember("keyInfo", key_info_array, *allocator); return util::OkStatus(); } util::StatusOr ToJsonString(const EncryptedKeyset& keyset) { rapidjson::Document json_doc(rapidjson::kObjectType); auto& allocator = json_doc.GetAllocator(); std::string base64_string; absl::Base64Escape(keyset.encrypted_keyset(), &base64_string); rapidjson::Value encrypted_keyset(rapidjson::kStringType); encrypted_keyset.SetString(base64_string.c_str(), allocator); json_doc.AddMember("encryptedKeyset", encrypted_keyset, allocator); if (keyset.has_keyset_info()) { rapidjson::Value json_keyset_info(rapidjson::kObjectType); auto status = ToJson(keyset.keyset_info(), &json_keyset_info, &allocator); if (!status.ok()) return status; json_doc.AddMember("keysetInfo", json_keyset_info, allocator); } rapidjson::StringBuffer string_buffer; rapidjson::PrettyWriter writer(string_buffer); json_doc.Accept(writer); return std::string(string_buffer.GetString()); } util::Status WriteData(absl::string_view data, std::ostream* destination) { (*destination) << data; if (destination->fail()) { return util::Status(absl::StatusCode::kUnknown, "Error writing to the destination stream."); } return util::OkStatus(); } } // anonymous namespace // static util::StatusOr> JsonKeysetWriter::New( std::unique_ptr destination_stream) { if (destination_stream == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "destination_stream must be non-null."); } std::unique_ptr writer( new JsonKeysetWriter(std::move(destination_stream))); return std::move(writer); } util::Status JsonKeysetWriter::Write(const Keyset& keyset) { auto json_string_result = ToJsonString(keyset); if (!json_string_result.ok()) return json_string_result.status(); return WriteData(json_string_result.value(), destination_stream_.get()); } util::Status JsonKeysetWriter::Write( const EncryptedKeyset& encrypted_keyset) { auto json_string_result = ToJsonString(encrypted_keyset); if (!json_string_result.ok()) return json_string_result.status(); return WriteData(json_string_result.value(), destination_stream_.get()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/core/json_keyset_writer_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/json_keyset_writer.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/substitute.h" #include "include/rapidjson/document.h" #include "include/rapidjson/error/en.h" #include "include/rapidjson/rapidjson.h" #include "tink/json_keyset_reader.h" #include "tink/util/protobuf_helper.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_eax.pb.h" #include "proto/aes_gcm.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::crypto::tink::test::AddRawKey; using ::crypto::tink::test::AddTinkKey; using ::crypto::tink::test::IsOk; using ::google::crypto::tink::AesEaxKey; using ::google::crypto::tink::AesGcmKey; using ::google::crypto::tink::EncryptedKeyset; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::Keyset; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::OutputPrefixType; using ::testing::HasSubstr; namespace { class JsonKeysetWriterTest : public ::testing::Test { protected: void SetUp() override { gcm_key_.set_key_value("some gcm key value"); gcm_key_.set_version(0); eax_key_.set_key_value("some eax key value"); eax_key_.set_version(0); eax_key_.mutable_params()->set_iv_size(16); AddTinkKey("type.googleapis.com/google.crypto.tink.AesGcmKey", 42, gcm_key_, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset_); AddRawKey("type.googleapis.com/google.crypto.tink.AesEaxKey", 711, eax_key_, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset_); keyset_.set_primary_key_id(42); std::string json_string = absl::Substitute(R"( { "primaryKeyId":42, "key":[ { "keyData":{ "typeUrl":"type.googleapis.com/google.crypto.tink.AesGcmKey", "keyMaterialType":"SYMMETRIC", "value": "$0" }, "outputPrefixType":"TINK", "keyId":42, "status":"ENABLED" }, { "keyData":{ "typeUrl":"type.googleapis.com/google.crypto.tink.AesEaxKey", "keyMaterialType":"SYMMETRIC", "value":"$1" }, "outputPrefixType":"RAW", "keyId":711, "status":"ENABLED" } ] })", absl::Base64Escape(gcm_key_.SerializeAsString()), absl::Base64Escape(eax_key_.SerializeAsString())); ASSERT_FALSE(good_json_keyset_.Parse(json_string.c_str()).HasParseError()); std::string enc_keyset = "some ciphertext with keyset"; encrypted_keyset_.set_encrypted_keyset(enc_keyset); std::string enc_keyset_base64; absl::Base64Escape(enc_keyset, &enc_keyset_base64); auto keyset_info = encrypted_keyset_.mutable_keyset_info(); keyset_info->set_primary_key_id(42); auto key_info = keyset_info->add_key_info(); key_info->set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey"); key_info->set_key_id(42); key_info->set_output_prefix_type(OutputPrefixType::TINK); key_info->set_status(KeyStatusType::ENABLED); good_json_encrypted_keyset_string_ = "{" "\"encryptedKeyset\": \"" + enc_keyset_base64 + "\", " "\"keysetInfo\": {" " \"primaryKeyId\": 42," " \"keyInfo\": [" " {" " \"typeUrl\":" " \"type.googleapis.com/google.crypto.tink.AesGcmKey\"," " \"outputPrefixType\": \"TINK\"," " \"keyId\": 42," " \"status\": \"ENABLED\"" " }" " ]" "}}"; ASSERT_FALSE(good_json_encrypted_keyset_.Parse( good_json_encrypted_keyset_string_.c_str()).HasParseError()); } EncryptedKeyset encrypted_keyset_; Keyset keyset_; rapidjson::Document good_json_keyset_; rapidjson::Document good_json_encrypted_keyset_; std::string good_json_encrypted_keyset_string_; AesGcmKey gcm_key_; AesEaxKey eax_key_; }; TEST_F(JsonKeysetWriterTest, testWriterCreation) { { // Input stream is null. std::unique_ptr null_stream(nullptr); auto writer_result = JsonKeysetWriter::New(std::move(null_stream)); EXPECT_FALSE(writer_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, writer_result.status().code()); } { // Stream with good keyset. std::unique_ptr destination_stream(new std::stringstream()); auto writer_result = JsonKeysetWriter::New(std::move(destination_stream)); EXPECT_TRUE(writer_result.ok()) << writer_result.status(); } } TEST_F(JsonKeysetWriterTest, testWriteKeyset) { std::stringbuf buffer; std::unique_ptr destination_stream(new std::ostream(&buffer)); auto writer_result = JsonKeysetWriter::New(std::move(destination_stream)); ASSERT_TRUE(writer_result.ok()) << writer_result.status(); auto writer = std::move(writer_result.value()); auto status = writer->Write(keyset_); EXPECT_TRUE(status.ok()) << status; rapidjson::Document json_keyset(rapidjson::kObjectType); EXPECT_FALSE(json_keyset.Parse(buffer.str().c_str()).HasParseError()); EXPECT_TRUE(good_json_keyset_ == json_keyset); } TEST_F(JsonKeysetWriterTest, testWriteAndReadKeyset) { std::stringbuf buffer; std::unique_ptr destination_stream(new std::ostream(&buffer)); auto writer_result = JsonKeysetWriter::New(std::move(destination_stream)); ASSERT_TRUE(writer_result.ok()) << writer_result.status(); auto writer = std::move(writer_result.value()); auto status = writer->Write(keyset_); EXPECT_TRUE(status.ok()) << status; auto reader_result = JsonKeysetReader::New(buffer.str()); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); auto reader = std::move(reader_result.value()); auto read_result = reader->Read(); EXPECT_TRUE(read_result.ok()) << read_result.status(); auto keyset = std::move(read_result.value()); EXPECT_EQ(keyset_.SerializeAsString(), keyset->SerializeAsString()); } TEST_F(JsonKeysetWriterTest, testWriteEncryptedKeyset) { std::stringbuf buffer; std::unique_ptr destination_stream(new std::ostream(&buffer)); auto writer_result = JsonKeysetWriter::New(std::move(destination_stream)); ASSERT_TRUE(writer_result.ok()) << writer_result.status(); auto writer = std::move(writer_result.value()); auto status = writer->Write(encrypted_keyset_); EXPECT_TRUE(status.ok()) << status; rapidjson::Document json_encrypted_keyset(rapidjson::kObjectType); EXPECT_FALSE( json_encrypted_keyset.Parse(buffer.str().c_str()).HasParseError()) << "Parsing error at position " << static_cast(json_encrypted_keyset.GetErrorOffset()) << " of JSON string\n" << buffer.str() << "\n" << rapidjson::GetParseError_En(json_encrypted_keyset.GetParseError()); EXPECT_TRUE(good_json_encrypted_keyset_ == json_encrypted_keyset) << "Expected JSON:\n" << good_json_encrypted_keyset_string_ << "\n" << "Got JSON:\n" << buffer.str(); } TEST_F(JsonKeysetWriterTest, testWriteAndReadEncryptedKeyset) { std::stringbuf buffer; std::unique_ptr destination_stream(new std::ostream(&buffer)); auto writer_result = JsonKeysetWriter::New(std::move(destination_stream)); ASSERT_TRUE(writer_result.ok()) << writer_result.status(); auto writer = std::move(writer_result.value()); auto status = writer->Write(encrypted_keyset_); EXPECT_TRUE(status.ok()) << status; auto reader_result = JsonKeysetReader::New(buffer.str()); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); auto reader = std::move(reader_result.value()); auto read_result = reader->ReadEncrypted(); EXPECT_TRUE(read_result.ok()) << read_result.status(); auto encrypted_keyset = std::move(read_result.value()); EXPECT_EQ(encrypted_keyset_.SerializeAsString(), encrypted_keyset->SerializeAsString()); } TEST_F(JsonKeysetWriterTest, testDestinationStreamErrors) { std::stringbuf buffer; std::unique_ptr destination_stream(new std::ostream(&buffer)); destination_stream->setstate(std::ostream::badbit); auto writer_result = JsonKeysetWriter::New(std::move(destination_stream)); ASSERT_TRUE(writer_result.ok()) << writer_result.status(); auto writer = std::move(writer_result.value()); { // Write keyset. auto status = writer->Write(keyset_); EXPECT_FALSE(status.ok()) << status; EXPECT_EQ(absl::StatusCode::kUnknown, status.code()); } { // Write encrypted keyset. auto status = writer->Write(encrypted_keyset_); EXPECT_FALSE(status.ok()) << status; EXPECT_EQ(absl::StatusCode::kUnknown, status.code()); } } TEST_F(JsonKeysetWriterTest, WriteLargeKeyId) { Keyset keyset; AddTinkKey("type.googleapis.com/google.crypto.tink.AesGcmKey", 4123456789, gcm_key_, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(4123456789); // 4123456789 > 2^31 std::stringbuf buffer; std::unique_ptr destination_stream(new std::ostream(&buffer)); auto writer_result = JsonKeysetWriter::New(std::move(destination_stream)); ASSERT_THAT(writer_result, IsOk()); auto writer = std::move(writer_result.value()); ASSERT_THAT(writer->Write(keyset), IsOk()); EXPECT_THAT(buffer.str(), HasSubstr("\"primaryKeyId\": 4123456789")); EXPECT_THAT(buffer.str(), HasSubstr("\"keyId\": 4123456789")); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/core/key_access_test.cc ================================================ // Copyright 2021 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/key_access.h" #include "gtest/gtest.h" #include "tink/secret_key_access.h" namespace crypto { namespace tink { namespace { TEST(KeyAccessTest, PublicHasNoSecretAccess) { KeyAccess public_access_token = KeyAccess::PublicAccess(); EXPECT_FALSE(public_access_token.CanAccessSecret()); } TEST(KeyAccessTest, SecretKeyAccessHasSecretAccess) { KeyAccess secret_access_token = SecretKeyAccess::SecretAccess(); EXPECT_TRUE(secret_access_token.CanAccessSecret()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/core/key_manager.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/key_manager.h" #include #include "absl/memory/memory.h" #include "absl/strings/string_view.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // A key factory which always fails. class AlwaysFailingKeyFactory : public KeyFactory { public: AlwaysFailingKeyFactory() = delete; explicit AlwaysFailingKeyFactory(const crypto::tink::util::Status& status) : status_(status) {} crypto::tink::util::StatusOr> NewKey(const portable_proto::MessageLite& key_format) const override { return status_; } crypto::tink::util::StatusOr> NewKey(absl::string_view serialized_key_format) const override { return status_; } crypto::tink::util::StatusOr> NewKeyData(absl::string_view serialized_key_format) const override { return status_; } private: crypto::tink::util::Status status_; }; std::unique_ptr KeyFactory::AlwaysFailingFactory( const crypto::tink::util::Status& status) { return absl::make_unique(status); } } // namespace tink } // namespace crypto ================================================ FILE: cc/core/key_manager_impl.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_CORE_KEY_MANAGER_IMPL_H_ #define TINK_CORE_KEY_MANAGER_IMPL_H_ #include #include #include #include #include #include "absl/base/casts.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/input_stream.h" #include "tink/key_manager.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/secret_proto.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { // Template declaration of the class "KeyFactoryImpl" with a single template // argument. We first declare it, then later give two "partial template // specializations". This will imply that the KeyFactoryImpl can only be // instantiated with arguments of the form KeyTypeManager<...>. template class KeyFactoryImpl; // First partial template specialization for KeyFactoryImpl: the given // KeyTypeManager is of the form KeyTypeManager>. template class KeyFactoryImpl< KeyTypeManager>> : public KeyFactory { public: explicit KeyFactoryImpl(KeyTypeManager>* key_type_manager) : key_type_manager_(key_type_manager) {} crypto::tink::util::StatusOr> NewKey(const portable_proto::MessageLite& key_format) const override { if (key_format.GetTypeName() != KeyFormatProto().GetTypeName()) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Key format proto '", key_format.GetTypeName(), "' is not supported by this manager.")); } auto validation = key_type_manager_->ValidateKeyFormat( static_cast(key_format)); if (!validation.ok()) { return validation; } crypto::tink::util::StatusOr new_key_result = key_type_manager_->CreateKey( static_cast(key_format)); if (!new_key_result.ok()) return new_key_result.status(); return absl::implicit_cast>( absl::make_unique(std::move(new_key_result.value()))); } crypto::tink::util::StatusOr> NewKey(absl::string_view serialized_key_format) const override { KeyFormatProto key_format; if (!key_format.ParseFromString(serialized_key_format)) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Could not parse the passed string as proto '", KeyFormatProto().GetTypeName(), "'.")); } auto validation = key_type_manager_->ValidateKeyFormat(key_format); if (!validation.ok()) { return validation; } return NewKey(static_cast(key_format)); } crypto::tink::util::StatusOr> NewKeyData(absl::string_view serialized_key_format) const override { auto new_key_result = NewKey(serialized_key_format); if (!new_key_result.ok()) return new_key_result.status(); auto new_key = static_cast(*(new_key_result.value())); auto key_data = absl::make_unique(); key_data->set_type_url( absl::StrCat(kTypeGoogleapisCom, KeyProto().GetTypeName())); key_data->set_value(new_key.SerializeAsString()); key_data->set_key_material_type(key_type_manager_->key_material_type()); return std::move(key_data); } private: KeyTypeManager>* key_type_manager_; }; // Second partial template specialization for KeyFactoryImpl: the given // KeyTypeManager is of the form KeyTypeManager>. template class KeyFactoryImpl>> : public KeyFactory { public: // We don't need the KeyTypeManager, but this is called from a template, // so the easiest way to ignore the argument is to provide a constructor which // ignores the argument. explicit KeyFactoryImpl( KeyTypeManager>* key_type_manager) {} crypto::tink::util::StatusOr> NewKey(const portable_proto::MessageLite& key_format) const override { return util::Status( absl::StatusCode::kUnimplemented, "Creating new keys is not supported for this key manager."); } crypto::tink::util::StatusOr> NewKey(absl::string_view serialized_key_format) const override { return util::Status( absl::StatusCode::kUnimplemented, "Creating new keys is not supported for this key manager."); } crypto::tink::util::StatusOr> NewKeyData(absl::string_view serialized_key_format) const override { return util::Status( absl::StatusCode::kUnimplemented, "Creating new keys is not supported for this key manager."); } }; // Template declaration of the class "KeyManagerImpl" with two template // arguments. There is only one specialization which is defined, namely when // the KeyTypeManager argument is of the form KeyTypeManager>. We don't provide a // specialization for the case KeyFormatProto = void, so the compiler will pick // this instantiation in this case. template class KeyManagerImpl; // The first template argument to the KeyManagerImpl is the primitive for which // we should generate a KeyManager. The second is the KeyTypeManager, which // takes itself template arguments. The list of the Primitives there must // contain the first Primitive argument (otherwise there will be failures at // runtime). template class KeyManagerImpl< Primitive, KeyTypeManager>> : public KeyManager { public: explicit KeyManagerImpl(KeyTypeManager>* key_type_manager) : key_type_manager_(key_type_manager), key_factory_( absl::make_unique>>>( key_type_manager_)) {} // Constructs an instance of Primitive for the given 'key_data'. crypto::tink::util::StatusOr> GetPrimitive( const google::crypto::tink::KeyData& key_data) const override { if (!this->DoesSupport(key_data.type_url())) { return ToStatusF(absl::StatusCode::kInvalidArgument, "Key type '%s' is not supported by this manager.", key_data.type_url()); } crypto::tink::util::SecretProto key_proto; if (!key_proto->ParseFromString(key_data.value())) { return ToStatusF(absl::StatusCode::kInvalidArgument, "Could not parse key_data.value as key type '%s'.", key_data.type_url()); } auto validation = key_type_manager_->ValidateKey(*key_proto); if (!validation.ok()) { return validation; } return key_type_manager_->template GetPrimitive(*key_proto); } crypto::tink::util::StatusOr> GetPrimitive( const portable_proto::MessageLite& key) const override { std::string key_type = absl::StrCat(kTypeGoogleapisCom, key.GetTypeName()); if (!this->DoesSupport(key_type)) { return ToStatusF(absl::StatusCode::kInvalidArgument, "Key type '%s' is not supported by this manager.", key_type); } const KeyProto& key_proto = static_cast(key); auto validation = key_type_manager_->ValidateKey(key_proto); if (!validation.ok()) { return validation; } return key_type_manager_->template GetPrimitive(key_proto); } uint32_t get_version() const override { return key_type_manager_->get_version(); } const std::string& get_key_type() const override { return key_type_manager_->get_key_type(); } const KeyFactory& get_key_factory() const override { return *key_factory_; } private: KeyTypeManager>* key_type_manager_; std::unique_ptr key_factory_; }; // Helper function to create a KeyManager from a KeyTypeManager. // Using this, all template arguments except the first one can be infered. // Example: // std::unique_ptr> km = // MakeKeyManager(my_key_type_manager.get()); template std::unique_ptr> MakeKeyManager( KeyTypeManager>* key_type_manager) { return absl::make_unique< KeyManagerImpl>>>( key_type_manager); } // Creates a function which can derive a key, using the given KeyTypeManager. // Note that the returned function stores a pointer to the given KeyTypeManager, // which must remain valid for the lifetime of the function. template std::function( absl::string_view, InputStream*)> CreateDeriverFunctionFor( KeyTypeManager>* key_type_manager) { return [key_type_manager](absl::string_view serialized_key_format, InputStream* randomness) -> crypto::tink::util::StatusOr { KeyFormatProto key_format; if (!key_format.ParseFromString(serialized_key_format)) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Could not parse the passed string as proto '", KeyFormatProto().GetTypeName(), "'.")); } auto status = key_type_manager->ValidateKeyFormat(key_format); if (!status.ok()) { return status; } auto key_proto_or = key_type_manager->DeriveKey(key_format, randomness); if (!key_proto_or.ok()) { return key_proto_or.status(); } status = key_type_manager->ValidateKey(key_proto_or.value()); if (!status.ok()) { return status; } google::crypto::tink::KeyData result; result.set_type_url(key_type_manager->get_key_type()); result.set_value(key_proto_or.value().SerializeAsString()); result.set_key_material_type(key_type_manager->key_material_type()); return std::move(result); }; } // Template specialization of CreateDeriverFor in case the KeyTypeManager has // KeyFormatProto = void, and hence there is no key derivation. template std::function( absl::string_view, InputStream*)> CreateDeriverFunctionFor( KeyTypeManager>* key_type_manager) { return [key_type_manager](absl::string_view serialized_key_format, InputStream* randomness) -> crypto::tink::util::StatusOr { return crypto::tink::util::Status( absl::StatusCode::kUnimplemented, absl::StrCat("Registered KeyManager for type '", key_type_manager->get_key_type(), "' does not support key generation.")); }; } } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_CORE_KEY_MANAGER_IMPL_H_ ================================================ FILE: cc/core/key_manager_impl_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/core/key_manager_impl.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/aead.h" #include "tink/subtle/aes_gcm_boringssl.h" #include "tink/subtle/random.h" #include "tink/util/input_stream_util.h" #include "tink/util/istream_input_stream.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "tink/util/validation.h" #include "proto/aes_gcm.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::AesGcmKey; using ::google::crypto::tink::AesGcmKeyFormat; using ::google::crypto::tink::KeyData; using ::testing::_; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::Return; using ::testing::SizeIs; // A class for testing. We will construct objects from an aead key, so that we // can check that a keymanager can handle multiple primitives. It is really // insecure, as it does nothing except provide access to the key. class AeadVariant { public: explicit AeadVariant(std::string s) : s_(s) {} std::string get() { return s_; } private: std::string s_; }; class ExampleKeyTypeManager : public KeyTypeManager> { public: class AeadFactory : public PrimitiveFactory { public: crypto::tink::util::StatusOr> Create( const AesGcmKey& key) const override { // Ignore the key and returned one with a fixed size for this test. return {subtle::AesGcmBoringSsl::New( util::SecretDataFromStringView(key.key_value()))}; } }; class AeadVariantFactory : public PrimitiveFactory { public: crypto::tink::util::StatusOr> Create( const AesGcmKey& key) const override { return absl::make_unique(key.key_value()); } }; ExampleKeyTypeManager() : KeyTypeManager(absl::make_unique(), absl::make_unique()) {} google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::SYMMETRIC; } MOCK_METHOD(uint32_t, get_version, (), (const, override)); // We mock out ValidateKey, ValidateKeyFormat, and DeriveKey so that we can // easily test proper behavior in case they return an error. MOCK_METHOD(crypto::tink::util::Status, ValidateKey, (const AesGcmKey& key), (const, override)); MOCK_METHOD(crypto::tink::util::Status, ValidateKeyFormat, (const AesGcmKeyFormat& key), (const, override)); MOCK_METHOD(crypto::tink::util::StatusOr, DeriveKey, (const KeyFormatProto& key_format, InputStream* input_stream), (const, override)); const std::string& get_key_type() const override { return kKeyType; } crypto::tink::util::StatusOr CreateKey( const AesGcmKeyFormat& key_format) const override { AesGcmKey result; result.set_key_value(subtle::Random::GetRandomBytes(key_format.key_size())); return result; } private: const std::string kKeyType = "type.googleapis.com/google.crypto.tink.AesGcmKey"; }; TEST(KeyManagerImplTest, FactoryNewKeyFromMessage) { ExampleKeyTypeManager internal_km; std::unique_ptr> key_manager = MakeKeyManager(&internal_km); AesGcmKeyFormat key_format; key_format.set_key_size(16); auto key = key_manager->get_key_factory().NewKey(key_format).value(); EXPECT_THAT(dynamic_cast(*key).key_value(), SizeIs(16)); } TEST(KeyManagerImplTest, FactoryNewKeyFromStringView) { ExampleKeyTypeManager internal_km; std::unique_ptr> key_manager = MakeKeyManager(&internal_km); AesGcmKeyFormat key_format; key_format.set_key_size(16); auto key = key_manager->get_key_factory() .NewKey(key_format.SerializeAsString()) .value(); EXPECT_THAT(dynamic_cast(*key).key_value(), SizeIs(16)); } TEST(KeyManagerImplTest, FactoryNewKeyFromKeyData) { ExampleKeyTypeManager internal_km; std::unique_ptr> key_manager = MakeKeyManager(&internal_km); AesGcmKeyFormat key_format; key_format.set_key_size(16); auto key_data = *key_manager->get_key_factory() .NewKeyData(key_format.SerializeAsString()) .value(); AesGcmKey key; key.ParseFromString(key_data.value()); EXPECT_THAT(key.key_value(), SizeIs(16)); } TEST(KeyManagerImplTest, FactoryNewKeyFromMessageCallsValidate) { ExampleKeyTypeManager internal_km; std::unique_ptr> key_manager = MakeKeyManager(&internal_km); AesGcmKeyFormat key_format; key_format.set_key_size(16); EXPECT_CALL(internal_km, ValidateKeyFormat(_)) .WillOnce(Return(util::Status(absl::StatusCode::kOutOfRange, "FactoryNewKeyFromMessageCallsValidate"))); EXPECT_THAT(key_manager->get_key_factory().NewKey(key_format).status(), StatusIs(absl::StatusCode::kOutOfRange, HasSubstr("FactoryNewKeyFromMessageCallsValidate"))); } TEST(KeyManagerImplTest, FactoryNewKeyFromStringViewCallsValidate) { ExampleKeyTypeManager internal_km; std::unique_ptr> key_manager = MakeKeyManager(&internal_km); AesGcmKeyFormat key_format; key_format.set_key_size(16); EXPECT_CALL(internal_km, ValidateKeyFormat(_)) .WillOnce( Return(util::Status(absl::StatusCode::kOutOfRange, "FactoryNewKeyFromStringViewCallsValidate"))); EXPECT_THAT(key_manager->get_key_factory() .NewKey(key_format.SerializeAsString()) .status(), StatusIs(absl::StatusCode::kOutOfRange, HasSubstr("FactoryNewKeyFromStringViewCallsValidate"))); } TEST(KeyManagerImplTest, FactoryNewKeyFromKeyDataCallsValidate) { ExampleKeyTypeManager internal_km; std::unique_ptr> key_manager = MakeKeyManager(&internal_km); AesGcmKeyFormat key_format; key_format.set_key_size(16); EXPECT_CALL(internal_km, ValidateKeyFormat(_)) .WillOnce(Return(util::Status(absl::StatusCode::kOutOfRange, "FactoryNewKeyFromKeyDataCallsValidate"))); EXPECT_THAT(key_manager->get_key_factory() .NewKeyData(key_format.SerializeAsString()) .status(), StatusIs(absl::StatusCode::kOutOfRange, HasSubstr("FactoryNewKeyFromKeyDataCallsValidate"))); } TEST(CreateDeriverFunctionForTest, KeyMaterialAndKeyType) { ExampleKeyTypeManager internal_km; EXPECT_CALL(internal_km, DeriveKey(_, _)). WillOnce(Return(AesGcmKey())); auto deriver = CreateDeriverFunctionFor(&internal_km); AesGcmKeyFormat key_format; key_format.set_key_size(16); auto key_or = deriver(key_format.SerializeAsString(), nullptr); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().key_material_type(), Eq(ExampleKeyTypeManager().key_material_type())); EXPECT_THAT(key_or.value().type_url(), Eq(ExampleKeyTypeManager().get_key_type())); } TEST(CreateDeriverFunctionForTest, UseParametersAndReturnValue) { crypto::tink::util::IstreamInputStream input_stream{ absl::make_unique("0123456789abcdefghijklmnop")}; ExampleKeyTypeManager internal_km; AesGcmKeyFormat key_format; key_format.set_key_size(9); EXPECT_CALL(internal_km, DeriveKey(_, _)) .WillOnce([](const AesGcmKeyFormat& format, InputStream* randomness) -> crypto::tink::util::StatusOr { auto bytes_or = ReadBytesFromStream(format.key_size(), randomness); if (!bytes_or.ok()) { return bytes_or.status(); } AesGcmKey key; key.set_key_value(bytes_or.value()); return key; }); auto deriver = CreateDeriverFunctionFor(&internal_km); auto key_or = deriver(key_format.SerializeAsString(), &input_stream); AesGcmKey result; result.ParseFromString(key_or.value().value()); // Length 9 prefix of the above string. EXPECT_THAT(result.key_value(), Eq("012345678")); } TEST(CreateDeriverFunctionForTest, ValidateKeyFormatIsCalled) { ExampleKeyTypeManager internal_km; EXPECT_CALL(internal_km, ValidateKeyFormat(_)) .WillOnce(Return(util::Status( absl::StatusCode::kOutOfRange, "CreateDeriverFunctionForTest ValidateKeyFormatIsCalled"))); auto deriver = CreateDeriverFunctionFor(&internal_km); EXPECT_THAT( deriver(AesGcmKeyFormat().SerializeAsString(), nullptr).status(), StatusIs( absl::StatusCode::kOutOfRange, HasSubstr("CreateDeriverFunctionForTest ValidateKeyFormatIsCalled"))); } TEST(CreateDeriverFunctionForTest, ValidateKeyIsCalled) { ExampleKeyTypeManager internal_km; EXPECT_CALL(internal_km, DeriveKey(_, _)). WillOnce(Return(AesGcmKey())); EXPECT_CALL(internal_km, ValidateKey(_)) .WillOnce(Return( util::Status(absl::StatusCode::kOutOfRange, "CreateDeriverFunctionForTest ValidateKeyIsCalled"))); auto deriver = CreateDeriverFunctionFor(&internal_km); EXPECT_THAT( deriver(AesGcmKeyFormat().SerializeAsString(), nullptr).status(), StatusIs( absl::StatusCode::kOutOfRange, HasSubstr("CreateDeriverFunctionForTest ValidateKeyIsCalled"))); } TEST(KeyManagerImplTest, GetPrimitiveAead) { ExampleKeyTypeManager internal_km; std::unique_ptr> key_manager = MakeKeyManager(&internal_km); AesGcmKeyFormat key_format; key_format.set_key_size(16); auto key_data = *key_manager->get_key_factory() .NewKeyData(key_format.SerializeAsString()) .value(); auto aead = key_manager->GetPrimitive(key_data).value(); std::string encryption = aead->Encrypt("Hi", "aad").value(); std::string decryption = aead->Decrypt(encryption, "aad").value(); EXPECT_THAT(decryption, Eq("Hi")); } TEST(KeyManagerImplTest, GetPrimitiveAeadVariant) { ExampleKeyTypeManager internal_km; std::unique_ptr> key_manager = MakeKeyManager(&internal_km); AesGcmKeyFormat key_format; key_format.set_key_size(16); auto key_data = *key_manager->get_key_factory() .NewKeyData(key_format.SerializeAsString()) .value(); AesGcmKey key; key.ParseFromString(key_data.value()); auto aead_variant = key_manager->GetPrimitive(key_data).value(); EXPECT_THAT(aead_variant->get(), Eq(key.key_value())); } TEST(KeyManagerImplTest, GetPrimitiveFromKey) { ExampleKeyTypeManager internal_km; std::unique_ptr> key_manager = MakeKeyManager(&internal_km); AesGcmKeyFormat key_format; key_format.set_key_size(16); auto key = key_manager->get_key_factory() .NewKey(key_format.SerializeAsString()) .value(); auto aead = key_manager->GetPrimitive(*key).value(); std::string encryption = aead->Encrypt("Hi", "aad").value(); std::string decryption = aead->Decrypt(encryption, "aad").value(); EXPECT_THAT(decryption, Eq("Hi")); } TEST(KeyManagerImplTest, GetKeyType) { ExampleKeyTypeManager internal_km; std::unique_ptr> key_manager = MakeKeyManager(&internal_km); EXPECT_THAT(key_manager->get_key_type(), Eq(internal_km.get_key_type())); } TEST(KeyManagerImplTest, GetVersion) { ExampleKeyTypeManager internal_km; std::unique_ptr> key_manager = MakeKeyManager(&internal_km); EXPECT_CALL(internal_km, get_version()).WillOnce(Return(121351)); EXPECT_THAT(121351, Eq(internal_km.get_version())); } TEST(KeyManagerImplTest, DoesSupport) { ExampleKeyTypeManager internal_km; std::unique_ptr> key_manager = MakeKeyManager(&internal_km); EXPECT_TRUE(key_manager->DoesSupport(internal_km.get_key_type())); // Check with first and last letter removed. EXPECT_FALSE(key_manager->DoesSupport( "type.googleapis.com/google.crypto.tink.AesGcmKe")); EXPECT_FALSE(key_manager->DoesSupport( "ype.googleapis.com/google.crypto.tink.AesGcmKey")); } TEST(KeyManagerImplTest, GetPrimitiveCallsValidate) { ExampleKeyTypeManager internal_km; std::unique_ptr> key_manager = MakeKeyManager(&internal_km); AesGcmKeyFormat key_format; key_format.set_key_size(16); auto key_data = *key_manager->get_key_factory() .NewKeyData(key_format.SerializeAsString()) .value(); AesGcmKey key; key.ParseFromString(key_data.value()); EXPECT_CALL(internal_km, ValidateKey(_)) .WillOnce(Return(util::Status(absl::StatusCode::kOutOfRange, "GetPrimitiveCallsValidate"))); EXPECT_THAT(key_manager->GetPrimitive(key_data).status(), StatusIs(absl::StatusCode::kOutOfRange, HasSubstr("GetPrimitiveCallsValidate"))); } TEST(KeyManagerImplTest, GetPrimitiveFromKeyCallsValidate) { ExampleKeyTypeManager internal_km; std::unique_ptr> key_manager = MakeKeyManager(&internal_km); AesGcmKeyFormat key_format; key_format.set_key_size(16); auto key_data = *key_manager->get_key_factory() .NewKeyData(key_format.SerializeAsString()) .value(); AesGcmKey key; key.ParseFromString(key_data.value()); EXPECT_CALL(internal_km, ValidateKey(_)) .WillOnce(Return(util::Status(absl::StatusCode::kOutOfRange, "GetPrimitiveFromKeyCallsValidate"))); EXPECT_THAT(key_manager->GetPrimitive(key).status(), StatusIs(absl::StatusCode::kOutOfRange, HasSubstr("GetPrimitiveFromKeyCallsValidate"))); } // If we create a KeyManager for a not supported class, creating the key manager // succeeds, but "GetPrimitive" will fail. Since MakeKeyManager is only supposed // to be used internally, we are not doing extra work to make this a compile // time error. class NotSupported {}; TEST(KeyManagerImplTest, GetPrimitiveFails) { ExampleKeyTypeManager internal_km; std::unique_ptr> key_manager = MakeKeyManager(&internal_km); AesGcmKeyFormat key_format; key_format.set_key_size(16); auto key_data = *key_manager->get_key_factory() .NewKeyData(key_format.SerializeAsString()) .value(); EXPECT_THAT(key_manager->GetPrimitive(key_data).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("No PrimitiveFactory was registered"))); } // Next, we test some of the methods with a KeyTypeManager which has no // factory. class ExampleKeyTypeManagerWithoutFactory : public KeyTypeManager> { public: class AeadFactory : public PrimitiveFactory { public: crypto::tink::util::StatusOr> Create( const AesGcmKey& key) const override { // Ignore the key and returned one with a fixed size for this test. return {subtle::AesGcmBoringSsl::New( util::SecretDataFromStringView(key.key_value()))}; } }; class AeadVariantFactory : public PrimitiveFactory { public: crypto::tink::util::StatusOr> Create( const AesGcmKey& key) const override { return absl::make_unique(key.key_value()); } }; ExampleKeyTypeManagerWithoutFactory() : KeyTypeManager(absl::make_unique(), absl::make_unique()) {} google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::SYMMETRIC; } uint32_t get_version() const override { return kVersion; } const std::string& get_key_type() const override { return key_type_; } util::Status ValidateKey(const AesGcmKey& key) const override { util::Status status = ValidateVersion(key.version(), kVersion); if (!status.ok()) return status; return ValidateAesKeySize(key.key_value().size()); } private: static constexpr int kVersion = 0; const std::string key_type_ = "type.googleapis.com/google.crypto.tink.AesGcmKey"; }; TEST(KeyManagerImplTest, GetPrimitiveWithoutFactoryAead) { ExampleKeyTypeManagerWithoutFactory internal_km; std::unique_ptr> key_manager = MakeKeyManager(&internal_km); AesGcmKeyFormat key_format; key_format.set_key_size(16); KeyData key_data = test::AsKeyData(ExampleKeyTypeManager().CreateKey(key_format).value(), KeyData::SYMMETRIC); auto aead = key_manager->GetPrimitive(key_data).value(); std::string encryption = aead->Encrypt("Hi", "aad").value(); std::string decryption = aead->Decrypt(encryption, "aad").value(); EXPECT_THAT(decryption, Eq("Hi")); } TEST(KeyManagerImplTest, NonexistentFactoryNewKeyFromMessage) { ExampleKeyTypeManagerWithoutFactory internal_km; std::unique_ptr> key_manager = MakeKeyManager(&internal_km); AesGcmKeyFormat key_format; key_format.set_key_size(16); EXPECT_THAT(key_manager->get_key_factory().NewKey(key_format).status(), StatusIs(absl::StatusCode::kUnimplemented)); } TEST(KeyManagerImplTest, NonexistentFactoryNewKeyFromStringView) { ExampleKeyTypeManagerWithoutFactory internal_km; std::unique_ptr> key_manager = MakeKeyManager(&internal_km); AesGcmKeyFormat key_format; key_format.set_key_size(16); EXPECT_THAT(key_manager->get_key_factory() .NewKey(key_format.SerializeAsString()) .status(), StatusIs(absl::StatusCode::kUnimplemented)); } TEST(KeyManagerImplTest, NonexistentFactoryNewKeyFromKeyData) { ExampleKeyTypeManagerWithoutFactory internal_km; std::unique_ptr> key_manager = MakeKeyManager(&internal_km); AesGcmKeyFormat key_format; key_format.set_key_size(16); EXPECT_THAT(key_manager->get_key_factory() .NewKeyData(key_format.SerializeAsString()) .status(), StatusIs(absl::StatusCode::kUnimplemented)); } TEST(CreateDeriverFunctionForTest, DeriverWithoutFactory) { ExampleKeyTypeManagerWithoutFactory internal_km; auto deriver = CreateDeriverFunctionFor(&internal_km); EXPECT_THAT(deriver("", nullptr).status(), StatusIs(absl::StatusCode::kUnimplemented)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/core/key_manager_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/key_manager.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/util/status.h" #include "tink/util/test_matchers.h" #include "proto/empty.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::StatusIs; TEST(AlwaysFailingFactoryTest, NewKeyFromProtoLite) { std::unique_ptr factory = KeyFactory::AlwaysFailingFactory( util::Status(absl::StatusCode::kAlreadyExists, "")); google::crypto::tink::Empty empty_proto; EXPECT_THAT(factory->NewKey(empty_proto).status(), StatusIs(absl::StatusCode::kAlreadyExists)); } TEST(AlwaysFailingFactoryTest, NewKeyFromStringView) { std::unique_ptr factory = KeyFactory::AlwaysFailingFactory( util::Status(absl::StatusCode::kAlreadyExists, "")); EXPECT_THAT(factory->NewKey("").status(), StatusIs(absl::StatusCode::kAlreadyExists)); } TEST(AlwaysFailingFactoryTest, NewKeyData) { std::unique_ptr factory = KeyFactory::AlwaysFailingFactory( util::Status(absl::StatusCode::kAlreadyExists, "")); EXPECT_THAT(factory->NewKeyData("").status(), StatusIs(absl::StatusCode::kAlreadyExists)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/core/key_type_manager.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_CORE_KEY_TYPE_MANAGER_H_ #define TINK_CORE_KEY_TYPE_MANAGER_H_ #include #include #include #include #include #include #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/core/template_util.h" #include "tink/input_stream.h" #include "tink/internal/fips_utils.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { // InternalKeyFactory should not be used directly: it is an implementation // detail. The internal key factory provides the functions which are required // if a KeyTypeManager can create new keys: ValidateKeyFormat and // CreateKey. The special case where KeyFormatProto = void implies that the // functions do not exist. template class InternalKeyFactory { public: virtual ~InternalKeyFactory() = default; // Validates a key format proto. KeyFormatProtos // on which this function returns a non-ok status will not be passed to // CreateKey or DeriveKey. virtual crypto::tink::util::Status ValidateKeyFormat( const KeyFormatProto& key_format) const = 0; // Creates a new key. This is expected to be randomized. virtual crypto::tink::util::StatusOr CreateKey( const KeyFormatProto& key_format) const = 0; // Creates a new key. Only needs to be overridden if it should be possible to // derive keys of this type. This must be deterministic. Furthermore, in order // to support long term usability of old keys, the KeyFormatProto should be // versioned. virtual crypto::tink::util::StatusOr DeriveKey( const KeyFormatProto& key_format, InputStream* input_stream) const { return crypto::tink::util::Status( absl::StatusCode::kUnimplemented, "Deriving key not implemented for this key type."); } }; // Template specialization for when KeyFormatProto = void. The compiler will // pick the most specialized template when compiling. template class InternalKeyFactory { public: virtual ~InternalKeyFactory() = default; }; } // namespace internal // We declare a KeyTypeManager without giving an implementation. We then // provide a specialization only for the case where PrimitivesList is a // List with multiple interfaces primitives. This allows to ensure // that such is always the case. template class KeyTypeManager; // A KeyTypeManager manages a single key proto. This includes // * parsing and validating keys // * parsing and validating key formats (in case generating keys is allowed). // * creating primitives. // To implement, one should subclass KeyTypeManager with the corresponding // KeyProto as a template parameter; KeyFormatProto should be void in case // the key manager cannot produce keys and a protobuf otherwise. // // The constructor should take unique pointers to primitive factories. // // KeyTypeManager uses templates for KeyProto, KeyFormatProto and a list of // Primitives which have to be provided as a List. template class KeyTypeManager> : public internal::InternalKeyFactory { public: static_assert( !crypto::tink::internal::HasDuplicates::value, "List or primitives contains a duplicate, which is not allowed."); // The types used in this key type manager; these can be useful when writing // templated code. using KeyProto = KeyProtoParam; using KeyFormatProto = KeyFormatProtoParam; using PrimitiveList = List; // A PrimitiveFactory knows how to create instances of the // Primitive. template class PrimitiveFactory { public: virtual ~PrimitiveFactory() = default; virtual crypto::tink::util::StatusOr> Create( const KeyProto& key) const = 0; }; // Creates a new KeyTypeManager. The parameter(s) primitives must be some // number of unique_ptr> types. explicit KeyTypeManager( std::unique_ptr>... primitives) : primitive_factories_{std::move(primitives)...} {} // Returns the type_url identifying the key type handled by this manager. virtual const std::string& get_key_type() const = 0; // Returns the version of this key manager. virtual uint32_t get_version() const = 0; // Returns the key material type for this key type. virtual google::crypto::tink::KeyData::KeyMaterialType key_material_type() const = 0; // Validates the key. Returns util::OkStatus() if the key is valid, // and an invalid argument error otherwise. virtual util::Status ValidateKey(const KeyProto& key) const = 0; // Creates a new primitive using one of the primitive factories passed in at // construction time. template util::StatusOr> GetPrimitive( const KeyProto& key) const { return GetPrimitiveImpl(key); } // Returns the FIPS compatibility of this KeyTypeManager. virtual internal::FipsCompatibility FipsStatus() const { return internal::FipsCompatibility::kNotFips; } private: // TODO(C++17) replace with `constexpr if` after migration template typename std::enable_if< !internal::OccursInTuple>::value, util::StatusOr>>::type GetPrimitiveImpl(const KeyProto& key) const { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("No PrimitiveFactory was registered for type ", typeid(Primitive).name())); } template typename std::enable_if< internal::OccursInTuple>::value, util::StatusOr>>::type GetPrimitiveImpl(const KeyProto& key) const { // TODO(C++14) replace with std::get after migration constexpr size_t index = internal::IndexOf>::value; return std::get(primitive_factories_)->Create(key); } std::tuple>...> primitive_factories_; }; } // namespace tink } // namespace crypto #endif // TINK_CORE_KEY_TYPE_MANAGER_H_ ================================================ FILE: cc/core/key_type_manager_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/core/key_type_manager.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/aead.h" #include "tink/core/template_util.h" #include "tink/subtle/aes_gcm_boringssl.h" #include "tink/subtle/random.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/validation.h" #include "proto/aes_gcm.pb.h" namespace crypto { namespace tink { namespace { using ::google::crypto::tink::AesGcmKey; using ::google::crypto::tink::AesGcmKeyFormat; using ::testing::Eq; // A class for testing. We will construct objects from an aead key, so that we // can check that a keymanager can handle multiple primitives. It is really // insecure, as it does nothing except provide access to the key. class AeadVariant { public: explicit AeadVariant(std::string s) : s_(s) {} std::string get() { return s_; } private: std::string s_; }; class ExampleKeyTypeManager : public KeyTypeManager> { public: class AeadFactory : public PrimitiveFactory { public: crypto::tink::util::StatusOr> Create( const AesGcmKey& key) const override { // Ignore the key and returned one with a fixed size for this test. return {subtle::AesGcmBoringSsl::New( util::SecretDataFromStringView(key.key_value()))}; } }; class AeadVariantFactory : public PrimitiveFactory { public: crypto::tink::util::StatusOr> Create( const AesGcmKey& key) const override { return absl::make_unique(key.key_value()); } }; ExampleKeyTypeManager() : KeyTypeManager(absl::make_unique(), absl::make_unique()) {} google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::SYMMETRIC; } uint32_t get_version() const override { return kVersion; } const std::string& get_key_type() const override { return kKeyType; } crypto::tink::util::Status ValidateKey(const AesGcmKey& key) const override { return util::OkStatus(); } crypto::tink::util::Status ValidateKeyFormat( const AesGcmKeyFormat& key_format) const override { return util::OkStatus(); } crypto::tink::util::StatusOr CreateKey( const AesGcmKeyFormat& key_format) const override { AesGcmKey result; result.set_key_value(subtle::Random::GetRandomBytes(key_format.key_size())); return result; } private: static constexpr int kVersion = 0; const std::string kKeyType = "myKeyType"; }; TEST(KeyManagerTest, CreateAead) { AesGcmKeyFormat key_format; key_format.set_key_size(16); AesGcmKey key = ExampleKeyTypeManager().CreateKey(key_format).value(); std::unique_ptr aead = ExampleKeyTypeManager().GetPrimitive(key).value(); std::string encryption = aead->Encrypt("Hi", "aad").value(); std::string decryption = aead->Decrypt(encryption, "aad").value(); EXPECT_THAT(decryption, Eq("Hi")); } TEST(KeyManagerTest, CreateAeadVariant) { AesGcmKeyFormat key_format; key_format.set_key_size(16); AesGcmKey key = ExampleKeyTypeManager().CreateKey(key_format).value(); std::unique_ptr aead_variant = ExampleKeyTypeManager().GetPrimitive(key).value(); EXPECT_THAT(aead_variant->get(), Eq(key.key_value())); } class NotRegistered {}; TEST(KeyManagerTest, CreateFails) { auto failing = ExampleKeyTypeManager().GetPrimitive(AesGcmKey()); EXPECT_THAT(failing.status(), test::StatusIs(absl::StatusCode::kInvalidArgument)); } class ExampleKeyTypeManagerWithoutFactory : public KeyTypeManager> { public: class AeadFactory : public PrimitiveFactory { public: crypto::tink::util::StatusOr> Create( const AesGcmKey& key) const override { // Ignore the key and returned one with a fixed size for this test. return {subtle::AesGcmBoringSsl::New( util::SecretDataFromStringView(key.key_value()))}; } }; class AeadVariantFactory : public PrimitiveFactory { public: crypto::tink::util::StatusOr> Create( const AesGcmKey& key) const override { return absl::make_unique(key.key_value()); } }; ExampleKeyTypeManagerWithoutFactory() : KeyTypeManager(absl::make_unique(), absl::make_unique()) {} google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::SYMMETRIC; } uint32_t get_version() const override { return kVersion; } const std::string& get_key_type() const override { return key_type_; } util::Status ValidateKey(const AesGcmKey& key) const override { util::Status status = ValidateVersion(key.version(), kVersion); if (!status.ok()) return status; return ValidateAesKeySize(key.key_value().size()); } private: static constexpr int kVersion = 0; const std::string key_type_ = "bla"; }; TEST(KeyManagerWithoutFactoryTest, CreateAead) { AesGcmKeyFormat key_format; key_format.set_key_size(16); AesGcmKey key = ExampleKeyTypeManager().CreateKey(key_format).value(); std::unique_ptr aead = ExampleKeyTypeManagerWithoutFactory().GetPrimitive(key).value(); std::string encryption = aead->Encrypt("Hi", "aad").value(); std::string decryption = aead->Decrypt(encryption, "aad").value(); EXPECT_THAT(decryption, Eq("Hi")); } TEST(KeyManagerWithoutFactoryTest, CreateAeadVariant) { AesGcmKeyFormat key_format; key_format.set_key_size(16); AesGcmKey key = ExampleKeyTypeManager().CreateKey(key_format).value(); std::unique_ptr aead_variant = ExampleKeyTypeManager().GetPrimitive(key).value(); EXPECT_THAT(aead_variant->get(), Eq(key.key_value())); } TEST(KeyManagerWithoutFactoryTest, CreateFails) { auto failing = ExampleKeyTypeManagerWithoutFactory().GetPrimitive( AesGcmKey()); EXPECT_THAT(failing.status(), test::StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/core/keyset_handle.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/keyset_handle.h" #include #include #include #include #include #include "absl/container/flat_hash_map.h" #include "absl/log/check.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/aead.h" #include "tink/config/global_registry.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/key_gen_configuration_impl.h" #include "tink/internal/key_info.h" #include "tink/internal/key_status_util.h" #include "tink/internal/key_type_info_store.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/util.h" #include "tink/key.h" #include "tink/key_gen_configuration.h" #include "tink/key_manager.h" #include "tink/key_status.h" #include "tink/keyset_reader.h" #include "tink/keyset_writer.h" #include "tink/registry.h" #include "tink/restricted_data.h" #include "tink/util/errors.h" #include "tink/util/keyset_util.h" #include "tink/util/secret_data.h" #include "tink/util/secret_proto.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" using google::crypto::tink::EncryptedKeyset; using google::crypto::tink::KeyData; using google::crypto::tink::Keyset; using google::crypto::tink::KeysetInfo; using google::crypto::tink::KeyStatusType; using google::crypto::tink::KeyTemplate; using google::crypto::tink::OutputPrefixType; namespace crypto { namespace tink { namespace { util::StatusOr> Encrypt( const Keyset& keyset, const Aead& master_key_aead, absl::string_view associated_data) { auto encrypt_result = master_key_aead.Encrypt(keyset.SerializeAsString(), associated_data); if (!encrypt_result.ok()) return encrypt_result.status(); auto enc_keyset = absl::make_unique(); enc_keyset->set_encrypted_keyset(encrypt_result.value()); return std::move(enc_keyset); } util::StatusOr> Decrypt( const EncryptedKeyset& enc_keyset, const Aead& master_key_aead, absl::string_view associated_data) { auto decrypt_result = master_key_aead.Decrypt(enc_keyset.encrypted_keyset(), associated_data); if (!decrypt_result.ok()) return decrypt_result.status(); util::SecretProto keyset; bool parsed = keyset->ParseFromString(decrypt_result.value()); util::SafeZeroString(&decrypt_result.value()); if (!parsed) { return util::Status( absl::StatusCode::kInvalidArgument, "Could not parse the decrypted data as a Keyset-proto."); } return std::move(keyset); } util::Status ValidateNoSecret(const Keyset& keyset) { for (const Keyset::Key& key : keyset.key()) { if (key.key_data().key_material_type() == KeyData::UNKNOWN_KEYMATERIAL || key.key_data().key_material_type() == KeyData::SYMMETRIC || key.key_data().key_material_type() == KeyData::ASYMMETRIC_PRIVATE) { return util::Status( absl::StatusCode::kFailedPrecondition, "Cannot create KeysetHandle with secret key material from " "potentially unencrypted source."); } } return util::OkStatus(); } util::StatusOr ToProtoKeySerialization( const Keyset::Key& key) { absl::optional id_requirement = absl::nullopt; if (key.output_prefix_type() != OutputPrefixType::RAW) { id_requirement = key.key_id(); } return internal::ProtoKeySerialization::Create( key.key_data().type_url(), RestrictedData(key.key_data().value(), InsecureSecretKeyAccess::Get()), key.key_data().key_material_type(), key.output_prefix_type(), id_requirement); } } // anonymous namespace util::Status KeysetHandle::ValidateAt(int index) const { const Keyset::Key& proto_key = keyset_->key(index); OutputPrefixType output_prefix_type = proto_key.output_prefix_type(); absl::optional id_requirement = absl::nullopt; if (output_prefix_type != OutputPrefixType::RAW) { id_requirement = proto_key.key_id(); } if (!internal::IsPrintableAscii(proto_key.key_data().type_url())) { return util::Status(absl::StatusCode::kFailedPrecondition, "Non-printable ASCII character in type URL."); } util::StatusOr key_status = internal::FromKeyStatusType(proto_key.status()); if (!key_status.ok()) return key_status.status(); return util::OkStatus(); } util::Status KeysetHandle::Validate() const { int num_primary = 0; for (int i = 0; i < size(); ++i) { util::Status status = ValidateAt(i); if (!status.ok()) return status; Keyset::Key proto_key = keyset_->key(i); if (proto_key.key_id() == keyset_->primary_key_id()) { ++num_primary; if (proto_key.status() != KeyStatusType::ENABLED) { return util::Status(absl::StatusCode::kFailedPrecondition, "Keyset has primary that is not enabled"); } } } if (num_primary < 1) { return util::Status(absl::StatusCode::kFailedPrecondition, "Keyset has no primary"); } if (num_primary > 1) { return util::Status(absl::StatusCode::kFailedPrecondition, "Keyset has more than one primary"); } return util::OkStatus(); } KeysetHandle::Entry KeysetHandle::GetPrimary() const { util::Status validation = Validate(); CHECK_OK(validation); for (int i = 0; i < keyset_->key_size(); ++i) { if (keyset_->key(i).key_id() == keyset_->primary_key_id()) { return (*this)[i]; } } // Since keyset handle was validated, it should have a valid primary key. internal::LogFatal("Keyset handle should have a valid primary key."); } KeysetHandle::Entry KeysetHandle::operator[](int index) const { CHECK(index >= 0 && index < size()) << "Invalid index " << index << " for keyset of size " << size(); if (!entries_.empty() && entries_.size() > index) { return *entries_[index]; } // Since `entries_` has not been populated, the entry must be created on // demand from the key proto entry at `index` in `keyset_`. This special // case will no longer be necessary after `keyset_` has been removed from the // `KeysetHandle` class. // // TODO(b/277792846): Remove after transition to rely solely on // `KeysetHandle::Entry`. return CreateEntryAt(index); } KeysetHandle::Entry KeysetHandle::CreateEntryAt(int index) const { CHECK(index >= 0 && index < size()) << "Invalid index " << index << " for keyset of size " << size(); util::Status validation = ValidateAt(index); CHECK_OK(validation); util::StatusOr entry = CreateEntry(keyset_->key(index), keyset_->primary_key_id()); // Status should be OK since this keyset handle has been validated. CHECK_OK(entry.status()); return *entry; } util::StatusOr KeysetHandle::CreateEntry( const Keyset::Key& proto_key, uint32_t primary_key_id) { util::StatusOr serialization = ToProtoKeySerialization(proto_key); if (!serialization.ok()) { return serialization.status(); } util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance() .ParseKeyWithLegacyFallback(*serialization, InsecureSecretKeyAccess::Get()); if (!key.ok()) { return key.status(); } util::StatusOr key_status = internal::FromKeyStatusType(proto_key.status()); if (!key_status.ok()) { return key_status.status(); } return Entry(*std::move(key), *key_status, proto_key.key_id(), proto_key.key_id() == primary_key_id); } util::StatusOr> KeysetHandle::Read( std::unique_ptr reader, const Aead& master_key_aead, const absl::flat_hash_map& monitoring_annotations) { return ReadWithAssociatedData(std::move(reader), master_key_aead, /*associated_data=*/"", monitoring_annotations); } util::StatusOr> KeysetHandle::ReadWithAssociatedData( std::unique_ptr reader, const Aead& master_key_aead, absl::string_view associated_data, const absl::flat_hash_map& monitoring_annotations) { util::StatusOr> enc_keyset_result = reader->ReadEncrypted(); if (!enc_keyset_result.ok()) { return ToStatusF(absl::StatusCode::kInvalidArgument, "Error reading encrypted keyset data: %s", enc_keyset_result.status().message()); } auto keyset_result = Decrypt(*enc_keyset_result.value(), master_key_aead, associated_data); if (!keyset_result.ok()) { return ToStatusF(absl::StatusCode::kInvalidArgument, "Error decrypting encrypted keyset: %s", keyset_result.status().message()); } util::StatusOr>> entries = GetEntriesFromKeyset(**keyset_result); if (!entries.ok()) { return entries.status(); } if (entries->size() != (*keyset_result)->key_size()) { return util::Status(absl::StatusCode::kInternal, "Error converting keyset proto into key entries."); } return absl::WrapUnique(new KeysetHandle(*std::move(keyset_result), *entries, monitoring_annotations)); } util::StatusOr> KeysetHandle::ReadNoSecret( const std::string& serialized_keyset, const absl::flat_hash_map& monitoring_annotations) { util::SecretProto keyset; if (!keyset->ParseFromString(serialized_keyset)) { return util::Status(absl::StatusCode::kInvalidArgument, "Could not parse the input string as a Keyset-proto."); } util::Status validation = ValidateNoSecret(*keyset); if (!validation.ok()) { return validation; } util::StatusOr>> entries = GetEntriesFromKeyset(*keyset); if (!entries.ok()) { return entries.status(); } if (entries->size() != keyset->key_size()) { return util::Status(absl::StatusCode::kInternal, "Error converting keyset proto into key entries."); } return absl::WrapUnique( new KeysetHandle(std::move(keyset), *entries, monitoring_annotations)); } util::Status KeysetHandle::Write(KeysetWriter* writer, const Aead& master_key_aead) const { return WriteWithAssociatedData(writer, master_key_aead, ""); } util::Status KeysetHandle::WriteWithAssociatedData( KeysetWriter* writer, const Aead& master_key_aead, absl::string_view associated_data) const { if (writer == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "Writer must be non-null"); } auto encrypt_result = Encrypt(*keyset_, master_key_aead, associated_data); if (!encrypt_result.ok()) { return ToStatusF(absl::StatusCode::kInvalidArgument, "Encryption of the keyset failed: %s", encrypt_result.status().message()); } return writer->Write(*(encrypt_result.value())); } util::Status KeysetHandle::WriteNoSecret(KeysetWriter* writer) const { if (writer == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "Writer must be non-null"); } util::Status validation = ValidateNoSecret(*keyset_); if (!validation.ok()) return validation; return writer->Write(*keyset_); } util::StatusOr> KeysetHandle::GenerateNew( const KeyTemplate& key_template, const KeyGenConfiguration& config, const absl::flat_hash_map& monitoring_annotations) { auto handle = absl::WrapUnique( new KeysetHandle(util::SecretProto(), monitoring_annotations)); util::StatusOr const result = handle->AddKey(key_template, /*as_primary=*/true, config); if (!result.ok()) { return result.status(); } return std::move(handle); } util::StatusOr> KeysetHandle::GenerateNew( const KeyTemplate& key_template, const KeyGenConfiguration& config) { return GenerateNew(key_template, config, /*monitoring_annotations=*/{}); } util::StatusOr> ExtractPublicKey( const Keyset::Key& key, const KeyGenConfiguration& config) { if (key.key_data().key_material_type() != KeyData::ASYMMETRIC_PRIVATE) { return util::Status( absl::StatusCode::kInvalidArgument, "Key material is not of type KeyData::ASYMMETRIC_PRIVATE"); } util::StatusOr> key_data; if (internal::KeyGenConfigurationImpl::IsInGlobalRegistryMode(config)) { key_data = Registry::GetPublicKeyData(key.key_data().type_url(), key.key_data().value()); } else { util::StatusOr key_type_info_store = internal::KeyGenConfigurationImpl::GetKeyTypeInfoStore(config); if (!key_type_info_store.ok()) { return key_type_info_store.status(); } util::StatusOr key_type_info = (*key_type_info_store)->Get(key.key_data().type_url()); if (!key_type_info.ok()) { return key_type_info.status(); } auto factory = dynamic_cast( &(*key_type_info)->key_factory()); if (factory == nullptr) { return ToStatusF( absl::StatusCode::kInvalidArgument, "KeyManager for type '%s' does not have a PrivateKeyFactory.", key.key_data().type_url()); } key_data = factory->GetPublicKeyData(key.key_data().value()); } if (!key_data.ok()) { return key_data.status(); } auto public_key = absl::make_unique(key); public_key->mutable_key_data()->Swap(key_data->get()); return std::move(public_key); } util::StatusOr> KeysetHandle::GetPublicKeysetHandle(const KeyGenConfiguration& config) const { util::SecretProto public_keyset; for (const Keyset::Key& key : keyset_->key()) { auto public_key_result = ExtractPublicKey(key, config); if (!public_key_result.ok()) return public_key_result.status(); public_keyset->add_key()->Swap(public_key_result.value().get()); } public_keyset->set_primary_key_id(keyset_->primary_key_id()); util::StatusOr>> entries = GetEntriesFromKeyset(*public_keyset); if (!entries.ok()) { return entries.status(); } if (entries->size() != public_keyset->key_size()) { return util::Status(absl::StatusCode::kInternal, "Error converting keyset proto into key entries."); } return absl::WrapUnique( new KeysetHandle(std::move(public_keyset), *entries)); } crypto::tink::util::StatusOr KeysetHandle::AddToKeyset( const google::crypto::tink::KeyTemplate& key_template, bool as_primary, const KeyGenConfiguration& config, Keyset* keyset) { if (key_template.output_prefix_type() == google::crypto::tink::OutputPrefixType::UNKNOWN_PREFIX) { return util::Status(absl::StatusCode::kInvalidArgument, "key template has unknown prefix"); } // Generate new key data. util::StatusOr> key_data; if (internal::KeyGenConfigurationImpl::IsInGlobalRegistryMode(config)) { key_data = Registry::NewKeyData(key_template); } else { util::StatusOr key_type_info_store = internal::KeyGenConfigurationImpl::GetKeyTypeInfoStore(config); if (!key_type_info_store.ok()) { return key_type_info_store.status(); } util::StatusOr key_type_info = (*key_type_info_store)->Get(key_template.type_url()); if (!key_type_info.ok()) { return key_type_info.status(); } key_data = (*key_type_info)->key_factory().NewKeyData(key_template.value()); } if (!key_data.ok()) { return key_data.status(); } // Add and fill in new key in `keyset`. Keyset::Key* key = keyset->add_key(); *(key->mutable_key_data()) = *std::move(key_data).value(); key->set_status(KeyStatusType::ENABLED); key->set_output_prefix_type(key_template.output_prefix_type()); uint32_t key_id = GenerateUnusedKeyId(*keyset); key->set_key_id(key_id); if (as_primary) { keyset->set_primary_key_id(key_id); } return key_id; } crypto::tink::util::StatusOr KeysetHandle::AddKey( const google::crypto::tink::KeyTemplate& key_template, bool as_primary, const KeyGenConfiguration& config) { util::StatusOr id = AddToKeyset(key_template, as_primary, config, keyset_.get()); if (!id.ok()) { return id.status(); } util::StatusOr entry = CreateEntry( keyset_->key(keyset_->key_size() - 1), keyset_->primary_key_id()); if (!entry.ok()) { return entry.status(); } entries_.push_back(std::make_shared(*entry)); return *id; } KeysetInfo KeysetHandle::GetKeysetInfo() const { return KeysetInfoFromKeyset(*keyset_); } util::StatusOr>> KeysetHandle::GetEntriesFromKeyset(const Keyset& keyset) { std::vector> entries; for (const Keyset::Key& key : keyset.key()) { util::StatusOr entry = CreateEntry(key, keyset.primary_key_id()); if (!entry.ok()) { return entry.status(); } entries.push_back(std::make_shared(*entry)); } return entries; } } // namespace tink } // namespace crypto ================================================ FILE: cc/core/keyset_handle_builder.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/keyset_handle_builder.h" #include #include #include #include #include #include #include "absl/container/flat_hash_map.h" #include "absl/log/check.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/internal/keyset_handle_builder_entry.h" #include "tink/key.h" #include "tink/key_status.h" #include "tink/keyset_handle.h" #include "tink/parameters.h" #include "tink/subtle/random.h" #include "tink/util/secret_proto.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::google::crypto::tink::Keyset; void SetBuilderEntryAttributes(KeyStatus status, bool is_primary, absl::optional id, KeysetHandleBuilder::Entry* entry) { entry->SetStatus(status); if (is_primary) { entry->SetPrimary(); } else { entry->UnsetPrimary(); } if (id.has_value()) { entry->SetFixedId(*id); } else { entry->SetRandomId(); } } } // namespace KeysetHandleBuilder::KeysetHandleBuilder(const KeysetHandle& handle) { for (int i = 0; i < handle.size(); ++i) { KeysetHandle::Entry entry = handle[i]; KeysetHandleBuilder::Entry builder_entry = KeysetHandleBuilder::Entry::CreateFromKey( std::move(entry.key_), entry.GetStatus(), entry.IsPrimary()); AddEntry(std::move(builder_entry)); } } KeysetHandleBuilder::Entry KeysetHandleBuilder::Entry::CreateFromKey( std::shared_ptr key, KeyStatus status, bool is_primary) { absl::optional id_requirement = key->GetIdRequirement(); auto imported_entry = absl::make_unique(std::move(key)); KeysetHandleBuilder::Entry entry(std::move(imported_entry)); SetBuilderEntryAttributes(status, is_primary, id_requirement, &entry); return entry; } KeysetHandleBuilder::Entry KeysetHandleBuilder::Entry::CreateFromParams( std::shared_ptr parameters, KeyStatus status, bool is_primary, absl::optional id) { auto generated_entry = absl::make_unique(std::move(parameters)); KeysetHandleBuilder::Entry entry(std::move(generated_entry)); SetBuilderEntryAttributes(status, is_primary, id, &entry); return entry; } util::StatusOr KeysetHandleBuilder::NextIdFromKeyIdStrategy( internal::KeyIdStrategy strategy, const std::set& ids_so_far) { if (strategy.strategy == internal::KeyIdStrategyEnum::kFixedId) { if (!strategy.id_requirement.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Missing fixed id with fixed id strategy."); } return *strategy.id_requirement; } if (strategy.strategy == internal::KeyIdStrategyEnum::kRandomId) { int id = 0; while (id == 0 || ids_so_far.find(id) != ids_so_far.end()) { id = subtle::Random::GetRandomUInt32(); } return id; } return util::Status(absl::StatusCode::kInvalidArgument, "Invalid key id strategy."); } void KeysetHandleBuilder::ClearPrimary() { for (KeysetHandleBuilder::Entry& entry : entries_) { entry.UnsetPrimary(); } } KeysetHandleBuilder& KeysetHandleBuilder::AddEntry( KeysetHandleBuilder::Entry entry) { CHECK(!entry.added_to_builder_) << "Keyset handle builder entry already added to a builder."; entry.added_to_builder_ = true; if (entry.IsPrimary()) { ClearPrimary(); } entries_.push_back(std::move(entry)); return *this; } KeysetHandleBuilder& KeysetHandleBuilder::RemoveEntry(int index) { CHECK(index >= 0 && index < entries_.size()) << "Keyset handle builder entry removal index out of range."; entries_.erase(entries_.begin() + index); return *this; } util::Status KeysetHandleBuilder::CheckIdAssignments() { // We only want random id entries after fixed id entries. Otherwise, we might // randomly pick an id that is later specified as a fixed id. for (int i = 0; i < entries_.size() - 1; ++i) { if (entries_[i].HasRandomId() && !entries_[i + 1].HasRandomId()) { return util::Status(absl::StatusCode::kFailedPrecondition, "Entries with random ids may only be followed " "by other entries with random ids."); } } return util::OkStatus(); } KeysetHandleBuilder& KeysetHandleBuilder::SetMonitoringAnnotations( const absl::flat_hash_map& monitoring_annotations) { monitoring_annotations_ = monitoring_annotations; return *this; } util::StatusOr KeysetHandleBuilder::Build() { if (build_called_) { return util::Status( absl::StatusCode::kFailedPrecondition, "KeysetHandleBuilder::Build may only be called once"); } build_called_ = true; util::SecretProto keyset; absl::optional primary_id = absl::nullopt; util::Status assigned_ids_status = CheckIdAssignments(); if (!assigned_ids_status.ok()) return assigned_ids_status; std::set ids_so_far; for (KeysetHandleBuilder::Entry& entry : entries_) { util::StatusOr id = NextIdFromKeyIdStrategy(entry.GetKeyIdStrategy(), ids_so_far); if (!id.ok()) return id.status(); if (ids_so_far.find(*id) != ids_so_far.end()) { return util::Status( absl::StatusCode::kAlreadyExists, absl::StrFormat("Next id %d is already used in the keyset.", *id)); } ids_so_far.insert(*id); util::StatusOr> key = entry.CreateKeysetKey(*id); if (!key.ok()) return key.status(); *keyset->add_key() = **key; if (entry.IsPrimary()) { if (primary_id.has_value()) { return util::Status( absl::StatusCode::kInternal, "Primary is already set in this keyset (should never happen since " "primary is cleared when a new primary is added)."); } primary_id = *id; } } if (!primary_id.has_value()) { return util::Status(absl::StatusCode::kFailedPrecondition, "No primary set in this keyset."); } keyset->set_primary_key_id(*primary_id); util::StatusOr>> entries = KeysetHandle::GetEntriesFromKeyset(*keyset); return KeysetHandle(std::move(keyset), *std::move(entries), monitoring_annotations_); } } // namespace tink } // namespace crypto ================================================ FILE: cc/core/keyset_handle_builder_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/keyset_handle_builder.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_map.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/aead/aes_gcm_parameters.h" #include "tink/config/global_registry.h" #include "tink/config/tink_config.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/input_stream.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/legacy_proto_key.h" #include "tink/internal/legacy_proto_parameters.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/key_status.h" #include "tink/keyset_handle.h" #include "tink/mac.h" #include "tink/mac/aes_cmac_key.h" #include "tink/mac/aes_cmac_parameters.h" #include "tink/mac/mac_key_templates.h" #include "tink/partial_key_access.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/registry.h" #include "tink/restricted_data.h" #include "tink/subtle/random.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_cmac.pb.h" #include "proto/aes_gcm.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::AddTinkKey; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::AesCmacParams; using ::google::crypto::tink::AesGcmKey; using ::google::crypto::tink::AesGcmKeyFormat; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::Keyset; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::OutputPrefixType; using ::testing::_; using ::testing::Eq; using ::testing::IsFalse; using ::testing::IsTrue; using ::testing::SizeIs; using ::testing::Test; class KeysetHandleBuilderTest : public Test { protected: void SetUp() override { util::Status status = TinkConfig::Register(); ASSERT_TRUE(status.ok()) << status; } }; using KeysetHandleBuilderDeathTest = KeysetHandleBuilderTest; util::StatusOr CreateLegacyProtoParameters( KeyTemplate key_template) { util::StatusOr serialization = internal::ProtoParametersSerialization::Create(key_template); if (!serialization.ok()) return serialization.status(); return internal::LegacyProtoParameters(*serialization); } TEST_F(KeysetHandleBuilderTest, BuildWithSingleKey) { util::StatusOr parameters = CreateLegacyProtoParameters(MacKeyTemplates::AesCmac()); ASSERT_THAT(parameters.status(), IsOk()); KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/123); util::StatusOr handle = KeysetHandleBuilder().AddEntry(std::move(entry)).Build(); ASSERT_THAT(handle.status(), IsOk()); EXPECT_THAT(*handle, SizeIs(1)); EXPECT_THAT((*handle)[0].GetStatus(), Eq(KeyStatus::kEnabled)); EXPECT_THAT((*handle)[0].GetId(), Eq(123)); EXPECT_THAT((*handle)[0].IsPrimary(), IsTrue()); EXPECT_THAT((*handle)[0].GetKey()->GetParameters().HasIdRequirement(), IsTrue()); } TEST_F(KeysetHandleBuilderTest, BuildWithMultipleKeys) { util::StatusOr parameters = CreateLegacyProtoParameters(MacKeyTemplates::AesCmac()); ASSERT_THAT(parameters.status(), IsOk()); KeysetHandleBuilder::Entry entry0 = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kDestroyed, /*is_primary=*/false, /*id=*/123); KeysetHandleBuilder::Entry entry1 = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/456); KeysetHandleBuilder::Entry entry2 = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kDisabled, /*is_primary=*/false, /*id=*/789); util::StatusOr handle = KeysetHandleBuilder() .AddEntry(std::move(entry0)) .AddEntry(std::move(entry1)) .AddEntry(std::move(entry2)) .Build(); ASSERT_THAT(handle.status(), IsOk()); EXPECT_THAT(*handle, SizeIs(3)); EXPECT_THAT((*handle)[0].GetStatus(), Eq(KeyStatus::kDestroyed)); EXPECT_THAT((*handle)[0].GetId(), Eq(123)); EXPECT_THAT((*handle)[0].IsPrimary(), IsFalse()); EXPECT_THAT((*handle)[0].GetKey()->GetParameters().HasIdRequirement(), IsTrue()); EXPECT_THAT((*handle)[1].GetStatus(), Eq(KeyStatus::kEnabled)); EXPECT_THAT((*handle)[1].GetId(), Eq(456)); EXPECT_THAT((*handle)[1].IsPrimary(), IsTrue()); EXPECT_THAT((*handle)[1].GetKey()->GetParameters().HasIdRequirement(), IsTrue()); EXPECT_THAT((*handle)[2].GetStatus(), Eq(KeyStatus::kDisabled)); EXPECT_THAT((*handle)[2].GetId(), Eq(789)); EXPECT_THAT((*handle)[2].IsPrimary(), IsFalse()); EXPECT_THAT((*handle)[2].GetKey()->GetParameters().HasIdRequirement(), IsTrue()); } TEST_F(KeysetHandleBuilderTest, BuildCopy) { util::StatusOr parameters = CreateLegacyProtoParameters(MacKeyTemplates::AesCmac()); ASSERT_THAT(parameters.status(), IsOk()); KeysetHandleBuilder::Entry entry0 = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kDestroyed, /*is_primary=*/false, /*id=*/123); KeysetHandleBuilder::Entry entry1 = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/456); KeysetHandleBuilder::Entry entry2 = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kDisabled, /*is_primary=*/false, /*id=*/789); util::StatusOr handle = KeysetHandleBuilder() .AddEntry(std::move(entry0)) .AddEntry(std::move(entry1)) .AddEntry(std::move(entry2)) .Build(); ASSERT_THAT(handle.status(), IsOk()); util::StatusOr copy = KeysetHandleBuilder(*handle).Build(); ASSERT_THAT(copy.status(), IsOk()); EXPECT_THAT(copy->size(), Eq(3)); EXPECT_THAT((*copy)[0].GetStatus(), Eq(KeyStatus::kDestroyed)); EXPECT_THAT((*copy)[0].GetId(), Eq(123)); EXPECT_THAT((*copy)[0].IsPrimary(), IsFalse()); EXPECT_THAT((*copy)[0].GetKey()->GetParameters().HasIdRequirement(), IsTrue()); EXPECT_THAT((*copy)[1].GetStatus(), Eq(KeyStatus::kEnabled)); EXPECT_THAT((*copy)[1].GetId(), Eq(456)); EXPECT_THAT((*copy)[1].IsPrimary(), IsTrue()); EXPECT_THAT((*copy)[1].GetKey()->GetParameters().HasIdRequirement(), IsTrue()); EXPECT_THAT((*copy)[2].GetStatus(), Eq(KeyStatus::kDisabled)); EXPECT_THAT((*copy)[2].GetId(), Eq(789)); EXPECT_THAT((*copy)[2].IsPrimary(), IsFalse()); EXPECT_THAT((*copy)[2].GetKey()->GetParameters().HasIdRequirement(), IsTrue()); } TEST_F(KeysetHandleBuilderTest, IsPrimary) { util::StatusOr parameters = CreateLegacyProtoParameters(MacKeyTemplates::AesCmac()); ASSERT_THAT(parameters.status(), IsOk()); KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromCopyableParams(*parameters, KeyStatus::kEnabled, /*is_primary=*/false, /*id=*/123); EXPECT_THAT(entry.IsPrimary(), IsFalse()); entry.SetPrimary(); EXPECT_THAT(entry.IsPrimary(), IsTrue()); } TEST_F(KeysetHandleBuilderTest, SetAndGetStatus) { util::StatusOr parameters = CreateLegacyProtoParameters(MacKeyTemplates::AesCmac()); ASSERT_THAT(parameters.status(), IsOk()); KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/false, /*id=*/123); entry.SetStatus(KeyStatus::kDisabled); EXPECT_THAT(entry.GetStatus(), Eq(KeyStatus::kDisabled)); entry.SetStatus(KeyStatus::kEnabled); EXPECT_THAT(entry.GetStatus(), Eq(KeyStatus::kEnabled)); entry.SetStatus(KeyStatus::kDestroyed); EXPECT_THAT(entry.GetStatus(), Eq(KeyStatus::kDestroyed)); } TEST_F(KeysetHandleBuilderTest, BuildWithRandomId) { util::StatusOr parameters = CreateLegacyProtoParameters(MacKeyTemplates::AesCmac()); ASSERT_THAT(parameters.status(), IsOk()); KeysetHandleBuilder::Entry primary = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true); KeysetHandleBuilder builder; builder.AddEntry(std::move(primary)); int num_non_primary_entries = 1 << 16; for (int i = 0; i < num_non_primary_entries; ++i) { KeysetHandleBuilder::Entry non_primary = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/false); builder.AddEntry(std::move(non_primary)); } util::StatusOr handle = builder.Build(); ASSERT_THAT(handle.status(), IsOk()); std::set ids; for (int i = 0; i < handle->size(); ++i) { ids.insert((*handle)[i].GetId()); } EXPECT_THAT(ids, SizeIs(num_non_primary_entries + 1)); } TEST_F(KeysetHandleBuilderTest, BuildWithRandomIdAfterFixedId) { util::StatusOr parameters = CreateLegacyProtoParameters(MacKeyTemplates::AesCmac()); ASSERT_THAT(parameters.status(), IsOk()); KeysetHandleBuilder::Entry fixed = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/123); KeysetHandleBuilder::Entry random = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/false); util::StatusOr handle = KeysetHandleBuilder() .AddEntry(std::move(fixed)) .AddEntry(std::move(random)) .Build(); ASSERT_THAT(handle.status(), IsOk()); EXPECT_THAT(*handle, SizeIs(2)); EXPECT_THAT((*handle)[0].GetId(), Eq(123)); } TEST_F(KeysetHandleBuilderTest, BuildWithFixedIdAfterRandomIdFails) { util::StatusOr parameters = CreateLegacyProtoParameters(MacKeyTemplates::AesCmac()); ASSERT_THAT(parameters.status(), IsOk()); KeysetHandleBuilder::Entry random = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/false); KeysetHandleBuilder::Entry fixed = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/123); util::StatusOr handle = KeysetHandleBuilder() .AddEntry(std::move(random)) .AddEntry(std::move(fixed)) .Build(); ASSERT_THAT(handle.status(), StatusIs(absl::StatusCode::kFailedPrecondition)); } TEST_F(KeysetHandleBuilderDeathTest, AddEntryToAnotherBuilderCrashes) { util::StatusOr parameters = CreateLegacyProtoParameters(MacKeyTemplates::AesCmac()); ASSERT_THAT(parameters.status(), IsOk()); KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/123); KeysetHandleBuilder builder0; builder0.AddEntry(std::move(entry)); KeysetHandleBuilder builder1; EXPECT_DEATH_IF_SUPPORTED( builder1.AddEntry(std::move(builder0[0])), "Keyset handle builder entry already added to a builder."); } TEST_F(KeysetHandleBuilderDeathTest, ReAddEntryToSameBuilderCrashes) { util::StatusOr parameters = CreateLegacyProtoParameters(MacKeyTemplates::AesCmac()); ASSERT_THAT(parameters.status(), IsOk()); KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/123); KeysetHandleBuilder builder; builder.AddEntry(std::move(entry)); EXPECT_DEATH_IF_SUPPORTED( builder.AddEntry(std::move(builder[0])), "Keyset handle builder entry already added to a builder."); } TEST_F(KeysetHandleBuilderDeathTest, AddDereferencedEntryToAnotherBuilderCrashes) { util::StatusOr parameters = CreateLegacyProtoParameters(MacKeyTemplates::AesCmac()); ASSERT_THAT(parameters.status(), IsOk()); KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/123); KeysetHandleBuilder builder0; builder0.AddEntry(std::move(entry)); KeysetHandleBuilder builder1; EXPECT_DEATH_IF_SUPPORTED( builder1.AddEntry(std::move(*&(builder0[0]))), "Keyset handle builder entry already added to a builder."); } TEST_F(KeysetHandleBuilderTest, RemoveEntry) { util::StatusOr parameters = CreateLegacyProtoParameters(MacKeyTemplates::AesCmac()); ASSERT_THAT(parameters.status(), IsOk()); KeysetHandleBuilder::Entry entry0 = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/false, /*id=*/123); KeysetHandleBuilder::Entry entry1 = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/456); util::StatusOr handle0 = KeysetHandleBuilder() .AddEntry(std::move(entry0)) .AddEntry(std::move(entry1)) .Build(); ASSERT_THAT(handle0.status(), IsOk()); ASSERT_THAT(*handle0, SizeIs(2)); util::StatusOr handle1 = KeysetHandleBuilder(*handle0).RemoveEntry(0).Build(); ASSERT_THAT(handle1.status(), IsOk()); ASSERT_THAT(*handle1, SizeIs(1)); EXPECT_THAT((*handle1)[0].GetStatus(), Eq(KeyStatus::kEnabled)); EXPECT_THAT((*handle1)[0].GetId(), Eq(456)); EXPECT_THAT((*handle1)[0].IsPrimary(), IsTrue()); EXPECT_THAT((*handle1)[0].GetKey()->GetParameters().HasIdRequirement(), IsTrue()); } TEST_F(KeysetHandleBuilderDeathTest, RemoveOutofRangeIndexEntryCrashes) { util::StatusOr parameters = CreateLegacyProtoParameters(MacKeyTemplates::AesCmac()); ASSERT_THAT(parameters.status(), IsOk()); KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/123); util::StatusOr handle = KeysetHandleBuilder().AddEntry(std::move(entry)).Build(); ASSERT_THAT(handle.status(), IsOk()); ASSERT_THAT(*handle, SizeIs(1)); EXPECT_DEATH_IF_SUPPORTED( KeysetHandleBuilder(*handle).RemoveEntry(1), "Keyset handle builder entry removal index out of range."); } TEST_F(KeysetHandleBuilderTest, Size) { util::StatusOr parameters = CreateLegacyProtoParameters(MacKeyTemplates::AesCmac()); ASSERT_THAT(parameters.status(), IsOk()); KeysetHandleBuilder::Entry entry0 = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kDestroyed, /*is_primary=*/false, /*id=*/123); KeysetHandleBuilder::Entry entry1 = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/456); KeysetHandleBuilder builder; ASSERT_THAT(builder, SizeIs(0)); builder.AddEntry(std::move(entry0)); ASSERT_THAT(builder, SizeIs(1)); builder.AddEntry(std::move(entry1)); EXPECT_THAT(builder, SizeIs(2)); } TEST_F(KeysetHandleBuilderTest, NoPrimaryFails) { util::StatusOr parameters = CreateLegacyProtoParameters(MacKeyTemplates::AesCmac()); ASSERT_THAT(parameters.status(), IsOk()); KeysetHandleBuilder::Entry entry0 = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/false, /*id=*/123); KeysetHandleBuilder::Entry entry1 = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/false, /*id=*/456); util::StatusOr handle = KeysetHandleBuilder() .AddEntry(std::move(entry0)) .AddEntry(std::move(entry1)) .Build(); ASSERT_THAT(handle.status(), StatusIs(absl::StatusCode::kFailedPrecondition)); } TEST_F(KeysetHandleBuilderTest, RemovePrimaryFails) { util::StatusOr parameters = CreateLegacyProtoParameters(MacKeyTemplates::AesCmac()); ASSERT_THAT(parameters.status(), IsOk()); KeysetHandleBuilder::Entry entry0 = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/123); KeysetHandleBuilder::Entry entry1 = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/false, /*id=*/456); util::StatusOr handle = KeysetHandleBuilder() .AddEntry(std::move(entry0)) .AddEntry(std::move(entry1)) .RemoveEntry(0) .Build(); ASSERT_THAT(handle.status(), StatusIs(absl::StatusCode::kFailedPrecondition)); } TEST_F(KeysetHandleBuilderTest, AddPrimaryClearsOtherPrimary) { util::StatusOr parameters = CreateLegacyProtoParameters(MacKeyTemplates::AesCmac()); ASSERT_THAT(parameters.status(), IsOk()); KeysetHandleBuilder builder; builder.AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/123)); builder.AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/456)); ASSERT_THAT(builder[0].IsPrimary(), IsFalse()); ASSERT_THAT(builder[1].IsPrimary(), IsTrue()); } TEST_F(KeysetHandleBuilderTest, NoIdStrategySucceeds) { util::StatusOr parameters = CreateLegacyProtoParameters(MacKeyTemplates::AesCmac()); ASSERT_THAT(parameters.status(), IsOk()); KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true); util::StatusOr handle = KeysetHandleBuilder().AddEntry(std::move(entry)).Build(); ASSERT_THAT(handle, IsOk()); } TEST_F(KeysetHandleBuilderTest, DuplicateId) { util::StatusOr parameters = CreateLegacyProtoParameters(MacKeyTemplates::AesCmac()); ASSERT_THAT(parameters.status(), IsOk()); util::StatusOr handle = KeysetHandleBuilder() .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/123)) .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/false, /*id=*/123)) .Build(); ASSERT_THAT(handle.status(), StatusIs(absl::StatusCode::kAlreadyExists)); } TEST_F(KeysetHandleBuilderTest, CreateBuilderEntryFromParams) { util::StatusOr params = AesCmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16, AesCmacParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromParams( absl::make_unique(std::move(*params)), KeyStatus::kEnabled, /*is_primary=*/true); util::StatusOr handle = KeysetHandleBuilder().AddEntry(std::move(entry)).Build(); ASSERT_THAT(handle.status(), IsOk()); } TEST_F(KeysetHandleBuilderTest, CreateBuilderEntryFromLegacyKey) { Keyset keyset; Keyset::Key key; AddTinkKey("first_key_type", 11, key, KeyStatusType::DISABLED, KeyData::SYMMETRIC, &keyset); util::StatusOr serialization = internal::ProtoKeySerialization::Create( key.key_data().type_url(), RestrictedData(key.SerializeAsString(), InsecureSecretKeyAccess::Get()), key.key_data().key_material_type(), key.output_prefix_type(), key.key_id()); util::StatusOr proto_key = internal::LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(proto_key.status(), IsOk()); KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromKey( absl::make_unique(std::move(*proto_key)), KeyStatus::kEnabled, /*is_primary=*/true); util::StatusOr handle = KeysetHandleBuilder().AddEntry(std::move(entry)).Build(); ASSERT_THAT(handle.status(), IsOk()); } TEST_F(KeysetHandleBuilderTest, CreateBuilderEntryFromKey) { util::StatusOr params = AesCmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16, AesCmacParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(32); util::StatusOr key = AesCmacKey::Create( *params, secret, /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(key.status(), IsOk()); KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromKey( absl::make_unique(std::move(*key)), KeyStatus::kEnabled, /*is_primary=*/true); util::StatusOr handle = KeysetHandleBuilder().AddEntry(std::move(entry)).Build(); ASSERT_THAT(handle.status(), IsOk()); } TEST_F(KeysetHandleBuilderTest, MergeTwoKeysetsWithTheSameIdButNoIdRequirementWorks) { util::StatusOr params = AesCmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16, AesCmacParameters::Variant::kNoPrefix); ASSERT_THAT(params, IsOk()); KeysetHandleBuilder::Entry entry1 = KeysetHandleBuilder::Entry::CreateFromParams( absl::make_unique(std::move(*params)), KeyStatus::kEnabled, /*is_primary=*/true); entry1.SetFixedId(123); util::StatusOr handle1 = KeysetHandleBuilder().AddEntry(std::move(entry1)).Build(); ASSERT_THAT(handle1.status(), IsOk()); KeysetHandleBuilder::Entry entry2 = KeysetHandleBuilder::Entry::CreateFromParams( absl::make_unique(std::move(*params)), KeyStatus::kEnabled, /*is_primary=*/true); entry2.SetFixedId(123); util::StatusOr handle2 = KeysetHandleBuilder().AddEntry(std::move(entry2)).Build(); ASSERT_THAT(handle2.status(), IsOk()); // handle1 and handle2 each contain one key with the same ID, but no ID // requirement. We can add them to a new keyset because they will get new, // random and distinct IDs. util::StatusOr handle12 = KeysetHandleBuilder() .AddEntry(KeysetHandleBuilder::Entry::CreateFromKey( (*handle1)[0].GetKey(), KeyStatus::kEnabled, /*is_primary=*/true)) .AddEntry(KeysetHandleBuilder::Entry::CreateFromKey( (*handle2)[0].GetKey(), KeyStatus::kEnabled, /*is_primary=*/false)) .Build(); ASSERT_THAT(handle12.status(), IsOk()); } TEST_F(KeysetHandleBuilderTest, CreateBuilderEntryFromCopyableKey) { Keyset keyset; Keyset::Key key; AddTinkKey("first_key_type", 11, key, KeyStatusType::DISABLED, KeyData::SYMMETRIC, &keyset); util::StatusOr serialization = internal::ProtoKeySerialization::Create( key.key_data().type_url(), RestrictedData(key.SerializeAsString(), InsecureSecretKeyAccess::Get()), key.key_data().key_material_type(), key.output_prefix_type(), key.key_id()); util::StatusOr proto_key = internal::LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(proto_key.status(), IsOk()); KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromCopyableKey( *proto_key, KeyStatus::kEnabled, /*is_primary=*/true); util::StatusOr handle = KeysetHandleBuilder().AddEntry(std::move(entry)).Build(); ASSERT_THAT(handle.status(), IsOk()); } TEST_F(KeysetHandleBuilderTest, CreateBuilderEntryFromParameters) { util::StatusOr parameters = CreateLegacyProtoParameters(MacKeyTemplates::AesCmac()); ASSERT_THAT(parameters.status(), IsOk()); KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromParams( absl::make_unique(*parameters), KeyStatus::kEnabled, /*is_primary=*/true); util::StatusOr handle = KeysetHandleBuilder().AddEntry(std::move(entry)).Build(); ASSERT_THAT(handle.status(), IsOk()); } TEST_F(KeysetHandleBuilderTest, CreateBuilderEntryFromCopyableParameters) { util::StatusOr parameters = CreateLegacyProtoParameters(MacKeyTemplates::AesCmac()); ASSERT_THAT(parameters.status(), IsOk()); KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true); util::StatusOr handle = KeysetHandleBuilder().AddEntry(std::move(entry)).Build(); ASSERT_THAT(handle.status(), IsOk()); } TEST_F(KeysetHandleBuilderTest, UsePrimitiveFromLegacyProtoParams) { util::StatusOr parameters = CreateLegacyProtoParameters(MacKeyTemplates::AesCmac()); ASSERT_THAT(parameters.status(), IsOk()); KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true); util::StatusOr handle = KeysetHandleBuilder().AddEntry(std::move(entry)).Build(); ASSERT_THAT(handle.status(), IsOk()); util::StatusOr> mac = handle->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(mac.status(), IsOk()); util::StatusOr tag = (*mac)->ComputeMac("some input"); ASSERT_THAT(tag.status(), IsOk()); util::Status verified = (*mac)->VerifyMac(*tag, "some input"); EXPECT_THAT(verified, IsOk()); } TEST_F(KeysetHandleBuilderTest, UsePrimitiveFromParams) { util::StatusOr params = AesCmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16, AesCmacParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromParams( absl::make_unique(std::move(*params)), KeyStatus::kEnabled, /*is_primary=*/true); util::StatusOr handle = KeysetHandleBuilder().AddEntry(std::move(entry)).Build(); ASSERT_THAT(handle.status(), IsOk()); util::StatusOr> mac = handle->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(mac.status(), IsOk()); util::StatusOr tag = (*mac)->ComputeMac("some input"); ASSERT_THAT(tag.status(), IsOk()); util::Status verified = (*mac)->VerifyMac(*tag, "some input"); EXPECT_THAT(verified, IsOk()); } TEST_F(KeysetHandleBuilderTest, UsePrimitiveFromLegacyProtoKey) { AesCmacParams params; params.set_tag_size(16); google::crypto::tink::AesCmacKey key; *key.mutable_params() = params; key.set_version(0); key.set_key_value(subtle::Random::GetRandomBytes(32)); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesCmacKey", RestrictedData(key.SerializeAsString(), InsecureSecretKeyAccess::Get()), KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/123); ASSERT_THAT(serialization, IsOk()); util::StatusOr proto_key = internal::LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(proto_key.status(), IsOk()); KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromCopyableKey( *proto_key, KeyStatus::kEnabled, /*is_primary=*/true); util::StatusOr handle = KeysetHandleBuilder().AddEntry(std::move(entry)).Build(); ASSERT_THAT(handle.status(), IsOk()); util::StatusOr> mac = handle->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(mac.status(), IsOk()); util::StatusOr tag = (*mac)->ComputeMac("some input"); ASSERT_THAT(tag.status(), IsOk()); util::Status verified = (*mac)->VerifyMac(*tag, "some input"); EXPECT_THAT(verified, IsOk()); } TEST_F(KeysetHandleBuilderTest, UsePrimitiveFromKey) { util::StatusOr params = AesCmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16, AesCmacParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(32); util::StatusOr key = AesCmacKey::Create( *params, secret, /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(key.status(), IsOk()); KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromKey( absl::make_unique(std::move(*key)), KeyStatus::kEnabled, /*is_primary=*/true); util::StatusOr handle = KeysetHandleBuilder().AddEntry(std::move(entry)).Build(); ASSERT_THAT(handle.status(), IsOk()); util::StatusOr> mac = handle->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(mac.status(), IsOk()); util::StatusOr tag = (*mac)->ComputeMac("some input"); ASSERT_THAT(tag.status(), IsOk()); util::Status verified = (*mac)->VerifyMac(*tag, "some input"); EXPECT_THAT(verified, IsOk()); } TEST_F(KeysetHandleBuilderTest, BuildTwiceFails) { util::StatusOr parameters = CreateLegacyProtoParameters(MacKeyTemplates::AesCmac()); ASSERT_THAT(parameters.status(), IsOk()); KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/123); KeysetHandleBuilder builder; builder.AddEntry(std::move(entry)); EXPECT_THAT(builder.Build(), IsOk()); EXPECT_THAT(builder.Build().status(), StatusIs(absl::StatusCode::kFailedPrecondition)); } TEST_F(KeysetHandleBuilderTest, UsePrimitivesFromSplitKeyset) { util::StatusOr params = AesCmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16, AesCmacParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); util::StatusOr handle = KeysetHandleBuilder() .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams( *params, KeyStatus::kEnabled, /*is_primary=*/false)) .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams( *params, KeyStatus::kEnabled, /*is_primary=*/true)) .Build(); ASSERT_THAT(handle, IsOkAndHolds(SizeIs(2))); util::StatusOr handle0 = KeysetHandleBuilder() .AddEntry(KeysetHandleBuilder::Entry::CreateFromKey( (*handle)[0].GetKey(), KeyStatus::kEnabled, /*is_primary=*/true)) .Build(); ASSERT_THAT(handle0, IsOkAndHolds(SizeIs(1))); ASSERT_THAT((*handle)[0].GetId(), Eq((*handle0)[0].GetId())); util::StatusOr handle1 = KeysetHandleBuilder() .AddEntry(KeysetHandleBuilder::Entry::CreateFromKey( (*handle)[1].GetKey(), KeyStatus::kEnabled, /*is_primary=*/true)) .Build(); ASSERT_THAT(handle1, IsOkAndHolds(SizeIs(1))); ASSERT_THAT((*handle)[1].GetId(), Eq((*handle1)[0].GetId())); util::StatusOr> mac0 = handle0->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(mac0.status(), IsOk()); util::StatusOr tag0 = (*mac0)->ComputeMac("some input"); ASSERT_THAT(tag0.status(), IsOk()); util::StatusOr> mac1 = handle1->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(mac1.status(), IsOk()); util::StatusOr tag1 = (*mac1)->ComputeMac("some other input"); ASSERT_THAT(tag1.status(), IsOk()); // Use original keyset to verify tags computed from new keysets. util::StatusOr> mac = handle->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(mac.status(), IsOk()); EXPECT_THAT((*mac)->VerifyMac(*tag0, "some input"), IsOk()); EXPECT_THAT((*mac)->VerifyMac(*tag1, "some other input"), IsOk()); } class MockAeadPrimitiveWrapper : public PrimitiveWrapper { public: MOCK_METHOD(util::StatusOr>, Wrap, (std::unique_ptr> primitive_set), (const override)); }; class FakeAeadKeyManager : public KeyTypeManager> { public: class AeadFactory : public PrimitiveFactory { public: explicit AeadFactory(absl::string_view key_type) : key_type_(key_type) {} util::StatusOr> Create( const AesGcmKey& key) const override { return {absl::make_unique(key_type_)}; } private: const std::string key_type_; }; explicit FakeAeadKeyManager(absl::string_view key_type) : KeyTypeManager(absl::make_unique(key_type)), key_type_(key_type) {} google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::SYMMETRIC; } uint32_t get_version() const override { return 0; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey(const AesGcmKey& key) const override { return util::OkStatus(); } crypto::tink::util::Status ValidateKeyFormat( const AesGcmKeyFormat& key_format) const override { return util::OkStatus(); } crypto::tink::util::StatusOr CreateKey( const AesGcmKeyFormat& key_format) const override { return AesGcmKey(); } crypto::tink::util::StatusOr DeriveKey( const AesGcmKeyFormat& key_format, InputStream* input_stream) const override { return AesGcmKey(); } private: const std::string key_type_; }; TEST_F(KeysetHandleBuilderTest, BuildWithAnnotations) { const absl::flat_hash_map kAnnotations = { {"key1", "value1"}, {"key2", "value2"}}; util::StatusOr aes_128_gcm = AesGcmParameters::Builder() .SetKeySizeInBytes(16) .SetIvSizeInBytes(12) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kTink) .Build(); ASSERT_THAT(aes_128_gcm, IsOk()); util::StatusOr keyset_handle = KeysetHandleBuilder() .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams( *aes_128_gcm, crypto::tink::KeyStatus::kEnabled, /*is_primary=*/true)) .SetMonitoringAnnotations(kAnnotations) .Build(); ASSERT_THAT(keyset_handle, IsOk()); // In order to validate annotations are set correctly, we need acceess to the // generated primitive set, which is populated by KeysetWrapperImpl and passed // to the primitive wrapper. We thus register a mock primitive wrapper for // Aead so that we can copy the annotations and later check them. auto primitive_wrapper = absl::make_unique(); absl::flat_hash_map generated_annotations; EXPECT_CALL(*primitive_wrapper, Wrap(_)) .WillOnce( [&generated_annotations]( std::unique_ptr> generated_primitive_set) { generated_annotations = generated_primitive_set->get_annotations(); std::unique_ptr aead = absl::make_unique(""); return aead; }); Registry::Reset(); ASSERT_THAT(Registry::RegisterPrimitiveWrapper(std::move(primitive_wrapper)), IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique( "type.googleapis.com/google.crypto.tink.AesGcmKey"), /*new_key_allowed=*/true), IsOk()); ASSERT_THAT( keyset_handle->GetPrimitive(ConfigGlobalRegistry()), IsOk()); EXPECT_EQ(generated_annotations, kAnnotations); // This is needed to cleanup mocks. Registry::Reset(); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/core/keyset_handle_test.cc ================================================ // Copyright 2017 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/keyset_handle.h" #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_map.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/aead.h" #include "tink/aead/aead_key_templates.h" #include "tink/aead/aead_wrapper.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/aead_key_templates.h" #include "tink/binary_keyset_reader.h" #include "tink/binary_keyset_writer.h" #include "tink/cleartext_keyset_handle.h" #include "tink/config/fips_140_2.h" #include "tink/config/global_registry.h" #include "tink/config/key_gen_fips_140_2.h" #include "tink/config/tink_config.h" #include "tink/configuration.h" #include "tink/core/key_manager_impl.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/input_stream.h" #include "tink/internal/configuration_impl.h" #include "tink/internal/fips_utils.h" #include "tink/internal/key_gen_configuration_impl.h" #include "tink/json_keyset_reader.h" #include "tink/json_keyset_writer.h" #include "tink/key_gen_configuration.h" #include "tink/key_status.h" #include "tink/keyset_reader.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/registry.h" #include "tink/signature/ecdsa_sign_key_manager.h" #include "tink/signature/ecdsa_verify_key_manager.h" #include "tink/signature/signature_key_templates.h" #include "tink/subtle/random.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_keyset_handle.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_gcm.pb.h" #include "proto/aes_gcm_siv.pb.h" #include "proto/ecdsa.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::crypto::tink::TestKeysetHandle; using ::crypto::tink::test::AddKeyData; using ::crypto::tink::test::AddLegacyKey; using ::crypto::tink::test::AddRawKey; using ::crypto::tink::test::AddTinkKey; using ::crypto::tink::test::DummyAead; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::AesGcmKey; using ::google::crypto::tink::AesGcmKeyFormat; using ::google::crypto::tink::AesGcmSivKey; using ::google::crypto::tink::EcdsaKeyFormat; using ::google::crypto::tink::EncryptedKeyset; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::Keyset; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::OutputPrefixType; using ::testing::_; using ::testing::Eq; using ::testing::IsFalse; using ::testing::IsTrue; using ::testing::Not; using ::testing::NotNull; using ::testing::SizeIs; namespace { class KeysetHandleTest : public ::testing::Test { protected: void SetUp() override { Registry::Reset(); auto status = TinkConfig::Register(); ASSERT_TRUE(status.ok()) << status; internal::UnSetFipsRestricted(); } }; using KeysetHandleDeathTest = KeysetHandleTest; // Fake AEAD key type manager for testing. class FakeAeadKeyManager : public KeyTypeManager> { public: class AeadFactory : public PrimitiveFactory { public: explicit AeadFactory(absl::string_view key_type) : key_type_(key_type) {} util::StatusOr> Create( const AesGcmKey& key) const override { return {absl::make_unique(key_type_)}; } private: const std::string key_type_; }; explicit FakeAeadKeyManager(absl::string_view key_type) : KeyTypeManager(absl::make_unique(key_type)), key_type_(key_type) {} google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::SYMMETRIC; } uint32_t get_version() const override { return 0; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey(const AesGcmKey& key) const override { return util::OkStatus(); } crypto::tink::util::Status ValidateKeyFormat( const AesGcmKeyFormat& key_format) const override { return util::OkStatus(); } crypto::tink::util::StatusOr CreateKey( const AesGcmKeyFormat& key_format) const override { return AesGcmKey(); } crypto::tink::util::StatusOr DeriveKey( const AesGcmKeyFormat& key_format, InputStream* input_stream) const override { return AesGcmKey(); } private: const std::string key_type_; }; class MockAeadPrimitiveWrapper : public PrimitiveWrapper { public: MOCK_METHOD(util::StatusOr>, Wrap, (std::unique_ptr> primitive_set), (const override)); }; // Generates a keyset for testing. Keyset GetTestKeyset() { Keyset keyset; Keyset::Key key; AddTinkKey("some_key_type", 42, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); AddRawKey("some_other_key_type", 711, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(42); return keyset; } // Generates a public keyset for testing. Keyset GetPublicTestKeyset() { Keyset keyset; Keyset::Key key; AddTinkKey("some_key_type", 42, key, KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PUBLIC, &keyset); AddRawKey("some_other_key_type", 711, key, KeyStatusType::ENABLED, KeyData::REMOTE, &keyset); keyset.set_primary_key_id(42); return keyset; } TEST_F(KeysetHandleTest, DefaultCtor) { KeysetHandle keyset_handle; EXPECT_THAT(keyset_handle.size(), Eq(0)); EXPECT_THAT(keyset_handle.Validate(), Not(IsOk())); EXPECT_THAT( keyset_handle.GetPrimitive(ConfigGlobalRegistry()), Not(IsOk())); } TEST_F(KeysetHandleTest, CopyCtorAndAssignment) { util::StatusOr> keyset_handle = KeysetHandle::ReadNoSecret(GetPublicTestKeyset().SerializeAsString()); ASSERT_THAT(keyset_handle, IsOk()); ASSERT_THAT(*keyset_handle, NotNull()); ASSERT_THAT((*keyset_handle)->Validate(), IsOk()); EXPECT_THAT((*keyset_handle)->size(), Eq(2)); EXPECT_THAT((*keyset_handle)->GetPrimary().GetId(), Eq(42)); KeysetHandle keyset_handle_copy = **keyset_handle; EXPECT_THAT(keyset_handle_copy.Validate(), IsOk()); EXPECT_EQ(keyset_handle_copy.size(), (*keyset_handle)->size()); EXPECT_THAT(keyset_handle_copy.GetPrimary().GetId(), Eq((*keyset_handle)->GetPrimary().GetId())); KeysetHandle keyset_handle_copy2; EXPECT_THAT(keyset_handle_copy2.Validate(), Not(IsOk())); EXPECT_THAT(keyset_handle_copy2.size(), Eq(0)); keyset_handle_copy2 = keyset_handle_copy; EXPECT_THAT(keyset_handle_copy2.Validate(), IsOk()); EXPECT_EQ(keyset_handle_copy2.size(), (*keyset_handle)->size()); EXPECT_THAT(keyset_handle_copy2.GetPrimary().GetId(), Eq((*keyset_handle)->GetPrimary().GetId())); } TEST_F(KeysetHandleTest, MoveCtorAndAssignment) { util::StatusOr> keyset_handle = KeysetHandle::ReadNoSecret(GetPublicTestKeyset().SerializeAsString()); ASSERT_THAT(keyset_handle, IsOk()); ASSERT_THAT(*keyset_handle, NotNull()); ASSERT_THAT((*keyset_handle)->Validate(), IsOk()); EXPECT_THAT((*keyset_handle)->size(), Eq(2)); EXPECT_THAT((*keyset_handle)->GetPrimary().GetId(), Eq(42)); KeysetHandle keyset_handle_moved = std::move(**keyset_handle); // Moved out handle becomes empty EXPECT_THAT((*keyset_handle)->Validate(), Not(IsOk())); EXPECT_THAT((*keyset_handle)->size(), Eq(0)); // Moved to handle is valid and contains expected values EXPECT_THAT(keyset_handle_moved.Validate(), IsOk()); EXPECT_THAT(keyset_handle_moved.size(), Eq(2)); EXPECT_THAT(keyset_handle_moved.GetPrimary().GetId(), Eq(42)); KeysetHandle keyset_handle_moved2; EXPECT_THAT(keyset_handle_moved2.Validate(), Not(IsOk())); EXPECT_THAT(keyset_handle_moved2.size(), Eq(0)); keyset_handle_moved2 = std::move(keyset_handle_moved); // Moved out handle becomes empty EXPECT_THAT(keyset_handle_moved.Validate(), Not(IsOk())); EXPECT_THAT(keyset_handle_moved.size(), Eq(0)); // Moved to handle is valid and contains expected values EXPECT_THAT(keyset_handle_moved2.Validate(), IsOk()); EXPECT_THAT(keyset_handle_moved2.size(), Eq(2)); EXPECT_THAT(keyset_handle_moved2.GetPrimary().GetId(), Eq(42)); } TEST_F(KeysetHandleTest, ReadEncryptedKeysetBinary) { Keyset keyset; Keyset::Key key; AddTinkKey("some_key_type", 42, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); AddRawKey("some_other_key_type", 711, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(42); { // Good encrypted keyset. DummyAead aead("dummy aead 42"); std::string keyset_ciphertext = aead.Encrypt(keyset.SerializeAsString(), /* associated_data= */ "") .value(); EncryptedKeyset encrypted_keyset; encrypted_keyset.set_encrypted_keyset(keyset_ciphertext); auto reader = std::move( BinaryKeysetReader::New(encrypted_keyset.SerializeAsString()).value()); auto result = KeysetHandle::Read(std::move(reader), aead); EXPECT_TRUE(result.ok()) << result.status(); auto handle = std::move(result.value()); EXPECT_EQ(keyset.SerializeAsString(), TestKeysetHandle::GetKeyset(*handle).SerializeAsString()); } { // AEAD does not match the ciphertext DummyAead aead("dummy aead 42"); std::string keyset_ciphertext = aead.Encrypt(keyset.SerializeAsString(), /* associated_data= */ "") .value(); EncryptedKeyset encrypted_keyset; encrypted_keyset.set_encrypted_keyset(keyset_ciphertext); auto reader = std::move( BinaryKeysetReader::New(encrypted_keyset.SerializeAsString()).value()); DummyAead wrong_aead("wrong aead"); auto result = KeysetHandle::Read(std::move(reader), wrong_aead); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); } { // Ciphertext does not contain actual keyset. DummyAead aead("dummy aead 42"); std::string keyset_ciphertext = aead.Encrypt("not a serialized keyset", /* associated_data= */ "") .value(); EncryptedKeyset encrypted_keyset; encrypted_keyset.set_encrypted_keyset(keyset_ciphertext); auto reader = std::move( BinaryKeysetReader::New(encrypted_keyset.SerializeAsString()).value()); auto result = KeysetHandle::Read(std::move(reader), aead); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); } { // Wrong ciphertext of encrypted keyset. DummyAead aead("dummy aead 42"); std::string keyset_ciphertext = "totally wrong ciphertext"; EncryptedKeyset encrypted_keyset; encrypted_keyset.set_encrypted_keyset(keyset_ciphertext); auto reader = std::move( BinaryKeysetReader::New(encrypted_keyset.SerializeAsString()).value()); auto result = KeysetHandle::Read(std::move(reader), aead); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); } } // Check that the generated keyset handle correctly propagates annotations. TEST_F(KeysetHandleTest, ReadEncryptedWithAnnotations) { const absl::flat_hash_map kAnnotations = { {"key1", "value1"}, {"key2", "value2"}}; Keyset keyset = GetTestKeyset(); DummyAead aead("dummy aead 42"); std::string keyset_ciphertext = *aead.Encrypt(keyset.SerializeAsString(), /*associated_data=*/""); EncryptedKeyset encrypted_keyset; encrypted_keyset.set_encrypted_keyset(keyset_ciphertext); util::StatusOr> reader = BinaryKeysetReader::New(encrypted_keyset.SerializeAsString()); util::StatusOr> keyset_handle = KeysetHandle::Read(*std::move(reader), aead, kAnnotations); ASSERT_THAT(keyset_handle, IsOk()); // In order to validate annotations are set correctly, we need acceess to the // generated primitive set, which is populated by KeysetWrapperImpl and passed // to the primitive wrapper. We thus register a mock primitive wrapper for // Aead so that we can copy the annotations and later check them. auto primitive_wrapper = absl::make_unique(); absl::flat_hash_map generated_annotations; EXPECT_CALL(*primitive_wrapper, Wrap(_)) .WillOnce( [&generated_annotations]( std::unique_ptr> generated_primitive_set) { generated_annotations = generated_primitive_set->get_annotations(); std::unique_ptr aead = absl::make_unique(""); return aead; }); Registry::Reset(); ASSERT_THAT(Registry::RegisterPrimitiveWrapper(std::move(primitive_wrapper)), IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique("some_key_type"), /*new_key_allowed=*/true), IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique("some_other_key_type"), /*new_key_allowed=*/true), IsOk()); ASSERT_THAT((*keyset_handle) ->GetPrimitive(ConfigGlobalRegistry()), IsOk()); EXPECT_EQ(generated_annotations, kAnnotations); // This is needed to cleanup mocks. Registry::Reset(); } TEST_F(KeysetHandleTest, ReadEncryptedKeysetJson) { Keyset keyset; Keyset::Key key; AddTinkKey("some_key_type", 42, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); AddRawKey("some_other_key_type", 711, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(42); { // Good encrypted keyset. DummyAead aead("dummy aead 42"); std::string keyset_ciphertext = aead.Encrypt(keyset.SerializeAsString(), /* associated_data= */ "") .value(); EncryptedKeyset encrypted_keyset; encrypted_keyset.set_encrypted_keyset(keyset_ciphertext); auto* keyset_info = encrypted_keyset.mutable_keyset_info(); keyset_info->set_primary_key_id(42); auto* key_info = keyset_info->add_key_info(); key_info->set_key_id(42); key_info->set_type_url("dummy key type"); key_info->set_output_prefix_type(OutputPrefixType::TINK); key_info->set_status(KeyStatusType::ENABLED); std::stringbuf buffer; std::unique_ptr destination_stream(new std::ostream(&buffer)); auto writer_result = JsonKeysetWriter::New(std::move(destination_stream)); ASSERT_TRUE(writer_result.ok()) << writer_result.status(); auto status = writer_result.value()->Write(encrypted_keyset); EXPECT_TRUE(status.ok()) << status; std::string json_serialized_encrypted_keyset = buffer.str(); EXPECT_TRUE(status.ok()) << status; auto reader = std::move( JsonKeysetReader::New(json_serialized_encrypted_keyset).value()); auto result = KeysetHandle::Read(std::move(reader), aead); EXPECT_TRUE(result.ok()) << result.status(); auto handle = std::move(result.value()); EXPECT_EQ(keyset.SerializeAsString(), TestKeysetHandle::GetKeyset(*handle).SerializeAsString()); } { // AEAD does not match the ciphertext DummyAead aead("dummy aead 42"); std::string keyset_ciphertext = aead.Encrypt(keyset.SerializeAsString(), /* associated_data= */ "") .value(); EncryptedKeyset encrypted_keyset; encrypted_keyset.set_encrypted_keyset(keyset_ciphertext); auto reader = std::move( JsonKeysetReader::New(encrypted_keyset.SerializeAsString()).value()); DummyAead wrong_aead("wrong aead"); auto result = KeysetHandle::Read(std::move(reader), wrong_aead); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); } { // Ciphertext does not contain actual keyset. DummyAead aead("dummy aead 42"); std::string keyset_ciphertext = aead.Encrypt("not a serialized keyset", /* associated_data= */ "") .value(); EncryptedKeyset encrypted_keyset; encrypted_keyset.set_encrypted_keyset(keyset_ciphertext); auto reader = std::move( JsonKeysetReader::New(encrypted_keyset.SerializeAsString()).value()); auto result = KeysetHandle::Read(std::move(reader), aead); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); } { // Wrong ciphertext of encrypted keyset. DummyAead aead("dummy aead 42"); std::string keyset_ciphertext = "totally wrong ciphertext"; EncryptedKeyset encrypted_keyset; encrypted_keyset.set_encrypted_keyset(keyset_ciphertext); auto reader = std::move( JsonKeysetReader::New(encrypted_keyset.SerializeAsString()).value()); auto result = KeysetHandle::Read(std::move(reader), aead); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); } } TEST_F(KeysetHandleTest, WriteEncryptedKeyset_Json) { // Prepare a valid keyset handle Keyset keyset; Keyset::Key key; AddTinkKey("some_key_type", 42, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); AddRawKey("some_other_key_type", 711, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(42); auto reader = std::move(BinaryKeysetReader::New(keyset.SerializeAsString()).value()); auto keyset_handle = std::move(CleartextKeysetHandle::Read(std::move(reader)).value()); // Prepare a keyset writer. DummyAead aead("dummy aead 42"); std::stringbuf buffer; std::unique_ptr destination_stream(new std::ostream(&buffer)); auto writer = std::move(JsonKeysetWriter::New(std::move(destination_stream)).value()); // Write the keyset handle and check the result. auto status = keyset_handle->Write(writer.get(), aead); EXPECT_TRUE(status.ok()) << status; auto reader_result = JsonKeysetReader::New(buffer.str()); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); auto read_encrypted_result = reader_result.value()->ReadEncrypted(); EXPECT_TRUE(read_encrypted_result.ok()) << read_encrypted_result.status(); auto encrypted_keyset = std::move(read_encrypted_result.value()); auto decrypt_result = aead.Decrypt(encrypted_keyset->encrypted_keyset(), /* associated_data= */ ""); EXPECT_TRUE(decrypt_result.status().ok()) << decrypt_result.status(); auto decrypted = decrypt_result.value(); EXPECT_EQ(decrypted, keyset.SerializeAsString()); // Try writing to a null-writer. status = keyset_handle->Write(nullptr, aead); EXPECT_FALSE(status.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, status.code()); } TEST_F(KeysetHandleTest, ReadEncryptedKeysetWithAssociatedDataGoodKeyset) { Keyset keyset; Keyset::Key key; AddTinkKey("some_key_type", 42, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); AddRawKey("some_other_key_type", 711, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(42); DummyAead aead("dummy aead 42"); std::string keyset_ciphertext = aead.Encrypt(keyset.SerializeAsString(), "aad").value(); EncryptedKeyset encrypted_keyset; encrypted_keyset.set_encrypted_keyset(keyset_ciphertext); std::unique_ptr reader = std::move( BinaryKeysetReader::New(encrypted_keyset.SerializeAsString()).value()); util::StatusOr> result = KeysetHandle::ReadWithAssociatedData(std::move(reader), aead, "aad"); EXPECT_THAT(result, IsOk()); auto handle = std::move(result.value()); EXPECT_EQ(keyset.SerializeAsString(), TestKeysetHandle::GetKeyset(*handle).SerializeAsString()); } // Check that the generated keyset handle correctly propagates annotations. TEST_F(KeysetHandleTest, ReadEncryptedWithAssociatedDataAndAnnotations) { const absl::flat_hash_map kAnnotations = { {"key1", "value1"}, {"key2", "value2"}}; constexpr absl::string_view kAssociatedData = "some associated data"; Keyset keyset = GetTestKeyset(); DummyAead aead("dummy aead 42"); std::string keyset_ciphertext = *aead.Encrypt(keyset.SerializeAsString(), kAssociatedData); EncryptedKeyset encrypted_keyset; encrypted_keyset.set_encrypted_keyset(keyset_ciphertext); util::StatusOr> reader = BinaryKeysetReader::New(encrypted_keyset.SerializeAsString()); util::StatusOr> keyset_handle = KeysetHandle::ReadWithAssociatedData(*std::move(reader), aead, kAssociatedData, kAnnotations); ASSERT_THAT(keyset_handle, IsOk()); auto primitive_wrapper = absl::make_unique(); absl::flat_hash_map generated_annotations; EXPECT_CALL(*primitive_wrapper, Wrap(_)) .WillOnce( [&generated_annotations]( std::unique_ptr> generated_primitive_set) { generated_annotations = generated_primitive_set->get_annotations(); std::unique_ptr aead = absl::make_unique(""); return aead; }); Registry::Reset(); ASSERT_THAT(Registry::RegisterPrimitiveWrapper(std::move(primitive_wrapper)), IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique("some_key_type"), /*new_key_allowed=*/true), IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique("some_other_key_type"), /*new_key_allowed=*/true), IsOk()); ASSERT_THAT((*keyset_handle) ->GetPrimitive(ConfigGlobalRegistry()), IsOk()); EXPECT_EQ(generated_annotations, kAnnotations); // This is needed to cleanup mocks. Registry::Reset(); } TEST_F(KeysetHandleTest, ReadEncryptedKeysetWithAssociatedDataWrongAad) { Keyset keyset; Keyset::Key key; AddTinkKey("some_key_type", 42, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); AddRawKey("some_other_key_type", 711, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(42); DummyAead aead("dummy aead 42"); std::string keyset_ciphertext = aead.Encrypt(keyset.SerializeAsString(), "aad").value(); EncryptedKeyset encrypted_keyset; encrypted_keyset.set_encrypted_keyset(keyset_ciphertext); auto reader = std::move( BinaryKeysetReader::New(encrypted_keyset.SerializeAsString()).value()); auto result = KeysetHandle::ReadWithAssociatedData(std::move(reader), aead, "different"); EXPECT_THAT(result, Not(IsOk())); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); } TEST_F(KeysetHandleTest, ReadEncryptedKeysetWithAssociatedDataEmptyAad) { Keyset keyset; Keyset::Key key; AddTinkKey("some_key_type", 42, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); AddRawKey("some_other_key_type", 711, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(42); DummyAead aead("dummy aead 42"); std::string keyset_ciphertext = aead.Encrypt(keyset.SerializeAsString(), "aad").value(); EncryptedKeyset encrypted_keyset; encrypted_keyset.set_encrypted_keyset(keyset_ciphertext); auto reader = std::move( BinaryKeysetReader::New(encrypted_keyset.SerializeAsString()).value()); auto result = KeysetHandle::Read(std::move(reader), aead); EXPECT_THAT(result, Not(IsOk())); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); } TEST_F(KeysetHandleTest, WriteEncryptedKeysetWithAssociatedData) { // Prepare a valid keyset handle Keyset keyset; Keyset::Key key; AddTinkKey("some_key_type", 42, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); AddRawKey("some_other_key_type", 711, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(42); auto reader = std::move(BinaryKeysetReader::New(keyset.SerializeAsString()).value()); auto keyset_handle = std::move(CleartextKeysetHandle::Read(std::move(reader)).value()); // Prepare a keyset writer. DummyAead aead("dummy aead 42"); std::stringbuf buffer; std::unique_ptr destination_stream(new std::ostream(&buffer)); auto writer = std::move(BinaryKeysetWriter::New(std::move(destination_stream)).value()); // Write the keyset handle and check the result. auto status = keyset_handle->WriteWithAssociatedData(writer.get(), aead, "aad"); EXPECT_TRUE(status.ok()) << status; auto reader_result = BinaryKeysetReader::New(buffer.str()); EXPECT_TRUE(reader_result.ok()) << reader_result.status(); auto read_encrypted_result = reader_result.value()->ReadEncrypted(); EXPECT_TRUE(read_encrypted_result.ok()) << read_encrypted_result.status(); auto encrypted_keyset = std::move(read_encrypted_result.value()); auto decrypt_result = aead.Decrypt(encrypted_keyset->encrypted_keyset(), "aad"); EXPECT_TRUE(decrypt_result.status().ok()) << decrypt_result.status(); auto decrypted = decrypt_result.value(); EXPECT_EQ(decrypted, keyset.SerializeAsString()); // Try writing to a null-writer. status = keyset_handle->Write(nullptr, aead); EXPECT_FALSE(status.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, status.code()); } TEST_F(KeysetHandleTest, GenerateNew) { const google::crypto::tink::KeyTemplate* templates[] = { &AeadKeyTemplates::Aes128Gcm(), &AeadKeyTemplates::Aes256Gcm(), &AeadKeyTemplates::Aes128CtrHmacSha256(), &AeadKeyTemplates::Aes256CtrHmacSha256(), }; for (auto templ : templates) { EXPECT_THAT(KeysetHandle::GenerateNew(*templ, KeyGenConfigGlobalRegistry()) .status(), IsOk()); EXPECT_THAT(KeysetHandle::GenerateNew(*templ, KeyGenConfigGlobalRegistry()) .status(), IsOk()); } } TEST_F(KeysetHandleTest, GenerateNewWithBespokeConfig) { KeyGenConfiguration config; EXPECT_THAT( KeysetHandle::GenerateNew(AeadKeyTemplates::Aes128Gcm(), config).status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(internal::KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config), IsOk()); EXPECT_THAT( KeysetHandle::GenerateNew(AeadKeyTemplates::Aes128Gcm(), config).status(), IsOk()); } TEST_F(KeysetHandleTest, GenerateNewWithGlobalRegistryConfig) { EXPECT_THAT(KeysetHandle::GenerateNew(AeadKeyTemplates::Aes128Gcm(), KeyGenConfigGlobalRegistry()), IsOk()); } TEST_F(KeysetHandleTest, GenerateNewWithAnnotations) { const absl::flat_hash_map kAnnotations = { {"key1", "value1"}, {"key2", "value2"}}; // `handle` depends on the global registry. util::StatusOr> handle = KeysetHandle::GenerateNew(AeadKeyTemplates::Aes128Gcm(), KeyGenConfigGlobalRegistry(), kAnnotations); ASSERT_THAT(handle, IsOk()); // `config_handle` uses a config that depends on the global registry. util::StatusOr> config_handle = KeysetHandle::GenerateNew(AeadKeyTemplates::Aes128Gcm(), KeyGenConfigGlobalRegistry(), kAnnotations); ASSERT_THAT(config_handle, IsOk()); for (KeysetHandle h : {**handle, **config_handle}) { auto primitive_wrapper = absl::make_unique(); absl::flat_hash_map generated_annotations; EXPECT_CALL(*primitive_wrapper, Wrap(_)) .WillOnce( [&generated_annotations]( std::unique_ptr> generated_primitive_set) { generated_annotations = generated_primitive_set->get_annotations(); std::unique_ptr aead = absl::make_unique(""); return aead; }); Registry::Reset(); ASSERT_THAT( Registry::RegisterPrimitiveWrapper(std::move(primitive_wrapper)), IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique( "type.googleapis.com/google.crypto.tink.AesGcmKey"), /*new_key_allowed=*/true), IsOk()); EXPECT_THAT(h.GetPrimitive(ConfigGlobalRegistry()), IsOk()); EXPECT_EQ(generated_annotations, kAnnotations); // This is needed to cleanup mocks. Registry::Reset(); } } TEST_F(KeysetHandleTest, GenerateNewErrors) { KeyTemplate templ; templ.set_type_url("type.googleapis.com/some.unknown.KeyType"); templ.set_output_prefix_type(OutputPrefixType::TINK); auto handle_result = KeysetHandle::GenerateNew(templ, KeyGenConfigGlobalRegistry()); EXPECT_FALSE(handle_result.ok()); EXPECT_EQ(absl::StatusCode::kNotFound, handle_result.status().code()); } TEST_F(KeysetHandleTest, UnknownPrefixIsInvalid) { KeyTemplate templ(AeadKeyTemplates::Aes128Gcm()); templ.set_output_prefix_type(OutputPrefixType::UNKNOWN_PREFIX); auto handle_result = KeysetHandle::GenerateNew(templ, KeyGenConfigGlobalRegistry()); EXPECT_FALSE(handle_result.ok()); } void CompareKeyMetadata(const Keyset::Key& expected, const Keyset::Key& actual) { EXPECT_EQ(expected.status(), actual.status()); EXPECT_EQ(expected.key_id(), actual.key_id()); EXPECT_EQ(expected.output_prefix_type(), actual.output_prefix_type()); } util::StatusOr CreateEcdsaMultiKeyset() { Keyset keyset; EcdsaSignKeyManager key_manager; EcdsaKeyFormat key_format; if (!key_format.ParseFromString(SignatureKeyTemplates::EcdsaP256().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse EcdsaP256 key template"); } AddTinkKey(EcdsaSignKeyManager().get_key_type(), /* key_id= */ 623628, key_manager.CreateKey(key_format).value(), KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PRIVATE, &keyset); if (!key_format.ParseFromString( SignatureKeyTemplates::EcdsaP384Sha384().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse EcdsaP384Sha384 key template"); } AddLegacyKey(EcdsaSignKeyManager().get_key_type(), /* key_id= */ 36285, key_manager.CreateKey(key_format).value(), KeyStatusType::DISABLED, KeyData::ASYMMETRIC_PRIVATE, &keyset); if (!key_format.ParseFromString( SignatureKeyTemplates::EcdsaP384Sha512().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse EcdsaP384Sha512 key template"); } AddRawKey(EcdsaSignKeyManager().get_key_type(), /* key_id= */ 42, key_manager.CreateKey(key_format).value(), KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PRIVATE, &keyset); keyset.set_primary_key_id(42); return keyset; } // TODO(b/265865177): Modernize existing GetPublicKeysetHandle tests. TEST_F(KeysetHandleTest, GetPublicKeysetHandle) { { // A keyset with a single key. auto handle_result = KeysetHandle::GenerateNew( SignatureKeyTemplates::EcdsaP256(), KeyGenConfigGlobalRegistry()); ASSERT_TRUE(handle_result.ok()) << handle_result.status(); auto handle = std::move(handle_result.value()); auto public_handle_result = handle->GetPublicKeysetHandle(KeyGenConfigGlobalRegistry()); ASSERT_TRUE(public_handle_result.ok()) << public_handle_result.status(); auto keyset = TestKeysetHandle::GetKeyset(*handle); auto public_keyset = TestKeysetHandle::GetKeyset(*(public_handle_result.value())); EXPECT_EQ(keyset.primary_key_id(), public_keyset.primary_key_id()); EXPECT_EQ(keyset.key_size(), public_keyset.key_size()); CompareKeyMetadata(keyset.key(0), public_keyset.key(0)); EXPECT_EQ(KeyData::ASYMMETRIC_PUBLIC, public_keyset.key(0).key_data().key_material_type()); } { // A keyset with multiple keys. util::StatusOr keyset = CreateEcdsaMultiKeyset(); ASSERT_THAT(keyset, IsOk()); std::unique_ptr handle = TestKeysetHandle::GetKeysetHandle(*keyset); util::StatusOr> public_handle = handle->GetPublicKeysetHandle(KeyGenConfigGlobalRegistry()); ASSERT_THAT(public_handle, IsOk()); const Keyset& public_keyset = TestKeysetHandle::GetKeyset(**public_handle); EXPECT_EQ(keyset->primary_key_id(), public_keyset.primary_key_id()); EXPECT_EQ(keyset->key_size(), public_keyset.key_size()); for (int i = 0; i < keyset->key_size(); i++) { CompareKeyMetadata(keyset->key(i), public_keyset.key(i)); EXPECT_EQ(KeyData::ASYMMETRIC_PUBLIC, public_keyset.key(i).key_data().key_material_type()); } } } TEST_F(KeysetHandleTest, GetPublicKeysetHandleErrors) { { // A keyset with a single key. auto handle_result = KeysetHandle::GenerateNew( AeadKeyTemplates::Aes128Eax(), KeyGenConfigGlobalRegistry()); ASSERT_TRUE(handle_result.ok()) << handle_result.status(); auto handle = std::move(handle_result.value()); auto public_handle_result = handle->GetPublicKeysetHandle(KeyGenConfigGlobalRegistry()); ASSERT_FALSE(public_handle_result.ok()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "ASYMMETRIC_PRIVATE", std::string(public_handle_result.status().message())); } { // A keyset with multiple keys. Keyset keyset; EcdsaKeyFormat ecdsa_key_format; ASSERT_TRUE(ecdsa_key_format.ParseFromString( SignatureKeyTemplates::EcdsaP256().value())); google::crypto::tink::AesGcmKeyFormat aead_key_format; aead_key_format.set_key_size(16); AddTinkKey(EcdsaSignKeyManager().get_key_type(), /* key_id= */ 623628, EcdsaSignKeyManager().CreateKey(ecdsa_key_format).value(), KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PRIVATE, &keyset); AddLegacyKey(AesGcmKeyManager().get_key_type(), /* key_id= */ 42, AesGcmKeyManager().CreateKey(aead_key_format).value(), KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PRIVATE, // Intentionally wrong setting. &keyset); keyset.set_primary_key_id(42); auto handle = TestKeysetHandle::GetKeysetHandle(keyset); auto public_handle_result = handle->GetPublicKeysetHandle(KeyGenConfigGlobalRegistry()); ASSERT_FALSE(public_handle_result.ok()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "PrivateKeyFactory", std::string(public_handle_result.status().message())); } } TEST_F(KeysetHandleTest, GetPublicKeysetHandleWithBespokeConfigSucceeds) { util::StatusOr keyset = CreateEcdsaMultiKeyset(); ASSERT_THAT(keyset, IsOk()); std::unique_ptr handle = TestKeysetHandle::GetKeysetHandle(*keyset); KeyGenConfiguration config; ASSERT_THAT(internal::KeyGenConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config), IsOk()); util::StatusOr> public_handle = handle->GetPublicKeysetHandle(config); ASSERT_THAT(public_handle, IsOk()); const Keyset& public_keyset = TestKeysetHandle::GetKeyset(**public_handle); EXPECT_EQ(keyset->primary_key_id(), public_keyset.primary_key_id()); EXPECT_EQ(keyset->key_size(), public_keyset.key_size()); for (int i = 0; i < keyset->key_size(); i++) { CompareKeyMetadata(keyset->key(i), public_keyset.key(i)); EXPECT_EQ(KeyData::ASYMMETRIC_PUBLIC, public_keyset.key(i).key_data().key_material_type()); } } TEST_F(KeysetHandleTest, GetPublicKeysetHandleWithBespokeConfigFails) { KeyGenConfiguration config; ASSERT_THAT(internal::KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config), IsOk()); util::StatusOr> handle = KeysetHandle::GenerateNew(AeadKeyTemplates::Aes128Gcm(), config); ASSERT_THAT(handle, IsOk()); EXPECT_THAT((*handle)->GetPublicKeysetHandle(config).status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(KeysetHandleTest, GetPublicKeysetHandleWithGlobalRegistryConfigSucceeds) { util::StatusOr keyset = CreateEcdsaMultiKeyset(); ASSERT_THAT(keyset, IsOk()); std::unique_ptr handle = TestKeysetHandle::GetKeysetHandle(*keyset); util::StatusOr> public_handle = handle->GetPublicKeysetHandle(KeyGenConfigGlobalRegistry()); ASSERT_THAT(public_handle, IsOk()); const Keyset& public_keyset = TestKeysetHandle::GetKeyset(**public_handle); EXPECT_EQ(keyset->primary_key_id(), public_keyset.primary_key_id()); EXPECT_EQ(keyset->key_size(), public_keyset.key_size()); for (int i = 0; i < keyset->key_size(); i++) { CompareKeyMetadata(keyset->key(i), public_keyset.key(i)); EXPECT_EQ(KeyData::ASYMMETRIC_PUBLIC, public_keyset.key(i).key_data().key_material_type()); } } TEST_F(KeysetHandleTest, GetPublicKeysetHandleWithGlobalRegistryConfigFails) { util::StatusOr> handle = KeysetHandle::GenerateNew(AeadKeyTemplates::Aes128Gcm(), KeyGenConfigGlobalRegistry()); ASSERT_THAT(handle, IsOk()); EXPECT_THAT( (*handle)->GetPublicKeysetHandle(KeyGenConfigGlobalRegistry()).status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(KeysetHandleTest, GetPrimitive) { Keyset keyset; KeyData key_data_0 = *Registry::NewKeyData(AeadKeyTemplates::Aes128Gcm()).value(); AddKeyData(key_data_0, /*key_id=*/0, google::crypto::tink::OutputPrefixType::TINK, KeyStatusType::ENABLED, &keyset); KeyData key_data_1 = *Registry::NewKeyData(AeadKeyTemplates::Aes256Gcm()).value(); AddKeyData(key_data_1, /*key_id=*/1, google::crypto::tink::OutputPrefixType::TINK, KeyStatusType::ENABLED, &keyset); KeyData key_data_2 = *Registry::NewKeyData(AeadKeyTemplates::Aes256Gcm()).value(); AddKeyData(key_data_2, /*key_id=*/2, google::crypto::tink::OutputPrefixType::RAW, KeyStatusType::ENABLED, &keyset); keyset.set_primary_key_id(1); std::unique_ptr keyset_handle = TestKeysetHandle::GetKeysetHandle(keyset); // Check that encryption with the primary can be decrypted with key_data_1. auto aead_result = keyset_handle->GetPrimitive(ConfigGlobalRegistry()); ASSERT_TRUE(aead_result.ok()) << aead_result.status(); std::unique_ptr aead = std::move(aead_result.value()); std::string plaintext = "plaintext"; std::string aad = "aad"; std::string encryption = aead->Encrypt(plaintext, aad).value(); EXPECT_EQ(aead->Decrypt(encryption, aad).value(), plaintext); std::unique_ptr raw_aead = Registry::GetPrimitive(key_data_2).value(); EXPECT_FALSE(raw_aead->Decrypt(encryption, aad).ok()); std::string raw_encryption = raw_aead->Encrypt(plaintext, aad).value(); EXPECT_EQ(aead->Decrypt(raw_encryption, aad).value(), plaintext); } TEST_F(KeysetHandleTest, GetPrimitiveWithBespokeConfigSucceeds) { KeyGenConfiguration key_gen_config; ASSERT_THAT(internal::KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), key_gen_config), IsOk()); util::StatusOr> handle = KeysetHandle::GenerateNew(AeadKeyTemplates::Aes128Gcm(), key_gen_config); ASSERT_THAT(handle, IsOk()); Configuration config; ASSERT_THAT(internal::ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config), IsOk()); ASSERT_THAT(internal::ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config), IsOk()); EXPECT_THAT((*handle)->GetPrimitive(config).status(), IsOk()); } TEST_F(KeysetHandleTest, GetPrimitiveWithBespokeConfigFailsIfEmpty) { KeyGenConfiguration key_gen_config; ASSERT_THAT(internal::KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), key_gen_config), IsOk()); util::StatusOr> handle = KeysetHandle::GenerateNew(AeadKeyTemplates::Aes128Gcm(), key_gen_config); ASSERT_THAT(handle, IsOk()); Configuration config; EXPECT_THAT((*handle)->GetPrimitive(config).status(), StatusIs(absl::StatusCode::kNotFound)); } TEST_F(KeysetHandleTest, GetPrimitiveWithGlobalRegistryConfig) { util::StatusOr> handle = KeysetHandle::GenerateNew(AeadKeyTemplates::Aes128Gcm(), KeyGenConfigGlobalRegistry()); ASSERT_THAT(handle, IsOk()); EXPECT_THAT((*handle)->GetPrimitive(ConfigGlobalRegistry()), IsOk()); } TEST_F(KeysetHandleTest, GetPrimitiveWithConfigFips1402) { if (!internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only test in FIPS mode"; } util::StatusOr> handle = KeysetHandle::GenerateNew(AeadKeyTemplates::Aes128Gcm(), KeyGenConfigFips140_2()); ASSERT_THAT(handle, IsOk()); EXPECT_THAT((*handle)->GetPrimitive(ConfigFips140_2()), IsOk()); } TEST_F(KeysetHandleTest, GetPrimitiveWithConfigFips1402FailsWithNonFipsHandle) { if (!internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only test in FIPS mode"; } Keyset keyset; AesGcmSivKey key_proto; *key_proto.mutable_key_value() = subtle::Random::GetRandomBytes(16); test::AddTinkKey(AeadKeyTemplates::Aes256GcmSiv().type_url(), /*key_id=*/13, key_proto, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(13); std::unique_ptr handle = TestKeysetHandle::GetKeysetHandle(keyset); EXPECT_THAT(handle->GetPrimitive(ConfigFips140_2()).status(), StatusIs(absl::StatusCode::kNotFound)); } // Tests that GetPrimitive(nullptr) fails with a non-ok status. // TINK-PENDING-REMOVAL-IN-3.0.0-START TEST_F(KeysetHandleTest, GetPrimitiveNullptrKeyManager) { Keyset keyset; AddKeyData(*Registry::NewKeyData(AeadKeyTemplates::Aes128Gcm()).value(), /*key_id=*/0, google::crypto::tink::OutputPrefixType::TINK, KeyStatusType::ENABLED, &keyset); keyset.set_primary_key_id(0); std::unique_ptr keyset_handle = TestKeysetHandle::GetKeysetHandle(keyset); ASSERT_THAT(keyset_handle->GetPrimitive(nullptr).status(), test::StatusIs(absl::StatusCode::kInvalidArgument)); } // TINK-PENDING-REMOVAL-IN-3.0.0-END // Test creating with custom key manager. For this, we reset the registry before // asking for the primitive. // NOLINTBEGIN(whitespace/line_length) (Formatted when commented in) // TINK-PENDING-REMOVAL-IN-3.0.0-START TEST_F(KeysetHandleTest, GetPrimitiveCustomKeyManager) { auto handle_result = KeysetHandle::GenerateNew(AeadKeyTemplates::Aes128Gcm(), KeyGenConfigGlobalRegistry()); ASSERT_TRUE(handle_result.ok()) << handle_result.status(); std::unique_ptr handle = std::move(handle_result.value()); Registry::Reset(); ASSERT_TRUE( Registry::RegisterPrimitiveWrapper(absl::make_unique()) .ok()); // Without custom key manager it now fails. ASSERT_FALSE( handle->GetPrimitive(ConfigGlobalRegistry()).ok()); AesGcmKeyManager key_type_manager; std::unique_ptr> key_manager = crypto::tink::internal::MakeKeyManager(&key_type_manager); // With custom key manager it works ok. ASSERT_TRUE(handle->GetPrimitive(key_manager.get()).ok()); } // TINK-PENDING-REMOVAL-IN-3.0.0-END // NOLINTEND(whitespace/line_length) // Compile time check: ensures that the KeysetHandle can be copied. TEST_F(KeysetHandleTest, Copiable) { auto handle_result = KeysetHandle::GenerateNew(AeadKeyTemplates::Aes128Eax(), KeyGenConfigGlobalRegistry()); ASSERT_TRUE(handle_result.ok()) << handle_result.status(); std::unique_ptr handle = std::move(handle_result.value()); KeysetHandle handle_copy = *handle; } TEST_F(KeysetHandleTest, ReadNoSecret) { Keyset keyset; Keyset::Key key; AddTinkKey("some_key_type", 42, key, KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PUBLIC, &keyset); AddRawKey("some_other_key_type", 711, key, KeyStatusType::ENABLED, KeyData::REMOTE, &keyset); keyset.set_primary_key_id(42); auto handle_result = KeysetHandle::ReadNoSecret(keyset.SerializeAsString()); ASSERT_THAT(handle_result, IsOk()); std::unique_ptr& keyset_handle = handle_result.value(); const Keyset& result = CleartextKeysetHandle::GetKeyset(*keyset_handle); // We check that result equals keyset. For lack of a better method we do this // by hand. EXPECT_EQ(result.primary_key_id(), keyset.primary_key_id()); ASSERT_EQ(result.key_size(), keyset.key_size()); ASSERT_EQ(result.key(0).key_id(), keyset.key(0).key_id()); ASSERT_EQ(result.key(1).key_id(), keyset.key(1).key_id()); } TEST_F(KeysetHandleTest, ReadNoSecretWithAnnotations) { const absl::flat_hash_map kAnnotations = { {"key1", "value1"}, {"key2", "value2"}}; Keyset keyset = GetPublicTestKeyset(); util::StatusOr> keyset_handle = KeysetHandle::ReadNoSecret(keyset.SerializeAsString(), kAnnotations); ASSERT_THAT(keyset_handle, IsOk()); auto primitive_wrapper = absl::make_unique(); absl::flat_hash_map generated_annotations; EXPECT_CALL(*primitive_wrapper, Wrap(_)) .WillOnce( [&generated_annotations]( std::unique_ptr> generated_primitive_set) { generated_annotations = generated_primitive_set->get_annotations(); std::unique_ptr aead = absl::make_unique(""); return aead; }); Registry::Reset(); ASSERT_THAT(Registry::RegisterPrimitiveWrapper(std::move(primitive_wrapper)), IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique("some_key_type"), /*new_key_allowed=*/true), IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique("some_other_key_type"), /*new_key_allowed=*/true), IsOk()); EXPECT_THAT((*keyset_handle) ->GetPrimitive(ConfigGlobalRegistry()), IsOk()); EXPECT_EQ(generated_annotations, kAnnotations); // This is needed to cleanup mocks. Registry::Reset(); } TEST_F(KeysetHandleTest, ReadNoSecretFailForTypeUnknown) { Keyset keyset; Keyset::Key key; AddTinkKey("some_key_type", 42, key, KeyStatusType::ENABLED, KeyData::UNKNOWN_KEYMATERIAL, &keyset); keyset.set_primary_key_id(42); auto result = KeysetHandle::ReadNoSecret(keyset.SerializeAsString()); EXPECT_THAT(result.status(), StatusIs(absl::StatusCode::kFailedPrecondition)); } TEST_F(KeysetHandleTest, ReadNoSecretFailForTypeSymmetric) { Keyset keyset; Keyset::Key key; AddTinkKey("some_key_type", 42, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(42); auto result = KeysetHandle::ReadNoSecret(keyset.SerializeAsString()); EXPECT_THAT(result.status(), StatusIs(absl::StatusCode::kFailedPrecondition)); } TEST_F(KeysetHandleTest, ReadNoSecretFailForTypeAssymmetricPrivate) { Keyset keyset; Keyset::Key key; AddTinkKey("some_key_type", 42, key, KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PRIVATE, &keyset); keyset.set_primary_key_id(42); auto result = KeysetHandle::ReadNoSecret(keyset.SerializeAsString()); EXPECT_THAT(result.status(), StatusIs(absl::StatusCode::kFailedPrecondition)); } TEST_F(KeysetHandleTest, ReadNoSecretFailForHidden) { Keyset keyset; Keyset::Key key; AddTinkKey("some_key_type", 42, key, KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PUBLIC, &keyset); for (int i = 0; i < 10; ++i) { AddTinkKey(absl::StrCat("more key type", i), i, key, KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PUBLIC, &keyset); } AddRawKey("some_other_key_type", 10, key, KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PRIVATE, &keyset); for (int i = 0; i < 10; ++i) { AddRawKey(absl::StrCat("more key type", i + 100), i + 100, key, KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PUBLIC, &keyset); } keyset.set_primary_key_id(42); auto result = KeysetHandle::ReadNoSecret(keyset.SerializeAsString()); EXPECT_THAT(result.status(), StatusIs(absl::StatusCode::kFailedPrecondition)); } TEST_F(KeysetHandleTest, ReadNoSecretFailForInvalidString) { auto result = KeysetHandle::ReadNoSecret("bad serialized keyset"); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); } TEST_F(KeysetHandleTest, WriteNoSecret) { Keyset keyset; Keyset::Key key; AddTinkKey("some_key_type", 42, key, KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PUBLIC, &keyset); AddRawKey("some_other_key_type", 711, key, KeyStatusType::ENABLED, KeyData::REMOTE, &keyset); keyset.set_primary_key_id(42); auto handle = TestKeysetHandle::GetKeysetHandle(keyset); std::stringbuf buffer; std::unique_ptr destination_stream(new std::ostream(&buffer)); auto writer = test::DummyKeysetWriter::New(std::move(destination_stream)).value(); auto result = handle->WriteNoSecret(writer.get()); EXPECT_TRUE(result.ok()); } TEST_F(KeysetHandleTest, WriteNoSecretFailForTypeUnknown) { Keyset keyset; Keyset::Key key; AddTinkKey("some_key_type", 42, key, KeyStatusType::ENABLED, KeyData::UNKNOWN_KEYMATERIAL, &keyset); keyset.set_primary_key_id(42); auto handle = TestKeysetHandle::GetKeysetHandle(keyset); std::stringbuf buffer; std::unique_ptr destination_stream(new std::ostream(&buffer)); auto writer = test::DummyKeysetWriter::New(std::move(destination_stream)).value(); auto result = handle->WriteNoSecret(writer.get()); EXPECT_FALSE(result.ok()); } TEST_F(KeysetHandleTest, WriteNoSecretFailForTypeSymmetric) { Keyset keyset; Keyset::Key key; AddTinkKey("some_key_type", 42, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(42); auto handle = TestKeysetHandle::GetKeysetHandle(keyset); std::stringbuf buffer; std::unique_ptr destination_stream(new std::ostream(&buffer)); auto writer = test::DummyKeysetWriter::New(std::move(destination_stream)).value(); auto result = handle->WriteNoSecret(writer.get()); EXPECT_FALSE(result.ok()); } TEST_F(KeysetHandleTest, WriteNoSecretFailForTypeAssymmetricPrivate) { Keyset keyset; Keyset::Key key; AddTinkKey("some_key_type", 42, key, KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PRIVATE, &keyset); keyset.set_primary_key_id(42); auto handle = TestKeysetHandle::GetKeysetHandle(keyset); std::stringbuf buffer; std::unique_ptr destination_stream(new std::ostream(&buffer)); auto writer = test::DummyKeysetWriter::New(std::move(destination_stream)).value(); auto result = handle->WriteNoSecret(writer.get()); EXPECT_FALSE(result.ok()); } TEST_F(KeysetHandleTest, WriteNoSecretFailForHidden) { Keyset keyset; Keyset::Key key; AddTinkKey("some_key_type", 42, key, KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PUBLIC, &keyset); for (int i = 0; i < 10; ++i) { AddTinkKey(absl::StrCat("more key type", i), i, key, KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PUBLIC, &keyset); } AddRawKey("some_other_key_type", 10, key, KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PRIVATE, &keyset); for (int i = 0; i < 10; ++i) { AddRawKey(absl::StrCat("more key type", i + 100), i + 100, key, KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PUBLIC, &keyset); } keyset.set_primary_key_id(42); auto handle = TestKeysetHandle::GetKeysetHandle(keyset); std::stringbuf buffer; std::unique_ptr destination_stream(new std::ostream(&buffer)); auto writer = test::DummyKeysetWriter::New(std::move(destination_stream)).value(); auto result = handle->WriteNoSecret(writer.get()); EXPECT_FALSE(result.ok()); } TEST_F(KeysetHandleTest, GetKeysetInfo) { Keyset keyset; Keyset::Key key; AddTinkKey("some_key_type", 42, key, KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PUBLIC, &keyset); for (int i = 0; i < 10; ++i) { AddTinkKey(absl::StrCat("more key type", i), i, key, KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PUBLIC, &keyset); } AddRawKey("some_other_key_type", 10, key, KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PRIVATE, &keyset); for (int i = 0; i < 10; ++i) { AddRawKey(absl::StrCat("more key type", i + 100), i + 100, key, KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PUBLIC, &keyset); } keyset.set_primary_key_id(42); auto handle = TestKeysetHandle::GetKeysetHandle(keyset); auto keyset_info = handle->GetKeysetInfo(); EXPECT_EQ(keyset.primary_key_id(), keyset_info.primary_key_id()); for (int i = 0; i < keyset.key_size(); ++i) { auto key_info = keyset_info.key_info(i); auto key = keyset.key(i); EXPECT_EQ(key.key_data().type_url(), key_info.type_url()); EXPECT_EQ(key.status(), key_info.status()); EXPECT_EQ(key.key_id(), key_info.key_id()); EXPECT_EQ(key.output_prefix_type(), key_info.output_prefix_type()); } } TEST_F(KeysetHandleTest, GetEntryFromSingleKeyKeyset) { Keyset keyset; Keyset::Key key; AddTinkKey("first_key_type", 11, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(11); std::unique_ptr handle = TestKeysetHandle::GetKeysetHandle(keyset); ASSERT_THAT(handle->Validate(), IsOk()); ASSERT_THAT(*handle, SizeIs(1)); ASSERT_THAT(handle->ValidateAt(0), IsOk()); KeysetHandle::Entry entry = (*handle)[0]; EXPECT_THAT(entry.GetId(), Eq(11)); EXPECT_THAT(entry.GetStatus(), Eq(KeyStatus::kEnabled)); EXPECT_THAT(entry.IsPrimary(), IsTrue()); EXPECT_THAT(entry.GetKey()->GetIdRequirement(), Eq(11)); EXPECT_THAT(entry.GetKey()->GetParameters().HasIdRequirement(), IsTrue()); } TEST_F(KeysetHandleTest, GetEntryFromMultipleKeyKeyset) { Keyset keyset; Keyset::Key key; AddRawKey("first_key_type", 11, key, KeyStatusType::DISABLED, KeyData::SYMMETRIC, &keyset); AddTinkKey("second_key_type", 22, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); AddRawKey("third_key_type", 33, key, KeyStatusType::DESTROYED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(22); std::unique_ptr handle = TestKeysetHandle::GetKeysetHandle(keyset); ASSERT_THAT(handle->Validate(), IsOk()); ASSERT_THAT(*handle, SizeIs(3)); ASSERT_THAT(handle->ValidateAt(0), IsOk()); KeysetHandle::Entry entry0 = (*handle)[0]; EXPECT_THAT(entry0.GetId(), Eq(11)); EXPECT_THAT(entry0.GetStatus(), Eq(KeyStatus::kDisabled)); EXPECT_THAT(entry0.IsPrimary(), IsFalse()); EXPECT_THAT(entry0.GetKey()->GetIdRequirement(), Eq(absl::nullopt)); EXPECT_THAT(entry0.GetKey()->GetParameters().HasIdRequirement(), IsFalse()); ASSERT_THAT(handle->ValidateAt(1), IsOk()); KeysetHandle::Entry entry1 = (*handle)[1]; EXPECT_THAT(entry1.GetId(), Eq(22)); EXPECT_THAT(entry1.GetStatus(), Eq(KeyStatus::kEnabled)); EXPECT_THAT(entry1.IsPrimary(), IsTrue()); EXPECT_THAT(entry1.GetKey()->GetIdRequirement(), Eq(22)); EXPECT_THAT(entry1.GetKey()->GetParameters().HasIdRequirement(), IsTrue()); ASSERT_THAT(handle->ValidateAt(2), IsOk()); KeysetHandle::Entry entry2 = (*handle)[2]; EXPECT_THAT(entry2.GetId(), Eq(33)); EXPECT_THAT(entry2.GetStatus(), Eq(KeyStatus::kDestroyed)); EXPECT_THAT(entry2.IsPrimary(), IsFalse()); EXPECT_THAT(entry2.GetKey()->GetIdRequirement(), Eq(absl::nullopt)); EXPECT_THAT(entry2.GetKey()->GetParameters().HasIdRequirement(), IsFalse()); } TEST_F(KeysetHandleDeathTest, EntryWithIndexOutOfBoundsCrashes) { Keyset keyset; Keyset::Key key; AddTinkKey("first_key_type", 11, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(11); std::unique_ptr handle = TestKeysetHandle::GetKeysetHandle(keyset); ASSERT_THAT(handle->Validate(), IsOk()); ASSERT_THAT(*handle, SizeIs(1)); EXPECT_DEATH_IF_SUPPORTED((*handle)[-1], "Invalid index -1 for keyset of size 1"); EXPECT_DEATH_IF_SUPPORTED((*handle)[1], "Invalid index 1 for keyset of size 1"); } TEST_F(KeysetHandleDeathTest, EntryWithUnknownStatusFails) { Keyset keyset; Keyset::Key key; AddTinkKey("first_key_type", 11, key, KeyStatusType::UNKNOWN_STATUS, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(11); std::unique_ptr handle = TestKeysetHandle::GetKeysetHandle(keyset); ASSERT_THAT(*handle, SizeIs(1)); EXPECT_THAT(handle->Validate(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(handle->ValidateAt(0), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_DEATH_IF_SUPPORTED((*handle)[0], "Invalid key status type."); } TEST_F(KeysetHandleDeathTest, EntryWithUnprintableTypeUrlFails) { Keyset keyset; Keyset::Key key; AddRawKey("invalid key type url with spaces", 11, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(11); std::unique_ptr handle = TestKeysetHandle::GetKeysetHandle(keyset); ASSERT_THAT(*handle, SizeIs(1)); EXPECT_THAT(handle->Validate(), StatusIs(absl::StatusCode::kFailedPrecondition)); EXPECT_THAT(handle->ValidateAt(0), StatusIs(absl::StatusCode::kFailedPrecondition)); EXPECT_DEATH_IF_SUPPORTED((*handle)[0], "Non-printable ASCII character in type URL."); } TEST_F(KeysetHandleTest, GetPrimary) { Keyset keyset; Keyset::Key key; AddTinkKey("first_key_type", 11, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); AddTinkKey("first_key_type", 22, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); AddTinkKey("first_key_type", 33, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(33); std::unique_ptr handle = TestKeysetHandle::GetKeysetHandle(keyset); ASSERT_THAT(handle->Validate(), IsOk()); ASSERT_THAT(*handle, SizeIs(3)); util::StatusOr primary = handle->GetPrimary(); ASSERT_THAT(primary, IsOk()); EXPECT_THAT(primary->GetId(), Eq(33)); EXPECT_THAT(primary->GetStatus(), Eq(KeyStatus::kEnabled)); EXPECT_THAT(primary->IsPrimary(), IsTrue()); } TEST_F(KeysetHandleDeathTest, NonexistentPrimaryFails) { Keyset keyset; Keyset::Key key; AddTinkKey("first_key_type", 11, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); std::unique_ptr handle = TestKeysetHandle::GetKeysetHandle(keyset); ASSERT_THAT(*handle, SizeIs(1)); EXPECT_THAT(handle->Validate(), StatusIs(absl::StatusCode::kFailedPrecondition)); EXPECT_DEATH_IF_SUPPORTED(handle->GetPrimary(), "Keyset has no primary"); } TEST_F(KeysetHandleDeathTest, MultiplePrimariesFail) { Keyset keyset; Keyset::Key key; AddTinkKey("first_key_type", 11, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); AddTinkKey("second_key_type", 11, key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); // Multiple primaries since two distinct keys share the same key id. keyset.set_primary_key_id(11); std::unique_ptr handle = TestKeysetHandle::GetKeysetHandle(keyset); ASSERT_THAT(*handle, SizeIs(2)); EXPECT_THAT(handle->Validate(), StatusIs(absl::StatusCode::kFailedPrecondition)); EXPECT_DEATH_IF_SUPPORTED(handle->GetPrimary(), "Keyset has more than one primary"); } TEST_F(KeysetHandleDeathTest, GetDisabledPrimaryFails) { Keyset keyset; Keyset::Key key; AddTinkKey("first_key_type", 11, key, KeyStatusType::DISABLED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(11); std::unique_ptr handle = TestKeysetHandle::GetKeysetHandle(keyset); ASSERT_THAT(*handle, SizeIs(1)); EXPECT_THAT(handle->Validate(), StatusIs(absl::StatusCode::kFailedPrecondition)); EXPECT_DEATH_IF_SUPPORTED(handle->GetPrimary(), "Keyset has primary that is not enabled"); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/core/keyset_manager.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/keyset_manager.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/synchronization/mutex.h" #include "tink/internal/key_gen_configuration_impl.h" #include "tink/key_gen_configuration.h" #include "tink/keyset_handle.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::crypto::tink::util::Enums; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; using google::crypto::tink::KeyStatusType; using google::crypto::tink::KeyTemplate; // static StatusOr> KeysetManager::New( const KeyTemplate& key_template) { auto manager = absl::make_unique(); auto rotate_result = manager->Rotate(key_template); if (!rotate_result.ok()) return rotate_result.status(); return std::move(manager); } // static StatusOr> KeysetManager::New( const KeysetHandle& keyset_handle) { auto manager = absl::make_unique(); absl::MutexLock lock(&manager->keyset_mutex_); *manager->keyset_ = keyset_handle.get_keyset(); return std::move(manager); } std::unique_ptr KeysetManager::GetKeysetHandle() { absl::MutexLock lock(&keyset_mutex_); std::unique_ptr handle(new KeysetHandle(keyset_)); return handle; } StatusOr KeysetManager::Add(const KeyTemplate& key_template) { return Add(key_template, false); } StatusOr KeysetManager::Add( const google::crypto::tink::KeyTemplate& key_template, bool as_primary) { KeyGenConfiguration config; Status status = internal::KeyGenConfigurationImpl::SetGlobalRegistryMode(config); if (!status.ok()) { return status; } absl::MutexLock lock(&keyset_mutex_); return KeysetHandle::AddToKeyset(key_template, as_primary, config, keyset_.get()); } StatusOr KeysetManager::Rotate(const KeyTemplate& key_template) { return Add(key_template, true); } Status KeysetManager::Enable(uint32_t key_id) { absl::MutexLock lock(&keyset_mutex_); for (auto& key : *(keyset_->mutable_key())) { if (key.key_id() == key_id) { if (key.status() != KeyStatusType::DISABLED && key.status() != KeyStatusType::ENABLED) { return ToStatusF(absl::StatusCode::kInvalidArgument, "Cannot enable key with key_id %u and status %s.", key_id, Enums::KeyStatusName(key.status())); } key.set_status(KeyStatusType::ENABLED); return util::OkStatus(); } } return ToStatusF(absl::StatusCode::kNotFound, "No key with key_id %u found in the keyset.", key_id); } Status KeysetManager::Disable(uint32_t key_id) { absl::MutexLock lock(&keyset_mutex_); if (keyset_->primary_key_id() == key_id) { return ToStatusF(absl::StatusCode::kInvalidArgument, "Cannot disable primary key (key_id %u).", key_id); } for (auto& key : *(keyset_->mutable_key())) { if (key.key_id() == key_id) { if (key.status() != KeyStatusType::DISABLED && key.status() != KeyStatusType::ENABLED) { return ToStatusF(absl::StatusCode::kInvalidArgument, "Cannot disable key with key_id %u and status %s.", key_id, Enums::KeyStatusName(key.status())); } key.set_status(KeyStatusType::DISABLED); return util::OkStatus(); } } return ToStatusF(absl::StatusCode::kNotFound, "No key with key_id %u found in the keyset.", key_id); } Status KeysetManager::Delete(uint32_t key_id) { absl::MutexLock lock(&keyset_mutex_); if (keyset_->primary_key_id() == key_id) { return ToStatusF(absl::StatusCode::kInvalidArgument, "Cannot delete primary key (key_id %u).", key_id); } auto key_field = keyset_->mutable_key(); for (auto key_iter = key_field->begin(); key_iter != key_field->end(); key_iter++) { auto key = *key_iter; if (key.key_id() == key_id) { keyset_->mutable_key()->erase(key_iter); return util::OkStatus(); } } return ToStatusF(absl::StatusCode::kNotFound, "No key with key_id %u found in the keyset.", key_id); } Status KeysetManager::Destroy(uint32_t key_id) { absl::MutexLock lock(&keyset_mutex_); if (keyset_->primary_key_id() == key_id) { return ToStatusF(absl::StatusCode::kInvalidArgument, "Cannot destroy primary key (key_id %u).", key_id); } for (auto& key : *(keyset_->mutable_key())) { if (key.key_id() == key_id) { if (key.status() != KeyStatusType::DISABLED && key.status() != KeyStatusType::DESTROYED && key.status() != KeyStatusType::ENABLED) { return ToStatusF(absl::StatusCode::kInvalidArgument, "Cannot destroy key with key_id %u and status %s.", key_id, Enums::KeyStatusName(key.status())); } key.clear_key_data(); key.set_status(KeyStatusType::DESTROYED); return util::OkStatus(); } } return ToStatusF(absl::StatusCode::kNotFound, "No key with key_id %u found in the keyset.", key_id); } Status KeysetManager::SetPrimary(uint32_t key_id) { absl::MutexLock lock(&keyset_mutex_); for (auto& key : keyset_->key()) { if (key.key_id() == key_id) { if (key.status() != KeyStatusType::ENABLED) { return ToStatusF(absl::StatusCode::kInvalidArgument, "The candidate for the primary key must be ENABLED" " (key_id %u).", key_id); } keyset_->set_primary_key_id(key_id); return util::OkStatus(); } } return ToStatusF(absl::StatusCode::kNotFound, "No key with key_id %u found in the keyset.", key_id); } int KeysetManager::KeyCount() const { absl::MutexLock lock(&keyset_mutex_); return keyset_->key_size(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/core/keyset_manager_test.cc ================================================ // Copyright 2017 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/keyset_manager.h" #include #include #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/aead/aead_config.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/keyset_handle.h" #include "tink/util/test_keyset_handle.h" #include "proto/aes_gcm.pb.h" #include "proto/tink.pb.h" using google::crypto::tink::AesGcmKeyFormat; using google::crypto::tink::KeyData; using google::crypto::tink::KeyStatusType; using google::crypto::tink::KeyTemplate; using google::crypto::tink::OutputPrefixType; namespace crypto { namespace tink { class KeysetManagerTest : public ::testing::Test { protected: void SetUp() override { auto status = AeadConfig::Register(); ASSERT_TRUE(status.ok()) << status; } void TearDown() override {} }; TEST_F(KeysetManagerTest, testBasicOperations) { AesGcmKeyFormat key_format; key_format.set_key_size(16); KeyTemplate key_template; key_template.set_type_url(AesGcmKeyManager().get_key_type()); key_template.set_output_prefix_type(OutputPrefixType::TINK); key_template.set_value(key_format.SerializeAsString()); // Create a keyset manager with a single key. auto new_result = KeysetManager::New(key_template); EXPECT_TRUE(new_result.ok()) << new_result.status(); auto keyset_manager = std::move(new_result.value()); EXPECT_EQ(1, keyset_manager->KeyCount()); // Verify the keyset. auto keyset = TestKeysetHandle::GetKeyset(*(keyset_manager->GetKeysetHandle())); EXPECT_EQ(1, keyset.key().size()); auto key_id_0 = keyset.key(0).key_id(); EXPECT_EQ(key_id_0, keyset.primary_key_id()); EXPECT_EQ(KeyStatusType::ENABLED, keyset.key(0).status()); EXPECT_EQ(OutputPrefixType::TINK, keyset.key(0).output_prefix_type()); EXPECT_EQ(AesGcmKeyManager().get_key_type(), keyset.key(0).key_data().type_url()); EXPECT_EQ(KeyData::SYMMETRIC, keyset.key(0).key_data().key_material_type()); // Add another key. key_template.set_output_prefix_type(OutputPrefixType::RAW); auto add_result = keyset_manager->Add(key_template); EXPECT_TRUE(add_result.ok()) << add_result.status(); EXPECT_EQ(2, keyset_manager->KeyCount()); auto key_id_1 = add_result.value(); keyset = TestKeysetHandle::GetKeyset(*(keyset_manager->GetKeysetHandle())); EXPECT_EQ(2, keyset.key().size()); EXPECT_EQ(key_id_0, keyset.primary_key_id()); EXPECT_FALSE(keyset.key(0).key_data().value() == keyset.key(1).key_data().value()); EXPECT_EQ(KeyStatusType::ENABLED, keyset.key(1).status()); EXPECT_EQ(OutputPrefixType::RAW, keyset.key(1).output_prefix_type()); EXPECT_EQ(AesGcmKeyManager().get_key_type(), keyset.key(1).key_data().type_url()); EXPECT_EQ(KeyData::SYMMETRIC, keyset.key(1).key_data().key_material_type()); // And another one, via rotation. key_template.set_output_prefix_type(OutputPrefixType::LEGACY); auto rotate_result = keyset_manager->Rotate(key_template); EXPECT_TRUE(rotate_result.ok()) << add_result.status(); EXPECT_EQ(3, keyset_manager->KeyCount()); auto key_id_2 = rotate_result.value(); keyset = TestKeysetHandle::GetKeyset(*(keyset_manager->GetKeysetHandle())); EXPECT_EQ(3, keyset.key().size()); EXPECT_EQ(key_id_2, keyset.primary_key_id()); EXPECT_FALSE(keyset.key(0).key_data().value() == keyset.key(2).key_data().value()); EXPECT_FALSE(keyset.key(1).key_data().value() == keyset.key(2).key_data().value()); EXPECT_EQ(KeyStatusType::ENABLED, keyset.key(2).status()); EXPECT_EQ(OutputPrefixType::LEGACY, keyset.key(2).output_prefix_type()); EXPECT_EQ(AesGcmKeyManager().get_key_type(), keyset.key(2).key_data().type_url()); EXPECT_EQ(KeyData::SYMMETRIC, keyset.key(2).key_data().key_material_type()); // Change the primary. auto status = keyset_manager->SetPrimary(key_id_1); EXPECT_TRUE(status.ok()) << status; keyset = TestKeysetHandle::GetKeyset(*(keyset_manager->GetKeysetHandle())); EXPECT_EQ(3, keyset.key().size()); EXPECT_EQ(3, keyset_manager->KeyCount()); EXPECT_EQ(key_id_1, keyset.primary_key_id()); // Clone a keyset via the manager, and check equality. auto keyset_manager_2 = std::move(KeysetManager::New(*keyset_manager->GetKeysetHandle()).value()); auto keyset_2 = TestKeysetHandle::GetKeyset(*(keyset_manager_2->GetKeysetHandle())); EXPECT_EQ(keyset.SerializeAsString(), keyset_2.SerializeAsString()); // Disable a key, and try to set it as primary. EXPECT_EQ(KeyStatusType::ENABLED, keyset.key(2).status()); status = keyset_manager->Disable(key_id_2); EXPECT_TRUE(status.ok()) << status; EXPECT_EQ(3, keyset_manager->KeyCount()); keyset = TestKeysetHandle::GetKeyset(*(keyset_manager->GetKeysetHandle())); EXPECT_EQ(KeyStatusType::DISABLED, keyset.key(2).status()); status = keyset_manager->SetPrimary(key_id_2); EXPECT_FALSE(status.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, status.code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "must be ENABLED", std::string(status.message())); keyset = TestKeysetHandle::GetKeyset(*(keyset_manager->GetKeysetHandle())); EXPECT_EQ(key_id_1, keyset.primary_key_id()); // Enable ENABLED key, disable a DISABLED one. EXPECT_EQ(KeyStatusType::ENABLED, keyset.key(1).status()); status = keyset_manager->Enable(key_id_1); EXPECT_TRUE(status.ok()) << status; keyset = TestKeysetHandle::GetKeyset(*(keyset_manager->GetKeysetHandle())); EXPECT_EQ(KeyStatusType::ENABLED, keyset.key(1).status()); EXPECT_EQ(KeyStatusType::DISABLED, keyset.key(2).status()); status = keyset_manager->Disable(key_id_2); EXPECT_TRUE(status.ok()) << status; keyset = TestKeysetHandle::GetKeyset(*(keyset_manager->GetKeysetHandle())); EXPECT_EQ(KeyStatusType::DISABLED, keyset.key(2).status()); // Enable the disabled key, then destroy it, and try to re-enable. EXPECT_EQ(KeyStatusType::DISABLED, keyset.key(2).status()); status = keyset_manager->Enable(key_id_2); EXPECT_TRUE(status.ok()) << status; keyset = TestKeysetHandle::GetKeyset(*(keyset_manager->GetKeysetHandle())); EXPECT_EQ(KeyStatusType::ENABLED, keyset.key(2).status()); EXPECT_TRUE(keyset.key(2).has_key_data()); status = keyset_manager->Destroy(key_id_2); EXPECT_TRUE(status.ok()) << status; EXPECT_EQ(3, keyset_manager->KeyCount()); keyset = TestKeysetHandle::GetKeyset(*(keyset_manager->GetKeysetHandle())); EXPECT_EQ(KeyStatusType::DESTROYED, keyset.key(2).status()); EXPECT_FALSE(keyset.key(2).has_key_data()); status = keyset_manager->Enable(key_id_2); EXPECT_FALSE(status.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, status.code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "Cannot enable", std::string(status.message())); keyset = TestKeysetHandle::GetKeyset(*(keyset_manager->GetKeysetHandle())); EXPECT_EQ(KeyStatusType::DESTROYED, keyset.key(2).status()); EXPECT_EQ(key_id_1, keyset.primary_key_id()); // Delete the destroyed key, then try to destroy and delete it again. status = keyset_manager->Delete(key_id_2); EXPECT_TRUE(status.ok()) << status; EXPECT_EQ(2, keyset_manager->KeyCount()); keyset = TestKeysetHandle::GetKeyset(*(keyset_manager->GetKeysetHandle())); EXPECT_EQ(2, keyset.key().size()); status = keyset_manager->Destroy(key_id_2); EXPECT_EQ(absl::StatusCode::kNotFound, status.code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "No key with key_id", std::string(status.message())); status = keyset_manager->Delete(key_id_2); EXPECT_EQ(absl::StatusCode::kNotFound, status.code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "No key with key_id", std::string(status.message())); // Try disabling/destroying/deleting the primary key. keyset = TestKeysetHandle::GetKeyset(*(keyset_manager->GetKeysetHandle())); EXPECT_EQ(key_id_1, keyset.primary_key_id()); status = keyset_manager->Disable(key_id_1); EXPECT_EQ(absl::StatusCode::kInvalidArgument, status.code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "Cannot disable primary", std::string(status.message())); status = keyset_manager->Destroy(key_id_1); EXPECT_EQ(absl::StatusCode::kInvalidArgument, status.code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "Cannot destroy primary", std::string(status.message())); status = keyset_manager->Delete(key_id_1); EXPECT_EQ(absl::StatusCode::kInvalidArgument, status.code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "Cannot delete primary", std::string(status.message())); keyset = TestKeysetHandle::GetKeyset(*(keyset_manager->GetKeysetHandle())); EXPECT_EQ(key_id_1, keyset.primary_key_id()); // Delete the first key, then try to set it as primary. status = keyset_manager->Delete(key_id_0); EXPECT_TRUE(status.ok()) << status; keyset = TestKeysetHandle::GetKeyset(*(keyset_manager->GetKeysetHandle())); EXPECT_EQ(1, keyset.key().size()); EXPECT_EQ(key_id_1, keyset.key(0).key_id()); status = keyset_manager->SetPrimary(key_id_0); EXPECT_FALSE(status.ok()); EXPECT_EQ(absl::StatusCode::kNotFound, status.code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "No key with key_id", std::string(status.message())); EXPECT_EQ(1, keyset_manager->KeyCount()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/core/kms_clients.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/kms_clients.h" #include #include #include #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" #include "tink/kms_client.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { using crypto::tink::util::Status; using crypto::tink::util::StatusOr; // static KmsClients& KmsClients::GlobalInstance() { static KmsClients* instance = new KmsClients(); return *instance; } Status KmsClients::LocalAdd(std::unique_ptr kms_client) { if (kms_client == nullptr) { return Status(absl::StatusCode::kInvalidArgument, "kms_client must be non-null."); } absl::MutexLock lock(&clients_mutex_); clients_.push_back(std::move(kms_client)); return util::OkStatus(); } StatusOr KmsClients::LocalGet(absl::string_view key_uri) { if (key_uri.empty()) { return Status(absl::StatusCode::kInvalidArgument, "key_uri must be non-empty."); } absl::MutexLock lock(&clients_mutex_); for (const auto& client : clients_) { if (client->DoesSupport(key_uri)) return client.get(); } return ToStatusF(absl::StatusCode::kNotFound, "no KmsClient found for key '%s'.", std::string(key_uri).c_str()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/core/kms_clients_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/kms_clients.h" #include #include #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/kms_client.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace { using crypto::tink::test::IsOk; using crypto::tink::test::StatusIs; using crypto::tink::test::DummyKmsClient; TEST(KmsClientsTest, Empty) { auto client_result = KmsClients::Get("some uri"); EXPECT_THAT(client_result.status(), StatusIs(absl::StatusCode::kNotFound)); client_result = KmsClients::Get(""); EXPECT_THAT(client_result.status(), StatusIs(absl::StatusCode::kInvalidArgument)); auto status = KmsClients::Add(nullptr); EXPECT_THAT(status, StatusIs(absl::StatusCode::kInvalidArgument)); } struct UriData { std::string prefix; std::string uri; }; TEST(KmsClientsTest, AddAndGet) { UriData data_1 = {"prefix1", "prefix1:uri1"}; UriData data_2 = {"prefix1", "prefix1:uri2"}; UriData data_3 = {"prefix2", "prefix2:uri42"}; // Add client for data_1, and verify it. auto status = KmsClients::Add( absl::make_unique(data_1.prefix, data_1.uri)); EXPECT_THAT(status, IsOk()); auto client_result = KmsClients::Get(data_1.uri); EXPECT_THAT(client_result, IsOk()); EXPECT_TRUE(client_result.value()->DoesSupport(data_1.uri)); EXPECT_FALSE(client_result.value()->DoesSupport(data_2.uri)); // Verify there is no client for data_2. client_result = KmsClients::Get(data_2.uri); EXPECT_THAT(client_result.status(), StatusIs(absl::StatusCode::kNotFound)); // Add client for data_2, and verify it. status = KmsClients::Add( absl::make_unique(data_2.prefix, data_2.uri)); EXPECT_THAT(status, IsOk()); client_result = KmsClients::Get(data_2.uri); EXPECT_THAT(client_result, IsOk()); EXPECT_TRUE(client_result.value()->DoesSupport(data_2.uri)); EXPECT_FALSE(client_result.value()->DoesSupport(data_1.uri)); // Verify there is no client for data_3. client_result = KmsClients::Get(data_3.uri); EXPECT_THAT(client_result.status(), StatusIs(absl::StatusCode::kNotFound)); // Add client for data_3, and verify it. status = KmsClients::Add( absl::make_unique(data_3.prefix, data_3.uri)); EXPECT_THAT(status, IsOk()); client_result = KmsClients::Get(data_3.uri); EXPECT_THAT(client_result, IsOk()); EXPECT_TRUE(client_result.value()->DoesSupport(data_3.uri)); EXPECT_FALSE(client_result.value()->DoesSupport(data_2.uri)); EXPECT_FALSE(client_result.value()->DoesSupport(data_1.uri)); // Verify that clients for data_1 and data_2 are still present. client_result = KmsClients::Get(data_1.uri); EXPECT_THAT(client_result, IsOk()); EXPECT_TRUE(client_result.value()->DoesSupport(data_1.uri)); EXPECT_FALSE(client_result.value()->DoesSupport(data_2.uri)); client_result = KmsClients::Get(data_2.uri); EXPECT_THAT(client_result, IsOk()); EXPECT_TRUE(client_result.value()->DoesSupport(data_2.uri)); EXPECT_FALSE(client_result.value()->DoesSupport(data_1.uri)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/core/partial_key_access_token_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include "tink/partial_key_access_token.h" #include "gtest/gtest.h" #include "absl/base/attributes.h" #include "tink/partial_key_access.h" namespace crypto { namespace tink { namespace { TEST(PartialKeyAccessTokenTest, CopyConstructor) { PartialKeyAccessToken token = GetPartialKeyAccess(); PartialKeyAccessToken copy ABSL_ATTRIBUTE_UNUSED(token); } TEST(PartialKeyAccessTokenTest, CopyAssignment) { PartialKeyAccessToken token = GetPartialKeyAccess(); PartialKeyAccessToken copy ABSL_ATTRIBUTE_UNUSED = token; } TEST(PartialKeyAccessTokenTest, MoveConstructor) { PartialKeyAccessToken token = GetPartialKeyAccess(); PartialKeyAccessToken move ABSL_ATTRIBUTE_UNUSED(std::move(token)); } TEST(PartialKeyAccessTokenTest, MoveAssignment) { PartialKeyAccessToken token = GetPartialKeyAccess(); PartialKeyAccessToken move ABSL_ATTRIBUTE_UNUSED = std::move(token); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/core/primitive_set_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/primitive_set.h" #include #include #include #include // NOLINT(build/c++11) #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/crypto_format.h" #include "tink/keyderivation/keyset_deriver.h" #include "tink/mac.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" using ::crypto::tink::test::DummyMac; using ::crypto::tink::test::IsOk; using ::google::crypto::tink::KeysetInfo; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::SizeIs; using ::testing::UnorderedElementsAreArray; namespace crypto { namespace tink { namespace { class PrimitiveSetTest : public ::testing::Test {}; void add_primitives(PrimitiveSet* primitive_set, int key_id_offset, int primitives_count) { for (int i = 0; i < primitives_count; i++) { int key_id = key_id_offset + i; KeysetInfo::KeyInfo key_info; key_info.set_output_prefix_type(OutputPrefixType::TINK); key_info.set_key_id(key_id); key_info.set_status(KeyStatusType::ENABLED); std::unique_ptr mac(new DummyMac("dummy MAC")); auto add_result = primitive_set->AddPrimitive(std::move(mac), key_info); EXPECT_TRUE(add_result.ok()) << add_result.status(); } } void add_primitives(PrimitiveSet::Builder* primitive_set_builder, int key_id_offset, int primitives_count) { for (int i = 0; i < primitives_count; i++) { int key_id = key_id_offset + i; KeysetInfo::KeyInfo key_info; key_info.set_output_prefix_type(OutputPrefixType::TINK); key_info.set_key_id(key_id); key_info.set_status(KeyStatusType::ENABLED); std::unique_ptr mac(new DummyMac("dummy MAC")); primitive_set_builder->AddPrimitive(std::move(mac), key_info); } } void access_primitives(PrimitiveSet* primitive_set, int key_id_offset, int primitives_count) { for (int i = 0; i < primitives_count; i++) { int key_id = key_id_offset + i; KeysetInfo::KeyInfo key_info; key_info.set_output_prefix_type(OutputPrefixType::TINK); key_info.set_key_id(key_id); key_info.set_status(KeyStatusType::ENABLED); std::string prefix = CryptoFormat::GetOutputPrefix(key_info).value(); auto get_result = primitive_set->get_primitives(prefix); EXPECT_TRUE(get_result.ok()) << get_result.status(); EXPECT_GE(get_result.value()->size(), 1); } } TEST_F(PrimitiveSetTest, ConcurrentOperations) { PrimitiveSet::Builder mac_set_builder; int offset_a = 100; int offset_b = 150; int count = 100; // Add some primitives. // See go/totw/133 on why we use a lambda here. std::thread add_primitives_a( [&]() { add_primitives(&mac_set_builder, offset_a, count); }); std::thread add_primitives_b( [&]() { add_primitives(&mac_set_builder, offset_b, count); }); add_primitives_a.join(); add_primitives_b.join(); auto mac_set_result = std::move(mac_set_builder).Build(); ASSERT_TRUE(mac_set_result.ok()) << mac_set_result.status(); PrimitiveSet mac_set = std::move(mac_set_result.value()); // Access primitives. std::thread access_primitives_a(access_primitives, &mac_set, offset_a, count); std::thread access_primitives_b(access_primitives, &mac_set, offset_b, count); access_primitives_a.join(); access_primitives_b.join(); // Verify the common key ids added by both threads. for (int key_id = offset_a; key_id < offset_b + count; key_id++) { KeysetInfo::KeyInfo key_info; key_info.set_output_prefix_type(OutputPrefixType::TINK); key_info.set_key_id(key_id); key_info.set_status(KeyStatusType::ENABLED); std::string prefix = CryptoFormat::GetOutputPrefix(key_info).value(); auto get_result = mac_set.get_primitives(prefix); EXPECT_TRUE(get_result.ok()) << get_result.status(); auto macs = get_result.value(); if (key_id >= offset_b && key_id < offset_a + count) { EXPECT_EQ(2, macs->size()); // overlapping key_id range } else { EXPECT_EQ(1, macs->size()); } } } TEST_F(PrimitiveSetTest, Basic) { std::string mac_name_1 = "MAC#1"; std::unique_ptr mac_1(new DummyMac(mac_name_1)); std::string mac_name_2 = "MAC#2"; std::unique_ptr mac_2(new DummyMac(mac_name_2)); std::string mac_name_3 = "MAC#3"; std::unique_ptr mac_3(new DummyMac(mac_name_3)); std::string mac_name_4 = "MAC#3"; std::unique_ptr mac_4(new DummyMac(mac_name_4)); std::string mac_name_5 = "MAC#3"; std::unique_ptr mac_5(new DummyMac(mac_name_5)); std::string mac_name_6 = "MAC#3"; std::unique_ptr mac_6(new DummyMac(mac_name_6)); uint32_t key_id_1 = 1234543; KeysetInfo::KeyInfo key_1; key_1.set_output_prefix_type(OutputPrefixType::TINK); key_1.set_key_id(key_id_1); key_1.set_status(KeyStatusType::ENABLED); uint32_t key_id_2 = 7213743; KeysetInfo::KeyInfo key_2; key_2.set_output_prefix_type(OutputPrefixType::LEGACY); key_2.set_key_id(key_id_2); key_2.set_status(KeyStatusType::ENABLED); uint32_t key_id_3 = key_id_2; // same id as key_2 KeysetInfo::KeyInfo key_3; key_3.set_output_prefix_type(OutputPrefixType::TINK); key_3.set_key_id(key_id_3); key_3.set_status(KeyStatusType::ENABLED); uint32_t key_id_4 = 947327; KeysetInfo::KeyInfo key_4; key_4.set_output_prefix_type(OutputPrefixType::RAW); key_4.set_key_id(key_id_4); key_4.set_status(KeyStatusType::ENABLED); uint32_t key_id_5 = 529472; KeysetInfo::KeyInfo key_5; key_5.set_output_prefix_type(OutputPrefixType::RAW); key_5.set_key_id(key_id_5); key_5.set_status(KeyStatusType::ENABLED); uint32_t key_id_6 = key_id_1; // same id as key_1 KeysetInfo::KeyInfo key_6; key_6.set_output_prefix_type(OutputPrefixType::TINK); key_6.set_key_id(key_id_6); key_6.set_status(KeyStatusType::ENABLED); PrimitiveSet::Builder primitive_set_builder; // Add all the primitives. auto primitive_set_result = PrimitiveSet::Builder{} .AddPrimitive(std::move(mac_1), key_1) .AddPrimitive(std::move(mac_2), key_2) .AddPrimaryPrimitive(std::move(mac_3), key_3) .AddPrimitive(std::move(mac_4), key_4) .AddPrimitive(std::move(mac_5), key_5) .AddPrimitive(std::move(mac_6), key_6) .Build(); ASSERT_TRUE(primitive_set_result.ok()) << primitive_set_result.status(); PrimitiveSet primitive_set = std::move(primitive_set_result.value()); std::string data = "some data"; { // Check the primary. auto primary = primitive_set.get_primary(); EXPECT_FALSE(primary == nullptr); EXPECT_EQ(KeyStatusType::ENABLED, primary->get_status()); EXPECT_EQ(DummyMac(mac_name_3).ComputeMac(data).value(), primary->get_primitive().ComputeMac(data).value()); } { // Check raw primitives. auto& primitives = *(primitive_set.get_raw_primitives().value()); EXPECT_EQ(2, primitives.size()); EXPECT_EQ(DummyMac(mac_name_4).ComputeMac(data).value(), primitives[0]->get_primitive().ComputeMac(data).value()); EXPECT_EQ(KeyStatusType::ENABLED, primitives[0]->get_status()); EXPECT_EQ(key_4.key_id(), primitives[0]->get_key_id()); EXPECT_EQ(OutputPrefixType::RAW, primitives[0]->get_output_prefix_type()); EXPECT_EQ(DummyMac(mac_name_5).ComputeMac(data).value(), primitives[1]->get_primitive().ComputeMac(data).value()); EXPECT_EQ(KeyStatusType::ENABLED, primitives[1]->get_status()); EXPECT_EQ(key_5.key_id(), primitives[1]->get_key_id()); EXPECT_EQ(OutputPrefixType::RAW, primitives[1]->get_output_prefix_type()); } { // Check Tink primitives. std::string prefix = CryptoFormat::GetOutputPrefix(key_1).value(); auto& primitives = *(primitive_set.get_primitives(prefix).value()); EXPECT_EQ(2, primitives.size()); EXPECT_EQ(DummyMac(mac_name_1).ComputeMac(data).value(), primitives[0]->get_primitive().ComputeMac(data).value()); EXPECT_EQ(KeyStatusType::ENABLED, primitives[0]->get_status()); EXPECT_EQ(key_1.key_id(), primitives[0]->get_key_id()); EXPECT_EQ(OutputPrefixType::TINK, primitives[0]->get_output_prefix_type()); EXPECT_EQ(DummyMac(mac_name_6).ComputeMac(data).value(), primitives[1]->get_primitive().ComputeMac(data).value()); EXPECT_EQ(KeyStatusType::ENABLED, primitives[1]->get_status()); EXPECT_EQ(key_1.key_id(), primitives[1]->get_key_id()); EXPECT_EQ(OutputPrefixType::TINK, primitives[1]->get_output_prefix_type()); } { // Check another Tink primitive. std::string prefix = CryptoFormat::GetOutputPrefix(key_3).value(); auto& primitives = *(primitive_set.get_primitives(prefix).value()); EXPECT_EQ(1, primitives.size()); EXPECT_EQ(DummyMac(mac_name_3).ComputeMac(data).value(), primitives[0]->get_primitive().ComputeMac(data).value()); EXPECT_EQ(KeyStatusType::ENABLED, primitives[0]->get_status()); EXPECT_EQ(key_3.key_id(), primitives[0]->get_key_id()); EXPECT_EQ(OutputPrefixType::TINK, primitives[0]->get_output_prefix_type()); } { // Check legacy primitive. std::string prefix = CryptoFormat::GetOutputPrefix(key_2).value(); auto& primitives = *(primitive_set.get_primitives(prefix).value()); EXPECT_EQ(1, primitives.size()); EXPECT_EQ(DummyMac(mac_name_2).ComputeMac(data).value(), primitives[0]->get_primitive().ComputeMac(data).value()); EXPECT_EQ(KeyStatusType::ENABLED, primitives[0]->get_status()); EXPECT_EQ(key_2.key_id(), primitives[0]->get_key_id()); EXPECT_EQ(OutputPrefixType::LEGACY, primitives[0]->get_output_prefix_type()); } } TEST_F(PrimitiveSetTest, PrimaryKeyWithIdCollisions) { std::string mac_name_1 = "MAC#1"; std::string mac_name_2 = "MAC#2"; uint32_t key_id_1 = 1234543; KeysetInfo::KeyInfo key_info_1; key_info_1.set_key_id(key_id_1); key_info_1.set_status(KeyStatusType::ENABLED); uint32_t key_id_2 = key_id_1; // same id as key_2 KeysetInfo::KeyInfo key_info_2; key_info_2.set_key_id(key_id_2); key_info_2.set_status(KeyStatusType::ENABLED); { // Test with RAW-keys. std::unique_ptr mac_1(new DummyMac(mac_name_1)); std::unique_ptr mac_2(new DummyMac(mac_name_2)); key_info_1.set_output_prefix_type(OutputPrefixType::RAW); key_info_2.set_output_prefix_type(OutputPrefixType::RAW); PrimitiveSet::Builder primitive_set_builder; // Add the first primitive, and set it as primary. primitive_set_builder.AddPrimaryPrimitive(std::move(mac_1), key_info_1); auto primitive_set_result = std::move(primitive_set_builder).Build(); ASSERT_TRUE(primitive_set_result.ok()) << primitive_set_result.status(); PrimitiveSet primitive_set = std::move(primitive_set_result.value()); std::string identifier = ""; const auto& primitives = *(primitive_set.get_primitives(identifier).value()); EXPECT_EQ(1, primitives.size()); EXPECT_EQ(primitive_set.get_primary(), primitives[0].get()); } { // Test with TINK-keys. std::unique_ptr mac_1(new DummyMac(mac_name_1)); std::unique_ptr mac_2(new DummyMac(mac_name_2)); key_info_1.set_output_prefix_type(OutputPrefixType::TINK); key_info_2.set_output_prefix_type(OutputPrefixType::TINK); PrimitiveSet::Builder primitive_set_builder; // Add the first primitive, and set it as primary. primitive_set_builder.AddPrimaryPrimitive(std::move(mac_1), key_info_1); auto primitive_set_result = std::move(primitive_set_builder).Build(); ASSERT_TRUE(primitive_set_result.ok()) << primitive_set_result.status(); PrimitiveSet primitive_set = std::move(primitive_set_result.value()); std::string identifier = CryptoFormat::GetOutputPrefix(key_info_1).value(); const auto& primitives = *(primitive_set.get_primitives(identifier).value()); EXPECT_EQ(1, primitives.size()); EXPECT_EQ(primitive_set.get_primary(), primitives[0].get()); } { // Test with LEGACY-keys. std::unique_ptr mac_1(new DummyMac(mac_name_1)); std::unique_ptr mac_2(new DummyMac(mac_name_2)); key_info_1.set_output_prefix_type(OutputPrefixType::LEGACY); key_info_2.set_output_prefix_type(OutputPrefixType::LEGACY); PrimitiveSet::Builder primitive_set_builder; // Add the first primitive, and set it as primary. primitive_set_builder.AddPrimaryPrimitive(std::move(mac_1), key_info_1); auto primitive_set_result = std::move(primitive_set_builder).Build(); ASSERT_TRUE(primitive_set_result.ok()) << primitive_set_result.status(); PrimitiveSet primitive_set = std::move(primitive_set_result.value()); std::string identifier = CryptoFormat::GetOutputPrefix(key_info_1).value(); const auto& primitives = *(primitive_set.get_primitives(identifier).value()); EXPECT_EQ(1, primitives.size()); EXPECT_EQ(primitive_set.get_primary(), primitives[0].get()); } } TEST_F(PrimitiveSetTest, DisabledKey) { std::string mac_name_1 = "MAC#1"; std::unique_ptr mac_1(new DummyMac(mac_name_1)); uint32_t key_id_1 = 1234543; KeysetInfo::KeyInfo key_info_1; key_info_1.set_output_prefix_type(OutputPrefixType::TINK); key_info_1.set_key_id(key_id_1); key_info_1.set_status(KeyStatusType::DISABLED); // Add all the primitives. auto add_primitive_result = PrimitiveSet::Builder{} .AddPrimitive(std::move(mac_1), key_info_1) .Build(); EXPECT_FALSE(add_primitive_result.ok()); } KeysetInfo::KeyInfo CreateKey(uint32_t key_id, OutputPrefixType output_prefix_type, KeyStatusType key_status, absl::string_view type_url) { KeysetInfo::KeyInfo key_info; key_info.set_output_prefix_type(output_prefix_type); key_info.set_key_id(key_id); key_info.set_status(key_status); std::string type_url_str(type_url); key_info.set_type_url(type_url_str); return key_info; } // Struct to hold MAC, Id and type_url. struct MacIdAndTypeUrl { std::string mac; std::string id; std::string type_url; }; bool operator==(const MacIdAndTypeUrl& first, const MacIdAndTypeUrl& other) { return first.mac == other.mac && first.id == other.id && first.type_url == other.type_url; } TEST_F(PrimitiveSetTest, GetAll) { auto pset_result = PrimitiveSet::Builder{} .AddPrimitive( absl::make_unique("MAC1"), CreateKey(0x01010101, OutputPrefixType::TINK, KeyStatusType::ENABLED, /*type_url=*/ "type.googleapis.com/google.crypto.tink.HmacKey")) .AddPrimitive( absl::make_unique("MAC2"), CreateKey(0x02020202, OutputPrefixType::TINK, KeyStatusType::ENABLED, /*type_url=*/ "type.googleapis.com/google.crypto.tink.HmacKey")) // Add primitive and make it primary. .AddPrimaryPrimitive( absl::make_unique("MAC3"), CreateKey(0x02020202, OutputPrefixType::TINK, KeyStatusType::ENABLED, /*type_url=*/ "type.googleapis.com/google.crypto.tink.AesCmacKey")) .AddPrimitive( absl::make_unique("MAC4"), CreateKey(0x02020202, OutputPrefixType::RAW, KeyStatusType::ENABLED, /*type_url=*/ "type.googleapis.com/google.crypto.tink.AesCmacKey")) .AddPrimitive( absl::make_unique("MAC5"), CreateKey(0x01010101, OutputPrefixType::TINK, KeyStatusType::ENABLED, /*type_url=*/ "type.googleapis.com/google.crypto.tink.AesCmacKey")) .Build(); ASSERT_TRUE(pset_result.ok()) << pset_result.status(); PrimitiveSet pset = std::move(pset_result.value()); std::vector mac_id_and_type; for (auto* entry : pset.get_all()) { auto mac_or = entry->get_primitive().ComputeMac(""); ASSERT_THAT(mac_or, IsOk()); mac_id_and_type.push_back({mac_or.value(), entry->get_identifier(), std::string(entry->get_key_type_url())}); } // In the following id part, the first byte is 1 for Tink. std::vector expected_result = { {/*mac=*/"13:0:DummyMac:MAC1", /*id=*/absl::StrCat("\1\1\1\1\1"), /*type_url=*/"type.googleapis.com/google.crypto.tink.HmacKey"}, {/*mac=*/"13:0:DummyMac:MAC2", /*id=*/absl::StrCat("\1\2\2\2\2"), /*type_url=*/"type.googleapis.com/google.crypto.tink.HmacKey"}, {/*mac=*/"13:0:DummyMac:MAC3", /*id=*/absl::StrCat("\1\2\2\2\2"), /*type_url=*/"type.googleapis.com/google.crypto.tink.AesCmacKey"}, {/*mac=*/"13:0:DummyMac:MAC4", /*id=*/"", /*type_url=*/"type.googleapis.com/google.crypto.tink.AesCmacKey"}, {/*mac=*/"13:0:DummyMac:MAC5", /*id=*/absl::StrCat("\1\1\1\1\1"), /*type_url=*/"type.googleapis.com/google.crypto.tink.AesCmacKey"}}; EXPECT_THAT(mac_id_and_type, UnorderedElementsAreArray(expected_result)); } TEST_F(PrimitiveSetTest, GetAllInKeysetOrder) { auto pset = absl::make_unique>(); std::vector key_infos; KeysetInfo::KeyInfo key_info; key_info.set_key_id(1010101); key_info.set_status(KeyStatusType::ENABLED); key_info.set_output_prefix_type(OutputPrefixType::RAW); key_info.set_type_url( "type.googleapis.com/google.crypto.tink.PrfBasedDeriverKey"); ASSERT_THAT(pset->AddPrimitive( absl::make_unique("one"), key_info), IsOk()); key_infos.push_back(key_info); key_info.set_key_id(2020202); key_info.set_status(KeyStatusType::ENABLED); key_info.set_output_prefix_type(OutputPrefixType::LEGACY); key_info.set_type_url( "type.googleapis.com/google.crypto.tink.PrfBasedDeriverKey"); ASSERT_THAT(pset->AddPrimitive( absl::make_unique("two"), key_info), IsOk()); key_infos.push_back(key_info); key_info.set_key_id(3030303); key_info.set_status(KeyStatusType::ENABLED); key_info.set_output_prefix_type(OutputPrefixType::TINK); key_info.set_type_url( "type.googleapis.com/google.crypto.tink.PrfBasedDeriverKey"); ASSERT_THAT( pset->AddPrimitive(absl::make_unique("three"), key_info), IsOk()); key_infos.push_back(key_info); std::vector::Entry*> entries = pset->get_all_in_keyset_order(); ASSERT_THAT(entries, SizeIs(key_infos.size())); for (int i = 0; i < entries.size(); i++) { EXPECT_THAT(entries[i]->get_identifier(), Eq(*CryptoFormat::GetOutputPrefix(key_infos[i]))); EXPECT_THAT(entries[i]->get_status(), Eq(KeyStatusType::ENABLED)); EXPECT_THAT(entries[i]->get_key_id(), Eq(key_infos[i].key_id())); EXPECT_THAT(entries[i]->get_output_prefix_type(), Eq(key_infos[i].output_prefix_type())); EXPECT_THAT(entries[i]->get_key_type_url(), Eq(key_infos[i].type_url())); } } TEST_F(PrimitiveSetTest, LegacyConcurrentOperations) { PrimitiveSet mac_set; int offset_a = 100; int offset_b = 150; int count = 100; // Add some primitives. std::thread add_primitives_a( [&]() { add_primitives(&mac_set, offset_a, count); }); std::thread add_primitives_b( [&]() { add_primitives(&mac_set, offset_b, count); }); add_primitives_a.join(); add_primitives_b.join(); // Access primitives. std::thread access_primitives_a(access_primitives, &mac_set, offset_a, count); std::thread access_primitives_b(access_primitives, &mac_set, offset_b, count); access_primitives_a.join(); access_primitives_b.join(); // Verify the common key ids added by both threads. for (int key_id = offset_a; key_id < offset_b + count; key_id++) { KeysetInfo::KeyInfo key_info; key_info.set_output_prefix_type(OutputPrefixType::TINK); key_info.set_key_id(key_id); key_info.set_status(KeyStatusType::ENABLED); std::string prefix = CryptoFormat::GetOutputPrefix(key_info).value(); auto get_result = mac_set.get_primitives(prefix); EXPECT_TRUE(get_result.ok()) << get_result.status(); auto macs = get_result.value(); if (key_id >= offset_b && key_id < offset_a + count) { EXPECT_EQ(2, macs->size()); // overlapping key_id range } else { EXPECT_EQ(1, macs->size()); } } } TEST_F(PrimitiveSetTest, LegacyBasic) { std::string mac_name_1 = "MAC#1"; std::unique_ptr mac_1(new DummyMac(mac_name_1)); std::string mac_name_2 = "MAC#2"; std::unique_ptr mac_2(new DummyMac(mac_name_2)); std::string mac_name_3 = "MAC#3"; std::unique_ptr mac_3(new DummyMac(mac_name_3)); std::string mac_name_4 = "MAC#3"; std::unique_ptr mac_4(new DummyMac(mac_name_4)); std::string mac_name_5 = "MAC#3"; std::unique_ptr mac_5(new DummyMac(mac_name_5)); std::string mac_name_6 = "MAC#3"; std::unique_ptr mac_6(new DummyMac(mac_name_6)); uint32_t key_id_1 = 1234543; KeysetInfo::KeyInfo key_1; key_1.set_output_prefix_type(OutputPrefixType::TINK); key_1.set_key_id(key_id_1); key_1.set_status(KeyStatusType::ENABLED); uint32_t key_id_2 = 7213743; KeysetInfo::KeyInfo key_2; key_2.set_output_prefix_type(OutputPrefixType::LEGACY); key_2.set_key_id(key_id_2); key_2.set_status(KeyStatusType::ENABLED); uint32_t key_id_3 = key_id_2; // same id as key_2 KeysetInfo::KeyInfo key_3; key_3.set_output_prefix_type(OutputPrefixType::TINK); key_3.set_key_id(key_id_3); key_3.set_status(KeyStatusType::ENABLED); uint32_t key_id_4 = 947327; KeysetInfo::KeyInfo key_4; key_4.set_output_prefix_type(OutputPrefixType::RAW); key_4.set_key_id(key_id_4); key_4.set_status(KeyStatusType::ENABLED); uint32_t key_id_5 = 529472; KeysetInfo::KeyInfo key_5; key_5.set_output_prefix_type(OutputPrefixType::RAW); key_5.set_key_id(key_id_5); key_5.set_status(KeyStatusType::ENABLED); uint32_t key_id_6 = key_id_1; // same id as key_1 KeysetInfo::KeyInfo key_6; key_6.set_output_prefix_type(OutputPrefixType::TINK); key_6.set_key_id(key_id_6); key_6.set_status(KeyStatusType::ENABLED); PrimitiveSet primitive_set; EXPECT_TRUE(primitive_set.get_primary() == nullptr); EXPECT_EQ(absl::StatusCode::kNotFound, primitive_set.get_raw_primitives().status().code()); EXPECT_EQ(absl::StatusCode::kNotFound, primitive_set.get_primitives("prefix").status().code()); // Add all the primitives. auto add_primitive_result = primitive_set.AddPrimitive(std::move(mac_1), key_1); EXPECT_TRUE(add_primitive_result.ok()) << add_primitive_result.status(); add_primitive_result = primitive_set.AddPrimitive(std::move(mac_2), key_2); EXPECT_TRUE(add_primitive_result.ok()) << add_primitive_result.status(); add_primitive_result = primitive_set.AddPrimitive(std::move(mac_3), key_3); EXPECT_TRUE(add_primitive_result.ok()) << add_primitive_result.status(); EXPECT_THAT(primitive_set.set_primary(add_primitive_result.value()), IsOk()); add_primitive_result = primitive_set.AddPrimitive(std::move(mac_4), key_4); EXPECT_TRUE(add_primitive_result.ok()) << add_primitive_result.status(); add_primitive_result = primitive_set.AddPrimitive(std::move(mac_5), key_5); EXPECT_TRUE(add_primitive_result.ok()) << add_primitive_result.status(); add_primitive_result = primitive_set.AddPrimitive(std::move(mac_6), key_6); EXPECT_TRUE(add_primitive_result.ok()) << add_primitive_result.status(); // Try adding a "consumed" unique_ptr as a primitive. add_primitive_result = primitive_set.AddPrimitive(std::move(mac_6), key_6); EXPECT_FALSE(add_primitive_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, add_primitive_result.status().code()); std::string data = "some data"; { // Check the primary. auto primary = primitive_set.get_primary(); EXPECT_FALSE(primary == nullptr); EXPECT_EQ(KeyStatusType::ENABLED, primary->get_status()); EXPECT_EQ(DummyMac(mac_name_3).ComputeMac(data).value(), primary->get_primitive().ComputeMac(data).value()); } { // Check raw primitives. auto& primitives = *(primitive_set.get_raw_primitives().value()); EXPECT_EQ(2, primitives.size()); EXPECT_EQ(DummyMac(mac_name_4).ComputeMac(data).value(), primitives[0]->get_primitive().ComputeMac(data).value()); EXPECT_EQ(KeyStatusType::ENABLED, primitives[0]->get_status()); EXPECT_EQ(key_4.key_id(), primitives[0]->get_key_id()); EXPECT_EQ(OutputPrefixType::RAW, primitives[0]->get_output_prefix_type()); EXPECT_EQ(DummyMac(mac_name_5).ComputeMac(data).value(), primitives[1]->get_primitive().ComputeMac(data).value()); EXPECT_EQ(KeyStatusType::ENABLED, primitives[1]->get_status()); EXPECT_EQ(key_5.key_id(), primitives[1]->get_key_id()); EXPECT_EQ(OutputPrefixType::RAW, primitives[1]->get_output_prefix_type()); } { // Check Tink primitives. std::string prefix = CryptoFormat::GetOutputPrefix(key_1).value(); auto& primitives = *(primitive_set.get_primitives(prefix).value()); EXPECT_EQ(2, primitives.size()); EXPECT_EQ(DummyMac(mac_name_1).ComputeMac(data).value(), primitives[0]->get_primitive().ComputeMac(data).value()); EXPECT_EQ(KeyStatusType::ENABLED, primitives[0]->get_status()); EXPECT_EQ(key_1.key_id(), primitives[0]->get_key_id()); EXPECT_EQ(OutputPrefixType::TINK, primitives[0]->get_output_prefix_type()); EXPECT_EQ(DummyMac(mac_name_6).ComputeMac(data).value(), primitives[1]->get_primitive().ComputeMac(data).value()); EXPECT_EQ(KeyStatusType::ENABLED, primitives[1]->get_status()); EXPECT_EQ(key_1.key_id(), primitives[1]->get_key_id()); EXPECT_EQ(OutputPrefixType::TINK, primitives[1]->get_output_prefix_type()); } { // Check another Tink primitive. std::string prefix = CryptoFormat::GetOutputPrefix(key_3).value(); auto& primitives = *(primitive_set.get_primitives(prefix).value()); EXPECT_EQ(1, primitives.size()); EXPECT_EQ(DummyMac(mac_name_3).ComputeMac(data).value(), primitives[0]->get_primitive().ComputeMac(data).value()); EXPECT_EQ(KeyStatusType::ENABLED, primitives[0]->get_status()); EXPECT_EQ(key_3.key_id(), primitives[0]->get_key_id()); EXPECT_EQ(OutputPrefixType::TINK, primitives[0]->get_output_prefix_type()); } { // Check legacy primitive. std::string prefix = CryptoFormat::GetOutputPrefix(key_2).value(); auto& primitives = *(primitive_set.get_primitives(prefix).value()); EXPECT_EQ(1, primitives.size()); EXPECT_EQ(DummyMac(mac_name_2).ComputeMac(data).value(), primitives[0]->get_primitive().ComputeMac(data).value()); EXPECT_EQ(KeyStatusType::ENABLED, primitives[0]->get_status()); EXPECT_EQ(key_2.key_id(), primitives[0]->get_key_id()); EXPECT_EQ(OutputPrefixType::LEGACY, primitives[0]->get_output_prefix_type()); } } TEST_F(PrimitiveSetTest, LegacyPrimaryKeyWithIdCollisions) { std::string mac_name_1 = "MAC#1"; std::string mac_name_2 = "MAC#2"; uint32_t key_id_1 = 1234543; KeysetInfo::KeyInfo key_info_1; key_info_1.set_key_id(key_id_1); key_info_1.set_status(KeyStatusType::ENABLED); uint32_t key_id_2 = key_id_1; // same id as key_2 KeysetInfo::KeyInfo key_info_2; key_info_2.set_key_id(key_id_2); key_info_2.set_status(KeyStatusType::ENABLED); { // Test with RAW-keys. std::unique_ptr mac_1(new DummyMac(mac_name_1)); std::unique_ptr mac_2(new DummyMac(mac_name_2)); key_info_1.set_output_prefix_type(OutputPrefixType::RAW); key_info_2.set_output_prefix_type(OutputPrefixType::RAW); PrimitiveSet primitive_set; EXPECT_TRUE(primitive_set.get_primary() == nullptr); // Add the first primitive, and set it as primary. auto add_primitive_result = primitive_set.AddPrimitive(std::move(mac_1), key_info_1); EXPECT_TRUE(add_primitive_result.ok()) << add_primitive_result.status(); ASSERT_THAT(primitive_set.set_primary(add_primitive_result.value()), IsOk()); std::string identifier = ""; const auto& primitives = *(primitive_set.get_primitives(identifier).value()); EXPECT_EQ(1, primitives.size()); EXPECT_EQ(primitive_set.get_primary(), primitives[0].get()); // Adding another primitive should not invalidate the primary. add_primitive_result = primitive_set.AddPrimitive(std::move(mac_2), key_info_2); EXPECT_TRUE(add_primitive_result.ok()) << add_primitive_result.status(); EXPECT_EQ(2, primitives.size()); EXPECT_EQ(primitive_set.get_primary(), primitives[0].get()); } { // Test with TINK-keys. std::unique_ptr mac_1(new DummyMac(mac_name_1)); std::unique_ptr mac_2(new DummyMac(mac_name_2)); key_info_1.set_output_prefix_type(OutputPrefixType::TINK); key_info_2.set_output_prefix_type(OutputPrefixType::TINK); PrimitiveSet primitive_set; EXPECT_TRUE(primitive_set.get_primary() == nullptr); // Add the first primitive, and set it as primary. auto add_primitive_result = primitive_set.AddPrimitive(std::move(mac_1), key_info_1); EXPECT_TRUE(add_primitive_result.ok()) << add_primitive_result.status(); ASSERT_THAT(primitive_set.set_primary(add_primitive_result.value()), IsOk()); std::string identifier = CryptoFormat::GetOutputPrefix(key_info_1).value(); const auto& primitives = *(primitive_set.get_primitives(identifier).value()); EXPECT_EQ(1, primitives.size()); EXPECT_EQ(primitive_set.get_primary(), primitives[0].get()); // Adding another primitive should not invalidate the primary. add_primitive_result = primitive_set.AddPrimitive(std::move(mac_2), key_info_2); EXPECT_TRUE(add_primitive_result.ok()) << add_primitive_result.status(); EXPECT_EQ(2, primitives.size()); EXPECT_EQ(primitive_set.get_primary(), primitives[0].get()); } { // Test with LEGACY-keys. std::unique_ptr mac_1(new DummyMac(mac_name_1)); std::unique_ptr mac_2(new DummyMac(mac_name_2)); key_info_1.set_output_prefix_type(OutputPrefixType::LEGACY); key_info_2.set_output_prefix_type(OutputPrefixType::LEGACY); PrimitiveSet primitive_set; EXPECT_TRUE(primitive_set.get_primary() == nullptr); // Add the first primitive, and set it as primary. auto add_primitive_result = primitive_set.AddPrimitive(std::move(mac_1), key_info_1); EXPECT_TRUE(add_primitive_result.ok()) << add_primitive_result.status(); ASSERT_THAT(primitive_set.set_primary(add_primitive_result.value()), IsOk()); std::string identifier = CryptoFormat::GetOutputPrefix(key_info_1).value(); const auto& primitives = *(primitive_set.get_primitives(identifier).value()); EXPECT_EQ(1, primitives.size()); EXPECT_EQ(primitive_set.get_primary(), primitives[0].get()); // Adding another primitive should not invalidate the primary. add_primitive_result = primitive_set.AddPrimitive(std::move(mac_2), key_info_2); EXPECT_TRUE(add_primitive_result.ok()) << add_primitive_result.status(); EXPECT_EQ(2, primitives.size()); EXPECT_EQ(primitive_set.get_primary(), primitives[0].get()); } } TEST_F(PrimitiveSetTest, LegacyDisabledKey) { std::string mac_name_1 = "MAC#1"; std::unique_ptr mac_1(new DummyMac(mac_name_1)); uint32_t key_id_1 = 1234543; KeysetInfo::KeyInfo key_info_1; key_info_1.set_output_prefix_type(OutputPrefixType::TINK); key_info_1.set_key_id(key_id_1); key_info_1.set_status(KeyStatusType::DISABLED); PrimitiveSet primitive_set; // Add all the primitives. auto add_primitive_result = primitive_set.AddPrimitive(std::move(mac_1), key_info_1); EXPECT_FALSE(add_primitive_result.ok()); } TEST_F(PrimitiveSetTest, LegacyGetAll) { PrimitiveSet pset; EXPECT_THAT( pset.AddPrimitive( absl::make_unique("MAC1"), CreateKey(0x01010101, OutputPrefixType::TINK, KeyStatusType::ENABLED, /*type_url=*/ "type.googleapis.com/google.crypto.tink.HmacKey")) .status(), IsOk()); EXPECT_THAT( pset.AddPrimitive( absl::make_unique("MAC2"), CreateKey(0x02020202, OutputPrefixType::TINK, KeyStatusType::ENABLED, /*type_url=*/ "type.googleapis.com/google.crypto.tink.HmacKey")) .status(), IsOk()); // Add primitive and make it primary. auto entry_or = pset.AddPrimitive( absl::make_unique("MAC3"), CreateKey(0x02020202, OutputPrefixType::TINK, KeyStatusType::ENABLED, /*type_url=*/ "type.googleapis.com/google.crypto.tink.AesCmacKey")); ASSERT_THAT(entry_or, IsOk()); EXPECT_THAT(pset.set_primary(entry_or.value()), IsOk()); EXPECT_THAT( pset.AddPrimitive( absl::make_unique("MAC4"), CreateKey(0x02020202, OutputPrefixType::RAW, KeyStatusType::ENABLED, /*type_url=*/ "type.googleapis.com/google.crypto.tink.AesCmacKey")) .status(), IsOk()); EXPECT_THAT( pset.AddPrimitive( absl::make_unique("MAC5"), CreateKey(0x01010101, OutputPrefixType::TINK, KeyStatusType::ENABLED, /*type_url=*/ "type.googleapis.com/google.crypto.tink.AesCmacKey")) .status(), IsOk()); std::vector mac_id_and_type; for (auto* entry : pset.get_all()) { auto mac_or = entry->get_primitive().ComputeMac(""); ASSERT_THAT(mac_or, IsOk()); mac_id_and_type.push_back({mac_or.value(), entry->get_identifier(), std::string(entry->get_key_type_url())}); } // In the following id part, the first byte is 1 for Tink. std::vector expected_result = { {/*mac=*/"13:0:DummyMac:MAC1", /*id=*/absl::StrCat("\1\1\1\1\1"), /*type_url=*/"type.googleapis.com/google.crypto.tink.HmacKey"}, {/*mac=*/"13:0:DummyMac:MAC2", /*id=*/absl::StrCat("\1\2\2\2\2"), /*type_url=*/"type.googleapis.com/google.crypto.tink.HmacKey"}, {/*mac=*/"13:0:DummyMac:MAC3", /*id=*/absl::StrCat("\1\2\2\2\2"), /*type_url=*/"type.googleapis.com/google.crypto.tink.AesCmacKey"}, {/*mac=*/"13:0:DummyMac:MAC4", /*id=*/"", /*type_url=*/"type.googleapis.com/google.crypto.tink.AesCmacKey"}, {/*mac=*/"13:0:DummyMac:MAC5", /*id=*/absl::StrCat("\1\1\1\1\1"), /*type_url=*/"type.googleapis.com/google.crypto.tink.AesCmacKey"}}; EXPECT_THAT(mac_id_and_type, UnorderedElementsAreArray(expected_result)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/core/private_key_manager_impl.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_CORE_PRIVATE_KEY_MANAGER_IMPL_H_ #define TINK_CORE_PRIVATE_KEY_MANAGER_IMPL_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/core/key_manager_impl.h" #include "tink/core/key_type_manager.h" #include "tink/core/private_key_type_manager.h" #include "tink/key_manager.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" namespace crypto { namespace tink { namespace internal { // An implementation of a PrivateKeyFactory given a corresponding internal // private key manager and an internal (public) key manager. // The template arguments PrivatePrimitivesList and PublicPrimitivesList should // be of type List. The assumption is that the given pointers in // the constructor are of type // PrivateKeyTypeManager // and // KeyTypeManager. template class PrivateKeyFactoryImpl : public PrivateKeyFactory { public: PrivateKeyFactoryImpl( PrivateKeyTypeManager* private_key_manager, KeyTypeManager* public_key_manager) : key_factory_impl_(private_key_manager), private_key_manager_(private_key_manager), public_key_type_(public_key_manager->get_key_type()), public_key_material_type_(public_key_manager->key_material_type()) {} crypto::tink::util::StatusOr> NewKey(const portable_proto::MessageLite& key_format) const override { return key_factory_impl_.NewKey(key_format); } crypto::tink::util::StatusOr> NewKey(absl::string_view serialized_key_format) const override { return key_factory_impl_.NewKey(serialized_key_format); } crypto::tink::util::StatusOr> NewKeyData(absl::string_view serialized_key_format) const override { return key_factory_impl_.NewKeyData(serialized_key_format); } crypto::tink::util::StatusOr> GetPublicKeyData(absl::string_view serialized_private_key) const override { PrivateKeyProto private_key; if (!private_key.ParseFromString(serialized_private_key)) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Could not parse the passed string as proto '", PrivateKeyProto().GetTypeName(), "'.")); } auto validation = private_key_manager_->ValidateKey(private_key); if (!validation.ok()) return validation; auto key_data = absl::make_unique(); util::StatusOr public_key_result = private_key_manager_->GetPublicKey(private_key); if (!public_key_result.ok()) return public_key_result.status(); key_data->set_type_url(public_key_type_); key_data->set_value(public_key_result.value().SerializeAsString()); key_data->set_key_material_type(public_key_material_type_); return std::move(key_data); } private: // We create a key_factory_impl_ as a member, instead of using virtual // inheritance to have it as a sub class. This means we have to forward the // calls to NewKeyData as above, but developers do not have to know about // virtual inheritance. KeyFactoryImpl> key_factory_impl_; PrivateKeyTypeManager* private_key_manager_; const std::string public_key_type_; google::crypto::tink::KeyData::KeyMaterialType public_key_material_type_; }; template class PrivateKeyManagerImpl; template class PrivateKeyManagerImpl< Primitive, PrivateKeyTypeManager, KeyTypeManager> : public KeyManagerImpl> { public: explicit PrivateKeyManagerImpl( PrivateKeyTypeManager* private_key_manager, KeyTypeManager* public_key_manager) : KeyManagerImpl>( private_key_manager), private_key_factory_(private_key_manager, public_key_manager) {} const PrivateKeyFactory& get_key_factory() const override { return private_key_factory_; } private: const PrivateKeyFactoryImpl private_key_factory_; }; // Helper function to create a KeyManager for a // PrivateKeyTypeManager. Using this, all template arguments except the // first one can be infered. Example: // std::unique_ptr> km = // MakePrivateKeyManager(internal_private_km, // internal_public_km); // // When creating a KeyManager like this, the passed in "private_key_manager" // must outlive the constructed KeyManager. The passed in "public_key_manager" // however must only be valid during construction of the KeyManager. template std::unique_ptr> MakePrivateKeyManager( PrivateKeyTypeManager* private_key_manager, KeyTypeManager* public_key_manager) { return absl::make_unique, KeyTypeManager>>( private_key_manager, public_key_manager); } } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_CORE_PRIVATE_KEY_MANAGER_IMPL_H_ ================================================ FILE: cc/core/private_key_manager_impl_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/core/private_key_manager_impl.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/core/key_manager_impl.h" #include "tink/core/key_type_manager.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/key_manager.h" #include "tink/registry.h" #include "tink/subtle/aes_gcm_boringssl.h" #include "tink/subtle/random.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "tink/util/validation.h" #include "proto/ecdsa.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::EcdsaKeyFormat; using ::google::crypto::tink::EcdsaPrivateKey; using ::google::crypto::tink::EcdsaPublicKey; using ::google::crypto::tink::EcdsaSignatureEncoding; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::Return; } // namespace // Placeholders for the primitives. We don't really want to test anything with // these except that things compile and List is never confused // with List in private_key_manager_impl. // NOTE: These are outside of the anonymous namespace to allow compiling with // MSVC. class PrivatePrimitive {}; class PublicPrimitive {}; namespace { class ExamplePrivateKeyTypeManager : public PrivateKeyTypeManager> { public: class PrivatePrimitiveFactory : public PrimitiveFactory { public: crypto::tink::util::StatusOr> Create( const EcdsaPrivateKey& key) const override { return util::Status(absl::StatusCode::kUnimplemented, "Not implemented"); } }; ExamplePrivateKeyTypeManager() : PrivateKeyTypeManager(absl::make_unique()) {} google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE; } MOCK_METHOD(uint32_t, get_version, (), (const, override)); // We mock out ValidateKey and ValidateKeyFormat so that we can easily test // proper behavior in case they return an error. MOCK_METHOD(crypto::tink::util::Status, ValidateKey, (const EcdsaPrivateKey& key), (const, override)); MOCK_METHOD(crypto::tink::util::Status, ValidateKeyFormat, (const EcdsaKeyFormat& key), (const, override)); const std::string& get_key_type() const override { return kKeyType; } crypto::tink::util::StatusOr CreateKey( const EcdsaKeyFormat& key_format) const override { EcdsaPublicKey public_key; *public_key.mutable_params() = key_format.params(); EcdsaPrivateKey result; *result.mutable_public_key() = public_key; return result; } crypto::tink::util::StatusOr GetPublicKey( const EcdsaPrivateKey& private_key) const override { return private_key.public_key(); } private: const std::string kKeyType = "type.googleapis.com/google.crypto.tink.EcdsaPublicKey"; }; class TestPublicKeyTypeManager : public KeyTypeManager> { public: class PublicPrimitiveFactory : public PrimitiveFactory { public: crypto::tink::util::StatusOr> Create( const EcdsaPublicKey& key) const override { return util::Status(absl::StatusCode::kUnimplemented, "Not implemented"); } }; TestPublicKeyTypeManager() : KeyTypeManager(absl::make_unique()) {} google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE; } MOCK_METHOD(uint32_t, get_version, (), (const, override)); // We mock out ValidateKey and ValidateKeyFormat so that we can easily test // proper behavior in case they return an error. MOCK_METHOD(crypto::tink::util::Status, ValidateKey, (const EcdsaPublicKey& key), (const, override)); const std::string& get_key_type() const override { return kKeyType; } private: const std::string kKeyType = "type.googleapis.com/google.crypto.tink.EcdsaPublicKey"; }; TEST(PrivateKeyManagerImplTest, FactoryNewKeyFromMessage) { ExamplePrivateKeyTypeManager private_km; TestPublicKeyTypeManager public_km; std::unique_ptr> key_manager = MakePrivateKeyManager(&private_km, &public_km); EcdsaKeyFormat key_format; key_format.mutable_params()->set_encoding(EcdsaSignatureEncoding::DER); auto key = key_manager->get_key_factory().NewKey(key_format).value(); EXPECT_THAT( dynamic_cast(*key).public_key().params().encoding(), Eq(EcdsaSignatureEncoding::DER)); } TEST(PrivateKeyManagerImplTest, GetPublicKeyData) { ExamplePrivateKeyTypeManager private_km; TestPublicKeyTypeManager public_km; std::unique_ptr> key_manager = MakePrivateKeyManager(&private_km, &public_km); EcdsaPrivateKey private_key; private_key.mutable_public_key()->mutable_params()->set_encoding( EcdsaSignatureEncoding::DER); auto key_data = dynamic_cast(key_manager->get_key_factory()) .GetPublicKeyData(private_key.SerializeAsString()) .value(); ASSERT_THAT(key_data->type_url(), Eq(public_km.get_key_type())); EcdsaPublicKey public_key; public_key.ParseFromString(key_data->value()); EXPECT_THAT(public_key.params().encoding(), Eq(EcdsaSignatureEncoding::DER)); } TEST(PrivateKeyManagerImplTest, GetPublicKeyDataValidatePrivateKey) { ExamplePrivateKeyTypeManager private_km; TestPublicKeyTypeManager public_km; EXPECT_CALL(private_km, ValidateKey) .WillOnce(Return(util::Status(absl::StatusCode::kOutOfRange, "GetPublicKeyDataValidatePrivateKey"))); std::unique_ptr> key_manager = MakePrivateKeyManager(&private_km, &public_km); EXPECT_THAT( dynamic_cast(key_manager->get_key_factory()) .GetPublicKeyData(EcdsaPrivateKey().SerializeAsString()) .status(), StatusIs(absl::StatusCode::kOutOfRange, HasSubstr("GetPublicKeyDataValidatePrivateKey"))); } TEST(PrivateKeyManagerImplTest, PublicKeyManagerCanHaveShortLifetime) { ExamplePrivateKeyTypeManager private_km; std::unique_ptr> key_manager; { TestPublicKeyTypeManager public_km; key_manager = MakePrivateKeyManager(&private_km, &public_km); // Let the public_km go out of scope; the key_manager should still work. } EcdsaKeyFormat key_format; key_format.mutable_params()->set_encoding(EcdsaSignatureEncoding::DER); auto key = key_manager->get_key_factory().NewKey(key_format).value(); EXPECT_THAT( dynamic_cast(*key).public_key().params().encoding(), Eq(EcdsaSignatureEncoding::DER)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/core/private_key_type_manager.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_CORE_PRIVATE_KEY_TYPE_MANAGER_H_ #define TINK_CORE_PRIVATE_KEY_TYPE_MANAGER_H_ #include #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { template class PrivateKeyTypeManager; // A PrivateKeyTypeManager is an extension of KeyTypeManager. One // should implement this in case there is a public key corresponding to the // private key managed by this manager. // Hence, in addition to the tasks a KeyTypeManager does, in order to // implement a PrivateKeyTypeManager one needs to provide a function // StatusOr GetPublicKey(const KeyProto& private_key) const = 0; template class PrivateKeyTypeManager> : public KeyTypeManager> { public: explicit PrivateKeyTypeManager( std::unique_ptr>:: template PrimitiveFactory>... primitives) : KeyTypeManager>( std::move(primitives)...) {} virtual crypto::tink::util::StatusOr GetPublicKey( const KeyProto& private_key) const = 0; }; } // namespace tink } // namespace crypto #endif // TINK_CORE_PRIVATE_KEY_TYPE_MANAGER_H_ ================================================ FILE: cc/core/restricted_big_integer.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/restricted_big_integer.h" #include #include "absl/strings/string_view.h" #include "openssl/crypto.h" #include "tink/secret_key_access_token.h" #include "tink/util/secret_data.h" namespace crypto { namespace tink { RestrictedBigInteger::RestrictedBigInteger(absl::string_view secret_big_integer, SecretKeyAccessToken token) { int padding_pos = secret_big_integer.find_first_not_of('\0'); if (padding_pos != std::string::npos) { secret_ = util::SecretDataFromStringView(secret_big_integer.substr(padding_pos)); } else { secret_ = util::SecretDataFromStringView(""); } } bool RestrictedBigInteger::operator==(const RestrictedBigInteger& other) const { if (secret_.size() != other.secret_.size()) { return false; } return CRYPTO_memcmp(secret_.data(), other.secret_.data(), secret_.size()) == 0; } } // namespace tink } // namespace crypto ================================================ FILE: cc/core/restricted_big_integer_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/restricted_big_integer.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/escaping.h" #include "absl/strings/string_view.h" #include "tink/insecure_secret_key_access.h" namespace crypto { namespace tink { using ::testing::Eq; constexpr absl::string_view kHexBigInt = "b3510a2bcd4ce644c5b594ae5059e12b2f054b658d5da5959a2fdf1871b808bc3df3e628" "d2792e51aad5c124b43bda453dca5cde4bcf28e7bd4effba0cb4b742bbb6d5a013cb63d1aa" "3a89e02627ef5398b52c0cfd97d208abeb8d7c9bce0bbeb019a86ddb589beb29a5b74bf861" "075c677c81d430f030c265247af9d3c9140ccb65309d07e0adc1efd15cf17e7b055d7da386" "8e4648cc3a180f0ee7f8e1e7b18098a3391b4ce7161e98d57af8a947e201a463e2d6bbca80" "59e5706e9dfed8f4856465ffa712ed1aa18e888d12dc6aa09ce95ecfca83cc5b0b15db09c8" "647f5d524c0f2e7620a3416b9623cadc0f097af573261c98c8400aa12af38e43cad84d"; constexpr absl::string_view kHexBigIntPadded = "0000b3510a2bcd4ce644c5b594ae5059e12b2f054b658d5da5959a2fdf1871b808bc3df3" "e628d2792e51aad5c124b43bda453dca5cde4bcf28e7bd4effba0cb4b742bbb6d5a013cb63" "d1aa3a89e02627ef5398b52c0cfd97d208abeb8d7c9bce0bbeb019a86ddb589beb29a5b74b" "f861075c677c81d430f030c265247af9d3c9140ccb65309d07e0adc1efd15cf17e7b055d7d" "a3868e4648cc3a180f0ee7f8e1e7b18098a3391b4ce7161e98d57af8a947e201a463e2d6bb" "ca8059e5706e9dfed8f4856465ffa712ed1aa18e888d12dc6aa09ce95ecfca83cc5b0b15db" "09c8647f5d524c0f2e7620a3416b9623cadc0f097af573261c98c8400aa12af38e43cad84" "d"; TEST(RestrictedBigIntegerTest, CreateAndGetSecret) { const std::string secret_bytes = absl::HexStringToBytes(kHexBigInt); RestrictedBigInteger restricted_big_integer(secret_bytes, InsecureSecretKeyAccess::Get()); EXPECT_THAT(restricted_big_integer.SizeInBytes(), Eq(256)); EXPECT_THAT(restricted_big_integer.GetSecret(InsecureSecretKeyAccess::Get()), Eq(secret_bytes)); } TEST(RestrictedBigIntegerTest, CreateAndGetSecretPadded) { const std::string secret_bytes = absl::HexStringToBytes(kHexBigInt); const std::string padded_secret_bytes = absl::HexStringToBytes(kHexBigIntPadded); RestrictedBigInteger from_padded_big_integer(padded_secret_bytes, InsecureSecretKeyAccess::Get()); EXPECT_THAT(from_padded_big_integer.SizeInBytes(), Eq(256)); EXPECT_FALSE(from_padded_big_integer.GetSecret( InsecureSecretKeyAccess::Get()) == padded_secret_bytes); EXPECT_THAT(from_padded_big_integer.GetSecret(InsecureSecretKeyAccess::Get()), Eq(secret_bytes)); } TEST(RestrictedBigIntegerTest, CreateAndGetEmptyStringWorks) { const std::string empty_string = ""; RestrictedBigInteger restricted_big_integer(empty_string, InsecureSecretKeyAccess::Get()); EXPECT_THAT(restricted_big_integer.SizeInBytes(), Eq(0)); EXPECT_THAT(restricted_big_integer.GetSecret(InsecureSecretKeyAccess::Get()), Eq("")); } TEST(RestrictedBigIntegerTest, CreateAndGetNullCharactersWorks) { const std::string empty_string = "\0\0\0"; RestrictedBigInteger restricted_big_integer(empty_string, InsecureSecretKeyAccess::Get()); EXPECT_THAT(restricted_big_integer.SizeInBytes(), Eq(0)); EXPECT_THAT(restricted_big_integer.GetSecret(InsecureSecretKeyAccess::Get()), Eq("")); } TEST(RestrictedBigIntegerTest, Equals) { const std::string secret_bytes = absl::HexStringToBytes(kHexBigInt); RestrictedBigInteger restricted_big_integer(secret_bytes, InsecureSecretKeyAccess::Get()); RestrictedBigInteger same_restricted_big_integer( secret_bytes, InsecureSecretKeyAccess::Get()); EXPECT_TRUE(restricted_big_integer == same_restricted_big_integer); EXPECT_TRUE(same_restricted_big_integer == restricted_big_integer); EXPECT_FALSE(restricted_big_integer != same_restricted_big_integer); EXPECT_FALSE(same_restricted_big_integer != restricted_big_integer); } TEST(RestricteddBigIntegerTest, EqualsPadded) { RestrictedBigInteger restricted_big_integer( absl::HexStringToBytes(kHexBigInt), InsecureSecretKeyAccess::Get()); RestrictedBigInteger padded_restricted_big_integer( absl::HexStringToBytes(kHexBigIntPadded), InsecureSecretKeyAccess::Get()); EXPECT_TRUE(restricted_big_integer == padded_restricted_big_integer); EXPECT_TRUE(padded_restricted_big_integer == restricted_big_integer); EXPECT_FALSE(restricted_big_integer != padded_restricted_big_integer); EXPECT_FALSE(padded_restricted_big_integer != restricted_big_integer); } TEST(RestrictedRestrictedBigIntegerTest, NotEquals) { const std::string other_big_integer_256 = absl::HexStringToBytes( "00c2410a2bcd4ce644c5b594ae5059e12b2f054b658d5da5959a2fdf1871b808bc3df3e6" "28d2792e51aad5c124b43bda453dca5cde4bcf28e7bd4effba0cb4b742bbb6d5a013cb63" "d1aa3a89e02627ef5398b52c0cfd97d208abeb8d7c9bce0bbeb019a86ddb589beb29a5b7" "4bf861075c677c81d430f030c265247af9d3c9140ccb65309d07e0adc1efd15cf17e7b05" "5d7da3868e4648cc3a180f0ee7f8e1e7b18098a3391b4ce7161e98d57af8a947e201a463" "e2d6bbca8059e5706e9dfed8f4856465ffa712ed1aa18e888d12dc6aa09ce95ecfca83cc" "5b0b15db09c8647f5d524c0f2e7620a3416b9623cadc0f097af573261c98c8400aa12af3" "8e43cad84d"); RestrictedBigInteger restricted_big_integer( absl::HexStringToBytes(kHexBigInt), InsecureSecretKeyAccess::Get()); RestrictedBigInteger diff_restricted_big_integer( other_big_integer_256, InsecureSecretKeyAccess::Get()); EXPECT_THAT(restricted_big_integer.SizeInBytes(), Eq(256)); EXPECT_THAT(diff_restricted_big_integer.SizeInBytes(), Eq(256)); EXPECT_FALSE(restricted_big_integer == diff_restricted_big_integer); EXPECT_FALSE(diff_restricted_big_integer == restricted_big_integer); EXPECT_TRUE(restricted_big_integer != diff_restricted_big_integer); EXPECT_TRUE(diff_restricted_big_integer != restricted_big_integer); } TEST(RestrictedRestrictedBigIntegerTest, NotEqualsDifferentSize) { const std::string other_big_integer_258 = absl::HexStringToBytes( "b3510a2bcd4ce644c5b594ae5059e12b2f054b658d5da5959a2fdf1871b808bc3df3e628" "d2792e51aad5c124b43bda453dca5cde4bcf28e7bd4effba0cb4b742bbb6d5a013cb63d1" "aa3a89e02627ef5398b52c0cfd97d208abeb8d7c9bce0bbeb019a86ddb589beb29a5b74b" "f861075c677c81d430f030c265247af9d3c9140ccb65309d07e0adc1efd15cf17e7b055d" "7da3868e4648cc3a180f0ee7f8e1e7b18098a3391b4ce7161e98d57af8a947e201a463e2" "d6bbca8059e5706e9dfed8f4856465ffa712ed1aa18e888d12dc6aa09ce95ecfca83cc5b" "0b15db09c8647f5d524c0f2e7620a3416b9623cadc0f097af573261c98c8400aa12af38e" "43cad84dbfff"); RestrictedBigInteger restricted_big_integer( absl::HexStringToBytes(kHexBigInt), InsecureSecretKeyAccess::Get()); RestrictedBigInteger diff_restricted_big_integer( other_big_integer_258, InsecureSecretKeyAccess::Get()); EXPECT_THAT(restricted_big_integer.SizeInBytes(), Eq(256)); EXPECT_THAT(diff_restricted_big_integer.SizeInBytes(), Eq(258)); EXPECT_FALSE(restricted_big_integer == diff_restricted_big_integer); EXPECT_FALSE(diff_restricted_big_integer == restricted_big_integer); EXPECT_TRUE(restricted_big_integer != diff_restricted_big_integer); EXPECT_TRUE(diff_restricted_big_integer != restricted_big_integer); } TEST(RestrictedRestrictedBigIntegerTest, CopyConstructor) { RestrictedBigInteger restricted_big_integer( absl::HexStringToBytes(kHexBigInt), InsecureSecretKeyAccess::Get()); RestrictedBigInteger copy(restricted_big_integer); EXPECT_THAT(copy.SizeInBytes(), Eq(256)); EXPECT_THAT( copy.GetSecret(InsecureSecretKeyAccess::Get()), Eq(restricted_big_integer.GetSecret(InsecureSecretKeyAccess::Get()))); } TEST(RestrictedRestrictedBigIntegerTest, CopyAssignment) { RestrictedBigInteger restricted_big_integer( absl::HexStringToBytes(kHexBigInt), InsecureSecretKeyAccess::Get()); RestrictedBigInteger copy = restricted_big_integer; EXPECT_THAT(copy.SizeInBytes(), Eq(256)); EXPECT_THAT(copy.GetSecret(InsecureSecretKeyAccess::Get()), Eq(absl::HexStringToBytes(kHexBigInt))); } TEST(RestrictedRestrictedBigIntegerTest, MoveConstructor) { RestrictedBigInteger restricted_big_integer( absl::HexStringToBytes(kHexBigInt), InsecureSecretKeyAccess::Get()); RestrictedBigInteger move(std::move(restricted_big_integer)); EXPECT_THAT(move.SizeInBytes(), Eq(256)); EXPECT_THAT(move.GetSecret(InsecureSecretKeyAccess::Get()), Eq(absl::HexStringToBytes(kHexBigInt))); } TEST(RestrictedRestrictedBigIntegerTest, MoveAssignment) { RestrictedBigInteger restricted_big_integer( absl::HexStringToBytes(kHexBigInt), InsecureSecretKeyAccess::Get()); RestrictedBigInteger move = std::move(restricted_big_integer); EXPECT_THAT(move.SizeInBytes(), Eq(256)); EXPECT_THAT(move.GetSecret(InsecureSecretKeyAccess::Get()), Eq(absl::HexStringToBytes(kHexBigInt))); } } // namespace tink } // namespace crypto ================================================ FILE: cc/core/restricted_data.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/restricted_data.h" #include #include #include "absl/log/check.h" #include "openssl/crypto.h" #include "tink/subtle/random.h" #include "tink/util/secret_data.h" namespace crypto { namespace tink { RestrictedData::RestrictedData(int64_t num_random_bytes) { CHECK_GE(num_random_bytes, 0) << "Cannot generate a negative number of random bytes.\n"; secret_ = util::SecretDataFromStringView( subtle::Random::GetRandomBytes(num_random_bytes)); } bool RestrictedData::operator==(const RestrictedData& other) const { if (secret_.size() != other.secret_.size()) { return false; } return CRYPTO_memcmp(secret_.data(), other.secret_.data(), secret_.size()) == 0; } } // namespace tink } // namespace crypto ================================================ FILE: cc/core/restricted_data_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/restricted_data.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/insecure_secret_key_access.h" #include "tink/subtle/random.h" #include "tink/util/secret_data.h" namespace crypto { namespace tink { using ::crypto::tink::subtle::Random; using ::testing::Eq; using ::testing::SizeIs; TEST(RestrictedDataTest, CreateAndGetSecret) { const std::string secret = Random::GetRandomBytes(32); RestrictedData data(secret, InsecureSecretKeyAccess::Get()); EXPECT_THAT(data.GetSecret(InsecureSecretKeyAccess::Get()), Eq(secret)); } TEST(RestrictedDataTest, GenerateRandomAndSize) { RestrictedData data(/*num_random_bytes=*/32); EXPECT_THAT(data.GetSecret(InsecureSecretKeyAccess::Get()), SizeIs(32)); EXPECT_THAT(data.size(), Eq(32)); } TEST(RestrictedDataTest, GenerateRandomNegative) { EXPECT_DEATH_IF_SUPPORTED( RestrictedData(/*num_random_bytes=*/-1), "Cannot generate a negative number of random bytes.\n"); } TEST(RestrictedDataTest, Equals) { const std::string secret = Random::GetRandomBytes(32); RestrictedData data(secret, InsecureSecretKeyAccess::Get()); RestrictedData same_data(secret, InsecureSecretKeyAccess::Get()); EXPECT_TRUE(data == same_data); EXPECT_TRUE(same_data == data); EXPECT_FALSE(data != same_data); EXPECT_FALSE(same_data != data); } TEST(RestrictedDataTest, NotEquals) { RestrictedData data( util::SecretDataAsStringView(Random::GetRandomKeyBytes(32)), InsecureSecretKeyAccess::Get()); RestrictedData diff_data( util::SecretDataAsStringView(Random::GetRandomKeyBytes(32)), InsecureSecretKeyAccess::Get()); EXPECT_TRUE(data != diff_data); EXPECT_TRUE(diff_data != data); EXPECT_FALSE(data == diff_data); EXPECT_FALSE(diff_data == data); } TEST(RestrictedDataTest, CopyConstructor) { RestrictedData data(/*num_random_bytes=*/32); RestrictedData copy(data); EXPECT_THAT(copy, SizeIs(32)); EXPECT_THAT(copy.GetSecret(InsecureSecretKeyAccess::Get()), Eq(data.GetSecret(InsecureSecretKeyAccess::Get()))); } TEST(RestrictedDataTest, CopyAssignment) { RestrictedData data(/*num_random_bytes=*/32); RestrictedData copy = data; EXPECT_THAT(copy, SizeIs(32)); EXPECT_THAT(copy.GetSecret(InsecureSecretKeyAccess::Get()), Eq(copy.GetSecret(InsecureSecretKeyAccess::Get()))); } TEST(RestrictedDataTest, MoveConstructor) { const std::string secret = Random::GetRandomBytes(32); RestrictedData data(secret, InsecureSecretKeyAccess::Get()); RestrictedData move(std::move(data)); EXPECT_THAT(move, SizeIs(32)); EXPECT_THAT(move.GetSecret(InsecureSecretKeyAccess::Get()), Eq(secret)); } TEST(RestrictedDataTest, MoveAssignment) { const std::string secret = Random::GetRandomBytes(32); RestrictedData data(secret, InsecureSecretKeyAccess::Get()); RestrictedData move = std::move(data); EXPECT_THAT(move, SizeIs(32)); EXPECT_THAT(move.GetSecret(InsecureSecretKeyAccess::Get()), Eq(secret)); } } // namespace tink } // namespace crypto ================================================ FILE: cc/core/template_util.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_CORE_TEMPLATE_UTIL_H_ #define TINK_CORE_TEMPLATE_UTIL_H_ #include #include #include #include "absl/meta/type_traits.h" namespace crypto { namespace tink { // A list of types template struct List {}; namespace internal { // A helper class template which decides if the TestType occurs in the Tuple // For example, OccursInTuple>::value == false, // and OccursInTuple>::value == true. Not intended // to be used directly. // First declare the template which always takes two parameters. template class OccursInTuple; // In the special case where the tuple is empty, the result is false. template class OccursInTuple> : public std::false_type {}; // If the list is not empty, the result is true if TestType equals the first in // the list, or TestType occurs in the rest of the list. template class OccursInTuple> : public absl::disjunction< std::is_same, OccursInTuple>> {}; // The class HasDuplicates. Defines ::value as true in case the given list has // a duplicate, false otherwise. template class HasDuplicates; // Empty list has no duplicates. template <> class HasDuplicates<> : public std::false_type {}; // Non-empty list has a duplicate if the first appears in the rest, or if the // rest has a duplicate. template class HasDuplicates : public absl::disjunction< OccursInTuple>, HasDuplicates> {}; // The class IndexOf. Defines ::value as zero-based index of first element of // type T in the List. template struct IndexOf; template struct IndexOf> : public std::integral_constant {}; template struct IndexOf> : public std::integral_constant>::value> { }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_CORE_TEMPLATE_UTIL_H_ ================================================ FILE: cc/core/template_util_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/core/template_util.h" namespace crypto { namespace tink { namespace internal { namespace { class C0 {}; class C1 {}; class C2 {}; class C3 {}; class C4 {}; } // namespace static_assert(!HasDuplicates<>::value, ""); static_assert(!HasDuplicates::value, ""); static_assert(!HasDuplicates::value, ""); static_assert(!HasDuplicates::value, ""); static_assert(!HasDuplicates::value, ""); static_assert(HasDuplicates::value, ""); static_assert(HasDuplicates::value, ""); static_assert(HasDuplicates::value, ""); static_assert(HasDuplicates::value, ""); static_assert(HasDuplicates::value, ""); static_assert(IndexOf>::value == 0, ""); static_assert(IndexOf>::value == 1, ""); static_assert(IndexOf>::value == 2, ""); static_assert(IndexOf>::value == 3, ""); static_assert(IndexOf>::value == 0, ""); static_assert(IndexOf>::value == 1, ""); static_assert(IndexOf>::value == 2, ""); static_assert(IndexOf>::value == 3, ""); } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/core/version.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/version.h" namespace crypto { namespace tink { constexpr char Version::kTinkVersion[]; } // namespace tink } // namespace crypto ================================================ FILE: cc/core/version_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/version.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/internal/util.h" namespace crypto { namespace tink { namespace { using ::testing::AnyOf; using ::testing::MatchesRegex; TEST(VersionTest, VersionHasCorrectFormat) { // The regex represents Semantic Versioning syntax (www.semver.org), // i.e. three dot-separated numbers, with an optional suffix // that starts with a hyphen, to cover alpha/beta releases and // release candiates, for example: // 1.2.3 // 1.2.3-beta // 1.2.3-RC1 if (crypto::tink::internal::IsWindows()) { // Using the syntax in // https://github.com/google/googletest/blob/main/docs/advanced.md#regular-expression-syntax. EXPECT_THAT(Version::kTinkVersion, AnyOf(MatchesRegex(R"regex(\d+\.\d+\.\d+)regex"), MatchesRegex(R"regex(\d+\.\d+\.\d+-\w+)regex"))); } else { std::string version_regex = "[0-9]+[.][0-9]+[.][0-9]+(-[A-Za-z0-9]+)?"; EXPECT_THAT(Version::kTinkVersion, testing::MatchesRegex(version_regex)); } } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/crypto_format.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_CRYPTO_FORMAT_H_ #define TINK_CRYPTO_FORMAT_H_ #include #include #include #include "absl/strings/string_view.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // Constants and convenience methods that deal with the format // of the outputs handled by Tink. class CryptoFormat { public: // Prefix size of Tink and Legacy key types. static constexpr int kNonRawPrefixSize = 5; // Legacy prefix starts with \x00 and followed by a 4-byte key id. static constexpr int kLegacyPrefixSize = kNonRawPrefixSize; static constexpr uint8_t kLegacyStartByte = 0x00; // Tink prefix starts with \x01 and followed by a 4-byte key id. static constexpr int kTinkPrefixSize = kNonRawPrefixSize; static constexpr uint8_t kTinkStartByte = 0x01; // Raw prefix is empty. static constexpr int kRawPrefixSize = 0; static const absl::string_view kRawPrefix; // empty string // Generates the prefix for the outputs handled with the given key_info. // Returns an error if the prefix type 'output_prefix_type' is invalid. static crypto::tink::util::StatusOr GetOutputPrefix( const google::crypto::tink::KeysetInfo::KeyInfo& key_info); }; } // namespace tink } // namespace crypto #endif // TINK_CRYPTO_FORMAT_H_ ================================================ FILE: cc/daead/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "aes_siv_key_manager", hdrs = ["aes_siv_key_manager.h"], include_prefix = "tink/daead", deps = [ "//:core/key_type_manager", "//:core/template_util", "//:deterministic_aead", "//:input_stream", "//proto:aes_siv_cc_proto", "//proto:tink_cc_proto", "//subtle:aes_siv_boringssl", "//subtle:random", "//util:constants", "//util:errors", "//util:input_stream_util", "//util:protobuf_helper", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "deterministic_aead_wrapper", srcs = ["deterministic_aead_wrapper.cc"], hdrs = ["deterministic_aead_wrapper.h"], include_prefix = "tink/daead", deps = [ "//:crypto_format", "//:deterministic_aead", "//:primitive_set", "//:primitive_wrapper", "//internal:monitoring_util", "//internal:registry_impl", "//internal:util", "//monitoring", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "deterministic_aead_config", srcs = ["deterministic_aead_config.cc"], hdrs = ["deterministic_aead_config.h"], include_prefix = "tink/daead", visibility = ["//visibility:public"], deps = [ ":aes_siv_key_manager", ":aes_siv_proto_serialization", ":deterministic_aead_wrapper", "//:registry", "//config:tink_fips", "//proto:config_cc_proto", "//util:status", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/memory", ], ) cc_library( name = "deterministic_aead_factory", srcs = ["deterministic_aead_factory.cc"], hdrs = ["deterministic_aead_factory.h"], include_prefix = "tink/daead", deps = [ ":deterministic_aead_wrapper", "//:deterministic_aead", "//:key_manager", "//:keyset_handle", "//:registry", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", ], ) cc_library( name = "deterministic_aead_key_templates", srcs = ["deterministic_aead_key_templates.cc"], hdrs = ["deterministic_aead_key_templates.h"], include_prefix = "tink/daead", visibility = ["//visibility:public"], deps = [ "//proto:aes_siv_cc_proto", "//proto:common_cc_proto", "//proto:tink_cc_proto", ], ) cc_library( name = "failing_daead", srcs = ["failing_daead.cc"], hdrs = ["failing_daead.h"], include_prefix = "tink/daead", deps = [ "//:deterministic_aead", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "deterministic_aead_parameters", hdrs = ["deterministic_aead_parameters.h"], include_prefix = "tink/daead", deps = ["//:parameters"], ) cc_library( name = "deterministic_aead_key", hdrs = ["deterministic_aead_key.h"], include_prefix = "tink/daead", deps = [ ":deterministic_aead_parameters", "//:key", "@com_google_absl//absl/strings", ], ) cc_library( name = "aes_siv_parameters", srcs = ["aes_siv_parameters.cc"], hdrs = ["aes_siv_parameters.h"], include_prefix = "tink/daead", deps = [ ":deterministic_aead_parameters", "//:parameters", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "aes_siv_key", srcs = ["aes_siv_key.cc"], hdrs = ["aes_siv_key.h"], include_prefix = "tink/daead", deps = [ ":aes_siv_parameters", ":deterministic_aead_key", "//:key", "//:partial_key_access_token", "//:restricted_data", "//subtle:subtle_util", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "aes_siv_proto_serialization", srcs = ["aes_siv_proto_serialization.cc"], hdrs = ["aes_siv_proto_serialization.h"], include_prefix = "tink/daead", deps = [ ":aes_siv_key", ":aes_siv_parameters", "//:partial_key_access", "//:restricted_data", "//:secret_key_access_token", "//internal:key_parser", "//internal:key_serializer", "//internal:mutable_serialization_registry", "//internal:parameters_parser", "//internal:parameters_serializer", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//proto:aes_siv_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "config_v0", srcs = ["config_v0.cc"], hdrs = ["config_v0.h"], include_prefix = "tink/daead", deps = [ "//:configuration", "//daead/internal:config_v0", "@com_google_absl//absl/log:check", ], ) cc_library( name = "key_gen_config_v0", srcs = ["key_gen_config_v0.cc"], hdrs = ["key_gen_config_v0.h"], include_prefix = "tink/daead", deps = [ "//:key_gen_configuration", "//daead/internal:key_gen_config_v0", "@com_google_absl//absl/log:check", ], ) # tests cc_test( name = "aes_siv_key_manager_test", size = "small", srcs = ["aes_siv_key_manager_test.cc"], deps = [ ":aes_siv_key_manager", "//:deterministic_aead", "//proto:aes_siv_cc_proto", "//proto:tink_cc_proto", "//subtle:aes_siv_boringssl", "//util:istream_input_stream", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "deterministic_aead_wrapper_test", size = "small", srcs = ["deterministic_aead_wrapper_test.cc"], deps = [ ":deterministic_aead_wrapper", ":failing_daead", "//:crypto_format", "//:deterministic_aead", "//:primitive_set", "//:registry", "//internal:registry_impl", "//monitoring", "//monitoring:monitoring_client_mocks", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "deterministic_aead_config_test", size = "small", srcs = ["deterministic_aead_config_test.cc"], tags = ["fips"], deps = [ ":aes_siv_key", ":aes_siv_key_manager", ":aes_siv_parameters", ":deterministic_aead_config", ":deterministic_aead_key_templates", "//:deterministic_aead", "//:insecure_secret_key_access", "//:key", "//:keyset_handle", "//:parameters", "//:partial_key_access", "//:primitive_set", "//:registry", "//:restricted_data", "//config:global_registry", "//config:tink_fips", "//internal:mutable_serialization_registry", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//internal:serialization", "//proto:aes_siv_cc_proto", "//proto:tink_cc_proto", "//subtle:random", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "deterministic_aead_factory_test", size = "small", srcs = ["deterministic_aead_factory_test.cc"], deps = [ ":aes_siv_key_manager", ":deterministic_aead_config", ":deterministic_aead_factory", "//:core/key_manager_impl", "//:crypto_format", "//:deterministic_aead", "//:keyset_handle", "//internal:key_info", "//proto:aes_siv_cc_proto", "//util:status", "//util:test_keyset_handle", "//util:test_util", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "deterministic_aead_key_templates_test", size = "small", srcs = ["deterministic_aead_key_templates_test.cc"], deps = [ ":aes_siv_key_manager", ":deterministic_aead_key_templates", "//:core/key_manager_impl", "//:deterministic_aead", "//proto:aes_siv_cc_proto", "//proto:common_cc_proto", "//proto:tink_cc_proto", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "failing_daead_test", srcs = ["failing_daead_test.cc"], deps = [ ":failing_daead", "//:deterministic_aead", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_siv_parameters_test", srcs = ["aes_siv_parameters_test.cc"], deps = [ ":aes_siv_parameters", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_siv_key_test", srcs = ["aes_siv_key_test.cc"], deps = [ ":aes_siv_key", ":aes_siv_parameters", "//:partial_key_access", "//:restricted_data", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_siv_proto_serialization_test", size = "small", srcs = ["aes_siv_proto_serialization_test.cc"], deps = [ ":aes_siv_key", ":aes_siv_parameters", ":aes_siv_proto_serialization", "//:insecure_secret_key_access", "//:key", "//:parameters", "//:partial_key_access", "//:restricted_data", "//internal:mutable_serialization_registry", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//internal:serialization", "//proto:aes_siv_cc_proto", "//proto:tink_cc_proto", "//subtle:random", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "config_v0_test", srcs = ["config_v0_test.cc"], deps = [ ":config_v0", ":deterministic_aead_key_templates", ":key_gen_config_v0", "//:deterministic_aead", "//:keyset_handle", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/daead/CMakeLists.txt ================================================ tink_module(daead) add_subdirectory(subtle) add_subdirectory(internal) tink_cc_library( NAME aes_siv_key_manager SRCS aes_siv_key_manager.h DEPS absl::memory absl::status absl::strings tink::core::key_type_manager tink::core::template_util tink::core::deterministic_aead tink::core::input_stream tink::subtle::aes_siv_boringssl tink::subtle::random tink::util::constants tink::util::errors tink::util::input_stream_util tink::util::protobuf_helper tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::aes_siv_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME deterministic_aead_wrapper SRCS deterministic_aead_wrapper.cc deterministic_aead_wrapper.h DEPS absl::memory absl::status absl::strings tink::core::crypto_format tink::core::deterministic_aead tink::core::primitive_set tink::core::primitive_wrapper tink::internal::monitoring_util tink::internal::registry_impl tink::internal::util tink::monitoring::monitoring tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME deterministic_aead_config SRCS deterministic_aead_config.cc deterministic_aead_config.h DEPS tink::daead::aes_siv_key_manager tink::daead::aes_siv_proto_serialization tink::daead::deterministic_aead_wrapper absl::core_headers absl::memory tink::core::registry tink::config::tink_fips tink::util::status tink::proto::config_cc_proto ) tink_cc_library( NAME deterministic_aead_factory SRCS deterministic_aead_factory.cc deterministic_aead_factory.h DEPS tink::daead::deterministic_aead_wrapper absl::core_headers tink::core::deterministic_aead tink::core::key_manager tink::core::keyset_handle tink::core::registry tink::util::status tink::util::statusor ) tink_cc_library( NAME deterministic_aead_key_templates SRCS deterministic_aead_key_templates.cc deterministic_aead_key_templates.h DEPS tink::proto::aes_siv_cc_proto tink::proto::common_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME failing_daead SRCS failing_daead.cc failing_daead.h DEPS absl::memory absl::status absl::strings tink::core::deterministic_aead tink::util::status tink::util::statusor ) tink_cc_library( NAME deterministic_aead_parameters SRCS deterministic_aead_parameters.h DEPS tink::core::parameters ) tink_cc_library( NAME deterministic_aead_key SRCS deterministic_aead_key.h DEPS tink::daead::deterministic_aead_parameters absl::strings tink::core::key ) tink_cc_library( NAME aes_siv_parameters SRCS aes_siv_parameters.cc aes_siv_parameters.h DEPS tink::daead::deterministic_aead_parameters absl::status absl::strings tink::core::parameters tink::util::status tink::util::statusor ) tink_cc_library( NAME aes_siv_key SRCS aes_siv_key.cc aes_siv_key.h DEPS tink::daead::aes_siv_parameters tink::daead::deterministic_aead_key absl::status absl::strings absl::optional tink::core::key tink::core::partial_key_access_token tink::core::restricted_data tink::subtle::subtle_util tink::util::status tink::util::statusor ) tink_cc_library( NAME aes_siv_proto_serialization SRCS aes_siv_proto_serialization.cc aes_siv_proto_serialization.h DEPS tink::daead::aes_siv_key tink::daead::aes_siv_parameters absl::core_headers absl::status absl::string_view absl::optional tink::core::partial_key_access tink::core::restricted_data tink::core::secret_key_access_token tink::internal::key_parser tink::internal::key_serializer tink::internal::mutable_serialization_registry tink::internal::parameters_parser tink::internal::parameters_serializer tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::util::status tink::util::statusor tink::proto::aes_siv_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME config_v0 SRCS config_v0.cc config_v0.h DEPS absl::check tink::core::configuration tink::daead::internal::config_v0 ) tink_cc_library( NAME key_gen_config_v0 SRCS key_gen_config_v0.cc key_gen_config_v0.h DEPS absl::check tink::core::key_gen_configuration tink::daead::internal::key_gen_config_v0 ) # tests tink_cc_test( NAME aes_siv_key_manager_test SRCS aes_siv_key_manager_test.cc DEPS tink::daead::aes_siv_key_manager gmock absl::memory absl::status tink::core::deterministic_aead tink::subtle::aes_siv_boringssl tink::util::istream_input_stream tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::aes_siv_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME deterministic_aead_wrapper_test SRCS deterministic_aead_wrapper_test.cc DEPS tink::daead::deterministic_aead_wrapper tink::daead::failing_daead gmock absl::flat_hash_map absl::memory absl::status absl::string_view tink::core::crypto_format tink::core::deterministic_aead tink::core::primitive_set tink::core::registry tink::internal::registry_impl tink::monitoring::monitoring tink::monitoring::monitoring_client_mocks tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::tink_cc_proto ) tink_cc_test( NAME deterministic_aead_config_test SRCS deterministic_aead_config_test.cc DEPS tink::daead::aes_siv_key tink::daead::aes_siv_key_manager tink::daead::aes_siv_parameters tink::daead::deterministic_aead_config tink::daead::deterministic_aead_key_templates gmock absl::memory absl::status tink::core::deterministic_aead tink::core::insecure_secret_key_access tink::core::key tink::core::keyset_handle tink::core::parameters tink::core::partial_key_access tink::core::primitive_set tink::core::registry tink::core::restricted_data tink::config::global_registry tink::config::tink_fips tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::internal::serialization tink::subtle::random tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::aes_siv_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME deterministic_aead_factory_test SRCS deterministic_aead_factory_test.cc DEPS tink::daead::aes_siv_key_manager tink::daead::deterministic_aead_config tink::daead::deterministic_aead_factory gmock tink::core::key_manager_impl tink::core::crypto_format tink::core::deterministic_aead tink::core::keyset_handle tink::internal::key_info tink::util::status tink::util::test_keyset_handle tink::util::test_util tink::proto::aes_siv_cc_proto ) tink_cc_test( NAME deterministic_aead_key_templates_test SRCS deterministic_aead_key_templates_test.cc DEPS tink::daead::aes_siv_key_manager tink::daead::deterministic_aead_key_templates gmock tink::core::key_manager_impl tink::core::deterministic_aead tink::proto::aes_siv_cc_proto tink::proto::common_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME failing_daead_test SRCS failing_daead_test.cc DEPS tink::daead::failing_daead gmock absl::status tink::core::deterministic_aead tink::util::test_matchers ) tink_cc_test( NAME aes_siv_parameters_test SRCS aes_siv_parameters_test.cc DEPS tink::daead::aes_siv_parameters gmock absl::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME aes_siv_key_test SRCS aes_siv_key_test.cc DEPS tink::daead::aes_siv_key tink::daead::aes_siv_parameters gmock absl::status absl::optional tink::core::partial_key_access tink::core::restricted_data tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME aes_siv_proto_serialization_test SRCS aes_siv_proto_serialization_test.cc DEPS tink::daead::aes_siv_key tink::daead::aes_siv_parameters tink::daead::aes_siv_proto_serialization gmock absl::status absl::optional tink::core::insecure_secret_key_access tink::core::key tink::core::parameters tink::core::partial_key_access tink::core::restricted_data tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::internal::serialization tink::subtle::random tink::util::statusor tink::util::test_matchers tink::proto::aes_siv_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME config_v0_test SRCS config_v0_test.cc DEPS tink::daead::config_v0 tink::daead::deterministic_aead_key_templates tink::daead::key_gen_config_v0 gmock tink::core::deterministic_aead tink::core::keyset_handle tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) ================================================ FILE: cc/daead/aes_siv_key.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/daead/aes_siv_key.h" #include #include #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/types/optional.h" #include "tink/daead/aes_siv_parameters.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { util::StatusOr ComputeOutputPrefix( const AesSivParameters& parameters, absl::optional id_requirement) { switch (parameters.GetVariant()) { case AesSivParameters::Variant::kNoPrefix: return std::string(""); // Empty prefix. case AesSivParameters::Variant::kCrunchy: if (!id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "id requirement must have value with kCrunchy or kLegacy"); } return absl::StrCat(absl::HexStringToBytes("00"), subtle::BigEndian32(*id_requirement)); case AesSivParameters::Variant::kTink: if (!id_requirement.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "id requirement must have value with kTink"); } return absl::StrCat(absl::HexStringToBytes("01"), subtle::BigEndian32(*id_requirement)); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid variant: ", parameters.GetVariant())); } } } // namespace util::StatusOr AesSivKey::Create(const AesSivParameters& parameters, const RestrictedData& key_bytes, absl::optional id_requirement, PartialKeyAccessToken token) { if (parameters.KeySizeInBytes() != key_bytes.size()) { return util::Status(absl::StatusCode::kInvalidArgument, "Key size does not match AES-SIV parameters"); } if (parameters.HasIdRequirement() && !id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key without ID requirement with parameters with ID " "requirement"); } if (!parameters.HasIdRequirement() && id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key with ID requirement with parameters without ID " "requirement"); } util::StatusOr output_prefix = ComputeOutputPrefix(parameters, id_requirement); if (!output_prefix.ok()) { return output_prefix.status(); } return AesSivKey(parameters, key_bytes, id_requirement, *std::move(output_prefix)); } bool AesSivKey::operator==(const Key& other) const { const AesSivKey* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (GetParameters() != that->GetParameters()) { return false; } if (id_requirement_ != that->id_requirement_) { return false; } return key_bytes_ == that->key_bytes_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/aes_siv_key.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_DAEAD_AES_SIV_KEY_H_ #define TINK_DAEAD_AES_SIV_KEY_H_ #include #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/daead/aes_siv_parameters.h" #include "tink/daead/deterministic_aead_key.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Represents a Deterministic AEAD that uses AES-SIV. class AesSivKey : public DeterministicAeadKey { public: // Copyable and movable. AesSivKey(const AesSivKey& other) = default; AesSivKey& operator=(const AesSivKey& other) = default; AesSivKey(AesSivKey&& other) = default; AesSivKey& operator=(AesSivKey&& other) = default; // Creates a new AES-SIV key. If the parameters specify a variant that uses // a prefix, then the id is used to compute this prefix. static util::StatusOr Create(const AesSivParameters& parameters, const RestrictedData& key_bytes, absl::optional id_requirement, PartialKeyAccessToken token); // Returns the underlying AES-SIV key. const RestrictedData& GetKeyBytes(PartialKeyAccessToken token) const { return key_bytes_; } absl::string_view GetOutputPrefix() const override { return output_prefix_; } const AesSivParameters& GetParameters() const override { return parameters_; } absl::optional GetIdRequirement() const override { return id_requirement_; } bool operator==(const Key& other) const override; private: AesSivKey(const AesSivParameters& parameters, const RestrictedData& key_bytes, absl::optional id_requirement, std::string output_prefix) : parameters_(parameters), key_bytes_(key_bytes), id_requirement_(id_requirement), output_prefix_(std::move(output_prefix)) {} AesSivParameters parameters_; RestrictedData key_bytes_; absl::optional id_requirement_; std::string output_prefix_; }; } // namespace tink } // namespace crypto #endif // TINK_DAEAD_AES_SIV_KEY_H_ ================================================ FILE: cc/daead/aes_siv_key_manager.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_DAEAD_AES_SIV_KEY_MANAGER_H_ #define TINK_DAEAD_AES_SIV_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/deterministic_aead.h" #include "tink/input_stream.h" #include "tink/subtle/aes_siv_boringssl.h" #include "tink/subtle/random.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/input_stream_util.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/aes_siv.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class AesSivKeyManager : public KeyTypeManager> { public: class DeterministicAeadFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::AesSivKey& key) const override { return subtle::AesSivBoringSsl::New( util::SecretDataFromStringView(key.key_value())); } }; AesSivKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::SYMMETRIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::AesSivKey& key) const override { crypto::tink::util::Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; return ValidateKeySize(key.key_value().size()); } crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::AesSivKeyFormat& key_format) const override { return ValidateKeySize(key_format.key_size()); } crypto::tink::util::StatusOr CreateKey( const google::crypto::tink::AesSivKeyFormat& key_format) const override { google::crypto::tink::AesSivKey key; key.set_version(get_version()); key.set_key_value(subtle::Random::GetRandomBytes(key_format.key_size())); return key; } crypto::tink::util::StatusOr DeriveKey( const google::crypto::tink::AesSivKeyFormat& key_format, InputStream* input_stream) const override { crypto::tink::util::Status status = ValidateVersion(key_format.version(), get_version()); if (!status.ok()) return status; crypto::tink::util::StatusOr randomness = ReadBytesFromStream(key_format.key_size(), input_stream); if (!randomness.ok()) { if (randomness.status().code() == absl::StatusCode::kOutOfRange) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, "Could not get enough pseudorandomness from input stream"); } return randomness.status(); } google::crypto::tink::AesSivKey key; key.set_version(get_version()); key.set_key_value(randomness.value()); return key; } private: crypto::tink::util::Status ValidateKeySize(uint32_t key_size) const { if (key_size != kKeySizeInBytes) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid key size: key size is ", key_size, " bytes; supported size: ", kKeySizeInBytes, " bytes.")); } return crypto::tink::util::OkStatus(); } const std::string key_type_ = absl::StrCat( kTypeGoogleapisCom, google::crypto::tink::AesSivKey().GetTypeName()); const int kKeySizeInBytes = 64; }; } // namespace tink } // namespace crypto #endif // TINK_DAEAD_AES_SIV_KEY_MANAGER_H_ ================================================ FILE: cc/daead/aes_siv_key_manager_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/daead/aes_siv_key_manager.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/deterministic_aead.h" #include "tink/subtle/aes_siv_boringssl.h" #include "tink/util/istream_input_stream.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/aes_siv.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::AesSivKey; using ::google::crypto::tink::AesSivKeyFormat; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::Ne; using ::testing::Not; using ::testing::SizeIs; namespace { TEST(AesSivKeyManagerTest, Basics) { EXPECT_THAT(AesSivKeyManager().get_version(), Eq(0)); EXPECT_THAT(AesSivKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.AesSivKey")); EXPECT_THAT(AesSivKeyManager().key_material_type(), Eq(google::crypto::tink::KeyData::SYMMETRIC)); } TEST(AesSivKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(AesSivKeyManager().ValidateKey(AesSivKey()), Not(IsOk())); } TEST(AesSivKeyManagerTest, ValidateEmptyKeyFormat) { EXPECT_THAT(AesSivKeyManager().ValidateKeyFormat(AesSivKeyFormat()), Not(IsOk())); } TEST(AesSivKeyManagerTest, ValidKeyFormat) { AesSivKeyFormat format; format.set_key_size(64); EXPECT_THAT(AesSivKeyManager().ValidateKeyFormat(format), IsOk()); } TEST(AesSivKeyManagerTest, ValidateKeyFormatWithWrongSizes) { AesSivKeyFormat format; for (int i = 0; i < 64; ++i) { format.set_key_size(i); EXPECT_THAT(AesSivKeyManager().ValidateKeyFormat(format), Not(IsOk())) << " for length " << i; } for (int i = 65; i <= 200; ++i) { format.set_key_size(i); EXPECT_THAT(AesSivKeyManager().ValidateKeyFormat(format), Not(IsOk())) << " for length " << i; } } TEST(AesSivKeyManagerTest, CreateKey) { AesSivKeyFormat format; format.set_key_size(64); auto key_or = AesSivKeyManager().CreateKey(format); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().key_value(), SizeIs(format.key_size())); EXPECT_THAT(key_or.value().version(), Eq(0)); } TEST(AesSivKeyManagerTest, CreateKeyIsValid) { AesSivKeyFormat format; format.set_key_size(64); auto key_or = AesSivKeyManager().CreateKey(format); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(AesSivKeyManager().ValidateKey(key_or.value()), IsOk()); } TEST(AesSivKeyManagerTest, MultipleCreateCallsCreateDifferentKeys) { AesSivKeyFormat format; AesSivKeyManager manager; format.set_key_size(64); auto key1_or = manager.CreateKey(format); ASSERT_THAT(key1_or, IsOk()); auto key2_or = manager.CreateKey(format); ASSERT_THAT(key2_or, IsOk()); EXPECT_THAT(key1_or.value().key_value(), Ne(key2_or.value().key_value())); } TEST(AesSivKeyManagerTest, DeriveKey) { util::IstreamInputStream input_stream{absl::make_unique( "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef")}; AesSivKeyFormat format; format.set_key_size(64); format.set_version(0); auto key_or = AesSivKeyManager().DeriveKey(format, &input_stream); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().key_value(), SizeIs(64)); EXPECT_THAT(key_or.value().version(), Eq(0)); } TEST(AesSivKeyManagerTest, DeriveKeyFromLongSeed) { util::IstreamInputStream input_stream{absl::make_unique( "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefXXXXX")}; AesSivKeyFormat format; format.set_key_size(64); format.set_version(0); auto key_or = AesSivKeyManager().DeriveKey(format, &input_stream); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT( key_or.value().key_value(), Eq("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef")); } TEST(AesSivKeyManagerTest, DeriveKeyWithoutEnoughEntropy) { AesSivKeyFormat format; format.set_key_size(64); format.set_version(0); util::IstreamInputStream input_stream{ absl::make_unique("0123456789abcdef0123456789abcdef")}; auto key_or = AesSivKeyManager().DeriveKey(format, &input_stream); ASSERT_THAT(key_or.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("pseudorandomness"))); } TEST(AesSivKeyManagerTest, DeriveKeyWrongVersion) { util::IstreamInputStream input_stream{absl::make_unique( "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef")}; AesSivKeyFormat format; format.set_key_size(64); format.set_version(1); auto key_or = AesSivKeyManager().DeriveKey(format, &input_stream); ASSERT_THAT(key_or.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("version"))); } TEST(AesSivKeyManagerTest, ValidateKey) { AesSivKey key; *key.mutable_key_value() = std::string(64, 'a'); key.set_version(0); EXPECT_THAT(AesSivKeyManager().ValidateKey(key), IsOk()); } TEST(AesSivKeyManagerTest, ValidateKeyStringLength) { AesSivKey key; key.set_version(0); for (int i = 0 ; i < 64; ++i) { *key.mutable_key_value() = std::string(i, 'a'); EXPECT_THAT(AesSivKeyManager().ValidateKey(key), Not(IsOk())); } for (int i = 65 ; i <= 200; ++i) { *key.mutable_key_value() = std::string(i, 'a'); EXPECT_THAT(AesSivKeyManager().ValidateKey(key), Not(IsOk())); } } TEST(AesSivKeyManagerTest, ValidateKeyVersion) { AesSivKey key; *key.mutable_key_value() = std::string(64, 'a'); key.set_version(1); EXPECT_THAT(AesSivKeyManager().ValidateKey(key), Not(IsOk())); } TEST(AesSivKeyManagerTest, GetPrimitive) { AesSivKeyFormat format; format.set_key_size(64); auto key_or = AesSivKeyManager().CreateKey(format); ASSERT_THAT(key_or, IsOk()); auto daead_or = AesSivKeyManager().GetPrimitive(key_or.value()); ASSERT_THAT(daead_or, IsOk()); auto direct_daead_or = subtle::AesSivBoringSsl::New( util::SecretDataFromStringView(key_or.value().key_value())); ASSERT_THAT(direct_daead_or, IsOk()); auto encryption_or = daead_or.value()->EncryptDeterministically("123", "abcd"); ASSERT_THAT(encryption_or, IsOk()); auto direct_encryption_or = direct_daead_or.value()->EncryptDeterministically("123", "abcd"); ASSERT_THAT(direct_encryption_or, IsOk()); ASSERT_THAT(encryption_or.value(), Eq(direct_encryption_or.value())); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/aes_siv_key_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/daead/aes_siv_key.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/daead/aes_siv_parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Combine; using ::testing::Eq; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { AesSivParameters::Variant variant; absl::optional id_requirement; std::string output_prefix; }; using AesSivKeyTest = TestWithParam>; INSTANTIATE_TEST_SUITE_P( AesSivKeyTestSuite, AesSivKeyTest, Combine(Values(32, 48, 64), Values(TestCase{AesSivParameters::Variant::kTink, 0x02030400, std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{AesSivParameters::Variant::kCrunchy, 0x01030005, std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{AesSivParameters::Variant::kNoPrefix, absl::nullopt, ""}))); TEST_P(AesSivKeyTest, CreateSucceeds) { int key_size; TestCase test_case; std::tie(key_size, test_case) = GetParam(); util::StatusOr params = AesSivParameters::Create(key_size, test_case.variant); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(key_size); util::StatusOr key = AesSivKey::Create( *params, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); EXPECT_THAT(key->GetParameters(), Eq(*params)); EXPECT_THAT(key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(key->GetOutputPrefix(), Eq(test_case.output_prefix)); } TEST(AesSivKeyTest, CreateKeyWithMismatchedKeySizeFails) { // Key size parameter is 64 bytes. util::StatusOr params = AesSivParameters::Create( /*key_size_in_bytes=*/64, AesSivParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); // Key material is 32 bytes (another valid key length). RestrictedData mismatched_secret = RestrictedData(/*num_random_bytes=*/32); EXPECT_THAT(AesSivKey::Create(*params, mismatched_secret, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesSivKeyTest, CreateKeyWithInvalidIdRequirementFails) { util::StatusOr no_prefix_params = AesSivParameters::Create( /*key_size_in_bytes=*/64, AesSivParameters::Variant::kNoPrefix); ASSERT_THAT(no_prefix_params, IsOk()); util::StatusOr tink_params = AesSivParameters::Create( /*key_size_in_bytes=*/64, AesSivParameters::Variant::kTink); ASSERT_THAT(tink_params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/64); EXPECT_THAT(AesSivKey::Create(*no_prefix_params, secret, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT( AesSivKey::Create(*tink_params, secret, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(AesSivKeyTest, GetKeyBytes) { int key_size; TestCase test_case; std::tie(key_size, test_case) = GetParam(); util::StatusOr params = AesSivParameters::Create(key_size, test_case.variant); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(key_size); util::StatusOr key = AesSivKey::Create( *params, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); EXPECT_THAT(key->GetKeyBytes(GetPartialKeyAccess()), Eq(secret)); } TEST_P(AesSivKeyTest, KeyEquals) { int key_size; TestCase test_case; std::tie(key_size, test_case) = GetParam(); util::StatusOr params = AesSivParameters::Create(key_size, test_case.variant); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(key_size); util::StatusOr key = AesSivKey::Create( *params, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = AesSivKey::Create( *params, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key == *other_key); EXPECT_TRUE(*other_key == *key); EXPECT_FALSE(*key != *other_key); EXPECT_FALSE(*other_key != *key); } TEST(AesSivKeyTest, DifferentVariantNotEqual) { util::StatusOr crunchy_params = AesSivParameters::Create( /*key_size_in_bytes=*/64, AesSivParameters::Variant::kCrunchy); ASSERT_THAT(crunchy_params, IsOk()); util::StatusOr tink_params = AesSivParameters::Create( /*key_size_in_bytes=*/64, AesSivParameters::Variant::kTink); ASSERT_THAT(tink_params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/64); util::StatusOr key = AesSivKey::Create(*crunchy_params, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = AesSivKey::Create(*tink_params, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST(AesSivKeyTest, DifferentSecretDataNotEqual) { util::StatusOr params = AesSivParameters::Create( /*key_size_in_bytes=*/64, AesSivParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); RestrictedData secret1 = RestrictedData(/*num_random_bytes=*/64); RestrictedData secret2 = RestrictedData(/*num_random_bytes=*/64); util::StatusOr key = AesSivKey::Create( *params, secret1, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = AesSivKey::Create( *params, secret2, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST(AesSivKeyTest, DifferentIdRequirementNotEqual) { util::StatusOr params = AesSivParameters::Create( /*key_size_in_bytes=*/64, AesSivParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/64); util::StatusOr key = AesSivKey::Create( *params, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = AesSivKey::Create( *params, secret, /*id_requirement=*/0x02030405, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/aes_siv_parameters.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/daead/aes_siv_parameters.h" #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/parameters.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { util::StatusOr AesSivParameters::Create(int key_size_in_bytes, Variant variant) { if (key_size_in_bytes != 32 && key_size_in_bytes != 48 && key_size_in_bytes != 64) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Key size should be 32, 48, or 64 bytes, got ", key_size_in_bytes, " bytes.")); } static const std::set* supported_variants = new std::set( {Variant::kTink, Variant::kCrunchy, Variant::kNoPrefix}); if (supported_variants->find(variant) == supported_variants->end()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create AES-SIV parameters with unknown variant."); } return AesSivParameters(key_size_in_bytes, variant); } bool AesSivParameters::operator==(const Parameters& other) const { const AesSivParameters* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (key_size_in_bytes_ != that->key_size_in_bytes_) { return false; } if (variant_ != that->variant_) { return false; } return true; } } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/aes_siv_parameters.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_DAEAD_AES_SIV_PARAMETERS_H_ #define TINK_DAEAD_AES_SIV_PARAMETERS_H_ #include "tink/daead/deterministic_aead_parameters.h" #include "tink/parameters.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Describes the parameters of an `AesSivKey`. class AesSivParameters : public DeterministicAeadParameters { public: // Description of the output prefix prepended to the ciphertext. enum class Variant : int { // Prepends '0x01' to the ciphertext. kTink = 1, // Prepends '0x00' to the ciphertext. kCrunchy = 2, // Does not prepend any prefix (i.e., keys must have no ID requirement). kNoPrefix = 3, // Added to guard from failures that may be caused by future expansions. kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Copyable and movable. AesSivParameters(const AesSivParameters& other) = default; AesSivParameters& operator=(const AesSivParameters& other) = default; AesSivParameters(AesSivParameters&& other) = default; AesSivParameters& operator=(AesSivParameters&& other) = default; // Creates `AesSivParameters` object from `key_size_in_bytes` and `variant`. // Only allows 32-, 48-, and 64-byte key sizes as specified in RFC 5297. static util::StatusOr Create(int key_size_in_bytes, Variant variant); int KeySizeInBytes() const { return key_size_in_bytes_; } Variant GetVariant() const { return variant_; } bool HasIdRequirement() const override { return variant_ != Variant::kNoPrefix; } bool operator==(const Parameters& other) const override; private: AesSivParameters(int key_size_in_bytes, Variant variant) : key_size_in_bytes_(key_size_in_bytes), variant_(variant) {} int key_size_in_bytes_; Variant variant_; }; } // namespace tink } // namespace crypto #endif // TINK_DAEAD_AES_SIV_PARAMETERS_H_ ================================================ FILE: cc/daead/aes_siv_parameters_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/daead/aes_siv_parameters.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Combine; using ::testing::Eq; using ::testing::IsTrue; using ::testing::TestWithParam; using ::testing::Values; struct CreateTestCase { AesSivParameters::Variant variant; int key_size; bool has_id_requirement; }; using AesSivParametersBuildTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( AesSivParametersBuildTestSuite, AesSivParametersBuildTest, Values(CreateTestCase{AesSivParameters::Variant::kTink, /*key_size=*/32, /*has_id_requirement=*/true}, CreateTestCase{AesSivParameters::Variant::kCrunchy, /*key_size=*/48, /*has_id_requirement=*/true}, CreateTestCase{AesSivParameters::Variant::kNoPrefix, /*key_size=*/64, /*has_id_requirement=*/false})); TEST_P(AesSivParametersBuildTest, Create) { CreateTestCase test_case = GetParam(); util::StatusOr parameters = AesSivParameters::Create(test_case.key_size, test_case.variant); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->KeySizeInBytes(), Eq(test_case.key_size)); EXPECT_THAT(parameters->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(parameters->HasIdRequirement(), Eq(test_case.has_id_requirement)); } TEST(AesSivParametersTest, CreateWithInvalidVariantFails) { EXPECT_THAT(AesSivParameters::Create( /*key_size_in_bytes=*/64, AesSivParameters::Variant:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesSivParametersTest, CreateWithInvalidKeySizeFails) { EXPECT_THAT(AesSivParameters::Create(/*key_size_in_bytes=*/31, AesSivParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesSivParameters::Create(/*key_size_in_bytes=*/33, AesSivParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesSivParameters::Create(/*key_size_in_bytes=*/47, AesSivParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesSivParameters::Create(/*key_size_in_bytes=*/49, AesSivParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesSivParameters::Create(/*key_size_in_bytes=*/63, AesSivParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesSivParameters::Create(/*key_size_in_bytes=*/65, AesSivParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesSivParametersTest, CopyConstructor) { util::StatusOr parameters = AesSivParameters::Create( /*key_size_in_bytes=*/64, AesSivParameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); AesSivParameters copy(*parameters); EXPECT_THAT(copy.KeySizeInBytes(), Eq(64)); EXPECT_THAT(copy.GetVariant(), Eq(AesSivParameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); } TEST(AesSivParametersTest, CopyAssignment) { util::StatusOr parameters = AesSivParameters::Create( /*key_size_in_bytes=*/64, AesSivParameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); AesSivParameters copy = *parameters; EXPECT_THAT(copy.KeySizeInBytes(), Eq(64)); EXPECT_THAT(copy.GetVariant(), Eq(AesSivParameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); } using AesSivParametersVariantTest = TestWithParam>; INSTANTIATE_TEST_SUITE_P(AesSivParametersVariantTestSuite, AesSivParametersVariantTest, Combine(Values(32, 48, 64), Values(AesSivParameters::Variant::kTink, AesSivParameters::Variant::kCrunchy, AesSivParameters::Variant::kNoPrefix))); TEST_P(AesSivParametersVariantTest, ParametersEquals) { int key_size; AesSivParameters::Variant variant; std::tie(key_size, variant) = GetParam(); util::StatusOr parameters = AesSivParameters::Create(key_size, variant); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesSivParameters::Create(key_size, variant); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters == *other_parameters); EXPECT_TRUE(*other_parameters == *parameters); EXPECT_FALSE(*parameters != *other_parameters); EXPECT_FALSE(*other_parameters != *parameters); } TEST(AesSivParametersTest, KeySizeNotEqual) { util::StatusOr parameters = AesSivParameters::Create( /*key_size_in_bytes=*/48, AesSivParameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesSivParameters::Create( /*key_size_in_bytes=*/64, AesSivParameters::Variant::kTink); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(AesSivParametersTest, VariantNotEqual) { util::StatusOr parameters = AesSivParameters::Create( /*key_size_in_bytes=*/64, AesSivParameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesSivParameters::Create( /*key_size_in_bytes=*/64, AesSivParameters::Variant::kNoPrefix); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/aes_siv_proto_serialization.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/daead/aes_siv_proto_serialization.h" #include #include "absl/base/attributes.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/daead/aes_siv_key.h" #include "tink/daead/aes_siv_parameters.h" #include "tink/internal/key_parser.h" #include "tink/internal/key_serializer.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/parameters_parser.h" #include "tink/internal/parameters_serializer.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/secret_key_access_token.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/aes_siv.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::google::crypto::tink::AesSivKeyFormat; using ::google::crypto::tink::OutputPrefixType; using AesSivProtoParametersParserImpl = internal::ParametersParserImpl; using AesSivProtoParametersSerializerImpl = internal::ParametersSerializerImpl; using AesSivProtoKeyParserImpl = internal::KeyParserImpl; using AesSivProtoKeySerializerImpl = internal::KeySerializerImpl; const absl::string_view kTypeUrl = "type.googleapis.com/google.crypto.tink.AesSivKey"; util::StatusOr ToVariant( OutputPrefixType output_prefix_type) { switch (output_prefix_type) { case OutputPrefixType::LEGACY: ABSL_FALLTHROUGH_INTENDED; // Parse LEGACY output prefix as CRUNCHY. case OutputPrefixType::CRUNCHY: return AesSivParameters::Variant::kCrunchy; case OutputPrefixType::RAW: return AesSivParameters::Variant::kNoPrefix; case OutputPrefixType::TINK: return AesSivParameters::Variant::kTink; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine AesSivParameters::Variant"); } } util::StatusOr ToOutputPrefixType( AesSivParameters::Variant variant) { switch (variant) { case AesSivParameters::Variant::kCrunchy: return OutputPrefixType::CRUNCHY; case AesSivParameters::Variant::kNoPrefix: return OutputPrefixType::RAW; case AesSivParameters::Variant::kTink: return OutputPrefixType::TINK; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine output prefix type"); } } util::StatusOr ParseParameters( const internal::ProtoParametersSerialization& serialization) { if (serialization.GetKeyTemplate().type_url() != kTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing AesSivParameters."); } AesSivKeyFormat proto_key_format; if (!proto_key_format.ParseFromString( serialization.GetKeyTemplate().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse AesSivKeyFormat proto"); } if (proto_key_format.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } util::StatusOr variant = ToVariant(serialization.GetKeyTemplate().output_prefix_type()); if (!variant.ok()) return variant.status(); return AesSivParameters::Create(proto_key_format.key_size(), *variant); } util::StatusOr SerializeParameters( const AesSivParameters& parameters) { util::StatusOr output_prefix_type = ToOutputPrefixType(parameters.GetVariant()); if (!output_prefix_type.ok()) return output_prefix_type.status(); AesSivKeyFormat proto_key_format; proto_key_format.set_key_size(parameters.KeySizeInBytes()); return internal::ProtoParametersSerialization::Create( kTypeUrl, *output_prefix_type, proto_key_format.SerializeAsString()); } util::StatusOr ParseKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (serialization.TypeUrl() != kTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing AesSivKey."); } if (!token.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "SecretKeyAccess is required"); } google::crypto::tink::AesSivKey proto_key; const RestrictedData& restricted_data = serialization.SerializedKeyProto(); if (!proto_key.ParseFromString(restricted_data.GetSecret(*token))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse AesSivKey proto"); } if (proto_key.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } util::StatusOr variant = ToVariant(serialization.GetOutputPrefixType()); if (!variant.ok()) return variant.status(); util::StatusOr parameters = AesSivParameters::Create(proto_key.key_value().length(), *variant); if (!parameters.ok()) return parameters.status(); return AesSivKey::Create( *parameters, RestrictedData(proto_key.key_value(), *token), serialization.IdRequirement(), GetPartialKeyAccess()); } util::StatusOr SerializeKey( const AesSivKey& key, absl::optional token) { util::StatusOr restricted_input = key.GetKeyBytes(GetPartialKeyAccess()); if (!restricted_input.ok()) return restricted_input.status(); if (!token.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "SecretKeyAccess is required"); } google::crypto::tink::AesSivKey proto_key; proto_key.set_version(0); // OSS proto library complains if input is not converted to a string. proto_key.set_key_value(std::string(restricted_input->GetSecret(*token))); util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetParameters().GetVariant()); if (!output_prefix_type.ok()) return output_prefix_type.status(); RestrictedData restricted_output = RestrictedData(proto_key.SerializeAsString(), *token); return internal::ProtoKeySerialization::Create( kTypeUrl, restricted_output, google::crypto::tink::KeyData::SYMMETRIC, *output_prefix_type, key.GetIdRequirement()); } AesSivProtoParametersParserImpl* AesSivProtoParametersParser() { static auto* parser = new AesSivProtoParametersParserImpl(kTypeUrl, ParseParameters); return parser; } AesSivProtoParametersSerializerImpl* AesSivProtoParametersSerializer() { static auto* serializer = new AesSivProtoParametersSerializerImpl(kTypeUrl, SerializeParameters); return serializer; } AesSivProtoKeyParserImpl* AesSivProtoKeyParser() { static auto* parser = new AesSivProtoKeyParserImpl(kTypeUrl, ParseKey); return parser; } AesSivProtoKeySerializerImpl* AesSivProtoKeySerializer() { static auto* serializer = new AesSivProtoKeySerializerImpl(SerializeKey); return serializer; } } // namespace util::Status RegisterAesSivProtoSerialization() { util::Status status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersParser(AesSivProtoParametersParser()); if (!status.ok()) return status; status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersSerializer(AesSivProtoParametersSerializer()); if (!status.ok()) return status; status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(AesSivProtoKeyParser()); if (!status.ok()) return status; return internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(AesSivProtoKeySerializer()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/aes_siv_proto_serialization.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_DAEAD_AES_SIV_PROTO_SERIALIZATION_H_ #define TINK_DAEAD_AES_SIV_PROTO_SERIALIZATION_H_ #include "tink/util/status.h" namespace crypto { namespace tink { // Registers proto parsers and serializers for AES-SIV parameters and keys. crypto::tink::util::Status RegisterAesSivProtoSerialization(); } // namespace tink } // namespace crypto #endif // TINK_DAEAD_AES_SIV_PROTO_SERIALIZATION_H_ ================================================ FILE: cc/daead/aes_siv_proto_serialization_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/daead/aes_siv_proto_serialization.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/daead/aes_siv_key.h" #include "tink/daead/aes_siv_parameters.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/subtle/random.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/aes_siv.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::subtle::Random; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::AesSivKeyFormat; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::IsTrue; using ::testing::NotNull; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { AesSivParameters::Variant variant; OutputPrefixType output_prefix_type; int key_size; absl::optional id; std::string output_prefix; }; class AesSivProtoSerializationTest : public TestWithParam { protected: void SetUp() override { internal::MutableSerializationRegistry::GlobalInstance().Reset(); } }; TEST_F(AesSivProtoSerializationTest, RegisterTwiceSucceeds) { ASSERT_THAT(RegisterAesSivProtoSerialization(), IsOk()); ASSERT_THAT(RegisterAesSivProtoSerialization(), IsOk()); } INSTANTIATE_TEST_SUITE_P( AesSivProtoSerializationTestSuite, AesSivProtoSerializationTest, Values(TestCase{AesSivParameters::Variant::kTink, OutputPrefixType::TINK, /*key_size=*/32, /*id=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{AesSivParameters::Variant::kCrunchy, OutputPrefixType::CRUNCHY, /*key_size=*/48, /*id=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{AesSivParameters::Variant::kNoPrefix, OutputPrefixType::RAW, /*key_size=*/64, /*id=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(AesSivProtoSerializationTest, ParseParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesSivProtoSerialization(), IsOk()); AesSivKeyFormat key_format_proto; key_format_proto.set_version(0); key_format_proto.set_key_size(test_case.key_size); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.AesSivKey", test_case.output_prefix_type, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(params, IsOk()); EXPECT_THAT((*params)->HasIdRequirement(), test_case.id.has_value()); const AesSivParameters* siv_params = dynamic_cast(params->get()); ASSERT_THAT(siv_params, NotNull()); EXPECT_THAT(siv_params->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(siv_params->KeySizeInBytes(), Eq(test_case.key_size)); } TEST_F(AesSivProtoSerializationTest, ParseParametersWithInvalidSerialization) { ASSERT_THAT(RegisterAesSivProtoSerialization(), IsOk()); AesSivKeyFormat key_format_proto; key_format_proto.set_version(0); key_format_proto.set_key_size(64); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.AesSivKey", OutputPrefixType::RAW, "invalid_serialization"); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(AesSivProtoSerializationTest, ParseParametersWithUnkownOutputPrefix) { ASSERT_THAT(RegisterAesSivProtoSerialization(), IsOk()); AesSivKeyFormat key_format_proto; key_format_proto.set_version(0); key_format_proto.set_key_size(64); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.AesSivKey", OutputPrefixType::UNKNOWN_PREFIX, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(AesSivProtoSerializationTest, ParseParametersWithInvalidVersion) { ASSERT_THAT(RegisterAesSivProtoSerialization(), IsOk()); AesSivKeyFormat key_format_proto; key_format_proto.set_version(1); key_format_proto.set_key_size(64); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.AesSivKey", OutputPrefixType::RAW, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(AesSivProtoSerializationTest, SerializeParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesSivProtoSerialization(), IsOk()); util::StatusOr parameters = AesSivParameters::Create(test_case.key_size, test_case.variant); ASSERT_THAT(parameters, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( *parameters); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq("type.googleapis.com/google.crypto.tink.AesSivKey")); const internal::ProtoParametersSerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->GetKeyTemplate().type_url(), Eq("type.googleapis.com/google.crypto.tink.AesSivKey")); EXPECT_THAT(proto_serialization->GetKeyTemplate().output_prefix_type(), Eq(test_case.output_prefix_type)); AesSivKeyFormat key_format; ASSERT_THAT( key_format.ParseFromString(proto_serialization->GetKeyTemplate().value()), IsTrue()); EXPECT_THAT(key_format.key_size(), Eq(test_case.key_size)); } TEST_P(AesSivProtoSerializationTest, ParseKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesSivProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(test_case.key_size); google::crypto::tink::AesSivKey key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesSivKey", serialized_key, KeyData::SYMMETRIC, test_case.output_prefix_type, test_case.id); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); EXPECT_THAT((*key)->GetIdRequirement(), Eq(test_case.id)); EXPECT_THAT((*key)->GetParameters().HasIdRequirement(), test_case.id.has_value()); util::StatusOr expected_parameters = AesSivParameters::Create(test_case.key_size, test_case.variant); ASSERT_THAT(expected_parameters, IsOk()); util::StatusOr expected_key = AesSivKey::Create( *expected_parameters, RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(expected_key, IsOk()); EXPECT_THAT(**key, Eq(*expected_key)); } TEST_F(AesSivProtoSerializationTest, ParseLegacyKeyAsCrunchy) { ASSERT_THAT(RegisterAesSivProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(64); google::crypto::tink::AesSivKey key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesSivKey", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::LEGACY, /*id_requirement=*/123); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); const AesSivKey* aes_siv_key = dynamic_cast(key->get()); ASSERT_THAT(aes_siv_key, NotNull()); EXPECT_THAT(aes_siv_key->GetParameters().GetVariant(), Eq(AesSivParameters::Variant::kCrunchy)); } TEST_F(AesSivProtoSerializationTest, ParseKeyWithInvalidSerialization) { ASSERT_THAT(RegisterAesSivProtoSerialization(), IsOk()); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesSivKey", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(AesSivProtoSerializationTest, ParseKeyNoSecretKeyAccess) { ASSERT_THAT(RegisterAesSivProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(64); google::crypto::tink::AesSivKey key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesSivKey", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(AesSivProtoSerializationTest, ParseKeyWithInvalidVersion) { ASSERT_THAT(RegisterAesSivProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(64); google::crypto::tink::AesSivKey key_proto; key_proto.set_version(1); // Invalid version number. key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesSivKey", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(AesSivProtoSerializationTest, SerializeKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesSivProtoSerialization(), IsOk()); util::StatusOr parameters = AesSivParameters::Create(test_case.key_size, test_case.variant); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(test_case.key_size); util::StatusOr key = AesSivKey::Create( *parameters, RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq("type.googleapis.com/google.crypto.tink.AesSivKey")); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq("type.googleapis.com/google.crypto.tink.AesSivKey")); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::SYMMETRIC)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id)); google::crypto::tink::AesSivKey proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.key_value().size(), Eq(test_case.key_size)); } TEST_F(AesSivProtoSerializationTest, SerializeKeyNoSecretKeyAccess) { ASSERT_THAT(RegisterAesSivProtoSerialization(), IsOk()); util::StatusOr parameters = AesSivParameters::Create( /*key_size_in_bytes=*/64, AesSivParameters::Variant::kNoPrefix); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(64); util::StatusOr key = AesSivKey::Create( *parameters, RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey(*key, absl::nullopt); EXPECT_THAT(serialization.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/daead/config_v0.h" #include "absl/log/check.h" #include "tink/configuration.h" #include "tink/daead/internal/config_v0.h" namespace crypto { namespace tink { const Configuration& ConfigDeterministicAeadV0() { static const Configuration* instance = [] { static Configuration* config = new Configuration(); CHECK_OK(internal::AddDeterministicAeadV0(*config)); return config; }(); return *instance; } } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_DAEAD_CONFIG_V0_H_ #define TINK_DAEAD_CONFIG_V0_H_ #include "tink/configuration.h" namespace crypto { namespace tink { // Configuration used to generate Deterministic AEAD primitives with recommended // key managers. const Configuration& ConfigDeterministicAeadV0(); } // namespace tink } // namespace crypto #endif // TINK_DAEAD_CONFIG_V0_H_ ================================================ FILE: cc/daead/config_v0_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/daead/config_v0.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/daead/deterministic_aead_key_templates.h" #include "tink/daead/key_gen_config_v0.h" #include "tink/deterministic_aead.h" #include "tink/keyset_handle.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; TEST(ConfigV0Test, GetPrimitive) { util::StatusOr> handle = KeysetHandle::GenerateNew(DeterministicAeadKeyTemplates::Aes256Siv(), KeyGenConfigDeterministicAeadV0()); ASSERT_THAT(handle, IsOk()); util::StatusOr> daead = (*handle)->GetPrimitive(ConfigDeterministicAeadV0()); ASSERT_THAT(daead, IsOk()); std::string plaintext = "plaintext"; util::StatusOr ciphertext = (*daead)->EncryptDeterministically(plaintext, "ad"); ASSERT_THAT(ciphertext, IsOk()); EXPECT_THAT((*daead)->DecryptDeterministically(*ciphertext, "ad"), IsOkAndHolds(plaintext)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/deterministic_aead_config.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/daead/deterministic_aead_config.h" #include "absl/memory/memory.h" #include "tink/config/tink_fips.h" #include "tink/daead/aes_siv_key_manager.h" #include "tink/daead/aes_siv_proto_serialization.h" #include "tink/daead/deterministic_aead_wrapper.h" #include "tink/registry.h" #include "tink/util/status.h" namespace crypto { namespace tink { // static util::Status DeterministicAeadConfig::Register() { // Currently there are no FIPS-validated deterministic AEAD key managers // available, therefore none will be registered in FIPS only mode. if (IsFipsModeEnabled()) { return util::OkStatus(); } // Register non-FIPS key managers. auto status = Registry::RegisterKeyTypeManager( absl::make_unique(), true); if (!status.ok()) return status; status = RegisterAesSivProtoSerialization(); if (!status.ok()) return status; // Register primitive wrapper. return Registry::RegisterPrimitiveWrapper( absl::make_unique()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/deterministic_aead_config.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_DAEAD_DETERMINISTIC_AEAD_CONFIG_H_ #define TINK_DAEAD_DETERMINISTIC_AEAD_CONFIG_H_ #include "absl/base/macros.h" #include "tink/util/status.h" #include "proto/config.pb.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Static methods and constants for registering with the Registry // all instances of DeterministicAead key types supported in a release of Tink. // // To register all DeterministicAead key types from the current Tink release // one can do: // // auto status = DeterministicAeadConfig::Register(); // class DeterministicAeadConfig { public: // Registers DeterministicAead primitive wrapper and key managers for all // DeterministicAead key types from the current Tink release. static crypto::tink::util::Status Register(); private: DeterministicAeadConfig() {} }; } // namespace tink } // namespace crypto #endif // TINK_DAEAD_DETERMINISTIC_AEAD_CONFIG_H_ ================================================ FILE: cc/daead/deterministic_aead_config_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/daead/deterministic_aead_config.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/config/global_registry.h" #include "tink/config/tink_fips.h" #include "tink/daead/aes_siv_key.h" #include "tink/daead/aes_siv_key_manager.h" #include "tink/daead/aes_siv_parameters.h" #include "tink/daead/deterministic_aead_key_templates.h" #include "tink/deterministic_aead.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/keyset_handle.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/primitive_set.h" #include "tink/registry.h" #include "tink/restricted_data.h" #include "tink/subtle/random.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_siv.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::DummyDeterministicAead; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; class DeterministicAeadConfigTest : public ::testing::Test { protected: void SetUp() override { Registry::Reset(); internal::MutableSerializationRegistry::GlobalInstance().Reset(); } }; TEST_F(DeterministicAeadConfigTest, Basic) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT(Registry::get_key_manager( AesSivKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT(DeterministicAeadConfig::Register(), IsOk()); EXPECT_THAT(Registry::get_key_manager( AesSivKeyManager().get_key_type()) .status(), IsOk()); } // Tests that the DeterministicAeadWrapper has been properly registered and we // can wrap primitives. TEST_F(DeterministicAeadConfigTest, WrappersRegistered) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } ASSERT_TRUE(DeterministicAeadConfig::Register().ok()); google::crypto::tink::KeysetInfo::KeyInfo key_info; key_info.set_status(google::crypto::tink::KeyStatusType::ENABLED); key_info.set_key_id(1234); key_info.set_output_prefix_type(google::crypto::tink::OutputPrefixType::RAW); auto primitive_set = absl::make_unique>(); ASSERT_THAT( primitive_set->set_primary( primitive_set ->AddPrimitive(absl::make_unique("dummy"), key_info) .value()), IsOk()); auto registry_wrapped = Registry::Wrap(std::move(primitive_set)); ASSERT_TRUE(registry_wrapped.ok()) << registry_wrapped.status(); auto encryption_result = registry_wrapped.value()->EncryptDeterministically("secret", ""); ASSERT_TRUE(encryption_result.ok()); auto decryption_result = DummyDeterministicAead("dummy").DecryptDeterministically( encryption_result.value(), ""); ASSERT_TRUE(decryption_result.status().ok()); EXPECT_THAT(decryption_result.value(), Eq("secret")); decryption_result = DummyDeterministicAead("dummy").DecryptDeterministically( encryption_result.value(), "wrong"); EXPECT_FALSE(decryption_result.status().ok()); } TEST_F(DeterministicAeadConfigTest, RegisterFipsValidTemplates) { if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Only supported in FIPS-only mode"; } EXPECT_THAT(DeterministicAeadConfig::Register(), IsOk()); // Check that we can not retrieve non-FIPS key handle std::list non_fips_key_templates; non_fips_key_templates.push_back(DeterministicAeadKeyTemplates::Aes256Siv()); for (auto key_template : non_fips_key_templates) { auto new_keyset_handle_result = KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()); EXPECT_THAT(new_keyset_handle_result.status(), StatusIs(absl::StatusCode::kNotFound)); } } TEST_F(DeterministicAeadConfigTest, AesSivProtoParamsSerializationRegistered) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::StatusOr proto_params_serialization = internal::ProtoParametersSerialization::Create( DeterministicAeadKeyTemplates::Aes256Siv()); ASSERT_THAT(proto_params_serialization, IsOk()); util::StatusOr> parsed_params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr params = AesSivParameters::Create( /*key_size_in_bytes=*/64, AesSivParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); util::StatusOr> serialized_params = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params.status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(DeterministicAeadConfig::Register(), IsOk()); util::StatusOr> parsed_params2 = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params2, IsOk()); util::StatusOr> serialized_params2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params2, IsOk()); } TEST_F(DeterministicAeadConfigTest, AesSivProtoKeySerializationRegistered) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } google::crypto::tink::AesSivKey key_proto; key_proto.set_version(0); key_proto.set_key_value(subtle::Random::GetRandomBytes(64)); util::StatusOr proto_key_serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesSivKey", RestrictedData(key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()), KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/123); ASSERT_THAT(proto_key_serialization, IsOk()); util::StatusOr> parsed_key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr params = AesSivParameters::Create( /*key_size_in_bytes=*/64, AesSivParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); util::StatusOr key = AesSivKey::Create(*params, RestrictedData(subtle::Random::GetRandomBytes(64), InsecureSecretKeyAccess::Get()), /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialized_key = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key.status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(DeterministicAeadConfig::Register(), IsOk()); util::StatusOr> parsed_key2 = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key2, IsOk()); util::StatusOr> serialized_key2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key2, IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/deterministic_aead_factory.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/daead/deterministic_aead_factory.h" #include #include "tink/daead/deterministic_aead_wrapper.h" #include "tink/deterministic_aead.h" #include "tink/key_manager.h" #include "tink/keyset_handle.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // NOLINTBEGIN(whitespace/line_length) (Formatted when commented in) // TINK-PENDING-REMOVAL-IN-3.0.0-START // static util::StatusOr> DeterministicAeadFactory::GetPrimitive(const KeysetHandle& keyset_handle) { util::Status status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) { return status; } return keyset_handle.GetPrimitive( ConfigGlobalRegistry()); } // static util::StatusOr> DeterministicAeadFactory::GetPrimitive( const KeysetHandle& keyset_handle, const KeyManager* custom_key_manager) { util::Status status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) { return status; } return keyset_handle.GetPrimitive(custom_key_manager); } // TINK-PENDING-REMOVAL-IN-3.0.0-END // NOLINTEND(whitespace/line_length) } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/deterministic_aead_factory.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_DAEAD_DETERMINISTIC_AEAD_FACTORY_H_ #define TINK_DAEAD_DETERMINISTIC_AEAD_FACTORY_H_ #include #include "absl/base/macros.h" #include "tink/deterministic_aead.h" #include "tink/key_manager.h" #include "tink/keyset_handle.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // This class is deprecated. Call // keyset_handle->GetPrimitive() instead. // // Note that in order to for this change to be safe, the // DeterministicAeadWrapper has to be registered in your binary before this // call. This happens automatically if you call one of // * DeterministicAeadConfig::Register() // * TinkConfig::Register() // NOLINTBEGIN(whitespace/line_length) (Formatted when commented in) // TINK-PENDING-REMOVAL-IN-3.0.0-START class ABSL_DEPRECATED( "Call getPrimitive() on the keyset_handle after " "registering the DeterministicAeadWrapper instead.") DeterministicAeadFactory { public: // Returns an DeterministicAead-primitive that uses key material from // the keyset specified via 'keyset_handle'. static crypto::tink::util::StatusOr> GetPrimitive(const KeysetHandle& keyset_handle); // Returns an DeterministicAead-primitive that uses key material from // the keyset specified via 'keyset_handle' and is instantiated by the given // 'custom_key_manager' (instead of the key manager from the Registry). static crypto::tink::util::StatusOr> GetPrimitive(const KeysetHandle& keyset_handle, const KeyManager* custom_key_manager); private: DeterministicAeadFactory() {} }; // TINK-PENDING-REMOVAL-IN-3.0.0-END // NOLINTEND(whitespace/line_length) } // namespace tink } // namespace crypto #endif // TINK_DAEAD_DETERMINISTIC_AEAD_FACTORY_H_ ================================================ FILE: cc/daead/deterministic_aead_factory_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/daead/deterministic_aead_factory.h" #include #include #include "gtest/gtest.h" #include "tink/core/key_manager_impl.h" #include "tink/crypto_format.h" #include "tink/daead/aes_siv_key_manager.h" #include "tink/daead/deterministic_aead_config.h" #include "tink/deterministic_aead.h" #include "tink/internal/key_info.h" #include "tink/keyset_handle.h" #include "tink/util/status.h" #include "tink/util/test_keyset_handle.h" #include "tink/util/test_util.h" #include "proto/aes_siv.pb.h" namespace crypto { namespace tink { namespace { // NOLINTBEGIN(whitespace/line_length) (Formatted when commented in) // TINK-PENDING-REMOVAL-IN-3.0.0-START using crypto::tink::test::AddRawKey; using crypto::tink::test::AddTinkKey; using google::crypto::tink::AesSivKeyFormat; using google::crypto::tink::KeyData; using google::crypto::tink::Keyset; using google::crypto::tink::KeyStatusType; class DeterministicAeadFactoryTest : public ::testing::Test {}; TEST_F(DeterministicAeadFactoryTest, testBasic) { Keyset keyset; auto daead_result = DeterministicAeadFactory::GetPrimitive( *TestKeysetHandle::GetKeysetHandle(keyset)); EXPECT_FALSE(daead_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, daead_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "at least one key", std::string(daead_result.status().message())); } TEST_F(DeterministicAeadFactoryTest, testPrimitive) { // Prepare a template for generating keys for a Keyset. AesSivKeyManager key_type_manager; auto key_manager = internal::MakeKeyManager(&key_type_manager); const KeyFactory& key_factory = key_manager->get_key_factory(); std::string key_type = key_manager->get_key_type(); AesSivKeyFormat key_format; key_format.set_key_size(64); // Prepare a Keyset. Keyset keyset; uint32_t key_id_1 = 1234543; auto new_key = std::move(key_factory.NewKey(key_format).value()); AddTinkKey(key_type, key_id_1, *new_key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); uint32_t key_id_2 = 726329; new_key = std::move(key_factory.NewKey(key_format).value()); AddRawKey(key_type, key_id_2, *new_key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); uint32_t key_id_3 = 7213743; new_key = std::move(key_factory.NewKey(key_format).value()); AddTinkKey(key_type, key_id_3, *new_key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(key_id_3); // Initialize the registry. ASSERT_TRUE(DeterministicAeadConfig::Register().ok()); // Create a KeysetHandle and use it with the factory. auto daead_result = DeterministicAeadFactory::GetPrimitive( *TestKeysetHandle::GetKeysetHandle(keyset)); EXPECT_TRUE(daead_result.ok()) << daead_result.status(); auto daead = std::move(daead_result.value()); // Test the resulting DeterministicAead-instance. std::string plaintext = "some_plaintext"; std::string aad = "some_aad"; auto encrypt_result = daead->EncryptDeterministically(plaintext, aad); EXPECT_TRUE(encrypt_result.ok()) << encrypt_result.status(); std::string ciphertext = encrypt_result.value(); std::string prefix = CryptoFormat::GetOutputPrefix(KeyInfoFromKey(keyset.key(2))).value(); EXPECT_PRED_FORMAT2(testing::IsSubstring, prefix, ciphertext); auto decrypt_result = daead->DecryptDeterministically(ciphertext, aad); EXPECT_TRUE(decrypt_result.ok()) << decrypt_result.status(); EXPECT_EQ(plaintext, decrypt_result.value()); decrypt_result = daead->DecryptDeterministically("some bad ciphertext", aad); EXPECT_FALSE(decrypt_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, decrypt_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "decryption failed", std::string(decrypt_result.status().message())); // Create raw ciphertext with 2nd key, and decrypt // with DeterministicAead-instance. auto raw_daead = std::move(key_manager->GetPrimitive(keyset.key(1).key_data()).value()); std::string raw_ciphertext = raw_daead->EncryptDeterministically(plaintext, aad).value(); decrypt_result = daead->DecryptDeterministically(ciphertext, aad); EXPECT_TRUE(decrypt_result.ok()) << decrypt_result.status(); EXPECT_EQ(plaintext, decrypt_result.value()); } // TINK-PENDING-REMOVAL-IN-3.0.0-END // NOLINTEND(whitespace/line_length) } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/deterministic_aead_key.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_DAEAD_DETERMINISTIC_AEAD_KEY_H_ #define TINK_DAEAD_DETERMINISTIC_AEAD_KEY_H_ #include "absl/strings/string_view.h" #include "tink/daead/deterministic_aead_parameters.h" #include "tink/key.h" namespace crypto { namespace tink { // Represents a function to encrypt and decrypt data using deterministic // authenticated encryption with associated data (Deterministic AEAD). class DeterministicAeadKey : public Key { public: // Returns the bytes prefixed to every ciphertext generated by this key. // // In order to make key rotation more efficient, Tink allows every // Deterministic AEAD key to have an associated ciphertext output prefix. When // decrypting a ciphertext, only keys with a matching prefix have to be tried. // // See https://developers.google.com/tink/wire-format#tink_output_prefix for // more background information on Tink output prefixes. virtual absl::string_view GetOutputPrefix() const = 0; const DeterministicAeadParameters& GetParameters() const override = 0; bool operator==(const Key& other) const override = 0; }; } // namespace tink } // namespace crypto #endif // TINK_DAEAD_DETERMINISTIC_AEAD_KEY_H_ ================================================ FILE: cc/daead/deterministic_aead_key_templates.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/daead/deterministic_aead_key_templates.h" #include "proto/aes_siv.pb.h" #include "proto/common.pb.h" #include "proto/tink.pb.h" using google::crypto::tink::AesSivKeyFormat; using google::crypto::tink::KeyTemplate; using google::crypto::tink::OutputPrefixType; namespace crypto { namespace tink { namespace { KeyTemplate* NewAesSivKeyTemplate(int key_size_in_bytes) { KeyTemplate* key_template = new KeyTemplate; key_template->set_type_url( "type.googleapis.com/google.crypto.tink.AesSivKey"); key_template->set_output_prefix_type(OutputPrefixType::TINK); AesSivKeyFormat key_format; key_format.set_key_size(key_size_in_bytes); key_format.SerializeToString(key_template->mutable_value()); return key_template; } } // anonymous namespace // static const KeyTemplate& DeterministicAeadKeyTemplates::Aes256Siv() { static const KeyTemplate* key_template = NewAesSivKeyTemplate(/* key_size_in_bytes= */ 64); return *key_template; } } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/deterministic_aead_key_templates.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_DAEAD_DETERMINISTIC_AEAD_KEY_TEMPLATES_H_ #define TINK_DAEAD_DETERMINISTIC_AEAD_KEY_TEMPLATES_H_ #include "proto/tink.pb.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Pre-generated KeyTemplate for DeterministicAead key types. One can use // these templates to generate new KeysetHandle object with fresh keys. // To generate a new keyset that contains a single AesGcmKey, one can do: // // auto status = DeterministicAeadConfig::Register(); // if (!status.ok()) { /* fail with error */ } // auto handle_result = // KeysetHandle::GenerateNew(DeterministicAeadKeyTemplates::Aes256Siv()); // if (!handle_result.ok()) { /* fail with error */ } // auto keyset_handle = std::move(handle_result.value()); class DeterministicAeadKeyTemplates { public: // Returns a KeyTemplate that generates new instances of AesSivKey // with the following parameters: // - key size: 64 bytes // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& Aes256Siv(); }; } // namespace tink } // namespace crypto #endif // TINK_DAEAD_DETERMINISTIC_AEAD_KEY_TEMPLATES_H_ ================================================ FILE: cc/daead/deterministic_aead_key_templates_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/daead/deterministic_aead_key_templates.h" #include #include "gtest/gtest.h" #include "tink/core/key_manager_impl.h" #include "tink/daead/aes_siv_key_manager.h" #include "tink/deterministic_aead.h" #include "proto/aes_siv.pb.h" #include "proto/common.pb.h" #include "proto/tink.pb.h" using google::crypto::tink::AesSivKeyFormat; using google::crypto::tink::KeyTemplate; using google::crypto::tink::OutputPrefixType; namespace crypto { namespace tink { namespace { TEST(DeterministicAeadKeyTemplatesTest, testAesSivKeyTemplates) { std::string type_url = "type.googleapis.com/google.crypto.tink.AesSivKey"; { // Test Aes256Siv(). // Check that returned template is correct. const KeyTemplate& key_template = DeterministicAeadKeyTemplates::Aes256Siv(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); AesSivKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(64, key_format.key_size()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = DeterministicAeadKeyTemplates::Aes256Siv(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. AesSivKeyManager key_type_manager; auto key_manager = internal::MakeKeyManager(&key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_template.value()); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/deterministic_aead_parameters.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_DAEAD_DETERMINISTIC_AEAD_PARAMETERS_H_ #define TINK_DAEAD_DETERMINISTIC_AEAD_PARAMETERS_H_ #include "tink/parameters.h" namespace crypto { namespace tink { // Describes a `DeterministicAeadKey` (e.g., key attributes), excluding the // randomly chosen key material. class DeterministicAeadParameters : public Parameters {}; } // namespace tink } // namespace crypto #endif // TINK_DAEAD_DETERMINISTIC_AEAD_PARAMETERS_H_ ================================================ FILE: cc/daead/deterministic_aead_wrapper.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/daead/deterministic_aead_wrapper.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/crypto_format.h" #include "tink/deterministic_aead.h" #include "tink/internal/monitoring_util.h" #include "tink/internal/registry_impl.h" #include "tink/internal/util.h" #include "tink/monitoring/monitoring.h" #include "tink/primitive_set.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { constexpr absl::string_view kPrimitive = "daead"; constexpr absl::string_view kEncryptApi = "encrypt"; constexpr absl::string_view kDecryptApi = "decrypt"; util::Status Validate(PrimitiveSet* daead_set) { if (daead_set == nullptr) { return util::Status(absl::StatusCode::kInternal, "daead_set must be non-NULL"); } if (daead_set->get_primary() == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "daead_set has no primary"); } return util::OkStatus(); } class DeterministicAeadSetWrapper : public DeterministicAead { public: explicit DeterministicAeadSetWrapper( std::unique_ptr> daead_set, std::unique_ptr monitoring_encryption_client = nullptr, std::unique_ptr monitoring_decryption_client = nullptr) : daead_set_(std::move(daead_set)), monitoring_encryption_client_(std::move(monitoring_encryption_client)), monitoring_decryption_client_(std::move(monitoring_decryption_client)) {} crypto::tink::util::StatusOr EncryptDeterministically( absl::string_view plaintext, absl::string_view associated_data) const override; crypto::tink::util::StatusOr DecryptDeterministically( absl::string_view ciphertext, absl::string_view associated_data) const override; ~DeterministicAeadSetWrapper() override = default; private: std::unique_ptr> daead_set_; std::unique_ptr monitoring_encryption_client_; std::unique_ptr monitoring_decryption_client_; }; util::StatusOr DeterministicAeadSetWrapper::EncryptDeterministically( absl::string_view plaintext, absl::string_view associated_data) const { // BoringSSL expects a non-null pointer for plaintext and associated_data, // regardless of whether the size is 0. plaintext = internal::EnsureStringNonNull(plaintext); associated_data = internal::EnsureStringNonNull(associated_data); auto encrypt_result = daead_set_->get_primary()->get_primitive().EncryptDeterministically( plaintext, associated_data); if (!encrypt_result.ok()) { if (monitoring_encryption_client_ != nullptr) { monitoring_encryption_client_->LogFailure(); } return encrypt_result.status(); } if (monitoring_encryption_client_ != nullptr) { monitoring_encryption_client_->Log(daead_set_->get_primary()->get_key_id(), plaintext.size()); } const std::string& key_id = daead_set_->get_primary()->get_identifier(); return key_id + encrypt_result.value(); } util::StatusOr DeterministicAeadSetWrapper::DecryptDeterministically( absl::string_view ciphertext, absl::string_view associated_data) const { // BoringSSL expects a non-null pointer for plaintext and associated_data, // regardless of whether the size is 0. associated_data = internal::EnsureStringNonNull(associated_data); if (ciphertext.length() > CryptoFormat::kNonRawPrefixSize) { absl::string_view key_id = ciphertext.substr(0, CryptoFormat::kNonRawPrefixSize); auto primitives_result = daead_set_->get_primitives(key_id); if (primitives_result.ok()) { absl::string_view raw_ciphertext = ciphertext.substr(CryptoFormat::kNonRawPrefixSize); for (const auto& daead_entry : *(primitives_result.value())) { DeterministicAead& daead = daead_entry->get_primitive(); auto decrypt_result = daead.DecryptDeterministically(raw_ciphertext, associated_data); if (decrypt_result.ok()) { if (monitoring_decryption_client_ != nullptr) { monitoring_decryption_client_->Log(daead_entry->get_key_id(), raw_ciphertext.size()); } return std::move(decrypt_result.value()); } else { // LOG that a matching key didn't decrypt the ciphertext. } } } } // No matching key succeeded with decryption, try all RAW keys. auto raw_primitives_result = daead_set_->get_raw_primitives(); if (raw_primitives_result.ok()) { for (const auto& daead_entry : *(raw_primitives_result.value())) { DeterministicAead& daead = daead_entry->get_primitive(); auto decrypt_result = daead.DecryptDeterministically(ciphertext, associated_data); if (decrypt_result.ok()) { if (monitoring_decryption_client_ != nullptr) { monitoring_decryption_client_->Log(daead_entry->get_key_id(), ciphertext.size()); } return std::move(decrypt_result.value()); } } } if (monitoring_decryption_client_ != nullptr) { monitoring_decryption_client_->LogFailure(); } return util::Status(absl::StatusCode::kInvalidArgument, "decryption failed"); } } // anonymous namespace util::StatusOr> DeterministicAeadWrapper::Wrap( std::unique_ptr> primitive_set) const { util::Status status = Validate(primitive_set.get()); if (!status.ok()) return status; MonitoringClientFactory* const monitoring_factory = internal::RegistryImpl::GlobalInstance().GetMonitoringClientFactory(); // Monitoring is not enabled. Create a wrapper without monitoring clients. if (monitoring_factory == nullptr) { return {absl::make_unique( std::move(primitive_set))}; } util::StatusOr keyset_info = internal::MonitoringKeySetInfoFromPrimitiveSet(*primitive_set); if (!keyset_info.ok()) { return keyset_info.status(); } util::StatusOr> monitoring_encryption_client = monitoring_factory->New( MonitoringContext(kPrimitive, kEncryptApi, *keyset_info)); if (!monitoring_encryption_client.ok()) { return monitoring_encryption_client.status(); } util::StatusOr> monitoring_decryption_client = monitoring_factory->New( MonitoringContext(kPrimitive, kDecryptApi, *keyset_info)); if (!monitoring_decryption_client.ok()) { return monitoring_decryption_client.status(); } return {absl::make_unique( std::move(primitive_set), *std::move(monitoring_encryption_client), *std::move(monitoring_decryption_client))}; } } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/deterministic_aead_wrapper.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_DAEAD_DETERMINISTIC_AEAD_WRAPPER_H_ #define TINK_DAEAD_DETERMINISTIC_AEAD_WRAPPER_H_ #include #include "absl/strings/string_view.h" #include "tink/deterministic_aead.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // Wraps a set of DeterministicAead-instances that correspond to a keyset, // and combines them into a single DeterministicAead-primitive, that uses // the provided instances, depending on the context: // * DeterministicAead::EncryptDeterministically(...) uses the primary // instance from the set // * DeterministicAead::DecryptDeterministically(...) uses the instance // that matches the ciphertext prefix. class DeterministicAeadWrapper : public PrimitiveWrapper { public: // Returns a DeterministicAead-primitive that uses Daead-instances provided // in 'daead_set', which must be non-NULL and must contain a primary instance. crypto::tink::util::StatusOr> Wrap( std::unique_ptr> primitive_set) const override; }; } // namespace tink } // namespace crypto #endif // TINK_DAEAD_DETERMINISTIC_AEAD_WRAPPER_H_ ================================================ FILE: cc/daead/deterministic_aead_wrapper_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/daead/deterministic_aead_wrapper.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_map.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/crypto_format.h" #include "tink/daead/failing_daead.h" #include "tink/deterministic_aead.h" #include "tink/internal/registry_impl.h" #include "tink/monitoring/monitoring.h" #include "tink/monitoring/monitoring_client_mocks.h" #include "tink/primitive_set.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" using ::crypto::tink::test::DummyDeterministicAead; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::KeysetInfo; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::OutputPrefixType; using ::testing::_; using ::testing::ByMove; using ::testing::IsNull; using ::testing::NiceMock; using ::testing::Not; using ::testing::NotNull; using ::testing::Return; using ::testing::Test; namespace crypto { namespace tink { namespace { class DeterministicAeadSetWrapperTest : public ::testing::Test { protected: void SetUp() override { } void TearDown() override { } }; TEST_F(DeterministicAeadSetWrapperTest, testBasic) { { // daead_set is nullptr. auto daead_result = DeterministicAeadWrapper().Wrap(nullptr); EXPECT_FALSE(daead_result.ok()); EXPECT_EQ(absl::StatusCode::kInternal, daead_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "non-NULL", std::string(daead_result.status().message())); } { // daead_set has no primary primitive. std::unique_ptr> daead_set( new PrimitiveSet()); auto daead_result = DeterministicAeadWrapper().Wrap(std::move(daead_set)); EXPECT_FALSE(daead_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, daead_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "no primary", std::string(daead_result.status().message())); } { // Correct daead_set; KeysetInfo::KeyInfo* key_info; KeysetInfo keyset_info; uint32_t key_id_0 = 1234543; key_info = keyset_info.add_key_info(); key_info->set_output_prefix_type(OutputPrefixType::TINK); key_info->set_key_id(key_id_0); key_info->set_status(KeyStatusType::ENABLED); uint32_t key_id_1 = 726329; key_info = keyset_info.add_key_info(); key_info->set_output_prefix_type(OutputPrefixType::LEGACY); key_info->set_key_id(key_id_1); key_info->set_status(KeyStatusType::ENABLED); uint32_t key_id_2 = 7213743; key_info = keyset_info.add_key_info(); key_info->set_output_prefix_type(OutputPrefixType::TINK); key_info->set_key_id(key_id_2); key_info->set_status(KeyStatusType::ENABLED); std::string daead_name_0 = "daead0"; std::string daead_name_1 = "daead1"; std::string daead_name_2 = "daead2"; std::unique_ptr> daead_set( new PrimitiveSet()); std::unique_ptr daead( new DummyDeterministicAead(daead_name_0)); auto entry_result = daead_set->AddPrimitive(std::move(daead), keyset_info.key_info(0)); ASSERT_TRUE(entry_result.ok()); daead = absl::make_unique(daead_name_1); entry_result = daead_set->AddPrimitive(std::move(daead), keyset_info.key_info(1)); ASSERT_TRUE(entry_result.ok()); daead = absl::make_unique(daead_name_2); entry_result = daead_set->AddPrimitive(std::move(daead), keyset_info.key_info(2)); ASSERT_TRUE(entry_result.ok()); // The last key is the primary. ASSERT_THAT(daead_set->set_primary(entry_result.value()), IsOk()); // Wrap daead_set and test the resulting DeterministicAead. auto daead_result = DeterministicAeadWrapper().Wrap(std::move(daead_set)); EXPECT_TRUE(daead_result.ok()) << daead_result.status(); daead = std::move(daead_result.value()); std::string plaintext = "some_plaintext"; std::string associated_data = "some_associated_data"; auto encrypt_result = daead->EncryptDeterministically(plaintext, associated_data); EXPECT_TRUE(encrypt_result.ok()) << encrypt_result.status(); std::string ciphertext = encrypt_result.value(); EXPECT_PRED_FORMAT2(testing::IsSubstring, daead_name_2, ciphertext); auto decrypt_result = daead->DecryptDeterministically(ciphertext, associated_data); EXPECT_TRUE(decrypt_result.ok()) << decrypt_result.status(); EXPECT_EQ(plaintext, decrypt_result.value()); decrypt_result = daead->DecryptDeterministically("some bad ciphertext", associated_data); EXPECT_FALSE(decrypt_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, decrypt_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "decryption failed", std::string(decrypt_result.status().message())); } } KeysetInfo::KeyInfo PopulateKeyInfo(uint32_t key_id, OutputPrefixType out_prefix_type, KeyStatusType status) { KeysetInfo::KeyInfo key_info; key_info.set_output_prefix_type(out_prefix_type); key_info.set_key_id(key_id); key_info.set_status(status); return key_info; } // Creates a test keyset info object. KeysetInfo CreateTestKeysetInfo() { KeysetInfo keyset_info; *keyset_info.add_key_info() = PopulateKeyInfo(/*key_id=*/1234543, OutputPrefixType::TINK, /*status=*/KeyStatusType::ENABLED); *keyset_info.add_key_info() = PopulateKeyInfo(/*key_id=*/726329, OutputPrefixType::LEGACY, /*status=*/KeyStatusType::ENABLED); *keyset_info.add_key_info() = PopulateKeyInfo(/*key_id=*/7213743, OutputPrefixType::TINK, /*status=*/KeyStatusType::ENABLED); return keyset_info; } // Tests for the monitoring behavior. class DeterministicAeadSetWrapperWithMonitoringTest : public Test { protected: // Perform some common initialization: reset the global registry, set expected // calls for the mock monitoring factory and the returned clients. void SetUp() override { Registry::Reset(); // Setup mocks for catching Monitoring calls. auto monitoring_client_factory = absl::make_unique(); auto encryption_monitoring_client = absl::make_unique>(); encryption_monitoring_client_ = encryption_monitoring_client.get(); auto decryption_monitoring_client = absl::make_unique>(); decryption_monitoring_client_ = decryption_monitoring_client.get(); // Monitoring tests expect that the client factory will create the // corresponding MockMonitoringClients. EXPECT_CALL(*monitoring_client_factory, New(_)) .WillOnce( Return(ByMove(util::StatusOr>( std::move(encryption_monitoring_client))))) .WillOnce( Return(ByMove(util::StatusOr>( std::move(decryption_monitoring_client))))); ASSERT_THAT(internal::RegistryImpl::GlobalInstance() .RegisterMonitoringClientFactory( std::move(monitoring_client_factory)), IsOk()); ASSERT_THAT( internal::RegistryImpl::GlobalInstance().GetMonitoringClientFactory(), Not(IsNull())); } // Cleanup the registry to avoid mock leaks. ~DeterministicAeadSetWrapperWithMonitoringTest() override { Registry::Reset(); } MockMonitoringClient* encryption_monitoring_client_; MockMonitoringClient* decryption_monitoring_client_; }; // Test that successful encrypt operations are logged. TEST_F(DeterministicAeadSetWrapperWithMonitoringTest, WrapKeysetWithMonitoringEncryptSuccess) { // Create a primitive set and fill it with some entries KeysetInfo keyset_info = CreateTestKeysetInfo(); const absl::flat_hash_map annotations = { {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}}; auto daead_primitive_set = absl::make_unique>(annotations); ASSERT_THAT( daead_primitive_set ->AddPrimitive(absl::make_unique("daead0"), keyset_info.key_info(0)) , IsOk()); ASSERT_THAT( daead_primitive_set ->AddPrimitive(absl::make_unique("daead1"), keyset_info.key_info(1)) , IsOk()); // Set the last as primary. util::StatusOr::Entry*> last = daead_primitive_set->AddPrimitive( absl::make_unique("daead2"), keyset_info.key_info(2)); ASSERT_THAT(last, IsOk()); ASSERT_THAT(daead_primitive_set->set_primary(*last), IsOk()); // Record the ID of the primary key. const uint32_t primary_key_id = keyset_info.key_info(2).key_id(); // Create a deterministic AEAD and encrypt some data. util::StatusOr> daead = DeterministicAeadWrapper().Wrap(std::move(daead_primitive_set)); ASSERT_THAT(daead, IsOkAndHolds(NotNull())); constexpr absl::string_view plaintext = "This is some plaintext!"; constexpr absl::string_view associated_data = "Some associated data!"; // Check that calling EncryptDeterministically triggers a Log() call. EXPECT_CALL(*encryption_monitoring_client_, Log(primary_key_id, plaintext.size())); util::StatusOr ciphertext = (*daead)->EncryptDeterministically(plaintext, associated_data); EXPECT_THAT(ciphertext, IsOk()); } // Test that successful encrypt operations are logged. TEST_F(DeterministicAeadSetWrapperWithMonitoringTest, WrapKeysetWithMonitoringDecryptSuccess) { // Create a primitive set and fill it with some entries KeysetInfo keyset_info = CreateTestKeysetInfo(); const absl::flat_hash_map annotations = { {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}}; auto daead_primitive_set = absl::make_unique>(annotations); ASSERT_THAT( daead_primitive_set ->AddPrimitive(absl::make_unique("daead0"), keyset_info.key_info(0)) .status(), IsOk()); ASSERT_THAT( daead_primitive_set ->AddPrimitive(absl::make_unique("daead1"), keyset_info.key_info(1)) .status(), IsOk()); // Set the last as primary. util::StatusOr::Entry*> last = daead_primitive_set->AddPrimitive( absl::make_unique("daead2"), keyset_info.key_info(2)); ASSERT_THAT(last, IsOk()); ASSERT_THAT(daead_primitive_set->set_primary(*last), IsOk()); // Record the ID of the primary key. const uint32_t primary_key_id = keyset_info.key_info(2).key_id(); // Create a deterministic AEAD and encrypt/decrypt some data. util::StatusOr> daead = DeterministicAeadWrapper().Wrap(std::move(daead_primitive_set)); ASSERT_THAT(daead, IsOkAndHolds(NotNull())); constexpr absl::string_view plaintext = "This is some plaintext!"; constexpr absl::string_view associated_data = "Some associated data!"; // Check that calling DecryptDeterministically triggers a Log() call. util::StatusOr ciphertext = (*daead)->EncryptDeterministically(plaintext, associated_data); EXPECT_THAT(ciphertext, IsOk()); // In the log expect the size of the ciphertext without the non-raw prefix. EXPECT_CALL(*decryption_monitoring_client_, Log(primary_key_id, ciphertext->size() - CryptoFormat::kNonRawPrefixSize)); EXPECT_THAT( (*daead)->DecryptDeterministically(*ciphertext, associated_data).status(), IsOk()); } TEST_F(DeterministicAeadSetWrapperWithMonitoringTest, WrapKeysetWithMonitoringEncryptFailures) { // Create a primitive set and fill it with some entries. KeysetInfo keyset_info = CreateTestKeysetInfo(); const absl::flat_hash_map annotations = { {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}}; auto daead_primitive_set = absl::make_unique>(annotations); ASSERT_THAT(daead_primitive_set ->AddPrimitive(CreateAlwaysFailingDeterministicAead("daead0"), keyset_info.key_info(0)) .status(), IsOk()); ASSERT_THAT(daead_primitive_set ->AddPrimitive(CreateAlwaysFailingDeterministicAead("daead1"), keyset_info.key_info(1)) .status(), IsOk()); // Set the last as primary. util::StatusOr::Entry*> last = daead_primitive_set->AddPrimitive( CreateAlwaysFailingDeterministicAead("daead2"), keyset_info.key_info(2)); ASSERT_THAT(last, IsOk()); ASSERT_THAT(daead_primitive_set->set_primary(*last), IsOk()); // Create a deterministic AEAD and encrypt. util::StatusOr> daead = DeterministicAeadWrapper().Wrap(std::move(daead_primitive_set)); ASSERT_THAT(daead, IsOkAndHolds(NotNull())); constexpr absl::string_view plaintext = "This is some plaintext!"; constexpr absl::string_view associated_data = "Some associated data!"; // Check that calling EncryptDeterministically triggers a LogFailure() call. EXPECT_CALL(*encryption_monitoring_client_, LogFailure()); util::StatusOr ciphertext = (*daead)->EncryptDeterministically(plaintext, associated_data); EXPECT_THAT(ciphertext.status(), StatusIs(absl::StatusCode::kInternal)); } // Test that monitoring logs decryption failures correctly. TEST_F(DeterministicAeadSetWrapperWithMonitoringTest, WrapKeysetWithMonitoringDecryptFailures) { // Create a primitive set and fill it with some entries. KeysetInfo keyset_info = CreateTestKeysetInfo(); const absl::flat_hash_map annotations = { {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}}; auto daead_primitive_set = absl::make_unique>(annotations); ASSERT_THAT(daead_primitive_set ->AddPrimitive(CreateAlwaysFailingDeterministicAead("daead0"), keyset_info.key_info(0)) .status(), IsOk()); ASSERT_THAT(daead_primitive_set ->AddPrimitive(CreateAlwaysFailingDeterministicAead("daead1"), keyset_info.key_info(1)) .status(), IsOk()); // Set the last as primary. util::StatusOr::Entry*> last = daead_primitive_set->AddPrimitive( CreateAlwaysFailingDeterministicAead("daead2"), keyset_info.key_info(2)); ASSERT_THAT(last, IsOk()); ASSERT_THAT(daead_primitive_set->set_primary(*last), IsOk()); // Create a deterministic AEAD and decrypt. util::StatusOr> daead = DeterministicAeadWrapper().Wrap(std::move(daead_primitive_set)); ASSERT_THAT(daead, IsOkAndHolds(NotNull())); constexpr absl::string_view associated_data = "Some associated data!"; constexpr absl::string_view ciphertext = "This is some ciphertext!"; // Check that calling DecryptDeterministically triggers a LogFailure() call. EXPECT_CALL(*decryption_monitoring_client_, LogFailure()); EXPECT_THAT( (*daead)->DecryptDeterministically(ciphertext, associated_data).status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/failing_daead.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/daead/failing_daead.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/deterministic_aead.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { // A deterministic AEAD that always return a kInternal status on API calls. class AlwaysFailDeterministicAead : public DeterministicAead { public: explicit AlwaysFailDeterministicAead(std::string message) : message_(std::move(message)) {} util::StatusOr EncryptDeterministically( absl::string_view plaintext, absl::string_view associated_data) const override { return util::Status( absl::StatusCode::kInternal, absl::StrCat( "AlwaysFailDeterministicAead will always fail on encrypt (msg=", message_, ")")); } util::StatusOr DecryptDeterministically( absl::string_view ciphertext, absl::string_view associated_data) const override { return util::Status( absl::StatusCode::kInternal, absl::StrCat( "AlwaysFailDeterministicAead will always fail on decrypt (msg=", message_, ")")); } private: const std::string message_; }; } // namespace std::unique_ptr CreateAlwaysFailingDeterministicAead( std::string message) { return absl::make_unique(std::move(message)); } } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/failing_daead.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_DAEAD_FAILING_DAEAD_H_ #define TINK_DAEAD_FAILING_DAEAD_H_ #include #include #include "absl/strings/string_view.h" #include "tink/deterministic_aead.h" namespace crypto { namespace tink { // Returns a deterministic AEAD which will always return an error when calling // EncryptDeterministically or DecryptDeterministically. The error message will // contain `message`. std::unique_ptr CreateAlwaysFailingDeterministicAead( std::string message = ""); } // namespace tink } // namespace crypto #endif // TINK_DAEAD_FAILING_DAEAD_H_ ================================================ FILE: cc/daead/failing_daead_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/daead/failing_daead.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/deterministic_aead.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::StatusIs; using ::testing::HasSubstr; TEST(AlwaysFailDeterministicAead, EncryptFails) { std::unique_ptr failing_daead = CreateAlwaysFailingDeterministicAead(); EXPECT_THAT( failing_daead->EncryptDeterministically("plaintext", "associated_data") .status(), StatusIs(absl::StatusCode::kInternal)); } TEST(AlwaysFailDeterministicAead, EncryptFailsContainsMessage) { const std::string expected_message = "expected_message"; std::unique_ptr failing_aead = CreateAlwaysFailingDeterministicAead(expected_message); EXPECT_THAT( failing_aead->EncryptDeterministically("plaintext", "associated_data") .status(), StatusIs(absl::StatusCode::kInternal, HasSubstr(expected_message))); } TEST(AlwaysFailDeterministicAead, DecryptFails) { std::unique_ptr failing_daead = CreateAlwaysFailingDeterministicAead(); EXPECT_THAT( failing_daead->DecryptDeterministically("ciphertext", "associated_data") .status(), StatusIs(absl::StatusCode::kInternal)); } TEST(AlwaysFailDeterministicAead, DecryptFailsContainsMessage) { const std::string expected_message = "expected_message"; std::unique_ptr failing_aead = CreateAlwaysFailingDeterministicAead(expected_message); EXPECT_THAT( failing_aead->EncryptDeterministically("plaintext", "associated_data") .status(), StatusIs(absl::StatusCode::kInternal, HasSubstr(expected_message))); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/internal/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "config_v0", srcs = ["config_v0.cc"], hdrs = ["config_v0.h"], include_prefix = "tink/daead/internal", deps = [ "//:configuration", "//daead:aes_siv_key_manager", "//daead:deterministic_aead_wrapper", "//internal:configuration_impl", "//util:status", "@com_google_absl//absl/memory", ], ) cc_library( name = "key_gen_config_v0", srcs = ["key_gen_config_v0.cc"], hdrs = ["key_gen_config_v0.h"], include_prefix = "tink/daead/internal", deps = [ "//:key_gen_configuration", "//daead:aes_siv_key_manager", "//internal:key_gen_configuration_impl", "//util:status", "@com_google_absl//absl/memory", ], ) cc_test( name = "config_v0_test", srcs = ["config_v0_test.cc"], deps = [ ":config_v0", ":key_gen_config_v0", "//:configuration", "//:deterministic_aead", "//:key_gen_configuration", "//:keyset_handle", "//daead:aes_siv_key_manager", "//daead:deterministic_aead_key_templates", "//internal:configuration_impl", "//internal:key_gen_configuration_impl", "//internal:key_type_info_store", "//internal:keyset_wrapper_store", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/daead/internal/CMakeLists.txt ================================================ tink_module(daead::internal) tink_cc_library( NAME config_v0 SRCS config_v0.cc config_v0.h DEPS absl::memory tink::core::configuration tink::daead::aes_siv_key_manager tink::daead::deterministic_aead_wrapper tink::internal::configuration_impl tink::util::status ) tink_cc_library( NAME key_gen_config_v0 SRCS key_gen_config_v0.cc key_gen_config_v0.h DEPS absl::memory tink::core::key_gen_configuration tink::daead::aes_siv_key_manager tink::internal::key_gen_configuration_impl tink::util::status ) tink_cc_test( NAME config_v0_test SRCS config_v0_test.cc DEPS tink::daead::internal::config_v0 tink::daead::internal::key_gen_config_v0 gmock tink::core::configuration tink::core::deterministic_aead tink::core::key_gen_configuration tink::core::keyset_handle tink::daead::aes_siv_key_manager tink::daead::deterministic_aead_key_templates tink::internal::configuration_impl tink::internal::key_gen_configuration_impl tink::internal::key_type_info_store tink::internal::keyset_wrapper_store tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) ================================================ FILE: cc/daead/internal/config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/daead/internal/config_v0.h" #include "absl/memory/memory.h" #include "tink/configuration.h" #include "tink/daead/aes_siv_key_manager.h" #include "tink/daead/deterministic_aead_wrapper.h" #include "tink/internal/configuration_impl.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { util::Status AddDeterministicAeadV0(Configuration& config) { util::Status status = ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config); if (!status.ok()) { return status; } return ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/internal/config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_DAEAD_INTERNAL_CONFIG_V0_H_ #define TINK_DAEAD_INTERNAL_CONFIG_V0_H_ #include "tink/configuration.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { // Add recommended Deterministic AEAD primitive wrappers and key managers to // `config`, used to generate primitives. util::Status AddDeterministicAeadV0(Configuration& config); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_DAEAD_INTERNAL_CONFIG_V0_H_ ================================================ FILE: cc/daead/internal/config_v0_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/daead/internal/config_v0.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/configuration.h" #include "tink/daead/aes_siv_key_manager.h" #include "tink/daead/deterministic_aead_key_templates.h" #include "tink/daead/internal/key_gen_config_v0.h" #include "tink/deterministic_aead.h" #include "tink/internal/configuration_impl.h" #include "tink/internal/key_gen_configuration_impl.h" #include "tink/internal/key_type_info_store.h" #include "tink/internal/keyset_wrapper_store.h" #include "tink/key_gen_configuration.h" #include "tink/keyset_handle.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; TEST(DeterministicAeadV0Test, PrimitiveWrapper) { Configuration config; ASSERT_THAT(AddDeterministicAeadV0(config), IsOk()); util::StatusOr store = ConfigurationImpl::GetKeysetWrapperStore(config); ASSERT_THAT(store, IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); } TEST(DeterministicAeadV0Test, KeyManager) { Configuration config; ASSERT_THAT(AddDeterministicAeadV0(config), IsOk()); util::StatusOr store = ConfigurationImpl::GetKeyTypeInfoStore(config); ASSERT_THAT(store, IsOk()); KeyGenConfiguration key_gen_config; ASSERT_THAT(AddDeterministicAeadKeyGenV0(key_gen_config), IsOk()); util::StatusOr key_gen_store = KeyGenConfigurationImpl::GetKeyTypeInfoStore(key_gen_config); ASSERT_THAT(key_gen_store, IsOk()); for (const KeyTypeInfoStore* s : {*store, *key_gen_store}) { EXPECT_THAT(s->Get(AesSivKeyManager().get_key_type()), IsOk()); } } TEST(DeterministicAeadV0Test, GetPrimitive) { KeyGenConfiguration key_gen_config; ASSERT_THAT(AddDeterministicAeadKeyGenV0(key_gen_config), IsOk()); Configuration config; ASSERT_THAT(AddDeterministicAeadV0(config), IsOk()); util::StatusOr> handle = KeysetHandle::GenerateNew(DeterministicAeadKeyTemplates::Aes256Siv(), key_gen_config); ASSERT_THAT(handle, IsOk()); util::StatusOr> daead = (*handle)->GetPrimitive(config); ASSERT_THAT(daead, IsOk()); std::string plaintext = "plaintext"; util::StatusOr ciphertext = (*daead)->EncryptDeterministically(plaintext, "ad"); ASSERT_THAT(ciphertext, IsOk()); EXPECT_THAT((*daead)->DecryptDeterministically(*ciphertext, "ad"), IsOkAndHolds(plaintext)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/internal/key_gen_config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/daead/internal/key_gen_config_v0.h" #include "absl/memory/memory.h" #include "tink/daead/aes_siv_key_manager.h" #include "tink/internal/key_gen_configuration_impl.h" #include "tink/key_gen_configuration.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { util::Status AddDeterministicAeadKeyGenV0(KeyGenConfiguration& config) { return KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/internal/key_gen_config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_DAEAD_INTERNAL_KEY_GEN_CONFIG_V0_H_ #define TINK_DAEAD_INTERNAL_KEY_GEN_CONFIG_V0_H_ #include "tink/key_gen_configuration.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { // Add recommended Deterministic AEAD key managers to `config`, used to generate // keys. util::Status AddDeterministicAeadKeyGenV0(KeyGenConfiguration& config); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_DAEAD_INTERNAL_KEY_GEN_CONFIG_V0_H_ ================================================ FILE: cc/daead/key_gen_config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/daead/key_gen_config_v0.h" #include "absl/log/check.h" #include "tink/daead/internal/key_gen_config_v0.h" #include "tink/key_gen_configuration.h" namespace crypto { namespace tink { const KeyGenConfiguration& KeyGenConfigDeterministicAeadV0() { static const KeyGenConfiguration* instance = [] { static KeyGenConfiguration* config = new KeyGenConfiguration(); CHECK_OK(internal::AddDeterministicAeadKeyGenV0(*config)); return config; }(); return *instance; } } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/key_gen_config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_DAEAD_KEY_GEN_CONFIG_V0_H_ #define TINK_DAEAD_KEY_GEN_CONFIG_V0_H_ #include "tink/key_gen_configuration.h" namespace crypto { namespace tink { // KeyGenConfiguration used to generate Deterministic AEAD keys with recommended // key managers. const KeyGenConfiguration& KeyGenConfigDeterministicAeadV0(); } // namespace tink } // namespace crypto #endif // TINK_DAEAD_KEY_GEN_CONFIG_V0_H_ ================================================ FILE: cc/daead/subtle/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "aead_or_daead", srcs = ["aead_or_daead.cc"], hdrs = ["aead_or_daead.h"], include_prefix = "tink/daead/subtle", visibility = ["//visibility:public"], deps = [ "//:aead", "//:deterministic_aead", "//util:statusor", "@com_google_absl//absl/functional:bind_front", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:variant", ], ) cc_test( name = "aead_or_daead_test", size = "small", srcs = ["aead_or_daead_test.cc"], deps = [ ":aead_or_daead", "//:aead", "//:deterministic_aead", "//util:status", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/daead/subtle/CMakeLists.txt ================================================ tink_module(daead::subtle) tink_cc_library( NAME aead_or_daead SRCS aead_or_daead.cc aead_or_daead.h DEPS absl::bind_front absl::string_view absl::variant tink::core::aead tink::core::deterministic_aead tink::util::statusor ) tink_cc_test( NAME aead_or_daead_test SRCS aead_or_daead_test.cc DEPS tink::daead::subtle::aead_or_daead gmock absl::memory absl::status absl::string_view tink::core::aead tink::core::deterministic_aead tink::util::status tink::util::test_matchers tink::util::test_util ) ================================================ FILE: cc/daead/subtle/aead_or_daead.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/aead.h" #include #include #include #include "absl/functional/bind_front.h" #include "absl/strings/string_view.h" #include "absl/types/variant.h" #include "tink/daead/subtle/aead_or_daead.h" #include "tink/deterministic_aead.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { namespace { // Functor implementing Encryption of a given plaintext. struct EncryptFunctor { crypto::tink::util::StatusOr operator()( absl::string_view plaintext, absl::string_view associated_data, const std::unique_ptr& aead_primitive) { return aead_primitive->Encrypt(plaintext, associated_data); } crypto::tink::util::StatusOr operator()( absl::string_view plaintext, absl::string_view associated_data, const std::unique_ptr& aead_primitive) { return aead_primitive->EncryptDeterministically(plaintext, associated_data); } }; // Functor implementing Decryption of a given ciphertext. struct DecryptFunctor { crypto::tink::util::StatusOr operator()( absl::string_view ciphertext, absl::string_view associated_data, const std::unique_ptr& aead_primitive) { return aead_primitive->Decrypt(ciphertext, associated_data); } crypto::tink::util::StatusOr operator()( absl::string_view ciphertext, absl::string_view associated_data, const std::unique_ptr& aead_primitive) { return aead_primitive->DecryptDeterministically(ciphertext, associated_data); } }; } // namespace crypto::tink::util::StatusOr AeadOrDaead::Encrypt( absl::string_view plaintext, absl::string_view associated_data) const { return absl::visit( absl::bind_front(EncryptFunctor(), plaintext, associated_data), primitive_variant_); } crypto::tink::util::StatusOr AeadOrDaead::Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const { return absl::visit( absl::bind_front(DecryptFunctor(), ciphertext, associated_data), primitive_variant_); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/daead/subtle/aead_or_daead.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_DAEAD_SUBTLE_AEAD_OR_DAEAD_H_ #define TINK_DAEAD_SUBTLE_AEAD_OR_DAEAD_H_ #include #include #include #include "absl/strings/string_view.h" #include "absl/types/variant.h" #include "tink/aead.h" #include "tink/deterministic_aead.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // This wrapper class abstracts away the differences between Deterministic Aead // and non-determinstic Aead primitives. This can be useful for building // higher-level functionality in which either of these primitives can be used. class AeadOrDaead { public: explicit AeadOrDaead(std::unique_ptr aead_primitive) : primitive_variant_(std::move(aead_primitive)) {} explicit AeadOrDaead( std::unique_ptr deterministic_aead_primitive) : primitive_variant_(std::move(deterministic_aead_primitive)) {} // Encrypts 'plaintext' using the underlying aead or determnistic aead // primitive, and returns the resulting ciphertext. crypto::tink::util::StatusOr Encrypt( absl::string_view plaintext, absl::string_view associated_data) const; // Decrypts 'ciphertext' using the underlying aead or determnistic aead // primitive, and returns the resulting plaintext. crypto::tink::util::StatusOr Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const; private: absl::variant, std::unique_ptr> primitive_variant_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_DAEAD_SUBTLE_AEAD_OR_DAEAD_H_ ================================================ FILE: cc/daead/subtle/aead_or_daead_test.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/aead.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/daead/subtle/aead_or_daead.h" #include "tink/deterministic_aead.h" #include "tink/util/status.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::util::StatusOr; // Checks whether Decrypt(Encrypt(message)) == message with the given // aead_or_daead. crypto::tink::util::Status EncryptThenDecrypt( const AeadOrDaead& aead_or_daead, absl::string_view message, absl::string_view associated_data) { StatusOr encryption_or = aead_or_daead.Encrypt(message, associated_data); if (!encryption_or.status().ok()) return encryption_or.status(); StatusOr decryption_or = aead_or_daead.Decrypt(encryption_or.value(), associated_data); if (!decryption_or.status().ok()) return decryption_or.status(); if (decryption_or.value() != message) { return crypto::tink::util::Status(absl::StatusCode::kInternal, "Message/Decryption mismatch"); } return util::OkStatus(); } TEST(AeadOrDaead, testWithAeadPrimitive) { std::unique_ptr aead = absl::make_unique("TestAead"); AeadOrDaead aead_or_daead(std::move(aead)); EXPECT_THAT(EncryptThenDecrypt(aead_or_daead, "test_plaintext", "aad"), IsOk()); } TEST(AeadOrDaead, testWithDeterministicAeadPrimitive) { std::unique_ptr daead = absl::make_unique("TestDaead"); AeadOrDaead aead_or_daead(std::move(daead)); EXPECT_THAT(EncryptThenDecrypt(aead_or_daead, "test_plaintext", "aad"), IsOk()); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/deterministic_aead.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_DETERMINISTIC_AEAD_H_ #define TINK_DETERMINISTIC_AEAD_H_ #include #include "absl/strings/string_view.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // The interface for deterministic authenticated encryption with associated // data. // TODO(bleichen): Copy the interface from Java. // Check the properties: // - authenticated // - secure in multi-user setting // - thread safe/copy safe // References: // https://eprint.iacr.org/2016/1124.pdf class DeterministicAead { public: // Encrypts 'plaintext' with 'associated_data' as associated data // deterministically, and returns the resulting ciphertext. // The ciphertext allows for checking authenticity and integrity // of the associated data, but does not guarantee its secrecy. virtual crypto::tink::util::StatusOr EncryptDeterministically( absl::string_view plaintext, absl::string_view associated_data) const = 0; // Decrypts 'ciphertext' with 'associated_data' as associated data, // and returns the resulting plaintext. // The decryption verifies the authenticity and integrity // of the associated data, but there are no guarantees wrt. secrecy // of that data. virtual crypto::tink::util::StatusOr DecryptDeterministically( absl::string_view ciphertext, absl::string_view associated_data) const = 0; virtual ~DeterministicAead() = default; }; } // namespace tink } // namespace crypto #endif // TINK_DETERMINISTIC_AEAD_H_ ================================================ FILE: cc/deterministic_aead_config.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_DETERMINISTIC_AEAD_CONFIG_H_ #define TINK_DETERMINISTIC_AEAD_CONFIG_H_ // IWYU pragma: begin_exports #include "tink/daead/deterministic_aead_config.h" // IWYU pragma: end_exports #endif // TINK_DETERMINISTIC_AEAD_CONFIG_H_ ================================================ FILE: cc/deterministic_aead_factory.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_DETERMINISTIC_AEAD_FACTORY_H_ #define TINK_DETERMINISTIC_AEAD_FACTORY_H_ // IWYU pragma: begin_exports #include "tink/daead/deterministic_aead_factory.h" // IWYU pragma: end_exports #endif // TINK_DETERMINISTIC_AEAD_FACTORY_H_ ================================================ FILE: cc/deterministic_aead_key_templates.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_DETERMINISTIC_AEAD_KEY_TEMPLATES_H_ #define TINK_DETERMINISTIC_AEAD_KEY_TEMPLATES_H_ // IWYU pragma: begin_exports #include "tink/daead/deterministic_aead_key_templates.h" // IWYU pragma: end_exports #endif // TINK_DETERMINISTIC_AEAD_KEY_TEMPLATES_H_ ================================================ FILE: cc/ec_point.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EC_POINT_H_ #define TINK_EC_POINT_H_ #include "tink/big_integer.h" namespace crypto { namespace tink { class EcPoint { public: EcPoint(const BigInteger& x, const BigInteger& y) : x_(x), y_(y) {} // Returns affine x-coordinate. const BigInteger& GetX() const { return x_; } // Returns affine y-coordinate. const BigInteger& GetY() const { return y_; } bool operator==(const EcPoint& other) const { return x_ == other.x_ && y_ == other.y_; } bool operator!=(const EcPoint& other) const { return !(*this == other); } private: // Affine coordinates. BigInteger x_; BigInteger y_; }; } // namespace tink } // namespace crypto #endif // TINK_EC_POINT_H_ ================================================ FILE: cc/examples/.bazelrc ================================================ # Minumum C++ version. Override it building this project with # `bazel build --cxxopt='-std=c++' --host_cxxopt='c++' ...` # (Both -std and --host_cxxopt must be set to force the desired version.) build --cxxopt='-std=c++14' --host_cxxopt='-std=c++14' ================================================ FILE: cc/examples/.bazelversion ================================================ 6.4.0 ================================================ FILE: cc/examples/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 3.13) project(Examples CXX) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_BUILD_TYPE Release) # Import Tink as an in-tree dependency. set(TINK_BUILD_TESTS OFF) add_subdirectory(../.. tink) # Make sure we have bash. find_program(BASH_PROGRAM bash REQUIRED) # Include path at the base of the examples folder. set(TINK_EXAMPLES_INCLUDE_PATH "${CMAKE_SOURCE_DIR}") if (TINK_USE_INSTALLED_ABSEIL) find_package(absl REQUIRED) endif() if (TINK_USE_INSTALLED_GOOGLETEST) find_package(GTest CONFIG REQUIRED) # NOTE: _create_interface_target is inherited by Tink. _create_interface_target(gmock GTest::gmock) _create_interface_target(gtest_main GTest::gtest_main) else() include(FetchContent) FetchContent_Declare( googletest URL https://github.com/google/googletest/archive/refs/tags/release-1.11.0.tar.gz URL_HASH SHA256=b4870bf121ff7795ba20d20bcdd8627b8e088f2d1dab299a031c1034eddc93d5 ) FetchContent_GetProperties(googletest) if(NOT googletest_POPULATED) FetchContent_Populate(googletest) add_subdirectory( ${googletest_SOURCE_DIR} ${googletest_BINARY_DIR}) endif() endif() enable_testing() add_subdirectory(util) add_subdirectory(aead) add_subdirectory(digital_signatures) add_subdirectory(hybrid_encryption) add_subdirectory(jwt) add_subdirectory(mac) add_subdirectory(walkthrough) ================================================ FILE: cc/examples/WORKSPACE ================================================ workspace(name = "tink_cc_examples") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") local_repository( name = "tink_cc", path = "../", ) # Release from 2023-09-18. maybe( http_archive, name = "com_google_absl", sha256 = "497ebdc3a4885d9209b9bd416e8c3f71e7a1fb8af249f6c2a80b7cbeefcd7e21", strip_prefix = "abseil-cpp-20230802.1", urls = ["https://github.com/abseil/abseil-cpp/archive/refs/tags/20230802.1.zip"], ) # Release from 2023-08-02. maybe( http_archive, name = "com_google_googletest", sha256 = "1f357c27ca988c3f7c6b4bf68a9395005ac6761f034046e9dde0896e3aba00e4", strip_prefix = "googletest-1.14.0", url = "https://github.com/google/googletest/archive/refs/tags/v1.14.0.zip", ) # Load Tink dependencies. load("@tink_cc//:tink_cc_deps.bzl", "tink_cc_deps") tink_cc_deps() load("@tink_cc//:tink_cc_deps_init.bzl", "tink_cc_deps_init") tink_cc_deps_init() ================================================ FILE: cc/examples/aead/BUILD.bazel ================================================ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) filegroup( name = "aead_test_keyset", srcs = ["aead_test_keyset.json"], ) cc_binary( name = "aead_cli", srcs = ["aead_cli.cc"], deps = [ "//util", "@com_google_absl//absl/flags:flag", "@com_google_absl//absl/flags:parse", "@com_google_absl//absl/log:check", "@com_google_absl//absl/strings", "@tink_cc//:aead", "@tink_cc//:keyset_handle", "@tink_cc//:keyset_reader", "@tink_cc//aead:aead_config", "@tink_cc//config:tink_config", "@tink_cc//util:status", ], ) sh_test( name = "aead_cli_test", size = "small", srcs = ["aead_cli_test.sh"], args = [ "$(rootpath :aead_cli)", "$(rootpath :aead_test_keyset)", ], data = [ ":aead_cli", ":aead_test_keyset", ], ) ================================================ FILE: cc/examples/aead/CMakeLists.txt ================================================ add_executable(aead_cli aead_cli.cc) target_include_directories(aead_cli PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${TINK_EXAMPLES_INCLUDE_PATH}") target_link_libraries(aead_cli tink::static absl::check absl::flags_parse util) add_test( NAME aead_cli_test COMMAND "${BASH_PROGRAM}" "${CMAKE_CURRENT_SOURCE_DIR}/aead_cli_test.sh" "${CMAKE_CURRENT_BINARY_DIR}/aead_cli" "${CMAKE_CURRENT_SOURCE_DIR}/aead_test_keyset.json") ================================================ FILE: cc/examples/aead/aead_cli.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// // [START aead-example] // A command-line utility for testing Tink AEAD. #include #include #include #include #include "absl/flags/flag.h" #include "absl/flags/parse.h" #include "absl/log/check.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/aead/aead_config.h" #include "tink/config/global_registry.h" #include "util/util.h" #include "tink/keyset_handle.h" #include "tink/util/status.h" ABSL_FLAG(std::string, keyset_filename, "", "Keyset file in JSON format"); ABSL_FLAG(std::string, mode, "", "Mode of operation {encrypt|decrypt}"); ABSL_FLAG(std::string, input_filename, "", "Filename to operate on"); ABSL_FLAG(std::string, output_filename, "", "Output file name"); ABSL_FLAG(std::string, associated_data, "", "Associated data for AEAD (default: empty"); namespace { using ::crypto::tink::Aead; using ::crypto::tink::AeadConfig; using ::crypto::tink::KeysetHandle; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; constexpr absl::string_view kEncrypt = "encrypt"; constexpr absl::string_view kDecrypt = "decrypt"; void ValidateParams() { // [START_EXCLUDE] CHECK(absl::GetFlag(FLAGS_mode) == kEncrypt || absl::GetFlag(FLAGS_mode) == kDecrypt) << "Invalid mode; must be `encrypt` or `decrypt`"; CHECK(!absl::GetFlag(FLAGS_keyset_filename).empty()) << "Keyset file must be specified"; CHECK(!absl::GetFlag(FLAGS_input_filename).empty()) << "Input file must be specified"; CHECK(!absl::GetFlag(FLAGS_output_filename).empty()) << "Output file must be specified"; // [END_EXCLUDE] } } // namespace namespace tink_cc_examples { // AEAD example CLI implementation. Status AeadCli(absl::string_view mode, const std::string& keyset_filename, const std::string& input_filename, const std::string& output_filename, absl::string_view associated_data) { Status result = AeadConfig::Register(); if (!result.ok()) return result; // Read the keyset from file. StatusOr> keyset_handle = ReadJsonCleartextKeyset(keyset_filename); if (!keyset_handle.ok()) return keyset_handle.status(); // Get the primitive. StatusOr> aead = (*keyset_handle) ->GetPrimitive( crypto::tink::ConfigGlobalRegistry()); if (!aead.ok()) return aead.status(); // Read the input. StatusOr input_file_content = ReadFile(input_filename); if (!input_file_content.ok()) return input_file_content.status(); // Compute the output. std::string output; if (mode == kEncrypt) { StatusOr encrypt_result = (*aead)->Encrypt(*input_file_content, associated_data); if (!encrypt_result.ok()) return encrypt_result.status(); output = encrypt_result.value(); } else { // operation == kDecrypt. StatusOr decrypt_result = (*aead)->Decrypt(*input_file_content, associated_data); if (!decrypt_result.ok()) return decrypt_result.status(); output = decrypt_result.value(); } // Write the output to the output file. return WriteToFile(output, output_filename); } } // namespace tink_cc_examples int main(int argc, char** argv) { absl::ParseCommandLine(argc, argv); ValidateParams(); std::string mode = absl::GetFlag(FLAGS_mode); std::string keyset_filename = absl::GetFlag(FLAGS_keyset_filename); std::string input_filename = absl::GetFlag(FLAGS_input_filename); std::string output_filename = absl::GetFlag(FLAGS_output_filename); std::string associated_data = absl::GetFlag(FLAGS_associated_data); std::clog << "Using keyset from file " << keyset_filename << " to AEAD-" << mode << " file " << input_filename << " with associated data '" << associated_data << "'." << '\n'; std::clog << "The resulting output will be written to " << output_filename << '\n'; CHECK_OK(tink_cc_examples::AeadCli(mode, keyset_filename, input_filename, output_filename, associated_data)); return 0; } // [END aead-example] ================================================ FILE: cc/examples/aead/aead_cli_test.sh ================================================ #!/bin/bash # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ################################################################################ set -euo pipefail ############################################################################# # Tests for Tink CC AEAD. ############################################################################# : "${TEST_TMPDIR:=$(mktemp -d)}" readonly CLI="$1" readonly KEYSET_FILE="$2" readonly DATA_FILE="${TEST_TMPDIR}/example_data.txt" readonly TEST_NAME="TinkExamplesCcAeadTest" echo "This is some plaintext to be encrypted." > "${DATA_FILE}" ####################################### # A helper function for getting the return code of a command that may fail. # Temporarily disables error safety and stores return value in TEST_STATUS. # # Globals: # TEST_STATUS # Arguments: # Command to execute. ####################################### test_command() { set +e "$@" TEST_STATUS=$? set -e } ####################################### # Asserts that the outcome of the latest test command is 0. # # If not, it terminates the test execution. # # Globals: # TEST_STATUS # TEST_NAME # TEST_CASE ####################################### assert_command_succeeded() { if (( TEST_STATUS != 0 )); then echo "[ FAILED ] ${TEST_NAME}.${TEST_CASE}" exit 1 fi } ####################################### # Asserts that the outcome of the latest test command is not 0. # # If not, it terminates the test execution. # # Globals: # TEST_STATUS # TEST_NAME # TEST_CASE ####################################### assert_command_failed() { if (( TEST_STATUS == 0 )); then echo "[ FAILED ] ${TEST_NAME}.${TEST_CASE}" exit 1 fi } ####################################### # Starts a new test case; records the test case name to TEST_CASE. # # Globals: # TEST_NAME # TEST_CASE # Arguments: # test_case: The name of the test case. ####################################### start_test_case() { TEST_CASE="$1" echo "[ RUN ] ${TEST_NAME}.${TEST_CASE}" } ####################################### # Ends a test case printing a success message. # # Globals: # TEST_NAME # TEST_CASE ####################################### end_test_case() { echo "[ OK ] ${TEST_NAME}.${TEST_CASE}" } ############################################################################# start_test_case "encrypt" # Run encryption. test_command "${CLI}" \ --mode encrypt \ --keyset_filename "${KEYSET_FILE}" \ --input_filename "${DATA_FILE}" \ --output_filename "${DATA_FILE}.encrypted" assert_command_succeeded end_test_case ############################################################################# start_test_case "decrypt" # Run decryption. test_command "${CLI}" \ --mode decrypt \ --keyset_filename "${KEYSET_FILE}" \ --input_filename "${DATA_FILE}.encrypted" \ --output_filename "${DATA_FILE}.decrypted" assert_command_succeeded test_command cmp -s "${DATA_FILE}" "${DATA_FILE}.decrypted" assert_command_succeeded end_test_case ############################################################################# start_test_case "encrypt_decrypt_fails_with_modified_ciphertext" # Run encryption test_command "${CLI}" \ --mode encrypt \ --keyset_filename "${KEYSET_FILE}" \ --input_filename "${DATA_FILE}" \ --output_filename "${DATA_FILE}.encrypted" assert_command_succeeded # Modify ciphertext. echo "modified" >> "${DATA_FILE}.encrypted" # Run decryption. test_command "${CLI}" \ --mode decrypt \ --keyset_filename "${KEYSET_FILE}" \ --input_filename "${DATA_FILE}.encrypted" \ --output_filename "${DATA_FILE}.decrypted" assert_command_failed end_test_case ############################################################################# start_test_case "encrypt_decrypt_succeeds_with_associated_data" # Run encryption. ASSOCIATED_DATA="header information" test_command "${CLI}" \ --mode encrypt \ --keyset_filename "${KEYSET_FILE}" \ --input_filename "${DATA_FILE}" \ --output_filename "${DATA_FILE}.encrypted" \ --associated_data "${ASSOCIATED_DATA}" assert_command_succeeded # Run decryption. test_command "${CLI}" \ --mode decrypt \ --keyset_filename "${KEYSET_FILE}" \ --input_filename "${DATA_FILE}.encrypted" \ --output_filename "${DATA_FILE}.decrypted" \ --associated_data "${ASSOCIATED_DATA}" assert_command_succeeded cmp --silent "${DATA_FILE}" "${DATA_FILE}.decrypted" assert_command_succeeded end_test_case ############################################################################# start_test_case "encrypt_decrypt_fails_with_modified_associated_data" # Run encryption. ASSOCIATED_DATA="header information" test_command "${CLI}" \ --mode encrypt \ --keyset_filename "${KEYSET_FILE}" \ --input_filename "${DATA_FILE}" \ --output_filename "${DATA_FILE}.encrypted" \ --associated_data "${ASSOCIATED_DATA}" assert_command_succeeded # Run decryption. MODIFIED_ASSOCIATED_DATA="modified header information" test_command "${CLI}" \ --mode decrypt \ --keyset_filename "${KEYSET_FILE}" \ --input_filename "${DATA_FILE}.encrypted" \ --output_filename "${DATA_FILE}.decrypted" \ --associated_data "${MODIFIED_ASSOCIATED_DATA}" assert_command_failed end_test_case ================================================ FILE: cc/examples/aead/aead_test_keyset.json ================================================ { "key": [ { "keyData": { "keyMaterialType": "SYMMETRIC", "typeUrl": "type.googleapis.com/google.crypto.tink.AesGcmKey", "value": "GiBWyUfGgYk3RTRhj/LIUzSudIWlyjCftCOypTr0jCNSLg==" }, "keyId": 294406504, "outputPrefixType": "TINK", "status": "ENABLED" } ], "primaryKeyId": 294406504 } ================================================ FILE: cc/examples/daead/BUILD.bazel ================================================ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) filegroup( name = "deterministic_aead_test_keyset", srcs = ["deterministic_aead_test_keyset.json"], ) cc_binary( name = "deterministic_aead_cli", srcs = ["deterministic_aead_cli.cc"], deps = [ "//util", "@com_google_absl//absl/flags:flag", "@com_google_absl//absl/flags:parse", "@com_google_absl//absl/log:check", "@com_google_absl//absl/strings", "@tink_cc//:deterministic_aead", "@tink_cc//:keyset_handle", "@tink_cc//:keyset_reader", "@tink_cc//config:tink_config", "@tink_cc//daead:deterministic_aead_config", "@tink_cc//util:status", ], ) sh_test( name = "deterministic_aead_cli_test", size = "small", srcs = ["deterministic_aead_cli_test.sh"], args = [ "$(rootpath :deterministic_aead_cli)", "$(rootpath :deterministic_aead_test_keyset)", ], data = [ ":deterministic_aead_cli", ":deterministic_aead_test_keyset", ], ) ================================================ FILE: cc/examples/daead/CMakeLists.txt ================================================ add_executable(deterministic_aead_cli deterministic_aead_cli.cc) target_include_directories(deterministic_aead_cli PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${TINK_EXAMPLES_INCLUDE_PATH}") target_link_libraries(deterministic_aead_cli tink::static absl::check absl::flags_parse util) add_test( NAME deterministic_aead_cli_test COMMAND "${BASH_PROGRAM}" "${CMAKE_CURRENT_SOURCE_DIR}/deterministic_aead_cli_test.sh" "${CMAKE_CURRENT_BINARY_DIR}/deterministic_aead_cli" "${CMAKE_CURRENT_SOURCE_DIR}/deterministic_aead_test_keyset.json") ================================================ FILE: cc/examples/daead/deterministic_aead_cli.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// // [START deterministic-aead-example] // A command-line utility for testing Tink Deterministic AEAD. #include #include #include #include #include "absl/flags/flag.h" #include "absl/flags/parse.h" #include "absl/log/check.h" #include "absl/strings/string_view.h" #include "tink/config/global_registry.h" #include "tink/daead/deterministic_aead_config.h" #include "tink/deterministic_aead.h" #include "util/util.h" #include "tink/keyset_handle.h" #include "tink/util/status.h" ABSL_FLAG(std::string, keyset_filename, "", "Keyset file in JSON format"); ABSL_FLAG(std::string, mode, "", "Mode of operation {encrypt|decrypt}"); ABSL_FLAG(std::string, input_filename, "", "Filename to operate on"); ABSL_FLAG(std::string, output_filename, "", "Output file name"); ABSL_FLAG(std::string, associated_data, "", "Associated data for Deterministic AEAD (default: empty"); namespace { using ::crypto::tink::DeterministicAead; using ::crypto::tink::DeterministicAeadConfig; using ::crypto::tink::KeysetHandle; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; constexpr absl::string_view kEncrypt = "encrypt"; constexpr absl::string_view kDecrypt = "decrypt"; void ValidateParams() { // [START_EXCLUDE] CHECK(absl::GetFlag(FLAGS_mode) == kEncrypt || absl::GetFlag(FLAGS_mode) == kDecrypt) << "Invalid mode; must be `encrypt` or `decrypt`"; CHECK(!absl::GetFlag(FLAGS_keyset_filename).empty()) << "Keyset file must be specified"; CHECK(!absl::GetFlag(FLAGS_input_filename).empty()) << "Input file must be specified"; CHECK(!absl::GetFlag(FLAGS_output_filename).empty()) << "Output file must be specified"; // [END_EXCLUDE] } } // namespace namespace tink_cc_examples { // Deterministic AEAD example CLI implementation. Status DeterministicAeadCli(absl::string_view mode, const std::string& keyset_filename, const std::string& input_filename, const std::string& output_filename, absl::string_view associated_data) { Status result = DeterministicAeadConfig::Register(); if (!result.ok()) return result; // Read keyset from file. StatusOr> keyset_handle = ReadJsonCleartextKeyset(keyset_filename); if (!keyset_handle.ok()) return keyset_handle.status(); // Get the primitive. StatusOr> daead = (*keyset_handle) ->GetPrimitive( crypto::tink::ConfigGlobalRegistry()); if (!daead.ok()) return daead.status(); // Read the input. StatusOr input_file_content = ReadFile(input_filename); if (!input_file_content.ok()) return input_file_content.status(); // Compute the output. std::string output; if (mode == kEncrypt) { StatusOr result = (*daead)->EncryptDeterministically( *input_file_content, associated_data); if (!result.ok()) return result.status(); output = *result; } else if (mode == kDecrypt) { StatusOr result = (*daead)->DecryptDeterministically( *input_file_content, associated_data); if (!result.ok()) return result.status(); output = *result; } // Write output to file. return WriteToFile(output, output_filename); } } // namespace tink_cc_examples int main(int argc, char** argv) { absl::ParseCommandLine(argc, argv); ValidateParams(); std::string mode = absl::GetFlag(FLAGS_mode); std::string keyset_filename = absl::GetFlag(FLAGS_keyset_filename); std::string input_filename = absl::GetFlag(FLAGS_input_filename); std::string output_filename = absl::GetFlag(FLAGS_output_filename); std::string associated_data = absl::GetFlag(FLAGS_associated_data); std::clog << "Using keyset from file " << keyset_filename << " to Deterministic AEAD-" << mode << " file " << input_filename << " with associated data '" << associated_data << "'." << std::endl; std::clog << "The resulting output will be written to " << output_filename << "." << std::endl; CHECK_OK(tink_cc_examples::DeterministicAeadCli( mode, keyset_filename, input_filename, output_filename, associated_data)); return 0; } // [END deterministic-aead-example] ================================================ FILE: cc/examples/daead/deterministic_aead_cli_test.sh ================================================ #!/bin/bash # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ################################################################################ set -euo pipefail ############################################################################# # Tests for Tink CC Deterministic AEAD. ############################################################################# : "${TEST_TMPDIR:=$(mktemp -d)}" readonly CLI="$1" readonly KEYSET_FILE="$2" readonly DATA_FILE="${TEST_TMPDIR}/example_data.txt" readonly TEST_NAME="TinkExamplesCcDeterministicAeadTest" echo "This is some plaintext to be encrypted." > "${DATA_FILE}" ####################################### # A helper function for getting the return code of a command that may fail. # Temporarily disables error safety and stores return value in TEST_STATUS. # # Globals: # TEST_STATUS # Arguments: # Command to execute. ####################################### test_command() { set +e "$@" TEST_STATUS=$? set -e } ####################################### # Asserts that the outcome of the latest test command is 0. # # If not, it terminates the test execution. # # Globals: # TEST_STATUS # TEST_NAME # TEST_CASE ####################################### assert_command_succeeded() { if (( TEST_STATUS != 0 )); then echo "[ FAILED ] ${TEST_NAME}.${TEST_CASE}" exit 1 fi } ####################################### # Asserts that the outcome of the latest test command is not 0. # # If not, it terminates the test execution. # # Globals: # TEST_STATUS # TEST_NAME # TEST_CASE ####################################### assert_command_failed() { if (( TEST_STATUS == 0 )); then echo "[ FAILED ] ${TEST_NAME}.${TEST_CASE}" exit 1 fi } ####################################### # Starts a new test case; records the test case name to TEST_CASE. # # Globals: # TEST_NAME # TEST_CASE # Arguments: # test_case: The name of the test case. ####################################### start_test_case() { TEST_CASE="$1" echo "[ RUN ] ${TEST_NAME}.${TEST_CASE}" } ####################################### # Ends a test case printing a success message. # # Globals: # TEST_NAME # TEST_CASE ####################################### end_test_case() { echo "[ OK ] ${TEST_NAME}.${TEST_CASE}" } ############################################################################# start_test_case "encrypt" # Run encryption. test_command "${CLI}" \ --mode encrypt \ --keyset_filename "${KEYSET_FILE}" \ --input_filename "${DATA_FILE}" \ --output_filename "${DATA_FILE}.encrypted" assert_command_succeeded end_test_case ############################################################################# start_test_case "decrypt" # Run decryption. test_command "${CLI}" \ --mode decrypt \ --keyset_filename "${KEYSET_FILE}" \ --input_filename "${DATA_FILE}.encrypted" \ --output_filename "${DATA_FILE}.decrypted" assert_command_succeeded test_command cmp -s "${DATA_FILE}" "${DATA_FILE}.decrypted" assert_command_succeeded end_test_case ############################################################################# start_test_case "encrypt_decrypt_fails_with_modified_ciphertext" # Run encryption test_command "${CLI}" \ --mode encrypt \ --keyset_filename "${KEYSET_FILE}" \ --input_filename "${DATA_FILE}" \ --output_filename "${DATA_FILE}.encrypted" assert_command_succeeded # Modify ciphertext. echo "modified" >> "${DATA_FILE}.encrypted" # Run decryption. test_command "${CLI}" \ --mode decrypt \ --keyset_filename "${KEYSET_FILE}" \ --input_filename "${DATA_FILE}.encrypted" \ --output_filename "${DATA_FILE}.decrypted" assert_command_failed end_test_case ############################################################################# start_test_case "encrypt_decrypt_succeeds_with_associated_data" # Run encryption. ASSOCIATED_DATA="header information" test_command "${CLI}" \ --mode encrypt \ --keyset_filename "${KEYSET_FILE}" \ --input_filename "${DATA_FILE}" \ --output_filename "${DATA_FILE}.encrypted" \ --associated_data "${ASSOCIATED_DATA}" assert_command_succeeded # Run decryption. test_command "${CLI}" \ --mode decrypt \ --keyset_filename "${KEYSET_FILE}" \ --input_filename "${DATA_FILE}.encrypted" \ --output_filename "${DATA_FILE}.decrypted" \ --associated_data "${ASSOCIATED_DATA}" assert_command_succeeded cmp --silent "${DATA_FILE}" "${DATA_FILE}.decrypted" assert_command_succeeded end_test_case ############################################################################# start_test_case "encrypt_decrypt_fails_with_modified_associated_data" # Run encryption. ASSOCIATED_DATA="header information" test_command "${CLI}" \ --mode encrypt \ --keyset_filename "${KEYSET_FILE}" \ --input_filename "${DATA_FILE}" \ --output_filename "${DATA_FILE}.encrypted" \ --associated_data "${ASSOCIATED_DATA}" assert_command_succeeded # Run decryption. MODIFIED_ASSOCIATED_DATA="modified header information" test_command "${CLI}" \ --mode decrypt \ --keyset_filename "${KEYSET_FILE}" \ --input_filename "${DATA_FILE}.encrypted" \ --output_filename "${DATA_FILE}.decrypted" \ --associated_data "${MODIFIED_ASSOCIATED_DATA}" assert_command_failed end_test_case ================================================ FILE: cc/examples/daead/deterministic_aead_test_keyset.json ================================================ { "primaryKeyId": 1184417862, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.AesSivKey", "value": "EkAbqs8wuMAXvuqU9FVOW9VvG9kE9P3aI5qjnkGvNTeRh/Cxoh06kosU5R9jRCHCkdMgnOSHMtfIKkQj5exuhesH", "keyMaterialType": "SYMMETRIC" }, "status": "ENABLED", "keyId": 1184417862, "outputPrefixType": "TINK" } ] } ================================================ FILE: cc/examples/digital_signatures/BUILD.bazel ================================================ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) filegroup( name = "digital_signature_keyset", srcs = [ "digital_signature_private_keyset.json", "digital_signature_public_keyset.json", ], ) cc_binary( name = "digital_signatures_cli", srcs = ["digital_signatures_cli.cc"], deps = [ "//util", "@com_google_absl//absl/flags:flag", "@com_google_absl//absl/flags:parse", "@com_google_absl//absl/log:check", "@tink_cc//:keyset_handle", "@tink_cc//:public_key_sign", "@tink_cc//:public_key_verify", "@tink_cc//signature:signature_config", "@tink_cc//util:status", ], ) sh_test( name = "digital_signatures_cli_test", size = "small", srcs = ["digital_signatures_cli_test.sh"], args = [ "$(rootpath :digital_signatures_cli)", "$(rootpaths :digital_signature_keyset)", ], data = [ ":digital_signature_keyset", ":digital_signatures_cli", ], ) ================================================ FILE: cc/examples/digital_signatures/CMakeLists.txt ================================================ add_executable(digital_signatures_cli digital_signatures_cli.cc) target_include_directories(digital_signatures_cli PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${TINK_EXAMPLES_INCLUDE_PATH}") target_link_libraries(digital_signatures_cli tink::static absl::check absl::flags_parse util) add_test( NAME digital_signatures_cli_test COMMAND "${BASH_PROGRAM}" "${CMAKE_CURRENT_SOURCE_DIR}/digital_signatures_cli_test.sh" "${CMAKE_CURRENT_BINARY_DIR}/digital_signatures_cli" "${CMAKE_CURRENT_SOURCE_DIR}/digital_signature_private_keyset.json" "${CMAKE_CURRENT_SOURCE_DIR}/digital_signature_public_keyset.json") ================================================ FILE: cc/examples/digital_signatures/digital_signature_private_keyset.json ================================================ { "primaryKeyId": 1487078030, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey", "value": "Ek0SBggDEAIYAhohANUKuRXZHBD8rPcB5M6+pmgVSjk3gLSD/htdVvbrfbnPIiAXepWekQPRS74qUTMEwN6nXeizXucBxDk0SoKoeqShOBogbJEwIZASdx42tIitAe8UoBxWyi11Mq+HnWNtcQWkG18=", "keyMaterialType": "ASYMMETRIC_PRIVATE" }, "status": "ENABLED", "keyId": 1487078030, "outputPrefixType": "TINK" } ] } ================================================ FILE: cc/examples/digital_signatures/digital_signature_public_keyset.json ================================================ { "primaryKeyId": 1487078030, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.EcdsaPublicKey", "value": "EgYIAxACGAIaIQDVCrkV2RwQ/Kz3AeTOvqZoFUo5N4C0g/4bXVb26325zyIgF3qVnpED0Uu+KlEzBMDep13os17nAcQ5NEqCqHqkoTg=", "keyMaterialType": "ASYMMETRIC_PUBLIC" }, "status": "ENABLED", "keyId": 1487078030, "outputPrefixType": "TINK" } ] } ================================================ FILE: cc/examples/digital_signatures/digital_signatures_cli.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// // [START digital-signature-example] // A utility for signing and verifying files using digital signatures. #include #include #include #include #include "absl/flags/flag.h" #include "absl/flags/parse.h" #include "absl/log/check.h" #include "absl/strings/string_view.h" #include "tink/config/global_registry.h" #include "util/util.h" #include "tink/keyset_handle.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/signature/signature_config.h" #include "tink/util/status.h" ABSL_FLAG(std::string, keyset_filename, "", "Keyset file in JSON format"); ABSL_FLAG(std::string, mode, "", "Mode of operation (sign|verify)"); ABSL_FLAG(std::string, input_filename, "", "Filename to operate on"); ABSL_FLAG(std::string, signature_filename, "", "Path to the signature file"); namespace { using ::crypto::tink::KeysetHandle; using ::crypto::tink::PublicKeySign; using ::crypto::tink::PublicKeyVerify; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; constexpr absl::string_view kSign = "sign"; constexpr absl::string_view kVerify = "verify"; void ValidateParams() { // [START_EXCLUDE] CHECK(absl::GetFlag(FLAGS_mode) == kSign || absl::GetFlag(FLAGS_mode) == kVerify) << "Invalid mode; must be `" << kSign << "` or `" << kVerify << "`" << '\n'; CHECK(!absl::GetFlag(FLAGS_keyset_filename).empty()) << "Keyset file must be specified"; CHECK(!absl::GetFlag(FLAGS_input_filename).empty()) << "Input file must be specified"; CHECK(!absl::GetFlag(FLAGS_signature_filename).empty()) << "Signature file must be specified"; // [END_EXCLUDE] } } // namespace namespace tink_cc_examples { // Digital signature example CLI implementation. Status DigitalSignatureCli(absl::string_view mode, const std::string& keyset_filename, const std::string& input_filename, const std::string& signature_filename) { Status result = crypto::tink::SignatureConfig::Register(); if (!result.ok()) return result; // Read the keyset from file. StatusOr> keyset_handle = ReadJsonCleartextKeyset(keyset_filename); if (!keyset_handle.ok()) return keyset_handle.status(); // Read the input. StatusOr input_file_content = ReadFile(input_filename); if (!input_file_content.ok()) return input_file_content.status(); if (mode == kSign) { StatusOr> public_key_sign = (*keyset_handle) ->GetPrimitive( crypto::tink::ConfigGlobalRegistry()); if (!public_key_sign.ok()) return public_key_sign.status(); StatusOr signature = (*public_key_sign)->Sign(*input_file_content); if (!signature.ok()) return signature.status(); return WriteToFile(*signature, signature_filename); } else { // mode == kVerify StatusOr> public_key_verify = (*keyset_handle) ->GetPrimitive( crypto::tink::ConfigGlobalRegistry()); if (!public_key_verify.ok()) return public_key_verify.status(); // Read the signature. StatusOr signature_file_content = ReadFile(signature_filename); if (!signature_file_content.ok()) return signature_file_content.status(); return (*public_key_verify) ->Verify(*signature_file_content, *input_file_content); } } } // namespace tink_cc_examples int main(int argc, char** argv) { absl::ParseCommandLine(argc, argv); ValidateParams(); std::string mode = absl::GetFlag(FLAGS_mode); std::string keyset_filename = absl::GetFlag(FLAGS_keyset_filename); std::string input_filename = absl::GetFlag(FLAGS_input_filename); std::string signature_filename = absl::GetFlag(FLAGS_signature_filename); std::clog << "Using keyset in " << keyset_filename << " to " << mode; if (mode == kSign) { std::clog << " file " << input_filename << "; the resulting signature is written to " << signature_filename << '\n'; } else { // mode == kVerify std::clog << " the signature in " << signature_filename << " over the content of " << input_filename << '\n'; } CHECK_OK(tink_cc_examples::DigitalSignatureCli( mode, keyset_filename, input_filename, signature_filename)); return 0; } // [END digital-signature-example] ================================================ FILE: cc/examples/digital_signatures/digital_signatures_cli_test.sh ================================================ #!/bin/bash # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ################################################################################ set -euo pipefail ############################################################################# # Tests for Tink C++ digital signature example. ############################################################################# : "${TEST_TMPDIR:=$(mktemp -d)}" readonly CLI="$1" readonly PRIVATE_KEYSET_FILE="$2" readonly PUBLIC_KEYSET_FILE="$3" readonly MESSAGE_FILE="${TEST_TMPDIR}/message.txt" readonly SIGNATURE_FILE="${TEST_TMPDIR}/signature.txt" readonly TEST_NAME="TinkCcExamplesDigitalSignaturesTest" echo "This is some message to be signed." > "${MESSAGE_FILE}" ####################################### # A helper function for getting the return code of a command that may fail. # Temporarily disables error safety and stores return value in TEST_STATUS. # # Globals: # TEST_STATUS # Arguments: # Command to execute. ####################################### test_command() { set +e "$@" TEST_STATUS=$? set -e } ####################################### # Asserts that the outcome of the latest test command is 0. # # If not, it terminates the test execution. # # Globals: # TEST_STATUS # TEST_NAME # TEST_CASE ####################################### assert_command_succeeded() { if (( TEST_STATUS != 0 )); then echo "[ FAILED ] ${TEST_NAME}.${TEST_CASE}" exit 1 fi } ####################################### # Asserts that the outcome of the latest test command is not 0. # # If not, it terminates the test execution. # # Globals: # TEST_STATUS # TEST_NAME # TEST_CASE ####################################### assert_command_failed() { if (( TEST_STATUS == 0 )); then echo "[ FAILED ] ${TEST_NAME}.${TEST_CASE}" exit 1 fi } ####################################### # Starts a new test case; records the test case name to TEST_CASE. # # Globals: # TEST_NAME # TEST_CASE # Arguments: # test_case: The name of the test case. ####################################### start_test_case() { TEST_CASE="$1" echo "[ RUN ] ${TEST_NAME}.${TEST_CASE}" } ####################################### # Ends a test case printing a success message. # # Globals: # TEST_NAME # TEST_CASE ####################################### end_test_case() { echo "[ OK ] ${TEST_NAME}.${TEST_CASE}" } ############################################################################# start_test_case "sign_verify_all_good" # Sign. test_command "${CLI}" \ --mode sign \ --keyset_filename "${PRIVATE_KEYSET_FILE}" \ --input_filename "${MESSAGE_FILE}" \ --signature_filename "${SIGNATURE_FILE}" assert_command_succeeded # Verify. test_command "${CLI}" \ --mode verify \ --keyset_filename "${PUBLIC_KEYSET_FILE}" \ --input_filename "${MESSAGE_FILE}" \ --signature_filename "${SIGNATURE_FILE}" assert_command_succeeded end_test_case ############################################################################# start_test_case "verify_fails_with_modified_signature" # Sign. test_command "${CLI}" \ --mode sign \ --keyset_filename "${PRIVATE_KEYSET_FILE}" \ --input_filename "${MESSAGE_FILE}" \ --signature_filename "${SIGNATURE_FILE}" assert_command_succeeded # Modify signature. echo "modified" >> "${SIGNATURE_FILE}" # Verify. test_command "${CLI}" \ --mode verify \ --keyset_filename "${PUBLIC_KEYSET_FILE}" \ --input_filename "${MESSAGE_FILE}" \ --signature_filename "${SIGNATURE_FILE}" assert_command_failed end_test_case ############################################################################# start_test_case "verify_fails_with_modified_message" # Sign. test_command "${CLI}" \ --mode sign \ --keyset_filename "${PRIVATE_KEYSET_FILE}" \ --input_filename "${MESSAGE_FILE}" \ --signature_filename "${SIGNATURE_FILE}" assert_command_succeeded # Modify message. echo "modified" >> "${MESSAGE_FILE}" # Verify. test_command "${CLI}" \ --mode verify \ --keyset_filename "${PUBLIC_KEYSET_FILE}" \ --input_filename "${MESSAGE_FILE}" \ --signature_filename "${SIGNATURE_FILE}" assert_command_failed end_test_case ================================================ FILE: cc/examples/hybrid_encryption/BUILD.bazel ================================================ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) cc_binary( name = "hybrid_cli", srcs = ["hybrid_cli.cc"], deps = [ "//util", "@com_google_absl//absl/flags:flag", "@com_google_absl//absl/flags:parse", "@com_google_absl//absl/log:check", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@tink_cc//:hybrid_decrypt", "@tink_cc//:hybrid_encrypt", "@tink_cc//:keyset_handle", "@tink_cc//hybrid:hpke_config", "@tink_cc//hybrid:hybrid_config", "@tink_cc//util:status", ], ) sh_test( name = "hybrid_cli_test", size = "small", srcs = ["hybrid_cli_test.sh"], args = [ "$(rootpath :hybrid_cli)", "$(rootpaths //hybrid_encryption/testdata:hpke_test_keyset)", ], data = [ ":hybrid_cli", "//hybrid_encryption/testdata:hpke_test_keyset", ], ) ================================================ FILE: cc/examples/hybrid_encryption/CMakeLists.txt ================================================ add_executable(hybrid_cli hybrid_cli.cc) target_include_directories(hybrid_cli PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${TINK_EXAMPLES_INCLUDE_PATH}") target_link_libraries(hybrid_cli tink::static absl::check absl::flags_parse util) # Tink CMake's configuration doesn't expose tink::core::hpke_config. Remove # HPKE from this example when building with CMake. target_compile_definitions(hybrid_cli PRIVATE TINK_EXAMPLES_EXCLUDE_HPKE) add_test( NAME hybrid_cli_test COMMAND "${BASH_PROGRAM}" "${CMAKE_CURRENT_SOURCE_DIR}/hybrid_cli_test.sh" "${CMAKE_CURRENT_BINARY_DIR}/hybrid_cli" "${CMAKE_CURRENT_SOURCE_DIR}/testdata/hybrid_test_private_keyset.json" "${CMAKE_CURRENT_SOURCE_DIR}/testdata/hybrid_test_public_keyset.json") ================================================ FILE: cc/examples/hybrid_encryption/hybrid_cli.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// // [START hybrid-example] // A command-line utility for testing Tink Hybrid Encryption. #include #include #include #include #include "absl/flags/flag.h" #include "absl/flags/parse.h" #include "absl/log/check.h" #include "absl/strings/string_view.h" #include "tink/config/global_registry.h" #include "util/util.h" #ifndef TINK_EXAMPLES_EXCLUDE_HPKE #include "tink/hybrid/hpke_config.h" #endif #include "tink/hybrid/hybrid_config.h" #include "tink/hybrid_decrypt.h" #include "tink/hybrid_encrypt.h" #include "tink/keyset_handle.h" #include "tink/util/status.h" ABSL_FLAG(std::string, keyset_filename, "", "Keyset file in JSON format"); ABSL_FLAG(std::string, mode, "", "Mode of operation {encrypt|decrypt}"); ABSL_FLAG(std::string, input_filename, "", "Input file name"); ABSL_FLAG(std::string, output_filename, "", "Output file name"); ABSL_FLAG(std::string, context_info, "", "Context info for Hybrid Encryption/Decryption"); namespace { using ::crypto::tink::HybridDecrypt; using ::crypto::tink::HybridEncrypt; using ::crypto::tink::KeysetHandle; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; constexpr absl::string_view kEncrypt = "encrypt"; constexpr absl::string_view kDecrypt = "decrypt"; void ValidateParams() { // [START_EXCLUDE] CHECK(absl::GetFlag(FLAGS_mode) == kEncrypt || absl::GetFlag(FLAGS_mode) == kDecrypt) << "Invalid mode; must be `encrypt` or `decrypt`"; CHECK(!absl::GetFlag(FLAGS_keyset_filename).empty()) << "Keyset file must be specified"; CHECK(!absl::GetFlag(FLAGS_input_filename).empty()) << "Input file must be specified"; CHECK(!absl::GetFlag(FLAGS_output_filename).empty()) << "Output file must be specified"; // [END_EXCLUDE] } } // namespace namespace tink_cc_examples { Status HybridCli(absl::string_view mode, const std::string& keyset_filename, const std::string& input_filename, const std::string& output_filename, absl::string_view context_info) { Status result = crypto::tink::HybridConfig::Register(); if (!result.ok()) return result; #ifndef TINK_EXAMPLES_EXCLUDE_HPKE // HPKE isn't supported when using OpenSSL as a backend. result = crypto::tink::RegisterHpke(); if (!result.ok()) return result; #endif // Read the keyset from file. StatusOr> keyset_handle = ReadJsonCleartextKeyset(keyset_filename); if (!keyset_handle.ok()) return keyset_handle.status(); // Read the input. StatusOr input_file_content = ReadFile(input_filename); if (!input_file_content.ok()) return input_file_content.status(); // Compute the output. std::string output; if (mode == kEncrypt) { // Get the hybrid encryption primitive. StatusOr> hybrid_encrypt_primitive = (*keyset_handle) ->GetPrimitive( crypto::tink::ConfigGlobalRegistry()); if (!hybrid_encrypt_primitive.ok()) { return hybrid_encrypt_primitive.status(); } // Generate the ciphertext. StatusOr encrypt_result = (*hybrid_encrypt_primitive)->Encrypt(*input_file_content, context_info); if (!encrypt_result.ok()) return encrypt_result.status(); output = encrypt_result.value(); } else { // operation == kDecrypt. // Get the hybrid decryption primitive. StatusOr> hybrid_decrypt_primitive = (*keyset_handle) ->GetPrimitive( crypto::tink::ConfigGlobalRegistry()); if (!hybrid_decrypt_primitive.ok()) { return hybrid_decrypt_primitive.status(); } // Recover the plaintext. StatusOr decrypt_result = (*hybrid_decrypt_primitive)->Decrypt(*input_file_content, context_info); if (!decrypt_result.ok()) return decrypt_result.status(); output = decrypt_result.value(); } // Write the output to the output file. return WriteToFile(output, output_filename); } } // namespace tink_cc_examples int main(int argc, char** argv) { absl::ParseCommandLine(argc, argv); ValidateParams(); std::string mode = absl::GetFlag(FLAGS_mode); std::string keyset_filename = absl::GetFlag(FLAGS_keyset_filename); std::string input_filename = absl::GetFlag(FLAGS_input_filename); std::string output_filename = absl::GetFlag(FLAGS_output_filename); std::string context_info = absl::GetFlag(FLAGS_context_info); std::clog << "Using keyset from file " << keyset_filename << " to hybrid " << mode << " file " << input_filename << " with context info '" << context_info << "'." << '\n'; std::clog << "The resulting output will be written to " << output_filename << '\n'; CHECK_OK(tink_cc_examples::HybridCli(mode, keyset_filename, input_filename, output_filename, context_info)); return 0; } // [END hybrid-example] ================================================ FILE: cc/examples/hybrid_encryption/hybrid_cli_test.sh ================================================ #!/bin/bash # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ################################################################################ set -euo pipefail ############################################################################# # Tests for Tink C++ hybrid encryption example. ############################################################################# : "${TEST_TMPDIR:=$(mktemp -d)}" readonly CLI="$1" readonly PRIVATE_KEYSET_FILE="$2" readonly PUBLIC_KEYSET_FILE="$3" readonly DATA_FILE="${TEST_TMPDIR}/example_data.txt" readonly TEST_NAME="TinkExamplesCcHybridTest" echo "This is some message to be encrypted." > "${DATA_FILE}" ####################################### # A helper function for getting the return code of a command that may fail. # Temporarily disables error safety and stores return value in TEST_STATUS. # # Globals: # TEST_STATUS # Arguments: # Command to execute. ####################################### test_command() { set +e "$@" TEST_STATUS=$? set -e } ####################################### # Asserts that the outcome of the latest test command is 0. # # If not, it terminates the test execution. # # Globals: # TEST_STATUS # TEST_NAME # TEST_CASE ####################################### assert_command_succeeded() { if (( TEST_STATUS != 0 )); then echo "[ FAILED ] ${TEST_NAME}.${TEST_CASE}" exit 1 fi } ####################################### # Asserts that the outcome of the latest test command is not 0. # # If not, it terminates the test execution. # # Globals: # TEST_STATUS # TEST_NAME # TEST_CASE ####################################### assert_command_failed() { if (( TEST_STATUS == 0 )); then echo "[ FAILED ] ${TEST_NAME}.${TEST_CASE}" exit 1 fi } ####################################### # Starts a new test case; records the test case name to TEST_CASE. # # Globals: # TEST_NAME # TEST_CASE # Arguments: # test_case: The name of the test case. ####################################### start_test_case() { TEST_CASE="$1" echo "[ RUN ] ${TEST_NAME}.${TEST_CASE}" } ####################################### # Ends a test case printing a success message. # # Globals: # TEST_NAME # TEST_CASE ####################################### end_test_case() { echo "[ OK ] ${TEST_NAME}.${TEST_CASE}" } ############################################################################# start_test_case "encrypt" # Run encryption. test_command "${CLI}" \ --mode encrypt \ --keyset_filename "${PUBLIC_KEYSET_FILE}" \ --input_filename "${DATA_FILE}" \ --output_filename "${DATA_FILE}.encrypted" assert_command_succeeded end_test_case ############################################################################# start_test_case "decrypt" # Run decryption. test_command "${CLI}" \ --mode decrypt \ --keyset_filename "${PRIVATE_KEYSET_FILE}" \ --input_filename "${DATA_FILE}.encrypted" \ --output_filename "${DATA_FILE}.decrypted" assert_command_succeeded test_command cmp -s "${DATA_FILE}" "${DATA_FILE}.decrypted" assert_command_succeeded end_test_case ############################################################################# start_test_case "encrypt_decrypt_fails_with_modified_ciphertext" # Run encryption test_command "${CLI}" \ --mode encrypt \ --keyset_filename "${PUBLIC_KEYSET_FILE}" \ --input_filename "${DATA_FILE}" \ --output_filename "${DATA_FILE}.encrypted" assert_command_succeeded # Modify ciphertext. echo "modified" >> "${DATA_FILE}.encrypted" # Run decryption. test_command "${CLI}" \ --mode decrypt \ --keyset_filename "${PRIVATE_KEYSET_FILE}" \ --input_filename "${DATA_FILE}.encrypted" \ --output_filename "${DATA_FILE}.decrypted" assert_command_failed end_test_case ############################################################################# start_test_case "encrypt_decrypt_succeeds_with_context_info" # Run encryption. CONTEXT_INFO="header information" test_command "${CLI}" \ --mode encrypt \ --keyset_filename "${PUBLIC_KEYSET_FILE}" \ --input_filename "${DATA_FILE}" \ --output_filename "${DATA_FILE}.encrypted" \ --context_info "${CONTEXT_INFO}" assert_command_succeeded # Run decryption. test_command "${CLI}" \ --mode decrypt \ --keyset_filename "${PRIVATE_KEYSET_FILE}" \ --input_filename "${DATA_FILE}.encrypted" \ --output_filename "${DATA_FILE}.decrypted" \ --context_info "${CONTEXT_INFO}" assert_command_succeeded cmp --silent "${DATA_FILE}" "${DATA_FILE}.decrypted" assert_command_succeeded end_test_case ############################################################################# start_test_case "encrypt_decrypt_fails_with_modified_context_info" # Run encryption. CONTEXT_INFO="header information" test_command "${CLI}" \ --mode encrypt \ --keyset_filename "${PUBLIC_KEYSET_FILE}" \ --input_filename "${DATA_FILE}" \ --output_filename "${DATA_FILE}.encrypted" \ --context_info "${CONTEXT_INFO}" assert_command_succeeded # Run decryption. MODIFIED_CONTEXT_INFO="modified header information" test_command "${CLI}" \ --mode decrypt \ --keyset_filename "${PRIVATE_KEYSET_FILE}" \ --input_filename "${DATA_FILE}.encrypted" \ --output_filename "${DATA_FILE}.decrypted" \ --context_info "${MODIFIED_CONTEXT_INFO}" assert_command_failed end_test_case ================================================ FILE: cc/examples/hybrid_encryption/testdata/BUILD.bazel ================================================ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) filegroup( name = "hpke_test_keyset", srcs = [ "hpke_test_private_keyset.json", "hpke_test_public_keyset.json", ], ) filegroup( name = "hybrid_test_keyset", srcs = [ "hybrid_test_private_keyset.json", "hybrid_test_public_keyset.json", ], ) ================================================ FILE: cc/examples/hybrid_encryption/testdata/hpke_test_private_keyset.json ================================================ { "primaryKeyId": 958452012, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.HpkePrivateKey", "value": "EioSBggBEAEYAhogVWQpmQoz74jcAp5WOD36KiBQ71MVCpn2iWfOzWLtKV4aINfn8qlMbyijNJcCzrafjsgJ493ZZGN256KTfKw0WN+p", "keyMaterialType": "ASYMMETRIC_PRIVATE" }, "status": "ENABLED", "keyId": 958452012, "outputPrefixType": "TINK" } ] } ================================================ FILE: cc/examples/hybrid_encryption/testdata/hpke_test_public_keyset.json ================================================ { "primaryKeyId": 958452012, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.HpkePublicKey", "value": "EgYIARABGAIaIFVkKZkKM++I3AKeVjg9+iogUO9TFQqZ9olnzs1i7Sle", "keyMaterialType": "ASYMMETRIC_PUBLIC" }, "status": "ENABLED", "keyId": 958452012, "outputPrefixType": "TINK" } ] } ================================================ FILE: cc/examples/hybrid_encryption/testdata/hybrid_test_private_keyset.json ================================================ { "primaryKeyId": 548859458, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey", "value": "EowBEkQKBAgCEAMSOhI4CjB0eXBlLmdvb2dsZWFwaXMuY29tL2dvb2dsZS5jcnlwdG8udGluay5BZXNHY21LZXkSAhAQGAEYARohAKjjAxgGmD9j90UyzNunoC04kWqaWiXGFRhOYfLS7Z2tIiEAhqqb+D0Din92zHwGQefzui0hma5khIZQCWyWHHVgNpsaIBQrEEuEn3hClVKM+4bsvmaUOqFYMbl7E6lNFJzbr+lp", "keyMaterialType": "ASYMMETRIC_PRIVATE" }, "status": "ENABLED", "keyId": 548859458, "outputPrefixType": "TINK" } ] } ================================================ FILE: cc/examples/hybrid_encryption/testdata/hybrid_test_public_keyset.json ================================================ { "primaryKeyId": 548859458, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPublicKey", "value": "EkQKBAgCEAMSOhI4CjB0eXBlLmdvb2dsZWFwaXMuY29tL2dvb2dsZS5jcnlwdG8udGluay5BZXNHY21LZXkSAhAQGAEYARohAKjjAxgGmD9j90UyzNunoC04kWqaWiXGFRhOYfLS7Z2tIiEAhqqb+D0Din92zHwGQefzui0hma5khIZQCWyWHHVgNps=", "keyMaterialType": "ASYMMETRIC_PUBLIC" }, "status": "ENABLED", "keyId": 548859458, "outputPrefixType": "TINK" } ] } ================================================ FILE: cc/examples/jwt/BUILD.bazel ================================================ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) filegroup( name = "jwt_signature_keysets", srcs = [ "jwt_signature_private_keyset.json", "jwt_signature_public_keyset.json", ], ) cc_binary( name = "jwt_sign", srcs = ["jwt_sign.cc"], deps = [ "//util", "@com_google_absl//absl/flags:flag", "@com_google_absl//absl/flags:parse", "@com_google_absl//absl/log:check", "@tink_cc//:keyset_handle", "@tink_cc//jwt:jwt_public_key_sign", "@tink_cc//jwt:jwt_signature_config", "@tink_cc//jwt:raw_jwt", "@tink_cc//util:status", ], ) cc_binary( name = "jwt_verify", srcs = ["jwt_verify.cc"], deps = [ "//util", "@com_google_absl//absl/flags:flag", "@com_google_absl//absl/flags:parse", "@com_google_absl//absl/log:check", "@tink_cc//:keyset_handle", "@tink_cc//jwt:jwk_set_converter", "@tink_cc//jwt:jwt_public_key_verify", "@tink_cc//jwt:jwt_signature_config", "@tink_cc//jwt:jwt_validator", "@tink_cc//util:status", ], ) cc_binary( name = "jwt_generate_public_jwk_set", srcs = ["jwt_generate_public_jwk_set.cc"], deps = [ "//util", "@com_google_absl//absl/flags:flag", "@com_google_absl//absl/flags:parse", "@com_google_absl//absl/log:check", "@tink_cc//:keyset_handle", "@tink_cc//jwt:jwk_set_converter", "@tink_cc//jwt:jwt_signature_config", "@tink_cc//util:status", ], ) sh_test( name = "jwt_signature_cli_test", size = "small", srcs = ["jwt_signature_cli_test.sh"], args = [ "$(rootpath :jwt_sign)", "$(rootpath :jwt_generate_public_jwk_set)", "$(rootpath :jwt_verify)", "$(rootpaths :jwt_signature_keysets)", ], data = [ ":jwt_generate_public_jwk_set", ":jwt_sign", ":jwt_signature_keysets", ":jwt_verify", ], ) ================================================ FILE: cc/examples/jwt/CMakeLists.txt ================================================ add_executable(jwt_sign jwt_sign.cc) target_include_directories(jwt_sign PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${TINK_EXAMPLES_INCLUDE_PATH}") target_link_libraries(jwt_sign tink::static tink::jwt::jwt_signature_config absl::check absl::flags_parse util) add_executable(jwt_verify jwt_verify.cc) target_include_directories(jwt_verify PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${TINK_EXAMPLES_INCLUDE_PATH}") target_link_libraries(jwt_verify tink::static tink::jwt::jwk_set_converter tink::jwt::jwt_signature_config absl::check absl::flags_parse util) add_executable(jwt_generate_public_jwk_set jwt_generate_public_jwk_set.cc) target_include_directories(jwt_generate_public_jwk_set PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${TINK_EXAMPLES_INCLUDE_PATH}") target_link_libraries(jwt_generate_public_jwk_set tink::static tink::jwt::jwk_set_converter tink::jwt::jwt_signature_config absl::check absl::flags_parse util) add_test( NAME jwt_signature_cli_test COMMAND "${BASH_PROGRAM}" "${CMAKE_CURRENT_SOURCE_DIR}/jwt_signature_cli_test.sh" "${CMAKE_CURRENT_BINARY_DIR}/jwt_sign" "${CMAKE_CURRENT_BINARY_DIR}/jwt_generate_public_jwk_set" "${CMAKE_CURRENT_BINARY_DIR}/jwt_verify" "${CMAKE_CURRENT_SOURCE_DIR}/jwt_signature_private_keyset.json" "${CMAKE_CURRENT_SOURCE_DIR}/jwt_signature_public_keyset.json") ================================================ FILE: cc/examples/jwt/jwt_generate_public_jwk_set.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// // [START jwt-generate-public-jwk-set] // An example for converting a Tink keyset with public keys into a JWK set. #include #include #include #include #include "absl/flags/flag.h" #include "absl/flags/parse.h" #include "absl/log/check.h" #include "util/util.h" #include "tink/jwt/jwk_set_converter.h" #include "tink/jwt/jwt_signature_config.h" #include "tink/keyset_handle.h" #include "tink/util/status.h" ABSL_FLAG(std::string, public_keyset_filename, "", "Public keyset file in Tink's JSON format"); ABSL_FLAG(std::string, public_jwk_set_filename, "", "Path to the output public JWK set file"); namespace { using ::crypto::tink::JwkSetFromPublicKeysetHandle; using ::crypto::tink::KeysetHandle; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; void ValidateParams() { // [START_EXCLUDE] CHECK(!absl::GetFlag(FLAGS_public_keyset_filename).empty()) << "Public keyset file must be specified"; CHECK(!absl::GetFlag(FLAGS_public_jwk_set_filename).empty()) << "Public JWK set file must be specified"; // [END_EXCLUDE] } } // namespace namespace tink_cc_examples { Status JwtGeneratePublicJwkSet(const std::string& public_keyset_filename, const std::string& public_jwk_set_filename) { Status result = crypto::tink::JwtSignatureRegister(); if (!result.ok()) return result; StatusOr> keyset_handle = ReadJsonCleartextKeyset(public_keyset_filename); if (!keyset_handle.ok()) return keyset_handle.status(); StatusOr public_jwk_set = JwkSetFromPublicKeysetHandle(**keyset_handle); if (!public_jwk_set.ok()) return keyset_handle.status(); return WriteToFile(*public_jwk_set, public_jwk_set_filename); } } // namespace tink_cc_examples int main(int argc, char** argv) { absl::ParseCommandLine(argc, argv); ValidateParams(); std::string public_keyset_filename = absl::GetFlag(FLAGS_public_keyset_filename); std::string public_jwk_set_filename = absl::GetFlag(FLAGS_public_jwk_set_filename); std::clog << "Convert public keyset in " << public_keyset_filename << " to "; std::clog << " to JWK set format; the result is written to " << public_jwk_set_filename << '\n'; CHECK_OK(tink_cc_examples::JwtGeneratePublicJwkSet(public_keyset_filename, public_jwk_set_filename)); return 0; } // [END jwt-generate-public-jwk-set] ================================================ FILE: cc/examples/jwt/jwt_sign.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// // [START jwt-sign] // An example for signing JSON Web Tokens (JWT). #include #include #include #include #include #include "absl/flags/flag.h" #include "absl/flags/parse.h" #include "absl/log/check.h" #include "absl/strings/string_view.h" #include "absl/time/clock.h" #include "absl/time/time.h" #include "tink/config/global_registry.h" #include "util/util.h" #include "tink/jwt/jwt_public_key_sign.h" #include "tink/jwt/jwt_signature_config.h" #include "tink/jwt/raw_jwt.h" #include "tink/keyset_handle.h" #include "tink/util/status.h" ABSL_FLAG(std::string, keyset_filename, "", "Keyset file in JSON format"); ABSL_FLAG(std::string, audience, "", "Expected audience in the token"); ABSL_FLAG(std::string, token_filename, "", "Path to the token file"); namespace { using ::crypto::tink::JwtPublicKeySign; using ::crypto::tink::KeysetHandle; using ::crypto::tink::RawJwt; using ::crypto::tink::RawJwtBuilder; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; void ValidateParams() { // [START_EXCLUDE] CHECK(!absl::GetFlag(FLAGS_keyset_filename).empty()) << "Keyset file must be specified"; CHECK(!absl::GetFlag(FLAGS_audience).empty()) << "Expected audience in the token must be specified"; CHECK(!absl::GetFlag(FLAGS_token_filename).empty()) << "Token file must be specified"; // [END_EXCLUDE] } } // namespace namespace tink_cc_examples { // JWT sign example CLI implementation. Status JwtSign(const std::string& keyset_filename, absl::string_view audience, const std::string& token_filename) { Status result = crypto::tink::JwtSignatureRegister(); if (!result.ok()) return result; // Read the keyset from file. StatusOr> keyset_handle = ReadJsonCleartextKeyset(keyset_filename); if (!keyset_handle.ok()) return keyset_handle.status(); StatusOr raw_jwt = RawJwtBuilder() .AddAudience(audience) .SetExpiration(absl::Now() + absl::Seconds(100)) .Build(); if (!raw_jwt.ok()) return raw_jwt.status(); StatusOr> jwt_signer = (*keyset_handle) ->GetPrimitive( crypto::tink::ConfigGlobalRegistry()); if (!jwt_signer.ok()) return jwt_signer.status(); StatusOr token = (*jwt_signer)->SignAndEncode(*raw_jwt); if (!token.ok()) return token.status(); return WriteToFile(*token, token_filename); } } // namespace tink_cc_examples int main(int argc, char** argv) { absl::ParseCommandLine(argc, argv); ValidateParams(); std::string keyset_filename = absl::GetFlag(FLAGS_keyset_filename); std::string audience = absl::GetFlag(FLAGS_audience); std::string token_filename = absl::GetFlag(FLAGS_token_filename); std::clog << "Using keyset in " << keyset_filename << " to "; std::clog << " generate and sign a token using audience '" << audience << "'; the resulting signature is written to " << token_filename << '\n'; CHECK_OK( tink_cc_examples::JwtSign(keyset_filename, audience, token_filename)); return 0; } // [END jwt-sign] ================================================ FILE: cc/examples/jwt/jwt_signature_cli_test.sh ================================================ #!/bin/bash # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ################################################################################ set -euo pipefail ############################################################################# # Tests for Tink C++ JWT signature example. ############################################################################# : "${TEST_TMPDIR:=$(mktemp -d)}" readonly CLI_SIGN="$1" readonly GEN_PUBLIC_JWK_SET_CLI="$2" readonly CLI_VERIFY="$3" readonly PRIVATE_KEYSET_FILE="$4" readonly PUBLIC_KEYSET_FILE="$5" readonly PUBLIC_JWK_SET_FILE="${TEST_TMPDIR}/public_jwk_set.json" readonly TOKEN_FILE="${TEST_TMPDIR}/token.json" readonly TEST_NAME="TinkCcExamplesJwtSignatureTest" readonly AUDIENCE="JWT audience" ####################################### # A helper function for getting the return code of a command that may fail. # Temporarily disables error safety and stores return value in TEST_STATUS. # # Globals: # TEST_STATUS # Arguments: # Command to execute. ####################################### test_command() { set +e "$@" TEST_STATUS=$? set -e } ####################################### # Asserts that the outcome of the latest test command is 0. # # If not, it terminates the test execution. # # Globals: # TEST_STATUS # TEST_NAME # TEST_CASE ####################################### assert_command_succeeded() { if (( TEST_STATUS != 0 )); then echo "[ FAILED ] ${TEST_NAME}.${TEST_CASE}" exit 1 fi } ####################################### # Asserts that the outcome of the latest test command is not 0. # # If not, it terminates the test execution. # # Globals: # TEST_STATUS # TEST_NAME # TEST_CASE ####################################### assert_command_failed() { if (( TEST_STATUS == 0 )); then echo "[ FAILED ] ${TEST_NAME}.${TEST_CASE}" exit 1 fi } ####################################### # Starts a new test case; records the test case name to TEST_CASE. # # Globals: # TEST_NAME # TEST_CASE # Arguments: # test_case: The name of the test case. ####################################### start_test_case() { TEST_CASE="$1" echo "[ RUN ] ${TEST_NAME}.${TEST_CASE}" } ####################################### # Ends a test case printing a success message. # # Globals: # TEST_NAME # TEST_CASE ####################################### end_test_case() { echo "[ OK ] ${TEST_NAME}.${TEST_CASE}" } ############################################################################# start_test_case "sign_verify_all_good" # Sign. test_command "${CLI_SIGN}" \ --keyset_filename "${PRIVATE_KEYSET_FILE}" \ --audience "${AUDIENCE}" \ --token_filename "${TOKEN_FILE}" assert_command_succeeded # Convert to JWK set. test_command "${GEN_PUBLIC_JWK_SET_CLI}" \ --public_keyset_filename "${PUBLIC_KEYSET_FILE}" \ --public_jwk_set_filename "${PUBLIC_JWK_SET_FILE}" assert_command_succeeded # Verify. test_command "${CLI_VERIFY}" \ --jwk_set_filename "${PUBLIC_JWK_SET_FILE}" \ --audience "${AUDIENCE}" \ --token_filename "${TOKEN_FILE}" assert_command_succeeded end_test_case ############################################################################# start_test_case "verify_fails_with_invalid_token" # Sign. test_command "${CLI_SIGN}" \ --keyset_filename "${PRIVATE_KEYSET_FILE}" \ --audience "${AUDIENCE}" \ --token_filename "${TOKEN_FILE}" assert_command_succeeded # Invalid token. echo "modified" >> "${TOKEN_FILE}" # Verify. test_command "${CLI_VERIFY}" \ --jwk_set_filename "${PUBLIC_JWK_SET_FILE}" \ --audience "${AUDIENCE}" \ --token_filename "${TOKEN_FILE}" assert_command_failed end_test_case ############################################################################# start_test_case "verify_fails_with_invalid_audience" # Sign. test_command "${CLI_SIGN}" \ --keyset_filename "${PRIVATE_KEYSET_FILE}" \ --audience "${AUDIENCE}" \ --token_filename "${TOKEN_FILE}" assert_command_succeeded # Modify audience. readonly INVALID_AUDIENCE="invalid audience" # Verify. test_command "${CLI_VERIFY}" \ --jwk_set_filename "${PUBLIC_JWK_SET_FILE}" \ --audience "${INVALID_AUDIENCE}" \ --token_filename "${TOKEN_FILE}" assert_command_failed end_test_case ================================================ FILE: cc/examples/jwt/jwt_signature_private_keyset.json ================================================ { "primaryKeyId": 185188009, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PrivateKey", "value": "EosCEAEagQIAs9iifvWObNLbP+x7zupVIYTdHKba4VFgJEnnGtIII21R+KGddTdvNGAokd4GPrFk1GDPitHrAAoW1+NWrafsEUi2J9Sy3uwEyarsKDggewoBCNg2fcWAiZXplPjUyTlhrLvTuyrcL/mGPy+ib7bdmov+D2EP+rKUH6/ydtQGiyHRR3uurTUWfrMD1/6WaBVfngpy5Pxs2nuHXRmBHQKWmPfvErgr4abdjhKDaWIuxzSise1CSAbiWTNcxpIuFYZgPjgQzpqeh93LUXIX9YJds/bhHtXqRdxk6yTisloHOZETItK/rHCCE25dLkkaJ2Li7AtnJdBc6tEUNiuFj2JCjSIDAQABGoACT2lWxwySaQbp/N3lBUZ/dJ+AKsiaWWdfNmbTfwpCwbHhwhFKv5lMpynWgCIzS7d0uDpPKhLq20eZMpaVjXRaTn92vzuyB7DbpFiukkvGO839CvS9iueMjDP/weHlwzxtHqKJKVoRg7WAS6Iy7XUngLhT5GKNdbsooJ1GSKXyhbgWyMcspKSQe4lZXUntVMK5z4iLNmcQwsBp8yM55mZra13TXowob/E/wd+tGiABCn6CDt8G1gXzWDaoF2tt6WhSGZbXUVGagmoea/BWeAuJyKSSi5h+uPpc5SPhGvyKfSEVaCs2QeM7/UIXhzAcx2j/VqySb6y9EbSiJfy8vr49QSKBAQD+AbFCGHd9kZ5LIQrfe9caOxS9pQPdFkBJESw0C3x2uBIg8awiQsuVXMeEgyGLyWBZoi2x98OMSR9OzCuSLtb7Nv0Wqn0LUj4WPRdmg//uLeD3O2rcVRIR4db/B8WvXnK2uQsqwGDyh4BepGvprXQPYMX2uwnBGL2ccS2De53HJSqBAQC1QfOi4egjmlmXqJLpISUSN1NixkIi8EJHaZZ0YrbaRrEyiJczthcazNHFt6gzgOcosFaKaZeqps4Tet+5NgS7eh7RzLQ2+cfT4ewpT2ExJ4NsOy8XDqD6GRjliLxjGAoUf24s3B+3LLACPiQjeeZGJP0ivh384WabyXXxRgHFSTKBAQChl7gKIYCbHPHEQAAnzyQ4Js/6GinMFCTPlyI09f23lUDLPpRQs4fKvNydO8Myp+ko/NjvOH1qGPbW7WLmu+++n+wA6HNmqWqgQTtK170Q7JULE/zWsTQutitN0cb82yxFfJFTIFJM2NFc5GNWpSeJxPoMDk+VTcUK6qGW3SSyFTqBAQCeaPFA3SZAV1kNjio2zNzVOr0JijOqzUdfmgv/03Xy9e1POMjMTMuMhIygu42o1XMwwEwh037Vicp4g96aw3cHUgc1XC30DgByUPRQdit/BgV5xY+2GvbdHKoBkKrz/8Jvf58OXaLqN4frrdtvlc2GaDVC89zJcUR3ym3lW0WY4UKBAQD6MCruwXaxXJMxjtlH1YT5ow4R5neeiswNfGj4Ta/WbWyiVA60zpdNbGqH+etmiHY8+aBb/H4O9+JhOcBtlMLN4UlK1jg8wPSemZjsIPiUZXHkeIUa2RTUSz90wgz7aOqC0lYsLLFaJNWs54fC9LpZ0JzoqYDI8iDPnlE7xaag9g==", "keyMaterialType": "ASYMMETRIC_PRIVATE" }, "status": "ENABLED", "keyId": 185188009, "outputPrefixType": "TINK" } ] } ================================================ FILE: cc/examples/jwt/jwt_signature_public_keyset.json ================================================ { "primaryKeyId": 185188009, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PublicKey", "value": "EAEagQIAs9iifvWObNLbP+x7zupVIYTdHKba4VFgJEnnGtIII21R+KGddTdvNGAokd4GPrFk1GDPitHrAAoW1+NWrafsEUi2J9Sy3uwEyarsKDggewoBCNg2fcWAiZXplPjUyTlhrLvTuyrcL/mGPy+ib7bdmov+D2EP+rKUH6/ydtQGiyHRR3uurTUWfrMD1/6WaBVfngpy5Pxs2nuHXRmBHQKWmPfvErgr4abdjhKDaWIuxzSise1CSAbiWTNcxpIuFYZgPjgQzpqeh93LUXIX9YJds/bhHtXqRdxk6yTisloHOZETItK/rHCCE25dLkkaJ2Li7AtnJdBc6tEUNiuFj2JCjSIDAQAB", "keyMaterialType": "ASYMMETRIC_PUBLIC" }, "status": "ENABLED", "keyId": 185188009, "outputPrefixType": "TINK" } ] } ================================================ FILE: cc/examples/jwt/jwt_verify.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// // [START jwt-verify] // A utility for creating, signing and verifying JSON Web Tokens (JWT). #include #include #include #include #include #include "absl/flags/flag.h" #include "absl/flags/parse.h" #include "absl/log/check.h" #include "absl/strings/string_view.h" #include "tink/config/global_registry.h" #include "util/util.h" #include "tink/jwt/jwk_set_converter.h" #include "tink/jwt/jwt_public_key_verify.h" #include "tink/jwt/jwt_signature_config.h" #include "tink/jwt/jwt_validator.h" #include "tink/keyset_handle.h" #include "tink/util/status.h" ABSL_FLAG(std::string, jwk_set_filename, "", "Path to the JWK set file"); ABSL_FLAG(std::string, audience, "", "Expected audience in the token"); ABSL_FLAG(std::string, token_filename, "", "Path to the token file"); namespace { using ::crypto::tink::JwkSetToPublicKeysetHandle; using ::crypto::tink::JwtPublicKeyVerify; using ::crypto::tink::JwtValidator; using ::crypto::tink::KeysetHandle; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; void ValidateParams() { // [START_EXCLUDE] CHECK(!absl::GetFlag(FLAGS_jwk_set_filename).empty()) << "Keyset file must be specified"; CHECK(!absl::GetFlag(FLAGS_audience).empty()) << "Expected audience in the token must be specified"; CHECK(!absl::GetFlag(FLAGS_token_filename).empty()) << "Token file must be specified"; // [END_EXCLUDE] } } // namespace namespace tink_cc_examples { // JWT verify example CLI implementation. Status JwtVerify(const std::string& jwk_set_filename, absl::string_view audience, const std::string& token_filename) { Status result = crypto::tink::JwtSignatureRegister(); if (!result.ok()) return result; // Read the JWK set from file and convert it. StatusOr jwk_set = ReadFile(jwk_set_filename); if (!jwk_set.ok()) return jwk_set.status(); StatusOr> keyset_handle = JwkSetToPublicKeysetHandle(*jwk_set); // Read the token. StatusOr token = ReadFile(token_filename); if (!token.ok()) return token.status(); StatusOr validator = crypto::tink::JwtValidatorBuilder().ExpectAudience(audience).Build(); if (!validator.ok()) return validator.status(); StatusOr> jwt_verifier = (*keyset_handle) ->GetPrimitive( crypto::tink::ConfigGlobalRegistry()); if (!jwt_verifier.ok()) return jwt_verifier.status(); return (*jwt_verifier)->VerifyAndDecode(*token, *validator).status(); } } // namespace tink_cc_examples int main(int argc, char** argv) { absl::ParseCommandLine(argc, argv); ValidateParams(); std::string jwk_set_filename = absl::GetFlag(FLAGS_jwk_set_filename); std::string audience = absl::GetFlag(FLAGS_audience); std::string token_filename = absl::GetFlag(FLAGS_token_filename); std::clog << "Using keyset in " << jwk_set_filename << " to "; std::clog << " verify a token with expected audience '" << audience << '\n'; CHECK_OK( tink_cc_examples::JwtVerify(jwk_set_filename, audience, token_filename)); return 0; } // [END jwt-verify] ================================================ FILE: cc/examples/key_derivation/BUILD.bazel ================================================ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) cc_binary( name = "key_derivation_cli", srcs = ["key_derivation_cli.cc"], deps = [ "//util", "@com_google_absl//absl/flags:flag", "@com_google_absl//absl/flags:parse", "@com_google_absl//absl/log:check", "@tink_cc//:aead", "@tink_cc//:keyset_handle", "@tink_cc//aead:aead_config", "@tink_cc//keyderivation:key_derivation_config", "@tink_cc//keyderivation:keyset_deriver", "@tink_cc//util:status", ], ) sh_test( name = "key_derivation_cli_test", size = "small", srcs = ["key_derivation_cli_test.sh"], args = [ "$(rootpath :key_derivation_cli)", "$(rootpaths :keyset.json)", ], data = [ ":key_derivation_cli", ":keyset.json", ], ) ================================================ FILE: cc/examples/key_derivation/CMakeLists.txt ================================================ add_executable(key_derivation_cli key_derivation_cli.cc) target_include_directories(key_derivation_cli PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${TINK_EXAMPLES_INCLUDE_PATH}") target_link_libraries(key_derivation_cli tink::static absl::check absl::flags_parse util) add_test( NAME key_derivation_cli_test COMMAND "${BASH_PROGRAM}" "${CMAKE_CURRENT_SOURCE_DIR}/key_derivation_cli_test.sh" "${CMAKE_CURRENT_BINARY_DIR}/key_derivation_cli" "${CMAKE_CURRENT_SOURCE_DIR}/keyset.json" ================================================ FILE: cc/examples/key_derivation/key_derivation_cli.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// // [START key-derivation-example] // A command-line utility for testing Tink Key Derivation. #include #include #include #include #include "absl/flags/flag.h" #include "absl/flags/parse.h" #include "absl/log/check.h" #include "absl/status/status.h" #include "tink/aead.h" #include "tink/aead/aead_config.h" #include "tink/config/global_registry.h" #include "util/util.h" #include "tink/keyderivation/key_derivation_config.h" #include "tink/keyderivation/keyset_deriver.h" #include "tink/keyset_handle.h" #include "tink/util/status.h" ABSL_FLAG(std::string, keyset_filename, "", "File in JSON format containing keyset that derives an AEAD keyset"); ABSL_FLAG(std::string, salt_filename, "", "Salt file name"); ABSL_FLAG(std::string, derived_keyset_filename, "", "Derived keyset file name"); namespace { using ::crypto::tink::Aead; using ::crypto::tink::AeadConfig; using ::crypto::tink::KeyDerivationConfig; using ::crypto::tink::KeysetDeriver; using ::crypto::tink::KeysetHandle; using ::crypto::tink::util::OkStatus; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; void ValidateParams() { // [START_EXCLUDE] CHECK(!absl::GetFlag(FLAGS_keyset_filename).empty()) << "Keyset file must be specified"; CHECK(!absl::GetFlag(FLAGS_salt_filename).empty()) << "Input file must be specified"; CHECK(!absl::GetFlag(FLAGS_derived_keyset_filename).empty()) << "Output file must be specified"; // [END_EXCLUDE] } // Verifies `handle` contains a valid AEAD primitive. Status VerifyDerivedAeadKeyset(const KeysetHandle& handle) { // [START_EXCLUDE] StatusOr> aead = handle.GetPrimitive( crypto::tink::ConfigGlobalRegistry()); if (!aead.ok()) return aead.status(); std::string plaintext = "plaintext"; std::string ad = "ad"; StatusOr ciphertext = (*aead)->Encrypt(plaintext, ad); if (!ciphertext.ok()) return ciphertext.status(); StatusOr got = (*aead)->Decrypt(*ciphertext, ad); if (!got.ok()) return got.status(); if (*got != plaintext) { return Status( absl::StatusCode::kInternal, "AEAD obtained from derived keyset failed to decrypt correctly"); } return OkStatus(); // [END_EXCLUDE] } } // namespace namespace tink_cc_examples { Status KeyDerivationCli(const std::string& keyset_filename, const std::string& salt_filename, const std::string& derived_keyset_filename) { Status result = KeyDerivationConfig::Register(); if (!result.ok()) return result; result = AeadConfig::Register(); if (!result.ok()) return result; // Read keyset from file. StatusOr> keyset_handle = ReadJsonCleartextKeyset(keyset_filename); if (!keyset_handle.ok()) return keyset_handle.status(); // Get the primitive. StatusOr> deriver = (*keyset_handle) ->GetPrimitive( crypto::tink::ConfigGlobalRegistry()); if (!deriver.ok()) return deriver.status(); // Read the salt. StatusOr salt_file_content = ReadFile(salt_filename); if (!salt_file_content.ok()) return salt_file_content.status(); // Derive new keyset. StatusOr> derived_handle = (*deriver)->DeriveKeyset(*salt_file_content); if (!derived_handle.ok()) return derived_handle.status(); Status status = VerifyDerivedAeadKeyset(**derived_handle); if (!status.ok()) return status; return WriteJsonCleartextKeyset(derived_keyset_filename, **derived_handle); } } // namespace tink_cc_examples int main(int argc, char** argv) { absl::ParseCommandLine(argc, argv); ValidateParams(); std::string keyset_filename = absl::GetFlag(FLAGS_keyset_filename); std::string salt_filename = absl::GetFlag(FLAGS_salt_filename); std::string derived_keyset_filename = absl::GetFlag(FLAGS_derived_keyset_filename); std::clog << "Using keyset from file " << keyset_filename << " to derive a new AEAD keyset with the salt in file " << salt_filename << "." << '\n'; std::clog << "The resulting derived keyset will be written to " << derived_keyset_filename << "." << '\n'; CHECK_OK(tink_cc_examples::KeyDerivationCli(keyset_filename, salt_filename, derived_keyset_filename)); return 0; } // [END key-derivation-example] ================================================ FILE: cc/examples/key_derivation/key_derivation_cli_test.sh ================================================ #!/bin/bash # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ################################################################################ set -euo pipefail ############################################################################# # Tests for Tink C++ Key Derivation example. ############################################################################# : "${TEST_TMPDIR:=$(mktemp -d)}" readonly CLI="$1" readonly KEYSET_FILE="$2" readonly SALT_FILE="${TEST_TMPDIR}/salt.txt" readonly DERIVED_KEYSET_FILE="${TEST_TMPDIR}/derived_keyset.json" readonly TEST_NAME="TinkCcExamplesKeyDerivationTest" echo "This is the salt used to derive keys." > "${SALT_FILE}" ####################################### # A helper function for getting the return code of a command that may fail. # Temporarily disables error safety and stores return value in TEST_STATUS. # # Globals: # TEST_STATUS # Arguments: # Command to execute. ####################################### test_command() { set +e "$@" TEST_STATUS=$? set -e } ####################################### # Asserts that the outcome of the latest test command is 0. # # If not, it terminates the test execution. # # Globals: # TEST_STATUS # TEST_NAME # TEST_CASE ####################################### assert_command_succeeded() { if (( TEST_STATUS != 0 )); then echo "[ FAILED ] ${TEST_NAME}.${TEST_CASE}" exit 1 fi } ####################################### # Asserts that the outcome of the latest test command is not 0. # # If not, it terminates the test execution. # # Globals: # TEST_STATUS # TEST_NAME # TEST_CASE ####################################### assert_command_failed() { if (( TEST_STATUS == 0 )); then echo "[ FAILED ] ${TEST_NAME}.${TEST_CASE}" exit 1 fi } ####################################### # Starts a new test case; records the test case name to TEST_CASE. # # Globals: # TEST_NAME # TEST_CASE # Arguments: # test_case: The name of the test case. ####################################### start_test_case() { TEST_CASE="$1" echo "[ RUN ] ${TEST_NAME}.${TEST_CASE}" } ####################################### # Ends a test case printing a success message. # # Globals: # TEST_NAME # TEST_CASE ####################################### end_test_case() { echo "[ OK ] ${TEST_NAME}.${TEST_CASE}" } ############################################################################# start_test_case "derive_key" test_command "${CLI}" \ --keyset_filename "${KEYSET_FILE}" \ --salt_filename "${SALT_FILE}" \ --derived_keyset_filename "${DERIVED_KEYSET_FILE}" assert_command_succeeded end_test_case ================================================ FILE: cc/examples/key_derivation/keyset.json ================================================ { "primaryKeyId": 1746379508, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.PrfBasedDeriverKey", "value": "El0KMXR5cGUuZ29vZ2xlYXBpcy5jb20vZ29vZ2xlLmNyeXB0by50aW5rLkhrZGZQcmZLZXkSJhICCAMaIHq3492RGOyzGsJTQh6Xi6noTDSrPQxULHuBqB10zMUCGAEaOgo4CjB0eXBlLmdvb2dsZWFwaXMuY29tL2dvb2dsZS5jcnlwdG8udGluay5BZXNHY21LZXkSAhAQGAE=", "keyMaterialType": "SYMMETRIC" }, "status": "ENABLED", "keyId": 1746379508, "outputPrefixType": "TINK" } ] } ================================================ FILE: cc/examples/mac/BUILD.bazel ================================================ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) filegroup( name = "mac_test_keyset", srcs = ["mac_test_keyset.json"], ) cc_binary( name = "mac_cli", srcs = ["mac_cli.cc"], deps = [ "//util", "@com_google_absl//absl/flags:flag", "@com_google_absl//absl/flags:parse", "@com_google_absl//absl/log:check", "@com_google_absl//absl/strings", "@tink_cc//:cleartext_keyset_handle", "@tink_cc//:keyset_handle", "@tink_cc//:mac", "@tink_cc//mac:mac_config", "@tink_cc//util:status", ], ) sh_test( name = "mac_cli_test", size = "small", srcs = ["mac_cli_test.sh"], args = [ "$(rootpath :mac_cli)", "$(rootpath :mac_test_keyset)", ], data = [ ":mac_cli", ":mac_test_keyset", ], ) ================================================ FILE: cc/examples/mac/CMakeLists.txt ================================================ add_executable(mac_cli mac_cli.cc) target_include_directories(mac_cli PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${TINK_EXAMPLES_INCLUDE_PATH}") target_link_libraries(mac_cli tink::static absl::check absl::flags_parse util) add_test( NAME mac_cli_test COMMAND "${BASH_PROGRAM}" "${CMAKE_CURRENT_SOURCE_DIR}/mac_cli_test.sh" "${CMAKE_CURRENT_BINARY_DIR}/mac_cli" "${CMAKE_CURRENT_SOURCE_DIR}/mac_test_keyset.json") ================================================ FILE: cc/examples/mac/mac_cli.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// // [START mac-example] // A command-line utility for showcasing using the Tink MAC primitive. #include #include #include #include #include #include #include #include #include "absl/flags/flag.h" #include "absl/flags/parse.h" #include "absl/log/check.h" #include "absl/strings/string_view.h" #include "tink/config/global_registry.h" #include "util/util.h" #include "tink/keyset_handle.h" #include "tink/mac.h" #include "tink/mac/mac_config.h" #include "tink/util/status.h" ABSL_FLAG(std::string, keyset_filename, "", "Keyset file in JSON format"); ABSL_FLAG(std::string, mode, "", "Mode of operation {compute|verify}"); ABSL_FLAG(std::string, data_filename, "", "Data file name"); ABSL_FLAG(std::string, tag_filename, "", "Authentication tag file name"); namespace { using ::crypto::tink::KeysetHandle; using ::crypto::tink::Mac; using ::crypto::tink::MacConfig; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; constexpr absl::string_view kCompute = "compute"; constexpr absl::string_view kVerify = "verify"; void ValidateParams() { // [START_EXCLUDE] CHECK(absl::GetFlag(FLAGS_mode) == kCompute || absl::GetFlag(FLAGS_mode) == kVerify) << "Invalid mode; must be `" << kCompute << "` or `" << kVerify << "`"; CHECK(!absl::GetFlag(FLAGS_keyset_filename).empty()) << "Keyset file must be specified"; CHECK(!absl::GetFlag(FLAGS_data_filename).empty()) << "Data file must be specified"; CHECK(!absl::GetFlag(FLAGS_tag_filename).empty()) << "Tag file must be specified"; // [END_EXCLUDE] } } // namespace namespace tink_cc_examples { // MAC example CLI implementation. Status MacCli(absl::string_view mode, const std::string keyset_filename, const std::string& data_filename, const std::string& tag_filename) { Status result = MacConfig::Register(); if (!result.ok()) return result; // Read the keyset from file. StatusOr> keyset_handle = ReadJsonCleartextKeyset(keyset_filename); if (!keyset_handle.ok()) return keyset_handle.status(); // Get the primitive. StatusOr> mac_primitive = (*keyset_handle) ->GetPrimitive( crypto::tink::ConfigGlobalRegistry()); if (!mac_primitive.ok()) return mac_primitive.status(); // Read the input. StatusOr data_file_content = ReadFile(data_filename); if (!data_file_content.ok()) return data_file_content.status(); std::string output; if (mode == kCompute) { // Compute authentication tag. StatusOr compute_result = (*mac_primitive)->ComputeMac(*data_file_content); if (!compute_result.ok()) return compute_result.status(); // Write out the authentication tag to tag file. return WriteToFile(*compute_result, tag_filename); } else { // operation == kVerify. // Read the authentication tag from tag file. StatusOr tag_result = ReadFile(tag_filename); if (!tag_result.ok()) { std::cerr << tag_result.status().message() << '\n'; exit(1); } // Verify authentication tag. Status verify_result = (*mac_primitive)->VerifyMac(*tag_result, *data_file_content); if (verify_result.ok()) std::clog << "Verification succeeded!" << '\n'; return verify_result; } } } // namespace tink_cc_examples int main(int argc, char** argv) { absl::ParseCommandLine(argc, argv); ValidateParams(); std::string mode = absl::GetFlag(FLAGS_mode); std::string keyset_filename = absl::GetFlag(FLAGS_keyset_filename); std::string data_filename = absl::GetFlag(FLAGS_data_filename); std::string tag_filename = absl::GetFlag(FLAGS_tag_filename); std::clog << "Using keyset from file '" << keyset_filename << "' to " << mode << " authentication tag from file '" << tag_filename << "' for data file '" << data_filename << "'." << '\n'; std::clog << "The tag will be " << ((mode == kCompute) ? "written to" : "read from") << " file '" << tag_filename << "'." << '\n'; CHECK_OK(tink_cc_examples::MacCli(mode, keyset_filename, data_filename, tag_filename)); return 0; } // [END mac-example] ================================================ FILE: cc/examples/mac/mac_cli_test.sh ================================================ #!/bin/bash # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ################################################################################ set -euo pipefail ############################################################################# # Tests for Tink CC MAC. ############################################################################# : "${TEST_TMPDIR:=$(mktemp -d)}" readonly CLI="$1" readonly KEYSET_FILE="$2" readonly DATA_FILE="${TEST_TMPDIR}/example_data.txt" readonly TEST_NAME="TinkExamplesCcMacTest" echo "This is some input data to be authenticated." > "${DATA_FILE}" ####################################### # A helper function for getting the return code of a command that may fail. # Temporarily disables error safety and stores return value in TEST_STATUS. # # Globals: # TEST_STATUS # Arguments: # Command to execute. ####################################### test_command() { set +e "$@" TEST_STATUS=$? set -e } ####################################### # Asserts that the outcome of the latest test command is 0. # # If not, it terminates the test execution. # # Globals: # TEST_STATUS # TEST_NAME # TEST_CASE ####################################### assert_command_succeeded() { if (( TEST_STATUS != 0 )); then echo "[ FAILED ] ${TEST_NAME}.${TEST_CASE}" exit 1 fi } ####################################### # Asserts that the outcome of the latest test command is not 0. # # If not, it terminates the test execution. # # Globals: # TEST_STATUS # TEST_NAME # TEST_CASE ####################################### assert_command_failed() { if (( TEST_STATUS == 0 )); then echo "[ FAILED ] ${TEST_NAME}.${TEST_CASE}" exit 1 fi } ####################################### # Starts a new test case; records the test case name to TEST_CASE. # # Globals: # TEST_NAME # TEST_CASE # Arguments: # test_case: The name of the test case. ####################################### start_test_case() { TEST_CASE="$1" echo "[ RUN ] ${TEST_NAME}.${TEST_CASE}" } ####################################### # Ends a test case printing a success message. # # Globals: # TEST_NAME # TEST_CASE ####################################### end_test_case() { echo "[ OK ] ${TEST_NAME}.${TEST_CASE}" } ############################################################################# start_test_case "compute" # Run MAC computation. test_command "${CLI}" \ --mode compute \ --keyset_filename "${KEYSET_FILE}" \ --data_filename "${DATA_FILE}" \ --tag_filename "${DATA_FILE}.tag" assert_command_succeeded end_test_case ############################################################################# start_test_case "verify" # Run MAC verification. test_command "${CLI}" \ --mode verify \ --keyset_filename "${KEYSET_FILE}" \ --data_filename "${DATA_FILE}" \ --tag_filename "${DATA_FILE}.tag" assert_command_succeeded end_test_case ############################################################################# start_test_case "verify_fails_with_modified_input_data" # Run MAC computation. test_command "${CLI}" \ --mode compute \ --keyset_filename "${KEYSET_FILE}" \ --data_filename "${DATA_FILE}" \ --tag_filename "${DATA_FILE}.tag" assert_command_succeeded # Copy input file. cp "${DATA_FILE}" "${DATA_FILE}.copy" # Verify with unmodified input. test_command "${CLI}" \ --mode verify \ --keyset_filename "${KEYSET_FILE}" \ --data_filename "${DATA_FILE}.copy" \ --tag_filename "${DATA_FILE}.tag" assert_command_succeeded # Modify copy of input file. echo "modified" >> "${DATA_FILE}.copy" # Verify with modified input. test_command "${CLI}" \ --mode verify \ --keyset_filename "${KEYSET_FILE}" \ --data_filename "${DATA_FILE}.copy" \ --tag_filename "${DATA_FILE}.tag" assert_command_failed end_test_case ############################################################################# start_test_case "verify_fails_with_modified_tag" # Run MAC computation. test_command "${CLI}" \ --mode compute \ --keyset_filename "${KEYSET_FILE}" \ --data_filename "${DATA_FILE}" \ --tag_filename "${DATA_FILE}.tag" assert_command_succeeded # Copy tag. cp "${DATA_FILE}.tag" "${DATA_FILE}.tag.copy" # Verify with unmodified tag. test_command "${CLI}" \ --mode verify \ --keyset_filename "${KEYSET_FILE}" \ --data_filename "${DATA_FILE}" \ --tag_filename "${DATA_FILE}.tag.copy" assert_command_succeeded # Modify copy of tag. echo "modified" >> "${DATA_FILE}.tag.copy" # Verify with modified tag. test_command "${CLI}" \ --mode verify \ --keyset_filename "${KEYSET_FILE}" \ --data_filename "${DATA_FILE}" \ --tag_filename "${DATA_FILE}.tag.copy" assert_command_failed end_test_case ================================================ FILE: cc/examples/mac/mac_test_keyset.json ================================================ { "primaryKeyId": 691856985, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.HmacKey", "keyMaterialType": "SYMMETRIC", "value": "EgQIAxAgGiDZsmkTufMG/XlKlk9m7bqxustjUPT2YULEVm8mOp2mSA==" }, "outputPrefixType": "TINK", "keyId": 691856985, "status": "ENABLED" } ] } ================================================ FILE: cc/examples/util/BUILD.bazel ================================================ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) cc_library( name = "util", srcs = ["util.cc"], hdrs = ["util.h"], deps = [ "@com_google_absl//absl/memory", "@tink_cc//:cleartext_keyset_handle", "@tink_cc//:json_keyset_reader", "@tink_cc//:json_keyset_writer", "@tink_cc//:keyset_handle", "@tink_cc//:keyset_reader", "@tink_cc//:keyset_writer", "@tink_cc//util:status", "@tink_cc//util:statusor", ], ) ================================================ FILE: cc/examples/util/CMakeLists.txt ================================================ add_library(util util.cc util.h) target_include_directories(util PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${TINK_EXAMPLES_INCLUDE_PATH}") target_link_libraries(util tink::static) ================================================ FILE: cc/examples/util/util.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "util/util.h" #include #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/cleartext_keyset_handle.h" #include "tink/json_keyset_reader.h" #include "tink/json_keyset_writer.h" #include "tink/keyset_handle.h" #include "tink/keyset_reader.h" #include "tink/keyset_writer.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace tink_cc_examples { namespace { using ::crypto::tink::JsonKeysetReader; using ::crypto::tink::JsonKeysetWriter; using ::crypto::tink::KeysetHandle; using ::crypto::tink::KeysetReader; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; // Creates a KeysetReader that reads a JSON-formatted keyset // from the given file. StatusOr> GetJsonKeysetReader( const std::string& filename) { auto input_stream = absl::make_unique(); input_stream->open(filename, std::ifstream::in); return JsonKeysetReader::New(std::move(input_stream)); } StatusOr> GetJsonKeysetWriter( const std::string& filename) { auto output_stream = absl::make_unique(); output_stream->open(filename, std::ofstream::out); return JsonKeysetWriter::New(std::move(output_stream)); } } // namespace StatusOr> ReadJsonCleartextKeyset( const std::string& filename) { StatusOr> keyset_reader = GetJsonKeysetReader(filename); if (!keyset_reader.ok()) return keyset_reader.status(); return crypto::tink::CleartextKeysetHandle::Read(*std::move(keyset_reader)); } Status WriteJsonCleartextKeyset(const std::string& filename, const KeysetHandle& keyset_handle) { StatusOr> keyset_writer = GetJsonKeysetWriter(filename); if (!keyset_writer.ok()) return keyset_writer.status(); return crypto::tink::CleartextKeysetHandle::Write(keyset_writer->get(), keyset_handle); } StatusOr ReadFile(const std::string& filename) { std::ifstream input_stream; input_stream.open(filename, std::ifstream::in); if (!input_stream.is_open()) { return Status(absl::StatusCode::kInternal, absl::StrCat("Error opening input file ", filename)); } std::stringstream input; input << input_stream.rdbuf(); return input.str(); } Status WriteToFile(const std::string& data_to_write, const std::string& filename) { std::ofstream output_stream(filename, std::ofstream::out | std::ofstream::binary); if (!output_stream.is_open()) { return Status(absl::StatusCode::kInternal, absl::StrCat("Error opening output file ", filename)); } output_stream << data_to_write; return crypto::tink::util::OkStatus(); } } // namespace tink_cc_examples ================================================ FILE: cc/examples/util/util.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXAMPLES_UTIL_UTIL_H_ #define TINK_EXAMPLES_UTIL_UTIL_H_ #include #include #include "tink/keyset_handle.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace tink_cc_examples { // Reads a keyset from the given file `filename` which is expected to contain a // JSON-formatted keyset. crypto::tink::util::StatusOr> ReadJsonCleartextKeyset(const std::string& filename); // Writes `keyset_handle` to the file `filename` formatted with JSON in // cleartext. crypto::tink::util::Status WriteJsonCleartextKeyset( const std::string& filename, const crypto::tink::KeysetHandle& keyset_handle); // Reads `filename` and returns the read content as a string, or an error status // if the file does not exist. crypto::tink::util::StatusOr ReadFile(const std::string& filename); // Writes the given `data_to_write` to the specified file `filename`. crypto::tink::util::Status WriteToFile(const std::string& data_to_write, const std::string& filename); } // namespace tink_cc_examples #endif // TINK_EXAMPLES_UTIL_UTIL_H_ ================================================ FILE: cc/examples/walkthrough/BUILD.bazel ================================================ """Walkthrough examples for using Tink.""" package(default_visibility = ["//visibility:public"]) licenses(["notice"]) cc_library( name = "test_util", testonly = 1, srcs = ["test_util.cc"], hdrs = ["test_util.h"], deps = [ ":load_cleartext_keyset", "@com_google_absl//absl/strings", "@tink_cc", ], ) cc_library( name = "create_keyset", srcs = ["create_keyset.cc"], hdrs = ["create_keyset.h"], deps = [ "@tink_cc", "@tink_cc//:keyset_handle", "@tink_cc//util:statusor", ], ) cc_test( name = "create_keyset_test", srcs = ["create_keyset_test.cc"], deps = [ ":create_keyset", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", "@tink_cc", "@tink_cc//util:test_matchers", ], ) cc_library( name = "load_cleartext_keyset", srcs = ["load_cleartext_keyset.cc"], hdrs = ["load_cleartext_keyset.h"], deps = [ "@com_google_absl//absl/strings", "@tink_cc", "@tink_cc//:cleartext_keyset_handle", ], ) cc_test( name = "load_cleartext_keyset_test", srcs = ["load_cleartext_keyset_test.cc"], deps = [ ":load_cleartext_keyset", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", "@tink_cc", "@tink_cc//util:test_matchers", ], ) cc_library( name = "load_encrypted_keyset", srcs = ["load_encrypted_keyset.cc"], hdrs = ["load_encrypted_keyset.h"], deps = [ "@com_google_absl//absl/strings", "@tink_cc", ], ) cc_test( name = "load_encrypted_keyset_test", srcs = ["load_encrypted_keyset_test.cc"], deps = [ ":load_cleartext_keyset", ":load_encrypted_keyset", ":test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", "@tink_cc", "@tink_cc//util:test_matchers", ], ) cc_library( name = "write_keyset", srcs = ["write_keyset.cc"], hdrs = ["write_keyset.h"], deps = [ "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@tink_cc", ], ) cc_test( name = "write_keyset_test", srcs = ["write_keyset_test.cc"], deps = [ ":load_cleartext_keyset", ":load_encrypted_keyset", ":test_util", ":write_keyset", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", "@tink_cc", "@tink_cc//util:test_matchers", ], ) cc_library( name = "obtain_and_use_a_primitive", srcs = ["obtain_and_use_a_primitive.cc"], hdrs = ["obtain_and_use_a_primitive.h"], deps = [ "@com_google_absl//absl/strings", "@tink_cc", ], ) cc_test( name = "obtain_and_use_a_primitive_test", srcs = ["obtain_and_use_a_primitive_test.cc"], deps = [ ":load_cleartext_keyset", ":obtain_and_use_a_primitive", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", "@tink_cc", "@tink_cc//util:test_matchers", ], ) cc_library( name = "write_cleartext_keyset", srcs = ["write_cleartext_keyset.cc"], hdrs = ["write_cleartext_keyset.h"], deps = [ "@com_google_absl//absl/strings", "@tink_cc", "@tink_cc//:cleartext_keyset_handle", ], ) cc_test( name = "write_cleartext_keyset_test", srcs = ["write_cleartext_keyset_test.cc"], deps = [ ":load_cleartext_keyset", ":write_cleartext_keyset", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", "@tink_cc", "@tink_cc//util:test_matchers", ], ) ================================================ FILE: cc/examples/walkthrough/CMakeLists.txt ================================================ # Library targets. add_library(create_keyset create_keyset.cc create_keyset.h) target_include_directories(create_keyset PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${TINK_EXAMPLES_INCLUDE_PATH}") target_link_libraries(create_keyset tink::static) add_library(load_cleartext_keyset load_cleartext_keyset.cc load_cleartext_keyset.h) target_include_directories(load_cleartext_keyset PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${TINK_EXAMPLES_INCLUDE_PATH}") target_link_libraries(load_cleartext_keyset tink::static) add_library(test_util test_util.cc test_util.h) target_include_directories(test_util PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${TINK_EXAMPLES_INCLUDE_PATH}") target_link_libraries(test_util load_cleartext_keyset tink::static) add_library(load_encrypted_keyset load_encrypted_keyset.cc load_encrypted_keyset.h) target_include_directories(load_encrypted_keyset PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${TINK_EXAMPLES_INCLUDE_PATH}") target_link_libraries(load_encrypted_keyset tink::static) add_library(write_keyset write_keyset.cc write_keyset.h) target_include_directories(write_keyset PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${TINK_EXAMPLES_INCLUDE_PATH}") target_link_libraries(write_keyset load_cleartext_keyset tink::static) add_library(obtain_and_use_a_primitive obtain_and_use_a_primitive.cc obtain_and_use_a_primitive.h) target_include_directories(obtain_and_use_a_primitive PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${TINK_EXAMPLES_INCLUDE_PATH}") target_link_libraries(obtain_and_use_a_primitive tink::static) add_library(write_cleartext_keyset write_cleartext_keyset.cc write_cleartext_keyset.h) target_include_directories(write_cleartext_keyset PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${TINK_EXAMPLES_INCLUDE_PATH}") target_link_libraries(write_cleartext_keyset tink::static) # Test targets. add_executable(create_keyset_test create_keyset_test.cc) add_test(NAME create_keyset_test COMMAND create_keyset_test WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) target_link_libraries(create_keyset_test create_keyset gmock gtest_main) add_executable(load_cleartext_keyset_test load_cleartext_keyset_test.cc) add_test(NAME load_cleartext_keyset_test COMMAND load_cleartext_keyset_test WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) target_link_libraries(load_cleartext_keyset_test load_cleartext_keyset gmock gtest_main) add_executable(load_encrypted_keyset_test load_encrypted_keyset_test.cc) add_test(NAME load_encrypted_keyset_test COMMAND load_encrypted_keyset_test WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) target_link_libraries(load_encrypted_keyset_test test_util load_encrypted_keyset load_cleartext_keyset gmock gtest_main) add_executable(write_keyset_test write_keyset_test.cc) add_test(NAME write_keyset_test COMMAND write_keyset_test WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) target_link_libraries(write_keyset_test test_util write_keyset load_cleartext_keyset load_encrypted_keyset gmock gtest_main) add_executable(obtain_and_use_a_primitive_test obtain_and_use_a_primitive_test.cc) add_test(NAME obtain_and_use_a_primitive_test COMMAND obtain_and_use_a_primitive_test WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) target_link_libraries(obtain_and_use_a_primitive_test obtain_and_use_a_primitive load_cleartext_keyset gmock gtest_main) add_executable(write_cleartext_keyset_test write_cleartext_keyset_test.cc) add_test(NAME write_cleartext_keyset_test COMMAND write_cleartext_keyset_test WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) target_link_libraries(write_cleartext_keyset_test write_cleartext_keyset load_cleartext_keyset gmock gtest_main) ================================================ FILE: cc/examples/walkthrough/create_keyset.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "walkthrough/create_keyset.h" // [START tink_walkthrough_create_keyset] #include #include "tink/aead/aead_key_templates.h" #include "tink/config/global_registry.h" #include "tink/keyset_handle.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace tink_walkthrough { using ::crypto::tink::KeysetHandle; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::KeyTemplate; // Creates a keyset with a single AES128-GCM key and return a handle to it. // // Prerequisites for this example: // - Register AEAD implementations of Tink. StatusOr> CreateAead128GcmKeyset() { // Tink provides pre-baked templates. For example, we generate a key template // for AES128-GCM. KeyTemplate key_template = crypto::tink::AeadKeyTemplates::Aes128Gcm(); // This will generate a new keyset with only *one* key and return a keyset // handle to it. return KeysetHandle::GenerateNew(key_template, crypto::tink::KeyGenConfigGlobalRegistry()); } } // namespace tink_walkthrough // [END tink_walkthrough_create_keyset] ================================================ FILE: cc/examples/walkthrough/create_keyset.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXAMPLES_WALKTHROUGH_CREATE_KEYSET_H_ #define TINK_EXAMPLES_WALKTHROUGH_CREATE_KEYSET_H_ #include #include "tink/keyset_handle.h" #include "tink/util/statusor.h" namespace tink_walkthrough { // Creates a keyset with a single AES128-GCM key and return a handle to it. crypto::tink::util::StatusOr> CreateAead128GcmKeyset(); } // namespace tink_walkthrough #endif // TINK_EXAMPLES_WALKTHROUGH_CREATE_KEYSET_H_ ================================================ FILE: cc/examples/walkthrough/create_keyset_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "walkthrough/create_keyset.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/aead/aead_config.h" #include "tink/config/global_registry.h" #include "tink/keyset_handle.h" #include "tink/registry.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace tink_walkthrough { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::util::StatusOr; using ::testing::Not; using ::testing::Test; class CreateAead128GcmKeysetTest : public Test { public: void TearDown() override { crypto::tink::Registry::Reset(); } }; TEST_F(CreateAead128GcmKeysetTest, CreateAead128GcmKeysetFailsIfAeadNotRegistered) { EXPECT_THAT(CreateAead128GcmKeyset(), Not(IsOk())); } TEST_F(CreateAead128GcmKeysetTest, CreateAead128GcmKeysetSucceeds) { ASSERT_THAT(crypto::tink::AeadConfig::Register(), IsOk()); StatusOr> keyset_handle = CreateAead128GcmKeyset(); ASSERT_THAT(keyset_handle, IsOk()); constexpr absl::string_view plaintext = "Some plaintext"; constexpr absl::string_view associated_data = "Some associated_data"; StatusOr> aead = (*keyset_handle) ->GetPrimitive( crypto::tink::ConfigGlobalRegistry()); ASSERT_THAT(aead, IsOk()); StatusOr ciphertext = (*aead)->Encrypt(plaintext, associated_data); ASSERT_THAT(ciphertext, IsOk()); EXPECT_THAT((*aead)->Decrypt(*ciphertext, associated_data), IsOkAndHolds(plaintext)); } } // namespace } // namespace tink_walkthrough ================================================ FILE: cc/examples/walkthrough/load_cleartext_keyset.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "walkthrough/load_cleartext_keyset.h" // [START tink_walkthrough_load_cleartext_keyset] #include #include #include #include "absl/strings/string_view.h" #include "tink/cleartext_keyset_handle.h" #include "tink/json_keyset_reader.h" #include "tink/keyset_handle.h" #include "tink/keyset_reader.h" #include "tink/util/statusor.h" namespace tink_walkthrough { using ::crypto::tink::util::StatusOr; // Loads a JSON-serialized unencrypted keyset `serialized_keyset` and returns a // KeysetHandle. // // Prerequisites for this example: // - Create an plaintext keyset in JSON, for example, using Tinkey: // // tinkey create-key --key-template AES256_GCM \ // --out-format json --out keyset.json // StatusOr> LoadKeyset( absl::string_view serialized_keyset) { // To load a serialized keyset we need a JSON keyset reader. StatusOr> reader = crypto::tink::JsonKeysetReader::New(serialized_keyset); if (!reader.ok()) return reader.status(); // Parse and obtain the keyset using the reader. return crypto::tink::CleartextKeysetHandle::Read(*std::move(reader)); } } // namespace tink_walkthrough // [END tink_walkthrough_load_cleartext_keyset] ================================================ FILE: cc/examples/walkthrough/load_cleartext_keyset.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXAMPLES_WALKTHROUGH_LOAD_CLEARTEXT_KEYSET_H_ #define TINK_EXAMPLES_WALKTHROUGH_LOAD_CLEARTEXT_KEYSET_H_ #include #include "absl/strings/string_view.h" #include "tink/keyset_handle.h" #include "tink/util/statusor.h" namespace tink_walkthrough { // Loads a JSON-serialized unencrypted keyset `serialized_keyset` and returns a // KeysetHandle. crypto::tink::util::StatusOr> LoadKeyset(absl::string_view serialized_keyset); } // namespace tink_walkthrough #endif // TINK_EXAMPLES_WALKTHROUGH_LOAD_CLEARTEXT_KEYSET_H_ ================================================ FILE: cc/examples/walkthrough/load_cleartext_keyset_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "walkthrough/load_cleartext_keyset.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/aead/aead_config.h" #include "tink/config/global_registry.h" #include "tink/keyset_handle.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace tink_walkthrough { namespace { constexpr absl::string_view kSerializedKeyset = R"json({ "key": [ { "keyData": { "keyMaterialType": "SYMMETRIC", "typeUrl": "type.googleapis.com/google.crypto.tink.AesGcmKey", "value": "GiBWyUfGgYk3RTRhj/LIUzSudIWlyjCftCOypTr0jCNSLg==" }, "keyId": 294406504, "outputPrefixType": "TINK", "status": "ENABLED" } ], "primaryKeyId": 294406504 })json"; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::StatusOr; TEST(LoadKeysetTest, LoadKeysetFailsWithInvalidKeyset) { EXPECT_THAT(LoadKeyset("Invalid").status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(LoadKeysetTest, LoadKeysetSucceeds) { StatusOr> keyset_handle = LoadKeyset(kSerializedKeyset); ASSERT_THAT(keyset_handle, IsOk()); ASSERT_THAT(crypto::tink::AeadConfig::Register(), IsOk()); // Make sure we can extract the Aead primitive and encrypt/decrypt with it. constexpr absl::string_view plaintext = "Some plaintext"; constexpr absl::string_view associated_data = "Some associated_data"; StatusOr> aead = (*keyset_handle) ->GetPrimitive( crypto::tink::ConfigGlobalRegistry()); ASSERT_THAT(aead, IsOk()); StatusOr ciphertext = (*aead)->Encrypt(plaintext, associated_data); ASSERT_THAT(ciphertext, IsOk()); EXPECT_THAT((*aead)->Decrypt(*ciphertext, associated_data), IsOkAndHolds(plaintext)); } } // namespace } // namespace tink_walkthrough ================================================ FILE: cc/examples/walkthrough/load_encrypted_keyset.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "walkthrough/load_encrypted_keyset.h" // [START tink_walkthrough_load_encrypted_keyset] #include #include #include #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/json_keyset_reader.h" #include "tink/keyset_handle.h" #include "tink/keyset_reader.h" #include "tink/kms_client.h" #include "tink/kms_clients.h" #include "tink/util/statusor.h" namespace tink_walkthrough { using ::crypto::tink::KeysetHandle; using ::crypto::tink::util::StatusOr; // Loads an encrypted JSON-serialized keyset `serialized_encrypted_keyset`. // The keyset is decrypted using `keyset_encryption_aead`. // // Prerequisites for this example: // - Register AEAD implementations of Tink. // - Create a KMS encrypted keyset, for example using Tinkey with Cloud KMS: // // tinkey create-keyset --key-template AES128_GCM \ // --out-format json --out encrypted_aead_keyset.json \ // --master-key-uri gcp-kms:// \ // --credentials gcp_credentials.json // - Get the keyset encryption AEAD for the key URI with KmsClient::GetAead. // StatusOr> LoadKeyset( absl::string_view serialized_encrypted_keyset, const crypto::tink::Aead& keyset_encryption_aead) { // Use a JSON reader to read the encrypted keyset. StatusOr> reader = crypto::tink::JsonKeysetReader::New(serialized_encrypted_keyset); if (!reader.ok()) return reader.status(); // Decrypt using the KMS, parse the keyset and retuns a handle to it. return KeysetHandle::Read(*std::move(reader), keyset_encryption_aead); } } // namespace tink_walkthrough // [END tink_walkthrough_load_encrypted_keyset] ================================================ FILE: cc/examples/walkthrough/load_encrypted_keyset.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXAMPLES_WALKTHROUGH_LOAD_ENCRYPTED_KEYSET_H_ #define TINK_EXAMPLES_WALKTHROUGH_LOAD_ENCRYPTED_KEYSET_H_ #include #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/keyset_handle.h" #include "tink/util/statusor.h" namespace tink_walkthrough { // Loads an encrypted JSON-serialized keyset `serialized_encrypted_keyset`. // The keyset is decrypted using `keyset_encryption_aead`. crypto::tink::util::StatusOr> LoadKeyset(absl::string_view serialized_encrypted_keyset, const crypto::tink::Aead& keyset_encryption_aead); } // namespace tink_walkthrough #endif // TINK_EXAMPLES_WALKTHROUGH_LOAD_ENCRYPTED_KEYSET_H_ ================================================ FILE: cc/examples/walkthrough/load_encrypted_keyset_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "walkthrough/load_encrypted_keyset.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/aead/aead_config.h" #include "tink/config/global_registry.h" #include "walkthrough/load_cleartext_keyset.h" #include "walkthrough/test_util.h" #include "tink/keyset_handle.h" #include "tink/kms_clients.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace tink_walkthrough { namespace { constexpr absl::string_view kSerializedMasterKeyKeyset = R"json({ "key": [ { "keyData": { "keyMaterialType": "SYMMETRIC", "typeUrl": "type.googleapis.com/google.crypto.tink.AesGcmKey", "value": "GiBWyUfGgYk3RTRhj/LIUzSudIWlyjCftCOypTr0jCNSLg==" }, "keyId": 294406504, "outputPrefixType": "TINK", "status": "ENABLED" } ], "primaryKeyId": 294406504 })json"; constexpr absl::string_view kSerializedKeysetToEncrypt = R"json({ "key": [ { "keyData": { "keyMaterialType": "SYMMETRIC", "typeUrl": "type.googleapis.com/google.crypto.tink.AesGcmKey", "value": "GhD+9l0RANZjzZEZ8PDp7LRW" }, "keyId": 1931667682, "outputPrefixType": "TINK", "status": "ENABLED" } ], "primaryKeyId": 1931667682 })json"; // Encryption of kSerializedKeysetToEncrypt using kSerializedMasterKeyKeyset. constexpr absl::string_view kEncryptedKeyset = R"json({ "encryptedKeyset": "ARGMSWi6YHyZ/Oqxl00XSq631a0q2UPmf+rCvCIAggSZrwCmxFF797MpY0dqgaXu1fz2eQ8zFNhlyTXv9kwg1kY6COpyhY/68zNBUkyKX4CharLYfpg1LgRl+6rMzIQa0XDHh7ZDmp1CevzecZIKnG83uDRHxxSv3h8c/Kc=" })json"; constexpr absl::string_view kFakeKmsKeyUri = "fake://some_key"; using ::crypto::tink::Aead; using ::crypto::tink::KeysetHandle; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; using ::testing::Test; class LoadKeysetTest : public Test { protected: void SetUp() override { ASSERT_THAT(crypto::tink::AeadConfig::Register(), IsOk()); } }; TEST_F(LoadKeysetTest, LoadKeysetFailsWhenInvalidKeyset) { auto fake_kms = absl::make_unique(kSerializedMasterKeyKeyset); StatusOr> keyset_encryption_aead = fake_kms->GetAead(kFakeKmsKeyUri); ASSERT_THAT(keyset_encryption_aead, IsOk()); StatusOr> expected_keyset = LoadKeyset("invalid", **keyset_encryption_aead); EXPECT_THAT(expected_keyset.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(LoadKeysetTest, LoadKeysetSucceeds) { auto fake_kms = absl::make_unique(kSerializedMasterKeyKeyset); StatusOr> keyset_encryption_aead = fake_kms->GetAead(kFakeKmsKeyUri); ASSERT_THAT(keyset_encryption_aead, IsOk()); StatusOr> handle = LoadKeyset(kEncryptedKeyset, **keyset_encryption_aead); ASSERT_THAT(handle, IsOk()); StatusOr> aead = (*handle)->GetPrimitive( crypto::tink::ConfigGlobalRegistry()); ASSERT_THAT(aead, IsOk()); StatusOr> expected_keyset = LoadKeyset(kSerializedKeysetToEncrypt); ASSERT_THAT(expected_keyset, IsOk()); StatusOr> expected_aead = (*expected_keyset) ->GetPrimitive( crypto::tink::ConfigGlobalRegistry()); ASSERT_THAT(expected_aead, IsOk()); std::string associated_data = "Some associated data"; std::string plaintext = "Some plaintext"; StatusOr ciphertext = (*aead)->Encrypt(plaintext, associated_data); ASSERT_THAT(ciphertext, IsOk()); EXPECT_THAT((*expected_aead)->Decrypt(*ciphertext, associated_data), IsOkAndHolds(plaintext)); } } // namespace } // namespace tink_walkthrough ================================================ FILE: cc/examples/walkthrough/obtain_and_use_a_primitive.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "walkthrough/obtain_and_use_a_primitive.h" // [START tink_walkthrough_obtain_and_use_a_primitive] #include #include #include #include #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/config/global_registry.h" #include "tink/keyset_handle.h" #include "tink/util/statusor.h" namespace tink_walkthrough { using ::crypto::tink::Aead; using ::crypto::tink::KeysetHandle; using ::crypto::tink::util::StatusOr; // AEAD encrypts `plaintext` with `associated_data` and the primary key in // `keyset_handle`. // // Prerequisites for this example: // - Register AEAD implementations of Tink. // - Create a keyset and get a handle to it. StatusOr AeadEncrypt(const KeysetHandle& keyset_handle, absl::string_view palintext, absl::string_view associated_data) { // To facilitate key rotation, GetPrimitive returns an Aead primitive that // "wraps" multiple Aead primitives in the keyset. When encrypting it uses the // primary key. StatusOr> aead = keyset_handle.GetPrimitive( crypto::tink::ConfigGlobalRegistry()); if (!aead.ok()) return aead.status(); return (*aead)->Encrypt(palintext, associated_data); } // AEAD decrypts `ciphertext` with `associated_data` and the correct key in // `keyset_handle`. // // Prerequisites for this example: // - Register AEAD implementations of Tink. // - Create a keyset and get a handle to it. StatusOr AeadDecrypt(const KeysetHandle& keyset_handle, absl::string_view ciphertext, absl::string_view associated_data) { // To facilitate key rotation, GetPrimitive returns an Aead primitive that // "wraps" multiple Aead primitives in the keyset. When decrypting it uses the // key that was used to encrypt using the key ID contained in the ciphertext. StatusOr> aead = keyset_handle.GetPrimitive( crypto::tink::ConfigGlobalRegistry()); if (!aead.ok()) return aead.status(); return (*aead)->Decrypt(ciphertext, associated_data); } } // namespace tink_walkthrough // [END tink_walkthrough_obtain_and_use_a_primitive] ================================================ FILE: cc/examples/walkthrough/obtain_and_use_a_primitive.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXAMPLES_WALKTHROUGH_OBTAIN_AND_USE_A_PRIMITIVE_H_ #define TINK_EXAMPLES_WALKTHROUGH_OBTAIN_AND_USE_A_PRIMITIVE_H_ #include #include #include "absl/strings/string_view.h" #include "tink/keyset_handle.h" #include "tink/util/statusor.h" namespace tink_walkthrough { // AEAD encrypts `plaintext` with `associated_data` and the primary key in // `keyset_handle`. crypto::tink::util::StatusOr AeadEncrypt( const crypto::tink::KeysetHandle& keyset_handle, absl::string_view palintext, absl::string_view associated_data); // AEAD decrypts `ciphertext` with `associated_data` and the correct key in // `keyset_handle`. crypto::tink::util::StatusOr AeadDecrypt( const crypto::tink::KeysetHandle& keyset_handle, absl::string_view ciphertext, absl::string_view associated_data); } // namespace tink_walkthrough #endif // TINK_EXAMPLES_WALKTHROUGH_OBTAIN_AND_USE_A_PRIMITIVE_H_ ================================================ FILE: cc/examples/walkthrough/obtain_and_use_a_primitive_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "walkthrough/obtain_and_use_a_primitive.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/string_view.h" #include "tink/aead/aead_config.h" #include "walkthrough/load_cleartext_keyset.h" #include "tink/keyset_handle.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace tink_walkthrough { namespace { constexpr absl::string_view kSerializedKeyset = R"string({ "key": [ { "keyData": { "keyMaterialType": "SYMMETRIC", "typeUrl": "type.googleapis.com/google.crypto.tink.AesGcmKey", "value": "GiBWyUfGgYk3RTRhj/LIUzSudIWlyjCftCOypTr0jCNSLg==" }, "keyId": 294406504, "outputPrefixType": "TINK", "status": "ENABLED" } ], "primaryKeyId": 294406504 })string"; using ::crypto::tink::KeysetHandle; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::util::StatusOr; TEST(LoadKeysetTest, EncryptDecrypt) { ASSERT_THAT(crypto::tink::AeadConfig::Register(), IsOk()); StatusOr> master_key_keyset = LoadKeyset(kSerializedKeyset); ASSERT_THAT(master_key_keyset, IsOk()); constexpr absl::string_view kPlaintext = "Some data"; constexpr absl::string_view kAssociatedData = "Some associated data"; StatusOr ciphertext = AeadEncrypt(**master_key_keyset, kPlaintext, kAssociatedData); ASSERT_THAT(ciphertext, IsOk()); EXPECT_THAT(AeadDecrypt(**master_key_keyset, *ciphertext, kAssociatedData), IsOkAndHolds(kPlaintext)); } } // namespace } // namespace tink_walkthrough ================================================ FILE: cc/examples/walkthrough/test_util.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "walkthrough/test_util.h" #include #include "absl/status/status.h" #include "absl/strings/match.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/config/global_registry.h" #include "walkthrough/load_cleartext_keyset.h" #include "tink/keyset_handle.h" #include "tink/util/status.h" namespace tink_walkthrough { using ::crypto::tink::Aead; using ::crypto::tink::KeysetHandle; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; bool FakeKmsClient::DoesSupport(absl::string_view key_uri) const { return absl::StartsWith(key_uri, "fake://"); } StatusOr> FakeKmsClient::GetAead( absl::string_view key_uri) const { StatusOr> master_key_keyset = LoadKeyset(serialized_master_key_keyset_); if (!master_key_keyset.ok()) return master_key_keyset.status(); return (*master_key_keyset) ->GetPrimitive(crypto::tink::ConfigGlobalRegistry()); } bool AlwaysFailingFakeKmsClient::DoesSupport(absl::string_view key_uri) const { return absl::StartsWith(key_uri, "failing://"); } StatusOr> AlwaysFailingFakeKmsClient::GetAead( absl::string_view key_uri) const { return Status(absl::StatusCode::kUnimplemented, "Unimplemented"); } } // namespace tink_walkthrough ================================================ FILE: cc/examples/walkthrough/test_util.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXAMPLES_WALKTHROUGH_TEST_UTIL_H_ #define TINK_EXAMPLES_WALKTHROUGH_TEST_UTIL_H_ #include #include #include #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/kms_client.h" #include "tink/util/statusor.h" namespace tink_walkthrough { // A fake KmsClient that for every key URI always returns an aead from // kSerializedMasterKeyKeyset. class FakeKmsClient : public crypto::tink::KmsClient { public: explicit FakeKmsClient(absl::string_view serialized_master_key_keyset) : serialized_master_key_keyset_(serialized_master_key_keyset) {} bool DoesSupport(absl::string_view key_uri) const override; crypto::tink::util::StatusOr> GetAead( absl::string_view key_uri) const override; private: std::string serialized_master_key_keyset_; }; // A fake KmsClient that always fails to return an AEAD. class AlwaysFailingFakeKmsClient : public crypto::tink::KmsClient { public: bool DoesSupport(absl::string_view key_uri) const override; crypto::tink::util::StatusOr> GetAead( absl::string_view key_uri) const override; }; } // namespace tink_walkthrough #endif // TINK_EXAMPLES_WALKTHROUGH_TEST_UTIL_H_ ================================================ FILE: cc/examples/walkthrough/write_cleartext_keyset.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "walkthrough/write_cleartext_keyset.h" // [START tink_walkthrough_write_keyset] #include #include #include #include "absl/status/status.h" #include "tink/cleartext_keyset_handle.h" #include "tink/json_keyset_writer.h" #include "tink/keyset_handle.h" #include "tink/util/status.h" namespace tink_walkthrough { using ::crypto::tink::JsonKeysetWriter; using ::crypto::tink::util::StatusOr; // Writes a `keyset` to `output_stream` as a plaintext JSON format. // // Warning: Storing keys in cleartext is not recommended. We recommend using a // Key Management Service to protect your keys. See // https://github.com/google/tink/blob/master/cc/examples/walkthrough/write_keyset.cc // for an example, and // https://developers.google.com/tink/key-management-overview for more info on // how to use a KMS with Tink. // // Prerequisites for this example: // - Create a keyset and obtain a KeysetHandle to it. crypto::tink::util::Status WriteKeyset( const crypto::tink::KeysetHandle& keyset, std::unique_ptr output_stream) { StatusOr> keyset_writer = JsonKeysetWriter::New(std::move(output_stream)); if (!keyset_writer.ok()) return keyset_writer.status(); return crypto::tink::CleartextKeysetHandle::Write((keyset_writer)->get(), keyset); } } // namespace tink_walkthrough // [END tink_walkthrough_write_keyset] ================================================ FILE: cc/examples/walkthrough/write_cleartext_keyset.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXAMPLES_WALKTHROUGH_WRITE_CLEARTEXT_KEYSET_H_ #define TINK_EXAMPLES_WALKTHROUGH_WRITE_CLEARTEXT_KEYSET_H_ #include #include #include "tink/keyset_handle.h" #include "tink/util/status.h" namespace tink_walkthrough { // Writes a `keyset` to `output_stream` as a plaintext JSON format. // // Warning: Storing keys in cleartext is not recommended. We recommend using a // Key Management Service to protect your keys. See // https://developers.google.com/tink/key-management-overview. crypto::tink::util::Status WriteKeyset( const crypto::tink::KeysetHandle& keyset, std::unique_ptr output_stream); } // namespace tink_walkthrough #endif // TINK_EXAMPLES_WALKTHROUGH_WRITE_CLEARTEXT_KEYSET_H_ ================================================ FILE: cc/examples/walkthrough/write_cleartext_keyset_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "walkthrough/write_cleartext_keyset.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/aead/aead_config.h" #include "tink/config/global_registry.h" #include "walkthrough/load_cleartext_keyset.h" #include "tink/keyset_handle.h" #include "tink/util/test_matchers.h" namespace tink_walkthrough { namespace { using ::crypto::tink::Aead; using ::crypto::tink::KeysetHandle; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::util::StatusOr; constexpr absl::string_view kSerializedKeyset = R"string({ "key": [ { "keyData": { "keyMaterialType": "SYMMETRIC", "typeUrl": "type.googleapis.com/google.crypto.tink.AesGcmKey", "value": "GiBWyUfGgYk3RTRhj/LIUzSudIWlyjCftCOypTr0jCNSLg==" }, "keyId": 294406504, "outputPrefixType": "TINK", "status": "ENABLED" } ], "primaryKeyId": 294406504 })string"; TEST(WriteCleartextKeysetTest, WriteKeysetSerializesCorrectly) { ASSERT_THAT(crypto::tink::AeadConfig::Register(), IsOk()); StatusOr> keyset = LoadKeyset(kSerializedKeyset); std::stringbuf buffer; auto output_stream = absl::make_unique(&buffer); ASSERT_THAT(WriteKeyset(**keyset, std::move(output_stream)), IsOk()); StatusOr> aead = (*keyset)->GetPrimitive( crypto::tink::ConfigGlobalRegistry()); // Make sure the encrypted keyset was written correctly by loading it and // trying to decrypt ciphertext. StatusOr> loaded_keyset = LoadKeyset(buffer.str()); ASSERT_THAT(loaded_keyset, IsOk()); StatusOr> loaded_keyset_aead = (*loaded_keyset) ->GetPrimitive( crypto::tink::ConfigGlobalRegistry()); ASSERT_THAT(loaded_keyset_aead, IsOk()); constexpr absl::string_view kPlaintext = "Some plaintext"; constexpr absl::string_view kAssociatedData = "Some associated data"; StatusOr ciphertext = (*aead)->Encrypt(kPlaintext, kAssociatedData); EXPECT_THAT((*loaded_keyset_aead)->Decrypt(*ciphertext, kAssociatedData), IsOkAndHolds(kPlaintext)); ciphertext = (*loaded_keyset_aead)->Encrypt(kPlaintext, kAssociatedData); EXPECT_THAT((*aead)->Decrypt(*ciphertext, kAssociatedData), IsOkAndHolds(kPlaintext)); } } // namespace } // namespace tink_walkthrough ================================================ FILE: cc/examples/walkthrough/write_keyset.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "walkthrough/write_keyset.h" // [START tink_walkthrough_write_keyset] #include #include #include #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/json_keyset_writer.h" #include "tink/keyset_handle.h" #include "tink/kms_client.h" #include "tink/kms_clients.h" #include "tink/util/status.h" namespace tink_walkthrough { using ::crypto::tink::JsonKeysetWriter; using ::crypto::tink::util::StatusOr; // Writes a `keyset` to `output_stream` in JSON format; the keyset is encrypted // with `keyset_encryption_aead`. // // Prerequisites for this example: // - Register AEAD implementations of Tink. // - Get the keyset encryption AEAD for a key URI with KmsClient::GetAead. // - Create a keyset and obtain a KeysetHandle to it. crypto::tink::util::Status WriteEncryptedKeyset( const crypto::tink::KeysetHandle& keyset, std::unique_ptr output_stream, const crypto::tink::Aead& keyset_encryption_aead) { // Create a writer that will write the keyset to output_stream as JSON. StatusOr> writer = JsonKeysetWriter::New(std::move(output_stream)); if (!writer.ok()) return writer.status(); return keyset.Write(writer->get(), keyset_encryption_aead); } } // namespace tink_walkthrough // [END tink_walkthrough_write_keyset] ================================================ FILE: cc/examples/walkthrough/write_keyset.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXAMPLES_WALKTHROUGH_WRITE_KEYSET_H_ #define TINK_EXAMPLES_WALKTHROUGH_WRITE_KEYSET_H_ #include #include #include "tink/aead.h" #include "tink/keyset_handle.h" #include "tink/util/status.h" namespace tink_walkthrough { // Writes a `keyset` to `output_stream` in JSON format; the keyset is encrypted // with `keyset_encryption_aead`. crypto::tink::util::Status WriteEncryptedKeyset( const crypto::tink::KeysetHandle& keyset, std::unique_ptr output_stream, const crypto::tink::Aead& keyset_encryption_aead); } // namespace tink_walkthrough #endif // TINK_EXAMPLES_WALKTHROUGH_WRITE_KEYSET_H_ ================================================ FILE: cc/examples/walkthrough/write_keyset_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "walkthrough/write_keyset.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/aead/aead_config.h" #include "tink/config/global_registry.h" #include "walkthrough/load_cleartext_keyset.h" #include "walkthrough/load_encrypted_keyset.h" #include "walkthrough/test_util.h" #include "tink/keyset_handle.h" #include "tink/kms_clients.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace tink_walkthrough { namespace { constexpr absl::string_view kSerializedMasterKeyKeyset = R"json({ "key": [ { "keyData": { "keyMaterialType": "SYMMETRIC", "typeUrl": "type.googleapis.com/google.crypto.tink.AesGcmKey", "value": "GiBWyUfGgYk3RTRhj/LIUzSudIWlyjCftCOypTr0jCNSLg==" }, "keyId": 294406504, "outputPrefixType": "TINK", "status": "ENABLED" } ], "primaryKeyId": 294406504 })json"; constexpr absl::string_view kSerializedKeysetToEncrypt = R"json({ "key": [ { "keyData": { "keyMaterialType": "SYMMETRIC", "typeUrl": "type.googleapis.com/google.crypto.tink.AesGcmKey", "value": "GhD+9l0RANZjzZEZ8PDp7LRW" }, "keyId": 1931667682, "outputPrefixType": "TINK", "status": "ENABLED" } ], "primaryKeyId": 1931667682 })json"; using ::crypto::tink::Aead; using ::crypto::tink::KeysetHandle; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; using ::testing::Not; class WriteKeysetTest : public testing::Test { protected: void SetUp() override { ASSERT_THAT(crypto::tink::AeadConfig::Register(), IsOk()); } }; TEST_F(WriteKeysetTest, WriteEncryptedKeysetFailsWithNullOutputStream) { auto fake_kms = absl::make_unique(kSerializedMasterKeyKeyset); StatusOr> keyset_encryption_aead = fake_kms->GetAead("fake://some_key"); ASSERT_THAT(keyset_encryption_aead, IsOk()); StatusOr> keyset_handle_to_encrypt = LoadKeyset(kSerializedKeysetToEncrypt); ASSERT_THAT(keyset_handle_to_encrypt, IsOk()); EXPECT_THAT( WriteEncryptedKeyset(**keyset_handle_to_encrypt, /*output_stream=*/nullptr, **keyset_encryption_aead), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(WriteKeysetTest, WriteEncryptedKeysetFailsWhenStreamFails) { auto fake_kms = absl::make_unique(kSerializedMasterKeyKeyset); StatusOr> keyset_encryption_aead = fake_kms->GetAead("fake://some_key"); ASSERT_THAT(keyset_encryption_aead, IsOk()); StatusOr> keyset_handle_to_encrypt = LoadKeyset(kSerializedKeysetToEncrypt); ASSERT_THAT(keyset_handle_to_encrypt, IsOk()); auto output_stream = absl::make_unique(nullptr); EXPECT_THAT( WriteEncryptedKeyset(**keyset_handle_to_encrypt, std::move(output_stream), **keyset_encryption_aead), Not(IsOk())); } TEST_F(WriteKeysetTest, WriteEncryptedKeysetWithValidInputs) { auto fake_kms = absl::make_unique(kSerializedMasterKeyKeyset); StatusOr> keyset_encryption_aead = fake_kms->GetAead("fake://some_key"); ASSERT_THAT(keyset_encryption_aead, IsOk()); StatusOr> keyset_handle_to_encrypt = LoadKeyset(kSerializedKeysetToEncrypt); ASSERT_THAT(keyset_handle_to_encrypt, IsOk()); std::stringbuf buffer; auto output_stream = absl::make_unique(&buffer); ASSERT_THAT( WriteEncryptedKeyset(**keyset_handle_to_encrypt, std::move(output_stream), **keyset_encryption_aead), IsOk()); StatusOr> expected_aead = (*keyset_handle_to_encrypt) ->GetPrimitive( crypto::tink::ConfigGlobalRegistry()); ASSERT_THAT(expected_aead, IsOk()); constexpr absl::string_view associated_data = "Some associated data"; constexpr absl::string_view plaintext = "Some plaintext"; StatusOr ciphertext = (*expected_aead)->Encrypt(plaintext, associated_data); ASSERT_THAT(ciphertext, IsOk()); // Make sure the encrypted keyset was written correctly by loading it and // trying to decrypt ciphertext. StatusOr> loaded_keyset = LoadKeyset(buffer.str(), **keyset_encryption_aead); ASSERT_THAT(loaded_keyset, IsOk()); StatusOr> loaded_keyset_aead = (*loaded_keyset) ->GetPrimitive( crypto::tink::ConfigGlobalRegistry()); ASSERT_THAT(loaded_keyset_aead, IsOk()); EXPECT_THAT((*loaded_keyset_aead)->Decrypt(*ciphertext, associated_data), IsOkAndHolds(plaintext)); } } // namespace } // namespace tink_walkthrough ================================================ FILE: cc/experimental/pqcrypto/README.md ================================================ This folder contains experimental implementations of post-quantum cryptographic primitives. ================================================ FILE: cc/experimental/pqcrypto/kem/BUILD.bazel ================================================ # package containing hybrid encryption implementations of PQC primitives package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "cecpq2_hybrid_config", srcs = ["cecpq2_hybrid_config.cc"], hdrs = ["cecpq2_hybrid_config.h"], include_prefix = "tink/experimental/pqcrypto/kem/", deps = [ ":cecpq2_aead_hkdf_private_key_manager", ":cecpq2_aead_hkdf_public_key_manager", "//:registry", "//aead:aead_config", "//config:tink_fips", "//hybrid:hybrid_decrypt_wrapper", "//hybrid:hybrid_encrypt_wrapper", "//util:status", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/memory", ], ) cc_library( name = "cecpq2_hybrid_key_templates", srcs = ["cecpq2_hybrid_key_templates.cc"], hdrs = ["cecpq2_hybrid_key_templates.h"], include_prefix = "tink/experimental/pqcrypto/kem/", deps = [ "//aead:aead_key_templates", "//daead:deterministic_aead_key_templates", "//experimental/pqcrypto/proto:cecpq2_aead_hkdf_cc_proto", "//proto:common_cc_proto", "//proto:tink_cc_proto", "@com_google_absl//absl/strings", ], ) cc_library( name = "cecpq2_aead_hkdf_dem_helper", srcs = ["cecpq2_aead_hkdf_dem_helper.cc"], hdrs = ["cecpq2_aead_hkdf_dem_helper.h"], include_prefix = "tink/experimental/pqcrypto/kem/", deps = [ "//:aead", "//:deterministic_aead", "//:registry", "//daead/subtle:aead_or_daead", "//proto:tink_cc_proto", "//util:errors", "//util:istream_input_stream", "//util:protobuf_helper", "//util:secret_data", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", ], ) cc_library( name = "cecpq2_aead_hkdf_private_key_manager", srcs = ["cecpq2_aead_hkdf_private_key_manager.cc"], hdrs = ["cecpq2_aead_hkdf_private_key_manager.h"], include_prefix = "tink/experimental/pqcrypto/kem/", deps = [ ":cecpq2_aead_hkdf_dem_helper", ":cecpq2_aead_hkdf_public_key_manager", "//:core/key_type_manager", "//:core/private_key_type_manager", "//:hybrid_decrypt", "//experimental/pqcrypto/kem/subtle:cecpq2_aead_hkdf_hybrid_decrypt", "//experimental/pqcrypto/kem/subtle:cecpq2_subtle_boringssl_util", "//experimental/pqcrypto/proto:cecpq2_aead_hkdf_cc_proto", "//proto:tink_cc_proto", "//subtle:random", "//subtle:subtle_util", "//util:enums", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "cecpq2_aead_hkdf_public_key_manager", srcs = ["cecpq2_aead_hkdf_public_key_manager.cc"], hdrs = ["cecpq2_aead_hkdf_public_key_manager.h"], include_prefix = "tink/experimental/pqcrypto/kem/", deps = [ ":cecpq2_aead_hkdf_dem_helper", "//:core/key_type_manager", "//:hybrid_encrypt", "//experimental/pqcrypto/kem/subtle:cecpq2_aead_hkdf_hybrid_encrypt", "//experimental/pqcrypto/proto:cecpq2_aead_hkdf_cc_proto", "//proto:common_cc_proto", "//proto:tink_cc_proto", "//util:enums", "//util:errors", "//util:protobuf_helper", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) # tests cc_test( name = "cecpq2_hybrid_config_test", size = "small", srcs = ["cecpq2_hybrid_config_test.cc"], deps = [ ":cecpq2_aead_hkdf_private_key_manager", ":cecpq2_aead_hkdf_public_key_manager", ":cecpq2_hybrid_config", ":cecpq2_hybrid_key_templates", "//:hybrid_decrypt", "//:hybrid_encrypt", "//:keyset_handle", "//:registry", "//config:tink_fips", "//util:status", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "cecpq2_hybrid_key_templates_test", size = "small", srcs = ["cecpq2_hybrid_key_templates_test.cc"], deps = [ ":cecpq2_aead_hkdf_private_key_manager", ":cecpq2_hybrid_config", ":cecpq2_hybrid_key_templates", "//experimental/pqcrypto/proto:cecpq2_aead_hkdf_cc_proto", "//util:test_matchers", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "cecpq2_aead_hkdf_dem_helper_test", size = "small", srcs = ["cecpq2_aead_hkdf_dem_helper_test.cc"], deps = [ ":cecpq2_aead_hkdf_dem_helper", "//:registry", "//aead:aes_gcm_key_manager", "//aead:xchacha20_poly1305_key_manager", "//config:tink_config", "//daead:aes_siv_key_manager", "//util:secret_data", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "cecpq2_aead_hkdf_private_key_manager_test", srcs = ["cecpq2_aead_hkdf_private_key_manager_test.cc"], deps = [ ":cecpq2_aead_hkdf_private_key_manager", ":cecpq2_aead_hkdf_public_key_manager", "//:hybrid_decrypt", "//:registry", "//aead:aead_key_templates", "//aead:aes_ctr_hmac_aead_key_manager", "//aead:aes_gcm_key_manager", "//experimental/pqcrypto/proto:cecpq2_aead_hkdf_cc_proto", "//proto:aes_eax_cc_proto", "//proto:common_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "cecpq2_aead_hkdf_public_key_manager_test", srcs = ["cecpq2_aead_hkdf_public_key_manager_test.cc"], deps = [ ":cecpq2_aead_hkdf_private_key_manager", ":cecpq2_aead_hkdf_public_key_manager", "//:hybrid_encrypt", "//:registry", "//aead:aead_key_templates", "//aead:aes_gcm_key_manager", "//experimental/pqcrypto/proto:cecpq2_aead_hkdf_cc_proto", "//proto:aes_eax_cc_proto", "//proto:common_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/experimental/pqcrypto/kem/cecpq2_aead_hkdf_dem_helper.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/kem/cecpq2_aead_hkdf_dem_helper.h" #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/daead/subtle/aead_or_daead.h" #include "tink/deterministic_aead.h" #include "tink/internal/registry_impl.h" #include "tink/registry.h" #include "tink/util/errors.h" #include "tink/util/istream_input_stream.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::subtle::AeadOrDaead; using ::google::crypto::tink::KeyTemplate; // Internal implementaton of the Cecpq2AeadHkdfDemHelper class, parametrized by // the Primitive used for data encapsulation (i.e Aead or DeterministicAead). template class Cecpq2AeadHkdfDemHelperImpl : public Cecpq2AeadHkdfDemHelper { public: explicit Cecpq2AeadHkdfDemHelperImpl( const google::crypto::tink::KeyTemplate& key_template) : key_template_(key_template) {} crypto::tink::util::StatusOr< std::unique_ptr> GetAeadOrDaead(const util::SecretData& seed) const override { if (seed.size() < 32) { return util::Status(absl::StatusCode::kInternal, "Seed length is smaller than 32 bytes " "and thus not post-quantum secure."); } std::string seed_str(util::SecretDataAsStringView(seed)); util::IstreamInputStream input_stream{ absl::make_unique(seed_str)}; auto key_or = internal::RegistryImpl::GlobalInstance().DeriveKey( key_template_, &input_stream); if (!key_or.ok()) return key_or.status(); auto key = std::move(key_or).value(); util::StatusOr> primitive_or = Registry::GetPrimitive(key); if (!primitive_or.ok()) return primitive_or.status(); return absl::make_unique(std::move(primitive_or.value())); } crypto::tink::util::StatusOr GetKeyMaterialSize() const override { absl::string_view dem_type_url = key_template_.type_url(); // For AES-SIV, two keys of 32 bytes each are needed if (dem_type_url == "type.googleapis.com/google.crypto.tink.AesSivKey") { return 64; } else if ( dem_type_url == "type.googleapis.com/google.crypto.tink.AesGcmKey" || dem_type_url == "type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key") { return 32; } else { return ToStatusF(absl::StatusCode::kInvalidArgument, "Unsupported DEM key type '%s'.", dem_type_url); } } private: const google::crypto::tink::KeyTemplate key_template_; }; } // namespace // static util::StatusOr> Cecpq2AeadHkdfDemHelper::New(const KeyTemplate& dem_key_template) { const std::string& dem_type_url = dem_key_template.type_url(); if (dem_type_url == "type.googleapis.com/google.crypto.tink.AesGcmKey" || dem_type_url == "type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key") { return { absl::make_unique>(dem_key_template)}; } else if (dem_type_url == "type.googleapis.com/google.crypto.tink.AesSivKey") { return {absl::make_unique>( dem_key_template)}; } return ToStatusF(absl::StatusCode::kInvalidArgument, "Unsupported DEM key type '%s'.", dem_type_url); } } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/kem/cecpq2_aead_hkdf_dem_helper.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_KEM_CECPQ2_AEAD_HKDF_DEM_HELPER_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_KEM_CECPQ2_AEAD_HKDF_DEM_HELPER_H_ #include #include #include "tink/aead.h" #include "tink/daead/subtle/aead_or_daead.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // A helper for DEM (data encapsulation mechanism) of CECPQ2-AEAD-HKDF. class Cecpq2AeadHkdfDemHelper { public: // Constructs a new helper for the specified DEM key template. static crypto::tink::util::StatusOr< std::unique_ptr> New(const google::crypto::tink::KeyTemplate& dem_key_template); virtual ~Cecpq2AeadHkdfDemHelper() = default; // Creates and returns a new AeadOrDaead object that uses // a 32-bytes or greater high-entropy seed to generate a key. virtual crypto::tink::util::StatusOr< std::unique_ptr> GetAeadOrDaead(const util::SecretData& seed) const = 0; // Return the key material size. virtual crypto::tink::util::StatusOr GetKeyMaterialSize() const = 0; }; } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_KEM_CECPQ2_AEAD_HKDF_DEM_HELPER_H_ ================================================ FILE: cc/experimental/pqcrypto/kem/cecpq2_aead_hkdf_dem_helper_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/kem/cecpq2_aead_hkdf_dem_helper.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/aead/xchacha20_poly1305_key_manager.h" #include "tink/config/tink_config.h" #include "tink/daead/aes_siv_key_manager.h" #include "tink/daead/subtle/aead_or_daead.h" #include "tink/registry.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_gcm.pb.h" #include "proto/aes_siv.pb.h" #include "proto/tink.pb.h" #include "proto/xchacha20_poly1305.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::subtle::AeadOrDaead; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::StatusOr; using ::testing::HasSubstr; // Checks whether Decrypt(Encrypt(message)) == message with the given dem. crypto::tink::util::Status EncryptThenDecrypt( const AeadOrDaead& dem, absl::string_view message, absl::string_view associated_data) { StatusOr encryption_or = dem.Encrypt(message, associated_data); if (!encryption_or.status().ok()) return encryption_or.status(); StatusOr decryption_or = dem.Decrypt(encryption_or.value(), associated_data); if (!decryption_or.status().ok()) return decryption_or.status(); if (decryption_or.value() != message) { return crypto::tink::util::Status(absl::StatusCode::kInternal, "Message/Decryption mismatch"); } return util::OkStatus(); } TEST(Cecpq2AeadHkdfDemHelperTest, InvalidKey) { google::crypto::tink::KeyTemplate dem_key_template; dem_key_template.set_type_url("some.type.url/that.is.not.supported"); auto result = Cecpq2AeadHkdfDemHelper::New(dem_key_template); EXPECT_THAT(Cecpq2AeadHkdfDemHelper::New(dem_key_template).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Unsupported DEM"))); } TEST(Cecpq2AeadHkdfDemHelperTest, DemHelperWithAesGcmKeyType) { google::crypto::tink::AesGcmKeyFormat key_format; key_format.set_key_size(32); auto key_manager(absl::make_unique()); std::string dem_key_type = key_manager->get_key_type(); ASSERT_THAT(Registry::RegisterKeyTypeManager(std::move(key_manager), true), IsOk()); google::crypto::tink::KeyTemplate dem_key_template; dem_key_template.set_type_url(dem_key_type); dem_key_template.set_value(key_format.SerializeAsString()); auto dem_helper_or = Cecpq2AeadHkdfDemHelper::New(dem_key_template); ASSERT_THAT(dem_helper_or, IsOk()); auto dem_helper = std::move(dem_helper_or.value()); util::SecretData seed_32_bytes = util::SecretDataFromStringView( test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f" "000102030405060708090a0b0c0d0e0f")); StatusOr> aead_or_daead_result_or = dem_helper->GetAeadOrDaead(seed_32_bytes); ASSERT_THAT(aead_or_daead_result_or, IsOk()); auto aead_or_daead = std::move(aead_or_daead_result_or.value()); EXPECT_THAT(EncryptThenDecrypt(*aead_or_daead, "test_plaintext", "test_ad"), IsOk()); } TEST(Cecpq2AeadHkdfDemHelperTest, DemHelperWithAesSivKeyType) { google::crypto::tink::AesSivKeyFormat key_format; key_format.set_key_size(64); auto key_manager(absl::make_unique()); std::string dem_key_type = key_manager->get_key_type(); ASSERT_THAT(Registry::RegisterKeyTypeManager(std::move(key_manager), true), IsOk()); google::crypto::tink::KeyTemplate dem_key_template; dem_key_template.set_type_url(dem_key_type); dem_key_template.set_value(key_format.SerializeAsString()); auto dem_helper_or = Cecpq2AeadHkdfDemHelper::New(dem_key_template); ASSERT_THAT(dem_helper_or, IsOk()); auto dem_helper = std::move(dem_helper_or.value()); util::SecretData seed_64_bytes = util::SecretDataFromStringView( test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f" "000102030405060708090a0b0c0d0e0f" "000102030405060708090a0b0c0d0e0f" "000102030405060708090a0b0c0d0e0f")); StatusOr> aead_or_daead_result_or = dem_helper->GetAeadOrDaead(seed_64_bytes); ASSERT_THAT(aead_or_daead_result_or, IsOk()); auto aead_or_daead = std::move(aead_or_daead_result_or.value()); EXPECT_THAT(EncryptThenDecrypt(*aead_or_daead, "test_plaintext", "test_ad"), IsOk()); } TEST(Cecpq2AeadHkdfDemHelperTest, DemHelperWithXchacha20Poly1305KeyType) { google::crypto::tink::XChaCha20Poly1305KeyFormat key_format; auto key_manager(absl::make_unique()); std::string dem_key_type = key_manager->get_key_type(); ASSERT_THAT(Registry::RegisterKeyTypeManager(std::move(key_manager), true), IsOk()); google::crypto::tink::KeyTemplate dem_key_template; dem_key_template.set_type_url(dem_key_type); dem_key_template.set_value(key_format.SerializeAsString()); auto dem_helper_or = Cecpq2AeadHkdfDemHelper::New(dem_key_template); ASSERT_THAT(dem_helper_or, IsOk()); auto dem_helper = std::move(dem_helper_or.value()); util::SecretData seed_32_bytes = util::SecretDataFromStringView( test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f" "000102030405060708090a0b0c0d0e0f")); StatusOr> aead_or_daead_result_or = dem_helper->GetAeadOrDaead(seed_32_bytes); ASSERT_THAT(aead_or_daead_result_or, IsOk()); auto aead_or_daead = std::move(aead_or_daead_result_or.value()); EXPECT_THAT(EncryptThenDecrypt(*aead_or_daead, "test_plaintext", "test_ad"), IsOk()); } TEST(Cecpq2AeadHkdfDemHelperTest, DemHelperKeyMaterialXChacha20Poly1305) { google::crypto::tink::XChaCha20Poly1305KeyFormat key_format; auto key_manager(absl::make_unique()); std::string dem_key_type = key_manager->get_key_type(); ASSERT_THAT(Registry::RegisterKeyTypeManager(std::move(key_manager), true), IsOk()); google::crypto::tink::KeyTemplate dem_key_template; dem_key_template.set_type_url(dem_key_type); dem_key_template.set_value(key_format.SerializeAsString()); auto dem_helper_or = Cecpq2AeadHkdfDemHelper::New(dem_key_template); ASSERT_THAT(dem_helper_or, IsOk()); auto dem_helper = std::move(dem_helper_or.value()); auto key_material_size_or = dem_helper->GetKeyMaterialSize(); ASSERT_THAT(key_material_size_or, IsOk()); ASSERT_EQ(key_material_size_or.value(), 32); } TEST(Cecpq2AeadHkdfDemHelperTest, DemHelperKeyMaterialAesGcm) { google::crypto::tink::AesGcmKeyFormat key_format; auto key_manager(absl::make_unique()); std::string dem_key_type = key_manager->get_key_type(); ASSERT_THAT(Registry::RegisterKeyTypeManager(std::move(key_manager), true), IsOk()); google::crypto::tink::KeyTemplate dem_key_template; dem_key_template.set_type_url(dem_key_type); dem_key_template.set_value(key_format.SerializeAsString()); auto dem_helper_or = Cecpq2AeadHkdfDemHelper::New(dem_key_template); ASSERT_THAT(dem_helper_or, IsOk()); auto dem_helper = std::move(dem_helper_or.value()); auto key_material_size_or = dem_helper->GetKeyMaterialSize(); ASSERT_THAT(key_material_size_or, IsOk()); ASSERT_EQ(key_material_size_or.value(), 32); } TEST(Cecpq2AeadHkdfDemHelperTest, DemHelperKeyMaterialAesSiv) { google::crypto::tink::AesSivKeyFormat key_format; auto key_manager(absl::make_unique()); std::string dem_key_type = key_manager->get_key_type(); ASSERT_THAT(Registry::RegisterKeyTypeManager(std::move(key_manager), true), IsOk()); google::crypto::tink::KeyTemplate dem_key_template; dem_key_template.set_type_url(dem_key_type); dem_key_template.set_value(key_format.SerializeAsString()); auto dem_helper_or = Cecpq2AeadHkdfDemHelper::New(dem_key_template); ASSERT_THAT(dem_helper_or, IsOk()); auto dem_helper = std::move(dem_helper_or.value()); auto key_material_size_or = dem_helper->GetKeyMaterialSize(); ASSERT_THAT(key_material_size_or, IsOk()); ASSERT_EQ(key_material_size_or.value(), 64); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/kem/cecpq2_aead_hkdf_private_key_manager.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/kem/cecpq2_aead_hkdf_private_key_manager.h" #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "openssl/hrss.h" #include "tink/experimental/pqcrypto/kem/cecpq2_aead_hkdf_public_key_manager.h" #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_aead_hkdf_hybrid_decrypt.h" #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_subtle_boringssl_util.h" #include "tink/hybrid_decrypt.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/random.h" #include "tink/subtle/subtle_util.h" #include "tink/util/enums.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/experimental/pqcrypto/cecpq2_aead_hkdf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using crypto::tink::util::Status; using crypto::tink::util::StatusOr; using google::crypto::tink::Cecpq2AeadHkdfKeyFormat; using google::crypto::tink::Cecpq2AeadHkdfPrivateKey; using google::crypto::tink::Cecpq2AeadHkdfPublicKey; Status Cecpq2AeadHkdfPrivateKeyManager::ValidateKeyFormat( const Cecpq2AeadHkdfKeyFormat& key_format) const { if (!key_format.has_params()) { return Status(absl::StatusCode::kInvalidArgument, "Missing params."); } return Cecpq2AeadHkdfPublicKeyManager().ValidateParams(key_format.params()); } StatusOr Cecpq2AeadHkdfPrivateKeyManager::CreateKey( const Cecpq2AeadHkdfKeyFormat& cecpq2_key_format) const { // Generate CECPQ2 key pair auto cecpq2_key_pair_or = pqc::GenerateCecpq2Keypair(subtle::EllipticCurveType::CURVE25519); if (!cecpq2_key_pair_or.ok()) return cecpq2_key_pair_or.status(); auto cecpq2_key_pair = std::move(cecpq2_key_pair_or.value()); // Build Cecpq2AeadHkdfPrivateKey Cecpq2AeadHkdfPrivateKey cecpq2_private_key; cecpq2_private_key.set_version(get_version()); cecpq2_private_key.set_x25519_private_key(std::string( util::SecretDataAsStringView(cecpq2_key_pair.x25519_key_pair.priv))); cecpq2_private_key.set_hrss_private_key_seed( std::string(util::SecretDataAsStringView( cecpq2_key_pair.hrss_key_pair.hrss_private_key_seed))); auto cecpq2_public_key = cecpq2_private_key.mutable_public_key(); cecpq2_public_key->set_version(get_version()); cecpq2_public_key->set_x25519_public_key_x( cecpq2_key_pair.x25519_key_pair.pub_x); cecpq2_public_key->set_x25519_public_key_y( cecpq2_key_pair.x25519_key_pair.pub_y); cecpq2_public_key->set_hrss_public_key_marshalled( cecpq2_key_pair.hrss_key_pair.hrss_public_key_marshaled); *(cecpq2_public_key->mutable_params()) = cecpq2_key_format.params(); return cecpq2_private_key; } StatusOr Cecpq2AeadHkdfPrivateKeyManager::GetPublicKey( const Cecpq2AeadHkdfPrivateKey& private_key) const { return private_key.public_key(); } Status Cecpq2AeadHkdfPrivateKeyManager::ValidateKey( const Cecpq2AeadHkdfPrivateKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; if (!key.has_public_key()) { return Status(absl::StatusCode::kInvalidArgument, "Missing public_key."); } return Cecpq2AeadHkdfPublicKeyManager().ValidateKey(key.public_key()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/kem/cecpq2_aead_hkdf_private_key_manager.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_KEM_CECPQ2_AEAD_HKDF_PRIVATE_KEY_MANAGER_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_KEM_CECPQ2_AEAD_HKDF_PRIVATE_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "openssl/hrss.h" #include "tink/core/key_type_manager.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/experimental/pqcrypto/kem/cecpq2_aead_hkdf_dem_helper.h" #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_aead_hkdf_hybrid_decrypt.h" #include "tink/hybrid_decrypt.h" #include "tink/util/enums.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/experimental/pqcrypto/cecpq2_aead_hkdf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class Cecpq2AeadHkdfPrivateKeyManager : public PrivateKeyTypeManager< google::crypto::tink::Cecpq2AeadHkdfPrivateKey, google::crypto::tink::Cecpq2AeadHkdfKeyFormat, google::crypto::tink::Cecpq2AeadHkdfPublicKey, List> { public: class HybridDecryptFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::Cecpq2AeadHkdfPrivateKey& cecpq2_private_key) const override { return Cecpq2AeadHkdfHybridDecrypt::New(cecpq2_private_key); } }; Cecpq2AeadHkdfPrivateKeyManager() : PrivateKeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::Cecpq2AeadHkdfPrivateKey& key) const override; crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::Cecpq2AeadHkdfKeyFormat& cecpq2_key_format) const override; crypto::tink::util::StatusOr CreateKey(const google::crypto::tink::Cecpq2AeadHkdfKeyFormat& key_format) const override; crypto::tink::util::StatusOr GetPublicKey(const google::crypto::tink::Cecpq2AeadHkdfPrivateKey& private_key) const override; private: const std::string key_type_ = absl::StrCat( "type.googleapis.com/", google::crypto::tink::Cecpq2AeadHkdfPrivateKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_KEM_CECPQ2_AEAD_HKDF_PRIVATE_KEY_MANAGER_H_ ================================================ FILE: cc/experimental/pqcrypto/kem/cecpq2_aead_hkdf_private_key_manager_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/kem/cecpq2_aead_hkdf_private_key_manager.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/aead/aead_key_templates.h" #include "tink/aead/aes_ctr_hmac_aead_key_manager.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/experimental/pqcrypto/kem/cecpq2_aead_hkdf_public_key_manager.h" #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_aead_hkdf_hybrid_encrypt.h" #include "tink/hybrid_decrypt.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_eax.pb.h" #include "proto/common.pb.h" #include "proto/experimental/pqcrypto/cecpq2_aead_hkdf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::Cecpq2AeadHkdfKeyFormat; using ::google::crypto::tink::Cecpq2AeadHkdfPrivateKey; using ::google::crypto::tink::Cecpq2AeadHkdfPublicKey; using ::google::crypto::tink::EcPointFormat; using ::google::crypto::tink::EllipticCurveType; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::testing::Eq; using ::testing::IsEmpty; using ::testing::Not; namespace { TEST(Cecpq2AeadHkdfPrivateKeyManagerTest, Basics) { EXPECT_THAT(Cecpq2AeadHkdfPrivateKeyManager().get_version(), Eq(0)); EXPECT_THAT(Cecpq2AeadHkdfPrivateKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PRIVATE)); EXPECT_THAT( Cecpq2AeadHkdfPrivateKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.Cecpq2AeadHkdfPrivateKey")); } TEST(Cecpq2AeadHkdfPrivateKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT( Cecpq2AeadHkdfPrivateKeyManager().ValidateKey(Cecpq2AeadHkdfPrivateKey()), StatusIs(absl::StatusCode::kInvalidArgument)); } Cecpq2AeadHkdfKeyFormat CreateValidKeyFormat() { Cecpq2AeadHkdfKeyFormat key_format; auto dem_params = key_format.mutable_params()->mutable_dem_params(); *(dem_params->mutable_aead_dem()) = AeadKeyTemplates::Aes256Gcm(); auto kem_params = key_format.mutable_params()->mutable_kem_params(); kem_params->set_curve_type(EllipticCurveType::CURVE25519); kem_params->set_hkdf_hash_type(HashType::SHA256); kem_params->set_hkdf_salt(""); kem_params->set_ec_point_format(EcPointFormat::COMPRESSED); return key_format; } TEST(Cecpq2AeadHkdfPrivateKeyManagerTest, ValidateKeyFormat) { EXPECT_THAT(Cecpq2AeadHkdfPrivateKeyManager().ValidateKeyFormat( CreateValidKeyFormat()), IsOk()); } TEST(Cecpq2AeadHkdfPrivateKeyManagerTest, ValidateKeyFormatNoPoint) { Cecpq2AeadHkdfKeyFormat key_format = CreateValidKeyFormat(); auto kem_params = key_format.mutable_params()->mutable_kem_params(); kem_params->set_ec_point_format(EcPointFormat::UNKNOWN_FORMAT); EXPECT_THAT(Cecpq2AeadHkdfPrivateKeyManager().ValidateKeyFormat(key_format), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(Cecpq2AeadHkdfPrivateKeyManagerTest, ValidateKeyFormatNoDem) { Cecpq2AeadHkdfKeyFormat key_format = CreateValidKeyFormat(); key_format.mutable_params()->mutable_dem_params()->clear_aead_dem(); EXPECT_THAT(Cecpq2AeadHkdfPrivateKeyManager().ValidateKeyFormat(key_format), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(Cecpq2AeadHkdfPrivateKeyManagerTest, ValidateKeyFormatNoKemCurve) { Cecpq2AeadHkdfKeyFormat key_format = CreateValidKeyFormat(); key_format.mutable_params()->mutable_kem_params()->set_curve_type( EllipticCurveType::UNKNOWN_CURVE); EXPECT_THAT(Cecpq2AeadHkdfPrivateKeyManager().ValidateKeyFormat(key_format), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(Cecpq2AeadHkdfPrivateKeyManagerTest, ValidateKeyFormatNoKemHash) { Cecpq2AeadHkdfKeyFormat key_format = CreateValidKeyFormat(); key_format.mutable_params()->mutable_kem_params()->set_hkdf_hash_type( HashType::UNKNOWN_HASH); EXPECT_THAT(Cecpq2AeadHkdfPrivateKeyManager().ValidateKeyFormat(key_format), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(Cecpq2AeadHkdfPrivateKeyManagerTest, CreateKey) { Cecpq2AeadHkdfKeyFormat key_format = CreateValidKeyFormat(); ASSERT_THAT(Cecpq2AeadHkdfPrivateKeyManager().CreateKey(key_format).status(), IsOk()); Cecpq2AeadHkdfPrivateKey key = Cecpq2AeadHkdfPrivateKeyManager().CreateKey(key_format).value(); EXPECT_THAT(key.public_key().params().kem_params().curve_type(), Eq(key_format.params().kem_params().curve_type())); EXPECT_THAT(key.public_key().params().kem_params().hkdf_hash_type(), Eq(key_format.params().kem_params().hkdf_hash_type())); EXPECT_THAT(key.public_key().params().dem_params().aead_dem().type_url(), Eq(key_format.params().dem_params().aead_dem().type_url())); EXPECT_THAT(key.public_key().params().dem_params().aead_dem().value(), Eq(key_format.params().dem_params().aead_dem().value())); EXPECT_THAT( key.public_key().params().dem_params().aead_dem().output_prefix_type(), Eq(key_format.params().dem_params().aead_dem().output_prefix_type())); // X25519 uses compressed points based on the "x" coordinate only. Therefore, // we only validate that the "x" coordinate is not empty here EXPECT_THAT(key.public_key().x25519_public_key_x(), Not(IsEmpty())); EXPECT_THAT(key.x25519_private_key(), Not(IsEmpty())); } Cecpq2AeadHkdfPrivateKey CreateValidKey() { return Cecpq2AeadHkdfPrivateKeyManager() .CreateKey(CreateValidKeyFormat()) .value(); } TEST(Cecpq2AeadHkdfPrivateKeyManagerTest, ValidateKeyEmpty) { EXPECT_THAT( Cecpq2AeadHkdfPrivateKeyManager().ValidateKey(Cecpq2AeadHkdfPrivateKey()), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(Cecpq2AeadHkdfPrivateKeyManagerTest, ValidateKey) { EXPECT_THAT(Cecpq2AeadHkdfPrivateKeyManager().ValidateKey(CreateValidKey()), IsOk()); } TEST(Cecpq2AeadHkdfPrivateKeyManagerTest, ValidateKeyWrongVersion) { Cecpq2AeadHkdfPrivateKey key = CreateValidKey(); key.set_version(1); EXPECT_THAT(Cecpq2AeadHkdfPrivateKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(Cecpq2AeadHkdfPrivateKeyManagerTest, ValidateKeyNoPoint) { Cecpq2AeadHkdfPrivateKey key = CreateValidKey(); key.mutable_public_key() ->mutable_params() ->mutable_kem_params() ->set_ec_point_format(EcPointFormat::UNKNOWN_FORMAT); EXPECT_THAT(Cecpq2AeadHkdfPrivateKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(Cecpq2AeadHkdfPrivateKeyManagerTest, ValidateKeyNoDem) { Cecpq2AeadHkdfPrivateKey key = CreateValidKey(); key.mutable_public_key() ->mutable_params() ->mutable_dem_params() ->clear_aead_dem(); EXPECT_THAT(Cecpq2AeadHkdfPrivateKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(Cecpq2AeadHkdfPrivateKeyManagerTest, ValidateKeyNoKemCurve) { Cecpq2AeadHkdfPrivateKey key = CreateValidKey(); key.mutable_public_key() ->mutable_params() ->mutable_kem_params() ->set_curve_type(EllipticCurveType::UNKNOWN_CURVE); EXPECT_THAT(Cecpq2AeadHkdfPrivateKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(Cecpq2AeadHkdfPrivateKeyManagerTest, ValidateKeyNoKemHash) { Cecpq2AeadHkdfPrivateKey key = CreateValidKey(); key.mutable_public_key() ->mutable_params() ->mutable_kem_params() ->set_hkdf_hash_type(HashType::UNKNOWN_HASH); EXPECT_THAT(Cecpq2AeadHkdfPrivateKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(Cecpq2AeadHkdfPrivateKeyManagerTest, GetPublicKey) { Cecpq2AeadHkdfPrivateKey key = CreateValidKey(); ASSERT_THAT(Cecpq2AeadHkdfPrivateKeyManager().GetPublicKey(key).status(), IsOk()); Cecpq2AeadHkdfPublicKey public_key = Cecpq2AeadHkdfPrivateKeyManager().GetPublicKey(key).value(); EXPECT_THAT(public_key.params().kem_params().curve_type(), Eq(key.public_key().params().kem_params().curve_type())); EXPECT_THAT(public_key.params().kem_params().hkdf_hash_type(), Eq(key.public_key().params().kem_params().hkdf_hash_type())); EXPECT_THAT(public_key.params().dem_params().aead_dem().type_url(), Eq(key.public_key().params().dem_params().aead_dem().type_url())); EXPECT_THAT(public_key.params().dem_params().aead_dem().value(), Eq(key.public_key().params().dem_params().aead_dem().value())); EXPECT_THAT(public_key.params().dem_params().aead_dem().output_prefix_type(), Eq(key.public_key() .params() .dem_params() .aead_dem() .output_prefix_type())); EXPECT_THAT(public_key.x25519_public_key_x(), Not(IsEmpty())); } TEST(Cecpq2AeadHkdfPrivateKeyManagerTest, Create) { ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); Cecpq2AeadHkdfPrivateKey private_key = CreateValidKey(); Cecpq2AeadHkdfPublicKey public_key = Cecpq2AeadHkdfPrivateKeyManager().GetPublicKey(private_key).value(); auto decrypt_or = Cecpq2AeadHkdfPrivateKeyManager().GetPrimitive( private_key); ASSERT_THAT(decrypt_or, IsOk()); auto encrypt_or = Cecpq2AeadHkdfHybridEncrypt::New(public_key); ASSERT_THAT(encrypt_or, IsOk()); std::string plaintext = "some text"; std::string context_info = "some aad"; auto ciphertext = encrypt_or.value()->Encrypt(plaintext, context_info); ASSERT_THAT(ciphertext, IsOk()); auto decryption = decrypt_or.value()->Decrypt(ciphertext.value(), context_info); ASSERT_THAT(decryption, IsOk()); ASSERT_EQ(decryption.value(), plaintext); } TEST(Cecpq2AeadHkdfPrivateKeyManagerTest, CreateDifferentKey) { ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); Cecpq2AeadHkdfPrivateKey private_key = CreateValidKey(); // Note: we create a new private key in the next line. Cecpq2AeadHkdfPublicKey public_key = Cecpq2AeadHkdfPrivateKeyManager().GetPublicKey(CreateValidKey()).value(); auto decrypt_or = Cecpq2AeadHkdfPrivateKeyManager().GetPrimitive( private_key); ASSERT_THAT(decrypt_or, IsOk()); auto encrypt_or = Cecpq2AeadHkdfHybridEncrypt::New(public_key); ASSERT_THAT(encrypt_or, IsOk()); std::string plaintext = "some text"; std::string context_info = "some aad"; auto ciphertext = encrypt_or.value()->Encrypt(plaintext, context_info); ASSERT_THAT(ciphertext, IsOk()); auto decryption = decrypt_or.value()->Decrypt(ciphertext.value(), context_info); ASSERT_THAT(decryption, Not(IsOk())); } TEST(Cecpq2AeadHkdfPrivateKeyManagerTest, ValidatePrivateKeyVersion) { Cecpq2AeadHkdfPrivateKey sk = CreateValidKey(); sk.set_version(1); EXPECT_THAT(Cecpq2AeadHkdfPrivateKeyManager().ValidateKey(sk), Not(IsOk())); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/kem/cecpq2_aead_hkdf_public_key_manager.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/kem/cecpq2_aead_hkdf_public_key_manager.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_aead_hkdf_hybrid_encrypt.h" #include "tink/hybrid_encrypt.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/common.pb.h" #include "proto/experimental/pqcrypto/cecpq2_aead_hkdf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using crypto::tink::util::Status; using google::crypto::tink::Cecpq2AeadHkdfParams; using google::crypto::tink::Cecpq2AeadHkdfPublicKey; using google::crypto::tink::EcPointFormat; using google::crypto::tink::EllipticCurveType; using google::crypto::tink::HashType; Status Cecpq2AeadHkdfPublicKeyManager::ValidateParams( const Cecpq2AeadHkdfParams& params) const { // Validate KEM params if (!params.has_kem_params()) { return Status(absl::StatusCode::kInvalidArgument, "Missing kem_params."); } if (params.kem_params().curve_type() == EllipticCurveType::UNKNOWN_CURVE || params.kem_params().curve_type() != EllipticCurveType::CURVE25519 || params.kem_params().hkdf_hash_type() == HashType::UNKNOWN_HASH) { return Status(absl::StatusCode::kInvalidArgument, "Invalid kem_params."); } // Validate DEM params if (!params.has_dem_params()) { return Status(absl::StatusCode::kInvalidArgument, "Missing dem_params."); } if (!params.dem_params().has_aead_dem()) { return Status(absl::StatusCode::kInvalidArgument, "dem_params has no aead_dem."); } // Validate EC point format if (params.kem_params().ec_point_format() == EcPointFormat::UNKNOWN_FORMAT) { return Status(absl::StatusCode::kInvalidArgument, "Unknown EC point format."); } return util::OkStatus(); } Status Cecpq2AeadHkdfPublicKeyManager::ValidateKey( const Cecpq2AeadHkdfPublicKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; if (!key.has_params()) { return Status(absl::StatusCode::kInvalidArgument, "Missing params."); } return ValidateParams(key.params()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/kem/cecpq2_aead_hkdf_public_key_manager.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_KEM_CECPQ2_AEAD_HKDF_PUBLIC_KEY_MANAGER_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_KEM_CECPQ2_AEAD_HKDF_PUBLIC_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/experimental/pqcrypto/kem/cecpq2_aead_hkdf_dem_helper.h" #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_aead_hkdf_hybrid_encrypt.h" #include "tink/hybrid_encrypt.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/experimental/pqcrypto/cecpq2_aead_hkdf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class Cecpq2AeadHkdfPublicKeyManager : public KeyTypeManager> { public: class HybridEncryptFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::Cecpq2AeadHkdfPublicKey& cecpq2_public_key) const override { return Cecpq2AeadHkdfHybridEncrypt::New(cecpq2_public_key); } }; Cecpq2AeadHkdfPublicKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PUBLIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::Cecpq2AeadHkdfPublicKey& key) const override; crypto::tink::util::Status ValidateParams( const google::crypto::tink::Cecpq2AeadHkdfParams& params) const; private: const std::string key_type_ = absl::StrCat( "type.googleapis.com/", google::crypto::tink::Cecpq2AeadHkdfPublicKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_KEM_CECPQ2_AEAD_HKDF_PUBLIC_KEY_MANAGER_H_ ================================================ FILE: cc/experimental/pqcrypto/kem/cecpq2_aead_hkdf_public_key_manager_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/kem/cecpq2_aead_hkdf_public_key_manager.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/aead/aead_key_templates.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/experimental/pqcrypto/kem/cecpq2_aead_hkdf_private_key_manager.h" #include "tink/hybrid_encrypt.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_eax.pb.h" #include "proto/common.pb.h" #include "proto/experimental/pqcrypto/cecpq2_aead_hkdf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::Cecpq2AeadHkdfKeyFormat; using ::google::crypto::tink::Cecpq2AeadHkdfParams; using ::google::crypto::tink::Cecpq2AeadHkdfPublicKey; using ::google::crypto::tink::EcPointFormat; using ::google::crypto::tink::EllipticCurveType; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::testing::Eq; using ::testing::Not; TEST(Cecpq2AeadHkdfPublicKeyManagerTest, Basics) { EXPECT_THAT(Cecpq2AeadHkdfPublicKeyManager().get_version(), Eq(0)); EXPECT_THAT(Cecpq2AeadHkdfPublicKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PUBLIC)); EXPECT_THAT( Cecpq2AeadHkdfPublicKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.Cecpq2AeadHkdfPublicKey")); } TEST(Cecpq2AeadHkdfPublicKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT( Cecpq2AeadHkdfPublicKeyManager().ValidateKey(Cecpq2AeadHkdfPublicKey()), StatusIs(absl::StatusCode::kInvalidArgument)); } Cecpq2AeadHkdfPublicKey CreatePublicKey() { Cecpq2AeadHkdfKeyFormat key_format; key_format.mutable_params()->mutable_kem_params()->set_ec_point_format( EcPointFormat::UNCOMPRESSED); auto dem_params = key_format.mutable_params()->mutable_dem_params(); *(dem_params->mutable_aead_dem()) = AeadKeyTemplates::Aes128Gcm(); auto kem_params = key_format.mutable_params()->mutable_kem_params(); kem_params->set_curve_type(EllipticCurveType::CURVE25519); kem_params->set_hkdf_hash_type(HashType::SHA256); kem_params->set_hkdf_salt(""); auto private_key_manager = Cecpq2AeadHkdfPrivateKeyManager(); return private_key_manager .GetPublicKey(private_key_manager.CreateKey(key_format).value()) .value(); } TEST(Cecpq2AeadHkdfPublicKeyManagerTest, ValidateParams) { EXPECT_THAT(Cecpq2AeadHkdfPublicKeyManager().ValidateParams( CreatePublicKey().params()), IsOk()); } TEST(Cecpq2AeadHkdfPublicKeyManagerTest, ValidateKeyNoPoint) { Cecpq2AeadHkdfParams params = CreatePublicKey().params(); params.mutable_kem_params()->set_ec_point_format( EcPointFormat::UNKNOWN_FORMAT); EXPECT_THAT(Cecpq2AeadHkdfPublicKeyManager().ValidateParams(params), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(Cecpq2AeadHkdfPublicKeyManagerTest, ValidateKeyNoDem) { Cecpq2AeadHkdfParams params = CreatePublicKey().params(); params.mutable_dem_params()->clear_aead_dem(); EXPECT_THAT(Cecpq2AeadHkdfPublicKeyManager().ValidateParams(params), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(Cecpq2AeadHkdfPublicKeyManagerTest, ValidateKeyNoKemCurve) { Cecpq2AeadHkdfParams params = CreatePublicKey().params(); params.mutable_kem_params()->set_curve_type(EllipticCurveType::UNKNOWN_CURVE); EXPECT_THAT(Cecpq2AeadHkdfPublicKeyManager().ValidateParams(params), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(Cecpq2AeadHkdfPublicKeyManagerTest, ValidateKeyNoKemHash) { Cecpq2AeadHkdfParams params = CreatePublicKey().params(); params.mutable_kem_params()->set_hkdf_hash_type(HashType::UNKNOWN_HASH); EXPECT_THAT(Cecpq2AeadHkdfPublicKeyManager().ValidateParams(params), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(Cecpq2AeadHkdfPublicKeyManagerTest, ValidateGeneratedKey) { EXPECT_THAT(Cecpq2AeadHkdfPublicKeyManager().ValidateKey(CreatePublicKey()), IsOk()); } TEST(Cecpq2AeadHkdfPublicKeyManagerTest, ValidatePublicKeyVersion) { Cecpq2AeadHkdfPublicKey pk = CreatePublicKey(); pk.set_version(1); EXPECT_THAT(Cecpq2AeadHkdfPublicKeyManager().ValidateKey(pk), Not(IsOk())); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/kem/cecpq2_hybrid_config.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/kem/cecpq2_hybrid_config.h" #include "absl/memory/memory.h" #include "tink/aead/aead_config.h" #include "tink/config/tink_fips.h" #include "tink/experimental/pqcrypto/kem/cecpq2_aead_hkdf_private_key_manager.h" #include "tink/experimental/pqcrypto/kem/cecpq2_aead_hkdf_public_key_manager.h" #include "tink/hybrid/hybrid_decrypt_wrapper.h" #include "tink/hybrid/hybrid_encrypt_wrapper.h" #include "tink/registry.h" #include "tink/util/status.h" namespace crypto { namespace tink { util::Status Cecpq2HybridConfigRegister() { auto status = AeadConfig::Register(); if (!status.ok()) return status; // Register primitive wrappers status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) return status; status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) return status; // Currently there are no CECPQ2 hybrid encryption key managers which only use // FIPS-validated implementations, therefore none will be registered in // FIPS only mode if (IsFipsModeEnabled()) { return util::OkStatus(); } // Register non-FIPS hybrid-hybrid key managers status = Registry::RegisterAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), true); if (!status.ok()) return status; return util::OkStatus(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/kem/cecpq2_hybrid_config.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_KEM_CECPQ2_HYBRID_CONFIG_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_KEM_CECPQ2_HYBRID_CONFIG_H_ #include "absl/base/macros.h" #include "tink/util/status.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Static methods and constants for registering with the Registry // all instances of CECPQ2 hybrid encryption key types supported in a particular // release of Tink, i.e. key types that correspond to primitives // HybridEncrypt and HybridDecrypt. // // To register the CECPQ2 hybrid encryption key types one can do: // // auto status = Cecpq2HybridConfigRegister(); // // Registers HybridEncrypt and HybridDecrypt primitive wrappers, and key // managers for all implementations of CECPQ2 HybridEncrypt and HybridDecrypt crypto::tink::util::Status Cecpq2HybridConfigRegister(); } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_KEM_CECPQ2_HYBRID_CONFIG_H_ ================================================ FILE: cc/experimental/pqcrypto/kem/cecpq2_hybrid_config_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/kem/cecpq2_hybrid_config.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/config/tink_fips.h" #include "tink/crypto_format.h" #include "tink/experimental/pqcrypto/kem/cecpq2_aead_hkdf_private_key_manager.h" #include "tink/experimental/pqcrypto/kem/cecpq2_aead_hkdf_public_key_manager.h" #include "tink/experimental/pqcrypto/kem/cecpq2_hybrid_key_templates.h" #include "tink/hybrid_decrypt.h" #include "tink/hybrid_encrypt.h" #include "tink/keyset_handle.h" #include "tink/primitive_set.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::DummyHybridDecrypt; using ::crypto::tink::test::DummyHybridEncrypt; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; class Cecpq2HybridConfigTest : public ::testing::Test { protected: void SetUp() override { Registry::Reset(); } }; TEST_F(Cecpq2HybridConfigTest, Basic) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT(Registry::get_key_manager( Cecpq2AeadHkdfPrivateKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT(Registry::get_key_manager( Cecpq2AeadHkdfPublicKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT(Cecpq2HybridConfigRegister(), IsOk()); EXPECT_THAT(Registry::get_key_manager( Cecpq2AeadHkdfPrivateKeyManager().get_key_type()) .status(), IsOk()); EXPECT_THAT(Registry::get_key_manager( Cecpq2AeadHkdfPublicKeyManager().get_key_type()) .status(), IsOk()); } // Tests that the HybridEncrypt wrapper has been properly registered and we // can wrap primitives TEST_F(Cecpq2HybridConfigTest, EncryptWrapperRegistered) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } ASSERT_TRUE(Cecpq2HybridConfigRegister().ok()); google::crypto::tink::KeysetInfo::KeyInfo key_info; key_info.set_status(google::crypto::tink::KeyStatusType::ENABLED); key_info.set_key_id(1234); key_info.set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); auto primitive_set = absl::make_unique>(); ASSERT_THAT( primitive_set->set_primary( primitive_set ->AddPrimitive(absl::make_unique("dummy"), key_info) .value()), IsOk()); auto wrapped = Registry::Wrap(std::move(primitive_set)); ASSERT_THAT(wrapped, IsOk()); auto encryption_result = wrapped.value()->Encrypt("secret", ""); ASSERT_THAT(encryption_result, IsOk()); std::string prefix = CryptoFormat::GetOutputPrefix(key_info).value(); EXPECT_EQ( encryption_result.value(), absl::StrCat(prefix, DummyHybridEncrypt("dummy").Encrypt("secret", "").value())); } // Tests that the HybridDecrypt wrapper has been properly registered and we // can wrap primitives TEST_F(Cecpq2HybridConfigTest, DecryptWrapperRegistered) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } ASSERT_TRUE(Cecpq2HybridConfigRegister().ok()); google::crypto::tink::KeysetInfo::KeyInfo key_info; key_info.set_status(google::crypto::tink::KeyStatusType::ENABLED); key_info.set_key_id(1234); key_info.set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); auto primitive_set = absl::make_unique>(); ASSERT_THAT( primitive_set->set_primary( primitive_set ->AddPrimitive(absl::make_unique("dummy"), key_info) .value()), IsOk()); auto wrapped = Registry::Wrap(std::move(primitive_set)); ASSERT_THAT(wrapped, IsOk()); std::string prefix = CryptoFormat::GetOutputPrefix(key_info).value(); std::string encryption = DummyHybridEncrypt("dummy").Encrypt("secret", "").value(); ASSERT_EQ( wrapped.value()->Decrypt(absl::StrCat(prefix, encryption), "").value(), "secret"); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/kem/cecpq2_hybrid_key_templates.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/kem/cecpq2_hybrid_key_templates.h" #include #include "absl/strings/string_view.h" #include "tink/aead/aead_key_templates.h" #include "tink/daead/deterministic_aead_key_templates.h" #include "proto/common.pb.h" #include "proto/experimental/pqcrypto/cecpq2_aead_hkdf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using google::crypto::tink::EcPointFormat; using google::crypto::tink::EllipticCurveType; using google::crypto::tink::HashType; using google::crypto::tink::KeyTemplate; using google::crypto::tink::OutputPrefixType; KeyTemplate* NewCecpq2AeadHkdfKeyTemplate(EllipticCurveType curve_type, HashType hkdf_hash_type, EcPointFormat ec_point_format, const KeyTemplate& dem_key_template, OutputPrefixType prefix_type, absl::string_view hkdf_salt) { KeyTemplate* key_template = new KeyTemplate; key_template->set_type_url( "type.googleapis.com/google.crypto.tink.Cecpq2AeadHkdfPrivateKey"); key_template->set_output_prefix_type(prefix_type); google::crypto::tink::Cecpq2AeadHkdfKeyFormat key_format; auto dem_params = key_format.mutable_params()->mutable_dem_params(); *(dem_params->mutable_aead_dem()) = dem_key_template; auto kem_params = key_format.mutable_params()->mutable_kem_params(); kem_params->set_curve_type(curve_type); kem_params->set_hkdf_hash_type(hkdf_hash_type); std::string hkdf_salt_str(hkdf_salt.data(), hkdf_salt.size()); kem_params->set_hkdf_salt(hkdf_salt_str); kem_params->set_ec_point_format(ec_point_format); key_format.SerializeToString(key_template->mutable_value()); return key_template; } } // anonymous namespace const KeyTemplate& Cecpq2HybridKeyTemplateX25519HkdfHmacSha256Aes256Gcm() { static const KeyTemplate* key_template = NewCecpq2AeadHkdfKeyTemplate( EllipticCurveType::CURVE25519, HashType::SHA256, EcPointFormat::COMPRESSED, AeadKeyTemplates::Aes256Gcm(), OutputPrefixType::TINK, /* hkdf_salt= */ ""); return *key_template; } const KeyTemplate& Cecpq2HybridKeyTemplateX25519HkdfHmacSha256XChaCha20Poly1305() { static const KeyTemplate* key_template = NewCecpq2AeadHkdfKeyTemplate( EllipticCurveType::CURVE25519, HashType::SHA256, EcPointFormat::COMPRESSED, AeadKeyTemplates::XChaCha20Poly1305(), OutputPrefixType::TINK, /* hkdf_salt= */ ""); return *key_template; } const google::crypto::tink::KeyTemplate& Cecpq2HybridKeyTemplateX25519HkdfHmacSha256DeterministicAesSiv() { static const KeyTemplate* key_template = NewCecpq2AeadHkdfKeyTemplate( EllipticCurveType::CURVE25519, HashType::SHA256, EcPointFormat::COMPRESSED, DeterministicAeadKeyTemplates::Aes256Siv(), OutputPrefixType::TINK, /* hkdf_salt= */ ""); return *key_template; } } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/kem/cecpq2_hybrid_key_templates.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_KEM_CECPQ2_HYBRID_KEY_TEMPLATES_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_KEM_CECPQ2_HYBRID_KEY_TEMPLATES_H_ #include "proto/tink.pb.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Pre-generated KeyTemplate for hybrid key types. One can use these templates // to generate a new KeysetHandle object with fresh keys. // To generate a new keyset that contains a single Cecpq2AeadHkdfPrivateKey, // one can do: // // auto status = Cecpq2HybridConfig::Register(); // if (!status.ok()) { /* fail with error */ } // auto handle_result = KeysetHandle::GenerateNew( // Cecpq2HybridKeyTemplates::Cecpq2P256HkdfHmacSha256Aes128Gcm()); // if (!handle_result.ok()) { /* fail with error */ } // auto keyset_handle = std::move(handle_result.value()); // Returns a KeyTemplate that generates new instances of // Cecpq2AeadHkdfPrivateKey with the following parameters: // - KEM: CECPQ2 // - DEM: AES256-GCM // - KDF: HKDF-HMAC-SHA256 with an empty salt // - EC Point Format: Compressed // - OutputPrefixType: TINK const google::crypto::tink::KeyTemplate& Cecpq2HybridKeyTemplateX25519HkdfHmacSha256Aes256Gcm(); // Returns a KeyTemplate that generates new instances of // Cecpq2AeadHkdfPrivateKey with the following parameters: // - KEM: CECPQ2 // - DEM: XChaCha20-Poly1305 with the following parameters: // * XChaCha20 key size: 32 bytes // * IV size: 24 bytes // - KDF: HKDF-HMAC-SHA256 with an empty salt // - EC Point Format: Compressed // - OutputPrefixType: TINK const google::crypto::tink::KeyTemplate& Cecpq2HybridKeyTemplateX25519HkdfHmacSha256XChaCha20Poly1305(); // Returns a KeyTemplate that generates new instances of // Cecpq2AeadHkdfPrivateKey with the following parameters: // - KEM: CECPQ2 // - DEM: AES256-SIV (Deterministic Aead) // - KDF: HKDF-HMAC-SHA256 with an empty salt // - EC Point Format: Compressed // - OutputPrefixType: TINK const google::crypto::tink::KeyTemplate& Cecpq2HybridKeyTemplateX25519HkdfHmacSha256DeterministicAesSiv(); } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_KEM_CECPQ2_HYBRID_KEY_TEMPLATES_H_ ================================================ FILE: cc/experimental/pqcrypto/kem/cecpq2_hybrid_key_templates_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/kem/cecpq2_hybrid_key_templates.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/experimental/pqcrypto/kem/cecpq2_aead_hkdf_private_key_manager.h" #include "tink/experimental/pqcrypto/kem/cecpq2_hybrid_config.h" #include "tink/util/test_matchers.h" #include "proto/experimental/pqcrypto/cecpq2_aead_hkdf.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using google::crypto::tink::KeyTemplate; using ::testing::Eq; class Cecpq2HybridKeyTemplatesTest : public ::testing::Test { protected: static void SetUpTestSuite() { // Initialize the registry, so that the templates can be tested ASSERT_THAT(Cecpq2HybridConfigRegister(), IsOk()); } }; TEST_F(Cecpq2HybridKeyTemplatesTest, ValidateX25519HkdfHmacSha256Aes256GcmKeyFormat) { const KeyTemplate& key_template = Cecpq2HybridKeyTemplateX25519HkdfHmacSha256Aes256Gcm(); google::crypto::tink::Cecpq2AeadHkdfKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(Cecpq2AeadHkdfPrivateKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST_F(Cecpq2HybridKeyTemplatesTest, ValidateX25519HkdfHmacSha256XChaCha20Poly1305KeyFormat) { const KeyTemplate& key_template = Cecpq2HybridKeyTemplateX25519HkdfHmacSha256XChaCha20Poly1305(); google::crypto::tink::Cecpq2AeadHkdfKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(Cecpq2AeadHkdfPrivateKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST_F(Cecpq2HybridKeyTemplatesTest, ValidateX25519HkdfHmacSha256DeterministicAesSivKeyFormat) { const KeyTemplate& key_template = Cecpq2HybridKeyTemplateX25519HkdfHmacSha256DeterministicAesSiv(); google::crypto::tink::Cecpq2AeadHkdfKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(Cecpq2AeadHkdfPrivateKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST_F(Cecpq2HybridKeyTemplatesTest, CheckX25519HkdfHmacSha256Aes256GcmTypeUrl) { const KeyTemplate& key_template = Cecpq2HybridKeyTemplateX25519HkdfHmacSha256Aes256Gcm(); EXPECT_THAT( key_template.type_url(), Eq("type.googleapis.com/google.crypto.tink.Cecpq2AeadHkdfPrivateKey")); google::crypto::tink::Cecpq2AeadHkdfKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(key_format.params().dem_params().aead_dem().type_url(), Eq("type.googleapis.com/google.crypto.tink.AesGcmKey")); } TEST_F(Cecpq2HybridKeyTemplatesTest, CheckX25519HkdfHmacSha256XChaCha20Poly1305TypeUrl) { const KeyTemplate& key_template = Cecpq2HybridKeyTemplateX25519HkdfHmacSha256XChaCha20Poly1305(); EXPECT_THAT( key_template.type_url(), Eq("type.googleapis.com/google.crypto.tink.Cecpq2AeadHkdfPrivateKey")); google::crypto::tink::Cecpq2AeadHkdfKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT( key_format.params().dem_params().aead_dem().type_url(), Eq("type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key")); } TEST_F(Cecpq2HybridKeyTemplatesTest, CheckX25519HkdfHmacSha256DeterministicAesSivTypeUrl) { const KeyTemplate& key_template = Cecpq2HybridKeyTemplateX25519HkdfHmacSha256DeterministicAesSiv(); EXPECT_THAT( key_template.type_url(), Eq("type.googleapis.com/google.crypto.tink.Cecpq2AeadHkdfPrivateKey")); google::crypto::tink::Cecpq2AeadHkdfKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(key_format.params().dem_params().aead_dem().type_url(), Eq("type.googleapis.com/google.crypto.tink.AesSivKey")); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/kem/subtle/BUILD.bazel ================================================ # package containing subtle implementations of PQC primitives package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "cecpq2_hkdf_sender_kem_boringssl", srcs = ["cecpq2_hkdf_sender_kem_boringssl.cc"], hdrs = ["cecpq2_hkdf_sender_kem_boringssl.h"], include_prefix = "tink/experimental/pqcrypto/kem/subtle", visibility = ["//visibility:public"], deps = [ "//internal:fips_utils", "//subtle", "//subtle:common_enums", "//subtle:hkdf", "//subtle:random", "//subtle:subtle_util", "//util:secret_data", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "cecpq2_hkdf_recipient_kem_boringssl", srcs = ["cecpq2_hkdf_recipient_kem_boringssl.cc"], hdrs = ["cecpq2_hkdf_recipient_kem_boringssl.h"], include_prefix = "tink/experimental/pqcrypto/kem/subtle", visibility = ["//visibility:public"], deps = [ ":cecpq2_hkdf_sender_kem_boringssl", "//internal:fips_utils", "//subtle", "//subtle:common_enums", "//subtle:hkdf", "//util:errors", "//util:secret_data", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "cecpq2_subtle_boringssl_util", srcs = ["cecpq2_subtle_boringssl_util.cc"], hdrs = ["cecpq2_subtle_boringssl_util.h"], include_prefix = "tink/experimental/pqcrypto/kem/subtle", visibility = ["//visibility:public"], deps = [ "//subtle", "//subtle:subtle_util", "//util:secret_data", "//util:statusor", "@boringssl//:crypto", ], ) cc_library( name = "cecpq2_aead_hkdf_hybrid_decrypt", srcs = ["cecpq2_aead_hkdf_hybrid_decrypt.cc"], hdrs = ["cecpq2_aead_hkdf_hybrid_decrypt.h"], include_prefix = "tink/experimental/pqcrypto/kem/subtle", visibility = ["//visibility:public"], deps = [ "//:hybrid_decrypt", "//experimental/pqcrypto/kem:cecpq2_aead_hkdf_dem_helper", "//experimental/pqcrypto/kem/subtle:cecpq2_hkdf_recipient_kem_boringssl", "//experimental/pqcrypto/kem/subtle:cecpq2_subtle_boringssl_util", "//experimental/pqcrypto/proto:cecpq2_aead_hkdf_cc_proto", "//subtle:ec_util", "//util:enums", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "cecpq2_aead_hkdf_hybrid_encrypt", srcs = ["cecpq2_aead_hkdf_hybrid_encrypt.cc"], hdrs = ["cecpq2_aead_hkdf_hybrid_encrypt.h"], include_prefix = "tink/experimental/pqcrypto/kem/subtle", visibility = ["//visibility:public"], deps = [ "//:aead", "//:hybrid_encrypt", "//experimental/pqcrypto/kem:cecpq2_aead_hkdf_dem_helper", "//experimental/pqcrypto/kem/subtle:cecpq2_hkdf_sender_kem_boringssl", "//experimental/pqcrypto/kem/subtle:cecpq2_subtle_boringssl_util", "//experimental/pqcrypto/proto:cecpq2_aead_hkdf_cc_proto", "//util:enums", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) #tests cc_test( name = "cecpq2_hkdf_sender_kem_boringssl_test", srcs = ["cecpq2_hkdf_sender_kem_boringssl_test.cc"], deps = [ ":cecpq2_hkdf_recipient_kem_boringssl", ":cecpq2_hkdf_sender_kem_boringssl", ":cecpq2_subtle_boringssl_util", "//config:tink_fips", "//subtle", "//subtle:common_enums", "//subtle:hkdf", "//subtle:random", "//subtle:subtle_util", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "cecpq2_hkdf_recipient_kem_boringssl_test", srcs = ["cecpq2_hkdf_recipient_kem_boringssl_test.cc"], deps = [ ":cecpq2_hkdf_recipient_kem_boringssl", "//config:tink_fips", "//subtle:random", "//util:test_matchers", "//util:test_util", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "cecpq2_subtle_boringssl_util_test", srcs = ["cecpq2_subtle_boringssl_util_test.cc"], deps = [ ":cecpq2_subtle_boringssl_util", "//subtle:random", "//subtle:subtle_util", "//util:secret_data", "//util:test_matchers", "//util:test_util", "@boringssl//:crypto", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "cecpq2_aead_hkdf_hybrid_encrypt_test", size = "small", srcs = ["cecpq2_aead_hkdf_hybrid_encrypt_test.cc"], copts = ["-Iexternal/gtest/include"], deps = [ ":cecpq2_aead_hkdf_hybrid_encrypt", "//:hybrid_encrypt", "//aead:aes_gcm_key_manager", "//experimental/pqcrypto/kem/subtle:cecpq2_subtle_boringssl_util", "//experimental/pqcrypto/kem/util:test_util", "//subtle:random", "//subtle:subtle_util", "//util:enums", "//util:statusor", "//util:test_matchers", "//util:test_util", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "cecpq2_aead_hkdf_hybrid_decrypt_test", size = "small", srcs = ["cecpq2_aead_hkdf_hybrid_decrypt_test.cc"], copts = ["-Iexternal/gtest/include"], deps = [ ":cecpq2_aead_hkdf_hybrid_decrypt", ":cecpq2_aead_hkdf_hybrid_encrypt", "//:hybrid_encrypt", "//aead:aes_ctr_hmac_aead_key_manager", "//aead:aes_gcm_key_manager", "//aead:xchacha20_poly1305_key_manager", "//config:tink_config", "//experimental/pqcrypto/kem/subtle:cecpq2_subtle_boringssl_util", "//experimental/pqcrypto/kem/util:test_util", "//experimental/pqcrypto/proto:cecpq2_aead_hkdf_cc_proto", "//subtle:random", "//subtle:subtle_util", "//util:enums", "//util:statusor", "//util:test_matchers", "//util:test_util", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/experimental/pqcrypto/kem/subtle/cecpq2_aead_hkdf_hybrid_decrypt.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_aead_hkdf_hybrid_decrypt.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "openssl/hrss.h" #include "openssl/nid.h" #include "tink/daead/subtle/aead_or_daead.h" #include "tink/experimental/pqcrypto/kem/cecpq2_aead_hkdf_dem_helper.h" #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_hkdf_recipient_kem_boringssl.h" #include "tink/hybrid_decrypt.h" #include "tink/internal/ec_util.h" #include "tink/util/enums.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/common.pb.h" namespace crypto { namespace tink { namespace { util::Status Validate( const google::crypto::tink::Cecpq2AeadHkdfPrivateKey& key) { if (key.hrss_private_key_seed().empty() || key.x25519_private_key().empty() || key.public_key().hrss_public_key_marshalled().empty() || key.public_key().x25519_public_key_x().empty()) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid Cecpq2AeadHkdfPrivateKeyInternal: missing KEM " "required fields."); } if (key.public_key().params().kem_params().curve_type() == google::crypto::tink::EllipticCurveType::CURVE25519) { if (!key.public_key().x25519_public_key_y().empty()) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid Cecpq2AeadHkdfPrivateKeyInternal: has KEM " "unexpected field."); } if (key.public_key().params().kem_params().ec_point_format() != google::crypto::tink::EcPointFormat::COMPRESSED) { return util::Status( absl::StatusCode::kInvalidArgument, "X25519 only supports compressed elliptic curve points."); } } return util::OkStatus(); } } // namespace // static util::StatusOr> Cecpq2AeadHkdfHybridDecrypt::New( const google::crypto::tink::Cecpq2AeadHkdfPrivateKey& private_key) { util::Status status = Validate(private_key); if (!status.ok()) return status; util::StatusOr> kem_result = subtle::Cecpq2HkdfRecipientKemBoringSsl::New( util::Enums::ProtoToSubtle( private_key.public_key().params().kem_params().curve_type()), util::SecretDataFromStringView(private_key.x25519_private_key()), util::SecretDataFromStringView(private_key.hrss_private_key_seed())); if (!kem_result.ok()) return kem_result.status(); util::StatusOr> dem_result = Cecpq2AeadHkdfDemHelper::New( private_key.public_key().params().dem_params().aead_dem()); if (!dem_result.ok()) return dem_result.status(); return {absl::WrapUnique(new Cecpq2AeadHkdfHybridDecrypt( private_key.public_key().params(), std::move(kem_result).value(), std::move(dem_result).value()))}; } util::StatusOr Cecpq2AeadHkdfHybridDecrypt::Decrypt( absl::string_view ciphertext, absl::string_view context_info) const { util::StatusOr cecpq2_header_point_encoding_size = internal::EcPointEncodingSizeInBytes( util::Enums::ProtoToSubtle( recipient_key_params_.kem_params().curve_type()), util::Enums::ProtoToSubtle( recipient_key_params_.kem_params().ec_point_format())); if (!cecpq2_header_point_encoding_size.ok()) { return cecpq2_header_point_encoding_size.status(); } int32_t cecpq2_header_size = *cecpq2_header_point_encoding_size + HRSS_CIPHERTEXT_BYTES; if (ciphertext.size() < cecpq2_header_size) { return util::Status(absl::StatusCode::kInvalidArgument, "ciphertext too short"); } // Get the key material size based on the DEM type_url. util::StatusOr key_material_size_or = dem_helper_->GetKeyMaterialSize(); if (!key_material_size_or.ok()) return key_material_size_or.status(); uint32_t key_material_size = key_material_size_or.value(); // Use KEM to get a symmetric key. util::StatusOr symmetric_key_result = recipient_kem_->GenerateKey( absl::string_view(ciphertext).substr(0, cecpq2_header_size), util::Enums::ProtoToSubtle( recipient_key_params_.kem_params().hkdf_hash_type()), recipient_key_params_.kem_params().hkdf_salt(), context_info, key_material_size, util::Enums::ProtoToSubtle( recipient_key_params_.kem_params().ec_point_format())); if (!symmetric_key_result.ok()) return symmetric_key_result.status(); util::SecretData symmetric_key = std::move(symmetric_key_result.value()); // Use the symmetric key to get an AEAD-primitive. util::StatusOr> aead_or_daead_result = dem_helper_->GetAeadOrDaead(symmetric_key); if (!aead_or_daead_result.ok()) return aead_or_daead_result.status(); std::unique_ptr aead_or_daead = std::move(aead_or_daead_result.value()); // Do the actual decryption using the AEAD-primitive. util::StatusOr decrypt_result = aead_or_daead->Decrypt( ciphertext.substr(cecpq2_header_size), ""); // empty aad if (!decrypt_result.ok()) return decrypt_result.status(); return decrypt_result.value(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/kem/subtle/cecpq2_aead_hkdf_hybrid_decrypt.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_KEM_SUBTLE_CECPQ2_AEAD_HKDF_HYBRID_DECRYPT_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_KEM_SUBTLE_CECPQ2_AEAD_HKDF_HYBRID_DECRYPT_H_ #include #include #include #include "absl/strings/string_view.h" #include "tink/experimental/pqcrypto/kem/cecpq2_aead_hkdf_dem_helper.h" #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_hkdf_recipient_kem_boringssl.h" #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_subtle_boringssl_util.h" #include "tink/hybrid_decrypt.h" #include "tink/util/statusor.h" #include "proto/experimental/pqcrypto/cecpq2_aead_hkdf.pb.h" namespace crypto { namespace tink { // CECPQ2 decryption with HKDF-KEM (key encapsulation mechanism) and // AEAD-DEM (data encapsulation mechanism) class Cecpq2AeadHkdfHybridDecrypt : public HybridDecrypt { public: // Returns an HybridDecrypt-primitive that uses the key material // given in 'recipient_key' static crypto::tink::util::StatusOr> New( const google::crypto::tink::Cecpq2AeadHkdfPrivateKey& private_key); crypto::tink::util::StatusOr Decrypt( absl::string_view ciphertext, absl::string_view context_info) const override; private: Cecpq2AeadHkdfHybridDecrypt( const google::crypto::tink::Cecpq2AeadHkdfParams& recipient_key_params, std::unique_ptr kem, std::unique_ptr dem_helper) : recipient_key_params_(recipient_key_params), recipient_kem_(std::move(kem)), dem_helper_(std::move(dem_helper)) {} google::crypto::tink::Cecpq2AeadHkdfParams recipient_key_params_; std::unique_ptr recipient_kem_; std::unique_ptr dem_helper_; }; } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_KEM_SUBTLE_CECPQ2_AEAD_HKDF_HYBRID_DECRYPT_H_ ================================================ FILE: cc/experimental/pqcrypto/kem/subtle/cecpq2_aead_hkdf_hybrid_decrypt_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_aead_hkdf_hybrid_decrypt.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/match.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "openssl/curve25519.h" #include "openssl/hrss.h" #include "tink/aead/aes_ctr_hmac_aead_key_manager.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/aead/xchacha20_poly1305_key_manager.h" #include "tink/config/tink_config.h" #include "tink/daead/aes_siv_key_manager.h" #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_aead_hkdf_hybrid_encrypt.h" #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_subtle_boringssl_util.h" #include "tink/experimental/pqcrypto/kem/util/test_util.h" #include "tink/hybrid_decrypt.h" #include "tink/hybrid_encrypt.h" #include "tink/registry.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/random.h" #include "tink/subtle/subtle_util.h" #include "tink/util/constants.h" #include "tink/util/enums.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_gcm.pb.h" #include "proto/aes_siv.pb.h" #include "proto/experimental/pqcrypto/cecpq2_aead_hkdf.pb.h" #include "proto/xchacha20_poly1305.pb.h" using crypto::tink::subtle::Random; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::HasSubstr; namespace crypto { namespace tink { namespace { class Cecpq2AeadHkdfHybridDecryptTest : public ::testing::Test { protected: struct CommonHybridKeyParams { subtle::EllipticCurveType ec_curve; subtle::EcPointFormat ec_point_format; subtle::HashType hash_type; }; std::vector GetCommonHybridKeyParamsList() { std::vector params_list; for (auto ec_curve : {subtle::EllipticCurveType::CURVE25519}) { for (auto ec_point_format : {subtle::EcPointFormat::COMPRESSED}) { for (auto hash_type : {subtle::HashType::SHA256, subtle::HashType::SHA512}) { CommonHybridKeyParams params; params.ec_curve = ec_curve; params.ec_point_format = ec_point_format; params.hash_type = hash_type; params_list.push_back(params); } } } return params_list; } util::Status CheckKeyValidity( const google::crypto::tink::Cecpq2AeadHkdfPrivateKey& cecpq2_key) { auto result = Cecpq2AeadHkdfHybridDecrypt::New(cecpq2_key); if (!result.ok()) return result.status(); std::unique_ptr hybrid_decrypt(std::move(result.value())); std::unique_ptr hybrid_encrypt(std::move( Cecpq2AeadHkdfHybridEncrypt::New(cecpq2_key.public_key()).value())); std::string context_info = "some context info"; for (uint32_t plaintext_size : {0, 1, 10, 100, 1000}) { // Use the primitive std::string plaintext = Random::GetRandomBytes(plaintext_size); auto ciphertext_or = hybrid_encrypt->Encrypt(plaintext, context_info); if (!ciphertext_or.ok()) return ciphertext_or.status(); auto ciphertext = ciphertext_or.value(); { // Regular decryption auto decrypt_result = hybrid_decrypt->Decrypt(ciphertext, context_info); if (!decrypt_result.ok()) { return decrypt_result.status(); } if (plaintext != decrypt_result.value()) return crypto::tink::util::Status( absl::StatusCode::kInternal, "Regular Encryption-Decryption failed:" "ciphertext differs from plaintext"); } { // Encryption and decryption with empty context info const absl::string_view empty_context_info; auto ciphertext = hybrid_encrypt->Encrypt(plaintext, empty_context_info).value(); auto decrypt_result = hybrid_decrypt->Decrypt(ciphertext, empty_context_info); if (!decrypt_result.ok()) { return decrypt_result.status(); } if (plaintext != decrypt_result.value()) return crypto::tink::util::Status( absl::StatusCode::kInternal, "Empty Context Info Encryption-Decryption failed:" "ciphertext differs from plaintext"); } { // Encryption and decryption w/ empty msg & context info const absl::string_view empty_plaintext; const absl::string_view empty_context_info; auto ciphertext = hybrid_encrypt->Encrypt(empty_plaintext, empty_context_info) .value(); auto decrypt_result = hybrid_decrypt->Decrypt(ciphertext, empty_context_info); if (!decrypt_result.ok()) { return decrypt_result.status(); } if (empty_plaintext != decrypt_result.value()) return crypto::tink::util::Status( absl::StatusCode::kInternal, "Empty Context Info and Message Encryption-Decryption failed:" "ciphertext differs from plaintext"); } { // Short bad ciphertext auto decrypt_result = hybrid_decrypt->Decrypt(Random::GetRandomBytes(16), context_info); if (decrypt_result.status().code() != absl::StatusCode::kInvalidArgument || !absl::StrContains(decrypt_result.status().message(), "ciphertext too short")) { return decrypt_result.status(); } } { // Long but still bad ciphertext auto decrypt_result = hybrid_decrypt->Decrypt(Random::GetRandomBytes(1198), context_info); if (decrypt_result.ok()) { return crypto::tink::util::Status(absl::StatusCode::kInternal, "Decrypted random ciphertext"); } } { // Bad context info auto decrypt_result = hybrid_decrypt->Decrypt(ciphertext, Random::GetRandomBytes(14)); if (decrypt_result.ok()) { return crypto::tink::util::Status( absl::StatusCode::kInternal, "Decrypted ciphertext with random context info"); } } } return util::OkStatus(); } }; google::crypto::tink::Cecpq2AeadHkdfPrivateKey CreateValidKey() { google::crypto::tink::Cecpq2AeadHkdfPrivateKey recipient_key; auto cecp2_key_pair = crypto::tink::pqc::GenerateCecpq2Keypair( subtle::EllipticCurveType::CURVE25519) .value(); recipient_key.set_x25519_private_key(std::string( util::SecretDataAsStringView(cecp2_key_pair.x25519_key_pair.priv))); recipient_key.set_hrss_private_key_seed( std::string(util::SecretDataAsStringView( cecp2_key_pair.hrss_key_pair.hrss_private_key_seed))); recipient_key.mutable_public_key()->set_x25519_public_key_x( cecp2_key_pair.x25519_key_pair.pub_x); recipient_key.mutable_public_key()->set_hrss_public_key_marshalled( cecp2_key_pair.hrss_key_pair.hrss_public_key_marshaled); recipient_key.mutable_public_key() ->mutable_params() ->mutable_kem_params() ->set_curve_type(google::crypto::tink::EllipticCurveType::CURVE25519); recipient_key.mutable_public_key() ->mutable_params() ->mutable_kem_params() ->set_ec_point_format(google::crypto::tink::EcPointFormat::COMPRESSED); recipient_key.mutable_public_key() ->mutable_params() ->mutable_kem_params() ->set_hkdf_hash_type(google::crypto::tink::HashType::SHA256); google::crypto::tink::AesGcmKeyFormat key_format; key_format.set_key_size(32); std::string dem_key_type = absl::StrCat( kTypeGoogleapisCom, google::crypto::tink::AesGcmKey().GetTypeName()); recipient_key.mutable_public_key() ->mutable_params() ->mutable_dem_params() ->mutable_aead_dem() ->set_type_url(dem_key_type); recipient_key.mutable_public_key() ->mutable_params() ->mutable_dem_params() ->mutable_aead_dem() ->set_value(key_format.SerializeAsString()); return recipient_key; } TEST_F(Cecpq2AeadHkdfHybridDecryptTest, ValidKey) { google::crypto::tink::Cecpq2AeadHkdfPrivateKey recipient_key = CreateValidKey(); EXPECT_THAT(Cecpq2AeadHkdfHybridDecrypt::New(recipient_key), IsOk()); } TEST_F(Cecpq2AeadHkdfHybridDecryptTest, InvalidKeyNoFieldsSet) { EXPECT_THAT(Cecpq2AeadHkdfHybridDecrypt::New( google::crypto::tink::Cecpq2AeadHkdfPrivateKey()) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("missing KEM required fields"))); } TEST_F(Cecpq2AeadHkdfHybridDecryptTest, InvalidKeyX25519PrivKeyFieldMissing) { google::crypto::tink::Cecpq2AeadHkdfPrivateKey recipient_key = CreateValidKey(); recipient_key.set_x25519_private_key(""); EXPECT_THAT(Cecpq2AeadHkdfHybridDecrypt::New(recipient_key).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("missing KEM required fields"))); } TEST_F(Cecpq2AeadHkdfHybridDecryptTest, InvalidKeyX25519PubKeyFieldMissing) { google::crypto::tink::Cecpq2AeadHkdfPrivateKey recipient_key = CreateValidKey(); recipient_key.mutable_public_key()->set_x25519_public_key_x(""); EXPECT_THAT(Cecpq2AeadHkdfHybridDecrypt::New(recipient_key).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("missing KEM required fields"))); } TEST_F(Cecpq2AeadHkdfHybridDecryptTest, InvalidKeyHrssPrivKeyFieldMissing) { google::crypto::tink::Cecpq2AeadHkdfPrivateKey recipient_key = CreateValidKey(); recipient_key.set_hrss_private_key_seed(""); EXPECT_THAT(Cecpq2AeadHkdfHybridDecrypt::New(recipient_key).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("missing KEM required fields"))); } TEST_F(Cecpq2AeadHkdfHybridDecryptTest, InvalidKeyHrssPubKeyFieldMissing) { google::crypto::tink::Cecpq2AeadHkdfPrivateKey recipient_key = CreateValidKey(); recipient_key.mutable_public_key()->set_hrss_public_key_marshalled(""); EXPECT_THAT(Cecpq2AeadHkdfHybridDecrypt::New(recipient_key).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("missing KEM required fields"))); } TEST_F(Cecpq2AeadHkdfHybridDecryptTest, InvalidKeyWrongEcType) { google::crypto::tink::Cecpq2AeadHkdfPrivateKey recipient_key = CreateValidKey(); recipient_key.mutable_public_key() ->mutable_params() ->mutable_kem_params() ->set_curve_type(google::crypto::tink::EllipticCurveType::NIST_P256); auto result(Cecpq2AeadHkdfHybridDecrypt::New(recipient_key)); EXPECT_THAT(result.status(), StatusIs(absl::StatusCode::kUnimplemented, HasSubstr("Unsupported elliptic curve"))); } TEST_F(Cecpq2AeadHkdfHybridDecryptTest, InvalidKeyUnsupportedDem) { google::crypto::tink::Cecpq2AeadHkdfPrivateKey recipient_key = CreateValidKey(); recipient_key.mutable_public_key() ->mutable_params() ->mutable_kem_params() ->set_curve_type(google::crypto::tink::EllipticCurveType::CURVE25519); recipient_key.mutable_public_key() ->mutable_params() ->mutable_kem_params() ->set_hkdf_hash_type(google::crypto::tink::HashType::SHA256); recipient_key.mutable_public_key() ->mutable_params() ->mutable_dem_params() ->mutable_aead_dem() ->set_type_url("some.type.url/that.is.not.supported"); auto result(Cecpq2AeadHkdfHybridDecrypt::New(recipient_key)); EXPECT_THAT(result.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Unsupported DEM"))); } TEST_F(Cecpq2AeadHkdfHybridDecryptTest, AesGcmHybridDecryption) { // Register DEM key manager ASSERT_TRUE(Registry::RegisterKeyTypeManager( absl::make_unique(), true) .ok()); // Generate and test many keys with various parameters for (auto key_params : GetCommonHybridKeyParamsList()) { for (uint32_t aes_gcm_key_size : {16, 32}) { SCOPED_TRACE(absl::StrCat(key_params.ec_curve, ":", key_params.ec_point_format, ":", key_params.hash_type, ":", aes_gcm_key_size)); auto cecpq2_key_pair_or_status = pqc::GenerateCecpq2Keypair(key_params.ec_curve); auto cecpq2_key_pair = std::move(cecpq2_key_pair_or_status.value()); google::crypto::tink::Cecpq2AeadHkdfPrivateKey cecpq2_key; cecpq2_key.set_hrss_private_key_seed( std::string(util::SecretDataAsStringView( cecpq2_key_pair.hrss_key_pair.hrss_private_key_seed))); cecpq2_key.set_x25519_private_key(std::string( util::SecretDataAsStringView(cecpq2_key_pair.x25519_key_pair.priv))); cecpq2_key.mutable_public_key()->set_hrss_public_key_marshalled( cecpq2_key_pair.hrss_key_pair.hrss_public_key_marshaled); cecpq2_key.mutable_public_key()->set_x25519_public_key_x( cecpq2_key_pair.x25519_key_pair.pub_x); cecpq2_key.mutable_public_key() ->mutable_params() ->mutable_kem_params() ->set_curve_type(util::Enums::SubtleToProto(key_params.ec_curve)); cecpq2_key.mutable_public_key() ->mutable_params() ->mutable_kem_params() ->set_ec_point_format( util::Enums::SubtleToProto(key_params.ec_point_format)); cecpq2_key.mutable_public_key() ->mutable_params() ->mutable_kem_params() ->set_hkdf_hash_type( util::Enums::SubtleToProto(key_params.hash_type)); google::crypto::tink::AesGcmKeyFormat key_format; key_format.set_key_size(aes_gcm_key_size); std::unique_ptr key_manager(new AesGcmKeyManager()); std::string dem_key_type = key_manager->get_key_type(); cecpq2_key.mutable_public_key() ->mutable_params() ->mutable_dem_params() ->mutable_aead_dem() ->set_type_url(dem_key_type); cecpq2_key.mutable_public_key() ->mutable_params() ->mutable_dem_params() ->mutable_aead_dem() ->set_value(key_format.SerializeAsString()); EXPECT_THAT(CheckKeyValidity(cecpq2_key), IsOk()); } } } TEST_F(Cecpq2AeadHkdfHybridDecryptTest, XChaCha20Poly1305HybridDecryption) { // Register DEM key manager ASSERT_TRUE(Registry::RegisterKeyTypeManager( absl::make_unique(), true) .ok()); // Generate and test many keys with various parameters for (auto key_params : GetCommonHybridKeyParamsList()) { SCOPED_TRACE(absl::StrCat(key_params.ec_curve, ":", key_params.ec_point_format, ":", key_params.hash_type)); auto cecpq2_key_pair_or_status = pqc::GenerateCecpq2Keypair(key_params.ec_curve); auto cecpq2_key_pair = std::move(cecpq2_key_pair_or_status.value()); google::crypto::tink::Cecpq2AeadHkdfPrivateKey cecpq2_key; cecpq2_key.set_hrss_private_key_seed( std::string(util::SecretDataAsStringView( cecpq2_key_pair.hrss_key_pair.hrss_private_key_seed))); cecpq2_key.set_x25519_private_key(std::string( util::SecretDataAsStringView(cecpq2_key_pair.x25519_key_pair.priv))); cecpq2_key.mutable_public_key()->set_hrss_public_key_marshalled( cecpq2_key_pair.hrss_key_pair.hrss_public_key_marshaled); cecpq2_key.mutable_public_key()->set_x25519_public_key_x( cecpq2_key_pair.x25519_key_pair.pub_x); cecpq2_key.mutable_public_key() ->mutable_params() ->mutable_kem_params() ->set_curve_type(util::Enums::SubtleToProto(key_params.ec_curve)); cecpq2_key.mutable_public_key() ->mutable_params() ->mutable_kem_params() ->set_ec_point_format( util::Enums::SubtleToProto(key_params.ec_point_format)); cecpq2_key.mutable_public_key() ->mutable_params() ->mutable_kem_params() ->set_hkdf_hash_type(util::Enums::SubtleToProto(key_params.hash_type)); google::crypto::tink::XChaCha20Poly1305KeyFormat key_format; std::unique_ptr key_manager( new XChaCha20Poly1305KeyManager()); std::string dem_key_type = key_manager->get_key_type(); cecpq2_key.mutable_public_key() ->mutable_params() ->mutable_dem_params() ->mutable_aead_dem() ->set_type_url(dem_key_type); cecpq2_key.mutable_public_key() ->mutable_params() ->mutable_dem_params() ->mutable_aead_dem() ->set_value(key_format.SerializeAsString()); EXPECT_THAT(CheckKeyValidity(cecpq2_key), IsOk()); } } TEST_F(Cecpq2AeadHkdfHybridDecryptTest, AesSivHybridDecryption) { // Register DEM key manager ASSERT_TRUE(Registry::RegisterKeyTypeManager( absl::make_unique(), true) .ok()); // Generate and test many keys with various parameters for (auto key_params : GetCommonHybridKeyParamsList()) { auto cecpq2_key_pair_or_status = pqc::GenerateCecpq2Keypair(key_params.ec_curve); auto cecpq2_key_pair = std::move(cecpq2_key_pair_or_status.value()); google::crypto::tink::Cecpq2AeadHkdfPrivateKey cecpq2_key; cecpq2_key.set_hrss_private_key_seed( std::string(util::SecretDataAsStringView( cecpq2_key_pair.hrss_key_pair.hrss_private_key_seed))); cecpq2_key.set_x25519_private_key(std::string( util::SecretDataAsStringView(cecpq2_key_pair.x25519_key_pair.priv))); cecpq2_key.mutable_public_key()->set_hrss_public_key_marshalled( cecpq2_key_pair.hrss_key_pair.hrss_public_key_marshaled); cecpq2_key.mutable_public_key()->set_x25519_public_key_x( cecpq2_key_pair.x25519_key_pair.pub_x); cecpq2_key.mutable_public_key() ->mutable_params() ->mutable_kem_params() ->set_curve_type(util::Enums::SubtleToProto(key_params.ec_curve)); cecpq2_key.mutable_public_key() ->mutable_params() ->mutable_kem_params() ->set_ec_point_format( util::Enums::SubtleToProto(key_params.ec_point_format)); cecpq2_key.mutable_public_key() ->mutable_params() ->mutable_kem_params() ->set_hkdf_hash_type(util::Enums::SubtleToProto(key_params.hash_type)); google::crypto::tink::AesSivKeyFormat key_format; key_format.set_key_size(64); std::unique_ptr key_manager(new AesSivKeyManager()); std::string dem_key_type = key_manager->get_key_type(); cecpq2_key.mutable_public_key() ->mutable_params() ->mutable_dem_params() ->mutable_aead_dem() ->set_type_url(dem_key_type); cecpq2_key.mutable_public_key() ->mutable_params() ->mutable_dem_params() ->mutable_aead_dem() ->set_value(key_format.SerializeAsString()); EXPECT_THAT(CheckKeyValidity(cecpq2_key), IsOk()); } } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/kem/subtle/cecpq2_aead_hkdf_hybrid_encrypt.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_aead_hkdf_hybrid_encrypt.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/daead/subtle/aead_or_daead.h" #include "tink/experimental/pqcrypto/kem/cecpq2_aead_hkdf_dem_helper.h" #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_hkdf_sender_kem_boringssl.h" #include "tink/hybrid_encrypt.h" #include "tink/util/enums.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/common.pb.h" namespace crypto { namespace tink { namespace { util::Status Validate( const google::crypto::tink::Cecpq2AeadHkdfPublicKey& key) { if (key.x25519_public_key_x().empty() || key.hrss_public_key_marshalled().empty()) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid Cecpq2AeadHkdfPublicKeyInternal: missing KEM " "required fields."); } if (key.params().kem_params().curve_type() == google::crypto::tink::EllipticCurveType::CURVE25519 && !key.x25519_public_key_y().empty()) { return util::Status( absl::StatusCode::kInvalidArgument, "Invalid Cecpq2AeadHkdfPublicKeyInternal: has KEM unexpected field."); } return util::OkStatus(); } } // namespace // static util::StatusOr> Cecpq2AeadHkdfHybridEncrypt::New( const google::crypto::tink::Cecpq2AeadHkdfPublicKey& recipient_key) { util::Status status = Validate(recipient_key); if (!status.ok()) return status; util::StatusOr> kem_result = subtle::Cecpq2HkdfSenderKemBoringSsl::New( util::Enums::ProtoToSubtle( recipient_key.params().kem_params().curve_type()), recipient_key.x25519_public_key_x(), recipient_key.x25519_public_key_y(), recipient_key.hrss_public_key_marshalled()); if (!kem_result.ok()) return kem_result.status(); util::StatusOr> dem_result = Cecpq2AeadHkdfDemHelper::New( recipient_key.params().dem_params().aead_dem()); if (!dem_result.ok()) return dem_result.status(); return {absl::WrapUnique(new Cecpq2AeadHkdfHybridEncrypt( recipient_key, std::move(kem_result).value(), std::move(dem_result).value()))}; } util::StatusOr Cecpq2AeadHkdfHybridEncrypt::Encrypt( absl::string_view plaintext, absl::string_view context_info) const { // Get the key material size based on the DEM type_url. util::StatusOr key_material_size_or = dem_helper_->GetKeyMaterialSize(); if (!key_material_size_or.ok()) return key_material_size_or.status(); uint32_t key_material_size = key_material_size_or.value(); // Use KEM to get a symmetric key util::StatusOr< std::unique_ptr> kem_key_result = sender_kem_->GenerateKey( util::Enums::ProtoToSubtle( recipient_key_.params().kem_params().hkdf_hash_type()), recipient_key_.params().kem_params().hkdf_salt(), context_info, key_material_size, util::Enums::ProtoToSubtle( recipient_key_.params().kem_params().ec_point_format())); if (!kem_key_result.ok()) return kem_key_result.status(); std::unique_ptr kem_key = std::move(kem_key_result.value()); // Use the symmetric key to get an AEAD-primitive util::StatusOr> aead_or_daead_result = dem_helper_->GetAeadOrDaead(kem_key->get_symmetric_key()); if (!aead_or_daead_result.ok()) return aead_or_daead_result.status(); std::unique_ptr aead_or_daead = std::move(aead_or_daead_result.value()); // Do the actual encryption using the AEAD-primitive util::StatusOr encrypt_result = aead_or_daead->Encrypt(plaintext, ""); // empty aad if (!encrypt_result.ok()) return encrypt_result.status(); // Prepend AEAD-ciphertext with a KEM component std::string ciphertext = absl::StrCat(kem_key->get_kem_bytes(), encrypt_result.value()); return ciphertext; } } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/kem/subtle/cecpq2_aead_hkdf_hybrid_encrypt.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_KEM_SUBTLE_CECPQ2_AEAD_HKDF_HYBRID_ENCRYPT_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_KEM_SUBTLE_CECPQ2_AEAD_HKDF_HYBRID_ENCRYPT_H_ #include #include #include #include "absl/strings/string_view.h" #include "tink/experimental/pqcrypto/kem/cecpq2_aead_hkdf_dem_helper.h" #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_hkdf_sender_kem_boringssl.h" #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_subtle_boringssl_util.h" #include "tink/hybrid_encrypt.h" #include "tink/util/statusor.h" #include "proto/experimental/pqcrypto/cecpq2_aead_hkdf.pb.h" namespace crypto { namespace tink { // CECPQ2 encryption with HKDF-KEM (key encapsulation mechanism) and // AEAD-DEM (data encapsulation mechanism) class Cecpq2AeadHkdfHybridEncrypt : public HybridEncrypt { public: // Returns an HybridEncrypt-primitive that uses the key material // given in 'recipient_key' static crypto::tink::util::StatusOr> New( const google::crypto::tink::Cecpq2AeadHkdfPublicKey& recipient_key); crypto::tink::util::StatusOr Encrypt( absl::string_view plaintext, absl::string_view context_info) const override; private: Cecpq2AeadHkdfHybridEncrypt( const google::crypto::tink::Cecpq2AeadHkdfPublicKey& recipient_key, std::unique_ptr sender_kem, std::unique_ptr dem_helper) : recipient_key_(recipient_key), sender_kem_(std::move(sender_kem)), dem_helper_(std::move(dem_helper)) {} google::crypto::tink::Cecpq2AeadHkdfPublicKey recipient_key_; std::unique_ptr sender_kem_; std::unique_ptr dem_helper_; }; } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_KEM_SUBTLE_CECPQ2_AEAD_HKDF_HYBRID_ENCRYPT_H_ ================================================ FILE: cc/experimental/pqcrypto/kem/subtle/cecpq2_aead_hkdf_hybrid_encrypt_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_aead_hkdf_hybrid_encrypt.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "openssl/curve25519.h" #include "openssl/hrss.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_subtle_boringssl_util.h" #include "tink/experimental/pqcrypto/kem/util/test_util.h" #include "tink/hybrid_encrypt.h" #include "tink/registry.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/random.h" #include "tink/subtle/subtle_util.h" #include "tink/util/enums.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_gcm.pb.h" #include "proto/common.pb.h" #include "proto/experimental/pqcrypto/cecpq2_aead_hkdf.pb.h" using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::HasSubstr; namespace crypto { namespace tink { namespace { google::crypto::tink::Cecpq2AeadHkdfPublicKey CreateValidKey() { auto cecp2_key_pair = crypto::tink::pqc::GenerateCecpq2Keypair( subtle::EllipticCurveType::CURVE25519) .value(); google::crypto::tink::Cecpq2AeadHkdfPublicKey sender_key; sender_key.set_hrss_public_key_marshalled( cecp2_key_pair.hrss_key_pair.hrss_public_key_marshaled); sender_key.set_x25519_public_key_x(cecp2_key_pair.x25519_key_pair.pub_x); sender_key.mutable_params()->mutable_kem_params()->set_curve_type( google::crypto::tink::EllipticCurveType::CURVE25519); sender_key.mutable_params()->mutable_kem_params()->set_hkdf_hash_type( google::crypto::tink::HashType::SHA256); sender_key.mutable_params() ->mutable_dem_params() ->mutable_aead_dem() ->set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey"); return sender_key; } TEST(Cecpq2AeadHkdfHybridEncryptTest, ValidKey) { google::crypto::tink::Cecpq2AeadHkdfPublicKey sender_key = CreateValidKey(); auto result = Cecpq2AeadHkdfHybridEncrypt::New(sender_key); EXPECT_THAT(result, IsOk()); } TEST(Cecpq2AeadHkdfHybridEncryptTest, InvalidKeyNoFieldSet) { auto result = Cecpq2AeadHkdfHybridEncrypt::New( google::crypto::tink::Cecpq2AeadHkdfPublicKey()); EXPECT_THAT(result.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("missing KEM required fields"))); } TEST(Cecpq2AeadHkdfHybridEncryptTest, InvalidKeySomeFieldsSet) { google::crypto::tink::Cecpq2AeadHkdfPublicKey sender_key = CreateValidKey(); sender_key.set_x25519_public_key_x(""); auto result(Cecpq2AeadHkdfHybridEncrypt::New(sender_key)); EXPECT_THAT(result.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("missing KEM required fields"))); } TEST(Cecpq2AeadHkdfHybridEncryptTest, InvalidKeyUnsupportedEcType) { google::crypto::tink::Cecpq2AeadHkdfPublicKey sender_key = CreateValidKey(); sender_key.mutable_params()->mutable_kem_params()->set_curve_type( google::crypto::tink::EllipticCurveType::NIST_P256); auto result = Cecpq2AeadHkdfHybridEncrypt::New(sender_key); EXPECT_THAT(result.status(), StatusIs(absl::StatusCode::kUnimplemented, HasSubstr("Unsupported elliptic curve"))); } TEST(Cecpq2AeadHkdfHybridEncryptTest, InvalidKeyUnsupportedDemKeyType) { auto status_or_cecpq2_key = pqc::GenerateCecpq2Keypair(subtle::EllipticCurveType::CURVE25519); ASSERT_THAT(status_or_cecpq2_key, IsOk()); auto cecpq2_key_pair = std::move(status_or_cecpq2_key).value(); google::crypto::tink::Cecpq2AeadHkdfPublicKey sender_key = CreateValidKey(); sender_key.mutable_params() ->mutable_dem_params() ->mutable_aead_dem() ->set_type_url("some.type.url/that.is.not.supported"); auto result(Cecpq2AeadHkdfHybridEncrypt::New(sender_key)); EXPECT_THAT(result.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Unsupported DEM key type"))); } TEST(Cecpq2AeadHkdfHybridEncryptTest, Basic) { // Prepare an Cecpq2 key auto cecpq2_key = CreateValidKey(); // Register DEM key manager ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); std::string dem_key_type = AesGcmKeyManager().get_key_type(); // Generate and test many keys with various parameters std::string plaintext = "some plaintext"; std::string context_info = "some context info"; for (auto curve : {google::crypto::tink::EllipticCurveType::CURVE25519}) { for (auto ec_point_format : {google::crypto::tink::EcPointFormat::COMPRESSED}) { for (auto hash_type : {google::crypto::tink::HashType::SHA256, google::crypto::tink::HashType::SHA512}) { for (uint32_t aes_gcm_key_size : {16, 32}) { SCOPED_TRACE(absl::StrCat(curve, ":", ec_point_format, ":", hash_type, ":", aes_gcm_key_size)); cecpq2_key.mutable_params()->mutable_kem_params()->set_curve_type( curve); cecpq2_key.mutable_params() ->mutable_kem_params() ->set_ec_point_format(ec_point_format); cecpq2_key.mutable_params()->mutable_kem_params()->set_hkdf_hash_type( hash_type); google::crypto::tink::AesGcmKeyFormat format; format.set_key_size(aes_gcm_key_size); cecpq2_key.mutable_params() ->mutable_dem_params() ->mutable_aead_dem() ->set_value(format.SerializeAsString()); cecpq2_key.mutable_params() ->mutable_dem_params() ->mutable_aead_dem() ->set_type_url( "type.googleapis.com/google.crypto.tink.AesGcmKey"); auto key_or = Cecpq2AeadHkdfHybridEncrypt::New(cecpq2_key); ASSERT_THAT(key_or, IsOk()); std::unique_ptr hybrid_encrypt( std::move(key_or.value())); // Use the primitive auto encrypt_result = hybrid_encrypt->Encrypt(plaintext, context_info); EXPECT_THAT(encrypt_result, IsOk()); } } } } } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/kem/subtle/cecpq2_hkdf_recipient_kem_boringssl.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_hkdf_recipient_kem_boringssl.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "openssl/bn.h" #include "openssl/curve25519.h" #include "openssl/ec.h" #include "openssl/hrss.h" #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_hkdf_sender_kem_boringssl.h" #include "tink/internal/fips_utils.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/hkdf.h" #include "tink/util/errors.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // This method only redirects the object creation to the appropriate class // based on the chosen curve. As of now, the only curve supported is // Curve25519. This method was designed to be generic enough to faciliate the // extension of this hybrid KEM to support other curves. // static util::StatusOr> Cecpq2HkdfRecipientKemBoringSsl::New(EllipticCurveType curve, util::SecretData ec_private_key, util::SecretData hrss_private_key_seed) { switch (curve) { case EllipticCurveType::CURVE25519: return Cecpq2HkdfX25519RecipientKemBoringSsl::New( curve, std::move(ec_private_key), std::move(hrss_private_key_seed)); default: return util::Status(absl::StatusCode::kUnimplemented, "Unsupported elliptic curve"); } } // static util::StatusOr> Cecpq2HkdfX25519RecipientKemBoringSsl::New( EllipticCurveType curve, util::SecretData ec_private_key, util::SecretData hrss_private_key_seed) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) return status; // Basic input checking if (curve != CURVE25519) { return util::Status(absl::StatusCode::kInvalidArgument, "curve is not CURVE25519"); } if (ec_private_key.size() != X25519_PRIVATE_KEY_LEN) { return util::Status(absl::StatusCode::kInvalidArgument, "priv has unexpected length"); } // If all input parameters are ok, create a CECPQ2 Recipient KEM instance return {absl::WrapUnique(new Cecpq2HkdfX25519RecipientKemBoringSsl( std::move(ec_private_key), std::move(hrss_private_key_seed)))}; } crypto::tink::util::StatusOr Cecpq2HkdfX25519RecipientKemBoringSsl::GenerateKey( absl::string_view kem_bytes, HashType hash, absl::string_view hkdf_salt, absl::string_view hkdf_info, uint32_t key_size_in_bytes, EcPointFormat point_format) const { // Basic input checking if (point_format != EcPointFormat::COMPRESSED) { return util::Status( absl::StatusCode::kInvalidArgument, "X25519 only supports compressed elliptic curve points"); } if (kem_bytes.size() != X25519_PUBLIC_VALUE_LEN + HRSS_PUBLIC_KEY_BYTES) { return util::Status(absl::StatusCode::kInvalidArgument, "kem_bytes has unexpected size"); } if (key_size_in_bytes < 32) { return util::Status(absl::StatusCode::kInvalidArgument, "key size length is smaller than 32 bytes " "and thus not post-quantum secure."); } // Recover X25519 shared secret util::SecretData x25519_shared_secret(X25519_SHARED_KEY_LEN); X25519(x25519_shared_secret.data(), private_key_x25519_.data(), reinterpret_cast(kem_bytes.data())); // Regenerate HRSS key pair from seed util::SecretUniquePtr hrss_private_key = util::MakeSecretUniquePtr(); struct HRSS_public_key hrss_public_key; HRSS_generate_key(&hrss_public_key, hrss_private_key.get(), private_key_hrss_seed_.data()); // Recover HRSS shared secret from kem_bytes and private key util::SecretData hrss_shared_secret(HRSS_KEY_BYTES); HRSS_decap(reinterpret_cast(hrss_shared_secret.data()), hrss_private_key.get(), reinterpret_cast(kem_bytes.data() + X25519_PUBLIC_VALUE_LEN), HRSS_CIPHERTEXT_BYTES); // Concatenate both shared secrets and kem_bytes util::SecretData ikm = util::SecretDataFromStringView(absl::StrCat( kem_bytes, util::SecretDataAsStringView(x25519_shared_secret), util::SecretDataAsStringView(hrss_shared_secret))); // Compute symmetric key from both shared secrets, kem_bytes, hkdf_salt and // hkdf_info using HKDF auto symmetric_key_or = Hkdf::ComputeHkdf(hash, ikm, hkdf_salt, hkdf_info, key_size_in_bytes); if (!symmetric_key_or.ok()) { return symmetric_key_or.status(); } util::SecretData symmetric_key = symmetric_key_or.value(); return symmetric_key; } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/kem/subtle/cecpq2_hkdf_recipient_kem_boringssl.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_KEM_SUBTLE_CECPQ2_HKDF_RECIPIENT_KEM_BORINGSSL_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_KEM_SUBTLE_CECPQ2_HKDF_RECIPIENT_KEM_BORINGSSL_H_ #include #include #include #include "absl/strings/string_view.h" #include "openssl/curve25519.h" #include "openssl/ec.h" #include "openssl/hrss.h" #include "tink/internal/fips_utils.h" #include "tink/subtle/common_enums.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // This class implements the CECPQ2 hybrid KEM from the recipient's perspective, // using Boring SSL for the underlying cryptographic operations. // This class is made generic enough so that extending the ECC algorithm to // support other curves is trivial. As of now, the only supported curve is // Curve25519. // // CECPQ2 combines both X25519 KEM and NTRU-HRSS KEM into a single hybrid KEM. // The NTRU-HRSS is a structured lattice-based key encapsulation mechanism. It // was originally proposed in [1] and submitted to the NIST Post-Quantum // Cryptography standardization process [2]. // // During the course of the NIST PQC standardization process, the NTRU-HRSS // proposal merged with another proposal (NTRUEncrypt). The resulting scheme, // simply called NTRU [3], is a 3rd round finalist of the NIST PQC // standardization process. // // The implementation available in BoringSSL is based on [1] but it // uses a different KEM construction based on [4]. Similar path has been taken // by the NTRU team in the NIST competition which later adopted [4] as their // QROM security proof approach. Note that the BoringSSL implementation is *not* // compatible with the 3rd Round finalist NTRU running in the NIST Post-Quantum // Cryptography standardization process [5]. // // References: // [1]: https://eprint.iacr.org/2017/667.pdf // [2]: https://csrc.nist.gov/Projects/post-quantum-cryptography/ // [3]: https://ntru.org/ // [4]: https://eprint.iacr.org/2017/1005.pdf // [5]: https://ntru.org/release/NIST-PQ-Submission-NTRU-20201016.tar.gz class Cecpq2HkdfRecipientKemBoringSsl { public: // Constructs a recipient KEM for the specified curve, recipient's ECC // private key, which must be a big-endian byte array, and recipient's HRSS // private key. This method is made generic enough so that extending the ECC // algorithm to support other curves is trivial. static crypto::tink::util::StatusOr< std::unique_ptr> New(EllipticCurveType curve, util::SecretData ec_private_key, util::SecretData hrss_private_key_seed); virtual ~Cecpq2HkdfRecipientKemBoringSsl() = default; // Computes the shared secret from the ECC private key and peer's ECC encoded // public key, and the shared secret from the HRSS private key, then uses a // hkdf to derive the symmetric key from the two shared secrets, hkdf info and // hkdf salt. This method is made generic enough so that extending the ECC // algorithm to support other curves is trivial. virtual crypto::tink::util::StatusOr GenerateKey( absl::string_view kem_bytes, HashType hash, absl::string_view hkdf_salt, absl::string_view hkdf_info, uint32_t key_size_in_bytes, EcPointFormat point_format) const = 0; }; // Implementation of Cecpq2HkdfRecipientKemBoringSsl for Curve25519. class Cecpq2HkdfX25519RecipientKemBoringSsl : public Cecpq2HkdfRecipientKemBoringSsl { public: static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kNotFips; // Constructs a recipient CECPQ2 KEM for recipient's X25519 private key, // which must be a big-endian byte array, and recipient's HRSS private key. static crypto::tink::util::StatusOr< std::unique_ptr> New(EllipticCurveType curve, util::SecretData ec_private_key, util::SecretData hrss_private_key_seed); // Computes the shared secret from X25519 private key and peer's X25519 // encoded public key, and the shared secret from the HRSS private key, then // uses a hkdf to derive the symmetric key from the two shared secrets, hkdf // info and hkdf salt. crypto::tink::util::StatusOr GenerateKey( absl::string_view kem_bytes, HashType hash, absl::string_view hkdf_salt, absl::string_view hkdf_info, uint32_t key_size_in_bytes, EcPointFormat point_format) const override; private: // The private constructor only takes the X25519 and HRSS private keys and // assign them to the class private members. explicit Cecpq2HkdfX25519RecipientKemBoringSsl( util::SecretData ec_private_key, util::SecretData hrss_private_key_seed) : private_key_x25519_(std::move(ec_private_key)), private_key_hrss_seed_(std::move(hrss_private_key_seed)) {} // X25519 and HRSS private key containers util::SecretData private_key_x25519_; util::SecretData private_key_hrss_seed_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_KEM_SUBTLE_CECPQ2_HKDF_RECIPIENT_KEM_BORINGSSL_H_ ================================================ FILE: cc/experimental/pqcrypto/kem/subtle/cecpq2_hkdf_recipient_kem_boringssl_test.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_hkdf_recipient_kem_boringssl.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "openssl/curve25519.h" #include "openssl/hrss.h" #include "tink/config/tink_fips.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/random.h" #include "tink/util/secret_data.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::HasSubstr; namespace crypto { namespace tink { namespace subtle { namespace { // CECPQ2 test vector from BoringSSL const char kHrssKeyGenEntropy[] = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324" "25262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243444546474849" "4a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e" "6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f90919293" "9495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8" "b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdd" "dedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102" "030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324252627" "28292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c" "4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f7071" "72737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f90919293949596" "9798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babb" "bcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0" "e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405" "060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a" "2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" "505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f7071727374" "75767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f90919293949596979899" "9a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbebfc0" "c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5" "e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a" "0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f" "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f5051525354" "55565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f70717273747576777879" "7a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e" "9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3" "c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8" "e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d" "0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132" "333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f5051525354555657" "58595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c" "7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1" "a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6" "c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaeb" "ecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f10" "1112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435" "363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a" "5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797c7d7e7f8081" "82838485868788898a8b8c8d8e8f909192939495969798999a9b"; const char kCecpq2KemBytes[] = "5b9cbc8389eb7b6ce907a61d63b6ea1e46f77b65821fb394bc8508d7584f7365e0c077eb7a" "487d744e4f6db95c18e95b476c789d9802849ff24543860ec69348d820ff82389e78b42cb3" "42e4b3abdfed65240ca5952cbf4c28fcb8e7c6bc76a0f53f297323f16c107c088e163ada17" "a30d4644ee6f70f1885135339176eb98c104db97ab88b90487d9b834d338e790052e45e0ac" "360c5958b1f5656d281a39d9d28317eeeb6f7d293c79cf48f16d35c28ce86718cc9d9b8d07" "7a4e56a8002e6767bbc1da4a7b9fa64a5c40cce4ddf5c044fea5a21cdcf231f4011f69157e" "8c54b6470c1d9f1afaf746a3cb342c184565c4f20ef8c7961d295c90d3dfb28e21f915407e" "d384521dd9eeede8711cdb48f52082c461fd6d719fd803908efced4dab6eb2e966fdcc3aa3" "99533576ea0888baf0b753f34c1a8f7fe41b8bfc993e4ca9d917106460fd8176e637b0e33e" "c0f7067e34a5f4b95f66e681c85eb2266b8cadd0940122f6be1a0b34fc33c084a5e0128a08" "ae8aaf550c344b2bdda37cc0ede88d98477c81251b9f08269dfc198e39c41a3c4270493757" "870f76b1c4be255e1c0657c6883428df603309c5ccf4c433858b48e827b7722244ffe789f9" "7199ed6247b0229ea67cafa9982b5c8a423477a3c8131ecf32a770a8adc1665c8faf146dc4" "4505cdcb80fa0ea6ca7286d2b7392677f814d0cdddf7dcda258e3c21fdef92ee52f7c3c7e2" "2d1c575abad8aa0d09a7b3cca15ddb042182efbac2c854b1bed72a91d8eb7254c17424245a" "03f7cdab91d163f1609f2207ad102b971c6fcec029c2b2b81bbd14c8b98066c186fc935f6e" "0b7a7b8e428c08d160b9f866247d88582fd252753a8a1cfa1ea11c9146799ae58addc275ed" "0db82b4f8f95cace21a47a0d147f2d98f088c36fadb50424914165d3a57efb531cccd0f77c" "91080eddd46c73aaa57ad224c93b6fda068adb2ea8e9e13e08eebe966572686ff750e7a718" "dac294dae3bcca03d8f77acc44a160a87fdcef80f462c6064eb6ac7717b7b33ef86d8a6183" "3afdbb935b1a33f8ee7d9e5cf8c9d53e3d429be50decc90f6f03b04185b9fef9b1b4c3d913" "03fa0de7d1b4c8f6b5117a9209217ba9894c19900d96324f77fc7f8ca3392a56e65cd1860a" "72f4a31ba530043c15204be42d1af14448fcdac141db71fd920053e470d0baf6ef1772b8ea" "6d41164d1f5918bd1fc56b6a6c2ea61a33748bc59f1601777e37e763e1a38c1f71e94fad15" "8bf3c9acdc19ad921800f6a1d597a33d9e7802c38f75d8ad22bfef195d15341a7c9bafd4f2" "f95f72889ce458da468f79302bd93bbcab2877750e2c23479514ebf04a3e5393a7f4829c34" "8b8042b2a7b07c6ce107f4343eed339cb3dea59161258e8c5456be1aac17d27aa412542a51" "d00ed1c144500539a7b61445caf85f066b5d5ec7e9276f38e031cff8cc2eb94a101bb4344b" "90bbf2e03c797f39590c014c0d2d71f1bdda1a78cf266fb5a90720e68cd0add4ca246cc528" "1dfbcce79372996163604c5ca9b61532a4bc1ff663612c26a70e5f1b25ce3f64df6db08fd2" "e93b35d0598122f165861510e8a7a16fb4341c79d59e8dc8a5bb8271810034556b9656130e" "e739a26fbe542a130313d21d719abe0900e18d59b54402"; const char kCecpq2X25519PrivateKeyHex[] = "b79cbf241478d6f5139d517cf1beae62296a9e86d05d9e14fcb52d80d30eaebe"; const char kCorrectSharedSecret[] = "4ba608d54c2c2159e7aa8f576df5d4403b9ad8d2718cf76e461da09343948e63"; const char kFailSharedSecret[] = "c3d8a7f03b25ce23287dd6e7c49596104732fa855266e4f6a4dc79eaaf2757ad"; const char kSaltHex[] = "0b0b0b0b"; const char kInfoHex[] = "0b0b0b0b0b0b0b0b"; // This test evaluates the creation of a Cecpq2HkdfRecipientKemBoringSslTest // instance with an unknown curve type. It should fail with an // absl::StatusCode::kUnimplemented error. TEST(Cecpq2HkdfRecipientKemBoringSslTest, TestUnknownCurve) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } // Creating the CECPQ2 recipient KEM using HRSS and X25519 private keys util::SecretData hrss_private_key_seed = util::SecretDataFromStringView(test::HexDecodeOrDie(kHrssKeyGenEntropy)); auto status_or_recipient_kem = Cecpq2HkdfRecipientKemBoringSsl::New( EllipticCurveType::UNKNOWN_CURVE, util::SecretDataFromStringView( test::HexDecodeOrDie(kCecpq2X25519PrivateKeyHex)), std::move(hrss_private_key_seed)); // The instance creation above should fail with an unimplemented algorithm // error given the UNKNOWN_CURVE parameter EXPECT_EQ(absl::StatusCode::kUnimplemented, status_or_recipient_kem.status().code()); } // This test evaluates the case where a unsupported curve (NIST_P256) is // specified. This test should fail with an absl::StatusCode::kUnimplemented // error. TEST(Cecpq2HkdfRecipientKemBoringSslTest, TestUnsupportedCurve) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } // Creating the CECPQ2 recipient KEM using HRSS and X25519 private keys util::SecretData hrss_private_key_seed = util::SecretDataFromStringView(test::HexDecodeOrDie(kHrssKeyGenEntropy)); auto status_or_recipient_kem = Cecpq2HkdfRecipientKemBoringSsl::New( EllipticCurveType::NIST_P256, util::SecretDataFromStringView( test::HexDecodeOrDie(kCecpq2X25519PrivateKeyHex)), std::move(hrss_private_key_seed)); // The instance creation above should fail with an unimplemented algorithm // error given the UNKNOWN_CURVE parameter EXPECT_EQ(absl::StatusCode::kUnimplemented, status_or_recipient_kem.status().code()); } // This test checks that an error is triggered if an output key lenth smaller // than 32 bytes is specified. TEST(Cecpq2HkdfRecipientKemBoringSslTest, TestNotPostQuantumSecureKeyLength) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } // Not post-quantum secure output key length int out_len = 31; // Creating the CECPQ2 recipient KEM using HRSS and X25519 private keys util::SecretData hrss_private_key_seed = util::SecretDataFromStringView(test::HexDecodeOrDie(kHrssKeyGenEntropy)); auto cecpq2_recipient_kem_or = Cecpq2HkdfRecipientKemBoringSsl::New( EllipticCurveType::CURVE25519, util::SecretDataFromStringView( test::HexDecodeOrDie(kCecpq2X25519PrivateKeyHex)), std::move(hrss_private_key_seed)); ASSERT_THAT(cecpq2_recipient_kem_or, IsOk()); auto cecpq2_recipient_kem = std::move(cecpq2_recipient_kem_or).value(); // Recovering the symmetric key auto kem_key_or = cecpq2_recipient_kem->GenerateKey( test::HexDecodeOrDie(kCecpq2KemBytes), HashType::SHA256, test::HexDecodeOrDie(kSaltHex), test::HexDecodeOrDie(kInfoHex), out_len, EcPointFormat::COMPRESSED); EXPECT_THAT(kem_key_or.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("not post-quantum secure"))); } TEST(Cecpq2HkdfRecipientKemBoringSslTest, TestRecipientFlowSuccess) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } int out_len = 32; // Creating the CECPQ2 recipient KEM using HRSS and X25519 private keys util::SecretData hrss_private_key_seed = util::SecretDataFromStringView(test::HexDecodeOrDie(kHrssKeyGenEntropy)); auto cecpq2_recipient_kem_or = Cecpq2HkdfRecipientKemBoringSsl::New( EllipticCurveType::CURVE25519, util::SecretDataFromStringView( test::HexDecodeOrDie(kCecpq2X25519PrivateKeyHex)), std::move(hrss_private_key_seed)); ASSERT_THAT(cecpq2_recipient_kem_or, IsOk()); auto cecpq2_recipient_kem = std::move(cecpq2_recipient_kem_or).value(); // Recovering the symmetric key auto kem_key_or = cecpq2_recipient_kem->GenerateKey( test::HexDecodeOrDie(kCecpq2KemBytes), HashType::SHA256, test::HexDecodeOrDie(kSaltHex), test::HexDecodeOrDie(kInfoHex), out_len, EcPointFormat::COMPRESSED); ASSERT_THAT(kem_key_or, IsOk()); // The generated symmetric key should match the expected one EXPECT_EQ(kCorrectSharedSecret, test::HexEncode(util::SecretDataAsStringView(kem_key_or.value()))); } TEST(Cecpq2HkdfRecipientKemBoringSslTest, TestRecipientFlowFailure) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } int out_len = 32; // The following kem_bytes is not correct. The 50-th position of the HRSS // kem_bytes has been modified (its original value xored with 4). This // modified HRSS kem_bytes matches the one used in BoringSSL test vector. This // change will result in an HRSS decapsulation failure which produces a // symmetric key using a deterministic algorithm based on HMAC-SHA256. std::string kem_bytes_modified = test::HexDecodeOrDie(kCecpq2KemBytes); kem_bytes_modified[X25519_PUBLIC_VALUE_LEN + 50] ^= 0x04; // Creating the CECPQ2 recipient KEM using HRSS and X25519 private keys util::SecretData hrss_private_key_seed = util::SecretDataFromStringView(test::HexDecodeOrDie(kHrssKeyGenEntropy)); auto cecpq2_recipient_kem_or = Cecpq2HkdfRecipientKemBoringSsl::New( EllipticCurveType::CURVE25519, util::SecretDataFromStringView( test::HexDecodeOrDie(kCecpq2X25519PrivateKeyHex)), std::move(hrss_private_key_seed)); ASSERT_THAT(cecpq2_recipient_kem_or, IsOk()); auto cecpq2_recipient_kem = std::move(cecpq2_recipient_kem_or).value(); // Recovering the symmetric key auto kem_key_or = cecpq2_recipient_kem->GenerateKey( kem_bytes_modified, HashType::SHA256, test::HexDecodeOrDie(kSaltHex), test::HexDecodeOrDie(kInfoHex), out_len, EcPointFormat::COMPRESSED); ASSERT_THAT(kem_key_or, IsOk()); // The produced symmetric key should match the one produced by CECPQ2 in case // of HRSS decapsulation failure for the altered HRSS kem_bytes EXPECT_EQ(kFailSharedSecret, test::HexEncode(util::SecretDataAsStringView(kem_key_or.value()))); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/kem/subtle/cecpq2_hkdf_sender_kem_boringssl.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_hkdf_sender_kem_boringssl.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "openssl/bn.h" #include "openssl/curve25519.h" #include "openssl/hrss.h" #include "tink/internal/fips_utils.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/hkdf.h" #include "tink/subtle/random.h" #include "tink/subtle/subtle_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // This method only redirects the object creation to the appropriate class // based on the chosen curve. As of now, the only curve supported is // Curve25519. This method was designed to be generic enough to faciliate the // extension of this hybrid KEM to support other curves. // static util::StatusOr> Cecpq2HkdfSenderKemBoringSsl::New(subtle::EllipticCurveType curve, const absl::string_view ec_pubx, const absl::string_view ec_puby, const absl::string_view marshalled_hrss_pub) { switch (curve) { case EllipticCurveType::CURVE25519: return Cecpq2HkdfX25519SenderKemBoringSsl::New(curve, ec_pubx, ec_puby, marshalled_hrss_pub); default: return util::Status(absl::StatusCode::kUnimplemented, "Unsupported elliptic curve"); } } Cecpq2HkdfX25519SenderKemBoringSsl::Cecpq2HkdfX25519SenderKemBoringSsl( const absl::string_view peer_ec_pubx, const absl::string_view marshalled_hrss_pub) { peer_public_key_x25519_.assign(std::string(peer_ec_pubx)); peer_marshalled_public_key_hrss_.assign(std::string(marshalled_hrss_pub)); } // static util::StatusOr> Cecpq2HkdfX25519SenderKemBoringSsl::New( subtle::EllipticCurveType curve, const absl::string_view pubx, const absl::string_view puby, const absl::string_view marshalled_hrss_pub) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) return status; // Basic input checking if (curve != CURVE25519) { return util::Status(absl::StatusCode::kInvalidArgument, "curve is not CURVE25519"); } if (pubx.size() != X25519_PUBLIC_VALUE_LEN) { return util::Status(absl::StatusCode::kInvalidArgument, "pubx has unexpected length"); } if (!puby.empty()) { return util::Status(absl::StatusCode::kInvalidArgument, "puby is not empty"); } if (marshalled_hrss_pub.size() != HRSS_PUBLIC_KEY_BYTES) { return util::Status(absl::StatusCode::kInvalidArgument, "marshalled_hrss_pub has unexpected length"); } // If input parameters are ok, create a CECPQ2 Sender KEM instance std::unique_ptr sender_kem( new Cecpq2HkdfX25519SenderKemBoringSsl(pubx, marshalled_hrss_pub)); return std::move(sender_kem); } util::StatusOr> Cecpq2HkdfX25519SenderKemBoringSsl::GenerateKey( subtle::HashType hash, absl::string_view hkdf_salt, absl::string_view hkdf_info, uint32_t key_size_in_bytes, subtle::EcPointFormat point_format) const { // Basic input validation: if (point_format != EcPointFormat::COMPRESSED) { return util::Status( absl::StatusCode::kInvalidArgument, "X25519 only supports compressed elliptic curve points"); } if (key_size_in_bytes < 32) { return util::Status(absl::StatusCode::kInvalidArgument, "key size length is smaller than 32 bytes " "and thus not post-quantum secure."); } // Generate the ephemeral X25519 key pair. Note that the // X25519_kem_bytes holds the X25519 public key util::SecretData ephemeral_x25519_private_key(X25519_PRIVATE_KEY_LEN); std::string x25519_kem_bytes(X25519_PUBLIC_VALUE_LEN, '\0'); X25519_keypair(const_cast(reinterpret_cast( x25519_kem_bytes.data())), ephemeral_x25519_private_key.data()); // Generate the x25519 shared secret using peer's X25519 public key and // locally generated ephemeral X25519 private key util::SecretData x25519_shared_secret(X25519_SHARED_KEY_LEN); X25519(x25519_shared_secret.data(), ephemeral_x25519_private_key.data(), reinterpret_cast(peer_public_key_x25519_.data())); // Declare the hrss_shared_secret and hrss_kem_bytes to be used in HRSS encaps util::SecretData hrss_shared_secret; hrss_shared_secret.resize(HRSS_KEY_BYTES); // The hrss_kem_bytes will contain the encrypted shared secret std::string hrss_kem_bytes; subtle::ResizeStringUninitialized(&hrss_kem_bytes, HRSS_CIPHERTEXT_BYTES); // Recover the internal HRSS public key representation from marshalled version struct HRSS_public_key peer_public_key_hrss; HRSS_parse_public_key(&peer_public_key_hrss, reinterpret_cast( peer_marshalled_public_key_hrss_.data())); // Generate entropy to be used in encaps util::SecretData encaps_entropy = crypto::tink::subtle::Random::GetRandomKeyBytes(HRSS_ENCAP_BYTES); // Generate a random shared secret and encapsulate it using peer's HRSS public // key HRSS_encap(const_cast( reinterpret_cast(hrss_kem_bytes.data())), reinterpret_cast(hrss_shared_secret.data()), &peer_public_key_hrss, encaps_entropy.data()); // Concatenate the two kem_bytes std::string kem_bytes(x25519_kem_bytes); kem_bytes += hrss_kem_bytes; // Concatenate the two shared secrets with the two kem_bytes std::string kem_bytes_and_shared_secrets = absl::StrCat( kem_bytes, util::SecretDataAsStringView(x25519_shared_secret), util::SecretDataAsStringView(hrss_shared_secret)); util::SecretData ikm = util::SecretDataFromStringView(kem_bytes_and_shared_secrets); // Compute the symmetric key from the two shared secrets, kem_bytes, hkdf_salt // and hkdf_info using HKDF auto symmetric_key_or = Hkdf::ComputeHkdf(hash, ikm, hkdf_salt, hkdf_info, key_size_in_bytes); if (!symmetric_key_or.ok()) { return symmetric_key_or.status(); } util::SecretData symmetric_key = symmetric_key_or.value(); // Return the produced pair kem_bytes and symmetric_key return absl::make_unique(kem_bytes, symmetric_key); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/kem/subtle/cecpq2_hkdf_sender_kem_boringssl.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_KEM_SUBTLE_CECPQ2_HKDF_SENDER_KEM_BORINGSSL_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_KEM_SUBTLE_CECPQ2_HKDF_SENDER_KEM_BORINGSSL_H_ #include #include #include #include #include "absl/strings/string_view.h" #include "openssl/curve25519.h" #include "openssl/ec.h" #include "openssl/hrss.h" #include "tink/internal/fips_utils.h" #include "tink/subtle/common_enums.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // This class implements the CECPQ2 hybrid KEM from the sender's perspective, // using Boring SSL for the underlying cryptographic operations. // This class is made generic enough so that extending the ECC algorithm to // support other curves is trivial. As of now, the only supported curve is // Curve25519. // // CECPQ2 combines both X25519 KEM and NTRU-HRSS KEM into a single hybrid KEM. // The NTRU-HRSS is a structured lattice-based key encapsulation mechanism. It // was originally proposed in [1] and submitted to the NIST Post-Quantum // Cryptography standardization process [2]. // // During the course of the NIST PQC standardization process, the NTRU-HRSS // proposal merged with another proposal (NTRUEncrypt). The resulting scheme, // simply called NTRU [3], is a 3rd round finalist of the NIST PQC // standardization process. // // The implementation available in BoringSSL is based on [1] but it // uses a different KEM construction based on [4]. Similar path has been taken // by the NTRU team in the NIST competition which later adopted [4] as their // QROM security proof approach. Note that the BoringSSL implementation is *not* // compatible with the 3rd Round finalist NTRU running in the NIST Post-Quantum // Cryptography standardization process [5]. // // References: // [1]: https://eprint.iacr.org/2017/667.pdf // [2]: https://csrc.nist.gov/Projects/post-quantum-cryptography/ // [3]: https://ntru.org/ // [4]: https://eprint.iacr.org/2017/1005.pdf // [5]: https://ntru.org/release/NIST-PQ-Submission-NTRU-20201016.tar.gz class Cecpq2HkdfSenderKemBoringSsl { public: // Container for the generated key and associated kem_bytes data. class KemKey { public: KemKey() = default; explicit KemKey(std::string kem_bytes, util::SecretData symmetric_key) : kem_bytes_(std::move(kem_bytes)), symmetric_key_(std::move(symmetric_key)) {} const std::string& get_kem_bytes() const { return kem_bytes_; } const util::SecretData& get_symmetric_key() const { return symmetric_key_; } private: // The kem_bytes variable stores both X25519 and HRSS kem_bytes in a // contiguous form. We note that for X25519, the kem_bytes consists of the // X25519 public key, while for HRSS it is the encrypted shared secret. std::string kem_bytes_; util::SecretData symmetric_key_; }; // Constructs a sender CECPQ2 KEM for recipient's ECC public key, which must // be a big-endian byte array, and recipient's HRSS public key. This method is // made generic enough so that extending the ECC algorithm to support other // curves is trivial. static crypto::tink::util::StatusOr< std::unique_ptr> New(EllipticCurveType curve, absl::string_view ec_pubx, absl::string_view ec_puby, absl::string_view marshalled_hrss_pub); // Generates ephemeral key pairs, computes ECC's shared secret based on // generated ephemeral key and recipient's public key, generate a random // shared secret and encapsulates it using recipient's HRSS public key. // Then it uses HKDF to derive the symmetric key from both shared secrets, // 'hkdf_info' and hkdf_salt. This method is made generic enough so that // extending the ECC algorithm to support other curves is trivial. virtual crypto::tink::util::StatusOr> GenerateKey(HashType hash, absl::string_view hkdf_salt, absl::string_view hkdf_info, uint32_t key_size_in_bytes, EcPointFormat point_format) const = 0; virtual ~Cecpq2HkdfSenderKemBoringSsl() = default; }; // Implementation of Cecpq2HkdfSenderKemBoringSsl for X25519 and HRSS. class Cecpq2HkdfX25519SenderKemBoringSsl : public Cecpq2HkdfSenderKemBoringSsl { public: // Constructs a sender CECPQ2 KEM for recipient's X25519 public key, which // must be a big-endian byte array, and recipient's HRSS public key. static crypto::tink::util::StatusOr< std::unique_ptr> New(EllipticCurveType curve, absl::string_view pubx, absl::string_view puby, absl::string_view marshalled_hrss_pub); // Generates an ephemeral X25519 key pair, computes the X25519's shared secret // based on the ephemeral key and recipient's public key, generates a random // shared secret and encapsulates it using the recipient's HRSS public key. // Then it uses HKDF to derive the symmetric key from both shared secrets, // 'hkdf_info' and hkdf_salt. crypto::tink::util::StatusOr> GenerateKey( HashType hash, absl::string_view hkdf_salt, absl::string_view hkdf_info, uint32_t key_size_in_bytes, EcPointFormat point_format) const override; // Flag to indicate CECPQ2 is not FIPS compliant static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kNotFips; private: // The private constructor only takes the X25519 and HRSS public keys. The // curve is not provided as a parameter here because the curve validation has // already been made in the New() method defined above. explicit Cecpq2HkdfX25519SenderKemBoringSsl( absl::string_view peer_ec_pubx, absl::string_view marshalled_hrss_pub); // X25519 and HRSS public key containers. We note that the BoringSSL // implementation of HRSS requires that the HRSS public key is stored in the // *marshalled* format. This is done by calling the HRSS_marshal_public_key // function from BoringSSL (see the tests available in cecpq2_hkdf_sender_kem // _boringssl_test.cc file that demonstrate this process). If this process is // not done, the internal raw HRSS public key representation (using the struct // HRSS_public_key data structure) might cause padding problems depending on // the compiler options. // X25519 public key of size X25519_PUBLIC_VALUE_LEN std::string peer_public_key_x25519_; // HRSS public key of size HRSS_PUBLIC_KEY_BYTES std::string peer_marshalled_public_key_hrss_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_KEM_SUBTLE_CECPQ2_HKDF_SENDER_KEM_BORINGSSL_H_ ================================================ FILE: cc/experimental/pqcrypto/kem/subtle/cecpq2_hkdf_sender_kem_boringssl_test.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_hkdf_sender_kem_boringssl.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "openssl/curve25519.h" #include "openssl/hrss.h" #include "openssl/sha.h" #include "tink/config/tink_fips.h" #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_hkdf_recipient_kem_boringssl.h" #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_subtle_boringssl_util.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/hkdf.h" #include "tink/subtle/random.h" #include "tink/subtle/subtle_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::HasSubstr; namespace crypto { namespace tink { namespace subtle { namespace { // This test evaluates the creation of a Cecpq2HkdfSenderKemBoringSsl instance // with an unknown curve type parameter. It should fail with an // absl::StatusCode::kUnimplemented error. TEST(Cecpq2HkdfSenderKemBoringSslTest, TestUnknownCurve) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } auto status_or_cecpq2_key = pqc::GenerateCecpq2Keypair(EllipticCurveType::CURVE25519); ASSERT_TRUE(status_or_cecpq2_key.ok()); auto cecpq2_key_pair = std::move(status_or_cecpq2_key).value(); // Creating an instance of Cecpq2HkdfSenderKemBoringSsl specifying an unknown // curve auto status_or_sender_kem = Cecpq2HkdfSenderKemBoringSsl::New( EllipticCurveType::UNKNOWN_CURVE, cecpq2_key_pair.x25519_key_pair.pub_x, cecpq2_key_pair.x25519_key_pair.pub_y, cecpq2_key_pair.hrss_key_pair.hrss_public_key_marshaled); // The instance creation above should fail with an unimplemented algorithm // error given the UNKNOWN_CURVE parameter EXPECT_EQ(absl::StatusCode::kUnimplemented, status_or_sender_kem.status().code()); } // This test evaluates the case where an unsupported curve (NIST_P256) is // specified. This test should fail with an absl::StatusCode::kUnimplemented // error. TEST(Cecpq2HkdfSenderKemBoringSslTest, TestUnsupportedCurve) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } auto status_or_cecpq2_key = pqc::GenerateCecpq2Keypair(EllipticCurveType::CURVE25519); ASSERT_TRUE(status_or_cecpq2_key.ok()); auto cecpq2_key_pair = std::move(status_or_cecpq2_key).value(); // Creating an instance of Cecpq2HkdfSenderKemBoringSsl specifying a // unsupported curve auto status_or_sender_kem = Cecpq2HkdfSenderKemBoringSsl::New( EllipticCurveType::NIST_P256, cecpq2_key_pair.x25519_key_pair.pub_x, cecpq2_key_pair.x25519_key_pair.pub_y, cecpq2_key_pair.hrss_key_pair.hrss_public_key_marshaled); // This test should fail with an unimplemented algorithm error EXPECT_EQ(absl::StatusCode::kUnimplemented, status_or_sender_kem.status().code()); } // This test checks that an error is triggered if an output key lenth smaller // than 32 bytes is specified. TEST(Cecpq2HkdfSenderKemBoringSslTest, TestNotPostQuantumSecureKeyLength) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } // Declaring auxiliary parameters std::string salt_hex = "0b0b0b0b"; std::string info_hex = "0b0b0b0b0b0b0b0b"; // Not post-quantum secure output key length int out_len = 31; auto status_or_cecpq2_key = pqc::GenerateCecpq2Keypair(EllipticCurveType::CURVE25519); ASSERT_TRUE(status_or_cecpq2_key.ok()); auto cecpq2_key_pair = std::move(status_or_cecpq2_key).value(); // Creating an instance of Cecpq2HkdfSenderKemBoringSsl auto status_or_sender_kem = Cecpq2HkdfSenderKemBoringSsl::New( EllipticCurveType::CURVE25519, cecpq2_key_pair.x25519_key_pair.pub_x, cecpq2_key_pair.x25519_key_pair.pub_y, cecpq2_key_pair.hrss_key_pair.hrss_public_key_marshaled); ASSERT_THAT(status_or_sender_kem, IsOk()); auto sender_kem = std::move(status_or_sender_kem.value()); // Generating a symmetric key auto status_or_kem_key = sender_kem->GenerateKey( HashType::SHA256, test::HexDecodeOrDie(salt_hex), test::HexDecodeOrDie(info_hex), out_len, EcPointFormat::COMPRESSED); EXPECT_THAT(status_or_kem_key.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("not post-quantum secure"))); } // This test evaluates if a Sender can successfully generate a symmetric key. TEST(Cecpq2HkdfSenderKemBoringSslTest, TestGenerateKey) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } // Declaring auxiliary parameters std::string salt_hex = "0b0b0b0b"; std::string info_hex = "0b0b0b0b0b0b0b0b"; int out_len = 32; auto status_or_cecpq2_key = pqc::GenerateCecpq2Keypair(EllipticCurveType::CURVE25519); ASSERT_TRUE(status_or_cecpq2_key.ok()); auto cecpq2_key_pair = std::move(status_or_cecpq2_key).value(); // Creating an instance of Cecpq2HkdfSenderKemBoringSsl auto status_or_sender_kem = Cecpq2HkdfSenderKemBoringSsl::New( EllipticCurveType::CURVE25519, cecpq2_key_pair.x25519_key_pair.pub_x, cecpq2_key_pair.x25519_key_pair.pub_y, cecpq2_key_pair.hrss_key_pair.hrss_public_key_marshaled); ASSERT_THAT(status_or_sender_kem, IsOk()); auto sender_kem = std::move(status_or_sender_kem.value()); // Generating a symmetric key auto status_or_kem_key = sender_kem->GenerateKey( HashType::SHA256, test::HexDecodeOrDie(salt_hex), test::HexDecodeOrDie(info_hex), out_len, EcPointFormat::COMPRESSED); // Asserting that the symmetric key has been successfully generated ASSERT_THAT(status_or_kem_key, IsOk()); auto kem_key = std::move(status_or_kem_key.value()); EXPECT_FALSE(kem_key->get_kem_bytes().empty()); EXPECT_EQ(kem_key->get_symmetric_key().size(), out_len); } // This test evaluates the whole KEM flow: from Sender to Recipient. This test // should successfully generate an encapsulated shared secret that matches with // a decapsulated shared secret. TEST(Cecpq2HkdfSenderKemBoringSslTest, TestSenderRecipientFullFlowSuccess) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } // Declaring auxiliary parameters std::string salt_hex = "0b0b0b0b"; std::string info_hex = "0b0b0b0b0b0b0b0b"; int out_len = 32; auto status_or_cecpq2_key = pqc::GenerateCecpq2Keypair(EllipticCurveType::CURVE25519); ASSERT_TRUE(status_or_cecpq2_key.ok()); auto cecpq2_key_pair = std::move(status_or_cecpq2_key).value(); // Creating an instance of Cecpq2HkdfSenderKemBoringSsl auto status_or_sender_kem = Cecpq2HkdfSenderKemBoringSsl::New( EllipticCurveType::CURVE25519, cecpq2_key_pair.x25519_key_pair.pub_x, cecpq2_key_pair.x25519_key_pair.pub_y, cecpq2_key_pair.hrss_key_pair.hrss_public_key_marshaled); ASSERT_TRUE(status_or_sender_kem.ok()); auto sender_kem = std::move(status_or_sender_kem.value()); // Generating sender's shared secret auto status_or_kem_key = sender_kem->GenerateKey( HashType::SHA256, test::HexDecodeOrDie(salt_hex), test::HexDecodeOrDie(info_hex), out_len, EcPointFormat::COMPRESSED); ASSERT_TRUE(status_or_kem_key.ok()); auto kem_key = std::move(status_or_kem_key.value()); // Initializing recipient's KEM data structure using recipient's private keys auto status_or_recipient_kem = Cecpq2HkdfRecipientKemBoringSsl::New( EllipticCurveType::CURVE25519, cecpq2_key_pair.x25519_key_pair.priv, std::move(cecpq2_key_pair.hrss_key_pair.hrss_private_key_seed)); ASSERT_TRUE(status_or_recipient_kem.ok()); auto recipient_kem = std::move(status_or_recipient_kem.value()); // Generating recipient's shared secret auto status_or_shared_secret = recipient_kem->GenerateKey( kem_key->get_kem_bytes(), HashType::SHA256, test::HexDecodeOrDie(salt_hex), test::HexDecodeOrDie(info_hex), out_len, EcPointFormat::COMPRESSED); ASSERT_TRUE(status_or_shared_secret.ok()); // Asserting that both shared secrets match EXPECT_EQ(test::HexEncode( util::SecretDataAsStringView(kem_key->get_symmetric_key())), test::HexEncode( util::SecretDataAsStringView(status_or_shared_secret.value()))); } // This test evaluates the whole KEM flow as in // TestSenderRecipientFullFlowSuccess with the difference that the caller's // public key is erased after Cecpq2HkdfSenderKemBoringSsl object is created. // This test would detect if the caller's public key buffers are being used // by Cecpq2HkdfSenderKemBoringSsl instead of Cecpq2HkdfSenderKemBoringSsl // having its own explicit copy. TEST(Cecpq2HkdfSenderKemBoringSslTest, TestFullFlowErasedCallersPublicKey) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } // Declaring auxiliary parameters std::string salt_hex = "0b0b0b0b"; std::string info_hex = "0b0b0b0b0b0b0b0b"; int out_len = 32; auto status_or_cecpq2_key = pqc::GenerateCecpq2Keypair(EllipticCurveType::CURVE25519); ASSERT_TRUE(status_or_cecpq2_key.ok()); auto cecpq2_key_pair = std::move(status_or_cecpq2_key).value(); // Creating an instance of Cecpq2HkdfSenderKemBoringSsl auto status_or_sender_kem = Cecpq2HkdfSenderKemBoringSsl::New( EllipticCurveType::CURVE25519, cecpq2_key_pair.x25519_key_pair.pub_x, cecpq2_key_pair.x25519_key_pair.pub_y, cecpq2_key_pair.hrss_key_pair.hrss_public_key_marshaled); ASSERT_THAT(status_or_sender_kem, IsOk()); auto sender_kem = std::move(status_or_sender_kem.value()); // Erasing caller's public key buffers cecpq2_key_pair.x25519_key_pair.pub_x.clear(); cecpq2_key_pair.x25519_key_pair.pub_y.clear(); cecpq2_key_pair.hrss_key_pair.hrss_public_key_marshaled.clear(); // Generating sender's shared secret auto status_or_kem_key = sender_kem->GenerateKey( HashType::SHA256, test::HexDecodeOrDie(salt_hex), test::HexDecodeOrDie(info_hex), out_len, EcPointFormat::COMPRESSED); ASSERT_THAT(status_or_kem_key, IsOk()); auto kem_key = std::move(status_or_kem_key.value()); // Initializing recipient's KEM data structure using recipient's private keys auto status_or_recipient_kem = Cecpq2HkdfRecipientKemBoringSsl::New( EllipticCurveType::CURVE25519, cecpq2_key_pair.x25519_key_pair.priv, std::move(cecpq2_key_pair.hrss_key_pair.hrss_private_key_seed)); ASSERT_THAT(status_or_recipient_kem, IsOk()); auto recipient_kem = std::move(status_or_recipient_kem.value()); // Generating recipient's shared secret auto status_or_shared_secret = recipient_kem->GenerateKey( kem_key->get_kem_bytes(), HashType::SHA256, test::HexDecodeOrDie(salt_hex), test::HexDecodeOrDie(info_hex), out_len, EcPointFormat::COMPRESSED); ASSERT_THAT(status_or_shared_secret, IsOk()); // Asserting that both shared secrets match EXPECT_EQ(test::HexEncode( util::SecretDataAsStringView(kem_key->get_symmetric_key())), test::HexEncode( util::SecretDataAsStringView(status_or_shared_secret.value()))); } // This test evaluates the whole KEM flow: from Sender to Recipient. This test // is essentially the same as TestSenderRecipientFullFlowSuccess with the // difference that we alter bytes of the kem_bytes thus preventing the two // shared secrets to match. TEST(Cecpq2HkdfSenderKemBoringSslTest, TestSenderRecipientFullFlowFailure) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } // Declaring auxiliary parameters std::string info_hex = "0b0b0b0b0b0b0b0b"; std::string salt_hex = "0b0b0b0b"; int out_len = 32; auto status_or_cecpq2_key = pqc::GenerateCecpq2Keypair(EllipticCurveType::CURVE25519); ASSERT_TRUE(status_or_cecpq2_key.ok()); auto cecpq2_key_pair = std::move(status_or_cecpq2_key).value(); // Initializing sender's KEM data structure using recipient's public keys auto status_or_sender_kem = Cecpq2HkdfSenderKemBoringSsl::New( EllipticCurveType::CURVE25519, cecpq2_key_pair.x25519_key_pair.pub_x, cecpq2_key_pair.x25519_key_pair.pub_y, cecpq2_key_pair.hrss_key_pair.hrss_public_key_marshaled); ASSERT_THAT(status_or_sender_kem, IsOk()); auto sender_kem = std::move(status_or_sender_kem.value()); // Generating sender's shared secret (using salt_hex1) auto status_or_kem_key = sender_kem->GenerateKey( HashType::SHA256, test::HexDecodeOrDie(salt_hex), test::HexDecodeOrDie(info_hex), out_len, EcPointFormat::COMPRESSED); ASSERT_THAT(status_or_kem_key, IsOk()); auto kem_key = std::move(status_or_kem_key.value()); // Initializing recipient's KEM data structure using recipient's private keys auto status_or_recipient_kem = Cecpq2HkdfRecipientKemBoringSsl::New( EllipticCurveType::CURVE25519, cecpq2_key_pair.x25519_key_pair.priv, std::move(cecpq2_key_pair.hrss_key_pair.hrss_private_key_seed)); ASSERT_THAT(status_or_recipient_kem, IsOk()); auto recipient_kem = std::move(status_or_recipient_kem.value()); // Here, we corrupt kem_bytes (we change all bytes to "a") so that // the HRSS shared secret is not successfully recovered std::string kem_bytes = kem_key->get_kem_bytes(); for (int i = 0; i < HRSS_CIPHERTEXT_BYTES; i++) kem_bytes[X25519_PUBLIC_VALUE_LEN + i] = 'a'; // Generating the defective recipient's shared secret auto status_or_shared_secret = recipient_kem->GenerateKey( kem_bytes, HashType::SHA256, test::HexDecodeOrDie(salt_hex), test::HexDecodeOrDie(info_hex), out_len, EcPointFormat::COMPRESSED); // With very high probability, the shared secrets should not match EXPECT_NE(test::HexEncode( util::SecretDataAsStringView(kem_key->get_symmetric_key())), test::HexEncode( util::SecretDataAsStringView(status_or_shared_secret.value()))); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/kem/subtle/cecpq2_subtle_boringssl_util.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_subtle_boringssl_util.h" #include #include #include "openssl/curve25519.h" #include "openssl/hrss.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/random.h" #include "tink/subtle/subtle_util.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace pqc { crypto::tink::util::StatusOr GenerateHrssKeyPair(util::SecretData hrss_key_entropy) { crypto::tink::pqc::HrssKeyPair hrss_key_pair; hrss_key_pair.hrss_private_key_seed = std::move(hrss_key_entropy); struct HRSS_public_key hrss_public_key; util::SecretUniquePtr hrss_private_key = util::MakeSecretUniquePtr(); // Generating a HRSS key pair HRSS_generate_key(&hrss_public_key, hrss_private_key.get(), hrss_key_pair.hrss_private_key_seed.data()); // Marshalling the HRSS public key crypto::tink::subtle::ResizeStringUninitialized( &(hrss_key_pair.hrss_public_key_marshaled), HRSS_PUBLIC_KEY_BYTES); HRSS_marshal_public_key( const_cast(reinterpret_cast( hrss_key_pair.hrss_public_key_marshaled.data())), &hrss_public_key); return hrss_key_pair; } crypto::tink::util::StatusOr GenerateCecpq2Keypair(subtle::EllipticCurveType curve_type) { crypto::tink::pqc::Cecpq2KeyPair cecpq2_key_pair; // Generating a X25519 key pair cecpq2_key_pair.x25519_key_pair.priv.resize(X25519_PRIVATE_KEY_LEN); subtle::ResizeStringUninitialized(&(cecpq2_key_pair.x25519_key_pair.pub_x), X25519_PUBLIC_VALUE_LEN); X25519_keypair(const_cast(reinterpret_cast( cecpq2_key_pair.x25519_key_pair.pub_x.data())), cecpq2_key_pair.x25519_key_pair.priv.data()); // Generating a HRSS key pair util::SecretData generate_hrss_key_entropy = crypto::tink::subtle::Random::GetRandomKeyBytes(HRSS_GENERATE_KEY_BYTES); auto hrss_key_pair_or_status = GenerateHrssKeyPair(generate_hrss_key_entropy); cecpq2_key_pair.hrss_key_pair = std::move(hrss_key_pair_or_status.value()); return cecpq2_key_pair; } } // namespace pqc } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/kem/subtle/cecpq2_subtle_boringssl_util.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_KEM_SUBTLE_CECPQ2_SUBTLE_BORINGSSL_UTIL_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_KEM_SUBTLE_CECPQ2_SUBTLE_BORINGSSL_UTIL_H_ #include #include "openssl/hrss.h" #include "tink/subtle/common_enums.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace pqc { struct HrssKeyPair { crypto::tink::util::SecretData hrss_private_key_seed; std::string hrss_public_key_marshaled; }; struct EccKeyPair { std::string pub_x; std::string pub_y; util::SecretData priv; }; struct Cecpq2KeyPair { struct HrssKeyPair hrss_key_pair; struct EccKeyPair x25519_key_pair; }; // This is an utility function that generates a new HRSS key pair from a high // entropy seed (hrss_key_entropy). This function is expected to be called from // a key manager class, which will take care of generating a high entropy seed. crypto::tink::util::StatusOr GenerateHrssKeyPair( util::SecretData hrss_key_entropy); // This method performs CECPQ2 (HRSS and X25519) key generation, // and HRSS public key marshaling. crypto::tink::util::StatusOr GenerateCecpq2Keypair(subtle::EllipticCurveType curve_type); } // namespace pqc } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_KEM_SUBTLE_CECPQ2_SUBTLE_BORINGSSL_UTIL_H_ ================================================ FILE: cc/experimental/pqcrypto/kem/subtle/cecpq2_subtle_boringssl_util_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_subtle_boringssl_util.h" #include #include "gtest/gtest.h" #include "openssl/hrss.h" #include "tink/subtle/random.h" #include "tink/subtle/subtle_util.h" #include "tink/util/secret_data.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace pqc { // CECPQ2 test vector from BoringSSL const char kHrssKeyGenEntropy[] = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324" "25262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243444546474849" "4a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e" "6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f90919293" "9495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8" "b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdd" "dedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102" "030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324252627" "28292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c" "4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f7071" "72737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f90919293949596" "9798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babb" "bcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0" "e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405" "060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a" "2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" "505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f7071727374" "75767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f90919293949596979899" "9a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbebfc0" "c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5" "e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a" "0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f" "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f5051525354" "55565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f70717273747576777879" "7a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e" "9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3" "c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8" "e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d" "0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132" "333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f5051525354555657" "58595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c" "7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1" "a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6" "c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaeb" "ecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f10" "1112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435" "363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a" "5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797c7d7e7f8081" "82838485868788898a8b8c8d8e8f909192939495969798999a9b"; const char kExpectedPub[] = "4a21397cb4a658153577e42a0279c002e221275f49c72c14b6e067c2c709620ce5239c40d7" "7ef5555aa2d09fd38c677b48a4538d39b1cc9929f783bf6f9b167323ccc38698b17c53b1f5" "f4ddc8975ed36d63cef3a2f6ef94ed4a3ee64ba2fb87a3bc651c176425a7b4a1e68406720c" "28e8fcaacaf8207989a9f060dfd6d4e0af995421af76d59a3180ea7f036c1474069c93e393" "cc464d82dadf67e96d582b49f31071a0c5eca029d77c43d5057e148c3928f9463dc1106c2f" "aaca11876ae2b1f63176b0dc308a977ddce4d118e90391f5d2944d71f735c83e46afa3eb35" "070177c558ca82673e4f0188a4a0ea0ab71306beb661a4a228e232cf2546cfcef5579b748f" "fdbcfa3aa21822f1b14312e8e2e306e61ca7762d0de55fbd8fa095cde928dbcce56633d44b" "f90c429b27ee11d0e30b9dce2c917a0eb8de3173868e3459932e379dc23e890b47ffa65521" "e64f727ccce5b8182c10cbce48a5c526b61976c538f03872ec22f925de1c0c1b3e43c55c8c" "dbf14266bcdfa0824bece15042578460fd89121bf6f94d0d16e8a4e2672c8f22eaba4634ce" "978b4c380e1682b6f334380787732a3d80564b8567ca2a19b6b62cfed802e5add0617973ab" "da3ba451b3f78599b2d06497b73c0e58dfd29898181af559cdc54817109fd819bdd042711c" "30c676e9b0eef53805be9b6c0db0d0da1c89bd405dc25abe83a6b547a7f8b9bfa265171ed8" "2842beb035f67b8838bef5b51b637a83920d64ad925997555c60ab488e232722753b7c9c69" "13526baefd38e54b36785592b58f25de0e93e31d8362056a5aff7f77f71bfc2145f7b8facb" "005e85f92f152fcf179e84f6f5156eddb47344c22c74ae275f19e75161c182cef15ba06f0b" "131068b7eefb8a85e2d6175526a5c5b39445df49e650f899d83ccb9480673b73acf6463163" "b31b47ce403f8cd082c4793a7c4810e39798dc0b6242fa2605f68c32a9b62c4f85d29bf389" "1f91ca123de2a80bca64280ea7fdd8a3cb0ad9972dc3f23974dbe39a871ae033e392e8deb5" "0828cbd7b679ec71cce5d14b89965ffafd4bd0a8660db4a75156bca774077fae0ef69c13d9" "f2ed12a9873eb79d538a822d032fac948495002909013862ffaffd102b3103b24f51fb7627" "1e2582796569fa24afcbe8408d7dd29a12692fe4ce99984f6c46fd634050ef2202682e53bb" "00a365613e97d45fa2c166cd04dcda5510280d4011e668ed68387d20c3979dcb6e30fcbe63" "e7724705f50b7e663bc53a855aa3c5729db9c1b480986e4086c9cba3ab77c256fccb6e12f5" "6362f8ff9115a7a15eb6ee694d5b5f4efad361caec14fdd910f54a055f29cb772c2de29067" "627875a94e20000c9184baed1ccebd574fa52f596c4cdf5faa32f086091536c6e66a24b4b3" "09dd32c595ac60b5099736a13c8f0e908ecdd04975f7f38080cb1feef26a2f198cba1000da" "13ef102bb7effdd1e07cf84601699b9980511f743b6793185ed4346c817602ef91a4222a23" "1b584375651387986014252867a3348ce0d5d3513368ff65595aa7b26b01ad70067301511b" "e1ec282f8a855a10d00e6b35452e61dd7720b1353ba8dd8ae2157907"; TEST(CreatesNewCecpq2KeyPairTest, GeneratesDifferentKeysEveryTime) { // Generating two HRSS key pairs crypto::tink::util::SecretData hrss_key_entropy1 = crypto::tink::subtle::Random::GetRandomKeyBytes(HRSS_GENERATE_KEY_BYTES); auto keypair1 = crypto::tink::pqc::GenerateHrssKeyPair(hrss_key_entropy1); crypto::tink::util::SecretData hrss_key_entropy2 = crypto::tink::subtle::Random::GetRandomKeyBytes(HRSS_GENERATE_KEY_BYTES); auto keypair2 = crypto::tink::pqc::GenerateHrssKeyPair(hrss_key_entropy2); std::string keypair1_pub_marsh_str( reinterpret_cast( keypair1.value().hrss_public_key_marshaled.data()), HRSS_PUBLIC_KEY_BYTES); std::string keypair2_pub_marsh_str( reinterpret_cast( keypair2.value().hrss_public_key_marshaled.data()), HRSS_PUBLIC_KEY_BYTES); // the two HRSS key pairs should be different with very high probability EXPECT_NE(keypair1_pub_marsh_str, keypair2_pub_marsh_str); } TEST(CreatesNewCecpq2KeyPairTest, SuccessfullHrssKeyGen) { // Generating HRSS key pair from BoringSSL test vector std::string hrss_key_gen_entropy_str( reinterpret_cast( test::HexDecodeOrDie(kHrssKeyGenEntropy).data()), HRSS_GENERATE_KEY_BYTES); util::SecretData hrss_key_gen_entropy = util::SecretDataFromStringView(hrss_key_gen_entropy_str); auto keypair = crypto::tink::pqc::GenerateHrssKeyPair(hrss_key_gen_entropy); // Checking that the generated HRSS public key matched the test vector one EXPECT_EQ(test::HexEncode(keypair.value().hrss_public_key_marshaled), kExpectedPub); } } // namespace pqc } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/kem/util/BUILD.bazel ================================================ # package containing useful functions for hybrid encryption PQC primitives package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "test_util", testonly = 1, srcs = ["test_util.cc"], hdrs = ["test_util.h"], include_prefix = "tink/experimental/pqcrypto/kem/util", deps = [ "//aead:aes_ctr_hmac_aead_key_manager", "//aead:aes_gcm_key_manager", "//aead:xchacha20_poly1305_key_manager", "//experimental/pqcrypto/kem/subtle:cecpq2_subtle_boringssl_util", "//experimental/pqcrypto/proto:cecpq2_aead_hkdf_cc_proto", "//proto:aes_ctr_cc_proto", "//proto:aes_ctr_hmac_aead_cc_proto", "//proto:hmac_cc_proto", "//proto:xchacha20_poly1305_cc_proto", "//subtle:subtle_util", "//util:enums", "@boringssl//:crypto", ], ) #tests cc_test( name = "test_util_test", srcs = ["test_util_test.cc"], deps = [ ":test_util", "//:hybrid_encrypt", "//:registry", "//aead:aes_gcm_key_manager", "//experimental/pqcrypto/proto:cecpq2_aead_hkdf_cc_proto", "//proto:aes_eax_cc_proto", "//proto:common_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/experimental/pqcrypto/kem/util/test_util.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/kem/util/test_util.h" #include #include #include #include #include "openssl/curve25519.h" #include "openssl/hrss.h" #include "tink/aead/aes_ctr_hmac_aead_key_manager.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/aead/xchacha20_poly1305_key_manager.h" #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_subtle_boringssl_util.h" #include "tink/subtle/subtle_util.h" #include "tink/util/enums.h" #include "proto/aes_ctr.pb.h" #include "proto/aes_ctr_hmac_aead.pb.h" #include "proto/aes_gcm.pb.h" #include "proto/common.pb.h" #include "proto/hmac.pb.h" #include "proto/xchacha20_poly1305.pb.h" namespace crypto { namespace tink { namespace test { google::crypto::tink::Cecpq2AeadHkdfPrivateKey GetCecpq2AeadHkdfTestKey( google::crypto::tink::EllipticCurveType curve_type, google::crypto::tink::EcPointFormat ec_point_format, google::crypto::tink::HashType hash_type) { google::crypto::tink::Cecpq2AeadHkdfPrivateKey cecpq2_key_pair_proto; cecpq2_key_pair_proto.set_version(0); auto cecpq2_key_pair_or_status = pqc::GenerateCecpq2Keypair(util::Enums::ProtoToSubtle(curve_type)); auto cecpq2_key_pair = std::move(cecpq2_key_pair_or_status.value()); std::string hrss_priv_key_seed_str( reinterpret_cast( cecpq2_key_pair.hrss_key_pair.hrss_private_key_seed.data()), HRSS_GENERATE_KEY_BYTES); cecpq2_key_pair_proto.set_hrss_private_key_seed(hrss_priv_key_seed_str); cecpq2_key_pair_proto.set_x25519_private_key( std::string(reinterpret_cast( cecpq2_key_pair.x25519_key_pair.priv.data()), X25519_PRIVATE_KEY_LEN)); auto public_key = cecpq2_key_pair_proto.mutable_public_key(); public_key->set_version(0); public_key->set_x25519_public_key_x(cecpq2_key_pair.x25519_key_pair.pub_x); public_key->set_x25519_public_key_y(cecpq2_key_pair.x25519_key_pair.pub_y); public_key->set_hrss_public_key_marshalled( cecpq2_key_pair.hrss_key_pair.hrss_public_key_marshaled); auto params = public_key->mutable_params(); params->mutable_kem_params()->set_ec_point_format(ec_point_format); params->mutable_kem_params()->set_curve_type(curve_type); params->mutable_kem_params()->set_hkdf_hash_type(hash_type); return cecpq2_key_pair_proto; } google::crypto::tink::Cecpq2AeadHkdfPrivateKey GetCecpq2AesGcmHkdfTestKey( google::crypto::tink::EllipticCurveType curve_type, google::crypto::tink::EcPointFormat ec_point_format, google::crypto::tink::HashType hash_type, uint32_t aes_gcm_key_size) { auto cecpq2_key = GetCecpq2AeadHkdfTestKey(curve_type, ec_point_format, hash_type); auto params = cecpq2_key.mutable_public_key()->mutable_params(); google::crypto::tink::AesGcmKeyFormat key_format; key_format.set_key_size(aes_gcm_key_size); auto aead_dem = params->mutable_dem_params()->mutable_aead_dem(); std::unique_ptr key_manager(new AesGcmKeyManager()); std::string dem_key_type = key_manager->get_key_type(); aead_dem->set_type_url(dem_key_type); aead_dem->set_value(key_format.SerializeAsString()); return cecpq2_key; } google::crypto::tink::Cecpq2AeadHkdfPrivateKey GetCecpq2AesCtrHmacHkdfTestKey( google::crypto::tink::EllipticCurveType curve_type, google::crypto::tink::EcPointFormat ec_point_format, google::crypto::tink::HashType hash_type, uint32_t aes_ctr_key_size, uint32_t aes_ctr_iv_size, google::crypto::tink::HashType hmac_hash_type, uint32_t hmac_tag_size, uint32_t hmac_key_size) { auto ecies_key = GetCecpq2AeadHkdfTestKey(curve_type, ec_point_format, hash_type); google::crypto::tink::AesCtrHmacAeadKeyFormat key_format; auto aes_ctr_key_format = key_format.mutable_aes_ctr_key_format(); auto aes_ctr_params = aes_ctr_key_format->mutable_params(); aes_ctr_params->set_iv_size(aes_ctr_iv_size); aes_ctr_key_format->set_key_size(aes_ctr_key_size); auto hmac_key_format = key_format.mutable_hmac_key_format(); auto hmac_params = hmac_key_format->mutable_params(); hmac_params->set_hash(hmac_hash_type); hmac_params->set_tag_size(hmac_tag_size); hmac_key_format->set_key_size(hmac_key_size); auto params = ecies_key.mutable_public_key()->mutable_params(); auto aead_dem = params->mutable_dem_params()->mutable_aead_dem(); std::unique_ptr key_manager( new AesCtrHmacAeadKeyManager()); std::string dem_key_type = key_manager->get_key_type(); aead_dem->set_type_url(dem_key_type); aead_dem->set_value(key_format.SerializeAsString()); return ecies_key; } google::crypto::tink::Cecpq2AeadHkdfPrivateKey GetCecpq2XChaCha20Poly1305HkdfTestKey( google::crypto::tink::EllipticCurveType curve_type, google::crypto::tink::EcPointFormat ec_point_format, google::crypto::tink::HashType hash_type) { auto ecies_key = GetCecpq2AeadHkdfTestKey(curve_type, ec_point_format, hash_type); auto params = ecies_key.mutable_public_key()->mutable_params(); google::crypto::tink::XChaCha20Poly1305KeyFormat key_format; auto aead_dem = params->mutable_dem_params()->mutable_aead_dem(); std::unique_ptr key_manager( new XChaCha20Poly1305KeyManager()); std::string dem_key_type = key_manager->get_key_type(); aead_dem->set_type_url(dem_key_type); aead_dem->set_value(key_format.SerializeAsString()); return ecies_key; } } // namespace test } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/kem/util/test_util.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_KEM_UTIL_TEST_UTIL_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_KEM_UTIL_TEST_UTIL_H_ #include #include "proto/experimental/pqcrypto/cecpq2_aead_hkdf.pb.h" namespace crypto { namespace tink { namespace test { google::crypto::tink::Cecpq2AeadHkdfPrivateKey GetCecpq2AeadHkdfTestKey( google::crypto::tink::EllipticCurveType curve_type, google::crypto::tink::EcPointFormat ec_point_format, google::crypto::tink::HashType hash_type); google::crypto::tink::Cecpq2AeadHkdfPrivateKey GetCecpq2AesGcmHkdfTestKey( google::crypto::tink::EllipticCurveType curve_type, google::crypto::tink::EcPointFormat ec_point_format, google::crypto::tink::HashType hash_type, uint32_t aes_gcm_key_size); google::crypto::tink::Cecpq2AeadHkdfPrivateKey GetCecpq2AesCtrHmacHkdfTestKey( google::crypto::tink::EllipticCurveType curve_type, google::crypto::tink::EcPointFormat ec_point_format, google::crypto::tink::HashType hash_type, uint32_t aes_ctr_key_size, uint32_t aes_ctr_iv_size, google::crypto::tink::HashType hmac_hash_type, uint32_t hmac_tag_size, uint32_t hmac_key_size); google::crypto::tink::Cecpq2AeadHkdfPrivateKey GetCecpq2XChaCha20Poly1305HkdfTestKey( google::crypto::tink::EllipticCurveType curve_type, google::crypto::tink::EcPointFormat ec_point_format, google::crypto::tink::HashType hash_type); } // namespace test } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_KEM_UTIL_TEST_UTIL_H_ ================================================ FILE: cc/experimental/pqcrypto/kem/util/test_util_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/kem/util/test_util.h" #include #include #include "gtest/gtest.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/hybrid_encrypt.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_eax.pb.h" #include "proto/common.pb.h" #include "proto/experimental/pqcrypto/cecpq2_aead_hkdf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using google::crypto::tink::EcPointFormat; using google::crypto::tink::EllipticCurveType; using google::crypto::tink::HashType; struct CommonHybridKeyParams { EllipticCurveType ec_curve; EcPointFormat ec_point_format; HashType hash_type; }; std::vector GetCommonHybridKeyParamsList() { std::vector params_list; for (auto ec_curve : {EllipticCurveType::CURVE25519}) { for (auto ec_point_format : {EcPointFormat::COMPRESSED}) { for (auto hash_type : {HashType::SHA256, HashType::SHA512}) { CommonHybridKeyParams params; params.ec_curve = ec_curve; params.ec_point_format = ec_point_format; params.hash_type = hash_type; params_list.push_back(params); } } } return params_list; } TEST(TestUtilTest, GetCecpq2AeadHkdfTestKeyBasics) { auto curve_type = EllipticCurveType::CURVE25519; auto ec_point_format = EcPointFormat::COMPRESSED; auto hkdf_hash_type = HashType::SHA384; auto cecpq2_key = test::GetCecpq2AeadHkdfTestKey(curve_type, ec_point_format, hkdf_hash_type); auto params = cecpq2_key.mutable_public_key()->mutable_params(); EXPECT_EQ(params->mutable_kem_params()->curve_type(), curve_type); EXPECT_EQ(params->mutable_kem_params()->ec_point_format(), ec_point_format); EXPECT_EQ(params->mutable_kem_params()->hkdf_hash_type(), hkdf_hash_type); } TEST(TestUtilTest, GetCecpq2AesGcmHkdfTestKeyBasics) { auto curve_type = EllipticCurveType::CURVE25519; auto ec_point_format = EcPointFormat::COMPRESSED; auto hkdf_hash_type = HashType::SHA384; auto aes_gcm_key_size = 32; auto cecpq2_key = test::GetCecpq2AesGcmHkdfTestKey( curve_type, ec_point_format, hkdf_hash_type, aes_gcm_key_size); auto params = cecpq2_key.mutable_public_key()->mutable_params(); EXPECT_EQ(params->mutable_kem_params()->curve_type(), curve_type); EXPECT_EQ(params->mutable_kem_params()->ec_point_format(), ec_point_format); EXPECT_EQ(params->mutable_kem_params()->hkdf_hash_type(), hkdf_hash_type); } TEST(TestUtilTest, GetCecpq2AesCtrHmacHkdfTestKeyBasics) { auto curve_type = EllipticCurveType::CURVE25519; auto ec_point_format = EcPointFormat::COMPRESSED; auto hmac_hash_type = HashType::SHA384; uint32_t aes_ctr_iv_size = 16; // Generate and test many keys with various parameters for (auto key_params : GetCommonHybridKeyParamsList()) { for (uint32_t aes_ctr_key_size : {16, 32}) { for (uint32_t hmac_tag_size : {16, 32}) { for (uint32_t hmac_key_size : {16, 32}) { auto cecpq2_key = test::GetCecpq2AesCtrHmacHkdfTestKey( key_params.ec_curve, key_params.ec_point_format, key_params.hash_type, aes_ctr_key_size, aes_ctr_iv_size, hmac_hash_type, hmac_tag_size, hmac_key_size); auto params = cecpq2_key.mutable_public_key()->mutable_params(); EXPECT_EQ(params->mutable_kem_params()->curve_type(), curve_type); EXPECT_EQ(params->mutable_kem_params()->ec_point_format(), ec_point_format); } } } } } TEST(TestUtilTest, GetCecpq2XChaCha20Poly1305HkdfTestKeyBasics) { auto curve_type = EllipticCurveType::CURVE25519; auto ec_point_format = EcPointFormat::COMPRESSED; auto hkdf_hash_type = HashType::SHA384; auto cecpq2_key = test::GetCecpq2XChaCha20Poly1305HkdfTestKey( curve_type, ec_point_format, hkdf_hash_type); auto params = cecpq2_key.mutable_public_key()->mutable_params(); EXPECT_EQ(params->mutable_kem_params()->curve_type(), curve_type); EXPECT_EQ(params->mutable_kem_params()->ec_point_format(), ec_point_format); EXPECT_EQ(params->mutable_kem_params()->hkdf_hash_type(), hkdf_hash_type); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/proto/BUILD.bazel ================================================ # Package containing C++ protos for experimental PQC primitives. package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) # ---------------------------------------- # cc_proto_library rules. # ---------------------------------------- cc_proto_library( name = "cecpq2_aead_hkdf_cc_proto", visibility = ["//visibility:public"], deps = ["//proto/experimental/pqcrypto:cecpq2_aead_hkdf_proto"], ) ================================================ FILE: cc/experimental/pqcrypto/signature/dilithium_key_template.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/dilithium_key_template.h" #include #include "absl/strings/str_cat.h" #include "tink/util/constants.h" #include "proto/experimental/pqcrypto/dilithium.pb.h" #include "proto/tink.pb.h" extern "C" { #include "third_party/pqclean/crypto_sign/dilithium2/api.h" #include "third_party/pqclean/crypto_sign/dilithium2aes/api.h" #include "third_party/pqclean/crypto_sign/dilithium3/api.h" #include "third_party/pqclean/crypto_sign/dilithium3aes/api.h" #include "third_party/pqclean/crypto_sign/dilithium5/api.h" #include "third_party/pqclean/crypto_sign/dilithium5aes/api.h" } namespace crypto { namespace tink { namespace { using google::crypto::tink::DilithiumKeyFormat; using google::crypto::tink::DilithiumParams; using google::crypto::tink::DilithiumPrivateKey; using google::crypto::tink::DilithiumSeedExpansion; using google::crypto::tink::KeyTemplate; using google::crypto::tink::OutputPrefixType; KeyTemplate* NewDilithiumKeyTemplate(int32_t key_size, DilithiumSeedExpansion seed_expansion) { KeyTemplate* key_template = new KeyTemplate; key_template->set_type_url( absl::StrCat(kTypeGoogleapisCom, DilithiumPrivateKey().GetTypeName())); key_template->set_output_prefix_type(OutputPrefixType::TINK); DilithiumKeyFormat key_format; DilithiumParams* params = key_format.mutable_params(); params->set_key_size(key_size); params->set_seed_expansion(seed_expansion); key_format.SerializeToString(key_template->mutable_value()); return key_template; } } // anonymous namespace const google::crypto::tink::KeyTemplate& Dilithium2KeyTemplate() { static const KeyTemplate* key_template = NewDilithiumKeyTemplate(PQCLEAN_DILITHIUM2_CRYPTO_SECRETKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE); return *key_template; } const google::crypto::tink::KeyTemplate& Dilithium3KeyTemplate() { static const KeyTemplate* key_template = NewDilithiumKeyTemplate(PQCLEAN_DILITHIUM3_CRYPTO_SECRETKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE); return *key_template; } const google::crypto::tink::KeyTemplate& Dilithium5KeyTemplate() { static const KeyTemplate* key_template = NewDilithiumKeyTemplate(PQCLEAN_DILITHIUM5_CRYPTO_SECRETKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE); return *key_template; } const google::crypto::tink::KeyTemplate& Dilithium2AesKeyTemplate() { static const KeyTemplate* key_template = NewDilithiumKeyTemplate(PQCLEAN_DILITHIUM2AES_CRYPTO_SECRETKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_AES); return *key_template; } const google::crypto::tink::KeyTemplate& Dilithium3AesKeyTemplate() { static const KeyTemplate* key_template = NewDilithiumKeyTemplate(PQCLEAN_DILITHIUM3AES_CRYPTO_SECRETKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_AES); return *key_template; } const google::crypto::tink::KeyTemplate& Dilithium5AesKeyTemplate() { static const KeyTemplate* key_template = NewDilithiumKeyTemplate(PQCLEAN_DILITHIUM5AES_CRYPTO_SECRETKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_AES); return *key_template; } } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/dilithium_key_template.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_DILITHIUM_KEY_TEMPLATE_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_DILITHIUM_KEY_TEMPLATE_H_ #include "proto/tink.pb.h" namespace crypto { namespace tink { // Returns a KeyTemplate that generates new instances of DilithiumPrivateKey. const google::crypto::tink::KeyTemplate& Dilithium2KeyTemplate(); const google::crypto::tink::KeyTemplate& Dilithium3KeyTemplate(); const google::crypto::tink::KeyTemplate& Dilithium5KeyTemplate(); const google::crypto::tink::KeyTemplate& Dilithium2AesKeyTemplate(); const google::crypto::tink::KeyTemplate& Dilithium3AesKeyTemplate(); const google::crypto::tink::KeyTemplate& Dilithium5AesKeyTemplate(); } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_DILITHIUM_KEY_TEMPLATE_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/dilithium_key_template_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/dilithium_key_template.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/core/key_manager_impl.h" #include "tink/core/private_key_manager_impl.h" #include "tink/experimental/pqcrypto/signature/dilithium_sign_key_manager.h" #include "tink/experimental/pqcrypto/signature/dilithium_verify_key_manager.h" #include "tink/key_manager.h" #include "tink/public_key_sign.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/experimental/pqcrypto/dilithium.pb.h" #include "proto/tink.pb.h" extern "C" { #include "third_party/pqclean/crypto_sign/dilithium2/api.h" #include "third_party/pqclean/crypto_sign/dilithium2aes/api.h" #include "third_party/pqclean/crypto_sign/dilithium3/api.h" #include "third_party/pqclean/crypto_sign/dilithium3aes/api.h" #include "third_party/pqclean/crypto_sign/dilithium5/api.h" #include "third_party/pqclean/crypto_sign/dilithium5aes/api.h" } namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::google::crypto::tink::DilithiumKeyFormat; using ::google::crypto::tink::DilithiumParams; using ::google::crypto::tink::DilithiumPrivateKey; using ::google::crypto::tink::DilithiumSeedExpansion; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::OutputPrefixType; struct DilithiumKeyTemplateTestCase { std::string test_name; int32_t key_size; DilithiumSeedExpansion seed_expansion; KeyTemplate key_template; }; using DilithiumKeyTemplateTest = testing::TestWithParam; TEST_P(DilithiumKeyTemplateTest, CheckDilithiumInitialization) { std::string type_url = "type.googleapis.com/google.crypto.tink.DilithiumPrivateKey"; const KeyTemplate& key_template = GetParam().key_template; EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); } TEST_P(DilithiumKeyTemplateTest, ValidateKeyFormat) { const DilithiumKeyTemplateTestCase& test_case = GetParam(); DilithiumKeyFormat key_format; DilithiumParams* params = key_format.mutable_params(); params->set_key_size(test_case.key_size); params->set_seed_expansion(test_case.seed_expansion); EXPECT_THAT(DilithiumSignKeyManager().ValidateKeyFormat(key_format), IsOk()); EXPECT_TRUE(key_format.ParseFromString(test_case.key_template.value())); } TEST_P(DilithiumKeyTemplateTest, SameReference) { const KeyTemplate& key_template = GetParam().key_template; const KeyTemplate& key_template_2 = GetParam().key_template; EXPECT_EQ(&key_template, &key_template_2); } TEST_P(DilithiumKeyTemplateTest, KeyManagerCompatibility) { DilithiumSignKeyManager sign_key_manager; DilithiumVerifyKeyManager verify_key_manager; std::unique_ptr> key_manager = internal::MakePrivateKeyManager(&sign_key_manager, &verify_key_manager); DilithiumKeyFormat key_format; const DilithiumKeyTemplateTestCase& test_case = GetParam(); DilithiumParams* params = key_format.mutable_params(); params->set_key_size(test_case.key_size); params->set_seed_expansion(test_case.seed_expansion); util::StatusOr> new_key_result = key_manager->get_key_factory().NewKey(key_format); EXPECT_THAT(new_key_result, IsOk()); } INSTANTIATE_TEST_SUITE_P( DilithiumKeyTemplateTests, DilithiumKeyTemplateTest, testing::ValuesIn( {{"Dilithium2", PQCLEAN_DILITHIUM2_CRYPTO_SECRETKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE, Dilithium2KeyTemplate()}, {"Dilithium3", PQCLEAN_DILITHIUM3_CRYPTO_SECRETKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE, Dilithium3KeyTemplate()}, {"Dilithium5", PQCLEAN_DILITHIUM5_CRYPTO_SECRETKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE, Dilithium5KeyTemplate()}, {"Dilithium2Aes", PQCLEAN_DILITHIUM2AES_CRYPTO_SECRETKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_AES, Dilithium2AesKeyTemplate()}, {"Dilithium3Aes", PQCLEAN_DILITHIUM3AES_CRYPTO_SECRETKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_AES, Dilithium3AesKeyTemplate()}, {"Dilithium5Aes", PQCLEAN_DILITHIUM5AES_CRYPTO_SECRETKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_AES, Dilithium5AesKeyTemplate()}}), [](const testing::TestParamInfo& info) { return info.param.test_name; }); } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/dilithium_sign_key_manager.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/dilithium_sign_key_manager.h" #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/experimental/pqcrypto/signature/dilithium_verify_key_manager.h" #include "tink/experimental/pqcrypto/signature/subtle/dilithium_avx2_sign.h" #include "tink/experimental/pqcrypto/signature/subtle/dilithium_key.h" #include "tink/experimental/pqcrypto/signature/util/enums.h" #include "tink/public_key_sign.h" #include "tink/util/errors.h" #include "tink/util/input_stream_util.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" extern "C" { #include "third_party/pqclean/crypto_sign/dilithium2/api.h" #include "third_party/pqclean/crypto_sign/dilithium3/api.h" #include "third_party/pqclean/crypto_sign/dilithium5/api.h" } namespace crypto { namespace tink { using ::crypto::tink::subtle::DilithiumPrivateKeyPqclean; using ::crypto::tink::subtle::DilithiumPublicKeyPqclean; using ::crypto::tink::util::EnumsPqcrypto; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::DilithiumKeyFormat; using ::google::crypto::tink::DilithiumPrivateKey; using ::google::crypto::tink::DilithiumPublicKey; StatusOr DilithiumSignKeyManager::CreateKey( const DilithiumKeyFormat& key_format) const { DilithiumPrivateKey dilithium_sk; dilithium_sk.set_version(get_version()); DilithiumPublicKey* dilithium_pk = dilithium_sk.mutable_public_key(); dilithium_pk->set_version(get_version()); util::StatusOr< std::pair> key_pair = DilithiumPrivateKeyPqclean::GenerateKeyPair( key_format.params().key_size(), EnumsPqcrypto::ProtoToSubtle(key_format.params().seed_expansion())); if (!key_pair.status().ok()) { return key_pair.status(); } dilithium_sk.set_key_value( util::SecretDataAsStringView(key_pair->first.GetKeyData())); dilithium_pk->set_key_value(key_pair->second.GetKeyData()); *(dilithium_pk->mutable_params()) = key_format.params(); return dilithium_sk; } StatusOr> DilithiumSignKeyManager::PublicKeySignFactory::Create( const DilithiumPrivateKey& private_key) const { util::SecretData sk_data = util::SecretDataFromStringView(private_key.key_value()); util::StatusOr dilithium_private_key = DilithiumPrivateKeyPqclean::NewPrivateKey( sk_data, EnumsPqcrypto::ProtoToSubtle( private_key.public_key().params().seed_expansion())); if (!dilithium_private_key.ok()) return dilithium_private_key.status(); return subtle::DilithiumAvx2Sign::New(*dilithium_private_key); } Status DilithiumSignKeyManager::ValidateKey( const DilithiumPrivateKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; if (key.key_value().length() != PQCLEAN_DILITHIUM2_CRYPTO_SECRETKEYBYTES && key.key_value().length() != PQCLEAN_DILITHIUM3_CRYPTO_SECRETKEYBYTES && key.key_value().length() != PQCLEAN_DILITHIUM5_CRYPTO_SECRETKEYBYTES) { return Status(absl::StatusCode::kInvalidArgument, "Invalid dilithium private key size."); } return util::OkStatus(); } Status DilithiumSignKeyManager::ValidateKeyFormat( const DilithiumKeyFormat& key_format) const { if (!key_format.has_params()) { return Status(absl::StatusCode::kInvalidArgument, "Missing params."); } return DilithiumVerifyKeyManager().ValidateParams(key_format.params()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/dilithium_sign_key_manager.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_DILITHIUM_SIGN_KEY_MANAGER_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_DILITHIUM_SIGN_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/public_key_sign.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/input_stream_util.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/experimental/pqcrypto/dilithium.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class DilithiumSignKeyManager : public PrivateKeyTypeManager> { public: class PublicKeySignFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::DilithiumPrivateKey& private_key) const override; }; DilithiumSignKeyManager() : PrivateKeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::DilithiumPrivateKey& key) const override; crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::DilithiumKeyFormat& key_format) const override; crypto::tink::util::StatusOr CreateKey(const google::crypto::tink::DilithiumKeyFormat& key_format) const override; crypto::tink::util::StatusOr GetPublicKey(const google::crypto::tink::DilithiumPrivateKey& private_key) const override { return private_key.public_key(); } private: const std::string key_type_ = absl::StrCat(kTypeGoogleapisCom, google::crypto::tink::DilithiumPrivateKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_DILITHIUM_SIGN_KEY_MANAGER_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/dilithium_sign_key_manager_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/dilithium_sign_key_manager.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_set.h" #include "absl/strings/str_cat.h" #include "tink/experimental/pqcrypto/signature/subtle/dilithium_avx2_sign.h" #include "tink/experimental/pqcrypto/signature/subtle/dilithium_avx2_verify.h" #include "tink/experimental/pqcrypto/signature/subtle/dilithium_key.h" #include "tink/experimental/pqcrypto/signature/util/enums.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/experimental/pqcrypto/dilithium.pb.h" #include "proto/tink.pb.h" extern "C" { #include "third_party/pqclean/crypto_sign/dilithium2/api.h" #include "third_party/pqclean/crypto_sign/dilithium2aes/api.h" #include "third_party/pqclean/crypto_sign/dilithium3/api.h" #include "third_party/pqclean/crypto_sign/dilithium3aes/api.h" #include "third_party/pqclean/crypto_sign/dilithium5/api.h" #include "third_party/pqclean/crypto_sign/dilithium5aes/api.h" } namespace crypto { namespace tink { namespace { using ::crypto::tink::subtle::DilithiumPublicKeyPqclean; using ::crypto::tink::test::IsOk; using ::crypto::tink::util::EnumsPqcrypto; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::DilithiumKeyFormat; using ::google::crypto::tink::DilithiumParams; using ::google::crypto::tink::DilithiumPrivateKey; using ::google::crypto::tink::DilithiumPublicKey; using ::google::crypto::tink::DilithiumSeedExpansion; using ::google::crypto::tink::KeyData; using ::testing::Eq; using ::testing::Not; using ::testing::SizeIs; struct DilithiumTestCase { std::string test_name; int32_t private_key_size; int32_t public_key_size; DilithiumSeedExpansion seed_expansion; }; using DilithiumSignKeyManagerTest = testing::TestWithParam; // Helper function that returns a valid dilithium key format. StatusOr CreateValidKeyFormat( int32_t private_key_size, DilithiumSeedExpansion seed_expansion) { DilithiumKeyFormat key_format; DilithiumParams* params = key_format.mutable_params(); params->set_key_size(private_key_size); params->set_seed_expansion(seed_expansion); return key_format; } TEST(DilithiumSignKeyManagerTest, Basic) { EXPECT_THAT(DilithiumSignKeyManager().get_version(), Eq(0)); EXPECT_THAT(DilithiumSignKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PRIVATE)); EXPECT_THAT(DilithiumSignKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.DilithiumPrivateKey")); } TEST_P(DilithiumSignKeyManagerTest, ValidateKeyFormat) { const DilithiumTestCase& test_case = GetParam(); StatusOr key_format = CreateValidKeyFormat( test_case.private_key_size, test_case.seed_expansion); ASSERT_THAT(key_format, IsOk()); EXPECT_THAT(DilithiumSignKeyManager().ValidateKeyFormat(*key_format), IsOk()); } TEST_P(DilithiumSignKeyManagerTest, PrivateKeyWrongVersion) { const DilithiumTestCase& test_case = GetParam(); StatusOr key_format = CreateValidKeyFormat( test_case.private_key_size, test_case.seed_expansion); ASSERT_THAT(key_format, IsOk()); StatusOr private_key = DilithiumSignKeyManager().CreateKey(*key_format); ASSERT_THAT(private_key, IsOk()); private_key->set_version(1); EXPECT_THAT(DilithiumSignKeyManager().ValidateKey(*private_key), Not(IsOk())); } TEST_P(DilithiumSignKeyManagerTest, CreateKey) { const DilithiumTestCase& test_case = GetParam(); StatusOr key_format = CreateValidKeyFormat( test_case.private_key_size, test_case.seed_expansion); ASSERT_THAT(key_format, IsOk()); StatusOr private_key = DilithiumSignKeyManager().CreateKey(*key_format); ASSERT_THAT(private_key, IsOk()); EXPECT_THAT(private_key->version(), Eq(0)); EXPECT_THAT(private_key->public_key().version(), Eq(private_key->version())); EXPECT_THAT(private_key->key_value(), SizeIs(test_case.private_key_size)); EXPECT_THAT(private_key->public_key().key_value(), SizeIs(test_case.public_key_size)); } TEST_P(DilithiumSignKeyManagerTest, CreateKeyValid) { const DilithiumTestCase& test_case = GetParam(); StatusOr key_format = CreateValidKeyFormat( test_case.private_key_size, test_case.seed_expansion); ASSERT_THAT(key_format, IsOk()); StatusOr private_key = DilithiumSignKeyManager().CreateKey(*key_format); ASSERT_THAT(private_key, IsOk()); EXPECT_THAT(DilithiumSignKeyManager().ValidateKey(*private_key), IsOk()); } TEST_P(DilithiumSignKeyManagerTest, CreateKeyAlwaysNew) { const DilithiumTestCase& test_case = GetParam(); StatusOr key_format = CreateValidKeyFormat( test_case.private_key_size, test_case.seed_expansion); ASSERT_THAT(key_format, IsOk()); absl::flat_hash_set keys; int num_tests = 100; for (int i = 0; i < num_tests; ++i) { StatusOr private_key = DilithiumSignKeyManager().CreateKey(*key_format); ASSERT_THAT(private_key, IsOk()); keys.insert(private_key->key_value()); } EXPECT_THAT(keys, SizeIs(num_tests)); } TEST_P(DilithiumSignKeyManagerTest, GetPublicKey) { const DilithiumTestCase& test_case = GetParam(); StatusOr key_format = CreateValidKeyFormat( test_case.private_key_size, test_case.seed_expansion); ASSERT_THAT(key_format, IsOk()); StatusOr private_key = DilithiumSignKeyManager().CreateKey(*key_format); ASSERT_THAT(private_key, IsOk()); StatusOr public_key_or = DilithiumSignKeyManager().GetPublicKey(*private_key); ASSERT_THAT(public_key_or, IsOk()); EXPECT_THAT(public_key_or->version(), Eq(private_key->public_key().version())); EXPECT_THAT(public_key_or->key_value(), Eq(private_key->public_key().key_value())); } TEST_P(DilithiumSignKeyManagerTest, Create) { const DilithiumTestCase& test_case = GetParam(); StatusOr key_format = CreateValidKeyFormat( test_case.private_key_size, test_case.seed_expansion); ASSERT_THAT(key_format, IsOk()); util::StatusOr private_key = DilithiumSignKeyManager().CreateKey(*key_format); ASSERT_THAT(private_key, IsOk()); util::StatusOr> signer = DilithiumSignKeyManager().GetPrimitive(*private_key); ASSERT_THAT(signer, IsOk()); util::StatusOr dilithium_public_key = DilithiumPublicKeyPqclean::NewPublicKey( private_key->public_key().key_value(), EnumsPqcrypto::ProtoToSubtle(test_case.seed_expansion)); util::StatusOr> verifier = subtle::DilithiumAvx2Verify::New(*dilithium_public_key); ASSERT_THAT(verifier, IsOk()); std::string message = "Some message"; util::StatusOr signature = (*signer)->Sign(message); ASSERT_THAT(signature, IsOk()); EXPECT_THAT((*verifier)->Verify(*signature, message), IsOk()); } TEST_P(DilithiumSignKeyManagerTest, CreateDifferentKey) { const DilithiumTestCase& test_case = GetParam(); StatusOr key_format = CreateValidKeyFormat( test_case.private_key_size, test_case.seed_expansion); ASSERT_THAT(key_format, IsOk()); util::StatusOr private_key = DilithiumSignKeyManager().CreateKey(*key_format); ASSERT_THAT(private_key, IsOk()); util::StatusOr> signer = DilithiumSignKeyManager().GetPrimitive(*private_key); ASSERT_THAT(signer, IsOk()); std::string bad_public_key_data(test_case.public_key_size, '@'); util::StatusOr dilithium_public_key = DilithiumPublicKeyPqclean::NewPublicKey( bad_public_key_data, EnumsPqcrypto::ProtoToSubtle(test_case.seed_expansion)); util::StatusOr> verifier = subtle::DilithiumAvx2Verify::New(*dilithium_public_key); ASSERT_THAT(verifier, IsOk()); std::string message = "Some message"; util::StatusOr signature = (*signer)->Sign(message); ASSERT_THAT(signature, IsOk()); EXPECT_THAT((*verifier)->Verify(*signature, message), Not(IsOk())); } INSTANTIATE_TEST_SUITE_P( DilithiumSignKeyManagerTests, DilithiumSignKeyManagerTest, testing::ValuesIn({ {"Dilithium2", PQCLEAN_DILITHIUM2_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM2_CRYPTO_PUBLICKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE}, {"Dilithium3", PQCLEAN_DILITHIUM3_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM3_CRYPTO_PUBLICKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE}, {"Dilithium5", PQCLEAN_DILITHIUM5_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM5_CRYPTO_PUBLICKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE}, {"Dilithium2Aes", PQCLEAN_DILITHIUM2AES_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM2AES_CRYPTO_PUBLICKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_AES}, {"Dilithium3Aes", PQCLEAN_DILITHIUM3AES_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM3AES_CRYPTO_PUBLICKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_AES}, {"Dilithium5Aes", PQCLEAN_DILITHIUM5AES_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM5AES_CRYPTO_PUBLICKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_AES}, }), [](const testing::TestParamInfo& info) { return info.param.test_name; }); } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/dilithium_verify_key_manager.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/dilithium_verify_key_manager.h" #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/experimental/pqcrypto/signature/subtle/dilithium_avx2_verify.h" #include "tink/experimental/pqcrypto/signature/subtle/dilithium_key.h" #include "tink/experimental/pqcrypto/signature/util/enums.h" #include "tink/public_key_verify.h" #include "tink/util/errors.h" #include "tink/util/input_stream_util.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" extern "C" { #include "third_party/pqclean/crypto_sign/dilithium2/api.h" #include "third_party/pqclean/crypto_sign/dilithium3/api.h" #include "third_party/pqclean/crypto_sign/dilithium5/api.h" } namespace crypto { namespace tink { using ::crypto::tink::subtle::DilithiumPublicKeyPqclean; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::DilithiumParams; using ::google::crypto::tink::DilithiumPublicKey; using ::google::crypto::tink::DilithiumSeedExpansion; using ::crypto::tink::util::EnumsPqcrypto; StatusOr> DilithiumVerifyKeyManager::PublicKeyVerifyFactory::Create( const DilithiumPublicKey& public_key) const { util::StatusOr dilithium_public_key = DilithiumPublicKeyPqclean::NewPublicKey( public_key.key_value(), EnumsPqcrypto::ProtoToSubtle(public_key.params().seed_expansion())); if (!dilithium_public_key.ok()) return dilithium_public_key.status(); return subtle::DilithiumAvx2Verify::New(*dilithium_public_key); } Status DilithiumVerifyKeyManager::ValidateKey( const DilithiumPublicKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; if (key.key_value().length() != PQCLEAN_DILITHIUM2_CRYPTO_PUBLICKEYBYTES && key.key_value().length() != PQCLEAN_DILITHIUM3_CRYPTO_PUBLICKEYBYTES && key.key_value().length() != PQCLEAN_DILITHIUM5_CRYPTO_PUBLICKEYBYTES) { return Status(absl::StatusCode::kInvalidArgument, "Invalid dilithium public key size."); } return util::OkStatus(); } Status DilithiumVerifyKeyManager::ValidateParams( const DilithiumParams& params) const { switch (params.seed_expansion()) { case DilithiumSeedExpansion::SEED_EXPANSION_SHAKE: case DilithiumSeedExpansion::SEED_EXPANSION_AES: { break; } default: { return Status(absl::StatusCode::kInvalidArgument, "Invalid seed expansion"); } } switch (params.key_size()) { case PQCLEAN_DILITHIUM2_CRYPTO_SECRETKEYBYTES: case PQCLEAN_DILITHIUM3_CRYPTO_SECRETKEYBYTES: case PQCLEAN_DILITHIUM5_CRYPTO_SECRETKEYBYTES: { break; } default: { return Status(absl::StatusCode::kInvalidArgument, "Invalid key size."); } } return util::OkStatus(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/dilithium_verify_key_manager.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_DILITHIUM_VERIFY_KEY_MANAGER_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_DILITHIUM_VERIFY_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/key_type_manager.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/public_key_verify.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/input_stream_util.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/experimental/pqcrypto/dilithium.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class DilithiumVerifyKeyManager : public KeyTypeManager> { public: class PublicKeyVerifyFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::DilithiumPublicKey& public_key) const override; }; DilithiumVerifyKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PUBLIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::DilithiumPublicKey& key) const override; crypto::tink::util::Status ValidateParams( const google::crypto::tink::DilithiumParams& params) const; private: const std::string key_type_ = absl::StrCat(kTypeGoogleapisCom, google::crypto::tink::DilithiumPublicKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_DILITHIUM_VERIFY_KEY_MANAGER_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/dilithium_verify_key_manager_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/dilithium_verify_key_manager.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_set.h" #include "absl/strings/str_cat.h" #include "tink/experimental/pqcrypto/signature/dilithium_sign_key_manager.h" #include "tink/experimental/pqcrypto/signature/subtle/dilithium_avx2_sign.h" #include "tink/experimental/pqcrypto/signature/subtle/dilithium_avx2_verify.h" #include "tink/experimental/pqcrypto/signature/subtle/dilithium_key.h" #include "tink/experimental/pqcrypto/signature/util/enums.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/experimental/pqcrypto/dilithium.pb.h" #include "proto/tink.pb.h" extern "C" { #include "third_party/pqclean/crypto_sign/dilithium2/api.h" #include "third_party/pqclean/crypto_sign/dilithium2aes/api.h" #include "third_party/pqclean/crypto_sign/dilithium3/api.h" #include "third_party/pqclean/crypto_sign/dilithium3aes/api.h" #include "third_party/pqclean/crypto_sign/dilithium5/api.h" #include "third_party/pqclean/crypto_sign/dilithium5aes/api.h" } namespace crypto { namespace tink { namespace { using ::crypto::tink::subtle::DilithiumPrivateKeyPqclean; using ::crypto::tink::test::IsOk; using ::crypto::tink::util::EnumsPqcrypto; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::DilithiumKeyFormat; using ::google::crypto::tink::DilithiumParams; using ::google::crypto::tink::DilithiumPrivateKey; using ::google::crypto::tink::DilithiumPublicKey; using ::google::crypto::tink::DilithiumSeedExpansion; using ::google::crypto::tink::KeyData; using ::testing::Eq; using ::testing::Not; struct DilithiumTestCase { std::string test_name; int32_t private_key_size; int32_t public_key_size; DilithiumSeedExpansion seed_expansion; }; using DilithiumVerifyKeyManagerTest = testing::TestWithParam; // Helper function that returns a valid dilithium private key. StatusOr CreateValidPrivateKey( int32_t private_key_size, DilithiumSeedExpansion seed_expansion) { DilithiumKeyFormat key_format; DilithiumParams* params = key_format.mutable_params(); params->set_key_size(private_key_size); params->set_seed_expansion(seed_expansion); return DilithiumSignKeyManager().CreateKey(key_format); } // Helper function that returns a valid dilithium public key. StatusOr CreateValidPublicKey( int32_t private_key_size, DilithiumSeedExpansion seed_expansion) { StatusOr private_key = CreateValidPrivateKey(private_key_size, seed_expansion); if (!private_key.ok()) return private_key.status(); return DilithiumSignKeyManager().GetPublicKey(*private_key); } TEST(DilithiumVerifyKeyManagerTest, Basics) { EXPECT_THAT(DilithiumVerifyKeyManager().get_version(), Eq(0)); EXPECT_THAT(DilithiumVerifyKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PUBLIC)); EXPECT_THAT(DilithiumVerifyKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.DilithiumPublicKey")); } TEST(DilithiumVerifyKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(DilithiumVerifyKeyManager().ValidateKey(DilithiumPublicKey()), Not(IsOk())); } TEST_P(DilithiumVerifyKeyManagerTest, InvalidParams) { const DilithiumTestCase& test_case = GetParam(); DilithiumKeyFormat key_format; DilithiumParams* params = key_format.mutable_params(); params->set_key_size(test_case.private_key_size); params->set_seed_expansion(DilithiumSeedExpansion::SEED_EXPANSION_UNKNOWN); EXPECT_THAT(DilithiumVerifyKeyManager().ValidateParams(*params), Not(IsOk())); } TEST_P(DilithiumVerifyKeyManagerTest, PublicKeyValid) { const DilithiumTestCase& test_case = GetParam(); StatusOr public_key = CreateValidPublicKey( test_case.private_key_size, test_case.seed_expansion); ASSERT_THAT(public_key, IsOk()); EXPECT_THAT(DilithiumVerifyKeyManager().ValidateKey(*public_key), IsOk()); } TEST_P(DilithiumVerifyKeyManagerTest, PublicKeyWrongVersion) { const DilithiumTestCase& test_case = GetParam(); StatusOr public_key = CreateValidPublicKey( test_case.private_key_size, test_case.seed_expansion); ASSERT_THAT(public_key, IsOk()); public_key->set_version(1); EXPECT_THAT(DilithiumVerifyKeyManager().ValidateKey(*public_key), Not(IsOk())); } TEST_P(DilithiumVerifyKeyManagerTest, PublicKeyWrongKeyLength) { const DilithiumTestCase& test_case = GetParam(); StatusOr public_key = CreateValidPublicKey( test_case.private_key_size, test_case.seed_expansion); ASSERT_THAT(public_key, IsOk()); for (int keysize = 0; keysize < PQCLEAN_DILITHIUM2_CRYPTO_PUBLICKEYBYTES; keysize++) { public_key->set_key_value(std::string(keysize, '@')); EXPECT_THAT(DilithiumVerifyKeyManager().ValidateKey(*public_key), Not(IsOk())); } } TEST_P(DilithiumVerifyKeyManagerTest, Create) { const DilithiumTestCase& test_case = GetParam(); StatusOr private_key = CreateValidPrivateKey( test_case.private_key_size, test_case.seed_expansion); ASSERT_THAT(private_key, IsOk()); StatusOr public_key = DilithiumSignKeyManager().GetPublicKey(*private_key); ASSERT_THAT(public_key, IsOk()); util::StatusOr dilithium_private_key = DilithiumPrivateKeyPqclean::NewPrivateKey( util::SecretDataFromStringView(private_key->key_value()), EnumsPqcrypto::ProtoToSubtle(test_case.seed_expansion)); ASSERT_THAT(dilithium_private_key, IsOk()); util::StatusOr> direct_signer = subtle::DilithiumAvx2Sign::New(*dilithium_private_key); ASSERT_THAT(direct_signer, IsOk()); util::StatusOr> verifier = DilithiumVerifyKeyManager().GetPrimitive(*public_key); ASSERT_THAT(verifier, IsOk()); std::string message = "Some message"; util::StatusOr signature = (*direct_signer)->Sign(message); ASSERT_THAT(signature, IsOk()); EXPECT_THAT((*verifier)->Verify(*signature, message), IsOk()); } TEST_P(DilithiumVerifyKeyManagerTest, CreateDifferentPublicKey) { const DilithiumTestCase& test_case = GetParam(); StatusOr private_key = CreateValidPrivateKey( test_case.private_key_size, test_case.seed_expansion); ASSERT_THAT(private_key, IsOk()); // Create a new public key derived from a diffferent private key. StatusOr new_private_key = CreateValidPrivateKey( test_case.private_key_size, test_case.seed_expansion); ASSERT_THAT(new_private_key, IsOk()); StatusOr public_key = DilithiumSignKeyManager().GetPublicKey(*new_private_key); ASSERT_THAT(public_key, IsOk()); util::StatusOr dilithium_private_key = DilithiumPrivateKeyPqclean::NewPrivateKey( util::SecretDataFromStringView(private_key->key_value()), EnumsPqcrypto::ProtoToSubtle(test_case.seed_expansion)); ASSERT_THAT(dilithium_private_key, IsOk()); util::StatusOr> direct_signer = subtle::DilithiumAvx2Sign::New(*dilithium_private_key); ASSERT_THAT(direct_signer, IsOk()); util::StatusOr> verifier = DilithiumVerifyKeyManager().GetPrimitive(*public_key); ASSERT_THAT(verifier, IsOk()); std::string message = "Some message"; util::StatusOr signature = (*direct_signer)->Sign(message); ASSERT_THAT(signature, IsOk()); EXPECT_THAT((*verifier)->Verify(*signature, message), Not(IsOk())); } INSTANTIATE_TEST_SUITE_P( DilithiumVerifyKeyManagerTests, DilithiumVerifyKeyManagerTest, testing::ValuesIn({ {"Dilithium2", PQCLEAN_DILITHIUM2_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM2_CRYPTO_PUBLICKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE}, {"Dilithium3", PQCLEAN_DILITHIUM3_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM3_CRYPTO_PUBLICKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE}, {"Dilithium5", PQCLEAN_DILITHIUM5_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM5_CRYPTO_PUBLICKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE}, {"Dilithium2Aes", PQCLEAN_DILITHIUM2AES_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM2AES_CRYPTO_PUBLICKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_AES}, {"Dilithium3Aes", PQCLEAN_DILITHIUM3AES_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM3AES_CRYPTO_PUBLICKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_AES}, {"Dilithium5Aes", PQCLEAN_DILITHIUM5AES_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM5AES_CRYPTO_PUBLICKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_AES}, }), [](const testing::TestParamInfo& info) { return info.param.test_name; }); } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/falcon_key_template.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/falcon_key_template.h" #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/experimental/pqcrypto/signature/subtle/falcon_subtle_utils.h" #include "tink/util/constants.h" #include "proto/experimental/pqcrypto/falcon.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using google::crypto::tink::FalconKeyFormat; using google::crypto::tink::FalconPrivateKey; using google::crypto::tink::KeyTemplate; using google::crypto::tink::OutputPrefixType; std::unique_ptr NewFalconKeyTemplate(int32_t key_size) { auto key_template = absl::make_unique(); key_template->set_type_url( absl::StrCat(kTypeGoogleapisCom, FalconPrivateKey().GetTypeName())); key_template->set_output_prefix_type(OutputPrefixType::TINK); FalconKeyFormat key_format; key_format.set_key_size(key_size); key_format.SerializeToString(key_template->mutable_value()); return key_template; } } // anonymous namespace const google::crypto::tink::KeyTemplate& Falcon512KeyTemplate() { static const KeyTemplate* key_template = NewFalconKeyTemplate(subtle::kFalcon512PrivateKeySize).release(); return *key_template; } const google::crypto::tink::KeyTemplate& Falcon1024KeyTemplate() { static const KeyTemplate* key_template = NewFalconKeyTemplate(subtle::kFalcon1024PrivateKeySize).release(); return *key_template; } } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/falcon_key_template.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_FALCON_KEY_TEMPLATE_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_FALCON_KEY_TEMPLATE_H_ #include "proto/tink.pb.h" namespace crypto { namespace tink { // Returns a KeyTemplate that generates new instances of // FalconPrivateKey with a 1281 private key size. const google::crypto::tink::KeyTemplate& Falcon512KeyTemplate(); // Returns a KeyTemplate that generates new instances of // FalconPrivateKey with a 2305 private key size. const google::crypto::tink::KeyTemplate& Falcon1024KeyTemplate(); } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_FALCON_KEY_TEMPLATE_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/falcon_key_template_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/falcon_key_template.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/core/key_manager_impl.h" #include "tink/core/private_key_manager_impl.h" #include "tink/experimental/pqcrypto/signature/falcon_sign_key_manager.h" #include "tink/experimental/pqcrypto/signature/falcon_verify_key_manager.h" #include "tink/experimental/pqcrypto/signature/subtle/falcon_subtle_utils.h" #include "tink/key_manager.h" #include "tink/public_key_sign.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/experimental/pqcrypto/falcon.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::google::crypto::tink::FalconKeyFormat; using ::google::crypto::tink::FalconPrivateKey; using google::crypto::tink::KeyTemplate; using google::crypto::tink::OutputPrefixType; struct FalconTestCase { std::string test_name; int32_t private_key_size; KeyTemplate key_template; }; using FalconKeyTemplateTest = testing::TestWithParam; TEST_P(FalconKeyTemplateTest, CheckKeyTemplateValid) { std::string type_url = "type.googleapis.com/google.crypto.tink.FalconPrivateKey"; const FalconTestCase& test_case = GetParam(); EXPECT_EQ(type_url, test_case.key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, test_case.key_template.output_prefix_type()); FalconKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(test_case.key_template.value())); EXPECT_EQ(test_case.private_key_size, key_format.key_size()); } TEST_P(FalconKeyTemplateTest, SameReference) { const KeyTemplate& key_template = GetParam().key_template; const KeyTemplate& key_template_2 = GetParam().key_template; EXPECT_EQ(&key_template, &key_template_2); } TEST_P(FalconKeyTemplateTest, KeyManagerCompatibility) { FalconSignKeyManager sign_key_manager; FalconVerifyKeyManager verify_key_manager; std::unique_ptr> key_manager = internal::MakePrivateKeyManager(&sign_key_manager, &verify_key_manager); FalconKeyFormat key_format; const FalconTestCase& test_case = GetParam(); key_format.set_key_size(test_case.private_key_size); util::StatusOr> new_key_result = key_manager->get_key_factory().NewKey(key_format); EXPECT_THAT(new_key_result, IsOk()); } INSTANTIATE_TEST_SUITE_P( FalconKeyTemplateTests, FalconKeyTemplateTest, testing::ValuesIn( {{"Falcon512", subtle::kFalcon512PrivateKeySize, Falcon512KeyTemplate()}, {"Falcon1024", subtle::kFalcon1024PrivateKeySize, Falcon1024KeyTemplate()}}), [](const testing::TestParamInfo& info) { return info.param.test_name; }); } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/falcon_sign_key_manager.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/falcon_sign_key_manager.h" #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/experimental/pqcrypto/signature/falcon_verify_key_manager.h" #include "tink/experimental/pqcrypto/signature/subtle/falcon_sign.h" #include "tink/experimental/pqcrypto/signature/subtle/falcon_subtle_utils.h" #include "tink/public_key_sign.h" #include "tink/util/errors.h" #include "tink/util/input_stream_util.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" namespace crypto { namespace tink { using ::crypto::tink::subtle::FalconKeyPair; using ::crypto::tink::subtle::FalconPrivateKeyPqclean; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::FalconKeyFormat; using ::google::crypto::tink::FalconPrivateKey; using ::google::crypto::tink::FalconPublicKey; StatusOr FalconSignKeyManager::CreateKey( const FalconKeyFormat& key_format) const { util::StatusOr key_pair = subtle::GenerateFalconKeyPair(key_format.key_size()); if (!key_pair.status().ok()) { return key_pair.status(); } FalconPrivateKey falcon_private_key; falcon_private_key.set_version(get_version()); falcon_private_key.set_key_value( util::SecretDataAsStringView(key_pair->GetPrivateKey().GetKey())); FalconPublicKey* falcon_public_key = falcon_private_key.mutable_public_key(); falcon_public_key->set_version(get_version()); falcon_public_key->set_key_value(key_pair->GetPublicKey().GetKey()); return falcon_private_key; } StatusOr> FalconSignKeyManager::PublicKeySignFactory::Create( const FalconPrivateKey& private_key) const { util::SecretData sk_data = util::SecretDataFromStringView(private_key.key_value()); util::StatusOr falcon_private_key = FalconPrivateKeyPqclean::NewPrivateKey(sk_data); if (!falcon_private_key.ok()) { return falcon_private_key.status(); } return subtle::FalconSign::New(*falcon_private_key); } Status FalconSignKeyManager::ValidateKey(const FalconPrivateKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) { return status; } status = subtle::ValidateFalconPrivateKeySize(key.key_value().length()); if (!status.ok()) { return status; } return FalconVerifyKeyManager().ValidateKey(key.public_key()); } Status FalconSignKeyManager::ValidateKeyFormat( const FalconKeyFormat& key_format) const { Status status = subtle::ValidateFalconPrivateKeySize(key_format.key_size()); if (!status.ok()) { return status; } return util::OkStatus(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/falcon_sign_key_manager.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_FALCON_SIGN_KEY_MANAGER_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_FALCON_SIGN_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/public_key_sign.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/input_stream_util.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/experimental/pqcrypto/falcon.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class FalconSignKeyManager : public PrivateKeyTypeManager> { public: class PublicKeySignFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::FalconPrivateKey& private_key) const override; }; FalconSignKeyManager() : PrivateKeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::FalconPrivateKey& key) const override; crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::FalconKeyFormat& key_format) const override; crypto::tink::util::StatusOr CreateKey(const google::crypto::tink::FalconKeyFormat& key_format) const override; crypto::tink::util::StatusOr GetPublicKey(const google::crypto::tink::FalconPrivateKey& private_key) const override { return private_key.public_key(); } private: const std::string key_type_ = absl::StrCat(kTypeGoogleapisCom, google::crypto::tink::FalconPrivateKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_FALCON_SIGN_KEY_MANAGER_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/falcon_sign_key_manager_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/falcon_sign_key_manager.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_set.h" #include "absl/strings/str_cat.h" #include "tink/experimental/pqcrypto/signature/subtle/falcon_sign.h" #include "tink/experimental/pqcrypto/signature/subtle/falcon_subtle_utils.h" #include "tink/experimental/pqcrypto/signature/subtle/falcon_verify.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/experimental/pqcrypto/falcon.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::FalconKeyFormat; using ::google::crypto::tink::FalconPrivateKey; using ::google::crypto::tink::FalconPublicKey; using ::google::crypto::tink::KeyData; using ::testing::Eq; using ::testing::Not; using ::testing::SizeIs; struct FalconTestCase { std::string test_name; int32_t private_key_size; int32_t public_key_size; }; using FalconSignKeyManagerTest = testing::TestWithParam; // Helper function that returns a valid falcon key format. StatusOr CreateValidKeyFormat(int32_t private_key_size) { FalconKeyFormat key_format; key_format.set_key_size(private_key_size); return key_format; } TEST(FalconSignKeyManagerTest, Basic) { EXPECT_THAT(FalconSignKeyManager().get_version(), Eq(0)); EXPECT_THAT(FalconSignKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PRIVATE)); EXPECT_THAT(FalconSignKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.FalconPrivateKey")); } TEST_P(FalconSignKeyManagerTest, ValidKeyFormat) { const FalconTestCase& test_case = GetParam(); StatusOr key_format = CreateValidKeyFormat(test_case.private_key_size); ASSERT_THAT(key_format, IsOk()); EXPECT_THAT(FalconSignKeyManager().ValidateKeyFormat(*key_format), IsOk()); } TEST(FalconSignKeyManagerTest, InvalidKeyFormat) { StatusOr key_format = CreateValidKeyFormat(0); ASSERT_THAT(key_format, IsOk()); EXPECT_THAT(FalconSignKeyManager().ValidateKeyFormat(*key_format), Not(IsOk())); } TEST_P(FalconSignKeyManagerTest, CreateKeyValid) { const FalconTestCase& test_case = GetParam(); StatusOr key_format = CreateValidKeyFormat(test_case.private_key_size); ASSERT_THAT(key_format, IsOk()); StatusOr private_key = FalconSignKeyManager().CreateKey(*key_format); ASSERT_THAT(private_key, IsOk()); EXPECT_THAT(FalconSignKeyManager().ValidateKey(*private_key), IsOk()); EXPECT_THAT(private_key->version(), Eq(0)); EXPECT_THAT(private_key->public_key().version(), Eq(private_key->version())); EXPECT_THAT(private_key->key_value(), SizeIs(test_case.private_key_size)); } TEST_P(FalconSignKeyManagerTest, PrivateKeyWrongVersion) { const FalconTestCase& test_case = GetParam(); StatusOr key_format = CreateValidKeyFormat(test_case.private_key_size); ASSERT_THAT(key_format, IsOk()); StatusOr private_key = FalconSignKeyManager().CreateKey(*key_format); ASSERT_THAT(private_key, IsOk()); private_key->set_version(1); EXPECT_THAT(FalconSignKeyManager().ValidateKey(*private_key), Not(IsOk())); } TEST_P(FalconSignKeyManagerTest, CreateKeyAlwaysNew) { const FalconTestCase& test_case = GetParam(); StatusOr key_format = CreateValidKeyFormat(test_case.private_key_size); ASSERT_THAT(key_format, IsOk()); absl::flat_hash_set keys; int num_tests = 5; for (int i = 0; i < num_tests; ++i) { StatusOr private_key = FalconSignKeyManager().CreateKey(*key_format); ASSERT_THAT(private_key, IsOk()); keys.insert(private_key->key_value()); } EXPECT_THAT(keys, SizeIs(num_tests)); } TEST_P(FalconSignKeyManagerTest, GetPublicKey) { const FalconTestCase& test_case = GetParam(); StatusOr key_format = CreateValidKeyFormat(test_case.private_key_size); ASSERT_THAT(key_format, IsOk()); StatusOr private_key = FalconSignKeyManager().CreateKey(*key_format); ASSERT_THAT(private_key, IsOk()); StatusOr public_key = FalconSignKeyManager().GetPublicKey(*private_key); ASSERT_THAT(public_key, IsOk()); EXPECT_THAT(public_key->version(), Eq(private_key->public_key().version())); EXPECT_THAT(public_key->key_value(), Eq(private_key->public_key().key_value())); } TEST_P(FalconSignKeyManagerTest, CreateValid) { const FalconTestCase& test_case = GetParam(); StatusOr key_format = CreateValidKeyFormat(test_case.private_key_size); ASSERT_THAT(key_format, IsOk()); util::StatusOr private_key = FalconSignKeyManager().CreateKey(*key_format); ASSERT_THAT(private_key, IsOk()); util::StatusOr> signer = FalconSignKeyManager().GetPrimitive(*private_key); ASSERT_THAT(signer, IsOk()); StatusOr falcon_public_key_pqclean = subtle::FalconPublicKeyPqclean::NewPublicKey( private_key->public_key().key_value()); ASSERT_THAT(falcon_public_key_pqclean, IsOk()); util::StatusOr> verifier = subtle::FalconVerify::New(*falcon_public_key_pqclean); ASSERT_THAT(verifier, IsOk()); std::string message = "Some message"; util::StatusOr signature = (*signer)->Sign(message); ASSERT_THAT(signature, IsOk()); EXPECT_THAT((*verifier)->Verify(*signature, message), IsOk()); } TEST_P(FalconSignKeyManagerTest, CreateBadPublicKey) { const FalconTestCase& test_case = GetParam(); StatusOr key_format = CreateValidKeyFormat(test_case.private_key_size); ASSERT_THAT(key_format, IsOk()); util::StatusOr private_key = FalconSignKeyManager().CreateKey(*key_format); ASSERT_THAT(private_key, IsOk()); util::StatusOr> signer = FalconSignKeyManager().GetPrimitive(*private_key); ASSERT_THAT(signer, IsOk()); std::string bad_public_key_data(test_case.public_key_size, '@'); StatusOr falcon_public_key_pqclean = subtle::FalconPublicKeyPqclean::NewPublicKey(bad_public_key_data); ASSERT_THAT(falcon_public_key_pqclean, IsOk()); util::StatusOr> direct_verifier = subtle::FalconVerify::New(*falcon_public_key_pqclean); ASSERT_THAT(direct_verifier, IsOk()); std::string message = "Some message"; util::StatusOr signature = (*signer)->Sign(message); ASSERT_THAT(signature, IsOk()); EXPECT_THAT((*direct_verifier)->Verify(*signature, message), Not(IsOk())); } INSTANTIATE_TEST_SUITE_P( FalconSignKeyManagerTests, FalconSignKeyManagerTest, testing::ValuesIn( {{"Falcon512", subtle::kFalcon512PrivateKeySize, subtle::kFalcon512PublicKeySize}, {"Falcon1024", subtle::kFalcon1024PrivateKeySize, subtle::kFalcon1024PublicKeySize}}), [](const testing::TestParamInfo& info) { return info.param.test_name; }); } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/falcon_verify_key_manager.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/falcon_verify_key_manager.h" #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/experimental/pqcrypto/signature/subtle/falcon_subtle_utils.h" #include "tink/experimental/pqcrypto/signature/subtle/falcon_verify.h" #include "tink/public_key_verify.h" #include "tink/util/errors.h" #include "tink/util/input_stream_util.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" namespace crypto { namespace tink { using ::crypto::tink::subtle::FalconPublicKeyPqclean; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::FalconPublicKey; StatusOr> FalconVerifyKeyManager::PublicKeyVerifyFactory::Create( const FalconPublicKey& public_key) const { StatusOr falcon_public_key_pqclean = FalconPublicKeyPqclean::NewPublicKey(public_key.key_value()); if (!falcon_public_key_pqclean.ok()) { return falcon_public_key_pqclean.status(); } return subtle::FalconVerify::New(*falcon_public_key_pqclean); } Status FalconVerifyKeyManager::ValidateKey(const FalconPublicKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) { return status; } status = subtle::ValidateFalconPublicKeySize(key.key_value().length()); if (!status.ok()) { return status; } return util::OkStatus(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/falcon_verify_key_manager.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_FALCON_VERIFY_KEY_MANAGER_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_FALCON_VERIFY_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/key_type_manager.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/public_key_verify.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/input_stream_util.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/experimental/pqcrypto/falcon.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class FalconVerifyKeyManager : public KeyTypeManager> { public: class PublicKeyVerifyFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::FalconPublicKey& public_key) const override; }; FalconVerifyKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PUBLIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::FalconPublicKey& key) const override; private: const std::string key_type_ = absl::StrCat(kTypeGoogleapisCom, google::crypto::tink::FalconPublicKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_FALCON_VERIFY_KEY_MANAGER_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/falcon_verify_key_manager_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/falcon_verify_key_manager.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_set.h" #include "absl/strings/str_cat.h" #include "tink/experimental/pqcrypto/signature/falcon_sign_key_manager.h" #include "tink/experimental/pqcrypto/signature/subtle/falcon_sign.h" #include "tink/experimental/pqcrypto/signature/subtle/falcon_subtle_utils.h" #include "tink/experimental/pqcrypto/signature/subtle/falcon_verify.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/experimental/pqcrypto/falcon.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::FalconKeyFormat; using ::google::crypto::tink::FalconPrivateKey; using ::google::crypto::tink::FalconPublicKey; using ::google::crypto::tink::KeyData; using ::testing::Eq; using ::testing::Not; struct FalconTestCase { std::string test_name; int32_t private_key_size; int32_t public_key_size; }; using FalconVerifyKeyManagerTest = testing::TestWithParam; // Helper function that returns a valid falcon private key. StatusOr CreateValidPrivateKey(int32_t private_key_size) { FalconKeyFormat key_format; key_format.set_key_size(private_key_size); return FalconSignKeyManager().CreateKey(key_format); } // Helper function that returns a valid falcon public key. StatusOr CreateValidPublicKey(int32_t private_key_size) { StatusOr private_key = CreateValidPrivateKey(private_key_size); if (!private_key.ok()) return private_key.status(); return FalconSignKeyManager().GetPublicKey(*private_key); } TEST(FalconVerifyKeyManagerTest, Basics) { EXPECT_THAT(FalconVerifyKeyManager().get_version(), Eq(0)); EXPECT_THAT(FalconVerifyKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PUBLIC)); EXPECT_THAT(FalconVerifyKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.FalconPublicKey")); } TEST(FalconVerifyKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(FalconVerifyKeyManager().ValidateKey(FalconPublicKey()), Not(IsOk())); } TEST_P(FalconVerifyKeyManagerTest, PublicKeyValid) { const FalconTestCase& test_case = GetParam(); StatusOr public_key = CreateValidPublicKey(test_case.private_key_size); ASSERT_THAT(public_key, IsOk()); EXPECT_THAT(FalconVerifyKeyManager().ValidateKey(*public_key), IsOk()); } TEST_P(FalconVerifyKeyManagerTest, PublicKeyWrongVersion) { const FalconTestCase& test_case = GetParam(); StatusOr public_key = CreateValidPublicKey(test_case.private_key_size); ASSERT_THAT(public_key, IsOk()); public_key->set_version(1); EXPECT_THAT(FalconVerifyKeyManager().ValidateKey(*public_key), Not(IsOk())); } TEST_P(FalconVerifyKeyManagerTest, Create) { const FalconTestCase& test_case = GetParam(); StatusOr private_key = CreateValidPrivateKey(test_case.private_key_size); ASSERT_THAT(private_key, IsOk()); StatusOr public_key = FalconSignKeyManager().GetPublicKey(*private_key); ASSERT_THAT(public_key, IsOk()); StatusOr falcon_private_key_pqclean = subtle::FalconPrivateKeyPqclean::NewPrivateKey( util::SecretDataFromStringView(private_key->key_value())); util::StatusOr> direct_signer = subtle::FalconSign::New(*falcon_private_key_pqclean); ASSERT_THAT(direct_signer, IsOk()); util::StatusOr> verifier = FalconVerifyKeyManager().GetPrimitive(*public_key); ASSERT_THAT(verifier, IsOk()); std::string message = "Some message"; util::StatusOr signature = (*direct_signer)->Sign(message); ASSERT_THAT(signature, IsOk()); EXPECT_THAT((*verifier)->Verify(*signature, message), IsOk()); } TEST_P(FalconVerifyKeyManagerTest, CreateInvalidPublicKey) { const FalconTestCase& test_case = GetParam(); StatusOr private_key = CreateValidPrivateKey(test_case.private_key_size); ASSERT_THAT(private_key, IsOk()); StatusOr public_key = FalconSignKeyManager().GetPublicKey(*private_key); ASSERT_THAT(public_key, IsOk()); std::string bad_public_key_data = "bad_public_key"; public_key->set_key_value(bad_public_key_data); util::StatusOr> verifier = FalconVerifyKeyManager().GetPrimitive(*public_key); EXPECT_THAT(verifier, Not(IsOk())); } TEST_P(FalconVerifyKeyManagerTest, CreateDifferentPublicKey) { const FalconTestCase& test_case = GetParam(); StatusOr private_key = CreateValidPrivateKey(test_case.private_key_size); ASSERT_THAT(private_key, IsOk()); // Create a new public key derived from a diffferent private key. StatusOr new_private_key = CreateValidPrivateKey(test_case.private_key_size); ASSERT_THAT(new_private_key, IsOk()); StatusOr public_key = FalconSignKeyManager().GetPublicKey(*new_private_key); ASSERT_THAT(public_key, IsOk()); StatusOr falcon_private_key_pqclean = subtle::FalconPrivateKeyPqclean::NewPrivateKey( util::SecretDataFromStringView(private_key->key_value())); util::StatusOr> direct_signer = subtle::FalconSign::New(*falcon_private_key_pqclean); ASSERT_THAT(direct_signer, IsOk()); util::StatusOr> verifier = FalconVerifyKeyManager().GetPrimitive(*public_key); ASSERT_THAT(verifier, IsOk()); std::string message = "Some message"; util::StatusOr signature = (*direct_signer)->Sign(message); ASSERT_THAT(signature, IsOk()); EXPECT_THAT((*verifier)->Verify(*signature, message), Not(IsOk())); } INSTANTIATE_TEST_SUITE_P( FalconVeirfyKeyManagerTests, FalconVerifyKeyManagerTest, testing::ValuesIn( {{"Falcon512", subtle::kFalcon512PrivateKeySize, subtle::kFalcon512PublicKeySize}, {"Falcon1024", subtle::kFalcon1024PrivateKeySize, subtle::kFalcon1024PublicKeySize}}), [](const testing::TestParamInfo& info) { return info.param.test_name; }); } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/signature_config.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/signature_config.h" #include "absl/memory/memory.h" #include "tink/config/config_util.h" #include "tink/config/tink_fips.h" #include "tink/experimental/pqcrypto/signature/dilithium_sign_key_manager.h" #include "tink/experimental/pqcrypto/signature/dilithium_verify_key_manager.h" #include "tink/experimental/pqcrypto/signature/falcon_sign_key_manager.h" #include "tink/experimental/pqcrypto/signature/falcon_verify_key_manager.h" #include "tink/experimental/pqcrypto/signature/sphincs_sign_key_manager.h" #include "tink/experimental/pqcrypto/signature/sphincs_verify_key_manager.h" #include "tink/registry.h" #include "tink/signature/public_key_sign_wrapper.h" #include "tink/signature/public_key_verify_wrapper.h" #include "tink/util/status.h" #include "proto/config.pb.h" namespace crypto { namespace tink { util::Status PqSignatureConfigRegister() { // Register primitive wrappers. auto status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) return status; status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) return status; if (IsFipsModeEnabled()) { return util::OkStatus(); } // Dilithium status = Registry::RegisterAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), true); // Sphincs status = Registry::RegisterAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), true); // Falcon status = Registry::RegisterAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), true); return status; } } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/signature_config.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SIGNATURE_CONFIG_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SIGNATURE_CONFIG_H_ #include "tink/util/status.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Static methods for registering with the Registry // all instances of experimental signature key types supported in a particular // release of Tink, i.e. key types that correspond to primitives // PublicKeySign and PublicKeyVerify. // // To register all experiemntal signature key types from the current Tink // release one calls PqSignatureConfigRegister(). // // Registers PublicKeySign and PublicKeyVerify primitive wrappers, and key // managers for all experimental implementations of PublicKeySign and // PublicKeyVerify from the current Tink release. crypto::tink::util::Status PqSignatureConfigRegister(); } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SIGNATURE_CONFIG_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/signature_config_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/signature_config.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/experimental/pqcrypto/signature/dilithium_sign_key_manager.h" #include "tink/experimental/pqcrypto/signature/dilithium_verify_key_manager.h" #include "tink/experimental/pqcrypto/signature/falcon_sign_key_manager.h" #include "tink/experimental/pqcrypto/signature/falcon_verify_key_manager.h" #include "tink/experimental/pqcrypto/signature/sphincs_sign_key_manager.h" #include "tink/experimental/pqcrypto/signature/sphincs_verify_key_manager.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; class PcqSignatureConfigTest : public ::testing::Test { protected: void SetUp() override { Registry::Reset(); } }; TEST_F(PcqSignatureConfigTest, CheckDilithium) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used"; } EXPECT_THAT(Registry::get_key_manager( DilithiumSignKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT(Registry::get_key_manager( DilithiumVerifyKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT(PqSignatureConfigRegister(), IsOk()); EXPECT_THAT(Registry::get_key_manager( DilithiumSignKeyManager().get_key_type()) .status(), IsOk()); EXPECT_THAT(Registry::get_key_manager( DilithiumVerifyKeyManager().get_key_type()) .status(), IsOk()); } TEST_F(PcqSignatureConfigTest, CheckSphincs) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used"; } EXPECT_THAT(Registry::get_key_manager( SphincsSignKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT(Registry::get_key_manager( SphincsVerifyKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT(PqSignatureConfigRegister(), IsOk()); EXPECT_THAT(Registry::get_key_manager( SphincsSignKeyManager().get_key_type()) .status(), IsOk()); EXPECT_THAT(Registry::get_key_manager( SphincsVerifyKeyManager().get_key_type()) .status(), IsOk()); } TEST_F(PcqSignatureConfigTest, CheckFalcon) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used"; } EXPECT_THAT(Registry::get_key_manager( FalconSignKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT(Registry::get_key_manager( FalconVerifyKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT(PqSignatureConfigRegister(), IsOk()); EXPECT_THAT(Registry::get_key_manager( FalconSignKeyManager().get_key_type()) .status(), IsOk()); EXPECT_THAT(Registry::get_key_manager( FalconVerifyKeyManager().get_key_type()) .status(), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/signature_config_util_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/crypto_format.h" #include "tink/experimental/pqcrypto/signature/dilithium_sign_key_manager.h" #include "tink/experimental/pqcrypto/signature/dilithium_verify_key_manager.h" #include "tink/experimental/pqcrypto/signature/signature_config.h" #include "tink/internal/fips_utils.h" #include "tink/primitive_set.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::DummyPublicKeySign; using ::crypto::tink::test::DummyPublicKeyVerify; using ::crypto::tink::test::IsOk; class PcqSignatureConfigTest : public ::testing::Test { protected: void SetUp() override { Registry::Reset(); } }; TEST_F(PcqSignatureConfigTest, CheckStatus) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used"; } EXPECT_THAT(PqSignatureConfigRegister(), IsOk()); } // Tests that the PublicKeySignWrapper has been properly registered and we // can wrap primitives. TEST_F(PcqSignatureConfigTest, PublicKeySignWrapperRegistered) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used"; } ASSERT_THAT(PqSignatureConfigRegister(), IsOk()); google::crypto::tink::KeysetInfo::KeyInfo key_info; key_info.set_status(google::crypto::tink::KeyStatusType::ENABLED); key_info.set_key_id(1234); key_info.set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); auto primitive_set = absl::make_unique>(); auto add_primitive = primitive_set->AddPrimitive( absl::make_unique("dummy"), key_info); ASSERT_THAT(add_primitive, IsOk()); ASSERT_THAT(primitive_set->set_primary(*add_primitive), IsOk()); util::StatusOr> wrapped = Registry::Wrap(std::move(primitive_set)); ASSERT_THAT(wrapped, IsOk()); util::StatusOr signature_result = (*wrapped)->Sign("message"); ASSERT_THAT(signature_result, IsOk()); util::StatusOr prefix = CryptoFormat::GetOutputPrefix(key_info); ASSERT_THAT(prefix, IsOk()); util::StatusOr signature = DummyPublicKeySign("dummy").Sign("message"); ASSERT_THAT(signature, IsOk()); EXPECT_EQ(*signature_result, absl::StrCat(*prefix, *signature)); } // Tests that the PublicKeyVerifyWrapper has been properly registered and we // can wrap primitives. TEST_F(PcqSignatureConfigTest, PublicKeyVerifyWrapperRegistered) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used"; } ASSERT_THAT(PqSignatureConfigRegister(), IsOk()); google::crypto::tink::KeysetInfo::KeyInfo key_info; key_info.set_status(google::crypto::tink::KeyStatusType::ENABLED); key_info.set_key_id(1234); key_info.set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); auto primitive_set = absl::make_unique>(); auto add_primitive = primitive_set->AddPrimitive( absl::make_unique("dummy"), key_info); ASSERT_THAT(add_primitive, IsOk()); ASSERT_THAT(primitive_set->set_primary(*add_primitive), IsOk()); util::StatusOr> wrapped = Registry::Wrap(std::move(primitive_set)); ASSERT_THAT(wrapped, IsOk()); util::StatusOr prefix = CryptoFormat::GetOutputPrefix(key_info); ASSERT_THAT(prefix, IsOk()); util::StatusOr signature = DummyPublicKeySign("dummy").Sign("message"); ASSERT_THAT(signature, IsOk()); ASSERT_THAT((*wrapped)->Verify(absl::StrCat(*prefix, *signature), "message"), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/slh_dsa_parameters.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/slh_dsa_parameters.h" #include "absl/status/status.h" #include "tink/parameters.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { util::StatusOr SlhDsaParameters::Create( HashType hash_type, int private_key_size_in_bytes, SignatureType signature_type, Variant variant) { // Validate HashType - only SHA2 is currently supported. if (hash_type != HashType::kSha2) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create Slh-DSA parameters with unknown HashType."); } if (private_key_size_in_bytes != 64) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid private key size. Only 64-bytes keys are " "currently supported."); } // Validate SignatureType - only SmallSignature is currently supported. if (signature_type != SignatureType::kSmallSignature) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create SLH-DSA parameters with unknown SignatureType."); } // Validate Variant. if (variant != Variant::kTink && variant != Variant::kNoPrefix) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create SLH-DSA parameters with unknown Variant."); } return SlhDsaParameters(hash_type, private_key_size_in_bytes, signature_type, variant); } bool SlhDsaParameters::operator==(const Parameters& other) const { const SlhDsaParameters* that = dynamic_cast(&other); if (that == nullptr) { return false; } return hash_type_ == that->hash_type_ && private_key_size_in_bytes_ == that->private_key_size_in_bytes_ && signature_type_ == that->signature_type_ && variant_ == that->variant_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/slh_dsa_parameters.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SLH_DSA_PARAMETERS_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SLH_DSA_PARAMETERS_H_ #include "tink/parameters.h" #include "tink/signature/signature_parameters.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Representation of the parameters sets for the Stateless Hash-Based Digital // Signature Standard (SLH-DSA) described at // https://csrc.nist.gov/pubs/fips/205/ipd. // // Note that only the SLH-DSA-SHA2-128s set is currently supported. class SlhDsaParameters : public SignatureParameters { public: // Describes the output prefix prepended to the signature. enum class Variant : int { // Prepends '0x01' to signature. kTink = 1, // Does not prepend any prefix (i.e., keys must have no ID requirement). kNoPrefix = 2, // Added to guard from failures that may be caused by future expansions. kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Description of the hash function used for this algorithm. enum class HashType : int { // The 128-bit security level variant uses SHA256. The 192-bit and 256-bit // variants require both SHA-256 and SHA-512 in their implementation. kSha2 = 1, kShake = 2, kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Description of the signature type. kFastSigning parameters sets // have significantly faster signing, but kSmallSignature come with faster // verification and smaller signatures. enum class SignatureType : int { kFastSigning = 1, kSmallSignature = 2, kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Copyable and movable. SlhDsaParameters(const SlhDsaParameters& other) = default; SlhDsaParameters& operator=(const SlhDsaParameters& other) = default; SlhDsaParameters(SlhDsaParameters&& other) = default; SlhDsaParameters& operator=(SlhDsaParameters&& other) = default; // Creates SLH-DSA parameters instances. static util::StatusOr Create(HashType hash_type, int private_key_size_in_bytes, SignatureType signature_type, Variant variant); HashType GetHashType() const { return hash_type_; } int GetPrivateKeySizeInBytes() const { return private_key_size_in_bytes_; } SignatureType GetSignatureType() const { return signature_type_; } Variant GetVariant() const { return variant_; } bool HasIdRequirement() const override { return variant_ != Variant::kNoPrefix; } bool operator==(const Parameters& other) const override; private: explicit SlhDsaParameters(HashType hash_type, int private_key_size_in_bytes, SignatureType signature_type, Variant variant) : hash_type_(hash_type), private_key_size_in_bytes_(private_key_size_in_bytes), signature_type_(signature_type), variant_(variant) {} HashType hash_type_; int private_key_size_in_bytes_; SignatureType signature_type_; Variant variant_; }; } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SLH_DSA_PARAMETERS_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/slh_dsa_parameters_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/slh_dsa_parameters.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::IsTrue; using ::testing::TestWithParam; using ::testing::Values; struct VariantTestCase { SlhDsaParameters::Variant variant; bool has_id_requirement; }; using SlhDsaParametersTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( SlhDsaParametersTestSuite, SlhDsaParametersTest, Values(VariantTestCase{SlhDsaParameters::Variant::kTink, /*has_id_requirement=*/true}, VariantTestCase{SlhDsaParameters::Variant::kNoPrefix, /*has_id_requirement=*/false})); TEST_P(SlhDsaParametersTest, CreateSlhDsa128Sha2SmallSignatureWorks) { VariantTestCase test_case = GetParam(); util::StatusOr parameters = SlhDsaParameters::Create( SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kSmallSignature, test_case.variant); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetHashType(), Eq(SlhDsaParameters::HashType::kSha2)); EXPECT_THAT(parameters->GetPrivateKeySizeInBytes(), Eq(64)); EXPECT_THAT(parameters->GetSignatureType(), Eq(SlhDsaParameters::SignatureType::kSmallSignature)); EXPECT_THAT(parameters->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(parameters->HasIdRequirement(), Eq(test_case.has_id_requirement)); } TEST(SlhDsaParametersTest, CreateWithInvalidVariantFails) { EXPECT_THAT( SlhDsaParameters::Create( SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kSmallSignature, SlhDsaParameters::Variant:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(SlhDsaParametersTest, CreateWithInvalidHashTypeFails) { EXPECT_THAT(SlhDsaParameters::Create( SlhDsaParameters::HashType:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kSmallSignature, SlhDsaParameters::Variant::kTink) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(SlhDsaParametersTest, CreateWithUnsupportedHashTypeFails) { EXPECT_THAT( SlhDsaParameters::Create(SlhDsaParameters::HashType::kShake, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kSmallSignature, SlhDsaParameters::Variant::kTink) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(SlhDsaParametersTest, CreateWithInvalidSignatureTypeFails) { EXPECT_THAT(SlhDsaParameters::Create( SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements, SlhDsaParameters::Variant::kTink) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(SlhDsaParametersTest, CreateWithUnsupportedSignatureTypeFails) { EXPECT_THAT( SlhDsaParameters::Create(SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kFastSigning, SlhDsaParameters::Variant::kTink) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(SlhDsaParametersTest, CreateWithInvalidKeySizeFails) { EXPECT_THAT( SlhDsaParameters::Create(SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/31, SlhDsaParameters::SignatureType::kSmallSignature, SlhDsaParameters::Variant::kTink) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(SlhDsaParametersTest, CreateWithUnsupportedKeySizeFails) { EXPECT_THAT( SlhDsaParameters::Create(SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/128, SlhDsaParameters::SignatureType::kSmallSignature, SlhDsaParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(SlhDsaParametersTest, CopyConstructor) { util::StatusOr parameters = SlhDsaParameters::Create(SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kSmallSignature, SlhDsaParameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); SlhDsaParameters copy(*parameters); EXPECT_THAT(copy.GetHashType(), Eq(SlhDsaParameters::HashType::kSha2)); EXPECT_THAT(copy.GetPrivateKeySizeInBytes(), Eq(64)); EXPECT_THAT(copy.GetSignatureType(), Eq(SlhDsaParameters::SignatureType::kSmallSignature)); EXPECT_THAT(copy.GetVariant(), Eq(SlhDsaParameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); } TEST(SlhDsaParametersTest, CopyAssignment) { util::StatusOr parameters = SlhDsaParameters::Create(SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kSmallSignature, SlhDsaParameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); SlhDsaParameters copy = *parameters; EXPECT_THAT(copy.GetHashType(), Eq(SlhDsaParameters::HashType::kSha2)); EXPECT_THAT(copy.GetPrivateKeySizeInBytes(), Eq(64)); EXPECT_THAT(copy.GetSignatureType(), Eq(SlhDsaParameters::SignatureType::kSmallSignature)); EXPECT_THAT(copy.GetVariant(), Eq(SlhDsaParameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); } TEST_P(SlhDsaParametersTest, ParametersEquals) { VariantTestCase test_case = GetParam(); util::StatusOr parameters = SlhDsaParameters::Create( SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kSmallSignature, test_case.variant); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = SlhDsaParameters::Create( SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kSmallSignature, test_case.variant); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters == *other_parameters); EXPECT_TRUE(*other_parameters == *parameters); EXPECT_FALSE(*parameters != *other_parameters); EXPECT_FALSE(*other_parameters != *parameters); } TEST(SlhDsaParametersTest, DifferentVariantNotEqual) { util::StatusOr parameters = SlhDsaParameters::Create( SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kSmallSignature, SlhDsaParameters::Variant::kNoPrefix); util::StatusOr other_parameters = SlhDsaParameters::Create(SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kSmallSignature, SlhDsaParameters::Variant::kTink); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/slh_dsa_private_key.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/slh_dsa_private_key.h" #include #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "openssl/boringssl/src/include/openssl/mem.h" #define OPENSSL_UNSTABLE_EXPERIMENTAL_SPX #include "openssl/experimental/spx.h" #undef OPENSSL_UNSTABLE_EXPERIMENTAL_SPX #include "tink/experimental/pqcrypto/signature/slh_dsa_public_key.h" #include "tink/insecure_secret_key_access.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { util::StatusOr SlhDsaPrivateKey::Create( const SlhDsaPublicKey& public_key, const RestrictedData& private_key_bytes, PartialKeyAccessToken token) { // Only 64-byte private keys are currently supported. if (private_key_bytes.size() != SPX_SECRET_KEY_BYTES) { return util::Status(absl::StatusCode::kInvalidArgument, "SLH-DSA private key length must be 64 bytes."); } if (public_key.GetParameters().GetPrivateKeySizeInBytes() != private_key_bytes.size()) { return util::Status(absl::StatusCode::kInvalidArgument, "Private key size does not match parameters"); } // Confirm that the private key and public key are a valid SLH-DSA key pair. std::string public_key_bytes_regen; public_key_bytes_regen.resize(SPX_PUBLIC_KEY_BYTES); std::string private_key_bytes_regen; private_key_bytes_regen.resize(SPX_SECRET_KEY_BYTES); absl::string_view expected_private_key_bytes = private_key_bytes.GetSecret(InsecureSecretKeyAccess::Get()); SPX_generate_key_from_seed( reinterpret_cast(public_key_bytes_regen.data()), reinterpret_cast(private_key_bytes_regen.data()), // Uses the first 48 bytes of the private key as seed. reinterpret_cast(expected_private_key_bytes.data())); absl::string_view expected_public_key_bytes = public_key.GetPublicKeyBytes(token); if (CRYPTO_memcmp(expected_public_key_bytes.data(), public_key_bytes_regen.data(), SPX_PUBLIC_KEY_BYTES) != 0 || CRYPTO_memcmp(expected_private_key_bytes.data(), private_key_bytes_regen.data(), SPX_SECRET_KEY_BYTES) != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid SLH-DSA key pair"); } return SlhDsaPrivateKey(public_key, private_key_bytes); } bool SlhDsaPrivateKey::operator==(const Key& other) const { const SlhDsaPrivateKey* that = dynamic_cast(&other); if (that == nullptr) { return false; } return public_key_ == that->public_key_ && private_key_bytes_ == that->private_key_bytes_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/slh_dsa_private_key.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SLH_DSA_PRIVATE_KEY_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SLH_DSA_PRIVATE_KEY_H_ #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/experimental/pqcrypto/signature/slh_dsa_public_key.h" #include "tink/signature/signature_private_key.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { class SlhDsaPrivateKey : public SignaturePrivateKey { public: // Copyable and movable. SlhDsaPrivateKey(const SlhDsaPrivateKey& other) = default; SlhDsaPrivateKey& operator=(const SlhDsaPrivateKey& other) = default; SlhDsaPrivateKey(SlhDsaPrivateKey&& other) = default; SlhDsaPrivateKey& operator=(SlhDsaPrivateKey&& other) = default; // Creates a new SLH-DSA private key from `private_key_bytes`. Returns an // error if `public_key` does not belong to the same key pair as // `private_key_bytes`. static util::StatusOr Create( const SlhDsaPublicKey& public_key, const RestrictedData& private_key_bytes, PartialKeyAccessToken token); const RestrictedData& GetPrivateKeyBytes(PartialKeyAccessToken token) const { return private_key_bytes_; } const SlhDsaPublicKey& GetPublicKey() const override { return public_key_; } bool operator==(const Key& other) const override; private: explicit SlhDsaPrivateKey(const SlhDsaPublicKey& public_key, const RestrictedData& private_key_bytes) : public_key_(public_key), private_key_bytes_(private_key_bytes) {} SlhDsaPublicKey public_key_; RestrictedData private_key_bytes_; }; } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SLH_DSA_PRIVATE_KEY_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/slh_dsa_private_key_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/slh_dsa_private_key.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #define OPENSSL_UNSTABLE_EXPERIMENTAL_SPX #include "openssl/experimental/spx.h" #undef OPENSSL_UNSTABLE_EXPERIMENTAL_SPX #include "tink/experimental/pqcrypto/signature/slh_dsa_parameters.h" #include "tink/experimental/pqcrypto/signature/slh_dsa_public_key.h" #include "tink/insecure_secret_key_access.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/subtle/random.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { SlhDsaParameters::Variant variant; absl::optional id_requirement; std::string output_prefix; }; using SlhDsaPrivateKeyTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( SlhDsaPrivateKeyTestSuite, SlhDsaPrivateKeyTest, Values(TestCase{SlhDsaParameters::Variant::kTink, 0x02030400, std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{SlhDsaParameters::Variant::kTink, 0x03050709, std::string("\x01\x03\x05\x07\x09", 5)}, TestCase{SlhDsaParameters::Variant::kNoPrefix, absl::nullopt, ""})); TEST_P(SlhDsaPrivateKeyTest, CreateSucceeds) { TestCase test_case = GetParam(); util::StatusOr parameters = SlhDsaParameters::Create( SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/SPX_SECRET_KEY_BYTES, SlhDsaParameters::SignatureType::kSmallSignature, test_case.variant); ASSERT_THAT(parameters, IsOk()); std::string public_key_bytes; public_key_bytes.resize(SPX_PUBLIC_KEY_BYTES); std::string private_key_bytes; private_key_bytes.resize(SPX_SECRET_KEY_BYTES); SPX_generate_key(reinterpret_cast(public_key_bytes.data()), reinterpret_cast(private_key_bytes.data())); util::StatusOr public_key = SlhDsaPublicKey::Create(*parameters, public_key_bytes, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); RestrictedData restricted_private_key_bytes = RestrictedData(private_key_bytes, InsecureSecretKeyAccess::Get()); util::StatusOr private_key = SlhDsaPrivateKey::Create( *public_key, restricted_private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); EXPECT_THAT(private_key->GetParameters(), Eq(*parameters)); EXPECT_THAT(private_key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(private_key->GetPublicKey(), Eq(*public_key)); EXPECT_THAT(private_key->GetOutputPrefix(), Eq(test_case.output_prefix)); EXPECT_THAT(private_key->GetPrivateKeyBytes(GetPartialKeyAccess()), Eq(restricted_private_key_bytes)); } TEST(SlhDsaPrivateKeyTest, CreateWithInvalidPrivateKeyLengthFails) { util::StatusOr parameters = SlhDsaParameters::Create( SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/SPX_SECRET_KEY_BYTES, SlhDsaParameters::SignatureType::kSmallSignature, SlhDsaParameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); util::StatusOr public_key = SlhDsaPublicKey::Create( *parameters, subtle::Random::GetRandomBytes(SPX_PUBLIC_KEY_BYTES), /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); RestrictedData restricted_private_key_bytes = RestrictedData( subtle::Random::GetRandomBytes(63), InsecureSecretKeyAccess::Get()); EXPECT_THAT( SlhDsaPrivateKey::Create(*public_key, restricted_private_key_bytes, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("SLH-DSA private key length must be " "64 bytes"))); } TEST(SlhDsaPrivateKeyTest, CreateWithMismatchedPairFails) { util::StatusOr parameters = SlhDsaParameters::Create( SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/SPX_SECRET_KEY_BYTES, SlhDsaParameters::SignatureType::kSmallSignature, SlhDsaParameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); std::string public_key_bytes; public_key_bytes.resize(SPX_PUBLIC_KEY_BYTES); std::string private_key_bytes; private_key_bytes.resize(SPX_SECRET_KEY_BYTES); SPX_generate_key(reinterpret_cast(public_key_bytes.data()), reinterpret_cast(private_key_bytes.data())); util::StatusOr public_key = SlhDsaPublicKey::Create(*parameters, public_key_bytes, /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); // Generate a new key pair. SPX_generate_key(reinterpret_cast(public_key_bytes.data()), reinterpret_cast(private_key_bytes.data())); RestrictedData restricted_private_key_bytes = RestrictedData(private_key_bytes, InsecureSecretKeyAccess::Get()); // Creating the private key using the different private_key_bytes should fail. EXPECT_THAT( SlhDsaPrivateKey::Create(*public_key, restricted_private_key_bytes, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Invalid SLH-DSA key pair"))); } TEST(SlhDsaPrivateKeyTest, CreateWithModifiedPrivateKeyFails) { util::StatusOr parameters = SlhDsaParameters::Create( SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/SPX_SECRET_KEY_BYTES, SlhDsaParameters::SignatureType::kSmallSignature, SlhDsaParameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); std::string public_key_bytes; public_key_bytes.resize(SPX_PUBLIC_KEY_BYTES); std::string private_key_bytes; private_key_bytes.resize(SPX_SECRET_KEY_BYTES); SPX_generate_key(reinterpret_cast(public_key_bytes.data()), reinterpret_cast(private_key_bytes.data())); util::StatusOr public_key = SlhDsaPublicKey::Create(*parameters, public_key_bytes, /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); // Replace last 16 bytes of the private key bytes with random bytes. private_key_bytes.replace(/*seed_size=*/48, /*pk_root_size=*/16, subtle::Random::GetRandomBytes(16)); RestrictedData restricted_private_key_bytes = RestrictedData(private_key_bytes, InsecureSecretKeyAccess::Get()); EXPECT_THAT( SlhDsaPrivateKey::Create(*public_key, restricted_private_key_bytes, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Invalid SLH-DSA key pair"))); } TEST_P(SlhDsaPrivateKeyTest, KeyEquals) { TestCase test_case = GetParam(); util::StatusOr parameters = SlhDsaParameters::Create( SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/SPX_SECRET_KEY_BYTES, SlhDsaParameters::SignatureType::kSmallSignature, test_case.variant); ASSERT_THAT(parameters, IsOk()); std::string public_key_bytes; public_key_bytes.resize(SPX_PUBLIC_KEY_BYTES); std::string private_key_bytes; private_key_bytes.resize(SPX_SECRET_KEY_BYTES); SPX_generate_key(reinterpret_cast(public_key_bytes.data()), reinterpret_cast(private_key_bytes.data())); util::StatusOr public_key = SlhDsaPublicKey::Create(*parameters, public_key_bytes, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); RestrictedData restricted_private_key_bytes = RestrictedData(private_key_bytes, InsecureSecretKeyAccess::Get()); util::StatusOr private_key = SlhDsaPrivateKey::Create( *public_key, restricted_private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr other_private_key = SlhDsaPrivateKey::Create( *public_key, restricted_private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(other_private_key, IsOk()); EXPECT_TRUE(*private_key == *other_private_key); EXPECT_TRUE(*other_private_key == *private_key); EXPECT_FALSE(*private_key != *other_private_key); EXPECT_FALSE(*other_private_key != *private_key); } TEST(SlhDsaPrivateKeyTest, DifferentPublicKeyNotEqual) { util::StatusOr parameters = SlhDsaParameters::Create( SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/SPX_SECRET_KEY_BYTES, SlhDsaParameters::SignatureType::kSmallSignature, SlhDsaParameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); std::string public_key_bytes; public_key_bytes.resize(SPX_PUBLIC_KEY_BYTES); std::string private_key_bytes; private_key_bytes.resize(parameters->GetPrivateKeySizeInBytes()); SPX_generate_key(reinterpret_cast(public_key_bytes.data()), reinterpret_cast(private_key_bytes.data())); util::StatusOr public_key123 = SlhDsaPublicKey::Create(*parameters, public_key_bytes, /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(public_key123, IsOk()); util::StatusOr public_key456 = SlhDsaPublicKey::Create(*parameters, public_key_bytes, /*id_requirement=*/456, GetPartialKeyAccess()); ASSERT_THAT(public_key456, IsOk()); RestrictedData restricted_private_key_bytes = RestrictedData(private_key_bytes, InsecureSecretKeyAccess::Get()); util::StatusOr private_key = SlhDsaPrivateKey::Create( *public_key123, restricted_private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr other_private_key = SlhDsaPrivateKey::Create( *public_key456, restricted_private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(other_private_key, IsOk()); EXPECT_TRUE(*private_key != *other_private_key); EXPECT_TRUE(*other_private_key != *private_key); EXPECT_FALSE(*private_key == *other_private_key); EXPECT_FALSE(*other_private_key == *private_key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/slh_dsa_proto_serialization.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/slh_dsa_proto_serialization.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/experimental/pqcrypto/signature/slh_dsa_parameters.h" #include "tink/experimental/pqcrypto/signature/slh_dsa_private_key.h" #include "tink/experimental/pqcrypto/signature/slh_dsa_public_key.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/key_parser.h" #include "tink/internal/key_serializer.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/parameters_parser.h" #include "tink/internal/parameters_serializer.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/secret_key_access_token.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/experimental/pqcrypto/slh_dsa.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::google::crypto::tink::SlhDsaHashType; using ::google::crypto::tink::SlhDsaKeyFormat; using ::google::crypto::tink::SlhDsaParams; using ::google::crypto::tink::SlhDsaSignatureType; using SlhDsaProtoParametersParserImpl = internal::ParametersParserImpl; using SlhDsaProtoParametersSerializerImpl = internal::ParametersSerializerImpl; using SlhDsaProtoPublicKeyParserImpl = internal::KeyParserImpl; using SlhDsaProtoPublicKeySerializerImpl = internal::KeySerializerImpl; using SlhDsaProtoPrivateKeyParserImpl = internal::KeyParserImpl; using SlhDsaProtoPrivateKeySerializerImpl = internal::KeySerializerImpl; const absl::string_view kPrivateTypeUrl = "type.googleapis.com/google.crypto.tink.SlhDsaPrivateKey"; const absl::string_view kPublicTypeUrl = "type.googleapis.com/google.crypto.tink.SlhDsaPublicKey"; util::StatusOr ToVariant( OutputPrefixType output_prefix_type) { switch (output_prefix_type) { case OutputPrefixType::RAW: return SlhDsaParameters::Variant::kNoPrefix; case OutputPrefixType::TINK: return SlhDsaParameters::Variant::kTink; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine SlhDsaParameters::Variant"); } } util::StatusOr ToOutputPrefixType( SlhDsaParameters::Variant variant) { switch (variant) { case SlhDsaParameters::Variant::kNoPrefix: return OutputPrefixType::RAW; case SlhDsaParameters::Variant::kTink: return OutputPrefixType::TINK; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine output prefix type"); } } util::StatusOr ToHashType( SlhDsaHashType proto_hash_type) { switch (proto_hash_type) { case SlhDsaHashType::SHA2: return SlhDsaParameters::HashType::kSha2; case SlhDsaHashType::SHAKE: return SlhDsaParameters::HashType::kShake; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine SlhDsaParameters::HashType"); } } util::StatusOr ToProtoHashType( SlhDsaParameters::HashType hash_type) { switch (hash_type) { case SlhDsaParameters::HashType::kSha2: return SlhDsaHashType::SHA2; case SlhDsaParameters::HashType::kShake: return SlhDsaHashType::SHAKE; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine SlhDsaHashType"); } } util::StatusOr ToSignatureType( SlhDsaSignatureType proto_signature_type) { switch (proto_signature_type) { case SlhDsaSignatureType::FAST_SIGNING: return SlhDsaParameters::SignatureType::kFastSigning; case SlhDsaSignatureType::SMALL_SIGNATURE: return SlhDsaParameters::SignatureType::kSmallSignature; default: return util::Status( absl::StatusCode::kInvalidArgument, "Could not determine SlhDsaParameters::SignatureType"); } } util::StatusOr ToProtoSignatureType( SlhDsaParameters::SignatureType signature_type) { switch (signature_type) { case SlhDsaParameters::SignatureType::kFastSigning: return SlhDsaSignatureType::FAST_SIGNING; case SlhDsaParameters::SignatureType::kSmallSignature: return SlhDsaSignatureType::SMALL_SIGNATURE; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine SlhDsaSignatureType"); } } util::StatusOr ToParameters( OutputPrefixType output_prefix_type, const SlhDsaParams& params) { util::StatusOr variant = ToVariant(output_prefix_type); if (!variant.ok()) { return variant.status(); } util::StatusOr hash_type = ToHashType(params.hash_type()); if (!hash_type.ok()) { return hash_type.status(); } util::StatusOr signature_type = ToSignatureType(params.sig_type()); if (!signature_type.ok()) { return signature_type.status(); } return SlhDsaParameters::Create(*hash_type, params.key_size(), *signature_type, *variant); } util::StatusOr FromParameters( const SlhDsaParameters& parameters) { /* Only SLH-DSA-SHA2-128s is currently supported*/ util::StatusOr hash_type = ToProtoHashType(parameters.GetHashType()); if (!hash_type.ok()) { return hash_type.status(); } util::StatusOr signature_type = ToProtoSignatureType(parameters.GetSignatureType()); if (!signature_type.ok()) { return signature_type.status(); } SlhDsaParams params; params.set_key_size(parameters.GetPrivateKeySizeInBytes()); params.set_hash_type(*hash_type); params.set_sig_type(*signature_type); return params; } util::StatusOr ParseParameters( const internal::ProtoParametersSerialization& serialization) { if (serialization.GetKeyTemplate().type_url() != kPrivateTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing SlhDsaParameters."); } SlhDsaKeyFormat proto_key_format; if (!proto_key_format.ParseFromString( serialization.GetKeyTemplate().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse SlhDsaKeyFormat proto"); } if (proto_key_format.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } if (!proto_key_format.has_params()) { return util::Status(absl::StatusCode::kInvalidArgument, "SlhDsaKeyFormat proto is missing params field."); } return ToParameters(serialization.GetKeyTemplate().output_prefix_type(), proto_key_format.params()); } util::StatusOr ParsePublicKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (serialization.TypeUrl() != kPublicTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing SlhDsaPublicKey."); } google::crypto::tink::SlhDsaPublicKey proto_key; const RestrictedData& restricted_data = serialization.SerializedKeyProto(); if (!proto_key.ParseFromString( restricted_data.GetSecret(InsecureSecretKeyAccess::Get()))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse SlhDsaPublicKey proto"); } if (proto_key.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } util::StatusOr parameters = ToParameters(serialization.GetOutputPrefixType(), proto_key.params()); if (!parameters.ok()) { return parameters.status(); } return SlhDsaPublicKey::Create(*parameters, proto_key.key_value(), serialization.IdRequirement(), GetPartialKeyAccess()); } util::StatusOr ParsePrivateKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (serialization.TypeUrl() != kPrivateTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing SlhDsaPrivateKey."); } if (!token.has_value()) { return util::Status(absl::StatusCode::kPermissionDenied, "SecretKeyAccess is required"); } google::crypto::tink::SlhDsaPrivateKey proto_key; const RestrictedData& restricted_data = serialization.SerializedKeyProto(); if (!proto_key.ParseFromString(restricted_data.GetSecret(*token))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse SlhDsaPrivateKey proto"); } if (proto_key.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } util::StatusOr parameters = ToParameters( serialization.GetOutputPrefixType(), proto_key.public_key().params()); if (!parameters.ok()) { return parameters.status(); } util::StatusOr public_key = SlhDsaPublicKey::Create( *parameters, proto_key.public_key().key_value(), serialization.IdRequirement(), GetPartialKeyAccess()); if (!public_key.ok()) { return public_key.status(); } return SlhDsaPrivateKey::Create(*public_key, RestrictedData(proto_key.key_value(), *token), GetPartialKeyAccess()); } util::StatusOr SerializeParameters( const SlhDsaParameters& parameters) { util::StatusOr output_prefix_type = ToOutputPrefixType(parameters.GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } util::StatusOr params = FromParameters(parameters); if (!params.ok()) { return params.status(); } SlhDsaKeyFormat proto_key_format; *proto_key_format.mutable_params() = *params; proto_key_format.set_version(0); return internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, *output_prefix_type, proto_key_format.SerializeAsString()); } util::StatusOr SerializePublicKey( const SlhDsaPublicKey& key, absl::optional token) { util::StatusOr params = FromParameters(key.GetParameters()); if (!params.ok()) { return params.status(); } google::crypto::tink::SlhDsaPublicKey proto_key; proto_key.set_version(0); *proto_key.mutable_params() = *params; proto_key.set_key_value(key.GetPublicKeyBytes(GetPartialKeyAccess())); util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetParameters().GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } RestrictedData restricted_output = RestrictedData( proto_key.SerializeAsString(), InsecureSecretKeyAccess::Get()); return internal::ProtoKeySerialization::Create( kPublicTypeUrl, restricted_output, KeyData::ASYMMETRIC_PUBLIC, *output_prefix_type, key.GetIdRequirement()); } util::StatusOr SerializePrivateKey( const SlhDsaPrivateKey& key, absl::optional token) { if (!token.has_value()) { return util::Status(absl::StatusCode::kPermissionDenied, "SecretKeyAccess is required"); } util::StatusOr restricted_input = key.GetPrivateKeyBytes(GetPartialKeyAccess()); if (!restricted_input.ok()) { return restricted_input.status(); } util::StatusOr params = FromParameters(key.GetPublicKey().GetParameters()); if (!params.ok()) { return params.status(); } google::crypto::tink::SlhDsaPublicKey proto_public_key; proto_public_key.set_version(0); *proto_public_key.mutable_params() = *params; proto_public_key.set_key_value( key.GetPublicKey().GetPublicKeyBytes(GetPartialKeyAccess())); google::crypto::tink::SlhDsaPrivateKey proto_private_key; proto_private_key.set_version(0); *proto_private_key.mutable_public_key() = proto_public_key; proto_private_key.set_key_value(restricted_input->GetSecret(*token)); util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetPublicKey().GetParameters().GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } RestrictedData restricted_output = RestrictedData(proto_private_key.SerializeAsString(), *token); return internal::ProtoKeySerialization::Create( kPrivateTypeUrl, restricted_output, KeyData::ASYMMETRIC_PRIVATE, *output_prefix_type, key.GetIdRequirement()); } SlhDsaProtoParametersParserImpl& SlhDsaProtoParametersParser() { static auto parser = new SlhDsaProtoParametersParserImpl(kPrivateTypeUrl, ParseParameters); return *parser; } SlhDsaProtoParametersSerializerImpl& SlhDsaProtoParametersSerializer() { static auto serializer = new SlhDsaProtoParametersSerializerImpl( kPrivateTypeUrl, SerializeParameters); return *serializer; } SlhDsaProtoPublicKeyParserImpl& SlhDsaProtoPublicKeyParser() { static auto* parser = new SlhDsaProtoPublicKeyParserImpl(kPublicTypeUrl, ParsePublicKey); return *parser; } SlhDsaProtoPublicKeySerializerImpl& SlhDsaProtoPublicKeySerializer() { static auto* serializer = new SlhDsaProtoPublicKeySerializerImpl(SerializePublicKey); return *serializer; } SlhDsaProtoPrivateKeyParserImpl& SlhDsaProtoPrivateKeyParser() { static auto* parser = new SlhDsaProtoPrivateKeyParserImpl(kPrivateTypeUrl, ParsePrivateKey); return *parser; } SlhDsaProtoPrivateKeySerializerImpl& SlhDsaProtoPrivateKeySerializer() { static auto* serializer = new SlhDsaProtoPrivateKeySerializerImpl(SerializePrivateKey); return *serializer; } } // namespace util::Status RegisterSlhDsaProtoSerialization() { util::Status status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersParser(&SlhDsaProtoParametersParser()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersSerializer(&SlhDsaProtoParametersSerializer()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(&SlhDsaProtoPublicKeyParser()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(&SlhDsaProtoPublicKeySerializer()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(&SlhDsaProtoPrivateKeyParser()); if (!status.ok()) { return status; } return internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(&SlhDsaProtoPrivateKeySerializer()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/slh_dsa_proto_serialization.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SLH_DSA_PROTO_SERIALIZATION_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SLH_DSA_PROTO_SERIALIZATION_H_ #include "tink/util/status.h" namespace crypto { namespace tink { // Registers proto parsers and serializers for SLH-DSA parameters and keys. crypto::tink::util::Status RegisterSlhDsaProtoSerialization(); } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SLH_DSA_PROTO_SERIALIZATION_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/slh_dsa_proto_serialization_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/slh_dsa_proto_serialization.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #define OPENSSL_UNSTABLE_EXPERIMENTAL_SPX #include "openssl/experimental/spx.h" #undef OPENSSL_UNSTABLE_EXPERIMENTAL_SPX #include "tink/experimental/pqcrypto/signature/slh_dsa_parameters.h" #include "tink/experimental/pqcrypto/signature/slh_dsa_private_key.h" #include "tink/experimental/pqcrypto/signature/slh_dsa_public_key.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/subtle/random.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/experimental/pqcrypto/slh_dsa.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::subtle::Random; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::google::crypto::tink::SlhDsaHashType; using ::google::crypto::tink::SlhDsaKeyFormat; using ::google::crypto::tink::SlhDsaParams; using ::google::crypto::tink::SlhDsaSignatureType; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::IsTrue; using ::testing::NotNull; using ::testing::TestWithParam; using ::testing::Values; const absl::string_view kPrivateTypeUrl = "type.googleapis.com/google.crypto.tink.SlhDsaPrivateKey"; const absl::string_view kPublicTypeUrl = "type.googleapis.com/google.crypto.tink.SlhDsaPublicKey"; struct TestCase { SlhDsaParameters::Variant variant; OutputPrefixType output_prefix_type; absl::optional id_requirement; std::string output_prefix; }; class SlhDsaProtoSerializationTest : public TestWithParam { protected: SlhDsaProtoSerializationTest() { internal::MutableSerializationRegistry::GlobalInstance().Reset(); } }; TEST_F(SlhDsaProtoSerializationTest, RegisterTwiceSucceeds) { ASSERT_THAT(RegisterSlhDsaProtoSerialization(), IsOk()); ASSERT_THAT(RegisterSlhDsaProtoSerialization(), IsOk()); } INSTANTIATE_TEST_SUITE_P( SlhDsaProtoSerializationTestSuite, SlhDsaProtoSerializationTest, Values(TestCase{SlhDsaParameters::Variant::kTink, OutputPrefixType::TINK, 0x02030400, std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{SlhDsaParameters::Variant::kTink, OutputPrefixType::TINK, 0x03050709, std::string("\x01\x03\x05\x07\x09", 5)}, TestCase{SlhDsaParameters::Variant::kNoPrefix, OutputPrefixType::RAW, absl::nullopt, ""})); TEST_P(SlhDsaProtoSerializationTest, ParseSlhDsa128Sha2SmallSignatureParametersWorks) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterSlhDsaProtoSerialization(), IsOk()); SlhDsaKeyFormat key_format_proto; SlhDsaParams& params = *key_format_proto.mutable_params(); params.set_sig_type(SlhDsaSignatureType::SMALL_SIGNATURE); params.set_hash_type(SlhDsaHashType::SHA2); params.set_key_size(64); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, test_case.output_prefix_type, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(parameters, IsOk()); EXPECT_EQ((*parameters)->HasIdRequirement(), test_case.id_requirement.has_value()); const SlhDsaParameters* slh_dsa_parameters = dynamic_cast(parameters->get()); ASSERT_THAT(slh_dsa_parameters, NotNull()); EXPECT_THAT(slh_dsa_parameters->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(slh_dsa_parameters->GetPrivateKeySizeInBytes(), Eq(64)); EXPECT_THAT(slh_dsa_parameters->GetSignatureType(), Eq(SlhDsaParameters::SignatureType::kSmallSignature)); EXPECT_THAT(slh_dsa_parameters->GetHashType(), Eq(SlhDsaParameters::HashType::kSha2)); } TEST_F(SlhDsaProtoSerializationTest, ParseParametersWithInvalidSerializationFails) { ASSERT_THAT(RegisterSlhDsaProtoSerialization(), IsOk()); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::RAW, "invalid_serialization"); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT(internal::MutableSerializationRegistry::GlobalInstance() .ParseParameters(*serialization) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Failed to parse SlhDsaKeyFormat proto"))); } TEST_F(SlhDsaProtoSerializationTest, ParseParametersWithInvalidVersionFails) { ASSERT_THAT(RegisterSlhDsaProtoSerialization(), IsOk()); SlhDsaKeyFormat key_format_proto; key_format_proto.set_version(1); SlhDsaParams& params = *key_format_proto.mutable_params(); params.set_sig_type(SlhDsaSignatureType::SMALL_SIGNATURE); params.set_hash_type(SlhDsaHashType::SHA2); params.set_key_size(64); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::RAW, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Only version 0 keys are accepted"))); } TEST_F(SlhDsaProtoSerializationTest, ParseParametersKeyFormatWithoutParamsFails) { ASSERT_THAT(RegisterSlhDsaProtoSerialization(), IsOk()); SlhDsaKeyFormat key_format_proto; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::RAW, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("SlhDsaKeyFormat proto is missing params"))); } TEST_F(SlhDsaProtoSerializationTest, ParseParametersWithUnkownOutputPrefixFails) { ASSERT_THAT(RegisterSlhDsaProtoSerialization(), IsOk()); SlhDsaKeyFormat key_format_proto; SlhDsaParams& params = *key_format_proto.mutable_params(); params.set_sig_type(SlhDsaSignatureType::SMALL_SIGNATURE); params.set_hash_type(SlhDsaHashType::SHA2); params.set_key_size(64); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::UNKNOWN_PREFIX, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT( parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Could not determine SlhDsaParameters::Variant"))); } TEST_F(SlhDsaProtoSerializationTest, ParseParametersWithUnkownSigTypeFails) { ASSERT_THAT(RegisterSlhDsaProtoSerialization(), IsOk()); SlhDsaKeyFormat key_format_proto; SlhDsaParams& params = *key_format_proto.mutable_params(); params.set_sig_type(SlhDsaSignatureType::SLH_DSA_SIGNATURE_TYPE_UNSPECIFIED); params.set_hash_type(SlhDsaHashType::SHA2); params.set_key_size(64); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::RAW, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT( parameters.status(), StatusIs( absl::StatusCode::kInvalidArgument, HasSubstr("Could not determine SlhDsaParameters::SignatureType"))); } TEST_F(SlhDsaProtoSerializationTest, ParseParametersWithUnkownHashTypeFails) { ASSERT_THAT(RegisterSlhDsaProtoSerialization(), IsOk()); SlhDsaKeyFormat key_format_proto; SlhDsaParams& params = *key_format_proto.mutable_params(); params.set_sig_type(SlhDsaSignatureType::SMALL_SIGNATURE); params.set_hash_type(SlhDsaHashType::SLH_DSA_HASH_TYPE_UNSPECIFIED); params.set_key_size(64); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::RAW, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT( parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Could not determine SlhDsaParameters::HashType"))); } TEST_P(SlhDsaProtoSerializationTest, SerializeSlhDsa128Sha2SmallSignatureParametersWorks) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterSlhDsaProtoSerialization(), IsOk()); util::StatusOr parameters = SlhDsaParameters::Create( SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kSmallSignature, test_case.variant); ASSERT_THAT(parameters, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( *parameters); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kPrivateTypeUrl)); const internal::ProtoParametersSerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->GetKeyTemplate().type_url(), Eq(kPrivateTypeUrl)); EXPECT_THAT(proto_serialization->GetKeyTemplate().output_prefix_type(), Eq(test_case.output_prefix_type)); SlhDsaKeyFormat key_format; ASSERT_THAT( key_format.ParseFromString(proto_serialization->GetKeyTemplate().value()), IsTrue()); ASSERT_TRUE(key_format.has_params()); EXPECT_THAT(key_format.params().hash_type(), Eq(SlhDsaHashType::SHA2)); EXPECT_THAT(key_format.params().sig_type(), Eq(SlhDsaSignatureType::SMALL_SIGNATURE)); EXPECT_THAT(key_format.params().key_size(), Eq(64)); } TEST_P(SlhDsaProtoSerializationTest, ParsePublicKeyWorks) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterSlhDsaProtoSerialization(), IsOk()); SlhDsaParams params; params.set_sig_type(SlhDsaSignatureType::SMALL_SIGNATURE); params.set_hash_type(SlhDsaHashType::SHA2); params.set_key_size(64); std::string raw_key_bytes = Random::GetRandomBytes(32); google::crypto::tink::SlhDsaPublicKey key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); *key_proto.mutable_params() = params; RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kPublicTypeUrl, serialized_key, KeyData::ASYMMETRIC_PUBLIC, test_case.output_prefix_type, test_case.id_requirement); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); ASSERT_THAT(key, IsOk()); EXPECT_THAT((*key)->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT((*key)->GetParameters().HasIdRequirement(), test_case.id_requirement.has_value()); util::StatusOr expected_parameters = SlhDsaParameters::Create( SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kSmallSignature, test_case.variant); ASSERT_THAT(expected_parameters, IsOk()); util::StatusOr expected_key = SlhDsaPublicKey::Create(*expected_parameters, raw_key_bytes, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(expected_key, IsOk()); EXPECT_THAT(**key, Eq(*expected_key)); } TEST_F(SlhDsaProtoSerializationTest, ParsePublicKeyWithInvalidSerializationFails) { ASSERT_THAT(RegisterSlhDsaProtoSerialization(), IsOk()); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPublicTypeUrl, serialized_key, KeyData::ASYMMETRIC_PUBLIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Failed to parse SlhDsaPublicKey proto"))); } TEST_F(SlhDsaProtoSerializationTest, ParsePublicKeyWithInvalidVersionFails) { ASSERT_THAT(RegisterSlhDsaProtoSerialization(), IsOk()); SlhDsaParams params; params.set_sig_type(SlhDsaSignatureType::SMALL_SIGNATURE); params.set_hash_type(SlhDsaHashType::SHA2); params.set_key_size(64); std::string raw_key_bytes = Random::GetRandomBytes(32); google::crypto::tink::SlhDsaPublicKey key_proto; key_proto.set_version(1); key_proto.set_key_value(raw_key_bytes); *key_proto.mutable_params() = params; RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPublicTypeUrl, serialized_key, KeyData::ASYMMETRIC_PUBLIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Only version 0 keys are accepted"))); } TEST_P(SlhDsaProtoSerializationTest, SerializePublicKeyWorks) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterSlhDsaProtoSerialization(), IsOk()); util::StatusOr parameters = SlhDsaParameters::Create( SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kSmallSignature, test_case.variant); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); util::StatusOr key = SlhDsaPublicKey::Create(*parameters, raw_key_bytes, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, /*token=*/absl::nullopt); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kPublicTypeUrl)); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq(kPublicTypeUrl)); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::ASYMMETRIC_PUBLIC)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id_requirement)); google::crypto::tink::SlhDsaPublicKey proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.version(), Eq(0)); EXPECT_THAT(proto_key.key_value(), Eq(raw_key_bytes)); EXPECT_THAT(proto_key.has_params(), IsTrue()); EXPECT_THAT(proto_key.params().key_size(), Eq(64)); EXPECT_THAT(proto_key.params().hash_type(), Eq(SlhDsaHashType::SHA2)); EXPECT_THAT(proto_key.params().sig_type(), Eq(SlhDsaSignatureType::SMALL_SIGNATURE)); } TEST_P(SlhDsaProtoSerializationTest, ParsePrivateKeyWorks) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterSlhDsaProtoSerialization(), IsOk()); std::string public_key_bytes; public_key_bytes.resize(SPX_PUBLIC_KEY_BYTES); std::string private_key_bytes; private_key_bytes.resize(SPX_SECRET_KEY_BYTES); SPX_generate_key(reinterpret_cast(public_key_bytes.data()), reinterpret_cast(private_key_bytes.data())); SlhDsaParams params; params.set_sig_type(SlhDsaSignatureType::SMALL_SIGNATURE); params.set_hash_type(SlhDsaHashType::SHA2); params.set_key_size(64); google::crypto::tink::SlhDsaPublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_key_value(public_key_bytes); *public_key_proto.mutable_params() = params; google::crypto::tink::SlhDsaPrivateKey private_key_proto; private_key_proto.set_version(0); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_key_value(private_key_bytes); RestrictedData serialized_key = RestrictedData( private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, test_case.output_prefix_type, test_case.id_requirement); ASSERT_THAT(serialization, IsOk()); util::StatusOr> private_key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(private_key, IsOk()); EXPECT_THAT((*private_key)->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT((*private_key)->GetParameters().HasIdRequirement(), test_case.id_requirement.has_value()); util::StatusOr expected_parameters = SlhDsaParameters::Create( SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kSmallSignature, test_case.variant); ASSERT_THAT(expected_parameters, IsOk()); util::StatusOr expected_public_key = SlhDsaPublicKey::Create(*expected_parameters, public_key_bytes, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(expected_public_key, IsOk()); util::StatusOr expected_private_key = SlhDsaPrivateKey::Create( *expected_public_key, RestrictedData(private_key_bytes, InsecureSecretKeyAccess::Get()), GetPartialKeyAccess()); ASSERT_THAT(expected_private_key, IsOk()); EXPECT_THAT(**private_key, Eq(*expected_private_key)); } TEST_F(SlhDsaProtoSerializationTest, ParsePrivateKeyWithInvalidSerialization) { ASSERT_THAT(RegisterSlhDsaProtoSerialization(), IsOk()); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Failed to parse SlhDsaPrivateKey proto"))); } TEST_F(SlhDsaProtoSerializationTest, ParsePrivateKeyWithInvalidVersion) { ASSERT_THAT(RegisterSlhDsaProtoSerialization(), IsOk()); std::string public_key_bytes; public_key_bytes.resize(SPX_PUBLIC_KEY_BYTES); std::string private_key_bytes; private_key_bytes.resize(SPX_SECRET_KEY_BYTES); SPX_generate_key(reinterpret_cast(public_key_bytes.data()), reinterpret_cast(private_key_bytes.data())); SlhDsaParams params; params.set_sig_type(SlhDsaSignatureType::SMALL_SIGNATURE); params.set_hash_type(SlhDsaHashType::SHA2); params.set_key_size(64); google::crypto::tink::SlhDsaPublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_key_value(public_key_bytes); *public_key_proto.mutable_params() = params; google::crypto::tink::SlhDsaPrivateKey private_key_proto; private_key_proto.set_version(1); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_key_value(private_key_bytes); RestrictedData serialized_key = RestrictedData( private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Only version 0 keys are accepted"))); } TEST_F(SlhDsaProtoSerializationTest, ParsePrivateKeyNoSecretKeyAccess) { ASSERT_THAT(RegisterSlhDsaProtoSerialization(), IsOk()); std::string public_key_bytes; public_key_bytes.resize(SPX_PUBLIC_KEY_BYTES); std::string private_key_bytes; private_key_bytes.resize(SPX_SECRET_KEY_BYTES); SPX_generate_key(reinterpret_cast(public_key_bytes.data()), reinterpret_cast(private_key_bytes.data())); SlhDsaParams params; params.set_sig_type(SlhDsaSignatureType::SMALL_SIGNATURE); params.set_hash_type(SlhDsaHashType::SHA2); params.set_key_size(64); google::crypto::tink::SlhDsaPublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_key_value(public_key_bytes); *public_key_proto.mutable_params() = params; google::crypto::tink::SlhDsaPrivateKey private_key_proto; private_key_proto.set_version(0); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_key_value(private_key_bytes); RestrictedData serialized_key = RestrictedData( private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kPermissionDenied)); } TEST_P(SlhDsaProtoSerializationTest, SerializePrivateKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterSlhDsaProtoSerialization(), IsOk()); std::string public_key_bytes; public_key_bytes.resize(SPX_PUBLIC_KEY_BYTES); std::string private_key_bytes; private_key_bytes.resize(SPX_SECRET_KEY_BYTES); SPX_generate_key(reinterpret_cast(public_key_bytes.data()), reinterpret_cast(private_key_bytes.data())); util::StatusOr parameters = SlhDsaParameters::Create( SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kSmallSignature, test_case.variant); ASSERT_THAT(parameters, IsOk()); util::StatusOr public_key = SlhDsaPublicKey::Create(*parameters, public_key_bytes, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = SlhDsaPrivateKey::Create( *public_key, RestrictedData(private_key_bytes, InsecureSecretKeyAccess::Get()), GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *private_key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kPrivateTypeUrl)); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq(kPrivateTypeUrl)); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::ASYMMETRIC_PRIVATE)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id_requirement)); google::crypto::tink::SlhDsaPrivateKey proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.version(), Eq(0)); EXPECT_THAT(proto_key.key_value(), Eq(private_key_bytes)); EXPECT_THAT(proto_key.has_public_key(), IsTrue()); EXPECT_THAT(proto_key.public_key().version(), Eq(0)); EXPECT_THAT(proto_key.public_key().key_value(), Eq(public_key_bytes)); EXPECT_THAT(proto_key.public_key().has_params(), IsTrue()); EXPECT_THAT(proto_key.public_key().params().key_size(), Eq(64)); EXPECT_THAT(proto_key.public_key().params().hash_type(), Eq(SlhDsaHashType::SHA2)); EXPECT_THAT(proto_key.public_key().params().sig_type(), Eq(SlhDsaSignatureType::SMALL_SIGNATURE)); } TEST_F(SlhDsaProtoSerializationTest, SerializePrivateKeyNoSecretKeyAccess) { ASSERT_THAT(RegisterSlhDsaProtoSerialization(), IsOk()); std::string public_key_bytes; public_key_bytes.resize(SPX_PUBLIC_KEY_BYTES); std::string private_key_bytes; private_key_bytes.resize(SPX_SECRET_KEY_BYTES); SPX_generate_key(reinterpret_cast(public_key_bytes.data()), reinterpret_cast(private_key_bytes.data())); util::StatusOr parameters = SlhDsaParameters::Create( SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kSmallSignature, SlhDsaParameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); util::StatusOr public_key = SlhDsaPublicKey::Create(*parameters, public_key_bytes, /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = SlhDsaPrivateKey::Create( *public_key, RestrictedData(private_key_bytes, InsecureSecretKeyAccess::Get()), GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *private_key, /*token=*/absl::nullopt); ASSERT_THAT(serialization.status(), StatusIs(absl::StatusCode::kPermissionDenied, HasSubstr("SecretKeyAccess is required"))); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/slh_dsa_public_key.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/slh_dsa_public_key.h" #include #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/experimental/pqcrypto/signature/slh_dsa_parameters.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { util::StatusOr ComputeOutputPrefix( const SlhDsaParameters& parameters, absl::optional id_requirement) { switch (parameters.GetVariant()) { case SlhDsaParameters::Variant::kNoPrefix: return std::string(""); // Empty prefix. case SlhDsaParameters::Variant::kTink: if (!id_requirement.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "ID requirement must have value with kTink"); } return absl::StrCat(absl::HexStringToBytes("01"), subtle::BigEndian32(*id_requirement)); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid variant: ", parameters.GetVariant())); } } } // namespace util::StatusOr SlhDsaPublicKey::Create( const SlhDsaParameters& parameters, absl::string_view public_key_bytes, absl::optional id_requirement, PartialKeyAccessToken token) { if (parameters.HasIdRequirement() && !id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key without ID requirement with parameters with ID " "requirement"); } if (!parameters.HasIdRequirement() && id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key with ID requirement with parameters without ID " "requirement"); } // Only 32-byte public keys are supported at the moment. if (public_key_bytes.size() != 32) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid public key size. Only 32-byte keys are " "currently supported."); } util::StatusOr output_prefix = ComputeOutputPrefix(parameters, id_requirement); if (!output_prefix.ok()) { return output_prefix.status(); } return SlhDsaPublicKey(parameters, public_key_bytes, id_requirement, *output_prefix); } bool SlhDsaPublicKey::operator==(const Key& other) const { const SlhDsaPublicKey* that = dynamic_cast(&other); if (that == nullptr) { return false; } return GetParameters() == that->GetParameters() && public_key_bytes_ == that->public_key_bytes_ && id_requirement_ == that->id_requirement_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/slh_dsa_public_key.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SLH_DSA_PUBLIC_KEY_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SLH_DSA_PUBLIC_KEY_H_ #include #include "absl/base/attributes.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/experimental/pqcrypto/signature/slh_dsa_parameters.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/signature/signature_public_key.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Representation of the verification function for the SLH-DSA digital signature // primitive. class SlhDsaPublicKey : public SignaturePublicKey { public: // Copyable and movable. SlhDsaPublicKey(const SlhDsaPublicKey& other) = default; SlhDsaPublicKey& operator=(const SlhDsaPublicKey& other) = default; SlhDsaPublicKey(SlhDsaPublicKey&& other) = default; SlhDsaPublicKey& operator=(SlhDsaPublicKey&& other) = default; // Creates a new SLH-DSA public key from `public_key_bytes`. If the // `parameters` specify a variant that uses a prefix, then `id_requirement` is // used to compute this prefix. static util::StatusOr Create( const SlhDsaParameters& parameters, absl::string_view public_key_bytes, absl::optional id_requirement, PartialKeyAccessToken token); absl::string_view GetPublicKeyBytes(PartialKeyAccessToken token) const ABSL_ATTRIBUTE_LIFETIME_BOUND { return public_key_bytes_; } absl::string_view GetOutputPrefix() const override { return output_prefix_; } const SlhDsaParameters& GetParameters() const override { return parameters_; } absl::optional GetIdRequirement() const override { return id_requirement_; } bool operator==(const Key& other) const override; private: explicit SlhDsaPublicKey(const SlhDsaParameters& parameters, absl::string_view public_key_bytes, absl::optional id_requirement, absl::string_view output_prefix) : parameters_(parameters), public_key_bytes_(public_key_bytes), id_requirement_(id_requirement), output_prefix_(output_prefix) {} SlhDsaParameters parameters_; std::string public_key_bytes_; absl::optional id_requirement_; std::string output_prefix_; }; } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SLH_DSA_PUBLIC_KEY_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/slh_dsa_public_key_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/slh_dsa_public_key.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/experimental/pqcrypto/signature/slh_dsa_parameters.h" #include "tink/partial_key_access.h" #include "tink/subtle/random.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { SlhDsaParameters::Variant variant; absl::optional id_requirement; std::string output_prefix; }; using SlhDsaPublicKeyTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( SlhDsaPublicKeyTestSuite, SlhDsaPublicKeyTest, Values(TestCase{SlhDsaParameters::Variant::kTink, 0x02030400, std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{SlhDsaParameters::Variant::kTink, 0x03050709, std::string("\x01\x03\x05\x07\x09", 5)}, TestCase{SlhDsaParameters::Variant::kNoPrefix, absl::nullopt, ""})); TEST_P(SlhDsaPublicKeyTest, CreatePublicKeyWorks) { TestCase test_case = GetParam(); util::StatusOr params = SlhDsaParameters::Create( SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kSmallSignature, test_case.variant); ASSERT_THAT(params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = SlhDsaPublicKey::Create(*params, public_key_bytes, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); EXPECT_THAT(public_key->GetParameters(), Eq(*params)); EXPECT_THAT(public_key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(public_key->GetOutputPrefix(), Eq(test_case.output_prefix)); EXPECT_THAT(public_key->GetPublicKeyBytes(GetPartialKeyAccess()), Eq(public_key_bytes)); } TEST(SlhDsaPublicKeyTest, CreateWithInvalidPublicKeyLengthFails) { util::StatusOr params = SlhDsaParameters::Create( SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kSmallSignature, SlhDsaParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(31); EXPECT_THAT( SlhDsaPublicKey::Create(*params, public_key_bytes, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Invalid public key size"))); } TEST(SlhDsaPublicKeyTest, CreateKeyWithNoIdRequirementWithTinkParamsFails) { util::StatusOr tink_params = SlhDsaParameters::Create( SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kSmallSignature, SlhDsaParameters::Variant::kTink); ASSERT_THAT(tink_params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); EXPECT_THAT(SlhDsaPublicKey::Create(*tink_params, public_key_bytes, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("key without ID requirement with parameters " "with ID requirement"))); } TEST(SlhDsaPublicKeyTest, CreateKeyWithIdRequirementWithNoPrefixParamsFails) { util::StatusOr no_prefix_params = SlhDsaParameters::Create(SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kSmallSignature, SlhDsaParameters::Variant::kNoPrefix); ASSERT_THAT(no_prefix_params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); EXPECT_THAT( SlhDsaPublicKey::Create(*no_prefix_params, public_key_bytes, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("key with ID requirement with parameters without ID " "requirement"))); } TEST_P(SlhDsaPublicKeyTest, PublicKeyEquals) { TestCase test_case = GetParam(); util::StatusOr params = SlhDsaParameters::Create( SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kSmallSignature, test_case.variant); ASSERT_THAT(params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = SlhDsaPublicKey::Create(*params, public_key_bytes, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = SlhDsaPublicKey::Create(*params, public_key_bytes, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key == *other_public_key); EXPECT_TRUE(*other_public_key == *public_key); EXPECT_FALSE(*public_key != *other_public_key); EXPECT_FALSE(*other_public_key != *public_key); } TEST(SlhDsaPublicKeyTest, DifferentPublicKeyBytesNotEqual) { util::StatusOr params = SlhDsaParameters::Create(SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kSmallSignature, SlhDsaParameters::Variant::kTink); std::string public_key_bytes1 = subtle::Random::GetRandomBytes(32); std::string public_key_bytes2 = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = SlhDsaPublicKey::Create( *params, public_key_bytes1, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = SlhDsaPublicKey::Create( *params, public_key_bytes2, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key != *other_public_key); EXPECT_TRUE(*other_public_key != *public_key); EXPECT_FALSE(*public_key == *other_public_key); EXPECT_FALSE(*other_public_key == *public_key); } TEST(SlhDsaPublicKeyTest, DifferentIdRequirementNotEqual) { util::StatusOr params = SlhDsaParameters::Create(SlhDsaParameters::HashType::kSha2, /*private_key_size_in_bytes=*/64, SlhDsaParameters::SignatureType::kSmallSignature, SlhDsaParameters::Variant::kTink); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = SlhDsaPublicKey::Create( *params, public_key_bytes, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = SlhDsaPublicKey::Create( *params, public_key_bytes, /*id_requirement=*/0x02030405, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key != *other_public_key); EXPECT_TRUE(*other_public_key != *public_key); EXPECT_FALSE(*public_key == *other_public_key); EXPECT_FALSE(*other_public_key == *public_key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/sphincs_key_template.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/sphincs_key_template.h" #include #include "absl/strings/str_cat.h" #include "tink/util/constants.h" #include "proto/experimental/pqcrypto/sphincs.pb.h" #include "proto/tink.pb.h" extern "C" { #include "third_party/pqclean/crypto_sign/sphincs-haraka-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256s-simple/api.h" } namespace crypto { namespace tink { namespace { using google::crypto::tink::KeyTemplate; using google::crypto::tink::OutputPrefixType; using ::google::crypto::tink::SphincsHashType; using ::google::crypto::tink::SphincsKeyFormat; using ::google::crypto::tink::SphincsParams; using ::google::crypto::tink::SphincsPrivateKey; using ::google::crypto::tink::SphincsSignatureType; using ::google::crypto::tink::SphincsVariant; KeyTemplate* NewSphincsKeyTemplate(int32_t private_key_size, SphincsHashType hash_type, SphincsVariant variant, SphincsSignatureType type) { KeyTemplate* key_template = new KeyTemplate; key_template->set_type_url( absl::StrCat(kTypeGoogleapisCom, SphincsPrivateKey().GetTypeName())); key_template->set_output_prefix_type(OutputPrefixType::TINK); SphincsKeyFormat key_format; SphincsParams* params = key_format.mutable_params(); params->set_key_size(private_key_size); params->set_hash_type(hash_type); params->set_variant(variant); params->set_sig_length_type(type); key_format.SerializeToString(key_template->mutable_value()); return key_template; } } // anonymous namespace // HARAKA const google::crypto::tink::KeyTemplate& Sphincs_Haraka_128_F_Robust_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSHARAKA128FROBUST_CRYPTO_SECRETKEYBYTES, SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Haraka_128_F_Simple_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSHARAKA128FSIMPLE_CRYPTO_SECRETKEYBYTES, SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Haraka_128_S_Robust_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSHARAKA128SROBUST_CRYPTO_SECRETKEYBYTES, SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Haraka_128_S_Simple_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSHARAKA128SSIMPLE_CRYPTO_SECRETKEYBYTES, SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Haraka_192_F_Robust_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSHARAKA192FROBUST_CRYPTO_SECRETKEYBYTES, SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Haraka_192_F_Simple_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSHARAKA192FSIMPLE_CRYPTO_SECRETKEYBYTES, SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Haraka_192_S_Robust_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSHARAKA192SROBUST_CRYPTO_SECRETKEYBYTES, SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Haraka_192_S_Simple_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSHARAKA192SSIMPLE_CRYPTO_SECRETKEYBYTES, SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Haraka_256_F_Robust_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSHARAKA256FROBUST_CRYPTO_SECRETKEYBYTES, SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Haraka_256_F_Simple_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSHARAKA256FSIMPLE_CRYPTO_SECRETKEYBYTES, SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Haraka_256_S_Robust_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSHARAKA256SROBUST_CRYPTO_SECRETKEYBYTES, SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Haraka_256_S_Simple_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSHARAKA256SSIMPLE_CRYPTO_SECRETKEYBYTES, SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE); return *key_template; } // SHA256 const google::crypto::tink::KeyTemplate& Sphincs_Sha256_128_F_Robust_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHA256128FROBUST_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Sha256_128_F_Simple_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHA256128FSIMPLE_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Sha256_128_S_Robust_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHA256128SROBUST_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Sha256_128_S_Simple_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHA256128SSIMPLE_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Sha256_192_F_Robust_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHA256192FROBUST_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Sha256_192_F_Simple_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHA256192FSIMPLE_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Sha256_192_S_Robust_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHA256192SROBUST_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Sha256_192_S_Simple_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHA256192SSIMPLE_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Sha256_256_F_Robust_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHA256256FROBUST_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Sha256_256_F_Simple_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHA256256FSIMPLE_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Sha256_256_S_Robust_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHA256256SROBUST_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Sha256_256_S_Simple_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHA256256SSIMPLE_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE); return *key_template; } // SHAKE256 const google::crypto::tink::KeyTemplate& Sphincs_Shake256_128_F_Robust_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHAKE256128FROBUST_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Shake256_128_F_Simple_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Shake256_128_S_Robust_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHAKE256128SROBUST_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Shake256_128_S_Simple_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Shake256_192_F_Robust_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHAKE256192FROBUST_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Shake256_192_F_Simple_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Shake256_192_S_Robust_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHAKE256192SROBUST_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Shake256_192_S_Simple_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Shake256_256_F_Robust_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHAKE256256FROBUST_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Shake256_256_F_Simple_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Shake256_256_S_Robust_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHAKE256256SROBUST_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE); return *key_template; } const google::crypto::tink::KeyTemplate& Sphincs_Shake256_256_S_Simple_KeyTemplate() { static const KeyTemplate* key_template = NewSphincsKeyTemplate( PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CRYPTO_SECRETKEYBYTES, SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE); return *key_template; } } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/sphincs_key_template.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SPHINCS_KEY_TEMPLATE_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SPHINCS_KEY_TEMPLATE_H_ #include "proto/tink.pb.h" namespace crypto { namespace tink { // Pre-generated KeyTemplates for Sphincs key type. // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: HARAKA // - VARIANT: ROBUST // - SIGNING TYPE: FAST SIGNING // - PRIVATE KEY SIZE: 64 const google::crypto::tink::KeyTemplate& Sphincs_Haraka_128_F_Robust_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: HARAKA // - VARIANT: SIMPLE // - SIGNING TYPE: FAST SIGNING // - PRIVATE KEY SIZE: 64 const google::crypto::tink::KeyTemplate& Sphincs_Haraka_128_F_Simple_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: HARAKA // - VARIANT: ROBUST // - SIGNING TYPE: SMALL SIGNATURE // - PRIVATE KEY SIZE: 64 const google::crypto::tink::KeyTemplate& Sphincs_Haraka_128_S_Robust_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: HARAKA // - VARIANT: SIMPLE // - SIGNING TYPE: SMALL SIGNATURE // - PRIVATE KEY SIZE: 64 const google::crypto::tink::KeyTemplate& Sphincs_Haraka_128_S_Simple_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: HARAKA // - VARIANT: ROBUST // - SIGNING TYPE: FAST SIGNING // - PRIVATE KEY SIZE: 96 const google::crypto::tink::KeyTemplate& Sphincs_Haraka_192_F_Robust_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: HARAKA // - VARIANT: SIMPLE // - SIGNING TYPE: FAST SIGNING // - PRIVATE KEY SIZE: 96 const google::crypto::tink::KeyTemplate& Sphincs_Haraka_192_F_Simple_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: HARAKA // - VARIANT: ROBUST // - SIGNING TYPE: SMALL SIGNATURE // - PRIVATE KEY SIZE: 96 const google::crypto::tink::KeyTemplate& Sphincs_Haraka_192_S_Robust_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: HARAKA // - VARIANT: SIMPLE // - SIGNING TYPE: SMALL SIGNATURE // - PRIVATE KEY SIZE: 96 const google::crypto::tink::KeyTemplate& Sphincs_Haraka_192_S_Simple_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: HARAKA // - VARIANT: ROBUST // - SIGNING TYPE: FAST SIGNING // - PRIVATE KEY SIZE: 128 const google::crypto::tink::KeyTemplate& Sphincs_Haraka_256_F_Robust_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: HARAKA // - VARIANT: SIMPLE // - SIGNING TYPE: FAST SIGNING // - PRIVATE KEY SIZE: 128 const google::crypto::tink::KeyTemplate& Sphincs_Haraka_256_F_Simple_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: HARAKA // - VARIANT: ROBUST // - SIGNING TYPE: SMALL SIGNATURE // - PRIVATE KEY SIZE: 128 const google::crypto::tink::KeyTemplate& Sphincs_Haraka_256_S_Robust_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: HARAKA // - VARIANT: SIMPLE // - SIGNING TYPE: SMALL SIGNATURE // - PRIVATE KEY SIZE: 128 const google::crypto::tink::KeyTemplate& Sphincs_Haraka_256_S_Simple_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHA256 // - VARIANT: ROBUST // - SIGNING TYPE: FAST SIGNING // - PRIVATE KEY SIZE: 64 const google::crypto::tink::KeyTemplate& Sphincs_Sha256_128_F_Robust_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHA256 // - VARIANT: SIMPLE // - SIGNING TYPE: FAST SIGNING // - PRIVATE KEY SIZE: 64 const google::crypto::tink::KeyTemplate& Sphincs_Sha256_128_F_Simple_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHA256 // - VARIANT: ROBUST // - SIGNING TYPE: SMALL SIGNATURE // - PRIVATE KEY SIZE: 64 const google::crypto::tink::KeyTemplate& Sphincs_Sha256_128_S_Robust_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHA256 // - VARIANT: SIMPLE // - SIGNING TYPE: SMALL SIGNATURE // - PRIVATE KEY SIZE: 64 const google::crypto::tink::KeyTemplate& Sphincs_Sha256_128_S_Simple_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHA256 // - VARIANT: ROBUST // - SIGNING TYPE: FAST SIGNING // - PRIVATE KEY SIZE: 96 const google::crypto::tink::KeyTemplate& Sphincs_Sha256_192_F_Robust_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHA256 // - VARIANT: SIMPLE // - SIGNING TYPE: FAST SIGNING // - PRIVATE KEY SIZE: 96 const google::crypto::tink::KeyTemplate& Sphincs_Sha256_192_F_Simple_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHA256 // - VARIANT: ROBUST // - SIGNING TYPE: SMALL SIGNATURE // - PRIVATE KEY SIZE: 96 const google::crypto::tink::KeyTemplate& Sphincs_Sha256_192_S_Robust_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHA256 // - VARIANT: SIMPLE // - SIGNING TYPE: SMALL SIGNATURE // - PRIVATE KEY SIZE: 96 const google::crypto::tink::KeyTemplate& Sphincs_Sha256_192_S_Simple_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHA256 // - VARIANT: ROBUST // - SIGNING TYPE: FAST SIGNING // - PRIVATE KEY SIZE: 128 const google::crypto::tink::KeyTemplate& Sphincs_Sha256_256_F_Robust_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHA256 // - VARIANT: SIMPLE // - SIGNING TYPE: FAST SIGNING // - PRIVATE KEY SIZE: 128 const google::crypto::tink::KeyTemplate& Sphincs_Sha256_256_F_Simple_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHA256 // - VARIANT: ROBUST // - SIGNING TYPE: SMALL SIGNATURE // - PRIVATE KEY SIZE: 128 const google::crypto::tink::KeyTemplate& Sphincs_Sha256_256_S_Robust_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHA256 // - VARIANT: SIMPLE // - SIGNING TYPE: SMALL SIGNATURE // - PRIVATE KEY SIZE: 128 const google::crypto::tink::KeyTemplate& Sphincs_Sha256_256_S_Simple_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHAKE256 // - VARIANT: ROBUST // - SIGNING TYPE: FAST SIGNING // - PRIVATE KEY SIZE: 64 const google::crypto::tink::KeyTemplate& Sphincs_Shake256_128_F_Robust_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHAKE256 // - VARIANT: SIMPLE // - SIGNING TYPE: FAST SIGNING // - PRIVATE KEY SIZE: 64 const google::crypto::tink::KeyTemplate& Sphincs_Shake256_128_F_Simple_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHAKE256 // - VARIANT: ROBUST // - SIGNING TYPE: SMALL SIGNATURE // - PRIVATE KEY SIZE: 64 const google::crypto::tink::KeyTemplate& Sphincs_Shake256_128_S_Robust_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHAKE256 // - VARIANT: SIMPLE // - SIGNING TYPE: SMALL SIGNATURE // - PRIVATE KEY SIZE: 64 const google::crypto::tink::KeyTemplate& Sphincs_Shake256_128_S_Simple_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHAKE256 // - VARIANT: ROBUST // - SIGNING TYPE: FAST SIGNING // - PRIVATE KEY SIZE: 96 const google::crypto::tink::KeyTemplate& Sphincs_Shake256_192_F_Robust_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHAKE256 // - VARIANT: SIMPLE // - SIGNING TYPE: FAST SIGNING // - PRIVATE KEY SIZE: 96 const google::crypto::tink::KeyTemplate& Sphincs_Shake256_192_F_Simple_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHAKE256 // - VARIANT: ROBUST // - SIGNING TYPE: SMALL SIGNATURE // - PRIVATE KEY SIZE: 96 const google::crypto::tink::KeyTemplate& Sphincs_Shake256_192_S_Robust_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHAKE256 // - VARIANT: SIMPLE // - SIGNING TYPE: SMALL SIGNATURE // - PRIVATE KEY SIZE: 96 const google::crypto::tink::KeyTemplate& Sphincs_Shake256_192_S_Simple_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHAKE256 // - VARIANT: ROBUST // - SIGNING TYPE: FAST SIGNING // - PRIVATE KEY SIZE: 128 const google::crypto::tink::KeyTemplate& Sphincs_Shake256_256_F_Robust_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHAKE256 // - VARIANT: SIMPLE // - SIGNING TYPE: FAST SIGNING // - PRIVATE KEY SIZE: 128 const google::crypto::tink::KeyTemplate& Sphincs_Shake256_256_F_Simple_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHAKE256 // - VARIANT: ROBUST // - SIGNING TYPE: SMALL SIGNATURE // - PRIVATE KEY SIZE: 128 const google::crypto::tink::KeyTemplate& Sphincs_Shake256_256_S_Robust_KeyTemplate(); // Returns a KeyTemplate that generates new instances of // SphincsPrivateKey with the following parameters: // - HASH: SHAKE256 // - VARIANT: SIMPLE // - SIGNING TYPE: SMALL SIGNATURE // - PRIVATE KEY SIZE: 128 const google::crypto::tink::KeyTemplate& Sphincs_Shake256_256_S_Simple_KeyTemplate(); } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SPHINCS_KEY_TEMPLATE_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/sphincs_key_template_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/sphincs_key_template.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/core/key_manager_impl.h" #include "tink/core/private_key_manager_impl.h" #include "tink/experimental/pqcrypto/signature/sphincs_sign_key_manager.h" #include "tink/experimental/pqcrypto/signature/sphincs_verify_key_manager.h" #include "tink/key_manager.h" #include "tink/public_key_sign.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/experimental/pqcrypto/sphincs.pb.h" #include "proto/tink.pb.h" extern "C" { #include "third_party/pqclean/crypto_sign/sphincs-haraka-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256s-simple/api.h" } namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using google::crypto::tink::KeyTemplate; using google::crypto::tink::OutputPrefixType; using ::google::crypto::tink::SphincsHashType; using ::google::crypto::tink::SphincsKeyFormat; using ::google::crypto::tink::SphincsParams; using ::google::crypto::tink::SphincsPrivateKey; using ::google::crypto::tink::SphincsSignatureType; using ::google::crypto::tink::SphincsVariant; struct SphincsTestCase { std::string test_name; SphincsHashType hash_type; SphincsVariant variant; SphincsSignatureType sig_length_type; int32_t private_key_size; KeyTemplate key_template; }; using SphincsKeyTemplateTest = testing::TestWithParam; TEST_P(SphincsKeyTemplateTest, CheckKeyTemplateValid) { std::string type_url = "type.googleapis.com/google.crypto.tink.SphincsPrivateKey"; const SphincsTestCase& test_case = GetParam(); EXPECT_EQ(type_url, test_case.key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, test_case.key_template.output_prefix_type()); SphincsKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(test_case.key_template.value())); EXPECT_EQ(test_case.hash_type, key_format.params().hash_type()); EXPECT_EQ(test_case.variant, key_format.params().variant()); EXPECT_EQ(test_case.sig_length_type, key_format.params().sig_length_type()); EXPECT_EQ(test_case.private_key_size, key_format.params().key_size()); } TEST_P(SphincsKeyTemplateTest, SameReference) { const KeyTemplate& key_template = GetParam().key_template; const KeyTemplate& key_template_2 = GetParam().key_template; EXPECT_EQ(&key_template, &key_template_2); } TEST_P(SphincsKeyTemplateTest, KeyManagerCompatibility) { SphincsSignKeyManager sign_key_manager; SphincsVerifyKeyManager verify_key_manager; std::unique_ptr> key_manager = internal::MakePrivateKeyManager(&sign_key_manager, &verify_key_manager); SphincsKeyFormat key_format; const SphincsTestCase& test_case = GetParam(); SphincsParams* params = key_format.mutable_params(); params->set_key_size(test_case.private_key_size); params->set_hash_type(test_case.hash_type); params->set_variant(test_case.variant); params->set_sig_length_type(test_case.sig_length_type); util::StatusOr> new_key_result = key_manager->get_key_factory().NewKey(key_format); EXPECT_THAT(new_key_result, IsOk()); } INSTANTIATE_TEST_SUITE_P( SphincsKeyTemplateTests, SphincsKeyTemplateTest, testing::ValuesIn( {{"SPHINCSHARAKA128FROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA128FROBUST_CRYPTO_SECRETKEYBYTES, Sphincs_Haraka_128_F_Robust_KeyTemplate()}, {"SPHINCSHARAKA128SROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA128SROBUST_CRYPTO_SECRETKEYBYTES, Sphincs_Haraka_128_S_Robust_KeyTemplate()}, {"SPHINCSHARAKA128FSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CRYPTO_SECRETKEYBYTES, Sphincs_Haraka_128_F_Simple_KeyTemplate()}, {"SPHINCSHARAKA128SSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CRYPTO_SECRETKEYBYTES, Sphincs_Haraka_128_S_Simple_KeyTemplate()}, {"SPHINCSHARAKA192FROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA192FROBUST_CRYPTO_SECRETKEYBYTES, Sphincs_Haraka_192_F_Robust_KeyTemplate()}, {"SPHINCSHARAKA192SROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA192SROBUST_CRYPTO_SECRETKEYBYTES, Sphincs_Haraka_192_S_Robust_KeyTemplate()}, {"SPHINCSHARAKA192FSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CRYPTO_SECRETKEYBYTES, Sphincs_Haraka_192_F_Simple_KeyTemplate()}, {"SPHINCSHARAKA192SSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CRYPTO_SECRETKEYBYTES, Sphincs_Haraka_192_S_Simple_KeyTemplate()}, {"SPHINCSHARAKA256FROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA256FROBUST_CRYPTO_SECRETKEYBYTES, Sphincs_Haraka_256_F_Robust_KeyTemplate()}, {"SPHINCSHARAKA256SROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA256SROBUST_CRYPTO_SECRETKEYBYTES, Sphincs_Haraka_256_S_Robust_KeyTemplate()}, {"SPHINCSHARAKA256FSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CRYPTO_SECRETKEYBYTES, Sphincs_Haraka_256_F_Simple_KeyTemplate()}, {"SPHINCSHARAKA256SSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CRYPTO_SECRETKEYBYTES, Sphincs_Haraka_256_S_Simple_KeyTemplate()}, {"SPHINCSSHA256128FROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256128FROBUST_CRYPTO_SECRETKEYBYTES, Sphincs_Sha256_128_F_Robust_KeyTemplate()}, {"SPHINCSSHA256128SROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256128SROBUST_CRYPTO_SECRETKEYBYTES, Sphincs_Sha256_128_S_Robust_KeyTemplate()}, {"SPHINCSSHA256128FSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256128FSIMPLE_CRYPTO_SECRETKEYBYTES, Sphincs_Sha256_128_F_Simple_KeyTemplate()}, {"SPHINCSSHA256128SSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256128SSIMPLE_CRYPTO_SECRETKEYBYTES, Sphincs_Sha256_128_S_Simple_KeyTemplate()}, {"SPHINCSSHA256192FROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256192FROBUST_CRYPTO_SECRETKEYBYTES, Sphincs_Sha256_192_F_Robust_KeyTemplate()}, {"SPHINCSSHA256192SROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256192SROBUST_CRYPTO_SECRETKEYBYTES, Sphincs_Sha256_192_S_Robust_KeyTemplate()}, {"SPHINCSSHA256192FSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256192FSIMPLE_CRYPTO_SECRETKEYBYTES, Sphincs_Sha256_192_F_Simple_KeyTemplate()}, {"SPHINCSSHA256192SSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256192SSIMPLE_CRYPTO_SECRETKEYBYTES, Sphincs_Sha256_192_S_Simple_KeyTemplate()}, {"SPHINCSSHA256256FROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256256FROBUST_CRYPTO_SECRETKEYBYTES, Sphincs_Sha256_256_F_Robust_KeyTemplate()}, {"SPHINCSSHA256256SROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256256SROBUST_CRYPTO_SECRETKEYBYTES, Sphincs_Sha256_256_S_Robust_KeyTemplate()}, {"SPHINCSSHA256256FSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256256FSIMPLE_CRYPTO_SECRETKEYBYTES, Sphincs_Sha256_256_F_Simple_KeyTemplate()}, {"SPHINCSSHA256256SSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256256SSIMPLE_CRYPTO_SECRETKEYBYTES, Sphincs_Sha256_256_S_Simple_KeyTemplate()}, {"SPHINCSSHAKE256128FROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256128FROBUST_CRYPTO_SECRETKEYBYTES, Sphincs_Shake256_128_F_Robust_KeyTemplate()}, {"SPHINCSSHAKE256128SROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256128SROBUST_CRYPTO_SECRETKEYBYTES, Sphincs_Shake256_128_S_Robust_KeyTemplate()}, {"SPHINCSSHAKE256128FSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CRYPTO_SECRETKEYBYTES, Sphincs_Shake256_128_F_Simple_KeyTemplate()}, {"SPHINCSSHAKE256128SSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CRYPTO_SECRETKEYBYTES, Sphincs_Shake256_128_S_Simple_KeyTemplate()}, {"SPHINCSSHAKE256192FROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256192FROBUST_CRYPTO_SECRETKEYBYTES, Sphincs_Shake256_192_F_Robust_KeyTemplate()}, {"SPHINCSSHAKE256192SROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256192SROBUST_CRYPTO_SECRETKEYBYTES, Sphincs_Shake256_192_S_Robust_KeyTemplate()}, {"SPHINCSSHAKE256192FSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CRYPTO_SECRETKEYBYTES, Sphincs_Shake256_192_F_Simple_KeyTemplate()}, {"SPHINCSSHAKE256192SSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CRYPTO_SECRETKEYBYTES, Sphincs_Shake256_192_S_Simple_KeyTemplate()}, {"SPHINCSSHAKE256256FROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256256FROBUST_CRYPTO_SECRETKEYBYTES, Sphincs_Shake256_256_F_Robust_KeyTemplate()}, {"SPHINCSSHAKE256256SROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256256SROBUST_CRYPTO_SECRETKEYBYTES, Sphincs_Shake256_256_S_Robust_KeyTemplate()}, {"SPHINCSSHAKE256256FSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CRYPTO_SECRETKEYBYTES, Sphincs_Shake256_256_F_Simple_KeyTemplate()}, {"SPHINCSSHAKE256256SSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CRYPTO_SECRETKEYBYTES, Sphincs_Shake256_256_S_Simple_KeyTemplate()}}), [](const testing::TestParamInfo& info) { return info.param.test_name; }); } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/sphincs_sign_key_manager.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/sphincs_sign_key_manager.h" #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/experimental/pqcrypto/signature/sphincs_verify_key_manager.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_sign.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h" #include "tink/experimental/pqcrypto/signature/util/enums.h" #include "tink/public_key_sign.h" #include "tink/util/errors.h" #include "tink/util/input_stream_util.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" namespace crypto { namespace tink { using ::crypto::tink::subtle::SphincsKeyPair; using ::crypto::tink::subtle::SphincsParamsPqclean; using ::crypto::tink::subtle::SphincsPrivateKeyPqclean; using ::crypto::tink::util::EnumsPqcrypto; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::SphincsKeyFormat; using ::google::crypto::tink::SphincsPrivateKey; using ::google::crypto::tink::SphincsPublicKey; StatusOr SphincsSignKeyManager::CreateKey( const SphincsKeyFormat& key_format) const { SphincsParamsPqclean sphincs_params_pqclean = { .hash_type = EnumsPqcrypto::ProtoToSubtle(key_format.params().hash_type()), .variant = EnumsPqcrypto::ProtoToSubtle(key_format.params().variant()), .sig_length_type = EnumsPqcrypto::ProtoToSubtle(key_format.params().sig_length_type()), .private_key_size = key_format.params().key_size()}; util::StatusOr key_pair = GenerateSphincsKeyPair(sphincs_params_pqclean); if (!key_pair.status().ok()) { return key_pair.status(); } SphincsPrivateKey sphincs_private_key; sphincs_private_key.set_version(get_version()); sphincs_private_key.set_key_value( util::SecretDataAsStringView(key_pair->GetPrivateKey().GetKey())); SphincsPublicKey* sphincs_public_key = sphincs_private_key.mutable_public_key(); sphincs_public_key->set_version(get_version()); sphincs_public_key->set_key_value(key_pair->GetPublicKey().GetKey()); *(sphincs_public_key->mutable_params()) = key_format.params(); return sphincs_private_key; } StatusOr> SphincsSignKeyManager::PublicKeySignFactory::Create( const SphincsPrivateKey& private_key) const { util::SecretData sk_data = util::SecretDataFromStringView(private_key.key_value()); SphincsParamsPqclean sphincs_params_pqclean = { .hash_type = EnumsPqcrypto::ProtoToSubtle( private_key.public_key().params().hash_type()), .variant = EnumsPqcrypto::ProtoToSubtle( private_key.public_key().params().variant()), .sig_length_type = EnumsPqcrypto::ProtoToSubtle( private_key.public_key().params().sig_length_type()), .private_key_size = private_key.public_key().params().key_size()}; SphincsPrivateKeyPqclean sphincs_private_key_pqclean(sk_data, sphincs_params_pqclean); return subtle::SphincsSign::New(sphincs_private_key_pqclean); } Status SphincsSignKeyManager::ValidateKey(const SphincsPrivateKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) { return status; } status = subtle::ValidatePrivateKeySize(key.key_value().length()); if (!status.ok()) { return status; } return SphincsVerifyKeyManager().ValidateKey(key.public_key()); } Status SphincsSignKeyManager::ValidateKeyFormat( const SphincsKeyFormat& key_format) const { if (!key_format.has_params()) { return Status(absl::StatusCode::kInvalidArgument, "Missing params."); } return SphincsVerifyKeyManager().ValidateParams(key_format.params()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/sphincs_sign_key_manager.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SPHINCS_SIGN_KEY_MANAGER_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SPHINCS_SIGN_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/public_key_sign.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/input_stream_util.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/experimental/pqcrypto/sphincs.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class SphincsSignKeyManager : public PrivateKeyTypeManager> { public: class PublicKeySignFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::SphincsPrivateKey& private_key) const override; }; SphincsSignKeyManager() : PrivateKeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::SphincsPrivateKey& key) const override; crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::SphincsKeyFormat& key_format) const override; crypto::tink::util::StatusOr CreateKey(const google::crypto::tink::SphincsKeyFormat& key_format) const override; crypto::tink::util::StatusOr GetPublicKey(const google::crypto::tink::SphincsPrivateKey& private_key) const override { return private_key.public_key(); } private: const std::string key_type_ = absl::StrCat(kTypeGoogleapisCom, google::crypto::tink::SphincsPrivateKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SPHINCS_SIGN_KEY_MANAGER_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/sphincs_sign_key_manager_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/sphincs_sign_key_manager.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_set.h" #include "absl/strings/str_cat.h" #include "tink/experimental/pqcrypto/signature/sphincs_verify_key_manager.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_sign.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_verify.h" #include "tink/experimental/pqcrypto/signature/util/enums.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/experimental/pqcrypto/sphincs.pb.h" #include "proto/tink.pb.h" extern "C" { #include "third_party/pqclean/crypto_sign/sphincs-haraka-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256s-simple/api.h" } namespace crypto { namespace tink { namespace { using ::crypto::tink::subtle::SphincsPublicKeyPqclean; using ::crypto::tink::test::IsOk; using ::crypto::tink::util::EnumsPqcrypto; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::SphincsHashType; using ::google::crypto::tink::SphincsKeyFormat; using ::google::crypto::tink::SphincsParams; using ::google::crypto::tink::SphincsPrivateKey; using ::google::crypto::tink::SphincsPublicKey; using ::google::crypto::tink::SphincsSignatureType; using ::google::crypto::tink::SphincsVariant; using ::testing::Eq; using ::testing::Not; using ::testing::SizeIs; struct SphincsTestCase { std::string test_name; SphincsHashType hash_type; SphincsVariant variant; SphincsSignatureType sig_length_type; int32_t private_key_size; int32_t public_key_size; }; using SphincsSignKeyManagerTest = testing::TestWithParam; // Helper function that returns a valid sphincs key format. StatusOr CreateValidKeyFormat(int32_t private_key_size, SphincsHashType hash_type, SphincsVariant variant, SphincsSignatureType type) { SphincsKeyFormat key_format; SphincsParams* params = key_format.mutable_params(); params->set_key_size(private_key_size); params->set_hash_type(hash_type); params->set_variant(variant); params->set_sig_length_type(type); return key_format; } TEST(SphincsSignKeyManagerTest, Basic) { EXPECT_THAT(SphincsSignKeyManager().get_version(), Eq(0)); EXPECT_THAT(SphincsSignKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PRIVATE)); EXPECT_THAT(SphincsSignKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.SphincsPrivateKey")); } TEST_P(SphincsSignKeyManagerTest, ValidKeyFormat) { const SphincsTestCase& test_case = GetParam(); StatusOr key_format = CreateValidKeyFormat(test_case.private_key_size, test_case.hash_type, test_case.variant, test_case.sig_length_type); ASSERT_THAT(key_format, IsOk()); EXPECT_THAT(SphincsSignKeyManager().ValidateKeyFormat(*key_format), IsOk()); } TEST(SphincsSignKeyManagerTest, InvalidKeyFormat) { StatusOr key_format = CreateValidKeyFormat( subtle::kSphincsPrivateKeySize64, SphincsHashType::HASH_TYPE_UNSPECIFIED, SphincsVariant::VARIANT_UNSPECIFIED, SphincsSignatureType::SIG_TYPE_UNSPECIFIED); ASSERT_THAT(key_format, IsOk()); EXPECT_THAT(SphincsSignKeyManager().ValidateKeyFormat(*key_format), Not(IsOk())); } TEST_P(SphincsSignKeyManagerTest, CreateKeyValid) { const SphincsTestCase& test_case = GetParam(); StatusOr key_format = CreateValidKeyFormat(test_case.private_key_size, test_case.hash_type, test_case.variant, test_case.sig_length_type); ASSERT_THAT(key_format, IsOk()); StatusOr private_key = SphincsSignKeyManager().CreateKey(*key_format); ASSERT_THAT(private_key, IsOk()); EXPECT_THAT(SphincsSignKeyManager().ValidateKey(*private_key), IsOk()); EXPECT_THAT(private_key->version(), Eq(0)); EXPECT_THAT(private_key->public_key().version(), Eq(private_key->version())); EXPECT_THAT(private_key->key_value(), SizeIs(test_case.private_key_size)); } TEST_P(SphincsSignKeyManagerTest, PrivateKeyWrongVersion) { const SphincsTestCase& test_case = GetParam(); StatusOr key_format = CreateValidKeyFormat(test_case.private_key_size, test_case.hash_type, test_case.variant, test_case.sig_length_type); ASSERT_THAT(key_format, IsOk()); StatusOr private_key = SphincsSignKeyManager().CreateKey(*key_format); ASSERT_THAT(private_key, IsOk()); private_key->set_version(1); EXPECT_THAT(SphincsSignKeyManager().ValidateKey(*private_key), Not(IsOk())); } TEST(SphincsSignKeyManagerTest, CreateKeyInvalidParams) { StatusOr key_format = CreateValidKeyFormat( subtle::kSphincsPrivateKeySize64, SphincsHashType::HASH_TYPE_UNSPECIFIED, SphincsVariant::VARIANT_UNSPECIFIED, SphincsSignatureType::SIG_TYPE_UNSPECIFIED); ASSERT_THAT(key_format, IsOk()); StatusOr private_key = SphincsSignKeyManager().CreateKey(*key_format); EXPECT_THAT(private_key, Not(IsOk())); } TEST_P(SphincsSignKeyManagerTest, CreateKeyAlwaysNew) { const SphincsTestCase& test_case = GetParam(); StatusOr key_format = CreateValidKeyFormat(test_case.private_key_size, test_case.hash_type, test_case.variant, test_case.sig_length_type); ASSERT_THAT(key_format, IsOk()); absl::flat_hash_set keys; int num_tests = 5; for (int i = 0; i < num_tests; ++i) { StatusOr private_key = SphincsSignKeyManager().CreateKey(*key_format); ASSERT_THAT(private_key, IsOk()); keys.insert(private_key->key_value()); } EXPECT_THAT(keys, SizeIs(num_tests)); } TEST_P(SphincsSignKeyManagerTest, GetPublicKey) { const SphincsTestCase& test_case = GetParam(); StatusOr key_format = CreateValidKeyFormat(test_case.private_key_size, test_case.hash_type, test_case.variant, test_case.sig_length_type); ASSERT_THAT(key_format, IsOk()); StatusOr private_key = SphincsSignKeyManager().CreateKey(*key_format); ASSERT_THAT(private_key, IsOk()); StatusOr public_key_or = SphincsSignKeyManager().GetPublicKey(*private_key); ASSERT_THAT(public_key_or, IsOk()); EXPECT_THAT(public_key_or->version(), Eq(private_key->public_key().version())); EXPECT_THAT(public_key_or->key_value(), Eq(private_key->public_key().key_value())); } TEST_P(SphincsSignKeyManagerTest, CreateValid) { const SphincsTestCase& test_case = GetParam(); StatusOr key_format = CreateValidKeyFormat(test_case.private_key_size, test_case.hash_type, test_case.variant, test_case.sig_length_type); ASSERT_THAT(key_format, IsOk()); util::StatusOr private_key = SphincsSignKeyManager().CreateKey(*key_format); ASSERT_THAT(private_key, IsOk()); util::StatusOr> signer = SphincsSignKeyManager().GetPrimitive(*private_key); ASSERT_THAT(signer, IsOk()); subtle::SphincsParamsPqclean sphincs_params_pqclean = { .hash_type = EnumsPqcrypto::ProtoToSubtle(test_case.hash_type), .variant = EnumsPqcrypto::ProtoToSubtle(test_case.variant), .sig_length_type = EnumsPqcrypto::ProtoToSubtle(test_case.sig_length_type), .private_key_size = test_case.private_key_size}; SphincsPublicKeyPqclean sphincs_public_key_pqclean( private_key->public_key().key_value(), sphincs_params_pqclean); util::StatusOr> verifier = subtle::SphincsVerify::New(sphincs_public_key_pqclean); ASSERT_THAT(verifier, IsOk()); std::string message = "Some message"; util::StatusOr signature = (*signer)->Sign(message); ASSERT_THAT(signature, IsOk()); EXPECT_THAT((*verifier)->Verify(*signature, message), IsOk()); } TEST_P(SphincsSignKeyManagerTest, CreateBadPublicKey) { const SphincsTestCase& test_case = GetParam(); StatusOr key_format = CreateValidKeyFormat(test_case.private_key_size, test_case.hash_type, test_case.variant, test_case.sig_length_type); ASSERT_THAT(key_format, IsOk()); util::StatusOr private_key = SphincsSignKeyManager().CreateKey(*key_format); ASSERT_THAT(private_key, IsOk()); util::StatusOr> signer = SphincsSignKeyManager().GetPrimitive(*private_key); ASSERT_THAT(signer, IsOk()); std::string bad_public_key_data(test_case.public_key_size, '@'); subtle::SphincsParamsPqclean sphincs_params_pqclean = { .hash_type = EnumsPqcrypto::ProtoToSubtle(test_case.hash_type), .variant = EnumsPqcrypto::ProtoToSubtle(test_case.variant), .sig_length_type = EnumsPqcrypto::ProtoToSubtle(test_case.sig_length_type), .private_key_size = test_case.private_key_size}; SphincsPublicKeyPqclean sphincs_public_key_pqclean(bad_public_key_data, sphincs_params_pqclean); util::StatusOr> direct_verifier = subtle::SphincsVerify::New(sphincs_public_key_pqclean); ASSERT_THAT(direct_verifier, IsOk()); std::string message = "Some message"; util::StatusOr signature = (*signer)->Sign(message); ASSERT_THAT(signature, IsOk()); EXPECT_THAT((*direct_verifier)->Verify(*signature, message), Not(IsOk())); } INSTANTIATE_TEST_SUITE_P( SphincsSignKeyManagerTests, SphincsSignKeyManagerTest, testing::ValuesIn( {{"SPHINCSHARAKA128FROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA128FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA128FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA128SROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA128SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA128SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA128FSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA128SSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA192FROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA192FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA192FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA192SROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA192SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA192SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA192FSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA192SSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA256FROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA256FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA256FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA256SROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA256SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA256SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA256FSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA256SSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256128FROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256128FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256128FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256128SROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256128SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256128SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256128FSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256128FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256128FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256128SSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256128SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256128SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256192FROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256192FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256192FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256192SROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256192SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256192SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256192FSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256192FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256192FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256192SSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256192SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256192SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256256FROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256256FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256256FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256256SROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256256SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256256SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256256FSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256256FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256256FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256256SSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256256SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256256SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256128FROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256128FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256128FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256128SROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256128SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256128SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256128FSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256128SSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256192FROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256192FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256192FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256192SROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256192SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256192SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256192FSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256192SSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256256FROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256256FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256256FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256256SROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256256SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256256SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256256FSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256256SSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CRYPTO_PUBLICKEYBYTES}}), [](const testing::TestParamInfo& info) { return info.param.test_name; }); } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/sphincs_verify_key_manager.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/sphincs_verify_key_manager.h" #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_verify.h" #include "tink/experimental/pqcrypto/signature/util/enums.h" #include "tink/public_key_verify.h" #include "tink/util/errors.h" #include "tink/util/input_stream_util.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" namespace crypto { namespace tink { using ::crypto::tink::subtle::SphincsParamsPqclean; using ::crypto::tink::subtle::SphincsPublicKeyPqclean; using ::crypto::tink::util::EnumsPqcrypto; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::SphincsParams; using ::google::crypto::tink::SphincsPublicKey; StatusOr> SphincsVerifyKeyManager::PublicKeyVerifyFactory::Create( const SphincsPublicKey& public_key) const { SphincsParamsPqclean sphincs_params_pqclean = { .hash_type = EnumsPqcrypto::ProtoToSubtle(public_key.params().hash_type()), .variant = EnumsPqcrypto::ProtoToSubtle(public_key.params().variant()), .sig_length_type = EnumsPqcrypto::ProtoToSubtle(public_key.params().sig_length_type()), .private_key_size = public_key.params().key_size()}; SphincsPublicKeyPqclean sphincs_public_key_pqclean(public_key.key_value(), sphincs_params_pqclean); return subtle::SphincsVerify::New(sphincs_public_key_pqclean); } Status SphincsVerifyKeyManager::ValidateKey(const SphincsPublicKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) { return status; } status = subtle::ValidatePublicKeySize(key.key_value().length()); if (!status.ok()) { return status; } return util::OkStatus(); } Status SphincsVerifyKeyManager::ValidateParams( const SphincsParams& params) const { SphincsParamsPqclean sphincs_params_pqclean = { .hash_type = EnumsPqcrypto::ProtoToSubtle(params.hash_type()), .variant = EnumsPqcrypto::ProtoToSubtle(params.variant()), .sig_length_type = EnumsPqcrypto::ProtoToSubtle(params.sig_length_type()), .private_key_size = params.key_size()}; Status status = subtle::ValidateParams(sphincs_params_pqclean); if (!status.ok()) { return status; } return util::OkStatus(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/sphincs_verify_key_manager.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SPHINCS_VERIFY_KEY_MANAGER_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SPHINCS_VERIFY_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/key_type_manager.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/public_key_verify.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/input_stream_util.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/experimental/pqcrypto/sphincs.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class SphincsVerifyKeyManager : public KeyTypeManager> { public: class PublicKeyVerifyFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::SphincsPublicKey& public_key) const override; }; SphincsVerifyKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PUBLIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::SphincsPublicKey& key) const override; crypto::tink::util::Status ValidateParams( const google::crypto::tink::SphincsParams& params) const; private: const std::string key_type_ = absl::StrCat(kTypeGoogleapisCom, google::crypto::tink::SphincsPublicKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SPHINCS_VERIFY_KEY_MANAGER_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/sphincs_verify_key_manager_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/sphincs_verify_key_manager.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_set.h" #include "absl/strings/str_cat.h" #include "tink/experimental/pqcrypto/signature/sphincs_sign_key_manager.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_sign.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_verify.h" #include "tink/experimental/pqcrypto/signature/util/enums.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/experimental/pqcrypto/sphincs.pb.h" #include "proto/tink.pb.h" extern "C" { #include "third_party/pqclean/crypto_sign/sphincs-haraka-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256s-simple/api.h" } namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::util::EnumsPqcrypto; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::SphincsHashType; using ::google::crypto::tink::SphincsKeyFormat; using ::google::crypto::tink::SphincsParams; using ::google::crypto::tink::SphincsPrivateKey; using ::google::crypto::tink::SphincsPublicKey; using ::google::crypto::tink::SphincsSignatureType; using ::google::crypto::tink::SphincsVariant; using ::testing::Eq; using ::testing::Not; struct SphincsTestCase { std::string test_name; SphincsHashType hash_type; SphincsVariant variant; SphincsSignatureType sig_length_type; int32_t private_key_size; int32_t public_key_size; }; using SphincsVerifyKeyManagerTest = testing::TestWithParam; // Helper function that returns a valid sphincs private key. StatusOr CreateValidPrivateKey(int32_t private_key_size, SphincsHashType hash_type, SphincsVariant variant, SphincsSignatureType type) { SphincsKeyFormat key_format; SphincsParams* params = key_format.mutable_params(); params->set_key_size(private_key_size); params->set_hash_type(hash_type); params->set_variant(variant); params->set_sig_length_type(type); return SphincsSignKeyManager().CreateKey(key_format); } // Helper function that returns a valid sphincs public key. StatusOr CreateValidPublicKey(int32_t private_key_size, SphincsHashType hash_type, SphincsVariant variant, SphincsSignatureType type) { StatusOr private_key = CreateValidPrivateKey(private_key_size, hash_type, variant, type); if (!private_key.ok()) return private_key.status(); return SphincsSignKeyManager().GetPublicKey(*private_key); } TEST(SphincsVerifyKeyManagerTest, Basics) { EXPECT_THAT(SphincsVerifyKeyManager().get_version(), Eq(0)); EXPECT_THAT(SphincsVerifyKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PUBLIC)); EXPECT_THAT(SphincsVerifyKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.SphincsPublicKey")); } TEST(SphincsVerifyKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(SphincsVerifyKeyManager().ValidateKey(SphincsPublicKey()), Not(IsOk())); } TEST_P(SphincsVerifyKeyManagerTest, InvalidParam) { const SphincsTestCase& test_case = GetParam(); SphincsKeyFormat key_format; SphincsParams* params = key_format.mutable_params(); params->set_key_size(test_case.private_key_size); params->set_hash_type(test_case.hash_type); params->set_variant(test_case.variant); params->set_sig_length_type(SphincsSignatureType::SIG_TYPE_UNSPECIFIED); EXPECT_THAT(SphincsVerifyKeyManager().ValidateParams(*params), Not(IsOk())); } TEST_P(SphincsVerifyKeyManagerTest, PublicKeyValid) { const SphincsTestCase& test_case = GetParam(); StatusOr public_key = CreateValidPublicKey(test_case.private_key_size, test_case.hash_type, test_case.variant, test_case.sig_length_type); ASSERT_THAT(public_key, IsOk()); EXPECT_THAT(SphincsVerifyKeyManager().ValidateKey(*public_key), IsOk()); } TEST(SphincsVerifyKeyManagerTest, PublicKeyInvalidParams) { StatusOr public_key = CreateValidPublicKey( subtle::kSphincsPrivateKeySize64, SphincsHashType::HASH_TYPE_UNSPECIFIED, SphincsVariant::VARIANT_UNSPECIFIED, SphincsSignatureType::SIG_TYPE_UNSPECIFIED); EXPECT_THAT(public_key, Not(IsOk())); } TEST_P(SphincsVerifyKeyManagerTest, PublicKeyWrongVersion) { const SphincsTestCase& test_case = GetParam(); StatusOr public_key = CreateValidPublicKey(test_case.private_key_size, test_case.hash_type, test_case.variant, test_case.sig_length_type); ASSERT_THAT(public_key, IsOk()); public_key->set_version(1); EXPECT_THAT(SphincsVerifyKeyManager().ValidateKey(*public_key), Not(IsOk())); } TEST_P(SphincsVerifyKeyManagerTest, Create) { const SphincsTestCase& test_case = GetParam(); StatusOr private_key = CreateValidPrivateKey(test_case.private_key_size, test_case.hash_type, test_case.variant, test_case.sig_length_type); ASSERT_THAT(private_key, IsOk()); StatusOr public_key = SphincsSignKeyManager().GetPublicKey(*private_key); ASSERT_THAT(public_key, IsOk()); subtle::SphincsParamsPqclean sphincs_params_pqclean = { .hash_type = EnumsPqcrypto::ProtoToSubtle(test_case.hash_type), .variant = EnumsPqcrypto::ProtoToSubtle(test_case.variant), .sig_length_type = EnumsPqcrypto::ProtoToSubtle(test_case.sig_length_type), .private_key_size = test_case.private_key_size}; subtle::SphincsPrivateKeyPqclean sphincs_private_key_pqclean( util::SecretDataFromStringView(private_key->key_value()), sphincs_params_pqclean); util::StatusOr> direct_signer = subtle::SphincsSign::New(sphincs_private_key_pqclean); ASSERT_THAT(direct_signer, IsOk()); util::StatusOr> verifier = SphincsVerifyKeyManager().GetPrimitive(*public_key); ASSERT_THAT(verifier, IsOk()); std::string message = "Some message"; util::StatusOr signature = (*direct_signer)->Sign(message); ASSERT_THAT(signature, IsOk()); EXPECT_THAT((*verifier)->Verify(*signature, message), IsOk()); } TEST_P(SphincsVerifyKeyManagerTest, CreateInvalidPublicKey) { const SphincsTestCase& test_case = GetParam(); StatusOr private_key = CreateValidPrivateKey(test_case.private_key_size, test_case.hash_type, test_case.variant, test_case.sig_length_type); ASSERT_THAT(private_key, IsOk()); StatusOr public_key = SphincsSignKeyManager().GetPublicKey(*private_key); ASSERT_THAT(public_key, IsOk()); std::string bad_public_key_data = "bad_public_key"; public_key->set_key_value(bad_public_key_data); util::StatusOr> verifier = SphincsVerifyKeyManager().GetPrimitive(*public_key); EXPECT_THAT(verifier, Not(IsOk())); } TEST_P(SphincsVerifyKeyManagerTest, CreateDifferentPublicKey) { const SphincsTestCase& test_case = GetParam(); StatusOr private_key = CreateValidPrivateKey(test_case.private_key_size, test_case.hash_type, test_case.variant, test_case.sig_length_type); ASSERT_THAT(private_key, IsOk()); // Create a new public key derived from a diffferent private key. StatusOr new_private_key = CreateValidPrivateKey(test_case.private_key_size, test_case.hash_type, test_case.variant, test_case.sig_length_type); ASSERT_THAT(new_private_key, IsOk()); StatusOr public_key = SphincsSignKeyManager().GetPublicKey(*new_private_key); ASSERT_THAT(public_key, IsOk()); subtle::SphincsParamsPqclean sphincs_params_pqclean = { .hash_type = EnumsPqcrypto::ProtoToSubtle(test_case.hash_type), .variant = EnumsPqcrypto::ProtoToSubtle(test_case.variant), .sig_length_type = EnumsPqcrypto::ProtoToSubtle(test_case.sig_length_type), .private_key_size = test_case.private_key_size}; subtle::SphincsPrivateKeyPqclean sphincs_private_key_pqclean( util::SecretDataFromStringView(private_key->key_value()), sphincs_params_pqclean); util::StatusOr> direct_signer = subtle::SphincsSign::New(sphincs_private_key_pqclean); ASSERT_THAT(direct_signer, IsOk()); util::StatusOr> verifier = SphincsVerifyKeyManager().GetPrimitive(*public_key); ASSERT_THAT(verifier, IsOk()); std::string message = "Some message"; util::StatusOr signature = (*direct_signer)->Sign(message); ASSERT_THAT(signature, IsOk()); EXPECT_THAT((*verifier)->Verify(*signature, message), Not(IsOk())); } INSTANTIATE_TEST_SUITE_P( SphincsVerifyKeyManagerTests, SphincsVerifyKeyManagerTest, testing::ValuesIn( {{"SPHINCSHARAKA128FROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA128FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA128FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA128SROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA128SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA128SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA128FSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA128SSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA192FROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA192FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA192FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA192SROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA192SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA192SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA192FSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA192SSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA256FROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA256FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA256FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA256SROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA256SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA256SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA256FSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA256SSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256128FROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256128FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256128FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256128SROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256128SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256128SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256128FSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256128FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256128FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256128SSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256128SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256128SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256192FROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256192FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256192FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256192SROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256192SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256192SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256192FSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256192FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256192FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256192SSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256192SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256192SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256256FROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256256FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256256FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256256SROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256256SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256256SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256256FSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256256FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256256FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256256SSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256256SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256256SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256128FROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256128FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256128FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256128SROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256128SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256128SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256128FSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256128SSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256192FROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256192FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256192FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256192SROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256192SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256192SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256192FSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256192SSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256256FROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256256FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256256FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256256SROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256256SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256256SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256256FSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256256SSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CRYPTO_PUBLICKEYBYTES}}), [](const testing::TestParamInfo& info) { return info.param.test_name; }); } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/dilithium_avx2_sign.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/subtle/dilithium_avx2_sign.h" #include #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "tink/experimental/pqcrypto/signature/subtle/dilithium_key.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_sign.h" #include "tink/util/status.h" #include "tink/util/statusor.h" extern "C" { #include "third_party/pqclean/crypto_sign/dilithium2/api.h" #include "third_party/pqclean/crypto_sign/dilithium2aes/api.h" #include "third_party/pqclean/crypto_sign/dilithium3/api.h" #include "third_party/pqclean/crypto_sign/dilithium3aes/api.h" #include "third_party/pqclean/crypto_sign/dilithium5/api.h" #include "third_party/pqclean/crypto_sign/dilithium5aes/api.h" } namespace crypto { namespace tink { namespace subtle { // static util::StatusOr> DilithiumAvx2Sign::New( DilithiumPrivateKeyPqclean private_key) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) return status; int32_t key_size = private_key.GetKeyData().size(); if (key_size != PQCLEAN_DILITHIUM2_CRYPTO_SECRETKEYBYTES && key_size != PQCLEAN_DILITHIUM3_CRYPTO_SECRETKEYBYTES && key_size != PQCLEAN_DILITHIUM5_CRYPTO_SECRETKEYBYTES) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrFormat("Invalid private key size (%d). " "The only valid sizes are %d, %d, %d.", private_key.GetKeyData().size(), PQCLEAN_DILITHIUM2_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM3_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM5_CRYPTO_SECRETKEYBYTES)); } return {absl::WrapUnique(new DilithiumAvx2Sign(std::move(private_key)))}; } util::StatusOr DilithiumAvx2Sign::Sign( absl::string_view data) const { size_t sig_length; int32_t key_size = private_key_.GetKeyData().size(); std::string signature; int result = 1; switch (key_size) { case PQCLEAN_DILITHIUM2_CRYPTO_SECRETKEYBYTES: { switch (private_key_.GetSeedExpansion()) { case DilithiumSeedExpansion::SEED_EXPANSION_AES: { signature.resize(PQCLEAN_DILITHIUM2AES_CRYPTO_BYTES, '0'); result = PQCLEAN_DILITHIUM2AES_crypto_sign_signature( reinterpret_cast(signature.data()), &sig_length, reinterpret_cast(data.data()), data.size(), reinterpret_cast( private_key_.GetKeyData().data())); break; } case DilithiumSeedExpansion::SEED_EXPANSION_SHAKE: { signature.resize(PQCLEAN_DILITHIUM2_CRYPTO_BYTES, '0'); result = PQCLEAN_DILITHIUM2_crypto_sign_signature( reinterpret_cast(signature.data()), &sig_length, reinterpret_cast(data.data()), data.size(), reinterpret_cast( private_key_.GetKeyData().data())); break; } default: { return util::Status(absl::StatusCode::kInternal, "Invalid seed expansion."); } } break; } case PQCLEAN_DILITHIUM3_CRYPTO_SECRETKEYBYTES: { switch (private_key_.GetSeedExpansion()) { case DilithiumSeedExpansion::SEED_EXPANSION_AES: { signature.resize(PQCLEAN_DILITHIUM3AES_CRYPTO_BYTES, '0'); result = PQCLEAN_DILITHIUM3AES_crypto_sign_signature( reinterpret_cast(signature.data()), &sig_length, reinterpret_cast(data.data()), data.size(), reinterpret_cast( private_key_.GetKeyData().data())); break; } case DilithiumSeedExpansion::SEED_EXPANSION_SHAKE: { signature.resize(PQCLEAN_DILITHIUM3_CRYPTO_BYTES, '0'); result = PQCLEAN_DILITHIUM3_crypto_sign_signature( reinterpret_cast(signature.data()), &sig_length, reinterpret_cast(data.data()), data.size(), reinterpret_cast( private_key_.GetKeyData().data())); break; } default: { return util::Status(absl::StatusCode::kInternal, "Invalid seed expansion."); } } break; } case PQCLEAN_DILITHIUM5_CRYPTO_SECRETKEYBYTES: { switch (private_key_.GetSeedExpansion()) { case DilithiumSeedExpansion::SEED_EXPANSION_AES: { signature.resize(PQCLEAN_DILITHIUM5AES_CRYPTO_BYTES, '0'); result = PQCLEAN_DILITHIUM5AES_crypto_sign_signature( reinterpret_cast(signature.data()), &sig_length, reinterpret_cast(data.data()), data.size(), reinterpret_cast( private_key_.GetKeyData().data())); break; } case DilithiumSeedExpansion::SEED_EXPANSION_SHAKE: { signature.resize(PQCLEAN_DILITHIUM5_CRYPTO_BYTES, '0'); result = PQCLEAN_DILITHIUM5_crypto_sign_signature( reinterpret_cast(signature.data()), &sig_length, reinterpret_cast(data.data()), data.size(), reinterpret_cast( private_key_.GetKeyData().data())); break; } default: { return util::Status(absl::StatusCode::kInternal, "Invalid seed expansion."); } } break; } default: return util::Status(absl::StatusCode::kInternal, "Invalid keysize."); } if (result != 0) { return util::Status(absl::StatusCode::kInternal, "Signing failed."); } return signature; } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/dilithium_avx2_sign.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_DILITHIUM_AVX2_SIGN_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_DILITHIUM_AVX2_SIGN_H_ #include #include #include #include "absl/strings/string_view.h" #include "tink/experimental/pqcrypto/signature/subtle/dilithium_key.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_sign.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // Post-Quantum Signing using an optimized implementation of Dilithium, // based on AVX2 vector instructions class DilithiumAvx2Sign : public PublicKeySign { public: static crypto::tink::util::StatusOr> New( DilithiumPrivateKeyPqclean private_key); // Computes the signature for 'data'. crypto::tink::util::StatusOr Sign( absl::string_view data) const override; ~DilithiumAvx2Sign() override = default; static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kNotFips; private: explicit DilithiumAvx2Sign(DilithiumPrivateKeyPqclean private_key) : private_key_(std::move(private_key)) {} const DilithiumPrivateKeyPqclean private_key_; }; } // namespace subtle } // namespace tink } // namespace crypto // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_DILITHIUM_AVX2_SIGN_H_ #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_DILITHIUM_AVX2_SIGN_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/dilithium_avx2_sign_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/subtle/dilithium_avx2_sign.h" #include #include #include #include #include "gmock/gmock.h" #include "testing/base/public/googletest.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/config/tink_fips.h" #include "tink/experimental/pqcrypto/signature/subtle/dilithium_key.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" extern "C" { #include "third_party/pqclean/crypto_sign/dilithium2/api.h" #include "third_party/pqclean/crypto_sign/dilithium2aes/api.h" #include "third_party/pqclean/crypto_sign/dilithium3/api.h" #include "third_party/pqclean/crypto_sign/dilithium3aes/api.h" #include "third_party/pqclean/crypto_sign/dilithium5/api.h" #include "third_party/pqclean/crypto_sign/dilithium5aes/api.h" } namespace crypto { namespace tink { namespace subtle { namespace { struct DilithiumTestCase { std::string test_name; int32_t key_size; int32_t signature_length; DilithiumSeedExpansion seed_expansion; }; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using crypto::tink::util::Status; using DilithiumAvx2SignTest = testing::TestWithParam; TEST(DilithiumAvx2SignTest, InvalidPrivateKeys) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } for (int keysize = 0; keysize <= PQCLEAN_DILITHIUM5_CRYPTO_SECRETKEYBYTES; keysize++) { if (keysize == PQCLEAN_DILITHIUM2_CRYPTO_SECRETKEYBYTES || keysize == PQCLEAN_DILITHIUM3_CRYPTO_SECRETKEYBYTES || keysize == PQCLEAN_DILITHIUM5_CRYPTO_SECRETKEYBYTES) { // Valid key size. continue; } util::SecretData key_data(keysize, 'x'); EXPECT_FALSE( DilithiumAvx2Sign::New( *DilithiumPrivateKeyPqclean::NewPrivateKey( key_data, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE)) .ok()); } } TEST_P(DilithiumAvx2SignTest, SignatureLength) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } const DilithiumTestCase& test_case = GetParam(); // Generate key pair. util::StatusOr< std::pair> key_pair = DilithiumPrivateKeyPqclean::GenerateKeyPair( test_case.key_size, test_case.seed_expansion); ASSERT_THAT(key_pair, IsOk()); // Create a new signer. util::StatusOr> signer = DilithiumAvx2Sign::New(key_pair->first); ASSERT_THAT(signer, IsOk()); // Sign a message. std::string message = "message to be signed"; util::StatusOr signature = (*std::move(signer))->Sign(message); ASSERT_THAT(signature, IsOk()); // Check signature size. EXPECT_NE(*signature, message); EXPECT_EQ((*signature).size(), test_case.signature_length); } TEST_P(DilithiumAvx2SignTest, Determinism) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } const DilithiumTestCase& test_case = GetParam(); // Generate key pair. util::StatusOr< std::pair> key_pair = DilithiumPrivateKeyPqclean::GenerateKeyPair( test_case.key_size, test_case.seed_expansion); ASSERT_THAT(key_pair, IsOk()); // Create two signers based on same private key. util::StatusOr> first_signer = DilithiumAvx2Sign::New(key_pair->first); ASSERT_THAT(first_signer, IsOk()); util::StatusOr> second_signer = DilithiumAvx2Sign::New(key_pair->first); ASSERT_THAT(second_signer, IsOk()); // Sign the same message twice, using the same private key. std::string message = "message to be signed"; util::StatusOr first_signature = (*std::move(first_signer))->Sign(message); ASSERT_THAT(first_signature, IsOk()); util::StatusOr second_signature = (*std::move(second_signer))->Sign(message); ASSERT_THAT(second_signature, IsOk()); // Check signatures size. EXPECT_NE(*first_signature, message); EXPECT_EQ((*first_signature).size(), test_case.signature_length); EXPECT_NE(*second_signature, message); EXPECT_EQ((*second_signature).size(), test_case.signature_length); // Check if signatures are equal. EXPECT_EQ(*first_signature, *second_signature); } TEST_P(DilithiumAvx2SignTest, FipsMode) { if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips."; } const DilithiumTestCase& test_case = GetParam(); // Generate key pair. util::StatusOr< std::pair> key_pair = DilithiumPrivateKeyPqclean::GenerateKeyPair( test_case.key_size, test_case.seed_expansion); ASSERT_THAT(key_pair, IsOk()); // Create a new signer. EXPECT_THAT(DilithiumAvx2Sign::New(key_pair->first).status(), StatusIs(absl::StatusCode::kInternal)); } INSTANTIATE_TEST_SUITE_P( DilithiumAvx2SignTests, DilithiumAvx2SignTest, testing::ValuesIn({ {"Dilithium2", PQCLEAN_DILITHIUM2_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM2_CRYPTO_BYTES, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE}, {"Dilithium3", PQCLEAN_DILITHIUM3_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM3_CRYPTO_BYTES, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE}, {"Dilithium5", PQCLEAN_DILITHIUM5_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM5_CRYPTO_BYTES, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE}, {"Dilithium2Aes", PQCLEAN_DILITHIUM2AES_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM2AES_CRYPTO_BYTES, DilithiumSeedExpansion::SEED_EXPANSION_AES}, {"Dilithium3Aes", PQCLEAN_DILITHIUM3AES_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM3_CRYPTO_BYTES, DilithiumSeedExpansion::SEED_EXPANSION_AES}, {"Dilithium5Aes", PQCLEAN_DILITHIUM5AES_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM5AES_CRYPTO_BYTES, DilithiumSeedExpansion::SEED_EXPANSION_AES}, }), [](const testing::TestParamInfo& info) { return info.param.test_name; }); } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/dilithium_avx2_verify.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/subtle/dilithium_avx2_verify.h" #include #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "tink/experimental/pqcrypto/signature/subtle/dilithium_key.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_verify.h" #include "tink/util/status.h" #include "tink/util/statusor.h" extern "C" { #include "third_party/pqclean/crypto_sign/dilithium2/api.h" #include "third_party/pqclean/crypto_sign/dilithium2aes/api.h" #include "third_party/pqclean/crypto_sign/dilithium3/api.h" #include "third_party/pqclean/crypto_sign/dilithium3aes/api.h" #include "third_party/pqclean/crypto_sign/dilithium5/api.h" #include "third_party/pqclean/crypto_sign/dilithium5aes/api.h" } namespace crypto { namespace tink { namespace subtle { // static util::StatusOr> DilithiumAvx2Verify::New( DilithiumPublicKeyPqclean public_key) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) return status; int32_t key_size = public_key.GetKeyData().size(); if (key_size != PQCLEAN_DILITHIUM2_CRYPTO_PUBLICKEYBYTES && key_size != PQCLEAN_DILITHIUM3_CRYPTO_PUBLICKEYBYTES && key_size != PQCLEAN_DILITHIUM5_CRYPTO_PUBLICKEYBYTES) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrFormat("Invalid public key size (%d). " "The only valid sizes are %d, %d, %d.", key_size, PQCLEAN_DILITHIUM2_CRYPTO_PUBLICKEYBYTES, PQCLEAN_DILITHIUM3_CRYPTO_PUBLICKEYBYTES, PQCLEAN_DILITHIUM5_CRYPTO_PUBLICKEYBYTES)); } return {absl::WrapUnique(new DilithiumAvx2Verify(std::move(public_key)))}; } util::Status DilithiumAvx2Verify::Verify(absl::string_view signature, absl::string_view data) const { int32_t key_size = public_key_.GetKeyData().size(); int result = 1; switch (key_size) { case PQCLEAN_DILITHIUM2_CRYPTO_PUBLICKEYBYTES: { switch (public_key_.GetSeedExpansion()) { case DilithiumSeedExpansion::SEED_EXPANSION_AES: { result = PQCLEAN_DILITHIUM2AES_crypto_sign_verify( reinterpret_cast(signature.data()), signature.size(), reinterpret_cast(data.data()), data.size(), reinterpret_cast( public_key_.GetKeyData().data())); break; } case DilithiumSeedExpansion::SEED_EXPANSION_SHAKE: { result = PQCLEAN_DILITHIUM2_crypto_sign_verify( reinterpret_cast(signature.data()), signature.size(), reinterpret_cast(data.data()), data.size(), reinterpret_cast( public_key_.GetKeyData().data())); break; } default: { return util::Status(absl::StatusCode::kInternal, "Invalid seed expansion."); } } break; } case PQCLEAN_DILITHIUM3_CRYPTO_PUBLICKEYBYTES: { switch (public_key_.GetSeedExpansion()) { case DilithiumSeedExpansion::SEED_EXPANSION_AES: { result = PQCLEAN_DILITHIUM3AES_crypto_sign_verify( reinterpret_cast(signature.data()), signature.size(), reinterpret_cast(data.data()), data.size(), reinterpret_cast( public_key_.GetKeyData().data())); break; } case DilithiumSeedExpansion::SEED_EXPANSION_SHAKE: { result = PQCLEAN_DILITHIUM3_crypto_sign_verify( reinterpret_cast(signature.data()), signature.size(), reinterpret_cast(data.data()), data.size(), reinterpret_cast( public_key_.GetKeyData().data())); break; } default: { return util::Status(absl::StatusCode::kInternal, "Invalid seed expansion."); } } break; } case PQCLEAN_DILITHIUM5_CRYPTO_PUBLICKEYBYTES: { switch (public_key_.GetSeedExpansion()) { case DilithiumSeedExpansion::SEED_EXPANSION_AES: { result = PQCLEAN_DILITHIUM5AES_crypto_sign_verify( reinterpret_cast(signature.data()), signature.size(), reinterpret_cast(data.data()), data.size(), reinterpret_cast( public_key_.GetKeyData().data())); break; } case DilithiumSeedExpansion::SEED_EXPANSION_SHAKE: { result = PQCLEAN_DILITHIUM5_crypto_sign_verify( reinterpret_cast(signature.data()), signature.size(), reinterpret_cast(data.data()), data.size(), reinterpret_cast( public_key_.GetKeyData().data())); break; } default: { return util::Status(absl::StatusCode::kInternal, "Invalid seed expansion."); } } break; } default: return util::Status(absl::StatusCode::kInternal, "Invalid keysize."); } if (result != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Signature is not valid."); } return util::OkStatus(); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/dilithium_avx2_verify.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_DILITHIUM_AVX2_VERIFY_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_DILITHIUM_AVX2_VERIFY_H_ #include #include #include "absl/strings/string_view.h" #include "tink/experimental/pqcrypto/signature/subtle/dilithium_key.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_verify.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { class DilithiumAvx2Verify : public PublicKeyVerify { public: static crypto::tink::util::StatusOr> New( DilithiumPublicKeyPqclean public_key); // Verifies that 'signature' is a digital signature for 'data'. crypto::tink::util::Status Verify(absl::string_view signature, absl::string_view data) const override; static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kNotFips; private: explicit DilithiumAvx2Verify(DilithiumPublicKeyPqclean public_key) : public_key_(public_key) {} DilithiumPublicKeyPqclean public_key_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_DILITHIUM_AVX2_VERIFY_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/dilithium_avx2_verify_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/subtle/dilithium_avx2_verify.h" #include #include #include #include #include "gmock/gmock.h" #include "testing/base/public/googletest.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/config/tink_fips.h" #include "tink/experimental/pqcrypto/signature/subtle/dilithium_avx2_sign.h" #include "tink/experimental/pqcrypto/signature/subtle/dilithium_key.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" extern "C" { #include "third_party/pqclean/crypto_sign/dilithium2/api.h" #include "third_party/pqclean/crypto_sign/dilithium2aes/api.h" #include "third_party/pqclean/crypto_sign/dilithium3/api.h" #include "third_party/pqclean/crypto_sign/dilithium3aes/api.h" #include "third_party/pqclean/crypto_sign/dilithium5/api.h" #include "third_party/pqclean/crypto_sign/dilithium5aes/api.h" } namespace crypto { namespace tink { namespace subtle { namespace { struct DilithiumTestCase { std::string test_name; int32_t key_size; DilithiumSeedExpansion seed_expansion; }; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using crypto::tink::util::Status; using DilithiumAvx2VerifyTest = testing::TestWithParam; TEST(DilithiumAvx2VerifyTest, InvalidPublicKeys) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } // Null public key. const absl::string_view null_public_key; EXPECT_FALSE( DilithiumAvx2Verify::New( *DilithiumPublicKeyPqclean::NewPublicKey( null_public_key, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE)) .ok()); for (int keysize = 0; keysize < PQCLEAN_DILITHIUM2_CRYPTO_PUBLICKEYBYTES; keysize++) { if (keysize == PQCLEAN_DILITHIUM2_CRYPTO_PUBLICKEYBYTES || keysize == PQCLEAN_DILITHIUM3_CRYPTO_PUBLICKEYBYTES || keysize == PQCLEAN_DILITHIUM5_CRYPTO_PUBLICKEYBYTES) { // Valid key size. continue; } std::string key(keysize, 'x'); EXPECT_FALSE(DilithiumAvx2Verify::New( *DilithiumPublicKeyPqclean::NewPublicKey( key, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE)) .ok()); } } TEST_P(DilithiumAvx2VerifyTest, BasicSignVerify) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } const DilithiumTestCase& test_case = GetParam(); // Generate key pair. util::StatusOr< std::pair> key_pair = DilithiumPrivateKeyPqclean::GenerateKeyPair( test_case.key_size, test_case.seed_expansion); ASSERT_THAT(key_pair, IsOk()); // Create a new signer. util::StatusOr> signer = DilithiumAvx2Sign::New(key_pair->first); ASSERT_THAT(signer, IsOk()); // Create a new verifier. absl::StatusOr> verifier = DilithiumAvx2Verify::New(key_pair->second); ASSERT_THAT(verifier, IsOk()); // Sign a message. std::string message = "message to be signed"; absl::StatusOr signature = (*std::move(signer))->Sign(message); ASSERT_THAT(signature, IsOk()); // Verify signature. Status status = (*verifier)->Verify(*signature, message); EXPECT_THAT(status, IsOk()); } TEST_P(DilithiumAvx2VerifyTest, FailsWithWrongMessage) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } const DilithiumTestCase& test_case = GetParam(); // Generate key pair. util::StatusOr< std::pair> key_pair = DilithiumPrivateKeyPqclean::GenerateKeyPair( test_case.key_size, test_case.seed_expansion); ASSERT_THAT(key_pair, IsOk()); // Create a new signer. util::StatusOr> signer = DilithiumAvx2Sign::New(key_pair->first); ASSERT_THAT(signer, IsOk()); // Create a new verifier. absl::StatusOr> verifier = DilithiumAvx2Verify::New(key_pair->second); ASSERT_THAT(verifier, IsOk()); // Sign a message. std::string message = "message to be signed"; absl::StatusOr signature = (*std::move(signer))->Sign(message); ASSERT_THAT(signature, IsOk()); // Verify signature. Status status = (*verifier)->Verify(*signature, "some bad message"); EXPECT_FALSE(status.ok()); } TEST_P(DilithiumAvx2VerifyTest, FailsWithWrongSignature) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } const DilithiumTestCase& test_case = GetParam(); // Generate key pair. util::StatusOr< std::pair> key_pair = DilithiumPrivateKeyPqclean::GenerateKeyPair( test_case.key_size, test_case.seed_expansion); ASSERT_THAT(key_pair, IsOk()); // Create a new signer. util::StatusOr> signer = DilithiumAvx2Sign::New(key_pair->first); ASSERT_THAT(signer, IsOk()); // Create a new verifier. absl::StatusOr> verifier = DilithiumAvx2Verify::New(key_pair->second); ASSERT_THAT(verifier, IsOk()); // Sign a message. std::string message = "message to be signed"; absl::StatusOr signature = (*std::move(signer))->Sign(message); ASSERT_THAT(signature, IsOk()); // Verify signature. Status status = (*verifier)->Verify(*signature + "some trailing data", message); EXPECT_FALSE(status.ok()); } TEST_P(DilithiumAvx2VerifyTest, FailsWithByteFlipped) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } const DilithiumTestCase& test_case = GetParam(); // Generate key pair. util::StatusOr< std::pair> key_pair = DilithiumPrivateKeyPqclean::GenerateKeyPair( test_case.key_size, test_case.seed_expansion); ASSERT_THAT(key_pair, IsOk()); // Create a new signer. util::StatusOr> signer = DilithiumAvx2Sign::New(key_pair->first); ASSERT_THAT(signer, IsOk()); // Create a new verifier. absl::StatusOr> verifier = DilithiumAvx2Verify::New(key_pair->second); ASSERT_THAT(verifier, IsOk()); // Sign a message. std::string message = "message to be signed"; absl::StatusOr signature = (*std::move(signer))->Sign(message); ASSERT_THAT(signature, IsOk()); // Invalidate one signature byte. (*signature)[0] ^= 1; // Verify signature. Status status = (*verifier)->Verify("some bad signature", message); EXPECT_FALSE(status.ok()); } TEST_P(DilithiumAvx2VerifyTest, FipsMode) { if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips."; } const DilithiumTestCase& test_case = GetParam(); // Generate key pair. util::StatusOr< std::pair> key_pair = DilithiumPrivateKeyPqclean::GenerateKeyPair( test_case.key_size, test_case.seed_expansion); ASSERT_THAT(key_pair, IsOk()); EXPECT_THAT(DilithiumAvx2Verify::New(key_pair->second).status(), StatusIs(absl::StatusCode::kInternal)); } struct TestVector { std::string public_key; std::string message; std::string signature; }; // Test vectors generated with https://github.com/pq-crystals/dilithium // commit 9dddb2a0537734e749ec2c8d4f952cb90cd9e67b TEST(DilithiumAvx2VerifyTest, Vectors) { TestVector dilithium_vectors[] = { {/*TEST Dilithium2*/ /*public_key= */ absl::HexStringToBytes( "1C0EE1111B08003F28E65E8B3BDEB037CF8F221DFCDAF5950EDB38D506D85BEF" "6177E3DE0D4F1EF5847735947B56D08E841DB2444FA2B729ADEB1417CA7ADF42" "A1490C5A097F002760C1FC419BE8325AAD0197C52CED80D3DF18E7774265B289" "912CECA1BE3A90D8A4FDE65C84C610864E47DEECAE3EEA4430B9909559408D11" "A6ABDB7DB9336DF7F96EAB4864A6579791265FA56C348CB7D2DDC90E133A95C3" "F6B13601429F5408BD999AA479C1018159550EC55A113C493BE648F4E036DD4F" "8C809E036B4FBB918C2C484AD8E1747AE05585AB433FDF461AF03C25A7737007" "21AA05F7379FE7F5ED96175D4021076E7F52B60308EFF5D42BA6E093B3D0815E" "B3496646E49230A9B35C8D41900C2BB8D3B446A23127F7E096D85A1C794AD4C8" "9277904FC6BFEC57B1CDD80DF9955030FDCA741AFBDAC827B13CCD5403588AF4" "644003C2265DFA4D419DBCCD2064892386518BE9D51C16498275EBECF5CDC7A8" "20F2C29314AC4A6F08B2252AD3CFB199AA42FE0B4FB571975C1020D949E194EE" "1EAD937BFB550BB3BA8E357A029C29F077554602E1CA2F2289CB9169941C3AAF" "DB8E58C7F2AC77291FB4147C65F6B031D3EBA42F2ACFD9448A5BC22B476E07CC" "CEDA2306C554EC9B7AB655F1D7318C2B7E67D5F69BEDF56000FDA98986B5AB1B" "3A22D8DFD6681697B23A55C96E8710F3F98C044FB15F606313EE56C0F1F5CA0F" "512E08484FCB358E6E528FFA89F8A866CCFF3C0C5813147EC59AF0470C4AAD01" "41D34F101DA2E5E1BD52D0D4C9B13B3E3D87D1586105796754E7978CA1C68A7D" "85DF112B7AB921B359A9F03CBD27A7EAC87A9A80B0B26B4C9657ED85AD7FA261" "6AB345EB8226F69FC0F48183FF574BCD767B5676413ADB12EA2150A0E97683EE" "54243C25B7EA8A718606F86993D8D0DACE834ED341EEB724FE3D5FF0BC8B8A7B" "8104BA269D34133A4CF8300A2D688496B59B6FCBC61AE96062EA1D8E5B410C56" "71F424417ED693329CD983001FFCD10023D598859FB7AD5FD263547117100690" "C6CE7438956E6CC57F1B5DE53BB0DC72CE9B6DEAA85789599A70F0051F1A0E25" "E86D888B00DF36BDBC93EF7217C45ACE11C0790D70E9953E5B417BA2FD9A4CAF" "82F1FCE6F45F53E215B8355EF61D891DF1C794231C162DD24164B534A9D48467" "CDC323624C2F95D4402FF9D66AB1191A8124144AFA35D4E31DC86CAA797C31F6" "8B85854CD959C4FAC5EC53B3B56D374B888A9E979A6576B6345EC8522C960699" "0281BF3EF7C5945D10FD21A2A1D2E5404C5CF21220641391B98BCF825398305B" "56E58B611FE5253203E3DF0D22466A73B3F0FBE43B9A62928091898B8A0E5B26" "9DB586B0E4DDEF50D682A12D2C1BE824149AA254C6381BB412D77C3F9AA902B6" "88C81715A59C839558556D35ED4FC83B4AB18181F40F73DCD76860D8D8BF9452" "0237C2AC0E463BA09E3C9782380DC07FE4FCBA340CC2003439FD231461063807" "0D6C9EEA0A70BAE83B5D5D3C5D3FDE26DD01606C8C520158E7E5104020F248CE" "AA666457C10AEBF068F8A3BD5CE7B52C6AF0ABD5944AF1AD4752C9113976083C" "03B6C34E1D47ED69644CAD782C2F7D05F8A148961D965FA2E1723A8DDEBC22A9" "0CD783DD1F4DB38FB9AE5A6714B3D946781643D317B7DD79381CF789A9588BB3" "E193B92A0B60D6B07D047F6984B0609EC57543C394CA8D5E5BCC2A731A79618B" "D1E2E0DA8704AF98F20F5F8F5452DDF646B95B341DD7F0D2CC1FA15BD9895CD5" "B65AA1CB94B5E2E788FDA9825B656639193D98328154A4F2C35495A38B6EA0D2" "FFAAA35DF92C203C7F31CBBCA7BD03C3C2302190CECD161FD49237E4F839E3F" "3"), /*message = */ absl::HexStringToBytes("D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835A" "D55B22E75BF57BB556AC8"), /*signature = */ absl::HexStringToBytes( "AF5920774603D20E98A79AA3ABFA32B6E22519E673E37AC4AC73FE85341E2C29" "23C1992E1B0BBE3873D7C8FC5662F207BF58EA381CD4A3A0C062DEC45BDAF8BA" "0AA52BEF6FA14F3F6CF28F7620BF94A92CC27D045414A64D65C0149630528024" "28BF3987A2D47516CA5C78AAB96B7BE11BCA5F2C5A26F3FCE3A26E8E09A2738F" "386F75D448F937EF19A846BD4DD949CAAF36DB5629884AF53A023E3F180FE4C0" "FAFF7BE5DFE4E89ADE3095A65600421461AD08C129D6CEA851BB39C0D7A7D151" "405689A091FA4DEBAC373CF54AE078F0AF7557BBC6F06A535AE8949E0C65308A" "59840072375295802D0E2CE9A3DA98426A00FF03FE80218C0EEC8EFE581CB9CC" "9A7D66B20645A8CD0490D3CE4F7E6FEAE9C9EB7A57F964D0EBC7C90B7A9F8630" "0B3E8095E64D1294CFC4B4D9E272E8FA8DB5707D7004AF22DBFF9CFD4863DF57" "3FE004341DA3CD4A3082532C2620455FA37C562BAFD5684EA128AFC79E01FC9B" "31E8433BAD7C029F2F13CC10592D2332E3E08B80D350463DE72750B1F806F493" "E143BD5FCA7D1698081B31BF876B2A1BC9DF50952D13B6C1321B1111172145A6" "27AE0B4427B98975CBFFF7D68275754B45B682D709E168522E84FEA7DD3BB0F4" "1505FF71926431D1A90D4CBF9A527AD4E284976FFF8BD9D6224A4F260391A987" "FB6DA6EE42C2A4900F407CE1F02E322475D313FBEBB68C2E05730809448A7428" "A5940139EBDF1B5556FCC5D42E1A13F32230CB6F0724831D0D071BBA5A670480" "6F475B74BA91B6E385D48620958D0AB1BF2B184E10F3E753B71337BE9EB65378" "6785B43AC7E5C494AC1BCB043D461425B36098AC93055A0105AB8523B61D024A" "6E9B56A42D3C04726512AE4CFE05710446B06F694234EE4FA8FEEDDDC5F28A65" "EDE2EB58E965FE3627A571BC45B397ED092AB4BE00041729C4D192FE30678279" "D223A848CF4366E92B3F68DEE97C9B4A7FF22F937BE6C56639961DB29FA3CFEC" "FFF293140886FFB92EBC79DAB59CEAF869C64F8EAF585CE97DD6B78F892772DB" "88A958CF0AB557A7FAA83FE621477E2B84497AB5A8ECF4A7BD32DFB902F05D2C" "A31047D0F1919ADDE1EE6DFD58E59BC4DAB3CCBBA36AAAF6AFCCC7B095CA94A1" "95BE9A289526B588C3A9C56876FC415D521D442BAC0298D302419AD527DA249C" "2A660CD064213FFAD563183F37972578EEB9F70AC67AEE6CC2B71F283A95930B" "554738555791C25E7A399E685636D58D69CB6BE793B45C1969E7D5615627EBC3" "2EED45440F87880D2829FA4FC871866164D259ED95D2731871017FF51894066F" "AE1FFA6F4B4A6F84FCFFDA09E718FA17135EDB3F48558D5BA67F9E6F0900340B" "D04DFE59B7BD67745884FB84AE3F8EE763D202743652D4F7333450580490B9C7" "44935B19C1D5FB0DB5FBB461411362838037EB7EC3F63F26C893E7CC1C3B3F47" "67ABAE00FEB7BB99B1420BB29EA614747896D9EDCF8107FE504C9C308A8264DA" "CE318D87CFE4761803E9A60DEFA6144AABC1F10A45B140DED754E73586C467BB" "7BF19EDEF25BE0C65E93C5E5EB8F880CCE4A858757F8FF56062B1067F4106F76" "B7007F6EA6F945047E85BD0FAD9D26994F678A0612B87CCF9C0CF9A433D889C9" "6E4C12BE372277005B06AD127105D16D8FB142AEAE5373ABD61D9ADCFC5550D6" "23CA3B8824B0E2E08C2BF4E2841EAC4C5DC56CF8954CF207C263F27C9F309F10" "307C0D84A65878425031375DD810D2D7E51098A3814350795C4A077FA40DD44F" "0FA7510F7C3F631407CF34F604C7B335632A20D2AD419BD7CC6D4242B1C66C35" "E5A5EDCCB13CA37D3B50465F3B4AAFF7E3161E7936088AE08401FD2C37D67A2F" "F91D3E6F08686D64BC2FC6C57106E49FA384AC22219F07EE8996CA3DFF59DCC5" "092A4BADBE87AEDE7F69A04C79B33BDF35D4A0E4CB4B55019CB0BF275295B93B" "DABEA516CA2B616A56918600B724BE7A01EC4EF54312B30D66F507815F2780FF" "EE7C30F8425A92252CE550FAB4E902E7B382D46DBD20EFE1BB0EF8A496873C09" "C4CEB0303C7F1DABA0102DE94190B6AC6DC810F72BCA3AA292FF38BD51A7FAB8" "509EC4FBE0EAA3C986166A674B7871155C348C477EF8CEDC832B5ABEE71A8D18" "D06DD0F5221160ABEB71E6E82CFABF731EA3515A76EF07B2C16C63B37F7AB73B" "67F005929A753E453B930C0AF432277FD77D8A1EB8022CDE9665763B014F0A67" "2A04160B0A06F5540F4C264B7F22740690A2352DC863B588303AD51F0AE162BF" "79797F07B534501CBBFDB713A724AA98E19532187180CCFADC6EBE3142FA7DB6" "6CD4DE7B9FBD4C8235686DB68CAF489AFA4E1E87AEF0CEFD8037E3A578EE62EB" "7F94ED5BC0B58EEA4B4C45FC56D31D29944D095AC96C29083DA2C77181D97A55" "FE6E903A2F2783DE0BAA5F47D704785C33E8D5C87ED61E65459167310EB7A995" "74EF819AE9161A3BD09634803D9E1E4EC7386D7946984517213AB9CF66AEA551" "CC457C39F86AF294CF7B073F563ED4DAB9419BDF004BD05C92B4E80EC3CFEAC9" "7E1DDA554FDA625C4B9B039BAA7C5A2F6F97057792483CF5F852D4C3AC71AD50" "F779953DCFE2F63ED235D8E1D5345D6C6DF0555CC2631DEAD9B714BC4C16501E" "01261381F3679715345123388C852D57DCF1941D0911D49FEA7143FD2FC343A5" "075B64CCA48291DC28B83F76074589EAB217C7847840652C0E3AE278B3B6FB0D" "800C5E7DB79D5CB9CC1A87450C00B7677812D22EE20FDE8C1753A7FB93BA8BBB" "8595A6393DF54AA9CDB6E0879A26E49BD3B01513C6053A0746C8596CE5E5B225" "CFCA26AB8BF12F1FE0A647A9E4453039A1226194C46E8B98ACD710F18FB7EC05" "476C1CD8FC3112CCDDB1582B8817C18FE315353E7A47C821E9EE3A43CADE1B80" "D92A0AE8DCEB4DFF766A54DF3665FEFE3C252B72DAD7B1E3359E7FA25562C3E3" "9DB521CE1874111FB090DBD38B3180AD034B57B031DC4DD6AF7C1A8AF3F6CE7E" "DB1A9E4B6D4A5920E3620818820659762EF7A4243F51DF2D8A900737D5810569" "9B4E10CBCB359C7F3A4007697C482050EC33CF8041916A3B919A50D96EF0F589" "FD4556F30DBDD942EAB79DFA97C07E30247074352E1BF98E349CC7EFA5A1B8FC" "E4F18F1FAF6F07C99C321448B0395C8A9CBC466412F89C1A98BF5715842844F0" "E8236FA4696C4658B8FDE4425D09D67A38AC7258E5D5966F2D3FF66A0C0CE76E" "7F6B81A1BCD047FD3A205BF0CCAEA3B11079909C6CE5698F32E1F3409658FFA0" "1EAECB4AE2B092B78989DAAD6623BB11F49F0F8F8699EC05661502FFCAD03CF4" "15191A222D3C4C7B8AB0B5B9BBC2D9DCEFF7202D3F4244494F525364666974C4" "D9E6F5FA0001041927373D5A7680B8C1C9FE2029383B3C484D565F65799D9EA6" "A9ADD2DEE5E7F7F9000000000000000012243248")}, {/*TEST Dilithium3*/ /*public_key= */ absl::HexStringToBytes( "1C0EE1111B08003F28E65E8B3BDEB037CF8F221DFCDAF5950EDB38D506D85BEF" "032369A2CE572FD08BFC304B4848E78D752D77E97A28B99B9BB6FB5C7C633751" "4B321ECDC1FB669F26D4171AB42B72720EE70E0519A6E1D3D6D9914EC1B21CDE" "38B41AAC1D3ABEE6F2B7495C4C820C1FC0CC9E71E24CFB5C9C0D8EEF4264AF48" "4FAE4D6E5DDE65D4DF72B61C6DBD26F861A5E0B853AC5413226FEBBABA5EB474" "C6FB25A82678EA1606B452A23112221017B8C073C10378F9145641A8C078C0ED" "9E421650F748892522AB9FB7D1FF8CF1CC71B8566E8DA33CD7361770C044349A" "C440CCCDC6BBE35E6C55782766F38E688BF47821037299E344ECDECA17AD5D15" "CD27A4F7B070661138EDE8ED72A8959C5AE36B1C46094A53CB21A7A42673F140" "1C2B259494090E2F53D7EE7063431EE5858002D850AF909C3783436010F7EA88" "625A36A0F0189FDE75B7E8C7E4B19D8527008328ADBC929BBC86E964CFC48B8C" "F1DA5D7ED3333AB55C15072832214A779A5FD10CC04005F46C1AA8884A161992" "472FD535B95ED18BDE1C6D8CE678D2817D69F90571103E8520E7313CE7B930C5" "EBFAF2F4EC758B626B5543A068CDE0FD0E94E6A64475B23268BF0380D075508F" "85128CA26F31A90C4A7D28440D54D4066B404588588B4CCF850B975C73AFE68C" "BCD102755F61EB3E60323C576E529EC0BF23BFA5BEA39CB73C37E8395D8DBD4C" "8DC8AB2F70A0BFC3A78C0D413F08D14D632BC0403B0383DBBB22BD9B113C8945" "2AEAB11210097947FEAAA3C9F05D1D300C33A55E3FBC81259E862705C3A13B9E" "E35F6B23ED10F4EDEA9519FA91B7BCD0D501B5ED57D9049FAB91AA779C725FF8" "E9F78017EA7807FA254B7105E826D096C01ADAE2C5D138251A92A478A33373F4" "DE912B83B6FB4B0D0DE6BC1118BB2FCFB07BD227A5F7F991439A13DE1238180C" "DC55119E65C418584D807A926E4A9C0F70155EE196FB07656D9AA7982B8795DB" "AD43D1059CA7F580D3320C0438A5ED5A7032B2E959678410F11AD98BE8826A44" "262615645D759A862B2AC52D3B014A25E8473F1F1EA4CFA819930AB3A34D710D" "EEE70CA13E88FD71AA064E6CB4697DE0E463B1370A6A3BFE98FDFE7B5471FF8D" "F6A6879FBEF9AFB3519D780757D67440AC36E837BAC3833EEAA980BD82B79364" "36A0307D164B6438869AE606E980518E913D0EE302396EF4EB25D9866E4BAFA1" "01E5992931361C4A982253D58ABE3BD57107635A46F09512085F4ADA08EC8B1B" "3910B0153B2AAFCAE5033EDD4153248DCD85B02C9A25D8BDC4068BB857417262" "97A25AEC55C44AA28059B71BB9F34067887ADE4C1CA4908B19B3D78123453876" "DB4DCEB42773069572CD8777E62CFBAF7203F020F281A6678F790720EAA20E34" "327D7A63688B09A01F4D7088F7B5059EDDEB45C0CE39321C79521D79A59ECDD4" "68CED0EA82CA484928702F57D6FC18D347AF3ED22AAF45ABB0F20BAB9E015576" "07AE3ED9CF0E26D34D305449669EC6FC1BECEADCE183F7A594CEA196D059A1E5" "50E547866CC087333F030E628F2CF1147925410ED0421DC7506138B1D19099C6" "95E1AFDACE4153825B66A8ECF55A021D21EB9F848FE55C21769A755FA9807EF7" "3A6C5BA15A06347D3F1C5C619A315598629106AC0B86AE0D8E55578292517258" "AE85F72E737AF5638D096B76A3C57F1B9C80E770A2D4EA4E42FE469AD4212852" "41960A8A86355EF22F583FE3BACADF8DA31D5C2DE254161BC6D10F9841DD27ED" "462A6B94B6DEEA90CBAB687FB84B56395DA763AB4B7FE3095D572D77EFF3FF0D" "8F9D19AA5AF7B676053DBEF64E61DD0A41D402318E3308669106259BF7A4CE31" "B346A9E983EDABA05180149AB057F9972977DA7C6F46E0CDF86F3091F04FD4E8" "3C6022E18CE4382B54D5DABA82E4DF1E53BF31FE4BB65A8524EDA83FD29D07E4" "9747B75291CBC8F8EE1415EC921E19022ADE2C047E4DF3507289E9D79A8E6992" "B48B8864204A416B769CC787D6DF4407E93D121F7FBEE0E408963E0609A9C75C" "B3117CA583DF6E79F31C635BF0F1BE98DF550727A45D3CA337D79DE5DCDB0B91" "CABBC30D7EF0AE1CA1E94904F78C1FD8FBA87545FDC174AD8190F9B5ED7B5869" "494FFA91033FDC6117BF662EC5F2AF2634BA3F8C02210F1C9BCDDA9BB39760E0" "0F25A7270C345666FB6DF85C919AA150CA7FC80FC0EACFE242EF55F429806362" "8E61056C966DB9964428D9CE99108271E29A12328E23999734E036F18A0EB8F0" "30E88062C56717E7A36314E44ECF357FF56EEDF90D3FB11B22A1B25905B379FC" "CA5CA1ACB956E178AD3F51D535AD119813B1E70F7317651BC75CAC64276BB981" "10B54EA0EF34541D73910721D657387677E332E9C8811C3FC1B923B2EE9C512F" "6D09DF372A5F97FAD7123389CEE197B5C269E221D7EED3160A521E56FF8AAFAB" "686179D09D78FC387B3EA6A672034D24AC7999D196B2316475F37DB8E9ED431D" "F58341FA88003D3C6489E78053D8E44CE7E16AEF416859B3D2AECE09086A748B" "7BCFD10F73E3CF8B31F0CC44DA059C69ABA5BC8EFAD45D3F376AF3A0DE6E1698" "78BD842E28798E4743F843844BCDF8506F136391EC8E721DC2B6282D9C50FAB6" "53A6ABF28947420E8C22A9A487D76A938933B34E497DA95394176B2774C09EF0" "BB1ED8C3B131A21957B31A0B47CBFBFF0533CAF33125221DB6BA4A518864892C" "F21D3D4D58B599A37A08F344AA7EF98E7D7D9D3316A6B115D9B8F20F93BC6865" "734699EB54C888D7E5A0ACAFD1915352B294243712CFE82F85248B00045CF3D0" "90C0C00D7CA0E3A1F147703FD94F717E49C81A7C3A76946E20A63F3B7C3EABA9" "225ABE0B34CB0CF235063967D16BC8A69C130CCE287615CC053114167EAC4E95" "BBABDFBBCF96BC0C0D65EA000AEAF490D723955BD1B4D69154D262F6A6D3534B" "B0BC397C29ECC6B1447B75C953AF441DE2E7133A7AC98988A7EF9E6EE63558AA" "ADA0603BD529776F05558D2DF5641C412E7347440F65EB823AFC7CCAE6B97108" "B857287A0486DBBE689D770CA92471309E73AD390ABF56912B2B7C49242CEC15" "7BDBBD493553735CB1D9B40AFC214DA153359C9DF576135901C2FDA58C0095B6" "FCE3FD0731DF34863AF2882D53773CE7C182473722AA79A6B37D3EDDDE38FA71" "DF8C0EDC081EFED8CE606E48299180EC6FE35FAB649910C48A6A29F9D0F85557" "E10BC5AE2ECF028AE399F55CD7976028935CC03C0CAFD5003C9EAED247FBE30A" "284CC4470A5525A6498E1DBBD3085C3F9D77C6064D0181BC5A829561560AA9A4" "EA8173D7937A9428109CB3A66B2B3DE11F88F55AB21EB49B77A39762CA9264E0" "156566765E2D3626B72B80BD1411E4EC53552828A24BC8CDC47F465FDDF4772C" "7BC02066854011287F739ABA6047596747F4234AE227DBFFABF0E13153E2E069" "F0B790251BE877FE5A198E808258639F5E79D3D5CD16F1A573724DD6A9F6990C" "4502334DC66F65493490673AB30DCA7C031F0C212C0D8BC9D0C874B319A97AD1" "CE9395D3D154203156C51CC3B9CB13D0BA1BDF618BC8EECA9DDD9412050CFA09" "235727AA50D46F79AD6F3C5A1BB6B284C8311DCF93756859704DF8FC3BB8D2F5" "E094E04502354942E9C852B208D4901834332EBC603270CB57ED418C34CE48A" "A"), /*message = */ absl::HexStringToBytes("D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835A" "D55B22E75BF57BB556AC8"), /*signature = */ absl::HexStringToBytes( "BBF85FFD0E01C80C8C1C1931CD640BF273D49693C4C4BFF5DD20D94CF3757ABD" "45473B9D01B1871305DA90EDC6707D5417129467F61F723950C1AEDF7055EC1D" "4777AD8808E8B347D1D0921EBAB890CCA8E3A0DFD3003DE9F9CB4A97D884E1DD" "042C958B816F7237032B20F8399A5182F46525EC357D2F03437403E0CB5DCA4A" "13FD2F1B09205B9890F02EE5AF542943E6F9375ED08A38533042D6BBD50F3725" "1B1590F63B4B58A7D1E1F31CE62E3D2AA91E1C767B9C3F5CB26823F97AD1D9FF" "AB2875EB68FFA9B09946EF1D7012C02919EF13CB100C2E2C7987A0A5785B5F3F" "3B948B7FD64B85B165AE2FBF3C47E039C3073CA78FC900BBCDC069FE906885D5" "B13740A223AF5254F98C1D58E2FC92B0373E2A933353CC3EECD39F71D59CFA09" "294E38262A4489400D222982F9C780CD0731D4EED916C5A31ABCD02A590ED8C6" "FFE18B5FC7B6888E74726940D02CCC62D78BCAEDDA2E028E535CDAFC0E091BEF" "50DE2DFD124F1E854F568527AEF4DC8455FDA01B6D0D43048ED5AB42B1D40813" "994B9F6AA0C036C0DCF08F46B00FDA014477CF879B8FE5EAC4541B82DA00B434" "6046865B092ED6AE0115FC834B58F75FF928D7D99AC8691FF70020ABA25480AB" "BCC709E46EC510F4B8CADD60045954D3EDDA7C23E03D91694D3C3EA292C92535" "E6B5FE171C567DF3729406CDBA2A5EFA59F156E9CCD0302FDC0F8BB759B05DFF" "5DD802CE4D5506A19A69D70B3AB48AB17A2FE59589F73083CCA547FFB3F14683" "C914BC1345E7387E831EE6037501495C92C357705A69F952A2F7CD30E03336AF" "AAFC9C56604CD545E82AA12AF058DABA974387FE8DCDEC699A1E3853E26D29E1" "578189AA8C2BBA1550DFBEDD1E4F224EFCD65491E54E56128AE7C2DC8566797A" "BF2D9455915203A5C89E55DD23DF827436A8D6DCC5ACA82F9B183692159EC03F" "2B798E557D147346D835A8D81B2E3D40863966863A54D9C87B5AACE963CD529A" "DBAE07070CEA00B780E18131E64F0AD70E9158F590D00AD9177908B90345FD79" "D0255771C608AF65EE5AC3C50166BAD057380258681941560F1133405FC2D761" "1314B4381D5459DCDEDE4D39F3823BC4422BB1D736E7474A8089F0ECFA3C30AA" "C119FFA42BF743F48E0FDD960292D3E49A14EB0590C8E02E421D54AE8A521951" "5E21895989A0D71D4F451669CD652DA3489E5CDBC0876BA0A0899E7D8773B24A" "FC2CD6D37CA380A5D0DD436304D6E1A4DCD638E8B95E6C95465C6690D4EFE8F4" "4691E48DE22CFC691C7561AD8CC1A2C3CC9FB86FF6F4705A573A720471ED33A0" "0E8A60203818A3961E4D213A78B8626394F75C282315574CCD725A67E20F0BF2" "24BFFCABD702BFD4E1CC5F78BEC0E042E12ED4C9474BDD5EED2AEB53F4A958D7" "F84EFD56EC030A94D200A539DE164E53C82AFE8C5F71BB99A01F7230B7AEBC21" "3ECDDBEF5B9E9064874396F8A91B0575F68A4515DD158178BF277A90A3FEA200" "9200DA2EDA2C8B3A47C104D350DF68E94C8A4023D3AEFBB70718FA2E27E6A5C3" "F9927EC596AB540F463AE010EF71B89B49497F0CFD2939FFAB2A7DD1247DC4A5" "9D8411A843BD84F1EA8DA33C0701D70AC27C4BDBD0D9A0CAB86B1FC5BE12458A" "2580A6CAB4B765B842C67AD54CA5D40A24E2DDBCF01E466E08D9B3449F13E82E" "16D61C723FB9462E97B7ABC70B2210ECA16B160D5B8F98A1794DCA92CD4F027F" "3E4152EA879507DDFE7F1F21514153F036AABC33F172C95A9B774722800F2E08" "CC44F923540D8AF64B429968B280364C1B7B4B3E9BEE40C50002657D994631F3" "3A8F8F134A27EB69BA4395908BA40634B8F2703149275FFBBE8B483EA1BBA91C" "28105136D97C470EE83CD21CEB2B21AAED98DB8AB165A7B4BE559E7EACA68460" "3015BC349B0A51214E4E8FBE1D2D883F79FD3F1EDCDD3FA6D4B5BBD2A5B3003A" "80F1DADE975B502C7F72037316BC55C1E57E500627D60E31087431D2C9D02CA9" "F0EBCCD4BFE3C4BB536D4CFEF7510750452D444BE2C3D64D84A832965305264A" "BB53E3614940F9B2F1EA6F41CA8F69E726690BA630630F8A916EE856268251B7" "73DC2A5DB45D22DFB2439CA4B7AB70215D23E1F2E2617394FF783B0BFF6DF034" "5CC927053D02C65FE2A86DEFBEBF5243A2EF6A6312BAEDB6E60DBB0C67CC9A65" "5585CB458D6A04181194815F03BE87F6E800492A24C5D502D5ECD53DD6DA3679" "95D32E8BBAA3EF62727E8A610E8D6B5C8FABCBE8893BDB5E038627F707E8464C" "55DCBB76F0836ADD298A967C459508BC4E88BA5CA38F5A561A6D2D6CB2178D90" "AC850CA2734B45C4A89AA0F152A3B53BCF1E13532B2B5B3878B205BD2B327DC4" "9EB6660B9511BFAE90C1DEA5BDEB6DC5DA068BCBDC6C093E5727E387374F452F" "963C307DEE865D41AA124CA803C12F9AE9299C3CB1345FCC568C6E71BE3366BF" "30EFEEEFC7693C36ACE576B0D10F402F380009FD0EC068CB2D45984884EDF16B" "C90B0FF6DC96309EA377A3CEC043CB76B6C885BBB848C4745B71E18C58E78050" "E19BD7BE0831EFE9052A6A7DF8D4E8B9FC3E082A4D40AD73E4B3185E2F6DEDE7" "EE51A4068FF2DA57373FD7E7BD46E0080F4C2C1F41BC250E6DA45A341F214771" "F5531A67B0FD97B53CD72CFAC7215BC4111F094030A91383D20182210FCECD75" "E59C4B0B33A3F93D865D847EC241E1B98481C5D9D27F0AE262B328650CDC13CD" "99866BE9A5A030E83D84E32BD213C94BD6AF950433A4F00C6149783B00750CDF" "D4F47AE75217EED1F60C366FA02CDB206FEB2A685D6B7D6A4C13553E2BE27794" "F53B0EF57315203263EB026EA5E67067D22F92E26E98DF9AB386C2705B4316A6" "9892688E601E7427595ACEE6E47F5EC598CC48C2F2DA1C32E062A349D89DCC8C" "05C62E7B0CED6F2E93A7BD48A8004A8C5C605DFFC805DE079EDEE7CED98639A9" "2F6CBA92F2089B145D2D61D9638C07347A2EF6B30FD90E111A7F5913F6E18795" "C19E0B9F60F85BD8F5C9A963339441E4A5B79EB2E867961B18A1884A01A74483" "D80B403EFBDBD4EDDDC1922DA3FBB37BEA97E0A5B6343E4367601BD21DB66941" "C2698BF506B04861B5F3D3D80AC6DCB684D9C4369ABD04BC4BDBEF49C66E3844" "513A3F3BDD400C080AC6EAD81E8BB0E7CB36DB7B7EAB4728391857F597A34648" "63C312645B20AF02F7D0BD9A74DE2361A0D2D98A698975B30F1010D90A126078" "584A45FFBCC65B47976AF657EA84E9730D9E363733736AC80103DC1C7573C4DE" "E28A7BAC9EF72CB829450B53EAF984CD01AA31416CE8914B7D7EF849EB9CC172" "D7096DEFDACF596B9B21A573E346A47A5A469E1D7939BE1982CB3954C214ED3A" "3707D740C033E3EF780F4C48BADD863848BBFC9DAA8E3806A84B2CAC0CA23200" "0CAF0203E908FCE18B5D62777225D2D7D584F2ED71885DFAF5A4DBEE02F285BC" "34559B88EA9CE15B47A3B92A8D6F91591C329A5AA21A1BC424BA2BDBD164CE1A" "8B78B38BEF2B47F21F7FB7A3C54E3EA4536E816E01656C8E26AD42F3CB906169" "67C0DD079F956C9F3C844D5F339C62EE8A358C4BEC2D278AF718AD509C6B6661" "3B580443FA6F11CD8D107693B5D7B738AA7E2FE662502D7504A9F596194180F8" "700DC4E6F7E8E7D2307234494B8DF1D57EE14D6C97926EB1D8904D8089BE7D13" "5B13D6DE30AA8720D67159BB50A834DE9079922B88931D458500626834DA040D" "B768DDDBE67A758A02B448E36BA455034ADE36802AA42A7F2F234A5E1CC241E5" "661C63AFCE59DFDCC0898347D2834D7264F5B21A47C5214ADC57AF76CE9EBDB6" "8C71029BCF0C4C745A33454ACF0CF6D5C68DEA06C45E7D4D1755C5ACDC37FC24" "34140EF707FD55FAF06CBB1707C27CE9D905905E37E2F147C9CB8808ECD05DF7" "1FC5F1DAF910D7BD68B6914938BF0CABCF66C905C49563D7D70F2C3D3A4A4F62" "9E3AFDE53BD14CD6E527E4F038D6A331D01468E22DFE93A379B3EC6DA6D1C2F6" "D5EAB141E575F93C8CC5580DF4A3DB5C4C87D8548E9A851946D1B90D7527407F" "1BA1121EAC54A11E6EDA45ABB08A7A78AB36A76EAD7FAC4678E52464EFF398E9" "0215AC316DE5A6EFE5A7B4A95DF92E4129F3F91B316F756708BDF37C01C12BBA" "A091F94884E38AFF3C7B8140888CAB4F7F867EADB0418584B6F770740250936A" "138AFF52888840677D8121C583806FE27104DE528813E56226B652C5869BB500" "303834D9C9D197DBA1DD5C4734307AB8BD006B66EF45ABED2E31377BEAA19DAE" "6EC82AD77C4C07744F9B93A8DD4CEE1A62A552EDF4E277CACFF1F964DA7AF8FA" "FF6B56E3EBC06850A9F76ECFB2C2BAA660958C6D1BA96BA8578D066D6AFE6E8F" "B2052B7421D57DE5AB4C1FD55170E9EE33EB32FB3D2C886142055EE8428BD745" "AABE1D15191FFC93A3FA7A86B427EB2370B78A67A485AF963BBE1F2246119FB4" "69A002D7029FC4F5F7E0125FDA7305ACF6C80C7BD3F668897BA81435F426B842" "5C9855CD46C3448BBAD0739BA88ABC273BCD0FA1FDA7F4F8183B5D73D16C407C" "452AEFA2E3CA9F2D9D638D966A58788B48BFC57D3FC2085FE85A7F7ADDD91EFD" "1BA0226046B127A97BC480479B92881A58A0BC04D8DD9E68B6D2BC5034CF2343" "0D1FE54991A6908B019EE018C843B9FA53EC7EE5F114ABE2B750D4E1E72EAFB4" "FBB33A1E2C4D6272CEE27BBB13B5D23E24F6129CF5825F34AFC056F95F53A09F" "6FCA9435CD5FB6C05F88B4DCE86CEABD7E0C785361D253BB9CDB3A0C6BC85183" "01FF44F9E87F7A97EC9F02FAB5134F3BBFA1CBE44FA83F1C543ED9B870657543" "5AC6A15F7B0DEBA9D45AF554BB0CCBCA12A6C16E5EE6FAD63721E4C3CC8D9EA6" "8C6149993080952407AFA203F504A887B3BF84D2BB6E45E7CC5326533D63963F" "FB72A9272C8FF637BE6E2473E9FCAB6B5E5E7CF3EDBDDAEF51C98D53170F9B64" "BCA5D49F76AF176D01A6F2ECB339151F49E49A8F6E286C6D4122D650D5015910" "FF7F28024693895C5803DDFFCB1EDC4679C8F535AC1597D9B28AC46E62888101" "29C179556AF7882DEE17D58A97F434DF83646B33CFBAB90A6250851CF53D4BDB" "4526337DCCB9D98A921676B51365DD08A5304D2A93534C52427E9AE5C1440592" "C5536E171CF4FD1F43578FEAFB32FF01D4FED635D752568F90ECFBB164A5B176" "3F70C72FD5BCDF61D01FF3236639C91C063C0B7A56AD03F4020E80BD9A5E2F16" "1E0578469B9950266BA96BBB73C08E7FAE856E1703CF3CBD21418089148F7A9F" "40D4D91151DBC4BAE8542359E882A19A9949CED5B75FF7B192DC279B3ED10076" "053F58DE435FC5875654E98633A397141142229D8CD613C66344326D83992B3C" "08F17BE0EC28FBDBABA12CB000B2A2B04E24D0C41BD6B580E999B257C007965C" "4475A9D5314CD6C1FB9FEDD516E6B3C0DDD404D68D78FD4DE40931B1B872D4D0" "1A2D46C9B293900D34EC91D3B693F4E72C228ED0294F6DC9B717260EBE75A471" "EA4D7800A3E7B7B476D64DEA6F4DA726B376F07800DB5F83C0A3DCC2C7026A4C" "378E880994885D6F7A8819D91A2D50D16D22BE592BED38330410E14CDDD4CE0C" "48D62B7797DE44C07F26A79EF3A5830F321A35AC507E943C6DE63FE136823225" "D6FC73D86D4C84399013E064E6683492907C7B78AEF2AAB180DC33E5E6BDBD6D" "490E3AA8BE8E82FA6CB13BEA360C510F9B4B5BA6640427ADDDF3D66DED41D1E2" "A06131E950136842732C273498D6A47CED4ED189B6E739361F68CCA0A99D5602" "B97655AB2682E837DBD688C173DD4950DD4CD4D3A338F3FCFF8C7116EBC630D0" "5AFAB8DF7C7560F4DE9AD92216268EE143A722C03497CE17EFE98F67580F0DDE" "F57F15255E68856D39A4EB338A653346FEDE46663A62307F6590E2EE7AB928AC" "5E8FA163AA74E40255D8D241668A1C717E3F28994350F49908A32E6FEC6206BD" "F7936DD2CF6A87B9994045552ACCE6EAF1294E7327A13E6EAC16221A676F605D" "6DA6365D0DB01135405013F874481A68330455281A41E83DF76D20D1DF75DFEC" "A0917F3E94BED22D1ECED8A9FC7B2A2E4A5B74D0B0C9282BD612A48648993F9F" "012BD70A0E43DC3D1C0A16711EBF6EA479DB941F68A6701B57F7B837B30C0A6D" "771123D6FC70BDBE24440CE4E254A070534F1C1813C516791260A73689DFE1BE" "AD6EBF6AFF7EE48DE1D59C62228B383E0ACA0690F805FEFDC54FC4F974BFACCD" "FE33216CD2BC06BA7C2F55D7A0708C48014FF0C535CD83D54708FD703E8EF510" "FA6072E25FDAEB9533D4806053076CB8E4FE6946FD1A670D1BDA92311D5ED5FA" "245FA74A6F04AE66E3C9E0A7182CFDB210E5A2F28C95439964742A987A162985" "DB91DF91D9529D8B850B8628A9C5C8455BDB417C927224A9A8FFCDFE00C228FA" "284C5052577098151E33787F8287CB0D2431324555848A8D9CDFE3E4F0F14261" "D0FBFC023C596C749EAEFB0A1784C8CFE5E7448A989FD8D94366B4C7D6FF0000" "0000000000000000000000070F1E232B32383E")}, {/*TEST Dilithium5*/ /*public_key= */ absl::HexStringToBytes( "1C0EE1111B08003F28E65E8B3BDEB037CF8F221DFCDAF5950EDB38D506D85BEF" "032369A2CE572FD08BFC304B4848E78D752D77E97A28B99B9BB6FB5C7C633751" "4B321ECDC1FB669F26D4171AB42B72720EE70E0519A6E1D3D6D9914EC1B21CDE" "38B41AAC1D3ABEE6F2B7495C4C820C1FC0CC9E71E24CFB5C9C0D8EEF4264AF48" "4FAE4D6E5DDE65D4DF72B61C6DBD26F861A5E0B853AC5413226FEBBABA5EB474" "C6FB25A82678EA1606B452A23112221017B8C073C10378F9145641A8C078C0ED" "9E421650F748892522AB9FB7D1FF8CF1CC71B8566E8DA33CD7361770C044349A" "C440CCCDC6BBE35E6C55782766F38E688BF47821037299E344ECDECA17AD5D15" "CD27A4F7B070661138EDE8ED72A8959C5AE36B1C46094A53CB21A7A42673F140" "1C2B259494090E2F53D7EE7063431EE5858002D850AF909C3783436010F7EA88" "625A36A0F0189FDE75B7E8C7E4B19D8527008328ADBC929BBC86E964CFC48B8C" "F1DA5D7ED3333AB55C15072832214A779A5FD10CC04005F46C1AA8884A161992" "472FD535B95ED18BDE1C6D8CE678D2817D69F90571103E8520E7313CE7B930C5" "EBFAF2F4EC758B626B5543A068CDE0FD0E94E6A64475B23268BF0380D075508F" "85128CA26F31A90C4A7D28440D54D4066B404588588B4CCF850B975C73AFE68C" "BCD102755F61EB3E60323C576E529EC0BF23BFA5BEA39CB73C37E8395D8DBD4C" "8DC8AB2F70A0BFC3A78C0D413F08D14D632BC0403B0383DBBB22BD9B113C8945" "2AEAB11210097947FEAAA3C9F05D1D300C33A55E3FBC81259E862705C3A13B9E" "E35F6B23ED10F4EDEA9519FA91B7BCD0D501B5ED57D9049FAB91AA779C725FF8" "E9F78017EA7807FA254B7105E826D096C01ADAE2C5D138251A92A478A33373F4" "DE912B83B6FB4B0D0DE6BC1118BB2FCFB07BD227A5F7F991439A13DE1238180C" "DC55119E65C418584D807A926E4A9C0F70155EE196FB07656D9AA7982B8795DB" "AD43D1059CA7F580D3320C0438A5ED5A7032B2E959678410F11AD98BE8826A44" "262615645D759A862B2AC52D3B014A25E8473F1F1EA4CFA819930AB3A34D710D" "EEE70CA13E88FD71AA064E6CB4697DE0E463B1370A6A3BFE98FDFE7B5471FF8D" "F6A6879FBEF9AFB3519D780757D67440AC36E837BAC3833EEAA980BD82B79364" "36A0307D164B6438869AE606E980518E913D0EE302396EF4EB25D9866E4BAFA1" "01E5992931361C4A982253D58ABE3BD57107635A46F09512085F4ADA08EC8B1B" "3910B0153B2AAFCAE5033EDD4153248DCD85B02C9A25D8BDC4068BB857417262" "97A25AEC55C44AA28059B71BB9F34067887ADE4C1CA4908B19B3D78123453876" "DB4DCEB42773069572CD8777E62CFBAF7203F020F281A6678F790720EAA20E34" "327D7A63688B09A01F4D7088F7B5059EDDEB45C0CE39321C79521D79A59ECDD4" "68CED0EA82CA484928702F57D6FC18D347AF3ED22AAF45ABB0F20BAB9E015576" "07AE3ED9CF0E26D34D305449669EC6FC1BECEADCE183F7A594CEA196D059A1E5" "50E547866CC087333F030E628F2CF1147925410ED0421DC7506138B1D19099C6" "95E1AFDACE4153825B66A8ECF55A021D21EB9F848FE55C21769A755FA9807EF7" "3A6C5BA15A06347D3F1C5C619A315598629106AC0B86AE0D8E55578292517258" "AE85F72E737AF5638D096B76A3C57F1B9C80E770A2D4EA4E42FE469AD4212852" "41960A8A86355EF22F583FE3BACADF8DA31D5C2DE254161BC6D10F9841DD27ED" "462A6B94B6DEEA90CBAB687FB84B56395DA763AB4B7FE3095D572D77EFF3FF0D" "8F9D19AA5AF7B676053DBEF64E61DD0A41D402318E3308669106259BF7A4CE31" "B346A9E983EDABA05180149AB057F9972977DA7C6F46E0CDF86F3091F04FD4E8" "3C6022E18CE4382B54D5DABA82E4DF1E53BF31FE4BB65A8524EDA83FD29D07E4" "9747B75291CBC8F8EE1415EC921E19022ADE2C047E4DF3507289E9D79A8E6992" "B48B8864204A416B769CC787D6DF4407E93D121F7FBEE0E408963E0609A9C75C" "B3117CA583DF6E79F31C635BF0F1BE98DF550727A45D3CA337D79DE5DCDB0B91" "CABBC30D7EF0AE1CA1E94904F78C1FD8FBA87545FDC174AD8190F9B5ED7B5869" "494FFA91033FDC6117BF662EC5F2AF2634BA3F8C02210F1C9BCDDA9BB39760E0" "0F25A7270C345666FB6DF85C919AA150CA7FC80FC0EACFE242EF55F429806362" "8E61056C966DB9964428D9CE99108271E29A12328E23999734E036F18A0EB8F0" "30E88062C56717E7A36314E44ECF357FF56EEDF90D3FB11B22A1B25905B379FC" "CA5CA1ACB956E178AD3F51D535AD119813B1E70F7317651BC75CAC64276BB981" "10B54EA0EF34541D73910721D657387677E332E9C8811C3FC1B923B2EE9C512F" "6D09DF372A5F97FAD7123389CEE197B5C269E221D7EED3160A521E56FF8AAFAB" "686179D09D78FC387B3EA6A672034D24AC7999D196B2316475F37DB8E9ED431D" "F58341FA88003D3C6489E78053D8E44CE7E16AEF416859B3D2AECE09086A748B" "7BCFD10F73E3CF8B31F0CC44DA059C69ABA5BC8EFAD45D3F376AF3A0DE6E1698" "78BD842E28798E4743F843844BCDF8506F136391EC8E721DC2B6282D9C50FAB6" "53A6ABF28947420E8C22A9A487D76A938933B34E497DA95394176B2774C09EF0" "BB1ED8C3B131A21957B31A0B47CBFBFF0533CAF33125221DB6BA4A518864892C" "F21D3D4D58B599A37A08F344AA7EF98E7D7D9D3316A6B115D9B8F20F93BC6865" "734699EB54C888D7E5A0ACAFD1915352B294243712CFE82F85248B00045CF3D0" "90C0C00D7CA0E3A1F147703FD94F717E49C81A7C3A76946E20A63F3B7C3EABA9" "225ABE0B34CB0CF235063967D16BC8A69C130CCE287615CC053114167EAC4E95" "BBABDFBBCF96BC0C0D65EA000AEAF490D723955BD1B4D69154D262F6A6D3534B" "B0BC397C29ECC6B1447B75C953AF441DE2E7133A7AC98988A7EF9E6EE63558AA" "ADA0603BD529776F05558D2DF5641C412E7347440F65EB823AFC7CCAE6B97108" "B857287A0486DBBE689D770CA92471309E73AD390ABF56912B2B7C49242CEC15" "7BDBBD493553735CB1D9B40AFC214DA153359C9DF576135901C2FDA58C0095B6" "FCE3FD0731DF34863AF2882D53773CE7C182473722AA79A6B37D3EDDDE38FA71" "DF8C0EDC081EFED8CE606E48299180EC6FE35FAB649910C48A6A29F9D0F85557" "E10BC5AE2ECF028AE399F55CD7976028935CC03C0CAFD5003C9EAED247FBE30A" "284CC4470A5525A6498E1DBBD3085C3F9D77C6064D0181BC5A829561560AA9A4" "EA8173D7937A9428109CB3A66B2B3DE11F88F55AB21EB49B77A39762CA9264E0" "156566765E2D3626B72B80BD1411E4EC53552828A24BC8CDC47F465FDDF4772C" "7BC02066854011287F739ABA6047596747F4234AE227DBFFABF0E13153E2E069" "F0B790251BE877FE5A198E808258639F5E79D3D5CD16F1A573724DD6A9F6990C" "4502334DC66F65493490673AB30DCA7C031F0C212C0D8BC9D0C874B319A97AD1" "CE9395D3D154203156C51CC3B9CB13D0BA1BDF618BC8EECA9DDD9412050CFA09" "235727AA50D46F79AD6F3C5A1BB6B284C8311DCF93756859704DF8FC3BB8D2F5" "E094E04502354942E9C852B208D4901834332EBC603270CB57ED418C34CE48A" "A"), /*message = */ absl::HexStringToBytes("D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835A" "D55B22E75BF57BB556AC8"), /*signature = */ absl::HexStringToBytes( "BBF85FFD0E01C80C8C1C1931CD640BF273D49693C4C4BFF5DD20D94CF3757ABD" "45473B9D01B1871305DA90EDC6707D5417129467F61F723950C1AEDF7055EC1D" "4777AD8808E8B347D1D0921EBAB890CCA8E3A0DFD3003DE9F9CB4A97D884E1DD" "042C958B816F7237032B20F8399A5182F46525EC357D2F03437403E0CB5DCA4A" "13FD2F1B09205B9890F02EE5AF542943E6F9375ED08A38533042D6BBD50F3725" "1B1590F63B4B58A7D1E1F31CE62E3D2AA91E1C767B9C3F5CB26823F97AD1D9FF" "AB2875EB68FFA9B09946EF1D7012C02919EF13CB100C2E2C7987A0A5785B5F3F" "3B948B7FD64B85B165AE2FBF3C47E039C3073CA78FC900BBCDC069FE906885D5" "B13740A223AF5254F98C1D58E2FC92B0373E2A933353CC3EECD39F71D59CFA09" "294E38262A4489400D222982F9C780CD0731D4EED916C5A31ABCD02A590ED8C6" "FFE18B5FC7B6888E74726940D02CCC62D78BCAEDDA2E028E535CDAFC0E091BEF" "50DE2DFD124F1E854F568527AEF4DC8455FDA01B6D0D43048ED5AB42B1D40813" "994B9F6AA0C036C0DCF08F46B00FDA014477CF879B8FE5EAC4541B82DA00B434" "6046865B092ED6AE0115FC834B58F75FF928D7D99AC8691FF70020ABA25480AB" "BCC709E46EC510F4B8CADD60045954D3EDDA7C23E03D91694D3C3EA292C92535" "E6B5FE171C567DF3729406CDBA2A5EFA59F156E9CCD0302FDC0F8BB759B05DFF" "5DD802CE4D5506A19A69D70B3AB48AB17A2FE59589F73083CCA547FFB3F14683" "C914BC1345E7387E831EE6037501495C92C357705A69F952A2F7CD30E03336AF" "AAFC9C56604CD545E82AA12AF058DABA974387FE8DCDEC699A1E3853E26D29E1" "578189AA8C2BBA1550DFBEDD1E4F224EFCD65491E54E56128AE7C2DC8566797A" "BF2D9455915203A5C89E55DD23DF827436A8D6DCC5ACA82F9B183692159EC03F" "2B798E557D147346D835A8D81B2E3D40863966863A54D9C87B5AACE963CD529A" "DBAE07070CEA00B780E18131E64F0AD70E9158F590D00AD9177908B90345FD79" "D0255771C608AF65EE5AC3C50166BAD057380258681941560F1133405FC2D761" "1314B4381D5459DCDEDE4D39F3823BC4422BB1D736E7474A8089F0ECFA3C30AA" "C119FFA42BF743F48E0FDD960292D3E49A14EB0590C8E02E421D54AE8A521951" "5E21895989A0D71D4F451669CD652DA3489E5CDBC0876BA0A0899E7D8773B24A" "FC2CD6D37CA380A5D0DD436304D6E1A4DCD638E8B95E6C95465C6690D4EFE8F4" "4691E48DE22CFC691C7561AD8CC1A2C3CC9FB86FF6F4705A573A720471ED33A0" "0E8A60203818A3961E4D213A78B8626394F75C282315574CCD725A67E20F0BF2" "24BFFCABD702BFD4E1CC5F78BEC0E042E12ED4C9474BDD5EED2AEB53F4A958D7" "F84EFD56EC030A94D200A539DE164E53C82AFE8C5F71BB99A01F7230B7AEBC21" "3ECDDBEF5B9E9064874396F8A91B0575F68A4515DD158178BF277A90A3FEA200" "9200DA2EDA2C8B3A47C104D350DF68E94C8A4023D3AEFBB70718FA2E27E6A5C3" "F9927EC596AB540F463AE010EF71B89B49497F0CFD2939FFAB2A7DD1247DC4A5" "9D8411A843BD84F1EA8DA33C0701D70AC27C4BDBD0D9A0CAB86B1FC5BE12458A" "2580A6CAB4B765B842C67AD54CA5D40A24E2DDBCF01E466E08D9B3449F13E82E" "16D61C723FB9462E97B7ABC70B2210ECA16B160D5B8F98A1794DCA92CD4F027F" "3E4152EA879507DDFE7F1F21514153F036AABC33F172C95A9B774722800F2E08" "CC44F923540D8AF64B429968B280364C1B7B4B3E9BEE40C50002657D994631F3" "3A8F8F134A27EB69BA4395908BA40634B8F2703149275FFBBE8B483EA1BBA91C" "28105136D97C470EE83CD21CEB2B21AAED98DB8AB165A7B4BE559E7EACA68460" "3015BC349B0A51214E4E8FBE1D2D883F79FD3F1EDCDD3FA6D4B5BBD2A5B3003A" "80F1DADE975B502C7F72037316BC55C1E57E500627D60E31087431D2C9D02CA9" "F0EBCCD4BFE3C4BB536D4CFEF7510750452D444BE2C3D64D84A832965305264A" "BB53E3614940F9B2F1EA6F41CA8F69E726690BA630630F8A916EE856268251B7" "73DC2A5DB45D22DFB2439CA4B7AB70215D23E1F2E2617394FF783B0BFF6DF034" "5CC927053D02C65FE2A86DEFBEBF5243A2EF6A6312BAEDB6E60DBB0C67CC9A65" "5585CB458D6A04181194815F03BE87F6E800492A24C5D502D5ECD53DD6DA3679" "95D32E8BBAA3EF62727E8A610E8D6B5C8FABCBE8893BDB5E038627F707E8464C" "55DCBB76F0836ADD298A967C459508BC4E88BA5CA38F5A561A6D2D6CB2178D90" "AC850CA2734B45C4A89AA0F152A3B53BCF1E13532B2B5B3878B205BD2B327DC4" "9EB6660B9511BFAE90C1DEA5BDEB6DC5DA068BCBDC6C093E5727E387374F452F" "963C307DEE865D41AA124CA803C12F9AE9299C3CB1345FCC568C6E71BE3366BF" "30EFEEEFC7693C36ACE576B0D10F402F380009FD0EC068CB2D45984884EDF16B" "C90B0FF6DC96309EA377A3CEC043CB76B6C885BBB848C4745B71E18C58E78050" "E19BD7BE0831EFE9052A6A7DF8D4E8B9FC3E082A4D40AD73E4B3185E2F6DEDE7" "EE51A4068FF2DA57373FD7E7BD46E0080F4C2C1F41BC250E6DA45A341F214771" "F5531A67B0FD97B53CD72CFAC7215BC4111F094030A91383D20182210FCECD75" "E59C4B0B33A3F93D865D847EC241E1B98481C5D9D27F0AE262B328650CDC13CD" "99866BE9A5A030E83D84E32BD213C94BD6AF950433A4F00C6149783B00750CDF" "D4F47AE75217EED1F60C366FA02CDB206FEB2A685D6B7D6A4C13553E2BE27794" "F53B0EF57315203263EB026EA5E67067D22F92E26E98DF9AB386C2705B4316A6" "9892688E601E7427595ACEE6E47F5EC598CC48C2F2DA1C32E062A349D89DCC8C" "05C62E7B0CED6F2E93A7BD48A8004A8C5C605DFFC805DE079EDEE7CED98639A9" "2F6CBA92F2089B145D2D61D9638C07347A2EF6B30FD90E111A7F5913F6E18795" "C19E0B9F60F85BD8F5C9A963339441E4A5B79EB2E867961B18A1884A01A74483" "D80B403EFBDBD4EDDDC1922DA3FBB37BEA97E0A5B6343E4367601BD21DB66941" "C2698BF506B04861B5F3D3D80AC6DCB684D9C4369ABD04BC4BDBEF49C66E3844" "513A3F3BDD400C080AC6EAD81E8BB0E7CB36DB7B7EAB4728391857F597A34648" "63C312645B20AF02F7D0BD9A74DE2361A0D2D98A698975B30F1010D90A126078" "584A45FFBCC65B47976AF657EA84E9730D9E363733736AC80103DC1C7573C4DE" "E28A7BAC9EF72CB829450B53EAF984CD01AA31416CE8914B7D7EF849EB9CC172" "D7096DEFDACF596B9B21A573E346A47A5A469E1D7939BE1982CB3954C214ED3A" "3707D740C033E3EF780F4C48BADD863848BBFC9DAA8E3806A84B2CAC0CA23200" "0CAF0203E908FCE18B5D62777225D2D7D584F2ED71885DFAF5A4DBEE02F285BC" "34559B88EA9CE15B47A3B92A8D6F91591C329A5AA21A1BC424BA2BDBD164CE1A" "8B78B38BEF2B47F21F7FB7A3C54E3EA4536E816E01656C8E26AD42F3CB906169" "67C0DD079F956C9F3C844D5F339C62EE8A358C4BEC2D278AF718AD509C6B6661" "3B580443FA6F11CD8D107693B5D7B738AA7E2FE662502D7504A9F596194180F8" "700DC4E6F7E8E7D2307234494B8DF1D57EE14D6C97926EB1D8904D8089BE7D13" "5B13D6DE30AA8720D67159BB50A834DE9079922B88931D458500626834DA040D" "B768DDDBE67A758A02B448E36BA455034ADE36802AA42A7F2F234A5E1CC241E5" "661C63AFCE59DFDCC0898347D2834D7264F5B21A47C5214ADC57AF76CE9EBDB6" "8C71029BCF0C4C745A33454ACF0CF6D5C68DEA06C45E7D4D1755C5ACDC37FC24" "34140EF707FD55FAF06CBB1707C27CE9D905905E37E2F147C9CB8808ECD05DF7" "1FC5F1DAF910D7BD68B6914938BF0CABCF66C905C49563D7D70F2C3D3A4A4F62" "9E3AFDE53BD14CD6E527E4F038D6A331D01468E22DFE93A379B3EC6DA6D1C2F6" "D5EAB141E575F93C8CC5580DF4A3DB5C4C87D8548E9A851946D1B90D7527407F" "1BA1121EAC54A11E6EDA45ABB08A7A78AB36A76EAD7FAC4678E52464EFF398E9" "0215AC316DE5A6EFE5A7B4A95DF92E4129F3F91B316F756708BDF37C01C12BBA" "A091F94884E38AFF3C7B8140888CAB4F7F867EADB0418584B6F770740250936A" "138AFF52888840677D8121C583806FE27104DE528813E56226B652C5869BB500" "303834D9C9D197DBA1DD5C4734307AB8BD006B66EF45ABED2E31377BEAA19DAE" "6EC82AD77C4C07744F9B93A8DD4CEE1A62A552EDF4E277CACFF1F964DA7AF8FA" "FF6B56E3EBC06850A9F76ECFB2C2BAA660958C6D1BA96BA8578D066D6AFE6E8F" "B2052B7421D57DE5AB4C1FD55170E9EE33EB32FB3D2C886142055EE8428BD745" "AABE1D15191FFC93A3FA7A86B427EB2370B78A67A485AF963BBE1F2246119FB4" "69A002D7029FC4F5F7E0125FDA7305ACF6C80C7BD3F668897BA81435F426B842" "5C9855CD46C3448BBAD0739BA88ABC273BCD0FA1FDA7F4F8183B5D73D16C407C" "452AEFA2E3CA9F2D9D638D966A58788B48BFC57D3FC2085FE85A7F7ADDD91EFD" "1BA0226046B127A97BC480479B92881A58A0BC04D8DD9E68B6D2BC5034CF2343" "0D1FE54991A6908B019EE018C843B9FA53EC7EE5F114ABE2B750D4E1E72EAFB4" "FBB33A1E2C4D6272CEE27BBB13B5D23E24F6129CF5825F34AFC056F95F53A09F" "6FCA9435CD5FB6C05F88B4DCE86CEABD7E0C785361D253BB9CDB3A0C6BC85183" "01FF44F9E87F7A97EC9F02FAB5134F3BBFA1CBE44FA83F1C543ED9B870657543" "5AC6A15F7B0DEBA9D45AF554BB0CCBCA12A6C16E5EE6FAD63721E4C3CC8D9EA6" "8C6149993080952407AFA203F504A887B3BF84D2BB6E45E7CC5326533D63963F" "FB72A9272C8FF637BE6E2473E9FCAB6B5E5E7CF3EDBDDAEF51C98D53170F9B64" "BCA5D49F76AF176D01A6F2ECB339151F49E49A8F6E286C6D4122D650D5015910" "FF7F28024693895C5803DDFFCB1EDC4679C8F535AC1597D9B28AC46E62888101" "29C179556AF7882DEE17D58A97F434DF83646B33CFBAB90A6250851CF53D4BDB" "4526337DCCB9D98A921676B51365DD08A5304D2A93534C52427E9AE5C1440592" "C5536E171CF4FD1F43578FEAFB32FF01D4FED635D752568F90ECFBB164A5B176" "3F70C72FD5BCDF61D01FF3236639C91C063C0B7A56AD03F4020E80BD9A5E2F16" "1E0578469B9950266BA96BBB73C08E7FAE856E1703CF3CBD21418089148F7A9F" "40D4D91151DBC4BAE8542359E882A19A9949CED5B75FF7B192DC279B3ED10076" "053F58DE435FC5875654E98633A397141142229D8CD613C66344326D83992B3C" "08F17BE0EC28FBDBABA12CB000B2A2B04E24D0C41BD6B580E999B257C007965C" "4475A9D5314CD6C1FB9FEDD516E6B3C0DDD404D68D78FD4DE40931B1B872D4D0" "1A2D46C9B293900D34EC91D3B693F4E72C228ED0294F6DC9B717260EBE75A471" "EA4D7800A3E7B7B476D64DEA6F4DA726B376F07800DB5F83C0A3DCC2C7026A4C" "378E880994885D6F7A8819D91A2D50D16D22BE592BED38330410E14CDDD4CE0C" "48D62B7797DE44C07F26A79EF3A5830F321A35AC507E943C6DE63FE136823225" "D6FC73D86D4C84399013E064E6683492907C7B78AEF2AAB180DC33E5E6BDBD6D" "490E3AA8BE8E82FA6CB13BEA360C510F9B4B5BA6640427ADDDF3D66DED41D1E2" "A06131E950136842732C273498D6A47CED4ED189B6E739361F68CCA0A99D5602" "B97655AB2682E837DBD688C173DD4950DD4CD4D3A338F3FCFF8C7116EBC630D0" "5AFAB8DF7C7560F4DE9AD92216268EE143A722C03497CE17EFE98F67580F0DDE" "F57F15255E68856D39A4EB338A653346FEDE46663A62307F6590E2EE7AB928AC" "5E8FA163AA74E40255D8D241668A1C717E3F28994350F49908A32E6FEC6206BD" "F7936DD2CF6A87B9994045552ACCE6EAF1294E7327A13E6EAC16221A676F605D" "6DA6365D0DB01135405013F874481A68330455281A41E83DF76D20D1DF75DFEC" "A0917F3E94BED22D1ECED8A9FC7B2A2E4A5B74D0B0C9282BD612A48648993F9F" "012BD70A0E43DC3D1C0A16711EBF6EA479DB941F68A6701B57F7B837B30C0A6D" "771123D6FC70BDBE24440CE4E254A070534F1C1813C516791260A73689DFE1BE" "AD6EBF6AFF7EE48DE1D59C62228B383E0ACA0690F805FEFDC54FC4F974BFACCD" "FE33216CD2BC06BA7C2F55D7A0708C48014FF0C535CD83D54708FD703E8EF510" "FA6072E25FDAEB9533D4806053076CB8E4FE6946FD1A670D1BDA92311D5ED5FA" "245FA74A6F04AE66E3C9E0A7182CFDB210E5A2F28C95439964742A987A162985" "DB91DF91D9529D8B850B8628A9C5C8455BDB417C927224A9A8FFCDFE00C228FA" "284C5052577098151E33787F8287CB0D2431324555848A8D9CDFE3E4F0F14261" "D0FBFC023C596C749EAEFB0A1784C8CFE5E7448A989FD8D94366B4C7D6FF0000" "0000000000000000000000070F1E232B32383E")}, }; for (const TestVector& v : dilithium_vectors) { // Create a new verifier. absl::StatusOr> verifier = DilithiumAvx2Verify::New(*DilithiumPublicKeyPqclean::NewPublicKey( v.public_key, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE)); ASSERT_THAT(verifier, IsOk()); // Verify signature. Status status = (*verifier)->Verify(v.signature, v.message); EXPECT_THAT(status, IsOk()); } } TEST(DilithiumAvx2VerifyTest, AesVectors) { TestVector dilithium_aes_vectors[] = { { /*TEST Dilithium2 AES*/ /*public_key= */ absl::HexStringToBytes( "1C0EE1111B08003F28E65E8B3BDEB037CF8F221DFCDAF5950EDB38D506D85BEF" "7E0188CEFDBAB31CF94FABE34E3C383EFCA7FA815D2C70826B1A046818E2A05F" "16B29C1C0BBBFC5707BB7051262FD0A2E34B7107D4619C54FE277549DBC23ED5" "75FB86BF077464CEC3394F2620FA11DDDABB793A9EDD03E66760E98D145234B1" "E8E66E1EB1FFBE34D368617BD99C01AFF2445A27B364ABDDCCD4CCF7CA3EFCB5" "7F5FF27C88AF9EA999C25EC73D1584E11C38898A77308D03097CD4AADE9C5FEB" "D06976E85558798084325BAA98F1C7F7BB8F39FB8B5BC8C14C48D88B8E600D23" "A17F2E342B6AF7DF689B74593DD3D6A8780D88895576526642ACE1C13636BCBB" "BAB8C7837BF10D59AEC63FA8DA5F24DE87190E5224DDE315B86E83A4E2647ECB" "674F51C85DBA38D6C585E61484942DB8C5407D87B8BDD4BB81E6BD2FC88DC6F0" "DFC3B0868B74E1FB36B3D39D0C5478273BEDB1B63AAED9342DF9527535B76C02" "1FB26B994C18B45E1EC91717A34FD2714D39FEBE73CC4A95B17D7CAA8F19A005" "91A3AA7249B084178BFF5A0F95B0E09D04D17021AF73DB6E3CD328492C0308F8" "EF8C50BD3E7C1AD22274DAD26626A21E606AF3F513D1E465AC526593450E1D3E" "02EBBBE48A5D053926E48D15B5F105E1952263A8C8F14C588598BBA82B1CDCB3" "E4E5D1F7D9E811F90F5D899C61F700B56D3B6571FE97E1CAE97B42EC0C4D33FE" "91B4EB518879677FABF02B369D7920AF961B3059683E9275498EC7D574E4C2BD" "CC35EA1C731B151F30188930DBEFDB25DC7A4C6622929D69AFCF67E6493F6F73" "0AD61F86B490936B0CDDC274353A26A69F471EF5B08837356167A9BB9835EBA1" "778B5DF38AE2CE7FFD0817BCD868A758584CD6175A1C48E3F380B7CFB385E585" "35597C6FC0412653F5DBA4BB3996543FEC8EBA277C7481AC0C7D5B7036213A90" "6A65B76DB7F1602C06CD792EEEBD001353CE82DCD9731773B55BB712E3F1C156" "9454903E87ECE65110BE634F6BD5E8622EED535824781C921B3D242AEF8B6867" "84BB870D8866593FC4B9287A5387C3D4AB6E4FFF4752C4CE3B5ED895E7F914F7" "8A25819BD5A3CB909A72D192A77BDDC5CE15137C28FB7FACBF06070A68BC11A8" "95F5D45832A11F81651F720B1FAA979FE7F375DCB11D240F1004E52FDCC07791" "D66C7AAB16BE58AB0A5BEF8425B45D9F9804FCDC83334ECD459DCDCE4EF51092" "A57314F249BFD7B2A11EFB2AC2C83E4F9453880AF8B19323F292D978B4C0EDE2" "D2C78E4A96BF8E6B6F4E4F519F226C9B634E9335C52290119F57B81577BC756F" "3146A056114DC877509F9DA9ADB614278D09284F8746D54420E2373F74AC06FD" "69B6DD4322273337360582661AF26060ECCFA680AA4AB56A5715E169F6202094" "3FDB1509A029A0514C028535EC4413E78A335680F59A078F279768D55B67FC21" "76CAE7AD4CF66765FC3C84FEE0010267747AE8CFDEAB4E47F280ADE944C102A0" "487F5FC2C1A7C81BAF61C574CADC911808E427D99339E54B2CB7CDB673209B8C" "6453EC879202DAB26221CA1C7F4C42D8823E8795E73904A9CB8F154B04D7B621" "B90880542BE50006CEFCB58442F02F92B4FCBBA4EAD0FF87673F4B8BC8160353" "41DCB4B260B93F9C4C6A650AEF7A5BFBECC0A5E5BECDF8AB8F6C42C5DEA1003A" "66386CFE8163229A973FBDEBB589FAA4CA291B2C4CFB095B18F03A7876F87854" "6DBE6D5D75FC6CB2741D3902346F182A1FE400D443256C92EB26B7840EB5FA4B" "CF67C1566E34E868A4F26CB33DA4C4E6904EC3DE60256077B2D0D742B942C738" "2A8214FF519EC3C2C61E841D7860975A2112AFAB01FEC4A221CAD2CD07A742A" "2"), /*message = */ absl::HexStringToBytes("D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835A" "D55B22E75BF57BB556AC8"), /*signature = */ absl::HexStringToBytes( "EB5742B00BD29D1365DE0E434DA8A154B0D939088507EABF21C68FF30BAEA9F0" "E6FEB469B6D4F14FCFA520ED2233A54778CE4FACF32A82593F741C3F1351DC21" "248C06F0688F3566AE473B0602E20DFD336FCDEEB016206C1F3AE2639466F143" "76391C675CF50839FE2C29C3D159BF45413CB9119B7626FE5D4365D7A910D579" "FACCFF17CFF7959FA9DF0E73C3DAECF1892E7C5A19F009A19186A99D2864E951" "6E50FF8703E10BC320C976AA76E43064C88FA5AE0342FEBD206B3D365667CEDD" "C8301C80FD5E0FBB344256907A4634F7C28DF75B6B8C959A9F659584A5E0B1EE" "70C2AA757EE84D878E52992D01EF38D77625CD9544B8281958EC99AC5C735506" "BEA736BB9FD82CCFF5B3FA30BDC61EB6FB16C6729A0657E4DEDA0CC7841E11E0" "5087DF7724A6FCAA8C9F538662FF043C54FFBDC4DCE9F76CF07DB4A2DFF1D1E0" "63D94C71730F0AAABFC67F8E97DBBA4714F84948F4B8E85BFD9B745833B3490C" "5B4FD166B2A128E8843A2C9D3D852599BDC7C365990EC971C4F1D2B1E7E34686" "66FBB7D2CCC31FC1B64D0E97BEFDBE7FD3F47318C3DFD70A9B3A0506CAE57623" "E77E2953E62DFDBD1EC81C63EAA41C58E835206914C5A60884EB0A4DA40F9542" "582FCEB8E5400EDE7C75ABDD0C97DE2C1842AF5D5C667CF49F8C459529EB0CDF" "D2F8F29570D637AE6F1B87B929D9D0C394C7D18C32E3179B4F089C0B2D31DE59" "0E32A06DE6EFE438246864729FE67739BAB47429F23A460BE5E3584432A3CCB7" "39619CF750405157C405C3C8F18C7BD351F3A31F7CB3442BC8ABAF8D1BD7EE2C" "299F12A80A5BAC18FCB3A35E4D908AEFD35E4EC283749960333DA17B670FB434" "D4519CB3A89FCCEE6D9DAA514C4033D44DE0B44BC2313FCC0D971C84798CEC07" "786B9788305950C776D3FA28045E795CE83C9BEE884B4DA3C9C52DBEC6C918DB" "E2925CEEB303D8A9BCF82280EF93487E6F11BF5427274A39D0AEC18A97AA8220" "E32A88DD0FF84A762D08674408197BB33D79F489CBA1EF67EE978E78B7C96720" "E44CE9C63146739311E752671D14529F616EF55B9375DBF5D4065428BD38FEF2" "E348AD8660F7D1A89DF1B4E997D1D9F7A1A3C920D3CDB86279E823F9640D5A0D" "A87C72257F1B147A881FD6E878EB1196C7A2DE7602D21D69055C927BC593CBA3" "80687CE2CA0B7E40EB175C02409282318363D36AC8009306D913758204F394DE" "0D5B49FE7882B3665BEDFF8B6B49AA1A7B26E5CAE27E6A0FCA4986468703B2D3" "2675B3812F59B7E6DCCCE73CAAAF7FE503B766AD05D5B2E5DBC77999B6927158" "90AFF83BFD63205A42A59F6EE3BC13C13E3A53C4130D0FE1024F871C1C149AB6" "DD715EF9BD810237EB0FDCC21645BDF31CE91D324F76E7CFD7F09B0506CBAFF3" "7BE519FBE9C8AC7C44AB78382BCBB2AA303C662BBDAAF8C3B8EA07BCD5EE1EC1" "A57356BE728FEBBD4463502AC998832A3CA40BA5B64F1A2D020BF350017DBEEF" "E43C292CCC13E8B44FF8D929BE6C5B9517FA9EED7259C7C87EA63D54E3F61789" "08CC80EB036B0D0FCD9398CC194B21E45A0E0A9AFF15D2EE81B497BD55DE0B60" "8DC5CF278AEE096D241C73C7385D2087F4B86DD890538F37A297E41A0E7F2F97" "917FBBF369E36EB0A4C12733A8473C7636393FDAF40932E3DD02B67A3A3A838F" "93D1EA0DBBC6D6685C5E82DC2B91D86FBDA077CA826FF515383768F4D03A7BDC" "41F4F91695C01C02666B4134C51EE1F6E6F8283E336D2CCC41154A23211F9DB0" "6530A3707095A4F21F2D3E423B5D059A8DF17E62E84DB880477F0E6A7CA063B5" "2AD819FE9F11D4822467EA80272BBA5A56608FF5748EE521876F89EEF035EB83" "B092E7CDA8329850BCBC323583AE31D9FE5725B8ADCFEB41EE8297ED7D84EF47" "E76B7193891572DE286F1630FB03A93262DE3E893949B0671E7343DADB408E2E" "76793F53AF0346581D41D12CEFA435B9EBAB31134811A237DC0E815B5925C664" "9E6D51AFC7DC9F3416F3A84C1A440D82753D54BF17AC51DD047C3F90B3455D4E" "31B9DF9E41E99F26800FBDDEC1F62777CBA1ED83F15D1E807F4DC638EAC9AD86" "CAE3BF25AB460EEF4E55C37C2225C3BA2FE12D8ADFFAF06488FB839369407ABF" "DDA75DA47446414B76522011EA4084C521DC423FDA10EEDCB864383517936DBA" "DBA395433E4AD4ABBAC6E58F3586BA22908AD9984673B540BA45F01AE9F1CB83" "4B6EA8E56E4280036F7FE9E61C5BA2AABAD0161BE181D1CFBAC87BFA2AF311D1" "14812894C8E92A7243C37C1E3DCBAD00F536DBAEA1156D0062C1265450B005BC" "1C20C637CDDD7378EA4CC08771AE4D5F86A43518B660FDBB93DEBA344026405C" "5BE26FF5F62AA491C5A9593C11FAE4191AF7BAD9044E60D426598A9CF42BD88F" "90A2DDFA8F51E45FB593054680A4871D8A6886D978D82D0F715905E80837D843" "0CE568DD7D70D055EAF6F36DA9335905D4EFBB9CFA2250F61992B162623150AB" "C0F151A55FBB0A9564CAADB134D0619854EA664985B02ABF8A76F7B9A15C95D0" "190FD709226EC0684E804F6E7B5A9CCABF99790232F60132FDBB29024F8B4FE4" "CA7C7234F10B58133098DA1CB0EB456363DE9C9F2D0A3EB3851855A50ADC06FE" "5C4FA08084B2B5056F9DAB5B5107397CF52F98C1AEB5CC62BC53C47F0F1E6F90" "7224C384EDFCE3382D00E04394678564E6914C46848BDE4ECE80394D494D484A" "C4454D06F3188F24001B7CB605BF525CAC0B1B8B1D80B4481D3373828C6C5DAF" "1599EF7C47FB9AF4F790749FB5330AF057C1A9A38B493C2451719D239037009E" "4D09738F07BB4DBFE2093279338F5D2C2524988EF5FB9B3BA864D520A5196681" "57847791960EC557076E628E92A81E7BE0D3D0F5310348BA0ADEA97FE9E6FD5B" "264B31CC1068FF8516A6157E1440AE2DAD72DB883E3FBFCEBA66A595461A9CD4" "BCABB8EB629E0A8ECCF011B30F90FE2EEF622A8C9BD30AFBBAE92EEFE075BB47" "CA020CB1B7309B7B1E46D8999B3A8EAB58A5CD7C79FD287E78EDDB5602C17972" "BD417073D78355E0C83BC0315847D348C7A61054688AA0E633331900F08DC24C" "B324ABCC29A8ADB18F6B2AA74EA5E6E506F5AD4E870DE2B965682D7503368F2E" "971781B5E63FB68507D6781837E91E0C880E094732B65F08DEC61813DE64A626" "9EC0557D3A00611F5D1C9BE130DE092C80E603EEBFCECA6343819CA7FAC59A95" "14691A7376F026C226B345CAF856F04B9A704388F223DE421D95EDD2EC184B94" "582D8A97798FC2E14B6493679A2BBAD860DE418460114E8F218F989CC638A10D" "22284A546C7A7B858C91A4ACBDC0C5D2FD132C3E4B85AEB2BFC0C8D5DBE9ED03" "13181E283944516C7A8596A2A8AAB2DEE1E2E3E5F41F2021263F545D65676F74" "99A2A7B4BFCAD2EDFD00000000000000111F3549"), }, { /*TEST Dilithium3 AES*/ /*public_key= */ absl::HexStringToBytes( "1C0EE1111B08003F28E65E8B3BDEB037CF8F221DFCDAF5950EDB38D506D85BEF" "939D474DC88E95C73766FD2228B27F4DCFFADFB35D22DCB8050237E977399E52" "E32C9939AEA889B14201AB02A2C4ED8DA6143693A7A6F0E4ACC419C16E5A1B5B" "A0DA078BB888CD4929052D096BF6C444847152CE38959B2DE2372834D59CF4E0" "2942692F97E68401C03B23288A53B9292CC0D0487A356C5B0B0F1399114F4D3D" "25D8C30AF7E528FE62FF0FDD42B5835C59E7F30EF9B56843DC289DD83677D810" "0E2950A86338D1187A6B241CDA7F414808E0266425F4E4278FD1D63194FD531A" "D8994CD2810CDC9F5EA830B3A876BE6D61719B7AD574BC248FEB3D0BE101CB9D" "5218CD474C2063F35459989981B7924EC49646520C16948D2D825F54FB3A99E2" "5129E7943D853CCFFAF6E34B6CD9C6D169D18DFEDC1B226B0FC5A889F291E03D" "782E5CA36257EACC9848BE58C146A81AF8B05B446EB8DFA31A1D99FD1D365E29" "C99C3C669D6348F76474344396995E0618F80CAD1DFCD90299B30B3DBCDD0C2A" "FE678910013649B6B5F03EE50E7A1D6E7115081DF6E822E711783DD383A93A5D" "BE3D223D854F617915FFC89327C616BB0ED65437F0200CEF72EBADDB3E26F9AD" "BAE75F656809847CE4BDDC4931BA09081F884E427ED7C8117CAB12B86AC52D6C" "9D2C54DB8475B2FBF49931C32CA65122ACD3A54EA57B2FE3B8CCB472F66B871A" "D9895A0BD1C71A8232A8327897DA9C848A57ADCCA587B508091E5FAC044BF0A7" "B7F8F98B5EF9C72CC488F290F059C44C32DA22DC941DAD863242AFAB941A003E" "90AE65DD6C27D8DD84F85C9538DF407EE40430AC86C67BB67B8B694730CA3B9A" "D4E0A3EBAEBF221207FC2650957D0E041E68602C2246AD646D32565AD0863465" "11E466FEE7C18934D2C87E49239EC4643B0211203E97F60D13876FB5CB5DC61A" "9156C1AB90DC3A70CD0EBB5757B4F601201C694FBC55DCE12A6033A59B373457" "01121A71B233CEBE7F229E10DDDEDCAD61A0AA713F45F48ACBE4FD9EFA88B119" "8DA00C030A6C662E85E0792FAF2A286D94EA4F04BFB6CD50E09837C2B1362C94" "76B3E268481C2084A3D64B58612CC5754CC23131B0CAD378198FBC39379C46D1" "1F669B65B749001AD28C4B3363C16D11CF14AB986A63A92E0BC7DE55F8B1578B" "692A4F074843DFCFCF66B3059E87BE7B624A93EA07BEA33672F048C91E5EB9DC" "07A61D496397BBED5B9CFDB3EB7C6E96DA540C80684AA96B319456E3798FA145" "3C3B24160ECE6CF7E8A39CD4453FEABADA160A4CB99716BD3D91EE6DD2585153" "DAD576B9F91A54248FD3CDC3ED469DEDF38180F29C6B6707DFD03B00B9DF9857" "31016943F248683E596B0C52950CC1413E6AAC82139ED1F10C02B3661CE4799C" "8478D83D5DFA536BB700C317EC07A59F8A3DE03B18664AE9B2C0648949299D3E" "62F17963648EB7C0BF5EAD36D28DF480D51ACB92E867ADF84C646F2330E34F47" "A8AB992EFB81783B2DE46E22961DDA72615E3B9C2E09C7DA4BBA604B1A22FF43" "D31C539F6979F0A8F6A8DC3CFE2AB38BF642C8DD20992726E90BDA6C1DDA79C7" "1BF7E7BDC82F83EB194378418883A5DDF85DFC2CDF9BF98F4F86891D023111CC" "ACB829B3BD6A8AA8D061E098D79978855FA8712E150C723F6EDAB16B2AF72A71" "ECE74FB4DA1499E1BB66F393DA5ABD60ACB9A40F480D7D39773A0792AAD44551" "13B48F790F82AF69391B9F5F5BF8BD6151BBFF28BE1CD54988DB6E7C7B49AC37" "D022ACDD6E5E96816BACE860C71B909F57621B4BEA989F286C85EAECFE291E49" "3D740D2BB089FDF210F62A9B4A33E80F7BFCC7102FD25957AC237FB9A9E6E114" "1F97B37D417B89DE2D0D2BF8BF3EC7F62D2F86FF1DB89A503164BB8D72BE0A1F" "4A3307661490175D289D38C7E4A00936B147900ADF917584427ED587477A24E7" "74E9F325A0679E69551361FCC26AE3A581002BFAB4BC664709472D14FB65E4B5" "B7606E578FF19F45C459BA2AED0065E7904D6FBB4AA3298264AC7FC0A978425A" "A9FCFA609C90ED18FC038CEA70C3FA5D4B5456AEAFCF8388E8F874E2370E2211" "D040448FD7C81C102B882AFE4591FF41686A88161AD67EBEB52A4CF1FA761B79" "92B28EDED607BE0C567F494A42267CBB9B5C576449A5FBEE81E5B00F7730D81C" "6C2B21188489D6AB8572BB6A2B9345AABF91914FB16BD0084CCDDCE17740A2E7" "D8D45F56692702F320E50FE02DCC1B65F402753352753F21D49F17081152C07C" "B4B23D65B8ABDC7A7BCE72975C1A04A7DFC58FF0EC5EE9B43F57A3C698531DCF" "6FD6C286AA0E1603D6001C04531A29954A7636EC66FA7F55192D8ECB36C21E3F" "096AA74641D9A1635E3D20D6CBFDFB4600A0684971C64133258904B8501E5483" "743AA6ADF116B7DEB75BAD06C5626C2F6AA9933FFA57715A6C2B0383E07A1AB3" "B5B58EFBA06365745DA4D28FD15F1864A066BC805A1BF598D715D15A7BDCB265" "2D0E0A4A001202AAD8C5C09D641B32077500324A19A188E3A3A7672980AF9AC2" "3862B41DBC7E7BE48FF3C8C3634D86E163D7613FF93057758A330FCABEF0A3B6" "0B2A540F82AAA09E7990B4D5A8B90710284D4DD7EBB40640231C591F3BEDF4DB" "B6144F53156656F098A5E8F417D148318018CA972F7DBBFB9D71C11ECC18786C" "CD471477E9C563117CE44B328FA103A9A8364EEA95C8DE24C7DDA504259FF4F5" "4525B32A0E60630065B23CE7E1DEC1B2A29790FA9F3CDB0797E23E69A5EDEED" "E"), /*message = */ absl::HexStringToBytes("D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835A" "D55B22E75BF57BB556AC8"), /*signature = */ absl::HexStringToBytes( "84EC9F59B6A2FDD5869CF5524ED3FF70BB40FE6BDC99C3B6733FB63DA094FA3F" "2815FE466856A22366F4F61351DE657481263D526A397E19548DF524932EF1D7" "7D71156AB32589BFCA3E79493AE2E8A48DC120812DFC80223F011BCFE26F7858" "60A7CC29B79CFCC33735EE33C5CA4CB5ACA0AD6A724C0EAEE7BA4FBA7752DCF3" "9D3AAF35D79E628BF0416744AF3268827895FC7E5E7261C023C204A407727BAA" "32058349B440AA3741052824BA52D3581FB44F4DC9D05FF05EF0AEEA8AF5622A" "4CC4384B1B24FAC53193CAE56663556D1C3456E04AAA42949CDA637C7F780D08" "E1B3221670981B24B03158B54FF2B1E06ABFDC3C21245573DF6A9C0025970484" "2AC618F8FB331942D64B88F5F659005887FCE8E4B78C37FAA506A2EC0C7A2343" "5B1D59AC6B168F9F2AE606BE0B4BDB819301E30A09598603959C702A9EE6D150" "E1039D4CD6F2A7B761D9711422101EF6DE7B7802EF9A5C6716FF527E286E3602" "4C1027D2E5AD899D50D88CEF875F7E185806EB002F7002DC06D8C57A1E41F3D9" "EED932ADF81534A5B347306A9A50156E176C7F284CEA470B024EAC92E0E829FB" "AA483FA26978FC85AC069319D5F201FF8D56556BE1756DC25AB7DF3894223A33" "5287FEBB15C768BA0D99AB3B3AA31E63F0445033CE31A8E12D308E877733525F" "ED4ECD878E5A6F513613CEC04F24E198F6BB081D7B2BAA7C04F3051A01EBB674" "CB99137771071FE73181E57F10950B8E952DDB1223023B791E957C4FB7F69316" "2DA8790550B8507306ABEC65843B1BC7910A5AD93B8EC49D94544E0DE11F9738" "468D4A71BC8EDCBF96ADD1A1D3A0EEFBF41BEE1593672FB0076FCD60BC0BA147" "D6436E3AC71D12EEC4CEEDC8CC4A794A7874B6D8B628BD17DB93246EA4075B22" "9D86E191D56CBFF091BCFF79E645094F06BBAB143882177DACA9FBB9D9BFF2C7" "46775D908F32F4D926480A01AE22AC6B2A63414FD8A77285A85A6EFDDD3F9BDC" "BAD3A8B613B0647D776A008029846E0D1664D7E290868A7D2A4F2A83D2F6E043" "4C8AD6CA664BE2A1A4B1C8B517492224FD1AD4AAED4A200DA2BF7AB0FF2693DC" "FCC026CD77D76111DCE7B3431BE13EF462F1A56EA87AA1647436429733D8B011" "0F34C7222A6A1C49CC772604D3856B5A82B2DE6E39D0112B438F74B37CEF4A39" "43530C02D0CD4BC70A98DEB62016D392CF9D8FD86EDC430407B6D01C203327C5" "4AAD87B63E93231D6F75AE9B6B8FF4DA71D3C6455448544FBF11AEF8861A720A" "5CEC13D07EB5F8EFF82C6DCCF8087F07B3573529FE8AD1972B0F490731D4ECC2" "5D6BEEB7CC540A38C2EA11B823FE424191893B2A22DB025C5AC3B688C578593A" "A3B0DE87A1A11BBF913DF07DAEBB8AC80F8B2BC545DE3AA10D12D2B2AD34400B" "366C507B6BF33E33CEBFC06B6E47EA6FA381E58876F8195DDA0A6DDCF88105C4" "753ABA652E4C7644544B08F2DA3403F5DFF7DEB68E5BE7824851D9EADB9FE04F" "DCDA8C5CBCCF01B720019DD977546FE0BE494E5C40FC5BD6C7E7DFC1073556C9" "7BFA9EE1BC15C1A80E097CF82E228825F16E8F2EB5078D223AAF2184196964DF" "44BB37052F528D84B7AA37E7E26E664BA94271F4A45BD89135FBCBCC69F25A12" "6C1CF457FB8040F6789E01936183956A9A95F95F7AF017775746F4DB5D6A8230" "05B0BB209389F9EC4D86371D44F4BABD585907F0E60E70263C32B9053978083E" "D22EFEADC228C831204EE2920626C90A2DF829A3CD1BC4447D05634DBAEC0660" "0B1DF87EC60C1D3C228CD2F1C4D8F1F58B48994ED1BCF68CC829121B0909B7D2" "99C5B97AC2B0E5A70D1782D8EC8553A2643A444B025245895A684E2F718BC5DC" "5D5C4027633DCDCADEBD4E432B30713979B479BFB64DE40E265E4569899D146C" "5FC8AE6FDE3EFEEF568484C8EC51635F05E0DDA9BBD2E5369B04C5F42D63782F" "062A1E5F7FA1D5262BBE90BB9FBC30A850FD79A87586BE6B9F7DD78B54D73378" "A7A8837217B32C6F98A1CDD30E00590D2B912407327D4F21B8EE134BE6BFA4C7" "4591715B293C6AFF4B458C2F3651CB129DED0A98181DF52F79321F5AFAB07F1E" "834583F16DBD84E22F4CF91674E0C368394950AB3AF90444E651D0AB5E65E395" "93BFF15BECD3815D8BAA1373A43D5EE1BEDF4EB71938ECF45C0830AB8E24C02F" "59D86781775D374EB860F8ADCC1012281DE73D68614BE9D7BF33445E64EA2F5B" "E0DA78E67E49BCEC4EA7AEAC2E579504DCF019AB9053297098CA649580A1EA01" "C8C31B71C327A99E7397411796FF2C23EDC1CF2229D728A0F13D7765ED46B99C" "9190ED7A0FBC47508C42D315D3D14AF691189CD9C9736BF5A052BF54E266817E" "DE8290585CAF02630A54575838B586F4355FEE407A10F8031C385B4AF8951052" "9F684A00499EAA516F4261B4FCAE2F7235DE044693A567B7E7D94C6E70564E54" "8F005610AD1063731974AFB946D44451B77C3C51B6CCF9653CBB2AA0A7A553E8" "F3C041204D116CF1F24B136782E6F20CCB8BB5612395CF2C8FE24DF4F6DB35CD" "06358B2D1DA9906CDC6491F4428399DCF171F2F1ADB791A8A01E4F5F3FE6FAEC" "DF38E135060942CAC880C720EEE4E2428E0B8ED272F18552A79CE0CB069BFA9D" "AB8A6C8210C7A0568ADCA57EC83A3191BBE50D00A01F871AF40D19EBA1186878" "BF1076077EBCB8355777CA3BC2EBD2AE147696AC5F89C4BCE186AEDF4DDA2647" "1AE7B45BB0BC641D5B658AED6B1A319BF568BC528EB417755F52103E37EE3E9C" "793DEE05F6D347452B60BFD82C51E1A8CAE61A079D253B97468CBD32020422AB" "540F4F82F7C7442613038989B9BCE865E2673F759FE182578D202B803CD5F865" "0E3F53957BF8FA21F7CF77A69DB41283C1428A0B1BD7D9BDAE26315D90BD929E" "8A7ED7591C6A6E4EBDF4B0D4007CCDD2CA6BAE16531E69C7BFF76B6FDCA61D41" "CB7C32DD333981BBDF0404166D77C31BA64A97C465DCE86B3143C9967645ECD5" "B1930063AD08E2CEACA8E2DA9FF189ECB37A432A147EC9F557142ABA369353C0" "CE571864ECF06A7647B177CF97137E0143CC81547FC09D54A174B8251AF0DDDB" "8E81554ABD5F1F3217346C36518CAD182EC423E2661E735E2DD72423D06E1674" "AF0D490B248BB1E0BF9EE7347E5510615AB8959BF69931361A71C527D06D9D3C" "3D525621A182DDBC5494B0CC1836263E4FB6E90BBC0E471436E895115F9409CD" "13E19B736A3C8AB169B68F62659CADBB4FECB9DE6C655BB63D2216FA0BB5049E" "E8165E0EF2BD2259B684A7FA1B1868CABBA476FF33C298C8327A0FCFCB32C7AB" "10FF8F775EDC16031E1B767B7E7DD0B2E3394994A23B8D3DD27437BC68F337DC" "5F784A204C8E1255C89BD9A39FAA3F0F601E23C2016ACEA507BB4A072BA13AB1" "05C8377E6C6D3B42A150A270C5EFEF8AB5EBD1D3AE549CEA563420E70A4AE801" "447E7B5DCC4BA64F0BE0AE062909B685FF2D2E1CC2B4F8AC41B9E16F87FCAA96" "E4AD032DDC6333251CDAEEC47177C879164F2F0A1B9EFA827203AD99223C54DE" "F7D517CA44D0CBC04150264060850014B302D2709591B874CF9A7B90C6E831BB" "C69C3F38D18EE4273D3B1FD6681C73F9ABE767F16033D7A65B39F41B0FCEDB91" "B02853ED35A7B899A08A700CC8B998A12ADCD53AE848606E3BA20899F533616A" "624B416732E0A6D33A893E4B5170FC8672859792E0867826528EFC70A8D08BC6" "451B4CF38A3DAA4CD0742DCB5332717B5241BE781276D72C38CA0CBAD6E24EB4" "7FBBB4BCCC3BB5E9D0E8FD1872864F23E922CB87EF94ADB4C045AF55897029A7" "AD4446EA14BC07E1BD60BB7433C48D9E06E11B25D70C7799933A78B75961E79C" "9D68FCB02208738EAC9BF5745CD615963ABB365C7CB396C3800E9536DBB7251C" "C6223D40176A027D2A9D1550D09562C59354B851AC7D90B1B435708B6F3BE37E" "C267A1EC1045AF287869B5EEA620C688383CD917068FB87E828782E946A494C4" "FFD4F6667A977D11156D30EF9E4C67DEB48151DB5898EEBE83CF756160924C0B" "D77E62F539EE5FF6186C5F1398CFA3AF59A1EDDCE36A0BD689207B710DC4B85F" "6664FE4CDB614C93C77DB1FE0004E47CD1CF77B95642B866935062E598704B30" "741F8B60FBC903FA85A3547FC72CDBC12935199C98ECF6C02B0AC93367FB1C16" "D7BCE9E5C3E4832B88D469A8A02B001B5B268C10099B17BA3E3E0D67C97E33A4" "DAF941BBAC7EF3C81EEB21EBC3C4778C23A6F8718B572D291B1DD81D32B2BBE0" "F75D9A40B89E47FE7D6A9928B857D740DA77A4D2113C7F267E87C277659F3594" "208C2AF2D5094FFFB9D1FF9FD978631FC0334661285A58538493CE47EFDC9687" "A8B09342D68D15F92E8959A7EE119F564723C40B1F41D21E919D3F7F18958949" "55921FAB129819E81D8FFF2D92C0657EA4D27895894F6139B688A2E31DD8D7D0" "5E2AF6D1BF1EAFBAC9D75F179F997B717D6215F8418AC93EA6FF002A388F5322" "37A2BAE82C4C12C81E8C7A5BB2F9660D0476B81208BF69BC8F336EA17A77CED6" "7A80DD81399BC5665FFB1B6427FDF980E4F3C0E9C6C41C93462DB0A14E5A3CBD" "346A749FD2E70D0F24293B90A1D2DDACFC2C3B55C2FC02454756AEDC06545E62" "7900000000000000000000000000000000000000000000060F11161C21"), }, { /*TEST Dilithium5 AES*/ /*public_key= */ absl::HexStringToBytes( "1C0EE1111B08003F28E65E8B3BDEB037CF8F221DFCDAF5950EDB38D506D85BEF" "66D02BD8299B815AB461FB6043BC1059C1850C557F629421BACB553D862C7F7B" "4461D75A2795D428F42F87D9B6FEDC924BF55402C3E98B1DD0A56069414E5D56" "42AB19C3BEA56B2B0B01811223E8EAEF97B25C925A1B414C350E473B81F588D8" "7A3A686CF9ECF44932AF571299F3D6DDB01C29B1C5935F49D9089AC82A0E8C8E" "04B388083AD1B454172B7BC1E334ADF871C5012679186FFF0BCFA1F842DE7C20" "38BB2E91848B6F60C4FFDA664A03058CC3EABADF70500189A456703332ECBB41" "3904A9FB06E943BAB4D77CDA89058DC49551F38CD347B030047ACDDFF5958FDA" "7FEB5C3136A826646A3C452FB4EDB368FDBCDE506EE0D7AB53E0931379A12AB5" "32AEA06A8C18B8AA839ABE02EF1018296CB5953AA21D9A634F4A40EBBA25481D" "E20F1D2B9FB1C2B745F528DD51E0C246013EC2121337C8A63B637C926B296224" "FEDCABA72F28489E016B0857116AE84DC1FB40CCBB9607B8261DA2E0DD150C71" "616D1EB95158778F8DB92C0FC155444ADE9229D2A62DEB7AED858155BDDB439C" "8C4FAA455714929B128E2F46A436BC3E807F7E426EA5E3310A6C591158B343CC" "3C50189D6129FF32C328F5E6A6296CE6D7235F1178373756B80B3A14CCC260A8" "423DC921AA9E7D6A4FF255318F036BECB16EAEC315DDED0FA5E2FD6FACDA118A" "0B737416DD6F3470791B62212D11A86FF045BA503EB872428513463B4B59C29F" "4B7D0EC7F470DB1F779531A4202C5B8AAFDC17AD3A76F39A59AF9C555780F31F" "610AE3497E0DAD70CD424AB616E952A41E20D2749074FEB15649152D49A9A84D" "5F2BF2376DAB936FDE9BDDC420C62BAEF6FEEA9FF069EBD0ADAFCF7B74F76D05" "732F8375FAAB0CB05CE67F87C512A91213A05E728225B92BAC8DD21F3DD5556D" "FE03E8BC27B7611E42A0F3CD309C0E0CF65473523A2AA89571540D3F1EEB91DC" "B5E41587BFB1926076545D673D0157C312F0BE43CE8FEFC5004FA35AF29B6E55" "CDDC87CE8E2C470D2299C8834A25BB1BEB02DF73DCC5289081026C6FDA6B72EC" "818848D694A69CBFB562D4D61625CFDF625C363468013D9E8F271F5C872BC959" "4015690ACF575428E2B4F79DAF14FA0562D757CEB1D7FBB837FD2EF6D19EB0EB" "1FCAA5399A0E1C2C723D9B18B80F896E26F0BEF62D96312243FE48EE5AE53BF8" "2B4CC1259BB55377689C9A3AAD964504E22F0A7B198E3B7DA88ECC926C8BDD28" "4D46ADDC9ACD49A0CF0DB3C36412A2DEBD1B0A65FEF211ABE40C78AE4441A9A3" "F81798DDD7C6C4C9121EE88D42D7FBC6DE13AFD4715DD71664B5404133993DC5" "AB8A10CBF3D1268A830DE41F90EF28A252620EA02402E9DCDB4C3470DE10C191" "2064F6C4CF79BBD126E215AC68216AABD1E4E46A4847CDC5F4E91CF4BFA9734D" "14A56D71843ECEA5E058BC33182876342DC05CC85C5F832059A6F616A3506F1B" "EECC1068A1849B8DFEDB57863304DAAD2AC2D246C16C210D807474A020812DB1" "DD7E3AB0ED2A9A5BD6481550CEEEFEA51531FAB03E5A25117988A58D34F98F4E" "96FDE2B4D0976C257DBBA78BE0248C20CBB1238C5A824E617909CB45E0D6D50A" "1A1E8CD3A4100C742279B1F3838E99D69F98F61FAA722585437C1D82C3AECDF0" "F14EB0D89AB5997797195F4F4B0601A67D5F0C29609C266876E6160C46B38704" "91E13EAAB7FB62B4030D160B959C4DB423E5D2BAA3DFCF960EB930958B1105B9" "00D9E629A941271833216C35539CD7C2C40030035AC1E630E9EC4B8324543DC7" "3138F6E9AE58F804556818CEAD6B1A8D526878386A0BBBC697565148D2986E27" "C376DFDF199991D067BED705C7A1FF419A45F188FBB715C06F9077E862E2B67E" "05F5386FABED0BBF587D935A25AF86F6B945C9E90CEB539EA3D820912F87CAD7" "BADBC3ECA84588ABEEC56910B84703618FD2491AE68C7FDB88CD5131F2C5D694" "336495E0AE434549F7E835CFBBCD2DE770D14209FB54F8CAEE092202F12C4D0B" "6A9F6C1ED7F9413D509CAC8F31E7393C717B340FEDECB77003305B54858C01C1" "7D3B281E894D59442B1D66944B59B3FCDF96EC6FD4B69ABDE2C5DF78B50E7DDB" "DE0A75054D93B6BE8E474CAAAF102FD1B577374FBB940748FF9F40482F2EA955" "7D3735E5355D74E97B824B30F80F85D2EC8179000B7912D5DD37984434A5C6C5" "A19F42C91F9220616DDA34DC54FDD47472BF95123A8EA0116FA65C5A53FC77CC" "F69F52A2FD373FA836BC214E6F2B4F3D64E5EF2D8F08DBB38F07520FA97D82ED" "F789D9387607E74DBAE2EBAE24EA2479A19CE185E2B0CCA4354AB7C40E8A502F" "BDA7A7666DABBE9C8A18A82B1F8FAF9322BF0C5743D4AE46346A10C365BD8F6F" "14F4118E022E910430013448E921D7B81AB74AFA11B9484B7049865B516FE2F8" "8F06B89C8823B81BF1E593CF8F0487AC065E732C29028B42FEB43BECB67E78C0" "9E4E74256B81C8E2F8AC317DE028F966F3E282913FE9860F16CD7055CBDEC81B" "60E00A12D4D94AF0FC3725E1574A32D5450C9840EEE663BC51360AECA9CDAFB4" "EC1EA6BD272997E7FB3EECCE1FA436EC19FD0AAA3CFFF1A1FD44098DDC9B16FD" "E5395EB16613ECFB0C1C40B8295066EDDF5F7B5BE3A2189D7D5BEA5065974177" "974D71395FE5D7A69D72F5466ACA864265C472ADAC2BB8122844ACA252C0A85F" "94C770226BC57EE92CE194F637D83CEF658F9528A9E2061712C399AC22C56021" "DB32647246AC2378F9D0436CEC6A2DAA87F5124BA4715591F5C489FD27CF27FF" "FAFCA66DD3C8E192664DD75AB63EC60D218583876E6051FA6B349404F412F477" "D9A74BF168E1CAD6BD0B21B013C4643060A46FD011D2B36BCDEA8E87BDAAF5FD" "F7C9DB5EDBC6E7D0F00444B464D365009CC074C6666F1497CA583AD445F759E5" "930E0917FE018DC0CF7058899BD1BFFA1DFB0689C50600E9322339C8A32A8ABD" "07B8817743F1EBDDC1732C704D887454DAD00769444F4E261D68B5C4A5A8EA49" "98FAFB4E77427BE737210DEAF20E4CF28EFBF524365E821B1960B1D761098253" "B2FE18D46CF6A892F9C38D6F3E8F5E2B719B73F8AA0B67A99B85BB9BF920AC7A" "3CE2F1B44A394E758EA7821D2503DFDB53BF4E1BA0C0912299AFCD096B3265C5" "BA95696980451CAE3248FA8D0D9E14AF8285DDC36C1A5AF0174D34DB2A5CD508" "E6CB19A33A2A9A26E76E1BCF3291CE184A11DA239C4D24826C6EB63CA2A5CE95" "CDFE130209E76E02C3057D6AB6CBDE61BD4E31DBECB56C271E11B45382F6BA06" "74334ADE92F26AFE57F433201E3DAF56FA8B3E08959FB6A45CDE1E9E4971C8D0" "05228C58C3A8632FDE53B7DEA834241B9C72CAA3C9FBAAAD249541C06FC5E21E" "3D19866373EBA687EF594B0D27E4A5CFA2CB6425DFAC1335BF9D4D04AA65F6DD" "B0481272702F15081FA4A1310717C214974C258A37B7969B69659A6602659482" "30B17BB6F32359F51918033A6F9E84645FFBF642F1BC16F28C314FD0150BD65C" "3D4E43562851207DEF5AAF80E851F4648DDA20DDAD03C1965855FD3684FD384E" "FD9E19169550D4337FAA85267639E6A9EEEFA3CB516B44C3CBCF07D1D5E585AF" "D6EE5099AB4F594494D7F6871ADA5B769FB9D3AD841F03DC942A4C049D181A2" "0"), /*message = */ absl::HexStringToBytes("D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835A" "D55B22E75BF57BB556AC8"), /*signature = */ absl::HexStringToBytes( "71F7F7FD6276C18539BF89D27B86C26716771342AD46F1FBC8594496B3C85B36" "1B2CBEEE99CF0BD6E8E43F31F6154D49C1ED65EF51F8BAE947469C3772B60065" "EA5FA1B02895D9DC1A02E063054420ADCAC38079419D1F02D89753ABAF499E28" "45F723609AD1F9341D6FD912DF241F0B9727BAF8A6D547E1DA8FEBB5A963C2B5" "3F2322B1CC2F4BBCD13B4F50A095166C7C918412737C9CD03C83CBC8A9AA64D7" "3399106BA0FC4827AC20B59889278CA7BBE8C06B4FE571C3C603C0FD1FE6AB15" "8A7778D4A76E425D048FEE82D0F8F95A84FD93818131A5A8B6C2A1DBE3DA04CC" "0D68013B9D5D1E3E3CDDD844335FC8F80CA5BC715C2D4DB8E80466256C2BF89D" "324FA709B4683F2E3CDCE00B9985CE75B931F378E8950CD1DF3F80190B162C2C" "4CB0297F16FC16908C1067F98211AF5AFF9036023799ABC95A5D6E91CA360049" "E1AD1CFF1B95245C692363D6BEFBA1B1E4F48E3DC33E490A0EACB7C3A9534EEC" "F7C66CE1CBDA457F76DB9540CC7A8E62331640001AA6CF0EEDEAE1805EE03F25" "23ED318DC2430BC096BD7BD830A88CF2CBCA2D11C511866C8E414CEF9F3C0CFC" "E915A0AD0547FE3BBBA8D0020981AF7F9D35494D883CBF9F32B457394794E0EA" "A06126E4516C1D71F44F7FB14925FFF6528C5277E60C16191717357560F2E9B7" "4E51BCB0E5E334D945972D26CCFFC7453630CA135FA005D3B1EFE929096A8E70" "AB90D3874E881035CED16297ABBD4A7D6647B89D213C251527EB644C1B133C18" "02350BE47CC90ADEFB83281A521C382BF55D376AD58AAAC68EBB3ECCD7A9E784" "83FE48965339368C9DF41BD34482A8357D0FE4A723A0C0881ED385E63F16B467" "81585B1B339D121250A26F1608AD0617CCCD6668F1E6EDD25B16AC43326F7E99" "B5245A8AA4A647D03DCA63C26C7BBA83F8A69A3BA807A8DF9CAEE0F5DF54BAC0" "E022FFD9F635DA265ADD24D90DAFFB86295CCDD510A3044563B276D1D406BC83" "4C7AA106D26EC3B3783F69AD001CBA0279580C499CC4D99996F36EBD8C711C78" "95F625D50BA375409646E0C2E6208877A4ACF92587B6D302401A25510D059FB4" "E3793BA52BE7E1C383D2E238804AB19837A9D2A1FBC96AB2C29B5496B0AF5F42" "57D51DB9AADCA5D67D0613579D40EF1FEF1A1D177B23FFAB218CF49073A6064E" "2531CF25A23C5C47AD4D71133FF6BF07673DEAA1D45ED860C5C58CFF65888BC6" "496FA5A2DF20DE617BFC0DECB4078CF081F7F18FFB350AD891F5FC80E5FCBB1E" "DE3653A4B760DE68046EF68524B4EB19D541905F7A3826148FE9FED184AE3A78" "D511B801967F40826D5267095271F7FE3FF423B0B5E741DC876F85C5959657A9" "6FD247481DAD3CEBC500660EEC6A31A89634005F6F5AF51662B16161AB561235" "A4F7547BE90354564A0B912FD576BD6F18F238BF9E7A20DD5537517AE11FC649" "46A8CCBAD13F14E13785E942D89B4AB084192A48DF017F9F87DC0641B21D132F" "6DFE7E25D993801287E7A5F073150C8DC43B08ACFA8001F0BE6FAF23CE83C4F5" "B49D6F2D04E4768E573D1EA1C703E7F7C2E892E63B654D8900B2307CA6C78F2C" "D8C98D8B00A484893D07CCAE09FF6602D2D2E17124EA7CE843A230ABF20DEE59" "303CDE65289D8BC354ADE66EFC23CB76ABEE4A3205212C51BEAE793DF29D2CA9" "57786A6DFAADA9A269707FC4F55AE554410851D7F1C7A22C730A669191DBDCAF" "6E24866B291218FCFC79CA19585A75672EFBC03239FB158DCBF402324099F33B" "7CADF4F4D35C65CCE5D33594F3F8F350A9520D1C47A8386F6342B462E560192A" "337429684B4497E20110946F6E9C8A87E93A51ECEA96E426E5D20F1AACC8773B" "281DA492976F8375538BE088033D5CE271ECDCA4B139E517194798721C16ECC8" "CB8B2DC4200D31B8BF87869960D7E0F8A46773D0C99BC76594F41859E6A92368" "73D7149CD9ACFFC8D075C532881AC55ACEBF062453FBBF4C329071DF798948E2" "21D68E7BFF4E7DE446EADD71005D38243FB61CEC26275D54A4A111323115CA8A" "17E9A8F401E8360B3BAFC52C0CA9535232FC57EB29342E322A8333A14972E9E1" "C38C9391330A030D19E96562A34D798A094C54CA834B376FF28ACF6CC70926EE" "25B0FA8C34D2E43C9593A8627409FA51ECD48572C015D4673329AF4AF047ACF1" "0590BAEB30919F1ABEBD2C79F337A2E860196E74531389B52BD03A8ED1011B60" "28B1019A0F52433B00D7EC5460E4226082A6D0BDD4B4DC03A97561EBF6881CE0" "7B768E096C05E6FC3E03A03F8057B310C70FAC81F26BE9A6DF94F7D0676061C8" "4E611F07F963A5F7FABEF8CBAE908C1DD706CE100D0A737F0D1BF349207A09CC" "BC45997C41352AB92A537F34CF64D1D82EBD7BE5DE3DEF74657BEDF2370D7E9C" "7B74A8E1F256F0E273E17C41E122D72E5E2382E3309C1BCFEB4430C3C7A50C5B" "A82E82E638FEA34391CB84B6B7A01ECB384E399419F9A71053C9C182D0EE2035" "76E3D40EDC3B1A59071092F2ACC1F49D65CDC71BA960DA38ED0F84858589A85C" "F2CEA9EB373D650C89D2E29408ED80AE7F01E06D01761F1D79BC38116CA97BF1" "844FD68999C3C75F51D534F032462F2BCC08655D1DE4BF1C8915178948DFB371" "8117CF9E1ABA63EFAA0FA9C8BDF3F7F422875574C090BDA33B741106672361D8" "86B025AB8CDE990D0F4159F522AB985426FA1BBFFFD6E83DB7FBF006207F02EF" "03E6AB6FC16B4306B1D437E4AFAD9CB7249217D7DCB3C20A2206CD29C088188F" "8DF36466D1ED6FC892789453EEE07F6D82BC8FCCFEBEEBF867964564BFA36D9A" "68BB05462B81DC5B0F30142C38E0EB31FBFE4C6651A08DD20644A7137DBA397B" "07763483CEF14897FF3D318C3A6F84913312E655C362E2EA37C0B1B406DC275F" "23687B7D6AD0580F545F88B9429B33892B85FE25FE86EBC9DA69E07C7F56F191" "C6FF43AA390FDAD81C9D7F9417BBFCD4A25317C3671D31D99FE9D5720B265D37" "892BB34883B668408B88936A166F12CE6A3FD6A90A4AA29DF4F8B07B987E9691" "EC6C6FFB279C4BFA6908BF05FAC22844717B6290B671321D5F865974D745DC81" "47D934588CBDEB138EBBC9AECB8120653F6ACE9ED40A2794D0BFBA2AF435EF58" "7FE07ED65B79F3C835B9E8D214A8F60CA8E942368B5E30E7F4C7BB27EFD0D2F3" "1C678733B75B202563C810847BF864B16CB1CC75DEADD5D1A994AD8A43077BA4" "DB51145CE8FE30E487748FB81AFA7D06C9CB2D20D9C741C91455E29C082DAB9B" "559A0B01579664E127BA51E2A53E79830E9C907DBAEF96E6B24D42035D94B7E4" "993EBB5CBA4E96DBFFAC4EAEAD7FC085A0B3D8FEDC8F2688FFD5CE96445DD452" "A5D680E61E5984395D88EA47E0AB2EEB4958E3FA70314866B6E767DBF346F014" "67ADCE60654758D3524A1A451036600C98329F78BCE31A9E238109867B647E1E" "73472C55BBE18B37436029C8FBFCD35FFAFC336C7CFE3E16994874ACD0347524" "4F663163789622B75D29F937737D5E91D4119616400066A0F710E740F578703B" "E692055AC486C66B4E6B0CCAA3DC82B55FADDEB9A2B0B27050DB015404EF4A2E" "BEAF52BF6EEC18A6A7DD955105784D232F921617560ADFC60E6F0750B628F72E" "8B2EE29D43C609C1EEE0BB2E60F166F11449139E0993A3DA27AE6104948DE565" "DB0EFC178E28AAADEF18271C086E29BFBF15A8F9E1ACFE86A6607A14E974067D" "B4E8054757FC996534684E44D9CB088553BA4762B17FF609AEEDD47895A07100" "6382C12190D002AC4D54B558169B5E486791BE0EFFFF17CEE0BAC7CBDB974149" "AF4D530587E2E732498BAF9BC3C9D59202CA94BBB657EB0DD909EC683E07016B" "62E8550EC4D2911741DC09265F8BCC15E10837E693C4FC47ED95B85020739A11" "230287E000E975B78D1461F74889422D4313F3646F3645BCA2685A954A5E6D32" "75DC98AFA40BA0065A77D5206C2DAD9A64C55F54E3B81803A9BAC6781F6065A6" "54B2D19126DA7AEE33C3EC3F43DB88F98D76BE744132B49DF9C8DD5CD7DFEA58" "B069A1669B7BD3C405A40154F66D7DF47AD3AF18C20641552345932A7E971229" "096F856D90A5DA032827CC74F8E30E48F7B8D1E64FAB11B8D0E941CEFD3BF948" "73C091C30EA47BC8A1840B7D9BCD248FF3B2B6542B19A228E5AD4B26B262F889" "97D25AFF20996088D75D920F4CFFA10138228C3F2236728F2173CF064CC3230F" "4FD1912434ED47CA75DE5DB2D93AC5AB9F4383B9E96A3B77C12E35283C4415CD" "6DA9C14EA2CD09666DDE33C95D89A9DE6DA18E05CB07961EC8EA4550290CA3E9" "7BAF9CAE6C720B7E6E33A15335ED342A75E91D6349AB18092352F6C28B4E0FB4" "8992EB48E498CE68557BC97DD8EF10C02A78F68B573047EC3F69F1ABF44229F0" "4B0097971575B16068F6D54AC63F85D4F309A070AFC5ADA6E99F2EAC1CACF52A" "40AA8E993D7475D0080F9C02F9A3E7BF6AC62CE0D67F820616551A6B7703ECAD" "2BBCF726149ACAB0569BD5C58C48BF1D8C6A811FA04762BF8AA92EC844E775F9" "94F106F05625B1493449C640E24483A49199C81FB7F7953BF3FDCD1105944789" "295E629578078955A93BB1CECEEABCB29FF35F43A37549F60ABB3EFB344A9151" "F93C617E7E710D8E8C48EBAAE83FEF43985AE5EDFCC716A700BDEB552037D286" "20121F6FEC1F3D2EA97E0346517D11A84FE969ECB3EF4F7787F8BD86C97EB2D6" "39AD8D97506B10C1AD10D2BBFF58307CD744A8FDC9141D873B13F78E6F74F820" "16DC3BFF252EC58933401C7BF14B0E0275881B96198E6FB6E5CBF22D29E286A8" "47B2857DC9D6214AFBFA2787A4FC0D65C65C6BF48A22F4001D8F538E63A2C3D7" "D6E0914DE4DA0A7BCA5DC5BE4578212F9CAED253CDA04ADC81D7DE8056165177" "54F1E8FCEB26B468789522CF42E400F5E1918EA3D3EF93E16CB10A234EAC91F2" "5801B1E2AC958FDC724B90F079E77C3EA89FBDD4566790DA20C0CE254DE71148" "9EFC4F7C0D5A31067D3A82A00CDB3C4E4475497A4A54FEA8C17C6836B6C3B70B" "00612152490C238B127EA698DC7E93CE8B1E0CE7E7902EA5EABBDF205732ECFF" "AE35D485D8E5D0DF235F2FE98848197E5AA9402EA3E987A46CE8B365A2E046CE" "819543FBAECA042C626B0F36F2E34328EC8AFFCCD799983026199729FE6EF74C" "81473BB2FF1CA4D8A5C9E78BB849AEB8B0F81A745A73119F6B07FDCA012F3431" "EFF38152A1DCDDA9A95D8593B17FB3D547508A1B09E00BBE8B44E50892968FBC" "6C3447901DBA193E75859A33475DC43422D296BB9547255374BED89BF6664533" "57A85452DCE35F044DB4FCC0FA68EBE6527ACC1E1A2453D56CBB3490BD08C086" "77E2BE61C94D570E5CF7EE97D03CCD971AFBD5225E1EAF18CF791742C3CF8CD8" "D0E26FBD2A6B15E452C182A271BF4E16866755BDE269F13AC6DF0199240A0690" "7BA634C9399EFD092D9137869AC79ABD42D0BC157D8FEBF1B77D322E808A21C4" "557ABB70D53E63AB101F4CF7A42A7BA796CEF56862064955736CEDABFAEB6F9B" "E1A1B22B93E803883104CBD532F0416E61576FC3FB75D7AE6C139FAEF577C62C" "481C4046D3B4954452B58AC5AE24B72E8E0D540BD714F0FE347BCD41C0E9D507" "B7F5A90299ADBD0D936EB49AFCDE0A4CA3A817F5D7360811F61D96D05B7C003B" "659D4025E96679793DCE976A0BA97E61ABAD5A15E2401FBA2146E9DAFCD31347" "6665F02A70BBAE96E39A3DE1282FA7961712A1EC2402B48DB4E2297BF6293B3E" "D7D8D4619E791C1CB6C50C61AE8B915A0E108FF82968CB0F1EDDA73E0CEE45FA" "D58422A02CD47736AC503CB4DE1A07C049F0FE5A2A5B1D282F8978FBB722B89C" "D7D389D9A4F0725C73A6442CA529DB3DCDE379A667D135A835B04450E0DE0BBE" "A8B8EE8FB98BBB2493A1FAF9B3F1C83A42B0EFC7F5672FBFCDCE3A5C62CC366E" "D063EA96758F2809DF1AE378AF893A44A6EF6CDC440350F5A56421AEDDA266FC" "B55435697A26E622E0E05D1ADB43CDE1F438979B3F7264D94A9C3640A8BA87A8" "1D3F917C1238AC025A929F862212A2CCB9F3A9A0D153E634195145E24160564D" "F84D38731206AEEC5B9F4120F5DF56C6500D0ABB9BB5B7EAAF890E875827EAB0" "A7C5761C67CA41D405A41D330B36601D94CC507787E6939EEB8345EB6A8BE7D7" "5DBD458877DC4414120C4F6AFAC87F8C15CC2CD02EEB40BF12176422437438D1" "E938CFF9F2196FDDB68D17E8ECDE577F105427009A9C31B7D944128B5E610635" "69367F5194E50B7D583FEEA7BE7B0B36BCDC2C0BC100F47820FE43061B1EBD64" "C2EFCDE9CDCDB1E59ABCE72882EE0295B35C26E5648846DA0E68E291EEEB1A91" "21AF9025F060AE6AD07A2805DE4E0D84B88D4FB1DE0CB6D5604614C1180AE4CE" "525983A8C3D3F42932575E7F89B28BC6011116667A80A8AEB0DEEBEEF545569C" "A4B1BAC6D2355D9DB3BAC1090A267C7E4E7F8292D7FE00000000000000000000" "0000000000000000000000070E101D252B3036"), }, }; for (const TestVector& v : dilithium_aes_vectors) { // Create a new verifier. absl::StatusOr> verifier = DilithiumAvx2Verify::New(*DilithiumPublicKeyPqclean::NewPublicKey( v.public_key, DilithiumSeedExpansion::SEED_EXPANSION_AES)); ASSERT_THAT(verifier, IsOk()); // Verify signature. Status status = (*verifier)->Verify(v.signature, v.message); EXPECT_THAT(status, IsOk()); } } INSTANTIATE_TEST_SUITE_P( DilithiumAvx2VerifyTests, DilithiumAvx2VerifyTest, testing::ValuesIn({ {"Dilithium2", PQCLEAN_DILITHIUM2_CRYPTO_SECRETKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE}, {"Dilithium3", PQCLEAN_DILITHIUM3_CRYPTO_SECRETKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE}, {"Dilithium5", PQCLEAN_DILITHIUM5_CRYPTO_SECRETKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE}, {"Dilithium2Aes", PQCLEAN_DILITHIUM2AES_CRYPTO_SECRETKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_AES}, {"Dilithium3Aes", PQCLEAN_DILITHIUM3AES_CRYPTO_SECRETKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_AES}, {"Dilithium5Aes", PQCLEAN_DILITHIUM5AES_CRYPTO_SECRETKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_AES}, }), [](const testing::TestParamInfo& info) { return info.param.test_name; }); } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/dilithium_key.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/subtle/dilithium_key.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" extern "C" { #include "third_party/pqclean/crypto_sign/dilithium2/api.h" #include "third_party/pqclean/crypto_sign/dilithium2aes/api.h" #include "third_party/pqclean/crypto_sign/dilithium3/api.h" #include "third_party/pqclean/crypto_sign/dilithium3aes/api.h" #include "third_party/pqclean/crypto_sign/dilithium5/api.h" #include "third_party/pqclean/crypto_sign/dilithium5aes/api.h" } namespace crypto { namespace tink { namespace subtle { // static util::StatusOr DilithiumPrivateKeyPqclean::NewPrivateKey( util::SecretData key_data, DilithiumSeedExpansion seed_expansion) { return DilithiumPrivateKeyPqclean(key_data, seed_expansion); } // static util::StatusOr> DilithiumPrivateKeyPqclean::GenerateKeyPair( int32_t private_key_size, DilithiumSeedExpansion seed_expansion) { std::string public_key; std::string private_key; private_key.resize(private_key_size); // Check if the key_size parameter is correct. switch (private_key_size) { // Dilithium2. case PQCLEAN_DILITHIUM2_CRYPTO_SECRETKEYBYTES: { switch (seed_expansion) { case DilithiumSeedExpansion::SEED_EXPANSION_AES: { public_key.resize(PQCLEAN_DILITHIUM2AES_CRYPTO_PUBLICKEYBYTES); PQCLEAN_DILITHIUM2AES_crypto_sign_keypair( reinterpret_cast(public_key.data()), reinterpret_cast(private_key.data())); break; } case DilithiumSeedExpansion::SEED_EXPANSION_SHAKE: { public_key.resize(PQCLEAN_DILITHIUM2_CRYPTO_PUBLICKEYBYTES); PQCLEAN_DILITHIUM2_crypto_sign_keypair( reinterpret_cast(public_key.data()), reinterpret_cast(private_key.data())); break; } default: { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid seed expansion"); } } break; } // Dilithium3. case PQCLEAN_DILITHIUM3_CRYPTO_SECRETKEYBYTES: { switch (seed_expansion) { case DilithiumSeedExpansion::SEED_EXPANSION_AES: { public_key.resize(PQCLEAN_DILITHIUM3AES_CRYPTO_PUBLICKEYBYTES); PQCLEAN_DILITHIUM3AES_crypto_sign_keypair( reinterpret_cast(public_key.data()), reinterpret_cast(private_key.data())); break; } case DilithiumSeedExpansion::SEED_EXPANSION_SHAKE: { public_key.resize(PQCLEAN_DILITHIUM3_CRYPTO_PUBLICKEYBYTES); PQCLEAN_DILITHIUM3_crypto_sign_keypair( reinterpret_cast(public_key.data()), reinterpret_cast(private_key.data())); break; } default: { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid seed expansion"); } } break; } // Dilithium5. case PQCLEAN_DILITHIUM5_CRYPTO_SECRETKEYBYTES: { switch (seed_expansion) { case DilithiumSeedExpansion::SEED_EXPANSION_AES: { public_key.resize(PQCLEAN_DILITHIUM5AES_CRYPTO_PUBLICKEYBYTES); PQCLEAN_DILITHIUM5AES_crypto_sign_keypair( reinterpret_cast(public_key.data()), reinterpret_cast(private_key.data())); break; } case DilithiumSeedExpansion::SEED_EXPANSION_SHAKE: { public_key.resize(PQCLEAN_DILITHIUM5_CRYPTO_PUBLICKEYBYTES); PQCLEAN_DILITHIUM5_crypto_sign_keypair( reinterpret_cast(public_key.data()), reinterpret_cast(private_key.data())); break; } default: { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid seed expansion"); } } break; } // Invalid key size. default: { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrFormat("Invalid private key size (%d). " "The only valid sizes are %d, %d, %d.", private_key_size, PQCLEAN_DILITHIUM2_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM3_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM5_CRYPTO_SECRETKEYBYTES)); } } util::SecretData private_key_data = util::SecretDataFromStringView(private_key); util::StatusOr dilithium_private_key = DilithiumPrivateKeyPqclean::NewPrivateKey(std::move(private_key_data), seed_expansion); util::StatusOr dilithium_public_key = DilithiumPublicKeyPqclean::NewPublicKey(public_key, seed_expansion); return std::make_pair(*dilithium_private_key, *dilithium_public_key); } const util::SecretData& DilithiumPrivateKeyPqclean::GetKeyData() const { return key_data_; } const DilithiumSeedExpansion& DilithiumPrivateKeyPqclean::GetSeedExpansion() const { return seed_expansion_; } // static util::StatusOr DilithiumPublicKeyPqclean::NewPublicKey(absl::string_view key_data, DilithiumSeedExpansion seed_expansion) { return DilithiumPublicKeyPqclean(key_data, seed_expansion); } const std::string& DilithiumPublicKeyPqclean::GetKeyData() const { return key_data_; } const DilithiumSeedExpansion& DilithiumPublicKeyPqclean::GetSeedExpansion() const { return seed_expansion_; } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/dilithium_key.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_DILITHIUM_KEY_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_DILITHIUM_KEY_H_ #include #include #include #include #include #include "absl/strings/string_view.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { enum class DilithiumSeedExpansion { SEED_EXPANSION_UNKNOWN = 0, SEED_EXPANSION_SHAKE = 1, SEED_EXPANSION_AES = 2, }; // Dilithium public key representation. class DilithiumPublicKeyPqclean { public: // Creates a new DilithiumPublicKeyPqclean from key_data. Should only be // called with the result of a previous call to GetKeyData(). static util::StatusOr NewPublicKey( absl::string_view key_data, DilithiumSeedExpansion seed_expansion); DilithiumPublicKeyPqclean(const DilithiumPublicKeyPqclean& other) = default; DilithiumPublicKeyPqclean& operator=(const DilithiumPublicKeyPqclean& other) = default; const std::string& GetKeyData() const; const DilithiumSeedExpansion& GetSeedExpansion() const; private: DilithiumPublicKeyPqclean(absl::string_view key_data, DilithiumSeedExpansion seed_expansion) : key_data_(key_data), seed_expansion_(seed_expansion) {} const std::string key_data_; const DilithiumSeedExpansion seed_expansion_; }; // Dilithium private key representation. class DilithiumPrivateKeyPqclean { public: // Creates a new DilithiumPrivateKeyPqclean from key_data. Should only be // called with the result of a previous call to GetKeyData(). static util::StatusOr NewPrivateKey( util::SecretData key_data, DilithiumSeedExpansion seed_expansion); DilithiumPrivateKeyPqclean(const DilithiumPrivateKeyPqclean& other) = default; DilithiumPrivateKeyPqclean& operator=( const DilithiumPrivateKeyPqclean& other) = default; // Generates a new dilithium key pair (different key sizes based on version). // Possible values for the private key size are: // 2528 - Dilithium2 // 4000 - Dilithium3 // 4864 - Dilithium5 static util::StatusOr< std::pair> GenerateKeyPair(int32_t key_size, DilithiumSeedExpansion seed_expansion); const util::SecretData& GetKeyData() const; const DilithiumSeedExpansion& GetSeedExpansion() const; private: DilithiumPrivateKeyPqclean(util::SecretData key_data, DilithiumSeedExpansion seed_expansion) : key_data_(std::move(key_data)), seed_expansion_(seed_expansion) {} const util::SecretData key_data_; const DilithiumSeedExpansion seed_expansion_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_DILITHIUM_KEY_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/dilithium_key_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/subtle/dilithium_key.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/str_cat.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" extern "C" { #include "third_party/pqclean/crypto_sign/dilithium2/api.h" #include "third_party/pqclean/crypto_sign/dilithium2aes/api.h" #include "third_party/pqclean/crypto_sign/dilithium3/api.h" #include "third_party/pqclean/crypto_sign/dilithium3aes/api.h" #include "third_party/pqclean/crypto_sign/dilithium5/api.h" #include "third_party/pqclean/crypto_sign/dilithium5aes/api.h" } namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::IsOk; struct DilithiumTestCase { std::string test_name; int32_t private_key_size; int32_t public_key_size; DilithiumSeedExpansion seed_expansion; }; using DilithiumKeyTest = testing::TestWithParam; TEST_P(DilithiumKeyTest, DilithiumKeysLength) { const DilithiumTestCase& test_case = GetParam(); // Generate key pair. util::StatusOr< std::pair> key_pair = DilithiumPrivateKeyPqclean::GenerateKeyPair( test_case.private_key_size, test_case.seed_expansion); ASSERT_THAT(key_pair, IsOk()); // Check keys size. EXPECT_EQ((key_pair->first).GetKeyData().size(), test_case.private_key_size); EXPECT_EQ((key_pair->second).GetKeyData().size(), test_case.public_key_size); } TEST_P(DilithiumKeyTest, DifferentContent) { const DilithiumTestCase& test_case = GetParam(); // Generate key pair. util::StatusOr< std::pair> key_pair = DilithiumPrivateKeyPqclean::GenerateKeyPair( test_case.private_key_size, test_case.seed_expansion); ASSERT_THAT(key_pair, IsOk()); // Check keys content is different. EXPECT_NE(util::SecretDataAsStringView(key_pair->first.GetKeyData()), key_pair->second.GetKeyData()); } INSTANTIATE_TEST_SUITE_P( DilithiumKeyTesta, DilithiumKeyTest, testing::ValuesIn({ {"Dilithium2", PQCLEAN_DILITHIUM2_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM2_CRYPTO_PUBLICKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE}, {"Dilithium3", PQCLEAN_DILITHIUM3_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM3_CRYPTO_PUBLICKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE}, {"Dilithium5", PQCLEAN_DILITHIUM5_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM5_CRYPTO_PUBLICKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_SHAKE}, {"Dilithium2Aes", PQCLEAN_DILITHIUM2AES_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM2AES_CRYPTO_PUBLICKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_AES}, {"Dilithium3Aes", PQCLEAN_DILITHIUM3AES_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM3AES_CRYPTO_PUBLICKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_AES}, {"Dilithium5Aes", PQCLEAN_DILITHIUM5AES_CRYPTO_SECRETKEYBYTES, PQCLEAN_DILITHIUM5AES_CRYPTO_PUBLICKEYBYTES, DilithiumSeedExpansion::SEED_EXPANSION_AES}, }), [](const testing::TestParamInfo& info) { return info.param.test_name; }); } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/falcon_sign.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/subtle/falcon_sign.h" #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "tink/experimental/pqcrypto/signature/subtle/falcon_subtle_utils.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_sign.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" extern "C" { #include "third_party/pqclean/crypto_sign/falcon-1024/api.h" #include "third_party/pqclean/crypto_sign/falcon-512/api.h" } namespace crypto { namespace tink { namespace subtle { // static util::StatusOr> FalconSign::New( const FalconPrivateKeyPqclean& key) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) return status; return {absl::WrapUnique(new FalconSign(key))}; } util::StatusOr FalconSign::Sign(absl::string_view data) const { size_t sig_length; int32_t key_size = private_key_.GetKey().size(); std::string signature; int result = 1; switch (key_size) { case kFalcon512PrivateKeySize: { signature.resize(PQCLEAN_FALCON512_CRYPTO_BYTES, '0'); result = PQCLEAN_FALCON512_crypto_sign_signature( reinterpret_cast(signature.data()), &sig_length, reinterpret_cast(data.data()), data.size(), reinterpret_cast(private_key_.GetKey().data())); if (sig_length > PQCLEAN_FALCON512_CRYPTO_BYTES) { result = -1; } break; } case kFalcon1024PrivateKeySize: { signature.resize(PQCLEAN_FALCON1024_CRYPTO_BYTES, '0'); result = PQCLEAN_FALCON1024_crypto_sign_signature( reinterpret_cast(signature.data()), &sig_length, reinterpret_cast(data.data()), data.size(), reinterpret_cast(private_key_.GetKey().data())); if (sig_length > PQCLEAN_FALCON1024_CRYPTO_BYTES) { result = -1; } break; } default: return util::Status(absl::StatusCode::kInvalidArgument, "Invalid keysize."); } if (result != 0) { return util::Status(absl::StatusCode::kInternal, "Signing failed."); } signature.resize(sig_length); return signature; } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/falcon_sign.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_FALCON_SIGN_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_FALCON_SIGN_H_ #include #include #include #include "absl/strings/string_view.h" #include "tink/experimental/pqcrypto/signature/subtle/falcon_subtle_utils.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_sign.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // Post-Quantum Signing using Falcon - Fast-Fourier Lattice-based // Compact Signature over NTRU class FalconSign : public PublicKeySign { public: static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kNotFips; static crypto::tink::util::StatusOr> New( const FalconPrivateKeyPqclean& private_key); ~FalconSign() override = default; // Computes the signature for 'data'. crypto::tink::util::StatusOr Sign( absl::string_view data) const override; private: explicit FalconSign(const FalconPrivateKeyPqclean& private_key) : private_key_(private_key) {} const FalconPrivateKeyPqclean private_key_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_FALCON_SIGN_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/falcon_sign_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/subtle/falcon_sign.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/config/tink_fips.h" #include "tink/experimental/pqcrypto/signature/subtle/falcon_subtle_utils.h" #include "tink/public_key_sign.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" extern "C" { #include "third_party/pqclean/crypto_sign/falcon-1024/api.h" #include "third_party/pqclean/crypto_sign/falcon-512/api.h" } namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::IsOk; struct FalconTestCase { std::string test_name; int32_t private_key_size; int32_t signature_length; }; using FalconSignTest = testing::TestWithParam; TEST_P(FalconSignTest, ValidSignatureLength) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } const FalconTestCase& test_case = GetParam(); // Generate falcon key pair. util::StatusOr key_pair = GenerateFalconKeyPair(test_case.private_key_size); ASSERT_THAT(key_pair, IsOk()); // Create a new signer. util::StatusOr> signer = FalconSign::New(key_pair->GetPrivateKey()); ASSERT_THAT(signer, IsOk()); // Sign a message. std::string message = "message to be signed"; util::StatusOr signature = ((*signer)->Sign(message)); ASSERT_THAT(signature, IsOk()); // Check signature size. EXPECT_NE(*signature, message); EXPECT_LE((*signature).size(), test_case.signature_length); } TEST_P(FalconSignTest, NonDeterminism) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } const FalconTestCase& test_case = GetParam(); // Generate falcon key pair. util::StatusOr key_pair = GenerateFalconKeyPair(test_case.private_key_size); ASSERT_THAT(key_pair, IsOk()); // Create two signers based on same private key. util::StatusOr> signer = FalconSign::New(key_pair->GetPrivateKey()); ASSERT_THAT(signer, IsOk()); // Sign the same message twice, using the same private key. std::string message = "message to be signed"; util::StatusOr first_signature = ((*signer))->Sign(message); ASSERT_THAT(first_signature, IsOk()); util::StatusOr second_signature = ((*signer))->Sign(message); ASSERT_THAT(second_signature, IsOk()); // Check signatures size. EXPECT_NE(*first_signature, message); EXPECT_LE((*first_signature).size(), test_case.signature_length); EXPECT_NE(*second_signature, message); EXPECT_LE((*second_signature).size(), test_case.signature_length); // Check if signatures are equal. EXPECT_NE(*first_signature, *second_signature); } TEST_P(FalconSignTest, FipsMode) { if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips."; } const FalconTestCase& test_case = GetParam(); // Generate falcon key pair. util::StatusOr key_pair = GenerateFalconKeyPair(test_case.private_key_size); ASSERT_THAT(key_pair, IsOk()); // Create a new signer. EXPECT_THAT(FalconSign::New(key_pair->GetPrivateKey()).status(), test::StatusIs(absl::StatusCode::kInternal)); } INSTANTIATE_TEST_SUITE_P( FalconSignTests, FalconSignTest, testing::ValuesIn({{"Falcon512", kFalcon512PrivateKeySize, PQCLEAN_FALCON512_CRYPTO_BYTES}, {"Falcon1024", kFalcon1024PrivateKeySize, PQCLEAN_FALCON1024_CRYPTO_BYTES}}), [](const testing::TestParamInfo& info) { return info.param.test_name; }); } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/falcon_subtle_utils.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/subtle/falcon_subtle_utils.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_helper_pqclean.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" extern "C" { #include "third_party/pqclean/crypto_sign/falcon-1024/api.h" #include "third_party/pqclean/crypto_sign/falcon-512/api.h" } namespace crypto { namespace tink { namespace subtle { // static util::StatusOr FalconPrivateKeyPqclean::NewPrivateKey( const util::SecretData& key_data) { util::Status status = ValidateFalconPrivateKeySize(key_data.size()); if (!status.ok()) { return status; } return FalconPrivateKeyPqclean(key_data); } // static util::StatusOr FalconPublicKeyPqclean::NewPublicKey( absl::string_view key_data) { util::Status status = ValidateFalconPublicKeySize(key_data.size()); if (!status.ok()) { return status; } return FalconPublicKeyPqclean(key_data); } crypto::tink::util::StatusOr GenerateFalconKeyPair( int32_t private_key_size) { std::string public_key; std::string private_key; switch (private_key_size) { // Falcon512. case kFalcon512PrivateKeySize: { private_key.resize(private_key_size); public_key.resize(kFalcon512PublicKeySize); PQCLEAN_FALCON512_crypto_sign_keypair( reinterpret_cast(public_key.data()), reinterpret_cast(private_key.data())); break; } // Falcon1024. case kFalcon1024PrivateKeySize: { private_key.resize(private_key_size); public_key.resize(kFalcon1024PublicKeySize); PQCLEAN_FALCON1024_crypto_sign_keypair( reinterpret_cast(public_key.data()), reinterpret_cast(private_key.data())); break; } // Invalid key size. default: { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrFormat("Invalid private key size (%d). " "The only valid sizes are %d, %d", private_key_size, kFalcon512PrivateKeySize, kFalcon1024PrivateKeySize)); } } util::SecretData private_key_data = util::SecretDataFromStringView(private_key); util::StatusOr falcon_private_key = FalconPrivateKeyPqclean::NewPrivateKey(private_key_data); util::StatusOr falcon_public_key = FalconPublicKeyPqclean::NewPublicKey(public_key); if (!falcon_private_key.ok() || !falcon_public_key.ok()) { return util::Status(absl::StatusCode::kInternal, "Key generation failed."); } FalconKeyPair key_pair(*falcon_private_key, *falcon_public_key); return key_pair; } crypto::tink::util::Status ValidateFalconPrivateKeySize(int32_t key_size) { switch (key_size) { case kFalcon512PrivateKeySize: case kFalcon1024PrivateKeySize: return util::OkStatus(); default: return util::Status(absl::StatusCode::kInvalidArgument, absl::StrFormat("Invalid private key size (%d). " "The only valid sizes are %d, %d", key_size, kFalcon512PrivateKeySize, kFalcon1024PrivateKeySize)); } } crypto::tink::util::Status ValidateFalconPublicKeySize(int32_t key_size) { switch (key_size) { case kFalcon512PublicKeySize: case kFalcon1024PublicKeySize: return util::OkStatus(); default: return util::Status(absl::StatusCode::kInvalidArgument, absl::StrFormat("Invalid public key size (%d). " "The only valid sizes are %d, %d", key_size, kFalcon512PublicKeySize, kFalcon1024PublicKeySize)); } } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/falcon_subtle_utils.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_FALCON_SUBTLE_UTILS_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_FALCON_SUBTLE_UTILS_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // The two possible falcon private key sizes, as defined at // https://falcon-sign.info/. const int kFalcon512PrivateKeySize = 1281; const int kFalcon1024PrivateKeySize = 2305; // The two possible falcon public key sizes as defined at // https://falcon-sign.info/. const int kFalcon512PublicKeySize = 897; const int kFalcon1024PublicKeySize = 1793; // Representation of the Falcon private key. class FalconPrivateKeyPqclean { public: // Creates a new FalconPrivateKeyPqclean from key_data. static util::StatusOr NewPrivateKey( const util::SecretData& key_data); FalconPrivateKeyPqclean(const FalconPrivateKeyPqclean& other) = default; FalconPrivateKeyPqclean& operator=(const FalconPrivateKeyPqclean& other) = default; const util::SecretData& GetKey() const { return key_data_; } private: explicit FalconPrivateKeyPqclean(const util::SecretData& key_data) : key_data_(key_data) {} const util::SecretData key_data_; }; // Representation of the Falcon public key. class FalconPublicKeyPqclean { public: // Creates a new FalconPublicKeyPqclean from key_data. static util::StatusOr NewPublicKey( absl::string_view key_data); FalconPublicKeyPqclean(const FalconPublicKeyPqclean& other) = default; FalconPublicKeyPqclean& operator=(const FalconPublicKeyPqclean& other) = default; const std::string& GetKey() const { return key_data_; } private: explicit FalconPublicKeyPqclean(absl::string_view key_data) : key_data_(std::move(key_data)) {} const std::string key_data_; }; class FalconKeyPair { public: FalconKeyPair(FalconPrivateKeyPqclean private_key, FalconPublicKeyPqclean public_key) : private_key_(std::move(private_key)), public_key_(std::move(public_key)) {} FalconKeyPair(const FalconKeyPair& other) = default; FalconKeyPair& operator=(const FalconKeyPair& other) = default; const FalconPrivateKeyPqclean& GetPrivateKey() const { return private_key_; } const FalconPublicKeyPqclean& GetPublicKey() const { return public_key_; } private: const FalconPrivateKeyPqclean private_key_; const FalconPublicKeyPqclean public_key_; }; // This is an utility function that generates a new Falcon key pair. // This function is expected to be called from a key manager class. crypto::tink::util::StatusOr GenerateFalconKeyPair( int32_t private_key_size); // Validates whether the private key size is safe to use for falcon signature. crypto::tink::util::Status ValidateFalconPrivateKeySize(int32_t key_size); // Validates whether the public key size is safe to use for falcon signature. crypto::tink::util::Status ValidateFalconPublicKeySize(int32_t key_size); } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_FALCON_SUBTLE_UTILS_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/falcon_subtle_utils_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/subtle/falcon_subtle_utils.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/str_cat.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::IsOk; using ::testing::Not; struct FalconTestCase { std::string test_name; int32_t private_key_size; int32_t public_key_size; }; using FalconUtilsTest = testing::TestWithParam; TEST_P(FalconUtilsTest, FalconKeyGeneration) { const FalconTestCase& test_case = GetParam(); // Generate falcon key pair. util::StatusOr key_pair = GenerateFalconKeyPair(test_case.private_key_size); ASSERT_THAT(key_pair, IsOk()); // Check keys size. EXPECT_EQ(key_pair->GetPrivateKey().GetKey().size(), test_case.private_key_size); EXPECT_EQ(key_pair->GetPublicKey().GetKey().size(), test_case.public_key_size); } TEST_P(FalconUtilsTest, DifferentContent) { const FalconTestCase& test_case = GetParam(); // Generate falcon key pair. util::StatusOr key_pair = GenerateFalconKeyPair(test_case.private_key_size); ASSERT_THAT(key_pair, IsOk()); // Check keys content is different. EXPECT_NE(util::SecretDataAsStringView(key_pair->GetPrivateKey().GetKey()), key_pair->GetPublicKey().GetKey()); } TEST(FalconUtilsTest, ValidPrivateKeySize) { EXPECT_THAT(ValidateFalconPrivateKeySize(kFalcon1024PrivateKeySize), IsOk()); EXPECT_THAT(ValidateFalconPrivateKeySize(kFalcon512PrivateKeySize), IsOk()); } TEST(FalconUtilsTest, InvalidPrivateKeySize) { std::vector invalid_keysizes{0, -1, kFalcon1024PrivateKeySize - 1, kFalcon1024PrivateKeySize + 1, INT_MAX, INT_MIN}; for (int i = 0; i < invalid_keysizes.size(); i++) { EXPECT_FALSE(ValidateFalconPrivateKeySize(invalid_keysizes[i]).ok()); } } TEST(FalconUtilsTest, ValidPublicKeySize) { EXPECT_THAT(ValidateFalconPublicKeySize(kFalcon1024PublicKeySize), IsOk()); EXPECT_THAT(ValidateFalconPublicKeySize(kFalcon512PublicKeySize), IsOk()); } TEST(FalconUtilsTest, InvalidPublicKeySize) { std::vector invalid_keysizes{0, -1, kFalcon1024PublicKeySize - 1, kFalcon1024PublicKeySize + 1, INT_MAX, INT_MIN}; for (int i = 0; i < invalid_keysizes.size(); i++) { EXPECT_FALSE(ValidateFalconPublicKeySize(invalid_keysizes[i]).ok()); } } TEST(FalconUtilsTest, InvalidPrivateKey) { std::string bad_private_key_data = "bad private key"; util::StatusOr private_key = FalconPrivateKeyPqclean::NewPrivateKey( util::SecretDataFromStringView(bad_private_key_data)); EXPECT_THAT(private_key.status(), testing::Not(IsOk())); } TEST(FalconUtilsTest, InvalidPubliceKey) { std::string bad_public_key_data = "bad public key"; util::StatusOr public_key = FalconPublicKeyPqclean::NewPublicKey(bad_public_key_data); EXPECT_THAT(public_key, Not(IsOk())); } INSTANTIATE_TEST_SUITE_P( FalconUtilsTests, FalconUtilsTest, testing::ValuesIn( {{"Falcon512", kFalcon512PrivateKeySize, kFalcon512PublicKeySize}, {"Falcon1024", kFalcon1024PrivateKeySize, kFalcon1024PublicKeySize}}), [](const testing::TestParamInfo& info) { return info.param.test_name; }); } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/falcon_verify.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/subtle/falcon_verify.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "tink/experimental/pqcrypto/signature/subtle/falcon_subtle_utils.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_verify.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" extern "C" { #include "third_party/pqclean/crypto_sign/falcon-1024/api.h" #include "third_party/pqclean/crypto_sign/falcon-512/api.h" } namespace crypto { namespace tink { namespace subtle { // static util::StatusOr> FalconVerify::New( const FalconPublicKeyPqclean& public_key) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) return status; return { absl::WrapUnique(new FalconVerify(public_key))}; } util::Status FalconVerify::Verify(absl::string_view signature, absl::string_view data) const { int32_t key_size = public_key_.GetKey().size(); int result = 1; switch (key_size) { case kFalcon512PublicKeySize: { result = PQCLEAN_FALCON512_crypto_sign_verify( reinterpret_cast(signature.data()), signature.size(), reinterpret_cast(data.data()), data.size(), reinterpret_cast(public_key_.GetKey().data())); break; } case kFalcon1024PublicKeySize: { result = PQCLEAN_FALCON1024_crypto_sign_verify( reinterpret_cast(signature.data()), signature.size(), reinterpret_cast(data.data()), data.size(), reinterpret_cast(public_key_.GetKey().data())); break; } default: return util::Status(absl::StatusCode::kInvalidArgument, "Invalid keysize."); } if (result != 0) { return util::Status(absl::StatusCode::kInternal, "Signature is not valid."); } return util::OkStatus(); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/falcon_verify.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_FALCON_VERIFY_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_FALCON_VERIFY_H_ #include #include #include #include "absl/strings/string_view.h" #include "tink/experimental/pqcrypto/signature/subtle/falcon_subtle_utils.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_verify.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { class FalconVerify : public PublicKeyVerify { public: static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kNotFips; static crypto::tink::util::StatusOr> New( const FalconPublicKeyPqclean& public_key); // Verifies that 'signature' is a digital signature for 'data'. crypto::tink::util::Status Verify(absl::string_view signature, absl::string_view data) const override; private: explicit FalconVerify(const FalconPublicKeyPqclean& public_key) : public_key_(public_key) {} const FalconPublicKeyPqclean public_key_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_FALCON_VERIFY_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/falcon_verify_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/subtle/falcon_verify.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "tink/config/tink_fips.h" #include "tink/experimental/pqcrypto/signature/subtle/falcon_sign.h" #include "tink/experimental/pqcrypto/signature/subtle/falcon_subtle_utils.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" extern "C" { #include "third_party/pqclean/crypto_sign/falcon-1024/api.h" #include "third_party/pqclean/crypto_sign/falcon-512/api.h" } namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using crypto::tink::util::Status; struct FalconTestCase { std::string test_name; int32_t private_key_size; int32_t signature_length; }; using FalconVerifyTest = testing::TestWithParam; TEST_P(FalconVerifyTest, BasicSignVerify) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } const FalconTestCase& test_case = GetParam(); // Generate falcon key pair. util::StatusOr key_pair = GenerateFalconKeyPair(test_case.private_key_size); ASSERT_THAT(key_pair, IsOk()); // Create a new signer. util::StatusOr> signer = FalconSign::New(key_pair->GetPrivateKey()); ASSERT_THAT(signer, IsOk()); // Sign a message. std::string message = "message to be signed"; util::StatusOr signature = (*signer)->Sign(message); ASSERT_THAT(signature, IsOk()); // Create a new verifier. absl::StatusOr> verifier = FalconVerify::New(key_pair->GetPublicKey()); ASSERT_THAT(verifier, IsOk()); // Verify signature. Status status = (*verifier)->Verify(*signature, message); EXPECT_THAT(status, IsOk()); } TEST_P(FalconVerifyTest, FailsWithWrongSignature) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } const FalconTestCase& test_case = GetParam(); // Generate falcon key pair. util::StatusOr key_pair = GenerateFalconKeyPair(test_case.private_key_size); ASSERT_THAT(key_pair, IsOk()); // Create a new signer. util::StatusOr> signer = FalconSign::New(key_pair->GetPrivateKey()); ASSERT_THAT(signer, IsOk()); // Sign a message. std::string message = "message to be signed"; util::StatusOr signature = (*signer)->Sign(message); ASSERT_THAT(signature, IsOk()); // Create a new verifier. absl::StatusOr> verifier = FalconVerify::New(key_pair->GetPublicKey()); ASSERT_THAT(verifier, IsOk()); // Verify signature. Status status = (*verifier)->Verify(*signature + "some trailing data", message); EXPECT_FALSE(status.ok()); } TEST_P(FalconVerifyTest, FailsWithWrongMessage) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } const FalconTestCase& test_case = GetParam(); // Generate falcon key pair. util::StatusOr key_pair = GenerateFalconKeyPair(test_case.private_key_size); ASSERT_THAT(key_pair, IsOk()); // Create a new signer. util::StatusOr> signer = FalconSign::New(key_pair->GetPrivateKey()); ASSERT_THAT(signer, IsOk()); // Sign a message. std::string message = "message to be signed"; util::StatusOr signature = (*signer)->Sign(message); ASSERT_THAT(signature, IsOk()); // Create a new verifier. absl::StatusOr> verifier = FalconVerify::New(key_pair->GetPublicKey()); ASSERT_THAT(verifier, IsOk()); // Verify signature. Status status = (*verifier)->Verify(*signature, "some bad message"); EXPECT_FALSE(status.ok()); } TEST_P(FalconVerifyTest, FailsWithBytesFlipped) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } const FalconTestCase& test_case = GetParam(); // Generate falcon key pair. util::StatusOr key_pair = GenerateFalconKeyPair(test_case.private_key_size); ASSERT_THAT(key_pair, IsOk()); // Create a new signer. util::StatusOr> signer = FalconSign::New(key_pair->GetPrivateKey()); ASSERT_THAT(signer, IsOk()); // Sign a message. std::string message = "message to be signed"; util::StatusOr signature = (*signer)->Sign(message); ASSERT_THAT(signature, IsOk()); // Create a new verifier. absl::StatusOr> verifier = FalconVerify::New(key_pair->GetPublicKey()); ASSERT_THAT(verifier, IsOk()); // Invalidate one signature byte. (*signature)[0] ^= 1; // Verify signature. Status status = (*verifier)->Verify(*signature, message); EXPECT_FALSE(status.ok()); } TEST_P(FalconVerifyTest, FipsMode) { if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips."; } const FalconTestCase& test_case = GetParam(); // Generate falcon key pair. util::StatusOr key_pair = GenerateFalconKeyPair(test_case.private_key_size); ASSERT_THAT(key_pair, IsOk()); // Create a new signer. EXPECT_THAT(FalconVerify::New(key_pair->GetPublicKey()).status(), StatusIs(absl::StatusCode::kInternal)); } INSTANTIATE_TEST_SUITE_P( FalconVerifyTests, FalconVerifyTest, testing::ValuesIn({{"Falcon512", kFalcon512PrivateKeySize, PQCLEAN_FALCON512_CRYPTO_BYTES}, {"Falcon1024", kFalcon1024PrivateKeySize, PQCLEAN_FALCON1024_CRYPTO_BYTES}}), [](const testing::TestParamInfo& info) { return info.param.test_name; }); } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/sphincs_helper_pqclean.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/subtle/sphincs_helper_pqclean.h" #include #include #include #include #include "absl/memory/memory.h" extern "C" { #include "third_party/pqclean/crypto_sign/sphincs-haraka-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256s-simple/api.h" } #define NUM_VARIANTS 2 #define NUM_KEY_SIZES 3 #define NUM_SIG_LENGTHS 2 namespace crypto { namespace tink { namespace subtle { class SphincsHaraka128FRobustPqclean : public SphincsHelperPqclean { public: SphincsHaraka128FRobustPqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSHARAKA128FROBUST_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSHARAKA128FROBUST_CRYPTO_BYTES) {} ~SphincsHaraka128FRobustPqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA128FROBUST_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSHARAKA128FROBUST_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA128FROBUST_crypto_sign_keypair(pk, sk); } }; class SphincsHaraka128SRobustPqclean : public SphincsHelperPqclean { public: SphincsHaraka128SRobustPqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSHARAKA128SROBUST_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSHARAKA128SROBUST_CRYPTO_BYTES) {} ~SphincsHaraka128SRobustPqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA128SROBUST_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSHARAKA128SROBUST_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA128SROBUST_crypto_sign_keypair(pk, sk); } }; class SphincsHaraka128FSimplePqclean : public SphincsHelperPqclean { public: SphincsHaraka128FSimplePqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSHARAKA128FSIMPLE_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CRYPTO_BYTES) {} ~SphincsHaraka128FSimplePqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA128FSIMPLE_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSHARAKA128FSIMPLE_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA128FSIMPLE_crypto_sign_keypair(pk, sk); } }; class SphincsHaraka128SSimplePqclean : public SphincsHelperPqclean { public: SphincsHaraka128SSimplePqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSHARAKA128SSIMPLE_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CRYPTO_BYTES) {} ~SphincsHaraka128SSimplePqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA128SSIMPLE_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSHARAKA128SSIMPLE_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA128SSIMPLE_crypto_sign_keypair(pk, sk); } }; class SphincsHaraka192FRobustPqclean : public SphincsHelperPqclean { public: SphincsHaraka192FRobustPqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSHARAKA192FROBUST_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSHARAKA192FROBUST_CRYPTO_BYTES) {} ~SphincsHaraka192FRobustPqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA192FROBUST_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSHARAKA192FROBUST_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA192FROBUST_crypto_sign_keypair(pk, sk); } }; class SphincsHaraka192SRobustPqclean : public SphincsHelperPqclean { public: SphincsHaraka192SRobustPqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSHARAKA192SROBUST_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSHARAKA192SROBUST_CRYPTO_BYTES) {} ~SphincsHaraka192SRobustPqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA192SROBUST_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSHARAKA192SROBUST_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA192SROBUST_crypto_sign_keypair(pk, sk); } }; class SphincsHaraka192FSimplePqclean : public SphincsHelperPqclean { public: SphincsHaraka192FSimplePqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSHARAKA192FSIMPLE_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CRYPTO_BYTES) {} ~SphincsHaraka192FSimplePqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA192FSIMPLE_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSHARAKA192FSIMPLE_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA192FSIMPLE_crypto_sign_keypair(pk, sk); } }; class SphincsHaraka192SSimplePqclean : public SphincsHelperPqclean { public: SphincsHaraka192SSimplePqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSHARAKA192SSIMPLE_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CRYPTO_BYTES) {} ~SphincsHaraka192SSimplePqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA192SSIMPLE_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSHARAKA192SSIMPLE_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA192SSIMPLE_crypto_sign_keypair(pk, sk); } }; class SphincsHaraka256FRobustPqclean : public SphincsHelperPqclean { public: SphincsHaraka256FRobustPqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSHARAKA256FROBUST_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSHARAKA256FROBUST_CRYPTO_BYTES) {} ~SphincsHaraka256FRobustPqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA256FROBUST_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSHARAKA256FROBUST_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA256FROBUST_crypto_sign_keypair(pk, sk); } }; class SphincsHaraka256SRobustPqclean : public SphincsHelperPqclean { public: SphincsHaraka256SRobustPqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSHARAKA256SROBUST_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSHARAKA256SROBUST_CRYPTO_BYTES) {} ~SphincsHaraka256SRobustPqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA256SROBUST_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSHARAKA256SROBUST_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA256SROBUST_crypto_sign_keypair(pk, sk); } }; class SphincsHaraka256FSimplePqclean : public SphincsHelperPqclean { public: SphincsHaraka256FSimplePqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSHARAKA256FSIMPLE_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CRYPTO_BYTES) {} ~SphincsHaraka256FSimplePqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA256FSIMPLE_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSHARAKA256FSIMPLE_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA256FSIMPLE_crypto_sign_keypair(pk, sk); } }; class SphincsHaraka256SSimplePqclean : public SphincsHelperPqclean { public: SphincsHaraka256SSimplePqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSHARAKA256SSIMPLE_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CRYPTO_BYTES) {} ~SphincsHaraka256SSimplePqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA256SSIMPLE_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSHARAKA256SSIMPLE_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSHARAKA256SSIMPLE_crypto_sign_keypair(pk, sk); } }; class SphincsSHA256128FRobustPqclean : public SphincsHelperPqclean { public: SphincsSHA256128FRobustPqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHA256128FROBUST_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHA256128FROBUST_CRYPTO_BYTES) {} ~SphincsSHA256128FRobustPqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256128FROBUST_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHA256128FROBUST_crypto_sign_verify(sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256128FROBUST_crypto_sign_keypair(pk, sk); } }; class SphincsSHA256128SRobustPqclean : public SphincsHelperPqclean { public: SphincsSHA256128SRobustPqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHA256128SROBUST_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHA256128SROBUST_CRYPTO_BYTES) {} ~SphincsSHA256128SRobustPqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256128SROBUST_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHA256128SROBUST_crypto_sign_verify(sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256128SROBUST_crypto_sign_keypair(pk, sk); } }; class SphincsSHA256128FSimplePqclean : public SphincsHelperPqclean { public: SphincsSHA256128FSimplePqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHA256128FSIMPLE_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHA256128FSIMPLE_CRYPTO_BYTES) {} ~SphincsSHA256128FSimplePqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256128FSIMPLE_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHA256128FSIMPLE_crypto_sign_verify(sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256128FSIMPLE_crypto_sign_keypair(pk, sk); } }; class SphincsSHA256128SSimplePqclean : public SphincsHelperPqclean { public: SphincsSHA256128SSimplePqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHA256128SSIMPLE_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHA256128SSIMPLE_CRYPTO_BYTES) {} ~SphincsSHA256128SSimplePqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256128SSIMPLE_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHA256128SSIMPLE_crypto_sign_verify(sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256128SSIMPLE_crypto_sign_keypair(pk, sk); } }; class SphincsSHA256192FRobustPqclean : public SphincsHelperPqclean { public: SphincsSHA256192FRobustPqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHA256192FROBUST_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHA256192FROBUST_CRYPTO_BYTES) {} ~SphincsSHA256192FRobustPqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256192FROBUST_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHA256192FROBUST_crypto_sign_verify(sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256192FROBUST_crypto_sign_keypair(pk, sk); } }; class SphincsSHA256192SRobustPqclean : public SphincsHelperPqclean { public: SphincsSHA256192SRobustPqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHA256192SROBUST_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHA256192SROBUST_CRYPTO_BYTES) {} ~SphincsSHA256192SRobustPqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256192SROBUST_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHA256192SROBUST_crypto_sign_verify(sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256192SROBUST_crypto_sign_keypair(pk, sk); } }; class SphincsSHA256192FSimplePqclean : public SphincsHelperPqclean { public: SphincsSHA256192FSimplePqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHA256192FSIMPLE_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHA256192FSIMPLE_CRYPTO_BYTES) {} ~SphincsSHA256192FSimplePqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256192FSIMPLE_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHA256192FSIMPLE_crypto_sign_verify(sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256192FSIMPLE_crypto_sign_keypair(pk, sk); } }; class SphincsSHA256192SSimplePqclean : public SphincsHelperPqclean { public: SphincsSHA256192SSimplePqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHA256192SSIMPLE_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHA256192SSIMPLE_CRYPTO_BYTES) {} ~SphincsSHA256192SSimplePqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256192SSIMPLE_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHA256192SSIMPLE_crypto_sign_verify(sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256192SSIMPLE_crypto_sign_keypair(pk, sk); } }; class SphincsSHA256256FRobustPqclean : public SphincsHelperPqclean { public: SphincsSHA256256FRobustPqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHA256256FROBUST_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHA256256FROBUST_CRYPTO_BYTES) {} ~SphincsSHA256256FRobustPqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256256FROBUST_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHA256256FROBUST_crypto_sign_verify(sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256256FROBUST_crypto_sign_keypair(pk, sk); } }; class SphincsSHA256256SRobustPqclean : public SphincsHelperPqclean { public: SphincsSHA256256SRobustPqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHA256256SROBUST_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHA256256SROBUST_CRYPTO_BYTES) {} ~SphincsSHA256256SRobustPqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256256SROBUST_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHA256256SROBUST_crypto_sign_verify(sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256256SROBUST_crypto_sign_keypair(pk, sk); } }; class SphincsSHA256256FSimplePqclean : public SphincsHelperPqclean { public: SphincsSHA256256FSimplePqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHA256256FSIMPLE_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHA256256FSIMPLE_CRYPTO_BYTES) {} ~SphincsSHA256256FSimplePqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256256FSIMPLE_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHA256256FSIMPLE_crypto_sign_verify(sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256256FSIMPLE_crypto_sign_keypair(pk, sk); } }; class SphincsSHA256256SSimplePqclean : public SphincsHelperPqclean { public: SphincsSHA256256SSimplePqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHA256256SSIMPLE_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHA256256SSIMPLE_CRYPTO_BYTES) {} ~SphincsSHA256256SSimplePqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256256SSIMPLE_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHA256256SSIMPLE_crypto_sign_verify(sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHA256256SSIMPLE_crypto_sign_keypair(pk, sk); } }; class SphincsSHAKE256128FRobustPqclean : public SphincsHelperPqclean { public: SphincsSHAKE256128FRobustPqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHAKE256128FROBUST_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHAKE256128FROBUST_CRYPTO_BYTES) {} ~SphincsSHAKE256128FRobustPqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256128FROBUST_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHAKE256128FROBUST_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256128FROBUST_crypto_sign_keypair(pk, sk); } }; class SphincsSHAKE256128SRobustPqclean : public SphincsHelperPqclean { public: SphincsSHAKE256128SRobustPqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHAKE256128SROBUST_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHAKE256128SROBUST_CRYPTO_BYTES) {} ~SphincsSHAKE256128SRobustPqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256128SROBUST_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHAKE256128SROBUST_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256128SROBUST_crypto_sign_keypair(pk, sk); } }; class SphincsSHAKE256128FSimplePqclean : public SphincsHelperPqclean { public: SphincsSHAKE256128FSimplePqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CRYPTO_BYTES) {} ~SphincsSHAKE256128FSimplePqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256128FSIMPLE_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHAKE256128FSIMPLE_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256128FSIMPLE_crypto_sign_keypair(pk, sk); } }; class SphincsSHAKE256128SSimplePqclean : public SphincsHelperPqclean { public: SphincsSHAKE256128SSimplePqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CRYPTO_BYTES) {} ~SphincsSHAKE256128SSimplePqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256128SSIMPLE_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHAKE256128SSIMPLE_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256128SSIMPLE_crypto_sign_keypair(pk, sk); } }; class SphincsSHAKE256192FRobustPqclean : public SphincsHelperPqclean { public: SphincsSHAKE256192FRobustPqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHAKE256192FROBUST_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHAKE256192FROBUST_CRYPTO_BYTES) {} ~SphincsSHAKE256192FRobustPqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256192FROBUST_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHAKE256192FROBUST_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256192FROBUST_crypto_sign_keypair(pk, sk); } }; class SphincsSHAKE256192SRobustPqclean : public SphincsHelperPqclean { public: SphincsSHAKE256192SRobustPqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHAKE256192SROBUST_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHAKE256192SROBUST_CRYPTO_BYTES) {} ~SphincsSHAKE256192SRobustPqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256192SROBUST_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHAKE256192SROBUST_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256192SROBUST_crypto_sign_keypair(pk, sk); } }; class SphincsSHAKE256192FSimplePqclean : public SphincsHelperPqclean { public: SphincsSHAKE256192FSimplePqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CRYPTO_BYTES) {} ~SphincsSHAKE256192FSimplePqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256192FSIMPLE_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHAKE256192FSIMPLE_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256192FSIMPLE_crypto_sign_keypair(pk, sk); } }; class SphincsSHAKE256192SSimplePqclean : public SphincsHelperPqclean { public: SphincsSHAKE256192SSimplePqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CRYPTO_BYTES) {} ~SphincsSHAKE256192SSimplePqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256192SSIMPLE_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHAKE256192SSIMPLE_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256192SSIMPLE_crypto_sign_keypair(pk, sk); } }; class SphincsSHAKE256256FRobustPqclean : public SphincsHelperPqclean { public: SphincsSHAKE256256FRobustPqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHAKE256256FROBUST_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHAKE256256FROBUST_CRYPTO_BYTES) {} ~SphincsSHAKE256256FRobustPqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256256FROBUST_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHAKE256256FROBUST_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256256FROBUST_crypto_sign_keypair(pk, sk); } }; class SphincsSHAKE256256SRobustPqclean : public SphincsHelperPqclean { public: SphincsSHAKE256256SRobustPqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHAKE256256SROBUST_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHAKE256256SROBUST_CRYPTO_BYTES) {} ~SphincsSHAKE256256SRobustPqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256256SROBUST_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHAKE256256SROBUST_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256256SROBUST_crypto_sign_keypair(pk, sk); } }; class SphincsSHAKE256256FSimplePqclean : public SphincsHelperPqclean { public: SphincsSHAKE256256FSimplePqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CRYPTO_BYTES) {} ~SphincsSHAKE256256FSimplePqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256256FSIMPLE_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHAKE256256FSIMPLE_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256256FSIMPLE_crypto_sign_keypair(pk, sk); } }; class SphincsSHAKE256256SSimplePqclean : public SphincsHelperPqclean { public: SphincsSHAKE256256SSimplePqclean() : SphincsHelperPqclean( PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CRYPTO_PUBLICKEYBYTES, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CRYPTO_BYTES) {} ~SphincsSHAKE256256SSimplePqclean() override = default; int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256256SSIMPLE_crypto_sign_signature( sig, siglen, m, mlen, sk); } int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const override { return PQCLEAN_SPHINCSSHAKE256256SSIMPLE_crypto_sign_verify( sig, siglen, m, mlen, pk); } int Keygen(uint8_t *pk, uint8_t *sk) const override { return PQCLEAN_SPHINCSSHAKE256256SSIMPLE_crypto_sign_keypair(pk, sk); } }; std::vector> GetSphincsPqcleanHelperArray() { std::vector> sphincs_helper_pqclean; sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); sphincs_helper_pqclean.push_back( absl::make_unique()); return sphincs_helper_pqclean; } const SphincsHelperPqclean &GetSphincsHelperPqclean(int hash_type, int variant, int key_size, int signature_length) { static std::vector> *sphincs_helper_pqclean = new std::vector(GetSphincsPqcleanHelperArray()); // Note that we have to adjust the enum values for hash_type, variant and // signature_length to start at 0. In the proto the 0 entry is for UNSPECIFIED // values, but here we require the valid enum values to start at index 0. return *sphincs_helper_pqclean->at( (hash_type - 1) * NUM_VARIANTS * NUM_KEY_SIZES * NUM_SIG_LENGTHS + key_size * NUM_VARIANTS * NUM_SIG_LENGTHS + (variant - 1) * NUM_SIG_LENGTHS + (signature_length - 1)); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/sphincs_helper_pqclean.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_SPHINCS_HELPER_PQCLEAN_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_SPHINCS_HELPER_PQCLEAN_H_ #include #include #include #include #include "absl/base/attributes.h" namespace crypto { namespace tink { namespace subtle { class SphincsHelperPqclean { public: SphincsHelperPqclean(int public_key_size, int signature_length) : public_key_size_(public_key_size), signature_length_(signature_length) {} SphincsHelperPqclean(const SphincsHelperPqclean &other) = delete; SphincsHelperPqclean &operator=(const SphincsHelperPqclean &other) = delete; virtual ~SphincsHelperPqclean() = default; // Arguments: // sig - output signature (allocated buffer of size at least // GetSignatureLength()); siglen - output length of signature; m - message // to be signed; mlen - length of message; sk - bit-packed secret key. // Computes signature. Returns 0 (success). virtual ABSL_MUST_USE_RESULT int Sign(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) const = 0; // Arguments: // sig - input signature; siglen - length of signature; // m - input message; mlen - length of message; pk - bit-packed public key. // Verifies the signature. Returns 0 (success). virtual ABSL_MUST_USE_RESULT int Verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) const = 0; // Arguments: // pk - output public key (allocated buffer of the corresponding public key // size); sk - output private key (allocated buffer of the corresponding // private key size) // Gnerates the key pair. Returns 0 (success). virtual ABSL_MUST_USE_RESULT int Keygen(uint8_t *pk, uint8_t *sk) const = 0; int GetPublicKeySize() const { return public_key_size_; } int GetSignatureLength() const { return signature_length_; } private: int public_key_size_; int signature_length_; }; // Returns a pointer to the corresponding SphincsHelperPqclean derived class. // Will be used for the key generation, signing and verifing. const SphincsHelperPqclean &GetSphincsHelperPqclean(int hash_type, int variant, int key_size, int signature_length); } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_SPHINCS_HELPER_PQCLEAN_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/sphincs_sign.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/subtle/sphincs_sign.h" #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_helper_pqclean.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_sign.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // static util::StatusOr> SphincsSign::New( SphincsPrivateKeyPqclean key) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) return status; util::Status key_size = ValidatePrivateKeySize(key.GetKey().size()); if (!key_size.ok()) { return key_size; } util::Status valid_parameters = ValidateParams(key.GetParams()); if (!valid_parameters.ok()) { return valid_parameters; } return {absl::WrapUnique(new SphincsSign(std::move(key)))}; } util::StatusOr SphincsSign::Sign(absl::string_view data) const { util::StatusOr key_size_index = SphincsKeySizeToIndex(key_.GetKey().size()); if (!key_size_index.ok()) { return key_size_index.status(); } size_t sig_length; SphincsParamsPqclean params = key_.GetParams(); const SphincsHelperPqclean &sphincs_helper_pqclean = GetSphincsHelperPqclean(params.hash_type, params.variant, *key_size_index, params.sig_length_type); std::string signature(sphincs_helper_pqclean.GetSignatureLength(), '0'); if ((sphincs_helper_pqclean.Sign( reinterpret_cast(signature.data()), &sig_length, reinterpret_cast(data.data()), data.size(), reinterpret_cast(key_.GetKey().data())) != 0)) { return util::Status(absl::StatusCode::kInternal, "Signing failed."); } return signature; } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/sphincs_sign.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_SPHINCS_SIGN_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_SPHINCS_SIGN_H_ #include #include #include #include "absl/strings/string_view.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_sign.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // Post-Quantum Signing using different variants of Sphincs stateless hash-based // signature scheme class SphincsSign : public PublicKeySign { public: static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kNotFips; static crypto::tink::util::StatusOr> New( SphincsPrivateKeyPqclean key); ~SphincsSign() override = default; // Computes the signature for 'data'. crypto::tink::util::StatusOr Sign( absl::string_view data) const override; private: explicit SphincsSign(SphincsPrivateKeyPqclean key) : key_(std::move(key)) {} const SphincsPrivateKeyPqclean key_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_SPHINCS_SIGN_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/sphincs_sign_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/subtle/sphincs_sign.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/config/tink_fips.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_helper_pqclean.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" extern "C" { #include "third_party/pqclean/crypto_sign/sphincs-haraka-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256s-simple/api.h" } namespace crypto { namespace tink { namespace subtle { namespace { struct SphincsTestCase { std::string test_name; SphincsHashType hash_type; SphincsVariant variant; SphincsSignatureType sig_length_type; int32_t private_key_size; int32_t signature_length; }; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using crypto::tink::util::Status; using SphincsSignTest = testing::TestWithParam; TEST_P(SphincsSignTest, SignatureLength) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } const SphincsTestCase& test_case = GetParam(); SphincsParamsPqclean params = { .hash_type = test_case.hash_type, .variant = test_case.variant, .sig_length_type = test_case.sig_length_type, .private_key_size = test_case.private_key_size, }; // Generate sphincs key pair. util::StatusOr key_pair = GenerateSphincsKeyPair(params); ASSERT_THAT(key_pair, IsOk()); // Create a new signer. util::StatusOr> signer = SphincsSign::New(key_pair->GetPrivateKey()); ASSERT_THAT(signer, IsOk()); // Sign a message. std::string message = "message to be signed"; util::StatusOr signature = (*signer)->Sign(message); ASSERT_THAT(signature, IsOk()); // Check signature size. EXPECT_NE(*signature, message); EXPECT_EQ((*signature).size(), test_case.signature_length); } TEST_P(SphincsSignTest, NonDeterminism) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } const SphincsTestCase& test_case = GetParam(); SphincsParamsPqclean params = { .hash_type = test_case.hash_type, .variant = test_case.variant, .sig_length_type = test_case.sig_length_type, .private_key_size = test_case.private_key_size, }; // Generate sphincs key pair. util::StatusOr key_pair = GenerateSphincsKeyPair(params); ASSERT_THAT(key_pair, IsOk()); // Create two signers based on same private key. util::StatusOr> first_signer = SphincsSign::New(key_pair->GetPrivateKey()); ASSERT_THAT(first_signer, IsOk()); util::StatusOr> second_signer = SphincsSign::New(key_pair->GetPrivateKey()); ASSERT_THAT(second_signer, IsOk()); // Sign the same message twice, using the same private key. std::string message = "message to be signed"; util::StatusOr first_signature = (*first_signer)->Sign(message); ASSERT_THAT(first_signature, IsOk()); util::StatusOr second_signature = (*second_signer)->Sign(message); ASSERT_THAT(second_signature, IsOk()); // Check signatures size. EXPECT_NE(*first_signature, message); EXPECT_EQ((*first_signature).size(), test_case.signature_length); EXPECT_NE(*second_signature, message); EXPECT_EQ((*second_signature).size(), test_case.signature_length); // Check if signatures are equal. EXPECT_NE(*first_signature, *second_signature); } TEST_P(SphincsSignTest, FipsMode) { if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips."; } const SphincsTestCase& test_case = GetParam(); SphincsParamsPqclean params = { .hash_type = test_case.hash_type, .variant = test_case.variant, .sig_length_type = test_case.sig_length_type, .private_key_size = test_case.private_key_size, }; // Generate sphincs key pair. util::StatusOr key_pair = GenerateSphincsKeyPair(params); ASSERT_THAT(key_pair, IsOk()); // Create a new signer. EXPECT_THAT(SphincsSign::New(key_pair->GetPrivateKey()).status(), StatusIs(absl::StatusCode::kInternal)); } INSTANTIATE_TEST_SUITE_P( SphincsSignTests, SphincsSignTest, testing::ValuesIn( {{"SPHINCSHARAKA128FROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA128FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA128FROBUST_CRYPTO_BYTES}, {"SPHINCSHARAKA128SROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA128SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA128SROBUST_CRYPTO_BYTES}, {"SPHINCSHARAKA128FSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CRYPTO_BYTES}, {"SPHINCSHARAKA128SSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CRYPTO_BYTES}, {"SPHINCSHARAKA192FROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA192FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA192FROBUST_CRYPTO_BYTES}, {"SPHINCSHARAKA192SROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA192SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA192SROBUST_CRYPTO_BYTES}, {"SPHINCSHARAKA192FSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CRYPTO_BYTES}, {"SPHINCSHARAKA192SSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CRYPTO_BYTES}, {"SPHINCSHARAKA256FROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA256FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA256FROBUST_CRYPTO_BYTES}, {"SPHINCSHARAKA256SROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA256SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA256SROBUST_CRYPTO_BYTES}, {"SPHINCSHARAKA256FSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CRYPTO_BYTES}, {"SPHINCSHARAKA256SSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHA256128FROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256128FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256128FROBUST_CRYPTO_BYTES}, {"SPHINCSSHA256128SROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256128SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256128SROBUST_CRYPTO_BYTES}, {"SPHINCSSHA256128FSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256128FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256128FSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHA256128SSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256128SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256128SSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHA256192FROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256192FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256192FROBUST_CRYPTO_BYTES}, {"SPHINCSSHA256192SROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256192SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256192SROBUST_CRYPTO_BYTES}, {"SPHINCSSHA256192FSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256192FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256192FSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHA256192SSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256192SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256192SSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHA256256FROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256256FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256256FROBUST_CRYPTO_BYTES}, {"SPHINCSSHA256256SROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256256SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256256SROBUST_CRYPTO_BYTES}, {"SPHINCSSHA256256FSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256256FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256256FSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHA256256SSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256256SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256256SSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHAKE256128FROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256128FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256128FROBUST_CRYPTO_BYTES}, {"SPHINCSSHAKE256128SROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256128SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256128SROBUST_CRYPTO_BYTES}, {"SPHINCSSHAKE256128FSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHAKE256128SSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHAKE256192FROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256192FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256192FROBUST_CRYPTO_BYTES}, {"SPHINCSSHAKE256192SROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256192SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256192SROBUST_CRYPTO_BYTES}, {"SPHINCSSHAKE256192FSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHAKE256192SSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHAKE256256FROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256256FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256256FROBUST_CRYPTO_BYTES}, {"SPHINCSSHAKE256256SROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256256SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256256SROBUST_CRYPTO_BYTES}, {"SPHINCSSHAKE256256FSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHAKE256256SSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CRYPTO_BYTES}}), [](const testing::TestParamInfo& info) { return info.param.test_name; }); } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_format.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_helper_pqclean.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { crypto::tink::util::StatusOr GenerateSphincsKeyPair( SphincsParamsPqclean params) { // Check if parameters are valid. util::Status valid_parameters = ValidateParams(params); if (!valid_parameters.ok()) { return valid_parameters; } util::StatusOr key_size_index = SphincsKeySizeToIndex(params.private_key_size); if (!key_size_index.ok()) { return key_size_index.status(); } std::string public_key; std::string private_key; private_key.resize(params.private_key_size); const SphincsHelperPqclean &sphincs_helper_pqclean = GetSphincsHelperPqclean(params.hash_type, params.variant, *key_size_index, params.sig_length_type); public_key.resize(sphincs_helper_pqclean.GetPublicKeySize()); if (0 != sphincs_helper_pqclean.Keygen( reinterpret_cast(public_key.data()), reinterpret_cast(private_key.data()))) { return util::Status(absl::StatusCode::kInternal, "Key generation failed."); } util::SecretData private_key_data = util::SecretDataFromStringView(private_key); SphincsKeyPair key_pair(SphincsPrivateKeyPqclean{private_key_data, params}, SphincsPublicKeyPqclean{public_key, params}); return key_pair; } crypto::tink::util::Status ValidatePrivateKeySize(int32_t key_size) { switch (key_size) { case kSphincsPrivateKeySize64: case kSphincsPrivateKeySize96: case kSphincsPrivateKeySize128: return util::OkStatus(); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrFormat("Invalid private key size (%d). " "The only valid sizes are %d, %d, %d.", key_size, kSphincsPrivateKeySize64, kSphincsPrivateKeySize96, kSphincsPrivateKeySize128)); } } crypto::tink::util::Status ValidatePublicKeySize(int32_t key_size) { switch (key_size) { case kSphincsPublicKeySize32: case kSphincsPublicKeySize48: case kSphincsPublicKeySize64: return util::OkStatus(); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrFormat("Invalid private key size (%d). " "The only valid sizes are %d, %d, %d.", key_size, kSphincsPublicKeySize32, kSphincsPublicKeySize48, kSphincsPublicKeySize64)); } } crypto::tink::util::StatusOr SphincsKeySizeToIndex(int32_t key_size) { switch (key_size) { case kSphincsPrivateKeySize64: return 0; case kSphincsPrivateKeySize96: return 1; case kSphincsPrivateKeySize128: return 2; default: return util::Status(absl::StatusCode::kInvalidArgument, "Invalid key size"); } } crypto::tink::util::Status ValidateParams(SphincsParamsPqclean params) { switch (params.hash_type) { case SphincsHashType::HARAKA: case SphincsHashType::SHA256: case SphincsHashType::SHAKE256: { break; } default: { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid hash type"); } } switch (params.variant) { case SphincsVariant::ROBUST: case SphincsVariant::SIMPLE: { break; } default: { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid variant"); } } switch (params.sig_length_type) { case SphincsSignatureType::FAST_SIGNING: case SphincsSignatureType::SMALL_SIGNATURE: { break; } default: { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid signature type"); } } return ValidatePrivateKeySize(params.private_key_size); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_SPHINCS_SUBTLE_UTILS_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_SPHINCS_SUBTLE_UTILS_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_format.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // The three possible sphincs private key sizes. const int kSphincsPrivateKeySize64 = 64; const int kSphincsPrivateKeySize96 = 96; const int kSphincsPrivateKeySize128 = 128; // The three possible sphincs public key sizes. const int kSphincsPublicKeySize32 = 32; const int kSphincsPublicKeySize48 = 48; const int kSphincsPublicKeySize64 = 64; enum SphincsHashType { HASH_TYPE_UNSPECIFIED = 0, HARAKA = 1, SHA256 = 2, SHAKE256 = 3, }; enum SphincsVariant { VARIANT_UNSPECIFIED = 0, ROBUST = 1, SIMPLE = 2, }; enum SphincsSignatureType { SIG_TYPE_UNSPECIFIED = 0, FAST_SIGNING = 1, SMALL_SIGNATURE = 2, }; struct SphincsParamsPqclean { SphincsHashType hash_type; SphincsVariant variant; SphincsSignatureType sig_length_type; int32_t private_key_size; }; // Representation of the Sphincs private key. class SphincsPrivateKeyPqclean { public: explicit SphincsPrivateKeyPqclean(util::SecretData key_data, SphincsParamsPqclean params) : private_key_data_(std::move(key_data)), params_(std::move(params)) {} SphincsPrivateKeyPqclean(const SphincsPrivateKeyPqclean& other) = default; SphincsPrivateKeyPqclean& operator=(const SphincsPrivateKeyPqclean& other) = default; const util::SecretData& GetKey() const { return private_key_data_; } const SphincsParamsPqclean& GetParams() const { return params_; } private: const util::SecretData private_key_data_; const SphincsParamsPqclean params_; }; // Representation of the Sphincs public key. class SphincsPublicKeyPqclean { public: SphincsPublicKeyPqclean(std::string key_data, SphincsParamsPqclean params) : public_key_data_(std::move(key_data)), params_(std::move(params)) {} SphincsPublicKeyPqclean(const SphincsPublicKeyPqclean& other) = default; SphincsPublicKeyPqclean& operator=(const SphincsPublicKeyPqclean& other) = default; const std::string& GetKey() const { return public_key_data_; } const SphincsParamsPqclean& GetParams() const { return params_; } private: const std::string public_key_data_; const SphincsParamsPqclean params_; }; class SphincsKeyPair { public: SphincsKeyPair(SphincsPrivateKeyPqclean private_key, SphincsPublicKeyPqclean public_key) : private_key_(std::move(private_key)), public_key_(std::move(public_key)) {} SphincsKeyPair(const SphincsKeyPair& other) = default; SphincsKeyPair& operator=(const SphincsKeyPair& other) = default; const SphincsPrivateKeyPqclean& GetPrivateKey() const { return private_key_; } const SphincsPublicKeyPqclean& GetPublicKey() const { return public_key_; } private: const SphincsPrivateKeyPqclean private_key_; const SphincsPublicKeyPqclean public_key_; }; // This is an utility function that generates a new Sphincs key pair based on // Sphincs specific parameters. This function is expected to be called from // a key manager class. crypto::tink::util::StatusOr GenerateSphincsKeyPair( SphincsParamsPqclean params); // Validates whether the private key size is safe to use for sphincs signature. crypto::tink::util::Status ValidatePrivateKeySize(int32_t key_size); // Validates whether the public key size is safe to use for sphincs signature. crypto::tink::util::Status ValidatePublicKeySize(int32_t key_size); // Validates whether the parameters are safe to use for sphincs signature. crypto::tink::util::Status ValidateParams(SphincsParamsPqclean params); // Convert the sphincs private key size to the appropriate index in the // pqclean functions array. crypto::tink::util::StatusOr SphincsKeySizeToIndex(int32_t key_size); } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_SPHINCS_SUBTLE_UTILS_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/str_cat.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_helper_pqclean.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" extern "C" { #include "third_party/pqclean/crypto_sign/sphincs-haraka-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256s-simple/api.h" } namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::IsOk; struct SphincsUtilsTestCase { std::string test_name; SphincsHashType hash_type; SphincsVariant variant; SphincsSignatureType sig_length_type; int32_t private_key_size; int32_t public_key_size; }; using SphincsUtilsTest = testing::TestWithParam; TEST_P(SphincsUtilsTest, SphincsKeysLength) { const SphincsUtilsTestCase& test_case = GetParam(); SphincsParamsPqclean params = { .hash_type = test_case.hash_type, .variant = test_case.variant, .sig_length_type = test_case.sig_length_type, .private_key_size = test_case.private_key_size, }; // Generate sphincs key pair. util::StatusOr key_pair = GenerateSphincsKeyPair(params); ASSERT_THAT(key_pair, IsOk()); // Check keys size. EXPECT_EQ(key_pair->GetPrivateKey().GetKey().size(), test_case.private_key_size); EXPECT_EQ(key_pair->GetPublicKey().GetKey().size(), test_case.public_key_size); } TEST_P(SphincsUtilsTest, DifferentContent) { const SphincsUtilsTestCase& test_case = GetParam(); SphincsParamsPqclean params = { .hash_type = test_case.hash_type, .variant = test_case.variant, .sig_length_type = test_case.sig_length_type, .private_key_size = test_case.private_key_size, }; // Generate sphincs key pair. util::StatusOr key_pair = GenerateSphincsKeyPair(params); ASSERT_THAT(key_pair, IsOk()); // Check keys content is different. EXPECT_NE(util::SecretDataAsStringView(key_pair->GetPrivateKey().GetKey()), key_pair->GetPublicKey().GetKey()); } TEST(SphincsUtilsTest, InvalidPrivateKeySize) { for (int keysize = 0; keysize <= kSphincsPrivateKeySize128; keysize++) { if (keysize == kSphincsPrivateKeySize64 || keysize == kSphincsPrivateKeySize96 || keysize == kSphincsPrivateKeySize128) { // Valid key size. continue; } EXPECT_FALSE(ValidatePrivateKeySize(keysize).ok()); } } TEST(SphincsUtilsTest, InvalidPublicKeySize) { for (int keysize = 0; keysize <= kSphincsPrivateKeySize128; keysize++) { if (keysize == kSphincsPublicKeySize32 || keysize == kSphincsPublicKeySize48 || keysize == kSphincsPublicKeySize64) { // Valid key size. continue; } EXPECT_FALSE(ValidatePublicKeySize(keysize).ok()); } } TEST_P(SphincsUtilsTest, ValidParams) { const SphincsUtilsTestCase& test_case = GetParam(); SphincsParamsPqclean params = { .hash_type = test_case.hash_type, .variant = test_case.variant, .sig_length_type = test_case.sig_length_type, .private_key_size = test_case.private_key_size, }; EXPECT_TRUE(ValidateParams(params).ok()); } TEST(SphincsUtilsTest, InvalidHashType) { SphincsParamsPqclean params = { .hash_type = SphincsHashType::HASH_TYPE_UNSPECIFIED, .variant = SphincsVariant::ROBUST, .sig_length_type = SphincsSignatureType::FAST_SIGNING, .private_key_size = kSphincsPrivateKeySize64, }; EXPECT_FALSE(ValidateParams(params).ok()); } TEST(SphincsUtilsTest, InvalidVariant) { SphincsParamsPqclean params = { .hash_type = SphincsHashType::HARAKA, .variant = SphincsVariant::VARIANT_UNSPECIFIED, .sig_length_type = SphincsSignatureType::FAST_SIGNING, .private_key_size = kSphincsPrivateKeySize64, }; EXPECT_FALSE(ValidateParams(params).ok()); } TEST(SphincsUtilsTest, InvalidSignatureType) { SphincsParamsPqclean params = { .hash_type = SphincsHashType::HARAKA, .variant = SphincsVariant::ROBUST, .sig_length_type = SphincsSignatureType::SIG_TYPE_UNSPECIFIED, .private_key_size = kSphincsPrivateKeySize64, }; EXPECT_FALSE(ValidateParams(params).ok()); } INSTANTIATE_TEST_SUITE_P( SphincsUtilsTests, SphincsUtilsTest, testing::ValuesIn( {{"SPHINCSHARAKA128FROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA128FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA128FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA128SROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA128SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA128SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA128FSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA128SSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA192FROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA192FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA192FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA192SROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA192SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA192SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA192FSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA192SSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA256FROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA256FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA256FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA256SROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA256SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA256SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA256FSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSHARAKA256SSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256128FROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256128FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256128FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256128SROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256128SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256128SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256128FSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256128FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256128FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256128SSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256128SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256128SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256192FROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256192FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256192FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256192SROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256192SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256192SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256192FSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256192FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256192FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256192SSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256192SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256192SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256256FROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256256FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256256FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256256SROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256256SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256256SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256256FSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256256FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256256FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHA256256SSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256256SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256256SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256128FROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256128FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256128FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256128SROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256128SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256128SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256128FSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256128SSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256192FROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256192FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256192FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256192SROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256192SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256192SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256192FSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256192SSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256256FROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256256FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256256FROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256256SROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256256SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256256SROBUST_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256256FSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CRYPTO_PUBLICKEYBYTES}, {"SPHINCSSHAKE256256SSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CRYPTO_PUBLICKEYBYTES}}), [](const testing::TestParamInfo& info) { return info.param.test_name; }); } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/sphincs_verify.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/subtle/sphincs_verify.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_helper_pqclean.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_verify.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // static util::StatusOr> SphincsVerify::New( SphincsPublicKeyPqclean public_key) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) return status; util::Status key_size = ValidatePublicKeySize(public_key.GetKey().size()); if (!key_size.ok()) { return key_size; } util::Status valid_parameters = ValidateParams(public_key.GetParams()); if (!valid_parameters.ok()) { return valid_parameters; } return {absl::WrapUnique( new SphincsVerify(std::move(public_key)))}; } util::Status SphincsVerify::Verify(absl::string_view signature, absl::string_view data) const { SphincsParamsPqclean params = key_.GetParams(); util::StatusOr key_size_index = SphincsKeySizeToIndex(params.private_key_size); if (!key_size_index.ok()) { return key_size_index.status(); } const SphincsHelperPqclean &sphincs_helper_pqclean = GetSphincsHelperPqclean(params.hash_type, params.variant, *key_size_index, params.sig_length_type); if ((sphincs_helper_pqclean.Verify( reinterpret_cast(signature.data()), signature.size(), reinterpret_cast(data.data()), data.size(), reinterpret_cast(key_.GetKey().data()))) != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Signature is not valid."); } return util::OkStatus(); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/sphincs_verify.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_SPHINCS_VERIFY_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_SPHINCS_VERIFY_H_ #include #include #include #include "absl/strings/string_view.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_verify.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { class SphincsVerify : public PublicKeyVerify { public: static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kNotFips; static crypto::tink::util::StatusOr> New( SphincsPublicKeyPqclean key); // Verifies that 'signature' is a digital signature for 'data'. crypto::tink::util::Status Verify(absl::string_view signature, absl::string_view data) const override; private: explicit SphincsVerify(SphincsPublicKeyPqclean key) : key_(std::move(key)) {} const SphincsPublicKeyPqclean key_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SUBTLE_SPHINCS_VERIFY_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/subtle/sphincs_verify_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/subtle/sphincs_verify.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/str_cat.h" #include "tink/config/tink_fips.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_helper_pqclean.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_sign.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" extern "C" { #include "third_party/pqclean/crypto_sign/sphincs-haraka-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-haraka-256s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-sha256-256s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-128s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-192s-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256f-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256f-simple/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256s-robust/api.h" #include "third_party/pqclean/crypto_sign/sphincs-shake256-256s-simple/api.h" } namespace crypto { namespace tink { namespace subtle { namespace { struct SphincsTestCase { std::string test_name; SphincsHashType hash_type; SphincsVariant variant; SphincsSignatureType sig_length_type; int32_t private_key_size; int32_t signature_length; }; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using crypto::tink::util::Status; using SphincsVerifyTest = testing::TestWithParam; TEST_P(SphincsVerifyTest, BasicSignVerify) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } const SphincsTestCase& test_case = GetParam(); SphincsParamsPqclean params = { .hash_type = test_case.hash_type, .variant = test_case.variant, .sig_length_type = test_case.sig_length_type, .private_key_size = test_case.private_key_size, }; // Generate sphincs key pair. util::StatusOr key_pair = GenerateSphincsKeyPair(params); ASSERT_THAT(key_pair, IsOk()); // Create a new signer. util::StatusOr> signer = SphincsSign::New(key_pair->GetPrivateKey()); ASSERT_THAT(signer, IsOk()); // Sign a message. std::string message = "message to be signed"; util::StatusOr signature = (*signer)->Sign(message); ASSERT_THAT(signature, IsOk()); // Create a new verifier. absl::StatusOr> verifier = SphincsVerify::New(key_pair->GetPublicKey()); ASSERT_THAT(verifier, IsOk()); // Verify signature. Status status = (*verifier)->Verify(*signature, message); EXPECT_THAT(status, IsOk()); } TEST_P(SphincsVerifyTest, FailsWithWrongSignature) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } const SphincsTestCase& test_case = GetParam(); SphincsParamsPqclean params = { .hash_type = test_case.hash_type, .variant = test_case.variant, .sig_length_type = test_case.sig_length_type, .private_key_size = test_case.private_key_size, }; // Generate sphincs key pair. util::StatusOr key_pair = GenerateSphincsKeyPair(params); ASSERT_THAT(key_pair, IsOk()); // Create a new signer. util::StatusOr> signer = SphincsSign::New(key_pair->GetPrivateKey()); ASSERT_THAT(signer, IsOk()); // Sign a message. std::string message = "message to be signed"; util::StatusOr signature = (*signer)->Sign(message); ASSERT_THAT(signature, IsOk()); // Create a new verifier. absl::StatusOr> verifier = SphincsVerify::New(key_pair->GetPublicKey()); ASSERT_THAT(verifier, IsOk()); // Verify signature. Status status = (*verifier)->Verify(*signature + "some trailing data", message); EXPECT_FALSE(status.ok()); } TEST_P(SphincsVerifyTest, FailsWithWrongMessage) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } const SphincsTestCase& test_case = GetParam(); SphincsParamsPqclean params = { .hash_type = test_case.hash_type, .variant = test_case.variant, .sig_length_type = test_case.sig_length_type, .private_key_size = test_case.private_key_size, }; // Generate sphincs key pair. util::StatusOr key_pair = GenerateSphincsKeyPair(params); ASSERT_THAT(key_pair, IsOk()); // Create a new signer. util::StatusOr> signer = SphincsSign::New(key_pair->GetPrivateKey()); ASSERT_THAT(signer, IsOk()); // Sign a message. std::string message = "message to be signed"; util::StatusOr signature = (*signer)->Sign(message); ASSERT_THAT(signature, IsOk()); // Create a new verifier. absl::StatusOr> verifier = SphincsVerify::New(key_pair->GetPublicKey()); ASSERT_THAT(verifier, IsOk()); // Verify signature. Status status = (*verifier)->Verify(*signature, "some bad message"); EXPECT_FALSE(status.ok()); } TEST_P(SphincsVerifyTest, FailsWithBytesFlipped) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } const SphincsTestCase& test_case = GetParam(); SphincsParamsPqclean params = { .hash_type = test_case.hash_type, .variant = test_case.variant, .sig_length_type = test_case.sig_length_type, .private_key_size = test_case.private_key_size, }; // Generate sphincs key pair. util::StatusOr key_pair = GenerateSphincsKeyPair(params); ASSERT_THAT(key_pair, IsOk()); // Create a new signer. util::StatusOr> signer = SphincsSign::New(key_pair->GetPrivateKey()); ASSERT_THAT(signer, IsOk()); // Sign a message. std::string message = "message to be signed"; util::StatusOr signature = (*signer)->Sign(message); ASSERT_THAT(signature, IsOk()); // Create a new verifier. absl::StatusOr> verifier = SphincsVerify::New(key_pair->GetPublicKey()); ASSERT_THAT(verifier, IsOk()); // Invalidate one signature byte. (*signature)[0] ^= 1; // Verify signature. Status status = (*verifier)->Verify(*signature, message); EXPECT_FALSE(status.ok()); } TEST_P(SphincsVerifyTest, FipsMode) { if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips."; } const SphincsTestCase& test_case = GetParam(); SphincsParamsPqclean params = { .hash_type = test_case.hash_type, .variant = test_case.variant, .sig_length_type = test_case.sig_length_type, .private_key_size = test_case.private_key_size, }; // Generate sphincs key pair. util::StatusOr key_pair = GenerateSphincsKeyPair(params); ASSERT_THAT(key_pair, IsOk()); // Create a new signer. EXPECT_THAT(SphincsVerify::New(key_pair->GetPublicKey()).status(), StatusIs(absl::StatusCode::kInternal)); } // TODO(ioannanedelcu): Add test with testvectors. INSTANTIATE_TEST_SUITE_P( SphincsVerifyTests, SphincsVerifyTest, testing::ValuesIn( {{"SPHINCSHARAKA128FROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA128FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA128FROBUST_CRYPTO_BYTES}, {"SPHINCSHARAKA128SROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA128SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA128SROBUST_CRYPTO_BYTES}, {"SPHINCSHARAKA128FSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CRYPTO_BYTES}, {"SPHINCSHARAKA128SSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CRYPTO_BYTES}, {"SPHINCSHARAKA192FROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA192FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA192FROBUST_CRYPTO_BYTES}, {"SPHINCSHARAKA192SROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA192SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA192SROBUST_CRYPTO_BYTES}, {"SPHINCSHARAKA192FSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CRYPTO_BYTES}, {"SPHINCSHARAKA192SSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CRYPTO_BYTES}, {"SPHINCSHARAKA256FROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA256FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA256FROBUST_CRYPTO_BYTES}, {"SPHINCSHARAKA256SROBUST", SphincsHashType::HARAKA, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA256SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA256SROBUST_CRYPTO_BYTES}, {"SPHINCSHARAKA256FSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CRYPTO_BYTES}, {"SPHINCSHARAKA256SSIMPLE", SphincsHashType::HARAKA, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHA256128FROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256128FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256128FROBUST_CRYPTO_BYTES}, {"SPHINCSSHA256128SROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256128SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256128SROBUST_CRYPTO_BYTES}, {"SPHINCSSHA256128FSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256128FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256128FSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHA256128SSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256128SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256128SSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHA256192FROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256192FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256192FROBUST_CRYPTO_BYTES}, {"SPHINCSSHA256192SROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256192SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256192SROBUST_CRYPTO_BYTES}, {"SPHINCSSHA256192FSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256192FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256192FSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHA256192SSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256192SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256192SSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHA256256FROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256256FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256256FROBUST_CRYPTO_BYTES}, {"SPHINCSSHA256256SROBUST", SphincsHashType::SHA256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256256SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256256SROBUST_CRYPTO_BYTES}, {"SPHINCSSHA256256FSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHA256256FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256256FSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHA256256SSIMPLE", SphincsHashType::SHA256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHA256256SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHA256256SSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHAKE256128FROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256128FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256128FROBUST_CRYPTO_BYTES}, {"SPHINCSSHAKE256128SROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256128SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256128SROBUST_CRYPTO_BYTES}, {"SPHINCSSHAKE256128FSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHAKE256128SSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHAKE256192FROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256192FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256192FROBUST_CRYPTO_BYTES}, {"SPHINCSSHAKE256192SROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256192SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256192SROBUST_CRYPTO_BYTES}, {"SPHINCSSHAKE256192FSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHAKE256192SSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHAKE256256FROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256256FROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256256FROBUST_CRYPTO_BYTES}, {"SPHINCSSHAKE256256SROBUST", SphincsHashType::SHAKE256, SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256256SROBUST_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256256SROBUST_CRYPTO_BYTES}, {"SPHINCSSHAKE256256FSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CRYPTO_BYTES}, {"SPHINCSSHAKE256256SSIMPLE", SphincsHashType::SHAKE256, SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CRYPTO_SECRETKEYBYTES, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CRYPTO_BYTES}}), [](const testing::TestParamInfo& info) { return info.param.test_name; }); } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/util/enums.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/util/enums.h" #include "tink/experimental/pqcrypto/signature/subtle/dilithium_key.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h" namespace crypto { namespace tink { namespace util { namespace pb = google::crypto::tink; // static pb::DilithiumSeedExpansion EnumsPqcrypto::SubtleToProto( subtle::DilithiumSeedExpansion expansion) { switch (expansion) { case subtle::DilithiumSeedExpansion::SEED_EXPANSION_SHAKE: return pb::DilithiumSeedExpansion::SEED_EXPANSION_SHAKE; case subtle::DilithiumSeedExpansion::SEED_EXPANSION_AES: return pb::DilithiumSeedExpansion::SEED_EXPANSION_AES; default: return pb::DilithiumSeedExpansion::SEED_EXPANSION_UNKNOWN; } } // static subtle::DilithiumSeedExpansion EnumsPqcrypto::ProtoToSubtle( pb::DilithiumSeedExpansion expansion) { switch (expansion) { case pb::DilithiumSeedExpansion::SEED_EXPANSION_SHAKE: return subtle::DilithiumSeedExpansion::SEED_EXPANSION_SHAKE; case pb::DilithiumSeedExpansion::SEED_EXPANSION_AES: return subtle::DilithiumSeedExpansion::SEED_EXPANSION_AES; default: return subtle::DilithiumSeedExpansion::SEED_EXPANSION_UNKNOWN; } } // static pb::SphincsHashType EnumsPqcrypto::SubtleToProto(subtle::SphincsHashType type) { switch (type) { case subtle::SphincsHashType::HARAKA: return pb::SphincsHashType::HARAKA; case subtle::SphincsHashType::SHA256: return pb::SphincsHashType::SHA256; case subtle::SphincsHashType::SHAKE256: return pb::SphincsHashType::SHAKE256; default: return pb::SphincsHashType::HASH_TYPE_UNSPECIFIED; } } // static subtle::SphincsHashType EnumsPqcrypto::ProtoToSubtle(pb::SphincsHashType type) { switch (type) { case pb::SphincsHashType::HARAKA: return subtle::SphincsHashType::HARAKA; case pb::SphincsHashType::SHA256: return subtle::SphincsHashType::SHA256; case pb::SphincsHashType::SHAKE256: return subtle::SphincsHashType::SHAKE256; default: return subtle::SphincsHashType::HASH_TYPE_UNSPECIFIED; } } // static pb::SphincsVariant EnumsPqcrypto::SubtleToProto( subtle::SphincsVariant variant) { switch (variant) { case subtle::SphincsVariant::ROBUST: return pb::SphincsVariant::ROBUST; case subtle::SphincsVariant::SIMPLE: return pb::SphincsVariant::SIMPLE; default: return pb::SphincsVariant::VARIANT_UNSPECIFIED; } } // static subtle::SphincsVariant EnumsPqcrypto::ProtoToSubtle( pb::SphincsVariant variant) { switch (variant) { case pb::SphincsVariant::ROBUST: return subtle::SphincsVariant::ROBUST; case pb::SphincsVariant::SIMPLE: return subtle::SphincsVariant::SIMPLE; default: return subtle::SphincsVariant::VARIANT_UNSPECIFIED; } } // static pb::SphincsSignatureType EnumsPqcrypto::SubtleToProto( subtle::SphincsSignatureType type) { switch (type) { case subtle::SphincsSignatureType::FAST_SIGNING: return pb::SphincsSignatureType::FAST_SIGNING; case subtle::SphincsSignatureType::SMALL_SIGNATURE: return pb::SphincsSignatureType::SMALL_SIGNATURE; default: return pb::SphincsSignatureType::SIG_TYPE_UNSPECIFIED; } } // static subtle::SphincsSignatureType EnumsPqcrypto::ProtoToSubtle( pb::SphincsSignatureType type) { switch (type) { case pb::SphincsSignatureType::FAST_SIGNING: return subtle::SphincsSignatureType::FAST_SIGNING; case pb::SphincsSignatureType::SMALL_SIGNATURE: return subtle::SphincsSignatureType::SMALL_SIGNATURE; default: return subtle::SphincsSignatureType::SIG_TYPE_UNSPECIFIED; } } } // namespace util } // namespace tink } // namespace crypto ================================================ FILE: cc/experimental/pqcrypto/signature/util/enums.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_UTIL_ENUMS_H_ #define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_UTIL_ENUMS_H_ #include "absl/strings/string_view.h" #include "tink/experimental/pqcrypto/signature/subtle/dilithium_key.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h" #include "tink/util/statusor.h" #include "proto/experimental/pqcrypto/dilithium.pb.h" #include "proto/experimental/pqcrypto/sphincs.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace util { // Helpers for translation of pqcrypto enums between protocol buffer enums, // their string representation, and pqcrypto enums used in subtle. class EnumsPqcrypto { public: // DilithiumSeedExpansion. static google::crypto::tink::DilithiumSeedExpansion SubtleToProto( crypto::tink::subtle::DilithiumSeedExpansion expansion); static crypto::tink::subtle::DilithiumSeedExpansion ProtoToSubtle( google::crypto::tink::DilithiumSeedExpansion expansion); // SphincsHashType. static google::crypto::tink::SphincsHashType SubtleToProto( crypto::tink::subtle::SphincsHashType type); static crypto::tink::subtle::SphincsHashType ProtoToSubtle( google::crypto::tink::SphincsHashType type); // SphincsVariant. static google::crypto::tink::SphincsVariant SubtleToProto( crypto::tink::subtle::SphincsVariant variant); static crypto::tink::subtle::SphincsVariant ProtoToSubtle( google::crypto::tink::SphincsVariant variant); // SphincsSignatureType. static google::crypto::tink::SphincsSignatureType SubtleToProto( crypto::tink::subtle::SphincsSignatureType type); static crypto::tink::subtle::SphincsSignatureType ProtoToSubtle( google::crypto::tink::SphincsSignatureType type); }; } // namespace util } // namespace tink } // namespace crypto #endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_UTIL_ENUMS_H_ ================================================ FILE: cc/experimental/pqcrypto/signature/util/enums_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/experimental/pqcrypto/signature/util/enums.h" #include "gtest/gtest.h" #include "tink/experimental/pqcrypto/signature/subtle/dilithium_key.h" #include "tink/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.h" #include "proto/experimental/pqcrypto/dilithium.pb.h" #include "proto/experimental/pqcrypto/sphincs.pb.h" namespace crypto { namespace tink { namespace { namespace pb = google::crypto::tink; using crypto::tink::util::EnumsPqcrypto; class EnumsTest : public ::testing::Test {}; TEST_F(EnumsTest, DilithiumSeedExpansion) { EXPECT_EQ(pb::DilithiumSeedExpansion::SEED_EXPANSION_SHAKE, EnumsPqcrypto::SubtleToProto( subtle::DilithiumSeedExpansion::SEED_EXPANSION_SHAKE)); EXPECT_EQ(pb::DilithiumSeedExpansion::SEED_EXPANSION_AES, EnumsPqcrypto::SubtleToProto( subtle::DilithiumSeedExpansion::SEED_EXPANSION_AES)); EXPECT_EQ(pb::DilithiumSeedExpansion::SEED_EXPANSION_UNKNOWN, EnumsPqcrypto::SubtleToProto( subtle::DilithiumSeedExpansion::SEED_EXPANSION_UNKNOWN)); EXPECT_EQ(subtle::DilithiumSeedExpansion::SEED_EXPANSION_SHAKE, EnumsPqcrypto::ProtoToSubtle( pb::DilithiumSeedExpansion::SEED_EXPANSION_SHAKE)); EXPECT_EQ(subtle::DilithiumSeedExpansion::SEED_EXPANSION_AES, EnumsPqcrypto::ProtoToSubtle( pb::DilithiumSeedExpansion::SEED_EXPANSION_AES)); EXPECT_EQ(subtle::DilithiumSeedExpansion::SEED_EXPANSION_UNKNOWN, EnumsPqcrypto::ProtoToSubtle( pb::DilithiumSeedExpansion::SEED_EXPANSION_UNKNOWN)); // Check that enum conversion covers the entire range of the proto-enum. int count = 0; for (int int_type = static_cast(pb::DilithiumSeedExpansion_MIN); int_type <= static_cast(pb::DilithiumSeedExpansion_MAX); int_type++) { if (pb::DilithiumSeedExpansion_IsValid(int_type)) { pb::DilithiumSeedExpansion type = static_cast(int_type); EXPECT_EQ(type, EnumsPqcrypto::SubtleToProto( EnumsPqcrypto::ProtoToSubtle(type))); count++; } } EXPECT_EQ(3, count); } TEST_F(EnumsTest, SphincsHashType) { EXPECT_EQ(pb::SphincsHashType::HARAKA, EnumsPqcrypto::SubtleToProto(subtle::SphincsHashType::HARAKA)); EXPECT_EQ(pb::SphincsHashType::SHA256, EnumsPqcrypto::SubtleToProto(subtle::SphincsHashType::SHA256)); EXPECT_EQ(pb::SphincsHashType::SHAKE256, EnumsPqcrypto::SubtleToProto(subtle::SphincsHashType::SHAKE256)); EXPECT_EQ(pb::SphincsHashType::HASH_TYPE_UNSPECIFIED, EnumsPqcrypto::SubtleToProto( subtle::SphincsHashType::HASH_TYPE_UNSPECIFIED)); EXPECT_EQ(subtle::SphincsHashType::HARAKA, EnumsPqcrypto::ProtoToSubtle(pb::SphincsHashType::HARAKA)); EXPECT_EQ(subtle::SphincsHashType::SHA256, EnumsPqcrypto::ProtoToSubtle(pb::SphincsHashType::SHA256)); EXPECT_EQ(subtle::SphincsHashType::SHAKE256, EnumsPqcrypto::ProtoToSubtle(pb::SphincsHashType::SHAKE256)); EXPECT_EQ( subtle::SphincsHashType::HASH_TYPE_UNSPECIFIED, EnumsPqcrypto::ProtoToSubtle(pb::SphincsHashType::HASH_TYPE_UNSPECIFIED)); // Check that enum conversion covers the entire range of the proto-enum. int count = 0; for (int int_type = static_cast(pb::SphincsHashType_MIN); int_type <= static_cast(pb::SphincsHashType_MAX); int_type++) { if (pb::SphincsHashType_IsValid(int_type)) { pb::SphincsHashType type = static_cast(int_type); EXPECT_EQ(type, EnumsPqcrypto::SubtleToProto( EnumsPqcrypto::ProtoToSubtle(type))); count++; } } EXPECT_EQ(4, count); } TEST_F(EnumsTest, SphincsVariant) { EXPECT_EQ(pb::SphincsVariant::ROBUST, EnumsPqcrypto::SubtleToProto(subtle::SphincsVariant::ROBUST)); EXPECT_EQ(pb::SphincsVariant::SIMPLE, EnumsPqcrypto::SubtleToProto(subtle::SphincsVariant::SIMPLE)); EXPECT_EQ(pb::SphincsVariant::VARIANT_UNSPECIFIED, EnumsPqcrypto::SubtleToProto( subtle::SphincsVariant::VARIANT_UNSPECIFIED)); EXPECT_EQ(subtle::SphincsVariant::ROBUST, EnumsPqcrypto::ProtoToSubtle(pb::SphincsVariant::ROBUST)); EXPECT_EQ(subtle::SphincsVariant::SIMPLE, EnumsPqcrypto::ProtoToSubtle(pb::SphincsVariant::SIMPLE)); EXPECT_EQ( subtle::SphincsVariant::VARIANT_UNSPECIFIED, EnumsPqcrypto::ProtoToSubtle(pb::SphincsVariant::VARIANT_UNSPECIFIED)); // Check that enum conversion covers the entire range of the proto-enum. int count = 0; for (int int_type = static_cast(pb::SphincsVariant_MIN); int_type <= static_cast(pb::SphincsVariant_MAX); int_type++) { if (pb::SphincsVariant_IsValid(int_type)) { pb::SphincsVariant type = static_cast(int_type); EXPECT_EQ(type, EnumsPqcrypto::SubtleToProto( EnumsPqcrypto::ProtoToSubtle(type))); count++; } } EXPECT_EQ(3, count); } TEST_F(EnumsTest, SphincsSignatureType) { EXPECT_EQ( pb::SphincsSignatureType::FAST_SIGNING, EnumsPqcrypto::SubtleToProto(subtle::SphincsSignatureType::FAST_SIGNING)); EXPECT_EQ(pb::SphincsSignatureType::SMALL_SIGNATURE, EnumsPqcrypto::SubtleToProto( subtle::SphincsSignatureType::SMALL_SIGNATURE)); EXPECT_EQ(pb::SphincsSignatureType::SIG_TYPE_UNSPECIFIED, EnumsPqcrypto::SubtleToProto( subtle::SphincsSignatureType::SIG_TYPE_UNSPECIFIED)); EXPECT_EQ( subtle::SphincsSignatureType::FAST_SIGNING, EnumsPqcrypto::ProtoToSubtle(pb::SphincsSignatureType::FAST_SIGNING)); EXPECT_EQ( subtle::SphincsSignatureType::SMALL_SIGNATURE, EnumsPqcrypto::ProtoToSubtle(pb::SphincsSignatureType::SMALL_SIGNATURE)); EXPECT_EQ(subtle::SphincsSignatureType::SIG_TYPE_UNSPECIFIED, EnumsPqcrypto::ProtoToSubtle( pb::SphincsSignatureType::SIG_TYPE_UNSPECIFIED)); // Check that enum conversion covers the entire range of the proto-enum. int count = 0; for (int int_type = static_cast(pb::SphincsSignatureType_MIN); int_type <= static_cast(pb::SphincsSignatureType_MAX); int_type++) { if (pb::SphincsSignatureType_IsValid(int_type)) { pb::SphincsSignatureType type = static_cast(int_type); EXPECT_EQ(type, EnumsPqcrypto::SubtleToProto( EnumsPqcrypto::ProtoToSubtle(type))); count++; } } EXPECT_EQ(3, count); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/exported_symbols.lds ================================================ *tink* *absl* ================================================ FILE: cc/hybrid/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "hybrid_config", srcs = ["hybrid_config.cc"], hdrs = ["hybrid_config.h"], include_prefix = "tink/hybrid", visibility = ["//visibility:public"], deps = [ ":ecies_aead_hkdf_private_key_manager", ":ecies_aead_hkdf_public_key_manager", ":ecies_proto_serialization", ":hybrid_decrypt_wrapper", ":hybrid_encrypt_wrapper", "//:registry", "//aead:aead_config", "//config:tink_fips", "//proto:config_cc_proto", "//util:status", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/memory", ], ) cc_library( name = "hpke_config", srcs = ["hpke_config.cc"], hdrs = ["hpke_config.h"], include_prefix = "tink/hybrid", tags = ["requires_boringcrypto_update"], visibility = ["//visibility:public"], deps = [ ":hpke_proto_serialization", ":hybrid_decrypt_wrapper", ":hybrid_encrypt_wrapper", "//:registry", "//aead:aead_config", "//config:tink_fips", "//hybrid/internal:hpke_private_key_manager", "//hybrid/internal:hpke_public_key_manager", "//util:status", "@com_google_absl//absl/memory", ], ) cc_library( name = "hybrid_decrypt_wrapper", srcs = ["hybrid_decrypt_wrapper.cc"], hdrs = ["hybrid_decrypt_wrapper.h"], include_prefix = "tink/hybrid", visibility = ["//visibility:public"], deps = [ "//:crypto_format", "//:hybrid_decrypt", "//:primitive_set", "//:primitive_wrapper", "//internal:monitoring_util", "//internal:registry_impl", "//internal:util", "//monitoring", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "hybrid_encrypt_wrapper", srcs = ["hybrid_encrypt_wrapper.cc"], hdrs = ["hybrid_encrypt_wrapper.h"], include_prefix = "tink/hybrid", visibility = ["//visibility:public"], deps = [ "//:crypto_format", "//:hybrid_encrypt", "//:primitive_set", "//:primitive_wrapper", "//internal:monitoring_util", "//internal:registry_impl", "//internal:util", "//monitoring", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "hybrid_decrypt_factory", srcs = ["hybrid_decrypt_factory.cc"], hdrs = ["hybrid_decrypt_factory.h"], include_prefix = "tink/hybrid", deps = [ ":hybrid_decrypt_wrapper", "//:hybrid_decrypt", "//:key_manager", "//:keyset_handle", "//:registry", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", ], ) cc_library( name = "hybrid_encrypt_factory", srcs = ["hybrid_encrypt_factory.cc"], hdrs = ["hybrid_encrypt_factory.h"], include_prefix = "tink/hybrid", deps = [ ":hybrid_encrypt_wrapper", "//:hybrid_encrypt", "//:key_manager", "//:keyset_handle", "//:registry", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", ], ) cc_library( name = "hybrid_key_templates", srcs = ["hybrid_key_templates.cc"], hdrs = ["hybrid_key_templates.h"], include_prefix = "tink/hybrid", visibility = ["//visibility:public"], deps = [ "//aead:aead_key_templates", "//daead:deterministic_aead_key_templates", "//proto:common_cc_proto", "//proto:ecies_aead_hkdf_cc_proto", "//proto:hpke_cc_proto", "//proto:tink_cc_proto", "@com_google_absl//absl/strings", ], ) cc_library( name = "ecies_aead_hkdf_dem_helper", srcs = ["ecies_aead_hkdf_dem_helper.cc"], hdrs = ["ecies_aead_hkdf_dem_helper.h"], include_prefix = "tink/hybrid", visibility = ["//visibility:private"], deps = [ "//:aead", "//:deterministic_aead", "//aead:aes_ctr_hmac_aead_key_manager", "//daead/subtle:aead_or_daead", "//proto:aes_ctr_cc_proto", "//proto:aes_ctr_hmac_aead_cc_proto", "//proto:aes_gcm_cc_proto", "//proto:aes_siv_cc_proto", "//proto:common_cc_proto", "//proto:hmac_cc_proto", "//proto:tink_cc_proto", "//proto:xchacha20_poly1305_cc_proto", "//subtle:aes_gcm_boringssl", "//subtle:aes_siv_boringssl", "//subtle:xchacha20_poly1305_boringssl", "//util:errors", "//util:protobuf_helper", "//util:secret_data", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", ], ) cc_library( name = "ecies_aead_hkdf_hybrid_decrypt", srcs = ["ecies_aead_hkdf_hybrid_decrypt.cc"], hdrs = ["ecies_aead_hkdf_hybrid_decrypt.h"], include_prefix = "tink/hybrid", visibility = ["//visibility:private"], deps = [ ":ecies_aead_hkdf_dem_helper", "//:hybrid_decrypt", "//internal:ec_util", "//proto:ecies_aead_hkdf_cc_proto", "//subtle:ecies_hkdf_recipient_kem_boringssl", "//util:enums", "//util:secret_data", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "ecies_aead_hkdf_hybrid_encrypt", srcs = ["ecies_aead_hkdf_hybrid_encrypt.cc"], hdrs = ["ecies_aead_hkdf_hybrid_encrypt.h"], include_prefix = "tink/hybrid", visibility = ["//visibility:private"], deps = [ ":ecies_aead_hkdf_dem_helper", "//:aead", "//:hybrid_encrypt", "//proto:ecies_aead_hkdf_cc_proto", "//subtle:ecies_hkdf_sender_kem_boringssl", "//util:enums", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "ecies_aead_hkdf_private_key_manager", srcs = ["ecies_aead_hkdf_private_key_manager.cc"], hdrs = ["ecies_aead_hkdf_private_key_manager.h"], include_prefix = "tink/hybrid", deps = [ ":ecies_aead_hkdf_hybrid_decrypt", ":ecies_aead_hkdf_public_key_manager", "//:core/key_type_manager", "//:core/private_key_type_manager", "//:core/template_util", "//:hybrid_decrypt", "//:key_manager", "//internal:ec_util", "//proto:ecies_aead_hkdf_cc_proto", "//proto:tink_cc_proto", "//util:constants", "//util:enums", "//util:errors", "//util:protobuf_helper", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "ecies_aead_hkdf_public_key_manager", srcs = ["ecies_aead_hkdf_public_key_manager.cc"], hdrs = ["ecies_aead_hkdf_public_key_manager.h"], include_prefix = "tink/hybrid", deps = [ ":ecies_aead_hkdf_hybrid_encrypt", "//:core/key_type_manager", "//:core/template_util", "//:hybrid_encrypt", "//:key_manager", "//proto:common_cc_proto", "//proto:ecies_aead_hkdf_cc_proto", "//proto:tink_cc_proto", "//util:constants", "//util:errors", "//util:protobuf_helper", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "failing_hybrid", srcs = ["failing_hybrid.cc"], hdrs = ["failing_hybrid.h"], include_prefix = "tink/hybrid", deps = [ "//:hybrid_decrypt", "//:hybrid_encrypt", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "hybrid_parameters", hdrs = ["hybrid_parameters.h"], include_prefix = "tink/hybrid", deps = ["//:parameters"], ) cc_library( name = "hybrid_public_key", hdrs = ["hybrid_public_key.h"], include_prefix = "tink/hybrid", deps = [ ":hybrid_parameters", "//:key", "@com_google_absl//absl/strings", ], ) cc_library( name = "hybrid_private_key", hdrs = ["hybrid_private_key.h"], include_prefix = "tink/hybrid", deps = [ ":hybrid_parameters", ":hybrid_public_key", "//:key", "//:private_key", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "hpke_parameters", srcs = ["hpke_parameters.cc"], hdrs = ["hpke_parameters.h"], include_prefix = "tink/hybrid", deps = [ ":hybrid_parameters", "//:parameters", "//util:status", "//util:statusor", "@com_google_absl//absl/status", ], ) cc_library( name = "hpke_public_key", srcs = ["hpke_public_key.cc"], hdrs = ["hpke_public_key.h"], include_prefix = "tink/hybrid", deps = [ ":hpke_parameters", ":hybrid_public_key", "//:key", "//:partial_key_access_token", "//internal:ec_util", "//subtle:common_enums", "//subtle:subtle_util", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:str_format", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "hpke_private_key", srcs = ["hpke_private_key.cc"], hdrs = ["hpke_private_key.h"], include_prefix = "tink/hybrid", deps = [ ":hpke_parameters", ":hpke_public_key", ":hybrid_private_key", "//:insecure_secret_key_access", "//:key", "//:partial_key_access_token", "//:restricted_data", "//internal:bn_util", "//internal:ec_util", "//internal:err_util", "//internal:ssl_unique_ptr", "//subtle:common_enums", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:str_format", ], ) cc_library( name = "hpke_proto_serialization", srcs = ["hpke_proto_serialization.cc"], hdrs = ["hpke_proto_serialization.h"], include_prefix = "tink/hybrid", deps = [ ":hpke_parameters", ":hpke_private_key", ":hpke_public_key", "//:insecure_secret_key_access", "//:partial_key_access", "//:restricted_data", "//:secret_key_access_token", "//internal:key_parser", "//internal:key_serializer", "//internal:mutable_serialization_registry", "//internal:parameters_parser", "//internal:parameters_serializer", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//proto:hpke_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "config_v0", srcs = ["config_v0.cc"], hdrs = ["config_v0.h"], include_prefix = "tink/hybrid", tags = ["requires_boringcrypto_update"], deps = [ "//:configuration", "//hybrid/internal:config_v0", "@com_google_absl//absl/log:check", ], ) cc_library( name = "key_gen_config_v0", srcs = ["key_gen_config_v0.cc"], hdrs = ["key_gen_config_v0.h"], include_prefix = "tink/hybrid", tags = ["requires_boringcrypto_update"], deps = [ "//:key_gen_configuration", "//hybrid/internal:key_gen_config_v0", "@com_google_absl//absl/log:check", ], ) cc_library( name = "ecies_parameters", srcs = ["ecies_parameters.cc"], hdrs = ["ecies_parameters.h"], include_prefix = "tink/hybrid", deps = [ ":hybrid_parameters", "//:parameters", "//aead:aes_ctr_hmac_aead_parameters", "//aead:aes_gcm_parameters", "//aead:xchacha20_poly1305_parameters", "//daead:aes_siv_parameters", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "ecies_public_key", srcs = ["ecies_public_key.cc"], hdrs = ["ecies_public_key.h"], include_prefix = "tink/hybrid", deps = [ ":ecies_parameters", ":hybrid_public_key", "//:ec_point", "//:key", "//:partial_key_access_token", "//internal:ec_util", "//internal:ssl_unique_ptr", "//subtle:common_enums", "//subtle:subtle_util", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:str_format", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "ecies_private_key", srcs = ["ecies_private_key.cc"], hdrs = ["ecies_private_key.h"], include_prefix = "tink/hybrid", deps = [ ":ecies_parameters", ":ecies_public_key", ":hybrid_private_key", "//:ec_point", "//:insecure_secret_key_access", "//:key", "//:partial_key_access_token", "//:restricted_big_integer", "//:restricted_data", "//internal:bn_util", "//internal:ec_util", "//internal:err_util", "//internal:ssl_unique_ptr", "//subtle:common_enums", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:str_format", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "ecies_proto_serialization", srcs = ["ecies_proto_serialization.cc"], hdrs = ["ecies_proto_serialization.h"], include_prefix = "tink/hybrid", deps = [ ":ecies_parameters", ":ecies_private_key", ":ecies_public_key", "//:big_integer", "//:ec_point", "//:insecure_secret_key_access", "//:partial_key_access", "//:restricted_big_integer", "//:restricted_data", "//:secret_key_access_token", "//internal:bn_encoding_util", "//internal:key_parser", "//internal:key_serializer", "//internal:mutable_serialization_registry", "//internal:parameters_parser", "//internal:parameters_serializer", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//proto:aes_ctr_cc_proto", "//proto:aes_ctr_hmac_aead_cc_proto", "//proto:aes_gcm_cc_proto", "//proto:aes_siv_cc_proto", "//proto:common_cc_proto", "//proto:ecies_aead_hkdf_cc_proto", "//proto:hmac_cc_proto", "//proto:tink_cc_proto", "//proto:xchacha20_poly1305_cc_proto", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) # tests cc_test( name = "hybrid_config_test", size = "small", srcs = ["hybrid_config_test.cc"], tags = ["fips"], deps = [ ":ecies_aead_hkdf_private_key_manager", ":ecies_aead_hkdf_public_key_manager", ":ecies_parameters", ":ecies_private_key", ":ecies_public_key", ":hybrid_config", ":hybrid_key_templates", "//:crypto_format", "//:hybrid_decrypt", "//:hybrid_encrypt", "//:insecure_secret_key_access", "//:key", "//:keyset_handle", "//:parameters", "//:partial_key_access", "//:primitive_set", "//:registry", "//:restricted_data", "//config:global_registry", "//internal:ec_util", "//internal:fips_utils", "//internal:mutable_serialization_registry", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//internal:serialization", "//proto:aes_gcm_cc_proto", "//proto:common_cc_proto", "//proto:ecies_aead_hkdf_cc_proto", "//proto:tink_cc_proto", "//subtle:random", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hpke_config_test", size = "small", srcs = ["hpke_config_test.cc"], tags = ["requires_boringcrypto_update"], deps = [ ":hpke_config", ":hpke_parameters", ":hpke_private_key", ":hpke_public_key", ":hybrid_key_templates", "//:hybrid_decrypt", "//:hybrid_encrypt", "//:insecure_secret_key_access", "//:key", "//:keyset_handle", "//:parameters", "//:partial_key_access", "//:registry", "//:restricted_data", "//config:global_registry", "//config:tink_fips", "//hybrid/internal:hpke_private_key_manager", "//hybrid/internal:hpke_public_key_manager", "//internal:ec_util", "//internal:mutable_serialization_registry", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//internal:serialization", "//proto:hpke_cc_proto", "//proto:tink_cc_proto", "//subtle:random", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hybrid_decrypt_wrapper_test", size = "small", srcs = ["hybrid_decrypt_wrapper_test.cc"], deps = [ ":failing_hybrid", ":hybrid_decrypt_wrapper", "//:hybrid_decrypt", "//:primitive_set", "//:registry", "//internal:registry_impl", "//monitoring", "//monitoring:monitoring_client_mocks", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hybrid_encrypt_wrapper_test", size = "small", srcs = ["hybrid_encrypt_wrapper_test.cc"], deps = [ ":failing_hybrid", ":hybrid_encrypt_wrapper", "//:hybrid_encrypt", "//:primitive_set", "//:registry", "//internal:registry_impl", "//monitoring", "//monitoring:monitoring_client_mocks", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hybrid_decrypt_factory_test", size = "small", srcs = ["hybrid_decrypt_factory_test.cc"], deps = [ ":ecies_aead_hkdf_public_key_manager", ":hybrid_config", ":hybrid_decrypt_factory", "//:crypto_format", "//:hybrid_decrypt", "//:hybrid_encrypt", "//:keyset_handle", "//proto:ecies_aead_hkdf_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:test_keyset_handle", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hybrid_encrypt_factory_test", size = "small", srcs = ["hybrid_encrypt_factory_test.cc"], deps = [ ":hybrid_config", ":hybrid_encrypt_factory", "//:crypto_format", "//:hybrid_encrypt", "//:keyset_handle", "//proto:ecies_aead_hkdf_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:test_keyset_handle", "//util:test_util", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hybrid_key_templates_test", size = "small", srcs = ["hybrid_key_templates_test.cc"], deps = [ ":ecies_aead_hkdf_private_key_manager", ":hybrid_config", ":hybrid_key_templates", "//aead:aead_key_templates", "//daead:deterministic_aead_key_templates", "//hybrid/internal:hpke_private_key_manager", "//proto:common_cc_proto", "//proto:ecies_aead_hkdf_cc_proto", "//proto:hpke_cc_proto", "//proto:tink_cc_proto", "//util:test_matchers", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ecies_aead_hkdf_dem_helper_test", size = "small", srcs = ["ecies_aead_hkdf_dem_helper_test.cc"], deps = [ ":ecies_aead_hkdf_dem_helper", "//aead:aes_gcm_key_manager", "//daead:aes_siv_key_manager", "//daead/subtle:aead_or_daead", "//proto:aes_gcm_cc_proto", "//proto:aes_siv_cc_proto", "//proto:tink_cc_proto", "//util:secret_data", "//util:status", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ecies_aead_hkdf_hybrid_decrypt_test", size = "large", srcs = ["ecies_aead_hkdf_hybrid_decrypt_test.cc"], deps = [ ":ecies_aead_hkdf_hybrid_decrypt", ":ecies_aead_hkdf_hybrid_encrypt", "//:hybrid_decrypt", "//:hybrid_encrypt", "//:registry", "//aead:aes_ctr_hmac_aead_key_manager", "//aead:aes_gcm_key_manager", "//aead:xchacha20_poly1305_key_manager", "//daead:aes_siv_key_manager", "//internal:ec_util", "//internal:ssl_util", "//proto:aes_gcm_cc_proto", "//proto:common_cc_proto", "//proto:ecies_aead_hkdf_cc_proto", "//subtle:random", "//util:enums", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ecies_aead_hkdf_hybrid_encrypt_test", size = "small", srcs = ["ecies_aead_hkdf_hybrid_encrypt_test.cc"], deps = [ ":ecies_aead_hkdf_hybrid_encrypt", "//:hybrid_encrypt", "//aead:aes_gcm_key_manager", "//internal:ec_util", "//proto:common_cc_proto", "//proto:ecies_aead_hkdf_cc_proto", "//util:enums", "//util:statusor", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ecies_aead_hkdf_private_key_manager_test", size = "small", srcs = ["ecies_aead_hkdf_private_key_manager_test.cc"], deps = [ ":ecies_aead_hkdf_hybrid_encrypt", ":ecies_aead_hkdf_private_key_manager", ":ecies_aead_hkdf_public_key_manager", ":hybrid_key_templates", "//:hybrid_decrypt", "//:registry", "//aead:aead_key_templates", "//aead:aes_ctr_hmac_aead_key_manager", "//aead:aes_gcm_key_manager", "//proto:aes_eax_cc_proto", "//proto:common_cc_proto", "//proto:ecies_aead_hkdf_cc_proto", "//proto:tink_cc_proto", "//subtle:hybrid_test_util", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ecies_aead_hkdf_public_key_manager_test", size = "small", srcs = ["ecies_aead_hkdf_public_key_manager_test.cc"], deps = [ ":ecies_aead_hkdf_private_key_manager", ":ecies_aead_hkdf_public_key_manager", "//:hybrid_encrypt", "//:registry", "//aead:aead_key_templates", "//aead:aes_gcm_key_manager", "//proto:aes_eax_cc_proto", "//proto:common_cc_proto", "//proto:ecies_aead_hkdf_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "failing_hybrid_test", srcs = ["failing_hybrid_test.cc"], deps = [ ":failing_hybrid", "//:hybrid_decrypt", "//:hybrid_encrypt", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hpke_parameters_test", srcs = ["hpke_parameters_test.cc"], deps = [ ":hpke_parameters", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hpke_public_key_test", srcs = ["hpke_public_key_test.cc"], deps = [ ":hpke_parameters", ":hpke_public_key", "//:partial_key_access", "//internal:ec_util", "//internal:ssl_unique_ptr", "//subtle:common_enums", "//subtle:random", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hpke_private_key_test", srcs = ["hpke_private_key_test.cc"], deps = [ ":hpke_parameters", ":hpke_private_key", ":hpke_public_key", "//:insecure_secret_key_access", "//:partial_key_access", "//:restricted_data", "//internal:ec_util", "//internal:ssl_unique_ptr", "//subtle:common_enums", "//subtle:random", "//util:secret_data", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hpke_proto_serialization_test", srcs = ["hpke_proto_serialization_test.cc"], deps = [ ":hpke_parameters", ":hpke_private_key", ":hpke_proto_serialization", ":hpke_public_key", "//:insecure_secret_key_access", "//:key", "//:parameters", "//:partial_key_access", "//:restricted_data", "//internal:ec_util", "//internal:mutable_serialization_registry", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//internal:serialization", "//internal:ssl_unique_ptr", "//proto:hpke_cc_proto", "//proto:tink_cc_proto", "//subtle:common_enums", "//subtle:random", "//util:secret_data", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "config_v0_test", srcs = ["config_v0_test.cc"], tags = ["requires_boringcrypto_update"], deps = [ ":config_v0", ":hybrid_key_templates", ":key_gen_config_v0", "//:hybrid_decrypt", "//:hybrid_encrypt", "//:keyset_handle", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ecies_parameters_test", srcs = ["ecies_parameters_test.cc"], deps = [ ":ecies_parameters", "//:parameters", "//aead:aes_ctr_hmac_aead_parameters", "//aead:aes_gcm_parameters", "//aead:xchacha20_poly1305_parameters", "//daead:aes_siv_parameters", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ecies_public_key_test", srcs = ["ecies_public_key_test.cc"], deps = [ ":ecies_parameters", ":ecies_public_key", "//:big_integer", "//:ec_point", "//:parameters", "//:partial_key_access", "//daead:aes_siv_parameters", "//internal:ec_util", "//internal:ssl_unique_ptr", "//subtle:common_enums", "//subtle:random", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ecies_private_key_test", srcs = ["ecies_private_key_test.cc"], deps = [ ":ecies_parameters", ":ecies_private_key", ":ecies_public_key", "//:big_integer", "//:ec_point", "//:insecure_secret_key_access", "//:partial_key_access", "//:restricted_big_integer", "//:restricted_data", "//internal:ec_util", "//subtle:common_enums", "//subtle:random", "//util:secret_data", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ecies_proto_serialization_test", srcs = ["ecies_proto_serialization_test.cc"], deps = [ ":ecies_parameters", ":ecies_private_key", ":ecies_proto_serialization", ":ecies_public_key", "//:big_integer", "//:ec_point", "//:insecure_secret_key_access", "//:key", "//:parameters", "//:partial_key_access", "//:restricted_big_integer", "//:restricted_data", "//internal:ec_util", "//internal:mutable_serialization_registry", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//internal:serialization", "//proto:aes_ctr_cc_proto", "//proto:aes_ctr_hmac_aead_cc_proto", "//proto:aes_gcm_cc_proto", "//proto:aes_siv_cc_proto", "//proto:common_cc_proto", "//proto:ecies_aead_hkdf_cc_proto", "//proto:hmac_cc_proto", "//proto:tink_cc_proto", "//proto:xchacha20_poly1305_cc_proto", "//subtle:common_enums", "//util:enums", "//util:secret_data", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/hybrid/CMakeLists.txt ================================================ tink_module(hybrid) add_subdirectory(internal) tink_cc_library( NAME hybrid_config SRCS hybrid_config.cc hybrid_config.h DEPS tink::hybrid::ecies_aead_hkdf_private_key_manager tink::hybrid::ecies_aead_hkdf_public_key_manager tink::hybrid::ecies_proto_serialization tink::hybrid::hybrid_decrypt_wrapper tink::hybrid::hybrid_encrypt_wrapper absl::core_headers absl::memory tink::core::registry tink::aead::aead_config tink::config::tink_fips tink::util::status tink::proto::config_cc_proto ) tink_cc_library( NAME hpke_config SRCS hpke_config.cc hpke_config.h DEPS tink::hybrid::hpke_proto_serialization tink::hybrid::hybrid_decrypt_wrapper tink::hybrid::hybrid_encrypt_wrapper absl::memory tink::core::registry tink::aead::aead_config tink::config::tink_fips tink::hybrid::internal::hpke_private_key_manager tink::hybrid::internal::hpke_public_key_manager tink::util::status TAGS exclude_if_openssl ) tink_cc_library( NAME hybrid_decrypt_wrapper SRCS hybrid_decrypt_wrapper.cc hybrid_decrypt_wrapper.h DEPS absl::memory absl::status absl::strings tink::core::crypto_format tink::core::hybrid_decrypt tink::core::primitive_set tink::core::primitive_wrapper tink::internal::monitoring_util tink::internal::registry_impl tink::internal::util tink::monitoring::monitoring tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME hybrid_encrypt_wrapper SRCS hybrid_encrypt_wrapper.cc hybrid_encrypt_wrapper.h DEPS absl::memory absl::status absl::strings tink::core::crypto_format tink::core::hybrid_encrypt tink::core::primitive_set tink::core::primitive_wrapper tink::internal::monitoring_util tink::internal::registry_impl tink::internal::util tink::monitoring::monitoring tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME hybrid_decrypt_factory SRCS hybrid_decrypt_factory.cc hybrid_decrypt_factory.h DEPS tink::hybrid::hybrid_decrypt_wrapper absl::core_headers tink::core::hybrid_decrypt tink::core::key_manager tink::core::keyset_handle tink::core::registry tink::util::status tink::util::statusor ) tink_cc_library( NAME hybrid_encrypt_factory SRCS hybrid_encrypt_factory.cc hybrid_encrypt_factory.h DEPS tink::hybrid::hybrid_encrypt_wrapper absl::core_headers tink::core::hybrid_encrypt tink::core::key_manager tink::core::keyset_handle tink::core::registry tink::util::status tink::util::statusor ) tink_cc_library( NAME hybrid_key_templates SRCS hybrid_key_templates.cc hybrid_key_templates.h DEPS absl::strings tink::aead::aead_key_templates tink::daead::deterministic_aead_key_templates tink::proto::common_cc_proto tink::proto::ecies_aead_hkdf_cc_proto tink::proto::hpke_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME ecies_aead_hkdf_dem_helper SRCS ecies_aead_hkdf_dem_helper.cc ecies_aead_hkdf_dem_helper.h DEPS absl::memory absl::status absl::statusor absl::strings tink::core::aead tink::core::deterministic_aead tink::aead::aes_ctr_hmac_aead_key_manager tink::daead::subtle::aead_or_daead tink::subtle::aes_gcm_boringssl tink::subtle::aes_siv_boringssl tink::subtle::xchacha20_poly1305_boringssl tink::util::errors tink::util::protobuf_helper tink::util::secret_data tink::util::status tink::util::statusor tink::proto::aes_ctr_cc_proto tink::proto::aes_ctr_hmac_aead_cc_proto tink::proto::aes_gcm_cc_proto tink::proto::aes_siv_cc_proto tink::proto::common_cc_proto tink::proto::hmac_cc_proto tink::proto::tink_cc_proto tink::proto::xchacha20_poly1305_cc_proto ) tink_cc_library( NAME ecies_aead_hkdf_hybrid_decrypt SRCS ecies_aead_hkdf_hybrid_decrypt.cc ecies_aead_hkdf_hybrid_decrypt.h DEPS tink::hybrid::ecies_aead_hkdf_dem_helper absl::memory absl::status absl::string_view tink::core::hybrid_decrypt tink::internal::ec_util tink::subtle::ecies_hkdf_recipient_kem_boringssl tink::util::enums tink::util::secret_data tink::util::status tink::util::statusor tink::proto::ecies_aead_hkdf_cc_proto ) tink_cc_library( NAME ecies_aead_hkdf_hybrid_encrypt SRCS ecies_aead_hkdf_hybrid_encrypt.cc ecies_aead_hkdf_hybrid_encrypt.h DEPS tink::hybrid::ecies_aead_hkdf_dem_helper absl::memory absl::status absl::strings tink::core::aead tink::core::hybrid_encrypt tink::subtle::ecies_hkdf_sender_kem_boringssl tink::util::enums tink::util::status tink::util::statusor tink::proto::ecies_aead_hkdf_cc_proto ) tink_cc_library( NAME ecies_aead_hkdf_private_key_manager SRCS ecies_aead_hkdf_private_key_manager.cc ecies_aead_hkdf_private_key_manager.h DEPS tink::hybrid::ecies_aead_hkdf_hybrid_decrypt tink::hybrid::ecies_aead_hkdf_public_key_manager absl::memory absl::status absl::strings tink::core::key_type_manager tink::core::private_key_type_manager tink::core::template_util tink::core::hybrid_decrypt tink::core::key_manager tink::internal::ec_util tink::util::constants tink::util::enums tink::util::errors tink::util::protobuf_helper tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::ecies_aead_hkdf_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME ecies_aead_hkdf_public_key_manager SRCS ecies_aead_hkdf_public_key_manager.cc ecies_aead_hkdf_public_key_manager.h DEPS tink::hybrid::ecies_aead_hkdf_hybrid_encrypt absl::memory absl::status absl::strings tink::core::key_type_manager tink::core::template_util tink::core::hybrid_encrypt tink::core::key_manager tink::util::constants tink::util::errors tink::util::protobuf_helper tink::util::status tink::util::statusor tink::util::validation tink::proto::common_cc_proto tink::proto::ecies_aead_hkdf_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME failing_hybrid SRCS failing_hybrid.cc failing_hybrid.h DEPS absl::memory absl::status absl::strings tink::core::hybrid_decrypt tink::core::hybrid_encrypt tink::util::status tink::util::statusor ) tink_cc_library( NAME hybrid_parameters SRCS hybrid_parameters.h DEPS tink::core::parameters ) tink_cc_library( NAME hybrid_public_key SRCS hybrid_public_key.h DEPS tink::hybrid::hybrid_parameters absl::strings tink::core::key ) tink_cc_library( NAME hybrid_private_key SRCS hybrid_private_key.h DEPS tink::hybrid::hybrid_parameters tink::hybrid::hybrid_public_key absl::strings absl::optional tink::core::key tink::core::private_key ) tink_cc_library( NAME hpke_parameters SRCS hpke_parameters.cc hpke_parameters.h DEPS tink::hybrid::hybrid_parameters absl::status tink::core::parameters tink::util::status tink::util::statusor ) tink_cc_library( NAME hpke_public_key SRCS hpke_public_key.cc hpke_public_key.h DEPS tink::hybrid::hpke_parameters tink::hybrid::hybrid_public_key absl::status absl::strings absl::str_format absl::optional tink::core::key tink::core::partial_key_access_token tink::internal::ec_util tink::subtle::common_enums tink::subtle::subtle_util tink::util::status tink::util::statusor ) tink_cc_library( NAME hpke_private_key SRCS hpke_private_key.cc hpke_private_key.h DEPS tink::hybrid::hpke_parameters tink::hybrid::hpke_public_key tink::hybrid::hybrid_private_key absl::status absl::strings absl::str_format crypto tink::core::insecure_secret_key_access tink::core::key tink::core::partial_key_access_token tink::core::restricted_data tink::internal::bn_util tink::internal::ec_util tink::internal::err_util tink::internal::ssl_unique_ptr tink::subtle::common_enums tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME hpke_proto_serialization SRCS hpke_proto_serialization.cc hpke_proto_serialization.h DEPS tink::hybrid::hpke_parameters tink::hybrid::hpke_private_key tink::hybrid::hpke_public_key absl::core_headers absl::status absl::strings absl::optional tink::core::insecure_secret_key_access tink::core::partial_key_access tink::core::restricted_data tink::core::secret_key_access_token tink::internal::key_parser tink::internal::key_serializer tink::internal::mutable_serialization_registry tink::internal::parameters_parser tink::internal::parameters_serializer tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::util::status tink::util::statusor tink::proto::hpke_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME config_v0 SRCS config_v0.cc config_v0.h DEPS absl::check tink::core::configuration tink::hybrid::internal::config_v0 TAGS exclude_if_openssl ) tink_cc_library( NAME config_v0_openssl SRCS config_v0.cc config_v0.h DEPS absl::check tink::core::configuration tink::hybrid::internal::config_v0_openssl TAGS exclude_if_boringssl ) tink_cc_library( NAME key_gen_config_v0 SRCS key_gen_config_v0.cc key_gen_config_v0.h DEPS absl::check tink::core::key_gen_configuration tink::hybrid::internal::key_gen_config_v0 TAGS exclude_if_openssl ) tink_cc_library( NAME key_gen_config_v0_openssl SRCS key_gen_config_v0.cc key_gen_config_v0.h DEPS absl::check tink::core::key_gen_configuration tink::hybrid::internal::key_gen_config_v0_openssl TAGS exclude_if_boringssl ) tink_cc_library( NAME ecies_parameters SRCS ecies_parameters.cc ecies_parameters.h DEPS tink::hybrid::hybrid_parameters absl::core_headers absl::status absl::strings absl::optional tink::core::parameters tink::aead::aes_ctr_hmac_aead_parameters tink::aead::aes_gcm_parameters tink::aead::xchacha20_poly1305_parameters tink::daead::aes_siv_parameters tink::util::status tink::util::statusor ) tink_cc_library( NAME ecies_public_key SRCS ecies_public_key.cc ecies_public_key.h DEPS tink::hybrid::ecies_parameters tink::hybrid::hybrid_public_key absl::status absl::strings absl::str_format absl::optional crypto tink::core::ec_point tink::core::key tink::core::partial_key_access_token tink::internal::ec_util tink::internal::ssl_unique_ptr tink::subtle::common_enums tink::subtle::subtle_util tink::util::status tink::util::statusor ) tink_cc_library( NAME ecies_private_key SRCS ecies_private_key.cc ecies_private_key.h DEPS tink::hybrid::ecies_parameters tink::hybrid::ecies_public_key tink::hybrid::hybrid_private_key absl::status absl::strings absl::str_format absl::optional crypto tink::core::ec_point tink::core::insecure_secret_key_access tink::core::key tink::core::partial_key_access_token tink::core::restricted_big_integer tink::core::restricted_data tink::internal::bn_util tink::internal::ec_util tink::internal::err_util tink::internal::ssl_unique_ptr tink::subtle::common_enums tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME ecies_proto_serialization SRCS ecies_proto_serialization.cc ecies_proto_serialization.h DEPS tink::hybrid::ecies_parameters tink::hybrid::ecies_private_key tink::hybrid::ecies_public_key absl::core_headers absl::status absl::strings absl::optional crypto tink::core::big_integer tink::core::ec_point tink::core::insecure_secret_key_access tink::core::partial_key_access tink::core::restricted_big_integer tink::core::restricted_data tink::core::secret_key_access_token tink::internal::bn_encoding_util tink::internal::key_parser tink::internal::key_serializer tink::internal::mutable_serialization_registry tink::internal::parameters_parser tink::internal::parameters_serializer tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::util::status tink::util::statusor tink::proto::aes_ctr_cc_proto tink::proto::aes_ctr_hmac_aead_cc_proto tink::proto::aes_gcm_cc_proto tink::proto::aes_siv_cc_proto tink::proto::common_cc_proto tink::proto::ecies_aead_hkdf_cc_proto tink::proto::hmac_cc_proto tink::proto::tink_cc_proto tink::proto::xchacha20_poly1305_cc_proto ) # tests tink_cc_test( NAME hybrid_config_test SRCS hybrid_config_test.cc DEPS tink::hybrid::ecies_aead_hkdf_private_key_manager tink::hybrid::ecies_aead_hkdf_public_key_manager tink::hybrid::ecies_parameters tink::hybrid::ecies_private_key tink::hybrid::ecies_public_key tink::hybrid::hybrid_config tink::hybrid::hybrid_key_templates gmock absl::memory absl::status absl::strings absl::optional crypto tink::core::crypto_format tink::core::hybrid_decrypt tink::core::hybrid_encrypt tink::core::insecure_secret_key_access tink::core::key tink::core::keyset_handle tink::core::parameters tink::core::partial_key_access tink::core::primitive_set tink::core::registry tink::core::restricted_data tink::config::global_registry tink::internal::ec_util tink::internal::fips_utils tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::internal::serialization tink::subtle::random tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::aes_gcm_cc_proto tink::proto::common_cc_proto tink::proto::ecies_aead_hkdf_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME hpke_config_test SRCS hpke_config_test.cc DEPS tink::hybrid::hpke_config tink::hybrid::hpke_parameters tink::hybrid::hpke_private_key tink::hybrid::hpke_public_key tink::hybrid::hybrid_key_templates gmock absl::status tink::core::hybrid_decrypt tink::core::hybrid_encrypt tink::core::insecure_secret_key_access tink::core::key tink::core::keyset_handle tink::core::parameters tink::core::partial_key_access tink::core::registry tink::core::restricted_data tink::config::global_registry tink::config::tink_fips tink::hybrid::internal::hpke_private_key_manager tink::hybrid::internal::hpke_public_key_manager tink::internal::ec_util tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::internal::serialization tink::subtle::random tink::util::statusor tink::util::test_matchers tink::proto::hpke_cc_proto tink::proto::tink_cc_proto TAGS exclude_if_openssl ) tink_cc_test( NAME hybrid_decrypt_wrapper_test SRCS hybrid_decrypt_wrapper_test.cc DEPS tink::hybrid::failing_hybrid tink::hybrid::hybrid_decrypt_wrapper gmock absl::flat_hash_map absl::memory absl::status absl::strings tink::core::hybrid_decrypt tink::core::primitive_set tink::core::registry tink::internal::registry_impl tink::monitoring::monitoring tink::monitoring::monitoring_client_mocks tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::tink_cc_proto ) tink_cc_test( NAME hybrid_encrypt_wrapper_test SRCS hybrid_encrypt_wrapper_test.cc DEPS tink::hybrid::failing_hybrid tink::hybrid::hybrid_encrypt_wrapper gmock absl::flat_hash_map absl::memory absl::status absl::string_view tink::core::hybrid_encrypt tink::core::primitive_set tink::core::registry tink::internal::registry_impl tink::monitoring::monitoring tink::monitoring::monitoring_client_mocks tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::tink_cc_proto ) tink_cc_test( NAME hybrid_decrypt_factory_test SRCS hybrid_decrypt_factory_test.cc DEPS tink::hybrid::ecies_aead_hkdf_public_key_manager tink::hybrid::hybrid_config tink::hybrid::hybrid_decrypt_factory gmock absl::memory tink::core::crypto_format tink::core::hybrid_decrypt tink::core::hybrid_encrypt tink::core::keyset_handle tink::util::status tink::util::test_keyset_handle tink::util::test_util tink::proto::ecies_aead_hkdf_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME hybrid_encrypt_factory_test SRCS hybrid_encrypt_factory_test.cc DEPS tink::hybrid::hybrid_config tink::hybrid::hybrid_encrypt_factory gmock tink::core::crypto_format tink::core::hybrid_encrypt tink::core::keyset_handle tink::util::status tink::util::test_keyset_handle tink::util::test_util tink::proto::ecies_aead_hkdf_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME hybrid_key_templates_test SRCS hybrid_key_templates_test.cc DEPS tink::hybrid::ecies_aead_hkdf_private_key_manager tink::hybrid::hybrid_config tink::hybrid::hybrid_key_templates gmock tink::aead::aead_key_templates tink::daead::deterministic_aead_key_templates tink::hybrid::internal::hpke_private_key_manager tink::util::test_matchers tink::proto::common_cc_proto tink::proto::ecies_aead_hkdf_cc_proto tink::proto::hpke_cc_proto tink::proto::tink_cc_proto TAGS exclude_if_openssl ) tink_cc_test( NAME ecies_aead_hkdf_dem_helper_test SRCS ecies_aead_hkdf_dem_helper_test.cc DEPS tink::hybrid::ecies_aead_hkdf_dem_helper gmock absl::status absl::string_view tink::aead::aes_gcm_key_manager tink::daead::aes_siv_key_manager tink::daead::subtle::aead_or_daead tink::util::secret_data tink::util::status tink::util::test_matchers tink::util::test_util tink::proto::aes_gcm_cc_proto tink::proto::aes_siv_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME ecies_aead_hkdf_hybrid_decrypt_test SRCS ecies_aead_hkdf_hybrid_decrypt_test.cc DEPS tink::hybrid::ecies_aead_hkdf_hybrid_decrypt tink::hybrid::ecies_aead_hkdf_hybrid_encrypt gmock absl::memory absl::status absl::string_view tink::core::hybrid_decrypt tink::core::hybrid_encrypt tink::core::registry tink::aead::aes_ctr_hmac_aead_key_manager tink::aead::aes_gcm_key_manager tink::aead::xchacha20_poly1305_key_manager tink::daead::aes_siv_key_manager tink::internal::ec_util tink::internal::ssl_util tink::subtle::random tink::util::enums tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::aes_gcm_cc_proto tink::proto::common_cc_proto tink::proto::ecies_aead_hkdf_cc_proto ) tink_cc_test( NAME ecies_aead_hkdf_hybrid_encrypt_test SRCS ecies_aead_hkdf_hybrid_encrypt_test.cc DEPS tink::hybrid::ecies_aead_hkdf_hybrid_encrypt gmock absl::memory absl::status tink::core::hybrid_encrypt tink::aead::aes_gcm_key_manager tink::internal::ec_util tink::util::enums tink::util::statusor tink::util::test_util tink::proto::common_cc_proto tink::proto::ecies_aead_hkdf_cc_proto ) tink_cc_test( NAME ecies_aead_hkdf_private_key_manager_test SRCS ecies_aead_hkdf_private_key_manager_test.cc DEPS tink::hybrid::ecies_aead_hkdf_hybrid_encrypt tink::hybrid::ecies_aead_hkdf_private_key_manager tink::hybrid::ecies_aead_hkdf_public_key_manager tink::hybrid::hybrid_key_templates gmock absl::memory absl::status tink::core::hybrid_decrypt tink::core::registry tink::aead::aead_key_templates tink::aead::aes_ctr_hmac_aead_key_manager tink::aead::aes_gcm_key_manager tink::subtle::hybrid_test_util tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::aes_eax_cc_proto tink::proto::common_cc_proto tink::proto::ecies_aead_hkdf_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME ecies_aead_hkdf_public_key_manager_test SRCS ecies_aead_hkdf_public_key_manager_test.cc DEPS tink::hybrid::ecies_aead_hkdf_private_key_manager tink::hybrid::ecies_aead_hkdf_public_key_manager gmock absl::status tink::core::hybrid_encrypt tink::core::registry tink::aead::aead_key_templates tink::aead::aes_gcm_key_manager tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::aes_eax_cc_proto tink::proto::common_cc_proto tink::proto::ecies_aead_hkdf_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME failing_hybrid_test SRCS failing_hybrid_test.cc DEPS tink::hybrid::failing_hybrid gmock absl::status tink::core::hybrid_decrypt tink::core::hybrid_encrypt tink::util::test_matchers ) tink_cc_test( NAME hpke_parameters_test SRCS hpke_parameters_test.cc DEPS tink::hybrid::hpke_parameters gmock absl::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME hpke_public_key_test SRCS hpke_public_key_test.cc DEPS tink::hybrid::hpke_parameters tink::hybrid::hpke_public_key gmock absl::status absl::strings absl::optional crypto tink::core::partial_key_access tink::internal::ec_util tink::internal::ssl_unique_ptr tink::subtle::common_enums tink::subtle::random tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME hpke_private_key_test SRCS hpke_private_key_test.cc DEPS tink::hybrid::hpke_parameters tink::hybrid::hpke_private_key tink::hybrid::hpke_public_key gmock absl::status absl::strings absl::string_view absl::optional crypto tink::core::insecure_secret_key_access tink::core::partial_key_access tink::core::restricted_data tink::internal::ec_util tink::internal::ssl_unique_ptr tink::subtle::common_enums tink::subtle::random tink::util::secret_data tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME hpke_proto_serialization_test SRCS hpke_proto_serialization_test.cc DEPS tink::hybrid::hpke_parameters tink::hybrid::hpke_private_key tink::hybrid::hpke_proto_serialization tink::hybrid::hpke_public_key gmock absl::status absl::string_view absl::optional crypto tink::core::insecure_secret_key_access tink::core::key tink::core::parameters tink::core::partial_key_access tink::core::restricted_data tink::internal::ec_util tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::internal::serialization tink::internal::ssl_unique_ptr tink::subtle::common_enums tink::subtle::random tink::util::secret_data tink::util::statusor tink::util::test_matchers tink::proto::hpke_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME config_v0_test SRCS config_v0_test.cc DEPS tink::hybrid::config_v0 tink::hybrid::hybrid_key_templates tink::hybrid::key_gen_config_v0 gmock tink::core::hybrid_decrypt tink::core::hybrid_encrypt tink::core::keyset_handle tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto TAGS exclude_if_openssl ) tink_cc_test( NAME config_v0_openssl_test SRCS config_v0_test.cc DEPS tink::hybrid::config_v0_openssl tink::hybrid::hybrid_key_templates tink::hybrid::key_gen_config_v0_openssl gmock tink::core::hybrid_decrypt tink::core::hybrid_encrypt tink::core::keyset_handle tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto TAGS exclude_if_boringssl ) tink_cc_test( NAME ecies_parameters_test SRCS ecies_parameters_test.cc DEPS tink::hybrid::ecies_parameters gmock absl::status absl::strings absl::string_view absl::optional tink::core::parameters tink::aead::aes_ctr_hmac_aead_parameters tink::aead::aes_gcm_parameters tink::aead::xchacha20_poly1305_parameters tink::daead::aes_siv_parameters tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME ecies_public_key_test SRCS ecies_public_key_test.cc DEPS tink::hybrid::ecies_parameters tink::hybrid::ecies_public_key gmock absl::memory absl::status absl::strings absl::optional crypto tink::core::big_integer tink::core::ec_point tink::core::parameters tink::core::partial_key_access tink::daead::aes_siv_parameters tink::internal::ec_util tink::internal::ssl_unique_ptr tink::subtle::common_enums tink::subtle::random tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME ecies_private_key_test SRCS ecies_private_key_test.cc DEPS tink::hybrid::ecies_parameters tink::hybrid::ecies_private_key tink::hybrid::ecies_public_key gmock absl::status absl::strings absl::string_view absl::optional crypto tink::core::big_integer tink::core::ec_point tink::core::insecure_secret_key_access tink::core::partial_key_access tink::core::restricted_big_integer tink::core::restricted_data tink::internal::ec_util tink::subtle::common_enums tink::subtle::random tink::util::secret_data tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME ecies_proto_serialization_test SRCS ecies_proto_serialization_test.cc DEPS tink::hybrid::ecies_parameters tink::hybrid::ecies_private_key tink::hybrid::ecies_proto_serialization tink::hybrid::ecies_public_key gmock absl::status absl::strings absl::string_view absl::optional crypto tink::core::big_integer tink::core::ec_point tink::core::insecure_secret_key_access tink::core::key tink::core::parameters tink::core::partial_key_access tink::core::restricted_big_integer tink::core::restricted_data tink::internal::ec_util tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::internal::serialization tink::subtle::common_enums tink::util::enums tink::util::secret_data tink::util::statusor tink::util::test_matchers tink::proto::aes_ctr_cc_proto tink::proto::aes_ctr_hmac_aead_cc_proto tink::proto::aes_gcm_cc_proto tink::proto::aes_siv_cc_proto tink::proto::common_cc_proto tink::proto::ecies_aead_hkdf_cc_proto tink::proto::hmac_cc_proto tink::proto::tink_cc_proto tink::proto::xchacha20_poly1305_cc_proto ) ================================================ FILE: cc/hybrid/config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/config_v0.h" #include "absl/log/check.h" #include "tink/configuration.h" #include "tink/hybrid/internal/config_v0.h" namespace crypto { namespace tink { const Configuration& ConfigHybridV0() { static const Configuration* instance = [] { static Configuration* config = new Configuration(); CHECK_OK(internal::AddHybridV0(*config)); return config; }(); return *instance; } } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_CONFIG_V0_H_ #define TINK_HYBRID_CONFIG_V0_H_ #include "tink/configuration.h" namespace crypto { namespace tink { // Configuration used to generate Hybrid Encryption primitives with recommended // key managers. const Configuration& ConfigHybridV0(); } // namespace tink } // namespace crypto #endif // TINK_HYBRID_CONFIG_V0_H_ ================================================ FILE: cc/hybrid/config_v0_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/config_v0.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/hybrid/hybrid_key_templates.h" #include "tink/hybrid/key_gen_config_v0.h" #include "tink/hybrid_decrypt.h" #include "tink/hybrid_encrypt.h" #include "tink/keyset_handle.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::google::crypto::tink::KeyTemplate; using ::testing::TestWithParam; using ::testing::Values; using ConfigV0Test = TestWithParam; #ifdef OPENSSL_IS_BORINGSSL INSTANTIATE_TEST_SUITE_P( ConfigV0TestSuite, ConfigV0Test, Values(HybridKeyTemplates::EciesP256HkdfHmacSha256Aes128Gcm(), HybridKeyTemplates::HpkeX25519HkdfSha256Aes128Gcm())); #else INSTANTIATE_TEST_SUITE_P( ConfigV0TestSuite, ConfigV0Test, Values(HybridKeyTemplates::EciesP256HkdfHmacSha256Aes128Gcm())); #endif TEST_P(ConfigV0Test, GetPrimitive) { util::StatusOr> handle = KeysetHandle::GenerateNew(GetParam(), KeyGenConfigHybridV0()); ASSERT_THAT(handle, IsOk()); util::StatusOr> public_handle = (*handle)->GetPublicKeysetHandle(KeyGenConfigHybridV0()); ASSERT_THAT(public_handle, IsOk()); util::StatusOr> encrypt = (*public_handle)->GetPrimitive(ConfigHybridV0()); ASSERT_THAT(encrypt, IsOk()); util::StatusOr> decrypt = (*handle)->GetPrimitive(ConfigHybridV0()); ASSERT_THAT(decrypt, IsOk()); std::string plaintext = "plaintext"; util::StatusOr ciphertext = (*encrypt)->Encrypt(plaintext, "ad"); ASSERT_THAT(ciphertext, IsOk()); EXPECT_THAT((*decrypt)->Decrypt(*ciphertext, "ad"), IsOkAndHolds(plaintext)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/ecies_aead_hkdf_dem_helper.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/ecies_aead_hkdf_dem_helper.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/aead/aes_ctr_hmac_aead_key_manager.h" #include "tink/daead/subtle/aead_or_daead.h" #include "tink/deterministic_aead.h" #include "tink/subtle/aes_gcm_boringssl.h" #include "tink/subtle/aes_siv_boringssl.h" #include "tink/subtle/xchacha20_poly1305_boringssl.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/aes_ctr.pb.h" #include "proto/aes_ctr_hmac_aead.pb.h" #include "proto/aes_gcm.pb.h" #include "proto/aes_siv.pb.h" #include "proto/hmac.pb.h" #include "proto/tink.pb.h" #include "proto/xchacha20_poly1305.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::subtle::AeadOrDaead; using ::google::crypto::tink::AesCtrHmacAeadKey; using ::google::crypto::tink::AesCtrHmacAeadKeyFormat; using ::google::crypto::tink::AesGcmKeyFormat; using ::google::crypto::tink::AesSivKeyFormat; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::XChaCha20Poly1305KeyFormat; crypto::tink::util::StatusOr> Wrap( crypto::tink::util::StatusOr> aead_or) { if (!aead_or.ok()) { return aead_or.status(); } return std::make_unique(std::move(aead_or.value())); } crypto::tink::util::StatusOr> Wrap( crypto::tink::util::StatusOr< std::unique_ptr> daead_or) { if (!daead_or.ok()) { return daead_or.status(); } return std::make_unique(std::move(daead_or.value())); } } // namespace util::StatusOr EciesAeadHkdfDemHelper::GetKeyParams(const KeyTemplate& key_template) { const std::string& type_url = key_template.type_url(); if (type_url == "type.googleapis.com/google.crypto.tink.AesGcmKey") { AesGcmKeyFormat key_format; if (!key_format.ParseFromString(key_template.value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid AesGcmKeyFormat in DEM key template"); } return {{AES_GCM_KEY, key_format.key_size()}}; } if (type_url == "type.googleapis.com/google.crypto.tink.AesCtrHmacAeadKey") { AesCtrHmacAeadKeyFormat key_format; if (!key_format.ParseFromString(key_template.value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid AesCtrHmacKeyFormat in DEM key template"); } uint32_t dem_key_size = key_format.aes_ctr_key_format().key_size() + key_format.hmac_key_format().key_size(); return {{AES_CTR_HMAC_AEAD_KEY, dem_key_size, key_format.aes_ctr_key_format().key_size(), key_format.aes_ctr_key_format().params().iv_size(), key_format.hmac_key_format().params().hash(), key_format.hmac_key_format().params().tag_size()}}; } if (type_url == "type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key") { if (!XChaCha20Poly1305KeyFormat().ParseFromString(key_template.value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid XChaCha20KeyFormat in DEM key template"); } return {{XCHACHA20_POLY1305_KEY, 32}}; } if (type_url == "type.googleapis.com/google.crypto.tink.AesSivKey") { AesSivKeyFormat key_format; if (!key_format.ParseFromString(key_template.value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid AesSiveKeyFormat in DEM key template"); } return {{AES_SIV_KEY, key_format.key_size()}}; } return ToStatusF(absl::StatusCode::kInvalidArgument, "Unsupported DEM key type '%s'.", type_url); } // static util::StatusOr> EciesAeadHkdfDemHelper::New(const KeyTemplate& dem_key_template) { auto key_params_or = GetKeyParams(dem_key_template); if (!key_params_or.ok()) return key_params_or.status(); DemKeyParams key_params = key_params_or.value(); return absl::WrapUnique( new EciesAeadHkdfDemHelper(dem_key_template, key_params)); } crypto::tink::util::StatusOr> EciesAeadHkdfDemHelper::GetAeadOrDaead( const util::SecretData& symmetric_key_value) const { if (symmetric_key_value.size() != key_params_.key_size_in_bytes) { return util::Status(absl::StatusCode::kInternal, "Wrong length of symmetric key."); } switch (key_params_.key_type) { case AES_GCM_KEY: return Wrap(subtle::AesGcmBoringSsl::New(symmetric_key_value)); case AES_CTR_HMAC_AEAD_KEY: { AesCtrHmacAeadKey key; auto aes_ctr_key = key.mutable_aes_ctr_key(); aes_ctr_key->mutable_params()->set_iv_size( key_params_.aes_ctr_key_iv_size_in_bytes); aes_ctr_key->set_key_value( std::string(util::SecretDataAsStringView(symmetric_key_value) .substr(0, key_params_.aes_ctr_key_size_in_bytes))); auto hmac_key = key.mutable_hmac_key(); hmac_key->mutable_params()->set_tag_size( key_params_.hmac_key_tag_size_in_bytes); hmac_key->mutable_params()->set_hash(key_params_.hmac_key_hash); hmac_key->set_key_value( std::string(util::SecretDataAsStringView(symmetric_key_value) .substr(key_params_.aes_ctr_key_size_in_bytes))); return Wrap(AesCtrHmacAeadKeyManager().GetPrimitive(key)); } case XCHACHA20_POLY1305_KEY: return Wrap(subtle::XChacha20Poly1305BoringSsl::New(symmetric_key_value)); case AES_SIV_KEY: return Wrap(subtle::AesSivBoringSsl::New(symmetric_key_value)); } } } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/ecies_aead_hkdf_dem_helper.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_ECIES_AEAD_HKDF_DEM_HELPER_H_ #define TINK_HYBRID_ECIES_AEAD_HKDF_DEM_HELPER_H_ #include #include #include "tink/aead.h" #include "tink/daead/subtle/aead_or_daead.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "proto/common.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // A helper for DEM (data encapsulation mechanism) of ECIES-AEAD-HKDF. class EciesAeadHkdfDemHelper { public: // Constructs a new helper for the specified DEM key template. static crypto::tink::util::StatusOr> New(const google::crypto::tink::KeyTemplate& dem_key_template); virtual ~EciesAeadHkdfDemHelper() = default; // Returns the size of the DEM-key in bytes. uint32_t dem_key_size_in_bytes() const { return key_params_.key_size_in_bytes; } // Creates and returns a new AeadOrDaead object that uses // the key material given in 'symmetric_key', which must // be of length dem_key_size_in_bytes(). virtual crypto::tink::util::StatusOr< std::unique_ptr> GetAeadOrDaead(const util::SecretData& symmetric_key_value) const; protected: enum DemKeyType { AES_GCM_KEY, AES_CTR_HMAC_AEAD_KEY, XCHACHA20_POLY1305_KEY, AES_SIV_KEY, }; struct DemKeyParams { DemKeyType key_type; uint32_t key_size_in_bytes; uint32_t aes_ctr_key_size_in_bytes; uint32_t aes_ctr_key_iv_size_in_bytes; google::crypto::tink::HashType hmac_key_hash; uint32_t hmac_key_tag_size_in_bytes; }; EciesAeadHkdfDemHelper(const google::crypto::tink::KeyTemplate& key_template, DemKeyParams key_params) : key_template_(key_template), key_params_(key_params) {} static util::StatusOr GetKeyParams( const ::google::crypto::tink::KeyTemplate& key_template); const google::crypto::tink::KeyTemplate key_template_; const DemKeyParams key_params_; }; } // namespace tink } // namespace crypto #endif // TINK_HYBRID_ECIES_AEAD_HKDF_DEM_HELPER_H_ ================================================ FILE: cc/hybrid/ecies_aead_hkdf_dem_helper_test.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/ecies_aead_hkdf_dem_helper.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/daead/aes_siv_key_manager.h" #include "tink/daead/subtle/aead_or_daead.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_gcm.pb.h" #include "proto/aes_siv.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::subtle::AeadOrDaead; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::StatusOr; using ::testing::HasSubstr; // Checks whether Decrypt(Encrypt(message)) == message with the given dem. crypto::tink::util::Status EncryptThenDecrypt( const AeadOrDaead& dem, absl::string_view message, absl::string_view associated_data) { StatusOr encryption_or = dem.Encrypt(message, associated_data); if (!encryption_or.status().ok()) return encryption_or.status(); StatusOr decryption_or = dem.Decrypt(encryption_or.value(), associated_data); if (!decryption_or.status().ok()) return decryption_or.status(); if (decryption_or.value() != message) { return crypto::tink::util::Status(absl::StatusCode::kInternal, "Message/Decryption mismatch"); } return util::OkStatus(); } TEST(EciesAeadHkdfDemHelperTest, InvalidKey) { google::crypto::tink::KeyTemplate dem_key_template; dem_key_template.set_type_url("some.type.url/that.is.not.supported"); auto result = EciesAeadHkdfDemHelper::New(dem_key_template); EXPECT_THAT(EciesAeadHkdfDemHelper::New(dem_key_template).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Unsupported DEM"))); } TEST(EciesAeadHkdfDemHelperTest, DemHelperWithSomeAeadKeyType) { google::crypto::tink::AesGcmKeyFormat key_format; key_format.set_key_size(16); std::unique_ptr key_manager(new AesGcmKeyManager()); std::string dem_key_type = key_manager->get_key_type(); google::crypto::tink::KeyTemplate dem_key_template; dem_key_template.set_type_url(dem_key_type); dem_key_template.set_value(key_format.SerializeAsString()); auto dem_helper_or = EciesAeadHkdfDemHelper::New(dem_key_template); ASSERT_THAT(dem_helper_or, IsOk()); auto dem_helper = std::move(dem_helper_or.value()); util::SecretData key128 = util::SecretDataFromStringView( test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f")); StatusOr> aead_or_daead_result_or = dem_helper->GetAeadOrDaead(key128); ASSERT_THAT(aead_or_daead_result_or, IsOk()); auto aead_or_daead = std::move(aead_or_daead_result_or.value()); EXPECT_THAT(EncryptThenDecrypt(*aead_or_daead, "test_plaintext", "test_ad"), IsOk()); } TEST(EciesAeadHkdfDemHelperTest, DemHelperWithSomeDeterministicAeadKeyType) { google::crypto::tink::AesSivKeyFormat key_format; key_format.set_key_size(64); std::unique_ptr key_manager(new AesSivKeyManager()); std::string dem_key_type = key_manager->get_key_type(); google::crypto::tink::KeyTemplate dem_key_template; dem_key_template.set_type_url(dem_key_type); dem_key_template.set_value(key_format.SerializeAsString()); auto dem_helper_or = EciesAeadHkdfDemHelper::New(dem_key_template); ASSERT_THAT(dem_helper_or, IsOk()); auto dem_helper = std::move(dem_helper_or.value()); util::SecretData key128 = util::SecretDataFromStringView(test::HexDecodeOrDie( "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f00010203" "0405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f")); StatusOr> aead_or_daead_result_or = dem_helper->GetAeadOrDaead(key128); ASSERT_THAT(aead_or_daead_result_or, IsOk()); auto aead_or_daead = std::move(aead_or_daead_result_or.value()); EXPECT_THAT(EncryptThenDecrypt(*aead_or_daead, "test_plaintext", "test_ad"), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/ecies_aead_hkdf_hybrid_decrypt.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/ecies_aead_hkdf_hybrid_decrypt.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/hybrid/ecies_aead_hkdf_dem_helper.h" #include "tink/hybrid_decrypt.h" #include "tink/internal/ec_util.h" #include "tink/subtle/ecies_hkdf_recipient_kem_boringssl.h" #include "tink/util/enums.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/ecies_aead_hkdf.pb.h" using ::google::crypto::tink::EciesAeadHkdfPrivateKey; using ::google::crypto::tink::EllipticCurveType; namespace crypto { namespace tink { namespace { util::Status Validate(const EciesAeadHkdfPrivateKey& key) { if (!key.has_public_key() || !key.public_key().has_params() || key.public_key().x().empty() || key.key_value().empty()) { return util::Status( absl::StatusCode::kInvalidArgument, "Invalid EciesAeadHkdfPublicKey: missing required fields."); } if (key.public_key().params().has_kem_params() && key.public_key().params().kem_params().curve_type() == EllipticCurveType::CURVE25519) { if (!key.public_key().y().empty()) { return util::Status( absl::StatusCode::kInvalidArgument, "Invalid EciesAeadHkdfPublicKey: has unexpected field."); } } else if (key.public_key().y().empty()) { return util::Status( absl::StatusCode::kInvalidArgument, "Invalid EciesAeadHkdfPublicKey: missing required fields."); } return util::OkStatus(); } } // namespace // static util::StatusOr> EciesAeadHkdfHybridDecrypt::New( const EciesAeadHkdfPrivateKey& recipient_key) { util::Status status = Validate(recipient_key); if (!status.ok()) return status; auto kem_result = subtle::EciesHkdfRecipientKemBoringSsl::New( util::Enums::ProtoToSubtle( recipient_key.public_key().params().kem_params().curve_type()), util::SecretDataFromStringView(recipient_key.key_value())); if (!kem_result.ok()) return kem_result.status(); auto dem_result = EciesAeadHkdfDemHelper::New( recipient_key.public_key().params().dem_params().aead_dem()); if (!dem_result.ok()) return dem_result.status(); return {absl::WrapUnique(new EciesAeadHkdfHybridDecrypt( recipient_key.public_key().params(), std::move(kem_result).value(), std::move(dem_result).value()))}; } util::StatusOr EciesAeadHkdfHybridDecrypt::Decrypt( absl::string_view ciphertext, absl::string_view context_info) const { // Extract KEM-bytes from the ciphertext. auto header_size_result = internal::EcPointEncodingSizeInBytes( util::Enums::ProtoToSubtle( recipient_key_params_.kem_params().curve_type()), util::Enums::ProtoToSubtle(recipient_key_params_.ec_point_format())); if (!header_size_result.ok()) return header_size_result.status(); auto header_size = header_size_result.value(); if (ciphertext.size() < header_size) { return util::Status(absl::StatusCode::kInvalidArgument, "ciphertext too short"); } // Use KEM to get a symmetric key. auto symmetric_key_result = recipient_kem_->GenerateKey( absl::string_view(ciphertext).substr(0, header_size), util::Enums::ProtoToSubtle( recipient_key_params_.kem_params().hkdf_hash_type()), recipient_key_params_.kem_params().hkdf_salt(), context_info, dem_helper_->dem_key_size_in_bytes(), util::Enums::ProtoToSubtle(recipient_key_params_.ec_point_format())); if (!symmetric_key_result.ok()) return symmetric_key_result.status(); auto symmetric_key = std::move(symmetric_key_result.value()); // Use the symmetric key to get an AEAD-primitive. auto aead_or_daead_result = dem_helper_->GetAeadOrDaead(symmetric_key); if (!aead_or_daead_result.ok()) return aead_or_daead_result.status(); auto aead_or_daead = std::move(aead_or_daead_result.value()); // Do the actual decryption using the AEAD-primitive. auto decrypt_result = aead_or_daead->Decrypt(ciphertext.substr(header_size), ""); // empty aad if (!decrypt_result.ok()) return decrypt_result.status(); return decrypt_result.value(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/ecies_aead_hkdf_hybrid_decrypt.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_ECIES_AEAD_HKDF_HYBRID_DECRYPT_H_ #define TINK_HYBRID_ECIES_AEAD_HKDF_HYBRID_DECRYPT_H_ #include #include #include #include "absl/strings/string_view.h" #include "tink/hybrid/ecies_aead_hkdf_dem_helper.h" #include "tink/hybrid_decrypt.h" #include "tink/subtle/ecies_hkdf_recipient_kem_boringssl.h" #include "tink/util/statusor.h" #include "proto/ecies_aead_hkdf.pb.h" namespace crypto { namespace tink { // ECIES decryption with HKDF-KEM (key encapsulation mechanism) and // AEAD-DEM (data encapsulation mechanism). class EciesAeadHkdfHybridDecrypt : public HybridDecrypt { public: // Returns an HybridDecrypt-primitive that uses the key material // given in 'recipient_key'. static crypto::tink::util::StatusOr> New( const google::crypto::tink::EciesAeadHkdfPrivateKey& recipient_key); crypto::tink::util::StatusOr Decrypt( absl::string_view ciphertext, absl::string_view context_info) const override; private: EciesAeadHkdfHybridDecrypt( google::crypto::tink::EciesAeadHkdfParams recipient_key_params, std::unique_ptr kem, std::unique_ptr dem_helper) : recipient_key_params_(std::move(recipient_key_params)), recipient_kem_(std::move(kem)), dem_helper_(std::move(dem_helper)) {} google::crypto::tink::EciesAeadHkdfParams recipient_key_params_; std::unique_ptr recipient_kem_; std::unique_ptr dem_helper_; }; } // namespace tink } // namespace crypto #endif // TINK_HYBRID_ECIES_AEAD_HKDF_HYBRID_DECRYPT_H_ ================================================ FILE: cc/hybrid/ecies_aead_hkdf_hybrid_decrypt_test.cc ================================================ // Copyright 2017 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/ecies_aead_hkdf_hybrid_decrypt.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/aead/aes_ctr_hmac_aead_key_manager.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/aead/xchacha20_poly1305_key_manager.h" #include "tink/daead/aes_siv_key_manager.h" #include "tink/hybrid/ecies_aead_hkdf_hybrid_encrypt.h" #include "tink/hybrid_decrypt.h" #include "tink/hybrid_encrypt.h" #include "tink/internal/ec_util.h" #include "tink/internal/ssl_util.h" #include "tink/registry.h" #include "tink/subtle/random.h" #include "tink/util/enums.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_gcm.pb.h" #include "proto/common.pb.h" #include "proto/ecies_aead_hkdf.pb.h" using crypto::tink::subtle::Random; using ::crypto::tink::test::IsOkAndHolds; using google::crypto::tink::EciesAeadHkdfPrivateKey; using google::crypto::tink::EcPointFormat; using google::crypto::tink::EllipticCurveType; using google::crypto::tink::HashType; using ::testing::Eq; namespace crypto { namespace tink { namespace { class EciesAeadHkdfHybridDecryptTest : public ::testing::Test { protected: void SetUp() override {} void TearDown() override {} struct CommonHybridKeyParams { EllipticCurveType ec_curve; EcPointFormat ec_point_format; HashType hash_type; }; std::vector GetCommonHybridKeyParamsList() { std::vector params_list; for (auto ec_curve : {EllipticCurveType::NIST_P256, EllipticCurveType::NIST_P384, EllipticCurveType::NIST_P521, EllipticCurveType::CURVE25519}) { for (auto ec_point_format : {EcPointFormat::UNCOMPRESSED, EcPointFormat::COMPRESSED}) { if (ec_curve == EllipticCurveType::CURVE25519 && ec_point_format == EcPointFormat::UNCOMPRESSED) { continue; } for (auto hash_type : {HashType::SHA256, HashType::SHA512}) { CommonHybridKeyParams params; params.ec_curve = ec_curve; params.ec_point_format = ec_point_format; params.hash_type = hash_type; params_list.push_back(params); } } } return params_list; } EciesAeadHkdfPrivateKey GetEciesPrivateKeyFromHexString( absl::string_view private_key_hex_string, CommonHybridKeyParams& key_params) { auto ecies_key = test::GetEciesAesSivHkdfTestKey( key_params.ec_curve, key_params.ec_point_format, key_params.hash_type); ecies_key.set_key_value(test::HexDecodeOrDie(private_key_hex_string)); return ecies_key; } void TestValidKey(const EciesAeadHkdfPrivateKey& ecies_key) { auto result(EciesAeadHkdfHybridDecrypt::New(ecies_key)); ASSERT_TRUE(result.ok()) << result.status(); std::unique_ptr hybrid_decrypt(std::move(result.value())); std::unique_ptr hybrid_encrypt(std::move( EciesAeadHkdfHybridEncrypt::New(ecies_key.public_key()).value())); std::string context_info = "some context info"; for (uint32_t plaintext_size : {0, 1, 10, 100, 1000}) { // Use the primitive. std::string plaintext = Random::GetRandomBytes(plaintext_size); auto ciphertext = hybrid_encrypt->Encrypt(plaintext, context_info).value(); { // Regular decryption. auto decrypt_result = hybrid_decrypt->Decrypt(ciphertext, context_info); EXPECT_TRUE(decrypt_result.ok()) << decrypt_result.status(); EXPECT_EQ(plaintext, decrypt_result.value()); } { // Encryption and decryption with empty context info. const absl::string_view empty_context_info; auto ciphertext = hybrid_encrypt->Encrypt(plaintext, empty_context_info).value(); auto decrypt_result = hybrid_decrypt->Decrypt(ciphertext, empty_context_info); ASSERT_TRUE(decrypt_result.ok()) << decrypt_result.status(); EXPECT_EQ(plaintext, decrypt_result.value()); } { // Encryption and decryption w/ empty msg & context info. const absl::string_view empty_plaintext; const absl::string_view empty_context_info; auto ciphertext = hybrid_encrypt->Encrypt(empty_plaintext, empty_context_info) .value(); auto decrypt_result = hybrid_decrypt->Decrypt(ciphertext, empty_context_info); ASSERT_TRUE(decrypt_result.ok()) << decrypt_result.status(); EXPECT_EQ(empty_plaintext, decrypt_result.value()); } { // Short bad ciphertext. auto decrypt_result = hybrid_decrypt->Decrypt(Random::GetRandomBytes(16), context_info); EXPECT_FALSE(decrypt_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, decrypt_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "ciphertext too short", std::string(decrypt_result.status().message())); } { // Long but still bad ciphertext. auto decrypt_result = hybrid_decrypt->Decrypt(Random::GetRandomBytes(142), context_info); EXPECT_FALSE(decrypt_result.ok()); // TODO(przydatek): add more checks while avoiding flakiness. } { // Bad context info auto decrypt_result = hybrid_decrypt->Decrypt(ciphertext, Random::GetRandomBytes(14)); EXPECT_FALSE(decrypt_result.ok()); } } } }; TEST_F(EciesAeadHkdfHybridDecryptTest, testInvalidKeys) { { // No fields set. EciesAeadHkdfPrivateKey recipient_key; auto result = EciesAeadHkdfHybridDecrypt::New(recipient_key); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "missing required fields", std::string(result.status().message())); } { // Only some fields set. EciesAeadHkdfPrivateKey recipient_key; recipient_key.set_version(0); recipient_key.mutable_public_key()->set_x("some x bytes"); recipient_key.mutable_public_key()->set_y("some y bytes"); auto result(EciesAeadHkdfHybridDecrypt::New(recipient_key)); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "missing required fields", std::string(result.status().message())); } { // Wrong EC type. EciesAeadHkdfPrivateKey recipient_key; recipient_key.set_version(0); recipient_key.set_key_value("some key value bytes"); recipient_key.mutable_public_key()->set_x("some x bytes"); recipient_key.mutable_public_key()->set_y("some y bytes"); recipient_key.mutable_public_key()->mutable_params(); auto result(EciesAeadHkdfHybridDecrypt::New(recipient_key)); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kUnimplemented, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "Unsupported elliptic curve", std::string(result.status().message())); } { // Unsupported DEM key type. EllipticCurveType curve = EllipticCurveType::NIST_P256; auto test_key = internal::NewEcKey(util::Enums::ProtoToSubtle(curve)).value(); EciesAeadHkdfPrivateKey recipient_key; recipient_key.set_version(0); recipient_key.set_key_value("some key value bytes"); recipient_key.mutable_public_key()->set_x(test_key.pub_x); recipient_key.mutable_public_key()->set_y(test_key.pub_y); auto params = recipient_key.mutable_public_key()->mutable_params(); params->mutable_kem_params()->set_curve_type(curve); params->mutable_kem_params()->set_hkdf_hash_type(HashType::SHA256); auto aead_dem = params->mutable_dem_params()->mutable_aead_dem(); aead_dem->set_type_url("some.type.url/that.is.not.supported"); auto result(EciesAeadHkdfHybridDecrypt::New(recipient_key)); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "Unsupported DEM", std::string(result.status().message())); } } TEST_F(EciesAeadHkdfHybridDecryptTest, testAesGcmHybridDecryption) { // Register DEM key manager. std::string dem_key_type = AesGcmKeyManager().get_key_type(); ASSERT_TRUE(Registry::RegisterKeyTypeManager( absl::make_unique(), true) .ok()); int i = 0; // Generate and test many keys with various parameters. for (auto key_params : GetCommonHybridKeyParamsList()) { for (uint32_t aes_gcm_key_size : {16, 32}) { ++i; auto ecies_key = test::GetEciesAesGcmHkdfTestKey( key_params.ec_curve, key_params.ec_point_format, key_params.hash_type, aes_gcm_key_size); TestValidKey(ecies_key); } } EXPECT_EQ(i, 32 - 4); } TEST_F(EciesAeadHkdfHybridDecryptTest, testAesCtrAeadHybridDecryption) { // Register DEM key manager. std::string dem_key_type = AesCtrHmacAeadKeyManager().get_key_type(); ASSERT_TRUE(Registry::RegisterKeyTypeManager( absl::make_unique(), true) .ok()); uint32_t aes_ctr_iv_size = 16; // Generate and test many keys with various parameters. for (auto key_params : GetCommonHybridKeyParamsList()) { for (uint32_t aes_ctr_key_size : {16, 32}) { for (auto hmac_hash_type : {HashType::SHA256, HashType::SHA512}) { for (uint32_t hmac_tag_size : {16, 32}) { for (uint32_t hmac_key_size : {16, 32}) { auto ecies_key = test::GetEciesAesCtrHmacHkdfTestKey( key_params.ec_curve, key_params.ec_point_format, key_params.hash_type, aes_ctr_key_size, aes_ctr_iv_size, hmac_hash_type, hmac_tag_size, hmac_key_size); TestValidKey(ecies_key); } } } } } } TEST_F(EciesAeadHkdfHybridDecryptTest, testXChaCha20Poly1305HybridDecryption) { if (!internal::IsBoringSsl()) { GTEST_SKIP() << "XChaCha20-Poly1305 is not supported when OpenSSL is used"; } // Register DEM key manager. std::string dem_key_type = XChaCha20Poly1305KeyManager().get_key_type(); ASSERT_TRUE(Registry::RegisterKeyTypeManager( absl::make_unique(), true) .ok()); // Generate and test many keys with various parameters. for (auto key_params : GetCommonHybridKeyParamsList()) { auto ecies_key = test::GetEciesXChaCha20Poly1305HkdfTestKey( key_params.ec_curve, key_params.ec_point_format, key_params.hash_type); TestValidKey(ecies_key); } } TEST_F(EciesAeadHkdfHybridDecryptTest, testAesSivHybridDecryption) { // Register DEM key manager. std::string dem_key_type = AesSivKeyManager().get_key_type(); ASSERT_TRUE(Registry::RegisterKeyTypeManager( absl::make_unique(), true) .ok()); // Generate and test many keys with various parameters. for (auto key_params : GetCommonHybridKeyParamsList()) { auto ecies_key = test::GetEciesAesSivHkdfTestKey( key_params.ec_curve, key_params.ec_point_format, key_params.hash_type); TestValidKey(ecies_key); } } struct TestVector { EciesAeadHkdfPrivateKey private_key; std::string ciphertext; std::string context_info; std::string plaintext; }; TEST_F(EciesAeadHkdfHybridDecryptTest, testAesSivHybridDecryptionWithTestVectors) { // Register DEM key manager. std::string dem_key_type = AesSivKeyManager().get_key_type(); ASSERT_TRUE(Registry::RegisterKeyTypeManager( absl::make_unique(), true) .ok()); CommonHybridKeyParams key_params = {EllipticCurveType::NIST_P256, EcPointFormat::UNCOMPRESSED, HashType::SHA256}; TestVector hybrid_decryption_test_vectors[] = { { /*TEST 1*/ /*private_key=*/ GetEciesPrivateKeyFromHexString("32588172ed65830571bb83748f7fddd38332" "3208a7825c80a71bef846333eb02", key_params), /*ciphertext=*/ test::HexDecodeOrDie( "0401b11f8c9bafe30ae13f8bd15528714e752631a4328bf146009068e99489c8" "e9fae1ec39e3fe9994723711417fcab2af4b3c9b60117d47d33d35175c87b483" "b8935a73312940d1fbf8da3944a89b5e8b"), /*context_info=*/ "some context info", /*plaintext=*/"", }, { /*TEST 2*/ /*private_key=*/ GetEciesPrivateKeyFromHexString("32588172ed65830571bb83748f7fddd38332" "3208a7825c80a71bef846333eb02", key_params), /*ciphertext=*/ test::HexDecodeOrDie( "040230023d1547b55af5a735a7f460722612126d7539d7cd0f677d308b29c6f5" "2a964e66e7b0cb44cff1673df9e2c793f1477ca755807bfbeadcae1ab20b45ec" "b1501ca5e3f5b0626d3ca40aa5d010443d506e4df90b"), /*context_info=*/ "some context info", /*plaintext=*/"hello", }, { /*TEST 3*/ /*private_key=*/ GetEciesPrivateKeyFromHexString("32588172ed65830571bb83748f7fddd38332" "3208a7825c80a71bef846333eb02", key_params), /*ciphertext=*/ test::HexDecodeOrDie( "0441ddd246cea0825bd68bddff05cec54a4ee678da35b2f5cfbbb32e5350bdd8" "17214bfb7b5ed5528131bde56916062cfbd8b9952d9e0907a6e87e1de54db5df" "3aaccddd328efcf7771ce061e647488f66b8c11a9fca171dcff813e90b44b273" "9573f9f23b60202491870c7ff8aaf0ae46838e48f17f8dc1ad55b67809699dd3" "1eb6ca50dfa9beeee32d30bdc00a1eb1d8b0cbcedbe50b1e24619cc5e79042f2" "5f49e2c2d5a35c79e833c0d68e31a93da4173aacd0428b367594ed4636763d16" "c23e4f8c115d44bddc83bcefcaea13587238ce8b7a5d5fad53beeb59aaa1d748" "3eb4bac93ed50ed4d3e9fd5af760283fd38080b58744b73212a36039179ce6f9" "6ef1ecaa05b5186967d81c06b9cd91140dfbd54084ddcfd941527719848a2eec" "b84278f6a0fe9357a3964f87222fcd16a12a353e1f64fd45dc227a4a2112da6f" "61269f22f16b41e68eadf0b6b3a48c67b9e7e3ec1c66eecce50dda8ecbce99d3" "778299aa28741b7247fbc46a1b8a908dc23943c2dd17210a270bb12b096c2c6a" "00400a95c62894a15b9fc44e709d27348f2f2644a786cd9e96caf42ea9b949f7" "6e85e6f7365e15fa2902e851222c025f6c208269d799fcfc4c0b37aba8979ed9" "e6ccf543c217ee0b6ad05f0e3ffb92943d308c801b25efedab5bf93a733bdae6" "11132d774d4b9ee4fb5e88ae63014315ae9571039a8c8c7020e2b3a1bbd4235b" "65af94771c8417c87fd6cab423b82a557f60a99ae7402dba205e05136dd34f00" "26fce87899d4b9819cc2b2ba686512d62c41a1e3a667a705ea45404aafa489cd" "7f53f42455fff3f9b22f960d12a2587efd6ed0fa3e00dd4645face1b2f1268e6" "019be70999eab00f0aeff3cb0e77b7c4a1ab1fdf15d00c4eedd7b75e8cf5c901" "19346894089ee0299d58f1d7ebac9b592da2325a5a738ea2baecc1468670f5ae" "c880bce32efecfb2a7c5ad3ae4096b0a07aa9bfe6cbaf53da6757377bb692e55" "ec8caf5f0af28dafdc42e1d6e5893140945a853f56652c575b99d64399aad2d0" "42948575134c8fe638fb0b80ac3a0f08a60f3aa817fe0a24c1fffee6933bd72e" "a460e0b241d3f5d98b2321ee25d8c0302353fcfd41bce964d73ff67042286450" "6cc56f3470362c90144586ccbfc8e5e6fefbb70429b0a517e4b1badb449cd110" "92790aba6e19b914899872f4fb481c8dc47a33422fc05072ac99c958e40dae53" "d96ebd87cfbde67a0f050203a89e487da5e03364951830e43771d36abfbe8f5a" "7da8e7aa891f36a68dbe9a3b0e3dfbd1afd6327a3ced4a5cd8a5b256fef46d20" "0df4af2e2da4dbb786ea0404bb968b6d961e4fc76f89e70ad7c9e11d6aee6526" "b75b399811f73c053a29582ba9295ea4d5a8fffb5a8ccbac008d291dd60e2041" "371acfc4c432a0ae0fcd8fa25c9551123c95da64caa134edaee5893e19c3c760" "75bef419c09681a67f4ede6f28d747b53afd61ddc937d7de96a22c7db10ad870" "0cade888de5d6f450c15d796978ddb5e6a52e5044e90247c988686d992105c85" "f6d198e2de859330f973ded4d7e5d90de57051dbaf0db0febd4cf9d44da155e5" "5293b0930f89c1d21cc227eba9615ca47cce41d16eaddb5bf5dc9bc8477df5cf" "21f460b83241e7d0fa3707f9d2b322b9aaa42747d0653168b095ca0a83f38426" "688f6f10143cbd1b84c08583b09ed6192c7366ecc23af528fc2e8c585560f9bd" "0fcc255b82fc70723a92506bb475ebc1f5ae34a902bf2aa75997ed90a54762c8" "e83720833b2fd607eee1beb347a75d3bd0f174ed450a72cce79f1be426de9d6f" "1a6feff052674af141b3cea89f8e749118392e9533c62ddad870e60d509fd7ab" "fa0bc33c2774b29a0170089b30d82047d6e130c49f6965f9871d1928b7f13e3e" "40ad8e3dc85195f4b312f9f6d8e4158aca23a611f6c6c798983555139942536f" "6ac59bbd6cc88b9933f22e81429e835bfd4fec27c67520d64a0ad8fd7feb6a3f" "be52dc56cbbf59644b0fad0c462ed02ffbf7258e4b94bdedefb187fbdb729a0d" "56a36e876ac76de766eed416f39ab4e8b1982b8d0a87cd33182ae81ecf1d1d52" "02cc3e82c5762646d15db5f13cde3e81c83715195f9af9f27e01e1829ce529fa" "0f715db1f5d227bb201c7c127ea8d0e9c21739c7e9c6a0d8d5a1aaea5216c549" "f3715f889e583555ac1bfd77339f3eff1bee75ee2fc45457f5c3ffe9401b8b67" "f5bb3f305f3269fe6153ba34de3fa90016c76811cd54b4b49b17b244b1a4f6ed" "fa2eaf46e2819aded26005b4ed712e8b700ae7b6123fa2c179640ee523f86436" "0d116ee243f13c66d2cd61d422709648d905ab17edf0d0075d2fed443889e153" "44069b69b2d3d8273f197f8468baf167074bf6dfdeea5871f0c0652ab2801f39" "4ef6fbf841e8072c8bf65026d85d441ca61e78785a2e7ca1e743640fecd6dfad" "8b77adcbb8bcb8ce8532ad0cd8b3e51269c26ad037545273f756c1a551192540" "8a5045af469ca947f9a3f5457bcc325d05291a192abe75b4da7c97a61adc2fa2" "47984edb5a03285f1c3b99f13f6a22f007029faffdd38b62f7bf909ce602e4e0" "6ab1ec4543013d354d0dd86d8933a53c17ead02faf0cc740d7191fe475be2f79" "40c234f8c73420774a7213fd2a477847527172c02a54928de5fde5f15616760e" "6f7ff3c03a233aec880a939d9f1ca68be7f474fd13184fe8f6deb0c4ea01617e" "a207d5d765d067fddba58b94f3b59d5996e9f5434f483e2f0079c48050f3ba94" "1b589294c41a0f350451d566fe58a9c9688cc3a75da314ff4b3473eeac58664c" "5922ae4efae850fe0f7f11dcc089bc0b4df9a64547a35b2559f4a4a3e7d3782d" "850997baa589534921becde8dc3f76380ae36bd9730956aae9f59b121d8ae4db" "bc586c6b45ad9d5c17cf6821b746177bc9fcb727db3f4aa190688c48826421de" "5ebcd429e0d9b479e66e676e8f9a3b4bd92621f47357a7b1b27942121f5a6e00" "87e4192a5f8cf4da942cc9d86eac5e"), /*context_info=*/ "some context info", /*plaintext=*/ "08b8b2b733424243760fe426a4b54908" "632110a66c2f6591eabd3345e3e4eb98" "fa6e264bf09efe12ee50f8f54e9f77b1" "e355f6c50544e23fb1433ddf73be84d8" "79de7c0046dc4996d9e773f4bc9efe57" "38829adb26c81b37c93a1b270b20329d" "658675fc6ea534e0810a4432826bf58c" "941efb65d57a338bbd2e26640f89ffbc" "1a858efcb8550ee3a5e1998bd177e93a" "7363c344fe6b199ee5d02e82d522c4fe" "ba15452f80288a821a579116ec6dad2b" "3b310da903401aa62100ab5d1a36553e" "06203b33890cc9b832f79ef80560ccb9" "a39ce767967ed628c6ad573cb116dbef" "efd75499da96bd68a8a97b928a8bbc10" "3b6621fcde2beca1231d206be6cd9ec7" "aff6f6c94fcd7204ed3455c68c83f4a4" "1da4af2b74ef5c53f1d8ac70bdcb7ed1" "85ce81bd84359d44254d95629e9855a9" "4a7c1958d1f8ada5d0532ed8a5aa3fb2" "d17ba70eb6248e594e1a2297acbbb39d" "502f1a8c6eb6f1ce22b3de1a1f40cc24" "554119a831a9aad6079cad88425de6bd" "e1a9187ebb6092cf67bf2b13fd65f270" "88d78b7e883c8759d2c4f5c65adb7553" "878ad575f9fad878e80a0c9ba63bcbcc" "2732e69485bbc9c90bfbd62481d9089b" "eccf80cfe2df16a2cf65bd92dd597b07" "07e0917af48bbb75fed413d238f5555a" "7a569d80c3414a8d0859dc65a46128ba" "b27af87a71314f318c782b23ebfe808b" "82b0ce26401d2e22f04d83d1255dc51a" "ddd3b75a2b1ae0784504df543af8969b" "e3ea7082ff7fc9888c144da2af58429e" "c96031dbcad3dad9af0dcbaaaf268cb8" "fcffead94f3c7ca495e056a9b47acdb7" "51fb73e666c6c655ade8297297d07ad1" "ba5e43f1bca32301651339e22904cc8c" "42f58c30c04aafdb038dda0847dd988d" "cda6f3bfd15c4b4c4525004aa06eeff8" "ca61783aacec57fb3d1f92b0fe2fd1a8" "5f6724517b65e614ad6808d6f6ee34df" "f7310fdc82aebfd904b01e1dc54b2927" "094b2db68d6f903b68401adebf5a7e08" "d78ff4ef5d63653a65040cf9bfd4aca7" "984a74d37145986780fc0b16ac451649" "de6188a7dbdf191f64b5fc5e2ab47b57" "f7f7276cd419c17a3ca8e1b939ae49e4" "88acba6b965610b5480109c8b17b80e1" "b7b750dfc7598d5d5011fd2dcc5600a3" "2ef5b52a1ecc820e308aa342721aac09" "43bf6686b64b2579376504ccc493d97e" "6aed3fb0f9cd71a43dd497f01f17c0e2" "cb3797aa2a2f256656168e6c496afc5f" "b93246f6b1116398a346f1a641f3b041" "e989f7914f90cc2c7fff357876e506b5" "0d334ba77c225bc307ba537152f3f161" "0e4eafe595f6d9d90d11faa933a15ef1" "369546868a7f3a45a96768d40fd9d034" "12c091c6315cf4fde7cb68606937380d" "b2eaaa707b4c4185c32eddcdd306705e" "4dc1ffc872eeee475a64dfac86aba41c" "0618983f8741c5ef68d3a101e8a3b8ca" "c60c905c15fc910840b94c00a0b9d0", }}; for (const TestVector& test_vector : hybrid_decryption_test_vectors) { std::unique_ptr hybrid_decrypt = EciesAeadHkdfHybridDecrypt::New(test_vector.private_key).value(); EXPECT_THAT(hybrid_decrypt->Decrypt(test_vector.ciphertext, test_vector.context_info), IsOkAndHolds(Eq(test_vector.plaintext))); } } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/ecies_aead_hkdf_hybrid_encrypt.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/ecies_aead_hkdf_hybrid_encrypt.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/hybrid/ecies_aead_hkdf_dem_helper.h" #include "tink/hybrid_encrypt.h" #include "tink/subtle/ecies_hkdf_sender_kem_boringssl.h" #include "tink/util/enums.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/ecies_aead_hkdf.pb.h" using ::google::crypto::tink::EciesAeadHkdfPublicKey; using ::google::crypto::tink::EllipticCurveType; namespace crypto { namespace tink { namespace { util::Status Validate(const EciesAeadHkdfPublicKey& key) { if (key.x().empty() || !key.has_params()) { return util::Status( absl::StatusCode::kInvalidArgument, "Invalid EciesAeadHkdfPublicKey: missing required fields."); } if (key.params().has_kem_params() && key.params().kem_params().curve_type() == EllipticCurveType::CURVE25519) { if (!key.y().empty()) { return util::Status( absl::StatusCode::kInvalidArgument, "Invalid EciesAeadHkdfPublicKey: has unexpected field."); } } else if (key.y().empty()) { return util::Status( absl::StatusCode::kInvalidArgument, "Invalid EciesAeadHkdfPublicKey: missing required fields."); } return util::OkStatus(); } } // namespace // static util::StatusOr> EciesAeadHkdfHybridEncrypt::New( const EciesAeadHkdfPublicKey& recipient_key) { util::Status status = Validate(recipient_key); if (!status.ok()) return status; auto kem_result = subtle::EciesHkdfSenderKemBoringSsl::New( util::Enums::ProtoToSubtle( recipient_key.params().kem_params().curve_type()), recipient_key.x(), recipient_key.y()); if (!kem_result.ok()) return kem_result.status(); auto dem_result = EciesAeadHkdfDemHelper::New( recipient_key.params().dem_params().aead_dem()); if (!dem_result.ok()) return dem_result.status(); return {absl::WrapUnique(new EciesAeadHkdfHybridEncrypt( recipient_key, std::move(kem_result).value(), std::move(dem_result).value()))}; } util::StatusOr EciesAeadHkdfHybridEncrypt::Encrypt( absl::string_view plaintext, absl::string_view context_info) const { // Use KEM to get a symmetric key. auto kem_key_result = sender_kem_->GenerateKey( util::Enums::ProtoToSubtle( recipient_key_.params().kem_params().hkdf_hash_type()), recipient_key_.params().kem_params().hkdf_salt(), context_info, dem_helper_->dem_key_size_in_bytes(), util::Enums::ProtoToSubtle( recipient_key_.params().ec_point_format())); if (!kem_key_result.ok()) return kem_key_result.status(); auto kem_key = std::move(kem_key_result.value()); // Use the symmetric key to get an AEAD-primitive. auto aead_or_daead_result = dem_helper_->GetAeadOrDaead(kem_key->get_symmetric_key()); if (!aead_or_daead_result.ok()) return aead_or_daead_result.status(); auto aead_or_daead = std::move(aead_or_daead_result.value()); // Do the actual encryption using the AEAD-primitive. auto encrypt_result = aead_or_daead->Encrypt(plaintext, ""); // empty aad if (!encrypt_result.ok()) return encrypt_result.status(); // Prepend AEAD-ciphertext with a KEM component. std::string ciphertext = absl::StrCat(kem_key->get_kem_bytes(), encrypt_result.value()); return ciphertext; } } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/ecies_aead_hkdf_hybrid_encrypt.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_ECIES_AEAD_HKDF_HYBRID_ENCRYPT_H_ #define TINK_HYBRID_ECIES_AEAD_HKDF_HYBRID_ENCRYPT_H_ #include #include #include #include "absl/strings/string_view.h" #include "tink/hybrid/ecies_aead_hkdf_dem_helper.h" #include "tink/hybrid_encrypt.h" #include "tink/subtle/ecies_hkdf_sender_kem_boringssl.h" #include "tink/util/statusor.h" #include "proto/ecies_aead_hkdf.pb.h" namespace crypto { namespace tink { // ECIES encryption with HKDF-KEM (key encapsulation mechanism) and // AEAD-DEM (data encapsulation mechanism). class EciesAeadHkdfHybridEncrypt : public HybridEncrypt { public: // Returns an HybridEncrypt-primitive that uses the key material // given in 'recipient_key'. static crypto::tink::util::StatusOr> New( const google::crypto::tink::EciesAeadHkdfPublicKey& recipient_key); crypto::tink::util::StatusOr Encrypt( absl::string_view plaintext, absl::string_view context_info) const override; private: EciesAeadHkdfHybridEncrypt( const google::crypto::tink::EciesAeadHkdfPublicKey& recipient_key, std::unique_ptr sender_kem, std::unique_ptr dem_helper) : recipient_key_(recipient_key), sender_kem_(std::move(sender_kem)), dem_helper_(std::move(dem_helper)) {} google::crypto::tink::EciesAeadHkdfPublicKey recipient_key_; std::unique_ptr sender_kem_; std::unique_ptr dem_helper_; }; } // namespace tink } // namespace crypto #endif // TINK_HYBRID_ECIES_AEAD_HKDF_HYBRID_ENCRYPT_H_ ================================================ FILE: cc/hybrid/ecies_aead_hkdf_hybrid_encrypt_test.cc ================================================ // Copyright 2017 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/ecies_aead_hkdf_hybrid_encrypt.h" #include #include #include #include #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/hybrid_encrypt.h" #include "tink/internal/ec_util.h" #include "tink/util/enums.h" #include "tink/util/statusor.h" #include "tink/util/test_util.h" #include "proto/common.pb.h" #include "proto/ecies_aead_hkdf.pb.h" using google::crypto::tink::EciesAeadHkdfPublicKey; using google::crypto::tink::EcPointFormat; using google::crypto::tink::EllipticCurveType; using google::crypto::tink::HashType; namespace crypto { namespace tink { namespace { class EciesAeadHkdfHybridEncryptTest : public ::testing::Test { protected: void SetUp() override { } void TearDown() override { } }; TEST_F(EciesAeadHkdfHybridEncryptTest, testInvalidKeys) { { // No fields set. EciesAeadHkdfPublicKey recipient_key; auto result = EciesAeadHkdfHybridEncrypt::New(recipient_key); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "missing required fields", std::string(result.status().message())); } { // Only some fields set. EciesAeadHkdfPublicKey recipient_key; recipient_key.set_version(0); recipient_key.set_x("some x bytes"); recipient_key.set_y("some y bytes"); auto result(EciesAeadHkdfHybridEncrypt::New(recipient_key)); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "missing required fields", std::string(result.status().message())); } { // Wrong EC type. EciesAeadHkdfPublicKey recipient_key; recipient_key.set_version(0); recipient_key.set_x("some x bytes"); recipient_key.set_y("some y bytes"); recipient_key.mutable_params(); auto result(EciesAeadHkdfHybridEncrypt::New(recipient_key)); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kUnimplemented, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "Unsupported elliptic curve", std::string(result.status().message())); } { // Unsupported DEM key type. EllipticCurveType curve = EllipticCurveType::NIST_P256; auto test_key = internal::NewEcKey(util::Enums::ProtoToSubtle(curve)).value(); EciesAeadHkdfPublicKey recipient_key; recipient_key.set_version(0); recipient_key.set_x(test_key.pub_x); recipient_key.set_y(test_key.pub_y); auto params = recipient_key.mutable_params(); params->mutable_kem_params()->set_curve_type(curve); params->mutable_kem_params()->set_hkdf_hash_type(HashType::SHA256); auto aead_dem = params->mutable_dem_params()->mutable_aead_dem(); aead_dem->set_type_url("some.type.url/that.is.not.supported"); auto result(EciesAeadHkdfHybridEncrypt::New(recipient_key)); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "Unsupported DEM", std::string(result.status().message())); } } TEST_F(EciesAeadHkdfHybridEncryptTest, testBasic) { // Prepare an ECIES key. auto ecies_key = test::GetEciesAesGcmHkdfTestKey( EllipticCurveType::NIST_P256, EcPointFormat::UNCOMPRESSED, HashType::SHA256, 32); // Generate and test many keys with various parameters. std::string plaintext = "some plaintext"; std::string context_info = "some context info"; for (auto curve : {EllipticCurveType::NIST_P256, EllipticCurveType::NIST_P384, EllipticCurveType::NIST_P521}) { for (auto ec_point_format : {EcPointFormat::UNCOMPRESSED, EcPointFormat::COMPRESSED}) { for (auto hash_type : {HashType::SHA256, HashType::SHA512}) { for (uint32_t aes_gcm_key_size : {16, 32}) { ecies_key = test::GetEciesAesGcmHkdfTestKey( curve, ec_point_format, hash_type, aes_gcm_key_size); auto result(EciesAeadHkdfHybridEncrypt::New(ecies_key.public_key())); ASSERT_TRUE(result.ok()) << result.status() << ecies_key.SerializeAsString(); std::unique_ptr hybrid_encrypt( std::move(result.value())); // Use the primitive. auto encrypt_result = hybrid_encrypt->Encrypt(plaintext, context_info); EXPECT_TRUE(encrypt_result.ok()) << encrypt_result.status(); } } } } } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/ecies_aead_hkdf_private_key_manager.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/ecies_aead_hkdf_private_key_manager.h" #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/hybrid/ecies_aead_hkdf_hybrid_decrypt.h" #include "tink/hybrid/ecies_aead_hkdf_public_key_manager.h" #include "tink/hybrid_decrypt.h" #include "tink/internal/ec_util.h" #include "tink/key_manager.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/ecies_aead_hkdf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using crypto::tink::util::Status; using crypto::tink::util::StatusOr; using google::crypto::tink::EciesAeadHkdfKeyFormat; using google::crypto::tink::EciesAeadHkdfPrivateKey; using google::crypto::tink::EciesAeadHkdfPublicKey; using google::crypto::tink::EciesHkdfKemParams; Status EciesAeadHkdfPrivateKeyManager::ValidateKeyFormat( const EciesAeadHkdfKeyFormat& key_format) const { if (!key_format.has_params()) { return Status(absl::StatusCode::kInvalidArgument, "Missing params."); } return EciesAeadHkdfPublicKeyManager().ValidateParams(key_format.params()); } StatusOr EciesAeadHkdfPrivateKeyManager::CreateKey( const EciesAeadHkdfKeyFormat& ecies_key_format) const { // Generate new EC key. const EciesHkdfKemParams& kem_params = ecies_key_format.params().kem_params(); util::StatusOr ec_key = internal::NewEcKey(util::Enums::ProtoToSubtle(kem_params.curve_type())); if (!ec_key.ok()) { return ec_key.status(); } // Build EciesAeadHkdfPrivateKey. EciesAeadHkdfPrivateKey ecies_private_key; ecies_private_key.set_version(get_version()); ecies_private_key.set_key_value( std::string(util::SecretDataAsStringView(ec_key->priv))); auto ecies_public_key = ecies_private_key.mutable_public_key(); ecies_public_key->set_version(get_version()); ecies_public_key->set_x(ec_key->pub_x); ecies_public_key->set_y(ec_key->pub_y); *(ecies_public_key->mutable_params()) = ecies_key_format.params(); return ecies_private_key; } StatusOr EciesAeadHkdfPrivateKeyManager::GetPublicKey( const EciesAeadHkdfPrivateKey& private_key) const { return private_key.public_key(); } Status EciesAeadHkdfPrivateKeyManager::ValidateKey( const EciesAeadHkdfPrivateKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; if (!key.has_public_key()) { return Status(absl::StatusCode::kInvalidArgument, "Missing public_key."); } return EciesAeadHkdfPublicKeyManager().ValidateKey(key.public_key()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/ecies_aead_hkdf_private_key_manager.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_ECIES_AEAD_HKDF_PRIVATE_KEY_MANAGER_H_ #define TINK_HYBRID_ECIES_AEAD_HKDF_PRIVATE_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/key_type_manager.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/hybrid/ecies_aead_hkdf_hybrid_decrypt.h" #include "tink/hybrid_decrypt.h" #include "tink/key_manager.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/ecies_aead_hkdf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class EciesAeadHkdfPrivateKeyManager : public PrivateKeyTypeManager< google::crypto::tink::EciesAeadHkdfPrivateKey, google::crypto::tink::EciesAeadHkdfKeyFormat, google::crypto::tink::EciesAeadHkdfPublicKey, List> { public: class HybridDecryptFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::EciesAeadHkdfPrivateKey& ecies_private_key) const override { return EciesAeadHkdfHybridDecrypt::New(ecies_private_key); } }; EciesAeadHkdfPrivateKeyManager() : PrivateKeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::EciesAeadHkdfPrivateKey& key) const override; crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::EciesAeadHkdfKeyFormat& ecies_key_format) const override; crypto::tink::util::StatusOr CreateKey(const google::crypto::tink::EciesAeadHkdfKeyFormat& key_format) const override; crypto::tink::util::StatusOr GetPublicKey(const google::crypto::tink::EciesAeadHkdfPrivateKey& private_key) const override; private: const std::string key_type_ = absl::StrCat( kTypeGoogleapisCom, google::crypto::tink::EciesAeadHkdfPrivateKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_HYBRID_ECIES_AEAD_HKDF_PRIVATE_KEY_MANAGER_H_ ================================================ FILE: cc/hybrid/ecies_aead_hkdf_private_key_manager_test.cc ================================================ // Copyright 2017 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/ecies_aead_hkdf_private_key_manager.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/aead/aead_key_templates.h" #include "tink/aead/aes_ctr_hmac_aead_key_manager.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/hybrid/ecies_aead_hkdf_hybrid_encrypt.h" #include "tink/hybrid/ecies_aead_hkdf_public_key_manager.h" #include "tink/hybrid/hybrid_key_templates.h" #include "tink/hybrid_decrypt.h" #include "tink/registry.h" #include "tink/subtle/hybrid_test_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_eax.pb.h" #include "proto/common.pb.h" #include "proto/ecies_aead_hkdf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::EciesAeadHkdfKeyFormat; using ::google::crypto::tink::EciesAeadHkdfPrivateKey; using ::google::crypto::tink::EciesAeadHkdfPublicKey; using ::google::crypto::tink::EcPointFormat; using ::google::crypto::tink::EllipticCurveType; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::testing::Eq; using ::testing::IsEmpty; using ::testing::Not; namespace { TEST(EciesAeadHkdfPrivateKeyManagerTest, Basics) { EXPECT_THAT(EciesAeadHkdfPrivateKeyManager().get_version(), Eq(0)); EXPECT_THAT(EciesAeadHkdfPrivateKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PRIVATE)); EXPECT_THAT( EciesAeadHkdfPrivateKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey")); } TEST(EciesAeadHkdfPrivateKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT( EciesAeadHkdfPrivateKeyManager().ValidateKey(EciesAeadHkdfPrivateKey()), StatusIs(absl::StatusCode::kInvalidArgument)); } EciesAeadHkdfKeyFormat CreateValidKeyFormat() { EciesAeadHkdfKeyFormat key_format; key_format.mutable_params()->set_ec_point_format(EcPointFormat::UNCOMPRESSED); auto dem_params = key_format.mutable_params()->mutable_dem_params(); *(dem_params->mutable_aead_dem()) = AeadKeyTemplates::Aes128Gcm(); auto kem_params = key_format.mutable_params()->mutable_kem_params(); kem_params->set_curve_type(EllipticCurveType::NIST_P256); kem_params->set_hkdf_hash_type(HashType::SHA256); kem_params->set_hkdf_salt(""); return key_format; } TEST(EciesAeadHkdfPrivateKeyManagerTest, ValidateKeyFormat) { EXPECT_THAT(EciesAeadHkdfPrivateKeyManager().ValidateKeyFormat( CreateValidKeyFormat()), IsOk()); } TEST(EciesAeadHkdfPrivateKeyManagerTest, ValidateKeyFormatNoPoint) { EciesAeadHkdfKeyFormat key_format = CreateValidKeyFormat(); key_format.mutable_params()->set_ec_point_format( EcPointFormat::UNKNOWN_FORMAT); EXPECT_THAT(EciesAeadHkdfPrivateKeyManager().ValidateKeyFormat(key_format), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesAeadHkdfPrivateKeyManagerTest, ValidateKeyFormatNoDem) { EciesAeadHkdfKeyFormat key_format = CreateValidKeyFormat(); key_format.mutable_params()->mutable_dem_params()->clear_aead_dem(); EXPECT_THAT(EciesAeadHkdfPrivateKeyManager().ValidateKeyFormat(key_format), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesAeadHkdfPrivateKeyManagerTest, ValidateKeyFormatNoKemCurve) { EciesAeadHkdfKeyFormat key_format = CreateValidKeyFormat(); key_format.mutable_params()->mutable_kem_params()->set_curve_type( EllipticCurveType::UNKNOWN_CURVE); EXPECT_THAT(EciesAeadHkdfPrivateKeyManager().ValidateKeyFormat(key_format), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesAeadHkdfPrivateKeyManagerTest, ValidateKeyFormatNoKemHash) { EciesAeadHkdfKeyFormat key_format = CreateValidKeyFormat(); key_format.mutable_params()->mutable_kem_params()->set_hkdf_hash_type( HashType::UNKNOWN_HASH); EXPECT_THAT(EciesAeadHkdfPrivateKeyManager().ValidateKeyFormat(key_format), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesAeadHkdfPrivateKeyManagerTest, CreateKey) { EciesAeadHkdfKeyFormat key_format = CreateValidKeyFormat(); ASSERT_THAT(EciesAeadHkdfPrivateKeyManager().CreateKey(key_format).status(), IsOk()); EciesAeadHkdfPrivateKey key = EciesAeadHkdfPrivateKeyManager().CreateKey(key_format).value(); EXPECT_THAT(key.public_key().params().kem_params().curve_type(), Eq(key_format.params().kem_params().curve_type())); EXPECT_THAT(key.public_key().params().kem_params().hkdf_hash_type(), Eq(key_format.params().kem_params().hkdf_hash_type())); EXPECT_THAT(key.public_key().params().dem_params().aead_dem().type_url(), Eq(key_format.params().dem_params().aead_dem().type_url())); EXPECT_THAT(key.public_key().params().dem_params().aead_dem().value(), Eq(key_format.params().dem_params().aead_dem().value())); EXPECT_THAT( key.public_key().params().dem_params().aead_dem().output_prefix_type(), Eq(key_format.params().dem_params().aead_dem().output_prefix_type())); EXPECT_THAT(key.public_key().x(), Not(IsEmpty())); EXPECT_THAT(key.public_key().y(), Not(IsEmpty())); EXPECT_THAT(key.key_value(), Not(IsEmpty())); } EciesAeadHkdfPrivateKey CreateValidKey() { return EciesAeadHkdfPrivateKeyManager() .CreateKey(CreateValidKeyFormat()) .value(); } TEST(EciesAeadHkdfPrivateKeyManagerTest, ValidateKeyEmpty) { EXPECT_THAT( EciesAeadHkdfPrivateKeyManager().ValidateKey(EciesAeadHkdfPrivateKey()), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesAeadHkdfPrivateKeyManagerTest, ValidateKey) { EXPECT_THAT(EciesAeadHkdfPrivateKeyManager().ValidateKey(CreateValidKey()), IsOk()); } TEST(EciesAeadHkdfPrivateKeyManagerTest, ValidateKeyWrongVersion) { EciesAeadHkdfPrivateKey key = CreateValidKey(); key.set_version(1); EXPECT_THAT(EciesAeadHkdfPrivateKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesAeadHkdfPrivateKeyManagerTest, ValidateKeyNoPoint) { EciesAeadHkdfPrivateKey key = CreateValidKey(); key.mutable_public_key()->mutable_params()->set_ec_point_format( EcPointFormat::UNKNOWN_FORMAT); EXPECT_THAT(EciesAeadHkdfPrivateKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesAeadHkdfPrivateKeyManagerTest, ValidateKeyNoDem) { EciesAeadHkdfPrivateKey key = CreateValidKey(); key.mutable_public_key() ->mutable_params() ->mutable_dem_params() ->clear_aead_dem(); EXPECT_THAT(EciesAeadHkdfPrivateKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesAeadHkdfPrivateKeyManagerTest, ValidateKeyNoKemCurve) { EciesAeadHkdfPrivateKey key = CreateValidKey(); key.mutable_public_key() ->mutable_params() ->mutable_kem_params() ->set_curve_type(EllipticCurveType::UNKNOWN_CURVE); EXPECT_THAT(EciesAeadHkdfPrivateKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesAeadHkdfPrivateKeyManagerTest, ValidateKeyNoKemHash) { EciesAeadHkdfPrivateKey key = CreateValidKey(); key.mutable_public_key() ->mutable_params() ->mutable_kem_params() ->set_hkdf_hash_type(HashType::UNKNOWN_HASH); EXPECT_THAT(EciesAeadHkdfPrivateKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesAeadHkdfPrivateKeyManagerTest, GetPublicKey) { EciesAeadHkdfPrivateKey key = CreateValidKey(); ASSERT_THAT(EciesAeadHkdfPrivateKeyManager().GetPublicKey(key).status(), IsOk()); EciesAeadHkdfPublicKey public_key = EciesAeadHkdfPrivateKeyManager().GetPublicKey(key).value(); EXPECT_THAT(public_key.params().kem_params().curve_type(), Eq(key.public_key().params().kem_params().curve_type())); EXPECT_THAT(public_key.params().kem_params().hkdf_hash_type(), Eq(key.public_key().params().kem_params().hkdf_hash_type())); EXPECT_THAT(public_key.params().dem_params().aead_dem().type_url(), Eq(key.public_key().params().dem_params().aead_dem().type_url())); EXPECT_THAT(public_key.params().dem_params().aead_dem().value(), Eq(key.public_key().params().dem_params().aead_dem().value())); EXPECT_THAT(public_key.params().dem_params().aead_dem().output_prefix_type(), Eq(key.public_key() .params() .dem_params() .aead_dem() .output_prefix_type())); EXPECT_THAT(public_key.x(), Not(IsEmpty())); EXPECT_THAT(public_key.y(), Not(IsEmpty())); } TEST(EciesAeadHkdfPrivateKeyManagerTest, Create) { ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); EciesAeadHkdfPrivateKey private_key = CreateValidKey(); EciesAeadHkdfPublicKey public_key = EciesAeadHkdfPrivateKeyManager().GetPublicKey(private_key).value(); auto decrypt_or = EciesAeadHkdfPrivateKeyManager().GetPrimitive(private_key); ASSERT_THAT(decrypt_or, IsOk()); auto encrypt_or = EciesAeadHkdfHybridEncrypt::New(public_key); ASSERT_THAT(encrypt_or, IsOk()); ASSERT_THAT(HybridEncryptThenDecrypt(encrypt_or.value().get(), decrypt_or.value().get(), "some text", "some aad"), IsOk()); } TEST(EciesAeadHkdfPrivateKeyManagerTest, CreateDifferentKey) { ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); EciesAeadHkdfPrivateKey private_key = CreateValidKey(); // Note: we create a new private key in the next line. EciesAeadHkdfPublicKey public_key = EciesAeadHkdfPrivateKeyManager().GetPublicKey(CreateValidKey()).value(); auto decrypt_or = EciesAeadHkdfPrivateKeyManager().GetPrimitive(private_key); ASSERT_THAT(decrypt_or, IsOk()); auto encrypt_or = EciesAeadHkdfHybridEncrypt::New(public_key); ASSERT_THAT(encrypt_or, IsOk()); ASSERT_THAT(HybridEncryptThenDecrypt(encrypt_or.value().get(), decrypt_or.value().get(), "some text", "some aad"), Not(IsOk())); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/ecies_aead_hkdf_public_key_manager.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/ecies_aead_hkdf_public_key_manager.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/hybrid/ecies_aead_hkdf_hybrid_encrypt.h" #include "tink/hybrid_encrypt.h" #include "tink/key_manager.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/common.pb.h" #include "proto/ecies_aead_hkdf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using crypto::tink::util::Status; using google::crypto::tink::EciesAeadHkdfParams; using google::crypto::tink::EciesAeadHkdfPublicKey; using google::crypto::tink::EcPointFormat; using google::crypto::tink::EllipticCurveType; using google::crypto::tink::HashType; Status EciesAeadHkdfPublicKeyManager::ValidateParams( const EciesAeadHkdfParams& params) const { // Validate KEM params. if (!params.has_kem_params()) { return Status(absl::StatusCode::kInvalidArgument, "Missing kem_params."); } if (params.kem_params().curve_type() == EllipticCurveType::UNKNOWN_CURVE || params.kem_params().hkdf_hash_type() == HashType::UNKNOWN_HASH) { return Status(absl::StatusCode::kInvalidArgument, "Invalid kem_params."); } // Validate DEM params. if (!params.has_dem_params()) { return Status(absl::StatusCode::kInvalidArgument, "Missing dem_params."); } if (!params.dem_params().has_aead_dem()) { return Status(absl::StatusCode::kInvalidArgument, "Invalid dem_params."); } // Validate EC point format. if (params.ec_point_format() == EcPointFormat::UNKNOWN_FORMAT) { return Status(absl::StatusCode::kInvalidArgument, "Unknown EC point format."); } return util::OkStatus(); } Status EciesAeadHkdfPublicKeyManager::ValidateKey( const EciesAeadHkdfPublicKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; if (!key.has_params()) { return Status(absl::StatusCode::kInvalidArgument, "Missing params."); } return ValidateParams(key.params()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/ecies_aead_hkdf_public_key_manager.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_ECIES_AEAD_HKDF_PUBLIC_KEY_MANAGER_H_ #define TINK_HYBRID_ECIES_AEAD_HKDF_PUBLIC_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/hybrid/ecies_aead_hkdf_hybrid_encrypt.h" #include "tink/hybrid_encrypt.h" #include "tink/key_manager.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/ecies_aead_hkdf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class EciesAeadHkdfPublicKeyManager : public KeyTypeManager> { public: class HybridEncryptFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::EciesAeadHkdfPublicKey& ecies_public_key) const override { return EciesAeadHkdfHybridEncrypt::New(ecies_public_key); } }; EciesAeadHkdfPublicKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PUBLIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::EciesAeadHkdfPublicKey& key) const override; crypto::tink::util::Status ValidateParams( const google::crypto::tink::EciesAeadHkdfParams& params) const; private: const std::string key_type_ = absl::StrCat( kTypeGoogleapisCom, google::crypto::tink::EciesAeadHkdfPublicKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_HYBRID_ECIES_AEAD_HKDF_PUBLIC_KEY_MANAGER_H_ ================================================ FILE: cc/hybrid/ecies_aead_hkdf_public_key_manager_test.cc ================================================ // Copyright 2017 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/ecies_aead_hkdf_public_key_manager.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/aead/aead_key_templates.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/hybrid/ecies_aead_hkdf_private_key_manager.h" #include "tink/hybrid_encrypt.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_eax.pb.h" #include "proto/common.pb.h" #include "proto/ecies_aead_hkdf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::EciesAeadHkdfKeyFormat; using ::google::crypto::tink::EciesAeadHkdfParams; using ::google::crypto::tink::EciesAeadHkdfPublicKey; using ::google::crypto::tink::EcPointFormat; using ::google::crypto::tink::EllipticCurveType; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::testing::Eq; TEST(EciesAeadHkdfPublicKeyManagerTest, Basics) { EXPECT_THAT(EciesAeadHkdfPublicKeyManager().get_version(), Eq(0)); EXPECT_THAT(EciesAeadHkdfPublicKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PUBLIC)); EXPECT_THAT( EciesAeadHkdfPublicKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.EciesAeadHkdfPublicKey")); } TEST(EciesAeadHkdfPublicKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT( EciesAeadHkdfPublicKeyManager().ValidateKey(EciesAeadHkdfPublicKey()), StatusIs(absl::StatusCode::kInvalidArgument)); } EciesAeadHkdfPublicKey CreatePublicKey() { EciesAeadHkdfKeyFormat key_format; key_format.mutable_params()->set_ec_point_format(EcPointFormat::UNCOMPRESSED); auto dem_params = key_format.mutable_params()->mutable_dem_params(); *(dem_params->mutable_aead_dem()) = AeadKeyTemplates::Aes128Gcm(); auto kem_params = key_format.mutable_params()->mutable_kem_params(); kem_params->set_curve_type(EllipticCurveType::NIST_P256); kem_params->set_hkdf_hash_type(HashType::SHA256); kem_params->set_hkdf_salt(""); auto private_key_manager = EciesAeadHkdfPrivateKeyManager(); return private_key_manager .GetPublicKey(private_key_manager.CreateKey(key_format).value()) .value(); } TEST(EciesAeadHkdfPublicKeyManagerTest, ValidateParams) { EXPECT_THAT(EciesAeadHkdfPublicKeyManager().ValidateParams( CreatePublicKey().params()), IsOk()); } TEST(EciesAeadHkdfPublicKeyManagerTest, ValidateKeyNoPoint) { EciesAeadHkdfParams params = CreatePublicKey().params(); params.set_ec_point_format(EcPointFormat::UNKNOWN_FORMAT); EXPECT_THAT(EciesAeadHkdfPublicKeyManager().ValidateParams(params), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesAeadHkdfPublicKeyManagerTest, ValidateKeyNoDem) { EciesAeadHkdfParams params = CreatePublicKey().params(); params.mutable_dem_params()->clear_aead_dem(); EXPECT_THAT(EciesAeadHkdfPublicKeyManager().ValidateParams(params), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesAeadHkdfPublicKeyManagerTest, ValidateKeyNoKemCurve) { EciesAeadHkdfParams params = CreatePublicKey().params(); params.mutable_kem_params()->set_curve_type(EllipticCurveType::UNKNOWN_CURVE); EXPECT_THAT(EciesAeadHkdfPublicKeyManager().ValidateParams(params), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesAeadHkdfPublicKeyManagerTest, ValidateKeyNoKemHash) { EciesAeadHkdfParams params = CreatePublicKey().params(); params.mutable_kem_params()->set_hkdf_hash_type(HashType::UNKNOWN_HASH); EXPECT_THAT(EciesAeadHkdfPublicKeyManager().ValidateParams(params), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesAeadHkdfPublicKeyManagerTest, ValidateGeneratedKey) { EXPECT_THAT(EciesAeadHkdfPublicKeyManager().ValidateKey(CreatePublicKey()), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/ecies_parameters.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/ecies_parameters.h" #include #include #include #include "absl/base/attributes.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/aead/aes_ctr_hmac_aead_parameters.h" #include "tink/aead/aes_gcm_parameters.h" #include "tink/aead/xchacha20_poly1305_parameters.h" #include "tink/daead/aes_siv_parameters.h" #include "tink/parameters.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { bool IsNistCurve(EciesParameters::CurveType curve_type) { return curve_type == EciesParameters::CurveType::kNistP256 || curve_type == EciesParameters::CurveType::kNistP384 || curve_type == EciesParameters::CurveType::kNistP521; } } // namespace EciesParameters::Builder& EciesParameters::Builder::SetCurveType( CurveType curve_type) { curve_type_ = curve_type; return *this; } EciesParameters::Builder& EciesParameters::Builder::SetHashType( HashType hash_type) { hash_type_ = hash_type; return *this; } EciesParameters::Builder& EciesParameters::Builder::SetNistCurvePointFormat( PointFormat point_format) { point_format_ = point_format; return *this; } EciesParameters::Builder& EciesParameters::Builder::SetDemId(DemId dem_id) { dem_id_ = dem_id; return *this; } EciesParameters::Builder& EciesParameters::Builder::SetSalt( absl::string_view salt) { if (!salt.empty()) { salt_ = std::string(salt); } return *this; } EciesParameters::Builder& EciesParameters::Builder::SetVariant( Variant variant) { variant_ = variant; return *this; } util::StatusOr EciesParameters::Builder::Build() { static const std::set* kSupportedCurves = new std::set({CurveType::kNistP256, CurveType::kNistP384, CurveType::kNistP521, CurveType::kX25519}); if (kSupportedCurves->find(curve_type_) == kSupportedCurves->end()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create ECIES parameters with unknown curve type."); } static const std::set* kSupportedHashes = new std::set( {HashType::kSha1, HashType::kSha224, HashType::kSha256, HashType::kSha384, HashType::kSha512}); if (kSupportedHashes->find(hash_type_) == kSupportedHashes->end()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create ECIES parameters with unknown hash type."); } static const std::set>* kSupportedPointFormats = new std::set>( {PointFormat::kCompressed, PointFormat::kUncompressed, PointFormat::kLegacyUncompressed, absl::nullopt}); if (kSupportedPointFormats->find(point_format_) == kSupportedPointFormats->end()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create ECIES parameters with unknown point format."); } static const std::set* kSupportedDemIds = new std::set( {DemId::kAes128GcmRaw, DemId::kAes256GcmRaw, DemId::kAes256SivRaw, DemId::kXChaCha20Poly1305Raw, DemId::kAes128CtrHmacSha256Raw, DemId::kAes256CtrHmacSha256Raw}); if (kSupportedDemIds->find(dem_id_) == kSupportedDemIds->end()) { return util::Status(absl::StatusCode::kInvalidArgument, "Cannot create ECIES parameters with unknown DEM."); } static const std::set* kSupportedVariants = new std::set( {Variant::kTink, Variant::kCrunchy, Variant::kNoPrefix}); if (kSupportedVariants->find(variant_) == kSupportedVariants->end()) { return util::Status(absl::StatusCode::kInvalidArgument, "Cannot create ECIES parameters with unknown variant."); } if (curve_type_ == EciesParameters::CurveType::kX25519 && point_format_.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Point format must not be specified for the X25519 curve."); } if (IsNistCurve(curve_type_) && !point_format_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Point format must be specified for a NIST curve."); } return EciesParameters(curve_type_, hash_type_, point_format_, dem_id_, salt_, variant_); } util::StatusOr> EciesParameters::CreateDemParameters() const { switch (dem_id_) { case DemId::kAes128GcmRaw: ABSL_FALLTHROUGH_INTENDED; case DemId::kAes256GcmRaw: { int key_size = (dem_id_ == EciesParameters::DemId::kAes128GcmRaw) ? 16 : 32; util::StatusOr aes_gcm_raw = AesGcmParameters::Builder() .SetKeySizeInBytes(key_size) .SetIvSizeInBytes(12) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kNoPrefix) .Build(); if (!aes_gcm_raw.ok()) { return aes_gcm_raw.status(); } return std::make_unique(*aes_gcm_raw); } case DemId::kAes256SivRaw: { util::StatusOr aes_256_siv_raw = AesSivParameters::Create(/*key_size_in_bytes=*/64, AesSivParameters::Variant::kNoPrefix); if (!aes_256_siv_raw.ok()) { return aes_256_siv_raw.status(); } return std::make_unique(*aes_256_siv_raw); } case DemId::kXChaCha20Poly1305Raw: { util::StatusOr xchacha20_poly1305_raw = XChaCha20Poly1305Parameters::Create( XChaCha20Poly1305Parameters::Variant::kNoPrefix); if (!xchacha20_poly1305_raw.ok()) { return xchacha20_poly1305_raw.status(); } return std::make_unique( *xchacha20_poly1305_raw); } case DemId::kAes128CtrHmacSha256Raw: ABSL_FALLTHROUGH_INTENDED; case DemId::kAes256CtrHmacSha256Raw: { // Allowed AES-CTR-HMAC DEMs have matching AES key and tag sizes. int size = (dem_id_ == EciesParameters::DemId::kAes128CtrHmacSha256Raw) ? 16 : 32; util::StatusOr aes_ctr_hmac_aead_raw = AesCtrHmacAeadParameters::Builder() .SetAesKeySizeInBytes(size) .SetHmacKeySizeInBytes(32) .SetIvSizeInBytes(16) .SetTagSizeInBytes(size) .SetHashType(AesCtrHmacAeadParameters::HashType::kSha256) .SetVariant(AesCtrHmacAeadParameters::Variant::kNoPrefix) .Build(); if (!aes_ctr_hmac_aead_raw.ok()) { return aes_ctr_hmac_aead_raw.status(); } return std::make_unique(*aes_ctr_hmac_aead_raw); } default: return util::Status( absl::StatusCode::kInternal, absl::StrCat("Cannot create DEM parameters for DEM id: ", dem_id_)); } } bool EciesParameters::operator==(const Parameters& other) const { const EciesParameters* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (curve_type_ != that->curve_type_) { return false; } if (hash_type_ != that->hash_type_) { return false; } if (point_format_ != that->point_format_) { return false; } if (dem_id_ != that->dem_id_) { return false; } if (salt_ != that->salt_) { return false; } if (variant_ != that->variant_) { return false; } return true; } } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/ecies_parameters.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_ECIES_PARAMETERS_H_ #define TINK_HYBRID_ECIES_PARAMETERS_H_ #include #include #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/hybrid/hybrid_parameters.h" #include "tink/parameters.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { class EciesParameters : public HybridParameters { public: // Description of the output prefix prepended to the ciphertext. enum class Variant : int { // Prepends '0x01' to ciphertext. kTink = 1, // Prepends '0x00' to ciphertext. kCrunchy = 2, // Does not prepend any prefix (i.e., keys must have no ID requirement). kNoPrefix = 3, // Added to guard from failures that may be caused by future expansions. kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Elliptic curve type used for KEM. enum class CurveType : int { kNistP256 = 1, kNistP384 = 2, kNistP521 = 3, kX25519 = 4, kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Hash algorithm used for KEM. enum class HashType : int { kSha1 = 1, kSha256 = 2, kSha224 = 3, kSha384 = 4, kSha512 = 5, kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Elliptic curve point format. enum class PointFormat : int { kCompressed = 1, kUncompressed = 2, // Same as `kUncompressed`, but without the leading '\x04' prefix byte. // Only used by Crunchy. DO NOT USE unless you are a Crunchy user migrating // to Tink. kLegacyUncompressed = 3, kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Data encapsulation mechanism (DEM) identifiers. Each entry should // correspond to either an allowed AEAD or an allowed Deterministic AEAD. enum class DemId : int { kAes128GcmRaw = 1, kAes256GcmRaw = 2, kAes256SivRaw = 3, kXChaCha20Poly1305Raw = 4, kAes128CtrHmacSha256Raw = 5, kAes256CtrHmacSha256Raw = 6, kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Creates ECIES parameters instances. class Builder { public: // Copyable and movable. Builder(const Builder& other) = default; Builder& operator=(const Builder& other) = default; Builder(Builder&& other) = default; Builder& operator=(Builder&& other) = default; // Creates initially empty parameters builder. Builder() = default; Builder& SetCurveType(CurveType curve); Builder& SetHashType(HashType hash); Builder& SetNistCurvePointFormat(PointFormat format); Builder& SetDemId(DemId dem_id); Builder& SetSalt(absl::string_view salt); Builder& SetVariant(Variant variant); // Creates ECIES parameters object from this builder. util::StatusOr Build(); private: CurveType curve_type_; HashType hash_type_; absl::optional point_format_ = absl::nullopt; DemId dem_id_; absl::optional salt_ = absl::nullopt; Variant variant_; }; // Copyable and movable. EciesParameters(const EciesParameters& other) = default; EciesParameters& operator=(const EciesParameters& other) = default; EciesParameters(EciesParameters&& other) = default; EciesParameters& operator=(EciesParameters&& other) = default; CurveType GetCurveType() const { return curve_type_; } HashType GetHashType() const { return hash_type_; } absl::optional GetNistCurvePointFormat() const { return point_format_; } DemId GetDemId() const { return dem_id_; } absl::optional GetSalt() const { return salt_; } Variant GetVariant() const { return variant_; } util::StatusOr> CreateDemParameters() const; bool HasIdRequirement() const override { return variant_ != Variant::kNoPrefix; } bool operator==(const Parameters& other) const override; private: explicit EciesParameters(CurveType curve_type, HashType hash_type, absl::optional point_format, DemId dem_id, absl::optional salt, Variant variant) : curve_type_(curve_type), hash_type_(hash_type), point_format_(point_format), dem_id_(dem_id), salt_(salt), variant_(variant) {} CurveType curve_type_; HashType hash_type_; absl::optional point_format_; DemId dem_id_; absl::optional salt_ = absl::nullopt; Variant variant_; }; } // namespace tink } // namespace crypto #endif // TINK_HYBRID_ECIES_PARAMETERS_H_ ================================================ FILE: cc/hybrid/ecies_parameters_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/ecies_parameters.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/aead/aes_ctr_hmac_aead_parameters.h" #include "tink/aead/aes_gcm_parameters.h" #include "tink/aead/xchacha20_poly1305_parameters.h" #include "tink/daead/aes_siv_parameters.h" #include "tink/parameters.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Combine; using ::testing::Eq; using ::testing::IsTrue; using ::testing::NotNull; using ::testing::TestWithParam; using ::testing::Values; constexpr absl::string_view kSalt = "2024ab"; struct VariantWithIdRequirement { EciesParameters::Variant variant; bool has_id_requirement; }; using EciesParametersTest = TestWithParam< std::tuple>; INSTANTIATE_TEST_SUITE_P( EciesParametersTestSuite, EciesParametersTest, Combine(Values(EciesParameters::CurveType::kNistP256, EciesParameters::CurveType::kNistP384, EciesParameters::CurveType::kNistP521), Values(EciesParameters::HashType::kSha1, EciesParameters::HashType::kSha224, EciesParameters::HashType::kSha256, EciesParameters::HashType::kSha384, EciesParameters::HashType::kSha512), Values(EciesParameters::PointFormat::kCompressed, EciesParameters::PointFormat::kUncompressed, EciesParameters::PointFormat::kLegacyUncompressed), Values(EciesParameters::DemId::kAes128GcmRaw, EciesParameters::DemId::kAes256GcmRaw, EciesParameters::DemId::kAes256SivRaw, EciesParameters::DemId::kXChaCha20Poly1305Raw, EciesParameters::DemId::kAes128CtrHmacSha256Raw, EciesParameters::DemId::kAes256CtrHmacSha256Raw), Values(VariantWithIdRequirement{EciesParameters::Variant::kTink, /*has_id_requirement=*/true}, VariantWithIdRequirement{EciesParameters::Variant::kCrunchy, /*has_id_requirement=*/true}, VariantWithIdRequirement{EciesParameters::Variant::kNoPrefix, /*has_id_requirement=*/false}))); TEST_P(EciesParametersTest, Build) { EciesParameters::CurveType curve_type; EciesParameters::HashType hash_type; EciesParameters::PointFormat point_format; EciesParameters::DemId dem_id; VariantWithIdRequirement variant; std::tie(curve_type, hash_type, point_format, dem_id, variant) = GetParam(); const std::string salt = absl::HexStringToBytes(kSalt); util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(curve_type) .SetHashType(hash_type) .SetNistCurvePointFormat(point_format) .SetDemId(dem_id) .SetSalt(salt) .SetVariant(variant.variant) .Build(); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetCurveType(), Eq(curve_type)); EXPECT_THAT(parameters->GetHashType(), Eq(hash_type)); EXPECT_THAT(parameters->GetNistCurvePointFormat(), Eq(point_format)); EXPECT_THAT(parameters->GetDemId(), Eq(dem_id)); EXPECT_THAT(parameters->GetSalt(), Eq(salt)); EXPECT_THAT(parameters->GetVariant(), Eq(variant.variant)); EXPECT_THAT(parameters->HasIdRequirement(), Eq(variant.has_id_requirement)); } TEST(EciesParametersTest, BuildWithX25519Curve) { util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kX25519) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetCurveType(), Eq(EciesParameters::CurveType::kX25519)); EXPECT_THAT(parameters->GetHashType(), Eq(EciesParameters::HashType::kSha256)); EXPECT_THAT(parameters->GetNistCurvePointFormat(), Eq(absl::nullopt)); EXPECT_THAT(parameters->GetDemId(), Eq(EciesParameters::DemId::kAes256SivRaw)); EXPECT_THAT(parameters->GetSalt(), Eq(absl::HexStringToBytes(kSalt))); EXPECT_THAT(parameters->GetVariant(), Eq(EciesParameters::Variant::kTink)); EXPECT_THAT(parameters->HasIdRequirement(), IsTrue()); } TEST(EciesParametersTest, BuildWithInvalidCurveTypeFails) { util::StatusOr parameters = EciesParameters::Builder() .SetCurveType( EciesParameters::CurveType:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesParametersTest, BuildWithoutCurveTypeFails) { util::StatusOr parameters = EciesParameters::Builder() .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesParametersTest, BuildWithInvalidHashTypeFails) { util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType( EciesParameters::HashType:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesParametersTest, BuildWithoutHashTypeFails) { util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesParametersTest, BuildWithInvalidPointFormatFails) { util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat( EciesParameters::PointFormat:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesParametersTest, BuildWithNistCurveWithoutPointFormatFails) { util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesParametersTest, BuildWithX25519WithPointFormatFails) { util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kX25519) .SetNistCurvePointFormat(EciesParameters::PointFormat::kCompressed) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesParametersTest, BuildWithInvalidDemIdFails) { util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesParametersTest, BuildWithoutDemIdFails) { util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesParametersTest, BuildWithEmptySaltSucceeds) { util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt("") .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetSalt(), Eq(absl::nullopt)); } TEST(EciesParametersTest, BuildWithoutSaltSucceeds) { util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetSalt(), Eq(absl::nullopt)); } TEST(EciesParametersTest, BuildWithInvalidVariantFails) { util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesParametersTest, BuildWithoutVariantFails) { util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes(kSalt)) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(Ed25519ParametersTest, CopyConstructor) { util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); EciesParameters copy(*parameters); EXPECT_THAT(copy.GetCurveType(), Eq(EciesParameters::CurveType::kNistP256)); EXPECT_THAT(copy.GetHashType(), Eq(EciesParameters::HashType::kSha256)); EXPECT_THAT(copy.GetNistCurvePointFormat(), Eq(EciesParameters::PointFormat::kUncompressed)); EXPECT_THAT(copy.GetDemId(), Eq(EciesParameters::DemId::kAes256SivRaw)); EXPECT_THAT(copy.GetSalt(), Eq(absl::HexStringToBytes(kSalt))); EXPECT_THAT(copy.GetVariant(), Eq(EciesParameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); } TEST(Ed25519ParametersTest, CopyAssignment) { util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); EciesParameters copy = *parameters; EXPECT_THAT(copy.GetCurveType(), Eq(EciesParameters::CurveType::kNistP256)); EXPECT_THAT(copy.GetHashType(), Eq(EciesParameters::HashType::kSha256)); EXPECT_THAT(copy.GetNistCurvePointFormat(), Eq(EciesParameters::PointFormat::kUncompressed)); EXPECT_THAT(copy.GetDemId(), Eq(EciesParameters::DemId::kAes256SivRaw)); EXPECT_THAT(copy.GetSalt(), Eq(absl::HexStringToBytes(kSalt))); EXPECT_THAT(copy.GetVariant(), Eq(EciesParameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); } TEST_P(EciesParametersTest, ParametersEqual) { EciesParameters::CurveType curve_type; EciesParameters::HashType hash_type; EciesParameters::PointFormat point_format; EciesParameters::DemId dem_id; VariantWithIdRequirement variant; std::tie(curve_type, hash_type, point_format, dem_id, variant) = GetParam(); const std::string salt = absl::HexStringToBytes(kSalt); util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(curve_type) .SetHashType(hash_type) .SetNistCurvePointFormat(point_format) .SetDemId(dem_id) .SetSalt(salt) .SetVariant(variant.variant) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = EciesParameters::Builder() .SetCurveType(curve_type) .SetHashType(hash_type) .SetNistCurvePointFormat(point_format) .SetDemId(dem_id) .SetSalt(salt) .SetVariant(variant.variant) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters == *other_parameters); EXPECT_TRUE(*other_parameters == *parameters); EXPECT_FALSE(*parameters != *other_parameters); EXPECT_FALSE(*other_parameters != *parameters); } TEST(EciesParametersTest, CurveTypeNotEqual) { util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP384) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(EciesParametersTest, HashTypeNotEqual) { util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha384) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(EciesParametersTest, PointFormatNotEqual) { util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kCompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(EciesParametersTest, DemIdNotEqual) { util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes128GcmRaw) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(EciesParametersTest, SaltNotEqual) { util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes("2024ab")) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes("2024xy")) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(EciesParametersTest, EmptySaltAndNoSaltEqual) { util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes("")) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters == *other_parameters); EXPECT_FALSE(*parameters != *other_parameters); } TEST(EciesParametersTest, VariantNotEqual) { util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kTink) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } struct AesGcmDemTestCase { EciesParameters::DemId dem_id; int key_size_in_bytes; }; using AesGcmDemTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( AesGcmDemTestSuite, AesGcmDemTest, Values(AesGcmDemTestCase{EciesParameters::DemId::kAes128GcmRaw, /*key_size_in_bytes=*/16}, AesGcmDemTestCase{EciesParameters::DemId::kAes256GcmRaw, /*key_size_in_bytes=*/32})); TEST_P(AesGcmDemTest, CreateAesGcmRawDemParameters) { AesGcmDemTestCase test_case = GetParam(); util::StatusOr ecies_parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(test_case.dem_id) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(ecies_parameters, IsOk()); util::StatusOr> dem_parameters = ecies_parameters->CreateDemParameters(); ASSERT_THAT(dem_parameters, IsOk()); const AesGcmParameters* aes_128_gcm_parameters = reinterpret_cast((dem_parameters)->get()); ASSERT_THAT(aes_128_gcm_parameters, NotNull()); EXPECT_THAT(aes_128_gcm_parameters->KeySizeInBytes(), Eq(test_case.key_size_in_bytes)); EXPECT_THAT(aes_128_gcm_parameters->IvSizeInBytes(), Eq(12)); EXPECT_THAT(aes_128_gcm_parameters->TagSizeInBytes(), Eq(16)); EXPECT_THAT(aes_128_gcm_parameters->GetVariant(), Eq(AesGcmParameters::Variant::kNoPrefix)); } TEST(EciesParametersTest, CreateAes256SivRawDemParameters) { util::StatusOr ecies_parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(ecies_parameters, IsOk()); util::StatusOr> dem_parameters = ecies_parameters->CreateDemParameters(); ASSERT_THAT(dem_parameters, IsOk()); const AesSivParameters* aes_256_siv_parameters = reinterpret_cast((dem_parameters)->get()); ASSERT_THAT(aes_256_siv_parameters, NotNull()); EXPECT_THAT(aes_256_siv_parameters->KeySizeInBytes(), Eq(64)); EXPECT_THAT(aes_256_siv_parameters->GetVariant(), Eq(AesSivParameters::Variant::kNoPrefix)); } TEST(EciesParametersTest, CreateXChaCha20Poly1305RawDemParameters) { util::StatusOr ecies_parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kXChaCha20Poly1305Raw) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(ecies_parameters, IsOk()); util::StatusOr> dem_parameters = ecies_parameters->CreateDemParameters(); ASSERT_THAT(dem_parameters, IsOk()); const XChaCha20Poly1305Parameters* xchacha20_poly1305_parameters = reinterpret_cast( (dem_parameters)->get()); ASSERT_THAT(xchacha20_poly1305_parameters, NotNull()); EXPECT_THAT(xchacha20_poly1305_parameters->GetVariant(), Eq(XChaCha20Poly1305Parameters::Variant::kNoPrefix)); } struct AesCtrHmacDemTestCase { EciesParameters::DemId dem_id; int aes_key_size_in_bytes; int tag_size_in_bytes; }; using AesCtrHmacDemTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( AesCtrHmacDemTestSuite, AesCtrHmacDemTest, Values( AesCtrHmacDemTestCase{EciesParameters::DemId::kAes128CtrHmacSha256Raw, /*aes_key_size_in_bytes=*/16, /*tag_size_in_bytes=*/16}, AesCtrHmacDemTestCase{EciesParameters::DemId::kAes256CtrHmacSha256Raw, /*aes_key_size_in_bytes=*/32, /*tag_size_in_bytes=*/32})); TEST_P(AesCtrHmacDemTest, CreateAesCtrHmacSha256RawDemParameters) { AesCtrHmacDemTestCase test_case = GetParam(); util::StatusOr ecies_parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(test_case.dem_id) .SetSalt(absl::HexStringToBytes(kSalt)) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(ecies_parameters, IsOk()); util::StatusOr> dem_parameters = ecies_parameters->CreateDemParameters(); ASSERT_THAT(dem_parameters, IsOk()); const AesCtrHmacAeadParameters* aes_ctr_hmac_aead_parameters = reinterpret_cast( (dem_parameters)->get()); ASSERT_THAT(aes_ctr_hmac_aead_parameters, NotNull()); EXPECT_THAT(aes_ctr_hmac_aead_parameters->GetAesKeySizeInBytes(), Eq(test_case.aes_key_size_in_bytes)); EXPECT_THAT(aes_ctr_hmac_aead_parameters->GetHmacKeySizeInBytes(), Eq(32)); EXPECT_THAT(aes_ctr_hmac_aead_parameters->GetIvSizeInBytes(), Eq(16)); EXPECT_THAT(aes_ctr_hmac_aead_parameters->GetTagSizeInBytes(), Eq(test_case.tag_size_in_bytes)); EXPECT_THAT(aes_ctr_hmac_aead_parameters->GetHashType(), Eq(AesCtrHmacAeadParameters::HashType::kSha256)); EXPECT_THAT(aes_ctr_hmac_aead_parameters->GetVariant(), Eq(AesCtrHmacAeadParameters::Variant::kNoPrefix)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/ecies_private_key.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/ecies_private_key.h" #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #include "openssl/ec_key.h" #else #include "openssl/ec.h" #endif #include "tink/ec_point.h" #include "tink/hybrid/ecies_parameters.h" #include "tink/hybrid/ecies_public_key.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/bn_util.h" #include "tink/internal/ec_util.h" #include "tink/internal/err_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_big_integer.h" #include "tink/restricted_data.h" #include "tink/subtle/common_enums.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { util::StatusOr SubtleCurveType( EciesParameters::CurveType curve_type) { switch (curve_type) { case EciesParameters::CurveType::kNistP256: return subtle::EllipticCurveType::NIST_P256; case EciesParameters::CurveType::kNistP384: return subtle::EllipticCurveType::NIST_P384; case EciesParameters::CurveType::kNistP521: return subtle::EllipticCurveType::NIST_P521; case EciesParameters::CurveType::kX25519: return subtle::EllipticCurveType::CURVE25519; default: return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Unknown curve type: ", curve_type)); } } util::Status ValidateNistKeyPair(const EciesPublicKey& public_key, const RestrictedBigInteger& private_key_value, PartialKeyAccessToken token) { internal::SslUniquePtr key(EC_KEY_new()); // Set EC_KEY group. util::StatusOr curve = SubtleCurveType(public_key.GetParameters().GetCurveType()); if (!curve.ok()) { return curve.status(); } util::StatusOr> group = internal::EcGroupFromCurveType(*curve); if (!group.ok()) { return group.status(); } EC_KEY_set_group(key.get(), group->get()); // Set EC_KEY public key. absl::optional ec_point = public_key.GetNistCurvePoint(token); if (!ec_point.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Missing public point for NIST curve public key."); } util::StatusOr> public_point = internal::GetEcPoint(*curve, ec_point->GetX().GetValue(), ec_point->GetY().GetValue()); if (!public_point.ok()) { return public_point.status(); } if (!EC_KEY_set_public_key(key.get(), public_point->get())) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid public key: ", internal::GetSslErrors())); } // Set EC_KEY private key. util::StatusOr> priv_big_num = internal::StringToBignum( private_key_value.GetSecret(InsecureSecretKeyAccess::Get())); if (!priv_big_num.ok()) { return priv_big_num.status(); } if (!EC_KEY_set_private_key(key.get(), priv_big_num->get())) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid private key: ", internal::GetSslErrors())); } // Check that EC_KEY is valid. if (!EC_KEY_check_key(key.get())) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid EC key pair: ", internal::GetSslErrors())); } return util::OkStatus(); } util::Status ValidateX25519KeyPair(const EciesPublicKey& public_key, const RestrictedData& private_key_bytes, PartialKeyAccessToken token) { util::StatusOr> x25519_key = internal::X25519KeyFromPrivateKey(util::SecretDataFromStringView( private_key_bytes.GetSecret(InsecureSecretKeyAccess::Get()))); if (!x25519_key.ok()) { return x25519_key.status(); } absl::optional public_key_bytes = public_key.GetX25519CurvePointBytes(token); if (!public_key_bytes.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Missing public key bytes for X25519 public key."); } absl::string_view public_key_bytes_from_private = absl::string_view( reinterpret_cast((*x25519_key)->public_value), internal::X25519KeyPubKeySize()); if (public_key_bytes != public_key_bytes_from_private) { return util::Status( absl::StatusCode::kInvalidArgument, "X25519 private key does not match the specified X25519 public key."); } return util::OkStatus(); } } // namespace util::StatusOr EciesPrivateKey::CreateForNistCurve( const EciesPublicKey& public_key, const RestrictedBigInteger& private_key_value, PartialKeyAccessToken token) { // Validate that public and private key match. util::Status key_pair_validation = ValidateNistKeyPair(public_key, private_key_value, token); if (!key_pair_validation.ok()) { return key_pair_validation; } return EciesPrivateKey(public_key, private_key_value); } util::StatusOr EciesPrivateKey::CreateForCurveX25519( const EciesPublicKey& public_key, const RestrictedData& private_key_bytes, PartialKeyAccessToken token) { // Validate private key length. int private_key_length = private_key_bytes.GetSecret(InsecureSecretKeyAccess::Get()).length(); if (private_key_length != internal::X25519KeyPrivKeySize()) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrFormat( "Invalid X25519 private key length (expected %d, got %d)", internal::X25519KeyPrivKeySize(), private_key_length)); } // Validate that public and private key match. util::Status key_pair_validation = ValidateX25519KeyPair(public_key, private_key_bytes, token); if (!key_pair_validation.ok()) { return key_pair_validation; } return EciesPrivateKey(public_key, private_key_bytes); } bool EciesPrivateKey::operator==(const Key& other) const { const EciesPrivateKey* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (public_key_ != that->public_key_) { return false; } if (private_key_value_ != that->private_key_value_) { return false; } return private_key_bytes_ == that->private_key_bytes_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/ecies_private_key.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_ECIES_PRIVATE_KEY_H_ #define TINK_HYBRID_ECIES_PRIVATE_KEY_H_ #include "absl/types/optional.h" #include "tink/hybrid/ecies_public_key.h" #include "tink/hybrid/hybrid_private_key.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_big_integer.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Representation of the decryption function for an ECIES hybrid encryption // primitive. class EciesPrivateKey : public HybridPrivateKey { public: // Copyable and movable. EciesPrivateKey(const EciesPrivateKey& other) = default; EciesPrivateKey& operator=(const EciesPrivateKey& other) = default; EciesPrivateKey(EciesPrivateKey&& other) = default; EciesPrivateKey& operator=(EciesPrivateKey&& other) = default; static util::StatusOr CreateForNistCurve( const EciesPublicKey& public_key, const RestrictedBigInteger& private_key_value, PartialKeyAccessToken token); static util::StatusOr CreateForCurveX25519( const EciesPublicKey& public_key, const RestrictedData& private_key_bytes, PartialKeyAccessToken token); absl::optional GetNistPrivateKeyValue( PartialKeyAccessToken token) const { return private_key_value_; } absl::optional GetX25519PrivateKeyBytes( PartialKeyAccessToken token) const { return private_key_bytes_; } const EciesPublicKey& GetPublicKey() const override { return public_key_; } bool operator==(const Key& other) const override; private: // Creates a NIST curve-based ECIES private key. explicit EciesPrivateKey(const EciesPublicKey& public_key, const RestrictedBigInteger& private_key_value) : public_key_(public_key), private_key_value_(private_key_value), private_key_bytes_(absl::nullopt) {} // Creates an X25519-based ECIES private key. explicit EciesPrivateKey(const EciesPublicKey& public_key, const RestrictedData& private_key_bytes) : public_key_(public_key), private_key_value_(absl::nullopt), private_key_bytes_(private_key_bytes) {} EciesPublicKey public_key_; absl::optional private_key_value_; absl::optional private_key_bytes_; }; } // namespace tink } // namespace crypto #endif // TINK_HYBRID_ECIES_PRIVATE_KEY_H_ ================================================ FILE: cc/hybrid/ecies_private_key_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/ecies_private_key.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #include "openssl/ec_key.h" #endif #include "tink/big_integer.h" #include "tink/ec_point.h" #include "tink/hybrid/ecies_parameters.h" #include "tink/hybrid/ecies_public_key.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/ec_util.h" #include "tink/partial_key_access.h" #include "tink/restricted_big_integer.h" #include "tink/restricted_data.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/random.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::IsEmpty; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { subtle::EllipticCurveType curve; EciesParameters::CurveType curve_type; EciesParameters::HashType hash_type; subtle::EcPointFormat ec_point_format; EciesParameters::PointFormat point_format; EciesParameters::DemId dem_id; EciesParameters::Variant variant; absl::optional id_requirement; std::string output_prefix; }; using EciesPrivateKeyTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( EciesPrivateKeyTestSuite, EciesPrivateKeyTest, Values(TestCase{subtle::EllipticCurveType::NIST_P256, EciesParameters::CurveType::kNistP256, EciesParameters::HashType::kSha256, subtle::EcPointFormat::COMPRESSED, EciesParameters::PointFormat::kCompressed, EciesParameters::DemId::kAes128GcmRaw, EciesParameters::Variant::kTink, /*id_requirement=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{subtle::EllipticCurveType::NIST_P384, EciesParameters::CurveType::kNistP384, EciesParameters::HashType::kSha384, subtle::EcPointFormat::DO_NOT_USE_CRUNCHY_UNCOMPRESSED, EciesParameters::PointFormat::kLegacyUncompressed, EciesParameters::DemId::kAes256GcmRaw, EciesParameters::Variant::kCrunchy, /*id_requirement=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{subtle::EllipticCurveType::NIST_P521, EciesParameters::CurveType::kNistP521, EciesParameters::HashType::kSha512, subtle::EcPointFormat::UNCOMPRESSED, EciesParameters::PointFormat::kUncompressed, EciesParameters::DemId::kAes256SivRaw, EciesParameters::Variant::kNoPrefix, /*id_requirement=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(EciesPrivateKeyTest, CreateNistCurvePrivateKey) { TestCase test_case = GetParam(); util::StatusOr params = EciesParameters::Builder() .SetCurveType(test_case.curve_type) .SetHashType(test_case.hash_type) .SetNistCurvePointFormat(test_case.point_format) .SetDemId(test_case.dem_id) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr ec_key = internal::NewEcKey(test_case.curve); ASSERT_THAT(ec_key, IsOk()); EcPoint public_point(BigInteger(ec_key->pub_x), BigInteger(ec_key->pub_y)); util::StatusOr public_key = EciesPublicKey::CreateForNistCurve(*params, public_point, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); RestrictedBigInteger private_key_value = RestrictedBigInteger(util::SecretDataAsStringView(ec_key->priv), InsecureSecretKeyAccess::Get()); util::StatusOr private_key = EciesPrivateKey::CreateForNistCurve(*public_key, private_key_value, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); EXPECT_THAT(private_key->GetParameters(), Eq(*params)); EXPECT_THAT(private_key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(private_key->GetPublicKey(), Eq(*public_key)); EXPECT_THAT(private_key->GetOutputPrefix(), Eq(test_case.output_prefix)); EXPECT_THAT(private_key->GetNistPrivateKeyValue(GetPartialKeyAccess()), Eq(private_key_value)); EXPECT_THAT(private_key->GetX25519PrivateKeyBytes(GetPartialKeyAccess()), Eq(absl::nullopt)); } TEST(EciesPublicKeyTest, CreateX25519PublicKey) { util::StatusOr params = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kX25519) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr> x25519_key = internal::NewX25519Key(); ASSERT_THAT(x25519_key, IsOk()); std::string public_key_bytes = std::string(reinterpret_cast((*x25519_key)->public_value), internal::X25519KeyPubKeySize()); RestrictedData private_key_bytes = RestrictedData( std::string(reinterpret_cast((*x25519_key)->private_key), internal::X25519KeyPrivKeySize()), InsecureSecretKeyAccess::Get()); util::StatusOr public_key = EciesPublicKey::CreateForCurveX25519(*params, public_key_bytes, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = EciesPrivateKey::CreateForCurveX25519(*public_key, private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); EXPECT_THAT(private_key->GetParameters(), Eq(*params)); EXPECT_THAT(private_key->GetIdRequirement(), Eq(absl::nullopt)); EXPECT_THAT(private_key->GetPublicKey(), Eq(*public_key)); EXPECT_THAT(private_key->GetOutputPrefix(), IsEmpty()); EXPECT_THAT(private_key->GetNistPrivateKeyValue(GetPartialKeyAccess()), Eq(absl::nullopt)); EXPECT_THAT(private_key->GetX25519PrivateKeyBytes(GetPartialKeyAccess()), Eq(private_key_bytes)); } TEST_P(EciesPrivateKeyTest, CreateMismatchedNistCurveKeyPairFails) { TestCase test_case = GetParam(); util::StatusOr params = EciesParameters::Builder() .SetCurveType(test_case.curve_type) .SetHashType(test_case.hash_type) .SetNistCurvePointFormat(test_case.point_format) .SetDemId(test_case.dem_id) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr ec_key1 = internal::NewEcKey(test_case.curve); ASSERT_THAT(ec_key1, IsOk()); EcPoint public_point(BigInteger(ec_key1->pub_x), BigInteger(ec_key1->pub_y)); util::StatusOr public_key1 = EciesPublicKey::CreateForNistCurve(*params, public_point, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key1, IsOk()); util::StatusOr ec_key2 = internal::NewEcKey(test_case.curve); ASSERT_THAT(ec_key2, IsOk()); RestrictedBigInteger private_key_bytes2 = RestrictedBigInteger(util::SecretDataAsStringView(ec_key2->priv), InsecureSecretKeyAccess::Get()); EXPECT_THAT(EciesPrivateKey::CreateForNistCurve( *public_key1, private_key_bytes2, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesPrivateKeyTest, CreateMismatchedX25519KeyPairFails) { util::StatusOr params = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kX25519) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = EciesPublicKey::CreateForCurveX25519(*params, public_key_bytes, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); RestrictedData private_key_bytes = RestrictedData( subtle::Random::GetRandomBytes(32), InsecureSecretKeyAccess::Get()); EXPECT_THAT(EciesPrivateKey::CreateForCurveX25519( *public_key, private_key_bytes, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesPrivateKeyTest, CreateX25519PrivateKeyWithInvalidKeyLengthFails) { util::StatusOr params = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kX25519) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr> x25519_key = internal::NewX25519Key(); ASSERT_THAT(x25519_key, IsOk()); std::string public_key_bytes = std::string(reinterpret_cast((*x25519_key)->public_value), internal::X25519KeyPubKeySize()); std::string private_key_input = std::string(reinterpret_cast((*x25519_key)->private_key), internal::X25519KeyPrivKeySize()); RestrictedData expanded_private_key_bytes = RestrictedData( absl::StrCat(absl::HexStringToBytes("00"), private_key_input), InsecureSecretKeyAccess::Get()); util::StatusOr public_key = EciesPublicKey::CreateForCurveX25519(*params, public_key_bytes, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); EXPECT_THAT( EciesPrivateKey::CreateForCurveX25519( *public_key, expanded_private_key_bytes, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(EciesPrivateKeyTest, NistCurvePrivateKeyEquals) { TestCase test_case = GetParam(); util::StatusOr params = EciesParameters::Builder() .SetCurveType(test_case.curve_type) .SetHashType(test_case.hash_type) .SetNistCurvePointFormat(test_case.point_format) .SetDemId(test_case.dem_id) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr ec_key = internal::NewEcKey(test_case.curve); ASSERT_THAT(ec_key, IsOk()); EcPoint public_point(BigInteger(ec_key->pub_x), BigInteger(ec_key->pub_y)); util::StatusOr public_key = EciesPublicKey::CreateForNistCurve(*params, public_point, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); RestrictedBigInteger private_key_value = RestrictedBigInteger(util::SecretDataAsStringView(ec_key->priv), InsecureSecretKeyAccess::Get()); util::StatusOr private_key = EciesPrivateKey::CreateForNistCurve(*public_key, private_key_value, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr other_private_key = EciesPrivateKey::CreateForNistCurve(*public_key, private_key_value, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); EXPECT_TRUE(*private_key == *other_private_key); EXPECT_TRUE(*other_private_key == *private_key); EXPECT_FALSE(*private_key != *other_private_key); EXPECT_FALSE(*other_private_key != *private_key); } TEST(EciesPrivateKeyTest, X25519PrivateKeyEquals) { util::StatusOr params = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kX25519) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr> x25519_key = internal::NewX25519Key(); ASSERT_THAT(x25519_key, IsOk()); std::string public_key_bytes = std::string(reinterpret_cast((*x25519_key)->public_value), internal::X25519KeyPubKeySize()); RestrictedData private_key_bytes = RestrictedData( std::string(reinterpret_cast((*x25519_key)->private_key), internal::X25519KeyPrivKeySize()), InsecureSecretKeyAccess::Get()); util::StatusOr public_key = EciesPublicKey::CreateForCurveX25519(*params, public_key_bytes, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = EciesPrivateKey::CreateForCurveX25519(*public_key, private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr other_private_key = EciesPrivateKey::CreateForCurveX25519(*public_key, private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(other_private_key, IsOk()); EXPECT_TRUE(*private_key == *other_private_key); EXPECT_TRUE(*other_private_key == *private_key); EXPECT_FALSE(*private_key != *other_private_key); EXPECT_FALSE(*other_private_key != *private_key); } TEST(EciesPrivateKeyTest, DifferentPublicKeyNotEqual) { util::StatusOr params = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kX25519) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kTink) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr> x25519_key = internal::NewX25519Key(); ASSERT_THAT(x25519_key, IsOk()); std::string public_key_bytes = std::string(reinterpret_cast((*x25519_key)->public_value), internal::X25519KeyPubKeySize()); RestrictedData private_key_bytes = RestrictedData( std::string(reinterpret_cast((*x25519_key)->private_key), internal::X25519KeyPrivKeySize()), InsecureSecretKeyAccess::Get()); util::StatusOr public_key123 = EciesPublicKey::CreateForCurveX25519(*params, public_key_bytes, /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(public_key123, IsOk()); util::StatusOr public_key456 = EciesPublicKey::CreateForCurveX25519(*params, public_key_bytes, /*id_requirement=*/456, GetPartialKeyAccess()); ASSERT_THAT(public_key456, IsOk()); util::StatusOr private_key = EciesPrivateKey::CreateForCurveX25519(*public_key123, private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr other_private_key = EciesPrivateKey::CreateForCurveX25519(*public_key456, private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(other_private_key, IsOk()); EXPECT_TRUE(*private_key != *other_private_key); EXPECT_TRUE(*other_private_key != *private_key); EXPECT_FALSE(*private_key == *other_private_key); EXPECT_FALSE(*other_private_key == *private_key); } TEST(EciesPrivateKeyTest, DifferentKeyTypesNotEqual) { util::StatusOr params = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kX25519) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kTink) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr> x25519_key = internal::NewX25519Key(); ASSERT_THAT(x25519_key, IsOk()); std::string public_key_bytes = std::string(reinterpret_cast((*x25519_key)->public_value), internal::X25519KeyPubKeySize()); RestrictedData private_key_bytes = RestrictedData( std::string(reinterpret_cast((*x25519_key)->private_key), internal::X25519KeyPrivKeySize()), InsecureSecretKeyAccess::Get()); util::StatusOr public_key = EciesPublicKey::CreateForCurveX25519(*params, public_key_bytes, /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = EciesPrivateKey::CreateForCurveX25519(*public_key, private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); EXPECT_TRUE(*private_key != *public_key); EXPECT_TRUE(*public_key != *private_key); EXPECT_FALSE(*private_key == *public_key); EXPECT_FALSE(*public_key == *private_key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/ecies_proto_serialization.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/ecies_proto_serialization.h" #include #include "absl/base/attributes.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/big_integer.h" #include "tink/ec_point.h" #include "tink/hybrid/ecies_parameters.h" #include "tink/hybrid/ecies_private_key.h" #include "tink/hybrid/ecies_public_key.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/bn_encoding_util.h" #include "tink/internal/key_parser.h" #include "tink/internal/key_serializer.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/parameters_parser.h" #include "tink/internal/parameters_serializer.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/partial_key_access.h" #include "tink/restricted_big_integer.h" #include "tink/restricted_data.h" #include "tink/secret_key_access_token.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/aes_ctr.pb.h" #include "proto/aes_ctr_hmac_aead.pb.h" #include "proto/aes_gcm.pb.h" #include "proto/aes_siv.pb.h" #include "proto/common.pb.h" #include "proto/ecies_aead_hkdf.pb.h" #include "proto/hmac.pb.h" #include "proto/tink.pb.h" #include "proto/xchacha20_poly1305.pb.h" namespace crypto { namespace tink { namespace { using ::google::crypto::tink::AesCtrHmacAeadKeyFormat; using ::google::crypto::tink::AesCtrKeyFormat; using ::google::crypto::tink::AesGcmKeyFormat; using ::google::crypto::tink::AesSivKeyFormat; using ::google::crypto::tink::EciesAeadDemParams; using ::google::crypto::tink::EciesAeadHkdfKeyFormat; using ::google::crypto::tink::EciesAeadHkdfParams; using ::google::crypto::tink::EciesAeadHkdfPrivateKey; using ::google::crypto::tink::EciesAeadHkdfPublicKey; using ::google::crypto::tink::EciesHkdfKemParams; using ::google::crypto::tink::EcPointFormat; using ::google::crypto::tink::EllipticCurveType; using ::google::crypto::tink::HashType; using ::google::crypto::tink::HmacKeyFormat; using ::google::crypto::tink::HmacParams; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::OutputPrefixType; using ::google::crypto::tink::XChaCha20Poly1305KeyFormat; using EciesProtoParametersParserImpl = internal::ParametersParserImpl; using EciesProtoParametersSerializerImpl = internal::ParametersSerializerImpl; using EciesProtoPublicKeyParserImpl = internal::KeyParserImpl; using EciesProtoPublicKeySerializerImpl = internal::KeySerializerImpl; using EciesProtoPrivateKeyParserImpl = internal::KeyParserImpl; using EciesProtoPrivateKeySerializerImpl = internal::KeySerializerImpl; const absl::string_view kPublicTypeUrl = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPublicKey"; const absl::string_view kPrivateTypeUrl = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey"; util::StatusOr ToVariant( OutputPrefixType output_prefix_type) { switch (output_prefix_type) { case OutputPrefixType::LEGACY: ABSL_FALLTHROUGH_INTENDED; // Parse LEGACY output prefix as CRUNCHY. case OutputPrefixType::CRUNCHY: return EciesParameters::Variant::kCrunchy; case OutputPrefixType::RAW: return EciesParameters::Variant::kNoPrefix; case OutputPrefixType::TINK: return EciesParameters::Variant::kTink; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine EciesParameters::Variant"); } } util::StatusOr ToOutputPrefixType( EciesParameters::Variant variant) { switch (variant) { case EciesParameters::Variant::kCrunchy: return OutputPrefixType::CRUNCHY; case EciesParameters::Variant::kNoPrefix: return OutputPrefixType::RAW; case EciesParameters::Variant::kTink: return OutputPrefixType::TINK; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine output prefix type."); } } bool IsNistCurve(EciesParameters::CurveType curve) { return curve == EciesParameters::CurveType::kNistP256 || curve == EciesParameters::CurveType::kNistP384 || curve == EciesParameters::CurveType::kNistP521; } util::StatusOr FromProtoCurveType( EllipticCurveType curve) { switch (curve) { case EllipticCurveType::NIST_P256: return EciesParameters::CurveType::kNistP256; case EllipticCurveType::NIST_P384: return EciesParameters::CurveType::kNistP384; case EllipticCurveType::NIST_P521: return EciesParameters::CurveType::kNistP521; case EllipticCurveType::CURVE25519: return EciesParameters::CurveType::kX25519; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine EciesParameters::CurveType."); } } util::StatusOr ToProtoCurveType( EciesParameters::CurveType curve) { switch (curve) { case EciesParameters::CurveType::kNistP256: return EllipticCurveType::NIST_P256; case EciesParameters::CurveType::kNistP384: return EllipticCurveType::NIST_P384; case EciesParameters::CurveType::kNistP521: return EllipticCurveType::NIST_P521; case EciesParameters::CurveType::kX25519: return EllipticCurveType::CURVE25519; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine curve type."); } } util::StatusOr FromProtoHashType(HashType hash) { switch (hash) { case HashType::SHA1: return EciesParameters::HashType::kSha1; case HashType::SHA224: return EciesParameters::HashType::kSha224; case HashType::SHA256: return EciesParameters::HashType::kSha256; case HashType::SHA384: return EciesParameters::HashType::kSha384; case HashType::SHA512: return EciesParameters::HashType::kSha512; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine EciesParameters::HashType."); } } util::StatusOr ToProtoHashType(EciesParameters::HashType hash) { switch (hash) { case EciesParameters::HashType::kSha1: return HashType::SHA1; case EciesParameters::HashType::kSha224: return HashType::SHA224; case EciesParameters::HashType::kSha256: return HashType::SHA256; case EciesParameters::HashType::kSha384: return HashType::SHA384; case EciesParameters::HashType::kSha512: return HashType::SHA512; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine hash type."); } } util::StatusOr FromProtoPointFormat( EcPointFormat format) { switch (format) { case EcPointFormat::COMPRESSED: return EciesParameters::PointFormat::kCompressed; case EcPointFormat::UNCOMPRESSED: return EciesParameters::PointFormat::kUncompressed; case EcPointFormat::DO_NOT_USE_CRUNCHY_UNCOMPRESSED: return EciesParameters::PointFormat::kLegacyUncompressed; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine EciesParameters::PointFormat."); } } util::StatusOr ToProtoPointFormat( EciesParameters::PointFormat format) { switch (format) { case EciesParameters::PointFormat::kCompressed: return EcPointFormat::COMPRESSED; case EciesParameters::PointFormat::kUncompressed: return EcPointFormat::UNCOMPRESSED; case EciesParameters::PointFormat::kLegacyUncompressed: return EcPointFormat::DO_NOT_USE_CRUNCHY_UNCOMPRESSED; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine point format."); } } absl::Status ValidateAesCtrHmacAeadKeyFormat( const AesCtrHmacAeadKeyFormat& format) { if (!format.has_aes_ctr_key_format()) { return util::Status(absl::StatusCode::kInvalidArgument, "Missing aes_ctr_key_format."); } if (!format.aes_ctr_key_format().has_params()) { return util::Status(absl::StatusCode::kInvalidArgument, "Missing aes_ctr_key_format.params."); } if (format.aes_ctr_key_format().params().iv_size() != 16) { return util::Status(absl::StatusCode::kInvalidArgument, "IV size must by 16 bytes."); } if (!format.has_hmac_key_format()) { return util::Status(absl::StatusCode::kInvalidArgument, "Missing hmac_key_format."); } if (format.hmac_key_format().version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "HMAC key format version must be 0."); } if (format.hmac_key_format().key_size() != 32) { return util::Status(absl::StatusCode::kInvalidArgument, "HMAC key size must be 32 bytes."); } if (!format.hmac_key_format().has_params()) { return util::Status(absl::StatusCode::kInvalidArgument, "Missing hmac_key_format.params."); } if (format.hmac_key_format().params().hash() != HashType::SHA256) { return util::Status(absl::StatusCode::kInvalidArgument, "Hash type must be SHA256."); } if (format.aes_ctr_key_format().key_size() != format.hmac_key_format().params().tag_size()) { return util::Status( absl::StatusCode::kInvalidArgument, "Allowed AES-CTR-HMAC DEMs must have matching key and tag sizes."); } return util::OkStatus(); } util::StatusOr FromProtoDemParams( EciesAeadDemParams proto_dem_params) { if (!proto_dem_params.has_aead_dem()) { return util::Status(absl::StatusCode::kInvalidArgument, "Missing EciesAeadDemParams.aead_dem field."); } if (proto_dem_params.aead_dem().type_url() == "type.googleapis.com/google.crypto.tink.AesGcmKey") { AesGcmKeyFormat aes_gcm_key_format; if (!aes_gcm_key_format.ParseFromString( proto_dem_params.aead_dem().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse AES-GCM key format."); } if (aes_gcm_key_format.key_size() == 16) { return EciesParameters::DemId::kAes128GcmRaw; } if (aes_gcm_key_format.key_size() == 32) { return EciesParameters::DemId::kAes256GcmRaw; } return util::Status(absl::StatusCode::kInvalidArgument, "Invalid AES-GCM key length for DEM."); } if (proto_dem_params.aead_dem().type_url() == "type.googleapis.com/google.crypto.tink.AesSivKey") { AesSivKeyFormat aes_siv_key_format; if (!aes_siv_key_format.ParseFromString( proto_dem_params.aead_dem().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse AES-SIV key format."); } if (aes_siv_key_format.key_size() == 64) { return EciesParameters::DemId::kAes256SivRaw; } return util::Status(absl::StatusCode::kInvalidArgument, "Invalid AES-SIV key length for DEM."); } if (proto_dem_params.aead_dem().type_url() == "type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key" || // TODO: b/330508549 - Remove type URL exception for an existing key. proto_dem_params.aead_dem().type_url() == "type.googleapis.com/google.crypto.tink.XChaCha20Poly1305KeyFormat") { XChaCha20Poly1305KeyFormat xchacha20_poly1305_key_format; if (!xchacha20_poly1305_key_format.ParseFromString( proto_dem_params.aead_dem().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse XChaCha20-Poly1305 key format."); } return EciesParameters::DemId::kXChaCha20Poly1305Raw; } if (proto_dem_params.aead_dem().type_url() == "type.googleapis.com/google.crypto.tink.AesCtrHmacAeadKey") { AesCtrHmacAeadKeyFormat aes_ctr_hmac_aead_key_format; if (!aes_ctr_hmac_aead_key_format.ParseFromString( proto_dem_params.aead_dem().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse AES-CTR-HMAC key format."); } util::Status format_validation = ValidateAesCtrHmacAeadKeyFormat(aes_ctr_hmac_aead_key_format); if (!format_validation.ok()) { return format_validation; } if (aes_ctr_hmac_aead_key_format.aes_ctr_key_format().key_size() == 16) { return EciesParameters::DemId::kAes128CtrHmacSha256Raw; } if (aes_ctr_hmac_aead_key_format.aes_ctr_key_format().key_size() == 32) { return EciesParameters::DemId::kAes256CtrHmacSha256Raw; } return util::Status(absl::StatusCode::kInvalidArgument, "Invalid AES-CTR-HMAC key length for DEM."); } return util::Status(absl::StatusCode::kInvalidArgument, "Unable to convert proto DEM params to DEM id."); } EciesAeadDemParams CreateEciesAeadDemParams( absl::string_view type_url, const std::string& serialized_key_format) { EciesAeadDemParams dem_params; KeyTemplate key_template; key_template.set_type_url(type_url); key_template.set_output_prefix_type(OutputPrefixType::TINK); *key_template.mutable_value() = serialized_key_format; *dem_params.mutable_aead_dem() = key_template; return dem_params; } util::StatusOr ToProtoDemParams( EciesParameters::DemId dem_id) { if (dem_id == EciesParameters::DemId::kAes128GcmRaw || dem_id == EciesParameters::DemId::kAes256GcmRaw) { int key_size = (dem_id == EciesParameters::DemId::kAes128GcmRaw) ? 16 : 32; AesGcmKeyFormat format; format.set_version(0); format.set_key_size(key_size); return CreateEciesAeadDemParams( "type.googleapis.com/google.crypto.tink.AesGcmKey", format.SerializeAsString()); } if (dem_id == EciesParameters::DemId::kAes256SivRaw) { AesSivKeyFormat format; format.set_version(0); format.set_key_size(64); return CreateEciesAeadDemParams( "type.googleapis.com/google.crypto.tink.AesSivKey", format.SerializeAsString()); } if (dem_id == EciesParameters::DemId::kXChaCha20Poly1305Raw) { XChaCha20Poly1305KeyFormat format; format.set_version(0); return CreateEciesAeadDemParams( "type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key", format.SerializeAsString()); } if (dem_id == EciesParameters::DemId::kAes128CtrHmacSha256Raw || dem_id == EciesParameters::DemId::kAes256CtrHmacSha256Raw) { int key_size = (dem_id == EciesParameters::DemId::kAes128CtrHmacSha256Raw) ? 16 : 32; int tag_size = key_size; // Allowed DEMs have matching key/tag sizes. AesCtrHmacAeadKeyFormat format; AesCtrKeyFormat* aes_ctr_key_format = format.mutable_aes_ctr_key_format(); aes_ctr_key_format->set_key_size(key_size); aes_ctr_key_format->mutable_params()->set_iv_size(16); HmacKeyFormat* hmac_key_format = format.mutable_hmac_key_format(); hmac_key_format->set_version(0); hmac_key_format->set_key_size(32); HmacParams* hmac_params = hmac_key_format->mutable_params(); hmac_params->set_tag_size(tag_size); hmac_params->set_hash(HashType::SHA256); return CreateEciesAeadDemParams( "type.googleapis.com/google.crypto.tink.AesCtrHmacAeadKey", format.SerializeAsString()); } return util::Status(absl::StatusCode::kInvalidArgument, "Unable to convert DEM id to proto DEM params."); } util::StatusOr ToParameters( OutputPrefixType output_prefix_type, EciesAeadHkdfParams params) { if (!params.has_kem_params()) { return util::Status(absl::StatusCode::kInvalidArgument, "Missing EciesAeadHkdfParams.kem_params field."); } if (!params.has_dem_params()) { return util::Status(absl::StatusCode::kInvalidArgument, "Missing EciesAeadHkdfParams.dem_params field."); } util::StatusOr variant = ToVariant(output_prefix_type); if (!variant.ok()) { return variant.status(); } util::StatusOr curve_type = FromProtoCurveType(params.kem_params().curve_type()); if (!curve_type.ok()) { return curve_type.status(); } util::StatusOr hash_type = FromProtoHashType(params.kem_params().hkdf_hash_type()); if (!hash_type.ok()) { return hash_type.status(); } util::StatusOr dem_id = FromProtoDemParams(params.dem_params()); if (!dem_id.ok()) { return dem_id.status(); } EciesParameters::Builder builder = EciesParameters::Builder() .SetVariant(*variant) .SetCurveType(*curve_type) .SetHashType(*hash_type) .SetDemId(*dem_id); if (IsNistCurve(*curve_type)) { util::StatusOr point_format = FromProtoPointFormat(params.ec_point_format()); if (!point_format.ok()) { return point_format.status(); } builder.SetNistCurvePointFormat(*point_format); } if (!params.kem_params().hkdf_salt().empty()) { builder.SetSalt(params.kem_params().hkdf_salt()); } return builder.Build(); } util::StatusOr FromParameters( const EciesParameters& parameters) { util::StatusOr curve_type = ToProtoCurveType(parameters.GetCurveType()); if (!curve_type.ok()) { return curve_type.status(); } util::StatusOr hash_type = ToProtoHashType(parameters.GetHashType()); if (!hash_type.ok()) { return hash_type.status(); } util::StatusOr dem_params = ToProtoDemParams(parameters.GetDemId()); if (!dem_params.ok()) { return dem_params.status(); } EciesAeadHkdfParams params; *params.mutable_dem_params() = *dem_params; EciesHkdfKemParams* kem_params = params.mutable_kem_params(); kem_params->set_curve_type(*curve_type); kem_params->set_hkdf_hash_type(*hash_type); if (parameters.GetSalt().has_value()) { kem_params->set_hkdf_salt(*parameters.GetSalt()); } if (parameters.GetNistCurvePointFormat().has_value()) { util::StatusOr ec_point_format = ToProtoPointFormat(*parameters.GetNistCurvePointFormat()); if (!ec_point_format.ok()) { return ec_point_format.status(); } params.set_ec_point_format(*ec_point_format); } else { // Must be X25519, so set to the compressed format. params.set_ec_point_format(EcPointFormat::COMPRESSED); } return params; } util::StatusOr ToPublicKey( const EciesParameters& parameters, const EciesAeadHkdfPublicKey& proto_key, absl::optional id_requirement) { if (IsNistCurve(parameters.GetCurveType())) { EcPoint point(BigInteger(proto_key.x()), BigInteger(proto_key.y())); return EciesPublicKey::CreateForNistCurve(parameters, point, id_requirement, GetPartialKeyAccess()); } return EciesPublicKey::CreateForCurveX25519( parameters, proto_key.x(), id_requirement, GetPartialKeyAccess()); } util::StatusOr GetEncodingLength(EciesParameters::CurveType curve) { // Encode EC field elements with extra leading zero byte for compatibility // with Java BigInteger decoding (b/264525021). switch (curve) { case EciesParameters::CurveType::kNistP256: return 33; case EciesParameters::CurveType::kNistP384: return 49; case EciesParameters::CurveType::kNistP521: return 67; default: return util::Status(absl::StatusCode::kInvalidArgument, "Cannot determine encoding length for curve."); } } util::StatusOr FromPublicKey( const EciesAeadHkdfParams& params, const EciesPublicKey& public_key) { EciesAeadHkdfPublicKey proto_key; proto_key.set_version(0); *proto_key.mutable_params() = params; if (public_key.GetNistCurvePoint(GetPartialKeyAccess()).has_value()) { EcPoint point = *public_key.GetNistCurvePoint(GetPartialKeyAccess()); util::StatusOr encoding_length = GetEncodingLength(public_key.GetParameters().GetCurveType()); if (!encoding_length.ok()) { return encoding_length.status(); } util::StatusOr x = internal::GetValueOfFixedLength( point.GetX().GetValue(), *encoding_length); if (!x.ok()) { return x.status(); } util::StatusOr y = internal::GetValueOfFixedLength( point.GetY().GetValue(), *encoding_length); if (!y.ok()) { return y.status(); } proto_key.set_x(*x); proto_key.set_y(*y); } else { if (!public_key.GetX25519CurvePointBytes(GetPartialKeyAccess()) .has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "X25519 public key missing point bytes."); } proto_key.set_x( *public_key.GetX25519CurvePointBytes(GetPartialKeyAccess())); proto_key.set_y(""); } return proto_key; } util::StatusOr ParseParameters( const internal::ProtoParametersSerialization& serialization) { if (serialization.GetKeyTemplate().type_url() != kPrivateTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing EciesParameters."); } EciesAeadHkdfKeyFormat proto_key_format; if (!proto_key_format.ParseFromString( serialization.GetKeyTemplate().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse EciesAeadHkdfKeyFormat proto."); } if (!proto_key_format.has_params()) { return util::Status( absl::StatusCode::kInvalidArgument, "EciesAeadHkdfKeyFormat proto is missing params field."); } return ToParameters(serialization.GetKeyTemplate().output_prefix_type(), proto_key_format.params()); } util::StatusOr ParsePublicKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (serialization.TypeUrl() != kPublicTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing EciesAeadHkdfPublicKey."); } EciesAeadHkdfPublicKey proto_key; const RestrictedData& restricted_data = serialization.SerializedKeyProto(); if (!proto_key.ParseFromString( restricted_data.GetSecret(InsecureSecretKeyAccess::Get()))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse EciesAeadHkdfPublicKey proto"); } if (proto_key.version() != 0) { return util::Status( absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted for EciesAeadHkdfPublicKey proto."); } util::StatusOr parameters = ToParameters(serialization.GetOutputPrefixType(), proto_key.params()); if (!parameters.ok()) { return parameters.status(); } return ToPublicKey(*parameters, proto_key, serialization.IdRequirement()); } util::StatusOr ParsePrivateKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (!token.has_value()) { return util::Status(absl::StatusCode::kPermissionDenied, "SecretKeyAccess is required"); } if (serialization.TypeUrl() != kPrivateTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing EciesAeadHkdfPrivateKey."); } EciesAeadHkdfPrivateKey proto_key; const RestrictedData& restricted_data = serialization.SerializedKeyProto(); if (!proto_key.ParseFromString(restricted_data.GetSecret(*token))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse EciesAeadHkdfPrivateKey proto."); } if (proto_key.version() != 0) { return util::Status( absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted for EciesAeadHkdfPrivateKey proto."); } util::StatusOr variant = ToVariant(serialization.GetOutputPrefixType()); if (!variant.ok()) { return variant.status(); } util::StatusOr parameters = ToParameters( serialization.GetOutputPrefixType(), proto_key.public_key().params()); if (!parameters.ok()) { return parameters.status(); } util::StatusOr public_key = ToPublicKey( *parameters, proto_key.public_key(), serialization.IdRequirement()); if (!public_key.ok()) { return public_key.status(); } if (IsNistCurve(parameters->GetCurveType())) { return EciesPrivateKey::CreateForNistCurve( *public_key, RestrictedBigInteger(proto_key.key_value(), *token), GetPartialKeyAccess()); } return EciesPrivateKey::CreateForCurveX25519( *public_key, RestrictedData(proto_key.key_value(), *token), GetPartialKeyAccess()); } util::StatusOr SerializeParameters( const EciesParameters& parameters) { util::StatusOr output_prefix_type = ToOutputPrefixType(parameters.GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } util::StatusOr params = FromParameters(parameters); if (!params.ok()) { return params.status(); } EciesAeadHkdfKeyFormat proto_key_format; *proto_key_format.mutable_params() = *params; return internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, *output_prefix_type, proto_key_format.SerializeAsString()); } util::StatusOr SerializePublicKey( const EciesPublicKey& key, absl::optional token) { util::StatusOr params = FromParameters(key.GetParameters()); if (!params.ok()) { return params.status(); } util::StatusOr proto_key = FromPublicKey(*params, key); if (!proto_key.ok()) { return proto_key.status(); } util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetParameters().GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } RestrictedData restricted_output = RestrictedData( proto_key->SerializeAsString(), InsecureSecretKeyAccess::Get()); return internal::ProtoKeySerialization::Create( kPublicTypeUrl, restricted_output, KeyData::ASYMMETRIC_PUBLIC, *output_prefix_type, key.GetIdRequirement()); } util::StatusOr SerializePrivateKey( const EciesPrivateKey& key, absl::optional token) { if (!token.has_value()) { return util::Status(absl::StatusCode::kPermissionDenied, "SecretKeyAccess is required"); } util::StatusOr params = FromParameters(key.GetPublicKey().GetParameters()); if (!params.ok()) { return params.status(); } util::StatusOr proto_public_key = FromPublicKey(*params, key.GetPublicKey()); if (!proto_public_key.ok()) { return proto_public_key.status(); } EciesAeadHkdfPrivateKey proto_private_key; proto_private_key.set_version(0); *proto_private_key.mutable_public_key() = *proto_public_key; if (IsNistCurve(key.GetPublicKey().GetParameters().GetCurveType())) { util::StatusOr encoding_length = GetEncodingLength(key.GetPublicKey().GetParameters().GetCurveType()); if (!encoding_length.ok()) { return encoding_length.status(); } absl::optional secret = key.GetNistPrivateKeyValue(GetPartialKeyAccess()); if (!secret.has_value()) { return util::Status( absl::StatusCode::kInternal, "NIST private key is missing NIST private key value."); } util::StatusOr key_value = internal::GetValueOfFixedLength( secret->GetSecret(InsecureSecretKeyAccess::Get()), *encoding_length); if (!key_value.ok()) { return key_value.status(); } proto_private_key.set_key_value(*key_value); } else { absl::optional secret = key.GetX25519PrivateKeyBytes(GetPartialKeyAccess()); if (!secret.has_value()) { return util::Status( absl::StatusCode::kInternal, "X25519 private key is missing X25519 private key bytes."); } proto_private_key.set_key_value( secret->GetSecret(InsecureSecretKeyAccess::Get())); } util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetPublicKey().GetParameters().GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } RestrictedData restricted_output = RestrictedData(proto_private_key.SerializeAsString(), *token); return internal::ProtoKeySerialization::Create( kPrivateTypeUrl, restricted_output, KeyData::ASYMMETRIC_PRIVATE, *output_prefix_type, key.GetIdRequirement()); } EciesProtoParametersParserImpl* EciesProtoParametersParser() { static auto* parser = new EciesProtoParametersParserImpl(kPrivateTypeUrl, ParseParameters); return parser; } EciesProtoParametersSerializerImpl* EciesProtoParametersSerializer() { static auto* serializer = new EciesProtoParametersSerializerImpl( kPrivateTypeUrl, SerializeParameters); return serializer; } EciesProtoPublicKeyParserImpl* EciesProtoPublicKeyParser() { static auto* parser = new EciesProtoPublicKeyParserImpl(kPublicTypeUrl, ParsePublicKey); return parser; } EciesProtoPublicKeySerializerImpl* EciesProtoPublicKeySerializer() { static auto* serializer = new EciesProtoPublicKeySerializerImpl(SerializePublicKey); return serializer; } EciesProtoPrivateKeyParserImpl* EciesProtoPrivateKeyParser() { static auto* parser = new EciesProtoPrivateKeyParserImpl(kPrivateTypeUrl, ParsePrivateKey); return parser; } EciesProtoPrivateKeySerializerImpl* EciesProtoPrivateKeySerializer() { static auto* serializer = new EciesProtoPrivateKeySerializerImpl(SerializePrivateKey); return serializer; } } // namespace util::Status RegisterEciesProtoSerialization() { util::Status status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersParser(EciesProtoParametersParser()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersSerializer(EciesProtoParametersSerializer()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(EciesProtoPublicKeyParser()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(EciesProtoPublicKeySerializer()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(EciesProtoPrivateKeyParser()); if (!status.ok()) { return status; } return internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(EciesProtoPrivateKeySerializer()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/ecies_proto_serialization.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_ECIES_PROTO_SERIALIZATION_H_ #define TINK_HYBRID_ECIES_PROTO_SERIALIZATION_H_ #include "tink/util/status.h" namespace crypto { namespace tink { // Registers proto parsers and serializers for ECIES parameters and keys. crypto::tink::util::Status RegisterEciesProtoSerialization(); } // namespace tink } // namespace crypto #endif // TINK_HYBRID_ECIES_PROTO_SERIALIZATION_H_ ================================================ FILE: cc/hybrid/ecies_proto_serialization_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/ecies_proto_serialization.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/big_integer.h" #include "tink/ec_point.h" #include "tink/hybrid/ecies_parameters.h" #include "tink/hybrid/ecies_private_key.h" #include "tink/hybrid/ecies_public_key.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/ec_util.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_big_integer.h" #include "tink/restricted_data.h" #include "tink/subtle/common_enums.h" #include "tink/util/enums.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/aes_ctr.pb.h" #include "proto/aes_ctr_hmac_aead.pb.h" #include "proto/aes_gcm.pb.h" #include "proto/aes_siv.pb.h" #include "proto/common.pb.h" #include "proto/ecies_aead_hkdf.pb.h" #include "proto/hmac.pb.h" #include "proto/tink.pb.h" #include "proto/xchacha20_poly1305.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::AesCtrHmacAeadKeyFormat; using ::google::crypto::tink::AesGcmKeyFormat; using ::google::crypto::tink::AesSivKeyFormat; using ::google::crypto::tink::EciesAeadDemParams; using ::google::crypto::tink::EciesAeadHkdfKeyFormat; using ::google::crypto::tink::EciesAeadHkdfParams; using ::google::crypto::tink::EciesAeadHkdfPrivateKey; using ::google::crypto::tink::EciesAeadHkdfPublicKey; using ::google::crypto::tink::EciesHkdfKemParams; using ::google::crypto::tink::EcPointFormat; using ::google::crypto::tink::EllipticCurveType; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::OutputPrefixType; using ::google::crypto::tink::XChaCha20Poly1305KeyFormat; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::IsTrue; using ::testing::NotNull; using ::testing::TestWithParam; using ::testing::Values; const absl::string_view kPublicTypeUrl = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPublicKey"; const absl::string_view kPrivateTypeUrl = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey"; constexpr absl::string_view kSalt = "2024ab"; struct TestCase { EciesParameters::Variant variant; EciesParameters::CurveType curve_type; EciesParameters::HashType hash_type; EciesParameters::DemId dem_id; absl::optional point_format; absl::optional salt; OutputPrefixType output_prefix_type; EciesHkdfKemParams kem_params; EciesAeadDemParams dem_params; EcPointFormat ec_point_format; absl::optional id; std::string output_prefix; }; class EciesProtoSerializationTest : public TestWithParam { protected: EciesProtoSerializationTest() { internal::MutableSerializationRegistry::GlobalInstance().Reset(); } }; TEST_F(EciesProtoSerializationTest, RegisterTwiceSucceeds) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); } EciesHkdfKemParams CreateKemParams(EllipticCurveType curve_type, HashType hash_type, absl::string_view salt) { EciesHkdfKemParams kem_params; kem_params.set_curve_type(curve_type); kem_params.set_hkdf_hash_type(hash_type); kem_params.set_hkdf_salt(salt); return kem_params; } EciesAeadDemParams CreateAesGcmDemParams(int key_size_in_bytes) { AesGcmKeyFormat format; format.set_key_size(key_size_in_bytes); format.set_version(0); KeyTemplate key_template; key_template.set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey"); key_template.set_output_prefix_type(OutputPrefixType::TINK); format.SerializeToString(key_template.mutable_value()); EciesAeadDemParams dem_params; *dem_params.mutable_aead_dem() = key_template; return dem_params; } EciesAeadDemParams CreateAes256SivDemParams() { AesSivKeyFormat format; format.set_key_size(64); format.set_version(0); KeyTemplate key_template; key_template.set_type_url("type.googleapis.com/google.crypto.tink.AesSivKey"); key_template.set_output_prefix_type(OutputPrefixType::TINK); format.SerializeToString(key_template.mutable_value()); EciesAeadDemParams dem_params; *dem_params.mutable_aead_dem() = key_template; return dem_params; } EciesAeadDemParams CreateXChaCha20Poly1305DemParams() { XChaCha20Poly1305KeyFormat format; format.set_version(0); KeyTemplate key_template; key_template.set_type_url( "type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key"); key_template.set_output_prefix_type(OutputPrefixType::TINK); format.SerializeToString(key_template.mutable_value()); EciesAeadDemParams dem_params; *dem_params.mutable_aead_dem() = key_template; return dem_params; } EciesAeadDemParams CreateAesCtrHmacDemParams( absl::optional aes_key_size, absl::optional iv_size, absl::optional version, absl::optional hmac_key_size, absl::optional tag_size, absl::optional hash_type) { AesCtrHmacAeadKeyFormat format; if (aes_key_size.has_value()) { format.mutable_aes_ctr_key_format()->set_key_size(aes_key_size.value()); } if (iv_size.has_value()) { format.mutable_aes_ctr_key_format()->mutable_params()->set_iv_size( iv_size.value()); } if (version.has_value()) { format.mutable_hmac_key_format()->set_version(version.value()); } if (hmac_key_size.has_value()) { format.mutable_hmac_key_format()->set_key_size(hmac_key_size.value()); } if (tag_size.has_value()) { format.mutable_hmac_key_format()->mutable_params()->set_tag_size( tag_size.value()); } if (hash_type.has_value()) { format.mutable_hmac_key_format()->mutable_params()->set_hash( hash_type.value()); } KeyTemplate key_template; key_template.set_type_url( "type.googleapis.com/google.crypto.tink.AesCtrHmacAeadKey"); key_template.set_output_prefix_type(OutputPrefixType::TINK); format.SerializeToString(key_template.mutable_value()); EciesAeadDemParams dem_params; *dem_params.mutable_aead_dem() = key_template; return dem_params; } EciesAeadDemParams CreateAesCtrHmacDemParams(int key_size) { // Key and tag sizes match for allowed AES-CTR-HMAC DEMs. return CreateAesCtrHmacDemParams(/*aes_key_size=*/key_size, /*iv_size=*/16, /*version=*/0, /*hmac_key_size=*/32, /*tag_size=*/key_size, /*hash_type=*/HashType::SHA256); } INSTANTIATE_TEST_SUITE_P( EciesProtoSerializationTestSuite, EciesProtoSerializationTest, Values(TestCase{EciesParameters::Variant::kTink, EciesParameters::CurveType::kNistP256, EciesParameters::HashType::kSha256, EciesParameters::DemId::kAes128GcmRaw, EciesParameters::PointFormat::kCompressed, kSalt.data(), OutputPrefixType::TINK, CreateKemParams(EllipticCurveType::NIST_P256, HashType::SHA256, kSalt), CreateAesGcmDemParams(16), EcPointFormat::COMPRESSED, /*id=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{EciesParameters::Variant::kCrunchy, EciesParameters::CurveType::kNistP384, EciesParameters::HashType::kSha384, EciesParameters::DemId::kAes256GcmRaw, EciesParameters::PointFormat::kLegacyUncompressed, /*salt=*/absl::nullopt, OutputPrefixType::CRUNCHY, CreateKemParams(EllipticCurveType::NIST_P384, HashType::SHA384, /*salt=*/""), CreateAesGcmDemParams(32), EcPointFormat::DO_NOT_USE_CRUNCHY_UNCOMPRESSED, /*id=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{EciesParameters::Variant::kTink, EciesParameters::CurveType::kNistP521, EciesParameters::HashType::kSha512, EciesParameters::DemId::kAes256SivRaw, EciesParameters::PointFormat::kUncompressed, /*salt=*/absl::nullopt, OutputPrefixType::TINK, CreateKemParams(EllipticCurveType::NIST_P521, HashType::SHA512, /*salt=*/""), CreateAes256SivDemParams(), EcPointFormat::UNCOMPRESSED, /*id=*/0x07080910, /*output_prefix=*/std::string("\x00\x07\x08\x09\x10", 5)}, TestCase{EciesParameters::Variant::kNoPrefix, EciesParameters::CurveType::kX25519, EciesParameters::HashType::kSha256, EciesParameters::DemId::kXChaCha20Poly1305Raw, /*point_format=*/absl::nullopt, /*salt=*/kSalt.data(), OutputPrefixType::RAW, CreateKemParams(EllipticCurveType::CURVE25519, HashType::SHA256, /*salt=*/kSalt), CreateXChaCha20Poly1305DemParams(), EcPointFormat::COMPRESSED, /*id=*/absl::nullopt, /*output_prefix=*/""}, TestCase{EciesParameters::Variant::kNoPrefix, EciesParameters::CurveType::kX25519, EciesParameters::HashType::kSha256, EciesParameters::DemId::kAes128CtrHmacSha256Raw, /*point_format=*/absl::nullopt, /*salt=*/kSalt.data(), OutputPrefixType::RAW, CreateKemParams(EllipticCurveType::CURVE25519, HashType::SHA256, /*salt=*/kSalt), CreateAesCtrHmacDemParams(16), EcPointFormat::COMPRESSED, /*id=*/absl::nullopt, /*output_prefix=*/""}, TestCase{EciesParameters::Variant::kNoPrefix, EciesParameters::CurveType::kX25519, EciesParameters::HashType::kSha256, EciesParameters::DemId::kAes256CtrHmacSha256Raw, /*point_format=*/absl::nullopt, /*salt=*/kSalt.data(), OutputPrefixType::RAW, CreateKemParams(EllipticCurveType::CURVE25519, HashType::SHA256, /*salt=*/kSalt), CreateAesCtrHmacDemParams(32), EcPointFormat::COMPRESSED, /*id=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(EciesProtoSerializationTest, ParseParametersSucceeds) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = test_case.kem_params; *params.mutable_dem_params() = test_case.dem_params; params.set_ec_point_format(test_case.ec_point_format); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, test_case.output_prefix_type, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT((*parameters)->HasIdRequirement(), test_case.id.has_value()); const EciesParameters* ecies_parameters = dynamic_cast(parameters->get()); ASSERT_THAT(ecies_parameters, NotNull()); EXPECT_THAT(ecies_parameters->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(ecies_parameters->GetCurveType(), Eq(test_case.curve_type)); EXPECT_THAT(ecies_parameters->GetHashType(), Eq(test_case.hash_type)); EXPECT_THAT(ecies_parameters->GetDemId(), Eq(test_case.dem_id)); EXPECT_THAT(ecies_parameters->GetNistCurvePointFormat(), Eq(test_case.point_format)); EXPECT_THAT(ecies_parameters->GetSalt(), Eq(test_case.salt)); } TEST_F(EciesProtoSerializationTest, ParseLegacyAsCrunchySucceeds) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = CreateKemParams(EllipticCurveType::NIST_P256, HashType::SHA256, kSalt); *params.mutable_dem_params() = CreateAesGcmDemParams(16); params.set_ec_point_format(EcPointFormat::COMPRESSED); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::LEGACY, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(parameters, IsOk()); const EciesParameters* ecies_parameters = dynamic_cast(parameters->get()); ASSERT_THAT(ecies_parameters, NotNull()); EXPECT_THAT(ecies_parameters->GetVariant(), Eq(EciesParameters::Variant::kCrunchy)); } TEST_F(EciesProtoSerializationTest, ParseParametersWithInvalidSerializationFails) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::RAW, "invalid_serialization"); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT( params.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Failed to parse EciesAeadHkdfKeyFormat proto"))); } TEST_F(EciesProtoSerializationTest, ParseParametersWithUnkownOutputPrefixFails) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = CreateKemParams(EllipticCurveType::NIST_P256, HashType::SHA256, kSalt); *params.mutable_dem_params() = CreateAesGcmDemParams(16); params.set_ec_point_format(EcPointFormat::COMPRESSED); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::UNKNOWN_PREFIX, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT( parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Could not determine EciesParameters::Variant"))); } TEST_F(EciesProtoSerializationTest, ParseParametersWithMissingKemFails) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_dem_params() = CreateAesGcmDemParams(16); params.set_ec_point_format(EcPointFormat::COMPRESSED); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT( parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Missing EciesAeadHkdfParams.kem_params field"))); } TEST_F(EciesProtoSerializationTest, ParseParametersWithMissingDemFails) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = CreateKemParams(EllipticCurveType::NIST_P256, HashType::SHA256, kSalt); params.set_ec_point_format(EcPointFormat::COMPRESSED); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT( parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Missing EciesAeadHkdfParams.dem_params field"))); } TEST_F(EciesProtoSerializationTest, ParseParametersWithMissingPointFormatFails) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = CreateKemParams(EllipticCurveType::NIST_P256, HashType::SHA256, kSalt); *params.mutable_dem_params() = CreateAesGcmDemParams(16); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT( parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Could not determine EciesParameters::PointFormat"))); } TEST_F(EciesProtoSerializationTest, ParseParametersWithMissingSaltSucceeds) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = CreateKemParams(EllipticCurveType::NIST_P256, HashType::SHA256, kSalt); params.mutable_kem_params()->clear_hkdf_salt(); // Missing salt. *params.mutable_dem_params() = CreateAesGcmDemParams(16); params.set_ec_point_format(EcPointFormat::COMPRESSED); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(parameters, IsOk()); const EciesParameters* ecies_parameters = dynamic_cast(parameters->get()); ASSERT_THAT(ecies_parameters, NotNull()); EXPECT_THAT(ecies_parameters->GetSalt(), Eq(absl::nullopt)); } TEST_F(EciesProtoSerializationTest, ParseParametersWithMissingParamsFails) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfKeyFormat key_format_proto; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT( parameters.status(), StatusIs( absl::StatusCode::kInvalidArgument, HasSubstr("EciesAeadHkdfKeyFormat proto is missing params field"))); } TEST_F(EciesProtoSerializationTest, ParseParametersWithMissingKeyTemplateFails) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = CreateKemParams(EllipticCurveType::NIST_P256, HashType::SHA256, kSalt); *params.mutable_dem_params() = CreateAesGcmDemParams(16); params.mutable_dem_params()->clear_aead_dem(); // Missing key template. params.set_ec_point_format(EcPointFormat::COMPRESSED); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Missing EciesAeadDemParams.aead_dem field"))); } TEST_F(EciesProtoSerializationTest, ParseParametersWithUnkownCurveTypeFails) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = CreateKemParams( EllipticCurveType::UNKNOWN_CURVE, HashType::SHA256, kSalt); *params.mutable_dem_params() = CreateAesGcmDemParams(16); params.set_ec_point_format(EcPointFormat::COMPRESSED); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT( parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Could not determine EciesParameters::CurveType"))); } TEST_F(EciesProtoSerializationTest, ParseParametersWithUnkownHashTypeFails) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = CreateKemParams(EllipticCurveType::NIST_P256, HashType::UNKNOWN_HASH, kSalt); *params.mutable_dem_params() = CreateAesGcmDemParams(16); params.set_ec_point_format(EcPointFormat::COMPRESSED); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT( parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Could not determine EciesParameters::HashType"))); } TEST_F(EciesProtoSerializationTest, ParseParametersWithUnkownPointFormatFails) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = CreateKemParams(EllipticCurveType::NIST_P256, HashType::SHA256, kSalt); *params.mutable_dem_params() = CreateAesGcmDemParams(16); params.set_ec_point_format(EcPointFormat::UNKNOWN_FORMAT); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT( parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Could not determine EciesParameters::PointFormat"))); } TEST_F(EciesProtoSerializationTest, ParseAesCtrHmacParamsWithMissingAesCtrKeyFormat) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = CreateKemParams(EllipticCurveType::NIST_P256, HashType::SHA256, kSalt); *params.mutable_dem_params() = CreateAesCtrHmacDemParams( /*aes_key_size=*/absl::nullopt, /*iv_size=*/absl::nullopt, /*version=*/0, /*hmac_key_size=*/32, /*tag_size=*/16, /*hash_type=*/HashType::SHA256); params.set_ec_point_format(EcPointFormat::COMPRESSED); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Missing aes_ctr_key_format"))); } TEST_F(EciesProtoSerializationTest, ParseAesCtrHmacParamsWithMissingAesCtrParams) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = CreateKemParams(EllipticCurveType::NIST_P256, HashType::SHA256, kSalt); *params.mutable_dem_params() = CreateAesCtrHmacDemParams(/*aes_key_size=*/16, /*iv_size=*/absl::nullopt, /*version=*/0, /*hmac_key_size=*/32, /*tag_size=*/16, /*hash_type=*/HashType::SHA256); params.set_ec_point_format(EcPointFormat::COMPRESSED); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Missing aes_ctr_key_format.params"))); } TEST_F(EciesProtoSerializationTest, ParseAesCtrHmacParamsWithInvalidIv) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = CreateKemParams(EllipticCurveType::NIST_P256, HashType::SHA256, kSalt); *params.mutable_dem_params() = CreateAesCtrHmacDemParams(/*aes_key_size=*/16, /*iv_size=*/14, /*version=*/0, /*hmac_key_size=*/32, /*tag_size=*/16, /*hash_type=*/HashType::SHA256); params.set_ec_point_format(EcPointFormat::COMPRESSED); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("IV size must by 16 bytes"))); } TEST_F(EciesProtoSerializationTest, ParseAesCtrHmacParamsWithMissingHmacKeyFormat) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = CreateKemParams(EllipticCurveType::NIST_P256, HashType::SHA256, kSalt); *params.mutable_dem_params() = CreateAesCtrHmacDemParams( /*aes_key_size=*/16, /*iv_size=*/16, /*version=*/absl::nullopt, /*hmac_key_size=*/absl::nullopt, /*tag_size=*/absl::nullopt, /*hash_type=*/absl::nullopt); params.set_ec_point_format(EcPointFormat::COMPRESSED); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Missing hmac_key_format"))); } TEST_F(EciesProtoSerializationTest, ParseAesCtrHmacParamsWithInvalidHmacKeySize) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = CreateKemParams(EllipticCurveType::NIST_P256, HashType::SHA256, kSalt); *params.mutable_dem_params() = CreateAesCtrHmacDemParams(/*aes_key_size=*/16, /*iv_size=*/16, /*version=*/0, /*hmac_key_size=*/30, /*tag_size=*/16, /*hash_type=*/HashType::SHA256); params.set_ec_point_format(EcPointFormat::COMPRESSED); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("HMAC key size must be 32 bytes"))); } TEST_F(EciesProtoSerializationTest, ParseAesCtrHmacParamsWithMissingHmacParams) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = CreateKemParams(EllipticCurveType::NIST_P256, HashType::SHA256, kSalt); *params.mutable_dem_params() = CreateAesCtrHmacDemParams( /*aes_key_size=*/16, /*iv_size=*/16, /*version=*/0, /*hmac_key_size=*/32, /*tag_size=*/absl::nullopt, /*hash_type=*/absl::nullopt); params.set_ec_point_format(EcPointFormat::COMPRESSED); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Missing hmac_key_format.params"))); } TEST_F(EciesProtoSerializationTest, ParseAesCtrHmacParamsWithInvalidHashType) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = CreateKemParams(EllipticCurveType::NIST_P256, HashType::SHA256, kSalt); *params.mutable_dem_params() = CreateAesCtrHmacDemParams(/*aes_key_size=*/16, /*iv_size=*/16, /*version=*/0, /*hmac_key_size=*/32, /*tag_size=*/16, /*hash_type=*/HashType::SHA1); params.set_ec_point_format(EcPointFormat::COMPRESSED); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Hash type must be SHA256"))); } TEST_F(EciesProtoSerializationTest, ParseAesCtrHmacParamsWithInvalidVersion) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = CreateKemParams(EllipticCurveType::NIST_P256, HashType::SHA256, kSalt); *params.mutable_dem_params() = CreateAesCtrHmacDemParams(/*aes_key_size=*/16, /*iv_size=*/16, /*version=*/1, /*hmac_key_size=*/32, /*tag_size=*/16, /*hash_type=*/HashType::SHA256); params.set_ec_point_format(EcPointFormat::COMPRESSED); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("HMAC key format version must be 0"))); } TEST_F(EciesProtoSerializationTest, ParseAesCtrHmacParamsWithMismatchedSizes) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = CreateKemParams(EllipticCurveType::NIST_P256, HashType::SHA256, kSalt); // AES key size and HMAC tag size should match for allowed AES-CTR-HMAC DEMs. *params.mutable_dem_params() = CreateAesCtrHmacDemParams(/*aes_key_size=*/16, /*iv_size=*/16, /*version=*/0, /*hmac_key_size=*/32, /*tag_size=*/32, /*hash_type=*/HashType::SHA256); params.set_ec_point_format(EcPointFormat::COMPRESSED); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Allowed AES-CTR-HMAC DEMs must have matching " "key and tag sizes"))); } TEST_P(EciesProtoSerializationTest, SerializeParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesParameters::Builder parameters_builder = EciesParameters::Builder() .SetCurveType(test_case.curve_type) .SetHashType(test_case.hash_type) .SetDemId(test_case.dem_id) .SetVariant(test_case.variant); if (test_case.point_format.has_value()) { parameters_builder.SetNistCurvePointFormat(*test_case.point_format); } if (test_case.salt.has_value()) { parameters_builder.SetSalt(*test_case.salt); } util::StatusOr parameters = parameters_builder.Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( *parameters); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kPrivateTypeUrl)); const internal::ProtoParametersSerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->GetKeyTemplate().type_url(), Eq(kPrivateTypeUrl)); EXPECT_THAT(proto_serialization->GetKeyTemplate().output_prefix_type(), Eq(test_case.output_prefix_type)); EciesAeadHkdfKeyFormat key_format; ASSERT_THAT( key_format.ParseFromString(proto_serialization->GetKeyTemplate().value()), IsTrue()); ASSERT_THAT(key_format.has_params(), IsTrue()); ASSERT_THAT(key_format.params().has_kem_params(), IsTrue()); EXPECT_THAT(key_format.params().kem_params().curve_type(), Eq(test_case.kem_params.curve_type())); EXPECT_THAT(key_format.params().kem_params().hkdf_hash_type(), Eq(test_case.kem_params.hkdf_hash_type())); EXPECT_THAT(key_format.params().kem_params().hkdf_salt(), Eq(test_case.kem_params.hkdf_salt())); ASSERT_THAT(key_format.params().has_dem_params(), IsTrue()); ASSERT_THAT(key_format.params().dem_params().has_aead_dem(), IsTrue()); EXPECT_THAT(key_format.params().dem_params().aead_dem().type_url(), Eq(test_case.dem_params.aead_dem().type_url())); EXPECT_THAT(key_format.params().dem_params().aead_dem().output_prefix_type(), Eq(test_case.dem_params.aead_dem().output_prefix_type())); EXPECT_THAT(key_format.params().dem_params().aead_dem().value(), Eq(test_case.dem_params.aead_dem().value())); EXPECT_THAT(key_format.params().ec_point_format(), Eq(test_case.ec_point_format)); } struct KeyPair { // Public key coordinates std::string x; std::string y; // Empty for X25519 public keys. std::string private_key; }; util::StatusOr GenerateKeyPair(subtle::EllipticCurveType curve) { if (curve == subtle::EllipticCurveType::CURVE25519) { util::StatusOr> x25519_key = internal::NewX25519Key(); if (!x25519_key.ok()) { return x25519_key.status(); } const std::string public_key_bytes = std::string(reinterpret_cast((*x25519_key)->public_value), internal::X25519KeyPubKeySize()); const std::string private_key_bytes = std::string(reinterpret_cast((*x25519_key)->private_key), internal::X25519KeyPrivKeySize()); return KeyPair{/*x=*/public_key_bytes, /*y=*/"", private_key_bytes}; } util::StatusOr ec_key = internal::NewEcKey(curve); if (!ec_key.ok()) { return ec_key.status(); } return KeyPair{ ec_key->pub_x, ec_key->pub_y, std::string(util::SecretDataAsStringView(ec_key->priv)), }; } TEST_P(EciesProtoSerializationTest, ParsePublicKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = test_case.kem_params; *params.mutable_dem_params() = test_case.dem_params; params.set_ec_point_format(test_case.ec_point_format); util::StatusOr key_pair = GenerateKeyPair( util::Enums::ProtoToSubtle(test_case.kem_params.curve_type())); ASSERT_THAT(key_pair, IsOk()); EciesAeadHkdfPublicKey key_proto; key_proto.set_version(0); key_proto.set_x(key_pair->x); key_proto.set_y(key_pair->y); *key_proto.mutable_params() = params; RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kPublicTypeUrl, serialized_key, KeyData::ASYMMETRIC_PUBLIC, test_case.output_prefix_type, test_case.id); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); ASSERT_THAT(key, IsOk()); EXPECT_THAT((*key)->GetIdRequirement(), Eq(test_case.id)); EXPECT_THAT((*key)->GetParameters().HasIdRequirement(), Eq(test_case.id.has_value())); EciesParameters::Builder parameters_builder = EciesParameters::Builder() .SetCurveType(test_case.curve_type) .SetHashType(test_case.hash_type) .SetDemId(test_case.dem_id) .SetVariant(test_case.variant); if (test_case.point_format.has_value()) { parameters_builder.SetNistCurvePointFormat(*test_case.point_format); } if (test_case.salt.has_value()) { parameters_builder.SetSalt(*test_case.salt); } util::StatusOr expected_parameters = parameters_builder.Build(); ASSERT_THAT(expected_parameters, IsOk()); util::StatusOr expected_key; if (test_case.curve_type != EciesParameters::CurveType::kX25519) { expected_key = EciesPublicKey::CreateForNistCurve( *expected_parameters, EcPoint(BigInteger(key_pair->x), BigInteger(key_pair->y)), test_case.id, GetPartialKeyAccess()); } else { expected_key = EciesPublicKey::CreateForCurveX25519( *expected_parameters, key_pair->x, test_case.id, GetPartialKeyAccess()); } ASSERT_THAT(expected_key, IsOk()); EXPECT_THAT(**key, Eq(*expected_key)); } TEST_F(EciesProtoSerializationTest, ParsePublicKeyWithInvalidSerialization) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPublicTypeUrl, serialized_key, KeyData::ASYMMETRIC_PUBLIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT( key.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Failed to parse EciesAeadHkdfPublicKey proto"))); } TEST_F(EciesProtoSerializationTest, ParsePublicKeyWithInvalidVersion) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = CreateKemParams(EllipticCurveType::NIST_P256, HashType::SHA256, kSalt); *params.mutable_dem_params() = CreateAesGcmDemParams(16); params.set_ec_point_format(EcPointFormat::COMPRESSED); util::StatusOr key_pair = GenerateKeyPair(subtle::EllipticCurveType::NIST_P256); ASSERT_THAT(key_pair, IsOk()); EciesAeadHkdfPublicKey key_proto; key_proto.set_version(1); key_proto.set_x(key_pair->x); key_proto.set_y(key_pair->y); *key_proto.mutable_params() = params; RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPublicTypeUrl, serialized_key, KeyData::ASYMMETRIC_PUBLIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); EXPECT_THAT( key.status(), StatusIs( absl::StatusCode::kInvalidArgument, HasSubstr( "Only version 0 keys are accepted for EciesAeadHkdfPublicKey"))); } TEST_P(EciesProtoSerializationTest, SerializePublicKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesParameters::Builder parameters_builder = EciesParameters::Builder() .SetCurveType(test_case.curve_type) .SetHashType(test_case.hash_type) .SetDemId(test_case.dem_id) .SetVariant(test_case.variant); if (test_case.point_format.has_value()) { parameters_builder.SetNistCurvePointFormat(*test_case.point_format); } if (test_case.salt.has_value()) { parameters_builder.SetSalt(*test_case.salt); } util::StatusOr parameters = parameters_builder.Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr key_pair = GenerateKeyPair( util::Enums::ProtoToSubtle(test_case.kem_params.curve_type())); ASSERT_THAT(key_pair, IsOk()); util::StatusOr public_key; if (test_case.curve_type != EciesParameters::CurveType::kX25519) { public_key = EciesPublicKey::CreateForNistCurve( *parameters, EcPoint(BigInteger(key_pair->x), BigInteger(key_pair->y)), test_case.id, GetPartialKeyAccess()); } else { public_key = EciesPublicKey::CreateForCurveX25519( *parameters, key_pair->x, test_case.id, GetPartialKeyAccess()); } ASSERT_THAT(public_key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *public_key, /*token=*/absl::nullopt); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kPublicTypeUrl)); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq(kPublicTypeUrl)); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::ASYMMETRIC_PUBLIC)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id)); EciesAeadHkdfPublicKey proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.version(), Eq(0)); const std::string prefix = (test_case.curve_type == EciesParameters::CurveType::kX25519) ? "" : std::string("\x00", 1); EXPECT_THAT(proto_key.x(), Eq(absl::StrCat(prefix, key_pair->x))); EXPECT_THAT(proto_key.y(), Eq(absl::StrCat(prefix, key_pair->y))); EXPECT_THAT(proto_key.has_params(), IsTrue()); EXPECT_THAT(proto_key.params().ec_point_format(), Eq(test_case.ec_point_format)); ASSERT_THAT(proto_key.params().has_kem_params(), IsTrue()); EXPECT_THAT(proto_key.params().kem_params().curve_type(), Eq(test_case.kem_params.curve_type())); EXPECT_THAT(proto_key.params().kem_params().hkdf_hash_type(), Eq(test_case.kem_params.hkdf_hash_type())); EXPECT_THAT(proto_key.params().kem_params().hkdf_salt(), Eq(test_case.kem_params.hkdf_salt())); ASSERT_THAT(proto_key.params().has_dem_params(), IsTrue()); ASSERT_THAT(proto_key.params().dem_params().has_aead_dem(), IsTrue()); EXPECT_THAT(proto_key.params().dem_params().aead_dem().type_url(), Eq(test_case.dem_params.aead_dem().type_url())); EXPECT_THAT(proto_key.params().dem_params().aead_dem().output_prefix_type(), Eq(test_case.dem_params.aead_dem().output_prefix_type())); EXPECT_THAT(proto_key.params().dem_params().aead_dem().value(), Eq(test_case.dem_params.aead_dem().value())); } TEST_P(EciesProtoSerializationTest, ParsePrivateKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = test_case.kem_params; *params.mutable_dem_params() = test_case.dem_params; params.set_ec_point_format(test_case.ec_point_format); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr key_pair = GenerateKeyPair( util::Enums::ProtoToSubtle(test_case.kem_params.curve_type())); ASSERT_THAT(key_pair, IsOk()); EciesAeadHkdfPublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_x(key_pair->x); public_key_proto.set_y(key_pair->y); *public_key_proto.mutable_params() = params; EciesAeadHkdfPrivateKey private_key_proto; private_key_proto.set_version(0); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_key_value(key_pair->private_key); RestrictedData serialized_key = RestrictedData( private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, test_case.output_prefix_type, test_case.id); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); EXPECT_THAT((*key)->GetIdRequirement(), Eq(test_case.id)); EXPECT_THAT((*key)->GetParameters().HasIdRequirement(), Eq(test_case.id.has_value())); EciesParameters::Builder parameters_builder = EciesParameters::Builder() .SetCurveType(test_case.curve_type) .SetHashType(test_case.hash_type) .SetDemId(test_case.dem_id) .SetVariant(test_case.variant); if (test_case.point_format.has_value()) { parameters_builder.SetNistCurvePointFormat(*test_case.point_format); } if (test_case.salt.has_value()) { parameters_builder.SetSalt(*test_case.salt); } util::StatusOr expected_parameters = parameters_builder.Build(); ASSERT_THAT(expected_parameters, IsOk()); util::StatusOr expected_public_key; if (test_case.curve_type != EciesParameters::CurveType::kX25519) { expected_public_key = EciesPublicKey::CreateForNistCurve( *expected_parameters, EcPoint(BigInteger(key_pair->x), BigInteger(key_pair->y)), test_case.id, GetPartialKeyAccess()); } else { expected_public_key = EciesPublicKey::CreateForCurveX25519( *expected_parameters, key_pair->x, test_case.id, GetPartialKeyAccess()); } ASSERT_THAT(expected_public_key, IsOk()); util::StatusOr expected_private_key; if (test_case.curve_type != EciesParameters::CurveType::kX25519) { expected_private_key = EciesPrivateKey::CreateForNistCurve( *expected_public_key, RestrictedBigInteger(key_pair->private_key, InsecureSecretKeyAccess::Get()), GetPartialKeyAccess()); } else { expected_private_key = EciesPrivateKey::CreateForCurveX25519( *expected_public_key, RestrictedData(key_pair->private_key, InsecureSecretKeyAccess::Get()), GetPartialKeyAccess()); } ASSERT_THAT(expected_private_key, IsOk()); EXPECT_THAT(**key, Eq(*expected_private_key)); } TEST_F(EciesProtoSerializationTest, ParsePrivateKeyWithInvalidSerialization) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT( key.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Failed to parse EciesAeadHkdfPrivateKey proto"))); } TEST_F(EciesProtoSerializationTest, ParsePrivateKeyWithInvalidVersion) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = CreateKemParams(EllipticCurveType::NIST_P256, HashType::SHA256, kSalt); *params.mutable_dem_params() = CreateAesGcmDemParams(16); params.set_ec_point_format(EcPointFormat::COMPRESSED); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr key_pair = GenerateKeyPair(subtle::EllipticCurveType::NIST_P256); ASSERT_THAT(key_pair, IsOk()); EciesAeadHkdfPublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_x(key_pair->x); public_key_proto.set_y(key_pair->y); *public_key_proto.mutable_params() = params; EciesAeadHkdfPrivateKey private_key_proto; private_key_proto.set_version(1); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_key_value(key_pair->private_key); RestrictedData serialized_key = RestrictedData( private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT( key.status(), StatusIs( absl::StatusCode::kInvalidArgument, HasSubstr( "Only version 0 keys are accepted for EciesAeadHkdfPrivateKey"))); } TEST_F(EciesProtoSerializationTest, ParsePrivateKeyNoSecretKeyAccess) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesAeadHkdfParams params; *params.mutable_kem_params() = CreateKemParams(EllipticCurveType::NIST_P256, HashType::SHA256, kSalt); *params.mutable_dem_params() = CreateAesGcmDemParams(16); params.set_ec_point_format(EcPointFormat::COMPRESSED); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr key_pair = GenerateKeyPair(subtle::EllipticCurveType::NIST_P256); ASSERT_THAT(key_pair, IsOk()); EciesAeadHkdfPublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_x(key_pair->x); public_key_proto.set_y(key_pair->y); *public_key_proto.mutable_params() = params; EciesAeadHkdfPrivateKey private_key_proto; private_key_proto.set_version(0); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_key_value(key_pair->private_key); RestrictedData serialized_key = RestrictedData( private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kPermissionDenied, HasSubstr("SecretKeyAccess is required"))); } TEST_P(EciesProtoSerializationTest, SerializePrivateKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); EciesParameters::Builder parameters_builder = EciesParameters::Builder() .SetCurveType(test_case.curve_type) .SetHashType(test_case.hash_type) .SetDemId(test_case.dem_id) .SetVariant(test_case.variant); if (test_case.point_format.has_value()) { parameters_builder.SetNistCurvePointFormat(*test_case.point_format); } if (test_case.salt.has_value()) { parameters_builder.SetSalt(*test_case.salt); } util::StatusOr parameters = parameters_builder.Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr key_pair = GenerateKeyPair( util::Enums::ProtoToSubtle(test_case.kem_params.curve_type())); ASSERT_THAT(key_pair, IsOk()); util::StatusOr public_key; if (test_case.curve_type != EciesParameters::CurveType::kX25519) { public_key = EciesPublicKey::CreateForNistCurve( *parameters, EcPoint(BigInteger(key_pair->x), BigInteger(key_pair->y)), test_case.id, GetPartialKeyAccess()); } else { public_key = EciesPublicKey::CreateForCurveX25519( *parameters, key_pair->x, test_case.id, GetPartialKeyAccess()); } ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key; if (test_case.curve_type != EciesParameters::CurveType::kX25519) { private_key = EciesPrivateKey::CreateForNistCurve( *public_key, RestrictedBigInteger(key_pair->private_key, InsecureSecretKeyAccess::Get()), GetPartialKeyAccess()); } else { private_key = EciesPrivateKey::CreateForCurveX25519( *public_key, RestrictedData(key_pair->private_key, InsecureSecretKeyAccess::Get()), GetPartialKeyAccess()); } ASSERT_THAT(private_key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *private_key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kPrivateTypeUrl)); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq(kPrivateTypeUrl)); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::ASYMMETRIC_PRIVATE)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id)); EciesAeadHkdfPrivateKey proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); const std::string prefix = (test_case.curve_type == EciesParameters::CurveType::kX25519) ? "" : std::string("\x00", 1); EXPECT_THAT(proto_key.version(), Eq(0)); EXPECT_THAT(proto_key.key_value(), Eq(absl::StrCat(prefix, key_pair->private_key))); EXPECT_THAT(proto_key.has_public_key(), IsTrue()); EXPECT_THAT(proto_key.public_key().version(), Eq(0)); EXPECT_THAT(proto_key.public_key().has_params(), IsTrue()); EXPECT_THAT(proto_key.version(), Eq(0)); EXPECT_THAT(proto_key.public_key().x(), Eq(absl::StrCat(prefix, key_pair->x))); EXPECT_THAT(proto_key.public_key().y(), Eq(absl::StrCat(prefix, key_pair->y))); EXPECT_THAT(proto_key.public_key().has_params(), IsTrue()); ASSERT_THAT(proto_key.public_key().params().has_kem_params(), IsTrue()); EXPECT_THAT(proto_key.public_key().params().kem_params().curve_type(), Eq(test_case.kem_params.curve_type())); EXPECT_THAT(proto_key.public_key().params().kem_params().hkdf_hash_type(), Eq(test_case.kem_params.hkdf_hash_type())); EXPECT_THAT(proto_key.public_key().params().kem_params().hkdf_salt(), Eq(test_case.kem_params.hkdf_salt())); ASSERT_THAT(proto_key.public_key().params().has_dem_params(), IsTrue()); ASSERT_THAT(proto_key.public_key().params().dem_params().has_aead_dem(), IsTrue()); EXPECT_THAT( proto_key.public_key().params().dem_params().aead_dem().type_url(), Eq(test_case.dem_params.aead_dem().type_url())); EXPECT_THAT(proto_key.public_key() .params() .dem_params() .aead_dem() .output_prefix_type(), Eq(test_case.dem_params.aead_dem().output_prefix_type())); EXPECT_THAT(proto_key.public_key().params().dem_params().aead_dem().value(), Eq(test_case.dem_params.aead_dem().value())); EXPECT_THAT(proto_key.public_key().params().ec_point_format(), Eq(test_case.ec_point_format)); } TEST_F(EciesProtoSerializationTest, SerializePrivateKeyNoSecretKeyAccess) { ASSERT_THAT(RegisterEciesProtoSerialization(), IsOk()); util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kX25519) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr key_pair = GenerateKeyPair( util::Enums::ProtoToSubtle(EllipticCurveType::CURVE25519)); ASSERT_THAT(key_pair, IsOk()); util::StatusOr public_key = EciesPublicKey::CreateForCurveX25519(*parameters, key_pair->x, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = EciesPrivateKey::CreateForCurveX25519( *public_key, RestrictedData(key_pair->private_key, InsecureSecretKeyAccess::Get()), GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *private_key, /*token=*/absl::nullopt); ASSERT_THAT(serialization.status(), StatusIs(absl::StatusCode::kPermissionDenied, HasSubstr("SecretKeyAccess is required"))); } // TODO: b/330508549 - Remove test after existing keys are updated/removed. TEST(AeadDemTypeUrlExceptionTest, ParseWithInvalidUrl) { const std::string invalid_aead_dem_type_url = "type.googleapis.com/google.crypto.tink.XChaCha20Poly1305KeyFormat"; XChaCha20Poly1305KeyFormat format; format.set_version(0); KeyTemplate key_template; key_template.set_type_url(invalid_aead_dem_type_url); key_template.set_output_prefix_type(OutputPrefixType::TINK); format.SerializeToString(key_template.mutable_value()); EciesAeadDemParams dem_params; *dem_params.mutable_aead_dem() = key_template; EciesAeadHkdfParams params; *params.mutable_dem_params() = dem_params; *params.mutable_kem_params() = CreateKemParams(EllipticCurveType::CURVE25519, HashType::SHA256, /*salt=*/""); params.set_ec_point_format(EcPointFormat::COMPRESSED); EciesAeadHkdfKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr key_pair = GenerateKeyPair( util::Enums::ProtoToSubtle(params.kem_params().curve_type())); ASSERT_THAT(key_pair, IsOk()); EciesAeadHkdfPublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_x(key_pair->x); public_key_proto.set_y(key_pair->y); *public_key_proto.mutable_params() = params; EciesAeadHkdfPrivateKey private_key_proto; private_key_proto.set_version(0); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_key_value(key_pair->private_key); RestrictedData serialized_key = RestrictedData( private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/123); ASSERT_THAT(serialization, IsOk()); util::StatusOr> private_key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(private_key, IsOk()); util::StatusOr expected_parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kX25519) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kXChaCha20Poly1305Raw) .SetVariant(EciesParameters::Variant::kTink) .Build(); ASSERT_THAT(expected_parameters, IsOk()); EXPECT_THAT((*private_key)->GetParameters(), Eq(*expected_parameters)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/ecies_public_key.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/ecies_public_key.h" #include #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #include "openssl/ec_key.h" #else #include "openssl/ec.h" #endif #include "tink/ec_point.h" #include "tink/hybrid/ecies_parameters.h" #include "tink/internal/ec_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { util::Status ValidateNistCurvePublicKey(EciesParameters::CurveType curve_type, const EcPoint& point) { subtle::EllipticCurveType curve; switch (curve_type) { case EciesParameters::CurveType::kNistP256: curve = subtle::EllipticCurveType::NIST_P256; break; case EciesParameters::CurveType::kNistP384: curve = subtle::EllipticCurveType::NIST_P384; break; case EciesParameters::CurveType::kNistP521: curve = subtle::EllipticCurveType::NIST_P521; break; case EciesParameters::CurveType::kX25519: curve = subtle::EllipticCurveType::CURVE25519; break; default: return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Unknown curve type: ", curve_type)); } util::StatusOr> ec_point = internal::GetEcPoint(curve, point.GetX().GetValue(), point.GetY().GetValue()); if (!ec_point.ok()) { return ec_point.status(); } util::StatusOr> group = internal::EcGroupFromCurveType(curve); if (!group.ok()) { return group.status(); } if (EC_POINT_is_on_curve(group->get(), ec_point->get(), /*ctx=*/nullptr) != 1) { return util::Status(absl::StatusCode::kInternal, absl::StrCat("EC public point is not on curve ", subtle::EnumToString(curve))); } return util::OkStatus(); } util::StatusOr ComputeOutputPrefix( const EciesParameters& parameters, absl::optional id_requirement) { switch (parameters.GetVariant()) { case EciesParameters::Variant::kNoPrefix: return std::string(""); // Empty prefix. case EciesParameters::Variant::kCrunchy: if (!id_requirement.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "ID requirement must have value with kCrunchy"); } return absl::StrCat(absl::HexStringToBytes("00"), subtle::BigEndian32(*id_requirement)); case EciesParameters::Variant::kTink: if (!id_requirement.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "ID requirement must have value with kTink"); } return absl::StrCat(absl::HexStringToBytes("01"), subtle::BigEndian32(*id_requirement)); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid variant: ", parameters.GetVariant())); } } util::Status ValidateIdRequirement(const EciesParameters& parameters, absl::optional id_requirement) { if (parameters.HasIdRequirement() && !id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key without ID requirement with parameters with ID " "requirement"); } if (!parameters.HasIdRequirement() && id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key with ID requirement with parameters without ID " "requirement"); } return util::OkStatus(); } } // namespace util::StatusOr EciesPublicKey::CreateForNistCurve( const EciesParameters& parameters, const EcPoint& point, absl::optional id_requirement, PartialKeyAccessToken token) { util::Status id_requirement_validation = ValidateIdRequirement(parameters, id_requirement); if (!id_requirement_validation.ok()) { return id_requirement_validation; } util::Status public_key_validation = ValidateNistCurvePublicKey(parameters.GetCurveType(), point); if (!public_key_validation.ok()) { return public_key_validation; } util::StatusOr output_prefix = ComputeOutputPrefix(parameters, id_requirement); if (!output_prefix.ok()) { return output_prefix.status(); } return EciesPublicKey(parameters, point, id_requirement, *output_prefix); } util::StatusOr EciesPublicKey::CreateForCurveX25519( const EciesParameters& parameters, absl::string_view public_key_bytes, absl::optional id_requirement, PartialKeyAccessToken token) { util::Status id_requirement_validation = ValidateIdRequirement(parameters, id_requirement); if (!id_requirement_validation.ok()) { return id_requirement_validation; } // Validate key length. if (public_key_bytes.length() != internal::X25519KeyPubKeySize()) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrFormat( "Invalid X25519 public key length (expected %d, got %d)", internal::X25519KeyPubKeySize(), public_key_bytes.length())); } util::StatusOr output_prefix = ComputeOutputPrefix(parameters, id_requirement); if (!output_prefix.ok()) { return output_prefix.status(); } return EciesPublicKey(parameters, public_key_bytes, id_requirement, *output_prefix); } bool EciesPublicKey::operator==(const Key& other) const { const EciesPublicKey* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (GetParameters() != that->GetParameters()) { return false; } if (id_requirement_ != that->id_requirement_) { return false; } if (point_ != that->point_) { return false; } return public_key_bytes_ == that->public_key_bytes_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/ecies_public_key.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_ECIES_PUBLIC_KEY_H_ #define TINK_HYBRID_ECIES_PUBLIC_KEY_H_ #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/ec_point.h" #include "tink/hybrid/ecies_parameters.h" #include "tink/hybrid/hybrid_public_key.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Representation of the encryption function for an ECIES hybrid encryption // primitive. class EciesPublicKey : public HybridPublicKey { public: // Copyable and movable. EciesPublicKey(const EciesPublicKey& other) = default; EciesPublicKey& operator=(const EciesPublicKey& other) = default; EciesPublicKey(EciesPublicKey&& other) = default; EciesPublicKey& operator=(EciesPublicKey&& other) = default; static util::StatusOr CreateForNistCurve( const EciesParameters& parameters, const EcPoint& point, absl::optional id_requirement, PartialKeyAccessToken token); static util::StatusOr CreateForCurveX25519( const EciesParameters& parameters, absl::string_view public_key_bytes, absl::optional id_requirement, PartialKeyAccessToken token); absl::optional GetNistCurvePoint(PartialKeyAccessToken token) const { return point_; } absl::optional GetX25519CurvePointBytes( PartialKeyAccessToken token) const { return public_key_bytes_; } absl::string_view GetOutputPrefix() const override { return output_prefix_; } const EciesParameters& GetParameters() const override { return parameters_; } absl::optional GetIdRequirement() const override { return id_requirement_; } bool operator==(const Key& other) const override; private: // Creates a NIST curve-based ECIES public key. explicit EciesPublicKey(const EciesParameters& parameters, const EcPoint& point, absl::optional id_requirement, absl::string_view output_prefix) : parameters_(parameters), point_(point), public_key_bytes_(absl::nullopt), id_requirement_(id_requirement), output_prefix_(output_prefix) {} // Creates an X25519-based ECIES public key. explicit EciesPublicKey(const EciesParameters& parameters, absl::string_view public_key_bytes, absl::optional id_requirement, absl::string_view output_prefix) : parameters_(parameters), point_(absl::nullopt), public_key_bytes_(public_key_bytes), id_requirement_(id_requirement), output_prefix_(output_prefix) {} EciesParameters parameters_; absl::optional point_; absl::optional public_key_bytes_; absl::optional id_requirement_; std::string output_prefix_; }; } // namespace tink } // namespace crypto #endif // TINK_HYBRID_ECIES_PUBLIC_KEY_H_ ================================================ FILE: cc/hybrid/ecies_public_key_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/ecies_public_key.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/types/optional.h" #include "tink/big_integer.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #endif #include "tink/ec_point.h" #include "tink/hybrid/ecies_parameters.h" #include "tink/internal/ec_util.h" #include "tink/partial_key_access.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/random.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::IsEmpty; using ::testing::SizeIs; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { subtle::EllipticCurveType curve; EciesParameters::CurveType curve_type; EciesParameters::HashType hash_type; subtle::EcPointFormat ec_point_format; EciesParameters::PointFormat point_format; EciesParameters::DemId dem_id; EciesParameters::Variant variant; absl::optional id_requirement; std::string output_prefix; }; using EciesPublicKeyTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( EciesPublicKeyTestSuite, EciesPublicKeyTest, Values(TestCase{subtle::EllipticCurveType::NIST_P256, EciesParameters::CurveType::kNistP256, EciesParameters::HashType::kSha256, subtle::EcPointFormat::COMPRESSED, EciesParameters::PointFormat::kCompressed, EciesParameters::DemId::kAes128GcmRaw, EciesParameters::Variant::kTink, /*id_requirement=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{subtle::EllipticCurveType::NIST_P384, EciesParameters::CurveType::kNistP384, EciesParameters::HashType::kSha384, subtle::EcPointFormat::DO_NOT_USE_CRUNCHY_UNCOMPRESSED, EciesParameters::PointFormat::kLegacyUncompressed, EciesParameters::DemId::kAes256GcmRaw, EciesParameters::Variant::kCrunchy, /*id_requirement=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{subtle::EllipticCurveType::NIST_P521, EciesParameters::CurveType::kNistP521, EciesParameters::HashType::kSha512, subtle::EcPointFormat::UNCOMPRESSED, EciesParameters::PointFormat::kUncompressed, EciesParameters::DemId::kAes256SivRaw, EciesParameters::Variant::kNoPrefix, /*id_requirement=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(EciesPublicKeyTest, CreateNistCurvePublicKey) { TestCase test_case = GetParam(); util::StatusOr params = EciesParameters::Builder() .SetCurveType(test_case.curve_type) .SetHashType(test_case.hash_type) .SetNistCurvePointFormat(test_case.point_format) .SetDemId(test_case.dem_id) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr ec_key = internal::NewEcKey(test_case.curve); ASSERT_THAT(ec_key, IsOk()); EcPoint public_point(BigInteger(ec_key->pub_x), BigInteger(ec_key->pub_y)); util::StatusOr public_key = EciesPublicKey::CreateForNistCurve(*params, public_point, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); EXPECT_THAT(public_key->GetParameters(), Eq(*params)); EXPECT_THAT(public_key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(public_key->GetOutputPrefix(), Eq(test_case.output_prefix)); EXPECT_THAT(public_key->GetNistCurvePoint(GetPartialKeyAccess()), Eq(public_point)); EXPECT_THAT(public_key->GetX25519CurvePointBytes(GetPartialKeyAccess()), Eq(absl::nullopt)); } TEST(EciesPublicKeyTest, CreateX25519PublicKey) { util::StatusOr params = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kX25519) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = EciesPublicKey::CreateForCurveX25519(*params, public_key_bytes, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); EXPECT_THAT(public_key->GetParameters(), Eq(*params)); EXPECT_THAT(public_key->GetIdRequirement(), Eq(absl::nullopt)); EXPECT_THAT(public_key->GetOutputPrefix(), IsEmpty()); EXPECT_THAT(public_key->GetNistCurvePoint(GetPartialKeyAccess()), Eq(absl::nullopt)); EXPECT_THAT(public_key->GetX25519CurvePointBytes(GetPartialKeyAccess()), Eq(public_key_bytes)); } TEST(EciesPublicKeyTest, CreateX25519PublicKeyWithInvalidLength) { util::StatusOr params = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kX25519) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = EciesPublicKey::CreateForCurveX25519( *params, public_key_bytes.substr(0, public_key_bytes.size() - 1), /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); EXPECT_THAT(public_key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesPublicKeyTest, CreateNistCurvePublicKeyWithInvalidPoint) { // Copied from "public point not on curve" Wycheproof test case in // // https://github.com/google/wycheproof/blob/master/testvectors/ecdh_secp256k1_test.json. std::string invalid_point = absl::HexStringToBytes( "3056301006072a8648ce3d020106052b8104000a0342000449c248edc659e18482b71057" "48a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d" "7a9a7063286bbd16ef64c65f546757e4"); util::StatusOr point_size = internal::EcPointEncodingSizeInBytes(subtle::EllipticCurveType::NIST_P256, subtle::EcPointFormat::UNCOMPRESSED); ASSERT_THAT(point_size, IsOk()); ASSERT_THAT(*point_size, testing::Lt(invalid_point.size())); std::string public_key_bytes = invalid_point.substr(invalid_point.size() - *point_size, *point_size); // Uncompressed point format starts with a 0x04-byte. ASSERT_THAT(public_key_bytes, SizeIs(65)); ASSERT_THAT(public_key_bytes[0], Eq(0x04)); BigInteger x(public_key_bytes.substr(1, 32)); BigInteger y(public_key_bytes.substr(33, 32)); EcPoint point(x, y); util::StatusOr params = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetHashType(EciesParameters::HashType::kSha256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr public_key = EciesPublicKey::CreateForNistCurve(*params, point, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); EXPECT_THAT(public_key.status(), StatusIs(absl::StatusCode::kInternal)); } TEST(EciesPublicKeyTest, CreateX2559CurvePublicKeyWithInvalidIdRequirementFails) { util::StatusOr no_prefix_params = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kX25519) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(no_prefix_params, IsOk()); util::StatusOr tink_params = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kX25519) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kTink) .Build(); ASSERT_THAT(tink_params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); EXPECT_THAT(EciesPublicKey::CreateForCurveX25519( *no_prefix_params, public_key_bytes, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(EciesPublicKey::CreateForCurveX25519( *tink_params, public_key_bytes, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EciesPublicKeyTest, CreateNistCurvePublicKeyWithInvalidIdRequirementFails) { util::StatusOr no_prefix_params = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(no_prefix_params, IsOk()); util::StatusOr tink_params = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kTink) .Build(); ASSERT_THAT(tink_params, IsOk()); util::StatusOr ec_key = internal::NewEcKey(subtle::EllipticCurveType::NIST_P256); ASSERT_THAT(ec_key, IsOk()); EcPoint public_point(BigInteger(ec_key->pub_x), BigInteger(ec_key->pub_y)); EXPECT_THAT(EciesPublicKey::CreateForNistCurve( *no_prefix_params, public_point, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(EciesPublicKey::CreateForNistCurve( *tink_params, public_point, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(EciesPublicKeyTest, NistCurvePublicKeyEquals) { TestCase test_case = GetParam(); util::StatusOr params = EciesParameters::Builder() .SetCurveType(test_case.curve_type) .SetHashType(test_case.hash_type) .SetNistCurvePointFormat(test_case.point_format) .SetDemId(test_case.dem_id) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr ec_key = internal::NewEcKey(test_case.curve); ASSERT_THAT(ec_key, IsOk()); EcPoint public_point(BigInteger(ec_key->pub_x), BigInteger(ec_key->pub_y)); util::StatusOr public_key = EciesPublicKey::CreateForNistCurve(*params, public_point, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = EciesPublicKey::CreateForNistCurve(*params, public_point, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key == *other_public_key); EXPECT_TRUE(*other_public_key == *public_key); EXPECT_FALSE(*public_key != *other_public_key); EXPECT_FALSE(*other_public_key != *public_key); } TEST(EciesPublicKeyTest, X25519PublicKeyEquals) { util::StatusOr params = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kX25519) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = EciesPublicKey::CreateForCurveX25519(*params, public_key_bytes, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = EciesPublicKey::CreateForCurveX25519(*params, public_key_bytes, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key == *other_public_key); EXPECT_TRUE(*other_public_key == *public_key); EXPECT_FALSE(*public_key != *other_public_key); EXPECT_FALSE(*other_public_key != *public_key); } TEST(EciesPublicKeyTest, DifferentParametersNotEqual) { util::StatusOr crunchy_params = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kX25519) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kCrunchy) .Build(); ASSERT_THAT(crunchy_params, IsOk()); util::StatusOr tink_params = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kX25519) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kTink) .Build(); ASSERT_THAT(tink_params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = EciesPublicKey::CreateForCurveX25519(*crunchy_params, public_key_bytes, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = EciesPublicKey::CreateForCurveX25519(*tink_params, public_key_bytes, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key != *other_public_key); EXPECT_TRUE(*other_public_key != *public_key); EXPECT_FALSE(*public_key == *other_public_key); EXPECT_FALSE(*other_public_key == *public_key); } TEST(EciesPublicKeyTest, DifferentPublicPointsNotEqual) { util::StatusOr params = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kNistP256) .SetNistCurvePointFormat(EciesParameters::PointFormat::kUncompressed) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kTink) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr ec_key1 = internal::NewEcKey(subtle::EllipticCurveType::NIST_P256); ASSERT_THAT(ec_key1, IsOk()); util::StatusOr ec_key2 = internal::NewEcKey(subtle::EllipticCurveType::NIST_P256); ASSERT_THAT(ec_key2, IsOk()); EcPoint public_point1(BigInteger(ec_key1->pub_x), BigInteger(ec_key1->pub_y)); EcPoint public_point2(BigInteger(ec_key2->pub_x), BigInteger(ec_key2->pub_y)); util::StatusOr public_key = EciesPublicKey::CreateForNistCurve(*params, public_point1, /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = EciesPublicKey::CreateForNistCurve(*params, public_point2, /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key != *other_public_key); EXPECT_TRUE(*other_public_key != *public_key); EXPECT_FALSE(*public_key == *other_public_key); EXPECT_FALSE(*other_public_key == *public_key); } TEST(EciesPublicKeyTest, DifferentPublicKeyBytesNotEqual) { util::StatusOr params = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kX25519) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kTink) .Build(); ASSERT_THAT(params, IsOk()); std::string public_key_bytes1 = subtle::Random::GetRandomBytes(32); std::string public_key_bytes2 = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = EciesPublicKey::CreateForCurveX25519(*params, public_key_bytes1, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = EciesPublicKey::CreateForCurveX25519(*params, public_key_bytes2, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key != *other_public_key); EXPECT_TRUE(*other_public_key != *public_key); EXPECT_FALSE(*public_key == *other_public_key); EXPECT_FALSE(*other_public_key == *public_key); } TEST(EciesPublicKeyTest, DifferentIdRequirementNotEqual) { util::StatusOr params = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kX25519) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kTink) .Build(); ASSERT_THAT(params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = EciesPublicKey::CreateForCurveX25519(*params, public_key_bytes, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = EciesPublicKey::CreateForCurveX25519(*params, public_key_bytes, /*id_requirement=*/0x02030405, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key != *other_public_key); EXPECT_TRUE(*other_public_key != *public_key); EXPECT_FALSE(*public_key == *other_public_key); EXPECT_FALSE(*other_public_key == *public_key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/failing_hybrid.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/failing_hybrid.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/hybrid_decrypt.h" #include "tink/hybrid_encrypt.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { // A HybridEncrypt which will always return a kInternal status on API calls. class AlwaysFailHybridEncrypt : public HybridEncrypt { public: explicit AlwaysFailHybridEncrypt(std::string message) : message_(std::move(message)) {} util::StatusOr Encrypt( absl::string_view plaintext, absl::string_view associated_data) const override { return util::Status( absl::StatusCode::kInternal, absl::StrCat( "AlwaysFailHybridEncrypt will always fail on encrypt (msg=", message_, ")")); } private: const std::string message_; }; // A HybridDecrypt which will always return a kInternal status on API calls. class AlwaysFailHybridDecrypt : public HybridDecrypt { public: explicit AlwaysFailHybridDecrypt(std::string message) : message_(std::move(message)) {} util::StatusOr Decrypt( absl::string_view plaintext, absl::string_view associated_data) const override { return util::Status( absl::StatusCode::kInternal, absl::StrCat( "AlwaysFailHybridDecrypt will always fail on decrypt (msg=", message_, ")")); } private: const std::string message_; }; } // namespace std::unique_ptr CreateAlwaysFailingHybridEncrypt( std::string message) { return absl::make_unique(std::move(message)); } std::unique_ptr CreateAlwaysFailingHybridDecrypt( std::string message) { return absl::make_unique(std::move(message)); } } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/failing_hybrid.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_FAILING_HYBRID_H_ #define TINK_HYBRID_FAILING_HYBRID_H_ #include #include #include "absl/strings/string_view.h" #include "tink/hybrid_decrypt.h" #include "tink/hybrid_encrypt.h" namespace crypto { namespace tink { // Returns a HybridEncrypt that always returns an error when calling Encrypt. // The error message will contain `message`. std::unique_ptr CreateAlwaysFailingHybridEncrypt( std::string message = ""); // Returns a HybridDecrypt that always returns an error when calling Decrypt. // The error message will contain `message`. std::unique_ptr CreateAlwaysFailingHybridDecrypt( std::string message = ""); } // namespace tink } // namespace crypto #endif // TINK_HYBRID_FAILING_HYBRID_H_ ================================================ FILE: cc/hybrid/failing_hybrid_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/failing_hybrid.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/hybrid_decrypt.h" #include "tink/hybrid_encrypt.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::StatusIs; using ::testing::HasSubstr; TEST(AlwaysFailHybridEncrypt, EncryptFails) { std::unique_ptr failing_hybrid_encrypt = CreateAlwaysFailingHybridEncrypt(); EXPECT_THAT( failing_hybrid_encrypt->Encrypt("plaintext", "context_info").status(), StatusIs(absl::StatusCode::kInternal)); } TEST(AlwaysFailHybridEncrypt, EncryptFailsContainsMessage) { const std::string expected_message = "expected_message"; std::unique_ptr failing_hybrid_encrypt = CreateAlwaysFailingHybridEncrypt(expected_message); EXPECT_THAT( failing_hybrid_encrypt->Encrypt("plaintext", "context_info").status(), StatusIs(absl::StatusCode::kInternal, HasSubstr(expected_message))); } TEST(AlwaysFailHybridDecrypt, DecryptFails) { std::unique_ptr failing_hybrid_decrypt = CreateAlwaysFailingHybridDecrypt(); EXPECT_THAT( failing_hybrid_decrypt->Decrypt("ciphertext", "context_info").status(), StatusIs(absl::StatusCode::kInternal)); } TEST(AlwaysFailHybridDecrypt, DecryptFailsContainsMessage) { const std::string expected_message = "expected_message"; std::unique_ptr failing_hybrid_decrypt = CreateAlwaysFailingHybridDecrypt(expected_message); EXPECT_THAT( failing_hybrid_decrypt->Decrypt("ciphertext", "context_info").status(), StatusIs(absl::StatusCode::kInternal, HasSubstr(expected_message))); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/hpke_config.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/hpke_config.h" #include "absl/memory/memory.h" #include "tink/aead/aead_config.h" #include "tink/config/tink_fips.h" #include "tink/hybrid/hpke_proto_serialization.h" #include "tink/hybrid/hybrid_decrypt_wrapper.h" #include "tink/hybrid/hybrid_encrypt_wrapper.h" #include "tink/hybrid/internal/hpke_private_key_manager.h" #include "tink/hybrid/internal/hpke_public_key_manager.h" #include "tink/registry.h" #include "tink/util/status.h" namespace crypto { namespace tink { util::Status RegisterHpke() { util::Status status = AeadConfig::Register(); if (!status.ok()) { return status; } // Register primitive wrappers. status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) { return status; } status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) { return status; } // Currently there are no HPKE key managers which only use FIPS-validated // implementations, therefore none will be registered in FIPS-only mode. if (IsFipsModeEnabled()) { return util::OkStatus(); } // Register non-FIPS HPKE key managers. status = Registry::RegisterAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), true); if (!status.ok()) { return status; } return RegisterHpkeProtoSerialization(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/hpke_config.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_HPKE_CONFIG_H_ #define TINK_HYBRID_HPKE_CONFIG_H_ #include "tink/util/status.h" namespace crypto { namespace tink { // Registers HybridEncrypt and HybridDecrypt primitive wrappers, and key // managers for HPKE Encrypt and HPKE Decrypt from the current Tink release. crypto::tink::util::Status RegisterHpke(); } // namespace tink } // namespace crypto #endif // TINK_HYBRID_HPKE_CONFIG_H_ ================================================ FILE: cc/hybrid/hpke_config_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/hpke_config.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/config/global_registry.h" #include "tink/config/tink_fips.h" #include "tink/hybrid/hpke_parameters.h" #include "tink/hybrid/hpke_private_key.h" #include "tink/hybrid/hpke_public_key.h" #include "tink/hybrid/hybrid_key_templates.h" #include "tink/hybrid/internal/hpke_private_key_manager.h" #include "tink/hybrid/internal/hpke_public_key_manager.h" #include "tink/hybrid_decrypt.h" #include "tink/hybrid_encrypt.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/ec_util.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/keyset_handle.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/registry.h" #include "tink/restricted_data.h" #include "tink/subtle/random.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/hpke.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::HpkeAead; using ::google::crypto::tink::HpkeKdf; using ::google::crypto::tink::HpkeKem; using ::google::crypto::tink::HpkeParams; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::OutputPrefixType; class HpkeConfigTest : public ::testing::Test { protected: void SetUp() override { Registry::Reset(); internal::MutableSerializationRegistry::GlobalInstance().Reset(); } }; TEST_F(HpkeConfigTest, Basic) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT(Registry::get_key_manager( internal::HpkePrivateKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT(Registry::get_key_manager( internal::HpkePublicKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT(RegisterHpke(), IsOk()); EXPECT_THAT(Registry::get_key_manager( internal::HpkePrivateKeyManager().get_key_type()) .status(), IsOk()); EXPECT_THAT(Registry::get_key_manager( internal::HpkePublicKeyManager().get_key_type()) .status(), IsOk()); } TEST_F(HpkeConfigTest, HpkeProtoParamsSerializationRegistered) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::StatusOr proto_params_serialization = internal::ProtoParametersSerialization::Create( HybridKeyTemplates::HpkeX25519HkdfSha256Aes256Gcm()); ASSERT_THAT(proto_params_serialization, IsOk()); util::StatusOr> parsed_params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr params = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kAesGcm256) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr> serialized_params = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params.status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(RegisterHpke(), IsOk()); util::StatusOr> parsed_params2 = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params2, IsOk()); util::StatusOr> serialized_params2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params2, IsOk()); } TEST_F(HpkeConfigTest, HpkeProtoPublicKeySerializationRegistered) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } const std::string raw_key = subtle::Random::GetRandomBytes(32); HpkeParams params; params.set_kem(HpkeKem::DHKEM_X25519_HKDF_SHA256); params.set_kdf(HpkeKdf::HKDF_SHA256); params.set_aead(HpkeAead::AES_256_GCM); google::crypto::tink::HpkePublicKey key_proto; key_proto.set_version(0); key_proto.set_public_key(raw_key); *key_proto.mutable_params() = params; util::StatusOr proto_key_serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.HpkePublicKey", RestrictedData(key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()), KeyData::ASYMMETRIC_PUBLIC, OutputPrefixType::TINK, /*id_requirement=*/123); ASSERT_THAT(proto_key_serialization, IsOk()); util::StatusOr> parsed_key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr parameters = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kAesGcm256) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr key = HpkePublicKey::Create( *parameters, raw_key, /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialized_key = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key.status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(RegisterHpke(), IsOk()); util::StatusOr> parsed_key2 = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key2, IsOk()); util::StatusOr> serialized_key2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key2, IsOk()); } TEST_F(HpkeConfigTest, HpkeProtoPrivateKeySerializationRegistered) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::StatusOr> key_pair = internal::NewX25519Key(); ASSERT_THAT(key_pair, IsOk()); HpkeParams params; params.set_kem(HpkeKem::DHKEM_X25519_HKDF_SHA256); params.set_kdf(HpkeKdf::HKDF_SHA256); params.set_aead(HpkeAead::AES_256_GCM); google::crypto::tink::HpkePublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_public_key( std::string(reinterpret_cast((*key_pair)->public_value), internal::X25519KeyPubKeySize())); *public_key_proto.mutable_params() = params; google::crypto::tink::HpkePrivateKey private_key_proto; private_key_proto.set_version(0); private_key_proto.set_private_key( std::string(reinterpret_cast((*key_pair)->private_key), internal::X25519KeyPrivKeySize())); *private_key_proto.mutable_public_key() = public_key_proto; util::StatusOr proto_key_serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.HpkePrivateKey", RestrictedData(private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()), KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/123); ASSERT_THAT(proto_key_serialization, IsOk()); util::StatusOr> parsed_key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr parameters = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kAesGcm256) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr public_key = HpkePublicKey::Create( *parameters, std::string(reinterpret_cast((*key_pair)->public_value), internal::X25519KeyPubKeySize()), /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); RestrictedData private_key_bytes = RestrictedData( std::string(reinterpret_cast((*key_pair)->private_key), internal::X25519KeyPrivKeySize()), InsecureSecretKeyAccess::Get()); util::StatusOr private_key = HpkePrivateKey::Create( *public_key, private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr> serialized_key = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *private_key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key.status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(RegisterHpke(), IsOk()); util::StatusOr> parsed_key2 = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key2, IsOk()); util::StatusOr> serialized_key2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *private_key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key2, IsOk()); } // FIPS-only mode tests TEST_F(HpkeConfigTest, RegisterNonFipsTemplates) { if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Only supported in FIPS-only mode"; } EXPECT_THAT(RegisterHpke(), IsOk()); // Check that we can not retrieve non-FIPS keyset handle std::list non_fips_key_templates; non_fips_key_templates.push_back( HybridKeyTemplates::HpkeX25519HkdfSha256Aes128Gcm()); non_fips_key_templates.push_back( HybridKeyTemplates::HpkeX25519HkdfSha256Aes256Gcm()); non_fips_key_templates.push_back( HybridKeyTemplates::HpkeX25519HkdfSha256ChaCha20Poly1305()); for (auto key_template : non_fips_key_templates) { EXPECT_THAT( KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()) .status(), StatusIs(absl::StatusCode::kNotFound)); } } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/hpke_parameters.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/hpke_parameters.h" #include #include "absl/status/status.h" #include "tink/parameters.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { HpkeParameters::Builder& HpkeParameters::Builder::SetKemId(KemId kem_id) { kem_id_ = kem_id; return *this; } HpkeParameters::Builder& HpkeParameters::Builder::SetKdfId(KdfId kdf_id) { kdf_id_ = kdf_id; return *this; } HpkeParameters::Builder& HpkeParameters::Builder::SetAeadId(AeadId aead_id) { aead_id_ = aead_id; return *this; } HpkeParameters::Builder& HpkeParameters::Builder::SetVariant(Variant variant) { variant_ = variant; return *this; } util::StatusOr HpkeParameters::Builder::Build() { static const std::set* supported_kem_ids = new std::set( {KemId::kDhkemP256HkdfSha256, KemId::kDhkemP384HkdfSha384, KemId::kDhkemP521HkdfSha512, KemId::kDhkemX25519HkdfSha256}); if (supported_kem_ids->find(kem_id_) == supported_kem_ids->end()) { return util::Status(absl::StatusCode::kInvalidArgument, "Cannot create HPKE parameters with unknown KEM ID."); } static const std::set* supported_kdf_ids = new std::set( {KdfId::kHkdfSha256, KdfId::kHkdfSha384, KdfId::kHkdfSha512}); if (supported_kdf_ids->find(kdf_id_) == supported_kdf_ids->end()) { return util::Status(absl::StatusCode::kInvalidArgument, "Cannot create HPKE parameters with unknown KDF ID."); } static const std::set* supported_aead_ids = new std::set( {AeadId::kAesGcm128, AeadId::kAesGcm256, AeadId::kChaCha20Poly1305}); if (supported_aead_ids->find(aead_id_) == supported_aead_ids->end()) { return util::Status(absl::StatusCode::kInvalidArgument, "Cannot create HPKE parameters with unknown AEAD ID."); } static const std::set* supported_variants = new std::set( {Variant::kTink, Variant::kCrunchy, Variant::kNoPrefix}); if (supported_variants->find(variant_) == supported_variants->end()) { return util::Status(absl::StatusCode::kInvalidArgument, "Cannot create HPKE parameters with unknown variant."); } return HpkeParameters(kem_id_, kdf_id_, aead_id_, variant_); } bool HpkeParameters::operator==(const Parameters& other) const { const HpkeParameters* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (kem_id_ != that->kem_id_) { return false; } if (kdf_id_ != that->kdf_id_) { return false; } if (aead_id_ != that->aead_id_) { return false; } if (variant_ != that->variant_) { return false; } return true; } } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/hpke_parameters.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_HPKE_PARAMETERS_H_ #define TINK_HYBRID_HPKE_PARAMETERS_H_ #include "tink/hybrid/hybrid_parameters.h" #include "tink/parameters.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { class HpkeParameters : public HybridParameters { public: // Description of the output prefix prepended to the ciphertext. enum class Variant : int { // Prepends '0x01' to ciphertext. kTink = 1, // Prepends '0x00' to ciphertext. kCrunchy = 2, // Does not prepend any prefix (i.e., keys must have no ID requirement). kNoPrefix = 3, // Added to guard from failures that may be caused by future expansions. kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // HPKE KEM identifiers specified in // https://www.rfc-editor.org/rfc/rfc9180.html#section-7.1. enum class KemId : int { kDhkemP256HkdfSha256 = 1, kDhkemP384HkdfSha384 = 2, kDhkemP521HkdfSha512 = 3, kDhkemX25519HkdfSha256 = 4, kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // HPKE KDF identifiers specified in // https://www.rfc-editor.org/rfc/rfc9180.html#section-7.2. enum class KdfId : int { kHkdfSha256 = 1, kHkdfSha384 = 2, kHkdfSha512 = 3, kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // HPKE AEAD identifiers specified in // https://www.rfc-editor.org/rfc/rfc9180.html#section-7.3. enum class AeadId : int { kAesGcm128 = 1, kAesGcm256 = 2, kChaCha20Poly1305 = 3, kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Creates HPKE parameters instances. class Builder { public: // Copyable and movable. Builder(const Builder& other) = default; Builder& operator=(const Builder& other) = default; Builder(Builder&& other) = default; Builder& operator=(Builder&& other) = default; // Creates initially empty parameters builder. Builder() = default; Builder& SetKemId(KemId kem_id); Builder& SetKdfId(KdfId kdf_id); Builder& SetAeadId(AeadId aead_id); Builder& SetVariant(Variant variant); // Creates HPKE parameters object from this builder. util::StatusOr Build(); private: KemId kem_id_; KdfId kdf_id_; AeadId aead_id_; Variant variant_; }; // Copyable and movable. HpkeParameters(const HpkeParameters& other) = default; HpkeParameters& operator=(const HpkeParameters& other) = default; HpkeParameters(HpkeParameters&& other) = default; HpkeParameters& operator=(HpkeParameters&& other) = default; KemId GetKemId() const { return kem_id_; } KdfId GetKdfId() const { return kdf_id_; } AeadId GetAeadId() const { return aead_id_; } Variant GetVariant() const { return variant_; } bool HasIdRequirement() const override { return variant_ != Variant::kNoPrefix; } bool operator==(const Parameters& other) const override; private: explicit HpkeParameters(KemId kem_id, KdfId kdf_id, AeadId aead_id, Variant variant) : kem_id_(kem_id), kdf_id_(kdf_id), aead_id_(aead_id), variant_(variant) {} KemId kem_id_; KdfId kdf_id_; AeadId aead_id_; Variant variant_; }; } // namespace tink } // namespace crypto #endif // TINK_HYBRID_HPKE_PARAMETERS_H_ ================================================ FILE: cc/hybrid/hpke_parameters_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/hpke_parameters.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Combine; using ::testing::Eq; using ::testing::IsTrue; using ::testing::TestWithParam; using ::testing::Values; struct VariantWithIdRequirement { HpkeParameters::Variant variant; bool has_id_requirement; }; using HpkeParametersTest = TestWithParam>; INSTANTIATE_TEST_SUITE_P( HpkeParametersTestSuite, HpkeParametersTest, Combine(Values(HpkeParameters::KemId::kDhkemP256HkdfSha256, HpkeParameters::KemId::kDhkemP384HkdfSha384, HpkeParameters::KemId::kDhkemP521HkdfSha512, HpkeParameters::KemId::kDhkemX25519HkdfSha256), Values(HpkeParameters::KdfId::kHkdfSha256, HpkeParameters::KdfId::kHkdfSha384, HpkeParameters::KdfId::kHkdfSha512), Values(HpkeParameters::AeadId::kAesGcm128, HpkeParameters::AeadId::kAesGcm256, HpkeParameters::AeadId::kChaCha20Poly1305), Values(VariantWithIdRequirement{HpkeParameters::Variant::kTink, /*has_id_requirement=*/true}, VariantWithIdRequirement{HpkeParameters::Variant::kCrunchy, /*has_id_requirement=*/true}, VariantWithIdRequirement{HpkeParameters::Variant::kNoPrefix, /*has_id_requirement=*/false}))); TEST_P(HpkeParametersTest, Build) { HpkeParameters::KemId kem_id; HpkeParameters::KdfId kdf_id; HpkeParameters::AeadId aead_id; VariantWithIdRequirement variant; std::tie(kem_id, kdf_id, aead_id, variant) = GetParam(); util::StatusOr parameters = HpkeParameters::Builder() .SetVariant(variant.variant) .SetKemId(kem_id) .SetKdfId(kdf_id) .SetAeadId(aead_id) .Build(); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetKemId(), Eq(kem_id)); EXPECT_THAT(parameters->GetKdfId(), Eq(kdf_id)); EXPECT_THAT(parameters->GetAeadId(), Eq(aead_id)); EXPECT_THAT(parameters->GetVariant(), Eq(variant.variant)); EXPECT_THAT(parameters->HasIdRequirement(), Eq(variant.has_id_requirement)); } TEST(HpkeParametersTest, BuildWithInvalidVariantFails) { util::StatusOr parameters = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kAesGcm128) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkeParametersTest, BuildWithoutVariantFails) { util::StatusOr parameters = HpkeParameters::Builder() .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kAesGcm128) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkeParametersTest, BuildWithInvalidKemIdFails) { util::StatusOr parameters = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKemId(HpkeParameters::KemId:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kAesGcm128) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkeParametersTest, BuildWithoutKemIdFails) { util::StatusOr parameters = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kAesGcm128) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkeParametersTest, BuildWithInvalidKdfIdFails) { util::StatusOr parameters = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .SetAeadId(HpkeParameters::AeadId::kAesGcm128) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkeParametersTest, BuildWithoutKdfIdFails) { util::StatusOr parameters = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetAeadId(HpkeParameters::AeadId::kAesGcm128) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkeParametersTest, BuildWithInvalidAeadIdFails) { util::StatusOr parameters = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkeParametersTest, BuildWithoutAeadIdFails) { util::StatusOr parameters = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkeParametersTest, CopyConstructor) { util::StatusOr parameters = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kAesGcm128) .Build(); ASSERT_THAT(parameters, IsOk()); HpkeParameters copy(*parameters); EXPECT_THAT(copy.GetVariant(), Eq(HpkeParameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); } TEST(HpkeParametersTest, CopyAssignment) { util::StatusOr parameters = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kAesGcm128) .Build(); ASSERT_THAT(parameters, IsOk()); HpkeParameters copy = *parameters; EXPECT_THAT(copy.GetVariant(), Eq(HpkeParameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); } TEST_P(HpkeParametersTest, ParametersEquals) { HpkeParameters::KemId kem_id; HpkeParameters::KdfId kdf_id; HpkeParameters::AeadId aead_id; VariantWithIdRequirement variant; std::tie(kem_id, kdf_id, aead_id, variant) = GetParam(); util::StatusOr parameters = HpkeParameters::Builder() .SetVariant(variant.variant) .SetKemId(kem_id) .SetKdfId(kdf_id) .SetAeadId(aead_id) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = HpkeParameters::Builder() .SetVariant(variant.variant) .SetKemId(kem_id) .SetKdfId(kdf_id) .SetAeadId(aead_id) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters == *other_parameters); EXPECT_TRUE(*other_parameters == *parameters); EXPECT_FALSE(*parameters != *other_parameters); EXPECT_FALSE(*other_parameters != *parameters); } TEST(HpkeParametersTest, VariantNotEqual) { util::StatusOr parameters = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kAesGcm128) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kCrunchy) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kAesGcm128) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(HpkeParametersTest, KemIdNotEqual) { util::StatusOr parameters = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kAesGcm128) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKemId(HpkeParameters::KemId::kDhkemP256HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kAesGcm128) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(HpkeParametersTest, KdfIdNotEqual) { util::StatusOr parameters = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha384) .SetAeadId(HpkeParameters::AeadId::kAesGcm128) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kAesGcm128) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(HpkeParametersTest, AeadIdNotEqual) { util::StatusOr parameters = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kAesGcm128) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kChaCha20Poly1305) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/hpke_private_key.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/hpke_private_key.h" #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "tink/internal/bn_util.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #include "openssl/ec_key.h" #else #include "openssl/ec.h" #endif #include "tink/hybrid/hpke_parameters.h" #include "tink/hybrid/hpke_public_key.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/ec_util.h" #include "tink/internal/err_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/subtle/common_enums.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { util::StatusOr CurveTypeFromKemId( HpkeParameters::KemId kem_id) { switch (kem_id) { case HpkeParameters::KemId::kDhkemP256HkdfSha256: return subtle::EllipticCurveType::NIST_P256; case HpkeParameters::KemId::kDhkemP384HkdfSha384: return subtle::EllipticCurveType::NIST_P384; case HpkeParameters::KemId::kDhkemP521HkdfSha512: return subtle::EllipticCurveType::NIST_P521; case HpkeParameters::KemId::kDhkemX25519HkdfSha256: return subtle::EllipticCurveType::CURVE25519; default: return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Unknown KEM ID: ", kem_id)); } } util::Status ValidatePrivateKeyLength(HpkeParameters::KemId kem_id, int length) { int expected_length; switch (kem_id) { // Key lengths from 'Nsk' column in // https://www.rfc-editor.org/rfc/rfc9180.html#table-2. case HpkeParameters::KemId::kDhkemP256HkdfSha256: expected_length = 32; break; case HpkeParameters::KemId::kDhkemP384HkdfSha384: expected_length = 48; break; case HpkeParameters::KemId::kDhkemP521HkdfSha512: expected_length = 66; break; case HpkeParameters::KemId::kDhkemX25519HkdfSha256: expected_length = 32; break; default: return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Unknown KEM ID: ", kem_id)); } // Validate key length. if (expected_length != length) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrFormat( "Invalid private key length for KEM %d (expected %d, got %d)", kem_id, expected_length, length)); } return util::OkStatus(); } bool IsNistKem(HpkeParameters::KemId kem_id) { return kem_id == HpkeParameters::KemId::kDhkemP256HkdfSha256 || kem_id == HpkeParameters::KemId::kDhkemP384HkdfSha384 || kem_id == HpkeParameters::KemId::kDhkemP521HkdfSha512; } util::Status ValidateNistEcKeyPair(subtle::EllipticCurveType curve, absl::string_view public_key_bytes, const util::SecretData& private_key_bytes) { // Construct EC_KEY from public and private key bytes. util::StatusOr> group = internal::EcGroupFromCurveType(curve); if (!group.ok()) { return group.status(); } internal::SslUniquePtr key(EC_KEY_new()); EC_KEY_set_group(key.get(), group->get()); util::StatusOr> public_key = internal::EcPointDecode(curve, subtle::EcPointFormat::UNCOMPRESSED, public_key_bytes); if (!public_key.ok()) { return public_key.status(); } if (!EC_KEY_set_public_key(key.get(), public_key->get())) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid public key: ", internal::GetSslErrors())); } util::StatusOr> priv_key = internal::StringToBignum(util::SecretDataAsStringView(private_key_bytes)); if (!priv_key.ok()) { return priv_key.status(); } if (!EC_KEY_set_private_key(key.get(), priv_key->get())) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid private key: ", internal::GetSslErrors())); } // Check that EC_KEY is valid. if (!EC_KEY_check_key(key.get())) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid EC key pair: ", internal::GetSslErrors())); } return util::OkStatus(); } util::Status ValidateX25519KeyPair(absl::string_view public_key_bytes, const util::SecretData& private_key_bytes) { util::StatusOr> x25519_key = internal::X25519KeyFromPrivateKey(private_key_bytes); if (!x25519_key.ok()) { return x25519_key.status(); } auto public_key_bytes_from_private = absl::string_view( reinterpret_cast((*x25519_key)->public_value), internal::X25519KeyPubKeySize()); if (public_key_bytes != public_key_bytes_from_private) { return util::Status( absl::StatusCode::kInvalidArgument, "X25519 private key does not match the specified X25519 public key."); } return util::OkStatus(); } util::Status ValidateKeyPair(const HpkePublicKey& public_key, const RestrictedData& private_key_bytes, PartialKeyAccessToken token) { HpkeParameters::KemId kem_id = public_key.GetParameters().GetKemId(); absl::string_view public_key_bytes = public_key.GetPublicKeyBytes(token); util::SecretData secret = util::SecretDataFromStringView( private_key_bytes.GetSecret(InsecureSecretKeyAccess::Get())); if (IsNistKem(kem_id)) { util::StatusOr curve = CurveTypeFromKemId(kem_id); if (!curve.ok()) { return curve.status(); } return ValidateNistEcKeyPair(*curve, public_key_bytes, secret); } return ValidateX25519KeyPair(public_key_bytes, secret); } } // namespace util::StatusOr HpkePrivateKey::Create( const HpkePublicKey& public_key, const RestrictedData& private_key_bytes, PartialKeyAccessToken token) { util::Status key_length_validation = ValidatePrivateKeyLength( public_key.GetParameters().GetKemId(), private_key_bytes.size()); if (!key_length_validation.ok()) { return key_length_validation; } util::Status key_pair_validation = ValidateKeyPair(public_key, private_key_bytes, token); if (!key_pair_validation.ok()) { return key_pair_validation; } return HpkePrivateKey(public_key, private_key_bytes); } bool HpkePrivateKey::operator==(const Key& other) const { const HpkePrivateKey* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (public_key_ != that->public_key_) { return false; } return private_key_bytes_ == that->private_key_bytes_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/hpke_private_key.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_HPKE_PRIVATE_KEY_H_ #define TINK_HYBRID_HPKE_PRIVATE_KEY_H_ #include "tink/hybrid/hpke_public_key.h" #include "tink/hybrid/hybrid_private_key.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Representation of the decryption function for an HPKE hybrid encryption // primitive. class HpkePrivateKey : public HybridPrivateKey { public: // Copyable and movable. HpkePrivateKey(const HpkePrivateKey& other) = default; HpkePrivateKey& operator=(const HpkePrivateKey& other) = default; HpkePrivateKey(HpkePrivateKey&& other) = default; HpkePrivateKey& operator=(HpkePrivateKey&& other) = default; // Creates a new HPKE private key from `private_key_bytes`. Returns an // error if `public_key` does not belong to the same key pair as // `private_key_bytes`. static util::StatusOr Create( const HpkePublicKey& public_key, const RestrictedData& private_key_bytes, PartialKeyAccessToken token); const RestrictedData& GetPrivateKeyBytes(PartialKeyAccessToken token) const { return private_key_bytes_; } const HpkePublicKey& GetPublicKey() const override { return public_key_; } bool operator==(const Key& other) const override; private: explicit HpkePrivateKey(const HpkePublicKey& public_key, const RestrictedData& private_key_bytes) : public_key_(public_key), private_key_bytes_(private_key_bytes) {} HpkePublicKey public_key_; RestrictedData private_key_bytes_; }; } // namespace tink } // namespace crypto #endif // TINK_HYBRID_HPKE_PRIVATE_KEY_H_ ================================================ FILE: cc/hybrid/hpke_private_key_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/hpke_private_key.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #include "openssl/ec_key.h" #endif #include "tink/hybrid/hpke_parameters.h" #include "tink/hybrid/hpke_public_key.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/ec_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/random.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { subtle::EllipticCurveType curve; HpkeParameters::KemId kem_id; HpkeParameters::KdfId kdf_id; HpkeParameters::AeadId aead_id; HpkeParameters::Variant variant; absl::optional id_requirement; std::string output_prefix; }; using HpkePrivateKeyTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( HpkePrivateKeyTestSuite, HpkePrivateKeyTest, Values(TestCase{subtle::EllipticCurveType::NIST_P256, HpkeParameters::KemId::kDhkemP256HkdfSha256, HpkeParameters::KdfId::kHkdfSha256, HpkeParameters::AeadId::kAesGcm128, HpkeParameters::Variant::kTink, /*id_requirement=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{subtle::EllipticCurveType::NIST_P384, HpkeParameters::KemId::kDhkemP384HkdfSha384, HpkeParameters::KdfId::kHkdfSha384, HpkeParameters::AeadId::kAesGcm256, HpkeParameters::Variant::kCrunchy, /*id_requirement=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{subtle::EllipticCurveType::NIST_P521, HpkeParameters::KemId::kDhkemP521HkdfSha512, HpkeParameters::KdfId::kHkdfSha512, HpkeParameters::AeadId::kChaCha20Poly1305, HpkeParameters::Variant::kNoPrefix, /*id_requirement=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(HpkePrivateKeyTest, CreateNistCurvePrivateKey) { TestCase test_case = GetParam(); util::StatusOr params = HpkeParameters::Builder() .SetVariant(test_case.variant) .SetKemId(test_case.kem_id) .SetKdfId(test_case.kdf_id) .SetAeadId(test_case.aead_id) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr ec_key = internal::NewEcKey(test_case.curve); ASSERT_THAT(ec_key, IsOk()); util::StatusOr> ec_point = internal::GetEcPoint(test_case.curve, ec_key->pub_x, ec_key->pub_y); ASSERT_THAT(ec_point, IsOk()); util::StatusOr public_key_bytes = internal::EcPointEncode( test_case.curve, subtle::EcPointFormat::UNCOMPRESSED, ec_point->get()); ASSERT_THAT(public_key_bytes, IsOk()); util::StatusOr public_key = HpkePublicKey::Create(*params, *public_key_bytes, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); RestrictedData private_key_bytes = RestrictedData(util::SecretDataAsStringView(ec_key->priv), InsecureSecretKeyAccess::Get()); util::StatusOr private_key = HpkePrivateKey::Create( *public_key, private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); EXPECT_THAT(private_key->GetParameters(), Eq(*params)); EXPECT_THAT(private_key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(private_key->GetPublicKey(), Eq(*public_key)); EXPECT_THAT(private_key->GetOutputPrefix(), Eq(test_case.output_prefix)); EXPECT_THAT(private_key->GetPrivateKeyBytes(GetPartialKeyAccess()), Eq(private_key_bytes)); } TEST(HpkePublicKeyTest, CreateX25519PublicKey) { util::StatusOr params = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kNoPrefix) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kChaCha20Poly1305) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr> x25519_key = internal::NewX25519Key(); ASSERT_THAT(x25519_key, IsOk()); std::string public_key_bytes = std::string(reinterpret_cast((*x25519_key)->public_value), internal::X25519KeyPubKeySize()); RestrictedData private_key_bytes = RestrictedData( std::string(reinterpret_cast((*x25519_key)->private_key), internal::X25519KeyPrivKeySize()), InsecureSecretKeyAccess::Get()); util::StatusOr public_key = HpkePublicKey::Create( *params, public_key_bytes, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = HpkePrivateKey::Create( *public_key, private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); EXPECT_THAT(private_key->GetParameters(), Eq(*params)); EXPECT_THAT(private_key->GetIdRequirement(), Eq(absl::nullopt)); EXPECT_THAT(private_key->GetPublicKey(), Eq(*public_key)); EXPECT_THAT(private_key->GetOutputPrefix(), Eq("")); EXPECT_THAT(private_key->GetPrivateKeyBytes(GetPartialKeyAccess()), Eq(private_key_bytes)); } TEST_P(HpkePrivateKeyTest, CreateMismatchedNistCurveKeyPairFails) { TestCase test_case = GetParam(); util::StatusOr params = HpkeParameters::Builder() .SetVariant(test_case.variant) .SetKemId(test_case.kem_id) .SetKdfId(test_case.kdf_id) .SetAeadId(test_case.aead_id) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr ec_key1 = internal::NewEcKey(test_case.curve); ASSERT_THAT(ec_key1, IsOk()); util::StatusOr> ec_point1 = internal::GetEcPoint(test_case.curve, ec_key1->pub_x, ec_key1->pub_y); ASSERT_THAT(ec_point1, IsOk()); util::StatusOr public_key_bytes1 = internal::EcPointEncode( test_case.curve, subtle::EcPointFormat::UNCOMPRESSED, ec_point1->get()); ASSERT_THAT(public_key_bytes1, IsOk()); util::StatusOr public_key1 = HpkePublicKey::Create(*params, *public_key_bytes1, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key1, IsOk()); util::StatusOr ec_key2 = internal::NewEcKey(test_case.curve); ASSERT_THAT(ec_key2, IsOk()); RestrictedData private_key_bytes2 = RestrictedData(util::SecretDataAsStringView(ec_key2->priv), InsecureSecretKeyAccess::Get()); EXPECT_THAT(HpkePrivateKey::Create(*public_key1, private_key_bytes2, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkePrivateKeyTest, CreateMismatchedX25519KeyPairFails) { util::StatusOr params = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kNoPrefix) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kChaCha20Poly1305) .Build(); ASSERT_THAT(params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = HpkePublicKey::Create( *params, public_key_bytes, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); RestrictedData private_key_bytes = RestrictedData( subtle::Random::GetRandomBytes(32), InsecureSecretKeyAccess::Get()); EXPECT_THAT(HpkePrivateKey::Create(*public_key, private_key_bytes, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(HpkePrivateKeyTest, CreateNistPrivateKeyWithInvalidKeyLengthFails) { TestCase test_case = GetParam(); util::StatusOr params = HpkeParameters::Builder() .SetVariant(test_case.variant) .SetKemId(test_case.kem_id) .SetKdfId(test_case.kdf_id) .SetAeadId(test_case.aead_id) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr ec_key = internal::NewEcKey(test_case.curve); ASSERT_THAT(ec_key, IsOk()); util::StatusOr> ec_point = internal::GetEcPoint(test_case.curve, ec_key->pub_x, ec_key->pub_y); ASSERT_THAT(ec_point, IsOk()); util::StatusOr public_key_bytes = internal::EcPointEncode( test_case.curve, subtle::EcPointFormat::UNCOMPRESSED, ec_point->get()); ASSERT_THAT(public_key_bytes, IsOk()); util::StatusOr public_key = HpkePublicKey::Create(*params, *public_key_bytes, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); absl::string_view private_key_input = util::SecretDataAsStringView(ec_key->priv); RestrictedData expanded_private_key_bytes = RestrictedData( absl::StrCat(absl::HexStringToBytes("00"), private_key_input), InsecureSecretKeyAccess::Get()); EXPECT_THAT(HpkePrivateKey::Create(*public_key, expanded_private_key_bytes, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkePrivateKeyTest, CreateX25519PrivateKeyWithInvalidKeyLengthFails) { util::StatusOr params = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kNoPrefix) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kChaCha20Poly1305) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr> x25519_key = internal::NewX25519Key(); ASSERT_THAT(x25519_key, IsOk()); std::string public_key_bytes = std::string(reinterpret_cast((*x25519_key)->public_value), internal::X25519KeyPubKeySize()); std::string private_key_input = std::string(reinterpret_cast((*x25519_key)->private_key), internal::X25519KeyPrivKeySize()); RestrictedData expanded_private_key_bytes = RestrictedData( absl::StrCat(absl::HexStringToBytes("00"), private_key_input), InsecureSecretKeyAccess::Get()); util::StatusOr public_key = HpkePublicKey::Create( *params, public_key_bytes, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); EXPECT_THAT(HpkePrivateKey::Create(*public_key, expanded_private_key_bytes, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(HpkePrivateKeyTest, NistCurvePrivateKeyEquals) { TestCase test_case = GetParam(); util::StatusOr params = HpkeParameters::Builder() .SetVariant(test_case.variant) .SetKemId(test_case.kem_id) .SetKdfId(test_case.kdf_id) .SetAeadId(test_case.aead_id) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr ec_key = internal::NewEcKey(test_case.curve); ASSERT_THAT(ec_key, IsOk()); util::StatusOr> ec_point = internal::GetEcPoint(test_case.curve, ec_key->pub_x, ec_key->pub_y); ASSERT_THAT(ec_point, IsOk()); util::StatusOr public_key_bytes = internal::EcPointEncode( test_case.curve, subtle::EcPointFormat::UNCOMPRESSED, ec_point->get()); ASSERT_THAT(public_key_bytes, IsOk()); RestrictedData private_key_bytes = RestrictedData(util::SecretDataAsStringView(ec_key->priv), InsecureSecretKeyAccess::Get()); util::StatusOr public_key = HpkePublicKey::Create(*params, *public_key_bytes, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = HpkePrivateKey::Create( *public_key, private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr other_private_key = HpkePrivateKey::Create( *public_key, private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); EXPECT_TRUE(*private_key == *other_private_key); EXPECT_TRUE(*other_private_key == *private_key); EXPECT_FALSE(*private_key != *other_private_key); EXPECT_FALSE(*other_private_key != *private_key); } TEST(HpkePrivateKeyTest, X25519PrivateKeyEquals) { util::StatusOr params = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kNoPrefix) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kChaCha20Poly1305) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr> x25519_key = internal::NewX25519Key(); ASSERT_THAT(x25519_key, IsOk()); std::string public_key_bytes = std::string(reinterpret_cast((*x25519_key)->public_value), internal::X25519KeyPubKeySize()); RestrictedData private_key_bytes = RestrictedData( std::string(reinterpret_cast((*x25519_key)->private_key), internal::X25519KeyPrivKeySize()), InsecureSecretKeyAccess::Get()); util::StatusOr public_key = HpkePublicKey::Create( *params, public_key_bytes, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = HpkePrivateKey::Create( *public_key, private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr other_private_key = HpkePrivateKey::Create( *public_key, private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); EXPECT_TRUE(*private_key == *other_private_key); EXPECT_TRUE(*other_private_key == *private_key); EXPECT_FALSE(*private_key != *other_private_key); EXPECT_FALSE(*other_private_key != *private_key); } TEST(HpkePrivateKeyTest, DifferentPublicKeyNotEqual) { util::StatusOr params = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kChaCha20Poly1305) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr> x25519_key = internal::NewX25519Key(); ASSERT_THAT(x25519_key, IsOk()); std::string public_key_bytes = std::string(reinterpret_cast((*x25519_key)->public_value), internal::X25519KeyPubKeySize()); RestrictedData private_key_bytes = RestrictedData( std::string(reinterpret_cast((*x25519_key)->private_key), internal::X25519KeyPrivKeySize()), InsecureSecretKeyAccess::Get()); util::StatusOr public_key123 = HpkePublicKey::Create(*params, public_key_bytes, /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(public_key123, IsOk()); util::StatusOr public_key456 = HpkePublicKey::Create(*params, public_key_bytes, /*id_requirement=*/456, GetPartialKeyAccess()); ASSERT_THAT(public_key456, IsOk()); util::StatusOr private_key = HpkePrivateKey::Create( *public_key123, private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr other_private_key = HpkePrivateKey::Create( *public_key456, private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(other_private_key, IsOk()); EXPECT_TRUE(*private_key != *other_private_key); EXPECT_TRUE(*other_private_key != *private_key); EXPECT_FALSE(*private_key == *other_private_key); EXPECT_FALSE(*other_private_key == *private_key); } TEST(HpkePrivateKeyTest, DifferentKeyTypesNotEqual) { util::StatusOr params = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kChaCha20Poly1305) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr> x25519_key = internal::NewX25519Key(); ASSERT_THAT(x25519_key, IsOk()); std::string public_key_bytes = std::string(reinterpret_cast((*x25519_key)->public_value), internal::X25519KeyPubKeySize()); RestrictedData private_key_bytes = RestrictedData( std::string(reinterpret_cast((*x25519_key)->private_key), internal::X25519KeyPrivKeySize()), InsecureSecretKeyAccess::Get()); util::StatusOr public_key = HpkePublicKey::Create(*params, public_key_bytes, /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = HpkePrivateKey::Create( *public_key, private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); EXPECT_TRUE(*private_key != *public_key); EXPECT_TRUE(*public_key != *private_key); EXPECT_FALSE(*private_key == *public_key); EXPECT_FALSE(*public_key == *private_key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/hpke_proto_serialization.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/hpke_proto_serialization.h" #include #include "absl/base/attributes.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/hybrid/hpke_parameters.h" #include "tink/hybrid/hpke_private_key.h" #include "tink/hybrid/hpke_public_key.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/key_parser.h" #include "tink/internal/key_serializer.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/parameters_parser.h" #include "tink/internal/parameters_serializer.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/secret_key_access_token.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/hpke.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::google::crypto::tink::HpkeAead; using ::google::crypto::tink::HpkeKdf; using ::google::crypto::tink::HpkeKem; using ::google::crypto::tink::HpkeKeyFormat; using ::google::crypto::tink::HpkeParams; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using HpkeProtoParametersParserImpl = internal::ParametersParserImpl; using HpkeProtoParametersSerializerImpl = internal::ParametersSerializerImpl; using HpkeProtoPublicKeyParserImpl = internal::KeyParserImpl; using HpkeProtoPublicKeySerializerImpl = internal::KeySerializerImpl; using HpkeProtoPrivateKeyParserImpl = internal::KeyParserImpl; using HpkeProtoPrivateKeySerializerImpl = internal::KeySerializerImpl; const absl::string_view kPublicTypeUrl = "type.googleapis.com/google.crypto.tink.HpkePublicKey"; const absl::string_view kPrivateTypeUrl = "type.googleapis.com/google.crypto.tink.HpkePrivateKey"; util::StatusOr ToVariant( OutputPrefixType output_prefix_type) { switch (output_prefix_type) { case OutputPrefixType::LEGACY: ABSL_FALLTHROUGH_INTENDED; // Parse LEGACY output prefix as CRUNCHY. case OutputPrefixType::CRUNCHY: return HpkeParameters::Variant::kCrunchy; case OutputPrefixType::RAW: return HpkeParameters::Variant::kNoPrefix; case OutputPrefixType::TINK: return HpkeParameters::Variant::kTink; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine HpkeParameters::Variant"); } } util::StatusOr ToOutputPrefixType( HpkeParameters::Variant variant) { switch (variant) { case HpkeParameters::Variant::kCrunchy: return OutputPrefixType::CRUNCHY; case HpkeParameters::Variant::kNoPrefix: return OutputPrefixType::RAW; case HpkeParameters::Variant::kTink: return OutputPrefixType::TINK; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine output prefix type."); } } util::StatusOr ToKemId(HpkeKem kem) { switch (kem) { case HpkeKem::DHKEM_P256_HKDF_SHA256: return HpkeParameters::KemId::kDhkemP256HkdfSha256; case HpkeKem::DHKEM_P384_HKDF_SHA384: return HpkeParameters::KemId::kDhkemP384HkdfSha384; case HpkeKem::DHKEM_P521_HKDF_SHA512: return HpkeParameters::KemId::kDhkemP521HkdfSha512; case HpkeKem::DHKEM_X25519_HKDF_SHA256: return HpkeParameters::KemId::kDhkemX25519HkdfSha256; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine KEM."); } } util::StatusOr FromKemId(HpkeParameters::KemId kem_id) { switch (kem_id) { case HpkeParameters::KemId::kDhkemP256HkdfSha256: return HpkeKem::DHKEM_P256_HKDF_SHA256; case HpkeParameters::KemId::kDhkemP384HkdfSha384: return HpkeKem::DHKEM_P384_HKDF_SHA384; case HpkeParameters::KemId::kDhkemP521HkdfSha512: return HpkeKem::DHKEM_P521_HKDF_SHA512; case HpkeParameters::KemId::kDhkemX25519HkdfSha256: return HpkeKem::DHKEM_X25519_HKDF_SHA256; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine KEM."); } } util::StatusOr ToKdfId(HpkeKdf kdf) { switch (kdf) { case HpkeKdf::HKDF_SHA256: return HpkeParameters::KdfId::kHkdfSha256; case HpkeKdf::HKDF_SHA384: return HpkeParameters::KdfId::kHkdfSha384; case HpkeKdf::HKDF_SHA512: return HpkeParameters::KdfId::kHkdfSha512; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine KDF."); } } util::StatusOr FromKdfId(HpkeParameters::KdfId kdf_id) { switch (kdf_id) { case HpkeParameters::KdfId::kHkdfSha256: return HpkeKdf::HKDF_SHA256; case HpkeParameters::KdfId::kHkdfSha384: return HpkeKdf::HKDF_SHA384; case HpkeParameters::KdfId::kHkdfSha512: return HpkeKdf::HKDF_SHA512; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine KDF."); } } util::StatusOr ToAeadId(HpkeAead aead) { switch (aead) { case HpkeAead::AES_128_GCM: return HpkeParameters::AeadId::kAesGcm128; case HpkeAead::AES_256_GCM: return HpkeParameters::AeadId::kAesGcm256; case HpkeAead::CHACHA20_POLY1305: return HpkeParameters::AeadId::kChaCha20Poly1305; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine AEAD."); } } util::StatusOr FromAeadId(HpkeParameters::AeadId aead_id) { switch (aead_id) { case HpkeParameters::AeadId::kAesGcm128: return HpkeAead::AES_128_GCM; case HpkeParameters::AeadId::kAesGcm256: return HpkeAead::AES_256_GCM; case HpkeParameters::AeadId::kChaCha20Poly1305: return HpkeAead::CHACHA20_POLY1305; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine AEAD."); } } util::StatusOr ToParameters(OutputPrefixType output_prefix_type, HpkeParams params) { util::StatusOr variant = ToVariant(output_prefix_type); if (!variant.ok()) { return variant.status(); } util::StatusOr kem_id = ToKemId(params.kem()); if (!kem_id.ok()) { return kem_id.status(); } util::StatusOr kdf_id = ToKdfId(params.kdf()); if (!kdf_id.ok()) { return kdf_id.status(); } util::StatusOr aead_id = ToAeadId(params.aead()); if (!aead_id.ok()) { return aead_id.status(); } return HpkeParameters::Builder() .SetVariant(*variant) .SetKemId(*kem_id) .SetKdfId(*kdf_id) .SetAeadId(*aead_id) .Build(); } util::StatusOr FromParameters(HpkeParameters parameters) { util::StatusOr kem = FromKemId(parameters.GetKemId()); if (!kem.ok()) { return kem.status(); } util::StatusOr kdf = FromKdfId(parameters.GetKdfId()); if (!kdf.ok()) { return kdf.status(); } util::StatusOr aead = FromAeadId(parameters.GetAeadId()); if (!aead.ok()) { return aead.status(); } HpkeParams params; params.set_kem(*kem); params.set_kdf(*kdf); params.set_aead(*aead); return params; } util::StatusOr ParseParameters( const internal::ProtoParametersSerialization& serialization) { if (serialization.GetKeyTemplate().type_url() != kPrivateTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing HpkeParameters."); } HpkeKeyFormat proto_key_format; if (!proto_key_format.ParseFromString( serialization.GetKeyTemplate().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse HpkeKeyFormat proto"); } if (!proto_key_format.has_params()) { return util::Status(absl::StatusCode::kInvalidArgument, "HpkeKeyFormat proto is missing params field."); } return ToParameters(serialization.GetKeyTemplate().output_prefix_type(), proto_key_format.params()); } util::StatusOr ParsePublicKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (serialization.TypeUrl() != kPublicTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing HpkePublicKey."); } google::crypto::tink::HpkePublicKey proto_key; const RestrictedData& restricted_data = serialization.SerializedKeyProto(); if (!proto_key.ParseFromString( restricted_data.GetSecret(InsecureSecretKeyAccess::Get()))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse HpkePublicKey proto"); } if (proto_key.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } util::StatusOr parameters = ToParameters(serialization.GetOutputPrefixType(), proto_key.params()); if (!parameters.ok()) { return parameters.status(); } return HpkePublicKey::Create(*parameters, proto_key.public_key(), serialization.IdRequirement(), GetPartialKeyAccess()); } util::StatusOr ParsePrivateKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (serialization.TypeUrl() != kPrivateTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing HpkePrivateKey."); } if (!token.has_value()) { return util::Status(absl::StatusCode::kPermissionDenied, "SecretKeyAccess is required"); } google::crypto::tink::HpkePrivateKey proto_key; const RestrictedData& restricted_data = serialization.SerializedKeyProto(); if (!proto_key.ParseFromString(restricted_data.GetSecret(*token))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse HpkePrivateKey proto"); } if (proto_key.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } util::StatusOr variant = ToVariant(serialization.GetOutputPrefixType()); if (!variant.ok()) { return variant.status(); } util::StatusOr parameters = ToParameters( serialization.GetOutputPrefixType(), proto_key.public_key().params()); if (!parameters.ok()) { return parameters.status(); } util::StatusOr public_key = HpkePublicKey::Create( *parameters, proto_key.public_key().public_key(), serialization.IdRequirement(), GetPartialKeyAccess()); if (!public_key.ok()) { return public_key.status(); } return HpkePrivateKey::Create(*public_key, RestrictedData(proto_key.private_key(), *token), GetPartialKeyAccess()); } util::StatusOr SerializeParameters( const HpkeParameters& parameters) { util::StatusOr output_prefix_type = ToOutputPrefixType(parameters.GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } util::StatusOr params = FromParameters(parameters); if (!params.ok()) { return params.status(); } HpkeKeyFormat proto_key_format; *proto_key_format.mutable_params() = *params; return internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, *output_prefix_type, proto_key_format.SerializeAsString()); } util::StatusOr SerializePublicKey( const HpkePublicKey& key, absl::optional token) { util::StatusOr params = FromParameters(key.GetParameters()); if (!params.ok()) { return params.status(); } google::crypto::tink::HpkePublicKey proto_key; proto_key.set_version(0); *proto_key.mutable_params() = *params; // OSS proto library complains if input is not converted to a string. proto_key.set_public_key( std::string(key.GetPublicKeyBytes(GetPartialKeyAccess()))); util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetParameters().GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } RestrictedData restricted_output = RestrictedData( proto_key.SerializeAsString(), InsecureSecretKeyAccess::Get()); return internal::ProtoKeySerialization::Create( kPublicTypeUrl, restricted_output, KeyData::ASYMMETRIC_PUBLIC, *output_prefix_type, key.GetIdRequirement()); } util::StatusOr SerializePrivateKey( const HpkePrivateKey& key, absl::optional token) { util::StatusOr restricted_input = key.GetPrivateKeyBytes(GetPartialKeyAccess()); if (!restricted_input.ok()) { return restricted_input.status(); } if (!token.has_value()) { return util::Status(absl::StatusCode::kPermissionDenied, "SecretKeyAccess is required"); } util::StatusOr params = FromParameters(key.GetPublicKey().GetParameters()); if (!params.ok()) { return params.status(); } google::crypto::tink::HpkePublicKey proto_public_key; proto_public_key.set_version(0); *proto_public_key.mutable_params() = *params; // OSS proto library complains if input is not converted to a string. proto_public_key.set_public_key( std::string(key.GetPublicKey().GetPublicKeyBytes(GetPartialKeyAccess()))); google::crypto::tink::HpkePrivateKey proto_private_key; proto_private_key.set_version(0); *proto_private_key.mutable_public_key() = proto_public_key; // OSS proto library complains if input is not converted to a string. proto_private_key.set_private_key( std::string(restricted_input->GetSecret(*token))); util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetPublicKey().GetParameters().GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } RestrictedData restricted_output = RestrictedData(proto_private_key.SerializeAsString(), *token); return internal::ProtoKeySerialization::Create( kPrivateTypeUrl, restricted_output, KeyData::ASYMMETRIC_PRIVATE, *output_prefix_type, key.GetIdRequirement()); } HpkeProtoParametersParserImpl* HpkeProtoParametersParser() { static auto* parser = new HpkeProtoParametersParserImpl(kPrivateTypeUrl, ParseParameters); return parser; } HpkeProtoParametersSerializerImpl* HpkeProtoParametersSerializer() { static auto* serializer = new HpkeProtoParametersSerializerImpl( kPrivateTypeUrl, SerializeParameters); return serializer; } HpkeProtoPublicKeyParserImpl* HpkeProtoPublicKeyParser() { static auto* parser = new HpkeProtoPublicKeyParserImpl(kPublicTypeUrl, ParsePublicKey); return parser; } HpkeProtoPublicKeySerializerImpl* HpkeProtoPublicKeySerializer() { static auto* serializer = new HpkeProtoPublicKeySerializerImpl(SerializePublicKey); return serializer; } HpkeProtoPrivateKeyParserImpl* HpkeProtoPrivateKeyParser() { static auto* parser = new HpkeProtoPrivateKeyParserImpl(kPrivateTypeUrl, ParsePrivateKey); return parser; } HpkeProtoPrivateKeySerializerImpl* HpkeProtoPrivateKeySerializer() { static auto* serializer = new HpkeProtoPrivateKeySerializerImpl(SerializePrivateKey); return serializer; } } // namespace util::Status RegisterHpkeProtoSerialization() { util::Status status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersParser(HpkeProtoParametersParser()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersSerializer(HpkeProtoParametersSerializer()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(HpkeProtoPublicKeyParser()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(HpkeProtoPublicKeySerializer()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(HpkeProtoPrivateKeyParser()); if (!status.ok()) { return status; } return internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(HpkeProtoPrivateKeySerializer()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/hpke_proto_serialization.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_HPKE_PROTO_SERIALIZATION_H_ #define TINK_HYBRID_HPKE_PROTO_SERIALIZATION_H_ #include "tink/util/status.h" namespace crypto { namespace tink { // Registers proto parsers and serializers for HPKE parameters and keys. crypto::tink::util::Status RegisterHpkeProtoSerialization(); } // namespace tink } // namespace crypto #endif // TINK_HYBRID_HPKE_PROTO_SERIALIZATION_H_ ================================================ FILE: cc/hybrid/hpke_proto_serialization_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/hpke_proto_serialization.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/util/secret_data.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #else #include "openssl/ec.h" #endif #include "tink/hybrid/hpke_parameters.h" #include "tink/hybrid/hpke_private_key.h" #include "tink/hybrid/hpke_public_key.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/ec_util.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/random.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/hpke.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::HpkeAead; using ::google::crypto::tink::HpkeKdf; using ::google::crypto::tink::HpkeKem; using ::google::crypto::tink::HpkeKeyFormat; using ::google::crypto::tink::HpkeParams; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::IsTrue; using ::testing::NotNull; using ::testing::TestWithParam; using ::testing::Values; const absl::string_view kPublicTypeUrl = "type.googleapis.com/google.crypto.tink.HpkePublicKey"; const absl::string_view kPrivateTypeUrl = "type.googleapis.com/google.crypto.tink.HpkePrivateKey"; struct TestCase { HpkeParameters::Variant variant; HpkeParameters::KemId kem_id; HpkeParameters::KdfId kdf_id; HpkeParameters::AeadId aead_id; OutputPrefixType output_prefix_type; HpkeKem kem; HpkeKdf kdf; HpkeAead aead; absl::optional id; std::string output_prefix; subtle::EllipticCurveType curve; }; class HpkeProtoSerializationTest : public TestWithParam { protected: void SetUp() override { internal::MutableSerializationRegistry::GlobalInstance().Reset(); } }; TEST_F(HpkeProtoSerializationTest, RegisterTwiceSucceeds) { ASSERT_THAT(RegisterHpkeProtoSerialization(), IsOk()); ASSERT_THAT(RegisterHpkeProtoSerialization(), IsOk()); } INSTANTIATE_TEST_SUITE_P( HpkeProtoSerializationTestSuite, HpkeProtoSerializationTest, Values(TestCase{HpkeParameters::Variant::kTink, HpkeParameters::KemId::kDhkemP256HkdfSha256, HpkeParameters::KdfId::kHkdfSha256, HpkeParameters::AeadId::kAesGcm128, OutputPrefixType::TINK, HpkeKem::DHKEM_P256_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM, /*id=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5), subtle::EllipticCurveType::NIST_P256}, TestCase{HpkeParameters::Variant::kCrunchy, HpkeParameters::KemId::kDhkemP384HkdfSha384, HpkeParameters::KdfId::kHkdfSha384, HpkeParameters::AeadId::kAesGcm256, OutputPrefixType::CRUNCHY, HpkeKem::DHKEM_P384_HKDF_SHA384, HpkeKdf::HKDF_SHA384, HpkeAead::AES_256_GCM, /*id=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5), subtle::EllipticCurveType::NIST_P384}, TestCase{HpkeParameters::Variant::kCrunchy, HpkeParameters::KemId::kDhkemP521HkdfSha512, HpkeParameters::KdfId::kHkdfSha512, HpkeParameters::AeadId::kAesGcm256, OutputPrefixType::CRUNCHY, HpkeKem::DHKEM_P521_HKDF_SHA512, HpkeKdf::HKDF_SHA512, HpkeAead::AES_256_GCM, /*id=*/0x07080910, /*output_prefix=*/std::string("\x00\x07\x08\x09\x10", 5), subtle::EllipticCurveType::NIST_P521}, TestCase{HpkeParameters::Variant::kNoPrefix, HpkeParameters::KemId::kDhkemX25519HkdfSha256, HpkeParameters::KdfId::kHkdfSha256, HpkeParameters::AeadId::kChaCha20Poly1305, OutputPrefixType::RAW, HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::CHACHA20_POLY1305, /*id=*/absl::nullopt, /*output_prefix=*/"", subtle::EllipticCurveType::CURVE25519})); TEST_P(HpkeProtoSerializationTest, ParseParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterHpkeProtoSerialization(), IsOk()); HpkeParams params; params.set_kem(test_case.kem); params.set_kdf(test_case.kdf); params.set_aead(test_case.aead); HpkeKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, test_case.output_prefix_type, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT((*parameters)->HasIdRequirement(), test_case.id.has_value()); const HpkeParameters* hpke_parameters = dynamic_cast(parameters->get()); ASSERT_THAT(hpke_parameters, NotNull()); EXPECT_THAT(hpke_parameters->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(hpke_parameters->GetKemId(), Eq(test_case.kem_id)); EXPECT_THAT(hpke_parameters->GetKdfId(), Eq(test_case.kdf_id)); EXPECT_THAT(hpke_parameters->GetAeadId(), Eq(test_case.aead_id)); } TEST_F(HpkeProtoSerializationTest, ParseLegacyAsCrunchy) { ASSERT_THAT(RegisterHpkeProtoSerialization(), IsOk()); HpkeParams params; params.set_kem(HpkeKem::DHKEM_X25519_HKDF_SHA256); params.set_kdf(HpkeKdf::HKDF_SHA256); params.set_aead(HpkeAead::CHACHA20_POLY1305); HpkeKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::LEGACY, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT((*parameters)->HasIdRequirement(), IsTrue()); const HpkeParameters* hpke_parameters = dynamic_cast(parameters->get()); ASSERT_THAT(hpke_parameters, NotNull()); EXPECT_THAT(hpke_parameters->GetVariant(), Eq(HpkeParameters::Variant::kCrunchy)); EXPECT_THAT(hpke_parameters->GetKemId(), Eq(HpkeParameters::KemId::kDhkemX25519HkdfSha256)); EXPECT_THAT(hpke_parameters->GetKdfId(), Eq(HpkeParameters::KdfId::kHkdfSha256)); EXPECT_THAT(hpke_parameters->GetAeadId(), Eq(HpkeParameters::AeadId::kChaCha20Poly1305)); } TEST_F(HpkeProtoSerializationTest, ParseParametersWithInvalidSerialization) { ASSERT_THAT(RegisterHpkeProtoSerialization(), IsOk()); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::RAW, "invalid_serialization"); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(HpkeProtoSerializationTest, ParseParametersWithUnkownOutputPrefix) { ASSERT_THAT(RegisterHpkeProtoSerialization(), IsOk()); HpkeParams params; params.set_kem(HpkeKem::DHKEM_X25519_HKDF_SHA256); params.set_kdf(HpkeKdf::HKDF_SHA256); params.set_aead(HpkeAead::CHACHA20_POLY1305); HpkeKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::UNKNOWN_PREFIX, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(HpkeProtoSerializationTest, ParseParametersWithUnkownKem) { ASSERT_THAT(RegisterHpkeProtoSerialization(), IsOk()); HpkeParams params; params.set_kem(HpkeKem::KEM_UNKNOWN); params.set_kdf(HpkeKdf::HKDF_SHA256); params.set_aead(HpkeAead::CHACHA20_POLY1305); HpkeKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(HpkeProtoSerializationTest, ParseParametersWithUnkownKdf) { ASSERT_THAT(RegisterHpkeProtoSerialization(), IsOk()); HpkeParams params; params.set_kem(HpkeKem::DHKEM_X25519_HKDF_SHA256); params.set_kdf(HpkeKdf::KDF_UNKNOWN); params.set_aead(HpkeAead::CHACHA20_POLY1305); HpkeKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(HpkeProtoSerializationTest, ParseParametersWithUnkownAead) { ASSERT_THAT(RegisterHpkeProtoSerialization(), IsOk()); HpkeParams params; params.set_kem(HpkeKem::DHKEM_X25519_HKDF_SHA256); params.set_kdf(HpkeKdf::HKDF_SHA256); params.set_aead(HpkeAead::AEAD_UNKNOWN); HpkeKeyFormat key_format_proto; *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(HpkeProtoSerializationTest, SerializeParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterHpkeProtoSerialization(), IsOk()); util::StatusOr parameters = HpkeParameters::Builder() .SetVariant(test_case.variant) .SetKemId(test_case.kem_id) .SetKdfId(test_case.kdf_id) .SetAeadId(test_case.aead_id) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( *parameters); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kPrivateTypeUrl)); const internal::ProtoParametersSerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->GetKeyTemplate().type_url(), Eq(kPrivateTypeUrl)); EXPECT_THAT(proto_serialization->GetKeyTemplate().output_prefix_type(), Eq(test_case.output_prefix_type)); HpkeKeyFormat key_format; ASSERT_THAT( key_format.ParseFromString(proto_serialization->GetKeyTemplate().value()), IsTrue()); ASSERT_THAT(key_format.has_params(), IsTrue()); EXPECT_THAT(key_format.params().kem(), Eq(test_case.kem)); EXPECT_THAT(key_format.params().kdf(), Eq(test_case.kdf)); EXPECT_THAT(key_format.params().aead(), Eq(test_case.aead)); } struct KeyPair { std::string public_key; std::string private_key; }; util::StatusOr GenerateKeyPair(subtle::EllipticCurveType curve) { if (curve == subtle::EllipticCurveType::CURVE25519) { util::StatusOr> x25519_key = internal::NewX25519Key(); if (!x25519_key.ok()) { return x25519_key.status(); } return KeyPair{ std::string(reinterpret_cast((*x25519_key)->public_value), internal::X25519KeyPubKeySize()), std::string(reinterpret_cast((*x25519_key)->private_key), internal::X25519KeyPrivKeySize())}; } util::StatusOr ec_key = internal::NewEcKey(curve); if (!ec_key.ok()) { return ec_key.status(); } util::StatusOr> ec_point = internal::GetEcPoint(curve, ec_key->pub_x, ec_key->pub_y); if (!ec_point.ok()) { return ec_point.status(); } util::StatusOr pub = internal::EcPointEncode( curve, subtle::EcPointFormat::UNCOMPRESSED, ec_point->get()); if (!pub.ok()) { return pub.status(); } return KeyPair{*pub, std::string(util::SecretDataAsStringView(ec_key->priv))}; } TEST_P(HpkeProtoSerializationTest, ParsePublicKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterHpkeProtoSerialization(), IsOk()); HpkeParams params; params.set_kem(test_case.kem); params.set_kdf(test_case.kdf); params.set_aead(test_case.aead); util::StatusOr key_pair = GenerateKeyPair(test_case.curve); ASSERT_THAT(key_pair, IsOk()); google::crypto::tink::HpkePublicKey key_proto; key_proto.set_version(0); key_proto.set_public_key(key_pair->public_key); *key_proto.mutable_params() = params; RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kPublicTypeUrl, serialized_key, KeyData::ASYMMETRIC_PUBLIC, test_case.output_prefix_type, test_case.id); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); ASSERT_THAT(key, IsOk()); EXPECT_THAT((*key)->GetIdRequirement(), Eq(test_case.id)); EXPECT_THAT((*key)->GetParameters().HasIdRequirement(), test_case.id.has_value()); util::StatusOr expected_parameters = HpkeParameters::Builder() .SetVariant(test_case.variant) .SetKemId(test_case.kem_id) .SetKdfId(test_case.kdf_id) .SetAeadId(test_case.aead_id) .Build(); ASSERT_THAT(expected_parameters, IsOk()); util::StatusOr expected_key = HpkePublicKey::Create(*expected_parameters, key_pair->public_key, test_case.id, GetPartialKeyAccess()); ASSERT_THAT(expected_key, IsOk()); EXPECT_THAT(**key, Eq(*expected_key)); } TEST_F(HpkeProtoSerializationTest, ParsePublicKeyWithInvalidSerialization) { ASSERT_THAT(RegisterHpkeProtoSerialization(), IsOk()); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPublicTypeUrl, serialized_key, KeyData::ASYMMETRIC_PUBLIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(HpkeProtoSerializationTest, ParsePublicKeyWithInvalidVersion) { ASSERT_THAT(RegisterHpkeProtoSerialization(), IsOk()); HpkeParams params; params.set_kem(HpkeKem::DHKEM_X25519_HKDF_SHA256); params.set_kdf(HpkeKdf::HKDF_SHA256); params.set_aead(HpkeAead::CHACHA20_POLY1305); util::StatusOr key_pair = GenerateKeyPair(subtle::EllipticCurveType::CURVE25519); ASSERT_THAT(key_pair, IsOk()); google::crypto::tink::HpkePublicKey key_proto; key_proto.set_version(1); key_proto.set_public_key(key_pair->public_key); *key_proto.mutable_params() = params; RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPublicTypeUrl, serialized_key, KeyData::ASYMMETRIC_PUBLIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(HpkeProtoSerializationTest, SerializePublicKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterHpkeProtoSerialization(), IsOk()); util::StatusOr parameters = HpkeParameters::Builder() .SetVariant(test_case.variant) .SetKemId(test_case.kem_id) .SetKdfId(test_case.kdf_id) .SetAeadId(test_case.aead_id) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr key_pair = GenerateKeyPair(test_case.curve); ASSERT_THAT(key_pair, IsOk()); util::StatusOr key = HpkePublicKey::Create( *parameters, key_pair->public_key, test_case.id, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, /*token=*/absl::nullopt); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kPublicTypeUrl)); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq(kPublicTypeUrl)); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::ASYMMETRIC_PUBLIC)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id)); google::crypto::tink::HpkePublicKey proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.version(), Eq(0)); EXPECT_THAT(proto_key.public_key(), Eq(key_pair->public_key)); EXPECT_THAT(proto_key.has_params(), IsTrue()); EXPECT_THAT(proto_key.params().kem(), Eq(test_case.kem)); EXPECT_THAT(proto_key.params().kdf(), Eq(test_case.kdf)); EXPECT_THAT(proto_key.params().aead(), Eq(test_case.aead)); } TEST_P(HpkeProtoSerializationTest, ParsePrivateKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterHpkeProtoSerialization(), IsOk()); HpkeParams params; params.set_kem(test_case.kem); params.set_kdf(test_case.kdf); params.set_aead(test_case.aead); util::StatusOr key_pair = GenerateKeyPair(test_case.curve); ASSERT_THAT(key_pair, IsOk()); google::crypto::tink::HpkePublicKey public_key_proto; public_key_proto.set_version(0); *public_key_proto.mutable_params() = params; public_key_proto.set_public_key(key_pair->public_key); google::crypto::tink::HpkePrivateKey private_key_proto; private_key_proto.set_version(0); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_private_key(key_pair->private_key); RestrictedData serialized_key = RestrictedData( private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, test_case.output_prefix_type, test_case.id); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); EXPECT_THAT((*key)->GetIdRequirement(), Eq(test_case.id)); EXPECT_THAT((*key)->GetParameters().HasIdRequirement(), test_case.id.has_value()); util::StatusOr expected_parameters = HpkeParameters::Builder() .SetVariant(test_case.variant) .SetKemId(test_case.kem_id) .SetKdfId(test_case.kdf_id) .SetAeadId(test_case.aead_id) .Build(); ASSERT_THAT(expected_parameters, IsOk()); util::StatusOr expected_public_key = HpkePublicKey::Create(*expected_parameters, key_pair->public_key, test_case.id, GetPartialKeyAccess()); ASSERT_THAT(expected_public_key, IsOk()); util::StatusOr expected_private_key = HpkePrivateKey::Create( *expected_public_key, RestrictedData(key_pair->private_key, InsecureSecretKeyAccess::Get()), GetPartialKeyAccess()); EXPECT_THAT(**key, Eq(*expected_private_key)); } TEST_F(HpkeProtoSerializationTest, ParsePrivateKeyWithInvalidSerialization) { ASSERT_THAT(RegisterHpkeProtoSerialization(), IsOk()); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(HpkeProtoSerializationTest, ParsePrivateKeyWithInvalidVersion) { ASSERT_THAT(RegisterHpkeProtoSerialization(), IsOk()); HpkeParams params; params.set_kem(HpkeKem::DHKEM_X25519_HKDF_SHA256); params.set_kdf(HpkeKdf::HKDF_SHA256); params.set_aead(HpkeAead::CHACHA20_POLY1305); util::StatusOr key_pair = GenerateKeyPair(subtle::EllipticCurveType::CURVE25519); ASSERT_THAT(key_pair, IsOk()); google::crypto::tink::HpkePublicKey public_key_proto; public_key_proto.set_version(0); *public_key_proto.mutable_params() = params; public_key_proto.set_public_key(key_pair->public_key); google::crypto::tink::HpkePrivateKey private_key_proto; private_key_proto.set_version(1); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_private_key(key_pair->private_key); RestrictedData serialized_key = RestrictedData( private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(HpkeProtoSerializationTest, ParsePrivateKeyNoSecretKeyAccess) { ASSERT_THAT(RegisterHpkeProtoSerialization(), IsOk()); HpkeParams params; params.set_kem(HpkeKem::DHKEM_X25519_HKDF_SHA256); params.set_kdf(HpkeKdf::HKDF_SHA256); params.set_aead(HpkeAead::CHACHA20_POLY1305); util::StatusOr key_pair = GenerateKeyPair(subtle::EllipticCurveType::CURVE25519); ASSERT_THAT(key_pair, IsOk()); google::crypto::tink::HpkePublicKey public_key_proto; public_key_proto.set_version(0); *public_key_proto.mutable_params() = params; public_key_proto.set_public_key(key_pair->public_key); google::crypto::tink::HpkePrivateKey private_key_proto; private_key_proto.set_version(0); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_private_key(key_pair->private_key); RestrictedData serialized_key = RestrictedData( private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kPermissionDenied)); } TEST_P(HpkeProtoSerializationTest, SerializePrivateKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterHpkeProtoSerialization(), IsOk()); util::StatusOr parameters = HpkeParameters::Builder() .SetVariant(test_case.variant) .SetKemId(test_case.kem_id) .SetKdfId(test_case.kdf_id) .SetAeadId(test_case.aead_id) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr key_pair = GenerateKeyPair(test_case.curve); ASSERT_THAT(key_pair, IsOk()); util::StatusOr public_key = HpkePublicKey::Create( *parameters, key_pair->public_key, test_case.id, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = HpkePrivateKey::Create( *public_key, RestrictedData(key_pair->private_key, InsecureSecretKeyAccess::Get()), GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *private_key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kPrivateTypeUrl)); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq(kPrivateTypeUrl)); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::ASYMMETRIC_PRIVATE)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id)); google::crypto::tink::HpkePrivateKey proto_key; // OSS proto library complains if input is not converted to a string. ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.version(), Eq(0)); EXPECT_THAT(proto_key.private_key(), Eq(key_pair->private_key)); EXPECT_THAT(proto_key.has_public_key(), IsTrue()); EXPECT_THAT(proto_key.public_key().version(), Eq(0)); EXPECT_THAT(proto_key.public_key().has_params(), IsTrue()); EXPECT_THAT(proto_key.public_key().params().kem(), Eq(test_case.kem)); EXPECT_THAT(proto_key.public_key().params().kdf(), Eq(test_case.kdf)); EXPECT_THAT(proto_key.public_key().params().aead(), Eq(test_case.aead)); EXPECT_THAT(proto_key.public_key().public_key(), Eq(key_pair->public_key)); } TEST_F(HpkeProtoSerializationTest, SerializePrivateKeyNoSecretKeyAccess) { ASSERT_THAT(RegisterHpkeProtoSerialization(), IsOk()); util::StatusOr parameters = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kNoPrefix) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kAesGcm256) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr key_pair = GenerateKeyPair(subtle::EllipticCurveType::CURVE25519); ASSERT_THAT(key_pair, IsOk()); util::StatusOr public_key = HpkePublicKey::Create( *parameters, key_pair->public_key, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = HpkePrivateKey::Create( *public_key, RestrictedData(key_pair->private_key, InsecureSecretKeyAccess::Get()), GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *private_key, /*token=*/absl::nullopt); ASSERT_THAT(serialization.status(), StatusIs(absl::StatusCode::kPermissionDenied)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/hpke_public_key.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/hpke_public_key.h" #include #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/hybrid/hpke_parameters.h" #include "tink/internal/ec_util.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { util::Status ValidatePublicKey(HpkeParameters::KemId kem_id, absl::string_view public_key_bytes) { int expected_length; subtle::EllipticCurveType curve; switch (kem_id) { // Key lengths from 'Npk' column in // https://www.rfc-editor.org/rfc/rfc9180.html#table-2. case HpkeParameters::KemId::kDhkemP256HkdfSha256: curve = subtle::EllipticCurveType::NIST_P256; expected_length = 65; break; case HpkeParameters::KemId::kDhkemP384HkdfSha384: curve = subtle::EllipticCurveType::NIST_P384; expected_length = 97; break; case HpkeParameters::KemId::kDhkemP521HkdfSha512: curve = subtle::EllipticCurveType::NIST_P521; expected_length = 133; break; case HpkeParameters::KemId::kDhkemX25519HkdfSha256: curve = subtle::EllipticCurveType::CURVE25519; expected_length = 32; break; default: return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Unknown KEM ID: ", kem_id)); } // Validate key length. if (expected_length != public_key_bytes.length()) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrFormat( "Invalid public key length for KEM %d (expected %d, got %d)", kem_id, expected_length, public_key_bytes.length())); } // Validate that NIST curve public point is actually on the specified curve. // // NOTE: `EcPointDecode()` verifies that the point is on the curve via // `SslGetEcPointFromEncoded()` for the uncompressed point format. if (curve != subtle::EllipticCurveType::CURVE25519) { util::Status decode_status = internal::EcPointDecode(curve, subtle::EcPointFormat::UNCOMPRESSED, public_key_bytes) .status(); if (!decode_status.ok()) { return decode_status; } } return util::OkStatus(); } util::StatusOr ComputeOutputPrefix( const HpkeParameters& parameters, absl::optional id_requirement) { switch (parameters.GetVariant()) { case HpkeParameters::Variant::kNoPrefix: return std::string(""); // Empty prefix. case HpkeParameters::Variant::kCrunchy: if (!id_requirement.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "ID requirement must have value with kCrunchy"); } return absl::StrCat(absl::HexStringToBytes("00"), subtle::BigEndian32(*id_requirement)); case HpkeParameters::Variant::kTink: if (!id_requirement.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "ID requirement must have value with kTink"); } return absl::StrCat(absl::HexStringToBytes("01"), subtle::BigEndian32(*id_requirement)); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid variant: ", parameters.GetVariant())); } } } // namespace util::StatusOr HpkePublicKey::Create( const HpkeParameters& parameters, absl::string_view public_key_bytes, absl::optional id_requirement, PartialKeyAccessToken token) { if (parameters.HasIdRequirement() && !id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key without ID requirement with parameters with ID " "requirement"); } if (!parameters.HasIdRequirement() && id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key with ID requirement with parameters without ID " "requirement"); } util::Status validation = ValidatePublicKey(parameters.GetKemId(), public_key_bytes); if (!validation.ok()) { return validation; } util::StatusOr output_prefix = ComputeOutputPrefix(parameters, id_requirement); if (!output_prefix.ok()) { return output_prefix.status(); } return HpkePublicKey(parameters, public_key_bytes, id_requirement, *output_prefix); } bool HpkePublicKey::operator==(const Key& other) const { const HpkePublicKey* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (GetParameters() != that->GetParameters()) { return false; } if (id_requirement_ != that->id_requirement_) { return false; } return public_key_bytes_ == that->public_key_bytes_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/hpke_public_key.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_HPKE_PUBLIC_KEY_H_ #define TINK_HYBRID_HPKE_PUBLIC_KEY_H_ #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/hybrid/hpke_parameters.h" #include "tink/hybrid/hybrid_public_key.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Representation of the encryption function for an HPKE hybrid encryption // primitive. class HpkePublicKey : public HybridPublicKey { public: // Copyable and movable. HpkePublicKey(const HpkePublicKey& other) = default; HpkePublicKey& operator=(const HpkePublicKey& other) = default; HpkePublicKey(HpkePublicKey&& other) = default; HpkePublicKey& operator=(HpkePublicKey&& other) = default; // Creates a new HPKE public key from `public_key_bytes`. If `parameters` // specify a variant that uses a prefix, then `id_requirement` is used to // compute this prefix. static util::StatusOr Create( const HpkeParameters& parameters, absl::string_view public_key_bytes, absl::optional id_requirement, PartialKeyAccessToken token); absl::string_view GetPublicKeyBytes(PartialKeyAccessToken token) const { return public_key_bytes_; } absl::string_view GetOutputPrefix() const override { return output_prefix_; } const HpkeParameters& GetParameters() const override { return parameters_; } absl::optional GetIdRequirement() const override { return id_requirement_; } bool operator==(const Key& other) const override; private: explicit HpkePublicKey(const HpkeParameters& parameters, absl::string_view public_key_bytes, absl::optional id_requirement, absl::string_view output_prefix) : parameters_(parameters), public_key_bytes_(public_key_bytes), id_requirement_(id_requirement), output_prefix_(output_prefix) {} HpkeParameters parameters_; std::string public_key_bytes_; absl::optional id_requirement_; std::string output_prefix_; }; } // namespace tink } // namespace crypto #endif // TINK_HYBRID_HPKE_PUBLIC_KEY_H_ ================================================ FILE: cc/hybrid/hpke_public_key_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/hpke_public_key.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/types/optional.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #endif #include "tink/hybrid/hpke_parameters.h" #include "tink/internal/ec_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/partial_key_access.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/random.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { subtle::EllipticCurveType curve; HpkeParameters::KemId kem_id; HpkeParameters::KdfId kdf_id; HpkeParameters::AeadId aead_id; HpkeParameters::Variant variant; absl::optional id_requirement; std::string output_prefix; }; using HpkePublicKeyTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( HpkePublicKeyTestSuite, HpkePublicKeyTest, Values(TestCase{subtle::EllipticCurveType::NIST_P256, HpkeParameters::KemId::kDhkemP256HkdfSha256, HpkeParameters::KdfId::kHkdfSha256, HpkeParameters::AeadId::kAesGcm128, HpkeParameters::Variant::kTink, /*id_requirement=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{subtle::EllipticCurveType::NIST_P384, HpkeParameters::KemId::kDhkemP384HkdfSha384, HpkeParameters::KdfId::kHkdfSha384, HpkeParameters::AeadId::kAesGcm256, HpkeParameters::Variant::kCrunchy, /*id_requirement=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{subtle::EllipticCurveType::NIST_P521, HpkeParameters::KemId::kDhkemP521HkdfSha512, HpkeParameters::KdfId::kHkdfSha512, HpkeParameters::AeadId::kChaCha20Poly1305, HpkeParameters::Variant::kNoPrefix, /*id_requirement=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(HpkePublicKeyTest, CreateNistCurvePublicKey) { TestCase test_case = GetParam(); util::StatusOr params = HpkeParameters::Builder() .SetVariant(test_case.variant) .SetKemId(test_case.kem_id) .SetKdfId(test_case.kdf_id) .SetAeadId(test_case.aead_id) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr ec_key = internal::NewEcKey(test_case.curve); ASSERT_THAT(ec_key, IsOk()); util::StatusOr> ec_point = internal::GetEcPoint(test_case.curve, ec_key->pub_x, ec_key->pub_y); ASSERT_THAT(ec_point, IsOk()); util::StatusOr public_key_bytes = internal::EcPointEncode( test_case.curve, subtle::EcPointFormat::UNCOMPRESSED, ec_point->get()); ASSERT_THAT(public_key_bytes, IsOk()); util::StatusOr public_key = HpkePublicKey::Create(*params, *public_key_bytes, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); EXPECT_THAT(public_key->GetParameters(), Eq(*params)); EXPECT_THAT(public_key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(public_key->GetOutputPrefix(), Eq(test_case.output_prefix)); EXPECT_THAT(public_key->GetPublicKeyBytes(GetPartialKeyAccess()), Eq(*public_key_bytes)); } TEST(HpkePublicKeyTest, CreateX25519PublicKey) { util::StatusOr params = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kNoPrefix) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kChaCha20Poly1305) .Build(); ASSERT_THAT(params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = HpkePublicKey::Create( *params, public_key_bytes, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); EXPECT_THAT(public_key->GetParameters(), Eq(*params)); EXPECT_THAT(public_key->GetIdRequirement(), Eq(absl::nullopt)); EXPECT_THAT(public_key->GetOutputPrefix(), Eq("")); EXPECT_THAT(public_key->GetPublicKeyBytes(GetPartialKeyAccess()), Eq(public_key_bytes)); } TEST_P(HpkePublicKeyTest, CreateNistCurvePublicKeyWithInvalidLength) { TestCase test_case = GetParam(); util::StatusOr params = HpkeParameters::Builder() .SetVariant(test_case.variant) .SetKemId(test_case.kem_id) .SetKdfId(test_case.kdf_id) .SetAeadId(test_case.aead_id) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr ec_key = internal::NewEcKey(test_case.curve); ASSERT_THAT(ec_key, IsOk()); util::StatusOr> ec_point = internal::GetEcPoint(test_case.curve, ec_key->pub_x, ec_key->pub_y); ASSERT_THAT(ec_point, IsOk()); util::StatusOr public_key_bytes = internal::EcPointEncode( test_case.curve, subtle::EcPointFormat::UNCOMPRESSED, ec_point->get()); ASSERT_THAT(public_key_bytes, IsOk()); util::StatusOr public_key = HpkePublicKey::Create( *params, public_key_bytes->substr(0, public_key_bytes->size() - 1), test_case.id_requirement, GetPartialKeyAccess()); EXPECT_THAT(public_key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkePublicKeyTest, CreateX25519PublicKeyWithInvalidLength) { util::StatusOr params = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kNoPrefix) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kChaCha20Poly1305) .Build(); ASSERT_THAT(params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = HpkePublicKey::Create( *params, public_key_bytes.substr(0, public_key_bytes.size() - 1), /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); EXPECT_THAT(public_key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkePublicKeyTest, CreateNistCurvePublicKeyWithInvalidPoint) { // Copied from "public point not on curve" Wycheproof test case in // https://github.com/google/wycheproof/blob/master/testvectors/ecdh_secp256k1_test.json. std::string invalid_point = absl::HexStringToBytes( "3056301006072a8648ce3d020106052b8104000a0342000449c248edc659e18482b71057" "48a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d" "7a9a7063286bbd16ef64c65f546757e4"); util::StatusOr point_size = internal::EcPointEncodingSizeInBytes(subtle::EllipticCurveType::NIST_P256, subtle::EcPointFormat::UNCOMPRESSED); ASSERT_THAT(point_size, IsOk()); ASSERT_THAT(*point_size, testing::Lt(invalid_point.size())); std::string public_key_bytes = invalid_point.substr(invalid_point.size() - *point_size, *point_size); // Uncompressed point format starts with a 0x04-byte. ASSERT_THAT(public_key_bytes[0], Eq(0x04)); util::StatusOr params = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kNoPrefix) .SetKemId(HpkeParameters::KemId::kDhkemP256HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kAesGcm128) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr public_key = HpkePublicKey::Create( *params, public_key_bytes, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); EXPECT_THAT(public_key.status(), StatusIs(absl::StatusCode::kInternal)); } TEST(HpkePublicKeyTest, CreatePublicKeyWithInvalidIdRequirementFails) { util::StatusOr no_prefix_params = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kNoPrefix) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kChaCha20Poly1305) .Build(); ASSERT_THAT(no_prefix_params, IsOk()); util::StatusOr tink_params = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kChaCha20Poly1305) .Build(); ASSERT_THAT(tink_params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); EXPECT_THAT( HpkePublicKey::Create(*no_prefix_params, public_key_bytes, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(HpkePublicKey::Create(*tink_params, public_key_bytes, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(HpkePublicKeyTest, NistCurvePublicKeyEquals) { TestCase test_case = GetParam(); util::StatusOr params = HpkeParameters::Builder() .SetVariant(test_case.variant) .SetKemId(test_case.kem_id) .SetKdfId(test_case.kdf_id) .SetAeadId(test_case.aead_id) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr ec_key = internal::NewEcKey(test_case.curve); ASSERT_THAT(ec_key, IsOk()); util::StatusOr> ec_point = internal::GetEcPoint(test_case.curve, ec_key->pub_x, ec_key->pub_y); ASSERT_THAT(ec_point, IsOk()); util::StatusOr public_key_bytes = internal::EcPointEncode( test_case.curve, subtle::EcPointFormat::UNCOMPRESSED, ec_point->get()); ASSERT_THAT(public_key_bytes, IsOk()); util::StatusOr public_key = HpkePublicKey::Create(*params, *public_key_bytes, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = HpkePublicKey::Create(*params, *public_key_bytes, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key == *other_public_key); EXPECT_TRUE(*other_public_key == *public_key); EXPECT_FALSE(*public_key != *other_public_key); EXPECT_FALSE(*other_public_key != *public_key); } TEST(HpkePublicKeyTest, X25519PublicKeyEquals) { util::StatusOr params = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kNoPrefix) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kChaCha20Poly1305) .Build(); ASSERT_THAT(params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = HpkePublicKey::Create( *params, public_key_bytes, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = HpkePublicKey::Create( *params, public_key_bytes, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key == *other_public_key); EXPECT_TRUE(*other_public_key == *public_key); EXPECT_FALSE(*public_key != *other_public_key); EXPECT_FALSE(*other_public_key != *public_key); } TEST(HpkePublicKeyTest, DifferentVariantNotEqual) { util::StatusOr crunchy_params = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kCrunchy) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kChaCha20Poly1305) .Build(); ASSERT_THAT(crunchy_params, IsOk()); util::StatusOr tink_params = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kChaCha20Poly1305) .Build(); ASSERT_THAT(tink_params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = HpkePublicKey::Create( *crunchy_params, public_key_bytes, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = HpkePublicKey::Create( *tink_params, public_key_bytes, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key != *other_public_key); EXPECT_TRUE(*other_public_key != *public_key); EXPECT_FALSE(*public_key == *other_public_key); EXPECT_FALSE(*other_public_key == *public_key); } TEST(HpkePublicKeyTest, DifferentPublicKeyBytesNotEqual) { util::StatusOr params = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kChaCha20Poly1305) .Build(); ASSERT_THAT(params, IsOk()); std::string public_key_bytes1 = subtle::Random::GetRandomBytes(32); std::string public_key_bytes2 = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = HpkePublicKey::Create( *params, public_key_bytes1, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = HpkePublicKey::Create( *params, public_key_bytes2, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key != *other_public_key); EXPECT_TRUE(*other_public_key != *public_key); EXPECT_FALSE(*public_key == *other_public_key); EXPECT_FALSE(*other_public_key == *public_key); } TEST(HpkePublicKeyTest, DifferentIdRequirementNotEqual) { util::StatusOr params = HpkeParameters::Builder() .SetVariant(HpkeParameters::Variant::kTink) .SetKemId(HpkeParameters::KemId::kDhkemX25519HkdfSha256) .SetKdfId(HpkeParameters::KdfId::kHkdfSha256) .SetAeadId(HpkeParameters::AeadId::kChaCha20Poly1305) .Build(); ASSERT_THAT(params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = HpkePublicKey::Create( *params, public_key_bytes, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = HpkePublicKey::Create( *params, public_key_bytes, /*id_requirement=*/0x02030405, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key != *other_public_key); EXPECT_TRUE(*other_public_key != *public_key); EXPECT_FALSE(*public_key == *other_public_key); EXPECT_FALSE(*other_public_key == *public_key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/hybrid_config.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/hybrid_config.h" #include "absl/memory/memory.h" #include "tink/aead/aead_config.h" #include "tink/config/tink_fips.h" #include "tink/hybrid/ecies_aead_hkdf_private_key_manager.h" #include "tink/hybrid/ecies_aead_hkdf_public_key_manager.h" #include "tink/hybrid/ecies_proto_serialization.h" #include "tink/hybrid/hybrid_decrypt_wrapper.h" #include "tink/hybrid/hybrid_encrypt_wrapper.h" #include "tink/registry.h" #include "tink/util/status.h" #include "proto/config.pb.h" namespace crypto { namespace tink { // static util::Status HybridConfig::Register() { auto status = AeadConfig::Register(); if (!status.ok()) { return status; } // Register primitive wrappers. status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) { return status; } status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) { return status; } // Currently there are no hybrid encryption key managers which only use // FIPS-validated implementations, therefore none will be registered in // FIPS only mode. if (IsFipsModeEnabled()) { return util::OkStatus(); } // Register non-FIPS key managers. status = Registry::RegisterAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), true); if (!status.ok()) { return status; } return RegisterEciesProtoSerialization(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/hybrid_config.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_HYBRID_CONFIG_H_ #define TINK_HYBRID_HYBRID_CONFIG_H_ #include "absl/base/macros.h" #include "tink/util/status.h" #include "proto/config.pb.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Static methods and constants for registering with the Registry // all instances of hybrid encryption key types supported in a particular // release of Tink, i.e. key types that correspond to primitives // HybridEncrypt and HybridDecrypt. // // To register all hybrid encryption key types from the current Tink release // one can do: // // auto status = HybridConfig::Register(); // class HybridConfig { public: // Registers HybridEncrypt and HybridDecrypt primitive wrappers, and key // managers for all implementations of HybridEncrypt and HybridDecrypt from // the current Tink release. static crypto::tink::util::Status Register(); private: HybridConfig() {} }; } // namespace tink } // namespace crypto #endif // TINK_HYBRID_HYBRID_CONFIG_H_ ================================================ FILE: cc/hybrid/hybrid_config_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/hybrid_config.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/types/optional.h" #include "tink/config/global_registry.h" #include "tink/crypto_format.h" #include "tink/hybrid/ecies_aead_hkdf_private_key_manager.h" #include "tink/hybrid/ecies_aead_hkdf_public_key_manager.h" #include "tink/hybrid/ecies_parameters.h" #include "tink/hybrid/ecies_private_key.h" #include "tink/hybrid/ecies_public_key.h" #include "tink/hybrid/hybrid_key_templates.h" #include "tink/hybrid_decrypt.h" #include "tink/hybrid_encrypt.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/ec_util.h" #include "tink/internal/fips_utils.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/keyset_handle.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/primitive_set.h" #include "tink/registry.h" #include "tink/restricted_data.h" #include "tink/subtle/random.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_gcm.pb.h" #include "proto/common.pb.h" #include "proto/ecies_aead_hkdf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::DummyHybridDecrypt; using ::crypto::tink::test::DummyHybridEncrypt; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::AesGcmKeyFormat; using ::google::crypto::tink::EciesAeadDemParams; using ::google::crypto::tink::EciesAeadHkdfParams; using ::google::crypto::tink::EciesAeadHkdfPrivateKey; using ::google::crypto::tink::EciesAeadHkdfPublicKey; using ::google::crypto::tink::EciesHkdfKemParams; using ::google::crypto::tink::EcPointFormat; using ::google::crypto::tink::EllipticCurveType; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::OutputPrefixType; class HybridConfigTest : public ::testing::Test { protected: void SetUp() override { Registry::Reset(); internal::MutableSerializationRegistry::GlobalInstance().Reset(); } }; TEST_F(HybridConfigTest, Basic) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT(Registry::get_key_manager( EciesAeadHkdfPrivateKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT(Registry::get_key_manager( EciesAeadHkdfPublicKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT(HybridConfig::Register(), IsOk()); EXPECT_THAT(Registry::get_key_manager( EciesAeadHkdfPrivateKeyManager().get_key_type()) .status(), IsOk()); EXPECT_THAT(Registry::get_key_manager( EciesAeadHkdfPublicKeyManager().get_key_type()) .status(), IsOk()); } // Tests that the HybridEncryptWrapper has been properly registered and we // can wrap primitives. TEST_F(HybridConfigTest, EncryptWrapperRegistered) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } ASSERT_TRUE(HybridConfig::Register().ok()); google::crypto::tink::KeysetInfo::KeyInfo key_info; key_info.set_status(google::crypto::tink::KeyStatusType::ENABLED); key_info.set_key_id(1234); key_info.set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); auto primitive_set = absl::make_unique>(); ASSERT_THAT( primitive_set->set_primary( primitive_set ->AddPrimitive(absl::make_unique("dummy"), key_info) .value()), IsOk()); auto wrapped = Registry::Wrap(std::move(primitive_set)); ASSERT_TRUE(wrapped.ok()) << wrapped.status(); auto encryption_result = wrapped.value()->Encrypt("secret", ""); ASSERT_TRUE(encryption_result.ok()); std::string prefix = CryptoFormat::GetOutputPrefix(key_info).value(); EXPECT_EQ( encryption_result.value(), absl::StrCat(prefix, DummyHybridEncrypt("dummy").Encrypt("secret", "").value())); } // Tests that the HybridDecryptWrapper has been properly registered and we // can wrap primitives. TEST_F(HybridConfigTest, DecryptWrapperRegistered) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } ASSERT_TRUE(HybridConfig::Register().ok()); google::crypto::tink::KeysetInfo::KeyInfo key_info; key_info.set_status(google::crypto::tink::KeyStatusType::ENABLED); key_info.set_key_id(1234); key_info.set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); auto primitive_set = absl::make_unique>(); ASSERT_THAT( primitive_set->set_primary( primitive_set ->AddPrimitive(absl::make_unique("dummy"), key_info) .value()), IsOk()); auto wrapped = Registry::Wrap(std::move(primitive_set)); ASSERT_TRUE(wrapped.ok()) << wrapped.status(); std::string prefix = CryptoFormat::GetOutputPrefix(key_info).value(); std::string encryption = DummyHybridEncrypt("dummy").Encrypt("secret", "").value(); ASSERT_EQ( wrapped.value()->Decrypt(absl::StrCat(prefix, encryption), "").value(), "secret"); } TEST_F(HybridConfigTest, EciesProtoParamsSerializationRegistered) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::StatusOr proto_params_serialization = internal::ProtoParametersSerialization::Create( HybridKeyTemplates::EciesX25519HkdfHmacSha256Aes256Gcm()); ASSERT_THAT(proto_params_serialization, IsOk()); util::StatusOr> parsed_params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr params = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kX25519) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256GcmRaw) .SetVariant(EciesParameters::Variant::kTink) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr> serialized_params = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params.status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(HybridConfig::Register(), IsOk()); util::StatusOr> parsed_params2 = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params2, IsOk()); util::StatusOr> serialized_params2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params2, IsOk()); } EciesAeadHkdfParams CreateParams() { EciesHkdfKemParams kem_params; kem_params.set_curve_type(EllipticCurveType::CURVE25519); kem_params.set_hkdf_hash_type(HashType::SHA256); EciesAeadDemParams dem_params; AesGcmKeyFormat format; format.set_key_size(32); format.set_version(0); KeyTemplate key_template; key_template.set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey"); key_template.set_output_prefix_type(OutputPrefixType::TINK); format.SerializeToString(key_template.mutable_value()); *dem_params.mutable_aead_dem() = key_template; EciesAeadHkdfParams params; *params.mutable_kem_params() = kem_params; *params.mutable_dem_params() = dem_params; params.set_ec_point_format(EcPointFormat::COMPRESSED); return params; } TEST_F(HybridConfigTest, EciesProtoPublicKeySerializationRegistered) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } const std::string public_key_bytes = subtle::Random::GetRandomBytes(internal::X25519KeyPubKeySize()); EciesAeadHkdfPublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_x(public_key_bytes); *public_key_proto.mutable_params() = CreateParams(); util::StatusOr proto_key_serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPublicKey", RestrictedData(public_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()), KeyData::ASYMMETRIC_PUBLIC, OutputPrefixType::RAW, /*id_requirement=*/absl::nullopt); ASSERT_THAT(proto_key_serialization, IsOk()); util::StatusOr> parsed_key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kX25519) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr public_key = EciesPublicKey::CreateForCurveX25519(*parameters, public_key_bytes, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr> serialized_key = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *public_key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key.status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(HybridConfig::Register(), IsOk()); util::StatusOr> parsed_key2 = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key2, IsOk()); util::StatusOr> serialized_key2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *public_key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key2, IsOk()); } TEST_F(HybridConfigTest, EciesProtoPrivateKeySerializationRegistered) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::StatusOr> x25519_key = internal::NewX25519Key(); ASSERT_THAT(x25519_key, IsOk()); const std::string public_key_bytes = std::string(reinterpret_cast((*x25519_key)->public_value), internal::X25519KeyPubKeySize()); const std::string private_key_bytes = std::string(reinterpret_cast((*x25519_key)->private_key), internal::X25519KeyPrivKeySize()); EciesAeadHkdfPublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_x(public_key_bytes); *public_key_proto.mutable_params() = CreateParams(); EciesAeadHkdfPrivateKey private_key_proto; private_key_proto.set_version(0); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_key_value(private_key_bytes); util::StatusOr proto_key_serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey", RestrictedData(private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()), KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::RAW, /*id_requirement=*/absl::nullopt); ASSERT_THAT(proto_key_serialization, IsOk()); util::StatusOr> parsed_key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr parameters = EciesParameters::Builder() .SetCurveType(EciesParameters::CurveType::kX25519) .SetHashType(EciesParameters::HashType::kSha256) .SetDemId(EciesParameters::DemId::kAes256SivRaw) .SetVariant(EciesParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr public_key = EciesPublicKey::CreateForCurveX25519(*parameters, public_key_bytes, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = EciesPrivateKey::CreateForCurveX25519( *public_key, RestrictedData(private_key_bytes, InsecureSecretKeyAccess::Get()), GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr> serialized_key = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *private_key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key.status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(HybridConfig::Register(), IsOk()); util::StatusOr> parsed_key2 = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key2, IsOk()); util::StatusOr> serialized_key2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *private_key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key2, IsOk()); } // FIPS-only mode tests TEST_F(HybridConfigTest, RegisterNonFipsTemplates) { if (!internal::IsFipsModeEnabled() || !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only supported in FIPS-only mode with BoringCrypto"; } EXPECT_THAT(HybridConfig::Register(), IsOk()); // Check that we can not retrieve non-FIPS keyset handle std::list non_fips_key_templates; non_fips_key_templates.push_back( HybridKeyTemplates:: EciesP256CompressedHkdfHmacSha256Aes128CtrHmacSha256()); non_fips_key_templates.push_back( HybridKeyTemplates::EciesP256CompressedHkdfHmacSha256Aes128Gcm()); non_fips_key_templates.push_back( HybridKeyTemplates::EciesP256HkdfHmacSha256Aes128CtrHmacSha256()); non_fips_key_templates.push_back( HybridKeyTemplates::EciesP256HkdfHmacSha256Aes128Gcm()); non_fips_key_templates.push_back( HybridKeyTemplates:: EciesP256HkdfHmacSha256Aes128GcmCompressedWithoutPrefix()); non_fips_key_templates.push_back( HybridKeyTemplates::EciesX25519HkdfHmacSha256Aes128CtrHmacSha256()); non_fips_key_templates.push_back( HybridKeyTemplates::EciesX25519HkdfHmacSha256Aes128Gcm()); non_fips_key_templates.push_back( HybridKeyTemplates::EciesX25519HkdfHmacSha256XChaCha20Poly1305()); for (auto key_template : non_fips_key_templates) { EXPECT_THAT( KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()) .status(), StatusIs(absl::StatusCode::kNotFound)); } } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/hybrid_decrypt_factory.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/hybrid_decrypt_factory.h" #include #include "tink/hybrid/hybrid_decrypt_wrapper.h" #include "tink/hybrid_decrypt.h" #include "tink/key_manager.h" #include "tink/keyset_handle.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // NOLINTBEGIN(whitespace/line_length) (Formatted when commented in) // TINK-PENDING-REMOVAL-IN-3.0.0-START // static util::StatusOr> HybridDecryptFactory::GetPrimitive(const KeysetHandle& keyset_handle) { util::Status status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) { return status; } return keyset_handle.GetPrimitive( ConfigGlobalRegistry()); } // static util::StatusOr> HybridDecryptFactory::GetPrimitive( const KeysetHandle& keyset_handle, const KeyManager* custom_key_manager) { util::Status status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) { return status; } return keyset_handle.GetPrimitive(custom_key_manager); } // TINK-PENDING-REMOVAL-IN-3.0.0-END // NOLINTEND(whitespace/line_length) } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/hybrid_decrypt_factory.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_HYBRID_DECRYPT_FACTORY_H_ #define TINK_HYBRID_HYBRID_DECRYPT_FACTORY_H_ #include #include "absl/base/macros.h" #include "tink/hybrid_decrypt.h" #include "tink/key_manager.h" #include "tink/keyset_handle.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // This class is deprecated. Call keyset_handle->GetPrimitive() // instead. // // Note that in order to for this change to be safe, the AeadSetWrapper has to // be registered in your binary before this call. This happens automatically if // you call one of // * HybridConfig::Register() // * TinkConfig::Register() // NOLINTBEGIN(whitespace/line_length) (Formatted when commented in) // TINK-PENDING-REMOVAL-IN-3.0.0-START class ABSL_DEPRECATED( "Call getPrimitive() on the keyset_handle after registering " "the HybridDecryptWrapper instead.") HybridDecryptFactory { public: // Returns a HybridDecrypt-primitive that uses key material from the keyset // specified via 'keyset_handle'. ABSL_DEPRECATED( "Call getPrimitive() on the keyset_handle after " "registering " "the HybridEncryptWrapper instead.") static crypto::tink::util::StatusOr> GetPrimitive(const KeysetHandle& keyset_handle); // Returns a HybridDecrypt-primitive that uses key material from the keyset // specified via 'keyset_handle' and is instantiated by the given // 'custom_key_manager' (instead of the key manager from the Registry). static crypto::tink::util::StatusOr> GetPrimitive(const KeysetHandle& keyset_handle, const KeyManager* custom_key_manager); private: HybridDecryptFactory() {} }; // TINK-PENDING-REMOVAL-IN-3.0.0-END // NOLINTEND(whitespace/line_length) } // namespace tink } // namespace crypto #endif // TINK_HYBRID_HYBRID_DECRYPT_FACTORY_H_ ================================================ FILE: cc/hybrid/hybrid_decrypt_factory_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/hybrid_decrypt_factory.h" #include #include #include #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "tink/crypto_format.h" #include "tink/hybrid/ecies_aead_hkdf_public_key_manager.h" #include "tink/hybrid/hybrid_config.h" #include "tink/hybrid_decrypt.h" #include "tink/hybrid_encrypt.h" #include "tink/keyset_handle.h" #include "tink/util/status.h" #include "tink/util/test_keyset_handle.h" #include "tink/util/test_util.h" #include "proto/ecies_aead_hkdf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { // NOLINTBEGIN(whitespace/line_length) (Formatted when commented in) // TINK-PENDING-REMOVAL-IN-3.0.0-START using crypto::tink::test::AddRawKey; using crypto::tink::test::AddTinkKey; using google::crypto::tink::EciesAeadHkdfPrivateKey; using google::crypto::tink::EcPointFormat; using google::crypto::tink::EllipticCurveType; using google::crypto::tink::HashType; using google::crypto::tink::KeyData; using google::crypto::tink::Keyset; using google::crypto::tink::KeyStatusType; class HybridDecryptFactoryTest : public ::testing::Test { }; EciesAeadHkdfPrivateKey GetNewEciesPrivateKey() { return test::GetEciesAesGcmHkdfTestKey( EllipticCurveType::NIST_P256, EcPointFormat::UNCOMPRESSED, HashType::SHA256, 32); } TEST_F(HybridDecryptFactoryTest, testBasic) { Keyset keyset; auto hybrid_decrypt_result = HybridDecryptFactory::GetPrimitive( *TestKeysetHandle::GetKeysetHandle(keyset)); EXPECT_FALSE(hybrid_decrypt_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, hybrid_decrypt_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "at least one key", std::string(hybrid_decrypt_result.status().message())); } TEST_F(HybridDecryptFactoryTest, testPrimitive) { // Prepare a Keyset. Keyset keyset; std::string key_type = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey"; uint32_t key_id_1 = 1234543; auto ecies_key_1 = GetNewEciesPrivateKey(); AddTinkKey(key_type, key_id_1, ecies_key_1, KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PRIVATE, &keyset); uint32_t key_id_2 = 726329; auto ecies_key_2 = GetNewEciesPrivateKey(); AddRawKey(key_type, key_id_2, ecies_key_2, KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PRIVATE, &keyset); uint32_t key_id_3 = 7213743; auto ecies_key_3 = GetNewEciesPrivateKey(); AddTinkKey(key_type, key_id_3, ecies_key_3, KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PRIVATE, &keyset); keyset.set_primary_key_id(key_id_3); // Initialize the registry. ASSERT_TRUE(HybridConfig::Register().ok()); // Prepare HybridEncrypt-instances. auto ecies_key_manager = absl::make_unique(); std::unique_ptr ecies_1 = std::move( ecies_key_manager->GetPrimitive(ecies_key_1.public_key()) .value()); std::unique_ptr ecies_2 = std::move( ecies_key_manager->GetPrimitive(ecies_key_2.public_key()) .value()); // Create a KeysetHandle and use it with the factory. auto hybrid_decrypt_result = HybridDecryptFactory::GetPrimitive( *TestKeysetHandle::GetKeysetHandle(keyset)); EXPECT_TRUE(hybrid_decrypt_result.ok()) << hybrid_decrypt_result.status(); auto hybrid_decrypt = std::move(hybrid_decrypt_result.value()); // Test the resulting HybridDecrypt-instance. std::string plaintext = "some plaintext"; std::string context_info = "some context info"; auto ciphertext_1 = CryptoFormat::GetOutputPrefix(KeyInfoFromKey(keyset.key(0))).value() + ecies_1->Encrypt(plaintext, context_info).value(); auto ciphertext_2 = CryptoFormat::GetOutputPrefix(KeyInfoFromKey(keyset.key(1))).value() + ecies_2->Encrypt(plaintext, context_info).value(); { // Regular decryption with key_1. auto decrypt_result = hybrid_decrypt->Decrypt(ciphertext_1, context_info); EXPECT_TRUE(decrypt_result.ok()) << decrypt_result.status(); EXPECT_EQ(plaintext, decrypt_result.value()); } { // Regular decryption with key_2. auto decrypt_result = hybrid_decrypt->Decrypt(ciphertext_2, context_info); EXPECT_TRUE(decrypt_result.ok()) << decrypt_result.status(); EXPECT_EQ(plaintext, decrypt_result.value()); } { // Wrong context_info. auto decrypt_result = hybrid_decrypt->Decrypt(ciphertext_1, "bad context"); EXPECT_FALSE(decrypt_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, decrypt_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "decryption failed", std::string(decrypt_result.status().message())); } } // TINK-PENDING-REMOVAL-IN-3.0.0-END // NOLINTEND(whitespace/line_length) } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/hybrid_decrypt_wrapper.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/hybrid_decrypt_wrapper.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/crypto_format.h" #include "tink/hybrid_decrypt.h" #include "tink/internal/monitoring_util.h" #include "tink/internal/registry_impl.h" #include "tink/internal/util.h" #include "tink/monitoring/monitoring.h" #include "tink/primitive_set.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { constexpr absl::string_view kPrimitive = "hybrid_decrypt"; constexpr absl::string_view kDecryptApi = "decrypt"; class HybridDecryptSetWrapper : public HybridDecrypt { public: explicit HybridDecryptSetWrapper( std::unique_ptr> hybrid_decrypt_set, std::unique_ptr monitoring_decryption_client = nullptr) : hybrid_decrypt_set_(std::move(hybrid_decrypt_set)), monitoring_decryption_client_(std::move(monitoring_decryption_client)) { } crypto::tink::util::StatusOr Decrypt( absl::string_view ciphertext, absl::string_view context_info) const override; ~HybridDecryptSetWrapper() override = default; private: std::unique_ptr> hybrid_decrypt_set_; std::unique_ptr monitoring_decryption_client_; }; util::StatusOr HybridDecryptSetWrapper::Decrypt( absl::string_view ciphertext, absl::string_view context_info) const { // BoringSSL expects a non-null pointer for context_info, // regardless of whether the size is 0. context_info = internal::EnsureStringNonNull(context_info); if (ciphertext.length() > CryptoFormat::kNonRawPrefixSize) { absl::string_view key_id = ciphertext.substr(0, CryptoFormat::kNonRawPrefixSize); auto primitives_result = hybrid_decrypt_set_->get_primitives(key_id); if (primitives_result.ok()) { absl::string_view raw_ciphertext = ciphertext.substr(CryptoFormat::kNonRawPrefixSize); for (auto& hybrid_decrypt_entry : *(primitives_result.value())) { HybridDecrypt& hybrid_decrypt = hybrid_decrypt_entry->get_primitive(); auto decrypt_result = hybrid_decrypt.Decrypt(raw_ciphertext, context_info); if (decrypt_result.ok()) { if (monitoring_decryption_client_ != nullptr) { monitoring_decryption_client_->Log( hybrid_decrypt_entry->get_key_id(), ciphertext.size()); } return std::move(decrypt_result.value()); } } } } // No matching key succeeded with decryption, try all RAW keys. auto raw_primitives_result = hybrid_decrypt_set_->get_raw_primitives(); if (raw_primitives_result.ok()) { for (auto& hybrid_decrypt_entry : *(raw_primitives_result.value())) { HybridDecrypt& hybrid_decrypt = hybrid_decrypt_entry->get_primitive(); auto decrypt_result = hybrid_decrypt.Decrypt(ciphertext, context_info); if (decrypt_result.ok()) { return std::move(decrypt_result.value()); } } } if (monitoring_decryption_client_ != nullptr) { monitoring_decryption_client_->LogFailure(); } return util::Status(absl::StatusCode::kInvalidArgument, "decryption failed"); } util::Status Validate(PrimitiveSet* hybrid_decrypt_set) { if (hybrid_decrypt_set == nullptr) { return util::Status(absl::StatusCode::kInternal, "hybrid_decrypt_set must be non-NULL"); } if (hybrid_decrypt_set->get_primary() == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "hybrid_decrypt_set has no primary"); } return util::OkStatus(); } } // anonymous namespace // static util::StatusOr> HybridDecryptWrapper::Wrap( std::unique_ptr> primitive_set) const { util::Status status = Validate(primitive_set.get()); if (!status.ok()) return status; MonitoringClientFactory* const monitoring_factory = internal::RegistryImpl::GlobalInstance().GetMonitoringClientFactory(); // Monitoring is not enabled. Create a wrapper without monitoring clients. if (monitoring_factory == nullptr) { return { absl::make_unique(std::move(primitive_set))}; } util::StatusOr keyset_info = internal::MonitoringKeySetInfoFromPrimitiveSet(*primitive_set); if (!keyset_info.ok()) { return keyset_info.status(); } util::StatusOr> monitoring_decryption_client = monitoring_factory->New( MonitoringContext(kPrimitive, kDecryptApi, *keyset_info)); if (!monitoring_decryption_client.ok()) { return monitoring_decryption_client.status(); } return {absl::make_unique( std::move(primitive_set), *std::move(monitoring_decryption_client))}; } } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/hybrid_decrypt_wrapper.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_HYBRID_DECRYPT_WRAPPER_H_ #define TINK_HYBRID_HYBRID_DECRYPT_WRAPPER_H_ #include #include "absl/strings/string_view.h" #include "tink/hybrid_decrypt.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // Wraps a set of HybridDecrypt-instances that correspond to a keyset, // and combines them into a single HybridDecrypt-primitive, that for // actual decryption uses the instance that matches the ciphertext prefix. class HybridDecryptWrapper : public PrimitiveWrapper { public: util::StatusOr> Wrap( std::unique_ptr> primitive_set) const override; }; } // namespace tink } // namespace crypto #endif // TINK_HYBRID_HYBRID_DECRYPT_WRAPPER_H_ ================================================ FILE: cc/hybrid/hybrid_decrypt_wrapper_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/hybrid_decrypt_wrapper.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_map.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/hybrid/failing_hybrid.h" #include "tink/hybrid_decrypt.h" #include "tink/internal/registry_impl.h" #include "tink/monitoring/monitoring.h" #include "tink/monitoring/monitoring_client_mocks.h" #include "tink/primitive_set.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" using ::crypto::tink::test::DummyHybridDecrypt; using ::crypto::tink::test::DummyHybridEncrypt; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::KeysetInfo; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::OutputPrefixType; using ::testing::_; using ::testing::ByMove; using ::testing::IsNull; using ::testing::NiceMock; using ::testing::Not; using ::testing::NotNull; using ::testing::Return; using ::testing::Test; namespace crypto { namespace tink { namespace { class HybridDecryptSetWrapperTest : public ::testing::Test { protected: void SetUp() override { } void TearDown() override { } }; TEST_F(HybridDecryptSetWrapperTest, Basic) { { // hybrid_decrypt_set is nullptr. auto hybrid_decrypt_result = HybridDecryptWrapper().Wrap(nullptr); EXPECT_FALSE(hybrid_decrypt_result.ok()); EXPECT_EQ(absl::StatusCode::kInternal, hybrid_decrypt_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "non-NULL", std::string(hybrid_decrypt_result.status().message())); } { // hybrid_decrypt_set has no primary primitive. std::unique_ptr> hybrid_decrypt_set(new PrimitiveSet()); auto hybrid_decrypt_result = HybridDecryptWrapper().Wrap( std::move(hybrid_decrypt_set)); EXPECT_FALSE(hybrid_decrypt_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, hybrid_decrypt_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "no primary", std::string(hybrid_decrypt_result.status().message())); } { // Correct hybrid_decrypt_set; KeysetInfo::KeyInfo* key; KeysetInfo keyset; uint32_t key_id_0 = 1234543; key = keyset.add_key_info(); key->set_output_prefix_type(OutputPrefixType::RAW); key->set_key_id(key_id_0); key->set_status(KeyStatusType::ENABLED); uint32_t key_id_1 = 726329; key = keyset.add_key_info(); key->set_output_prefix_type(OutputPrefixType::LEGACY); key->set_key_id(key_id_1); key->set_status(KeyStatusType::ENABLED); uint32_t key_id_2 = 7213743; key = keyset.add_key_info(); key->set_output_prefix_type(OutputPrefixType::TINK); key->set_key_id(key_id_2); key->set_status(KeyStatusType::ENABLED); std::string hybrid_name_0 = "hybrid_0"; std::string hybrid_name_1 = "hybrid_1"; std::string hybrid_name_2 = "hybrid_2"; std::unique_ptr> hybrid_decrypt_set( new PrimitiveSet()); std::unique_ptr hybrid_decrypt( new DummyHybridDecrypt(hybrid_name_0)); auto entry_result = hybrid_decrypt_set->AddPrimitive( std::move(hybrid_decrypt), keyset.key_info(0)); ASSERT_TRUE(entry_result.ok()); hybrid_decrypt = std::make_unique(hybrid_name_1); entry_result = hybrid_decrypt_set->AddPrimitive(std::move(hybrid_decrypt), keyset.key_info(1)); ASSERT_TRUE(entry_result.ok()); std::string prefix_id_1 = entry_result.value()->get_identifier(); hybrid_decrypt = std::make_unique(hybrid_name_2); entry_result = hybrid_decrypt_set->AddPrimitive(std::move(hybrid_decrypt), keyset.key_info(2)); ASSERT_TRUE(entry_result.ok()); // The last key is the primary. ASSERT_THAT(hybrid_decrypt_set->set_primary(entry_result.value()), IsOk()); // Wrap hybrid_decrypt_set and test the resulting HybridDecrypt. auto hybrid_decrypt_result = HybridDecryptWrapper().Wrap( std::move(hybrid_decrypt_set)); EXPECT_TRUE(hybrid_decrypt_result.ok()) << hybrid_decrypt_result.status(); hybrid_decrypt = std::move(hybrid_decrypt_result.value()); std::string plaintext = "some_plaintext"; std::string context_info = "some_context"; { // RAW key std::string ciphertext = DummyHybridEncrypt(hybrid_name_0) .Encrypt(plaintext, context_info) .value(); auto decrypt_result = hybrid_decrypt->Decrypt(ciphertext, context_info); EXPECT_TRUE(decrypt_result.ok()) << decrypt_result.status(); EXPECT_EQ(plaintext, decrypt_result.value()); } { // No ciphertext prefix. std::string ciphertext = plaintext + hybrid_name_1; auto decrypt_result = hybrid_decrypt->Decrypt(ciphertext, context_info); EXPECT_FALSE(decrypt_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, decrypt_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "decryption failed", std::string(decrypt_result.status().message())); } { // Correct ciphertext prefix. std::string ciphertext = prefix_id_1 + DummyHybridEncrypt(hybrid_name_1) .Encrypt(plaintext, context_info) .value(); auto decrypt_result = hybrid_decrypt->Decrypt(ciphertext, context_info); EXPECT_TRUE(decrypt_result.ok()) << decrypt_result.status(); EXPECT_EQ(plaintext, decrypt_result.value()); } { // Bad ciphertext. std::string ciphertext = "some bad ciphertext"; auto decrypt_result = hybrid_decrypt->Decrypt(ciphertext, context_info); EXPECT_FALSE(decrypt_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, decrypt_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "decryption failed", std::string(decrypt_result.status().message())); } } } KeysetInfo::KeyInfo PopulateKeyInfo(uint32_t key_id, OutputPrefixType out_prefix_type, KeyStatusType status) { KeysetInfo::KeyInfo key_info; key_info.set_output_prefix_type(out_prefix_type); key_info.set_key_id(key_id); key_info.set_status(status); return key_info; } // Creates a test keyset info object. KeysetInfo CreateTestKeysetInfo() { KeysetInfo keyset_info; *keyset_info.add_key_info() = PopulateKeyInfo(/*key_id=*/1234543, OutputPrefixType::TINK, /*status=*/KeyStatusType::ENABLED); *keyset_info.add_key_info() = PopulateKeyInfo(/*key_id=*/726329, OutputPrefixType::LEGACY, /*status=*/KeyStatusType::ENABLED); *keyset_info.add_key_info() = PopulateKeyInfo(/*key_id=*/7213743, OutputPrefixType::TINK, /*status=*/KeyStatusType::ENABLED); return keyset_info; } // Tests for the monitoring behavior. class HybridDecryptSetWrapperWithMonitoringTest : public Test { protected: // Perform some common initialization: reset the global registry, set expected // calls for the mock monitoring factory and the returned clients. void SetUp() override { Registry::Reset(); // Setup mocks for catching Monitoring calls. auto monitoring_client_factory = absl::make_unique(); auto decryption_monitoring_client = absl::make_unique>(); decryption_monitoring_client_ = decryption_monitoring_client.get(); // Monitoring tests expect that the client factory will create the // corresponding MockMonitoringClients. EXPECT_CALL(*monitoring_client_factory, New(_)) .WillOnce( Return(ByMove(util::StatusOr>( std::move(decryption_monitoring_client))))); ASSERT_THAT(internal::RegistryImpl::GlobalInstance() .RegisterMonitoringClientFactory( std::move(monitoring_client_factory)), IsOk()); ASSERT_THAT( internal::RegistryImpl::GlobalInstance().GetMonitoringClientFactory(), Not(IsNull())); } // Cleanup the registry to avoid mock leaks. ~HybridDecryptSetWrapperWithMonitoringTest() override { Registry::Reset(); } MockMonitoringClient* decryption_monitoring_client_; }; // Test that successful encrypt operations are logged. TEST_F(HybridDecryptSetWrapperWithMonitoringTest, WrapKeysetWithMonitoringEncryptSuccess) { // Create a primitive set and fill it with some entries KeysetInfo keyset_info = CreateTestKeysetInfo(); const absl::flat_hash_map annotations = { {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}}; auto hybrid_decrypt_primitive_set = absl::make_unique>(annotations); ASSERT_THAT( hybrid_decrypt_primitive_set ->AddPrimitive(absl::make_unique("hybrid0"), keyset_info.key_info(0)) .status(), IsOk()); ASSERT_THAT( hybrid_decrypt_primitive_set ->AddPrimitive(absl::make_unique("hybrid1"), keyset_info.key_info(1)) .status(), IsOk()); // Set the last as primary. util::StatusOr::Entry*> last = hybrid_decrypt_primitive_set->AddPrimitive( absl::make_unique("hybrid2"), keyset_info.key_info(2)); ASSERT_THAT(last, IsOk()); ASSERT_THAT(hybrid_decrypt_primitive_set->set_primary(*last), IsOk()); // Record the ID of the primary key. const uint32_t primary_key_id = keyset_info.key_info(2).key_id(); // Create a Hybrid Encrypt and encrypt some data, so we can decrypt it later. util::StatusOr> hybrid_decrypt = HybridDecryptWrapper().Wrap(std::move(hybrid_decrypt_primitive_set)); ASSERT_THAT(hybrid_decrypt, IsOkAndHolds(NotNull())); constexpr absl::string_view plaintext = "This is some plaintext!"; constexpr absl::string_view context = "Some context!"; std::string ciphertext = absl::StrCat((*last)->get_identifier(), DummyHybridEncrypt("hybrid2").Encrypt(plaintext, context).value()); // Check that calling Decrypt triggers a Log() call. EXPECT_CALL(*decryption_monitoring_client_, Log(primary_key_id, ciphertext.size())); EXPECT_THAT((*hybrid_decrypt)->Decrypt(ciphertext, context), IsOkAndHolds(plaintext)); } TEST_F(HybridDecryptSetWrapperWithMonitoringTest, WrapKeysetWithMonitoringEncryptFailures) { // Create a primitive set and fill it with some entries KeysetInfo keyset_info = CreateTestKeysetInfo(); const absl::flat_hash_map annotations = { {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}}; auto hybrid_decrypt_primitive_set = absl::make_unique>(annotations); ASSERT_THAT(hybrid_decrypt_primitive_set ->AddPrimitive(CreateAlwaysFailingHybridDecrypt("hybrid0"), keyset_info.key_info(0)) .status(), IsOk()); ASSERT_THAT(hybrid_decrypt_primitive_set ->AddPrimitive(CreateAlwaysFailingHybridDecrypt("hybrid1"), keyset_info.key_info(1)) .status(), IsOk()); // Set the last as primary. util::StatusOr::Entry*> last = hybrid_decrypt_primitive_set->AddPrimitive( CreateAlwaysFailingHybridDecrypt("hybrid2"), keyset_info.key_info(2)); ASSERT_THAT(last, IsOkAndHolds(NotNull())); ASSERT_THAT(hybrid_decrypt_primitive_set->set_primary(*last), IsOk()); // Create a Hybrid Decrypt and decrypt some invalid ciphertext. util::StatusOr> hybrid_decrypt = HybridDecryptWrapper().Wrap(std::move(hybrid_decrypt_primitive_set)); ASSERT_THAT(hybrid_decrypt, IsOk()); constexpr absl::string_view ciphertext = "This is some ciphertext!"; constexpr absl::string_view context = "Some context!"; // Check that calling Decrypt triggers a LogFailure() call. EXPECT_CALL(*decryption_monitoring_client_, LogFailure()); EXPECT_THAT((*hybrid_decrypt)->Decrypt(ciphertext, context).status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/hybrid_encrypt_factory.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/hybrid_encrypt_factory.h" #include #include "tink/hybrid/hybrid_encrypt_wrapper.h" #include "tink/hybrid_encrypt.h" #include "tink/key_manager.h" #include "tink/keyset_handle.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // NOLINTBEGIN(whitespace/line_length) (Formatted when commented in) // TINK-PENDING-REMOVAL-IN-3.0.0-START // static util::StatusOr> HybridEncryptFactory::GetPrimitive(const KeysetHandle& keyset_handle) { util::Status status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) { return status; } return keyset_handle.GetPrimitive( ConfigGlobalRegistry()); } // static util::StatusOr> HybridEncryptFactory::GetPrimitive( const KeysetHandle& keyset_handle, const KeyManager* custom_key_manager) { util::Status status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) { return status; } return keyset_handle.GetPrimitive(custom_key_manager); } // TINK-PENDING-REMOVAL-IN-3.0.0-END // NOLINTEND(whitespace/line_length) } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/hybrid_encrypt_factory.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_HYBRID_ENCRYPT_FACTORY_H_ #define TINK_HYBRID_HYBRID_ENCRYPT_FACTORY_H_ #include #include "absl/base/macros.h" #include "tink/hybrid_encrypt.h" #include "tink/key_manager.h" #include "tink/keyset_handle.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // This class is deprecated. Call keyset_handle->GetPrimitive() // instead. // // Note that in order to for this change to be safe, the AeadSetWrapper has to // be registered in your binary before this call. This happens automatically if // you call one of // * HybridConfig::Register() // * TinkConfig::Register() // NOLINTBEGIN(whitespace/line_length) (Formatted when commented in) // TINK-PENDING-REMOVAL-IN-3.0.0-START class ABSL_DEPRECATED( "Call getPrimitive() on the keyset_handle after registering " "the HybridEncryptWrapper instead.") HybridEncryptFactory { public: // Returns a HybridEncrypt-primitive that uses key material from the keyset // specified via 'keyset_handle'. static crypto::tink::util::StatusOr> GetPrimitive(const KeysetHandle& keyset_handle); // Returns a HybridEncrypt-primitive that uses key material from the keyset // specified via 'keyset_handle' and is instantiated by the given // 'custom_key_manager' (instead of the key manager from the Registry). static crypto::tink::util::StatusOr> GetPrimitive(const KeysetHandle& keyset_handle, const KeyManager* custom_key_manager); private: HybridEncryptFactory() {} }; // TINK-PENDING-REMOVAL-IN-3.0.0-END // NOLINTEND(whitespace/line_length) } // namespace tink } // namespace crypto #endif // TINK_HYBRID_HYBRID_ENCRYPT_FACTORY_H_ ================================================ FILE: cc/hybrid/hybrid_encrypt_factory_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/hybrid_encrypt_factory.h" #include #include #include "gtest/gtest.h" #include "tink/crypto_format.h" #include "tink/hybrid/hybrid_config.h" #include "tink/hybrid_encrypt.h" #include "tink/keyset_handle.h" #include "tink/util/status.h" #include "tink/util/test_keyset_handle.h" #include "tink/util/test_util.h" #include "proto/ecies_aead_hkdf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { // NOLINTBEGIN(whitespace/line_length) (Formatted when commented in) // TINK-PENDING-REMOVAL-IN-3.0.0-START using crypto::tink::test::AddRawKey; using crypto::tink::test::AddTinkKey; using google::crypto::tink::EciesAeadHkdfPublicKey; using google::crypto::tink::EcPointFormat; using google::crypto::tink::EllipticCurveType; using google::crypto::tink::HashType; using google::crypto::tink::KeyData; using google::crypto::tink::Keyset; using google::crypto::tink::KeyStatusType; class HybridEncryptFactoryTest : public ::testing::Test { }; EciesAeadHkdfPublicKey GetNewEciesPublicKey() { auto ecies_key = test::GetEciesAesGcmHkdfTestKey( EllipticCurveType::NIST_P256, EcPointFormat::UNCOMPRESSED, HashType::SHA256, 32); return ecies_key.public_key(); } TEST_F(HybridEncryptFactoryTest, testBasic) { Keyset keyset; auto hybrid_encrypt_result = HybridEncryptFactory::GetPrimitive( *TestKeysetHandle::GetKeysetHandle(keyset)); EXPECT_FALSE(hybrid_encrypt_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, hybrid_encrypt_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "at least one key", std::string(hybrid_encrypt_result.status().message())); } TEST_F(HybridEncryptFactoryTest, testPrimitive) { // Prepare a Keyset. Keyset keyset; std::string key_type = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPublicKey"; uint32_t key_id_1 = 1234543; AddTinkKey(key_type, key_id_1, GetNewEciesPublicKey(), KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PUBLIC, &keyset); uint32_t key_id_2 = 726329; AddRawKey(key_type, key_id_2, GetNewEciesPublicKey(), KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PUBLIC, &keyset); uint32_t key_id_3 = 7213743; AddTinkKey(key_type, key_id_3, GetNewEciesPublicKey(), KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PUBLIC, &keyset); keyset.set_primary_key_id(key_id_3); // Initialize the registry. ASSERT_TRUE(HybridConfig::Register().ok()); // Create a KeysetHandle and use it with the factory. auto hybrid_encrypt_result = HybridEncryptFactory::GetPrimitive( *TestKeysetHandle::GetKeysetHandle(keyset)); EXPECT_TRUE(hybrid_encrypt_result.ok()) << hybrid_encrypt_result.status(); auto hybrid_encrypt = std::move(hybrid_encrypt_result.value()); // Test the resulting HybridEncrypt-instance. std::string plaintext = "some plaintext"; std::string context_info = "some context info"; auto encrypt_result = hybrid_encrypt->Encrypt(plaintext, context_info); EXPECT_TRUE(encrypt_result.ok()) << encrypt_result.status(); } // TINK-PENDING-REMOVAL-IN-3.0.0-END // NOLINTEND(whitespace/line_length) } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/hybrid_encrypt_wrapper.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/hybrid_encrypt_wrapper.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/crypto_format.h" #include "tink/hybrid_encrypt.h" #include "tink/internal/monitoring_util.h" #include "tink/internal/registry_impl.h" #include "tink/internal/util.h" #include "tink/monitoring/monitoring.h" #include "tink/primitive_set.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { constexpr absl::string_view kPrimitive = "hybrid_encrypt"; constexpr absl::string_view kEncryptApi = "encrypt"; util::Status Validate(PrimitiveSet* hybrid_encrypt_set) { if (hybrid_encrypt_set == nullptr) { return util::Status(absl::StatusCode::kInternal, "hybrid_encrypt_set must be non-NULL"); } if (hybrid_encrypt_set->get_primary() == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "hybrid_encrypt_set has no primary"); } return util::OkStatus(); } // Returns an HybridEncrypt-primitive that uses the primary // HybridEncrypt-instance provided in 'hybrid_encrypt_set', // which must be non-NULL (and must contain a primary instance). class HybridEncryptSetWrapper : public HybridEncrypt { public: explicit HybridEncryptSetWrapper( std::unique_ptr> hybrid_encrypt_set, std::unique_ptr monitoring_encryption_client = nullptr) : hybrid_encrypt_set_(std::move(hybrid_encrypt_set)), monitoring_encryption_client_(std::move(monitoring_encryption_client)) { } crypto::tink::util::StatusOr Encrypt( absl::string_view plaintext, absl::string_view context_info) const override; ~HybridEncryptSetWrapper() override = default; private: std::unique_ptr> hybrid_encrypt_set_; std::unique_ptr monitoring_encryption_client_; }; util::StatusOr HybridEncryptSetWrapper::Encrypt( absl::string_view plaintext, absl::string_view context_info) const { // BoringSSL expects a non-null pointer for plaintext and context_info, // regardless of whether the size is 0. plaintext = internal::EnsureStringNonNull(plaintext); context_info = internal::EnsureStringNonNull(context_info); auto primary = hybrid_encrypt_set_->get_primary(); auto encrypt_result = primary->get_primitive().Encrypt(plaintext, context_info); if (!encrypt_result.ok()) { if (monitoring_encryption_client_ != nullptr) { monitoring_encryption_client_->LogFailure(); } return encrypt_result.status(); } if (monitoring_encryption_client_ != nullptr) { monitoring_encryption_client_->Log( hybrid_encrypt_set_->get_primary()->get_key_id(), plaintext.size()); } const std::string& key_id = primary->get_identifier(); return key_id + encrypt_result.value(); } } // anonymous namespace util::StatusOr> HybridEncryptWrapper::Wrap( std::unique_ptr> primitive_set) const { util::Status status = Validate(primitive_set.get()); if (!status.ok()) return status; MonitoringClientFactory* const monitoring_factory = internal::RegistryImpl::GlobalInstance().GetMonitoringClientFactory(); // Monitoring is not enabled. Create a wrapper without monitoring clients. if (monitoring_factory == nullptr) { return { absl::make_unique(std::move(primitive_set))}; } util::StatusOr keyset_info = internal::MonitoringKeySetInfoFromPrimitiveSet(*primitive_set); if (!keyset_info.ok()) { return keyset_info.status(); } util::StatusOr> monitoring_encryption_client = monitoring_factory->New( MonitoringContext(kPrimitive, kEncryptApi, *keyset_info)); if (!monitoring_encryption_client.ok()) { return monitoring_encryption_client.status(); } return {absl::make_unique( std::move(primitive_set), *std::move(monitoring_encryption_client))}; } } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/hybrid_encrypt_wrapper.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_HYBRID_ENCRYPT_WRAPPER_H_ #define TINK_HYBRID_HYBRID_ENCRYPT_WRAPPER_H_ #include #include "absl/strings/string_view.h" #include "tink/hybrid_encrypt.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // Wraps a set of HybridEncrypt-instances that correspond to a keyset, // and combines them into a single HybridEncrypt-primitive, that uses // the primary instance to do the actual encryption. class HybridEncryptWrapper : public PrimitiveWrapper { public: util::StatusOr> Wrap( std::unique_ptr> primitive_set) const override; }; } // namespace tink } // namespace crypto #endif // TINK_HYBRID_HYBRID_ENCRYPT_WRAPPER_H_ ================================================ FILE: cc/hybrid/hybrid_encrypt_wrapper_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/hybrid_encrypt_wrapper.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_map.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/hybrid/failing_hybrid.h" #include "tink/hybrid_encrypt.h" #include "tink/internal/registry_impl.h" #include "tink/monitoring/monitoring.h" #include "tink/monitoring/monitoring_client_mocks.h" #include "tink/primitive_set.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" using ::crypto::tink::test::DummyHybridEncrypt; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::KeysetInfo; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::OutputPrefixType; using ::testing::_; using ::testing::ByMove; using ::testing::IsNull; using ::testing::NiceMock; using ::testing::Not; using ::testing::NotNull; using ::testing::Return; using ::testing::Test; namespace crypto { namespace tink { namespace { class HybridEncryptSetWrapperTest : public ::testing::Test { protected: void SetUp() override { } void TearDown() override { } }; TEST_F(HybridEncryptSetWrapperTest, testBasic) { { // hybrid_encrypt_set is nullptr. auto hybrid_encrypt_result = HybridEncryptWrapper().Wrap(nullptr); EXPECT_FALSE(hybrid_encrypt_result.ok()); EXPECT_EQ(absl::StatusCode::kInternal, hybrid_encrypt_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "non-NULL", std::string(hybrid_encrypt_result.status().message())); } { // hybrid_encrypt_set has no primary primitive. std::unique_ptr> hybrid_encrypt_set(new PrimitiveSet()); auto hybrid_encrypt_result = HybridEncryptWrapper().Wrap( std::move(hybrid_encrypt_set)); EXPECT_FALSE(hybrid_encrypt_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, hybrid_encrypt_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "no primary", std::string(hybrid_encrypt_result.status().message())); } { // Correct hybrid_encrypt_set; KeysetInfo::KeyInfo* key_info; KeysetInfo keyset_info; uint32_t key_id_0 = 1234543; key_info = keyset_info.add_key_info(); key_info->set_output_prefix_type(OutputPrefixType::TINK); key_info->set_key_id(key_id_0); key_info->set_status(KeyStatusType::ENABLED); uint32_t key_id_1 = 726329; key_info = keyset_info.add_key_info(); key_info->set_output_prefix_type(OutputPrefixType::LEGACY); key_info->set_key_id(key_id_1); key_info->set_status(KeyStatusType::ENABLED); uint32_t key_id_2 = 7213743; key_info = keyset_info.add_key_info(); key_info->set_output_prefix_type(OutputPrefixType::TINK); key_info->set_key_id(key_id_2); key_info->set_status(KeyStatusType::ENABLED); std::string hybrid_name_0 = "hybrid_0"; std::string hybrid_name_1 = "hybrid_1"; std::string hybrid_name_2 = "hybrid_2"; std::unique_ptr> hybrid_encrypt_set( new PrimitiveSet()); std::unique_ptr hybrid_encrypt( new DummyHybridEncrypt(hybrid_name_0)); auto entry_result = hybrid_encrypt_set->AddPrimitive( std::move(hybrid_encrypt), keyset_info.key_info(0)); ASSERT_TRUE(entry_result.ok()); hybrid_encrypt = std::make_unique(hybrid_name_1); entry_result = hybrid_encrypt_set->AddPrimitive(std::move(hybrid_encrypt), keyset_info.key_info(1)); ASSERT_TRUE(entry_result.ok()); hybrid_encrypt = std::make_unique(hybrid_name_2); entry_result = hybrid_encrypt_set->AddPrimitive(std::move(hybrid_encrypt), keyset_info.key_info(2)); ASSERT_TRUE(entry_result.ok()); // The last key is the primary. ASSERT_THAT(hybrid_encrypt_set->set_primary(entry_result.value()), IsOk()); // Wrap hybrid_encrypt_set and test the resulting HybridEncrypt. auto hybrid_encrypt_result = HybridEncryptWrapper().Wrap( std::move(hybrid_encrypt_set)); EXPECT_TRUE(hybrid_encrypt_result.ok()) << hybrid_encrypt_result.status(); hybrid_encrypt = std::move(hybrid_encrypt_result.value()); std::string plaintext = "some_plaintext"; std::string context_info = "some_context"; auto encrypt_result = hybrid_encrypt->Encrypt(plaintext, context_info); EXPECT_TRUE(encrypt_result.ok()) << encrypt_result.status(); std::string ciphertext = encrypt_result.value(); EXPECT_PRED_FORMAT2(testing::IsSubstring, hybrid_name_2, ciphertext); } } KeysetInfo::KeyInfo PopulateKeyInfo(uint32_t key_id, OutputPrefixType out_prefix_type, KeyStatusType status) { KeysetInfo::KeyInfo key_info; key_info.set_output_prefix_type(out_prefix_type); key_info.set_key_id(key_id); key_info.set_status(status); return key_info; } // Creates a test keyset info object. KeysetInfo CreateTestKeysetInfo() { KeysetInfo keyset_info; *keyset_info.add_key_info() = PopulateKeyInfo(/*key_id=*/1234543, OutputPrefixType::TINK, /*status=*/KeyStatusType::ENABLED); *keyset_info.add_key_info() = PopulateKeyInfo(/*key_id=*/726329, OutputPrefixType::LEGACY, /*status=*/KeyStatusType::ENABLED); *keyset_info.add_key_info() = PopulateKeyInfo(/*key_id=*/7213743, OutputPrefixType::TINK, /*status=*/KeyStatusType::ENABLED); return keyset_info; } // Tests for the monitoring behavior. class HybridEncryptSetWrapperWithMonitoringTest : public Test { protected: // Perform some common initialization: reset the global registry, set expected // calls for the mock monitoring factory and the returned clients. void SetUp() override { Registry::Reset(); // Setup mocks for catching Monitoring calls. auto monitoring_client_factory = absl::make_unique(); auto encryption_monitoring_client = absl::make_unique>(); encryption_monitoring_client_ = encryption_monitoring_client.get(); // Monitoring tests expect that the client factory will create the // corresponding MockMonitoringClients. EXPECT_CALL(*monitoring_client_factory, New(_)) .WillOnce( Return(ByMove(util::StatusOr>( std::move(encryption_monitoring_client))))); ASSERT_THAT(internal::RegistryImpl::GlobalInstance() .RegisterMonitoringClientFactory( std::move(monitoring_client_factory)), IsOk()); ASSERT_THAT( internal::RegistryImpl::GlobalInstance().GetMonitoringClientFactory(), Not(IsNull())); } // Cleanup the registry to avoid mock leaks. ~HybridEncryptSetWrapperWithMonitoringTest() override { Registry::Reset(); } MockMonitoringClient* encryption_monitoring_client_; }; // Test that successful encrypt operations are logged. TEST_F(HybridEncryptSetWrapperWithMonitoringTest, WrapKeysetWithMonitoringEncryptSuccess) { // Create a primitive set and fill it with some entries KeysetInfo keyset_info = CreateTestKeysetInfo(); const absl::flat_hash_map annotations = { {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}}; auto hybrid_encrypt_primitive_set = absl::make_unique>(annotations); ASSERT_THAT( hybrid_encrypt_primitive_set ->AddPrimitive(absl::make_unique("hybrid0"), keyset_info.key_info(0)) , IsOk()); ASSERT_THAT( hybrid_encrypt_primitive_set ->AddPrimitive(absl::make_unique("hybrid1"), keyset_info.key_info(1)) , IsOk()); // Set the last as primary. util::StatusOr::Entry*> last = hybrid_encrypt_primitive_set->AddPrimitive( absl::make_unique("hybrid2"), keyset_info.key_info(2)); ASSERT_THAT(last, IsOk()); ASSERT_THAT(hybrid_encrypt_primitive_set->set_primary(*last), IsOk()); // Record the ID of the primary key. const uint32_t primary_key_id = keyset_info.key_info(2).key_id(); // Create a Hybrid Encrypt and encrypt some data. util::StatusOr> hybrid_encrypt = HybridEncryptWrapper().Wrap(std::move(hybrid_encrypt_primitive_set)); ASSERT_THAT(hybrid_encrypt, IsOkAndHolds(NotNull())); constexpr absl::string_view plaintext = "This is some plaintext!"; constexpr absl::string_view context = "Some context!"; // Check that calling Encrypt triggers a Log() call. EXPECT_CALL(*encryption_monitoring_client_, Log(primary_key_id, plaintext.size())); util::StatusOr ciphertext = (*hybrid_encrypt)->Encrypt(plaintext, context); EXPECT_THAT(ciphertext, IsOk()); } TEST_F(HybridEncryptSetWrapperWithMonitoringTest, WrapKeysetWithMonitoringEncryptFailures) { // Create a primitive set and fill it with some entries KeysetInfo keyset_info = CreateTestKeysetInfo(); const absl::flat_hash_map annotations = { {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}}; auto hybrid_encrypt_primitive_set = absl::make_unique>(annotations); ASSERT_THAT(hybrid_encrypt_primitive_set ->AddPrimitive(CreateAlwaysFailingHybridEncrypt("hybrid0"), keyset_info.key_info(0)) .status(), IsOk()); ASSERT_THAT(hybrid_encrypt_primitive_set ->AddPrimitive(CreateAlwaysFailingHybridEncrypt("hybrid1"), keyset_info.key_info(1)) .status(), IsOk()); // Set the last as primary. util::StatusOr::Entry*> last = hybrid_encrypt_primitive_set->AddPrimitive( CreateAlwaysFailingHybridEncrypt("hybrid2"), keyset_info.key_info(2)); ASSERT_THAT(last, IsOkAndHolds(NotNull())); ASSERT_THAT(hybrid_encrypt_primitive_set->set_primary(*last), IsOk()); // Create a Hybrid Encrypt and encrypt some data. util::StatusOr> hybrid_encrypt = HybridEncryptWrapper().Wrap(std::move(hybrid_encrypt_primitive_set)); ASSERT_THAT(hybrid_encrypt, IsOk()); constexpr absl::string_view plaintext = "This is some plaintext!"; constexpr absl::string_view context = "Some context!"; // Check that calling Encrypt triggers a LogFailure() call. EXPECT_CALL(*encryption_monitoring_client_, LogFailure()); util::StatusOr ciphertext = (*hybrid_encrypt)->Encrypt(plaintext, context); EXPECT_THAT(ciphertext.status(), StatusIs(absl::StatusCode::kInternal)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/hybrid_key_templates.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/hybrid_key_templates.h" #include #include "absl/strings/string_view.h" #include "tink/aead/aead_key_templates.h" #include "tink/daead/deterministic_aead_key_templates.h" #include "proto/common.pb.h" #include "proto/ecies_aead_hkdf.pb.h" #include "proto/hpke.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using google::crypto::tink::EciesAeadHkdfKeyFormat; using google::crypto::tink::EcPointFormat; using google::crypto::tink::EllipticCurveType; using google::crypto::tink::HashType; using google::crypto::tink::HpkeAead; using google::crypto::tink::HpkeKdf; using google::crypto::tink::HpkeKem; using google::crypto::tink::HpkeKeyFormat; using google::crypto::tink::HpkeParams; using google::crypto::tink::KeyTemplate; using google::crypto::tink::OutputPrefixType; KeyTemplate* NewEciesAeadHkdfKeyTemplate( EllipticCurveType curve_type, HashType hkdf_hash_type, EcPointFormat ec_point_format, const KeyTemplate& dem_key_template, OutputPrefixType prefix_type, absl::string_view hkdf_salt) { KeyTemplate* key_template = new KeyTemplate; key_template->set_type_url( "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey"); key_template->set_output_prefix_type(prefix_type); EciesAeadHkdfKeyFormat key_format; key_format.mutable_params()->set_ec_point_format(ec_point_format); auto dem_params = key_format.mutable_params()->mutable_dem_params(); *(dem_params->mutable_aead_dem()) = dem_key_template; auto kem_params = key_format.mutable_params()->mutable_kem_params(); kem_params->set_curve_type(curve_type); kem_params->set_hkdf_hash_type(hkdf_hash_type); kem_params->set_hkdf_salt(std::string(hkdf_salt)); key_format.SerializeToString(key_template->mutable_value()); return key_template; } KeyTemplate* NewHpkeKeyTemplate(HpkeKem kem, HpkeKdf kdf, HpkeAead aead, OutputPrefixType prefix_type) { KeyTemplate* key_template = new KeyTemplate; key_template->set_type_url( "type.googleapis.com/google.crypto.tink.HpkePrivateKey"); key_template->set_output_prefix_type(prefix_type); HpkeKeyFormat key_format; HpkeParams* params = key_format.mutable_params(); params->set_kem(kem); params->set_kdf(kdf); params->set_aead(aead); key_format.SerializeToString(key_template->mutable_value()); return key_template; } } // anonymous namespace // static const KeyTemplate& HybridKeyTemplates::EciesP256HkdfHmacSha256Aes128Gcm() { static const KeyTemplate* key_template = NewEciesAeadHkdfKeyTemplate(EllipticCurveType::NIST_P256, HashType::SHA256, EcPointFormat::UNCOMPRESSED, AeadKeyTemplates::Aes128Gcm(), OutputPrefixType::TINK, /* hkdf_salt= */ ""); return *key_template; } // static const KeyTemplate& HybridKeyTemplates::EciesP256HkdfHmacSha512Aes128Gcm() { static const KeyTemplate* key_template = NewEciesAeadHkdfKeyTemplate( EllipticCurveType::NIST_P256, HashType::SHA512, EcPointFormat::UNCOMPRESSED, AeadKeyTemplates::Aes128Gcm(), OutputPrefixType::TINK, /* hkdf_salt= */ ""); return *key_template; } // static const KeyTemplate& HybridKeyTemplates::EciesP256HkdfHmacSha256Aes128GcmCompressedWithoutPrefix() { static const KeyTemplate* key_template = NewEciesAeadHkdfKeyTemplate(EllipticCurveType::NIST_P256, HashType::SHA256, EcPointFormat::COMPRESSED, AeadKeyTemplates::Aes128Gcm(), OutputPrefixType::RAW, /* hkdf_salt= */ ""); return *key_template; } // static const KeyTemplate& HybridKeyTemplates::EciesP256HkdfHmacSha256Aes128CtrHmacSha256() { static const KeyTemplate* key_template = NewEciesAeadHkdfKeyTemplate(EllipticCurveType::NIST_P256, HashType::SHA256, EcPointFormat::UNCOMPRESSED, AeadKeyTemplates::Aes128CtrHmacSha256(), OutputPrefixType::TINK, /* hkdf_salt= */ ""); return *key_template; } // static const KeyTemplate& HybridKeyTemplates::EciesP256HkdfHmacSha512Aes128CtrHmacSha256() { static const KeyTemplate* key_template = NewEciesAeadHkdfKeyTemplate( EllipticCurveType::NIST_P256, HashType::SHA512, EcPointFormat::UNCOMPRESSED, AeadKeyTemplates::Aes128CtrHmacSha256(), OutputPrefixType::TINK, /* hkdf_salt= */ ""); return *key_template; } // static const KeyTemplate& HybridKeyTemplates::EciesP256CompressedHkdfHmacSha256Aes128Gcm() { static const KeyTemplate* key_template = NewEciesAeadHkdfKeyTemplate( EllipticCurveType::NIST_P256, HashType::SHA256, EcPointFormat::COMPRESSED, AeadKeyTemplates::Aes128Gcm(), OutputPrefixType::TINK, /* hkdf_salt= */ ""); return *key_template; } // static const KeyTemplate& HybridKeyTemplates::EciesP256CompressedHkdfHmacSha256Aes128CtrHmacSha256() { static const KeyTemplate* key_template = NewEciesAeadHkdfKeyTemplate( EllipticCurveType::NIST_P256, HashType::SHA256, EcPointFormat::COMPRESSED, AeadKeyTemplates::Aes128CtrHmacSha256(), OutputPrefixType::TINK, /* hkdf_salt= */ ""); return *key_template; } // static const KeyTemplate& HybridKeyTemplates::EciesX25519HkdfHmacSha256Aes128Gcm() { static const KeyTemplate* key_template = NewEciesAeadHkdfKeyTemplate( EllipticCurveType::CURVE25519, HashType::SHA256, EcPointFormat::COMPRESSED, AeadKeyTemplates::Aes128Gcm(), OutputPrefixType::TINK, /* hkdf_salt= */ ""); return *key_template; } // static const KeyTemplate& HybridKeyTemplates::EciesX25519HkdfHmacSha256Aes256Gcm() { static const KeyTemplate* key_template = NewEciesAeadHkdfKeyTemplate( EllipticCurveType::CURVE25519, HashType::SHA256, EcPointFormat::COMPRESSED, AeadKeyTemplates::Aes256Gcm(), OutputPrefixType::TINK, /* hkdf_salt= */ ""); return *key_template; } // static const KeyTemplate& HybridKeyTemplates::EciesX25519HkdfHmacSha256Aes128CtrHmacSha256() { static const KeyTemplate* key_template = NewEciesAeadHkdfKeyTemplate( EllipticCurveType::CURVE25519, HashType::SHA256, EcPointFormat::COMPRESSED, AeadKeyTemplates::Aes128CtrHmacSha256(), OutputPrefixType::TINK, /* hkdf_salt= */ ""); return *key_template; } // static const KeyTemplate& HybridKeyTemplates::EciesX25519HkdfHmacSha256XChaCha20Poly1305() { static const KeyTemplate* key_template = NewEciesAeadHkdfKeyTemplate( EllipticCurveType::CURVE25519, HashType::SHA256, EcPointFormat::COMPRESSED, AeadKeyTemplates::XChaCha20Poly1305(), OutputPrefixType::TINK, /* hkdf_salt= */ ""); return *key_template; } // static const KeyTemplate& HybridKeyTemplates::EciesX25519HkdfHmacSha256DeterministicAesSiv() { static const KeyTemplate* key_template = NewEciesAeadHkdfKeyTemplate( EllipticCurveType::CURVE25519, HashType::SHA256, EcPointFormat::COMPRESSED, DeterministicAeadKeyTemplates::Aes256Siv(), OutputPrefixType::TINK, /* hkdf_salt= */ ""); return *key_template; } // static const KeyTemplate& HybridKeyTemplates::HpkeX25519HkdfSha256Aes128Gcm() { static const KeyTemplate* key_template = NewHpkeKeyTemplate( HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM, OutputPrefixType::TINK); return *key_template; } // static const KeyTemplate& HybridKeyTemplates::HpkeX25519HkdfSha256Aes128GcmRaw() { static const KeyTemplate* key_template = NewHpkeKeyTemplate( HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM, OutputPrefixType::RAW); return *key_template; } // static const KeyTemplate& HybridKeyTemplates::HpkeX25519HkdfSha256Aes256Gcm() { static const KeyTemplate* key_template = NewHpkeKeyTemplate( HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_256_GCM, OutputPrefixType::TINK); return *key_template; } // static const KeyTemplate& HybridKeyTemplates::HpkeX25519HkdfSha256Aes256GcmRaw() { static const KeyTemplate* key_template = NewHpkeKeyTemplate( HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_256_GCM, OutputPrefixType::RAW); return *key_template; } // static const KeyTemplate& HybridKeyTemplates::HpkeX25519HkdfSha256ChaCha20Poly1305() { static const KeyTemplate* key_template = NewHpkeKeyTemplate( HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::CHACHA20_POLY1305, OutputPrefixType::TINK); return *key_template; } // static const KeyTemplate& HybridKeyTemplates::HpkeX25519HkdfSha256ChaCha20Poly1305Raw() { static const KeyTemplate* key_template = NewHpkeKeyTemplate( HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::CHACHA20_POLY1305, OutputPrefixType::RAW); return *key_template; } } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/hybrid_key_templates.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_HYBRID_KEY_TEMPLATES_H_ #define TINK_HYBRID_HYBRID_KEY_TEMPLATES_H_ #include "proto/tink.pb.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Pre-generated KeyTemplate for hybrid key types. One can use these templates // to generate a new KeysetHandle object with fresh keys. // To generate a new keyset that contains a single EciesAeadHkdfPrivateKey, // one can do: // // auto status = HybridConfig::Register(); // if (!status.ok()) { /* fail with error */ } // auto handle_result = KeysetHandle::GenerateNew( // HybridKeyTemplates::EciesP256HkdfHmacSha256Aes128Gcm()); // if (!handle_result.ok()) { /* fail with error */ } // auto keyset_handle = std::move(handle_result.value()); class HybridKeyTemplates { public: // Returns a KeyTemplate that generates new instances of // EciesAeadHkdfPrivateKey with the following parameters: // - KEM: ECDH over NIST P-256 // - DEM: AES128-GCM // - KDF: HKDF-HMAC-SHA256 with an empty salt // - EC Point Format: Uncompressed // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& EciesP256HkdfHmacSha256Aes128Gcm(); // Returns a KeyTemplate that generates new instances of // EciesAeadHkdfPrivateKey with the following parameters: // - KEM: ECDH over NIST P-256 // - DEM: AES128-GCM // - KDF: HKDF-HMAC-SHA512 with an empty salt // - EC Point Format: Uncompressed // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& EciesP256HkdfHmacSha512Aes128Gcm(); // Returns a KeyTemplate that generates new instances of // EciesAeadHkdfPrivateKey with the following parameters: // - KEM: ECDH over NIST P-256 // - DEM: AES128-GCM // - KDF: HKDF-HMAC-SHA256 with an empty salt // - EC Point Format: Compressed // - OutputPrefixType: RAW static const google::crypto::tink::KeyTemplate& EciesP256HkdfHmacSha256Aes128GcmCompressedWithoutPrefix(); // Returns a KeyTemplate that generates new instances of // EciesAeadHkdfPrivateKey with the following parameters: // - KEM: ECDH over NIST P-256 // - DEM: AES128-CTR-HMAC-SHA256 with the following parameters: // * AES key size: 16 bytes // * AES CTR IV size: 16 bytes // * HMAC key size: 32 bytes // * HMAC tag size: 16 bytes // - KDF: HKDF-HMAC-SHA256 with an empty salt // - EC Point Format: Uncompressed // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& EciesP256HkdfHmacSha256Aes128CtrHmacSha256(); // Returns a KeyTemplate that generates new instances of // EciesAeadHkdfPrivateKey with the following parameters: // - KEM: ECDH over NIST P-256 // - DEM: AES128-CTR-HMAC-SHA256 with the following parameters: // * AES key size: 16 bytes // * AES CTR IV size: 16 bytes // * HMAC key size: 32 bytes // * HMAC tag size: 16 bytes // - KDF: HKDF-HMAC-SHA512 with an empty salt // - EC Point Format: Uncompressed // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& EciesP256HkdfHmacSha512Aes128CtrHmacSha256(); // Returns a KeyTemplate that generates new instances of // EciesAeadHkdfPrivateKey with the following parameters: // - KEM: ECDH over NIST P-256 // - DEM: AES128-GCM // - KDF: HKDF-HMAC-SHA256 with an empty salt // - EC Point Format: Compressed // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& EciesP256CompressedHkdfHmacSha256Aes128Gcm(); // Returns a KeyTemplate that generates new instances of // EciesAeadHkdfPrivateKey with the following parameters: // - KEM: ECDH over NIST P-256 // - DEM: AES128-CTR-HMAC-SHA256 with the following parameters: // * AES key size: 16 bytes // * AES CTR IV size: 16 bytes // * HMAC key size: 32 bytes // * HMAC tag size: 16 bytes // - KDF: HKDF-HMAC-SHA256 with an empty salt // - EC Point Format: Compressed // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& EciesP256CompressedHkdfHmacSha256Aes128CtrHmacSha256(); // Returns a KeyTemplate that generates new instances of // EciesAeadHkdfPrivateKey with the following parameters: // - KEM: ECDH over curve 25519 // - DEM: AES128-GCM // - KDF: HKDF-HMAC-SHA256 with an empty salt // - EC Point Format: Compressed // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& EciesX25519HkdfHmacSha256Aes128Gcm(); // Returns a KeyTemplate that generates new instances of // EciesAeadHkdfPrivateKey with the following parameters: // - KEM: ECDH over curve 25519 // - DEM: AES256-GCM // - KDF: HKDF-HMAC-SHA256 with an empty salt // - EC Point Format: Compressed // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& EciesX25519HkdfHmacSha256Aes256Gcm(); // Returns a KeyTemplate that generates new instances of // EciesAeadHkdfPrivateKey with the following parameters: // - KEM: ECDH over curve 25519 // - DEM: AES128-CTR-HMAC-SHA256 with the following parameters: // * AES key size: 16 bytes // * AES CTR IV size: 16 bytes // * HMAC key size: 32 bytes // * HMAC tag size: 16 bytes // - KDF: HKDF-HMAC-SHA256 with an empty salt // - EC Point Format: Compressed // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& EciesX25519HkdfHmacSha256Aes128CtrHmacSha256(); // Returns a KeyTemplate that generates new instances of // EciesAeadHkdfPrivateKey with the following parameters: // - KEM: ECDH over curve 25519 // - DEM: XChaCha20-Poly1305 with the following parameters: // * XChaCha20 key size: 32 bytes // * IV size: 24 bytes // - KDF: HKDF-HMAC-SHA256 with an empty salt // - EC Point Format: Compressed // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& EciesX25519HkdfHmacSha256XChaCha20Poly1305(); // Returns a KeyTemplate that generates new instances of // EciesAeadHkdfPrivateKey with the following parameters: // - KEM: ECDH over curve 25519 // - DEM: AES-SIV (Deterministic Aead) // - KDF: HKDF-HMAC-SHA256 with an empty salt // - EC Point Format: Compressed // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& EciesX25519HkdfHmacSha256DeterministicAesSiv(); // Returns a KeyTemplate that generates new instances of // HpkePrivateKey with the following parameters: // - KEM: ECDH over curve 25519 plus HKDF-SHA256 // - KDF: HKDF-SHA256 // - AEAD: AES-128-GCM // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& HpkeX25519HkdfSha256Aes128Gcm(); // Returns a KeyTemplate that generates new instances of // HpkePrivateKey with the following parameters: // - KEM: ECDH over curve 25519 plus HKDF-SHA256 // - KDF: HKDF-SHA256 // - AEAD: AES-128-GCM // - OutputPrefixType: RAW static const google::crypto::tink::KeyTemplate& HpkeX25519HkdfSha256Aes128GcmRaw(); // Returns a KeyTemplate that generates new instances of // HpkePrivateKey with the following parameters: // - KEM: ECDH over curve 25519 plus HKDF-SHA256 // - KDF: HKDF-SHA256 // - AEAD: AES-256-GCM // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& HpkeX25519HkdfSha256Aes256Gcm(); // Returns a KeyTemplate that generates new instances of // HpkePrivateKey with the following parameters: // - KEM: ECDH over curve 25519 plus HKDF-SHA256 // - KDF: HKDF-SHA256 // - AEAD: AES-256-GCM // - OutputPrefixType: RAW static const google::crypto::tink::KeyTemplate& HpkeX25519HkdfSha256Aes256GcmRaw(); // Returns a KeyTemplate that generates new instances of // HpkePrivateKey with the following parameters: // - KEM: ECDH over curve 25519 plus HKDF-SHA256 // - KDF: HKDF-SHA256 // - AEAD: ChaCha20-Poly1305 // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& HpkeX25519HkdfSha256ChaCha20Poly1305(); // Returns a KeyTemplate that generates new instances of // HpkePrivateKey with the following parameters: // - KEM: ECDH over curve 25519 plus HKDF-SHA256 // - KDF: HKDF-SHA256 // - AEAD: ChaCha20-Poly1305 // - OutputPrefixType: RAW static const google::crypto::tink::KeyTemplate& HpkeX25519HkdfSha256ChaCha20Poly1305Raw(); }; } // namespace tink } // namespace crypto #endif // TINK_HYBRID_HYBRID_KEY_TEMPLATES_H_ ================================================ FILE: cc/hybrid/hybrid_key_templates_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/hybrid_key_templates.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/aead/aead_key_templates.h" #include "tink/daead/deterministic_aead_key_templates.h" #include "tink/hybrid/ecies_aead_hkdf_private_key_manager.h" #include "tink/hybrid/hybrid_config.h" #include "tink/hybrid/internal/hpke_private_key_manager.h" #include "tink/util/test_matchers.h" #include "proto/common.pb.h" #include "proto/ecies_aead_hkdf.pb.h" #include "proto/hpke.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::internal::HpkePrivateKeyManager; using ::crypto::tink::test::IsOk; using ::google::crypto::tink::EciesAeadHkdfKeyFormat; using ::google::crypto::tink::EcPointFormat; using ::google::crypto::tink::EllipticCurveType; using ::google::crypto::tink::HashType; using ::google::crypto::tink::HpkeAead; using ::google::crypto::tink::HpkeKdf; using ::google::crypto::tink::HpkeKem; using ::google::crypto::tink::HpkeKeyFormat; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; class HybridKeyTemplatesTest : public ::testing::Test { protected: static void SetUpTestSuite() { // Initialize the registry, so that the templates can be tested. ASSERT_THAT(HybridConfig::Register(), IsOk()); } }; TEST_F(HybridKeyTemplatesTest, EciesP256HkdfHmacSha256Aes128Gcm) { // Check that returned template is correct. std::string type_url = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey"; const KeyTemplate& key_template = HybridKeyTemplates::EciesP256HkdfHmacSha256Aes128Gcm(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); EciesAeadHkdfKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(EcPointFormat::UNCOMPRESSED, key_format.params().ec_point_format()); auto dem_params = key_format.mutable_params()->mutable_dem_params(); auto expected_dem = AeadKeyTemplates::Aes128Gcm(); EXPECT_EQ(expected_dem.output_prefix_type(), dem_params->aead_dem().output_prefix_type()); EXPECT_EQ(expected_dem.type_url(), dem_params->aead_dem().type_url()); EXPECT_EQ(expected_dem.value(), dem_params->aead_dem().value()); auto kem_params = key_format.mutable_params()->mutable_kem_params(); EXPECT_EQ(EllipticCurveType::NIST_P256, kem_params->curve_type()); EXPECT_EQ(HashType::SHA256, kem_params->hkdf_hash_type()); EXPECT_EQ("", kem_params->hkdf_salt()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = HybridKeyTemplates::EciesP256HkdfHmacSha256Aes128Gcm(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. EciesAeadHkdfPrivateKeyManager key_manager; EXPECT_EQ(key_manager.get_key_type(), key_template.type_url()); EXPECT_THAT(key_manager.ValidateKeyFormat(key_format), IsOk()); } TEST_F(HybridKeyTemplatesTest, EciesP256HkdfHmacSha512Aes128Gcm) { // Check that returned template is correct. std::string type_url = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey"; const KeyTemplate& key_template = HybridKeyTemplates::EciesP256HkdfHmacSha512Aes128Gcm(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); EciesAeadHkdfKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(EcPointFormat::UNCOMPRESSED, key_format.params().ec_point_format()); auto dem_params = key_format.mutable_params()->mutable_dem_params(); auto expected_dem = AeadKeyTemplates::Aes128Gcm(); EXPECT_EQ(expected_dem.output_prefix_type(), dem_params->aead_dem().output_prefix_type()); EXPECT_EQ(expected_dem.type_url(), dem_params->aead_dem().type_url()); EXPECT_EQ(expected_dem.value(), dem_params->aead_dem().value()); auto kem_params = key_format.mutable_params()->mutable_kem_params(); EXPECT_EQ(EllipticCurveType::NIST_P256, kem_params->curve_type()); EXPECT_EQ(HashType::SHA512, kem_params->hkdf_hash_type()); EXPECT_EQ("", kem_params->hkdf_salt()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = HybridKeyTemplates::EciesP256HkdfHmacSha512Aes128Gcm(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. EciesAeadHkdfPrivateKeyManager key_manager; EXPECT_EQ(key_manager.get_key_type(), key_template.type_url()); EXPECT_THAT(key_manager.ValidateKeyFormat(key_format), IsOk()); } TEST_F(HybridKeyTemplatesTest, EciesP256HkdfHmacSha256Aes128GcmCompressedWithoutPrefix) { // Check that returned template is correct. std::string type_url = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey"; const KeyTemplate& key_template = HybridKeyTemplates:: EciesP256HkdfHmacSha256Aes128GcmCompressedWithoutPrefix(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::RAW, key_template.output_prefix_type()); EciesAeadHkdfKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(EcPointFormat::COMPRESSED, key_format.params().ec_point_format()); auto dem_params = key_format.mutable_params()->mutable_dem_params(); auto expected_dem = AeadKeyTemplates::Aes128Gcm(); EXPECT_EQ(expected_dem.output_prefix_type(), dem_params->aead_dem().output_prefix_type()); EXPECT_EQ(expected_dem.type_url(), dem_params->aead_dem().type_url()); EXPECT_EQ(expected_dem.value(), dem_params->aead_dem().value()); auto kem_params = key_format.mutable_params()->mutable_kem_params(); EXPECT_EQ(EllipticCurveType::NIST_P256, kem_params->curve_type()); EXPECT_EQ(HashType::SHA256, kem_params->hkdf_hash_type()); EXPECT_EQ("", kem_params->hkdf_salt()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = HybridKeyTemplates:: EciesP256HkdfHmacSha256Aes128GcmCompressedWithoutPrefix(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. EciesAeadHkdfPrivateKeyManager key_manager; EXPECT_EQ(key_manager.get_key_type(), key_template.type_url()); EXPECT_THAT(key_manager.ValidateKeyFormat(key_format), IsOk()); } TEST_F(HybridKeyTemplatesTest, EciesP256HkdfHmacSha256Aes128CtrHmacSha256) { // Check that returned template is correct. std::string type_url = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey"; const KeyTemplate& key_template = HybridKeyTemplates::EciesP256HkdfHmacSha256Aes128CtrHmacSha256(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); EciesAeadHkdfKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(EcPointFormat::UNCOMPRESSED, key_format.params().ec_point_format()); auto dem_params = key_format.mutable_params()->mutable_dem_params(); auto expected_dem = AeadKeyTemplates::Aes128CtrHmacSha256(); EXPECT_EQ(expected_dem.output_prefix_type(), dem_params->aead_dem().output_prefix_type()); EXPECT_EQ(expected_dem.type_url(), dem_params->aead_dem().type_url()); EXPECT_EQ(expected_dem.value(), dem_params->aead_dem().value()); auto kem_params = key_format.mutable_params()->mutable_kem_params(); EXPECT_EQ(EllipticCurveType::NIST_P256, kem_params->curve_type()); EXPECT_EQ(HashType::SHA256, kem_params->hkdf_hash_type()); EXPECT_EQ("", kem_params->hkdf_salt()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = HybridKeyTemplates::EciesP256HkdfHmacSha256Aes128CtrHmacSha256(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. EciesAeadHkdfPrivateKeyManager key_manager; EXPECT_EQ(key_manager.get_key_type(), key_template.type_url()); EXPECT_THAT(key_manager.ValidateKeyFormat(key_format), IsOk()); } TEST_F(HybridKeyTemplatesTest, EciesP256HkdfHmacSha512Aes128CtrHmacSha256) { // Check that returned template is correct. std::string type_url = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey"; const KeyTemplate& key_template = HybridKeyTemplates::EciesP256HkdfHmacSha512Aes128CtrHmacSha256(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); EciesAeadHkdfKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(EcPointFormat::UNCOMPRESSED, key_format.params().ec_point_format()); auto dem_params = key_format.mutable_params()->mutable_dem_params(); auto expected_dem = AeadKeyTemplates::Aes128CtrHmacSha256(); EXPECT_EQ(expected_dem.output_prefix_type(), dem_params->aead_dem().output_prefix_type()); EXPECT_EQ(expected_dem.type_url(), dem_params->aead_dem().type_url()); EXPECT_EQ(expected_dem.value(), dem_params->aead_dem().value()); auto kem_params = key_format.mutable_params()->mutable_kem_params(); EXPECT_EQ(EllipticCurveType::NIST_P256, kem_params->curve_type()); EXPECT_EQ(HashType::SHA512, kem_params->hkdf_hash_type()); EXPECT_EQ("", kem_params->hkdf_salt()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = HybridKeyTemplates::EciesP256HkdfHmacSha512Aes128CtrHmacSha256(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. EciesAeadHkdfPrivateKeyManager key_manager; EXPECT_EQ(key_manager.get_key_type(), key_template.type_url()); EXPECT_THAT(key_manager.ValidateKeyFormat(key_format), IsOk()); } TEST_F(HybridKeyTemplatesTest, EciesP256CompressedHkdfHmacSha256Aes128Gcm) { // Check that returned template is correct. std::string type_url = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey"; const KeyTemplate& key_template = HybridKeyTemplates::EciesP256CompressedHkdfHmacSha256Aes128Gcm(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); EciesAeadHkdfKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(EcPointFormat::COMPRESSED, key_format.params().ec_point_format()); auto dem_params = key_format.mutable_params()->mutable_dem_params(); auto expected_dem = AeadKeyTemplates::Aes128Gcm(); EXPECT_EQ(expected_dem.output_prefix_type(), dem_params->aead_dem().output_prefix_type()); EXPECT_EQ(expected_dem.type_url(), dem_params->aead_dem().type_url()); EXPECT_EQ(expected_dem.value(), dem_params->aead_dem().value()); auto kem_params = key_format.mutable_params()->mutable_kem_params(); EXPECT_EQ(EllipticCurveType::NIST_P256, kem_params->curve_type()); EXPECT_EQ(HashType::SHA256, kem_params->hkdf_hash_type()); EXPECT_EQ("", kem_params->hkdf_salt()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = HybridKeyTemplates::EciesP256CompressedHkdfHmacSha256Aes128Gcm(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. EciesAeadHkdfPrivateKeyManager key_manager; EXPECT_EQ(key_manager.get_key_type(), key_template.type_url()); EXPECT_THAT(key_manager.ValidateKeyFormat(key_format), IsOk()); } TEST_F(HybridKeyTemplatesTest, EciesP256CompressedHkdfHmacSha256Aes128CtrHmacSha256) { // Check that returned template is correct. std::string type_url = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey"; const KeyTemplate& key_template = HybridKeyTemplates:: EciesP256CompressedHkdfHmacSha256Aes128CtrHmacSha256(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); EciesAeadHkdfKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(EcPointFormat::COMPRESSED, key_format.params().ec_point_format()); auto dem_params = key_format.mutable_params()->mutable_dem_params(); auto expected_dem = AeadKeyTemplates::Aes128CtrHmacSha256(); EXPECT_EQ(expected_dem.output_prefix_type(), dem_params->aead_dem().output_prefix_type()); EXPECT_EQ(expected_dem.type_url(), dem_params->aead_dem().type_url()); EXPECT_EQ(expected_dem.value(), dem_params->aead_dem().value()); auto kem_params = key_format.mutable_params()->mutable_kem_params(); EXPECT_EQ(EllipticCurveType::NIST_P256, kem_params->curve_type()); EXPECT_EQ(HashType::SHA256, kem_params->hkdf_hash_type()); EXPECT_EQ("", kem_params->hkdf_salt()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = HybridKeyTemplates:: EciesP256CompressedHkdfHmacSha256Aes128CtrHmacSha256(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. EciesAeadHkdfPrivateKeyManager key_manager; EXPECT_EQ(key_manager.get_key_type(), key_template.type_url()); EXPECT_THAT(key_manager.ValidateKeyFormat(key_format), IsOk()); } TEST_F(HybridKeyTemplatesTest, EciesX25519HkdfHmacSha256Aes128Gcm) { // Check that returned template is correct. std::string type_url = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey"; const KeyTemplate& key_template = HybridKeyTemplates::EciesX25519HkdfHmacSha256Aes128Gcm(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); EciesAeadHkdfKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(EcPointFormat::COMPRESSED, key_format.params().ec_point_format()); auto dem_params = key_format.mutable_params()->mutable_dem_params(); auto expected_dem = AeadKeyTemplates::Aes128Gcm(); EXPECT_EQ(expected_dem.output_prefix_type(), dem_params->aead_dem().output_prefix_type()); EXPECT_EQ(expected_dem.type_url(), dem_params->aead_dem().type_url()); EXPECT_EQ(expected_dem.value(), dem_params->aead_dem().value()); auto kem_params = key_format.mutable_params()->mutable_kem_params(); EXPECT_EQ(EllipticCurveType::CURVE25519, kem_params->curve_type()); EXPECT_EQ(HashType::SHA256, kem_params->hkdf_hash_type()); EXPECT_EQ("", kem_params->hkdf_salt()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = HybridKeyTemplates::EciesX25519HkdfHmacSha256Aes128Gcm(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. EciesAeadHkdfPrivateKeyManager key_manager; EXPECT_EQ(key_manager.get_key_type(), key_template.type_url()); EXPECT_THAT(key_manager.ValidateKeyFormat(key_format), IsOk()); } TEST_F(HybridKeyTemplatesTest, EciesX25519HkdfHmacSha256Aes256Gcm) { // Check that returned template is correct. std::string type_url = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey"; const KeyTemplate& key_template = HybridKeyTemplates::EciesX25519HkdfHmacSha256Aes256Gcm(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); EciesAeadHkdfKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(EcPointFormat::COMPRESSED, key_format.params().ec_point_format()); auto dem_params = key_format.mutable_params()->mutable_dem_params(); auto expected_dem = AeadKeyTemplates::Aes256Gcm(); EXPECT_EQ(expected_dem.output_prefix_type(), dem_params->aead_dem().output_prefix_type()); EXPECT_EQ(expected_dem.type_url(), dem_params->aead_dem().type_url()); EXPECT_EQ(expected_dem.value(), dem_params->aead_dem().value()); auto kem_params = key_format.mutable_params()->mutable_kem_params(); EXPECT_EQ(EllipticCurveType::CURVE25519, kem_params->curve_type()); EXPECT_EQ(HashType::SHA256, kem_params->hkdf_hash_type()); EXPECT_EQ("", kem_params->hkdf_salt()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = HybridKeyTemplates::EciesX25519HkdfHmacSha256Aes256Gcm(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. EciesAeadHkdfPrivateKeyManager key_manager; EXPECT_EQ(key_manager.get_key_type(), key_template.type_url()); EXPECT_THAT(key_manager.ValidateKeyFormat(key_format), IsOk()); } TEST_F(HybridKeyTemplatesTest, EciesX25519HkdfHmacSha256Aes128CtrHmacSha256) { // Check that returned template is correct. std::string type_url = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey"; const KeyTemplate& key_template = HybridKeyTemplates::EciesX25519HkdfHmacSha256Aes128CtrHmacSha256(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); EciesAeadHkdfKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(EcPointFormat::COMPRESSED, key_format.params().ec_point_format()); auto dem_params = key_format.mutable_params()->mutable_dem_params(); auto expected_dem = AeadKeyTemplates::Aes128CtrHmacSha256(); EXPECT_EQ(expected_dem.output_prefix_type(), dem_params->aead_dem().output_prefix_type()); EXPECT_EQ(expected_dem.type_url(), dem_params->aead_dem().type_url()); EXPECT_EQ(expected_dem.value(), dem_params->aead_dem().value()); auto kem_params = key_format.mutable_params()->mutable_kem_params(); EXPECT_EQ(EllipticCurveType::CURVE25519, kem_params->curve_type()); EXPECT_EQ(HashType::SHA256, kem_params->hkdf_hash_type()); EXPECT_EQ("", kem_params->hkdf_salt()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = HybridKeyTemplates::EciesX25519HkdfHmacSha256Aes128CtrHmacSha256(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. EciesAeadHkdfPrivateKeyManager key_manager; EXPECT_EQ(key_manager.get_key_type(), key_template.type_url()); EXPECT_THAT(key_manager.ValidateKeyFormat(key_format), IsOk()); } TEST_F(HybridKeyTemplatesTest, EciesX25519HkdfHmacSha256XChaCha20Poly1305) { // Check that returned template is correct. std::string type_url = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey"; const KeyTemplate& key_template = HybridKeyTemplates::EciesX25519HkdfHmacSha256XChaCha20Poly1305(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); EciesAeadHkdfKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(EcPointFormat::COMPRESSED, key_format.params().ec_point_format()); auto dem_params = key_format.mutable_params()->mutable_dem_params(); auto expected_dem = AeadKeyTemplates::XChaCha20Poly1305(); EXPECT_EQ(expected_dem.output_prefix_type(), dem_params->aead_dem().output_prefix_type()); EXPECT_EQ(expected_dem.type_url(), dem_params->aead_dem().type_url()); EXPECT_EQ(expected_dem.value(), dem_params->aead_dem().value()); auto kem_params = key_format.mutable_params()->mutable_kem_params(); EXPECT_EQ(EllipticCurveType::CURVE25519, kem_params->curve_type()); EXPECT_EQ(HashType::SHA256, kem_params->hkdf_hash_type()); EXPECT_EQ("", kem_params->hkdf_salt()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = HybridKeyTemplates::EciesX25519HkdfHmacSha256XChaCha20Poly1305(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. EciesAeadHkdfPrivateKeyManager key_manager; EXPECT_EQ(key_manager.get_key_type(), key_template.type_url()); EXPECT_THAT(key_manager.ValidateKeyFormat(key_format), IsOk()); } TEST_F(HybridKeyTemplatesTest, EciesX25519HkdfHmacSha256DeterministicAesSiv) { // Check that returned template is correct. std::string type_url = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey"; const KeyTemplate& key_template = HybridKeyTemplates::EciesX25519HkdfHmacSha256DeterministicAesSiv(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); EciesAeadHkdfKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(EcPointFormat::COMPRESSED, key_format.params().ec_point_format()); auto dem_params = key_format.mutable_params()->mutable_dem_params(); auto expected_dem = DeterministicAeadKeyTemplates::Aes256Siv(); EXPECT_EQ(expected_dem.output_prefix_type(), dem_params->aead_dem().output_prefix_type()); EXPECT_EQ(expected_dem.type_url(), dem_params->aead_dem().type_url()); EXPECT_EQ(expected_dem.value(), dem_params->aead_dem().value()); auto kem_params = key_format.mutable_params()->mutable_kem_params(); EXPECT_EQ(EllipticCurveType::CURVE25519, kem_params->curve_type()); EXPECT_EQ(HashType::SHA256, kem_params->hkdf_hash_type()); EXPECT_EQ("", kem_params->hkdf_salt()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = HybridKeyTemplates::EciesX25519HkdfHmacSha256DeterministicAesSiv(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. EciesAeadHkdfPrivateKeyManager key_manager; EXPECT_EQ(key_manager.get_key_type(), key_template.type_url()); EXPECT_THAT(key_manager.ValidateKeyFormat(key_format), IsOk()); } TEST_F(HybridKeyTemplatesTest, HpkeX25519HkdfSha256Aes128Gcm) { // Check that returned template is correct. std::string type_url = "type.googleapis.com/google.crypto.tink.HpkePrivateKey"; const KeyTemplate& key_template = HybridKeyTemplates::HpkeX25519HkdfSha256Aes128Gcm(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); HpkeKeyFormat key_format; ASSERT_TRUE(key_format.ParseFromString(key_template.value())); ASSERT_TRUE(key_format.has_params()); EXPECT_THAT(key_format.params().kem(), Eq(HpkeKem::DHKEM_X25519_HKDF_SHA256)); EXPECT_THAT(key_format.params().kdf(), Eq(HpkeKdf::HKDF_SHA256)); EXPECT_THAT(key_format.params().aead(), Eq(HpkeAead::AES_128_GCM)); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = HybridKeyTemplates::HpkeX25519HkdfSha256Aes128Gcm(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. HpkePrivateKeyManager key_manager; EXPECT_EQ(key_manager.get_key_type(), key_template.type_url()); EXPECT_THAT(key_manager.ValidateKeyFormat(key_format), IsOk()); } TEST_F(HybridKeyTemplatesTest, HpkeX25519HkdfSha256Aes128GcmRaw) { // Check that returned template is correct. std::string type_url = "type.googleapis.com/google.crypto.tink.HpkePrivateKey"; const KeyTemplate& key_template = HybridKeyTemplates::HpkeX25519HkdfSha256Aes128GcmRaw(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::RAW, key_template.output_prefix_type()); HpkeKeyFormat key_format; ASSERT_TRUE(key_format.ParseFromString(key_template.value())); ASSERT_TRUE(key_format.has_params()); EXPECT_THAT(key_format.params().kem(), Eq(HpkeKem::DHKEM_X25519_HKDF_SHA256)); EXPECT_THAT(key_format.params().kdf(), Eq(HpkeKdf::HKDF_SHA256)); EXPECT_THAT(key_format.params().aead(), Eq(HpkeAead::AES_128_GCM)); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = HybridKeyTemplates::HpkeX25519HkdfSha256Aes128GcmRaw(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. HpkePrivateKeyManager key_manager; EXPECT_EQ(key_manager.get_key_type(), key_template.type_url()); EXPECT_THAT(key_manager.ValidateKeyFormat(key_format), IsOk()); } TEST_F(HybridKeyTemplatesTest, HpkeX25519HkdfSha256Aes256Gcm) { // Check that returned template is correct. std::string type_url = "type.googleapis.com/google.crypto.tink.HpkePrivateKey"; const KeyTemplate& key_template = HybridKeyTemplates::HpkeX25519HkdfSha256Aes256Gcm(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); HpkeKeyFormat key_format; ASSERT_TRUE(key_format.ParseFromString(key_template.value())); ASSERT_TRUE(key_format.has_params()); EXPECT_THAT(key_format.params().kem(), Eq(HpkeKem::DHKEM_X25519_HKDF_SHA256)); EXPECT_THAT(key_format.params().kdf(), Eq(HpkeKdf::HKDF_SHA256)); EXPECT_THAT(key_format.params().aead(), Eq(HpkeAead::AES_256_GCM)); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = HybridKeyTemplates::HpkeX25519HkdfSha256Aes256Gcm(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. HpkePrivateKeyManager key_manager; EXPECT_EQ(key_manager.get_key_type(), key_template.type_url()); EXPECT_THAT(key_manager.ValidateKeyFormat(key_format), IsOk()); } TEST_F(HybridKeyTemplatesTest, HpkeX25519HkdfSha256Aes256GcmRaw) { // Check that returned template is correct. std::string type_url = "type.googleapis.com/google.crypto.tink.HpkePrivateKey"; const KeyTemplate& key_template = HybridKeyTemplates::HpkeX25519HkdfSha256Aes256GcmRaw(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::RAW, key_template.output_prefix_type()); HpkeKeyFormat key_format; ASSERT_TRUE(key_format.ParseFromString(key_template.value())); ASSERT_TRUE(key_format.has_params()); EXPECT_THAT(key_format.params().kem(), Eq(HpkeKem::DHKEM_X25519_HKDF_SHA256)); EXPECT_THAT(key_format.params().kdf(), Eq(HpkeKdf::HKDF_SHA256)); EXPECT_THAT(key_format.params().aead(), Eq(HpkeAead::AES_256_GCM)); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = HybridKeyTemplates::HpkeX25519HkdfSha256Aes256GcmRaw(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. HpkePrivateKeyManager key_manager; EXPECT_EQ(key_manager.get_key_type(), key_template.type_url()); EXPECT_THAT(key_manager.ValidateKeyFormat(key_format), IsOk()); } TEST_F(HybridKeyTemplatesTest, HpkeX25519HkdfSha256ChaCha20Poly1305) { // Check that returned template is correct. std::string type_url = "type.googleapis.com/google.crypto.tink.HpkePrivateKey"; const KeyTemplate& key_template = HybridKeyTemplates::HpkeX25519HkdfSha256ChaCha20Poly1305(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); HpkeKeyFormat key_format; ASSERT_TRUE(key_format.ParseFromString(key_template.value())); ASSERT_TRUE(key_format.has_params()); EXPECT_THAT(key_format.params().kem(), Eq(HpkeKem::DHKEM_X25519_HKDF_SHA256)); EXPECT_THAT(key_format.params().kdf(), Eq(HpkeKdf::HKDF_SHA256)); EXPECT_THAT(key_format.params().aead(), Eq(HpkeAead::CHACHA20_POLY1305)); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = HybridKeyTemplates::HpkeX25519HkdfSha256ChaCha20Poly1305(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. HpkePrivateKeyManager key_manager; EXPECT_EQ(key_manager.get_key_type(), key_template.type_url()); EXPECT_THAT(key_manager.ValidateKeyFormat(key_format), IsOk()); } TEST_F(HybridKeyTemplatesTest, HpkeX25519HkdfSha256ChaCha20Poly1305Raw) { // Check that returned template is correct. std::string type_url = "type.googleapis.com/google.crypto.tink.HpkePrivateKey"; const KeyTemplate& key_template = HybridKeyTemplates::HpkeX25519HkdfSha256ChaCha20Poly1305Raw(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::RAW, key_template.output_prefix_type()); HpkeKeyFormat key_format; ASSERT_TRUE(key_format.ParseFromString(key_template.value())); ASSERT_TRUE(key_format.has_params()); EXPECT_THAT(key_format.params().kem(), Eq(HpkeKem::DHKEM_X25519_HKDF_SHA256)); EXPECT_THAT(key_format.params().kdf(), Eq(HpkeKdf::HKDF_SHA256)); EXPECT_THAT(key_format.params().aead(), Eq(HpkeAead::CHACHA20_POLY1305)); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = HybridKeyTemplates::HpkeX25519HkdfSha256ChaCha20Poly1305Raw(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. HpkePrivateKeyManager key_manager; EXPECT_EQ(key_manager.get_key_type(), key_template.type_url()); EXPECT_THAT(key_manager.ValidateKeyFormat(key_format), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/hybrid_parameters.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_HYBRID_PARAMETERS_H_ #define TINK_HYBRID_HYBRID_PARAMETERS_H_ #include "tink/parameters.h" namespace crypto { namespace tink { // Describes a hybrid encryption key pair (e.g., key attributes), excluding the // randomly chosen key material. class HybridParameters : public Parameters {}; } // namespace tink } // namespace crypto #endif // TINK_HYBRID_HYBRID_PARAMETERS_H_ ================================================ FILE: cc/hybrid/hybrid_private_key.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_HYBRID_PRIVATE_KEY_H_ #define TINK_HYBRID_HYBRID_PRIVATE_KEY_H_ #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/hybrid/hybrid_parameters.h" #include "tink/hybrid/hybrid_public_key.h" #include "tink/key.h" #include "tink/private_key.h" namespace crypto { namespace tink { // Represents the decryption function for a hybrid encryption primitive. class HybridPrivateKey : public PrivateKey { public: const HybridPublicKey& GetPublicKey() const override = 0; // Returns the bytes prefixed to every ciphertext generated by the // corresponding public key. // // In order to make key rotation more efficient, Tink allows every hybrid // private key to have an associated ciphertext output prefix. When decrypting // a ciphertext, only keys with a matching prefix have to be tried. // // See https://developers.google.com/tink/wire-format#tink_output_prefix for // more background information on Tink output prefixes. absl::string_view GetOutputPrefix() const { return GetPublicKey().GetOutputPrefix(); } absl::optional GetIdRequirement() const override { return GetPublicKey().GetIdRequirement(); } const HybridParameters& GetParameters() const override { return GetPublicKey().GetParameters(); } bool operator==(const Key& other) const override = 0; }; } // namespace tink } // namespace crypto #endif // TINK_HYBRID_HYBRID_PRIVATE_KEY_H_ ================================================ FILE: cc/hybrid/hybrid_public_key.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_HYBRID_PUBLIC_KEY_H_ #define TINK_HYBRID_HYBRID_PUBLIC_KEY_H_ #include "absl/strings/string_view.h" #include "tink/hybrid/hybrid_parameters.h" #include "tink/key.h" namespace crypto { namespace tink { // Represents the encryption function for a hybrid encryption primitive. class HybridPublicKey : public Key { public: // Returns the bytes prefixed to every ciphertext generated by this key. // // In order to make key rotation more efficient, Tink allows every hybrid // public key to have an associated ciphertext output prefix. When decrypting // a ciphertext, only keys with a matching prefix have to be tried. // // See https://developers.google.com/tink/wire-format#tink_output_prefix for // more background information on Tink output prefixes. virtual absl::string_view GetOutputPrefix() const = 0; const HybridParameters& GetParameters() const override = 0; bool operator==(const Key& other) const override = 0; }; } // namespace tink } // namespace crypto #endif // TINK_HYBRID_HYBRID_PUBLIC_KEY_H_ ================================================ FILE: cc/hybrid/internal/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "hpke_context", srcs = ["hpke_context.cc"], hdrs = ["hpke_context.h"], include_prefix = "tink/hybrid/internal", tags = ["requires_boringcrypto_update"], visibility = ["//visibility:public"], deps = [ ":hpke_context_boringssl", ":hpke_util", "//util:secret_data", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "hpke_context_boringssl", srcs = ["hpke_context_boringssl.cc"], hdrs = ["hpke_context_boringssl.h"], include_prefix = "tink/hybrid/internal", tags = ["requires_boringcrypto_update"], deps = [ ":hpke_util", ":hpke_util_boringssl", "//internal:ssl_unique_ptr", "//subtle:subtle_util", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "hpke_decrypt", srcs = ["hpke_decrypt.cc"], hdrs = ["hpke_decrypt.h"], include_prefix = "tink/hybrid/internal", tags = ["requires_boringcrypto_update"], deps = [ ":hpke_context", ":hpke_util", "//:hybrid_decrypt", "//proto:hpke_cc_proto", "//util:secret_data", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "hpke_decrypt_boringssl", srcs = ["hpke_decrypt_boringssl.cc"], hdrs = ["hpke_decrypt_boringssl.h"], include_prefix = "tink/hybrid/internal", tags = ["requires_boringcrypto_update"], deps = [ ":hpke_key_boringssl", ":hpke_util_boringssl", "//proto:hpke_cc_proto", "//subtle:subtle_util", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "hpke_encrypt", srcs = ["hpke_encrypt.cc"], hdrs = ["hpke_encrypt.h"], include_prefix = "tink/hybrid/internal", tags = ["requires_boringcrypto_update"], deps = [ ":hpke_context", ":hpke_util", "//:hybrid_encrypt", "//proto:hpke_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "hpke_encrypt_boringssl", srcs = ["hpke_encrypt_boringssl.cc"], hdrs = ["hpke_encrypt_boringssl.h"], include_prefix = "tink/hybrid/internal", tags = ["requires_boringcrypto_update"], deps = [ ":hpke_util_boringssl", "//proto:hpke_cc_proto", "//subtle:subtle_util", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/algorithm:container", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "hpke_key_boringssl", srcs = ["hpke_key_boringssl.cc"], hdrs = ["hpke_key_boringssl.h"], include_prefix = "tink/hybrid/internal", tags = ["requires_boringcrypto_update"], deps = [ ":hpke_util_boringssl", "//proto:hpke_cc_proto", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "hpke_key_manager_util", srcs = ["hpke_key_manager_util.cc"], hdrs = ["hpke_key_manager_util.h"], include_prefix = "tink/hybrid/internal", deps = [ "//proto:hpke_cc_proto", "//util:status", "//util:validation", "@com_google_absl//absl/status", ], ) cc_library( name = "hpke_private_key_manager", srcs = ["hpke_private_key_manager.cc"], hdrs = ["hpke_private_key_manager.h"], include_prefix = "tink/hybrid/internal", tags = ["requires_boringcrypto_update"], deps = [ ":hpke_decrypt", ":hpke_key_manager_util", "//:core/key_type_manager", "//:core/private_key_type_manager", "//:core/template_util", "//:hybrid_decrypt", "//:key_manager", "//internal:ec_util", "//internal:ssl_unique_ptr", "//proto:hpke_cc_proto", "//proto:tink_cc_proto", "//subtle:common_enums", "//util:constants", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "hpke_public_key_manager", srcs = ["hpke_public_key_manager.cc"], hdrs = ["hpke_public_key_manager.h"], include_prefix = "tink/hybrid/internal", tags = ["requires_boringcrypto_update"], deps = [ ":hpke_encrypt", ":hpke_key_manager_util", "//:core/key_type_manager", "//:core/template_util", "//:hybrid_encrypt", "//:key_manager", "//proto:hpke_cc_proto", "//proto:tink_cc_proto", "//util:constants", "//util:errors", "//util:protobuf_helper", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/strings", ], ) cc_library( name = "hpke_test_util", testonly = 1, srcs = ["hpke_test_util.cc"], hdrs = ["hpke_test_util.h"], include_prefix = "tink/hybrid/internal", deps = [ ":hpke_util", "//proto:hpke_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "hpke_util", srcs = ["hpke_util.cc"], hdrs = ["hpke_util.h"], include_prefix = "tink/hybrid/internal", deps = [ "//internal:ec_util", "//proto:hpke_cc_proto", "//subtle:common_enums", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "hpke_util_boringssl", srcs = ["hpke_util_boringssl.cc"], hdrs = ["hpke_util_boringssl.h"], include_prefix = "tink/hybrid/internal", tags = ["requires_boringcrypto_update"], deps = [ ":hpke_util", "//proto:hpke_cc_proto", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "test_hpke_context_boringssl", testonly = 1, srcs = ["test_hpke_context_boringssl.cc"], hdrs = ["test_hpke_context_boringssl.h"], include_prefix = "tink/hybrid/internal", tags = ["requires_boringcrypto_update"], deps = [ ":hpke_context_boringssl", ":hpke_util", ":hpke_util_boringssl", "//internal:ssl_unique_ptr", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "config_v0", srcs = ["config_v0.cc"], hdrs = ["config_v0.h"], include_prefix = "tink/hybrid/internal", tags = ["requires_boringcrypto_update"], deps = [ ":hpke_private_key_manager", ":hpke_public_key_manager", "//:configuration", "//hybrid:ecies_aead_hkdf_private_key_manager", "//hybrid:ecies_aead_hkdf_public_key_manager", "//hybrid:hybrid_decrypt_wrapper", "//hybrid:hybrid_encrypt_wrapper", "//internal:configuration_impl", "//util:status", "@com_google_absl//absl/memory", ], ) cc_library( name = "key_gen_config_v0", srcs = ["key_gen_config_v0.cc"], hdrs = ["key_gen_config_v0.h"], include_prefix = "tink/hybrid/internal", tags = ["requires_boringcrypto_update"], deps = [ ":hpke_private_key_manager", ":hpke_public_key_manager", "//:key_gen_configuration", "//hybrid:ecies_aead_hkdf_private_key_manager", "//hybrid:ecies_aead_hkdf_public_key_manager", "//internal:key_gen_configuration_impl", "//util:status", "@com_google_absl//absl/memory", ], ) # tests cc_test( name = "hpke_context_test", size = "small", srcs = ["hpke_context_test.cc"], tags = ["requires_boringcrypto_update"], deps = [ ":hpke_context", ":hpke_test_util", ":hpke_util", "//util:secret_data", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hpke_context_boringssl_test", size = "small", srcs = ["hpke_context_boringssl_test.cc"], tags = ["requires_boringcrypto_update"], deps = [ ":hpke_context_boringssl", ":hpke_test_util", ":hpke_util", ":test_hpke_context_boringssl", "//util:secret_data", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hpke_decrypt_boringssl_test", size = "small", srcs = ["hpke_decrypt_boringssl_test.cc"], tags = ["requires_boringcrypto_update"], deps = [ ":hpke_decrypt_boringssl", ":hpke_key_boringssl", ":hpke_test_util", "//proto:hpke_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hpke_decrypt_test", size = "small", srcs = ["hpke_decrypt_test.cc"], tags = ["requires_boringcrypto_update"], deps = [ ":hpke_decrypt", ":hpke_encrypt", ":hpke_test_util", "//:hybrid_decrypt", "//:hybrid_encrypt", "//proto:hpke_cc_proto", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hpke_encrypt_boringssl_test", size = "small", srcs = ["hpke_encrypt_boringssl_test.cc"], tags = ["requires_boringcrypto_update"], deps = [ ":hpke_encrypt_boringssl", ":hpke_test_util", "//proto:hpke_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hpke_encrypt_test", size = "small", srcs = ["hpke_encrypt_test.cc"], tags = ["requires_boringcrypto_update"], deps = [ ":hpke_encrypt", ":hpke_test_util", ":hpke_util", "//:hybrid_encrypt", "//proto:hpke_cc_proto", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hpke_key_boringssl_test", size = "small", srcs = ["hpke_key_boringssl_test.cc"], tags = ["requires_boringcrypto_update"], deps = [ ":hpke_key_boringssl", ":hpke_test_util", "//proto:hpke_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hpke_key_manager_util_test", size = "small", srcs = ["hpke_key_manager_util_test.cc"], deps = [ ":hpke_key_manager_util", ":hpke_test_util", "//proto:hpke_cc_proto", "//util:status", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hpke_private_key_manager_test", size = "small", srcs = ["hpke_private_key_manager_test.cc"], tags = ["requires_boringcrypto_update"], deps = [ ":hpke_encrypt", ":hpke_private_key_manager", "//:hybrid_decrypt", "//:hybrid_encrypt", "//proto:hpke_cc_proto", "//proto:tink_cc_proto", "//subtle:hybrid_test_util", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/container:btree", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hpke_public_key_manager_test", size = "small", srcs = ["hpke_public_key_manager_test.cc"], tags = ["requires_boringcrypto_update"], deps = [ ":hpke_public_key_manager", ":hpke_test_util", "//proto:hpke_cc_proto", "//proto:tink_cc_proto", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hpke_util_boringssl_test", size = "small", srcs = ["hpke_util_boringssl_test.cc"], tags = ["requires_boringcrypto_update"], deps = [ ":hpke_test_util", ":hpke_util", ":hpke_util_boringssl", "//proto:hpke_cc_proto", "//util:statusor", "//util:test_matchers", "//util:test_util", "@boringssl//:crypto", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hpke_util_test", size = "small", srcs = ["hpke_util_test.cc"], deps = [ ":hpke_test_util", ":hpke_util", "//proto:hpke_cc_proto", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "config_v0_test", srcs = ["config_v0_test.cc"], tags = ["requires_boringcrypto_update"], deps = [ ":config_v0", ":hpke_private_key_manager", ":key_gen_config_v0", "//:configuration", "//:hybrid_decrypt", "//:hybrid_encrypt", "//:key_gen_configuration", "//:keyset_handle", "//hybrid:ecies_aead_hkdf_private_key_manager", "//hybrid:hybrid_key_templates", "//internal:configuration_impl", "//internal:key_gen_configuration_impl", "//internal:key_type_info_store", "//internal:keyset_wrapper_store", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/hybrid/internal/CMakeLists.txt ================================================ tink_module(hybrid::internal) tink_cc_library( NAME hpke_context SRCS hpke_context.cc hpke_context.h DEPS tink::hybrid::internal::hpke_context_boringssl tink::hybrid::internal::hpke_util absl::memory absl::status absl::strings tink::util::secret_data tink::util::status tink::util::statusor TAGS exclude_if_openssl ) tink_cc_library( NAME hpke_context_boringssl SRCS hpke_context_boringssl.cc hpke_context_boringssl.h DEPS tink::hybrid::internal::hpke_util tink::hybrid::internal::hpke_util_boringssl absl::memory absl::status absl::strings crypto tink::internal::ssl_unique_ptr tink::subtle::subtle_util tink::util::secret_data tink::util::status tink::util::statusor TAGS exclude_if_openssl ) tink_cc_library( NAME hpke_decrypt SRCS hpke_decrypt.cc hpke_decrypt.h DEPS tink::hybrid::internal::hpke_context tink::hybrid::internal::hpke_util absl::memory absl::status absl::string_view tink::core::hybrid_decrypt tink::util::secret_data tink::util::status tink::util::statusor tink::proto::hpke_cc_proto TAGS exclude_if_openssl ) tink_cc_library( NAME hpke_decrypt_boringssl SRCS hpke_decrypt_boringssl.cc hpke_decrypt_boringssl.h DEPS tink::hybrid::internal::hpke_key_boringssl tink::hybrid::internal::hpke_util_boringssl absl::core_headers absl::memory absl::status absl::strings crypto tink::subtle::subtle_util tink::util::status tink::util::statusor tink::proto::hpke_cc_proto TAGS exclude_if_openssl ) tink_cc_library( NAME hpke_encrypt SRCS hpke_encrypt.cc hpke_encrypt.h DEPS tink::hybrid::internal::hpke_context tink::hybrid::internal::hpke_util absl::memory absl::status absl::string_view tink::core::hybrid_encrypt tink::util::status tink::util::statusor tink::proto::hpke_cc_proto TAGS exclude_if_openssl ) tink_cc_library( NAME hpke_encrypt_boringssl SRCS hpke_encrypt_boringssl.cc hpke_encrypt_boringssl.h DEPS tink::hybrid::internal::hpke_util_boringssl absl::algorithm_container absl::core_headers absl::memory absl::status absl::strings crypto tink::subtle::subtle_util tink::util::status tink::util::statusor tink::proto::hpke_cc_proto TAGS exclude_if_openssl ) tink_cc_library( NAME hpke_key_boringssl SRCS hpke_key_boringssl.cc hpke_key_boringssl.h DEPS tink::hybrid::internal::hpke_util_boringssl absl::core_headers absl::memory absl::status absl::string_view crypto tink::util::status tink::util::statusor tink::proto::hpke_cc_proto TAGS exclude_if_openssl ) tink_cc_library( NAME hpke_key_manager_util SRCS hpke_key_manager_util.cc hpke_key_manager_util.h DEPS absl::status tink::util::status tink::util::validation tink::proto::hpke_cc_proto TAGS exclude_if_openssl ) tink_cc_library( NAME hpke_private_key_manager SRCS hpke_private_key_manager.cc hpke_private_key_manager.h DEPS tink::hybrid::internal::hpke_decrypt tink::hybrid::internal::hpke_key_manager_util absl::memory absl::status absl::strings crypto tink::core::key_type_manager tink::core::private_key_type_manager tink::core::template_util tink::core::hybrid_decrypt tink::core::key_manager tink::internal::ec_util tink::internal::ssl_unique_ptr tink::subtle::common_enums tink::util::constants tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::hpke_cc_proto tink::proto::tink_cc_proto TAGS exclude_if_openssl ) tink_cc_library( NAME hpke_public_key_manager SRCS hpke_public_key_manager.cc hpke_public_key_manager.h DEPS tink::hybrid::internal::hpke_encrypt tink::hybrid::internal::hpke_key_manager_util absl::memory absl::strings tink::core::key_type_manager tink::core::template_util tink::core::hybrid_encrypt tink::core::key_manager tink::util::constants tink::util::errors tink::util::protobuf_helper tink::util::status tink::util::statusor tink::proto::hpke_cc_proto tink::proto::tink_cc_proto TAGS exclude_if_openssl ) tink_cc_library( NAME hpke_test_util SRCS hpke_test_util.cc hpke_test_util.h DEPS tink::hybrid::internal::hpke_util absl::status absl::strings tink::util::status tink::util::statusor tink::proto::hpke_cc_proto TESTONLY TAGS exclude_if_openssl ) tink_cc_library( NAME hpke_util SRCS hpke_util.cc hpke_util.h DEPS absl::status absl::strings tink::internal::ec_util tink::subtle::common_enums tink::util::status tink::util::statusor tink::proto::hpke_cc_proto TAGS exclude_if_openssl ) tink_cc_library( NAME hpke_util_boringssl SRCS hpke_util_boringssl.cc hpke_util_boringssl.h DEPS tink::hybrid::internal::hpke_util absl::status absl::strings crypto tink::util::status tink::util::statusor tink::proto::hpke_cc_proto TAGS exclude_if_openssl ) tink_cc_library( NAME test_hpke_context_boringssl SRCS test_hpke_context_boringssl.cc test_hpke_context_boringssl.h DEPS tink::hybrid::internal::hpke_context_boringssl tink::hybrid::internal::hpke_util tink::hybrid::internal::hpke_util_boringssl absl::memory absl::status absl::strings crypto tink::internal::ssl_unique_ptr tink::util::status tink::util::statusor TESTONLY TAGS exclude_if_openssl ) tink_cc_library( NAME config_v0 SRCS config_v0.cc config_v0.h DEPS tink::hybrid::internal::hpke_private_key_manager tink::hybrid::internal::hpke_public_key_manager absl::memory tink::core::configuration tink::hybrid::ecies_aead_hkdf_private_key_manager tink::hybrid::ecies_aead_hkdf_public_key_manager tink::hybrid::hybrid_decrypt_wrapper tink::hybrid::hybrid_encrypt_wrapper tink::internal::configuration_impl tink::util::status TAGS exclude_if_openssl ) tink_cc_library( NAME config_v0_openssl SRCS config_v0.cc config_v0.h DEPS absl::memory tink::core::configuration tink::hybrid::ecies_aead_hkdf_private_key_manager tink::hybrid::ecies_aead_hkdf_public_key_manager tink::hybrid::hybrid_decrypt_wrapper tink::hybrid::hybrid_encrypt_wrapper tink::internal::configuration_impl tink::util::status TAGS exclude_if_boringssl ) tink_cc_library( NAME key_gen_config_v0 SRCS key_gen_config_v0.cc key_gen_config_v0.h DEPS tink::hybrid::internal::hpke_private_key_manager tink::hybrid::internal::hpke_public_key_manager absl::memory tink::core::key_gen_configuration tink::hybrid::ecies_aead_hkdf_private_key_manager tink::hybrid::ecies_aead_hkdf_public_key_manager tink::internal::key_gen_configuration_impl tink::util::status TAGS exclude_if_openssl ) tink_cc_library( NAME key_gen_config_v0_openssl SRCS key_gen_config_v0.cc key_gen_config_v0.h DEPS absl::memory tink::core::key_gen_configuration tink::hybrid::ecies_aead_hkdf_private_key_manager tink::hybrid::ecies_aead_hkdf_public_key_manager tink::internal::key_gen_configuration_impl tink::util::status TAGS exclude_if_boringssl ) # tests tink_cc_test( NAME hpke_context_test SRCS hpke_context_test.cc DEPS tink::hybrid::internal::hpke_context tink::hybrid::internal::hpke_test_util tink::hybrid::internal::hpke_util gmock absl::status absl::strings tink::util::secret_data tink::util::statusor tink::util::test_matchers TAGS exclude_if_openssl ) tink_cc_test( NAME hpke_context_boringssl_test SRCS hpke_context_boringssl_test.cc DEPS tink::hybrid::internal::hpke_context_boringssl tink::hybrid::internal::hpke_test_util tink::hybrid::internal::hpke_util tink::hybrid::internal::test_hpke_context_boringssl gmock absl::status crypto tink::util::secret_data tink::util::statusor tink::util::test_matchers TAGS exclude_if_openssl ) tink_cc_test( NAME hpke_decrypt_boringssl_test SRCS hpke_decrypt_boringssl_test.cc DEPS tink::hybrid::internal::hpke_decrypt_boringssl tink::hybrid::internal::hpke_key_boringssl tink::hybrid::internal::hpke_test_util gmock absl::status absl::strings crypto tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::hpke_cc_proto TAGS exclude_if_openssl ) tink_cc_test( NAME hpke_decrypt_test SRCS hpke_decrypt_test.cc DEPS tink::hybrid::internal::hpke_decrypt tink::hybrid::internal::hpke_encrypt tink::hybrid::internal::hpke_test_util gmock absl::status absl::strings tink::core::hybrid_decrypt tink::core::hybrid_encrypt tink::util::statusor tink::util::test_matchers tink::proto::hpke_cc_proto TAGS exclude_if_openssl ) tink_cc_test( NAME hpke_encrypt_boringssl_test SRCS hpke_encrypt_boringssl_test.cc DEPS tink::hybrid::internal::hpke_encrypt_boringssl tink::hybrid::internal::hpke_test_util gmock absl::status absl::strings crypto tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::hpke_cc_proto TAGS exclude_if_openssl ) tink_cc_test( NAME hpke_encrypt_test SRCS hpke_encrypt_test.cc DEPS tink::hybrid::internal::hpke_encrypt tink::hybrid::internal::hpke_test_util tink::hybrid::internal::hpke_util gmock absl::status absl::strings tink::core::hybrid_encrypt tink::util::statusor tink::util::test_matchers tink::proto::hpke_cc_proto TAGS exclude_if_openssl ) tink_cc_test( NAME hpke_key_boringssl_test SRCS hpke_key_boringssl_test.cc DEPS tink::hybrid::internal::hpke_key_boringssl tink::hybrid::internal::hpke_test_util gmock absl::status absl::strings crypto tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::hpke_cc_proto TAGS exclude_if_openssl ) tink_cc_test( NAME hpke_key_manager_util_test SRCS hpke_key_manager_util_test.cc DEPS tink::hybrid::internal::hpke_key_manager_util tink::hybrid::internal::hpke_test_util gmock absl::status tink::util::status tink::util::test_matchers tink::proto::hpke_cc_proto TAGS exclude_if_openssl ) tink_cc_test( NAME hpke_private_key_manager_test SRCS hpke_private_key_manager_test.cc DEPS tink::hybrid::internal::hpke_encrypt tink::hybrid::internal::hpke_private_key_manager gmock absl::btree absl::status tink::core::hybrid_decrypt tink::core::hybrid_encrypt tink::subtle::hybrid_test_util tink::util::statusor tink::util::test_matchers tink::proto::hpke_cc_proto tink::proto::tink_cc_proto TAGS exclude_if_openssl ) tink_cc_test( NAME hpke_public_key_manager_test SRCS hpke_public_key_manager_test.cc DEPS tink::hybrid::internal::hpke_public_key_manager tink::hybrid::internal::hpke_test_util gmock absl::status tink::util::test_matchers tink::util::test_util tink::proto::hpke_cc_proto tink::proto::tink_cc_proto TAGS exclude_if_openssl ) tink_cc_test( NAME hpke_util_boringssl_test SRCS hpke_util_boringssl_test.cc DEPS tink::hybrid::internal::hpke_test_util tink::hybrid::internal::hpke_util tink::hybrid::internal::hpke_util_boringssl gmock crypto tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::hpke_cc_proto TAGS exclude_if_openssl ) tink_cc_test( NAME hpke_util_test SRCS hpke_util_test.cc DEPS tink::hybrid::internal::hpke_test_util tink::hybrid::internal::hpke_util gmock absl::status tink::util::statusor tink::util::test_matchers tink::proto::hpke_cc_proto TAGS exclude_if_openssl ) tink_cc_test( NAME config_v0_test SRCS config_v0_test.cc DEPS tink::hybrid::internal::config_v0 tink::hybrid::internal::hpke_private_key_manager tink::hybrid::internal::key_gen_config_v0 gmock tink::core::configuration tink::core::hybrid_decrypt tink::core::hybrid_encrypt tink::core::key_gen_configuration tink::core::keyset_handle tink::hybrid::ecies_aead_hkdf_private_key_manager tink::hybrid::hybrid_key_templates tink::internal::configuration_impl tink::internal::key_gen_configuration_impl tink::internal::key_type_info_store tink::internal::keyset_wrapper_store tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto TAGS exclude_if_openssl ) tink_cc_test( NAME config_v0_openssl_test SRCS config_v0_test.cc DEPS tink::hybrid::internal::config_v0_openssl tink::hybrid::internal::key_gen_config_v0_openssl gmock tink::core::configuration tink::core::hybrid_decrypt tink::core::hybrid_encrypt tink::core::key_gen_configuration tink::core::keyset_handle tink::hybrid::ecies_aead_hkdf_private_key_manager tink::hybrid::hybrid_key_templates tink::internal::configuration_impl tink::internal::key_gen_configuration_impl tink::internal::key_type_info_store tink::internal::keyset_wrapper_store tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto TAGS exclude_if_boringssl ) ================================================ FILE: cc/hybrid/internal/config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/config_v0.h" #include "absl/memory/memory.h" #include "tink/configuration.h" #include "tink/hybrid/ecies_aead_hkdf_private_key_manager.h" #include "tink/hybrid/ecies_aead_hkdf_public_key_manager.h" #include "tink/hybrid/hybrid_decrypt_wrapper.h" #include "tink/hybrid/hybrid_encrypt_wrapper.h" #ifdef OPENSSL_IS_BORINGSSL #include "tink/hybrid/internal/hpke_private_key_manager.h" #include "tink/hybrid/internal/hpke_public_key_manager.h" #endif #include "tink/internal/configuration_impl.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { util::Status AddHybridV0(Configuration& config) { util::Status status = ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config); if (!status.ok()) { return status; } status = ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config); if (!status.ok()) { return status; } #ifdef OPENSSL_IS_BORINGSSL status = ConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config); if (!status.ok()) { return status; } #endif return ConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_INTERNAL_CONFIG_V0_H_ #define TINK_HYBRID_INTERNAL_CONFIG_V0_H_ #include "tink/configuration.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { // Add recommended Hybrid Encryption primitive wrappers and key managers to // `config`, used to generate primitives. util::Status AddHybridV0(Configuration& config); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_HYBRID_INTERNAL_CONFIG_V0_H_ ================================================ FILE: cc/hybrid/internal/config_v0_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/config_v0.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/configuration.h" #include "tink/hybrid/ecies_aead_hkdf_private_key_manager.h" #include "tink/hybrid/hybrid_key_templates.h" #ifdef OPENSSL_IS_BORINGSSL #include "tink/hybrid/internal/hpke_private_key_manager.h" #endif #include "tink/hybrid/internal/key_gen_config_v0.h" #include "tink/hybrid_decrypt.h" #include "tink/hybrid_encrypt.h" #include "tink/internal/configuration_impl.h" #include "tink/internal/key_gen_configuration_impl.h" #include "tink/internal/key_type_info_store.h" #include "tink/internal/keyset_wrapper_store.h" #include "tink/key_gen_configuration.h" #include "tink/keyset_handle.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::google::crypto::tink::KeyTemplate; using ::testing::TestWithParam; using ::testing::Values; TEST(HybridV0Test, PrimitiveWrappers) { Configuration config; ASSERT_THAT(AddHybridV0(config), IsOk()); util::StatusOr store = ConfigurationImpl::GetKeysetWrapperStore(config); ASSERT_THAT(store, IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); } TEST(HybridV0Test, KeyManagers) { Configuration config; ASSERT_THAT(AddHybridV0(config), IsOk()); util::StatusOr store = ConfigurationImpl::GetKeyTypeInfoStore(config); ASSERT_THAT(store, IsOk()); KeyGenConfiguration key_gen_config; ASSERT_THAT(AddHybridKeyGenV0(key_gen_config), IsOk()); util::StatusOr key_gen_store = KeyGenConfigurationImpl::GetKeyTypeInfoStore(key_gen_config); ASSERT_THAT(key_gen_store, IsOk()); for (const KeyTypeInfoStore* s : {*store, *key_gen_store}) { EXPECT_THAT(s->Get(EciesAeadHkdfPrivateKeyManager().get_key_type()), IsOk()); #ifdef OPENSSL_IS_BORINGSSL EXPECT_THAT(s->Get(HpkePrivateKeyManager().get_key_type()), IsOk()); #endif } } using HybridV0KeyTypesTest = TestWithParam; #ifdef OPENSSL_IS_BORINGSSL INSTANTIATE_TEST_SUITE_P( HybridV0KeyTypesTestSuite, HybridV0KeyTypesTest, Values(HybridKeyTemplates::EciesP256HkdfHmacSha256Aes128Gcm(), HybridKeyTemplates::HpkeX25519HkdfSha256Aes128Gcm())); #else INSTANTIATE_TEST_SUITE_P( HybridV0KeyTypesTestSuite, HybridV0KeyTypesTest, Values(HybridKeyTemplates::EciesP256HkdfHmacSha256Aes128Gcm())); #endif TEST_P(HybridV0KeyTypesTest, GetPrimitive) { KeyGenConfiguration key_gen_config; ASSERT_THAT(AddHybridKeyGenV0(key_gen_config), IsOk()); Configuration config; ASSERT_THAT(AddHybridV0(config), IsOk()); util::StatusOr> handle = KeysetHandle::GenerateNew(GetParam(), key_gen_config); ASSERT_THAT(handle, IsOk()); util::StatusOr> public_handle = (*handle)->GetPublicKeysetHandle(key_gen_config); ASSERT_THAT(public_handle, IsOk()); util::StatusOr> encrypt = (*public_handle)->GetPrimitive(config); ASSERT_THAT(encrypt, IsOk()); util::StatusOr> decrypt = (*handle)->GetPrimitive(config); ASSERT_THAT(decrypt, IsOk()); std::string plaintext = "plaintext"; util::StatusOr ciphertext = (*encrypt)->Encrypt(plaintext, "ad"); ASSERT_THAT(ciphertext, IsOk()); EXPECT_THAT((*decrypt)->Decrypt(*ciphertext, "ad"), IsOkAndHolds(plaintext)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_context.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_context.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/hybrid/internal/hpke_context_boringssl.h" #include "tink/hybrid/internal/hpke_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { constexpr int kX25519KemEncodingLengthInBytes = 32; std::string ConcatenatePayload(absl::string_view encapsulated_key, absl::string_view ciphertext) { return absl::StrCat(encapsulated_key, ciphertext); } util::StatusOr SplitPayload(const HpkeKem& kem, absl::string_view payload) { if (kem == HpkeKem::kX25519HkdfSha256) { return HpkePayloadView(payload.substr(0, kX25519KemEncodingLengthInBytes), payload.substr(kX25519KemEncodingLengthInBytes)); } return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Unable to split HPKE payload for KEM type ", kem)); } util::StatusOr> HpkeContext::SetupSender( const HpkeParams& params, absl::string_view recipient_public_key, absl::string_view info) { if (recipient_public_key.empty()) { return util::Status(absl::StatusCode::kInvalidArgument, "Recipient public key is empty."); } util::StatusOr sender_context = HpkeContextBoringSsl::SetupSender(params, recipient_public_key, info); if (!sender_context.ok()) { return sender_context.status(); } return {absl::WrapUnique(new HpkeContext( sender_context->encapsulated_key, std::move(sender_context->context)))}; } util::StatusOr> HpkeContext::SetupRecipient( const HpkeParams& params, const util::SecretData& recipient_private_key, absl::string_view encapsulated_key, absl::string_view info) { if (recipient_private_key.empty()) { return util::Status(absl::StatusCode::kInvalidArgument, "Recipient private key is empty."); } if (encapsulated_key.empty()) { return util::Status(absl::StatusCode::kInvalidArgument, "Encapsulated key is empty."); } util::StatusOr> context = HpkeContextBoringSsl::SetupRecipient(params, recipient_private_key, encapsulated_key, info); if (!context.ok()) { return context.status(); } return {absl::WrapUnique( new HpkeContext(encapsulated_key, *std::move(context)))}; } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_context.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_INTERNAL_HPKE_CONTEXT_H_ #define TINK_HYBRID_INTERNAL_HPKE_CONTEXT_H_ #include #include #include #include #include "absl/strings/string_view.h" #include "tink/hybrid/internal/hpke_context_boringssl.h" #include "tink/hybrid/internal/hpke_util.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { // Pair of string views for an HPKE payload (encapsulated key and ciphertext). struct HpkePayloadView { HpkePayloadView(absl::string_view encapsulated_key, absl::string_view ciphertext) : encapsulated_key(encapsulated_key), ciphertext(ciphertext) {} absl::string_view encapsulated_key; absl::string_view ciphertext; }; // Creates HPKE payload `encapsulated_key` || `ciphertext` (i.e., Tink hybrid // encryption wire format described at // https://developers.google.com/tink/wire-format#hybrid_encryption). std::string ConcatenatePayload(absl::string_view encapsulated_key, absl::string_view ciphertext); // Splits `payload` into an `HpkePayloadView` struct. The `kem` parameter is // used to determine how to split the payload. // // WARNING: The string pointed to by `payload` must outlive the returned object. crypto::tink::util::StatusOr SplitPayload( const HpkeKem& kem, absl::string_view payload); // Represents an HPKE context for either a sender or a recipient. class HpkeContext { public: // Sets up an HPKE sender context. Returns an error if initialization // fails. Otherwise, returns a unique pointer to the sender context. // // `params`: HPKE parameters (KEM, KDF, and AEAD). // `recipient_public_key`: KEM-encoding of recipient public key. // `info`: Application-specific context for key derivation. static crypto::tink::util::StatusOr> SetupSender( const HpkeParams& params, absl::string_view recipient_public_key, absl::string_view info); // Sets up an HPKE recipient context. Returns an error if initialization // fails. Otherwise, returns a unique pointer to the recipient context. // // `params`: HPKE parameters (KEM, KDF, and AEAD). // `recipient_private_key`: Recipient private key. // `encapsulated_key`: Encapsulated key. // `info`: Application-specific context for key derivation. static crypto::tink::util::StatusOr> SetupRecipient(const HpkeParams& params, const util::SecretData& recipient_private_key, absl::string_view encapsulated_key, absl::string_view info); absl::string_view EncapsulatedKey() const { return encapsulated_key_; } // Performs an AEAD encryption of `plaintext` with `associated_data`. Returns // an error if encryption fails. Otherwise, returns the ciphertext. crypto::tink::util::StatusOr Seal( absl::string_view plaintext, absl::string_view associated_data) { return context_->Seal(plaintext, associated_data); } // Performs an AEAD decryption of `ciphertext` with `associated_data`. Returns // an error if decryption fails. Otherwise, returns the plaintext. crypto::tink::util::StatusOr Open( absl::string_view ciphertext, absl::string_view associated_data) { return context_->Open(ciphertext, associated_data); } // Exports `secret_length` bytes of secret material using `exporter_context` // for the input context. Returns an error if export fails. Otherwise, // returns a secret of the requested length. crypto::tink::util::StatusOr Export( absl::string_view exporter_context, size_t secret_length) { return context_->Export(exporter_context, secret_length); } private: explicit HpkeContext(absl::string_view encapsulated_key, std::unique_ptr context) : encapsulated_key_(encapsulated_key), context_(std::move(context)) {} const std::string encapsulated_key_; const std::unique_ptr context_; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_HYBRID_INTERNAL_HPKE_CONTEXT_H_ ================================================ FILE: cc/hybrid/internal/hpke_context_boringssl.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_context_boringssl.h" #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "openssl/base.h" #include "openssl/hpke.h" #include "tink/hybrid/internal/hpke_util.h" #include "tink/hybrid/internal/hpke_util_boringssl.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/subtle/subtle_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { util::StatusOr HpkeContextBoringSsl::SetupSender(const HpkeParams& params, absl::string_view recipient_public_key, absl::string_view context_info) { util::StatusOr kem = KemParam(params); if (!kem.ok()) { return kem.status(); } util::StatusOr kdf = KdfParam(params); if (!kdf.ok()) { return kdf.status(); } util::StatusOr aead = AeadParam(params); if (!aead.ok()) { return aead.status(); } uint8_t enc[EVP_HPKE_MAX_ENC_LENGTH]; size_t enc_len; SslUniquePtr context(EVP_HPKE_CTX_new()); if (!EVP_HPKE_CTX_setup_sender( context.get(), enc, &enc_len, sizeof(enc), *kem, *kdf, *aead, reinterpret_cast(recipient_public_key.data()), recipient_public_key.size(), reinterpret_cast(context_info.data()), context_info.size())) { return util::Status(absl::StatusCode::kUnknown, "Unable to set up HPKE sender context."); } SenderHpkeContextBoringSsl tuple; tuple.context = absl::WrapUnique(new HpkeContextBoringSsl(std::move(context))); tuple.encapsulated_key = std::string(reinterpret_cast(enc), enc_len); return std::move(tuple); } util::StatusOr> HpkeContextBoringSsl::SetupRecipient( const HpkeParams& params, const util::SecretData& recipient_private_key, absl::string_view encapsulated_key, absl::string_view info) { util::StatusOr kem = KemParam(params); if (!kem.ok()) { return kem.status(); } util::StatusOr kdf = KdfParam(params); if (!kdf.ok()) { return kdf.status(); } util::StatusOr aead = AeadParam(params); if (!aead.ok()) { return aead.status(); } bssl::ScopedEVP_HPKE_KEY hpke_key; if (!EVP_HPKE_KEY_init( hpke_key.get(), *kem, reinterpret_cast(recipient_private_key.data()), recipient_private_key.size())) { return util::Status( absl::StatusCode::kInvalidArgument, "Unable to initialize BoringSSL HPKE recipient private key."); } SslUniquePtr context(EVP_HPKE_CTX_new()); if (!EVP_HPKE_CTX_setup_recipient( context.get(), hpke_key.get(), *kdf, *aead, reinterpret_cast(encapsulated_key.data()), encapsulated_key.size(), reinterpret_cast(info.data()), info.size())) { return util::Status(absl::StatusCode::kUnknown, "Unable to set up BoringSSL HPKE recipient context."); } return absl::WrapUnique(new HpkeContextBoringSsl(std::move(context))); } util::StatusOr HpkeContextBoringSsl::Seal( absl::string_view plaintext, absl::string_view associated_data) { std::string ciphertext; subtle::ResizeStringUninitialized( &ciphertext, plaintext.size() + EVP_HPKE_CTX_max_overhead(context_.get())); size_t max_out_len = ciphertext.size(); size_t ciphertext_size; if (!EVP_HPKE_CTX_seal( context_.get(), reinterpret_cast(&ciphertext[0]), &ciphertext_size, max_out_len, reinterpret_cast(plaintext.data()), plaintext.size(), reinterpret_cast(associated_data.data()), associated_data.size())) { return util::Status(absl::StatusCode::kUnknown, "BoringSSL HPKE encryption failed."); } if (ciphertext_size < ciphertext.size()) { subtle::ResizeStringUninitialized(&ciphertext, ciphertext_size); } return ciphertext; } util::StatusOr HpkeContextBoringSsl::Open( absl::string_view ciphertext, absl::string_view associated_data) { std::string plaintext; subtle::ResizeStringUninitialized(&plaintext, ciphertext.size()); size_t plaintext_size; if (!EVP_HPKE_CTX_open( context_.get(), reinterpret_cast(&plaintext[0]), &plaintext_size, plaintext.size(), reinterpret_cast(ciphertext.data()), ciphertext.size(), reinterpret_cast(associated_data.data()), associated_data.size())) { return util::Status(absl::StatusCode::kUnknown, "BoringSSL HPKE decryption failed."); } subtle::ResizeStringUninitialized(&plaintext, plaintext_size); return plaintext; } util::StatusOr HpkeContextBoringSsl::Export( absl::string_view exporter_context, int64_t secret_length) { std::string secret; subtle::ResizeStringUninitialized(&secret, secret_length); if (!EVP_HPKE_CTX_export( context_.get(), reinterpret_cast(&secret[0]), secret_length, reinterpret_cast(exporter_context.data()), exporter_context.size())) { return util::Status(absl::StatusCode::kUnknown, "Unable to export secret."); } return util::SecretDataFromStringView(secret); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_context_boringssl.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_INTERNAL_HPKE_CONTEXT_BORINGSSL_H_ #define TINK_HYBRID_INTERNAL_HPKE_CONTEXT_BORINGSSL_H_ #include #include #include #include #include #include "absl/strings/string_view.h" #include "openssl/base.h" #include "openssl/hpke.h" #include "tink/hybrid/internal/hpke_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { struct SenderHpkeContextBoringSsl; class HpkeContextBoringSsl { public: // Sets up an HPKE sender context. Returns an error if initialization // fails. Otherwise, returns a unique pointer to the sender context. // // `params`: HPKE parameters (KEM, KDF, and AEAD). // `recipient_public_key`: KEM-encoding of recipient public key. // `info`: Application-specific context for key derivation. static crypto::tink::util::StatusOr SetupSender(const HpkeParams& params, absl::string_view recipient_public_key, absl::string_view info); // Sets up an HPKE recipient context. Returns an error if initialization // fails. Otherwise, returns a unique pointer to the recipient context. // // `params`: HPKE parameters (KEM, KDF, and AEAD). // `recipient_private_key`: Recipient private key. // `encapsulated_key`: Encapsulated key. // `info`: Application-specific context for key derivation. static crypto::tink::util::StatusOr> SetupRecipient(const HpkeParams& params, const util::SecretData& recipient_private_key, absl::string_view encapsulated_key, absl::string_view info); // Performs an AEAD encryption of `plaintext` with `associated_data`. Returns // an error if encryption fails. Otherwise, returns the ciphertext. crypto::tink::util::StatusOr Seal( absl::string_view plaintext, absl::string_view associated_data); // Performs an AEAD decryption of `ciphertext` with `associated_data`. Returns // an error if decryption fails. Otherwise, returns the plaintext. crypto::tink::util::StatusOr Open( absl::string_view ciphertext, absl::string_view associated_data); // Exports `secret_length` bytes of secret material using `exporter_context` // for the input context. Returns an error if export fails. Otherwise, // returns a secret of the requested length. crypto::tink::util::StatusOr Export( absl::string_view exporter_context, int64_t secret_length); protected: explicit HpkeContextBoringSsl(SslUniquePtr context) : context_(std::move(context)) {} private: SslUniquePtr context_; }; struct SenderHpkeContextBoringSsl { std::unique_ptr context; std::string encapsulated_key; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_HYBRID_INTERNAL_HPKE_CONTEXT_BORINGSSL_H_ ================================================ FILE: cc/hybrid/internal/hpke_context_boringssl_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_context_boringssl.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/hybrid/internal/hpke_test_util.h" #include "tink/hybrid/internal/hpke_util.h" #include "tink/hybrid/internal/test_hpke_context_boringssl.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::testing::Values; class HpkeContextBoringSslTest : public testing::TestWithParam {}; INSTANTIATE_TEST_SUITE_P( HpkeContextBoringSslTestSuite, HpkeContextBoringSslTest, Values(HpkeParams{HpkeKem::kX25519HkdfSha256, HpkeKdf::kHkdfSha256, HpkeAead::kAes128Gcm}, HpkeParams{HpkeKem::kX25519HkdfSha256, HpkeKdf::kHkdfSha256, HpkeAead::kChaCha20Poly1305})); TEST_P(HpkeContextBoringSslTest, Seal) { HpkeParams hpke_params = GetParam(); util::StatusOr params = CreateHpkeTestParams(hpke_params); ASSERT_THAT(params, IsOk()); util::StatusOr hpke_context = TestHpkeContextBoringSsl::SetupSender( hpke_params, params->recipient_public_key, params->application_info, params->seed_for_testing); ASSERT_THAT(hpke_context, IsOk()); util::StatusOr ciphertext = hpke_context->context->Seal(params->plaintext, params->associated_data); ASSERT_THAT(ciphertext, IsOkAndHolds(params->ciphertext)); } TEST_P(HpkeContextBoringSslTest, Open) { HpkeParams hpke_params = GetParam(); util::StatusOr params = CreateHpkeTestParams(hpke_params); ASSERT_THAT(params, IsOk()); util::StatusOr> hpke_context = HpkeContextBoringSsl::SetupRecipient( hpke_params, util::SecretDataFromStringView(params->recipient_private_key), params->encapsulated_key, params->application_info); ASSERT_THAT(hpke_context, IsOk()); util::StatusOr plaintext = (*hpke_context)->Open(params->ciphertext, params->associated_data); ASSERT_THAT(plaintext, IsOkAndHolds(params->plaintext)); } TEST_P(HpkeContextBoringSslTest, SenderExport) { HpkeParams hpke_params = GetParam(); util::StatusOr params = CreateHpkeTestParams(hpke_params); ASSERT_THAT(params, IsOk()); util::StatusOr sender_hpke_context = TestHpkeContextBoringSsl::SetupSender( hpke_params, params->recipient_public_key, params->application_info, params->seed_for_testing); ASSERT_THAT(sender_hpke_context, IsOk()); for (int i = 0; i < params->exported_contexts.size(); ++i) { util::StatusOr sender_secret = sender_hpke_context->context->Export(params->exported_contexts[i], 32); ASSERT_THAT(sender_secret, IsOkAndHolds(util::SecretDataFromStringView( params->exported_values[i]))); } } TEST_P(HpkeContextBoringSslTest, RecipientExport) { HpkeParams hpke_params = GetParam(); util::StatusOr params = CreateHpkeTestParams(hpke_params); ASSERT_THAT(params, IsOk()); util::StatusOr> recipient_hpke_context = HpkeContextBoringSsl::SetupRecipient( hpke_params, util::SecretDataFromStringView(params->recipient_private_key), params->encapsulated_key, params->application_info); ASSERT_THAT(recipient_hpke_context, IsOk()); for (int i = 0; i < params->exported_contexts.size(); ++i) { util::StatusOr recipient_secret = (*recipient_hpke_context)->Export(params->exported_contexts[i], 32); ASSERT_THAT(recipient_secret, IsOkAndHolds(util::SecretDataFromStringView( params->exported_values[i]))); } } class HpkeContextBoringSslWithBadParamTest : public testing::TestWithParam {}; INSTANTIATE_TEST_SUITE_P( HpkeContextBoringSslWithBadParamTestSuite, HpkeContextBoringSslWithBadParamTest, Values(HpkeParams{HpkeKem::kUnknownKem, HpkeKdf::kHkdfSha256, HpkeAead::kAes128Gcm}, HpkeParams{HpkeKem::kX25519HkdfSha256, HpkeKdf::kUnknownKdf, HpkeAead::kAes128Gcm}, HpkeParams{HpkeKem::kX25519HkdfSha256, HpkeKdf::kHkdfSha256, HpkeAead::kUnknownAead})); TEST_P(HpkeContextBoringSslWithBadParamTest, BadSenderParamsFail) { HpkeParams hpke_params = GetParam(); HpkeTestParams params = DefaultHpkeTestParams(); util::StatusOr result = TestHpkeContextBoringSsl::SetupSender( hpke_params, params.recipient_public_key, params.application_info, params.seed_for_testing); ASSERT_THAT(result.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(HpkeContextBoringSslWithBadParamTest, BadRecipientParamsFail) { HpkeParams hpke_params = GetParam(); HpkeTestParams params = DefaultHpkeTestParams(); util::StatusOr> hpke_context = HpkeContextBoringSsl::SetupRecipient( hpke_params, util::SecretDataFromStringView(params.recipient_private_key), params.encapsulated_key, params.application_info); ASSERT_THAT(hpke_context.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkeContextBoringSslWithMissingPublicKeyTest, ZeroLengthPublicKeyFails) { HpkeParams hpke_params = {HpkeKem::kX25519HkdfSha256, HpkeKdf::kHkdfSha256, HpkeAead::kAes128Gcm}; HpkeTestParams params = DefaultHpkeTestParams(); util::StatusOr result = TestHpkeContextBoringSsl::SetupSender( hpke_params, /*recipient_public_key=*/"", params.application_info, params.seed_for_testing); ASSERT_THAT(result.status(), StatusIs(absl::StatusCode::kUnknown)); } TEST(HpkeContextBoringSslWithMissingPrivateKeyTest, ZeroLengthPrivateKeyFails) { HpkeParams hpke_params = {HpkeKem::kX25519HkdfSha256, HpkeKdf::kHkdfSha256, HpkeAead::kAes128Gcm}; HpkeTestParams params = DefaultHpkeTestParams(); util::StatusOr> hpke_context = HpkeContextBoringSsl::SetupRecipient( hpke_params, util::SecretDataFromStringView(/*secret=*/""), params.encapsulated_key, params.application_info); ASSERT_THAT(hpke_context.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_context_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_context.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/hybrid/internal/hpke_test_util.h" #include "tink/hybrid/internal/hpke_util.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::internal::CreateHpkeTestParams; using ::crypto::tink::internal::DefaultHpkeTestParams; using ::crypto::tink::internal::HpkeTestParams; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::TestWithParam; using ::testing::Values; class HpkeContextTest : public TestWithParam {}; INSTANTIATE_TEST_SUITE_P( HpkeContextTestSuite, HpkeContextTest, Values(HpkeParams{HpkeKem::kX25519HkdfSha256, HpkeKdf::kHkdfSha256, HpkeAead::kAes128Gcm}, HpkeParams{HpkeKem::kX25519HkdfSha256, HpkeKdf::kHkdfSha256, HpkeAead::kChaCha20Poly1305})); TEST_P(HpkeContextTest, SealAndOpen) { HpkeParams hpke_params = GetParam(); util::StatusOr params = CreateHpkeTestParams(hpke_params); ASSERT_THAT(params, IsOk()); util::StatusOr> sender_hpke_context = HpkeContext::SetupSender(hpke_params, params->recipient_public_key, params->application_info); ASSERT_THAT(sender_hpke_context, IsOk()); util::StatusOr> recipient_hpke_context = HpkeContext::SetupRecipient( hpke_params, util::SecretDataFromStringView(params->recipient_private_key), (*sender_hpke_context)->EncapsulatedKey(), params->application_info); ASSERT_THAT(recipient_hpke_context, IsOk()); std::vector inputs = {"", params->plaintext}; std::vector context_infos = {"", params->application_info}; for (const std::string& input : inputs) { for (const std::string& context_info : context_infos) { SCOPED_TRACE(absl::StrCat("plaintext: '", input, "', context_info: '", context_info, "'")); util::StatusOr ciphertext = (*sender_hpke_context)->Seal(input, context_info); ASSERT_THAT(ciphertext, IsOk()); util::StatusOr plaintext = (*recipient_hpke_context)->Open(*ciphertext, context_info); ASSERT_THAT(plaintext, IsOk()); EXPECT_THAT(*plaintext, Eq(input)); } } } TEST_P(HpkeContextTest, Export) { HpkeParams hpke_params = GetParam(); util::StatusOr params = CreateHpkeTestParams(hpke_params); ASSERT_THAT(params, IsOk()); util::StatusOr> sender_hpke_context = HpkeContext::SetupSender(hpke_params, params->recipient_public_key, params->application_info); ASSERT_THAT(sender_hpke_context, IsOk()); util::StatusOr> recipient_hpke_context = HpkeContext::SetupRecipient( hpke_params, util::SecretDataFromStringView(params->recipient_private_key), (*sender_hpke_context)->EncapsulatedKey(), params->application_info); ASSERT_THAT(recipient_hpke_context, IsOk()); std::vector exporter_contexts = {"", "c", "context"}; std::vector secret_lengths = {0, 8, 16, 32, 64}; for (const std::string& exporter_context : exporter_contexts) { for (int secret_length : secret_lengths) { SCOPED_TRACE(absl::StrCat("exporter_context: '", exporter_context, "', secret_length: '", secret_length, "'")); util::StatusOr sender_secret = (*sender_hpke_context)->Export(exporter_context, secret_length); ASSERT_THAT(sender_secret, IsOk()); util::StatusOr recipient_secret = (*recipient_hpke_context)->Export(exporter_context, secret_length); ASSERT_THAT(recipient_secret, IsOk()); EXPECT_THAT(*sender_secret, Eq(*recipient_secret)); } } } TEST_P(HpkeContextTest, OpenTruncatedCiphertextFails) { HpkeParams hpke_params = GetParam(); util::StatusOr params = CreateHpkeTestParams(hpke_params); ASSERT_THAT(params, IsOk()); util::StatusOr> recipient_hpke_context = HpkeContext::SetupRecipient( hpke_params, util::SecretDataFromStringView(params->recipient_private_key), params->encapsulated_key, params->application_info); ASSERT_THAT(recipient_hpke_context, IsOk()); util::StatusOr plaintext = (*recipient_hpke_context) ->Open(params->ciphertext, params->associated_data); ASSERT_THAT(plaintext, IsOk()); const std::string truncated_ciphertext = params->ciphertext.substr(params->ciphertext.length() - 1); util::StatusOr bad_plaintext = (*recipient_hpke_context) ->Open(truncated_ciphertext, params->associated_data); EXPECT_THAT(bad_plaintext.status(), StatusIs(absl::StatusCode::kUnknown)); } TEST_P(HpkeContextTest, OpenModifiedCiphertextFails) { HpkeParams hpke_params = GetParam(); util::StatusOr params = CreateHpkeTestParams(hpke_params); ASSERT_THAT(params, IsOk()); util::StatusOr> recipient_hpke_context = HpkeContext::SetupRecipient( hpke_params, util::SecretDataFromStringView(params->recipient_private_key), params->encapsulated_key, params->application_info); ASSERT_THAT(recipient_hpke_context, IsOk()); util::StatusOr plaintext = (*recipient_hpke_context) ->Open(params->ciphertext, params->associated_data); ASSERT_THAT(plaintext, IsOk()); const std::string modified_ciphertext = absl::StrCat(params->ciphertext, "modification"); util::StatusOr bad_plaintext = (*recipient_hpke_context) ->Open(modified_ciphertext, params->associated_data); EXPECT_THAT(bad_plaintext.status(), StatusIs(absl::StatusCode::kUnknown)); } TEST_P(HpkeContextTest, OpenModifiedAssociatedDataFails) { HpkeParams hpke_params = GetParam(); util::StatusOr params = CreateHpkeTestParams(hpke_params); ASSERT_THAT(params, IsOk()); util::StatusOr> recipient_hpke_context = HpkeContext::SetupRecipient( hpke_params, util::SecretDataFromStringView(params->recipient_private_key), params->encapsulated_key, params->application_info); ASSERT_THAT(recipient_hpke_context, IsOk()); util::StatusOr plaintext = (*recipient_hpke_context) ->Open(params->ciphertext, params->associated_data); ASSERT_THAT(plaintext, IsOk()); const std::string modified_associated_data = absl::StrCat(params->associated_data, "modification"); util::StatusOr bad_plaintext = (*recipient_hpke_context) ->Open(params->ciphertext, modified_associated_data); EXPECT_THAT(bad_plaintext.status(), StatusIs(absl::StatusCode::kUnknown)); } class HpkeContextWithBadHpkeParamTest : public TestWithParam {}; INSTANTIATE_TEST_SUITE_P( HpkeContextWithBadHpkeParamTestTestSuite, HpkeContextWithBadHpkeParamTest, Values(HpkeParams{HpkeKem::kUnknownKem, HpkeKdf::kHkdfSha256, HpkeAead::kAes128Gcm}, HpkeParams{HpkeKem::kX25519HkdfSha256, HpkeKdf::kUnknownKdf, HpkeAead::kAes256Gcm}, HpkeParams{HpkeKem::kX25519HkdfSha256, HpkeKdf::kHkdfSha256, HpkeAead::kUnknownAead})); TEST_P(HpkeContextWithBadHpkeParamTest, SenderBadHpkeParamFails) { HpkeParams hpke_params = GetParam(); HpkeTestParams params = DefaultHpkeTestParams(); util::StatusOr> sender_hpke_context = HpkeContext::SetupSender(hpke_params, params.recipient_public_key, params.application_info); EXPECT_THAT(sender_hpke_context.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(HpkeContextWithBadHpkeParamTest, RecipientBadHpkeParamFails) { HpkeParams hpke_params = GetParam(); HpkeTestParams params = DefaultHpkeTestParams(); util::StatusOr> recipient_hpke_context = HpkeContext::SetupRecipient( hpke_params, util::SecretDataFromStringView(params.recipient_private_key), params.encapsulated_key, params.application_info); EXPECT_THAT(recipient_hpke_context.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkeContextZeroLengthKeyTest, ZeroLengthPublicKeyFails) { HpkeParams hpke_params = {HpkeKem::kX25519HkdfSha256, HpkeKdf::kHkdfSha256, HpkeAead::kAes256Gcm}; HpkeTestParams params = DefaultHpkeTestParams(); util::StatusOr> sender_hpke_context = HpkeContext::SetupSender(hpke_params, /*recipient_public_key=*/"", params.application_info); EXPECT_THAT(sender_hpke_context.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkeContextZeroLengthKeyTest, ZeroLengthPrivateKeyFails) { HpkeParams hpke_params = {HpkeKem::kX25519HkdfSha256, HpkeKdf::kHkdfSha256, HpkeAead::kAes256Gcm}; HpkeTestParams params = DefaultHpkeTestParams(); util::StatusOr> recipient_hpke_context = HpkeContext::SetupRecipient( hpke_params, /*recipient_private_key=*/util::SecretDataFromStringView(""), params.encapsulated_key, params.application_info); EXPECT_THAT(recipient_hpke_context.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkeContextZeroLengthKeyTest, ZeroLengthEncapsulatedKeyFails) { HpkeParams hpke_params = {HpkeKem::kX25519HkdfSha256, HpkeKdf::kHkdfSha256, HpkeAead::kAes256Gcm}; HpkeTestParams params = DefaultHpkeTestParams(); util::StatusOr> recipient_hpke_context = HpkeContext::SetupRecipient( hpke_params, util::SecretDataFromStringView(params.recipient_private_key), /*encapsulated_key=*/"", params.application_info); EXPECT_THAT(recipient_hpke_context.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(ConcatenatePayloadTest, ConcatenatePayloadSucceeds) { HpkeTestParams params = DefaultHpkeTestParams(); EXPECT_THAT(ConcatenatePayload(params.encapsulated_key, params.ciphertext), Eq(absl::StrCat(params.encapsulated_key, params.ciphertext))); } TEST(SplitPayloadTest, SplitPayloadSucceeds) { HpkeTestParams params = DefaultHpkeTestParams(); const std::string payload = absl::StrCat(params.encapsulated_key, params.ciphertext); util::StatusOr hpke_payload = SplitPayload(HpkeKem::kX25519HkdfSha256, payload); ASSERT_THAT(hpke_payload, IsOk()); EXPECT_THAT(hpke_payload->encapsulated_key, Eq(params.encapsulated_key)); EXPECT_THAT(hpke_payload->ciphertext, Eq(params.ciphertext)); } TEST(SplitPayloadTest, InvalidKemFails) { HpkeTestParams params = DefaultHpkeTestParams(); util::StatusOr payload = SplitPayload(HpkeKem::kUnknownKem, absl::StrCat(params.encapsulated_key, params.ciphertext)); EXPECT_THAT(payload.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_decrypt.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_decrypt.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/hybrid/internal/hpke_context.h" #include "tink/hybrid/internal/hpke_util.h" #include "tink/hybrid_decrypt.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace { using ::google::crypto::tink::HpkeAead; using ::google::crypto::tink::HpkeKdf; using ::google::crypto::tink::HpkeKem; using ::google::crypto::tink::HpkePrivateKey; } // namespace util::StatusOr> HpkeDecrypt::New( const HpkePrivateKey& recipient_private_key) { if (recipient_private_key.private_key().empty()) { return util::Status(absl::StatusCode::kInvalidArgument, "Recipient private key is empty."); } if (!recipient_private_key.has_public_key()) { return util::Status(absl::StatusCode::kInvalidArgument, "Recipient private key is missing public key."); } if (!recipient_private_key.public_key().has_params()) { return util::Status(absl::StatusCode::kInvalidArgument, "Recipient private key is missing HPKE parameters."); } if (recipient_private_key.public_key().params().kem() != HpkeKem::DHKEM_X25519_HKDF_SHA256) { return util::Status(absl::StatusCode::kInvalidArgument, "Recipient private key has an unsupported KEM"); } if (recipient_private_key.public_key().params().kdf() != HpkeKdf::HKDF_SHA256) { return util::Status(absl::StatusCode::kInvalidArgument, "Recipient private key has an unsupported KDF"); } if (recipient_private_key.public_key().params().aead() == HpkeAead::AEAD_UNKNOWN) { return util::Status(absl::StatusCode::kInvalidArgument, "Recipient private key is missing AEAD"); } return {absl::WrapUnique(new HpkeDecrypt( recipient_private_key.public_key().params(), util::SecretDataFromStringView(recipient_private_key.private_key())))}; } util::StatusOr HpkeDecrypt::Decrypt( absl::string_view ciphertext, absl::string_view context_info) const { util::StatusOr encoding_size = internal::HpkeEncapsulatedKeyLength(hpke_params_.kem()); if (!encoding_size.ok()) return encoding_size.status(); // Verify that ciphertext length is at least the encapsulated key length. if (ciphertext.size() < *encoding_size) { return util::Status(absl::StatusCode::kInvalidArgument, "Ciphertext is too short."); } absl::string_view encapsulated_key = ciphertext.substr(0, *encoding_size); absl::string_view ciphertext_payload = ciphertext.substr(*encoding_size); util::StatusOr params = internal::HpkeParamsProtoToStruct(hpke_params_); if (!params.ok()) return params.status(); util::StatusOr> recipient_context = internal::HpkeContext::SetupRecipient(*params, recipient_private_key_, encapsulated_key, context_info); if (!recipient_context.ok()) return recipient_context.status(); return (*recipient_context)->Open(ciphertext_payload, /*associated_data=*/""); } } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_decrypt.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_INTERNAL_HPKE_DECRYPT_H_ #define TINK_HYBRID_INTERNAL_HPKE_DECRYPT_H_ #include #include #include #include "absl/strings/string_view.h" #include "tink/hybrid_decrypt.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { class HpkeDecrypt : public HybridDecrypt { public: // Copyable and movable. HpkeDecrypt(const HpkeDecrypt& other) = default; HpkeDecrypt& operator=(const HpkeDecrypt& other) = default; HpkeDecrypt(HpkeDecrypt&& other) = default; HpkeDecrypt& operator=(HpkeDecrypt&& other) = default; static crypto::tink::util::StatusOr> New( const google::crypto::tink::HpkePrivateKey& recipient_private_key); crypto::tink::util::StatusOr Decrypt( absl::string_view ciphertext, absl::string_view context_info) const override; private: HpkeDecrypt(const google::crypto::tink::HpkeParams& hpke_params, const util::SecretData& recipient_private_key) : hpke_params_(hpke_params), recipient_private_key_(recipient_private_key) {} google::crypto::tink::HpkeParams hpke_params_; util::SecretData recipient_private_key_; }; } // namespace tink } // namespace crypto #endif // TINK_HYBRID_INTERNAL_HPKE_DECRYPT_H_ ================================================ FILE: cc/hybrid/internal/hpke_decrypt_boringssl.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_decrypt_boringssl.h" #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "openssl/base.h" #include "openssl/err.h" #include "openssl/hpke.h" #include "tink/hybrid/internal/hpke_key_boringssl.h" #include "tink/hybrid/internal/hpke_util_boringssl.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace internal { util::StatusOr> HpkeDecryptBoringSsl::New( const google::crypto::tink::HpkeParams& params, const HpkeKeyBoringSsl& hpke_key, absl::string_view encapsulated_key, absl::string_view context_info) { auto hpke_decrypt = absl::WrapUnique(new HpkeDecryptBoringSsl()); util::Status status = hpke_decrypt->Init(params, hpke_key, encapsulated_key, context_info); if (!status.ok()) { return status; } return std::move(hpke_decrypt); } util::Status HpkeDecryptBoringSsl::Init( const google::crypto::tink::HpkeParams& params, const HpkeKeyBoringSsl& hpke_key, absl::string_view encapsulated_key, absl::string_view context_info) { util::StatusOr kem = KemParam(params); if (!kem.ok()) { return kem.status(); } if (params.kem() != hpke_key.kem()) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Specified KEM parameter '", params.kem(), "' does not match given HPKE key's KEM parameter '", hpke_key.kem(), "'.")); } util::StatusOr kdf = KdfParam(params); if (!kdf.ok()) { return kdf.status(); } util::StatusOr aead = AeadParam(params); if (!aead.ok()) { return aead.status(); } if (!EVP_HPKE_CTX_setup_recipient( recipient_ctx_.get(), hpke_key.recipient_private_key(), *kdf, *aead, reinterpret_cast(encapsulated_key.data()), encapsulated_key.size(), reinterpret_cast(context_info.data()), context_info.size())) { return util::Status(absl::StatusCode::kUnknown, "Unable to set up BoringSSL HPKE recipient context."); } return util::OkStatus(); } util::StatusOr HpkeDecryptBoringSsl::Decrypt( absl::string_view ciphertext, absl::string_view associated_data) { std::string plaintext; subtle::ResizeStringUninitialized(&plaintext, ciphertext.size()); size_t plaintext_size; if (!EVP_HPKE_CTX_open( recipient_ctx_.get(), reinterpret_cast(&plaintext[0]), &plaintext_size, plaintext.size(), reinterpret_cast(ciphertext.data()), ciphertext.size(), reinterpret_cast(associated_data.data()), associated_data.size())) { return util::Status(absl::StatusCode::kUnknown, "BoringSSL HPKE decryption failed."); } subtle::ResizeStringUninitialized(&plaintext, plaintext_size); return plaintext; } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_decrypt_boringssl.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_INTERNAL_HPKE_DECRYPT_BORINGSSL_H_ #define TINK_HYBRID_INTERNAL_HPKE_DECRYPT_BORINGSSL_H_ #include #include #include #include "absl/base/attributes.h" #include "absl/strings/string_view.h" #include "openssl/hpke.h" #include "tink/hybrid/internal/hpke_key_boringssl.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace internal { class ABSL_DEPRECATED("Use HpkeContext.") HpkeDecryptBoringSsl { public: // Sets up an HPKE recipient context. Returns an error if initialization // fails. Otherwise, returns a unique pointer to the recipient context. // // `params`: HPKE parameters proto (KEM, KDF, and AEAD). // `hpke_key`: Recipient private key. // `encapsulated_key`: Encapsulated key. // `context_info`: Application-specific context for key derivation. static util::StatusOr> New( const google::crypto::tink::HpkeParams& params, const HpkeKeyBoringSsl& hpke_key, absl::string_view encapsulated_key, absl::string_view context_info); // Performs an AEAD decryption of `ciphertext` with `associated_data`. // Returns an error if decryption fails. Otherwise, returns the plaintext. util::StatusOr Decrypt(absl::string_view ciphertext, absl::string_view associated_data); private: HpkeDecryptBoringSsl() {} util::Status Init(const google::crypto::tink::HpkeParams& params, const HpkeKeyBoringSsl& hpke_key, absl::string_view encapsulated_key, absl::string_view context_info); bssl::ScopedEVP_HPKE_CTX recipient_ctx_; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_HYBRID_INTERNAL_HPKE_DECRYPT_BORINGSSL_H_ ================================================ FILE: cc/hybrid/internal/hpke_decrypt_boringssl_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_decrypt_boringssl.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "openssl/hpke.h" #include "tink/hybrid/internal/hpke_key_boringssl.h" #include "tink/hybrid/internal/hpke_test_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::HpkeAead; using ::google::crypto::tink::HpkeKdf; using ::google::crypto::tink::HpkeKem; using ::google::crypto::tink::HpkeParams; using ::testing::Values; class HpkeDecryptBoringSslTest : public testing::TestWithParam {}; INSTANTIATE_TEST_SUITE_P( HpkeDecryptionBoringSslTestSuite, HpkeDecryptBoringSslTest, Values(CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM), CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::CHACHA20_POLY1305))); TEST_P(HpkeDecryptBoringSslTest, SetupSenderContextAndDecrypt) { HpkeParams hpke_params = GetParam(); util::StatusOr params = CreateHpkeTestParams(hpke_params); ASSERT_THAT(params, IsOk()); util::StatusOr> hpke_key = HpkeKeyBoringSsl::New(hpke_params.kem(), params->recipient_private_key); ASSERT_THAT(hpke_key, IsOk()); util::StatusOr> hpke_decrypt = HpkeDecryptBoringSsl::New(hpke_params, **hpke_key, params->encapsulated_key, params->application_info); ASSERT_THAT(hpke_decrypt, IsOk()); util::StatusOr plaintext = (*hpke_decrypt)->Decrypt(params->ciphertext, params->associated_data); ASSERT_THAT(plaintext, IsOkAndHolds(params->plaintext)); } class HpkeDecryptBoringSslWithBadParamTest : public testing::TestWithParam {}; INSTANTIATE_TEST_SUITE_P( HpkeDecryptionBoringSslWithBadParamTestSuite, HpkeDecryptBoringSslWithBadParamTest, Values(CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::KDF_UNKNOWN, HpkeAead::AES_128_GCM), CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AEAD_UNKNOWN))); TEST_P(HpkeDecryptBoringSslWithBadParamTest, BadParamsFails) { HpkeParams hpke_params = GetParam(); HpkeTestParams params = DefaultHpkeTestParams(); util::StatusOr> hpke_key = HpkeKeyBoringSsl::New(hpke_params.kem(), params.recipient_private_key); ASSERT_THAT(hpke_key, IsOk()); util::StatusOr> hpke_decrypt = HpkeDecryptBoringSsl::New(hpke_params, **hpke_key, params.encapsulated_key, params.application_info); ASSERT_THAT(hpke_decrypt.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_decrypt_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_decrypt.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/hybrid/internal/hpke_encrypt.h" #include "tink/hybrid/internal/hpke_test_util.h" #include "tink/hybrid_decrypt.h" #include "tink/hybrid_encrypt.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::internal::CreateHpkeParams; using ::crypto::tink::internal::CreateHpkePrivateKey; using ::crypto::tink::internal::CreateHpkePublicKey; using ::crypto::tink::internal::CreateHpkeTestParams; using ::crypto::tink::internal::DefaultHpkeTestParams; using ::crypto::tink::internal::HpkeTestParams; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::HpkeAead; using ::google::crypto::tink::HpkeKdf; using ::google::crypto::tink::HpkeKem; using ::google::crypto::tink::HpkeParams; using ::google::crypto::tink::HpkePrivateKey; using ::google::crypto::tink::HpkePublicKey; using ::testing::Values; util::StatusOr Encrypt(HpkeParams params, absl::string_view recipient_public_key, absl::string_view plaintext, absl::string_view context_info) { HpkePublicKey recipient_key = CreateHpkePublicKey(params, std::string(recipient_public_key)); util::StatusOr> hpke_encrypt = HpkeEncrypt::New(recipient_key); if (!hpke_encrypt.ok()) { return hpke_encrypt.status(); } return (*hpke_encrypt)->Encrypt(plaintext, context_info); } class HpkeDecryptTest : public testing::TestWithParam {}; INSTANTIATE_TEST_SUITE_P( HpkeDecryptionTestSuite, HpkeDecryptTest, Values(CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM), CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::CHACHA20_POLY1305))); TEST_P(HpkeDecryptTest, SetupRecipientContextAndDecrypt) { HpkeParams hpke_params = GetParam(); util::StatusOr params = CreateHpkeTestParams(hpke_params); ASSERT_THAT(params, IsOk()); HpkePrivateKey recipient_key = CreateHpkePrivateKey(hpke_params, params->recipient_private_key); util::StatusOr> hpke_decrypt = HpkeDecrypt::New(recipient_key); ASSERT_THAT(hpke_decrypt, IsOk()); std::vector inputs = {"", params->plaintext}; std::vector context_infos = {"", params->application_info}; for (const std::string& input : inputs) { for (const std::string& context_info : context_infos) { SCOPED_TRACE(absl::StrCat("input: '", input, "', context_info: '", context_info, "'")); util::StatusOr ciphertext = Encrypt( hpke_params, params->recipient_public_key, input, context_info); ASSERT_THAT(ciphertext, IsOk()); util::StatusOr plaintext = (*hpke_decrypt)->Decrypt(*ciphertext, context_info); EXPECT_THAT(plaintext, IsOkAndHolds(input)); } } } class HpkeDecryptWithBadParamTest : public testing::TestWithParam { }; INSTANTIATE_TEST_SUITE_P( HpkeDecryptionWithBadParamTestSuite, HpkeDecryptWithBadParamTest, Values(CreateHpkeParams(HpkeKem::KEM_UNKNOWN, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM), CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::KDF_UNKNOWN, HpkeAead::AES_128_GCM), CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AEAD_UNKNOWN), CreateHpkeParams(HpkeKem::DHKEM_P256_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM), CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA384, HpkeAead::AES_128_GCM))); TEST_P(HpkeDecryptWithBadParamTest, BadParamsFails) { HpkeParams bad_params = GetParam(); HpkeTestParams params = DefaultHpkeTestParams(); HpkePrivateKey recipient_key = CreateHpkePrivateKey(bad_params, params.recipient_private_key); util::StatusOr> hpke_decrypt = HpkeDecrypt::New(recipient_key); ASSERT_THAT(hpke_decrypt.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkeDecryptWithShortCiphertextTest, ShortCiphertextFails) { HpkeParams hpke_params = CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); HpkeTestParams params = DefaultHpkeTestParams(); HpkePrivateKey recipient_key = CreateHpkePrivateKey(hpke_params, params.recipient_private_key); util::StatusOr> hpke_decrypt = HpkeDecrypt::New(recipient_key); ASSERT_THAT(hpke_decrypt, IsOk()); util::StatusOr plaintext = (*hpke_decrypt)->Decrypt("short ciphertext", "associated data"); EXPECT_THAT(plaintext.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkeDecryptWithBadCiphertextTest, BadCiphertextFails) { HpkeParams hpke_params = CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); HpkeTestParams params = DefaultHpkeTestParams(); HpkePrivateKey recipient_key = CreateHpkePrivateKey(hpke_params, params.recipient_private_key); util::StatusOr> hpke_decrypt = HpkeDecrypt::New(recipient_key); ASSERT_THAT(hpke_decrypt, IsOk()); util::StatusOr ciphertext = Encrypt(hpke_params, params.recipient_public_key, params.plaintext, params.application_info); ASSERT_THAT(ciphertext, IsOk()); util::StatusOr plaintext = (*hpke_decrypt) ->Decrypt(absl::StrCat(*ciphertext, "modified ciphertext"), params.application_info); EXPECT_THAT(plaintext.status(), StatusIs(absl::StatusCode::kUnknown)); } TEST(HpkeDecryptWithBadAssociatedDataTest, BadAssociatedDataFails) { HpkeParams hpke_params = CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); HpkeTestParams params = DefaultHpkeTestParams(); HpkePrivateKey recipient_key = CreateHpkePrivateKey(hpke_params, params.recipient_private_key); util::StatusOr> hpke_decrypt = HpkeDecrypt::New(recipient_key); ASSERT_THAT(hpke_decrypt, IsOk()); util::StatusOr ciphertext = Encrypt(hpke_params, params.recipient_public_key, params.plaintext, params.application_info); ASSERT_THAT(ciphertext, IsOk()); util::StatusOr plaintext = (*hpke_decrypt) ->Decrypt(*ciphertext, absl::StrCat(params.application_info, "modified aad")); EXPECT_THAT(plaintext.status(), StatusIs(absl::StatusCode::kUnknown)); } TEST(HpkeDecryptWithMissingPublicKeyTest, MissingPublicKeyFails) { HpkeParams hpke_params = CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); HpkeTestParams params = DefaultHpkeTestParams(); HpkePrivateKey recipient_key = CreateHpkePrivateKey(hpke_params, params.recipient_private_key); recipient_key.clear_public_key(); util::StatusOr> hpke_decrypt = HpkeDecrypt::New(recipient_key); EXPECT_THAT(hpke_decrypt.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkeDecryptWithMissingHpkeParamsTest, MissingHpkeParamsFails) { HpkeParams hpke_params = CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); HpkeTestParams params = DefaultHpkeTestParams(); HpkePrivateKey recipient_key = CreateHpkePrivateKey(hpke_params, params.recipient_private_key); recipient_key.mutable_public_key()->clear_params(); util::StatusOr> hpke_decrypt = HpkeDecrypt::New(recipient_key); EXPECT_THAT(hpke_decrypt.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkeDecryptWithZeroLengthPrivateKeyTest, ZeroLengthPrivateKeyFails) { HpkeParams hpke_params = CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); HpkeTestParams params = DefaultHpkeTestParams(); HpkePrivateKey recipient_key = CreateHpkePrivateKey(hpke_params, /*raw_key_bytes=*/""); util::StatusOr> hpke_decrypt = HpkeDecrypt::New(recipient_key); EXPECT_THAT(hpke_decrypt.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_encrypt.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_encrypt.h" #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/hybrid/internal/hpke_context.h" #include "tink/hybrid/internal/hpke_util.h" #include "tink/hybrid_encrypt.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { using ::google::crypto::tink::HpkeAead; using ::google::crypto::tink::HpkeKdf; using ::google::crypto::tink::HpkeKem; using ::google::crypto::tink::HpkePublicKey; util::StatusOr> HpkeEncrypt::New( const HpkePublicKey& recipient_public_key) { if (recipient_public_key.public_key().empty()) { return util::Status(absl::StatusCode::kInvalidArgument, "Recipient public key is empty."); } if (!recipient_public_key.has_params()) { return util::Status(absl::StatusCode::kInvalidArgument, "Recipient public key is missing HPKE parameters."); } if (recipient_public_key.params().kem() != HpkeKem::DHKEM_X25519_HKDF_SHA256) { return util::Status(absl::StatusCode::kInvalidArgument, "Recipient public key has an unsupported KEM"); } if (recipient_public_key.params().kdf() != HpkeKdf::HKDF_SHA256) { return util::Status(absl::StatusCode::kInvalidArgument, "Recipient public key has an unsupported KDF"); } if (recipient_public_key.params().aead() == HpkeAead::AEAD_UNKNOWN) { return util::Status(absl::StatusCode::kInvalidArgument, "Recipient public key is missing AEAD"); } return {absl::WrapUnique(new HpkeEncrypt(recipient_public_key))}; } util::StatusOr HpkeEncrypt::Encrypt( absl::string_view plaintext, absl::string_view context_info) const { util::StatusOr params = internal::HpkeParamsProtoToStruct(recipient_public_key_.params()); if (!params.ok()) return params.status(); util::StatusOr> sender_context = internal::HpkeContext::SetupSender( *params, recipient_public_key_.public_key(), context_info); if (!sender_context.ok()) return sender_context.status(); util::StatusOr ciphertext = (*sender_context)->Seal(plaintext, /*associated_data=*/""); if (!ciphertext.ok()) return ciphertext.status(); return internal::ConcatenatePayload((*sender_context)->EncapsulatedKey(), *ciphertext); } } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_encrypt.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_INTERNAL_HPKE_ENCRYPT_H_ #define TINK_HYBRID_INTERNAL_HPKE_ENCRYPT_H_ #include #include #include "absl/strings/string_view.h" #include "tink/hybrid_encrypt.h" #include "tink/util/statusor.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { class HpkeEncrypt : public HybridEncrypt { public: // Copyable and movable. HpkeEncrypt(const HpkeEncrypt& other) = default; HpkeEncrypt& operator=(const HpkeEncrypt& other) = default; HpkeEncrypt(HpkeEncrypt&& other) = default; HpkeEncrypt& operator=(HpkeEncrypt&& other) = default; static crypto::tink::util::StatusOr> New( const google::crypto::tink::HpkePublicKey& recipient_public_key); crypto::tink::util::StatusOr Encrypt( absl::string_view plaintext, absl::string_view context_info) const override; private: explicit HpkeEncrypt( const google::crypto::tink::HpkePublicKey& recipient_public_key) : recipient_public_key_(recipient_public_key) {} google::crypto::tink::HpkePublicKey recipient_public_key_; }; } // namespace tink } // namespace crypto #endif // TINK_HYBRID_INTERNAL_HPKE_ENCRYPT_H_ ================================================ FILE: cc/hybrid/internal/hpke_encrypt_boringssl.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_encrypt_boringssl.h" #include #include #include #include #include #include "absl/algorithm/container.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "openssl/base.h" #include "openssl/err.h" #include "openssl/hpke.h" #include "tink/hybrid/internal/hpke_util_boringssl.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace internal { util::StatusOr> HpkeEncryptBoringSsl::New( const google::crypto::tink::HpkeParams& params, absl::string_view recipient_public_key, absl::string_view context_info) { auto hpke_encrypt = absl::WrapUnique(new HpkeEncryptBoringSsl()); util::Status status = hpke_encrypt->Init(params, recipient_public_key, context_info); if (!status.ok()) { return status; } return std::move(hpke_encrypt); } util::StatusOr> HpkeEncryptBoringSsl::NewForTesting( const google::crypto::tink::HpkeParams& params, absl::string_view recipient_public_key, absl::string_view context_info, absl::string_view seed_for_testing) { auto hpke_encrypt = absl::WrapUnique(new HpkeEncryptBoringSsl()); util::Status status = hpke_encrypt->InitForTesting( params, recipient_public_key, context_info, seed_for_testing); if (!status.ok()) { return status; } return std::move(hpke_encrypt); } util::Status HpkeEncryptBoringSsl::Init( const google::crypto::tink::HpkeParams& params, absl::string_view recipient_public_key, absl::string_view context_info) { util::StatusOr kem = KemParam(params); if (!kem.ok()) { return kem.status(); } util::StatusOr kdf = KdfParam(params); if (!kdf.ok()) { return kdf.status(); } util::StatusOr aead = AeadParam(params); if (!aead.ok()) { return aead.status(); } uint8_t enc[EVP_HPKE_MAX_ENC_LENGTH]; size_t enc_len; if (!EVP_HPKE_CTX_setup_sender( sender_ctx_.get(), enc, &enc_len, sizeof(enc), *kem, *kdf, *aead, reinterpret_cast(recipient_public_key.data()), recipient_public_key.size(), reinterpret_cast(context_info.data()), context_info.size())) { return util::Status(absl::StatusCode::kUnknown, "Unable to set up HPKE sender context."); } encapsulated_key_ = std::string(reinterpret_cast(enc), enc_len); return util::OkStatus(); } util::Status HpkeEncryptBoringSsl::InitForTesting( const google::crypto::tink::HpkeParams& params, absl::string_view recipient_public_key, absl::string_view context_info, absl::string_view seed_for_testing) { util::StatusOr kem = KemParam(params); if (!kem.ok()) { return kem.status(); } util::StatusOr kdf = KdfParam(params); if (!kdf.ok()) { return kdf.status(); } util::StatusOr aead = AeadParam(params); if (!aead.ok()) { return aead.status(); } uint8_t enc[EVP_HPKE_MAX_ENC_LENGTH]; size_t enc_len; if (!EVP_HPKE_CTX_setup_sender_with_seed_for_testing( sender_ctx_.get(), enc, &enc_len, sizeof(enc), *kem, *kdf, *aead, reinterpret_cast(recipient_public_key.data()), recipient_public_key.size(), reinterpret_cast(context_info.data()), context_info.size(), reinterpret_cast(seed_for_testing.data()), seed_for_testing.size())) { return util::Status(absl::StatusCode::kUnknown, "Unable to set up HPKE sender context."); } encapsulated_key_ = std::string(reinterpret_cast(enc), enc_len); return util::OkStatus(); } util::StatusOr HpkeEncryptBoringSsl::EncapsulateKeyThenEncrypt( absl::string_view plaintext, absl::string_view associated_data) { size_t enc_size = encapsulated_key_.size(); std::string ciphertext(encapsulated_key_); subtle::ResizeStringUninitialized( &ciphertext, enc_size + plaintext.size() + EVP_HPKE_CTX_max_overhead(sender_ctx_.get())); size_t max_out_len = ciphertext.size() - enc_size; size_t ciphertext_size; if (!EVP_HPKE_CTX_seal( sender_ctx_.get(), reinterpret_cast(&ciphertext[enc_size]), &ciphertext_size, max_out_len, reinterpret_cast(plaintext.data()), plaintext.size(), reinterpret_cast(associated_data.data()), associated_data.size())) { return util::Status(absl::StatusCode::kUnknown, "BoringSSL HPKE encryption failed."); } return ciphertext; } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_encrypt_boringssl.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_INTERNAL_HPKE_ENCRYPT_BORINGSSL_H_ #define TINK_HYBRID_INTERNAL_HPKE_ENCRYPT_BORINGSSL_H_ #include #include #include #include "absl/base/attributes.h" #include "absl/strings/string_view.h" #include "openssl/hpke.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace internal { class ABSL_DEPRECATED("Use HpkeContext.") HpkeEncryptBoringSsl { public: // Sets up an HPKE sender context. Returns an error if initialization // fails. Otherwise, returns a unique pointer to the sender context. // // `params`: HPKE parameters proto (KEM, KDF, and AEAD). // `recipient_public_key`: KEM-encoding of recipient public key. // `context_info`: Application-specific context for key derivation. static util::StatusOr> New( const google::crypto::tink::HpkeParams& params, absl::string_view recipient_public_key, absl::string_view context_info); // NOTE: The following method SHOULD ONLY BE USED FOR TESTING. // // Sets up an HPKE sender context. Returns an error if initialization // fails. Otherwise, returns a unique pointer to the sender context. // // `params`: HPKE parameters proto (KEM, KDF, and AEAD). // `recipient_public_key`: KEM-encoding of recipient public key. // `context_info`: Application-specific context for key derivation. // `seed_for_testing`: Seed used to match test vector values. static util::StatusOr> NewForTesting( const google::crypto::tink::HpkeParams& params, absl::string_view recipient_public_key, absl::string_view context_info, absl::string_view seed_for_testing); // Performs an AEAD encryption of `plaintext` with `associated_data`. // Returns an error if encryption fails. Otherwise, returns the ciphertext // appended to the encapsulated key. util::StatusOr EncapsulateKeyThenEncrypt( absl::string_view plaintext, absl::string_view associated_data); const std::string& encapsulated_key() const { return encapsulated_key_; } private: HpkeEncryptBoringSsl() {} util::Status Init(const google::crypto::tink::HpkeParams& params, absl::string_view recipient_public_key, absl::string_view context_info); util::Status InitForTesting(const google::crypto::tink::HpkeParams& params, absl::string_view recipient_public_key, absl::string_view context_info, absl::string_view seed_for_testing); bssl::ScopedEVP_HPKE_CTX sender_ctx_; std::string encapsulated_key_; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_HYBRID_INTERNAL_HPKE_ENCRYPT_BORINGSSL_H_ ================================================ FILE: cc/hybrid/internal/hpke_encrypt_boringssl_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_encrypt_boringssl.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "openssl/hpke.h" #include "tink/hybrid/internal/hpke_test_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::HpkeAead; using ::google::crypto::tink::HpkeKdf; using ::google::crypto::tink::HpkeKem; using ::google::crypto::tink::HpkeParams; using ::testing::Values; class HpkeEncapsulateKeyThenEncryptBoringSslTest : public testing::TestWithParam {}; INSTANTIATE_TEST_SUITE_P( HpkeEncapsulateKeyThenEncryptBoringSslTestSuite, HpkeEncapsulateKeyThenEncryptBoringSslTest, Values(CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM), CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::CHACHA20_POLY1305))); TEST_P(HpkeEncapsulateKeyThenEncryptBoringSslTest, EncapsulateKeyThenEncrypt) { HpkeParams hpke_params = GetParam(); util::StatusOr params = CreateHpkeTestParams(hpke_params); ASSERT_THAT(params, IsOk()); util::StatusOr> hpke_encrypt = HpkeEncryptBoringSsl::NewForTesting( hpke_params, params->recipient_public_key, params->application_info, params->seed_for_testing); ASSERT_THAT(hpke_encrypt, IsOk()); util::StatusOr ciphertext = (*hpke_encrypt) ->EncapsulateKeyThenEncrypt(params->plaintext, params->associated_data); ASSERT_THAT(ciphertext, IsOkAndHolds(absl::StrCat(params->encapsulated_key, params->ciphertext))); } class HpkeEncryptBoringSslWithBadParamTest : public testing::TestWithParam {}; INSTANTIATE_TEST_SUITE_P( HpkeEncryptionBoringSslWithBadParamTestSuite, HpkeEncryptBoringSslWithBadParamTest, Values(CreateHpkeParams(HpkeKem::KEM_UNKNOWN, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM), CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::KDF_UNKNOWN, HpkeAead::AES_128_GCM), CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AEAD_UNKNOWN))); TEST_P(HpkeEncryptBoringSslWithBadParamTest, BadParamFails) { HpkeParams hpke_params = GetParam(); HpkeTestParams params = DefaultHpkeTestParams(); util::StatusOr> result = HpkeEncryptBoringSsl::NewForTesting( hpke_params, params.recipient_public_key, params.application_info, params.seed_for_testing); ASSERT_THAT(result.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkeEncryptBoringSslWithMissingPublicKeyTest, ZeroLengthPublicKeyFails) { HpkeParams hpke_params = CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); HpkeTestParams params = DefaultHpkeTestParams(); util::StatusOr> result = HpkeEncryptBoringSsl::NewForTesting( hpke_params, /*recipient_public_key=*/"", params.application_info, params.seed_for_testing); ASSERT_THAT(result.status(), StatusIs(absl::StatusCode::kUnknown)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_encrypt_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_encrypt.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/hybrid/internal/hpke_test_util.h" #include "tink/hybrid/internal/hpke_util.h" #include "tink/hybrid_encrypt.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::internal::CreateHpkeParams; using ::crypto::tink::internal::CreateHpkePublicKey; using ::crypto::tink::internal::CreateHpkeTestParams; using ::crypto::tink::internal::DefaultHpkeTestParams; using ::crypto::tink::internal::HpkeTestParams; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::HpkeAead; using ::google::crypto::tink::HpkeKdf; using ::google::crypto::tink::HpkeKem; using ::google::crypto::tink::HpkeParams; using ::google::crypto::tink::HpkePublicKey; using ::testing::SizeIs; using ::testing::Values; constexpr int kTagLength = 16; // Tag length (in bytes) for GCM and Poly1305. class HpkeEncryptTest : public testing::TestWithParam {}; INSTANTIATE_TEST_SUITE_P( HpkeEncryptionTestSuite, HpkeEncryptTest, Values(CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM), CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::CHACHA20_POLY1305), CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_256_GCM))); TEST_P(HpkeEncryptTest, SetupSenderContextAndEncrypt) { HpkeParams hpke_params = GetParam(); util::StatusOr encapsulated_key_length = internal::HpkeEncapsulatedKeyLength(hpke_params.kem()); ASSERT_THAT(encapsulated_key_length, IsOk()); util::StatusOr params = CreateHpkeTestParams(hpke_params); ASSERT_THAT(params, IsOk()); HpkePublicKey recipient_key = CreateHpkePublicKey(hpke_params, params->recipient_public_key); util::StatusOr> hpke_encrypt = HpkeEncrypt::New(recipient_key); ASSERT_THAT(hpke_encrypt, IsOk()); std::vector plaintexts = {"", params->plaintext}; std::vector context_infos = {"", params->application_info}; for (const std::string& plaintext : plaintexts) { for (const std::string& context_info : context_infos) { SCOPED_TRACE(absl::StrCat("plaintext: '", plaintext, "', context_info: '", context_info, "'")); int expected_ciphertext_length = *encapsulated_key_length + plaintext.size() + kTagLength; util::StatusOr encryption_result = (*hpke_encrypt)->Encrypt(plaintext, context_info); EXPECT_THAT(encryption_result, IsOkAndHolds(SizeIs(expected_ciphertext_length))); } } } class HpkeEncryptWithBadParamTest : public testing::TestWithParam { }; INSTANTIATE_TEST_SUITE_P( HpkeEncryptionWithBadParamTestSuite, HpkeEncryptWithBadParamTest, Values(CreateHpkeParams(HpkeKem::KEM_UNKNOWN, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM), CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::KDF_UNKNOWN, HpkeAead::AES_128_GCM), CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AEAD_UNKNOWN), CreateHpkeParams(HpkeKem::DHKEM_P256_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM), CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA384, HpkeAead::AES_128_GCM))); TEST_P(HpkeEncryptWithBadParamTest, BadParamFails) { HpkeParams hpke_params = GetParam(); HpkeTestParams params = DefaultHpkeTestParams(); HpkePublicKey recipient_key = CreateHpkePublicKey(hpke_params, params.recipient_public_key); util::StatusOr> hpke_encrypt = HpkeEncrypt::New(recipient_key); ASSERT_THAT(hpke_encrypt.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkeEncryptWithZeroLengthPublicKey, ZeroLengthPublicKeyFails) { HpkeParams hpke_params = CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); HpkeTestParams params = DefaultHpkeTestParams(); HpkePublicKey recipient_key = CreateHpkePublicKey(hpke_params, /*raw_key_bytes=*/""); util::StatusOr> hpke_encrypt = HpkeEncrypt::New(recipient_key); EXPECT_THAT(hpke_encrypt.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_key_boringssl.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_key_boringssl.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "openssl/base.h" #include "openssl/err.h" #include "openssl/hpke.h" #include "tink/hybrid/internal/hpke_util_boringssl.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace internal { util::StatusOr> HpkeKeyBoringSsl::New( const google::crypto::tink::HpkeKem& kem, absl::string_view recipient_private_key) { std::unique_ptr hpke_key = absl::WrapUnique(new HpkeKeyBoringSsl(kem)); util::Status status = hpke_key->Init(recipient_private_key); if (!status.ok()) { return status; } return std::move(hpke_key); } util::Status HpkeKeyBoringSsl::Init(absl::string_view recipient_private_key) { util::StatusOr hpke_kem = KemParam(kem_); if (!hpke_kem.ok()) { return hpke_kem.status(); } if (!EVP_HPKE_KEY_init( recipient_private_key_.get(), *hpke_kem, reinterpret_cast(recipient_private_key.data()), recipient_private_key.size())) { return util::Status( absl::StatusCode::kUnknown, "Unable to initialize BoringSSL HPKE recipient private key."); } return util::OkStatus(); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_key_boringssl.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_INTERNAL_HPKE_KEY_BORINGSSL_H_ #define TINK_HYBRID_INTERNAL_HPKE_KEY_BORINGSSL_H_ #include #include #include #include "absl/base/attributes.h" #include "absl/strings/string_view.h" #include "openssl/hpke.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace internal { class ABSL_DEPRECATED("Store keys in util::SecretData.") HpkeKeyBoringSsl { public: // Initializes an HPKE recipient private key. Returns an error if // initialization fails. Otherwise, returns a unique pointer to the key. // // `kem`: HPKE KEM parameter. // `recipient_private_key`: KEM-encoding of recipient private key. static util::StatusOr> New( const google::crypto::tink::HpkeKem& kem, absl::string_view recipient_private_key); // HpkeKeyBoringSsl objects are neither movable, nor copyable. HpkeKeyBoringSsl(HpkeKeyBoringSsl&& other) = delete; HpkeKeyBoringSsl& operator=(HpkeKeyBoringSsl&& other) = delete; HpkeKeyBoringSsl(const HpkeKeyBoringSsl&) = delete; HpkeKeyBoringSsl& operator=(const HpkeKeyBoringSsl&) = delete; const google::crypto::tink::HpkeKem& kem() const { return kem_; } const EVP_HPKE_KEY* recipient_private_key() const { return recipient_private_key_.get(); } private: explicit HpkeKeyBoringSsl(const google::crypto::tink::HpkeKem& kem) : kem_(kem) {} util::Status Init(absl::string_view recipient_private_key); google::crypto::tink::HpkeKem kem_; bssl::ScopedEVP_HPKE_KEY recipient_private_key_; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_HYBRID_INTERNAL_HPKE_KEY_BORINGSSL_H_ ================================================ FILE: cc/hybrid/internal/hpke_key_boringssl_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_key_boringssl.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "openssl/hpke.h" #include "tink/hybrid/internal/hpke_test_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::HpkeAead; using ::google::crypto::tink::HpkeKdf; using ::google::crypto::tink::HpkeKem; using ::google::crypto::tink::HpkeParams; TEST(HpkeKeyBoringSslTest, CreateValidHpkeKey) { HpkeParams hpke_params = CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); HpkeTestParams params = DefaultHpkeTestParams(); util::StatusOr> hpke_key = HpkeKeyBoringSsl::New(hpke_params.kem(), params.recipient_private_key); ASSERT_THAT(hpke_key, IsOk()); } TEST(HpkeKeyBoringSslTest, BadKemFails) { HpkeTestParams params = DefaultHpkeTestParams(); util::StatusOr> result = HpkeKeyBoringSsl::New(HpkeKem::KEM_UNKNOWN, params.recipient_private_key); ASSERT_THAT(result.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkeKeyBoringSslTest, ZeroLengthPrivateKeyFails) { util::StatusOr> result = HpkeKeyBoringSsl::New(HpkeKem::DHKEM_X25519_HKDF_SHA256, /*recipient_private_key=*/""); ASSERT_THAT(result.status(), StatusIs(absl::StatusCode::kUnknown)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_key_manager_util.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_key_manager_util.h" #include #include "absl/status/status.h" #include "tink/util/status.h" #include "tink/util/validation.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace internal { using ::google::crypto::tink::HpkeAead; using ::google::crypto::tink::HpkeKdf; using ::google::crypto::tink::HpkeKem; using ::google::crypto::tink::HpkeParams; using ::google::crypto::tink::HpkePublicKey; util::Status ValidateParams(const HpkeParams& params) { if (params.kem() == HpkeKem::KEM_UNKNOWN) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid KEM param."); } if (params.kdf() == HpkeKdf::KDF_UNKNOWN) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid KDF param."); } if (params.aead() == HpkeAead::AEAD_UNKNOWN) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid AEAD param."); } return util::OkStatus(); } util::Status ValidateKeyAndVersion(const HpkePublicKey& key, uint32_t max_key_version) { util::Status status = ValidateVersion(key.version(), max_key_version); if (!status.ok()) return status; if (!key.has_params()) { return util::Status(absl::StatusCode::kInvalidArgument, "Missing HPKE key params."); } return ValidateParams(key.params()); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_key_manager_util.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_INTERNAL_HPKE_KEY_MANAGER_UTIL_H_ #define TINK_HYBRID_INTERNAL_HPKE_KEY_MANAGER_UTIL_H_ #include #include #include "tink/util/status.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace internal { crypto::tink::util::Status ValidateParams( const google::crypto::tink::HpkeParams& params); crypto::tink::util::Status ValidateKeyAndVersion( const google::crypto::tink::HpkePublicKey& key, uint32_t max_key_version); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_HYBRID_INTERNAL_HPKE_KEY_MANAGER_UTIL_H_ ================================================ FILE: cc/hybrid/internal/hpke_key_manager_util_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_key_manager_util.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/hybrid/internal/hpke_test_util.h" #include "tink/util/status.h" #include "tink/util/test_matchers.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::internal::CreateHpkeParams; using ::crypto::tink::internal::CreateHpkePublicKey; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::HpkeAead; using ::google::crypto::tink::HpkeKdf; using ::google::crypto::tink::HpkeKem; using ::google::crypto::tink::HpkePublicKey; TEST(HpkeKeyManagerUtilTest, ValidateValidParamsSucceeds) { ASSERT_THAT(ValidateParams(CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_256_GCM)), IsOk()); } TEST(HpkeKeyManagerUtilTest, ValidateInvalidParamsFails) { ASSERT_THAT( ValidateParams(CreateHpkeParams( HpkeKem::KEM_UNKNOWN, HpkeKdf::HKDF_SHA256, HpkeAead::AES_256_GCM)), StatusIs(absl::StatusCode::kInvalidArgument)); ASSERT_THAT(ValidateParams(CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::KDF_UNKNOWN, HpkeAead::AES_256_GCM)), StatusIs(absl::StatusCode::kInvalidArgument)); ASSERT_THAT(ValidateParams(CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AEAD_UNKNOWN)), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkeKeyManagerUtilTest, ValidateValidKeyAndVersionSucceeds) { HpkePublicKey key = CreateHpkePublicKey( CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_256_GCM), "rawkeybytes"); ASSERT_THAT(ValidateKeyAndVersion(key, /*max_key_version=*/1), IsOk()); } TEST(HpkeKeyManagerUtilTest, ValidateTooHighKeyVersionFails) { HpkePublicKey key = CreateHpkePublicKey( CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_256_GCM), "rawkeybytes"); key.set_version(1); ASSERT_THAT(ValidateKeyAndVersion(key, /*max_key_version=*/0), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkeKeyManagerUtilTest, ValidateMissingKeyParamsFails) { HpkePublicKey key = CreateHpkePublicKey( CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_256_GCM), "rawkeybytes"); key.clear_params(); ASSERT_THAT(ValidateKeyAndVersion(key, /*max_key_version=*/1), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_private_key_manager.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_private_key_manager.h" #include #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "openssl/base.h" #include "tink/hybrid/internal/hpke_key_manager_util.h" #include "tink/internal/ec_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/subtle/common_enums.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::subtle::EcPointFormat; using ::crypto::tink::subtle::EllipticCurveType; using ::google::crypto::tink::HpkeKem; using ::google::crypto::tink::HpkeKeyFormat; using ::google::crypto::tink::HpkePrivateKey; using ::google::crypto::tink::HpkePublicKey; util::Status GenerateX25519Key(HpkePublicKey& public_key, HpkePrivateKey& private_key) { util::StatusOr> key = internal::NewX25519Key(); if (!key.ok()) { return key.status(); } public_key.set_public_key((*key)->public_value, X25519KeyPubKeySize()); private_key.set_private_key((*key)->private_key, X25519KeyPrivKeySize()); return util::OkStatus(); } util::Status GenerateEcKey(HpkePublicKey& public_key, HpkePrivateKey& private_key, EllipticCurveType ec_curve_type) { util::StatusOr ec_key = internal::NewEcKey(ec_curve_type); if (!ec_key.ok()) { return ec_key.status(); } util::StatusOr> pub_point = internal::GetEcPoint(ec_curve_type, ec_key->pub_x, ec_key->pub_y); if (!pub_point.ok()) { return pub_point.status(); } util::StatusOr encoded_pub_point = EcPointEncode( ec_curve_type, EcPointFormat::UNCOMPRESSED, pub_point->get()); if (!encoded_pub_point.ok()) { return encoded_pub_point.status(); } private_key.set_private_key( std::string(util::SecretDataAsStringView(ec_key->priv))); public_key.set_public_key(encoded_pub_point.value()); return util::OkStatus(); } } // namespace util::Status HpkePrivateKeyManager::ValidateKeyFormat( const HpkeKeyFormat& key_format) const { if (!key_format.has_params()) { return util::Status(absl::StatusCode::kInvalidArgument, "Missing params."); } return ValidateParams(key_format.params()); } util::StatusOr HpkePrivateKeyManager::CreateKey( const HpkeKeyFormat& key_format) const { // Set key metadata. HpkePrivateKey private_key; private_key.set_version(get_version()); HpkePublicKey* public_key = private_key.mutable_public_key(); public_key->set_version(get_version()); *(public_key->mutable_params()) = key_format.params(); // Generate key material. switch (key_format.params().kem()) { case HpkeKem::DHKEM_X25519_HKDF_SHA256: { util::Status res = GenerateX25519Key(*public_key, private_key); if (!res.ok()) { return res; } break; } case HpkeKem::DHKEM_P256_HKDF_SHA256: { util::Status res = GenerateEcKey(*public_key, private_key, EllipticCurveType::NIST_P256); if (!res.ok()) { return res; } break; } case HpkeKem::DHKEM_P384_HKDF_SHA384: { util::Status res = GenerateEcKey(*public_key, private_key, EllipticCurveType::NIST_P384); if (!res.ok()) { return res; } break; } case HpkeKem::DHKEM_P521_HKDF_SHA512: { util::Status res = GenerateEcKey(*public_key, private_key, EllipticCurveType::NIST_P521); if (!res.ok()) { return res; } break; } default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Unsupported KEM type: ", key_format.params().kem())); } return private_key; } util::StatusOr HpkePrivateKeyManager::GetPublicKey( const HpkePrivateKey& private_key) const { return private_key.public_key(); } util::Status HpkePrivateKeyManager::ValidateKey( const HpkePrivateKey& key) const { util::Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; if (!key.has_public_key()) { return util::Status(absl::StatusCode::kInvalidArgument, "Missing HPKE public key."); } return ValidateKeyAndVersion(key.public_key(), get_version()); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_private_key_manager.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_INTERNAL_HPKE_PRIVATE_KEY_MANAGER_H_ #define TINK_HYBRID_INTERNAL_HPKE_PRIVATE_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/key_type_manager.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/hybrid/internal/hpke_decrypt.h" #include "tink/hybrid_decrypt.h" #include "tink/key_manager.h" #include "tink/util/constants.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/hpke.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { class HpkePrivateKeyManager : public PrivateKeyTypeManager> { public: class HybridDecryptFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::HpkePrivateKey& private_key) const override { return HpkeDecrypt::New(private_key); } }; HpkePrivateKeyManager() : PrivateKeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::HpkePrivateKey& key) const override; crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::HpkeKeyFormat& key_format) const override; crypto::tink::util::StatusOr CreateKey( const google::crypto::tink::HpkeKeyFormat& key_format) const override; crypto::tink::util::StatusOr GetPublicKey( const google::crypto::tink::HpkePrivateKey& private_key) const override; private: const std::string key_type_ = absl::StrCat( kTypeGoogleapisCom, google::crypto::tink::HpkePrivateKey().GetTypeName()); }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_HYBRID_INTERNAL_HPKE_PRIVATE_KEY_MANAGER_H_ ================================================ FILE: cc/hybrid/internal/hpke_private_key_manager_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_private_key_manager.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/btree_set.h" #include "absl/status/status.h" #include "tink/hybrid/internal/hpke_encrypt.h" #include "tink/hybrid_decrypt.h" #include "tink/hybrid_encrypt.h" #include "tink/subtle/hybrid_test_util.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/hpke.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::HpkeAead; using ::google::crypto::tink::HpkeKdf; using ::google::crypto::tink::HpkeKem; using ::google::crypto::tink::HpkeKeyFormat; using ::google::crypto::tink::HpkeParams; using ::google::crypto::tink::HpkePrivateKey; using ::google::crypto::tink::HpkePublicKey; using ::google::crypto::tink::KeyData; using ::testing::Eq; using ::testing::IsEmpty; using ::testing::Not; HpkeKeyFormat CreateKeyFormat(HpkeKem kem, HpkeKdf kdf, HpkeAead aead) { HpkeKeyFormat key_format; HpkeParams *params = key_format.mutable_params(); params->set_kem(kem); params->set_kdf(kdf); params->set_aead(aead); return key_format; } util::StatusOr CreateKey(HpkeKem kem, HpkeKdf kdf, HpkeAead aead) { return HpkePrivateKeyManager().CreateKey(CreateKeyFormat(kem, kdf, aead)); } TEST(HpkePrivateKeyManagerTest, BasicAccessors) { EXPECT_THAT(HpkePrivateKeyManager().get_version(), Eq(0)); EXPECT_THAT(HpkePrivateKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PRIVATE)); EXPECT_THAT(HpkePrivateKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.HpkePrivateKey")); } TEST(HpkePrivateKeyManagerTest, ValidateEmptyKeyFormatFails) { EXPECT_THAT(HpkePrivateKeyManager().ValidateKeyFormat(HpkeKeyFormat()), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkePrivateKeyManagerTest, ValidateKeyFormatSucceeds) { EXPECT_THAT(HpkePrivateKeyManager().ValidateKeyFormat( CreateKeyFormat(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM)), IsOk()); } TEST(HpkePrivateKeyManagerTest, ValidateKeyFormatWithInvalidKemFails) { EXPECT_THAT( HpkePrivateKeyManager().ValidateKeyFormat(CreateKeyFormat( HpkeKem::KEM_UNKNOWN, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM)), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkePrivateKeyManagerTest, ValidateKeyFormatWithInvalidKdfFails) { EXPECT_THAT(HpkePrivateKeyManager().ValidateKeyFormat( CreateKeyFormat(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::KDF_UNKNOWN, HpkeAead::AES_128_GCM)), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkePrivateKeyManagerTest, ValidateKeyFormatWithInvalidAeadFails) { EXPECT_THAT(HpkePrivateKeyManager().ValidateKeyFormat(CreateKeyFormat( HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AEAD_UNKNOWN)), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkePrivateKeyManagerTest, CreateKeySucceeds) { HpkeKeyFormat key_format = CreateKeyFormat(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); util::StatusOr key = HpkePrivateKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); ASSERT_TRUE(key->has_public_key()); ASSERT_TRUE(key->public_key().has_params()); EXPECT_THAT(key->public_key().params().kem(), Eq(key_format.params().kem())); EXPECT_THAT(key->public_key().params().kdf(), Eq(key_format.params().kdf())); EXPECT_THAT(key->public_key().params().aead(), Eq(key_format.params().aead())); EXPECT_THAT(key->public_key().public_key(), Not(IsEmpty())); EXPECT_THAT(key->private_key(), Not(IsEmpty())); } TEST(HpkePrivateKeyManagerTest, CreateP256KeySucceeds) { HpkeKeyFormat key_format = CreateKeyFormat(HpkeKem::DHKEM_P256_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); util::StatusOr key = HpkePrivateKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); ASSERT_TRUE(key->has_public_key()); ASSERT_TRUE(key->public_key().has_params()); EXPECT_THAT(key->public_key().params().kem(), Eq(key_format.params().kem())); EXPECT_THAT(key->public_key().params().kdf(), Eq(key_format.params().kdf())); EXPECT_THAT(key->public_key().params().aead(), Eq(key_format.params().aead())); EXPECT_THAT(key->public_key().public_key().size(), Eq(65)); EXPECT_THAT(key->private_key().size(), Eq(32)); // Test that all generated keys are unique const int number_of_keys = 1000; absl::btree_set private_keys; absl::btree_set public_keys; for (int i = 0; i < number_of_keys; ++i) { util::StatusOr key = HpkePrivateKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); private_keys.insert(key->private_key()); public_keys.insert(key->public_key().public_key()); } EXPECT_THAT(private_keys.size(), Eq(number_of_keys)); EXPECT_THAT(public_keys.size(), Eq(number_of_keys)); } TEST(HpkePrivateKeyManagerTest, CreateP384KeySucceeds) { HpkeKeyFormat key_format = CreateKeyFormat(HpkeKem::DHKEM_P384_HKDF_SHA384, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); util::StatusOr key = HpkePrivateKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); ASSERT_TRUE(key->has_public_key()); ASSERT_TRUE(key->public_key().has_params()); EXPECT_THAT(key->public_key().params().kem(), Eq(key_format.params().kem())); EXPECT_THAT(key->public_key().params().kdf(), Eq(key_format.params().kdf())); EXPECT_THAT(key->public_key().params().aead(), Eq(key_format.params().aead())); EXPECT_THAT(key->public_key().public_key().size(), Eq(97)); EXPECT_THAT(key->private_key().size(), Eq(48)); // Test that all generated keys are unique const int number_of_keys = 1000; absl::btree_set private_keys; absl::btree_set public_keys; for (int i = 0; i < number_of_keys; ++i) { util::StatusOr key = HpkePrivateKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); private_keys.insert(key->private_key()); public_keys.insert(key->public_key().public_key()); } EXPECT_THAT(private_keys.size(), Eq(number_of_keys)); EXPECT_THAT(public_keys.size(), Eq(number_of_keys)); } TEST(HpkePrivateKeyManagerTest, CreateP521KeySucceeds) { HpkeKeyFormat key_format = CreateKeyFormat(HpkeKem::DHKEM_P521_HKDF_SHA512, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); util::StatusOr key = HpkePrivateKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); ASSERT_TRUE(key->has_public_key()); ASSERT_TRUE(key->public_key().has_params()); EXPECT_THAT(key->public_key().params().kem(), Eq(key_format.params().kem())); EXPECT_THAT(key->public_key().params().kdf(), Eq(key_format.params().kdf())); EXPECT_THAT(key->public_key().params().aead(), Eq(key_format.params().aead())); EXPECT_THAT(key->public_key().public_key().size(), Eq(133)); EXPECT_THAT(key->private_key().size(), Eq(66)); // Test that all generated keys are unique const int number_of_keys = 1000; absl::btree_set private_keys; absl::btree_set public_keys; for (int i = 0; i < number_of_keys; ++i) { util::StatusOr key = HpkePrivateKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); private_keys.insert(key->private_key()); public_keys.insert(key->public_key().public_key()); } EXPECT_THAT(private_keys.size(), Eq(number_of_keys)); EXPECT_THAT(public_keys.size(), Eq(number_of_keys)); } TEST(HpkePrivateKeyManagerTest, CreateKeyWithInvalidKemFails) { HpkeKeyFormat key_format = CreateKeyFormat( HpkeKem::KEM_UNKNOWN, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); ASSERT_THAT(HpkePrivateKeyManager().CreateKey(key_format).status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkePrivateKeyManagerTest, ValidateEmptyKeyFails) { EXPECT_THAT(HpkePrivateKeyManager().ValidateKey(HpkePrivateKey()), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkePrivateKeyManagerTest, ValidateKeySucceeds) { util::StatusOr key = CreateKey(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); ASSERT_THAT(key, IsOk()); EXPECT_THAT(HpkePrivateKeyManager().ValidateKey(*key), IsOk()); } TEST(HpkePrivateKeyManagerTest, ValidateKeyWithWrongVersionFails) { util::StatusOr key = CreateKey(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); ASSERT_THAT(key, IsOk()); key->set_version(1); EXPECT_THAT(HpkePrivateKeyManager().ValidateKey(*key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkePrivateKeyManagerTest, ValidateKeyWithInvalidKemFails) { util::StatusOr key = CreateKey(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); ASSERT_THAT(key, IsOk()); key->mutable_public_key()->mutable_params()->set_kem(HpkeKem::KEM_UNKNOWN); EXPECT_THAT(HpkePrivateKeyManager().ValidateKey(*key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkePrivateKeyManagerTest, ValidateKeyWithInvalidKdfFails) { util::StatusOr key = CreateKey(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::KDF_UNKNOWN, HpkeAead::AES_128_GCM); ASSERT_THAT(key, IsOk()); EXPECT_THAT(HpkePrivateKeyManager().ValidateKey(*key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkePrivateKeyManagerTest, ValidateKeyWithInvalidAeadFails) { util::StatusOr key = CreateKey(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AEAD_UNKNOWN); ASSERT_THAT(key, IsOk()); EXPECT_THAT(HpkePrivateKeyManager().ValidateKey(*key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkePrivateKeyManagerTest, GetPublicKeySucceeds) { HpkeKeyFormat key_format = CreateKeyFormat(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); util::StatusOr key = HpkePrivateKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); util::StatusOr public_key = HpkePrivateKeyManager().GetPublicKey(*key); ASSERT_THAT(public_key, IsOk()); ASSERT_TRUE(key->has_public_key()); ASSERT_TRUE(key->public_key().has_params()); EXPECT_THAT(public_key->params().kem(), Eq(key_format.params().kem())); EXPECT_THAT(public_key->params().kdf(), Eq(key_format.params().kdf())); EXPECT_THAT(public_key->params().aead(), Eq(key_format.params().aead())); ASSERT_THAT(public_key->public_key(), Not(IsEmpty())); EXPECT_THAT(public_key->public_key(), Eq(key->public_key().public_key())); } TEST(HpkePrivateKeyManagerTest, GetPublicKeyP256Succeeds) { HpkeKeyFormat key_format = CreateKeyFormat(HpkeKem::DHKEM_P256_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); util::StatusOr key = HpkePrivateKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); util::StatusOr public_key = HpkePrivateKeyManager().GetPublicKey(*key); ASSERT_THAT(public_key, IsOk()); ASSERT_TRUE(key->has_public_key()); ASSERT_TRUE(key->public_key().has_params()); EXPECT_THAT(public_key->params().kem(), Eq(HpkeKem::DHKEM_P256_HKDF_SHA256)); EXPECT_THAT(public_key->params().kdf(), Eq(HpkeKdf::HKDF_SHA256)); EXPECT_THAT(public_key->params().aead(), Eq(HpkeAead::AES_128_GCM)); ASSERT_THAT(public_key->public_key(), Not(IsEmpty())); EXPECT_THAT(public_key->public_key(), Eq(key->public_key().public_key())); } TEST(HpkePrivateKeyManagerTest, GetPublicKey384Succeeds) { HpkeKeyFormat key_format = CreateKeyFormat(HpkeKem::DHKEM_P384_HKDF_SHA384, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); util::StatusOr key = HpkePrivateKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); util::StatusOr public_key = HpkePrivateKeyManager().GetPublicKey(*key); ASSERT_THAT(public_key, IsOk()); ASSERT_TRUE(key->has_public_key()); ASSERT_TRUE(key->public_key().has_params()); EXPECT_THAT(public_key->params().kem(), Eq(HpkeKem::DHKEM_P384_HKDF_SHA384)); EXPECT_THAT(public_key->params().kdf(), Eq(HpkeKdf::HKDF_SHA256)); EXPECT_THAT(public_key->params().aead(), Eq(HpkeAead::AES_128_GCM)); ASSERT_THAT(public_key->public_key(), Not(IsEmpty())); EXPECT_THAT(public_key->public_key(), Eq(key->public_key().public_key())); } TEST(HpkePrivateKeyManagerTest, GetPublicKey521Succeeds) { HpkeKeyFormat key_format = CreateKeyFormat(HpkeKem::DHKEM_P521_HKDF_SHA512, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); util::StatusOr key = HpkePrivateKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); util::StatusOr public_key = HpkePrivateKeyManager().GetPublicKey(*key); ASSERT_THAT(public_key, IsOk()); ASSERT_TRUE(key->has_public_key()); ASSERT_TRUE(key->public_key().has_params()); EXPECT_THAT(public_key->params().kem(), Eq(HpkeKem::DHKEM_P521_HKDF_SHA512)); EXPECT_THAT(public_key->params().kdf(), Eq(HpkeKdf::HKDF_SHA256)); EXPECT_THAT(public_key->params().aead(), Eq(HpkeAead::AES_128_GCM)); ASSERT_THAT(public_key->public_key(), Not(IsEmpty())); EXPECT_THAT(public_key->public_key(), Eq(key->public_key().public_key())); } TEST(HpkePrivateKeyManagerTest, EncryptThenDecryptSucceeds) { util::StatusOr private_key = CreateKey(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); ASSERT_THAT(private_key, IsOk()); util::StatusOr public_key = HpkePrivateKeyManager().GetPublicKey(*private_key); ASSERT_THAT(public_key, IsOk()); util::StatusOr> decrypt = HpkePrivateKeyManager().GetPrimitive(*private_key); ASSERT_THAT(decrypt, IsOk()); util::StatusOr> encrypt = HpkeEncrypt::New(*public_key); ASSERT_THAT(encrypt, IsOk()); ASSERT_THAT(HybridEncryptThenDecrypt(encrypt->get(), decrypt->get(), "some text", "some aad"), IsOk()); } TEST(HpkePrivateKeyManagerTest, GetPrimitiveP256Fails) { util::StatusOr private_key = CreateKey(HpkeKem::DHKEM_P256_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); ASSERT_THAT(private_key, IsOk()); util::StatusOr public_key = HpkePrivateKeyManager().GetPublicKey(*private_key); ASSERT_THAT(public_key, IsOk()); util::StatusOr> decrypt = HpkePrivateKeyManager().GetPrimitive(*private_key); ASSERT_THAT(decrypt.status(), StatusIs(absl::StatusCode::kInvalidArgument)); util::StatusOr> encrypt = HpkeEncrypt::New(*public_key); ASSERT_THAT(encrypt.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkePrivateKeyManagerTest, GetPrimitiveP384Fails) { util::StatusOr private_key = CreateKey(HpkeKem::DHKEM_P384_HKDF_SHA384, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); ASSERT_THAT(private_key, IsOk()); util::StatusOr public_key = HpkePrivateKeyManager().GetPublicKey(*private_key); ASSERT_THAT(public_key, IsOk()); util::StatusOr> decrypt = HpkePrivateKeyManager().GetPrimitive(*private_key); ASSERT_THAT(decrypt.status(), StatusIs(absl::StatusCode::kInvalidArgument)); util::StatusOr> encrypt = HpkeEncrypt::New(*public_key); ASSERT_THAT(encrypt.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkePrivateKeyManagerTest, GetPrimitiveP521Fails) { util::StatusOr private_key = CreateKey(HpkeKem::DHKEM_P521_HKDF_SHA512, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); ASSERT_THAT(private_key, IsOk()); util::StatusOr public_key = HpkePrivateKeyManager().GetPublicKey(*private_key); ASSERT_THAT(public_key, IsOk()); util::StatusOr> decrypt = HpkePrivateKeyManager().GetPrimitive(*private_key); ASSERT_THAT(decrypt.status(), StatusIs(absl::StatusCode::kInvalidArgument)); util::StatusOr> encrypt = HpkeEncrypt::New(*public_key); ASSERT_THAT(encrypt.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkePrivateKeyManagerTest, EncryptThenDecryptWithDifferentKeysFails) { util::StatusOr private_key = CreateKey(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); ASSERT_THAT(private_key, IsOk()); util::StatusOr different_private_key = CreateKey(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM); ASSERT_THAT(different_private_key, IsOk()); util::StatusOr public_key = HpkePrivateKeyManager().GetPublicKey(*different_private_key); ASSERT_THAT(public_key, IsOk()); util::StatusOr> decrypt = HpkePrivateKeyManager().GetPrimitive(*private_key); ASSERT_THAT(decrypt, IsOk()); util::StatusOr> encrypt = HpkeEncrypt::New(*public_key); ASSERT_THAT(encrypt, IsOk()); ASSERT_THAT(HybridEncryptThenDecrypt(encrypt->get(), decrypt->get(), "some text", "some aad"), Not(IsOk())); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_public_key_manager.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_public_key_manager.h" #include "tink/hybrid/internal/hpke_key_manager_util.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { using ::google::crypto::tink::HpkePublicKey; util::Status HpkePublicKeyManager::ValidateKey(const HpkePublicKey& key) const { return ValidateKeyAndVersion(key, get_version()); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_public_key_manager.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_INTERNAL_HPKE_PUBLIC_KEY_MANAGER_H_ #define TINK_HYBRID_INTERNAL_HPKE_PUBLIC_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/hybrid/internal/hpke_encrypt.h" #include "tink/hybrid_encrypt.h" #include "tink/key_manager.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/hpke.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { class HpkePublicKeyManager : public KeyTypeManager> { public: class HybridEncryptFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::HpkePublicKey& public_key) const override { return HpkeEncrypt::New(public_key); } }; HpkePublicKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PUBLIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::HpkePublicKey& key) const override; private: const std::string key_type_ = absl::StrCat( kTypeGoogleapisCom, google::crypto::tink::HpkePublicKey().GetTypeName()); }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_HYBRID_INTERNAL_HPKE_PUBLIC_KEY_MANAGER_H_ ================================================ FILE: cc/hybrid/internal/hpke_public_key_manager_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_public_key_manager.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/hybrid/internal/hpke_test_util.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/hpke.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::internal::CreateHpkeParams; using ::crypto::tink::internal::CreateHpkePublicKey; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::HpkeAead; using ::google::crypto::tink::HpkeKdf; using ::google::crypto::tink::HpkeKem; using ::google::crypto::tink::HpkePublicKey; using ::google::crypto::tink::KeyData; using ::testing::Eq; TEST(HpkePublicKeyManagerTest, BasicAccessors) { EXPECT_THAT(HpkePublicKeyManager().get_version(), Eq(0)); EXPECT_THAT(HpkePublicKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PUBLIC)); EXPECT_THAT(HpkePublicKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.HpkePublicKey")); } TEST(HpkePublicKeyManagerTest, ValidateEmptyKeyFails) { EXPECT_THAT(HpkePublicKeyManager().ValidateKey(HpkePublicKey()), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkePublicKeyManagerTest, ValidateKeySucceeds) { EXPECT_THAT(HpkePublicKeyManager().ValidateKey(CreateHpkePublicKey( CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM), /*raw_key_bytes=*/"")), IsOk()); } TEST(HpkePublicKeyManagerTest, ValidateKeyWithInvalidKemFails) { EXPECT_THAT(HpkePublicKeyManager().ValidateKey(CreateHpkePublicKey( CreateHpkeParams(HpkeKem::KEM_UNKNOWN, HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM), /*raw_key_bytes=*/"")), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkePublicKeyManagerTest, ValidateKeyWithInvalidKdfFails) { EXPECT_THAT(HpkePublicKeyManager().ValidateKey(CreateHpkePublicKey( CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::KDF_UNKNOWN, HpkeAead::AES_128_GCM), /*raw_key_bytes=*/"")), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkePublicKeyManagerTest, ValidateKeyWithInvalidAeadFails) { EXPECT_THAT( HpkePublicKeyManager().ValidateKey(CreateHpkePublicKey( CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256, HpkeAead::AEAD_UNKNOWN), /*raw_key_bytes=*/"")), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_test_util.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_test_util.h" #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/hybrid/internal/hpke_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace internal { // Test vector from https://www.rfc-editor.org/rfc/rfc9180.html#appendix-A.1. // DHKEM(X25519, HKDF-SHA256), HKDF-SHA256, AES-128-GCM const absl::string_view kTestX25519HkdfSha256Aes128Gcm[] = { "3948cfe0ad1ddb695d780e59077195da6c56506b027329794ab02bca80815c4d", // pkRm "52c4a758a802cd8b936eceea314432798d5baf2d7e9235dc084ab1b9cfa2f736", // skEm "4f6465206f6e2061204772656369616e2055726e", // info "4265617574792069732074727574682c20747275746820626561757479", // pt "436f756e742d30", // aad "f938558b5d72f1a23810b4be2ab4f84331acc02fc97babc53a52ae8218a355a96d8770ac83" "d07bea87e13c512a", // ct "4612c550263fc8ad58375df3f557aac531d26850903e55a9f23f21d8534e8ac8", // skRm "37fda3567bdbd628e88668c3c8d7e97d1d1253b6d4ea6d44c150f741f1bf4431", // enc "", // exporter_contexts[0] "00", // exporter_contexts[1] "54657374436f6e74657874", // exporter_contexts[2] // exporter_values[0] "3853fe2b4035195a573ffc53856e77058e15d9ea064de3e59f4961d0095250ee", // exporter_values[1] "2e8f0b54673c7029649d4eb9d5e33bf1872cf76d623ff164ac185da9e88c21a5", // exporter_values[2] "e9e43065102c3836401bed8c3c3c75ae46be1639869391d62c61f1ec7af54931" }; // Test vector from https://www.rfc-editor.org/rfc/rfc9180.html#appendix-A.2. // DHKEM(X25519, HKDF-SHA256), HKDF-SHA256, ChaCha20Poly1305 const absl::string_view kTestX25519HkdfSha256ChaCha20Poly1305[] = { "4310ee97d88cc1f088a5576c77ab0cf5c3ac797f3d95139c6c84b5429c59662a", // pkRm "f4ec9b33b792c372c1d2c2063507b684ef925b8c75a42dbcbf57d63ccd381600", // skEm "4f6465206f6e2061204772656369616e2055726e", // info "4265617574792069732074727574682c20747275746820626561757479", // pt "436f756e742d30", // aad "1c5250d8034ec2b784ba2cfd69dbdb8af406cfe3ff938e131f0def8c8b60b4db21993c" "62ce81883d2dd1b51a28", // ct "8057991eef8f1f1af18f4a9491d16a1ce333f695d4db8e38da75975c4478e0fb", // skRm "1afa08d3dec047a643885163f1180476fa7ddb54c6a8029ea33f95796bf2ac4a", // enc "", // exporter_contexts[0] "00", // exporter_contexts[1] "54657374436f6e74657874", // exporter_contexts[2] // exporter_values[0] "4bbd6243b8bb54cec311fac9df81841b6fd61f56538a775e7c80a9f40160606e", // exporter_values[1] "8c1df14732580e5501b00f82b10a1647b40713191b7c1240ac80e2b68808ba69", // exporter_values[2] "5acb09211139c43b3090489a9da433e8a30ee7188ba8b0a9a1ccf0c229283e53" }; // BoringSSL test vectors with aead_id = 2. Missing 'skRm' and 'enc'. // (No test vectors provided by RFC 9180 for this test case). // DHKEM(X25519, HKDF-SHA256), HKDF-SHA256, AES-256-GCM const absl::string_view kTestX25519HkdfSha256Aes256Gcm[] = { "ac66bae9ffa270cf4a89ed9f274e30c0456babae2572aaaf002ff0d8884ab018", // pkRm "28e212563a8b6f068af7ff17400ff1baf23612b7a738bbaf5dfb321b2b5b431a", // skEm "4f6465206f6e2061204772656369616e2055726e", // info "4265617574792069732074727574682c20747275746820626561757479", // pt "436f756e742d30", // aad "23ded2d5d90ea89d975dac4792b297240f194952d7421aacbff0474100052b6bb8aa58d1" "8ef6c42b6960e2e28f", // ct "", // Missing skRm "", // Missing enc "", // Missing exporter_contexts[0] "", // Missing exporter_contexts[1] "", // Missing exporter_contexts[2] "", // Missing exporter_values[0] "", // Missing exporter_values[1] "", // Missing exporter_values[2] }; HpkeTestParams DefaultHpkeTestParams() { return HpkeTestParams(kTestX25519HkdfSha256Aes128Gcm); } util::StatusOr CreateHpkeTestParams( const google::crypto::tink::HpkeParams& params) { if (params.kem() != google::crypto::tink::HpkeKem::DHKEM_X25519_HKDF_SHA256) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("No test parameters for specified KEM:", params.kem())); } if (params.kdf() != google::crypto::tink::HpkeKdf::HKDF_SHA256) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("No test parameters for specified KDF:", params.kdf())); } switch (params.aead()) { case google::crypto::tink::HpkeAead::AES_128_GCM: return HpkeTestParams(kTestX25519HkdfSha256Aes128Gcm); case google::crypto::tink::HpkeAead::AES_256_GCM: return HpkeTestParams(kTestX25519HkdfSha256Aes256Gcm); case google::crypto::tink::HpkeAead::CHACHA20_POLY1305: return HpkeTestParams(kTestX25519HkdfSha256ChaCha20Poly1305); default: return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("No test parameters for specified AEAD:", params.aead())); } } util::StatusOr CreateHpkeTestParams(const HpkeParams& params) { if (params.kem != HpkeKem::kX25519HkdfSha256) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("No test parameters for specified KEM:", params.kem)); } if (params.kdf != HpkeKdf::kHkdfSha256) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("No test parameters for specified KDF:", params.kdf)); } switch (params.aead) { case HpkeAead::kAes128Gcm: return HpkeTestParams(kTestX25519HkdfSha256Aes128Gcm); case HpkeAead::kAes256Gcm: return HpkeTestParams(kTestX25519HkdfSha256Aes256Gcm); case HpkeAead::kChaCha20Poly1305: return HpkeTestParams(kTestX25519HkdfSha256ChaCha20Poly1305); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("No test parameters for specified AEAD:", params.aead)); } } google::crypto::tink::HpkeParams CreateHpkeParams( const google::crypto::tink::HpkeKem& kem, const google::crypto::tink::HpkeKdf& kdf, const google::crypto::tink::HpkeAead& aead) { google::crypto::tink::HpkeParams params; params.set_kem(kem); params.set_kdf(kdf); params.set_aead(aead); return params; } google::crypto::tink::HpkePublicKey CreateHpkePublicKey( const google::crypto::tink::HpkeParams& params, const std::string& raw_key_bytes) { google::crypto::tink::HpkePublicKey key_proto; key_proto.set_version(0); key_proto.set_public_key(raw_key_bytes); *key_proto.mutable_params() = params; return key_proto; } google::crypto::tink::HpkePrivateKey CreateHpkePrivateKey( const google::crypto::tink::HpkeParams& params, const std::string& raw_key_bytes) { google::crypto::tink::HpkePrivateKey private_key_proto; private_key_proto.set_version(0); private_key_proto.set_private_key(raw_key_bytes); google::crypto::tink::HpkePublicKey* public_key_proto = private_key_proto.mutable_public_key(); *public_key_proto->mutable_params() = params; return private_key_proto; } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_test_util.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_INTERNAL_HPKE_TEST_UTIL_H_ #define TINK_HYBRID_INTERNAL_HPKE_TEST_UTIL_H_ #include #include #include "absl/strings/escaping.h" #include "absl/strings/string_view.h" #include "tink/hybrid/internal/hpke_util.h" #include "tink/util/statusor.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace internal { struct HpkeTestParams { std::string recipient_public_key; // pkRm std::string seed_for_testing; // skEm std::string application_info; // info std::string plaintext; // pt std::string associated_data; // aad std::string ciphertext; // ct std::string recipient_private_key; // skRm std::string encapsulated_key; // enc std::vector exported_contexts; std::vector exported_values; explicit HpkeTestParams(const absl::string_view* test_vector) : recipient_public_key(absl::HexStringToBytes(test_vector[0])), seed_for_testing(absl::HexStringToBytes(test_vector[1])), application_info(absl::HexStringToBytes(test_vector[2])), plaintext(absl::HexStringToBytes(test_vector[3])), associated_data(absl::HexStringToBytes(test_vector[4])), ciphertext(absl::HexStringToBytes(test_vector[5])), recipient_private_key(absl::HexStringToBytes(test_vector[6])), encapsulated_key(absl::HexStringToBytes(test_vector[7])), exported_contexts({absl::HexStringToBytes(test_vector[8]), absl::HexStringToBytes(test_vector[9]), absl::HexStringToBytes(test_vector[10])}), exported_values({absl::HexStringToBytes(test_vector[11]), absl::HexStringToBytes(test_vector[12]), absl::HexStringToBytes(test_vector[13])}) {} }; // Returns an HpkeTestParams struct for the following HPKE parameters: // DHKEM(X25519, HKDF-SHA256), HKDF-SHA256, AES-128-GCM. HpkeTestParams DefaultHpkeTestParams(); // Creates an HpkeTestParams struct for the specified HpkeParams protobuf. util::StatusOr CreateHpkeTestParams( const google::crypto::tink::HpkeParams& params); // Creates an HpkeTestParams struct for the specified HpkeParams struct. util::StatusOr CreateHpkeTestParams( const HpkeParams& params); // Creates an HpkeParams protobuf from `kem`, `kdf`, and `aead`. google::crypto::tink::HpkeParams CreateHpkeParams( const google::crypto::tink::HpkeKem& kem, const google::crypto::tink::HpkeKdf& kdf, const google::crypto::tink::HpkeAead& aead); // Creates an HpkePublicKey proto from the specified HpkeParams protobuf and // the `raw_key_bytes`. google::crypto::tink::HpkePublicKey CreateHpkePublicKey( const google::crypto::tink::HpkeParams& params, const std::string& raw_key_bytes); // Creates an HpkePrivateKey proto from the specified HpkeParams protobuf and // the `raw_key_bytes`. Note that the key material for the embedded // HpkePublicKey `public_key` field will be empty. google::crypto::tink::HpkePrivateKey CreateHpkePrivateKey( const google::crypto::tink::HpkeParams& params, const std::string& raw_key_bytes); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_HYBRID_INTERNAL_HPKE_TEST_UTIL_H_ ================================================ FILE: cc/hybrid/internal/hpke_util.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_util.h" #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/internal/ec_util.h" #include "tink/subtle/common_enums.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace internal { namespace { util::StatusOr HpkeKemProtoToEnum(google::crypto::tink::HpkeKem kem) { switch (kem) { case google::crypto::tink::HpkeKem::DHKEM_X25519_HKDF_SHA256: return HpkeKem::kX25519HkdfSha256; default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Unable to convert unsupported HPKE KEM: ", kem)); } } util::StatusOr HpkeKdfProtoToEnum(google::crypto::tink::HpkeKdf kdf) { switch (kdf) { case google::crypto::tink::HpkeKdf::HKDF_SHA256: return HpkeKdf::kHkdfSha256; default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Unable to convert unsupported HPKE KDF: ", kdf)); } } util::StatusOr HpkeAeadProtoToEnum( google::crypto::tink::HpkeAead aead) { switch (aead) { case google::crypto::tink::HpkeAead::AES_128_GCM: return HpkeAead::kAes128Gcm; case google::crypto::tink::HpkeAead::AES_256_GCM: return HpkeAead::kAes256Gcm; case google::crypto::tink::HpkeAead::CHACHA20_POLY1305: return HpkeAead::kChaCha20Poly1305; default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Unable to convert unsupported HPKE AEAD: ", aead)); } } } // namespace util::StatusOr HpkeParamsProtoToStruct( google::crypto::tink::HpkeParams params) { util::StatusOr kem = HpkeKemProtoToEnum(params.kem()); if (!kem.ok()) return kem.status(); util::StatusOr kdf = HpkeKdfProtoToEnum(params.kdf()); if (!kdf.ok()) return kdf.status(); util::StatusOr aead = HpkeAeadProtoToEnum(params.aead()); if (!aead.ok()) return aead.status(); return HpkeParams{*kem, *kdf, *aead}; } util::StatusOr HpkeEncapsulatedKeyLength( google::crypto::tink::HpkeKem kem) { switch (kem) { case google::crypto::tink::HpkeKem::DHKEM_X25519_HKDF_SHA256: return internal::EcPointEncodingSizeInBytes( subtle::EllipticCurveType::CURVE25519, subtle::EcPointFormat::UNCOMPRESSED); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Unable to determine KEM-encoding length for ", kem)); } } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_util.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_INTERNAL_HPKE_UTIL_H_ #define TINK_HYBRID_INTERNAL_HPKE_UTIL_H_ #include #include "tink/util/statusor.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace internal { // Values from https://www.rfc-editor.org/rfc/rfc9180.html#section-7.1. enum class HpkeKem { kUnknownKem = 0x0, kX25519HkdfSha256 = 0x20, }; // Values from https://www.rfc-editor.org/rfc/rfc9180.html#section-7.2. enum class HpkeKdf { kUnknownKdf = 0x0, kHkdfSha256 = 0x1, }; // Values from https://www.rfc-editor.org/rfc/rfc9180.html#section-7.3. enum class HpkeAead { kUnknownAead = 0x0, kAes128Gcm = 0x1, kAes256Gcm = 0x2, kChaCha20Poly1305 = 0x3, }; struct HpkeParams { HpkeKem kem; HpkeKdf kdf; HpkeAead aead; }; // Converts a google::crypto::tink::HpkeParams proto to an HpkeParams struct. util::StatusOr HpkeParamsProtoToStruct( google::crypto::tink::HpkeParams params); // Returns the encapsulated key length (in bytes) for the specified `kem`. util::StatusOr HpkeEncapsulatedKeyLength( google::crypto::tink::HpkeKem kem); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_HYBRID_INTERNAL_HPKE_UTIL_H_ ================================================ FILE: cc/hybrid/internal/hpke_util_boringssl.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_util_boringssl.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "openssl/base.h" #include "openssl/hpke.h" #include "tink/hybrid/internal/hpke_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace internal { util::StatusOr KemParam(const HpkeParams& params) { switch (params.kem) { case HpkeKem::kX25519HkdfSha256: return EVP_hpke_x25519_hkdf_sha256(); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Unsupported HPKE KEM algorithm: ", params.kem)); } } util::StatusOr KemParam( const google::crypto::tink::HpkeKem& kem) { switch (kem) { case google::crypto::tink::HpkeKem::DHKEM_X25519_HKDF_SHA256: return EVP_hpke_x25519_hkdf_sha256(); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Unsupported HPKE KEM algorithm: ", kem)); } } util::StatusOr KemParam( const google::crypto::tink::HpkeParams& params) { return KemParam(params.kem()); } util::StatusOr KdfParam(const HpkeParams& params) { switch (params.kdf) { case HpkeKdf::kHkdfSha256: return EVP_hpke_hkdf_sha256(); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Unsupported HPKE KDF algorithm: ", params.kdf)); } } util::StatusOr KdfParam( const google::crypto::tink::HpkeParams& params) { switch (params.kdf()) { case google::crypto::tink::HpkeKdf::HKDF_SHA256: return EVP_hpke_hkdf_sha256(); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Unsupported HPKE KDF algorithm: ", params.kdf())); } } util::StatusOr AeadParam(const HpkeParams& params) { switch (params.aead) { case HpkeAead::kAes128Gcm: return EVP_hpke_aes_128_gcm(); case HpkeAead::kAes256Gcm: return EVP_hpke_aes_256_gcm(); case HpkeAead::kChaCha20Poly1305: return EVP_hpke_chacha20_poly1305(); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Unsupported HPKE AEAD algorithm: ", params.aead)); } } util::StatusOr AeadParam( const google::crypto::tink::HpkeParams& params) { switch (params.aead()) { case google::crypto::tink::HpkeAead::AES_128_GCM: return EVP_hpke_aes_128_gcm(); case google::crypto::tink::HpkeAead::AES_256_GCM: return EVP_hpke_aes_256_gcm(); case google::crypto::tink::HpkeAead::CHACHA20_POLY1305: return EVP_hpke_chacha20_poly1305(); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Unsupported HPKE AEAD algorithm: ", params.aead())); } } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_util_boringssl.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_INTERNAL_HPKE_UTIL_BORINGSSL_H_ #define TINK_HYBRID_INTERNAL_HPKE_UTIL_BORINGSSL_H_ #include "openssl/hpke.h" #include "tink/hybrid/internal/hpke_util.h" #include "tink/util/statusor.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace internal { util::StatusOr KemParam( const google::crypto::tink::HpkeKem& kem); util::StatusOr KemParam(const HpkeParams& params); util::StatusOr KemParam( const google::crypto::tink::HpkeParams& params); util::StatusOr KdfParam(const HpkeParams& params); util::StatusOr KdfParam( const google::crypto::tink::HpkeParams& params); util::StatusOr AeadParam(const HpkeParams& params); util::StatusOr AeadParam( const google::crypto::tink::HpkeParams& params); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_HYBRID_INTERNAL_HPKE_UTIL_BORINGSSL_H_ ================================================ FILE: cc/hybrid/internal/hpke_util_boringssl_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_util_boringssl.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "openssl/base.h" #include "openssl/hpke.h" #include "tink/hybrid/internal/hpke_test_util.h" #include "tink/hybrid/internal/hpke_util.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::testing::Eq; using ::testing::Not; TEST(HpkeUtilBoringSslTest, ValidParamsFromProto) { google::crypto::tink::HpkeParams params = CreateHpkeParams(google::crypto::tink::HpkeKem::DHKEM_X25519_HKDF_SHA256, google::crypto::tink::HpkeKdf::HKDF_SHA256, google::crypto::tink::HpkeAead::AES_256_GCM); util::StatusOr kem_from_enum = KemParam(google::crypto::tink::HpkeKem::DHKEM_X25519_HKDF_SHA256); ASSERT_THAT(kem_from_enum, IsOk()); EXPECT_THAT(EVP_HPKE_KEM_id(*kem_from_enum), Eq(EVP_HPKE_DHKEM_X25519_HKDF_SHA256)); util::StatusOr kem_from_proto = KemParam(params); ASSERT_THAT(kem_from_proto, IsOk()); EXPECT_THAT(EVP_HPKE_KEM_id(*kem_from_proto), Eq(EVP_HPKE_DHKEM_X25519_HKDF_SHA256)); util::StatusOr kdf = KdfParam(params); ASSERT_THAT(kdf, IsOk()); EXPECT_THAT(EVP_HPKE_KDF_id(*kdf), Eq(EVP_HPKE_HKDF_SHA256)); util::StatusOr aead = AeadParam(params); ASSERT_THAT(aead, IsOk()); EXPECT_THAT(EVP_HPKE_AEAD_id(*aead), Eq(EVP_HPKE_AES_256_GCM)); } TEST(HpkeUtilBoringSslTest, ValidParamsFromStruct) { HpkeParams params = {HpkeKem::kX25519HkdfSha256, HpkeKdf::kHkdfSha256, HpkeAead::kAes256Gcm}; util::StatusOr kem_from_proto = KemParam(params); ASSERT_THAT(kem_from_proto, IsOk()); EXPECT_THAT(EVP_HPKE_KEM_id(*kem_from_proto), Eq(EVP_HPKE_DHKEM_X25519_HKDF_SHA256)); util::StatusOr kdf = KdfParam(params); ASSERT_THAT(kdf, IsOk()); EXPECT_THAT(EVP_HPKE_KDF_id(*kdf), Eq(EVP_HPKE_HKDF_SHA256)); util::StatusOr aead = AeadParam(params); ASSERT_THAT(aead, IsOk()); EXPECT_THAT(EVP_HPKE_AEAD_id(*aead), Eq(EVP_HPKE_AES_256_GCM)); } TEST(HpkeUtilBoringSslTest, UnknownKemParamFromProto) { google::crypto::tink::HpkeParams params = CreateHpkeParams(google::crypto::tink::HpkeKem::KEM_UNKNOWN, google::crypto::tink::HpkeKdf::HKDF_SHA256, google::crypto::tink::HpkeAead::AES_256_GCM); EXPECT_THAT(KemParam(params), Not(IsOk())); EXPECT_THAT(KdfParam(params), IsOk()); EXPECT_THAT(AeadParam(params), IsOk()); } TEST(HpkeUtilBoringSslTest, UnknownKemParamFromStruct) { HpkeParams params = {HpkeKem::kUnknownKem, HpkeKdf::kHkdfSha256, HpkeAead::kAes256Gcm}; EXPECT_THAT(KemParam(params), Not(IsOk())); EXPECT_THAT(KdfParam(params), IsOk()); EXPECT_THAT(AeadParam(params), IsOk()); } TEST(HpkeUtilBoringSslTest, UnknownKdfParamFromProto) { google::crypto::tink::HpkeParams params = CreateHpkeParams(google::crypto::tink::HpkeKem::DHKEM_X25519_HKDF_SHA256, google::crypto::tink::HpkeKdf::KDF_UNKNOWN, google::crypto::tink::HpkeAead::AES_256_GCM); EXPECT_THAT(KemParam(params), IsOk()); EXPECT_THAT(KdfParam(params), Not(IsOk())); EXPECT_THAT(AeadParam(params), IsOk()); } TEST(HpkeUtilBoringSslTest, UnknownKdfParamFromStruct) { HpkeParams params = {HpkeKem::kX25519HkdfSha256, HpkeKdf::kUnknownKdf, HpkeAead::kAes256Gcm}; EXPECT_THAT(KemParam(params), IsOk()); EXPECT_THAT(KdfParam(params), Not(IsOk())); EXPECT_THAT(AeadParam(params), IsOk()); } TEST(HpkeUtilBoringSslTest, UnknownAeadParamFromProto) { google::crypto::tink::HpkeParams params = CreateHpkeParams(google::crypto::tink::HpkeKem::DHKEM_X25519_HKDF_SHA256, google::crypto::tink::HpkeKdf::HKDF_SHA256, google::crypto::tink::HpkeAead::AEAD_UNKNOWN); EXPECT_THAT(KemParam(params), IsOk()); EXPECT_THAT(KdfParam(params), IsOk()); EXPECT_THAT(AeadParam(params), Not(IsOk())); } TEST(HpkeUtilBoringSslTest, UnknownAeadParamFromStruct) { HpkeParams params = {HpkeKem::kX25519HkdfSha256, HpkeKdf::kHkdfSha256, HpkeAead::kUnknownAead}; EXPECT_THAT(KemParam(params), IsOk()); EXPECT_THAT(KdfParam(params), IsOk()); EXPECT_THAT(AeadParam(params), Not(IsOk())); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/hpke_util_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/hpke_util.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/hybrid/internal/hpke_test_util.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/hpke.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::Values; struct HpkeParamsConversionTestCase { google::crypto::tink::HpkeParams input; HpkeParams expected; }; using HpkeParamsConversionTest = testing::TestWithParam; INSTANTIATE_TEST_SUITE_P( HpkeParamsConversionTestSuite, HpkeParamsConversionTest, Values( HpkeParamsConversionTestCase{ CreateHpkeParams(google::crypto::tink::DHKEM_X25519_HKDF_SHA256, google::crypto::tink::HKDF_SHA256, google::crypto::tink::AES_128_GCM), HpkeParams{HpkeKem::kX25519HkdfSha256, HpkeKdf::kHkdfSha256, HpkeAead::kAes128Gcm}}, HpkeParamsConversionTestCase{ CreateHpkeParams(google::crypto::tink::DHKEM_X25519_HKDF_SHA256, google::crypto::tink::HKDF_SHA256, google::crypto::tink::AES_256_GCM), HpkeParams{HpkeKem::kX25519HkdfSha256, HpkeKdf::kHkdfSha256, HpkeAead::kAes256Gcm}}, HpkeParamsConversionTestCase{ CreateHpkeParams(google::crypto::tink::DHKEM_X25519_HKDF_SHA256, google::crypto::tink::HKDF_SHA256, google::crypto::tink::CHACHA20_POLY1305), HpkeParams{HpkeKem::kX25519HkdfSha256, HpkeKdf::kHkdfSha256, HpkeAead::kChaCha20Poly1305}})); TEST_P(HpkeParamsConversionTest, HpkeParamsProtoToStruct) { HpkeParamsConversionTestCase test_case = GetParam(); util::StatusOr params = HpkeParamsProtoToStruct(test_case.input); ASSERT_THAT(params, IsOk()); EXPECT_THAT(params->kem, Eq(test_case.expected.kem)); EXPECT_THAT(params->kdf, Eq(test_case.expected.kdf)); EXPECT_THAT(params->aead, Eq(test_case.expected.aead)); } using HpkeBadParamsTest = testing::TestWithParam; INSTANTIATE_TEST_SUITE_P( HpkeBadParamsTestSuite, HpkeBadParamsTest, Values(CreateHpkeParams(google::crypto::tink::KEM_UNKNOWN, google::crypto::tink::HKDF_SHA256, google::crypto::tink::AES_128_GCM), CreateHpkeParams(google::crypto::tink::DHKEM_X25519_HKDF_SHA256, google::crypto::tink::KDF_UNKNOWN, google::crypto::tink::AES_256_GCM), CreateHpkeParams(google::crypto::tink::DHKEM_X25519_HKDF_SHA256, google::crypto::tink::HKDF_SHA256, google::crypto::tink::AEAD_UNKNOWN))); TEST_P(HpkeBadParamsTest, HpkeParamsProtoToStruct) { google::crypto::tink::HpkeParams params = GetParam(); EXPECT_THAT(HpkeParamsProtoToStruct(params).status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HpkeKemEncodingSizeTest, HpkeEncapsulatedKeyLength) { // Encapsulated key length should match 'Nenc' column from // https://www.rfc-editor.org/rfc/rfc9180.html#section-7.1. EXPECT_THAT( HpkeEncapsulatedKeyLength(google::crypto::tink::DHKEM_X25519_HKDF_SHA256), IsOkAndHolds(32)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/key_gen_config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/key_gen_config_v0.h" #include "absl/memory/memory.h" #include "tink/hybrid/ecies_aead_hkdf_private_key_manager.h" #include "tink/hybrid/ecies_aead_hkdf_public_key_manager.h" #ifdef OPENSSL_IS_BORINGSSL #include "tink/hybrid/internal/hpke_private_key_manager.h" #include "tink/hybrid/internal/hpke_public_key_manager.h" #endif #include "tink/internal/key_gen_configuration_impl.h" #include "tink/key_gen_configuration.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { util::Status AddHybridKeyGenV0(KeyGenConfiguration& config) { #ifdef OPENSSL_IS_BORINGSSL util::Status status = KeyGenConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config); if (!status.ok()) { return status; } #endif return KeyGenConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/key_gen_config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_INTERNAL_KEY_GEN_CONFIG_V0_H_ #define TINK_HYBRID_INTERNAL_KEY_GEN_CONFIG_V0_H_ #include "tink/key_gen_configuration.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { // Add recommended Hybrid Encryption key managers to `config`, used to generate // keys. util::Status AddHybridKeyGenV0(KeyGenConfiguration& config); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_HYBRID_INTERNAL_KEY_GEN_CONFIG_V0_H_ ================================================ FILE: cc/hybrid/internal/test_hpke_context_boringssl.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/internal/test_hpke_context_boringssl.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "openssl/base.h" #include "openssl/hpke.h" #include "tink/hybrid/internal/hpke_context_boringssl.h" #include "tink/hybrid/internal/hpke_util.h" #include "tink/hybrid/internal/hpke_util_boringssl.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { util::StatusOr TestHpkeContextBoringSsl::SetupSender( const HpkeParams ¶ms, absl::string_view recipient_public_key, absl::string_view context_info, absl::string_view seed_for_testing) { util::StatusOr kem = KemParam(params); if (!kem.ok()) { return kem.status(); } util::StatusOr kdf = KdfParam(params); if (!kdf.ok()) { return kdf.status(); } util::StatusOr aead = AeadParam(params); if (!aead.ok()) { return aead.status(); } uint8_t enc[EVP_HPKE_MAX_ENC_LENGTH]; size_t enc_len; SslUniquePtr context(EVP_HPKE_CTX_new()); if (!EVP_HPKE_CTX_setup_sender_with_seed_for_testing( context.get(), enc, &enc_len, sizeof(enc), *kem, *kdf, *aead, reinterpret_cast(recipient_public_key.data()), recipient_public_key.size(), reinterpret_cast(context_info.data()), context_info.size(), reinterpret_cast(seed_for_testing.data()), seed_for_testing.size())) { return util::Status(absl::StatusCode::kUnknown, "Unable to set up HPKE sender context."); } SenderHpkeContextBoringSsl tuple; tuple.context = absl::WrapUnique(new TestHpkeContextBoringSsl(std::move(context))); tuple.encapsulated_key = std::string(reinterpret_cast(enc), enc_len); return std::move(tuple); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/internal/test_hpke_context_boringssl.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_INTERNAL_TEST_HPKE_CONTEXT_BORINGSSL_H_ #define TINK_HYBRID_INTERNAL_TEST_HPKE_CONTEXT_BORINGSSL_H_ #include #include #include #include #include "absl/strings/string_view.h" #include "openssl/base.h" #include "openssl/hpke.h" #include "tink/hybrid/internal/hpke_context_boringssl.h" #include "tink/hybrid/internal/hpke_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { class TestHpkeContextBoringSsl : public HpkeContextBoringSsl { public: // Sets up a test HPKE sender context. Returns an error if initialization // fails. Otherwise, returns a unique pointer to the sender context. // // `params`: HPKE parameters (KEM, KDF, and AEAD). // `recipient_public_key`: KEM-encoding of recipient public key. // `info`: Application-specific context for key derivation. // `seed_for_testing`: Seed used to match test vector values. static crypto::tink::util::StatusOr SetupSender( const HpkeParams& params, absl::string_view recipient_public_key, absl::string_view info, absl::string_view seed_for_testing); private: explicit TestHpkeContextBoringSsl(SslUniquePtr context) : HpkeContextBoringSsl(std::move(context)) {} }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_HYBRID_INTERNAL_TEST_HPKE_CONTEXT_BORINGSSL_H_ ================================================ FILE: cc/hybrid/key_gen_config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/hybrid/key_gen_config_v0.h" #include "absl/log/check.h" #include "tink/hybrid/internal/key_gen_config_v0.h" #include "tink/key_gen_configuration.h" namespace crypto { namespace tink { const KeyGenConfiguration& KeyGenConfigHybridV0() { static const KeyGenConfiguration* instance = [] { static KeyGenConfiguration* config = new KeyGenConfiguration(); CHECK_OK(internal::AddHybridKeyGenV0(*config)); return config; }(); return *instance; } } // namespace tink } // namespace crypto ================================================ FILE: cc/hybrid/key_gen_config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_KEY_GEN_CONFIG_V0_H_ #define TINK_HYBRID_KEY_GEN_CONFIG_V0_H_ #include "tink/key_gen_configuration.h" namespace crypto { namespace tink { // KeyGenConfiguration used to generate Hybrid Encryption keys with recommended // key managers. const KeyGenConfiguration& KeyGenConfigHybridV0(); } // namespace tink } // namespace crypto #endif // TINK_HYBRID_KEY_GEN_CONFIG_V0_H_ ================================================ FILE: cc/hybrid/subtle/BUILD.bazel ================================================ licenses(["notice"]) ================================================ FILE: cc/hybrid/subtle/CMakeLists.txt ================================================ ================================================ FILE: cc/hybrid_config.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_CONFIG_H_ #define TINK_HYBRID_CONFIG_H_ #include "tink/hybrid/hybrid_config.h" // IWYU pragma: export #endif // TINK_HYBRID_CONFIG_H_ ================================================ FILE: cc/hybrid_decrypt.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_DECRYPT_H_ #define TINK_HYBRID_DECRYPT_H_ #include #include "absl/strings/string_view.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // The interface for hybrid decryption. // // Implementations of this interface are secure against adaptive // chosen ciphertext attacks. In addition to 'plaintext' the // encryption takes an extra parameter 'context_info', which usually // is public data implicit from the context, but should be bound to // the resulting ciphertext: upon decryption the ciphertext allows for // checking the integrity of 'context_info' (but there are no // guarantees wrt. to secrecy or authenticity of 'context_info'). // // WARNING: hybrid encryption does not provide authenticity, that is the // recipient of an encrypted message does not know the identity of the sender. // Similar to general public-key encryption schemes the security goal of // hybrid encryption is to provide privacy only. In other words, hybrid // encryption is secure if and only if the recipient can accept anonymous // messages or can rely on other mechanisms to authenticate the sender. // // 'context_info' can be empty or null, but to ensure the correct // decryption of the ciphertext the same value must be provided // as was used during encryption operation (cf. HybridEncrypt-interface). // // A concrete instantiation of this interface can implement the // binding of 'context_info' to the ciphertext in various ways, for // example: // // - use 'context_info' as "associated data"-input for the employed // AEAD symmetric encryption (cf. https://tools.ietf.org/html/rfc5116). // - use 'context_info' as "CtxInfo"-input for HKDF (if the implementation uses // HKDF as key derivation function, cf. https://tools.ietf.org/html/rfc5869). class HybridDecrypt { public: // Decrypts 'ciphertext' verifying the integrity of 'context_info'. virtual crypto::tink::util::StatusOr Decrypt( absl::string_view ciphertext, absl::string_view context_info) const = 0; virtual ~HybridDecrypt() = default; }; } // namespace tink } // namespace crypto #endif // TINK_HYBRID_DECRYPT_H_ ================================================ FILE: cc/hybrid_decrypt_factory.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_DECRYPT_FACTORY_H_ #define TINK_HYBRID_DECRYPT_FACTORY_H_ #include "tink/hybrid/hybrid_decrypt_factory.h" // IWYU pragma: export #endif // TINK_HYBRID_DECRYPT_FACTORY_H_ ================================================ FILE: cc/hybrid_encrypt.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_ENCRYPT_H_ #define TINK_HYBRID_ENCRYPT_H_ #include #include "absl/strings/string_view.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // The interface for hybrid encryption. // // Implementations of this interface are secure against adaptive // chosen ciphertext attacks. In addition to 'plaintext' the // encryption takes an extra parameter 'context_info', which usually // is public data implicit from the context, but should be bound to // the resulting ciphertext: upon decryption the ciphertext allows for // checking the integrity of 'context_info' (but there are no // guarantees wrt. to secrecy or authenticity of 'context_info'). // // WARNING: hybrid encryption does not provide authenticity, that is the // recipient of an encrypted message does not know the identity of the sender. // Similar to general public-key encryption schemes the security goal of // hybrid encryption is to provide privacy only. In other words, hybrid // encryption is secure if and only if the recipient can accept anonymous // messages or can rely on other mechanisms to authenticate the sender. // // 'context_info' can be empty or null, but to ensure the correct // decryption of the resulting ciphertext the same value must be // provided for decryption operation (cf. HybridDecrypt-interface). // // A concrete instantiation of this interface can implement the // binding of 'context_info' to the ciphertext in various ways, for // example: // // - use 'context_info' as "associated data"-input for the employed // AEAD symmetric encryption (cf. https://tools.ietf.org/html/rfc5116). // - use 'context_info' as "CtxInfo"-input for HKDF (if the implementation uses // HKDF as key derivation function, cf. https://tools.ietf.org/html/rfc5869). class HybridEncrypt { public: // Encrypts 'plaintext' binding 'context_info' to the resulting ciphertext. virtual crypto::tink::util::StatusOr Encrypt( absl::string_view plaintext, absl::string_view context_info) const = 0; virtual ~HybridEncrypt() = default; }; } // namespace tink } // namespace crypto #endif // TINK_HYBRID_ENCRYPT_H_ ================================================ FILE: cc/hybrid_encrypt_factory.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_ENCRYPT_FACTORY_H_ #define TINK_HYBRID_ENCRYPT_FACTORY_H_ #include "tink/hybrid/hybrid_encrypt_factory.h" // IWYU pragma: export #endif // TINK_HYBRID_ENCRYPT_FACTORY_H_ ================================================ FILE: cc/hybrid_key_templates.h ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_HYBRID_KEY_TEMPLATES_H_ #define TINK_HYBRID_KEY_TEMPLATES_H_ #include "tink/hybrid/hybrid_key_templates.h" // IWYU pragma: export #endif // TINK_HYBRID_KEY_TEMPLATES_H_ ================================================ FILE: cc/input_stream.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INPUT_STREAM_H_ #define TINK_INPUT_STREAM_H_ #include #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Abstract interface similar to an input stream, and to // Protocol Buffers' google::protobuf::io::ZeroCopyInputStream. class InputStream { public: InputStream() = default; virtual ~InputStream() = default; // Obtains a chunk of data from the stream. // // Preconditions: // * "data" is not NULL. // // Postconditions: // * If the returned status is not OK, there is no more data to return // (status equal to OUT_OF_RANGE) or an error occurred // (status not in {OK, OUT_OF_RANGE}. All errors are permanent. // * Otherwise, the returned value is the number of bytes read and "data" // points to a buffer containing these bytes. // * Ownership of this buffer remains with the stream, and the buffer // remains valid only until some other non-const method of the stream // is called or the stream is destroyed. // * It is legal for the returned buffer to have zero size, as long as // repeatedly calling Next() eventually yields a buffer with non-zero // size or a non-OK status. virtual crypto::tink::util::StatusOr Next(const void** data) = 0; // Backs up a number of bytes, so that the next call to Next() returns // data again that was already returned by the last call to Next(). // This is useful when writing procedures that are only supposed to read // up to a certain point in the input, then return. If Next() returns a // buffer that goes beyond what you wanted to read, you can use BackUp() // to return to the point where you intended to finish. // // Preconditions: // * The last call to Next() must have returned status OK. // If there was no Next()-call yet, or the last one failed, // BackUp()-call is ignored. // * count must be less than or equal to the size of the last buffer // returned by Next(). Non-positive count is ignored (no action on this // stream), and count larger than the size of the last buffer is treated // as equal to the size of the last buffer. // // Postconditions: // * The last "count" bytes of the last buffer returned by Next() will be // pushed back into the stream. Subsequent calls to Next() will return // the same data again before producing new data. // * Repeated calls to BackUp() accumulate: // BackUp(a); // Backup(b); // is equivalent to // Backup(c); // with c = max(0, a) + max(0, b). // * The actual result of BackUp()-call can be verified via Position(). virtual void BackUp(int count) = 0; // Returns the current byte position in the stream. // // Preconditions: // * The last call to Next() ended with status in {OK, OUT_OF_RANGE}. // // Postconditions: // * Position equal to i means that the next call to Next() will // return a data buffer starting at (i+1)st byte of the stream (if any). // * If the last call to Next() reached end of stream (status OUT_OF_RANGE), // then returned value is the total number of bytes in the stream. // * If the last call to Next() ended with a failure, -1 is returned; virtual int64_t Position() const = 0; }; } // namespace tink } // namespace crypto #endif // TINK_INPUT_STREAM_H_ ================================================ FILE: cc/insecure_secret_key_access.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INSECURE_SECRET_KEY_ACCESS_H_ #define TINK_INSECURE_SECRET_KEY_ACCESS_H_ #include "tink/secret_key_access_token.h" namespace crypto { namespace tink { class InsecureSecretKeyAccess { public: // Returns a `SecretKeyAccessToken`. // // The token can be used to access secret key material. Within Google, access // to this function is restricted by the build system. Outside of Google, // users can search their codebase for "InsecureSecretKeyAccess" to find // instances where it is used. static SecretKeyAccessToken Get() { return SecretKeyAccessToken(); } private: InsecureSecretKeyAccess() = default; }; } // namespace tink } // namespace crypto #endif // TINK_INSECURE_SECRET_KEY_ACCESS_H_ ================================================ FILE: cc/integration/awskms/.bazelrc ================================================ # Minumum C++ version. Override it building this project with # `bazel build --cxxopt='-std=c++' --host_cxxopt='c++' ...` # (Both -std and --host_cxxopt must be set to force the desired version.) build --cxxopt='-std=c++14' --host_cxxopt='-std=c++14' ================================================ FILE: cc/integration/awskms/.bazelversion ================================================ 6.0.0 ================================================ FILE: cc/integration/awskms/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "aws_kms_aead", srcs = ["aws_kms_aead.cc"], hdrs = ["aws_kms_aead.h"], include_prefix = "tink/integration/awskms", visibility = ["//visibility:public"], deps = [ "@aws_cpp_sdk//:aws_sdk_core", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@tink_cc//:aead", "@tink_cc//util:status", "@tink_cc//util:statusor", ], alwayslink = 1, ) cc_library( name = "aws_kms_client", srcs = ["aws_kms_client.cc"], hdrs = ["aws_kms_client.h"], include_prefix = "tink/integration/awskms", visibility = ["//visibility:public"], deps = [ ":aws_kms_aead", "@aws_cpp_sdk//:aws_sdk_core", "@com_google_absl//absl/base", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/synchronization", "@tink_cc//:kms_client", "@tink_cc//:kms_clients", "@tink_cc//util:status", "@tink_cc//util:statusor", ], alwayslink = 1, ) cc_test( name = "aws_kms_aead_integration_test", size = "small", srcs = ["aws_kms_aead_integration_test.cc"], data = ["//testdata/aws:credentials"], # This target requires valid credentials to interact with the AWS KMS. tags = ["manual"], deps = [ ":aws_kms_aead", ":aws_kms_client", "//tink/integration/awskms/internal:test_file_util", "@aws_cpp_sdk//:aws_sdk_core", "@bazel_tools//tools/cpp/runfiles", "@com_google_absl//absl/base", "@com_google_absl//absl/log:check", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", "@tink_cc//util:statusor", "@tink_cc//util:test_matchers", ], ) cc_test( name = "aws_kms_client_test", size = "small", srcs = ["aws_kms_client_test.cc"], data = ["//testdata/aws:credentials"], deps = [ ":aws_kms_client", "//tink/integration/awskms/internal:test_file_util", "@aws_cpp_sdk//:aws_sdk_core", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", "@tink_cc//util:status", "@tink_cc//util:statusor", "@tink_cc//util:test_matchers", "@tink_cc//util:test_util", ], ) ================================================ FILE: cc/integration/awskms/WORKSPACE ================================================ workspace(name = "tink_cc_awskms") local_repository( name = "tink_cc", path = "../../../cc", ) load("@tink_cc//:tink_cc_deps.bzl", "tink_cc_deps") tink_cc_deps() load("@tink_cc//:tink_cc_deps_init.bzl", "tink_cc_deps_init") tink_cc_deps_init() load("@tink_cc_awskms//:tink_cc_awskms_deps.bzl", "tink_cc_awskms_deps") tink_cc_awskms_deps() ================================================ FILE: cc/integration/awskms/aws_kms_aead.cc ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/integration/awskms/aws_kms_aead.h" #include "aws/core/auth/AWSCredentialsProvider.h" #include "aws/core/client/AWSClient.h" #include "aws/core/utils/Outcome.h" #include "aws/core/utils/memory/AWSMemory.h" #include "aws/kms/KMSClient.h" #include "aws/kms/KMSErrors.h" #include "aws/kms/model/DecryptRequest.h" #include "aws/kms/model/DecryptResult.h" #include "aws/kms/model/EncryptRequest.h" #include "aws/kms/model/EncryptResult.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/match.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace integration { namespace awskms { namespace { std::string AwsErrorToString(Aws::Client::AWSError err) { return absl::StrCat("AWS error code: ", err.GetErrorType(), ", ", err.GetExceptionName(), ": ", err.GetMessage()); } } // namespace util::StatusOr> AwsKmsAead::New( absl::string_view key_arn, std::shared_ptr aws_client) { if (key_arn.empty()) { return util::Status(absl::StatusCode::kInvalidArgument, "Key ARN cannot be empty."); } if (aws_client == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "AWS KMS client cannot be null."); } return {absl::WrapUnique(new AwsKmsAead(key_arn, aws_client))}; } util::StatusOr AwsKmsAead::Encrypt( absl::string_view plaintext, absl::string_view associated_data) const { Aws::KMS::Model::EncryptRequest req; req.SetKeyId(key_arn_.c_str()); Aws::Utils::ByteBuffer plaintext_buffer( reinterpret_cast(plaintext.data()), plaintext.length()); req.SetPlaintext(plaintext_buffer); if (!associated_data.empty()) { req.AddEncryptionContext("associatedData", absl::BytesToHexString(associated_data).c_str()); } auto outcome = aws_client_->Encrypt(req); if (!outcome.IsSuccess()) { auto& err = outcome.GetError(); return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("AWS KMS encryption failed with error: ", AwsErrorToString(err))); } auto& blob = outcome.GetResult().GetCiphertextBlob(); std::string ciphertext( reinterpret_cast(blob.GetUnderlyingData()), blob.GetLength()); return ciphertext; } util::StatusOr AwsKmsAead::Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const { Aws::KMS::Model::DecryptRequest req; req.SetKeyId(key_arn_.c_str()); Aws::Utils::ByteBuffer ciphertext_buffer( reinterpret_cast(ciphertext.data()), ciphertext.length()); req.SetCiphertextBlob(ciphertext_buffer); if (!associated_data.empty()) { req.AddEncryptionContext("associatedData", absl::BytesToHexString(associated_data).c_str()); } auto outcome = aws_client_->Decrypt(req); if (!outcome.IsSuccess()) { auto& err = outcome.GetError(); return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("AWS KMS decryption failed with error: ", AwsErrorToString(err))); } auto& buffer = outcome.GetResult().GetPlaintext(); std::string plaintext( reinterpret_cast(buffer.GetUnderlyingData()), buffer.GetLength()); return plaintext; } } // namespace awskms } // namespace integration } // namespace tink } // namespace crypto ================================================ FILE: cc/integration/awskms/aws_kms_aead.h ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTEGRATION_AWSKMS_AWS_KMS_AEAD_H_ #define TINK_INTEGRATION_AWSKMS_AWS_KMS_AEAD_H_ #include "aws/kms/KMSClient.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace integration { namespace awskms { // AwsKmsAead is an implementation of AEAD that forwards encryption/decryption // requests to a key managed by the AWS KMS (https://aws.amazon.com/kms). class AwsKmsAead : public Aead { public: // Move only. AwsKmsAead(AwsKmsAead&& other) = default; AwsKmsAead& operator=(AwsKmsAead&& other) = default; AwsKmsAead(const AwsKmsAead&) = delete; AwsKmsAead& operator=(const AwsKmsAead&) = delete; // Creates a new AwsKmsAead that is bound to the key specified in `key_arn`, // and that uses the given client when communicating with the KMS. static crypto::tink::util::StatusOr> New( absl::string_view key_arn, std::shared_ptr aws_client); crypto::tink::util::StatusOr Encrypt( absl::string_view plaintext, absl::string_view associated_data) const override; crypto::tink::util::StatusOr Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const override; private: AwsKmsAead(absl::string_view key_arn, std::shared_ptr aws_client) : key_arn_(key_arn), aws_client_(aws_client) {} std::string key_arn_; // The location of a crypto key in AWS KMS. std::shared_ptr aws_client_; }; } // namespace awskms } // namespace integration } // namespace tink } // namespace crypto #endif // TINK_INTEGRATION_AWSKMS_AWS_KMS_AEAD_H_ ================================================ FILE: cc/integration/awskms/aws_kms_aead_integration_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include "aws/core/Aws.h" #include "aws/core/auth/AWSCredentialsProvider.h" #include "aws/core/auth/AWSCredentialsProviderChain.h" #include "aws/core/client/ClientConfiguration.h" #include "aws/core/utils/crypto/Factories.h" #include "aws/core/utils/memory/AWSMemory.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/ascii.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/integration/awskms/aws_kms_aead.h" #include "tink/integration/awskms/aws_kms_client.h" #include "tink/integration/awskms/internal/test_file_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace integration { namespace awskms { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::testing::Not; constexpr absl::string_view kAwsKmsKeyUri = "aws-kms://arn:aws:kms:us-east-2:235739564943:key/" "3ee50705-5a82-4f5b-9753-05c4f473922f"; constexpr absl::string_view kAwsKmsKeyArn = "arn:aws:kms:us-east-2:235739564943:key/" "3ee50705-5a82-4f5b-9753-05c4f473922f"; constexpr absl::string_view kAwsKmsKeyAliasUri = "aws-kms://arn:aws:kms:us-east-2:235739564943:alias/" "unit-and-integration-testing"; TEST(AwsKmsAeadTest, EncryptDecrypt) { std::string credentials = internal::RunfilesPath("testdata/aws/credentials.ini"); util::StatusOr> client = AwsKmsClient::New(/*key_uri=*/"", credentials); ASSERT_THAT(client, IsOk()); util::StatusOr> aead = (*client)->GetAead(kAwsKmsKeyUri); ASSERT_THAT(aead, IsOk()); constexpr absl::string_view kPlaintext = "plaintext"; constexpr absl::string_view kAssociatedData = "aad"; util::StatusOr ciphertext = (*aead)->Encrypt(kPlaintext, kAssociatedData); ASSERT_THAT(ciphertext, IsOk()); EXPECT_THAT((*aead)->Decrypt(*ciphertext, kAssociatedData), IsOkAndHolds(kPlaintext)); } TEST(AwsKmsAeadTest, EncryptDecryptWithKeyAlias) { std::string credentials = internal::RunfilesPath("testdata/aws/credentials.ini"); util::StatusOr> client = AwsKmsClient::New(/*key_uri=*/"", credentials); ASSERT_THAT(client, IsOk()); util::StatusOr> aead = (*client)->GetAead(kAwsKmsKeyAliasUri); ASSERT_THAT(aead, IsOk()); constexpr absl::string_view kPlaintext = "plaintext"; constexpr absl::string_view kAssociatedData = "associatedData"; util::StatusOr ciphertext = (*aead)->Encrypt(kPlaintext, kAssociatedData); ASSERT_THAT(ciphertext, IsOk()); EXPECT_THAT((*aead)->Decrypt(*ciphertext, kAssociatedData), IsOkAndHolds(kPlaintext)); EXPECT_THAT((*aead)->Decrypt(*ciphertext, "invalidAssociatedData"), Not(IsOk())); } util::StatusOr ReadFile(const std::string& filename) { std::ifstream input_stream; input_stream.open(filename, std::ifstream::in); if (!input_stream.is_open()) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Error opening file ", filename)); } std::stringstream input; input << input_stream.rdbuf(); input_stream.close(); return input.str(); } util::StatusOr GetValue(absl::string_view name, absl::string_view line) { std::vector parts = absl::StrSplit(line, '='); if (parts.size() != 2 || absl::StripAsciiWhitespace(parts[0]) != name) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Expected line to have the format: ", name, " = value. Found: ", line)); } return std::string(absl::StripAsciiWhitespace(parts[1])); } TEST(AwsKmsAeadTest, AwsKmsAeadNewWorks) { Aws::SDKOptions options; Aws::InitAPI(options); // Read credentials and get secret access key. std::string credentials_path = internal::RunfilesPath("testdata/aws/credentials.ini"); util::StatusOr creds = ReadFile(credentials_path); ASSERT_THAT(creds, IsOk()); std::vector creds_lines = absl::StrSplit(*creds, '\n'); util::StatusOr key_id = GetValue("aws_access_key_id", creds_lines[1]); ASSERT_THAT(key_id, IsOk()); util::StatusOr secret_key = GetValue("aws_secret_access_key", creds_lines[2]); ASSERT_THAT(secret_key, IsOk()); // Create an Aws::KMS::KMSClient. Aws::Auth::AWSCredentials credentials = Aws::Auth::AWSCredentials(key_id->c_str(), secret_key->c_str()); Aws::Client::ClientConfiguration config; config.region = "us-east-2"; config.scheme = Aws::Http::Scheme::HTTPS; config.connectTimeoutMs = 30000; config.requestTimeoutMs = 60000; auto aws_client = Aws::MakeShared( "tink::integration::awskms", credentials, config); util::StatusOr> aead = AwsKmsAead::New(kAwsKmsKeyArn, aws_client); ASSERT_THAT(aead, IsOk()); constexpr absl::string_view kPlaintext = "plaintext"; constexpr absl::string_view kAssociatedData = "associatedData"; util::StatusOr ciphertext = (*aead)->Encrypt(kPlaintext, kAssociatedData); ASSERT_THAT(ciphertext, IsOk()); EXPECT_THAT((*aead)->Decrypt(*ciphertext, kAssociatedData), IsOkAndHolds(kPlaintext)); EXPECT_THAT((*aead)->Decrypt(*ciphertext, "invalidAssociatedData"), Not(IsOk())); } } // namespace } // namespace awskms } // namespace integration } // namespace tink } // namespace crypto ================================================ FILE: cc/integration/awskms/aws_kms_client.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/integration/awskms/aws_kms_client.h" #include #include #include #include "aws/core/Aws.h" #include "aws/core/auth/AWSCredentialsProvider.h" #include "aws/core/auth/AWSCredentialsProviderChain.h" #include "aws/core/client/ClientConfiguration.h" #include "aws/core/utils/crypto/Factories.h" #include "aws/core/utils/memory/AWSMemory.h" #include "aws/kms/KMSClient.h" #include "absl/base/call_once.h" #include "absl/status/status.h" #include "absl/strings/ascii.h" #include "absl/strings/escaping.h" #include "absl/strings/match.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" #include "tink/integration/awskms/aws_kms_aead.h" #include "tink/kms_client.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace integration { namespace awskms { namespace { constexpr absl::string_view kKeyUriPrefix = "aws-kms://"; constexpr char kTinkAwsKmsAllocationTag[] = "tink::integration::awskms"; // Returns AWS key ARN contained in `key_uri`. If `key_uri` does not refer to an // AWS key, returns an error. util::StatusOr GetKeyArn(absl::string_view key_uri) { if (!absl::StartsWithIgnoreCase(key_uri, kKeyUriPrefix)) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid key URI ", key_uri)); } return std::string(key_uri.substr(kKeyUriPrefix.length())); } // Returns ClientConfiguration with region set to the value extracted from // `key_arn`. // An AWS key ARN is of the form // arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab. util::StatusOr GetAwsClientConfig( absl::string_view key_arn) { std::vector key_arn_parts = absl::StrSplit(key_arn, ':'); if (key_arn_parts.size() < 6) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid key ARN ", key_arn)); } Aws::Client::ClientConfiguration config; // 4th part of key arn. config.region = key_arn_parts[3].c_str(); config.scheme = Aws::Http::Scheme::HTTPS; config.connectTimeoutMs = 30000; config.requestTimeoutMs = 60000; return config; } // Reads the specified file and returns the content as a string. util::StatusOr ReadFile(const std::string& filename) { std::ifstream input_stream; input_stream.open(filename, std::ifstream::in); if (!input_stream.is_open()) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Error opening file ", filename)); } std::stringstream input; input << input_stream.rdbuf(); input_stream.close(); return input.str(); } // Extracts a value of `name` from `line`, where `line` must be of the form: // name = value util::StatusOr GetValue(absl::string_view name, absl::string_view line) { std::vector parts = absl::StrSplit(line, '='); if (parts.size() != 2 || absl::StripAsciiWhitespace(parts[0]) != name) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Expected line to have the format: ", name, " = value. Found: ", line)); } return std::string(absl::StripAsciiWhitespace(parts[1])); } // Returns AWS credentials from the given `credential_path`. // // Credentials are retrieved as follows: // // If `credentials_path` is not empty the credentials in the given file are // returned. The file should have the following format: // // [default] // aws_access_key_id = your_access_key_id // aws_secret_access_key = your_secret_access_key // // If `credentials_path` is empty, the credentials are searched for in the // following order: // 1. In the file specified via environment variable // AWS_SHARED_CREDENTIALS_FILE // 2. In the file specified via environment variable AWS_PROFILE // 3. In the file ~/.aws/credentials // 4. In the file ~/.aws/config // 5. In values specified in environment variables AWS_ACCESS_KEY_ID, // AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN // // For more info on AWS credentials see: // https://docs.aws.amazon.com/sdk-for-cpp/v1/developer-guide/credentials.html // and documentation of Aws::Auth::EnvironmentAWSCredentialsProvider and // Aws::Auth::ProfileConfigFileAWSCredentialsProvider. util::StatusOr GetAwsCredentials( absl::string_view credentials_path) { if (credentials_path.empty()) { // Get default credentials. Aws::Auth::DefaultAWSCredentialsProviderChain provider_chain; return provider_chain.GetAWSCredentials(); } // Read credentials from the given file. util::StatusOr creds_result = ReadFile(std::string(credentials_path)); if (!creds_result.ok()) { return creds_result.status(); } std::vector creds_lines = absl::StrSplit(creds_result.value(), '\n'); if (creds_lines.size() < 3) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid format of credentials in file ", credentials_path)); } util::StatusOr key_id_result = GetValue("aws_access_key_id", creds_lines[1]); if (!key_id_result.ok()) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid format of credentials in file ", credentials_path, " : ", key_id_result.status().message())); } util::StatusOr secret_key_result = GetValue("aws_secret_access_key", creds_lines[2]); if (!secret_key_result.ok()) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid format of credentials in file ", credentials_path, " : ", secret_key_result.status().message())); } return Aws::Auth::AWSCredentials(key_id_result.value().c_str(), secret_key_result.value().c_str()); } void InitAwsApi() { Aws::SDKOptions options; Aws::InitAPI(options); } } // namespace static absl::once_flag aws_initialization_once; util::StatusOr> AwsKmsClient::New( absl::string_view key_uri, absl::string_view credentials_path) { absl::call_once(aws_initialization_once, []() { InitAwsApi(); }); // Read credentials. util::StatusOr credentials = GetAwsCredentials(credentials_path); if (!credentials.ok()) { return credentials.status(); } if (key_uri.empty()) { return absl::WrapUnique(new AwsKmsClient(*credentials)); } // If a specific key is given, create an AWS KMSClient. util::StatusOr key_arn = GetKeyArn(key_uri); if (!key_arn.ok()) { return key_arn.status(); } util::StatusOr client_config = GetAwsClientConfig(*key_arn); if (!client_config.ok()) { return client_config.status(); } auto client = absl::WrapUnique(new AwsKmsClient(*key_arn, *credentials)); // Create AWS KMSClient. client->aws_client_ = Aws::MakeShared( kTinkAwsKmsAllocationTag, client->credentials_, *client_config); return std::move(client); } bool AwsKmsClient::DoesSupport(absl::string_view key_uri) const { util::StatusOr key_arn = GetKeyArn(key_uri); if (!key_arn.ok()) { return false; } // If this is bound to a specific key, make sure the key ARNs are equal. return key_arn_.empty() ? true : key_arn_ == *key_arn; } util::StatusOr> AwsKmsClient::GetAead( absl::string_view key_uri) const { util::StatusOr key_arn = GetKeyArn(key_uri); if (!key_arn.ok()) { return key_arn.status(); } // This client is bound to a specific key. if (!key_arn_.empty()) { if (key_arn_ != *key_arn) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("This client is bound to ", key_arn_, " and cannot use key ", key_uri)); } return AwsKmsAead::New(key_arn_, aws_client_); } util::StatusOr client_config = GetAwsClientConfig(*key_arn); if (!client_config.ok()) { return client_config.status(); } auto aws_client = Aws::MakeShared( kTinkAwsKmsAllocationTag, credentials_, *client_config); return AwsKmsAead::New(*key_arn, aws_client); } util::Status AwsKmsClient::RegisterNewClient( absl::string_view key_uri, absl::string_view credentials_path) { util::StatusOr> client_result = AwsKmsClient::New(key_uri, credentials_path); if (!client_result.ok()) { return client_result.status(); } return KmsClients::Add(*std::move(client_result)); } } // namespace awskms } // namespace integration } // namespace tink } // namespace crypto ================================================ FILE: cc/integration/awskms/aws_kms_client.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTEGRATION_AWSKMS_AWS_KMS_CLIENT_H_ #define TINK_INTEGRATION_AWSKMS_AWS_KMS_CLIENT_H_ #include #include "aws/core/auth/AWSCredentialsProvider.h" #include "aws/kms/KMSClient.h" #include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" #include "tink/aead.h" #include "tink/kms_client.h" #include "tink/kms_clients.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace integration { namespace awskms { // AwsKmsClient is an implementation of KmsClient for AWS KMS // (https://aws.amazon.com/kms/). class AwsKmsClient : public crypto::tink::KmsClient { public: // Move only. AwsKmsClient(AwsKmsClient&& other) = default; AwsKmsClient& operator=(AwsKmsClient&& other) = default; AwsKmsClient(const AwsKmsClient&) = delete; AwsKmsClient& operator=(const AwsKmsClient&) = delete; // Creates a new AwsKmsClient that is bound to the key specified in `key_uri`, // if not empty, and that uses the credentials in `credentials_path`, if not // empty, or the default ones to authenticate to the KMS. // // If `key_uri` is empty, then the client is not bound to any particular key. static crypto::tink::util::StatusOr> New( absl::string_view key_uri, absl::string_view credentials_path); // Creates a new client and adds it to the global list of KMSClients. // // This function should only be called on startup and not on every operation. // Avoid registering a client more than once. // // It is often not necessary to use this function. Instead, you can call // AwsKmsAead::New to directly create an Aead object without creating or // registering a client. static crypto::tink::util::Status RegisterNewClient( absl::string_view key_uri, absl::string_view credentials_path); // Returns true if: (1) `key_uri` is a valid AWS KMS key URI, and (2) the // resulting AWS key ARN is equals to key_arn_, in case this client is bound // to a specific key. bool DoesSupport(absl::string_view key_uri) const override; crypto::tink::util::StatusOr> GetAead( absl::string_view key_uri) const override; private: AwsKmsClient(absl::string_view key_arn, Aws::Auth::AWSCredentials credentials) : key_arn_(key_arn), credentials_(credentials) {} AwsKmsClient(Aws::Auth::AWSCredentials credentials) : credentials_(credentials) {} std::string key_arn_; Aws::Auth::AWSCredentials credentials_; std::shared_ptr aws_client_; }; } // namespace awskms } // namespace integration } // namespace tink } // namespace crypto #endif // TINK_INTEGRATION_AWSKMS_AWS_KMS_CLIENT_H_ ================================================ FILE: cc/integration/awskms/aws_kms_client_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/integration/awskms/aws_kms_client.h" #include #include #include #include #include #include "aws/core/Aws.h" #include "aws/kms/KMSClient.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/integration/awskms/internal/test_file_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace integration { namespace awskms { namespace { using ::crypto::tink::integration::awskms::AwsKmsClient; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::testing::IsNull; using ::testing::IsSubstring; using ::testing::Not; constexpr absl::string_view kAwsKey1 = "aws-kms://arn:aws:kms:us-east-1:acc:some/key1"; constexpr absl::string_view kAwsKey2 = "aws-kms://arn:aws:kms:us-east-1:acc:some/key2"; constexpr absl::string_view kNonAwsKey = "gcp-kms:://some/gcp/key"; TEST(AwsKmsClientTest, CreateClientNotBoundToSpecificKeySupportsAllValidKeys) { std::string creds_file = internal::RunfilesPath("testdata/aws/credentials.ini"); util::StatusOr> client = AwsKmsClient::New(/*key_uri=*/"", creds_file); ASSERT_THAT(client, IsOk()); EXPECT_TRUE((*client)->DoesSupport(kAwsKey1)); EXPECT_TRUE((*client)->DoesSupport(kAwsKey2)); EXPECT_FALSE((*client)->DoesSupport(kNonAwsKey)); } // Test that a client that is bound to a specific key does not support a // different key URI. TEST(AwsKmsClientTest, CreateClientBoundToSpecificKeySupportOnlyOneKey) { std::string creds_file = internal::RunfilesPath("testdata/aws/credentials.ini"); util::StatusOr> client = AwsKmsClient::New(kAwsKey1, creds_file); ASSERT_THAT(client, IsOk()); EXPECT_TRUE((*client)->DoesSupport(kAwsKey1)); EXPECT_FALSE((*client)->DoesSupport(kAwsKey2)); EXPECT_FALSE((*client)->DoesSupport(kNonAwsKey)); } TEST(AwsKmsClientTest, RegisterKmsClient) { std::string creds_file = internal::RunfilesPath("testdata/aws/credentials.ini"); ASSERT_THAT(AwsKmsClient::RegisterNewClient(kAwsKey1, creds_file), IsOk()); util::StatusOr kms_client = KmsClients::Get(kAwsKey1); EXPECT_THAT(kms_client, IsOkAndHolds(Not(IsNull()))); } TEST(AwsKmsClientTest, RegisterKmsClientFailsWhenKeyIsInvalid) { util::Status client = AwsKmsClient::RegisterNewClient( "gcp-kms://projects/someProject/.../cryptoKeys/key1", internal::RunfilesPath("testdata/aws/credentials.ini")); EXPECT_THAT(client, StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_PRED_FORMAT2(IsSubstring, "Invalid key URI", std::string(client.message())); } TEST(AwsKmsClientTest, RegisterKmsClientFailsWhenCredentialsDoNotExist) { util::Status client = AwsKmsClient::RegisterNewClient(kAwsKey1, "this/file/does/not/exist.ini"); EXPECT_THAT(client, StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_PRED_FORMAT2(IsSubstring, "Error opening file", std::string(client.message())); } TEST(AwsKmsClientTest, RegisterKmsClientFailsWhenMalformedCredentials) { // Create an invalid credentials file. std::string malformed_content = "These are malformed credentials."; std::string invalid_credentials_file = internal::RunfilesPath("testdata/aws/invalid.ini"); std::ofstream out_stream(invalid_credentials_file, std::ios::binary); out_stream.write(malformed_content.data(), malformed_content.size()); out_stream.close(); util::Status client = AwsKmsClient::RegisterNewClient(kAwsKey1, invalid_credentials_file); EXPECT_THAT(client, StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_PRED_FORMAT2(IsSubstring, "Invalid format", std::string(client.message())); } } // namespace } // namespace awskms } // namespace integration } // namespace tink } // namespace crypto ================================================ FILE: cc/integration/awskms/internal/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "test_file_util", srcs = ["test_file_util_bazel.cc"], hdrs = ["test_file_util.h"], include_prefix = "tink/integration/awskms/internal", testonly = 1, deps = [ "@bazel_tools//tools/cpp/runfiles", "@com_google_absl//absl/log:check", "@com_google_absl//absl/strings", ], alwayslink = 1, ) ================================================ FILE: cc/integration/awskms/internal/test_file_util.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTEGRATION_AWSKMS_INTERNAL_TEST_FILE_UTIL_H_ #define TINK_INTEGRATION_AWSKMS_INTERNAL_TEST_FILE_UTIL_H_ #include "absl/strings/string_view.h" namespace crypto { namespace tink { namespace integration { namespace awskms { namespace internal { // Returns the path of the specified file in the runfiles directory. std::string RunfilesPath(absl::string_view path); } // namespace internal } // namespace awskms } // namespace integration } // namespace tink } // namespace crypto #endif // TINK_INTEGRATION_AWSKMS_INTERNAL_TEST_FILE_UTIL_H_ ================================================ FILE: cc/integration/awskms/internal/test_file_util_bazel.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/integration/awskms/internal/test_file_util.h" #include "absl/log/check.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tools/cpp/runfiles/runfiles.h" namespace crypto { namespace tink { namespace integration { namespace awskms { namespace internal { using ::bazel::tools::cpp::runfiles::Runfiles; std::string RunfilesPath(absl::string_view path) { std::string error; std::unique_ptr runfiles(Runfiles::CreateForTest(&error)); CHECK(runfiles != nullptr) << "Unable to determine runfile path: "; const char* workspace_dir = getenv("TEST_WORKSPACE"); CHECK(workspace_dir != nullptr && workspace_dir[0] != '\0') << "Unable to determine workspace name."; return runfiles->Rlocation(absl::StrCat(workspace_dir, "/", path)); } } // namespace internal } // namespace awskms } // namespace integration } // namespace tink } // namespace crypto ================================================ FILE: cc/integration/awskms/template_rule.bzl ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Rule for simple expansion of template files.""" def _template_rule_impl(ctx): """Modifies ctx.file.src keys in ctx.attr.substitutions with corresponding values.""" ctx.actions.expand_template( template = ctx.file.src, output = ctx.outputs.out, substitutions = ctx.attr.substitutions, ) # Rule for simple expansion of template files. Modifies the templates in src substituting the keys # in substitutions with the corresponding values; the result is output to out. # # Borrowed from TensorFlow (https://github.com/tensorflow/tensorflow) # # Typical usage: # template_rule( # name = "ExpandMyTemplate", # src = "my.template", # out = "my.txt", # substitutions = { # "$VAR1": "foo", # "$VAR2": "bar", # } # ) # # Args: # name: The name of the rule. # src: The template file to expand # out: The destination of the expanded file # substitutions: A dictionary mapping strings to their substitutions template_rule = rule( attrs = { "src": attr.label( mandatory = True, allow_single_file = True, ), "substitutions": attr.string_dict(mandatory = True), "out": attr.output(mandatory = True), }, implementation = _template_rule_impl, ) ================================================ FILE: cc/integration/awskms/testdata/aws/BUILD.bazel ================================================ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) filegroup( name = "credentials", testonly = 1, srcs = [ "credentials.cred", "credentials.csv", "credentials.ini", "key_arn.txt", ], ) filegroup( name = "bad_credentials", testonly = 1, srcs = [ "access_keys_bad.csv", "credentials_bad.csv", "credentials_bad.ini", "key_arn_bad.txt", ], ) ================================================ FILE: cc/integration/awskms/testdata/aws/README.md ================================================ This folder contains AWS credentials that are used for testing Tink. For security reasons, all credentials in this folder are invalid. If you want to run tests that depend on them, please create your own [AWS access keys][aws-access-keys]. The credentials are required in several formats expected by different APIs. For example, Java expects the credentials as a [properties file][properties-file]. In order to cover all tests across all languages you have to replace `aws/credentials.cred`, `aws/credentials.csv` and `aws/credentials.ini`. These can be generated in a similar way to this [credential copying script][copy-credentials-script]. [aws-access-keys]: https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html [properties-file]: https://docs.aws.amazon.com/AmazonS3/latest/dev/AuthUsingAcctOrUserCredentials.html [copy-credentials-script]: https://github.com/google/tink/blob/master/kokoro/copy_credentials.sh ================================================ FILE: cc/integration/awskms/testdata/aws/access_keys_bad.csv ================================================ Access key ID,Secret access key AKIAIOSFODNN7EXAMPLE,wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY ================================================ FILE: cc/integration/awskms/testdata/aws/credentials.cred ================================================ [default] accessKey = AKIAIIK5X7P3NAHNSNUQ secretKey = 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 ================================================ FILE: cc/integration/awskms/testdata/aws/credentials.csv ================================================ User name,Password,Access key ID,Secret access key,Console login link tink-user1,,AKIAIIK5X7P3NAHNSNUQ,c7k55Gw83QlN1gYBhVPEEn1pKV909sxbll8JOvHF,https://235739564943.signin.aws.amazon.com/console ================================================ FILE: cc/integration/awskms/testdata/aws/credentials.ini ================================================ [default] aws_access_key_id = AKIAIIK5X7P3NAHNSNUQ aws_secret_access_key = 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 ================================================ FILE: cc/integration/awskms/testdata/aws/credentials_bad.csv ================================================ User name,Password,Access key ID,Secret access key ,,AKIAIOSFODNN7EXAMPLE,wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY ================================================ FILE: cc/integration/awskms/testdata/aws/credentials_bad.ini ================================================ [default] aws_access_key_id = AKIAIOSFODNN7EXAMPLE aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY ================================================ FILE: cc/integration/awskms/testdata/aws/key_arn.txt ================================================ arn:aws:kms:us-east-2:235739564943:key/3ee50705-5a82-4f5b-9753-05c4f473922f ================================================ FILE: cc/integration/awskms/testdata/aws/key_arn_bad.txt ================================================ arn:aws:kms:us-east-2:123456789012:key/12345678-1234-1234-1234-123456789012 ================================================ FILE: cc/integration/awskms/third_party/aws_c_common.BUILD.bazel ================================================ load("@tink_cc_awskms//:template_rule.bzl", "template_rule") licenses(["notice"]) # Apache 2.0 cc_library( name = "aws_c_common", srcs = glob(["source/*.c"]) + glob(["source/posix/*.c"]), hdrs = [ "include/aws/common/config.h" ] + glob([ "include/**/*.h", "include/aws/common/**/*.inl" ]), includes = ["include/"], visibility = ["//visibility:public"], ) template_rule( name = "config.h", src = "include/aws/common/config.h.in", out = "include/aws/common/config.h", substitutions = { "cmakedefine AWS_HAVE_GCC_OVERFLOW_MATH_EXTENSIONS": "undef AWS_HAVE_GCC_OVERFLOW_MATH_EXTENSIONS", "cmakedefine AWS_HAVE_GCC_INLINE_ASM": "define AWS_HAVE_GCC_INLINE_ASM", "cmakedefine AWS_HAVE_MSVC_MULX": "undef AWS_HAVE_MSVC_MULX", "cmakedefine AWS_HAVE_EXECINFO": "define AWS_HAVE_EXECINFO", }, ) ================================================ FILE: cc/integration/awskms/third_party/aws_c_event_stream.BUILD.bazel ================================================ licenses(["notice"]) # Apache 2.0 cc_library( name = "aws_c_event_stream", srcs = glob([ "source/*.c", ]), hdrs = glob([ "include/**/*.h" ]), includes = [ "include/", ], deps = [ "@aws_c_common", "@aws_checksums" ], visibility = ["//visibility:public"], ) ================================================ FILE: cc/integration/awskms/third_party/aws_checksums.BUILD.bazel ================================================ licenses(["notice"]) # Apache 2.0 cc_library( name = "aws_checksums", srcs = glob([ "source/*.c", ]) + select({ "@platforms//cpu:x86_64": glob(["source/intel/*.c"]), "@platforms//cpu:aarch64": glob(["source/arm/*.c"]), "//conditions:default": ["@platforms//:incompatible"], }), hdrs = glob([ "include/**/*.h" ]), includes = [ "include/", ], copts = [ "-O2" # Note there is some issue with the assembly implementation and GCC, therefore this should always be compiled with -O (https://github.com/awslabs/aws-checksums/issues/8) ], deps = [ "@aws_c_common", ], visibility = ["//visibility:public"], ) ================================================ FILE: cc/integration/awskms/third_party/aws_sdk_cpp.BUILD.bazel ================================================ load("@tink_cc_awskms//:template_rule.bzl", "template_rule") licenses(["notice"]) # Apache 2.0 cc_library( name = "aws_sdk_core", srcs = glob([ "aws-cpp-sdk-core/include/**/*.h", "aws-cpp-sdk-core/source/*.cpp", "aws-cpp-sdk-core/source/auth/**/*.cpp", "aws-cpp-sdk-core/source/config/**/*.cpp", "aws-cpp-sdk-core/source/client/**/*.cpp", "aws-cpp-sdk-core/source/external/**/*.cpp", "aws-cpp-sdk-core/source/internal/**/*.cpp", "aws-cpp-sdk-core/source/http/*.cpp", "aws-cpp-sdk-core/source/http/curl/**/*.cpp", "aws-cpp-sdk-core/source/http/standard/**/*.cpp", "aws-cpp-sdk-core/source/platform/linux-shared/*.cpp", "aws-cpp-sdk-core/source/utils/*.cpp", "aws-cpp-sdk-core/source/utils/*.h", "aws-cpp-sdk-core/source/utils/base64/**/*.cpp", "aws-cpp-sdk-core/source/utils/json/**/*.cpp", "aws-cpp-sdk-core/source/utils/logging/**/*.cpp", "aws-cpp-sdk-core/source/utils/memory/**/*.cpp", "aws-cpp-sdk-core/source/utils/stream/**/*.cpp", "aws-cpp-sdk-core/source/utils/threading/**/*.cpp", "aws-cpp-sdk-core/source/utils/xml/**/*.cpp", "aws-cpp-sdk-core/source/utils/crypto/*.cpp", "aws-cpp-sdk-core/source/utils/crypto/factory/**/*.cpp", "aws-cpp-sdk-kms/include/**/*.h", "aws-cpp-sdk-kms/source/**/*.cpp", "aws-cpp-sdk-core/source/monitoring/*.cpp", "aws-cpp-sdk-core/source/net/linux-shared/*.cpp", "aws-cpp-sdk-core/source/utils/crypto/openssl/*.cpp", ]), hdrs = [ "aws-cpp-sdk-core/include/aws/core/SDKConfig.h", ], includes = [ "aws-cpp-sdk-core/include/", "aws-cpp-sdk-kms/include/", ], # These must be in sync with version of aws_cpp_sdk in WORKSPACE. defines = [ "AWS_SDK_VERSION_MAJOR=1", "AWS_SDK_VERSION_MINOR=7", "AWS_SDK_VERSION_PATCH=345", "ENABLE_CURL_CLIENT", "ENABLE_OPENSSL_ENCRYPTION", # This is needed for UUID generation "OPENSSL_IS_BORINGSSL", "PLATFORM_LINUX", ], visibility = ["//visibility:public"], strip_include_prefix = "aws-cpp-sdk-core/include", deps = [ "@aws_c_common", "@aws_c_event_stream", "@curl", "@boringssl//:crypto", ], ) template_rule( name = "SDKConfig_h", src = "aws-cpp-sdk-core/include/aws/core/SDKConfig.h.in", out = "aws-cpp-sdk-core/include/aws/core/SDKConfig.h", substitutions = { "cmakedefine": "define", }, ) ================================================ FILE: cc/integration/awskms/third_party/curl.BUILD.bazel ================================================ # Description: # curl is a tool for talking to web servers. licenses(["notice"]) # MIT/X derivative license cc_library( name = "curl", srcs = [ "include/curl_config.h", "lib/amigaos.h", "lib/arpa_telnet.h", "lib/asyn.h", "lib/asyn-ares.c", "lib/base64.c", "lib/config-win32.h", "lib/conncache.c", "lib/conncache.h", "lib/connect.c", "lib/connect.h", "lib/content_encoding.c", "lib/content_encoding.h", "lib/cookie.c", "lib/cookie.h", "lib/curl_addrinfo.c", "lib/curl_addrinfo.h", "lib/curl_base64.h", "lib/curl_des.h", "lib/curl_endian.h", "lib/curl_fnmatch.c", "lib/curl_fnmatch.h", "lib/curl_gethostname.c", "lib/curl_gethostname.h", "lib/curl_gssapi.h", "lib/curl_hmac.h", "lib/curl_ldap.h", "lib/curl_md4.h", "lib/curl_md5.h", "lib/curl_memory.h", "lib/curl_memrchr.c", "lib/curl_memrchr.h", "lib/curl_multibyte.c", "lib/curl_multibyte.h", "lib/curl_ntlm_core.h", "lib/curl_ntlm_wb.h", "lib/curl_printf.h", "lib/curl_rtmp.c", "lib/curl_rtmp.h", "lib/curl_sasl.c", "lib/curl_sasl.h", "lib/curl_sec.h", "lib/curl_setup.h", "lib/curl_setup_once.h", "lib/curl_sspi.c", "lib/curl_sspi.h", "lib/curl_threads.c", "lib/curl_threads.h", "lib/curlx.h", "lib/dict.h", "lib/dotdot.c", "lib/dotdot.h", "lib/easy.c", "lib/easyif.h", "lib/escape.c", "lib/escape.h", "lib/file.h", "lib/fileinfo.c", "lib/fileinfo.h", "lib/formdata.c", "lib/formdata.h", "lib/ftp.h", "lib/ftplistparser.h", "lib/getenv.c", "lib/getinfo.c", "lib/getinfo.h", "lib/gopher.h", "lib/hash.c", "lib/hash.h", "lib/hmac.c", "lib/hostasyn.c", "lib/hostcheck.c", "lib/hostcheck.h", "lib/hostip.c", "lib/hostip.h", "lib/hostip4.c", "lib/hostip6.c", "lib/hostsyn.c", "lib/http.c", "lib/http.h", "lib/http2.c", "lib/http2.h", "lib/http_chunks.c", "lib/http_chunks.h", "lib/http_digest.c", "lib/http_digest.h", "lib/http_negotiate.h", "lib/http_ntlm.h", "lib/http_proxy.c", "lib/http_proxy.h", "lib/if2ip.c", "lib/if2ip.h", "lib/imap.h", "lib/inet_ntop.h", "lib/inet_pton.c", "lib/inet_pton.h", "lib/krb5.c", "lib/llist.c", "lib/llist.h", "lib/md4.c", "lib/md5.c", "lib/memdebug.c", "lib/memdebug.h", "lib/mprintf.c", "lib/multi.c", "lib/multihandle.h", "lib/multiif.h", "lib/netrc.c", "lib/netrc.h", "lib/non-ascii.h", "lib/nonblock.c", "lib/nonblock.h", "lib/nwlib.c", "lib/nwos.c", "lib/parsedate.c", "lib/parsedate.h", "lib/pingpong.h", "lib/pipeline.c", "lib/pipeline.h", "lib/pop3.h", "lib/progress.c", "lib/progress.h", "lib/rawstr.c", "lib/rawstr.h", "lib/rtsp.c", "lib/rtsp.h", "lib/security.c", "lib/select.c", "lib/select.h", "lib/sendf.c", "lib/sendf.h", "lib/setup-os400.h", "lib/setup-vms.h", "lib/share.c", "lib/share.h", "lib/sigpipe.h", "lib/slist.c", "lib/slist.h", "lib/smb.h", "lib/smtp.h", "lib/sockaddr.h", "lib/socks.c", "lib/socks.h", "lib/speedcheck.c", "lib/speedcheck.h", "lib/splay.c", "lib/splay.h", "lib/ssh.h", "lib/strdup.c", "lib/strdup.h", "lib/strequal.c", "lib/strequal.h", "lib/strerror.c", "lib/strerror.h", "lib/strtok.c", "lib/strtok.h", "lib/strtoofft.c", "lib/strtoofft.h", "lib/system_win32.h", "lib/telnet.h", "lib/tftp.h", "lib/timeval.c", "lib/timeval.h", "lib/transfer.c", "lib/transfer.h", "lib/url.c", "lib/url.h", "lib/urldata.h", "lib/vauth/cleartext.c", "lib/vauth/cram.c", "lib/vauth/digest.c", "lib/vauth/digest.h", "lib/vauth/ntlm.h", "lib/vauth/oauth2.c", "lib/vauth/vauth.c", "lib/vauth/vauth.h", "lib/version.c", "lib/vtls/axtls.h", "lib/vtls/cyassl.h", "lib/vtls/darwinssl.h", "lib/vtls/gskit.h", "lib/vtls/gtls.h", "lib/vtls/mbedtls.h", "lib/vtls/nssg.h", "lib/vtls/openssl.h", "lib/vtls/polarssl.h", "lib/vtls/polarssl_threadlock.h", "lib/vtls/schannel.h", "lib/vtls/vtls.c", "lib/vtls/vtls.h", "lib/warnless.c", "lib/warnless.h", "lib/wildcard.c", "lib/wildcard.h", "lib/x509asn1.h", ] + select({ "@platforms//os:macos": ["lib/vtls/darwinssl.c"], "@platforms//os:linux": ["lib/vtls/openssl.c"], "//conditions:default": ["@platforms//:incompatible"], }), hdrs = [ ":configure", "include/curl/curl.h", "include/curl/curlbuild.h", "include/curl/curlrules.h", "include/curl/curlver.h", "include/curl/easy.h", "include/curl/mprintf.h", "include/curl/multi.h", "include/curl/stdcheaders.h", "include/curl/typecheck-gcc.h", ], copts = [ "-Iexternal/curl/lib", "-D_GNU_SOURCE", "-DHAVE_CONFIG_H", "-DCURL_DISABLE_FTP", "-DCURL_DISABLE_NTLM", # turning it off in configure is not enough "-DHAVE_LIBZ", "-DHAVE_ZLIB_H", "-Wno-string-plus-int", ] + select({ "@platforms//os:macos": ["-fno-constant-cfstrings"], "@platforms//os:linux": ["-DCURL_MAX_WRITE_SIZE=65536"], "//conditions:default": ["@platforms//:incompatible"], }), defines = ["CURL_STATICLIB"], includes = ["include"], linkopts = select({ "@platforms//os:macos": [ "-Wl,-framework", "-Wl,CoreFoundation", "-Wl,-framework", "-Wl,Security", ], "@platforms//os:linux": ["-lrt"], "//conditions:default": ["@platforms//:incompatible"], }), visibility = ["//visibility:public"], deps = [ "@boringssl//:ssl", "@zlib//:zlib", ], ) cc_binary( name = "curl_bin", srcs = [ "lib/config-win32.h", "src/slist_wc.c", "src/slist_wc.h", "src/tool_binmode.c", "src/tool_binmode.h", "src/tool_bname.c", "src/tool_bname.h", "src/tool_cb_dbg.c", "src/tool_cb_dbg.h", "src/tool_cb_hdr.c", "src/tool_cb_hdr.h", "src/tool_cb_prg.c", "src/tool_cb_prg.h", "src/tool_cb_rea.c", "src/tool_cb_rea.h", "src/tool_cb_see.c", "src/tool_cb_see.h", "src/tool_cb_wrt.c", "src/tool_cb_wrt.h", "src/tool_cfgable.c", "src/tool_cfgable.h", "src/tool_convert.c", "src/tool_convert.h", "src/tool_dirhie.c", "src/tool_dirhie.h", "src/tool_doswin.c", "src/tool_doswin.h", "src/tool_easysrc.c", "src/tool_easysrc.h", "src/tool_formparse.c", "src/tool_formparse.h", "src/tool_getparam.c", "src/tool_getparam.h", "src/tool_getpass.c", "src/tool_getpass.h", "src/tool_help.c", "src/tool_help.h", "src/tool_helpers.c", "src/tool_helpers.h", "src/tool_homedir.c", "src/tool_homedir.h", "src/tool_hugehelp.c", "src/tool_hugehelp.h", "src/tool_libinfo.c", "src/tool_libinfo.h", "src/tool_main.c", "src/tool_main.h", "src/tool_metalink.c", "src/tool_metalink.h", "src/tool_mfiles.c", "src/tool_mfiles.h", "src/tool_msgs.c", "src/tool_msgs.h", "src/tool_operate.c", "src/tool_operate.h", "src/tool_operhlp.c", "src/tool_operhlp.h", "src/tool_panykey.c", "src/tool_panykey.h", "src/tool_paramhlp.c", "src/tool_paramhlp.h", "src/tool_parsecfg.c", "src/tool_parsecfg.h", "src/tool_sdecls.h", "src/tool_setopt.c", "src/tool_setopt.h", "src/tool_setup.h", "src/tool_sleep.c", "src/tool_sleep.h", "src/tool_strdup.c", "src/tool_strdup.h", "src/tool_urlglob.c", "src/tool_urlglob.h", "src/tool_util.c", "src/tool_util.h", "src/tool_version.h", "src/tool_vms.c", "src/tool_vms.h", "src/tool_writeenv.c", "src/tool_writeenv.h", "src/tool_writeout.c", "src/tool_writeout.h", "src/tool_xattr.c", "src/tool_xattr.h", ], copts = [ "-Iexternal/curl/lib", "-D_GNU_SOURCE", "-DHAVE_CONFIG_H", "-DCURL_DISABLE_LIBCURL_OPTION", "-Wno-string-plus-int", ], deps = [":curl"], ) genrule( name = "configure", outs = ["include/curl_config.h"], cmd = "\n".join([ "cat <<'EOF' >$@", "#ifndef EXTERNAL_CURL_INCLUDE_CURL_CONFIG_H_", "#define EXTERNAL_CURL_INCLUDE_CURL_CONFIG_H_", "", "#if !defined(_WIN32) && !defined(__APPLE__)", "# include ", "# if defined(OPENSSL_IS_BORINGSSL)", "# define HAVE_BORINGSSL 1", "# endif", "#endif", "", "#if defined(_WIN32)", "# include \"lib/config-win32.h\"", "# define BUILDING_LIBCURL 1", "# define CURL_DISABLE_CRYPTO_AUTH 1", "# define CURL_DISABLE_DICT 1", "# define CURL_DISABLE_FILE 1", "# define CURL_DISABLE_GOPHER 1", "# define CURL_DISABLE_IMAP 1", "# define CURL_DISABLE_LDAP 1", "# define CURL_DISABLE_LDAPS 1", "# define CURL_DISABLE_POP3 1", "# define CURL_PULL_WS2TCPIP_H 1", "# define CURL_DISABLE_SMTP 1", "# define CURL_DISABLE_TELNET 1", "# define CURL_DISABLE_TFTP 1", "# define CURL_PULL_WS2TCPIP_H 1", "# define USE_WINDOWS_SSPI 1", "# define USE_WIN32_IDN 1", "# define USE_SCHANNEL 1", "# define WANT_IDN_PROTOTYPES 1", "#elif defined(__APPLE__)", "# define HAVE_FSETXATTR_6 1", "# define HAVE_SETMODE 1", "# define HAVE_SYS_FILIO_H 1", "# define HAVE_SYS_SOCKIO_H 1", "# define OS \"x86_64-apple-darwin15.5.0\"", "# define USE_DARWINSSL 1", "#else", "# define CURL_CA_BUNDLE \"/etc/ssl/certs/ca-certificates.crt\"", "# define GETSERVBYPORT_R_ARGS 6", "# define GETSERVBYPORT_R_BUFSIZE 4096", "# define HAVE_BORINGSSL 1", "# define HAVE_CLOCK_GETTIME_MONOTONIC 1", "# define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1", "# define HAVE_FSETXATTR_5 1", "# define HAVE_GETHOSTBYADDR_R 1", "# define HAVE_GETHOSTBYADDR_R_8 1", "# define HAVE_GETHOSTBYNAME_R 1", "# define HAVE_GETHOSTBYNAME_R_6 1", "# define HAVE_GETSERVBYPORT_R 1", "# define HAVE_LIBSSL 1", "# define HAVE_MALLOC_H 1", "# define HAVE_MSG_NOSIGNAL 1", "# define HAVE_OPENSSL_CRYPTO_H 1", "# define HAVE_OPENSSL_ERR_H 1", "# define HAVE_OPENSSL_PEM_H 1", "# define HAVE_OPENSSL_PKCS12_H 1", "# define HAVE_OPENSSL_RSA_H 1", "# define HAVE_OPENSSL_SSL_H 1", "# define HAVE_OPENSSL_X509_H 1", "# define HAVE_RAND_EGD 1", "# define HAVE_RAND_STATUS 1", "# define HAVE_SSL_GET_SHUTDOWN 1", "# define HAVE_TERMIOS_H 1", "# define OS \"x86_64-pc-linux-gnu\"", "# define RANDOM_FILE \"/dev/urandom\"", "# define USE_OPENSSL 1", "#endif", "", "#if !defined(_WIN32)", "# define CURL_DISABLE_DICT 1", "# define CURL_DISABLE_FILE 1", "# define CURL_DISABLE_GOPHER 1", "# define CURL_DISABLE_IMAP 1", "# define CURL_DISABLE_LDAP 1", "# define CURL_DISABLE_LDAPS 1", "# define CURL_DISABLE_POP3 1", "# define CURL_DISABLE_SMTP 1", "# define CURL_DISABLE_TELNET 1", "# define CURL_DISABLE_TFTP 1", "# define CURL_EXTERN_SYMBOL __attribute__ ((__visibility__ (\"default\")))", "# define ENABLE_IPV6 1", "# define GETHOSTNAME_TYPE_ARG2 size_t", "# define GETNAMEINFO_QUAL_ARG1 const", "# define GETNAMEINFO_TYPE_ARG1 struct sockaddr *", "# define GETNAMEINFO_TYPE_ARG2 socklen_t", "# define GETNAMEINFO_TYPE_ARG46 socklen_t", "# define GETNAMEINFO_TYPE_ARG7 int", "# define HAVE_ALARM 1", "# define HAVE_ALLOCA_H 1", "# define HAVE_ARPA_INET_H 1", "# define HAVE_ARPA_TFTP_H 1", "# define HAVE_ASSERT_H 1", "# define HAVE_BASENAME 1", "# define HAVE_BOOL_T 1", "# define HAVE_CONNECT 1", "# define HAVE_DLFCN_H 1", "# define HAVE_ERRNO_H 1", "# define HAVE_FCNTL 1", "# define HAVE_FCNTL_H 1", "# define HAVE_FCNTL_O_NONBLOCK 1", "# define HAVE_FDOPEN 1", "# define HAVE_FORK 1", "# define HAVE_FREEADDRINFO 1", "# define HAVE_FREEIFADDRS 1", "# if !defined(__ANDROID__)", "# define HAVE_FSETXATTR 1", "# endif", "# define HAVE_FTRUNCATE 1", "# define HAVE_GAI_STRERROR 1", "# define HAVE_GETADDRINFO 1", "# define HAVE_GETADDRINFO_THREADSAFE 1", "# define HAVE_GETEUID 1", "# define HAVE_GETHOSTBYADDR 1", "# define HAVE_GETHOSTBYNAME 1", "# define HAVE_GETHOSTNAME 1", "# if !defined(__ANDROID__)", "# define HAVE_GETIFADDRS 1", "# endif", "# define HAVE_GETNAMEINFO 1", "# define HAVE_GETPPID 1", "# define HAVE_GETPROTOBYNAME 1", "# define HAVE_GETPWUID 1", "# if !defined(__ANDROID__)", "# define HAVE_GETPWUID_R 1", "# endif", "# define HAVE_GETRLIMIT 1", "# define HAVE_GETTIMEOFDAY 1", "# define HAVE_GMTIME_R 1", "# if !defined(__ANDROID__)", "# define HAVE_IFADDRS_H 1", "# endif", "# define HAVE_IF_NAMETOINDEX 1", "# define HAVE_INET_ADDR 1", "# define HAVE_INET_NTOP 1", "# define HAVE_INET_PTON 1", "# define HAVE_INTTYPES_H 1", "# define HAVE_IOCTL 1", "# define HAVE_IOCTL_FIONBIO 1", "# define HAVE_IOCTL_SIOCGIFADDR 1", "# define HAVE_LIBGEN_H 1", "# define HAVE_LIBZ 1", "# define HAVE_LIMITS_H 1", "# define HAVE_LL 1", "# define HAVE_LOCALE_H 1", "# define HAVE_LOCALTIME_R 1", "# define HAVE_LONGLONG 1", "# define HAVE_MEMORY_H 1", "# define HAVE_NETDB_H 1", "# define HAVE_NETINET_IN_H 1", "# define HAVE_NETINET_TCP_H 1", "# define HAVE_NET_IF_H 1", "# define HAVE_PERROR 1", "# define HAVE_PIPE 1", "# define HAVE_POLL 1", "# define HAVE_POLL_FINE 1", "# define HAVE_POLL_H 1", "# define HAVE_POSIX_STRERROR_R 1", "# define HAVE_PWD_H 1", "# define HAVE_RECV 1", "# define HAVE_SELECT 1", "# define HAVE_SEND 1", "# define HAVE_SETJMP_H 1", "# define HAVE_SETLOCALE 1", "# define HAVE_SETRLIMIT 1", "# define HAVE_SETSOCKOPT 1", "# define HAVE_SGTTY_H 1", "# define HAVE_SIGACTION 1", "# define HAVE_SIGINTERRUPT 1", "# define HAVE_SIGNAL 1", "# define HAVE_SIGNAL_H 1", "# define HAVE_SIGSETJMP 1", "# define HAVE_SIG_ATOMIC_T 1", "# define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1", "# define HAVE_SOCKET 1", "# define HAVE_SOCKETPAIR 1", "# define HAVE_STDBOOL_H 1", "# define HAVE_STDINT_H 1", "# define HAVE_STDIO_H 1", "# define HAVE_STDLIB_H 1", "# define HAVE_STRCASECMP 1", "# define HAVE_STRDUP 1", "# define HAVE_STRERROR_R 1", "# define HAVE_STRINGS_H 1", "# define HAVE_STRING_H 1", "# define HAVE_STRNCASECMP 1", "# define HAVE_STRSTR 1", "# define HAVE_STRTOK_R 1", "# define HAVE_STRTOLL 1", "# define HAVE_STRUCT_SOCKADDR_STORAGE 1", "# define HAVE_STRUCT_TIMEVAL 1", "# define HAVE_SYS_IOCTL_H 1", "# define HAVE_SYS_PARAM_H 1", "# define HAVE_SYS_POLL_H 1", "# define HAVE_SYS_RESOURCE_H 1", "# define HAVE_SYS_SELECT_H 1", "# define HAVE_SYS_SOCKET_H 1", "# define HAVE_SYS_STAT_H 1", "# define HAVE_SYS_TIME_H 1", "# define HAVE_SYS_TYPES_H 1", "# define HAVE_SYS_UIO_H 1", "# define HAVE_SYS_UN_H 1", "# define HAVE_SYS_WAIT_H 1", "# define HAVE_SYS_XATTR_H 1", "# define HAVE_TIME_H 1", "# define HAVE_UNAME 1", "# define HAVE_UNISTD_H 1", "# define HAVE_UTIME 1", "# define HAVE_UTIME_H 1", "# define HAVE_VARIADIC_MACROS_C99 1", "# define HAVE_VARIADIC_MACROS_GCC 1", "# define HAVE_WRITABLE_ARGV 1", "# define HAVE_WRITEV 1", "# define HAVE_ZLIB_H 1", "# define LT_OBJDIR \".libs/\"", "# define PACKAGE \"curl\"", "# define PACKAGE_BUGREPORT \"a suitable curl mailing list: https://curl.haxx.se/mail/\"", "# define PACKAGE_NAME \"curl\"", "# define PACKAGE_STRING \"curl -\"", "# define PACKAGE_TARNAME \"curl\"", "# define PACKAGE_URL \"\"", "# define PACKAGE_VERSION \"-\"", "# define RECV_TYPE_ARG1 int", "# define RECV_TYPE_ARG2 void *", "# define RECV_TYPE_ARG3 size_t", "# define RECV_TYPE_ARG4 int", "# define RECV_TYPE_RETV ssize_t", "# define RETSIGTYPE void", "# define SELECT_QUAL_ARG5", "# define SELECT_TYPE_ARG1 int", "# define SELECT_TYPE_ARG234 fd_set *", "# define SELECT_TYPE_ARG5 struct timeval *", "# define SELECT_TYPE_RETV int", "# define SEND_QUAL_ARG2 const", "# define SEND_TYPE_ARG1 int", "# define SEND_TYPE_ARG2 void *", "# define SEND_TYPE_ARG3 size_t", "# define SEND_TYPE_ARG4 int", "# define SEND_TYPE_RETV ssize_t", "# define SIZEOF_INT 4", "# define SIZEOF_LONG 8", "# define SIZEOF_OFF_T 8", "# define SIZEOF_SHORT 2", "# define SIZEOF_SIZE_T 8", "# define SIZEOF_TIME_T 8", "# define SIZEOF_VOIDP 8", "# define STDC_HEADERS 1", "# define STRERROR_R_TYPE_ARG3 size_t", "# define TIME_WITH_SYS_TIME 1", "# define VERSION \"-\"", "# ifndef _DARWIN_USE_64_BIT_INODE", "# define _DARWIN_USE_64_BIT_INODE 1", "# endif", "#endif", "", "#endif // EXTERNAL_CURL_INCLUDE_CURL_CONFIG_H_", "EOF", ]), ) ================================================ FILE: cc/integration/awskms/third_party/zlib.BUILD.bazel ================================================ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) # BSD/MIT-like license (for zlib) cc_library( name = "zlib", srcs = [ "adler32.c", "compress.c", "crc32.c", "crc32.h", "deflate.c", "deflate.h", "gzclose.c", "gzguts.h", "gzlib.c", "gzread.c", "gzwrite.c", "infback.c", "inffast.c", "inffast.h", "inffixed.h", "inflate.c", "inflate.h", "inftrees.c", "inftrees.h", "trees.c", "trees.h", "uncompr.c", "zconf.h", "zutil.c", "zutil.h", ], hdrs = ["zlib.h"], copts = [ "-Wno-shift-negative-value", "-DZ_HAVE_UNISTD_H", ], includes = ["."], ) ================================================ FILE: cc/integration/awskms/tink_cc_awskms_deps.bzl ================================================ """Tink C++ AWS-KMS Integration Dependencies.""" load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") def tink_cc_awskms_deps(): """Loads dependencies for Tink C++ AWS-KMS.""" if not native.existing_rule("aws_cpp_sdk"): # Release from 2020-06-01 http_archive( name = "aws_cpp_sdk", # Must be in sync with defines in third_party/aws_sdk_cpp.BUILD.bazel. url = "https://github.com/aws/aws-sdk-cpp/archive/1.7.345.tar.gz", sha256 = "7df6491e6e0fac726c00b5e6298d5749b131b25a3dd8b905eb311dc7dcc97aaf", strip_prefix = "aws-sdk-cpp-1.7.345", build_file = "@tink_cc_awskms//:third_party/aws_sdk_cpp.BUILD.bazel", ) if not native.existing_rule("aws_c_common"): http_archive( name = "aws_c_common", url = "https://github.com/awslabs/aws-c-common/archive/v0.4.29.tar.gz", sha256 = "01c2a58553a37b3aa5914d9e0bf7bf14507ff4937bc5872a678892ca20fcae1f", strip_prefix = "aws-c-common-0.4.29", build_file = "@tink_cc_awskms//:third_party/aws_c_common.BUILD.bazel", ) if not native.existing_rule("aws_c_event_stream"): http_archive( name = "aws_c_event_stream", url = "https://github.com/awslabs/aws-c-event-stream/archive/v0.1.4.tar.gz", sha256 = "31d880d1c868d3f3df1e1f4b45e56ac73724a4dc3449d04d47fc0746f6f077b6", strip_prefix = "aws-c-event-stream-0.1.4", build_file = "@tink_cc_awskms//:third_party/aws_c_event_stream.BUILD.bazel", ) if not native.existing_rule("aws_checksums"): http_archive( name = "aws_checksums", url = "https://github.com/awslabs/aws-checksums/archive/v0.1.5.tar.gz", sha256 = "6e6bed6f75cf54006b6bafb01b3b96df19605572131a2260fddaf0e87949ced0", strip_prefix = "aws-checksums-0.1.5", build_file = "@tink_cc_awskms//:third_party/aws_checksums.BUILD.bazel", ) if not native.existing_rule("curl"): # Release from 2016-05-30 http_archive( name = "curl", url = "https://mirror.bazel.build/curl.haxx.se/download/curl-7.49.1.tar.gz", sha256 = "ff3e80c1ca6a068428726cd7dd19037a47cc538ce58ef61c59587191039b2ca6", strip_prefix = "curl-7.49.1", build_file = "@tink_cc_awskms//:third_party/curl.BUILD.bazel", ) if not native.existing_rule("zlib"): # Releaes from 2022-03-27. http_archive( name = "zlib", url = "https://mirror.bazel.build/zlib.net/zlib-1.2.12.tar.gz", sha256 = "91844808532e5ce316b3c010929493c0244f3d37593afd6de04f71821d5136d9", strip_prefix = "zlib-1.2.12", build_file = "@tink_cc_awskms//:third_party/zlib.BUILD.bazel", ) ================================================ FILE: cc/integration/gcpkms/.bazelrc ================================================ # Minumum C++ version. Override it building this project with # `bazel build --cxxopt='-std=c++' --host_cxxopt='c++' ...` # (Both -std and --host_cxxopt must be set to force the desired version.) build --cxxopt='-std=c++14' --host_cxxopt='-std=c++14' ================================================ FILE: cc/integration/gcpkms/.bazelversion ================================================ 6.4.0 ================================================ FILE: cc/integration/gcpkms/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "gcp_kms_aead", srcs = ["gcp_kms_aead.cc"], hdrs = ["gcp_kms_aead.h"], include_prefix = "tink/integration/gcpkms", visibility = ["//visibility:public"], deps = [ "@com_github_grpc_grpc//:grpc++", "@com_google_absl//absl/status", "@com_google_googleapis//google/cloud/kms/v1:kms_cc_grpc", "@google_cloud_cpp//:kms", "@com_googlesource_code_re2//:re2", "@tink_cc//:aead", "@tink_cc//util:status", "@tink_cc//util:statusor", ], ) cc_library( name = "gcp_kms_public_key_sign", srcs = ["gcp_kms_public_key_sign.cc"], hdrs = ["gcp_kms_public_key_sign.h"], include_prefix = "tink/integration/gcpkms", visibility = ["//visibility:public"], deps = [ "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/base:nullability", "@google_cloud_cpp//:kms", "@com_googlesource_code_re2//:re2", "@tink_cc//:public_key_sign", "@tink_cc//util:status", "@tink_cc//util:statusor", ], ) cc_library( name = "gcp_kms_client", srcs = ["gcp_kms_client.cc"], hdrs = ["gcp_kms_client.h"], include_prefix = "tink/integration/gcpkms", visibility = ["//visibility:public"], deps = [ ":gcp_kms_aead", "@com_github_grpc_grpc//:grpc++", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/synchronization", "@tink_cc//:aead", "@tink_cc//:kms_client", "@tink_cc//:kms_clients", "@tink_cc//:version", "@tink_cc//util:status", "@tink_cc//util:statusor", ], ) cc_test( name = "gcp_kms_aead_integration_test", size = "medium", srcs = ["gcp_kms_aead_integration_test.cc"], data = [ "//testdata/gcp:credentials", "@google_root_pem//file", ], # This target requires valid credentials to interact with the Google Cloud # KMS. tags = ["manual"], deps = [ ":gcp_kms_aead", ":gcp_kms_client", "@bazel_tools//tools/cpp/runfiles", "@com_github_grpc_grpc//:grpc++", "@com_google_absl//absl/log:check", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", "@tink_cc//:aead", "@tink_cc//util:status", "@tink_cc//util:statusor", "@tink_cc//util:test_matchers", ], ) cc_test( name = "gcp_kms_client_test", size = "medium", srcs = ["gcp_kms_client_test.cc"], data = ["//testdata/gcp:credentials"], deps = [ ":gcp_kms_client", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", "@tink_cc//util:status", "@tink_cc//util:statusor", "@tink_cc//util:test_matchers", "@tink_cc//util:test_util", ], ) cc_test( name = "gcp_kms_aead_test", srcs = ["gcp_kms_aead_test.cc"], deps = [ ":gcp_kms_aead", "@com_github_grpc_grpc//:grpc++", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_googleapis//google/cloud/kms/v1:kms_cc_grpc", "@com_google_googletest//:gtest_main", "@google_cloud_cpp//:kms", "@google_cloud_cpp//:kms_mocks", "@tink_cc//util:status", "@tink_cc//util:statusor", "@tink_cc//util:test_matchers", "@tink_cc//util:test_util", ], ) cc_test( name = "gcp_kms_public_key_sign_test", srcs = ["gcp_kms_public_key_sign_test.cc"], deps = [ ":gcp_kms_public_key_sign", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_googletest//:gtest_main", "@google_cloud_cpp//:kms", "@google_cloud_cpp//:kms_mocks", "@tink_cc//util:statusor", "@tink_cc//util:test_matchers", "@tink_cc//util:test_util", ], ) ================================================ FILE: cc/integration/gcpkms/WORKSPACE ================================================ workspace(name = "tink_cc_gcpkms") local_repository( name = "tink_cc", path = "../../../cc", ) load("@tink_cc//:tink_cc_deps.bzl", "tink_cc_deps") tink_cc_deps() load("@tink_cc//:tink_cc_deps_init.bzl", "tink_cc_deps_init") tink_cc_deps_init() load("@tink_cc_gcpkms//:tink_cc_gcpkms_deps.bzl", "tink_cc_gcpkms_deps") tink_cc_gcpkms_deps() load("@tink_cc_gcpkms//:tink_cc_gcpkms_deps_init.bzl", "tink_cc_gcpkms_deps_init") tink_cc_gcpkms_deps_init(register_go = True) ================================================ FILE: cc/integration/gcpkms/gcp_kms_aead.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/integration/gcpkms/gcp_kms_aead.h" #include #include #include "google/cloud/kms/v1/service.grpc.pb.h" #include "grpcpp/client_context.h" #include "grpcpp/support/status.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "third_party/cloud_cpp/google/cloud/kms/v1/key_management_client.h" #include "third_party/re2/re2.h" #include "tink/aead.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace integration { namespace gcpkms { static constexpr LazyRE2 kKmsKeyNameFormat = { "projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/.*"}; using ::google::cloud::kms::v1::DecryptRequest; using ::google::cloud::kms::v1::DecryptResponse; using ::google::cloud::kms::v1::EncryptRequest; using ::google::cloud::kms::v1::EncryptResponse; using ::google::cloud::kms::v1::KeyManagementService; util::StatusOr> NewGcpKmsAead( absl::string_view key_name, std::shared_ptr kms_client) { if (!RE2::FullMatch(key_name, *kKmsKeyNameFormat)) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat(key_name, " does not match the KMS key name format: ", kKmsKeyNameFormat->pattern())); } if (kms_client == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "KMS client cannot be null."); } return absl::WrapUnique(new GcpKmsAead(key_name, kms_client)); } util::StatusOr> GcpKmsAead::New( absl::string_view key_name, std::shared_ptr kms_stub) { if (!RE2::FullMatch(key_name, *kKmsKeyNameFormat)) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat(key_name, " does not match the KMS key name format: ", kKmsKeyNameFormat->pattern())); } if (kms_stub == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "KMS stub cannot be null."); } return absl::WrapUnique(new GcpKmsAead(key_name, kms_stub)); } util::StatusOr GcpKmsAead::Encrypt( absl::string_view plaintext, absl::string_view associated_data) const { EncryptRequest req; req.set_name(key_name_); req.set_plaintext(std::string(plaintext)); req.set_additional_authenticated_data(std::string(associated_data)); if (kms_client_) { auto response = kms_client_->Encrypt(req); if (!response.ok()) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("GCP KMS encryption failed: ", response.status().message())); } return response->ciphertext(); } EncryptResponse resp; grpc::ClientContext context; context.AddMetadata("x-goog-request-params", absl::StrCat("name=", key_name_)); grpc::Status status = kms_stub_->Encrypt(&context, req, &resp); if (!status.ok()) { return util::Status( static_cast(status.error_code()), absl::StrCat("GCP KMS encryption failed: ", status.error_message())); } return resp.ciphertext(); } util::StatusOr GcpKmsAead::Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const { DecryptRequest req; req.set_name(key_name_); req.set_ciphertext(std::string(ciphertext)); req.set_additional_authenticated_data(std::string(associated_data)); if (kms_client_) { auto response = kms_client_->Decrypt(req); if (!response.ok()) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("GCP KMS decryption failed: ", response.status().message())); } return response->plaintext(); } DecryptResponse resp; grpc::ClientContext context; context.AddMetadata("x-goog-request-params", absl::StrCat("name=", key_name_)); grpc::Status status = kms_stub_->Decrypt(&context, req, &resp); if (!status.ok()) { return util::Status( static_cast(status.error_code()), absl::StrCat("GCP KMS decryption failed: ", status.error_message())); } return resp.plaintext(); } } // namespace gcpkms } // namespace integration } // namespace tink } // namespace crypto ================================================ FILE: cc/integration/gcpkms/gcp_kms_aead.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTEGRATION_GCPKMS_GCP_KMS_AEAD_H_ #define TINK_INTEGRATION_GCPKMS_GCP_KMS_AEAD_H_ #include #include #include "google/cloud/kms/v1/service.grpc.pb.h" #include "absl/strings/string_view.h" #include "third_party/cloud_cpp/google/cloud/kms/v1/key_management_client.h" #include "tink/aead.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace integration { namespace gcpkms { // GcpKmsAead is an implementation of AEAD that forwards encryption/decryption // requests to the Google Cloud KMS (https://cloud.google.com/kms/). class GcpKmsAead : public Aead { public: // Move only. GcpKmsAead(GcpKmsAead&& other) = default; GcpKmsAead& operator=(GcpKmsAead&& other) = default; GcpKmsAead(const GcpKmsAead&) = delete; GcpKmsAead& operator=(const GcpKmsAead&) = delete; // Creates a new GcpKmsAead that is bound to the key specified in `key_name`, // and that uses the channel when communicating with the KMS. // // Valid values for `key_name` have the following format: // projects/*/locations/*/keyRings/*/cryptoKeys/*. // See https://cloud.google.com/kms/docs/object-hierarchy for more info. static crypto::tink::util::StatusOr> New( absl::string_view key_name, std::shared_ptr kms_stub); crypto::tink::util::StatusOr Encrypt( absl::string_view plaintext, absl::string_view associated_data) const override; crypto::tink::util::StatusOr Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const override; private: explicit GcpKmsAead( absl::string_view key_name, std::shared_ptr kms_stub) : key_name_(key_name), kms_stub_(kms_stub) {} explicit GcpKmsAead( absl::string_view key_name, std::shared_ptr kms_client) : key_name_(key_name), kms_client_(kms_client) {} friend crypto::tink::util::StatusOr> NewGcpKmsAead( absl::string_view key_name, std::shared_ptr kms_client); // The location of a crypto key in GCP KMS. std::string key_name_; std::shared_ptr kms_stub_; std::shared_ptr kms_client_; }; // Creates a new `GcpKmsAead` object that is bound to the key specified in // `key_name`, and that uses the `kms_client` to communicate with the KMS. // // Valid values for `key_name` have the following format: // projects/*/locations/*/keyRings/*/cryptoKeys/*. // See https://cloud.google.com/kms/docs/object-hierarchy for more info. crypto::tink::util::StatusOr> NewGcpKmsAead( absl::string_view key_name, std::shared_ptr kms_client); } // namespace gcpkms } // namespace integration } // namespace tink } // namespace crypto #endif // TINK_INTEGRATION_GCPKMS_GCP_KMS_AEAD_H_ ================================================ FILE: cc/integration/gcpkms/gcp_kms_aead_integration_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include "google/cloud/kms/v1/service.grpc.pb.h" #include "grpcpp/channel.h" #include "grpcpp/create_channel.h" #include "grpcpp/security/credentials.h" #include "gtest/gtest.h" #include "absl/log/check.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/integration/gcpkms/gcp_kms_aead.h" #include "tink/integration/gcpkms/gcp_kms_client.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tools/cpp/runfiles/runfiles.h" namespace crypto { namespace tink { namespace integration { namespace gcpkms { namespace { using ::bazel::tools::cpp::runfiles::Runfiles; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::google::cloud::kms::v1::KeyManagementService; using ::testing::Environment; using ::testing::Not; constexpr absl::string_view kGcpKmsKeyUri = "gcp-kms://projects/tink-test-infrastructure/locations/global/keyRings/" "unit-and-integration-testing/cryptoKeys/aead-key"; constexpr absl::string_view kGcpKmsKeyName = "projects/tink-test-infrastructure/locations/global/keyRings/" "unit-and-integration-testing/cryptoKeys/aead-key"; std::string RunfilesPath(absl::string_view path) { std::string error; std::unique_ptr runfiles(Runfiles::CreateForTest(&error)); CHECK(runfiles != nullptr) << "Unable to determine runfile path: "; const char* workspace_dir = getenv("TEST_WORKSPACE"); CHECK(workspace_dir != nullptr && workspace_dir[0] != '\0') << "Unable to determine workspace name."; return runfiles->Rlocation(absl::StrCat(workspace_dir, "/", path)); } class GcpKmsAeadIntegrationTestEnvironment : public Environment { public: ~GcpKmsAeadIntegrationTestEnvironment() override = default; void SetUp() override { // Set root certificates for gRPC in Bazel Test which are needed on macOS. const char* test_srcdir = getenv("TEST_SRCDIR"); if (test_srcdir != nullptr) { setenv( "GRPC_DEFAULT_SSL_ROOTS_FILE_PATH", absl::StrCat(test_srcdir, "/google_root_pem/file/downloaded").c_str(), /*overwrite=*/false); } } }; Environment* const foo_env = testing::AddGlobalTestEnvironment( new GcpKmsAeadIntegrationTestEnvironment()); TEST(GcpKmsAeadIntegrationTest, EncryptDecrypt) { std::string credentials = RunfilesPath("testdata/gcp/credential.json"); util::StatusOr> client = GcpKmsClient::New(/*key_uri=*/"", credentials); ASSERT_THAT(client, IsOk()); util::StatusOr> aead = (*client)->GetAead(kGcpKmsKeyUri); ASSERT_THAT(aead, IsOk()); constexpr absl::string_view kPlaintext = "plaintext"; constexpr absl::string_view kAssociatedData = "associatedData"; util::StatusOr ciphertext = (*aead)->Encrypt(kPlaintext, kAssociatedData); ASSERT_THAT(ciphertext, IsOk()); EXPECT_THAT((*aead)->Decrypt(*ciphertext, kAssociatedData), IsOkAndHolds(kPlaintext)); EXPECT_THAT((*aead)->Decrypt(*ciphertext, "invalidAssociatedData"), Not(IsOk())); } util::StatusOr ReadFile(const std::string& filename) { std::ifstream input_stream; input_stream.open(filename, std::ifstream::in); if (!input_stream.is_open()) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Error opening file ", filename)); } std::stringstream input; input << input_stream.rdbuf(); input_stream.close(); return input.str(); } TEST(GcpKmsAeadIntegrationTest, GcpKmsAeadNewWorks) { // Read credentials file. std::string credentials_path = RunfilesPath("testdata/gcp/credential.json"); util::StatusOr json_creds = ReadFile(credentials_path); ASSERT_THAT(json_creds, IsOk()); // Create a GCP KMS stub. std::shared_ptr creds = grpc::ServiceAccountJWTAccessCredentials(*json_creds); std::shared_ptr channel_creds = grpc::SslCredentials(grpc::SslCredentialsOptions()); std::shared_ptr credentials = grpc::CompositeChannelCredentials(channel_creds, creds); grpc::ChannelArguments args; args.SetUserAgentPrefix("Tink Test CPP"); std::shared_ptr kms_stub = KeyManagementService::NewStub(grpc::CreateCustomChannel( "cloudkms.googleapis.com", credentials, args)); util::StatusOr> aead = GcpKmsAead::New(kGcpKmsKeyName, kms_stub); ASSERT_THAT(aead, IsOk()); constexpr absl::string_view kPlaintext = "plaintext"; constexpr absl::string_view kAssociatedData = "associatedData"; util::StatusOr ciphertext = (*aead)->Encrypt(kPlaintext, kAssociatedData); ASSERT_THAT(ciphertext, IsOk()); EXPECT_THAT((*aead)->Decrypt(*ciphertext, kAssociatedData), IsOkAndHolds(kPlaintext)); EXPECT_THAT((*aead)->Decrypt(*ciphertext, "invalidAssociatedData"), Not(IsOk())); } } // namespace } // namespace gcpkms } // namespace integration } // namespace tink } // namespace crypto ================================================ FILE: cc/integration/gcpkms/gcp_kms_aead_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/integration/gcpkms/gcp_kms_aead.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "third_party/cloud_cpp/google/cloud/kms/v1/key_management_client.h" #include "third_party/cloud_cpp/google/cloud/kms/v1/mocks/mock_key_management_connection.h" #include "third_party/cloud_cpp/google/cloud/status.h" #include "tink/aead.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace integration { namespace gcpkms { namespace kmsV1 = ::google::cloud::kms::v1; using ::crypto::tink::test::DummyAead; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::google::cloud::Status; using ::google::cloud::StatusOr; using ::google::cloud::kms_v1::KeyManagementServiceClient; using ::google::cloud::kms_v1_mocks::MockKeyManagementServiceConnection; using ::testing::HasSubstr; constexpr absl::string_view kAad1 = "additional authenticated data1"; constexpr absl::string_view kAad2 = "additional authenticated data2"; constexpr absl::string_view kPlaintext = "plaintext"; constexpr absl::string_view kKeyName = "projects/project1/locations/global/keyRings/key1/cryptoKeys/aead-key"; class TestGcpKmsAead : public testing::Test { public: TestGcpKmsAead() : mock_connection_( std::make_shared()), kms_client_( std::make_shared( mock_connection_)) {} void ExpectEncrypt(const DummyAead& aead, int times) { EXPECT_CALL(*mock_connection_, Encrypt) .Times(times) .WillRepeatedly([&](kmsV1::EncryptRequest const& request) -> StatusOr { auto ciphertext = aead.Encrypt( request.plaintext(), request.additional_authenticated_data()); kmsV1::EncryptResponse response; response.set_ciphertext(*ciphertext); return StatusOr(response); }); } void ExpectDecrypt(const DummyAead& aead, int times) { EXPECT_CALL(*mock_connection_, Decrypt) .Times(times) .WillRepeatedly([&](kmsV1::DecryptRequest const& request) -> StatusOr { util::StatusOr plaintext = aead.Decrypt( request.ciphertext(), request.additional_authenticated_data()); if (!plaintext.ok()) { return Status(google::cloud::StatusCode::kInvalidArgument, "Decryption failed."); } kmsV1::DecryptResponse response; response.set_plaintext(*plaintext); return StatusOr(response); }); } protected: std::shared_ptr mock_connection_; std::shared_ptr kms_client_; }; TEST_F(TestGcpKmsAead, FailsWithNullKmsClient) { EXPECT_THAT(NewGcpKmsAead(kKeyName, nullptr).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("KMS client cannot be null"))); } TEST_F(TestGcpKmsAead, FailsWithEmptyKeyName) { EXPECT_THAT(NewGcpKmsAead("", kms_client_).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("does not match"))); } TEST_F(TestGcpKmsAead, FailsWithWrongKeyName) { EXPECT_THAT(NewGcpKmsAead("Wrong/Key/Name", kms_client_).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("does not match"))); } TEST_F(TestGcpKmsAead, EncryptionDecryptionWorks) { auto kmsAead = NewGcpKmsAead(kKeyName, kms_client_); EXPECT_THAT(kmsAead.status(), IsOk()); DummyAead aead = DummyAead(kKeyName); // There are 9 encryption calls and 3 decryption calls in total. ExpectEncrypt(aead, 9); ExpectDecrypt(aead, 3); EXPECT_THAT(kmsAead->get()->Encrypt(kPlaintext, kAad1), IsOkAndHolds(*aead.Encrypt(kPlaintext, kAad1))); EXPECT_THAT(kmsAead->get()->Encrypt(kPlaintext, kAad2), IsOkAndHolds(*aead.Encrypt(kPlaintext, kAad2))); // Different AADs generate different ciphertexts. EXPECT_NE(*kmsAead->get()->Encrypt(kPlaintext, kAad1), *kmsAead->get()->Encrypt(kPlaintext, kAad2)); // Decryption works. EXPECT_THAT(kmsAead->get()->Decrypt( *kmsAead->get()->Encrypt(kPlaintext, kAad1), kAad1), IsOkAndHolds(*aead.Decrypt( *kmsAead->get()->Encrypt(kPlaintext, kAad1), kAad1))); EXPECT_THAT(kmsAead->get()->Decrypt( *kmsAead->get()->Encrypt(kPlaintext, kAad2), kAad2), IsOkAndHolds(*aead.Decrypt( *kmsAead->get()->Encrypt(kPlaintext, kAad2), kAad2))); // Decryption with a different AAD fails. EXPECT_THAT(kmsAead->get() ->Decrypt(*kmsAead->get()->Encrypt(kPlaintext, kAad1), kAad2) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("KMS decryption failed"))); } } // namespace gcpkms } // namespace integration } // namespace tink } // namespace crypto ================================================ FILE: cc/integration/gcpkms/gcp_kms_client.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/integration/gcpkms/gcp_kms_client.h" #include #include #include #include #include #include #include "grpcpp/channel.h" #include "grpcpp/create_channel.h" #include "grpcpp/security/credentials.h" #include "grpcpp/support/channel_arguments.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/match.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/integration/gcpkms/gcp_kms_aead.h" #include "tink/kms_clients.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/version.h" namespace crypto { namespace tink { namespace integration { namespace gcpkms { namespace { using ::google::cloud::kms::v1::KeyManagementService; static constexpr absl::string_view kKeyUriPrefix = "gcp-kms://"; static constexpr absl::string_view kGcpKmsServer = "cloudkms.googleapis.com"; static constexpr absl::string_view kTinkUserAgentPrefix = "Tink/"; util::StatusOr ReadFile(absl::string_view filename) { std::ifstream input_stream; input_stream.open(std::string(filename), std::ifstream::in); if (!input_stream.is_open()) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Error reading file ", filename)); } std::stringstream input; input << input_stream.rdbuf(); input_stream.close(); return input.str(); } util::StatusOr> GetCredentials( absl::string_view credentials_path) { if (credentials_path.empty()) { std::shared_ptr creds = grpc::GoogleDefaultCredentials(); if (creds == nullptr) { return util::Status(absl::StatusCode::kInternal, "Could not read default credentials"); } return creds; } // Try reading credentials from a file. util::StatusOr json_creds_result = ReadFile(credentials_path); if (!json_creds_result.ok()) { return json_creds_result.status(); } std::shared_ptr creds = grpc::ServiceAccountJWTAccessCredentials(json_creds_result.value()); if (creds == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Could not load credentials from file ", credentials_path)); } // Creating "empty" 'channel_creds', to convert 'creds' to ChannelCredentials // via CompositeChannelCredentials(). std::shared_ptr channel_creds = grpc::SslCredentials(grpc::SslCredentialsOptions()); return grpc::CompositeChannelCredentials(channel_creds, creds); } // Returns GCP KMS key name contained in `key_uri`. If `key_uri` does not refer // to a GCP key, returns an error status. util::StatusOr GetKeyName(absl::string_view key_uri) { if (!absl::StartsWithIgnoreCase(key_uri, kKeyUriPrefix)) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("The key URI ", key_uri, " does not start with ", kKeyUriPrefix)); } return std::string(key_uri.substr(kKeyUriPrefix.length())); } } // namespace util::StatusOr> GcpKmsClient::New( absl::string_view key_uri, absl::string_view credentials_path) { // Empty key name by default. std::string key_name = ""; if (!key_uri.empty()) { util::StatusOr key_name_from_uri = GetKeyName(key_uri); if (!key_name_from_uri.ok()) { return key_name_from_uri.status(); } key_name = key_name_from_uri.value(); } // Read credentials. util::StatusOr> creds_result = GetCredentials(credentials_path); if (!creds_result.ok()) { return creds_result.status(); } // Create a KMS stub. grpc::ChannelArguments args; args.SetUserAgentPrefix( absl::StrCat(kTinkUserAgentPrefix, Version::kTinkVersion, " CPP")); std::shared_ptr kms_stub = KeyManagementService::NewStub(grpc::CreateCustomChannel( std::string(kGcpKmsServer), creds_result.value(), args)); return absl::WrapUnique(new GcpKmsClient(key_name, std::move(kms_stub))); } bool GcpKmsClient::DoesSupport(absl::string_view key_uri) const { util::StatusOr key_name = GetKeyName(key_uri); if (!key_name.ok()) { return false; } return key_name_.empty() ? true : key_name_ == *key_name; } util::StatusOr> GcpKmsClient::GetAead( absl::string_view key_uri) const { util::StatusOr key_name_from_key_uri = GetKeyName(key_uri); // key_uri is invalid. if (!key_name_from_key_uri.ok()) { return key_name_from_key_uri.status(); } // key_uri is valid, but if key_name_ is not empty key_name_from_key_uri must // be equal to key_name_. if (!key_name_.empty() && key_name_ != *key_name_from_key_uri) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("This client is bound to ", key_name_, " and cannot use key ", key_uri)); } return GcpKmsAead::New(*key_name_from_key_uri, kms_stub_); } util::Status GcpKmsClient::RegisterNewClient( absl::string_view key_uri, absl::string_view credentials_path) { auto client_result = GcpKmsClient::New(key_uri, credentials_path); if (!client_result.ok()) { return client_result.status(); } return KmsClients::Add(std::move(client_result.value())); } } // namespace gcpkms } // namespace integration } // namespace tink } // namespace crypto ================================================ FILE: cc/integration/gcpkms/gcp_kms_client.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTEGRATION_GCPKMS_GCP_KMS_CLIENT_H_ #define TINK_INTEGRATION_GCPKMS_GCP_KMS_CLIENT_H_ #include #include #include #include "google/cloud/kms/v1/service.grpc.pb.h" #include "grpcpp/channel.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/kms_client.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace integration { namespace gcpkms { // GcpKmsClient is an implementation of KmsClient for Google Cloud KMS // (https://cloud.google.com/kms/). class GcpKmsClient : public crypto::tink::KmsClient { public: // Move only. GcpKmsClient(GcpKmsClient&& other) = default; GcpKmsClient& operator=(GcpKmsClient&& other) = default; GcpKmsClient(const GcpKmsClient&) = delete; GcpKmsClient& operator=(const GcpKmsClient&) = delete; // Creates a new GcpKmsClient that is bound to the key specified in `key_uri`, // and that uses the specified credentials when communicating with the KMS. // // Either argument can be empty. // If `key_uri` is empty, then the client is not bound to any particular key. // If `credential_path` is empty, then default credentials will be used. static crypto::tink::util::StatusOr> New( absl::string_view key_uri, absl::string_view credentials_path); // Creates a new client and adds it to the global list of KMSClients. // // This function should only be called on startup and not on every operation. // Avoid registering a client more than once. // // It is often not necessary to use this function. Instead, you can call // GcpKmsAead::New to directly create an Aead object without creating or // registering a client. static crypto::tink::util::Status RegisterNewClient( absl::string_view key_uri, absl::string_view credentials_path); // Returns true iff this client does support KMS key specified by `key_uri`. bool DoesSupport(absl::string_view key_uri) const override; // Returns an Aead-primitive backed by KMS key specified by `key_uri`, // provided that this KmsClient does support `key_uri`. crypto::tink::util::StatusOr> GetAead( absl::string_view key_uri) const override; private: explicit GcpKmsClient( std::string key_name, std::shared_ptr kms_stub) : key_name_(key_name), kms_stub_(std::move(kms_stub)) {} std::string key_name_; std::shared_ptr kms_stub_; }; } // namespace gcpkms } // namespace integration } // namespace tink } // namespace crypto #endif // TINK_INTEGRATION_GCPKMS_GCP_KMS_CLIENT_H_ ================================================ FILE: cc/integration/gcpkms/gcp_kms_client_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/integration/gcpkms/gcp_kms_client.h" #include #include #include #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/kms_clients.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace integration { namespace gcpkms { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; TEST(GcpKmsClientTest, ClientNotBoundToAKey) { std::string gcp_key1 = "gcp-kms://projects/someProject/.../cryptoKeys/key1"; std::string gcp_key2 = "gcp-kms://projects/otherProject/.../cryptoKeys/key2"; std::string non_gcp_key = "aws-kms://arn:aws:kms:us-west-2:acc:other/key3"; std::string creds_file = std::string(getenv("TEST_SRCDIR")) + "/tink_cc_gcpkms/testdata/gcp/credential.json"; util::StatusOr> client = GcpKmsClient::New("", creds_file); ASSERT_THAT(client, IsOk()); EXPECT_TRUE((*client)->DoesSupport(gcp_key1)); EXPECT_TRUE((*client)->DoesSupport(gcp_key2)); EXPECT_FALSE((*client)->DoesSupport(non_gcp_key)); } TEST(GcpKmsClientTest, ClientBoundToASpecificKey) { std::string gcp_key1 = "gcp-kms://projects/someProject/.../cryptoKeys/key1"; std::string gcp_key2 = "gcp-kms://projects/otherProject/.../cryptoKeys/key2"; std::string non_gcp_key = "aws-kms://arn:aws:kms:us-west-2:acc:other/key3"; std::string creds_file = std::string(getenv("TEST_SRCDIR")) + "/tink_cc_gcpkms/testdata/gcp/credential.json"; util::StatusOr> client = GcpKmsClient::New(gcp_key1, creds_file); ASSERT_THAT(client, IsOk()); EXPECT_TRUE((*client)->DoesSupport(gcp_key1)); EXPECT_FALSE((*client)->DoesSupport(gcp_key2)); EXPECT_FALSE((*client)->DoesSupport(non_gcp_key)); } TEST(GcpKmsClientTest, ClientCreationAndRegistry) { std::string gcp_key1 = "gcp-kms://projects/someProject/.../cryptoKeys/key1"; std::string creds_file = absl::StrCat(getenv("TEST_SRCDIR"), "/tink_cc_gcpkms/testdata/gcp/credential.json"); util::Status client_result = GcpKmsClient::RegisterNewClient(gcp_key1, creds_file); ASSERT_THAT(client_result, IsOk()); util::StatusOr registry_result = KmsClients::Get(gcp_key1); EXPECT_THAT(registry_result, IsOk()); } TEST(GcpKmsClientTest, ClientCreationInvalidRegistry) { std::string non_gcp_key = "aws-kms://arn:aws:kms:us-west-2:acc:other/key3"; std::string creds_file = std::string(getenv("TEST_SRCDIR")) + "/tink_cc_gcpkms/testdata/gcp/credential.json"; util::Status client_result = GcpKmsClient::RegisterNewClient(non_gcp_key, creds_file); EXPECT_THAT(client_result, StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace gcpkms } // namespace integration } // namespace tink } // namespace crypto ================================================ FILE: cc/integration/gcpkms/gcp_kms_public_key_sign.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/integration/gcpkms/gcp_kms_public_key_sign.h" #include #include #include #include "absl/base/nullability.h" #include "absl/crc/crc32c.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "third_party/cloud_cpp/google/cloud/kms/v1/key_management_client.h" #include "third_party/cloud_cpp/google/cloud/status_or.h" #include "openssl/base.h" #include "openssl/digest.h" #include "third_party/re2/re2.h" #include "tink/public_key_sign.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace integration { namespace gcpkms { namespace { using ::crypto::tink::util::StatusOr; using ::google::cloud::kms::v1::AsymmetricSignRequest; using ::google::cloud::kms::v1::AsymmetricSignResponse; using ::google::cloud::kms::v1::CryptoKeyVersion; using ::google::cloud::kms::v1::Digest; using ::google::cloud::kms::v1::GetPublicKeyRequest; using ::google::cloud::kms::v1::ProtectionLevel; using ::google::cloud::kms::v1::PublicKey; using ::google::cloud::kms_v1::KeyManagementServiceClient; // Maximum size of the data that can be signed. static constexpr int kMaxSignDataSize = 64 * 1024; static constexpr LazyRE2 kKmsKeyNameFormat = { "projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+/" "cryptoKeyVersions/.*"}; // Some AsymmetricSign algorithms require data as input and some other // operate on a digest of the data. This method determines if data itself is // required for signing and returns true if so. bool RequiresDataForSign(CryptoKeyVersion::CryptoKeyVersionAlgorithm algorithm, ProtectionLevel protection_level) { // Operate on the data if the algorithm is one of the followings: switch (algorithm) { case CryptoKeyVersion::RSA_SIGN_RAW_PKCS1_2048: case CryptoKeyVersion::RSA_SIGN_RAW_PKCS1_3072: case CryptoKeyVersion::RSA_SIGN_RAW_PKCS1_4096: return true; default: break; } // or the protection level is one of the followings: switch (protection_level) { case ProtectionLevel::EXTERNAL: case ProtectionLevel::EXTERNAL_VPC: return true; default: break; } return false; } // Finds out and returns the proper DigestCase for the given algorithm. StatusOr GetDigestFromAlgorithm( CryptoKeyVersion::CryptoKeyVersionAlgorithm algorithm) { switch (algorithm) { case CryptoKeyVersion::EC_SIGN_P256_SHA256: case CryptoKeyVersion::EC_SIGN_SECP256K1_SHA256: case CryptoKeyVersion::RSA_SIGN_PSS_2048_SHA256: case CryptoKeyVersion::RSA_SIGN_PSS_3072_SHA256: case CryptoKeyVersion::RSA_SIGN_PSS_4096_SHA256: case CryptoKeyVersion::RSA_SIGN_PKCS1_2048_SHA256: case CryptoKeyVersion::RSA_SIGN_PKCS1_3072_SHA256: case CryptoKeyVersion::RSA_SIGN_PKCS1_4096_SHA256: return Digest::DigestCase::kSha256; case CryptoKeyVersion::EC_SIGN_P384_SHA384: return Digest::DigestCase::kSha384; case CryptoKeyVersion::RSA_SIGN_PSS_4096_SHA512: case CryptoKeyVersion::RSA_SIGN_PKCS1_4096_SHA512: return Digest::DigestCase::kSha512; default: return absl::InternalError(absl::StrCat( "The given algorithm ", CryptoKeyVersion::CryptoKeyVersionAlgorithm_Name(algorithm), " does not support digests.")); } } StatusOr ComputeDigest(absl::string_view data, Digest::DigestCase digest_case) { const EVP_MD* md; switch (digest_case) { case Digest::kSha256: md = EVP_sha256(); break; case Digest::kSha384: md = EVP_sha384(); break; case Digest::kSha512: md = EVP_sha512(); break; default: return util::Status(absl::StatusCode::kInternal, absl::StrCat("Invalid DigestCase: ", digest_case)); } unsigned int digest_size; uint8_t digest[EVP_MAX_MD_SIZE]; if (EVP_Digest(data.data(), data.size(), digest, &digest_size, md, /*impl=*/nullptr) != 1) { return util::Status(absl::StatusCode::kInternal, "Error computing the digest."); } return std::string(reinterpret_cast(digest), digest_size); } // Builds and returns an AsymmetricSignRequest. // It determines whether data or digest is required for signing, // and prepares the request accordingly. StatusOr BuildAsymmetricSignRequest( absl::string_view key_name, absl::string_view data, PublicKey public_key) { AsymmetricSignRequest request; request.set_name(key_name); if (RequiresDataForSign(public_key.algorithm(), public_key.protection_level())) { request.set_data(data); request.mutable_data_crc32c()->set_value( static_cast(absl::ComputeCrc32c(data))); return request; } // Digest is needed; compute it. StatusOr digest_case = GetDigestFromAlgorithm(public_key.algorithm()); if (!digest_case.ok()) { return digest_case.status(); } StatusOr digest_string = ComputeDigest(data, *digest_case); if (!digest_string.ok()) { return digest_string.status(); } switch (*digest_case) { case Digest::kSha256: request.mutable_digest()->set_sha256(*digest_string); break; case Digest::kSha384: request.mutable_digest()->set_sha384(*digest_string); break; case Digest::kSha512: request.mutable_digest()->set_sha512(*digest_string); break; default: return util::Status(absl::StatusCode::kInternal, absl::StrCat("Invalid DigestCase: ", *digest_case)); } request.mutable_digest_crc32c()->set_value( static_cast(absl::ComputeCrc32c(*digest_string))); return request; } // GcpKmsPublicKeySign is an implementation of PublicKeySign that forwards // asymmetric sign requests to Google Cloud KMS (https://cloud.google.com/kms/). class GcpKmsPublicKeySign : public PublicKeySign { public: crypto::tink::util::StatusOr Sign( absl::string_view data) const override; GcpKmsPublicKeySign( absl::string_view key_name, google::cloud::kms::v1::PublicKey public_key, std::shared_ptr kms_client) : key_name_(key_name), public_key_(public_key), kms_client_(kms_client) {} private: // The location of a crypto key in GCP KMS. std::string key_name_; google::cloud::kms::v1::PublicKey public_key_; std::shared_ptr kms_client_; }; StatusOr GcpKmsPublicKeySign::Sign(absl::string_view data) const { if (data.size() > kMaxSignDataSize) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("The input data (", data.size(), " bytes) is larger than the allowed limit (", kMaxSignDataSize, " bytes).")); } // Build the sign request. StatusOr request = BuildAsymmetricSignRequest(key_name_, data, public_key_); if (!request.ok()) { return request.status(); } // Send the request to KMS for signing. google::cloud::StatusOr response = kms_client_->AsymmetricSign(*request); if (!response.ok()) { return util::Status(absl::StatusCode::kInternal, absl::StrCat("GCP KMS AsymmetricSign failed: ", response.status().message())); } // Perform integrity checks. if (response->name() != key_name_) { return util::Status(absl::StatusCode::kInternal, absl::StrCat("The key name in the response does not " "match the requested key name.", response.status().message())); } if (!response->verified_data_crc32c() && !response->verified_digest_crc32c()) { return util::Status(absl::StatusCode::kInternal, absl::StrCat("Checking the input checksum failed.", response.status().message())); } uint32_t given_crc32c = static_cast(response->signature_crc32c().value()); uint32_t computed_crc32c = static_cast(absl::ComputeCrc32c(response->signature())); if (computed_crc32c != given_crc32c) { return util::Status(absl::StatusCode::kInternal, absl::StrCat("Signature checksum mismatch.", response.status().message())); } // Return the signature. return response->signature(); } } // namespace StatusOr> CreateGcpKmsPublicKeySign( absl::string_view key_name, absl::Nonnull> kms_client) { if (!RE2::FullMatch(key_name, *kKmsKeyNameFormat)) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat(key_name, " does not match the KMS key name format: ", kKmsKeyNameFormat->pattern())); } if (kms_client == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "KMS client cannot be null."); } // Retrieve the related public key from KMS, that contains information on // how to prepare the later AsymmetricSign requests. GetPublicKeyRequest request; request.set_name(key_name); google::cloud::StatusOr response = kms_client->GetPublicKey(request); if (!response.ok()) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("GCP KMS GetPublicKey failed: ", response.status().message())); } return absl::make_unique(key_name, *response, kms_client); } } // namespace gcpkms } // namespace integration } // namespace tink } // namespace crypto ================================================ FILE: cc/integration/gcpkms/gcp_kms_public_key_sign.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTEGRATION_GCPKMS_GCP_KMS_PUBLIC_KEY_SIGN_H_ #define TINK_INTEGRATION_GCPKMS_GCP_KMS_PUBLIC_KEY_SIGN_H_ #include #include "absl/base/nullability.h" #include "absl/strings/string_view.h" #include "third_party/cloud_cpp/google/cloud/kms/v1/key_management_client.h" #include "tink/public_key_sign.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace integration { namespace gcpkms { // Creates a new PublicKeySign object that is bound to the key specified // in `key_name`, and that uses the `kms_client` to communicate with the KMS. // // Valid values for `key_name` have the following format: // projects/*/locations/*/keyRings/*/cryptoKeys/*/cryptoKeyVersions/*. // See https://cloud.google.com/kms/docs/object-hierarchy for more info. crypto::tink::util::StatusOr> CreateGcpKmsPublicKeySign( absl::string_view key_name, absl::Nonnull< std::shared_ptr> kms_client); } // namespace gcpkms } // namespace integration } // namespace tink } // namespace crypto #endif // TINK_INTEGRATION_GCPKMS_GCP_KMS_PUBLIC_KEY_SIGN_H_ ================================================ FILE: cc/integration/gcpkms/gcp_kms_public_key_sign_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/integration/gcpkms/gcp_kms_public_key_sign.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/crc/crc32c.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "third_party/cloud_cpp/google/cloud/kms/v1/key_management_client.h" #include "third_party/cloud_cpp/google/cloud/kms/v1/mocks/mock_key_management_connection.h" #include "third_party/cloud_cpp/google/cloud/status.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace integration { namespace gcpkms { namespace { namespace kmsV1 = ::google::cloud::kms::v1; using ::crypto::tink::test::DummyPublicKeySign; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::google::cloud::Status; using ::google::cloud::StatusOr; using ::google::cloud::kms_v1::KeyManagementServiceClient; using ::google::cloud::kms_v1_mocks::MockKeyManagementServiceConnection; using ::testing::HasSubstr; constexpr absl::string_view kData = "data for signing"; constexpr absl::string_view kDigest = "digest for signing"; constexpr absl::string_view kKeyNameRequiresData1 = "projects/P1/locations/L1/keyRings/R1/cryptoKeys/K1/cryptoKeyVersions/1"; constexpr absl::string_view kKeyNameRequiresData2 = "projects/P1/locations/L1/keyRings/R1/cryptoKeys/K1/cryptoKeyVersions/2"; constexpr absl::string_view kKeyNameRequiresDigest = "projects/P1/locations/L1/keyRings/R1/cryptoKeys/K1/cryptoKeyVersions/3"; constexpr absl::string_view kKeyNameErrorGetPublicKey = "projects/P1/locations/L1/keyRings/R1/cryptoKeys/K1/cryptoKeyVersions/4"; constexpr absl::string_view kKeyNameErrorAsymmetricSign = "projects/P1/locations/L1/keyRings/R1/cryptoKeys/K1/cryptoKeyVersions/5"; constexpr absl::string_view kKeyNameErrorCrc32c = "projects/P1/locations/L1/keyRings/R1/cryptoKeys/K1/cryptoKeyVersions/6"; constexpr absl::string_view kKeyNameErrorCrc32cNotVerified = "projects/P1/locations/L1/keyRings/R1/cryptoKeys/K1/cryptoKeyVersions/7"; constexpr absl::string_view kKeyNameErrorWrongKeyName = "projects/P1/locations/L1/keyRings/R1/cryptoKeys/K1/cryptoKeyVersions/8"; class TestGcpKmsPublicKeySign : public testing::Test { public: TestGcpKmsPublicKeySign() : mock_connection_( std::make_shared()), kms_client_( std::make_shared(mock_connection_)) {} void ExpectSign(const DummyPublicKeySign& signer, int times) { EXPECT_CALL(*mock_connection_, AsymmetricSign) .Times(times) .WillRepeatedly([&](kmsV1::AsymmetricSignRequest const& request) -> StatusOr { if (request.name() == kKeyNameErrorAsymmetricSign) { return Status(google::cloud::StatusCode::kInternal, "Internal error"); } // Prepare response based on the given data/digest. kmsV1::AsymmetricSignResponse response; response.set_name(request.name()); if (request.has_digest()) { response.set_verified_digest_crc32c(true); response.set_signature(*signer.Sign(kDigest)); } else { response.set_verified_data_crc32c(true); response.set_signature(*signer.Sign(kData)); } response.mutable_signature_crc32c()->set_value( static_cast(absl::ComputeCrc32c(response.signature()))); // Manipulate the key name value for the: kKeyNameErrorWrongKeyName. if (request.name() == kKeyNameErrorWrongKeyName) { response.set_name(kKeyNameRequiresData1); } // Manipulate the crc32c value for the case: kKeyNameErrorCrc32c. if (request.name() == kKeyNameErrorCrc32c) { response.mutable_signature_crc32c()->set_value(1); } // Crc32c check failed, set both fields to false, for the case: // kKeyNameErrorCrc32cNotVerified. if (request.name() == kKeyNameErrorCrc32cNotVerified) { response.set_verified_data_crc32c(false); response.set_verified_digest_crc32c(false); } return StatusOr(response); }); } void ExpectGetPublicKey(int times) { EXPECT_CALL(*mock_connection_, GetPublicKey) .Times(times) .WillRepeatedly([&](kmsV1::GetPublicKeyRequest const& request) -> StatusOr { kmsV1::PublicKey response; if (request.name() == kKeyNameRequiresData1 || request.name() == kKeyNameErrorAsymmetricSign || request.name() == kKeyNameErrorCrc32c || request.name() == kKeyNameErrorCrc32cNotVerified || request.name() == kKeyNameErrorWrongKeyName) { // This operates on the data. response.set_algorithm( kmsV1::CryptoKeyVersion::RSA_SIGN_RAW_PKCS1_2048); response.set_protection_level(kmsV1::ProtectionLevel::SOFTWARE); } else if (request.name() == kKeyNameRequiresData2) { // This operates on the data. response.set_algorithm( kmsV1::CryptoKeyVersion::RSA_SIGN_PSS_2048_SHA256); response.set_protection_level(kmsV1::ProtectionLevel::EXTERNAL); } else if (request.name() == kKeyNameRequiresDigest) { // This operates on the digest. response.set_algorithm( kmsV1::CryptoKeyVersion::RSA_SIGN_PSS_2048_SHA256); response.set_protection_level(kmsV1::ProtectionLevel::SOFTWARE); } else if (request.name() == kKeyNameErrorGetPublicKey) { return Status(google::cloud::StatusCode::kInternal, "Internal error"); } return StatusOr(response); }); } protected: std::shared_ptr mock_connection_; std::shared_ptr kms_client_; }; TEST_F(TestGcpKmsPublicKeySign, NullKmsClientFails) { EXPECT_THAT( CreateGcpKmsPublicKeySign(kKeyNameRequiresData1, nullptr).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("KMS client cannot be null"))); } TEST_F(TestGcpKmsPublicKeySign, EmptyKeyNameFails) { EXPECT_THAT(CreateGcpKmsPublicKeySign("", kms_client_).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("does not match"))); } TEST_F(TestGcpKmsPublicKeySign, WrongKeyNameFails) { EXPECT_THAT(CreateGcpKmsPublicKeySign("Wrong/Key/Name", kms_client_).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("does not match"))); } TEST_F(TestGcpKmsPublicKeySign, GetPublicKeyFails) { ExpectGetPublicKey(1); auto kmsSigner = CreateGcpKmsPublicKeySign(kKeyNameErrorGetPublicKey, kms_client_); EXPECT_THAT(kmsSigner.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("GCP KMS GetPublicKey failed"))); } TEST_F(TestGcpKmsPublicKeySign, AsymmetricSignFails) { DummyPublicKeySign signer = DummyPublicKeySign(kKeyNameErrorAsymmetricSign); ExpectGetPublicKey(1); ExpectSign(signer, /*times*/ 1); auto kmsSigner = CreateGcpKmsPublicKeySign(kKeyNameErrorAsymmetricSign, kms_client_); EXPECT_THAT(kmsSigner.status(), IsOk()); EXPECT_THAT((*kmsSigner)->Sign(kData).status(), StatusIs(absl::StatusCode::kInternal, HasSubstr("GCP KMS AsymmetricSign failed"))); } TEST_F(TestGcpKmsPublicKeySign, WrongInputCrc32cFails) { DummyPublicKeySign signer = DummyPublicKeySign(kKeyNameErrorCrc32cNotVerified); ExpectGetPublicKey(1); ExpectSign(signer, /*times*/ 1); auto kmsSigner = CreateGcpKmsPublicKeySign(kKeyNameErrorCrc32cNotVerified, kms_client_); EXPECT_THAT(kmsSigner.status(), IsOk()); EXPECT_THAT((*kmsSigner)->Sign(kData).status(), StatusIs(absl::StatusCode::kInternal, HasSubstr("Checking the input checksum failed."))); } TEST_F(TestGcpKmsPublicKeySign, WrongSignatureCrc32cFails) { DummyPublicKeySign signer = DummyPublicKeySign(kKeyNameErrorCrc32c); ExpectGetPublicKey(1); ExpectSign(signer, /*times*/ 1); auto kmsSigner = CreateGcpKmsPublicKeySign(kKeyNameErrorCrc32c, kms_client_); EXPECT_THAT(kmsSigner.status(), IsOk()); EXPECT_THAT((*kmsSigner)->Sign(kData).status(), StatusIs(absl::StatusCode::kInternal, HasSubstr("Signature checksum mismatch"))); } TEST_F(TestGcpKmsPublicKeySign, LargeInputDataFails) { ExpectGetPublicKey(1); std::string large_data(64 * 1024 + 1, 'A'); auto kmsSigner = CreateGcpKmsPublicKeySign(kKeyNameRequiresData1, kms_client_); EXPECT_THAT(kmsSigner.status(), IsOk()); EXPECT_THAT( (*kmsSigner)->Sign(large_data).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("larger than"))); } TEST_F(TestGcpKmsPublicKeySign, WrongKeyNameInTheResponseFails) { DummyPublicKeySign signer = DummyPublicKeySign(kKeyNameErrorWrongKeyName); ExpectGetPublicKey(1); ExpectSign(signer, /*times*/ 1); auto kmsSigner = CreateGcpKmsPublicKeySign(kKeyNameErrorWrongKeyName, kms_client_); EXPECT_THAT(kmsSigner.status(), IsOk()); EXPECT_THAT((*kmsSigner)->Sign(kData).status(), StatusIs(absl::StatusCode::kInternal, HasSubstr("does not match the requested key name"))); } TEST_F(TestGcpKmsPublicKeySign, PublicKeySignDataOnAlgorithmSuccess) { DummyPublicKeySign signer = DummyPublicKeySign(kKeyNameRequiresData1); ExpectGetPublicKey(1); ExpectSign(signer, /*times*/ 1); auto kmsSigner = CreateGcpKmsPublicKeySign(kKeyNameRequiresData1, kms_client_); EXPECT_THAT(kmsSigner.status(), IsOk()); EXPECT_THAT((*kmsSigner)->Sign(kData), IsOkAndHolds(*signer.Sign(kData))); } TEST_F(TestGcpKmsPublicKeySign, PublicKeySignDataOnProtectionLevelSuccess) { DummyPublicKeySign signer = DummyPublicKeySign(kKeyNameRequiresData2); ExpectGetPublicKey(1); ExpectSign(signer, /*times*/ 1); auto kmsSigner = CreateGcpKmsPublicKeySign(kKeyNameRequiresData2, kms_client_); EXPECT_THAT(kmsSigner.status(), IsOk()); EXPECT_THAT((*kmsSigner)->Sign(kData), IsOkAndHolds(*signer.Sign(kData))); } TEST_F(TestGcpKmsPublicKeySign, PublicKeySignDigestSuccess) { DummyPublicKeySign signer = DummyPublicKeySign(kKeyNameRequiresDigest); ExpectGetPublicKey(1); ExpectSign(signer, /*times*/ 1); auto kmsSigner = CreateGcpKmsPublicKeySign(kKeyNameRequiresDigest, kms_client_); EXPECT_THAT(kmsSigner.status(), IsOk()); EXPECT_THAT((*kmsSigner)->Sign(kData), IsOkAndHolds(*signer.Sign(kDigest))); } } // namespace } // namespace gcpkms } // namespace integration } // namespace tink } // namespace crypto ================================================ FILE: cc/integration/gcpkms/testdata/gcp/BUILD.bazel ================================================ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) exports_files(srcs = ["credential.json"]) filegroup( name = "credentials", testonly = 1, srcs = [ "credential.json", "key_name.txt", ], ) filegroup( name = "bad_credentials", testonly = 1, srcs = [ "credential_bad.json", "key_name_bad.txt", ], ) ================================================ FILE: cc/integration/gcpkms/testdata/gcp/README.md ================================================ This folder contains GCP credentials that are used for testing Tink. For security reasons, all credentials in this folder are invalid. If you want to run tests that depend on them, please create your own [Cloud KMS key](https://cloud.google.com/kms/docs/creating-keys), and copy the credentials to `gcp/credential.json` and the key URI to `gcp/key_name.txt`. ================================================ FILE: cc/integration/gcpkms/testdata/gcp/credential.json ================================================ { "type": "service_account", "project_id": "tink-test-infrastructure", "private_key_id": "some_bad_private_key_id", "private_key": "-----BEGIN PRIVATE KEY-----\nMIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMtJlaQD79xGIC28\nowTpj7wkdi34piSubtDKttgC3lL00ioyQf/WMqLnyDWySNufCjhavQ7/sxXQAUCL\n5B3WDwM8+mFqQM2wJB18NBWBSfGOFSMwVQyWv7Y/1AFr+PvNKVlw4RZ4G8VuJzXZ\n9v/+5zyKv8py66sGVoHPI+LGfIprAgMBAAECgYEAxcgX8PVrnrITiKwpJxReJbyL\nxnpOmw2i/zza3BseVzOebjNrhw/NQDWl0qhcvmBjvyR5IGiiwiwXq8bu8CBdhRiE\nw3vKf1iuVOKhH07RB2wvCaGbVlB/p15gYau3sTRn5nej0tjYHX7xa/St/DwPk2H/\nxYGTRhyYtNL6wdtMjYECQQD+LVVJf0rLnxyPADTcz7Wdb+FUX79nWtMlzQOEB09+\nJj4ie0kD0cIvTQFjV3pOsg3uW2khFpjg110TXpJJfPjhAkEAzL7RhhfDdL7Dn2zl\n1orUthcGa2pzEAmg1tGBNb1pOg7LbVHKSa3GOOwyPRsActoyrPw18/fXaJdEfByY\ne9kwywJAB7rHMjH9y01uZ+bgtKpYYo5JcvBqeLEpZKfkaHp0b2ioURIguU4Csr+L\nwEKjxIrjo5ECFHCEe6nw+arRlgyH4QJBAIfQmEn733LEzB0n7npXU2yKb363eSYN\nTPzSsoREZdXWVIjqtWYUeKXvwA+apryJEw5+qwdvwxslJI+zpE6bLusCQE6M1lO9\nN6A3PtQv7Z3XwrEE/sPEVv4M4VHj0YHLs/32UuSXq5taMizKILfis1Stry4WjRHp\nQxEqdLrIkb13NH8=\n-----END PRIVATE KEY-----", "client_email": "unit-and-integration-testing@tink-test-infrastructure.iam.gserviceaccount.com", "client_id": "111876397550362269561", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://accounts.google.com/o/oauth2/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/unit-and-integration-testing%40tink-test-infrastructure.iam.gserviceaccount.com" } ================================================ FILE: cc/integration/gcpkms/testdata/gcp/credential_bad.json ================================================ { "type": "service_account", "project_id": "tink-test-infrastructure", "private_key_id": "some_bad_private_key_id", "private_key": "-----BEGIN PRIVATE KEY-----\nMIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMtJlaQD79xGIC28\nowTpj7wkdi34piSubtDKttgC3lL00ioyQf/WMqLnyDWySNufCjhavQ7/sxXQAUCL\n5B3WDwM8+mFqQM2wJB18NBWBSfGOFSMwVQyWv7Y/1AFr+PvNKVlw4RZ4G8VuJzXZ\n9v/+5zyKv8py66sGVoHPI+LGfIprAgMBAAECgYEAxcgX8PVrnrITiKwpJxReJbyL\nxnpOmw2i/zza3BseVzOebjNrhw/NQDWl0qhcvmBjvyR5IGiiwiwXq8bu8CBdhRiE\nw3vKf1iuVOKhH07RB2wvCaGbVlB/p15gYau3sTRn5nej0tjYHX7xa/St/DwPk2H/\nxYGTRhyYtNL6wdtMjYECQQD+LVVJf0rLnxyPADTcz7Wdb+FUX79nWtMlzQOEB09+\nJj4ie0kD0cIvTQFjV3pOsg3uW2khFpjg110TXpJJfPjhAkEAzL7RhhfDdL7Dn2zl\n1orUthcGa2pzEAmg1tGBNb1pOg7LbVHKSa3GOOwyPRsActoyrPw18/fXaJdEfByY\ne9kwywJAB7rHMjH9y01uZ+bgtKpYYo5JcvBqeLEpZKfkaHp0b2ioURIguU4Csr+L\nwEKjxIrjo5ECFHCEe6nw+arRlgyH4QJBAIfQmEn733LEzB0n7npXU2yKb363eSYN\nTPzSsoREZdXWVIjqtWYUeKXvwA+apryJEw5+qwdvwxslJI+zpE6bLusCQE6M1lO9\nN6A3PtQv7Z3XwrEE/sPEVv4M4VHj0YHLs/32UuSXq5taMizKILfis1Stry4WjRHp\nQxEqdLrIkb13NH8=\n-----END PRIVATE KEY-----", "client_email": "unit-and-integration-testing@tink-test-infrastructure.iam.gserviceaccount.com", "client_id": "111876397550362269561", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://accounts.google.com/o/oauth2/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/unit-and-integration-testing%40tink-test-infrastructure.iam.gserviceaccount.com" } ================================================ FILE: cc/integration/gcpkms/testdata/gcp/key_name.txt ================================================ projects/tink-test-infrastructure/locations/global/keyRings/unit-and-integration-testing/cryptoKeys/aead-key ================================================ FILE: cc/integration/gcpkms/testdata/gcp/key_name_bad.txt ================================================ projects/non-existing-project/locations/global/keyRings/some-key-ring/cryptoKeys/aead-key ================================================ FILE: cc/integration/gcpkms/tink_cc_gcpkms_deps.bzl ================================================ """Tink C++ Cloud KMS Integration Dependencies.""" load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file") def _grpc_deps(): """Imports gRPC and its dependencies. Dependencies taken from: https://github.com/grpc/grpc/blob/v1.59.3/bazel/grpc_deps.bzl. """ if "com_google_protobuf" not in native.existing_rules(): http_archive( name = "com_google_protobuf", sha256 = "660ce016f987550bc1ccec4a6ee4199afb871799b696227098e3641476a7d566", strip_prefix = "protobuf-b2b7a51158418f41cff0520894836c15b1738721", urls = [ # https://github.com/protocolbuffers/protobuf/commits/v24.3 "https://storage.googleapis.com/grpc-bazel-mirror/github.com/protocolbuffers/protobuf/archive/b2b7a51158418f41cff0520894836c15b1738721.tar.gz", "https://github.com/protocolbuffers/protobuf/archive/b2b7a51158418f41cff0520894836c15b1738721.tar.gz", ], patches = [ "@com_github_grpc_grpc//third_party:protobuf.patch", ], patch_args = ["-p1"], ) if "upb" not in native.existing_rules(): http_archive( name = "upb", sha256 = "5147e0ab6a28421d1e49004f4a205d84f06b924585e15eaa884cfe13289165b7", strip_prefix = "upb-42cd08932e364a4cde35033b73f15c30250d7c2e", urls = [ # https://github.com/protocolbuffers/upb/commits/24.x "https://storage.googleapis.com/grpc-bazel-mirror/github.com/protocolbuffers/upb/archive/42cd08932e364a4cde35033b73f15c30250d7c2e.tar.gz", "https://github.com/protocolbuffers/upb/archive/42cd08932e364a4cde35033b73f15c30250d7c2e.tar.gz", ], ) if "envoy_api" not in native.existing_rules(): http_archive( name = "envoy_api", sha256 = "6fd3496c82919a433219733819a93b56699519a193126959e9c4fedc25e70663", strip_prefix = "data-plane-api-e53e7bbd012f81965f2e79848ad9a58ceb67201f", urls = [ "https://storage.googleapis.com/grpc-bazel-mirror/github.com/envoyproxy/data-plane-api/archive/e53e7bbd012f81965f2e79848ad9a58ceb67201f.tar.gz", "https://github.com/envoyproxy/data-plane-api/archive/e53e7bbd012f81965f2e79848ad9a58ceb67201f.tar.gz", ], ) if "io_bazel_rules_go" not in native.existing_rules(): http_archive( name = "io_bazel_rules_go", sha256 = "69de5c704a05ff37862f7e0f5534d4f479418afc21806c887db544a316f3cb6b", urls = [ "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.27.0/rules_go-v0.27.0.tar.gz", "https://github.com/bazelbuild/rules_go/releases/download/v0.27.0/rules_go-v0.27.0.tar.gz", ], ) if "build_bazel_rules_apple" not in native.existing_rules(): http_archive( name = "build_bazel_rules_apple", sha256 = "f94e6dddf74739ef5cb30f000e13a2a613f6ebfa5e63588305a71fce8a8a9911", urls = [ "https://storage.googleapis.com/grpc-bazel-mirror/github.com/bazelbuild/rules_apple/releases/download/1.1.3/rules_apple.1.1.3.tar.gz", "https://github.com/bazelbuild/rules_apple/releases/download/1.1.3/rules_apple.1.1.3.tar.gz", ], ) if "build_bazel_apple_support" not in native.existing_rules(): http_archive( name = "build_bazel_apple_support", sha256 = "f4fdf5c9b42b92ea12f229b265d74bb8cedb8208ca7a445b383c9f866cf53392", urls = [ "https://storage.googleapis.com/grpc-bazel-mirror/github.com/bazelbuild/apple_support/releases/download/1.3.1/apple_support.1.3.1.tar.gz", "https://github.com/bazelbuild/apple_support/releases/download/1.3.1/apple_support.1.3.1.tar.gz", ], ) if "bazel_gazelle" not in native.existing_rules(): http_archive( name = "bazel_gazelle", sha256 = "de69a09dc70417580aabf20a28619bb3ef60d038470c7cf8442fafcf627c21cb", urls = [ "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.24.0/bazel-gazelle-v0.24.0.tar.gz", "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.24.0/bazel-gazelle-v0.24.0.tar.gz", ], ) if "com_envoyproxy_protoc_gen_validate" not in native.existing_rules(): http_archive( name = "com_envoyproxy_protoc_gen_validate", strip_prefix = "protoc-gen-validate-4694024279bdac52b77e22dc87808bd0fd732b69", sha256 = "1e490b98005664d149b379a9529a6aa05932b8a11b76b4cd86f3d22d76346f47", urls = [ "https://github.com/envoyproxy/protoc-gen-validate/archive/4694024279bdac52b77e22dc87808bd0fd732b69.tar.gz", ], patches = ["@com_github_grpc_grpc//third_party:protoc-gen-validate.patch"], patch_args = ["-p1"], ) if not native.existing_rule("com_github_grpc_grpc"): # Release from 2023-11-15. http_archive( name = "com_github_grpc_grpc", sha256 = "03ca78ecf847783ac6e895dc7a24834e86981bd8c5408cf86f6ccee886bd3079", strip_prefix = "grpc-1.59.3", urls = ["https://github.com/grpc/grpc/archive/refs/tags/v1.59.3.zip"], ) def tink_cc_gcpkms_deps(): """Loads dependencies for Tink C++ Cloud KMS.""" # Google PKI certs for connecting to GCP KMS. if not native.existing_rule("google_root_pem"): http_file( name = "google_root_pem", executable = 0, urls = ["https://pki.goog/roots.pem"], sha256 = "1acf0d4780541758be2c0f998e1e0275232626ed3f8793d8e2fe8e2753750613", ) _grpc_deps() if "com_google_googleapis" not in native.existing_rules(): http_archive( name = "com_google_googleapis", sha256 = "b541d28b3fd5c0ce802f02b665cf14dfe7a88bd34d8549215127e7ab1008bbbc", strip_prefix = "googleapis-e56f4b1c926f42d6ab127c049158df2dda189914", build_file = Label("@com_github_grpc_grpc//bazel:googleapis.BUILD"), urls = [ "https://storage.googleapis.com/cloud-cpp-community-archive/com_google_googleapis/e56f4b1c926f42d6ab127c049158df2dda189914.tar.gz", "https://github.com/googleapis/googleapis/archive/e56f4b1c926f42d6ab127c049158df2dda189914.tar.gz", ], ) if "google_cloud_cpp" not in native.existing_rules(): http_archive( name = "google_cloud_cpp", sha256 = "0f42208ca782249555aac06455b1669c17dfb31d6d8fa4baad29a90f295666bb", strip_prefix = "google-cloud-cpp-2.20.0", url = "https://github.com/googleapis/google-cloud-cpp/archive/v2.20.0.tar.gz", ) if not native.existing_rule("com_google_absl"): # Release from 2023-09-18. http_archive( name = "com_google_absl", sha256 = "497ebdc3a4885d9209b9bd416e8c3f71e7a1fb8af249f6c2a80b7cbeefcd7e21", strip_prefix = "abseil-cpp-20230802.1", urls = ["https://github.com/abseil/abseil-cpp/archive/refs/tags/20230802.1.zip"], ) if not native.existing_rule("tink_cc"): # Release from 2024-04-05. http_archive( name = "tink_cc", sha256 = "d0fefc61e3bde758c8773f1348e6a64fc4fd6ecafe62c4adc0df8957ce800757", strip_prefix = "tink-cc-2.1.2", urls = ["https://github.com/tink-crypto/tink-cc/releases/download/v2.1.2/tink-cc-2.1.2.zip"], ) if not native.existing_rule("com_googlesource_code_re2"): http_archive( name = "com_googlesource_code_re2", sha256 = "cd191a311b84fcf37310e5cd876845b4bf5aee76fdd755008eef3b6478ce07bb", strip_prefix = "re2-2024-02-01", url = "https://github.com/google/re2/releases/download/2024-02-01/re2-2024-02-01.tar.gz", ) def tink_cc_gcpkms_testonly_deps(): """Test only dependencies.""" if not native.existing_rule("com_google_googletest"): # Release from 2023-08-02. http_archive( name = "com_google_googletest", sha256 = "1f357c27ca988c3f7c6b4bf68a9395005ac6761f034046e9dde0896e3aba00e4", strip_prefix = "googletest-1.14.0", url = "https://github.com/google/googletest/archive/refs/tags/v1.14.0.zip", ) ================================================ FILE: cc/integration/gcpkms/tink_cc_gcpkms_deps_init.bzl ================================================ """Initialization of dependencies of Tink C++ Cloud KMS.""" # TODO(b/233231652): Revert back to grpc_extra_deps() when it's safe to do so. #load("@com_github_grpc_grpc//bazel:grpc_extra_deps.bzl", "grpc_extra_deps") load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies") load("@build_bazel_apple_support//lib:repositories.bzl", "apple_support_dependencies") load("@build_bazel_rules_apple//apple:repositories.bzl", "apple_rules_dependencies") load("@com_envoyproxy_protoc_gen_validate//:dependencies.bzl", "go_third_party") load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps") load("@com_google_googleapis//:repository_rules.bzl", "switched_rules_by_language") load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") load("@envoy_api//bazel:repositories.bzl", "api_dependencies") load("@google_cloud_cpp//bazel:google_cloud_cpp_deps.bzl", "google_cloud_cpp_deps") load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") load("@tink_cc//:tink_cc_deps.bzl", "tink_cc_deps") load("@tink_cc//:tink_cc_deps_init.bzl", "tink_cc_deps_init") load("@upb//bazel:workspace_deps.bzl", "upb_deps") def tink_cc_gcpkms_deps_init( ignore_version_differences = False, register_go = True): """Initializes dependencies of Tink C++ GCP Cloud KMS. Args: ignore_version_differences: Plumbed directly to the invocation of apple_rules_dependencies. register_go: Whether or not to register Go toolchains. If toolchains are already registered, it should not be done again here. """ tink_cc_deps() tink_cc_deps_init() switched_rules_by_language( name = "com_google_googleapis_imports", cc = True, grpc = True, ) grpc_deps() # From this point on, the work normally done by grpc_extra_deps() is # locally replicated, to facilitate making makes Go toolchain registration # optional. Without this option, Bazel will fail if this is used in a # workspace where go_register_toolchains() has already been called. # # TODO(b/233231652): Upstream this (or an equivalent) fix to gRPC. protobuf_deps() upb_deps() api_dependencies() google_cloud_cpp_deps() if register_go: go_rules_dependencies() go_register_toolchains(version = "1.21.8") gazelle_dependencies() # Pull-in the go 3rd party dependencies for protoc_gen_validate, which is # needed for building C++ xDS protos go_third_party() apple_rules_dependencies(ignore_version_differences = ignore_version_differences) apple_support_dependencies() ================================================ FILE: cc/internal/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "ssl_util", hdrs = ["ssl_util.h"], include_prefix = "tink/internal", deps = ["@boringssl//:crypto"], ) cc_library( name = "keyset_wrapper", hdrs = ["keyset_wrapper.h"], include_prefix = "tink/internal", deps = [ "//proto:tink_cc_proto", "//util:statusor", "@com_google_absl//absl/container:flat_hash_map", ], ) cc_library( name = "util", srcs = ["util.cc"], hdrs = ["util.h"], include_prefix = "tink/internal", deps = [ "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/log", "@com_google_absl//absl/strings", ], ) cc_library( name = "test_file_util", testonly = 1, srcs = [ "test_file_util.cc", "test_file_util_bazel.cc", ], hdrs = ["test_file_util.h"], include_prefix = "tink/internal", deps = [ "//subtle:random", "//util:status", "//util:test_util", "@bazel_tools//tools/cpp/runfiles", "@com_google_absl//absl/log:check", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest", ], ) cc_library( name = "keyset_wrapper_impl", hdrs = ["keyset_wrapper_impl.h"], include_prefix = "tink/internal", deps = [ ":key_info", ":keyset_wrapper", "//:primitive_set", "//:primitive_wrapper", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/functional:any_invocable", ], ) cc_library( name = "ssl_unique_ptr", hdrs = ["ssl_unique_ptr.h"], include_prefix = "tink/internal", deps = ["@boringssl//:crypto"], ) cc_library( name = "key_info", srcs = ["key_info.cc"], hdrs = ["key_info.h"], include_prefix = "tink/internal", deps = ["//proto:tink_cc_proto"], ) cc_library( name = "registry_impl", srcs = ["registry_impl.cc"], hdrs = ["registry_impl.h"], include_prefix = "tink/internal", deps = [ ":fips_utils", ":key_type_info_store", ":keyset_wrapper", ":keyset_wrapper_store", "//:core/key_type_manager", "//:core/private_key_type_manager", "//:input_stream", "//:key_manager", "//:primitive_set", "//:primitive_wrapper", "//monitoring", "//proto:tink_cc_proto", "//util:errors", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/functional:any_invocable", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/synchronization", ], ) config_setting( name = "fips_enabled", flag_values = {"//config:use_only_fips": "True"}, visibility = ["//visibility:public"], ) cc_library( name = "fips_utils", srcs = ["fips_utils.cc"], hdrs = ["fips_utils.h"], defines = select({ "fips_enabled": ["TINK_USE_ONLY_FIPS"], "//conditions:default": [], }), include_prefix = "tink/internal", deps = [ "//util:status", "@boringssl//:crypto", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/status", ], ) cc_library( name = "err_util", srcs = ["err_util.cc"], hdrs = ["err_util.h"], include_prefix = "tink/internal", deps = ["@boringssl//:crypto"], ) cc_library( name = "bn_util", srcs = ["bn_util.cc"], hdrs = ["bn_util.h"], include_prefix = "tink/internal", deps = [ ":ssl_unique_ptr", "//subtle:subtle_util", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", ], ) cc_library( name = "rsa_util", srcs = ["rsa_util.cc"], hdrs = ["rsa_util.h"], include_prefix = "tink/internal", deps = [ ":bn_util", ":err_util", ":fips_utils", ":ssl_unique_ptr", ":ssl_util", "//config:tink_fips", "//subtle:common_enums", "//util:errors", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", ], ) cc_library( name = "ec_util", srcs = ["ec_util.cc"], hdrs = ["ec_util.h"], include_prefix = "tink/internal", deps = [ ":bn_util", ":err_util", ":fips_utils", ":ssl_unique_ptr", "//subtle:common_enums", "//subtle:random", "//subtle:subtle_util", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", ], ) cc_library( name = "md_util", srcs = ["md_util.cc"], hdrs = ["md_util.h"], include_prefix = "tink/internal", deps = [ ":err_util", ":util", "//subtle:common_enums", "//subtle:subtle_util", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_test( name = "util_test", srcs = ["util_test.cc"], deps = [ ":util", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "keyset_wrapper_impl_test", srcs = ["keyset_wrapper_impl_test.cc"], deps = [ ":keyset_wrapper_impl", "//:primitive_set", "//:primitive_wrapper", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "key_info_test", srcs = ["key_info_test.cc"], deps = [ ":key_info", "//proto:tink_cc_proto", "@com_google_googletest//:gtest_main", "@com_google_protobuf//:protobuf", ], ) cc_test( name = "registry_impl_test", size = "small", srcs = ["registry_impl_test.cc"], tags = ["fips"], deps = [ ":fips_utils", ":registry_impl", "//:aead", "//:core/key_manager_impl", "//:core/key_type_manager", "//:core/private_key_manager_impl", "//:core/private_key_type_manager", "//:core/template_util", "//:hybrid_decrypt", "//:input_stream", "//:key_manager", "//:mac", "//:primitive_set", "//:primitive_wrapper", "//:registry", "//aead:aead_wrapper", "//aead:aes_gcm_key_manager", "//hybrid:ecies_aead_hkdf_private_key_manager", "//hybrid:ecies_aead_hkdf_public_key_manager", "//monitoring:monitoring_client_mocks", "//proto:aes_ctr_hmac_aead_cc_proto", "//proto:aes_gcm_cc_proto", "//proto:common_cc_proto", "//proto:ecdsa_cc_proto", "//proto:ecies_aead_hkdf_cc_proto", "//proto:tink_cc_proto", "//subtle:aes_gcm_boringssl", "//subtle:random", "//util:input_stream_util", "//util:istream_input_stream", "//util:protobuf_helper", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "fips_utils_test", size = "small", srcs = ["fips_utils_test.cc"], tags = ["fips"], deps = [ ":fips_utils", "//util:status", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "err_util_test", size = "small", srcs = ["err_util_test.cc"], deps = [ ":err_util", "@boringssl//:crypto", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "bn_util_test", size = "small", srcs = ["bn_util_test.cc"], deps = [ ":bn_util", ":ssl_unique_ptr", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "rsa_util_test", srcs = ["rsa_util_test.cc"], deps = [ ":bn_util", ":rsa_util", ":ssl_unique_ptr", "//subtle:random", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ec_util_test", srcs = ["ec_util_test.cc"], data = [ "//testvectors:ecdh", "//testvectors:ecdsa_webcrypto", "//testvectors:eddsa", ], deps = [ ":bn_util", ":ec_util", ":fips_utils", ":ssl_unique_ptr", ":ssl_util", "//subtle:common_enums", "//subtle:subtle_util", "//subtle:wycheproof_util", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", "@com_google_googletest//:gtest_main", "@rapidjson", ], ) cc_test( name = "md_util_test", size = "small", srcs = ["md_util_test.cc"], deps = [ ":md_util", "//subtle:common_enums", "//util:status", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "aes_util", srcs = ["aes_util.cc"], hdrs = ["aes_util.h"], include_prefix = "tink/internal", deps = [ ":util", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", ], ) cc_test( name = "aes_util_test", size = "small", srcs = ["aes_util_test.cc"], deps = [ ":aes_util", "//subtle:subtle_util", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "monitoring_util", hdrs = ["monitoring_util.h"], include_prefix = "tink/internal", deps = [ ":key_status_util", "//:key_status", "//:primitive_set", "//monitoring", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_test( name = "monitoring_util_test", srcs = ["monitoring_util_test.cc"], deps = [ ":monitoring_util", "//:key_status", "//:primitive_set", "//monitoring", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "serialization", hdrs = ["serialization.h"], include_prefix = "tink/internal", deps = ["@com_google_absl//absl/strings"], ) cc_library( name = "proto_parameters_serialization", srcs = ["proto_parameters_serialization.cc"], hdrs = ["proto_parameters_serialization.h"], include_prefix = "tink/internal", deps = [ ":serialization", ":util", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_test( name = "proto_parameters_serialization_test", srcs = ["proto_parameters_serialization_test.cc"], deps = [ ":proto_parameters_serialization", "//proto:test_proto_cc_proto", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "proto_key_serialization", srcs = ["proto_key_serialization.cc"], hdrs = ["proto_key_serialization.h"], include_prefix = "tink/internal", deps = [ ":serialization", ":util", "//:restricted_data", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_test( name = "proto_key_serialization_test", srcs = ["proto_key_serialization_test.cc"], deps = [ ":proto_key_serialization", "//:insecure_secret_key_access", "//:restricted_data", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "legacy_proto_parameters", srcs = ["legacy_proto_parameters.cc"], hdrs = ["legacy_proto_parameters.h"], include_prefix = "tink/internal", deps = [ ":proto_parameters_serialization", "//:parameters", "//proto:tink_cc_proto", ], ) cc_test( name = "legacy_proto_parameters_test", srcs = ["legacy_proto_parameters_test.cc"], deps = [ ":legacy_proto_parameters", ":proto_parameters_serialization", "//:parameters", "//proto:test_proto_cc_proto", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "legacy_proto_key", srcs = ["legacy_proto_key.cc"], hdrs = ["legacy_proto_key.h"], include_prefix = "tink/internal", deps = [ ":proto_key_serialization", "//:key", "//:parameters", "//:secret_key_access_token", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_test( name = "legacy_proto_key_test", srcs = ["legacy_proto_key_test.cc"], deps = [ ":legacy_proto_key", ":proto_key_serialization", "//:insecure_secret_key_access", "//:key", "//:parameters", "//:restricted_data", "//:secret_key_access_token", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "parser_index", hdrs = ["parser_index.h"], include_prefix = "tink/internal", deps = [ ":serialization", "@com_google_absl//absl/strings", ], ) cc_test( name = "parser_index_test", srcs = ["parser_index_test.cc"], deps = [ ":parser_index", ":serialization", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "serializer_index", hdrs = ["serializer_index.h"], include_prefix = "tink/internal", deps = [ ":serialization", "//:key", "//:parameters", ], ) cc_test( name = "serializer_index_test", srcs = ["serializer_index_test.cc"], deps = [ ":serialization_test_util", ":serializer_index", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "parameters_parser", hdrs = ["parameters_parser.h"], include_prefix = "tink/internal", deps = [ ":parser_index", ":serialization", "//:parameters", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_test( name = "parameters_parser_test", srcs = ["parameters_parser_test.cc"], deps = [ ":parameters_parser", ":parser_index", ":serialization", ":serialization_test_util", "//:parameters", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "parameters_serializer", hdrs = ["parameters_serializer.h"], include_prefix = "tink/internal", deps = [ ":serialization", ":serializer_index", "//:parameters", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_test( name = "parameters_serializer_test", srcs = ["parameters_serializer_test.cc"], deps = [ ":parameters_serializer", ":serialization", ":serialization_test_util", ":serializer_index", "//:parameters", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "key_parser", hdrs = ["key_parser.h"], include_prefix = "tink/internal", deps = [ ":parser_index", ":serialization", "//:key", "//:secret_key_access_token", "//util:status", "//util:statusor", "@com_google_absl//absl/functional:function_ref", "@com_google_absl//absl/log", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_test( name = "key_parser_test", srcs = ["key_parser_test.cc"], deps = [ ":key_parser", ":parser_index", ":serialization", ":serialization_test_util", "//:insecure_secret_key_access", "//:key", "//:parameters", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "key_serializer", hdrs = ["key_serializer.h"], include_prefix = "tink/internal", deps = [ ":serialization", ":serializer_index", "//:key", "//:secret_key_access_token", "//util:status", "//util:statusor", "@com_google_absl//absl/functional:function_ref", "@com_google_absl//absl/log", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", ], ) cc_test( name = "key_serializer_test", srcs = ["key_serializer_test.cc"], deps = [ ":key_serializer", ":serialization", ":serialization_test_util", ":serializer_index", "//:insecure_secret_key_access", "//:key", "//:secret_key_access_token", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "key_status_util", srcs = ["key_status_util.cc"], hdrs = ["key_status_util.h"], include_prefix = "tink/internal", deps = [ "//:key_status", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/status", ], ) cc_test( name = "key_status_util_test", srcs = ["key_status_util_test.cc"], deps = [ ":key_status_util", "//:key_status", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "keyset_handle_builder_entry", srcs = ["keyset_handle_builder_entry.cc"], hdrs = ["keyset_handle_builder_entry.h"], include_prefix = "tink/internal", deps = [ ":key_status_util", ":legacy_proto_key", ":legacy_proto_parameters", ":mutable_serialization_registry", ":proto_key_serialization", ":proto_parameters_serialization", ":serialization", "//:insecure_secret_key_access", "//:key", "//:key_status", "//:parameters", "//:registry", "//:restricted_data", "//:secret_key_access_token", "//proto:tink_cc_proto", "//util:secret_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_test( name = "keyset_handle_builder_entry_test", srcs = ["keyset_handle_builder_entry_test.cc"], deps = [ ":keyset_handle_builder_entry", ":legacy_proto_key", ":legacy_proto_parameters", ":proto_key_serialization", ":proto_parameters_serialization", "//:insecure_secret_key_access", "//:key", "//:key_status", "//:keyset_handle", "//:keyset_handle_builder", "//:parameters", "//:partial_key_access", "//:restricted_data", "//:secret_key_access_token", "//config:tink_config", "//mac:aes_cmac_key", "//mac:aes_cmac_parameters", "//mac:mac_key_templates", "//proto:tink_cc_proto", "//util:secret_proto", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "serialization_registry", srcs = ["serialization_registry.cc"], hdrs = ["serialization_registry.h"], include_prefix = "tink/internal", deps = [ ":key_parser", ":key_serializer", ":parameters_parser", ":parameters_serializer", ":parser_index", ":serialization", ":serializer_index", "//:key", "//:parameters", "//:secret_key_access_token", "//util:status", "//util:statusor", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:str_format", "@com_google_absl//absl/types:optional", ], ) cc_test( name = "serialization_registry_test", srcs = ["serialization_registry_test.cc"], deps = [ ":key_parser", ":key_serializer", ":parameters_parser", ":parameters_serializer", ":serialization", ":serialization_registry", ":serialization_test_util", "//:insecure_secret_key_access", "//:key", "//:parameters", "//:secret_key_access_token", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "mutable_serialization_registry", srcs = ["mutable_serialization_registry.cc"], hdrs = ["mutable_serialization_registry.h"], include_prefix = "tink/internal", deps = [ ":key_parser", ":key_serializer", ":legacy_proto_key", ":parameters_parser", ":parameters_serializer", ":proto_key_serialization", ":serialization", ":serialization_registry", "//:insecure_secret_key_access", "//:key", "//:parameters", "//:secret_key_access_token", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/synchronization", "@com_google_absl//absl/types:optional", ], ) cc_test( name = "mutable_serialization_registry_test", srcs = ["mutable_serialization_registry_test.cc"], deps = [ ":key_parser", ":key_serializer", ":mutable_serialization_registry", ":parameters_parser", ":parameters_serializer", ":proto_key_serialization", ":serialization", ":serialization_test_util", "//:insecure_secret_key_access", "//:key", "//:parameters", "//:restricted_data", "//:secret_key_access_token", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "serialization_test_util", testonly = 1, hdrs = ["serialization_test_util.h"], include_prefix = "tink/internal", deps = [ ":serialization", "//:key", "//:parameters", "//:secret_key_access_token", "//util:statusor", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_test( name = "serialization_test_util_test", srcs = ["serialization_test_util_test.cc"], deps = [ ":serialization_test_util", "//:insecure_secret_key_access", "//:parameters", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "test_random_access_stream", testonly = 1, srcs = ["test_random_access_stream.cc"], hdrs = ["test_random_access_stream.h"], include_prefix = "tink/internal", deps = [ "//:random_access_stream", "//util:buffer", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_test( name = "test_random_access_stream_test", srcs = ["test_random_access_stream_test.cc"], deps = [ ":test_random_access_stream", "//subtle:random", "//util:buffer", "//util:status", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "configuration_impl", hdrs = ["configuration_impl.h"], include_prefix = "tink/internal", deps = [ ":key_type_info_store", ":keyset_wrapper_store", "//:configuration", "//:key_manager", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", ], ) cc_test( name = "configuration_impl_test", srcs = ["configuration_impl_test.cc"], deps = [ ":configuration_impl", ":key_type_info_store", ":keyset_wrapper", ":keyset_wrapper_store", "//:cleartext_keyset_handle", "//:configuration", "//:core/key_manager_impl", "//:core/key_type_manager", "//:core/private_key_type_manager", "//:core/template_util", "//:input_stream", "//:key_manager", "//:keyset_handle", "//:primitive_set", "//:primitive_wrapper", "//:public_key_sign", "//:public_key_verify", "//:registry", "//proto:aes_gcm_cc_proto", "//proto:rsa_ssa_pss_cc_proto", "//proto:tink_cc_proto", "//subtle:random", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "key_type_info_store", srcs = ["key_type_info_store.cc"], hdrs = ["key_type_info_store.h"], include_prefix = "tink/internal", deps = [ ":fips_utils", "//:core/key_manager_impl", "//:core/key_type_manager", "//:core/private_key_manager_impl", "//:core/private_key_type_manager", "//:core/template_util", "//:input_stream", "//:key_manager", "//proto:tink_cc_proto", "//util:errors", "//util:status", "//util:statusor", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_test( name = "key_type_info_store_test", srcs = ["key_type_info_store_test.cc"], deps = [ ":fips_utils", ":key_type_info_store", "//:aead", "//:core/key_manager_impl", "//:key_manager", "//:public_key_sign", "//:public_key_verify", "//aead:aes_gcm_key_manager", "//aead:cord_aead", "//aead:kms_envelope_aead_key_manager", "//proto:aes_gcm_cc_proto", "//proto:common_cc_proto", "//proto:ecdsa_cc_proto", "//proto:tink_cc_proto", "//signature:ecdsa_sign_key_manager", "//signature:ecdsa_verify_key_manager", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "keyset_wrapper_store", hdrs = ["keyset_wrapper_store.h"], include_prefix = "tink/internal", deps = [ ":keyset_wrapper", ":keyset_wrapper_impl", "//:primitive_wrapper", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/functional:any_invocable", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_test( name = "keyset_wrapper_store_test", srcs = ["keyset_wrapper_store_test.cc"], deps = [ ":keyset_wrapper", ":keyset_wrapper_store", ":registry_impl", "//:core/key_type_manager", "//:core/template_util", "//:input_stream", "//:mac", "//:primitive_set", "//:primitive_wrapper", "//mac:mac_wrapper", "//proto:aes_gcm_cc_proto", "//proto:tink_cc_proto", "//subtle:random", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "key_gen_configuration_impl", hdrs = ["key_gen_configuration_impl.h"], include_prefix = "tink/internal", deps = [ ":key_type_info_store", "//:key_gen_configuration", "//:key_manager", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", ], ) cc_test( name = "key_gen_configuration_impl_test", srcs = ["key_gen_configuration_impl_test.cc"], deps = [ ":key_gen_configuration_impl", ":key_type_info_store", "//:core/key_manager_impl", "//:core/key_type_manager", "//:core/private_key_type_manager", "//:core/template_util", "//:input_stream", "//:key_gen_configuration", "//:key_manager", "//:keyset_handle", "//:public_key_sign", "//:public_key_verify", "//:registry", "//aead:aead_key_templates", "//proto:aes_gcm_cc_proto", "//proto:rsa_ssa_pss_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "call_with_core_dump_protection", hdrs = ["call_with_core_dump_protection.h"], include_prefix = "tink/internal", ) cc_test( name = "call_with_core_dump_protection_test", srcs = ["call_with_core_dump_protection_test.cc"], deps = [ ":call_with_core_dump_protection", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "safe_stringops", hdrs = ["safe_stringops.h"], include_prefix = "tink/internal", deps = [ ":call_with_core_dump_protection", "@boringssl//:crypto", ], ) cc_test( name = "safe_stringops_test", srcs = ["safe_stringops_test.cc"], deps = [ ":safe_stringops", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "bn_encoding_util", srcs = ["bn_encoding_util.cc"], hdrs = ["bn_encoding_util.h"], include_prefix = "tink/internal", deps = [ "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:str_format", "@com_google_absl//absl/strings:string_view", ], ) cc_test( name = "bn_encoding_util_test", srcs = ["bn_encoding_util_test.cc"], deps = [ ":bn_encoding_util", "//:big_integer", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/internal/CMakeLists.txt ================================================ tink_module(internal) tink_cc_library( NAME ssl_util SRCS ssl_util.h DEPS crypto ) tink_cc_library( NAME keyset_wrapper SRCS keyset_wrapper.h DEPS absl::flat_hash_map tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME util SRCS util.cc util.h DEPS absl::core_headers absl::log absl::strings ) tink_cc_library( NAME test_file_util SRCS test_file_util.cc test_file_util_cmake.cc test_file_util.h DEPS absl::check absl::strings gmock tink::subtle::random tink::util::status tink::util::test_util TESTONLY ) tink_cc_library( NAME keyset_wrapper_impl SRCS keyset_wrapper_impl.h DEPS tink::internal::key_info tink::internal::keyset_wrapper absl::flat_hash_map absl::any_invocable tink::core::primitive_set tink::core::primitive_wrapper tink::util::status tink::util::statusor tink::util::validation tink::proto::tink_cc_proto ) tink_cc_library( NAME ssl_unique_ptr SRCS ssl_unique_ptr.h DEPS crypto ) tink_cc_library( NAME err_util SRCS err_util.cc err_util.h DEPS crypto ) tink_cc_library( NAME key_info SRCS key_info.cc key_info.h DEPS tink::proto::tink_cc_proto ) tink_cc_library( NAME registry_impl SRCS registry_impl.cc registry_impl.h DEPS tink::internal::fips_utils tink::internal::key_type_info_store tink::internal::keyset_wrapper tink::internal::keyset_wrapper_store absl::core_headers absl::flat_hash_map absl::any_invocable absl::memory absl::status absl::strings absl::synchronization tink::core::key_type_manager tink::core::private_key_type_manager tink::core::input_stream tink::core::key_manager tink::core::primitive_set tink::core::primitive_wrapper tink::monitoring::monitoring tink::util::errors tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME fips_utils SRCS fips_utils.cc fips_utils.h DEPS absl::core_headers absl::status crypto tink::util::status ) tink_cc_library( NAME ec_util SRCS ec_util.cc ec_util.h DEPS tink::internal::bn_util tink::internal::err_util tink::internal::fips_utils tink::internal::ssl_unique_ptr absl::memory absl::status absl::strings absl::span crypto tink::subtle::common_enums tink::subtle::random tink::subtle::subtle_util tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME bn_util SRCS bn_util.cc bn_util.h DEPS tink::internal::ssl_unique_ptr absl::status absl::strings absl::span crypto tink::subtle::subtle_util tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME rsa_util SRCS rsa_util.cc rsa_util.h DEPS tink::internal::bn_util tink::internal::err_util tink::internal::fips_utils tink::internal::ssl_unique_ptr tink::internal::ssl_util absl::status absl::statusor absl::strings crypto tink::config::tink_fips tink::subtle::common_enums tink::util::errors tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_test( NAME util_test SRCS util_test.cc DEPS tink::internal::util gmock absl::strings ) tink_cc_test( NAME keyset_wrapper_impl_test SRCS keyset_wrapper_impl_test.cc DEPS tink::internal::keyset_wrapper_impl gmock absl::flat_hash_map absl::memory absl::status absl::strings tink::core::primitive_set tink::core::primitive_wrapper tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::tink_cc_proto ) tink_cc_test( NAME key_info_test SRCS key_info_test.cc DEPS tink::internal::key_info gmock protobuf::libprotobuf-lite tink::proto::tink_cc_proto ) tink_cc_test( NAME registry_impl_test SRCS registry_impl_test.cc DEPS tink::internal::fips_utils tink::internal::registry_impl gmock absl::memory absl::status absl::statusor absl::strings crypto tink::core::aead tink::core::key_manager_impl tink::core::key_type_manager tink::core::private_key_manager_impl tink::core::private_key_type_manager tink::core::template_util tink::core::hybrid_decrypt tink::core::input_stream tink::core::key_manager tink::core::mac tink::core::primitive_set tink::core::primitive_wrapper tink::core::registry tink::aead::aead_wrapper tink::aead::aes_gcm_key_manager tink::hybrid::ecies_aead_hkdf_private_key_manager tink::hybrid::ecies_aead_hkdf_public_key_manager tink::monitoring::monitoring_client_mocks tink::subtle::aes_gcm_boringssl tink::subtle::random tink::util::input_stream_util tink::util::istream_input_stream tink::util::protobuf_helper tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::aes_ctr_hmac_aead_cc_proto tink::proto::aes_gcm_cc_proto tink::proto::common_cc_proto tink::proto::ecdsa_cc_proto tink::proto::ecies_aead_hkdf_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME err_util_test SRCS err_util_test.cc DEPS tink::internal::err_util gmock absl::strings crypto ) tink_cc_test( NAME bn_util_test SRCS bn_util_test.cc DEPS tink::internal::bn_util tink::internal::ssl_unique_ptr gmock absl::strings absl::span crypto tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME rsa_util_test SRCS rsa_util_test.cc DEPS tink::internal::bn_util tink::internal::rsa_util tink::internal::ssl_unique_ptr gmock absl::status absl::strings crypto tink::subtle::random tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME fips_utils_test SRCS fips_utils_test.cc DEPS tink::internal::fips_utils gmock absl::status crypto tink::util::status tink::util::test_matchers ) tink_cc_test( NAME ec_util_test SRCS ec_util_test.cc DATA wycheproof::testvectors DEPS tink::internal::bn_util tink::internal::ec_util tink::internal::fips_utils tink::internal::ssl_unique_ptr tink::internal::ssl_util gmock absl::status absl::strings absl::span crypto rapidjson tink::subtle::common_enums tink::subtle::subtle_util tink::subtle::wycheproof_util tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers ) tink_cc_library( NAME md_util SRCS md_util.cc md_util.h DEPS tink::internal::err_util tink::internal::util absl::status absl::strings crypto tink::subtle::common_enums tink::subtle::subtle_util tink::util::status tink::util::statusor ) tink_cc_test( NAME md_util_test SRCS md_util_test.cc DEPS tink::internal::md_util gmock absl::strings crypto tink::subtle::common_enums tink::util::status tink::util::statusor tink::util::test_matchers ) tink_cc_library( NAME aes_util SRCS aes_util.cc aes_util.h DEPS tink::internal::util absl::status absl::strings absl::span crypto tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_test( NAME aes_util_test SRCS aes_util_test.cc DEPS tink::internal::aes_util gmock absl::status absl::strings absl::span crypto tink::subtle::subtle_util tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers ) tink_cc_library( NAME monitoring_util SRCS monitoring_util.h DEPS tink::internal::key_status_util absl::flat_hash_map absl::status absl::strings tink::core::key_status tink::core::primitive_set tink::monitoring::monitoring tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_test( NAME monitoring_util_test SRCS monitoring_util_test.cc DEPS tink::internal::monitoring_util gmock absl::flat_hash_map absl::memory absl::status absl::strings tink::core::key_status tink::core::primitive_set tink::monitoring::monitoring tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) tink_cc_library( NAME serialization SRCS serialization.h DEPS absl::strings ) tink_cc_library( NAME proto_parameters_serialization SRCS proto_parameters_serialization.cc proto_parameters_serialization.h DEPS tink::internal::serialization tink::internal::util absl::status absl::strings tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_test( NAME proto_parameters_serialization_test SRCS proto_parameters_serialization_test.cc DEPS tink::internal::proto_parameters_serialization gmock tink::util::statusor tink::util::test_matchers tink::proto::test_proto_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME proto_key_serialization SRCS proto_key_serialization.cc proto_key_serialization.h DEPS tink::internal::serialization tink::internal::util absl::status absl::strings absl::optional tink::core::restricted_data tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_test( NAME proto_key_serialization_test SRCS proto_key_serialization_test.cc DEPS tink::internal::proto_key_serialization gmock absl::status absl::strings absl::optional tink::core::insecure_secret_key_access tink::core::restricted_data tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) tink_cc_library( NAME legacy_proto_parameters SRCS legacy_proto_parameters.cc legacy_proto_parameters.h DEPS tink::internal::proto_parameters_serialization tink::core::parameters tink::proto::tink_cc_proto ) tink_cc_test( NAME legacy_proto_parameters_test SRCS legacy_proto_parameters_test.cc DEPS tink::internal::legacy_proto_parameters tink::internal::proto_parameters_serialization gmock tink::core::parameters tink::util::statusor tink::util::test_matchers tink::proto::test_proto_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME legacy_proto_key SRCS legacy_proto_key.cc legacy_proto_key.h DEPS tink::internal::proto_key_serialization absl::status absl::strings absl::optional tink::core::key tink::core::parameters tink::core::secret_key_access_token tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_test( NAME legacy_proto_key_test SRCS legacy_proto_key_test.cc DEPS tink::internal::legacy_proto_key tink::internal::proto_key_serialization gmock absl::status absl::optional tink::core::insecure_secret_key_access tink::core::key tink::core::parameters tink::core::restricted_data tink::core::secret_key_access_token tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) tink_cc_library( NAME parser_index SRCS parser_index.h DEPS tink::internal::serialization absl::strings ) tink_cc_test( NAME parser_index_test SRCS parser_index_test.cc DEPS tink::internal::parser_index tink::internal::serialization gmock absl::strings ) tink_cc_library( NAME serializer_index SRCS serializer_index.h DEPS tink::internal::serialization tink::core::key tink::core::parameters ) tink_cc_test( NAME serializer_index_test SRCS serializer_index_test.cc DEPS tink::internal::serialization_test_util tink::internal::serializer_index gmock ) tink_cc_library( NAME parameters_parser SRCS parameters_parser.h DEPS tink::internal::parser_index tink::internal::serialization absl::status absl::strings tink::core::parameters tink::util::status tink::util::statusor ) tink_cc_test( NAME parameters_parser_test SRCS parameters_parser_test.cc DEPS tink::internal::parameters_parser tink::internal::parser_index tink::internal::serialization tink::internal::serialization_test_util gmock absl::memory absl::status tink::core::parameters tink::util::statusor tink::util::test_matchers ) tink_cc_library( NAME parameters_serializer SRCS parameters_serializer.h DEPS tink::internal::serialization tink::internal::serializer_index absl::status absl::strings tink::core::parameters tink::util::status tink::util::statusor ) tink_cc_test( NAME parameters_serializer_test SRCS parameters_serializer_test.cc DEPS tink::internal::parameters_serializer tink::internal::serialization tink::internal::serialization_test_util tink::internal::serializer_index gmock absl::memory absl::status tink::core::parameters tink::util::statusor tink::util::test_matchers ) tink_cc_library( NAME key_parser SRCS key_parser.h DEPS tink::internal::parser_index tink::internal::serialization absl::function_ref absl::log absl::status absl::strings absl::optional tink::core::key tink::core::secret_key_access_token tink::util::status tink::util::statusor ) tink_cc_test( NAME key_parser_test SRCS key_parser_test.cc DEPS tink::internal::key_parser tink::internal::parser_index tink::internal::serialization tink::internal::serialization_test_util gmock absl::memory absl::status absl::optional tink::core::insecure_secret_key_access tink::core::key tink::core::parameters tink::util::statusor tink::util::test_matchers ) tink_cc_library( NAME key_serializer SRCS key_serializer.h DEPS tink::internal::serialization tink::internal::serializer_index absl::function_ref absl::log absl::status absl::optional tink::core::key tink::core::secret_key_access_token tink::util::status tink::util::statusor ) tink_cc_test( NAME key_serializer_test SRCS key_serializer_test.cc DEPS tink::internal::key_serializer tink::internal::serialization tink::internal::serialization_test_util tink::internal::serializer_index gmock absl::memory absl::status absl::optional tink::core::insecure_secret_key_access tink::core::key tink::core::secret_key_access_token tink::util::statusor tink::util::test_matchers ) tink_cc_library( NAME key_status_util SRCS key_status_util.cc key_status_util.h DEPS absl::status tink::core::key_status tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_test( NAME key_status_util_test SRCS key_status_util_test.cc DEPS tink::internal::key_status_util gmock absl::status tink::core::key_status tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) tink_cc_library( NAME keyset_handle_builder_entry SRCS keyset_handle_builder_entry.cc keyset_handle_builder_entry.h DEPS tink::internal::key_status_util tink::internal::legacy_proto_key tink::internal::legacy_proto_parameters tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::internal::serialization absl::status absl::strings absl::optional tink::core::insecure_secret_key_access tink::core::key tink::core::key_status tink::core::parameters tink::core::registry tink::core::restricted_data tink::core::secret_key_access_token tink::util::secret_proto tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_test( NAME keyset_handle_builder_entry_test SRCS keyset_handle_builder_entry_test.cc DEPS tink::internal::keyset_handle_builder_entry tink::internal::legacy_proto_key tink::internal::legacy_proto_parameters tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization gmock absl::memory absl::status absl::optional tink::core::insecure_secret_key_access tink::core::key tink::core::key_status tink::core::keyset_handle tink::core::keyset_handle_builder tink::core::parameters tink::core::partial_key_access tink::core::restricted_data tink::core::secret_key_access_token tink::config::tink_config tink::mac::aes_cmac_key tink::mac::aes_cmac_parameters tink::mac::mac_key_templates tink::util::secret_proto tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) tink_cc_library( NAME serialization_registry SRCS serialization_registry.cc serialization_registry.h DEPS tink::internal::key_parser tink::internal::key_serializer tink::internal::parameters_parser tink::internal::parameters_serializer tink::internal::parser_index tink::internal::serialization tink::internal::serializer_index absl::flat_hash_map absl::status absl::str_format absl::optional tink::core::key tink::core::parameters tink::core::secret_key_access_token tink::util::status tink::util::statusor ) tink_cc_test( NAME serialization_registry_test SRCS serialization_registry_test.cc DEPS tink::internal::key_parser tink::internal::key_serializer tink::internal::parameters_parser tink::internal::parameters_serializer tink::internal::serialization tink::internal::serialization_registry tink::internal::serialization_test_util gmock absl::status absl::optional tink::core::insecure_secret_key_access tink::core::key tink::core::parameters tink::core::secret_key_access_token tink::util::status tink::util::statusor tink::util::test_matchers ) tink_cc_library( NAME mutable_serialization_registry SRCS mutable_serialization_registry.cc mutable_serialization_registry.h DEPS tink::internal::key_parser tink::internal::key_serializer tink::internal::legacy_proto_key tink::internal::parameters_parser tink::internal::parameters_serializer tink::internal::proto_key_serialization tink::internal::serialization tink::internal::serialization_registry absl::core_headers absl::memory absl::status absl::synchronization absl::optional tink::core::insecure_secret_key_access tink::core::key tink::core::parameters tink::core::secret_key_access_token tink::util::status tink::util::statusor ) tink_cc_test( NAME mutable_serialization_registry_test SRCS mutable_serialization_registry_test.cc DEPS tink::internal::key_parser tink::internal::key_serializer tink::internal::mutable_serialization_registry tink::internal::parameters_parser tink::internal::parameters_serializer tink::internal::proto_key_serialization tink::internal::serialization tink::internal::serialization_test_util gmock absl::status absl::optional tink::core::insecure_secret_key_access tink::core::key tink::core::parameters tink::core::restricted_data tink::core::secret_key_access_token tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) tink_cc_library( NAME serialization_test_util SRCS serialization_test_util.h DEPS tink::internal::serialization absl::strings absl::optional tink::core::key tink::core::parameters tink::core::secret_key_access_token tink::util::statusor TESTONLY ) tink_cc_test( NAME serialization_test_util_test SRCS serialization_test_util_test.cc DEPS tink::internal::serialization_test_util gmock absl::optional tink::core::insecure_secret_key_access tink::core::parameters tink::util::statusor tink::util::test_matchers ) tink_cc_library( NAME test_random_access_stream SRCS test_random_access_stream.cc test_random_access_stream.h DEPS absl::status absl::strings tink::core::random_access_stream tink::util::buffer tink::util::status tink::util::statusor TESTONLY ) tink_cc_test( NAME test_random_access_stream_test SRCS test_random_access_stream_test.cc DEPS tink::internal::test_random_access_stream gmock absl::status tink::subtle::random tink::util::buffer tink::util::status tink::util::test_matchers ) tink_cc_library( NAME configuration_impl SRCS configuration_impl.h DEPS tink::internal::key_type_info_store tink::internal::keyset_wrapper_store absl::status absl::string_view tink::core::configuration tink::core::key_manager tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_test( NAME configuration_impl_test SRCS configuration_impl_test.cc DEPS tink::internal::configuration_impl tink::internal::key_type_info_store tink::internal::keyset_wrapper tink::internal::keyset_wrapper_store gmock absl::memory absl::status tink::core::cleartext_keyset_handle tink::core::configuration tink::core::key_manager_impl tink::core::key_type_manager tink::core::private_key_type_manager tink::core::template_util tink::core::input_stream tink::core::key_manager tink::core::keyset_handle tink::core::primitive_set tink::core::primitive_wrapper tink::core::public_key_sign tink::core::public_key_verify tink::core::registry tink::subtle::random tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::aes_gcm_cc_proto tink::proto::rsa_ssa_pss_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME key_type_info_store SRCS key_type_info_store.cc key_type_info_store.h DEPS tink::internal::fips_utils absl::flat_hash_map absl::status absl::strings absl::optional tink::core::key_manager_impl tink::core::key_type_manager tink::core::private_key_manager_impl tink::core::private_key_type_manager tink::core::template_util tink::core::input_stream tink::core::key_manager tink::util::errors tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_test( NAME key_type_info_store_test SRCS key_type_info_store_test.cc DEPS tink::internal::fips_utils tink::internal::key_type_info_store gmock absl::memory absl::status absl::optional tink::core::aead tink::core::key_manager_impl tink::core::key_manager tink::core::public_key_sign tink::core::public_key_verify tink::aead::aes_gcm_key_manager tink::aead::cord_aead tink::aead::kms_envelope_aead_key_manager tink::signature::ecdsa_sign_key_manager tink::signature::ecdsa_verify_key_manager tink::util::statusor tink::util::test_matchers tink::proto::aes_gcm_cc_proto tink::proto::common_cc_proto tink::proto::ecdsa_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME keyset_wrapper_store SRCS keyset_wrapper_store.h DEPS tink::internal::keyset_wrapper tink::internal::keyset_wrapper_impl absl::flat_hash_map absl::any_invocable absl::status absl::strings tink::core::primitive_wrapper tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_test( NAME keyset_wrapper_store_test SRCS keyset_wrapper_store_test.cc DEPS tink::internal::keyset_wrapper tink::internal::keyset_wrapper_store tink::internal::registry_impl gmock absl::memory absl::status tink::core::key_type_manager tink::core::template_util tink::core::input_stream tink::core::mac tink::core::primitive_set tink::core::primitive_wrapper tink::mac::mac_wrapper tink::subtle::random tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::aes_gcm_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME key_gen_configuration_impl SRCS key_gen_configuration_impl.h DEPS tink::internal::key_type_info_store absl::status absl::string_view tink::core::key_gen_configuration tink::core::key_manager tink::util::status tink::util::statusor ) tink_cc_test( NAME key_gen_configuration_impl_test SRCS key_gen_configuration_impl_test.cc DEPS tink::internal::key_gen_configuration_impl tink::internal::key_type_info_store gmock absl::memory absl::status tink::core::key_manager_impl tink::core::key_type_manager tink::core::private_key_type_manager tink::core::template_util tink::core::input_stream tink::core::key_gen_configuration tink::core::key_manager tink::core::keyset_handle tink::core::public_key_sign tink::core::public_key_verify tink::core::registry tink::aead::aead_key_templates tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::aes_gcm_cc_proto tink::proto::rsa_ssa_pss_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME call_with_core_dump_protection SRCS call_with_core_dump_protection.h ) tink_cc_test( NAME call_with_core_dump_protection_test SRCS call_with_core_dump_protection_test.cc DEPS tink::internal::call_with_core_dump_protection gmock ) tink_cc_library( NAME safe_stringops SRCS safe_stringops.h DEPS crypto tink::internal::call_with_core_dump_protection ) tink_cc_test( NAME safe_stringops_test SRCS safe_stringops_test.cc DEPS tink::internal::safe_stringops gmock ) tink_cc_library( NAME bn_encoding_util SRCS bn_encoding_util.cc bn_encoding_util.h DEPS absl::status absl::strings absl::str_format absl::string_view crypto tink::util::status tink::util::statusor ) tink_cc_test( NAME bn_encoding_util_test SRCS bn_encoding_util_test.cc DEPS tink::internal::bn_encoding_util gmock absl::status absl::strings tink::core::big_integer tink::util::statusor tink::util::test_matchers ) ================================================ FILE: cc/internal/aes_util.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/aes_util.h" #include #include #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "openssl/aes.h" #include "openssl/evp.h" #include "tink/util/statusor.h" #ifndef OPENSSL_IS_BORINGSSL // This is needed to use block128_f, which is necessary when OpenSSL is used. #include "openssl/modes.h" #endif #include "tink/internal/util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { util::Status AesCtr128Crypt(absl::string_view data, uint8_t iv[AesBlockSize()], const AES_KEY* key, absl::Span out) { if (out.size() < data.size()) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid size for output buffer; expected at least ", data.size(), " got ", out.size())); } // Only full overlap or no overlap is allowed. if (!BuffersAreIdentical(data, absl::string_view(out.data(), out.size())) && BuffersOverlap(data, absl::string_view(out.data(), out.size()))) { return util::Status(absl::StatusCode::kInvalidArgument, "Buffers must not partially overlap"); } unsigned int num = 0; std::vector ecount_buf(AesBlockSize(), 0); // OpenSSL >= v1.1.0 public APIs no longer exposes an AES_ctr128_encrypt // function; as an alternative we use CRYPTO_ctr128_encrypt when OpenSSL is // used as a backend. The latter is not part of the public API of BoringSSL, // so we must selectively compile using either of them. #ifdef OPENSSL_IS_BORINGSSL AES_ctr128_encrypt(reinterpret_cast(data.data()), reinterpret_cast(out.data()), data.size(), key, iv, ecount_buf.data(), &num); #else CRYPTO_ctr128_encrypt(reinterpret_cast(data.data()), reinterpret_cast(out.data()), data.size(), key, iv, ecount_buf.data(), &num, reinterpret_cast(AES_encrypt)); #endif return util::OkStatus(); } util::StatusOr GetAesCtrCipherForKeySize( uint32_t key_size_in_bytes) { switch (key_size_in_bytes) { case 16: return EVP_aes_128_ctr(); case 32: return EVP_aes_256_ctr(); default: return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid key size ", key_size_in_bytes)); } } util::StatusOr GetAesCbcCipherForKeySize( uint32_t key_size_in_bytes) { switch (key_size_in_bytes) { case 16: return EVP_aes_128_cbc(); case 32: return EVP_aes_256_cbc(); } return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid key size ", key_size_in_bytes)); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/aes_util.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_AES_UTIL_H_ #define TINK_INTERNAL_AES_UTIL_H_ #include #include #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "openssl/aes.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { // AES block size in bytes. constexpr int AesBlockSize() { return 16; } // Wrapper for BoringSSL/OpenSSL low-level functions that encrypt/decrypt (same // operation in CTR mode) `data`, with IV `iv` and key `key`. The result is // written to `out`. `out` may fully overlap with `data`; partial overlaps will // result in an kInvalidArgument error. `iv` is incremented of the number of // blocks that were encrypted/decrypted. crypto::tink::util::Status AesCtr128Crypt(absl::string_view data, uint8_t iv[AesBlockSize()], const AES_KEY* key, absl::Span out); // Returns a pointer to an AES-CTR EVP_CIPHER for the given key size // `key_size_in_bytes`. util::StatusOr GetAesCtrCipherForKeySize( uint32_t key_size_in_bytes); // Returns a pointer to an AES-CBC EVP_CIPHER for the given key size // `key_size_in_bytes`. util::StatusOr GetAesCbcCipherForKeySize( uint32_t key_size_in_bytes); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_AES_UTIL_H_ ================================================ FILE: cc/internal/aes_util_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/aes_util.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "openssl/aes.h" #include "openssl/evp.h" #include "tink/subtle/subtle_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::testing::HasSubstr; using ::testing::Not; struct NistAesCtrTestVector { std::string iv; std::string key; std::string plaintext; std::string ciphertext; }; class AesCtrTest : public testing::Test { protected: AesCtrTest() : aes_key_(util::MakeSecretUniquePtr()) {} void SetUp() override { ASSERT_EQ(AES_set_encrypt_key( reinterpret_cast(test_vector_.key.data()), /*bits=*/test_vector_.key.size() * 8, aes_key_.get()), 0); } // Test vector from NIST SP 800-38A. NistAesCtrTestVector test_vector_ = { /*iv=*/absl::HexStringToBytes("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"), /*key=*/absl::HexStringToBytes("2b7e151628aed2a6abf7158809cf4f3c"), /*plaintext=*/ absl::HexStringToBytes( "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c8" "1c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"), /*ciphertext=*/ absl::HexStringToBytes( "874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4" "df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee"), }; const util::SecretUniquePtr aes_key_; }; // Check that AesCtr128Crypt fails when out buffer is too small. TEST_F(AesCtrTest, AesCtrInvalidOutSize) { std::string out; for (int size = 0; size < test_vector_.plaintext.size(); size++) { subtle::ResizeStringUninitialized(&out, size); EXPECT_THAT(AesCtr128Crypt(test_vector_.plaintext, reinterpret_cast(&test_vector_.iv[0]), aes_key_.get(), absl::MakeSpan(out)), Not(IsOk())); } } // Partial overlap of buffers of the right size is not allowed. TEST_F(AesCtrTest, AesCtrPartiallyOverlappingFails) { std::string out; subtle::ResizeStringUninitialized(&out, 2 * test_vector_.plaintext.size()); const int kStartIndex = test_vector_.plaintext.size() / 2; std::copy(test_vector_.plaintext.begin(), test_vector_.plaintext.end(), out.begin() + kStartIndex); auto plaintext = absl::string_view(out).substr(kStartIndex, test_vector_.plaintext.size()); util::Status res = AesCtr128Crypt( plaintext, reinterpret_cast(&test_vector_.iv[0]), aes_key_.get(), absl::MakeSpan(out).subspan(0, plaintext.size())); // Checking the message to disambiguate from the kInvalidArgumentError that is // returned in case of wrong size of the output buffer. EXPECT_THAT( res, StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("overlap"))); res = AesCtr128Crypt( plaintext, reinterpret_cast(&test_vector_.iv[0]), aes_key_.get(), absl::MakeSpan(out).subspan(plaintext.size(), plaintext.size())); EXPECT_THAT( res, StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("overlap"))); } TEST_F(AesCtrTest, AesCtrEncrypt) { std::string out; subtle::ResizeStringUninitialized(&out, test_vector_.plaintext.size()); ASSERT_THAT(AesCtr128Crypt(test_vector_.plaintext, reinterpret_cast(&test_vector_.iv[0]), aes_key_.get(), absl::MakeSpan(out)), IsOk()); EXPECT_EQ(out, test_vector_.ciphertext); } TEST_F(AesCtrTest, AesCtrEncryptInPlace) { std::string inout = test_vector_.plaintext; ASSERT_THAT( AesCtr128Crypt(inout, reinterpret_cast(&test_vector_.iv[0]), aes_key_.get(), absl::MakeSpan(inout)), IsOk()); EXPECT_EQ(inout, test_vector_.ciphertext); } TEST_F(AesCtrTest, AesCtrDecrypt) { std::string out; subtle::ResizeStringUninitialized(&out, test_vector_.ciphertext.size()); ASSERT_THAT(AesCtr128Crypt(test_vector_.ciphertext, reinterpret_cast(&test_vector_.iv[0]), aes_key_.get(), absl::MakeSpan(out)), IsOk()); EXPECT_EQ(out, test_vector_.plaintext); } TEST_F(AesCtrTest, AesCtrDecryptInPlace) { std::string inout = test_vector_.ciphertext; ASSERT_THAT( AesCtr128Crypt(inout, reinterpret_cast(&test_vector_.iv[0]), aes_key_.get(), absl::MakeSpan(inout)), IsOk()); EXPECT_EQ(inout, test_vector_.plaintext); } TEST(AesUtilTest, GetAesCtrCipherForKeySize) { for (int i = 0; i < 64; i++) { util::StatusOr cipher = GetAesCtrCipherForKeySize(i); if (i == 16) { EXPECT_THAT(cipher, IsOkAndHolds(EVP_aes_128_ctr())); } else if (i == 32) { EXPECT_THAT(cipher, IsOkAndHolds(EVP_aes_256_ctr())); } else { EXPECT_THAT(cipher, Not(IsOk())); } } } TEST(AesUtilTest, GetAesCbcCipherForKeySize) { for (int i = 0; i < 64; i++) { util::StatusOr cipher = GetAesCbcCipherForKeySize(i); if (i == 16) { EXPECT_THAT(cipher, IsOkAndHolds(EVP_aes_128_cbc())); } else if (i == 32) { EXPECT_THAT(cipher, IsOkAndHolds(EVP_aes_256_cbc())); } else { EXPECT_THAT(cipher, Not(IsOk())); } } } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/bn_encoding_util.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/bn_encoding_util.h" #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { util::StatusOr GetValueOfFixedLength( absl::string_view big_integer_encoding, int length) { if (big_integer_encoding.size() == length) { return std::string(big_integer_encoding); } if (big_integer_encoding.size() > length) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrFormat( "Value too large for the given length. Expected %d, got %d", length, big_integer_encoding.size())); } std::string padded_string(length - big_integer_encoding.size(), 0); return absl::StrCat(padded_string, big_integer_encoding); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/bn_encoding_util.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_BN_ENCODING_UTIL_H_ #define TINK_INTERNAL_BN_ENCODING_UTIL_H_ #include #include #include "absl/strings/string_view.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { // Returns the value of a big integer `big_integer_encoding` (represented as a // big endian encoded string), left padded to obtain a fixed length `length`. // Returns an error if the `length` is too short. crypto::tink::util::StatusOr GetValueOfFixedLength( absl::string_view big_integer_encoding, int length); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_BN_ENCODING_UTIL_H_ ================================================ FILE: cc/internal/bn_encoding_util_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/bn_encoding_util.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/big_integer.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::SizeIs; TEST(BnEncodingUtilTest, GetValueOfFixedLength) { std::vector bn_str = {"0000000000000000", "0000000000000001", "1000000000000000", "ffffffffffffffff", "0fffffffffffffff", "00ffffffffffffff"}; for (const std::string& s : bn_str) { const std::string bn_bytes = absl::HexStringToBytes(s); util::StatusOr bn_bytes_fixed_length = GetValueOfFixedLength(bn_bytes, 10); EXPECT_THAT(bn_bytes_fixed_length, IsOkAndHolds(absl::HexStringToBytes(absl::StrCat("0000", s)))); } } TEST(BnEncodingUtilTest, GetValueOfFixedLengthIntegerTooBig) { std::string bn_str = "0fffffffffffffff"; const std::string bn_bytes = absl::HexStringToBytes(bn_str); util::StatusOr bn_bytes_fixed_length = GetValueOfFixedLength(bn_bytes, 2); EXPECT_THAT(bn_bytes_fixed_length.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(BnEncodingUtilTest, GetValueOfFixedLengthSameLength) { std::string bn_str = "0fffffffffffffff"; const std::string bn_bytes = absl::HexStringToBytes(bn_str); util::StatusOr bn_bytes_fixed_length = GetValueOfFixedLength(bn_bytes, 8); EXPECT_THAT(bn_bytes_fixed_length, IsOkAndHolds(bn_bytes)); } TEST(BnEncodingUtilTest, CreateBigIntegerObjectOfFixedLength) { constexpr absl::string_view big_integer_hex_256 = "b3510a2bcd4ce644c5b594ae5059e12b2f054b658d5da5959a2fdf1871b808bc3df3e628" "d2792e51aad5c124b43bda453dca5cde4bcf28e7bd4effba0cb4b742bbb6d5a013cb63d1" "aa3a89e02627ef5398b52c0cfd97d208abeb8d7c9bce0bbeb019a86ddb589beb29a5b74b" "f861075c677c81d430f030c265247af9d3c9140ccb65309d07e0adc1efd15cf17e7b055d" "7da3868e4648cc3a180f0ee7f8e1e7b18098a3391b4ce7161e98d57af8a947e201a463e2" "d6bbca8059e5706e9dfed8f4856465ffa712ed1aa18e888d12dc6aa09ce95ecfca83cc5b" "0b15db09c8647f5d524c0f2e7620a3416b9623cadc0f097af573261c98c8400aa12af38e" "43cad84d"; const std::string big_integer_bytes_256 = absl::HexStringToBytes(big_integer_hex_256); util::StatusOr big_integer_bytes_fixed_length = GetValueOfFixedLength(big_integer_bytes_256, 258); BigInteger big_integer(big_integer_bytes_256); EXPECT_THAT(big_integer.SizeInBytes(), Eq(256)); EXPECT_THAT(big_integer.GetValue(), Eq(big_integer_bytes_256)); EXPECT_THAT(*big_integer_bytes_fixed_length, SizeIs(258)); EXPECT_THAT( big_integer_bytes_fixed_length, IsOkAndHolds(absl::HexStringToBytes( "0000b3510a2bcd4ce644c5b594ae5059e12b2f054b658d5da5959a2fdf1871b808bc" "3df3e628d2792e51aad5c124b43bda453dca5cde4bcf28e7bd4effba0cb4b742bbb6" "d5a013cb63d1aa3a89e02627ef5398b52c0cfd97d208abeb8d7c9bce0bbeb019a86d" "db589beb29a5b74bf861075c677c81d430f030c265247af9d3c9140ccb65309d07e0" "adc1efd15cf17e7b055d7da3868e4648cc3a180f0ee7f8e1e7b18098a3391b4ce716" "1e98d57af8a947e201a463e2d6bbca8059e5706e9dfed8f4856465ffa712ed1aa18e" "888d12dc6aa09ce95ecfca83cc5b0b15db09c8647f5d524c0f2e7620a3416b9623ca" "dc0f097af573261c98c8400aa12af38e43cad84d"))); BigInteger same_big_integer(*big_integer_bytes_fixed_length); EXPECT_THAT(big_integer, Eq(same_big_integer)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/bn_util.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/bn_util.h" #include #include #include #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "openssl/bn.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/subtle/subtle_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { util::Status BignumToBinaryPadded(absl::Span buffer, const BIGNUM *bignum) { if (bignum == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "BIGNUM is NULL"); } if (BN_is_negative(bignum)) { return util::Status(absl::StatusCode::kInternal, "Value must not be negative"); } // BN_bn2binpad returns the length of the buffer on success and -1 on failure. int len = BN_bn2binpad( bignum, reinterpret_cast(buffer.data()), buffer.size()); if (len == -1) { return util::Status(absl::StatusCode::kInternal, "Value too large to fit into the given buffer"); } return util::OkStatus(); } util::StatusOr BignumToString(const BIGNUM *bn, size_t len) { if (bn == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "BIGNUM is NULL"); } std::string buffer; subtle::ResizeStringUninitialized(&buffer, len); util::Status res = BignumToBinaryPadded(absl::MakeSpan(&buffer[0], len), bn); if (!res.ok()) { return res; } return buffer; } util::StatusOr BignumToSecretData(const BIGNUM *bn, size_t len) { if (bn == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "BIGNUM is NULL"); } util::SecretData secret_data(len); util::Status res = BignumToBinaryPadded( absl::MakeSpan(reinterpret_cast(secret_data.data()), secret_data.size()), bn); if (!res.ok()) { return res; } return secret_data; } util::StatusOr> StringToBignum( absl::string_view bigendian_bn_str) { internal::SslUniquePtr bn(BN_bin2bn( reinterpret_cast(bigendian_bn_str.data()), bigendian_bn_str.length(), /*ret=*/nullptr)); if (bn.get() == nullptr) { return util::Status(absl::StatusCode::kInternal, "BIGNUM allocation failed"); } return std::move(bn); } int CompareBignumWithWord(const BIGNUM *bignum, BN_ULONG word) { #ifdef OPENSSL_IS_BORINGSSL return BN_cmp_word(bignum, word); #else internal::SslUniquePtr bn_word(BN_new()); BN_set_word(bn_word.get(), word); return BN_cmp(bignum, bn_word.get()); #endif } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/bn_util.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_BN_UTIL_H_ #define TINK_INTERNAL_BN_UTIL_H_ #include #include #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "openssl/bn.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { // Compares `bignum` with the given `word`. It returns a result < 0 if `bignum` // < `word`, 0 if `bignum` == `word`, and > 0 if `bignum` > `word`. int CompareBignumWithWord(const BIGNUM* bignum, BN_ULONG word); // Converts the absolute value of `bignum` into a big-endian form, and writes it // in `buffer`. crypto::tink::util::Status BignumToBinaryPadded(absl::Span buffer, const BIGNUM* bignum); // Retuns a string that encodes `bn` in big-endian form of size `len` with // leading zeroes. crypto::tink::util::StatusOr BignumToString(const BIGNUM* bn, size_t len); // Retuns a SecretData object that encodes `bn` in big-endian form of size `len` // with leading zeroes. crypto::tink::util::StatusOr BignumToSecretData( const BIGNUM* bn, size_t len); // Returns an OpenSSL/BoringSSL BIGNUM constructed from a bigendian string // representation `bigendian_bn_str`. crypto::tink::util::StatusOr> StringToBignum( absl::string_view bigendian_bn_str); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_BN_UTIL_H_ ================================================ FILE: cc/internal/bn_util_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/bn_util.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "openssl/bn.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::testing::Not; util::StatusOr> HexToBignum( absl::string_view bn_hex) { BIGNUM* bn = nullptr; BN_hex2bn(&bn, bn_hex.data()); return internal::SslUniquePtr(bn); } TEST(BnUtil, StringToBignum) { std::vector bn_str = {"0000000000000000", "0000000000000001", "1000000000000000", "ffffffffffffffff", "0fffffffffffffff", "00ffffffffffffff"}; for (const std::string& s : bn_str) { const std::string bn_bytes = absl::HexStringToBytes(s); util::StatusOr> bn = StringToBignum(bn_bytes); ASSERT_THAT(bn, IsOk()); util::StatusOr> expected_bn = HexToBignum(s); ASSERT_THAT(expected_bn, IsOk()); EXPECT_EQ(BN_cmp(expected_bn->get(), bn->get()), 0); } } TEST(StringToBignum, IgnoresLeadingZeros) { std::string encoded = absl::HexStringToBytes("0102"); std::string encoded_with_leading_zeros = absl::HexStringToBytes("0000000102"); util::StatusOr> num = StringToBignum(encoded); ASSERT_THAT(num, IsOk()); util::StatusOr> num2 = StringToBignum(encoded_with_leading_zeros); ASSERT_THAT(num2, IsOk()); EXPECT_EQ(BN_cmp(num2->get(), num->get()), 0); } TEST(BnUtil, BignumToString) { std::vector bn_strs = {"0000000000000000", "0000000000000001", "1000000000000000", "ffffffffffffffff", "0fffffffffffffff", "00ffffffffffffff"}; for (const std::string& s : bn_strs) { util::StatusOr> expected_bn = HexToBignum(s); ASSERT_THAT(expected_bn, IsOk()); const std::string bn_bytes = absl::HexStringToBytes(s); util::StatusOr result = BignumToString(expected_bn->get(), bn_bytes.size()); ASSERT_THAT(result, IsOk()); EXPECT_EQ(bn_bytes, *result); } } TEST(BignumToStringWithBNNumBytes, NoLeadingZeros) { { util::StatusOr> bn0 = StringToBignum(absl::HexStringToBytes("000000")); ASSERT_THAT(bn0, IsOk()); util::StatusOr encoded0 = internal::BignumToString(bn0->get(), BN_num_bytes(bn0->get())); ASSERT_THAT(encoded0, IsOk()); EXPECT_EQ(*encoded0, absl::HexStringToBytes("")); } { util::StatusOr> bn127 = StringToBignum(absl::HexStringToBytes("00007F")); ASSERT_THAT(bn127, IsOk()); util::StatusOr encoded127 = internal::BignumToString(bn127->get(), BN_num_bytes(bn127->get())); ASSERT_THAT(encoded127, IsOk()); EXPECT_EQ(*encoded127, absl::HexStringToBytes("7F")); } { util::StatusOr> bn128 = StringToBignum(absl::HexStringToBytes("000080")); ASSERT_THAT(bn128, IsOk()); util::StatusOr encoded128 = internal::BignumToString(bn128->get(), BN_num_bytes(bn128->get())); ASSERT_THAT(encoded128, IsOk()); EXPECT_EQ(*encoded128, absl::HexStringToBytes("80")); } { util::StatusOr> bn255 = StringToBignum(absl::HexStringToBytes("0000FF")); ASSERT_THAT(bn255, IsOk()); util::StatusOr encoded255 = internal::BignumToString(bn255->get(), BN_num_bytes(bn255->get())); ASSERT_THAT(encoded255, IsOk()); EXPECT_EQ(*encoded255, absl::HexStringToBytes("FF")); } { util::StatusOr> bn256 = StringToBignum(absl::HexStringToBytes("000100")); ASSERT_THAT(bn256, IsOk()); util::StatusOr encoded256 = internal::BignumToString(bn256->get(), BN_num_bytes(bn256->get())); ASSERT_THAT(encoded256, IsOk()); EXPECT_EQ(*encoded256, absl::HexStringToBytes("0100")); } } TEST(BignumToString, PadsWithLeadingZeros) { util::StatusOr> num = StringToBignum(absl::HexStringToBytes("0102")); ASSERT_THAT(num, IsOk()); util::StatusOr encoded = BignumToString(num->get(), /*len=*/ 2); ASSERT_THAT(encoded, IsOk()); EXPECT_EQ(*encoded, absl::HexStringToBytes("0102")); util::StatusOr encodedWithPadding = BignumToString(num->get(), /*len=*/ 5); ASSERT_THAT(encodedWithPadding, IsOk()); EXPECT_EQ(*encodedWithPadding, absl::HexStringToBytes("0000000102")); // try to encode with a value for len that is too short. ASSERT_THAT(BignumToString(num->get(), /*len=*/1), Not(IsOk())); } TEST(BignumToString, RejectsNegativeNumbers) { // create a negative BIGNUM util::StatusOr> number = HexToBignum("01"); ASSERT_THAT(number, IsOk()); BN_set_negative(number->get(), 1); // Check that number is negative ASSERT_EQ(CompareBignumWithWord(number->get(), /*word=*/0), -1); ASSERT_THAT(BignumToString(number->get(), /*len=*/2), Not(IsOk())); } TEST(BnUtil, BignumToSecretData) { std::vector bn_strs = {"0000000000000000", "0000000000000001", "1000000000000000", "ffffffffffffffff", "0fffffffffffffff", "00ffffffffffffff"}; for (const std::string& s : bn_strs) { util::StatusOr> expected_bn = HexToBignum(s); ASSERT_THAT(expected_bn, IsOk()); const std::string bn_bytes = absl::HexStringToBytes(s); util::StatusOr result = BignumToSecretData(expected_bn->get(), bn_bytes.size()); ASSERT_THAT(result, IsOk()); auto result_data = absl::string_view( reinterpret_cast(result->data()), result->size()); EXPECT_EQ(absl::string_view(bn_bytes), result_data); } } TEST(BnUtil, BignumToBinaryPadded) { std::vector bn_strs = {"0000000000000000", "0000000000000001", "1000000000000000", "ffffffffffffffff", "0fffffffffffffff", "00ffffffffffffff"}; for (const std::string& s : bn_strs) { util::StatusOr> expected_bn = HexToBignum(s); ASSERT_THAT(expected_bn, IsOk()); const std::string bn_bytes = absl::HexStringToBytes(s); std::vector buffer; buffer.resize(bn_bytes.size()); util::Status res = BignumToBinaryPadded( absl::MakeSpan(buffer.data(), buffer.size()), expected_bn->get()); ASSERT_THAT(res, IsOk()); auto buffer_data = absl::string_view(buffer.data(), buffer.size()); EXPECT_EQ(absl::string_view(bn_bytes), buffer_data); } } // Make sure that for every buffer size that is smaller than the actual BN as a // string, we get an error. TEST(BnUtil, BufferToSmall) { const std::string bn_str = "0fffffffffffffff"; util::StatusOr> expected_bn = HexToBignum(bn_str); ASSERT_THAT(expected_bn, IsOk()); const std::string bn_bytes = absl::HexStringToBytes(bn_str); for (size_t buffer_size = 1; buffer_size < bn_bytes.size(); buffer_size++) { { std::vector buffer; buffer.resize(buffer_size); util::Status result = BignumToBinaryPadded( absl::MakeSpan(buffer.data(), buffer.size()), expected_bn->get()); EXPECT_THAT(result, Not(IsOk())); } { util::StatusOr result = BignumToString(expected_bn->get(), buffer_size); EXPECT_THAT(result, Not(IsOk())); } { util::StatusOr result = BignumToSecretData(expected_bn->get(), buffer_size); EXPECT_THAT(result, Not(IsOk())); } } } TEST(BnUtil, CompareBignumWithWord) { internal::SslUniquePtr bn(BN_new()); BN_set_word(bn.get(), /*value=*/0x0fffffffffffffffUL); EXPECT_EQ(CompareBignumWithWord(bn.get(), /*word=*/0x0fffffffffffffffL), 0); std::vector smaller_words = { 0x0000000000000000UL, 0x0000000000000001UL, 0x00ffffffffffffffUL}; for (const auto& word : smaller_words) { EXPECT_GT(CompareBignumWithWord(bn.get(), word), 0) << absl::StrCat("With value: 0x", absl::Hex(word)); } std::vector larger_words = {0x1000000000000000UL, 0xffffffffffffffffUL}; for (const auto& word : larger_words) { EXPECT_LT(CompareBignumWithWord(bn.get(), word), 0) << absl::StrCat("With value: 0x", absl::Hex(word)); } } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/call_with_core_dump_protection.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_CALL_WITH_CORE_DUMP_PROTECTION_H_ #define TINK_INTERNAL_CALL_WITH_CORE_DUMP_PROTECTION_H_ namespace crypto { namespace tink { namespace internal { // Just a stub. // Internally we have great control over core dump collection and use this // function to redact execution state (e.g. CPU register values) of sensitive // crypto operations. // If you are interested in implementing it for your platform, open a GitHub // issue. template auto CallWithCoreDumpProtection(Func&& func) -> decltype(func()) { return func(); } } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_CALL_WITH_CORE_DUMP_PROTECTION_H_ ================================================ FILE: cc/internal/call_with_core_dump_protection_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/call_with_core_dump_protection.h" #include "gtest/gtest.h" namespace crypto { namespace tink { namespace internal { namespace { TEST(CallWithCoreDumpProtectionTest, Basic) { EXPECT_EQ(CallWithCoreDumpProtection([]() { return 1 + 2; }), 3); } TEST(CallWithCoreDumpProtectionTest, WithCapture) { int a = 10; int b = 20; EXPECT_EQ(CallWithCoreDumpProtection([&]() { return a + b; }), a + b); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/configuration_impl.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_CONFIGURATION_IMPL_H_ #define TINK_INTERNAL_CONFIGURATION_IMPL_H_ #include #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/configuration.h" #include "tink/internal/key_type_info_store.h" #include "tink/internal/keyset_wrapper_store.h" #include "tink/key_manager.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { constexpr absl::string_view kConfigurationImplErr = "Use crypto::tink::Registry instead when in global registry mode."; class ConfigurationImpl { public: template static crypto::tink::util::Status AddPrimitiveWrapper( std::unique_ptr wrapper, crypto::tink::Configuration& config) { if (config.global_registry_mode_) { return crypto::tink::util::Status(absl::StatusCode::kFailedPrecondition, kConfigurationImplErr); } // `primitive_getter` must be defined here, as PW::InputPrimitive is not // accessible later. // TODO(b/284084337): Move primitive getter out of key manager. std::function>( const google::crypto::tink::KeyData& key_data)> primitive_getter = [&config](const google::crypto::tink::KeyData& key_data) -> crypto::tink::util::StatusOr< std::unique_ptr> { crypto::tink::util::StatusOr< const crypto::tink::internal::KeyTypeInfoStore::Info*> info = config.key_type_info_store_.Get(key_data.type_url()); if (!info.ok()) { return info.status(); } return (*info)->GetPrimitive(key_data); }; return config.keyset_wrapper_store_ .Add( std::move(wrapper), primitive_getter); } template static crypto::tink::util::Status AddKeyTypeManager( std::unique_ptr key_manager, crypto::tink::Configuration& config) { if (config.global_registry_mode_) { return crypto::tink::util::Status(absl::StatusCode::kFailedPrecondition, kConfigurationImplErr); } return config.key_type_info_store_.AddKeyTypeManager( std::move(key_manager), /*new_key_allowed=*/true); } template static crypto::tink::util::Status AddAsymmetricKeyManagers( std::unique_ptr private_key_manager, std::unique_ptr public_key_manager, crypto::tink::Configuration& config) { if (config.global_registry_mode_) { return crypto::tink::util::Status(absl::StatusCode::kFailedPrecondition, kConfigurationImplErr); } return config.key_type_info_store_.AddAsymmetricKeyTypeManagers( std::move(private_key_manager), std::move(public_key_manager), /*new_key_allowed=*/true); } template static crypto::tink::util::Status AddLegacyKeyManager( std::unique_ptr> key_manager, crypto::tink::Configuration& config) { if (config.global_registry_mode_) { return crypto::tink::util::Status(absl::StatusCode::kFailedPrecondition, kConfigurationImplErr); } return config.key_type_info_store_.AddKeyManager(std::move(key_manager), /*new_key_allowed=*/true); } static crypto::tink::util::StatusOr< const crypto::tink::internal::KeyTypeInfoStore*> GetKeyTypeInfoStore(const crypto::tink::Configuration& config) { if (config.global_registry_mode_) { return crypto::tink::util::Status(absl::StatusCode::kFailedPrecondition, kConfigurationImplErr); } return &config.key_type_info_store_; } static crypto::tink::util::StatusOr< const crypto::tink::internal::KeysetWrapperStore*> GetKeysetWrapperStore(const crypto::tink::Configuration& config) { if (config.global_registry_mode_) { return crypto::tink::util::Status(absl::StatusCode::kFailedPrecondition, kConfigurationImplErr); } return &config.keyset_wrapper_store_; } // `config` can be set to global registry mode only if empty. static crypto::tink::util::Status SetGlobalRegistryMode( crypto::tink::Configuration& config) { if (!config.key_type_info_store_.IsEmpty() || !config.keyset_wrapper_store_.IsEmpty()) { return crypto::tink::util::Status(absl::StatusCode::kFailedPrecondition, "Using the global registry is only " "allowed when Configuration is empty."); } config.global_registry_mode_ = true; return crypto::tink::util::OkStatus(); } static bool IsInGlobalRegistryMode( const crypto::tink::Configuration& config) { return config.global_registry_mode_; } }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_CONFIGURATION_IMPL_H_ ================================================ FILE: cc/internal/configuration_impl_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/configuration_impl.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/cleartext_keyset_handle.h" #include "tink/configuration.h" #include "tink/core/key_manager_impl.h" #include "tink/core/key_type_manager.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/input_stream.h" #include "tink/internal/key_type_info_store.h" #include "tink/internal/keyset_wrapper.h" #include "tink/internal/keyset_wrapper_store.h" #include "tink/key_manager.h" #include "tink/keyset_handle.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/registry.h" #include "tink/subtle/random.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_gcm.pb.h" #include "proto/rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::AesGcmKey; using ::google::crypto::tink::AesGcmKeyFormat; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::Keyset; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::OutputPrefixType; using ::google::crypto::tink::RsaSsaPssKeyFormat; using ::google::crypto::tink::RsaSsaPssParams; using ::google::crypto::tink::RsaSsaPssPrivateKey; using ::google::crypto::tink::RsaSsaPssPublicKey; class FakePrimitive { public: explicit FakePrimitive(std::string s) : s_(s) {} std::string get() { return s_; } private: std::string s_; }; class FakePrimitive2 { public: explicit FakePrimitive2(std::string s) : s_(s) {} std::string get() { return s_ + "2"; } private: std::string s_; }; // Transforms AesGcmKey into FakePrimitive. class FakeKeyTypeManager : public KeyTypeManager> { public: class FakePrimitiveFactory : public PrimitiveFactory { public: util::StatusOr> Create( const AesGcmKey& key) const override { return absl::make_unique(key.key_value()); } }; FakeKeyTypeManager() : KeyTypeManager(absl::make_unique()) {} KeyData::KeyMaterialType key_material_type() const override { return KeyData::SYMMETRIC; } uint32_t get_version() const override { return 0; } const std::string& get_key_type() const override { return key_type_; } util::Status ValidateKey(const AesGcmKey& key) const override { return util::OkStatus(); } util::Status ValidateKeyFormat( const AesGcmKeyFormat& key_format) const override { return util::OkStatus(); } util::StatusOr CreateKey( const AesGcmKeyFormat& key_format) const override { return AesGcmKey(); } util::StatusOr DeriveKey( const AesGcmKeyFormat& key_format, InputStream* input_stream) const override { return AesGcmKey(); } private: const std::string key_type_ = "type.googleapis.com/google.crypto.tink.AesGcmKey"; }; // Transforms FakePrimitive into FakePrimitive. class FakePrimitiveWrapper : public PrimitiveWrapper { public: util::StatusOr> Wrap( std::unique_ptr> primitive_set) const override { return absl::make_unique( primitive_set->get_primary()->get_primitive().get()); } }; // Transforms FakePrimitive2 into FakePrimitive. class FakePrimitiveWrapper2 : public PrimitiveWrapper { public: util::StatusOr> Wrap( std::unique_ptr> primitive_set) const override { return absl::make_unique( primitive_set->get_primary()->get_primitive().get()); } }; std::string AddAesGcmKeyToKeyset(Keyset& keyset, uint32_t key_id, OutputPrefixType output_prefix_type, KeyStatusType key_status_type) { AesGcmKey key; key.set_version(0); key.set_key_value(subtle::Random::GetRandomBytes(16)); KeyData key_data; key_data.set_value(key.SerializeAsString()); key_data.set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey"); test::AddKeyData(key_data, key_id, output_prefix_type, key_status_type, &keyset); return key.key_value(); } TEST(ConfigurationImplTest, AddPrimitiveWrapper) { Configuration config; EXPECT_THAT((ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config)), IsOk()); } TEST(ConfigurationImplTest, AddKeyTypeManager) { Configuration config; EXPECT_THAT(ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config), IsOk()); } TEST(ConfigurationImplTest, AddLegacyKeyManager) { Configuration config; FakeKeyTypeManager manager; EXPECT_THAT(ConfigurationImpl::AddLegacyKeyManager( MakeKeyManager(&manager), config), IsOk()); } TEST(ConfigurationImplTest, GetKeyTypeInfoStore) { Configuration config; ASSERT_THAT(ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config), IsOk()); EXPECT_THAT(ConfigurationImpl::GetKeyTypeInfoStore(config), IsOk()); } TEST(ConfigurationImplTest, GetKeyTypeManager) { Configuration config; ASSERT_THAT(ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config), IsOk()); util::StatusOr store = ConfigurationImpl::GetKeyTypeInfoStore(config); ASSERT_THAT(store, IsOk()); std::string type_url = FakeKeyTypeManager().get_key_type(); util::StatusOr info = (*store)->Get(type_url); ASSERT_THAT(info, IsOk()); util::StatusOr*> key_manager = (*info)->get_key_manager(type_url); ASSERT_THAT(key_manager, IsOk()); EXPECT_EQ((*key_manager)->get_key_type(), type_url); } TEST(ConfigurationImplTest, GetLegacyKeyManager) { Configuration config; FakeKeyTypeManager manager; ASSERT_THAT(ConfigurationImpl::AddLegacyKeyManager( MakeKeyManager(&manager), config), IsOk()); util::StatusOr store = ConfigurationImpl::GetKeyTypeInfoStore(config); ASSERT_THAT(store, IsOk()); std::string type_url = FakeKeyTypeManager().get_key_type(); util::StatusOr info = (*store)->Get(type_url); ASSERT_THAT(info, IsOk()); util::StatusOr*> key_manager = (*info)->get_key_manager(type_url); ASSERT_THAT(key_manager, IsOk()); EXPECT_EQ((*key_manager)->get_key_type(), type_url); } TEST(ConfigurationImplTest, GetMissingKeyManagerFails) { Configuration config; util::StatusOr store = ConfigurationImpl::GetKeyTypeInfoStore(config); ASSERT_THAT(store, IsOk()); EXPECT_THAT((*store)->Get("i.do.not.exist").status(), StatusIs(absl::StatusCode::kNotFound)); } TEST(ConfigurationImplTest, GetKeysetWrapperStoreAndWrap) { Configuration config; ASSERT_THAT((ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config)), IsOk()); ASSERT_THAT(ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config), IsOk()); util::StatusOr store = ConfigurationImpl::GetKeysetWrapperStore(config); ASSERT_THAT(store, IsOk()); util::StatusOr*> wrapper = (*store)->Get(); ASSERT_THAT(wrapper, IsOk()); Keyset keyset; std::string raw_key = AddAesGcmKeyToKeyset( keyset, /*key_id=*/13, OutputPrefixType::TINK, KeyStatusType::ENABLED); keyset.set_primary_key_id(13); util::StatusOr> aead = (*wrapper)->Wrap(keyset, /*annotations=*/{}); ASSERT_THAT(aead, IsOk()); EXPECT_EQ((*aead)->get(), raw_key); } TEST(ConfigurationImplTest, KeysetWrapperWrapMissingKeyTypeInfoFails) { Configuration config; ASSERT_THAT(ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config), IsOk()); util::StatusOr store = ConfigurationImpl::GetKeysetWrapperStore(config); ASSERT_THAT(store, IsOk()); util::StatusOr*> wrapper = (*store)->Get(); ASSERT_THAT(wrapper, IsOk()); Keyset keyset; std::string raw_key = AddAesGcmKeyToKeyset( keyset, /*key_id=*/13, OutputPrefixType::TINK, KeyStatusType::ENABLED); keyset.set_primary_key_id(13); EXPECT_THAT((*wrapper)->Wrap(keyset, /*annotations=*/{}).status(), StatusIs(absl::StatusCode::kNotFound)); } TEST(ConfigurationImplTest, KeysetWrapperWrapMissingKeyManagerFails) { Configuration config; // Transforms FakePrimitive2 to FakePrimitive. ASSERT_THAT((ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config)), IsOk()); // Transforms KeyData to FakePrimitive. ASSERT_THAT(ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config), IsOk()); // AesGcmKey KeyData -> FakePrimitive2 -> FakePrimitive is the success path, // but the AesGcmKey KeyData -> FakePrimitive2 transformation is not // registered. util::StatusOr store = ConfigurationImpl::GetKeysetWrapperStore(config); ASSERT_THAT(store, IsOk()); util::StatusOr*> wrapper = (*store)->Get(); ASSERT_THAT(wrapper, IsOk()); Keyset keyset; std::string raw_key = AddAesGcmKeyToKeyset( keyset, /*key_id=*/13, OutputPrefixType::TINK, KeyStatusType::ENABLED); keyset.set_primary_key_id(13); // FakeKeyTypeManager cannot transform AesGcmKey KeyData -> FakePrimitive2. EXPECT_THAT((*wrapper)->Wrap(keyset, /*annotations=*/{}).status(), StatusIs(absl::StatusCode::kInvalidArgument)); } class FakeSignKeyManager : public PrivateKeyTypeManager> { public: class PublicKeySignFactory : public PrimitiveFactory { public: util::StatusOr> Create( const RsaSsaPssPrivateKey& key) const override { return {absl::make_unique("a public key sign")}; } }; explicit FakeSignKeyManager() : PrivateKeyTypeManager(absl::make_unique()) {} KeyData::KeyMaterialType key_material_type() const override { return KeyData::ASYMMETRIC_PRIVATE; } uint32_t get_version() const override { return 0; } const std::string& get_key_type() const override { return key_type_; } util::Status ValidateKey(const RsaSsaPssPrivateKey& key) const override { return util::OkStatus(); } util::Status ValidateKeyFormat( const RsaSsaPssKeyFormat& key_format) const override { return util::OkStatus(); } util::StatusOr CreateKey( const RsaSsaPssKeyFormat& key_format) const override { return RsaSsaPssPrivateKey(); } util::StatusOr DeriveKey( const RsaSsaPssKeyFormat& key_format, InputStream* input_stream) const override { return RsaSsaPssPrivateKey(); } util::StatusOr GetPublicKey( const RsaSsaPssPrivateKey& private_key) const override { return private_key.public_key(); } private: const std::string key_type_ = "some.sign.key.type"; }; class FakeVerifyKeyManager : public KeyTypeManager> { public: class PublicKeyVerifyFactory : public PrimitiveFactory { public: util::StatusOr> Create( const RsaSsaPssPublicKey& key) const override { return { absl::make_unique("a public key verify")}; } }; explicit FakeVerifyKeyManager() : KeyTypeManager(absl::make_unique()) {} KeyData::KeyMaterialType key_material_type() const override { return KeyData::ASYMMETRIC_PUBLIC; } uint32_t get_version() const override { return 0; } const std::string& get_key_type() const override { return key_type_; } util::Status ValidateKey(const RsaSsaPssPublicKey& key) const override { return util::OkStatus(); } util::Status ValidateParams(const RsaSsaPssParams& params) const { return util::OkStatus(); } private: const std::string key_type_ = "some.verify.key.type"; }; TEST(ConfigurationImplTest, AddAsymmetricKeyManagers) { Configuration config; EXPECT_THAT(ConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config), IsOk()); } TEST(ConfigurationImplTest, GetAsymmetricKeyManagers) { Configuration config; ASSERT_THAT(ConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config), IsOk()); { std::string type_url = FakeSignKeyManager().get_key_type(); util::StatusOr store = ConfigurationImpl::GetKeyTypeInfoStore(config); ASSERT_THAT(store, IsOk()); util::StatusOr info = (*store)->Get(type_url); ASSERT_THAT(info, IsOk()); util::StatusOr*> key_manager = (*info)->get_key_manager(type_url); ASSERT_THAT(key_manager, IsOk()); EXPECT_EQ((*key_manager)->get_key_type(), type_url); } { std::string type_url = FakeVerifyKeyManager().get_key_type(); util::StatusOr store = ConfigurationImpl::GetKeyTypeInfoStore(config); ASSERT_THAT(store, IsOk()); util::StatusOr info = (*store)->Get(type_url); ASSERT_THAT(info, IsOk()); util::StatusOr*> key_manager = (*info)->get_key_manager(type_url); ASSERT_THAT(key_manager, IsOk()); EXPECT_EQ((*key_manager)->get_key_type(), type_url); } } TEST(ConfigurationImplTest, GlobalRegistryMode) { Registry::Reset(); Configuration config; ASSERT_THAT(ConfigurationImpl::SetGlobalRegistryMode(config), IsOk()); EXPECT_TRUE(ConfigurationImpl::IsInGlobalRegistryMode(config)); // Check that ConfigurationImpl functions return kFailedPrecondition. EXPECT_THAT(ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config), StatusIs(absl::StatusCode::kFailedPrecondition)); EXPECT_THAT(ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config), StatusIs(absl::StatusCode::kFailedPrecondition)); EXPECT_THAT(ConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config), StatusIs(absl::StatusCode::kFailedPrecondition)); FakeKeyTypeManager manager; EXPECT_THAT(ConfigurationImpl::AddLegacyKeyManager( MakeKeyManager(&manager), config), StatusIs(absl::StatusCode::kFailedPrecondition)); EXPECT_THAT(ConfigurationImpl::GetKeyTypeInfoStore(config).status(), StatusIs(absl::StatusCode::kFailedPrecondition)); EXPECT_THAT(ConfigurationImpl::GetKeysetWrapperStore(config).status(), StatusIs(absl::StatusCode::kFailedPrecondition)); Keyset keyset; std::string raw_key = AddAesGcmKeyToKeyset( keyset, /*key_id=*/13, OutputPrefixType::TINK, KeyStatusType::ENABLED); keyset.set_primary_key_id(13); std::unique_ptr handle = CleartextKeysetHandle::GetKeysetHandle(keyset); EXPECT_THAT(handle->GetPrimitive(config).status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(Registry::RegisterPrimitiveWrapper( absl::make_unique()), IsOk()); ASSERT_THAT( Registry::RegisterKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/true), IsOk()); EXPECT_THAT(handle->GetPrimitive(config), IsOk()); } TEST(ConfigurationImplTest, GlobalRegistryModeWithNonEmptyConfigFails) { Configuration config; ASSERT_THAT(ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config), IsOk()); EXPECT_THAT(ConfigurationImpl::SetGlobalRegistryMode(config), StatusIs(absl::StatusCode::kFailedPrecondition)); EXPECT_FALSE(ConfigurationImpl::IsInGlobalRegistryMode(config)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/ec_util.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/ec_util.h" #include #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "openssl/bn.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #include "openssl/ec_key.h" #else #include "openssl/ec.h" #endif #include "openssl/crypto.h" #include "openssl/ecdsa.h" #include "openssl/evp.h" #include "tink/internal/bn_util.h" #include "tink/internal/err_util.h" #include "tink/internal/fips_utils.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/random.h" #include "tink/subtle/subtle_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::subtle::EcPointFormat; using ::crypto::tink::subtle::EllipticCurveType; // Encodes the given `point` to string, according to a `conversion_form`. util::StatusOr SslEcPointEncode( EC_GROUP *group, const EC_POINT *point, point_conversion_form_t conversion_form) { // Get the buffer size first passing a NULL buffer. size_t buffer_size = EC_POINT_point2oct(group, point, conversion_form, /*buf=*/nullptr, /*max_out=*/0, /*ctx=*/nullptr); if (buffer_size == 0) { return util::Status(absl::StatusCode::kInternal, "EC_POINT_point2oct failed"); } std::string encoded_point; subtle::ResizeStringUninitialized(&encoded_point, buffer_size); size_t size = EC_POINT_point2oct(group, point, conversion_form, reinterpret_cast(&encoded_point[0]), buffer_size, /*ctx=*/nullptr); if (size == 0) { return util::Status(absl::StatusCode::kInternal, "EC_POINT_point2oct failed"); } return encoded_point; } // Returns an EC_POINT from `group`, and encoded (bigendian string // representation of BIGNUMs) point coordinates `pubx`, `puby`. util::StatusOr> SslGetEcPointFromCoordinates( const EC_GROUP *group, absl::string_view pubx, absl::string_view puby) { util::StatusOr> bn_x = StringToBignum(pubx); if (!bn_x.ok()) { return bn_x.status(); } util::StatusOr> bn_y = StringToBignum(puby); if (!bn_y.ok()) { return bn_y.status(); } SslUniquePtr pub_key(EC_POINT_new(group)); // In BoringSSL and OpenSSL > 1.1.0 EC_POINT_set_affine_coordinates_GFp // already checks if the point is on the curve. if (EC_POINT_set_affine_coordinates_GFp(group, pub_key.get(), bn_x->get(), bn_y->get(), nullptr) != 1) { return util::Status(absl::StatusCode::kInternal, "EC_POINT_set_affine_coordinates_GFp failed"); } return std::move(pub_key); } // Returns an EC_POINT from an `encoded` point with format `format` and curve // type `curve`. `format` is either COMPRESSED or UNCOMPRESSED. util::StatusOr> SslGetEcPointFromEncoded( EllipticCurveType curve, EcPointFormat format, absl::string_view encoded) { if (format != EcPointFormat::UNCOMPRESSED && format != EcPointFormat::COMPRESSED) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid format ", subtle::EnumToString(format))); } util::StatusOr> group = EcGroupFromCurveType(curve); if (!group.ok()) { return group.status(); } util::StatusOr encoding_size = EcPointEncodingSizeInBytes(curve, format); if (!encoding_size.ok()) { return encoding_size.status(); } if (encoded.size() != *encoding_size) { return util::Status(absl::StatusCode::kInternal, absl::StrCat("Encoded point's size is ", encoded.size(), " bytes; expected ", *encoding_size)); } // Check starting byte. if (format == EcPointFormat::UNCOMPRESSED && static_cast(encoded[0]) != 0x04) { return util::Status( absl::StatusCode::kInternal, "Uncompressed point should start with 0x04, but input doesn't"); } else if (format == EcPointFormat::COMPRESSED && static_cast(encoded[0]) != 0x03 && static_cast(encoded[0]) != 0x02) { return util::Status(absl::StatusCode::kInternal, "Compressed point should start with either 0x02 or " "0x03, but input doesn't"); } SslUniquePtr point(EC_POINT_new(group->get())); if (EC_POINT_oct2point(group->get(), point.get(), reinterpret_cast(encoded.data()), encoded.size(), nullptr) != 1) { return util::Status(absl::StatusCode::kInternal, "EC_POINT_toc2point failed"); } // Check that point is on curve. if (EC_POINT_is_on_curve(group->get(), point.get(), nullptr) != 1) { return util::Status(absl::StatusCode::kInternal, "Point is not on curve"); } return std::move(point); } // OpenSSL/BoringSSL's EC_POINT as a pair of BIGNUMs. struct EcPointCoordinates { SslUniquePtr x; SslUniquePtr y; }; // Returns a given `point` as a pair of BIGNUMs. Precondition: `group` and // `point` are not null. util::StatusOr SslGetEcPointCoordinates( const EC_GROUP *group, const EC_POINT *point) { EcPointCoordinates coordinates = { SslUniquePtr(BN_new()), SslUniquePtr(BN_new()), }; if (coordinates.x == nullptr || coordinates.y == nullptr) { return util::Status(absl::StatusCode::kInternal, "Unable to allocate memory for the point coordinates"); } if (EC_POINT_get_affine_coordinates_GFp(group, point, coordinates.x.get(), coordinates.y.get(), nullptr) != 1) { return util::Status(absl::StatusCode::kInternal, "EC_POINT_get_affine_coordinates_GFp failed"); } return std::move(coordinates); } size_t ScalarSizeInBytes(const EC_GROUP *group) { return BN_num_bytes(EC_GROUP_get0_order(group)); } size_t SslEcFieldSizeInBytes(const EC_GROUP *group) { unsigned degree_bits = EC_GROUP_get_degree(group); return (degree_bits + 7) / 8; } enum SslEvpPkeyType { kX25519Key = EVP_PKEY_X25519, kEd25519Key = EVP_PKEY_ED25519 }; // Returns a new EVP_PKEY key from the given `key_type`. util::StatusOr> SslNewEvpKey(SslEvpPkeyType key_type) { EVP_PKEY *private_key = nullptr; SslUniquePtr pctx(EVP_PKEY_CTX_new_id(key_type, /*e=*/nullptr)); if (pctx == nullptr) { return util::Status( absl::StatusCode::kInternal, absl::StrCat("EVP_PKEY_CTX_new_id failed for id ", key_type)); } if (EVP_PKEY_keygen_init(pctx.get()) != 1) { return util::Status(absl::StatusCode::kInternal, "EVP_PKEY_keygen_init failed"); } if (EVP_PKEY_keygen(pctx.get(), &private_key) != 1) { return util::Status(absl::StatusCode::kInternal, "EVP_PKEY_keygen failed"); } return {SslUniquePtr(private_key)}; } // Given a private EVP_PKEY `evp_key` of key type `key_type` fills `priv_key` // and `pub_key` with raw private and public keys, respectively. util::Status SslNewKeyPairFromEcKey(SslEvpPkeyType key_type, const EVP_PKEY &evp_key, absl::Span priv_key, absl::Span pub_key) { size_t len = priv_key.size(); if (EVP_PKEY_get_raw_private_key(&evp_key, priv_key.data(), &len) != 1) { return util::Status(absl::StatusCode::kInternal, "EVP_PKEY_get_raw_private_key failed"); } if (len != priv_key.size()) { return util::Status(absl::StatusCode::kInternal, absl::StrCat("Invalid private key size; expected ", priv_key.size(), " got ", len)); } len = pub_key.size(); if (EVP_PKEY_get_raw_public_key(&evp_key, pub_key.data(), &len) != 1) { return util::Status(absl::StatusCode::kInternal, "EVP_PKEY_get_raw_public_key failed"); } if (len != pub_key.size()) { return util::Status(absl::StatusCode::kInternal, absl::StrCat("Invalid public key size; expected ", pub_key.size(), " got ", len)); } return util::OkStatus(); } util::StatusOr SslEcdsaSignatureToBytes( const ECDSA_SIG *ecdsa_signature) { if (ecdsa_signature == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "ECDSA signature is null"); } uint8_t *der = nullptr; int der_len = i2d_ECDSA_SIG(ecdsa_signature, &der); if (der_len <= 0) { return util::Status(absl::StatusCode::kInternal, "i2d_ECDSA_SIG failed"); } auto result = std::string(reinterpret_cast(der), der_len); OPENSSL_free(der); return result; } } // namespace util::StatusOr EcKeyFromSslEcKey(EllipticCurveType curve, const EC_KEY &key) { util::StatusOr> group = EcGroupFromCurveType(curve); if (!group.ok()) { return group.status(); } const BIGNUM *priv_key = EC_KEY_get0_private_key(&key); const EC_POINT *pub_key = EC_KEY_get0_public_key(&key); util::StatusOr pub_key_bns = SslGetEcPointCoordinates(group->get(), pub_key); if (!pub_key_bns.ok()) { return pub_key_bns.status(); } const int kFieldElementSizeInBytes = SslEcFieldSizeInBytes(group->get()); util::StatusOr pub_x_str = BignumToString(pub_key_bns->x.get(), kFieldElementSizeInBytes); if (!pub_x_str.ok()) { return pub_x_str.status(); } util::StatusOr pub_y_str = BignumToString(pub_key_bns->y.get(), kFieldElementSizeInBytes); if (!pub_y_str.ok()) { return pub_y_str.status(); } util::StatusOr priv_key_data = BignumToSecretData(priv_key, ScalarSizeInBytes(group->get())); if (!priv_key_data.ok()) { return priv_key_data.status(); } EcKey ec_key = { /*curve=*/curve, /*pub_x=*/*std::move(pub_x_str), /*pub_y=*/*std::move(pub_y_str), /*priv=*/*std::move(priv_key_data), }; return ec_key; } util::StatusOr EcFieldSizeInBytes(EllipticCurveType curve_type) { if (curve_type == EllipticCurveType::CURVE25519) { return 32; } util::StatusOr> ec_group = EcGroupFromCurveType(curve_type); if (!ec_group.ok()) { return ec_group.status(); } return SslEcFieldSizeInBytes(ec_group->get()); } util::StatusOr EcPointEncodingSizeInBytes(EllipticCurveType curve_type, EcPointFormat point_format) { util::StatusOr coordinate_size = EcFieldSizeInBytes(curve_type); if (!coordinate_size.ok()) { return coordinate_size.status(); } if (curve_type == EllipticCurveType::CURVE25519) { return coordinate_size; } if (*coordinate_size == 0) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Unsupported elliptic curve type: ", EnumToString(curve_type))); } switch (point_format) { case EcPointFormat::UNCOMPRESSED: return 2 * (*coordinate_size) + 1; case EcPointFormat::COMPRESSED: return (*coordinate_size) + 1; case EcPointFormat::DO_NOT_USE_CRUNCHY_UNCOMPRESSED: return 2 * (*coordinate_size); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Unsupported elliptic curve point format: ", EnumToString(point_format))); } } util::StatusOr NewEcKey(EllipticCurveType curve_type) { if (curve_type == EllipticCurveType::CURVE25519) { util::StatusOr> key = NewX25519Key(); if (!key.ok()) { return key.status(); } return EcKeyFromX25519Key(key->get()); } util::StatusOr> group = EcGroupFromCurveType(curve_type); if (!group.ok()) { return group.status(); } SslUniquePtr key(EC_KEY_new()); if (key.get() == nullptr) { return util::Status(absl::StatusCode::kInternal, "EC_KEY_new failed"); } EC_KEY_set_group(key.get(), group->get()); EC_KEY_generate_key(key.get()); return EcKeyFromSslEcKey(curve_type, *key); } util::StatusOr NewEcKey(EllipticCurveType curve_type, const util::SecretData &secret_seed) { // EC_KEY_derive_from_secret() is neither defined in the version of BoringSSL // used when FIPS-only mode is enabled at compile time, nor currently // implemented for OpenSSL. #if defined(TINK_USE_ONLY_FIPS) return util::Status( absl::StatusCode::kUnimplemented, "Deriving EC keys from a secret seed is not allowed in FIPS mode"); #elif !defined(OPENSSL_IS_BORINGSSL) return util::Status( absl::StatusCode::kUnimplemented, "Deriving EC keys from a secret seed is not supported with OpenSSL"); #else if (IsFipsModeEnabled()) { return util::Status( absl::StatusCode::kInternal, "Deriving EC keys from a secret seed is not allowed in FIPS mode"); } if (curve_type == EllipticCurveType::CURVE25519) { return util::Status( absl::StatusCode::kInternal, "Creating a X25519 key from a secret seed is not supported"); } util::StatusOr> group = EcGroupFromCurveType(curve_type); if (!group.ok()) { return group.status(); } SslUniquePtr key(EC_KEY_derive_from_secret( group->get(), secret_seed.data(), secret_seed.size())); if (key.get() == nullptr) { return util::Status(absl::StatusCode::kInternal, "EC_KEY_derive_from_secret failed"); } return EcKeyFromSslEcKey(curve_type, *key); #endif } util::StatusOr> NewX25519Key() { util::StatusOr> private_key = SslNewEvpKey(SslEvpPkeyType::kX25519Key); if (!private_key.ok()) { return private_key.status(); } auto key = absl::make_unique(); util::Status res = SslNewKeyPairFromEcKey( SslEvpPkeyType::kX25519Key, **private_key, absl::MakeSpan(key->private_key, X25519KeyPrivKeySize()), absl::MakeSpan(key->public_value, X25519KeyPubKeySize())); if (!res.ok()) { return res; } return std::move(key); } EcKey EcKeyFromX25519Key(const X25519Key *x25519_key) { EcKey ec_key; ec_key.curve = subtle::EllipticCurveType::CURVE25519; // Curve25519 public key is x, not (x,y). ec_key.pub_x = std::string(reinterpret_cast(x25519_key->public_value), X25519KeyPubKeySize()); ec_key.priv = util::SecretData(std::begin(x25519_key->private_key), std::end(x25519_key->private_key)); return ec_key; } util::StatusOr> NewEd25519Key() { util::SecretData seed = subtle::Random::GetRandomKeyBytes(Ed25519KeyPrivKeySize()); return NewEd25519Key(seed); } util::StatusOr> NewEd25519Key( const util::SecretData &secret_seed) { if (secret_seed.size() != Ed25519KeyPrivKeySize()) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid seed of length ", secret_seed.size(), "; expected ", Ed25519KeyPrivKeySize())); } // In BoringSSL this calls ED25519_keypair_from_seed. Accessing the public key // with EVP_PKEY_get_raw_public_key returns the last 32 bytes of the private // key stored by BoringSSL. SslUniquePtr priv_key(EVP_PKEY_new_raw_private_key( SslEvpPkeyType::kEd25519Key, nullptr, secret_seed.data(), Ed25519KeyPrivKeySize())); if (priv_key == nullptr) { return util::Status(absl::StatusCode::kInternal, "EVP_PKEY_new_raw_private_key failed"); } auto key = absl::make_unique(); subtle::ResizeStringUninitialized(&key->private_key, Ed25519KeyPrivKeySize()); subtle::ResizeStringUninitialized(&key->public_key, Ed25519KeyPubKeySize()); uint8_t *priv_key_ptr = reinterpret_cast(&key->private_key[0]); uint8_t *pub_key_ptr = reinterpret_cast(&key->public_key[0]); // The EVP_PKEY interface returns only the first 32 bytes of the private key. util::Status res = SslNewKeyPairFromEcKey( SslEvpPkeyType::kEd25519Key, *priv_key, absl::MakeSpan(priv_key_ptr, Ed25519KeyPrivKeySize()), absl::MakeSpan(pub_key_ptr, Ed25519KeyPubKeySize())); if (!res.ok()) { return res; } return std::move(key); } util::StatusOr> X25519KeyFromEcKey( const EcKey &ec_key) { auto x25519_key = absl::make_unique(); if (ec_key.curve != subtle::EllipticCurveType::CURVE25519) { return util::Status(absl::StatusCode::kInvalidArgument, "This key is not on curve 25519"); } if (!ec_key.pub_y.empty()) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid X25519 key. pub_y is unexpectedly set."); } // Curve25519 public key is x, not (x,y). std::copy_n(ec_key.pub_x.begin(), X25519KeyPubKeySize(), std::begin(x25519_key->public_value)); std::copy_n(ec_key.priv.begin(), X25519KeyPrivKeySize(), std::begin(x25519_key->private_key)); return std::move(x25519_key); } util::StatusOr ComputeX25519SharedSecret( EVP_PKEY *private_key, EVP_PKEY *peer_public_key) { // Make sure the keys are actually X25519 keys. if (EVP_PKEY_id(private_key) != SslEvpPkeyType::kX25519Key) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid type for private key"); } if (EVP_PKEY_id(peer_public_key) != SslEvpPkeyType::kX25519Key) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid type for peer's public key"); } internal::SslUniquePtr pctx( EVP_PKEY_CTX_new(private_key, nullptr)); util::SecretData shared_secret(internal::X25519KeySharedKeySize()); size_t out_key_length = shared_secret.size(); if (EVP_PKEY_derive_init(pctx.get()) <= 0 || EVP_PKEY_derive_set_peer(pctx.get(), peer_public_key) <= 0 || EVP_PKEY_derive(pctx.get(), shared_secret.data(), &out_key_length) <= 0) { return util::Status(absl::StatusCode::kInternal, "Secret generation failed"); } return shared_secret; } util::StatusOr> X25519KeyFromPrivateKey( const util::SecretData &private_key) { if (private_key.size() != X25519KeyPrivKeySize()) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid length for private key"); } internal::SslUniquePtr pkey( EVP_PKEY_new_raw_private_key(SslEvpPkeyType::kX25519Key, nullptr, private_key.data(), private_key.size())); auto key = absl::make_unique(); util::Status res = SslNewKeyPairFromEcKey( SslEvpPkeyType::kX25519Key, *pkey, absl::MakeSpan(key->private_key, X25519KeyPrivKeySize()), absl::MakeSpan(key->public_value, X25519KeyPubKeySize())); if (!res.ok()) { return res; } return std::move(key); } util::StatusOr EcPointEncode(EllipticCurveType curve, EcPointFormat format, const EC_POINT *point) { util::StatusOr> group = EcGroupFromCurveType(curve); if (!group.ok()) { return group.status(); } if (EC_POINT_is_on_curve(group->get(), point, nullptr) != 1) { return util::Status(absl::StatusCode::kInternal, "Point is not on curve"); } switch (format) { case EcPointFormat::UNCOMPRESSED: { return SslEcPointEncode(group->get(), point, POINT_CONVERSION_UNCOMPRESSED); } case EcPointFormat::COMPRESSED: { return SslEcPointEncode(group->get(), point, POINT_CONVERSION_COMPRESSED); } case EcPointFormat::DO_NOT_USE_CRUNCHY_UNCOMPRESSED: { util::StatusOr ec_point_xy = SslGetEcPointCoordinates(group->get(), point); if (!ec_point_xy.ok()) { return ec_point_xy.status(); } const int kCurveSizeInBytes = SslEcFieldSizeInBytes(group->get()); std::string encoded_point; subtle::ResizeStringUninitialized(&encoded_point, 2 * kCurveSizeInBytes); util::Status res = BignumToBinaryPadded( absl::MakeSpan(&encoded_point[0], kCurveSizeInBytes), ec_point_xy->x.get()); if (!res.ok()) { return util::Status( absl::StatusCode::kInternal, absl::StrCat(res.message(), " serializing the x coordinate")); } res = BignumToBinaryPadded( absl::MakeSpan(&encoded_point[kCurveSizeInBytes], kCurveSizeInBytes), ec_point_xy->y.get()); if (!res.ok()) { return util::Status( absl::StatusCode::kInternal, absl::StrCat(res.message(), " serializing the y coordinate")); } return encoded_point; } default: return util::Status(absl::StatusCode::kInternal, "Unsupported point format"); } } util::StatusOr> EcPointDecode( EllipticCurveType curve, EcPointFormat format, absl::string_view encoded) { switch (format) { case EcPointFormat::UNCOMPRESSED: case EcPointFormat::COMPRESSED: return SslGetEcPointFromEncoded(curve, format, encoded); case EcPointFormat::DO_NOT_USE_CRUNCHY_UNCOMPRESSED: { util::StatusOr> group = EcGroupFromCurveType(curve); if (!group.ok()) { return group.status(); } const int kCurveSizeInBytes = SslEcFieldSizeInBytes(group->get()); if (encoded.size() != 2 * kCurveSizeInBytes) { return util::Status( absl::StatusCode::kInternal, absl::StrCat("Encoded point's size is ", encoded.size(), " bytes; expected ", 2 * kCurveSizeInBytes)); } // SslGetEcPoint already checks if the point is on curve so we can return // directly. return SslGetEcPointFromCoordinates(group->get(), encoded.substr(0, kCurveSizeInBytes), encoded.substr(kCurveSizeInBytes)); } default: return util::Status(absl::StatusCode::kInternal, "Unsupported format"); } } util::StatusOr> EcGroupFromCurveType( EllipticCurveType curve_type) { EC_GROUP *ec_group = nullptr; switch (curve_type) { case EllipticCurveType::NIST_P256: { ec_group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); break; } case EllipticCurveType::NIST_P384: { ec_group = EC_GROUP_new_by_curve_name(NID_secp384r1); break; } case EllipticCurveType::NIST_P521: { ec_group = EC_GROUP_new_by_curve_name(NID_secp521r1); break; } default: return util::Status(absl::StatusCode::kUnimplemented, "Unsupported elliptic curve"); } if (ec_group == nullptr) { return util::Status(absl::StatusCode::kInternal, "EC_GROUP_new_by_curve_name failed"); } return {SslUniquePtr(ec_group)}; } util::StatusOr CurveTypeFromEcGroup(const EC_GROUP *group) { if (group == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "Null group provided"); } switch (EC_GROUP_get_curve_name(group)) { case NID_X9_62_prime256v1: return EllipticCurveType::NIST_P256; case NID_secp384r1: return EllipticCurveType::NIST_P384; case NID_secp521r1: return EllipticCurveType::NIST_P521; default: return util::Status(absl::StatusCode::kUnimplemented, "Unsupported elliptic curve"); } } util::StatusOr> GetEcPoint(EllipticCurveType curve, absl::string_view pubx, absl::string_view puby) { util::StatusOr> group = EcGroupFromCurveType(curve); if (!group.ok()) { return group.status(); } return SslGetEcPointFromCoordinates(group->get(), pubx, puby); } util::StatusOr ComputeEcdhSharedSecret( EllipticCurveType curve, const BIGNUM *priv_key, const EC_POINT *pub_key) { util::StatusOr> priv_group = internal::EcGroupFromCurveType(curve); if (!priv_group.ok()) { return priv_group.status(); } if (EC_POINT_is_on_curve(priv_group->get(), pub_key, /*ctx=*/nullptr) != 1) { return util::Status(absl::StatusCode::kInternal, absl::StrCat("Public key is not on curve ", subtle::EnumToString(curve))); } // Compute the shared point and make sure it is on `curve`. internal::SslUniquePtr shared_point( EC_POINT_new(priv_group->get())); if (EC_POINT_mul(priv_group->get(), shared_point.get(), /*n=*/nullptr, pub_key, priv_key, /*ctx=*/nullptr) != 1) { return util::Status(absl::StatusCode::kInternal, "Point multiplication failed"); } if (EC_POINT_is_on_curve(priv_group->get(), shared_point.get(), /*ctx=*/nullptr) != 1) { return util::Status(absl::StatusCode::kInternal, absl::StrCat("Shared point is not on curve ", subtle::EnumToString(curve))); } util::StatusOr shared_point_coordinates = SslGetEcPointCoordinates(priv_group->get(), shared_point.get()); if (!shared_point_coordinates.ok()) { return shared_point_coordinates.status(); } // We need only the x coordinate. return internal::BignumToSecretData(shared_point_coordinates->x.get(), SslEcFieldSizeInBytes(priv_group->get())); } util::StatusOr EcSignatureIeeeToDer(const EC_GROUP *group, absl::string_view ieee_sig) { const size_t kFieldSizeInBytes = SslEcFieldSizeInBytes(group); if (ieee_sig.size() != kFieldSizeInBytes * 2) { return util::Status(absl::StatusCode::kInvalidArgument, "Signature is not valid."); } util::StatusOr> r = internal::StringToBignum(ieee_sig.substr(0, kFieldSizeInBytes)); if (!r.ok()) { return r.status(); } util::StatusOr> s = internal::StringToBignum(ieee_sig.substr(kFieldSizeInBytes)); if (!s.ok()) { return s.status(); } internal::SslUniquePtr ecdsa(ECDSA_SIG_new()); if (ECDSA_SIG_set0(ecdsa.get(), r->get(), s->get()) != 1) { return util::Status(absl::StatusCode::kInternal, "ECDSA_SIG_set0 failed"); } // ECDSA_SIG_set0 takes ownership of s and r's pointers. r->release(); s->release(); return SslEcdsaSignatureToBytes(ecdsa.get()); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/ec_util.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_EC_UTIL_H_ #define TINK_INTERNAL_EC_UTIL_H_ #include #include #include #include "absl/strings/string_view.h" #include "openssl/ec.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/subtle/common_enums.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { constexpr int64_t X25519KeyPubKeySize() { return 32; } constexpr int64_t X25519KeyPrivKeySize() { return 32; } constexpr int64_t X25519KeySharedKeySize() { return 32; } constexpr int64_t Ed25519KeyPubKeySize() { return 32; } constexpr int64_t Ed25519KeyPrivKeySize() { return 32; } struct EcKey { subtle::EllipticCurveType curve; // Affine coordinates in bigendian representation. std::string pub_x; std::string pub_y; // Big integer in bigendian representation. crypto::tink::util::SecretData priv; }; struct X25519Key { uint8_t public_value[X25519KeyPubKeySize()]; uint8_t private_key[X25519KeyPrivKeySize()]; }; struct Ed25519Key { std::string public_key; std::string private_key; }; // EcKey. // Returns a new EC key for the specified curve. crypto::tink::util::StatusOr NewEcKey( crypto::tink::subtle::EllipticCurveType curve_type); // Returns a new EC key for the specified curve derived from a secret seed. crypto::tink::util::StatusOr NewEcKey( crypto::tink::subtle::EllipticCurveType curve_type, const crypto::tink::util::SecretData &secret_seed); // X25519Key Utils. // Returns a new X25519Key key. It returns a kInternal error status if the // OpenSSL/BoringSSL APIs fail. crypto::tink::util::StatusOr> NewX25519Key(); // Returns a X25519Key matching the specified EcKey. crypto::tink::util::StatusOr> X25519KeyFromEcKey( const EcKey &ec_key); // Returns an EcKey matching the specified X25519Key. EcKey EcKeyFromX25519Key(const X25519Key *x25519_key); // Given an OpenSSL/BoringSSL key EC_KEY `key` and curve type `curve` return an // EcKey. util::StatusOr EcKeyFromSslEcKey( crypto::tink::subtle::EllipticCurveType curve, const EC_KEY &key); // Generates a shared secret using `private_key` and `peer_public_key`; keys // must be X25519 keys otherwise an error is returned. crypto::tink::util::StatusOr ComputeX25519SharedSecret( EVP_PKEY *private_key, EVP_PKEY *peer_public_key); // Computes the corresponding public+private key for the supplied private key. crypto::tink::util::StatusOr> X25519KeyFromPrivateKey(const crypto::tink::util::SecretData &private_key); // Ed25519Key Utils. // Returns a new ED25519 key. crypto::tink::util::StatusOr> NewEd25519Key(); // Returns a new ED25519 key generated from a 32-byte secret seed. crypto::tink::util::StatusOr> NewEd25519Key( const crypto::tink::util::SecretData &secret_seed); // EC_POINT Encode/Decode. // Given x, y as curve_size_in_bytes big-endian byte array, encoding is as // follows: // - The uncompressed point is encoded as 0x04 || x || y. // - The compressed point is encoded as: // - 0x03 || x if the least significant bit of y is 1; // - 0x02 || x otherwise. // Returns OpenSSL/BoringSSL's EC_POINT constructed from curve type // `curve_type`, point `format` and encoded public key's point `encoded_point`. crypto::tink::util::StatusOr> EcPointDecode( crypto::tink::subtle::EllipticCurveType curve_type, crypto::tink::subtle::EcPointFormat format, absl::string_view encoded_point); // Returns the encoded public key based on curve type `curve_type`, point // `format` and OpenSSL/BoringSSL's EC_POINT public key `point`. crypto::tink::util::StatusOr EcPointEncode( crypto::tink::subtle::EllipticCurveType curve_type, crypto::tink::subtle::EcPointFormat format, const EC_POINT *point); // Returns the encoding size of a point on the specified elliptic curve // `curve_type` when the given point `format` is used. util::StatusOr EcPointEncodingSizeInBytes( crypto::tink::subtle::EllipticCurveType curve_type, crypto::tink::subtle::EcPointFormat format); // Returns the size (in bytes) of an element of the field over which // the curve `curve_type` is defined. util::StatusOr EcFieldSizeInBytes( crypto::tink::subtle::EllipticCurveType curve_type); // EC_GROUP Utils. // Returns OpenSSL/BoringSSL's EC_GROUP constructed from the given `curve_type`. crypto::tink::util::StatusOr> EcGroupFromCurveType( crypto::tink::subtle::EllipticCurveType curve_type); // Returns the curve type associated with the given `group`. crypto::tink::util::StatusOr CurveTypeFromEcGroup(const EC_GROUP *group); // Returns OpenSSL/BoringSSL's EC_POINT constructed from the curve type, // big-endian representation of public key's x-coordinate and y-coordinate. crypto::tink::util::StatusOr> GetEcPoint( crypto::tink::subtle::EllipticCurveType curve, absl::string_view pubx, absl::string_view puby); // Transforms ECDSA IEEE_P1363 signature encoding to DER encoding. // // The IEEE_P1363 signature's format is r || s, where r and s are zero-padded // and have the same size in bytes as the order of the curve. For example, for // NIST P-256 curve, r and s are zero-padded to 32 bytes. // // The DER signature is encoded using ASN.1 // (https://tools.ietf.org/html/rfc5480#appendix-A): // ECDSA-Sig-Value :: = SEQUENCE { r INTEGER, s INTEGER }. // In particular, the encoding is: // 0x30 || totalLength || 0x02 || r's length || r || 0x02 || s's length || s util::StatusOr EcSignatureIeeeToDer(const EC_GROUP *group, absl::string_view ieee_sig); // Returns the ECDH's shared secret between two peers A and B using A's private // key `priv_key` and B's public key `pub_key`. Returns error if `pub_key` // is not on `priv_key`'s curve `curve`. util::StatusOr ComputeEcdhSharedSecret( crypto::tink::subtle::EllipticCurveType curve, const BIGNUM *priv_key, const EC_POINT *pub_key); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_EC_UTIL_H_ ================================================ FILE: cc/internal/ec_util_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/ec_util.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #include "openssl/ec_key.h" #endif #include "openssl/bn.h" #include "openssl/ec.h" #include "openssl/ecdsa.h" #include "openssl/evp.h" #include "include/rapidjson/document.h" #include "tink/internal/bn_util.h" #include "tink/internal/fips_utils.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/internal/ssl_util.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/subtle_util.h" #include "tink/subtle/wycheproof_util.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::subtle::EcPointFormat; using ::crypto::tink::subtle::EllipticCurveType; using ::crypto::tink::subtle::WycheproofUtil; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::testing::AllOf; using ::testing::ElementsAreArray; using ::testing::Eq; using ::testing::Field; using ::testing::HasSubstr; using ::testing::IsEmpty; using ::testing::IsNull; using ::testing::Matcher; using ::testing::Not; using ::testing::SizeIs; using ::testing::TestParamInfo; using ::testing::TestWithParam; using ::testing::ValuesIn; // Use wycheproof test vectors to verify Ed25519 key generation from a seed (the // private key) results in the public/private key. TEST(EcUtilTest, NewEd25519KeyWithWycheproofTestVectors) { std::unique_ptr test_vectors = WycheproofUtil::ReadTestVectors("eddsa_test.json"); ASSERT_THAT(test_vectors, Not(IsNull())); // For this test we are only interested in Ed25519 keys. for (const auto& test_group : (*test_vectors)["testGroups"].GetArray()) { std::string private_key = WycheproofUtil::GetBytes(test_group["key"]["sk"]); std::string public_key = WycheproofUtil::GetBytes(test_group["key"]["pk"]); util::StatusOr> key = NewEd25519Key(util::SecretDataFromStringView(private_key)); ASSERT_THAT(key, IsOk()); EXPECT_EQ((*key)->public_key, public_key); EXPECT_EQ((*key)->private_key, private_key); } } TEST(EcUtilTest, NewEd25519KeyInvalidSeed) { std::string valid_seed = absl::HexStringToBytes( "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"); // Seed that is too small. for (int i = 0; i < 32; i++) { EXPECT_THAT( NewEd25519Key(util::SecretDataFromStringView(valid_seed.substr(0, i))) .status(), Not(IsOk())) << " with seed of length " << i; } // Seed that is too large. std::string large_seed = absl::StrCat(valid_seed, "a"); EXPECT_THAT( NewEd25519Key(util::SecretDataFromStringView(large_seed)).status(), Not(IsOk())) << " with seed of length " << large_seed.size(); } TEST(EcUtilTest, NewEcKeyReturnsWellFormedX25519Key) { util::StatusOr ec_key = NewEcKey(subtle::EllipticCurveType::CURVE25519); ASSERT_THAT(ec_key, IsOk()); EXPECT_THAT( *ec_key, AllOf(Field(&EcKey::curve, Eq(subtle::EllipticCurveType::CURVE25519)), Field(&EcKey::pub_x, SizeIs(X25519KeyPubKeySize())), Field(&EcKey::pub_y, IsEmpty()), Field(&EcKey::priv, SizeIs(X25519KeyPrivKeySize())))); } using EcUtilNewEcKeyWithSeed = TestWithParam; // Matcher for the equality of two EcKeys. Matcher EqualsEcKey(const EcKey& expected) { return AllOf(Field(&EcKey::priv, Eq(expected.priv)), Field(&EcKey::pub_x, Eq(expected.pub_x)), Field(&EcKey::pub_y, Eq(expected.pub_y)), Field(&EcKey::curve, Eq(expected.curve))); } TEST_P(EcUtilNewEcKeyWithSeed, KeysFromDifferentSeedAreDifferent) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } if (!IsBoringSsl()) { GTEST_SKIP() << "NewEcKey with seed is not supported with OpenSSL"; } util::SecretData seed1 = util::SecretDataFromStringView( absl::HexStringToBytes("000102030405060708090a0b0c0d0e0f")); util::SecretData seed2 = util::SecretDataFromStringView( absl::HexStringToBytes("0f0e0d0c0b0a09080706050403020100")); subtle::EllipticCurveType curve = GetParam(); util::StatusOr keypair1 = NewEcKey(curve, seed1); ASSERT_THAT(keypair1, IsOk()); util::StatusOr keypair2 = NewEcKey(curve, seed2); ASSERT_THAT(keypair2, IsOk()); EXPECT_THAT(*keypair1, Not(EqualsEcKey(*keypair2))); } TEST_P(EcUtilNewEcKeyWithSeed, SameSeedGivesSameKey) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } if (!IsBoringSsl()) { GTEST_SKIP() << "NewEcKey with seed is not supported with OpenSSL"; } util::SecretData seed1 = util::SecretDataFromStringView( absl::HexStringToBytes("000102030405060708090a0b0c0d0e0f")); subtle::EllipticCurveType curve = GetParam(); util::StatusOr keypair1 = NewEcKey(curve, seed1); ASSERT_THAT(keypair1, IsOk()); util::StatusOr keypair2 = NewEcKey(curve, seed1); ASSERT_THAT(keypair2, IsOk()); EXPECT_THAT(*keypair1, EqualsEcKey(*keypair2)); } INSTANTIATE_TEST_SUITE_P(EcUtilNewEcKeyWithSeeds, EcUtilNewEcKeyWithSeed, ValuesIn({subtle::NIST_P256, subtle::NIST_P384, subtle::NIST_P521})); TEST(EcUtilTest, GenerationWithSeedFailsWithWrongCurve) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } if (!IsBoringSsl()) { GTEST_SKIP() << "NewEcKey with seed is not supported with OpenSSL"; } util::SecretData seed = util::SecretDataFromStringView( absl::HexStringToBytes("000102030405060708090a0b0c0d0e0f")); util::StatusOr keypair = NewEcKey(subtle::EllipticCurveType::CURVE25519, seed); EXPECT_THAT(keypair.status(), StatusIs(absl::StatusCode::kInternal)); } TEST(EcUtilTest, NewEcKeyFromSeedUnimplementedIfOpenSsl) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } if (IsBoringSsl()) { GTEST_SKIP() << "OpenSSL-only test; skipping because BoringSSL is being used"; } util::SecretData seed = util::SecretDataFromStringView( absl::HexStringToBytes("000102030405060708090a0b0c0d0e0f")); util::StatusOr keypair = NewEcKey(subtle::EllipticCurveType::CURVE25519, seed); EXPECT_THAT(keypair.status(), StatusIs(absl::StatusCode::kUnimplemented)); } TEST(EcUtilTest, NewX25519KeyGeneratesNewKeyEveryTime) { util::StatusOr> keypair1 = NewX25519Key(); ASSERT_THAT(keypair1, IsOk()); util::StatusOr> keypair2 = NewX25519Key(); ASSERT_THAT(keypair2, IsOk()); auto priv_key1 = absl::MakeSpan((*keypair1)->private_key, X25519KeyPrivKeySize()); auto priv_key2 = absl::MakeSpan((*keypair2)->private_key, X25519KeyPrivKeySize()); auto pub_key1 = absl::MakeSpan((*keypair1)->public_value, X25519KeyPubKeySize()); auto pub_key2 = absl::MakeSpan((*keypair2)->public_value, X25519KeyPubKeySize()); EXPECT_THAT(priv_key1, Not(ElementsAreArray(priv_key2))); EXPECT_THAT(pub_key1, Not(ElementsAreArray(pub_key2))); } TEST(EcUtilTest, X25519KeyToEcKeyAndBack) { util::StatusOr> x25519_key = NewX25519Key(); ASSERT_THAT(x25519_key, IsOk()); EcKey ec_key = EcKeyFromX25519Key(x25519_key->get()); ASSERT_EQ(ec_key.curve, EllipticCurveType::CURVE25519); util::StatusOr> roundtrip_key = X25519KeyFromEcKey(ec_key); ASSERT_THAT(roundtrip_key, IsOk()); EXPECT_THAT( absl::MakeSpan((*x25519_key)->private_key, X25519KeyPrivKeySize()), ElementsAreArray(absl::MakeSpan((*roundtrip_key)->private_key, X25519KeyPrivKeySize()))); EXPECT_THAT( absl::MakeSpan((*x25519_key)->public_value, X25519KeyPubKeySize()), ElementsAreArray(absl::MakeSpan((*roundtrip_key)->public_value, X25519KeyPubKeySize()))); } TEST(EcUtilTest, X25519KeyFromRandomPrivateKey) { util::StatusOr> x25519_key = NewX25519Key(); ASSERT_THAT(x25519_key, IsOk()); absl::Span pkey_span = absl::MakeSpan((*x25519_key)->private_key, X25519KeyPrivKeySize()); util::StatusOr> roundtrip_key = X25519KeyFromPrivateKey({pkey_span.begin(), pkey_span.end()}); ASSERT_THAT(roundtrip_key, IsOk()); EXPECT_THAT( absl::MakeSpan((*x25519_key)->private_key, X25519KeyPrivKeySize()), ElementsAreArray(absl::MakeSpan((*roundtrip_key)->private_key, X25519KeyPrivKeySize()))); EXPECT_THAT( absl::MakeSpan((*x25519_key)->public_value, X25519KeyPubKeySize()), ElementsAreArray(absl::MakeSpan((*roundtrip_key)->public_value, X25519KeyPubKeySize()))); } struct X25519FunctionTestVector { std::string private_key; std::string expected_public_key; }; // Returns some X25519 test vectors taken from // https://datatracker.ietf.org/doc/html/rfc7748. std::vector GetX25519FunctionTestVectors() { return { // https://datatracker.ietf.org/doc/html/rfc7748#section-5.2 { /*private_key=*/ absl::HexStringToBytes("090000000000000000000000000000000000000000000" "0000000000000000000"), /*expected_public_key=*/ absl::HexStringToBytes("422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854" "b783c60e80311ae3079"), }, // https://datatracker.ietf.org/doc/html/rfc7748#section-6.1; Alice { /*private_key=*/ absl::HexStringToBytes("77076d0a7318a57d3c16c17251b26645df4c2f87ebc09" "92ab177fba51db92c2a"), /*expected_public_key=*/ absl::HexStringToBytes("8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381" "af4eba4a98eaa9b4e6a"), }, // https://datatracker.ietf.org/doc/html/rfc7748#section-6.1; Bob { /*private_key=*/ absl::HexStringToBytes("5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b" "6fd1c2f8b27ff88e0eb"), /*expected_public_key=*/ absl::HexStringToBytes("de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b786" "74dadfc7e146f882b4f"), }, // Locally made up test vector { /*private_key=*/ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", /*expected_public_key=*/ absl::HexStringToBytes("4049502db92ca2342c3f92dac5d6de7c85db5df5407a5" "b4996ce39f2efb7e827"), }, }; } using X25519FunctionTest = TestWithParam; TEST_P(X25519FunctionTest, ComputeX25519PublicKey) { X25519FunctionTestVector test_vector = GetParam(); util::StatusOr> key = X25519KeyFromPrivateKey( util::SecretDataFromStringView(test_vector.private_key)); ASSERT_THAT(key, IsOk()); EXPECT_THAT(absl::MakeSpan((*key)->public_value, X25519KeyPubKeySize()), ElementsAreArray(test_vector.expected_public_key)); } INSTANTIATE_TEST_SUITE_P(X25519SharedSecretTests, X25519FunctionTest, ValuesIn(GetX25519FunctionTestVectors())); struct X25519SharedSecretTestVector { std::string private_key; std::string public_key; std::string expected_shared_secret; }; // Returns some X25519 test vectors taken from // https://datatracker.ietf.org/doc/html/rfc7748#section-5.2. std::vector GetX25519SharedSecretTestVectors() { return { { /*private_key=*/ absl::HexStringToBytes("a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5" "a18506a2244ba449ac4"), /*public_key=*/ absl::HexStringToBytes("e6db6867583030db3594c1a424b15f7c726624ec26b33" "53b10a903a6d0ab1c4c"), /*expected_shared_secret=*/ absl::HexStringToBytes("c3da55379de9c6908e94ea4df28d084f32eccf03491c7" "1f754b4075577a28552"), }, { /*private_key=*/ absl::HexStringToBytes("4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea0" "1d42ca4169e7918ba0d"), /*public_key=*/ absl::HexStringToBytes("e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03" "c3efc4cd549c715a493"), /*expected_shared_secret=*/ absl::HexStringToBytes("95cbde9476e8907d7aade45cb4b873f88b595a68799fa" "152e6f8f7647aac7957"), }, }; } using X25519SharedSecretTest = TestWithParam; TEST_P(X25519SharedSecretTest, ComputeX25519SharedSecret) { X25519SharedSecretTestVector test_vector = GetParam(); // Generate the EVP_PKEYs. internal::SslUniquePtr ssl_priv_key(EVP_PKEY_new_raw_private_key( /*type=*/EVP_PKEY_X25519, /*unused=*/nullptr, /*in=*/reinterpret_cast(test_vector.private_key.data()), /*len=*/Ed25519KeyPrivKeySize())); ASSERT_THAT(ssl_priv_key, Not(IsNull())); internal::SslUniquePtr ssl_pub_key(EVP_PKEY_new_raw_public_key( /*type=*/EVP_PKEY_X25519, /*unused=*/nullptr, /*in=*/reinterpret_cast(test_vector.public_key.data()), /*len=*/Ed25519KeyPrivKeySize())); ASSERT_THAT(ssl_pub_key, Not(IsNull())); EXPECT_THAT(ComputeX25519SharedSecret(ssl_priv_key.get(), ssl_pub_key.get()), IsOkAndHolds(util::SecretDataFromStringView( test_vector.expected_shared_secret))); } INSTANTIATE_TEST_SUITE_P(X25519SharedSecretTests, X25519SharedSecretTest, ValuesIn(GetX25519SharedSecretTestVectors())); TEST(EcUtilTest, ComputeX25519SharedSecretInvalidKeyType) { // Key pair of an invalid type EVP_PKEY_ED25519. SslUniquePtr pctx(EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, /*e=*/nullptr)); ASSERT_THAT(pctx, Not(IsNull())); ASSERT_EQ(EVP_PKEY_keygen_init(pctx.get()), 1); EVP_PKEY* invalid_type_key_ptr = nullptr; ASSERT_EQ(EVP_PKEY_keygen(pctx.get(), &invalid_type_key_ptr), 1); SslUniquePtr invalid_type_key(invalid_type_key_ptr); // Private and public key with valid type. internal::SslUniquePtr ssl_priv_key(EVP_PKEY_new_raw_private_key( /*type=*/EVP_PKEY_X25519, /*unused=*/nullptr, /*in=*/ reinterpret_cast( absl::HexStringToBytes("a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5" "a18506a2244ba449ac4") .data()), /*len=*/Ed25519KeyPrivKeySize())); ASSERT_THAT(ssl_priv_key, Not(IsNull())); internal::SslUniquePtr ssl_pub_key(EVP_PKEY_new_raw_public_key( /*type=*/EVP_PKEY_X25519, /*unused=*/nullptr, /*in=*/ reinterpret_cast( absl::HexStringToBytes("e6db6867583030db3594c1a424b15f7c726624ec26b33" "53b10a903a6d0ab1c4c") .data()), /*len=*/Ed25519KeyPubKeySize())); ASSERT_THAT(ssl_pub_key, Not(IsNull())); EXPECT_THAT( ComputeX25519SharedSecret(ssl_priv_key.get(), invalid_type_key.get()) .status(), Not(IsOk())); EXPECT_THAT( ComputeX25519SharedSecret(invalid_type_key.get(), ssl_pub_key.get()) .status(), Not(IsOk())); } struct EncodingTestVector { EcPointFormat format; std::string x_hex; std::string y_hex; std::string encoded_hex; EllipticCurveType curve; }; std::vector GetEncodingTestVectors() { return { {EcPointFormat::UNCOMPRESSED, "00093057fb862f2ad2e82e581baeb3324e7b32946f2ba845a9beeed87d6995f54918ec6" "619b9931955d5a89d4d74adf1046bb362192f2ef6bd3e3d2d04dd1f87054a", "00aa3fb2448335f694e3cda4ae0cc71b1b2f2a206fa802d7262f19983c44674fe15327a" "caac1fa40424c395a6556cb8167312527fae5865ecffc14bbdc17da78cdcf", "0400093057fb862f2ad2e82e581baeb3324e7b32946f2ba845a9beeed87d6995f54918e" "c6619b9931955d5a89d4d74adf1046bb362192f2ef6bd3e3d2d04dd1f87054a00aa3fb2" "448335f694e3cda4ae0cc71b1b2f2a206fa802d7262f19983c44674fe15327acaac1fa4" "0424c395a6556cb8167312527fae5865ecffc14bbdc17da78cdcf", EllipticCurveType::NIST_P521}, {EcPointFormat::DO_NOT_USE_CRUNCHY_UNCOMPRESSED, "00093057fb862f2ad2e82e581baeb3324e7b32946f2ba845a9beeed87d6995f54918ec6" "619b9931955d5a89d4d74adf1046bb362192f2ef6bd3e3d2d04dd1f87054a", "00aa3fb2448335f694e3cda4ae0cc71b1b2f2a206fa802d7262f19983c44674fe15327a" "caac1fa40424c395a6556cb8167312527fae5865ecffc14bbdc17da78cdcf", "00093057fb862f2ad2e82e581baeb3324e7b32946f2ba845a9beeed87d6995f54918ec6" "619b9931955d5a89d4d74adf1046bb362192f2ef6bd3e3d2d04dd1f87054a00aa3fb244" "8335f694e3cda4ae0cc71b1b2f2a206fa802d7262f19983c44674fe15327acaac1fa404" "24c395a6556cb8167312527fae5865ecffc14bbdc17da78cdcf", EllipticCurveType::NIST_P521}, {EcPointFormat::COMPRESSED, "00093057fb862f2ad2e82e581baeb3324e7b32946f2ba845a9beeed87d6995f54918ec6" "619b9931955d5a89d4d74adf1046bb362192f2ef6bd3e3d2d04dd1f87054a", "00aa3fb2448335f694e3cda4ae0cc71b1b2f2a206fa802d7262f19983c44674fe15327a" "caac1fa40424c395a6556cb8167312527fae5865ecffc14bbdc17da78cdcf", "0300093057fb862f2ad2e82e581baeb3324e7b32946f2ba845a9beeed87d6995f54918e" "c6619b9931955d5a89d4d74adf1046bb362192f2ef6bd3e3d2d04dd1f87054a", EllipticCurveType::NIST_P521}}; } using EcUtilEncodeDecodePointTest = TestWithParam; TEST_P(EcUtilEncodeDecodePointTest, EcPointEncode) { const EncodingTestVector& test = GetParam(); util::StatusOr> point = GetEcPoint(test.curve, absl::HexStringToBytes(test.x_hex), absl::HexStringToBytes(test.y_hex)); ASSERT_THAT(point, IsOk()); util::StatusOr encoded_point = EcPointEncode(test.curve, test.format, point->get()); ASSERT_THAT(encoded_point, IsOk()); EXPECT_EQ(test.encoded_hex, absl::BytesToHexString(*encoded_point)); } TEST_P(EcUtilEncodeDecodePointTest, EcPointDecode) { const EncodingTestVector& test = GetParam(); // Get the test point and its encoded version. util::StatusOr> point = GetEcPoint(test.curve, absl::HexStringToBytes(test.x_hex), absl::HexStringToBytes(test.y_hex)); ASSERT_THAT(point, IsOk()); std::string encoded_str = absl::HexStringToBytes(test.encoded_hex); util::StatusOr> ec_group = EcGroupFromCurveType(test.curve); util::StatusOr> ec_point = EcPointDecode(test.curve, test.format, encoded_str); ASSERT_THAT(ec_point, IsOk()); EXPECT_EQ(EC_POINT_cmp(ec_group->get(), point->get(), ec_point->get(), /*ctx=*/nullptr), 0); // Modifying the 1st byte decoding fails. encoded_str[0] = '0'; util::StatusOr> ec_point2 = EcPointDecode(test.curve, test.format, encoded_str); EXPECT_THAT(ec_point2, Not(IsOk())); if (test.format == EcPointFormat::UNCOMPRESSED || test.format == EcPointFormat::COMPRESSED) { EXPECT_THAT(std::string(ec_point2.status().message()), HasSubstr("point should start with")); } } INSTANTIATE_TEST_SUITE_P( EcUtilEncodeDecodePointTests, EcUtilEncodeDecodePointTest, ValuesIn(GetEncodingTestVectors()), [](const TestParamInfo& info) { switch (info.param.format) { case EcPointFormat::UNCOMPRESSED: return "Uncompressed"; case EcPointFormat::DO_NOT_USE_CRUNCHY_UNCOMPRESSED: return "DoNotUseCrunchyUncompressed"; case EcPointFormat::COMPRESSED: return "Compressed"; default: return "Unknown"; } }); TEST(EcUtilTest, EcFieldSizeInBytes) { EXPECT_THAT(EcFieldSizeInBytes(EllipticCurveType::NIST_P256), IsOkAndHolds(256 / 8)); EXPECT_THAT(EcFieldSizeInBytes(EllipticCurveType::NIST_P384), IsOkAndHolds(384 / 8)); EXPECT_THAT(EcFieldSizeInBytes(EllipticCurveType::NIST_P521), IsOkAndHolds((521 + 7) / 8)); EXPECT_THAT(EcFieldSizeInBytes(EllipticCurveType::CURVE25519), IsOkAndHolds(256 / 8)); EXPECT_THAT(EcFieldSizeInBytes(EllipticCurveType::UNKNOWN_CURVE).status(), Not(IsOk())); } TEST(EcUtilTest, EcPointEncodingSizeInBytes) { EXPECT_THAT(EcPointEncodingSizeInBytes(EllipticCurveType::NIST_P256, EcPointFormat::UNCOMPRESSED), IsOkAndHolds(2 * (256 / 8) + 1)); EXPECT_THAT(EcPointEncodingSizeInBytes(EllipticCurveType::NIST_P256, EcPointFormat::COMPRESSED), IsOkAndHolds(256 / 8 + 1)); EXPECT_THAT(EcPointEncodingSizeInBytes(EllipticCurveType::NIST_P384, EcPointFormat::UNCOMPRESSED), IsOkAndHolds(2 * (384 / 8) + 1)); EXPECT_THAT(EcPointEncodingSizeInBytes(EllipticCurveType::NIST_P384, EcPointFormat::COMPRESSED), IsOkAndHolds(384 / 8 + 1)); EXPECT_THAT(EcPointEncodingSizeInBytes(EllipticCurveType::NIST_P521, EcPointFormat::UNCOMPRESSED), IsOkAndHolds(2 * ((521 + 7) / 8) + 1)); EXPECT_THAT(EcPointEncodingSizeInBytes(EllipticCurveType::NIST_P521, EcPointFormat::COMPRESSED), IsOkAndHolds((521 + 7) / 8 + 1)); EXPECT_THAT(EcPointEncodingSizeInBytes(EllipticCurveType::CURVE25519, EcPointFormat::COMPRESSED), IsOkAndHolds(256 / 8)); EXPECT_THAT(EcPointEncodingSizeInBytes(EllipticCurveType::NIST_P256, EcPointFormat::UNKNOWN_FORMAT) .status(), Not(IsOk())); } TEST(EcUtilTest, CurveTypeFromEcGroupSuccess) { EC_GROUP* p256_group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); EC_GROUP* p384_group = EC_GROUP_new_by_curve_name(NID_secp384r1); EC_GROUP* p521_group = EC_GROUP_new_by_curve_name(NID_secp521r1); util::StatusOr p256_curve = CurveTypeFromEcGroup(p256_group); util::StatusOr p384_curve = CurveTypeFromEcGroup(p384_group); util::StatusOr p521_curve = CurveTypeFromEcGroup(p521_group); ASSERT_THAT(p256_curve, IsOkAndHolds(EllipticCurveType::NIST_P256)); ASSERT_THAT(p384_curve, IsOkAndHolds(EllipticCurveType::NIST_P384)); ASSERT_THAT(p521_curve, IsOkAndHolds(EllipticCurveType::NIST_P521)); } TEST(EcUtilTest, CurveTypeFromEcGroupUnimplemented) { EXPECT_THAT( CurveTypeFromEcGroup(EC_GROUP_new_by_curve_name(NID_secp224r1)).status(), StatusIs(absl::StatusCode::kUnimplemented)); } TEST(EcUtilTest, EcGroupFromCurveTypeSuccess) { util::StatusOr> p256_curve = EcGroupFromCurveType(EllipticCurveType::NIST_P256); util::StatusOr> p384_curve = EcGroupFromCurveType(EllipticCurveType::NIST_P384); util::StatusOr> p521_curve = EcGroupFromCurveType(EllipticCurveType::NIST_P521); ASSERT_THAT(p256_curve, IsOk()); ASSERT_THAT(p384_curve, IsOk()); ASSERT_THAT(p521_curve, IsOk()); SslUniquePtr ssl_p256_group( EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); SslUniquePtr ssl_p384_group( EC_GROUP_new_by_curve_name(NID_secp384r1)); SslUniquePtr ssl_p521_group( EC_GROUP_new_by_curve_name(NID_secp521r1)); EXPECT_EQ(EC_GROUP_cmp(p256_curve->get(), ssl_p256_group.get(), /*ignored=*/nullptr), 0); EXPECT_EQ(EC_GROUP_cmp(p384_curve->get(), ssl_p384_group.get(), /*ignored=*/nullptr), 0); EXPECT_EQ(EC_GROUP_cmp(p521_curve->get(), ssl_p521_group.get(), /*ignored=*/nullptr), 0); } TEST(EcUtilTest, EcGroupFromCurveTypeUnimplemented) { EXPECT_THAT(EcGroupFromCurveType(EllipticCurveType::UNKNOWN_CURVE).status(), StatusIs(absl::StatusCode::kUnimplemented)); } TEST(EcUtilTest, GetEcPointReturnsAValidPoint) { SslUniquePtr group(EC_GROUP_new_by_curve_name(NID_secp521r1)); const unsigned int kCurveSizeInBytes = (EC_GROUP_get_degree(group.get()) + 7) / 8; constexpr absl::string_view kXCoordinateHex = "00093057fb862f2ad2e82e581baeb3324e7b32946f2ba845a9beeed87d6995f54918ec6" "619b9931955d5a89d4d74adf1046bb362192f2ef6bd3e3d2d04dd1f87054a"; constexpr absl::string_view kYCoordinateHex = "00aa3fb2448335f694e3cda4ae0cc71b1b2f2a206fa802d7262f19983c44674fe15327a" "caac1fa40424c395a6556cb8167312527fae5865ecffc14bbdc17da78cdcf"; util::StatusOr> point = GetEcPoint( EllipticCurveType::NIST_P521, absl::HexStringToBytes(kXCoordinateHex), absl::HexStringToBytes(kYCoordinateHex)); ASSERT_THAT(point, IsOk()); // We check that we can decode this point and the result is the same as the // original coordinates. std::string xy; subtle::ResizeStringUninitialized(&xy, 2 * kCurveSizeInBytes); SslUniquePtr x(BN_new()); SslUniquePtr y(BN_new()); ASSERT_EQ(EC_POINT_get_affine_coordinates(group.get(), point->get(), x.get(), y.get(), /*ctx=*/nullptr), 1); ASSERT_THAT( BignumToBinaryPadded(absl::MakeSpan(&xy[0], kCurveSizeInBytes), x.get()), IsOk()); ASSERT_THAT( BignumToBinaryPadded( absl::MakeSpan(&xy[kCurveSizeInBytes], kCurveSizeInBytes), y.get()), IsOk()); EXPECT_EQ(xy, absl::StrCat(absl::HexStringToBytes(kXCoordinateHex), absl::HexStringToBytes(kYCoordinateHex))); } TEST(EcUtilTest, EcSignatureIeeeToDer) { std::unique_ptr test_vectors = WycheproofUtil::ReadTestVectors("ecdsa_webcrypto_test.json"); ASSERT_THAT(test_vectors, Not(IsNull())); for (const auto& test_group : (*test_vectors)["testGroups"].GetArray()) { EllipticCurveType curve = WycheproofUtil::GetEllipticCurveType(test_group["key"]["curve"]); if (curve == EllipticCurveType::UNKNOWN_CURVE) { continue; } util::StatusOr> ec_group = EcGroupFromCurveType(curve); ASSERT_THAT(ec_group, IsOk()); // Read all the valid signatures. for (const auto& test : test_group["tests"].GetArray()) { std::string result = test["result"].GetString(); if (result != "valid") { continue; } std::string sig = WycheproofUtil::GetBytes(test["sig"]); util::StatusOr der_encoded = EcSignatureIeeeToDer(ec_group->get(), sig); ASSERT_THAT(der_encoded, IsOk()); // Make sure we can reconstruct the IEEE format: [ s || r ]. const uint8_t* der_sig_data_ptr = reinterpret_cast(der_encoded->data()); SslUniquePtr ecdsa_sig(d2i_ECDSA_SIG( /*out=*/nullptr, &der_sig_data_ptr, der_encoded->size())); ASSERT_THAT(ecdsa_sig, Not(IsNull())); // Owned by OpenSSL/BoringSSL. const BIGNUM* r; const BIGNUM* s; ECDSA_SIG_get0(ecdsa_sig.get(), &r, &s); ASSERT_THAT(r, Not(IsNull())); ASSERT_THAT(s, Not(IsNull())); util::StatusOr field_size = EcFieldSizeInBytes(curve); ASSERT_THAT(field_size, IsOk()); util::StatusOr r_str = BignumToString(r, *field_size); ASSERT_THAT(r_str, IsOk()); util::StatusOr s_str = BignumToString(s, *field_size); ASSERT_THAT(s_str, IsOk()); EXPECT_EQ(absl::StrCat(*r_str, *s_str), sig); } } } using EcKeyFromSslEcKeyTestWithParam = testing::TestWithParam; TEST_P(EcKeyFromSslEcKeyTestWithParam, EcKeyFromSslEcKeySucceeds) { EllipticCurveType curve_type = GetParam(); util::StatusOr> group = EcGroupFromCurveType(curve_type); SslUniquePtr key(EC_KEY_new()); EC_KEY_set_group(key.get(), group->get()); EC_KEY_generate_key(key.get()); util::StatusOr ec_key = EcKeyFromSslEcKey(curve_type, *key); EXPECT_THAT(ec_key, IsOk()); EXPECT_THAT(ec_key->curve, Eq(curve_type)); EXPECT_THAT(ec_key->priv, Not(IsEmpty())); EXPECT_THAT(ec_key->pub_x, Not(IsEmpty())); EXPECT_THAT(ec_key->pub_y, Not(IsEmpty())); } TEST(EcKeyFromSSLEcKeyTest, EcKeyFromSslKeyFailsWrongCurveType) { util::StatusOr> group = EcGroupFromCurveType(EllipticCurveType::NIST_P256); SslUniquePtr key(EC_KEY_new()); EC_KEY_set_group(key.get(), group->get()); EC_KEY_generate_key(key.get()); util::StatusOr ec_key = EcKeyFromSslEcKey(EllipticCurveType::NIST_P384, *key); EXPECT_THAT(ec_key.status(), StatusIs(absl::StatusCode::kInternal)); } INSTANTIATE_TEST_SUITE_P(EcKeyFromSslEcKeyTestWithParams, EcKeyFromSslEcKeyTestWithParam, testing::ValuesIn({EllipticCurveType::NIST_P256, EllipticCurveType::NIST_P384, EllipticCurveType::NIST_P521})); // ECDH test vector. struct EcdhWycheproofTestVector { std::string testcase_name; EllipticCurveType curve; std::string id; std::string comment; std::string pub_bytes; std::string priv_bytes; std::string expected_shared_bytes; std::string result; EcPointFormat format; }; // Utility function to look for a `value` inside an array of flags `flags`. bool HasFlag(const rapidjson::Value& flags, absl::string_view value) { if (!flags.IsArray()) { return false; } for (const rapidjson::Value& flag : flags.GetArray()) { if (std::string(flag.GetString()) == value) { return true; } } return false; } // Reads Wycheproof's ECDH test vectors from the given file `file_name`. std::vector ReadEcdhWycheproofTestVectors( absl::string_view file_name) { std::unique_ptr root = WycheproofUtil::ReadTestVectors(std::string(file_name)); std::vector test_vectors; for (const rapidjson::Value& test_group : (*root)["testGroups"].GetArray()) { // Tink only supports secp256r1, secp384r1 or secp521r1. EllipticCurveType curve = WycheproofUtil::GetEllipticCurveType(test_group["curve"]); if (curve == EllipticCurveType::UNKNOWN_CURVE) { continue; } for (const rapidjson::Value& test : test_group["tests"].GetArray()) { // Wycheproof's ECDH public key uses ASN encoding while Tink uses X9.62 // format point encoding. For the purpose of testing, we note the // followings: // + The prefix of ASN encoding contains curve name, so we can skip test // vector with "UnnamedCurve". // + The suffix of ASN encoding is X9.62 format point encoding. // TODO(quannguyen): Use X9.62 test vectors once it's available. if (HasFlag(test["flags"], /*value=*/"UnnamedCurve")) { continue; } // Get the format from "flags". EcPointFormat format = EcPointFormat::UNCOMPRESSED; if (HasFlag(test["flags"], /*value=*/"CompressedPoint")) { format = EcPointFormat::COMPRESSED; } // Testcase name is of the form: _tcid. std::vector file_name_tokens = absl::StrSplit(file_name, '.'); test_vectors.push_back({ absl::StrCat(file_name_tokens[0], "_tcid", test["tcId"].GetInt()), curve, absl::StrCat(test["tcId"].GetInt()), test["comment"].GetString(), WycheproofUtil::GetBytes(test["public"]), WycheproofUtil::GetBytes(test["private"]), WycheproofUtil::GetBytes(test["shared"]), test["result"].GetString(), format, }); } } return test_vectors; } using EcUtilComputeEcdhSharedSecretTest = TestWithParam; TEST_P(EcUtilComputeEcdhSharedSecretTest, ComputeEcdhSharedSecretWycheproof) { EcdhWycheproofTestVector params = GetParam(); util::StatusOr point_size = internal::EcPointEncodingSizeInBytes(params.curve, params.format); ASSERT_THAT(point_size, IsOk()); if (*point_size > params.pub_bytes.size()) { GTEST_SKIP(); } std::string pub_bytes = params.pub_bytes.substr( params.pub_bytes.size() - *point_size, *point_size); util::StatusOr> pub_key = EcPointDecode(params.curve, params.format, pub_bytes); if (!pub_key.ok()) { // Make sure we didn't fail decoding a valid point, then we can terminate // testing; ASSERT_NE(params.result, "valid"); return; } util::StatusOr> priv_key = StringToBignum(params.priv_bytes); ASSERT_THAT(priv_key, IsOk()); util::StatusOr shared_secret = ComputeEcdhSharedSecret(params.curve, priv_key->get(), pub_key->get()); if (params.result == "invalid") { EXPECT_THAT(shared_secret, Not(IsOk())); } else { EXPECT_THAT(shared_secret, IsOkAndHolds(util::SecretDataFromStringView( params.expected_shared_bytes))); } } std::vector GetEcUtilComputeEcdhSharedSecretParams() { std::vector test_vectors = ReadEcdhWycheproofTestVectors( /*file_name=*/"ecdh_secp256r1_test.json"); std::vector others = ReadEcdhWycheproofTestVectors( /*file_name=*/"ecdh_secp384r1_test.json"); test_vectors.insert(test_vectors.end(), others.begin(), others.end()); others = ReadEcdhWycheproofTestVectors( /*file_name=*/"ecdh_secp521r1_test.json"); test_vectors.insert(test_vectors.end(), others.begin(), others.end()); others = ReadEcdhWycheproofTestVectors( /*file_name=*/"ecdh_test.json"); test_vectors.insert(test_vectors.end(), others.begin(), others.end()); return test_vectors; } INSTANTIATE_TEST_SUITE_P( EcUtilComputeEcdhSharedSecretTests, EcUtilComputeEcdhSharedSecretTest, ValuesIn(GetEcUtilComputeEcdhSharedSecretParams()), [](const TestParamInfo& info) { return info.param.testcase_name; }); } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/err_util.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/err_util.h" #include #include #include "openssl/err.h" namespace crypto { namespace tink { namespace internal { std::string GetSslErrors() { std::string ret; ERR_print_errors_cb( [](const char *str, size_t len, void *ctx) -> int { static_cast(ctx)->append(str, len); return 1; }, &ret); return ret; } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/err_util.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_ERR_UTIL_H_ #define TINK_INTERNAL_ERR_UTIL_H_ #include namespace crypto { namespace tink { namespace internal { // Returns OpenSSL error strings accumulated in the error queue, thus emptying // the queue. std::string GetSslErrors(); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_ERR_UTIL_H_ ================================================ FILE: cc/internal/err_util_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/err_util.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "openssl/bio.h" #include "openssl/err.h" namespace crypto { namespace tink { namespace internal { namespace { using ::testing::AllOf; using ::testing::HasSubstr; using ::testing::IsEmpty; using ::testing::SizeIs; TEST(GetSslErrorsTest, ReturnsExpectedErrorrs) { // Artificially add some errors to OpenSSL/BoringSSL's error queue. #ifdef OPENSSL_IS_BORINGSSL OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED); OPENSSL_PUT_ERROR(BIO, BIO_R_WRITE_TO_READ_ONLY_BIO); OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD); #else BIOerr(BIO_F_BIO_READ_INTERN, BIO_R_UNINITIALIZED); BIOerr(BIO_F_MEM_WRITE, BIO_R_WRITE_TO_READ_ONLY_BIO); BIOerr(BIO_F_BIO_CTRL, BIO_R_UNSUPPORTED_METHOD); #endif std::string error = GetSslErrors(); // OpenSSL/BoringSSL returns each error as a null terminated char*; since we // accumulate each of them into a std::string, the resulting string will be // "double null terminated". So we ignore the last char, and split by \n. auto errors_without_last_char = absl::string_view(error); errors_without_last_char.remove_suffix(1); std::vector lines = absl::StrSplit(errors_without_last_char, '\n'); ASSERT_THAT(lines, SizeIs(3)); #ifdef OPENSSL_IS_BORINGSSL std::string uninitialized_str = "UNINITIALIZED"; std::string write_to_read_only_bio_str = "WRITE_TO_READ_ONLY_BIO"; std::string unsupported_method_str = "UNSUPPORTED_METHOD"; #else std::string uninitialized_str = "uninitialized"; std::string write_to_read_only_bio_str = "write to read only BIO"; std::string unsupported_method_str = "unsupported method"; #endif EXPECT_THAT(lines[0], AllOf(HasSubstr("BIO"), HasSubstr(uninitialized_str))); EXPECT_THAT(lines[1], AllOf(HasSubstr("BIO"), HasSubstr(write_to_read_only_bio_str))); EXPECT_THAT(lines[2], AllOf(HasSubstr("BIO"), HasSubstr(unsupported_method_str))); // A second call to GetSslErrors() returns an empty string because the // OpenSSL/BoringSSL error queue is empty. EXPECT_THAT(GetSslErrors(), IsEmpty()); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/fips_utils.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/fips_utils.h" #include #include "absl/base/attributes.h" #include "absl/status/status.h" #include "openssl/crypto.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { #ifdef TINK_USE_ONLY_FIPS ABSL_CONST_INIT const bool kUseOnlyFips = true; #else ABSL_CONST_INIT const bool kUseOnlyFips = false; #endif static std::atomic is_fips_restricted(false); void SetFipsRestricted() { is_fips_restricted = true; } void UnSetFipsRestricted() { is_fips_restricted = false; } bool IsFipsModeEnabled() { return kUseOnlyFips || is_fips_restricted; } bool IsFipsEnabledInSsl() { #ifdef OPENSSL_IS_BORINGSSL return FIPS_mode(); #else return false; #endif } util::Status ChecksFipsCompatibility(FipsCompatibility fips_status) { switch (fips_status) { case FipsCompatibility::kNotFips: if (IsFipsModeEnabled()) { return util::Status(absl::StatusCode::kInternal, "Primitive not available in FIPS only mode."); } else { return util::OkStatus(); } case FipsCompatibility::kRequiresBoringCrypto: if ((IsFipsModeEnabled()) && !IsFipsEnabledInSsl()) { return util::Status( absl::StatusCode::kInternal, "BoringSSL not built with the BoringCrypto module. If you want to " "use FIPS only mode you have to build BoringSSL in FIPS Mode."); } else { return util::OkStatus(); } default: return util::Status(absl::StatusCode::kInternal, "Could not determine FIPS status."); } } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/fips_utils.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_FIPS_UTILS_H_ #define TINK_INTERNAL_FIPS_UTILS_H_ #include "absl/base/attributes.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { // This flag indicates whether Tink was build in FIPS only mode. If the flag // is set, then usage of algorithms will be restricted to algorithms which // utilize the FIPS validated BoringCrypto module. TODO(kste): Check if this can // be removed. ABSL_CONST_INIT extern const bool kUseOnlyFips; // This function will return true if Tink has been built in FIPS mode or if // the FIPS restrictions have been enabled at runtime. bool IsFipsModeEnabled(); // Returns true if the Ssl layer (BoringSSL or OpenSSL) has FIPS mode enabled. bool IsFipsEnabledInSsl(); // Enable FIPS restrictions. If Tink has been built in FIPS mode this is // redundant. void SetFipsRestricted(); // Disable FIPS restrictions. Note that if Tink has been built in FIPS mode this // will have no effect. void UnSetFipsRestricted(); // Should be used to indicate whether an algorithm can be used in FIPS only // mode or not. enum class FipsCompatibility { kNotFips = 0, // The algorithm can not use a FIPS validated implementation. kRequiresBoringCrypto, // The algorithm requires BoringCrypto to use a FIPS // validated implementation. }; // Allows to check for a cryptographic algorithm whether it is available in // the FIPS only mode, based on it's FipsCompatibility flag. If FIPS only // mode is enabled this will return an INTERNAL error if: // 1) The algorithm has no FIPS support. // 2) The algorithm has FIPS support, but BoringSSL has not been compiled with // the BoringCrypto module. crypto::tink::util::Status ChecksFipsCompatibility( FipsCompatibility fips_status); // Utility function wich calls CheckFipsCompatibility(T::kFipsStatus). template crypto::tink::util::Status CheckFipsCompatibility() { return ChecksFipsCompatibility(T::kFipsStatus); } } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_FIPS_UTILS_H_ ================================================ FILE: cc/internal/fips_utils_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/fips_utils.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "openssl/crypto.h" #include "tink/util/status.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; class FipsIncompatible { public: static constexpr FipsCompatibility kFipsStatus = FipsCompatibility::kNotFips; }; class FipsCompatibleWithBoringCrypto { public: static constexpr FipsCompatibility kFipsStatus = FipsCompatibility::kRequiresBoringCrypto; }; TEST(FipsUtilsTest, CompatibilityInNonFipsMode) { if (kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT(CheckFipsCompatibility(), IsOk()); EXPECT_THAT(CheckFipsCompatibility(), IsOk()); } TEST(FipsUtilsTest, CompatibilityInFipsMode) { if (!kUseOnlyFips || !IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test should only run in FIPS mode with Boringcrypto available."; } EXPECT_THAT(CheckFipsCompatibility(), StatusIs(absl::StatusCode::kInternal)); EXPECT_THAT(CheckFipsCompatibility(), IsOk()); } TEST(TinkFipsTest, CompatibilityInFipsModeWithoutBoringCrypto) { if (!kUseOnlyFips || IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test only run if BoringCrypto module is not available."; } // In FIPS only mode compatibility checks should disallow algorithms // with the FipsCompatibility::kNone flag. EXPECT_THAT(CheckFipsCompatibility(), StatusIs(absl::StatusCode::kInternal)); // FIPS validated implementations are not allowed if BoringCrypto is not // available. EXPECT_THAT(CheckFipsCompatibility(), StatusIs(absl::StatusCode::kInternal)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/key_gen_configuration_impl.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_KEY_GEN_CONFIGURATION_IMPL_H_ #define TINK_INTERNAL_KEY_GEN_CONFIGURATION_IMPL_H_ #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/internal/key_type_info_store.h" #include "tink/key_gen_configuration.h" #include "tink/key_manager.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { constexpr absl::string_view kKeyGenConfigurationImplErr = "Use crypto::tink::Registry instead when in global registry mode."; class KeyGenConfigurationImpl { public: template static crypto::tink::util::Status AddKeyTypeManager( std::unique_ptr key_manager, crypto::tink::KeyGenConfiguration& config) { if (config.global_registry_mode_) { return crypto::tink::util::Status(absl::StatusCode::kFailedPrecondition, kKeyGenConfigurationImplErr); } return config.key_type_info_store_.AddKeyTypeManager( std::move(key_manager), /*new_key_allowed=*/true); } template static crypto::tink::util::Status AddAsymmetricKeyManagers( std::unique_ptr private_key_manager, std::unique_ptr public_key_manager, crypto::tink::KeyGenConfiguration& config) { if (config.global_registry_mode_) { return crypto::tink::util::Status(absl::StatusCode::kFailedPrecondition, kKeyGenConfigurationImplErr); } return config.key_type_info_store_.AddAsymmetricKeyTypeManagers( std::move(private_key_manager), std::move(public_key_manager), /*new_key_allowed=*/true); } template static crypto::tink::util::Status AddLegacyKeyManager( std::unique_ptr> key_manager, crypto::tink::KeyGenConfiguration& config) { if (config.global_registry_mode_) { return crypto::tink::util::Status(absl::StatusCode::kFailedPrecondition, kKeyGenConfigurationImplErr); } return config.key_type_info_store_.AddKeyManager(std::move(key_manager), /*new_key_allowed=*/true); } static crypto::tink::util::StatusOr< const crypto::tink::internal::KeyTypeInfoStore*> GetKeyTypeInfoStore(const crypto::tink::KeyGenConfiguration& config) { if (config.global_registry_mode_) { return crypto::tink::util::Status(absl::StatusCode::kFailedPrecondition, kKeyGenConfigurationImplErr); } return &config.key_type_info_store_; } // `config` can be set to global registry mode only if empty. static crypto::tink::util::Status SetGlobalRegistryMode( crypto::tink::KeyGenConfiguration& config) { if (!config.key_type_info_store_.IsEmpty()) { return crypto::tink::util::Status( absl::StatusCode::kFailedPrecondition, "Using the global registry is only allowed when KeyGenConfiguration " "is empty."); } config.global_registry_mode_ = true; return crypto::tink::util::OkStatus(); } static bool IsInGlobalRegistryMode( const crypto::tink::KeyGenConfiguration& config) { return config.global_registry_mode_; } }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_KEY_GEN_CONFIGURATION_IMPL_H_ ================================================ FILE: cc/internal/key_gen_configuration_impl_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/key_gen_configuration_impl.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/aead/aead_key_templates.h" #include "tink/core/key_manager_impl.h" #include "tink/core/key_type_manager.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/input_stream.h" #include "tink/internal/key_type_info_store.h" #include "tink/key_gen_configuration.h" #include "tink/key_manager.h" #include "tink/keyset_handle.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_gcm.pb.h" #include "proto/rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::AesGcmKey; using ::google::crypto::tink::AesGcmKeyFormat; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::RsaSsaPssKeyFormat; using ::google::crypto::tink::RsaSsaPssParams; using ::google::crypto::tink::RsaSsaPssPrivateKey; using ::google::crypto::tink::RsaSsaPssPublicKey; class FakePrimitive { public: explicit FakePrimitive(std::string s) : s_(s) {} std::string get() { return s_; } private: std::string s_; }; class FakeKeyTypeManager : public KeyTypeManager> { public: class FakePrimitiveFactory : public PrimitiveFactory { public: util::StatusOr> Create( const AesGcmKey& key) const override { return absl::make_unique(key.key_value()); } }; FakeKeyTypeManager() : KeyTypeManager(absl::make_unique()) {} KeyData::KeyMaterialType key_material_type() const override { return KeyData::SYMMETRIC; } uint32_t get_version() const override { return 0; } const std::string& get_key_type() const override { return key_type_; } util::Status ValidateKey(const AesGcmKey& key) const override { return util::OkStatus(); } util::Status ValidateKeyFormat( const AesGcmKeyFormat& key_format) const override { return util::OkStatus(); } util::StatusOr CreateKey( const AesGcmKeyFormat& key_format) const override { return AesGcmKey(); } util::StatusOr DeriveKey( const AesGcmKeyFormat& key_format, InputStream* input_stream) const override { return AesGcmKey(); } private: const std::string key_type_ = "type.googleapis.com/google.crypto.tink.AesGcmKey"; }; TEST(KeyGenConfigurationImplTest, AddKeyTypeManager) { KeyGenConfiguration config; EXPECT_THAT(KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config), IsOk()); } TEST(KeyGenConfigurationImplTest, AddLegacyKeyManager) { KeyGenConfiguration config; FakeKeyTypeManager manager; EXPECT_THAT(KeyGenConfigurationImpl::AddLegacyKeyManager( MakeKeyManager(&manager), config), IsOk()); } TEST(KeyGenConfigurationImplTest, GetKeyTypeInfoStore) { KeyGenConfiguration config; ASSERT_THAT(KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config), IsOk()); EXPECT_THAT(KeyGenConfigurationImpl::GetKeyTypeInfoStore(config), IsOk()); } TEST(KeyGenConfigurationImplTest, GetKeyTypeManager) { KeyGenConfiguration config; ASSERT_THAT(KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config), IsOk()); std::string type_url = FakeKeyTypeManager().get_key_type(); util::StatusOr store = KeyGenConfigurationImpl::GetKeyTypeInfoStore(config); ASSERT_THAT(store, IsOk()); util::StatusOr info = (*store)->Get(type_url); ASSERT_THAT(info, IsOk()); util::StatusOr*> key_manager = (*info)->get_key_manager(type_url); ASSERT_THAT(key_manager, IsOk()); EXPECT_EQ((*key_manager)->get_key_type(), type_url); } TEST(KeyGenConfigurationImplTest, GetLegacyKeyManager) { KeyGenConfiguration config; FakeKeyTypeManager manager; ASSERT_THAT(KeyGenConfigurationImpl::AddLegacyKeyManager( MakeKeyManager(&manager), config), IsOk()); util::StatusOr store = KeyGenConfigurationImpl::GetKeyTypeInfoStore(config); ASSERT_THAT(store, IsOk()); std::string type_url = FakeKeyTypeManager().get_key_type(); util::StatusOr info = (*store)->Get(type_url); ASSERT_THAT(info, IsOk()); util::StatusOr*> key_manager = (*info)->get_key_manager(type_url); ASSERT_THAT(key_manager, IsOk()); EXPECT_EQ((*key_manager)->get_key_type(), type_url); } TEST(KeyGenConfigurationImplTest, GetMissingKeyManagerFails) { KeyGenConfiguration config; util::StatusOr store = KeyGenConfigurationImpl::GetKeyTypeInfoStore(config); ASSERT_THAT(store, IsOk()); EXPECT_THAT((*store)->Get("i.do.not.exist").status(), StatusIs(absl::StatusCode::kNotFound)); } class FakeSignKeyManager : public PrivateKeyTypeManager> { public: class PublicKeySignFactory : public PrimitiveFactory { public: util::StatusOr> Create( const RsaSsaPssPrivateKey& key) const override { return {absl::make_unique("a public key sign")}; } }; explicit FakeSignKeyManager() : PrivateKeyTypeManager(absl::make_unique()) {} KeyData::KeyMaterialType key_material_type() const override { return KeyData::ASYMMETRIC_PRIVATE; } uint32_t get_version() const override { return 0; } const std::string& get_key_type() const override { return key_type_; } util::Status ValidateKey(const RsaSsaPssPrivateKey& key) const override { return util::OkStatus(); } util::Status ValidateKeyFormat( const RsaSsaPssKeyFormat& key_format) const override { return util::OkStatus(); } util::StatusOr CreateKey( const RsaSsaPssKeyFormat& key_format) const override { return RsaSsaPssPrivateKey(); } util::StatusOr DeriveKey( const RsaSsaPssKeyFormat& key_format, InputStream* input_stream) const override { return RsaSsaPssPrivateKey(); } util::StatusOr GetPublicKey( const RsaSsaPssPrivateKey& private_key) const override { return private_key.public_key(); } private: const std::string key_type_ = "some.sign.key.type"; }; class FakeVerifyKeyManager : public KeyTypeManager> { public: class PublicKeyVerifyFactory : public PrimitiveFactory { public: util::StatusOr> Create( const RsaSsaPssPublicKey& key) const override { return { absl::make_unique("a public key verify")}; } }; explicit FakeVerifyKeyManager() : KeyTypeManager(absl::make_unique()) {} KeyData::KeyMaterialType key_material_type() const override { return KeyData::ASYMMETRIC_PUBLIC; } uint32_t get_version() const override { return 0; } const std::string& get_key_type() const override { return key_type_; } util::Status ValidateKey(const RsaSsaPssPublicKey& key) const override { return util::OkStatus(); } util::Status ValidateParams(const RsaSsaPssParams& params) const { return util::OkStatus(); } private: const std::string key_type_ = "some.verify.key.type"; }; TEST(KeyGenConfigurationImplTest, AddAsymmetricKeyManagers) { KeyGenConfiguration config; EXPECT_THAT(KeyGenConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config), IsOk()); } TEST(KeyGenConfigurationImplTest, GetAsymmetricKeyManagers) { KeyGenConfiguration config; ASSERT_THAT(KeyGenConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config), IsOk()); { std::string type_url = FakeSignKeyManager().get_key_type(); util::StatusOr store = KeyGenConfigurationImpl::GetKeyTypeInfoStore(config); ASSERT_THAT(store, IsOk()); util::StatusOr info = (*store)->Get(type_url); ASSERT_THAT(info, IsOk()); util::StatusOr*> key_manager = (*info)->get_key_manager(type_url); ASSERT_THAT(key_manager, IsOk()); EXPECT_EQ((*key_manager)->get_key_type(), type_url); } { std::string type_url = FakeVerifyKeyManager().get_key_type(); util::StatusOr store = KeyGenConfigurationImpl::GetKeyTypeInfoStore(config); ASSERT_THAT(store, IsOk()); util::StatusOr info = (*store)->Get(type_url); ASSERT_THAT(info, IsOk()); util::StatusOr*> key_manager = (*info)->get_key_manager(type_url); ASSERT_THAT(key_manager, IsOk()); EXPECT_EQ((*key_manager)->get_key_type(), type_url); } } TEST(KeyGenConfigurationImplTest, GlobalRegistryMode) { Registry::Reset(); KeyGenConfiguration config; ASSERT_THAT(KeyGenConfigurationImpl::SetGlobalRegistryMode(config), IsOk()); EXPECT_TRUE(KeyGenConfigurationImpl::IsInGlobalRegistryMode(config)); // Check that KeyGenConfigurationImpl functions return kFailedPrecondition. EXPECT_THAT(KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config), StatusIs(absl::StatusCode::kFailedPrecondition)); EXPECT_THAT(KeyGenConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config), StatusIs(absl::StatusCode::kFailedPrecondition)); FakeKeyTypeManager manager; EXPECT_THAT(KeyGenConfigurationImpl::AddLegacyKeyManager( MakeKeyManager(&manager), config), StatusIs(absl::StatusCode::kFailedPrecondition)); EXPECT_THAT(KeyGenConfigurationImpl::GetKeyTypeInfoStore(config).status(), StatusIs(absl::StatusCode::kFailedPrecondition)); EXPECT_THAT( KeysetHandle::GenerateNew(AeadKeyTemplates::Aes256Gcm(), config).status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT( Registry::RegisterKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/true), IsOk()); EXPECT_THAT( KeysetHandle::GenerateNew(AeadKeyTemplates::Aes256Gcm(), config).status(), IsOk()); } TEST(KeyGenConfigurationImplTest, GlobalRegistryModeWithNonEmptyConfigFails) { KeyGenConfiguration config; ASSERT_THAT(KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config), IsOk()); EXPECT_THAT(KeyGenConfigurationImpl::SetGlobalRegistryMode(config), StatusIs(absl::StatusCode::kFailedPrecondition)); EXPECT_FALSE(KeyGenConfigurationImpl::IsInGlobalRegistryMode(config)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/key_info.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/key_info.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::google::crypto::tink::Keyset; using ::google::crypto::tink::KeysetInfo; KeysetInfo::KeyInfo KeyInfoFromKey(const Keyset::Key& key) { KeysetInfo::KeyInfo key_info; key_info.set_key_id(key.key_id()); key_info.set_type_url(key.key_data().type_url()); key_info.set_output_prefix_type(key.output_prefix_type()); key_info.set_status(key.status()); return key_info; } KeysetInfo KeysetInfoFromKeyset(const Keyset& keyset) { KeysetInfo keyset_info; keyset_info.set_primary_key_id(keyset.primary_key_id()); for (const Keyset::Key& key : keyset.key()) { *keyset_info.add_key_info() = KeyInfoFromKey(key); } return keyset_info; } } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/key_info.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_KEY_INFO_H_ #define TINK_INTERNAL_KEY_INFO_H_ #include "proto/tink.pb.h" namespace crypto { namespace tink { google::crypto::tink::KeysetInfo::KeyInfo KeyInfoFromKey( const google::crypto::tink::Keyset::Key& key); google::crypto::tink::KeysetInfo KeysetInfoFromKeyset( const google::crypto::tink::Keyset& keyset); } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_KEY_INFO_H_ ================================================ FILE: cc/internal/key_info_test.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/key_info.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::testing::Eq; using ::google::crypto::tink::Keyset; TEST(KeyInfoFromKeyTest, Basic) { Keyset::Key key; key.set_key_id(1234); key.set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); key.set_status(google::crypto::tink::ENABLED); key.mutable_key_data()->set_type_url("MyTypeUrl"); EXPECT_THAT(KeyInfoFromKey(key).key_id(), Eq(1234)); EXPECT_THAT(KeyInfoFromKey(key).output_prefix_type(), Eq(google::crypto::tink::OutputPrefixType::TINK)); EXPECT_THAT(KeyInfoFromKey(key).status(), Eq(google::crypto::tink::ENABLED)); EXPECT_THAT(KeyInfoFromKey(key).type_url(), Eq("MyTypeUrl")); } TEST(KeyInfoFromKeyTest, Status) { google::crypto::tink::Keyset::Key key; key.set_status(google::crypto::tink::ENABLED); EXPECT_THAT(KeyInfoFromKey(key).status(), Eq(google::crypto::tink::ENABLED)); key.set_status(google::crypto::tink::DISABLED); EXPECT_THAT(KeyInfoFromKey(key).status(), Eq(google::crypto::tink::DISABLED)); } TEST(KeyInfoFromKeyTest, OutputPrefixType) { google::crypto::tink::Keyset::Key key; key.set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); EXPECT_THAT(KeyInfoFromKey(key).output_prefix_type(), Eq(google::crypto::tink::OutputPrefixType::TINK)); key.set_output_prefix_type(google::crypto::tink::OutputPrefixType::CRUNCHY); EXPECT_THAT(KeyInfoFromKey(key).output_prefix_type(), Eq(google::crypto::tink::OutputPrefixType::CRUNCHY)); } TEST(KeySetInfoForKeySetTest, Basic) { Keyset keyset; keyset.set_primary_key_id(1234); keyset.add_key()->set_key_id(1233); keyset.add_key()->set_key_id(1234); keyset.add_key()->set_key_id(1235); EXPECT_THAT(KeysetInfoFromKeyset(keyset).primary_key_id(), Eq(1234)); EXPECT_THAT(KeysetInfoFromKeyset(keyset).key_info().size(), Eq(3)); EXPECT_THAT(KeysetInfoFromKeyset(keyset).key_info(0).key_id(), Eq(1233)); EXPECT_THAT(KeysetInfoFromKeyset(keyset).key_info(1).key_id(), Eq(1234)); EXPECT_THAT(KeysetInfoFromKeyset(keyset).key_info(2).key_id(), Eq(1235)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/key_parser.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_KEY_PARSER_H_ #define TINK_INTERNAL_KEY_PARSER_H_ #include #include #include #include #include #include "absl/functional/function_ref.h" #include "absl/log/log.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/internal/parser_index.h" #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/secret_key_access_token.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { // Non-template base class that can be used with internal registry map. class KeyParser { public: // Parses a `serialization` into a key. // // This function is usually called on a `Serialization` subclass matching the // value returned by `ObjectIdentifier()`. However, implementations should // check that this is the case. virtual util::StatusOr> ParseKey( const Serialization& serialization, absl::optional token) const = 0; // Returns the object identifier for `SerializationT`, which is only valid // for the lifetime of this object. // // The object identifier is a unique identifier per registry for this object // (in the standard proto serialization, it is the type URL). In other words, // when registering a `KeyParser`, the registry will invoke this to get // the handled object identifier. In order to parse an object of // `SerializationT`, the registry will then obtain the object identifier of // this serialization object, and call the parser corresponding to this // object. virtual absl::string_view ObjectIdentifier() const = 0; // Returns an index that can be used to look up the `KeyParser` // object registered for the `KeyT` type in a registry. virtual ParserIndex Index() const = 0; virtual ~KeyParser() = default; }; // Parses `SerializationT` objects into `KeyT` objects. template class KeyParserImpl : public KeyParser { public: // Creates a key parser with `object_identifier` and parsing `function`. The // referenced `function` should outlive the created key parser object. explicit KeyParserImpl( absl::string_view object_identifier, absl::FunctionRef( SerializationT, absl::optional)> function) : object_identifier_(object_identifier), function_(function) {} util::StatusOr> ParseKey( const Serialization& serialization, absl::optional token) const override { if (serialization.ObjectIdentifier() != object_identifier_) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid object identifier for this key parser."); } const SerializationT* st = dynamic_cast(&serialization); if (st == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid serialization type for this key parser."); } util::StatusOr key = function_(*st, token); if (!key.ok()) return key.status(); return {absl::make_unique(std::move(*key))}; } absl::string_view ObjectIdentifier() const override { return object_identifier_; } ParserIndex Index() const override { return ParserIndex::Create(object_identifier_); } private: std::string object_identifier_; std::function(SerializationT, absl::optional)> function_; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_KEY_PARSER_H_ ================================================ FILE: cc/internal/key_parser_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/key_parser.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/parser_index.h" #include "tink/internal/serialization.h" #include "tink/internal/serialization_test_util.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; TEST(KeyParserTest, Create) { std::unique_ptr parser = absl::make_unique>( kNoIdTypeUrl, ParseNoIdKey); EXPECT_THAT(parser->ObjectIdentifier(), Eq(kNoIdTypeUrl)); EXPECT_THAT( parser->Index(), Eq(ParserIndex::Create(kNoIdTypeUrl))); } TEST(KeyParserTest, ParseKey) { std::unique_ptr parser = absl::make_unique>( kNoIdTypeUrl, ParseNoIdKey); NoIdSerialization serialization; util::StatusOr> key = parser->ParseKey(serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); EXPECT_THAT((*key)->GetIdRequirement(), Eq(absl::nullopt)); EXPECT_THAT((*key)->GetParameters(), Eq(NoIdParams())); EXPECT_THAT(**key, Eq(NoIdKey())); } TEST(KeyParserTest, ParsePublicKeyNoAccessToken) { std::unique_ptr parser = absl::make_unique>( kNoIdTypeUrl, ParseNoIdKey); NoIdSerialization serialization; util::StatusOr> public_key = parser->ParseKey(serialization, absl::nullopt); ASSERT_THAT(public_key, IsOk()); EXPECT_THAT((*public_key)->GetIdRequirement(), Eq(absl::nullopt)); EXPECT_THAT((*public_key)->GetParameters(), Eq(NoIdParams())); EXPECT_THAT(**public_key, Eq(NoIdKey())); } TEST(KeyParserTest, ParseKeyWithInvalidSerializationType) { std::unique_ptr parser = absl::make_unique>( "example_type_url", ParseNoIdKey); IdKeySerialization serialization(/*id=*/123); util::StatusOr> key = parser->ParseKey(serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(KeyParserTest, ParseKeyWithInvalidObjectIdentifier) { std::unique_ptr parser = absl::make_unique>( "mismatched_type_url", ParseNoIdKey); NoIdSerialization serialization; util::StatusOr> key = parser->ParseKey(serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/key_serializer.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_KEY_SERIALIZER_H_ #define TINK_INTERNAL_KEY_SERIALIZER_H_ #include #include #include #include #include "absl/functional/function_ref.h" #include "absl/log/log.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/internal/serialization.h" #include "tink/internal/serializer_index.h" #include "tink/key.h" #include "tink/secret_key_access_token.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { // Non-template base class that can be used with internal registry map. class KeySerializer { public: // Returns the serialization of `key`. virtual util::StatusOr> SerializeKey( const Key& key, absl::optional token) const = 0; // Returns an index that can be used to look up the `KeySerializer` // object registered for the `KeyT` type in a registry. virtual SerializerIndex Index() const = 0; virtual ~KeySerializer() = default; }; // Serializes `KeyT` objects into `SerializationT` objects. template class KeySerializerImpl : public KeySerializer { public: // Creates a key serializer with serialization `function`. The referenced // `function` should outlive the created key serializer object. explicit KeySerializerImpl(absl::FunctionRef( KeyT, absl::optional)> function) : function_(function) {} util::StatusOr> SerializeKey( const Key& key, absl::optional token) const override { const KeyT* kt = dynamic_cast(&key); if (kt == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid key type for this key serializer."); } util::StatusOr serialization = function_(*kt, token); if (!serialization.ok()) return serialization.status(); return {absl::make_unique(std::move(*serialization))}; } SerializerIndex Index() const override { return SerializerIndex::Create(); } private: std::function( KeyT, absl::optional)> function_; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_KEY_SERIALIZER_H_ ================================================ FILE: cc/internal/key_serializer_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/key_serializer.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/serialization.h" #include "tink/internal/serialization_test_util.h" #include "tink/internal/serializer_index.h" #include "tink/key.h" #include "tink/secret_key_access_token.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; TEST(KeySerializerTest, Create) { std::unique_ptr serializer = absl::make_unique>( SerializeNoIdKey); EXPECT_THAT(serializer->Index(), Eq(SerializerIndex::Create())); } TEST(KeySerializerTest, SerializeKey) { std::unique_ptr serializer = absl::make_unique>( SerializeNoIdKey); NoIdKey key; util::StatusOr> serialization = serializer->SerializeKey(key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kNoIdTypeUrl)); } TEST(KeySerializerTest, SerializePublicKeyNoAccessToken) { std::unique_ptr serializer = absl::make_unique>( SerializeNoIdKey); NoIdKey public_key; util::StatusOr> serialization = serializer->SerializeKey(public_key, absl::nullopt); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kNoIdTypeUrl)); } TEST(KeySerializerTest, SerializeKeyWithInvalidKeyType) { std::unique_ptr serializer = absl::make_unique>( SerializeNoIdKey); IdKey key(/*id=*/123); util::StatusOr> serialization = serializer->SerializeKey(key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/key_status_util.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/key_status_util.h" #include #include "absl/status/status.h" #include "tink/key_status.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { using ::google::crypto::tink::KeyStatusType; util::StatusOr FromKeyStatusType(KeyStatusType status_type) { switch (status_type) { case KeyStatusType::ENABLED: return KeyStatus::kEnabled; case KeyStatusType::DISABLED: return KeyStatus::kDisabled; case KeyStatusType::DESTROYED: return KeyStatus::kDestroyed; default: return util::Status(absl::StatusCode::kInvalidArgument, "Invalid key status type."); } } util::StatusOr ToKeyStatusType(KeyStatus status) { switch (status) { case KeyStatus::kEnabled: return KeyStatusType::ENABLED; case KeyStatus::kDisabled: return KeyStatusType::DISABLED; case KeyStatus::kDestroyed: return KeyStatusType::DESTROYED; default: return util::Status(absl::StatusCode::kInvalidArgument, "Invalid key status."); } } std::string ToKeyStatusName(KeyStatus status) { switch (status) { case KeyStatus::kEnabled: return KeyStatusType_Name(KeyStatusType::ENABLED); case KeyStatus::kDisabled: return KeyStatusType_Name(KeyStatusType::DISABLED); case KeyStatus::kDestroyed: return KeyStatusType_Name(KeyStatusType::DESTROYED); default: return KeyStatusType_Name(KeyStatusType::UNKNOWN_STATUS); } } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/key_status_util.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_KEY_STATUS_UTIL_H_ #define TINK_INTERNAL_KEY_STATUS_UTIL_H_ #include #include "tink/key_status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { // Returns `KeyStatus` C++ enum for a given `KeyStatusType` proto enum. If // `status_type` is unrecognized (i.e., not handled), then an error is returned. util::StatusOr FromKeyStatusType( google::crypto::tink::KeyStatusType status_type); // Returns `KeyStatusType` proto enum for a given `KeyStatus` C++ enum. If // `status` is unrecognized (i.e., not handled), then an error is returned. util::StatusOr ToKeyStatusType( KeyStatus status); // Returns a canonical name for a `KeyStatus` based on the corresponding // `KeyStatusType` proto enum. std::string ToKeyStatusName(KeyStatus status); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_KEY_STATUS_UTIL_H_ ================================================ FILE: cc/internal/key_status_util_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/key_status_util.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/key_status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::KeyStatusType; TEST(KeyStatusUtilTest, FromKeyStatusType) { util::StatusOr enabled = FromKeyStatusType(KeyStatusType::ENABLED); EXPECT_THAT(enabled, IsOkAndHolds(KeyStatus::kEnabled)); util::StatusOr disabled = FromKeyStatusType(KeyStatusType::DISABLED); EXPECT_THAT(disabled, IsOkAndHolds(KeyStatus::kDisabled)); util::StatusOr destroyed = FromKeyStatusType(KeyStatusType::DESTROYED); EXPECT_THAT(destroyed, IsOkAndHolds(KeyStatus::kDestroyed)); util::StatusOr unknown = FromKeyStatusType(KeyStatusType::UNKNOWN_STATUS); EXPECT_THAT(unknown.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(KeyStatusUtilTest, ToKeyStatusType) { util::StatusOr enabled = ToKeyStatusType(KeyStatus::kEnabled); EXPECT_THAT(enabled, IsOkAndHolds(KeyStatusType::ENABLED)); util::StatusOr disabled = ToKeyStatusType(KeyStatus::kDisabled); EXPECT_THAT(disabled, IsOkAndHolds(KeyStatusType::DISABLED)); util::StatusOr destroyed = ToKeyStatusType(KeyStatus::kDestroyed); EXPECT_THAT(destroyed, IsOkAndHolds(KeyStatusType::DESTROYED)); util::StatusOr unknown = ToKeyStatusType( KeyStatus::kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements); EXPECT_THAT(unknown.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(KeyStatusUtilTest, ToKeyStatusName) { EXPECT_EQ(ToKeyStatusName(KeyStatus::kEnabled), "ENABLED"); EXPECT_EQ(ToKeyStatusName(KeyStatus::kDisabled), "DISABLED"); EXPECT_EQ(ToKeyStatusName(KeyStatus::kDestroyed), "DESTROYED"); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/key_type_info_store.cc ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/key_type_info_store.h" #include #include #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { util::StatusOr KeyTypeInfoStore::Get( absl::string_view type_url) const { auto it = type_url_to_info_.find(type_url); if (it == type_url_to_info_.end()) { return ToStatusF(absl::StatusCode::kNotFound, "No manager for type '%s' has been registered.", type_url); } return it->second.get(); } util::Status KeyTypeInfoStore::IsInsertable( absl::string_view type_url, const std::type_index& key_manager_type_index, bool new_key_allowed) const { auto it = type_url_to_info_.find(type_url); if (it == type_url_to_info_.end()) { return crypto::tink::util::OkStatus(); } if (it->second->key_manager_type_index() != key_manager_type_index) { return ToStatusF(absl::StatusCode::kAlreadyExists, "A manager for type '%s' has been already registered.", type_url); } if (!it->second->new_key_allowed() && new_key_allowed) { return ToStatusF(absl::StatusCode::kAlreadyExists, "A manager for type '%s' has been already registered " "with forbidden new key operation.", type_url); } return util::OkStatus(); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/key_type_info_store.h ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_KEY_TYPE_INFO_STORE_H_ #define TINK_INTERNAL_KEY_TYPE_INFO_STORE_H_ #include #include #include #include #include #include #include #include "absl/container/flat_hash_map.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_join.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/core/key_manager_impl.h" #include "tink/core/key_type_manager.h" #include "tink/core/private_key_manager_impl.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/input_stream.h" #include "tink/internal/fips_utils.h" #include "tink/key_manager.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { // Stores information about key types constructed from their KeyTypeManager or // KeyManager. This is used by the Configuration and Registry classes. // // Once inserted, Info objects must remain valid for the lifetime of the // KeyTypeInfoStore object, and the Info object's pointer stability is required. // Elements in Info, which include the KeyTypeManager or KeyManager, must not // be replaced. // // Example: // KeyTypeInfoStore store; // crypto::tink::util::Status status = // store.AddKeyTypeManager(absl::make_unique(), true); // crypto::tink::util::StatusOr info = // store.Get(AesGcmKeyManager().get_key_type()); class KeyTypeInfoStore { public: KeyTypeInfoStore() = default; // Movable, but not copyable. KeyTypeInfoStore(KeyTypeInfoStore&& other) = default; KeyTypeInfoStore& operator=(KeyTypeInfoStore&& other) = default; // Information about a key type constructed from its KeyTypeManager or // KeyManager. class Info { public: // Takes ownership of `manager`. template Info(KeyTypeManager>* manager, bool new_key_allowed) : key_manager_type_index_(std::type_index(typeid(*manager))), public_key_type_manager_type_index_(absl::nullopt), new_key_allowed_(new_key_allowed), key_type_manager_(absl::WrapUnique(manager)), internal_key_factory_( absl::make_unique>>>(manager)), key_factory_(internal_key_factory_.get()), key_deriver_(CreateDeriverFunctionFor(manager)) { // TODO(C++17): Replace with a fold expression. (void)std::initializer_list{ 0, (primitive_to_manager_.emplace( std::type_index(typeid(Primitives)), internal::MakeKeyManager(manager)), 0)...}; } // Takes ownership of `private_manager`, but not of `public_manager`, which // must only be alive for the duration of the constructor. template Info(PrivateKeyTypeManager>* private_manager, KeyTypeManager* public_manager, bool new_key_allowed) : key_manager_type_index_(std::type_index(typeid(*private_manager))), public_key_type_manager_type_index_( std::type_index(typeid(*public_manager))), new_key_allowed_(new_key_allowed), key_type_manager_(absl::WrapUnique(private_manager)), internal_key_factory_( absl::make_unique, PublicPrimitivesList>>( private_manager, public_manager)), key_factory_(internal_key_factory_.get()), key_deriver_(CreateDeriverFunctionFor(private_manager)) { // TODO(C++17): Replace with a fold expression. (void)std::initializer_list{ 0, (primitive_to_manager_.emplace( std::type_index(typeid(PrivatePrimitives)), internal::MakePrivateKeyManager( private_manager, public_manager)), 0)...}; } // Takes ownership of `manager`. KeyManager is the legacy/internal version // of KeyTypeManager. template Info(KeyManager

* manager, bool new_key_allowed) : key_manager_type_index_(std::type_index(typeid(*manager))), public_key_type_manager_type_index_(absl::nullopt), new_key_allowed_(new_key_allowed), key_type_manager_(nullptr), internal_key_factory_(nullptr), key_factory_(&manager->get_key_factory()) { primitive_to_manager_.emplace(std::type_index(typeid(P)), absl::WrapUnique(manager)); } template crypto::tink::util::StatusOr> GetPrimitive( const google::crypto::tink::KeyData& key_data) const { crypto::tink::util::StatusOr*> key_manager = get_key_manager

(key_data.type_url()); if (!key_manager.ok()) { return key_manager.status(); } return (*key_manager)->GetPrimitive(key_data); } template crypto::tink::util::StatusOr*> get_key_manager( absl::string_view requested_type_url) const { auto it = primitive_to_manager_.find(std::type_index(typeid(P))); if (it == primitive_to_manager_.end()) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat( "Primitive type ", typeid(P).name(), " not among supported primitives ", absl::StrJoin( primitive_to_manager_.begin(), primitive_to_manager_.end(), ", ", [](std::string* out, const std::pair>& kv) { absl::StrAppend(out, kv.first.name()); }), " for type URL ", requested_type_url)); } return static_cast*>(it->second.get()); } const std::type_index& key_manager_type_index() const { return key_manager_type_index_; } const absl::optional& public_key_type_manager_type_index() const { return public_key_type_manager_type_index_; } bool new_key_allowed() const { return new_key_allowed_.load(); } void set_new_key_allowed(bool b) { new_key_allowed_.store(b); } const KeyFactory& key_factory() const { return *key_factory_; } const std::function(absl::string_view, InputStream*)>& key_deriver() const { return key_deriver_; } private: // Dynamic type_index of the KeyManager or KeyTypeManager for this key type. std::type_index key_manager_type_index_; // Dynamic type_index of the public KeyTypeManager for this key type when // inserted into the registry via RegisterAsymmetricKeyManagers. Otherwise, // nullopt. absl::optional public_key_type_manager_type_index_; // Whether the key manager allows the creation of new keys. std::atomic new_key_allowed_; // Map from primitive type_index to KeyManager. absl::flat_hash_map> primitive_to_manager_; // Key type manager. Equals nullptr if Info was constructed from a // KeyManager. const std::shared_ptr key_type_manager_; // Key factory. Equals nullptr if Info was constructed from a KeyManager. std::unique_ptr internal_key_factory_; // Unowned version of `internal_key_factory_` if Info was constructed from a // KeyTypeManager. Key factory belonging to the KeyManager if Info was // constructed from a KeyManager. const KeyFactory* key_factory_; // Derives a key if Info was constructed from a KeyTypeManager with a // non-void KeyFormat type. Else, this function is empty and casting to a // bool returns false. std::function( absl::string_view, InputStream*)> key_deriver_; }; // Adds a crypto::tink::KeyTypeManager to KeyTypeInfoStore. `new_key_allowed` // indicates whether `manager` may create new keys. template crypto::tink::util::Status AddKeyTypeManager( std::unique_ptr manager, bool new_key_allowed); // Adds a pair of crypto::tink::PrivateKeyTypeManager and // crypto::tink::KeyTypeManager to KeyTypeInfoStore. `new_key_allowed` // indicates whether `private_manager` may create new keys. template crypto::tink::util::Status AddAsymmetricKeyTypeManagers( std::unique_ptr private_manager, std::unique_ptr public_manager, bool new_key_allowed); // Adds a crypto::tink::KeyManager to KeyTypeInfoStore. `new_key_allowed` // indicates whether `manager` may create new keys. KeyManager is the // legacy/internal version of KeyTypeManager. template crypto::tink::util::Status AddKeyManager( std::unique_ptr> manager, bool new_key_allowed); // Gets Info associated with `type_url`, returning either a valid, non-null // Info or an error. crypto::tink::util::StatusOr Get(absl::string_view type_url) const; bool IsEmpty() const { return type_url_to_info_.empty(); } private: // Whether a key manager with `type_url` and `key_manager_type_index` can be // inserted. crypto::tink::util::Status IsInsertable( absl::string_view type_url, const std::type_index& key_manager_type_index, bool new_key_allowed) const; void Add(std::string type_url, std::unique_ptr info, bool new_key_allowed) { auto it = type_url_to_info_.find(type_url); if (it != type_url_to_info_.end()) { it->second->set_new_key_allowed(new_key_allowed); } else { type_url_to_info_.insert({type_url, std::move(info)}); } } // Map from the type_url to Info. // Elements in Info must not be replaced, and pointer stability is required // for `Get()`. absl::flat_hash_map> type_url_to_info_; }; template crypto::tink::util::Status KeyTypeInfoStore::AddKeyManager( std::unique_ptr> manager, bool new_key_allowed) { std::string type_url = manager->get_key_type(); if (!manager->DoesSupport(type_url)) { return ToStatusF(absl::StatusCode::kInvalidArgument, "The manager does not support type '%s'.", type_url); } crypto::tink::util::Status status = IsInsertable( type_url, std::type_index(typeid(*manager)), new_key_allowed); if (!status.ok()) { return status; } auto info = absl::make_unique(manager.release(), new_key_allowed); Add(type_url, std::move(info), new_key_allowed); return crypto::tink::util::OkStatus(); } template crypto::tink::util::Status KeyTypeInfoStore::AddKeyTypeManager( std::unique_ptr manager, bool new_key_allowed) { // Check FIPS status. internal::FipsCompatibility fips_compatible = manager->FipsStatus(); auto fips_status = internal::ChecksFipsCompatibility(fips_compatible); if (!fips_status.ok()) { return crypto::tink::util::Status( absl::StatusCode::kInternal, absl::StrCat("Failed registering the key manager for ", typeid(*manager).name(), " as it is not FIPS compatible: ", fips_status.message())); } std::string type_url = manager->get_key_type(); crypto::tink::util::Status status = IsInsertable( type_url, std::type_index(typeid(*manager)), new_key_allowed); if (!status.ok()) { return status; } auto info = absl::make_unique(manager.release(), new_key_allowed); Add(type_url, std::move(info), new_key_allowed); return crypto::tink::util::OkStatus(); } template crypto::tink::util::Status KeyTypeInfoStore::AddAsymmetricKeyTypeManagers( std::unique_ptr private_manager, std::unique_ptr public_manager, bool new_key_allowed) { std::string private_type_url = private_manager->get_key_type(); std::string public_type_url = public_manager->get_key_type(); if (private_type_url == public_type_url) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, "Passed in key managers must have different get_key_type() results."); } // Check FIPS status. auto private_fips_status = internal::ChecksFipsCompatibility(private_manager->FipsStatus()); if (!private_fips_status.ok()) { return crypto::tink::util::Status( absl::StatusCode::kInternal, absl::StrCat( "Failed registering the key manager for ", typeid(*private_manager).name(), " as it is not FIPS compatible: ", private_fips_status.message())); } auto public_fips_status = internal::ChecksFipsCompatibility(public_manager->FipsStatus()); if (!public_fips_status.ok()) { return crypto::tink::util::Status( absl::StatusCode::kInternal, absl::StrCat( "Failed registering the key manager for ", typeid(*public_manager).name(), " as it is not FIPS compatible: ", public_fips_status.message())); } crypto::tink::util::Status private_status = IsInsertable(private_type_url, std::type_index(typeid(*private_manager)), new_key_allowed); if (!private_status.ok()) { return private_status; } crypto::tink::util::Status public_status = IsInsertable(public_type_url, std::type_index(typeid(*public_manager)), new_key_allowed); if (!public_status.ok()) { return public_status; } util::StatusOr private_found = Get(private_type_url); util::StatusOr public_found = Get(public_type_url); // Only one of the private and public key type managers is found. if (private_found.ok() && !public_found.ok()) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat( "Private key manager corresponding to ", typeid(*private_manager).name(), " was previously registered, but key manager corresponding to ", typeid(*public_manager).name(), " was not, so it's impossible to register them jointly")); } if (!private_found.ok() && public_found.ok()) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Key manager corresponding to ", typeid(*public_manager).name(), " was previously registered, but private key manager " "corresponding to ", typeid(*private_manager).name(), " was not, so it's impossible to register them jointly")); } // Both private and public key type managers are found. if (private_found.ok() && public_found.ok()) { if (!(*private_found)->public_key_type_manager_type_index().has_value()) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("private key manager corresponding to ", typeid(*private_manager).name(), " is already registered without public key manager, " "cannot be re-registered with public key manager. ")); } if ((*private_found)->public_key_type_manager_type_index() != std::type_index(typeid(*public_manager))) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat( "private key manager corresponding to ", typeid(*private_manager).name(), " is already registered with ", (*private_found)->public_key_type_manager_type_index()->name(), ", cannot be re-registered with ", typeid(*public_manager).name())); } // Since `private_manager` passed the `IsInsertable` check above, the // `set_new_key_allowed` operation is permissible. (*private_found)->set_new_key_allowed(new_key_allowed); return crypto::tink::util::OkStatus(); } // Both private and public key type managers were not found. auto private_info = absl::make_unique( private_manager.release(), public_manager.get(), new_key_allowed); Add(private_type_url, std::move(private_info), new_key_allowed); // TODO(b/265705174): Store public key type managers in an asymmetric pair // with new_key_allowed = false. auto public_info = absl::make_unique(public_manager.release(), new_key_allowed); Add(public_type_url, std::move(public_info), new_key_allowed); return crypto::tink::util::OkStatus(); } } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_KEY_TYPE_INFO_STORE_H_ ================================================ FILE: cc/internal/key_type_info_store_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/key_type_info_store.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/aead.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/aead/cord_aead.h" #include "tink/aead/kms_envelope_aead_key_manager.h" #include "tink/core/key_manager_impl.h" #include "tink/internal/fips_utils.h" #include "tink/key_manager.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/signature/ecdsa_sign_key_manager.h" #include "tink/signature/ecdsa_verify_key_manager.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/aes_gcm.pb.h" #include "proto/common.pb.h" #include "proto/ecdsa.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::AesGcmKeyFormat; using ::google::crypto::tink::EcdsaKeyFormat; using ::google::crypto::tink::EcdsaParams; using ::google::crypto::tink::EcdsaSignatureEncoding; using ::google::crypto::tink::EllipticCurveType; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; // TODO(b/265705174): Use fake key managers to avoid relying on key manager // implementations. TEST(KeyTypeInfoStoreTest, AddKeyTypeManager) { KeyTypeInfoStore store; ASSERT_THAT(store.AddKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/true), IsOk()); std::string type_url = AesGcmKeyManager().get_key_type(); util::StatusOr info = store.Get(type_url); ASSERT_THAT(info, IsOk()); EXPECT_EQ((*info)->new_key_allowed(), true); util::StatusOr*> manager = (*info)->get_key_manager(type_url); ASSERT_THAT(manager, IsOk()); EXPECT_EQ((*manager)->get_key_type(), type_url); } TEST(KeyTypeInfoStoreTest, AddKeyTypeManagerNoBoringCrypto) { if (!kUseOnlyFips || IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only supported in FIPS-mode with BoringCrypto not available."; } KeyTypeInfoStore store; EXPECT_THAT( store.AddKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/true), StatusIs(absl::StatusCode::kInternal)); } TEST(KeyTypeInfoStoreTest, AddKeyTypeManagerAndChangeNewKeyAllowed) { KeyTypeInfoStore store; ASSERT_THAT(store.AddKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/true), IsOk()); std::string type_url = AesGcmKeyManager().get_key_type(); util::StatusOr info = store.Get(type_url); ASSERT_THAT(info, IsOk()); EXPECT_EQ((*info)->new_key_allowed(), true); // new_key_allowed true -> true is allowed. ASSERT_THAT(store.AddKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/true), IsOk()); info = store.Get(type_url); ASSERT_THAT(info, IsOk()); EXPECT_EQ((*info)->new_key_allowed(), true); // new_key_allowed true -> false is allowed. ASSERT_THAT(store.AddKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/false), IsOk()); info = store.Get(type_url); ASSERT_THAT(info, IsOk()); EXPECT_EQ((*info)->new_key_allowed(), false); // new_key_allowed false -> false is allowed. ASSERT_THAT(store.AddKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/false), IsOk()); info = store.Get(type_url); ASSERT_THAT(info, IsOk()); EXPECT_EQ((*info)->new_key_allowed(), false); // new_key_allowed false -> true is not allowed. ASSERT_THAT(store.AddKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/true), StatusIs(absl::StatusCode::kAlreadyExists)); } TEST(KeyTypeInfoStoreTest, AddAsymmetricKeyTypeManagers) { KeyTypeInfoStore store; ASSERT_THAT(store.AddAsymmetricKeyTypeManagers( absl::make_unique(), absl::make_unique(), /*new_key_allowed=*/true), IsOk()); { std::string private_type_url = EcdsaSignKeyManager().get_key_type(); util::StatusOr info = store.Get(private_type_url); ASSERT_THAT(info, IsOk()); util::StatusOr*> manager = (*info)->get_key_manager(private_type_url); ASSERT_THAT(manager, IsOk()); EXPECT_EQ((*manager)->get_key_type(), private_type_url); } { std::string public_type_url = EcdsaVerifyKeyManager().get_key_type(); util::StatusOr info = store.Get(public_type_url); ASSERT_THAT(info, IsOk()); util::StatusOr*> manager = (*info)->get_key_manager(public_type_url); ASSERT_THAT(manager, IsOk()); EXPECT_EQ((*manager)->get_key_type(), public_type_url); } } TEST(KeyTypeInfoStoreTest, AddAsymmetricKeyTypeManagersAlreadyExists) { { KeyTypeInfoStore store; ASSERT_THAT( store.AddKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/true), IsOk()); EXPECT_THAT(store.AddAsymmetricKeyTypeManagers( absl::make_unique(), absl::make_unique(), /*new_key_allowed=*/true), StatusIs(absl::StatusCode::kInvalidArgument)); } { KeyTypeInfoStore store; ASSERT_THAT( store.AddKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/true), IsOk()); EXPECT_THAT(store.AddAsymmetricKeyTypeManagers( absl::make_unique(), absl::make_unique(), /*new_key_allowed=*/true), StatusIs(absl::StatusCode::kInvalidArgument)); } { KeyTypeInfoStore store; EXPECT_THAT(store.AddAsymmetricKeyTypeManagers( absl::make_unique(), absl::make_unique(), /*new_key_allowed=*/true), IsOk()); EXPECT_THAT(store.AddAsymmetricKeyTypeManagers( absl::make_unique(), absl::make_unique(), /*new_key_allowed=*/true), IsOk()); } } TEST(KeyTypeInfoStoreTest, AddAsymmetricKeyTypeManagersAndChangeNewKeyAllowed) { KeyTypeInfoStore store; ASSERT_THAT(store.AddAsymmetricKeyTypeManagers( absl::make_unique(), absl::make_unique(), /*new_key_allowed=*/true), IsOk()); std::string private_type_url = EcdsaSignKeyManager().get_key_type(); std::string public_type_url = EcdsaVerifyKeyManager().get_key_type(); util::StatusOr private_info = store.Get(private_type_url); ASSERT_THAT(private_info, IsOk()); EXPECT_EQ((*private_info)->new_key_allowed(), true); util::StatusOr public_info = store.Get(public_type_url); ASSERT_THAT(public_info, IsOk()); EXPECT_EQ((*public_info)->new_key_allowed(), true); // new_key_allowed true -> true is allowed. ASSERT_THAT(store.AddAsymmetricKeyTypeManagers( absl::make_unique(), absl::make_unique(), /*new_key_allowed=*/true), IsOk()); private_info = store.Get(private_type_url); ASSERT_THAT(private_info, IsOk()); EXPECT_EQ((*private_info)->new_key_allowed(), true); public_info = store.Get(public_type_url); ASSERT_THAT(public_info, IsOk()); EXPECT_EQ((*public_info)->new_key_allowed(), true); // new_key_allowed true -> false is allowed. ASSERT_THAT(store.AddAsymmetricKeyTypeManagers( absl::make_unique(), absl::make_unique(), /*new_key_allowed=*/false), IsOk()); private_info = store.Get(private_type_url); ASSERT_THAT(private_info, IsOk()); EXPECT_EQ((*private_info)->new_key_allowed(), false); public_info = store.Get(public_type_url); ASSERT_THAT(public_info, IsOk()); EXPECT_EQ((*public_info)->new_key_allowed(), true); // new_key_allowed false -> false is allowed. ASSERT_THAT(store.AddAsymmetricKeyTypeManagers( absl::make_unique(), absl::make_unique(), /*new_key_allowed=*/false), IsOk()); private_info = store.Get(private_type_url); ASSERT_THAT(private_info, IsOk()); EXPECT_EQ((*private_info)->new_key_allowed(), false); public_info = store.Get(public_type_url); ASSERT_THAT(public_info, IsOk()); EXPECT_EQ((*public_info)->new_key_allowed(), true); // new_key_allowed false -> true is not allowed. ASSERT_THAT(store.AddAsymmetricKeyTypeManagers( absl::make_unique(), absl::make_unique(), /*new_key_allowed=*/true), StatusIs(absl::StatusCode::kAlreadyExists)); } TEST(KeyTypeInfoStoreTest, AddKeyManager) { KeyTypeInfoStore store; AesGcmKeyManager manager; ASSERT_THAT(store.AddKeyManager(MakeKeyManager(&manager), /*new_key_allowed=*/true), IsOk()); std::string type_url = manager.get_key_type(); util::StatusOr info = store.Get(type_url); ASSERT_THAT(info, IsOk()); util::StatusOr*> got_manager = (*info)->get_key_manager(type_url); ASSERT_THAT(got_manager, IsOk()); EXPECT_EQ((*got_manager)->get_key_type(), type_url); } TEST(KeyTypeInfoStoreTest, AddKeyManagerAndChangeNewKeyAllowed) { KeyTypeInfoStore store; AesGcmKeyManager manager; ASSERT_THAT(store.AddKeyManager(MakeKeyManager(&manager), /*new_key_allowed=*/true), IsOk()); std::string type_url = manager.get_key_type(); util::StatusOr info = store.Get(type_url); ASSERT_THAT(info, IsOk()); EXPECT_EQ((*info)->new_key_allowed(), true); // new_key_allowed true -> true is allowed. ASSERT_THAT(store.AddKeyManager(MakeKeyManager(&manager), /*new_key_allowed=*/true), IsOk()); info = store.Get(type_url); ASSERT_THAT(info, IsOk()); EXPECT_EQ((*info)->new_key_allowed(), true); // new_key_allowed true -> false is allowed. ASSERT_THAT(store.AddKeyManager(MakeKeyManager(&manager), /*new_key_allowed=*/false), IsOk()); info = store.Get(type_url); ASSERT_THAT(info, IsOk()); EXPECT_EQ((*info)->new_key_allowed(), false); // new_key_allowed false -> false is allowed. ASSERT_THAT(store.AddKeyManager(MakeKeyManager(&manager), /*new_key_allowed=*/false), IsOk()); info = store.Get(type_url); ASSERT_THAT(info, IsOk()); EXPECT_EQ((*info)->new_key_allowed(), false); // new_key_allowed false -> true is not allowed. ASSERT_THAT(store.AddKeyManager(MakeKeyManager(&manager), /*new_key_allowed=*/true), StatusIs(absl::StatusCode::kAlreadyExists)); } TEST(KeyTypeInfoStoreTest, Get) { KeyTypeInfoStore store; ASSERT_THAT(store.AddKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/true), IsOk()); util::StatusOr info = store.Get(AesGcmKeyManager().get_key_type()); EXPECT_THAT(info, IsOk()); EXPECT_THAT(store.Get("nonexistent.type.url").status(), StatusIs(absl::StatusCode::kNotFound)); } TEST(KeyTypeInfoStoreTest, IsEmpty) { KeyTypeInfoStore store; EXPECT_EQ(store.IsEmpty(), true); ASSERT_THAT(store.AddKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/true), IsOk()); EXPECT_THAT(store.IsEmpty(), false); } TEST(KeyTypeInfoStoreInfoTest, KeyTypeManager) { KeyTypeInfoStore::Info info(absl::make_unique().release(), /*new_key_allowed=*/false); EXPECT_EQ(info.key_manager_type_index(), std::type_index(typeid(AesGcmKeyManager))); EXPECT_EQ(info.public_key_type_manager_type_index(), absl::nullopt); EXPECT_EQ(info.new_key_allowed(), false); info.set_new_key_allowed(true); EXPECT_EQ(info.new_key_allowed(), true); std::string type_url = AesGcmKeyManager().get_key_type(); util::StatusOr*> aead_manager = info.get_key_manager(type_url); ASSERT_THAT(aead_manager, IsOk()); EXPECT_EQ((*aead_manager)->DoesSupport(type_url), true); util::StatusOr*> cord_aead_manager = info.get_key_manager(type_url); ASSERT_THAT(aead_manager, IsOk()); EXPECT_EQ((*aead_manager)->DoesSupport(type_url), true); AesGcmKeyFormat format; format.set_key_size(32); EXPECT_THAT(info.key_factory().NewKeyData(format.SerializeAsString()), IsOk()); EXPECT_EQ((bool)info.key_deriver(), true); } TEST(KeyTypeInfoStoreInfoTest, AsymmetricKeyTypeManagers) { KeyTypeInfoStore::Info info( absl::make_unique().release(), absl::make_unique().get(), /*new_key_allowed=*/false); EXPECT_EQ(info.key_manager_type_index(), std::type_index(typeid(EcdsaSignKeyManager))); EXPECT_EQ(info.public_key_type_manager_type_index(), std::type_index(typeid(EcdsaVerifyKeyManager))); EXPECT_EQ(info.new_key_allowed(), false); info.set_new_key_allowed(true); EXPECT_EQ(info.new_key_allowed(), true); std::string type_url = EcdsaSignKeyManager().get_key_type(); util::StatusOr*> manager = info.get_key_manager(type_url); ASSERT_THAT(manager, IsOk()); EXPECT_EQ((*manager)->DoesSupport(type_url), true); EcdsaKeyFormat format; EcdsaParams* params = format.mutable_params(); params->set_hash_type(HashType::SHA256); params->set_curve(EllipticCurveType::NIST_P256); params->set_encoding(EcdsaSignatureEncoding::DER); EXPECT_THAT(info.key_factory().NewKeyData(format.SerializeAsString()), IsOk()); EXPECT_EQ((bool)info.key_deriver(), true); } TEST(KeyTypeInfoStoreInfoTest, KeyManager) { AesGcmKeyManager key_type_manager; std::unique_ptr> manager = MakeKeyManager(&key_type_manager); std::type_index type_index = std::type_index(typeid(*manager)); KeyTypeInfoStore::Info info(manager.release(), /*new_key_allowed=*/false); EXPECT_EQ(info.key_manager_type_index(), type_index); EXPECT_EQ(info.public_key_type_manager_type_index(), absl::nullopt); EXPECT_EQ(info.new_key_allowed(), false); info.set_new_key_allowed(true); EXPECT_EQ(info.new_key_allowed(), true); std::string type_url = AesGcmKeyManager().get_key_type(); util::StatusOr*> got_manager = info.get_key_manager(type_url); ASSERT_THAT(got_manager, IsOk()); EXPECT_EQ((*got_manager)->DoesSupport(type_url), true); // Inserted KeyManager only supports Aead, not CordAead. EXPECT_THAT(info.get_key_manager(type_url).status(), StatusIs(absl::StatusCode::kInvalidArgument)); AesGcmKeyFormat format; format.set_key_size(32); EXPECT_THAT(info.key_factory().NewKeyData(format.SerializeAsString()), IsOk()); EXPECT_EQ((bool)info.key_deriver(), false); } TEST(KeyTypeInfoStoreInfoTest, GetPrimitive) { KeyTypeInfoStore::Info info(absl::make_unique().release(), /*new_key_allowed=*/false); AesGcmKeyFormat format; format.set_key_size(32); util::StatusOr> key_data = info.key_factory().NewKeyData(format.SerializeAsString()); ASSERT_THAT(key_data, IsOk()); util::StatusOr> aead = info.GetPrimitive(**key_data); ASSERT_THAT(aead, IsOk()); util::StatusOr ciphertext = (*aead)->Encrypt("plaintext", "ad"); ASSERT_THAT(ciphertext, IsOk()); EXPECT_THAT((*aead)->Decrypt(*ciphertext, "ad"), IsOk()); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/keyset_handle_builder_entry.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/keyset_handle_builder_entry.h" #include #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/key_status_util.h" #include "tink/internal/legacy_proto_key.h" #include "tink/internal/legacy_proto_parameters.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/registry.h" #include "tink/restricted_data.h" #include "tink/secret_key_access_token.h" #include "tink/util/secret_proto.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::util::SecretProto; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::Keyset; using ::google::crypto::tink::KeyStatusType; SecretProto ToKeysetKey( int id, KeyStatusType status, const ProtoKeySerialization& serialization) { SecretProto key; key->set_status(status); key->set_key_id(id); key->set_output_prefix_type(serialization.GetOutputPrefixType()); KeyData* key_data = key->mutable_key_data(); key_data->set_type_url(std::string(serialization.TypeUrl())); key_data->set_value(serialization.SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())); key_data->set_key_material_type(serialization.KeyMaterialType()); return key; } util::StatusOr SerializeParameters( const Parameters& params) { util::StatusOr> serialization = MutableSerializationRegistry::GlobalInstance() .SerializeParameters(params); if (!serialization.ok()) return serialization.status(); const ProtoParametersSerialization* proto_serialization = dynamic_cast(serialization->get()); if (proto_serialization == nullptr) { return util::Status(absl::StatusCode::kInternal, "Failed to serialize proto parameters."); } return *proto_serialization; } util::StatusOr SerializeLegacyParameters( const Parameters* params) { const LegacyProtoParameters* proto_params = dynamic_cast(params); if (proto_params == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to serialize legacy proto parameters."); } return proto_params->Serialization(); } util::StatusOr SerializeKey(const Key& key) { util::StatusOr> serialization = MutableSerializationRegistry::GlobalInstance() .SerializeKey(key, InsecureSecretKeyAccess::Get()); if (!serialization.ok()) return serialization.status(); const ProtoKeySerialization* serialized_proto_key = dynamic_cast(serialization->get()); if (serialized_proto_key == nullptr) { return util::Status(absl::StatusCode::kInternal, "Failed to serialize proto key."); } return *serialized_proto_key; } util::StatusOr SerializeLegacyKey(const Key* key) { const LegacyProtoKey* proto_key = dynamic_cast(key); if (proto_key == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to serialize legacy proto key."); } util::StatusOr serialized_key = proto_key->Serialization(InsecureSecretKeyAccess::Get()); if (!serialized_key.ok()) return serialized_key.status(); return **serialized_key; } util::StatusOr> CreateKeysetKeyFromProtoParametersSerialization( const ProtoParametersSerialization& serialization, int id, KeyStatusType status) { // TODO(tholenst): ensure this doesn't leak. util::StatusOr> key_data = Registry::NewKeyData(serialization.GetKeyTemplate()); if (!key_data.ok()) return key_data.status(); SecretProto key; key->set_status(status); key->set_key_id(id); key->set_output_prefix_type( serialization.GetKeyTemplate().output_prefix_type()); *key->mutable_key_data() = **key_data; return key; } util::StatusOr> CreateKeysetKeyFromProtoKeySerialization(const ProtoKeySerialization& key, int id, KeyStatusType status) { absl::optional id_requirement = key.IdRequirement(); if (id_requirement.has_value() && *id_requirement != id) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong ID set for key with ID requirement."); } return ToKeysetKey(id, status, key); } } // namespace void KeysetHandleBuilderEntry::SetFixedId(int id) { strategy_.strategy = KeyIdStrategyEnum::kFixedId; strategy_.id_requirement = id; } void KeysetHandleBuilderEntry::SetRandomId() { strategy_.strategy = KeyIdStrategyEnum::kRandomId; strategy_.id_requirement = absl::nullopt; } util::StatusOr> KeyEntry::CreateKeysetKey(int id) { util::StatusOr key_status = ToKeyStatusType(key_status_); if (!key_status.ok()) return key_status.status(); if (GetKeyIdRequirement().has_value() && GetKeyIdRequirement() != id) { return util::Status(absl::StatusCode::kInvalidArgument, "Requested id does not match id requirement."); } util::StatusOr serialization = SerializeKey(*key_); if (!serialization.ok() && serialization.status().code() != absl::StatusCode::kNotFound) { return serialization.status(); } if (serialization.status().code() == absl::StatusCode::kNotFound) { // Fallback to legacy proto key. serialization = SerializeLegacyKey(key_.get()); if (!serialization.ok()) return serialization.status(); } return CreateKeysetKeyFromProtoKeySerialization(*serialization, id, *key_status); } util::StatusOr> ParametersEntry::CreateKeysetKey( int id) { util::StatusOr key_status = ToKeyStatusType(key_status_); if (!key_status.ok()) return key_status.status(); if (GetKeyIdRequirement().has_value() && GetKeyIdRequirement() != id) { return util::Status(absl::StatusCode::kInvalidArgument, "Requested id does not match id requirement."); } util::StatusOr serialization = SerializeParameters(*parameters_); if (!serialization.ok() && serialization.status().code() != absl::StatusCode::kNotFound) { return serialization.status(); } if (serialization.status().code() == absl::StatusCode::kNotFound) { // Fallback to legacy proto parameters. serialization = SerializeLegacyParameters(parameters_.get()); if (!serialization.ok()) return serialization.status(); } return CreateKeysetKeyFromProtoParametersSerialization(*serialization, id, *key_status); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/keyset_handle_builder_entry.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_KEYSET_HANDLE_BUILDER_ENTRY_H_ #define TINK_INTERNAL_KEYSET_HANDLE_BUILDER_ENTRY_H_ #include #include #include "absl/types/optional.h" #include "tink/key.h" #include "tink/key_status.h" #include "tink/parameters.h" #include "tink/util/secret_proto.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { enum class KeyIdStrategyEnum : int { kFixedId = 1, kRandomId = 2, // Added to guard from failures that may be caused by future expansions. kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; struct KeyIdStrategy { KeyIdStrategyEnum strategy; absl::optional id_requirement; }; // Internal keyset handle builder entry. The public keyset handle builder // entry will delegate its method calls to an instance of this class. class KeysetHandleBuilderEntry { public: KeysetHandleBuilderEntry() = default; virtual ~KeysetHandleBuilderEntry() = default; // Sets the key `status` of this entry. void SetStatus(KeyStatus status) { key_status_ = status; } // Returns key status of this entry. KeyStatus GetStatus() const { return key_status_; } // Assigns a fixed `id` when this keyset is built. void SetFixedId(int id); // Assigns an unused random id when this keyset is built. void SetRandomId(); // Sets this entry as the primary key. void SetPrimary() { is_primary_ = true; } // Unsets this entry as the primary key. void UnsetPrimary() { is_primary_ = false; } // Returns whether or not this entry has been marked as a primary. bool IsPrimary() const { return is_primary_; } // Returns key id strategy. KeyIdStrategy GetKeyIdStrategy() { return strategy_; } // Returns key id strategy enum. KeyIdStrategyEnum GetKeyIdStrategyEnum() { return strategy_.strategy; } // Returns key id requirement. absl::optional GetKeyIdRequirement() { return strategy_.id_requirement; } // Creates a Keyset::Key proto with the specified key `id` from either a // `Key` object or a `Parameters` object. virtual crypto::tink::util::StatusOr< crypto::tink::util::SecretProto> CreateKeysetKey(int id) = 0; protected: KeyStatus key_status_ = KeyStatus::kDisabled; private: bool is_primary_ = false; KeyIdStrategy strategy_ = KeyIdStrategy{KeyIdStrategyEnum::kRandomId, absl::nullopt}; }; // Internal keyset handle builder entry constructed from a `Key` object. class KeyEntry : public KeysetHandleBuilderEntry { public: // Movable, but not copyable. KeyEntry(KeyEntry&& other) = default; KeyEntry& operator=(KeyEntry&& other) = default; KeyEntry(const KeyEntry& other) = delete; KeyEntry& operator=(const KeyEntry& other) = delete; explicit KeyEntry(std::shared_ptr key) : key_(std::move(key)) {} crypto::tink::util::StatusOr< crypto::tink::util::SecretProto> CreateKeysetKey(int id) override; private: std::shared_ptr key_; }; // Internal keyset handle builder entry constructed from a `Parameters` object. class ParametersEntry : public KeysetHandleBuilderEntry { public: // Movable, but not copyable. ParametersEntry(ParametersEntry&& other) = default; ParametersEntry& operator=(ParametersEntry&& other) = default; ParametersEntry(const ParametersEntry& other) = delete; ParametersEntry& operator=(const ParametersEntry& other) = delete; explicit ParametersEntry(std::shared_ptr parameters) : parameters_(std::move(parameters)) {} crypto::tink::util::StatusOr< crypto::tink::util::SecretProto> CreateKeysetKey(int id) override; private: std::shared_ptr parameters_; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_KEYSET_HANDLE_BUILDER_ENTRY_H_ ================================================ FILE: cc/internal/keyset_handle_builder_entry_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/keyset_handle_builder_entry.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/config/tink_config.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/legacy_proto_key.h" #include "tink/internal/legacy_proto_parameters.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/key.h" #include "tink/key_status.h" #include "tink/keyset_handle.h" #include "tink/keyset_handle_builder.h" #include "tink/mac/aes_cmac_key.h" #include "tink/mac/aes_cmac_parameters.h" #include "tink/mac/mac_key_templates.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/secret_key_access_token.h" #include "tink/util/secret_proto.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::Keyset; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::IsFalse; using ::testing::IsTrue; using ::testing::Test; util::StatusOr CreateLegacyProtoParameters() { util::StatusOr serialization = ProtoParametersSerialization::Create(MacKeyTemplates::AesCmac()); if (!serialization.ok()) return serialization.status(); return LegacyProtoParameters(*serialization); } TEST(KeysetHandleBuilderEntryTest, Status) { util::StatusOr parameters = CreateLegacyProtoParameters(); ASSERT_THAT(parameters, IsOk()); ParametersEntry entry = ParametersEntry(absl::make_unique(*parameters)); entry.SetStatus(KeyStatus::kEnabled); EXPECT_THAT(entry.GetStatus(), KeyStatus::kEnabled); entry.SetStatus(KeyStatus::kDisabled); EXPECT_THAT(entry.GetStatus(), KeyStatus::kDisabled); entry.SetStatus(KeyStatus::kDestroyed); EXPECT_THAT(entry.GetStatus(), KeyStatus::kDestroyed); } TEST(KeysetHandleBuilderEntryTest, IdStrategy) { util::StatusOr parameters = CreateLegacyProtoParameters(); ASSERT_THAT(parameters, IsOk()); ParametersEntry entry = ParametersEntry(absl::make_unique(*parameters)); entry.SetFixedId(123); EXPECT_THAT(entry.GetKeyIdStrategyEnum(), KeyIdStrategyEnum::kFixedId); EXPECT_THAT(entry.GetKeyIdStrategy().strategy, KeyIdStrategyEnum::kFixedId); EXPECT_THAT(entry.GetKeyIdStrategy().id_requirement, 123); EXPECT_THAT(entry.GetKeyIdRequirement(), 123); entry.SetRandomId(); EXPECT_THAT(entry.GetKeyIdStrategyEnum(), KeyIdStrategyEnum::kRandomId); EXPECT_THAT(entry.GetKeyIdStrategy().strategy, KeyIdStrategyEnum::kRandomId); EXPECT_THAT(entry.GetKeyIdStrategy().id_requirement, absl::nullopt); EXPECT_THAT(entry.GetKeyIdRequirement(), absl::nullopt); } TEST(KeysetHandleBuilderEntryTest, Primary) { util::StatusOr parameters = CreateLegacyProtoParameters(); ASSERT_THAT(parameters, IsOk()); ParametersEntry entry = ParametersEntry(absl::make_unique(*parameters)); entry.SetPrimary(); EXPECT_THAT(entry.IsPrimary(), IsTrue()); entry.UnsetPrimary(); EXPECT_THAT(entry.IsPrimary(), IsFalse()); } class CreateKeysetKeyTest : public Test { protected: void SetUp() override { ASSERT_THAT(TinkConfig::Register(), IsOk()); } }; TEST_F(CreateKeysetKeyTest, CreateKeysetKeyFromParameters) { util::StatusOr parameters = CreateLegacyProtoParameters(); ASSERT_THAT(parameters, IsOk()); ParametersEntry entry = ParametersEntry(absl::make_unique(*parameters)); entry.SetStatus(KeyStatus::kEnabled); entry.SetFixedId(123); util::StatusOr> keyset_key = entry.CreateKeysetKey(/*id=*/123); ASSERT_THAT(keyset_key, IsOk()); EXPECT_THAT((*keyset_key)->status(), Eq(KeyStatusType::ENABLED)); EXPECT_THAT((*keyset_key)->key_id(), Eq(123)); EXPECT_THAT( (*keyset_key)->output_prefix_type(), Eq(parameters->Serialization().GetKeyTemplate().output_prefix_type())); EXPECT_THAT((*keyset_key)->key_data().type_url(), Eq(parameters->Serialization().GetKeyTemplate().type_url())); } TEST_F(CreateKeysetKeyTest, CreateKeysetKeyFromParametersWithDifferentKeyId) { util::StatusOr parameters = CreateLegacyProtoParameters(); ASSERT_THAT(parameters, IsOk()); ParametersEntry entry = ParametersEntry(absl::make_unique(*parameters)); entry.SetStatus(KeyStatus::kEnabled); entry.SetFixedId(123); util::StatusOr> keyset_key = entry.CreateKeysetKey(/*id=*/456); EXPECT_THAT(keyset_key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(CreateKeysetKeyTest, CreateKeysetKeyFromKey) { RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/123); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr key = LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key.status(), IsOk()); KeyEntry entry = KeyEntry(absl::make_unique(*key)); entry.SetStatus(KeyStatus::kEnabled); entry.SetFixedId(123); util::StatusOr> keyset_key = entry.CreateKeysetKey(/*id=*/123); ASSERT_THAT(keyset_key, IsOk()); EXPECT_THAT((*keyset_key)->status(), Eq(KeyStatusType::ENABLED)); EXPECT_THAT((*keyset_key)->key_id(), Eq(123)); EXPECT_THAT((*keyset_key)->output_prefix_type(), OutputPrefixType::TINK); EXPECT_THAT((*keyset_key)->key_data().type_url(), Eq("type_url")); EXPECT_THAT((*keyset_key)->key_data().key_material_type(), Eq(KeyData::SYMMETRIC)); EXPECT_THAT((*keyset_key)->key_data().value(), Eq("serialized_key")); } TEST_F(CreateKeysetKeyTest, CreateKeysetKeyFromKeyWithDifferentEntryKeyId) { RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/123); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr key = LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key.status(), IsOk()); KeyEntry entry = KeyEntry(absl::make_unique(*key)); entry.SetStatus(KeyStatus::kEnabled); entry.SetFixedId(123); util::StatusOr> keyset_key = entry.CreateKeysetKey(/*id=*/456); EXPECT_THAT(keyset_key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(CreateKeysetKeyTest, CreateKeysetKeyFromKeyWithDifferentSerializationKeyId) { RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/123); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr key = LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key.status(), IsOk()); KeyEntry entry = KeyEntry(absl::make_unique(*key)); entry.SetStatus(KeyStatus::kEnabled); util::StatusOr> keyset_key = entry.CreateKeysetKey(/*id=*/456); EXPECT_THAT(keyset_key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(CreateKeysetKeyTest, CreateKeysetFromNonLegacyParameters) { util::StatusOr aes_cmac_parameters = AesCmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/10, AesCmacParameters::Variant::kTink); ASSERT_THAT(aes_cmac_parameters, IsOk()); util::StatusOr handle = KeysetHandleBuilder() .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams( *aes_cmac_parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/123)) .Build(); ASSERT_THAT(handle, IsOk()); } TEST_F(CreateKeysetKeyTest, CreateKeysetWithAllowedParametersProhibitedByKeyManager) { util::StatusOr aes_cmac_parameters = AesCmacParameters::Create(/*key_size_in_bytes=*/16, /*cryptographic_tag_size_in_bytes=*/10, AesCmacParameters::Variant::kTink); ASSERT_THAT(aes_cmac_parameters, IsOk()); util::StatusOr handle = KeysetHandleBuilder() .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams( *aes_cmac_parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/123)) .Build(); ASSERT_THAT(handle.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(CreateKeysetKeyTest, CreateKeysetFromNonLegacyKey) { util::StatusOr aes_cmac_parameters = AesCmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/10, AesCmacParameters::Variant::kTink); ASSERT_THAT(aes_cmac_parameters, IsOk()); util::StatusOr aes_cmac_key = AesCmacKey::Create( *aes_cmac_parameters, RestrictedData(32), 123, GetPartialKeyAccess()); ASSERT_THAT(aes_cmac_key.status(), IsOk()); util::StatusOr handle = KeysetHandleBuilder() .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableKey( *aes_cmac_key, KeyStatus::kEnabled, /*is_primary=*/true)) .Build(); ASSERT_THAT(handle, IsOk()); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/keyset_wrapper.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_KEYSET_WRAPPER_H_ #define TINK_INTERNAL_KEYSET_WRAPPER_H_ #include #include #include "absl/container/flat_hash_map.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { // A Keyset wrapper wraps a Tink Keyset into a set of primitives. This is a // Tink internal object, which is created from a PrimitiveWrapper. // // The KeysetWrapper is used because the only moment during compilation in which // the registry knows the input primitive type of a PrimitiveWrapper is // when RegisterPrimitiveWrapper(transforming_wrapper) is called. (There, the // compiler infers the template arguments. This means that all the work which // handles Q needs to be done in that compilation unit, and when creating the // primitive we cannot refer to Q. // // Hence, when registering the object, we first use type erasure to forget about // Q and create a subclass (KeysetWrapperImpl) of this object. template class KeysetWrapper { public: virtual ~KeysetWrapper() = default; // Wraps a given `keyset` with annotations `annotations`. virtual crypto::tink::util::StatusOr> Wrap( const google::crypto::tink::Keyset& keyset, const absl::flat_hash_map& annotations) const = 0; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_KEYSET_WRAPPER_H_ ================================================ FILE: cc/internal/keyset_wrapper_impl.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_KEYSET_WRAPPER_IMPL_H_ #define TINK_INTERNAL_KEYSET_WRAPPER_IMPL_H_ #include #include #include #include "absl/container/flat_hash_map.h" #include "absl/functional/any_invocable.h" #include "tink/internal/key_info.h" #include "tink/internal/keyset_wrapper.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { template class KeysetWrapperImpl : public KeysetWrapper { public: // We allow injection of a function creating the P primitive from KeyData for // testing -- later, this function will just be Registry::GetPrimitive(). explicit KeysetWrapperImpl( const PrimitiveWrapper* transforming_wrapper, absl::AnyInvocable>( const google::crypto::tink::KeyData& key_data) const> primitive_getter) : primitive_getter_(std::move(primitive_getter)), transforming_wrapper_(*transforming_wrapper) {} crypto::tink::util::StatusOr> Wrap( const google::crypto::tink::Keyset& keyset, const absl::flat_hash_map& annotations) const override { crypto::tink::util::Status status = ValidateKeyset(keyset); if (!status.ok()) return status; typename PrimitiveSet

::Builder primitives_builder; primitives_builder.AddAnnotations(annotations); for (const google::crypto::tink::Keyset::Key& key : keyset.key()) { if (key.status() != google::crypto::tink::KeyStatusType::ENABLED) { continue; } auto primitive = primitive_getter_(key.key_data()); if (!primitive.ok()) return primitive.status(); if (key.key_id() == keyset.primary_key_id()) { primitives_builder.AddPrimaryPrimitive(std::move(primitive.value()), KeyInfoFromKey(key)); } else { primitives_builder.AddPrimitive(std::move(primitive.value()), KeyInfoFromKey(key)); } } crypto::tink::util::StatusOr> primitives = std::move(primitives_builder).Build(); if (!primitives.ok()) return primitives.status(); return transforming_wrapper_.Wrap( absl::make_unique>(*std::move(primitives))); } private: absl::AnyInvocable>( const google::crypto::tink::KeyData& key_data) const> primitive_getter_; const PrimitiveWrapper& transforming_wrapper_; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_KEYSET_WRAPPER_IMPL_H_ ================================================ FILE: cc/internal/keyset_wrapper_impl_test.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/keyset_wrapper_impl.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_map.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/match.h" #include "absl/strings/string_view.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::AddKeyData; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::google::crypto::tink::Keyset; using ::testing::HasSubstr; using ::testing::Not; using ::testing::Pair; using ::testing::Pointee; using ::testing::UnorderedElementsAre; using InputPrimitive = std::string; using OutputPrimitive = std::vector>; // This "Wrapper" wraps primitives of type std::string into primitives of type // std::vector simply by returning pairs {key_id, string}. // It appends " (primary)" to the string for the primary id. class Wrapper : public PrimitiveWrapper { public: crypto::tink::util::StatusOr> Wrap( std::unique_ptr> primitive_set) const override { auto result = absl::make_unique(); for (const auto* entry : primitive_set->get_all()) { (*result).push_back( std::make_pair(entry->get_key_id(), entry->get_primitive())); if (entry->get_key_id() == primitive_set->get_primary()->get_key_id()) { result->back().second.append(" (primary)"); } } return std::move(result); } }; crypto::tink::util::StatusOr> CreateIn( const google::crypto::tink::KeyData& key_data) { if (absl::StartsWith(key_data.type_url(), "error:")) { return crypto::tink::util::Status(absl::StatusCode::kInvalidArgument, key_data.type_url()); } else { return absl::make_unique(key_data.type_url()); } } google::crypto::tink::KeyData OnlyTypeUrlKeyData(absl::string_view type_url) { google::crypto::tink::KeyData result; result.set_type_url(std::string(type_url)); return result; } google::crypto::tink::Keyset CreateKeyset( const std::vector>& keydata) { google::crypto::tink::Keyset keyset; for (const auto& pair : keydata) { AddKeyData(OnlyTypeUrlKeyData(pair.second), pair.first, google::crypto::tink::OutputPrefixType::TINK, google::crypto::tink::KeyStatusType::ENABLED, &keyset); } return keyset; } TEST(KeysetWrapperImplTest, Basic) { Wrapper wrapper; auto wrapper_or = absl::make_unique>( &wrapper, &CreateIn); std::vector> keydata = { {111, "one"}, {222, "two"}, {333, "three"}}; google::crypto::tink::Keyset keyset = CreateKeyset(keydata); keyset.set_primary_key_id(222); util::StatusOr> wrapped = wrapper_or->Wrap(keyset, /*annotations=*/{}); ASSERT_THAT(wrapped, IsOk()); ASSERT_THAT(*wrapped.value(), UnorderedElementsAre(Pair(111, "one"), Pair(222, "two (primary)"), Pair(333, "three"))); } TEST(KeysetWrapperImplTest, FailingGetPrimitive) { Wrapper wrapper; auto wrapper_or = absl::make_unique>( &wrapper, &CreateIn); std::vector> keydata = {{1, "ok:one"}, {2, "error:two"}}; google::crypto::tink::Keyset keyset = CreateKeyset(keydata); keyset.set_primary_key_id(1); util::StatusOr> wrapped = wrapper_or->Wrap(keyset, /*annotations=*/{}); ASSERT_THAT(wrapped, Not(IsOk())); ASSERT_THAT(std::string(wrapped.status().message()), HasSubstr("error:two")); } // This test checks that validate keyset is called. We simply pass an empty // keyset. TEST(KeysetWrapperImplTest, ValidatesKeyset) { Wrapper wrapper; auto wrapper_or = absl::make_unique>( &wrapper, &CreateIn); util::StatusOr> wrapped = wrapper_or->Wrap(google::crypto::tink::Keyset(), /*annotations=*/{}); ASSERT_THAT(wrapped, Not(IsOk())); } // This test checks that only enabled keys are used to create the primitive set. TEST(KeysetWrapperImplTest, OnlyEnabled) { Wrapper wrapper; auto wrapper_or = absl::make_unique>( &wrapper, &CreateIn); std::vector> keydata = { {111, "one"}, {222, "two"}, {333, "three"}, {444, "four"}}; google::crypto::tink::Keyset keyset = CreateKeyset(keydata); keyset.set_primary_key_id(222); // KeyId 333 is index 2. keyset.mutable_key(2)->set_status(google::crypto::tink::DISABLED); util::StatusOr> wrapped = wrapper_or->Wrap(keyset, /*annotations=*/{}); ASSERT_THAT(wrapped, IsOk()); ASSERT_THAT(*wrapped.value(), UnorderedElementsAre(Pair(111, "one"), Pair(222, "two (primary)"), Pair(444, "four"))); } // Mock PrimitiveWrapper with input primitive I and output primitive O. template class MockWrapper : public PrimitiveWrapper { public: MOCK_METHOD(util::StatusOr>, Wrap, (std::unique_ptr> primitive_set), (const, override)); }; // Returns a valid output primitive. std::unique_ptr GetOutputPrimitiveForTesting() { auto output_primitive = absl::make_unique(); output_primitive->push_back({111, "one"}); output_primitive->push_back({222, "two (primary)"}); output_primitive->push_back({333, "three"}); output_primitive->push_back({444, "four"}); return output_primitive; } // Tests that annotations are correctly passed on to the generated PrimitiveSet. TEST(KeysetWrapperImplTest, WrapWithAnnotationCorrectlyWrittenToPrimitiveSet) { MockWrapper wrapper; auto keyset_wrapper = absl::make_unique>( &wrapper, CreateIn); Keyset keyset = CreateKeyset( /*keydata=*/{{111, "one"}, {222, "two"}, {333, "three"}, {444, "four"}}); keyset.set_primary_key_id(222); const absl::flat_hash_map kExpectedAnnotations = { {"key1", "value1"}, {"key2", "value2"}}; absl::flat_hash_map generated_annotations; EXPECT_CALL(wrapper, Wrap(testing::_)) .WillOnce( [&generated_annotations](std::unique_ptr> generated_primitive_set) { // We are interested to check if the annotations are what we // expected, so we copy them to `generated_annotations`. generated_annotations = generated_primitive_set->get_annotations(); // Return a valid output primitive. return GetOutputPrimitiveForTesting(); }); util::StatusOr> wrapped_primitive = keyset_wrapper->Wrap(keyset, kExpectedAnnotations); EXPECT_EQ(generated_annotations, kExpectedAnnotations); EXPECT_THAT(wrapped_primitive, IsOkAndHolds(Pointee(UnorderedElementsAre( Pair(111, "one"), Pair(222, "two (primary)"), Pair(333, "three"), Pair(444, "four"))))); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/keyset_wrapper_store.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_KEYSET_WRAPPER_STORE_H_ #define TINK_INTERNAL_KEYSET_WRAPPER_STORE_H_ #include #include #include #include "absl/container/flat_hash_map.h" #include "absl/functional/any_invocable.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/internal/keyset_wrapper.h" #include "tink/internal/keyset_wrapper_impl.h" #include "tink/primitive_wrapper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { // Stores KeysetWrappers constructed from their PrimitiveWrapper. This is used // by the Configuration and Registry classes. // // Once inserted, elements in Info, which include the PrimitiveWrapper, must not // be replaced. // // Example: // KeysetWrapperStore store; // crypto::tink::util::Status status = store.Add( // absl::make_unique(), std::move(primitive_getter)); // crypto::tink::util::StatusOr*> wrapper = // store.Get(); class KeysetWrapperStore { public: KeysetWrapperStore() = default; // Movable, but not copyable. KeysetWrapperStore(KeysetWrapperStore&& other) = default; KeysetWrapperStore& operator=(KeysetWrapperStore&& other) = default; // Adds a crypto::tink::PrimitiveWrapper and `primitive_getter` function to // KeysetWrapperStore. template crypto::tink::util::Status Add( std::unique_ptr> wrapper, absl::AnyInvocable>( const google::crypto::tink::KeyData& key_data) const> primitive_getter); // Gets the PrimitiveWrapper that produces primitive P. This is a legacy // function. template crypto::tink::util::StatusOr*> GetPrimitiveWrapper() const; // Gets the KeysetWrapper that produces primitive Q. template crypto::tink::util::StatusOr*> Get() const; bool IsEmpty() const { return primitive_to_info_.empty(); } private: class Info { public: template explicit Info( std::unique_ptr> wrapper, absl::AnyInvocable>( const google::crypto::tink::KeyData& key_data) const> primitive_getter) : is_same_primitive_wrapping_(std::is_same::value), wrapper_type_index_(std::type_index(typeid(*wrapper))), q_type_index_(std::type_index(typeid(Q))) { keyset_wrapper_ = absl::make_unique>( wrapper.get(), std::move(primitive_getter)); original_wrapper_ = std::move(wrapper); } template crypto::tink::util::StatusOr*> Get() const { if (q_type_index_ != std::type_index(typeid(Q))) { return crypto::tink::util::Status( absl::StatusCode::kInternal, "RegistryImpl::KeysetWrapper() called with wrong type"); } return static_cast*>(keyset_wrapper_.get()); } // TODO(b/171021679): Deprecate this and upstream functions. template crypto::tink::util::StatusOr*> GetPrimitiveWrapper() const { if (!is_same_primitive_wrapping_) { // This happens if a user uses a legacy method (like Registry::Wrap) // directly or has a custom key manager for a primitive which has a // PrimitiveWrapper with P != Q. return crypto::tink::util::Status( absl::StatusCode::kFailedPrecondition, absl::StrCat("Cannot use primitive type ", typeid(P).name(), " with a custom key manager.")); } if (q_type_index_ != std::type_index(typeid(P))) { return crypto::tink::util::Status( absl::StatusCode::kInternal, "RegistryImpl::LegacyWrapper() called with wrong type"); } return static_cast*>( original_wrapper_.get()); } // Returns true if the PrimitiveWrapper is the same class as the one used // to construct this Info. template bool HasSameType(const PrimitiveWrapper& wrapper) { return wrapper_type_index_ == std::type_index(typeid(wrapper)); } private: bool is_same_primitive_wrapping_; // dynamic std::type_index of the actual PrimitiveWrapper class for // which this key was inserted. std::type_index wrapper_type_index_; // dynamic std::type_index of Q, when PrimitiveWrapper was inserted. std::type_index q_type_index_; // The primitive_wrapper passed in. We use a shared_ptr because // unique_ptr is invalid. std::shared_ptr original_wrapper_; // The keyset_wrapper_. We use a shared_ptr because unique_ptr is // invalid. std::shared_ptr keyset_wrapper_; }; // Map from primitive type_index to Info. absl::flat_hash_map primitive_to_info_; }; template crypto::tink::util::Status KeysetWrapperStore::Add( std::unique_ptr> wrapper, absl::AnyInvocable>( const google::crypto::tink::KeyData& key_data) const> primitive_getter) { if (wrapper == nullptr) { return crypto::tink::util::Status(absl::StatusCode::kInvalidArgument, "Parameter 'wrapper' must be non-null."); } auto it = primitive_to_info_.find(std::type_index(typeid(Q))); if (it != primitive_to_info_.end()) { if (!it->second.HasSameType(*wrapper)) { return util::Status(absl::StatusCode::kAlreadyExists, "A wrapper named for this primitive already exists."); } return crypto::tink::util::OkStatus(); } primitive_to_info_.insert( {std::type_index(typeid(Q)), Info(std::move(wrapper), std::move(primitive_getter))}); return crypto::tink::util::OkStatus(); } template crypto::tink::util::StatusOr*> KeysetWrapperStore::GetPrimitiveWrapper() const { auto it = primitive_to_info_.find(std::type_index(typeid(P))); if (it == primitive_to_info_.end()) { return util::Status( absl::StatusCode::kNotFound, absl::StrCat("No wrapper registered for type ", typeid(P).name())); } return it->second.GetPrimitiveWrapper

(); } template crypto::tink::util::StatusOr*> KeysetWrapperStore::Get() const { auto it = primitive_to_info_.find(std::type_index(typeid(P))); if (it == primitive_to_info_.end()) { return util::Status( absl::StatusCode::kNotFound, absl::StrCat("No wrapper registered for type ", typeid(P).name())); } return it->second.Get

(); } } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_KEYSET_WRAPPER_STORE_H_ ================================================ FILE: cc/internal/keyset_wrapper_store_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/keyset_wrapper_store.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/input_stream.h" #include "tink/internal/keyset_wrapper.h" #include "tink/internal/registry_impl.h" #include "tink/mac.h" #include "tink/mac/mac_wrapper.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/subtle/random.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_gcm.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::AesGcmKey; using ::google::crypto::tink::AesGcmKeyFormat; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::Keyset; using ::google::crypto::tink::KeysetInfo; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; class FakePrimitive { public: explicit FakePrimitive(std::string s) : s_(s) {} std::string get() { return s_; } private: std::string s_; }; class FakeKeyTypeManager : public KeyTypeManager> { public: class FakePrimitiveFactory : public PrimitiveFactory { public: util::StatusOr> Create( const AesGcmKey& key) const override { return absl::make_unique(key.key_value()); } }; FakeKeyTypeManager() : KeyTypeManager(absl::make_unique()) {} KeyData::KeyMaterialType key_material_type() const override { return KeyData::SYMMETRIC; } uint32_t get_version() const override { return 0; } const std::string& get_key_type() const override { return key_type_; } util::Status ValidateKey(const AesGcmKey& key) const override { return util::OkStatus(); } util::Status ValidateKeyFormat( const AesGcmKeyFormat& key_format) const override { return util::OkStatus(); } util::StatusOr CreateKey( const AesGcmKeyFormat& key_format) const override { return AesGcmKey(); } util::StatusOr DeriveKey( const AesGcmKeyFormat& key_format, InputStream* input_stream) const override { return AesGcmKey(); } private: const std::string key_type_ = "type.googleapis.com/google.crypto.tink.AesGcmKey"; }; class FakePrimitiveWrapper : public PrimitiveWrapper { public: util::StatusOr> Wrap( std::unique_ptr> primitive_set) const override { return absl::make_unique( primitive_set->get_primary()->get_primitive().get()); } }; class FakePrimitiveWrapper2 : public PrimitiveWrapper { public: util::StatusOr> Wrap( std::unique_ptr> primitive_set) const override { return absl::make_unique( primitive_set->get_primary()->get_primitive().get()); } }; std::string AddAesGcmKeyToKeyset(Keyset& keyset, uint32_t key_id, OutputPrefixType output_prefix_type, KeyStatusType key_status_type) { AesGcmKey key; key.set_version(0); key.set_key_value(subtle::Random::GetRandomBytes(16)); KeyData key_data; key_data.set_value(key.SerializeAsString()); key_data.set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey"); test::AddKeyData(key_data, key_id, output_prefix_type, key_status_type, &keyset); return key.key_value(); } // Returns the function that relies on `registry` to transform `key_data` into // FakePrimitive. util::StatusOr>(const KeyData& key_data)>> PrimitiveGetter(RegistryImpl& registry) { util::Status status = registry.RegisterKeyTypeManager>( absl::make_unique(), /*new_key_allowed=*/true); if (!status.ok()) { return status; } return [®istry](const KeyData& key_data) { return registry.GetPrimitive(key_data); }; } TEST(KeysetWrapperStoreTest, Add) { RegistryImpl registry; util::StatusOr>( const KeyData& key_data)>> primitive_getter = PrimitiveGetter(registry); ASSERT_THAT(primitive_getter, IsOk()); KeysetWrapperStore store; EXPECT_THAT( (store.Add( absl::make_unique(), *primitive_getter)), IsOk()); } TEST(KeysetWrapperStoreTest, AddNull) { RegistryImpl registry; util::StatusOr>( const KeyData& key_data)>> primitive_getter = PrimitiveGetter(registry); ASSERT_THAT(primitive_getter, IsOk()); KeysetWrapperStore store; EXPECT_THAT((store.Add(/*wrapper=*/nullptr, *primitive_getter)), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(KeysetWrapperStoreTest, AddWrappersForDifferentPrimitivesSucceeds) { RegistryImpl registry; util::StatusOr>( const KeyData& key_data)>> primitive_getter = PrimitiveGetter(registry); ASSERT_THAT(primitive_getter, IsOk()); KeysetWrapperStore store; ASSERT_THAT( (store.Add( absl::make_unique(), *primitive_getter)), IsOk()); std::function>(const KeyData& key_data)> primitive_getter_mac = [®istry](const KeyData& key_data) { return registry.GetPrimitive(key_data); }; EXPECT_THAT((store.Add(absl::make_unique(), primitive_getter_mac)), IsOk()); } TEST(KeysetWrapperStoreTest, AddSameWrapperTwiceSucceeds) { RegistryImpl registry; util::StatusOr>( const KeyData& key_data)>> primitive_getter = PrimitiveGetter(registry); ASSERT_THAT(primitive_getter, IsOk()); KeysetWrapperStore store; ASSERT_THAT( (store.Add( absl::make_unique(), *primitive_getter)), IsOk()); EXPECT_THAT( (store.Add( absl::make_unique(), *primitive_getter)), IsOk()); } TEST(KeysetWrapperStoreTest, AddDifferentWrappersForSamePrimitiveFails) { RegistryImpl registry; util::StatusOr>( const KeyData& key_data)>> primitive_getter = PrimitiveGetter(registry); ASSERT_THAT(primitive_getter, IsOk()); KeysetWrapperStore store; ASSERT_THAT( (store.Add( absl::make_unique(), *primitive_getter)), IsOk()); EXPECT_THAT( (store.Add( absl::make_unique(), *primitive_getter)), StatusIs(absl::StatusCode::kAlreadyExists)); } TEST(KeysetWrapperStoreTest, GetPrimitiveWrapper) { RegistryImpl registry; util::StatusOr>( const KeyData& key_data)>> primitive_getter = PrimitiveGetter(registry); ASSERT_THAT(primitive_getter, IsOk()); KeysetWrapperStore store; ASSERT_THAT( (store.Add( absl::make_unique(), *primitive_getter)), IsOk()); util::StatusOr*> legacy_wrapper = store.GetPrimitiveWrapper(); ASSERT_THAT(legacy_wrapper, IsOk()); Keyset keyset; std::string raw_key = AddAesGcmKeyToKeyset(keyset, 13, OutputPrefixType::TINK, KeyStatusType::ENABLED); KeysetInfo keyset_info; keyset_info.add_key_info(); keyset_info.mutable_key_info(0)->set_output_prefix_type( OutputPrefixType::TINK); keyset_info.mutable_key_info(0)->set_key_id(1234543); keyset_info.mutable_key_info(0)->set_status(KeyStatusType::ENABLED); keyset_info.set_primary_key_id(1234543); std::unique_ptr> primitive_set( new PrimitiveSet()); auto entry = primitive_set->AddPrimitive( absl::make_unique(raw_key), keyset_info.key_info(0)); ASSERT_THAT(entry, IsOk()); ASSERT_THAT(primitive_set->set_primary(*entry), IsOk()); util::StatusOr> legacy_aead = (*legacy_wrapper)->Wrap(std::move(primitive_set)); ASSERT_THAT(legacy_aead, IsOk()); EXPECT_THAT((*legacy_aead)->get(), Eq(raw_key)); } TEST(KeysetWrapperStoreTest, GetPrimitiveWrapperNonexistentWrapperFails) { RegistryImpl registry; util::StatusOr>( const KeyData& key_data)>> primitive_getter = PrimitiveGetter(registry); ASSERT_THAT(primitive_getter, IsOk()); KeysetWrapperStore store; ASSERT_THAT( (store.Add( absl::make_unique(), *primitive_getter)), IsOk()); EXPECT_THAT(store.GetPrimitiveWrapper().status(), StatusIs(absl::StatusCode::kNotFound)); } TEST(KeysetWrapperStoreTest, Get) { RegistryImpl registry; util::StatusOr>( const KeyData& key_data)>> primitive_getter = PrimitiveGetter(registry); ASSERT_THAT(primitive_getter, IsOk()); KeysetWrapperStore store; ASSERT_THAT( (store.Add( absl::make_unique(), *primitive_getter)), IsOk()); util::StatusOr*> wrapper = store.Get(); ASSERT_THAT(wrapper, IsOk()); Keyset keyset; std::string raw_key = AddAesGcmKeyToKeyset(keyset, 13, OutputPrefixType::TINK, KeyStatusType::ENABLED); keyset.set_primary_key_id(13); util::StatusOr> aead = (*wrapper)->Wrap(keyset, /*annotations=*/{}); ASSERT_THAT(aead, IsOk()); EXPECT_THAT((*aead)->get(), Eq(raw_key)); } TEST(KeysetWrapperStoreTest, GetNonexistentWrapperFails) { RegistryImpl registry; util::StatusOr>( const KeyData& key_data)>> primitive_getter = PrimitiveGetter(registry); ASSERT_THAT(primitive_getter, IsOk()); KeysetWrapperStore store; ASSERT_THAT( (store.Add( absl::make_unique(), *primitive_getter)), IsOk()); EXPECT_THAT(store.Get().status(), StatusIs(absl::StatusCode::kNotFound)); } TEST(KeysetWrapperStoreTest, IsEmpty) { KeysetWrapperStore store; EXPECT_EQ(store.IsEmpty(), true); RegistryImpl registry; util::StatusOr>( const KeyData& key_data)>> primitive_getter = PrimitiveGetter(registry); ASSERT_THAT(primitive_getter, IsOk()); ASSERT_THAT( (store.Add( absl::make_unique(), *primitive_getter)), IsOk()); EXPECT_THAT(store.IsEmpty(), false); } TEST(KeysetWrapperStoreTest, Move) { RegistryImpl registry; util::StatusOr>( const KeyData& key_data)>> primitive_getter = PrimitiveGetter(registry); ASSERT_THAT(primitive_getter, IsOk()); KeysetWrapperStore store; ASSERT_THAT( (store.Add( absl::make_unique(), *primitive_getter)), IsOk()); util::StatusOr*> wrapper = store.Get(); ASSERT_THAT(wrapper, IsOk()); KeysetWrapperStore new_store = std::move(store); wrapper = new_store.Get(); ASSERT_THAT(wrapper, IsOk()); Keyset keyset; std::string raw_key = AddAesGcmKeyToKeyset(keyset, 13, OutputPrefixType::TINK, KeyStatusType::ENABLED); keyset.set_primary_key_id(13); util::StatusOr> aead = (*wrapper)->Wrap(keyset, /*annotations=*/{}); ASSERT_THAT(aead, IsOk()); EXPECT_THAT((*aead)->get(), Eq(raw_key)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/legacy_proto_key.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/legacy_proto_key.h" #include #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/internal/proto_key_serialization.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/secret_key_access_token.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::google::crypto::tink::KeyData; util::Status CheckKeyAccess(KeyData::KeyMaterialType key_material_type, absl::optional token) { if (key_material_type == KeyData::SYMMETRIC || key_material_type == KeyData::ASYMMETRIC_PRIVATE) { if (!token.has_value()) { return util::Status( absl::StatusCode::kPermissionDenied, "Missing secret key access token for legacy proto key."); } } return util::OkStatus(); } } // namespace bool UnusableLegacyProtoParameters::operator==(const Parameters& other) const { const UnusableLegacyProtoParameters* that = dynamic_cast(&other); if (that == nullptr) { return false; } return type_url_ == that->type_url_ && output_prefix_type_ == that->output_prefix_type_; } util::StatusOr LegacyProtoKey::Create( ProtoKeySerialization serialization, absl::optional token) { util::Status access_check_status = CheckKeyAccess(serialization.KeyMaterialType(), token); if (!access_check_status.ok()) { return access_check_status; } return LegacyProtoKey(serialization); } bool LegacyProtoKey::operator==(const Key& other) const { const LegacyProtoKey* that = dynamic_cast(&other); if (that == nullptr) { return false; } return serialization_.EqualsWithPotentialFalseNegatives(that->serialization_); } util::StatusOr LegacyProtoKey::Serialization( absl::optional token) const { util::Status access_check_status = CheckKeyAccess(serialization_.KeyMaterialType(), token); if (!access_check_status.ok()) { return access_check_status; } return &serialization_; } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/legacy_proto_key.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_LEGACY_PROTO_KEY_H_ #define TINK_INTERNAL_LEGACY_PROTO_KEY_H_ #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/internal/proto_key_serialization.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/secret_key_access_token.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { // Parameters returned by `LegacyProtoKey::GetParameters()` that cannot be used // to create other LegacyProtoKey instances. class UnusableLegacyProtoParameters : public Parameters { public: // Copyable and movable. UnusableLegacyProtoParameters(const UnusableLegacyProtoParameters& other) = default; UnusableLegacyProtoParameters& operator=( const UnusableLegacyProtoParameters& other) = default; UnusableLegacyProtoParameters(UnusableLegacyProtoParameters&& other) = default; UnusableLegacyProtoParameters& operator=( UnusableLegacyProtoParameters&& other) = default; explicit UnusableLegacyProtoParameters( absl::string_view type_url, google::crypto::tink::OutputPrefixType output_prefix_type) : type_url_(type_url), output_prefix_type_(output_prefix_type) {} bool HasIdRequirement() const override { return output_prefix_type_ != google::crypto::tink::OutputPrefixType::RAW; } bool operator==(const Parameters& other) const override; private: std::string type_url_; google::crypto::tink::OutputPrefixType output_prefix_type_; }; // Key type for legacy proto keys. class LegacyProtoKey : public Key { public: // Copyable and movable. LegacyProtoKey(const LegacyProtoKey& other) = default; LegacyProtoKey& operator=(const LegacyProtoKey& other) = default; LegacyProtoKey(LegacyProtoKey&& other) = default; LegacyProtoKey& operator=(LegacyProtoKey&& other) = default; // Creates `LegacyProtoKey` object from `serialization`. Requires `token` if // the key material type is either SYMMETRIC or ASYMMETRIC_PRIVATE. static util::StatusOr Create( ProtoKeySerialization serialization, absl::optional token); const Parameters& GetParameters() const override { return unusable_proto_parameters_; } absl::optional GetIdRequirement() const override { return serialization_.IdRequirement(); } bool operator==(const Key& other) const override; // Returns `ProtoKeySerialization` pointer for this object. Requires `token` // if the key material type is either SYMMETRIC or ASYMMETRIC_PRIVATE. util::StatusOr Serialization( absl::optional token) const; private: explicit LegacyProtoKey(ProtoKeySerialization serialization) : serialization_(serialization), unusable_proto_parameters_(serialization.TypeUrl(), serialization.GetOutputPrefixType()) {} ProtoKeySerialization serialization_; UnusableLegacyProtoParameters unusable_proto_parameters_; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_LEGACY_PROTO_KEY_H_ ================================================ FILE: cc/internal/legacy_proto_key_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/legacy_proto_key.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/proto_key_serialization.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/restricted_data.h" #include "tink/secret_key_access_token.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::IsTrue; using ::testing::TestWithParam; using ::testing::Values; class LegacyProtoKeyTest : public ::testing::Test { protected: // Although this is a friend class, this utility function is necessary to // access `ProtoKeySerialization::EqualsWithPotentialFalseNegatives()` // since the test fixtures are subclasses that would not have direct access. bool Equals(ProtoKeySerialization serialization, ProtoKeySerialization other) { return serialization.EqualsWithPotentialFalseNegatives(other); } }; TEST_F(LegacyProtoKeyTest, CreateAndSerialization) { RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr key = LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key.status(), IsOk()); EXPECT_THAT(key->GetIdRequirement(), Eq(12345)); EXPECT_THAT(key->GetParameters().HasIdRequirement(), IsTrue()); EXPECT_THAT(key->Serialization(InsecureSecretKeyAccess::Get()), IsOk()); util::StatusOr key_serialization = key->Serialization(InsecureSecretKeyAccess::Get()); ASSERT_THAT(key_serialization.status(), IsOk()); EXPECT_THAT(Equals(**key_serialization, *serialization), IsTrue()); } TEST_F(LegacyProtoKeyTest, Equals) { RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr other_serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(other_serialization.status(), IsOk()); util::StatusOr key = LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key.status(), IsOk()); util::StatusOr other_key = LegacyProtoKey::Create( *other_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(other_key.status(), IsOk()); EXPECT_TRUE(*key == *other_key); EXPECT_TRUE(*other_key == *key); EXPECT_FALSE(*key != *other_key); EXPECT_FALSE(*other_key != *key); } TEST_F(LegacyProtoKeyTest, TypeUrlNotEqual) { RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr other_serialization = ProtoKeySerialization::Create("other_type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(other_serialization.status(), IsOk()); util::StatusOr key = LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key.status(), IsOk()); util::StatusOr other_key = LegacyProtoKey::Create( *other_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(other_key.status(), IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST_F(LegacyProtoKeyTest, SerializedKeyNotEqual) { RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); RestrictedData other_serialized_key = RestrictedData("other_serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr other_serialization = ProtoKeySerialization::Create("type_url", other_serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(other_serialization.status(), IsOk()); util::StatusOr key = LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key.status(), IsOk()); util::StatusOr other_key = LegacyProtoKey::Create( *other_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(other_key.status(), IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST_F(LegacyProtoKeyTest, KeyMaterialTypeNotEqual) { RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr other_serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::REMOTE, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(other_serialization.status(), IsOk()); util::StatusOr key = LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key.status(), IsOk()); util::StatusOr other_key = LegacyProtoKey::Create( *other_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(other_key.status(), IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST_F(LegacyProtoKeyTest, OutputPrefixTypeNotEqual) { RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr other_serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::CRUNCHY, /*id_requirement=*/12345); ASSERT_THAT(other_serialization.status(), IsOk()); util::StatusOr key = LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key.status(), IsOk()); util::StatusOr other_key = LegacyProtoKey::Create( *other_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(other_key.status(), IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST_F(LegacyProtoKeyTest, IdRequirementNotEqual) { RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr other_serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/6789); ASSERT_THAT(other_serialization.status(), IsOk()); util::StatusOr key = LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key.status(), IsOk()); util::StatusOr other_key = LegacyProtoKey::Create( *other_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(other_key.status(), IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } using AllOutputPrefixTypesTest = TestWithParam>>; INSTANTIATE_TEST_SUITE_P( AllOutputPrefixTypesTestSuite, AllOutputPrefixTypesTest, Values(std::make_tuple(OutputPrefixType::RAW, absl::nullopt), std::make_tuple(OutputPrefixType::TINK, 123), std::make_tuple(OutputPrefixType::CRUNCHY, 456), std::make_tuple(OutputPrefixType::LEGACY, 789))); TEST_P(AllOutputPrefixTypesTest, GetIdRequirement) { OutputPrefixType output_prefix_type; absl::optional id_requirement; std::tie(output_prefix_type, id_requirement) = GetParam(); RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, output_prefix_type, id_requirement); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr key = LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key.status(), IsOk()); EXPECT_THAT(key->GetIdRequirement(), Eq(id_requirement)); } using AllKeyMaterialTypesTest = TestWithParam; INSTANTIATE_TEST_SUITE_P(AllKeyMaterialTypesTestSuite, AllKeyMaterialTypesTest, Values(KeyData::SYMMETRIC, KeyData::ASYMMETRIC_PRIVATE, KeyData::ASYMMETRIC_PUBLIC, KeyData::REMOTE)); TEST_P(AllKeyMaterialTypesTest, CreateAndSerializationWithSecretAccessToken) { KeyData::KeyMaterialType key_material_type = GetParam(); RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, key_material_type, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr key = LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key.status(), IsOk()); util::StatusOr key_serialization = key->Serialization(InsecureSecretKeyAccess::Get()); ASSERT_THAT(key_serialization.status(), IsOk()); } using SecretKeyMaterialTypesTest = TestWithParam; INSTANTIATE_TEST_SUITE_P(SecretKeyMaterialTypesTestSuite, SecretKeyMaterialTypesTest, Values(KeyData::SYMMETRIC, KeyData::ASYMMETRIC_PRIVATE)); TEST_P(SecretKeyMaterialTypesTest, CreateWithoutSecretAccessToken) { KeyData::KeyMaterialType key_material_type = GetParam(); RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, key_material_type, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr key = LegacyProtoKey::Create(*serialization, /*token=*/absl::nullopt); ASSERT_THAT(key.status(), StatusIs(absl::StatusCode::kPermissionDenied)); } TEST_P(SecretKeyMaterialTypesTest, SerializationWithoutSecretAccessToken) { KeyData::KeyMaterialType key_material_type = GetParam(); RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, key_material_type, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(serialization.status(), IsOk()); // Must use token for key creation. util::StatusOr key = LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key.status(), IsOk()); util::StatusOr key_serialization = key->Serialization(/*token=*/absl::nullopt); ASSERT_THAT(key_serialization.status(), StatusIs(absl::StatusCode::kPermissionDenied)); } using NonSecretKeyMaterialTypesTest = TestWithParam; INSTANTIATE_TEST_SUITE_P(NonSecretKeyMaterialTypesTestSuite, NonSecretKeyMaterialTypesTest, Values(KeyData::ASYMMETRIC_PUBLIC, KeyData::REMOTE)); TEST_P(NonSecretKeyMaterialTypesTest, CreateWithoutSecretAccessToken) { KeyData::KeyMaterialType key_material_type = GetParam(); RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, key_material_type, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr key = LegacyProtoKey::Create(*serialization, /*token=*/absl::nullopt); ASSERT_THAT(key.status(), IsOk()); } TEST_P(NonSecretKeyMaterialTypesTest, SerializationWithoutSecretAccessToken) { KeyData::KeyMaterialType key_material_type = GetParam(); RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, key_material_type, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(serialization.status(), IsOk()); // Must use token for key creation. util::StatusOr key = LegacyProtoKey::Create(*serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key.status(), IsOk()); util::StatusOr key_serialization = key->Serialization(/*token=*/absl::nullopt); ASSERT_THAT(key_serialization.status(), IsOk()); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/legacy_proto_parameters.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/legacy_proto_parameters.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/parameters.h" namespace crypto { namespace tink { namespace internal { bool LegacyProtoParameters::operator==(const Parameters& other) const { const LegacyProtoParameters* that = dynamic_cast(&other); if (that == nullptr) { return false; } return serialization_.EqualsWithPotentialFalseNegatives(that->serialization_); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/legacy_proto_parameters.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_LEGACY_PROTO_PARAMETERS_H_ #define TINK_INTERNAL_LEGACY_PROTO_PARAMETERS_H_ #include #include "tink/internal/proto_parameters_serialization.h" #include "tink/parameters.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { class LegacyProtoParameters : public Parameters { public: // Copyable and movable. LegacyProtoParameters(const LegacyProtoParameters& other) = default; LegacyProtoParameters& operator=(const LegacyProtoParameters& other) = default; LegacyProtoParameters(LegacyProtoParameters&& other) = default; LegacyProtoParameters& operator=(LegacyProtoParameters&& other) = default; explicit LegacyProtoParameters(ProtoParametersSerialization serialization) : serialization_(std::move(serialization)) {} bool HasIdRequirement() const override { return serialization_.GetKeyTemplate().output_prefix_type() != google::crypto::tink::OutputPrefixType::RAW; } bool operator==(const Parameters& other) const override; const ProtoParametersSerialization& Serialization() const { return serialization_; } private: ProtoParametersSerialization serialization_; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_LEGACY_PROTO_PARAMETERS_H_ ================================================ FILE: cc/internal/legacy_proto_parameters_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/legacy_proto_parameters.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/parameters.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/test_proto.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { using ::crypto::tink::test::IsOk; using ::google::crypto::tink::OutputPrefixType; using ::google::crypto::tink::TestProto; using ::testing::IsFalse; using ::testing::IsTrue; class LegacyProtoParametersTest : public ::testing::Test { protected: // Although this is a friend class, this utility function is necessary to // access `ProtoParametersSerialization::EqualsWithPotentialFalseNegatives()` // since the test fixtures are subclasses that would not have direct access. bool Equals(ProtoParametersSerialization serialization, ProtoParametersSerialization other) { return serialization.EqualsWithPotentialFalseNegatives(other); } }; TEST_F(LegacyProtoParametersTest, CreateWithIdRequirement) { TestProto test_proto; test_proto.set_num(12345); util::StatusOr serialization = ProtoParametersSerialization::Create("type_url", OutputPrefixType::TINK, test_proto.SerializeAsString()); ASSERT_THAT(serialization.status(), IsOk()); LegacyProtoParameters parameters(*serialization); EXPECT_THAT(parameters.HasIdRequirement(), IsTrue()); EXPECT_THAT(Equals(*serialization, parameters.Serialization()), IsTrue()); } TEST_F(LegacyProtoParametersTest, CreateWithoutIdRequirement) { TestProto test_proto; test_proto.set_num(12345); util::StatusOr serialization = ProtoParametersSerialization::Create("type_url", OutputPrefixType::RAW, test_proto.SerializeAsString()); ASSERT_THAT(serialization.status(), IsOk()); LegacyProtoParameters parameters(*serialization); EXPECT_THAT(parameters.HasIdRequirement(), IsFalse()); EXPECT_THAT(Equals(*serialization, parameters.Serialization()), IsTrue()); } TEST_F(LegacyProtoParametersTest, Equals) { TestProto test_proto; test_proto.set_num(12345); util::StatusOr serialization = ProtoParametersSerialization::Create("type_url", OutputPrefixType::RAW, test_proto.SerializeAsString()); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr other_serialization = ProtoParametersSerialization::Create("type_url", OutputPrefixType::RAW, test_proto.SerializeAsString()); ASSERT_THAT(other_serialization.status(), IsOk()); LegacyProtoParameters parameters(*serialization); LegacyProtoParameters other_parameters(*other_serialization); EXPECT_TRUE(parameters == other_parameters); EXPECT_TRUE(other_parameters == parameters); EXPECT_FALSE(parameters != other_parameters); EXPECT_FALSE(other_parameters != parameters); } TEST_F(LegacyProtoParametersTest, TypeUrlNotEqual) { TestProto test_proto; test_proto.set_num(12345); util::StatusOr serialization = ProtoParametersSerialization::Create("type_url", OutputPrefixType::RAW, test_proto.SerializeAsString()); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr other_serialization = ProtoParametersSerialization::Create("other_type_url", OutputPrefixType::RAW, test_proto.SerializeAsString()); ASSERT_THAT(other_serialization.status(), IsOk()); LegacyProtoParameters parameters(*serialization); LegacyProtoParameters other_parameters(*other_serialization); EXPECT_TRUE(parameters != other_parameters); EXPECT_TRUE(other_parameters != parameters); EXPECT_FALSE(parameters == other_parameters); EXPECT_FALSE(other_parameters == parameters); } TEST_F(LegacyProtoParametersTest, OutputPrefixTypeNotEqual) { TestProto test_proto; test_proto.set_num(12345); util::StatusOr serialization = ProtoParametersSerialization::Create("type_url", OutputPrefixType::RAW, test_proto.SerializeAsString()); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr other_serialization = ProtoParametersSerialization::Create("type_url", OutputPrefixType::TINK, test_proto.SerializeAsString()); ASSERT_THAT(other_serialization.status(), IsOk()); LegacyProtoParameters parameters(*serialization); LegacyProtoParameters other_parameters(*other_serialization); EXPECT_TRUE(parameters != other_parameters); EXPECT_TRUE(other_parameters != parameters); EXPECT_FALSE(parameters == other_parameters); EXPECT_FALSE(other_parameters == parameters); } TEST_F(LegacyProtoParametersTest, DifferentValueNotEqual) { TestProto test_proto; test_proto.set_num(12345); TestProto other_proto; other_proto.set_num(67890); util::StatusOr serialization = ProtoParametersSerialization::Create("type_url", OutputPrefixType::RAW, test_proto.SerializeAsString()); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr other_serialization = ProtoParametersSerialization::Create("type_url", OutputPrefixType::RAW, other_proto.SerializeAsString()); ASSERT_THAT(other_serialization.status(), IsOk()); LegacyProtoParameters parameters(*serialization); LegacyProtoParameters other_parameters(*other_serialization); EXPECT_TRUE(parameters != other_parameters); EXPECT_TRUE(other_parameters != parameters); EXPECT_FALSE(parameters == other_parameters); EXPECT_FALSE(other_parameters == parameters); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/md_util.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/md_util.h" #include #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "tink/internal/err_util.h" #include "tink/internal/util.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { util::StatusOr EvpHashFromHashType(subtle::HashType hash_type) { switch (hash_type) { case subtle::HashType::SHA1: return EVP_sha1(); case subtle::HashType::SHA224: return EVP_sha224(); case subtle::HashType::SHA256: return EVP_sha256(); case subtle::HashType::SHA384: return EVP_sha384(); case subtle::HashType::SHA512: return EVP_sha512(); default: return util::Status( absl::StatusCode::kUnimplemented, absl::StrCat("Unsupported hash ", subtle::EnumToString(hash_type))); } } util::Status IsHashTypeSafeForSignature(subtle::HashType sig_hash) { switch (sig_hash) { case subtle::HashType::SHA256: case subtle::HashType::SHA384: case subtle::HashType::SHA512: return util::OkStatus(); case subtle::HashType::SHA1: case subtle::HashType::SHA224: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Hash function ", subtle::EnumToString(sig_hash), " is not safe for digital signature")); default: return util::Status(absl::StatusCode::kInvalidArgument, "Unsupported hash function"); } } util::StatusOr ComputeHash(absl::string_view input, const EVP_MD &hasher) { input = EnsureStringNonNull(input); std::string digest; subtle::ResizeStringUninitialized(&digest, EVP_MAX_MD_SIZE); uint32_t digest_length = 0; if (EVP_Digest(input.data(), input.length(), reinterpret_cast(&digest[0]), &digest_length, &hasher, /*impl=*/nullptr) != 1) { return util::Status(absl::StatusCode::kInternal, absl::StrCat("Openssl internal error computing hash: ", internal::GetSslErrors())); } digest.resize(digest_length); return digest; } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/md_util.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_MD_UTIL_H_ #define TINK_INTERNAL_MD_UTIL_H_ #include #include #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "tink/subtle/common_enums.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { // Returns an EVP structure for a hash function type `hash_type`. // Note: EVP_MD instances are sigletons owned by BoringSSL/OpenSSL. util::StatusOr EvpHashFromHashType( crypto::tink::subtle::HashType hash_type); // Validates whether `sig_hash` is safe to use for digital signature. crypto::tink::util::Status IsHashTypeSafeForSignature( crypto::tink::subtle::HashType sig_hash); // Returns the hash of `input` using the hash function `hasher`. crypto::tink::util::StatusOr ComputeHash(absl::string_view input, const EVP_MD &hasher); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_MD_UTIL_H_ ================================================ FILE: cc/internal/md_util_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/md_util.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/escaping.h" #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "tink/subtle/common_enums.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::subtle::HashType; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::testing::Not; using ::testing::TestWithParam; using ::testing::ValuesIn; TEST(MdUtil, EvpHashFromHashType) { EXPECT_THAT(EvpHashFromHashType(HashType::SHA1), IsOkAndHolds(EVP_sha1())); EXPECT_THAT(EvpHashFromHashType(HashType::SHA224), IsOkAndHolds(EVP_sha224())); EXPECT_THAT(EvpHashFromHashType(HashType::SHA256), IsOkAndHolds(EVP_sha256())); EXPECT_THAT(EvpHashFromHashType(HashType::SHA384), IsOkAndHolds(EVP_sha384())); EXPECT_THAT(EvpHashFromHashType(HashType::SHA512), IsOkAndHolds(EVP_sha512())); EXPECT_THAT(EvpHashFromHashType(HashType::UNKNOWN_HASH).status(), Not(IsOk())); } TEST(MdUtil, IsHashTypeSafeForSignature) { EXPECT_THAT(IsHashTypeSafeForSignature(HashType::SHA256), IsOk()); EXPECT_THAT(IsHashTypeSafeForSignature(HashType::SHA384), IsOk()); EXPECT_THAT(IsHashTypeSafeForSignature(HashType::SHA512), IsOk()); EXPECT_THAT(IsHashTypeSafeForSignature(HashType::SHA1), Not(IsOk())); EXPECT_THAT(IsHashTypeSafeForSignature(HashType::SHA224), Not(IsOk())); EXPECT_THAT(IsHashTypeSafeForSignature(HashType::UNKNOWN_HASH), Not(IsOk())); } TEST(MdUtil, ComputeHashAcceptsNullStringView) { util::StatusOr null_hash = ComputeHash(absl::string_view(nullptr, 0), *EVP_sha512()); util::StatusOr empty_hash = ComputeHash("", *EVP_sha512()); std::string str; util::StatusOr empty_str_hash = ComputeHash(str, *EVP_sha512()); ASSERT_THAT(null_hash, IsOk()); ASSERT_THAT(empty_hash, IsOk()); ASSERT_THAT(empty_str_hash, IsOk()); EXPECT_EQ(*null_hash, *empty_hash); EXPECT_EQ(*null_hash, *empty_str_hash); } struct MdUtilComputeHashSamplesTestParam { HashType hash_type; std::string data_hex; std::string expected_digest_hex; }; using MdUtilComputeHashSamplesTest = TestWithParam; // Returns the test parameters for MdUtilComputeHashSamplesTest from NIST's // samples. std::vector GetMdUtilComputeHashSamplesTestParams() { std::vector params; params.push_back({ HashType::SHA256, "af397a8b8dd73ab702ce8e53aa9f", "d189498a3463b18e846b8ab1b41583b0b7efc789dad8a7fb885bbf8fb5b45c5c", }); params.push_back({ HashType::SHA256, "59eb45bbbeb054b0b97334d53580ce03f699", "32c38c54189f2357e96bd77eb00c2b9c341ebebacc2945f97804f59a93238288", }); params.push_back({ HashType::SHA512, "16b17074d3e3d97557f9ed77d920b4b1bff4e845b345a922", "6884134582a760046433abcbd53db8ff1a89995862f305b887020f6da6c7b903a314721e" "972bf438483f452a8b09596298a576c903c91df4a414c7bd20fd1d07", }); params.push_back({ HashType::SHA512, "7651ab491b8fa86f969d42977d09df5f8bee3e5899180b52c968b0db057a6f02a886ad61" "7a84915a", "f35e50e2e02b8781345f8ceb2198f068ba103476f715cfb487a452882c9f0de0c720b2a0" "88a39d06a8a6b64ce4d6470dfeadc4f65ae06672c057e29f14c4daf9", }); return params; } TEST_P(MdUtilComputeHashSamplesTest, ComputesHash) { const MdUtilComputeHashSamplesTestParam& params = GetParam(); util::StatusOr hasher = EvpHashFromHashType(params.hash_type); ASSERT_THAT(hasher, IsOk()); std::string data = absl::HexStringToBytes(params.data_hex); std::string expected_digest = absl::HexStringToBytes(params.expected_digest_hex); EXPECT_THAT(ComputeHash(data, **hasher), IsOkAndHolds(expected_digest)); } INSTANTIATE_TEST_SUITE_P(MdUtilComputeHashSamplesTests, MdUtilComputeHashSamplesTest, ValuesIn(GetMdUtilComputeHashSamplesTestParams())); } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/monitoring_util.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_MONITORING_UTIL_H_ #define TINK_INTERNAL_MONITORING_UTIL_H_ #include #include #include "absl/container/flat_hash_map.h" #include "absl/status/status.h" #include "absl/strings/strip.h" #include "tink/internal/key_status_util.h" #include "tink/key_status.h" #include "tink/monitoring/monitoring.h" #include "tink/primitive_set.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { constexpr char kKeyTypePrefix[] = "type.googleapis.com/google.crypto."; // Constructs a MonitoringKeySetInfo object from a PrimitiveSet `primitive_set` // for a given primitive P. template crypto::tink::util::StatusOr MonitoringKeySetInfoFromPrimitiveSet(const PrimitiveSet

& primitive_set) { const std::vector::template Entry

*> primitive_set_entries = primitive_set.get_all(); if (primitive_set_entries.empty()) { return util::Status(absl::StatusCode::kInvalidArgument, "The primitive set is empty"); } if (primitive_set.get_primary() == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "The primary keys must not be null"); } std::vector keyset_info_entries = {}; for (const auto& entry : primitive_set_entries) { util::StatusOr key_status = FromKeyStatusType(entry->get_status()); if (!key_status.ok()) return key_status.status(); auto keyset_info_entry = MonitoringKeySetInfo::Entry( *key_status, entry->get_key_id(), absl::StripPrefix(entry->get_key_type_url(), kKeyTypePrefix), OutputPrefixType_Name(entry->get_output_prefix_type())); keyset_info_entries.push_back(keyset_info_entry); } MonitoringKeySetInfo keyset_info(primitive_set.get_annotations(), keyset_info_entries, primitive_set.get_primary()->get_key_id()); return keyset_info; } } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_MONITORING_UTIL_H_ ================================================ FILE: cc/internal/monitoring_util_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/monitoring_util.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_map.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/key_status.h" #include "tink/monitoring/monitoring.h" #include "tink/primitive_set.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::MonitoringKeySetInfo; using ::crypto::tink::test::IsOk; using ::google::crypto::tink::KeysetInfo; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::OutputPrefixType; using ::testing::UnorderedElementsAre; using ::testing::UnorderedElementsAreArray; TEST(MonitoringUtilTest, MonitoringKeySetInfoFromPrimitiveSetEmptyPrimitiveSet) { PrimitiveSet primitive_set; EXPECT_THAT(MonitoringKeySetInfoFromPrimitiveSet(primitive_set).status(), test::StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(MonitoringUtilTest, MonitoringKeySetInfoFromPrimitiveSetNullPrimary) { PrimitiveSet primitive_set; auto some_string = absl::make_unique("Text"); KeysetInfo::KeyInfo key_info; key_info.set_type_url( "type.googleapis.com/google.crypto.tink.SomePrimitiveInstance"); key_info.set_status(KeyStatusType::ENABLED); key_info.set_key_id(1); key_info.set_output_prefix_type(OutputPrefixType::TINK); util::StatusOr::Entry *> added_entry = primitive_set.AddPrimitive(std::move(some_string), key_info); ASSERT_THAT(added_entry, IsOk()); EXPECT_THAT(MonitoringKeySetInfoFromPrimitiveSet(primitive_set).status(), test::StatusIs(absl::StatusCode::kInvalidArgument)); } // Utility struct to hold primitive and key info. template struct PrimitiveSetInputPrimitive { std::unique_ptr

primitive; KeysetInfo::KeyInfo key_info; }; PrimitiveSetInputPrimitive NewPrimitiveSetInputPrimitive( absl::string_view primitive_value, absl::string_view type_url, KeyStatusType status, uint32_t key_id, OutputPrefixType prefix_type) { auto some_string = absl::make_unique(primitive_value); KeysetInfo::KeyInfo key_info; std::string type_url_str(type_url); key_info.set_type_url(type_url_str); key_info.set_status(status); key_info.set_key_id(key_id); key_info.set_output_prefix_type(prefix_type); return {/*primitive=*/std::move(some_string), /*key_info=*/std::move(key_info)}; } MATCHER_P(MonitoringKeySetInfoEntryEq, other, "") { return arg.GetStatus() == other.GetStatus() && arg.GetKeyId() == other.GetKeyId() && arg.GetKeyPrefix() == other.GetKeyPrefix() && arg.GetKeyType() == other.GetKeyType(); } TEST(MonitoringUtilTest, MonitoringKeySetInfoFromPrimitiveSetValid) { const absl::flat_hash_map kAnnotations = { {"key1", "value1"}, {"key2", "value2"}, }; PrimitiveSet primitive_set(kAnnotations); constexpr absl::string_view kPrimitive1KeyTyepUrl = "type.googleapis.com/google.crypto.tink.SomePrimitiveInstance"; constexpr absl::string_view kPrimitive2KeyTypeUrl = "type.googleapis.com/google.crypto.tink.SomeOtherPrimitiveInstance"; PrimitiveSetInputPrimitive primitive_1 = NewPrimitiveSetInputPrimitive( /*primitive_value=*/"primitive_1", kPrimitive1KeyTyepUrl, /*status=*/KeyStatusType::ENABLED, /*key_id=*/1, /*prefix_type=*/OutputPrefixType::TINK); PrimitiveSetInputPrimitive primitive_2 = NewPrimitiveSetInputPrimitive( /*primitive_value=*/"primitive_2", kPrimitive2KeyTypeUrl, /*status=*/KeyStatusType::ENABLED, /*key_id=*/2, /*prefix_type=*/OutputPrefixType::TINK); util::StatusOr::Entry *> added_entry = primitive_set.AddPrimitive(std::move(primitive_1.primitive), primitive_1.key_info); ASSERT_THAT(added_entry, IsOk()); ASSERT_THAT(primitive_set.set_primary(*added_entry), IsOk()); added_entry = primitive_set.AddPrimitive(std::move(primitive_2.primitive), primitive_2.key_info); ASSERT_THAT(added_entry, IsOk()); util::StatusOr monitoring_keyset_info = MonitoringKeySetInfoFromPrimitiveSet(primitive_set); ASSERT_THAT(monitoring_keyset_info, IsOk()); EXPECT_EQ(monitoring_keyset_info->GetPrimaryKeyId(), 1); EXPECT_THAT(monitoring_keyset_info->GetAnnotations(), UnorderedElementsAreArray(kAnnotations)); const std::vector &monitoring_entries = monitoring_keyset_info->GetEntries(); EXPECT_THAT( monitoring_entries, UnorderedElementsAre( MonitoringKeySetInfoEntryEq(MonitoringKeySetInfo::Entry( KeyStatus::kEnabled, /*key_id=*/1, "tink.SomePrimitiveInstance", "TINK")), MonitoringKeySetInfoEntryEq(MonitoringKeySetInfo::Entry( KeyStatus::kEnabled, /*key_id=*/2, "tink.SomeOtherPrimitiveInstance", "TINK")))); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/mutable_serialization_registry.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/mutable_serialization_registry.h" #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/synchronization/mutex.h" #include "absl/types/optional.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/key_parser.h" #include "tink/internal/key_serializer.h" #include "tink/internal/legacy_proto_key.h" #include "tink/internal/parameters_parser.h" #include "tink/internal/parameters_serializer.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/serialization.h" #include "tink/internal/serialization_registry.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/secret_key_access_token.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { MutableSerializationRegistry& MutableSerializationRegistry::GlobalInstance() { static MutableSerializationRegistry* instance = new MutableSerializationRegistry(); return *instance; } util::Status MutableSerializationRegistry::RegisterParametersParser( ParametersParser* parser) { absl::WriterMutexLock lock(®istry_mutex_); SerializationRegistry::Builder builder(registry_); util::Status status = builder.RegisterParametersParser(parser); if (!status.ok()) return status; registry_ = std::move(builder).Build(); return util::OkStatus(); } util::Status MutableSerializationRegistry::RegisterParametersSerializer( ParametersSerializer* serializer) { absl::WriterMutexLock lock(®istry_mutex_); SerializationRegistry::Builder builder(registry_); util::Status status = builder.RegisterParametersSerializer(serializer); if (!status.ok()) return status; registry_ = std::move(builder).Build(); return util::OkStatus(); } util::Status MutableSerializationRegistry::RegisterKeyParser( KeyParser* parser) { absl::WriterMutexLock lock(®istry_mutex_); SerializationRegistry::Builder builder(registry_); util::Status status = builder.RegisterKeyParser(parser); if (!status.ok()) return status; registry_ = std::move(builder).Build(); return util::OkStatus(); } util::Status MutableSerializationRegistry::RegisterKeySerializer( KeySerializer* serializer) { absl::WriterMutexLock lock(®istry_mutex_); SerializationRegistry::Builder builder(registry_); util::Status status = builder.RegisterKeySerializer(serializer); if (!status.ok()) return status; registry_ = std::move(builder).Build(); return util::OkStatus(); } util::StatusOr> MutableSerializationRegistry::ParseParameters( const Serialization& serialization) { absl::ReaderMutexLock lock(®istry_mutex_); return registry_.ParseParameters(serialization); } util::StatusOr> MutableSerializationRegistry::ParseKey( const Serialization& serialization, absl::optional token) { absl::ReaderMutexLock lock(®istry_mutex_); return registry_.ParseKey(serialization, token); } util::StatusOr> MutableSerializationRegistry::ParseKeyWithLegacyFallback( const Serialization& serialization, SecretKeyAccessToken token) { util::StatusOr> key = ParseKey(serialization, token); if (key.status().code() == absl::StatusCode::kNotFound) { const ProtoKeySerialization* proto_serialization = dynamic_cast(&serialization); util::StatusOr proto_key = internal::LegacyProtoKey::Create( *proto_serialization, InsecureSecretKeyAccess::Get()); if (!proto_key.ok()) return proto_key.status(); return {absl::make_unique(*proto_key)}; } if (!key.ok()) return key.status(); return key; } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/mutable_serialization_registry.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_MUTABLE_SERIALIZATION_REGISTRY_H_ #define TINK_INTERNAL_MUTABLE_SERIALIZATION_REGISTRY_H_ #include #include "absl/base/thread_annotations.h" #include "absl/synchronization/mutex.h" #include "absl/types/optional.h" #include "tink/internal/key_parser.h" #include "tink/internal/key_serializer.h" #include "tink/internal/parameters_parser.h" #include "tink/internal/parameters_serializer.h" #include "tink/internal/serialization.h" #include "tink/internal/serialization_registry.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/secret_key_access_token.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { // This class provides a global, mutable serialization registry by wrapping an // instance of an immutable `SerializationRegistry`. This registry will enable // the Tink 2.0 C++ Keyset API in the near term. class MutableSerializationRegistry { public: // Returns the global serialization registry. static MutableSerializationRegistry& GlobalInstance(); // Registers parameters `parser`. Returns an error if a different parameters // parser with the same parser index has already been registered. util::Status RegisterParametersParser(ParametersParser* parser) ABSL_LOCKS_EXCLUDED(registry_mutex_); // Registers parameters `serializer`. Returns an error if a different // parameters serializer with the same serializer index has already been // registered. util::Status RegisterParametersSerializer(ParametersSerializer* serializer) ABSL_LOCKS_EXCLUDED(registry_mutex_); // Registers key `parser`. Returns an error if a different key parser with the // same parser index has already been registered. util::Status RegisterKeyParser(KeyParser* parser) ABSL_LOCKS_EXCLUDED(registry_mutex_); // Registers key `serializer`. Returns an error if a different key serializer // with the same serializer index has already been registered. util::Status RegisterKeySerializer(KeySerializer* serializer) ABSL_LOCKS_EXCLUDED(registry_mutex_); // Parses `serialization` into a `Parameters` instance. util::StatusOr> ParseParameters( const Serialization& serialization) ABSL_LOCKS_EXCLUDED(registry_mutex_); // Serializes `parameters` into a `Serialization` instance. template util::StatusOr> SerializeParameters( const Parameters& parameters) ABSL_LOCKS_EXCLUDED(registry_mutex_) { absl::ReaderMutexLock lock(®istry_mutex_); return registry_.SerializeParameters(parameters); } // Parses `serialization` into a `Key` instance. util::StatusOr> ParseKey( const Serialization& serialization, absl::optional token) ABSL_LOCKS_EXCLUDED(registry_mutex_); // Similar to `ParseKey` but falls back to legacy proto key serialization if // the corresponding key parser is not found. util::StatusOr> ParseKeyWithLegacyFallback( const Serialization& serialization, SecretKeyAccessToken token); // Serializes `parameters` into a `Serialization` instance. template util::StatusOr> SerializeKey( const Key& key, absl::optional token) ABSL_LOCKS_EXCLUDED(registry_mutex_) { absl::ReaderMutexLock lock(®istry_mutex_); return registry_.SerializeKey(key, token); } // Resets to a new empty registry. void Reset() ABSL_LOCKS_EXCLUDED(registry_mutex_) { absl::WriterMutexLock lock(®istry_mutex_); registry_ = SerializationRegistry(); } private: mutable absl::Mutex registry_mutex_; // Simple wrappers around const methods of `registry_` may safely acquire a // shared (reader) lock. Other calls require an exclusive (writer) lock. SerializationRegistry registry_ ABSL_GUARDED_BY(registry_mutex_); }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_MUTABLE_SERIALIZATION_REGISTRY_H_ ================================================ FILE: cc/internal/mutable_serialization_registry_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/mutable_serialization_registry.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/key_parser.h" #include "tink/internal/key_serializer.h" #include "tink/internal/parameters_parser.h" #include "tink/internal/parameters_serializer.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/serialization.h" #include "tink/internal/serialization_test_util.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/restricted_data.h" #include "tink/secret_key_access_token.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::IsFalse; using ::testing::IsTrue; TEST(MutableSerializationRegistryTest, ParseParameters) { MutableSerializationRegistry registry; ParametersParserImpl parser1(kNoIdTypeUrl, ParseNoIdParams); ParametersParserImpl parser2(kIdTypeUrl, ParseIdParams); ASSERT_THAT(registry.RegisterParametersParser(&parser1), IsOk()); ASSERT_THAT(registry.RegisterParametersParser(&parser2), IsOk()); util::StatusOr> no_id_params = registry.ParseParameters(NoIdSerialization()); ASSERT_THAT(no_id_params, IsOk()); EXPECT_THAT((*no_id_params)->HasIdRequirement(), IsFalse()); EXPECT_THAT(std::type_index(typeid(**no_id_params)), std::type_index(typeid(NoIdParams))); util::StatusOr> id_params = registry.ParseParameters(IdParamsSerialization()); ASSERT_THAT(id_params, IsOk()); EXPECT_THAT((*id_params)->HasIdRequirement(), IsTrue()); EXPECT_THAT(std::type_index(typeid(**id_params)), std::type_index(typeid(IdParams))); } TEST(MutableSerializationRegistryTest, ParseParametersWithoutRegistration) { MutableSerializationRegistry registry; ASSERT_THAT(registry.ParseParameters(NoIdSerialization()).status(), StatusIs(absl::StatusCode::kNotFound)); } TEST(MutableSerializationRegistryTest, RegisterSameParametersParser) { MutableSerializationRegistry registry; ParametersParserImpl parser(kNoIdTypeUrl, ParseNoIdParams); EXPECT_THAT(registry.RegisterParametersParser(&parser), IsOk()); EXPECT_THAT(registry.RegisterParametersParser(&parser), IsOk()); } TEST(MutableSerializationRegistryTest, RegisterDifferentParametersParserWithSameIndex) { MutableSerializationRegistry registry; ParametersParserImpl parser1(kNoIdTypeUrl, ParseNoIdParams); ParametersParserImpl parser2(kNoIdTypeUrl, ParseNoIdParams); EXPECT_THAT(registry.RegisterParametersParser(&parser1), IsOk()); EXPECT_THAT(registry.RegisterParametersParser(&parser2), StatusIs(absl::StatusCode::kAlreadyExists)); } TEST(MutableSerializationRegistryTest, SerializeParameters) { MutableSerializationRegistry registry; ParametersSerializerImpl serializer1( kNoIdTypeUrl, SerializeNoIdParams); ParametersSerializerImpl serializer2( kIdTypeUrl, SerializeIdParams); ASSERT_THAT(registry.RegisterParametersSerializer(&serializer1), IsOk()); ASSERT_THAT(registry.RegisterParametersSerializer(&serializer2), IsOk()); util::StatusOr> serialization1 = registry.SerializeParameters(NoIdParams()); ASSERT_THAT(serialization1, IsOk()); EXPECT_THAT((*serialization1)->ObjectIdentifier(), Eq(kNoIdTypeUrl)); util::StatusOr> serialization2 = registry.SerializeParameters(IdParams()); ASSERT_THAT(serialization2, IsOk()); EXPECT_THAT((*serialization2)->ObjectIdentifier(), Eq(kIdTypeUrl)); } TEST(MutableSerializationRegistryTest, SerializeParametersWithoutRegistration) { MutableSerializationRegistry registry; ASSERT_THAT( registry.SerializeParameters(NoIdParams()).status(), StatusIs(absl::StatusCode::kNotFound)); } TEST(MutableSerializationRegistryTest, RegisterSameParametersSerializer) { MutableSerializationRegistry registry; ParametersSerializerImpl serializer( kNoIdTypeUrl, SerializeNoIdParams); EXPECT_THAT(registry.RegisterParametersSerializer(&serializer), IsOk()); EXPECT_THAT(registry.RegisterParametersSerializer(&serializer), IsOk()); } TEST(MutableSerializationRegistryTest, RegisterDifferentParametersSerializerWithSameIndex) { MutableSerializationRegistry registry; ParametersSerializerImpl serializer1( kNoIdTypeUrl, SerializeNoIdParams); ParametersSerializerImpl serializer2( kNoIdTypeUrl, SerializeNoIdParams); EXPECT_THAT(registry.RegisterParametersSerializer(&serializer1), IsOk()); EXPECT_THAT(registry.RegisterParametersSerializer(&serializer2), StatusIs(absl::StatusCode::kAlreadyExists)); } TEST(MutableSerializationRegistryTest, ParseKey) { MutableSerializationRegistry registry; KeyParserImpl parser1(kNoIdTypeUrl, ParseNoIdKey); KeyParserImpl parser2(kIdTypeUrl, ParseIdKey); ASSERT_THAT(registry.RegisterKeyParser(&parser1), IsOk()); ASSERT_THAT(registry.RegisterKeyParser(&parser2), IsOk()); util::StatusOr> no_id_key = registry.ParseKey(NoIdSerialization(), InsecureSecretKeyAccess::Get()); ASSERT_THAT(no_id_key, IsOk()); EXPECT_THAT(std::type_index(typeid(**no_id_key)), std::type_index(typeid(NoIdKey))); util::StatusOr> id_key = registry.ParseKey( IdKeySerialization(/*id=*/123), InsecureSecretKeyAccess::Get()); ASSERT_THAT(id_key, IsOk()); EXPECT_THAT(std::type_index(typeid(**id_key)), std::type_index(typeid(IdKey))); EXPECT_THAT((*id_key)->GetIdRequirement(), Eq(123)); } TEST(MutableSerializationRegistryTest, ParseKeyNoSecretAccess) { MutableSerializationRegistry registry; KeyParserImpl parser(kNoIdTypeUrl, ParseNoIdKey); ASSERT_THAT(registry.RegisterKeyParser(&parser), IsOk()); util::StatusOr> no_id_public_key = registry.ParseKey(NoIdSerialization(), absl::nullopt); ASSERT_THAT(no_id_public_key, IsOk()); EXPECT_THAT(std::type_index(typeid(**no_id_public_key)), std::type_index(typeid(NoIdKey))); } TEST(MutableSerializationRegistryTest, ParseKeyWithLegacyFallback) { MutableSerializationRegistry registry; KeyParserImpl parser(kIdTypeUrl, ParseIdKey); ASSERT_THAT(registry.RegisterKeyParser(&parser), IsOk()); // Parse key with registered key parser. util::StatusOr> id_key = registry.ParseKeyWithLegacyFallback(IdKeySerialization(/*id=*/123), InsecureSecretKeyAccess::Get()); ASSERT_THAT(id_key, IsOk()); EXPECT_THAT(std::type_index(typeid(**id_key)), std::type_index(typeid(IdKey))); EXPECT_THAT((*id_key)->GetIdRequirement(), Eq(123)); RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/456); ASSERT_THAT(serialization.status(), IsOk()); // Fall back to legacy proto key. util::StatusOr> proto_key = registry.ParseKeyWithLegacyFallback(*serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(proto_key, IsOk()); EXPECT_THAT((*proto_key)->GetIdRequirement(), Eq(456)); } TEST(MutableSerializationRegistryTest, ParseKeyWithoutRegistration) { MutableSerializationRegistry registry; ASSERT_THAT( registry.ParseKey(NoIdSerialization(), InsecureSecretKeyAccess::Get()) .status(), StatusIs(absl::StatusCode::kNotFound)); } TEST(MutableSerializationRegistryTest, RegisterSameKeyParser) { MutableSerializationRegistry registry; KeyParserImpl parser(kNoIdTypeUrl, ParseNoIdKey); EXPECT_THAT(registry.RegisterKeyParser(&parser), IsOk()); EXPECT_THAT(registry.RegisterKeyParser(&parser), IsOk()); } TEST(MutableSerializationRegistryTest, RegisterDifferentKeyParserWithSameIndex) { MutableSerializationRegistry registry; KeyParserImpl parser1(kNoIdTypeUrl, ParseNoIdKey); KeyParserImpl parser2(kNoIdTypeUrl, ParseNoIdKey); EXPECT_THAT(registry.RegisterKeyParser(&parser1), IsOk()); EXPECT_THAT(registry.RegisterKeyParser(&parser2), StatusIs(absl::StatusCode::kAlreadyExists)); } TEST(MutableSerializationRegistryTest, SerializeKey) { MutableSerializationRegistry registry; KeySerializerImpl serializer1(SerializeNoIdKey); KeySerializerImpl serializer2(SerializeIdKey); ASSERT_THAT(registry.RegisterKeySerializer(&serializer1), IsOk()); ASSERT_THAT(registry.RegisterKeySerializer(&serializer2), IsOk()); util::StatusOr> serialization1 = registry.SerializeKey(NoIdKey(), InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization1, IsOk()); EXPECT_THAT((*serialization1)->ObjectIdentifier(), Eq(kNoIdTypeUrl)); util::StatusOr> serialization2 = registry.SerializeKey(IdKey(123), InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization2, IsOk()); EXPECT_THAT((*serialization2)->ObjectIdentifier(), Eq(kIdTypeUrl)); } TEST(MutableSerializationRegistryTest, SerializeKeyNoSecretAccess) { MutableSerializationRegistry registry; KeySerializerImpl serializer(SerializeNoIdKey); ASSERT_THAT(registry.RegisterKeySerializer(&serializer), IsOk()); util::StatusOr> serialization = registry.SerializeKey(NoIdKey(), absl::nullopt); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kNoIdTypeUrl)); } TEST(MutableSerializationRegistryTest, SerializeKeyWithoutRegistration) { MutableSerializationRegistry registry; ASSERT_THAT(registry .SerializeKey( NoIdKey(), InsecureSecretKeyAccess::Get()) .status(), StatusIs(absl::StatusCode::kNotFound)); } TEST(MutableSerializationRegistryTest, RegisterSameKeySerializer) { MutableSerializationRegistry registry; KeySerializerImpl serializer(SerializeNoIdKey); EXPECT_THAT(registry.RegisterKeySerializer(&serializer), IsOk()); EXPECT_THAT(registry.RegisterKeySerializer(&serializer), IsOk()); } TEST(MutableSerializationRegistryTest, RegisterDifferentKeySerializerWithSameIndex) { MutableSerializationRegistry registry; KeySerializerImpl serializer1(SerializeNoIdKey); KeySerializerImpl serializer2(SerializeNoIdKey); EXPECT_THAT(registry.RegisterKeySerializer(&serializer1), IsOk()); EXPECT_THAT(registry.RegisterKeySerializer(&serializer2), StatusIs(absl::StatusCode::kAlreadyExists)); } TEST(MutableSerializationRegistryTest, Reset) { MutableSerializationRegistry registry; ParametersParserImpl params_parser( kNoIdTypeUrl, ParseNoIdParams); ParametersSerializerImpl params_serializer( kNoIdTypeUrl, SerializeNoIdParams); KeyParserImpl key_parser(kNoIdTypeUrl, ParseNoIdKey); KeySerializerImpl key_serializer( SerializeNoIdKey); ASSERT_THAT(registry.RegisterParametersParser(¶ms_parser), IsOk()); ASSERT_THAT(registry.RegisterParametersSerializer(¶ms_serializer), IsOk()); ASSERT_THAT(registry.RegisterKeyParser(&key_parser), IsOk()); ASSERT_THAT(registry.RegisterKeySerializer(&key_serializer), IsOk()); util::StatusOr> params = registry.ParseParameters(NoIdSerialization()); ASSERT_THAT(params, IsOk()); util::StatusOr> serialization1 = registry.SerializeParameters(NoIdParams()); ASSERT_THAT(serialization1, IsOk()); util::StatusOr> key = registry.ParseKey(NoIdSerialization(), InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization2 = registry.SerializeKey(NoIdKey(), InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization2, IsOk()); registry.Reset(); ASSERT_THAT(registry.ParseParameters(NoIdSerialization()).status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT( registry.SerializeParameters(NoIdParams()).status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT( registry.ParseKey(NoIdSerialization(), InsecureSecretKeyAccess::Get()) .status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(registry .SerializeKey( NoIdKey(), InsecureSecretKeyAccess::Get()) .status(), StatusIs(absl::StatusCode::kNotFound)); } TEST(MutableSerializationRegistryTest, GlobalInstance) { MutableSerializationRegistry::GlobalInstance().Reset(); ParametersParserImpl parser(kNoIdTypeUrl, ParseNoIdParams); ASSERT_THAT( MutableSerializationRegistry::GlobalInstance().RegisterParametersParser( &parser), IsOk()); util::StatusOr> params = MutableSerializationRegistry::GlobalInstance().ParseParameters( NoIdSerialization()); ASSERT_THAT(params, IsOk()); EXPECT_THAT((*params)->HasIdRequirement(), IsFalse()); EXPECT_THAT(std::type_index(typeid(**params)), std::type_index(typeid(NoIdParams))); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/parameters_parser.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_PARAMETERS_PARSER_H_ #define TINK_INTERNAL_PARAMETERS_PARSER_H_ #include #include #include #include #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/internal/parser_index.h" #include "tink/internal/serialization.h" #include "tink/parameters.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { // Non-template base class that can be used with internal registry map. class ParametersParser { public: // Parses `serialization` into a parameters object. // // This function is usually called on a `Serialization` subclass matching the // value returned by `ObjectIdentifier()`. However, implementations should // verify that this is the case. virtual util::StatusOr> ParseParameters( const Serialization& serialization) const = 0; // Returns the object identifier for `SerializationT`, which is only valid // for the lifetime of this object. // // The object identifier is a unique identifier per registry for this object // (in the standard proto serialization, it is the type URL). In other words, // when registering a `ParametersParser`, the registry will invoke this to get // the handled object identifier. In order to parse an object of // `SerializationT`, the registry will then obtain the object identifier of // this serialization object, and call the parser corresponding to this // object. virtual absl::string_view ObjectIdentifier() const = 0; // Returns an index that can be used to look up the `ParametersParser` // object registered for the `ParametersT` type in a registry. virtual ParserIndex Index() const = 0; virtual ~ParametersParser() = default; }; // Parses `SerializationT` objects into `ParametersT` objects. template class ParametersParserImpl : public ParametersParser { public: explicit ParametersParserImpl( absl::string_view object_identifier, const std::function(SerializationT)>& function) : object_identifier_(object_identifier), function_(function) {} util::StatusOr> ParseParameters( const Serialization& serialization) const override { if (serialization.ObjectIdentifier() != object_identifier_) { return util::Status( absl::StatusCode::kInvalidArgument, "Invalid object identifier for this parameters parser."); } const SerializationT* st = dynamic_cast(&serialization); if (st == nullptr) { return util::Status( absl::StatusCode::kInvalidArgument, "Invalid serialization type for this parameters parser."); } util::StatusOr parameters = function_(*st); if (!parameters.ok()) return parameters.status(); return {absl::make_unique(std::move(*parameters))}; } absl::string_view ObjectIdentifier() const override { return object_identifier_; } ParserIndex Index() const override { return ParserIndex::Create(object_identifier_); } private: std::string object_identifier_; std::function(SerializationT)> function_; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_PARAMETERS_PARSER_H_ ================================================ FILE: cc/internal/parameters_parser_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/parameters_parser.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/internal/parser_index.h" #include "tink/internal/serialization.h" #include "tink/internal/serialization_test_util.h" #include "tink/parameters.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::IsFalse; TEST(ParametersParserTest, Create) { std::unique_ptr parser = absl::make_unique>( kNoIdTypeUrl, ParseNoIdParams); EXPECT_THAT(parser->ObjectIdentifier(), Eq(kNoIdTypeUrl)); EXPECT_THAT(parser->Index(), Eq(ParserIndex::Create(kNoIdTypeUrl))); } TEST(ParametersParserTest, ParseParameters) { std::unique_ptr parser = absl::make_unique>( kNoIdTypeUrl, ParseNoIdParams); NoIdSerialization serialization; util::StatusOr> params = parser->ParseParameters(serialization); ASSERT_THAT(params, IsOk()); EXPECT_THAT((*params)->HasIdRequirement(), IsFalse()); } TEST(ParametersParserTest, ParseParametersWithInvalidSerializationType) { std::unique_ptr parser = absl::make_unique>( kNoIdTypeUrl, ParseNoIdParams); IdParamsSerialization serialization; util::StatusOr> params = parser->ParseParameters(serialization); ASSERT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(ParametersParserTest, ParseParametersWithInvalidObjectIdentifier) { std::unique_ptr parser = absl::make_unique>( "mismatched_type_url", ParseNoIdParams); IdParamsSerialization serialization; util::StatusOr> params = parser->ParseParameters(serialization); ASSERT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/parameters_serializer.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_PARAMETERS_SERIALIZER_H_ #define TINK_INTERNAL_PARAMETERS_SERIALIZER_H_ #include #include #include #include #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/internal/serialization.h" #include "tink/internal/serializer_index.h" #include "tink/parameters.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { // Non-template base class that can be used with internal registry map. class ParametersSerializer { public: // Returns the serialization of `parameters`. virtual util::StatusOr> SerializeParameters( const Parameters& parameters) const = 0; // Returns the object identifier for this serialization, which is only valid // for the lifetime of this object. // // The object identifier is a unique identifier per registry for this object // (in the standard proto serialization, it is the type URL). In other words, // when registering a `ParametersSerializer`, the registry will invoke this to // get the handled object identifier. In order to serialize an object of // `ParametersT`, the registry will then obtain the object identifier of // this serialization object, and call the serializer corresponding to this // object. virtual absl::string_view ObjectIdentifier() const = 0; // Returns an index that can be used to look up the `ParametersSerializer` // object registered for the `ParametersT` type in a registry. virtual SerializerIndex Index() const = 0; virtual ~ParametersSerializer() = default; }; // Serializes `ParametersT` objects into `SerializationT` objects. template class ParametersSerializerImpl : public ParametersSerializer { public: explicit ParametersSerializerImpl( absl::string_view object_identifier, const std::function(ParametersT)>& function) : object_identifier_(object_identifier), function_(function) {} util::StatusOr> SerializeParameters( const Parameters& parameters) const override { const ParametersT* pt = dynamic_cast(¶meters); if (pt == nullptr) { return util::Status( absl::StatusCode::kInvalidArgument, "Invalid parameters type for this parameters serializer."); } util::StatusOr serialization = function_(*pt); if (!serialization.ok()) return serialization.status(); return {absl::make_unique(std::move(*serialization))}; } absl::string_view ObjectIdentifier() const override { return object_identifier_; } SerializerIndex Index() const override { return SerializerIndex::Create(); } private: std::string object_identifier_; std::function(ParametersT)> function_; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_PARAMETERS_SERIALIZER_H_ ================================================ FILE: cc/internal/parameters_serializer_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/parameters_serializer.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/internal/serialization.h" #include "tink/internal/serialization_test_util.h" #include "tink/internal/serializer_index.h" #include "tink/parameters.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; TEST(ParametersSerializerTest, Create) { std::unique_ptr serializer = absl::make_unique< ParametersSerializerImpl>( kNoIdTypeUrl, SerializeNoIdParams); EXPECT_THAT(serializer->ObjectIdentifier(), Eq(kNoIdTypeUrl)); EXPECT_THAT(serializer->Index(), Eq(SerializerIndex::Create())); } TEST(ParametersSerializerTest, SerializeParameters) { std::unique_ptr serializer = absl::make_unique< ParametersSerializerImpl>( kNoIdTypeUrl, SerializeNoIdParams); NoIdParams parameters; util::StatusOr> serialization = serializer->SerializeParameters(parameters); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kNoIdTypeUrl)); } TEST(ParametersSerializerTest, SerializeParametersWithInvalidParametersType) { std::unique_ptr serializer = absl::make_unique< ParametersSerializerImpl>( kNoIdTypeUrl, SerializeNoIdParams); IdParams parameters; util::StatusOr> serialization = serializer->SerializeParameters(parameters); ASSERT_THAT(serialization.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/parser_index.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_PARSER_INDEX_H_ #define TINK_INTERNAL_PARSER_INDEX_H_ #include #include #include "absl/strings/string_view.h" #include "tink/internal/serialization.h" namespace crypto { namespace tink { namespace internal { class ParserIndex { public: // Create registry lookup key for a `SerializationT` type object with // `object_identifier`. Useful for key and parameters parsers. template static ParserIndex Create(absl::string_view object_identifier) { return ParserIndex(std::type_index(typeid(SerializationT)), object_identifier); } // Create registry lookup key for `serialization`. Useful for the // serialization registry. static ParserIndex Create(const Serialization& serialization) { return ParserIndex(std::type_index(typeid(serialization)), serialization.ObjectIdentifier()); } // Returns true if serialization type index and object identifier match. bool operator==(const ParserIndex& other) const { return index_ == other.index_ && object_identifier_ == other.object_identifier_; } // Required function to make `ParserIndex` hashable for Abseil hash maps. template friend H AbslHashValue(H h, const ParserIndex& index) { return H::combine(std::move(h), index.index_, index.object_identifier_); } private: ParserIndex(std::type_index index, absl::string_view object_identifier) : index_(index), object_identifier_(object_identifier) {} std::type_index index_; std::string object_identifier_; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_PARSER_INDEX_H_ ================================================ FILE: cc/internal/parser_index_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/parser_index.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/string_view.h" #include "tink/internal/serialization.h" namespace crypto { namespace tink { namespace internal { using ::testing::Eq; using ::testing::Not; class ExampleSerialization : public Serialization { public: explicit ExampleSerialization(absl::string_view object_identifier) : object_identifier_(object_identifier) {} absl::string_view ObjectIdentifier() const override { return object_identifier_; } protected: std::string object_identifier_; }; class DifferentSerialization : public ExampleSerialization { public: explicit DifferentSerialization(absl::string_view object_identifier) : ExampleSerialization(object_identifier) {} }; TEST(ParserIndex, CreateEquivalent) { ASSERT_THAT(ParserIndex::Create("id"), Eq(ParserIndex::Create("id"))); ASSERT_THAT(ParserIndex::Create("id"), Eq(ParserIndex::Create(ExampleSerialization("id")))); ASSERT_THAT(ParserIndex::Create(ExampleSerialization("id")), Eq(ParserIndex::Create(ExampleSerialization("id")))); } TEST(ParserIndex, CreateWithDifferentObjectIdentifier) { ASSERT_THAT( ParserIndex::Create("id"), Not(Eq(ParserIndex::Create("different id")))); ASSERT_THAT( ParserIndex::Create(ExampleSerialization("id")), Not(Eq(ParserIndex::Create(ExampleSerialization("different id"))))); } TEST(ParserIndex, CreateWithDifferentSerializationType) { ASSERT_THAT(ParserIndex::Create("id"), Not(Eq(ParserIndex::Create("id")))); ASSERT_THAT(ParserIndex::Create(ExampleSerialization("id")), Not(Eq(ParserIndex::Create(DifferentSerialization("id"))))); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/proto_key_serialization.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/proto_key_serialization.h" #include #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/internal/util.h" #include "tink/restricted_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; util::StatusOr ProtoKeySerialization::Create( absl::string_view type_url, RestrictedData serialized_key, KeyData::KeyMaterialType key_material_type, OutputPrefixType output_prefix_type, absl::optional id_requirement) { if (!IsPrintableAscii(type_url)) { return util::Status(absl::StatusCode::kInvalidArgument, "Non-printable ASCII character in type URL."); } if (output_prefix_type == OutputPrefixType::RAW && id_requirement.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Keys with a RAW output prefix type should not have an " "ID requirement."); } if (output_prefix_type != OutputPrefixType::RAW && !id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Keys without a RAW output prefix type should have an ID requirement."); } return ProtoKeySerialization(type_url, type_url, std::move(serialized_key), key_material_type, output_prefix_type, id_requirement); } bool ProtoKeySerialization::EqualsWithPotentialFalseNegatives( const ProtoKeySerialization& other) const { if (type_url_ != other.type_url_) return false; if (object_identifier_ != other.object_identifier_) return false; if (key_material_type_ != other.key_material_type_) return false; if (output_prefix_type_ != other.output_prefix_type_) return false; if (id_requirement_ != other.id_requirement_) return false; // RestrictedData::operator== is a constant-time comparison. return serialized_key_ == other.serialized_key_; } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/proto_key_serialization.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_PROTO_KEY_SERIALIZATION_H_ #define TINK_INTERNAL_PROTO_KEY_SERIALIZATION_H_ #include #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/internal/serialization.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { // Represents a `Key` object serialized with binary protocol buffer // serialization. class ProtoKeySerialization : public Serialization { public: // Copyable and movable. ProtoKeySerialization(const ProtoKeySerialization& other) = default; ProtoKeySerialization& operator=(const ProtoKeySerialization& other) = default; ProtoKeySerialization(ProtoKeySerialization&& other) = default; ProtoKeySerialization& operator=(ProtoKeySerialization&& other) = default; // Creates a `ProtoKeySerialization` object from individual components. static util::StatusOr Create( absl::string_view type_url, RestrictedData serialized_key, google::crypto::tink::KeyData::KeyMaterialType key_material_type, google::crypto::tink::OutputPrefixType output_prefix_type, absl::optional id_requirement); // Returned value is only valid for the lifetime of this object. absl::string_view TypeUrl() const { return type_url_; } // Returned value is only valid for the lifetime of this object. absl::string_view ObjectIdentifier() const override { return object_identifier_; } // Returned value is only valid for the lifetime of this object. const RestrictedData& SerializedKeyProto() const { return serialized_key_; } google::crypto::tink::KeyData::KeyMaterialType KeyMaterialType() const { return key_material_type_; } google::crypto::tink::OutputPrefixType GetOutputPrefixType() const { return output_prefix_type_; } absl::optional IdRequirement() const { return id_requirement_; } private: friend class ProtoKeySerializationTest; friend class LegacyProtoKey; friend class LegacyProtoKeyTest; ProtoKeySerialization( absl::string_view type_url, absl::string_view object_identifier, RestrictedData serialized_key, google::crypto::tink::KeyData::KeyMaterialType key_material_type, google::crypto::tink::OutputPrefixType output_prefix_type, absl::optional id_requirement) : type_url_(type_url), object_identifier_(object_identifier), serialized_key_(std::move(serialized_key)), key_material_type_(key_material_type), output_prefix_type_(output_prefix_type), id_requirement_(id_requirement) {} // Returns `true` if this `ProtoKeySerialization` object is equal to // `other` (with the possibility of false negatives due to lack of // determinism during serialization). Should only be used temporarily by the // `LegacyKeyParameters` class. bool EqualsWithPotentialFalseNegatives( const ProtoKeySerialization& other) const; std::string type_url_; std::string object_identifier_; RestrictedData serialized_key_; google::crypto::tink::KeyData::KeyMaterialType key_material_type_; google::crypto::tink::OutputPrefixType output_prefix_type_; absl::optional id_requirement_; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_PROTO_KEY_SERIALIZATION_H_ ================================================ FILE: cc/internal/proto_key_serialization_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/proto_key_serialization.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/insecure_secret_key_access.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::IsFalse; using ::testing::IsTrue; class ProtoKeySerializationTest : public ::testing::Test { protected: bool Equals(ProtoKeySerialization serialization, ProtoKeySerialization other) { return serialization.EqualsWithPotentialFalseNegatives(other); } }; TEST_F(ProtoKeySerializationTest, CreateWithIdRequirement) { RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(serialization.status(), IsOk()); EXPECT_THAT(serialization->TypeUrl(), Eq("type_url")); EXPECT_THAT(serialization->SerializedKeyProto(), Eq(serialized_key)); EXPECT_THAT(serialization->KeyMaterialType(), Eq(KeyData::SYMMETRIC)); EXPECT_THAT(serialization->GetOutputPrefixType(), Eq(OutputPrefixType::TINK)); EXPECT_THAT(serialization->IdRequirement(), Eq(12345)); EXPECT_THAT(serialization->ObjectIdentifier(), Eq("type_url")); } TEST_F(ProtoKeySerializationTest, CreateWithoutIdRequirement) { RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::RAW, /*id_requirement=*/absl::nullopt); ASSERT_THAT(serialization.status(), IsOk()); EXPECT_THAT(serialization->TypeUrl(), Eq("type_url")); EXPECT_THAT(serialization->SerializedKeyProto(), Eq(serialized_key)); EXPECT_THAT(serialization->KeyMaterialType(), Eq(KeyData::SYMMETRIC)); EXPECT_THAT(serialization->GetOutputPrefixType(), Eq(OutputPrefixType::RAW)); EXPECT_THAT(serialization->IdRequirement(), Eq(absl::nullopt)); EXPECT_THAT(serialization->ObjectIdentifier(), Eq("type_url")); } TEST_F(ProtoKeySerializationTest, OutputPrefixIncompatibleWithIdRequirement) { RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr tink_without_id = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/absl::nullopt); ASSERT_THAT(tink_without_id.status(), StatusIs(absl::StatusCode::kInvalidArgument)); util::StatusOr raw_with_id = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::RAW, /*id_requirement=*/12345); ASSERT_THAT(raw_with_id.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(ProtoKeySerializationTest, Equals) { RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr other_serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(other_serialization.status(), IsOk()); EXPECT_THAT(Equals(*serialization, *other_serialization), IsTrue()); } TEST_F(ProtoKeySerializationTest, TypeUrlAndObjectIdentifierNotEqual) { RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr other_serialization = ProtoKeySerialization::Create("different_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(other_serialization.status(), IsOk()); EXPECT_THAT(Equals(*serialization, *other_serialization), IsFalse()); } TEST_F(ProtoKeySerializationTest, SerializedKeyNotEqual) { util::StatusOr serialization = ProtoKeySerialization::Create( "type_url", RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()), KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr other_serialization = ProtoKeySerialization::Create( "type_url", RestrictedData("different_key", InsecureSecretKeyAccess::Get()), KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(other_serialization.status(), IsOk()); EXPECT_THAT(Equals(*serialization, *other_serialization), IsFalse()); } TEST_F(ProtoKeySerializationTest, KeyMaterialTypeNotEqual) { RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr other_serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::REMOTE, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(other_serialization.status(), IsOk()); EXPECT_THAT(Equals(*serialization, *other_serialization), IsFalse()); } TEST_F(ProtoKeySerializationTest, OutputPrefixTypeNotEqual) { RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr other_serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::CRUNCHY, /*id_requirement=*/12345); EXPECT_THAT(Equals(*serialization, *other_serialization), IsFalse()); } TEST_F(ProtoKeySerializationTest, IdRequirementNotEqual) { RestrictedData serialized_key = RestrictedData("serialized_key", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr other_serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/6789); ASSERT_THAT(other_serialization.status(), IsOk()); EXPECT_THAT(Equals(*serialization, *other_serialization), IsFalse()); } TEST_F(ProtoKeySerializationTest, AssignSecretToStringView) { RestrictedData serialized_key = RestrictedData("secret", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = ProtoKeySerialization::Create("type_url", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/12345); ASSERT_THAT(serialization.status(), IsOk()); ASSERT_THAT(serialization->SerializedKeyProto(), Eq(serialized_key)); ASSERT_THAT(serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get()), Eq("secret")); absl::string_view secret = serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get()); EXPECT_THAT(secret, Eq("secret")); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/proto_parameters_serialization.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/proto_parameters_serialization.h" #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/internal/util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::OutputPrefixType; util::StatusOr ProtoParametersSerialization::Create(absl::string_view type_url, OutputPrefixType output_prefix_type, absl::string_view serialized_proto) { if (!IsPrintableAscii(type_url)) { return util::Status(absl::StatusCode::kInvalidArgument, "Non-printable ASCII character in type URL."); } KeyTemplate key_template; key_template.set_type_url(std::string(type_url)); key_template.set_output_prefix_type(output_prefix_type); key_template.set_value(std::string(serialized_proto)); return ProtoParametersSerialization(key_template); } util::StatusOr ProtoParametersSerialization::Create(KeyTemplate key_template) { if (!IsPrintableAscii(key_template.type_url())) { return util::Status(absl::StatusCode::kInvalidArgument, "Non-printable ASCII character in type URL."); } return ProtoParametersSerialization(key_template); } bool ProtoParametersSerialization::EqualsWithPotentialFalseNegatives( const ProtoParametersSerialization& other) const { const ProtoParametersSerialization* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (key_template_.type_url() != that->key_template_.type_url()) { return false; } if (key_template_.output_prefix_type() != that->key_template_.output_prefix_type()) { return false; } if (key_template_.value() != that->key_template_.value()) { return false; } if (object_identifier_ != that->object_identifier_) { return false; } return true; } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/proto_parameters_serialization.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_PROTO_PARAMETERS_SERIALIZATION_H_ #define TINK_INTERNAL_PROTO_PARAMETERS_SERIALIZATION_H_ #include #include "absl/strings/string_view.h" #include "tink/internal/serialization.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { // Represents a `Parameters` object serialized with binary protocol buffer // serialization. class ProtoParametersSerialization : public Serialization { public: // Copyable and movable. ProtoParametersSerialization(const ProtoParametersSerialization& other) = default; ProtoParametersSerialization& operator=( const ProtoParametersSerialization& other) = default; ProtoParametersSerialization(ProtoParametersSerialization&& other) = default; ProtoParametersSerialization& operator=( ProtoParametersSerialization&& other) = default; // Creates a `ProtoParametersSerialization` object from individual components. static util::StatusOr Create( absl::string_view type_url, google::crypto::tink::OutputPrefixType output_prefix_type, absl::string_view serialized_proto); // Creates a `ProtoParametersSerialization` object from a key template. static util::StatusOr Create( google::crypto::tink::KeyTemplate key_template); const google::crypto::tink::KeyTemplate& GetKeyTemplate() const { return key_template_; } absl::string_view ObjectIdentifier() const override { return object_identifier_; } private: // The following friend classes require access to // `EqualsWithPotentialFalseNegatives()`. friend class ProtoParametersSerializationTest; friend class LegacyProtoParameters; friend class LegacyProtoParametersTest; explicit ProtoParametersSerialization( google::crypto::tink::KeyTemplate key_template) : key_template_(key_template), object_identifier_(key_template.type_url()) {} // Returns `true` if this `ProtoParametersSerialization` object is equal to // `other` (with the possibility of false negatives due to lack of // determinism during serialization). Should only be used temporarily by the // `LegacyProtoParameters` class. bool EqualsWithPotentialFalseNegatives( const ProtoParametersSerialization& other) const; google::crypto::tink::KeyTemplate key_template_; std::string object_identifier_; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_PROTO_PARAMETERS_SERIALIZATION_H_ ================================================ FILE: cc/internal/proto_parameters_serialization_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/proto_parameters_serialization.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/test_proto.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { using ::crypto::tink::test::IsOk; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::OutputPrefixType; using ::google::crypto::tink::TestProto; using ::testing::Eq; using ::testing::IsFalse; using ::testing::IsTrue; class ProtoParametersSerializationTest : public ::testing::Test { protected: bool Equals(ProtoParametersSerialization serialization, ProtoParametersSerialization other) { return serialization.EqualsWithPotentialFalseNegatives(other); } }; TEST_F(ProtoParametersSerializationTest, CreateFromIndividualComponents) { TestProto test_proto; test_proto.set_num(12345); util::StatusOr serialization = ProtoParametersSerialization::Create("type_url", OutputPrefixType::RAW, test_proto.SerializeAsString()); ASSERT_THAT(serialization.status(), IsOk()); EXPECT_THAT(serialization->ObjectIdentifier(), "type_url"); EXPECT_THAT(serialization->GetKeyTemplate().type_url(), "type_url"); EXPECT_THAT(serialization->GetKeyTemplate().output_prefix_type(), OutputPrefixType::RAW); EXPECT_THAT(serialization->GetKeyTemplate().value(), test_proto.SerializeAsString()); TestProto parsed_proto; parsed_proto.ParseFromString(serialization->GetKeyTemplate().value()); EXPECT_THAT(parsed_proto.num(), Eq(12345)); } TEST_F(ProtoParametersSerializationTest, CreateFromKeyTemplate) { TestProto test_proto; test_proto.set_num(12345); KeyTemplate key_template; key_template.set_value(test_proto.SerializeAsString()); key_template.set_output_prefix_type(OutputPrefixType::TINK); key_template.set_type_url("type_url"); util::StatusOr serialization = ProtoParametersSerialization::Create(key_template); ASSERT_THAT(serialization.status(), IsOk()); EXPECT_THAT(serialization->ObjectIdentifier(), "type_url"); EXPECT_THAT(serialization->GetKeyTemplate().type_url(), "type_url"); EXPECT_THAT(serialization->GetKeyTemplate().output_prefix_type(), OutputPrefixType::TINK); EXPECT_THAT(serialization->GetKeyTemplate().value(), test_proto.SerializeAsString()); TestProto parsed_proto; parsed_proto.ParseFromString(serialization->GetKeyTemplate().value()); EXPECT_THAT(parsed_proto.num(), Eq(12345)); } TEST_F(ProtoParametersSerializationTest, Equals) { TestProto test_proto; test_proto.set_num(12345); util::StatusOr serialization = ProtoParametersSerialization::Create("type_url", OutputPrefixType::RAW, test_proto.SerializeAsString()); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr other_serialization = ProtoParametersSerialization::Create("type_url", OutputPrefixType::RAW, test_proto.SerializeAsString()); ASSERT_THAT(other_serialization.status(), IsOk()); EXPECT_THAT(Equals(*serialization, *other_serialization), IsTrue()); } TEST_F(ProtoParametersSerializationTest, TypeUrlNotEqual) { TestProto test_proto; test_proto.set_num(12345); util::StatusOr serialization = ProtoParametersSerialization::Create("type_url", OutputPrefixType::RAW, test_proto.SerializeAsString()); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr other_serialization = ProtoParametersSerialization::Create("other_url", OutputPrefixType::RAW, test_proto.SerializeAsString()); ASSERT_THAT(other_serialization.status(), IsOk()); EXPECT_THAT(Equals(*serialization, *other_serialization), IsFalse()); } TEST_F(ProtoParametersSerializationTest, OutputPrefixTypeNotEqual) { TestProto test_proto; test_proto.set_num(12345); util::StatusOr serialization = ProtoParametersSerialization::Create("type_url", OutputPrefixType::RAW, test_proto.SerializeAsString()); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr other_serialization = ProtoParametersSerialization::Create("type_url", OutputPrefixType::TINK, test_proto.SerializeAsString()); ASSERT_THAT(other_serialization.status(), IsOk()); EXPECT_THAT(Equals(*serialization, *other_serialization), IsFalse()); } TEST_F(ProtoParametersSerializationTest, DifferentValueNotEqual) { TestProto test_proto; test_proto.set_num(12345); TestProto other_proto; other_proto.set_num(67890); util::StatusOr serialization = ProtoParametersSerialization::Create("type_url", OutputPrefixType::RAW, test_proto.SerializeAsString()); ASSERT_THAT(serialization.status(), IsOk()); util::StatusOr other_serialization = ProtoParametersSerialization::Create("type_url", OutputPrefixType::RAW, other_proto.SerializeAsString()); ASSERT_THAT(other_serialization.status(), IsOk()); EXPECT_THAT(Equals(*serialization, *other_serialization), IsFalse()); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/registry_impl.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/registry_impl.h" #include #include #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" #include "tink/input_stream.h" #include "tink/internal/key_type_info_store.h" #include "tink/internal/keyset_wrapper_store.h" #include "tink/key_manager.h" #include "tink/monitoring/monitoring.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { using ::crypto::tink::MonitoringClientFactory; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::KeyTemplate; util::StatusOr RegistryImpl::get_key_type_info( absl::string_view type_url) const { absl::MutexLock lock(&maps_mutex_); return key_type_info_store_.Get(type_url); } util::StatusOr> RegistryImpl::NewKeyData( const KeyTemplate& key_template) const { util::StatusOr info = get_key_type_info(key_template.type_url()); if (!info.ok()) { return info.status(); } if (!(*info)->new_key_allowed()) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("KeyManager for type ", key_template.type_url(), " does not allow for creation of new keys.")); } return (*info)->key_factory().NewKeyData(key_template.value()); } util::StatusOr> RegistryImpl::GetPublicKeyData( absl::string_view type_url, absl::string_view serialized_private_key) const { util::StatusOr info = get_key_type_info(type_url); if (!info.ok()) { return info.status(); } auto factory = dynamic_cast(&(*info)->key_factory()); if (factory == nullptr) { return ToStatusF(absl::StatusCode::kInvalidArgument, "KeyManager for type '%s' does not have " "a PrivateKeyFactory.", type_url); } auto result = factory->GetPublicKeyData(serialized_private_key); return result; } util::StatusOr RegistryImpl::DeriveKey(const KeyTemplate& key_template, InputStream* randomness) const { util::StatusOr info = get_key_type_info(key_template.type_url()); if (!info.ok()) { return info.status(); } if (!(*info)->key_deriver()) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Manager for type '", key_template.type_url(), "' cannot derive keys.")); } return (*info)->key_deriver()(key_template.value(), randomness); } util::Status RegistryImpl::RegisterMonitoringClientFactory( std::unique_ptr factory) { if (factory == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "Monitoring factory must not be null"); } absl::MutexLock lock(&monitoring_factory_mutex_); if (GetMonitoringClientFactory() != nullptr) { return util::Status(absl::StatusCode::kAlreadyExists, "A monitoring factory is already registered"); } monitoring_factory_.store(factory.release(), std::memory_order_release); return util::OkStatus(); } void RegistryImpl::Reset() { { absl::MutexLock lock(&maps_mutex_); key_type_info_store_ = KeyTypeInfoStore(); keyset_wrapper_store_ = KeysetWrapperStore(); } { absl::MutexLock lock(&monitoring_factory_mutex_); MonitoringClientFactory* factory = monitoring_factory_.exchange(nullptr); delete factory; } } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/registry_impl.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_REGISTRY_IMPL_H_ #define TINK_INTERNAL_REGISTRY_IMPL_H_ #include #include #include #include #include #include #include "absl/base/thread_annotations.h" #include "absl/container/flat_hash_map.h" #include "absl/functional/any_invocable.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" #include "tink/core/key_type_manager.h" #include "tink/core/private_key_type_manager.h" #include "tink/input_stream.h" #include "tink/internal/fips_utils.h" #include "tink/internal/key_type_info_store.h" #include "tink/internal/keyset_wrapper.h" #include "tink/internal/keyset_wrapper_store.h" #include "tink/key_manager.h" #include "tink/monitoring/monitoring.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { class RegistryImpl { public: static RegistryImpl& GlobalInstance() { static RegistryImpl* instance = new RegistryImpl(); return *instance; } RegistryImpl() = default; RegistryImpl(const RegistryImpl&) = delete; RegistryImpl& operator=(const RegistryImpl&) = delete; ~RegistryImpl() { Reset(); } // Registers the given 'manager' for the key type 'manager->get_key_type()'. // Takes ownership of 'manager', which must be non-nullptr. KeyManager is the // legacy/internal version of KeyTypeManager. template crypto::tink::util::Status RegisterKeyManager(KeyManager

* manager, bool new_key_allowed = true) ABSL_LOCKS_EXCLUDED(maps_mutex_); // Takes ownership of 'manager', which must be non-nullptr. template crypto::tink::util::Status RegisterKeyTypeManager( std::unique_ptr> manager, bool new_key_allowed) ABSL_LOCKS_EXCLUDED(maps_mutex_); // Takes ownership of 'private_manager' and 'public_manager'. Both must be // non-nullptr. template crypto::tink::util::Status RegisterAsymmetricKeyManagers( PrivateKeyTypeManager* private_manager, KeyTypeManager* public_manager, bool new_key_allowed) ABSL_LOCKS_EXCLUDED(maps_mutex_); template crypto::tink::util::StatusOr*> get_key_manager( absl::string_view type_url) const ABSL_LOCKS_EXCLUDED(maps_mutex_); // Takes ownership of 'wrapper', which must be non-nullptr. template crypto::tink::util::Status RegisterPrimitiveWrapper( PrimitiveWrapper* wrapper) ABSL_LOCKS_EXCLUDED(maps_mutex_); template crypto::tink::util::StatusOr> GetPrimitive( const google::crypto::tink::KeyData& key_data) const ABSL_LOCKS_EXCLUDED(maps_mutex_); crypto::tink::util::StatusOr> NewKeyData(const google::crypto::tink::KeyTemplate& key_template) const ABSL_LOCKS_EXCLUDED(maps_mutex_); crypto::tink::util::StatusOr> GetPublicKeyData(absl::string_view type_url, absl::string_view serialized_private_key) const ABSL_LOCKS_EXCLUDED(maps_mutex_); template crypto::tink::util::StatusOr> Wrap( std::unique_ptr> primitive_set) const ABSL_LOCKS_EXCLUDED(maps_mutex_); // Wraps a `keyset` and annotates it with `annotations`. template crypto::tink::util::StatusOr> WrapKeyset( const google::crypto::tink::Keyset& keyset, const absl::flat_hash_map& annotations) const ABSL_LOCKS_EXCLUDED(maps_mutex_); crypto::tink::util::StatusOr DeriveKey( const google::crypto::tink::KeyTemplate& key_template, InputStream* randomness) const ABSL_LOCKS_EXCLUDED(maps_mutex_); void Reset() ABSL_LOCKS_EXCLUDED(maps_mutex_, monitoring_factory_mutex_); crypto::tink::util::Status RestrictToFipsIfEmpty() const ABSL_LOCKS_EXCLUDED(maps_mutex_); // Registers a `monitoring_factory`. Only one factory can be registered, // subsequent calls to this method will return a kAlreadyExists error. crypto::tink::util::Status RegisterMonitoringClientFactory( std::unique_ptr monitoring_factory) ABSL_LOCKS_EXCLUDED(monitoring_factory_mutex_); // Returns a pointer to the registered monitoring factory if any, and nullptr // otherwise. crypto::tink::MonitoringClientFactory* GetMonitoringClientFactory() const { return monitoring_factory_.load(std::memory_order_acquire); } private: // Returns the key type info for a given type URL. Since we never replace // key type infos, the pointers will stay valid for the lifetime of the // binary. crypto::tink::util::StatusOr get_key_type_info( absl::string_view type_url) const ABSL_LOCKS_EXCLUDED(maps_mutex_); mutable absl::Mutex maps_mutex_; // Stores information about key types constructed from their KeyTypeManager or // KeyManager. // Once inserted, KeyTypeInfoStore::Info objects must remain valid for the // lifetime of the binary, and the Info object's pointer stability is // required. Elements in Info, which include the KeyTypeManager or KeyManager, // must not be replaced. KeyTypeInfoStore key_type_info_store_ ABSL_GUARDED_BY(maps_mutex_); // Stores information about keyset wrappers constructed from their // PrimitiveWrapper. KeysetWrapperStore keyset_wrapper_store_ ABSL_GUARDED_BY(maps_mutex_); // Mutex to protect writes to `monitoring_factory_`. mutable absl::Mutex monitoring_factory_mutex_; // Owned. std::atomic monitoring_factory_{ nullptr}; }; template crypto::tink::util::Status RegistryImpl::RegisterKeyManager( KeyManager

* manager, bool new_key_allowed) { auto owned_manager = absl::WrapUnique(manager); if (manager == nullptr) { return crypto::tink::util::Status(absl::StatusCode::kInvalidArgument, "Parameter 'manager' must be non-null."); } absl::MutexLock lock(&maps_mutex_); return key_type_info_store_.AddKeyManager(std::move(owned_manager), new_key_allowed); } template crypto::tink::util::Status RegistryImpl::RegisterKeyTypeManager( std::unique_ptr> manager, bool new_key_allowed) { if (manager == nullptr) { return crypto::tink::util::Status(absl::StatusCode::kInvalidArgument, "Parameter 'manager' must be non-null."); } absl::MutexLock lock(&maps_mutex_); return key_type_info_store_.AddKeyTypeManager(std::move(manager), new_key_allowed); } template crypto::tink::util::Status RegistryImpl::RegisterAsymmetricKeyManagers( PrivateKeyTypeManager* private_manager, KeyTypeManager* public_manager, bool new_key_allowed) ABSL_LOCKS_EXCLUDED(maps_mutex_) { auto owned_private_manager = absl::WrapUnique(private_manager); auto owned_public_manager = absl::WrapUnique(public_manager); if (private_manager == nullptr) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, "Parameter 'private_manager' must be non-null."); } if (public_manager == nullptr) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, "Parameter 'public_manager' must be non-null."); } absl::MutexLock lock(&maps_mutex_); return key_type_info_store_.AddAsymmetricKeyTypeManagers( std::move(owned_private_manager), std::move(owned_public_manager), new_key_allowed); } template crypto::tink::util::Status RegistryImpl::RegisterPrimitiveWrapper( PrimitiveWrapper* wrapper) { if (wrapper == nullptr) { return crypto::tink::util::Status(absl::StatusCode::kInvalidArgument, "Parameter 'wrapper' must be non-null."); } std::unique_ptr> owned_wrapper(wrapper); absl::MutexLock lock(&maps_mutex_); absl::AnyInvocable>( const google::crypto::tink::KeyData& key_data) const> primitive_getter = [this](const google::crypto::tink::KeyData& key_data) { return this->GetPrimitive

(key_data); }; return keyset_wrapper_store_.Add(std::move(owned_wrapper), std::move(primitive_getter)); } // TODO: b/284059638 - Remove this and upstream functions from the public API. template crypto::tink::util::StatusOr*> RegistryImpl::get_key_manager(absl::string_view type_url) const { crypto::tink::util::StatusOr< const crypto::tink::internal::KeyTypeInfoStore::Info*> info = get_key_type_info(type_url); if (!info.ok()) { return info.status(); } return (*info)->get_key_manager

(type_url); } template crypto::tink::util::StatusOr> RegistryImpl::GetPrimitive( const google::crypto::tink::KeyData& key_data) const { crypto::tink::util::StatusOr< const crypto::tink::internal::KeyTypeInfoStore::Info*> info = get_key_type_info(key_data.type_url()); if (!info.ok()) { return info.status(); } return (*info)->GetPrimitive

(key_data); } template crypto::tink::util::StatusOr> RegistryImpl::Wrap( std::unique_ptr> primitive_set) const { if (primitive_set == nullptr) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, "Parameter 'primitive_set' must be non-null."); } const PrimitiveWrapper* wrapper = nullptr; { absl::MutexLock lock(&maps_mutex_); crypto::tink::util::StatusOr*> wrapper_status = keyset_wrapper_store_.GetPrimitiveWrapper

(); if (!wrapper_status.ok()) { return wrapper_status.status(); } wrapper = *wrapper_status; } return wrapper->Wrap(std::move(primitive_set)); } template crypto::tink::util::StatusOr> RegistryImpl::WrapKeyset( const google::crypto::tink::Keyset& keyset, const absl::flat_hash_map& annotations) const { const KeysetWrapper

* keyset_wrapper = nullptr; { absl::MutexLock lock(&maps_mutex_); crypto::tink::util::StatusOr*> keyset_wrapper_status = keyset_wrapper_store_.Get

(); if (!keyset_wrapper_status.ok()) { return keyset_wrapper_status.status(); } keyset_wrapper = *keyset_wrapper_status; } // `maps_mutex_` must be released before calling Wrap or this will deadlock, // as Wrap calls get_key_manager. return keyset_wrapper->Wrap(keyset, annotations); } inline crypto::tink::util::Status RegistryImpl::RestrictToFipsIfEmpty() const { absl::MutexLock lock(&maps_mutex_); // If we are already in FIPS mode, then do nothing.. if (IsFipsModeEnabled()) { return util::OkStatus(); } if (key_type_info_store_.IsEmpty()) { SetFipsRestricted(); return util::OkStatus(); } return util::Status(absl::StatusCode::kInternal, "Could not set FIPS only mode. Registry is not empty."); } } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_REGISTRY_IMPL_H_ ================================================ FILE: cc/internal/registry_impl_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/registry_impl.h" #include #include #include #include #include // NOLINT(build/c++11) #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/string_view.h" #include "openssl/crypto.h" #include "tink/aead.h" #include "tink/aead/aead_wrapper.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/core/key_manager_impl.h" #include "tink/core/key_type_manager.h" #include "tink/core/private_key_manager_impl.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/hybrid/ecies_aead_hkdf_private_key_manager.h" #include "tink/hybrid/ecies_aead_hkdf_public_key_manager.h" #include "tink/hybrid_decrypt.h" #include "tink/input_stream.h" #include "tink/internal/fips_utils.h" #include "tink/key_manager.h" #include "tink/mac.h" #include "tink/monitoring/monitoring_client_mocks.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/registry.h" #include "tink/subtle/aes_gcm_boringssl.h" #include "tink/subtle/random.h" #include "tink/util/input_stream_util.h" #include "tink/util/istream_input_stream.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_ctr_hmac_aead.pb.h" #include "proto/aes_gcm.pb.h" #include "proto/common.pb.h" #include "proto/ecdsa.pb.h" #include "proto/ecies_aead_hkdf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::AddLegacyKey; using ::crypto::tink::test::AddRawKey; using ::crypto::tink::test::AddTinkKey; using ::crypto::tink::test::DummyAead; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::Status; using ::google::crypto::tink::AesCtrHmacAeadKey; using ::google::crypto::tink::AesGcmKey; using ::google::crypto::tink::AesGcmKeyFormat; using ::google::crypto::tink::EcdsaKeyFormat; using ::google::crypto::tink::EcdsaPrivateKey; using ::google::crypto::tink::EcdsaPublicKey; using ::google::crypto::tink::EcdsaSignatureEncoding; using ::google::crypto::tink::EcPointFormat; using ::google::crypto::tink::EllipticCurveType; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::Keyset; using ::google::crypto::tink::KeysetInfo; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::OutputPrefixType; using ::portable_proto::MessageLite; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::IsNull; using ::testing::Not; using ::testing::SizeIs; class RegistryTest : public ::testing::Test { protected: void SetUp() override { Registry::Reset(); } void TearDown() override { // Reset is needed here to ensure Mock objects get deleted and do not leak. Registry::Reset(); } }; class TestKeyFactory : public KeyFactory { public: explicit TestKeyFactory(const std::string& key_type) : key_type_(key_type) {} util::StatusOr> NewKey( const MessageLite& key_format) const override { return util::Status(absl::StatusCode::kUnknown, "TestKeyFactory cannot produce a key"); } util::StatusOr> NewKey( absl::string_view serialized_key_format) const override { return util::Status(absl::StatusCode::kUnknown, "TestKeyFactory cannot produce a key"); } util::StatusOr> NewKeyData( absl::string_view serialized_key_format) const override { auto key_data = absl::make_unique(); key_data->set_type_url(key_type_); key_data->set_value(serialized_key_format); return std::move(key_data); } private: std::string key_type_; }; class TestAeadKeyManager : public KeyManager { public: explicit TestAeadKeyManager(const std::string& key_type) : key_type_(key_type), key_factory_(key_type) {} util::StatusOr> GetPrimitive( const KeyData& key) const override { std::unique_ptr aead(new DummyAead(key_type_)); return std::move(aead); } util::StatusOr> GetPrimitive( const MessageLite& key) const override { return util::Status(absl::StatusCode::kUnknown, "TestKeyFactory cannot construct an aead"); } uint32_t get_version() const override { return 0; } const std::string& get_key_type() const override { return key_type_; } const KeyFactory& get_key_factory() const override { return key_factory_; } private: std::string key_type_; TestKeyFactory key_factory_; }; // A class for testing. We will construct objects from an aead key, so that we // can check that a keymanager can handle multiple primitives. It is really // insecure, as it does nothing except provide access to the key. class AeadVariant { public: explicit AeadVariant(std::string s) : s_(s) {} std::string get() { return s_; } private: std::string s_; }; class ExampleKeyTypeManager : public KeyTypeManager> { public: class AeadFactory : public PrimitiveFactory { public: crypto::tink::util::StatusOr> Create( const AesGcmKey& key) const override { // Ignore the key and returned one with a fixed size for this test. return {subtle::AesGcmBoringSsl::New( util::SecretDataFromStringView(key.key_value()))}; } }; class AeadVariantFactory : public PrimitiveFactory { public: crypto::tink::util::StatusOr> Create( const AesGcmKey& key) const override { return absl::make_unique(key.key_value()); } }; ExampleKeyTypeManager() : KeyTypeManager(absl::make_unique(), absl::make_unique()) {} google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::SYMMETRIC; } uint32_t get_version() const override { return kVersion; } const std::string& get_key_type() const override { return kKeyType; } crypto::tink::util::Status ValidateKey(const AesGcmKey& key) const override { return util::OkStatus(); } crypto::tink::util::Status ValidateKeyFormat( const AesGcmKeyFormat& key_format) const override { return util::OkStatus(); } crypto::tink::util::StatusOr CreateKey( const AesGcmKeyFormat& key_format) const override { AesGcmKey result; result.set_key_value(subtle::Random::GetRandomBytes(key_format.key_size())); return result; } crypto::tink::util::StatusOr DeriveKey( const AesGcmKeyFormat& key_format, InputStream* input_stream) const override { // Note: in an actual key type manager we need to do more work, e.g., test // that the generated key is long enough. crypto::tink::util::StatusOr randomness = ReadBytesFromStream(key_format.key_size(), input_stream); if (!randomness.status().ok()) { return randomness.status(); } AesGcmKey key; key.set_key_value(randomness.value()); return key; } MOCK_METHOD(FipsCompatibility, FipsStatus, (), (const, override)); private: static constexpr int kVersion = 0; const std::string kKeyType = "type.googleapis.com/google.crypto.tink.AesGcmKey"; }; template class TestWrapper : public PrimitiveWrapper { public: TestWrapper() = default; crypto::tink::util::StatusOr> Wrap( std::unique_ptr> primitive_set) const override { return util::Status(absl::StatusCode::kUnimplemented, "This is a test wrapper."); } }; class AeadVariantWrapper : public PrimitiveWrapper { public: crypto::tink::util::StatusOr> Wrap( std::unique_ptr> primitive_set) const override { return absl::make_unique( primitive_set->get_primary()->get_primitive().get()); } }; class AeadVariantToStringWrapper : public PrimitiveWrapper { public: crypto::tink::util::StatusOr> Wrap( std::unique_ptr> primitive_set) const override { return absl::make_unique( primitive_set->get_primary()->get_primitive().get()); } }; void register_test_managers(const std::string& key_type_prefix, int manager_count) { for (int i = 0; i < manager_count; i++) { std::string key_type = key_type_prefix + std::to_string(i); util::Status status = Registry::RegisterKeyManager( absl::make_unique(key_type), /* new_key_allowed= */ true); EXPECT_TRUE(status.ok()) << status; } } void verify_test_managers(const std::string& key_type_prefix, int manager_count) { for (int i = 0; i < manager_count; i++) { std::string key_type = key_type_prefix + std::to_string(i); auto manager_result = Registry::get_key_manager(key_type); EXPECT_TRUE(manager_result.ok()) << manager_result.status(); auto manager = manager_result.value(); EXPECT_EQ(key_type, manager->get_key_type()); } } TEST_F(RegistryTest, testRegisterKeyManagerMoreRestrictiveNewKeyAllowed) { std::string key_type = "some_key_type"; KeyTemplate key_template; key_template.set_type_url(key_type); // Register the key manager with new_key_allowed == true and verify that // new key data can be created. util::Status status = Registry::RegisterKeyManager( absl::make_unique(key_type), /* new_key_allowed= */ true); EXPECT_TRUE(status.ok()) << status; auto result_before = Registry::NewKeyData(key_template); EXPECT_TRUE(result_before.ok()) << result_before.status(); // Re-register the key manager with new_key_allowed == false and check the // restriction (i.e. new key data cannot be created). status = Registry::RegisterKeyManager( absl::make_unique(key_type), /* new_key_allowed= */ false); EXPECT_TRUE(status.ok()) << status; auto result_after = Registry::NewKeyData(key_template); EXPECT_FALSE(result_after.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result_after.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, key_type, std::string(result_after.status().message())); EXPECT_PRED_FORMAT2(testing::IsSubstring, "does not allow", std::string(result_after.status().message())); } TEST_F(RegistryTest, testRegisterKeyManagerLessRestrictiveNewKeyAllowed) { std::string key_type = "some_key_type"; KeyTemplate key_template; key_template.set_type_url(key_type); // Register the key manager with new_key_allowed == false. util::Status status = Registry::RegisterKeyManager( absl::make_unique(key_type), /* new_key_allowed= */ false); EXPECT_TRUE(status.ok()) << status; // Verify that re-registering the key manager with new_key_allowed == true is // not possible and that the restriction still holds after that operation // (i.e. new key data cannot be created). status = Registry::RegisterKeyManager( absl::make_unique(key_type), /* new_key_allowed= */ true); EXPECT_FALSE(status.ok()); EXPECT_EQ(absl::StatusCode::kAlreadyExists, status.code()) << status; EXPECT_PRED_FORMAT2(testing::IsSubstring, key_type, std::string(status.message())) << status; EXPECT_PRED_FORMAT2(testing::IsSubstring, "forbidden new key operation", std::string(status.message())) << status; auto result_after = Registry::NewKeyData(key_template); EXPECT_FALSE(result_after.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result_after.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, key_type, std::string(result_after.status().message())); EXPECT_PRED_FORMAT2(testing::IsSubstring, "does not allow", std::string(result_after.status().message())); } TEST_F(RegistryTest, testConcurrentRegistration) { std::string key_type_prefix_a = "key_type_a_"; std::string key_type_prefix_b = "key_type_b_"; int count_a = 42; int count_b = 72; // Register some managers. std::thread register_a(register_test_managers, key_type_prefix_a, count_a); std::thread register_b(register_test_managers, key_type_prefix_b, count_b); register_a.join(); register_b.join(); // Check that the managers were registered. Also, keep registering new // versions while we check. std::thread register_more_a(register_test_managers, key_type_prefix_a, count_a); std::thread register_more_b(register_test_managers, key_type_prefix_b, count_b); std::thread verify_a(verify_test_managers, key_type_prefix_a, count_a); std::thread verify_b(verify_test_managers, key_type_prefix_b, count_b); verify_a.join(); verify_b.join(); register_more_a.join(); register_more_b.join(); // Check that there are no extra managers. std::string key_type = key_type_prefix_a + std::to_string(count_a - 1); auto manager_result = Registry::get_key_manager(key_type); EXPECT_TRUE(manager_result.ok()) << manager_result.status(); EXPECT_EQ(key_type, manager_result.value()->get_key_type()); key_type = key_type_prefix_a + std::to_string(count_a); manager_result = Registry::get_key_manager(key_type); EXPECT_FALSE(manager_result.ok()); EXPECT_EQ(absl::StatusCode::kNotFound, manager_result.status().code()); } TEST_F(RegistryTest, testBasic) { std::string key_type_1 = "google.crypto.tink.AesCtrHmacAeadKey"; std::string key_type_2 = "google.crypto.tink.AesGcmKey"; auto manager_result = Registry::get_key_manager(key_type_1); EXPECT_FALSE(manager_result.ok()); EXPECT_EQ(absl::StatusCode::kNotFound, manager_result.status().code()); auto status = Registry::RegisterKeyManager( absl::make_unique(key_type_1), true); EXPECT_TRUE(status.ok()) << status; status = Registry::RegisterKeyManager( absl::make_unique(key_type_2), true); EXPECT_TRUE(status.ok()) << status; manager_result = Registry::get_key_manager(key_type_1); EXPECT_TRUE(manager_result.ok()) << manager_result.status(); auto manager = manager_result.value(); EXPECT_TRUE(manager->DoesSupport(key_type_1)); EXPECT_FALSE(manager->DoesSupport(key_type_2)); manager_result = Registry::get_key_manager(key_type_2); EXPECT_TRUE(manager_result.ok()) << manager_result.status(); manager = manager_result.value(); EXPECT_TRUE(manager->DoesSupport(key_type_2)); EXPECT_FALSE(manager->DoesSupport(key_type_1)); } TEST_F(RegistryTest, testRegisterKeyManager) { std::string key_type_1 = AesGcmKeyManager().get_key_type(); std::unique_ptr null_key_manager = nullptr; auto status = Registry::RegisterKeyManager(std::move(null_key_manager), true); EXPECT_FALSE(status.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, status.code()) << status; // Register a key manager. status = Registry::RegisterKeyManager( absl::make_unique(key_type_1), true); EXPECT_TRUE(status.ok()) << status; // Register the same key manager again, it should work (idempotence). status = Registry::RegisterKeyManager( absl::make_unique(key_type_1), true); EXPECT_TRUE(status.ok()) << status; // Try overriding a key manager. AesGcmKeyManager key_type_manager; status = Registry::RegisterKeyManager( crypto::tink::internal::MakeKeyManager(&key_type_manager), true); EXPECT_FALSE(status.ok()); EXPECT_EQ(absl::StatusCode::kAlreadyExists, status.code()) << status; // Check the key manager is still registered. auto manager_result = Registry::get_key_manager(key_type_1); EXPECT_TRUE(manager_result.ok()) << manager_result.status(); auto manager = manager_result.value(); EXPECT_TRUE(manager->DoesSupport(key_type_1)); } // Tests that if we register a key manager once more after a call to // get_key_manager, the key manager previously obtained with "get_key_manager()" // remains valid. TEST_F(RegistryTest, GetKeyManagerRemainsValid) { std::string key_type = AesGcmKeyManager().get_key_type(); EXPECT_THAT(Registry::RegisterKeyManager( absl::make_unique(key_type), true), IsOk()); crypto::tink::util::StatusOr*> key_manager = Registry::get_key_manager(key_type); ASSERT_THAT(key_manager, IsOk()); EXPECT_THAT(Registry::RegisterKeyManager( absl::make_unique(key_type), true), IsOk()); EXPECT_THAT(key_manager.value()->get_key_type(), Eq(key_type)); } TEST_F(RegistryTest, testGettingPrimitives) { std::string key_type_1 = "google.crypto.tink.AesCtrHmacAeadKey"; std::string key_type_2 = "google.crypto.tink.AesGcmKey"; AesCtrHmacAeadKey dummy_key_1; AesGcmKey dummy_key_2; // Prepare keyset. Keyset keyset; uint32_t key_id_1 = 1234543; AddTinkKey(key_type_1, key_id_1, dummy_key_1, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); uint32_t key_id_2 = 726329; AddTinkKey(key_type_2, key_id_2, dummy_key_2, KeyStatusType::DISABLED, KeyData::SYMMETRIC, &keyset); uint32_t key_id_3 = 7213743; AddLegacyKey(key_type_2, key_id_3, dummy_key_2, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); uint32_t key_id_4 = 6268492; AddRawKey(key_type_1, key_id_4, dummy_key_1, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); uint32_t key_id_5 = 42; AddRawKey(key_type_2, key_id_5, dummy_key_2, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(key_id_3); // Register key managers. util::Status status; status = Registry::RegisterKeyManager( absl::make_unique(key_type_1), true); EXPECT_TRUE(status.ok()) << status; status = Registry::RegisterKeyManager( absl::make_unique(key_type_2), true); EXPECT_TRUE(status.ok()) << status; // Get and use primitives. std::string plaintext = "some data"; std::string aad = "aad"; // Key #1. { auto result = Registry::GetPrimitive(keyset.key(0).key_data()); EXPECT_TRUE(result.ok()) << result.status(); auto aead = std::move(result.value()); EXPECT_EQ(DummyAead(key_type_1).Encrypt(plaintext, aad).value(), aead->Encrypt(plaintext, aad).value()); } // Key #3. { auto result = Registry::GetPrimitive(keyset.key(2).key_data()); EXPECT_TRUE(result.ok()) << result.status(); auto aead = std::move(result.value()); EXPECT_EQ(DummyAead(key_type_2).Encrypt(plaintext, aad).value(), aead->Encrypt(plaintext, aad).value()); } } TEST_F(RegistryTest, testNewKeyData) { std::string key_type_1 = "google.crypto.tink.AesCtrHmacAeadKey"; std::string key_type_2 = "google.crypto.tink.AesGcmKey"; std::string key_type_3 = "yet/another/keytype"; // Register key managers. util::Status status; status = Registry::RegisterKeyManager( absl::make_unique(key_type_1), /*new_key_allowed=*/true); EXPECT_TRUE(status.ok()) << status; status = Registry::RegisterKeyManager( absl::make_unique(key_type_2), /*new_key_allowed=*/true); EXPECT_TRUE(status.ok()) << status; status = Registry::RegisterKeyManager( absl::make_unique(key_type_3), /*new_key_allowed=*/false); EXPECT_TRUE(status.ok()) << status; { // A supported key type. KeyTemplate key_template; key_template.set_type_url(key_type_1); key_template.set_value("test value 42"); auto new_key_data_result = Registry::NewKeyData(key_template); EXPECT_TRUE(new_key_data_result.ok()) << new_key_data_result.status(); EXPECT_EQ(key_type_1, new_key_data_result.value()->type_url()); EXPECT_EQ(key_template.value(), new_key_data_result.value()->value()); } { // Another supported key type. KeyTemplate key_template; key_template.set_type_url(key_type_2); key_template.set_value("yet another test value 42"); auto new_key_data_result = Registry::NewKeyData(key_template); EXPECT_TRUE(new_key_data_result.ok()) << new_key_data_result.status(); EXPECT_EQ(key_type_2, new_key_data_result.value()->type_url()); EXPECT_EQ(key_template.value(), new_key_data_result.value()->value()); } { // A key type that does not allow NewKey-operations. KeyTemplate key_template; key_template.set_type_url(key_type_3); key_template.set_value("some other value 72"); auto new_key_data_result = Registry::NewKeyData(key_template); EXPECT_FALSE(new_key_data_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, new_key_data_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, key_type_3, std::string(new_key_data_result.status().message())); EXPECT_PRED_FORMAT2(testing::IsSubstring, "does not allow", std::string(new_key_data_result.status().message())); } { // A key type that is not supported. KeyTemplate key_template; std::string bad_type_url = "some key type that is not supported"; key_template.set_type_url(bad_type_url); key_template.set_value("some totally other value 42"); auto new_key_data_result = Registry::NewKeyData(key_template); EXPECT_FALSE(new_key_data_result.ok()); EXPECT_EQ(absl::StatusCode::kNotFound, new_key_data_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, bad_type_url, std::string(new_key_data_result.status().message())); } } TEST_F(RegistryTest, testGetPublicKeyData) { // Setup the registry. Registry::Reset(); auto private_key_type_manager = absl::make_unique(); auto public_key_type_manager = absl::make_unique(); auto status = Registry::RegisterKeyManager( internal::MakePrivateKeyManager( private_key_type_manager.get(), public_key_type_manager.get()), true); ASSERT_TRUE(status.ok()) << status; AesGcmKeyManager key_type_manager; status = Registry::RegisterKeyManager( crypto::tink::internal::MakeKeyManager(&key_type_manager), true); ASSERT_TRUE(status.ok()) << status; // Get a test private key. auto ecies_key = test::GetEciesAesGcmHkdfTestKey( EllipticCurveType::NIST_P256, EcPointFormat::UNCOMPRESSED, HashType::SHA256, /* aes_gcm_key_size= */ 24); // Extract public key data and check. auto public_key_data_result = Registry::GetPublicKeyData( EciesAeadHkdfPrivateKeyManager().get_key_type(), ecies_key.SerializeAsString()); EXPECT_TRUE(public_key_data_result.ok()) << public_key_data_result.status(); auto public_key_data = std::move(public_key_data_result.value()); EXPECT_EQ(EciesAeadHkdfPublicKeyManager().get_key_type(), public_key_data->type_url()); EXPECT_EQ(KeyData::ASYMMETRIC_PUBLIC, public_key_data->key_material_type()); EXPECT_EQ(ecies_key.public_key().SerializeAsString(), public_key_data->value()); // Try with a wrong key type. auto wrong_key_type_result = Registry::GetPublicKeyData( AesGcmKeyManager().get_key_type(), ecies_key.SerializeAsString()); EXPECT_FALSE(wrong_key_type_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, wrong_key_type_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "PrivateKeyFactory", std::string(wrong_key_type_result.status().message())); // Try with a bad serialized key. auto bad_key_result = Registry::GetPublicKeyData( EciesAeadHkdfPrivateKeyManager().get_key_type(), "some bad serialized key"); EXPECT_FALSE(bad_key_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, bad_key_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "Could not parse", std::string(bad_key_result.status().message())); } // Tests that if we register the same type of wrapper twice, the second call // succeeds. TEST_F(RegistryTest, RegisterWrapperTwice) { EXPECT_TRUE( Registry::RegisterPrimitiveWrapper(absl::make_unique()) .ok()); EXPECT_TRUE( Registry::RegisterPrimitiveWrapper(absl::make_unique()) .ok()); } // Tests that if we register the same type of wrapper twice, the second call // succeeds. TEST_F(RegistryTest, RegisterTransformingWrapperTwice) { EXPECT_TRUE(Registry::RegisterPrimitiveWrapper( absl::make_unique()) .ok()); EXPECT_TRUE(Registry::RegisterPrimitiveWrapper( absl::make_unique()) .ok()); } // Test that if we register a second wrapper, wrapping to the same type as a // previous wrapper it will fail. TEST_F(RegistryTest, RegisterTransformingWrapperTwiceMixing) { EXPECT_TRUE(Registry::RegisterPrimitiveWrapper( absl::make_unique()) .ok()); // We cannot register a different wrapper creating a std::string. EXPECT_THAT(Registry::RegisterPrimitiveWrapper( absl::make_unique>()), Not(IsOk())); // But one creating an Aead. EXPECT_THAT(Registry::RegisterPrimitiveWrapper( absl::make_unique>()), IsOk()); } // Test that if we register a second wrapper, wrapping to the same type as a // previous wrapper it will fail (order swapped). TEST_F(RegistryTest, RegisterTransformingWrapperTwiceMixingBackwards) { EXPECT_THAT(Registry::RegisterPrimitiveWrapper( absl::make_unique>()), IsOk()); // We cannot register another wrapper producing strings. EXPECT_THAT(Registry::RegisterPrimitiveWrapper( absl::make_unique()), Not(IsOk())); } // Tests that if we register different wrappers for the same primitive twice, // the second call fails. TEST_F(RegistryTest, RegisterDifferentWrappers) { EXPECT_TRUE( Registry::RegisterPrimitiveWrapper(absl::make_unique()) .ok()); util::Status result = Registry::RegisterPrimitiveWrapper( absl::make_unique>()); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kAlreadyExists, result.code()); } // Tests that if we register different wrappers for different primitives, this // returns ok. TEST_F(RegistryTest, RegisterDifferentWrappersDifferentPrimitives) { EXPECT_TRUE( Registry::RegisterPrimitiveWrapper(absl::make_unique>()) .ok()); EXPECT_TRUE( Registry::RegisterPrimitiveWrapper(absl::make_unique>()) .ok()); } // Tests that if we do not register a wrapper, then calls to Wrap // fail with "No wrapper registered" -- even if there is a wrapper for a // different primitive registered. TEST_F(RegistryTest, NoWrapperRegistered) { EXPECT_TRUE( Registry::RegisterPrimitiveWrapper(absl::make_unique>()) .ok()); crypto::tink::util::StatusOr> result = Registry::Wrap(absl::make_unique>()); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kNotFound, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "No wrapper registered", std::string(result.status().message())); } // Tests that if the wrapper fails, the error of the wrapped is forwarded // in GetWrappedPrimitive. TEST_F(RegistryTest, WrapperFails) { EXPECT_TRUE( Registry::RegisterPrimitiveWrapper(absl::make_unique>()) .ok()); crypto::tink::util::StatusOr> result = Registry::Wrap(absl::make_unique>()); EXPECT_FALSE(result.ok()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "This is a test wrapper", std::string(result.status().message())); } // Tests that wrapping works as expected in the usual case. TEST_F(RegistryTest, UsualWrappingTest) { KeysetInfo keyset_info; keyset_info.add_key_info(); keyset_info.mutable_key_info(0)->set_output_prefix_type( OutputPrefixType::TINK); keyset_info.mutable_key_info(0)->set_key_id(1234543); keyset_info.mutable_key_info(0)->set_status(KeyStatusType::ENABLED); keyset_info.add_key_info(); keyset_info.mutable_key_info(1)->set_output_prefix_type( OutputPrefixType::LEGACY); keyset_info.mutable_key_info(1)->set_key_id(726329); keyset_info.mutable_key_info(1)->set_status(KeyStatusType::ENABLED); keyset_info.add_key_info(); keyset_info.mutable_key_info(2)->set_output_prefix_type( OutputPrefixType::TINK); keyset_info.mutable_key_info(2)->set_key_id(7213743); keyset_info.mutable_key_info(2)->set_status(KeyStatusType::ENABLED); auto primitive_set = absl::make_unique>(); ASSERT_TRUE(primitive_set ->AddPrimitive(absl::make_unique("aead0"), keyset_info.key_info(0)) .ok()); ASSERT_TRUE(primitive_set ->AddPrimitive(absl::make_unique("aead1"), keyset_info.key_info(1)) .ok()); auto entry_result = primitive_set->AddPrimitive( absl::make_unique("primary_aead"), keyset_info.key_info(2)); ASSERT_THAT(primitive_set->set_primary(entry_result.value()), IsOk()); EXPECT_TRUE( Registry::RegisterPrimitiveWrapper(absl::make_unique()) .ok()); auto aead_result = Registry::Wrap(std::move(primitive_set)); EXPECT_TRUE(aead_result.ok()) << aead_result.status(); std::unique_ptr aead = std::move(aead_result.value()); std::string plaintext = "some_plaintext"; std::string aad = "some_aad"; auto encrypt_result = aead->Encrypt(plaintext, aad); EXPECT_TRUE(encrypt_result.ok()) << encrypt_result.status(); std::string ciphertext = encrypt_result.value(); EXPECT_PRED_FORMAT2(testing::IsSubstring, "primary_aead", ciphertext); auto decrypt_result = aead->Decrypt(ciphertext, aad); EXPECT_TRUE(decrypt_result.ok()) << decrypt_result.status(); EXPECT_EQ(plaintext, decrypt_result.value()); decrypt_result = aead->Decrypt("some bad ciphertext", aad); EXPECT_FALSE(decrypt_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, decrypt_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "decryption failed", std::string(decrypt_result.status().message())); } std::string AddAesGcmKey(uint32_t key_id, OutputPrefixType output_prefix_type, KeyStatusType key_status_type, Keyset& modified_keyset) { AesGcmKey key; key.set_version(0); key.set_key_value(subtle::Random::GetRandomBytes(16)); KeyData key_data; key_data.set_value(key.SerializeAsString()); key_data.set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey"); test::AddKeyData(key_data, key_id, output_prefix_type, key_status_type, &modified_keyset); return key.key_value(); } // Tests that wrapping of a keyset works in the usual case. TEST_F(RegistryTest, KeysetWrappingTest) { if (!IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported when BoringSSL is not built in FIPS-mode."; } Keyset keyset; std::string raw_key = AddAesGcmKey(13, OutputPrefixType::TINK, KeyStatusType::ENABLED, keyset); keyset.set_primary_key_id(13); auto fips_key_manager = absl::make_unique(); ON_CALL(*fips_key_manager, FipsStatus()) .WillByDefault(testing::Return(FipsCompatibility::kRequiresBoringCrypto)); ASSERT_THAT( Registry::RegisterKeyTypeManager(std::move(fips_key_manager), true), IsOk()); ASSERT_THAT(Registry::RegisterPrimitiveWrapper( absl::make_unique()), IsOk()); crypto::tink::util::StatusOr> aead_variant = RegistryImpl::GlobalInstance().WrapKeyset( keyset, /*annotations=*/{}); EXPECT_THAT(aead_variant, IsOk()); EXPECT_THAT(aead_variant.value()->get(), Eq(raw_key)); } // Tests that wrapping of a keyset works. TEST_F(RegistryTest, TransformingKeysetWrappingTest) { if (kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } Keyset keyset; std::string raw_key = AddAesGcmKey(13, OutputPrefixType::TINK, KeyStatusType::ENABLED, keyset); keyset.set_primary_key_id(13); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); ASSERT_THAT(Registry::RegisterPrimitiveWrapper( absl::make_unique()), IsOk()); crypto::tink::util::StatusOr> string_primitive = RegistryImpl::GlobalInstance().WrapKeyset( keyset, /*annotations=*/{}); EXPECT_THAT(string_primitive, IsOk()); EXPECT_THAT(*string_primitive.value(), Eq(raw_key)); } // Tests that when we ask the registry to wrap a PrimitiveSet into an // Aead, but the wrapper is in fact from something else into Aead, we give a // correct error message. TEST_F(RegistryTest, TransformingPrimitiveWrapperCustomKeyManager) { if (kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); // Register a transforming wrapper taking strings and making Aeads. ASSERT_THAT(Registry::RegisterPrimitiveWrapper( absl::make_unique>()), IsOk()); KeysetInfo keyset_info; keyset_info.add_key_info(); keyset_info.mutable_key_info(0)->set_output_prefix_type( OutputPrefixType::TINK); keyset_info.mutable_key_info(0)->set_key_id(1234543); keyset_info.mutable_key_info(0)->set_status(KeyStatusType::ENABLED); keyset_info.set_primary_key_id(1234543); auto primitive_set = absl::make_unique>(); ASSERT_TRUE(primitive_set ->AddPrimitive(absl::make_unique("aead0"), keyset_info.key_info(0)) .ok()); EXPECT_THAT(Registry::Wrap(std::move(primitive_set)).status(), StatusIs(absl::StatusCode::kFailedPrecondition, HasSubstr("custom key manager"))); } // Tests that the error message in GetKeyManager contains the type_id.name() of // the primitive for which the key manager was actually registered. TEST_F(RegistryTest, GetKeyManagerErrorMessage) { AesGcmKeyManager key_type_manager; EXPECT_TRUE( Registry::RegisterKeyManager( crypto::tink::internal::MakeKeyManager(&key_type_manager), true) .ok()); auto result = Registry::get_key_manager(AesGcmKeyManager().get_key_type()); EXPECT_FALSE(result.ok()); EXPECT_THAT(std::string(result.status().message()), HasSubstr(AesGcmKeyManager().get_key_type())); // Note: The C++ standard does not guarantee the next line. If some toolchain // update fails it, one can delete it. EXPECT_THAT(std::string(result.status().message()), HasSubstr(typeid(Aead).name())); } TEST_F(RegistryTest, RegisterKeyTypeManager) { if (kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); } TEST_F(RegistryTest, RegisterFipsKeyTypeManager) { if (!kUseOnlyFips || !IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only supported in FIPS-mode with BoringCrypto available."; } auto fips_key_manager = absl::make_unique(); ON_CALL(*fips_key_manager, FipsStatus()) .WillByDefault(testing::Return(FipsCompatibility::kRequiresBoringCrypto)); EXPECT_THAT( Registry::RegisterKeyTypeManager(std::move(fips_key_manager), true), IsOk()); } TEST_F(RegistryTest, RegisterFipsKeyTypeManagerNoBoringCrypto) { if (!kUseOnlyFips || IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only supported in FIPS-mode with BoringCrypto not available."; } auto fips_key_manager = absl::make_unique(); ON_CALL(*fips_key_manager, FipsStatus()) .WillByDefault(testing::Return(FipsCompatibility::kNotFips)); EXPECT_THAT( Registry::RegisterKeyTypeManager(std::move(fips_key_manager), true), StatusIs(absl::StatusCode::kInternal)); } TEST_F(RegistryTest, KeyTypeManagerGetFirstKeyManager) { if (kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); AesGcmKeyFormat format; format.set_key_size(16); AesGcmKey key = ExampleKeyTypeManager().CreateKey(format).value(); auto aead = Registry::get_key_manager( "type.googleapis.com/google.crypto.tink.AesGcmKey") .value() ->GetPrimitive(key) .value(); std::string encryption = aead->Encrypt("TESTMESSAGE", "").value(); std::string decryption = aead->Decrypt(encryption, "").value(); EXPECT_THAT(decryption, Eq("TESTMESSAGE")); } TEST_F(RegistryTest, KeyTypeManagerGetSecondKeyManager) { if (kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); AesGcmKeyFormat format; format.set_key_size(16); AesGcmKey key = ExampleKeyTypeManager().CreateKey(format).value(); auto aead_variant = Registry::get_key_manager( "type.googleapis.com/google.crypto.tink.AesGcmKey") .value() ->GetPrimitive(key) .value(); EXPECT_THAT(aead_variant->get(), Eq(key.key_value())); } TEST_F(RegistryTest, KeyTypeManagerNotSupportedPrimitive) { if (kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); EXPECT_THAT(Registry::get_key_manager( "type.googleapis.com/google.crypto.tink.AesGcmKey") .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("not among supported primitives"))); } // Tests that if we register a key manager once more after a call to // get_key_manager, the key manager previously obtained with "get_key_manager()" // remains valid. TEST_F(RegistryTest, GetKeyManagerRemainsValidForKeyTypeManagers) { if (kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); crypto::tink::util::StatusOr*> key_manager = Registry::get_key_manager(ExampleKeyTypeManager().get_key_type()); ASSERT_THAT(key_manager, IsOk()); EXPECT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); EXPECT_THAT(key_manager.value()->get_key_type(), Eq(ExampleKeyTypeManager().get_key_type())); } TEST_F(RegistryTest, KeyTypeManagerNewKey) { if (kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); AesGcmKeyFormat format; format.set_key_size(32); KeyTemplate key_template; key_template.set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey"); key_template.set_value(format.SerializeAsString()); KeyData key_data = *Registry::NewKeyData(key_template).value(); EXPECT_THAT(key_data.type_url(), Eq("type.googleapis.com/google.crypto.tink.AesGcmKey")); EXPECT_THAT(key_data.key_material_type(), Eq(google::crypto::tink::KeyData::SYMMETRIC)); AesGcmKey key; key.ParseFromString(key_data.value()); EXPECT_THAT(key.key_value(), SizeIs(32)); } TEST_F(RegistryTest, KeyTypeManagerNewKeyInvalidSize) { if (kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); AesGcmKeyFormat format; format.set_key_size(33); KeyTemplate key_template; key_template.set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey"); key_template.set_value(format.SerializeAsString()); EXPECT_THAT(Registry::NewKeyData(key_template), IsOk()); } TEST_F(RegistryTest, KeyTypeManagerDeriveKey) { if (kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); AesGcmKeyFormat format; format.set_key_size(32); KeyTemplate key_template; key_template.set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey"); key_template.set_value(format.SerializeAsString()); crypto::tink::util::IstreamInputStream input_stream{ absl::make_unique( "0123456789012345678901234567890123456789")}; auto key_data_or = RegistryImpl::GlobalInstance().DeriveKey(key_template, &input_stream); ASSERT_THAT(key_data_or, IsOk()); EXPECT_THAT(key_data_or.value().type_url(), Eq(key_template.type_url())); AesGcmKey key; EXPECT_TRUE(key.ParseFromString(key_data_or.value().value())); // 32 byte prefix of above string. EXPECT_THAT(key.key_value(), Eq("01234567890123456789012345678901")); } // The same, but we register the key manager twice. This should catch some of // the possible lifetime issues. TEST_F(RegistryTest, KeyTypeManagerDeriveKeyRegisterTwice) { if (kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); EXPECT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); AesGcmKeyFormat format; format.set_key_size(32); KeyTemplate key_template; key_template.set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey"); key_template.set_value(format.SerializeAsString()); crypto::tink::util::IstreamInputStream input_stream{ absl::make_unique( "0123456789012345678901234567890123456789")}; auto key_data_or = RegistryImpl::GlobalInstance().DeriveKey(key_template, &input_stream); ASSERT_THAT(key_data_or, IsOk()); EXPECT_THAT(key_data_or.value().type_url(), Eq(key_template.type_url())); AesGcmKey key; EXPECT_TRUE(key.ParseFromString(key_data_or.value().value())); // 32 byte prefix of above string. EXPECT_THAT(key.key_value(), Eq("01234567890123456789012345678901")); } // Tests that if we register a KeyManager instead of a KeyTypeManager, DeriveKey // fails properly. TEST_F(RegistryTest, KeyManagerDeriveKeyFail) { std::string key_type = "type.googleapis.com/google.crypto.tink.AesGcmKey"; ASSERT_THAT(Registry::RegisterKeyManager( absl::make_unique(key_type), /* new_key_allowed= */ true), IsOk()); KeyTemplate key_template; key_template.set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey"); EXPECT_THAT( RegistryImpl::GlobalInstance().DeriveKey(key_template, nullptr).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("cannot derive"))); } TEST_F(RegistryTest, KeyManagerDeriveNotRegistered) { KeyTemplate key_template; key_template.set_type_url("some_inexistent_keytype"); EXPECT_THAT( RegistryImpl::GlobalInstance().DeriveKey(key_template, nullptr).status(), StatusIs(absl::StatusCode::kNotFound, HasSubstr("No manager"))); } TEST_F(RegistryTest, RegisterKeyTypeManagerTwiceMoreRestrictive) { if (kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); EXPECT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), false), IsOk()); } TEST_F(RegistryTest, RegisterKeyTypeManagerTwice) { if (kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); EXPECT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); EXPECT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), false), IsOk()); EXPECT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), false), IsOk()); } TEST_F(RegistryTest, RegisterKeyTypeManagerLessRestrictive) { if (kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), false), IsOk()); EXPECT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), StatusIs(absl::StatusCode::kAlreadyExists)); } TEST_F(RegistryTest, RegisterKeyTypeManagerBeforeKeyManager) { if (kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); EXPECT_THAT(Registry::RegisterKeyManager( absl::make_unique( "type.googleapis.com/google.crypto.tink.AesGcmKey"), true), StatusIs(absl::StatusCode::kAlreadyExists)); } TEST_F(RegistryTest, RegisterKeyTypeManagerAfterKeyManager) { if (kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT(Registry::RegisterKeyManager( absl::make_unique( "type.googleapis.com/google.crypto.tink.AesGcmKey"), true), IsOk()); EXPECT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), StatusIs(absl::StatusCode::kAlreadyExists)); } } // namespace // NOTE: These are outside of the anonymous namespace to allow compiling with // MSVC. class PrivatePrimitiveA {}; class PrivatePrimitiveB {}; namespace { class TestPrivateKeyTypeManager : public PrivateKeyTypeManager> { public: class PrivatePrimitiveAFactory : public PrimitiveFactory { public: crypto::tink::util::StatusOr> Create( const EcdsaPrivateKey& key) const override { return util::Status(absl::StatusCode::kUnimplemented, "Not implemented"); } }; class PrivatePrimitiveBFactory : public PrimitiveFactory { public: crypto::tink::util::StatusOr> Create( const EcdsaPrivateKey& key) const override { return util::Status(absl::StatusCode::kUnimplemented, "Not implemented"); } }; TestPrivateKeyTypeManager() : PrivateKeyTypeManager(absl::make_unique(), absl::make_unique()) {} google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE; } uint32_t get_version() const override { return 0; } crypto::tink::util::Status ValidateKey( const EcdsaPrivateKey& key) const override { return crypto::tink::util::OkStatus(); } crypto::tink::util::Status ValidateKeyFormat( const EcdsaKeyFormat& key) const override { return crypto::tink::util::OkStatus(); } const std::string& get_key_type() const override { return kKeyType; } crypto::tink::util::StatusOr CreateKey( const EcdsaKeyFormat& key_format) const override { EcdsaPublicKey public_key; *public_key.mutable_params() = key_format.params(); EcdsaPrivateKey result; *result.mutable_public_key() = public_key; return result; } crypto::tink::util::StatusOr GetPublicKey( const EcdsaPrivateKey& private_key) const override { return private_key.public_key(); } MOCK_METHOD(FipsCompatibility, FipsStatus, (), (const, override)); private: const std::string kKeyType = "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey"; }; } // namespace // NOTE: These are outside of the anonymous namespace to allow compiling with // MSVC. class PublicPrimitiveA {}; class PublicPrimitiveB {}; namespace { class TestPublicKeyTypeManager : public KeyTypeManager> { public: class PublicPrimitiveAFactory : public PrimitiveFactory { public: crypto::tink::util::StatusOr> Create( const EcdsaPublicKey& key) const override { return util::Status(absl::StatusCode::kUnimplemented, "Not implemented"); } }; class PublicPrimitiveBFactory : public PrimitiveFactory { public: crypto::tink::util::StatusOr> Create( const EcdsaPublicKey& key) const override { return util::Status(absl::StatusCode::kUnimplemented, "Not implemented"); } }; TestPublicKeyTypeManager() : KeyTypeManager(absl::make_unique(), absl::make_unique()) {} google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE; } uint32_t get_version() const override { return 0; } crypto::tink::util::Status ValidateKey( const EcdsaPublicKey& key) const override { return crypto::tink::util::OkStatus(); } const std::string& get_key_type() const override { return kKeyType; } MOCK_METHOD(FipsCompatibility, FipsStatus, (), (const, override)); private: const std::string kKeyType = "type.googleapis.com/google.crypto.tink.EcdsaPublicKey"; }; std::unique_ptr CreateTestPrivateKeyManagerFipsCompatible() { auto private_key_manager = absl::make_unique(); ON_CALL(*private_key_manager, FipsStatus()) .WillByDefault(testing::Return(FipsCompatibility::kRequiresBoringCrypto)); return private_key_manager; } std::unique_ptr CreateTestPublicKeyManagerFipsCompatible() { auto public_key_manager = absl::make_unique(); ON_CALL(*public_key_manager, FipsStatus()) .WillByDefault(testing::Return(FipsCompatibility::kRequiresBoringCrypto)); return public_key_manager; } TEST_F(RegistryTest, RegisterAsymmetricKeyManagers) { if (kUseOnlyFips && !IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is " "not available"; } crypto::tink::util::Status status = Registry::RegisterAsymmetricKeyManagers( CreateTestPrivateKeyManagerFipsCompatible(), CreateTestPublicKeyManagerFipsCompatible(), true); ASSERT_TRUE(status.ok()) << status; } TEST_F(RegistryTest, AsymmetricMoreRestrictiveNewKey) { if (kUseOnlyFips && !IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is " "not available"; } ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers( CreateTestPrivateKeyManagerFipsCompatible(), CreateTestPublicKeyManagerFipsCompatible(), true) .ok()); crypto::tink::util::Status status = Registry::RegisterAsymmetricKeyManagers( CreateTestPrivateKeyManagerFipsCompatible(), CreateTestPublicKeyManagerFipsCompatible(), false); ASSERT_TRUE(status.ok()) << status; } TEST_F(RegistryTest, AsymmetricSameNewKey) { if (kUseOnlyFips && !IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is " "not available"; } ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers( CreateTestPrivateKeyManagerFipsCompatible(), CreateTestPublicKeyManagerFipsCompatible(), true) .ok()); crypto::tink::util::Status status = Registry::RegisterAsymmetricKeyManagers( CreateTestPrivateKeyManagerFipsCompatible(), CreateTestPublicKeyManagerFipsCompatible(), true); ASSERT_TRUE(status.ok()) << status; ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers( CreateTestPrivateKeyManagerFipsCompatible(), CreateTestPublicKeyManagerFipsCompatible(), false) .ok()); status = Registry::RegisterAsymmetricKeyManagers( CreateTestPrivateKeyManagerFipsCompatible(), CreateTestPublicKeyManagerFipsCompatible(), false); ASSERT_TRUE(status.ok()) << status; } TEST_F(RegistryTest, AsymmetricLessRestrictiveGivesError) { if (kUseOnlyFips && !IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is " "not available"; } crypto::tink::util::Status status = Registry::RegisterAsymmetricKeyManagers( CreateTestPrivateKeyManagerFipsCompatible(), CreateTestPublicKeyManagerFipsCompatible(), false); ASSERT_TRUE(status.ok()) << status; EXPECT_THAT(Registry::RegisterAsymmetricKeyManagers( CreateTestPrivateKeyManagerFipsCompatible(), CreateTestPublicKeyManagerFipsCompatible(), true), StatusIs(absl::StatusCode::kAlreadyExists, HasSubstr("forbidden new key operation"))); } // Tests that if we register asymmetric key managers once more after a call to // get_key_manager, the key manager previously obtained with "get_key_manager()" // remains valid. TEST_F(RegistryTest, RegisterAsymmetricKeyManagersGetKeyManagerStaysValid) { if (kUseOnlyFips && !IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is " "not available"; } ASSERT_THAT(Registry::RegisterAsymmetricKeyManagers( CreateTestPrivateKeyManagerFipsCompatible(), CreateTestPublicKeyManagerFipsCompatible(), true), IsOk()); crypto::tink::util::StatusOr*> private_key_manager = Registry::get_key_manager( TestPrivateKeyTypeManager().get_key_type()); crypto::tink::util::StatusOr*> public_key_manager = Registry::get_key_manager( TestPublicKeyTypeManager().get_key_type()); ASSERT_THAT(Registry::RegisterAsymmetricKeyManagers( CreateTestPrivateKeyManagerFipsCompatible(), CreateTestPublicKeyManagerFipsCompatible(), true), IsOk()); EXPECT_THAT(private_key_manager.value()->get_key_type(), Eq(TestPrivateKeyTypeManager().get_key_type())); EXPECT_THAT(public_key_manager.value()->get_key_type(), Eq(TestPublicKeyTypeManager().get_key_type())); } TEST_F(RegistryTest, AsymmetricPrivateRegisterAlone) { if (kUseOnlyFips && !IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is " "not available"; } ASSERT_TRUE(Registry::RegisterKeyTypeManager( CreateTestPrivateKeyManagerFipsCompatible(), true) .ok()); ASSERT_TRUE(Registry::RegisterKeyTypeManager( CreateTestPublicKeyManagerFipsCompatible(), true) .ok()); // Registering the same as asymmetric key managers must fail, because doing so // would mean we invalidate key managers previously obtained with // get_key_manager(). ASSERT_FALSE(Registry::RegisterAsymmetricKeyManagers( CreateTestPrivateKeyManagerFipsCompatible(), CreateTestPublicKeyManagerFipsCompatible(), true) .ok()); ASSERT_TRUE(Registry::RegisterKeyTypeManager( CreateTestPrivateKeyManagerFipsCompatible(), true) .ok()); ASSERT_TRUE(Registry::RegisterKeyTypeManager( CreateTestPublicKeyManagerFipsCompatible(), true) .ok()); } TEST_F(RegistryTest, AsymmetricGetPrimitiveA) { if (kUseOnlyFips && !IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is " "not available"; } ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers( CreateTestPrivateKeyManagerFipsCompatible(), CreateTestPublicKeyManagerFipsCompatible(), true) .ok()); crypto::tink::util::StatusOr*> km = Registry::get_key_manager( TestPrivateKeyTypeManager().get_key_type()); ASSERT_TRUE(km.ok()) << km.status(); EXPECT_THAT(km.value()->get_key_type(), Eq(TestPrivateKeyTypeManager().get_key_type())); } TEST_F(RegistryTest, AsymmetricGetPrimitiveB) { if (kUseOnlyFips && !IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is " "not available"; } ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers( CreateTestPrivateKeyManagerFipsCompatible(), CreateTestPublicKeyManagerFipsCompatible(), true) .ok()); crypto::tink::util::StatusOr*> km = Registry::get_key_manager( TestPrivateKeyTypeManager().get_key_type()); ASSERT_TRUE(km.ok()) << km.status(); EXPECT_THAT(km.value()->get_key_type(), Eq(TestPrivateKeyTypeManager().get_key_type())); } TEST_F(RegistryTest, AsymmetricGetPublicPrimitiveA) { if (kUseOnlyFips && !IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is " "not available"; } ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers( CreateTestPrivateKeyManagerFipsCompatible(), CreateTestPublicKeyManagerFipsCompatible(), true) .ok()); crypto::tink::util::StatusOr*> km = Registry::get_key_manager( TestPublicKeyTypeManager().get_key_type()); ASSERT_TRUE(km.ok()) << km.status(); EXPECT_THAT(km.value()->get_key_type(), Eq(TestPublicKeyTypeManager().get_key_type())); } TEST_F(RegistryTest, AsymmetricGetPublicPrimitiveB) { if (kUseOnlyFips && !IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is " "not available"; } ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers( CreateTestPrivateKeyManagerFipsCompatible(), CreateTestPublicKeyManagerFipsCompatible(), true) .ok()); crypto::tink::util::StatusOr*> km = Registry::get_key_manager( TestPublicKeyTypeManager().get_key_type()); ASSERT_TRUE(km.ok()) << km.status(); EXPECT_THAT(km.value()->get_key_type(), Eq(TestPublicKeyTypeManager().get_key_type())); } TEST_F(RegistryTest, AsymmetricGetWrongPrimitiveError) { if (kUseOnlyFips && !IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is " "not available"; } ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers( CreateTestPrivateKeyManagerFipsCompatible(), CreateTestPublicKeyManagerFipsCompatible(), true) .ok()); crypto::tink::util::StatusOr*> km = Registry::get_key_manager( TestPrivateKeyTypeManager().get_key_type()); EXPECT_THAT(km.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("not among supported primitives"))); } class PrivateKeyManagerImplTest : public testing::Test { void SetUp() override { Registry::Reset(); } void TearDown() override { // Reset is needed here to ensure Mock objects get deleted and do not leak. Registry::Reset(); } }; TEST_F(PrivateKeyManagerImplTest, AsymmetricFactoryNewKeyFromMessage) { if (kUseOnlyFips && !IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is " "not available"; } ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers( CreateTestPrivateKeyManagerFipsCompatible(), CreateTestPublicKeyManagerFipsCompatible(), true) .ok()); EcdsaKeyFormat key_format; key_format.mutable_params()->set_encoding(EcdsaSignatureEncoding::DER); KeyTemplate key_template; key_template.set_type_url(TestPrivateKeyTypeManager().get_key_type()); key_template.set_value(key_format.SerializeAsString()); key_template.set_output_prefix_type(OutputPrefixType::TINK); std::unique_ptr key_data = Registry::NewKeyData(key_template).value(); EXPECT_THAT(key_data->type_url(), Eq(TestPrivateKeyTypeManager().get_key_type())); EcdsaPrivateKey private_key; private_key.ParseFromString(key_data->value()); EXPECT_THAT(private_key.public_key().params().encoding(), Eq(EcdsaSignatureEncoding::DER)); } TEST_F(PrivateKeyManagerImplTest, AsymmetricNewKeyDisallowed) { if (kUseOnlyFips && !IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is " "not available"; } ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers( CreateTestPrivateKeyManagerFipsCompatible(), CreateTestPublicKeyManagerFipsCompatible(), true) .ok()); ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers( CreateTestPrivateKeyManagerFipsCompatible(), CreateTestPublicKeyManagerFipsCompatible(), false) .ok()); KeyTemplate key_template; key_template.set_type_url(TestPrivateKeyTypeManager().get_key_type()); EXPECT_THAT( Registry::NewKeyData(key_template).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("not allow"))); } TEST_F(RegistryTest, AsymmetricGetPublicKeyData) { if (kUseOnlyFips && !IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is " "not available"; } crypto::tink::util::Status status = Registry::RegisterAsymmetricKeyManagers( CreateTestPrivateKeyManagerFipsCompatible(), CreateTestPublicKeyManagerFipsCompatible(), true); EcdsaPrivateKey private_key; private_key.mutable_public_key()->mutable_params()->set_encoding( EcdsaSignatureEncoding::DER); std::unique_ptr key_data = Registry::GetPublicKeyData(TestPrivateKeyTypeManager().get_key_type(), private_key.SerializeAsString()) .value(); ASSERT_THAT(key_data->type_url(), Eq(TestPublicKeyTypeManager().get_key_type())); EcdsaPublicKey public_key; public_key.ParseFromString(key_data->value()); EXPECT_THAT(public_key.params().encoding(), Eq(EcdsaSignatureEncoding::DER)); } class TestPrivateKeyTypeManager2 : public TestPrivateKeyTypeManager {}; class TestPublicKeyTypeManager2 : public TestPublicKeyTypeManager {}; TEST_F(RegistryTest, RegisterAssymmetricReregistrationWithWrongClasses) { if (kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), true) .ok()); EXPECT_THAT(Registry::RegisterAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), true), StatusIs(absl::StatusCode::kAlreadyExists, HasSubstr("already registered"))); EXPECT_THAT(Registry::RegisterAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), true), StatusIs(absl::StatusCode::kAlreadyExists, HasSubstr("already registered"))); EXPECT_THAT(Registry::RegisterAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), true), StatusIs(absl::StatusCode::kAlreadyExists, HasSubstr("already registered"))); EXPECT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), StatusIs(absl::StatusCode::kAlreadyExists, HasSubstr("already registered"))); EXPECT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), StatusIs(absl::StatusCode::kAlreadyExists, HasSubstr("already registered"))); } class TestPublicKeyTypeManagerWithDifferentKeyType : public TestPublicKeyTypeManager { const std::string& get_key_type() const override { return kKeyType; } private: const std::string kKeyType = "bla"; }; TEST_F(RegistryTest, RegisterAssymmetricReregistrationWithNewKeyType) { if (kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), true) .ok()); EXPECT_THAT( Registry::RegisterAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), true), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("impossible to register"))); } // The DelegatingKeyTypeManager calls the registry class DelegatingKeyTypeManager : public PrivateKeyTypeManager> { public: DelegatingKeyTypeManager() : PrivateKeyTypeManager() {} void set_registry(RegistryImpl* registry) { registry_ = registry; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::SYMMETRIC; } uint32_t get_version() const override { return kVersion; } const std::string& get_key_type() const override { return kKeyType; } crypto::tink::util::Status ValidateKey( const EcdsaPrivateKey& key) const override { return util::OkStatus(); } crypto::tink::util::Status ValidateKeyFormat( const EcdsaKeyFormat& key_format) const override { return util::OkStatus(); } crypto::tink::util::StatusOr CreateKey( const EcdsaKeyFormat& key_format) const override { AesGcmKeyFormat format; KeyTemplate key_template; key_template.set_type_url( "type.googleapis.com/google.crypto.tink.AesGcmKey"); key_template.set_value(format.SerializeAsString()); auto result = registry_->NewKeyData(key_template); if (!result.ok()) return result.status(); // Return a string we can check for. return util::Status(absl::StatusCode::kDeadlineExceeded, "CreateKey worked"); } crypto::tink::util::StatusOr DeriveKey( const EcdsaKeyFormat& key_format, InputStream* input_stream) const override { AesGcmKeyFormat format; KeyTemplate key_template; key_template.set_type_url( "type.googleapis.com/google.crypto.tink.AesGcmKey"); key_template.set_value(format.SerializeAsString()); auto result = registry_->DeriveKey(key_template, input_stream); if (!result.ok()) return result.status(); // Return a string we can check for. return util::Status(absl::StatusCode::kDeadlineExceeded, "DeriveKey worked"); } crypto::tink::util::StatusOr GetPublicKey( const EcdsaPrivateKey& private_key) const override { AesGcmKeyFormat format; KeyTemplate key_template; key_template.set_type_url( "type.googleapis.com/google.crypto.tink.AesGcmKey"); key_template.set_value(format.SerializeAsString()); auto result = registry_->NewKeyData(key_template); if (!result.ok()) return result.status(); // Return a string we can check for. return util::Status(absl::StatusCode::kDeadlineExceeded, "GetPublicKey worked"); } private: RegistryImpl* registry_; static constexpr int kVersion = 0; const std::string kKeyType = "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey"; }; class RegistryImplTest : public ::testing::Test { protected: void TearDown() override { // Calling RestrictToFipsIfEmpty() may call SetFipsRestricted(), which // set a global variable to true. We have to reset that after the test. UnSetFipsRestricted(); } }; // Check that we can call the registry again from within NewKeyData TEST_F(RegistryImplTest, CanDelegateCreateKey) { if (kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } RegistryImpl registry_impl; auto delegating_key_manager = absl::make_unique(); delegating_key_manager->set_registry(®istry_impl); auto status = registry_impl .RegisterKeyTypeManager>( std::move(delegating_key_manager), true); EXPECT_THAT(status, IsOk()); status = registry_impl.RegisterKeyTypeManager>( absl::make_unique(), true); EXPECT_THAT(status, IsOk()); EcdsaKeyFormat format; KeyTemplate key_template; key_template.set_type_url( "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey"); key_template.set_value(format.SerializeAsString()); EXPECT_THAT(registry_impl.NewKeyData(key_template).status(), StatusIs(absl::StatusCode::kDeadlineExceeded, HasSubstr("CreateKey worked"))); } // Check that we can call the registry again from within NewKeyData TEST_F(RegistryImplTest, CanDelegateDeriveKey) { if (kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } RegistryImpl registry_impl; auto delegating_key_manager = absl::make_unique(); delegating_key_manager->set_registry(®istry_impl); auto status = registry_impl .RegisterKeyTypeManager>( std::move(delegating_key_manager), true); EXPECT_THAT(status, IsOk()); status = registry_impl.RegisterKeyTypeManager>( absl::make_unique(), true); EXPECT_THAT(status, IsOk()); EcdsaKeyFormat format; KeyTemplate key_template; key_template.set_type_url( "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey"); key_template.set_value(format.SerializeAsString()); EXPECT_THAT(registry_impl.DeriveKey(key_template, nullptr).status(), StatusIs(absl::StatusCode::kDeadlineExceeded, HasSubstr("DeriveKey worked"))); } TEST_F(RegistryImplTest, CanDelegateGetPublicKey) { if (kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } RegistryImpl registry_impl; auto delegating_key_manager = absl::make_unique(); delegating_key_manager->set_registry(®istry_impl); auto status = registry_impl.RegisterAsymmetricKeyManagers( delegating_key_manager.release(), absl::make_unique().release(), true); EXPECT_THAT(status, IsOk()); status = registry_impl.RegisterKeyTypeManager>( absl::make_unique(), true); EXPECT_THAT(status, IsOk()); EcdsaPrivateKey private_key; private_key.mutable_public_key()->mutable_params()->set_encoding( EcdsaSignatureEncoding::DER); EXPECT_THAT(registry_impl .GetPublicKeyData(DelegatingKeyTypeManager().get_key_type(), private_key.SerializeAsString()) .status(), StatusIs(absl::StatusCode::kDeadlineExceeded, HasSubstr("GetPublicKey worked"))); } TEST_F(RegistryImplTest, FipsRestrictionSucceedsOnEmptyRegistry) { RegistryImpl registry_impl; EXPECT_THAT(registry_impl.RestrictToFipsIfEmpty(), IsOk()); } TEST_F(RegistryImplTest, FipsRestrictionSucceedsWhenSettingMultipleTimes) { RegistryImpl registry_impl; EXPECT_THAT(registry_impl.RestrictToFipsIfEmpty(), IsOk()); EXPECT_THAT(registry_impl.RestrictToFipsIfEmpty(), IsOk()); EXPECT_THAT(registry_impl.RestrictToFipsIfEmpty(), IsOk()); } TEST_F(RegistryImplTest, FipsRestrictionSucceedsIfBuildInFipsMode) { if (!kUseOnlyFips) { GTEST_SKIP() << "Not supported when Tink is not built in FIPS mode."; } RegistryImpl registry_impl; EXPECT_THAT(registry_impl.RestrictToFipsIfEmpty(), IsOk()); } TEST_F(RegistryImplTest, FipsFailsIfNotEmpty) { if (kUseOnlyFips) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } auto fips_key_manager = absl::make_unique(); ON_CALL(*fips_key_manager, FipsStatus()) .WillByDefault(testing::Return(FipsCompatibility::kRequiresBoringCrypto)); RegistryImpl registry_impl; auto status = registry_impl.RegisterKeyTypeManager>( std::move(fips_key_manager), true); EXPECT_THAT(status, IsOk()); EXPECT_THAT(registry_impl.RestrictToFipsIfEmpty(), StatusIs(absl::StatusCode::kInternal)); } TEST_F(RegistryImplTest, CanRegisterOnlyOneMonitoringFactory) { auto monitoring_client_factory = absl::make_unique(); RegistryImpl registry_impl; EXPECT_THAT(registry_impl.RegisterMonitoringClientFactory( std::move(monitoring_client_factory)), IsOk()); ASSERT_THAT(registry_impl.GetMonitoringClientFactory(), Not(IsNull())); auto another_monitoring_client_factory = absl::make_unique(); EXPECT_THAT(registry_impl.RegisterMonitoringClientFactory( std::move(another_monitoring_client_factory)), StatusIs(absl::StatusCode::kAlreadyExists)); } TEST_F(RegistryImplTest, CannotRegisterNullFactory) { RegistryImpl registry_impl; EXPECT_THAT(registry_impl.RegisterMonitoringClientFactory(nullptr), StatusIs(absl::StatusCode::kInvalidArgument)); auto monitoring_client_factory = absl::make_unique(); EXPECT_THAT(registry_impl.RegisterMonitoringClientFactory( std::move(monitoring_client_factory)), IsOk()); ASSERT_THAT(registry_impl.GetMonitoringClientFactory(), Not(IsNull())); EXPECT_THAT(registry_impl.RegisterMonitoringClientFactory(nullptr), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/rsa_util.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/rsa_util.h" #include #include #include #include #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "openssl/bn.h" #include "openssl/rsa.h" #include "tink/config/tink_fips.h" #include "tink/internal/bn_util.h" #include "tink/internal/err_util.h" #include "tink/internal/fips_utils.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/internal/ssl_util.h" #include "tink/util/errors.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { constexpr int kMaxRsaModulusSizeBits = 16 * 1024; // Mitigate DoS attacks by limiting the exponent size. 33 bits was chosen as // the limit based on the recommendations in [1] and [2]. Windows CryptoAPI // doesn't support values larger than 32 bits [3], so it is unlikely that // exponents larger than 32 bits are being used for anything Windows commonly // does. // // [1] https://www.imperialviolet.org/2012/03/16/rsae.html // [2] https://www.imperialviolet.org/2012/03/17/rsados.html // [3] https://msdn.microsoft.com/en-us/library/aa387685(VS.85).aspx constexpr int kMaxRsaExponentBits = 33; util::Status ValidateRsaModulusSize(size_t modulus_size) { if (modulus_size < 2048) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Modulus size is ", modulus_size, " only modulus size >= 2048-bit is supported")); } // In FIPS only mode we check here if the modulus is 2048- or 3072-bit, as // these are the only size which is covered by the FIPS validation and // supported by Tink. See // https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3318 if (IsFipsModeEnabled()) { if (modulus_size != 2048 && modulus_size != 3072) { return util::Status( absl::StatusCode::kInternal, absl::StrCat("Modulus size is ", modulus_size, " only modulus size 2048 or 3072 is supported.")); } } return util::OkStatus(); } util::Status ValidateRsaPublicExponent(const BIGNUM *exponent) { if (exponent == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "Public exponent must not be NULL."); } if (BN_is_odd(exponent) == 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Public exponent must be odd."); } if (CompareBignumWithWord(exponent, /*word=*/65536) <= 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Public exponent must be greater than 65536."); } // OpenSSL doesn't pose a limit to the size of the exponent, so for // consistency w.r.t. BoringSSL, we enforce it here. if (BN_num_bits(exponent) > 32) { return util::Status(absl::StatusCode::kInvalidArgument, "Exponent size must be smaller than 32 bits"); } return util::OkStatus(); } util::Status ValidateRsaPublicExponent(absl::string_view exponent) { util::StatusOr> e = internal::StringToBignum(exponent); if (!e.ok()) { return e.status(); } return ValidateRsaPublicExponent(e->get()); } util::Status NewRsaKeyPair(int modulus_size_in_bits, const BIGNUM *e, RsaPrivateKey *private_key, RsaPublicKey *public_key) { internal::SslUniquePtr rsa(RSA_new()); if (rsa == nullptr) { return util::Status(absl::StatusCode::kInternal, "Could not initialize RSA."); } util::Status exponent_validation_res = ValidateRsaPublicExponent(e); if (!exponent_validation_res.ok()) { return exponent_validation_res; } internal::SslUniquePtr e_copy(BN_new()); if (BN_copy(e_copy.get(), e) == nullptr) { return util::Status(absl::StatusCode::kInternal, internal::GetSslErrors()); } if (RSA_generate_key_ex(rsa.get(), modulus_size_in_bits, e_copy.get(), /*cb=*/nullptr) != 1) { return util::Status(absl::StatusCode::kInternal, absl::StrCat("Error generating private key: ", internal::GetSslErrors())); } const BIGNUM *n_bn, *e_bn, *d_bn; RSA_get0_key(rsa.get(), &n_bn, &e_bn, &d_bn); // Save exponents. util::StatusOr n_str = internal::BignumToString(n_bn, BN_num_bytes(n_bn)); if (!n_str.ok()) { return n_str.status(); } util::StatusOr e_str = internal::BignumToString(e_bn, BN_num_bytes(e_bn)); if (!e_str.ok()) { return e_str.status(); } util::StatusOr d_str = internal::BignumToSecretData(d_bn, BN_num_bytes(d_bn)); if (!d_str.ok()) { return d_str.status(); } private_key->n = *std::move(n_str); private_key->e = *std::move(e_str); private_key->d = *std::move(d_str); public_key->n = private_key->n; public_key->e = private_key->e; // Save factors. const BIGNUM *p_bn, *q_bn; RSA_get0_factors(rsa.get(), &p_bn, &q_bn); util::StatusOr p_str = internal::BignumToSecretData(p_bn, BN_num_bytes(p_bn)); if (!p_str.ok()) { return p_str.status(); } util::StatusOr q_str = internal::BignumToSecretData(q_bn, BN_num_bytes(q_bn)); if (!q_str.ok()) { return q_str.status(); } private_key->p = *std::move(p_str); private_key->q = *std::move(q_str); // Save CRT parameters. const BIGNUM *dp_bn, *dq_bn, *crt_bn; RSA_get0_crt_params(rsa.get(), &dp_bn, &dq_bn, &crt_bn); util::StatusOr dp_str = internal::BignumToSecretData(dp_bn, BN_num_bytes(dp_bn)); if (!dp_str.ok()) { return dp_str.status(); } util::StatusOr dq_str = internal::BignumToSecretData(dq_bn, BN_num_bytes(dq_bn)); if (!dq_str.ok()) { return dq_str.status(); } util::StatusOr crt_str = internal::BignumToSecretData(crt_bn, BN_num_bytes(crt_bn)); if (!crt_str.ok()) { return crt_str.status(); } private_key->dp = *std::move(dp_str); private_key->dq = *std::move(dq_str); private_key->crt = *std::move(crt_str); return util::OkStatus(); } util::Status GetRsaModAndExponents(const RsaPrivateKey &key, RSA *rsa) { util::StatusOr> n = internal::StringToBignum(key.n); util::StatusOr> e = internal::StringToBignum(key.e); util::StatusOr> d = internal::StringToBignum(util::SecretDataAsStringView(key.d)); if (!n.ok()) { return n.status(); } if (!e.ok()) { return e.status(); } if (!d.ok()) { return d.status(); } if (RSA_set0_key(rsa, n->get(), e->get(), d->get()) != 1) { return util::Status( absl::StatusCode::kInternal, absl::StrCat("Could not load RSA key: ", internal::GetSslErrors())); } // The RSA object takes ownership when RSA_set0_key is called. n->release(); e->release(); d->release(); return util::OkStatus(); } util::Status GetRsaPrimeFactors(const RsaPrivateKey &key, RSA *rsa) { util::StatusOr> p = internal::StringToBignum(util::SecretDataAsStringView(key.p)); util::StatusOr> q = internal::StringToBignum(util::SecretDataAsStringView(key.q)); if (!p.ok()) { return p.status(); } if (!q.ok()) { return q.status(); } if (RSA_set0_factors(rsa, p->get(), q->get()) != 1) { return util::Status( absl::StatusCode::kInternal, absl::StrCat("Could not load RSA key: ", internal::GetSslErrors())); } p->release(); q->release(); return util::OkStatus(); } util::Status GetRsaCrtParams(const RsaPrivateKey &key, RSA *rsa) { util::StatusOr> dp = internal::StringToBignum(util::SecretDataAsStringView(key.dp)); util::StatusOr> dq = internal::StringToBignum(util::SecretDataAsStringView(key.dq)); util::StatusOr> crt = internal::StringToBignum(util::SecretDataAsStringView(key.crt)); if (!dp.ok()) { return dp.status(); } if (!dq.ok()) { return dq.status(); } if (!crt.ok()) { return crt.status(); } if (RSA_set0_crt_params(rsa, dp->get(), dq->get(), crt->get()) != 1) { return util::Status( absl::StatusCode::kInternal, absl::StrCat("Could not load RSA key: ", internal::GetSslErrors())); } dp->release(); dq->release(); crt->release(); return util::OkStatus(); } util::StatusOr> RsaPrivateKeyToRsa( const RsaPrivateKey &private_key) { auto n = internal::StringToBignum(private_key.n); if (!n.ok()) { return n.status(); } auto validation_result = ValidateRsaModulusSize(BN_num_bits(n->get())); if (!validation_result.ok()) { return validation_result; } // Check RSA's public exponent auto exponent_status = ValidateRsaPublicExponent(private_key.e); if (!exponent_status.ok()) { return exponent_status; } internal::SslUniquePtr rsa(RSA_new()); if (rsa.get() == nullptr) { return util::Status(absl::StatusCode::kInternal, "BoringSsl RSA allocation error"); } util::Status status = GetRsaModAndExponents(private_key, rsa.get()); if (!status.ok()) { return status; } status = GetRsaPrimeFactors(private_key, rsa.get()); if (!status.ok()) { return status; } status = GetRsaCrtParams(private_key, rsa.get()); if (!status.ok()) { return status; } if (RSA_check_key(rsa.get()) == 0) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Could not load RSA key: ", internal::GetSslErrors())); } #ifdef OPENSSL_IS_BORINGSSL if (RSA_check_fips(rsa.get()) == 0) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Could not load RSA key: ", internal::GetSslErrors())); } #endif return std::move(rsa); } util::StatusOr> RsaPublicKeyToRsa( const RsaPublicKey &public_key) { auto n = internal::StringToBignum(public_key.n); if (!n.ok()) { return n.status(); } auto e = internal::StringToBignum(public_key.e); if (!e.ok()) { return e.status(); } auto validation_result = ValidateRsaModulusSize(BN_num_bits(n->get())); if (!validation_result.ok()) { return validation_result; } internal::SslUniquePtr rsa(RSA_new()); if (rsa.get() == nullptr) { return util::Status(absl::StatusCode::kInternal, "RSA allocation error"); } // The value d is null for a public RSA key. if (RSA_set0_key(rsa.get(), n->get(), e->get(), /*d=*/nullptr) != 1) { return util::Status(absl::StatusCode::kInternal, "Could not set RSA key."); } n->release(); e->release(); return std::move(rsa); } util::Status RsaCheckPublicKey(const RSA *key) { if (key == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "RSA key is null"); } // BoringSSL `RSA_check_key` supports checking the public key. if (internal::IsBoringSsl()) { if (RSA_check_key(key) != 1) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid RSA key format"); } return util::OkStatus(); } const BIGNUM *n = nullptr; const BIGNUM *e = nullptr; const BIGNUM *d = nullptr; RSA_get0_key(key, &n, &e, &d); if (e == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "RSA key's public exponent is null"); } if (n == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "RSA key's public modulus is null"); } // Check the size of the public modulus. unsigned n_bits = BN_num_bits(n); if (n_bits > kMaxRsaModulusSizeBits) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat( "RSA key's public modulus size is too large; expected at most ", kMaxRsaModulusSizeBits, " bits, got ", n_bits)); } unsigned e_bits = BN_num_bits(e); // Valis size is 1 < e_bits <= kMaxRsaExponentBits. if (e_bits > kMaxRsaExponentBits || e_bits < 2) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid public exponent size of ", e_bits, " bits")); } // The exponent must be odd to be relatively prime with phi(n). if (!BN_is_odd(e)) { return util::Status(absl::StatusCode::kInvalidArgument, "Public exponent is not odd"); } // Verify |n > e| first taking the shortcut of making sure the size in bits of // n is larger than the maximum modulus size; if this not the case, directly // compare n and e. if (n_bits <= kMaxRsaExponentBits || BN_ucmp(n, e) <= 0) { return util::Status( absl::StatusCode::kInvalidArgument, "RSA key's public exponent is smaller than the modulus"); } return util::OkStatus(); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/rsa_util.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_RSA_UTIL_H_ #define TINK_INTERNAL_RSA_UTIL_H_ #include #include #include "absl/strings/string_view.h" #include "openssl/bn.h" #include "openssl/rsa.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/subtle/common_enums.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { struct RsaPublicKey { // Modulus. // Unsigned big integer in bigendian representation. std::string n; // Public exponent. // Unsigned big integer in bigendian representation. std::string e; }; // Parameters of RSA SSA (Signature Schemes with Appendix) using PSS // (Probabilistic Signature Scheme) encoding (see // https://tools.ietf.org/html/rfc8017#section-8.1). struct RsaSsaPssParams { // Hash function used in computing hash of the signing message // (see https://tools.ietf.org/html/rfc8017#section-9.1.1). subtle::HashType sig_hash; // Hash function used in MGF1 (a mask generation function based on a // hash function) (see https://tools.ietf.org/html/rfc8017#appendix-B.2.1). subtle::HashType mgf1_hash; // Salt length (see https://tools.ietf.org/html/rfc8017#section-9.1.1) int salt_length; }; // Parameters of RSA SSA (Signature Schemes with Appendix) using PKCS1 // (Probabilistic Signature Scheme) encoding (see // https://tools.ietf.org/html/rfc8017#section-8.2). struct RsaSsaPkcs1Params { // Hash function used in computing hash of the signing message // (see https://tools.ietf.org/html/rfc8017#section-9.2). subtle::HashType hash_type; }; // RSA private key representation. struct RsaPrivateKey { // Modulus. std::string n; // Public exponent. std::string e; // Private exponent. // Unsigned big integer in bigendian representation. util::SecretData d; // The prime factor p of n. // Unsigned big integer in bigendian representation. util::SecretData p; // The prime factor q of n. // Unsigned big integer in bigendian representation. util::SecretData q; // d mod (p - 1). util::SecretData dp; // d mod (q - 1). // Unsigned big integer in bigendian representation. util::SecretData dq; // Chinese Remainder Theorem coefficient q^(-1) mod p. // Unsigned big integer in bigendian representation. util::SecretData crt; }; // Validates whether 'modulus_size' is at least 2048-bit. // To reach 128-bit security strength, RSA's modulus must be at least // 3072-bit while 2048-bit RSA key only has 112-bit security. Nevertheless, // a 2048-bit RSA key is considered safe by NIST until 2030 (see // https://www.keylength.com/en/4/). crypto::tink::util::Status ValidateRsaModulusSize(size_t modulus_size); // Validates whether `exponent` is a valid bignum, is odd, greater than 65536 // and smaller than 32 bits. The primes p and q are chosen such that (p-1)(q-1) // is relatively prime to the public exponent. Therefore, the public exponent // must be odd. Furthermore, choosing a public exponent which is not greater // than 65536 can lead to weak instantiations of RSA. A public exponent which is // odd and greater than 65536 conforms to the requirements set by NIST FIPS // 186-4 (Appendix B.3.1). crypto::tink::util::Status ValidateRsaPublicExponent(const BIGNUM *exponent); // Validates whether `exponent` is a valid bignum, is odd, greater than 65536 // and smaller than 32 bits. crypto::tink::util::Status ValidateRsaPublicExponent( absl::string_view exponent); // Creates a new RSA key pair and populates `private_key` and `public_key`. crypto::tink::util::Status NewRsaKeyPair(int modulus_size_in_bits, const BIGNUM *e, RsaPrivateKey *private_key, RsaPublicKey *public_key); // Returns `key`'s private and public exponents (d and e) and mosulus // (n) writing a copy of them into `rsa`. crypto::tink::util::Status GetRsaModAndExponents(const RsaPrivateKey &key, RSA *rsa); // Returns `key`'s prime factors (p and q) writing a copy of them into `rsa`. crypto::tink::util::Status GetRsaPrimeFactors(const RsaPrivateKey &key, RSA *rsa); // Returns `key`'s CRT parameters (dp and dq) writing a copy of them into `rsa`. crypto::tink::util::Status GetRsaCrtParams(const RsaPrivateKey &key, RSA *rsa); // Creates a OpenSSL/BoringSSL RSA key from `private_key`. crypto::tink::util::StatusOr> RsaPrivateKeyToRsa( const RsaPrivateKey &private_key); // Creates a OpenSSL/BoringSSL RSA key from an `public_key`. crypto::tink::util::StatusOr> RsaPublicKeyToRsa( const RsaPublicKey &public_key); // Performs some basic checks on the given RSA public key `key` as in [1] when // OpenSSL is used as a backend. This is needed because with OpenSSL calls to // RSA_check_key with RSA keys that have only the modulus and public exponent // populated don't work [2]. When BoringSSL is used, it uses BoringSSL's // RSA_check_key. // // [1] https://github.com/google/boringssl/blob/master/crypto/fipsmodule/rsa/rsa_impl.c#L76 // [2] https://www.openssl.org/docs/man1.1.1/man3/RSA_check_key.html crypto::tink::util::Status RsaCheckPublicKey(const RSA *key); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_RSA_UTIL_H_ ================================================ FILE: cc/internal/rsa_util_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/rsa_util.h" #include #include #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/string_view.h" #include "openssl/bn.h" #include "openssl/rsa.h" #include "tink/internal/bn_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/subtle/random.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::IsEmpty; using ::testing::Not; constexpr int kSslSuccess = 1; // 2048 bits modulus. constexpr absl::string_view k2048BitRsaModulus = "b5a5651bc2e15ce31d789f0984053a2ea0cf8f964a78068c45acfdf078c57fd62d5a287c32" "f3baa879f5dfea27d7a3077c9d3a2a728368c3d90164690c3d82f660ffebc7f13fed454eb5" "103df943c10dc32ec60b0d9b6e307bfd7f9b943e0dc3901e42501765365f7286eff2f1f728" "774aa6a371e108a3a7dd00d7bcd4c1a186c2865d4b370ea38cc89c0b23b318dbcafbd872b4" "f9b833dfb2a4ca7fcc23298020044e8130bfe930adfb3e5cab8d324547adf4b2ce34d7cea4" "298f0b613d85f2bf1df03da44aee0784a1a20a15ee0c38a0f8e84962f1f61b18bd43781c73" "85f3c2b8e2aebd3c560b4faad208ad3938bad27ddda9ed9e933dba0880212dd9e28d"; // Utility function to create an RSA key pair. util::StatusOr> GetKeyPair( size_t modulus_size_in_bits) { RsaPublicKey public_key; RsaPrivateKey private_key; internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), RSA_F4); util::Status res = NewRsaKeyPair(modulus_size_in_bits, e.get(), &private_key, &public_key); if (!res.ok()) { return res; } return {{public_key, private_key}}; } TEST(RsaUtilTest, BasicSanityChecks) { util::StatusOr> keys = GetKeyPair(/*modulus_size_in_bits=*/2048); ASSERT_THAT(keys, IsOk()); const RsaPublicKey& public_key = keys->first; const RsaPrivateKey& private_key = keys->second; EXPECT_THAT(private_key.n, Not(IsEmpty())); EXPECT_THAT(private_key.e, Not(IsEmpty())); EXPECT_THAT(private_key.d, Not(IsEmpty())); EXPECT_THAT(private_key.p, Not(IsEmpty())); EXPECT_THAT(private_key.q, Not(IsEmpty())); EXPECT_THAT(private_key.dp, Not(IsEmpty())); EXPECT_THAT(private_key.dq, Not(IsEmpty())); EXPECT_THAT(private_key.crt, Not(IsEmpty())); EXPECT_THAT(public_key.n, Not(IsEmpty())); EXPECT_THAT(public_key.e, Not(IsEmpty())); EXPECT_EQ(public_key.n, private_key.n); EXPECT_EQ(public_key.e, private_key.e); } TEST(RsaUtilTest, FailsOnLargeE) { // OpenSSL requires the "e" value to be at most 32 bits. RsaPublicKey public_key; RsaPrivateKey private_key; internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), 1L << 33); EXPECT_THAT(NewRsaKeyPair(/*modulus_size_in_bits=*/2048, e.get(), &private_key, &public_key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaUtilTest, KeyIsWellFormed) { util::StatusOr> keys = GetKeyPair(/*modulus_size_in_bits=*/2048); ASSERT_THAT(keys, IsOk()); const RsaPrivateKey& private_key = keys->second; util::StatusOr> n = internal::StringToBignum(private_key.n); ASSERT_THAT(n, IsOk()); util::StatusOr> d = internal::StringToBignum(util::SecretDataAsStringView(private_key.d)); ASSERT_THAT(d, IsOk()); util::StatusOr> p = internal::StringToBignum(util::SecretDataAsStringView(private_key.p)); ASSERT_THAT(p, IsOk()); util::StatusOr> q = internal::StringToBignum(util::SecretDataAsStringView(private_key.q)); ASSERT_THAT(q, IsOk()); util::StatusOr> dp = internal::StringToBignum(util::SecretDataAsStringView(private_key.dp)); ASSERT_THAT(dp, IsOk()); util::StatusOr> dq = internal::StringToBignum(util::SecretDataAsStringView(private_key.dq)); ASSERT_THAT(dq, IsOk()); internal::SslUniquePtr ctx(BN_CTX_new()); // Check n = p * q. { auto n_calc = internal::SslUniquePtr(BN_new()); ASSERT_EQ(BN_mul(n_calc.get(), p->get(), q->get(), ctx.get()), kSslSuccess); EXPECT_EQ(BN_cmp(n_calc.get(), n->get()), 0); } // Check n size >= 2048 bit. EXPECT_GE(BN_num_bits(n->get()), 2048); // dp = d mod (p - 1) { auto pm1 = internal::SslUniquePtr(BN_dup(p->get())); ASSERT_EQ(BN_sub_word(pm1.get(), /*w=*/1), kSslSuccess); auto dp_calc = internal::SslUniquePtr(BN_new()); ASSERT_EQ(BN_mod(dp_calc.get(), d->get(), pm1.get(), ctx.get()), kSslSuccess); EXPECT_EQ(BN_cmp(dp_calc.get(), dp->get()), 0); } // dq = d mod (q - 1) { auto qm1 = internal::SslUniquePtr(BN_dup(q->get())); ASSERT_EQ(BN_sub_word(qm1.get(), /*w=*/1), kSslSuccess); auto dq_calc = internal::SslUniquePtr(BN_new()); ASSERT_EQ(BN_mod(dq_calc.get(), d->get(), qm1.get(), ctx.get()), kSslSuccess); EXPECT_EQ(BN_cmp(dq_calc.get(), dq->get()), 0); } } TEST(RsaUtilTest, GeneratesDifferentPrivateKeys) { RsaPublicKey public_key; internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), RSA_F4); std::vector private_keys; std::generate_n(std::back_inserter(private_keys), 4, [&]() { RsaPrivateKey private_key; EXPECT_THAT(NewRsaKeyPair(/*modulus_size_in_bits=*/2048, e.get(), &private_key, &public_key), IsOk()); return private_key; }); for (int i = 0; i < private_keys.size() - 1; i++) { for (int j = i + 1; j < private_keys.size(); j++) { // The only field that should be equal. EXPECT_EQ(private_keys[i].e, private_keys[j].e); EXPECT_NE(private_keys[i].n, private_keys[j].n); EXPECT_NE(private_keys[i].d, private_keys[j].d); EXPECT_NE(private_keys[i].p, private_keys[j].p); EXPECT_NE(private_keys[i].q, private_keys[j].q); EXPECT_NE(private_keys[i].dp, private_keys[j].dp); EXPECT_NE(private_keys[i].dq, private_keys[j].dq); EXPECT_NE(private_keys[i].crt, private_keys[j].crt); } } } TEST(RsaUtilTest, ValidateRsaModulusSize) { util::StatusOr> keys = GetKeyPair(/*modulus_size_in_bits=*/2048); ASSERT_THAT(keys, IsOk()); { const RsaPrivateKey& private_key = keys->second; util::StatusOr> n = internal::StringToBignum(private_key.n); EXPECT_THAT(ValidateRsaModulusSize(BN_num_bits(n->get())), IsOk()); } keys = GetKeyPair(/*modulus_size_in_bits=*/1024); ASSERT_THAT(keys, IsOk()); { const RsaPrivateKey& private_key = keys->second; util::StatusOr> n = internal::StringToBignum(private_key.n); EXPECT_THAT(ValidateRsaModulusSize(BN_num_bits(n->get())), Not(IsOk())); } } TEST(RsaUtilTest, ValidateRsaPublicExponent) { internal::SslUniquePtr e_bn(BN_new()); // Failure scenario. const std::vector invalid_exponents = {2, 3, 4, 65536, 65538}; for (const BN_ULONG exponent : invalid_exponents) { BN_set_word(e_bn.get(), exponent); util::StatusOr e_str = internal::BignumToString(e_bn.get(), BN_num_bytes(e_bn.get())); ASSERT_THAT(e_str, IsOk()); EXPECT_THAT(ValidateRsaPublicExponent(*e_str), Not(IsOk())); } // Successful case. BN_set_word(e_bn.get(), RSA_F4); util::StatusOr e_str = internal::BignumToString(e_bn.get(), BN_num_bytes(e_bn.get())); ASSERT_THAT(e_str, IsOk()); EXPECT_THAT(ValidateRsaPublicExponent(*e_str), IsOk()); } // Checks if a BIGNUM is equal to a string value. void ExpectBignumEquals(const BIGNUM* bn, absl::string_view data) { util::StatusOr converted = internal::BignumToString(bn, BN_num_bytes(bn)); ASSERT_THAT(converted, IsOk()); EXPECT_EQ(*converted, data); } // Checks if a BIGNUM is equal to a SecretData value. void ExpectBignumEquals(const BIGNUM* bn, const util::SecretData& data) { internal::ExpectBignumEquals(bn, util::SecretDataAsStringView(data)); } TEST(RsaUtilTest, GetRsaModAndExponents) { util::StatusOr> keys = GetKeyPair(/*modulus_size_in_bits=*/2048); ASSERT_THAT(keys, IsOk()); const RsaPrivateKey& private_key = keys->second; internal::SslUniquePtr rsa(RSA_new()); util::Status result = GetRsaModAndExponents(private_key, rsa.get()); ASSERT_THAT(result, IsOk()); const BIGNUM* n = nullptr; const BIGNUM* e = nullptr; const BIGNUM* d = nullptr; RSA_get0_key(rsa.get(), &n, &e, &d); ExpectBignumEquals(n, private_key.n); ExpectBignumEquals(e, private_key.e); ExpectBignumEquals(d, private_key.d); } TEST(RsaUtilTest, GetRsaPrimeFactors) { util::StatusOr> keys = GetKeyPair(/*modulus_size_in_bits=*/2048); ASSERT_THAT(keys, IsOk()); const RsaPrivateKey& private_key = keys->second; internal::SslUniquePtr rsa(RSA_new()); util::Status result = GetRsaPrimeFactors(private_key, rsa.get()); ASSERT_THAT(result, IsOk()); const BIGNUM* p = nullptr; const BIGNUM* q = nullptr; RSA_get0_factors(rsa.get(), &p, &q); ExpectBignumEquals(p, private_key.p); ExpectBignumEquals(q, private_key.q); } TEST(RsaUtilTest, GetRsaCrtParams) { util::StatusOr> keys = GetKeyPair(/*modulus_size_in_bits=*/2048); ASSERT_THAT(keys, IsOk()); const RsaPrivateKey& private_key = keys->second; internal::SslUniquePtr rsa(RSA_new()); const BIGNUM* dp = nullptr; const BIGNUM* dq = nullptr; const BIGNUM* crt = nullptr; util::Status result = GetRsaCrtParams(private_key, rsa.get()); ASSERT_THAT(result, IsOk()); RSA_get0_crt_params(rsa.get(), &dp, &dq, &crt); ExpectBignumEquals(dp, private_key.dp); ExpectBignumEquals(dq, private_key.dq); ExpectBignumEquals(crt, private_key.crt); } TEST(RsaUtilTest, CopiesRsaPrivateKey) { util::StatusOr> keys = GetKeyPair(/*modulus_size_in_bits=*/2048); ASSERT_THAT(keys, IsOk()); const RsaPrivateKey& private_key = keys->second; util::StatusOr> rsa_result = RsaPrivateKeyToRsa(private_key); EXPECT_TRUE(rsa_result.ok()); internal::SslUniquePtr rsa = std::move(rsa_result).value(); const BIGNUM* n = nullptr; const BIGNUM* e = nullptr; const BIGNUM* d = nullptr; RSA_get0_key(rsa.get(), &n, &e, &d); const BIGNUM* p = nullptr; const BIGNUM* q = nullptr; RSA_get0_factors(rsa.get(), &p, &q); ExpectBignumEquals(n, private_key.n); ExpectBignumEquals(e, private_key.e); ExpectBignumEquals(d, private_key.d); ExpectBignumEquals(p, private_key.p); ExpectBignumEquals(q, private_key.q); } TEST(RsaUtilTest, CopiesRsaPublicKey) { util::StatusOr> keys = GetKeyPair(/*modulus_size_in_bits=*/2048); ASSERT_THAT(keys, IsOk()); const RsaPublicKey& public_key = keys->first; util::StatusOr> rsa_result = RsaPublicKeyToRsa(public_key); EXPECT_TRUE(rsa_result.ok()); internal::SslUniquePtr rsa = std::move(rsa_result).value(); const BIGNUM* n = nullptr; const BIGNUM* e = nullptr; RSA_get0_key(rsa.get(), &n, &e, /*out_d=*/nullptr); ExpectBignumEquals(n, public_key.n); ExpectBignumEquals(e, public_key.e); } // Utility function that creates an RSA public key with the given modulus // `n_hex` and exponent `exp`. util::StatusOr> NewRsaPublicKey( absl::string_view n_hex, uint64_t exp) { internal::SslUniquePtr key(RSA_new()); util::StatusOr> n_bn = internal::StringToBignum(absl::HexStringToBytes(n_hex)); if (!n_bn.ok()) { return n_bn.status(); } internal::SslUniquePtr n = *std::move(n_bn); internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), exp); if (RSA_set0_key(key.get(), n.get(), e.get(), /*d=*/nullptr) != 1) { return util::Status(absl::StatusCode::kInternal, "RSA_set0_key failed"); } // RSA_set0_key takes ownership of the arguments. n.release(); e.release(); return std::move(key); } TEST(RsaUtilTest, RsaCheckPublicKeyNullKey) { EXPECT_THAT(RsaCheckPublicKey(nullptr), Not(IsOk())); } TEST(RsaUtilTest, RsaCheckPublicKeyMissingExponentAndModule) { internal::SslUniquePtr key(RSA_new()); EXPECT_THAT(RsaCheckPublicKey(key.get()), Not(IsOk())); } TEST(RsaUtilTest, RsaCheckPublicKeyValid) { util::StatusOr> key = NewRsaPublicKey(k2048BitRsaModulus, RSA_F4); ASSERT_THAT(key, IsOk()); EXPECT_THAT(RsaCheckPublicKey(key->get()), IsOk()); } TEST(RsaUtilTest, RsaCheckPublicKeyExponentTooLarge) { // Invalid exponent of 34 bits. constexpr uint64_t kExponentTooLarge = 0x200000000; util::StatusOr> key = NewRsaPublicKey(k2048BitRsaModulus, kExponentTooLarge); ASSERT_THAT(key, IsOk()); EXPECT_THAT(RsaCheckPublicKey(key->get()), Not(IsOk())); } TEST(RsaUtilTest, RsaCheckPublicKeyExponentTooSmall) { constexpr uint64_t kExponentEqualsToOne = 0x1; util::StatusOr> key = NewRsaPublicKey(k2048BitRsaModulus, kExponentEqualsToOne); ASSERT_THAT(key, IsOk()); EXPECT_THAT(RsaCheckPublicKey(key->get()), Not(IsOk())); } TEST(RsaUtilTest, RsaCheckPublicKeyExponentNotOdd) { constexpr uint64_t kExponentNotOdd = 0x20000000; util::StatusOr> key = NewRsaPublicKey(k2048BitRsaModulus, kExponentNotOdd); ASSERT_THAT(key, IsOk()); EXPECT_THAT(RsaCheckPublicKey(key->get()), Not(IsOk())); } TEST(RsaUtilTest, RsaCheckPublicKeyModulusTooLarge) { // Get 1 byte more than 16384 bits (2048 bytes). std::string too_large_modulus = subtle::Random::GetRandomBytes(2049); if (too_large_modulus[0] == '\0') { too_large_modulus[0] = 0x01; } util::StatusOr> key = NewRsaPublicKey(absl::BytesToHexString(too_large_modulus), RSA_F4); ASSERT_THAT(key, IsOk()); EXPECT_THAT(RsaCheckPublicKey(key->get()), Not(IsOk())); } TEST(RsaUtilTest, RsaCheckPublicKeyModulusSmallerThanExp) { constexpr absl::string_view kModulusSmallerThanExp = "1001"; util::StatusOr> key = NewRsaPublicKey(kModulusSmallerThanExp, RSA_F4); ASSERT_THAT(key, IsOk()); EXPECT_THAT(RsaCheckPublicKey(key->get()), Not(IsOk())); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/safe_stringops.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_SAFE_STRINGOPS_H_ #define TINK_INTERNAL_SAFE_STRINGOPS_H_ #include #include "tink/internal/call_with_core_dump_protection.h" #include "openssl/crypto.h" namespace crypto { namespace tink { namespace internal { // Equivalents of regular memcpy/memmove, which do not leak contents of the // arguments in the core dump. inline void* SafeMemCopy(void* dst, const void* src, size_t n) { return CallWithCoreDumpProtection( [dst, src, n]() { return memcpy(dst, src, n); }); } inline void* SafeMemMove(void* dst, const void* src, size_t n) { return CallWithCoreDumpProtection( [dst, src, n]() { return memmove(dst, src, n); }); } // Test equality of two memory areas. // Not only protects from leaking any info about the contents in the core dump, // but also is safe for crypto material (const time). inline int SafeCryptoMemEquals(const void* s1, const void* s2, size_t n) { return CallWithCoreDumpProtection( [s1, s2, n]() { return CRYPTO_memcmp(s1, s2, n) == 0; }); } } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_SAFE_STRINGOPS_H_ ================================================ FILE: cc/internal/safe_stringops_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/safe_stringops.h" #include "gmock/gmock.h" #include "gtest/gtest.h" namespace crypto { namespace tink { namespace internal { namespace { using ::testing::StrEq; TEST(MemCopyTest, Regular) { char src[] = "hello"; char dst[] = "world"; EXPECT_THAT(dst, StrEq("world")); static_assert(sizeof(src) == sizeof(dst), "size mismatch"); EXPECT_EQ(SafeMemCopy(dst, src, sizeof(src)), dst); EXPECT_THAT(dst, StrEq("hello")); } TEST(MemMoveTest, Regular) { char src[] = "hello"; char dst[] = "world"; EXPECT_THAT(dst, StrEq("world")); static_assert(sizeof(src) == sizeof(dst), "size mismatch"); EXPECT_EQ(SafeMemMove(dst, src, sizeof(src)), dst); EXPECT_THAT(dst, StrEq("hello")); } TEST(MemMoveTest, NoMove) { char mem[] = "hello"; EXPECT_THAT(mem, StrEq("hello")); EXPECT_EQ(SafeMemMove(mem, mem, sizeof(mem)), mem); EXPECT_THAT(mem, StrEq("hello")); } TEST(MemmoveTest, OverlapSuffix) { char mem[] = "hello"; EXPECT_THAT(mem, StrEq("hello")); EXPECT_EQ(SafeMemMove(&mem[1], mem, sizeof(mem) - 2), &mem[1]); EXPECT_THAT(mem, StrEq("hhell")); } TEST(MemMoveTest, OverlapPrefix) { char mem[] = "hello"; EXPECT_THAT(mem, StrEq("hello")); EXPECT_EQ(SafeMemMove(mem, &mem[1], sizeof(mem) - 2), mem); EXPECT_THAT(mem, StrEq("elloo")); } TEST(MemEqualsTest, Equal) { char a[] = "hello"; char b[] = "hello"; EXPECT_NE(a, b); static_assert(sizeof(a) == sizeof(b), "size mismatch"); EXPECT_TRUE(SafeCryptoMemEquals(a, b, sizeof(a))); EXPECT_TRUE(SafeCryptoMemEquals(b, a, sizeof(a))); } TEST(MemEqualsTest, Unequal) { char a[] = "hello"; char b[] = "hellu"; EXPECT_NE(a, b); static_assert(sizeof(a) == sizeof(b), "size mismatch"); EXPECT_FALSE(SafeCryptoMemEquals(a, b, sizeof(a))); EXPECT_FALSE(SafeCryptoMemEquals(b, a, sizeof(a))); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/serialization.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_SERIALIZATION_H_ #define TINK_INTERNAL_SERIALIZATION_H_ #include "absl/strings/string_view.h" namespace crypto { namespace tink { // Represents either a serialized `Key` or a serialized `Parameters` object. // // Serialization objects are used within Tink to serialize keys, keysets, and // parameters. For each serialization method (e.g., binary protobuf // serialization), one subclass of this interface must be defined. // // This class should eventually be moved to the Tink Public API, but major // changes still might be made until then (i.e., don't assume that this API // is completely stable yet). class Serialization { public: // Identifies which parsing method to use in the registry. // // When registering a parsing function in the registry, one argument will be // this object identifier. When the registry is asked to parse a // `Serialization`, the registry will then dispatch it to the corresponding // method. // // The returned absl::string_view must remain valid for the lifetime of this // `Serialization` object. virtual absl::string_view ObjectIdentifier() const = 0; virtual ~Serialization() = default; }; } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_SERIALIZATION_H_ ================================================ FILE: cc/internal/serialization_registry.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/serialization_registry.h" #include #include #include #include #include "absl/container/flat_hash_map.h" #include "absl/status/status.h" #include "absl/strings/str_format.h" #include "absl/types/optional.h" #include "tink/internal/key_parser.h" #include "tink/internal/key_serializer.h" #include "tink/internal/parameters_parser.h" #include "tink/internal/parameters_serializer.h" #include "tink/internal/parser_index.h" #include "tink/internal/serialization.h" #include "tink/internal/serializer_index.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/secret_key_access_token.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { SerializationRegistry::Builder::Builder(const SerializationRegistry& registry) : Builder(registry.parameters_parsers_, registry.parameters_serializers_, registry.key_parsers_, registry.key_serializers_) {} util::Status SerializationRegistry::Builder::RegisterParametersParser( ParametersParser* parser) { ParserIndex index = parser->Index(); auto it = parameters_parsers_.find(index); if (it != parameters_parsers_.end()) { if (parameters_parsers_[index] != parser) { return util::Status(absl::StatusCode::kAlreadyExists, "Attempted to update existing parameters parser."); } } parameters_parsers_.insert({parser->Index(), parser}); return util::OkStatus(); } util::Status SerializationRegistry::Builder::RegisterParametersSerializer( ParametersSerializer* serializer) { SerializerIndex index = serializer->Index(); auto it = parameters_serializers_.find(index); if (it != parameters_serializers_.end()) { if (parameters_serializers_[index] != serializer) { return util::Status( absl::StatusCode::kAlreadyExists, "Attempted to update existing parameters serializer."); } } parameters_serializers_.insert({serializer->Index(), serializer}); return util::OkStatus(); } util::Status SerializationRegistry::Builder::RegisterKeyParser( KeyParser* parser) { ParserIndex index = parser->Index(); auto it = key_parsers_.find(index); if (it != key_parsers_.end()) { if (key_parsers_[index] != parser) { return util::Status(absl::StatusCode::kAlreadyExists, "Attempted to update existing key parser."); } } key_parsers_.insert({parser->Index(), parser}); return util::OkStatus(); } util::Status SerializationRegistry::Builder::RegisterKeySerializer( KeySerializer* serializer) { SerializerIndex index = serializer->Index(); auto it = key_serializers_.find(index); if (it != key_serializers_.end()) { if (key_serializers_[index] != serializer) { return util::Status(absl::StatusCode::kAlreadyExists, "Attempted to update existing key serializer."); } } key_serializers_.insert({serializer->Index(), serializer}); return util::OkStatus(); } SerializationRegistry SerializationRegistry::Builder::Build() && { return SerializationRegistry( std::move(parameters_parsers_), std::move(parameters_serializers_), std::move(key_parsers_), std::move(key_serializers_)); } util::StatusOr> SerializationRegistry::ParseParameters( const Serialization& serialization) const { ParserIndex index = ParserIndex::Create(serialization); auto it = parameters_parsers_.find(index); if (it == parameters_parsers_.end()) { return util::Status( absl::StatusCode::kNotFound, absl::StrFormat("No parameters parser found for parameters type %s", typeid(serialization).name())); } return parameters_parsers_.at(index)->ParseParameters(serialization); } util::StatusOr> SerializationRegistry::ParseKey( const Serialization& serialization, absl::optional token) const { ParserIndex index = ParserIndex::Create(serialization); auto it = key_parsers_.find(index); if (it == key_parsers_.end()) { return util::Status( absl::StatusCode::kNotFound, absl::StrFormat("No key parser found for serialization type %s", typeid(serialization).name())); } return key_parsers_.at(index)->ParseKey(serialization, token); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/serialization_registry.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_SERIALIZATION_REGISTRY_H_ #define TINK_INTERNAL_SERIALIZATION_REGISTRY_H_ #include #include #include #include #include #include #include "absl/container/flat_hash_map.h" #include "absl/status/status.h" #include "absl/strings/str_format.h" #include "absl/types/optional.h" #include "tink/internal/key_parser.h" #include "tink/internal/key_serializer.h" #include "tink/internal/parameters_parser.h" #include "tink/internal/parameters_serializer.h" #include "tink/internal/parser_index.h" #include "tink/internal/serialization.h" #include "tink/internal/serializer_index.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/secret_key_access_token.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { class SerializationRegistry { public: class Builder { public: // Neither movable nor copyable. Builder(const Builder& other) = delete; Builder& operator=(const Builder& other) = delete; // Creates initially empty serialization registry builder. Builder() = default; // Creates serialization registry builder by initially copying entries from // `registry`. explicit Builder(const SerializationRegistry& registry); // Registers parameters `parser`. Returns an error if a different parameters // parser has already been registered. util::Status RegisterParametersParser(ParametersParser* parser); // Registers parameters `serializer`. Returns an error if a different // parameters serializer has already been registered. util::Status RegisterParametersSerializer(ParametersSerializer* serializer); // Registers key `parser`. Returns an error if a different key parser has // already been registered. util::Status RegisterKeyParser(KeyParser* parser); // Registers key `serializer`. Returns an error if a different key // serializer has already been registered. util::Status RegisterKeySerializer(KeySerializer* serializer); // Creates serialization registry from this builder. SerializationRegistry Build() &&; private: Builder(const absl::flat_hash_map& parameters_parsers, const absl::flat_hash_map& parameters_serializers, absl::flat_hash_map key_parsers, const absl::flat_hash_map key_serializers) : parameters_parsers_(parameters_parsers), parameters_serializers_(parameters_serializers), key_parsers_(std::move(key_parsers)), key_serializers_(key_serializers) {} absl::flat_hash_map parameters_parsers_; absl::flat_hash_map parameters_serializers_; absl::flat_hash_map key_parsers_; absl::flat_hash_map key_serializers_; }; // Movable and copyable. SerializationRegistry(SerializationRegistry&& other) = default; SerializationRegistry& operator=(SerializationRegistry&& other) = default; SerializationRegistry(const SerializationRegistry& other) = default; SerializationRegistry& operator=(const SerializationRegistry& other) = default; // Creates empty serialization registry. SerializationRegistry() = default; // Parses `serialization` into a `Parameters` instance. util::StatusOr> ParseParameters( const Serialization& serialization) const; // Serializes `parameters` into a `Serialization` instance. template util::StatusOr> SerializeParameters( const Parameters& parameters) const { SerializerIndex index = SerializerIndex::Create(parameters); auto it = parameters_serializers_.find(index); if (it == parameters_serializers_.end()) { return util::Status( absl::StatusCode::kNotFound, absl::StrFormat( "No parameters serializer found for parameters type %s", typeid(parameters).name())); } return parameters_serializers_.at(index)->SerializeParameters(parameters); } // Parses `serialization` into a `Key` instance. util::StatusOr> ParseKey( const Serialization& serialization, absl::optional token) const; // Serializes `parameters` into a `Serialization` instance. template util::StatusOr> SerializeKey( const Key& key, absl::optional token) const { SerializerIndex index = SerializerIndex::Create(key); auto it = key_serializers_.find(index); if (it == key_serializers_.end()) { return util::Status( absl::StatusCode::kNotFound, absl::StrFormat("No key serializer found for key type %s", typeid(key).name())); } return key_serializers_.at(index)->SerializeKey(key, token); } private: SerializationRegistry( absl::flat_hash_map parameters_parsers, absl::flat_hash_map parameters_serializers, absl::flat_hash_map key_parsers, absl::flat_hash_map key_serializers) : parameters_parsers_(std::move(parameters_parsers)), parameters_serializers_(std::move(parameters_serializers)), key_parsers_(std::move(key_parsers)), key_serializers_(std::move(key_serializers)) {} absl::flat_hash_map parameters_parsers_; absl::flat_hash_map parameters_serializers_; absl::flat_hash_map key_parsers_; absl::flat_hash_map key_serializers_; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_SERIALIZATION_REGISTRY_H_ ================================================ FILE: cc/internal/serialization_registry_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/serialization_registry.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/key_parser.h" #include "tink/internal/key_serializer.h" #include "tink/internal/parameters_parser.h" #include "tink/internal/parameters_serializer.h" #include "tink/internal/serialization.h" #include "tink/internal/serialization_test_util.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/secret_key_access_token.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace internal { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::IsFalse; using ::testing::IsTrue; TEST(SerializationRegistryTest, ParseParameters) { SerializationRegistry::Builder builder; ParametersParserImpl parser1(kNoIdTypeUrl, ParseNoIdParams); ParametersParserImpl parser2(kIdTypeUrl, ParseIdParams); ASSERT_THAT(builder.RegisterParametersParser(&parser1), IsOk()); ASSERT_THAT(builder.RegisterParametersParser(&parser2), IsOk()); SerializationRegistry registry = std::move(builder).Build(); util::StatusOr> no_id_params = registry.ParseParameters(NoIdSerialization()); ASSERT_THAT(no_id_params, IsOk()); EXPECT_THAT((*no_id_params)->HasIdRequirement(), IsFalse()); EXPECT_THAT(std::type_index(typeid(**no_id_params)), std::type_index(typeid(NoIdParams))); util::StatusOr> id_params = registry.ParseParameters(IdParamsSerialization()); ASSERT_THAT(id_params, IsOk()); EXPECT_THAT((*id_params)->HasIdRequirement(), IsTrue()); EXPECT_THAT(std::type_index(typeid(**id_params)), std::type_index(typeid(IdParams))); } TEST(SerializationRegistryTest, ParseParametersWithoutRegistration) { SerializationRegistry registry = SerializationRegistry::Builder().Build(); ASSERT_THAT(registry.ParseParameters(NoIdSerialization()).status(), StatusIs(absl::StatusCode::kNotFound)); } TEST(SerializationRegistryTest, RegisterSameParametersParser) { SerializationRegistry::Builder builder; ParametersParserImpl parser(kNoIdTypeUrl, ParseNoIdParams); EXPECT_THAT(builder.RegisterParametersParser(&parser), IsOk()); EXPECT_THAT(builder.RegisterParametersParser(&parser), IsOk()); } TEST(SerializationRegistryTest, RegisterDifferentParametersParserWithSameIndex) { SerializationRegistry::Builder builder; ParametersParserImpl parser1(kNoIdTypeUrl, ParseNoIdParams); ParametersParserImpl parser2(kNoIdTypeUrl, ParseNoIdParams); EXPECT_THAT(builder.RegisterParametersParser(&parser1), IsOk()); EXPECT_THAT(builder.RegisterParametersParser(&parser2), StatusIs(absl::StatusCode::kAlreadyExists)); } TEST(SerializationRegistryTest, SerializeParameters) { SerializationRegistry::Builder builder; ParametersSerializerImpl serializer1( kNoIdTypeUrl, SerializeNoIdParams); ParametersSerializerImpl serializer2( kIdTypeUrl, SerializeIdParams); ASSERT_THAT(builder.RegisterParametersSerializer(&serializer1), IsOk()); ASSERT_THAT(builder.RegisterParametersSerializer(&serializer2), IsOk()); SerializationRegistry registry = std::move(builder).Build(); util::StatusOr> serialization1 = registry.SerializeParameters(NoIdParams()); ASSERT_THAT(serialization1, IsOk()); EXPECT_THAT((*serialization1)->ObjectIdentifier(), Eq(kNoIdTypeUrl)); util::StatusOr> serialization2 = registry.SerializeParameters(IdParams()); ASSERT_THAT(serialization2, IsOk()); EXPECT_THAT((*serialization2)->ObjectIdentifier(), Eq(kIdTypeUrl)); } TEST(SerializationRegistryTest, SerializeParametersWithoutRegistration) { SerializationRegistry registry = SerializationRegistry::Builder().Build(); ASSERT_THAT( registry.SerializeParameters(NoIdParams()).status(), StatusIs(absl::StatusCode::kNotFound)); } TEST(SerializationRegistryTest, RegisterSameParametersSerializer) { SerializationRegistry::Builder builder; ParametersSerializerImpl serializer( kNoIdTypeUrl, SerializeNoIdParams); EXPECT_THAT(builder.RegisterParametersSerializer(&serializer), IsOk()); EXPECT_THAT(builder.RegisterParametersSerializer(&serializer), IsOk()); } TEST(SerializationRegistryTest, RegisterDifferentParametersSerializerWithSameIndex) { SerializationRegistry::Builder builder; ParametersSerializerImpl serializer1( kNoIdTypeUrl, SerializeNoIdParams); ParametersSerializerImpl serializer2( kNoIdTypeUrl, SerializeNoIdParams); EXPECT_THAT(builder.RegisterParametersSerializer(&serializer1), IsOk()); EXPECT_THAT(builder.RegisterParametersSerializer(&serializer2), StatusIs(absl::StatusCode::kAlreadyExists)); } TEST(SerializationRegistryTest, ParseKey) { SerializationRegistry::Builder builder; KeyParserImpl parser1(kNoIdTypeUrl, ParseNoIdKey); KeyParserImpl parser2(kIdTypeUrl, ParseIdKey); ASSERT_THAT(builder.RegisterKeyParser(&parser1), IsOk()); ASSERT_THAT(builder.RegisterKeyParser(&parser2), IsOk()); SerializationRegistry registry = std::move(builder).Build(); util::StatusOr> no_id_key = registry.ParseKey(NoIdSerialization(), InsecureSecretKeyAccess::Get()); ASSERT_THAT(no_id_key, IsOk()); EXPECT_THAT(std::type_index(typeid(**no_id_key)), std::type_index(typeid(NoIdKey))); util::StatusOr> id_key = registry.ParseKey( IdKeySerialization(/*id=*/123), InsecureSecretKeyAccess::Get()); ASSERT_THAT(id_key, IsOk()); EXPECT_THAT(std::type_index(typeid(**id_key)), std::type_index(typeid(IdKey))); EXPECT_THAT((*id_key)->GetIdRequirement(), Eq(123)); } TEST(SerializationRegistryTest, ParseKeyNoSecretAccess) { SerializationRegistry::Builder builder; KeyParserImpl parser(kNoIdTypeUrl, ParseNoIdKey); ASSERT_THAT(builder.RegisterKeyParser(&parser), IsOk()); SerializationRegistry registry = std::move(builder).Build(); util::StatusOr> no_id_public_key = registry.ParseKey(NoIdSerialization(), absl::nullopt); ASSERT_THAT(no_id_public_key, IsOk()); EXPECT_THAT(std::type_index(typeid(**no_id_public_key)), std::type_index(typeid(NoIdKey))); } TEST(SerializationRegistryTest, ParseKeyWithoutRegistration) { SerializationRegistry registry = SerializationRegistry::Builder().Build(); ASSERT_THAT( registry.ParseKey(NoIdSerialization(), InsecureSecretKeyAccess::Get()) .status(), StatusIs(absl::StatusCode::kNotFound)); } TEST(SerializationRegistryTest, RegisterSameKeyParser) { SerializationRegistry::Builder builder; KeyParserImpl parser(kNoIdTypeUrl, ParseNoIdKey); EXPECT_THAT(builder.RegisterKeyParser(&parser), IsOk()); EXPECT_THAT(builder.RegisterKeyParser(&parser), IsOk()); } TEST(SerializationRegistryTest, RegisterDifferentKeyParserWithSameIndex) { SerializationRegistry::Builder builder; KeyParserImpl parser1(kNoIdTypeUrl, ParseNoIdKey); KeyParserImpl parser2(kNoIdTypeUrl, ParseNoIdKey); EXPECT_THAT(builder.RegisterKeyParser(&parser1), IsOk()); EXPECT_THAT(builder.RegisterKeyParser(&parser2), StatusIs(absl::StatusCode::kAlreadyExists)); } TEST(SerializationRegistryTest, SerializeKey) { SerializationRegistry::Builder builder; KeySerializerImpl serializer1(SerializeNoIdKey); KeySerializerImpl serializer2(SerializeIdKey); ASSERT_THAT(builder.RegisterKeySerializer(&serializer1), IsOk()); ASSERT_THAT(builder.RegisterKeySerializer(&serializer2), IsOk()); SerializationRegistry registry = std::move(builder).Build(); util::StatusOr> serialization1 = registry.SerializeKey(NoIdKey(), InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization1, IsOk()); EXPECT_THAT((*serialization1)->ObjectIdentifier(), Eq(kNoIdTypeUrl)); util::StatusOr> serialization2 = registry.SerializeKey(IdKey(123), InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization2, IsOk()); EXPECT_THAT((*serialization2)->ObjectIdentifier(), Eq(kIdTypeUrl)); } TEST(SerializationRegistryTest, SerializeKeyNoSecretAccess) { SerializationRegistry::Builder builder; KeySerializerImpl serializer(SerializeNoIdKey); ASSERT_THAT(builder.RegisterKeySerializer(&serializer), IsOk()); SerializationRegistry registry = std::move(builder).Build(); util::StatusOr> serialization = registry.SerializeKey(NoIdKey(), absl::nullopt); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kNoIdTypeUrl)); } TEST(SerializationRegistryTest, SerializeKeyWithoutRegistration) { SerializationRegistry::Builder builder; SerializationRegistry registry = std::move(builder).Build(); ASSERT_THAT(registry .SerializeKey( NoIdKey(), InsecureSecretKeyAccess::Get()) .status(), StatusIs(absl::StatusCode::kNotFound)); } TEST(SerializationRegistryTest, RegisterSameKeySerializer) { SerializationRegistry::Builder builder; KeySerializerImpl serializer(SerializeNoIdKey); EXPECT_THAT(builder.RegisterKeySerializer(&serializer), IsOk()); EXPECT_THAT(builder.RegisterKeySerializer(&serializer), IsOk()); } TEST(SerializationRegistryTest, RegisterDifferentKeySerializerWithSameIndex) { SerializationRegistry::Builder builder; KeySerializerImpl serializer1(SerializeNoIdKey); KeySerializerImpl serializer2(SerializeNoIdKey); EXPECT_THAT(builder.RegisterKeySerializer(&serializer1), IsOk()); EXPECT_THAT(builder.RegisterKeySerializer(&serializer2), StatusIs(absl::StatusCode::kAlreadyExists)); } TEST(SerializationRegistryTest, BuiltFromAnotherRegistry) { SerializationRegistry::Builder builder1; ParametersParserImpl parser1(kNoIdTypeUrl, ParseNoIdParams); ParametersSerializerImpl serializer1( kNoIdTypeUrl, SerializeNoIdParams); ASSERT_THAT(builder1.RegisterParametersParser(&parser1), IsOk()); ASSERT_THAT(builder1.RegisterParametersSerializer(&serializer1), IsOk()); SerializationRegistry registry1 = std::move(builder1).Build(); SerializationRegistry::Builder builder2(registry1); KeyParserImpl parser2(kNoIdTypeUrl, ParseNoIdKey); KeySerializerImpl serializer2(SerializeNoIdKey); ASSERT_THAT(builder2.RegisterKeyParser(&parser2), IsOk()); ASSERT_THAT(builder2.RegisterKeySerializer(&serializer2), IsOk()); SerializationRegistry registry2 = std::move(builder2).Build(); util::StatusOr> params = registry2.ParseParameters(NoIdSerialization()); ASSERT_THAT(params, IsOk()); EXPECT_THAT((*params)->HasIdRequirement(), IsFalse()); EXPECT_THAT(std::type_index(typeid(**params)), std::type_index(typeid(NoIdParams))); util::StatusOr> params_serialization = registry2.SerializeParameters(NoIdParams()); ASSERT_THAT(params_serialization, IsOk()); EXPECT_THAT((*params_serialization)->ObjectIdentifier(), Eq(kNoIdTypeUrl)); util::StatusOr> key = registry2.ParseKey(NoIdSerialization(), InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); EXPECT_THAT(std::type_index(typeid(**key)), std::type_index(typeid(NoIdKey))); util::StatusOr> key_serialization = registry2.SerializeKey(NoIdKey(), InsecureSecretKeyAccess::Get()); ASSERT_THAT(key_serialization, IsOk()); EXPECT_THAT((*key_serialization)->ObjectIdentifier(), Eq(kNoIdTypeUrl)); } TEST(SerializationRegistryTest, RegistryCopy) { SerializationRegistry::Builder builder; ParametersParserImpl parser1(kNoIdTypeUrl, ParseNoIdParams); ParametersSerializerImpl serializer1( kNoIdTypeUrl, SerializeNoIdParams); KeyParserImpl parser2(kNoIdTypeUrl, ParseNoIdKey); KeySerializerImpl serializer2(SerializeNoIdKey); ASSERT_THAT(builder.RegisterParametersParser(&parser1), IsOk()); ASSERT_THAT(builder.RegisterParametersSerializer(&serializer1), IsOk()); ASSERT_THAT(builder.RegisterKeyParser(&parser2), IsOk()); ASSERT_THAT(builder.RegisterKeySerializer(&serializer2), IsOk()); SerializationRegistry registry1 = std::move(builder).Build(); SerializationRegistry registry2 = registry1; util::StatusOr> params = registry2.ParseParameters(NoIdSerialization()); ASSERT_THAT(params, IsOk()); EXPECT_THAT((*params)->HasIdRequirement(), IsFalse()); EXPECT_THAT(std::type_index(typeid(**params)), std::type_index(typeid(NoIdParams))); util::StatusOr> params_serialization = registry2.SerializeParameters(NoIdParams()); ASSERT_THAT(params_serialization, IsOk()); EXPECT_THAT((*params_serialization)->ObjectIdentifier(), Eq(kNoIdTypeUrl)); util::StatusOr> key = registry2.ParseKey(NoIdSerialization(), InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); EXPECT_THAT(std::type_index(typeid(**key)), std::type_index(typeid(NoIdKey))); util::StatusOr> key_serialization = registry2.SerializeKey(NoIdKey(), InsecureSecretKeyAccess::Get()); ASSERT_THAT(key_serialization, IsOk()); EXPECT_THAT((*key_serialization)->ObjectIdentifier(), Eq(kNoIdTypeUrl)); } TEST(SerializationRegistryTest, RegistryMove) { SerializationRegistry::Builder builder; ParametersParserImpl parser1(kNoIdTypeUrl, ParseNoIdParams); ParametersSerializerImpl serializer1( kNoIdTypeUrl, SerializeNoIdParams); KeyParserImpl parser2(kNoIdTypeUrl, ParseNoIdKey); KeySerializerImpl serializer2(SerializeNoIdKey); ASSERT_THAT(builder.RegisterParametersParser(&parser1), IsOk()); ASSERT_THAT(builder.RegisterParametersSerializer(&serializer1), IsOk()); ASSERT_THAT(builder.RegisterKeyParser(&parser2), IsOk()); ASSERT_THAT(builder.RegisterKeySerializer(&serializer2), IsOk()); SerializationRegistry registry1 = std::move(builder).Build(); SerializationRegistry registry2 = std::move(registry1); util::StatusOr> params = registry2.ParseParameters(NoIdSerialization()); ASSERT_THAT(params, IsOk()); EXPECT_THAT((*params)->HasIdRequirement(), IsFalse()); EXPECT_THAT(std::type_index(typeid(**params)), std::type_index(typeid(NoIdParams))); util::StatusOr> params_serialization = registry2.SerializeParameters(NoIdParams()); ASSERT_THAT(params_serialization, IsOk()); EXPECT_THAT((*params_serialization)->ObjectIdentifier(), Eq(kNoIdTypeUrl)); util::StatusOr> key = registry2.ParseKey(NoIdSerialization(), InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); EXPECT_THAT(std::type_index(typeid(**key)), std::type_index(typeid(NoIdKey))); util::StatusOr> key_serialization = registry2.SerializeKey(NoIdKey(), InsecureSecretKeyAccess::Get()); ASSERT_THAT(key_serialization, IsOk()); EXPECT_THAT((*key_serialization)->ObjectIdentifier(), Eq(kNoIdTypeUrl)); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/serialization_test_util.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_SERIALIZATION_TEST_UTIL_H_ #define TINK_INTERNAL_SERIALIZATION_TEST_UTIL_H_ #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/secret_key_access_token.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { constexpr absl::string_view kNoIdTypeUrl = "NoIdTypeUrl"; constexpr absl::string_view kIdTypeUrl = "IdTypeUrl"; // Generic serialization for keys or parameters. class BaseSerialization : public Serialization { public: explicit BaseSerialization(absl::string_view object_identifier) : object_identifier_(object_identifier) {} absl::string_view ObjectIdentifier() const override { return object_identifier_; } bool operator==(const BaseSerialization& other) const { return object_identifier_ == other.object_identifier_; } private: std::string object_identifier_; }; // Serialization for keys or parameters without an ID requirement. class NoIdSerialization : public BaseSerialization { public: NoIdSerialization() : BaseSerialization(kNoIdTypeUrl) {} }; // Serialization for parameters with an ID requirement. class IdParamsSerialization : public BaseSerialization { public: IdParamsSerialization() : BaseSerialization(kIdTypeUrl) {} }; // Serialization for keys with an ID requirement. class IdKeySerialization : public BaseSerialization { public: explicit IdKeySerialization(int id) : BaseSerialization(kIdTypeUrl), id_(id) {} int GetKeyId() const { return id_; } private: int id_; }; // Parameters without an ID requirement. class NoIdParams : public Parameters { public: bool HasIdRequirement() const override { return false; } bool operator==(const Parameters& other) const override { return !other.HasIdRequirement(); } }; // Key without an ID requirement. class NoIdKey : public Key { public: const Parameters& GetParameters() const override { return params_; } absl::optional GetIdRequirement() const override { return absl::nullopt; } bool operator==(const Key& other) const override { return params_ == other.GetParameters() && absl::nullopt == other.GetIdRequirement(); } private: NoIdParams params_; }; // Parameters with an ID requirement. class IdParams : public Parameters { public: bool HasIdRequirement() const override { return true; } bool operator==(const Parameters& other) const override { return other.HasIdRequirement(); } }; // Key with an ID requirement. class IdKey : public Key { public: explicit IdKey(int id) : id_(id) {} const Parameters& GetParameters() const override { return params_; } absl::optional GetIdRequirement() const override { return id_; } bool operator==(const Key& other) const override { return params_ == other.GetParameters() && id_ == other.GetIdRequirement(); } private: IdParams params_; int id_; }; // Parse `serialization` into parameters without an ID requirement. inline util::StatusOr ParseNoIdParams( NoIdSerialization serialization) { return NoIdParams(); } // Parse `serialization` into parameters with an ID requirement. inline util::StatusOr ParseIdParams( IdParamsSerialization serialization) { return IdParams(); } // Serialize `parameters` without an ID requirement. inline util::StatusOr SerializeNoIdParams( NoIdParams parameters) { return NoIdSerialization(); } // Serialize `parameters` with an ID requirement. inline util::StatusOr SerializeIdParams( IdParams parameters) { return IdParamsSerialization(); } // Parse `serialization` into a key without an ID requirement. inline util::StatusOr ParseNoIdKey( NoIdSerialization serialization, absl::optional token) { return NoIdKey(); } // Parse `serialization` into a key with an ID requirement. inline util::StatusOr ParseIdKey( IdKeySerialization serialization, absl::optional token) { return IdKey(serialization.GetKeyId()); } // Serialize `key` without an ID requirement. inline util::StatusOr SerializeNoIdKey( NoIdKey key, absl::optional token) { return NoIdSerialization(); } // Serialize `key` with an ID requirement. inline util::StatusOr SerializeIdKey( IdKey key, absl::optional token) { return IdKeySerialization(key.GetIdRequirement().value()); } } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_SERIALIZATION_TEST_UTIL_H_ ================================================ FILE: cc/internal/serialization_test_util_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/serialization_test_util.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/types/optional.h" #include "tink/insecure_secret_key_access.h" #include "tink/parameters.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOkAndHolds; using ::testing::Eq; using ::testing::IsFalse; using ::testing::IsTrue; using ::testing::Not; TEST(SerializationTest, Create) { EXPECT_THAT(BaseSerialization("base_type_url").ObjectIdentifier(), Eq("base_type_url")); EXPECT_THAT(NoIdSerialization().ObjectIdentifier(), Eq(kNoIdTypeUrl)); EXPECT_THAT(IdParamsSerialization().ObjectIdentifier(), Eq(kIdTypeUrl)); IdKeySerialization id_key(123); EXPECT_THAT(id_key.ObjectIdentifier(), Eq(kIdTypeUrl)); EXPECT_THAT(id_key.GetKeyId(), Eq(123)); } TEST(NoIdParamsTest, Create) { NoIdParams params; EXPECT_THAT(params.HasIdRequirement(), IsFalse()); EXPECT_THAT(params, Eq(NoIdParams())); EXPECT_THAT(params, Not(Eq(IdParams()))); } TEST(NoIdParamsTest, ParseAndSerialize) { EXPECT_THAT(ParseNoIdParams(NoIdSerialization()), IsOkAndHolds(NoIdParams())); EXPECT_THAT(SerializeNoIdParams(NoIdParams()), IsOkAndHolds(NoIdSerialization())); } TEST(IdParamsTest, Create) { IdParams params; EXPECT_THAT(params.HasIdRequirement(), IsTrue()); EXPECT_THAT(params, Eq(IdParams())); EXPECT_THAT(params, Not(Eq(NoIdParams()))); } TEST(IdParamsTest, ParseAndSerialize) { EXPECT_THAT(ParseIdParams(IdParamsSerialization()), IsOkAndHolds(IdParams())); EXPECT_THAT(SerializeIdParams(IdParams()), IsOkAndHolds(IdParamsSerialization())); } TEST(NoIdKeyTest, Create) { NoIdKey key; EXPECT_THAT(key.GetIdRequirement(), Eq(absl::nullopt)); EXPECT_THAT(key.GetParameters(), Eq(NoIdParams())); EXPECT_THAT(key, Eq(NoIdKey())); EXPECT_THAT(key, Not(Eq(IdKey(123)))); } TEST(NoIdKeyTest, ParseAndSerialize) { EXPECT_THAT(ParseNoIdKey(NoIdSerialization(), InsecureSecretKeyAccess::Get()), IsOkAndHolds(NoIdKey())); EXPECT_THAT(SerializeNoIdKey(NoIdKey(), InsecureSecretKeyAccess::Get()), IsOkAndHolds(NoIdSerialization())); } TEST(IdKeyTest, Create) { IdKey key(123); EXPECT_THAT(key.GetIdRequirement(), Eq(123)); EXPECT_THAT(key.GetParameters(), Eq(IdParams())); EXPECT_THAT(key, Eq(IdKey(123))); EXPECT_THAT(key, Not(Eq(IdKey(456)))); EXPECT_THAT(key, Not(Eq(NoIdKey()))); } TEST(IdKeyTest, ParseAndSerialize) { EXPECT_THAT(ParseIdKey(IdKeySerialization(123), InsecureSecretKeyAccess::Get()), IsOkAndHolds(IdKey(123))); EXPECT_THAT(SerializeIdKey(IdKey(123), InsecureSecretKeyAccess::Get()), IsOkAndHolds(IdKeySerialization(123))); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/serializer_index.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_SERIALIZER_INDEX_H_ #define TINK_INTERNAL_SERIALIZER_INDEX_H_ #include #include #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/parameters.h" namespace crypto { namespace tink { namespace internal { class SerializerIndex { public: // Create registry lookup key for the combination of the `KeyOrParameterT` and // `SerializationT` types. Useful for key and parameters serializers. template static SerializerIndex Create() { return SerializerIndex(std::type_index(typeid(KeyOrParameterT)), std::type_index(typeid(SerializationT))); } // Create registry lookup key for `SerializationT` type and `parameters`. // Useful for the serialization registry. template static SerializerIndex Create(const Parameters& parameters) { return SerializerIndex(std::type_index(typeid(parameters)), std::type_index(typeid(SerializationT))); } // Create registry lookup key for `SerializationT` type and `key`. Useful for // the serialization registry. template static SerializerIndex Create(const Key& key) { return SerializerIndex(std::type_index(typeid(key)), std::type_index(typeid(SerializationT))); } // Returns true if key/parameters index and serialization type index match. bool operator==(const SerializerIndex& other) const { return kp_index_ == other.kp_index_ && serialization_index_ == other.serialization_index_; } // Required function to make `SerializerIndex` hashable for Abseil hash maps. template friend H AbslHashValue(H h, const SerializerIndex& index) { return H::combine(std::move(h), index.kp_index_, index.serialization_index_); } private: SerializerIndex(std::type_index kp_index, std::type_index serialization_index) : kp_index_(kp_index), serialization_index_(serialization_index) {} std::type_index kp_index_; std::type_index serialization_index_; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_SERIALIZER_INDEX_H_ ================================================ FILE: cc/internal/serializer_index_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/internal/serializer_index.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/internal/serialization_test_util.h" namespace crypto { namespace tink { namespace internal { using ::testing::Eq; using ::testing::Not; TEST(SerializerIndex, CreateEquivalentFromParameters) { // Multi-parameter templates require extra surrounding parentheses. ASSERT_THAT((SerializerIndex::Create()), Eq((SerializerIndex::Create()))); ASSERT_THAT((SerializerIndex::Create()), Eq((SerializerIndex::Create(NoIdParams())))); ASSERT_THAT((SerializerIndex::Create(NoIdParams())), Eq((SerializerIndex::Create(NoIdParams())))); } TEST(SerializerIndex, CreateFromDifferentParametersType) { // Multi-parameter templates require extra surrounding parentheses. ASSERT_THAT( (SerializerIndex::Create()), Not(Eq((SerializerIndex::Create())))); ASSERT_THAT( (SerializerIndex::Create(NoIdParams())), Not(Eq((SerializerIndex::Create(IdParams()))))); } TEST(SerializerIndex, CreateFromSameParametersTypeWithDifferentSerialization) { // Multi-parameter templates require extra surrounding parentheses. ASSERT_THAT( (SerializerIndex::Create()), Not(Eq((SerializerIndex::Create())))); ASSERT_THAT( (SerializerIndex::Create(NoIdParams())), Not(Eq((SerializerIndex::Create(NoIdParams()))))); } TEST(SerializerIndex, CreateEquivalentFromKey) { // Multi-parameter templates require extra surrounding parentheses. ASSERT_THAT((SerializerIndex::Create()), Eq((SerializerIndex::Create()))); ASSERT_THAT((SerializerIndex::Create()), Eq((SerializerIndex::Create(NoIdKey())))); ASSERT_THAT((SerializerIndex::Create(NoIdKey())), Eq((SerializerIndex::Create(NoIdKey())))); } TEST(SerializerIndex, CreateFromDifferentKeyType) { // Multi-parameter templates require extra surrounding parentheses. ASSERT_THAT((SerializerIndex::Create()), Not(Eq((SerializerIndex::Create())))); ASSERT_THAT( (SerializerIndex::Create(NoIdKey())), Not(Eq((SerializerIndex::Create(IdKey(/*id=*/1)))))); } TEST(SerializerIndex, CreateFromSameKeyTypeWithDifferentSerialization) { // Multi-parameter templates require extra surrounding parentheses. ASSERT_THAT( (SerializerIndex::Create()), Not(Eq((SerializerIndex::Create())))); ASSERT_THAT( (SerializerIndex::Create(NoIdKey())), Not(Eq((SerializerIndex::Create(NoIdKey()))))); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/ssl_unique_ptr.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_SSL_UNIQUE_PTR_H_ #define TINK_INTERNAL_SSL_UNIQUE_PTR_H_ #include // Every header in BoringSSL includes base.h, which in turn defines // OPENSSL_IS_BORINGSSL. So we include this common header here to "force" the // definition of OPENSSL_IS_BORINGSSL in case BoringSSL is used. #include "openssl/crypto.h" #ifndef OPENSSL_IS_BORINGSSL #include "openssl/bn.h" #include "openssl/cmac.h" #include "openssl/ec.h" #include "openssl/evp.h" #include "openssl/hmac.h" #include "openssl/rsa.h" #endif namespace crypto { namespace tink { namespace internal { #ifdef OPENSSL_IS_BORINGSSL // In this case, simply use BoringSSL's UniquePtr. template using SslUniquePtr = ::bssl::UniquePtr; #else // We define SslUniquePtr similarly to how bssl::UniquePtr is defined, // i.e., as a unique_ptr with custom deleter for each type T. The difference // w.r.t. the BoringSSL equivalent is that we have to define each deleter here // explicitly, while bssl::UniquePtr allows for forward declaration and // later specialization when including specific headers. This is possible in // BoringSSL because each module's header defines the appropriate deleter with // BORINGSSL_MAKE_DELETER, which is not the case for OpenSSL. template struct Deleter { void operator()(T* ptr); }; // Here are all the custom deleters. template <> struct Deleter { void operator()(BIO* ptr) { BIO_free(ptr); } }; template <> struct Deleter { void operator()(EVP_CIPHER_CTX* ptr) { EVP_CIPHER_CTX_free(ptr); } }; template <> struct Deleter { void operator()(BIGNUM* ptr) { BN_free(ptr); } }; template <> struct Deleter { void operator()(BN_CTX* ptr) { BN_CTX_free(ptr); } }; template <> struct Deleter { void operator()(RSA* ptr) { RSA_free(ptr); } }; template <> struct Deleter { void operator()(EC_POINT* ptr) { EC_POINT_free(ptr); } }; template <> struct Deleter { void operator()(EC_GROUP* ptr) { EC_GROUP_free(ptr); } }; template <> struct Deleter { void operator()(EC_KEY* ptr) { EC_KEY_free(ptr); } }; template <> struct Deleter { void operator()(EVP_PKEY* ptr) { EVP_PKEY_free(ptr); } }; template <> struct Deleter { void operator()(EVP_PKEY_CTX* ptr) { EVP_PKEY_CTX_free(ptr); } }; template <> struct Deleter { void operator()(ECDSA_SIG* ptr) { ECDSA_SIG_free(ptr); } }; template <> struct Deleter { void operator()(CMAC_CTX* ptr) { CMAC_CTX_free(ptr); } }; template <> struct Deleter { void operator()(EVP_MD_CTX* ptr) { EVP_MD_CTX_free(ptr); } }; template <> struct Deleter { void operator()(HMAC_CTX* ptr) { HMAC_CTX_free(ptr); } }; template using SslUniquePtr = std::unique_ptr >; #endif // OPENSSL_IS_BORINGSSL } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_SSL_UNIQUE_PTR_H_ ================================================ FILE: cc/internal/ssl_util.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_SSL_UTIL_H_ #define TINK_INTERNAL_SSL_UTIL_H_ // Every header in BoringSSL includes base.h, which in turn defines // OPENSSL_IS_BORINGSSL. So we include this common header here to "force" the // definition of OPENSSL_IS_BORINGSSL in case BoringSSL is used. #include "openssl/crypto.h" namespace crypto { namespace tink { namespace internal { // Returns true if currently using BoringSSL; false (OpenSSL) otherwise. inline bool IsBoringSsl() { #ifdef OPENSSL_IS_BORINGSSL return true; #else return false; #endif } } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_SSL_UTIL_H_ ================================================ FILE: cc/internal/test_file_util.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/test_file_util.h" #include #include #include #include #include "gtest/gtest.h" #include "absl/log/check.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "tink/subtle/random.h" #include "tink/util/status.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace internal { util::Status CreateTestFile(absl::string_view filename, absl::string_view file_content) { std::string full_filename = absl::StrCat(test::TmpDir(), "/", filename); std::ofstream output_stream(full_filename, std::ios::binary); if (!output_stream) { return util::Status(absl::StatusCode::kInternal, "Cannot open file"); } output_stream.write(file_content.data(), file_content.size()); return util::OkStatus(); } std::string GetTestFileNamePrefix() { const testing::TestInfo* const test_info = testing::UnitTest::GetInstance()->current_test_info(); CHECK(test_info != nullptr); std::string random_string = subtle::Random::GetRandomBytes(/*length=*/16); std::string test_suite_name = test_info->test_suite_name(); std::string test_name = test_info->name(); // Parametrized tests return test_suite_name of the form / // and name of the form /. // In this case, get only the prefix and test name. Keeping all of these may // result in a file name that is too long. if (test_info->value_param() != nullptr) { std::vector test_suite_parts = absl::StrSplit(test_info->test_suite_name(), '/'); CHECK_GE(test_suite_parts.size(), 1); test_suite_name = test_suite_parts[0]; std::vector test_name_parts = absl::StrSplit(test_info->name(), '/'); CHECK_GE(test_name_parts.size(), 1); test_name = test_name_parts[0]; } return absl::StrCat(test_suite_name, "_", test_name, "_", absl::BytesToHexString(random_string)); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/test_file_util.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_TEST_FILE_UTIL_H_ #define TINK_INTERNAL_TEST_FILE_UTIL_H_ #include #include "absl/strings/string_view.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { // File utilities for testing. /////////////////////////////////////////////////////////////////////////////// // TODO(ckl): Move other file related functionality from cc/util/test_util.h // Returns the path of the specified file in the runfiles directory. std::string RunfilesPath(absl::string_view path); crypto::tink::util::Status CreateTestFile(absl::string_view filename, absl::string_view file_content); // Returns the prefix to use for files to use in tests. The result will be of // the form: __. std::string GetTestFileNamePrefix(); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_TEST_FILE_UTIL_H_ ================================================ FILE: cc/internal/test_file_util_bazel.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/test_file_util.h" #include #include #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tools/cpp/runfiles/runfiles.h" namespace crypto { namespace tink { namespace internal { using ::bazel::tools::cpp::runfiles::Runfiles; std::string RunfilesPath(absl::string_view path) { std::string error; std::unique_ptr runfiles(Runfiles::CreateForTest(&error)); if (runfiles == nullptr) { std::clog << "Unable to determine runfile path: " << error; exit(1); } const char* workspace_dir = getenv("TEST_WORKSPACE"); if (workspace_dir == nullptr || workspace_dir[0] == '\0') { std::clog << "Unable to determine workspace name." << std::endl; exit(1); } return runfiles->Rlocation(absl::StrCat(workspace_dir, "/", path)); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/test_file_util_cmake.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/test_file_util.h" #include #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" namespace crypto { namespace tink { namespace internal { std::string RunfilesPath(absl::string_view path) { return absl::StrCat("./", path); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/test_random_access_stream.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/test_random_access_stream.h" #include #include #include #include #include #include "absl/status/status.h" #include "tink/random_access_stream.h" #include "tink/util/buffer.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { util::Status TestRandomAccessStream::PRead(int64_t position, int count, util::Buffer* dest_buffer) { if (dest_buffer == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "dest_buffer must be non-null"); } if (count <= 0) { return util::Status(absl::StatusCode::kInvalidArgument, "count must be positive"); } if (count > dest_buffer->allocated_size()) { return util::Status(absl::StatusCode::kInvalidArgument, "buffer too small"); } if (position < 0) { return util::Status(absl::StatusCode::kInvalidArgument, "position cannot be negative"); } if (position >= content_.size()) { dest_buffer->set_size(0).IgnoreError(); return util::Status(absl::StatusCode::kOutOfRange, "EOF"); } util::Status status = dest_buffer->set_size(count); if (!status.ok()) { return status; } int read_count = std::min(count, static_cast(content_.size() - position)); std::copy(content_.begin() + position, content_.begin() + position + read_count, dest_buffer->get_mem_block()); status = dest_buffer->set_size(read_count); if (!status.ok()) { return status; } if (position + read_count == content_.size()) { // We reached EOF. return util::Status(absl::StatusCode::kOutOfRange, "EOF"); } return util::OkStatus(); } util::Status ReadAllFromRandomAccessStream( RandomAccessStream* random_access_stream, std::string& contents, int chunk_size) { if (chunk_size < 1) { return util::Status(absl::StatusCode::kInvalidArgument, "chunk_size must be greater than zero"); } contents.clear(); std::unique_ptr buffer = *std::move(util::Buffer::New(chunk_size)); int64_t position = 0; auto status = util::OkStatus(); while (status.ok()) { status = random_access_stream->PRead(position, chunk_size, buffer.get()); contents.append(buffer->get_mem_block(), buffer->size()); position = contents.size(); } return status; } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/test_random_access_stream.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_TEST_RANDOM_ACCESS_STREAM_H_ #define TINK_INTERNAL_TEST_RANDOM_ACCESS_STREAM_H_ #include #include #include #include #include "absl/strings/string_view.h" #include "tink/random_access_stream.h" #include "tink/util/buffer.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { // A simple test-only RandomAccessStream implementation that reads from a // std::string. class TestRandomAccessStream : public RandomAccessStream { public: explicit TestRandomAccessStream(std::string content) : content_(std::move(content)) {} // Move only. TestRandomAccessStream(TestRandomAccessStream&& other) = default; TestRandomAccessStream& operator=(TestRandomAccessStream&& other) = default; TestRandomAccessStream(const TestRandomAccessStream&) = delete; TestRandomAccessStream& operator=(const TestRandomAccessStream&) = delete; util::Status PRead(int64_t position, int count, util::Buffer* dest_buffer) override; util::StatusOr size() override { return content_.size(); } private: std::string content_; }; // Reads the entire `random_access_stream` using a buffer of size `chunk_size` // until no more bytes can be read, and puts the read bytes into `contents`. // Returns the status of the last call to random_access_stream->PRead(). util::Status ReadAllFromRandomAccessStream( RandomAccessStream* random_access_stream, std::string& contents, int chunk_size = 42); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_TEST_RANDOM_ACCESS_STREAM_H_ ================================================ FILE: cc/internal/test_random_access_stream_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/test_random_access_stream.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/subtle/random.h" #include "tink/util/buffer.h" #include "tink/util/status.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::StatusIs; TEST(TestRandomAccessStreamTest, ReadAllSucceeds) { const int buffer_size = 4 * 1024; const int stream_size = 100 * 1024; std::string stream_content = subtle::Random::GetRandomBytes(stream_size); auto rand_access_stream = std::make_unique(stream_content); auto buffer = *std::move(util::Buffer::New(buffer_size)); util::Status pread_status = util::OkStatus(); std::string result; do { pread_status = rand_access_stream->PRead(result.size(), buffer_size, buffer.get()); result.append(buffer->get_mem_block(), buffer->size()); } while (pread_status.ok()); EXPECT_THAT(pread_status, StatusIs(absl::StatusCode::kOutOfRange)); EXPECT_EQ(result, stream_content); } TEST(TestRandomAccessStreamTest, PreadAllInOnePread) { const int stream_size = 8 * 1024; std::string stream_content = subtle::Random::GetRandomBytes(stream_size); auto rand_access_stream = std::make_unique(stream_content); auto buffer = *std::move(util::Buffer::New(stream_size)); ASSERT_THAT( rand_access_stream->PRead(/*position=*/0, stream_size, buffer.get()), StatusIs(absl::StatusCode::kOutOfRange)); EXPECT_EQ(std::string(buffer->get_mem_block(), buffer->size()), stream_content); } TEST(TestRandomAccessStreamTest, PreadCountLargerThanBufferFails) { const int buffer_size = 4 * 1024; const int stream_size = 100 * 1024; std::string stream_content = subtle::Random::GetRandomBytes(stream_size); auto rand_access_stream = std::make_unique(stream_content); auto buffer = *std::move(util::Buffer::New(buffer_size)); EXPECT_THAT( rand_access_stream->PRead(/*position=*/0, buffer_size + 1, buffer.get()), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(TestRandomAccessStreamTest, InvalidPosition) { const int buffer_size = 4 * 1024; const int stream_size = 100 * 1024; std::string stream_content = subtle::Random::GetRandomBytes(stream_size); auto rand_access_stream = std::make_unique(stream_content); auto buffer = *std::move(util::Buffer::New(buffer_size)); EXPECT_THAT(rand_access_stream->PRead(-1, buffer_size, buffer.get()), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(TestRandomAccessStreamTest, PreadWithNullBufferFails) { const int stream_size = 100 * 1024; std::string stream_content = subtle::Random::GetRandomBytes(stream_size); auto rand_access_stream = std::make_unique(stream_content); EXPECT_THAT(rand_access_stream->PRead(/*position=*/0, stream_size, /*dest_buffer=*/nullptr), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(TestRandomAccessStreamTest, PreadWithEmptyStreamEof) { const int buffer_size = 4 * 1024; std::string stream_content; // Empty string. auto rand_access_stream = std::make_unique(stream_content); auto buffer = *std::move(util::Buffer::New(buffer_size)); EXPECT_THAT( rand_access_stream->PRead(/*position=*/0, buffer_size, buffer.get()), StatusIs(absl::StatusCode::kOutOfRange)); } // Pread of the last partial block populates the buffer with the remaining // bytes and returns an EOF status. TEST(TestRandomAccessStreamTest, PreadTheLastPartialBlockReturnsEof) { const int buffer_size = 4 * 1024; const int stream_size = 100 * 1024; std::string stream_content = subtle::Random::GetRandomBytes(stream_size); auto rand_access_stream = std::make_unique(stream_content); auto buffer = *std::move(util::Buffer::New(buffer_size)); // Read at a postion so that only buffer_size - 1 bytes are left. EXPECT_THAT(rand_access_stream->PRead(stream_size - buffer_size + 1, buffer_size, buffer.get()), StatusIs(absl::StatusCode::kOutOfRange)); EXPECT_EQ(buffer->size(), buffer_size - 1); EXPECT_EQ(std::string(buffer->get_mem_block(), buffer->size()), stream_content.substr(stream_size - buffer_size + 1)); } TEST(TestRandomAccessStreamTest, ReadAllFromRandomAccessStreamSucceeds) { std::string content_to_read = subtle::Random::GetRandomBytes(4 * 1024); auto test_random_access_stream = std::make_unique(content_to_read); std::string read_content; EXPECT_THAT(ReadAllFromRandomAccessStream(test_random_access_stream.get(), read_content, /*chunk_size=*/128), StatusIs(absl::StatusCode::kOutOfRange)); EXPECT_EQ(content_to_read, read_content); } TEST(TestRandomAccessStreamTest, ReadAllFromRandomAccessStreamFailsWhenChunkIsLessThanOne) { std::string content_to_read = subtle::Random::GetRandomBytes(4 * 1024); auto test_random_access_stream = std::make_unique(content_to_read); std::string read_content; EXPECT_THAT(ReadAllFromRandomAccessStream(test_random_access_stream.get(), read_content, /*chunk_size=*/0), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(ReadAllFromRandomAccessStream(test_random_access_stream.get(), read_content, /*chunk_size=*/-10), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/util.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/util.h" #include #include #include "absl/strings/ascii.h" #include "absl/log/log.h" #include "absl/strings/string_view.h" namespace crypto { namespace tink { namespace internal { absl::string_view EnsureStringNonNull(absl::string_view str) { if (str.empty() && str.data() == nullptr) { return absl::string_view(""); } return str; } bool BuffersOverlap(absl::string_view first, absl::string_view second) { // first begins within second's buffer. bool first_begins_in_second = std::less_equal{}(second.begin(), first.begin()) && std::less{}(first.begin(), second.end()); // second begins within first's buffer. bool second_begins_in_first = std::less_equal{}(first.begin(), second.begin()) && std::less{}(second.begin(), first.end()); return first_begins_in_second || second_begins_in_first; } bool BuffersAreIdentical(absl::string_view first, absl::string_view second) { return !first.empty() && !second.empty() && std::equal_to{}(first.begin(), second.begin()) && std::equal_to{}( std::prev(first.end()), std::prev(second.end())); } bool IsPrintableAscii(absl::string_view input) { for (char c : input) { if (!absl::ascii_isprint(c) || absl::ascii_isspace(c)) { return false; } } return true; } void LogFatal(absl::string_view msg) { LOG(FATAL) << msg; } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/internal/util.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_INTERNAL_UTIL_H_ #define TINK_INTERNAL_UTIL_H_ #include "absl/base/attributes.h" #include "absl/strings/string_view.h" namespace crypto { namespace tink { namespace internal { // Return an empty string if str.data() is nullptr; otherwise return str. absl::string_view EnsureStringNonNull(absl::string_view str); // Returns true if `first` overlaps with `second`. bool BuffersOverlap(absl::string_view first, absl::string_view second); // Returns true if `first` fully overlaps with `second`. bool BuffersAreIdentical(absl::string_view first, absl::string_view second); // Returns true if `input` only contains printable ASCII characters (whitespace // is not allowed). bool IsPrintableAscii(absl::string_view input); // Returns true if built on Windows; false otherwise. inline bool IsWindows() { #if defined(_WIN32) return true; #else return false; #endif } // Wraps Abseil's LOG(FATAL) macro and sets the [noreturn] attribute, which is // useful for avoiding false positive [-Werror=return-type] compiler errors. ABSL_ATTRIBUTE_NORETURN void LogFatal(absl::string_view msg); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_INTERNAL_UTIL_H_ ================================================ FILE: cc/internal/util_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/internal/util.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/string_view.h" namespace crypto { namespace tink { namespace internal { namespace { using ::testing::IsFalse; using ::testing::IsTrue; constexpr absl::string_view kLongString = "a long buffer with \n several \n newlines"; TEST(UtilTest, EnsureStringNonNull) { // Purposely create a string_view from nullptr. auto null_str = absl::string_view(nullptr, 0); EXPECT_EQ(EnsureStringNonNull(null_str), absl::string_view("")); auto uninit_str = absl::string_view(); EXPECT_EQ(EnsureStringNonNull(uninit_str), absl::string_view("")); auto regular_str = absl::string_view("This is a non-empty non-null str"); EXPECT_EQ(EnsureStringNonNull(regular_str), regular_str); } TEST(BuffersOverlapTest, BufferOverlapEmpty) { absl::string_view empty = ""; EXPECT_FALSE(BuffersOverlap(empty, empty)); EXPECT_FALSE(BuffersOverlap(empty, "")); } TEST(BuffersOverlapTest, BufferOverlapSeparate) { absl::string_view first = "first"; absl::string_view second = "second"; EXPECT_FALSE(BuffersOverlap(first, second)); EXPECT_TRUE(BuffersOverlap(first, first)); } TEST(BuffersOverlapTest, BufferOverlap) { absl::string_view long_buffer = kLongString; EXPECT_TRUE(BuffersOverlap(long_buffer, long_buffer)); EXPECT_TRUE( BuffersOverlap(long_buffer.substr(0, 10), long_buffer.substr(9, 5))); EXPECT_FALSE( BuffersOverlap(long_buffer.substr(0, 10), long_buffer.substr(10, 5))); EXPECT_TRUE( BuffersOverlap(long_buffer.substr(9, 5), long_buffer.substr(0, 10))); EXPECT_FALSE( BuffersOverlap(long_buffer.substr(10, 5), long_buffer.substr(0, 10))); } TEST(BuffersAreIdenticalTest, EmptyString) { std::string empty_str = ""; absl::string_view empty = ""; EXPECT_FALSE(BuffersAreIdentical(empty, empty)); EXPECT_FALSE(BuffersAreIdentical(absl::string_view(empty_str), absl::string_view(empty_str))); EXPECT_FALSE(BuffersAreIdentical(empty, "")); EXPECT_FALSE(BuffersAreIdentical(empty, absl::string_view(empty_str))); } TEST(BuffersAreIdenticalTest, BuffersAreIdentical) { auto some_string = std::string(kLongString); auto buffer = absl::string_view(some_string); EXPECT_TRUE(BuffersAreIdentical(buffer, buffer)); // Make sure BuffersAreIdentical is not checking for string equality. std::string identical_string = some_string; EXPECT_FALSE( BuffersAreIdentical(buffer, absl::string_view(identical_string))); } TEST(BuffersAreIdenticalTest, PartialOverlapFails) { auto some_string = std::string(kLongString); auto buffer = absl::string_view(some_string); EXPECT_FALSE(BuffersAreIdentical(buffer.substr(0, 10), buffer.substr(9, 5))); EXPECT_FALSE(BuffersAreIdentical(buffer.substr(0, 10), buffer.substr(10, 5))); EXPECT_FALSE(BuffersAreIdentical(buffer.substr(9, 5), buffer.substr(0, 10))); EXPECT_FALSE(BuffersAreIdentical(buffer.substr(10, 5), buffer.substr(0, 10))); } TEST(UtilTest, IsPrintableAscii) { const std::string input = "!\"#$%&'()*+,-./" "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" "abcdefghijklmnopqrstuvwxyz{|}~"; EXPECT_THAT(IsPrintableAscii(input), IsTrue()); } TEST(UtilTest, IsNotPrintableAscii) { EXPECT_THAT(IsPrintableAscii("\n"), IsFalse()); EXPECT_THAT(IsPrintableAscii("\t"), IsFalse()); EXPECT_THAT(IsPrintableAscii(" "), IsFalse()); EXPECT_THAT(IsPrintableAscii(std::string("\x7f", 1)), IsFalse()); EXPECT_THAT(IsPrintableAscii("ö"), IsFalse()); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/json_keyset_reader.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JSON_KEYSET_READER_H_ #define TINK_JSON_KEYSET_READER_H_ #include #include #include #include #include "absl/strings/string_view.h" #include "tink/keyset_reader.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // A KeysetReader that can read from some source cleartext or // encrypted keysets in proto JSON wire format, cf. // https://developers.google.com/protocol-buffers/docs/encoding class JsonKeysetReader : public KeysetReader { public: static crypto::tink::util::StatusOr> New( std::unique_ptr keyset_stream); static crypto::tink::util::StatusOr> New( absl::string_view serialized_keyset); crypto::tink::util::StatusOr> Read() override; crypto::tink::util::StatusOr< std::unique_ptr> ReadEncrypted() override; private: explicit JsonKeysetReader(std::unique_ptr keyset_stream) : serialized_keyset_(""), keyset_stream_(std::move(keyset_stream)) {} explicit JsonKeysetReader(absl::string_view serialized_keyset) : serialized_keyset_(serialized_keyset), keyset_stream_(nullptr) {} std::string serialized_keyset_; std::unique_ptr keyset_stream_; }; } // namespace tink } // namespace crypto #endif // TINK_JSON_KEYSET_READER_H_ ================================================ FILE: cc/json_keyset_writer.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JSON_KEYSET_WRITER_H_ #define TINK_JSON_KEYSET_WRITER_H_ #include #include #include #include "absl/strings/string_view.h" #include "tink/keyset_writer.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // A KeysetWriter that can write to some destination cleartext // or encrypted keysets in proto JSON wire format, cf. // https://developers.google.com/protocol-buffers/docs/encoding class JsonKeysetWriter : public KeysetWriter { public: static crypto::tink::util::StatusOr> New( std::unique_ptr destination_stream); crypto::tink::util::Status Write(const google::crypto::tink::Keyset& keyset) override;; crypto::tink::util::Status Write(const google::crypto::tink::EncryptedKeyset& encrypted_keyset) override; private: explicit JsonKeysetWriter(std::unique_ptr destination_stream) : destination_stream_(std::move(destination_stream)) {} std::unique_ptr destination_stream_; }; } // namespace tink } // namespace crypto #endif // TINK_JSON_KEYSET_WRITER_H_ ================================================ FILE: cc/jwt/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "raw_jwt", srcs = ["raw_jwt.cc"], hdrs = ["raw_jwt.h"], include_prefix = "tink/jwt", visibility = ["//visibility:public"], deps = [ "//jwt/internal:json_util", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:str_format", "@com_google_absl//absl/time", "@com_google_absl//absl/types:optional", "@com_google_protobuf//:protobuf", ], ) cc_library( name = "verified_jwt", srcs = ["verified_jwt.cc"], hdrs = ["verified_jwt.h"], include_prefix = "tink/jwt", visibility = ["//visibility:public"], deps = [ ":raw_jwt", "//jwt/internal:json_util", "//util:status", "//util:statusor", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:str_format", "@com_google_absl//absl/time", "@com_google_protobuf//:protobuf", ], ) cc_library( name = "jwt_validator", srcs = ["jwt_validator.cc"], hdrs = ["jwt_validator.h"], include_prefix = "tink/jwt", visibility = ["//visibility:public"], deps = [ ":raw_jwt", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/time", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "jwt_mac", hdrs = ["jwt_mac.h"], include_prefix = "tink/jwt", visibility = ["//visibility:public"], deps = [ ":jwt_validator", ":raw_jwt", ":verified_jwt", "//util:status", "//util:statusor", "@com_google_absl//absl/strings", ], ) cc_library( name = "jwt_public_key_sign", hdrs = ["jwt_public_key_sign.h"], include_prefix = "tink/jwt", visibility = ["//visibility:public"], deps = [ ":raw_jwt", "//util:status", "//util:statusor", "@com_google_absl//absl/strings", ], ) cc_library( name = "jwt_public_key_verify", hdrs = ["jwt_public_key_verify.h"], include_prefix = "tink/jwt", visibility = ["//visibility:public"], deps = [ ":jwt_validator", ":verified_jwt", "//util:status", "//util:statusor", "@com_google_absl//absl/strings", ], ) cc_library( name = "jwt_mac_config", srcs = ["jwt_mac_config.cc"], hdrs = ["jwt_mac_config.h"], include_prefix = "tink/jwt", visibility = ["//visibility:public"], deps = [ "//:registry", "//config:config_util", "//config:tink_fips", "//jwt/internal:jwt_hmac_key_manager", "//jwt/internal:jwt_mac_wrapper", "//proto:config_cc_proto", "//util:status", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/memory", ], ) cc_library( name = "jwt_key_templates", srcs = ["jwt_key_templates.cc"], hdrs = ["jwt_key_templates.h"], include_prefix = "tink/jwt", visibility = ["//visibility:public"], deps = [ "//internal:bn_util", "//internal:ssl_unique_ptr", "//proto:common_cc_proto", "//proto:jwt_ecdsa_cc_proto", "//proto:jwt_hmac_cc_proto", "//proto:jwt_rsa_ssa_pkcs1_cc_proto", "//proto:jwt_rsa_ssa_pss_cc_proto", "//proto:tink_cc_proto", "//util:statusor", "@boringssl//:crypto", ], ) cc_library( name = "jwk_set_converter", srcs = ["jwk_set_converter.cc"], hdrs = ["jwk_set_converter.h"], include_prefix = "tink/jwt", visibility = ["//visibility:public"], deps = [ "//:binary_keyset_writer", "//:keyset_handle", "//internal:ec_util", "//internal:ssl_unique_ptr", "//jwt/internal:json_util", "//jwt/internal:jwt_format", "//proto:jwt_ecdsa_cc_proto", "//proto:jwt_rsa_ssa_pkcs1_cc_proto", "//proto:jwt_rsa_ssa_pss_cc_proto", "//proto:tink_cc_proto", "//subtle:common_enums", "//util:keyset_util", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", "@com_google_protobuf//:protobuf", ], ) cc_library( name = "jwt_signature_config", srcs = ["jwt_signature_config.cc"], hdrs = ["jwt_signature_config.h"], include_prefix = "tink/jwt", visibility = ["//visibility:public"], deps = [ "//:registry", "//config:config_util", "//config:tink_fips", "//jwt/internal:jwt_ecdsa_sign_key_manager", "//jwt/internal:jwt_ecdsa_verify_key_manager", "//jwt/internal:jwt_public_key_sign_wrapper", "//jwt/internal:jwt_public_key_verify_wrapper", "//jwt/internal:jwt_rsa_ssa_pkcs1_sign_key_manager", "//jwt/internal:jwt_rsa_ssa_pkcs1_verify_key_manager", "//jwt/internal:jwt_rsa_ssa_pss_sign_key_manager", "//jwt/internal:jwt_rsa_ssa_pss_verify_key_manager", "//proto:config_cc_proto", "//util:status", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/memory", ], ) cc_library( name = "jwt_mac_parameters", hdrs = ["jwt_mac_parameters.h"], include_prefix = "tink/jwt", deps = ["//:parameters"], ) cc_library( name = "jwt_mac_key", hdrs = ["jwt_mac_key.h"], include_prefix = "tink/jwt", deps = [ ":jwt_mac_parameters", "//:key", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "jwt_hmac_parameters", srcs = ["jwt_hmac_parameters.cc"], hdrs = ["jwt_hmac_parameters.h"], include_prefix = "tink/jwt", deps = [ ":jwt_mac_parameters", "//:parameters", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "jwt_hmac_key", srcs = ["jwt_hmac_key.cc"], hdrs = ["jwt_hmac_key.h"], include_prefix = "tink/jwt", deps = [ ":jwt_hmac_parameters", ":jwt_mac_key", "//:key", "//:partial_key_access_token", "//:restricted_data", "//util:status", "//util:statusor", "@com_google_absl//absl/base:endian", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "jwt_hmac_proto_serialization", srcs = ["jwt_hmac_proto_serialization.cc"], hdrs = ["jwt_hmac_proto_serialization.h"], include_prefix = "tink/jwt", deps = [ ":jwt_hmac_key", ":jwt_hmac_parameters", "//:partial_key_access", "//:restricted_data", "//:secret_key_access_token", "//internal:key_parser", "//internal:key_serializer", "//internal:mutable_serialization_registry", "//internal:parameters_parser", "//internal:parameters_serializer", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//proto:common_cc_proto", "//proto:jwt_hmac_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "jwt_signature_parameters", hdrs = ["jwt_signature_parameters.h"], include_prefix = "tink/jwt", deps = ["//:parameters"], ) cc_library( name = "jwt_signature_public_key", hdrs = ["jwt_signature_public_key.h"], include_prefix = "tink/jwt", deps = [ ":jwt_signature_parameters", "//:key", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "jwt_signature_private_key", hdrs = ["jwt_signature_private_key.h"], include_prefix = "tink/jwt", deps = [ ":jwt_signature_parameters", ":jwt_signature_public_key", "//:key", "//:private_key", "@com_google_absl//absl/types:optional", ], ) # tests cc_test( name = "raw_jwt_test", size = "small", srcs = ["raw_jwt_test.cc"], deps = [ ":raw_jwt", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/strings", "@com_google_absl//absl/time", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "verified_jwt_test", size = "small", srcs = ["verified_jwt_test.cc"], deps = [ ":jwt_mac", ":jwt_validator", ":raw_jwt", ":verified_jwt", "//:mac", "//jwt/internal:jwt_mac_impl", "//jwt/internal:jwt_mac_internal", "//proto:common_cc_proto", "//subtle:hmac_boringssl", "//util:constants", "//util:enums", "//util:errors", "//util:protobuf_helper", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/time", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "jwt_validator_test", size = "small", srcs = ["jwt_validator_test.cc"], deps = [ ":jwt_validator", ":raw_jwt", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/strings", "@com_google_absl//absl/time", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "jwt_key_templates_test", srcs = ["jwt_key_templates_test.cc"], deps = [ ":jwt_key_templates", ":jwt_mac", ":jwt_mac_config", ":jwt_public_key_sign", ":jwt_public_key_verify", ":jwt_signature_config", ":jwt_validator", ":raw_jwt", ":verified_jwt", "//:keyset_handle", "//config:global_registry", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "jwk_set_converter_test", srcs = ["jwk_set_converter_test.cc"], deps = [ ":jwk_set_converter", ":jwt_public_key_sign", ":jwt_public_key_verify", ":jwt_signature_config", ":jwt_validator", ":raw_jwt", ":verified_jwt", "//:cleartext_keyset_handle", "//:json_keyset_reader", "//:keyset_handle", "//:keyset_reader", "//config:global_registry", "//jwt/internal:json_util", "//proto:ecdsa_cc_proto", "//proto:jwt_ecdsa_cc_proto", "//proto:jwt_rsa_ssa_pkcs1_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", "@com_google_protobuf//:protobuf", ], ) cc_test( name = "jwt_mac_config_test", srcs = ["jwt_mac_config_test.cc"], tags = ["fips"], deps = [ ":jwt_key_templates", ":jwt_mac_config", "//:keyset_handle", "//:registry", "//config:global_registry", "//internal:fips_utils", "//util:test_matchers", "@boringssl//:crypto", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "jwt_signature_config_test", srcs = ["jwt_signature_config_test.cc"], tags = ["fips"], deps = [ ":jwt_key_templates", ":jwt_signature_config", "//:keyset_handle", "//:registry", "//config:global_registry", "//internal:fips_utils", "//util:test_matchers", "@boringssl//:crypto", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "jwt_hmac_parameters_test", srcs = ["jwt_hmac_parameters_test.cc"], deps = [ ":jwt_hmac_parameters", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "jwt_hmac_key_test", srcs = ["jwt_hmac_key_test.cc"], deps = [ ":jwt_hmac_key", ":jwt_hmac_parameters", "//:partial_key_access", "//:restricted_data", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "jwt_hmac_proto_serialization_test", srcs = ["jwt_hmac_proto_serialization_test.cc"], deps = [ ":jwt_hmac_key", ":jwt_hmac_parameters", ":jwt_hmac_proto_serialization", "//:insecure_secret_key_access", "//:key", "//:parameters", "//:partial_key_access", "//:restricted_data", "//internal:mutable_serialization_registry", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//internal:serialization", "//proto:common_cc_proto", "//proto:jwt_hmac_cc_proto", "//proto:tink_cc_proto", "//subtle:random", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/jwt/CMakeLists.txt ================================================ tink_module(jwt) add_subdirectory(internal) tink_cc_library( NAME raw_jwt SRCS raw_jwt.cc raw_jwt.h DEPS protobuf::libprotobuf absl::status absl::strings absl::str_format absl::time absl::optional tink::jwt::internal::json_util tink::util::status tink::util::statusor ) tink_cc_library( NAME jwt_validator SRCS jwt_validator.cc jwt_validator.h DEPS tink::jwt::raw_jwt absl::status absl::strings absl::time absl::optional tink::util::status tink::util::statusor ) tink_cc_library( NAME verified_jwt SRCS verified_jwt.cc verified_jwt.h DEPS tink::jwt::raw_jwt protobuf::libprotobuf absl::strings absl::str_format absl::time tink::jwt::internal::json_util tink::util::status tink::util::statusor ) tink_cc_library( NAME jwt_mac SRCS jwt_mac.h DEPS tink::jwt::jwt_validator tink::jwt::raw_jwt tink::jwt::verified_jwt absl::strings tink::util::status tink::util::statusor ) tink_cc_library( NAME jwt_public_key_sign SRCS jwt_public_key_sign.h DEPS tink::jwt::raw_jwt absl::strings tink::util::status tink::util::statusor ) tink_cc_library( NAME jwt_public_key_verify SRCS jwt_public_key_verify.h DEPS tink::jwt::jwt_validator tink::jwt::verified_jwt absl::strings tink::util::status tink::util::statusor ) tink_cc_library( NAME jwk_set_converter SRCS jwk_set_converter.cc jwk_set_converter.h DEPS protobuf::libprotobuf absl::memory absl::status absl::strings absl::optional crypto tink::core::binary_keyset_writer tink::core::keyset_handle tink::internal::ec_util tink::internal::ssl_unique_ptr tink::jwt::internal::json_util tink::jwt::internal::jwt_format tink::subtle::common_enums tink::util::keyset_util tink::util::status tink::util::statusor tink::proto::jwt_ecdsa_cc_proto tink::proto::jwt_rsa_ssa_pkcs1_cc_proto tink::proto::jwt_rsa_ssa_pss_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME jwt_mac_config SRCS jwt_mac_config.cc jwt_mac_config.h DEPS absl::core_headers absl::memory tink::core::registry tink::config::config_util tink::config::tink_fips tink::jwt::internal::jwt_hmac_key_manager tink::jwt::internal::jwt_mac_wrapper tink::util::status tink::proto::config_cc_proto ) tink_cc_library( NAME jwt_signature_config SRCS jwt_signature_config.cc jwt_signature_config.h DEPS absl::core_headers absl::memory tink::core::registry tink::config::config_util tink::config::tink_fips tink::jwt::internal::jwt_ecdsa_sign_key_manager tink::jwt::internal::jwt_ecdsa_verify_key_manager tink::jwt::internal::jwt_public_key_sign_wrapper tink::jwt::internal::jwt_public_key_verify_wrapper tink::jwt::internal::jwt_rsa_ssa_pkcs1_sign_key_manager tink::jwt::internal::jwt_rsa_ssa_pkcs1_verify_key_manager tink::jwt::internal::jwt_rsa_ssa_pss_sign_key_manager tink::jwt::internal::jwt_rsa_ssa_pss_verify_key_manager tink::util::status tink::proto::config_cc_proto ) tink_cc_library( NAME jwt_key_templates SRCS jwt_key_templates.cc jwt_key_templates.h DEPS crypto tink::internal::bn_util tink::internal::ssl_unique_ptr tink::util::statusor tink::proto::common_cc_proto tink::proto::jwt_ecdsa_cc_proto tink::proto::jwt_hmac_cc_proto tink::proto::jwt_rsa_ssa_pkcs1_cc_proto tink::proto::jwt_rsa_ssa_pss_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME jwt_mac_parameters SRCS jwt_mac_parameters.h DEPS tink::core::parameters ) tink_cc_library( NAME jwt_mac_key SRCS jwt_mac_key.h DEPS tink::jwt::jwt_mac_parameters absl::optional tink::core::key ) tink_cc_library( NAME jwt_hmac_parameters SRCS jwt_hmac_parameters.cc jwt_hmac_parameters.h DEPS tink::jwt::jwt_mac_parameters absl::status absl::strings tink::core::parameters tink::util::status tink::util::statusor ) tink_cc_library( NAME jwt_hmac_key SRCS jwt_hmac_key.cc jwt_hmac_key.h DEPS tink::jwt::jwt_hmac_parameters tink::jwt::jwt_mac_key absl::endian absl::status absl::strings absl::string_view absl::optional tink::core::key tink::core::partial_key_access_token tink::core::restricted_data tink::util::status tink::util::statusor ) tink_cc_library( NAME jwt_hmac_proto_serialization SRCS jwt_hmac_proto_serialization.cc jwt_hmac_proto_serialization.h DEPS tink::jwt::jwt_hmac_key tink::jwt::jwt_hmac_parameters absl::status absl::string_view absl::optional tink::core::partial_key_access tink::core::restricted_data tink::core::secret_key_access_token tink::internal::key_parser tink::internal::key_serializer tink::internal::mutable_serialization_registry tink::internal::parameters_parser tink::internal::parameters_serializer tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::util::status tink::util::statusor tink::proto::common_cc_proto tink::proto::jwt_hmac_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME jwt_signature_parameters SRCS jwt_signature_parameters.h DEPS tink::core::parameters ) tink_cc_library( NAME jwt_signature_public_key SRCS jwt_signature_public_key.h DEPS tink::jwt::jwt_signature_parameters absl::optional tink::core::key ) tink_cc_library( NAME jwt_signature_private_key SRCS jwt_signature_private_key.h DEPS tink::jwt::jwt_signature_parameters tink::jwt::jwt_signature_public_key absl::optional tink::core::key tink::core::private_key ) # tests tink_cc_test( NAME raw_jwt_test SRCS raw_jwt_test.cc DEPS tink::jwt::raw_jwt gmock absl::strings absl::time tink::util::statusor tink::util::test_matchers tink::util::test_util ) tink_cc_test( NAME verified_jwt_test SRCS verified_jwt_test.cc DEPS tink::jwt::jwt_mac tink::jwt::jwt_validator tink::jwt::raw_jwt tink::jwt::verified_jwt gmock absl::memory absl::status absl::strings absl::time absl::optional tink::core::mac tink::jwt::internal::jwt_mac_impl tink::jwt::internal::jwt_mac_internal tink::subtle::hmac_boringssl tink::util::constants tink::util::enums tink::util::errors tink::util::protobuf_helper tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::common_cc_proto ) tink_cc_test( NAME jwt_validator_test SRCS jwt_validator_test.cc DEPS tink::jwt::jwt_validator tink::jwt::raw_jwt gmock absl::strings absl::time tink::util::statusor tink::util::test_matchers tink::util::test_util ) tink_cc_test( NAME jwt_key_templates_test SRCS jwt_key_templates_test.cc DEPS tink::jwt::jwt_key_templates tink::jwt::jwt_mac tink::jwt::jwt_mac_config tink::jwt::jwt_public_key_sign tink::jwt::jwt_public_key_verify tink::jwt::jwt_signature_config tink::jwt::jwt_validator tink::jwt::raw_jwt tink::jwt::verified_jwt gmock tink::core::keyset_handle tink::config::global_registry tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::tink_cc_proto ) tink_cc_test( NAME jwk_set_converter_test SRCS jwk_set_converter_test.cc DEPS tink::jwt::jwk_set_converter tink::jwt::jwt_public_key_sign tink::jwt::jwt_public_key_verify tink::jwt::jwt_signature_config tink::jwt::jwt_validator tink::jwt::raw_jwt tink::jwt::verified_jwt protobuf::libprotobuf gmock absl::strings crypto tink::core::cleartext_keyset_handle tink::core::json_keyset_reader tink::core::keyset_handle tink::core::keyset_reader tink::config::global_registry tink::jwt::internal::json_util tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::ecdsa_cc_proto tink::proto::jwt_ecdsa_cc_proto tink::proto::jwt_rsa_ssa_pkcs1_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME jwt_signature_config_test SRCS jwt_signature_config_test.cc DEPS tink::jwt::jwt_key_templates tink::jwt::jwt_signature_config gmock crypto tink::core::keyset_handle tink::core::registry tink::config::global_registry tink::internal::fips_utils tink::util::test_matchers ) tink_cc_test( NAME jwt_mac_config_test SRCS jwt_mac_config_test.cc DEPS tink::jwt::jwt_key_templates tink::jwt::jwt_mac_config gmock crypto tink::core::keyset_handle tink::core::registry tink::config::global_registry tink::internal::fips_utils tink::util::test_matchers ) tink_cc_test( NAME jwt_hmac_parameters_test SRCS jwt_hmac_parameters_test.cc DEPS tink::jwt::jwt_hmac_parameters gmock absl::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME jwt_hmac_key_test SRCS jwt_hmac_key_test.cc DEPS tink::jwt::jwt_hmac_key tink::jwt::jwt_hmac_parameters gmock absl::status absl::optional tink::core::partial_key_access tink::core::restricted_data tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME jwt_hmac_proto_serialization_test SRCS jwt_hmac_proto_serialization_test.cc DEPS tink::jwt::jwt_hmac_key tink::jwt::jwt_hmac_parameters tink::jwt::jwt_hmac_proto_serialization gmock absl::status absl::string_view absl::optional tink::core::insecure_secret_key_access tink::core::key tink::core::parameters tink::core::partial_key_access tink::core::restricted_data tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::internal::serialization tink::subtle::random tink::util::statusor tink::util::test_matchers tink::proto::common_cc_proto tink::proto::jwt_hmac_cc_proto tink::proto::tink_cc_proto ) ================================================ FILE: cc/jwt/internal/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "raw_jwt_hmac_key_manager", srcs = ["raw_jwt_hmac_key_manager.cc"], hdrs = ["raw_jwt_hmac_key_manager.h"], include_prefix = "tink/jwt/internal", visibility = ["//visibility:public"], deps = [ "//:core/key_type_manager", "//:core/template_util", "//:input_stream", "//:mac", "//internal:fips_utils", "//proto:common_cc_proto", "//proto:jwt_hmac_cc_proto", "//proto:tink_cc_proto", "//subtle:hmac_boringssl", "//subtle:random", "//util:constants", "//util:enums", "//util:errors", "//util:input_stream_util", "//util:protobuf_helper", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_test( name = "raw_jwt_hmac_key_manager_test", size = "small", srcs = ["raw_jwt_hmac_key_manager_test.cc"], deps = [ ":raw_jwt_hmac_key_manager", "//:core/key_manager_impl", "//:mac", "//:tink_cc", "//config:global_registry", "//mac:mac_config", "//proto:jwt_hmac_cc_proto", "//proto:tink_cc_proto", "//util:istream_input_stream", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "json_util", srcs = ["json_util.cc"], hdrs = ["json_util.h"], include_prefix = "tink/jwt/internal", deps = [ "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_protobuf//:protobuf", ], ) cc_test( name = "json_util_test", srcs = ["json_util_test.cc"], deps = [ ":json_util", "//util:statusor", "//util:test_matchers", "@com_google_googletest//:gtest_main", "@com_google_protobuf//:protobuf", ], ) cc_library( name = "jwt_format", srcs = ["jwt_format.cc"], hdrs = ["jwt_format.h"], include_prefix = "tink/jwt/internal", deps = [ ":json_util", "//:crypto_format", "//jwt:raw_jwt", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/base:endian", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", "@com_google_protobuf//:protobuf", ], ) cc_test( name = "jwt_format_test", srcs = ["jwt_format_test.cc"], deps = [ ":json_util", ":jwt_format", "//jwt:raw_jwt", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/time", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", "@com_google_protobuf//:protobuf", ], ) cc_library( name = "jwt_mac_impl", srcs = ["jwt_mac_impl.cc"], hdrs = ["jwt_mac_impl.h"], include_prefix = "tink/jwt/internal", deps = [ ":json_util", ":jwt_format", ":jwt_mac_internal", "//:mac", "//jwt:jwt_mac", "//jwt:jwt_validator", "//jwt:raw_jwt", "//jwt:verified_jwt", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", "@com_google_protobuf//:protobuf", ], ) cc_test( name = "jwt_mac_impl_test", srcs = ["jwt_mac_impl_test.cc"], deps = [ ":json_util", ":jwt_format", ":jwt_mac_impl", ":jwt_mac_internal", "//:mac", "//jwt:jwt_mac", "//jwt:jwt_validator", "//jwt:raw_jwt", "//jwt:verified_jwt", "//proto:common_cc_proto", "//subtle:hmac_boringssl", "//util:constants", "//util:enums", "//util:errors", "//util:protobuf_helper", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/time", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", "@com_google_protobuf//:protobuf", ], ) cc_library( name = "jwt_hmac_key_manager", srcs = ["jwt_hmac_key_manager.cc"], hdrs = ["jwt_hmac_key_manager.h"], include_prefix = "tink/jwt/internal", deps = [ ":jwt_mac_impl", ":jwt_mac_internal", ":raw_jwt_hmac_key_manager", "//:core/key_type_manager", "//:core/template_util", "//:input_stream", "//:mac", "//internal:fips_utils", "//jwt:jwt_mac", "//proto:common_cc_proto", "//proto:jwt_hmac_cc_proto", "//proto:tink_cc_proto", "//subtle:hmac_boringssl", "//subtle:random", "//util:constants", "//util:enums", "//util:errors", "//util:input_stream_util", "//util:protobuf_helper", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_test( name = "jwt_hmac_key_manager_test", srcs = ["jwt_hmac_key_manager_test.cc"], deps = [ ":json_util", ":jwt_format", ":jwt_hmac_key_manager", ":jwt_mac_internal", "//:core/key_manager_impl", "//:mac", "//jwt:jwt_validator", "//jwt:raw_jwt", "//jwt:verified_jwt", "//proto:jwt_hmac_cc_proto", "//proto:tink_cc_proto", "//util:istream_input_stream", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/time", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", "@com_google_protobuf//:protobuf", ], ) cc_library( name = "jwt_mac_wrapper", srcs = ["jwt_mac_wrapper.cc"], hdrs = ["jwt_mac_wrapper.h"], include_prefix = "tink/jwt/internal", deps = [ ":jwt_format", ":jwt_mac_internal", "//:primitive_set", "//:primitive_wrapper", "//jwt:jwt_mac", "//jwt:jwt_validator", "//jwt:raw_jwt", "//jwt:verified_jwt", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_test( name = "jwt_mac_wrapper_test", srcs = ["jwt_mac_wrapper_test.cc"], deps = [ ":json_util", ":jwt_format", ":jwt_hmac_key_manager", ":jwt_mac_internal", ":jwt_mac_wrapper", "//:cleartext_keyset_handle", "//:keyset_manager", "//:primitive_set", "//:registry", "//config:global_registry", "//jwt:jwt_mac", "//jwt:jwt_validator", "//jwt:raw_jwt", "//jwt:verified_jwt", "//proto:jwt_hmac_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", "@com_google_protobuf//:protobuf", ], ) cc_library( name = "raw_jwt_ecdsa_sign_key_manager", srcs = ["raw_jwt_ecdsa_sign_key_manager.cc"], hdrs = ["raw_jwt_ecdsa_sign_key_manager.h"], include_prefix = "tink/jwt/internal", visibility = ["//visibility:public"], deps = [ ":raw_jwt_ecdsa_verify_key_manager", "//:core/private_key_type_manager", "//:core/template_util", "//:public_key_sign", "//internal:ec_util", "//internal:fips_utils", "//proto:common_cc_proto", "//proto:jwt_ecdsa_cc_proto", "//proto:tink_cc_proto", "//subtle:common_enums", "//subtle:ecdsa_sign_boringssl", "//util:constants", "//util:enums", "//util:errors", "//util:protobuf_helper", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/strings", ], ) cc_test( name = "raw_jwt_ecdsa_sign_key_manager_test", srcs = ["raw_jwt_ecdsa_sign_key_manager_test.cc"], deps = [ ":raw_jwt_ecdsa_sign_key_manager", ":raw_jwt_ecdsa_verify_key_manager", "//:public_key_sign", "//:public_key_verify", "//internal:ec_util", "//proto:ecdsa_cc_proto", "//proto:jwt_ecdsa_cc_proto", "//proto:tink_cc_proto", "//subtle:common_enums", "//subtle:ecdsa_verify_boringssl", "//util:enums", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "raw_jwt_ecdsa_verify_key_manager", srcs = ["raw_jwt_ecdsa_verify_key_manager.cc"], hdrs = ["raw_jwt_ecdsa_verify_key_manager.h"], include_prefix = "tink/jwt/internal", visibility = ["//visibility:public"], deps = [ "//:core/key_type_manager", "//:core/template_util", "//:public_key_verify", "//internal:ec_util", "//internal:fips_utils", "//proto:common_cc_proto", "//proto:jwt_ecdsa_cc_proto", "//proto:tink_cc_proto", "//subtle:common_enums", "//subtle:ecdsa_verify_boringssl", "//util:constants", "//util:enums", "//util:errors", "//util:protobuf_helper", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_test( name = "raw_jwt_ecdsa_verify_key_manager_test", srcs = ["raw_jwt_ecdsa_verify_key_manager_test.cc"], deps = [ ":raw_jwt_ecdsa_sign_key_manager", ":raw_jwt_ecdsa_verify_key_manager", "//:public_key_sign", "//:public_key_verify", "//internal:ec_util", "//proto:ecdsa_cc_proto", "//proto:jwt_ecdsa_cc_proto", "//proto:tink_cc_proto", "//subtle:common_enums", "//subtle:ecdsa_sign_boringssl", "//util:enums", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "raw_jwt_rsa_ssa_pkcs1_sign_key_manager", srcs = ["raw_jwt_rsa_ssa_pkcs1_sign_key_manager.cc"], hdrs = ["raw_jwt_rsa_ssa_pkcs1_sign_key_manager.h"], include_prefix = "tink/jwt/internal", visibility = ["//visibility:public"], deps = [ ":raw_jwt_rsa_ssa_pkcs1_verify_key_manager", "//:core/private_key_type_manager", "//:core/template_util", "//:public_key_sign", "//:public_key_verify", "//internal:bn_util", "//internal:fips_utils", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//proto:common_cc_proto", "//proto:jwt_rsa_ssa_pkcs1_cc_proto", "//proto:tink_cc_proto", "//signature:sig_util", "//subtle:rsa_ssa_pkcs1_sign_boringssl", "//util:constants", "//util:enums", "//util:errors", "//util:protobuf_helper", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_test( name = "raw_jwt_rsa_ssa_pkcs1_sign_key_manager_test", srcs = ["raw_jwt_rsa_ssa_pkcs1_sign_key_manager_test.cc"], deps = [ ":raw_jwt_rsa_ssa_pkcs1_sign_key_manager", ":raw_jwt_rsa_ssa_pkcs1_verify_key_manager", "//:public_key_sign", "//internal:bn_util", "//internal:ssl_unique_ptr", "//proto:jwt_rsa_ssa_pkcs1_cc_proto", "//proto:rsa_ssa_pkcs1_cc_proto", "//proto:tink_cc_proto", "//subtle:common_enums", "//subtle:rsa_ssa_pkcs1_verify_boringssl", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@boringssl//:crypto", "@com_google_absl//absl/container:flat_hash_set", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "raw_jwt_rsa_ssa_pkcs1_verify_key_manager", srcs = ["raw_jwt_rsa_ssa_pkcs1_verify_key_manager.cc"], hdrs = ["raw_jwt_rsa_ssa_pkcs1_verify_key_manager.h"], include_prefix = "tink/jwt/internal", visibility = ["//visibility:public"], deps = [ "//:core/key_type_manager", "//:core/template_util", "//:public_key_verify", "//internal:bn_util", "//internal:fips_utils", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//proto:common_cc_proto", "//proto:jwt_rsa_ssa_pkcs1_cc_proto", "//proto:tink_cc_proto", "//subtle:rsa_ssa_pkcs1_verify_boringssl", "//util:constants", "//util:enums", "//util:errors", "//util:protobuf_helper", "//util:status", "//util:statusor", "//util:validation", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_test( name = "raw_jwt_rsa_ssa_pkcs1_verify_key_manager_test", srcs = ["raw_jwt_rsa_ssa_pkcs1_verify_key_manager_test.cc"], deps = [ ":raw_jwt_rsa_ssa_pkcs1_sign_key_manager", ":raw_jwt_rsa_ssa_pkcs1_verify_key_manager", "//:public_key_sign", "//:public_key_verify", "//internal:bn_util", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//proto:jwt_rsa_ssa_pkcs1_cc_proto", "//proto:tink_cc_proto", "//subtle:common_enums", "//subtle:rsa_ssa_pkcs1_sign_boringssl", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "raw_jwt_rsa_ssa_pss_sign_key_manager", srcs = ["raw_jwt_rsa_ssa_pss_sign_key_manager.cc"], hdrs = ["raw_jwt_rsa_ssa_pss_sign_key_manager.h"], include_prefix = "tink/jwt/internal", visibility = ["//visibility:public"], deps = [ ":raw_jwt_rsa_ssa_pss_verify_key_manager", "//:core/private_key_type_manager", "//:core/template_util", "//:public_key_sign", "//:public_key_verify", "//internal:bn_util", "//internal:fips_utils", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//proto:common_cc_proto", "//proto:jwt_rsa_ssa_pss_cc_proto", "//proto:tink_cc_proto", "//signature:sig_util", "//subtle:rsa_ssa_pss_sign_boringssl", "//util:constants", "//util:enums", "//util:errors", "//util:protobuf_helper", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_test( name = "raw_jwt_rsa_ssa_pss_sign_key_manager_test", srcs = ["raw_jwt_rsa_ssa_pss_sign_key_manager_test.cc"], deps = [ ":raw_jwt_rsa_ssa_pss_sign_key_manager", "//:public_key_sign", "//internal:bn_util", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//proto:jwt_rsa_ssa_pss_cc_proto", "//proto:tink_cc_proto", "//subtle:common_enums", "//subtle:rsa_ssa_pss_verify_boringssl", "//util:status", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/container:flat_hash_set", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "raw_jwt_rsa_ssa_pss_verify_key_manager", srcs = ["raw_jwt_rsa_ssa_pss_verify_key_manager.cc"], hdrs = ["raw_jwt_rsa_ssa_pss_verify_key_manager.h"], include_prefix = "tink/jwt/internal", visibility = ["//visibility:public"], deps = [ "//:core/key_type_manager", "//:core/template_util", "//:public_key_verify", "//internal:bn_util", "//internal:fips_utils", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//proto:common_cc_proto", "//proto:jwt_rsa_ssa_pss_cc_proto", "//proto:tink_cc_proto", "//subtle:rsa_ssa_pss_verify_boringssl", "//util:constants", "//util:enums", "//util:errors", "//util:protobuf_helper", "//util:status", "//util:statusor", "//util:validation", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_test( name = "raw_jwt_rsa_ssa_pss_verify_key_manager_test", srcs = ["raw_jwt_rsa_ssa_pss_verify_key_manager_test.cc"], deps = [ ":raw_jwt_rsa_ssa_pss_sign_key_manager", ":raw_jwt_rsa_ssa_pss_verify_key_manager", "//:public_key_sign", "//:public_key_verify", "//internal:bn_util", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//proto:jwt_rsa_ssa_pss_cc_proto", "//proto:tink_cc_proto", "//subtle:common_enums", "//subtle:rsa_ssa_pss_sign_boringssl", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "jwt_public_key_sign_impl", srcs = ["jwt_public_key_sign_impl.cc"], hdrs = ["jwt_public_key_sign_impl.h"], include_prefix = "tink/jwt/internal", deps = [ ":jwt_format", ":jwt_public_key_sign_internal", "//:public_key_sign", "//jwt:raw_jwt", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "jwt_public_key_verify_impl", srcs = ["jwt_public_key_verify_impl.cc"], hdrs = ["jwt_public_key_verify_impl.h"], include_prefix = "tink/jwt/internal", deps = [ ":json_util", ":jwt_format", ":jwt_public_key_verify_internal", "//:public_key_verify", "//jwt:jwt_validator", "//jwt:raw_jwt", "//jwt:verified_jwt", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", "@com_google_protobuf//:protobuf", ], ) cc_test( name = "jwt_public_key_sign_verify_impl_test", srcs = ["jwt_public_key_sign_verify_impl_test.cc"], deps = [ ":json_util", ":jwt_format", ":jwt_public_key_sign_impl", ":jwt_public_key_verify_impl", "//internal:ec_util", "//jwt:jwt_public_key_sign", "//jwt:jwt_public_key_verify", "//jwt:jwt_validator", "//jwt:raw_jwt", "//jwt:verified_jwt", "//subtle:common_enums", "//subtle:ecdsa_sign_boringssl", "//subtle:ecdsa_verify_boringssl", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/strings", "@com_google_absl//absl/time", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", "@com_google_protobuf//:protobuf", ], ) cc_library( name = "jwt_ecdsa_sign_key_manager", srcs = ["jwt_ecdsa_sign_key_manager.cc"], hdrs = ["jwt_ecdsa_sign_key_manager.h"], include_prefix = "tink/jwt/internal", deps = [ ":jwt_ecdsa_verify_key_manager", ":jwt_public_key_sign_impl", ":jwt_public_key_sign_internal", ":raw_jwt_ecdsa_sign_key_manager", "//:core/private_key_type_manager", "//:core/template_util", "//:public_key_sign", "//internal:fips_utils", "//jwt:jwt_public_key_sign", "//proto:jwt_ecdsa_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "jwt_ecdsa_verify_key_manager", srcs = ["jwt_ecdsa_verify_key_manager.cc"], hdrs = ["jwt_ecdsa_verify_key_manager.h"], include_prefix = "tink/jwt/internal", deps = [ ":jwt_public_key_verify_impl", ":jwt_public_key_verify_internal", ":raw_jwt_ecdsa_verify_key_manager", "//:core/key_type_manager", "//:core/template_util", "//:public_key_verify", "//internal:fips_utils", "//proto:jwt_ecdsa_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_test( name = "jwt_ecdsa_sign_verify_key_manager_test", srcs = ["jwt_ecdsa_sign_verify_key_manager_test.cc"], deps = [ ":json_util", ":jwt_ecdsa_sign_key_manager", ":jwt_ecdsa_verify_key_manager", ":jwt_format", ":jwt_public_key_sign_internal", ":jwt_public_key_verify_internal", "//jwt:jwt_validator", "//jwt:raw_jwt", "//jwt:verified_jwt", "//proto:jwt_ecdsa_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", "@com_google_protobuf//:protobuf", ], ) cc_library( name = "jwt_public_key_sign_wrapper", srcs = ["jwt_public_key_sign_wrapper.cc"], hdrs = ["jwt_public_key_sign_wrapper.h"], include_prefix = "tink/jwt/internal", deps = [ ":jwt_format", ":jwt_public_key_sign_internal", "//:primitive_set", "//:primitive_wrapper", "//jwt:jwt_public_key_sign", "//jwt:raw_jwt", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", ], ) cc_library( name = "jwt_public_key_verify_wrapper", srcs = ["jwt_public_key_verify_wrapper.cc"], hdrs = ["jwt_public_key_verify_wrapper.h"], include_prefix = "tink/jwt/internal", deps = [ ":jwt_format", ":jwt_public_key_verify_internal", "//:primitive_set", "//:primitive_wrapper", "//jwt:jwt_public_key_verify", "//jwt:jwt_validator", "//jwt:verified_jwt", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_test( name = "jwt_public_key_wrappers_test", srcs = ["jwt_public_key_wrappers_test.cc"], deps = [ ":json_util", ":jwt_ecdsa_sign_key_manager", ":jwt_ecdsa_verify_key_manager", ":jwt_format", ":jwt_public_key_sign_internal", ":jwt_public_key_sign_wrapper", ":jwt_public_key_verify_wrapper", "//:cleartext_keyset_handle", "//:keyset_manager", "//:primitive_set", "//:registry", "//config:global_registry", "//jwt:jwt_public_key_sign", "//jwt:jwt_public_key_verify", "//jwt:jwt_validator", "//jwt:raw_jwt", "//jwt:verified_jwt", "//proto:jwt_ecdsa_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", "@com_google_protobuf//:protobuf", ], ) cc_library( name = "jwt_rsa_ssa_pkcs1_sign_key_manager", srcs = ["jwt_rsa_ssa_pkcs1_sign_key_manager.cc"], hdrs = ["jwt_rsa_ssa_pkcs1_sign_key_manager.h"], include_prefix = "tink/jwt/internal", deps = [ ":jwt_public_key_sign_impl", ":jwt_public_key_sign_internal", ":jwt_rsa_ssa_pkcs1_verify_key_manager", ":raw_jwt_rsa_ssa_pkcs1_sign_key_manager", "//:core/private_key_type_manager", "//:core/template_util", "//:public_key_sign", "//internal:fips_utils", "//jwt:jwt_public_key_sign", "//proto:jwt_rsa_ssa_pkcs1_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "jwt_rsa_ssa_pkcs1_verify_key_manager", srcs = ["jwt_rsa_ssa_pkcs1_verify_key_manager.cc"], hdrs = ["jwt_rsa_ssa_pkcs1_verify_key_manager.h"], include_prefix = "tink/jwt/internal", deps = [ ":jwt_public_key_verify_impl", ":jwt_public_key_verify_internal", ":raw_jwt_rsa_ssa_pkcs1_verify_key_manager", "//:core/key_type_manager", "//:core/template_util", "//:public_key_verify", "//internal:fips_utils", "//proto:jwt_rsa_ssa_pkcs1_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_test( name = "jwt_rsa_ssa_pkcs1_sign_verify_key_manager_test", srcs = ["jwt_rsa_ssa_pkcs1_sign_verify_key_manager_test.cc"], deps = [ ":json_util", ":jwt_format", ":jwt_public_key_sign_internal", ":jwt_public_key_verify_internal", ":jwt_rsa_ssa_pkcs1_sign_key_manager", ":jwt_rsa_ssa_pkcs1_verify_key_manager", "//internal:bn_util", "//internal:ssl_unique_ptr", "//jwt:jwt_validator", "//jwt:raw_jwt", "//jwt:verified_jwt", "//proto:jwt_rsa_ssa_pkcs1_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", "@com_google_protobuf//:protobuf", ], ) cc_library( name = "jwt_rsa_ssa_pss_sign_key_manager", srcs = ["jwt_rsa_ssa_pss_sign_key_manager.cc"], hdrs = ["jwt_rsa_ssa_pss_sign_key_manager.h"], include_prefix = "tink/jwt/internal", deps = [ ":jwt_public_key_sign_impl", ":jwt_public_key_sign_internal", ":jwt_rsa_ssa_pss_verify_key_manager", ":raw_jwt_rsa_ssa_pss_sign_key_manager", "//:core/private_key_type_manager", "//:core/template_util", "//:public_key_sign", "//internal:fips_utils", "//jwt:jwt_public_key_sign", "//proto:jwt_rsa_ssa_pss_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "jwt_rsa_ssa_pss_verify_key_manager", srcs = ["jwt_rsa_ssa_pss_verify_key_manager.cc"], hdrs = ["jwt_rsa_ssa_pss_verify_key_manager.h"], include_prefix = "tink/jwt/internal", deps = [ ":jwt_public_key_verify_impl", ":jwt_public_key_verify_internal", ":raw_jwt_rsa_ssa_pss_verify_key_manager", "//:core/key_type_manager", "//:core/template_util", "//:public_key_verify", "//internal:fips_utils", "//proto:jwt_rsa_ssa_pss_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_test( name = "jwt_rsa_ssa_pss_sign_verify_key_manager_test", srcs = ["jwt_rsa_ssa_pss_sign_verify_key_manager_test.cc"], deps = [ ":json_util", ":jwt_format", ":jwt_public_key_sign_internal", ":jwt_public_key_verify_internal", ":jwt_rsa_ssa_pss_sign_key_manager", ":jwt_rsa_ssa_pss_verify_key_manager", "//internal:bn_util", "//internal:ssl_unique_ptr", "//jwt:jwt_validator", "//jwt:raw_jwt", "//jwt:verified_jwt", "//proto:jwt_rsa_ssa_pss_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", "@com_google_protobuf//:protobuf", ], ) cc_library( name = "jwt_public_key_sign_internal", hdrs = ["jwt_public_key_sign_internal.h"], include_prefix = "tink/jwt/internal", deps = [ "//jwt:raw_jwt", "//util:status", "//util:statusor", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "jwt_mac_internal", hdrs = ["jwt_mac_internal.h"], include_prefix = "tink/jwt/internal", deps = [ "//jwt:jwt_validator", "//jwt:raw_jwt", "//jwt:verified_jwt", "//util:status", "//util:statusor", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "jwt_public_key_verify_internal", hdrs = ["jwt_public_key_verify_internal.h"], include_prefix = "tink/jwt/internal", deps = [ "//jwt:jwt_validator", "//jwt:verified_jwt", "//util:status", "//util:statusor", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) ================================================ FILE: cc/jwt/internal/CMakeLists.txt ================================================ tink_module(jwt::internal) tink_cc_library( NAME raw_jwt_hmac_key_manager SRCS raw_jwt_hmac_key_manager.cc raw_jwt_hmac_key_manager.h DEPS absl::memory absl::status absl::strings tink::core::key_type_manager tink::core::template_util tink::core::input_stream tink::core::mac tink::internal::fips_utils tink::subtle::hmac_boringssl tink::subtle::random tink::util::constants tink::util::enums tink::util::errors tink::util::input_stream_util tink::util::protobuf_helper tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::common_cc_proto tink::proto::jwt_hmac_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME json_util SRCS json_util.cc json_util.h DEPS protobuf::libprotobuf absl::status absl::strings tink::util::status tink::util::statusor ) tink_cc_test( NAME json_util_test SRCS json_util_test.cc DEPS tink::jwt::internal::json_util protobuf::libprotobuf gmock tink::util::statusor tink::util::test_matchers ) tink_cc_library( NAME jwt_format SRCS jwt_format.cc jwt_format.h DEPS tink::jwt::internal::json_util protobuf::libprotobuf absl::endian absl::status absl::strings absl::optional tink::core::crypto_format tink::jwt::raw_jwt tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_test( NAME jwt_format_test SRCS jwt_format_test.cc DEPS tink::jwt::internal::json_util tink::jwt::internal::jwt_format protobuf::libprotobuf gmock absl::time absl::optional tink::jwt::raw_jwt tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::tink_cc_proto ) tink_cc_test( NAME raw_jwt_hmac_key_manager_test SRCS raw_jwt_hmac_key_manager_test.cc DEPS tink::jwt::internal::raw_jwt_hmac_key_manager gmock absl::memory absl::status tink::core::cc tink::core::key_manager_impl tink::core::mac tink::config::global_registry tink::mac::mac_config tink::util::istream_input_stream tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::jwt_hmac_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME jwt_mac_impl SRCS jwt_mac_impl.cc jwt_mac_impl.h DEPS tink::jwt::internal::json_util tink::jwt::internal::jwt_format tink::jwt::internal::jwt_mac_internal protobuf::libprotobuf absl::status absl::strings absl::optional tink::core::mac tink::jwt::jwt_mac tink::jwt::jwt_validator tink::jwt::raw_jwt tink::jwt::verified_jwt tink::util::status tink::util::statusor ) tink_cc_test( NAME jwt_mac_impl_test SRCS jwt_mac_impl_test.cc DEPS tink::jwt::internal::json_util tink::jwt::internal::jwt_format tink::jwt::internal::jwt_mac_impl tink::jwt::internal::jwt_mac_internal protobuf::libprotobuf gmock absl::memory absl::status absl::strings absl::time absl::optional tink::core::mac tink::jwt::jwt_mac tink::jwt::jwt_validator tink::jwt::raw_jwt tink::jwt::verified_jwt tink::subtle::hmac_boringssl tink::util::constants tink::util::enums tink::util::errors tink::util::protobuf_helper tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::common_cc_proto ) tink_cc_library( NAME jwt_hmac_key_manager SRCS jwt_hmac_key_manager.cc jwt_hmac_key_manager.h DEPS tink::jwt::internal::jwt_mac_impl tink::jwt::internal::jwt_mac_internal tink::jwt::internal::raw_jwt_hmac_key_manager absl::memory absl::status absl::strings absl::optional tink::core::key_type_manager tink::core::template_util tink::core::input_stream tink::core::mac tink::internal::fips_utils tink::jwt::jwt_mac tink::subtle::hmac_boringssl tink::subtle::random tink::util::constants tink::util::enums tink::util::errors tink::util::input_stream_util tink::util::protobuf_helper tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::common_cc_proto tink::proto::jwt_hmac_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME jwt_hmac_key_manager_test SRCS jwt_hmac_key_manager_test.cc DEPS tink::jwt::internal::json_util tink::jwt::internal::jwt_format tink::jwt::internal::jwt_hmac_key_manager tink::jwt::internal::jwt_mac_internal protobuf::libprotobuf gmock absl::memory absl::status absl::strings absl::time absl::optional tink::core::key_manager_impl tink::core::mac tink::jwt::jwt_validator tink::jwt::raw_jwt tink::jwt::verified_jwt tink::util::istream_input_stream tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::jwt_hmac_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME jwt_mac_wrapper SRCS jwt_mac_wrapper.cc jwt_mac_wrapper.h DEPS tink::jwt::internal::jwt_format tink::jwt::internal::jwt_mac_internal absl::memory absl::status absl::string_view absl::optional tink::core::primitive_set tink::core::primitive_wrapper tink::jwt::jwt_mac tink::jwt::jwt_validator tink::jwt::raw_jwt tink::jwt::verified_jwt tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_test( NAME jwt_mac_wrapper_test SRCS jwt_mac_wrapper_test.cc DEPS tink::jwt::internal::json_util tink::jwt::internal::jwt_format tink::jwt::internal::jwt_hmac_key_manager tink::jwt::internal::jwt_mac_internal tink::jwt::internal::jwt_mac_wrapper protobuf::libprotobuf gmock absl::memory absl::strings tink::core::cleartext_keyset_handle tink::core::keyset_manager tink::core::primitive_set tink::core::registry tink::config::global_registry tink::jwt::jwt_mac tink::jwt::jwt_validator tink::jwt::raw_jwt tink::jwt::verified_jwt tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::jwt_hmac_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME raw_jwt_ecdsa_sign_key_manager SRCS raw_jwt_ecdsa_sign_key_manager.cc raw_jwt_ecdsa_sign_key_manager.h DEPS tink::jwt::internal::raw_jwt_ecdsa_verify_key_manager absl::memory absl::strings tink::core::private_key_type_manager tink::core::template_util tink::core::public_key_sign tink::internal::ec_util tink::internal::fips_utils tink::subtle::common_enums tink::subtle::ecdsa_sign_boringssl tink::util::constants tink::util::enums tink::util::errors tink::util::protobuf_helper tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::common_cc_proto tink::proto::jwt_ecdsa_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME raw_jwt_ecdsa_sign_key_manager_test SRCS raw_jwt_ecdsa_sign_key_manager_test.cc DEPS tink::jwt::internal::raw_jwt_ecdsa_sign_key_manager tink::jwt::internal::raw_jwt_ecdsa_verify_key_manager gmock absl::status tink::core::public_key_sign tink::core::public_key_verify tink::internal::ec_util tink::subtle::common_enums tink::subtle::ecdsa_verify_boringssl tink::util::enums tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::ecdsa_cc_proto tink::proto::jwt_ecdsa_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME raw_jwt_ecdsa_verify_key_manager SRCS raw_jwt_ecdsa_verify_key_manager.cc raw_jwt_ecdsa_verify_key_manager.h DEPS absl::memory absl::status absl::strings tink::core::key_type_manager tink::core::template_util tink::core::public_key_verify tink::internal::ec_util tink::internal::fips_utils tink::subtle::common_enums tink::subtle::ecdsa_verify_boringssl tink::util::constants tink::util::enums tink::util::errors tink::util::protobuf_helper tink::util::status tink::util::statusor tink::util::validation tink::proto::common_cc_proto tink::proto::jwt_ecdsa_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME raw_jwt_ecdsa_verify_key_manager_test SRCS raw_jwt_ecdsa_verify_key_manager_test.cc DEPS tink::jwt::internal::raw_jwt_ecdsa_sign_key_manager tink::jwt::internal::raw_jwt_ecdsa_verify_key_manager gmock absl::status tink::core::public_key_sign tink::core::public_key_verify tink::internal::ec_util tink::subtle::common_enums tink::subtle::ecdsa_sign_boringssl tink::util::enums tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::ecdsa_cc_proto tink::proto::jwt_ecdsa_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME raw_jwt_rsa_ssa_pkcs1_sign_key_manager SRCS raw_jwt_rsa_ssa_pkcs1_sign_key_manager.cc raw_jwt_rsa_ssa_pkcs1_sign_key_manager.h DEPS tink::jwt::internal::raw_jwt_rsa_ssa_pkcs1_verify_key_manager absl::memory absl::status absl::strings tink::core::private_key_type_manager tink::core::template_util tink::core::public_key_sign tink::core::public_key_verify tink::internal::bn_util tink::internal::fips_utils tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::signature::sig_util tink::subtle::rsa_ssa_pkcs1_sign_boringssl tink::util::constants tink::util::enums tink::util::errors tink::util::protobuf_helper tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::common_cc_proto tink::proto::jwt_rsa_ssa_pkcs1_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME raw_jwt_rsa_ssa_pkcs1_sign_key_manager_test SRCS raw_jwt_rsa_ssa_pkcs1_sign_key_manager_test.cc DEPS tink::jwt::internal::raw_jwt_rsa_ssa_pkcs1_sign_key_manager tink::jwt::internal::raw_jwt_rsa_ssa_pkcs1_verify_key_manager gmock absl::flat_hash_set crypto tink::core::public_key_sign tink::internal::bn_util tink::internal::ssl_unique_ptr tink::subtle::common_enums tink::subtle::rsa_ssa_pkcs1_verify_boringssl tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::jwt_rsa_ssa_pkcs1_cc_proto tink::proto::rsa_ssa_pkcs1_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME raw_jwt_rsa_ssa_pkcs1_verify_key_manager SRCS raw_jwt_rsa_ssa_pkcs1_verify_key_manager.cc raw_jwt_rsa_ssa_pkcs1_verify_key_manager.h DEPS absl::memory absl::status absl::strings crypto tink::core::key_type_manager tink::core::template_util tink::core::public_key_verify tink::internal::bn_util tink::internal::fips_utils tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::subtle::rsa_ssa_pkcs1_verify_boringssl tink::util::constants tink::util::enums tink::util::errors tink::util::protobuf_helper tink::util::status tink::util::statusor tink::util::validation tink::proto::common_cc_proto tink::proto::jwt_rsa_ssa_pkcs1_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME raw_jwt_rsa_ssa_pkcs1_verify_key_manager_test SRCS raw_jwt_rsa_ssa_pkcs1_verify_key_manager_test.cc DEPS tink::jwt::internal::raw_jwt_rsa_ssa_pkcs1_sign_key_manager tink::jwt::internal::raw_jwt_rsa_ssa_pkcs1_verify_key_manager gmock absl::status absl::strings crypto tink::core::public_key_sign tink::core::public_key_verify tink::internal::bn_util tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::subtle::common_enums tink::subtle::rsa_ssa_pkcs1_sign_boringssl tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::jwt_rsa_ssa_pkcs1_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME raw_jwt_rsa_ssa_pss_sign_key_manager SRCS raw_jwt_rsa_ssa_pss_sign_key_manager.cc raw_jwt_rsa_ssa_pss_sign_key_manager.h DEPS tink::jwt::internal::raw_jwt_rsa_ssa_pss_verify_key_manager absl::memory absl::status absl::strings tink::core::private_key_type_manager tink::core::template_util tink::core::public_key_sign tink::core::public_key_verify tink::internal::bn_util tink::internal::fips_utils tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::signature::sig_util tink::subtle::rsa_ssa_pss_sign_boringssl tink::util::constants tink::util::enums tink::util::errors tink::util::protobuf_helper tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::common_cc_proto tink::proto::jwt_rsa_ssa_pss_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME raw_jwt_rsa_ssa_pss_sign_key_manager_test SRCS raw_jwt_rsa_ssa_pss_sign_key_manager_test.cc DEPS tink::jwt::internal::raw_jwt_rsa_ssa_pss_sign_key_manager gmock absl::flat_hash_set crypto tink::core::public_key_sign tink::internal::bn_util tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::subtle::common_enums tink::subtle::rsa_ssa_pss_verify_boringssl tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::jwt_rsa_ssa_pss_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME raw_jwt_rsa_ssa_pss_verify_key_manager SRCS raw_jwt_rsa_ssa_pss_verify_key_manager.cc raw_jwt_rsa_ssa_pss_verify_key_manager.h DEPS absl::memory absl::status absl::strings crypto tink::core::key_type_manager tink::core::template_util tink::core::public_key_verify tink::internal::bn_util tink::internal::fips_utils tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::subtle::rsa_ssa_pss_verify_boringssl tink::util::constants tink::util::enums tink::util::errors tink::util::protobuf_helper tink::util::status tink::util::statusor tink::util::validation tink::proto::common_cc_proto tink::proto::jwt_rsa_ssa_pss_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME raw_jwt_rsa_ssa_pss_verify_key_manager_test SRCS raw_jwt_rsa_ssa_pss_verify_key_manager_test.cc DEPS tink::jwt::internal::raw_jwt_rsa_ssa_pss_sign_key_manager tink::jwt::internal::raw_jwt_rsa_ssa_pss_verify_key_manager gmock absl::status absl::strings crypto tink::core::public_key_sign tink::core::public_key_verify tink::internal::bn_util tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::subtle::common_enums tink::subtle::rsa_ssa_pss_sign_boringssl tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::jwt_rsa_ssa_pss_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME jwt_public_key_sign_impl SRCS jwt_public_key_sign_impl.cc jwt_public_key_sign_impl.h DEPS tink::jwt::internal::jwt_format tink::jwt::internal::jwt_public_key_sign_internal absl::status absl::strings absl::optional tink::core::public_key_sign tink::jwt::raw_jwt tink::util::status tink::util::statusor ) tink_cc_library( NAME jwt_public_key_verify_impl SRCS jwt_public_key_verify_impl.cc jwt_public_key_verify_impl.h DEPS tink::jwt::internal::json_util tink::jwt::internal::jwt_format tink::jwt::internal::jwt_public_key_verify_internal protobuf::libprotobuf absl::status absl::strings absl::optional tink::core::public_key_verify tink::jwt::jwt_validator tink::jwt::raw_jwt tink::jwt::verified_jwt tink::util::status tink::util::statusor ) tink_cc_test( NAME jwt_public_key_sign_verify_impl_test SRCS jwt_public_key_sign_verify_impl_test.cc DEPS tink::jwt::internal::json_util tink::jwt::internal::jwt_format tink::jwt::internal::jwt_public_key_sign_impl tink::jwt::internal::jwt_public_key_verify_impl protobuf::libprotobuf gmock absl::memory absl::strings absl::time absl::optional tink::internal::ec_util tink::jwt::jwt_public_key_sign tink::jwt::jwt_public_key_verify tink::jwt::jwt_validator tink::jwt::raw_jwt tink::jwt::verified_jwt tink::subtle::common_enums tink::subtle::ecdsa_sign_boringssl tink::subtle::ecdsa_verify_boringssl tink::util::statusor tink::util::test_matchers ) tink_cc_library( NAME jwt_ecdsa_sign_key_manager SRCS jwt_ecdsa_sign_key_manager.cc jwt_ecdsa_sign_key_manager.h DEPS tink::jwt::internal::jwt_ecdsa_verify_key_manager tink::jwt::internal::jwt_public_key_sign_impl tink::jwt::internal::jwt_public_key_sign_internal tink::jwt::internal::raw_jwt_ecdsa_sign_key_manager absl::memory absl::string_view absl::optional tink::core::private_key_type_manager tink::core::template_util tink::core::public_key_sign tink::internal::fips_utils tink::jwt::jwt_public_key_sign tink::util::status tink::util::statusor tink::proto::jwt_ecdsa_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME jwt_ecdsa_verify_key_manager SRCS jwt_ecdsa_verify_key_manager.cc jwt_ecdsa_verify_key_manager.h DEPS tink::jwt::internal::jwt_public_key_verify_impl tink::jwt::internal::jwt_public_key_verify_internal tink::jwt::internal::raw_jwt_ecdsa_verify_key_manager absl::memory absl::status absl::string_view absl::optional tink::core::key_type_manager tink::core::template_util tink::core::public_key_verify tink::internal::fips_utils tink::util::status tink::util::statusor tink::proto::jwt_ecdsa_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME jwt_ecdsa_sign_verify_key_manager_test SRCS jwt_ecdsa_sign_verify_key_manager_test.cc DEPS tink::jwt::internal::json_util tink::jwt::internal::jwt_ecdsa_sign_key_manager tink::jwt::internal::jwt_ecdsa_verify_key_manager tink::jwt::internal::jwt_format tink::jwt::internal::jwt_public_key_sign_internal tink::jwt::internal::jwt_public_key_verify_internal protobuf::libprotobuf gmock absl::strings absl::optional tink::jwt::jwt_validator tink::jwt::raw_jwt tink::jwt::verified_jwt tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::jwt_ecdsa_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME jwt_public_key_sign_wrapper SRCS jwt_public_key_sign_wrapper.cc jwt_public_key_sign_wrapper.h DEPS tink::jwt::internal::jwt_format tink::jwt::internal::jwt_public_key_sign_internal absl::memory absl::status tink::core::primitive_set tink::core::primitive_wrapper tink::jwt::jwt_public_key_sign tink::jwt::raw_jwt tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME jwt_public_key_verify_wrapper SRCS jwt_public_key_verify_wrapper.cc jwt_public_key_verify_wrapper.h DEPS tink::jwt::internal::jwt_format tink::jwt::internal::jwt_public_key_verify_internal absl::memory absl::status absl::string_view absl::optional tink::core::primitive_set tink::core::primitive_wrapper tink::jwt::jwt_public_key_verify tink::jwt::jwt_validator tink::jwt::verified_jwt tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_test( NAME jwt_public_key_wrappers_test SRCS jwt_public_key_wrappers_test.cc DEPS tink::jwt::internal::json_util tink::jwt::internal::jwt_ecdsa_sign_key_manager tink::jwt::internal::jwt_ecdsa_verify_key_manager tink::jwt::internal::jwt_format tink::jwt::internal::jwt_public_key_sign_internal tink::jwt::internal::jwt_public_key_sign_wrapper tink::jwt::internal::jwt_public_key_verify_wrapper protobuf::libprotobuf gmock absl::memory absl::strings tink::core::cleartext_keyset_handle tink::core::keyset_manager tink::core::primitive_set tink::core::registry tink::config::global_registry tink::jwt::jwt_public_key_sign tink::jwt::jwt_public_key_verify tink::jwt::jwt_validator tink::jwt::raw_jwt tink::jwt::verified_jwt tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::jwt_ecdsa_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME jwt_rsa_ssa_pkcs1_sign_key_manager SRCS jwt_rsa_ssa_pkcs1_sign_key_manager.cc jwt_rsa_ssa_pkcs1_sign_key_manager.h DEPS tink::jwt::internal::jwt_public_key_sign_impl tink::jwt::internal::jwt_public_key_sign_internal tink::jwt::internal::jwt_rsa_ssa_pkcs1_verify_key_manager tink::jwt::internal::raw_jwt_rsa_ssa_pkcs1_sign_key_manager absl::memory absl::string_view absl::optional tink::core::private_key_type_manager tink::core::template_util tink::core::public_key_sign tink::internal::fips_utils tink::jwt::jwt_public_key_sign tink::util::status tink::util::statusor tink::proto::jwt_rsa_ssa_pkcs1_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME jwt_rsa_ssa_pkcs1_verify_key_manager SRCS jwt_rsa_ssa_pkcs1_verify_key_manager.cc jwt_rsa_ssa_pkcs1_verify_key_manager.h DEPS tink::jwt::internal::jwt_public_key_verify_impl tink::jwt::internal::jwt_public_key_verify_internal tink::jwt::internal::raw_jwt_rsa_ssa_pkcs1_verify_key_manager absl::memory absl::status absl::string_view absl::optional tink::core::key_type_manager tink::core::template_util tink::core::public_key_verify tink::internal::fips_utils tink::util::status tink::util::statusor tink::proto::jwt_rsa_ssa_pkcs1_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME jwt_rsa_ssa_pkcs1_sign_verify_key_manager_test SRCS jwt_rsa_ssa_pkcs1_sign_verify_key_manager_test.cc DEPS tink::jwt::internal::json_util tink::jwt::internal::jwt_format tink::jwt::internal::jwt_public_key_sign_internal tink::jwt::internal::jwt_public_key_verify_internal tink::jwt::internal::jwt_rsa_ssa_pkcs1_sign_key_manager tink::jwt::internal::jwt_rsa_ssa_pkcs1_verify_key_manager protobuf::libprotobuf gmock absl::strings absl::optional crypto tink::internal::bn_util tink::internal::ssl_unique_ptr tink::jwt::jwt_validator tink::jwt::raw_jwt tink::jwt::verified_jwt tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::jwt_rsa_ssa_pkcs1_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME jwt_rsa_ssa_pss_sign_key_manager SRCS jwt_rsa_ssa_pss_sign_key_manager.cc jwt_rsa_ssa_pss_sign_key_manager.h DEPS tink::jwt::internal::jwt_public_key_sign_impl tink::jwt::internal::jwt_public_key_sign_internal tink::jwt::internal::jwt_rsa_ssa_pss_verify_key_manager tink::jwt::internal::raw_jwt_rsa_ssa_pss_sign_key_manager absl::memory absl::string_view absl::optional tink::core::private_key_type_manager tink::core::template_util tink::core::public_key_sign tink::internal::fips_utils tink::jwt::jwt_public_key_sign tink::util::status tink::util::statusor tink::proto::jwt_rsa_ssa_pss_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME jwt_rsa_ssa_pss_verify_key_manager SRCS jwt_rsa_ssa_pss_verify_key_manager.cc jwt_rsa_ssa_pss_verify_key_manager.h DEPS tink::jwt::internal::jwt_public_key_verify_impl tink::jwt::internal::jwt_public_key_verify_internal tink::jwt::internal::raw_jwt_rsa_ssa_pss_verify_key_manager absl::memory absl::status absl::string_view absl::optional tink::core::key_type_manager tink::core::template_util tink::core::public_key_verify tink::internal::fips_utils tink::util::status tink::util::statusor tink::proto::jwt_rsa_ssa_pss_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME jwt_rsa_ssa_pss_sign_verify_key_manager_test SRCS jwt_rsa_ssa_pss_sign_verify_key_manager_test.cc DEPS tink::jwt::internal::json_util tink::jwt::internal::jwt_format tink::jwt::internal::jwt_public_key_sign_internal tink::jwt::internal::jwt_public_key_verify_internal tink::jwt::internal::jwt_rsa_ssa_pss_sign_key_manager tink::jwt::internal::jwt_rsa_ssa_pss_verify_key_manager protobuf::libprotobuf gmock absl::strings absl::optional crypto tink::internal::bn_util tink::internal::ssl_unique_ptr tink::jwt::jwt_validator tink::jwt::raw_jwt tink::jwt::verified_jwt tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::jwt_rsa_ssa_pss_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME jwt_public_key_sign_internal SRCS jwt_public_key_sign_internal.h DEPS absl::strings absl::optional tink::jwt::raw_jwt tink::util::status tink::util::statusor ) tink_cc_library( NAME jwt_mac_internal SRCS jwt_mac_internal.h DEPS absl::strings absl::optional tink::jwt::jwt_validator tink::jwt::raw_jwt tink::jwt::verified_jwt tink::util::status tink::util::statusor ) tink_cc_library( NAME jwt_public_key_verify_internal SRCS jwt_public_key_verify_internal.h DEPS absl::strings absl::optional tink::jwt::jwt_validator tink::jwt::verified_jwt tink::util::status tink::util::statusor ) ================================================ FILE: cc/jwt/internal/json_util.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/json_util.h" #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "google/protobuf/json/json.h" #include "google/protobuf/util/json_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace jwt_internal { using ::google::protobuf::ListValue; using ::google::protobuf::Struct; using ::google::protobuf::util::JsonParseOptions; using ::google::protobuf::util::JsonStringToMessage; using ::google::protobuf::util::MessageToJsonString; util::StatusOr JsonStringToProtoStruct(absl::string_view json_string) { Struct proto; JsonParseOptions json_parse_options; absl::Status status = JsonStringToMessage(json_string, &proto, json_parse_options); if (!status.ok()) { return util::Status(absl::StatusCode::kInvalidArgument, "invalid JSON"); } return proto; } util::StatusOr JsonStringToProtoList(absl::string_view json_string) { ListValue proto; JsonParseOptions json_parse_options; absl::Status status = JsonStringToMessage(json_string, &proto, json_parse_options); if (!status.ok()) { return util::Status(absl::StatusCode::kInvalidArgument, "invalid JSON"); } return proto; } util::StatusOr ProtoStructToJsonString(const Struct& proto) { std::string output; absl::Status status = MessageToJsonString(proto, &output); if (!status.ok()) { return status; } return output; } util::StatusOr ProtoListToJsonString(const ListValue& proto) { std::string output; absl::Status status = MessageToJsonString(proto, &output); if (!status.ok()) { return status; } return output; } } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/json_util.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_JSON_UTIL_H_ #define TINK_JWT_INTERNAL_JSON_UTIL_H_ #include #include "google/protobuf/struct.pb.h" #include "absl/strings/string_view.h" #include "absl/strings/substitute.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace jwt_internal { util::StatusOr JsonStringToProtoStruct( absl::string_view json_string); util::StatusOr JsonStringToProtoList( absl::string_view json_string); util::StatusOr ProtoStructToJsonString( const google::protobuf::Struct& proto); util::StatusOr ProtoListToJsonString( const google::protobuf::ListValue& proto); } // namespace jwt_internal } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_JSON_UTIL_H_ ================================================ FILE: cc/jwt/internal/json_util_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/json_util.h" #include #include "google/protobuf/struct.pb.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::google::protobuf::ListValue; using ::google::protobuf::Struct; namespace crypto { namespace tink { namespace jwt_internal { TEST(JsonUtil, ParseThenSerializeStructWtihStringListOk) { util::StatusOr proto = JsonStringToProtoStruct(R"({"some_key":["hello","world","!"]})"); ASSERT_THAT(proto, IsOk()); ASSERT_THAT(ProtoStructToJsonString(*proto), IsOkAndHolds(R"({"some_key":["hello","world","!"]})")); } TEST(JsonUtil, ParseThenSerializeStructWtihNumberOk) { util::StatusOr proto = JsonStringToProtoStruct(R"({"some_key":-12345})"); ASSERT_THAT(proto, IsOk()); ASSERT_THAT(ProtoStructToJsonString(*proto), IsOkAndHolds(R"({"some_key":-12345})")); } TEST(JsonUtil, ParseThenSerializeStructWtihBoolOk) { util::StatusOr proto = JsonStringToProtoStruct(R"({"some_key":false})"); ASSERT_THAT(proto, IsOk()); ASSERT_THAT(ProtoStructToJsonString(*proto), IsOkAndHolds(R"({"some_key":false})")); } TEST(JsonUtil, ParseThenSerializeListOk) { util::StatusOr proto = JsonStringToProtoList(R"(["hello", "world", 42, true])"); ASSERT_THAT(proto, IsOk()); ASSERT_THAT(ProtoListToJsonString(*proto), IsOkAndHolds(R"(["hello","world",42,true])")); } TEST(JsonUtil, ParseInvalidStructTokenNotOk) { util::StatusOr proto = JsonStringToProtoStruct(R"({"some_key":false)"); ASSERT_FALSE(proto.ok()); } TEST(JsonUtil, ParseInvalidListTokenNotOk) { util::StatusOr proto = JsonStringToProtoStruct(R"(["one", )"); ASSERT_FALSE(proto.ok()); } TEST(JsonUtil, parseRecursiveJsonStringFails) { std::string recursive_json; for (int i = 0; i < 10000; i++) { recursive_json.append("{\"a\":"); } recursive_json.append("1"); for (int i = 0; i < 10000; i++) { recursive_json.append("}"); } util::StatusOr proto = JsonStringToProtoStruct(recursive_json); EXPECT_FALSE(proto.ok()); } TEST(JsonUtil, ParseStructWithoutQuotesOk) { // TODO(b/360366279) Make parsing stricter that this is not allowed. util::StatusOr proto = JsonStringToProtoStruct(R"({some_key:false})"); ASSERT_THAT(proto, IsOk()); ASSERT_THAT(ProtoStructToJsonString(*proto), IsOkAndHolds(R"({"some_key":false})")); } TEST(JsonUtil, ParseListWithoutQuotesNotOk) { util::StatusOr proto = JsonStringToProtoList(R"([one,two])"); EXPECT_FALSE(proto.ok()); } TEST(JsonUtil, ParseStructWithCommentNotOk) { util::StatusOr proto = JsonStringToProtoStruct(R"({"some_key":false /* comment */})"); EXPECT_FALSE(proto.ok()); } TEST(JsonUtil, ParseListWithCommentNotOk) { util::StatusOr proto = JsonStringToProtoList(R"(["hello", "world" /* comment */])"); EXPECT_FALSE(proto.ok()); } } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_ecdsa_sign_key_manager.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/jwt_ecdsa_sign_key_manager.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/jwt/internal/jwt_ecdsa_verify_key_manager.h" #include "tink/jwt/internal/jwt_public_key_sign_impl.h" #include "tink/jwt/internal/jwt_public_key_sign_internal.h" #include "tink/public_key_sign.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { using crypto::tink::util::Status; using crypto::tink::util::StatusOr; using google::crypto::tink::JwtEcdsaKeyFormat; using google::crypto::tink::JwtEcdsaPrivateKey; using google::crypto::tink::JwtEcdsaPublicKey; StatusOr> JwtEcdsaSignKeyManager::PublicKeySignFactory::Create( const JwtEcdsaPrivateKey& jwt_ecdsa_private_key) const { StatusOr name = JwtEcdsaVerifyKeyManager::AlgorithmName( jwt_ecdsa_private_key.public_key().algorithm()); if (!name.ok()) { return name.status(); } util::StatusOr> sign = raw_key_manager_.GetPrimitive(jwt_ecdsa_private_key); if (!sign.ok()) { return sign.status(); } absl::optional custom_kid = absl::nullopt; if (jwt_ecdsa_private_key.public_key().has_custom_kid()) { custom_kid = jwt_ecdsa_private_key.public_key().custom_kid().value(); } std::unique_ptr jwt_public_key_sign = absl::make_unique(*std::move(sign), *name, custom_kid); return std::move(jwt_public_key_sign); } uint32_t JwtEcdsaSignKeyManager::get_version() const { return raw_key_manager_.get_version(); } google::crypto::tink::KeyData::KeyMaterialType JwtEcdsaSignKeyManager::key_material_type() const { return raw_key_manager_.key_material_type(); } const std::string& JwtEcdsaSignKeyManager::get_key_type() const { return raw_key_manager_.get_key_type(); } StatusOr JwtEcdsaSignKeyManager::CreateKey( const JwtEcdsaKeyFormat& key_format) const { return raw_key_manager_.CreateKey(key_format); } Status JwtEcdsaSignKeyManager::ValidateKey( const JwtEcdsaPrivateKey& key) const { return raw_key_manager_.ValidateKey(key); } Status JwtEcdsaSignKeyManager::ValidateKeyFormat( const JwtEcdsaKeyFormat& key_format) const { return raw_key_manager_.ValidateKeyFormat(key_format); } StatusOr JwtEcdsaSignKeyManager::GetPublicKey( const JwtEcdsaPrivateKey& private_key) const { return raw_key_manager_.GetPublicKey(private_key); } } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_ecdsa_sign_key_manager.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_JWT_ECDSA_SIGN_KEY_MANAGER_H_ #define TINK_JWT_INTERNAL_JWT_ECDSA_SIGN_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/internal/fips_utils.h" #include "tink/jwt/internal/jwt_public_key_sign_internal.h" #include "tink/jwt/internal/raw_jwt_ecdsa_sign_key_manager.h" #include "tink/jwt/jwt_public_key_sign.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/jwt_ecdsa.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { class JwtEcdsaSignKeyManager : public PrivateKeyTypeManager> { public: class PublicKeySignFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create(const google::crypto::tink::JwtEcdsaPrivateKey& private_key) const override; private: const RawJwtEcdsaSignKeyManager raw_key_manager_; }; JwtEcdsaSignKeyManager() : PrivateKeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override; google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override; const std::string& get_key_type() const override; crypto::tink::util::Status ValidateKey( const google::crypto::tink::JwtEcdsaPrivateKey& key) const override; crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::JwtEcdsaKeyFormat& key_format) const override; crypto::tink::util::StatusOr CreateKey( const google::crypto::tink::JwtEcdsaKeyFormat& key_format) const override; crypto::tink::util::StatusOr GetPublicKey(const google::crypto::tink::JwtEcdsaPrivateKey& private_key) const override; internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: const RawJwtEcdsaSignKeyManager raw_key_manager_; }; } // namespace jwt_internal } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_JWT_ECDSA_SIGN_KEY_MANAGER_H_ ================================================ FILE: cc/jwt/internal/jwt_ecdsa_sign_verify_key_manager_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include "google/protobuf/struct.pb.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/jwt/internal/json_util.h" #include "tink/jwt/internal/jwt_ecdsa_sign_key_manager.h" #include "tink/jwt/internal/jwt_ecdsa_verify_key_manager.h" #include "tink/jwt/internal/jwt_format.h" #include "tink/jwt/internal/jwt_public_key_sign_internal.h" #include "tink/jwt/internal/jwt_public_key_verify_internal.h" #include "tink/jwt/jwt_validator.h" #include "tink/jwt/raw_jwt.h" #include "tink/jwt/verified_jwt.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/jwt_ecdsa.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::JwtEcdsaAlgorithm; using ::google::crypto::tink::JwtEcdsaKeyFormat; using ::google::crypto::tink::JwtEcdsaPrivateKey; using ::google::crypto::tink::JwtEcdsaPublicKey; using ::google::crypto::tink::KeyData; using ::testing::Eq; using ::testing::Not; namespace { constexpr absl::string_view kTestKid = "kid-123"; TEST(JwtEcdsaSignVerifyKeyManagerTest, BasicsSign) { EXPECT_EQ(JwtEcdsaSignKeyManager().get_version(), 0); EXPECT_EQ(JwtEcdsaSignKeyManager().get_key_type(), "type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey"); EXPECT_EQ(JwtEcdsaSignKeyManager().key_material_type(), KeyData::ASYMMETRIC_PRIVATE); } TEST(JwtEcdsaSignVerifyKeyManagerTest, BasicsVerify) { EXPECT_EQ(JwtEcdsaVerifyKeyManager().get_version(), 0); EXPECT_EQ(JwtEcdsaVerifyKeyManager().get_key_type(), "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey"); EXPECT_EQ(JwtEcdsaVerifyKeyManager().key_material_type(), KeyData::ASYMMETRIC_PUBLIC); } TEST(JwtEcdsaSignVerifyKeyManagerTest, ValidateEmptyPrivateKey) { EXPECT_THAT(JwtEcdsaSignKeyManager().ValidateKey(JwtEcdsaPrivateKey()), Not(IsOk())); } TEST(JwtEcdsaSignVerifyKeyManagerTest, ValidateEmptyPublicKey) { EXPECT_THAT(JwtEcdsaVerifyKeyManager().ValidateKey(JwtEcdsaPublicKey()), Not(IsOk())); } TEST(JwtEcdsaSignVerifyKeyManagerTest, ValidateEmptyKeyFormat) { EXPECT_THAT(JwtEcdsaSignKeyManager().ValidateKeyFormat(JwtEcdsaKeyFormat()), Not(IsOk())); } TEST(JwtEcdsaSignVerifyKeyManagerTest, ValidKeyFormatES256) { JwtEcdsaKeyFormat key_format; key_format.set_algorithm(JwtEcdsaAlgorithm::ES256); EXPECT_THAT(JwtEcdsaSignKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(JwtEcdsaSignVerifyKeyManagerTest, ValidateKeyFormatES384) { JwtEcdsaKeyFormat key_format; key_format.set_algorithm(JwtEcdsaAlgorithm::ES384); EXPECT_THAT(JwtEcdsaSignKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(JwtEcdsaSignVerifyKeyManagerTest, ValidateKeyFormatES512) { JwtEcdsaKeyFormat key_format; key_format.set_algorithm(JwtEcdsaAlgorithm::ES512); EXPECT_THAT(JwtEcdsaSignKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(JwtEcdsaSignVerifyKeyManagerTest, CreatePrivateKeyAndValidate) { JwtEcdsaKeyFormat key_format; key_format.set_algorithm(JwtEcdsaAlgorithm::ES256); util::StatusOr key = JwtEcdsaSignKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); EXPECT_EQ(key->version(), 0); EXPECT_EQ(key->public_key().algorithm(), key_format.algorithm()); EXPECT_THAT(JwtEcdsaSignKeyManager().ValidateKey(*key), IsOk()); // Change key to an invalid algorithm. key->mutable_public_key()->set_algorithm(JwtEcdsaAlgorithm::ES_UNKNOWN); EXPECT_FALSE(JwtEcdsaSignKeyManager().ValidateKey(*key).ok()); } TEST(JwtEcdsaSignVerifyKeyManagerTest, CreatePublicKeyAndValidate) { JwtEcdsaKeyFormat key_format; key_format.set_algorithm(JwtEcdsaAlgorithm::ES256); util::StatusOr key = JwtEcdsaSignKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); util::StatusOr public_key = JwtEcdsaSignKeyManager().GetPublicKey(*key); EXPECT_THAT(JwtEcdsaVerifyKeyManager().ValidateKey(*public_key), IsOk()); // Change key to an invalid algorithm. public_key->set_algorithm(JwtEcdsaAlgorithm::ES_UNKNOWN); EXPECT_FALSE(JwtEcdsaVerifyKeyManager().ValidateKey(*public_key).ok()); } TEST(JwtEcdsaSignVerifyKeyManagerTest, GetAndUsePrimitive) { JwtEcdsaKeyFormat key_format; key_format.set_algorithm(JwtEcdsaAlgorithm::ES256); util::StatusOr key = JwtEcdsaSignKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); util::StatusOr> sign = JwtEcdsaSignKeyManager().GetPrimitive(*key); ASSERT_THAT(sign, IsOk()); util::StatusOr raw_jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr compact = (*sign)->SignAndEncodeWithKid(*raw_jwt, /*kid=*/absl::nullopt); ASSERT_THAT(compact, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .ExpectIssuer("issuer") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); util::StatusOr> verify = JwtEcdsaVerifyKeyManager().GetPrimitive( key->public_key()); ASSERT_THAT(verify, IsOk()); util::StatusOr verified_jwt = (*verify)->VerifyAndDecodeWithKid( *compact, *validator, /*kid=*/absl::nullopt); ASSERT_THAT(verified_jwt, IsOk()); util::StatusOr issuer = verified_jwt->GetIssuer(); EXPECT_THAT(issuer, IsOkAndHolds("issuer")); EXPECT_THAT((*verify) ->VerifyAndDecodeWithKid(*compact, *validator, kTestKid) .status(), Not(IsOk())); util::StatusOr validator2 = JwtValidatorBuilder().ExpectIssuer("unknown").Build(); ASSERT_THAT(validator2, IsOk()); EXPECT_THAT( (*verify) ->VerifyAndDecodeWithKid(*compact, *validator2, /*kid=*/absl::nullopt) .status(), Not(IsOk())); // Token with kid header util::StatusOr token_with_kid = (*sign)->SignAndEncodeWithKid(*raw_jwt, kTestKid); ASSERT_THAT(compact, IsOk()); EXPECT_THAT((*verify) ->VerifyAndDecodeWithKid(*token_with_kid, *validator, /*kid=*/absl::nullopt) .status(), IsOk()); EXPECT_THAT( (*verify) ->VerifyAndDecodeWithKid(*token_with_kid, *validator, kTestKid) .status(), IsOk()); EXPECT_THAT( (*verify) ->VerifyAndDecodeWithKid(*token_with_kid, *validator, "other-kid") .status(), Not(IsOk())); } TEST(JwtRsaSsaPkcs1SignVerifyKeyManagerTest, GetAndUsePrimitivesWithCustomKid) { JwtEcdsaKeyFormat key_format; key_format.set_algorithm(JwtEcdsaAlgorithm::ES256); util::StatusOr key = JwtEcdsaSignKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); key->mutable_public_key()->mutable_custom_kid()->set_value( "Lorem ipsum dolor sit amet, consectetur adipiscing elit"); util::StatusOr> sign = JwtEcdsaSignKeyManager().GetPrimitive(*key); ASSERT_THAT(sign, IsOk()); util::StatusOr raw_jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr compact = (*sign)->SignAndEncodeWithKid(*raw_jwt, /*kid=*/absl::nullopt); ASSERT_THAT(compact, IsOk()); // parse header and check "kid" std::vector parts = absl::StrSplit(*compact, '.'); ASSERT_THAT(parts.size(), Eq(3)); std::string json_header; ASSERT_TRUE(DecodeHeader(parts[0], &json_header)); util::StatusOr header = JsonStringToProtoStruct(json_header); ASSERT_THAT(header, IsOk()); auto it = header->fields().find("kid"); ASSERT_FALSE(it == header->fields().end()); EXPECT_THAT(it->second.string_value(), Eq("Lorem ipsum dolor sit amet, consectetur adipiscing elit")); // validate token util::StatusOr validator = JwtValidatorBuilder() .ExpectIssuer("issuer") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); util::StatusOr> verify = JwtEcdsaVerifyKeyManager().GetPrimitive( key->public_key()); ASSERT_THAT(verify, IsOk()); util::StatusOr verified_jwt = (*verify)->VerifyAndDecodeWithKid( *compact, *validator, /*kid=*/absl::nullopt); ASSERT_THAT(verified_jwt, IsOk()); util::StatusOr issuer = verified_jwt->GetIssuer(); ASSERT_THAT(issuer, IsOk()); EXPECT_THAT(*issuer, Eq("issuer")); // passing a kid when custom_kid is set should fail EXPECT_THAT((*sign)->SignAndEncodeWithKid(*raw_jwt, kTestKid).status(), Not(IsOk())); EXPECT_THAT((*verify) ->VerifyAndDecodeWithKid(*compact, *validator, kTestKid) .status(), Not(IsOk())); // Test that custom kid is verified: validation should fail with other kid. key->mutable_public_key()->mutable_custom_kid()->set_value("other kid"); ASSERT_THAT(validator, IsOk()); util::StatusOr> other_verify = JwtEcdsaVerifyKeyManager().GetPrimitive( key->public_key()); ASSERT_THAT(other_verify, IsOk()); EXPECT_THAT( (*other_verify) ->VerifyAndDecodeWithKid(*compact, *validator, /*kid=*/absl::nullopt) .status(), Not(IsOk())); } TEST(JwtEcdsaSignVerifyKeyManagerTest, VerifyFailsWithDifferentKey) { JwtEcdsaKeyFormat key_format; key_format.set_algorithm(JwtEcdsaAlgorithm::ES256); util::StatusOr key1 = JwtEcdsaSignKeyManager().CreateKey(key_format); ASSERT_THAT(key1, IsOk()); util::StatusOr key2 = JwtEcdsaSignKeyManager().CreateKey(key_format); ASSERT_THAT(key2, IsOk()); util::StatusOr> sign1 = JwtEcdsaSignKeyManager().GetPrimitive(*key1); ASSERT_THAT(sign1, IsOk()); util::StatusOr raw_jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr compact = (*sign1)->SignAndEncodeWithKid(*raw_jwt, /*kid=*/absl::nullopt); ASSERT_THAT(compact, IsOk()); util::StatusOr validator = JwtValidatorBuilder().AllowMissingExpiration().Build(); util::StatusOr> verify2 = JwtEcdsaVerifyKeyManager().GetPrimitive( key2->public_key()); EXPECT_THAT(verify2, IsOk()); EXPECT_THAT( (*verify2) ->VerifyAndDecodeWithKid(*compact, *validator, /*kid=*/absl::nullopt) .status(), Not(IsOk())); } } // namespace } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_ecdsa_verify_key_manager.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/jwt_ecdsa_verify_key_manager.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/jwt/internal/jwt_public_key_verify_impl.h" #include "tink/jwt/internal/jwt_public_key_verify_internal.h" #include "tink/public_key_verify.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { using crypto::tink::util::Status; using crypto::tink::util::StatusOr; using google::crypto::tink::JwtEcdsaPublicKey; using google::crypto::tink::JwtEcdsaAlgorithm; StatusOr> JwtEcdsaVerifyKeyManager::PublicKeyVerifyFactory::Create( const JwtEcdsaPublicKey& jwt_ecdsa_public_key) const { StatusOr name = AlgorithmName(jwt_ecdsa_public_key.algorithm()); if (!name.ok()) { return name.status(); } util::StatusOr> verify = raw_key_manager_.GetPrimitive(jwt_ecdsa_public_key); if (!verify.ok()) { return verify.status(); } absl::optional custom_kid = absl::nullopt; if (jwt_ecdsa_public_key.has_custom_kid()) { custom_kid = jwt_ecdsa_public_key.custom_kid().value(); } std::unique_ptr jwt_public_key_verify = absl::make_unique( *std::move(verify), *name, custom_kid); return std::move(jwt_public_key_verify); } uint32_t JwtEcdsaVerifyKeyManager::get_version() const { return raw_key_manager_.get_version(); } google::crypto::tink::KeyData::KeyMaterialType JwtEcdsaVerifyKeyManager::key_material_type() const { return raw_key_manager_.key_material_type(); } const std::string& JwtEcdsaVerifyKeyManager::get_key_type() const { return raw_key_manager_.get_key_type(); } Status JwtEcdsaVerifyKeyManager::ValidateKey( const JwtEcdsaPublicKey& key) const { return raw_key_manager_.ValidateKey(key); } StatusOr JwtEcdsaVerifyKeyManager::AlgorithmName( const JwtEcdsaAlgorithm& algorithm) { switch (algorithm) { case JwtEcdsaAlgorithm::ES256: return std::string("ES256"); case JwtEcdsaAlgorithm::ES384: return std::string("ES384"); case JwtEcdsaAlgorithm::ES512: return std::string("ES512"); default: return Status(absl::StatusCode::kInvalidArgument, "Unknown algorithm"); } } } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_ecdsa_verify_key_manager.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_JWT_ECDSA_VERIFY_KEY_MANAGER_H_ #define TINK_JWT_INTERNAL_JWT_ECDSA_VERIFY_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/internal/fips_utils.h" #include "tink/jwt/internal/jwt_public_key_verify_impl.h" #include "tink/jwt/internal/jwt_public_key_verify_internal.h" #include "tink/jwt/internal/raw_jwt_ecdsa_verify_key_manager.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/jwt_ecdsa.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { class JwtEcdsaVerifyKeyManager : public KeyTypeManager> { public: class PublicKeyVerifyFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create(const google::crypto::tink::JwtEcdsaPublicKey& jwt_ecdsa_public_key) const override; private: const RawJwtEcdsaVerifyKeyManager raw_key_manager_; }; JwtEcdsaVerifyKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override; google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override; const std::string& get_key_type() const override; crypto::tink::util::Status ValidateKey( const google::crypto::tink::JwtEcdsaPublicKey& key) const override; internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: static crypto::tink::util::StatusOr AlgorithmName( const google::crypto::tink::JwtEcdsaAlgorithm& algorithm); const RawJwtEcdsaVerifyKeyManager raw_key_manager_; friend class JwtEcdsaSignKeyManager; }; } // namespace jwt_internal } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_JWT_ECDSA_VERIFY_KEY_MANAGER_H_ ================================================ FILE: cc/jwt/internal/jwt_format.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/jwt_format.h" #include #include #include "absl/base/internal/endian.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/crypto_format.h" #include "tink/jwt/internal/json_util.h" #include "tink/jwt/raw_jwt.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { using ::google::crypto::tink::OutputPrefixType; namespace { bool isValidUrlsafeBase64Char(char c) { return (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || ((c >= '0') && (c <= '9')) || ((c == '-') || (c == '_'))); } bool StrictWebSafeBase64Unescape(absl::string_view src, std::string* dest) { for (char c : src) { if (!isValidUrlsafeBase64Char(c)) { return false; } } return absl::WebSafeBase64Unescape(src, dest); } util::Status ValidateKidInHeader(const google::protobuf::Value& kid_in_header, absl::string_view kid) { if (kid_in_header.kind_case() != google::protobuf::Value::kStringValue) { return util::Status(absl::StatusCode::kInvalidArgument, "kid header is not a string"); } if (kid_in_header.string_value() != kid) { return util::Status(absl::StatusCode::kInvalidArgument, "invalid kid header"); } return util::OkStatus(); } } // namespace std::string EncodeHeader(absl::string_view json_header) { return absl::WebSafeBase64Escape(json_header); } bool DecodeHeader(absl::string_view header, std::string* json_header) { return StrictWebSafeBase64Unescape(header, json_header); } absl::optional GetKid(uint32_t key_id, OutputPrefixType output_prefix_type) { if (output_prefix_type != OutputPrefixType::TINK) { return absl::nullopt; } char buffer[4]; absl::big_endian::Store32(buffer, key_id); return absl::WebSafeBase64Escape(absl::string_view(buffer, 4)); } absl::optional GetKeyId(absl::string_view kid) { std::string decoded_kid; if (!StrictWebSafeBase64Unescape(kid, &decoded_kid)) { return absl::nullopt; } if (decoded_kid.size() != 4) { return absl::nullopt; } return absl::big_endian::Load32(decoded_kid.data()); } util::StatusOr CreateHeader( absl::string_view algorithm, absl::optional type_header, absl::optional kid) { google::protobuf::Struct header; auto fields = header.mutable_fields(); if (kid.has_value()) { (*fields)["kid"].set_string_value(std::string(kid.value())); } if (type_header.has_value()) { (*fields)["typ"].set_string_value(std::string(type_header.value())); } (*fields)["alg"].set_string_value(std::string(algorithm)); util::StatusOr json_header = jwt_internal::ProtoStructToJsonString(header); if (!json_header.ok()) { return json_header.status(); } return EncodeHeader(*json_header); } util::Status ValidateHeader(const google::protobuf::Struct& header, absl::string_view algorithm, absl::optional tink_kid, absl::optional custom_kid) { auto fields = header.fields(); auto it = fields.find("alg"); if (it == fields.end()) { return util::Status(absl::StatusCode::kInvalidArgument, "header is missing alg"); } const google::protobuf::Value& alg = it->second; if (alg.kind_case() != google::protobuf::Value::kStringValue) { return util::Status(absl::StatusCode::kInvalidArgument, "alg is not a string"); } if (alg.string_value() != algorithm) { return util::Status(absl::StatusCode::kInvalidArgument, "invalid alg"); } if (fields.find("crit") != fields.end()) { return util::Status(absl::StatusCode::kInvalidArgument, "all tokens with crit headers are rejected"); } if (tink_kid.has_value() && custom_kid.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "custom_kid can only be set for RAW keys"); } auto kid_it = fields.find("kid"); bool header_has_kid = (kid_it != fields.end()); if (tink_kid.has_value()) { if (!header_has_kid) { // for output prefix type TINK, the kid header is required. return util::Status(absl::StatusCode::kInvalidArgument, "missing kid in header"); } util::Status status = ValidateKidInHeader(kid_it->second, *tink_kid); if (!status.ok()) { return status; } } if (custom_kid.has_value() && header_has_kid) { util::Status status = ValidateKidInHeader(kid_it->second, *custom_kid); if (!status.ok()) { return status; } } return util::OkStatus(); } absl::optional GetTypeHeader( const google::protobuf::Struct& header) { auto it = header.fields().find("typ"); if (it == header.fields().end()) { return absl::nullopt; } const auto& value = it->second; if (value.kind_case() != google::protobuf::Value::kStringValue) { return absl::nullopt; } return value.string_value(); } std::string EncodePayload(absl::string_view json_payload) { return absl::WebSafeBase64Escape(json_payload); } bool DecodePayload(absl::string_view payload, std::string* json_payload) { return StrictWebSafeBase64Unescape(payload, json_payload); } std::string EncodeSignature(absl::string_view signature) { return absl::WebSafeBase64Escape(signature); } bool DecodeSignature(absl::string_view encoded_signature, std::string* signature) { return StrictWebSafeBase64Unescape(encoded_signature, signature); } util::StatusOr RawJwtParser::FromJson( absl::optional type_header, absl::string_view json_payload) { return RawJwt::FromJson(type_header, json_payload); } } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_format.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_JWT_FORMAT_H_ #define TINK_JWT_INTERNAL_JWT_FORMAT_H_ #include #include #include "google/protobuf/struct.pb.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/jwt/raw_jwt.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { std::string EncodeHeader(absl::string_view json_header); bool DecodeHeader(absl::string_view header, std::string* json_header); absl::optional GetKid( uint32_t key_id, ::google::crypto::tink::OutputPrefixType output_prefix_type); absl::optional GetKeyId(absl::string_view kid); util::StatusOr CreateHeader(absl::string_view algorithm, absl::optional type_header, absl::optional kid); util::Status ValidateHeader(const google::protobuf::Struct& header, absl::string_view algorithm, absl::optional tink_kid, absl::optional custom_kid); absl::optional GetTypeHeader( const google::protobuf::Struct& header); std::string EncodePayload(absl::string_view json_payload); bool DecodePayload(absl::string_view payload, std::string* json_payload); std::string EncodeSignature(absl::string_view signature); bool DecodeSignature(absl::string_view encoded_signature, std::string* signature); class RawJwtParser { public: static util::StatusOr FromJson( absl::optional type_header, absl::string_view json_payload); }; } // namespace jwt_internal } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_JWT_FORMAT_H_ ================================================ FILE: cc/jwt/internal/jwt_format_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/jwt_format.h" #include #include #include #include "google/protobuf/struct.pb.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/time/time.h" #include "absl/types/optional.h" #include "tink/jwt/internal/json_util.h" #include "tink/jwt/raw_jwt.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::google::crypto::tink::OutputPrefixType; using testing::Eq; namespace crypto { namespace tink { namespace jwt_internal { TEST(JwtFormat, EncodeDecodeHeader) { std::string header = R"({"alg":"HS256"})"; std::string output; ASSERT_TRUE(DecodeHeader(EncodeHeader(header), &output)); EXPECT_THAT(output, Eq(header)); } TEST(JwtFormat, EncodeFixedHeader) { // Null-terminted example from https://tools.ietf.org/html/rfc7519#section-3.1 char header[] = {123, 34, 116, 121, 112, 34, 58, 34, 74, 87, 84, 34, 44, 13, 10, 32, 34, 97, 108, 103, 34, 58, 34, 72, 83, 50, 53, 54, 34, 125, 0}; EXPECT_THAT(EncodeHeader(header), Eq("eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9")); } TEST(JwtFormat, DecodedHeaderWithLineFeedFails) { std::string output; ASSERT_FALSE( DecodeHeader("eyJ0eXAiOiJKV1Qi\nLA0KICJhbGciOiJIUzI1NiJ9", &output)); } TEST(JwtFormat, EncodeDecodePayload) { std::string payload = R"({"iss":"issuer"})"; std::string output; ASSERT_TRUE(DecodePayload(EncodePayload(payload), &output)); EXPECT_THAT(output, Eq(payload)); } TEST(JwtFormat, EncodeFixedPayload) { // Null-terminted example from https://tools.ietf.org/html/rfc7519#section-3.1 char payload[] = {123, 34, 105, 115, 115, 34, 58, 34, 106, 111, 101, 34, 44, 13, 10, 32, 34, 101, 120, 112, 34, 58, 49, 51, 48, 48, 56, 49, 57, 51, 56, 48, 44, 13, 10, 32, 34, 104, 116, 116, 112, 58, 47, 47, 101, 120, 97, 109, 112, 108, 101, 46, 99, 111, 109, 47, 105, 115, 95, 114, 111, 111, 116, 34, 58, 116, 114, 117, 101, 125, 0}; EXPECT_THAT(EncodeHeader(payload), Eq("eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0" "dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ")); } TEST(JwtFormat, DecodeInvalidPayload_fails) { std::string output; ASSERT_FALSE(DecodePayload("eyJmb28iO?JiYXIifQ", &output)); } TEST(JwtFormat, DecodeAndValidateFixedHeaderHS256) { // Example from https://tools.ietf.org/html/rfc7515#appendix-A.1 std::string encoded_header = "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9"; std::string json_header; ASSERT_TRUE(DecodeHeader(encoded_header, &json_header)); EXPECT_THAT(json_header, Eq("{\"typ\":\"JWT\",\r\n \"alg\":\"HS256\"}")); util::StatusOr header = JsonStringToProtoStruct(json_header); EXPECT_THAT(header, IsOk()); EXPECT_THAT(ValidateHeader(*header, "HS256", absl::nullopt, absl::nullopt), IsOk()); EXPECT_FALSE( ValidateHeader(*header, "RS256", absl::nullopt, absl::nullopt).ok()); } TEST(JwtFormat, DecodeAndValidateFixedHeaderRS256) { // Example from https://tools.ietf.org/html/rfc7515#appendix-A.2 std::string encoded_header = "eyJhbGciOiJSUzI1NiJ9"; std::string json_header; ASSERT_TRUE(DecodeHeader(encoded_header, &json_header)); EXPECT_THAT(json_header, Eq(R"({"alg":"RS256"})")); util::StatusOr header = JsonStringToProtoStruct(json_header); EXPECT_THAT(header, IsOk()); EXPECT_THAT(ValidateHeader(*header, "RS256", absl::nullopt, absl::nullopt), IsOk()); EXPECT_FALSE( ValidateHeader(*header, "HS256", absl::nullopt, absl::nullopt).ok()); } TEST(JwtFormat, CreateValidateHeader) { util::StatusOr encoded_header = CreateHeader("PS384", absl::nullopt, absl::nullopt); EXPECT_THAT(encoded_header, IsOk()); std::string json_header; ASSERT_TRUE(DecodeHeader(*encoded_header, &json_header)); util::StatusOr header = JsonStringToProtoStruct(json_header); EXPECT_THAT(header, IsOk()); EXPECT_THAT(ValidateHeader(*header, "PS384", absl::nullopt, absl::nullopt), IsOk()); EXPECT_FALSE( ValidateHeader(*header, "HS256", absl::nullopt, absl::nullopt).ok()); } TEST(JwtFormat, CreateValidateHeaderWithTypeAndKid) { util::StatusOr encoded_header = CreateHeader("PS384", "JWT", "kid-1234"); EXPECT_THAT(encoded_header, IsOk()); std::string json_header; ASSERT_TRUE(DecodeHeader(*encoded_header, &json_header)); util::StatusOr header = JsonStringToProtoStruct(json_header); EXPECT_THAT(header, IsOk()); EXPECT_THAT(GetTypeHeader(*header), Eq("JWT")); EXPECT_THAT(ValidateHeader(*header, "PS384", absl::nullopt, absl::nullopt), IsOk()); EXPECT_FALSE( ValidateHeader(*header, "HS256", absl::nullopt, absl::nullopt).ok()); auto it = header->fields().find("kid"); EXPECT_FALSE(it == header->fields().end()); const google::protobuf::Value& value = it->second; EXPECT_THAT(value.kind_case(), Eq(google::protobuf::Value::kStringValue)); EXPECT_THAT(value.string_value(), Eq("kid-1234")); } TEST(JwtFormat, ValidateEmptyHeaderFails) { google::protobuf::Struct empty_header; EXPECT_FALSE( ValidateHeader(empty_header, "HS256", absl::nullopt, absl::nullopt).ok()); } TEST(JwtFormat, ValidateHeaderWithUnknownTypeOk) { std::string json_header = R"({"alg":"HS256","typ":"unknown"})"; util::StatusOr header = JsonStringToProtoStruct(json_header); EXPECT_THAT(header, IsOk()); EXPECT_THAT(ValidateHeader(*header, "HS256", absl::nullopt, absl::nullopt), IsOk()); } TEST(JwtFormat, ValidateHeaderRejectsCrit) { std::string json_header = R"({"alg":"HS256","crit":["http://example.invalid/UNDEFINED"],)" R"("http://example.invalid/UNDEFINED":true})"; util::StatusOr header = JsonStringToProtoStruct(json_header); EXPECT_THAT(header, IsOk()); EXPECT_FALSE( ValidateHeader(*header, "HS256", absl::nullopt, absl::nullopt).ok()); } TEST(JwtFormat, ValidateHeaderWithUnknownEntry) { std::string json_header = R"({"alg":"HS256","unknown":"header"})"; util::StatusOr header = JsonStringToProtoStruct(json_header); EXPECT_THAT(header, IsOk()); EXPECT_THAT(ValidateHeader(*header, "HS256", absl::nullopt, absl::nullopt), IsOk()); } TEST(JwtFormat, ValidateHeaderWithInvalidAlgTypFails) { std::string json_header = R"({"alg":true})"; util::StatusOr header = JsonStringToProtoStruct(json_header); EXPECT_THAT(header, IsOk()); EXPECT_FALSE( ValidateHeader(*header, "HS256", absl::nullopt, absl::nullopt).ok()); } TEST(JwtFormat, ValidateHeaderWithTinkKid) { std::string json_header = R"({"alg":"HS256","kid":"tink_kid"})"; util::StatusOr header = JsonStringToProtoStruct(json_header); EXPECT_THAT(header, IsOk()); EXPECT_THAT(ValidateHeader(*header, "HS256", "tink_kid", absl::nullopt), IsOk()); EXPECT_FALSE( ValidateHeader(*header, "HS256", "other_tink_kid", absl::nullopt).ok()); } TEST(JwtFormat, ValidateHeaderWithTinkKidMissingFails) { std::string json_header = R"({"alg":"HS256"})"; util::StatusOr header = JsonStringToProtoStruct(json_header); EXPECT_THAT(header, IsOk()); // If tink_kid is set, then the kid is required in the header. EXPECT_FALSE( ValidateHeader(*header, "HS256", "tink_kid", absl::nullopt).ok()); } TEST(JwtFormat, ValidateHeaderWithCustomKid) { std::string json_header = R"({"alg":"HS256","kid":"custom_kid"})"; util::StatusOr header = JsonStringToProtoStruct(json_header); EXPECT_THAT(header, IsOk()); EXPECT_THAT(ValidateHeader(*header, "HS256", absl::nullopt, "custom_kid"), IsOk()); EXPECT_FALSE( ValidateHeader(*header, "HS256", absl::nullopt, "other_custom_kid").ok()); } TEST(JwtFormat, ValidateHeaderWithCustomKidMissingFails) { std::string json_header = R"({"alg":"HS256"})"; util::StatusOr header = JsonStringToProtoStruct(json_header); EXPECT_THAT(header, IsOk()); // If custom_kid is set, then the kid is not required in the header. EXPECT_THAT(ValidateHeader(*header, "HS256", absl::nullopt, "custom_kid"), IsOk()); } TEST(JwtFormat, ValidateHeaderWithTinkAndCustomKidFails) { std::string json_header = R"({"alg":"HS256","kid":"tink_kid"})"; util::StatusOr header = JsonStringToProtoStruct(json_header); EXPECT_THAT(header, IsOk()); EXPECT_FALSE(ValidateHeader(*header, "HS256", "kid", "kid").ok()); } TEST(JwtFormat, GetKidWithTinkOutputPrefixType) { uint32_t keyId = 0x1ac6a944; std::string kid = "GsapRA"; EXPECT_THAT(GetKid(keyId, OutputPrefixType::TINK), Eq(kid)); EXPECT_THAT(GetKeyId(kid), Eq(keyId)); } TEST(JwtFormat, GetKeyId) { uint32_t keyId = 0x1ac6a944; std::string kid = "GsapRA"; EXPECT_THAT(GetKeyId(kid), Eq(keyId)); } TEST(JwtFormat, GetKidWithRawOutputPrefixTypeIsNotPresent) { uint32_t keyId = 0x1ac6a944; EXPECT_THAT(GetKid(keyId, OutputPrefixType::RAW), Eq(absl::nullopt)); } TEST(JwtFormat, KeyIdKidConversion) { EXPECT_THAT(GetKeyId(*GetKid(0x12345678, OutputPrefixType::TINK)), Eq(0x12345678)); EXPECT_THAT(GetKeyId(*GetKid(0, OutputPrefixType::TINK)), Eq(0)); EXPECT_THAT(GetKeyId(*GetKid(100, OutputPrefixType::TINK)), Eq(100)); EXPECT_THAT(GetKeyId(*GetKid(2147483647, OutputPrefixType::TINK)), Eq(2147483647)); EXPECT_THAT(GetKeyId(*GetKid(0xffffffff, OutputPrefixType::TINK)), Eq(0xffffffff)); } TEST(JwtFormat, GetKeyIdFromInvalidKidIsNotPresent) { EXPECT_THAT(GetKeyId(""), Eq(absl::nullopt)); EXPECT_THAT(GetKeyId("Gsap"), Eq(absl::nullopt)); EXPECT_THAT(GetKeyId("GsapRAAA"), Eq(absl::nullopt)); } TEST(JwtFormat, DecodeFixedPayload) { // Example from https://tools.ietf.org/html/rfc7519#section-3.1 std::string encoded_payload = "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0" "dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ"; std::string expected = "{\"iss\":\"joe\",\r\n \"exp\":1300819380,\r\n " "\"http://example.com/is_root\":true}"; std::string output; ASSERT_TRUE(DecodePayload(encoded_payload, &output)); EXPECT_THAT(output, Eq(expected)); } TEST(JwtFormat, DecodePayloadWithLineFeedFails) { // A linefeed as part of the payload (as in test DecodeFixedPayload) is fine, // but a linefeed in the encoded payload is not. std::string encoded_header_with_line_feed = "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0\n" "dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ"; std::string output; ASSERT_FALSE( DecodePayload(encoded_header_with_line_feed, &output)); } TEST(JwtFormat, EncodeFixedSignature) { std::string encoded_signature = "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"; std::string signature; ASSERT_TRUE(DecodeSignature(encoded_signature, &signature)); EXPECT_THAT(EncodeSignature(signature), Eq(encoded_signature)); } TEST(JwtFormat, DecodeSignatureWithLineFeedFails) { std::string output; ASSERT_FALSE( DecodePayload("dBjftJeZ4CVP-mB92K2\n7uhbUJU1p1r_wW1gFWFOEjXk", &output)); } TEST(RawJwt, FromJson) { util::StatusOr jwt = RawJwtParser::FromJson( absl::nullopt, R"({"iss":"issuer", "sub":"subject", "exp":123, "aud":["a1", "a2"]})"); ASSERT_THAT(jwt, IsOk()); EXPECT_FALSE(jwt->HasTypeHeader()); EXPECT_THAT(jwt->GetIssuer(), IsOkAndHolds("issuer")); EXPECT_THAT(jwt->GetSubject(), IsOkAndHolds("subject")); EXPECT_THAT(jwt->GetExpiration(), IsOkAndHolds(absl::FromUnixSeconds(123))); std::vector expected_audiences = {"a1", "a2"}; EXPECT_THAT(jwt->GetAudiences(), IsOkAndHolds(expected_audiences)); } TEST(RawJwt, FromJsonWithTypeHeader) { util::StatusOr jwt = RawJwtParser::FromJson("typeHeader", R"({"iss":"issuer"})"); ASSERT_THAT(jwt, IsOk()); EXPECT_THAT(jwt->GetTypeHeader(), IsOkAndHolds("typeHeader")); EXPECT_THAT(jwt->GetIssuer(), IsOkAndHolds("issuer")); } TEST(RawJwt, FromJsonExpExpiration) { util::StatusOr jwt = RawJwtParser::FromJson(absl::nullopt, R"({"exp":1e10})"); ASSERT_THAT(jwt, IsOk()); EXPECT_THAT(jwt->GetExpiration(), IsOkAndHolds(absl::FromUnixSeconds(10000000000))); } TEST(RawJwt, FromJsonExpirationTooLarge) { util::StatusOr jwt = RawJwtParser::FromJson(absl::nullopt, R"({"exp":1e30})"); EXPECT_FALSE(jwt.ok()); } TEST(RawJwt, FromJsonNegativeExpirationAreInvalid) { util::StatusOr jwt = RawJwtParser::FromJson(absl::nullopt, R"({"exp":-1})"); EXPECT_FALSE(jwt.ok()); } TEST(RawJwt, FromJsonPreservesStringAud) { util::StatusOr jwt = RawJwtParser::FromJson(absl::nullopt, R"({"aud":"audience"})"); ASSERT_THAT(jwt, IsOk()); std::vector expected = {"audience"}; EXPECT_TRUE(jwt->HasAudiences()); EXPECT_THAT(jwt->GetAudiences(), IsOkAndHolds(expected)); EXPECT_THAT(jwt->GetJsonPayload(), IsOkAndHolds(R"({"aud":"audience"})")); } TEST(RawJwt, FromJsonPreservesListAud) { util::StatusOr jwt = RawJwtParser::FromJson(absl::nullopt, R"({"aud":["audience"]})"); ASSERT_THAT(jwt, IsOk()); std::vector expected = {"audience"}; EXPECT_TRUE(jwt->HasAudiences()); EXPECT_THAT(jwt->GetAudiences(), IsOkAndHolds(expected)); EXPECT_THAT(jwt->GetJsonPayload(), IsOkAndHolds(R"({"aud":["audience"]})")); } TEST(RawJwt, FromJsonWithBadRegisteredTypes) { EXPECT_FALSE(RawJwtParser::FromJson(absl::nullopt, R"({"iss":123})").ok()); EXPECT_FALSE(RawJwtParser::FromJson(absl::nullopt, R"({"sub":123})").ok()); EXPECT_FALSE(RawJwtParser::FromJson(absl::nullopt, R"({"aud":123})").ok()); EXPECT_FALSE(RawJwtParser::FromJson(absl::nullopt, R"({"aud":[]})").ok()); EXPECT_FALSE( RawJwtParser::FromJson(absl::nullopt, R"({"aud":["abc",123]})").ok()); EXPECT_FALSE(RawJwtParser::FromJson(absl::nullopt, R"({"exp":"abc"})").ok()); EXPECT_FALSE(RawJwtParser::FromJson(absl::nullopt, R"({"nbf":"abc"})").ok()); EXPECT_FALSE(RawJwtParser::FromJson(absl::nullopt, R"({"iat":"abc"})").ok()); } } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_hmac_key_manager.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/jwt_hmac_key_manager.h" #include #include #include #include "absl/strings/string_view.h" #include "tink/input_stream.h" #include "tink/jwt/internal/raw_jwt_hmac_key_manager.h" #include "tink/mac.h" #include "tink/subtle/hmac_boringssl.h" #include "tink/subtle/random.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/input_stream_util.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/common.pb.h" #include "proto/jwt_hmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { using crypto::tink::util::Status; using crypto::tink::util::StatusOr; using google::crypto::tink::JwtHmacKey; using google::crypto::tink::JwtHmacKeyFormat; uint32_t JwtHmacKeyManager::get_version() const { return raw_key_manager_.get_version(); } google::crypto::tink::KeyData::KeyMaterialType JwtHmacKeyManager::key_material_type() const { return raw_key_manager_.key_material_type(); } const std::string& JwtHmacKeyManager::get_key_type() const { return raw_key_manager_.get_key_type(); } StatusOr JwtHmacKeyManager::CreateKey( const JwtHmacKeyFormat& jwt_hmac_key_format) const { return raw_key_manager_.CreateKey(jwt_hmac_key_format); } StatusOr JwtHmacKeyManager::DeriveKey( const JwtHmacKeyFormat& jwt_hmac_key_format, InputStream* input_stream) const { return raw_key_manager_.DeriveKey(jwt_hmac_key_format, input_stream); } Status JwtHmacKeyManager::ValidateKey(const JwtHmacKey& key) const { return raw_key_manager_.ValidateKey(key); } Status JwtHmacKeyManager::ValidateKeyFormat( const JwtHmacKeyFormat& key_format) const { return raw_key_manager_.ValidateKeyFormat(key_format); } } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_hmac_key_manager.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_JWT_HMAC_KEY_MANAGER_H_ #define TINK_JWT_INTERNAL_JWT_HMAC_KEY_MANAGER_H_ #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/types/optional.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/input_stream.h" #include "tink/internal/fips_utils.h" #include "tink/jwt/internal/jwt_mac_impl.h" #include "tink/jwt/internal/jwt_mac_internal.h" #include "tink/jwt/internal/raw_jwt_hmac_key_manager.h" #include "tink/jwt/jwt_mac.h" #include "tink/mac.h" #include "tink/subtle/hmac_boringssl.h" #include "tink/util/constants.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/jwt_hmac.pb.h" namespace crypto { namespace tink { namespace jwt_internal { class JwtHmacKeyManager : public KeyTypeManager> { public: class JwtMacFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::JwtHmacKey& jwt_hmac_key) const override { int tag_size; std::string algorithm; google::crypto::tink::HashType hash_type; switch (jwt_hmac_key.algorithm()) { case google::crypto::tink::JwtHmacAlgorithm::HS256: hash_type = google::crypto::tink::HashType::SHA256; tag_size = 32; algorithm = "HS256"; break; case google::crypto::tink::JwtHmacAlgorithm::HS384: hash_type = google::crypto::tink::HashType::SHA384; tag_size = 48; algorithm = "HS384"; break; case google::crypto::tink::JwtHmacAlgorithm::HS512: hash_type = google::crypto::tink::HashType::SHA512; tag_size = 64; algorithm = "HS512"; break; default: return util::Status(absl::StatusCode::kInvalidArgument, "Unknown algorithm."); } crypto::tink::util::StatusOr> mac = subtle::HmacBoringSsl::New( util::Enums::ProtoToSubtle(hash_type), tag_size, util::SecretDataFromStringView(jwt_hmac_key.key_value())); if (!mac.ok()) { return mac.status(); } absl::optional custom_kid = absl::nullopt; if (jwt_hmac_key.has_custom_kid()) { custom_kid = jwt_hmac_key.custom_kid().value(); } std::unique_ptr jwt_mac = absl::make_unique(*std::move(mac), algorithm, custom_kid); return std::move(jwt_mac); } }; JwtHmacKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override; google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override; const std::string& get_key_type() const override; crypto::tink::util::Status ValidateKey( const google::crypto::tink::JwtHmacKey& key) const override; crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::JwtHmacKeyFormat& key_format) const override; crypto::tink::util::StatusOr CreateKey( const google::crypto::tink::JwtHmacKeyFormat& key_format) const override; crypto::tink::util::StatusOr DeriveKey( const google::crypto::tink::JwtHmacKeyFormat& key_format, InputStream* input_stream) const override; internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: const RawJwtHmacKeyManager raw_key_manager_; }; } // namespace jwt_internal } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_JWT_HMAC_KEY_MANAGER_H_ ================================================ FILE: cc/jwt/internal/jwt_hmac_key_manager_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/jwt_hmac_key_manager.h" #include #include #include #include #include "google/protobuf/struct.pb.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "absl/time/time.h" #include "absl/types/optional.h" #include "tink/core/key_manager_impl.h" #include "tink/jwt/internal/json_util.h" #include "tink/jwt/internal/jwt_format.h" #include "tink/jwt/internal/jwt_mac_internal.h" #include "tink/jwt/jwt_validator.h" #include "tink/jwt/raw_jwt.h" #include "tink/jwt/verified_jwt.h" #include "tink/mac.h" #include "tink/util/istream_input_stream.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/jwt_hmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::IstreamInputStream; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::JwtHmacAlgorithm; using ::google::crypto::tink::JwtHmacKey; using ::google::crypto::tink::JwtHmacKeyFormat; using ::testing::Eq; using ::testing::Not; using ::testing::SizeIs; namespace { TEST(JwtHmacKeyManagerTest, Basics) { EXPECT_EQ(JwtHmacKeyManager().get_version(), 0); EXPECT_EQ(JwtHmacKeyManager().get_key_type(), "type.googleapis.com/google.crypto.tink.JwtHmacKey"); EXPECT_EQ(JwtHmacKeyManager().key_material_type(), google::crypto::tink::KeyData::SYMMETRIC); } TEST(JwtHmacKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(JwtHmacKeyManager().ValidateKey(JwtHmacKey()), Not(IsOk())); } TEST(JwtHmacKeyManagerTest, ValidateEmptyKeyFormat) { EXPECT_THAT(JwtHmacKeyManager().ValidateKeyFormat(JwtHmacKeyFormat()), Not(IsOk())); } TEST(RawJwtHmacKeyManagerTest, ValidateHS256KeyFormat) { JwtHmacKeyFormat key_format; key_format.set_algorithm(JwtHmacAlgorithm::HS256); key_format.set_key_size(32); EXPECT_THAT(JwtHmacKeyManager().ValidateKeyFormat(key_format), IsOk()); key_format.set_key_size(31); EXPECT_THAT(JwtHmacKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(RawJwtHmacKeyManagerTest, ValidateHS384KeyFormat) { JwtHmacKeyFormat key_format; key_format.set_algorithm(JwtHmacAlgorithm::HS384); key_format.set_key_size(48); EXPECT_THAT(JwtHmacKeyManager().ValidateKeyFormat(key_format), IsOk()); key_format.set_key_size(47); EXPECT_THAT(JwtHmacKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(RawJwtHmacKeyManagerTest, ValidateHS512KeyFormat) { JwtHmacKeyFormat key_format; key_format.set_algorithm(JwtHmacAlgorithm::HS512); key_format.set_key_size(64); EXPECT_THAT(JwtHmacKeyManager().ValidateKeyFormat(key_format), IsOk()); key_format.set_key_size(63); EXPECT_THAT(JwtHmacKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(JwtHmacKeyManagerTest, CreateKey) { JwtHmacKeyFormat key_format; key_format.set_key_size(32); key_format.set_algorithm(JwtHmacAlgorithm::HS256); util::StatusOr key = JwtHmacKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); EXPECT_EQ(key->version(), 0); EXPECT_EQ(key->algorithm(), key_format.algorithm()); EXPECT_THAT(key->key_value(), SizeIs(key_format.key_size())); EXPECT_THAT(JwtHmacKeyManager().ValidateKey(*key), IsOk()); } TEST(JwtHmacKeyManagerTest, ValidateKeyWithUnknownAlgorithm_fails) { JwtHmacKey key; key.set_version(0); key.set_algorithm(JwtHmacAlgorithm::HS_UNKNOWN); key.set_key_value("0123456789abcdef0123456789abcdef"); EXPECT_FALSE(JwtHmacKeyManager().ValidateKey(key).ok()); } TEST(JwtHmacKeyManagerTest, ValidateHS256Key) { JwtHmacKey key; key.set_version(0); key.set_algorithm(JwtHmacAlgorithm::HS256); key.set_key_value("0123456789abcdef0123456789abcdef"); // 32 bytes EXPECT_THAT(JwtHmacKeyManager().ValidateKey(key), IsOk()); key.set_key_value("0123456789abcdef0123456789abcde"); // 31 bytes EXPECT_THAT(JwtHmacKeyManager().ValidateKey(key), Not(IsOk())); } TEST(JwtHmacKeyManagerTest, ValidateHS384Key) { JwtHmacKey key; key.set_version(0); key.set_algorithm(JwtHmacAlgorithm::HS384); key.set_key_value( "0123456789abcdef0123456789abcdef0123456789abcdef"); // 48 bytes EXPECT_THAT(JwtHmacKeyManager().ValidateKey(key), IsOk()); key.set_key_value( "0123456789abcdef0123456789abcdef0123456789abcde"); // 47 bytes EXPECT_THAT(JwtHmacKeyManager().ValidateKey(key), Not(IsOk())); } TEST(JwtHmacKeyManagerTest, ValidateHS512Key) { JwtHmacKey key; key.set_version(0); key.set_algorithm(JwtHmacAlgorithm::HS512); key.set_key_value( // 64 bytes "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"); key.set_key_value( // 63 bytes "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde"); EXPECT_THAT(JwtHmacKeyManager().ValidateKey(key), Not(IsOk())); } TEST(JwtHmacKeyManagerTest, DeriveKeyIsNotImplemented) { JwtHmacKeyFormat format; format.set_version(0); format.set_key_size(32); format.set_algorithm(JwtHmacAlgorithm::HS256); IstreamInputStream input_stream{ absl::make_unique("0123456789abcdefghijklmnop")}; ASSERT_THAT(JwtHmacKeyManager().DeriveKey(format, &input_stream).status(), StatusIs(absl::StatusCode::kUnimplemented)); } TEST(JwtHmacKeyManagerTest, GetAndUsePrimitive) { JwtHmacKeyFormat key_format; key_format.set_key_size(32); key_format.set_algorithm(JwtHmacAlgorithm::HS256); util::StatusOr key = JwtHmacKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); util::StatusOr> jwt_mac = JwtHmacKeyManager().GetPrimitive(*key); ASSERT_THAT(jwt_mac, IsOk()); util::StatusOr raw_jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr compact = (*jwt_mac)->ComputeMacAndEncodeWithKid(*raw_jwt, /*kid=*/absl::nullopt); ASSERT_THAT(compact, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .ExpectIssuer("issuer") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); util::StatusOr verified_jwt = (*jwt_mac)->VerifyMacAndDecodeWithKid(*compact, *validator, /*kid=*/absl::nullopt); ASSERT_THAT(verified_jwt, IsOk()); util::StatusOr issuer = verified_jwt->GetIssuer(); EXPECT_THAT(issuer, IsOkAndHolds("issuer")); } TEST(JwtHmacKeyManagerTest, GetAndUsePrimitiveWithKid) { JwtHmacKeyFormat key_format; key_format.set_key_size(32); key_format.set_algorithm(JwtHmacAlgorithm::HS256); util::StatusOr key = JwtHmacKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); util::StatusOr> jwt_mac = JwtHmacKeyManager().GetPrimitive(*key); ASSERT_THAT(jwt_mac, IsOk()); util::StatusOr raw_jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr token_with_kid = (*jwt_mac)->ComputeMacAndEncodeWithKid(*raw_jwt, /*kid=*/"kid-123"); ASSERT_THAT(token_with_kid, IsOk()); util::StatusOr token_without_kid = (*jwt_mac)->ComputeMacAndEncodeWithKid(*raw_jwt, /*kid=*/absl::nullopt); ASSERT_THAT(token_without_kid, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .ExpectIssuer("issuer") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); // A token with kid only fails if the wrong kid is passed. ASSERT_THAT((*jwt_mac) ->VerifyMacAndDecodeWithKid(*token_with_kid, *validator, /*kid=*/absl::nullopt) .status(), IsOk()); ASSERT_THAT((*jwt_mac) ->VerifyMacAndDecodeWithKid(*token_with_kid, *validator, /*kid=*/"kid-123") .status(), IsOk()); ASSERT_THAT((*jwt_mac) ->VerifyMacAndDecodeWithKid(*token_with_kid, *validator, /*kid=*/"wrong-kid") .status(), Not(IsOk())); // A token without kid is only valid if no kid is passed. ASSERT_THAT((*jwt_mac) ->VerifyMacAndDecodeWithKid(*token_without_kid, *validator, /*kid=*/absl::nullopt) .status(), IsOk()); ASSERT_THAT( (*jwt_mac) ->VerifyMacAndDecodeWithKid(*token_without_kid, *validator, "kid-123") .status(), Not(IsOk())); } TEST(JwtHmacKeyManagerTest, GetAndUsePrimitiveWithCustomKid) { JwtHmacKeyFormat key_format; key_format.set_key_size(32); key_format.set_algorithm(JwtHmacAlgorithm::HS256); util::StatusOr key = JwtHmacKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); key->mutable_custom_kid()->set_value( "Lorem ipsum dolor sit amet, consectetur adipiscing elit"); util::StatusOr> jwt_mac = JwtHmacKeyManager().GetPrimitive(*key); ASSERT_THAT(jwt_mac, IsOk()); util::StatusOr raw_jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr compact = (*jwt_mac)->ComputeMacAndEncodeWithKid(*raw_jwt, /*kid=*/absl::nullopt); ASSERT_THAT(compact, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .ExpectIssuer("issuer") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); // parse header and check "kid" std::vector parts = absl::StrSplit(*compact, '.'); ASSERT_THAT(parts.size(), Eq(3)); std::string json_header; ASSERT_TRUE(DecodeHeader(parts[0], &json_header)); util::StatusOr header = JsonStringToProtoStruct(json_header); ASSERT_THAT(header, IsOk()); auto it = header->fields().find("kid"); ASSERT_FALSE(it == header->fields().end()); EXPECT_THAT(it->second.string_value(), Eq("Lorem ipsum dolor sit amet, consectetur adipiscing elit")); // validate token util::StatusOr verified_jwt = (*jwt_mac)->VerifyMacAndDecodeWithKid(*compact, *validator, /*kid=*/absl::nullopt); ASSERT_THAT(verified_jwt, IsOk()); util::StatusOr issuer = verified_jwt->GetIssuer(); ASSERT_THAT(issuer, IsOk()); EXPECT_THAT(*issuer, testing::Eq("issuer")); // passing a kid when custom_kid is set should fail EXPECT_THAT((*jwt_mac) ->ComputeMacAndEncodeWithKid(*raw_jwt, /*kid=*/"kid123") .status(), Not(IsOk())); } TEST(JwtHmacKeyManagerTest, ValidateTokenWithFixedKey) { JwtHmacKey key; key.set_version(0); key.set_algorithm(JwtHmacAlgorithm::HS256); std::string key_value; ASSERT_TRUE(absl::WebSafeBase64Unescape( "AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1" "qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow", &key_value)); key.set_key_value(key_value); util::StatusOr> jwt_mac = JwtHmacKeyManager().GetPrimitive(key); ASSERT_THAT(jwt_mac, IsOk()); std::string compact = "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleH" "AiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ." "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"; util::StatusOr validator = JwtValidatorBuilder() .ExpectTypeHeader("JWT") .ExpectIssuer("joe") .SetFixedNow(absl::FromUnixSeconds(12345)) .Build(); ASSERT_THAT(validator, IsOk()); util::StatusOr verified_jwt = (*jwt_mac)->VerifyMacAndDecodeWithKid(compact, *validator, /*kid=*/absl::nullopt); ASSERT_THAT(verified_jwt, IsOk()); EXPECT_THAT(verified_jwt->GetIssuer(), IsOkAndHolds("joe")); EXPECT_THAT(verified_jwt->GetBooleanClaim("http://example.com/is_root"), IsOkAndHolds(true)); util::StatusOr validator_now = JwtValidatorBuilder().Build(); ASSERT_THAT(validator_now, IsOk()); EXPECT_THAT((*jwt_mac) ->VerifyMacAndDecodeWithKid(compact, *validator_now, /*kid=*/absl::nullopt) .status(), Not(IsOk())); std::string modified_compact = "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleH" "AiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ." "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXi"; EXPECT_THAT((*jwt_mac) ->VerifyMacAndDecodeWithKid(modified_compact, *validator, /*kid=*/absl::nullopt) .status(), Not(IsOk())); } } // namespace } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_mac_impl.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/jwt_mac_impl.h" #include #include #include #include #include "google/protobuf/struct.pb.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/jwt/internal/json_util.h" #include "tink/jwt/internal/jwt_format.h" #include "tink/jwt/jwt_validator.h" #include "tink/jwt/raw_jwt.h" #include "tink/jwt/verified_jwt.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace jwt_internal { util::StatusOr JwtMacImpl::ComputeMacAndEncodeWithKid( const RawJwt& token, absl::optional kid) const { absl::optional type_header; if (token.HasTypeHeader()) { util::StatusOr type = token.GetTypeHeader(); if (!type.ok()) { return type.status(); } type_header = *type; } if (custom_kid_.has_value()) { if (kid.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "TINK keys are not allowed to have a kid value set."); } kid = *custom_kid_; } util::StatusOr encoded_header = CreateHeader(algorithm_, type_header, kid); if (!encoded_header.ok()) { return encoded_header.status(); } util::StatusOr payload = token.GetJsonPayload(); if (!payload.ok()) { return payload.status(); } std::string encoded_payload = EncodePayload(*payload); std::string unsigned_token = absl::StrCat(*encoded_header, ".", encoded_payload); util::StatusOr tag = mac_->ComputeMac(unsigned_token); if (!tag.ok()) { return tag.status(); } std::string encoded_tag = EncodeSignature(*tag); return absl::StrCat(unsigned_token, ".", encoded_tag); } util::StatusOr JwtMacImpl::VerifyMacAndDecodeWithKid( absl::string_view compact, const JwtValidator& validator, absl::optional kid) const { std::size_t mac_pos = compact.find_last_of('.'); if (mac_pos == absl::string_view::npos) { return util::Status(absl::StatusCode::kInvalidArgument, "invalid token"); } absl::string_view unsigned_token = compact.substr(0, mac_pos); std::string mac_value; if (!DecodeSignature(compact.substr(mac_pos + 1), &mac_value)) { return util::Status(absl::StatusCode::kInvalidArgument, "invalid JWT MAC"); } util::Status verify_result = mac_->VerifyMac(mac_value, unsigned_token); if (!verify_result.ok()) { // Use a different error code so that we can distinguish it. return util::Status(absl::StatusCode::kUnauthenticated, verify_result.message()); } std::vector parts = absl::StrSplit(unsigned_token, '.'); if (parts.size() != 2) { return util::Status( absl::StatusCode::kInvalidArgument, "only tokens in JWS compact serialization format are supported"); } std::string json_header; if (!DecodeHeader(parts[0], &json_header)) { return util::Status(absl::StatusCode::kInvalidArgument, "invalid header"); } util::StatusOr header = JsonStringToProtoStruct(json_header); if (!header.ok()) { return header.status(); } util::Status validate_header_result = ValidateHeader(*header, algorithm_, kid, custom_kid_); if (!validate_header_result.ok()) { return validate_header_result; } std::string json_payload; if (!DecodePayload(parts[1], &json_payload)) { return util::Status(absl::StatusCode::kInvalidArgument, "invalid JWT payload"); } util::StatusOr raw_jwt = RawJwtParser::FromJson(GetTypeHeader(*header), json_payload); if (!raw_jwt.ok()) { return raw_jwt.status(); } util::Status validate_result = validator.Validate(*raw_jwt); if (!validate_result.ok()) { return validate_result; } return VerifiedJwt(*std::move(raw_jwt)); } } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_mac_impl.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_JWT_MAC_IMPL_H_ #define TINK_JWT_INTERNAL_JWT_MAC_IMPL_H_ #include #include #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/jwt/internal/jwt_mac_internal.h" #include "tink/jwt/jwt_mac.h" #include "tink/jwt/jwt_validator.h" #include "tink/jwt/raw_jwt.h" #include "tink/jwt/verified_jwt.h" #include "tink/mac.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace jwt_internal { class JwtMacImpl : public JwtMacInternal { public: explicit JwtMacImpl(std::unique_ptr mac, absl::string_view algorithm, absl::optional custom_kid) { mac_ = std::move(mac); algorithm_ = std::string(algorithm); if (custom_kid.has_value()) { custom_kid_ = std::string(*custom_kid); } } crypto::tink::util::StatusOr ComputeMacAndEncodeWithKid( const crypto::tink::RawJwt& token, absl::optional kid) const override; crypto::tink::util::StatusOr VerifyMacAndDecodeWithKid( absl::string_view compact, const crypto::tink::JwtValidator& validator, absl::optional kid) const override; private: std::unique_ptr mac_; std::string algorithm_; absl::optional custom_kid_; }; } // namespace jwt_internal } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_JWT_MAC_IMPL_H_ ================================================ FILE: cc/jwt/internal/jwt_mac_impl_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/jwt_mac_impl.h" #include #include #include #include #include "google/protobuf/struct.pb.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "absl/time/clock.h" #include "absl/time/time.h" #include "absl/types/optional.h" #include "tink/jwt/internal/json_util.h" #include "tink/jwt/internal/jwt_format.h" #include "tink/jwt/internal/jwt_mac_internal.h" #include "tink/jwt/jwt_mac.h" #include "tink/jwt/jwt_validator.h" #include "tink/jwt/raw_jwt.h" #include "tink/jwt/verified_jwt.h" #include "tink/mac.h" #include "tink/subtle/hmac_boringssl.h" #include "tink/util/constants.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/common.pb.h" using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::testing::Eq; using ::testing::Not; namespace crypto { namespace tink { namespace jwt_internal { namespace { util::StatusOr> CreateJwtMac() { std::string key_value; if (!absl::WebSafeBase64Unescape( "AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1" "qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow", &key_value)) { return util::Status(absl::StatusCode::kInvalidArgument, "failed to parse key"); } crypto::tink::util::StatusOr> mac = subtle::HmacBoringSsl::New( util::Enums::ProtoToSubtle(google::crypto::tink::HashType::SHA256), 32, util::SecretDataFromStringView(key_value)); if (!mac.ok()) { return mac.status(); } std::unique_ptr jwt_mac = absl::make_unique( *std::move(mac), "HS256", /*kid=*/absl::nullopt); return std::move(jwt_mac); } TEST(JwtMacImplTest, CreateAndValidateToken) { util::StatusOr> jwt_mac = CreateJwtMac(); ASSERT_THAT(jwt_mac, IsOk()); absl::Time now = absl::Now(); util::StatusOr raw_jwt = RawJwtBuilder() .SetTypeHeader("typeHeader") .SetJwtId("id123") .SetNotBefore(now - absl::Seconds(300)) .SetIssuedAt(now) .SetExpiration(now + absl::Seconds(300)) .Build(); ASSERT_THAT(raw_jwt, IsOk()); EXPECT_TRUE(raw_jwt->HasTypeHeader()); EXPECT_THAT(raw_jwt->GetTypeHeader(), IsOkAndHolds("typeHeader")); util::StatusOr compact = (*jwt_mac)->ComputeMacAndEncodeWithKid(*raw_jwt, /*kid=*/absl::nullopt); ASSERT_THAT(compact, IsOk()); util::StatusOr validator = JwtValidatorBuilder().ExpectTypeHeader("typeHeader").Build(); ASSERT_THAT(validator, IsOk()); util::StatusOr verified_jwt = (*jwt_mac)->VerifyMacAndDecodeWithKid(*compact, *validator, /*kid=*/absl::nullopt); ASSERT_THAT(verified_jwt, IsOk()); EXPECT_THAT(verified_jwt->GetTypeHeader(), IsOkAndHolds("typeHeader")); EXPECT_THAT(verified_jwt->GetJwtId(), IsOkAndHolds("id123")); util::StatusOr validator2 = JwtValidatorBuilder().ExpectIssuer("unknown").Build(); ASSERT_THAT(validator2, IsOk()); EXPECT_FALSE((*jwt_mac) ->VerifyMacAndDecodeWithKid(*compact, *validator2, /*kid=*/absl::nullopt) .ok()); } TEST(JwtMacImplTest, CreateAndValidateTokenWithKid) { util::StatusOr> jwt_mac = CreateJwtMac(); ASSERT_THAT(jwt_mac, IsOk()); absl::Time now = absl::Now(); util::StatusOr raw_jwt = RawJwtBuilder() .SetTypeHeader("typeHeader") .SetJwtId("id123") .SetNotBefore(now - absl::Seconds(300)) .SetIssuedAt(now) .SetExpiration(now + absl::Seconds(300)) .Build(); ASSERT_THAT(raw_jwt, IsOk()); EXPECT_TRUE(raw_jwt->HasTypeHeader()); EXPECT_THAT(raw_jwt->GetTypeHeader(), IsOkAndHolds("typeHeader")); util::StatusOr compact = (*jwt_mac)->ComputeMacAndEncodeWithKid(*raw_jwt, "kid-123"); ASSERT_THAT(compact, IsOk()); util::StatusOr validator = JwtValidatorBuilder().ExpectTypeHeader("typeHeader").Build(); ASSERT_THAT(validator, IsOk()); util::StatusOr verified_jwt = (*jwt_mac)->VerifyMacAndDecodeWithKid(*compact, *validator, /*kid=*/"kid-123"); ASSERT_THAT(verified_jwt, IsOk()); EXPECT_THAT(verified_jwt->GetTypeHeader(), IsOkAndHolds("typeHeader")); EXPECT_THAT(verified_jwt->GetJwtId(), IsOkAndHolds("id123")); // with kid=absl::nullopt, the kid header in the token is ignored. EXPECT_THAT((*jwt_mac) ->VerifyMacAndDecodeWithKid(*compact, *validator, /*kid=*/absl::nullopt) .status(), IsOk()); // with a different kid, the verification fails. EXPECT_THAT((*jwt_mac) ->VerifyMacAndDecodeWithKid(*compact, *validator, /*kid=*/"other-kid") .status(), Not(IsOk())); // parse header to make sure the kid value is set correctly. std::vector parts = absl::StrSplit(*compact, '.'); ASSERT_THAT(parts.size(), Eq(3)); std::string json_header; ASSERT_TRUE(DecodeHeader(parts[0], &json_header)); util::StatusOr header = JsonStringToProtoStruct(json_header); ASSERT_THAT(header, IsOk()); EXPECT_THAT(header->fields().find("kid")->second.string_value(), Eq("kid-123")); } TEST(JwtMacImplTest, ValidateFixedToken) { util::StatusOr> jwt_mac = CreateJwtMac(); ASSERT_THAT(jwt_mac, IsOk()); // token that expired in 2011 std::string compact = "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleH" "AiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ." "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"; util::StatusOr validator_1970 = JwtValidatorBuilder() .ExpectTypeHeader("JWT") .ExpectIssuer("joe") .SetFixedNow(absl::FromUnixSeconds(12345)) .Build(); ASSERT_THAT(validator_1970, IsOk()); // verification succeeds because token was valid 1970 util::StatusOr verified_jwt = (*jwt_mac)->VerifyMacAndDecodeWithKid(compact, *validator_1970, /*kid=*/absl::nullopt); ASSERT_THAT(verified_jwt, IsOk()); EXPECT_THAT(verified_jwt->GetIssuer(), IsOkAndHolds("joe")); EXPECT_THAT(verified_jwt->GetBooleanClaim("http://example.com/is_root"), IsOkAndHolds(true)); // verification fails because token is expired util::StatusOr validator_now = JwtValidatorBuilder().Build(); ASSERT_THAT(validator_now, IsOk()); EXPECT_FALSE((*jwt_mac) ->VerifyMacAndDecodeWithKid(compact, *validator_now, /*kid=*/absl::nullopt) .ok()); // verification fails because token was modified std::string modified_compact = "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleH" "AiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ." "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXi"; EXPECT_FALSE((*jwt_mac) ->VerifyMacAndDecodeWithKid( modified_compact, *validator_1970, /*kid=*/absl::nullopt) .ok()); } TEST(JwtMacImplTest, ValidateInvalidTokens) { util::StatusOr> jwt_mac = CreateJwtMac(); ASSERT_THAT(jwt_mac, IsOk()); util::StatusOr validator = JwtValidatorBuilder().Build(); ASSERT_THAT(validator, IsOk()); EXPECT_FALSE((*jwt_mac) ->VerifyMacAndDecodeWithKid("eyJhbGciOiJIUzI1NiJ9.e30.abc.", *validator, /*kid=*/absl::nullopt) .ok()); EXPECT_FALSE((*jwt_mac) ->VerifyMacAndDecodeWithKid("eyJhbGciOiJIUzI1NiJ9?.e30.abc", *validator, /*kid=*/absl::nullopt) .ok()); EXPECT_FALSE((*jwt_mac) ->VerifyMacAndDecodeWithKid("eyJhbGciOiJIUzI1NiJ9.e30?.abc", *validator, /*kid=*/absl::nullopt) .ok()); EXPECT_FALSE((*jwt_mac) ->VerifyMacAndDecodeWithKid("eyJhbGciOiJIUzI1NiJ9.e30.abc?", *validator, /*kid=*/absl::nullopt) .ok()); EXPECT_FALSE((*jwt_mac) ->VerifyMacAndDecodeWithKid("eyJhbGciOiJIUzI1NiJ9.e30", *validator, /*kid=*/absl::nullopt) .ok()); } } // namespace } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_mac_internal.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_JWT_MAC_INTERNAL_H_ #define TINK_JWT_INTERNAL_JWT_MAC_INTERNAL_H_ #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/jwt/jwt_validator.h" #include "tink/jwt/raw_jwt.h" #include "tink/jwt/verified_jwt.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace jwt_internal { /////////////////////////////////////////////////////////////////////////////// // Internal Interface for authenticating and verifying JWT with JWS MAC. // // Sees RFC 7519 and RFC 7515. Security guarantees: similar to MAC. class JwtMacInternal { public: // Computes a MAC and encodes the raw JWT token and the MAC in the JWS compact // serialization format. // // When the `kid` parameter has a value, the token will have a kid header. virtual crypto::tink::util::StatusOr ComputeMacAndEncodeWithKid( const RawJwt& token, absl::optional kid) const = 0; // Verifies and decodes a JWT token in the JWS compact serialization format. // // The JWT is validated against the rules in `validator`. That is, every claim // in validator must also be present in the JWT. For example, if validator // contains an issuer (iss) claim, the JWT must contain an identical claim. // The JWT can contain claims that are NOT in the validator. However, if the // JWT contains a list of audiences, the validator must also contain an // audience in the list. // // If the JWT contains timestamp claims such as expiration (exp), issued_at // (iat) or not_before (nbf), they will also be validated. validator allows to // set a clock skew, to deal with small clock differences among different // machines. // // When the `kid` parameter has a value, then only token with the correct kid // header are valid. When the `kid` parameter does not have a value the kid // header in the token is ignored. The `kid` parameter is set by the primitive // wrapper based on the output prefix type and the key id. virtual crypto::tink::util::StatusOr VerifyMacAndDecodeWithKid( absl::string_view compact, const JwtValidator& validator, absl::optional kid) const = 0; virtual ~JwtMacInternal() = default; }; } // namespace jwt_internal } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_JWT_MAC_INTERNAL_H_ ================================================ FILE: cc/jwt/internal/jwt_mac_wrapper.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/jwt_mac_wrapper.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/jwt/internal/jwt_format.h" #include "tink/jwt/internal/jwt_mac_internal.h" #include "tink/jwt/jwt_mac.h" #include "tink/jwt/jwt_validator.h" #include "tink/jwt/raw_jwt.h" #include "tink/jwt/verified_jwt.h" #include "tink/primitive_set.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { using ::google::crypto::tink::OutputPrefixType; namespace { class JwtMacSetWrapper : public JwtMac { public: explicit JwtMacSetWrapper( std::unique_ptr> jwt_mac_set) : jwt_mac_set_(std::move(jwt_mac_set)) {} crypto::tink::util::StatusOr ComputeMacAndEncode( const crypto::tink::RawJwt& token) const override; crypto::tink::util::StatusOr VerifyMacAndDecode( absl::string_view compact, const crypto::tink::JwtValidator& validator) const override; ~JwtMacSetWrapper() override = default; private: std::unique_ptr> jwt_mac_set_; }; util::Status Validate(PrimitiveSet* jwt_mac_set) { if (jwt_mac_set == nullptr) { return util::Status(absl::StatusCode::kInternal, "jwt_mac_set must be non-NULL"); } if (jwt_mac_set->get_primary() == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "jwt_mac_set has no primary"); } for (const auto* entry : jwt_mac_set->get_all()) { if ((entry->get_output_prefix_type() != OutputPrefixType::RAW) && (entry->get_output_prefix_type() != OutputPrefixType::TINK)) { return util::Status(absl::StatusCode::kInvalidArgument, "all JWT keys must be either RAW or TINK"); } } return util::OkStatus(); } util::StatusOr JwtMacSetWrapper::ComputeMacAndEncode( const crypto::tink::RawJwt& token) const { auto primary = jwt_mac_set_->get_primary(); absl::optional kid = GetKid(primary->get_key_id(), primary->get_output_prefix_type()); return primary->get_primitive().ComputeMacAndEncodeWithKid(token, kid); } util::StatusOr JwtMacSetWrapper::VerifyMacAndDecode( absl::string_view compact, const crypto::tink::JwtValidator& validator) const { absl::optional interesting_status; for (const auto* mac_entry : jwt_mac_set_->get_all()) { JwtMacInternal& jwt_mac = mac_entry->get_primitive(); absl::optional kid = GetKid(mac_entry->get_key_id(), mac_entry->get_output_prefix_type()); util::StatusOr verified_jwt = jwt_mac.VerifyMacAndDecodeWithKid(compact, validator, kid); if (verified_jwt.ok()) { return verified_jwt; } else if (verified_jwt.status().code() != absl::StatusCode::kUnauthenticated) { // errors that are not the result of a MAC verification interesting_status = verified_jwt.status(); } } if (interesting_status.has_value()) { return *interesting_status; } return util::Status(absl::StatusCode::kInvalidArgument, "verification failed"); } } // namespace util::StatusOr> JwtMacWrapper::Wrap( std::unique_ptr> jwt_mac_set) const { util::Status status = Validate(jwt_mac_set.get()); if (!status.ok()) return status; std::unique_ptr jwt_mac = absl::make_unique(std::move(jwt_mac_set)); return std::move(jwt_mac); } } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_mac_wrapper.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_JWT_MAC_WRAPPER_H_ #define TINK_JWT_INTERNAL_JWT_MAC_WRAPPER_H_ #include #include "tink/jwt/internal/jwt_mac_internal.h" #include "tink/jwt/jwt_mac.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace jwt_internal { // Wraps a set of JwtMac-instances that correspond to a keyset, // and combines them into a single JwtMac-primitive, that uses the provided // instances, depending on the context: // * JwtMac::ComputeMacAndEncode(...) uses the primary instance from the set // * JwtMac::VerifyMacAndDecode(...) uses all instance from the set // only keys with RAW output prefix are supported. class JwtMacWrapper : public PrimitiveWrapper { public: util::StatusOr> Wrap( std::unique_ptr> jwt_mac_set) const override; }; } // namespace jwt_internal } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_JWT_MAC_WRAPPER_H_ ================================================ FILE: cc/jwt/internal/jwt_mac_wrapper_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/jwt_mac_wrapper.h" #include #include #include #include #include #include "google/protobuf/struct.pb.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "tink/cleartext_keyset_handle.h" #include "tink/config/global_registry.h" #include "tink/jwt/internal/json_util.h" #include "tink/jwt/internal/jwt_format.h" #include "tink/jwt/internal/jwt_hmac_key_manager.h" #include "tink/jwt/internal/jwt_mac_internal.h" #include "tink/jwt/jwt_mac.h" #include "tink/jwt/jwt_validator.h" #include "tink/jwt/raw_jwt.h" #include "tink/jwt/verified_jwt.h" #include "tink/keyset_manager.h" #include "tink/primitive_set.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/jwt_hmac.pb.h" #include "proto/tink.pb.h" using google::crypto::tink::JwtHmacAlgorithm; using google::crypto::tink::JwtHmacKeyFormat; using google::crypto::tink::KeyTemplate; using google::crypto::tink::OutputPrefixType; namespace crypto { namespace tink { namespace jwt_internal { namespace { using ::crypto::tink::CleartextKeysetHandle; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::google::crypto::tink::Keyset; using ::testing::Eq; using ::testing::Not; KeyTemplate createTemplate(OutputPrefixType output_prefix) { KeyTemplate key_template; key_template.set_type_url( "type.googleapis.com/google.crypto.tink.JwtHmacKey"); key_template.set_output_prefix_type(output_prefix); JwtHmacKeyFormat key_format; key_format.set_key_size(32); key_format.set_algorithm(JwtHmacAlgorithm::HS256); key_format.SerializeToString(key_template.mutable_value()); return key_template; } std::unique_ptr KeysetHandleWithNewKeyId( const KeysetHandle& keyset_handle) { Keyset keyset(CleartextKeysetHandle::GetKeyset(keyset_handle)); uint32_t new_key_id = keyset.mutable_key(0)->key_id() ^ 0xdeadbeef; keyset.mutable_key(0)->set_key_id(new_key_id); keyset.set_primary_key_id(new_key_id); return CleartextKeysetHandle::GetKeysetHandle(keyset); } std::unique_ptr KeysetHandleWithTinkPrefix( const KeysetHandle& keyset_handle) { Keyset keyset(CleartextKeysetHandle::GetKeyset(keyset_handle)); keyset.mutable_key(0)->set_output_prefix_type(OutputPrefixType::TINK); return CleartextKeysetHandle::GetKeysetHandle(keyset); } class JwtMacWrapperTest : public ::testing::Test { protected: void SetUp() override { ASSERT_THAT( Registry::RegisterPrimitiveWrapper(absl::make_unique()), IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); } }; TEST_F(JwtMacWrapperTest, WrapNullptr) { util::StatusOr> mac_result = JwtMacWrapper().Wrap(nullptr); EXPECT_FALSE(mac_result.ok()); } TEST_F(JwtMacWrapperTest, WrapEmpty) { auto jwt_mac_set = absl::make_unique>(); util::StatusOr> jwt_mac_result = JwtMacWrapper().Wrap(std::move(jwt_mac_set)); EXPECT_FALSE(jwt_mac_result.ok()); } TEST_F(JwtMacWrapperTest, CannotWrapPrimitivesFromNonRawOrTinkKeys) { KeyTemplate tink_key_template = createTemplate(OutputPrefixType::LEGACY); util::StatusOr> keyset_handle = KeysetHandle::GenerateNew(tink_key_template, KeyGenConfigGlobalRegistry()); EXPECT_THAT(keyset_handle, IsOk()); EXPECT_FALSE((*keyset_handle) ->GetPrimitive(ConfigGlobalRegistry()) .status() .ok()); } TEST_F(JwtMacWrapperTest, GenerateRawComputeVerifySuccess) { KeyTemplate key_template = createTemplate(OutputPrefixType::RAW); util::StatusOr> keyset_handle = KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()); EXPECT_THAT(keyset_handle, IsOk()); util::StatusOr> jwt_mac = (*keyset_handle) ->GetPrimitive(ConfigGlobalRegistry()); EXPECT_THAT(jwt_mac, IsOk()); util::StatusOr raw_jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr compact = (*jwt_mac)->ComputeMacAndEncode(*raw_jwt); ASSERT_THAT(compact, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .ExpectIssuer("issuer") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); util::StatusOr verified_jwt = (*jwt_mac)->VerifyMacAndDecode(*compact, *validator); ASSERT_THAT(verified_jwt, IsOk()); EXPECT_THAT(verified_jwt->GetIssuer(), IsOkAndHolds("issuer")); util::StatusOr validator2 = JwtValidatorBuilder() .ExpectIssuer("unknown") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator2, IsOk()); util::StatusOr verified_jwt2 = (*jwt_mac)->VerifyMacAndDecode(*compact, *validator2); EXPECT_FALSE(verified_jwt2.ok()); // Make sure the error message is interesting EXPECT_THAT(verified_jwt2.status().message(), Eq("wrong issuer")); // Raw primitives don't add a kid header, Tink primitives require a kid // header to be set. Thefore, changing the output prefix to TINK makes the // validation fail. std::unique_ptr tink_keyset_handle = KeysetHandleWithTinkPrefix(**keyset_handle); util::StatusOr> tink_jwt_mac = tink_keyset_handle->GetPrimitive( ConfigGlobalRegistry()); ASSERT_THAT(tink_jwt_mac, IsOk()); EXPECT_THAT( (*tink_jwt_mac)->VerifyMacAndDecode(*compact, *validator).status(), Not(IsOk())); } TEST_F(JwtMacWrapperTest, GenerateTinkComputeVerifySuccess) { KeyTemplate key_template = createTemplate(OutputPrefixType::TINK); util::StatusOr> keyset_handle = KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()); EXPECT_THAT(keyset_handle, IsOk()); util::StatusOr> jwt_mac = (*keyset_handle) ->GetPrimitive(ConfigGlobalRegistry()); EXPECT_THAT(jwt_mac, IsOk()); util::StatusOr raw_jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr compact = (*jwt_mac)->ComputeMacAndEncode(*raw_jwt); ASSERT_THAT(compact, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .ExpectIssuer("issuer") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); util::StatusOr verified_jwt = (*jwt_mac)->VerifyMacAndDecode(*compact, *validator); ASSERT_THAT(verified_jwt, IsOk()); EXPECT_THAT(verified_jwt->GetIssuer(), test::IsOkAndHolds("issuer")); // Parse header to make sure that key ID is correctly encoded. google::crypto::tink::KeysetInfo keyset_info = (*keyset_handle)->GetKeysetInfo(); uint32_t key_id = keyset_info.key_info(0).key_id(); std::vector parts = absl::StrSplit(*compact, '.'); ASSERT_THAT(parts.size(), Eq(3)); std::string json_header; ASSERT_TRUE(DecodeHeader(parts[0], &json_header)); util::StatusOr header = JsonStringToProtoStruct(json_header); ASSERT_THAT(header, IsOk()); EXPECT_THAT(GetKeyId((*header).fields().find("kid")->second.string_value()), key_id); // For Tink primitives, the kid must be correctly set and is verified. // Therefore, changing the key_id makes the validation fail. std::unique_ptr keyset_handle_with_new_key_id = KeysetHandleWithNewKeyId(**keyset_handle); util::StatusOr> jwt_mac_with_new_key_id = keyset_handle_with_new_key_id->GetPrimitive( ConfigGlobalRegistry()); ASSERT_THAT(jwt_mac_with_new_key_id, IsOk()); util::StatusOr verified_jwt_2 = (*jwt_mac_with_new_key_id)->VerifyMacAndDecode(*compact, *validator); EXPECT_FALSE(verified_jwt_2.ok()); } TEST_F(JwtMacWrapperTest, KeyRotation) { std::vector prefixes = {OutputPrefixType::RAW, OutputPrefixType::TINK}; for (OutputPrefixType prefix : prefixes) { SCOPED_TRACE(absl::StrCat("Testing with prefix ", prefix)); KeyTemplate key_template = createTemplate(prefix); KeysetManager manager; util::StatusOr old_id = manager.Add(key_template); ASSERT_THAT(old_id, IsOk()); ASSERT_THAT(manager.SetPrimary(*old_id), IsOk()); std::unique_ptr handle1 = manager.GetKeysetHandle(); util::StatusOr> jwt_mac1 = handle1->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(jwt_mac1, IsOk()); util::StatusOr new_id = manager.Add(key_template); ASSERT_THAT(new_id, IsOk()); std::unique_ptr handle2 = manager.GetKeysetHandle(); util::StatusOr> jwt_mac2 = handle2->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(jwt_mac2, IsOk()); ASSERT_THAT(manager.SetPrimary(*new_id), IsOk()); std::unique_ptr handle3 = manager.GetKeysetHandle(); util::StatusOr> jwt_mac3 = handle3->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(jwt_mac3, IsOk()); ASSERT_THAT(manager.Disable(*old_id), IsOk()); std::unique_ptr handle4 = manager.GetKeysetHandle(); util::StatusOr> jwt_mac4 = handle4->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(jwt_mac4, IsOk()); util::StatusOr raw_jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .ExpectIssuer("issuer") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); util::StatusOr compact1 = (*jwt_mac1)->ComputeMacAndEncode(*raw_jwt); ASSERT_THAT(compact1, IsOk()); util::StatusOr compact2 = (*jwt_mac2)->ComputeMacAndEncode(*raw_jwt); ASSERT_THAT(compact2, IsOk()); util::StatusOr compact3 = (*jwt_mac3)->ComputeMacAndEncode(*raw_jwt); ASSERT_THAT(compact3, IsOk()); util::StatusOr compact4 = (*jwt_mac4)->ComputeMacAndEncode(*raw_jwt); ASSERT_THAT(compact4, IsOk()); EXPECT_THAT((*jwt_mac1)->VerifyMacAndDecode(*compact1, *validator).status(), IsOk()); EXPECT_THAT((*jwt_mac2)->VerifyMacAndDecode(*compact1, *validator).status(), IsOk()); EXPECT_THAT((*jwt_mac3)->VerifyMacAndDecode(*compact1, *validator).status(), IsOk()); EXPECT_FALSE((*jwt_mac4)->VerifyMacAndDecode(*compact1, *validator).ok()); EXPECT_THAT((*jwt_mac1)->VerifyMacAndDecode(*compact2, *validator).status(), IsOk()); EXPECT_THAT((*jwt_mac2)->VerifyMacAndDecode(*compact2, *validator).status(), IsOk()); EXPECT_THAT((*jwt_mac3)->VerifyMacAndDecode(*compact2, *validator).status(), IsOk()); EXPECT_FALSE((*jwt_mac4)->VerifyMacAndDecode(*compact2, *validator).ok()); EXPECT_FALSE((*jwt_mac1)->VerifyMacAndDecode(*compact3, *validator).ok()); EXPECT_THAT((*jwt_mac2)->VerifyMacAndDecode(*compact3, *validator).status(), IsOk()); EXPECT_THAT((*jwt_mac3)->VerifyMacAndDecode(*compact3, *validator).status(), IsOk()); EXPECT_THAT((*jwt_mac4)->VerifyMacAndDecode(*compact3, *validator).status(), IsOk()); EXPECT_FALSE((*jwt_mac1)->VerifyMacAndDecode(*compact4, *validator).ok()); EXPECT_THAT((*jwt_mac2)->VerifyMacAndDecode(*compact4, *validator).status(), IsOk()); EXPECT_THAT((*jwt_mac3)->VerifyMacAndDecode(*compact4, *validator).status(), IsOk()); EXPECT_THAT((*jwt_mac4)->VerifyMacAndDecode(*compact4, *validator).status(), IsOk()); } } } // namespace } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_public_key_sign_impl.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/jwt_public_key_sign_impl.h" #include #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/jwt/internal/jwt_format.h" #include "tink/jwt/raw_jwt.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace jwt_internal { util::StatusOr JwtPublicKeySignImpl::SignAndEncodeWithKid( const RawJwt& token, absl::optional kid) const { absl::optional type_header; if (token.HasTypeHeader()) { util::StatusOr type = token.GetTypeHeader(); if (!type.ok()) { return type.status(); } type_header = *type; } if (custom_kid_.has_value()) { if (kid.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "TINK keys are not allowed to have a kid value set."); } kid = *custom_kid_; } util::StatusOr encoded_header = CreateHeader(algorithm_, type_header, kid); if (!encoded_header.ok()) { return encoded_header.status(); } util::StatusOr payload = token.GetJsonPayload(); if (!payload.ok()) { return payload.status(); } std::string encoded_payload = EncodePayload(*payload); std::string unsigned_token = absl::StrCat(*encoded_header, ".", encoded_payload); util::StatusOr tag = sign_->Sign(unsigned_token); if (!tag.ok()) { return tag.status(); } std::string encoded_tag = EncodeSignature(*tag); return absl::StrCat(unsigned_token, ".", encoded_tag); } } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_public_key_sign_impl.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_JWT_PUBLIC_KEY_SIGN_IMPL_H_ #define TINK_JWT_INTERNAL_JWT_PUBLIC_KEY_SIGN_IMPL_H_ #include #include #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/jwt/internal/jwt_public_key_sign_internal.h" #include "tink/jwt/raw_jwt.h" #include "tink/public_key_sign.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace jwt_internal { class JwtPublicKeySignImpl : public JwtPublicKeySignInternal { public: explicit JwtPublicKeySignImpl( std::unique_ptr sign, absl::string_view algorithm, absl::optional custom_kid) { sign_ = std::move(sign); algorithm_ = std::string(algorithm); if (custom_kid.has_value()) { custom_kid_ = std::string(*custom_kid); } } crypto::tink::util::StatusOr SignAndEncodeWithKid( const crypto::tink::RawJwt& token, absl::optional kid) const override; private: std::unique_ptr sign_; std::string algorithm_; // custom_kid may be set when a key is converted from another format, for // example JWK. It does not have any relation to the key id. It can only be // set for keys with output prefix RAW. absl::optional custom_kid_; }; } // namespace jwt_internal } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_JWT_PUBLIC_KEY_SIGN_IMPL_H_ ================================================ FILE: cc/jwt/internal/jwt_public_key_sign_internal.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_JWT_PUBLIC_KEY_SIGN_INTERNAL_H_ #define TINK_JWT_INTERNAL_JWT_PUBLIC_KEY_SIGN_INTERNAL_H_ #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/jwt/raw_jwt.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Internal interface for signing JWT. // // Sees RFC 7519 and RFC 7515. Security guarantees: similar to PublicKeySign. class JwtPublicKeySignInternal { public: // Computes a signature, and encodes the JWT and the signature in the JWS // compact serialization format. // // When `kid` has a value, the token will have a kid header. `kid` is set by // the primitive wrapper based on the output prefix type and the key id. virtual crypto::tink::util::StatusOr SignAndEncodeWithKid( const RawJwt& token, absl::optional kid) const = 0; virtual ~JwtPublicKeySignInternal() = default; }; } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_JWT_PUBLIC_KEY_SIGN_INTERNAL_H_ ================================================ FILE: cc/jwt/internal/jwt_public_key_sign_verify_impl_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include "google/protobuf/struct.pb.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "absl/time/clock.h" #include "absl/time/time.h" #include "absl/types/optional.h" #include "tink/internal/ec_util.h" #include "tink/jwt/internal/json_util.h" #include "tink/jwt/internal/jwt_format.h" #include "tink/jwt/internal/jwt_public_key_sign_impl.h" #include "tink/jwt/internal/jwt_public_key_verify_impl.h" #include "tink/jwt/jwt_public_key_sign.h" #include "tink/jwt/jwt_public_key_verify.h" #include "tink/jwt/jwt_validator.h" #include "tink/jwt/raw_jwt.h" #include "tink/jwt/verified_jwt.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/ecdsa_sign_boringssl.h" #include "tink/subtle/ecdsa_verify_boringssl.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::testing::Eq; using ::testing::Not; namespace crypto { namespace tink { namespace jwt_internal { namespace { class JwtSignatureImplTest : public ::testing::Test { protected: void SetUp() override { util::StatusOr ec_key = internal::NewEcKey(subtle::EllipticCurveType::NIST_P256); ASSERT_THAT(ec_key, IsOk()); util::StatusOr> sign = subtle::EcdsaSignBoringSsl::New( *ec_key, subtle::HashType::SHA256, subtle::EcdsaSignatureEncoding::IEEE_P1363); ASSERT_THAT(sign, IsOk()); util::StatusOr> verify = subtle::EcdsaVerifyBoringSsl::New( *ec_key, subtle::HashType::SHA256, subtle::EcdsaSignatureEncoding::IEEE_P1363); ASSERT_THAT(verify, IsOk()); jwt_sign_ = absl::make_unique( *std::move(sign), "ES256", /*custom_kid=*/absl::nullopt); jwt_verify_ = absl::make_unique( *std::move(verify), "ES256", /*custom_kid=*/absl::nullopt); } std::unique_ptr jwt_sign_; std::unique_ptr jwt_verify_; }; TEST_F(JwtSignatureImplTest, CreateAndValidateToken) { absl::Time now = absl::Now(); util::StatusOr raw_jwt_or = RawJwtBuilder() .SetTypeHeader("typeHeader") .SetJwtId("id123") .SetNotBefore(now - absl::Seconds(300)) .SetIssuedAt(now) .SetExpiration(now + absl::Seconds(300)) .Build(); ASSERT_THAT(raw_jwt_or, IsOk()); RawJwt raw_jwt = raw_jwt_or.value(); util::StatusOr compact = jwt_sign_->SignAndEncodeWithKid(raw_jwt, /*kid=*/absl::nullopt); ASSERT_THAT(compact, IsOk()); util::StatusOr validator = JwtValidatorBuilder().ExpectTypeHeader("typeHeader").Build(); ASSERT_THAT(validator, IsOk()); // Success util::StatusOr verified_jwt = jwt_verify_->VerifyAndDecodeWithKid(*compact, *validator, /*kid=*/absl::nullopt); ASSERT_THAT(verified_jwt, IsOk()); EXPECT_THAT(verified_jwt->GetTypeHeader(), IsOkAndHolds("typeHeader")); EXPECT_THAT(verified_jwt->GetJwtId(), IsOkAndHolds("id123")); // Fails because kid header is not present EXPECT_THAT( jwt_verify_->VerifyAndDecodeWithKid(*compact, *validator, "kid-123") .status(), Not(IsOk())); // Fails with wrong issuer util::StatusOr validator2 = JwtValidatorBuilder().ExpectIssuer("unknown").Build(); ASSERT_THAT(validator2, IsOk()); EXPECT_FALSE( jwt_verify_ ->VerifyAndDecodeWithKid(*compact, *validator2, /*kid=*/absl::nullopt) .ok()); // Fails because token is not yet valid util::StatusOr validator_1970 = JwtValidatorBuilder().SetFixedNow(absl::FromUnixSeconds(12345)).Build(); ASSERT_THAT(validator_1970, IsOk()); EXPECT_FALSE(jwt_verify_ ->VerifyAndDecodeWithKid(*compact, *validator_1970, /*kid=*/absl::nullopt) .ok()); } TEST_F(JwtSignatureImplTest, CreateAndValidateTokenWithKid) { absl::Time now = absl::Now(); util::StatusOr raw_jwt = RawJwtBuilder() .SetTypeHeader("typeHeader") .SetJwtId("id123") .SetNotBefore(now - absl::Seconds(300)) .SetIssuedAt(now) .SetExpiration(now + absl::Seconds(300)) .Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr compact = jwt_sign_->SignAndEncodeWithKid(*raw_jwt, "kid-123"); ASSERT_THAT(compact, IsOk()); util::StatusOr validator = JwtValidatorBuilder().ExpectTypeHeader("typeHeader").Build(); util::StatusOr verified_jwt = jwt_verify_->VerifyAndDecodeWithKid(*compact, *validator, "kid-123"); ASSERT_THAT(verified_jwt, IsOk()); EXPECT_THAT(verified_jwt->GetTypeHeader(), IsOkAndHolds("typeHeader")); EXPECT_THAT(verified_jwt->GetJwtId(), IsOkAndHolds("id123")); // Kid header in the token is ignored. EXPECT_THAT( jwt_verify_ ->VerifyAndDecodeWithKid(*compact, *validator, /*kid=*/absl::nullopt) .status(), IsOk()); // parse header to make sure the kid value is set correctly. std::vector parts = absl::StrSplit(*compact, '.'); ASSERT_THAT(parts.size(), Eq(3)); std::string json_header; ASSERT_TRUE(DecodeHeader(parts[0], &json_header)); util::StatusOr header = JsonStringToProtoStruct(json_header); ASSERT_THAT(header, IsOk()); EXPECT_THAT(header->fields().find("kid")->second.string_value(), Eq("kid-123")); } TEST_F(JwtSignatureImplTest, FailsWithModifiedCompact) { util::StatusOr raw_jwt = RawJwtBuilder().SetJwtId("id123").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr compact = jwt_sign_->SignAndEncodeWithKid(*raw_jwt, /*kid=*/absl::nullopt); ASSERT_THAT(compact, IsOk()); util::StatusOr validator = JwtValidatorBuilder().AllowMissingExpiration().Build(); ASSERT_THAT(validator, IsOk()); EXPECT_THAT( jwt_verify_ ->VerifyAndDecodeWithKid(*compact, *validator, /*kid=*/absl::nullopt) .status(), IsOk()); EXPECT_FALSE(jwt_verify_ ->VerifyAndDecodeWithKid(absl::StrCat(*compact, "x"), *validator, /*kid=*/absl::nullopt) .ok()); EXPECT_FALSE(jwt_verify_ ->VerifyAndDecodeWithKid(absl::StrCat(*compact, " "), *validator, /*kid=*/absl::nullopt) .ok()); EXPECT_FALSE(jwt_verify_ ->VerifyAndDecodeWithKid(absl::StrCat("x", *compact), *validator, /*kid=*/absl::nullopt) .ok()); EXPECT_FALSE(jwt_verify_ ->VerifyAndDecodeWithKid(absl::StrCat(" ", *compact), *validator, /*kid=*/absl::nullopt) .ok()); } TEST_F(JwtSignatureImplTest, FailsWithInvalidTokens) { util::StatusOr validator = JwtValidatorBuilder().AllowMissingExpiration().Build(); ASSERT_THAT(validator, IsOk()); EXPECT_FALSE(jwt_verify_ ->VerifyAndDecodeWithKid("eyJhbGciOiJIUzI1NiJ9.e30.YWJj.", *validator, /*kid=*/absl::nullopt) .ok()); EXPECT_FALSE(jwt_verify_ ->VerifyAndDecodeWithKid("eyJhbGciOiJIUzI1NiJ9?.e30.YWJj", *validator, /*kid=*/absl::nullopt) .ok()); EXPECT_FALSE(jwt_verify_ ->VerifyAndDecodeWithKid("eyJhbGciOiJIUzI1NiJ9.e30?.YWJj", *validator, /*kid=*/absl::nullopt) .ok()); EXPECT_FALSE(jwt_verify_ ->VerifyAndDecodeWithKid("eyJhbGciOiJIUzI1NiJ9.e30.YWJj?", *validator, /*kid=*/absl::nullopt) .ok()); EXPECT_FALSE(jwt_verify_ ->VerifyAndDecodeWithKid("eyJhbGciOiJIUzI1NiJ9.YWJj", *validator, /*kid=*/absl::nullopt) .ok()); EXPECT_FALSE( jwt_verify_->VerifyAndDecodeWithKid("", *validator, /*kid=*/absl::nullopt) .ok()); EXPECT_FALSE( jwt_verify_ ->VerifyAndDecodeWithKid("..", *validator, /*kid=*/absl::nullopt) .ok()); } } // namespace } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_public_key_sign_wrapper.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/jwt_public_key_sign_wrapper.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/jwt/internal/jwt_format.h" #include "tink/jwt/internal/jwt_public_key_sign_internal.h" #include "tink/jwt/jwt_public_key_sign.h" #include "tink/jwt/raw_jwt.h" #include "tink/primitive_set.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { using google::crypto::tink::OutputPrefixType; namespace { class JwtPublicKeySignSetWrapper : public JwtPublicKeySign { public: explicit JwtPublicKeySignSetWrapper( std::unique_ptr> jwt_sign_set) : jwt_sign_set_(std::move(jwt_sign_set)) {} crypto::tink::util::StatusOr SignAndEncode( const crypto::tink::RawJwt& token) const override; ~JwtPublicKeySignSetWrapper() override = default; private: std::unique_ptr> jwt_sign_set_; }; util::Status Validate(PrimitiveSet* jwt_sign_set) { if (jwt_sign_set == nullptr) { return util::Status(absl::StatusCode::kInternal, "jwt_sign_set must be non-NULL"); } if (jwt_sign_set->get_primary() == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "jwt_sign_set has no primary"); } for (const auto* entry : jwt_sign_set->get_all()) { if ((entry->get_output_prefix_type() != OutputPrefixType::RAW) && (entry->get_output_prefix_type() != OutputPrefixType::TINK)) { return util::Status(absl::StatusCode::kInvalidArgument, "all JWT keys must be either RAW or TINK"); } } return util::OkStatus(); } util::StatusOr JwtPublicKeySignSetWrapper::SignAndEncode( const crypto::tink::RawJwt& token) const { auto primary = jwt_sign_set_->get_primary(); return primary->get_primitive().SignAndEncodeWithKid( token, GetKid(primary->get_key_id(), primary->get_output_prefix_type())); } } // namespace util::StatusOr> JwtPublicKeySignWrapper::Wrap( std::unique_ptr> jwt_sign_set) const { util::Status status = Validate(jwt_sign_set.get()); if (!status.ok()) return status; std::unique_ptr jwt_sign = absl::make_unique(std::move(jwt_sign_set)); return std::move(jwt_sign); } } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_public_key_sign_wrapper.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_JWT_PUBLIC_KEY_SIGN_WRAPPER_H_ #define TINK_JWT_INTERNAL_JWT_PUBLIC_KEY_SIGN_WRAPPER_H_ #include #include "tink/jwt/internal/jwt_public_key_sign_internal.h" #include "tink/jwt/jwt_public_key_sign.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace jwt_internal { // Wraps a set of JwtPublicKeySign-instances that correspond to a keyset, // and combines them into a single JwtPublicKeySign-primitive. It always // uses the primary instance from the set in SignAndEncode. Only keys with RAW // output prefix are supported. class JwtPublicKeySignWrapper : public PrimitiveWrapper { public: util::StatusOr> Wrap( std::unique_ptr> jwt_sign_set) const override; }; } // namespace jwt_internal } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_JWT_PUBLIC_KEY_SIGN_WRAPPER_H_ ================================================ FILE: cc/jwt/internal/jwt_public_key_verify_impl.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/jwt_public_key_verify_impl.h" #include #include #include #include #include "google/protobuf/struct.pb.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/jwt/internal/json_util.h" #include "tink/jwt/internal/jwt_format.h" #include "tink/jwt/jwt_validator.h" #include "tink/jwt/raw_jwt.h" #include "tink/jwt/verified_jwt.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace jwt_internal { util::StatusOr JwtPublicKeyVerifyImpl::VerifyAndDecodeWithKid( absl::string_view compact, const JwtValidator& validator, absl::optional kid) const { // TODO(juerg): Refactor this code into a util function. std::size_t signature_pos = compact.find_last_of('.'); if (signature_pos == absl::string_view::npos) { return util::Status(absl::StatusCode::kInvalidArgument, "invalid token"); } absl::string_view unsigned_token = compact.substr(0, signature_pos); std::string signature; if (!DecodeSignature(compact.substr(signature_pos + 1), &signature)) { return util::Status(absl::StatusCode::kInvalidArgument, "invalid JWT signature"); } util::Status verify_result = verify_->Verify(signature, unsigned_token); if (!verify_result.ok()) { // Use a different error code so that we can distinguish it. return util::Status(absl::StatusCode::kUnauthenticated, verify_result.message()); } std::vector parts = absl::StrSplit(unsigned_token, '.'); if (parts.size() != 2) { return util::Status( absl::StatusCode::kInvalidArgument, "only tokens in JWS compact serialization format are supported"); } std::string json_header; if (!DecodeHeader(parts[0], &json_header)) { return util::Status(absl::StatusCode::kInvalidArgument, "invalid header"); } util::StatusOr header = JsonStringToProtoStruct(json_header); if (!header.ok()) { return header.status(); } util::Status validate_header_result = ValidateHeader(*header, algorithm_, kid, custom_kid_); if (!validate_header_result.ok()) { return validate_header_result; } std::string json_payload; if (!DecodePayload(parts[1], &json_payload)) { return util::Status(absl::StatusCode::kInvalidArgument, "invalid JWT payload"); } util::StatusOr raw_jwt = RawJwtParser::FromJson( GetTypeHeader(*header), json_payload); if (!raw_jwt.ok()) { return raw_jwt.status(); } util::Status validate_result = validator.Validate(*raw_jwt); if (!validate_result.ok()) { return validate_result; } return VerifiedJwt(*std::move(raw_jwt)); } } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_public_key_verify_impl.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_JWT_PUBLIC_KEY_VERIFY_IMPL_H_ #define TINK_JWT_INTERNAL_JWT_PUBLIC_KEY_VERIFY_IMPL_H_ #include #include #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/jwt/internal/jwt_public_key_verify_internal.h" #include "tink/jwt/jwt_validator.h" #include "tink/jwt/raw_jwt.h" #include "tink/jwt/verified_jwt.h" #include "tink/public_key_verify.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace jwt_internal { class JwtPublicKeyVerifyImpl : public JwtPublicKeyVerifyInternal { public: explicit JwtPublicKeyVerifyImpl( std::unique_ptr verify, absl::string_view algorithm, absl::optional custom_kid) { verify_ = std::move(verify); algorithm_ = std::string(algorithm); if (custom_kid.has_value()) { custom_kid_ = std::string(*custom_kid); } } crypto::tink::util::StatusOr VerifyAndDecodeWithKid( absl::string_view compact, const JwtValidator& validator, absl::optional kid) const override; private: std::unique_ptr verify_; std::string algorithm_; // custom_kid may be set when a key is converted from another format, for // example JWK. It does not have any relation to the key id. It can only be // set for keys with output prefix RAW. absl::optional custom_kid_; }; } // namespace jwt_internal } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_JWT_PUBLIC_KEY_VERIFY_IMPL_H_ ================================================ FILE: cc/jwt/internal/jwt_public_key_verify_internal.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_JWT_PUBLIC_KEY_VERIFY_INTERNAL_H_ #define TINK_JWT_INTERNAL_JWT_PUBLIC_KEY_VERIFY_INTERNAL_H_ #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/jwt/jwt_validator.h" #include "tink/jwt/verified_jwt.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Internal interface for verifying signed JWT. // // Sees RFC 7519 and RFC 7515. Security guarantees: similar to PublicKeyVerify. class JwtPublicKeyVerifyInternal { public: // Verifies and decodes a JWT token in the JWS compact serialization format. // // The JWT is validated against the rules in validator. That is, every claim // in validator must also be present in the JWT. For example, if validator // contains an issuer (iss) claim, the JWT must contain an identical claim. // The JWT can contain claims that are NOT in the validator. However, if the // JWT contains a list of audiences, the validator must also contain an // audience in the list. // // If the JWT contains timestamp claims such as expiration (exp), issued_at // (iat) or not_before (nbf), they will also be validated. validator allows to // set a clock skew, to deal with small clock differences among different // machines. // // When `kid` has a value only a token with the correct kid header is valid. // When `kid` does not have a value a kid header in the token is ignored. // `kid` is set by the primitive wrapper based on the output prefix type and // the key id. virtual crypto::tink::util::StatusOr VerifyAndDecodeWithKid( absl::string_view compact, const JwtValidator& validator, absl::optional kid) const = 0; virtual ~JwtPublicKeyVerifyInternal() = default; }; } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_JWT_PUBLIC_KEY_VERIFY_INTERNAL_H_ ================================================ FILE: cc/jwt/internal/jwt_public_key_verify_wrapper.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/jwt_public_key_verify_wrapper.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/jwt/internal/jwt_format.h" #include "tink/jwt/internal/jwt_public_key_verify_internal.h" #include "tink/jwt/jwt_public_key_verify.h" #include "tink/jwt/jwt_validator.h" #include "tink/jwt/verified_jwt.h" #include "tink/primitive_set.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { using google::crypto::tink::OutputPrefixType; namespace { class JwtPublicKeyVerifySetWrapper : public JwtPublicKeyVerify { public: explicit JwtPublicKeyVerifySetWrapper( std::unique_ptr> jwt_verify_set) : jwt_verify_set_(std::move(jwt_verify_set)) {} crypto::tink::util::StatusOr VerifyAndDecode( absl::string_view compact, const crypto::tink::JwtValidator& validator) const override; ~JwtPublicKeyVerifySetWrapper() override = default; private: std::unique_ptr> jwt_verify_set_; }; util::Status Validate( PrimitiveSet* jwt_verify_set) { if (jwt_verify_set == nullptr) { return util::Status(absl::StatusCode::kInternal, "jwt_verify_set must be non-NULL"); } for (const auto* entry : jwt_verify_set->get_all()) { if ((entry->get_output_prefix_type() != OutputPrefixType::RAW) && (entry->get_output_prefix_type() != OutputPrefixType::TINK)) { return util::Status(absl::StatusCode::kInvalidArgument, "all JWT keys must be either RAW or TINK"); } } return util::OkStatus(); } util::StatusOr JwtPublicKeyVerifySetWrapper::VerifyAndDecode( absl::string_view compact, const crypto::tink::JwtValidator& validator) const { absl::optional interesting_status; for (const auto* entry : jwt_verify_set_->get_all()) { JwtPublicKeyVerifyInternal& jwt_verify = entry->get_primitive(); absl::optional kid = GetKid(entry->get_key_id(), entry->get_output_prefix_type()); util::StatusOr verified_jwt = jwt_verify.VerifyAndDecodeWithKid(compact, validator, kid); if (verified_jwt.ok()) { return verified_jwt; } else if (verified_jwt.status().code() != absl::StatusCode::kUnauthenticated) { // errors that are not the result of a signature verification interesting_status = verified_jwt.status(); } } if (interesting_status.has_value()) { return *std::move(interesting_status); } return util::Status(absl::StatusCode::kInvalidArgument, "verification failed"); } } // namespace util::StatusOr> JwtPublicKeyVerifyWrapper::Wrap( std::unique_ptr> jwt_verify_set) const { util::Status status = Validate(jwt_verify_set.get()); if (!status.ok()) return status; std::unique_ptr jwt_verify = absl::make_unique( std::move(jwt_verify_set)); return std::move(jwt_verify); } } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_public_key_verify_wrapper.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_JWT_PUBLIC_KEY_VERIFY_WRAPPER_H_ #define TINK_JWT_INTERNAL_JWT_PUBLIC_KEY_VERIFY_WRAPPER_H_ #include #include "tink/jwt/internal/jwt_public_key_verify_internal.h" #include "tink/jwt/jwt_public_key_verify.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace jwt_internal { // Wraps a set of JwtPublicKeyVerify-instances that correspond to a keyset, // and combines them into a single JwtPublicKeyVerify-primitive. It always // uses all instances from the set in VerifyAndDecode. Only keys with RAW // output prefix are supported. class JwtPublicKeyVerifyWrapper : public PrimitiveWrapper { public: util::StatusOr> Wrap( std::unique_ptr> jwt_verify_set) const override; }; } // namespace jwt_internal } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_JWT_PUBLIC_KEY_VERIFY_WRAPPER_H_ ================================================ FILE: cc/jwt/internal/jwt_public_key_wrappers_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include "google/protobuf/struct.pb.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "tink/cleartext_keyset_handle.h" #include "tink/config/global_registry.h" #include "tink/jwt/internal/json_util.h" #include "tink/jwt/internal/jwt_ecdsa_sign_key_manager.h" #include "tink/jwt/internal/jwt_ecdsa_verify_key_manager.h" #include "tink/jwt/internal/jwt_format.h" #include "tink/jwt/internal/jwt_public_key_sign_internal.h" #include "tink/jwt/internal/jwt_public_key_sign_wrapper.h" #include "tink/jwt/internal/jwt_public_key_verify_wrapper.h" #include "tink/jwt/jwt_public_key_sign.h" #include "tink/jwt/jwt_public_key_verify.h" #include "tink/jwt/jwt_validator.h" #include "tink/jwt/raw_jwt.h" #include "tink/jwt/verified_jwt.h" #include "tink/keyset_manager.h" #include "tink/primitive_set.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/jwt_ecdsa.pb.h" #include "proto/tink.pb.h" using ::crypto::tink::test::IsOk; using ::google::crypto::tink::JwtEcdsaAlgorithm; using ::google::crypto::tink::JwtEcdsaKeyFormat; using ::google::crypto::tink::Keyset; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::Not; using ::testing::SizeIs; namespace crypto { namespace tink { namespace jwt_internal { namespace { using ::crypto::tink::test::IsOk; using ::testing::Eq; KeyTemplate CreateTemplate(OutputPrefixType output_prefix) { KeyTemplate key_template; key_template.set_type_url( "type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey"); key_template.set_output_prefix_type(output_prefix); JwtEcdsaKeyFormat key_format; key_format.set_algorithm(JwtEcdsaAlgorithm::ES256); key_format.SerializeToString(key_template.mutable_value()); return key_template; } // KeysetHandleWithNewKeyId generates a new keyset handle with the exact same // keyset, except that the key ID of the first key is different. std::unique_ptr KeysetHandleWithNewKeyId( const KeysetHandle& keyset_handle) { Keyset keyset(CleartextKeysetHandle::GetKeyset(keyset_handle)); // Modify the key ID by XORing it with a arbitrary constant value. uint32_t new_key_id = keyset.mutable_key(0)->key_id() ^ 0xdeadbeef; keyset.mutable_key(0)->set_key_id(new_key_id); keyset.set_primary_key_id(new_key_id); return CleartextKeysetHandle::GetKeysetHandle(keyset); } // KeysetHandleWithTinkPrefix generates a new keyset handle with the exact same // keyset, except that the output prefix type of the first key is set to TINK. std::unique_ptr KeysetHandleWithTinkPrefix( const KeysetHandle& keyset_handle) { Keyset keyset(CleartextKeysetHandle::GetKeyset(keyset_handle)); keyset.mutable_key(0)->set_output_prefix_type(OutputPrefixType::TINK); return CleartextKeysetHandle::GetKeysetHandle(keyset); } class JwtPublicKeyWrappersTest : public ::testing::Test { protected: void SetUp() override { ASSERT_THAT(Registry::RegisterPrimitiveWrapper( absl::make_unique()), IsOk()); ASSERT_THAT(Registry::RegisterPrimitiveWrapper( absl::make_unique()), IsOk()); ASSERT_THAT(Registry::RegisterAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), true), IsOk()); } }; TEST_F(JwtPublicKeyWrappersTest, WrapNullptrSign) { EXPECT_FALSE(JwtPublicKeySignWrapper().Wrap(nullptr).ok()); } TEST_F(JwtPublicKeyWrappersTest, WrapNullptrVerify) { EXPECT_FALSE(JwtPublicKeyVerifyWrapper().Wrap(nullptr).ok()); } TEST_F(JwtPublicKeyWrappersTest, WrapEmptySign) { auto jwt_sign_set = absl::make_unique>(); auto result = JwtPublicKeySignWrapper().Wrap(std::move(jwt_sign_set)); EXPECT_FALSE(result.ok()); } TEST_F(JwtPublicKeyWrappersTest, CannotWrapPrimitivesFromNonRawOrTinkKeys) { KeyTemplate tink_key_template = CreateTemplate(OutputPrefixType::LEGACY); util::StatusOr> keyset_handle = KeysetHandle::GenerateNew(tink_key_template, KeyGenConfigGlobalRegistry()); ASSERT_THAT(keyset_handle, IsOk()); EXPECT_FALSE( (*keyset_handle) ->GetPrimitive(ConfigGlobalRegistry()) .status() .ok()); util::StatusOr> public_handle = (*keyset_handle)->GetPublicKeysetHandle(KeyGenConfigGlobalRegistry()); ASSERT_THAT(public_handle, IsOk()); EXPECT_FALSE((*public_handle) ->GetPrimitive( ConfigGlobalRegistry()) .status() .ok()); } TEST_F(JwtPublicKeyWrappersTest, GenerateRawSignVerifySuccess) { KeyTemplate key_template = CreateTemplate(OutputPrefixType::RAW); util::StatusOr> handle = KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()); ASSERT_THAT(handle, IsOk()); util::StatusOr> jwt_sign = (*handle)->GetPrimitive( ConfigGlobalRegistry()); EXPECT_THAT(jwt_sign, IsOk()); util::StatusOr> public_handle = (*handle)->GetPublicKeysetHandle(KeyGenConfigGlobalRegistry()); EXPECT_THAT(public_handle, IsOk()); util::StatusOr> jwt_verify = (*public_handle) ->GetPrimitive( ConfigGlobalRegistry()); EXPECT_THAT(jwt_verify, IsOk()); util::StatusOr raw_jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr compact = (*jwt_sign)->SignAndEncode(*raw_jwt); ASSERT_THAT(compact, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .ExpectIssuer("issuer") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); util::StatusOr verified_jwt = (*jwt_verify)->VerifyAndDecode(*compact, *validator); ASSERT_THAT(verified_jwt, IsOk()); EXPECT_THAT(verified_jwt->GetIssuer(), test::IsOkAndHolds("issuer")); util::StatusOr validator2 = JwtValidatorBuilder() .ExpectIssuer("unknown") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator2, IsOk()); util::StatusOr verified_jwt2 = (*jwt_verify)->VerifyAndDecode(*compact, *validator2); EXPECT_FALSE(verified_jwt2.ok()); // Make sure the error message is interesting EXPECT_THAT(verified_jwt2.status().message(), Eq("wrong issuer")); // Raw primitives don't add a kid header, Tink primitives require a kid // header to be set. Thefore, changing the output prefix to TINK makes the // validation fail. std::unique_ptr tink_public_handle = KeysetHandleWithTinkPrefix(**public_handle); util::StatusOr> tink_verify = tink_public_handle->GetPrimitive( ConfigGlobalRegistry()); ASSERT_THAT(tink_verify, IsOk()); EXPECT_THAT((*tink_verify)->VerifyAndDecode(*compact, *validator).status(), Not(IsOk())); } TEST_F(JwtPublicKeyWrappersTest, GenerateTinkSignVerifySuccess) { KeyTemplate key_template = CreateTemplate(OutputPrefixType::TINK); util::StatusOr> handle = KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()); ASSERT_THAT(handle, IsOk()); util::StatusOr> jwt_sign = (*handle)->GetPrimitive( ConfigGlobalRegistry()); EXPECT_THAT(jwt_sign, IsOk()); util::StatusOr> public_handle = (*handle)->GetPublicKeysetHandle(KeyGenConfigGlobalRegistry()); EXPECT_THAT(public_handle, IsOk()); util::StatusOr> jwt_verify = (*public_handle) ->GetPrimitive( ConfigGlobalRegistry()); EXPECT_THAT(jwt_verify, IsOk()); util::StatusOr raw_jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr compact = (*jwt_sign)->SignAndEncode(*raw_jwt); ASSERT_THAT(compact, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .ExpectIssuer("issuer") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); util::StatusOr verified_jwt = (*jwt_verify)->VerifyAndDecode(*compact, *validator); ASSERT_THAT(verified_jwt, IsOk()); EXPECT_THAT(verified_jwt->GetIssuer(), test::IsOkAndHolds("issuer")); // Parse header to make sure that key ID is correctly encoded. google::crypto::tink::KeysetInfo keyset_info = (*public_handle)->GetKeysetInfo(); uint32_t key_id = keyset_info.key_info(0).key_id(); std::vector parts = absl::StrSplit(*compact, '.'); ASSERT_THAT(parts, SizeIs(3)); std::string json_header; ASSERT_TRUE(DecodeHeader(parts[0], &json_header)); util::StatusOr header = JsonStringToProtoStruct(json_header); ASSERT_THAT(header, IsOk()); google::protobuf::Value value = (*header).fields().find("kid")->second; EXPECT_THAT(GetKeyId(value.string_value()), Eq(key_id)); // For Tink primitives, the kid must be correctly set and verified. // Therefore, changing the key_id makes the validation fail. std::unique_ptr public_handle_with_new_key_id = KeysetHandleWithNewKeyId(**public_handle); util::StatusOr> verify_with_new_key_id = public_handle_with_new_key_id ->GetPrimitive( ConfigGlobalRegistry()); ASSERT_THAT(verify_with_new_key_id, IsOk()); util::StatusOr verified_jwt_2 = (*verify_with_new_key_id)->VerifyAndDecode(*compact, *validator); EXPECT_FALSE(verified_jwt_2.ok()); } TEST_F(JwtPublicKeyWrappersTest, KeyRotation) { std::vector prefixes = {OutputPrefixType::RAW, OutputPrefixType::TINK}; for (OutputPrefixType prefix : prefixes) { SCOPED_TRACE(absl::StrCat("Testing with prefix ", prefix)); KeyTemplate key_template = CreateTemplate(prefix); KeysetManager manager; util::StatusOr old_id = manager.Add(key_template); ASSERT_THAT(old_id, IsOk()); ASSERT_THAT(manager.SetPrimary(*old_id), IsOk()); std::unique_ptr handle1 = manager.GetKeysetHandle(); util::StatusOr> jwt_sign1 = handle1->GetPrimitive( ConfigGlobalRegistry()); ASSERT_THAT(jwt_sign1, IsOk()); util::StatusOr> public_handle1 = handle1->GetPublicKeysetHandle(KeyGenConfigGlobalRegistry()); EXPECT_THAT(public_handle1, IsOk()); util::StatusOr> jwt_verify1 = (*public_handle1) ->GetPrimitive( ConfigGlobalRegistry()); EXPECT_THAT(jwt_verify1, IsOk()); util::StatusOr new_id = manager.Add(key_template); ASSERT_THAT(new_id, IsOk()); std::unique_ptr handle2 = manager.GetKeysetHandle(); util::StatusOr> jwt_sign2 = handle2->GetPrimitive( ConfigGlobalRegistry()); ASSERT_THAT(jwt_sign2, IsOk()); util::StatusOr> public_handle2 = handle2->GetPublicKeysetHandle(KeyGenConfigGlobalRegistry()); EXPECT_THAT(public_handle2, IsOk()); util::StatusOr> jwt_verify2 = (*public_handle2) ->GetPrimitive( ConfigGlobalRegistry()); EXPECT_THAT(jwt_verify2, IsOk()); ASSERT_THAT(manager.SetPrimary(*new_id), IsOk()); std::unique_ptr handle3 = manager.GetKeysetHandle(); util::StatusOr> jwt_sign3 = handle3->GetPrimitive( ConfigGlobalRegistry()); ASSERT_THAT(jwt_sign3, IsOk()); util::StatusOr> public_handle3 = handle3->GetPublicKeysetHandle(KeyGenConfigGlobalRegistry()); EXPECT_THAT(public_handle3, IsOk()); util::StatusOr> jwt_verify3 = (*public_handle3) ->GetPrimitive( ConfigGlobalRegistry()); EXPECT_THAT(jwt_verify3, IsOk()); ASSERT_THAT(manager.Disable(*old_id), IsOk()); std::unique_ptr handle4 = manager.GetKeysetHandle(); util::StatusOr> jwt_sign4 = handle4->GetPrimitive( ConfigGlobalRegistry()); ASSERT_THAT(jwt_sign4, IsOk()); util::StatusOr> public_handle4 = handle4->GetPublicKeysetHandle(KeyGenConfigGlobalRegistry()); EXPECT_THAT(public_handle4, IsOk()); util::StatusOr> jwt_verify4 = (*public_handle4) ->GetPrimitive( ConfigGlobalRegistry()); EXPECT_THAT(jwt_verify4, IsOk()); util::StatusOr raw_jwt = RawJwtBuilder().SetJwtId("id123").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder().AllowMissingExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr compact1 = (*jwt_sign1)->SignAndEncode(*raw_jwt); ASSERT_THAT(compact1, IsOk()); util::StatusOr compact2 = (*jwt_sign2)->SignAndEncode(*raw_jwt); ASSERT_THAT(compact2, IsOk()); util::StatusOr compact3 = (*jwt_sign3)->SignAndEncode(*raw_jwt); ASSERT_THAT(compact3, IsOk()); util::StatusOr compact4 = (*jwt_sign4)->SignAndEncode(*raw_jwt); ASSERT_THAT(compact4, IsOk()); EXPECT_THAT((*jwt_verify1)->VerifyAndDecode(*compact1, *validator).status(), IsOk()); EXPECT_THAT((*jwt_verify2)->VerifyAndDecode(*compact1, *validator).status(), IsOk()); EXPECT_THAT((*jwt_verify3)->VerifyAndDecode(*compact1, *validator).status(), IsOk()); EXPECT_FALSE((*jwt_verify4)->VerifyAndDecode(*compact1, *validator).ok()); EXPECT_THAT((*jwt_verify1)->VerifyAndDecode(*compact2, *validator).status(), IsOk()); EXPECT_THAT((*jwt_verify2)->VerifyAndDecode(*compact2, *validator).status(), IsOk()); EXPECT_THAT((*jwt_verify3)->VerifyAndDecode(*compact2, *validator).status(), IsOk()); EXPECT_FALSE((*jwt_verify4)->VerifyAndDecode(*compact2, *validator).ok()); EXPECT_FALSE((*jwt_verify1)->VerifyAndDecode(*compact3, *validator).ok()); EXPECT_THAT((*jwt_verify2)->VerifyAndDecode(*compact3, *validator).status(), IsOk()); EXPECT_THAT((*jwt_verify3)->VerifyAndDecode(*compact3, *validator).status(), IsOk()); EXPECT_THAT((*jwt_verify4)->VerifyAndDecode(*compact3, *validator).status(), IsOk()); EXPECT_FALSE((*jwt_verify1)->VerifyAndDecode(*compact4, *validator).ok()); EXPECT_THAT((*jwt_verify2)->VerifyAndDecode(*compact4, *validator).status(), IsOk()); EXPECT_THAT((*jwt_verify3)->VerifyAndDecode(*compact4, *validator).status(), IsOk()); EXPECT_THAT((*jwt_verify4)->VerifyAndDecode(*compact4, *validator).status(), IsOk()); } } } // namespace } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_rsa_ssa_pkcs1_sign_key_manager.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/jwt_rsa_ssa_pkcs1_sign_key_manager.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/jwt/internal/jwt_public_key_sign_impl.h" #include "tink/jwt/internal/jwt_public_key_sign_internal.h" #include "tink/jwt/internal/jwt_rsa_ssa_pkcs1_verify_key_manager.h" #include "tink/public_key_sign.h" #include "tink/util/status.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { using crypto::tink::util::Status; using crypto::tink::util::StatusOr; using google::crypto::tink::JwtRsaSsaPkcs1KeyFormat; using google::crypto::tink::JwtRsaSsaPkcs1PrivateKey; using google::crypto::tink::JwtRsaSsaPkcs1PublicKey; StatusOr> JwtRsaSsaPkcs1SignKeyManager::PublicKeySignFactory::Create( const JwtRsaSsaPkcs1PrivateKey& jwt_rsa_ssa_pkcs1_private_key) const { StatusOr name = JwtRsaSsaPkcs1VerifyKeyManager::AlgorithmName( jwt_rsa_ssa_pkcs1_private_key.public_key().algorithm()); if (!name.ok()) { return name.status(); } StatusOr> sign = raw_key_manager_.GetPrimitive( jwt_rsa_ssa_pkcs1_private_key); if (!sign.ok()) { return sign.status(); } absl::optional custom_kid = absl::nullopt; if (jwt_rsa_ssa_pkcs1_private_key.public_key().has_custom_kid()) { custom_kid = jwt_rsa_ssa_pkcs1_private_key.public_key().custom_kid().value(); } std::unique_ptr jwt_public_key_sign = absl::make_unique(*std::move(sign), *name, custom_kid); return std::move(jwt_public_key_sign); } uint32_t JwtRsaSsaPkcs1SignKeyManager::get_version() const { return raw_key_manager_.get_version(); } google::crypto::tink::KeyData::KeyMaterialType JwtRsaSsaPkcs1SignKeyManager::key_material_type() const { return raw_key_manager_.key_material_type(); } const std::string& JwtRsaSsaPkcs1SignKeyManager::get_key_type() const { return raw_key_manager_.get_key_type(); } StatusOr JwtRsaSsaPkcs1SignKeyManager::CreateKey( const JwtRsaSsaPkcs1KeyFormat& key_format) const { return raw_key_manager_.CreateKey(key_format); } Status JwtRsaSsaPkcs1SignKeyManager::ValidateKey( const JwtRsaSsaPkcs1PrivateKey& key) const { return raw_key_manager_.ValidateKey(key); } Status JwtRsaSsaPkcs1SignKeyManager::ValidateKeyFormat( const JwtRsaSsaPkcs1KeyFormat& key_format) const { return raw_key_manager_.ValidateKeyFormat(key_format); } StatusOr JwtRsaSsaPkcs1SignKeyManager::GetPublicKey( const JwtRsaSsaPkcs1PrivateKey& private_key) const { return raw_key_manager_.GetPublicKey(private_key); } } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_rsa_ssa_pkcs1_sign_key_manager.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_JWT_RSA_SSA_PKCS1_SIGN_KEY_MANAGER_H_ #define TINK_JWT_INTERNAL_JWT_RSA_SSA_PKCS1_SIGN_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/internal/fips_utils.h" #include "tink/jwt/internal/jwt_public_key_sign_internal.h" #include "tink/jwt/internal/raw_jwt_rsa_ssa_pkcs1_sign_key_manager.h" #include "tink/jwt/jwt_public_key_sign.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/jwt_rsa_ssa_pkcs1.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { class JwtRsaSsaPkcs1SignKeyManager : public PrivateKeyTypeManager< google::crypto::tink::JwtRsaSsaPkcs1PrivateKey, google::crypto::tink::JwtRsaSsaPkcs1KeyFormat, google::crypto::tink::JwtRsaSsaPkcs1PublicKey, List> { public: class PublicKeySignFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create(const google::crypto::tink::JwtRsaSsaPkcs1PrivateKey& private_key) const override; private: const RawJwtRsaSsaPkcs1SignKeyManager raw_key_manager_; }; JwtRsaSsaPkcs1SignKeyManager() : PrivateKeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override; google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override; const std::string& get_key_type() const override; crypto::tink::util::Status ValidateKey( const google::crypto::tink::JwtRsaSsaPkcs1PrivateKey& key) const override; crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::JwtRsaSsaPkcs1KeyFormat& key_format) const override; crypto::tink::util::StatusOr CreateKey(const google::crypto::tink::JwtRsaSsaPkcs1KeyFormat& key_format) const override; crypto::tink::util::StatusOr GetPublicKey(const google::crypto::tink::JwtRsaSsaPkcs1PrivateKey& private_key) const override; internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: const RawJwtRsaSsaPkcs1SignKeyManager raw_key_manager_; }; } // namespace jwt_internal } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_JWT_RSA_SSA_PKCS1_SIGN_KEY_MANAGER_H_ ================================================ FILE: cc/jwt/internal/jwt_rsa_ssa_pkcs1_sign_verify_key_manager_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include "google/protobuf/struct.pb.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "openssl/bn.h" #include "openssl/rsa.h" #include "tink/internal/bn_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/jwt/internal/json_util.h" #include "tink/jwt/internal/jwt_format.h" #include "tink/jwt/internal/jwt_public_key_sign_internal.h" #include "tink/jwt/internal/jwt_public_key_verify_internal.h" #include "tink/jwt/internal/jwt_rsa_ssa_pkcs1_sign_key_manager.h" #include "tink/jwt/internal/jwt_rsa_ssa_pkcs1_verify_key_manager.h" #include "tink/jwt/jwt_validator.h" #include "tink/jwt/raw_jwt.h" #include "tink/jwt/verified_jwt.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/jwt_rsa_ssa_pkcs1.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::JwtRsaSsaPkcs1Algorithm; using ::google::crypto::tink::JwtRsaSsaPkcs1KeyFormat; using ::google::crypto::tink::JwtRsaSsaPkcs1PrivateKey; using ::google::crypto::tink::JwtRsaSsaPkcs1PublicKey; using ::testing::Eq; using ::testing::Not; namespace { constexpr absl::string_view kTestKid = "kid-123"; JwtRsaSsaPkcs1KeyFormat CreateKeyFormat(JwtRsaSsaPkcs1Algorithm algorithm, int modulus_size_in_bits, int public_exponent) { JwtRsaSsaPkcs1KeyFormat key_format; key_format.set_algorithm(algorithm); key_format.set_modulus_size_in_bits(modulus_size_in_bits); internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), public_exponent); key_format.set_public_exponent( internal::BignumToString(e.get(), BN_num_bytes(e.get())).value()); return key_format; } TEST(JwtRsaSsaPkcs1SignVerifyKeyManagerTest, BasicsSign) { EXPECT_EQ(JwtRsaSsaPkcs1SignKeyManager().get_version(), 0); EXPECT_EQ(JwtRsaSsaPkcs1SignKeyManager().get_key_type(), "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PrivateKey"); EXPECT_EQ(JwtRsaSsaPkcs1SignKeyManager().key_material_type(), google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE); } TEST(JwtRsaSsaPkcs1SignVerifyKeyManagerTest, BasicsVerify) { EXPECT_EQ(JwtRsaSsaPkcs1VerifyKeyManager().get_version(), 0); EXPECT_EQ(JwtRsaSsaPkcs1VerifyKeyManager().get_key_type(), "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PublicKey"); EXPECT_EQ(JwtRsaSsaPkcs1VerifyKeyManager().key_material_type(), google::crypto::tink::KeyData::ASYMMETRIC_PUBLIC); } TEST(JwtRsaSsaPkcs1SignVerifyKeyManagerTest, ValidateEmptyPrivateKey) { EXPECT_THAT( JwtRsaSsaPkcs1SignKeyManager().ValidateKey(JwtRsaSsaPkcs1PrivateKey()), Not(IsOk())); } TEST(JwtRsaSsaPkcs1SignVerifyKeyManagerTest, ValidateEmptyPublicKey) { EXPECT_THAT( JwtRsaSsaPkcs1VerifyKeyManager().ValidateKey(JwtRsaSsaPkcs1PublicKey()), Not(IsOk())); } TEST(JwtRsaSsaPkcs1SignVerifyKeyManagerTest, ValidateEmptyKeyFormat) { EXPECT_THAT(JwtRsaSsaPkcs1SignKeyManager().ValidateKeyFormat( JwtRsaSsaPkcs1KeyFormat()), Not(IsOk())); } TEST(JwtRsaSsaPkcs1SignVerifyKeyManagerTest, ValidKeyFormatRS256) { JwtRsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(JwtRsaSsaPkcs1Algorithm::RS256, 2048, RSA_F4); EXPECT_THAT(JwtRsaSsaPkcs1SignKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(JwtRsaSsaPkcs1SignVerifyKeyManagerTest, ValidateKeyFormatRS384) { JwtRsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(JwtRsaSsaPkcs1Algorithm::RS384, 3072, RSA_F4); EXPECT_THAT(JwtRsaSsaPkcs1SignKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(JwtRsaSsaPkcs1SignVerifyKeyManagerTest, ValidateKeyFormatRS512) { JwtRsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(JwtRsaSsaPkcs1Algorithm::RS512, 4096, RSA_F4); EXPECT_THAT(JwtRsaSsaPkcs1SignKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(JwtRsaSsaPkcs1SignVerifyKeyManagerTest, CreatePrivateKeyAndValidate) { JwtRsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(JwtRsaSsaPkcs1Algorithm::RS256, 2048, RSA_F4); util::StatusOr key = JwtRsaSsaPkcs1SignKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); EXPECT_EQ(key->version(), 0); EXPECT_EQ(key->public_key().algorithm(), key_format.algorithm()); EXPECT_THAT(JwtRsaSsaPkcs1SignKeyManager().ValidateKey(*key), IsOk()); // Change key to an invalid algorithm. key->mutable_public_key()->set_algorithm(JwtRsaSsaPkcs1Algorithm::RS_UNKNOWN); EXPECT_FALSE(JwtRsaSsaPkcs1SignKeyManager().ValidateKey(*key).ok()); } TEST(JwtRsaSsaPkcs1SignVerifyKeyManagerTest, CreatePublicKeyAndValidate) { JwtRsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(JwtRsaSsaPkcs1Algorithm::RS256, 2048, RSA_F4); util::StatusOr key = JwtRsaSsaPkcs1SignKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); util::StatusOr public_key = JwtRsaSsaPkcs1SignKeyManager().GetPublicKey(*key); EXPECT_THAT(JwtRsaSsaPkcs1VerifyKeyManager().ValidateKey(*public_key), IsOk()); // Change key to an invalid algorithm. public_key->set_algorithm(JwtRsaSsaPkcs1Algorithm::RS_UNKNOWN); EXPECT_FALSE(JwtRsaSsaPkcs1VerifyKeyManager().ValidateKey(*public_key).ok()); } TEST(JwtRsaSsaPkcs1SignVerifyKeyManagerTest, GetAndUsePrimitives) { JwtRsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(JwtRsaSsaPkcs1Algorithm::RS256, 2048, RSA_F4); util::StatusOr key = JwtRsaSsaPkcs1SignKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); util::StatusOr> sign = JwtRsaSsaPkcs1SignKeyManager().GetPrimitive( *key); ASSERT_THAT(sign, IsOk()); util::StatusOr raw_jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr compact = (*sign)->SignAndEncodeWithKid(*raw_jwt, /*kid=*/absl::nullopt); ASSERT_THAT(compact, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .ExpectIssuer("issuer") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); util::StatusOr> verify = JwtRsaSsaPkcs1VerifyKeyManager().GetPrimitive( key->public_key()); ASSERT_THAT(verify, IsOk()); util::StatusOr verified_jwt = (*verify)->VerifyAndDecodeWithKid( *compact, *validator, /*kid=*/absl::nullopt); ASSERT_THAT(verified_jwt, IsOk()); util::StatusOr issuer = verified_jwt->GetIssuer(); EXPECT_THAT(issuer, IsOkAndHolds("issuer")); EXPECT_THAT((*verify) ->VerifyAndDecodeWithKid(*compact, *validator, kTestKid) .status(), Not(IsOk())); util::StatusOr validator2 = JwtValidatorBuilder().ExpectIssuer("unknown").Build(); ASSERT_THAT(validator2, IsOk()); EXPECT_FALSE( (*verify) ->VerifyAndDecodeWithKid(*compact, *validator2, /*kid=*/absl::nullopt) .ok()); // Token with kid header util::StatusOr token_with_kid = (*sign)->SignAndEncodeWithKid(*raw_jwt, kTestKid); ASSERT_THAT(compact, IsOk()); EXPECT_THAT((*verify) ->VerifyAndDecodeWithKid(*token_with_kid, *validator, /*kid=*/absl::nullopt) .status(), IsOk()); EXPECT_THAT( (*verify) ->VerifyAndDecodeWithKid(*token_with_kid, *validator, kTestKid) .status(), IsOk()); EXPECT_THAT( (*verify) ->VerifyAndDecodeWithKid(*token_with_kid, *validator, "other-kid") .status(), Not(IsOk())); } TEST(JwtRsaSsaPkcs1SignVerifyKeyManagerTest, GetAndUsePrimitivesWithCustomKid) { JwtRsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(JwtRsaSsaPkcs1Algorithm::RS256, 2048, RSA_F4); util::StatusOr key = JwtRsaSsaPkcs1SignKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); key->mutable_public_key()->mutable_custom_kid()->set_value( "Lorem ipsum dolor sit amet, consectetur adipiscing elit"); util::StatusOr> sign = JwtRsaSsaPkcs1SignKeyManager().GetPrimitive( *key); ASSERT_THAT(sign, IsOk()); util::StatusOr raw_jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr compact = (*sign)->SignAndEncodeWithKid(*raw_jwt, /*kid=*/absl::nullopt); ASSERT_THAT(compact, IsOk()); // parse header and check "kid" std::vector parts = absl::StrSplit(*compact, '.'); ASSERT_THAT(parts.size(), Eq(3)); std::string json_header; ASSERT_TRUE(DecodeHeader(parts[0], &json_header)); util::StatusOr header = JsonStringToProtoStruct(json_header); ASSERT_THAT(header, IsOk()); auto it = header->fields().find("kid"); ASSERT_FALSE(it == header->fields().end()); EXPECT_THAT(it->second.string_value(), Eq("Lorem ipsum dolor sit amet, consectetur adipiscing elit")); // validate token util::StatusOr validator = JwtValidatorBuilder() .ExpectIssuer("issuer") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); util::StatusOr> verify = JwtRsaSsaPkcs1VerifyKeyManager().GetPrimitive( key->public_key()); ASSERT_THAT(verify, IsOk()); util::StatusOr verified_jwt = (*verify)->VerifyAndDecodeWithKid( *compact, *validator, /*kid=*/absl::nullopt); ASSERT_THAT(verified_jwt, IsOk()); util::StatusOr issuer = verified_jwt->GetIssuer(); ASSERT_THAT(issuer, IsOk()); EXPECT_THAT(*issuer, Eq("issuer")); // passing a kid when custom_kid is set should fail EXPECT_THAT((*sign)->SignAndEncodeWithKid(*raw_jwt, kTestKid).status(), Not(IsOk())); EXPECT_THAT((*verify) ->VerifyAndDecodeWithKid(*compact, *validator, kTestKid) .status(), Not(IsOk())); // Test that custom kid is verified: validation should fail with other kid. key->mutable_public_key()->mutable_custom_kid()->set_value("other kid"); ASSERT_THAT(validator, IsOk()); util::StatusOr> other_verify = JwtRsaSsaPkcs1VerifyKeyManager().GetPrimitive( key->public_key()); ASSERT_THAT(other_verify, IsOk()); EXPECT_THAT( (*other_verify) ->VerifyAndDecodeWithKid(*compact, *validator, /*kid=*/absl::nullopt) .status(), Not(IsOk())); } TEST(JwtRsaSsaPkcs1SignVerifyKeyManagerTest, VerifyFailsWithDifferentKey) { JwtRsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(JwtRsaSsaPkcs1Algorithm::RS256, 2048, RSA_F4); util::StatusOr key1 = JwtRsaSsaPkcs1SignKeyManager().CreateKey(key_format); ASSERT_THAT(key1, IsOk()); util::StatusOr key2 = JwtRsaSsaPkcs1SignKeyManager().CreateKey(key_format); ASSERT_THAT(key2, IsOk()); util::StatusOr> sign1 = JwtRsaSsaPkcs1SignKeyManager().GetPrimitive( *key1); ASSERT_THAT(sign1, IsOk()); util::StatusOr raw_jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr compact = (*sign1)->SignAndEncodeWithKid(*raw_jwt, /*kid=*/absl::nullopt); ASSERT_THAT(compact, IsOk()); util::StatusOr validator = JwtValidatorBuilder().AllowMissingExpiration().Build(); ASSERT_THAT(validator, IsOk()); util::StatusOr> verify2 = JwtRsaSsaPkcs1VerifyKeyManager().GetPrimitive( key2->public_key()); EXPECT_THAT(verify2, IsOk()); EXPECT_THAT( (*verify2) ->VerifyAndDecodeWithKid(*compact, *validator, /*kid=*/absl::nullopt) .status(), Not(IsOk())); } } // namespace } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_rsa_ssa_pkcs1_verify_key_manager.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/jwt_rsa_ssa_pkcs1_verify_key_manager.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/jwt/internal/jwt_public_key_verify_impl.h" #include "tink/jwt/internal/jwt_public_key_verify_internal.h" #include "tink/public_key_verify.h" #include "tink/util/status.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { using crypto::tink::util::Status; using crypto::tink::util::StatusOr; using google::crypto::tink::JwtRsaSsaPkcs1Algorithm; using google::crypto::tink::JwtRsaSsaPkcs1PublicKey; StatusOr> JwtRsaSsaPkcs1VerifyKeyManager::PublicKeyVerifyFactory::Create( const JwtRsaSsaPkcs1PublicKey& jwt_rsa_ssa_pkcs1_public_key) const { StatusOr name = AlgorithmName(jwt_rsa_ssa_pkcs1_public_key.algorithm()); if (!name.ok()) { return name.status(); } StatusOr> verify = raw_key_manager_.GetPrimitive( jwt_rsa_ssa_pkcs1_public_key); if (!verify.ok()) { return verify.status(); } absl::optional custom_kid = absl::nullopt; if (jwt_rsa_ssa_pkcs1_public_key.has_custom_kid()) { custom_kid = jwt_rsa_ssa_pkcs1_public_key.custom_kid().value(); } std::unique_ptr jwt_public_key_verify = absl::make_unique( *std::move(verify), *name, custom_kid); return std::move(jwt_public_key_verify); } uint32_t JwtRsaSsaPkcs1VerifyKeyManager::get_version() const { return raw_key_manager_.get_version(); } google::crypto::tink::KeyData::KeyMaterialType JwtRsaSsaPkcs1VerifyKeyManager::key_material_type() const { return raw_key_manager_.key_material_type(); } const std::string& JwtRsaSsaPkcs1VerifyKeyManager::get_key_type() const { return raw_key_manager_.get_key_type(); } Status JwtRsaSsaPkcs1VerifyKeyManager::ValidateKey( const JwtRsaSsaPkcs1PublicKey& key) const { return raw_key_manager_.ValidateKey(key); } StatusOr JwtRsaSsaPkcs1VerifyKeyManager::AlgorithmName( const JwtRsaSsaPkcs1Algorithm& algorithm) { switch (algorithm) { case JwtRsaSsaPkcs1Algorithm::RS256: return std::string("RS256"); case JwtRsaSsaPkcs1Algorithm::RS384: return std::string("RS384"); case JwtRsaSsaPkcs1Algorithm::RS512: return std::string("RS512"); default: return Status(absl::StatusCode::kInvalidArgument, "Unsupported RSA SSA PKCS1 Algorithm"); } } } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_rsa_ssa_pkcs1_verify_key_manager.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_JWT_RSA_SSA_PKCS1_VERIFY_KEY_MANAGER_H_ #define TINK_JWT_INTERNAL_JWT_RSA_SSA_PKCS1_VERIFY_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/internal/fips_utils.h" #include "tink/jwt/internal/jwt_public_key_verify_impl.h" #include "tink/jwt/internal/jwt_public_key_verify_internal.h" #include "tink/jwt/internal/raw_jwt_rsa_ssa_pkcs1_verify_key_manager.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/jwt_rsa_ssa_pkcs1.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { class JwtRsaSsaPkcs1VerifyKeyManager : public KeyTypeManager> { public: class PublicKeyVerifyFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create(const google::crypto::tink::JwtRsaSsaPkcs1PublicKey& jwt_rsa_ssa_pkcs1_public_key) const override; private: const RawJwtRsaSsaPkcs1VerifyKeyManager raw_key_manager_; }; JwtRsaSsaPkcs1VerifyKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override; google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override; const std::string& get_key_type() const override; crypto::tink::util::Status ValidateKey( const google::crypto::tink::JwtRsaSsaPkcs1PublicKey& key) const override; internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: static crypto::tink::util::StatusOr AlgorithmName( const google::crypto::tink::JwtRsaSsaPkcs1Algorithm& algorithm); const RawJwtRsaSsaPkcs1VerifyKeyManager raw_key_manager_; friend class JwtRsaSsaPkcs1SignKeyManager; }; } // namespace jwt_internal } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_JWT_RSA_SSA_PKCS1_VERIFY_KEY_MANAGER_H_ ================================================ FILE: cc/jwt/internal/jwt_rsa_ssa_pss_sign_key_manager.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/jwt_rsa_ssa_pss_sign_key_manager.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/jwt/internal/jwt_public_key_sign_impl.h" #include "tink/jwt/internal/jwt_public_key_sign_internal.h" #include "tink/jwt/internal/jwt_rsa_ssa_pss_verify_key_manager.h" #include "tink/public_key_sign.h" #include "tink/util/status.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { using crypto::tink::util::Status; using crypto::tink::util::StatusOr; using google::crypto::tink::JwtRsaSsaPssKeyFormat; using google::crypto::tink::JwtRsaSsaPssPrivateKey; using google::crypto::tink::JwtRsaSsaPssPublicKey; StatusOr> JwtRsaSsaPssSignKeyManager::PublicKeySignFactory::Create( const JwtRsaSsaPssPrivateKey& jwt_rsa_ssa_pss_private_key) const { StatusOr name = JwtRsaSsaPssVerifyKeyManager::AlgorithmName( jwt_rsa_ssa_pss_private_key.public_key().algorithm()); if (!name.ok()) { return name.status(); } StatusOr> sign = raw_key_manager_.GetPrimitive(jwt_rsa_ssa_pss_private_key); if (!sign.ok()) { return sign.status(); } absl::optional custom_kid = absl::nullopt; if (jwt_rsa_ssa_pss_private_key.public_key().has_custom_kid()) { custom_kid = jwt_rsa_ssa_pss_private_key.public_key().custom_kid().value(); } std::unique_ptr jwt_public_key_sign = absl::make_unique(*std::move(sign), *name, custom_kid); return std::move(jwt_public_key_sign); } uint32_t JwtRsaSsaPssSignKeyManager::get_version() const { return raw_key_manager_.get_version(); } google::crypto::tink::KeyData::KeyMaterialType JwtRsaSsaPssSignKeyManager::key_material_type() const { return raw_key_manager_.key_material_type(); } const std::string& JwtRsaSsaPssSignKeyManager::get_key_type() const { return raw_key_manager_.get_key_type(); } StatusOr JwtRsaSsaPssSignKeyManager::CreateKey( const JwtRsaSsaPssKeyFormat& key_format) const { return raw_key_manager_.CreateKey(key_format); } Status JwtRsaSsaPssSignKeyManager::ValidateKey( const JwtRsaSsaPssPrivateKey& key) const { return raw_key_manager_.ValidateKey(key); } Status JwtRsaSsaPssSignKeyManager::ValidateKeyFormat( const JwtRsaSsaPssKeyFormat& key_format) const { return raw_key_manager_.ValidateKeyFormat(key_format); } StatusOr JwtRsaSsaPssSignKeyManager::GetPublicKey( const JwtRsaSsaPssPrivateKey& private_key) const { return raw_key_manager_.GetPublicKey(private_key); } } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_rsa_ssa_pss_sign_key_manager.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_JWT_RSA_SSA_PSS_SIGN_KEY_MANAGER_H_ #define TINK_JWT_INTERNAL_JWT_RSA_SSA_PSS_SIGN_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/internal/fips_utils.h" #include "tink/jwt/internal/jwt_public_key_sign_internal.h" #include "tink/jwt/internal/raw_jwt_rsa_ssa_pss_sign_key_manager.h" #include "tink/jwt/jwt_public_key_sign.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/jwt_rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { class JwtRsaSsaPssSignKeyManager : public PrivateKeyTypeManager> { public: class PublicKeySignFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create(const google::crypto::tink::JwtRsaSsaPssPrivateKey& private_key) const override; private: const RawJwtRsaSsaPssSignKeyManager raw_key_manager_; }; JwtRsaSsaPssSignKeyManager() : PrivateKeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override; google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override; const std::string& get_key_type() const override; crypto::tink::util::Status ValidateKey( const google::crypto::tink::JwtRsaSsaPssPrivateKey& key) const override; crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::JwtRsaSsaPssKeyFormat& key_format) const override; crypto::tink::util::StatusOr CreateKey(const google::crypto::tink::JwtRsaSsaPssKeyFormat& key_format) const override; crypto::tink::util::StatusOr GetPublicKey(const google::crypto::tink::JwtRsaSsaPssPrivateKey& private_key) const override; internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: const RawJwtRsaSsaPssSignKeyManager raw_key_manager_; }; } // namespace jwt_internal } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_JWT_RSA_SSA_PSS_SIGN_KEY_MANAGER_H_ ================================================ FILE: cc/jwt/internal/jwt_rsa_ssa_pss_sign_verify_key_manager_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include "google/protobuf/struct.pb.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "openssl/bn.h" #include "openssl/rsa.h" #include "tink/internal/bn_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/jwt/internal/json_util.h" #include "tink/jwt/internal/jwt_format.h" #include "tink/jwt/internal/jwt_public_key_sign_internal.h" #include "tink/jwt/internal/jwt_public_key_verify_internal.h" #include "tink/jwt/internal/jwt_rsa_ssa_pss_sign_key_manager.h" #include "tink/jwt/internal/jwt_rsa_ssa_pss_verify_key_manager.h" #include "tink/jwt/jwt_validator.h" #include "tink/jwt/raw_jwt.h" #include "tink/jwt/verified_jwt.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/jwt_rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::JwtRsaSsaPssAlgorithm; using ::google::crypto::tink::JwtRsaSsaPssKeyFormat; using ::google::crypto::tink::JwtRsaSsaPssPrivateKey; using ::google::crypto::tink::JwtRsaSsaPssPublicKey; using ::testing::Eq; using ::testing::Not; namespace { constexpr absl::string_view kTestKid = "kid-123"; JwtRsaSsaPssKeyFormat CreateKeyFormat(JwtRsaSsaPssAlgorithm algorithm, int modulus_size_in_bits, int public_exponent) { JwtRsaSsaPssKeyFormat key_format; key_format.set_algorithm(algorithm); key_format.set_modulus_size_in_bits(modulus_size_in_bits); internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), public_exponent); key_format.set_public_exponent( internal::BignumToString(e.get(), BN_num_bytes(e.get())).value()); return key_format; } TEST(JwtRsaSsaPssSignVerifyKeyManagerTest, BasicsSign) { EXPECT_EQ(JwtRsaSsaPssSignKeyManager().get_version(), 0); EXPECT_EQ(JwtRsaSsaPssSignKeyManager().get_key_type(), "type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPrivateKey"); EXPECT_EQ(JwtRsaSsaPssSignKeyManager().key_material_type(), google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE); } TEST(JwtRsaSsaPssSignVerifyKeyManagerTest, BasicsVerify) { EXPECT_EQ(JwtRsaSsaPssVerifyKeyManager().get_version(), 0); EXPECT_EQ(JwtRsaSsaPssVerifyKeyManager().get_key_type(), "type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPublicKey"); EXPECT_EQ(JwtRsaSsaPssVerifyKeyManager().key_material_type(), google::crypto::tink::KeyData::ASYMMETRIC_PUBLIC); } TEST(JwtRsaSsaPssSignVerifyKeyManagerTest, ValidateEmptyPrivateKey) { EXPECT_THAT( JwtRsaSsaPssSignKeyManager().ValidateKey(JwtRsaSsaPssPrivateKey()), Not(IsOk())); } TEST(JwtRsaSsaPssSignVerifyKeyManagerTest, ValidateEmptyPublicKey) { EXPECT_THAT( JwtRsaSsaPssVerifyKeyManager().ValidateKey(JwtRsaSsaPssPublicKey()), Not(IsOk())); } TEST(JwtRsaSsaPssSignVerifyKeyManagerTest, ValidateEmptyKeyFormat) { EXPECT_THAT( JwtRsaSsaPssSignKeyManager().ValidateKeyFormat(JwtRsaSsaPssKeyFormat()), Not(IsOk())); } TEST(JwtRsaSsaPssSignVerifyKeyManagerTest, ValidKeyFormatPS256) { JwtRsaSsaPssKeyFormat key_format = CreateKeyFormat(JwtRsaSsaPssAlgorithm::PS256, 2048, RSA_F4); EXPECT_THAT(JwtRsaSsaPssSignKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(JwtRsaSsaPssSignVerifyKeyManagerTest, ValidateKeyFormatRS384) { JwtRsaSsaPssKeyFormat key_format = CreateKeyFormat(JwtRsaSsaPssAlgorithm::PS384, 3072, RSA_F4); EXPECT_THAT(JwtRsaSsaPssSignKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(JwtRsaSsaPssSignVerifyKeyManagerTest, ValidateKeyFormatRS512) { JwtRsaSsaPssKeyFormat key_format = CreateKeyFormat(JwtRsaSsaPssAlgorithm::PS512, 4096, RSA_F4); EXPECT_THAT(JwtRsaSsaPssSignKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(JwtRsaSsaPssSignVerifyKeyManagerTest, CreatePrivateKeyAndValidate) { JwtRsaSsaPssKeyFormat key_format = CreateKeyFormat(JwtRsaSsaPssAlgorithm::PS256, 2048, RSA_F4); util::StatusOr key = JwtRsaSsaPssSignKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); EXPECT_EQ(key->version(), 0); EXPECT_EQ(key->public_key().algorithm(), key_format.algorithm()); EXPECT_THAT(JwtRsaSsaPssSignKeyManager().ValidateKey(*key), IsOk()); // Change key to an invalid algorithm. key->mutable_public_key()->set_algorithm(JwtRsaSsaPssAlgorithm::PS_UNKNOWN); EXPECT_FALSE(JwtRsaSsaPssSignKeyManager().ValidateKey(*key).ok()); } TEST(JwtRsaSsaPssSignVerifyKeyManagerTest, CreatePublicKeyAndValidate) { JwtRsaSsaPssKeyFormat key_format = CreateKeyFormat(JwtRsaSsaPssAlgorithm::PS256, 2048, RSA_F4); util::StatusOr key = JwtRsaSsaPssSignKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); util::StatusOr public_key = JwtRsaSsaPssSignKeyManager().GetPublicKey(*key); EXPECT_THAT(JwtRsaSsaPssVerifyKeyManager().ValidateKey(*public_key), IsOk()); // Change key to an invalid algorithm. public_key->set_algorithm(JwtRsaSsaPssAlgorithm::PS_UNKNOWN); EXPECT_FALSE(JwtRsaSsaPssVerifyKeyManager().ValidateKey(*public_key).ok()); } TEST(JwtRsaSsaPssSignVerifyKeyManagerTest, GetAndUsePrimitives) { JwtRsaSsaPssKeyFormat key_format = CreateKeyFormat(JwtRsaSsaPssAlgorithm::PS256, 2048, RSA_F4); util::StatusOr key = JwtRsaSsaPssSignKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); util::StatusOr> sign = JwtRsaSsaPssSignKeyManager().GetPrimitive(*key); ASSERT_THAT(sign, IsOk()); util::StatusOr raw_jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr compact = (*sign)->SignAndEncodeWithKid(*raw_jwt, /*kid=*/absl::nullopt); ASSERT_THAT(compact, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .ExpectIssuer("issuer") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); util::StatusOr> verify = JwtRsaSsaPssVerifyKeyManager().GetPrimitive( key->public_key()); ASSERT_THAT(verify, IsOk()); util::StatusOr verified_jwt = (*verify)->VerifyAndDecodeWithKid( *compact, *validator, /*kid=*/absl::nullopt); ASSERT_THAT(verified_jwt, IsOk()); util::StatusOr issuer = verified_jwt->GetIssuer(); ASSERT_THAT(issuer, IsOkAndHolds("issuer")); EXPECT_THAT((*verify) ->VerifyAndDecodeWithKid(*compact, *validator, kTestKid) .status(), Not(IsOk())); util::StatusOr validator2 = JwtValidatorBuilder() .ExpectIssuer("unknown") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator2, IsOk()); EXPECT_FALSE( (*verify) ->VerifyAndDecodeWithKid(*compact, *validator2, /*kid=*/absl::nullopt) .ok()); // Token with kid header util::StatusOr token_with_kid = (*sign)->SignAndEncodeWithKid(*raw_jwt, kTestKid); ASSERT_THAT(compact, IsOk()); EXPECT_THAT((*verify) ->VerifyAndDecodeWithKid(*token_with_kid, *validator, /*kid=*/absl::nullopt) .status(), IsOk()); EXPECT_THAT( (*verify) ->VerifyAndDecodeWithKid(*token_with_kid, *validator, kTestKid) .status(), IsOk()); EXPECT_THAT( (*verify) ->VerifyAndDecodeWithKid(*token_with_kid, *validator, "other-kid") .status(), Not(IsOk())); } TEST(JwtRsaSsaPkcs1SignVerifyKeyManagerTest, GetAndUsePrimitivesWithCustomKid) { JwtRsaSsaPssKeyFormat key_format = CreateKeyFormat(JwtRsaSsaPssAlgorithm::PS256, 2048, RSA_F4); util::StatusOr key = JwtRsaSsaPssSignKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); key->mutable_public_key()->mutable_custom_kid()->set_value( "Lorem ipsum dolor sit amet, consectetur adipiscing elit"); util::StatusOr> sign = JwtRsaSsaPssSignKeyManager().GetPrimitive(*key); ASSERT_THAT(sign, IsOk()); util::StatusOr raw_jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr compact = (*sign)->SignAndEncodeWithKid(*raw_jwt, /*kid=*/absl::nullopt); ASSERT_THAT(compact, IsOk()); // parse header and check "kid" std::vector parts = absl::StrSplit(*compact, '.'); ASSERT_THAT(parts.size(), Eq(3)); std::string json_header; ASSERT_TRUE(DecodeHeader(parts[0], &json_header)); util::StatusOr header = JsonStringToProtoStruct(json_header); ASSERT_THAT(header, IsOk()); auto it = header->fields().find("kid"); ASSERT_FALSE(it == header->fields().end()); EXPECT_THAT(it->second.string_value(), Eq("Lorem ipsum dolor sit amet, consectetur adipiscing elit")); // validate token util::StatusOr validator = JwtValidatorBuilder() .ExpectIssuer("issuer") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); util::StatusOr> verify = JwtRsaSsaPssVerifyKeyManager().GetPrimitive( key->public_key()); ASSERT_THAT(verify, IsOk()); util::StatusOr verified_jwt = (*verify)->VerifyAndDecodeWithKid( *compact, *validator, /*kid=*/absl::nullopt); ASSERT_THAT(verified_jwt, IsOk()); util::StatusOr issuer = verified_jwt->GetIssuer(); ASSERT_THAT(issuer, IsOk()); EXPECT_THAT(*issuer, Eq("issuer")); // passing a kid when custom_kid is set should fail EXPECT_THAT((*sign)->SignAndEncodeWithKid(*raw_jwt, kTestKid).status(), Not(IsOk())); EXPECT_THAT((*verify) ->VerifyAndDecodeWithKid(*compact, *validator, kTestKid) .status(), Not(IsOk())); // Test that custom kid is verified: validation should fail with other kid. key->mutable_public_key()->mutable_custom_kid()->set_value("other kid"); ASSERT_THAT(validator, IsOk()); util::StatusOr> other_verify = JwtRsaSsaPssVerifyKeyManager().GetPrimitive( key->public_key()); ASSERT_THAT(other_verify, IsOk()); EXPECT_THAT( (*other_verify) ->VerifyAndDecodeWithKid(*compact, *validator, /*kid=*/absl::nullopt) .status(), Not(IsOk())); } TEST(JwtRsaSsaPssSignVerifyKeyManagerTest, VerifyFailsWithDifferentKey) { JwtRsaSsaPssKeyFormat key_format = CreateKeyFormat(JwtRsaSsaPssAlgorithm::PS256, 2048, RSA_F4); util::StatusOr key1 = JwtRsaSsaPssSignKeyManager().CreateKey(key_format); ASSERT_THAT(key1, IsOk()); util::StatusOr key2 = JwtRsaSsaPssSignKeyManager().CreateKey(key_format); ASSERT_THAT(key2, IsOk()); util::StatusOr> sign1 = JwtRsaSsaPssSignKeyManager().GetPrimitive( *key1); ASSERT_THAT(sign1, IsOk()); util::StatusOr raw_jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr compact = (*sign1)->SignAndEncodeWithKid(*raw_jwt, /*kid=*/absl::nullopt); ASSERT_THAT(compact, IsOk()); util::StatusOr validator = JwtValidatorBuilder().AllowMissingExpiration().Build(); ASSERT_THAT(validator, IsOk()); util::StatusOr> verify2 = JwtRsaSsaPssVerifyKeyManager().GetPrimitive( key2->public_key()); ASSERT_THAT(verify2, IsOk()); EXPECT_THAT( (*verify2) ->VerifyAndDecodeWithKid(*compact, *validator, /*kid=*/absl::nullopt) .status(), Not(IsOk())); } } // namespace } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_rsa_ssa_pss_verify_key_manager.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/jwt_rsa_ssa_pss_verify_key_manager.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/jwt/internal/jwt_public_key_verify_impl.h" #include "tink/jwt/internal/jwt_public_key_verify_internal.h" #include "tink/public_key_verify.h" #include "tink/util/status.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { using crypto::tink::util::Status; using crypto::tink::util::StatusOr; using google::crypto::tink::JwtRsaSsaPssAlgorithm; using google::crypto::tink::JwtRsaSsaPssPublicKey; StatusOr> JwtRsaSsaPssVerifyKeyManager::PublicKeyVerifyFactory::Create( const JwtRsaSsaPssPublicKey& jwt_rsa_ssa_pss_public_key) const { StatusOr name = AlgorithmName(jwt_rsa_ssa_pss_public_key.algorithm()); if (!name.ok()) { return name.status(); } StatusOr> verify = raw_key_manager_.GetPrimitive( jwt_rsa_ssa_pss_public_key); if (!verify.ok()) { return verify.status(); } absl::optional custom_kid = absl::nullopt; if (jwt_rsa_ssa_pss_public_key.has_custom_kid()) { custom_kid = jwt_rsa_ssa_pss_public_key.custom_kid().value(); } std::unique_ptr jwt_public_key_verify = absl::make_unique( *std::move(verify), *name, custom_kid); return std::move(jwt_public_key_verify); } uint32_t JwtRsaSsaPssVerifyKeyManager::get_version() const { return raw_key_manager_.get_version(); } google::crypto::tink::KeyData::KeyMaterialType JwtRsaSsaPssVerifyKeyManager::key_material_type() const { return raw_key_manager_.key_material_type(); } const std::string& JwtRsaSsaPssVerifyKeyManager::get_key_type() const { return raw_key_manager_.get_key_type(); } Status JwtRsaSsaPssVerifyKeyManager::ValidateKey( const JwtRsaSsaPssPublicKey& key) const { return raw_key_manager_.ValidateKey(key); } StatusOr JwtRsaSsaPssVerifyKeyManager::AlgorithmName( const JwtRsaSsaPssAlgorithm& algorithm) { switch (algorithm) { case JwtRsaSsaPssAlgorithm::PS256: return std::string("PS256"); case JwtRsaSsaPssAlgorithm::PS384: return std::string("PS384"); case JwtRsaSsaPssAlgorithm::PS512: return std::string("PS512"); default: return Status(absl::StatusCode::kInvalidArgument, "Unsupported RSA SSA PKCS1 Algorithm"); } } } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/jwt_rsa_ssa_pss_verify_key_manager.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_JWT_RSA_SSA_PSS_VERIFY_KEY_MANAGER_H_ #define TINK_JWT_INTERNAL_JWT_RSA_SSA_PSS_VERIFY_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/internal/fips_utils.h" #include "tink/jwt/internal/jwt_public_key_verify_impl.h" #include "tink/jwt/internal/jwt_public_key_verify_internal.h" #include "tink/jwt/internal/raw_jwt_rsa_ssa_pss_verify_key_manager.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/jwt_rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { class JwtRsaSsaPssVerifyKeyManager : public KeyTypeManager> { public: class PublicKeyVerifyFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create(const google::crypto::tink::JwtRsaSsaPssPublicKey& jwt_rsa_ssa_pss_public_key) const override; private: const RawJwtRsaSsaPssVerifyKeyManager raw_key_manager_; }; JwtRsaSsaPssVerifyKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override; google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override; const std::string& get_key_type() const override; crypto::tink::util::Status ValidateKey( const google::crypto::tink::JwtRsaSsaPssPublicKey& key) const override; internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: static crypto::tink::util::StatusOr AlgorithmName( const google::crypto::tink::JwtRsaSsaPssAlgorithm& algorithm); const RawJwtRsaSsaPssVerifyKeyManager raw_key_manager_; friend class JwtRsaSsaPssSignKeyManager; }; } // namespace jwt_internal } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_JWT_RSA_SSA_PSS_VERIFY_KEY_MANAGER_H_ ================================================ FILE: cc/jwt/internal/raw_jwt_ecdsa_sign_key_manager.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/raw_jwt_ecdsa_sign_key_manager.h" #include #include #include #include "absl/memory/memory.h" #include "absl/strings/string_view.h" #include "tink/internal/ec_util.h" #include "tink/jwt/internal/raw_jwt_ecdsa_verify_key_manager.h" #include "tink/public_key_sign.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/ecdsa_sign_boringssl.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/common.pb.h" #include "proto/jwt_ecdsa.pb.h" namespace crypto { namespace tink { namespace jwt_internal { using crypto::tink::util::Enums; using crypto::tink::util::Status; using crypto::tink::util::StatusOr; using google::crypto::tink::JwtEcdsaKeyFormat; using google::crypto::tink::JwtEcdsaPrivateKey; using google::crypto::tink::JwtEcdsaPublicKey; StatusOr RawJwtEcdsaSignKeyManager::CreateKey( const JwtEcdsaKeyFormat& jwt_ecdsa_key_format) const { // Generate new EC key. util::StatusOr curve = RawJwtEcdsaVerifyKeyManager::CurveForEcdsaAlgorithm( jwt_ecdsa_key_format.algorithm()); if (!curve.ok()) { return curve.status(); } util::StatusOr ec_key = internal::NewEcKey(util::Enums::ProtoToSubtle(*curve)); if (!ec_key.ok()) return ec_key.status(); // Build EcdsaPrivateKey. JwtEcdsaPrivateKey jwt_ecdsa_private_key; jwt_ecdsa_private_key.set_version(get_version()); jwt_ecdsa_private_key.set_key_value( std::string(util::SecretDataAsStringView(ec_key->priv))); auto jwt_ecdsa_public_key = jwt_ecdsa_private_key.mutable_public_key(); jwt_ecdsa_public_key->set_version(get_version()); jwt_ecdsa_public_key->set_x(ec_key->pub_x); jwt_ecdsa_public_key->set_y(ec_key->pub_y); jwt_ecdsa_public_key->set_algorithm(jwt_ecdsa_key_format.algorithm()); return jwt_ecdsa_private_key; } StatusOr> RawJwtEcdsaSignKeyManager::PublicKeySignFactory::Create( const JwtEcdsaPrivateKey& jwt_ecdsa_private_key) const { const JwtEcdsaPublicKey& public_key = jwt_ecdsa_private_key.public_key(); internal::EcKey ec_key; util::StatusOr curve = RawJwtEcdsaVerifyKeyManager::CurveForEcdsaAlgorithm( public_key.algorithm()); if (!curve.ok()) { return curve.status(); } ec_key.curve = Enums::ProtoToSubtle(*curve); ec_key.pub_x = public_key.x(); ec_key.pub_y = public_key.y(); ec_key.priv = util::SecretDataFromStringView(jwt_ecdsa_private_key.key_value()); util::StatusOr hash_type = RawJwtEcdsaVerifyKeyManager::HashForEcdsaAlgorithm( public_key.algorithm()); if (!hash_type.ok()) { return hash_type.status(); } auto result = subtle::EcdsaSignBoringSsl::New( ec_key, Enums::ProtoToSubtle(*hash_type), subtle::EcdsaSignatureEncoding::IEEE_P1363); if (!result.ok()) return result.status(); return {*std::move(result)}; } Status RawJwtEcdsaSignKeyManager::ValidateKey( const JwtEcdsaPrivateKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; return RawJwtEcdsaVerifyKeyManager().ValidateKey(key.public_key()); } Status RawJwtEcdsaSignKeyManager::ValidateKeyFormat( const JwtEcdsaKeyFormat& key_format) const { return RawJwtEcdsaVerifyKeyManager::ValidateAlgorithm(key_format.algorithm()); } } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/raw_jwt_ecdsa_sign_key_manager.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_RAW_JWT_ECDSA_SIGN_KEY_MANAGER_H_ #define TINK_JWT_INTERNAL_RAW_JWT_ECDSA_SIGN_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_sign.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/jwt_ecdsa.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { class RawJwtEcdsaSignKeyManager : public PrivateKeyTypeManager> { public: class PublicKeySignFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::JwtEcdsaPrivateKey& private_key) const override; }; RawJwtEcdsaSignKeyManager() : PrivateKeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::JwtEcdsaPrivateKey& key) const override; crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::JwtEcdsaKeyFormat& key_format) const override; crypto::tink::util::StatusOr CreateKey( const google::crypto::tink::JwtEcdsaKeyFormat& key_format) const override; crypto::tink::util::StatusOr GetPublicKey(const google::crypto::tink::JwtEcdsaPrivateKey& private_key) const override { return private_key.public_key(); } internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: const std::string key_type_ = absl::StrCat(kTypeGoogleapisCom, google::crypto::tink::JwtEcdsaPrivateKey().GetTypeName()); }; } // namespace jwt_internal } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_RAW_JWT_ECDSA_SIGN_KEY_MANAGER_H_ ================================================ FILE: cc/jwt/internal/raw_jwt_ecdsa_sign_key_manager_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/raw_jwt_ecdsa_sign_key_manager.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/internal/ec_util.h" #include "tink/jwt/internal/raw_jwt_ecdsa_verify_key_manager.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/ecdsa_verify_boringssl.h" #include "tink/util/enums.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/ecdsa.pb.h" #include "proto/jwt_ecdsa.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::Enums; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::EllipticCurveType; using ::google::crypto::tink::HashType; using ::google::crypto::tink::JwtEcdsaAlgorithm; using ::google::crypto::tink::JwtEcdsaKeyFormat; using ::google::crypto::tink::JwtEcdsaPrivateKey; using ::google::crypto::tink::JwtEcdsaPublicKey; using ::google::crypto::tink::KeyData; using ::testing::Eq; using ::testing::Gt; using ::testing::Not; using ::testing::SizeIs; namespace { TEST(RawJwtEcdsaSignKeyManagerTest, Basic) { EXPECT_THAT(RawJwtEcdsaSignKeyManager().get_version(), Eq(0)); EXPECT_THAT(RawJwtEcdsaSignKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PRIVATE)); EXPECT_THAT(RawJwtEcdsaSignKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey")); } TEST(RawJwtEcdsaSignKeyManagerTest, ValidateEmptyKeyFormat) { EXPECT_THAT( RawJwtEcdsaSignKeyManager().ValidateKeyFormat(JwtEcdsaKeyFormat()), Not(IsOk())); } JwtEcdsaKeyFormat CreateValidEs256KeyFormat() { JwtEcdsaKeyFormat key_format; key_format.set_algorithm(JwtEcdsaAlgorithm::ES256); return key_format; } TEST(RawJwtEcdsaSignKeyManagerTest, ValidateKeyFormat) { JwtEcdsaKeyFormat format = CreateValidEs256KeyFormat(); EXPECT_THAT(RawJwtEcdsaSignKeyManager().ValidateKeyFormat(format), IsOk()); } TEST(RawJwtEcdsaSignKeyManagerTest, ValidateKeyFormatUnknownAlgorithm) { JwtEcdsaKeyFormat key_format = CreateValidEs256KeyFormat(); key_format.set_algorithm(JwtEcdsaAlgorithm::ES_UNKNOWN); EXPECT_THAT(RawJwtEcdsaSignKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(RawJwtEcdsaSignKeyManagerTest, CreateKey) { JwtEcdsaKeyFormat format = CreateValidEs256KeyFormat(); StatusOr key = RawJwtEcdsaSignKeyManager().CreateKey(format); ASSERT_THAT(key, IsOk()); EXPECT_THAT(key->version(), Eq(0)); EXPECT_THAT(key->public_key().version(), Eq(key->version())); EXPECT_THAT(key->public_key().algorithm(), Eq(format.algorithm())); EXPECT_THAT(key->public_key().x(), SizeIs(Gt(0))); EXPECT_THAT(key->public_key().y(), SizeIs(Gt(0))); EXPECT_THAT(key->key_value(), SizeIs(Gt(0))); } TEST(RawJwtEcdsaSignKeyManagerTest, CreateKeyValid) { JwtEcdsaKeyFormat format = CreateValidEs256KeyFormat(); StatusOr key = RawJwtEcdsaSignKeyManager().CreateKey(format); ASSERT_THAT(key, IsOk()); EXPECT_THAT(RawJwtEcdsaSignKeyManager().ValidateKey(*key), IsOk()); } JwtEcdsaPrivateKey CreateValidEs256Key() { JwtEcdsaKeyFormat format = CreateValidEs256KeyFormat(); return RawJwtEcdsaSignKeyManager().CreateKey(format).value(); } TEST(RawJwtEcdsaSignKeyManagerTest, ValidateKey) { JwtEcdsaPrivateKey key = CreateValidEs256Key(); EXPECT_THAT(RawJwtEcdsaSignKeyManager().ValidateKey(key), IsOk()); } TEST(RawJwtEcdsaSignKeyManagerTest, ValidateKeyUnknownAlgorithm) { JwtEcdsaPrivateKey key = CreateValidEs256Key(); key.mutable_public_key()->set_algorithm(JwtEcdsaAlgorithm::ES_UNKNOWN); EXPECT_THAT(RawJwtEcdsaSignKeyManager().ValidateKey(key), Not(IsOk())); EXPECT_THAT(RawJwtEcdsaSignKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RawJwtEcdsaSignKeyManagerTest, GetPublicKey) { JwtEcdsaPrivateKey key = CreateValidEs256Key(); StatusOr public_key = RawJwtEcdsaSignKeyManager().GetPublicKey(key); ASSERT_THAT(public_key, IsOk()); EXPECT_THAT(public_key->version(), Eq(key.public_key().version())); EXPECT_THAT(public_key->algorithm(), Eq(key.public_key().algorithm())); EXPECT_THAT(public_key->x(), Eq(key.public_key().x())); EXPECT_THAT(public_key->y(), Eq(key.public_key().y())); } TEST(RawJwtEcdsaSignKeyManagerTest, Create) { JwtEcdsaPrivateKey private_key = CreateValidEs256Key(); util::StatusOr public_key = RawJwtEcdsaSignKeyManager().GetPublicKey(private_key); ASSERT_THAT(public_key, IsOk()); util::StatusOr> signer = RawJwtEcdsaSignKeyManager().GetPrimitive(private_key); ASSERT_THAT(signer, IsOk()); internal::EcKey ec_key; ec_key.curve = Enums::ProtoToSubtle(EllipticCurveType::NIST_P256); ec_key.pub_x = public_key->x(); ec_key.pub_y = public_key->y(); util::StatusOr> direct_verifier = subtle::EcdsaVerifyBoringSsl::New( ec_key, Enums::ProtoToSubtle(HashType::SHA256), subtle::EcdsaSignatureEncoding::IEEE_P1363); ASSERT_THAT(direct_verifier, IsOk()); std::string message = "Some message"; util::StatusOr sig = (*signer)->Sign(message); ASSERT_THAT(sig, IsOk()); EXPECT_THAT((*direct_verifier)->Verify(*sig, message), IsOk()); } TEST(RawJwtEcdsaSignKeyManagerTest, CreateDifferentKey) { JwtEcdsaPrivateKey private_key = CreateValidEs256Key(); // Note: we create a new key in the next line. util::StatusOr public_key = RawJwtEcdsaSignKeyManager() .GetPublicKey(CreateValidEs256Key()); util::StatusOr> signer = RawJwtEcdsaSignKeyManager().GetPrimitive(private_key); ASSERT_THAT(signer, IsOk()); internal::EcKey ec_key; ec_key.curve = Enums::ProtoToSubtle(EllipticCurveType::NIST_P256); ec_key.pub_x = public_key->x(); ec_key.pub_y = public_key->y(); util::StatusOr> direct_verifier = subtle::EcdsaVerifyBoringSsl::New( ec_key, Enums::ProtoToSubtle(HashType::SHA256), subtle::EcdsaSignatureEncoding::IEEE_P1363); ASSERT_THAT(direct_verifier, IsOk()); std::string message = "Some message"; util::StatusOr sig = (*signer)->Sign(message); ASSERT_THAT(sig, IsOk()); EXPECT_THAT((*direct_verifier)->Verify(*sig, message), Not(IsOk())); } } // namespace } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/raw_jwt_ecdsa_verify_key_manager.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/raw_jwt_ecdsa_verify_key_manager.h" #include #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/internal/ec_util.h" #include "tink/public_key_verify.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/ecdsa_verify_boringssl.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/jwt_ecdsa.pb.h" namespace crypto { namespace tink { namespace jwt_internal { using crypto::tink::util::Enums; using crypto::tink::util::Status; using crypto::tink::util::StatusOr; using google::crypto::tink::JwtEcdsaAlgorithm; using google::crypto::tink::JwtEcdsaPublicKey; using google::crypto::tink::EllipticCurveType; using google::crypto::tink::HashType; StatusOr> RawJwtEcdsaVerifyKeyManager::PublicKeyVerifyFactory::Create( const JwtEcdsaPublicKey& jwt_ecdsa_public_key) const { internal::EcKey ec_key; util::StatusOr curve = CurveForEcdsaAlgorithm(jwt_ecdsa_public_key.algorithm()); if (!curve.ok()) { return curve.status(); } ec_key.curve = Enums::ProtoToSubtle(*curve); ec_key.pub_x = jwt_ecdsa_public_key.x(); ec_key.pub_y = jwt_ecdsa_public_key.y(); util::StatusOr hash_type = HashForEcdsaAlgorithm(jwt_ecdsa_public_key.algorithm()); if (!hash_type.ok()) { return hash_type.status(); } auto result = subtle::EcdsaVerifyBoringSsl::New( ec_key, Enums::ProtoToSubtle(*hash_type), subtle::EcdsaSignatureEncoding::IEEE_P1363); if (!result.ok()) return result.status(); return {*std::move(result)}; } StatusOr RawJwtEcdsaVerifyKeyManager::CurveForEcdsaAlgorithm( const JwtEcdsaAlgorithm& algorithm) { switch (algorithm) { case JwtEcdsaAlgorithm::ES256: return EllipticCurveType::NIST_P256; case JwtEcdsaAlgorithm::ES384: return EllipticCurveType::NIST_P384; case JwtEcdsaAlgorithm::ES512: return EllipticCurveType::NIST_P521; default: return Status(absl::StatusCode::kInvalidArgument, "Unsupported Ecdsa Algorithm"); } } StatusOr RawJwtEcdsaVerifyKeyManager::HashForEcdsaAlgorithm( const JwtEcdsaAlgorithm& algorithm) { switch (algorithm) { case JwtEcdsaAlgorithm::ES256: return HashType::SHA256; case JwtEcdsaAlgorithm::ES384: return HashType::SHA384; case JwtEcdsaAlgorithm::ES512: return HashType::SHA512; default: return Status(absl::StatusCode::kInvalidArgument, "Unsupported Ecdsa Algorithm"); } } Status RawJwtEcdsaVerifyKeyManager::ValidateAlgorithm( const JwtEcdsaAlgorithm& algorithm) { switch (algorithm) { case JwtEcdsaAlgorithm::ES256: case JwtEcdsaAlgorithm::ES384: case JwtEcdsaAlgorithm::ES512: return util::OkStatus(); default: return Status(absl::StatusCode::kInvalidArgument, "Unsupported Ecdsa Algorithm"); } return util::OkStatus(); } Status RawJwtEcdsaVerifyKeyManager::ValidateKey( const JwtEcdsaPublicKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; return ValidateAlgorithm(key.algorithm()); } } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/raw_jwt_ecdsa_verify_key_manager.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_RAW_JWT_ECDSA_VERIFY_KEY_MANAGER_H_ #define TINK_JWT_INTERNAL_RAW_JWT_ECDSA_VERIFY_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_verify.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/common.pb.h" #include "proto/jwt_ecdsa.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { class RawJwtEcdsaVerifyKeyManager : public KeyTypeManager> { public: class PublicKeyVerifyFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::JwtEcdsaPublicKey& jwt_ecdsa_public_key) const override; }; RawJwtEcdsaVerifyKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PUBLIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::JwtEcdsaPublicKey& key) const override; internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: static crypto::tink::util::Status ValidateAlgorithm( const google::crypto::tink::JwtEcdsaAlgorithm& algorithm); static crypto::tink::util::StatusOr CurveForEcdsaAlgorithm( const google::crypto::tink::JwtEcdsaAlgorithm& algorithm); static crypto::tink::util::StatusOr HashForEcdsaAlgorithm( const google::crypto::tink::JwtEcdsaAlgorithm& algorithm); const std::string key_type_ = absl::StrCat(kTypeGoogleapisCom, google::crypto::tink::JwtEcdsaPublicKey().GetTypeName()); friend class RawJwtEcdsaSignKeyManager; }; } // namespace jwt_internal } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_RAW_JWT_ECDSA_VERIFY_KEY_MANAGER_H_ ================================================ FILE: cc/jwt/internal/raw_jwt_ecdsa_verify_key_manager_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/raw_jwt_ecdsa_verify_key_manager.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/internal/ec_util.h" #include "tink/jwt/internal/raw_jwt_ecdsa_sign_key_manager.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/ecdsa_sign_boringssl.h" #include "tink/util/enums.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/ecdsa.pb.h" #include "proto/jwt_ecdsa.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::Enums; using ::google::crypto::tink::JwtEcdsaKeyFormat; using ::google::crypto::tink::JwtEcdsaPrivateKey; using ::google::crypto::tink::JwtEcdsaPublicKey; using ::google::crypto::tink::EllipticCurveType; using ::google::crypto::tink::JwtEcdsaAlgorithm; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::testing::Eq; using ::testing::Not; namespace { TEST(RawJwtEcdsaVerifyKeyManagerTest, Basics) { EXPECT_THAT(RawJwtEcdsaVerifyKeyManager().get_version(), Eq(0)); EXPECT_THAT(RawJwtEcdsaVerifyKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PUBLIC)); EXPECT_THAT(RawJwtEcdsaVerifyKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey")); } TEST(RawJwtEcdsaVerifyKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(RawJwtEcdsaVerifyKeyManager().ValidateKey(JwtEcdsaPublicKey()), Not(IsOk())); } JwtEcdsaPrivateKey CreateValidEs256PrivateKey() { JwtEcdsaKeyFormat key_format; key_format.set_algorithm(JwtEcdsaAlgorithm::ES256); return RawJwtEcdsaSignKeyManager().CreateKey(key_format).value(); } JwtEcdsaPublicKey CreateValidPublicKey() { return RawJwtEcdsaSignKeyManager() .GetPublicKey(CreateValidEs256PrivateKey()) .value(); } // Checks that a public key generaed by the SignKeyManager is considered valid. TEST(RawJwtEcdsaVerifyKeyManagerTest, PublicKeyValid) { JwtEcdsaPublicKey key = CreateValidPublicKey(); EXPECT_THAT(RawJwtEcdsaVerifyKeyManager().ValidateKey(key), IsOk()); } TEST(EcdsaSignKeyManagerTest, ValidateKeyUnknownAlgorithm) { JwtEcdsaPublicKey key = CreateValidPublicKey(); key.set_algorithm(JwtEcdsaAlgorithm::ES_UNKNOWN); EXPECT_THAT(RawJwtEcdsaVerifyKeyManager().ValidateKey(key), Not(IsOk())); EXPECT_THAT(RawJwtEcdsaVerifyKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EcdsaSignKeyManagerTest, Create) { JwtEcdsaPrivateKey private_key = CreateValidEs256PrivateKey(); JwtEcdsaPublicKey public_key = RawJwtEcdsaSignKeyManager().GetPublicKey(private_key).value(); internal::EcKey ec_key; ec_key.curve = Enums::ProtoToSubtle(EllipticCurveType::NIST_P256); ec_key.pub_x = public_key.x(); ec_key.pub_y = public_key.y(); ec_key.priv = util::SecretDataFromStringView(private_key.key_value()); util::StatusOr> direct_signer = subtle::EcdsaSignBoringSsl::New( ec_key, Enums::ProtoToSubtle(HashType::SHA256), subtle::EcdsaSignatureEncoding::IEEE_P1363); ASSERT_THAT(direct_signer, IsOk()); util::StatusOr> verifier = RawJwtEcdsaVerifyKeyManager().GetPrimitive(public_key); ASSERT_THAT(verifier, IsOk()); std::string message = "Some message"; util::StatusOr sig = (*direct_signer)->Sign(message); ASSERT_THAT(sig, IsOk()); EXPECT_THAT((*verifier)->Verify(*sig, message), IsOk()); } TEST(EcdsaSignKeyManagerTest, CreateDifferentPrivateKey) { JwtEcdsaPrivateKey private_key = CreateValidEs256PrivateKey(); // Note: we create a new key in the next line. util::StatusOr public_key = RawJwtEcdsaSignKeyManager().GetPublicKey(CreateValidEs256PrivateKey()); internal::EcKey ec_key; ec_key.curve = Enums::ProtoToSubtle(EllipticCurveType::NIST_P256); ec_key.pub_x = public_key->x(); ec_key.pub_y = public_key->y(); ec_key.priv = util::SecretDataFromStringView(private_key.key_value()); util::StatusOr> direct_signer = subtle::EcdsaSignBoringSsl::New( ec_key, Enums::ProtoToSubtle(HashType::SHA256), subtle::EcdsaSignatureEncoding::IEEE_P1363); ASSERT_THAT(direct_signer, IsOk()); util::StatusOr> verifier = RawJwtEcdsaVerifyKeyManager().GetPrimitive(*public_key); ASSERT_THAT(verifier, IsOk()); std::string message = "Some message"; util::StatusOr sig = (*direct_signer)->Sign(message); ASSERT_THAT(sig, IsOk()); EXPECT_THAT((*verifier)->Verify(*sig, message), Not(IsOk())); } } // namespace } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/raw_jwt_hmac_key_manager.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/raw_jwt_hmac_key_manager.h" #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/input_stream.h" #include "tink/mac.h" #include "tink/subtle/hmac_boringssl.h" #include "tink/subtle/random.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/input_stream_util.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/common.pb.h" #include "proto/jwt_hmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { using crypto::tink::util::Status; using crypto::tink::util::StatusOr; using google::crypto::tink::JwtHmacAlgorithm; using google::crypto::tink::JwtHmacKey; using google::crypto::tink::JwtHmacKeyFormat; namespace { StatusOr MinimumKeySize(const JwtHmacAlgorithm& algorithm) { switch (algorithm) { case JwtHmacAlgorithm::HS256: return 32; case JwtHmacAlgorithm::HS384: return 48; case JwtHmacAlgorithm::HS512: return 64; default: return Status(absl::StatusCode::kInvalidArgument, "Unsupported algorithm."); } } } // namespace StatusOr RawJwtHmacKeyManager::CreateKey( const JwtHmacKeyFormat& jwt_hmac_key_format) const { JwtHmacKey jwt_hmac_key; jwt_hmac_key.set_version(get_version()); jwt_hmac_key.set_algorithm(jwt_hmac_key_format.algorithm()); jwt_hmac_key.set_key_value( subtle::Random::GetRandomBytes(jwt_hmac_key_format.key_size())); return jwt_hmac_key; } StatusOr RawJwtHmacKeyManager::DeriveKey( const JwtHmacKeyFormat& jwt_hmac_key_format, InputStream* input_stream) const { return util::Status(absl::StatusCode::kUnimplemented, "RawJwtHmacKeyManager::DeriveKey is not implemented"); } Status RawJwtHmacKeyManager::ValidateKey(const JwtHmacKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; StatusOr min_key_size = MinimumKeySize(key.algorithm()); if (!min_key_size.ok()) { return min_key_size.status(); } if (key.key_value().size() < *min_key_size) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid JwtHmacKey: key_value is too short."); } return util::OkStatus(); } // static Status RawJwtHmacKeyManager::ValidateKeyFormat( const JwtHmacKeyFormat& key_format) const { StatusOr min_key_size = MinimumKeySize(key_format.algorithm()); if (!min_key_size.ok()) { return min_key_size.status(); } if (key_format.key_size() < *min_key_size) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid HmacKeyFormat: key_size is too small."); } return util::OkStatus(); } } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/raw_jwt_hmac_key_manager.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_RAW_JWT_HMAC_KEY_MANAGER_H_ #define TINK_JWT_INTERNAL_RAW_JWT_HMAC_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/input_stream.h" #include "tink/internal/fips_utils.h" #include "tink/mac.h" #include "tink/subtle/hmac_boringssl.h" #include "tink/util/constants.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/jwt_hmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { /////////////////////////////////////////////////////////////////////////////// // This key manager creates MAC primitives from JwtHmacKeys. It is by the Tink // JWT implementation in Python, and should not be used by anybody else. // class RawJwtHmacKeyManager : public KeyTypeManager> { public: class MacFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::JwtHmacKey& jwt_hmac_key) const override { int tag_size; google::crypto::tink::HashType hash_type; switch (jwt_hmac_key.algorithm()) { case google::crypto::tink::JwtHmacAlgorithm::HS256: hash_type = google::crypto::tink::HashType::SHA256; tag_size = 32; break; case google::crypto::tink::JwtHmacAlgorithm::HS384: hash_type = google::crypto::tink::HashType::SHA384; tag_size = 48; break; case google::crypto::tink::JwtHmacAlgorithm::HS512: hash_type = google::crypto::tink::HashType::SHA512; tag_size = 64; break; default: return util::Status(absl::StatusCode::kInvalidArgument, "Unknown algorithm."); } return subtle::HmacBoringSsl::New( util::Enums::ProtoToSubtle(hash_type), tag_size, util::SecretDataFromStringView(jwt_hmac_key.key_value())); } }; RawJwtHmacKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::SYMMETRIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::JwtHmacKey& key) const override; crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::JwtHmacKeyFormat& key_format) const override; crypto::tink::util::StatusOr CreateKey( const google::crypto::tink::JwtHmacKeyFormat& key_format) const override; crypto::tink::util::StatusOr DeriveKey( const google::crypto::tink::JwtHmacKeyFormat& key_format, InputStream* input_stream) const override; internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: const std::string key_type_ = absl::StrCat( kTypeGoogleapisCom, google::crypto::tink::JwtHmacKey().GetTypeName()); }; } // namespace jwt_internal } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_RAW_JWT_HMAC_KEY_MANAGER_H_ ================================================ FILE: cc/jwt/internal/raw_jwt_hmac_key_manager_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/raw_jwt_hmac_key_manager.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/config/global_registry.h" #include "tink/core/key_manager_impl.h" #include "tink/keyset_handle.h" #include "tink/mac.h" #include "tink/mac/mac_config.h" #include "tink/registry.h" #include "tink/util/istream_input_stream.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/jwt_hmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace jwt_internal { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::IstreamInputStream; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::JwtHmacAlgorithm; using ::google::crypto::tink::JwtHmacKey; using ::google::crypto::tink::JwtHmacKeyFormat; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::Not; using ::testing::SizeIs; namespace { TEST(RawJwtHmacKeyManagerTest, Basics) { EXPECT_THAT(RawJwtHmacKeyManager().get_version(), Eq(0)); EXPECT_THAT(RawJwtHmacKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.JwtHmacKey")); EXPECT_THAT(RawJwtHmacKeyManager().key_material_type(), Eq(google::crypto::tink::KeyData::SYMMETRIC)); } TEST(RawJwtHmacKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(RawJwtHmacKeyManager().ValidateKey(JwtHmacKey()), Not(IsOk())); } TEST(RawJwtHmacKeyManagerTest, ValidateEmptyKeyFormat) { EXPECT_THAT(RawJwtHmacKeyManager().ValidateKeyFormat(JwtHmacKeyFormat()), Not(IsOk())); } // BETTER TESTS. TEST(RawJwtHmacKeyManagerTest, ValidateHS256KeyFormat) { JwtHmacKeyFormat key_format; key_format.set_algorithm(JwtHmacAlgorithm::HS256); key_format.set_key_size(32); EXPECT_THAT(RawJwtHmacKeyManager().ValidateKeyFormat(key_format), IsOk()); key_format.set_key_size(33); EXPECT_THAT(RawJwtHmacKeyManager().ValidateKeyFormat(key_format), IsOk()); key_format.set_key_size(31); EXPECT_THAT(RawJwtHmacKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(RawJwtHmacKeyManagerTest, ValidateHS384KeyFormat) { JwtHmacKeyFormat key_format; key_format.set_algorithm(JwtHmacAlgorithm::HS384); key_format.set_key_size(48); EXPECT_THAT(RawJwtHmacKeyManager().ValidateKeyFormat(key_format), IsOk()); key_format.set_key_size(49); EXPECT_THAT(RawJwtHmacKeyManager().ValidateKeyFormat(key_format), IsOk()); key_format.set_key_size(47); EXPECT_THAT(RawJwtHmacKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(RawJwtHmacKeyManagerTest, ValidateHS512KeyFormat) { JwtHmacKeyFormat key_format; key_format.set_algorithm(JwtHmacAlgorithm::HS512); key_format.set_key_size(64); EXPECT_THAT(RawJwtHmacKeyManager().ValidateKeyFormat(key_format), IsOk()); key_format.set_key_size(65); EXPECT_THAT(RawJwtHmacKeyManager().ValidateKeyFormat(key_format), IsOk()); key_format.set_key_size(63); EXPECT_THAT(RawJwtHmacKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(RawJwtHmacKeyManagerTest, Sha1IsInvalidKeyFormat) { JwtHmacKeyFormat key_format; key_format.set_algorithm(JwtHmacAlgorithm::HS_UNKNOWN); key_format.set_key_size(32); EXPECT_THAT(RawJwtHmacKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(RawJwtHmacKeyManagerTest, CreateKeyWithSha256) { JwtHmacKeyFormat key_format; key_format.set_key_size(32); key_format.set_algorithm(JwtHmacAlgorithm::HS256); auto hmac_key_or = RawJwtHmacKeyManager().CreateKey(key_format); ASSERT_THAT(hmac_key_or, IsOk()); EXPECT_THAT(hmac_key_or.value().version(), Eq(0)); EXPECT_THAT(hmac_key_or.value().algorithm(), Eq(key_format.algorithm())); EXPECT_THAT(hmac_key_or.value().key_value(), SizeIs(key_format.key_size())); EXPECT_THAT(RawJwtHmacKeyManager().ValidateKey(hmac_key_or.value()), IsOk()); } TEST(RawJwtHmacKeyManagerTest, CreateKeyWithSha384) { JwtHmacKeyFormat key_format; key_format.set_key_size(48); key_format.set_algorithm(JwtHmacAlgorithm::HS384); auto hmac_key_or = RawJwtHmacKeyManager().CreateKey(key_format); ASSERT_THAT(hmac_key_or, IsOk()); EXPECT_THAT(hmac_key_or.value().version(), Eq(0)); EXPECT_THAT(hmac_key_or.value().algorithm(), Eq(key_format.algorithm())); EXPECT_THAT(hmac_key_or.value().key_value(), SizeIs(key_format.key_size())); EXPECT_THAT(RawJwtHmacKeyManager().ValidateKey(hmac_key_or.value()), IsOk()); } TEST(RawJwtHmacKeyManagerTest, CreateKeyWithSha512) { JwtHmacKeyFormat key_format; key_format.set_key_size(64); key_format.set_algorithm(JwtHmacAlgorithm::HS512); auto key_or = RawJwtHmacKeyManager().CreateKey(key_format); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().version(), Eq(0)); EXPECT_THAT(key_or.value().algorithm(), Eq(key_format.algorithm())); EXPECT_THAT(key_or.value().key_value(), SizeIs(key_format.key_size())); EXPECT_THAT(RawJwtHmacKeyManager().ValidateKey(key_or.value()), IsOk()); } TEST(RawJwtHmacKeyManagerTest, ValidateHS256Key) { JwtHmacKey key; key.set_version(0); key.set_algorithm(JwtHmacAlgorithm::HS256); key.set_key_value("0123456789abcdef0123456789abcdef"); // 32 bytes EXPECT_THAT(RawJwtHmacKeyManager().ValidateKey(key), IsOk()); key.set_key_value("0123456789abcdef0123456789abcde"); // 31 bytes EXPECT_THAT(RawJwtHmacKeyManager().ValidateKey(key), Not(IsOk())); } TEST(RawJwtHmacKeyManagerTest, ValidateHS384Key) { JwtHmacKey key; key.set_version(0); key.set_algorithm(JwtHmacAlgorithm::HS384); key.set_key_value( "0123456789abcdef0123456789abcdef0123456789abcdef"); // 48 bytes EXPECT_THAT(RawJwtHmacKeyManager().ValidateKey(key), IsOk()); key.set_key_value( "0123456789abcdef0123456789abcdef0123456789abcde"); // 47 bytes EXPECT_THAT(RawJwtHmacKeyManager().ValidateKey(key), Not(IsOk())); } TEST(RawJwtHmacKeyManagerTest, ValidateHS512Key) { JwtHmacKey key; key.set_version(0); key.set_algorithm(JwtHmacAlgorithm::HS512); key.set_key_value( // 64 bytes "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"); key.set_key_value( // 63 bytes "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde"); EXPECT_THAT(RawJwtHmacKeyManager().ValidateKey(key), Not(IsOk())); } TEST(RawJwtHmacKeyManagerTest, Sha1KeyIsInvalid) { JwtHmacKey key; key.set_version(0); key.set_algorithm(JwtHmacAlgorithm::HS_UNKNOWN); key.set_key_value("0123456789abcdef0123456789abcdef"); EXPECT_THAT(RawJwtHmacKeyManager().ValidateKey(key), Not(IsOk())); } TEST(RawJwtHmacKeyManagerTest, DeriveKeyIsNotImplemented) { JwtHmacKeyFormat format; format.set_key_size(32); format.set_version(0); format.set_algorithm(JwtHmacAlgorithm::HS256); IstreamInputStream input_stream{ absl::make_unique("0123456789abcdef0123456789abcdef")}; StatusOr key_or = RawJwtHmacKeyManager().DeriveKey(format, &input_stream); EXPECT_THAT(key_or.status(), StatusIs(absl::StatusCode::kUnimplemented)); } TEST(RawJwtHmacKeyManagerTest, GetPrimitiveFromNewKeysetHandle) { Registry::Reset(); ASSERT_THAT(MacConfig::Register(), IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); JwtHmacKeyFormat key_format; key_format.set_algorithm(JwtHmacAlgorithm::HS256); key_format.set_key_size(32); KeyTemplate key_template; key_template.set_type_url( "type.googleapis.com/google.crypto.tink.JwtHmacKey"); key_template.set_output_prefix_type(OutputPrefixType::RAW); key_format.SerializeToString(key_template.mutable_value()); auto handle_result = KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()); ASSERT_TRUE(handle_result.ok()) << handle_result.status(); std::unique_ptr handle = std::move(handle_result.value()); auto mac_result = handle->GetPrimitive(ConfigGlobalRegistry()); ASSERT_TRUE(mac_result.ok()) << mac_result.status(); std::unique_ptr mac = std::move(mac_result.value()); auto tag_or = mac->ComputeMac("some plaintext"); ASSERT_THAT(tag_or, IsOk()); EXPECT_THAT(mac->VerifyMac(tag_or.value(), "some plaintext"), IsOk()); } } // namespace } // namespace jwt_internal } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/raw_jwt_rsa_ssa_pkcs1_sign_key_manager.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/raw_jwt_rsa_ssa_pkcs1_sign_key_manager.h" #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/internal/bn_util.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/jwt/internal/raw_jwt_rsa_ssa_pkcs1_verify_key_manager.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/signature/sig_util.h" #include "tink/subtle/rsa_ssa_pkcs1_sign_boringssl.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/common.pb.h" #include "proto/jwt_rsa_ssa_pkcs1.pb.h" namespace crypto { namespace tink { using crypto::tink::util::Enums; using crypto::tink::util::Status; using crypto::tink::util::StatusOr; using google::crypto::tink::JwtRsaSsaPkcs1KeyFormat; using google::crypto::tink::JwtRsaSsaPkcs1PrivateKey; using ::google::crypto::tink::JwtRsaSsaPkcs1PublicKey; namespace { JwtRsaSsaPkcs1PrivateKey RsaPrivateKeySubtleToProto( const internal::RsaPrivateKey& private_key) { JwtRsaSsaPkcs1PrivateKey key_proto; key_proto.set_version(RawJwtRsaSsaPkcs1SignKeyManager().get_version()); key_proto.set_d(std::string(util::SecretDataAsStringView(private_key.d))); key_proto.set_p(std::string(util::SecretDataAsStringView(private_key.p))); key_proto.set_q(std::string(util::SecretDataAsStringView(private_key.q))); key_proto.set_dp(std::string(util::SecretDataAsStringView(private_key.dp))); key_proto.set_dq(std::string(util::SecretDataAsStringView(private_key.dq))); key_proto.set_crt(std::string(util::SecretDataAsStringView(private_key.crt))); JwtRsaSsaPkcs1PublicKey* public_key_proto = key_proto.mutable_public_key(); public_key_proto->set_version( RawJwtRsaSsaPkcs1SignKeyManager().get_version()); public_key_proto->set_n(private_key.n); public_key_proto->set_e(private_key.e); return key_proto; } internal::RsaPrivateKey RsaPrivateKeyProtoToSubtle( const JwtRsaSsaPkcs1PrivateKey& key_proto) { internal::RsaPrivateKey key; key.n = key_proto.public_key().n(); key.e = key_proto.public_key().e(); key.d = util::SecretDataFromStringView(key_proto.d()); key.p = util::SecretDataFromStringView(key_proto.p()); key.q = util::SecretDataFromStringView(key_proto.q()); key.dp = util::SecretDataFromStringView(key_proto.dp()); key.dq = util::SecretDataFromStringView(key_proto.dq()); key.crt = util::SecretDataFromStringView(key_proto.crt()); return key; } } // namespace StatusOr RawJwtRsaSsaPkcs1SignKeyManager::CreateKey( const JwtRsaSsaPkcs1KeyFormat& jwt_rsa_ssa_pkcs1_key_format) const { StatusOr> e = internal::StringToBignum(jwt_rsa_ssa_pkcs1_key_format.public_exponent()); if (!e.ok()) { return e.status(); } internal::RsaPrivateKey private_key; internal::RsaPublicKey public_key; Status status = internal::NewRsaKeyPair( jwt_rsa_ssa_pkcs1_key_format.modulus_size_in_bits(), e->get(), &private_key, &public_key); if (!status.ok()) { return status; } JwtRsaSsaPkcs1PrivateKey key_proto = RsaPrivateKeySubtleToProto(private_key); JwtRsaSsaPkcs1PublicKey* public_key_proto = key_proto.mutable_public_key(); public_key_proto->set_algorithm(jwt_rsa_ssa_pkcs1_key_format.algorithm()); return key_proto; } StatusOr> RawJwtRsaSsaPkcs1SignKeyManager::PublicKeySignFactory::Create( const JwtRsaSsaPkcs1PrivateKey& private_key) const { internal::RsaPrivateKey key = RsaPrivateKeyProtoToSubtle(private_key); util::StatusOr hash = RawJwtRsaSsaPkcs1VerifyKeyManager::HashForPkcs1Algorithm( private_key.public_key().algorithm()); if (!hash.ok()) { return hash.status(); } internal::RsaSsaPkcs1Params params; params.hash_type = Enums::ProtoToSubtle(*hash); util::StatusOr> signer = subtle::RsaSsaPkcs1SignBoringSsl::New(key, params); if (!signer.ok()) return signer.status(); // To check that the key is correct, we sign a test message with private key // and verify with public key. util::StatusOr> verifier = RawJwtRsaSsaPkcs1VerifyKeyManager().GetPrimitive( private_key.public_key()); if (!verifier.ok()) return verifier.status(); util::Status sign_verify_result = SignAndVerify(signer->get(), verifier->get()); if (!sign_verify_result.ok()) { return util::Status(absl::StatusCode::kInternal, "security bug: signing with private key followed by " "verifying with public key failed"); } return signer; } Status RawJwtRsaSsaPkcs1SignKeyManager::ValidateKey( const JwtRsaSsaPkcs1PrivateKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; return RawJwtRsaSsaPkcs1VerifyKeyManager().ValidateKey(key.public_key()); } Status RawJwtRsaSsaPkcs1SignKeyManager::ValidateKeyFormat( const JwtRsaSsaPkcs1KeyFormat& key_format) const { Status modulus_status = internal::ValidateRsaModulusSize(key_format.modulus_size_in_bits()); if (!modulus_status.ok()) { return modulus_status; } Status exponent_status = internal::ValidateRsaPublicExponent(key_format.public_exponent()); if (!exponent_status.ok()) { return exponent_status; } return RawJwtRsaSsaPkcs1VerifyKeyManager().ValidateAlgorithm( key_format.algorithm()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/raw_jwt_rsa_ssa_pkcs1_sign_key_manager.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_RAW_JWT_RSA_SSA_PKCS1_SIGN_KEY_MANAGER_H_ #define TINK_JWT_INTERNAL_RAW_JWT_RSA_SSA_PKCS1_SIGN_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_sign.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/jwt_rsa_ssa_pkcs1.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class RawJwtRsaSsaPkcs1SignKeyManager : public PrivateKeyTypeManager< google::crypto::tink::JwtRsaSsaPkcs1PrivateKey, google::crypto::tink::JwtRsaSsaPkcs1KeyFormat, google::crypto::tink::JwtRsaSsaPkcs1PublicKey, List> { public: class PublicKeySignFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::JwtRsaSsaPkcs1PrivateKey& private_key) const override; }; RawJwtRsaSsaPkcs1SignKeyManager() : PrivateKeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::JwtRsaSsaPkcs1PrivateKey& key) const override; crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::JwtRsaSsaPkcs1KeyFormat& key_format) const override; crypto::tink::util::StatusOr CreateKey(const google::crypto::tink::JwtRsaSsaPkcs1KeyFormat& key_format) const override; crypto::tink::util::StatusOr GetPublicKey(const google::crypto::tink::JwtRsaSsaPkcs1PrivateKey& private_key) const override { return private_key.public_key(); } internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: const std::string key_type_ = absl::StrCat( kTypeGoogleapisCom, google::crypto::tink::JwtRsaSsaPkcs1PrivateKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_RAW_JWT_RSA_SSA_PKCS1_SIGN_KEY_MANAGER_H_ ================================================ FILE: cc/jwt/internal/raw_jwt_rsa_ssa_pkcs1_sign_key_manager_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/raw_jwt_rsa_ssa_pkcs1_sign_key_manager.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_set.h" #include "openssl/rsa.h" #include "tink/internal/bn_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/jwt/internal/raw_jwt_rsa_ssa_pkcs1_verify_key_manager.h" #include "tink/public_key_sign.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/rsa_ssa_pkcs1_verify_boringssl.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/jwt_rsa_ssa_pkcs1.pb.h" #include "proto/rsa_ssa_pkcs1.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::subtle::RsaSsaPkcs1VerifyBoringSsl; using ::crypto::tink::test::IsOk; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::JwtRsaSsaPkcs1Algorithm; using ::google::crypto::tink::JwtRsaSsaPkcs1KeyFormat; using ::google::crypto::tink::JwtRsaSsaPkcs1PrivateKey; using ::google::crypto::tink::JwtRsaSsaPkcs1PublicKey; using ::google::crypto::tink::KeyData; using ::testing::Eq; using ::testing::Not; using ::testing::SizeIs; TEST(JwtRsaSsaPkcsSignKeyManagerTest, Basic) { EXPECT_THAT(RawJwtRsaSsaPkcs1SignKeyManager().get_version(), Eq(0)); EXPECT_THAT(RawJwtRsaSsaPkcs1SignKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PRIVATE)); EXPECT_THAT( RawJwtRsaSsaPkcs1SignKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PrivateKey")); } JwtRsaSsaPkcs1KeyFormat CreateKeyFormat(JwtRsaSsaPkcs1Algorithm algorithm, int modulus_size_in_bits, int public_exponent) { JwtRsaSsaPkcs1KeyFormat key_format; key_format.set_algorithm(algorithm); key_format.set_modulus_size_in_bits(modulus_size_in_bits); internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), public_exponent); key_format.set_public_exponent( internal::BignumToString(e.get(), BN_num_bytes(e.get())).value()); return key_format; } TEST(JwtRsaSsaPkcs1SignKeyManagerTest, ValidateKeyFormatRs256) { JwtRsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(JwtRsaSsaPkcs1Algorithm::RS256, 3072, RSA_F4); EXPECT_THAT(RawJwtRsaSsaPkcs1SignKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(JwtRsaSsaPkcs1SignKeyManagerTest, ValidateKeyFormatRs384) { JwtRsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(JwtRsaSsaPkcs1Algorithm::RS384, 3072, RSA_F4); EXPECT_THAT(RawJwtRsaSsaPkcs1SignKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(JwtRsaSsaPkcs1SignKeyManagerTest, ValidateKeyFormatRs512) { JwtRsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(JwtRsaSsaPkcs1Algorithm::RS512, 3072, RSA_F4); EXPECT_THAT(RawJwtRsaSsaPkcs1SignKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(JwtRsaSsaPkcs1SignKeyManagerTest, KeyFormatWithUnknownAlgorithmIsInvalid) { JwtRsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(JwtRsaSsaPkcs1Algorithm::RS_UNKNOWN, 3072, RSA_F4); EXPECT_THAT(RawJwtRsaSsaPkcs1SignKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(JwtRsaSsaPkcs1SignKeyManagerTest, KeyFormatWithSmallModulusIsInvalid) { JwtRsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(JwtRsaSsaPkcs1Algorithm::RS256, 2047, RSA_F4); EXPECT_THAT(RawJwtRsaSsaPkcs1SignKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } // Checks whether given key is compatible with the given format. void CheckNewKey(const JwtRsaSsaPkcs1PrivateKey& private_key, const JwtRsaSsaPkcs1KeyFormat& key_format) { RawJwtRsaSsaPkcs1SignKeyManager key_manager; JwtRsaSsaPkcs1PublicKey public_key = private_key.public_key(); EXPECT_EQ(0, private_key.version()); EXPECT_TRUE(private_key.has_public_key()); EXPECT_EQ(0, public_key.version()); EXPECT_GT(public_key.n().length(), 0); EXPECT_GT(public_key.e().length(), 0); EXPECT_EQ(public_key.algorithm(), key_format.algorithm()); EXPECT_EQ(key_format.public_exponent(), public_key.e()); util::StatusOr> n = internal::StringToBignum(public_key.n()); ASSERT_THAT(n, IsOk()); util::StatusOr> d = internal::StringToBignum(private_key.d()); ASSERT_THAT(d, IsOk()); util::StatusOr> p = internal::StringToBignum(private_key.p()); ASSERT_THAT(p, IsOk()); util::StatusOr> q = internal::StringToBignum(private_key.q()); ASSERT_THAT(q, IsOk()); util::StatusOr> dp = internal::StringToBignum(private_key.dp()); ASSERT_THAT(dp, IsOk()); util::StatusOr> dq = internal::StringToBignum(private_key.dq()); ASSERT_THAT(dq, IsOk()); internal::SslUniquePtr ctx(BN_CTX_new()); // Check n = p * q. auto n_calc = internal::SslUniquePtr(BN_new()); EXPECT_TRUE(BN_mul(n_calc.get(), p->get(), q->get(), ctx.get())); EXPECT_EQ(BN_cmp(n_calc.get(), n->get()), 0); // Check n size >= modulus_size_in_bits bit. EXPECT_GE(BN_num_bits(n->get()), key_format.modulus_size_in_bits()); // dp = d mod (p - 1) auto pm1 = internal::SslUniquePtr(BN_dup(p->get())); EXPECT_TRUE(BN_sub_word(pm1.get(), 1)); auto dp_calc = internal::SslUniquePtr(BN_new()); EXPECT_TRUE(BN_mod(dp_calc.get(), d->get(), pm1.get(), ctx.get())); EXPECT_EQ(BN_cmp(dp_calc.get(), dp->get()), 0); // dq = d mod (q - 1) auto qm1 = internal::SslUniquePtr(BN_dup(q->get())); EXPECT_TRUE(BN_sub_word(qm1.get(), 1)); auto dq_calc = internal::SslUniquePtr(BN_new()); EXPECT_TRUE(BN_mod(dq_calc.get(), d->get(), qm1.get(), ctx.get())); EXPECT_EQ(BN_cmp(dq_calc.get(), dq->get()), 0); } TEST(JwtRsaSsaPkcs1SignKeyManagerTest, CreateRs256Key) { JwtRsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(JwtRsaSsaPkcs1Algorithm::RS256, 3072, RSA_F4); StatusOr private_key = RawJwtRsaSsaPkcs1SignKeyManager().CreateKey(key_format); ASSERT_THAT(private_key, IsOk()); EXPECT_THAT(RawJwtRsaSsaPkcs1SignKeyManager().ValidateKey(*private_key), IsOk()); CheckNewKey(*private_key, key_format); } TEST(JwtRsaSsaPkcs1SignKeyManagerTest, CreateSmallRs256Key) { JwtRsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(JwtRsaSsaPkcs1Algorithm::RS256, 2048, RSA_F4); StatusOr private_key = RawJwtRsaSsaPkcs1SignKeyManager().CreateKey(key_format); ASSERT_THAT(private_key, IsOk()); EXPECT_THAT(RawJwtRsaSsaPkcs1SignKeyManager().ValidateKey(*private_key), IsOk()); CheckNewKey(*private_key, key_format); } TEST(JwtRsaSsaPkcs1SignKeyManagerTest, CreateKeyLargeRs512Key) { JwtRsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(JwtRsaSsaPkcs1Algorithm::RS512, 4096, RSA_F4); StatusOr private_key = RawJwtRsaSsaPkcs1SignKeyManager().CreateKey(key_format); ASSERT_THAT(private_key, IsOk()); EXPECT_THAT(RawJwtRsaSsaPkcs1SignKeyManager().ValidateKey(*private_key), IsOk()); CheckNewKey(*private_key, key_format); } // Check that in a bunch of CreateKey calls all generated primes are distinct. TEST(JwtRsaSsaPkcs1SignKeyManagerTest, CreateKeyAlwaysNewRsaPair) { absl::flat_hash_set keys; // This test takes about a second per key. JwtRsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(JwtRsaSsaPkcs1Algorithm::RS256, 2048, RSA_F4); int num_generated_keys = 5; for (int i = 0; i < num_generated_keys; ++i) { StatusOr key = RawJwtRsaSsaPkcs1SignKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); keys.insert(key->p()); keys.insert(key->q()); } EXPECT_THAT(keys, SizeIs(2 * num_generated_keys)); } TEST(JwtRsaSsaPkcs1SignKeyManagerTest, GetPublicKey) { JwtRsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(JwtRsaSsaPkcs1Algorithm::RS256, 2048, RSA_F4); StatusOr key = RawJwtRsaSsaPkcs1SignKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); StatusOr public_key = RawJwtRsaSsaPkcs1SignKeyManager().GetPublicKey(*key); ASSERT_THAT(public_key, IsOk()); EXPECT_THAT(public_key->version(), Eq(key->public_key().version())); EXPECT_THAT(public_key->algorithm(), Eq(key->public_key().algorithm())); EXPECT_THAT(public_key->n(), Eq(key->public_key().n())); EXPECT_THAT(public_key->e(), Eq(key->public_key().e())); } TEST(JwtRsaSsaPkcs1SignKeyManagerTest, Create) { JwtRsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(JwtRsaSsaPkcs1Algorithm::RS256, 3072, RSA_F4); StatusOr key = RawJwtRsaSsaPkcs1SignKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); util::StatusOr> signer = RawJwtRsaSsaPkcs1SignKeyManager().GetPrimitive(*key); ASSERT_THAT(signer, IsOk()); util::StatusOr> direct_verifier = subtle::RsaSsaPkcs1VerifyBoringSsl::New( {key->public_key().n(), key->public_key().e()}, {subtle::HashType::SHA256}); ASSERT_THAT(direct_verifier, IsOk()); std::string message = "Some message"; util::StatusOr sig = (*signer)->Sign(message); ASSERT_THAT(sig, IsOk()); EXPECT_THAT((*direct_verifier)->Verify(*sig, message), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/raw_jwt_rsa_ssa_pkcs1_verify_key_manager.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/raw_jwt_rsa_ssa_pkcs1_verify_key_manager.h" #include #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/internal/bn_util.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/public_key_verify.h" #include "tink/subtle/rsa_ssa_pkcs1_verify_boringssl.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/jwt_rsa_ssa_pkcs1.pb.h" namespace crypto { namespace tink { using crypto::tink::util::Enums; using crypto::tink::util::Status; using crypto::tink::util::StatusOr; using google::crypto::tink::HashType; using google::crypto::tink::JwtRsaSsaPkcs1Algorithm; using google::crypto::tink::JwtRsaSsaPkcs1PublicKey; StatusOr> RawJwtRsaSsaPkcs1VerifyKeyManager::PublicKeyVerifyFactory::Create( const JwtRsaSsaPkcs1PublicKey& jwt_rsa_ssa_pkcs1_public_key) const { internal::RsaPublicKey rsa_pub_key; rsa_pub_key.n = jwt_rsa_ssa_pkcs1_public_key.n(); rsa_pub_key.e = jwt_rsa_ssa_pkcs1_public_key.e(); util::StatusOr hash = RawJwtRsaSsaPkcs1VerifyKeyManager::HashForPkcs1Algorithm( jwt_rsa_ssa_pkcs1_public_key.algorithm()); if (!hash.ok()) { return hash.status(); } internal::RsaSsaPkcs1Params params; params.hash_type = Enums::ProtoToSubtle(*hash); util::StatusOr> verify = subtle::RsaSsaPkcs1VerifyBoringSsl::New(rsa_pub_key, params); if (!verify.ok()) return verify.status(); return {std::move(*verify)}; } Status RawJwtRsaSsaPkcs1VerifyKeyManager::ValidateKey( const JwtRsaSsaPkcs1PublicKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; StatusOr> n = internal::StringToBignum(key.n()); if (!n.ok()) { return n.status(); } Status modulus_status = internal::ValidateRsaModulusSize(BN_num_bits(n->get())); if (!modulus_status.ok()) { return modulus_status; } Status exponent_status = internal::ValidateRsaPublicExponent(key.e()); if (!exponent_status.ok()) { return exponent_status; } return ValidateAlgorithm(key.algorithm()); } Status RawJwtRsaSsaPkcs1VerifyKeyManager::ValidateAlgorithm( const JwtRsaSsaPkcs1Algorithm& algorithm) { switch (algorithm) { case JwtRsaSsaPkcs1Algorithm::RS256: case JwtRsaSsaPkcs1Algorithm::RS384: case JwtRsaSsaPkcs1Algorithm::RS512: return util::OkStatus(); default: return Status(absl::StatusCode::kInvalidArgument, "Unsupported RSA SSA PKCS1 Algorithm"); } return util::OkStatus(); } StatusOr RawJwtRsaSsaPkcs1VerifyKeyManager::HashForPkcs1Algorithm( const JwtRsaSsaPkcs1Algorithm& algorithm) { switch (algorithm) { case JwtRsaSsaPkcs1Algorithm::RS256: return HashType::SHA256; case JwtRsaSsaPkcs1Algorithm::RS384: return HashType::SHA384; case JwtRsaSsaPkcs1Algorithm::RS512: return HashType::SHA512; default: return Status(absl::StatusCode::kInvalidArgument, "Unsupported RSA SSA PKCS1 Algorithm"); } } } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/raw_jwt_rsa_ssa_pkcs1_verify_key_manager.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_RAW_JWT_RSA_SSA_PKCS1_VERIFY_KEY_MANAGER_H_ #define TINK_JWT_INTERNAL_RAW_JWT_RSA_SSA_PKCS1_VERIFY_KEY_MANAGER_H_ #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_verify.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/common.pb.h" #include "proto/jwt_rsa_ssa_pkcs1.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class RawJwtRsaSsaPkcs1VerifyKeyManager : public KeyTypeManager> { public: class PublicKeyVerifyFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::JwtRsaSsaPkcs1PublicKey& jwt_rsa_ssa_pkcs1_public_key) const override; }; RawJwtRsaSsaPkcs1VerifyKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PUBLIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::JwtRsaSsaPkcs1PublicKey& key) const override; internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: static crypto::tink::util::Status ValidateAlgorithm( const google::crypto::tink::JwtRsaSsaPkcs1Algorithm& algorithm); static crypto::tink::util::StatusOr HashForPkcs1Algorithm( const google::crypto::tink::JwtRsaSsaPkcs1Algorithm& algorithm); const std::string key_type_ = absl::StrCat( kTypeGoogleapisCom, google::crypto::tink::JwtRsaSsaPkcs1PublicKey().GetTypeName()); friend class RawJwtRsaSsaPkcs1SignKeyManager; }; } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_RAW_JWT_RSA_SSA_PKCS1_VERIFY_KEY_MANAGER_H_ ================================================ FILE: cc/jwt/internal/raw_jwt_rsa_ssa_pkcs1_verify_key_manager_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/raw_jwt_rsa_ssa_pkcs1_verify_key_manager.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "openssl/bn.h" #include "openssl/rsa.h" #include "tink/internal/bn_util.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/jwt/internal/raw_jwt_rsa_ssa_pkcs1_sign_key_manager.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/rsa_ssa_pkcs1_sign_boringssl.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/jwt_rsa_ssa_pkcs1.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::JwtRsaSsaPkcs1Algorithm; using ::google::crypto::tink::JwtRsaSsaPkcs1KeyFormat; using ::google::crypto::tink::JwtRsaSsaPkcs1PrivateKey; using ::google::crypto::tink::JwtRsaSsaPkcs1PublicKey; using ::google::crypto::tink::KeyData; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::Not; namespace { TEST(RawJwtRsaSsaPkcs1VerifyKeyManagerTest, Basics) { EXPECT_THAT(RawJwtRsaSsaPkcs1VerifyKeyManager().get_version(), Eq(0)); EXPECT_THAT(RawJwtRsaSsaPkcs1VerifyKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PUBLIC)); EXPECT_THAT( RawJwtRsaSsaPkcs1VerifyKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PublicKey")); } TEST(RawJwtRsaSsaPkcs1VerifyKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(RawJwtRsaSsaPkcs1VerifyKeyManager().ValidateKey( JwtRsaSsaPkcs1PublicKey()), Not(IsOk())); } JwtRsaSsaPkcs1KeyFormat CreateKeyFormat(JwtRsaSsaPkcs1Algorithm algorithm, int modulus_size_in_bits, int public_exponent) { JwtRsaSsaPkcs1KeyFormat key_format; key_format.set_algorithm(algorithm); key_format.set_modulus_size_in_bits(modulus_size_in_bits); internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), public_exponent); key_format.set_public_exponent( internal::BignumToString(e.get(), BN_num_bytes(e.get())).value()); return key_format; } JwtRsaSsaPkcs1KeyFormat ValidKeyFormat() { return CreateKeyFormat(JwtRsaSsaPkcs1Algorithm::RS256, 3072, RSA_F4); } JwtRsaSsaPkcs1PrivateKey CreateValidPrivateKey() { return RawJwtRsaSsaPkcs1SignKeyManager().CreateKey(ValidKeyFormat()).value(); } JwtRsaSsaPkcs1PublicKey CreateValidPublicKey() { return RawJwtRsaSsaPkcs1SignKeyManager() .GetPublicKey(CreateValidPrivateKey()) .value(); } // Checks that a public key generaed by the SignKeyManager is considered valid. TEST(RawJwtRsaSsaPkcs1VerifyKeyManagerTest, PublicKeyValid) { JwtRsaSsaPkcs1PublicKey key = CreateValidPublicKey(); EXPECT_THAT(RawJwtRsaSsaPkcs1VerifyKeyManager().ValidateKey(key), IsOk()); } TEST(RawJwtRsaSsaPkcs1VerifyKeyManagerTest, PublicKeyWrongVersion) { JwtRsaSsaPkcs1PublicKey key = CreateValidPublicKey(); key.set_version(1); EXPECT_THAT(RawJwtRsaSsaPkcs1VerifyKeyManager().ValidateKey(key), Not(IsOk())); } TEST(RawJwtRsaSsaPkcs1VerifyKeyManagerTest, KeyWithUnkownAlgorithmInvalid) { JwtRsaSsaPkcs1PublicKey key = CreateValidPublicKey(); key.set_algorithm(JwtRsaSsaPkcs1Algorithm::RS_UNKNOWN); EXPECT_THAT(RawJwtRsaSsaPkcs1VerifyKeyManager().ValidateKey(key), Not(IsOk())); } TEST(RawJwtRsaSsaPkcs1VerifyKeyManagerTest, KeyFormatWithSmallModulusInvalid) { JwtRsaSsaPkcs1PublicKey key = CreateValidPublicKey(); key.set_n("\x23"); key.set_e("\x3"); EXPECT_THAT(RawJwtRsaSsaPkcs1VerifyKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("only modulus size >= 2048"))); } TEST(JwtRsaSsaPkcs1SignKeyManagerTest, Create) { JwtRsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(JwtRsaSsaPkcs1Algorithm::RS256, 3072, RSA_F4); StatusOr private_key = RawJwtRsaSsaPkcs1SignKeyManager().CreateKey(key_format); ASSERT_THAT(private_key, IsOk()); StatusOr public_key = RawJwtRsaSsaPkcs1SignKeyManager().GetPublicKey(*private_key); ASSERT_THAT(public_key, IsOk()); internal::RsaPrivateKey private_key_subtle; private_key_subtle.n = private_key->public_key().n(); private_key_subtle.e = private_key->public_key().e(); private_key_subtle.d = util::SecretDataFromStringView(private_key->d()); private_key_subtle.p = util::SecretDataFromStringView(private_key->p()); private_key_subtle.q = util::SecretDataFromStringView(private_key->q()); private_key_subtle.dp = util::SecretDataFromStringView(private_key->dp()); private_key_subtle.dq = util::SecretDataFromStringView(private_key->dq()); private_key_subtle.crt = util::SecretDataFromStringView(private_key->crt()); util::StatusOr> direct_signer = subtle::RsaSsaPkcs1SignBoringSsl::New( private_key_subtle, {crypto::tink::subtle::HashType::SHA256}); util::StatusOr> verifier = RawJwtRsaSsaPkcs1VerifyKeyManager().GetPrimitive( *public_key); ASSERT_THAT(verifier, IsOk()); std::string message = "Some message"; util::StatusOr sig = (*direct_signer)->Sign(message); ASSERT_THAT(sig, IsOk()); EXPECT_THAT((*verifier)->Verify(*sig, message), IsOk()); } TEST(RawJwtRsaSsaPkcs1VerifyKeyManagerTest, NistTestVector) { // Test vector from // https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Digital-Signatures struct NistTestVector { std::string n; std::string e; std::string message; std::string signature; JwtRsaSsaPkcs1Algorithm algorithm; }; const NistTestVector nist_test_vector{ absl::HexStringToBytes( "c9548608087bed6be0a4623b9d849aa0b4b4b6114ad0a7d82578076ceefe26ce48d1" "448e16d69963510e1e5fc658f3cf8f32a489b62d93fec1cdea6e1dde3feba04bb6a0" "34518d83fd6138ea999982ab95d6a03517688ab6f8411c4a96b3e79d4141b8f68338" "a9baa99f4e2c7845b573981061c5fd29d5fc21833ff1b030b2deb651e51a291168e2" "b45ab4202dcd97b891925c75338e0e648d9d9ad325c10884e1fcdccc1c547b4a9c36" "aef939e8802b62405d6e3d358ffa88f206b976b87f8b12b827b0ee7823f9d1955f47" "f8678f7843b4cd03777e46717060e82bf149b36d4cf3d0bc7e4d0effde51a72f4ced" "8e8e5b11bdb135825ff08873e2f776929abb"), absl::HexStringToBytes("3c7bf9"), absl::HexStringToBytes( "bf082fa4b79f32849e8fae692696fc978ccb648c6e278d9bde4338d7b4632e3228b4" "77e6a0d2cd14c68d51abdeed7c8c577457ec9fa2eff93cbf03c019d4014e1dfb3115" "02d82f9265689e2d19f91b61c17a701c9ef50a69a55aae4cd57e67edc763c3f987ba" "3e46a2a6ffb680c3c25df46716e61228c832419e9f43916a4959"), absl::HexStringToBytes( "621120a71ff2a182dd2997beb2480f54be516b79a4c202d1d6f59270f8e4d4dbd625" "ac52fe0e49c5fd69dc0d15fb19ec58c9312a8161a61cb878abcb11399937f28ff080" "3877c239ce0b7c4cbc1e23eca22746b071b2716475424c12944660b929b6240aebe8" "47fcb94f63d212f3aa538515dc061e9810fdb0adeb374d0f69d24fd52c94e42668a4" "8fc0a57819952a40efb732cfa08b3d2b371780aea97be34efb5239994d7ee7c6ab91" "34b76711e76813ad5f5c3a5c95399e907650534dbfafec900c21be1308ddff6eda52" "5f35e4fb3d275de46250ea1e4b96b60bd125b85f6c52b5419a725cd69b10cefd0901" "abe7f9e15940594cf811e34c60f38768244c"), JwtRsaSsaPkcs1Algorithm::RS256}; JwtRsaSsaPkcs1PublicKey key; key.set_algorithm(JwtRsaSsaPkcs1Algorithm::RS256); key.set_version(0); key.set_n(nist_test_vector.n); key.set_e(nist_test_vector.e); util::StatusOr> verifier = RawJwtRsaSsaPkcs1VerifyKeyManager().GetPrimitive(key); EXPECT_THAT(verifier, IsOk()); EXPECT_THAT( (*verifier)->Verify(nist_test_vector.signature, nist_test_vector.message), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/raw_jwt_rsa_ssa_pss_sign_key_manager.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/raw_jwt_rsa_ssa_pss_sign_key_manager.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/internal/bn_util.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/jwt/internal/raw_jwt_rsa_ssa_pss_verify_key_manager.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/signature/sig_util.h" #include "tink/subtle/rsa_ssa_pss_sign_boringssl.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/common.pb.h" #include "proto/jwt_rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::crypto::tink::util::Enums; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::HashType; using ::google::crypto::tink::JwtRsaSsaPssAlgorithm; using ::google::crypto::tink::JwtRsaSsaPssKeyFormat; using ::google::crypto::tink::JwtRsaSsaPssPrivateKey; using ::google::crypto::tink::JwtRsaSsaPssPublicKey; namespace { std::unique_ptr RsaPrivateKeySubtleToProto( const internal::RsaPrivateKey& private_key) { auto key_proto = absl::make_unique(); key_proto->set_version(RawJwtRsaSsaPssSignKeyManager().get_version()); key_proto->set_d(std::string(util::SecretDataAsStringView(private_key.d))); key_proto->set_p(std::string(util::SecretDataAsStringView(private_key.p))); key_proto->set_q(std::string(util::SecretDataAsStringView(private_key.q))); key_proto->set_dp(std::string(util::SecretDataAsStringView(private_key.dp))); key_proto->set_dq(std::string(util::SecretDataAsStringView(private_key.dq))); key_proto->set_crt( std::string(util::SecretDataAsStringView(private_key.crt))); JwtRsaSsaPssPublicKey* public_key_proto = key_proto->mutable_public_key(); public_key_proto->set_version(RawJwtRsaSsaPssSignKeyManager().get_version()); public_key_proto->set_n(private_key.n); public_key_proto->set_e(private_key.e); return key_proto; } internal::RsaPrivateKey RsaPrivateKeyProtoToSubtle( const JwtRsaSsaPssPrivateKey& key_proto) { internal::RsaPrivateKey key; key.n = key_proto.public_key().n(); key.e = key_proto.public_key().e(); key.d = util::SecretDataFromStringView(key_proto.d()); key.p = util::SecretDataFromStringView(key_proto.p()); key.q = util::SecretDataFromStringView(key_proto.q()); key.dp = util::SecretDataFromStringView(key_proto.dp()); key.dq = util::SecretDataFromStringView(key_proto.dq()); key.crt = util::SecretDataFromStringView(key_proto.crt()); return key; } } // namespace StatusOr RawJwtRsaSsaPssSignKeyManager::CreateKey( const JwtRsaSsaPssKeyFormat& key_format) const { StatusOr> e = internal::StringToBignum(key_format.public_exponent()); if (!e.ok()) { return e.status(); } internal::RsaPrivateKey private_key; internal::RsaPublicKey public_key; util::Status status = internal::NewRsaKeyPair( key_format.modulus_size_in_bits(), e->get(), &private_key, &public_key); if (!status.ok()) { return status; } JwtRsaSsaPssPrivateKey key_proto = std::move(*RsaPrivateKeySubtleToProto(private_key)); key_proto.mutable_public_key()->set_algorithm(key_format.algorithm()); return key_proto; } StatusOr> RawJwtRsaSsaPssSignKeyManager::PublicKeySignFactory::Create( const JwtRsaSsaPssPrivateKey& private_key) const { auto key = RsaPrivateKeyProtoToSubtle(private_key); JwtRsaSsaPssAlgorithm algorithm = private_key.public_key().algorithm(); StatusOr hash = RawJwtRsaSsaPssVerifyKeyManager::HashForPssAlgorithm(algorithm); if (!hash.ok()) { return hash.status(); } StatusOr salt_length = RawJwtRsaSsaPssVerifyKeyManager::SaltLengthForPssAlgorithm(algorithm); if (!salt_length.ok()) { return salt_length.status(); } internal::RsaSsaPssParams params; params.sig_hash = Enums::ProtoToSubtle(*hash); params.mgf1_hash = Enums::ProtoToSubtle(*hash); params.salt_length = *salt_length; util::StatusOr> signer = subtle::RsaSsaPssSignBoringSsl::New(key, params); if (!signer.ok()) return signer.status(); // To check that the key is correct, we sign a test message with private key // and verify with public key. util::StatusOr> verifier = RawJwtRsaSsaPssVerifyKeyManager().GetPrimitive( private_key.public_key()); if (!verifier.ok()) return verifier.status(); util::Status sign_verify_result = SignAndVerify(signer->get(), verifier->get()); if (!sign_verify_result.ok()) { return util::Status(absl::StatusCode::kInternal, "security bug: signing with private key followed by " "verifying with public key failed"); } return signer; } Status RawJwtRsaSsaPssSignKeyManager::ValidateKey( const JwtRsaSsaPssPrivateKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; return RawJwtRsaSsaPssVerifyKeyManager().ValidateKey(key.public_key()); } Status RawJwtRsaSsaPssSignKeyManager::ValidateKeyFormat( const JwtRsaSsaPssKeyFormat& key_format) const { Status modulus_status = internal::ValidateRsaModulusSize(key_format.modulus_size_in_bits()); if (!modulus_status.ok()) { return modulus_status; } Status exponent_status = internal::ValidateRsaPublicExponent(key_format.public_exponent()); if (!exponent_status.ok()) { return exponent_status; } return RawJwtRsaSsaPssVerifyKeyManager::ValidateAlgorithm( key_format.algorithm()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/raw_jwt_rsa_ssa_pss_sign_key_manager.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_RAW_JWT_RSA_SSA_PSS_SIGN_KEY_MANAGER_H_ #define TINK_JWT_INTERNAL_RAW_JWT_RSA_SSA_PSS_SIGN_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_sign.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/jwt_rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class RawJwtRsaSsaPssSignKeyManager : public PrivateKeyTypeManager> { public: class PublicKeySignFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::JwtRsaSsaPssPrivateKey& private_key) const override; }; RawJwtRsaSsaPssSignKeyManager() : PrivateKeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::JwtRsaSsaPssPrivateKey& key) const override; crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::JwtRsaSsaPssKeyFormat& key_format) const override; crypto::tink::util::StatusOr CreateKey(const google::crypto::tink::JwtRsaSsaPssKeyFormat& key_format) const override; crypto::tink::util::StatusOr GetPublicKey(const google::crypto::tink::JwtRsaSsaPssPrivateKey& private_key) const override { return private_key.public_key(); } internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: const std::string key_type_ = absl::StrCat( kTypeGoogleapisCom, google::crypto::tink::JwtRsaSsaPssPrivateKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_RAW_JWT_RSA_SSA_PSS_SIGN_KEY_MANAGER_H_ ================================================ FILE: cc/jwt/internal/raw_jwt_rsa_ssa_pss_sign_key_manager_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/raw_jwt_rsa_ssa_pss_sign_key_manager.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_set.h" #include "openssl/rsa.h" #include "tink/internal/bn_util.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/public_key_sign.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/rsa_ssa_pss_verify_boringssl.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/jwt_rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::subtle::RsaSsaPssVerifyBoringSsl; using ::crypto::tink::test::IsOk; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::JwtRsaSsaPssAlgorithm; using ::google::crypto::tink::JwtRsaSsaPssKeyFormat; using ::google::crypto::tink::JwtRsaSsaPssPrivateKey; using ::google::crypto::tink::JwtRsaSsaPssPublicKey; using ::google::crypto::tink::KeyData; using ::testing::Eq; using ::testing::Gt; using ::testing::Not; using ::testing::SizeIs; TEST(RawJwtRsaSsaPssSignKeyManagerTest, Basic) { EXPECT_THAT(RawJwtRsaSsaPssSignKeyManager().get_version(), Eq(0)); EXPECT_THAT(RawJwtRsaSsaPssSignKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PRIVATE)); EXPECT_THAT( RawJwtRsaSsaPssSignKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPrivateKey")); } JwtRsaSsaPssKeyFormat CreateKeyFormat(JwtRsaSsaPssAlgorithm algorithm, int modulus_size_in_bits, int public_exponent) { JwtRsaSsaPssKeyFormat key_format; key_format.set_algorithm(algorithm); key_format.set_modulus_size_in_bits(modulus_size_in_bits); internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), public_exponent); key_format.set_public_exponent( internal::BignumToString(e.get(), BN_num_bytes(e.get())).value()); return key_format; } TEST(RawJwtRsaSsaPssSignKeyManagerTest, ValidatePs256KeyFormat) { JwtRsaSsaPssKeyFormat key_format = CreateKeyFormat(JwtRsaSsaPssAlgorithm::PS256, 3072, RSA_F4); EXPECT_THAT(RawJwtRsaSsaPssSignKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(RawJwtRsaSsaPssSignKeyManagerTest, ValidatePs512KeyFormat) { JwtRsaSsaPssKeyFormat key_format = CreateKeyFormat(JwtRsaSsaPssAlgorithm::PS512, 3072, RSA_F4); EXPECT_THAT(RawJwtRsaSsaPssSignKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(RawJwtRsaSsaPssSignKeyManagerTest, KeyWithSmallModulusIsInvalid) { JwtRsaSsaPssKeyFormat key_format = CreateKeyFormat(JwtRsaSsaPssAlgorithm::PS256, 512, RSA_F4); key_format.set_modulus_size_in_bits(512); EXPECT_THAT(RawJwtRsaSsaPssSignKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(RawJwtRsaSsaPssSignKeyManagerTest, ValidateKeyFormatUnkownHashDisallowed) { JwtRsaSsaPssKeyFormat key_format = CreateKeyFormat(JwtRsaSsaPssAlgorithm::PS_UNKNOWN, 3072, RSA_F4); EXPECT_THAT(RawJwtRsaSsaPssSignKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } // Runs several sanity checks, checking if a given private key fits a format. void CheckNewKey(const JwtRsaSsaPssPrivateKey& private_key, const JwtRsaSsaPssKeyFormat& key_format) { JwtRsaSsaPssPublicKey public_key = private_key.public_key(); EXPECT_THAT(private_key.version(), Eq(0)); EXPECT_THAT(private_key.version(), Eq(public_key.version())); EXPECT_THAT(public_key.n().length(), Gt(0)); EXPECT_THAT(public_key.e().length(), Gt(0)); EXPECT_THAT(public_key.algorithm(), Eq(key_format.algorithm())); EXPECT_THAT(key_format.public_exponent(), Eq(public_key.e())); util::StatusOr> n = internal::StringToBignum(public_key.n()); ASSERT_THAT(n, IsOk()); util::StatusOr> d = internal::StringToBignum(private_key.d()); ASSERT_THAT(d, IsOk()); util::StatusOr> p = internal::StringToBignum(private_key.p()); ASSERT_THAT(p, IsOk()); util::StatusOr> q = internal::StringToBignum(private_key.q()); ASSERT_THAT(q, IsOk()); util::StatusOr> dp = internal::StringToBignum(private_key.dp()); ASSERT_THAT(dp, IsOk()); util::StatusOr> dq = internal::StringToBignum(private_key.dq()); ASSERT_THAT(dq, IsOk()); internal::SslUniquePtr ctx(BN_CTX_new()); // Check n = p * q. auto n_calc = internal::SslUniquePtr(BN_new()); EXPECT_TRUE(BN_mul(n_calc.get(), p->get(), q->get(), ctx.get())); EXPECT_EQ(BN_cmp(n_calc.get(), n->get()), 0); // Check n size >= modulus_size_in_bits bit. EXPECT_GE(BN_num_bits(n->get()), key_format.modulus_size_in_bits()); // dp = d mod (p - 1) auto pm1 = internal::SslUniquePtr(BN_dup(p->get())); EXPECT_TRUE(BN_sub_word(pm1.get(), 1)); auto dp_calc = internal::SslUniquePtr(BN_new()); EXPECT_TRUE(BN_mod(dp_calc.get(), d->get(), pm1.get(), ctx.get())); EXPECT_EQ(BN_cmp(dp_calc.get(), dp->get()), 0); // dq = d mod (q - 1) auto qm1 = internal::SslUniquePtr(BN_dup(q->get())); EXPECT_TRUE(BN_sub_word(qm1.get(), 1)); auto dq_calc = internal::SslUniquePtr(BN_new()); EXPECT_TRUE(BN_mod(dq_calc.get(), d->get(), qm1.get(), ctx.get())); EXPECT_EQ(BN_cmp(dq_calc.get(), dq->get()), 0); } TEST(RawJwtRsaSsaPssSignKeyManagerTest, CreatePs256KeyValid) { JwtRsaSsaPssKeyFormat key_format = CreateKeyFormat(JwtRsaSsaPssAlgorithm::PS256, 2048, RSA_F4); StatusOr private_key = RawJwtRsaSsaPssSignKeyManager().CreateKey(key_format); ASSERT_THAT(private_key, IsOk()); CheckNewKey(*private_key, key_format); EXPECT_THAT(RawJwtRsaSsaPssSignKeyManager().ValidateKey(*private_key), IsOk()); } TEST(RawJwtRsaSsaPssSignKeyManagerTest, CreatePs384KeyValid) { JwtRsaSsaPssKeyFormat key_format = CreateKeyFormat(JwtRsaSsaPssAlgorithm::PS384, 3072, RSA_F4); StatusOr private_key = RawJwtRsaSsaPssSignKeyManager().CreateKey(key_format); ASSERT_THAT(private_key, IsOk()); CheckNewKey(*private_key, key_format); EXPECT_THAT(RawJwtRsaSsaPssSignKeyManager().ValidateKey(*private_key), IsOk()); } TEST(RawJwtRsaSsaPssSignKeyManagerTest, CreatePs512KeyValid) { JwtRsaSsaPssKeyFormat key_format = CreateKeyFormat(JwtRsaSsaPssAlgorithm::PS512, 4096, RSA_F4); StatusOr private_key = RawJwtRsaSsaPssSignKeyManager().CreateKey(key_format); ASSERT_THAT(private_key, IsOk()); CheckNewKey(*private_key, key_format); EXPECT_THAT(RawJwtRsaSsaPssSignKeyManager().ValidateKey(*private_key), IsOk()); } // Check that in a bunch of CreateKey calls all generated primes are distinct. TEST(RawJwtRsaSsaPssSignKeyManagerTest, CreateKeyAlwaysNewRsaPair) { JwtRsaSsaPssKeyFormat key_format = CreateKeyFormat(JwtRsaSsaPssAlgorithm::PS256, 2048, RSA_F4); absl::flat_hash_set keys; // This test takes about a second per key. int num_generated_keys = 5; for (int i = 0; i < num_generated_keys; ++i) { StatusOr key = RawJwtRsaSsaPssSignKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); keys.insert(key->p()); keys.insert(key->q()); } EXPECT_THAT(keys, SizeIs(2 * num_generated_keys)); } TEST(RawJwtRsaSsaPssSignKeyManagerTest, GetPublicKey) { JwtRsaSsaPssKeyFormat key_format = CreateKeyFormat(JwtRsaSsaPssAlgorithm::PS256, 2048, RSA_F4); StatusOr key = RawJwtRsaSsaPssSignKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); StatusOr public_key = RawJwtRsaSsaPssSignKeyManager().GetPublicKey(*key); ASSERT_THAT(public_key, IsOk()); EXPECT_THAT(public_key->version(), Eq(key->public_key().version())); EXPECT_THAT(public_key->n(), Eq(key->public_key().n())); EXPECT_THAT(public_key->e(), Eq(key->public_key().e())); } TEST(RawJwtRsaSsaPssSignKeyManagerTest, Create) { JwtRsaSsaPssKeyFormat key_format = CreateKeyFormat(JwtRsaSsaPssAlgorithm::PS256, 3072, RSA_F4); StatusOr key = RawJwtRsaSsaPssSignKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); util::StatusOr> signer = RawJwtRsaSsaPssSignKeyManager().GetPrimitive(*key); ASSERT_THAT(signer, IsOk()); internal::RsaSsaPssParams params; params.sig_hash = subtle::HashType::SHA256; params.mgf1_hash = subtle::HashType::SHA256; params.salt_length = 32; util::StatusOr> direct_verifier = subtle::RsaSsaPssVerifyBoringSsl::New( {key->public_key().n(), key->public_key().e()}, params); ASSERT_THAT(direct_verifier, IsOk()); std::string message = "Some message"; util::StatusOr sig = (*signer)->Sign(message); EXPECT_THAT((*direct_verifier)->Verify(*sig, message), IsOk()); } TEST(RawJwtRsaSsaPssSignKeyManagerTest, CreateWrongKey) { JwtRsaSsaPssKeyFormat key_format = CreateKeyFormat(JwtRsaSsaPssAlgorithm::PS256, 3072, RSA_F4); StatusOr key = RawJwtRsaSsaPssSignKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); util::StatusOr> signer = RawJwtRsaSsaPssSignKeyManager().GetPrimitive(*key); ASSERT_THAT(signer, IsOk()); StatusOr second_key = RawJwtRsaSsaPssSignKeyManager().CreateKey(key_format); ASSERT_THAT(second_key, IsOk()); internal::RsaSsaPssParams params; params.sig_hash = subtle::HashType::SHA256; params.mgf1_hash = subtle::HashType::SHA256; params.salt_length = 32; util::StatusOr> direct_verifier = subtle::RsaSsaPssVerifyBoringSsl::New( {second_key->public_key().n(), second_key->public_key().e()}, params); ASSERT_THAT(direct_verifier, IsOk()); std::string message = "Some message"; util::StatusOr sig = (*signer)->Sign(message); EXPECT_THAT((*direct_verifier)->Verify(*sig, message), Not(IsOk())); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/raw_jwt_rsa_ssa_pss_verify_key_manager.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/raw_jwt_rsa_ssa_pss_verify_key_manager.h" #include #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/internal/bn_util.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/public_key_verify.h" #include "tink/subtle/rsa_ssa_pss_verify_boringssl.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/jwt_rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::crypto::tink::subtle::RsaSsaPssVerifyBoringSsl; using ::crypto::tink::util::Enums; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::HashType; using ::google::crypto::tink::JwtRsaSsaPssAlgorithm; using ::google::crypto::tink::JwtRsaSsaPssPublicKey; StatusOr> RawJwtRsaSsaPssVerifyKeyManager::PublicKeyVerifyFactory::Create( const JwtRsaSsaPssPublicKey& rsa_ssa_pss_public_key) const { internal::RsaPublicKey rsa_pub_key; rsa_pub_key.n = rsa_ssa_pss_public_key.n(); rsa_pub_key.e = rsa_ssa_pss_public_key.e(); JwtRsaSsaPssAlgorithm algorithm = rsa_ssa_pss_public_key.algorithm(); StatusOr hash_or = HashForPssAlgorithm(algorithm); if (!hash_or.ok()) { return hash_or.status(); } StatusOr salt_length = SaltLengthForPssAlgorithm(algorithm); if (!salt_length.ok()) { return salt_length.status(); } internal::RsaSsaPssParams params; params.sig_hash = Enums::ProtoToSubtle(hash_or.value()); params.mgf1_hash = Enums::ProtoToSubtle(hash_or.value()); params.salt_length = *salt_length; util::StatusOr> verify = subtle::RsaSsaPssVerifyBoringSsl::New(rsa_pub_key, params); if (!verify.ok()) { return verify.status(); } return {*std::move(verify)}; } Status RawJwtRsaSsaPssVerifyKeyManager::ValidateKey( const JwtRsaSsaPssPublicKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) { return status; } StatusOr> n = internal::StringToBignum(key.n()); if (!n.ok()) { return n.status(); } Status modulus_status = internal::ValidateRsaModulusSize(BN_num_bits(n->get())); if (!modulus_status.ok()) { return modulus_status; } Status exponent_status = internal::ValidateRsaPublicExponent(key.e()); if (!exponent_status.ok()) { return exponent_status; } return ValidateAlgorithm(key.algorithm()); } Status RawJwtRsaSsaPssVerifyKeyManager::ValidateAlgorithm( const JwtRsaSsaPssAlgorithm& algorithm) { switch (algorithm) { case JwtRsaSsaPssAlgorithm::PS256: case JwtRsaSsaPssAlgorithm::PS384: case JwtRsaSsaPssAlgorithm::PS512: return util::OkStatus(); default: return Status(absl::StatusCode::kInvalidArgument, "Unsupported RSA SSA PSS Algorithm"); } return util::OkStatus(); } StatusOr RawJwtRsaSsaPssVerifyKeyManager::HashForPssAlgorithm( const JwtRsaSsaPssAlgorithm& algorithm) { switch (algorithm) { case JwtRsaSsaPssAlgorithm::PS256: return HashType::SHA256; case JwtRsaSsaPssAlgorithm::PS384: return HashType::SHA384; case JwtRsaSsaPssAlgorithm::PS512: return HashType::SHA512; default: return Status(absl::StatusCode::kInvalidArgument, "Unsupported RSA SSA PSS Algorithm"); } } StatusOr RawJwtRsaSsaPssVerifyKeyManager::SaltLengthForPssAlgorithm( const JwtRsaSsaPssAlgorithm& algorithm) { switch (algorithm) { case JwtRsaSsaPssAlgorithm::PS256: return 32; case JwtRsaSsaPssAlgorithm::PS384: return 48; case JwtRsaSsaPssAlgorithm::PS512: return 64; default: return Status(absl::StatusCode::kInvalidArgument, "Unsupported RSA SSA PSS Algorithm"); } } } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/internal/raw_jwt_rsa_ssa_pss_verify_key_manager.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_INTERNAL_RAW_JWT_RSA_SSA_PSS_VERIFY_KEY_MANAGER_H_ #define TINK_JWT_INTERNAL_RAW_JWT_RSA_SSA_PSS_VERIFY_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_verify.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/common.pb.h" #include "proto/jwt_rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class RawJwtRsaSsaPssVerifyKeyManager : public KeyTypeManager> { public: class PublicKeyVerifyFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::JwtRsaSsaPssPublicKey& rsa_ssa_pss_public_key) const override; }; RawJwtRsaSsaPssVerifyKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PUBLIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::JwtRsaSsaPssPublicKey& key) const override; internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: static crypto::tink::util::Status ValidateAlgorithm( const google::crypto::tink::JwtRsaSsaPssAlgorithm& algorithm); static crypto::tink::util::StatusOr HashForPssAlgorithm( const google::crypto::tink::JwtRsaSsaPssAlgorithm& algorithm); static crypto::tink::util::StatusOr SaltLengthForPssAlgorithm( const google::crypto::tink::JwtRsaSsaPssAlgorithm& algorithm); const std::string key_type_ = absl::StrCat(kTypeGoogleapisCom, google::crypto::tink::JwtRsaSsaPssPublicKey().GetTypeName()); friend class RawJwtRsaSsaPssSignKeyManager; }; } // namespace tink } // namespace crypto #endif // TINK_JWT_INTERNAL_RAW_JWT_RSA_SSA_PSS_VERIFY_KEY_MANAGER_H_ ================================================ FILE: cc/jwt/internal/raw_jwt_rsa_ssa_pss_verify_key_manager_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/internal/raw_jwt_rsa_ssa_pss_verify_key_manager.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "openssl/rsa.h" #include "tink/internal/bn_util.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/jwt/internal/raw_jwt_rsa_ssa_pss_sign_key_manager.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/rsa_ssa_pss_sign_boringssl.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/jwt_rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::JwtRsaSsaPssAlgorithm; using ::google::crypto::tink::JwtRsaSsaPssKeyFormat; using ::google::crypto::tink::JwtRsaSsaPssPrivateKey; using ::google::crypto::tink::JwtRsaSsaPssPublicKey; using ::google::crypto::tink::KeyData; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::Not; TEST(RawJwtRsaSsaPssVerifyKeyManagerTest, Basics) { EXPECT_THAT(RawJwtRsaSsaPssVerifyKeyManager().get_version(), Eq(0)); EXPECT_THAT(RawJwtRsaSsaPssVerifyKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PUBLIC)); EXPECT_THAT( RawJwtRsaSsaPssVerifyKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPublicKey")); } TEST(RawJwtRsaSsaPssVerifyKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT( RawJwtRsaSsaPssVerifyKeyManager().ValidateKey(JwtRsaSsaPssPublicKey()), Not(IsOk())); } JwtRsaSsaPssKeyFormat CreateKeyFormat(JwtRsaSsaPssAlgorithm algorithm, int modulus_size_in_bits, int public_exponent) { JwtRsaSsaPssKeyFormat key_format; key_format.set_algorithm(algorithm); key_format.set_modulus_size_in_bits(modulus_size_in_bits); internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), public_exponent); key_format.set_public_exponent( internal::BignumToString(e.get(), BN_num_bytes(e.get())).value()); return key_format; } JwtRsaSsaPssPublicKey CreateValidPublicKey() { JwtRsaSsaPssPrivateKey private_key = RawJwtRsaSsaPssSignKeyManager() .CreateKey( CreateKeyFormat(JwtRsaSsaPssAlgorithm::PS256, 3072, RSA_F4)) .value(); return RawJwtRsaSsaPssSignKeyManager().GetPublicKey(private_key).value(); } // Checks that a public key generaed by the SignKeyManager is considered valid. TEST(RawJwtRsaSsaPssVerifyKeyManagerTest, PublicKeyValid) { JwtRsaSsaPssPublicKey key = CreateValidPublicKey(); EXPECT_THAT(RawJwtRsaSsaPssVerifyKeyManager().ValidateKey(key), IsOk()); } TEST(RawJwtRsaSsaPssVerifyKeyManagerTest, PublicKeyWrongVersion) { JwtRsaSsaPssPublicKey key = CreateValidPublicKey(); key.set_version(1); EXPECT_THAT(RawJwtRsaSsaPssVerifyKeyManager().ValidateKey(key), Not(IsOk())); } TEST(RawJwtRsaSsaPssVerifyKeyManagerTest, PublicKeyUnknownAlgorithmIsInvalid) { JwtRsaSsaPssPublicKey key = CreateValidPublicKey(); key.set_algorithm(JwtRsaSsaPssAlgorithm::PS_UNKNOWN); EXPECT_THAT(RawJwtRsaSsaPssVerifyKeyManager().ValidateKey(key), Not(IsOk())); } TEST(RawJwtRsaSsaPssVerifyKeyManagerTest, PublicKeyWithSmallModulusIsInvalid) { JwtRsaSsaPssPublicKey key = CreateValidPublicKey(); key.set_n("\x23"); key.set_e("\x3"); EXPECT_THAT(RawJwtRsaSsaPssVerifyKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("only modulus size >= 2048"))); } TEST(RsaSsaPssSignKeyManagerTest, Create) { JwtRsaSsaPssKeyFormat key_format = CreateKeyFormat(JwtRsaSsaPssAlgorithm::PS256, 3072, RSA_F4); StatusOr private_key = RawJwtRsaSsaPssSignKeyManager().CreateKey(key_format); ASSERT_THAT(private_key, IsOk()); StatusOr public_key = RawJwtRsaSsaPssSignKeyManager().GetPublicKey(*private_key); ASSERT_THAT(public_key, IsOk()); internal::RsaPrivateKey private_key_subtle; private_key_subtle.n = private_key->public_key().n(); private_key_subtle.e = private_key->public_key().e(); private_key_subtle.d = util::SecretDataFromStringView(private_key->d()); private_key_subtle.p = util::SecretDataFromStringView(private_key->p()); private_key_subtle.q = util::SecretDataFromStringView(private_key->q()); private_key_subtle.dp = util::SecretDataFromStringView(private_key->dp()); private_key_subtle.dq = util::SecretDataFromStringView(private_key->dq()); private_key_subtle.crt = util::SecretDataFromStringView(private_key->crt()); util::StatusOr> direct_signer = subtle::RsaSsaPssSignBoringSsl::New( private_key_subtle, {crypto::tink::subtle::HashType::SHA256, crypto::tink::subtle::HashType::SHA256, 32}); util::StatusOr> verifier = RawJwtRsaSsaPssVerifyKeyManager().GetPrimitive( *public_key); ASSERT_THAT(verifier, IsOk()); std::string message = "Some message"; util::StatusOr sig = (*direct_signer)->Sign(message); ASSERT_THAT(sig, IsOk()); EXPECT_THAT((*verifier)->Verify(*sig, message), IsOk()); } // Test vector from // https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Digital-Signatures struct NistTestVector { std::string n; std::string e; std::string message; std::string signature; JwtRsaSsaPssAlgorithm algorithm; }; // clang-format off static const NistTestVector* nist_test_vector = new NistTestVector({ absl::HexStringToBytes( "a47d04e7cacdba4ea26eca8a4c6e14563c2ce03b623b768c0d49868a57121301dbf783" "d82f4c055e73960e70550187d0af62ac3496f0a3d9103c2eb7919a72752fa7ce8c688d" "81e3aee99468887a15288afbb7acb845b7c522b5c64e678fcd3d22feb84b44272700be" "527d2b2025a3f83c2383bf6a39cf5b4e48b3cf2f56eef0dfff18555e31037b91524869" "4876f3047814415164f2c660881e694b58c28038a032ad25634aad7b39171dee368e3d" "59bfb7299e4601d4587e68caaf8db457b75af42fc0cf1ae7caced286d77fac6cedb03a" "d94f1433d2c94d08e60bc1fdef0543cd2951e765b38230fdd18de5d2ca627ddc032fe0" "5bbd2ff21e2db1c2f94d8b"), absl::HexStringToBytes("10e43f"), absl::HexStringToBytes( "e002377affb04f0fe4598de9d92d31d6c786040d5776976556a2cfc55e54a1dcb3cb1b" "126bd6a4bed2a184990ccea773fcc79d246553e6c64f686d21ad4152673cafec22aeb4" "0f6a084e8a5b4991f4c64cf8a927effd0fd775e71e8329e41fdd4457b3911173187b4f" "09a817d79ea2397fc12dfe3d9c9a0290c8ead31b6690a6"), absl::HexStringToBytes( "4f9b425c2058460e4ab2f5c96384da2327fd29150f01955a76b4efe956af06dc08779a" "374ee4607eab61a93adc5608f4ec36e47f2a0f754e8ff839a8a19b1db1e884ea4cf348" "cd455069eb87afd53645b44e28a0a56808f5031da5ba9112768dfbfca44ebe63a0c057" "2b731d66122fb71609be1480faa4e4f75e43955159d70f081e2a32fbb19a48b9f162cf" "6b2fb445d2d6994bc58910a26b5943477803cdaaa1bd74b0da0a5d053d8b1dc593091d" "b5388383c26079f344e2aea600d0e324164b450f7b9b465111b7265f3b1b063089ae7e" "2623fc0fda8052cf4bf3379102fbf71d7c98e8258664ceed637d20f95ff0111881e650" "ce61f251d9c3a629ef222d"), JwtRsaSsaPssAlgorithm::PS256}); // clang-format on TEST(RawJwtRsaSsaPssVerifyKeyManagerTest, TestVector) { JwtRsaSsaPssPublicKey key; key.set_algorithm(nist_test_vector->algorithm); key.set_version(0); key.set_n(nist_test_vector->n); key.set_e(nist_test_vector->e); util::StatusOr> verifier = RawJwtRsaSsaPssVerifyKeyManager().GetPrimitive(key); ASSERT_THAT(verifier, IsOk()); EXPECT_THAT((*verifier)->Verify(nist_test_vector->signature, nist_test_vector->message), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/jwk_set_converter.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/jwk_set_converter.h" #include #include #include #include #include #include #include "google/protobuf/struct.pb.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "openssl/ec.h" #include "tink/binary_keyset_writer.h" #include "tink/internal/ec_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/jwt/internal/json_util.h" #include "tink/jwt/internal/jwt_format.h" #include "tink/keyset_handle.h" #include "tink/subtle/common_enums.h" #include "tink/util/keyset_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/jwt_ecdsa.pb.h" #include "proto/jwt_rsa_ssa_pkcs1.pb.h" #include "proto/jwt_rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::google::crypto::tink::JwtRsaSsaPkcs1Algorithm; using ::google::crypto::tink::JwtRsaSsaPkcs1PublicKey; using ::google::crypto::tink::JwtRsaSsaPssAlgorithm; using ::google::crypto::tink::JwtRsaSsaPssPublicKey; using ::google::crypto::tink::JwtEcdsaAlgorithm; using ::google::crypto::tink::JwtEcdsaPublicKey; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::Keyset; using ::google::crypto::tink::Keyset_Key; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::OutputPrefixType; using ::google::protobuf::ListValue; using ::google::protobuf::Struct; using ::google::protobuf::Value; namespace { bool HasItem(const Struct& key_struct, absl::string_view name) { return key_struct.fields().find(std::string(name)) != key_struct.fields().end(); } util::StatusOr GetStringItem(const Struct& key_struct, absl::string_view name) { auto it = key_struct.fields().find(std::string(name)); if (it == key_struct.fields().end()) { return util::Status(absl::StatusCode::kInvalidArgument, "not found"); } if (it->second.kind_case() != Value::kStringValue) { return util::Status(absl::StatusCode::kInvalidArgument, "is not a string"); } return it->second.string_value(); } util::Status ExpectStringItem(const Struct& key_struct, absl::string_view name, absl::string_view value) { util::StatusOr item = GetStringItem(key_struct, name); if (!item.ok()) { return item.status(); } if (*item != value) { return util::Status(absl::StatusCode::kInvalidArgument, "unexpected value"); } return util::OkStatus(); } util::Status ValidateUseIsSig(const Struct& key_struct) { if (!HasItem(key_struct, "use")) { return util::OkStatus(); } return ExpectStringItem(key_struct, "use", "sig"); } util::Status ValidateKeyOpsIsVerify(const Struct& key_struct) { if (!HasItem(key_struct, "key_ops")) { return util::OkStatus(); } auto it = key_struct.fields().find("key_ops"); if (it == key_struct.fields().end()) { return util::Status(absl::StatusCode::kInvalidArgument, "key_ops not found"); } if (it->second.kind_case() != Value::kListValue) { return util::Status(absl::StatusCode::kInvalidArgument, "key_ops is not a list"); } const ListValue& key_ops_list = it->second.list_value(); if (key_ops_list.values_size() != 1) { return util::Status(absl::StatusCode::kInvalidArgument, "key_ops size is not 1"); } const Value & value = key_ops_list.values().Get(0); if (value.kind_case() != Value::kStringValue) { return util::Status(absl::StatusCode::kInvalidArgument, "key_ops item is not a string"); } if (value.string_value() != "verify") { return util::Status(absl::StatusCode::kInvalidArgument, "key_ops is not equal to [\"verify\"]"); } return util::OkStatus(); } util::StatusOr RsPublicKeyDataFromKeyStruct(const Struct& key_struct) { JwtRsaSsaPkcs1PublicKey public_key_proto; public_key_proto.set_version(0); util::StatusOr alg = GetStringItem(key_struct, "alg"); if (!alg.ok()) { return alg.status(); } if (*alg == "RS256") { public_key_proto.set_algorithm(JwtRsaSsaPkcs1Algorithm::RS256); } else if (*alg == "RS384") { public_key_proto.set_algorithm(JwtRsaSsaPkcs1Algorithm::RS384); } else if (*alg == "RS512") { public_key_proto.set_algorithm(JwtRsaSsaPkcs1Algorithm::RS512); } else { return util::Status(absl::StatusCode::kInvalidArgument, "invalid alg"); } if (HasItem(key_struct, "p") || HasItem(key_struct, "q") || HasItem(key_struct, "dq") || HasItem(key_struct, "dp") || HasItem(key_struct, "d") || HasItem(key_struct, "qi")) { return util::Status(absl::StatusCode::kInvalidArgument, "private keys cannot be converted"); } util::Status status_kty = ExpectStringItem(key_struct, "kty", "RSA"); if (!status_kty.ok()) { return status_kty; } util::Status status_use = ValidateUseIsSig(key_struct); if (!status_use.ok()) { return status_use; } util::Status status_key_ops = ValidateKeyOpsIsVerify(key_struct); if (!status_key_ops.ok()) { return status_key_ops; } util::StatusOr e = GetStringItem(key_struct, "e"); if (!e.ok()) { return e.status(); } std::string decoded_e; if (!absl::WebSafeBase64Unescape(*e, &decoded_e)) { return util::Status(absl::StatusCode::kInvalidArgument, "failed to decode e"); } public_key_proto.set_e(decoded_e); util::StatusOr n = GetStringItem(key_struct, "n"); if (!n.ok()) { return n.status(); } std::string decoded_n; if (!absl::WebSafeBase64Unescape(*n, &decoded_n)) { return util::Status(absl::StatusCode::kInvalidArgument, "failed to decode n"); } public_key_proto.set_n(decoded_n); if (HasItem(key_struct, "kid")) { util::StatusOr kid = GetStringItem(key_struct, "kid"); if (!kid.ok()) { return kid.status(); } public_key_proto.mutable_custom_kid()->set_value(*kid); } KeyData key_data_proto; key_data_proto.set_type_url( "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PublicKey"); key_data_proto.set_value(public_key_proto.SerializeAsString()); key_data_proto.set_key_material_type(KeyData::ASYMMETRIC_PUBLIC); return key_data_proto; } util::StatusOr PsPublicKeyDataFromKeyStruct(const Struct& key_struct) { JwtRsaSsaPssPublicKey public_key_proto; public_key_proto.set_version(0); util::StatusOr alg = GetStringItem(key_struct, "alg"); if (!alg.ok()) { return alg.status(); } if (*alg == "PS256") { public_key_proto.set_algorithm(JwtRsaSsaPssAlgorithm::PS256); } else if (*alg == "PS384") { public_key_proto.set_algorithm(JwtRsaSsaPssAlgorithm::PS384); } else if (*alg == "PS512") { public_key_proto.set_algorithm(JwtRsaSsaPssAlgorithm::PS512); } else { return util::Status(absl::StatusCode::kInvalidArgument, "invalid alg"); } if (HasItem(key_struct, "p") || HasItem(key_struct, "q") || HasItem(key_struct, "dq") || HasItem(key_struct, "dp") || HasItem(key_struct, "d") || HasItem(key_struct, "qi")) { return util::Status(absl::StatusCode::kInvalidArgument, "private keys cannot be converted"); } util::Status status_kty = ExpectStringItem(key_struct, "kty", "RSA"); if (!status_kty.ok()) { return status_kty; } util::Status status_use = ValidateUseIsSig(key_struct); if (!status_use.ok()) { return status_use; } util::Status status_key_ops = ValidateKeyOpsIsVerify(key_struct); if (!status_key_ops.ok()) { return status_key_ops; } util::StatusOr e = GetStringItem(key_struct, "e"); if (!e.ok()) { return e.status(); } std::string decoded_e; if (!absl::WebSafeBase64Unescape(*e, &decoded_e)) { return util::Status(absl::StatusCode::kInvalidArgument, "failed to decode e"); } public_key_proto.set_e(decoded_e); util::StatusOr n = GetStringItem(key_struct, "n"); if (!n.ok()) { return n.status(); } std::string decoded_n; if (!absl::WebSafeBase64Unescape(*n, &decoded_n)) { return util::Status(absl::StatusCode::kInvalidArgument, "failed to decode n"); } public_key_proto.set_n(decoded_n); if (HasItem(key_struct, "kid")) { util::StatusOr kid = GetStringItem(key_struct, "kid"); if (!kid.ok()) { return kid.status(); } public_key_proto.mutable_custom_kid()->set_value(*kid); } KeyData key_data_proto; key_data_proto.set_type_url( "type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPublicKey"); key_data_proto.set_value(public_key_proto.SerializeAsString()); key_data_proto.set_key_material_type(KeyData::ASYMMETRIC_PUBLIC); return key_data_proto; } util::StatusOr EsPublicKeyDataFromKeyStruct(const Struct& key_struct) { JwtEcdsaPublicKey public_key_proto; public_key_proto.set_version(0); util::StatusOr alg = GetStringItem(key_struct, "alg"); if (!alg.ok()) { return alg.status(); } util::StatusOr curve = GetStringItem(key_struct, "crv"); if (!curve.ok()) { return curve.status(); } if (*alg == "ES256") { if (*curve != "P-256") { return util::Status(absl::StatusCode::kInvalidArgument, "crv is not equal to P-256"); } public_key_proto.set_algorithm(JwtEcdsaAlgorithm::ES256); } else if (*alg == "ES384") { if (*curve != "P-384") { return util::Status(absl::StatusCode::kInvalidArgument, "crv is not equal to P-384"); } public_key_proto.set_algorithm(JwtEcdsaAlgorithm::ES384); } else if (*alg == "ES512") { if (*curve != "P-521") { return util::Status(absl::StatusCode::kInvalidArgument, "crv is not equal to P-521"); } public_key_proto.set_algorithm(JwtEcdsaAlgorithm::ES512); } else { return util::Status(absl::StatusCode::kInvalidArgument, "invalid alg"); } if (HasItem(key_struct, "d")) { return util::Status(absl::StatusCode::kInvalidArgument, "private keys cannot be converted"); } util::Status status_kty = ExpectStringItem(key_struct, "kty", "EC"); if (!status_kty.ok()) { return status_kty; } util::Status status_use = ValidateUseIsSig(key_struct); if (!status_use.ok()) { return status_use; } util::Status status_key_ops = ValidateKeyOpsIsVerify(key_struct); if (!status_key_ops.ok()) { return status_key_ops; } util::StatusOr x = GetStringItem(key_struct, "x"); if (!x.ok()) { return x.status(); } std::string decoded_x; if (!absl::WebSafeBase64Unescape(*x, &decoded_x)) { return util::Status(absl::StatusCode::kInvalidArgument, "failed to decode x"); } public_key_proto.set_x(decoded_x); util::StatusOr y = GetStringItem(key_struct, "y"); if (!y.ok()) { return y.status(); } std::string decoded_y; if (!absl::WebSafeBase64Unescape(*y, &decoded_y)) { return util::Status(absl::StatusCode::kInvalidArgument, "failed to decode y"); } public_key_proto.set_y(decoded_y); if (HasItem(key_struct, "kid")) { util::StatusOr kid = GetStringItem(key_struct, "kid"); if (!kid.ok()) { return kid.status(); } public_key_proto.mutable_custom_kid()->set_value(*kid); } KeyData key_data_proto; key_data_proto.set_type_url( "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey"); key_data_proto.set_value(public_key_proto.SerializeAsString()); key_data_proto.set_key_material_type(KeyData::ASYMMETRIC_PUBLIC); return key_data_proto; } // RFC 7518 specifies a fixed sized encoding for the x and y coordinates from // SEC 1 https://datatracker.ietf.org/doc/html/rfc7518#section-6.2.1.2 util::StatusOr> Sec1EncodeCoordinates( absl::string_view x, absl::string_view y, subtle::EllipticCurveType curve_type) { util::StatusOr encoded_size = internal::EcFieldSizeInBytes(curve_type); util::StatusOr> point = internal::GetEcPoint(curve_type, x, y); if (!point.ok()) { return point.status(); } // The uncompressed point is encoded as 0x04 || x || y. util::StatusOr uncompressed_point = internal::EcPointEncode( curve_type, subtle::EcPointFormat::UNCOMPRESSED, (*point).get()); if (!uncompressed_point.ok()) { return uncompressed_point.status(); } if ((*uncompressed_point).size() != *encoded_size * 2 + 1) { return util::Status(absl::StatusCode::kInvalidArgument, "invalid encoded size"); } return std::make_pair( uncompressed_point.value().substr(1, *encoded_size), uncompressed_point.value().substr(*encoded_size + 1, *encoded_size)); } } // namespace util::StatusOr> JwkSetToPublicKeysetHandle( absl::string_view jwk_set) { util::StatusOr jwk_set_struct = jwt_internal::JsonStringToProtoStruct(jwk_set); if (!jwk_set_struct.ok()) { return jwk_set_struct.status(); } auto it = jwk_set_struct->fields().find("keys"); if (it == jwk_set_struct->fields().end()) { return util::Status(absl::StatusCode::kInvalidArgument, "keys not found"); } if (it->second.kind_case() != Value::kListValue) { return util::Status(absl::StatusCode::kInvalidArgument, "keys is not a list"); } if (it->second.list_value().values_size() <= 0) { return util::Status(absl::StatusCode::kInvalidArgument, "keys list is empty"); } uint32_t last_key_id = 0; Keyset keyset; for (const Value& value : it->second.list_value().values()) { if (value.kind_case() != Value::kStructValue) { return util::Status(absl::StatusCode::kInvalidArgument, "key is not a JSON object"); } const Struct& key_struct = value.struct_value(); util::StatusOr alg = GetStringItem(key_struct, "alg"); if (!alg.ok()) { return alg.status(); } absl::string_view alg_prefix = absl::string_view(*alg).substr(0, 2); // Add to keyset Keyset_Key* key = keyset.add_key(); uint32_t key_id = GenerateUnusedKeyId(keyset); key->set_key_id(key_id); key->set_status(KeyStatusType::ENABLED); key->set_output_prefix_type(OutputPrefixType::RAW); if (alg_prefix == "RS") { util::StatusOr key_data = RsPublicKeyDataFromKeyStruct(key_struct); if (!key_data.ok()) { return key_data.status(); } *key->mutable_key_data() = *key_data; } else if (alg_prefix == "PS") { util::StatusOr key_data = PsPublicKeyDataFromKeyStruct(key_struct); if (!key_data.ok()) { return key_data.status(); } *key->mutable_key_data() = *key_data; } else if (alg_prefix == "ES") { util::StatusOr key_data = EsPublicKeyDataFromKeyStruct(key_struct); if (!key_data.ok()) { return key_data.status(); } *key->mutable_key_data() = *key_data; } else { return util::Status(absl::StatusCode::kInvalidArgument, "invalid alg prefix"); } last_key_id = key_id; } keyset.set_primary_key_id(last_key_id); return KeysetHandle::ReadNoSecret(keyset.SerializeAsString()); } void AddStringEntry(Struct* key, absl::string_view name, absl::string_view value) { auto val = key->mutable_fields()->insert({std::string(name), Value()}); val.first->second.set_string_value(std::string(value)); } void AddKeyOpsVerifyEntry(Struct* key) { auto key_ops = key->mutable_fields()->insert({"key_ops", Value()}); key_ops.first->second.mutable_list_value()->add_values()->set_string_value( "verify"); } util::StatusOr EsPublicKeyToKeyStruct(const Keyset_Key& key) { JwtEcdsaPublicKey public_key; if (!public_key.ParseFromString(key.key_data().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "parse JwtEcdsaPublicKey failed"); } Struct output_key; subtle::EllipticCurveType curve_type; switch (public_key.algorithm()) { case JwtEcdsaAlgorithm::ES256: AddStringEntry(&output_key, "crv", "P-256"); AddStringEntry(&output_key, "alg", "ES256"); curve_type = subtle::EllipticCurveType::NIST_P256; break; case JwtEcdsaAlgorithm::ES384: AddStringEntry(&output_key, "crv", "P-384"); AddStringEntry(&output_key, "alg", "ES384"); curve_type = subtle::EllipticCurveType::NIST_P384; break; case JwtEcdsaAlgorithm::ES512: AddStringEntry(&output_key, "crv", "P-521"); AddStringEntry(&output_key, "alg", "ES512"); curve_type = subtle::EllipticCurveType::NIST_P521; break; default: return util::Status(absl::StatusCode::kInvalidArgument, "unknown JwtEcdsaAlgorithm"); } util::StatusOr> encoded_point = Sec1EncodeCoordinates(public_key.x(), public_key.y(), curve_type); if (!encoded_point.ok()) { return encoded_point.status(); } AddStringEntry(&output_key, "kty", "EC"); AddStringEntry(&output_key, "x", absl::WebSafeBase64Escape((*encoded_point).first)); AddStringEntry(&output_key, "y", absl::WebSafeBase64Escape((*encoded_point).second)); AddStringEntry(&output_key, "use", "sig"); AddKeyOpsVerifyEntry(&output_key); absl::optional kid = jwt_internal::GetKid(key.key_id(), key.output_prefix_type()); if (kid.has_value()) { AddStringEntry(&output_key, "kid", kid.value()); } else if (public_key.has_custom_kid()) { AddStringEntry(&output_key, "kid", public_key.custom_kid().value()); } return output_key; } util::StatusOr RsPublicKeyToKeyStruct(const Keyset_Key& key) { JwtRsaSsaPkcs1PublicKey public_key; if (!public_key.ParseFromString(key.key_data().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "parse JwtRsaSsaPkcs1PublicKey failed"); } Struct output_key; switch (public_key.algorithm()) { case JwtRsaSsaPkcs1Algorithm::RS256: AddStringEntry(&output_key, "alg", "RS256"); break; case JwtRsaSsaPkcs1Algorithm::RS384: AddStringEntry(&output_key, "alg", "RS384"); break; case JwtRsaSsaPkcs1Algorithm::RS512: AddStringEntry(&output_key, "alg", "RS512"); break; default: return util::Status(absl::StatusCode::kInvalidArgument, "unknown JwtRsaSsaPkcs1Algorithm"); } AddStringEntry(&output_key, "kty", "RSA"); AddStringEntry(&output_key, "e", absl::WebSafeBase64Escape(public_key.e())); AddStringEntry(&output_key, "n", absl::WebSafeBase64Escape(public_key.n())); AddStringEntry(&output_key, "use", "sig"); AddKeyOpsVerifyEntry(&output_key); absl::optional kid = jwt_internal::GetKid(key.key_id(), key.output_prefix_type()); if (kid.has_value()) { AddStringEntry(&output_key, "kid", kid.value()); } else if (public_key.has_custom_kid()) { AddStringEntry(&output_key, "kid", public_key.custom_kid().value()); } return output_key; } util::StatusOr PsPublicKeyToKeyStruct(const Keyset_Key& key) { JwtRsaSsaPssPublicKey public_key; if (!public_key.ParseFromString(key.key_data().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "parse JwtRsaSsaPkcs1PublicKey failed"); } Struct output_key; switch (public_key.algorithm()) { case JwtRsaSsaPssAlgorithm::PS256: AddStringEntry(&output_key, "alg", "PS256"); break; case JwtRsaSsaPssAlgorithm::PS384: AddStringEntry(&output_key, "alg", "PS384"); break; case JwtRsaSsaPssAlgorithm::PS512: AddStringEntry(&output_key, "alg", "PS512"); break; default: return util::Status(absl::StatusCode::kInvalidArgument, "unknown JwtRsaSsaPkcs1Algorithm"); } AddStringEntry(&output_key, "kty", "RSA"); AddStringEntry(&output_key, "e", absl::WebSafeBase64Escape(public_key.e())); AddStringEntry(&output_key, "n", absl::WebSafeBase64Escape(public_key.n())); AddStringEntry(&output_key, "use", "sig"); AddKeyOpsVerifyEntry(&output_key); absl::optional kid = jwt_internal::GetKid(key.key_id(), key.output_prefix_type()); if (kid.has_value()) { AddStringEntry(&output_key, "kid", kid.value()); } else if (public_key.has_custom_kid()) { AddStringEntry(&output_key, "kid", public_key.custom_kid().value()); } return output_key; } util::StatusOr JwkSetFromPublicKeysetHandle( const KeysetHandle& keyset_handle) { std::stringbuf keyset_buf; util::StatusOr> writer = BinaryKeysetWriter::New(absl::make_unique(&keyset_buf)); if (!writer.ok()) { return writer.status(); } util::Status status = keyset_handle.WriteNoSecret((*writer).get()); if (!status.ok()) { return status; } Keyset keyset; if (!keyset.ParseFromString(keyset_buf.str())) { return util::Status(absl::StatusCode::kInvalidArgument, "parse Keyset failed"); } Struct output; auto insertion_result = output.mutable_fields()->insert({"keys", Value()}); ListValue* keys_list = insertion_result.first->second.mutable_list_value(); for (const Keyset::Key& key : keyset.key()) { if (key.status() != KeyStatusType::ENABLED) { continue; } if ((key.output_prefix_type() != OutputPrefixType::RAW) && (key.output_prefix_type() != OutputPrefixType::TINK)) { return util::Status(absl::StatusCode::kInvalidArgument, "Unknown output prefix type"); } if (key.key_data().key_material_type() != KeyData::ASYMMETRIC_PUBLIC) { return util::Status(absl::StatusCode::kInvalidArgument, "Only asymmetric public keys are supported"); } if (key.key_data().type_url() == "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey") { util::StatusOr output_key = EsPublicKeyToKeyStruct(key); if (!output_key.ok()) { return output_key.status(); } *keys_list->add_values()->mutable_struct_value() = *output_key; } else if (key.key_data().type_url() == "type.googleapis.com/" "google.crypto.tink.JwtRsaSsaPkcs1PublicKey") { util::StatusOr output_key = RsPublicKeyToKeyStruct(key); if (!output_key.ok()) { return output_key.status(); } *keys_list->add_values()->mutable_struct_value() = *output_key; } else if (key.key_data().type_url() == "type.googleapis.com/" "google.crypto.tink.JwtRsaSsaPssPublicKey") { util::StatusOr output_key = PsPublicKeyToKeyStruct(key); if (!output_key.ok()) { return output_key.status(); } *keys_list->add_values()->mutable_struct_value() = *output_key; } else { return util::Status(absl::StatusCode::kInvalidArgument, "Unknown key type url"); } } return jwt_internal::ProtoStructToJsonString(output); } } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/jwk_set_converter.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_JWK_SET_CONVERTER_H_ #define TINK_JWT_JWK_SET_CONVERTER_H_ #include #include #include "absl/strings/string_view.h" #include "tink/keyset_handle.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Converts a Json Web Key (JWK) set into a Tink KeysetHandle. // // It requires that all keys in the set have the "alg" field set. Currently, // only public keys for algorithms RS256, RS384, RS512, ES256, ES384 and ES512 // are supported. // // JWK is defined in https://www.rfc-editor.org/rfc/rfc7517.txt. util::StatusOr> JwkSetToPublicKeysetHandle( absl::string_view jwk_set); // Converts a Tink KeysetHandle with JWT keys into a Json Web Key (JWK) set. // // Currently only public keys for algorithms ES256, ES384 and ES512 are // supported. // // JWK is defined in https://www.rfc-editor.org/rfc/rfc7517.txt. util::StatusOr JwkSetFromPublicKeysetHandle( const KeysetHandle& keyset_handle); } // namespace tink } // namespace crypto #endif // TINK_JWT_JWK_SET_CONVERTER_H_ ================================================ FILE: cc/jwt/jwk_set_converter_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/jwk_set_converter.h" #include #include #include #include #include "google/protobuf/struct.pb.h" #include "google/protobuf/util/message_differencer.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/escaping.h" #include "absl/strings/string_view.h" #include "tink/cleartext_keyset_handle.h" #include "tink/config/global_registry.h" #include "tink/json_keyset_reader.h" #include "tink/jwt/internal/json_util.h" #include "tink/jwt/jwt_public_key_sign.h" #include "tink/jwt/jwt_public_key_verify.h" #include "tink/jwt/jwt_signature_config.h" #include "tink/jwt/jwt_validator.h" #include "tink/jwt/raw_jwt.h" #include "tink/jwt/verified_jwt.h" #include "tink/keyset_handle.h" #include "tink/keyset_reader.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/ecdsa.pb.h" #include "proto/jwt_ecdsa.pb.h" #include "proto/jwt_rsa_ssa_pkcs1.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::google::protobuf::Struct; using ::google::protobuf::util::MessageDifferencer; using ::testing::Eq; using ::testing::Not; constexpr absl::string_view kRs256PrivateKey = R"( { "primaryKeyId":1277272603, "key":[{ "keyData":{ "typeUrl": "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PrivateKey", "value":"QoABP3S5U0JiFQcqcMFT0Ysqk7FK2NunBCY9o+EAE+svaQi6zWQq2ODFoxB2NU9nqa3ZbhRiCdKNLz6o+jOTIpemKx8Gh/7GufRGLFAjjMchZYs3ripiTNSMaqXgm6ECt8DqrAZbMQ7D3Ha1vArcZG97pbE9t3m4M87zhLs3wPYd/kQ6gAEFPE2GLD5ai8VYd/Q0ePZR0ttLgkJ/2yIig5T8YyJaoZEPjK+v3zVFQuGguJApnl2tC0S7OqOtqsDZ5Dux0H3Cx85FLeyB2STHlXtq9GUGI2VrC/TP3OASc6ap75WMKZRpowEVaip8wWehAOL+VIgTajiFf0yXdSodc4ZjJKreiTKAAd6ahHQiVJapNKY6XANgA+JmluAWq/Fk1LmEnTybWVelcODbppwIvhJ6Xuz6kjuEhhxsUtkPO4vuZJfEF8DWAH5L/FHjJpgP3NnDoNVzGOL5w8SdgIfgCS0UqBLSv2/KhlIEijuL9NYaqydN1cPcjdeadSMcDSIwKjNASRVaPZDJKoABx1/CfOqCbE8eh450YvGwYvII+ro8tR+uusnt2QuQZux3wvl9eto9Dr+5Iq/0bKqpMMgvYHIT+mlkgK6SYLcynZx+SYMAtbixa0nH1lJnnBodOJS6zdMRTcFkpI4g/CbCvzTp5gF5EkfBSbVToVLqICydokKnTvNK6chX3MEUjskigAH0eGwQwn174yJzJTUWH4cRxDredI6LkjADm/ikza76AHT8qRJHJkmwSXL88p3M2bYFN+g9Z/FTL21Ylc0mxn/iII3vabfZWZTWK9QGR7YjAicFyLDeu/ZccCkCXgTFzqqlZ7w4Sv05hWz57xxm81JyxftzapeflfAmjRircFXG2RqAAgub/Z28+SFSf6zSPFMKiYVWx//DI0ubbiuuu65tUse9xYq9JtHEobgYk0dJXNuY9RzPkGblZ8/SD06yRf9l8DMRAbivDfgXY5QZ2PBDk1jn6A2y0S+i80h9MILJ+/sfkljiyvtBFDQwiI9tPOOnxbWmg6bl5xYUdvjbhxBoVB1fgOtAid6gGuLstbf8ycV+DkaWg3mo4054ge9BBT4eWKGC/LHctSaQ/OBs5cbGW+UqZxIjSN9YeOTkbvNKO4l4jGTg0BUBPB3GH8KQPtE4sbBhUDyjYYgAZZcSaRq7AfhLUkiDSfIVcKAIoEOaTS63vf2BQlbW8/HuNlWNUX0M+hkSigIiAwEAARqAAr5lDmutk2K8Y+zfK2VQM6BHUp5rEUGjVgTAHQfGnRmvJ+MnBomFqBr9LmVnPLx9o5+pdz2v+9m29iB39/ig9lGk8C5Ncd8koV8mxKEuWRfW3ps659qITYsRqDezn4+8D2+tWfhdTb+d56t9PM/kSNVnsiB/vR47iHLlMWlmNFXr7F8wnoTCT+YO5Fc8peeW2HEYtvHYnZFWs681YDRt+cjTTBC99qFtVX776e4X0B7cUsJBTj8yYMyDx2yRW8QCxq64Fx7KKu1LQ0HUvb76BKePyc0IQrZwhCmoYJE8Dlsk/ejpURmIjyUhR1k7o8tUJ3ejinPCxhLKQF+KA+mZfmEQAQ==", "keyMaterialType":"ASYMMETRIC_PRIVATE" }, "status":"ENABLED", "keyId":1277272603, "outputPrefixType":"TINK" }] })"; constexpr absl::string_view kRs256JwkPublicKey = R"({ "keys":[{ "kty":"RSA", "n": "vmUOa62TYrxj7N8rZVAzoEdSnmsRQaNWBMAdB8adGa8n4ycGiYWoGv0uZWc8vH2jn6l3Pa_72bb2IHf3-KD2UaTwLk1x3yShXybEoS5ZF9bemzrn2ohNixGoN7Ofj7wPb61Z-F1Nv53nq308z-RI1WeyIH-9HjuIcuUxaWY0VevsXzCehMJP5g7kVzyl55bYcRi28didkVazrzVgNG35yNNMEL32oW1Vfvvp7hfQHtxSwkFOPzJgzIPHbJFbxALGrrgXHsoq7UtDQdS9vvoEp4_JzQhCtnCEKahgkTwOWyT96OlRGYiPJSFHWTujy1Qnd6OKc8LGEspAX4oD6Zl-YQ", "e":"AQAB", "use":"sig", "alg":"RS256", "key_ops":["verify"], "kid":"TCGiGw" }] })"; constexpr absl::string_view kRs384PrivateKey = R"({ "primaryKeyId":357749026, "key":[{ "keyData":{ "typeUrl": "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PrivateKey", "value":"EosDEAIagQMAjzf/xTLS/jFLqQNkqpyrNJt7KSzLYLrtqO0jjUnYowO072NRoQBD24OEy5uNnM9iHXB/+C0mAALk9KIjd84tQbQAcJuL/JdV8ff/VT9iXhv97zLH80/K4i/AfBfATlrfaGKyz0+5jb6oSK8fksrgBfE+JOJRz3HiCHU7BlpJNhZPtJE77RE7BjALCmDhR/Qgwu2Yei782Y3DS46U6Ap/H4QWYzNX7mmykSfCwer+KMVLGYc0B3LlLSfi7UsgoqaBckjJS7cAp8AkzJ2fqdMrOs5ylfTIyfE+r3I/zEq4r+ZfKwXI2+ZLRKrlz6Cs4RMV4wVJzB6hSlZWdg4IJLJn3fICGxNRacONl3uK6OL1jvNSjg9aUpfJFHP9pKnGuyfvQs5k0stSMgtV7J8JGzYlem1/EI2DfCDoVUAfTFM5GY8YgKBYObA4WA/Vjq1b6nRycrwvBWS5FyXIoAy9O1ib3FlkdRKPDzqscScHZV+w9MifT9YBWcnY4AqG5Uy3CMHtIgMBAAEagAMPPYhMNdJaFmjUvXWy6iUV3g3HHesuifXMah/EYz1Ya4aPiuQe2+Zcr6wr9oulSjRIqbYUdMl8atJubeqUTy5ltX/ue77zzC7rJtbW/X28QgJNt/urGqyeUTKMggKG1Ai+FPKuOO+n88f4pBoaBti8CSXxytul1ZqWB9OWI3ly9gDZWDMmURUU3XvvSMvwWjw6Qgpdxi5GAF3t5mhWIPfSJL41JDuRNVI5PB/vftA5CnWpa8fPmxxkJ8BwO/RnGoy3GgFGFwRuvuLiQgQiHwjCq6czgCKaw1FPq5HaTyJBdCfv+gDG8EjvnsDLzWQqQkq7obvY7uSCxw2lomlXp4cPOo5dbwTSJg2OessyL4rQQJZjw78etOMjOx1M+Q4sVlKbPdd/qxZpnlZ2EG1oUjRM7ZMuJEVfxSy7KRt9GG0P4pqMX7uhMmjF5B/H/re/GujrhISA92cPc8MQX+IA1z9ZHUrHgSMLoSVIf7pwB335sQe9R6pR8xjgoPorFzQ7/kEiwQEAwBOLB9g8uS68ypaUHMixM0RSqaHwaCmhJ8YvJ3z3y7qDYrJWSNmL1zzAjPdbHtvO+u9yssevvuj0/RdjI4U0lAYbT/RsSWMG9M+ojRr/CpK3tcOGE+fJg6EAjOnJXKxkGhxdftM8Nr9ErlyQcei5iNoNbzC5yrytPOM3QvczwiIpbWiygI/+IouMM1gnY7f0OfUFHEyMMOl4hEc8rBKiijJSSbLnuTERLLHDkVlvoCz59D1VUuG+aCUaaRb3vF6ZKsEBAL7h5x4M7K+tBi0prtJy/PCxL70RgGWscummSF7gO8Rw0W0SmA4g8Q9SrEBOI3I/51KFTdxgp6CWQfO2S/L5tbhtDeye7CGqnO8oVeDuB2kD7k4yUkhgyeUFxc7DB/aU1lo8Bc3kClsmecWtwDbJ1pMrCwF7yXifBK6TuVY6iZ/46+HfLnZQ+fWcvvbPAtSbKVZ1YMVYMVipBbvIWf1slWOaHfXIi1YtZlkM+wJHX+a9zheP4HW2TBt4qoTSlm92dTLAAXPv1+2mQhDs+xu1hDVTllIBnXuyua/F4PZnE7NcJR4duIxsZNSYK2aBzx/HdoLL3sVsnuj2y0gKyUWzRi38i14FyZqbSHmLgnlmlrCFaQhywty95kJBmEsRdYmY2+hKTinMkUqqKiBJlyU/zhhThxnptE43NQ4AkPi9lW+gUueNQ0A8//HF+HnVjYy4Wx4/vPT2xlzsf3pOkmYVsbOTk/SipzTA/km0Kk+2BPvI5i3iuAUKuGPMyueF7ckdCe/zkTrAAWDkpP/hCagnSTJVrVNQYUsAdj4gCzAROIeYC7Z1VoFhzzzxqlPJrvPbQGqn/2A4RgDif+J1AcIHY9UFXUoqLW8/lEjfZvez9lOEAwvZZ9OL1kTFUHVDBFkH9B//aiRl6uUFAOFBd2xLfJa2mxJ0pEIyIDURk/Rxq9u+St8VedTFc19Fff07H5boiRsZe9NWK8aicIvcN7hMnAd1LRDyNGbJzZl8whXtl71uVGAUwP6MrHfTZdn6vmlXeB9SEmDkHULAASQW/j0wELpL4tHoIM1q+MpU6x/JB4e+H3oAZv081V9ADroMaweBurQtfa6wH+w/imenWNh+ipFZQe7R9UKsno9fhU2uBZG6gsOLmb2MMpuBMWJNqJMZAQ7jfsubtpyTeL44nkRT8cOxIIGwmjU9jt6CA/CrfKrgH5s5UYcfhIiLqJI+jLIVHn+ygbG0aLoUVoy55mtdW3aCkpdb1GIR8G9ahguwIDzvWKIy8GQpyKA9Rt2tpzMFm7gWK4cz3qrXHg==", "keyMaterialType":"ASYMMETRIC_PRIVATE" }, "status":"ENABLED", "keyId":357749026, "outputPrefixType":"TINK" }] })"; constexpr absl::string_view kRs384JwkPublicKey = R"({ "keys":[{ "kty":"RSA", "n":"AI83_8Uy0v4xS6kDZKqcqzSbeyksy2C67ajtI41J2KMDtO9jUaEAQ9uDhMubjZzPYh1wf_gtJgAC5PSiI3fOLUG0AHCbi_yXVfH3_1U_Yl4b_e8yx_NPyuIvwHwXwE5a32hiss9PuY2-qEivH5LK4AXxPiTiUc9x4gh1OwZaSTYWT7SRO-0ROwYwCwpg4Uf0IMLtmHou_NmNw0uOlOgKfx-EFmMzV-5pspEnwsHq_ijFSxmHNAdy5S0n4u1LIKKmgXJIyUu3AKfAJMydn6nTKzrOcpX0yMnxPq9yP8xKuK_mXysFyNvmS0Sq5c-grOETFeMFScweoUpWVnYOCCSyZ93yAhsTUWnDjZd7iuji9Y7zUo4PWlKXyRRz_aSpxrsn70LOZNLLUjILVeyfCRs2JXptfxCNg3wg6FVAH0xTORmPGICgWDmwOFgP1Y6tW-p0cnK8LwVkuRclyKAMvTtYm9xZZHUSjw86rHEnB2VfsPTIn0_WAVnJ2OAKhuVMtwjB7Q", "e":"AQAB", "use":"sig", "alg":"RS384", "key_ops":["verify"], "kid":"FVLRIg" }] })"; constexpr absl::string_view kRs512PrivateKey = R"({ "primaryKeyId":2102918723, "key":[{ "keyData":{ "typeUrl": "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PrivateKey", "value":"EosEEAMagQQApm24cAZjL7Uxzvyx2nWA5XeMwIm07s2aHItKmuhZwGepI3WD2YHYR0Hbb5YtaEH9T8mVlEJ0dPoLE8dKJ3Rz0klz7YKaJX3NTaxVMlSQLK05VLSGtw8TPkkrprpVXL5KRz/X4jQPZi6td3RpEHIMAsLyF4cyiTpVBdbyrAeBHJzQmvVFxtj4IX9IyVFefzyDh7dueTUAmI9yYewk5zCRqfCVbGrjoPE+/l9/Su5c3iA8NhT7r8nrJkmt5iPCuX4uGSrM6TPp74sTix0jlYUlBH1wYZEx/iS2AXeSoW1wU0WQa106/Dkx0t7R5oQ0PNnxNnJAOCIdiXzvzHy48+mah6J/lp/9lQCyu/9tX6HdGlKhN1M/hKVAyY/7fLZHYvG9Sz8KJRqGhUXBO39tEc7RDL5DClO8B0lfwLOsrZq6rJwVrBibzFiOP96lMVLAEIm5mNqbGllJrb3NMOo/gBfC3b70s77vSPma7MNAvflzOkGBpdIAQmSsz1273U6OQna+1gVUuNai6A3m5WkQHHUiyT8qCt46CXeUXW+zYSNO6KFrEmEz7XtqUkuYMvTpkQOyG3ZSG79kTER8/BMppH/6R+OVqa6gtS9O1WHM1m44cP9cA6sZp8yMz1ZWr8PleOoXtYWdv+3hgg5A2YZ454gUtvguVHmccHUcgdSkBZrOu+UiAwEAARqABE1h5sfvsF6WWTpstCVnTS9kjsVXQhFm96kd+upb7p9Pk40xLsULYox/SpBvu10mkalviWUOISfiuxPPLeN6ef/kt0pP12xnOfZLkrF8MC0Vvfpslda347KqQuma6eXddJv8S1yZ6C8StQU90zwaSwtdqULXUeAMh0vXza2/L4EmSLhEItV6PKUWkblJZC607FNGLs+cnVJSIFT3f5EfPBtQCaoHaR+EDE4qCP3GJtgBFP3wc7YgpH2A9KJ1Li0hRj3dcLldsf/3InckbU8wQS39RSuYXy5T02yLNFpqkDenuKazCqIL1ea+Q8py3fcNPuKZ7NIsyp8KwFTMCRMgIwD5dq6l0lsNZ7UMx2/5ex5LEGlTmNdQZCZivav2hQF8/zeEWzq4dH+hDrNWSwIyMF1t70mxChMAQ0RAzH6iteCQQFnLIFFqVTiXIo2FCwwlyg2uQ6ASJvnW4M6ftXw8ktpLlPeP9uDpN2idBW3kO8dLUfQbCjIIr4cQozQvYenVkMBAbXjqORFK0YRp7xtUNeV5i/y0Dd8tKTmVx8QwGaI48RLVZUC6xelFugbP7UKCkVTPw204JbQGj0Bc1o+KM+ekEWd6Z1oyQQEE/tx2pMsQwrC5FrOv6LtVCLTyQrfHmrENpFI3MRyHJsBFSO0UrDFu9CSCsLSvGjM4eAlI+1xhIoECAP9WTkzedYf0VvNI3oMuENt4nG1CLycY9ZoUmebVvaR6jcFFHr8AxT0JGt/ZdnSt5iDK+VC52Z4kjVfiyJaj9O8PKifKiGho9IpXbd57k0lhDVwEZ6jLJ55y3KJRBcXaTtqodO3KsP8Nix2mcInQvKT9y6ZY7w8PT9WOrJuXtClc3CvgK5LyFQLRQ8dsCWclcb2MWD7IKBam1yvdd5mtCylsF0mnSoLfYPFcPAZ/O0zKCQOtyCm1duEfuBlef0mGwYAJsvKvj4N8U10Yk5TNr4oZM4olP2WY4Jf4fucnKscMxwkkbSVOOjms/r8NEBUH6XUpGewUQyaV47LPcFsvw48qgQIAptxTtmGV5XcQqYJJ3bvPAjm03+wr0A32cr4Z0cnByBz/dfNFxacEm6cWKflsu4CB931hDiI0CLveTgElNR0TKdNG5tpM6/17WOowACANRhLjEMH+p5A7zpzAwJrWHEh5qrSpgPm08fJhrUfyWoRZ7kxXm7SoVHWlKvAw4QR1PNPYxcg3Tm1zgZ40/gYn3JSdnDf1KN25XRfxrHgSVbKl3XRL4+6TgzTyu7olONlYEXjpxuuX+UMyTX5oozyxNAC3UUHNXlRPMWhKLy5vbhLDsk5LFwM4j5PL0Edj6pdfuegclsZYqxwWXLdHWu98EKUdZaucFVFoHc77h9OgmSv/SzKAAjhOW+3vkJNuek4j342l9umu6y/czHEeu+pCaL3SnINM0z2vdFxCWzxeaaK7XbfVMU5B9ECs+yQ4g0LCK+GsPjMJcQ5dRz9fBa4MIZpSPeSMllmYTxOV2SLDyYuxukgrIABv7XkSnX1hCzB6p458jV0E6ofATNdRVRWO5Nla1svYQmUahgFdiOyaIQw08s3gH/jgngUaNlzoZcKyj9E/q5pyz5/aWEAL6mDPKh10qSsB0oMRK3anIZP7XqmZgRBBuyH1AZUqyccA/5Ej/kduJCub6xWnqRdKYxygG7v1kyVZ1/pYIgl7+rMFRxfyVX2NxRmk+qZowXYcz516yRgSrFk6gQIAlvfbabTrKTzLv4IZENwelHXfl4WXslsfsnsa4zt273aFD5O2efj961KGdB2u6gqADIrM6Du79nb70Hmqz15p+zqj+LRkSlQCaNUh7ssRF2h5Nq0+mR6fbfVXVCwDMn3ETtW8UuwacZmKFHx24rzCnR9HWKJgdmImuS2uG7ir1ggaJgBbQcM3cXvRmE+7exCfdTsPvhS15GuIhjHw7MaA2VeiXix6HIkoYP8vNDs5Oj26zfZUfvr0JTcMtzxvW4yWT5eIlyMSr7IbBIsv2Fhz5Px/ZefNIeJn0h71YMfqnUpLq4LzsITuGp7cmYL6Lhkl+toEkykfWXDvFNo9gLhU90KBAgDytWdZp7okr10lBmVx+V5mMkmYv7Pa6H2Xp+Ntgr5JxGac771oZs/46EQ4Kl7F6+OSDqyL0d0JVgOYOT3toNnEdYEe+Pv0xfl7PKG2OV2v7+Ud0Ko4PITt9tYUrBHI/LuDJl1D9MsEDwEToQIFhNjgfNlwHsvqWpOWUo1Km2h108cubdC8wv7pkMCJJagOb8XsfnYscT+FCQHOGv+PRIzKTxU1DtZe07i3ZTkvRyYh2e5PLvMRFBNM0RudybikzECPboeWd8EpKY2RUaesNZoXmpPeFh/LsRZQfgnOt9trxQGtKmVUT0b63Jt0sRe3ydYuYldp0PvO0CsClFihj4tv", "keyMaterialType":"ASYMMETRIC_PRIVATE" }, "status":"ENABLED", "keyId":2102918723, "outputPrefixType":"TINK" }] })"; constexpr absl::string_view kRs512JwkPublicKey = R"({ "keys":[{ "kty":"RSA", "n":"AKZtuHAGYy-1Mc78sdp1gOV3jMCJtO7NmhyLSproWcBnqSN1g9mB2EdB22-WLWhB_U_JlZRCdHT6CxPHSid0c9JJc-2CmiV9zU2sVTJUkCytOVS0hrcPEz5JK6a6VVy-Skc_1-I0D2YurXd0aRByDALC8heHMok6VQXW8qwHgRyc0Jr1RcbY-CF_SMlRXn88g4e3bnk1AJiPcmHsJOcwkanwlWxq46DxPv5ff0ruXN4gPDYU-6_J6yZJreYjwrl-LhkqzOkz6e-LE4sdI5WFJQR9cGGRMf4ktgF3kqFtcFNFkGtdOvw5MdLe0eaENDzZ8TZyQDgiHYl878x8uPPpmoeif5af_ZUAsrv_bV-h3RpSoTdTP4SlQMmP-3y2R2LxvUs_CiUahoVFwTt_bRHO0Qy-QwpTvAdJX8CzrK2auqycFawYm8xYjj_epTFSwBCJuZjamxpZSa29zTDqP4AXwt2-9LO-70j5muzDQL35czpBgaXSAEJkrM9du91OjkJ2vtYFVLjWougN5uVpEBx1Isk_KgreOgl3lF1vs2EjTuihaxJhM-17alJLmDL06ZEDsht2Uhu_ZExEfPwTKaR_-kfjlamuoLUvTtVhzNZuOHD_XAOrGafMjM9WVq_D5XjqF7WFnb_t4YIOQNmGeOeIFLb4LlR5nHB1HIHUpAWazrvl", "e":"AQAB", "use":"sig", "alg":"RS512", "key_ops":["verify"], "kid":"fVf-Qw" }] })"; constexpr absl::string_view kRawRs256PrivateKey = R"( { "primaryKeyId":234505441, "key":[{ "keyData":{ "typeUrl": "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PrivateKey", "value":"EosCEAEagQIAiatQ/c8O22Ke3tqUHEp7Fj457icKPRM5nTrK4qCrtRC77cZzwonJAc7lLM+UwHLoWNxao7PP6SQ2b2x6PcCx0aFMkJw4JgOguACtgJoxCgws46MxAlNVsd6I+nJWAfO+kb1fD8hU09tEmGxPibOoe7KilQQR7FVBwWjoXdTzMTWSmnHOgy8iLPn5mbp0VfwSjOiUwPZMsOHg1kUBv7q4mzxNjNLw53pXQFWHUJ8cvUK4im8iKuSCSLZEZc0TWvntuEl8xlRa2oBRdvlIzYgWEtRyAYtX49/E/ZzFwnsceGTn6UV/nv3gKapwVriaWJHa0lGeFRHa+aWDGpSPPArccSIDAQABGoACOgE5vcbpLpxt7d3Qu97R37xWMja2xKb+BnZIF5a04jRryjJsgdIGJEHlI61Osot3xEEL25+egU/ls6rUEoLHKVk55lA8BCBRLlXyxJWzBdW9cChJNP6hw7DMrCFShb4KVGOi0waIXz8qtsIj/RP6cCwC/qBZYOdHLlOiXC6mTNv0blQ2Cb9yfZZ1Lz855DH0l2/GMdZYXwb6JElM+u/vR7lxTp4Wc6kq/31PULDH7G+Ps+QpXxHMIqghgSWyRsJ9+SHv5yo7JxA58eTQEUXkI6RCJJQ3pSXjdveBzzPyN6ZCmjz91Np3oPh36dZtknW0UspZ6Jnpc5GLphkvG8GblSKBAQC/vcua6r6FGW0VO2yD93nWgX1qepmULYGw7lv+mfOvodPUr+8EqDZXaRzUqCHynhVfb1BDEsoxP9aLoPVFZoJbL1MqBnUx6X0FXoKu2FzqsEJYw2qnl4VLhFn7xebnR+vwv+MMYf+yvnIdcMfmrZhWmCS4hTFQlJDfxji2SPSdByqBAQC3znfJnB2xC7eDUCTSH49h/xW1YWaS6nTqXvk3LJeq4tX2WGBWxfCLh6xpNpzF31xCDdYlt+yGcy6UUBKr4TteePrWf6jY9TWJZO7FvAqIIIxaQv3a/0A4/sgzYcrr2ansWzhNtfCESxOaPFVfLE1wh/PpJBzbcltRbG/mEY3UxzKBAQCfvXhN5Pm6m1c0lCAwxVE88v5QYjlmqI7en4YG062gCbsX+0au45D6O7joNfaqUSdPLcZ5SsMmSp/sDbmpCuDZJNEtNtoWLgaZHYbUMa8fWp67onpNiz9ija4Fwnc/Ab1AAi0fGNnUyTL68gWoWcGLiw80pspR7qPPui1vN9KKqzqAASl2qg8Q6KHHwt4cdjHwbKfuozcHgdwih71XL2EC7jPed+XaieEJRfoz4PDbIQKCII3GEUjw9Kpf0WIjrhKX/IyTPgKlSbGnnywfWL3CbZ3HueGiuyFr81DoKMFujhgmQe7PpSPipx8w0Hs6oQeXNuDryloNi3T1lyQHEjcUPqqBQoABcIm6r6QyTlBactKBKEqyhkXF1tCvw7YR9herJoubM/xklWzU5J8bgSQ1h4dutlANutXFqeOInUufyPChP3inQhcirp3CccJFaMP9uevRMMhUxyOyQkpOfxnAe7hvCjRsDDZZqh5bi5siNzeIEnU1s7sq/0XvzZA7G5fGZgb+dZs=", "keyMaterialType":"ASYMMETRIC_PRIVATE" }, "status":"ENABLED", "keyId":234505441, "outputPrefixType":"RAW" }] })"; constexpr absl::string_view kRs256JwkPublicKeyWithoutKid = R"({ "keys":[{ "kty":"RSA", "n":"AImrUP3PDttint7alBxKexY-Oe4nCj0TOZ06yuKgq7UQu-3Gc8KJyQHO5SzPlMBy6FjcWqOzz-kkNm9sej3AsdGhTJCcOCYDoLgArYCaMQoMLOOjMQJTVbHeiPpyVgHzvpG9Xw_IVNPbRJhsT4mzqHuyopUEEexVQcFo6F3U8zE1kppxzoMvIiz5-Zm6dFX8EozolMD2TLDh4NZFAb-6uJs8TYzS8Od6V0BVh1CfHL1CuIpvIirkgki2RGXNE1r57bhJfMZUWtqAUXb5SM2IFhLUcgGLV-PfxP2cxcJ7HHhk5-lFf5794CmqcFa4mliR2tJRnhUR2vmlgxqUjzwK3HE", "e":"AQAB", "use":"sig", "alg":"RS256", "key_ops":["verify"] }] })"; constexpr absl::string_view kPs256PrivateKey = R"( { "primaryKeyId": 1803616132, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPrivateKey", "value": "QoABPzsxHq7K5f91YucwaXUDk7ERgE8pqLSc8w34gEnc/wo5vk0BamvQaWRVQQdzEfK+eqVbrHmWi5mhY9QXpOv0dhuhyvo8ZS0ya60cT6DYSu2LBLDHFa68Wp6SWbIwFN4X5uGC8DYvWpJU9PCYg6XUu67T37FhGFekGHTSXDLf9Ko6gAFm7TJOM/v8MbHkCpY5NTtda7fb09XBXFDSC2XFGKvOkfQrGEKdEAvOCffpTBHsyvZAEJag/p2OZ+4W2D3upPNFkrmtS9MSGU39o0kn2fd6Cw90w5S1gjfxgWDbZpzs4AvbpU436Zy2wZYjJSIG6xbjDuYwizrflPX/sq5GUpuCuTKAAW+ovScT/DR/doxZm+xykUTTfEr2W4pd5PpLQiI1gUA2UTnY6p0svW+IbbSaj6vTE8s6+STsTGYAteUgdFBo7Ao501XbAJpJQX4ONI6o66BUvvzy0S6VLs+YQ6MWpArvNnnzRo5NbznO6IESyumWNm+8HQMaJ12sAqpWOoH4bz1xKoAB02eSVf5ZSDiYa4uF85NvvAVvEVPOPAd2gOqXzOWH+AXtTHJ8n/gcvUMnFR3W7cdZdyY2HslV0qphvkL7mCwsoOUBH5dA+F10Ebmk4hU9XEkeQvgFVgffzyqKjG521WOnAXQXudhOkJgXqGoTB/fESyRvSqA7ZKwPL1dvZnpJRv8igAH8m64q3qJFFcHWsnUb3hS58BXm8aTuk8Reju8XDXjBa9DPy5UySS0P/Chyh8HF5PAIwWSXTYDtFvdve3UN28oxTzhZ1xsz86BOeF2lFHpZ1y8/uNzwLRTIYWCXhbAS+bGpQOUR4JJDjSyivJCBqrkMCDUWAXQSqIZzHnyD+wbP8RqAAkukY+fCuoTpXOd06ASnbIsb+ZF4y++LsoulcQ//wmemVEOihJcQDgAfcL0j6HTylFG2EJJMDoLVWv6sZgrYpR1O1g97IB8KsLvyLm1JHxb9rbTDBnKSWL72NSZWPfs/Q5y5SXRxSD1gJoL/pcL5uuOosJjIvQ2olVMryYAgbnsA5UHZP7N8YpX0njZxBl9/PFNrTkWBMr15+A0VqOGh0TGnE/D4iAAduMJn1f4a3ZYVC4FgxKVxLxkB3oOLZz+QXKvs61slwRjotY3BXoKeImedOFmZoOJCA9qD+9rT01mQ113Fi9ylkBD1VGqtvIoB1CZa4tZZkRyoAeIMU7vMUpESigIiAwEAARqAAtCag5YMvymg6QloWgfeXCnS7MgRgm4fOubRxytyzNSL+apbeHqjvZ9gZ+Uef2R6zBBr1aAZsKZH51pmjMamYPuvZPIndHTeDyngbiGHjuQtiBNw9LjtVFs7D4uFx7V39wmJsGDlByeQ0/Kv44DF2Ann8rODr2JEXH0qVlbxbRdT8wUoo0GsQ0FMdK3Sb4tCWU0Dlx5eDMIM6xaBEU3WbMAF4dtTCtVGr+vAGv2fE2VN0f6mPk1+/KoQQr/E/9cK6KKaxf8WiaqcsF5LVJ0MVYLvmhuvsqKKqyAr6G3Pyx3Rf/EfkKdqWH7B0pjw0irvuSassiCKMX16S3VLKw5eBw8QAQ==", "keyMaterialType": "ASYMMETRIC_PRIVATE" }, "status": "ENABLED", "keyId": 1803616132, "outputPrefixType": "TINK" } ] })"; constexpr absl::string_view kPs256JwkPublicKey = R"({ "keys":[{ "kty":"RSA", "n":"0JqDlgy_KaDpCWhaB95cKdLsyBGCbh865tHHK3LM1Iv5qlt4eqO9n2Bn5R5_ZHrMEGvVoBmwpkfnWmaMxqZg-69k8id0dN4PKeBuIYeO5C2IE3D0uO1UWzsPi4XHtXf3CYmwYOUHJ5DT8q_jgMXYCefys4OvYkRcfSpWVvFtF1PzBSijQaxDQUx0rdJvi0JZTQOXHl4MwgzrFoERTdZswAXh21MK1Uav68Aa_Z8TZU3R_qY-TX78qhBCv8T_1wrooprF_xaJqpywXktUnQxVgu-aG6-yooqrICvobc_LHdF_8R-Qp2pYfsHSmPDSKu-5JqyyIIoxfXpLdUsrDl4HDw", "e":"AQAB", "use":"sig", "alg":"PS256", "key_ops":["verify"], "kid":"a4D_hA" }] })"; constexpr absl::string_view kPs384PrivateKey = R"( { "primaryKeyId": 743880559, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPrivateKey", "value": "QsABGgBRiQlPP7T0l7qjag22t5qPSbLa/PkaEnEatcxTqtJ18qo9ncTqNa7Ts851twenilUdELx+HLARFmRtmYcJuanBNMIrJ4ua/I0+rWY2rU/NwxB39x3SglT2T/wvwOx0fZAhXPNqgF6m2aGLMsppgDN6TKrvWZdC8YTC1e+ZoDlq4miBuU+NEOOsrS6Zv0SW/ZI5OxUqvGqQwaaiiy0VCsIzpJjO8GkaPntCYnA6Z1MNZTREOUcncMg2MsPEmYslOsABxBOOesQfs2aiCmt50XjN9bUvTlu/Z9z6/k327kwLpWloxZuzZWz1LMpbchnmrNvl8uj+N8qSvaIk6/Gq2y6w5TtDEdELZuuNcCkUqnnOaUJyVqkZ10PwILL0Ig+tt4GSIGlEFmdt1cL9tdU8Za/IQTkYzDQG11iG6h6llYPmj4aJxeDc/wnon5dT1pMuW93uFygwXpSkYMIvzDBQys6sUGtRbPVjNRsndRVl9w8oiF5wvEeLMtAMpAUgFxmXdC5JMsABHN4zpQrc8qsuYZa57/5gCmi4qGhECQNdsJlu7YjqjScBcRQZEK5F4pUZl2lY4zGQlClRnXUgx/g6F9FGW/ENnHebfYQ63eg2wL/EqvWBujDdYjYvs1oUBXcMFSG66VAkOYkkS8a8JnQpOfEPCkvo4/Hmz32YXjExEZWe450v8KhE4JYsaEolyoH/EoDAfG++NoIfUR6A+slyXqeQlnWK8+GMitoLKaN6EMdc31YeVsioEhn/rFfzd7p5FlLbjqBJKsABzisQA/QhytqNUWQhnhYFSs9QF+Z10ZCuUxwaSZKmD8SV4JTiHcMy7LK7RGt3Btlf76HmTNVOtTTsjXbBftVv4HDNamPmtzg1ggZi05cjPYi3STFZu3lUVAv2tJP5gdjuMe7slW+MqECUfPyz7OkJRBVAPQl0fbH/FSeSb529H6R+/1uXQ9nmXmikUFEt5PvY77li7Qyb6p67B1krBQusW0Lk2SL1Fs8Y8bj/lkjJar86sxGIGl2JNfSwajyK/waJIsAB1o1XIXWE82dw1r/TmkhY+bF4vvApYMYSz7lhsK5shZcY6VeQMXNUY/SCMTTndHzUNmbwdi4NCbnNt/vEOvmZnvQ2Q3YNphd6BLfeZxEmBcPzUMDTKXNaZBLbe8j1HUtaOHoaCfVuLhxxDT8knntNZNIJNuGhAK8YweR96qKQSDyL1zZRXBqnPZlGNnVCDVx0ijMmAmAY43IC5/XCR5h03TwbiJTQ5tG3FImoSXqA7RmwTSr1ynR4EKmRWt34uiVFGoADF4o9gu4FGlXDarpwmxkGQwUESUpJUEI65LDD0Vk71q0ZMMWUg2AXDov5UFx5zQkxx0Hx1ncN/pNy4qyaL3NgGg82OTxtajflwarFm5S4gKp4Ly3jtVWEYJDxa8D6JA4O5xuUl+qSJhEEIcLdUYXU/x/aPISklyupxSF2ze07QG1yNYV3/IadLxOWTtPlos1R0HE+x9g8JAYVC4kt2fQ6ldmZaD6h9fJORqSr6i5mdikzGw1vrJs0XaGmIxuN+C9jAS031tkD15BgK9vd6wrlT9d5C/KDJT7zJShYnNTJ2E9vRXBby7AaiOGjeRx/E67oPzdWH/8qwsLNfkS4eYLT9nbwmIMQ7pWVxcatnWKzuQuYLpCR/O2iJlaSoO76Xuy8RklES38lB2+FNzHuHtN2xAPms74WAUX+dLrIlcA7ceWwUqeF8iyXL9vmCuMmd5kHZGxUJbzVpLOkRUdcDNtc1qXm8qufzWABOUtzVnkn1CuejH/Xv9IpbuCHhQEv8o4REooDIgMBAAEagAOsydNGtOTfNZ/Rmq6SayE30Yf1SwJwPRrZaWY77SrvH+TfUkh7bC2qGVBHCzN+44mYvkzhymy+QMFPy2HnIOrPMcwlECzrUmroAI16mPf/SErwazPGLLEVAveazGa7x7cXXgz5Xfmf1ouvSZ5EeT23Ob3rz7C+nsj8heW/WFvMd6OH+APXiDL4aN2IlgbCDWhYg0vpjNK/kMhLEgC/0cu7l+YEu2hXK9T2Jksd9Ql2rdGWPmIIFQQUwlVvrw99aIH/GgDuePe+mAB8aMPNDrZtWtVo4c6DYjhfY7EkFYny4XDpFGhykB8P+URkF637DoVowdeH+JXDE9Y241NtUeV6t91QdMwc7aMJHUkoqQjmnHtpUzt9BRW1hIGTvngsg2FKGQwI72j76Tuxk4Uv9WiFoIe0T19HEgzkxg4o/K89N/fwTIKsCqt4V3iiXQUI95ryfz0HBXfvUateA/kL/0F2gba5jqvFHBPMw2IvHPFamS+Wms1HECx1FJk8TMo4j+0QAg==", "keyMaterialType": "ASYMMETRIC_PRIVATE" }, "status": "ENABLED", "keyId": 743880559, "outputPrefixType": "TINK" } ] })"; constexpr absl::string_view kPs384JwkPublicKey = R"({ "keys":[{ "kty":"RSA", "n":"rMnTRrTk3zWf0ZqukmshN9GH9UsCcD0a2WlmO-0q7x_k31JIe2wtqhlQRwszfuOJmL5M4cpsvkDBT8th5yDqzzHMJRAs61Jq6ACNepj3_0hK8GszxiyxFQL3msxmu8e3F14M-V35n9aLr0meRHk9tzm968-wvp7I_IXlv1hbzHejh_gD14gy-GjdiJYGwg1oWINL6YzSv5DISxIAv9HLu5fmBLtoVyvU9iZLHfUJdq3Rlj5iCBUEFMJVb68PfWiB_xoA7nj3vpgAfGjDzQ62bVrVaOHOg2I4X2OxJBWJ8uFw6RRocpAfD_lEZBet-w6FaMHXh_iVwxPWNuNTbVHlerfdUHTMHO2jCR1JKKkI5px7aVM7fQUVtYSBk754LINhShkMCO9o--k7sZOFL_VohaCHtE9fRxIM5MYOKPyvPTf38EyCrAqreFd4ol0FCPea8n89BwV371GrXgP5C_9BdoG2uY6rxRwTzMNiLxzxWpkvlprNRxAsdRSZPEzKOI_t", "e":"AQAB", "use":"sig", "alg":"PS384", "key_ops":["verify"], "kid":"LFa3bw" }] })"; constexpr absl::string_view kPs512PrivateKey = R"( { "primaryKeyId": 803396643, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPrivateKey", "value": "QoACUsRKIPRhEtXtTxcFVM0/KMBMyzrafB6NNwb8cHSM0N9XGZEbeUh6EF5JGsbI0PndFyMk2wdhkCdtpdH7Bc/n7hLlW7yVR9fvPQMDoG6mITa0E2XXDkW/iJZ1cZhkiR4ptWMgNKm2xLlxOUTGcVr8+jKQ0Tb1TMsvojs3GeBLJ5jDtzq3HE6kcNY611L/hzft1aOb3+zJGRZpLcN3CuXVbhluTyrccl4V3jWN1KSejvj32zn5l0hRMYES9Ek2h686a+gqK4RYkbeP4QL7ZnT2tkG0rxfi5HlklmLn620YTzrlYpGd9x3ID7NnMjDfTz0mR/910p6JzVBloCbJ6Ai/JTqAApRrAvbP7oGaPN25FupqEWCrTZfpmOZuH2NT4h6KiB6/RxyrbRQWSh6bpRXsS/C8aHlnSj83nFT+G1j7qLINDbqHlrYD8aycRRuiLm5WWNtO6wQzpXmWmrSYutln9Yj6QWtIOIA0Pn4b1u1Aj7DudBpKhd8feihkZa9AHqmsolOi9FKILQ2FwAfmEGDXHtRjP6KrB6bMbg1XuLXrJT6xEBLyfSswsk/UnlHG3+q++jDp5tLPJnmqDgPcZ017PY71JoHE8QyNu2d4+Ng8+wOZxyYWPOvfgC12ZFaGso8do3+vG8C+HEIiHM9+brv4SyWaVZxFt3jn/aezXDlXbIsG4nMygAIJ7xT/Qz6vOVZSAvqRSVMXS20Awi1TnsgxHbUzImi6KMBRrlyFud0ltpQcZw98jlo5qB11d34HFnXTK1TOvNiB61Z2olr2+4Nt2MFPRu26r3uR3mhpacHW+TfkHw5whudHpybXkFc2asiL8auAToS2i2pr1hSOqKUDI0B6qy+qjDjWUCDziJE+IcpWjTEY74UpE5rREBIer5Xci8FPCP4FFjfomAtZZSGgS3DHwnCh9NfqyLZTGdDVJe+MEMlAFFmFUcCAk708H16bqJ8UuJMdGoFqvxU9bJrLGDkAg/CttX0BI6OCs5DR4Rqy+XKHYIkIvy6DVFja3mmhIhAVXXQHKoACvAckkJ1ayoNwbcV11yOBd0qNmPl0+NWdGlkc7+Aft6rLAR25t2tpfEjsFFYEaNCQIlzJNLAXa41Ac7cGdOLx+nRAJI3d/ExRLXhJrbAD95YM6WSM8cXf0dsR+q3hoTE0522T1XwSXICXb1Z2hzfmghL5WigezMdsEolqF/pRpQUcnZug/mpa0P40evFEIsoiPpMJYwS67iETxKeeEJv55z1W5GkT5reEeRwkQIuJm3kZB2r95p2sU82PFyXMVjgnqcqUAKWudi+oRp3jhzd0IUMQg6gcm62kpF7XgQmobMPYloc2c5VIEM1NS52s4arADR7dFxU6R28paLea8LsCByKAAvzUpants7GpQz2rJ7Gl9x0uQjr48yetqeTyzxInjezcKGgO7s85c2GzO3MkeaYcT+68NXHtdUVXrXJYerAiH+PAA2CdouEg8ra/ZOl0t3x9402kkFYcwbzmI1O0TLV4kv6NONapFj7U2WYfj0IdVILYoJWS4PSvvMWrDzP2SlZ7alSZ0zqCUGYa47Mz9d9A7d2teQ6z3UdzrUw3EBWz83szslYXQg6QDtsF+PYUhNx0tBuAdUtF4kVFXPSZoaOzaKdYwxb9TApmRheVsmOVAqb7xtwo9WmqUuJgDADjlfxwA9cam+uggvogd7Ta3i48SbJG6RXboaydht1F0AYeKZsagAQVZNwC5x8yE/nFakDyvtlO5SHR/1qvzhE0ZCepOIEmCmGTubQs5JwMllGJWhwxucVVv/5Rq9CsYjn+fpV8uj6DC2qqMiSIag+SuKjymACBktQuGGOiByYQExwMC8/ry326ehPAy588K9SM8ZuDeCswvp/cWs0aUDOlGsuXtJrKgKXdr8zDnbmZvrTIzA+nDC7R7Kv6NaBTF613XwIPIw0oPSDij0OPHy72+9BLraTRJVQP8GbvSWLb0YraMW2lyYNQN7Djd8rpO2AYKfsJAmmax/HFyPGMuKm2SjlnSxo8bmvH69DGjyK7wkU7bLJQ5Lbp98DpauhGY3EdXispU2fnJkoa9DaDmEzArRGa+T05YCyuzezuYE4eBUlxXJj2QY5ABDH5VkxcnWPSftKUUG5TSRwnIKZQ2Ab2ONNOQDafSOsg2KYDBKmLw4ZxUp2I2izXPeICfCJ2sBW2IOwSK5tRcvno8QoMvkz+9Ci8QNRpNLYTiCgbxXaoW/eLayvKt3qhkj+rKMded7yzWjq2dNv3HfvPUIwtSlAHGSqEhGkuzSijHhp2s2LN5OB6mfQt6d4pzvlh5w+pxaK3sH/wsLoVsdvUg4OBaH+KBFVYRZ9eAQMU8a6fmoFreMpSiNS6B0jY7XPsCL3mgSAuzkojCx2YBh79VB9SjcKrGGdRYLot/RKKBCIDAQABGoAEubM3lgyGn8IyKO+56q18hvuJkkxPrDXgalRWNmnA3QEseglU/9tp598dlq04eF1G4Xkrmk9OVyVSCuRdvMoko6wP4Jum+3cn42/Gsk8PdTwm3WD+yEBg/Usa/omLGiTfktyqqoZhh1TeOOBtNpD1U/p1wQxP3+bLl4//uR75CqlK9FYdBrIuqLP3nqa3/OAFuPBX77BuD1kcr5pUxPZkXBNAWpnvsW56swyIMZF2GRhfv2n2bZJgT4iybQcmEnvt1wfY3ecO5ZMSX2QNKpnRRejlIEqR9uAQa4wIJMViL8jDbAV+ZvUjMM1G0aAyMHPQzb2Hfkr9OtEi+/xyUCwqF2IUZfUb0+mCjOutpbBlSfkYULOrwd9RQTaLeNe3GhRjYWTJ+gLDS8DUWz8AcpCI7xoQSfuZLmBwxslqsObMYolxQJXej1IDmGX+Rjr4ro80EpMkv67gxYQwjP8p7FMHfK7FSDZMtT+h4mO7AD68vwHd99c9ALDJfPO7tAMG53opzD7YEZU+ySKRcMBIFRe5Kxj+m1fbN9q2ictzoQOvKh8TBlCsPLRbF5WVheUtE9anKiIik5zQInihoZidH5YJksdipMVWLeRs1Qk5J8ddv7n2dlbW7zoC60sh3ubLQ/MDm+eHlXoeKGioCMjDABRdokqal4wugvQUZyQcBBtfWT0QAw==", "keyMaterialType": "ASYMMETRIC_PRIVATE" }, "status": "ENABLED", "keyId": 803396643, "outputPrefixType": "TINK" } ] })"; constexpr absl::string_view kPs512JwkPublicKey = R"({ "keys":[{ "kty":"RSA", "n":"ubM3lgyGn8IyKO-56q18hvuJkkxPrDXgalRWNmnA3QEseglU_9tp598dlq04eF1G4Xkrmk9OVyVSCuRdvMoko6wP4Jum-3cn42_Gsk8PdTwm3WD-yEBg_Usa_omLGiTfktyqqoZhh1TeOOBtNpD1U_p1wQxP3-bLl4__uR75CqlK9FYdBrIuqLP3nqa3_OAFuPBX77BuD1kcr5pUxPZkXBNAWpnvsW56swyIMZF2GRhfv2n2bZJgT4iybQcmEnvt1wfY3ecO5ZMSX2QNKpnRRejlIEqR9uAQa4wIJMViL8jDbAV-ZvUjMM1G0aAyMHPQzb2Hfkr9OtEi-_xyUCwqF2IUZfUb0-mCjOutpbBlSfkYULOrwd9RQTaLeNe3GhRjYWTJ-gLDS8DUWz8AcpCI7xoQSfuZLmBwxslqsObMYolxQJXej1IDmGX-Rjr4ro80EpMkv67gxYQwjP8p7FMHfK7FSDZMtT-h4mO7AD68vwHd99c9ALDJfPO7tAMG53opzD7YEZU-ySKRcMBIFRe5Kxj-m1fbN9q2ictzoQOvKh8TBlCsPLRbF5WVheUtE9anKiIik5zQInihoZidH5YJksdipMVWLeRs1Qk5J8ddv7n2dlbW7zoC60sh3ubLQ_MDm-eHlXoeKGioCMjDABRdokqal4wugvQUZyQcBBtfWT0", "e":"AQAB", "use":"sig", "alg":"PS512", "key_ops":["verify"], "kid":"L-LcIw" }] })"; constexpr absl::string_view kRawPs256PrivateKey = R"( { "primaryKeyId": 1629784556, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPrivateKey", "value": "QoABP9TTJpZ3lfj28Zh9hqHMNydjyJGup+Q8xjYubqsE+E3AlnSIvRDp9r0VVHZzsHBEdKtQQgCW4FT0I7Cy4z4W3ecKskuJWFYYn0PYOXLZoFo2MF3yZ0wI04aWhRS2+Zwl3BSr1eu84jiCm9rTsODyZ0MQORvpeBVaX9Y2IOPclvQ6gAGBpXDhI/1yKJq6vlymUBwKS2FG9Tf3as3YkH2B0b7wtv1Ir+WEa78ub52BwxnOKsf3V57WLnuQppLiw/bvHFxKVDNuWGiGTzEVhJW2qK3RgryXtqzkACm6cjL1FT22B9VmVx/GqWOOOLX4He1pq+UYkboWgXVkAdP0OaPv2hWIMTKAASnEMbcFq+ZbOJIJBwZXsSmrdSnfg8A2kwuatK2U2Of7/YCE5i11CUjWUvi99plk8g/mAinYu0Gfw6YSRgbWsAvK4GsIJ4322WT1yy4g6XuncL8MKC2rCYIkhFWpI1qcsS/PxU3zWMYodV6GjK31HXvqczlJfBYNEBo9HxeYDtchKoAB0vRt2QsYTMSVYw1gIDeKdHnhMDaakaIazjc4o+DCQSk+dU0EStSn8GHON0nIrEA8A5UHqF8/yh1mW+M0mkSaSiBp+7CLAowEu72wgdrymK/e6eIELH+joEDDgWpcF/WMEWSvls2a0q1atiYvC2ERLuSxSFjoJ8IRKVfVmjPi53EigAHUpqb3E/I863RAT2ocS5CnT7A8PBgttZqIyR1H8iC2bocre8H+8z8fVf4SeYsLhqvuBcTPXxZSUT+ZVf+LeELfmcd54savTU/yTQJ27s8WIkuLeTj+80FWCVtengLwP+Bte7nyzqbuXSWHUTUSVTCMK5PiBdWrOElVYlp3JxvTxRqAAgNrTEVGQYjy+xnFbKHHmGr7olwVAi1lqCGQDDZKMQH2fZOQqURH13MhdpPEL8LlKYuLejl5B+hzLaTWOqxx4TmD9Df3nMwAC0ELpDUAfz4e2quvuRD28+cR9u0G560ON53sJPbqPGVlbtaDmpn8nzvCOmczpoGmtzcBeZ/4GeEHThzq1sRE+tBJ6B4oS8R4LUtldg+FBUnZgqJvSC1gYYHO7oySCPC5V0R3EhpWDcVbYf7PyMC7oaxIPmCAu5Wc4DFirh13BAZI2FKW+Np/heZAjYUKa4Gtb0dMxvLwz3OcPPa/AQKSjko6aMRAQvjgd/UgQ+Sr496td45I4JGandESigIiAwEAARqAAq87vw0RbcxaTFMvrVwvfGMbcgEsvt4VbTNV/SosAKGoUn3e1X8yJSF3G591XsJGQbShgvfLBkCUkFgPhGoDozA7muKwBlQmfQo9NdTMctXto+sO6kQrnbVmjKK5nzKT+p9obetR5GZEA2SJW3Ub69tBpX9iloHfCoEqBGSkuwIyB76BmyQlOwO2o2zjcironK2KtV2LOG9XWEqkOFSGWnouTUDO/7XXWCZfpUijd5ixD4XVih1n9a1Xw2yTaGwG6jewu9K1CiUtw2ZMKPqt/kDqGZXiVyk17q3UQIU+up32vtX+4nZiDt+y8EXl/M64A1pjGT2dpqXwPOnSJZJJPPUQAQ==", "keyMaterialType": "ASYMMETRIC_PRIVATE" }, "status": "ENABLED", "keyId": 1629784556, "outputPrefixType": "RAW" } ] })"; constexpr absl::string_view kPs256JwkPublicKeyWithoutKid = R"({ "keys":[{ "kty":"RSA", "n":"rzu_DRFtzFpMUy-tXC98YxtyASy-3hVtM1X9KiwAoahSfd7VfzIlIXcbn3VewkZBtKGC98sGQJSQWA-EagOjMDua4rAGVCZ9Cj011Mxy1e2j6w7qRCudtWaMormfMpP6n2ht61HkZkQDZIlbdRvr20Glf2KWgd8KgSoEZKS7AjIHvoGbJCU7A7ajbONyKuicrYq1XYs4b1dYSqQ4VIZaei5NQM7_tddYJl-lSKN3mLEPhdWKHWf1rVfDbJNobAbqN7C70rUKJS3DZkwo-q3-QOoZleJXKTXurdRAhT66nfa-1f7idmIO37LwReX8zrgDWmMZPZ2mpfA86dIlkkk89Q", "e":"AQAB", "use":"sig", "alg":"PS256", "key_ops":["verify"], }] })"; // contains the public key of both kRs256PrivateKey and kRs384PrivateKey constexpr absl::string_view kJwkPublicKeySet = R"({ "keys":[{ "kty":"RSA", "n": "vmUOa62TYrxj7N8rZVAzoEdSnmsRQaNWBMAdB8adGa8n4ycGiYWoGv0uZWc8vH2jn6l3Pa_72bb2IHf3-KD2UaTwLk1x3yShXybEoS5ZF9bemzrn2ohNixGoN7Ofj7wPb61Z-F1Nv53nq308z-RI1WeyIH-9HjuIcuUxaWY0VevsXzCehMJP5g7kVzyl55bYcRi28didkVazrzVgNG35yNNMEL32oW1Vfvvp7hfQHtxSwkFOPzJgzIPHbJFbxALGrrgXHsoq7UtDQdS9vvoEp4_JzQhCtnCEKahgkTwOWyT96OlRGYiPJSFHWTujy1Qnd6OKc8LGEspAX4oD6Zl-YQ", "e":"AQAB", "use":"sig", "alg":"RS256", "key_ops":["verify"], "kid":"TCGiGw" }, { "kty":"RSA", "n":"AI83_8Uy0v4xS6kDZKqcqzSbeyksy2C67ajtI41J2KMDtO9jUaEAQ9uDhMubjZzPYh1wf_gtJgAC5PSiI3fOLUG0AHCbi_yXVfH3_1U_Yl4b_e8yx_NPyuIvwHwXwE5a32hiss9PuY2-qEivH5LK4AXxPiTiUc9x4gh1OwZaSTYWT7SRO-0ROwYwCwpg4Uf0IMLtmHou_NmNw0uOlOgKfx-EFmMzV-5pspEnwsHq_ijFSxmHNAdy5S0n4u1LIKKmgXJIyUu3AKfAJMydn6nTKzrOcpX0yMnxPq9yP8xKuK_mXysFyNvmS0Sq5c-grOETFeMFScweoUpWVnYOCCSyZ93yAhsTUWnDjZd7iuji9Y7zUo4PWlKXyRRz_aSpxrsn70LOZNLLUjILVeyfCRs2JXptfxCNg3wg6FVAH0xTORmPGICgWDmwOFgP1Y6tW-p0cnK8LwVkuRclyKAMvTtYm9xZZHUSjw86rHEnB2VfsPTIn0_WAVnJ2OAKhuVMtwjB7Q", "e":"AQAB", "use":"sig", "alg":"RS384", "key_ops":["verify"], "kid":"FVLRIg" }] })"; constexpr absl::string_view kEs256PrivateKey = R"( { "primaryKeyId": 303799737, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey", "value": "GiA2S/eedsXqu0DhnOlCJugsHugdpPaAGr/byxXXsZBiVRJGIiDuhGJiGeaQ/qeqt1daC2xZRarm4VEsmSHJUWJY9EHbvxogwO6uIxh8SkKOO8VjZXNRTteRcwCPE4/4JElKyaa0fcQQAQ==", "keyMaterialType": "ASYMMETRIC_PRIVATE" }, "status": "ENABLED", "keyId": 303799737, "outputPrefixType": "TINK" } ] })"; constexpr absl::string_view kEs256JwkPublicKey = R"({ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES256","key_ops":["verify"], "kid":"EhuduQ"}] })"; constexpr absl::string_view kEs384PrivateKey = R"( { "primaryKeyId": 2145899635, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey", "value": "GjCfHcFYHsiwTcBCATSyjOyJ64iy4LGa4OuFaR9wZqkYTuYrY1I3ssxO4UK11j/IUe4SZiIwwQcqkI9pV66PJFmJVyZ7BsqvFaqoWT+jAFvYNjsgdvAIpyB3MHWXkxNhlPYcpEIfGjAARQJOQqFEMSAnalOLI+hKwg4RHLCsHbGMEOBQfwsuDQCj3FPZLEpp3Et1EUivwuUQAg==", "keyMaterialType": "ASYMMETRIC_PRIVATE" }, "status": "ENABLED", "keyId": 2145899635, "outputPrefixType": "TINK" } ] })"; constexpr absl::string_view kEs384JwkPublicKey = R"({ "keys":[{"kty":"EC","crv":"P-384", "x":"AEUCTkKhRDEgJ2pTiyPoSsIOERywrB2xjBDgUH8LLg0Ao9xT2SxKadxLdRFIr8Ll", "y":"wQcqkI9pV66PJFmJVyZ7BsqvFaqoWT-jAFvYNjsgdvAIpyB3MHWXkxNhlPYcpEIf", "use":"sig","alg":"ES384","key_ops":["verify"],"kid":"f-fUcw"}] })"; constexpr absl::string_view kEs512PrivateKey = R"( { "primaryKeyId": 1480242041, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey", "value": "GkIBnhWq6UrOj8hKwGovjSsLT+dtAGlRqoIkQ2FzMeKxIApx0dT3O4yHrmi6v5sElZHM6BsLz47IopAOajVRYGh48b0SigEiQgDWSuSY03DQCrXs5lxbw0pK8XcT4rl9rj6uqEdzNKW9sKp3wy/p1nlnCm9pwDsWEssnbK2ffG8QS+tJRK9tMdRnPxpCAKRFrHHoTaFAO+d4sCOw78KyUlZijBgqfp2rXtkLZ/QQGLtDM2nScAilkryvw3c/4fM39CEygtSunFLI9xyUyE3mEAM=", "keyMaterialType": "ASYMMETRIC_PRIVATE" }, "status": "ENABLED", "keyId": 1480242041, "outputPrefixType": "TINK" } ] })"; constexpr absl::string_view kEs512JwkPublicKey = R"({ "keys":[{"kty":"EC","crv":"P-521", "x":"AKRFrHHoTaFAO-d4sCOw78KyUlZijBgqfp2rXtkLZ_QQGLtDM2nScAilkryvw3c_4fM39CEygtSunFLI9xyUyE3m", "y":"ANZK5JjTcNAKtezmXFvDSkrxdxPiuX2uPq6oR3M0pb2wqnfDL-nWeWcKb2nAOxYSyydsrZ98bxBL60lEr20x1Gc_", "use":"sig","alg":"ES512","key_ops":["verify"],"kid":"WDqzeQ"}] })"; constexpr absl::string_view kRawEs256PrivateKey = R"( { "primaryKeyId": 765975903, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey", "value": "GiCbUAItoAVleOSwYdPWs563CCFhGHSdX4t/C2xBY2J/ERJGIiAA7lMx7mU1yMmm4aOMa0d3iBf084b12H+8b7ym2nscmxogytH8MlvqTx3X+eL0pdx4ULKUb2YOi2DPnIPpSaIk28MQAQ==", "keyMaterialType": "ASYMMETRIC_PRIVATE" }, "status": "ENABLED", "keyId": 765975903, "outputPrefixType": "RAW" } ] })"; constexpr absl::string_view kEs256JwkPublicKeyWithoutKid = R"({ "keys":[{ "kty":"EC", "crv":"P-256", "x":"ytH8MlvqTx3X-eL0pdx4ULKUb2YOi2DPnIPpSaIk28M", "y":"AO5TMe5lNcjJpuGjjGtHd4gX9POG9dh_vG-8ptp7HJs", "use":"sig","alg":"ES256","key_ops":["verify"]}], })"; constexpr absl::string_view kEs256WithBiggerCoordinates = R"( { "primaryKeyId":858766452, "key":[ { "keyData": { "typeUrl":"type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey", "value":"EAEaIQAocb/rp/rsVlYMqlR2KB18kpSAPURySedsnfswHoqEviIhANrIMzHBtAQvDOKUf3BYVmV+AfwKyA0lq9gHOTY3gVm+", "keyMaterialType":"ASYMMETRIC_PUBLIC" }, "status":"ENABLED", "keyId":858766452, "outputPrefixType":"TINK"}] })"; constexpr absl::string_view kEs256JwkWithEncodedBiggerCoordinates = R"({ "keys":[{ "alg":"ES256", "crv":"P-256", "key_ops":["verify"], "kid":"My-8dA", "kty":"EC", "use":"sig", "x":"KHG_66f67FZWDKpUdigdfJKUgD1EcknnbJ37MB6KhL4", "y":"2sgzMcG0BC8M4pR_cFhWZX4B_ArIDSWr2Ac5NjeBWb4"}], })"; constexpr absl::string_view kEs256WithSmallCoordinates = R"( { "primaryKeyId": 2124611562, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey", "value": "EAEaH2lFjtbwLgtzRDh7dV9sYmW4IWl3ZKA+WghvrQPiCNoiIEJ8pQXMyA/JywaGWT+IHmWxuVYWqdxkPsUSHLhSQm51", "keyMaterialType": "ASYMMETRIC_PUBLIC" }, "status": "ENABLED", "keyId": 2124611562, "outputPrefixType": "TINK" } ] })"; constexpr absl::string_view kEs256JwkWithEncodedSmallCoordinates = R"({ "keys":[{ "alg":"ES256", "crv":"P-256", "key_ops":["verify"], "kid":"fqL_6g", "kty":"EC", "use":"sig", "x":"AGlFjtbwLgtzRDh7dV9sYmW4IWl3ZKA-WghvrQPiCNo", "y":"QnylBczID8nLBoZZP4geZbG5Vhap3GQ-xRIcuFJCbnU"}], })"; constexpr absl::string_view kEs384WithSmallCoordinates = R"( { "primaryKeyId": 4159170178, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey", "value": "EAIaL/bm1+e6X7gat+MJK3e65BGlZzKIf6I1q0Ro8zAKeyryUxgvZl8Ww/NlcVN2XJhEIjA3b73hm8eDfSEEUAAaJbrLZFOFGnSdTWng116r+hOvszYiov+WrsTyIgnL/9aRdN8=", "keyMaterialType": "ASYMMETRIC_PUBLIC" }, "status": "ENABLED", "keyId": 4159170178, "outputPrefixType": "TINK" } ] })"; constexpr absl::string_view kEs384JwkWithEncodedSmallCoordinates = R"({ "keys":[{ "alg":"ES384", "crv":"P-384", "key_ops":["verify"], "kid":"9-fmgg", "kty":"EC", "use":"sig", "x":"APbm1-e6X7gat-MJK3e65BGlZzKIf6I1q0Ro8zAKeyryUxgvZl8Ww_NlcVN2XJhE", "y":"N2-94ZvHg30hBFAAGiW6y2RThRp0nU1p4Ndeq_oTr7M2IqL_lq7E8iIJy__WkXTf"}], })"; constexpr absl::string_view kEs512WithSmallCoordinates = R"( { "primaryKeyId": 1286030637, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey", "value": "EAMaQUgdEssWf+tdFT3vSoy/OAotV501af+XQ6JSXDjnOPCzZnFh8fYwrJ8Yu8XYF33IeHBdAIKyicKuW884JkjYR1qJIkH2OWoa4SOmk0FtpeRBZHPbs7U8SMFXVkaV+HZtjmfl11QGiQU9hqUhoW9ock2K0xg6wdcWBe67YTVFdQbThFmtCg==", "keyMaterialType": "ASYMMETRIC_PUBLIC" }, "status": "ENABLED", "keyId": 1286030637, "outputPrefixType": "TINK" } ] })"; constexpr absl::string_view kEs512JwkWithEncodedSmallCoordinates = R"({ "keys":[{ "alg":"ES512", "crv":"P-521", "key_ops":["verify"], "kid":"TKdFLQ", "kty":"EC", "use":"sig", "x":"AEgdEssWf-tdFT3vSoy_OAotV501af-XQ6JSXDjnOPCzZnFh8fYwrJ8Yu8XYF33IeHBdAIKyicKuW884JkjYR1qJ", "y":"APY5ahrhI6aTQW2l5EFkc9uztTxIwVdWRpX4dm2OZ-XXVAaJBT2GpSGhb2hyTYrTGDrB1xYF7rthNUV1BtOEWa0K"}], })"; class JwkSetConverterTest : public testing::TestWithParam { void SetUp() override { ASSERT_THAT(JwtSignatureRegister(), IsOk()); } }; TEST_P(JwkSetConverterTest, ToAndFromPublicKeysetHandleIsIdentical) { std::string jwk_set = GetParam(); // Convert JWK set to KeysetHandle util::StatusOr> keyset_handle = JwkSetToPublicKeysetHandle(jwk_set); ASSERT_THAT(keyset_handle, IsOk()); // Convert KeysetHandle to JWK set util::StatusOr output = JwkSetFromPublicKeysetHandle(**keyset_handle); ASSERT_THAT(output, IsOk()); // Check that output is the same as jwk_set. The order of the elements may // have changed. util::StatusOr output_struct = jwt_internal::JsonStringToProtoStruct(*output); ASSERT_THAT(output_struct, IsOk()); util::StatusOr expected_struct = jwt_internal::JsonStringToProtoStruct(jwk_set); ASSERT_THAT(expected_struct, IsOk()); std::string differences; MessageDifferencer message_differencer; message_differencer.ReportDifferencesToString(&differences); EXPECT_TRUE(message_differencer.Compare(*output_struct, *expected_struct)) << differences; } INSTANTIATE_TEST_SUITE_P( JwkSetConverterTest, JwkSetConverterTest, testing::Values(kEs256JwkPublicKey, kEs384JwkPublicKey, kEs512JwkPublicKey, kEs256JwkPublicKeyWithoutKid, kRs256JwkPublicKey, kRs384JwkPublicKey, kRs512JwkPublicKey, kRs256JwkPublicKeyWithoutKid, kPs256JwkPublicKey, kPs384JwkPublicKey, kPs512JwkPublicKey, kPs256JwkPublicKeyWithoutKid)); class JwkSetToPublicKeysetHandleTest : public testing::TestWithParam> { void SetUp() override { ASSERT_TRUE(JwtSignatureRegister().ok()); } }; TEST_P(JwkSetToPublicKeysetHandleTest, VerifyValidJwtWithSuccess) { std::string private_keyset; std::string jwk_public_keyset; std::tie(private_keyset, jwk_public_keyset) = GetParam(); // Create a valid jwt using the private key util::StatusOr> reader = JsonKeysetReader::New(private_keyset); EXPECT_THAT(reader, IsOk()); util::StatusOr> private_handle = CleartextKeysetHandle::Read(std::move(*reader)); EXPECT_THAT(private_handle, IsOk()); util::StatusOr> sign = (*private_handle) ->GetPrimitive( ConfigGlobalRegistry()); ASSERT_THAT(sign, IsOk()); util::StatusOr raw_jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr compact = (*sign)->SignAndEncode(*raw_jwt); ASSERT_THAT(compact, IsOk()); // verify the JWT using the JWK public keys util::StatusOr> public_handle = JwkSetToPublicKeysetHandle(jwk_public_keyset); ASSERT_THAT(public_handle, IsOk()); util::StatusOr> verify = (*public_handle) ->GetPrimitive( ConfigGlobalRegistry()); ASSERT_THAT(verify, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .ExpectIssuer("issuer") .AllowMissingExpiration() .Build(); util::StatusOr verified_jwt = (*verify)->VerifyAndDecode(*compact, *validator); ASSERT_THAT(verified_jwt, IsOk()); EXPECT_THAT(verified_jwt->GetIssuer(), IsOkAndHolds("issuer")); } INSTANTIATE_TEST_SUITE_P( JwkSetToPublicKeysetHandleTest, JwkSetToPublicKeysetHandleTest, testing::Values( std::make_tuple(std::string(kRs256PrivateKey), std::string(kRs256JwkPublicKey)), std::make_tuple(std::string(kRs384PrivateKey), std::string(kRs384JwkPublicKey)), std::make_tuple(std::string(kRs512PrivateKey), std::string(kRs512JwkPublicKey)), std::make_tuple(std::string(kRawRs256PrivateKey), std::string(kRs256JwkPublicKeyWithoutKid)), std::make_tuple(std::string(kRs256PrivateKey), std::string(kJwkPublicKeySet)), std::make_tuple(std::string(kRs384PrivateKey), std::string(kJwkPublicKeySet)), std::make_tuple(std::string(kEs256PrivateKey), std::string(kEs256JwkPublicKey)), std::make_tuple(std::string(kEs384PrivateKey), std::string(kEs384JwkPublicKey)), std::make_tuple(std::string(kEs512PrivateKey), std::string(kEs512JwkPublicKey)), std::make_tuple(std::string(kRawEs256PrivateKey), std::string(kEs256JwkPublicKeyWithoutKid)), std::make_tuple(std::string(kPs256PrivateKey), std::string(kPs256JwkPublicKey)), std::make_tuple(std::string(kPs384PrivateKey), std::string(kPs384JwkPublicKey)), std::make_tuple(std::string(kPs512PrivateKey), std::string(kPs512JwkPublicKey)), std::make_tuple(std::string(kRawPs256PrivateKey), std::string(kPs256JwkPublicKeyWithoutKid)))); TEST_F(JwkSetToPublicKeysetHandleTest, InvalidJsonFails) { std::string invalid_json = R"({[}])"; EXPECT_THAT(JwkSetToPublicKeysetHandle(invalid_json), Not(IsOk())); } TEST_F(JwkSetToPublicKeysetHandleTest, Rs256WithSmallModulusGetPrimitiveFails) { std::string jwt_set = R"( {"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "use":"sig", "alg":"RS256", "key_ops":["verify"], "kid":"DfpE4Q" }] })"; // The keys in the keyset are validated when the primitive is generated. // So JwkSetToPublicKeysetHandle succeeds, but GetPrimitive fails. util::StatusOr> public_handle = JwkSetToPublicKeysetHandle(jwt_set); ASSERT_THAT(public_handle, IsOk()); util::StatusOr> verify = (*public_handle) ->GetPrimitive( ConfigGlobalRegistry()); EXPECT_THAT(verify, Not(IsOk())); } TEST_F(JwkSetToPublicKeysetHandleTest, Rs256CorrectlySetsKid) { std::string jwt_set = R"( {"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "use":"sig", "alg":"RS256", "key_ops":["verify"], "kid":"DfpE4Q" }] })"; util::StatusOr> public_handle = JwkSetToPublicKeysetHandle(jwt_set); EXPECT_THAT(public_handle, IsOk()); const google::crypto::tink::Keyset &keyset = CleartextKeysetHandle::GetKeyset(**public_handle); ASSERT_THAT(keyset.key_size(), Eq(1)); EXPECT_THAT(keyset.key(0).output_prefix_type(), Eq(google::crypto::tink::OutputPrefixType::RAW)); google::crypto::tink::JwtRsaSsaPkcs1PublicKey key; key.ParseFromString(keyset.key(0).key_data().value()); EXPECT_THAT(key.custom_kid().value(), Eq("DfpE4Q")); } TEST_F(JwkSetToPublicKeysetHandleTest, Rs256WithoutOptionalFieldsSucceeds) { std::string jwt_set = R"( {"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "alg":"RS256", }] })"; EXPECT_THAT(JwkSetToPublicKeysetHandle(jwt_set), IsOk()); } TEST_F(JwkSetToPublicKeysetHandleTest, Rs256WithoutKtyFails) { std::string jwt_set = R"( {"keys":[ {"n":"AQAB", "e":"AQAB", "use":"sig", "alg":"RS256", "key_ops":["verify"], "kid":"DfpE4Q" }] })"; EXPECT_THAT(JwkSetToPublicKeysetHandle(jwt_set), Not(IsOk())); } TEST_F(JwkSetToPublicKeysetHandleTest, Rs256WithoutAlgFails) { std::string jwt_set = R"( {"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "use":"sig", "key_ops":["verify"], "kid":"DfpE4Q" }] })"; EXPECT_THAT(JwkSetToPublicKeysetHandle(jwt_set), Not(IsOk())); } TEST_F(JwkSetToPublicKeysetHandleTest, Rs256InvalidKtyFails) { std::string jwt_set = R"( {"keys":[ {"kty":"EC", "n":"AQAB", "e":"AQAB", "use":"sig", "alg":"RS256", "key_ops":["verify"], "kid":"DfpE4Q" }] })"; EXPECT_THAT(JwkSetToPublicKeysetHandle(jwt_set), Not(IsOk())); } TEST_F(JwkSetToPublicKeysetHandleTest, Rs256InvalidAlgFails) { std::string jwt_set = R"( {"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "use":"sig", "alg":"RS257", "key_ops":["verify"], "kid":"DfpE4Q" }] })"; EXPECT_THAT(JwkSetToPublicKeysetHandle(jwt_set), Not(IsOk())); } TEST_F(JwkSetToPublicKeysetHandleTest, Rs256InvalidKeyOpsFails) { std::string jwt_set = R"( {"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "use":"sig", "alg":"RS256", "key_ops":["verify "], "kid":"DfpE4Q" }] })"; EXPECT_THAT(JwkSetToPublicKeysetHandle(jwt_set), Not(IsOk())); } TEST_F(JwkSetToPublicKeysetHandleTest, Rs256InvalidKeyOpsTypeFails) { std::string jwt_set = R"( {"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "use":"sig", "alg":"RS256", "key_ops":"verify", "kid":"DfpE4Q" }] })"; EXPECT_THAT(JwkSetToPublicKeysetHandle(jwt_set), Not(IsOk())); } TEST_F(JwkSetToPublicKeysetHandleTest, Rs256InvalidUseFails) { std::string jwt_set = R"( {"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "use":"zag", "alg":"RS256", "key_ops":["verify"], "kid":"DfpE4Q" }] })"; EXPECT_THAT(JwkSetToPublicKeysetHandle(jwt_set), Not(IsOk())); } TEST_F(JwkSetToPublicKeysetHandleTest, Rs256WithoutModulusFails) { std::string jwt_set = R"( {"keys":[ {"kty":"RSA", "e":"AQAB", "use":"sig", "alg":"RS256", "key_ops":["verify"], "kid":"DfpE4Q" }] })"; EXPECT_THAT(JwkSetToPublicKeysetHandle(jwt_set), Not(IsOk())); } TEST_F(JwkSetToPublicKeysetHandleTest, Rs256WithoutExponentFails) { std::string jwt_set = R"( {"keys":[ {"kty":"RSA", "n":"AQAB", "use":"sig", "alg":"RS256", "key_ops":["verify"], "kid":"DfpE4Q" }] })"; EXPECT_THAT(JwkSetToPublicKeysetHandle(jwt_set), Not(IsOk())); } TEST_F(JwkSetToPublicKeysetHandleTest, Es256WithSmallXFails) { std::string jwt_set = R"({ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8Sk", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES256","key_ops":["verify"]}], "kid":"EhuduQ" })"; // The keys in the keyset are validated when the primitive is generated. // So JwkSetToPublicKeysetHandle succeeds, but GetPrimitive fails. util::StatusOr> public_handle = JwkSetToPublicKeysetHandle(jwt_set); ASSERT_THAT(public_handle, IsOk()); util::StatusOr> verify = (*public_handle) ->GetPrimitive( ConfigGlobalRegistry()); EXPECT_THAT(verify, Not(IsOk())); } TEST_F(JwkSetToPublicKeysetHandleTest, Es256WithSmallYFails) { std::string jwt_set = R"({ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB27", "use":"sig","alg":"ES256","key_ops":["verify"]}], "kid":"EhuduQ" })"; // The keys in the keyset are validated when the primitive is generated. // So JwkSetToPublicKeysetHandle succeeds, but GetPrimitive fails. util::StatusOr> public_handle = JwkSetToPublicKeysetHandle(jwt_set); ASSERT_THAT(public_handle, IsOk()); util::StatusOr> verify = (*public_handle) ->GetPrimitive( ConfigGlobalRegistry()); EXPECT_THAT(verify, Not(IsOk())); } TEST_F(JwkSetToPublicKeysetHandleTest, Es256CorrectlySetsKid) { std::string jwt_set = R"({ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES256","key_ops":["verify"], "kid":"EhuduQ"}] })"; util::StatusOr> public_handle = JwkSetToPublicKeysetHandle(jwt_set); EXPECT_THAT(public_handle, IsOk()); const google::crypto::tink::Keyset &keyset = CleartextKeysetHandle::GetKeyset(**public_handle); ASSERT_THAT(keyset.key_size(), Eq(1)); EXPECT_THAT(keyset.key(0).output_prefix_type(), Eq(google::crypto::tink::OutputPrefixType::RAW)); google::crypto::tink::JwtEcdsaPublicKey key; key.ParseFromString(keyset.key(0).key_data().value()); EXPECT_THAT(key.custom_kid().value(), Eq("EhuduQ")); } TEST_F(JwkSetToPublicKeysetHandleTest, Es256WithoutOptionalFieldsSucceeds) { std::string jwt_set = R"({ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "alg":"ES256"}] })"; util::StatusOr> public_handle = JwkSetToPublicKeysetHandle(jwt_set); EXPECT_THAT(public_handle, IsOk()); } TEST_F(JwkSetToPublicKeysetHandleTest, Es256WithoutKtyFails) { std::string jwt_set = R"({ "keys":[{ "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES256","key_ops":["verify"], "kid":"EhuduQ"}] })"; EXPECT_THAT(JwkSetToPublicKeysetHandle(jwt_set), Not(IsOk())); } TEST_F(JwkSetToPublicKeysetHandleTest, Es256WithoutAlgFails) { std::string jwt_set = R"({ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","key_ops":["verify"], "kid":"EhuduQ"}] })"; EXPECT_THAT(JwkSetToPublicKeysetHandle(jwt_set), Not(IsOk())); } TEST_F(JwkSetToPublicKeysetHandleTest, Es256WithoutCrvFails) { std::string jwt_set = R"({ "keys":[{ "kty":"EC", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES256","key_ops":["verify"], "kid":"EhuduQ"}] })"; EXPECT_THAT(JwkSetToPublicKeysetHandle(jwt_set), Not(IsOk())); } TEST_F(JwkSetToPublicKeysetHandleTest, Es256InvalidKtyFails) { std::string jwt_set = R"({ "keys":[{ "kty":"RSA", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES256","key_ops":["verify"], "kid":"EhuduQ"}] })"; EXPECT_THAT(JwkSetToPublicKeysetHandle(jwt_set), Not(IsOk())); } TEST_F(JwkSetToPublicKeysetHandleTest, Es256InvalidAlgFails) { std::string jwt_set = R"({ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES257","key_ops":["verify"], "kid":"EhuduQ"}] })"; EXPECT_THAT(JwkSetToPublicKeysetHandle(jwt_set), Not(IsOk())); } TEST_F(JwkSetToPublicKeysetHandleTest, Es256InvalidKeyOpsFails) { std::string jwt_set = R"({ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES256","key_ops":["verify "], "kid":"EhuduQ"}] })"; EXPECT_THAT(JwkSetToPublicKeysetHandle(jwt_set), Not(IsOk())); } TEST_F(JwkSetToPublicKeysetHandleTest, Es256InvalidKeyOpsTypeFails) { std::string jwt_set = R"({ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES256","key_ops":"verify", "kid":"EhuduQ"}] })"; EXPECT_THAT(JwkSetToPublicKeysetHandle(jwt_set), Not(IsOk())); } TEST_F(JwkSetToPublicKeysetHandleTest, Es256InvalidUseFails) { std::string jwt_set = R"({ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"zag","alg":"ES256","key_ops":["verify"], "kid":"EhuduQ"}] })"; EXPECT_THAT(JwkSetToPublicKeysetHandle(jwt_set), Not(IsOk())); } TEST_F(JwkSetToPublicKeysetHandleTest, Es256WithoutXFails) { std::string jwt_set = R"({ "keys":[{ "kty":"EC", "crv":"P-256", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES256","key_ops":["verify"], "kid":"EhuduQ"}] })"; EXPECT_THAT(JwkSetToPublicKeysetHandle(jwt_set), Not(IsOk())); } TEST_F(JwkSetToPublicKeysetHandleTest, Es256WithoutYFails) { std::string jwt_set = R"({ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "use":"sig","alg":"ES256","key_ops":["verify"], "kid":"EhuduQ"}] })"; EXPECT_THAT(JwkSetToPublicKeysetHandle(jwt_set), Not(IsOk())); } TEST_F(JwkSetToPublicKeysetHandleTest, Es256PrivateKeyFails) { std::string jwt_set = R"({ "keys":[{ "kty":"EC", "crv":"P-256", "alg":"ES256", "x":"SVqB4JcUD6lsfvqMr-OKUNUphdNn64Eay60978ZlL74", "y":"lf0u0pMj4lGAzZix5u4Cm5CMQIgMNpkwy163wtKYVKI", "d":"0g5vAEKzugrXaRbgKG0Tj2qJ5lMP4Bezds1_sTybkfk" })"; EXPECT_THAT(JwkSetToPublicKeysetHandle(jwt_set), Not(IsOk())); } TEST(JwkSetFromPublicKeysetHandleTest, EcdsaWithTinkOutputPrefixSuccessWithKid) { std::string public_keyset_with_tink_output_prefix = R"({ "primaryKeyId": 303799737, "key": [ { "keyId": 303799737, "status": "ENABLED", "outputPrefixType": "TINK", "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey", "keyMaterialType": "ASYMMETRIC_PUBLIC", "value": "IiDuhGJiGeaQ/qeqt1daC2xZRarm4VEsmSHJUWJY9EHbvxogwO6uIxh8SkKOO8VjZXNRTteRcwCPE4/4JElKyaa0fcQQAQ==" } } ] })"; util::StatusOr> reader = JsonKeysetReader::New(public_keyset_with_tink_output_prefix); ASSERT_THAT(reader, IsOk()); util::StatusOr> keyset_handle = CleartextKeysetHandle::Read(std::move(*reader)); ASSERT_THAT(keyset_handle, IsOk()); util::StatusOr jwk_set = JwkSetFromPublicKeysetHandle(**keyset_handle); ASSERT_THAT(jwk_set, IsOk()); // Check that jwk_set is equalivalent to kEs256JwkPublicKey. util::StatusOr output_struct = jwt_internal::JsonStringToProtoStruct(*jwk_set); ASSERT_THAT(output_struct, IsOk()); util::StatusOr expected_struct = jwt_internal::JsonStringToProtoStruct(kEs256JwkPublicKey); ASSERT_THAT(expected_struct, IsOk()); std::string differences; MessageDifferencer message_differencer; message_differencer.ReportDifferencesToString(&differences); EXPECT_TRUE(message_differencer.Compare(*output_struct, *expected_struct)) << differences; } TEST(JwkSetFromPublicKeysetHandleTest, JwtRsaSsaPkcs1WithTinkOutputPrefixSuccessWithKid) { std::string public_keyset_with_tink_output_prefix = R"({ "primaryKeyId": 1277272603, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PublicKey", "value": "IgMBAAEagAK+ZQ5rrZNivGPs3ytlUDOgR1KeaxFBo1YEwB0Hxp0ZryfjJwaJhaga/S5lZzy8faOfqXc9r/vZtvYgd/f4oPZRpPAuTXHfJKFfJsShLlkX1t6bOufaiE2LEag3s5+PvA9vrVn4XU2/neerfTzP5EjVZ7Igf70eO4hy5TFpZjRV6+xfMJ6Ewk/mDuRXPKXnlthxGLbx2J2RVrOvNWA0bfnI00wQvfahbVV+++nuF9Ae3FLCQU4/MmDMg8dskVvEAsauuBceyirtS0NB1L2++gSnj8nNCEK2cIQpqGCRPA5bJP3o6VEZiI8lIUdZO6PLVCd3o4pzwsYSykBfigPpmX5hEAE=", "keyMaterialType": "ASYMMETRIC_PUBLIC" }, "status": "ENABLED", "keyId": 1277272603, "outputPrefixType": "TINK" } ] })"; util::StatusOr> reader = JsonKeysetReader::New(public_keyset_with_tink_output_prefix); ASSERT_THAT(reader, IsOk()); util::StatusOr> keyset_handle = CleartextKeysetHandle::Read(std::move(*reader)); ASSERT_THAT(keyset_handle, IsOk()); util::StatusOr jwk_set = JwkSetFromPublicKeysetHandle(**keyset_handle); ASSERT_THAT(jwk_set, IsOk()); // Check that jwk_set is equalivalent to kRs256JwkPublicKey. util::StatusOr output_struct = jwt_internal::JsonStringToProtoStruct(*jwk_set); ASSERT_THAT(output_struct, IsOk()); util::StatusOr expected_struct = jwt_internal::JsonStringToProtoStruct(kRs256JwkPublicKey); ASSERT_THAT(expected_struct, IsOk()); std::string differences; MessageDifferencer message_differencer; message_differencer.ReportDifferencesToString(&differences); EXPECT_TRUE(message_differencer.Compare(*output_struct, *expected_struct)) << differences; } TEST(JwkSetFromPublicKeysetHandleTest, WithLegacyOutputPrefixFails) { std::string public_keyset_with_bad_output_prefix = R"({ "primaryKeyId": 303799737, "key": [ { "keyId": 303799737, "status": "ENABLED", "outputPrefixType": "LEGACY", "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey", "keyMaterialType": "ASYMMETRIC_PUBLIC", "value": "IiDuhGJiGeaQ/qeqt1daC2xZRarm4VEsmSHJUWJY9EHbvxogwO6uIxh8SkKOO8VjZXNRTteRcwCPE4/4JElKyaa0fcQQAQ==" } } ] })"; util::StatusOr> reader = JsonKeysetReader::New(public_keyset_with_bad_output_prefix); ASSERT_THAT(reader, IsOk()); util::StatusOr> keyset_handle = CleartextKeysetHandle::Read(std::move(*reader)); ASSERT_THAT(keyset_handle, IsOk()); util::StatusOr jwk_set = JwkSetFromPublicKeysetHandle(**keyset_handle); EXPECT_THAT(jwk_set, Not(IsOk())); } TEST(JwkSetFromPublicKeysetHandleTest, WithInvalidKeyMaterialTypeFails) { std::string public_keyset_with_invalid_key_material_type = R"({ "primaryKeyId": 303799737, "key": [ { "keyId": 303799737, "status": "ENABLED", "outputPrefixType": "TINK", "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey", "keyMaterialType": "ASYMMETRIC_PRIVATE", "value": "IiDuhGJiGeaQ/qeqt1daC2xZRarm4VEsmSHJUWJY9EHbvxogwO6uIxh8SkKOO8VjZXNRTteRcwCPE4/4JElKyaa0fcQQAQ==" } } ] })"; util::StatusOr> reader = JsonKeysetReader::New(public_keyset_with_invalid_key_material_type); ASSERT_THAT(reader, IsOk()); util::StatusOr> keyset_handle = CleartextKeysetHandle::Read(std::move(*reader)); ASSERT_THAT(keyset_handle, IsOk()); util::StatusOr jwk_set = JwkSetFromPublicKeysetHandle(**keyset_handle); EXPECT_THAT(jwk_set, Not(IsOk())); } TEST(JwkSetFromPublicKeysetHandleTest, WithUnknownTypeUrlFails) { std::string public_keyset_with_invalid_key_material_type = R"({ "primaryKeyId": 303799737, "key": [ { "keyId": 303799737, "status": "ENABLED", "outputPrefixType": "TINK", "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.Unknown", "keyMaterialType": "ASYMMETRIC_PUBLIC", "value": "IiDuhGJiGeaQ/qeqt1daC2xZRarm4VEsmSHJUWJY9EHbvxogwO6uIxh8SkKOO8VjZXNRTteRcwCPE4/4JElKyaa0fcQQAQ==" } } ] })"; util::StatusOr> reader = JsonKeysetReader::New(public_keyset_with_invalid_key_material_type); ASSERT_THAT(reader, IsOk()); util::StatusOr> keyset_handle = CleartextKeysetHandle::Read(std::move(*reader)); ASSERT_THAT(keyset_handle, IsOk()); util::StatusOr jwk_set = JwkSetFromPublicKeysetHandle(**keyset_handle); EXPECT_THAT(jwk_set, Not(IsOk())); } TEST(JwkSetFromPublicKeysetHandleTest, EcdsaWithUnknownAlgorithmFails) { std::string public_keyset_with_unknown_algorithm = R"({ "primaryKeyId": 303799737, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey", "value": "IiDuhGJiGeaQ/qeqt1daC2xZRarm4VEsmSHJUWJY9EHbvxogwO6uIxh8SkKOO8VjZXNRTteRcwCPE4/4JElKyaa0fcQ=", "keyMaterialType": "ASYMMETRIC_PUBLIC" }, "status": "ENABLED", "keyId": 303799737, "outputPrefixType": "TINK" } ] })"; util::StatusOr> reader = JsonKeysetReader::New(public_keyset_with_unknown_algorithm); ASSERT_THAT(reader, IsOk()); util::StatusOr> keyset_handle = CleartextKeysetHandle::Read(std::move(*reader)); ASSERT_THAT(keyset_handle, IsOk()); util::StatusOr jwk_set = JwkSetFromPublicKeysetHandle(**keyset_handle); EXPECT_THAT(jwk_set, Not(IsOk())); } struct SmallCordinateTestCase { std::string name; std::string public_keyset; std::string jwk_set; int expected_encoded_size; }; class JwkSetSmallCoordinateConverterTest : public testing::TestWithParam { void SetUp() override { ASSERT_THAT(JwtSignatureRegister(), IsOk()); } }; TEST_P(JwkSetSmallCoordinateConverterTest, convertEcdsaKeysetsEncodesFixedSizedCoordinates) { util::StatusOr> reader = JsonKeysetReader::New(GetParam().public_keyset); ASSERT_THAT(reader, IsOk()); util::StatusOr> keyset_handle = CleartextKeysetHandle::Read(std::move(*reader)); ASSERT_THAT(keyset_handle, IsOk()); const google::crypto::tink::Keyset &public_keyset = CleartextKeysetHandle::GetKeyset(**keyset_handle); google::crypto::tink::EcdsaPublicKey public_key; ASSERT_TRUE( public_key.ParseFromString(public_keyset.key().at(0).key_data().value())); // verify one of the coordinates is different than the field element size. ASSERT_FALSE(public_key.x().size() == GetParam().expected_encoded_size && public_key.y().size() == GetParam().expected_encoded_size); util::StatusOr jwk_set_str = JwkSetFromPublicKeysetHandle(**keyset_handle); ASSERT_THAT(jwk_set_str, IsOk()); util::StatusOr output_struct = jwt_internal::JsonStringToProtoStruct(*jwk_set_str); ASSERT_THAT(output_struct, IsOk()); util::StatusOr expected_struct = jwt_internal::JsonStringToProtoStruct(GetParam().jwk_set); ASSERT_THAT(expected_struct, IsOk()); std::string differences; MessageDifferencer message_differencer; message_differencer.ReportDifferencesToString(&differences); EXPECT_TRUE(message_differencer.Compare(*output_struct, *expected_struct)) << differences; Struct key = (*expected_struct) .fields() .find("keys") ->second.list_value() .values() .Get(0) .struct_value(); std::string x, y; EXPECT_TRUE(absl::WebSafeBase64Unescape( key.fields().find("x")->second.string_value(), &x)); EXPECT_TRUE(absl::WebSafeBase64Unescape( key.fields().find("y")->second.string_value(), &y)); EXPECT_EQ(x.size(), GetParam().expected_encoded_size); EXPECT_EQ(y.size(), GetParam().expected_encoded_size); } INSTANTIATE_TEST_SUITE_P( JwkSetSmallCoordinateConverterTests, JwkSetSmallCoordinateConverterTest, testing::ValuesIn({ {"ES256_smaller", std::string(kEs256WithSmallCoordinates), std::string(kEs256JwkWithEncodedSmallCoordinates), 32}, {"ES256_larger", std::string(kEs256WithBiggerCoordinates), std::string(kEs256JwkWithEncodedBiggerCoordinates), 32}, {"ES384_smaller", std::string(kEs384WithSmallCoordinates), std::string(kEs384JwkWithEncodedSmallCoordinates), 48}, {"ES512_larger", std::string(kEs512WithSmallCoordinates), std::string(kEs512JwkWithEncodedSmallCoordinates), 66}, }), [](const testing::TestParamInfo< JwkSetSmallCoordinateConverterTest::ParamType> &info) { return info.param.name; }); TEST(JwkSetFromPublicKeysetHandleTest, JwtRsaSsaPkcs1WithUnknownAlgorithmFails) { std::string public_keyset_with_unknown_algorithm = R"({ "primaryKeyId": 1277272603, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PublicKey", "value": "IgMBAAEagAK+ZQ5rrZNivGPs3ytlUDOgR1KeaxFBo1YEwB0Hxp0ZryfjJwaJhaga/S5lZzy8faOfqXc9r/vZtvYgd/f4oPZRpPAuTXHfJKFfJsShLlkX1t6bOufaiE2LEag3s5+PvA9vrVn4XU2/neerfTzP5EjVZ7Igf70eO4hy5TFpZjRV6+xfMJ6Ewk/mDuRXPKXnlthxGLbx2J2RVrOvNWA0bfnI00wQvfahbVV+++nuF9Ae3FLCQU4/MmDMg8dskVvEAsauuBceyirtS0NB1L2++gSnj8nNCEK2cIQpqGCRPA5bJP3o6VEZiI8lIUdZO6PLVCd3o4pzwsYSykBfigPpmX5h", "keyMaterialType": "ASYMMETRIC_PUBLIC" }, "status": "ENABLED", "keyId": 1277272603, "outputPrefixType": "TINK" } ] })"; util::StatusOr> reader = JsonKeysetReader::New(public_keyset_with_unknown_algorithm); ASSERT_THAT(reader, IsOk()); util::StatusOr> keyset_handle = CleartextKeysetHandle::Read(std::move(*reader)); ASSERT_THAT(keyset_handle, IsOk()); util::StatusOr jwk_set = JwkSetFromPublicKeysetHandle(**keyset_handle); EXPECT_THAT(jwk_set, Not(IsOk())); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/jwt_hmac_key.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/jwt_hmac_key.h" #include #include "absl/base/internal/endian.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/jwt/jwt_hmac_parameters.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { JwtHmacKey::Builder& JwtHmacKey::Builder::SetParameters( const JwtHmacParameters& parameters) { parameters_ = parameters; return *this; } JwtHmacKey::Builder& JwtHmacKey::Builder::SetKeyBytes( const RestrictedData& key_bytes) { key_bytes_ = key_bytes; return *this; } JwtHmacKey::Builder& JwtHmacKey::Builder::SetIdRequirement(int id_requirement) { id_requirement_ = id_requirement; return *this; } JwtHmacKey::Builder& JwtHmacKey::Builder::SetCustomKid( absl::string_view custom_kid) { custom_kid_ = custom_kid.data(); return *this; } util::StatusOr> JwtHmacKey::Builder::ComputeKid() { switch (parameters_->GetKidStrategy()) { case JwtHmacParameters::KidStrategy::kBase64EncodedKeyId: { if (custom_kid_.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Custom kid must not be set for KidStrategy::kBase64EncodedKeyId."); } std::string base64_kid; char buffer[4]; absl::big_endian::Store32(buffer, *id_requirement_); absl::WebSafeBase64Escape(absl::string_view(buffer, 4), &base64_kid); return base64_kid; } case JwtHmacParameters::KidStrategy::kCustom: { if (!custom_kid_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Custom kid must be set for KidStrategy::kCustom."); } return custom_kid_; } case JwtHmacParameters::KidStrategy::kIgnored: { if (custom_kid_.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Custom kid must not be set for KidStrategy::kIgnored."); } return absl::nullopt; } default: // Should be unreachable if all valid kid strategies have been handled. return util::Status(absl::StatusCode::kFailedPrecondition, "Unknown kid strategy."); } } util::StatusOr JwtHmacKey::Builder::Build( PartialKeyAccessToken token) { if (!parameters_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "JWT HMAC parameters must be specified."); } if (!key_bytes_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "JWT HMAC key bytes must be specified."); } if (parameters_->KeySizeInBytes() != key_bytes_->size()) { return util::Status( absl::StatusCode::kInvalidArgument, "Actual JWT HMAC key size does not match size specified in " "the parameters."); } if (parameters_->HasIdRequirement() && !id_requirement_.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key without ID requirement with parameters with ID " "requirement"); } if (!parameters_->HasIdRequirement() && id_requirement_.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key with ID requirement with parameters without ID " "requirement"); } util::StatusOr> kid = ComputeKid(); if (!kid.ok()) { return kid.status(); } return JwtHmacKey(*parameters_, *key_bytes_, id_requirement_, *kid); } bool JwtHmacKey::operator==(const Key& other) const { const JwtHmacKey* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (parameters_ != that->parameters_) { return false; } if (key_bytes_ != that->key_bytes_) { return false; } if (id_requirement_ != that->id_requirement_) { return false; } if (kid_ != that->kid_) { return false; } return true; } } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/jwt_hmac_key.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_JWT_HMAC_KEY_H_ #define TINK_JWT_JWT_HMAC_KEY_H_ #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/jwt/jwt_hmac_parameters.h" #include "tink/jwt/jwt_mac_key.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Represents functions to authenticate and verify JWTs using HMAC. class JwtHmacKey : public JwtMacKey { public: // Creates JWT HMAC key instances. class Builder { public: // Copyable and movable. Builder(const Builder& other) = default; Builder& operator=(const Builder& other) = default; Builder(Builder&& other) = default; Builder& operator=(Builder&& other) = default; // Creates initially empty parameters builder. Builder() = default; Builder& SetParameters(const JwtHmacParameters& parameters); Builder& SetKeyBytes(const RestrictedData& key_bytes); Builder& SetIdRequirement(int id_requirement); Builder& SetCustomKid(absl::string_view custom_kid); // Creates JWT HMAC key object from this builder. util::StatusOr Build(PartialKeyAccessToken token); private: util::StatusOr> ComputeKid(); absl::optional parameters_; absl::optional key_bytes_; absl::optional id_requirement_; absl::optional custom_kid_; }; // Copyable and movable. JwtHmacKey(const JwtHmacKey& other) = default; JwtHmacKey& operator=(const JwtHmacKey& other) = default; JwtHmacKey(JwtHmacKey&& other) = default; JwtHmacKey& operator=(JwtHmacKey&& other) = default; const RestrictedData& GetKeyBytes(PartialKeyAccessToken token) const { return key_bytes_; } const JwtHmacParameters& GetParameters() const override { return parameters_; } absl::optional GetIdRequirement() const override { return id_requirement_; } absl::optional GetKid() const override { return kid_; } bool operator==(const Key& other) const override; private: JwtHmacKey(const JwtHmacParameters& parameters, const RestrictedData& key_bytes, absl::optional id_requirement, absl::optional kid) : parameters_(parameters), key_bytes_(key_bytes), id_requirement_(id_requirement), kid_(kid) {} JwtHmacParameters parameters_; RestrictedData key_bytes_; absl::optional id_requirement_; absl::optional kid_; }; } // namespace tink } // namespace crypto #endif // TINK_JWT_JWT_HMAC_KEY_H_ ================================================ FILE: cc/jwt/jwt_hmac_key_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/jwt_hmac_key.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/jwt/jwt_hmac_parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { int key_size_in_bytes; JwtHmacParameters::KidStrategy kid_strategy; JwtHmacParameters::Algorithm algorithm; absl::optional custom_kid; absl::optional id_requirement; absl::optional expected_kid; }; using JwtHmacKeyTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( JwtHmacKeyTestSuite, JwtHmacKeyTest, Values(TestCase{/*key_size_in_bytes=*/16, JwtHmacParameters::KidStrategy::kBase64EncodedKeyId, JwtHmacParameters::Algorithm::kHs256, /*custom_kid=*/absl::nullopt, /*id_requirement=*/123, /*expected_kid=*/"AAAAew"}, TestCase{/*key_size_in_bytes=*/32, JwtHmacParameters::KidStrategy::kCustom, JwtHmacParameters::Algorithm::kHs384, /*custom_kid=*/"custom_kid", /*id_requirement=*/absl::nullopt, /*expected_kid=*/"custom_kid"}, TestCase{/*key_size_in_bytes=*/32, JwtHmacParameters::KidStrategy::kIgnored, JwtHmacParameters::Algorithm::kHs512, /*custom_kid=*/absl::nullopt, /*id_requirement=*/absl::nullopt, /*expected_kid=*/absl::nullopt})); TEST_P(JwtHmacKeyTest, CreateSucceeds) { TestCase test_case = GetParam(); util::StatusOr params = JwtHmacParameters::Create( test_case.key_size_in_bytes, test_case.kid_strategy, test_case.algorithm); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(test_case.key_size_in_bytes); JwtHmacKey::Builder builder = JwtHmacKey::Builder().SetParameters(*params).SetKeyBytes(secret); if (test_case.id_requirement.has_value()) { builder.SetIdRequirement(*test_case.id_requirement); } if (test_case.custom_kid.has_value()) { builder.SetCustomKid(*test_case.custom_kid); } util::StatusOr key = builder.Build(GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); EXPECT_THAT(key->GetParameters(), Eq(*params)); EXPECT_THAT(key->GetKeyBytes(GetPartialKeyAccess()), Eq(secret)); EXPECT_THAT(key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(key->GetKid(), Eq(test_case.expected_kid)); } TEST(JwtHmacKeyTest, CreateKeyWithMismatchedKeySizeFails) { // Key size parameter is 32 bytes. util::StatusOr params = JwtHmacParameters::Create( /*key_size_in_bytes=*/32, JwtHmacParameters::KidStrategy::kBase64EncodedKeyId, JwtHmacParameters::Algorithm::kHs256); ASSERT_THAT(params, IsOk()); // Key material is 16 bytes (another valid key length). RestrictedData mismatched_secret = RestrictedData(/*num_random_bytes=*/16); JwtHmacKey::Builder builder = JwtHmacKey::Builder() .SetParameters(*params) .SetKeyBytes(mismatched_secret) .SetIdRequirement(123); EXPECT_THAT(builder.Build(GetPartialKeyAccess()).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Actual JWT HMAC key size does not match"))); } TEST(JwtHmacKeyTest, CreateKeyWithoutKeyBytesFails) { util::StatusOr params = JwtHmacParameters::Create( /*key_size_in_bytes=*/32, JwtHmacParameters::KidStrategy::kBase64EncodedKeyId, JwtHmacParameters::Algorithm::kHs256); ASSERT_THAT(params, IsOk()); JwtHmacKey::Builder builder = JwtHmacKey::Builder().SetParameters(*params).SetIdRequirement(123); EXPECT_THAT(builder.Build(GetPartialKeyAccess()).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("JWT HMAC key bytes must be specified"))); } TEST(JwtHmacKeyTest, CreateKeyWithoutParametersFails) { util::StatusOr params = JwtHmacParameters::Create( /*key_size_in_bytes=*/32, JwtHmacParameters::KidStrategy::kBase64EncodedKeyId, JwtHmacParameters::Algorithm::kHs256); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); JwtHmacKey::Builder builder = JwtHmacKey::Builder().SetKeyBytes(secret).SetIdRequirement(123); EXPECT_THAT(builder.Build(GetPartialKeyAccess()).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("JWT HMAC parameters must be specified"))); } TEST(JwtHmacKeyTest, CreateBase64EncodedKidWithoutIdRequirementFails) { util::StatusOr params = JwtHmacParameters::Create( /*key_size_in_bytes=*/32, JwtHmacParameters::KidStrategy::kBase64EncodedKeyId, JwtHmacParameters::Algorithm::kHs256); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); JwtHmacKey::Builder builder = JwtHmacKey::Builder().SetParameters(*params).SetKeyBytes(secret); EXPECT_THAT(builder.Build(GetPartialKeyAccess()).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Cannot create key without ID requirement " "with parameters with ID requirement"))); } TEST(JwtHmacKeyTest, CreateBase64EncodedKidWithCustomKidFails) { util::StatusOr params = JwtHmacParameters::Create( /*key_size_in_bytes=*/32, JwtHmacParameters::KidStrategy::kBase64EncodedKeyId, JwtHmacParameters::Algorithm::kHs256); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); JwtHmacKey::Builder builder = JwtHmacKey::Builder() .SetParameters(*params) .SetKeyBytes(secret) .SetIdRequirement(123) .SetCustomKid("custom_kid"); EXPECT_THAT(builder.Build(GetPartialKeyAccess()).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Custom kid must not be set for " "KidStrategy::kBase64EncodedKeyId"))); } TEST(JwtHmacKeyTest, CreateCustomKidWithIdRequirementFails) { util::StatusOr params = JwtHmacParameters::Create( /*key_size_in_bytes=*/32, JwtHmacParameters::KidStrategy::kCustom, JwtHmacParameters::Algorithm::kHs256); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); JwtHmacKey::Builder builder = JwtHmacKey::Builder() .SetParameters(*params) .SetKeyBytes(secret) .SetCustomKid("custom_kid") .SetIdRequirement(123); EXPECT_THAT(builder.Build(GetPartialKeyAccess()).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Cannot create key with ID requirement with " "parameters without ID requirement"))); } TEST(JwtHmacKeyTest, CreateCustomKidWithoutCustomKidFails) { util::StatusOr params = JwtHmacParameters::Create( /*key_size_in_bytes=*/32, JwtHmacParameters::KidStrategy::kCustom, JwtHmacParameters::Algorithm::kHs256); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); JwtHmacKey::Builder builder = JwtHmacKey::Builder().SetParameters(*params).SetKeyBytes(secret); EXPECT_THAT(builder.Build(GetPartialKeyAccess()).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Custom kid must be set"))); } TEST(JwtHmacKeyTest, CreateIgnoredKidWithIdRequirementFails) { util::StatusOr params = JwtHmacParameters::Create( /*key_size_in_bytes=*/32, JwtHmacParameters::KidStrategy::kIgnored, JwtHmacParameters::Algorithm::kHs256); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); JwtHmacKey::Builder builder = JwtHmacKey::Builder() .SetParameters(*params) .SetKeyBytes(secret) .SetIdRequirement(123); EXPECT_THAT(builder.Build(GetPartialKeyAccess()).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Cannot create key with ID requirement with " "parameters without ID requirement"))); } TEST(JwtHmacKeyTest, CreateIgnoredKidWithCustomKidFails) { util::StatusOr params = JwtHmacParameters::Create( /*key_size_in_bytes=*/32, JwtHmacParameters::KidStrategy::kIgnored, JwtHmacParameters::Algorithm::kHs256); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); JwtHmacKey::Builder builder = JwtHmacKey::Builder() .SetParameters(*params) .SetKeyBytes(secret) .SetCustomKid("custom_kid"); EXPECT_THAT( builder.Build(GetPartialKeyAccess()).status(), StatusIs( absl::StatusCode::kInvalidArgument, HasSubstr("Custom kid must not be set for KidStrategy::kIgnored"))); } TEST_P(JwtHmacKeyTest, KeyEquals) { TestCase test_case = GetParam(); util::StatusOr params = JwtHmacParameters::Create( test_case.key_size_in_bytes, test_case.kid_strategy, test_case.algorithm); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(test_case.key_size_in_bytes); JwtHmacKey::Builder builder = JwtHmacKey::Builder().SetParameters(*params).SetKeyBytes(secret); if (test_case.id_requirement.has_value()) { builder.SetIdRequirement(*test_case.id_requirement); } if (test_case.custom_kid.has_value()) { builder.SetCustomKid(*test_case.custom_kid); } util::StatusOr key = builder.Build(GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); JwtHmacKey::Builder other_builder = JwtHmacKey::Builder().SetParameters(*params).SetKeyBytes(secret); if (test_case.id_requirement.has_value()) { other_builder.SetIdRequirement(*test_case.id_requirement); } if (test_case.custom_kid.has_value()) { other_builder.SetCustomKid(*test_case.custom_kid); } util::StatusOr other_key = other_builder.Build(GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key == *other_key); EXPECT_TRUE(*other_key == *key); EXPECT_FALSE(*key != *other_key); EXPECT_FALSE(*other_key != *key); } TEST(JwtHmacKeyTest, DifferentParametersNotEqual) { util::StatusOr params = JwtHmacParameters::Create( /*key_size_in_bytes=*/32, JwtHmacParameters::KidStrategy::kBase64EncodedKeyId, JwtHmacParameters::Algorithm::kHs256); ASSERT_THAT(params, IsOk()); util::StatusOr other_params = JwtHmacParameters::Create( /*key_size_in_bytes=*/32, JwtHmacParameters::KidStrategy::kBase64EncodedKeyId, JwtHmacParameters::Algorithm::kHs384); ASSERT_THAT(other_params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = JwtHmacKey::Builder() .SetParameters(*params) .SetKeyBytes(secret) .SetIdRequirement(123) .Build(GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = JwtHmacKey::Builder() .SetParameters(*other_params) .SetKeyBytes(secret) .SetIdRequirement(123) .Build(GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST(JwtHmacKeyTest, DifferentSecretDataNotEqual) { util::StatusOr params = JwtHmacParameters::Create( /*key_size_in_bytes=*/32, JwtHmacParameters::KidStrategy::kBase64EncodedKeyId, JwtHmacParameters::Algorithm::kHs256); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); RestrictedData other_secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = JwtHmacKey::Builder() .SetParameters(*params) .SetKeyBytes(secret) .SetIdRequirement(123) .Build(GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = JwtHmacKey::Builder() .SetParameters(*params) .SetKeyBytes(other_secret) .SetIdRequirement(123) .Build(GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST(JwtHmacKeyTest, DifferentIdRequirementNotEqual) { util::StatusOr params = JwtHmacParameters::Create( /*key_size_in_bytes=*/32, JwtHmacParameters::KidStrategy::kBase64EncodedKeyId, JwtHmacParameters::Algorithm::kHs256); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = JwtHmacKey::Builder() .SetParameters(*params) .SetKeyBytes(secret) .SetIdRequirement(123) .Build(GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = JwtHmacKey::Builder() .SetParameters(*params) .SetKeyBytes(secret) .SetIdRequirement(456) .Build(GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST(JwtHmacKeyTest, DifferentCustomKidNotEqual) { util::StatusOr params = JwtHmacParameters::Create( /*key_size_in_bytes=*/32, JwtHmacParameters::KidStrategy::kCustom, JwtHmacParameters::Algorithm::kHs256); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = JwtHmacKey::Builder() .SetParameters(*params) .SetKeyBytes(secret) .SetCustomKid("custom_kid") .Build(GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = JwtHmacKey::Builder() .SetParameters(*params) .SetKeyBytes(secret) .SetCustomKid("other_custom_kid") .Build(GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/jwt_hmac_parameters.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/jwt_hmac_parameters.h" #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/parameters.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { util::StatusOr JwtHmacParameters::Create( int key_size_in_bytes, KidStrategy kid_strategy, Algorithm algorithm) { if (key_size_in_bytes < 16) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Key size should be at least 16 bytes, got ", key_size_in_bytes, " bytes.")); } static const std::set* kSupportedKidStrategies = new std::set({KidStrategy::kBase64EncodedKeyId, KidStrategy::kIgnored, KidStrategy::kCustom}); if (kSupportedKidStrategies->find(kid_strategy) == kSupportedKidStrategies->end()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create JWT HMAC parameters with unknown kid strategy."); } static const std::set* kSupportedAlgorithms = new std::set( {Algorithm::kHs256, Algorithm::kHs384, Algorithm::kHs512}); if (kSupportedAlgorithms->find(algorithm) == kSupportedAlgorithms->end()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create JWT HMAC parameters with unknown algorithm."); } return JwtHmacParameters(key_size_in_bytes, kid_strategy, algorithm); } bool JwtHmacParameters::operator==(const Parameters& other) const { const JwtHmacParameters* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (key_size_in_bytes_ != that->key_size_in_bytes_) { return false; } if (kid_strategy_ != that->kid_strategy_) { return false; } if (algorithm_ != that->algorithm_) { return false; } return true; } } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/jwt_hmac_parameters.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_JWT_HMAC_PARAMETERS_H_ #define TINK_JWT_JWT_HMAC_PARAMETERS_H_ #include "tink/jwt/jwt_mac_parameters.h" #include "tink/parameters.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Describes the parameters of an `JwtHmacKey`. class JwtHmacParameters : public JwtMacParameters { public: // Strategy for handling the "kid" header. enum class KidStrategy : int { // The `kid` is the URL safe (RFC 4648 Section 5) base64-encoded big-endian // `key_id` in the keyset. // // In `ComputeMacAndEncode()`, Tink always adds the `kid`. // // In `VerifyMacAndDecode()`, Tink checks that the `kid` is present and // equal to this value. // // NOTE: This strategy is recommended by Tink. kBase64EncodedKeyId = 1, // The `kid` header is ignored. // // In `ComputeMacAndEncode()`, Tink does not write a `kid` header. // // In `VerifyMacAndDecode()`, Tink ignores the `kid` header. kIgnored = 2, // The `kid` is fixed. It can be obtained by calling `key.GetKid()`. // // In `ComputeMacAndEncode()`, Tink writes the `kid` header to the // value given by `key.getCustomKid()`. // // In `VerifyMacAndDecode()`, if the `kid` is present, it must match // `key.GetKid()`. If the `kid` is absent, it will be accepted. // // NOTE: Tink does not allow random generation of `JwtHmacKey` objects from // parameters objects with `KidStrategy::kCustom`. kCustom = 3, kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // MAC computation algorithm. enum class Algorithm : int { kHs256 = 1, kHs384 = 2, kHs512 = 3, kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Copyable and movable. JwtHmacParameters(const JwtHmacParameters& other) = default; JwtHmacParameters& operator=(const JwtHmacParameters& other) = default; JwtHmacParameters(JwtHmacParameters&& other) = default; JwtHmacParameters& operator=(JwtHmacParameters&& other) = default; // Creates JWT HMAC parameters object. Returns an error status if // `key_size_in_bytes` is less than 16 bytes, if `kid_strategy` is invalid, or // if `algorithm` is invalid. static util::StatusOr Create(int key_size_in_bytes, KidStrategy kid_strategy, Algorithm algorithm); int KeySizeInBytes() const { return key_size_in_bytes_; } KidStrategy GetKidStrategy() const { return kid_strategy_; } Algorithm GetAlgorithm() const { return algorithm_; } bool AllowKidAbsent() const override { return kid_strategy_ == KidStrategy::kCustom || kid_strategy_ == KidStrategy::kIgnored; } bool HasIdRequirement() const override { return kid_strategy_ == KidStrategy::kBase64EncodedKeyId; } bool operator==(const Parameters& other) const override; private: JwtHmacParameters(int key_size_in_bytes, KidStrategy kid_strategy, Algorithm algorithm) : key_size_in_bytes_(key_size_in_bytes), kid_strategy_(kid_strategy), algorithm_(algorithm) {} int key_size_in_bytes_; KidStrategy kid_strategy_; Algorithm algorithm_; }; } // namespace tink } // namespace crypto #endif // TINK_JWT_JWT_HMAC_PARAMETERS_H_ ================================================ FILE: cc/jwt/jwt_hmac_parameters_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/jwt_hmac_parameters.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Combine; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::TestWithParam; using ::testing::Values; struct KidStrategyTuple { JwtHmacParameters::KidStrategy kid_strategy; bool allowed_kid_absent; bool has_id_requirement; }; using JwtHmacParametersTest = TestWithParam< std::tuple>; INSTANTIATE_TEST_SUITE_P( JwtHmacParametersTestSuite, JwtHmacParametersTest, Combine(Values(16, 32), Values( KidStrategyTuple{ JwtHmacParameters::KidStrategy::kBase64EncodedKeyId, /*allowed_kid_absent=*/false, /*has_id_requirement=*/true}, KidStrategyTuple{JwtHmacParameters::KidStrategy::kCustom, /*allowed_kid_absent=*/true, /*has_id_requirement=*/false}, KidStrategyTuple{JwtHmacParameters::KidStrategy::kIgnored, /*allowed_kid_absent=*/true, /*has_id_requirement=*/false}), Values(JwtHmacParameters::Algorithm::kHs256, JwtHmacParameters::Algorithm::kHs384, JwtHmacParameters::Algorithm::kHs512))); TEST_P(JwtHmacParametersTest, Create) { int key_size_in_bytes; KidStrategyTuple tuple; JwtHmacParameters::Algorithm algorithm; std::tie(key_size_in_bytes, tuple, algorithm) = GetParam(); util::StatusOr parameters = JwtHmacParameters::Create( key_size_in_bytes, tuple.kid_strategy, algorithm); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->KeySizeInBytes(), Eq(key_size_in_bytes)); EXPECT_THAT(parameters->GetKidStrategy(), Eq(tuple.kid_strategy)); EXPECT_THAT(parameters->AllowKidAbsent(), Eq(tuple.allowed_kid_absent)); EXPECT_THAT(parameters->HasIdRequirement(), Eq(tuple.has_id_requirement)); EXPECT_THAT(parameters->GetAlgorithm(), Eq(algorithm)); } TEST(JwtHmacParametersTest, CreateWithInvalidKidStrategyFails) { EXPECT_THAT(JwtHmacParameters::Create( /*key_size_in_bytes=*/16, JwtHmacParameters::KidStrategy:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements, JwtHmacParameters::Algorithm::kHs512) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("unknown kid strategy"))); } TEST(JwtHmacParametersTest, CreateWithInvalidAlgorithmFails) { EXPECT_THAT(JwtHmacParameters::Create( /*key_size_in_bytes=*/16, JwtHmacParameters::KidStrategy::kBase64EncodedKeyId, JwtHmacParameters::Algorithm:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("unknown algorithm"))); } TEST(JwtHmacParametersTest, CreateWithInvalidKeySizeFails) { EXPECT_THAT(JwtHmacParameters::Create( /*key_size_in_bytes=*/15, JwtHmacParameters::KidStrategy::kBase64EncodedKeyId, JwtHmacParameters::Algorithm::kHs512) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Key size should be at least 16 bytes"))); } TEST(JwtHmacParametersTest, CopyConstructor) { util::StatusOr parameters = JwtHmacParameters::Create( /*key_size_in_bytes=*/16, JwtHmacParameters::KidStrategy::kBase64EncodedKeyId, JwtHmacParameters::Algorithm::kHs512); ASSERT_THAT(parameters, IsOk()); JwtHmacParameters copy(*parameters); EXPECT_THAT(copy.KeySizeInBytes(), Eq(parameters->KeySizeInBytes())); EXPECT_THAT(copy.GetKidStrategy(), Eq(parameters->GetKidStrategy())); EXPECT_THAT(copy.GetAlgorithm(), Eq(parameters->GetAlgorithm())); EXPECT_THAT(copy.AllowKidAbsent(), Eq(parameters->AllowKidAbsent())); EXPECT_THAT(copy.HasIdRequirement(), Eq(parameters->HasIdRequirement())); } TEST(JwtHmacParametersTest, CopyAssignment) { util::StatusOr parameters = JwtHmacParameters::Create( /*key_size_in_bytes=*/16, JwtHmacParameters::KidStrategy::kBase64EncodedKeyId, JwtHmacParameters::Algorithm::kHs512); ASSERT_THAT(parameters, IsOk()); JwtHmacParameters copy = *parameters; EXPECT_THAT(copy.KeySizeInBytes(), Eq(parameters->KeySizeInBytes())); EXPECT_THAT(copy.GetKidStrategy(), Eq(parameters->GetKidStrategy())); EXPECT_THAT(copy.GetAlgorithm(), Eq(parameters->GetAlgorithm())); EXPECT_THAT(copy.AllowKidAbsent(), Eq(parameters->AllowKidAbsent())); EXPECT_THAT(copy.HasIdRequirement(), Eq(parameters->HasIdRequirement())); } TEST_P(JwtHmacParametersTest, ParametersEquals) { int key_size_in_bytes; KidStrategyTuple tuple; JwtHmacParameters::Algorithm algorithm; std::tie(key_size_in_bytes, tuple, algorithm) = GetParam(); util::StatusOr parameters = JwtHmacParameters::Create( key_size_in_bytes, tuple.kid_strategy, algorithm); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = JwtHmacParameters::Create(key_size_in_bytes, tuple.kid_strategy, algorithm); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters == *other_parameters); EXPECT_TRUE(*other_parameters == *parameters); EXPECT_FALSE(*parameters != *other_parameters); EXPECT_FALSE(*other_parameters != *parameters); } TEST(JwtHmacParametersTest, KeySizeNotEqual) { util::StatusOr parameters = JwtHmacParameters::Create( /*key_size_in_bytes=*/16, JwtHmacParameters::KidStrategy::kBase64EncodedKeyId, JwtHmacParameters::Algorithm::kHs256); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = JwtHmacParameters::Create( /*key_size_in_bytes=*/32, JwtHmacParameters::KidStrategy::kBase64EncodedKeyId, JwtHmacParameters::Algorithm::kHs256); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(JwtHmacParametersTest, KidStrategyNotEqual) { util::StatusOr parameters = JwtHmacParameters::Create( /*key_size_in_bytes=*/16, JwtHmacParameters::KidStrategy::kBase64EncodedKeyId, JwtHmacParameters::Algorithm::kHs256); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = JwtHmacParameters::Create( /*key_size_in_bytes=*/16, JwtHmacParameters::KidStrategy::kCustom, JwtHmacParameters::Algorithm::kHs256); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(JwtHmacParametersTest, AlgorithmNotEqual) { util::StatusOr parameters = JwtHmacParameters::Create( /*key_size_in_bytes=*/16, JwtHmacParameters::KidStrategy::kBase64EncodedKeyId, JwtHmacParameters::Algorithm::kHs256); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = JwtHmacParameters::Create( /*key_size_in_bytes=*/16, JwtHmacParameters::KidStrategy::kBase64EncodedKeyId, JwtHmacParameters::Algorithm::kHs384); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/jwt_hmac_proto_serialization.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/jwt_hmac_proto_serialization.h" #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/internal/key_parser.h" #include "tink/internal/key_serializer.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/parameters_parser.h" #include "tink/internal/parameters_serializer.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/jwt/jwt_hmac_key.h" #include "tink/jwt/jwt_hmac_parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/secret_key_access_token.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/common.pb.h" #include "proto/jwt_hmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::google::crypto::tink::JwtHmacAlgorithm; using ::google::crypto::tink::JwtHmacKeyFormat; using ::google::crypto::tink::OutputPrefixType; using JwtHmacProtoParametersParserImpl = internal::ParametersParserImpl; using JwtHmacProtoParametersSerializerImpl = internal::ParametersSerializerImpl; using JwtHmacProtoKeyParserImpl = internal::KeyParserImpl; using JwtHmacProtoKeySerializerImpl = internal::KeySerializerImpl; const absl::string_view kTypeUrl = "type.googleapis.com/google.crypto.tink.JwtHmacKey"; util::StatusOr ToKidStrategy( OutputPrefixType output_prefix_type, bool has_custom_kid) { switch (output_prefix_type) { case OutputPrefixType::RAW: if (has_custom_kid) { return JwtHmacParameters::KidStrategy::kCustom; } return JwtHmacParameters::KidStrategy::kIgnored; case OutputPrefixType::TINK: return JwtHmacParameters::KidStrategy::kBase64EncodedKeyId; default: return util::Status(absl::StatusCode::kInvalidArgument, "Invalid OutputPrefixType for JwtHmacKeyFormat."); } } util::StatusOr ToOutputPrefixType( JwtHmacParameters::KidStrategy kid_strategy) { switch (kid_strategy) { case JwtHmacParameters::KidStrategy::kCustom: return OutputPrefixType::RAW; case JwtHmacParameters::KidStrategy::kIgnored: return OutputPrefixType::RAW; case JwtHmacParameters::KidStrategy::kBase64EncodedKeyId: return OutputPrefixType::TINK; default: return util::Status( absl::StatusCode::kInvalidArgument, "Could not determine JwtHmacParameters::KidStrategy."); } } util::StatusOr FromProtoAlgorithm( JwtHmacAlgorithm algorithm) { switch (algorithm) { case JwtHmacAlgorithm::HS256: return JwtHmacParameters::Algorithm::kHs256; case JwtHmacAlgorithm::HS384: return JwtHmacParameters::Algorithm::kHs384; case JwtHmacAlgorithm::HS512: return JwtHmacParameters::Algorithm::kHs512; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine JwtHmacAlgorithm."); } } util::StatusOr ToProtoAlgorithm( JwtHmacParameters::Algorithm algorithm) { switch (algorithm) { case JwtHmacParameters::Algorithm::kHs256: return JwtHmacAlgorithm::HS256; case JwtHmacParameters::Algorithm::kHs384: return JwtHmacAlgorithm::HS384; case JwtHmacParameters::Algorithm::kHs512: return JwtHmacAlgorithm::HS512; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine JwtHmacParameters::Algorithm"); } } util::StatusOr ToParameters( int key_size_in_bytes, OutputPrefixType output_prefix_type, JwtHmacAlgorithm proto_algorithm, bool has_custom_kid) { util::StatusOr kid_strategy = ToKidStrategy(output_prefix_type, has_custom_kid); if (!kid_strategy.ok()) { return kid_strategy.status(); } util::StatusOr algorithm = FromProtoAlgorithm(proto_algorithm); if (!algorithm.ok()) { return algorithm.status(); } return JwtHmacParameters::Create(key_size_in_bytes, *kid_strategy, *algorithm); } util::StatusOr ParseParameters( const internal::ProtoParametersSerialization& serialization) { if (serialization.GetKeyTemplate().type_url() != kTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing JwtHmacParameters."); } JwtHmacKeyFormat proto_key_format; if (!proto_key_format.ParseFromString( serialization.GetKeyTemplate().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse JwtHmacKeyFormat proto."); } if (proto_key_format.version() != 0) { return util::Status( absl::StatusCode::kInvalidArgument, "Parsing JwtHmacParameters failed: only version 0 is accepted."); } return ToParameters(proto_key_format.key_size(), serialization.GetKeyTemplate().output_prefix_type(), proto_key_format.algorithm(), /*has_custom_kid=*/false); } util::StatusOr SerializeParameters( const JwtHmacParameters& parameters) { if (parameters.GetKidStrategy() == JwtHmacParameters::KidStrategy::kCustom) { return util::Status( absl::StatusCode::kInvalidArgument, "Unable to serialize JwtHmacParameters::KidStrategy::kCustom."); } util::StatusOr output_prefix_type = ToOutputPrefixType(parameters.GetKidStrategy()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } util::StatusOr proto_algorithm = ToProtoAlgorithm(parameters.GetAlgorithm()); if (!proto_algorithm.ok()) { return proto_algorithm.status(); } JwtHmacKeyFormat format; format.set_version(0); format.set_key_size(parameters.KeySizeInBytes()); format.set_algorithm(*proto_algorithm); return internal::ProtoParametersSerialization::Create( kTypeUrl, *output_prefix_type, format.SerializeAsString()); } util::StatusOr ParseKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (!token.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "SecretKeyAccess is required."); } if (serialization.TypeUrl() != kTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing JwtHmacKey."); } google::crypto::tink::JwtHmacKey proto_key; const RestrictedData& restricted_data = serialization.SerializedKeyProto(); if (!proto_key.ParseFromString(restricted_data.GetSecret(*token))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse JwtHmacKey proto."); } if (proto_key.version() != 0) { return util::Status( absl::StatusCode::kInvalidArgument, "Parsing JwtHmacKey failed: only version 0 is accepted."); } util::StatusOr parameters = ToParameters( proto_key.key_value().length(), serialization.GetOutputPrefixType(), proto_key.algorithm(), proto_key.has_custom_kid()); if (!parameters.ok()) { return parameters.status(); } JwtHmacKey::Builder builder = JwtHmacKey::Builder() .SetParameters(*parameters) .SetKeyBytes(RestrictedData(proto_key.key_value(), *token)); if (serialization.IdRequirement().has_value()) { builder.SetIdRequirement(*serialization.IdRequirement()); } if (proto_key.has_custom_kid()) { builder.SetCustomKid(proto_key.custom_kid().value()); } return builder.Build(GetPartialKeyAccess()); } util::StatusOr SerializeKey( const JwtHmacKey& key, absl::optional token) { if (!token.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "SecretKeyAccess is required."); } util::StatusOr restricted_input = key.GetKeyBytes(GetPartialKeyAccess()); if (!restricted_input.ok()) { return restricted_input.status(); } util::StatusOr proto_algorithm = ToProtoAlgorithm(key.GetParameters().GetAlgorithm()); if (!proto_algorithm.ok()) { return proto_algorithm.status(); } google::crypto::tink::JwtHmacKey proto_key; proto_key.set_version(0); proto_key.set_key_value(restricted_input->GetSecret(*token)); proto_key.set_algorithm(*proto_algorithm); if (key.GetParameters().GetKidStrategy() == JwtHmacParameters::KidStrategy::kCustom) { proto_key.mutable_custom_kid()->set_value(*key.GetKid()); } util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetParameters().GetKidStrategy()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } RestrictedData restricted_output = RestrictedData(proto_key.SerializeAsString(), *token); return internal::ProtoKeySerialization::Create( kTypeUrl, restricted_output, google::crypto::tink::KeyData::SYMMETRIC, *output_prefix_type, key.GetIdRequirement()); } JwtHmacProtoParametersParserImpl* JwtHmacProtoParametersParser() { static auto* parser = new JwtHmacProtoParametersParserImpl(kTypeUrl, ParseParameters); return parser; } JwtHmacProtoParametersSerializerImpl* JwtHmacProtoParametersSerializer() { static auto* serializer = new JwtHmacProtoParametersSerializerImpl(kTypeUrl, SerializeParameters); return serializer; } JwtHmacProtoKeyParserImpl* JwtHmacProtoKeyParser() { static auto* parser = new JwtHmacProtoKeyParserImpl(kTypeUrl, ParseKey); return parser; } JwtHmacProtoKeySerializerImpl* JwtHmacProtoKeySerializer() { static auto* serializer = new JwtHmacProtoKeySerializerImpl(SerializeKey); return serializer; } } // namespace util::Status RegisterJwtHmacProtoSerialization() { util::Status status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersParser(JwtHmacProtoParametersParser()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersSerializer(JwtHmacProtoParametersSerializer()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(JwtHmacProtoKeyParser()); if (!status.ok()) { return status; } return internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(JwtHmacProtoKeySerializer()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/jwt_hmac_proto_serialization.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_JWT_HMAC_PROTO_SERIALIZATION_H_ #define TINK_JWT_JWT_HMAC_PROTO_SERIALIZATION_H_ #include "tink/util/status.h" namespace crypto { namespace tink { // Registers proto parsers and serializers for JWT HMAC parameters and keys. crypto::tink::util::Status RegisterJwtHmacProtoSerialization(); } // namespace tink } // namespace crypto #endif // TINK_JWT_JWT_HMAC_PROTO_SERIALIZATION_H_ ================================================ FILE: cc/jwt/jwt_hmac_proto_serialization_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/jwt_hmac_proto_serialization.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/jwt/jwt_hmac_key.h" #include "tink/jwt/jwt_hmac_parameters.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/subtle/random.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/common.pb.h" #include "proto/jwt_hmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::subtle::Random; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::JwtHmacAlgorithm; using ::google::crypto::tink::JwtHmacKeyFormat; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::IsFalse; using ::testing::IsTrue; using ::testing::NotNull; using ::testing::TestWithParam; using ::testing::Values; const absl::string_view kTypeUrl = "type.googleapis.com/google.crypto.tink.JwtHmacKey"; struct TestCase { JwtHmacParameters::KidStrategy strategy; OutputPrefixType output_prefix_type; JwtHmacParameters::Algorithm algorithm; JwtHmacAlgorithm proto_algorithm; int key_size; absl::optional expected_kid; absl::optional id; std::string output_prefix; }; class JwtHmacProtoSerializationTest : public TestWithParam { protected: void SetUp() override { internal::MutableSerializationRegistry::GlobalInstance().Reset(); } }; TEST_F(JwtHmacProtoSerializationTest, RegisterTwiceSucceeds) { EXPECT_THAT(RegisterJwtHmacProtoSerialization(), IsOk()); EXPECT_THAT(RegisterJwtHmacProtoSerialization(), IsOk()); } INSTANTIATE_TEST_SUITE_P( JwtHmacProtoSerializationTestSuite, JwtHmacProtoSerializationTest, Values(TestCase{JwtHmacParameters::KidStrategy::kBase64EncodedKeyId, OutputPrefixType::TINK, JwtHmacParameters::Algorithm::kHs256, JwtHmacAlgorithm::HS256, /*key_size=*/16, /*expected_kid=*/"AgMEAA", /*id=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{JwtHmacParameters::KidStrategy::kIgnored, OutputPrefixType::RAW, JwtHmacParameters::Algorithm::kHs384, JwtHmacAlgorithm::HS384, /*key_size=*/32, /*expected_kid=*/absl::nullopt, /*id=*/absl::nullopt, /*output_prefix=*/""}, TestCase{JwtHmacParameters::KidStrategy::kIgnored, OutputPrefixType::RAW, JwtHmacParameters::Algorithm::kHs512, JwtHmacAlgorithm::HS512, /*key_size=*/32, /*expected_kid=*/absl::nullopt, /*id=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(JwtHmacProtoSerializationTest, ParseParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterJwtHmacProtoSerialization(), IsOk()); JwtHmacKeyFormat format; format.set_version(0); format.set_key_size(test_case.key_size); format.set_algorithm(test_case.proto_algorithm); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kTypeUrl, test_case.output_prefix_type, format.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parsed = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(parsed, IsOk()); EXPECT_THAT((*parsed)->HasIdRequirement(), test_case.id.has_value()); util::StatusOr expected = JwtHmacParameters::Create( test_case.key_size, test_case.strategy, test_case.algorithm); ASSERT_THAT(expected, IsOk()); EXPECT_THAT(**parsed, Eq(*expected)); } TEST_F(JwtHmacProtoSerializationTest, ParseParametersWithInvalidSerialization) { ASSERT_THAT(RegisterJwtHmacProtoSerialization(), IsOk()); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kTypeUrl, OutputPrefixType::RAW, "invalid_serialization"); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Failed to parse JwtHmacKeyFormat proto"))); } TEST_F(JwtHmacProtoSerializationTest, ParseParametersWithInvalidVersion) { ASSERT_THAT(RegisterJwtHmacProtoSerialization(), IsOk()); JwtHmacKeyFormat format; format.set_version(1); // Invalid version number. format.set_key_size(32); format.set_algorithm(JwtHmacAlgorithm::HS256); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kTypeUrl, OutputPrefixType::RAW, format.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("only version 0 is accepted"))); } TEST_F(JwtHmacProtoSerializationTest, ParseParametersWithUnknownAlgorithm) { ASSERT_THAT(RegisterJwtHmacProtoSerialization(), IsOk()); JwtHmacKeyFormat format; format.set_version(0); format.set_key_size(32); format.set_algorithm(JwtHmacAlgorithm::HS_UNKNOWN); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kTypeUrl, OutputPrefixType::RAW, format.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Could not determine JwtHmacAlgorithm"))); } using JwtHmacParsePrefixTest = TestWithParam; INSTANTIATE_TEST_SUITE_P(JwtHmacParsePrefixTestSuite, JwtHmacParsePrefixTest, Values(OutputPrefixType::CRUNCHY, OutputPrefixType::LEGACY, OutputPrefixType::UNKNOWN_PREFIX)); TEST_P(JwtHmacParsePrefixTest, ParseParametersWithInvalidPrefix) { OutputPrefixType invalid_output_prefix_type = GetParam(); internal::MutableSerializationRegistry::GlobalInstance().Reset(); ASSERT_THAT(RegisterJwtHmacProtoSerialization(), IsOk()); JwtHmacKeyFormat format; format.set_version(0); format.set_key_size(32); format.set_algorithm(JwtHmacAlgorithm::HS256); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kTypeUrl, invalid_output_prefix_type, format.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT( params.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Invalid OutputPrefixType for JwtHmacKeyFormat"))); } TEST_P(JwtHmacProtoSerializationTest, SerializeParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterJwtHmacProtoSerialization(), IsOk()); util::StatusOr parameters = JwtHmacParameters::Create( test_case.key_size, test_case.strategy, test_case.algorithm); ASSERT_THAT(parameters, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( *parameters); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kTypeUrl)); const internal::ProtoParametersSerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->GetKeyTemplate().type_url(), Eq(kTypeUrl)); EXPECT_THAT(proto_serialization->GetKeyTemplate().output_prefix_type(), Eq(test_case.output_prefix_type)); JwtHmacKeyFormat format; ASSERT_THAT( format.ParseFromString(proto_serialization->GetKeyTemplate().value()), IsTrue()); EXPECT_THAT(format.version(), Eq(0)); EXPECT_THAT(format.key_size(), Eq(test_case.key_size)); EXPECT_THAT(format.algorithm(), Eq(test_case.proto_algorithm)); } TEST_F(JwtHmacProtoSerializationTest, SerializeParametersWithCustomKidFails) { ASSERT_THAT(RegisterJwtHmacProtoSerialization(), IsOk()); util::StatusOr parameters = JwtHmacParameters::Create( /*key_size_in_bytes=*/32, JwtHmacParameters::KidStrategy::kCustom, JwtHmacParameters::Algorithm::kHs256); ASSERT_THAT(parameters, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( *parameters); EXPECT_THAT( serialization.status(), StatusIs( absl::StatusCode::kInvalidArgument, HasSubstr( "Unable to serialize JwtHmacParameters::KidStrategy::kCustom"))); } TEST_P(JwtHmacProtoSerializationTest, ParseKeyWithoutCustomKid) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterJwtHmacProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(test_case.key_size); google::crypto::tink::JwtHmacKey key_proto; key_proto.set_version(0); key_proto.set_algorithm(test_case.proto_algorithm); key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kTypeUrl, serialized_key, KeyData::SYMMETRIC, test_case.output_prefix_type, test_case.id); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parsed_key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key, IsOk()); EXPECT_THAT((*parsed_key)->GetParameters().HasIdRequirement(), test_case.id.has_value()); EXPECT_THAT((*parsed_key)->GetIdRequirement(), Eq(test_case.id)); util::StatusOr expected_parameters = JwtHmacParameters::Create(test_case.key_size, test_case.strategy, test_case.algorithm); ASSERT_THAT(expected_parameters, IsOk()); JwtHmacKey::Builder builder = JwtHmacKey::Builder() .SetParameters(*expected_parameters) .SetKeyBytes( RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get())); if (test_case.id.has_value()) { builder.SetIdRequirement(*test_case.id); } util::StatusOr expected_key = builder.Build(GetPartialKeyAccess()); ASSERT_THAT(expected_key, IsOk()); EXPECT_THAT(**parsed_key, Eq(*expected_key)); } TEST_F(JwtHmacProtoSerializationTest, ParseKeyWithCustomKid) { ASSERT_THAT(RegisterJwtHmacProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); google::crypto::tink::JwtHmacKey key_proto; key_proto.set_version(0); key_proto.set_algorithm(JwtHmacAlgorithm::HS256); key_proto.set_key_value(raw_key_bytes); key_proto.mutable_custom_kid()->set_value("custom_kid"); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::RAW, /*id_requirement=*/absl::nullopt); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parsed_key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key, IsOk()); EXPECT_THAT((*parsed_key)->GetParameters().HasIdRequirement(), IsFalse()); EXPECT_THAT((*parsed_key)->GetIdRequirement(), Eq(absl::nullopt)); util::StatusOr expected_parameters = JwtHmacParameters::Create(/*key_size_in_bytes=*/32, JwtHmacParameters::KidStrategy::kCustom, JwtHmacParameters::Algorithm::kHs256); ASSERT_THAT(expected_parameters, IsOk()); util::StatusOr expected_key = JwtHmacKey::Builder() .SetParameters(*expected_parameters) .SetKeyBytes( RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get())) .SetCustomKid(key_proto.custom_kid().value()) .Build(GetPartialKeyAccess()); ASSERT_THAT(expected_key, IsOk()); EXPECT_THAT(**parsed_key, Eq(*expected_key)); } TEST_F(JwtHmacProtoSerializationTest, ParseTinkKeyWithCustomKidFails) { ASSERT_THAT(RegisterJwtHmacProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); google::crypto::tink::JwtHmacKey key_proto; key_proto.set_version(0); key_proto.set_algorithm(JwtHmacAlgorithm::HS256); key_proto.set_key_value(raw_key_bytes); key_proto.mutable_custom_kid()->set_value("custom_kid"); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/123); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); // Omitting expectation on specific error message since the error occurs // downstream while building JwtHmacKey object. EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(JwtHmacProtoSerializationTest, ParseKeyWithInvalidSerialization) { ASSERT_THAT(RegisterJwtHmacProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); google::crypto::tink::JwtHmacKey key_proto; key_proto.set_version(0); key_proto.set_algorithm(JwtHmacAlgorithm::HS256); key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::RAW, /*id_requirement=*/absl::nullopt); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Failed to parse JwtHmacKey proto"))); } TEST_F(JwtHmacProtoSerializationTest, ParseKeyWithInvalidVersion) { ASSERT_THAT(RegisterJwtHmacProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); google::crypto::tink::JwtHmacKey key_proto; key_proto.set_version(1); // Invalid version number. key_proto.set_algorithm(JwtHmacAlgorithm::HS256); key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::RAW, /*id_requirement=*/absl::nullopt); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT( key.status(), StatusIs( absl::StatusCode::kInvalidArgument, HasSubstr("Parsing JwtHmacKey failed: only version 0 is accepted"))); } TEST_P(JwtHmacParsePrefixTest, ParseKeyWithInvalidPrefix) { OutputPrefixType invalid_output_prefix_type = GetParam(); internal::MutableSerializationRegistry::GlobalInstance().Reset(); ASSERT_THAT(RegisterJwtHmacProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); google::crypto::tink::JwtHmacKey key_proto; key_proto.set_version(0); key_proto.set_algorithm(JwtHmacAlgorithm::HS256); key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kTypeUrl, serialized_key, KeyData::SYMMETRIC, invalid_output_prefix_type, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT( key.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Invalid OutputPrefixType for JwtHmacKeyFormat"))); } TEST_F(JwtHmacProtoSerializationTest, ParseKeyWithUnknownAlgorithm) { ASSERT_THAT(RegisterJwtHmacProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); google::crypto::tink::JwtHmacKey key_proto; key_proto.set_version(0); key_proto.set_algorithm(JwtHmacAlgorithm::HS_UNKNOWN); key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::RAW, /*id_requirement=*/absl::nullopt); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Could not determine JwtHmacAlgorithm"))); } TEST_F(JwtHmacProtoSerializationTest, ParseKeyWithoutSecretKeyAccess) { ASSERT_THAT(RegisterJwtHmacProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); google::crypto::tink::JwtHmacKey key_proto; key_proto.set_version(0); key_proto.set_algorithm(JwtHmacAlgorithm::HS256); key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kTypeUrl, serialized_key, KeyData::SYMMETRIC, OutputPrefixType::RAW, /*id_requirement=*/absl::nullopt); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("SecretKeyAccess is required"))); } TEST_P(JwtHmacProtoSerializationTest, SerializeKeyWithoutCustomKid) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterJwtHmacProtoSerialization(), IsOk()); util::StatusOr parameters = JwtHmacParameters::Create( test_case.key_size, test_case.strategy, test_case.algorithm); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(test_case.key_size); JwtHmacKey::Builder builder = JwtHmacKey::Builder() .SetParameters(*parameters) .SetKeyBytes( RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get())); if (test_case.id.has_value()) { builder.SetIdRequirement(*test_case.id); } util::StatusOr key = builder.Build(GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kTypeUrl)); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq(kTypeUrl)); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::SYMMETRIC)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id)); google::crypto::tink::JwtHmacKey proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.version(), Eq(0)); EXPECT_THAT(proto_key.key_value(), Eq(raw_key_bytes)); EXPECT_THAT(proto_key.algorithm(), Eq(test_case.proto_algorithm)); EXPECT_THAT(proto_key.has_custom_kid(), IsFalse()); } TEST_F(JwtHmacProtoSerializationTest, SerializeKeyWithCustomKid) { ASSERT_THAT(RegisterJwtHmacProtoSerialization(), IsOk()); util::StatusOr parameters = JwtHmacParameters::Create( /*key_size_in_bytes=*/32, JwtHmacParameters::KidStrategy::kCustom, JwtHmacParameters::Algorithm::kHs256); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); util::StatusOr key = JwtHmacKey::Builder() .SetParameters(*parameters) .SetKeyBytes( RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get())) .SetCustomKid("custom_kid") .Build(GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kTypeUrl)); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq(kTypeUrl)); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::SYMMETRIC)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(OutputPrefixType::RAW)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(absl::nullopt)); google::crypto::tink::JwtHmacKey proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.version(), Eq(0)); EXPECT_THAT(proto_key.key_value(), Eq(raw_key_bytes)); EXPECT_THAT(proto_key.algorithm(), Eq(JwtHmacAlgorithm::HS256)); ASSERT_THAT(proto_key.has_custom_kid(), IsTrue()); EXPECT_THAT(proto_key.custom_kid().value(), Eq(*key->GetKid())); } TEST_F(JwtHmacProtoSerializationTest, SerializeKeyWithoutSecretKeyAccess) { ASSERT_THAT(RegisterJwtHmacProtoSerialization(), IsOk()); util::StatusOr parameters = JwtHmacParameters::Create( /*key_size_in_bytes=*/32, JwtHmacParameters::KidStrategy::kIgnored, JwtHmacParameters::Algorithm::kHs256); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); util::StatusOr key = JwtHmacKey::Builder() .SetParameters(*parameters) .SetKeyBytes( RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get())) .Build(GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, /*token=*/absl::nullopt); ASSERT_THAT(serialization.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("SecretKeyAccess is required"))); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/jwt_key_templates.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/jwt_key_templates.h" #include #include #include "openssl/bn.h" #include "openssl/rsa.h" #include "tink/internal/bn_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/util/statusor.h" #include "proto/common.pb.h" #include "proto/jwt_ecdsa.pb.h" #include "proto/jwt_hmac.pb.h" #include "proto/jwt_rsa_ssa_pkcs1.pb.h" #include "proto/jwt_rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" using ::google::crypto::tink::JwtEcdsaAlgorithm; using ::google::crypto::tink::JwtEcdsaKeyFormat; using ::google::crypto::tink::JwtHmacAlgorithm; using ::google::crypto::tink::JwtHmacKeyFormat; using ::google::crypto::tink::JwtRsaSsaPkcs1Algorithm; using ::google::crypto::tink::JwtRsaSsaPkcs1KeyFormat; using ::google::crypto::tink::JwtRsaSsaPssAlgorithm; using ::google::crypto::tink::JwtRsaSsaPssKeyFormat; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::OutputPrefixType; namespace crypto { namespace tink { namespace { KeyTemplate* NewJwtHmacKeyTemplate(JwtHmacAlgorithm algorithm, uint32_t key_size, OutputPrefixType output_prefix_type) { KeyTemplate* key_template = new KeyTemplate; key_template->set_type_url( "type.googleapis.com/google.crypto.tink.JwtHmacKey"); key_template->set_output_prefix_type(output_prefix_type); JwtHmacKeyFormat key_format; key_format.set_key_size(key_size); key_format.set_algorithm(algorithm); key_format.SerializeToString(key_template->mutable_value()); return key_template; } KeyTemplate* NewJwtEcdsaKeyTemplate(JwtEcdsaAlgorithm algorithm, OutputPrefixType output_prefix_type) { KeyTemplate* key_template = new KeyTemplate; key_template->set_type_url( "type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey"); key_template->set_output_prefix_type(output_prefix_type); JwtEcdsaKeyFormat key_format; key_format.set_algorithm(algorithm); key_format.SerializeToString(key_template->mutable_value()); return key_template; } KeyTemplate* NewJwtRsaSsaPkcs1KeyTemplate(JwtRsaSsaPkcs1Algorithm algorithm, int modulus_size_in_bits, int public_exponent, OutputPrefixType output_prefix_type) { KeyTemplate* key_template = new KeyTemplate; key_template->set_type_url( "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PrivateKey"); key_template->set_output_prefix_type(output_prefix_type); JwtRsaSsaPkcs1KeyFormat key_format; key_format.set_algorithm(algorithm); key_format.set_modulus_size_in_bits(modulus_size_in_bits); internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), public_exponent); util::StatusOr e_str = internal::BignumToString(e.get(), BN_num_bytes(e.get())); key_format.set_public_exponent(e_str.value()); key_format.SerializeToString(key_template->mutable_value()); return key_template; } KeyTemplate* NewJwtRsaSsaPssKeyTemplate(JwtRsaSsaPssAlgorithm algorithm, int modulus_size_in_bits, int public_exponent, OutputPrefixType output_prefix_type) { KeyTemplate* key_template = new KeyTemplate; key_template->set_type_url( "type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPrivateKey"); key_template->set_output_prefix_type(output_prefix_type); JwtRsaSsaPssKeyFormat key_format; key_format.set_algorithm(algorithm); key_format.set_modulus_size_in_bits(modulus_size_in_bits); internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), public_exponent); util::StatusOr e_str = internal::BignumToString(e.get(), BN_num_bytes(e.get())); key_format.set_public_exponent(e_str.value()); key_format.SerializeToString(key_template->mutable_value()); return key_template; } } // anonymous namespace const KeyTemplate& JwtHs256Template() { static const KeyTemplate* key_template = NewJwtHmacKeyTemplate( JwtHmacAlgorithm::HS256, 32, OutputPrefixType::TINK); return *key_template; } const KeyTemplate& RawJwtHs256Template() { static const KeyTemplate* key_template = NewJwtHmacKeyTemplate(JwtHmacAlgorithm::HS256, 32, OutputPrefixType::RAW); return *key_template; } const KeyTemplate& JwtHs384Template() { static const KeyTemplate* key_template = NewJwtHmacKeyTemplate( JwtHmacAlgorithm::HS384, 48, OutputPrefixType::TINK); return *key_template; } const KeyTemplate& RawJwtHs384Template() { static const KeyTemplate* key_template = NewJwtHmacKeyTemplate(JwtHmacAlgorithm::HS384, 48, OutputPrefixType::RAW); return *key_template; } const KeyTemplate& JwtHs512Template() { static const KeyTemplate* key_template = NewJwtHmacKeyTemplate( JwtHmacAlgorithm::HS512, 64, OutputPrefixType::TINK); return *key_template; } const KeyTemplate& RawJwtHs512Template() { static const KeyTemplate* key_template = NewJwtHmacKeyTemplate(JwtHmacAlgorithm::HS512, 64, OutputPrefixType::RAW); return *key_template; } const KeyTemplate& JwtEs256Template() { static const KeyTemplate* key_template = NewJwtEcdsaKeyTemplate(JwtEcdsaAlgorithm::ES256, OutputPrefixType::TINK); return *key_template; } const KeyTemplate& RawJwtEs256Template() { static const KeyTemplate* key_template = NewJwtEcdsaKeyTemplate(JwtEcdsaAlgorithm::ES256, OutputPrefixType::RAW); return *key_template; } const KeyTemplate& JwtEs384Template() { static const KeyTemplate* key_template = NewJwtEcdsaKeyTemplate(JwtEcdsaAlgorithm::ES384, OutputPrefixType::TINK); return *key_template; } const KeyTemplate& RawJwtEs384Template() { static const KeyTemplate* key_template = NewJwtEcdsaKeyTemplate(JwtEcdsaAlgorithm::ES384, OutputPrefixType::RAW); return *key_template; } const KeyTemplate& JwtEs512Template() { static const KeyTemplate* key_template = NewJwtEcdsaKeyTemplate(JwtEcdsaAlgorithm::ES512, OutputPrefixType::TINK); return *key_template; } const KeyTemplate& RawJwtEs512Template() { static const KeyTemplate* key_template = NewJwtEcdsaKeyTemplate(JwtEcdsaAlgorithm::ES512, OutputPrefixType::RAW); return *key_template; } const KeyTemplate& JwtRs256_2048_F4_Template() { static const KeyTemplate* key_template = NewJwtRsaSsaPkcs1KeyTemplate( JwtRsaSsaPkcs1Algorithm::RS256, 2048, RSA_F4, OutputPrefixType::TINK); return *key_template; } const KeyTemplate& RawJwtRs256_2048_F4_Template() { static const KeyTemplate* key_template = NewJwtRsaSsaPkcs1KeyTemplate( JwtRsaSsaPkcs1Algorithm::RS256, 2048, RSA_F4, OutputPrefixType::RAW); return *key_template; } const KeyTemplate& JwtRs256_3072_F4_Template() { static const KeyTemplate* key_template = NewJwtRsaSsaPkcs1KeyTemplate( JwtRsaSsaPkcs1Algorithm::RS256, 3072, RSA_F4, OutputPrefixType::TINK); return *key_template; } const KeyTemplate& RawJwtRs256_3072_F4_Template() { static const KeyTemplate* key_template = NewJwtRsaSsaPkcs1KeyTemplate( JwtRsaSsaPkcs1Algorithm::RS256, 3072, RSA_F4, OutputPrefixType::RAW); return *key_template; } const KeyTemplate& JwtRs384_3072_F4_Template() { static const KeyTemplate* key_template = NewJwtRsaSsaPkcs1KeyTemplate( JwtRsaSsaPkcs1Algorithm::RS384, 3072, RSA_F4, OutputPrefixType::TINK); return *key_template; } const KeyTemplate& RawJwtRs384_3072_F4_Template() { static const KeyTemplate* key_template = NewJwtRsaSsaPkcs1KeyTemplate( JwtRsaSsaPkcs1Algorithm::RS384, 3072, RSA_F4, OutputPrefixType::RAW); return *key_template; } const KeyTemplate& JwtRs512_4096_F4_Template() { static const KeyTemplate* key_template = NewJwtRsaSsaPkcs1KeyTemplate( JwtRsaSsaPkcs1Algorithm::RS512, 4096, RSA_F4, OutputPrefixType::TINK); return *key_template; } const KeyTemplate& RawJwtRs512_4096_F4_Template() { static const KeyTemplate* key_template = NewJwtRsaSsaPkcs1KeyTemplate( JwtRsaSsaPkcs1Algorithm::RS512, 4096, RSA_F4, OutputPrefixType::RAW); return *key_template; } const KeyTemplate& JwtPs256_2048_F4_Template() { static const KeyTemplate* key_template = NewJwtRsaSsaPssKeyTemplate( JwtRsaSsaPssAlgorithm::PS256, 2048, RSA_F4, OutputPrefixType::TINK); return *key_template; } const KeyTemplate& RawJwtPs256_2048_F4_Template() { static const KeyTemplate* key_template = NewJwtRsaSsaPssKeyTemplate( JwtRsaSsaPssAlgorithm::PS256, 2048, RSA_F4, OutputPrefixType::RAW); return *key_template; } const KeyTemplate& JwtPs256_3072_F4_Template() { static const KeyTemplate* key_template = NewJwtRsaSsaPssKeyTemplate( JwtRsaSsaPssAlgorithm::PS256, 3072, RSA_F4, OutputPrefixType::TINK); return *key_template; } const KeyTemplate& RawJwtPs256_3072_F4_Template() { static const KeyTemplate* key_template = NewJwtRsaSsaPssKeyTemplate( JwtRsaSsaPssAlgorithm::PS256, 3072, RSA_F4, OutputPrefixType::RAW); return *key_template; } const KeyTemplate& JwtPs384_3072_F4_Template() { static const KeyTemplate* key_template = NewJwtRsaSsaPssKeyTemplate( JwtRsaSsaPssAlgorithm::PS384, 3072, RSA_F4, OutputPrefixType::TINK); return *key_template; } const KeyTemplate& RawJwtPs384_3072_F4_Template() { static const KeyTemplate* key_template = NewJwtRsaSsaPssKeyTemplate( JwtRsaSsaPssAlgorithm::PS384, 3072, RSA_F4, OutputPrefixType::RAW); return *key_template; } const KeyTemplate& JwtPs512_4096_F4_Template() { static const KeyTemplate* key_template = NewJwtRsaSsaPssKeyTemplate( JwtRsaSsaPssAlgorithm::PS512, 4096, RSA_F4, OutputPrefixType::TINK); return *key_template; } const KeyTemplate& RawJwtPs512_4096_F4_Template() { static const KeyTemplate* key_template = NewJwtRsaSsaPssKeyTemplate( JwtRsaSsaPssAlgorithm::PS512, 4096, RSA_F4, OutputPrefixType::RAW); return *key_template; } } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/jwt_key_templates.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_JWT_KEY_TEMPLATES_H_ #define TINK_JWT_JWT_KEY_TEMPLATES_H_ #include "proto/tink.pb.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Pre-generated KeyTemplate for Jwt key types. One can use these templates // to generate new KeysetHandle object with fresh keys. The templates with // the "Raw" prefix generate tokens without a "kid" header. // // To generate a new keyset that contains a single JwtHmacKey, one can do: // // auto status = JwtMacRegister(); // if (!status.ok()) { /* fail with error */ } // auto handle_result = // KeysetHandle::GenerateNew(JwtHs256Template()); // if (!handle_result.ok()) { /* fail with error */ } // auto keyset_handle = std::move(handle_result.value()); const google::crypto::tink::KeyTemplate& JwtHs256Template(); const google::crypto::tink::KeyTemplate& RawJwtHs256Template(); const google::crypto::tink::KeyTemplate& JwtHs384Template(); const google::crypto::tink::KeyTemplate& RawJwtHs384Template(); const google::crypto::tink::KeyTemplate& JwtHs512Template(); const google::crypto::tink::KeyTemplate& RawJwtHs512Template(); const google::crypto::tink::KeyTemplate& JwtEs256Template(); const google::crypto::tink::KeyTemplate& RawJwtEs256Template(); const google::crypto::tink::KeyTemplate& JwtEs384Template(); const google::crypto::tink::KeyTemplate& RawJwtEs384Template(); const google::crypto::tink::KeyTemplate& JwtEs512Template(); const google::crypto::tink::KeyTemplate& RawJwtEs512Template(); const google::crypto::tink::KeyTemplate& JwtRs256_2048_F4_Template(); const google::crypto::tink::KeyTemplate& RawJwtRs256_2048_F4_Template(); const google::crypto::tink::KeyTemplate& JwtRs256_3072_F4_Template(); const google::crypto::tink::KeyTemplate& RawJwtRs256_3072_F4_Template(); const google::crypto::tink::KeyTemplate& JwtRs384_3072_F4_Template(); const google::crypto::tink::KeyTemplate& RawJwtRs384_3072_F4_Template(); const google::crypto::tink::KeyTemplate& JwtRs512_4096_F4_Template(); const google::crypto::tink::KeyTemplate& RawJwtRs512_4096_F4_Template(); const google::crypto::tink::KeyTemplate& JwtPs256_2048_F4_Template(); const google::crypto::tink::KeyTemplate& RawJwtPs256_2048_F4_Template(); const google::crypto::tink::KeyTemplate& JwtPs256_3072_F4_Template(); const google::crypto::tink::KeyTemplate& RawJwtPs256_3072_F4_Template(); const google::crypto::tink::KeyTemplate& JwtPs384_3072_F4_Template(); const google::crypto::tink::KeyTemplate& RawJwtPs384_3072_F4_Template(); const google::crypto::tink::KeyTemplate& JwtPs512_4096_F4_Template(); const google::crypto::tink::KeyTemplate& RawJwtPs512_4096_F4_Template(); } // namespace tink } // namespace crypto #endif // TINK_JWT_JWT_KEY_TEMPLATES_H_ ================================================ FILE: cc/jwt/jwt_key_templates_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/jwt_key_templates.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/config/global_registry.h" #include "tink/jwt/jwt_mac.h" #include "tink/jwt/jwt_mac_config.h" #include "tink/jwt/jwt_public_key_sign.h" #include "tink/jwt/jwt_public_key_verify.h" #include "tink/jwt/jwt_signature_config.h" #include "tink/jwt/jwt_validator.h" #include "tink/jwt/raw_jwt.h" #include "tink/jwt/verified_jwt.h" #include "tink/keyset_handle.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" using ::crypto::tink::test::IsOk; using google::crypto::tink::KeyTemplate; namespace crypto { namespace tink { namespace { class JwtMacKeyTemplatesTest : public testing::TestWithParam { void SetUp() override { ASSERT_TRUE(JwtMacRegister().ok()); } }; TEST_P(JwtMacKeyTemplatesTest, CreateComputeVerify) { KeyTemplate key_template = GetParam(); util::StatusOr> keyset_handle = KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()); ASSERT_THAT(keyset_handle, IsOk()); util::StatusOr> jwt_mac = (*keyset_handle) ->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(jwt_mac, IsOk()); util::StatusOr raw_jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr compact = (*jwt_mac)->ComputeMacAndEncode(*raw_jwt); ASSERT_THAT(compact, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .ExpectIssuer("issuer") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); util::StatusOr verified_jwt = (*jwt_mac)->VerifyMacAndDecode(*compact, *validator); ASSERT_THAT(verified_jwt, IsOk()); EXPECT_THAT(verified_jwt->GetIssuer(), test::IsOkAndHolds("issuer")); util::StatusOr validator2 = JwtValidatorBuilder() .ExpectIssuer("unknown") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator2, IsOk()); EXPECT_FALSE((*jwt_mac)->VerifyMacAndDecode(*compact, *validator2).ok()); } INSTANTIATE_TEST_SUITE_P(JwtMacKeyTemplatesTest, JwtMacKeyTemplatesTest, testing::Values(JwtHs256Template(), JwtHs384Template(), JwtHs512Template())); class JwtSignatureKeyTemplatesTest : public testing::TestWithParam { void SetUp() override { ASSERT_TRUE(JwtSignatureRegister().ok()); } }; TEST_P(JwtSignatureKeyTemplatesTest, CreateComputeVerify) { KeyTemplate key_template = GetParam(); util::StatusOr> private_handle = KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()); ASSERT_THAT(private_handle, IsOk()); util::StatusOr> sign = (*private_handle) ->GetPrimitive( ConfigGlobalRegistry()); ASSERT_THAT(sign, IsOk()); util::StatusOr> public_handle = (*private_handle)->GetPublicKeysetHandle(KeyGenConfigGlobalRegistry()); ASSERT_THAT(public_handle, IsOk()); util::StatusOr> verify = (*public_handle) ->GetPrimitive( ConfigGlobalRegistry()); ASSERT_THAT(verify, IsOk()); util::StatusOr raw_jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr compact = (*sign)->SignAndEncode(*raw_jwt); ASSERT_THAT(compact, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .ExpectIssuer("issuer") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); util::StatusOr verified_jwt = (*verify)->VerifyAndDecode(*compact, *validator); ASSERT_THAT(verified_jwt, IsOk()); EXPECT_THAT(verified_jwt->GetIssuer(), test::IsOkAndHolds("issuer")); util::StatusOr validator2 = JwtValidatorBuilder() .ExpectIssuer("unknown") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); EXPECT_FALSE((*verify)->VerifyAndDecode(*compact, *validator2).ok()); } INSTANTIATE_TEST_SUITE_P( JwtSignatureKeyTemplatesTest, JwtSignatureKeyTemplatesTest, testing::Values(JwtEs256Template(), JwtEs384Template(), JwtEs512Template(), RawJwtEs256Template(), JwtRs256_2048_F4_Template(), JwtRs256_3072_F4_Template(), JwtRs384_3072_F4_Template(), JwtRs512_4096_F4_Template(), RawJwtRs256_2048_F4_Template(), JwtPs256_2048_F4_Template(), JwtPs256_3072_F4_Template(), JwtPs384_3072_F4_Template(), JwtPs512_4096_F4_Template(), RawJwtPs256_2048_F4_Template())); } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/jwt_mac.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_JWT_MAC_H_ #define TINK_JWT_JWT_MAC_H_ #include #include "absl/strings/string_view.h" #include "tink/jwt/jwt_validator.h" #include "tink/jwt/raw_jwt.h" #include "tink/jwt/verified_jwt.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Interface for authenticating and verifying JWT with JWS MAC. // // Sees RFC 7519 and RFC 7515. Security guarantees: similar to MAC. class JwtMac { public: // Computes a MAC and encodes the raw JWT token and the MAC in the JWS compact // serialization format. virtual crypto::tink::util::StatusOr ComputeMacAndEncode( const RawJwt& token) const = 0; // Verifies and decodes a JWT token in the JWS compact serialization format. // // The JWT is validated against the rules in validator. That is, every claim // in validator must also be present in the JWT. For example, if validator // contains an issuer (iss) claim, the JWT must contain an identical claim. // The JWT can contain claims that are NOT in the validator. However, if the // JWT contains a list of audiences, the validator must also contain an // audience in the list. // // If the JWT contains timestamp claims such as expiration (exp), issued_at // (iat) or not_before (nbf), they will also be validated. validator allows to // set a clock skew, to deal with small clock differences among different // machines. virtual crypto::tink::util::StatusOr VerifyMacAndDecode( absl::string_view compact, const JwtValidator& validator) const = 0; virtual ~JwtMac() = default; }; } // namespace tink } // namespace crypto #endif // TINK_JWT_JWT_MAC_H_ ================================================ FILE: cc/jwt/jwt_mac_config.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/jwt_mac_config.h" #include "absl/memory/memory.h" #include "tink/config/config_util.h" #include "tink/config/tink_fips.h" #include "tink/jwt/internal/jwt_hmac_key_manager.h" #include "tink/jwt/internal/jwt_mac_wrapper.h" #include "tink/registry.h" #include "tink/util/status.h" #include "proto/config.pb.h" namespace crypto { namespace tink { // static util::Status JwtMacRegister() { // Register primitive wrapper. auto status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) return status; // Register key managers which utilize the FIPS validated BoringCrypto // implementations. status = Registry::RegisterKeyTypeManager( absl::make_unique(), true); if (!status.ok()) return status; if (IsFipsModeEnabled()) { return util::OkStatus(); } // There are currently no non-FIPS key managers. return util::OkStatus(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/jwt_mac_config.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_JWT_MAC_CONFIG_H_ #define TINK_JWT_JWT_MAC_CONFIG_H_ #include "absl/base/macros.h" #include "tink/util/status.h" #include "proto/config.pb.h" namespace crypto { namespace tink { // Registers JwtMac primitive wrapper and key managers for all JwtMac key // types from the current Tink release. crypto::tink::util::Status JwtMacRegister(); } // namespace tink } // namespace crypto #endif // TINK_JWT_JWT_MAC_CONFIG_H_ ================================================ FILE: cc/jwt/jwt_mac_config_test.cc ================================================ // Copyright 2023 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/jwt_mac_config.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/config/global_registry.h" #include "tink/internal/fips_utils.h" #include "tink/jwt/jwt_key_templates.h" #include "tink/keyset_handle.h" #include "tink/registry.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::testing::Not; class JwtMacConfigTest : public ::testing::Test { protected: void SetUp() override { Registry::Reset(); } }; TEST_F(JwtMacConfigTest, FailIfAndOnlyIfInInvalidFipsState) { // If FIPS is enabled, then we need FIPS also to be enabled in BoringSSL. // Otherwise we are in an invalid state and must fail. bool invalid_fips_state = internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl(); if (invalid_fips_state) { EXPECT_THAT(JwtMacRegister(), Not(IsOk())); EXPECT_THAT(KeysetHandle::GenerateNew(JwtHs256Template(), KeyGenConfigGlobalRegistry()) .status(), Not(IsOk())); } else { EXPECT_THAT(JwtMacRegister(), IsOk()); EXPECT_THAT(KeysetHandle::GenerateNew(JwtHs256Template(), KeyGenConfigGlobalRegistry()) .status(), IsOk()); } } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/jwt_mac_key.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_JWT_MAC_KEY_H_ #define TINK_JWT_JWT_MAC_KEY_H_ #include #include "absl/types/optional.h" #include "tink/jwt/jwt_mac_parameters.h" #include "tink/key.h" namespace crypto { namespace tink { // Represents the authentication and verification functions for the JWT MAC // primitive. class JwtMacKey : public Key { public: // Returns the `kid` to be used for this key // (https://www.rfc-editor.org/rfc/rfc7517#section-4.5). // // Note that the `kid` is not necessarily related to Tink's key ID in the // keyset. // // If present, this `kid` will be written into the `kid` header during // `ComputeMacAndEncode()`. If absent, no `kid` will be written. // // If present, and the `kid` header is present, the contents of the // `kid` header need to match the return value of this function for // validation to succeed in `VerifyMacAndDecode()`. // // Note that `GetParameters().AllowKidAbsent()` specifies whether or not // omitting the `kid` header is allowed. Of course, if // `GetParameters().AllowKidAbsent()` returns false, then `GetKid()` must // return a non-empty value. virtual absl::optional GetKid() const = 0; const JwtMacParameters& GetParameters() const override = 0; bool operator==(const Key& other) const override = 0; }; } // namespace tink } // namespace crypto #endif // TINK_JWT_JWT_MAC_KEY_H_ ================================================ FILE: cc/jwt/jwt_mac_parameters.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_JWT_MAC_PARAMETERS_H_ #define TINK_JWT_JWT_MAC_PARAMETERS_H_ #include "tink/parameters.h" namespace crypto { namespace tink { // `JwtMacKey` description without the randomly chosen key material. class JwtMacParameters : public Parameters { // Returns true if verification is allowed for tokens without a `kid` header. virtual bool AllowKidAbsent() const = 0; }; } // namespace tink } // namespace crypto #endif // TINK_JWT_JWT_MAC_PARAMETERS_H_ ================================================ FILE: cc/jwt/jwt_public_key_sign.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_JWT_PUBLIC_KEY_SIGN_H_ #define TINK_JWT_JWT_PUBLIC_KEY_SIGN_H_ #include #include "absl/strings/string_view.h" #include "tink/jwt/raw_jwt.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Interface for signing JWT. // // Sees RFC 7519 and RFC 7515. Security guarantees: similar to PublicKeySign. class JwtPublicKeySign { public: // Computes a signature, and encodes the JWT and the signature in the JWS // compact serialization format. virtual crypto::tink::util::StatusOr SignAndEncode( const RawJwt& token) const = 0; virtual ~JwtPublicKeySign() = default; }; } // namespace tink } // namespace crypto #endif // TINK_JWT_JWT_PUBLIC_KEY_SIGN_H_ ================================================ FILE: cc/jwt/jwt_public_key_verify.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_JWT_PUBLIC_KEY_VERIFY_H_ #define TINK_JWT_JWT_PUBLIC_KEY_VERIFY_H_ #include "absl/strings/string_view.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/jwt/verified_jwt.h" #include "tink/jwt/jwt_validator.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Interface for verifying signed JWT. // // Sees RFC 7519 and RFC 7515. Security guarantees: similar to PublicKeyVerify. class JwtPublicKeyVerify { public: // Verifies and decodes a JWT token in the JWS compact serialization format. // // The JWT is validated against the rules in validator. That is, every claim // in validator must also be present in the JWT. For example, if validator // contains an issuer (iss) claim, the JWT must contain an identical claim. // The JWT can contain claims that are NOT in the validator. However, if the // JWT contains a list of audiences, the validator must also contain an // audience in the list. // // If the JWT contains timestamp claims such as expiration (exp), issued_at // (iat) or not_before (nbf), they will also be validated. validator allows to // set a clock skew, to deal with small clock differences among different // machines. virtual crypto::tink::util::StatusOr VerifyAndDecode( absl::string_view compact, const JwtValidator& validator) const = 0; virtual ~JwtPublicKeyVerify() = default; }; } // namespace tink } // namespace crypto #endif // TINK_JWT_JWT_PUBLIC_KEY_VERIFY_H_ ================================================ FILE: cc/jwt/jwt_signature_config.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/jwt_signature_config.h" #include "absl/memory/memory.h" #include "tink/config/config_util.h" #include "tink/config/tink_fips.h" #include "tink/jwt/internal/jwt_ecdsa_sign_key_manager.h" #include "tink/jwt/internal/jwt_ecdsa_verify_key_manager.h" #include "tink/jwt/internal/jwt_public_key_sign_wrapper.h" #include "tink/jwt/internal/jwt_public_key_verify_wrapper.h" #include "tink/jwt/internal/jwt_rsa_ssa_pkcs1_sign_key_manager.h" #include "tink/jwt/internal/jwt_rsa_ssa_pkcs1_verify_key_manager.h" #include "tink/jwt/internal/jwt_rsa_ssa_pss_sign_key_manager.h" #include "tink/jwt/internal/jwt_rsa_ssa_pss_verify_key_manager.h" #include "tink/registry.h" #include "tink/util/status.h" #include "proto/config.pb.h" namespace crypto { namespace tink { // static util::Status JwtSignatureRegister() { // Register primitive wrappers. auto status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) return status; status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) return status; // Register key managers which utilize FIPS validated BoringCrypto // implementations. // ECDSA status = Registry::RegisterAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), true); if (!status.ok()) return status; // RSA SSA PKCS1 status = Registry::RegisterAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), true); if (!status.ok()) return status; // RSA SSA PSS status = Registry::RegisterAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), true); if (!status.ok()) return status; if (IsFipsModeEnabled()) { return util::OkStatus(); } // There are currently no non-FIPS key managers. return util::OkStatus(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/jwt_signature_config.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_JWT_SIGNATURE_CONFIG_H_ #define TINK_JWT_JWT_SIGNATURE_CONFIG_H_ #include "absl/base/macros.h" #include "tink/util/status.h" #include "proto/config.pb.h" namespace crypto { namespace tink { // Registers JwtPublicKeySign and JwtPublicKeyVerify primitive wrapper and key // managers for all JwtPublicKeySign and JwtPublicKeyVerify key types from the // current Tink release. crypto::tink::util::Status JwtSignatureRegister(); } // namespace tink } // namespace crypto #endif // TINK_JWT_JWT_SIGNATURE_CONFIG_H_ ================================================ FILE: cc/jwt/jwt_signature_config_test.cc ================================================ // Copyright 2023 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/jwt_signature_config.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/config/global_registry.h" #include "tink/internal/fips_utils.h" #include "tink/jwt/jwt_key_templates.h" #include "tink/keyset_handle.h" #include "tink/registry.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::testing::Not; class JwtSignatureConfigTest : public ::testing::Test { protected: void SetUp() override { Registry::Reset(); } }; TEST_F(JwtSignatureConfigTest, FailIfAndOnlyIfInInvalidFipsState) { // If FIPS is enabled, then we need FIPS also to be enabled in BoringSSL. // Otherwise we are in an invalid state and must fail. bool invalid_fips_state = internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl(); if (invalid_fips_state) { EXPECT_THAT(JwtSignatureRegister(), Not(IsOk())); EXPECT_THAT(KeysetHandle::GenerateNew(JwtEs256Template(), KeyGenConfigGlobalRegistry()) .status(), Not(IsOk())); EXPECT_THAT(KeysetHandle::GenerateNew(JwtRs256_2048_F4_Template(), KeyGenConfigGlobalRegistry()) .status(), Not(IsOk())); EXPECT_THAT(KeysetHandle::GenerateNew(JwtPs256_2048_F4_Template(), KeyGenConfigGlobalRegistry()) .status(), Not(IsOk())); } else { EXPECT_THAT(JwtSignatureRegister(), IsOk()); EXPECT_THAT(KeysetHandle::GenerateNew(JwtEs256Template(), KeyGenConfigGlobalRegistry()) .status(), IsOk()); EXPECT_THAT(KeysetHandle::GenerateNew(JwtRs256_2048_F4_Template(), KeyGenConfigGlobalRegistry()) .status(), IsOk()); EXPECT_THAT(KeysetHandle::GenerateNew(JwtPs256_2048_F4_Template(), KeyGenConfigGlobalRegistry()) .status(), IsOk()); } } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/jwt_signature_parameters.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_JWT_SIGNATURE_PARAMETERS_H_ #define TINK_JWT_JWT_SIGNATURE_PARAMETERS_H_ #include "tink/parameters.h" namespace crypto { namespace tink { // Describes a JWT signature key pair without the randomly chosen key material. class JwtSignatureParameters : public Parameters { // Returns true if verification is allowed for tokens without a `kid` header. virtual bool AllowKidAbsent() const = 0; }; } // namespace tink } // namespace crypto #endif // TINK_JWT_JWT_SIGNATURE_PARAMETERS_H_ ================================================ FILE: cc/jwt/jwt_signature_private_key.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_JWT_SIGNATURE_PRIVATE_KEY_H_ #define TINK_JWT_JWT_SIGNATURE_PRIVATE_KEY_H_ #include #include "absl/types/optional.h" #include "tink/jwt/jwt_signature_parameters.h" #include "tink/jwt/jwt_signature_public_key.h" #include "tink/key.h" #include "tink/private_key.h" namespace crypto { namespace tink { // Represents the signing function for a JWT Signature primitive. class JwtSignaturePrivateKey : public PrivateKey { public: const JwtSignaturePublicKey& GetPublicKey() const override = 0; absl::optional GetKid() const { return GetPublicKey().GetKid(); } absl::optional GetIdRequirement() const override { return GetPublicKey().GetIdRequirement(); } const JwtSignatureParameters& GetParameters() const override { return GetPublicKey().GetParameters(); } bool operator==(const Key& other) const override = 0; }; } // namespace tink } // namespace crypto #endif // TINK_JWT_JWT_SIGNATURE_PRIVATE_KEY_H_ ================================================ FILE: cc/jwt/jwt_signature_public_key.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_JWT_SIGNATURE_PUBLIC_KEY_H_ #define TINK_JWT_JWT_SIGNATURE_PUBLIC_KEY_H_ #include #include "absl/types/optional.h" #include "tink/jwt/jwt_signature_parameters.h" #include "tink/key.h" namespace crypto { namespace tink { // Represents the verification function for a JWT Signature primitive. class JwtSignaturePublicKey : public Key { public: // Returns the `kid` to be used for this key // (https://www.rfc-editor.org/rfc/rfc7517#section-4.5). // // Note that the `kid` is not necessarily related to Tink's key ID in the // keyset. // // If present, this `kid` will be written into the `kid` header during // `ComputeMacAndEncode()`. If absent, no `kid` will be written. // // If present, and the `kid` header is present, the contents of the // `kid` header need to match the return value of this function for // validation to succeed in `VerifyMacAndDecode()`. // // Note that `GetParameters().AllowKidAbsent()` specifies whether or not // omitting the `kid` header is allowed. Of course, if // `GetParameters().AllowKidAbsent()` returns false, then `GetKid()` must // return a non-empty value. virtual absl::optional GetKid() const = 0; const JwtSignatureParameters& GetParameters() const override = 0; bool operator==(const Key& other) const override = 0; }; } // namespace tink } // namespace crypto #endif // TINK_JWT_JWT_SIGNATURE_PUBLIC_KEY_H_ ================================================ FILE: cc/jwt/jwt_validator.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/jwt_validator.h" #include #include #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/time/clock.h" #include "absl/time/time.h" #include "tink/jwt/raw_jwt.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { static constexpr absl::Duration kJwtMaxClockSkew = absl::Minutes(10); } JwtValidator::JwtValidator(const JwtValidatorBuilder& builder) { expected_type_header_ = builder.expected_type_header_; expected_issuer_ = builder.expected_issuer_; expected_audience_ = builder.expected_audience_; ignore_type_header_ = builder.ignore_type_header_; ignore_issuer_ = builder.ignore_issuer_; ignore_audiences_ = builder.ignore_audiences_; allow_missing_expiration_ = builder.allow_missing_expiration_; expect_issued_in_the_past_ = builder.expect_issued_in_the_past_; clock_skew_ = builder.clock_skew_; fixed_now_ = builder.fixed_now_; } util::Status JwtValidator::ValidateTimestamps(RawJwt const& raw_jwt) const { absl::Time now; if (fixed_now_.has_value()) { now = fixed_now_.value(); } else { now = absl::Now(); } if (!raw_jwt.HasExpiration() && !allow_missing_expiration_) { return util::Status(absl::StatusCode::kInvalidArgument, "token does not have an expiration set"); } if (raw_jwt.HasExpiration()) { util::StatusOr expiration = raw_jwt.GetExpiration(); if (!expiration.ok()) { return expiration.status(); } if (*expiration <= now - clock_skew_) { return util::Status(absl::StatusCode::kInvalidArgument, "token has expired"); } } if (raw_jwt.HasNotBefore()) { util::StatusOr not_before = raw_jwt.GetNotBefore(); if (!not_before.ok()) { return not_before.status(); } if (*not_before > now + clock_skew_) { return util::Status(absl::StatusCode::kInvalidArgument, "token cannot yet be used"); } } if (expect_issued_in_the_past_) { util::StatusOr issued_at = raw_jwt.GetIssuedAt(); if (!issued_at.ok()) { return issued_at.status(); } if (*issued_at > now + clock_skew_) { return util::Status(absl::StatusCode::kInvalidArgument, "token has an invalid iat claim in the future"); } } return util::OkStatus(); } util::Status JwtValidator::ValidateTypeHeader(RawJwt const& raw_jwt) const { if (expected_type_header_.has_value()) { if (!raw_jwt.HasTypeHeader()) { return util::Status(absl::StatusCode::kInvalidArgument, "missing expected type header"); } util::StatusOr type_header = raw_jwt.GetTypeHeader(); if (!type_header.ok()) { return type_header.status(); } if (expected_type_header_.value() != *type_header) { return util::Status(absl::StatusCode::kInvalidArgument, "wrong type header"); } } else { if (raw_jwt.HasTypeHeader() && !ignore_type_header_) { return util::Status( absl::StatusCode::kInvalidArgument, "invalid JWT; token has type header set, but validator not"); } } return util::OkStatus(); } util::Status JwtValidator::ValidateIssuer(RawJwt const& raw_jwt) const { if (expected_issuer_.has_value()){ if (!raw_jwt.HasIssuer()) { return util::Status(absl::StatusCode::kInvalidArgument, "missing expected issuer"); } util::StatusOr issuer = raw_jwt.GetIssuer(); if (!issuer.ok()) { return issuer.status(); } if (expected_issuer_.value() != *issuer) { return util::Status(absl::StatusCode::kInvalidArgument, "wrong issuer"); } } else { if (raw_jwt.HasIssuer() && !ignore_issuer_) { return util::Status( absl::StatusCode::kInvalidArgument, "invalid JWT; token has issuer set, but validator not"); } } return util::OkStatus(); } util::Status JwtValidator::ValidateAudiences(RawJwt const& raw_jwt) const { if (expected_audience_.has_value()) { if (!raw_jwt.HasAudiences()) { return util::Status(absl::StatusCode::kInvalidArgument, "missing expected audiences"); } util::StatusOr> audiences = raw_jwt.GetAudiences(); if (!audiences.ok()) { return audiences.status(); } auto it = std::find(audiences->begin(), audiences->end(), expected_audience_); if (it == audiences->end()) { return util::Status(absl::StatusCode::kInvalidArgument, "audience not found"); } } else { if (raw_jwt.HasAudiences() && !ignore_audiences_) { return util::Status( absl::StatusCode::kInvalidArgument, "invalid JWT; token has audience set, but validator not"); } } return util::OkStatus(); } util::Status JwtValidator::Validate(RawJwt const& raw_jwt) const { util::Status status; status = ValidateTimestamps(raw_jwt); if (!status.ok()) { return status; } status = ValidateTypeHeader(raw_jwt); if (!status.ok()) { return status; } status = ValidateIssuer(raw_jwt); if (!status.ok()) { return status; } status = ValidateAudiences(raw_jwt); if (!status.ok()) { return status; } return util::OkStatus(); } JwtValidatorBuilder::JwtValidatorBuilder() { ignore_type_header_ = false; ignore_issuer_ = false; ignore_audiences_ = false; allow_missing_expiration_ = false; expect_issued_in_the_past_ = false; clock_skew_ = absl::ZeroDuration(); } JwtValidatorBuilder& JwtValidatorBuilder::ExpectTypeHeader( absl::string_view type_header) { expected_type_header_ = std::string(type_header); return *this; } JwtValidatorBuilder& JwtValidatorBuilder::ExpectIssuer( absl::string_view issuer) { expected_issuer_ = std::string(issuer); return *this; } JwtValidatorBuilder& JwtValidatorBuilder::ExpectAudience( absl::string_view audience) { expected_audience_ = std::string(audience); return *this; } JwtValidatorBuilder& JwtValidatorBuilder::IgnoreTypeHeader() { ignore_type_header_ = true; return *this; } JwtValidatorBuilder& JwtValidatorBuilder::IgnoreIssuer() { ignore_issuer_ = true; return *this; } JwtValidatorBuilder& JwtValidatorBuilder::IgnoreAudiences() { ignore_audiences_ = true; return *this; } JwtValidatorBuilder& JwtValidatorBuilder::AllowMissingExpiration() { allow_missing_expiration_ = true; return *this; } JwtValidatorBuilder& JwtValidatorBuilder::ExpectIssuedInThePast() { expect_issued_in_the_past_ = true; return *this; } JwtValidatorBuilder& JwtValidatorBuilder::SetClockSkew( absl::Duration clock_skew) { clock_skew_ = clock_skew; return *this; } JwtValidatorBuilder& JwtValidatorBuilder::SetFixedNow(absl::Time fixed_now) { fixed_now_ = fixed_now; return *this; } util::StatusOr JwtValidatorBuilder::Build() { if (expected_type_header_.has_value() && ignore_type_header_) { return util::Status( absl::StatusCode::kInvalidArgument, "IgnoreTypeHeader() and ExpectTypeHeader() cannot be used together"); } if (expected_issuer_.has_value() && ignore_issuer_) { return util::Status( absl::StatusCode::kInvalidArgument, "IgnoreIssuer() and ExpectedIssuer() cannot be used together"); } if (expected_audience_.has_value() && ignore_audiences_) { return util::Status( absl::StatusCode::kInvalidArgument, "IgnoreAudiences() and ExpectAudience() cannot be used together"); } if (clock_skew_ > kJwtMaxClockSkew) { return util::Status(absl::StatusCode::kInvalidArgument, "clock skew too large, max is 10 minutes"); } JwtValidator validator(*this); return validator; } } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/jwt_validator.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_JWT_VALIDATOR_H_ #define TINK_JWT_JWT_VALIDATOR_H_ #include #include "absl/strings/string_view.h" #include "absl/time/clock.h" #include "absl/time/time.h" #include "absl/types/optional.h" #include "tink/jwt/raw_jwt.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // A JwtValidator defines how JSON Web Tokens (JWTs) should be validated. // class JwtValidatorBuilder; class JwtValidator { public: // JwtValidator objects are copiable and movable. JwtValidator(const JwtValidator&) = default; JwtValidator& operator=(const JwtValidator&) = default; JwtValidator(JwtValidator&& other) = default; JwtValidator& operator=(JwtValidator&& other) = default; util::Status Validate(crypto::tink::RawJwt const& raw_jwt) const; private: util::Status ValidateTimestamps(crypto::tink::RawJwt const& raw_jwt) const; util::Status ValidateTypeHeader(crypto::tink::RawJwt const& raw_jwt) const; util::Status ValidateIssuer(crypto::tink::RawJwt const& raw_jwt) const; util::Status ValidateAudiences(crypto::tink::RawJwt const& raw_jwt) const; explicit JwtValidator(const JwtValidatorBuilder& builder); friend class JwtValidatorBuilder; absl::optional expected_type_header_; absl::optional expected_issuer_; absl::optional expected_audience_; bool ignore_type_header_; bool ignore_issuer_; bool ignore_audiences_; bool allow_missing_expiration_; bool expect_issued_in_the_past_; absl::Duration clock_skew_; absl::optional fixed_now_; }; class JwtValidatorBuilder { public: JwtValidatorBuilder(); // JwtValidatorBuilder objects are copiable and movable. JwtValidatorBuilder(const JwtValidatorBuilder&) = default; JwtValidatorBuilder& operator=(const JwtValidatorBuilder&) = default; JwtValidatorBuilder(JwtValidatorBuilder&& other) = default; JwtValidatorBuilder& operator=(JwtValidatorBuilder&& other) = default; JwtValidatorBuilder& ExpectTypeHeader(absl::string_view expected_type_header); JwtValidatorBuilder& ExpectIssuer(absl::string_view expected_issuer); JwtValidatorBuilder& ExpectAudience(absl::string_view expected_audience); JwtValidatorBuilder& IgnoreTypeHeader(); JwtValidatorBuilder& IgnoreIssuer(); JwtValidatorBuilder& IgnoreAudiences(); JwtValidatorBuilder& AllowMissingExpiration(); JwtValidatorBuilder& ExpectIssuedInThePast(); JwtValidatorBuilder& SetClockSkew(absl::Duration clock_skew); JwtValidatorBuilder& SetFixedNow(absl::Time fixed_now); util::StatusOr Build(); private: friend class JwtValidator; absl::optional expected_type_header_; absl::optional expected_issuer_; absl::optional expected_audience_; bool ignore_type_header_; bool ignore_issuer_; bool ignore_audiences_; bool allow_missing_expiration_; bool expect_issued_in_the_past_; absl::Duration clock_skew_; absl::optional fixed_now_; }; } // namespace tink } // namespace crypto #endif // TINK_JWT_JWT_VALIDATOR_H_ ================================================ FILE: cc/jwt/jwt_validator_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/jwt_validator.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/escaping.h" #include "absl/time/clock.h" #include "absl/time/time.h" #include "tink/jwt/raw_jwt.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" using ::crypto::tink::test::IsOk; namespace crypto { namespace tink { TEST(JwtValidator, ExpiredTokenNotOK) { absl::Time now = absl::Now(); util::StatusOr jwt = RawJwtBuilder().SetExpiration(now - absl::Seconds(100)).Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder().Build(); ASSERT_THAT(validator, IsOk()); EXPECT_FALSE(validator->Validate(*jwt).ok()); } TEST(JwtValidator, NotExpiredTokenOK) { absl::Time now = absl::Now(); util::StatusOr jwt = RawJwtBuilder().SetExpiration(now + absl::Seconds(100)).Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder().Build(); ASSERT_THAT(validator, IsOk()); EXPECT_THAT(validator->Validate(*jwt), IsOk()); } TEST(JwtValidator, TokenWithExpEqualToNowIsExpired) { absl::Time now = absl::FromUnixSeconds(12345); util::StatusOr jwt = RawJwtBuilder().SetExpiration(now).Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder().SetFixedNow(now).Build(); ASSERT_THAT(validator, IsOk()); EXPECT_FALSE(validator->Validate(*jwt).ok()); } TEST(JwtValidator, ClockSkewIsToLarge) { EXPECT_FALSE( JwtValidatorBuilder().SetClockSkew(absl::Minutes(11)).Build().ok()); } TEST(JwtValidator, RecentlyExpiredTokenWithClockSkewOK) { absl::Time now = absl::Now(); util::StatusOr jwt = RawJwtBuilder().SetExpiration(now - absl::Seconds(100)).Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder().SetClockSkew(absl::Seconds(200)).Build(); ASSERT_THAT(validator, IsOk()); EXPECT_THAT(validator->Validate(*jwt), IsOk()); } TEST(JwtValidator, NotBeforeInTheFutureNotOK) { absl::Time now = absl::Now(); util::StatusOr jwt = RawJwtBuilder() .SetNotBefore(now + absl::Seconds(100)) .WithoutExpiration() .Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder().AllowMissingExpiration().Build(); ASSERT_THAT(validator, IsOk()); EXPECT_FALSE(validator->Validate(*jwt).ok()); } TEST(JwtValidator, NotBeforeInThePastOK) { absl::Time now = absl::Now(); util::StatusOr jwt = RawJwtBuilder() .SetNotBefore(now - absl::Seconds(100)) .WithoutExpiration() .Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder().AllowMissingExpiration().Build(); ASSERT_THAT(validator, IsOk()); EXPECT_THAT(validator->Validate(*jwt), IsOk()); } TEST(JwtValidator, TokenWithNotBeforeEqualToNowIsValid) { absl::Time now = absl::FromUnixSeconds(12345); util::StatusOr jwt = RawJwtBuilder().SetNotBefore(now).WithoutExpiration().Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder().SetFixedNow(now).AllowMissingExpiration().Build(); ASSERT_THAT(validator, IsOk()); EXPECT_THAT(validator->Validate(*jwt), IsOk()); } TEST(JwtValidator, NotBeforeInTheNearFutureWithClockSkewOK) { absl::Time now = absl::Now(); util::StatusOr jwt = RawJwtBuilder() .SetNotBefore(now + absl::Seconds(100)) .WithoutExpiration() .Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .AllowMissingExpiration() .SetClockSkew(absl::Seconds(200)) .Build(); ASSERT_THAT(validator, IsOk()); EXPECT_THAT(validator->Validate(*jwt), IsOk()); } TEST(JwtValidator, IssuedAt) { absl::Time now = absl::Now(); util::StatusOr tokenIssuedInTheFuture = RawJwtBuilder() .SetIssuedAt(now + absl::Seconds(100)) .WithoutExpiration() .Build(); ASSERT_THAT(tokenIssuedInTheFuture, IsOk()); util::StatusOr tokenIssuedInThePast = RawJwtBuilder() .SetIssuedAt(now - absl::Seconds(100)) .WithoutExpiration() .Build(); ASSERT_THAT(tokenIssuedInThePast, IsOk()); util::StatusOr tokenWithoutIssuedAt = RawJwtBuilder() .WithoutExpiration() .Build(); ASSERT_THAT(tokenWithoutIssuedAt, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); EXPECT_THAT(validator->Validate(*tokenIssuedInTheFuture), IsOk()); EXPECT_THAT(validator->Validate(*tokenIssuedInThePast), IsOk()); EXPECT_THAT(validator->Validate(*tokenWithoutIssuedAt), IsOk()); util::StatusOr issued_at_validator = JwtValidatorBuilder() .ExpectIssuedInThePast() .AllowMissingExpiration() .Build(); ASSERT_THAT(issued_at_validator, IsOk()); EXPECT_FALSE(issued_at_validator->Validate(*tokenIssuedInTheFuture).ok()); EXPECT_THAT(issued_at_validator->Validate(*tokenIssuedInThePast), IsOk()); EXPECT_FALSE(issued_at_validator->Validate(*tokenWithoutIssuedAt).ok()); } TEST(JwtValidator, IssuedAtWithClockSkew) { absl::Time now = absl::Now(); util::StatusOr tokenOneMinuteInTheFuture = RawJwtBuilder() .SetIssuedAt(now + absl::Minutes(1)) .WithoutExpiration() .Build(); ASSERT_THAT(tokenOneMinuteInTheFuture, IsOk()); util::StatusOr validator_without_clock_skew = JwtValidatorBuilder() .ExpectIssuedInThePast() .AllowMissingExpiration() .Build(); ASSERT_THAT(validator_without_clock_skew, IsOk()); EXPECT_FALSE( validator_without_clock_skew->Validate(*tokenOneMinuteInTheFuture).ok()); util::StatusOr validator_with_clock_skew = JwtValidatorBuilder() .ExpectIssuedInThePast() .AllowMissingExpiration() .SetClockSkew(absl::Minutes(2)) .Build(); ASSERT_THAT(validator_with_clock_skew, IsOk()); EXPECT_THAT(validator_with_clock_skew->Validate(*tokenOneMinuteInTheFuture), IsOk()); } TEST(JwtValidator, RequiresTypeHeaderButNotTypHeaderNotOK) { util::StatusOr jwt = RawJwtBuilder().WithoutExpiration().Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder().ExpectTypeHeader("typeHeader").Build(); ASSERT_THAT(validator, IsOk()); EXPECT_FALSE(validator->Validate(*jwt).ok()); } TEST(JwtValidator, InvalidTypeHeaderNotOK) { util::StatusOr jwt = RawJwtBuilder().SetTypeHeader("unknown").WithoutExpiration().Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .ExpectTypeHeader("JWT") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); EXPECT_FALSE(validator->Validate(*jwt).ok()); } TEST(JwtValidator, CorrectTypeHeaderOK) { util::StatusOr jwt = RawJwtBuilder().SetTypeHeader("typeHeader").WithoutExpiration().Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .ExpectTypeHeader("typeHeader") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); EXPECT_THAT(validator->Validate(*jwt), IsOk()); } TEST(JwtValidator, TypeHeaderInTokenButNotInValiatorNotOK) { util::StatusOr jwt = RawJwtBuilder().SetTypeHeader("typeHeader").WithoutExpiration().Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder().AllowMissingExpiration().Build(); ASSERT_THAT(validator, IsOk()); EXPECT_FALSE(validator->Validate(*jwt).ok()); } TEST(JwtValidator, IgnoreTypeHeaderOK) { util::StatusOr jwt = RawJwtBuilder().SetTypeHeader("typeHeader").WithoutExpiration().Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder().IgnoreTypeHeader().AllowMissingExpiration().Build(); ASSERT_THAT(validator, IsOk()); EXPECT_THAT(validator->Validate(*jwt), IsOk()); } TEST(JwtValidator, RequiresIssuerButNotIssuerNotOK) { util::StatusOr jwt = RawJwtBuilder().WithoutExpiration().Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .ExpectIssuer("issuer") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); EXPECT_FALSE(validator->Validate(*jwt).ok()); } TEST(JwtValidator, InvalidIssuerNotOK) { util::StatusOr jwt = RawJwtBuilder().SetIssuer("unknown").WithoutExpiration().Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .ExpectIssuer("issuer") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); EXPECT_FALSE(validator->Validate(*jwt).ok()); } TEST(JwtValidator, CorrectIssuerOK) { util::StatusOr jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .ExpectIssuer("issuer") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); EXPECT_THAT(validator->Validate(*jwt), IsOk()); } TEST(JwtValidator, IssuerInTokenButNotInValiatorNotOK) { util::StatusOr jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder().AllowMissingExpiration().Build(); ASSERT_THAT(validator, IsOk()); EXPECT_FALSE(validator->Validate(*jwt).ok()); } TEST(JwtValidator, IgnoreIssuerOK) { util::StatusOr jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder().IgnoreIssuer().AllowMissingExpiration().Build(); ASSERT_THAT(validator, IsOk()); EXPECT_THAT(validator->Validate(*jwt), IsOk()); } TEST(JwtValidator, RequiresAudienceButNotAudienceNotOK) { util::StatusOr jwt = RawJwtBuilder().WithoutExpiration().Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .ExpectAudience("audience") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); EXPECT_FALSE(validator->Validate(*jwt).ok()); } TEST(JwtValidator, InvalidAudienceNotOK) { util::StatusOr jwt = RawJwtBuilder().SetSubject("unknown").WithoutExpiration().Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .ExpectAudience("audience") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); EXPECT_FALSE(validator->Validate(*jwt).ok()); } TEST(JwtValidator, CorrectAudienceOK) { util::StatusOr jwt = RawJwtBuilder() .AddAudience("otherAudience") .AddAudience("audience") .WithoutExpiration() .Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .ExpectAudience("audience") .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); EXPECT_THAT(validator->Validate(*jwt), IsOk()); } TEST(JwtValidator, AudienceInTokenButNotInValiatorNotOK) { util::StatusOr jwt = RawJwtBuilder().AddAudience("audience").WithoutExpiration().Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder().AllowMissingExpiration().Build(); ASSERT_THAT(validator, IsOk()); EXPECT_FALSE(validator->Validate(*jwt).ok()); } TEST(JwtValidator, NoAudienceOK) { util::StatusOr jwt = RawJwtBuilder().WithoutExpiration().Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder().AllowMissingExpiration().Build(); ASSERT_THAT(validator, IsOk()); EXPECT_THAT(validator->Validate(*jwt), IsOk()); } TEST(JwtValidator, IgnoreAudiencesOK) { util::StatusOr jwt = RawJwtBuilder().AddAudience("audience").WithoutExpiration().Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder().IgnoreAudiences().AllowMissingExpiration().Build(); ASSERT_THAT(validator, IsOk()); EXPECT_THAT(validator->Validate(*jwt), IsOk()); } TEST(JwtValidator, FixedNowExpiredNotOk) { absl::Time now = absl::Now(); util::StatusOr jwt = RawJwtBuilder().SetExpiration(now + absl::Seconds(100)).Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .SetFixedNow(now + absl::Seconds(200)) .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); EXPECT_FALSE(validator->Validate(*jwt).ok()); } TEST(JwtValidator, FixedNowNotYetValidNotOk) { absl::Time now = absl::Now(); util::StatusOr jwt = RawJwtBuilder() .SetNotBefore(now - absl::Seconds(100)) .WithoutExpiration() .Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder() .SetFixedNow(now - absl::Seconds(200)) .AllowMissingExpiration() .Build(); ASSERT_THAT(validator, IsOk()); EXPECT_FALSE(validator->Validate(*jwt).ok()); } TEST(JwtValidator, FixedNowValidOk) { absl::Time now = absl::FromUnixSeconds(12345); util::StatusOr jwt = RawJwtBuilder() .SetExpiration(now + absl::Seconds(100)) .SetNotBefore(now - absl::Seconds(100)) .Build(); ASSERT_THAT(jwt, IsOk()); util::StatusOr validator = JwtValidatorBuilder().SetFixedNow(now).Build(); ASSERT_THAT(validator, IsOk()); EXPECT_THAT(validator->Validate(*jwt), IsOk()); } TEST(JwtValidator, CallBuildTwiceOk) { JwtValidatorBuilder builder = JwtValidatorBuilder().AllowMissingExpiration(); builder.ExpectIssuer("issuer1"); util::StatusOr validator1 = builder.Build(); ASSERT_THAT(validator1, IsOk()); builder.ExpectIssuer("issuer2"); util::StatusOr validator2 = builder.Build(); ASSERT_THAT(validator2, IsOk()); util::StatusOr jwt1 = RawJwtBuilder().SetIssuer("issuer1").WithoutExpiration().Build(); ASSERT_THAT(jwt1, IsOk()); util::StatusOr jwt2 = RawJwtBuilder().SetIssuer("issuer2").WithoutExpiration().Build(); ASSERT_THAT(jwt2, IsOk()); EXPECT_THAT(validator1->Validate(*jwt1), IsOk()); EXPECT_FALSE(validator1->Validate(*jwt2).ok()); EXPECT_THAT(validator2->Validate(*jwt2), IsOk()); EXPECT_FALSE(validator2->Validate(*jwt1).ok()); } TEST(JwtValidator, InvalidValidators) { EXPECT_FALSE(JwtValidatorBuilder() .ExpectTypeHeader("a") .IgnoreTypeHeader() .AllowMissingExpiration() .Build() .ok()); EXPECT_FALSE(JwtValidatorBuilder() .ExpectIssuer("a") .IgnoreIssuer() .AllowMissingExpiration() .Build() .ok()); EXPECT_FALSE(JwtValidatorBuilder() .ExpectAudience("a") .IgnoreAudiences() .AllowMissingExpiration() .Build() .ok()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/raw_jwt.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/raw_jwt.h" #include #include #include #include #include "absl/status/status.h" #include "absl/strings/numbers.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "absl/strings/substitute.h" #include "absl/time/time.h" #include "absl/types/optional.h" #include "tink/jwt/internal/json_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { using ::google::protobuf::Struct; using ::google::protobuf::Value; // Registered claim names, as defined in // https://tools.ietf.org/html/rfc7519#section-4.1. constexpr absl::string_view kJwtClaimIssuer = "iss"; constexpr absl::string_view kJwtClaimSubject = "sub"; constexpr absl::string_view kJwtClaimAudience = "aud"; constexpr absl::string_view kJwtClaimExpiration = "exp"; constexpr absl::string_view kJwtClaimNotBefore = "nbf"; constexpr absl::string_view kJwtClaimIssuedAt = "iat"; constexpr absl::string_view kJwtClaimJwtId = "jti"; constexpr int64_t kJwtTimestampMax = 253402300799; // 31 Dec 9999, 23:59:59 GMT bool IsRegisteredClaimName(absl::string_view name) { return name == kJwtClaimIssuer || name == kJwtClaimSubject || name == kJwtClaimAudience || name == kJwtClaimExpiration || name == kJwtClaimNotBefore || name == kJwtClaimIssuedAt || name == kJwtClaimJwtId; } util::Status ValidatePayloadName(absl::string_view name) { if (IsRegisteredClaimName(name)) { return absl::InvalidArgumentError(absl::Substitute( "claim '$0' is invalid because it's a registered name; " "use the corresponding getter or setter method.", name)); } return util::OkStatus(); } bool HasClaimOfKind(const google::protobuf::Struct& json_proto, absl::string_view name, Value::KindCase kind) { if (IsRegisteredClaimName(name)) { return false; } const auto& fields = json_proto.fields(); auto it = fields.find(std::string(name)); if (it == fields.end()) { return false; } const Value& value = it->second; return value.kind_case() == kind; } // Returns true if the claim is present but not a string. bool ClaimIsNotAString(const google::protobuf::Struct& json_proto, absl::string_view name) { const auto& fields = json_proto.fields(); auto it = fields.find(std::string(name)); if (it == fields.end()) { return false; } const Value& value = it->second; return value.kind_case() != Value::kStringValue; } // Returns true if the claim is present but not a list. bool ClaimIsNotAList(google::protobuf::Struct& json_proto, absl::string_view name) { const auto& fields = json_proto.fields(); auto it = fields.find(std::string(name)); if (it == fields.end()) { return false; } const Value& value = it->second; return value.kind_case() != Value::kListValue; } // Returns true if the claim is present but not a timestamp. bool ClaimIsNotATimestamp(const google::protobuf::Struct& json_proto, absl::string_view name) { const auto& fields = json_proto.fields(); auto it = fields.find(std::string(name)); if (it == fields.end()) { return false; } const Value& value = it->second; if (value.kind_case() != Value::kNumberValue) { return true; } double timestamp = value.number_value(); return (timestamp > kJwtTimestampMax) || (timestamp < 0); } int64_t TimeToTimestamp(absl::Time time) { // We round the timestamp to a whole number. We always round down. return absl::ToUnixSeconds(time); } absl::Time TimestampToTime(double timestamp) { if (timestamp > kJwtTimestampMax) { return absl::FromUnixSeconds(kJwtTimestampMax); } return absl::FromUnixSeconds(timestamp); } util::Status ValidateAudienceClaim(const google::protobuf::Struct& json_proto) { const auto& fields = json_proto.fields(); auto it = fields.find(std::string(kJwtClaimAudience)); if (it == fields.end()) { return util::OkStatus(); } const Value& value = it->second; if (value.kind_case() == Value::kStringValue) { return util::OkStatus(); } if (value.kind_case() != Value::kListValue) { return util::Status(absl::StatusCode::kInvalidArgument, "aud claim is not a list"); } if (value.list_value().values_size() < 1) { return util::Status(absl::StatusCode::kInvalidArgument, "aud claim is present but empty"); } for (const Value& v : value.list_value().values()) { if (v.kind_case() != Value::kStringValue) { return util::Status(absl::StatusCode::kInvalidArgument, "aud claim is not a list of strings"); } } return util::OkStatus(); } } // namespace util::StatusOr RawJwt::FromJson(absl::optional type_header, absl::string_view json_payload) { util::StatusOr proto = jwt_internal::JsonStringToProtoStruct(json_payload); if (!proto.ok()) { return proto.status(); } if (ClaimIsNotAString(*proto, kJwtClaimIssuer) || ClaimIsNotAString(*proto, kJwtClaimSubject) || ClaimIsNotATimestamp(*proto, kJwtClaimExpiration) || ClaimIsNotATimestamp(*proto, kJwtClaimNotBefore) || ClaimIsNotATimestamp(*proto, kJwtClaimIssuedAt)) { return util::Status(absl::StatusCode::kInvalidArgument, "contains an invalid registered claim"); } util::Status aud_status = ValidateAudienceClaim(*proto); if (!aud_status.ok()) { return aud_status; } RawJwt token(type_header, *std::move(proto)); return token; } util::StatusOr RawJwt::GetJsonPayload() const { return jwt_internal::ProtoStructToJsonString(json_proto_); } RawJwt::RawJwt() = default; RawJwt::RawJwt(absl::optional type_header, google::protobuf::Struct json_proto) { type_header_ = type_header; json_proto_ = json_proto; } bool RawJwt::HasTypeHeader() const { return type_header_.has_value(); } util::StatusOr RawJwt::GetTypeHeader() const { if (!type_header_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "No type header found"); } return *type_header_; } bool RawJwt::HasIssuer() const { return json_proto_.fields().contains(std::string(kJwtClaimIssuer)); } util::StatusOr RawJwt::GetIssuer() const { const auto& fields = json_proto_.fields(); auto it = fields.find(std::string(kJwtClaimIssuer)); if (it == fields.end()) { return util::Status(absl::StatusCode::kInvalidArgument, "No Issuer found"); } const Value& value = it->second; if (value.kind_case() != Value::kStringValue) { return util::Status(absl::StatusCode::kInvalidArgument, "Issuer is not a string"); } return value.string_value(); } bool RawJwt::HasSubject() const { return json_proto_.fields().contains(std::string(kJwtClaimSubject)); } util::StatusOr RawJwt::GetSubject() const { const auto& fields = json_proto_.fields(); auto it = fields.find(std::string(kJwtClaimSubject)); if (it == fields.end()) { return util::Status(absl::StatusCode::kInvalidArgument, "No Subject found"); } const Value& value = it->second; if (value.kind_case() != Value::kStringValue) { return util::Status(absl::StatusCode::kInvalidArgument, "Subject is not a string"); } return value.string_value(); } bool RawJwt::HasAudiences() const { return json_proto_.fields().contains(std::string(kJwtClaimAudience)); } util::StatusOr> RawJwt::GetAudiences() const { const auto& fields = json_proto_.fields(); auto it = fields.find(std::string(kJwtClaimAudience)); if (it == fields.end()) { return util::Status(absl::StatusCode::kNotFound, "No Audiences found"); } Value list = it->second; if (list.kind_case() != Value::kListValue) { std::vector audiences; audiences.push_back(list.string_value()); return audiences; } if (list.kind_case() != Value::kListValue) { return util::Status(absl::StatusCode::kInvalidArgument, "Audiences is not a list"); } std::vector audiences; for (const auto& value : list.list_value().values()) { if (value.kind_case() != Value::kStringValue) { return util::Status(absl::StatusCode::kInvalidArgument, "Audiences is not a list of strings"); } audiences.push_back(value.string_value()); } return audiences; } bool RawJwt::HasJwtId() const { return json_proto_.fields().contains(std::string(kJwtClaimJwtId)); } util::StatusOr RawJwt::GetJwtId() const { const auto& fields = json_proto_.fields(); auto it = fields.find(std::string(kJwtClaimJwtId)); if (it == fields.end()) { return util::Status(absl::StatusCode::kNotFound, "No JwtId found"); } const Value& value = it->second; if (value.kind_case() != Value::kStringValue) { return util::Status(absl::StatusCode::kInvalidArgument, "JwtId is not a string"); } return value.string_value(); } bool RawJwt::HasExpiration() const { return json_proto_.fields().contains(std::string(kJwtClaimExpiration)); } util::StatusOr RawJwt::GetExpiration() const { const auto& fields = json_proto_.fields(); auto it = fields.find(std::string(kJwtClaimExpiration)); if (it == fields.end()) { return util::Status(absl::StatusCode::kNotFound, "No Expiration found"); } const Value& value = it->second; if (value.kind_case() != Value::kNumberValue) { return util::Status(absl::StatusCode::kInvalidArgument, "Expiration is not a number"); } return TimestampToTime(value.number_value()); } bool RawJwt::HasNotBefore() const { return json_proto_.fields().contains(std::string(kJwtClaimNotBefore)); } util::StatusOr RawJwt::GetNotBefore() const { const auto& fields = json_proto_.fields(); auto it = fields.find(std::string(kJwtClaimNotBefore)); if (it == fields.end()) { return util::Status(absl::StatusCode::kNotFound, "No NotBefore found"); } const Value& value = it->second; if (value.kind_case() != Value::kNumberValue) { return util::Status(absl::StatusCode::kInvalidArgument, "NotBefore is not a number"); } return TimestampToTime(value.number_value()); } bool RawJwt::HasIssuedAt() const { return json_proto_.fields().contains(std::string(kJwtClaimIssuedAt)); } util::StatusOr RawJwt::GetIssuedAt() const { const auto& fields = json_proto_.fields(); auto it = fields.find(std::string(kJwtClaimIssuedAt)); if (it == fields.end()) { return util::Status(absl::StatusCode::kNotFound, "No IssuedAt found"); } const Value& value = it->second; if (value.kind_case() != Value::kNumberValue) { return util::Status(absl::StatusCode::kInvalidArgument, "IssuedAt is not a number"); } return TimestampToTime(value.number_value()); } bool RawJwt::IsNullClaim(absl::string_view name) const { return HasClaimOfKind(json_proto_, name, Value::kNullValue); } bool RawJwt::HasBooleanClaim(absl::string_view name) const { return HasClaimOfKind(json_proto_, name, Value::kBoolValue); } util::StatusOr RawJwt::GetBooleanClaim( absl::string_view name) const { util::Status status = ValidatePayloadName(name); if (!status.ok()) { return status; } const auto& fields = json_proto_.fields(); auto it = fields.find(std::string(name)); if (it == fields.end()) { return util::Status(absl::StatusCode::kNotFound, absl::Substitute("claim '$0' not found", name)); } const Value& value = it->second; if (value.kind_case() != Value::kBoolValue) { return util::Status(absl::StatusCode::kInvalidArgument, absl::Substitute("claim '$0' is not a bool", name)); } return value.bool_value(); } bool RawJwt::HasStringClaim(absl::string_view name) const { return HasClaimOfKind(json_proto_, name, Value::kStringValue); } util::StatusOr RawJwt::GetStringClaim( absl::string_view name) const { util::Status status = ValidatePayloadName(name); if (!status.ok()) { return status; } const auto& fields = json_proto_.fields(); auto it = fields.find(std::string(name)); if (it == fields.end()) { return util::Status(absl::StatusCode::kNotFound, absl::Substitute("claim '$0' not found", name)); } const Value& value = it->second; if (value.kind_case() != Value::kStringValue) { return util::Status(absl::StatusCode::kInvalidArgument, absl::Substitute("claim '$0' is not a string", name)); } return value.string_value(); } bool RawJwt::HasNumberClaim(absl::string_view name) const { return HasClaimOfKind(json_proto_, name, Value::kNumberValue); } util::StatusOr RawJwt::GetNumberClaim(absl::string_view name) const { util::Status status = ValidatePayloadName(name); if (!status.ok()) { return status; } const auto& fields = json_proto_.fields(); auto it = fields.find(std::string(name)); if (it == fields.end()) { return util::Status(absl::StatusCode::kNotFound, absl::Substitute("claim '$0' not found", name)); } const Value& value = it->second; if (value.kind_case() != Value::kNumberValue) { return util::Status(absl::StatusCode::kInvalidArgument, absl::Substitute("claim '$0' is not a number", name)); } return value.number_value(); } bool RawJwt::HasJsonObjectClaim(absl::string_view name) const { return HasClaimOfKind(json_proto_, name, Value::kStructValue); } util::StatusOr RawJwt::GetJsonObjectClaim( absl::string_view name) const { util::Status status = ValidatePayloadName(name); if (!status.ok()) { return status; } const auto& fields = json_proto_.fields(); auto it = fields.find(std::string(name)); if (it == fields.end()) { return util::Status(absl::StatusCode::kNotFound, absl::Substitute("claim '$0' not found", name)); } const Value& value = it->second; if (value.kind_case() != Value::kStructValue) { return util::Status( absl::StatusCode::kInvalidArgument, absl::Substitute("claim '$0' is not a JSON object", name)); } return jwt_internal::ProtoStructToJsonString(value.struct_value()); } bool RawJwt::HasJsonArrayClaim(absl::string_view name) const { return HasClaimOfKind(json_proto_, name, Value::kListValue); } util::StatusOr RawJwt::GetJsonArrayClaim( absl::string_view name) const { util::Status status = ValidatePayloadName(name); if (!status.ok()) { return status; } const auto& fields = json_proto_.fields(); auto it = fields.find(std::string(name)); if (it == fields.end()) { return util::Status(absl::StatusCode::kNotFound, absl::Substitute("claim '$0' not found", name)); } const Value& value = it->second; if (value.kind_case() != Value::kListValue) { return util::Status( absl::StatusCode::kInvalidArgument, absl::Substitute("claim '$0' is not a JSON array", name)); } return jwt_internal::ProtoListToJsonString(value.list_value()); } std::vector RawJwt::CustomClaimNames() const { const auto& fields = json_proto_.fields(); std::vector values; for (auto it = fields.begin(); it != fields.end(); it++) { if (!IsRegisteredClaimName(it->first)) { values.push_back(it->first); } } return values; } RawJwtBuilder::RawJwtBuilder() { without_expiration_ = false; } RawJwtBuilder& RawJwtBuilder::SetTypeHeader(absl::string_view type_header) { type_header_ = std::string(type_header); return *this; } RawJwtBuilder& RawJwtBuilder::SetIssuer(absl::string_view issuer) { auto fields = json_proto_.mutable_fields(); Value value; value.set_string_value(std::string(issuer)); (*fields)[std::string(kJwtClaimIssuer)] = value; return *this; } RawJwtBuilder& RawJwtBuilder::SetSubject(absl::string_view subject) { auto fields = json_proto_.mutable_fields(); Value value; value.set_string_value(std::string(subject)); (*fields)[std::string(kJwtClaimSubject)] = value; return *this; } RawJwtBuilder& RawJwtBuilder::SetAudience(absl::string_view audience) { // Make sure that "aud" is not already a list by a call to SetAudiences or // AddAudience. if (ClaimIsNotAString(json_proto_, kJwtClaimAudience)) { error_ = util::Status(absl::StatusCode::kInvalidArgument, "SetAudience() must not be called together with " "SetAudiences() or AddAudience"); return *this; } auto fields = json_proto_.mutable_fields(); Value value; value.set_string_value(std::string(audience)); (*fields)[std::string(kJwtClaimAudience)] = value; return *this; } RawJwtBuilder& RawJwtBuilder::SetAudiences(std::vector audiences) { // Make sure that "aud" is not already a string by a call to SetAudience. if (ClaimIsNotAList(json_proto_, kJwtClaimAudience)) { error_ = util::Status( absl::StatusCode::kInvalidArgument, "SetAudiences() and SetAudience() must not be called together"); return *this; } auto fields = json_proto_.mutable_fields(); Value value; for (const auto& audience : audiences) { value.mutable_list_value()->add_values()->set_string_value(audience); } (*fields)[std::string(kJwtClaimAudience)] = value; return *this; } RawJwtBuilder& RawJwtBuilder::AddAudience(absl::string_view audience) { // Make sure that "aud" is not already a string by a call to SetAudience. if (ClaimIsNotAList(json_proto_, kJwtClaimAudience)) { error_ = util::Status( absl::StatusCode::kInvalidArgument, "AddAudience() and SetAudience() must not be called together"); return *this; } auto fields = json_proto_.mutable_fields(); auto insertion_result = fields->insert({std::string(kJwtClaimAudience), Value()}); google::protobuf::ListValue* list_value = insertion_result.first->second.mutable_list_value(); list_value->add_values()->set_string_value(std::string(audience)); return *this; } RawJwtBuilder& RawJwtBuilder::SetJwtId(absl::string_view jwid) { auto fields = json_proto_.mutable_fields(); Value value; value.set_string_value(std::string(jwid)); (*fields)[std::string(kJwtClaimJwtId)] = value; return *this; } RawJwtBuilder& RawJwtBuilder::WithoutExpiration() { without_expiration_ = true; return *this; } RawJwtBuilder& RawJwtBuilder::SetExpiration(absl::Time expiration) { int64_t exp_timestamp = TimeToTimestamp(expiration); if ((exp_timestamp > kJwtTimestampMax) || (exp_timestamp < 0)) { if (!error_.has_value()) { error_ = util::Status(absl::StatusCode::kInvalidArgument, "invalid expiration timestamp"); } return *this; } auto fields = json_proto_.mutable_fields(); Value value; value.set_number_value(exp_timestamp); (*fields)[std::string(kJwtClaimExpiration)] = value; return *this; } RawJwtBuilder& RawJwtBuilder::SetNotBefore(absl::Time not_before) { int64_t nbf_timestamp = TimeToTimestamp(not_before); if ((nbf_timestamp > kJwtTimestampMax) || (nbf_timestamp < 0)) { if (!error_.has_value()) { error_ = util::Status(absl::StatusCode::kInvalidArgument, "invalid not_before timestamp"); } return *this; } auto fields = json_proto_.mutable_fields(); Value value; value.set_number_value(nbf_timestamp); (*fields)[std::string(kJwtClaimNotBefore)] = value; return *this; } RawJwtBuilder& RawJwtBuilder::SetIssuedAt(absl::Time issued_at) { int64_t iat_timestamp = TimeToTimestamp(issued_at); if ((iat_timestamp > kJwtTimestampMax) || (iat_timestamp < 0)) { if (!error_.has_value()) { error_ = util::Status(absl::StatusCode::kInvalidArgument, "invalid issued_at timestamp"); } return *this; } auto fields = json_proto_.mutable_fields(); Value value; value.set_number_value(iat_timestamp); (*fields)[std::string(kJwtClaimIssuedAt)] = value; return *this; } RawJwtBuilder& RawJwtBuilder::AddNullClaim(absl::string_view name) { util::Status status = ValidatePayloadName(name); if (!status.ok()) { if (!error_.has_value()) { error_ = status; } return *this; } auto fields = json_proto_.mutable_fields(); Value value; value.set_null_value(google::protobuf::NULL_VALUE); (*fields)[std::string(name)] = value; return *this; } RawJwtBuilder& RawJwtBuilder::AddBooleanClaim(absl::string_view name, bool bool_value) { util::Status status = ValidatePayloadName(name); if (!status.ok()) { if (!error_.has_value()) { error_ = status; } return *this; } auto fields = json_proto_.mutable_fields(); Value value; value.set_bool_value(bool_value); (*fields)[std::string(name)] = value; return *this; } RawJwtBuilder& RawJwtBuilder::AddStringClaim(absl::string_view name, absl::string_view string_value) { util::Status status = ValidatePayloadName(name); if (!status.ok()) { if (!error_.has_value()) { error_ = status; } return *this; } auto fields = json_proto_.mutable_fields(); Value value; value.set_string_value(std::string(string_value)); (*fields)[std::string(name)] = value; return *this; } RawJwtBuilder& RawJwtBuilder::AddNumberClaim(absl::string_view name, double double_value) { util::Status status = ValidatePayloadName(name); if (!status.ok()) { if (!error_.has_value()) { error_ = status; } return *this; } auto fields = json_proto_.mutable_fields(); Value value; value.set_number_value(double_value); (*fields)[std::string(name)] = value; return *this; } RawJwtBuilder& RawJwtBuilder::AddJsonObjectClaim( absl::string_view name, absl::string_view object_value) { util::Status status = ValidatePayloadName(name); if (!status.ok()) { if (!error_.has_value()) { error_ = status; } return *this; } util::StatusOr proto = jwt_internal::JsonStringToProtoStruct(object_value); if (!proto.ok()) { if (!error_.has_value()) { error_ = proto.status(); } return *this; } auto fields = json_proto_.mutable_fields(); Value value; *value.mutable_struct_value() = *std::move(proto); (*fields)[std::string(name)] = value; return *this; } RawJwtBuilder& RawJwtBuilder::AddJsonArrayClaim(absl::string_view name, absl::string_view array_value) { util::Status status = ValidatePayloadName(name); if (!status.ok()) { if (!error_.has_value()) { error_ = status; } return *this; } util::StatusOr list = jwt_internal::JsonStringToProtoList(array_value); if (!list.ok()) { if (!error_.has_value()) { error_ = list.status(); } return *this; } auto fields = json_proto_.mutable_fields(); Value value; *value.mutable_list_value() = *list; (*fields)[std::string(name)] = value; return *this; } util::StatusOr RawJwtBuilder::Build() { if (error_.has_value()) { return *error_; } if (!json_proto_.fields().contains(std::string(kJwtClaimExpiration)) && !without_expiration_) { return util::Status( absl::StatusCode::kInvalidArgument, "neither SetExpiration() nor WithoutExpiration() was called"); } if (json_proto_.fields().contains(std::string(kJwtClaimExpiration)) && without_expiration_) { return util::Status( absl::StatusCode::kInvalidArgument, "SetExpiration() and WithoutExpiration() must not be called together"); } RawJwt token(type_header_, json_proto_); return token; } } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/raw_jwt.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_RAW_JWT_H_ #define TINK_JWT_RAW_JWT_H_ #include #include #include "google/protobuf/struct.pb.h" #include "absl/strings/string_view.h" #include "absl/time/clock.h" #include "absl/time/time.h" #include "absl/types/optional.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace jwt_internal { // For friend declaration class RawJwtParser; } // namespace jwt_internal /////////////////////////////////////////////////////////////////////////////// // An unsigned JSON Web Token (JWT), https://tools.ietf.org/html/rfc7519. // // It contains all payload claims and a subset of the headers. It does not // contain any headers that depend on the key, such as "alg" or "kid", because // these headers are chosen when the token is signed and encoded, and should not // be chosen by the user. This ensures that the key can be changed without any // changes to the user code. class RawJwt { public: RawJwt(); bool HasTypeHeader() const; util::StatusOr GetTypeHeader() const; bool HasIssuer() const; util::StatusOr GetIssuer() const; bool HasSubject() const; util::StatusOr GetSubject() const; bool HasAudiences() const; util::StatusOr> GetAudiences() const; bool HasJwtId() const; util::StatusOr GetJwtId() const; bool HasExpiration() const; util::StatusOr GetExpiration() const; bool HasNotBefore() const; util::StatusOr GetNotBefore() const; bool HasIssuedAt() const; util::StatusOr GetIssuedAt() const; bool IsNullClaim(absl::string_view name) const; bool HasBooleanClaim(absl::string_view name) const; util::StatusOr GetBooleanClaim(absl::string_view name) const; bool HasStringClaim(absl::string_view name) const; util::StatusOr GetStringClaim(absl::string_view name) const; bool HasNumberClaim(absl::string_view name) const; util::StatusOr GetNumberClaim(absl::string_view name) const; bool HasJsonObjectClaim(absl::string_view name) const; util::StatusOr GetJsonObjectClaim(absl::string_view name) const; bool HasJsonArrayClaim(absl::string_view name) const; util::StatusOr GetJsonArrayClaim(absl::string_view name) const; std::vector CustomClaimNames() const; util::StatusOr GetJsonPayload() const; // RawJwt objects are copiable and movable. RawJwt(const RawJwt&) = default; RawJwt& operator=(const RawJwt&) = default; RawJwt(RawJwt&& other) = default; RawJwt& operator=(RawJwt&& other) = default; private: static util::StatusOr FromJson( absl::optional type_header, absl::string_view json_payload); explicit RawJwt(absl::optional type_header, google::protobuf::Struct json_proto); friend class RawJwtBuilder; friend class jwt_internal::RawJwtParser; absl::optional type_header_; google::protobuf::Struct json_proto_; }; class RawJwtBuilder { public: RawJwtBuilder(); RawJwtBuilder& SetTypeHeader(absl::string_view type_header); RawJwtBuilder& SetIssuer(absl::string_view issuer); RawJwtBuilder& SetSubject(absl::string_view subject); RawJwtBuilder& SetAudience(absl::string_view audience); RawJwtBuilder& SetAudiences(std::vector audience); RawJwtBuilder& AddAudience(absl::string_view audience); RawJwtBuilder& SetJwtId(absl::string_view jwid); RawJwtBuilder& WithoutExpiration(); RawJwtBuilder& SetExpiration(absl::Time expiration); RawJwtBuilder& SetNotBefore(absl::Time not_before); RawJwtBuilder& SetIssuedAt(absl::Time issued_at); RawJwtBuilder& AddNullClaim(absl::string_view name); RawJwtBuilder& AddBooleanClaim(absl::string_view name, bool bool_value); RawJwtBuilder& AddStringClaim(absl::string_view name, absl::string_view string_value); RawJwtBuilder& AddNumberClaim(absl::string_view name, double double_value); RawJwtBuilder& AddJsonObjectClaim(absl::string_view name, absl::string_view object_value); RawJwtBuilder& AddJsonArrayClaim(absl::string_view name, absl::string_view array_value); util::StatusOr Build(); // RawJwtBuilder objects are copiable and movable. RawJwtBuilder(const RawJwtBuilder&) = default; RawJwtBuilder& operator=(const RawJwtBuilder&) = default; RawJwtBuilder(RawJwtBuilder&& other) = default; RawJwtBuilder& operator=(RawJwtBuilder&& other) = default; private: absl::optional error_; absl::optional type_header_; bool without_expiration_; google::protobuf::Struct json_proto_; }; } // namespace tink } // namespace crypto #endif // TINK_JWT_RAW_JWT_H_ ================================================ FILE: cc/jwt/raw_jwt_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/raw_jwt.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/escaping.h" #include "absl/time/clock.h" #include "absl/time/time.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::testing::IsEmpty; using ::testing::Not; using ::testing::UnorderedElementsAreArray; namespace crypto { namespace tink { TEST(RawJwt, GetTypeHeaderIssuerSubjectJwtIdOK) { util::StatusOr jwt = RawJwtBuilder() .SetTypeHeader("typeHeader") .SetIssuer("issuer") .SetSubject("subject") .SetJwtId("jwt_id") .WithoutExpiration() .Build(); ASSERT_THAT(jwt, IsOk()); EXPECT_TRUE(jwt->HasTypeHeader()); EXPECT_THAT(jwt->GetTypeHeader(), IsOkAndHolds("typeHeader")); EXPECT_TRUE(jwt->HasIssuer()); EXPECT_THAT(jwt->GetIssuer(), IsOkAndHolds("issuer")); EXPECT_TRUE(jwt->HasSubject()); EXPECT_THAT(jwt->GetSubject(), IsOkAndHolds("subject")); EXPECT_TRUE(jwt->HasJwtId()); EXPECT_THAT(jwt->GetJwtId(), IsOkAndHolds("jwt_id")); } TEST(RawJwt, TimestampsOK) { absl::Time nbf = absl::FromUnixSeconds(1234567890); absl::Time iat = absl::FromUnixSeconds(1234567891); absl::Time exp = absl::FromUnixSeconds(1234567892); util::StatusOr jwt = RawJwtBuilder() .SetNotBefore(nbf) .SetIssuedAt(iat) .SetExpiration(exp) .Build(); ASSERT_THAT(jwt, IsOk()); EXPECT_TRUE(jwt->HasNotBefore()); EXPECT_THAT(jwt->GetNotBefore(), IsOkAndHolds(nbf)); EXPECT_TRUE(jwt->HasIssuedAt()); EXPECT_THAT(jwt->GetIssuedAt(), IsOkAndHolds(iat)); EXPECT_TRUE(jwt->HasExpiration()); EXPECT_THAT(jwt->GetExpiration(), IsOkAndHolds(exp)); } TEST(RawJwt, ExpWithMillisAlwaysRoundDown) { util::StatusOr jwt = RawJwtBuilder().SetExpiration(absl::FromUnixMillis(123999)).Build(); ASSERT_THAT(jwt, IsOk()); EXPECT_TRUE(jwt->HasExpiration()); util::StatusOr exp = jwt->GetExpiration(); EXPECT_THAT(exp, IsOkAndHolds(absl::FromUnixSeconds(123))); } TEST(RawJwt, NbfWithMillisAlwaysRoundDown) { util::StatusOr jwt = RawJwtBuilder() .SetNotBefore(absl::FromUnixMillis(123999)) .WithoutExpiration() .Build(); ASSERT_THAT(jwt, IsOk()); EXPECT_TRUE(jwt->HasNotBefore()); util::StatusOr nbf = jwt->GetNotBefore(); EXPECT_THAT(nbf, IsOkAndHolds(absl::FromUnixSeconds(123))); } TEST(RawJwt, IatWithMillisAlwaysRoundDown) { util::StatusOr jwt = RawJwtBuilder() .SetIssuedAt(absl::FromUnixMillis(123999)) .WithoutExpiration() .Build(); ASSERT_THAT(jwt, IsOk()); EXPECT_TRUE(jwt->HasIssuedAt()); util::StatusOr iat = jwt->GetIssuedAt(); EXPECT_THAT(iat, IsOkAndHolds(absl::FromUnixSeconds(123))); } TEST(RawJwt, LargeExpirationWorks) { absl::Time large = absl::FromUnixSeconds(253402300799); // year 9999 util::StatusOr jwt = RawJwtBuilder() .SetNotBefore(large) .SetIssuedAt(large) .SetExpiration(large) .Build(); ASSERT_THAT(jwt, IsOk()); EXPECT_TRUE(jwt->HasExpiration()); EXPECT_TRUE(jwt->HasIssuedAt()); EXPECT_TRUE(jwt->HasNotBefore()); util::StatusOr exp = jwt->GetExpiration(); EXPECT_THAT(exp, IsOkAndHolds(large)); util::StatusOr iat = jwt->GetIssuedAt(); EXPECT_THAT(iat, IsOkAndHolds(large)); util::StatusOr nbf = jwt->GetNotBefore(); EXPECT_THAT(nbf, IsOkAndHolds(large)); } TEST(RawJwt, TooLargeTimestampsFail) { absl::Time too_large = absl::FromUnixSeconds(253402300800); // year 10000 EXPECT_FALSE(RawJwtBuilder().SetExpiration(too_large).Build().ok()); EXPECT_FALSE( RawJwtBuilder().SetIssuedAt(too_large).WithoutExpiration().Build().ok()); EXPECT_FALSE( RawJwtBuilder().SetNotBefore(too_large).WithoutExpiration().Build().ok()); } TEST(RawJwt, NegativeTimestampsFail) { absl::Time neg = absl::FromUnixMillis(-1); EXPECT_FALSE(RawJwtBuilder().SetExpiration(neg).Build().ok()); EXPECT_FALSE( RawJwtBuilder().SetIssuedAt(neg).WithoutExpiration().Build().ok()); EXPECT_FALSE( RawJwtBuilder().SetNotBefore(neg).WithoutExpiration().Build().ok()); } TEST(RawJwt, SetExpirationAndWithoutExpirationFail) { absl::Time exp = absl::FromUnixMillis(12345); EXPECT_FALSE( RawJwtBuilder().SetExpiration(exp).WithoutExpiration().Build().ok()); } TEST(RawJwt, NeitherSetExpirationNorWithoutExpirationFail) { EXPECT_FALSE(RawJwtBuilder().Build().ok()); } TEST(RawJwt, SetAudienceAndGetAudiencesOK) { util::StatusOr jwt = RawJwtBuilder().SetAudience("audience").WithoutExpiration().Build(); ASSERT_THAT(jwt, IsOk()); std::vector expected = {"audience"}; EXPECT_TRUE(jwt->HasAudiences()); EXPECT_THAT(jwt->GetAudiences(), IsOkAndHolds(expected)); } TEST(RawJwt, SetAudiencesAndGetAudiencesOK) { util::StatusOr jwt = RawJwtBuilder() .SetAudiences({"audience1", "audience2"}) .WithoutExpiration() .Build(); ASSERT_THAT(jwt, IsOk()); std::vector expected = {"audience1", "audience2"}; EXPECT_TRUE(jwt->HasAudiences()); EXPECT_THAT(jwt->GetAudiences(), IsOkAndHolds(expected)); } TEST(RawJwt, AddGetAudiencesOK) { util::StatusOr jwt = RawJwtBuilder() .AddAudience("audience1") .AddAudience("audience2") .WithoutExpiration() .Build(); ASSERT_THAT(jwt, IsOk()); std::vector expected = {"audience1", "audience2"}; EXPECT_TRUE(jwt->HasAudiences()); EXPECT_THAT(jwt->GetAudiences(), IsOkAndHolds(expected)); } TEST(RawJwt, SetAudienceStringAud) { util::StatusOr jwt = RawJwtBuilder().SetAudience("audience").WithoutExpiration().Build(); ASSERT_THAT(jwt, IsOk()); EXPECT_THAT(jwt->GetJsonPayload(), IsOkAndHolds(R"({"aud":"audience"})")); } TEST(RawJwt, AddAudienceListAud) { util::StatusOr jwt = RawJwtBuilder().AddAudience("audience").WithoutExpiration().Build(); ASSERT_THAT(jwt, IsOk()); EXPECT_THAT(jwt->GetJsonPayload(), IsOkAndHolds(R"({"aud":["audience"]})")); } TEST(RawJwt, SetAndAddAudienceFail) { EXPECT_THAT(RawJwtBuilder() .SetAudience("audience1") .AddAudience("audience2") .Build() .status(), Not(IsOk())); EXPECT_THAT(RawJwtBuilder() .AddAudience("audience2") .SetAudience("audience1") .Build() .status(), Not(IsOk())); } TEST(RawJwt, GetCustomClaimOK) { util::StatusOr jwt = RawJwtBuilder() .WithoutExpiration() .AddNullClaim("null_claim") .AddBooleanClaim("boolean_claim", true) .AddNumberClaim("number_claim", 123.456) .AddStringClaim("string_claim", "a string") .AddJsonObjectClaim("object_claim", R"({ "number": 123.456})") .AddJsonArrayClaim("array_claim", R"([1, "one", 1.2, true])") .Build(); ASSERT_THAT(jwt, IsOk()); EXPECT_TRUE(jwt->IsNullClaim("null_claim")); EXPECT_TRUE(jwt->HasBooleanClaim("boolean_claim")); EXPECT_THAT(jwt->GetBooleanClaim("boolean_claim"), IsOkAndHolds(true)); EXPECT_TRUE(jwt->HasNumberClaim("number_claim")); EXPECT_THAT(jwt->GetNumberClaim("number_claim"), IsOkAndHolds(123.456)); EXPECT_TRUE(jwt->HasStringClaim("string_claim")); EXPECT_THAT(jwt->GetStringClaim("string_claim"), IsOkAndHolds("a string")); EXPECT_TRUE(jwt->HasJsonObjectClaim("object_claim")); EXPECT_THAT(jwt->GetJsonObjectClaim("object_claim"), IsOkAndHolds(R"({"number":123.456})")); EXPECT_TRUE(jwt->HasJsonArrayClaim("array_claim")); EXPECT_THAT(jwt->GetJsonArrayClaim("array_claim"), IsOkAndHolds(R"([1,"one",1.2,true])")); std::vector expected_claim_names = { "object_claim", "number_claim", "boolean_claim", "array_claim", "null_claim", "string_claim"}; EXPECT_THAT(jwt->CustomClaimNames(), UnorderedElementsAreArray(expected_claim_names)); } TEST(RawJwt, HasCustomClaimIsFalseForWrongType) { util::StatusOr jwt = RawJwtBuilder() .WithoutExpiration() .AddNullClaim("null_claim") .AddBooleanClaim("boolean_claim", true) .AddNumberClaim("number_claim", 123.456) .AddStringClaim("string_claim", "a string") .Build(); ASSERT_THAT(jwt, IsOk()); EXPECT_FALSE(jwt->IsNullClaim("boolean_claim")); EXPECT_FALSE(jwt->HasBooleanClaim("number_claim")); EXPECT_FALSE(jwt->HasNumberClaim("string_claim")); EXPECT_FALSE(jwt->HasStringClaim("null_claim")); } TEST(RawJwt, HasAlwaysReturnsFalseForRegisteredClaims) { absl::Time now = absl::Now(); util::StatusOr jwt = RawJwtBuilder() .SetIssuer("issuer") .SetSubject("subject") .SetJwtId("jwt_id") .SetNotBefore(now - absl::Seconds(300)) .SetIssuedAt(now) .SetExpiration(now + absl::Seconds(300)) .Build(); ASSERT_THAT(jwt, IsOk()); EXPECT_FALSE(jwt->HasStringClaim("iss")); EXPECT_FALSE(jwt->HasStringClaim("sub")); EXPECT_FALSE(jwt->HasStringClaim("jti")); EXPECT_FALSE(jwt->HasNumberClaim("nbf")); EXPECT_FALSE(jwt->HasNumberClaim("iat")); EXPECT_FALSE(jwt->HasNumberClaim("exp")); EXPECT_THAT(jwt->CustomClaimNames(), IsEmpty()); } TEST(RawJwt, GetRegisteredCustomClaimNotOK) { absl::Time now = absl::Now(); util::StatusOr jwt = RawJwtBuilder() .SetIssuer("issuer") .SetSubject("subject") .SetJwtId("jwt_id") .SetNotBefore(now - absl::Seconds(300)) .SetIssuedAt(now) .SetExpiration(now + absl::Seconds(300)) .Build(); ASSERT_THAT(jwt, IsOk()); EXPECT_FALSE(jwt->GetStringClaim("iss").ok()); EXPECT_FALSE(jwt->GetStringClaim("sub").ok()); EXPECT_FALSE(jwt->GetStringClaim("jti").ok()); EXPECT_FALSE(jwt->GetNumberClaim("nbf").ok()); EXPECT_FALSE(jwt->GetNumberClaim("iat").ok()); EXPECT_FALSE(jwt->GetNumberClaim("exp").ok()); } TEST(RawJwt, SetRegisteredCustomClaimNotOK) { EXPECT_FALSE(RawJwtBuilder() .WithoutExpiration() .AddStringClaim("iss", "issuer") .Build() .ok()); EXPECT_FALSE(RawJwtBuilder() .WithoutExpiration() .AddStringClaim("sub", "issuer") .Build() .ok()); EXPECT_FALSE(RawJwtBuilder() .WithoutExpiration() .AddStringClaim("jti", "issuer") .Build() .ok()); EXPECT_FALSE(RawJwtBuilder() .WithoutExpiration() .AddNumberClaim("nbf", 123) .Build() .ok()); EXPECT_FALSE(RawJwtBuilder() .WithoutExpiration() .AddNumberClaim("iat", 123) .Build() .ok()); EXPECT_FALSE(RawJwtBuilder() .WithoutExpiration() .AddNumberClaim("exp", 123) .Build() .ok()); EXPECT_FALSE(RawJwtBuilder() .WithoutExpiration() .AddBooleanClaim("iss", true) .Build() .ok()); EXPECT_FALSE( RawJwtBuilder().WithoutExpiration().AddNullClaim("iss").Build().ok()); EXPECT_FALSE(RawJwtBuilder() .WithoutExpiration() .AddJsonObjectClaim("iss", "{\"1\": 2}") .Build() .ok()); EXPECT_FALSE(RawJwtBuilder() .WithoutExpiration() .AddJsonArrayClaim("iss", "[1,2]") .Build() .ok()); } TEST(RawJwt, SetInvalidJsonObjectClaimNotOK) { EXPECT_FALSE(RawJwtBuilder() .WithoutExpiration() .AddJsonObjectClaim("obj", "invalid") .Build() .ok()); EXPECT_FALSE(RawJwtBuilder() .WithoutExpiration() .AddJsonObjectClaim("obj", R"("string")") .Build() .ok()); EXPECT_FALSE(RawJwtBuilder() .WithoutExpiration() .AddJsonObjectClaim("obj", "42") .Build() .ok()); EXPECT_FALSE(RawJwtBuilder() .WithoutExpiration() .AddJsonObjectClaim("obj", "[1,2]") .Build() .ok()); } TEST(RawJwt, SetInvalidJsonArrayClaimNotOK) { EXPECT_FALSE(RawJwtBuilder() .WithoutExpiration() .AddJsonArrayClaim("arr", "invalid") .Build() .ok()); EXPECT_FALSE(RawJwtBuilder() .WithoutExpiration() .AddJsonArrayClaim("arr", R"("string")") .Build() .ok()); EXPECT_FALSE(RawJwtBuilder() .WithoutExpiration() .AddJsonArrayClaim("arr", "42") .Build() .ok()); EXPECT_FALSE(RawJwtBuilder() .WithoutExpiration() .AddJsonArrayClaim("arr", R"({"1": 2})") .Build() .ok()); } TEST(RawJwt, EmptyTokenHasAndIsReturnsFalse) { util::StatusOr jwt = RawJwtBuilder().WithoutExpiration().Build(); ASSERT_THAT(jwt, IsOk()); EXPECT_FALSE(jwt->HasTypeHeader()); EXPECT_FALSE(jwt->HasIssuer()); EXPECT_FALSE(jwt->HasSubject()); EXPECT_FALSE(jwt->HasAudiences()); EXPECT_FALSE(jwt->HasJwtId()); EXPECT_FALSE(jwt->HasExpiration()); EXPECT_FALSE(jwt->HasNotBefore()); EXPECT_FALSE(jwt->HasIssuedAt()); EXPECT_FALSE(jwt->IsNullClaim("null_claim")); EXPECT_FALSE(jwt->HasBooleanClaim("boolean_claim")); EXPECT_FALSE(jwt->HasNumberClaim("number_claim")); EXPECT_FALSE(jwt->HasStringClaim("string_claim")); EXPECT_FALSE(jwt->HasJsonObjectClaim("object_claim")); EXPECT_FALSE(jwt->HasJsonArrayClaim("array_claim")); } TEST(RawJwt, EmptyTokenGetReturnsNotOK) { util::StatusOr jwt = RawJwtBuilder().WithoutExpiration().Build(); ASSERT_THAT(jwt, IsOk()); EXPECT_FALSE(jwt->GetTypeHeader().ok()); EXPECT_FALSE(jwt->GetIssuer().ok()); EXPECT_FALSE(jwt->GetSubject().ok()); EXPECT_FALSE(jwt->GetAudiences().ok()); EXPECT_FALSE(jwt->GetJwtId().ok()); EXPECT_FALSE(jwt->GetExpiration().ok()); EXPECT_FALSE(jwt->GetNotBefore().ok()); EXPECT_FALSE(jwt->GetIssuedAt().ok()); EXPECT_FALSE(jwt->IsNullClaim("null_claim")); EXPECT_FALSE(jwt->GetBooleanClaim("boolean_claim").ok()); EXPECT_FALSE(jwt->GetNumberClaim("number_claim").ok()); EXPECT_FALSE(jwt->GetStringClaim("string_claim").ok()); EXPECT_FALSE(jwt->GetJsonObjectClaim("object_claim").ok()); EXPECT_FALSE(jwt->GetJsonArrayClaim("array_claim").ok()); } TEST(RawJwt, BuildCanBeCalledTwice) { auto builder = RawJwtBuilder() .SetIssuer("issuer") .SetSubject("subject") .WithoutExpiration(); util::StatusOr jwt = builder.Build(); ASSERT_THAT(jwt, IsOk()); builder.SetSubject("subject2"); util::StatusOr jwt2 = builder.Build(); ASSERT_THAT(jwt2, IsOk()); EXPECT_THAT(jwt->GetIssuer(), IsOkAndHolds("issuer")); EXPECT_THAT(jwt->GetSubject(), IsOkAndHolds("subject")); EXPECT_THAT(jwt2->GetIssuer(), IsOkAndHolds("issuer")); EXPECT_THAT(jwt2->GetSubject(), IsOkAndHolds("subject2")); } TEST(RawJwt, GetJsonPayload) { util::StatusOr jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(jwt, IsOk()); EXPECT_THAT(jwt->GetJsonPayload(), IsOkAndHolds(R"({"iss":"issuer"})")); } TEST(RawJwt, IntegerIsEncodedAsInteger) { util::StatusOr jwt = RawJwtBuilder().AddNumberClaim("num", 1).WithoutExpiration().Build(); ASSERT_THAT(jwt, IsOk()); EXPECT_THAT(jwt->GetJsonPayload(), IsOkAndHolds(R"({"num":1})")); } TEST(RawJwt, GetExpirationJsonPayload) { util::StatusOr jwt = RawJwtBuilder().SetExpiration(absl::FromUnixSeconds(2218027244)).Build(); ASSERT_THAT(jwt, IsOk()); EXPECT_THAT(jwt->GetJsonPayload(), IsOkAndHolds(R"({"exp":2218027244})")); } TEST(RawJwt, GetNanoExpirationJsonPayload) { util::StatusOr jwt = RawJwtBuilder().SetExpiration(absl::FromUnixNanos(123456789012)).Build(); ASSERT_THAT(jwt, IsOk()); EXPECT_THAT(jwt->GetJsonPayload(), IsOkAndHolds(R"({"exp":123})")); } } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/verified_jwt.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/verified_jwt.h" #include #include #include "absl/strings/numbers.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "absl/strings/substitute.h" #include "absl/time/time.h" #include "tink/jwt/internal/json_util.h" #include "tink/jwt/raw_jwt.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { VerifiedJwt::VerifiedJwt() = default; VerifiedJwt::VerifiedJwt(const RawJwt& raw_jwt) { raw_jwt_ = raw_jwt; } bool VerifiedJwt::HasTypeHeader() const { return raw_jwt_.HasTypeHeader(); } util::StatusOr VerifiedJwt::GetTypeHeader() const { return raw_jwt_.GetTypeHeader(); } bool VerifiedJwt::HasIssuer() const { return raw_jwt_.HasIssuer(); } util::StatusOr VerifiedJwt::GetIssuer() const { return raw_jwt_.GetIssuer(); } bool VerifiedJwt::HasSubject() const { return raw_jwt_.HasSubject(); } util::StatusOr VerifiedJwt::GetSubject() const { return raw_jwt_.GetSubject(); } bool VerifiedJwt::HasAudiences() const { return raw_jwt_.HasAudiences(); } util::StatusOr> VerifiedJwt::GetAudiences() const { return raw_jwt_.GetAudiences(); } bool VerifiedJwt::HasJwtId() const { return raw_jwt_.HasJwtId(); } util::StatusOr VerifiedJwt::GetJwtId() const { return raw_jwt_.GetJwtId(); } bool VerifiedJwt::HasExpiration() const { return raw_jwt_.HasExpiration(); } util::StatusOr VerifiedJwt::GetExpiration() const { return raw_jwt_.GetExpiration(); } bool VerifiedJwt::HasNotBefore() const { return raw_jwt_.HasNotBefore(); } util::StatusOr VerifiedJwt::GetNotBefore() const { return raw_jwt_.GetNotBefore(); } bool VerifiedJwt::HasIssuedAt() const { return raw_jwt_.HasIssuedAt(); } util::StatusOr VerifiedJwt::GetIssuedAt() const { return raw_jwt_.GetIssuedAt(); } bool VerifiedJwt::IsNullClaim(absl::string_view name) const { return raw_jwt_.IsNullClaim(name); } bool VerifiedJwt::HasBooleanClaim(absl::string_view name) const { return raw_jwt_.HasBooleanClaim(name); } util::StatusOr VerifiedJwt::GetBooleanClaim( absl::string_view name) const { return raw_jwt_.GetBooleanClaim(name); } bool VerifiedJwt::HasStringClaim(absl::string_view name) const { return raw_jwt_.HasStringClaim(name); } util::StatusOr VerifiedJwt::GetStringClaim( absl::string_view name) const { return raw_jwt_.GetStringClaim(name); } bool VerifiedJwt::HasNumberClaim(absl::string_view name) const { return raw_jwt_.HasNumberClaim(name); } util::StatusOr VerifiedJwt::GetNumberClaim( absl::string_view name) const { return raw_jwt_.GetNumberClaim(name); } bool VerifiedJwt::HasJsonObjectClaim(absl::string_view name) const { return raw_jwt_.HasJsonObjectClaim(name); } util::StatusOr VerifiedJwt::GetJsonObjectClaim( absl::string_view name) const { return raw_jwt_.GetJsonObjectClaim(name); } bool VerifiedJwt::HasJsonArrayClaim(absl::string_view name) const { return raw_jwt_.HasJsonArrayClaim(name); } util::StatusOr VerifiedJwt::GetJsonArrayClaim( absl::string_view name) const { return raw_jwt_.GetJsonArrayClaim(name); } std::vector VerifiedJwt::CustomClaimNames() const { return raw_jwt_.CustomClaimNames(); } util::StatusOr VerifiedJwt::GetJsonPayload() { return raw_jwt_.GetJsonPayload(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/jwt/verified_jwt.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_JWT_VERIFIED_JWT_H_ #define TINK_JWT_VERIFIED_JWT_H_ #include #include #include "google/protobuf/struct.pb.h" #include "absl/strings/string_view.h" #include "absl/time/clock.h" #include "absl/time/time.h" #include "tink/jwt/raw_jwt.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace jwt_internal { // For friend declaration class JwtMacImpl; class JwtPublicKeyVerifyImpl; } /////////////////////////////////////////////////////////////////////////////// // A decoded and verified JSON Web Token (JWT). // // A new instance of this class is returned as the result of a sucessfully // verification of a MACed or signed compact JWT. // // It gives read-only access all payload claims and a subset of the headers. It // does not contain any headers that depend on the key, such as "alg" or "kid". // These headers are checked when the signature is verified and should not be // read by the user. This ensures that the key can be changed without any // changes to the user code. class VerifiedJwt { public: // VerifiedJwt objects are copiable and implicitly movable. VerifiedJwt(const VerifiedJwt&) = default; VerifiedJwt& operator=(const VerifiedJwt&) = default; bool HasTypeHeader() const; util::StatusOr GetTypeHeader() const; bool HasIssuer() const; util::StatusOr GetIssuer() const; bool HasSubject() const; util::StatusOr GetSubject() const; bool HasAudiences() const; util::StatusOr> GetAudiences() const; bool HasJwtId() const; util::StatusOr GetJwtId() const; bool HasExpiration() const; util::StatusOr GetExpiration() const; bool HasNotBefore() const; util::StatusOr GetNotBefore() const; bool HasIssuedAt() const; util::StatusOr GetIssuedAt() const; bool IsNullClaim(absl::string_view name) const; bool HasBooleanClaim(absl::string_view name) const; util::StatusOr GetBooleanClaim(absl::string_view name) const; bool HasStringClaim(absl::string_view name) const; util::StatusOr GetStringClaim(absl::string_view name) const; bool HasNumberClaim(absl::string_view name) const; util::StatusOr GetNumberClaim(absl::string_view name) const; bool HasJsonObjectClaim(absl::string_view name) const; util::StatusOr GetJsonObjectClaim(absl::string_view name) const; bool HasJsonArrayClaim(absl::string_view name) const; util::StatusOr GetJsonArrayClaim(absl::string_view name) const; std::vector CustomClaimNames() const; util::StatusOr GetJsonPayload(); private: VerifiedJwt(); explicit VerifiedJwt(const RawJwt& raw_jwt); friend class jwt_internal::JwtMacImpl; friend class jwt_internal::JwtPublicKeyVerifyImpl; RawJwt raw_jwt_; }; } // namespace tink } // namespace crypto #endif // TINK_JWT_VERIFIED_JWT_H_ ================================================ FILE: cc/jwt/verified_jwt_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/jwt/verified_jwt.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/time/clock.h" #include "absl/time/time.h" #include "absl/types/optional.h" #include "tink/jwt/internal/jwt_mac_impl.h" #include "tink/jwt/internal/jwt_mac_internal.h" #include "tink/jwt/jwt_mac.h" #include "tink/jwt/jwt_validator.h" #include "tink/jwt/raw_jwt.h" #include "tink/mac.h" #include "tink/subtle/hmac_boringssl.h" #include "tink/util/constants.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/common.pb.h" using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; namespace crypto { namespace tink { namespace { util::StatusOr CreateVerifiedJwt(const RawJwt& raw_jwt) { // Creating a VerifiedJwt is a bit complicated since it can only be created // JWT primitives. std::string key_value; if (!absl::WebSafeBase64Unescape( "AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1" "qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow", &key_value)) { return util::Status(absl::StatusCode::kInvalidArgument, "failed to parse key"); } crypto::tink::util::StatusOr> mac = subtle::HmacBoringSsl::New( util::Enums::ProtoToSubtle(google::crypto::tink::HashType::SHA256), 32, util::SecretDataFromStringView(key_value)); if (!mac.ok()) { return mac.status(); } std::unique_ptr jwt_mac = absl::make_unique(std::move(*mac), "HS256", absl::nullopt); util::StatusOr compact = jwt_mac->ComputeMacAndEncodeWithKid(raw_jwt, "kid-123"); if (!compact.ok()) { return compact.status(); } JwtValidatorBuilder validator_builder = JwtValidatorBuilder() .IgnoreTypeHeader() .IgnoreIssuer() .IgnoreAudiences() .AllowMissingExpiration(); util::StatusOr issued_at = raw_jwt.GetIssuedAt(); if (issued_at.ok()) { validator_builder.SetFixedNow(*issued_at); } util::StatusOr validator = validator_builder.Build(); if (!validator.ok()) { return validator.status(); } return jwt_mac->VerifyMacAndDecodeWithKid(*compact, *validator, "kid-123"); } TEST(VerifiedJwt, GetTypeIssuerSubjectJwtIdOK) { util::StatusOr raw_jwt = RawJwtBuilder() .SetTypeHeader("typeHeader") .SetIssuer("issuer") .SetSubject("subject") .SetJwtId("jwt_id") .WithoutExpiration() .Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr jwt = CreateVerifiedJwt(*raw_jwt); ASSERT_THAT(jwt, IsOk()); EXPECT_TRUE(jwt->HasTypeHeader()); EXPECT_THAT(jwt->GetTypeHeader(), IsOkAndHolds("typeHeader")); EXPECT_TRUE(jwt->HasIssuer()); EXPECT_THAT(jwt->GetIssuer(), IsOkAndHolds("issuer")); EXPECT_TRUE(jwt->HasSubject()); EXPECT_THAT(jwt->GetSubject(), IsOkAndHolds("subject")); EXPECT_TRUE(jwt->HasJwtId()); EXPECT_THAT(jwt->GetJwtId(), IsOkAndHolds("jwt_id")); } TEST(VerifiedJwt, TimestampsOK) { absl::Time now = absl::Now(); util::StatusOr raw_jwt = RawJwtBuilder() .SetIssuer("issuer") .SetNotBefore(now - absl::Seconds(300)) .SetIssuedAt(now) .SetExpiration(now + absl::Seconds(300)) .Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr jwt = CreateVerifiedJwt(*raw_jwt); ASSERT_THAT(jwt, IsOk()); EXPECT_TRUE(jwt->HasNotBefore()); util::StatusOr nbf = jwt->GetNotBefore(); ASSERT_THAT(nbf, IsOk()); EXPECT_LT(*nbf, now - absl::Seconds(299)); EXPECT_GT(*nbf, now - absl::Seconds(301)); EXPECT_TRUE(jwt->HasIssuedAt()); util::StatusOr iat = jwt->GetIssuedAt(); ASSERT_THAT(iat, IsOk()); EXPECT_LT(*iat, now + absl::Seconds(1)); EXPECT_GT(*iat, now - absl::Seconds(1)); EXPECT_TRUE(jwt->HasExpiration()); util::StatusOr exp = jwt->GetExpiration(); ASSERT_THAT(exp, IsOk()); EXPECT_LT(*exp, now + absl::Seconds(301)); EXPECT_GT(*exp, now + absl::Seconds(299)); } TEST(VerifiedJwt, GetAudiencesOK) { util::StatusOr raw_jwt = RawJwtBuilder() .AddAudience("audience1") .AddAudience("audience2") .WithoutExpiration() .Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr jwt = CreateVerifiedJwt(*raw_jwt); ASSERT_THAT(jwt, IsOk()); std::vector expected = {"audience1", "audience2"}; EXPECT_TRUE(jwt->HasAudiences()); EXPECT_THAT(jwt->GetAudiences(), IsOkAndHolds(expected)); } TEST(VerifiedJwt, GetCustomClaimOK) { util::StatusOr raw_jwt = RawJwtBuilder() .WithoutExpiration() .AddNullClaim("null_claim") .AddBooleanClaim("boolean_claim", true) .AddNumberClaim("number_claim", 123.456) .AddStringClaim("string_claim", "a string") .AddJsonObjectClaim("object_claim", R"({ "number": 123.456})") .AddJsonArrayClaim("array_claim", R"([1, "one", 1.2, true])") .Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr jwt = CreateVerifiedJwt(*raw_jwt); ASSERT_THAT(jwt, IsOk()); EXPECT_TRUE(jwt->IsNullClaim("null_claim")); EXPECT_TRUE(jwt->HasBooleanClaim("boolean_claim")); EXPECT_THAT(jwt->GetBooleanClaim("boolean_claim"), IsOkAndHolds(true)); EXPECT_TRUE(jwt->HasNumberClaim("number_claim")); EXPECT_THAT(jwt->GetNumberClaim("number_claim"), IsOkAndHolds(123.456)); EXPECT_TRUE(jwt->HasStringClaim("string_claim")); EXPECT_THAT(jwt->GetStringClaim("string_claim"), IsOkAndHolds("a string")); EXPECT_TRUE(jwt->HasJsonObjectClaim("object_claim")); EXPECT_THAT(jwt->GetJsonObjectClaim("object_claim"), IsOkAndHolds(R"({"number":123.456})")); EXPECT_TRUE(jwt->HasJsonArrayClaim("array_claim")); EXPECT_THAT(jwt->GetJsonArrayClaim("array_claim"), IsOkAndHolds(R"([1,"one",1.2,true])")); std::vector expected_claim_names = { "object_claim", "number_claim", "boolean_claim", "array_claim", "null_claim", "string_claim"}; EXPECT_THAT(jwt->CustomClaimNames(), testing::UnorderedElementsAreArray(expected_claim_names)); } TEST(VerifiedJwt, HasCustomClaimIsFalseForWrongType) { util::StatusOr raw_jwt = RawJwtBuilder() .WithoutExpiration() .AddNullClaim("null_claim") .AddBooleanClaim("boolean_claim", true) .AddNumberClaim("number_claim", 123.456) .AddStringClaim("string_claim", "a string") .Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr jwt = CreateVerifiedJwt(*raw_jwt); ASSERT_THAT(jwt, IsOk()); EXPECT_FALSE(jwt->IsNullClaim("boolean_claim")); EXPECT_FALSE(jwt->HasBooleanClaim("number_claim")); EXPECT_FALSE(jwt->HasNumberClaim("string_claim")); EXPECT_FALSE(jwt->HasStringClaim("null_claim")); } TEST(VerifiedJwt, HasAlwaysReturnsFalseForRegisteredClaims) { absl::Time now = absl::Now(); util::StatusOr raw_jwt = RawJwtBuilder() .SetIssuer("issuer") .SetSubject("subject") .SetJwtId("jwt_id") .SetNotBefore(now - absl::Seconds(300)) .SetIssuedAt(now) .SetExpiration(now + absl::Seconds(300)) .Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr jwt = CreateVerifiedJwt(*raw_jwt); ASSERT_THAT(jwt, IsOk()); EXPECT_FALSE(jwt->HasStringClaim("iss")); EXPECT_FALSE(jwt->HasStringClaim("sub")); EXPECT_FALSE(jwt->HasStringClaim("jti")); EXPECT_FALSE(jwt->HasNumberClaim("nbf")); EXPECT_FALSE(jwt->HasNumberClaim("iat")); EXPECT_FALSE(jwt->HasNumberClaim("exp")); EXPECT_THAT(jwt->CustomClaimNames(), testing::IsEmpty()); } TEST(VerifiedJwt, GetRegisteredCustomClaimNotOK) { absl::Time now = absl::Now(); util::StatusOr raw_jwt = RawJwtBuilder() .SetIssuer("issuer") .SetSubject("subject") .SetJwtId("jwt_id") .SetNotBefore(now - absl::Seconds(300)) .SetIssuedAt(now) .SetExpiration(now + absl::Seconds(300)) .Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr jwt = CreateVerifiedJwt(*raw_jwt); ASSERT_THAT(jwt, IsOk()); EXPECT_FALSE(jwt->GetStringClaim("iss").ok()); EXPECT_FALSE(jwt->GetStringClaim("sub").ok()); EXPECT_FALSE(jwt->GetStringClaim("jti").ok()); EXPECT_FALSE(jwt->GetNumberClaim("nbf").ok()); EXPECT_FALSE(jwt->GetNumberClaim("iat").ok()); EXPECT_FALSE(jwt->GetNumberClaim("exp").ok()); } TEST(VerifiedJwt, EmptyTokenHasAndIsReturnsFalse) { util::StatusOr raw_jwt = RawJwtBuilder().WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr jwt = CreateVerifiedJwt(*raw_jwt); ASSERT_THAT(jwt, IsOk()); EXPECT_FALSE(jwt->HasTypeHeader()); EXPECT_FALSE(jwt->HasIssuer()); EXPECT_FALSE(jwt->HasSubject()); EXPECT_FALSE(jwt->HasAudiences()); EXPECT_FALSE(jwt->HasJwtId()); EXPECT_FALSE(jwt->HasExpiration()); EXPECT_FALSE(jwt->HasNotBefore()); EXPECT_FALSE(jwt->HasIssuedAt()); EXPECT_FALSE(jwt->IsNullClaim("null_claim")); EXPECT_FALSE(jwt->HasBooleanClaim("boolean_claim")); EXPECT_FALSE(jwt->HasNumberClaim("number_claim")); EXPECT_FALSE(jwt->HasStringClaim("string_claim")); EXPECT_FALSE(jwt->HasJsonObjectClaim("object_claim")); EXPECT_FALSE(jwt->HasJsonArrayClaim("array_claim")); } TEST(VerifiedJwt, EmptyTokenGetReturnsNotOK) { util::StatusOr raw_jwt = RawJwtBuilder().WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr jwt = CreateVerifiedJwt(*raw_jwt); ASSERT_THAT(jwt, IsOk()); EXPECT_FALSE(jwt->GetTypeHeader().ok()); EXPECT_FALSE(jwt->GetIssuer().ok()); EXPECT_FALSE(jwt->GetSubject().ok()); EXPECT_FALSE(jwt->GetAudiences().ok()); EXPECT_FALSE(jwt->GetJwtId().ok()); EXPECT_FALSE(jwt->GetExpiration().ok()); EXPECT_FALSE(jwt->GetNotBefore().ok()); EXPECT_FALSE(jwt->GetIssuedAt().ok()); EXPECT_FALSE(jwt->IsNullClaim("null_claim")); EXPECT_FALSE(jwt->GetBooleanClaim("boolean_claim").ok()); EXPECT_FALSE(jwt->GetNumberClaim("number_claim").ok()); EXPECT_FALSE(jwt->GetStringClaim("string_claim").ok()); EXPECT_FALSE(jwt->GetJsonObjectClaim("object_claim").ok()); EXPECT_FALSE(jwt->GetJsonArrayClaim("array_claim").ok()); } TEST(VerifiedJwt, GetJsonPayload) { util::StatusOr raw_jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr jwt = CreateVerifiedJwt(*raw_jwt); ASSERT_THAT(jwt, IsOk()); EXPECT_THAT(jwt->GetJsonPayload(), IsOkAndHolds(R"({"iss":"issuer"})")); } TEST(VerifiedJwt, MoveMakesCopy) { util::StatusOr raw_jwt = RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build(); ASSERT_THAT(raw_jwt, IsOk()); util::StatusOr jwt = CreateVerifiedJwt(*raw_jwt); ASSERT_THAT(jwt, IsOk()); VerifiedJwt jwt1 = *jwt; VerifiedJwt jwt2 = std::move(jwt1); // We want that a VerifiedJwt object remains a valid object, even after // std::moved has been called. EXPECT_TRUE(jwt1.HasIssuer()); // NOLINT(bugprone-use-after-move) EXPECT_THAT(jwt1.GetIssuer(), IsOkAndHolds("issuer")); EXPECT_TRUE(jwt2.HasIssuer()); EXPECT_THAT(jwt2.GetIssuer(), IsOkAndHolds("issuer")); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/kem/internal/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "raw_kem_decapsulate", hdrs = ["raw_kem_decapsulate.h"], include_prefix = "tink/kem/internal", deps = [ "//:restricted_data", "//util:statusor", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "raw_kem_encapsulate", hdrs = ["raw_kem_encapsulate.h"], include_prefix = "tink/kem/internal", deps = [ "//:restricted_data", "//util:statusor", ], ) ================================================ FILE: cc/kem/internal/CMakeLists.txt ================================================ tink_cc_library( NAME raw_kem_decapsulate SRCS raw_kem_decapsulate.h DEPS absl::string_view tink::core::restricted_data tink::util::statusor ) tink_cc_library( NAME raw_kem_encapsulate SRCS raw_kem_encapsulate.h DEPS tink::core::restricted_data tink::util::statusor ) ================================================ FILE: cc/kem/internal/raw_kem_decapsulate.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_KEM_INTERNAL_RAW_KEM_DECAPSULATE_H_ #define TINK_KEM_INTERNAL_RAW_KEM_DECAPSULATE_H_ #include "absl/strings/string_view.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { // A raw KEM decapsulation interface. // // The decapsulation method directly exposes the shared secret bytes, rather // than a higher-level KeysetHandle abstraction. class RawKemDecapsulate { public: // Decapsulates the ciphertext and returns the shared secret bytes. virtual util::StatusOr Decapsulate( absl::string_view ciphertext) const = 0; virtual ~RawKemDecapsulate() = default; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_KEM_INTERNAL_RAW_KEM_DECAPSULATE_H_ ================================================ FILE: cc/kem/internal/raw_kem_encapsulate.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_KEM_INTERNAL_RAW_KEM_ENCAPSULATE_H_ #define TINK_KEM_INTERNAL_RAW_KEM_ENCAPSULATE_H_ #include #include "tink/restricted_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { // A raw KEM encapsulation. // // This directly exposes the shared secret bytes. struct RawKemEncapsulation { std::string ciphertext; RestrictedData shared_secret; }; // A raw KEM encapsulation interface. // // The encapsulation method directly exposes shared secret bytes, rather than a // higher-level KeysetHandle abstraction. class RawKemEncapsulate { public: // Generates a new encapsulation, containing the ciphertext and the shared // secret bytes. virtual util::StatusOr Encapsulate() const = 0; virtual ~RawKemEncapsulate() = default; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_KEM_INTERNAL_RAW_KEM_ENCAPSULATE_H_ ================================================ FILE: cc/key.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_KEY_H_ #define TINK_KEY_H_ #include "absl/types/optional.h" #include "tink/parameters.h" namespace crypto { namespace tink { // Represents a cryptographic function. // // In Tink, `Key` objects represent cryptographic functions. For example, a // `MacKey` represents the two functions: `computeMac()` and `verifyMac()`. // The function `computeMac()` maps a byte sequence (possibly with additional // randomness) to another byte sequence, called the tag. The function // `verifyMac()` verifies the tag. A subclass `HmacKey` would contain all the // information needed to properly compute an HMAC (e.g., including the hash // function and tag length used). // // `Key` objects are lightweight, meaning they should have almost no // dependencies except what is needed to represent the function. This allows // `Key` objects to be used in contexts where dependencies need to be kept to a // minimum. class Key { public: Key() = default; // Copyable and movable. Key(const Key& other) = default; Key& operator=(const Key& other) = default; Key(Key&& other) = default; Key& operator=(Key&& other) = default; // Returns a `Parameters` object containing all the information about the key // that is not randomly chosen. // // Implementations should ensure that 'GetParameters().HasIdRequirement()` // returns true if and only if `GetIdRequirement()` has a non-empty value. virtual const Parameters& GetParameters() const = 0; // Returns the required id if this key has an id requirement. Otherwise, // returns an empty value if the key can have an arbitrary id. // // Some keys within a keyset are required to have a specific id to work // properly. This comes from the fact that Tink in some cases prefixes // ciphertexts or signatures with the string '0x01', where the key id is // encoded in big endian format (see the documentation of the key type for // details). The key id provides a hint for which specific key was used to // generate the ciphertext or signature. virtual absl::optional GetIdRequirement() const = 0; // Returns true if all `Key` object fields have identical values, including // the bytes for the raw key material. Otherwise, returns false. // // NOTE: Implementations must perform equality checks in constant time. virtual bool operator==(const Key& other) const = 0; bool operator!=(const Key& other) const { return !(*this == other); } virtual ~Key() = default; }; } // namespace tink } // namespace crypto #endif // TINK_KEY_H_ ================================================ FILE: cc/key_access.h ================================================ // Copyright 2021 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_KEY_ACCESS_H_ #define TINK_KEY_ACCESS_H_ namespace crypto { namespace tink { class KeyAccess { public: static KeyAccess PublicAccess() { KeyAccess token(false); return token; } bool CanAccessSecret() { return can_access_secret_; } // KeyAccess objects are copiable and movable. KeyAccess(const KeyAccess&) = default; KeyAccess& operator=(const KeyAccess&) = default; KeyAccess(KeyAccess&& other) = default; KeyAccess& operator=(KeyAccess&& other) = default; private: KeyAccess() = delete; explicit KeyAccess(bool can_access_secret) : can_access_secret_(can_access_secret) {} friend class SecretKeyAccess; bool can_access_secret_; }; } // namespace tink } // namespace crypto #endif // TINK_KEY_ACCESS_H_ ================================================ FILE: cc/key_gen_configuration.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_KEY_GEN_CONFIGURATION_H_ #define TINK_KEY_GEN_CONFIGURATION_H_ #include "tink/internal/key_type_info_store.h" namespace crypto { namespace tink { namespace internal { class KeyGenConfigurationImpl; } // KeyGenConfiguration used to generate keys using stored key type managers. class KeyGenConfiguration { public: KeyGenConfiguration() = default; // Not copyable or movable. KeyGenConfiguration(const KeyGenConfiguration&) = delete; KeyGenConfiguration& operator=(const KeyGenConfiguration&) = delete; private: friend class internal::KeyGenConfigurationImpl; // When true, KeyGenConfiguration is in global registry mode. For // `some_fn(config)` with a `config` parameter, this indicates to `some_fn` to // use crypto::tink::Registry directly. bool global_registry_mode_ = false; crypto::tink::internal::KeyTypeInfoStore key_type_info_store_; }; } // namespace tink } // namespace crypto #endif // TINK_KEY_GEN_CONFIGURATION_H_ ================================================ FILE: cc/key_manager.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_KEY_MANAGER_H_ #define TINK_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // Auxiliary containers for methods that generate or extract key material. // These methods are grouped separately, as their functionality // is independent of the primitive of the corresponding KeyManager. class KeyFactory { public: // Helper function which creates a factory which always fails with a specified // status. static std::unique_ptr AlwaysFailingFactory( const crypto::tink::util::Status& status); // Generates a new random key, based on the specified 'key_format'. virtual crypto::tink::util::StatusOr< std::unique_ptr> NewKey(const portable_proto::MessageLite& key_format) const = 0; // Generates a new random key, based on the specified 'serialized_key_format'. virtual crypto::tink::util::StatusOr< std::unique_ptr> NewKey(absl::string_view serialized_key_format) const = 0; // Generates a new random key, based on the specified 'serialized_key_format', // and wraps it in a KeyData-proto. virtual crypto::tink::util::StatusOr< std::unique_ptr> NewKeyData(absl::string_view serialized_key_format) const = 0; virtual ~KeyFactory() = default; }; class PrivateKeyFactory : public virtual KeyFactory { public: // Returns public key data extracted from the given serialized_private_key. virtual crypto::tink::util::StatusOr< std::unique_ptr> GetPublicKeyData(absl::string_view serialized_private_key) const = 0; ~PrivateKeyFactory() override = default; }; /** * KeyManager "understands" keys of a specific key types: it can * generate keys of a supported type and create primitives for * supported keys. A key type is identified by the global name of the * protocol buffer that holds the corresponding key material, and is * given by type_url-field of KeyData-protocol buffer. * * - P: the primitive implemented by keys understood by this manager */ class KeyManagerBase { public: // Returns the type_url identifying the key type handled by this manager. virtual const std::string& get_key_type() const = 0; // Returns the version of this key manager. virtual uint32_t get_version() const = 0; // Returns a factory that generates keys of the key type // handled by this manager. virtual const KeyFactory& get_key_factory() const = 0; bool DoesSupport(absl::string_view key_type) const { return (key_type == get_key_type()); } virtual ~KeyManagerBase() = default; }; template class KeyManager : public KeyManagerBase { public: // Constructs an instance of P for the given 'key_data'. virtual crypto::tink::util::StatusOr> GetPrimitive( const google::crypto::tink::KeyData& key_data) const = 0; // Constructs an instance of P for the given 'key'. virtual crypto::tink::util::StatusOr> GetPrimitive( const portable_proto::MessageLite& key) const = 0; }; } // namespace tink } // namespace crypto #endif // TINK_KEY_MANAGER_H_ ================================================ FILE: cc/key_status.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_KEY_STATUS_H_ #define TINK_KEY_STATUS_H_ namespace crypto { namespace tink { // Enum representation of KeyStatusType in tink/proto/tink.proto. Using an // enum class prevents unintentional implicit conversions. enum class KeyStatus : int { kEnabled = 1, // Can be used for cryptographic operations. kDisabled = 2, // Cannot be used (but can become kEnabled again). kDestroyed = 3, // Key data does not exist in this Keyset any more. // Added to guard from failures that may be caused by future expansions. kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; } // namespace tink } // namespace crypto #endif // TINK_KEY_STATUS_H_ ================================================ FILE: cc/keyderivation/BUILD.bazel ================================================ package( default_visibility = ["//:__subpackages__"], ) licenses(["notice"]) cc_library( name = "key_derivation_config", srcs = ["key_derivation_config.cc"], hdrs = ["key_derivation_config.h"], include_prefix = "tink/keyderivation", visibility = ["//visibility:public"], deps = [ ":keyset_deriver_wrapper", "//:registry", "//config:tink_fips", "//keyderivation/internal:prf_based_deriver_key_manager", "//prf:hkdf_prf_key_manager", "//util:status", "@com_google_absl//absl/memory", ], ) cc_test( name = "key_derivation_config_test", srcs = ["key_derivation_config_test.cc"], deps = [ ":key_derivation_config", ":key_derivation_key_templates", ":keyset_deriver", "//:aead", "//:keyset_handle", "//:registry", "//aead:aead_config", "//aead:aead_key_templates", "//aead:aes_gcm_key_manager", "//config:global_registry", "//prf:prf_key_templates", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "key_derivation_key_templates", srcs = ["key_derivation_key_templates.cc"], hdrs = ["key_derivation_key_templates.h"], include_prefix = "tink/keyderivation", visibility = ["//visibility:public"], deps = [ ":keyset_deriver", "//:keyset_handle", "//config:global_registry", "//keyderivation/internal:prf_based_deriver_key_manager", "//proto:prf_based_deriver_cc_proto", "//proto:tink_cc_proto", "//util:statusor", ], ) cc_test( name = "key_derivation_key_templates_test", srcs = ["key_derivation_key_templates_test.cc"], deps = [ ":key_derivation_key_templates", ":keyset_deriver_wrapper", "//:registry", "//aead:aead_key_templates", "//aead:aes_gcm_key_manager", "//keyderivation/internal:prf_based_deriver_key_manager", "//prf:hkdf_prf_key_manager", "//prf:prf_key_templates", "//proto:prf_based_deriver_cc_proto", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "keyset_deriver", hdrs = ["keyset_deriver.h"], include_prefix = "tink/keyderivation", visibility = ["//visibility:public"], deps = [ "//:keyset_handle", "//util:statusor", "@com_google_absl//absl/strings", ], ) cc_library( name = "keyset_deriver_wrapper", srcs = ["keyset_deriver_wrapper.cc"], hdrs = ["keyset_deriver_wrapper.h"], include_prefix = "tink/keyderivation", deps = [ ":keyset_deriver", "//:cleartext_keyset_handle", "//:keyset_handle", "//:primitive_set", "//:primitive_wrapper", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", ], ) cc_test( name = "keyset_deriver_wrapper_test", srcs = ["keyset_deriver_wrapper_test.cc"], deps = [ ":keyset_deriver", ":keyset_deriver_wrapper", "//:cleartext_keyset_handle", "//:keyset_handle", "//:primitive_set", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "keyset_deriver_test", srcs = ["keyset_deriver_test.cc"], deps = [ ":keyset_deriver", ":keyset_deriver_wrapper", "//:insecure_secret_key_access", "//:key", "//:keyset_handle", "//:partial_key_access", "//:partial_key_access_token", "//:registry", "//:restricted_data", "//aead:aes_gcm_key", "//aead:aes_gcm_parameters", "//aead:aes_gcm_proto_serialization", "//config:global_registry", "//internal:mutable_serialization_registry", "//internal:proto_parameters_serialization", "//internal:serialization", "//keyderivation/internal:prf_based_deriver_key_manager", "//proto:hkdf_prf_cc_proto", "//proto:prf_based_deriver_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_keyset_handle", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/keyderivation/CMakeLists.txt ================================================ tink_module(keyderivation) add_subdirectory(internal) tink_cc_library( NAME key_derivation_config SRCS key_derivation_config.cc key_derivation_config.h DEPS tink::keyderivation::keyset_deriver_wrapper absl::memory tink::core::registry tink::config::tink_fips tink::keyderivation::internal::prf_based_deriver_key_manager tink::prf::hkdf_prf_key_manager tink::util::status PUBLIC ) tink_cc_test( NAME key_derivation_config_test SRCS key_derivation_config_test.cc DEPS tink::keyderivation::key_derivation_config tink::keyderivation::key_derivation_key_templates tink::keyderivation::keyset_deriver gmock absl::memory tink::core::aead tink::core::keyset_handle tink::core::registry tink::aead::aead_config tink::aead::aead_key_templates tink::aead::aes_gcm_key_manager tink::config::global_registry tink::prf::prf_key_templates tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) tink_cc_library( NAME key_derivation_key_templates SRCS key_derivation_key_templates.cc key_derivation_key_templates.h DEPS tink::keyderivation::keyset_deriver tink::core::keyset_handle tink::config::global_registry tink::keyderivation::internal::prf_based_deriver_key_manager tink::util::statusor tink::proto::prf_based_deriver_cc_proto tink::proto::tink_cc_proto PUBLIC ) tink_cc_test( NAME key_derivation_key_templates_test SRCS key_derivation_key_templates_test.cc DEPS tink::keyderivation::key_derivation_key_templates tink::keyderivation::keyset_deriver_wrapper gmock absl::memory absl::status tink::core::registry tink::aead::aead_key_templates tink::aead::aes_gcm_key_manager tink::keyderivation::internal::prf_based_deriver_key_manager tink::prf::hkdf_prf_key_manager tink::prf::prf_key_templates tink::util::statusor tink::util::test_matchers tink::proto::prf_based_deriver_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME keyset_deriver SRCS keyset_deriver.h DEPS absl::strings tink::core::keyset_handle tink::util::statusor PUBLIC ) tink_cc_library( NAME keyset_deriver_wrapper SRCS keyset_deriver_wrapper.cc keyset_deriver_wrapper.h DEPS tink::keyderivation::keyset_deriver absl::memory absl::status absl::string_view tink::core::cleartext_keyset_handle tink::core::keyset_handle tink::core::primitive_set tink::core::primitive_wrapper tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_test( NAME keyset_deriver_wrapper_test SRCS keyset_deriver_wrapper_test.cc DEPS tink::keyderivation::keyset_deriver tink::keyderivation::keyset_deriver_wrapper gmock absl::memory absl::status absl::strings absl::string_view tink::core::cleartext_keyset_handle tink::core::keyset_handle tink::core::primitive_set tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::tink_cc_proto ) tink_cc_test( NAME keyset_deriver_test SRCS keyset_deriver_test.cc DEPS tink::keyderivation::keyset_deriver tink::keyderivation::keyset_deriver_wrapper gmock absl::memory absl::status absl::string_view absl::optional tink::core::insecure_secret_key_access tink::core::key tink::core::keyset_handle tink::core::partial_key_access tink::core::partial_key_access_token tink::core::registry tink::core::restricted_data tink::aead::aes_gcm_key tink::aead::aes_gcm_parameters tink::aead::aes_gcm_proto_serialization tink::config::global_registry tink::internal::mutable_serialization_registry tink::internal::proto_parameters_serialization tink::internal::serialization tink::keyderivation::internal::prf_based_deriver_key_manager tink::util::status tink::util::statusor tink::util::test_keyset_handle tink::util::test_matchers tink::util::test_util tink::proto::hkdf_prf_cc_proto tink::proto::prf_based_deriver_cc_proto tink::proto::tink_cc_proto ) ================================================ FILE: cc/keyderivation/internal/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "prf_based_deriver", srcs = ["prf_based_deriver.cc"], hdrs = ["prf_based_deriver.h"], include_prefix = "tink/keyderivation/internal", deps = [ ":config_prf_for_deriver", ":key_derivers", "//:cleartext_keyset_handle", "//:input_stream", "//:key", "//:key_status", "//:keyset_handle", "//:keyset_handle_builder", "//:parameters", "//aead:aes_gcm_proto_serialization", "//internal:configuration_impl", "//internal:key_type_info_store", "//internal:mutable_serialization_registry", "//internal:proto_parameters_serialization", "//internal:registry_impl", "//keyderivation:keyset_deriver", "//proto:tink_cc_proto", "//subtle/prf:streaming_prf", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/strings:string_view", ], ) cc_test( name = "prf_based_deriver_test", srcs = ["prf_based_deriver_test.cc"], deps = [ ":prf_based_deriver", "//:cleartext_keyset_handle", "//:insecure_secret_key_access", "//:key_status", "//:keyset_handle", "//:partial_key_access", "//:registry", "//aead:aead_key_templates", "//aead:aes_ctr_hmac_aead_key_manager", "//aead:aes_gcm_key", "//aead:aes_gcm_key_manager", "//aead:aes_gcm_parameters", "//internal:registry_impl", "//keyderivation:keyset_deriver", "//prf:hkdf_prf_key_manager", "//proto:aes_gcm_cc_proto", "//proto:common_cc_proto", "//proto:hkdf_prf_cc_proto", "//proto:tink_cc_proto", "//subtle:random", "//subtle/prf:streaming_prf", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "prf_based_deriver_key_manager", hdrs = ["prf_based_deriver_key_manager.h"], include_prefix = "tink/keyderivation/internal", deps = [ ":prf_based_deriver", "//:core/key_type_manager", "//:core/template_util", "//:registry", "//keyderivation:keyset_deriver", "//proto:prf_based_deriver_cc_proto", "//proto:tink_cc_proto", "//util:constants", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_test( name = "prf_based_deriver_key_manager_test", srcs = ["prf_based_deriver_key_manager_test.cc"], deps = [ ":prf_based_deriver", ":prf_based_deriver_key_manager", "//:cleartext_keyset_handle", "//:keyset_handle", "//:registry", "//aead:aead_key_templates", "//aead:aes_gcm_key_manager", "//keyderivation:keyset_deriver", "//prf:hkdf_prf_key_manager", "//proto:aes_gcm_cc_proto", "//proto:hkdf_prf_cc_proto", "//proto:prf_based_deriver_cc_proto", "//proto:tink_cc_proto", "//subtle", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "key_derivers", srcs = ["key_derivers.cc"], hdrs = ["key_derivers.h"], include_prefix = "tink/keyderivation/internal", deps = [ "//:input_stream", "//:insecure_secret_key_access", "//:key", "//:parameters", "//:partial_key_access", "//:restricted_data", "//aead:aes_gcm_key", "//aead:aes_gcm_parameters", "//aead:aes_gcm_proto_serialization", "//proto:aes_gcm_cc_proto", "//proto:tink_cc_proto", "//util:input_stream_util", "//util:status", "//util:statusor", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/functional:any_invocable", "@com_google_absl//absl/log:check", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_test( name = "key_derivers_test", srcs = ["key_derivers_test.cc"], deps = [ ":key_derivers", "//:input_stream", "//:insecure_secret_key_access", "//:key", "//:key_status", "//:keyset_handle", "//:keyset_handle_builder", "//:partial_key_access", "//:registry", "//:restricted_data", "//:secret_key_access_token", "//aead:aes_eax_parameters", "//aead:aes_eax_proto_serialization", "//aead:aes_gcm_key", "//aead:aes_gcm_key_manager", "//aead:aes_gcm_parameters", "//aead:aes_gcm_proto_serialization", "//internal:mutable_serialization_registry", "//internal:proto_parameters_serialization", "//internal:serialization", "//prf:hkdf_prf_key_manager", "//proto:aes_gcm_cc_proto", "//proto:common_cc_proto", "//proto:hkdf_prf_cc_proto", "//proto:tink_cc_proto", "//subtle:common_enums", "//subtle:random", "//subtle/prf:hkdf_streaming_prf", "//subtle/prf:streaming_prf", "//util:istream_input_stream", "//util:secret_data", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "config_prf_for_deriver", hdrs = ["config_prf_for_deriver.h"], include_prefix = "tink/keyderivation/internal", deps = [ "//:configuration", "//internal:configuration_impl", "//prf:hkdf_prf_key_manager", "@com_google_absl//absl/log:check", "@com_google_absl//absl/memory", ], ) cc_test( name = "config_prf_for_deriver_test", srcs = ["config_prf_for_deriver_test.cc"], deps = [ ":config_prf_for_deriver", "//internal:configuration_impl", "//internal:key_type_info_store", "//prf:hkdf_prf_key_manager", "//proto:tink_cc_proto", "//subtle/prf:streaming_prf", "//util:input_stream_util", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/keyderivation/internal/CMakeLists.txt ================================================ tink_module(keyderivation::internal) tink_cc_library( NAME prf_based_deriver SRCS prf_based_deriver.cc prf_based_deriver.h DEPS tink::keyderivation::internal::config_prf_for_deriver tink::keyderivation::internal::key_derivers absl::memory absl::string_view tink::core::cleartext_keyset_handle tink::core::input_stream tink::core::key tink::core::key_status tink::core::keyset_handle tink::core::keyset_handle_builder tink::core::parameters tink::aead::aes_gcm_proto_serialization tink::internal::configuration_impl tink::internal::key_type_info_store tink::internal::mutable_serialization_registry tink::internal::proto_parameters_serialization tink::internal::registry_impl tink::keyderivation::keyset_deriver tink::subtle::prf::streaming_prf tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_test( NAME prf_based_deriver_test SRCS prf_based_deriver_test.cc DEPS tink::keyderivation::internal::prf_based_deriver gmock absl::memory absl::status absl::string_view absl::optional tink::core::cleartext_keyset_handle tink::core::insecure_secret_key_access tink::core::key_status tink::core::keyset_handle tink::core::partial_key_access tink::core::registry tink::aead::aead_key_templates tink::aead::aes_ctr_hmac_aead_key_manager tink::aead::aes_gcm_key tink::aead::aes_gcm_key_manager tink::aead::aes_gcm_parameters tink::internal::registry_impl tink::keyderivation::keyset_deriver tink::prf::hkdf_prf_key_manager tink::subtle::random tink::subtle::prf::streaming_prf tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::aes_gcm_cc_proto tink::proto::common_cc_proto tink::proto::hkdf_prf_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME prf_based_deriver_key_manager SRCS prf_based_deriver_key_manager.h DEPS tink::keyderivation::internal::prf_based_deriver absl::memory absl::status absl::strings tink::core::key_type_manager tink::core::template_util tink::core::registry tink::keyderivation::keyset_deriver tink::util::constants tink::util::status tink::util::statusor tink::util::validation tink::proto::prf_based_deriver_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME prf_based_deriver_key_manager_test SRCS prf_based_deriver_key_manager_test.cc DEPS tink::keyderivation::internal::prf_based_deriver tink::keyderivation::internal::prf_based_deriver_key_manager gmock absl::memory absl::status tink::core::cleartext_keyset_handle tink::core::keyset_handle tink::core::registry tink::aead::aead_key_templates tink::aead::aes_gcm_key_manager tink::keyderivation::keyset_deriver tink::prf::hkdf_prf_key_manager tink::subtle::subtle tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::aes_gcm_cc_proto tink::proto::hkdf_prf_cc_proto tink::proto::prf_based_deriver_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME key_derivers SRCS key_derivers.cc key_derivers.h DEPS absl::flat_hash_map absl::any_invocable absl::check absl::memory absl::status absl::strings absl::string_view absl::optional tink::core::input_stream tink::core::insecure_secret_key_access tink::core::key tink::core::parameters tink::core::partial_key_access tink::core::restricted_data tink::aead::aes_gcm_key tink::aead::aes_gcm_parameters tink::aead::aes_gcm_proto_serialization tink::util::input_stream_util tink::util::status tink::util::statusor tink::proto::aes_gcm_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME key_derivers_test SRCS key_derivers_test.cc DEPS tink::keyderivation::internal::key_derivers gmock absl::memory absl::status absl::optional tink::core::input_stream tink::core::insecure_secret_key_access tink::core::key tink::core::key_status tink::core::keyset_handle tink::core::keyset_handle_builder tink::core::partial_key_access tink::core::registry tink::core::restricted_data tink::core::secret_key_access_token tink::aead::aes_eax_parameters tink::aead::aes_eax_proto_serialization tink::aead::aes_gcm_key tink::aead::aes_gcm_key_manager tink::aead::aes_gcm_parameters tink::aead::aes_gcm_proto_serialization tink::internal::mutable_serialization_registry tink::internal::proto_parameters_serialization tink::internal::serialization tink::prf::hkdf_prf_key_manager tink::subtle::common_enums tink::subtle::random tink::subtle::prf::hkdf_streaming_prf tink::subtle::prf::streaming_prf tink::util::istream_input_stream tink::util::secret_data tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::aes_gcm_cc_proto tink::proto::common_cc_proto tink::proto::hkdf_prf_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME config_prf_for_deriver SRCS config_prf_for_deriver.h DEPS absl::check absl::memory tink::core::configuration tink::internal::configuration_impl tink::prf::hkdf_prf_key_manager ) tink_cc_test( NAME config_prf_for_deriver_test SRCS config_prf_for_deriver_test.cc DEPS tink::keyderivation::internal::config_prf_for_deriver gmock tink::internal::configuration_impl tink::internal::key_type_info_store tink::prf::hkdf_prf_key_manager tink::subtle::prf::streaming_prf tink::util::input_stream_util tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::tink_cc_proto ) ================================================ FILE: cc/keyderivation/internal/config_prf_for_deriver.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_KEYDERIVATION_INTERNAL_CONFIG_PRF_FOR_DERIVER_H_ #define TINK_KEYDERIVATION_INTERNAL_CONFIG_PRF_FOR_DERIVER_H_ #include "absl/log/check.h" #include "absl/memory/memory.h" #include "tink/configuration.h" #include "tink/internal/configuration_impl.h" #include "tink/prf/hkdf_prf_key_manager.h" namespace crypto { namespace tink { namespace internal { // Configuration used to generate unwrapped PRF primitives in // PrfBasedDeriver::New(). inline const Configuration& ConfigPrfForDeriver() { static const Configuration* instance = [] { static Configuration* config = new Configuration(); CHECK_OK(ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), *config)); return config; }(); return *instance; } } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_KEYDERIVATION_INTERNAL_CONFIG_PRF_FOR_DERIVER_H_ ================================================ FILE: cc/keyderivation/internal/config_prf_for_deriver_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/keyderivation/internal/config_prf_for_deriver.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/internal/configuration_impl.h" #include "tink/internal/key_type_info_store.h" #include "tink/prf/hkdf_prf_key_manager.h" #include "tink/subtle/prf/streaming_prf.h" #include "tink/util/input_stream_util.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::google::crypto::tink::HkdfPrfKey; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::SHA256; TEST(ConfigPrfForDeriverTest, KeyManager) { util::StatusOr store = ConfigurationImpl::GetKeyTypeInfoStore(ConfigPrfForDeriver()); ASSERT_THAT(store, IsOk()); EXPECT_THAT((*store)->Get(HkdfPrfKeyManager().get_key_type()), IsOk()); } TEST(ConfigPrfForDeriverTest, GetUnwrappedPrimitive) { util::StatusOr store = ConfigurationImpl::GetKeyTypeInfoStore(ConfigPrfForDeriver()); ASSERT_THAT(store, IsOk()); util::StatusOr info = (*store)->Get(HkdfPrfKeyManager().get_key_type()); ASSERT_THAT(info, IsOk()); HkdfPrfKey prf_key; prf_key.set_version(0); prf_key.set_key_value("01234567890123456789012345678901"); prf_key.mutable_params()->set_hash(SHA256); util::StatusOr> prf = (*info)->GetPrimitive( test::AsKeyData(prf_key, KeyData::SYMMETRIC)); ASSERT_THAT(prf, IsOk()); EXPECT_THAT(ReadBytesFromStream(32, (*prf)->ComputePrf("input").get()), IsOk()); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/keyderivation/internal/key_derivers.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/keyderivation/internal/key_derivers.h" #include #include #include #include #include "absl/container/flat_hash_map.h" #include "absl/functional/any_invocable.h" #include "absl/log/check.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/aead/aes_gcm_key.h" #include "tink/aead/aes_gcm_parameters.h" #include "tink/aead/aes_gcm_proto_serialization.h" #include "tink/input_stream.h" #include "tink/insecure_secret_key_access.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/util/input_stream_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/aes_gcm.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { using KeyDeriverFn = absl::AnyInvocable>( const Parameters&, InputStream*) const>; using KeyDeriverFnMap = absl::flat_hash_map; util::StatusOr> DeriveAesGcmKey( const Parameters& generic_params, InputStream* randomness) { const AesGcmParameters* params = dynamic_cast(&generic_params); if (params == nullptr) { return util::Status(absl::StatusCode::kInternal, "Parameters is not AesGcmParameters."); } util::StatusOr randomness_str = ReadBytesFromStream(params->KeySizeInBytes(), randomness); if (!randomness_str.ok()) { return randomness_str.status(); } util::StatusOr key = AesGcmKey::Create( *params, RestrictedData(*randomness_str, InsecureSecretKeyAccess::Get()), /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); if (!key.ok()) { return key.status(); } return absl::make_unique(*key); } const KeyDeriverFnMap& ParametersToKeyDeriver() { static const KeyDeriverFnMap* instance = [] { CHECK_OK(RegisterAesGcmProtoSerialization()); static KeyDeriverFnMap* m = new KeyDeriverFnMap(); m->insert({std::type_index(typeid(AesGcmParameters)), DeriveAesGcmKey}); return m; }(); return *instance; } util::StatusOr> DeriveKey(const Parameters& params, InputStream* randomness) { auto it = ParametersToKeyDeriver().find(std::type_index(typeid(params))); if (it == ParametersToKeyDeriver().end()) { return util::Status( absl::StatusCode::kUnimplemented, absl::StrCat("Key deriver not found for ", typeid(params).name())); } return it->second(params, randomness); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/keyderivation/internal/key_derivers.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_KEYDERIVATION_INTERNAL_KEY_DERIVERS_H_ #define TINK_KEYDERIVATION_INTERNAL_KEY_DERIVERS_H_ #include #include "tink/input_stream.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { crypto::tink::util::StatusOr> DeriveKey( const crypto::tink::Parameters& params, crypto::tink::InputStream* randomness); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_KEYDERIVATION_INTERNAL_KEY_DERIVERS_H_ ================================================ FILE: cc/keyderivation/internal/key_derivers_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/keyderivation/internal/key_derivers.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/aead/aes_eax_parameters.h" #include "tink/aead/aes_eax_proto_serialization.h" #include "tink/aead/aes_gcm_key.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/aead/aes_gcm_parameters.h" #include "tink/aead/aes_gcm_proto_serialization.h" #include "tink/input_stream.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/key_status.h" #include "tink/keyset_handle.h" #include "tink/keyset_handle_builder.h" #include "tink/partial_key_access.h" #include "tink/prf/hkdf_prf_key_manager.h" #include "tink/registry.h" #include "tink/restricted_data.h" #include "tink/secret_key_access_token.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/prf/hkdf_streaming_prf.h" #include "tink/subtle/prf/streaming_prf.h" #include "tink/subtle/random.h" #include "tink/util/istream_input_stream.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_gcm.pb.h" #include "proto/common.pb.h" #include "proto/hkdf_prf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::AesGcmKeyFormat; using ::google::crypto::tink::HashType; using ::google::crypto::tink::HkdfPrfKey; using ::google::crypto::tink::KeyData; using ::testing::Eq; using ::testing::IsTrue; using ::testing::NotNull; using ::testing::SizeIs; using ::testing::Test; class KeyDeriversTest : public Test { protected: void SetUp() override { util::StatusOr> streaming_prf = subtle::HkdfStreamingPrf::New( subtle::HashType::SHA256, util::SecretDataFromStringView(subtle::Random::GetRandomBytes(32)), "salty"); ASSERT_THAT(streaming_prf, IsOk()); randomness_ = (*streaming_prf)->ComputePrf("input"); } std::unique_ptr randomness_; }; TEST_F(KeyDeriversTest, DeriveKey) { int key_size = 16; util::StatusOr params = AesGcmParameters::Builder() .SetKeySizeInBytes(key_size) .SetIvSizeInBytes(12) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr> generic_key = DeriveKey(*params, randomness_.get()); ASSERT_THAT(generic_key, IsOk()); const AesGcmKey* key = dynamic_cast(&**std::move(generic_key)); ASSERT_THAT(key, NotNull()); EXPECT_THAT(key->GetIdRequirement(), Eq(absl::nullopt)); EXPECT_THAT(key->GetOutputPrefix(), Eq("")); EXPECT_THAT(key->GetKeyBytes(GetPartialKeyAccess()), SizeIs(key_size)); KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromCopyableKey(*key, KeyStatus::kEnabled, /*is_primary=*/true); EXPECT_THAT(KeysetHandleBuilder().AddEntry(std::move(entry)).Build(), IsOk()); } TEST_F(KeyDeriversTest, MissingKeyDeriverFn) { ASSERT_THAT(RegisterAesEaxProtoSerialization(), IsOk()); util::StatusOr params = AesEaxParameters::Builder() .SetKeySizeInBytes(16) .SetIvSizeInBytes(12) .SetTagSizeInBytes(12) .SetVariant(AesEaxParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(params, IsOk()); EXPECT_THAT(DeriveKey(*params, randomness_.get()).status(), StatusIs(absl::StatusCode::kUnimplemented)); } TEST_F(KeyDeriversTest, InsufficientRandomness) { util::StatusOr params = AesGcmParameters::Builder() .SetKeySizeInBytes(16) .SetIvSizeInBytes(12) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(params, IsOk()); util::IstreamInputStream insufficient_randomness{ absl::make_unique("0123456789")}; util::StatusOr> key = DeriveKey(*params, &insufficient_randomness); ASSERT_THAT(key.status(), StatusIs(absl::StatusCode::kOutOfRange)); } // Test vector from https://tools.ietf.org/html/rfc5869#appendix-A.2. class KeyDeriversRfcVectorTest : public Test { public: void SetUp() override { Registry::Reset(); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); HkdfPrfKey prf_key; prf_key.set_version(0); prf_key.mutable_params()->set_hash(HashType::SHA256); prf_key.mutable_params()->set_salt( test::HexDecodeOrDie("606162636465666768696a6b6c6d6e6f" "707172737475767778797a7b7c7d7e7f" "808182838485868788898a8b8c8d8e8f" "909192939495969798999a9b9c9d9e9f" "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf")); prf_key.set_key_value( test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f" "101112131415161718191a1b1c1d1e1f" "202122232425262728292a2b2c2d2e2f" "303132333435363738393a3b3c3d3e3f" "404142434445464748494a4b4c4d4e4f")); KeyData key_data = test::AsKeyData(prf_key, KeyData::SYMMETRIC); util::StatusOr> streaming_prf = Registry::GetPrimitive(key_data); ASSERT_THAT(streaming_prf, IsOk()); util::StatusOr> same_streaming_prf = Registry::GetPrimitive(key_data); ASSERT_THAT(same_streaming_prf, IsOk()); std::string salt = test::HexDecodeOrDie( "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"); randomness_from_rfc_vector_ = (*streaming_prf)->ComputePrf(salt); same_randomness_from_rfc_vector_ = (*same_streaming_prf)->ComputePrf(salt); } std::unique_ptr randomness_from_rfc_vector_; std::unique_ptr same_randomness_from_rfc_vector_; // The first 32 bytes of the vector's output key material (OKM). std::string derived_key_value_ = "b11e398dc80327a1c8e7f78c596a4934" "4f012eda2d4efad8a050cc4c19afa97c"; }; TEST_F(KeyDeriversRfcVectorTest, AesGcm) { // Derive key with hard-coded map. util::StatusOr params = AesGcmParameters::Builder() .SetKeySizeInBytes(32) .SetIvSizeInBytes(12) .SetTagSizeInBytes(16) .SetVariant(AesGcmParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr> generic_key = DeriveKey(*params, randomness_from_rfc_vector_.get()); ASSERT_THAT(generic_key, IsOk()); const AesGcmKey* key = dynamic_cast(&**std::move(generic_key)); ASSERT_THAT(key, NotNull()); std::string key_bytes = test::HexEncode(key->GetKeyBytes(GetPartialKeyAccess()) .GetSecret(InsecureSecretKeyAccess::Get())); ASSERT_THAT(key_bytes, Eq(derived_key_value_)); // Derive key with AesGcmKeyManager. ASSERT_THAT(RegisterAesGcmProtoSerialization(), IsOk()); util::StatusOr> serialization = MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialization, IsOk()); const ProtoParametersSerialization* proto_serialization = dynamic_cast(serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); AesGcmKeyFormat key_format; ASSERT_THAT( key_format.ParseFromString(proto_serialization->GetKeyTemplate().value()), IsTrue()); util::StatusOr proto_key = AesGcmKeyManager().DeriveKey(key_format, same_randomness_from_rfc_vector_.get()); ASSERT_THAT(proto_key, IsOk()); std::string proto_key_bytes = test::HexEncode(proto_key->key_value()); ASSERT_THAT(proto_key_bytes, Eq(derived_key_value_)); EXPECT_THAT(key_bytes, Eq(proto_key_bytes)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/keyderivation/internal/prf_based_deriver.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/keyderivation/internal/prf_based_deriver.h" #include #include #include "absl/memory/memory.h" #include "absl/strings/string_view.h" #include "tink/aead/aes_gcm_proto_serialization.h" #include "tink/cleartext_keyset_handle.h" #include "tink/input_stream.h" #include "tink/internal/configuration_impl.h" #include "tink/internal/key_type_info_store.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/registry_impl.h" #include "tink/key.h" #include "tink/key_status.h" #include "tink/keyderivation/internal/config_prf_for_deriver.h" #include "tink/keyderivation/internal/key_derivers.h" #include "tink/keyderivation/keyset_deriver.h" #include "tink/keyset_handle.h" #include "tink/keyset_handle_builder.h" #include "tink/parameters.h" #include "tink/subtle/prf/streaming_prf.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { using ::google::crypto::tink::KeyData; using ::google::crypto::tink::Keyset; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::OutputPrefixType; util::StatusOr> DeriveWithGlobalRegistry( const KeyTemplate& key_template, InputStream& randomness) { util::StatusOr key_data = RegistryImpl::GlobalInstance().DeriveKey(key_template, &randomness); if (!key_data.ok()) { return key_data.status(); } // Fill placeholders key ID 0, OutputPrefixType::UNKNOWN_PREFIX, and // KeyStatusType::UNKNOWN_STATUS. // Tink users interact with this keyset only after it has been processed by // KeysetDeriverSetWrapper::DeriveKeyset, which uses // google::crypto::tink::KeyData's value field (the serialized *Key proto) and // nothing else. // http://google3/third_party/tink/cc/keyderivation/keyset_deriver_wrapper.cc;l=88-91;rcl=592310815 Keyset::Key key; *key.mutable_key_data() = *key_data; key.set_key_id(0); key.set_output_prefix_type(OutputPrefixType::UNKNOWN_PREFIX); key.set_status(KeyStatusType::UNKNOWN_STATUS); Keyset keyset; *keyset.add_key() = key; keyset.set_primary_key_id(0); return CleartextKeysetHandle::GetKeysetHandle(keyset); } util::StatusOr> DeriveWithHardCodedMap( const KeyTemplate& key_template, InputStream& randomness) { // Fill placeholders OutputPrefixType::RAW and KeyStatus::kEnabled. // Tink users interact with this keyset only after it has been processed by // KeysetDeriverSetWrapper::DeriveKeyset, which uses // google::crypto::tink::KeyData's value field (the serialized *Key proto) and // nothing else. // http://google3/third_party/tink/cc/keyderivation/keyset_deriver_wrapper.cc;l=88-91;rcl=592310815 util::StatusOr serialization = ProtoParametersSerialization::Create( key_template.type_url(), OutputPrefixType::RAW, key_template.value()); if (!serialization.ok()) { return serialization.status(); } util::StatusOr> params = MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); if (!params.ok()) { return params.status(); } util::StatusOr> key = DeriveKey(**std::move(params), &randomness); if (!key.ok()) { return key.status(); } KeysetHandleBuilder::Entry entry = KeysetHandleBuilder::Entry::CreateFromKey( *std::move(key), KeyStatus::kEnabled, /*is_primary=*/true); util::StatusOr handle = KeysetHandleBuilder().AddEntry(std::move(entry)).Build(); if (!handle.ok()) { return handle.status(); } return absl::make_unique(*handle); } util::StatusOr> DeriveKeysetHandle( const KeyTemplate& key_template, InputStream& randomness) { util::StatusOr> handle = DeriveWithGlobalRegistry(key_template, randomness); if (!handle.ok()) { return DeriveWithHardCodedMap(key_template, randomness); } return *std::move(handle); } util::Status RegisterProtoSerializations() { return RegisterAesGcmProtoSerialization(); } util::StatusOr> GetUnwrappedStreamingPrf( const KeyData& prf_key) { util::StatusOr store = ConfigurationImpl::GetKeyTypeInfoStore(ConfigPrfForDeriver()); if (!store.ok()) { return store.status(); } util::StatusOr info = (*store)->Get(prf_key.type_url()); if (!info.ok()) { return info.status(); } return (*info)->GetPrimitive(prf_key); } util::StatusOr> PrfBasedDeriver::New( const KeyData& prf_key, const KeyTemplate& key_template) { // Create unwrapped StreamingPrf primitive from `prf_key`. util::StatusOr> streaming_prf = GetUnwrappedStreamingPrf(prf_key); if (!streaming_prf.ok()) { return streaming_prf.status(); } util::Status status = RegisterProtoSerializations(); if (!status.ok()) { return status; } // Validate `key_template`. std::unique_ptr randomness = (*streaming_prf)->ComputePrf("s"); util::StatusOr> handle = DeriveKeysetHandle(key_template, *randomness); if (!handle.ok()) { return handle.status(); } return {absl::WrapUnique( new PrfBasedDeriver(*std::move(streaming_prf), key_template))}; } util::StatusOr> PrfBasedDeriver::DeriveKeyset( absl::string_view salt) const { std::unique_ptr randomness = streaming_prf_->ComputePrf(salt); return DeriveKeysetHandle(key_template_, *randomness); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/keyderivation/internal/prf_based_deriver.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_KEYDERIVATION_INTERNAL_PRF_BASED_DERIVER_H_ #define TINK_KEYDERIVATION_INTERNAL_PRF_BASED_DERIVER_H_ #include #include #include "absl/strings/string_view.h" #include "tink/keyderivation/keyset_deriver.h" #include "tink/keyset_handle.h" #include "tink/subtle/prf/streaming_prf.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { // The PrfBasedDeriver first uses a PRF to get some randomness, then gives this // to the Tink registry to derive a key. class PrfBasedDeriver : public KeysetDeriver { public: static crypto::tink::util::StatusOr> New( const ::google::crypto::tink::KeyData& prf_key, const ::google::crypto::tink::KeyTemplate& key_template); crypto::tink::util::StatusOr> DeriveKeyset( absl::string_view salt) const override; private: PrfBasedDeriver(std::unique_ptr streaming_prf, const ::google::crypto::tink::KeyTemplate& key_template) : streaming_prf_(std::move(streaming_prf)), key_template_(key_template) {} const ::std::unique_ptr streaming_prf_; const ::google::crypto::tink::KeyTemplate key_template_; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_KEYDERIVATION_INTERNAL_PRF_BASED_DERIVER_H_ ================================================ FILE: cc/keyderivation/internal/prf_based_deriver_key_manager.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_KEYDERIVATION_INTERNAL_PRF_BASED_DERIVER_KEY_MANAGER_H_ #define TINK_KEYDERIVATION_INTERNAL_PRF_BASED_DERIVER_KEY_MANAGER_H_ #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/keyderivation/internal/prf_based_deriver.h" #include "tink/keyderivation/keyset_deriver.h" #include "tink/registry.h" #include "tink/util/constants.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/prf_based_deriver.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { class PrfBasedDeriverKeyManager : public KeyTypeManager> { public: class KeysetDeriverFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::PrfBasedDeriverKey& key) const override { return internal::PrfBasedDeriver::New( key.prf_key(), key.params().derived_key_template()); } }; PrfBasedDeriverKeyManager() : KeyTypeManager(absl::make_unique< PrfBasedDeriverKeyManager::KeysetDeriverFactory>()) {} // Returns the version of this key manager. uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::SYMMETRIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::PrfBasedDeriverKey& key) const override { crypto::tink::util::Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; if (!key.has_prf_key()) { return crypto::tink::util::Status(absl::StatusCode::kInvalidArgument, "key.prf_key() must be set"); } if (!key.params().has_derived_key_template()) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, "key.params().derived_key_template() must be set"); } return util::OkStatus(); } crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::PrfBasedDeriverKeyFormat& key_format) const override { if (!key_format.has_prf_key_template()) { return crypto::tink::util::Status(absl::StatusCode::kInvalidArgument, "key.prf_key_template() must be set"); } if (!key_format.params().has_derived_key_template()) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, "key_format.params().derived_key_template() must be set"); } return util::OkStatus(); } crypto::tink::util::StatusOr CreateKey(const google::crypto::tink::PrfBasedDeriverKeyFormat& key_format) const override { crypto::tink::util::StatusOr> prf_key = CreateKeyData(key_format.prf_key_template()); if (!prf_key.ok()) return prf_key.status(); // Java and Go implementations perform additional verification by getting a // StreamingPrf primitive from the registry and trying to derive // `key_format.params().derived_key_template()` with a fake salt. This is // currently not possible in C++. google::crypto::tink::PrfBasedDeriverKey key; key.set_version(get_version()); *key.mutable_params()->mutable_derived_key_template() = key_format.params().derived_key_template(); *key.mutable_prf_key() = **std::move(prf_key); return key; } protected: virtual crypto::tink::util::StatusOr< std::unique_ptr> CreateKeyData(const google::crypto::tink::KeyTemplate& key_template) const { return Registry::NewKeyData(key_template); } private: const std::string key_type_ = absl::StrCat(kTypeGoogleapisCom, google::crypto::tink::PrfBasedDeriverKey().GetTypeName()); }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_KEYDERIVATION_INTERNAL_PRF_BASED_DERIVER_KEY_MANAGER_H_ ================================================ FILE: cc/keyderivation/internal/prf_based_deriver_key_manager_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/keyderivation/internal/prf_based_deriver_key_manager.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/aead/aead_key_templates.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/cleartext_keyset_handle.h" #include "tink/keyderivation/internal/prf_based_deriver.h" #include "tink/keyderivation/keyset_deriver.h" #include "tink/keyset_handle.h" #include "tink/prf/hkdf_prf_key_manager.h" #include "tink/registry.h" #include "tink/subtle/random.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_gcm.pb.h" #include "proto/hkdf_prf.pb.h" #include "proto/prf_based_deriver.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::AesGcmKey; using ::google::crypto::tink::HashType; using ::google::crypto::tink::HkdfPrfKey; using ::google::crypto::tink::HkdfPrfKeyFormat; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::Keyset; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::PrfBasedDeriverKey; using ::google::crypto::tink::PrfBasedDeriverKeyFormat; using ::testing::Eq; using ::testing::SizeIs; TEST(PrfBasedDeriverKeyManagerTest, Basics) { EXPECT_THAT(PrfBasedDeriverKeyManager().get_version(), Eq(0)); EXPECT_THAT(PrfBasedDeriverKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.PrfBasedDeriverKey")); EXPECT_THAT(PrfBasedDeriverKeyManager().key_material_type(), Eq(KeyData::SYMMETRIC)); } TEST(PrfBasedDeriverKeyManagerTest, ValidateKeyEmpty) { EXPECT_THAT(PrfBasedDeriverKeyManager().ValidateKey(PrfBasedDeriverKey()), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(PrfBasedDeriverKeyManagerTest, ValidateKey) { HkdfPrfKey prf_key; prf_key.set_version(0); prf_key.set_key_value("0123456789abcdef"); prf_key.mutable_params()->set_hash(HashType::SHA256); PrfBasedDeriverKey key; key.set_version(0); *key.mutable_prf_key() = test::AsKeyData(prf_key, KeyData::SYMMETRIC); *key.mutable_params()->mutable_derived_key_template() = AeadKeyTemplates::Aes256Gcm(); EXPECT_THAT(PrfBasedDeriverKeyManager().ValidateKey(key), IsOk()); } TEST(PrfBasedDeriverKeyManagerTest, ValidateKeyWithWrongVersion) { HkdfPrfKey prf_key; prf_key.set_version(0); prf_key.set_key_value("0123456789abcdef"); prf_key.mutable_params()->set_hash(HashType::SHA256); PrfBasedDeriverKey key; key.set_version(1); *key.mutable_prf_key() = test::AsKeyData(prf_key, KeyData::SYMMETRIC); *key.mutable_params()->mutable_derived_key_template() = AeadKeyTemplates::Aes256Gcm(); EXPECT_THAT(PrfBasedDeriverKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(PrfBasedDeriverKeyManagerTest, ValidateKeyFormat) { HkdfPrfKeyFormat prf_key_format; prf_key_format.set_key_size(16); prf_key_format.mutable_params()->set_hash(HashType::SHA256); PrfBasedDeriverKeyFormat key_format; key_format.mutable_prf_key_template()->set_type_url( HkdfPrfKeyManager().get_key_type()); key_format.mutable_prf_key_template()->set_value( prf_key_format.SerializeAsString()); *key_format.mutable_params()->mutable_derived_key_template() = AeadKeyTemplates::Aes256Gcm(); EXPECT_THAT(PrfBasedDeriverKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(PrfBasedDeriverKeyManagerTest, ValidateKeyFormatEmpty) { EXPECT_THAT( PrfBasedDeriverKeyManager().ValidateKeyFormat(PrfBasedDeriverKeyFormat()), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(PrfBasedDeriverKeyManagerTest, CreateKey) { Registry::Reset(); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); HkdfPrfKeyFormat prf_key_format; prf_key_format.set_key_size(32); prf_key_format.mutable_params()->set_hash(HashType::SHA256); PrfBasedDeriverKeyFormat key_format; key_format.mutable_prf_key_template()->set_type_url( HkdfPrfKeyManager().get_key_type()); key_format.mutable_prf_key_template()->set_value( prf_key_format.SerializeAsString()); *key_format.mutable_params()->mutable_derived_key_template() = AeadKeyTemplates::Aes256Gcm(); util::StatusOr key = PrfBasedDeriverKeyManager().CreateKey(key_format); ASSERT_THAT(key, IsOk()); EXPECT_THAT((*key).version(), Eq(0)); EXPECT_THAT((*key).prf_key().type_url(), Eq(HkdfPrfKeyManager().get_key_type())); EXPECT_THAT((*key).prf_key().key_material_type(), Eq(KeyData::SYMMETRIC)); HkdfPrfKey prf_key; ASSERT_TRUE(prf_key.ParseFromString((*key).prf_key().value())); EXPECT_THAT(prf_key.key_value().size(), Eq(32)); EXPECT_THAT((*key).params().derived_key_template().type_url(), Eq(key_format.params().derived_key_template().type_url())); EXPECT_THAT((*key).params().derived_key_template().value(), Eq(key_format.params().derived_key_template().value())); } TEST(PrfBasedDeriverKeyManagerTest, CreateKeyWithInvalidPrfKey) { Registry::Reset(); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); HkdfPrfKeyFormat prf_key_format; prf_key_format.set_key_size(32); prf_key_format.mutable_params()->set_hash(HashType::UNKNOWN_HASH); PrfBasedDeriverKeyFormat key_format; key_format.mutable_prf_key_template()->set_type_url( HkdfPrfKeyManager().get_key_type()); key_format.mutable_prf_key_template()->set_value( prf_key_format.SerializeAsString()); *key_format.mutable_params()->mutable_derived_key_template() = AeadKeyTemplates::Aes256Gcm(); EXPECT_THAT(PrfBasedDeriverKeyManager().CreateKey(key_format).status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(PrfBasedDeriverKeyManagerTest, CreateKeyWithInvalidDerivedKeyTemplate) { Registry::Reset(); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); HkdfPrfKeyFormat prf_key_format; prf_key_format.set_key_size(32); prf_key_format.mutable_params()->set_hash(HashType::SHA256); KeyTemplate derived_template; derived_template.set_type_url("nonexistent.type.url"); PrfBasedDeriverKeyFormat key_format; key_format.mutable_prf_key_template()->set_type_url( HkdfPrfKeyManager().get_key_type()); key_format.mutable_prf_key_template()->set_value( prf_key_format.SerializeAsString()); *key_format.mutable_params()->mutable_derived_key_template() = derived_template; // See comment in PrfBasedDeriverKeyManager::CreateKey(). EXPECT_THAT(PrfBasedDeriverKeyManager().CreateKey(key_format).status(), IsOk()); } TEST(PrfBasedDeriverKeyManagerTest, GetPrimitive) { Registry::Reset(); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); HkdfPrfKey prf_key; prf_key.set_version(0); prf_key.mutable_params()->set_hash(HashType::SHA256); prf_key.mutable_params()->set_salt(subtle::Random::GetRandomBytes(15)); prf_key.set_key_value(subtle::Random::GetRandomBytes(33)); prf_key.mutable_params()->set_hash(HashType::SHA256); PrfBasedDeriverKey key; key.set_version(0); *key.mutable_prf_key() = test::AsKeyData(prf_key, KeyData::SYMMETRIC); *key.mutable_params()->mutable_derived_key_template() = AeadKeyTemplates::Aes256Gcm(); StatusOr> deriver = PrfBasedDeriverKeyManager().GetPrimitive(key); ASSERT_THAT(deriver, IsOk()); std::string salt = subtle::Random::GetRandomBytes(23); util::StatusOr> handle = (*deriver)->DeriveKeyset(salt); ASSERT_THAT(handle, IsOk()); Keyset keyset = CleartextKeysetHandle::GetKeyset(**handle); StatusOr> direct_deriver = internal::PrfBasedDeriver::New(key.prf_key(), key.params().derived_key_template()); ASSERT_THAT(direct_deriver, IsOk()); util::StatusOr> direct_handle = (*direct_deriver)->DeriveKeyset(salt); ASSERT_THAT(direct_handle, IsOk()); Keyset direct_keyset = CleartextKeysetHandle::GetKeyset(**direct_handle); ASSERT_THAT(keyset.key(), SizeIs(1)); ASSERT_THAT(direct_keyset.key(), SizeIs(1)); ASSERT_THAT(keyset.key(0).key_data().type_url(), Eq(keyset.key(0).key_data().type_url())); AesGcmKey derived_key; ASSERT_TRUE(derived_key.ParseFromString(keyset.key(0).key_data().value())); AesGcmKey direct_derived_key; ASSERT_TRUE(direct_derived_key.ParseFromString( direct_keyset.key(0).key_data().value())); EXPECT_THAT(derived_key.key_value(), Eq(direct_derived_key.key_value())); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/keyderivation/internal/prf_based_deriver_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/keyderivation/internal/prf_based_deriver.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/aead/aead_key_templates.h" #include "tink/aead/aes_ctr_hmac_aead_key_manager.h" #include "tink/aead/aes_gcm_key.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/aead/aes_gcm_parameters.h" #include "tink/cleartext_keyset_handle.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/registry_impl.h" #include "tink/key_status.h" #include "tink/keyderivation/keyset_deriver.h" #include "tink/keyset_handle.h" #include "tink/partial_key_access.h" #include "tink/prf/hkdf_prf_key_manager.h" #include "tink/registry.h" #include "tink/subtle/prf/streaming_prf.h" #include "tink/subtle/random.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_gcm.pb.h" #include "proto/common.pb.h" #include "proto/hkdf_prf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::HashType; using ::google::crypto::tink::HkdfPrfKey; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::Keyset; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::Ne; using ::testing::NotNull; using ::testing::SizeIs; using ::testing::Test; using ::testing::TestWithParam; using ::testing::ValuesIn; class PrfBasedDeriverTest : public Test { public: KeyData valid_prf_key_data_ = PrfKeyData(); HkdfPrfKey valid_prf_key_ = PrfKey(); private: HkdfPrfKey PrfKey() { HkdfPrfKey prf_key; prf_key.set_version(0); prf_key.mutable_params()->set_hash(HashType::SHA256); prf_key.mutable_params()->set_salt(""); prf_key.set_key_value("0123456789abcdef0123456789abcdef"); return prf_key; } KeyData PrfKeyData() { return test::AsKeyData(PrfKey(), KeyData::SYMMETRIC); } }; TEST_F(PrfBasedDeriverTest, New) { EXPECT_THAT( PrfBasedDeriver::New(valid_prf_key_data_, AeadKeyTemplates::Aes128Gcm()), IsOk()); } TEST_F(PrfBasedDeriverTest, NewWithInvalidPrfKey) { HkdfPrfKey invalid_prf_key = valid_prf_key_; invalid_prf_key.mutable_params()->set_hash(HashType::UNKNOWN_HASH); EXPECT_THAT( PrfBasedDeriver::New(test::AsKeyData(invalid_prf_key, KeyData::SYMMETRIC), AeadKeyTemplates::Aes128Gcm()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(PrfBasedDeriverTest, NewWithInvalidDerivedKeyTemplate) { KeyTemplate invalid_derived_template; invalid_derived_template.set_type_url("i.do.not.exist"); EXPECT_THAT(PrfBasedDeriver::New( test::AsKeyData(valid_prf_key_data_, KeyData::SYMMETRIC), invalid_derived_template) .status(), StatusIs(absl::StatusCode::kNotFound)); } TEST_F(PrfBasedDeriverTest, DeriveKeysetPlaceholders) { util::StatusOr> deriver = PrfBasedDeriver::New(valid_prf_key_data_, AeadKeyTemplates::Aes128Gcm()); ASSERT_THAT(deriver, IsOk()); util::StatusOr> handle = (*deriver)->DeriveKeyset("salt"); ASSERT_THAT(handle, IsOk()); ASSERT_THAT(**handle, SizeIs(1)); // Verify placeholders. KeysetHandle::Entry primary = (*handle)->GetPrimary(); const AesGcmKey* key = dynamic_cast(primary.GetKey().get()); ASSERT_THAT(key, NotNull()); EXPECT_THAT(key->GetParameters().GetVariant(), Eq(AesGcmParameters::Variant::kNoPrefix)); EXPECT_THAT(primary.GetStatus(), Eq(KeyStatus::kEnabled)); // Verify derived key ID. EXPECT_THAT(key->GetIdRequirement(), Eq(absl::nullopt)); // Verify primary key ID, which is generated when the KeysetHandle is built. // http://google3/third_party/tink/cc/core/keyset_handle_builder.cc;l=163;rcl=604267117 EXPECT_THAT(CleartextKeysetHandle::GetKeyset(**handle).primary_key_id(), Ne(0)); } TEST_F(PrfBasedDeriverTest, DeriveKeysetPlaceholdersWithGlobalRegistry) { Registry::Reset(); ASSERT_THAT(PrfBasedDeriver::New(valid_prf_key_data_, AeadKeyTemplates::Aes128CtrHmacSha256()) .status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); util::StatusOr> deriver = PrfBasedDeriver::New( valid_prf_key_data_, AeadKeyTemplates::Aes128CtrHmacSha256()); ASSERT_THAT(deriver, IsOk()); util::StatusOr> handle = (*deriver)->DeriveKeyset("salt"); ASSERT_THAT(handle, IsOk()); ASSERT_THAT(**handle, SizeIs(1)); // Verify placeholders. Keyset keyset = CleartextKeysetHandle::GetKeyset(**handle); EXPECT_THAT(keyset.key(0).output_prefix_type(), Eq(OutputPrefixType::UNKNOWN_PREFIX)); EXPECT_THAT(keyset.key(0).status(), Eq(KeyStatusType::UNKNOWN_STATUS)); // Verify primary key ID and derived key ID are both 0. EXPECT_THAT(keyset.primary_key_id(), Eq(0)); EXPECT_THAT(keyset.key(0).key_id(), Eq(0)); } TEST_F(PrfBasedDeriverTest, DeriveKeysetWithDifferentPrfKeys) { google::crypto::tink::AesGcmKey derived_key_0; google::crypto::tink::AesGcmKey derived_key_1; KeyTemplate key_template = AeadKeyTemplates::Aes128Gcm(); std::string salt = "salt"; { util::StatusOr> deriver = PrfBasedDeriver::New(valid_prf_key_data_, key_template); ASSERT_THAT(deriver, IsOk()); util::StatusOr> handle = (*deriver)->DeriveKeyset(salt); ASSERT_THAT(handle, IsOk()); Keyset keyset = CleartextKeysetHandle::GetKeyset(**handle); ASSERT_TRUE( derived_key_0.ParseFromString(keyset.key(0).key_data().value())); } { HkdfPrfKey different_prf_key = valid_prf_key_; different_prf_key.set_key_value(subtle::Random::GetRandomBytes(32)); KeyData different_key_data = test::AsKeyData(different_prf_key, KeyData::SYMMETRIC); util::StatusOr> deriver = PrfBasedDeriver::New(different_key_data, key_template); ASSERT_THAT(deriver, IsOk()); util::StatusOr> handle = (*deriver)->DeriveKeyset(salt); ASSERT_THAT(handle, IsOk()); Keyset keyset = CleartextKeysetHandle::GetKeyset(**handle); ASSERT_TRUE( derived_key_1.ParseFromString(keyset.key(0).key_data().value())); } EXPECT_THAT(derived_key_0.key_value(), SizeIs(16)); EXPECT_THAT(derived_key_1.key_value(), SizeIs(16)); EXPECT_THAT(derived_key_0.key_value(), Ne(derived_key_1.key_value())); } TEST_F(PrfBasedDeriverTest, DeriveKeysetWithDifferentSalts) { util::StatusOr> deriver = PrfBasedDeriver::New(valid_prf_key_data_, AeadKeyTemplates::Aes128Gcm()); ASSERT_THAT(deriver, IsOk()); google::crypto::tink::AesGcmKey derived_key_0; google::crypto::tink::AesGcmKey derived_key_1; { util::StatusOr> handle = (*deriver)->DeriveKeyset("salt"); ASSERT_THAT(handle, IsOk()); Keyset keyset = CleartextKeysetHandle::GetKeyset(**handle); ASSERT_TRUE( derived_key_0.ParseFromString(keyset.key(0).key_data().value())); } { util::StatusOr> handle = (*deriver)->DeriveKeyset("different_salt"); ASSERT_THAT(handle, IsOk()); Keyset keyset = CleartextKeysetHandle::GetKeyset(**handle); ASSERT_TRUE( derived_key_1.ParseFromString(keyset.key(0).key_data().value())); } EXPECT_THAT(derived_key_0.key_value(), SizeIs(16)); EXPECT_THAT(derived_key_1.key_value(), SizeIs(16)); EXPECT_THAT(derived_key_0.key_value(), Ne(derived_key_1.key_value())); } // Test vector from https://tools.ietf.org/html/rfc5869#appendix-A.2. class PrfBasedDeriverRfcVectorTest : public Test { public: KeyData prf_key_from_rfc_vector_ = PrfKeyData(); std::string salt_ = test::HexDecodeOrDie( "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"); // The first 32 bytes of the vector's output key material (OKM). std::string derived_key_value_ = "b11e398dc80327a1c8e7f78c596a4934" "4f012eda2d4efad8a050cc4c19afa97c"; private: KeyData PrfKeyData() { HkdfPrfKey prf_key; prf_key.set_version(0); prf_key.mutable_params()->set_hash(HashType::SHA256); prf_key.mutable_params()->set_salt( test::HexDecodeOrDie("606162636465666768696a6b6c6d6e6f" "707172737475767778797a7b7c7d7e7f" "808182838485868788898a8b8c8d8e8f" "909192939495969798999a9b9c9d9e9f" "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf")); prf_key.set_key_value( test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f" "101112131415161718191a1b1c1d1e1f" "202122232425262728292a2b2c2d2e2f" "303132333435363738393a3b3c3d3e3f" "404142434445464748494a4b4c4d4e4f")); return test::AsKeyData(prf_key, KeyData::SYMMETRIC); } }; TEST_F(PrfBasedDeriverRfcVectorTest, AesGcm) { KeyTemplate key_template = AeadKeyTemplates::Aes256Gcm(); // Derive key with hard-coded map. util::StatusOr> deriver = PrfBasedDeriver::New(prf_key_from_rfc_vector_, key_template); ASSERT_THAT(deriver, IsOk()); util::StatusOr> handle = (*deriver)->DeriveKeyset(salt_); ASSERT_THAT(handle, IsOk()); const AesGcmKey* key = dynamic_cast((*handle)->GetPrimary().GetKey().get()); ASSERT_THAT(key, NotNull()); std::string key_bytes = test::HexEncode(key->GetKeyBytes(GetPartialKeyAccess()) .GetSecret(InsecureSecretKeyAccess::Get())); ASSERT_THAT(key_bytes, Eq(derived_key_value_)); // Derive key with global registry. Registry::Reset(); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); util::StatusOr> streaming_prf = Registry::GetPrimitive(prf_key_from_rfc_vector_); ASSERT_THAT(streaming_prf, IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); util::StatusOr proto_generic_key = RegistryImpl::GlobalInstance().DeriveKey( key_template, (*streaming_prf)->ComputePrf(salt_).get()); ASSERT_THAT(proto_generic_key, IsOk()); google::crypto::tink::AesGcmKey proto_key; ASSERT_TRUE(proto_key.ParseFromString(proto_generic_key->value())); std::string proto_key_bytes = test::HexEncode(proto_key.key_value()); ASSERT_THAT(proto_key_bytes, Eq(derived_key_value_)); EXPECT_THAT(key_bytes, Eq(proto_key_bytes)); } struct PrfBasedDeriverJavaVector { std::string prf_key_value; std::string deriving_salt; std::string derived_key_value; }; // Test vectors generated with the Tink Java implementation. std::vector GetPrfBasedDeriverJavaVectors() { return { { /*prf_key_value=*/test::HexDecodeOrDie( "a1a2a3a4a5a6a7a8a9aaabacadaeafb1b2b3b4b5b6b7b8b9babbbcbdbebf" "c1c2c3c4c5c6c7c8c9cacbcccdcecfc1c2c3c4c5c6c7c8c9cacbcccdcecf" "00"), /*deriving_salt=*/test::HexDecodeOrDie("1122334455"), /*derived_key_value=*/"31c449af66b669b9963ef2df30dfe5f9", }, { /*prf_key_value=*/test::HexDecodeOrDie( "c1c2c3c4c5c6c7c8c9cacbcccdcecfc1c2c3c4c5c6c7c8c9cacbcccdcecf" "a1a2a3a4a5a6a7a8a9aaabacadaeafb1b2b3b4b5b6b7b8b9babbbcbdbebf"), /*deriving_salt=*/test::HexDecodeOrDie("00"), /*derived_key_value=*/"887af0808c1855eba1594bf540adb957", }, { /*prf_key_value=*/test::HexDecodeOrDie( "c1c2c3c4c5c6c7c8c9cacbcccdcecfc1c2c3c4c5c6c7c8c9cacbcccdcecf" "a1a2a3a4a5a6a7a8a9aaabacadaeafb1b2b3b4b5b6b7b8b9babbbcbdbebf"), /*deriving_salt=*/"", /*derived_key_value=*/"fb2b448c2595caf75129e282af758bf1", }, }; } using PrfBasedDeriverJavaVectorsTest = TestWithParam; INSTANTIATE_TEST_SUITE_P(PrfBasedDeriverJavaVectorsTests, PrfBasedDeriverJavaVectorsTest, ValuesIn(GetPrfBasedDeriverJavaVectors())); TEST_P(PrfBasedDeriverJavaVectorsTest, AesGcm) { PrfBasedDeriverJavaVector test_vector = GetParam(); HkdfPrfKey prf_key; prf_key.set_version(0); prf_key.mutable_params()->set_hash(HashType::SHA512); prf_key.set_key_value(test_vector.prf_key_value); KeyData key_data = test::AsKeyData(prf_key, KeyData::SYMMETRIC); util::StatusOr> deriver = PrfBasedDeriver::New(key_data, AeadKeyTemplates::Aes128Gcm()); ASSERT_THAT(deriver, IsOk()); util::StatusOr> handle = (*deriver)->DeriveKeyset(test_vector.deriving_salt); ASSERT_THAT(handle, IsOk()); Keyset keyset = CleartextKeysetHandle::GetKeyset(**handle); google::crypto::tink::AesGcmKey derived_key; ASSERT_TRUE(derived_key.ParseFromString(keyset.key(0).key_data().value())); EXPECT_THAT(derived_key.version(), Eq(AesGcmKeyManager().get_version())); EXPECT_THAT(test::HexEncode(derived_key.key_value()), Eq(test_vector.derived_key_value)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/keyderivation/key_derivation_config.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/keyderivation/key_derivation_config.h" #include "absl/memory/memory.h" #include "tink/config/tink_fips.h" #include "tink/keyderivation/internal/prf_based_deriver_key_manager.h" #include "tink/keyderivation/keyset_deriver_wrapper.h" #include "tink/prf/hkdf_prf_key_manager.h" #include "tink/registry.h" #include "tink/util/status.h" namespace crypto { namespace tink { // static util::Status KeyDerivationConfig::Register() { // Register primitive wrappers. util::Status status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) { return status; } // Currently, no KeysetDeriver key managers only use FIPS-validated // implementations, so none are registered in FIPS-only mode. if (IsFipsModeEnabled()) { return util::OkStatus(); } // Register required key manager for PrfBasedDeriverKeyManager. status = Registry::RegisterKeyTypeManager( absl::make_unique(), true); if (!status.ok()) { return status; } // Register key managers. return Registry::RegisterKeyTypeManager( absl::make_unique(), true); } } // namespace tink } // namespace crypto ================================================ FILE: cc/keyderivation/key_derivation_config.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_KEYDERIVATION_KEY_DERIVATION_CONFIG_H_ #define TINK_KEYDERIVATION_KEY_DERIVATION_CONFIG_H_ #include "tink/util/status.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Static methods and constants for registering to the Registry all // KeysetDeriver key types supported in a particular release of Tink. // // To register all KeysetDeriver key types, one can do: // // crypto::tink::util::Status status = KeyDerivationConfig::Register(); // class KeyDerivationConfig { public: // Registers KeysetDeriver primitive wrapper and key managers for all // KeyDerivation key types from the current Tink release. static crypto::tink::util::Status Register(); private: KeyDerivationConfig() {} }; } // namespace tink } // namespace crypto #endif // TINK_KEYDERIVATION_KEY_DERIVATION_CONFIG_H_ ================================================ FILE: cc/keyderivation/key_derivation_config_test.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/keyderivation/key_derivation_config.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "tink/aead.h" #include "tink/aead/aead_config.h" #include "tink/aead/aead_key_templates.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/config/global_registry.h" #include "tink/keyderivation/key_derivation_key_templates.h" #include "tink/keyderivation/keyset_deriver.h" #include "tink/keyset_handle.h" #include "tink/prf/prf_key_templates.h" #include "tink/registry.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::testing::Not; TEST(KeyDerivationConfigTest, Register) { Registry::Reset(); EXPECT_THAT(KeyDerivationKeyTemplates::CreatePrfBasedKeyTemplate( PrfKeyTemplates::HkdfSha256(), AeadKeyTemplates::Aes256Gcm()), Not(IsOk())); ASSERT_THAT(KeyDerivationConfig::Register(), IsOk()); ASSERT_THAT(AeadConfig::Register(), IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); util::StatusOr<::google::crypto::tink::KeyTemplate> templ = KeyDerivationKeyTemplates::CreatePrfBasedKeyTemplate( PrfKeyTemplates::HkdfSha256(), AeadKeyTemplates::Aes256Gcm()); ASSERT_THAT(templ, IsOk()); util::StatusOr> handle = KeysetHandle::GenerateNew(*templ, KeyGenConfigGlobalRegistry()); ASSERT_THAT(handle, IsOk()); util::StatusOr> deriver = (*handle)->GetPrimitive( ConfigGlobalRegistry()); ASSERT_THAT(deriver, IsOk()); util::StatusOr> derived_handle = (*deriver)->DeriveKeyset("salty"); ASSERT_THAT(derived_handle, IsOk()); util::StatusOr> aead = (*derived_handle) ->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(aead, IsOk()); std::string plaintext = "plaintext"; std::string ad = "ad"; util::StatusOr ciphertext = (*aead)->Encrypt(plaintext, ad); ASSERT_THAT(ciphertext, IsOk()); util::StatusOr got = (*aead)->Decrypt(*ciphertext, ad); ASSERT_THAT(got, IsOk()); EXPECT_EQ(plaintext, *got); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/keyderivation/key_derivation_key_templates.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/keyderivation/key_derivation_key_templates.h" #include #include "tink/config/global_registry.h" #include "tink/keyderivation/internal/prf_based_deriver_key_manager.h" #include "tink/keyderivation/keyset_deriver.h" #include "tink/keyset_handle.h" #include "tink/util/statusor.h" #include "proto/prf_based_deriver.pb.h" namespace crypto { namespace tink { using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::PrfBasedDeriverKeyFormat; util::StatusOr KeyDerivationKeyTemplates::CreatePrfBasedKeyTemplate( const KeyTemplate& prf_key_template, const KeyTemplate& derived_key_template) { KeyTemplate key_template; key_template.set_type_url( internal::PrfBasedDeriverKeyManager().get_key_type()); key_template.set_output_prefix_type( derived_key_template.output_prefix_type()); PrfBasedDeriverKeyFormat format; *format.mutable_prf_key_template() = prf_key_template; *format.mutable_params()->mutable_derived_key_template() = derived_key_template; format.SerializeToString(key_template.mutable_value()); // Verify `key_template` is derivable. util::StatusOr> handle = KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()); if (!handle.ok()) { return handle.status(); } util::StatusOr> deriver = (*handle)->GetPrimitive( ConfigGlobalRegistry()); if (!deriver.ok()) { return deriver.status(); } return key_template; } } // namespace tink } // namespace crypto ================================================ FILE: cc/keyderivation/key_derivation_key_templates.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_KEYDERIVATION_KEY_DERIVATION_KEY_TEMPLATES_H_ #define TINK_KEYDERIVATION_KEY_DERIVATION_KEY_TEMPLATES_H_ #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Methods to generate KeyTemplates for key derivation. class KeyDerivationKeyTemplates { public: // Creates a key template for key derivation that uses a PRF to derive a key // that adheres to `derived_key_template`. The following must be true: // (1) `prf_key_template` is a PRF key template, i.e. // `keyset_handle->GetPrimitive()` works. // (2) `derived_key_template` describes a key type that supports derivation. // // The output prefix type of the derived key will match the output prefix type // of `derived_key_template`. // // This function verifies the newly created key template by creating a // KeysetDeriver primitive from it. This requires both the `prf_key_template` // and `derived_key_template` key types to be in the registry. It also // attempts to derive a key, returning an error on failure. static util::StatusOr CreatePrfBasedKeyTemplate( const google::crypto::tink::KeyTemplate& prf_key_template, const google::crypto::tink::KeyTemplate& derived_key_template); }; } // namespace tink } // namespace crypto #endif // TINK_KEYDERIVATION_KEY_DERIVATION_KEY_TEMPLATES_H_ ================================================ FILE: cc/keyderivation/key_derivation_key_templates_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/keyderivation/key_derivation_key_templates.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/aead/aead_key_templates.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/keyderivation/internal/prf_based_deriver_key_manager.h" #include "tink/keyderivation/keyset_deriver_wrapper.h" #include "tink/prf/hkdf_prf_key_manager.h" #include "tink/prf/prf_key_templates.h" #include "tink/registry.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/prf_based_deriver.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::OutputPrefixType; using ::google::crypto::tink::PrfBasedDeriverKeyFormat; using ::testing::Eq; using ::testing::Not; class KeyDerivationKeyTemplatesTest : public ::testing::Test { protected: void TearDown() override { Registry::Reset(); } }; TEST_F(KeyDerivationKeyTemplatesTest, CreatePrfBasedKeyTemplate) { ASSERT_THAT(Registry::RegisterPrimitiveWrapper( absl::make_unique()), IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), /*new_key_allowed=*/true), IsOk()); ASSERT_THAT( Registry::RegisterKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/true), IsOk()); ASSERT_THAT( Registry::RegisterKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/true), IsOk()); std::vector output_prefix_types = { OutputPrefixType::RAW, OutputPrefixType::TINK, OutputPrefixType::LEGACY}; for (OutputPrefixType output_prefix_type : output_prefix_types) { KeyTemplate derived_key_template = AeadKeyTemplates::Aes256Gcm(); derived_key_template.set_output_prefix_type(output_prefix_type); util::StatusOr key_template = KeyDerivationKeyTemplates::CreatePrfBasedKeyTemplate( PrfKeyTemplates::HkdfSha256(), derived_key_template); ASSERT_THAT(key_template, IsOk()); EXPECT_THAT( key_template->type_url(), Eq("type.googleapis.com/google.crypto.tink.PrfBasedDeriverKey")); EXPECT_THAT(key_template->type_url(), Eq(internal::PrfBasedDeriverKeyManager().get_key_type())); EXPECT_THAT(key_template->output_prefix_type(), Eq(output_prefix_type)); PrfBasedDeriverKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template->value())); EXPECT_THAT( internal::PrfBasedDeriverKeyManager().ValidateKeyFormat(key_format), IsOk()); } } TEST_F(KeyDerivationKeyTemplatesTest, CreatePrfBasedKeyTemplateInvalidPrfKey) { ASSERT_THAT(Registry::RegisterPrimitiveWrapper( absl::make_unique()), IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), /*new_key_allowed=*/true), IsOk()); ASSERT_THAT( Registry::RegisterKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/true), IsOk()); ASSERT_THAT( Registry::RegisterKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/true), IsOk()); EXPECT_THAT(KeyDerivationKeyTemplates::CreatePrfBasedKeyTemplate( AeadKeyTemplates::Aes256Gcm(), AeadKeyTemplates::Aes256Gcm()) .status(), StatusIs(absl::StatusCode::kNotFound)); } TEST_F(KeyDerivationKeyTemplatesTest, CreatePrfBasedKeyTemplateInvalidDerivedKeyTemplate) { ASSERT_THAT(Registry::RegisterPrimitiveWrapper( absl::make_unique()), IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), /*new_key_allowed=*/true), IsOk()); ASSERT_THAT( Registry::RegisterKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/true), IsOk()); ASSERT_THAT( Registry::RegisterKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/true), IsOk()); util::StatusOr derived_key_template = KeyDerivationKeyTemplates::CreatePrfBasedKeyTemplate( PrfKeyTemplates::HkdfSha256(), AeadKeyTemplates::Aes256Gcm()); ASSERT_THAT(derived_key_template, IsOk()); EXPECT_THAT(KeyDerivationKeyTemplates::CreatePrfBasedKeyTemplate( PrfKeyTemplates::HkdfSha256(), *derived_key_template) .status(), StatusIs(absl::StatusCode::kNotFound)); } TEST_F(KeyDerivationKeyTemplatesTest, CreatePrfBasedKeyTemplateNoPrfBasedDeriverKeyManager) { ASSERT_THAT(Registry::RegisterPrimitiveWrapper( absl::make_unique()), IsOk()); ASSERT_THAT( Registry::RegisterKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/true), IsOk()); ASSERT_THAT( Registry::RegisterKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/true), IsOk()); EXPECT_THAT(KeyDerivationKeyTemplates::CreatePrfBasedKeyTemplate( PrfKeyTemplates::HkdfSha256(), AeadKeyTemplates::Aes256Gcm()), Not(IsOk())); } TEST_F(KeyDerivationKeyTemplatesTest, CreatePrfBasedKeyTemplateNoHkdfPrfKeyManager) { ASSERT_THAT(Registry::RegisterPrimitiveWrapper( absl::make_unique()), IsOk()); ASSERT_THAT(Registry::RegisterKeyTypeManager( absl::make_unique(), /*new_key_allowed=*/true), IsOk()); ASSERT_THAT( Registry::RegisterKeyTypeManager(absl::make_unique(), /*new_key_allowed=*/true), IsOk()); EXPECT_THAT(KeyDerivationKeyTemplates::CreatePrfBasedKeyTemplate( PrfKeyTemplates::HkdfSha256(), AeadKeyTemplates::Aes256Gcm()), Not(IsOk())); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/keyderivation/keyset_deriver.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_KEYDERIVATION_KEYSET_DERIVER_H_ #define TINK_KEYDERIVATION_KEYSET_DERIVER_H_ #include #include "absl/strings/string_view.h" #include "tink/keyset_handle.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // KeysetDeriver is the interface used to derive new keysets based on an // additional input, the salt. // // The salt is used to create the keyset using a pseudorandom function. // Implementations must be indistinguishable from ideal KeysetDerivers, which, // for every salt, generates a new random keyset and caches it. class KeysetDeriver { public: virtual crypto::tink::util::StatusOr> DeriveKeyset(absl::string_view salt) const = 0; virtual ~KeysetDeriver() = default; }; } // namespace tink } // namespace crypto #endif // TINK_KEYDERIVATION_KEYSET_DERIVER_H_ ================================================ FILE: cc/keyderivation/keyset_deriver_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/keyderivation/keyset_deriver.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/aead/aes_gcm_key.h" #include "tink/aead/aes_gcm_parameters.h" #include "tink/aead/aes_gcm_proto_serialization.h" #include "tink/config/global_registry.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/keyderivation/internal/prf_based_deriver_key_manager.h" #include "tink/keyderivation/keyset_deriver_wrapper.h" #include "tink/keyset_handle.h" #include "tink/partial_key_access.h" #include "tink/partial_key_access_token.h" #include "tink/registry.h" #include "tink/restricted_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_keyset_handle.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/hkdf_prf.pb.h" #include "proto/prf_based_deriver.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::Keyset; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::KeyTemplate; using ::testing::Eq; using ::testing::TestWithParam; using ::testing::ValuesIn; // Hex values from HKDF RFC https://tools.ietf.org/html/rfc5869#appendix-A.2. static constexpr absl::string_view kOutputKeyMaterialFromRfcVector = "b11e398dc80327a1c8e7f78c596a4934" "4f012eda2d4efad8a050cc4c19afa97c" "59045a99cac7827271cb41c65e590e09" "da3275600c2f09b8367793a9aca3db71" "cc30c58179ec3e87c14c01d5c1f3434f"; KeyData PrfKeyFromRfcVector() { google::crypto::tink::HkdfPrfKey prf_key; prf_key.set_version(0); prf_key.mutable_params()->set_hash(HashType::SHA256); prf_key.mutable_params()->set_salt( test::HexDecodeOrDie("606162636465666768696a6b6c6d6e6f" "707172737475767778797a7b7c7d7e7f" "808182838485868788898a8b8c8d8e8f" "909192939495969798999a9b9c9d9e9f" "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf")); prf_key.set_key_value( test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f" "101112131415161718191a1b1c1d1e1f" "202122232425262728292a2b2c2d2e2f" "303132333435363738393a3b3c3d3e3f" "404142434445464748494a4b4c4d4e4f")); return test::AsKeyData(prf_key, KeyData::SYMMETRIC); } std::string SaltFromRfcVector() { return test::HexDecodeOrDie( "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"); } std::unique_ptr CreateAesGcmKey(int key_size, AesGcmParameters::Variant variant, absl::string_view secret, absl::optional id_requirement) { AesGcmParameters params = AesGcmParameters::Builder() .SetKeySizeInBytes(key_size) .SetIvSizeInBytes(12) .SetTagSizeInBytes(16) .SetVariant(variant) .Build() .value(); return std::make_unique( AesGcmKey::Create(params, RestrictedData(test::HexDecodeOrDie(secret), InsecureSecretKeyAccess::Get()), id_requirement, GetPartialKeyAccess()) .value()); } std::vector>> TestVectors() { return { /*AesGcm KeysetHandle*/ { { CreateAesGcmKey( /*key_size=*/16, /*variant=*/AesGcmParameters::Variant::kTink, /*secret=*/kOutputKeyMaterialFromRfcVector.substr(0, 32), /*id_requirement=*/1010101), }, { CreateAesGcmKey( /*key_size=*/32, /*variant=*/AesGcmParameters::Variant::kCrunchy, /*secret=*/kOutputKeyMaterialFromRfcVector.substr(0, 64), /*id_requirement=*/2020202), }, { CreateAesGcmKey( /*key_size=*/16, /*variant=*/AesGcmParameters::Variant::kNoPrefix, /*secret=*/kOutputKeyMaterialFromRfcVector.substr(0, 32), /*id_requirement=*/absl::nullopt), }, }, }; } util::StatusOr> CreatePrfBasedDeriverHandle( std::vector> derived_keys) { Keyset keyset; keyset.set_primary_key_id(derived_keys[0]->GetIdRequirement().value_or(0)); for (const auto& derived_key : derived_keys) { // Get KeyTemplate from Parameters. util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( derived_key->GetParameters()); if (!serialization.ok()) { return serialization.status(); } const internal::ProtoParametersSerialization* proto_serialization = dynamic_cast( serialization->get()); if (proto_serialization == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "Serialization is not ProtoParametersSerialization"); } KeyTemplate derived_key_template = proto_serialization->GetKeyTemplate(); // Create PrfBasedDeriverKey. google::crypto::tink::PrfBasedDeriverKey deriver_key; deriver_key.set_version(0); *deriver_key.mutable_prf_key() = PrfKeyFromRfcVector(); *deriver_key.mutable_params()->mutable_derived_key_template() = derived_key_template; // Add PrfBasedDeriverKey to Keyset. Keyset::Key* keyset_key = keyset.add_key(); *(keyset_key->mutable_key_data()) = test::AsKeyData(deriver_key, KeyData::SYMMETRIC); keyset_key->set_status(KeyStatusType::ENABLED); keyset_key->set_output_prefix_type( derived_key_template.output_prefix_type()); keyset_key->set_key_id(derived_key->GetIdRequirement().value_or(0)); } return TestKeysetHandle::GetKeysetHandle(keyset); } using KeysetDeriverTest = TestWithParam>>; INSTANTIATE_TEST_SUITE_P(KeysetDeriverTests, KeysetDeriverTest, ValuesIn(TestVectors())); TEST_P(KeysetDeriverTest, DeriveKeyset) { ASSERT_THAT(Registry::RegisterPrimitiveWrapper( absl::make_unique()), IsOk()); ASSERT_THAT( Registry::RegisterKeyTypeManager( absl::make_unique(), true), IsOk()); ASSERT_THAT(RegisterAesGcmProtoSerialization(), IsOk()); std::vector> derived_keys = GetParam(); util::StatusOr> handle = CreatePrfBasedDeriverHandle(derived_keys); ASSERT_THAT(handle, IsOk()); ASSERT_THAT((*handle)->size(), Eq(derived_keys.size())); util::StatusOr> deriver = (*handle)->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(deriver, IsOk()); util::StatusOr> derived_handle = (*deriver)->DeriveKeyset(SaltFromRfcVector()); ASSERT_THAT(derived_handle, IsOk()); ASSERT_THAT((*derived_handle)->size(), Eq(derived_keys.size())); for (int i = 0; i < derived_keys.size(); i++) { EXPECT_THAT(*(**derived_handle)[i].GetKey(), Eq(std::ref(*derived_keys[i]))); } } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/keyderivation/keyset_deriver_wrapper.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/keyderivation/keyset_deriver_wrapper.h" #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/cleartext_keyset_handle.h" #include "tink/keyderivation/keyset_deriver.h" #include "tink/keyset_handle.h" #include "tink/primitive_set.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::google::crypto::tink::KeyData; using ::google::crypto::tink::Keyset; util::Status Validate(PrimitiveSet* deriver_set) { if (deriver_set == nullptr) { return util::Status(absl::StatusCode::kInternal, "deriver_set must be non-NULL"); } if (deriver_set->get_primary() == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "deriver_set has no primary"); } return util::OkStatus(); } class KeysetDeriverSetWrapper : public KeysetDeriver { public: explicit KeysetDeriverSetWrapper( std::unique_ptr> deriver_set) : deriver_set_(std::move(deriver_set)) {} crypto::tink::util::StatusOr> DeriveKeyset( absl::string_view salt) const override; ~KeysetDeriverSetWrapper() override = default; private: std::unique_ptr> deriver_set_; }; crypto::tink::util::StatusOr DeriveAndGetKeyData( absl::string_view salt, const KeysetDeriver& deriver) { auto keyset_handle_or = deriver.DeriveKeyset(salt); if (!keyset_handle_or.ok()) return keyset_handle_or.status(); const Keyset& keyset = CleartextKeysetHandle::GetKeyset(*keyset_handle_or.value()); if (keyset.key_size() != 1) { return util::Status( absl::StatusCode::kInternal, "Wrapper Deriver must create a keyset with exactly one KeyData"); } return keyset.key(0).key_data(); } crypto::tink::util::StatusOr> KeysetDeriverSetWrapper::DeriveKeyset(absl::string_view salt) const { Keyset keyset; for (const auto* entry : deriver_set_->get_all_in_keyset_order()) { Keyset::Key* key = keyset.add_key(); crypto::tink::util::StatusOr key_data_or = DeriveAndGetKeyData(salt, entry->get_primitive()); if (!key_data_or.ok()) return key_data_or.status(); *key->mutable_key_data() = key_data_or.value(); key->set_status(entry->get_status()); key->set_output_prefix_type(entry->get_output_prefix_type()); key->set_key_id(entry->get_key_id()); } keyset.set_primary_key_id(deriver_set_->get_primary()->get_key_id()); return CleartextKeysetHandle::GetKeysetHandle(keyset); } } // namespace crypto::tink::util::StatusOr> KeysetDeriverWrapper::Wrap( std::unique_ptr> deriver_set) const { util::Status status = Validate(deriver_set.get()); if (!status.ok()) return status; return {absl::make_unique(std::move(deriver_set))}; } } // namespace tink } // namespace crypto ================================================ FILE: cc/keyderivation/keyset_deriver_wrapper.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_KEYDERIVATION_KEYSET_DERIVER_WRAPPER_H_ #define TINK_KEYDERIVATION_KEYSET_DERIVER_WRAPPER_H_ #include #include "tink/keyderivation/keyset_deriver.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // A KeysetDeriverWrapper wraps the KeysetDeriver primitive. // // The wrapper derives a key from each key in a keyset. It returns the resulting // keys in a new keyset. Each of the derived keys inherits key_id, status, and // output_prefix_type from the key from which it was derived. class KeysetDeriverWrapper : public PrimitiveWrapper { public: crypto::tink::util::StatusOr> Wrap( std::unique_ptr> deriver_set) const override; }; } // namespace tink } // namespace crypto #endif // TINK_KEYDERIVATION_KEYSET_DERIVER_WRAPPER_H_ ================================================ FILE: cc/keyderivation/keyset_deriver_wrapper_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/keyderivation/keyset_deriver_wrapper.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/cleartext_keyset_handle.h" #include "tink/keyderivation/keyset_deriver.h" #include "tink/keyset_handle.h" #include "tink/primitive_set.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::Keyset; using ::google::crypto::tink::KeysetInfo; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::HasSubstr; TEST(KeysetDeriverWrapperTest, WrapNullptr) { EXPECT_THAT(KeysetDeriverWrapper().Wrap(nullptr).status(), StatusIs(absl::StatusCode::kInternal, HasSubstr("non-NULL"))); } TEST(KeysetDeriverWrapperTest, WrapEmpty) { EXPECT_THAT( KeysetDeriverWrapper() .Wrap(absl::make_unique>()) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("no primary"))); } TEST(KeysetDeriverWrapperTest, WrapNoPrimary) { auto deriver_set = absl::make_unique>(); KeysetInfo::KeyInfo key_info; key_info.set_key_id(1234); key_info.set_status(KeyStatusType::ENABLED); key_info.set_output_prefix_type(OutputPrefixType::TINK); EXPECT_THAT(deriver_set ->AddPrimitive(absl::make_unique(""), key_info) .status(), IsOk()); EXPECT_THAT( KeysetDeriverWrapper().Wrap(std::move(deriver_set)).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("no primary"))); } TEST(KeysetDeriverWrapperTest, WrapSingle) { auto deriver_set = absl::make_unique>(); KeysetInfo::KeyInfo key_info; key_info.set_key_id(1234); key_info.set_status(KeyStatusType::ENABLED); key_info.set_output_prefix_type(OutputPrefixType::TINK); key_info.set_type_url( "type.googleapis.com/google.crypto.tink.PrfBasedDeriverKey"); auto entry_or = deriver_set->AddPrimitive( absl::make_unique("wrap_single_key"), key_info); ASSERT_THAT(entry_or, IsOk()); EXPECT_THAT(deriver_set->set_primary(entry_or.value()), IsOk()); auto wrapper_deriver_or = KeysetDeriverWrapper().Wrap(std::move(deriver_set)); ASSERT_THAT(wrapper_deriver_or, IsOk()); auto derived_keyset_or = wrapper_deriver_or.value()->DeriveKeyset("wrap_single_salt"); ASSERT_THAT(derived_keyset_or, IsOk()); Keyset keyset = CleartextKeysetHandle::GetKeyset(*derived_keyset_or.value()); EXPECT_THAT(keyset.primary_key_id(), Eq(1234)); ASSERT_THAT(keyset.key_size(), Eq(1)); EXPECT_THAT(keyset.key(0).key_data().type_url(), Eq("15:wrap_single_keywrap_single_salt")); EXPECT_THAT(keyset.key(0).status(), Eq(KeyStatusType::ENABLED)); EXPECT_THAT(keyset.key(0).key_id(), Eq(1234)); EXPECT_THAT(keyset.key(0).output_prefix_type(), Eq(OutputPrefixType::TINK)); } TEST(KeysetDeriverWrapperTest, WrapMultiple) { auto pset = absl::make_unique>(); std::vector key_infos; KeysetInfo::KeyInfo key_info; key_info.set_key_id(1010101); key_info.set_status(KeyStatusType::ENABLED); key_info.set_output_prefix_type(OutputPrefixType::RAW); key_info.set_type_url( "type.googleapis.com/google.crypto.tink.PrfBasedDeriverKey"); ASSERT_THAT( pset->AddPrimitive(absl::make_unique("k1"), key_info) .status(), IsOk()); key_infos.push_back(key_info); key_info.set_key_id(2020202); key_info.set_status(KeyStatusType::ENABLED); key_info.set_output_prefix_type(OutputPrefixType::LEGACY); key_info.set_type_url( "type.googleapis.com/google.crypto.tink.PrfBasedDeriverKey"); util::StatusOr::Entry*> entry = pset->AddPrimitive(absl::make_unique("k2"), key_info); ASSERT_THAT(entry, IsOk()); ASSERT_THAT(pset->set_primary(*entry), IsOk()); key_infos.push_back(key_info); key_info.set_key_id(3030303); key_info.set_status(KeyStatusType::ENABLED); key_info.set_output_prefix_type(OutputPrefixType::TINK); key_info.set_type_url( "type.googleapis.com/google.crypto.tink.PrfBasedDeriverKey"); ASSERT_THAT(pset->AddPrimitive( absl::make_unique("k3"), key_info), IsOk()); key_infos.push_back(key_info); util::StatusOr> wrapper_deriver = KeysetDeriverWrapper().Wrap(std::move(pset)); ASSERT_THAT(wrapper_deriver, IsOk()); util::StatusOr> derived_keyset = (*wrapper_deriver)->DeriveKeyset("salt"); ASSERT_THAT(derived_keyset, IsOk()); Keyset keyset = CleartextKeysetHandle::GetKeyset(**derived_keyset); EXPECT_THAT(keyset.primary_key_id(), Eq(2020202)); ASSERT_THAT(keyset.key_size(), Eq(3)); for (int i = 0; i < keyset.key().size(); i++) { std::string type_url = absl::StrCat("2:k", i + 1, "salt"); EXPECT_THAT(keyset.key(i).key_data().type_url(), Eq(type_url)); Keyset::Key key = keyset.key(i); key_info = key_infos[i]; EXPECT_THAT(key.status(), Eq(key_info.status())); EXPECT_THAT(key.key_id(), Eq(key_info.key_id())); EXPECT_THAT(key.output_prefix_type(), Eq(key_info.output_prefix_type())); } } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/keyderivation/subtle/BUILD.bazel ================================================ licenses(["notice"]) ================================================ FILE: cc/keyderivation/subtle/CMakeLists.txt ================================================ ================================================ FILE: cc/keyset_handle.h ================================================ // Copyright 2017 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_KEYSET_HANDLE_H_ #define TINK_KEYSET_HANDLE_H_ #include #include #include #include #include #include "absl/base/attributes.h" #include "absl/base/macros.h" #include "absl/container/flat_hash_map.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/config/global_registry.h" #include "tink/configuration.h" #include "tink/internal/configuration_impl.h" #include "tink/internal/key_info.h" #include "tink/internal/keyset_wrapper.h" #include "tink/internal/keyset_wrapper_store.h" #include "tink/internal/registry_impl.h" #include "tink/key.h" #include "tink/key_gen_configuration.h" #include "tink/key_manager.h" #include "tink/key_status.h" #include "tink/keyset_reader.h" #include "tink/keyset_writer.h" #include "tink/primitive_set.h" #include "tink/registry.h" #include "tink/secret_key_access_token.h" #include "tink/util/secret_proto.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // KeysetHandle provides abstracted access to Keysets, to limit // the exposure of actual protocol buffers that hold sensitive // key material. class KeysetHandle { public: // Represents a single entry in a `KeysetHandle`. Some current behavior will // be changed in the future. class Entry { public: // May return an internal class in case there is no implementation of the // corresponding key class yet. std::shared_ptr GetKey() const { return key_; } // Status indicates whether or not a key should still be used. KeyStatus GetStatus() const { return status_; } // ID should be unique (though currently Tink still accepts keysets with // repeated IDs). int GetId() const { return id_; } // Should return true for exactly one entry (though currently Tink still // accepts keysets which have no entry marked as primary). bool IsPrimary() const { return is_primary_; } private: friend class KeysetHandle; friend class KeysetHandleBuilder; Entry(std::shared_ptr key, KeyStatus status, int id, bool is_primary) : key_(std::move(key)), status_(status), id_(id), is_primary_(is_primary) {} std::shared_ptr key_; KeyStatus status_; int id_; bool is_primary_; }; KeysetHandle() = default; KeysetHandle(const KeysetHandle&) = default; KeysetHandle(KeysetHandle&&) = default; KeysetHandle& operator=(const KeysetHandle&) = default; KeysetHandle& operator=(KeysetHandle&&) = default; // Returns the number of entries in this keyset. int size() const { return keyset_->key_size(); } // Validates single `KeysetHandle::Entry` at `index` by making sure that the // key entry's type URL is printable and that it has a valid key status. crypto::tink::util::Status ValidateAt(int index) const; // Validates each individual `KeysetHandle::Entry` in keyset handle by calling // `ValidateAt()`. Also, checks that there is a single enabled primary key. crypto::tink::util::Status Validate() const; // Returns entry for primary key in this keyset. Crashes if `Validate()` // does not return an OK status. Call `Validate()` prior to calling this // method to avoid potentially crashing your program. Entry GetPrimary() const; // Returns the `KeysetHandle::Entry` at `index`. Crashes if // `ValidateAt(index)` does not return an OK status. Call `ValidateAt(index)` // prior to calling this method to avoid potentially crashing your program. Entry operator[](int index) const; // Creates a KeysetHandle from an encrypted keyset obtained via `reader` // using `master_key_aead` to decrypt the keyset, with monitoring annotations // `monitoring_annotations`; by default, `monitoring_annotations` is empty. static crypto::tink::util::StatusOr> Read( std::unique_ptr reader, const Aead& master_key_aead, const absl::flat_hash_map& monitoring_annotations = {}); // Creates a KeysetHandle from an encrypted keyset obtained via `reader` // using `master_key_aead` to decrypt the keyset, expecting `associated_data`. // The keyset is annotated for monitoring with `monitoring_annotations`; by // default, `monitoring_annotations` is empty. static crypto::tink::util::StatusOr> ReadWithAssociatedData(std::unique_ptr reader, const Aead& master_key_aead, absl::string_view associated_data, const absl::flat_hash_map& monitoring_annotations = {}); // Creates a KeysetHandle from a serialized keyset `serialized_keyset` which // contains no secret key material, and annotates it with // `monitoring_annotations` for monitoring; by default, // `monitoring_annotations` is empty. This can be used to load public keysets // or envelope encryption keysets. static crypto::tink::util::StatusOr> ReadNoSecret(const std::string& serialized_keyset, const absl::flat_hash_map& monitoring_annotations = {}); // Returns a KeysetHandle containing one new key generated according to // `key_template` using `config`. When specified, the keyset is annotated // for monitoring with `monitoring_annotations`. static crypto::tink::util::StatusOr> GenerateNew(const google::crypto::tink::KeyTemplate& key_template, const crypto::tink::KeyGenConfiguration& config, const absl::flat_hash_map& monitoring_annotations); static crypto::tink::util::StatusOr> GenerateNew(const google::crypto::tink::KeyTemplate& key_template, const crypto::tink::KeyGenConfiguration& config); // Returns a KeysetHandle containing one new key generated according to // `key_template` using the global registry. When specified, the keyset is // annotated for monitoring with `monitoring_annotations`. ABSL_DEPRECATED("Inline this function's body at its call sites") static crypto::tink::util::StatusOr> GenerateNew(const google::crypto::tink::KeyTemplate& key_template, const absl::flat_hash_map& monitoring_annotations) { return GenerateNew(key_template, crypto::tink::KeyGenConfigGlobalRegistry(), monitoring_annotations); } ABSL_DEPRECATED("Inline this function's body at its call sites") static crypto::tink::util::StatusOr> GenerateNew(const google::crypto::tink::KeyTemplate& key_template) { return GenerateNew(key_template, crypto::tink::KeyGenConfigGlobalRegistry()); } // Encrypts the underlying keyset with the provided `master_key_aead` // and writes the resulting EncryptedKeyset to the given `writer`, // which must be non-null. crypto::tink::util::Status Write(KeysetWriter* writer, const Aead& master_key_aead) const; // Encrypts the underlying keyset with the provided `master_key_aead`, using // `associated_data`. and writes the resulting EncryptedKeyset to the given // `writer`, which must be non-null. crypto::tink::util::Status WriteWithAssociatedData( KeysetWriter* writer, const Aead& master_key_aead, absl::string_view associated_data) const; // Returns KeysetInfo, a "safe" Keyset that doesn't contain any actual // key material, thus can be used for logging or monitoring. google::crypto::tink::KeysetInfo GetKeysetInfo() const; // Writes the underlying keyset to `writer` only if the keyset does not // contain any secret key material. // This can be used to persist public keysets or envelope encryption keysets. // Users that need to persist cleartext keysets can use // `CleartextKeysetHandle`. crypto::tink::util::Status WriteNoSecret(KeysetWriter* writer) const; // Returns a new KeysetHandle containing public keys corresponding to the // private keys in this handle. Relies on key type managers stored in `config` // to do so. Returns an error if this handle contains keys that are not // private keys. crypto::tink::util::StatusOr> GetPublicKeysetHandle(const KeyGenConfiguration& config) const; // Returns a new KeysetHandle containing public keys corresponding to the // private keys in this handle. Relies on key type managers stored in the // global registry to do so. Returns an error if this handle contains keys // that are not private keys. ABSL_DEPRECATED("Inline this function's body at its call sites") crypto::tink::util::StatusOr> GetPublicKeysetHandle() const { return GetPublicKeysetHandle(crypto::tink::KeyGenConfigGlobalRegistry()); } // Creates a wrapped primitive using this keyset handle and config, which // stores necessary primitive wrappers and key type managers. template crypto::tink::util::StatusOr> GetPrimitive( const Configuration& config) const; // Creates a wrapped primitive using this keyset handle and the global // registry, which stores necessary primitive wrappers and key type managers. template ABSL_DEPRECATED("Inline this function's body at its call sites") crypto::tink::util::StatusOr> GetPrimitive() const { return GetPrimitive

(crypto::tink::ConfigGlobalRegistry()); } // Creates a wrapped primitive corresponding to this keyset. Uses the given // KeyManager, as well as the KeyManager and PrimitiveWrapper objects in the // global registry to create the primitive. The given KeyManager is used for // keys supported by it. For those, the registry is ignored. // TINK-PENDING-REMOVAL-IN-3.0.0-START template ABSL_DEPRECATED("Register the keymanager and use GetPrimitive") crypto::tink::util::StatusOr> GetPrimitive( const KeyManager

* custom_manager) const; // TINK-PENDING-REMOVAL-IN-3.0.0-END private: // The classes below need access to get_keyset(); friend class CleartextKeysetHandle; friend class KeysetManager; // TestKeysetHandle::GetKeyset() provides access to get_keyset(). friend class TestKeysetHandle; // KeysetHandleBuilder::Build() needs access to KeysetHandle(Keyset). friend class KeysetHandleBuilder; friend crypto::tink::util::StatusOr ParseKeysetFromProtoKeysetFormat(absl::string_view serialized_keyset, SecretKeyAccessToken token); // Creates a handle that contains the given keyset. explicit KeysetHandle(util::SecretProto keyset) : keyset_(std::move(keyset)) {} // Creates a handle that contains the given `keyset` and `entries`. KeysetHandle( util::SecretProto keyset, const std::vector>& entries) : keyset_(std::move(keyset)), entries_(entries) {} // Creates a handle that contains the given `keyset` and // `monitoring_annotations`. KeysetHandle(util::SecretProto keyset, const absl::flat_hash_map& monitoring_annotations) : keyset_(std::move(*keyset)), monitoring_annotations_(monitoring_annotations) {} // Creates a handle that contains the given `keyset`, `entries`, and // `monitoring_annotations`. KeysetHandle(util::SecretProto keyset, const std::vector>& entries, const absl::flat_hash_map& monitoring_annotations) : keyset_(std::move(keyset)), entries_(entries), monitoring_annotations_(monitoring_annotations) {} // Generates a key from `key_template` and adds it `keyset`. static crypto::tink::util::StatusOr AddToKeyset( const google::crypto::tink::KeyTemplate& key_template, bool as_primary, const crypto::tink::KeyGenConfiguration& config, google::crypto::tink::Keyset* keyset); // Creates list of KeysetHandle::Entry entries derived from `keyset` in order. static crypto::tink::util::StatusOr>> GetEntriesFromKeyset(const google::crypto::tink::Keyset& keyset); // Creates KeysetHandle::Entry for `key`, which will be set to primary if // its key id equals `primary_key_id`. static util::StatusOr CreateEntry( const google::crypto::tink::Keyset::Key& key, uint32_t primary_key_id); // Generates a key from `key_template` and adds it to the keyset handle. crypto::tink::util::StatusOr AddKey( const google::crypto::tink::KeyTemplate& key_template, bool as_primary, const crypto::tink::KeyGenConfiguration& config); // Returns keyset held by this handle. const google::crypto::tink::Keyset& get_keyset() const { return *keyset_; } // Creates a set of primitives corresponding to the keys with // (status == ENABLED) in the keyset given in 'keyset_handle', // assuming all the corresponding key managers are present (keys // with (status != ENABLED) are skipped). // // The returned set is usually later "wrapped" into a class that // implements the corresponding Primitive-interface. template crypto::tink::util::StatusOr>> GetPrimitives( const KeyManager

* custom_manager) const; // Creates KeysetHandle::Entry from `keyset_` at `index`. Entry CreateEntryAt(int index) const; util::SecretProto keyset_; // If this keyset handle has been created with a constructor that does not // accept an entries argument, then `entries` will be empty and operator[] // will fall back to creating the key entry on demand from `keyset_`. // // If `entries_` is not empty, then it should contain exactly one key entry // for each key proto in `keyset_`. std::vector> entries_; absl::flat_hash_map monitoring_annotations_; }; /////////////////////////////////////////////////////////////////////////////// // Implementation details of templated methods. template crypto::tink::util::StatusOr>> KeysetHandle::GetPrimitives(const KeyManager

* custom_manager) const { crypto::tink::util::Status status = ValidateKeyset(*keyset_); if (!status.ok()) return status; typename PrimitiveSet

::Builder primitives_builder; primitives_builder.AddAnnotations(monitoring_annotations_); for (const google::crypto::tink::Keyset::Key& key : keyset_->key()) { if (key.status() == google::crypto::tink::KeyStatusType::ENABLED) { std::unique_ptr

primitive; if (custom_manager != nullptr && custom_manager->DoesSupport(key.key_data().type_url())) { auto primitive_result = custom_manager->GetPrimitive(key.key_data()); if (!primitive_result.ok()) return primitive_result.status(); primitive = std::move(primitive_result.value()); } else { auto primitive_result = Registry::GetPrimitive

(key.key_data()); if (!primitive_result.ok()) return primitive_result.status(); primitive = std::move(primitive_result.value()); } if (key.key_id() == keyset_->primary_key_id()) { primitives_builder.AddPrimaryPrimitive(std::move(primitive), KeyInfoFromKey(key)); } else { primitives_builder.AddPrimitive(std::move(primitive), KeyInfoFromKey(key)); } } } auto primitives = std::move(primitives_builder).Build(); if (!primitives.ok()) return primitives.status(); return absl::make_unique>(*std::move(primitives)); } template crypto::tink::util::StatusOr> KeysetHandle::GetPrimitive( const Configuration& config) const { if (crypto::tink::internal::ConfigurationImpl::IsInGlobalRegistryMode( config)) { return crypto::tink::internal::RegistryImpl::GlobalInstance().WrapKeyset

( *keyset_, monitoring_annotations_); } crypto::tink::util::StatusOr< const crypto::tink::internal::KeysetWrapperStore*> wrapper_store = crypto::tink::internal::ConfigurationImpl::GetKeysetWrapperStore( config); if (!wrapper_store.ok()) { return wrapper_store.status(); } crypto::tink::util::StatusOr*> wrapper = (*wrapper_store)->Get

(); if (!wrapper.ok()) { return wrapper.status(); } return (*wrapper)->Wrap(*keyset_, monitoring_annotations_); } // TINK-PENDING-REMOVAL-IN-3.0.0-START template crypto::tink::util::StatusOr> KeysetHandle::GetPrimitive( const KeyManager

* custom_manager) const { if (custom_manager == nullptr) { return crypto::tink::util::Status(absl::StatusCode::kInvalidArgument, "custom_manager must not be null"); } auto primitives_result = this->GetPrimitives

(custom_manager); if (!primitives_result.ok()) { return primitives_result.status(); } return Registry::Wrap

(std::move(primitives_result.value())); } // TINK-PENDING-REMOVAL-IN-3.0.0-END } // namespace tink } // namespace crypto #endif // TINK_KEYSET_HANDLE_H_ ================================================ FILE: cc/keyset_handle_builder.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_KEYSET_HANDLE_BUILDER_H_ #define TINK_KEYSET_HANDLE_BUILDER_H_ #include #include #include #include #include #include "absl/container/flat_hash_map.h" #include "absl/types/optional.h" #include "tink/internal/keyset_handle_builder_entry.h" #include "tink/key.h" #include "tink/key_status.h" #include "tink/keyset_handle.h" #include "tink/parameters.h" #include "tink/util/secret_proto.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Creates new `KeysetHandle` objects. class KeysetHandleBuilder { public: // Movable, but not copyable. KeysetHandleBuilder(KeysetHandleBuilder&& other) = default; KeysetHandleBuilder& operator=(KeysetHandleBuilder&& other) = default; KeysetHandleBuilder(const KeysetHandleBuilder& other) = delete; KeysetHandleBuilder& operator=(const KeysetHandleBuilder& other) = delete; // Creates initially empty keyset handle builder. KeysetHandleBuilder() = default; // Creates keyset handle builder by initially moving keys from `handle`. explicit KeysetHandleBuilder(const KeysetHandle& handle); // Represents a single entry in a `KeysetHandleBuilder`. class Entry { public: // Movable, but not copyable. Entry(Entry&& other) = default; Entry& operator=(Entry&& other) = default; Entry(const Entry& other) = delete; Entry& operator=(const Entry& other) = delete; // Creates new KeysetHandleBuilder::Entry from a given `key`. Also, sets // key `status` and whether or not the key `is_primary`. static Entry CreateFromKey(std::shared_ptr key, KeyStatus status, bool is_primary); template inline static Entry CreateFromCopyableKey(CopyableKey key, KeyStatus status, bool is_primary) { auto copyable_key = absl::make_unique(std::move(key)); return CreateFromKey(std::move(copyable_key), status, is_primary); } // Creates new KeysetHandleBuilder::Entry from given `parameters`. Also, // sets key `status` and whether or not the key `is_primary`. If `id` // does not have a value, then the key will be assigned a random id. static Entry CreateFromParams(std::shared_ptr parameters, KeyStatus status, bool is_primary, absl::optional id = absl::nullopt); template inline static Entry CreateFromCopyableParams( CopyableParameters parameters, KeyStatus status, bool is_primary, absl::optional id = absl::nullopt) { auto copyable_params = absl::make_unique(std::move(parameters)); return CreateFromParams(std::move(copyable_params), status, is_primary, id); } // Sets the key status of this entry. void SetStatus(KeyStatus status) { entry_->SetStatus(status); } // Returns key status of this entry. KeyStatus GetStatus() const { return entry_->GetStatus(); } // Assigns a fixed id when this keyset is built. void SetFixedId(int id) { entry_->SetFixedId(id); } // Assigns an unused random id when this keyset is built. void SetRandomId() { entry_->SetRandomId(); } // Sets this entry as the primary key. void SetPrimary() { entry_->SetPrimary(); } // Unsets this entry as the primary key. void UnsetPrimary() { entry_->UnsetPrimary(); } // Returns whether or not this entry has been marked as a primary. bool IsPrimary() const { return entry_->IsPrimary(); } private: friend class KeysetHandleBuilder; explicit Entry(std::unique_ptr entry) : entry_(std::move(entry)) {} // Returns whether or not this entry has a randomly assigned id. bool HasRandomId() { return entry_->GetKeyIdStrategyEnum() == internal::KeyIdStrategyEnum::kRandomId; } internal::KeyIdStrategy GetKeyIdStrategy() { return entry_->GetKeyIdStrategy(); } crypto::tink::util::StatusOr< crypto::tink::util::SecretProto> CreateKeysetKey(int id) { return entry_->CreateKeysetKey(id); } std::unique_ptr entry_; bool added_to_builder_ = false; }; // Adds an `entry` to the keyset builder. Crashes if `entry` has already been // added to a keyset handle builder. KeysetHandleBuilder& AddEntry(KeysetHandleBuilder::Entry entry); // Removes an entry at `index` from keyset builder. KeysetHandleBuilder& RemoveEntry(int index); // Returns the number of Entry objects in this keyset builder. int size() const { return entries_.size(); } // Returns entry from keyset builder at `index`. KeysetHandleBuilder::Entry& operator[](int index) { return entries_[index]; } // Sets MonitoringAnnotations. If not called, then the default value of an // empty map is used. When called multiple times, previous values are // replaced. KeysetHandleBuilder& SetMonitoringAnnotations( const absl::flat_hash_map& monitoring_annotations); // Creates a new `KeysetHandle` object. // // Note: Since KeysetHandleBuilder::Entry objects might have randomly // generated IDs, Build() can only be called once on a single // KeysetHandleBuilder object. Otherwise, the KeysetHandleBuilder::Entry // IDs would randomly change for each call to Build(), which would result // in incompatible keysets. crypto::tink::util::StatusOr Build(); private: // Select the next key id based on the given strategy. crypto::tink::util::StatusOr NextIdFromKeyIdStrategy( internal::KeyIdStrategy strategy, const std::set& ids_so_far); // Unset primary flag on all entries. void ClearPrimary(); // Verify that entries with fixed IDs do not follow entries with random IDs. crypto::tink::util::Status CheckIdAssignments(); std::vector entries_; absl::flat_hash_map monitoring_annotations_; bool build_called_ = false; }; } // namespace tink } // namespace crypto #endif // TINK_KEYSET_HANDLE_BUILDER_H_ ================================================ FILE: cc/keyset_manager.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_KEYSET_MANAGER_H_ #define TINK_KEYSET_MANAGER_H_ #include #include #include "absl/base/thread_annotations.h" #include "absl/synchronization/mutex.h" #include "tink/util/secret_proto.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class KeysetHandle; // KeysetManager provides convenience methods for creation of Keysets, and for // rotating, disabling, enabling, or destroying keys. // An instance of this class takes care of a single Keyset, that can be // accessed via GetKeysetHandle()-method. class KeysetManager { public: // Constructs a KeysetManager with an empty Keyset. KeysetManager() = default; // Creates a new KeysetManager that contains a Keyset with a single key // generated freshly according the specification in 'key_template'. static crypto::tink::util::StatusOr> New( const google::crypto::tink::KeyTemplate& key_template); // Creates a new KeysetManager that contains a Keyset cloned from // the given 'keyset_handle'. static crypto::tink::util::StatusOr> New( const KeysetHandle& keyset_handle); // Adds to the managed keyset a fresh key generated according to // 'keyset_template' and returns the key_id of the added key. // The added key has status 'ENABLED'. crypto::tink::util::StatusOr Add( const google::crypto::tink::KeyTemplate& key_template) ABSL_LOCKS_EXCLUDED(keyset_mutex_); // Adds to the managed keyset a fresh key generated according to // 'keyset_template', sets the new key as the primary, // and returns the key_id of the added key. // The key that was primary prior to rotation remains 'ENABLED'. crypto::tink::util::StatusOr Rotate( const google::crypto::tink::KeyTemplate& key_template) ABSL_LOCKS_EXCLUDED(keyset_mutex_); // Sets the status of the specified key to 'ENABLED'. // Succeeds only if before the call the specified key // has status 'DISABLED' or 'ENABLED'. crypto::tink::util::Status Enable(uint32_t key_id) ABSL_LOCKS_EXCLUDED(keyset_mutex_); // Sets the status of the specified key to 'DISABLED'. // Succeeds only if before the call the specified key // is not primary and has status 'DISABLED' or 'ENABLED'. crypto::tink::util::Status Disable(uint32_t key_id) ABSL_LOCKS_EXCLUDED(keyset_mutex_); // Sets the status of the specified key to 'DESTROYED', // and removes the corresponding key material, if any. // Succeeds only if before the call the specified key // is not primary and has status 'DISABLED', or 'ENABLED', // or 'DESTROYED'. crypto::tink::util::Status Destroy(uint32_t key_id) ABSL_LOCKS_EXCLUDED(keyset_mutex_); // Removes the specifed key from the managed keyset. // Succeeds only if the specified key is not primary. // After deletion the keyset contains one key fewer. crypto::tink::util::Status Delete(uint32_t key_id) ABSL_LOCKS_EXCLUDED(keyset_mutex_); // Sets the specified key as the primary. // Succeeds only if the specified key is 'ENABLED'. crypto::tink::util::Status SetPrimary(uint32_t key_id) ABSL_LOCKS_EXCLUDED(keyset_mutex_); // Returns the count of all keys in the keyset. int KeyCount() const; // Returns a handle with a copy of the managed keyset. std::unique_ptr GetKeysetHandle() ABSL_LOCKS_EXCLUDED(keyset_mutex_); private: crypto::tink::util::StatusOr Add( const google::crypto::tink::KeyTemplate& key_template, bool as_primary) ABSL_LOCKS_EXCLUDED(keyset_mutex_); mutable absl::Mutex keyset_mutex_; util::SecretProto keyset_ ABSL_GUARDED_BY(keyset_mutex_); }; } // namespace tink } // namespace crypto #endif // TINK_KEYSET_MANAGER_H_ ================================================ FILE: cc/keyset_reader.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_KEYSET_READER_H_ #define TINK_KEYSET_READER_H_ #include #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // KeysetReader knows how to read a Keyset or an EncryptedKeyset // from some source. class KeysetReader { public: // Reads and returns a (cleartext) Keyset object from the underlying source. virtual crypto::tink::util::StatusOr< std::unique_ptr> Read() = 0; // Reads and returns an EncryptedKeyset object from the underlying source. virtual crypto::tink::util::StatusOr< std::unique_ptr> ReadEncrypted() = 0; virtual ~KeysetReader() = default; }; } // namespace tink } // namespace crypto #endif // TINK_KEYSET_READER_H_ ================================================ FILE: cc/keyset_writer.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_KEYSET_WRITER_H_ #define TINK_KEYSET_WRITER_H_ #include "tink/util/status.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // KeysetWriter knows how to write a Keyset or an EncryptedKeyset // to some storage system. class KeysetWriter { public: // Writes 'keyset' to the underlying storage system. virtual crypto::tink::util::Status Write(const google::crypto::tink::Keyset& keyset) = 0; // Writes 'encrypted_keyset' to the underlying storage system. virtual crypto::tink::util::Status Write(const google::crypto::tink::EncryptedKeyset& encrypted_keyset) = 0; virtual ~KeysetWriter() = default; }; } // namespace tink } // namespace crypto #endif // TINK_KEYSET_WRITER_H_ ================================================ FILE: cc/kms_client.h ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_KMS_CLIENT_H_ #define TINK_KMS_CLIENT_H_ #include #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // KmsClient knows how to produce primitives backed by keys stored // in remote KMS services. class KmsClient { public: // Returns true iff this client does support KMS key specified by 'key_uri'. virtual bool DoesSupport(absl::string_view key_uri) const = 0; // Returns an Aead-primitive backed by KMS key specified by 'key_uri', // provided that this KmsClient does support 'key_uri'. virtual crypto::tink::util::StatusOr> GetAead(absl::string_view key_uri) const = 0; virtual ~KmsClient() = default; }; } // namespace tink } // namespace crypto #endif // TINK_KMS_CLIENT_H_ ================================================ FILE: cc/kms_clients.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_KMS_CLIENTS_H_ #define TINK_KMS_CLIENTS_H_ #include #include #include #include "absl/base/thread_annotations.h" #include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" #include "tink/kms_client.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // A container for KmsClient-objects that are needed by KeyManager-objects for // primitives that use KMS-managed keys. // // This class consists exclusively of static methods that register and load // KmsClient-objects. class KmsClients { public: // Adds 'kms_client' to the global list of known clients. // // This function should only be called on startup and not on every operation. // Avoid registering a client more than once. // // It is often not necessary to use this function. For example, you can call // kms_client.GetAead to get a remote AEAD instance, and use that to create // an encrypted keyset using KeysetHandle::Write, or create an envelope // AEAD using KmsEnvelopeAead::New. static crypto::tink::util::Status Add(std::unique_ptr kms_client) { return GlobalInstance().LocalAdd(std::move(kms_client)); } // Returns the first KmsClient that was added previously via Add(), // and that does support 'key_uri', which must be non-empty. // Retains the ownership of the returned KmsClient. static crypto::tink::util::StatusOr Get(absl::string_view key_uri) { return GlobalInstance().LocalGet(key_uri); } private: KmsClients() {} // Per-instance API, to be used by GlobalInstance(); crypto::tink::util::Status LocalAdd(std::unique_ptr kms_client); crypto::tink::util::StatusOr LocalGet(absl::string_view key_uri); absl::Mutex clients_mutex_; std::vector> clients_ ABSL_GUARDED_BY(clients_mutex_); static KmsClients& GlobalInstance(); }; } // namespace tink } // namespace crypto #endif // TINK_KMS_CLIENTS_H_ ================================================ FILE: cc/mac/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "mac_wrapper", srcs = ["mac_wrapper.cc"], hdrs = ["mac_wrapper.h"], include_prefix = "tink/mac", deps = [ "//:crypto_format", "//:mac", "//:primitive_set", "//:primitive_wrapper", "//internal:monitoring_util", "//internal:registry_impl", "//internal:util", "//monitoring", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "mac_config", srcs = ["mac_config.cc"], hdrs = ["mac_config.h"], include_prefix = "tink/mac", visibility = ["//visibility:public"], deps = [ ":aes_cmac_key_manager", ":aes_cmac_proto_serialization", ":hmac_key_manager", ":hmac_proto_serialization", ":mac_wrapper", "//:registry", "//config:config_util", "//config:tink_fips", "//mac/internal:chunked_mac_wrapper", "//proto:config_cc_proto", "//util:status", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/memory", ], ) cc_library( name = "mac_factory", srcs = ["mac_factory.cc"], hdrs = ["mac_factory.h"], include_prefix = "tink/mac", deps = [ ":mac_wrapper", "//:key_manager", "//:keyset_handle", "//:mac", "//:registry", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", ], ) cc_library( name = "mac_key_templates", srcs = ["mac_key_templates.cc"], hdrs = ["mac_key_templates.h"], include_prefix = "tink/mac", visibility = ["//visibility:public"], deps = [ "//proto:aes_cmac_cc_proto", "//proto:common_cc_proto", "//proto:hmac_cc_proto", "//proto:tink_cc_proto", ], ) cc_library( name = "aes_cmac_key_manager", hdrs = ["aes_cmac_key_manager.h"], include_prefix = "tink/mac", deps = [ "//:chunked_mac", "//:core/key_type_manager", "//:core/template_util", "//:key_manager", "//:mac", "//mac/internal:chunked_mac_impl", "//proto:aes_cmac_cc_proto", "//proto:tink_cc_proto", "//subtle:aes_cmac_boringssl", "//subtle:random", "//util:constants", "//util:errors", "//util:protobuf_helper", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "hmac_key_manager", srcs = ["hmac_key_manager.cc"], hdrs = ["hmac_key_manager.h"], include_prefix = "tink/mac", deps = [ "//:chunked_mac", "//:core/key_type_manager", "//:core/template_util", "//:input_stream", "//:mac", "//internal:fips_utils", "//mac/internal:chunked_mac_impl", "//proto:common_cc_proto", "//proto:hmac_cc_proto", "//proto:tink_cc_proto", "//subtle:hmac_boringssl", "//subtle:random", "//util:constants", "//util:enums", "//util:errors", "//util:input_stream_util", "//util:protobuf_helper", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "mac_parameters", hdrs = ["mac_parameters.h"], include_prefix = "tink/mac", deps = ["//:parameters"], ) cc_library( name = "mac_key", hdrs = ["mac_key.h"], include_prefix = "tink/mac", deps = [ ":mac_parameters", "//:key", "//util:statusor", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "failing_mac", testonly = 1, srcs = ["failing_mac.cc"], hdrs = ["failing_mac.h"], include_prefix = "tink/mac", visibility = ["//visibility:public"], deps = [ "//:mac", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "aes_cmac_parameters", srcs = ["aes_cmac_parameters.cc"], hdrs = ["aes_cmac_parameters.h"], include_prefix = "tink/mac", deps = [ ":mac_parameters", "//:crypto_format", "//:parameters", "//internal:util", "//util:status", "//util:statusor", "@com_google_absl//absl/log", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "aes_cmac_key", srcs = ["aes_cmac_key.cc"], hdrs = ["aes_cmac_key.h"], include_prefix = "tink/mac", deps = [ ":aes_cmac_parameters", ":mac_key", "//:key", "//:partial_key_access_token", "//:restricted_data", "//subtle:subtle_util", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:str_format", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "aes_cmac_proto_serialization", srcs = ["aes_cmac_proto_serialization.cc"], hdrs = ["aes_cmac_proto_serialization.h"], include_prefix = "tink/mac", deps = [ ":aes_cmac_key", ":aes_cmac_parameters", "//:partial_key_access", "//:restricted_data", "//:secret_key_access_token", "//internal:key_parser", "//internal:key_serializer", "//internal:mutable_serialization_registry", "//internal:parameters_parser", "//internal:parameters_serializer", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//proto:aes_cmac_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "hmac_parameters", srcs = ["hmac_parameters.cc"], hdrs = ["hmac_parameters.h"], include_prefix = "tink/mac", deps = [ ":mac_parameters", "//:crypto_format", "//:parameters", "//internal:util", "//util:status", "//util:statusor", "@com_google_absl//absl/log", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "hmac_key", srcs = ["hmac_key.cc"], hdrs = ["hmac_key.h"], include_prefix = "tink/mac", deps = [ ":hmac_parameters", ":mac_key", "//:key", "//:partial_key_access_token", "//:restricted_data", "//subtle:subtle_util", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:str_format", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "hmac_proto_serialization", srcs = ["hmac_proto_serialization.cc"], hdrs = ["hmac_proto_serialization.h"], include_prefix = "tink/mac", deps = [ ":hmac_key", ":hmac_parameters", "//:partial_key_access", "//:restricted_data", "//:secret_key_access_token", "//internal:key_parser", "//internal:key_serializer", "//internal:mutable_serialization_registry", "//internal:parameters_parser", "//internal:parameters_serializer", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//proto:common_cc_proto", "//proto:hmac_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "config_v0", srcs = ["config_v0.cc"], hdrs = ["config_v0.h"], include_prefix = "tink/mac", deps = [ "//:configuration", "//mac/internal:config_v0", "@com_google_absl//absl/log:check", ], ) cc_library( name = "key_gen_config_v0", srcs = ["key_gen_config_v0.cc"], hdrs = ["key_gen_config_v0.h"], include_prefix = "tink/mac", deps = [ "//:key_gen_configuration", "//mac/internal:key_gen_config_v0", "@com_google_absl//absl/log:check", ], ) # tests cc_test( name = "mac_wrapper_test", size = "small", srcs = ["mac_wrapper_test.cc"], deps = [ ":failing_mac", ":mac_wrapper", "//:crypto_format", "//:mac", "//:primitive_set", "//:registry", "//internal:registry_impl", "//monitoring", "//monitoring:monitoring_client_mocks", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "mac_config_test", size = "small", srcs = ["mac_config_test.cc"], tags = ["fips"], deps = [ ":aes_cmac_key", ":aes_cmac_key_manager", ":aes_cmac_parameters", ":hmac_key", ":hmac_key_manager", ":hmac_parameters", ":mac_config", ":mac_key_templates", "//:chunked_mac", "//:insecure_secret_key_access", "//:key", "//:keyset_handle", "//:mac", "//:parameters", "//:partial_key_access", "//:primitive_set", "//:registry", "//:restricted_data", "//config:global_registry", "//internal:fips_utils", "//internal:mutable_serialization_registry", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//internal:serialization", "//proto:aes_cmac_cc_proto", "//proto:common_cc_proto", "//proto:hmac_cc_proto", "//proto:tink_cc_proto", "//subtle:random", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "mac_factory_test", size = "small", srcs = ["mac_factory_test.cc"], deps = [ ":hmac_key_manager", ":mac_config", ":mac_factory", "//:crypto_format", "//:keyset_handle", "//:mac", "//internal:key_info", "//proto:common_cc_proto", "//proto:hmac_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:test_keyset_handle", "//util:test_util", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "mac_key_templates_test", size = "small", srcs = ["mac_key_templates_test.cc"], deps = [ ":aes_cmac_key_manager", ":hmac_key_manager", ":mac_key_templates", "//:core/key_manager_impl", "//:mac", "//proto:aes_cmac_cc_proto", "//proto:common_cc_proto", "//proto:hmac_cc_proto", "//proto:tink_cc_proto", "//util:test_matchers", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_cmac_key_manager_test", size = "small", srcs = ["aes_cmac_key_manager_test.cc"], deps = [ ":aes_cmac_key_manager", "//:chunked_mac", "//:mac", "//proto:aes_cmac_cc_proto", "//proto:tink_cc_proto", "//subtle:aes_cmac_boringssl", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hmac_key_manager_test", size = "small", srcs = ["hmac_key_manager_test.cc"], deps = [ ":hmac_key_manager", "//:chunked_mac", "//:core/key_manager_impl", "//:mac", "//proto:hmac_cc_proto", "//proto:tink_cc_proto", "//subtle:hmac_boringssl", "//util:enums", "//util:istream_input_stream", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "failing_mac_test", srcs = ["failing_mac_test.cc"], deps = [ ":failing_mac", "//:mac", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_cmac_parameters_test", size = "small", srcs = ["aes_cmac_parameters_test.cc"], deps = [ ":aes_cmac_parameters", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_cmac_key_test", size = "small", srcs = ["aes_cmac_key_test.cc"], deps = [ ":aes_cmac_key", ":aes_cmac_parameters", "//:partial_key_access", "//:restricted_data", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_cmac_proto_serialization_test", size = "small", srcs = ["aes_cmac_proto_serialization_test.cc"], deps = [ ":aes_cmac_key", ":aes_cmac_parameters", ":aes_cmac_proto_serialization", "//:insecure_secret_key_access", "//:key", "//:parameters", "//:partial_key_access", "//:restricted_data", "//internal:mutable_serialization_registry", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//internal:serialization", "//proto:aes_cmac_cc_proto", "//proto:tink_cc_proto", "//subtle:random", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hmac_parameters_test", size = "small", srcs = ["hmac_parameters_test.cc"], deps = [ ":hmac_parameters", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hmac_key_test", srcs = ["hmac_key_test.cc"], deps = [ ":hmac_key", ":hmac_parameters", "//:partial_key_access", "//:restricted_data", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hmac_proto_serialization_test", srcs = ["hmac_proto_serialization_test.cc"], deps = [ ":hmac_key", ":hmac_parameters", ":hmac_proto_serialization", "//:insecure_secret_key_access", "//:key", "//:parameters", "//:partial_key_access", "//:restricted_data", "//internal:mutable_serialization_registry", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//internal:serialization", "//proto:common_cc_proto", "//proto:hmac_cc_proto", "//proto:tink_cc_proto", "//subtle:random", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "config_v0_test", srcs = ["config_v0_test.cc"], deps = [ ":config_v0", ":key_gen_config_v0", ":mac_key_templates", "//:chunked_mac", "//:key_gen_configuration", "//:keyset_handle", "//:mac", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/mac/CMakeLists.txt ================================================ tink_module(mac) add_subdirectory(internal) tink_cc_library( NAME mac_wrapper SRCS mac_wrapper.cc mac_wrapper.h DEPS absl::memory absl::status absl::strings tink::core::crypto_format tink::core::mac tink::core::primitive_set tink::core::primitive_wrapper tink::internal::monitoring_util tink::internal::registry_impl tink::internal::util tink::monitoring::monitoring tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME mac_config SRCS mac_config.cc mac_config.h DEPS tink::mac::aes_cmac_key_manager tink::mac::aes_cmac_proto_serialization tink::mac::hmac_key_manager tink::mac::hmac_proto_serialization tink::mac::mac_wrapper absl::core_headers absl::memory tink::core::registry tink::config::config_util tink::config::tink_fips tink::mac::internal::chunked_mac_wrapper tink::util::status tink::proto::config_cc_proto ) tink_cc_library( NAME mac_factory SRCS mac_factory.cc mac_factory.h DEPS tink::mac::mac_wrapper absl::core_headers tink::core::key_manager tink::core::keyset_handle tink::core::mac tink::core::registry tink::util::status tink::util::statusor ) tink_cc_library( NAME mac_key_templates SRCS mac_key_templates.cc mac_key_templates.h DEPS tink::proto::aes_cmac_cc_proto tink::proto::common_cc_proto tink::proto::hmac_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME aes_cmac_key_manager SRCS aes_cmac_key_manager.h DEPS absl::memory absl::status absl::strings tink::core::chunked_mac tink::core::key_type_manager tink::core::template_util tink::core::key_manager tink::core::mac tink::mac::internal::chunked_mac_impl tink::subtle::aes_cmac_boringssl tink::subtle::random tink::util::constants tink::util::errors tink::util::protobuf_helper tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::aes_cmac_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME hmac_key_manager SRCS hmac_key_manager.cc hmac_key_manager.h DEPS absl::memory absl::status absl::strings tink::core::chunked_mac tink::core::key_type_manager tink::core::template_util tink::core::input_stream tink::core::mac tink::internal::fips_utils tink::mac::internal::chunked_mac_impl tink::subtle::hmac_boringssl tink::subtle::random tink::util::constants tink::util::enums tink::util::errors tink::util::input_stream_util tink::util::protobuf_helper tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::common_cc_proto tink::proto::hmac_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME mac_parameters SRCS mac_parameters.h DEPS tink::core::parameters ) tink_cc_library( NAME mac_key SRCS mac_key.h DEPS tink::mac::mac_parameters absl::string_view tink::core::key tink::util::statusor ) tink_cc_library( NAME failing_mac SRCS failing_mac.cc failing_mac.h DEPS absl::memory absl::status absl::strings tink::core::mac tink::util::status tink::util::statusor TESTONLY ) tink_cc_library( NAME aes_cmac_parameters SRCS aes_cmac_parameters.cc aes_cmac_parameters.h DEPS tink::mac::mac_parameters absl::log absl::status absl::strings tink::core::crypto_format tink::core::parameters tink::internal::util tink::util::status tink::util::statusor ) tink_cc_library( NAME aes_cmac_key SRCS aes_cmac_key.cc aes_cmac_key.h DEPS tink::mac::aes_cmac_parameters tink::mac::mac_key absl::core_headers absl::status absl::strings absl::str_format absl::optional crypto tink::core::key tink::core::partial_key_access_token tink::core::restricted_data tink::subtle::subtle_util tink::util::status tink::util::statusor ) tink_cc_library( NAME aes_cmac_proto_serialization SRCS aes_cmac_proto_serialization.cc aes_cmac_proto_serialization.h DEPS tink::mac::aes_cmac_key tink::mac::aes_cmac_parameters absl::status absl::string_view absl::optional tink::core::partial_key_access tink::core::restricted_data tink::core::secret_key_access_token tink::internal::key_parser tink::internal::key_serializer tink::internal::mutable_serialization_registry tink::internal::parameters_parser tink::internal::parameters_serializer tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::util::status tink::util::statusor tink::proto::aes_cmac_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME hmac_parameters SRCS hmac_parameters.cc hmac_parameters.h DEPS tink::mac::mac_parameters absl::log absl::status absl::strings tink::core::crypto_format tink::core::parameters tink::internal::util tink::util::status tink::util::statusor ) tink_cc_library( NAME hmac_key SRCS hmac_key.cc hmac_key.h DEPS tink::mac::hmac_parameters tink::mac::mac_key absl::core_headers absl::status absl::strings absl::str_format absl::optional tink::core::key tink::core::partial_key_access_token tink::core::restricted_data tink::subtle::subtle_util tink::util::status tink::util::statusor ) tink_cc_library( NAME hmac_proto_serialization SRCS hmac_proto_serialization.cc hmac_proto_serialization.h DEPS tink::mac::hmac_key tink::mac::hmac_parameters absl::status absl::string_view absl::optional tink::core::partial_key_access tink::core::restricted_data tink::core::secret_key_access_token tink::internal::key_parser tink::internal::key_serializer tink::internal::mutable_serialization_registry tink::internal::parameters_parser tink::internal::parameters_serializer tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::util::status tink::util::statusor tink::proto::common_cc_proto tink::proto::hmac_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME config_v0 SRCS config_v0.cc config_v0.h DEPS absl::check tink::core::configuration tink::mac::internal::config_v0 ) tink_cc_library( NAME key_gen_config_v0 SRCS key_gen_config_v0.cc key_gen_config_v0.h DEPS absl::check tink::core::key_gen_configuration tink::mac::internal::key_gen_config_v0 ) # tests tink_cc_test( NAME mac_wrapper_test SRCS mac_wrapper_test.cc DEPS tink::mac::failing_mac tink::mac::mac_wrapper gmock absl::flat_hash_map absl::memory absl::status absl::strings tink::core::crypto_format tink::core::mac tink::core::primitive_set tink::core::registry tink::internal::registry_impl tink::monitoring::monitoring tink::monitoring::monitoring_client_mocks tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::tink_cc_proto ) tink_cc_test( NAME mac_config_test SRCS mac_config_test.cc DEPS tink::mac::aes_cmac_key tink::mac::aes_cmac_key_manager tink::mac::aes_cmac_parameters tink::mac::hmac_key tink::mac::hmac_key_manager tink::mac::hmac_parameters tink::mac::mac_config tink::mac::mac_key_templates gmock absl::memory absl::status crypto tink::core::chunked_mac tink::core::insecure_secret_key_access tink::core::key tink::core::keyset_handle tink::core::mac tink::core::parameters tink::core::partial_key_access tink::core::primitive_set tink::core::registry tink::core::restricted_data tink::config::global_registry tink::internal::fips_utils tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::internal::serialization tink::subtle::random tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::aes_cmac_cc_proto tink::proto::common_cc_proto tink::proto::hmac_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME mac_factory_test SRCS mac_factory_test.cc DEPS tink::mac::hmac_key_manager tink::mac::mac_config tink::mac::mac_factory gmock tink::core::crypto_format tink::core::keyset_handle tink::core::mac tink::internal::key_info tink::util::status tink::util::test_keyset_handle tink::util::test_util tink::proto::common_cc_proto tink::proto::hmac_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME mac_key_templates_test SRCS mac_key_templates_test.cc DEPS tink::mac::aes_cmac_key_manager tink::mac::hmac_key_manager tink::mac::mac_key_templates gmock tink::core::key_manager_impl tink::core::mac tink::util::test_matchers tink::proto::aes_cmac_cc_proto tink::proto::common_cc_proto tink::proto::hmac_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME aes_cmac_key_manager_test SRCS aes_cmac_key_manager_test.cc DEPS tink::mac::aes_cmac_key_manager gmock tink::core::chunked_mac tink::core::mac tink::subtle::aes_cmac_boringssl tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::aes_cmac_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME hmac_key_manager_test SRCS hmac_key_manager_test.cc DEPS tink::mac::hmac_key_manager gmock absl::memory absl::status tink::core::chunked_mac tink::core::key_manager_impl tink::core::mac tink::subtle::hmac_boringssl tink::util::enums tink::util::istream_input_stream tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::hmac_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME failing_mac_test SRCS failing_mac_test.cc DEPS tink::mac::failing_mac gmock absl::status tink::core::mac tink::util::test_matchers ) tink_cc_test( NAME aes_cmac_parameters_test SRCS aes_cmac_parameters_test.cc DEPS tink::mac::aes_cmac_parameters gmock absl::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME aes_cmac_key_test SRCS aes_cmac_key_test.cc DEPS tink::mac::aes_cmac_key tink::mac::aes_cmac_parameters gmock absl::status absl::optional tink::core::partial_key_access tink::core::restricted_data tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME aes_cmac_proto_serialization_test SRCS aes_cmac_proto_serialization_test.cc DEPS tink::mac::aes_cmac_key tink::mac::aes_cmac_parameters tink::mac::aes_cmac_proto_serialization gmock absl::status absl::optional tink::core::insecure_secret_key_access tink::core::key tink::core::parameters tink::core::partial_key_access tink::core::restricted_data tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::internal::serialization tink::subtle::random tink::util::statusor tink::util::test_matchers tink::proto::aes_cmac_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME hmac_parameters_test SRCS hmac_parameters_test.cc DEPS tink::mac::hmac_parameters gmock absl::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME hmac_key_test SRCS hmac_key_test.cc DEPS tink::mac::hmac_key tink::mac::hmac_parameters gmock absl::status absl::optional tink::core::partial_key_access tink::core::restricted_data tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME hmac_proto_serialization_test SRCS hmac_proto_serialization_test.cc DEPS tink::mac::hmac_key tink::mac::hmac_parameters tink::mac::hmac_proto_serialization gmock absl::status absl::optional tink::core::insecure_secret_key_access tink::core::key tink::core::parameters tink::core::partial_key_access tink::core::restricted_data tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::internal::serialization tink::subtle::random tink::util::statusor tink::util::test_matchers tink::proto::common_cc_proto tink::proto::hmac_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME config_v0_test SRCS config_v0_test.cc DEPS tink::mac::config_v0 tink::mac::key_gen_config_v0 tink::mac::mac_key_templates gmock tink::core::chunked_mac tink::core::key_gen_configuration tink::core::keyset_handle tink::core::mac tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) ================================================ FILE: cc/mac/aes_cmac_key.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/aes_cmac_key.h" #include #include #include #include "absl/base/attributes.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/types/optional.h" #include "tink/key.h" #include "tink/mac/aes_cmac_parameters.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { util::StatusOr AesCmacKey::Create( const AesCmacParameters& parameters, const RestrictedData& key_bytes, absl::optional id_requirement, PartialKeyAccessToken token) { if (parameters.KeySizeInBytes() != key_bytes.size()) { return util::Status(absl::StatusCode::kInvalidArgument, "Key size does not match AES-CMAC parameters"); } if (parameters.HasIdRequirement() && !id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key without ID requirement with parameters with ID " "requirement"); } if (!parameters.HasIdRequirement() && id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key with ID requirement with parameters without ID " "requirement"); } util::StatusOr output_prefix = ComputeOutputPrefix(parameters, id_requirement); if (!output_prefix.ok()) { return output_prefix.status(); } return AesCmacKey(parameters, key_bytes, id_requirement, *std::move(output_prefix)); } util::StatusOr AesCmacKey::ComputeOutputPrefix( const AesCmacParameters& parameters, absl::optional id_requirement) { switch (parameters.GetVariant()) { case AesCmacParameters::Variant::kNoPrefix: return std::string(""); // Empty prefix. case AesCmacParameters::Variant::kLegacy: ABSL_FALLTHROUGH_INTENDED; case AesCmacParameters::Variant::kCrunchy: if (!id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "id requirement must have value with kCrunchy or kLegacy"); } return absl::StrCat(absl::HexStringToBytes("00"), subtle::BigEndian32(*id_requirement)); case AesCmacParameters::Variant::kTink: if (!id_requirement.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "id requirement must have value with kTink"); } return absl::StrCat(absl::HexStringToBytes("01"), subtle::BigEndian32(*id_requirement)); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid variant: ", parameters.GetVariant())); } } bool AesCmacKey::operator==(const Key& other) const { const AesCmacKey* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (GetParameters() != that->GetParameters()) { return false; } if (id_requirement_ != that->id_requirement_) { return false; } return key_bytes_ == that->key_bytes_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/aes_cmac_key.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_AES_CMAC_KEY_H_ #define TINK_MAC_AES_CMAC_KEY_H_ #include #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/key.h" #include "tink/mac/aes_cmac_parameters.h" #include "tink/mac/mac_key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { class AesCmacKey : public MacKey { public: // Copyable and movable. AesCmacKey(const AesCmacKey& other) = default; AesCmacKey& operator=(const AesCmacKey& other) = default; AesCmacKey(AesCmacKey&& other) = default; AesCmacKey& operator=(AesCmacKey&& other) = default; // Creates a new AES-CMAC key. If the parameters specify a variant that uses // a prefix, then the id is used to compute this prefix. static util::StatusOr Create(const AesCmacParameters& parameters, const RestrictedData& key_bytes, absl::optional id_requirement, PartialKeyAccessToken token); // Returns the underlying AES key. const RestrictedData& GetKeyBytes(PartialKeyAccessToken token) const { return key_bytes_; } absl::string_view GetOutputPrefix() const override { return output_prefix_; } const AesCmacParameters& GetParameters() const override { return parameters_; } absl::optional GetIdRequirement() const override { return id_requirement_; } bool operator==(const Key& other) const override; private: AesCmacKey(const AesCmacParameters& parameters, const RestrictedData& key_bytes, absl::optional id_requirement, std::string output_prefix) : parameters_(parameters), key_bytes_(key_bytes), id_requirement_(id_requirement), output_prefix_(std::move(output_prefix)) {} static util::StatusOr ComputeOutputPrefix( const AesCmacParameters& parameters, absl::optional id_requirement); AesCmacParameters parameters_; RestrictedData key_bytes_; absl::optional id_requirement_; std::string output_prefix_; }; } // namespace tink } // namespace crypto #endif // TINK_MAC_AES_CMAC_KEY_H_ ================================================ FILE: cc/mac/aes_cmac_key_manager.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_AES_CMAC_KEY_MANAGER_H_ #define TINK_MAC_AES_CMAC_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/chunked_mac.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/key_manager.h" #include "tink/mac.h" #include "tink/mac/internal/chunked_mac_impl.h" #include "tink/subtle/aes_cmac_boringssl.h" #include "tink/subtle/random.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/aes_cmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class AesCmacKeyManager : public KeyTypeManager> { public: class MacFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::AesCmacKey& key) const override { return subtle::AesCmacBoringSsl::New( util::SecretDataFromStringView(key.key_value()), key.params().tag_size()); } }; class ChunkedMacFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::AesCmacKey& key) const override { return internal::NewChunkedCmac(key); } }; AesCmacKeyManager() : KeyTypeManager( absl::make_unique(), absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::SYMMETRIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::AesCmacKey& key) const override { crypto::tink::util::Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; if (key.key_value().size() != kKeySizeInBytes) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, "Invalid AesCmacKey: key_value wrong length."); } return ValidateParams(key.params()); } crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::AesCmacKeyFormat& key_format) const override { if (key_format.key_size() != kKeySizeInBytes) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, "Invalid AesCmacKeyFormat: invalid key_size."); } return ValidateParams(key_format.params()); } crypto::tink::util::StatusOr CreateKey( const google::crypto::tink::AesCmacKeyFormat& key_format) const override { google::crypto::tink::AesCmacKey key; key.set_version(get_version()); key.set_key_value( subtle::Random::GetRandomBytes(key_format.key_size())); *key.mutable_params() = key_format.params(); return key; } private: crypto::tink::util::Status ValidateParams( const google::crypto::tink::AesCmacParams& params) const { if (params.tag_size() < kMinTagSizeInBytes) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid AesCmacParams: tag_size ", params.tag_size(), " is too small.")); } if (params.tag_size() > kMaxTagSizeInBytes) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid AesCmacParams: tag_size ", params.tag_size(), " is too big.")); } return util::OkStatus(); } // Due to https://www.math.uwaterloo.ca/~ajmeneze/publications/tightness.pdf, // we only allow key sizes of 256 bit. const int kKeySizeInBytes = 32; const int kMaxTagSizeInBytes = 16; const int kMinTagSizeInBytes = 10; const std::string key_type_ = absl::StrCat( kTypeGoogleapisCom, google::crypto::tink::AesCmacKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_MAC_AES_CMAC_KEY_MANAGER_H_ ================================================ FILE: cc/mac/aes_cmac_key_manager_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/aes_cmac_key_manager.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/chunked_mac.h" #include "tink/mac.h" #include "tink/subtle/aes_cmac_boringssl.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/aes_cmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::google::crypto::tink::AesCmacKey; using ::google::crypto::tink::AesCmacKeyFormat; using ::google::crypto::tink::AesCmacParams; using ::testing::Eq; using ::testing::Not; using ::testing::SizeIs; TEST(AesCmacKeyManagerTest, Basics) { EXPECT_THAT(AesCmacKeyManager().get_version(), Eq(0)); EXPECT_THAT(AesCmacKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.AesCmacKey")); EXPECT_THAT(AesCmacKeyManager().key_material_type(), Eq(google::crypto::tink::KeyData::SYMMETRIC)); } TEST(AesCmacKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(AesCmacKeyManager().ValidateKey(AesCmacKey()), Not(IsOk())); } AesCmacParams ValidParams() { AesCmacParams params; params.set_tag_size(16); return params; } AesCmacKeyFormat ValidKeyFormat() { AesCmacKeyFormat format; *format.mutable_params() = ValidParams(); format.set_key_size(32); return format; } TEST(AesCmacKeyManagerTest, ValidateEmptyKeyFormat) { EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(AesCmacKeyFormat()), Not(IsOk())); } TEST(AesCmacKeyManagerTest, ValidateSimpleKeyFormat) { EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(ValidKeyFormat()), IsOk()); } TEST(AesCmacKeyManagerTest, ValidateKeyFormatKeySizes) { AesCmacKeyFormat format = ValidKeyFormat(); format.set_key_size(0); EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), Not(IsOk())); format.set_key_size(1); EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), Not(IsOk())); format.set_key_size(15); EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), Not(IsOk())); format.set_key_size(16); EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), Not(IsOk())); format.set_key_size(17); EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), Not(IsOk())); format.set_key_size(31); EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), Not(IsOk())); format.set_key_size(32); EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), IsOk()); format.set_key_size(33); EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), Not(IsOk())); } TEST(AesCmacKeyManagerTest, ValidateKeyFormatTagSizes) { AesCmacKeyFormat format = ValidKeyFormat(); format.mutable_params()->set_tag_size(0); EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), Not(IsOk())); format.mutable_params()->set_tag_size(9); EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), Not(IsOk())); format.mutable_params()->set_tag_size(10); EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), IsOk()); format.mutable_params()->set_tag_size(11); EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), IsOk()); format.mutable_params()->set_tag_size(12); EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), IsOk()); format.mutable_params()->set_tag_size(15); EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), IsOk()); format.mutable_params()->set_tag_size(16); EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), IsOk()); format.mutable_params()->set_tag_size(17); EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), Not(IsOk())); format.mutable_params()->set_tag_size(32); EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), Not(IsOk())); } TEST(AesCmacKeyManagerTest, CreateKey) { AesCmacKeyFormat format = ValidKeyFormat(); ASSERT_THAT(AesCmacKeyManager().CreateKey(format), IsOk()); AesCmacKey key = AesCmacKeyManager().CreateKey(format).value(); EXPECT_THAT(key.version(), Eq(0)); EXPECT_THAT(key.key_value(), SizeIs(format.key_size())); EXPECT_THAT(key.params().tag_size(), Eq(format.params().tag_size())); } TEST(AesCmacKeyManagerTest, ValidateKey) { AesCmacKeyFormat format = ValidKeyFormat(); AesCmacKey key = AesCmacKeyManager().CreateKey(format).value(); EXPECT_THAT(AesCmacKeyManager().ValidateKey(key), IsOk()); } TEST(AesCmacKeyManagerTest, ValidateKeyInvalidVersion) { AesCmacKeyFormat format = ValidKeyFormat(); AesCmacKey key = AesCmacKeyManager().CreateKey(format).value(); key.set_version(1); EXPECT_THAT(AesCmacKeyManager().ValidateKey(key), Not(IsOk())); } TEST(AesCmacKeyManagerTest, ValidateKeyShortKey) { AesCmacKeyFormat format = ValidKeyFormat(); AesCmacKey key = AesCmacKeyManager().CreateKey(format).value(); key.set_key_value("0123456789abcdef"); EXPECT_THAT(AesCmacKeyManager().ValidateKey(key), Not(IsOk())); } TEST(AesCmacKeyManagerTest, ValidateKeyLongTagSize) { AesCmacKeyFormat format = ValidKeyFormat(); AesCmacKey key = AesCmacKeyManager().CreateKey(format).value(); key.mutable_params()->set_tag_size(17); EXPECT_THAT(AesCmacKeyManager().ValidateKey(key), Not(IsOk())); } TEST(AesCmacKeyManagerTest, ValidateKeyTooShortTagSize) { AesCmacKeyFormat format = ValidKeyFormat(); AesCmacKey key = AesCmacKeyManager().CreateKey(format).value(); key.mutable_params()->set_tag_size(9); EXPECT_THAT(AesCmacKeyManager().ValidateKey(key), Not(IsOk())); } TEST(AesCmacKeyManagerTest, GetMacPrimitive) { AesCmacKeyFormat format = ValidKeyFormat(); AesCmacKey key = AesCmacKeyManager().CreateKey(format).value(); auto manager_mac_or = AesCmacKeyManager().GetPrimitive(key); ASSERT_THAT(manager_mac_or, IsOk()); auto mac_value_or = manager_mac_or.value()->ComputeMac("some plaintext"); ASSERT_THAT(mac_value_or, IsOk()); auto direct_mac_or = subtle::AesCmacBoringSsl::New( util::SecretDataFromStringView(key.key_value()), key.params().tag_size()); ASSERT_THAT(direct_mac_or, IsOk()); EXPECT_THAT( direct_mac_or.value()->VerifyMac(mac_value_or.value(), "some plaintext"), IsOk()); } TEST(AesCmacKeyManagerTest, GetChunkedMacPrimitive) { AesCmacKeyFormat format = ValidKeyFormat(); AesCmacKey key = AesCmacKeyManager().CreateKey(format).value(); util::StatusOr> chunked_mac = AesCmacKeyManager().GetPrimitive(key); ASSERT_THAT(chunked_mac, IsOk()); util::StatusOr> computation = (*chunked_mac)->CreateComputation(); ASSERT_THAT(computation, IsOk()); ASSERT_THAT((*computation)->Update("abc"), IsOk()); ASSERT_THAT((*computation)->Update("xyz"), IsOk()); util::StatusOr tag = (*computation)->ComputeMac(); ASSERT_THAT(tag, IsOk()); util::StatusOr> verification = (*chunked_mac)->CreateVerification(*tag); ASSERT_THAT(verification, IsOk()); ASSERT_THAT((*verification)->Update("abc"), IsOk()); ASSERT_THAT((*verification)->Update("xyz"), IsOk()); EXPECT_THAT((*verification)->VerifyMac(), IsOk()); } TEST(AesCmacKeyManagerTest, MixPrimitives) { AesCmacKeyFormat format = ValidKeyFormat(); AesCmacKey key = AesCmacKeyManager().CreateKey(format).value(); util::StatusOr> mac = AesCmacKeyManager().GetPrimitive(key); ASSERT_THAT(mac, IsOk()); util::StatusOr> chunked_mac = AesCmacKeyManager().GetPrimitive(key); ASSERT_THAT(chunked_mac, IsOk()); // Compute tag with Mac. util::StatusOr tag = (*mac)->ComputeMac("abcxyz"); ASSERT_THAT(tag, IsOk()); // Compute chunked tag with ChunkedMac. util::StatusOr> computation = (*chunked_mac)->CreateComputation(); ASSERT_THAT(computation, IsOk()); ASSERT_THAT((*computation)->Update("abc"), IsOk()); ASSERT_THAT((*computation)->Update("xyz"), IsOk()); util::StatusOr chunked_tag = (*computation)->ComputeMac(); ASSERT_THAT(chunked_tag, IsOk()); ASSERT_THAT(*chunked_tag, Eq(*tag)); // Both primitives generated same tag. // Verify chunked tag with Mac. ASSERT_THAT((*mac)->VerifyMac(*chunked_tag, "abcxyz"), IsOk()); // Verify tag with ChunkedMac. util::StatusOr> verification = (*chunked_mac)->CreateVerification(*tag); ASSERT_THAT(verification, IsOk()); ASSERT_THAT((*verification)->Update("abc"), IsOk()); ASSERT_THAT((*verification)->Update("xyz"), IsOk()); EXPECT_THAT((*verification)->VerifyMac(), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/aes_cmac_key_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/aes_cmac_key.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/mac/aes_cmac_parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Combine; using ::testing::Eq; using ::testing::Range; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { AesCmacParameters::Variant variant; absl::optional id_requirement; std::string output_prefix; }; using AesCmacKeyTest = TestWithParam>; INSTANTIATE_TEST_SUITE_P( AesCmacKeyTestSuite, AesCmacKeyTest, Combine(Values(16, 32), Range(10, 16), Values(TestCase{AesCmacParameters::Variant::kTink, 0x02030400, std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{AesCmacParameters::Variant::kCrunchy, 0x01030005, std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{AesCmacParameters::Variant::kLegacy, 0x01020304, std::string("\x00\x01\x02\x03\x04", 5)}, TestCase{AesCmacParameters::Variant::kNoPrefix, absl::nullopt, ""}))); TEST_P(AesCmacKeyTest, CreateSucceeds) { int key_size; int cryptographic_tag_size; TestCase test_case; std::tie(key_size, cryptographic_tag_size, test_case) = GetParam(); util::StatusOr params = AesCmacParameters::Create( key_size, cryptographic_tag_size, test_case.variant); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(key_size); util::StatusOr key = AesCmacKey::Create( *params, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(key.status(), IsOk()); EXPECT_THAT(key->GetParameters(), Eq(*params)); EXPECT_THAT(key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(key->GetOutputPrefix(), Eq(test_case.output_prefix)); } TEST(AesCmacKeyTest, CreateKeyWithMismatchedKeySizeFails) { // Key size parameter is 32 bytes. util::StatusOr params = AesCmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16, AesCmacParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); // Key material is 16 bytes (another valid key length). RestrictedData mismatched_secret = RestrictedData(/*num_random_bytes=*/16); EXPECT_THAT(AesCmacKey::Create(*params, mismatched_secret, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesCmacKeyTest, CreateKeyWithWrongIdRequirementFails) { util::StatusOr no_prefix_params = AesCmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16, AesCmacParameters::Variant::kNoPrefix); ASSERT_THAT(no_prefix_params, IsOk()); util::StatusOr tink_params = AesCmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16, AesCmacParameters::Variant::kTink); ASSERT_THAT(tink_params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); EXPECT_THAT(AesCmacKey::Create(*no_prefix_params, secret, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesCmacKey::Create(*tink_params, secret, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(AesCmacKeyTest, GetAesCmacKey) { int key_size; int cryptographic_tag_size; TestCase test_case; std::tie(key_size, cryptographic_tag_size, test_case) = GetParam(); util::StatusOr params = AesCmacParameters::Create( key_size, cryptographic_tag_size, test_case.variant); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(key_size); util::StatusOr key = AesCmacKey::Create( *params, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(key.status(), IsOk()); EXPECT_THAT(key->GetKeyBytes(GetPartialKeyAccess()), Eq(secret)); } TEST_P(AesCmacKeyTest, KeyEquals) { int key_size; int cryptographic_tag_size; TestCase test_case; std::tie(key_size, cryptographic_tag_size, test_case) = GetParam(); util::StatusOr params = AesCmacParameters::Create( key_size, cryptographic_tag_size, test_case.variant); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(key_size); util::StatusOr key = AesCmacKey::Create( *params, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = AesCmacKey::Create( *params, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key == *other_key); EXPECT_TRUE(*other_key == *key); EXPECT_FALSE(*key != *other_key); EXPECT_FALSE(*other_key != *key); } TEST(AesCmacKeyTest, DifferentFormatNotEqual) { util::StatusOr legacy_params = AesCmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16, AesCmacParameters::Variant::kLegacy); ASSERT_THAT(legacy_params, IsOk()); util::StatusOr tink_params = AesCmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16, AesCmacParameters::Variant::kTink); ASSERT_THAT(tink_params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = AesCmacKey::Create(*legacy_params, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key.status(), IsOk()); util::StatusOr other_key = AesCmacKey::Create(*tink_params, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_key.status(), IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST(AesCmacKeyTest, DifferentSecretDataNotEqual) { util::StatusOr params = AesCmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16, AesCmacParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); RestrictedData secret1 = RestrictedData(/*num_random_bytes=*/32); RestrictedData secret2 = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = AesCmacKey::Create( *params, secret1, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key.status(), IsOk()); util::StatusOr other_key = AesCmacKey::Create( *params, secret2, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_key.status(), IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST(AesCmacKeyTest, DifferentIdRequirementNotEqual) { util::StatusOr params = AesCmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16, AesCmacParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = AesCmacKey::Create( *params, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key.status(), IsOk()); util::StatusOr other_key = AesCmacKey::Create( *params, secret, /*id_requirement=*/0x02030405, GetPartialKeyAccess()); ASSERT_THAT(other_key.status(), IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/aes_cmac_parameters.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/aes_cmac_parameters.h" #include #include #include #include #include #include "absl/log/log.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/crypto_format.h" #include "tink/internal/util.h" #include "tink/parameters.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { util::StatusOr AesCmacParameters::Create( int key_size_in_bytes, int cryptographic_tag_size_in_bytes, Variant variant) { if (key_size_in_bytes != 16 && key_size_in_bytes != 32) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Key size should be either 16 or 32 bytes, got ", key_size_in_bytes, " bytes.")); } if (cryptographic_tag_size_in_bytes < 10) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Tag size should be at least 10 bytes, got ", cryptographic_tag_size_in_bytes, " bytes.")); } if (cryptographic_tag_size_in_bytes > 16) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Tag size should not exceed 16 bytes, got ", cryptographic_tag_size_in_bytes, " bytes.")); } static const std::set* supported_variants = new std::set({Variant::kTink, Variant::kCrunchy, Variant::kLegacy, Variant::kNoPrefix}); if (supported_variants->find(variant) == supported_variants->end()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create AES-CMAC parameters with unknown variant."); } return AesCmacParameters(key_size_in_bytes, cryptographic_tag_size_in_bytes, variant); } int AesCmacParameters::TotalTagSizeInBytes() const { switch (variant_) { case Variant::kTink: case Variant::kCrunchy: case Variant::kLegacy: return CryptographicTagSizeInBytes() + CryptoFormat::kNonRawPrefixSize; case Variant::kNoPrefix: return CryptographicTagSizeInBytes(); default: // Parameters objects with unknown variants should never be created. internal::LogFatal("AES-CMAC parameters has an unknown variant."); } } bool AesCmacParameters::operator==(const Parameters& other) const { const AesCmacParameters* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (key_size_in_bytes_ != that->key_size_in_bytes_) { return false; } if (cryptographic_tag_size_in_bytes_ != that->cryptographic_tag_size_in_bytes_) { return false; } if (variant_ != that->variant_) { return false; } return true; } } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/aes_cmac_parameters.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_AES_CMAC_PARAMETERS_H_ #define TINK_MAC_AES_CMAC_PARAMETERS_H_ #include #include "tink/mac/mac_parameters.h" #include "tink/parameters.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Describes the parameters of an `AesCmacKey`. class AesCmacParameters : public MacParameters { public: // Describes the details of a MAC computation. // // The usual AES-CMAC key is used for variant `NO_PREFIX`. Other variants // slightly change how the MAC is computed, or add a prefix to every // computation depending on the key id. enum class Variant : int { // Prepends '0x01' to tag. kTink = 1, // Prepends '0x00' to tag. kCrunchy = 2, // Appends a 0-byte to input message BEFORE computing the tag, then // prepends '0x00' to tag. kLegacy = 3, // Does not prepend any prefix (i.e., keys must have no ID requirement). kNoPrefix = 4, // Added to guard from failures that may be caused by future expansions. kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Copyable and movable. AesCmacParameters(const AesCmacParameters& other) = default; AesCmacParameters& operator=(const AesCmacParameters& other) = default; AesCmacParameters(AesCmacParameters&& other) = default; AesCmacParameters& operator=(AesCmacParameters&& other) = default; // Creates a new AES-CMAC parameters object unless an error occurs. An error // occurs under one of the following conditions: // 1. `key_size_in_bytes` is a value other than 16 or 32 // 2. `cryptographic_tag_size_in_bytes` falls outside [10,...,16] static util::StatusOr Create( int key_size_in_bytes, int cryptographic_tag_size_in_bytes, Variant variant); Variant GetVariant() const { return variant_; } int KeySizeInBytes() const { return key_size_in_bytes_; } // Returns the size of the tag, which is computed cryptographically from the // message. Note that this may differ from the total size of the tag, as for // some keys, Tink prefixes the tag with a key dependent output prefix. int CryptographicTagSizeInBytes() const { return cryptographic_tag_size_in_bytes_; } // Returns the size of the cryptographic tag plus the size of the prefix with // which this key prefixes every cryptographic tag. int TotalTagSizeInBytes() const; bool HasIdRequirement() const override { return variant_ != Variant::kNoPrefix; } bool operator==(const Parameters& other) const override; private: AesCmacParameters(int key_size_in_bytes, int cryptographic_tag_size_in_bytes, Variant variant) : key_size_in_bytes_(key_size_in_bytes), cryptographic_tag_size_in_bytes_(cryptographic_tag_size_in_bytes), variant_(variant) {} int key_size_in_bytes_; int cryptographic_tag_size_in_bytes_; Variant variant_; }; } // namespace tink } // namespace crypto #endif // TINK_MAC_AES_CMAC_PARAMETERS_H_ ================================================ FILE: cc/mac/aes_cmac_parameters_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/aes_cmac_parameters.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Combine; using ::testing::Eq; using ::testing::Range; using ::testing::TestWithParam; using ::testing::Values; struct CreateTestCase { AesCmacParameters::Variant variant; int key_size; int cryptographic_tag_size; int total_tag_size; bool has_id_requirement; }; using AesCmacParametersCreateTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( AesCmacParametersCreateTestSuite, AesCmacParametersCreateTest, Values(CreateTestCase{AesCmacParameters::Variant::kTink, /*key_size=*/16, /*cryptographic_tag_size=*/10, /*total_tag_size=*/15, /*has_id_requirement=*/true}, CreateTestCase{AesCmacParameters::Variant::kCrunchy, /*key_size=*/16, /*cryptographic_tag_size=*/12, /*total_tag_size=*/17, /*has_id_requirement=*/true}, CreateTestCase{AesCmacParameters::Variant::kLegacy, /*key_size=*/32, /*cryptographic_tag_size=*/14, /*total_tag_size=*/19, /*has_id_requirement=*/true}, CreateTestCase{AesCmacParameters::Variant::kNoPrefix, /*key_size=*/32, /*cryptographic_tag_size=*/16, /*total_tag_size=*/16, /*has_id_requirement=*/false})); TEST_P(AesCmacParametersCreateTest, Create) { CreateTestCase test_case = GetParam(); util::StatusOr parameters = AesCmacParameters::Create( test_case.key_size, test_case.cryptographic_tag_size, test_case.variant); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(parameters->KeySizeInBytes(), Eq(test_case.key_size)); EXPECT_THAT(parameters->CryptographicTagSizeInBytes(), Eq(test_case.cryptographic_tag_size)); EXPECT_THAT(parameters->TotalTagSizeInBytes(), Eq(test_case.total_tag_size)); EXPECT_THAT(parameters->HasIdRequirement(), Eq(test_case.has_id_requirement)); } TEST(AesCmacParametersTest, CreateWithInvalidVariantFails) { EXPECT_THAT(AesCmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/12, AesCmacParameters::Variant:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesCmacParametersTest, CreateWithInvalidKeySizeFails) { EXPECT_THAT(AesCmacParameters::Create(/*key_size_in_bytes=*/15, /*cryptographic_tag_size_in_bytes=*/16, AesCmacParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesCmacParameters::Create(/*key_size_in_bytes=*/17, /*cryptographic_tag_size_in_bytes=*/16, AesCmacParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesCmacParameters::Create(/*key_size_in_bytes=*/31, /*cryptographic_tag_size_in_bytes=*/16, AesCmacParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesCmacParameters::Create(/*key_size_in_bytes=*/33, /*cryptographic_tag_size_in_bytes=*/16, AesCmacParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesCmacParametersTest, CreateWithInvalidTagSizeFails) { // Too small. EXPECT_THAT(AesCmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/7, AesCmacParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesCmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/8, AesCmacParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesCmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/9, AesCmacParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); // Too big; EXPECT_THAT(AesCmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/17, AesCmacParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesCmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/18, AesCmacParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(AesCmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/19, AesCmacParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesCmacParametersTest, CopyConstructor) { util::StatusOr parameters = AesCmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/12, AesCmacParameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); AesCmacParameters copy(*parameters); EXPECT_THAT(copy.GetVariant(), Eq(parameters->GetVariant())); EXPECT_THAT(copy.CryptographicTagSizeInBytes(), Eq(parameters->CryptographicTagSizeInBytes())); EXPECT_THAT(copy.TotalTagSizeInBytes(), Eq(parameters->TotalTagSizeInBytes())); EXPECT_THAT(copy.HasIdRequirement(), Eq(parameters->HasIdRequirement())); } TEST(AesCmacParametersTest, CopyAssignment) { util::StatusOr parameters = AesCmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/12, AesCmacParameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); AesCmacParameters copy = *parameters; EXPECT_THAT(copy.GetVariant(), Eq(parameters->GetVariant())); EXPECT_THAT(copy.CryptographicTagSizeInBytes(), Eq(parameters->CryptographicTagSizeInBytes())); EXPECT_THAT(copy.TotalTagSizeInBytes(), Eq(parameters->TotalTagSizeInBytes())); EXPECT_THAT(copy.HasIdRequirement(), Eq(parameters->HasIdRequirement())); } using AesCmacParametersVariantTest = TestWithParam>; INSTANTIATE_TEST_SUITE_P( AesCmacParametersVariantTestSuite, AesCmacParametersVariantTest, Combine(Values(16, 32), Range(10, 16), Values(AesCmacParameters::Variant::kTink, AesCmacParameters::Variant::kCrunchy, AesCmacParameters::Variant::kLegacy, AesCmacParameters::Variant::kNoPrefix))); TEST_P(AesCmacParametersVariantTest, ParametersEquals) { int key_size; int cryptographic_tag_size; AesCmacParameters::Variant variant; std::tie(key_size, cryptographic_tag_size, variant) = GetParam(); util::StatusOr parameters = AesCmacParameters::Create(key_size, cryptographic_tag_size, variant); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesCmacParameters::Create(key_size, cryptographic_tag_size, variant); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters == *other_parameters); EXPECT_TRUE(*other_parameters == *parameters); EXPECT_FALSE(*parameters != *other_parameters); EXPECT_FALSE(*other_parameters != *parameters); } TEST(AesCmacParametersTest, KeySizeNotEqual) { util::StatusOr parameters = AesCmacParameters::Create(/*key_size_in_bytes=*/16, /*cryptographic_tag_size_in_bytes=*/10, AesCmacParameters::Variant::kNoPrefix); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesCmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/10, AesCmacParameters::Variant::kNoPrefix); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(AesCmacParametersTest, TagSizeNotEqual) { util::StatusOr parameters = AesCmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/10, AesCmacParameters::Variant::kNoPrefix); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesCmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/11, AesCmacParameters::Variant::kNoPrefix); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(AesCmacParametersTest, VariantNotEqual) { util::StatusOr parameters = AesCmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/10, AesCmacParameters::Variant::kNoPrefix); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = AesCmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/10, AesCmacParameters::Variant::kTink); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/aes_cmac_proto_serialization.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/aes_cmac_proto_serialization.h" #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/internal/key_parser.h" #include "tink/internal/key_serializer.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/parameters_parser.h" #include "tink/internal/parameters_serializer.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/mac/aes_cmac_key.h" #include "tink/mac/aes_cmac_parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/secret_key_access_token.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/aes_cmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::google::crypto::tink::AesCmacKeyFormat; using ::google::crypto::tink::AesCmacParams; using ::google::crypto::tink::OutputPrefixType; using AesCmacProtoParametersParserImpl = internal::ParametersParserImpl; using AesCmacProtoParametersSerializerImpl = internal::ParametersSerializerImpl; using AesCmacProtoKeyParserImpl = internal::KeyParserImpl; using AesCmacProtoKeySerializerImpl = internal::KeySerializerImpl; const absl::string_view kTypeUrl = "type.googleapis.com/google.crypto.tink.AesCmacKey"; util::StatusOr ToVariant( OutputPrefixType output_prefix_type) { switch (output_prefix_type) { case OutputPrefixType::CRUNCHY: return AesCmacParameters::Variant::kCrunchy; case OutputPrefixType::LEGACY: return AesCmacParameters::Variant::kLegacy; case OutputPrefixType::RAW: return AesCmacParameters::Variant::kNoPrefix; case OutputPrefixType::TINK: return AesCmacParameters::Variant::kTink; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine AesCmacParameters::Variant"); } } util::StatusOr ToOutputPrefixType( AesCmacParameters::Variant variant) { switch (variant) { case AesCmacParameters::Variant::kCrunchy: return OutputPrefixType::CRUNCHY; case AesCmacParameters::Variant::kLegacy: return OutputPrefixType::LEGACY; case AesCmacParameters::Variant::kNoPrefix: return OutputPrefixType::RAW; case AesCmacParameters::Variant::kTink: return OutputPrefixType::TINK; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine output prefix type"); } } util::StatusOr ParseParameters( const internal::ProtoParametersSerialization& serialization) { if (serialization.GetKeyTemplate().type_url() != kTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing AesCmacParameters."); } AesCmacKeyFormat proto_key_format; if (!proto_key_format.ParseFromString( serialization.GetKeyTemplate().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse AesCmacKeyFormat proto"); } util::StatusOr variant = ToVariant(serialization.GetKeyTemplate().output_prefix_type()); if (!variant.ok()) return variant.status(); return AesCmacParameters::Create(proto_key_format.key_size(), proto_key_format.params().tag_size(), *variant); } util::StatusOr SerializeParameters( const AesCmacParameters& parameters) { util::StatusOr output_prefix_type = ToOutputPrefixType(parameters.GetVariant()); if (!output_prefix_type.ok()) return output_prefix_type.status(); AesCmacParams proto_params; proto_params.set_tag_size(parameters.CryptographicTagSizeInBytes()); AesCmacKeyFormat proto_key_format; proto_key_format.set_key_size(parameters.KeySizeInBytes()); *proto_key_format.mutable_params() = proto_params; return internal::ProtoParametersSerialization::Create( kTypeUrl, *output_prefix_type, proto_key_format.SerializeAsString()); } util::StatusOr ParseKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (serialization.TypeUrl() != kTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing AesCmacKey."); } if (!token.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "SecretKeyAccess is required"); } google::crypto::tink::AesCmacKey proto_key; const RestrictedData& restricted_data = serialization.SerializedKeyProto(); if (!proto_key.ParseFromString(restricted_data.GetSecret(*token))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse AesCmacKey proto"); } if (proto_key.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } util::StatusOr variant = ToVariant(serialization.GetOutputPrefixType()); if (!variant.ok()) return variant.status(); util::StatusOr parameters = AesCmacParameters::Create( proto_key.key_value().length(), proto_key.params().tag_size(), *variant); if (!parameters.ok()) return parameters.status(); util::StatusOr key = AesCmacKey::Create( *parameters, RestrictedData(proto_key.key_value(), *token), serialization.IdRequirement(), GetPartialKeyAccess()); if (!key.ok()) return key.status(); return *key; } util::StatusOr SerializeKey( const AesCmacKey& key, absl::optional token) { util::StatusOr restricted_input = key.GetKeyBytes(GetPartialKeyAccess()); if (!restricted_input.ok()) return restricted_input.status(); if (!token.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "SecretKeyAccess is required"); } AesCmacParams proto_params; proto_params.set_tag_size(key.GetParameters().CryptographicTagSizeInBytes()); google::crypto::tink::AesCmacKey proto_key; *proto_key.mutable_params() = proto_params; proto_key.set_version(0); proto_key.set_key_value(restricted_input->GetSecret(*token)); util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetParameters().GetVariant()); if (!output_prefix_type.ok()) return output_prefix_type.status(); RestrictedData restricted_output = RestrictedData(proto_key.SerializeAsString(), *token); return internal::ProtoKeySerialization::Create( kTypeUrl, restricted_output, google::crypto::tink::KeyData::SYMMETRIC, *output_prefix_type, key.GetIdRequirement()); } AesCmacProtoParametersParserImpl* AesCmacProtoParametersParser() { static auto* parser = new AesCmacProtoParametersParserImpl(kTypeUrl, ParseParameters); return parser; } AesCmacProtoParametersSerializerImpl* AesCmacProtoParametersSerializer() { static auto* serializer = new AesCmacProtoParametersSerializerImpl(kTypeUrl, SerializeParameters); return serializer; } AesCmacProtoKeyParserImpl* AesCmacProtoKeyParser() { static auto* parser = new AesCmacProtoKeyParserImpl(kTypeUrl, ParseKey); return parser; } AesCmacProtoKeySerializerImpl* AesCmacProtoKeySerializer() { static auto* serializer = new AesCmacProtoKeySerializerImpl(SerializeKey); return serializer; } } // namespace util::Status RegisterAesCmacProtoSerialization() { util::Status status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersParser(AesCmacProtoParametersParser()); if (!status.ok()) return status; status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersSerializer(AesCmacProtoParametersSerializer()); if (!status.ok()) return status; status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(AesCmacProtoKeyParser()); if (!status.ok()) return status; return internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(AesCmacProtoKeySerializer()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/aes_cmac_proto_serialization.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_AES_CMAC_PROTO_SERIALIZATION_H_ #define TINK_MAC_AES_CMAC_PROTO_SERIALIZATION_H_ #include "tink/util/status.h" namespace crypto { namespace tink { // Registers proto parsers and serializers for AES-CMAC parameters and keys. crypto::tink::util::Status RegisterAesCmacProtoSerialization(); } // namespace tink } // namespace crypto #endif // TINK_MAC_AES_CMAC_PROTO_SERIALIZATION_H_ ================================================ FILE: cc/mac/aes_cmac_proto_serialization_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/aes_cmac_proto_serialization.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/mac/aes_cmac_key.h" #include "tink/mac/aes_cmac_parameters.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/subtle/random.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/aes_cmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::subtle::Random; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::AesCmacKeyFormat; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::IsTrue; using ::testing::NotNull; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { AesCmacParameters::Variant variant; OutputPrefixType output_prefix_type; int key_size; int tag_size; int total_size; absl::optional id; std::string output_prefix; }; class AesCmacProtoSerializationTest : public TestWithParam { protected: void SetUp() override { internal::MutableSerializationRegistry::GlobalInstance().Reset(); } }; TEST_F(AesCmacProtoSerializationTest, RegisterTwiceSucceeds) { ASSERT_THAT(RegisterAesCmacProtoSerialization(), IsOk()); ASSERT_THAT(RegisterAesCmacProtoSerialization(), IsOk()); } INSTANTIATE_TEST_SUITE_P( AesCmacProtoSerializationTestSuite, AesCmacProtoSerializationTest, Values(TestCase{AesCmacParameters::Variant::kTink, OutputPrefixType::TINK, /*key_size=*/16, /*tag_size=*/10, /*total_size=*/15, /*id=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{AesCmacParameters::Variant::kCrunchy, OutputPrefixType::CRUNCHY, /*key_size=*/16, /*tag_size=*/12, /*total_size=*/17, /*id=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{AesCmacParameters::Variant::kLegacy, OutputPrefixType::LEGACY, /*key_size=*/32, /*cryptographic_tag_size=*/14, /*total_tag_size=*/19, /*id=*/0x01020304, /*output_prefix=*/std::string("\x00\x01\x02\x03\x04", 5)}, TestCase{AesCmacParameters::Variant::kNoPrefix, OutputPrefixType::RAW, /*key_size=*/32, /*cryptographic_tag_size=*/16, /*total_tag_size=*/16, /*id=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(AesCmacProtoSerializationTest, ParseParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesCmacProtoSerialization(), IsOk()); AesCmacKeyFormat key_format_proto; key_format_proto.set_key_size(test_case.key_size); key_format_proto.mutable_params()->set_tag_size(test_case.tag_size); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.AesCmacKey", test_case.output_prefix_type, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(params, IsOk()); EXPECT_THAT((*params)->HasIdRequirement(), test_case.id.has_value()); const AesCmacParameters* cmac_params = dynamic_cast(params->get()); ASSERT_THAT(cmac_params, NotNull()); EXPECT_THAT(cmac_params->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(cmac_params->KeySizeInBytes(), Eq(test_case.key_size)); EXPECT_THAT(cmac_params->CryptographicTagSizeInBytes(), Eq(test_case.tag_size)); EXPECT_THAT(cmac_params->TotalTagSizeInBytes(), Eq(test_case.total_size)); } TEST_F(AesCmacProtoSerializationTest, ParseParametersWithInvalidSerialization) { ASSERT_THAT(RegisterAesCmacProtoSerialization(), IsOk()); AesCmacKeyFormat key_format_proto; key_format_proto.set_key_size(16); key_format_proto.mutable_params()->set_tag_size(10); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.AesCmacKey", OutputPrefixType::RAW, "invalid_serialization"); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(AesCmacProtoSerializationTest, ParseParametersWithUnkownOutputPrefix) { ASSERT_THAT(RegisterAesCmacProtoSerialization(), IsOk()); AesCmacKeyFormat key_format_proto; key_format_proto.set_key_size(16); key_format_proto.mutable_params()->set_tag_size(10); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.AesCmacKey", OutputPrefixType::UNKNOWN_PREFIX, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(AesCmacProtoSerializationTest, SerializeParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesCmacProtoSerialization(), IsOk()); util::StatusOr parameters = AesCmacParameters::Create( test_case.key_size, test_case.tag_size, test_case.variant); ASSERT_THAT(parameters, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( *parameters); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq("type.googleapis.com/google.crypto.tink.AesCmacKey")); const internal::ProtoParametersSerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->GetKeyTemplate().type_url(), Eq("type.googleapis.com/google.crypto.tink.AesCmacKey")); EXPECT_THAT(proto_serialization->GetKeyTemplate().output_prefix_type(), Eq(test_case.output_prefix_type)); AesCmacKeyFormat key_format; ASSERT_THAT( key_format.ParseFromString(proto_serialization->GetKeyTemplate().value()), IsTrue()); ASSERT_THAT(key_format.key_size(), Eq(test_case.key_size)); ASSERT_THAT(key_format.params().tag_size(), Eq(test_case.tag_size)); } TEST_P(AesCmacProtoSerializationTest, ParseKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesCmacProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(test_case.key_size); google::crypto::tink::AesCmacKey key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); key_proto.mutable_params()->set_tag_size(test_case.tag_size); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesCmacKey", serialized_key, KeyData::SYMMETRIC, test_case.output_prefix_type, test_case.id); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); EXPECT_THAT((*key)->GetIdRequirement(), Eq(test_case.id)); EXPECT_THAT((*key)->GetParameters().HasIdRequirement(), test_case.id.has_value()); const AesCmacKey* cmac_key = dynamic_cast(key->get()); ASSERT_THAT(cmac_key, NotNull()); util::StatusOr parsed_key = cmac_key->GetKeyBytes(GetPartialKeyAccess()); ASSERT_THAT(parsed_key, IsOk()); EXPECT_THAT(parsed_key->GetSecret(InsecureSecretKeyAccess::Get()), Eq(raw_key_bytes)); EXPECT_THAT(cmac_key->GetOutputPrefix(), Eq(test_case.output_prefix)); EXPECT_THAT(cmac_key->GetParameters().GetVariant(), Eq(test_case.variant)); EXPECT_THAT(cmac_key->GetParameters().KeySizeInBytes(), Eq(test_case.key_size)); EXPECT_THAT(cmac_key->GetParameters().CryptographicTagSizeInBytes(), Eq(test_case.tag_size)); EXPECT_THAT(cmac_key->GetParameters().TotalTagSizeInBytes(), test_case.total_size); EXPECT_THAT(cmac_key->GetParameters().HasIdRequirement(), test_case.id.has_value()); } TEST_F(AesCmacProtoSerializationTest, ParseKeyWithInvalidSerialization) { ASSERT_THAT(RegisterAesCmacProtoSerialization(), IsOk()); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesCmacKey", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(AesCmacProtoSerializationTest, ParseKeyNoSecretKeyAccess) { ASSERT_THAT(RegisterAesCmacProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(16); google::crypto::tink::AesCmacKey key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); key_proto.mutable_params()->set_tag_size(10); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesCmacKey", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, absl::nullopt); ASSERT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(AesCmacProtoSerializationTest, ParseKeyWithInvalidVersion) { ASSERT_THAT(RegisterAesCmacProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(16); google::crypto::tink::AesCmacKey key_proto; key_proto.set_version(1); // Invalid version number. key_proto.set_key_value(raw_key_bytes); key_proto.mutable_params()->set_tag_size(10); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesCmacKey", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(AesCmacProtoSerializationTest, SerializeKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterAesCmacProtoSerialization(), IsOk()); util::StatusOr parameters = AesCmacParameters::Create( test_case.key_size, test_case.tag_size, test_case.variant); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(test_case.key_size); util::StatusOr key = AesCmacKey::Create( *parameters, RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq("type.googleapis.com/google.crypto.tink.AesCmacKey")); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq("type.googleapis.com/google.crypto.tink.AesCmacKey")); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::SYMMETRIC)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id)); google::crypto::tink::AesCmacKey proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.key_value().size(), Eq(test_case.key_size)); EXPECT_THAT(proto_key.params().tag_size(), Eq(test_case.tag_size)); } TEST_F(AesCmacProtoSerializationTest, SerializeKeyNoSecretKeyAccess) { ASSERT_THAT(RegisterAesCmacProtoSerialization(), IsOk()); util::StatusOr parameters = AesCmacParameters::Create( /*key_size_in_bytes=*/16, /*cryptographic_tag_size_in_bytes=*/10, AesCmacParameters::Variant::kNoPrefix); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(16); util::StatusOr key = AesCmacKey::Create( *parameters, RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey(*key, absl::nullopt); ASSERT_THAT(serialization.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/config_v0.h" #include "absl/log/check.h" #include "tink/configuration.h" #include "tink/mac/internal/config_v0.h" namespace crypto { namespace tink { const Configuration& ConfigMacV0() { static const Configuration* instance = [] { static Configuration* config = new Configuration(); CHECK_OK(internal::AddMacV0(*config)); return config; }(); return *instance; } } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_CONFIG_V0_H_ #define TINK_MAC_CONFIG_V0_H_ #include "tink/configuration.h" namespace crypto { namespace tink { // Configuration used to generate MAC primitives with recommended key managers. const Configuration& ConfigMacV0(); } // namespace tink } // namespace crypto #endif // TINK_MAC_CONFIG_V0_H_ ================================================ FILE: cc/mac/config_v0_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/config_v0.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/chunked_mac.h" #include "tink/key_gen_configuration.h" #include "tink/keyset_handle.h" #include "tink/mac.h" #include "tink/mac/key_gen_config_v0.h" #include "tink/mac/mac_key_templates.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::google::crypto::tink::KeyTemplate; using ::testing::TestWithParam; using ::testing::Values; using ConfigV0Test = TestWithParam; INSTANTIATE_TEST_SUITE_P(ConfigV0TestSuite, ConfigV0Test, Values(MacKeyTemplates::AesCmac(), MacKeyTemplates::HmacSha256())); TEST_P(ConfigV0Test, GetPrimitive) { util::StatusOr> handle = KeysetHandle::GenerateNew(GetParam(), KeyGenConfigMacV0()); ASSERT_THAT(handle, IsOk()); util::StatusOr> mac = (*handle)->GetPrimitive(ConfigMacV0()); ASSERT_THAT(mac, IsOk()); std::string data = "data"; util::StatusOr tag = (*mac)->ComputeMac(data); ASSERT_THAT(tag, IsOk()); EXPECT_THAT((*mac)->VerifyMac(*tag, data), IsOk()); } TEST_P(ConfigV0Test, GetPrimitiveChunkedMac) { util::StatusOr> handle = KeysetHandle::GenerateNew(GetParam(), KeyGenConfigMacV0()); ASSERT_THAT(handle, IsOk()); util::StatusOr> chunked_mac = (*handle)->GetPrimitive(ConfigMacV0()); ASSERT_THAT(chunked_mac, IsOk()); std::string data1 = "da"; std::string data2 = "ta"; util::StatusOr> compute = (*chunked_mac)->CreateComputation(); ASSERT_THAT(compute, IsOk()); ASSERT_THAT((*compute)->Update(data1), IsOk()); ASSERT_THAT((*compute)->Update(data2), IsOk()); util::StatusOr tag = (*compute)->ComputeMac(); ASSERT_THAT(tag, IsOk()); util::StatusOr> verify = (*chunked_mac)->CreateVerification(*tag); ASSERT_THAT(verify, IsOk()); ASSERT_THAT((*verify)->Update(data1), IsOk()); ASSERT_THAT((*verify)->Update(data2), IsOk()); EXPECT_THAT((*verify)->VerifyMac(), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/failing_mac.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/mac/failing_mac.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/mac.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { // A MAC that always returns a kInternal status on API calls. class AlwaysFailMac : public Mac { public: explicit AlwaysFailMac(std::string message) : message_(std::move(message)) {} util::StatusOr ComputeMac( absl::string_view /*data*/) const override { return util::Status( absl::StatusCode::kInternal, absl::StrCat("AlwaysFailMac will always fail on ComputeMac (msg=", message_, ")")); } util::Status VerifyMac(absl::string_view /*mac_value*/, absl::string_view /*data*/) const override { return util::Status( absl::StatusCode::kInternal, absl::StrCat("AlwaysFailMac will always fail on VerifyMac (msg=", message_, ")")); } private: const std::string message_; }; } // namespace std::unique_ptr CreateAlwaysFailingMac(std::string message) { return absl::make_unique(std::move(message)); } } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/failing_mac.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_FAILING_MAC_H_ #define TINK_MAC_FAILING_MAC_H_ #include #include #include "absl/strings/string_view.h" #include "tink/mac.h" namespace crypto { namespace tink { // Returns a MAC that always returns an error when calling ComputeMac or // VerifyMac. The error message will contain `message`. std::unique_ptr CreateAlwaysFailingMac(std::string message = ""); } // namespace tink } // namespace crypto #endif // TINK_MAC_FAILING_MAC_H_ ================================================ FILE: cc/mac/failing_mac_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/mac/failing_mac.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/mac.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::StatusIs; using ::testing::HasSubstr; TEST(AlwaysFailMac, ComputeMacFails) { std::unique_ptr failing_Mac = CreateAlwaysFailingMac(); EXPECT_THAT(failing_Mac->ComputeMac("message").status(), StatusIs(absl::StatusCode::kInternal)); } TEST(AlwaysFailMac, ComputeMacFailsContainsMessage) { const std::string expected_message = "expected_message"; std::unique_ptr failing_Mac = CreateAlwaysFailingMac(expected_message); EXPECT_THAT( failing_Mac->ComputeMac("message").status(), StatusIs(absl::StatusCode::kInternal, HasSubstr(expected_message))); } TEST(AlwaysFailMac, VerifyMacFails) { std::unique_ptr failing_Mac = CreateAlwaysFailingMac(); EXPECT_THAT(failing_Mac->VerifyMac("tag", "message"), StatusIs(absl::StatusCode::kInternal)); } TEST(AlwaysFailMac, VerifyMacFailsContainsMessage) { const std::string expected_message = "expected_message"; std::unique_ptr failing_Mac = CreateAlwaysFailingMac(expected_message); EXPECT_THAT( failing_Mac->VerifyMac("tag", "message"), StatusIs(absl::StatusCode::kInternal, HasSubstr(expected_message))); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/hmac_key.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/hmac_key.h" #include #include #include #include "absl/base/attributes.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/types/optional.h" #include "tink/key.h" #include "tink/mac/hmac_parameters.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { util::StatusOr HmacKey::Create(const HmacParameters& parameters, const RestrictedData& key_bytes, absl::optional id_requirement, PartialKeyAccessToken token) { if (parameters.KeySizeInBytes() != key_bytes.size()) { return util::Status(absl::StatusCode::kInvalidArgument, "Key size does not match HMAC parameters"); } if (parameters.HasIdRequirement() && !id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key without ID requirement with parameters with ID " "requirement"); } if (!parameters.HasIdRequirement() && id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key with ID requirement with parameters without ID " "requirement"); } util::StatusOr output_prefix = ComputeOutputPrefix(parameters, id_requirement); if (!output_prefix.ok()) { return output_prefix.status(); } return HmacKey(parameters, key_bytes, id_requirement, *std::move(output_prefix)); } util::StatusOr HmacKey::ComputeOutputPrefix( const HmacParameters& parameters, absl::optional id_requirement) { switch (parameters.GetVariant()) { case HmacParameters::Variant::kNoPrefix: return std::string(""); // Empty prefix. case HmacParameters::Variant::kLegacy: ABSL_FALLTHROUGH_INTENDED; case HmacParameters::Variant::kCrunchy: if (!id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "id requirement must have value with kCrunchy or kLegacy"); } return absl::StrCat(absl::HexStringToBytes("00"), subtle::BigEndian32(*id_requirement)); case HmacParameters::Variant::kTink: if (!id_requirement.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "id requirement must have value with kTink"); } return absl::StrCat(absl::HexStringToBytes("01"), subtle::BigEndian32(*id_requirement)); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid variant: ", parameters.GetVariant())); } } bool HmacKey::operator==(const Key& other) const { const HmacKey* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (GetParameters() != that->GetParameters()) { return false; } if (id_requirement_ != that->id_requirement_) { return false; } return key_bytes_ == that->key_bytes_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/hmac_key.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_HMAC_KEY_H_ #define TINK_MAC_HMAC_KEY_H_ #include #include #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/key.h" #include "tink/mac/hmac_parameters.h" #include "tink/mac/mac_key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { class HmacKey : public MacKey { public: // Copyable and movable. HmacKey(const HmacKey& other) = default; HmacKey& operator=(const HmacKey& other) = default; HmacKey(HmacKey&& other) = default; HmacKey& operator=(HmacKey&& other) = default; // Creates a new HMAC key. If the parameters specify a variant that uses // a prefix, then the id is used to compute this prefix. static util::StatusOr Create(const HmacParameters& parameters, const RestrictedData& key_bytes, absl::optional id_requirement, PartialKeyAccessToken token); // Returns the underlying HMAC key bytes. const RestrictedData& GetKeyBytes(PartialKeyAccessToken token) const { return key_bytes_; } absl::string_view GetOutputPrefix() const override { return output_prefix_; } const HmacParameters& GetParameters() const override { return parameters_; } absl::optional GetIdRequirement() const override { return id_requirement_; } bool operator==(const Key& other) const override; private: HmacKey(const HmacParameters& parameters, const RestrictedData& key_bytes, absl::optional id_requirement, std::string output_prefix) : parameters_(parameters), key_bytes_(key_bytes), id_requirement_(id_requirement), output_prefix_(std::move(output_prefix)) {} static util::StatusOr ComputeOutputPrefix( const HmacParameters& parameters, absl::optional id_requirement); HmacParameters parameters_; RestrictedData key_bytes_; absl::optional id_requirement_; std::string output_prefix_; }; } // namespace tink } // namespace crypto #endif // TINK_MAC_HMAC_KEY_H_ ================================================ FILE: cc/mac/hmac_key_manager.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/mac/hmac_key_manager.h" #include #include #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/input_stream.h" #include "tink/mac.h" #include "tink/subtle/hmac_boringssl.h" #include "tink/subtle/random.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/input_stream_util.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/common.pb.h" #include "proto/hmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using crypto::tink::util::Enums; using crypto::tink::util::Status; using crypto::tink::util::StatusOr; using google::crypto::tink::HashType; using google::crypto::tink::HmacKey; using google::crypto::tink::HmacKeyFormat; using google::crypto::tink::HmacParams; namespace { constexpr int kMinKeySizeInBytes = 16; constexpr int kMinTagSizeInBytes = 10; } // namespace StatusOr HmacKeyManager::CreateKey( const HmacKeyFormat& hmac_key_format) const { HmacKey hmac_key; hmac_key.set_version(get_version()); *(hmac_key.mutable_params()) = hmac_key_format.params(); hmac_key.set_key_value( subtle::Random::GetRandomBytes(hmac_key_format.key_size())); return hmac_key; } StatusOr HmacKeyManager::DeriveKey( const HmacKeyFormat& hmac_key_format, InputStream* input_stream) const { crypto::tink::util::Status status = ValidateVersion(hmac_key_format.version(), get_version()); if (!status.ok()) return status; crypto::tink::util::StatusOr randomness = ReadBytesFromStream(hmac_key_format.key_size(), input_stream); if (!randomness.ok()) { if (randomness.status().code() == absl::StatusCode::kOutOfRange) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, "Could not get enough pseudorandomness from input stream"); } return randomness.status(); } HmacKey hmac_key; hmac_key.set_version(get_version()); *(hmac_key.mutable_params()) = hmac_key_format.params(); hmac_key.set_key_value(randomness.value()); return hmac_key; } Status HmacKeyManager::ValidateParams(const HmacParams& params) const { if (params.tag_size() < kMinTagSizeInBytes) { return ToStatusF(absl::StatusCode::kInvalidArgument, "Invalid HmacParams: tag_size %d is too small.", params.tag_size()); } std::map max_tag_size = {{HashType::SHA1, 20}, {HashType::SHA224, 28}, {HashType::SHA256, 32}, {HashType::SHA384, 48}, {HashType::SHA512, 64}}; if (max_tag_size.find(params.hash()) == max_tag_size.end()) { return ToStatusF(absl::StatusCode::kInvalidArgument, "Invalid HmacParams: HashType '%s' not supported.", Enums::HashName(params.hash())); } else { if (params.tag_size() > max_tag_size[params.hash()]) { return ToStatusF( absl::StatusCode::kInvalidArgument, "Invalid HmacParams: tag_size %d is too big for HashType '%s'.", params.tag_size(), Enums::HashName(params.hash())); } } return util::OkStatus(); } Status HmacKeyManager::ValidateKey(const HmacKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; if (key.key_value().size() < kMinKeySizeInBytes) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid HmacKey: key_value is too short."); } return ValidateParams(key.params()); } // static Status HmacKeyManager::ValidateKeyFormat( const HmacKeyFormat& key_format) const { if (key_format.key_size() < kMinKeySizeInBytes) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid HmacKeyFormat: key_size is too small."); } return ValidateParams(key_format.params()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/hmac_key_manager.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_HMAC_KEY_MANAGER_H_ #define TINK_MAC_HMAC_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/chunked_mac.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/input_stream.h" #include "tink/internal/fips_utils.h" #include "tink/mac.h" #include "tink/mac/internal/chunked_mac_impl.h" #include "tink/subtle/hmac_boringssl.h" #include "tink/util/constants.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/hmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class HmacKeyManager : public KeyTypeManager> { public: class MacFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::HmacKey& hmac_key) const override { return subtle::HmacBoringSsl::New( util::Enums::ProtoToSubtle(hmac_key.params().hash()), hmac_key.params().tag_size(), util::SecretDataFromStringView(hmac_key.key_value())); } }; class ChunkedMacFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::HmacKey& hmac_key) const override { return internal::NewChunkedHmac(hmac_key); } }; HmacKeyManager() : KeyTypeManager(absl::make_unique(), absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::SYMMETRIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::HmacKey& key) const override; crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::HmacKeyFormat& key_format) const override; crypto::tink::util::StatusOr CreateKey( const google::crypto::tink::HmacKeyFormat& key_format) const override; crypto::tink::util::StatusOr DeriveKey( const google::crypto::tink::HmacKeyFormat& key_format, InputStream* input_stream) const override; internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: crypto::tink::util::Status ValidateParams( const google::crypto::tink::HmacParams& params) const; const std::string key_type_ = absl::StrCat( kTypeGoogleapisCom, google::crypto::tink::HmacKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_MAC_HMAC_KEY_MANAGER_H_ ================================================ FILE: cc/mac/hmac_key_manager_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/hmac_key_manager.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/chunked_mac.h" #include "tink/core/key_manager_impl.h" #include "tink/mac.h" #include "tink/subtle/hmac_boringssl.h" #include "tink/util/enums.h" #include "tink/util/istream_input_stream.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/hmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::IstreamInputStream; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::HashType; using ::google::crypto::tink::HmacKey; using ::google::crypto::tink::HmacKeyFormat; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::Not; using ::testing::SizeIs; namespace { TEST(HmacKeyManagerTest, Basics) { EXPECT_EQ(HmacKeyManager().get_version(), 0); EXPECT_EQ(HmacKeyManager().get_key_type(), "type.googleapis.com/google.crypto.tink.HmacKey"); EXPECT_EQ(HmacKeyManager().key_material_type(), google::crypto::tink::KeyData::SYMMETRIC); } TEST(HmacKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(HmacKeyManager().ValidateKey(HmacKey()), Not(IsOk())); } TEST(HmacKeyManagerTest, ValidateEmptyKeyFormat) { EXPECT_THAT(HmacKeyManager().ValidateKeyFormat(HmacKeyFormat()), Not(IsOk())); } TEST(HmacKeyManagerTest, ValidKeyFormat) { HmacKeyFormat key_format; key_format.mutable_params()->set_tag_size(16); key_format.mutable_params()->set_hash(HashType::SHA256); key_format.set_key_size(16); EXPECT_THAT(HmacKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(HmacKeyManagerTest, ValidateKeyFormatSmallTagSizes) { for (int i = 0; i < 10; ++i) { HmacKeyFormat key_format; key_format.mutable_params()->set_tag_size(i); key_format.mutable_params()->set_hash(HashType::SHA256); key_format.set_key_size(16); EXPECT_THAT(HmacKeyManager().ValidateKeyFormat(key_format), Not(IsOk())) << " for length " << i; } } TEST(HmacKeyManagerTest, ValidateKeyFormatTagSizesSha1) { HmacKeyFormat key_format; key_format.mutable_params()->set_hash(HashType::SHA1); key_format.set_key_size(16); key_format.mutable_params()->set_tag_size(20); EXPECT_THAT(HmacKeyManager().ValidateKeyFormat(key_format), IsOk()); key_format.mutable_params()->set_tag_size(21); EXPECT_THAT(HmacKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(HmacKeyManagerTest, ValidateKeyFormatTagSizesSha224) { HmacKeyFormat key_format; key_format.mutable_params()->set_hash(HashType::SHA224); key_format.set_key_size(16); key_format.mutable_params()->set_tag_size(28); EXPECT_THAT(HmacKeyManager().ValidateKeyFormat(key_format), IsOk()); key_format.mutable_params()->set_tag_size(29); EXPECT_THAT(HmacKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(HmacKeyManagerTest, ValidateKeyFormatTagSizesSha256) { HmacKeyFormat key_format; key_format.mutable_params()->set_hash(HashType::SHA256); key_format.set_key_size(16); key_format.mutable_params()->set_tag_size(32); EXPECT_THAT(HmacKeyManager().ValidateKeyFormat(key_format), IsOk()); key_format.mutable_params()->set_tag_size(33); EXPECT_THAT(HmacKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(HmacKeyManagerTest, ValidateKeyFormatTagSizesSha384) { HmacKeyFormat key_format; key_format.mutable_params()->set_hash(HashType::SHA384); key_format.set_key_size(16); key_format.mutable_params()->set_tag_size(48); EXPECT_THAT(HmacKeyManager().ValidateKeyFormat(key_format), IsOk()); key_format.mutable_params()->set_tag_size(49); EXPECT_THAT(HmacKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(HmacKeyManagerTest, ValidateKeyFormatTagSizesSha512) { HmacKeyFormat key_format; key_format.mutable_params()->set_hash(HashType::SHA512); key_format.set_key_size(16); key_format.mutable_params()->set_tag_size(64); EXPECT_THAT(HmacKeyManager().ValidateKeyFormat(key_format), IsOk()); key_format.mutable_params()->set_tag_size(65); EXPECT_THAT(HmacKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(HmacKeyManagerTest, ValidateKeyFormatKeySizes) { HmacKeyFormat key_format; key_format.mutable_params()->set_hash(HashType::SHA512); key_format.mutable_params()->set_tag_size(64); key_format.set_key_size(15); EXPECT_THAT(HmacKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); key_format.set_key_size(16); EXPECT_THAT(HmacKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(HmacKeyManagerTest, CreateKey) { HmacKeyFormat key_format; key_format.set_key_size(16); key_format.mutable_params()->set_tag_size(10); key_format.mutable_params()->set_hash(HashType::SHA512); auto hmac_key_or = HmacKeyManager().CreateKey(key_format); ASSERT_THAT(hmac_key_or, IsOk()); EXPECT_EQ(hmac_key_or.value().version(), 0); EXPECT_EQ(hmac_key_or.value().params().hash(), key_format.params().hash()); EXPECT_EQ(hmac_key_or.value().params().tag_size(), key_format.params().tag_size()); EXPECT_THAT(hmac_key_or.value().key_value(), SizeIs(key_format.key_size())); EXPECT_THAT(HmacKeyManager().ValidateKey(hmac_key_or.value()), IsOk()); } TEST(HmacKeyManagerTest, ValidKey) { HmacKey key; key.set_version(0); key.mutable_params()->set_hash(HashType::SHA256); key.mutable_params()->set_tag_size(10); key.set_key_value("0123456789abcdef"); EXPECT_THAT(HmacKeyManager().ValidateKey(key), IsOk()); } TEST(HmacKeyManagerTest, ValidateKeyTagSizesSha1) { HmacKey key; key.set_version(0); key.mutable_params()->set_hash(HashType::SHA1); key.set_key_value("0123456789abcdef"); key.mutable_params()->set_tag_size(20); EXPECT_THAT(HmacKeyManager().ValidateKey(key), IsOk()); key.mutable_params()->set_tag_size(21); EXPECT_THAT(HmacKeyManager().ValidateKey(key), Not(IsOk())); } TEST(HmacKeyManagerTest, ValidateKeyTagSizesSha224) { HmacKey key; key.set_version(0); key.mutable_params()->set_hash(HashType::SHA224); key.set_key_value("0123456789abcdef"); key.mutable_params()->set_tag_size(28); EXPECT_THAT(HmacKeyManager().ValidateKey(key), IsOk()); key.mutable_params()->set_tag_size(29); EXPECT_THAT(HmacKeyManager().ValidateKey(key), Not(IsOk())); } TEST(HmacKeyManagerTest, ValidateKeyTagSizesSha256) { HmacKey key; key.set_version(0); key.mutable_params()->set_hash(HashType::SHA256); key.set_key_value("0123456789abcdef"); key.mutable_params()->set_tag_size(32); EXPECT_THAT(HmacKeyManager().ValidateKey(key), IsOk()); key.mutable_params()->set_tag_size(33); EXPECT_THAT(HmacKeyManager().ValidateKey(key), Not(IsOk())); } TEST(HmacKeyManagerTest, ValidateKeyTagSizesSha384) { HmacKey key; key.set_version(0); key.mutable_params()->set_hash(HashType::SHA384); key.set_key_value("0123456789abcdef"); key.mutable_params()->set_tag_size(48); EXPECT_THAT(HmacKeyManager().ValidateKey(key), IsOk()); key.mutable_params()->set_tag_size(49); EXPECT_THAT(HmacKeyManager().ValidateKey(key), Not(IsOk())); } TEST(HmacKeyManagerTest, ValidateKeyTagSizesSha512) { HmacKey key; key.set_version(0); key.mutable_params()->set_hash(HashType::SHA512); key.set_key_value("0123456789abcdef"); key.mutable_params()->set_tag_size(64); EXPECT_THAT(HmacKeyManager().ValidateKey(key), IsOk()); key.mutable_params()->set_tag_size(65); EXPECT_THAT(HmacKeyManager().ValidateKey(key), Not(IsOk())); } TEST(HmacKeyManagerTest, ValidateKeyShortKey) { HmacKey key; key.set_version(0); key.mutable_params()->set_hash(HashType::SHA256); key.mutable_params()->set_tag_size(10); key.set_key_value("0123456789abcde"); EXPECT_THAT(HmacKeyManager().ValidateKey(key), Not(IsOk())); } TEST(HmacKeyManagerTest, DeriveKey) { HmacKeyFormat format; format.set_key_size(23); format.set_version(0); format.mutable_params()->set_hash(HashType::SHA256); format.mutable_params()->set_tag_size(10); IstreamInputStream input_stream{ absl::make_unique("0123456789abcdefghijklmnop")}; StatusOr key_or = HmacKeyManager().DeriveKey(format, &input_stream); ASSERT_THAT(key_or, IsOk()); EXPECT_EQ(key_or.value().key_value(), "0123456789abcdefghijklm"); EXPECT_EQ(key_or.value().params().hash(), format.params().hash()); EXPECT_EQ(key_or.value().params().tag_size(), format.params().tag_size()); } TEST(HmacKeyManagerTest, DeriveKeyNotEnoughRandomness) { HmacKeyFormat format; format.set_key_size(17); format.set_version(0); format.mutable_params()->set_hash(HashType::SHA256); format.mutable_params()->set_tag_size(10); IstreamInputStream input_stream{ absl::make_unique("0123456789abcdef")}; ASSERT_THAT(HmacKeyManager().DeriveKey(format, &input_stream).status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HmacKeyManagerTest, DeriveKeyWrongVersion) { HmacKeyFormat format; format.set_key_size(16); format.set_version(1); format.mutable_params()->set_hash(HashType::SHA256); format.mutable_params()->set_tag_size(10); IstreamInputStream input_stream{ absl::make_unique("0123456789abcdef")}; ASSERT_THAT( HmacKeyManager().DeriveKey(format, &input_stream).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("version"))); } TEST(HmacKeyManagerTest, GetMacPrimitive) { HmacKeyFormat key_format; key_format.mutable_params()->set_tag_size(16); key_format.mutable_params()->set_hash(HashType::SHA256); key_format.set_key_size(16); HmacKey key = HmacKeyManager().CreateKey(key_format).value(); auto manager_mac_or = HmacKeyManager().GetPrimitive(key); ASSERT_THAT(manager_mac_or, IsOk()); auto mac_value_or = manager_mac_or.value()->ComputeMac("some plaintext"); ASSERT_THAT(mac_value_or, IsOk()); auto direct_mac_or = subtle::HmacBoringSsl::New( util::Enums::ProtoToSubtle(key.params().hash()), key.params().tag_size(), util::SecretDataFromStringView(key.key_value())); ASSERT_THAT(direct_mac_or, IsOk()); EXPECT_THAT( direct_mac_or.value()->VerifyMac(mac_value_or.value(), "some plaintext"), IsOk()); } TEST(HmacKeyManagerTest, GetChunkedMacPrimitive) { HmacKeyFormat key_format; key_format.mutable_params()->set_tag_size(16); key_format.mutable_params()->set_hash(HashType::SHA256); key_format.set_key_size(16); HmacKey key = HmacKeyManager().CreateKey(key_format).value(); util::StatusOr> chunked_mac = HmacKeyManager().GetPrimitive(key); ASSERT_THAT(chunked_mac, IsOk()); util::StatusOr> computation = (*chunked_mac)->CreateComputation(); ASSERT_THAT(computation, IsOk()); ASSERT_THAT((*computation)->Update("abc"), IsOk()); ASSERT_THAT((*computation)->Update("xyz"), IsOk()); util::StatusOr tag = (*computation)->ComputeMac(); ASSERT_THAT(tag, IsOk()); util::StatusOr> verification = (*chunked_mac)->CreateVerification(*tag); ASSERT_THAT(verification, IsOk()); ASSERT_THAT((*verification)->Update("abc"), IsOk()); ASSERT_THAT((*verification)->Update("xyz"), IsOk()); EXPECT_THAT((*verification)->VerifyMac(), IsOk()); } TEST(HmacKeyManagerTest, MixPrimitives) { HmacKeyFormat key_format; key_format.mutable_params()->set_tag_size(16); key_format.mutable_params()->set_hash(HashType::SHA256); key_format.set_key_size(16); HmacKey key = HmacKeyManager().CreateKey(key_format).value(); util::StatusOr> mac = HmacKeyManager().GetPrimitive(key); ASSERT_THAT(mac, IsOk()); util::StatusOr> chunked_mac = HmacKeyManager().GetPrimitive(key); ASSERT_THAT(chunked_mac, IsOk()); // Compute tag with Mac. util::StatusOr tag = (*mac)->ComputeMac("abcxyz"); ASSERT_THAT(tag, IsOk()); // Compute chunked tag with ChunkedMac. util::StatusOr> computation = (*chunked_mac)->CreateComputation(); ASSERT_THAT(computation, IsOk()); ASSERT_THAT((*computation)->Update("abc"), IsOk()); ASSERT_THAT((*computation)->Update("xyz"), IsOk()); util::StatusOr chunked_tag = (*computation)->ComputeMac(); ASSERT_THAT(chunked_tag, IsOk()); ASSERT_THAT(*chunked_tag, Eq(*tag)); // Both primitives generated same tag. // Verify chunked tag with Mac. ASSERT_THAT((*mac)->VerifyMac(*chunked_tag, "abcxyz"), IsOk()); // Verify tag with ChunkedMac. util::StatusOr> verification = (*chunked_mac)->CreateVerification(*tag); ASSERT_THAT(verification, IsOk()); ASSERT_THAT((*verification)->Update("abc"), IsOk()); ASSERT_THAT((*verification)->Update("xyz"), IsOk()); EXPECT_THAT((*verification)->VerifyMac(), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/hmac_key_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/hmac_key.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/mac/hmac_parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Combine; using ::testing::Eq; using ::testing::Range; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { HmacParameters::Variant variant; absl::optional id_requirement; std::string output_prefix; }; using HmacKeyTest = TestWithParam>; INSTANTIATE_TEST_SUITE_P( HmacKeyTestSuite, HmacKeyTest, Combine(Values(16, 32), Range(10, 20), Values(HmacParameters::HashType::kSha1, HmacParameters::HashType::kSha224, HmacParameters::HashType::kSha256, HmacParameters::HashType::kSha384, HmacParameters::HashType::kSha512), Values(TestCase{HmacParameters::Variant::kTink, 0x02030400, std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{HmacParameters::Variant::kCrunchy, 0x01030005, std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{HmacParameters::Variant::kLegacy, 0x01020304, std::string("\x00\x01\x02\x03\x04", 5)}, TestCase{HmacParameters::Variant::kNoPrefix, absl::nullopt, ""}))); TEST_P(HmacKeyTest, CreateSucceeds) { int key_size; int cryptographic_tag_size; HmacParameters::HashType hash_type; TestCase test_case; std::tie(key_size, cryptographic_tag_size, hash_type, test_case) = GetParam(); util::StatusOr params = HmacParameters::Create( key_size, cryptographic_tag_size, hash_type, test_case.variant); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(key_size); util::StatusOr key = HmacKey::Create( *params, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(key.status(), IsOk()); EXPECT_THAT(key->GetParameters(), Eq(*params)); EXPECT_THAT(key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(key->GetOutputPrefix(), Eq(test_case.output_prefix)); } TEST(HmacKeyTest, CreateKeyWithMismatchedKeySizeFails) { // Key size parameter is 32 bytes. util::StatusOr params = HmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16, HmacParameters::HashType::kSha256, HmacParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); // Key material is 16 bytes (another valid key length). RestrictedData mismatched_secret = RestrictedData(/*num_random_bytes=*/16); EXPECT_THAT(HmacKey::Create(*params, mismatched_secret, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HmacKeyTest, CreateKeyWithWrongIdRequirementFails) { util::StatusOr no_prefix_params = HmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16, HmacParameters::HashType::kSha512, HmacParameters::Variant::kNoPrefix); ASSERT_THAT(no_prefix_params, IsOk()); util::StatusOr tink_params = HmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16, HmacParameters::HashType::kSha512, HmacParameters::Variant::kTink); ASSERT_THAT(tink_params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); EXPECT_THAT(HmacKey::Create(*no_prefix_params, secret, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT( HmacKey::Create(*tink_params, secret, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(HmacKeyTest, GetKeyBytes) { int key_size; int cryptographic_tag_size; HmacParameters::HashType hash_type; TestCase test_case; std::tie(key_size, cryptographic_tag_size, hash_type, test_case) = GetParam(); util::StatusOr params = HmacParameters::Create( key_size, cryptographic_tag_size, hash_type, test_case.variant); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(key_size); util::StatusOr key = HmacKey::Create( *params, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(key.status(), IsOk()); EXPECT_THAT(key->GetKeyBytes(GetPartialKeyAccess()), Eq(secret)); } TEST_P(HmacKeyTest, KeyEquals) { int key_size; int cryptographic_tag_size; HmacParameters::HashType hash_type; TestCase test_case; std::tie(key_size, cryptographic_tag_size, hash_type, test_case) = GetParam(); util::StatusOr params = HmacParameters::Create( key_size, cryptographic_tag_size, hash_type, test_case.variant); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(key_size); util::StatusOr key = HmacKey::Create( *params, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr other_key = HmacKey::Create( *params, secret, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(other_key, IsOk()); EXPECT_TRUE(*key == *other_key); EXPECT_TRUE(*other_key == *key); EXPECT_FALSE(*key != *other_key); EXPECT_FALSE(*other_key != *key); } TEST(HmacKeyTest, DifferentFormatNotEqual) { util::StatusOr legacy_params = HmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16, HmacParameters::HashType::kSha256, HmacParameters::Variant::kLegacy); ASSERT_THAT(legacy_params, IsOk()); util::StatusOr tink_params = HmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16, HmacParameters::HashType::kSha256, HmacParameters::Variant::kTink); ASSERT_THAT(tink_params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = HmacKey::Create(*legacy_params, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key.status(), IsOk()); util::StatusOr other_key = HmacKey::Create(*tink_params, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_key.status(), IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST(HmacKeyTest, DifferentSecretDataNotEqual) { util::StatusOr params = HmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16, HmacParameters::HashType::kSha384, HmacParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); RestrictedData secret1 = RestrictedData(/*num_random_bytes=*/32); RestrictedData secret2 = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = HmacKey::Create( *params, secret1, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key.status(), IsOk()); util::StatusOr other_key = HmacKey::Create( *params, secret2, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_key.status(), IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } TEST(HmacKeyTest, DifferentIdRequirementNotEqual) { util::StatusOr params = HmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16, HmacParameters::HashType::kSha224, HmacParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); RestrictedData secret = RestrictedData(/*num_random_bytes=*/32); util::StatusOr key = HmacKey::Create( *params, secret, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(key.status(), IsOk()); util::StatusOr other_key = HmacKey::Create( *params, secret, /*id_requirement=*/0x02030405, GetPartialKeyAccess()); ASSERT_THAT(other_key.status(), IsOk()); EXPECT_TRUE(*key != *other_key); EXPECT_TRUE(*other_key != *key); EXPECT_FALSE(*key == *other_key); EXPECT_FALSE(*other_key == *key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/hmac_parameters.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/hmac_parameters.h" #include #include #include #include #include #include #include #include "absl/log/log.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/crypto_format.h" #include "tink/internal/util.h" #include "tink/parameters.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { util::Status ValidateTagSizeBytes(int cryptographic_tag_size_in_bytes, HmacParameters::HashType hash_type) { if (cryptographic_tag_size_in_bytes < 10) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Tag size should be at least 10 bytes, got ", cryptographic_tag_size_in_bytes, " bytes.")); } std::map max_tag_size = { {HmacParameters::HashType::kSha1, 20}, {HmacParameters::HashType::kSha224, 28}, {HmacParameters::HashType::kSha256, 32}, {HmacParameters::HashType::kSha384, 48}, {HmacParameters::HashType::kSha512, 64}}; if (max_tag_size.find(hash_type) == max_tag_size.end()) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Cannot create HMAC parameters with given hash type. ", hash_type, " not supported.")); } if (cryptographic_tag_size_in_bytes > max_tag_size[hash_type]) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Tag size is too big for given ", hash_type, " , got ", cryptographic_tag_size_in_bytes, " bytes.")); } return util::OkStatus(); } } // namespace util::StatusOr HmacParameters::Create( int key_size_in_bytes, int cryptographic_tag_size_in_bytes, HashType hash_type, Variant variant) { if (key_size_in_bytes < 16) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Key size must be at least 16 bytes, got ", key_size_in_bytes, " bytes.")); } util::Status status = ValidateTagSizeBytes(cryptographic_tag_size_in_bytes, hash_type); if (!status.ok()) return status; static const std::set* supported_variants = new std::set({Variant::kTink, Variant::kCrunchy, Variant::kLegacy, Variant::kNoPrefix}); if (supported_variants->find(variant) == supported_variants->end()) { return util::Status(absl::StatusCode::kInvalidArgument, "Cannot create HMAC parameters with unknown variant."); } return HmacParameters(key_size_in_bytes, cryptographic_tag_size_in_bytes, hash_type, variant); } int HmacParameters::TotalTagSizeInBytes() const { switch (variant_) { case Variant::kTink: case Variant::kCrunchy: case Variant::kLegacy: return CryptographicTagSizeInBytes() + CryptoFormat::kNonRawPrefixSize; case Variant::kNoPrefix: return CryptographicTagSizeInBytes(); default: // Parameters objects with unknown variants should never be created. internal::LogFatal("HMAC parameters has an unknown variant."); } } bool HmacParameters::operator==(const Parameters& other) const { const HmacParameters* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (key_size_in_bytes_ != that->key_size_in_bytes_) { return false; } if (cryptographic_tag_size_in_bytes_ != that->cryptographic_tag_size_in_bytes_) { return false; } if (hash_type_ != that->hash_type_) { return false; } if (variant_ != that->variant_) { return false; } return true; } } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/hmac_parameters.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_HMAC_PARAMETERS_H_ #define TINK_MAC_HMAC_PARAMETERS_H_ #include #include "tink/mac/mac_parameters.h" #include "tink/parameters.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Describes the parameters of an `HmacKey`. class HmacParameters : public MacParameters { public: // Describes the details of a MAC computation. // // The usual HMAC key is used for variant `NO_PREFIX`. Other variants // slightly change how the MAC is computed, or add a prefix to every // computation depending on the key id. enum class Variant : int { // Prepends '0x01' to tag. kTink = 1, // Prepends '0x00' to tag. kCrunchy = 2, // Appends a 0-byte to input message BEFORE computing the tag, then // prepends '0x00' to tag. kLegacy = 3, // Does not prepend any prefix (i.e., keys must have no ID requirement). kNoPrefix = 4, // Added to guard from failures that may be caused by future expansions. kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Describes the hash algorithm used. enum class HashType : int { kSha1 = 1, kSha224 = 2, kSha256 = 3, kSha384 = 4, kSha512 = 5, kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Copyable and movable. HmacParameters(const HmacParameters& other) = default; HmacParameters& operator=(const HmacParameters& other) = default; HmacParameters(HmacParameters&& other) = default; HmacParameters& operator=(HmacParameters&& other) = default; // Creates a new HMAC parameters object unless an error occurs. An error // occurs under one of the following conditions: // 1. `key_size_in_bytes` is a value smaller than 16 bytes // 2. `cryptographic_tag_size_in_bytes` is either less than 10 bytes or // greater than the maximum value accepted by the corresponding hash algorithm static util::StatusOr Create( int key_size_in_bytes, int cryptographic_tag_size_in_bytes, HashType hash_type, Variant variant); Variant GetVariant() const { return variant_; } HashType GetHashType() const { return hash_type_; } int KeySizeInBytes() const { return key_size_in_bytes_; } // Returns the size of the tag, which is computed cryptographically from the // message. Note that this may differ from the total size of the tag, as for // some keys, Tink prefixes the tag with a key dependent output prefix. int CryptographicTagSizeInBytes() const { return cryptographic_tag_size_in_bytes_; } // Returns the size of the cryptographic tag plus the size of the prefix with // which this key prefixes every cryptographic tag. int TotalTagSizeInBytes() const; bool HasIdRequirement() const override { return variant_ != Variant::kNoPrefix; } bool operator==(const Parameters& other) const override; private: HmacParameters(int key_size_in_bytes, int cryptographic_tag_size_in_bytes, HashType hash_type, Variant variant) : key_size_in_bytes_(key_size_in_bytes), cryptographic_tag_size_in_bytes_(cryptographic_tag_size_in_bytes), hash_type_(hash_type), variant_(variant) {} int key_size_in_bytes_; int cryptographic_tag_size_in_bytes_; HashType hash_type_; Variant variant_; }; } // namespace tink } // namespace crypto #endif // TINK_MAC_HMAC_PARAMETERS_H_ ================================================ FILE: cc/mac/hmac_parameters_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/hmac_parameters.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Combine; using ::testing::Eq; using ::testing::Range; using ::testing::TestWithParam; using ::testing::Values; struct CreateTestCase { HmacParameters::Variant variant; int key_size; int cryptographic_tag_size; int total_tag_size; HmacParameters::HashType hash_type; bool has_id_requirement; }; using HmacParametersCreateTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( HmacParametersCreateTestSuite, HmacParametersCreateTest, Values(CreateTestCase{HmacParameters::Variant::kNoPrefix, /*key_size=*/16, /*cryptographic_tag_size=*/20, /*total_tag_size=*/20, HmacParameters::HashType::kSha1, /*has_id_requirement=*/false}, CreateTestCase{HmacParameters::Variant::kTink, /*key_size=*/16, /*cryptographic_tag_size=*/28, /*total_tag_size=*/33, HmacParameters::HashType::kSha224, /*has_id_requirement=*/true}, CreateTestCase{HmacParameters::Variant::kCrunchy, /*key_size=*/16, /*cryptographic_tag_size=*/32, /*total_tag_size=*/37, HmacParameters::HashType::kSha256, /*has_id_requirement=*/true}, CreateTestCase{HmacParameters::Variant::kLegacy, /*key_size=*/32, /*cryptographic_tag_size=*/48, /*total_tag_size=*/53, HmacParameters::HashType::kSha384, /*has_id_requirement=*/true}, CreateTestCase{HmacParameters::Variant::kNoPrefix, /*key_size=*/32, /*cryptographic_tag_size=*/64, /*total_tag_size=*/64, HmacParameters::HashType::kSha512, /*has_id_requirement=*/false})); TEST_P(HmacParametersCreateTest, Create) { CreateTestCase test_case = GetParam(); util::StatusOr parameters = HmacParameters::Create( test_case.key_size, test_case.cryptographic_tag_size, test_case.hash_type, test_case.variant); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(parameters->KeySizeInBytes(), Eq(test_case.key_size)); EXPECT_THAT(parameters->CryptographicTagSizeInBytes(), Eq(test_case.cryptographic_tag_size)); EXPECT_THAT(parameters->TotalTagSizeInBytes(), Eq(test_case.total_tag_size)); EXPECT_THAT(parameters->GetHashType(), Eq(test_case.hash_type)); EXPECT_THAT(parameters->HasIdRequirement(), Eq(test_case.has_id_requirement)); } TEST(HmacParametersTest, CreateWithInvalidVariantFails) { EXPECT_THAT(HmacParameters::Create( /*key_size_in_bytes=*/16, /*cryptographic_tag_size_in_bytes=*/12, HmacParameters::HashType::kSha256, HmacParameters::Variant:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HmacParametersTest, CreateWithInvalidHashTypeFails) { EXPECT_THAT(HmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/12, HmacParameters::HashType:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements, HmacParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HmacParametersTest, CreateWithInvalidKeySizeFails) { EXPECT_THAT(HmacParameters::Create(/*key_size_in_bytes=*/15, /*cryptographic_tag_size_in_bytes=*/16, HmacParameters::HashType::kSha256, HmacParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HmacParametersTest, CreateWithInvalidTagSizeFails) { // Too small. EXPECT_THAT(HmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/7, HmacParameters::HashType::kSha224, HmacParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); // Too big for kSha1. EXPECT_THAT(HmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/21, HmacParameters::HashType::kSha1, HmacParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); // Too big for kSha224. EXPECT_THAT(HmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/29, HmacParameters::HashType::kSha224, HmacParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); // Too big for kSha256; EXPECT_THAT(HmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/33, HmacParameters::HashType::kSha256, HmacParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); // Too big for kSha384; EXPECT_THAT(HmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/49, HmacParameters::HashType::kSha384, HmacParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); // Too big for kSha512; EXPECT_THAT(HmacParameters::Create(/*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/65, HmacParameters::HashType::kSha512, HmacParameters::Variant::kNoPrefix) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HmacParametersTest, CopyConstructor) { util::StatusOr parameters = HmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/12, HmacParameters::HashType::kSha256, HmacParameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); HmacParameters copy(*parameters); EXPECT_THAT(copy.GetVariant(), Eq(parameters->GetVariant())); EXPECT_THAT(copy.CryptographicTagSizeInBytes(), Eq(parameters->CryptographicTagSizeInBytes())); EXPECT_THAT(copy.TotalTagSizeInBytes(), Eq(parameters->TotalTagSizeInBytes())); EXPECT_THAT(copy.GetHashType(), Eq(parameters->GetHashType())); EXPECT_THAT(copy.HasIdRequirement(), Eq(parameters->HasIdRequirement())); } TEST(HmacParametersTest, CopyAssignment) { util::StatusOr parameters = HmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/12, HmacParameters::HashType::kSha512, HmacParameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); HmacParameters copy = *parameters; EXPECT_THAT(copy.GetVariant(), Eq(parameters->GetVariant())); EXPECT_THAT(copy.CryptographicTagSizeInBytes(), Eq(parameters->CryptographicTagSizeInBytes())); EXPECT_THAT(copy.TotalTagSizeInBytes(), Eq(parameters->TotalTagSizeInBytes())); EXPECT_THAT(copy.GetHashType(), Eq(parameters->GetHashType())); EXPECT_THAT(copy.HasIdRequirement(), Eq(parameters->HasIdRequirement())); } using HmacParametersVariantTest = TestWithParam< std::tuple>; INSTANTIATE_TEST_SUITE_P(HmacParametersVariantTestSuite, HmacParametersVariantTest, Combine(Range(16, 32), Range(10, 20), Values(HmacParameters::HashType::kSha1, HmacParameters::HashType::kSha224, HmacParameters::HashType::kSha256, HmacParameters::HashType::kSha384, HmacParameters::HashType::kSha512), Values(HmacParameters::Variant::kTink, HmacParameters::Variant::kCrunchy, HmacParameters::Variant::kLegacy, HmacParameters::Variant::kNoPrefix))); TEST_P(HmacParametersVariantTest, ParametersEquals) { int key_size; int cryptographic_tag_size; HmacParameters::HashType hash_type; HmacParameters::Variant variant; std::tie(key_size, cryptographic_tag_size, hash_type, variant) = GetParam(); util::StatusOr parameters = HmacParameters::Create( key_size, cryptographic_tag_size, hash_type, variant); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = HmacParameters::Create( key_size, cryptographic_tag_size, hash_type, variant); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters == *other_parameters); EXPECT_TRUE(*other_parameters == *parameters); EXPECT_FALSE(*parameters != *other_parameters); EXPECT_FALSE(*other_parameters != *parameters); } TEST(HmacParametersTest, KeySizeNotEqual) { util::StatusOr parameters = HmacParameters::Create( /*key_size_in_bytes=*/16, /*cryptographic_tag_size_in_bytes=*/10, HmacParameters::HashType::kSha224, HmacParameters::Variant::kNoPrefix); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = HmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/10, HmacParameters::HashType::kSha224, HmacParameters::Variant::kNoPrefix); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(HmacParametersTest, HashTypeNotEqual) { util::StatusOr parameters = HmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/10, HmacParameters::HashType::kSha256, HmacParameters::Variant::kNoPrefix); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = HmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/10, HmacParameters::HashType::kSha512, HmacParameters::Variant::kNoPrefix); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(HmacParametersTest, TagSizeNotEqual) { util::StatusOr parameters = HmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/10, HmacParameters::HashType::kSha256, HmacParameters::Variant::kNoPrefix); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = HmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/11, HmacParameters::HashType::kSha256, HmacParameters::Variant::kNoPrefix); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(HmacParametersTest, VariantNotEqual) { util::StatusOr parameters = HmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/10, HmacParameters::HashType::kSha256, HmacParameters::Variant::kNoPrefix); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = HmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/10, HmacParameters::HashType::kSha256, HmacParameters::Variant::kTink); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/hmac_proto_serialization.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/hmac_proto_serialization.h" #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/internal/key_parser.h" #include "tink/internal/key_serializer.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/parameters_parser.h" #include "tink/internal/parameters_serializer.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/mac/hmac_key.h" #include "tink/mac/hmac_parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/secret_key_access_token.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/common.pb.h" #include "proto/hmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::google::crypto::tink::HashType; using ::google::crypto::tink::HmacKeyFormat; using ::google::crypto::tink::HmacParams; using ::google::crypto::tink::OutputPrefixType; using HmacProtoParametersParserImpl = internal::ParametersParserImpl; using HmacProtoParametersSerializerImpl = internal::ParametersSerializerImpl; using HmacProtoKeyParserImpl = internal::KeyParserImpl; using HmacProtoKeySerializerImpl = internal::KeySerializerImpl; const absl::string_view kTypeUrl = "type.googleapis.com/google.crypto.tink.HmacKey"; util::StatusOr ToVariant( OutputPrefixType output_prefix_type) { switch (output_prefix_type) { case OutputPrefixType::CRUNCHY: return HmacParameters::Variant::kCrunchy; case OutputPrefixType::LEGACY: return HmacParameters::Variant::kLegacy; case OutputPrefixType::RAW: return HmacParameters::Variant::kNoPrefix; case OutputPrefixType::TINK: return HmacParameters::Variant::kTink; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine HmacParameters::Variant"); } } util::StatusOr ToOutputPrefixType( HmacParameters::Variant variant) { switch (variant) { case HmacParameters::Variant::kCrunchy: return OutputPrefixType::CRUNCHY; case HmacParameters::Variant::kLegacy: return OutputPrefixType::LEGACY; case HmacParameters::Variant::kNoPrefix: return OutputPrefixType::RAW; case HmacParameters::Variant::kTink: return OutputPrefixType::TINK; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine output prefix type"); } } util::StatusOr ToHashType(HashType hash_type) { switch (hash_type) { case HashType::SHA1: return HmacParameters::HashType::kSha1; case HashType::SHA224: return HmacParameters::HashType::kSha224; case HashType::SHA256: return HmacParameters::HashType::kSha256; case HashType::SHA384: return HmacParameters::HashType::kSha384; case HashType::SHA512: return HmacParameters::HashType::kSha512; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine HashType"); } } util::StatusOr ToProtoHashType(HmacParameters::HashType hash_type) { switch (hash_type) { case HmacParameters::HashType::kSha1: return HashType::SHA1; case HmacParameters::HashType::kSha224: return HashType::SHA224; case HmacParameters::HashType::kSha256: return HashType::SHA256; case HmacParameters::HashType::kSha384: return HashType::SHA384; case HmacParameters::HashType::kSha512: return HashType::SHA512; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine HmacParameters::HashType"); } } util::StatusOr ParseParameters( const internal::ProtoParametersSerialization& serialization) { if (serialization.GetKeyTemplate().type_url() != kTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing HmacParameters."); } HmacKeyFormat proto_key_format; if (!proto_key_format.ParseFromString( serialization.GetKeyTemplate().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse HmacKeyFormat proto"); } if (proto_key_format.version() != 0) { return util::Status( absl::StatusCode::kInvalidArgument, "Parsing HmacParameters failed: only version 0 is accepted"); } util::StatusOr variant = ToVariant(serialization.GetKeyTemplate().output_prefix_type()); if (!variant.ok()) return variant.status(); util::StatusOr hash_type = ToHashType(proto_key_format.params().hash()); if (!hash_type.ok()) return hash_type.status(); return HmacParameters::Create(proto_key_format.key_size(), proto_key_format.params().tag_size(), *hash_type, *variant); } util::StatusOr SerializeParameters( const HmacParameters& parameters) { util::StatusOr output_prefix_type = ToOutputPrefixType(parameters.GetVariant()); if (!output_prefix_type.ok()) return output_prefix_type.status(); util::StatusOr proto_hash_type = ToProtoHashType(parameters.GetHashType()); if (!proto_hash_type.ok()) return proto_hash_type.status(); HmacParams proto_params; proto_params.set_tag_size(parameters.CryptographicTagSizeInBytes()); proto_params.set_hash(*proto_hash_type); HmacKeyFormat proto_key_format; proto_key_format.set_key_size(parameters.KeySizeInBytes()); proto_key_format.set_version(0); *proto_key_format.mutable_params() = proto_params; return internal::ProtoParametersSerialization::Create( kTypeUrl, *output_prefix_type, proto_key_format.SerializeAsString()); } util::StatusOr ParseKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (serialization.TypeUrl() != kTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing HmacKey."); } if (!token.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "SecretKeyAccess is required"); } google::crypto::tink::HmacKey proto_key; const RestrictedData& restricted_data = serialization.SerializedKeyProto(); if (!proto_key.ParseFromString(restricted_data.GetSecret(*token))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse HmacKey proto"); } if (proto_key.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } util::StatusOr variant = ToVariant(serialization.GetOutputPrefixType()); if (!variant.ok()) return variant.status(); util::StatusOr hash_type = ToHashType(proto_key.params().hash()); if (!hash_type.ok()) return hash_type.status(); util::StatusOr parameters = HmacParameters::Create( proto_key.key_value().length(), proto_key.params().tag_size(), *hash_type, *variant); if (!parameters.ok()) return parameters.status(); return HmacKey::Create(*parameters, RestrictedData(proto_key.key_value(), *token), serialization.IdRequirement(), GetPartialKeyAccess()); } util::StatusOr SerializeKey( const HmacKey& key, absl::optional token) { util::StatusOr restricted_input = key.GetKeyBytes(GetPartialKeyAccess()); if (!token.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "SecretKeyAccess is required"); } if (!restricted_input.ok()) return restricted_input.status(); util::StatusOr proto_hash_type = ToProtoHashType(key.GetParameters().GetHashType()); if (!proto_hash_type.ok()) return proto_hash_type.status(); HmacParams proto_params; proto_params.set_tag_size(key.GetParameters().CryptographicTagSizeInBytes()); proto_params.set_hash(*proto_hash_type); google::crypto::tink::HmacKey proto_key; *proto_key.mutable_params() = proto_params; proto_key.set_version(0); proto_key.set_key_value(restricted_input->GetSecret(*token)); util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetParameters().GetVariant()); if (!output_prefix_type.ok()) return output_prefix_type.status(); RestrictedData restricted_output = RestrictedData(proto_key.SerializeAsString(), *token); return internal::ProtoKeySerialization::Create( kTypeUrl, restricted_output, google::crypto::tink::KeyData::SYMMETRIC, *output_prefix_type, key.GetIdRequirement()); } HmacProtoParametersParserImpl* HmacProtoParametersParser() { static auto* parser = new HmacProtoParametersParserImpl(kTypeUrl, ParseParameters); return parser; } HmacProtoParametersSerializerImpl* HmacProtoParametersSerializer() { static auto* serializer = new HmacProtoParametersSerializerImpl(kTypeUrl, SerializeParameters); return serializer; } HmacProtoKeyParserImpl* HmacProtoKeyParser() { static auto* parser = new HmacProtoKeyParserImpl(kTypeUrl, ParseKey); return parser; } HmacProtoKeySerializerImpl* HmacProtoKeySerializer() { static auto* serializer = new HmacProtoKeySerializerImpl(SerializeKey); return serializer; } } // namespace util::Status RegisterHmacProtoSerialization() { util::Status status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersParser(HmacProtoParametersParser()); if (!status.ok()) return status; status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersSerializer(HmacProtoParametersSerializer()); if (!status.ok()) return status; status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(HmacProtoKeyParser()); if (!status.ok()) return status; return internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(HmacProtoKeySerializer()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/hmac_proto_serialization.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_HMAC_PROTO_SERIALIZATION_H_ #define TINK_MAC_HMAC_PROTO_SERIALIZATION_H_ #include "tink/util/status.h" namespace crypto { namespace tink { // Registers proto parsers and serializers for HMAC parameters and keys. crypto::tink::util::Status RegisterHmacProtoSerialization(); } // namespace tink } // namespace crypto #endif // TINK_MAC_HMAC_PROTO_SERIALIZATION_H_ ================================================ FILE: cc/mac/hmac_proto_serialization_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/hmac_proto_serialization.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/mac/hmac_key.h" #include "tink/mac/hmac_parameters.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/subtle/random.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/common.pb.h" #include "proto/hmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::subtle::Random; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::HashType; using ::google::crypto::tink::HmacKeyFormat; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::IsTrue; using ::testing::NotNull; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { HmacParameters::Variant variant; OutputPrefixType output_prefix_type; HmacParameters::HashType hash_type; HashType proto_hash_type; int key_size; int tag_size; int total_size; absl::optional id; std::string output_prefix; }; class HmacProtoSerializationTest : public TestWithParam { protected: void SetUp() override { internal::MutableSerializationRegistry::GlobalInstance().Reset(); } }; TEST_F(HmacProtoSerializationTest, RegisterTwiceSucceeds) { ASSERT_THAT(RegisterHmacProtoSerialization(), IsOk()); ASSERT_THAT(RegisterHmacProtoSerialization(), IsOk()); } INSTANTIATE_TEST_SUITE_P( HmacProtoSerializationTestSuite, HmacProtoSerializationTest, Values(TestCase{HmacParameters::Variant::kTink, OutputPrefixType::TINK, HmacParameters::HashType::kSha1, HashType::SHA1, /*key_size=*/16, /*cryptographic_tag_size=*/10, /*total_size=*/15, /*id=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{HmacParameters::Variant::kCrunchy, OutputPrefixType::CRUNCHY, HmacParameters::HashType::kSha224, HashType::SHA224, /*key_size=*/16, /*tag_size=*/12, /*total_size=*/17, /*id=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{HmacParameters::Variant::kLegacy, OutputPrefixType::LEGACY, HmacParameters::HashType::kSha256, HashType::SHA256, /*key_size=*/32, /*cryptographic_tag_size=*/14, /*total_tag_size=*/19, /*id=*/0x01020304, /*output_prefix=*/std::string("\x00\x01\x02\x03\x04", 5)}, TestCase{HmacParameters::Variant::kNoPrefix, OutputPrefixType::RAW, HmacParameters::HashType::kSha384, HashType::SHA384, /*key_size=*/32, /*cryptographic_tag_size=*/16, /*total_tag_size=*/16, /*id=*/absl::nullopt, /*output_prefix=*/""}, TestCase{HmacParameters::Variant::kNoPrefix, OutputPrefixType::RAW, HmacParameters::HashType::kSha512, HashType::SHA512, /*key_size=*/32, /*cryptographic_tag_size=*/20, /*total_tag_size=*/20, /*id=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(HmacProtoSerializationTest, ParseParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterHmacProtoSerialization(), IsOk()); HmacKeyFormat key_format_proto; key_format_proto.set_key_size(test_case.key_size); key_format_proto.mutable_params()->set_tag_size(test_case.tag_size); key_format_proto.mutable_params()->set_hash(test_case.proto_hash_type); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.HmacKey", test_case.output_prefix_type, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parsed_parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(parsed_parameters, IsOk()); EXPECT_THAT((*parsed_parameters)->HasIdRequirement(), test_case.id.has_value()); util::StatusOr expected_parameters = HmacParameters::Create(test_case.key_size, test_case.tag_size, test_case.hash_type, test_case.variant); ASSERT_THAT(expected_parameters, IsOk()); ASSERT_THAT(**parsed_parameters, Eq(*expected_parameters)); } TEST_F(HmacProtoSerializationTest, ParseParametersWithInvalidSerialization) { ASSERT_THAT(RegisterHmacProtoSerialization(), IsOk()); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.HmacKey", OutputPrefixType::RAW, "invalid_serialization"); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(HmacProtoSerializationTest, ParseParametersWithInvalidVersion) { ASSERT_THAT(RegisterHmacProtoSerialization(), IsOk()); HmacKeyFormat key_format_proto; key_format_proto.set_key_size(16); key_format_proto.set_version(1); // Invalid version. key_format_proto.mutable_params()->set_tag_size(10); key_format_proto.mutable_params()->set_hash(HashType::SHA256); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.HmacKey", OutputPrefixType::RAW, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(HmacProtoSerializationTest, ParseParametersWithUnknownHashType) { ASSERT_THAT(RegisterHmacProtoSerialization(), IsOk()); HmacKeyFormat key_format_proto; key_format_proto.set_key_size(16); key_format_proto.set_version(0); key_format_proto.mutable_params()->set_tag_size(10); key_format_proto.mutable_params()->set_hash(HashType::UNKNOWN_HASH); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.HmacKey", OutputPrefixType::RAW, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(HmacProtoSerializationTest, ParseParametersWithUnkownOutputPrefix) { ASSERT_THAT(RegisterHmacProtoSerialization(), IsOk()); HmacKeyFormat key_format_proto; key_format_proto.set_key_size(16); key_format_proto.mutable_params()->set_tag_size(10); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.HmacKey", OutputPrefixType::UNKNOWN_PREFIX, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(HmacProtoSerializationTest, SerializeParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterHmacProtoSerialization(), IsOk()); util::StatusOr parameters = HmacParameters::Create(test_case.key_size, test_case.tag_size, test_case.hash_type, test_case.variant); ASSERT_THAT(parameters, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( *parameters); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq("type.googleapis.com/google.crypto.tink.HmacKey")); const internal::ProtoParametersSerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->GetKeyTemplate().type_url(), Eq("type.googleapis.com/google.crypto.tink.HmacKey")); EXPECT_THAT(proto_serialization->GetKeyTemplate().output_prefix_type(), Eq(test_case.output_prefix_type)); HmacKeyFormat key_format; ASSERT_THAT( key_format.ParseFromString(proto_serialization->GetKeyTemplate().value()), IsTrue()); ASSERT_THAT(key_format.key_size(), Eq(test_case.key_size)); ASSERT_THAT(key_format.params().tag_size(), Eq(test_case.tag_size)); ASSERT_THAT(key_format.params().hash(), Eq(test_case.proto_hash_type)); } TEST_P(HmacProtoSerializationTest, ParseKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterHmacProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(test_case.key_size); google::crypto::tink::HmacKey key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); key_proto.mutable_params()->set_tag_size(test_case.tag_size); key_proto.mutable_params()->set_hash(test_case.proto_hash_type); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.HmacKey", serialized_key, KeyData::SYMMETRIC, test_case.output_prefix_type, test_case.id); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parsed_key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key, IsOk()); EXPECT_THAT((*parsed_key)->GetParameters().HasIdRequirement(), test_case.id.has_value()); EXPECT_THAT((*parsed_key)->GetIdRequirement(), Eq(test_case.id)); util::StatusOr expected_parameters = HmacParameters::Create(test_case.key_size, test_case.tag_size, test_case.hash_type, test_case.variant); ASSERT_THAT(expected_parameters, IsOk()); util::StatusOr expected_key = HmacKey::Create( *expected_parameters, RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(expected_key, IsOk()); ASSERT_THAT(**parsed_key, Eq(*expected_key)); } TEST_F(HmacProtoSerializationTest, ParseKeyWithInvalidSerialization) { ASSERT_THAT(RegisterHmacProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(16); google::crypto::tink::HmacKey key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); key_proto.mutable_params()->set_tag_size(10); key_proto.mutable_params()->set_hash(HashType::SHA256); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.HmacKey", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(HmacProtoSerializationTest, ParseKeyWithInvalidVersion) { ASSERT_THAT(RegisterHmacProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(16); google::crypto::tink::HmacKey key_proto; key_proto.set_version(1); // Invalid version number. key_proto.set_key_value(raw_key_bytes); key_proto.mutable_params()->set_tag_size(10); key_proto.mutable_params()->set_hash(HashType::SHA256); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.HmacKey", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(HmacProtoSerializationTest, ParseKeyWithUnknownOutputPrefixType) { ASSERT_THAT(RegisterHmacProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(16); google::crypto::tink::HmacKey key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); key_proto.mutable_params()->set_tag_size(10); key_proto.mutable_params()->set_hash(HashType::SHA256); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.HmacKey", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::UNKNOWN_PREFIX, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(HmacProtoSerializationTest, ParseKeyWithUnknownHashType) { ASSERT_THAT(RegisterHmacProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(16); google::crypto::tink::HmacKey key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); key_proto.mutable_params()->set_tag_size(10); key_proto.mutable_params()->set_hash(HashType::UNKNOWN_HASH); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.HmacKey", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(HmacProtoSerializationTest, ParseKeyWithoutSecretKeyAccess) { ASSERT_THAT(RegisterHmacProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(16); google::crypto::tink::HmacKey key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); key_proto.mutable_params()->set_tag_size(10); key_proto.mutable_params()->set_hash(HashType::SHA256); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.HmacKey", serialized_key, KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, absl::nullopt); ASSERT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(HmacProtoSerializationTest, SerializeKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterHmacProtoSerialization(), IsOk()); util::StatusOr parameters = HmacParameters::Create(test_case.key_size, test_case.tag_size, test_case.hash_type, test_case.variant); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(test_case.key_size); util::StatusOr key = HmacKey::Create( *parameters, RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq("type.googleapis.com/google.crypto.tink.HmacKey")); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq("type.googleapis.com/google.crypto.tink.HmacKey")); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::SYMMETRIC)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id)); google::crypto::tink::HmacKey proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.key_value().size(), Eq(test_case.key_size)); EXPECT_THAT(proto_key.params().tag_size(), Eq(test_case.tag_size)); EXPECT_THAT(proto_key.params().hash(), Eq(test_case.proto_hash_type)); } TEST_F(HmacProtoSerializationTest, SerializeKeyWithoutSecretKeyAccess) { ASSERT_THAT(RegisterHmacProtoSerialization(), IsOk()); util::StatusOr parameters = HmacParameters::Create( /*key_size_in_bytes=*/16, /*cryptographic_tag_size_in_bytes=*/10, HmacParameters::HashType::kSha256, HmacParameters::Variant::kNoPrefix); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(16); util::StatusOr key = HmacKey::Create( *parameters, RestrictedData(raw_key_bytes, InsecureSecretKeyAccess::Get()), /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey(*key, absl::nullopt); ASSERT_THAT(serialization.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/internal/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "chunked_mac_impl", srcs = ["chunked_mac_impl.cc"], hdrs = ["chunked_mac_impl.h"], include_prefix = "tink/mac/internal", deps = [ "//:chunked_mac", "//proto:aes_cmac_cc_proto", "//proto:hmac_cc_proto", "//subtle:common_enums", "//subtle:stateful_cmac_boringssl", "//subtle:stateful_hmac_boringssl", "//subtle/mac:stateful_mac", "//util:enums", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "chunked_mac_wrapper", srcs = ["chunked_mac_wrapper.cc"], hdrs = ["chunked_mac_wrapper.h"], include_prefix = "tink/mac/internal", deps = [ "//:chunked_mac", "//:crypto_format", "//:primitive_set", "//:primitive_wrapper", "//internal:util", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "config_v0", srcs = ["config_v0.cc"], hdrs = ["config_v0.h"], include_prefix = "tink/mac/internal", deps = [ ":chunked_mac_wrapper", "//:configuration", "//internal:configuration_impl", "//mac:aes_cmac_key_manager", "//mac:hmac_key_manager", "//mac:mac_wrapper", "//util:status", "@com_google_absl//absl/memory", ], ) cc_library( name = "key_gen_config_v0", srcs = ["key_gen_config_v0.cc"], hdrs = ["key_gen_config_v0.h"], include_prefix = "tink/mac/internal", deps = [ "//:key_gen_configuration", "//internal:key_gen_configuration_impl", "//mac:aes_cmac_key_manager", "//mac:hmac_key_manager", "//util:status", "@com_google_absl//absl/memory", ], ) # tests cc_test( name = "chunked_mac_impl_test", size = "small", srcs = ["chunked_mac_impl_test.cc"], deps = [ ":chunked_mac_impl", "//:chunked_mac", "//proto:aes_cmac_cc_proto", "//proto:common_cc_proto", "//proto:hmac_cc_proto", "//subtle/mac:stateful_mac", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "chunked_mac_wrapper_test", size = "small", srcs = ["chunked_mac_wrapper_test.cc"], deps = [ ":chunked_mac_impl", ":chunked_mac_wrapper", "//:chunked_mac", "//:primitive_set", "//proto:tink_cc_proto", "//subtle/mac:stateful_mac", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "chunked_mac_test", size = "small", srcs = ["chunked_mac_test.cc"], deps = [ "//:chunked_mac", "//:keyset_handle", "//:mac", "//config:global_registry", "//mac:mac_config", "//mac:mac_key_templates", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "config_v0_test", srcs = ["config_v0_test.cc"], deps = [ ":config_v0", ":key_gen_config_v0", "//:chunked_mac", "//:configuration", "//:key_gen_configuration", "//:keyset_handle", "//:mac", "//internal:configuration_impl", "//internal:key_gen_configuration_impl", "//internal:key_type_info_store", "//internal:keyset_wrapper_store", "//mac:aes_cmac_key_manager", "//mac:hmac_key_manager", "//mac:mac_key_templates", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/mac/internal/CMakeLists.txt ================================================ tink_module(mac::internal) tink_cc_library( NAME chunked_mac_impl SRCS chunked_mac_impl.cc chunked_mac_impl.h DEPS absl::memory absl::status absl::strings crypto tink::core::chunked_mac tink::subtle::common_enums tink::subtle::stateful_cmac_boringssl tink::subtle::stateful_hmac_boringssl tink::subtle::mac::stateful_mac tink::util::enums tink::util::secret_data tink::util::status tink::util::statusor tink::proto::aes_cmac_cc_proto tink::proto::hmac_cc_proto ) tink_cc_library( NAME chunked_mac_wrapper SRCS chunked_mac_wrapper.cc chunked_mac_wrapper.h DEPS absl::memory absl::status absl::strings tink::core::chunked_mac tink::core::crypto_format tink::core::primitive_set tink::core::primitive_wrapper tink::internal::util tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME config_v0 SRCS config_v0.cc config_v0.h DEPS tink::mac::internal::chunked_mac_wrapper absl::memory tink::core::configuration tink::internal::configuration_impl tink::mac::aes_cmac_key_manager tink::mac::hmac_key_manager tink::mac::mac_wrapper tink::util::status ) tink_cc_library( NAME key_gen_config_v0 SRCS key_gen_config_v0.cc key_gen_config_v0.h DEPS absl::memory tink::core::key_gen_configuration tink::internal::key_gen_configuration_impl tink::mac::aes_cmac_key_manager tink::mac::hmac_key_manager tink::util::status ) # tests tink_cc_test( NAME chunked_mac_impl_test SRCS chunked_mac_impl_test.cc DEPS tink::mac::internal::chunked_mac_impl gmock absl::memory absl::status absl::string_view tink::core::chunked_mac tink::subtle::mac::stateful_mac tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::aes_cmac_cc_proto tink::proto::common_cc_proto tink::proto::hmac_cc_proto ) tink_cc_test( NAME chunked_mac_wrapper_test SRCS chunked_mac_wrapper_test.cc DEPS tink::mac::internal::chunked_mac_impl tink::mac::internal::chunked_mac_wrapper gmock absl::memory absl::status absl::strings tink::core::chunked_mac tink::core::primitive_set tink::subtle::mac::stateful_mac tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) tink_cc_test( NAME chunked_mac_test SRCS chunked_mac_test.cc DEPS gmock absl::status tink::core::chunked_mac tink::core::keyset_handle tink::core::mac tink::config::global_registry tink::mac::mac_config tink::mac::mac_key_templates tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) tink_cc_test( NAME config_v0_test SRCS config_v0_test.cc DEPS tink::mac::internal::config_v0 tink::mac::internal::key_gen_config_v0 gmock tink::core::chunked_mac tink::core::configuration tink::core::key_gen_configuration tink::core::keyset_handle tink::core::mac tink::internal::configuration_impl tink::internal::key_gen_configuration_impl tink::internal::key_type_info_store tink::internal::keyset_wrapper_store tink::mac::aes_cmac_key_manager tink::mac::hmac_key_manager tink::mac::mac_key_templates tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) ================================================ FILE: cc/mac/internal/chunked_mac_impl.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/mac/internal/chunked_mac_impl.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "openssl/crypto.h" #include "tink/chunked_mac.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/mac/stateful_mac.h" #include "tink/subtle/stateful_cmac_boringssl.h" #include "tink/subtle/stateful_hmac_boringssl.h" #include "tink/util/enums.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/aes_cmac.pb.h" #include "proto/hmac.pb.h" namespace crypto { namespace tink { namespace internal { using ::google::crypto::tink::AesCmacKey; using ::google::crypto::tink::HmacKey; util::Status ChunkedMacComputationImpl::Update(absl::string_view data) { if (!status_.ok()) return status_; return stateful_mac_->Update(data); } util::StatusOr ChunkedMacComputationImpl::ComputeMac() { if (!status_.ok()) return status_; status_ = util::Status(absl::StatusCode::kFailedPrecondition, "MAC computation already finalized."); return stateful_mac_->Finalize(); } util::Status ChunkedMacVerificationImpl::Update(absl::string_view data) { if (!status_.ok()) return status_; return stateful_mac_->Update(data); } util::Status ChunkedMacVerificationImpl::VerifyMac() { if (!status_.ok()) return status_; status_ = util::Status(absl::StatusCode::kFailedPrecondition, "MAC verification already finalized."); util::StatusOr computed_mac = stateful_mac_->Finalize(); if (!computed_mac.ok()) { return computed_mac.status(); } if (computed_mac->size() != tag_.size()) { return util::Status(absl::StatusCode::kInvalidArgument, "Verification failed."); } if (CRYPTO_memcmp(computed_mac->data(), tag_.data(), computed_mac->size())) { return util::Status(absl::StatusCode::kInvalidArgument, "Verification failed."); } return util::OkStatus(); } util::StatusOr> ChunkedMacImpl::CreateComputation() const { util::StatusOr> stateful_mac = stateful_mac_factory_->Create(); if (!stateful_mac.ok()) return stateful_mac.status(); return std::unique_ptr( new ChunkedMacComputationImpl(*std::move(stateful_mac))); } util::StatusOr> ChunkedMacImpl::CreateVerification(absl::string_view tag) const { util::StatusOr> stateful_mac = stateful_mac_factory_->Create(); if (!stateful_mac.ok()) return stateful_mac.status(); return std::unique_ptr( new ChunkedMacVerificationImpl(*std::move(stateful_mac), tag)); } util::StatusOr> NewChunkedCmac( const AesCmacKey& key) { if (!key.has_params()) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid key: missing parameters."); } util::SecretData secret_key_data = util::SecretDataFromStringView(key.key_value()); auto stateful_mac_factory = absl::make_unique( key.params().tag_size(), secret_key_data); return std::unique_ptr( new ChunkedMacImpl(std::move(stateful_mac_factory))); } util::StatusOr> NewChunkedHmac(const HmacKey& key) { if (!key.has_params()) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid key: missing paramaters."); } subtle::HashType hash_type = util::Enums::ProtoToSubtle(key.params().hash()); util::SecretData secret_key_data = util::SecretDataFromStringView(key.key_value()); auto stateful_mac_factory = absl::make_unique( hash_type, key.params().tag_size(), secret_key_data); return std::unique_ptr( new ChunkedMacImpl(std::move(stateful_mac_factory))); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/internal/chunked_mac_impl.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_INTERNAL_CHUNKED_MAC_IMPL_H_ #define TINK_MAC_INTERNAL_CHUNKED_MAC_IMPL_H_ #include #include #include #include "absl/strings/string_view.h" #include "tink/chunked_mac.h" #include "tink/subtle/mac/stateful_mac.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/aes_cmac.pb.h" #include "proto/hmac.pb.h" namespace crypto { namespace tink { namespace internal { class ChunkedMacComputationImpl : public ChunkedMacComputation { public: explicit ChunkedMacComputationImpl( std::unique_ptr stateful_mac) : stateful_mac_(std::move(stateful_mac)) {} util::Status Update(absl::string_view data) override; util::StatusOr ComputeMac() override; private: const std::unique_ptr stateful_mac_; util::Status status_ = util::OkStatus(); }; class ChunkedMacVerificationImpl : public ChunkedMacVerification { public: explicit ChunkedMacVerificationImpl( std::unique_ptr stateful_mac, absl::string_view tag) : stateful_mac_(std::move(stateful_mac)), tag_(tag) {} util::Status Update(absl::string_view data) override; util::Status VerifyMac() override; private: const std::unique_ptr stateful_mac_; const std::string tag_; util::Status status_ = util::OkStatus(); }; class ChunkedMacImpl : public ChunkedMac { public: explicit ChunkedMacImpl( std::unique_ptr stateful_mac_factory) : stateful_mac_factory_(std::move(stateful_mac_factory)) {} util::StatusOr> CreateComputation() const override; util::StatusOr> CreateVerification( absl::string_view tag) const override; private: std::unique_ptr stateful_mac_factory_; }; // Create new Chunked CMAC instance from `key`. util::StatusOr> NewChunkedCmac( const google::crypto::tink::AesCmacKey& key); // Create new Chunked HMAC instance from `key`. util::StatusOr> NewChunkedHmac( const google::crypto::tink::HmacKey& key); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_MAC_INTERNAL_CHUNKED_MAC_IMPL_H_ ================================================ FILE: cc/mac/internal/chunked_mac_impl_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/mac/internal/chunked_mac_impl.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/chunked_mac.h" #include "tink/subtle/mac/stateful_mac.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/aes_cmac.pb.h" #include "proto/common.pb.h" #include "proto/hmac.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::AesCmacKey; using ::google::crypto::tink::AesCmacParams; using ::google::crypto::tink::HashType; using ::google::crypto::tink::HmacKey; using ::google::crypto::tink::HmacParams; using ::testing::_; using ::testing::ByMove; using ::testing::Return; class MockStatefulMac : public subtle::StatefulMac { public: MOCK_METHOD(util::Status, Update, (absl::string_view), (override)); MOCK_METHOD(util::StatusOr, Finalize, (), (override)); }; class MockStatefulMacFactory : public subtle::StatefulMacFactory { public: MOCK_METHOD(util::StatusOr>, Create, (), (const, override)); }; TEST(ChunkedMacFactoryTest, NewChunkedCmacSucceeds) { AesCmacParams params; params.set_tag_size(16); AesCmacKey key; *key.mutable_params() = params; EXPECT_THAT(NewChunkedCmac(key), IsOk()); } TEST(ChunkedMacFactoryTest, NewChunkedCmacWithMissingKeyParamsFails) { EXPECT_THAT(NewChunkedCmac(AesCmacKey()).status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(ChunkedMacFactoryTest, NewChunkedHmacSucceeds) { HmacParams params; params.set_hash(HashType::SHA256); params.set_tag_size(16); HmacKey key; *key.mutable_params() = params; EXPECT_THAT(NewChunkedHmac(key), IsOk()); } TEST(ChunkedMacFactoryTest, NewChunkedHmacWithMissingKeyParamsFails) { EXPECT_THAT(NewChunkedHmac(HmacKey()).status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(ChunkedMacImplTest, CreateComputationSucceeds) { auto factory = absl::make_unique(); auto stateful_mac = absl::make_unique(); EXPECT_CALL(*factory, Create()) .WillOnce( Return(ByMove(util::StatusOr>( std::move(stateful_mac))))); ChunkedMacImpl chunked_mac(std::move(factory)); EXPECT_THAT(chunked_mac.CreateComputation(), IsOk()); } TEST(ChunkedMacImplTest, CreateComputationWithFactoryErrorFails) { auto factory = absl::make_unique(); util::StatusOr> error_status = util::Status(absl::StatusCode::kInternal, "Internal error."); EXPECT_CALL(*factory, Create()) .WillOnce(Return(ByMove(std::move(error_status)))); ChunkedMacImpl chunked_mac(std::move(factory)); EXPECT_THAT(chunked_mac.CreateComputation().status(), StatusIs(absl::StatusCode::kInternal)); } TEST(ChunkedMacImplTest, CreateVerificationSucceeds) { auto factory = absl::make_unique(); auto stateful_mac = absl::make_unique(); EXPECT_CALL(*factory, Create()) .WillOnce( Return(ByMove(util::StatusOr>( std::move(stateful_mac))))); ChunkedMacImpl chunked_mac(std::move(factory)); EXPECT_THAT(chunked_mac.CreateVerification("tag"), IsOk()); } TEST(ChunkedMacImplTest, CreateVerificationWithFactoryErrorFails) { auto factory = absl::make_unique(); util::StatusOr> error_status = util::Status(absl::StatusCode::kInternal, "Internal error."); EXPECT_CALL(*factory, Create()) .WillOnce(Return(ByMove(std::move(error_status)))); ChunkedMacImpl chunked_mac(std::move(factory)); EXPECT_THAT(chunked_mac.CreateVerification("tag").status(), StatusIs(absl::StatusCode::kInternal)); } TEST(ChunkedMacComputationImplTest, UpdateSucceeds) { auto stateful_mac = absl::make_unique(); EXPECT_CALL(*stateful_mac, Update(_)).WillOnce(Return(util::OkStatus())); ChunkedMacComputationImpl mac_computation(std::move(stateful_mac)); EXPECT_THAT(mac_computation.Update("data"), IsOk()); } TEST(ChunkedMacComputationImplTest, UpdateFails) { auto stateful_mac = absl::make_unique(); util::Status error_status = util::Status(absl::StatusCode::kInternal, "Internal error."); EXPECT_CALL(*stateful_mac, Update(_)).WillOnce(Return(error_status)); ChunkedMacComputationImpl mac_computation(std::move(stateful_mac)); EXPECT_THAT(mac_computation.Update("data"), StatusIs(error_status.code())); } TEST(ChunkedMacComputationImplTest, OperationsFailAfterComputeMac) { auto stateful_mac = absl::make_unique(); util::StatusOr tag = std::string("tag"); EXPECT_CALL(*stateful_mac, Finalize()).WillOnce(Return(tag)); ChunkedMacComputationImpl mac_computation(std::move(stateful_mac)); EXPECT_THAT(mac_computation.ComputeMac(), IsOkAndHolds(*tag)); EXPECT_THAT(mac_computation.Update("data"), StatusIs(absl::StatusCode::kFailedPrecondition)); EXPECT_THAT(mac_computation.ComputeMac().status(), StatusIs(absl::StatusCode::kFailedPrecondition)); } TEST(ChunkedMacComputationImplTest, ComputeMacSucceeds) { auto stateful_mac = absl::make_unique(); util::StatusOr tag = std::string("tag"); EXPECT_CALL(*stateful_mac, Finalize()).WillOnce(Return(tag)); ChunkedMacComputationImpl mac_computation(std::move(stateful_mac)); EXPECT_THAT(mac_computation.ComputeMac(), IsOkAndHolds(*tag)); } TEST(ChunkedMacComputationImplTest, ComputeMacFails) { auto stateful_mac = absl::make_unique(); util::Status error_status = util::Status(absl::StatusCode::kInternal, "Internal error."); EXPECT_CALL(*stateful_mac, Finalize()).WillOnce(Return(error_status)); ChunkedMacComputationImpl mac_computation(std::move(stateful_mac)); EXPECT_THAT(mac_computation.ComputeMac().status(), StatusIs(error_status.code())); } TEST(ChunkedMacVerificationImplTest, UpdateSucceeds) { auto stateful_mac = absl::make_unique(); EXPECT_CALL(*stateful_mac, Update(_)).WillOnce(Return(util::OkStatus())); ChunkedMacVerificationImpl mac_verification(std::move(stateful_mac), "tag"); EXPECT_THAT(mac_verification.Update("data"), IsOk()); } TEST(ChunkedMacVerificationImplTest, UpdateFails) { auto stateful_mac = absl::make_unique(); util::Status error_status = util::Status(absl::StatusCode::kInternal, "Internal error."); EXPECT_CALL(*stateful_mac, Update(_)).WillOnce(Return(error_status)); ChunkedMacVerificationImpl mac_verification(std::move(stateful_mac), "tag"); EXPECT_THAT(mac_verification.Update("data"), StatusIs(error_status.code())); } TEST(ChunkedMacVerificationImplTest, VerifyMacSucceeds) { auto stateful_mac = absl::make_unique(); util::StatusOr tag = std::string("tag"); EXPECT_CALL(*stateful_mac, Finalize()).WillOnce(Return(tag)); ChunkedMacVerificationImpl mac_verification(std::move(stateful_mac), *tag); EXPECT_THAT(mac_verification.VerifyMac(), IsOk()); } TEST(ChunkedMacVerificationImplTest, VerifyMacFailsWithInvalidSameLengthTag) { auto stateful_mac = absl::make_unique(); util::StatusOr tag = std::string("tag123"); EXPECT_CALL(*stateful_mac, Finalize()).WillOnce(Return(tag)); ChunkedMacVerificationImpl mac_verification(std::move(stateful_mac), "tag456"); EXPECT_THAT(mac_verification.VerifyMac(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(ChunkedMacVerificationImplTest, VerifyMacFailsWithDifferentLengthTag) { auto stateful_mac = absl::make_unique(); util::StatusOr tag = std::string("tag"); EXPECT_CALL(*stateful_mac, Finalize()).WillOnce(Return(tag)); ChunkedMacVerificationImpl mac_verification(std::move(stateful_mac), "tag456"); EXPECT_THAT(mac_verification.VerifyMac(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(ChunkedMacVerificationImplTest, VerifyMacFailsWithFinalizeError) { auto stateful_mac = absl::make_unique(); util::Status error_status = util::Status(absl::StatusCode::kInternal, "Internal error."); EXPECT_CALL(*stateful_mac, Finalize()).WillOnce(Return(error_status)); ChunkedMacVerificationImpl mac_verification(std::move(stateful_mac), "tag"); EXPECT_THAT(mac_verification.VerifyMac(), StatusIs(error_status.code())); } TEST(ChunkedMacVerificationImplTest, OperationsFailAfterVerifyMac) { auto stateful_mac = absl::make_unique(); util::StatusOr tag = std::string("tag"); EXPECT_CALL(*stateful_mac, Finalize()).WillOnce(Return(tag)); ChunkedMacVerificationImpl mac_verification(std::move(stateful_mac), *tag); EXPECT_THAT(mac_verification.VerifyMac(), IsOk()); EXPECT_THAT(mac_verification.Update("data"), StatusIs(absl::StatusCode::kFailedPrecondition)); EXPECT_THAT(mac_verification.VerifyMac(), StatusIs(absl::StatusCode::kFailedPrecondition)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/internal/chunked_mac_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/chunked_mac.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/config/global_registry.h" #include "tink/keyset_handle.h" #include "tink/mac.h" #include "tink/mac/mac_config.h" #include "tink/mac/mac_key_templates.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::MacKeyTemplates; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::Combine; using ::testing::Values; class ChunkedMacCompatibilityTest : public testing::TestWithParam> { }; INSTANTIATE_TEST_SUITE_P( ChunkedMacCompatibilityTestSuite, ChunkedMacCompatibilityTest, Combine(Values(MacKeyTemplates::AesCmac(), MacKeyTemplates::HmacSha256()), Values(OutputPrefixType::LEGACY, OutputPrefixType::RAW, OutputPrefixType::CRUNCHY, OutputPrefixType::TINK))); TEST_P(ChunkedMacCompatibilityTest, ComputeAndVerify) { KeyTemplate key_template; OutputPrefixType output_prefix_type; std::tie(key_template, output_prefix_type) = GetParam(); key_template.set_output_prefix_type(output_prefix_type); ASSERT_THAT(MacConfig::Register(), IsOk()); util::StatusOr> key = KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()); ASSERT_THAT(key, IsOk()); util::StatusOr> mac = (*key)->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(mac, IsOk()); util::StatusOr> chunked_mac = (*key)->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(chunked_mac, IsOk()); // Compute tag with chunked MAC. util::StatusOr> computation = (*chunked_mac)->CreateComputation(); ASSERT_THAT(computation, IsOk()); ASSERT_THAT((*computation)->Update("abc"), IsOk()); ASSERT_THAT((*computation)->Update("xyz"), IsOk()); util::StatusOr chunked_tag = (*computation)->ComputeMac(); ASSERT_THAT(chunked_tag, IsOk()); // Verify tag with regular MAC. ASSERT_THAT((*mac)->VerifyMac(*chunked_tag, "abcxyz"), IsOk()); // Compute tag with regular MAC. util::StatusOr tag = (*mac)->ComputeMac("abcxyz"); ASSERT_THAT(tag, IsOk()); ASSERT_THAT(*tag, Eq(*chunked_tag)); // Verify tag with chunked MAC. util::StatusOr> verification = (*chunked_mac)->CreateVerification(*tag); ASSERT_THAT(verification, IsOk()); ASSERT_THAT((*verification)->Update("abc"), IsOk()); ASSERT_THAT((*verification)->Update("xyz"), IsOk()); EXPECT_THAT((*verification)->VerifyMac(), IsOk()); } TEST(ChunkedMacSlicingTest, DifferentChunkSizes) { ASSERT_THAT(MacConfig::Register(), IsOk()); util::StatusOr> key = KeysetHandle::GenerateNew( MacKeyTemplates::HmacSha256(), KeyGenConfigGlobalRegistry()); ASSERT_THAT(key, IsOk()); util::StatusOr> chunked_mac = (*key)->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(chunked_mac, IsOk()); // Update three input chunks. util::StatusOr> computation = (*chunked_mac)->CreateComputation(); ASSERT_THAT(computation, IsOk()); ASSERT_THAT((*computation)->Update("ab"), IsOk()); ASSERT_THAT((*computation)->Update("cx"), IsOk()); ASSERT_THAT((*computation)->Update("yz"), IsOk()); util::StatusOr tag = (*computation)->ComputeMac(); ASSERT_THAT(tag, IsOk()); // Update two input chunks. util::StatusOr> verification = (*chunked_mac)->CreateVerification(*tag); ASSERT_THAT(verification, IsOk()); ASSERT_THAT((*verification)->Update("abc"), IsOk()); ASSERT_THAT((*verification)->Update("xyz"), IsOk()); EXPECT_THAT((*verification)->VerifyMac(), IsOk()); } TEST(ChunkedMacTest, VerifyPrefixFails) { ASSERT_THAT(MacConfig::Register(), IsOk()); util::StatusOr> key = KeysetHandle::GenerateNew( MacKeyTemplates::HmacSha256(), KeyGenConfigGlobalRegistry()); ASSERT_THAT(key, IsOk()); util::StatusOr> chunked_mac = (*key)->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(chunked_mac, IsOk()); util::StatusOr> computation = (*chunked_mac)->CreateComputation(); ASSERT_THAT(computation, IsOk()); ASSERT_THAT((*computation)->Update("abcxyz"), IsOk()); util::StatusOr tag = (*computation)->ComputeMac(); ASSERT_THAT(tag, IsOk()); util::StatusOr> verification = (*chunked_mac)->CreateVerification(*tag); ASSERT_THAT(verification, IsOk()); ASSERT_THAT((*verification)->Update("abc"), IsOk()); EXPECT_THAT((*verification)->VerifyMac(), StatusIs(absl::StatusCode::kUnknown)); } TEST(ChunkedMacTest, UpdateWrongOrderFails) { ASSERT_THAT(MacConfig::Register(), IsOk()); util::StatusOr> key = KeysetHandle::GenerateNew( MacKeyTemplates::HmacSha256(), KeyGenConfigGlobalRegistry()); ASSERT_THAT(key, IsOk()); util::StatusOr> chunked_mac = (*key)->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(chunked_mac, IsOk()); util::StatusOr> computation = (*chunked_mac)->CreateComputation(); ASSERT_THAT(computation, IsOk()); ASSERT_THAT((*computation)->Update("abc"), IsOk()); ASSERT_THAT((*computation)->Update("xyz"), IsOk()); util::StatusOr tag = (*computation)->ComputeMac(); ASSERT_THAT(tag, IsOk()); util::StatusOr> verification = (*chunked_mac)->CreateVerification(*tag); ASSERT_THAT(verification, IsOk()); ASSERT_THAT((*verification)->Update("xyz"), IsOk()); ASSERT_THAT((*verification)->Update("abc"), IsOk()); EXPECT_THAT((*verification)->VerifyMac(), StatusIs(absl::StatusCode::kUnknown)); } TEST(ChunkedMacTest, OperationsFailAfterComputeVerifyMac) { ASSERT_THAT(MacConfig::Register(), IsOk()); util::StatusOr> key = KeysetHandle::GenerateNew( MacKeyTemplates::HmacSha256(), KeyGenConfigGlobalRegistry()); ASSERT_THAT(key, IsOk()); util::StatusOr> chunked_mac = (*key)->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(chunked_mac, IsOk()); util::StatusOr> computation = (*chunked_mac)->CreateComputation(); ASSERT_THAT(computation, IsOk()); ASSERT_THAT((*computation)->Update("abc"), IsOk()); ASSERT_THAT((*computation)->Update("xyz"), IsOk()); util::StatusOr tag = (*computation)->ComputeMac(); ASSERT_THAT(tag, IsOk()); // ChunkedMacComputation has already been finalized. EXPECT_THAT((*computation)->Update("toolate"), StatusIs(absl::StatusCode::kFailedPrecondition)); EXPECT_THAT((*computation)->ComputeMac().status(), StatusIs(absl::StatusCode::kFailedPrecondition)); util::StatusOr> verification = (*chunked_mac)->CreateVerification(*tag); ASSERT_THAT(verification, IsOk()); ASSERT_THAT((*verification)->Update("abc"), IsOk()); ASSERT_THAT((*verification)->Update("xyz"), IsOk()); EXPECT_THAT((*verification)->VerifyMac(), IsOk()); // ChunkedMacVerification has already been finalized. EXPECT_THAT((*verification)->Update("toolate"), StatusIs(absl::StatusCode::kUnknown)); EXPECT_THAT((*verification)->VerifyMac(), StatusIs(absl::StatusCode::kUnknown)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/internal/chunked_mac_wrapper.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/mac/internal/chunked_mac_wrapper.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/chunked_mac.h" #include "tink/crypto_format.h" #include "tink/internal/util.h" #include "tink/primitive_set.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::google::crypto::tink::OutputPrefixType; class ChunkedMacComputationSetWrapper : public ChunkedMacComputation { public: explicit ChunkedMacComputationSetWrapper( std::unique_ptr computation, absl::string_view tag_prefix, OutputPrefixType output_prefix_type) : computation_(std::move(computation)), tag_prefix_(tag_prefix), output_prefix_type_(output_prefix_type) {} util::Status Update(absl::string_view data) override; util::StatusOr ComputeMac() override; private: const std::unique_ptr computation_; const std::string tag_prefix_; const OutputPrefixType output_prefix_type_; }; util::Status ChunkedMacComputationSetWrapper::Update(absl::string_view data) { return computation_->Update(data); } util::StatusOr ChunkedMacComputationSetWrapper::ComputeMac() { if (output_prefix_type_ == OutputPrefixType::LEGACY) { util::Status append_status = computation_->Update(std::string("\x00", 1)); if (!append_status.ok()) return append_status; } util::StatusOr raw_tag = computation_->ComputeMac(); if (!raw_tag.ok()) return raw_tag.status(); return absl::StrCat(tag_prefix_, *raw_tag); } class ChunkedMacVerificationWithPrefixType : public ChunkedMacVerification { public: explicit ChunkedMacVerificationWithPrefixType( std::unique_ptr verification, OutputPrefixType output_prefix_type) : verification_(std::move(verification)), output_prefix_type_(output_prefix_type) {} util::Status Update(absl::string_view data) override; util::Status VerifyMac() override; private: const std::unique_ptr verification_; const OutputPrefixType output_prefix_type_; }; util::Status ChunkedMacVerificationWithPrefixType::Update( absl::string_view data) { return verification_->Update(data); } util::Status ChunkedMacVerificationWithPrefixType::VerifyMac() { if (output_prefix_type_ == OutputPrefixType::LEGACY) { util::Status append_status = verification_->Update(std::string("\x00", 1)); if (!append_status.ok()) return append_status; } return verification_->VerifyMac(); } class ChunkedMacVerificationSetWrapper : public ChunkedMacVerification { public: explicit ChunkedMacVerificationSetWrapper( std::unique_ptr< std::vector>> verifications) : verifications_(std::move(verifications)) {} util::Status Update(absl::string_view data) override; util::Status VerifyMac() override; private: const std::unique_ptr< std::vector>> verifications_; }; util::Status ChunkedMacVerificationSetWrapper::Update(absl::string_view data) { util::Status status = util::Status(absl::StatusCode::kUnknown, "Update failed."); for (auto& verification : *verifications_) { util::Status individual_update_status = verification->Update(data); if (individual_update_status.ok()) { // At least one update succeeded. status = util::OkStatus(); } } return status; } util::Status ChunkedMacVerificationSetWrapper::VerifyMac() { for (auto& verification : *verifications_) { absl::Status status = verification->VerifyMac(); if (status.ok()) { // One of the verifications succeeded. return status; } } return util::Status(absl::StatusCode::kUnknown, "Verification failed."); } class ChunkedMacSetWrapper : public ChunkedMac { public: explicit ChunkedMacSetWrapper( std::unique_ptr> mac_set) : mac_set_(std::move(mac_set)) {} util::StatusOr> CreateComputation() const override; util::StatusOr> CreateVerification( absl::string_view tag) const override; ~ChunkedMacSetWrapper() override = default; private: std::unique_ptr> mac_set_; }; util::Status Validate(PrimitiveSet* mac_set) { if (mac_set == nullptr) { return util::Status(absl::StatusCode::kInternal, "mac_set must be non-NULL"); } if (mac_set->get_primary() == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "mac_set has no primary"); } return util::OkStatus(); } util::StatusOr> ChunkedMacSetWrapper::CreateComputation() const { const PrimitiveSet::Entry* primary = mac_set_->get_primary(); util::StatusOr> computation = primary->get_primitive().CreateComputation(); if (!computation.ok()) return computation.status(); return {absl::make_unique( *std::move(computation), primary->get_identifier(), primary->get_output_prefix_type())}; } util::StatusOr> ChunkedMacSetWrapper::CreateVerification(absl::string_view tag) const { tag = internal::EnsureStringNonNull(tag); auto verifications = absl::make_unique< std::vector>>(); // Create verifications for all non-RAW keys with matching identifiers by // removing prefix. if (tag.length() > CryptoFormat::kNonRawPrefixSize) { absl::string_view key_id = tag.substr(0, CryptoFormat::kNonRawPrefixSize); auto primitives_result = mac_set_->get_primitives(key_id); if (primitives_result.ok()) { absl::string_view raw_tag = tag.substr(CryptoFormat::kNonRawPrefixSize); for (auto& mac_entry : *(primitives_result.value())) { util::StatusOr> verification = mac_entry->get_primitive().CreateVerification(raw_tag); if (verification.ok()) { auto verification_with_prefix = absl::make_unique( *std::move(verification), mac_entry->get_output_prefix_type()); verifications->push_back(std::move(verification_with_prefix)); } } } } // Create verifications for all RAW keys by including prefix. auto raw_primitives_result = mac_set_->get_raw_primitives(); if (raw_primitives_result.ok()) { for (auto& mac_entry : *(raw_primitives_result.value())) { util::StatusOr> verification = mac_entry->get_primitive().CreateVerification(tag); if (verification.ok()) { auto verification_with_prefix = absl::make_unique( *std::move(verification), mac_entry->get_output_prefix_type()); verifications->push_back(std::move(verification_with_prefix)); } } } return {absl::make_unique( std::move(verifications))}; } } // namespace util::StatusOr> ChunkedMacWrapper::Wrap( std::unique_ptr> mac_set) const { util::Status status = Validate(mac_set.get()); if (!status.ok()) return status; return {absl::make_unique(std::move(mac_set))}; } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/internal/chunked_mac_wrapper.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_INTERNAL_CHUNKED_MAC_WRAPPER_H_ #define TINK_MAC_INTERNAL_CHUNKED_MAC_WRAPPER_H_ #include #include "absl/strings/string_view.h" #include "tink/chunked_mac.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { // Wraps a set of ChunkedMac-instances that correspond to a keyset, // and combines them into a single ChunkedMac-primitive, that uses the provided // instances, depending on the context: // * ChunkedMac::CreateComputation(...) uses the primary instance from the // set. // * ChunkedMac::CreateVerification(...) uses all instances with matching // MAC prefixes. class ChunkedMacWrapper : public PrimitiveWrapper { public: util::StatusOr> Wrap( std::unique_ptr> mac_set) const override; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_MAC_INTERNAL_CHUNKED_MAC_WRAPPER_H_ ================================================ FILE: cc/mac/internal/chunked_mac_wrapper_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/mac/internal/chunked_mac_wrapper.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/chunked_mac.h" #include "tink/mac/internal/chunked_mac_impl.h" #include "tink/primitive_set.h" #include "tink/subtle/mac/stateful_mac.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::KeysetInfo; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::OutputPrefixType; using ::testing::Values; class FakeStatefulMac : public subtle::StatefulMac { public: explicit FakeStatefulMac(absl::string_view name) : name_(name) {} util::Status Update(absl::string_view data) override { absl::StrAppend(&buffer_, data); return util::OkStatus(); } util::StatusOr Finalize() override { return absl::StrCat(name_, buffer_); } private: const std::string name_; std::string buffer_ = ""; }; class FakeStatefulMacFactory : public subtle::StatefulMacFactory { public: explicit FakeStatefulMacFactory(absl::string_view name) : name_(name) {} util::StatusOr> Create() const override { return std::unique_ptr( absl::make_unique(name_)); } private: std::string name_; }; TEST(ChunkedMacWrapperTest, WrapNullptr) { EXPECT_THAT(ChunkedMacWrapper().Wrap(nullptr).status(), StatusIs(absl::StatusCode::kInternal)); } TEST(ChunkedMacWrapperTest, WrapEmpty) { std::unique_ptr> mac_set( new PrimitiveSet()); EXPECT_THAT(ChunkedMacWrapper().Wrap(std::move(mac_set)).status(), StatusIs(absl::StatusCode::kInvalidArgument)); } std::unique_ptr CreateFakeChunkedMac(absl::string_view name) { return absl::make_unique( absl::make_unique(name)); } util::Status AddPrimitiveToSet(uint32_t key_id, bool set_primary, OutputPrefixType output_prefix_type, std::unique_ptr mac, KeysetInfo& keyset_info, PrimitiveSet& mac_set) { int index = keyset_info.key_info_size(); KeysetInfo::KeyInfo* key_info = keyset_info.add_key_info(); key_info->set_output_prefix_type(output_prefix_type); key_info->set_key_id(key_id); key_info->set_status(KeyStatusType::ENABLED); auto entry = mac_set.AddPrimitive(std::move(mac), keyset_info.key_info(index)); if (!entry.ok()) { return entry.status(); } if (set_primary) { util::Status set_primary_status = mac_set.set_primary(*entry); if (!set_primary_status.ok()) { return set_primary_status; } } return util::OkStatus(); } TEST(ChunkedMacWrapperTest, ComputeMac) { KeysetInfo keyset_info; auto mac_set = absl::make_unique>(); // Add primitives to the primitive set. ASSERT_THAT( AddPrimitiveToSet( /*key_id=*/0x12d66f, /*set_primary=*/false, OutputPrefixType::TINK, CreateFakeChunkedMac("chunkedmac0:"), keyset_info, *mac_set), IsOk()); ASSERT_THAT( AddPrimitiveToSet( /*key_id=*/0xb1539, /*set_primary=*/false, OutputPrefixType::LEGACY, CreateFakeChunkedMac("chunkedmac1:"), keyset_info, *mac_set), IsOk()); ASSERT_THAT( AddPrimitiveToSet( /*key_id=*/0x6e12af, /*set_primary=*/true, OutputPrefixType::TINK, CreateFakeChunkedMac("chunkedmac2:"), keyset_info, *mac_set), IsOk()); // Wrap primitive set into a ChunkedMac. util::StatusOr> chunked_mac = ChunkedMacWrapper().Wrap(std::move(mac_set)); ASSERT_THAT(chunked_mac.status(), IsOk()); util::StatusOr> computation = (*chunked_mac)->CreateComputation(); EXPECT_THAT(computation.status(), IsOk()); EXPECT_THAT((*computation)->Update("inputdata"), IsOk()); util::StatusOr tag = (*computation)->ComputeMac(); const std::string output_prefix = std::string("\x01\x00\x6e\x12\xaf", 5); const std::string raw_tag = "chunkedmac2:inputdata"; EXPECT_THAT(tag, IsOkAndHolds(absl::StrCat(output_prefix, raw_tag))); } TEST(ChunkedMacWrapperTest, VerifyMacWithUniquePrefix) { KeysetInfo keyset_info; auto mac_set = absl::make_unique>(); // Add primitives to primitive set. ASSERT_THAT( AddPrimitiveToSet( /*key_id=*/0x12d66f, /*set_primary=*/false, OutputPrefixType::TINK, CreateFakeChunkedMac("chunkedmac0:"), keyset_info, *mac_set), IsOk()); ASSERT_THAT( AddPrimitiveToSet( /*key_id=*/0xb1539, /*set_primary=*/false, OutputPrefixType::LEGACY, CreateFakeChunkedMac("chunkedmac1:"), keyset_info, *mac_set), IsOk()); ASSERT_THAT( AddPrimitiveToSet( /*key_id=*/0x6e12af, /*set_primary=*/true, OutputPrefixType::TINK, CreateFakeChunkedMac("chunkedmac2:"), keyset_info, *mac_set), IsOk()); // Wrap primitive set into a ChunkedMac. util::StatusOr> chunked_mac = ChunkedMacWrapper().Wrap(std::move(mac_set)); ASSERT_THAT(chunked_mac.status(), IsOk()); const std::string output_prefix = std::string("\x01\x00\x6e\x12\xaf", 5); const std::string raw_tag = "chunkedmac2:inputdata"; util::StatusOr> verification = (*chunked_mac) ->CreateVerification(absl::StrCat(output_prefix, raw_tag)); EXPECT_THAT(verification.status(), IsOk()); EXPECT_THAT((*verification)->Update("inputdata"), IsOk()); EXPECT_THAT((*verification)->VerifyMac(), IsOk()); } TEST(ChunkedMacWrapperTest, VerifyMacWithDuplicatePrefix) { KeysetInfo keyset_info; auto mac_set = absl::make_unique>(); // Add primitives to primitive set. ASSERT_THAT( AddPrimitiveToSet( /*key_id=*/0x12d66f, /*set_primary=*/false, OutputPrefixType::LEGACY, CreateFakeChunkedMac("chunkedmac0:"), keyset_info, *mac_set), IsOk()); ASSERT_THAT( AddPrimitiveToSet( /*key_id=*/0x6e12af, /*set_primary=*/false, OutputPrefixType::TINK, CreateFakeChunkedMac("chunkedmac1:"), keyset_info, *mac_set), IsOk()); ASSERT_THAT( AddPrimitiveToSet( /*key_id=*/0x6e12af, /*set_primary=*/true, OutputPrefixType::TINK, CreateFakeChunkedMac("chunkedmac2:"), keyset_info, *mac_set), IsOk()); // Wrap primitive set into a ChunkedMac. util::StatusOr> chunked_mac = ChunkedMacWrapper().Wrap(std::move(mac_set)); ASSERT_THAT(chunked_mac.status(), IsOk()); const std::string output_prefix = std::string("\x01\x00\x6e\x12\xaf", 5); const std::string raw_tag = "chunkedmac1:inputdata"; util::StatusOr> verification = (*chunked_mac) ->CreateVerification(absl::StrCat(output_prefix, raw_tag)); EXPECT_THAT(verification.status(), IsOk()); EXPECT_THAT((*verification)->Update("inputdata"), IsOk()); EXPECT_THAT((*verification)->VerifyMac(), IsOk()); } TEST(ChunkedMacWrapperTest, VerifyMacWithRawTagStartingWithKeyId) { KeysetInfo keyset_info; auto mac_set = absl::make_unique>(); const std::string key_id0 = std::string("\x01\x00\x12\xd6\x6f", 5); // Add primitives to primitive set. ASSERT_THAT( AddPrimitiveToSet( /*key_id=*/0x12d66f, /*set_primary=*/false, OutputPrefixType::TINK, CreateFakeChunkedMac("chunkedmac0:"), keyset_info, *mac_set), IsOk()); ASSERT_THAT( AddPrimitiveToSet( /*key_id=*/0x6e12af, /*set_primary=*/true, OutputPrefixType::RAW, CreateFakeChunkedMac(/*name=*/absl::StrCat(key_id0, ":chunkedmac1:")), keyset_info, *mac_set), IsOk()); // Wrap primitive set into a ChunkedMac. util::StatusOr> chunked_mac = ChunkedMacWrapper().Wrap(std::move(mac_set)); ASSERT_THAT(chunked_mac.status(), IsOk()); const std::string raw_tag = absl::StrCat(key_id0, ":chunkedmac1:inputdata"); util::StatusOr> verification = (*chunked_mac)->CreateVerification(raw_tag); EXPECT_THAT(verification.status(), IsOk()); EXPECT_THAT((*verification)->Update("inputdata"), IsOk()); EXPECT_THAT((*verification)->VerifyMac(), IsOk()); } class ChunkedMacWrapperOutputPrefixTest : public testing::TestWithParam {}; INSTANTIATE_TEST_SUITE_P( ChunkedMacWrapperOutputPrefixTestSuite, ChunkedMacWrapperOutputPrefixTest, Values(OutputPrefixType::LEGACY, OutputPrefixType::RAW, OutputPrefixType::CRUNCHY, OutputPrefixType::TINK)); TEST_P(ChunkedMacWrapperOutputPrefixTest, ComputeVerifyMac) { OutputPrefixType output_prefix_type = GetParam(); KeysetInfo keyset_info; auto mac_set = absl::make_unique>(); // Add primitives to primitive set. ASSERT_THAT( AddPrimitiveToSet( /*key_id=*/0x12d66f, /*set_primary=*/true, output_prefix_type, CreateFakeChunkedMac("chunkedmac:"), keyset_info, *mac_set), IsOk()); // Wrap primitive set into a ChunkedMac. util::StatusOr> chunked_mac = ChunkedMacWrapper().Wrap(std::move(mac_set)); ASSERT_THAT(chunked_mac.status(), IsOk()); // Compute MAC via wrapper. util::StatusOr> mac_computation = (*chunked_mac)->CreateComputation(); ASSERT_THAT(mac_computation.status(), IsOk()); ASSERT_THAT((*mac_computation)->Update("inputdata"), IsOk()); util::StatusOr tag = (*mac_computation)->ComputeMac(); ASSERT_THAT(tag.status(), IsOk()); // Verify MAC via wrapper. util::StatusOr> mac_verification = (*chunked_mac)->CreateVerification(*tag); ASSERT_THAT(mac_verification.status(), IsOk()); ASSERT_THAT((*mac_verification)->Update("inputdata"), IsOk()); ASSERT_THAT((*mac_verification)->VerifyMac(), IsOk()); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/internal/config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/internal/config_v0.h" #include "absl/memory/memory.h" #include "tink/configuration.h" #include "tink/internal/configuration_impl.h" #include "tink/mac/aes_cmac_key_manager.h" #include "tink/mac/hmac_key_manager.h" #include "tink/mac/internal/chunked_mac_wrapper.h" #include "tink/mac/mac_wrapper.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { util::Status AddMacV0(Configuration& config) { util::Status status = ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config); if (!status.ok()) { return status; } status = ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config); if (!status.ok()) { return status; } status = ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); if (!status.ok()) { return status; } return ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/internal/config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_INTERNAL_CONFIG_V0_H_ #define TINK_MAC_INTERNAL_CONFIG_V0_H_ #include "tink/configuration.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { // Add recommended MAC primitive wrappers and key managers to `config`, used to // generate primitives. util::Status AddMacV0(Configuration& config); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_MAC_INTERNAL_CONFIG_V0_H_ ================================================ FILE: cc/mac/internal/config_v0_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/internal/config_v0.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/chunked_mac.h" #include "tink/configuration.h" #include "tink/internal/configuration_impl.h" #include "tink/internal/key_gen_configuration_impl.h" #include "tink/internal/key_type_info_store.h" #include "tink/internal/keyset_wrapper_store.h" #include "tink/key_gen_configuration.h" #include "tink/keyset_handle.h" #include "tink/mac.h" #include "tink/mac/aes_cmac_key_manager.h" #include "tink/mac/hmac_key_manager.h" #include "tink/mac/internal/key_gen_config_v0.h" #include "tink/mac/mac_key_templates.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::google::crypto::tink::KeyTemplate; using ::testing::TestWithParam; using ::testing::Values; TEST(MacV0Test, PrimitiveWrappers) { Configuration config; ASSERT_THAT(AddMacV0(config), IsOk()); util::StatusOr store = ConfigurationImpl::GetKeysetWrapperStore(config); ASSERT_THAT(store, IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); } TEST(MacV0Test, KeyManagers) { Configuration config; ASSERT_THAT(AddMacV0(config), IsOk()); util::StatusOr store = ConfigurationImpl::GetKeyTypeInfoStore(config); ASSERT_THAT(store, IsOk()); KeyGenConfiguration key_gen_config; ASSERT_THAT(AddMacKeyGenV0(key_gen_config), IsOk()); util::StatusOr key_gen_store = KeyGenConfigurationImpl::GetKeyTypeInfoStore(key_gen_config); ASSERT_THAT(key_gen_store, IsOk()); for (const KeyTypeInfoStore* s : {*store, *key_gen_store}) { EXPECT_THAT(s->Get(AesCmacKeyManager().get_key_type()), IsOk()); EXPECT_THAT(s->Get(HmacKeyManager().get_key_type()), IsOk()); } } using MacV0KeyTypesTest = TestWithParam; INSTANTIATE_TEST_SUITE_P(MacV0KeyTypesTestSuite, MacV0KeyTypesTest, Values(MacKeyTemplates::AesCmac(), MacKeyTemplates::HmacSha256())); TEST_P(MacV0KeyTypesTest, GetPrimitive) { KeyGenConfiguration key_gen_config; ASSERT_THAT(AddMacKeyGenV0(key_gen_config), IsOk()); Configuration config; ASSERT_THAT(AddMacV0(config), IsOk()); util::StatusOr> handle = KeysetHandle::GenerateNew(GetParam(), key_gen_config); ASSERT_THAT(handle, IsOk()); util::StatusOr> mac = (*handle)->GetPrimitive(config); ASSERT_THAT(mac, IsOk()); std::string data = "data"; util::StatusOr tag = (*mac)->ComputeMac(data); ASSERT_THAT(tag, IsOk()); EXPECT_THAT((*mac)->VerifyMac(*tag, data), IsOk()); } TEST_P(MacV0KeyTypesTest, GetPrimitiveChunkedMac) { KeyGenConfiguration key_gen_config; ASSERT_THAT(AddMacKeyGenV0(key_gen_config), IsOk()); Configuration config; ASSERT_THAT(AddMacV0(config), IsOk()); util::StatusOr> handle = KeysetHandle::GenerateNew(GetParam(), key_gen_config); ASSERT_THAT(handle, IsOk()); util::StatusOr> chunked_mac = (*handle)->GetPrimitive(config); ASSERT_THAT(chunked_mac, IsOk()); std::string data1 = "da"; std::string data2 = "ta"; util::StatusOr> compute = (*chunked_mac)->CreateComputation(); ASSERT_THAT(compute, IsOk()); ASSERT_THAT((*compute)->Update(data1), IsOk()); ASSERT_THAT((*compute)->Update(data2), IsOk()); util::StatusOr tag = (*compute)->ComputeMac(); ASSERT_THAT(tag, IsOk()); util::StatusOr> verify = (*chunked_mac)->CreateVerification(*tag); ASSERT_THAT(verify, IsOk()); ASSERT_THAT((*verify)->Update(data1), IsOk()); ASSERT_THAT((*verify)->Update(data2), IsOk()); EXPECT_THAT((*verify)->VerifyMac(), IsOk()); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/internal/key_gen_config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/internal/key_gen_config_v0.h" #include "absl/memory/memory.h" #include "tink/internal/key_gen_configuration_impl.h" #include "tink/key_gen_configuration.h" #include "tink/mac/aes_cmac_key_manager.h" #include "tink/mac/hmac_key_manager.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { util::Status AddMacKeyGenV0(KeyGenConfiguration& config) { util::Status status = KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); if (!status.ok()) { return status; } return KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/internal/key_gen_config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_INTERNAL_KEY_GEN_CONFIG_V0_H_ #define TINK_MAC_INTERNAL_KEY_GEN_CONFIG_V0_H_ #include "tink/key_gen_configuration.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { // Add recommended MAC key managers to `config`, used to generate keys. util::Status AddMacKeyGenV0(KeyGenConfiguration& config); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_MAC_INTERNAL_KEY_GEN_CONFIG_V0_H_ ================================================ FILE: cc/mac/key_gen_config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/key_gen_config_v0.h" #include "absl/log/check.h" #include "tink/key_gen_configuration.h" #include "tink/mac/internal/key_gen_config_v0.h" namespace crypto { namespace tink { const KeyGenConfiguration& KeyGenConfigMacV0() { static const KeyGenConfiguration* instance = [] { static KeyGenConfiguration* config = new KeyGenConfiguration(); CHECK_OK(internal::AddMacKeyGenV0(*config)); return config; }(); return *instance; } } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/key_gen_config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_KEY_GEN_CONFIG_V0_H_ #define TINK_MAC_KEY_GEN_CONFIG_V0_H_ #include "tink/key_gen_configuration.h" namespace crypto { namespace tink { // KeyGenConfiguration used to generate MAC keys with recommended key managers. const KeyGenConfiguration& KeyGenConfigMacV0(); } // namespace tink } // namespace crypto #endif // TINK_MAC_KEY_GEN_CONFIG_V0_H_ ================================================ FILE: cc/mac/mac_config.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/mac/mac_config.h" #include "absl/memory/memory.h" #include "tink/config/config_util.h" #include "tink/config/tink_fips.h" #include "tink/mac/aes_cmac_key_manager.h" #include "tink/mac/aes_cmac_proto_serialization.h" #include "tink/mac/hmac_key_manager.h" #include "tink/mac/hmac_proto_serialization.h" #include "tink/mac/internal/chunked_mac_wrapper.h" #include "tink/mac/mac_wrapper.h" #include "tink/registry.h" #include "tink/util/status.h" #include "proto/config.pb.h" namespace crypto { namespace tink { // static util::Status MacConfig::Register() { // Register primitive wrappers. auto status = Registry::RegisterPrimitiveWrapper(absl::make_unique()); if (!status.ok()) return status; status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) return status; // Register key managers which utilize the FIPS validated BoringCrypto // implementations. status = Registry::RegisterKeyTypeManager(absl::make_unique(), true); if (!status.ok()) return status; status = RegisterHmacProtoSerialization(); if (!status.ok()) return status; if (IsFipsModeEnabled()) { return util::OkStatus(); } // CMac in BoringSSL is not FIPS validated. status = Registry::RegisterKeyTypeManager( absl::make_unique(), true); if (!status.ok()) return status; status = RegisterAesCmacProtoSerialization(); if (!status.ok()) return status; return util::OkStatus(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/mac_config.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_MAC_CONFIG_H_ #define TINK_MAC_MAC_CONFIG_H_ #include "absl/base/macros.h" #include "tink/util/status.h" #include "proto/config.pb.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Static methods and constants for registering with the Registry // all instances of Mac key types supported in a particular release of Tink. // // To register all Mac key types from the current Tink release one can do: // // auto status = MacConfig::Register(); // class MacConfig { public: // Registers Mac primitive wrapper and key managers for all Mac key types // from the current Tink release. static crypto::tink::util::Status Register(); private: MacConfig() {} }; } // namespace tink } // namespace crypto #endif // TINK_MAC_MAC_CONFIG_H_ ================================================ FILE: cc/mac/mac_config_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/mac_config.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/chunked_mac.h" #include "tink/config/global_registry.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/fips_utils.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/keyset_handle.h" #include "tink/mac.h" #include "tink/mac/aes_cmac_key.h" #include "tink/mac/aes_cmac_key_manager.h" #include "tink/mac/aes_cmac_parameters.h" #include "tink/mac/hmac_key.h" #include "tink/mac/hmac_key_manager.h" #include "tink/mac/hmac_parameters.h" #include "tink/mac/mac_key_templates.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/primitive_set.h" #include "tink/registry.h" #include "tink/restricted_data.h" #include "tink/subtle/random.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_cmac.pb.h" #include "proto/common.pb.h" #include "proto/hmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::DummyMac; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::KeysetInfo; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::OutputPrefixType; using ::testing::Values; class MacConfigTest : public ::testing::Test { protected: void SetUp() override { Registry::Reset(); internal::MutableSerializationRegistry::GlobalInstance().Reset(); } }; TEST_F(MacConfigTest, Basic) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT( Registry::get_key_manager(HmacKeyManager().get_key_type()).status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT( Registry::get_key_manager(HmacKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT(Registry::get_key_manager(AesCmacKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT( Registry::get_key_manager(AesCmacKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(MacConfig::Register(), IsOk()); EXPECT_THAT( Registry::get_key_manager(HmacKeyManager().get_key_type()).status(), IsOk()); EXPECT_THAT( Registry::get_key_manager(HmacKeyManager().get_key_type()) .status(), IsOk()); EXPECT_THAT(Registry::get_key_manager(AesCmacKeyManager().get_key_type()) .status(), IsOk()); EXPECT_THAT( Registry::get_key_manager(AesCmacKeyManager().get_key_type()) .status(), IsOk()); } // Tests that the MacWrapper has been properly registered and we can wrap // primitives. TEST_F(MacConfigTest, MacWrappersRegistered) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } ASSERT_TRUE(MacConfig::Register().ok()); KeysetInfo::KeyInfo key_info; key_info.set_status(KeyStatusType::ENABLED); key_info.set_key_id(1234); key_info.set_output_prefix_type(OutputPrefixType::RAW); auto primitive_set = absl::make_unique>(); ASSERT_TRUE( primitive_set ->set_primary( primitive_set ->AddPrimitive(absl::make_unique("dummy"), key_info) .value()) .ok()); auto primitive_result = Registry::Wrap(std::move(primitive_set)); ASSERT_TRUE(primitive_result.ok()) << primitive_result.status(); auto mac_result = primitive_result.value()->ComputeMac("verified text"); ASSERT_TRUE(mac_result.ok()); EXPECT_TRUE( DummyMac("dummy").VerifyMac(mac_result.value(), "verified text").ok()); EXPECT_FALSE( DummyMac("dummy").VerifyMac(mac_result.value(), "faked text").ok()); } TEST_F(MacConfigTest, AesCmacProtoParamsSerializationRegistered) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::StatusOr proto_params_serialization = internal::ProtoParametersSerialization::Create( MacKeyTemplates::AesCmac()); ASSERT_THAT(proto_params_serialization, IsOk()); util::StatusOr> parsed_params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr params = AesCmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16, AesCmacParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); util::StatusOr> serialized_params = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params.status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(MacConfig::Register(), IsOk()); util::StatusOr> parsed_params2 = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params2, IsOk()); util::StatusOr> serialized_params2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params2, IsOk()); } TEST_F(MacConfigTest, AesCmacProtoKeySerializationRegistered) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } google::crypto::tink::AesCmacKey key_proto; key_proto.set_version(0); key_proto.set_key_value(subtle::Random::GetRandomBytes(32)); key_proto.mutable_params()->set_tag_size(16); util::StatusOr proto_key_serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.AesCmacKey", RestrictedData(key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()), KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/123); ASSERT_THAT(proto_key_serialization, IsOk()); util::StatusOr> parsed_key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr params = AesCmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/16, AesCmacParameters::Variant::kTink); ASSERT_THAT(params, IsOk()); util::StatusOr key = AesCmacKey::Create(*params, RestrictedData(subtle::Random::GetRandomBytes(32), InsecureSecretKeyAccess::Get()), /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialized_key = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key.status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(MacConfig::Register(), IsOk()); util::StatusOr> parsed_key2 = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key2, IsOk()); util::StatusOr> serialized_key2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key2, IsOk()); } TEST_F(MacConfigTest, HmacProtoParamsSerializationRegistered) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::StatusOr proto_params_serialization = internal::ProtoParametersSerialization::Create( MacKeyTemplates::HmacSha256()); ASSERT_THAT(proto_params_serialization, IsOk()); util::StatusOr> parsed_params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr parameters = HmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/32, HmacParameters::HashType::kSha256, HmacParameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); util::StatusOr> serialized_parameters = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( *parameters); ASSERT_THAT(serialized_parameters.status(), StatusIs(absl::StatusCode::kNotFound)); // Register parser and serializer. ASSERT_THAT(MacConfig::Register(), IsOk()); util::StatusOr> parsed_params2 = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params2, IsOk()); util::StatusOr> serialized_params2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( *parameters); ASSERT_THAT(serialized_params2, IsOk()); } TEST_F(MacConfigTest, HmacProtoKeySerializationRegistered) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } google::crypto::tink::HmacKey key_proto; key_proto.set_version(0); key_proto.set_key_value(subtle::Random::GetRandomBytes(32)); key_proto.mutable_params()->set_tag_size(32); key_proto.mutable_params()->set_hash(HashType::SHA256); util::StatusOr proto_key_serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.HmacKey", RestrictedData(key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()), KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/123); ASSERT_THAT(proto_key_serialization, IsOk()); util::StatusOr> parsed_key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr parameters = HmacParameters::Create( /*key_size_in_bytes=*/32, /*cryptographic_tag_size_in_bytes=*/32, HmacParameters::HashType::kSha256, HmacParameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); util::StatusOr key = HmacKey::Create(*parameters, RestrictedData(subtle::Random::GetRandomBytes(32), InsecureSecretKeyAccess::Get()), /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialized_key = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key.status(), StatusIs(absl::StatusCode::kNotFound)); // Register parser and serializer. ASSERT_THAT(MacConfig::Register(), IsOk()); util::StatusOr> parsed_key2 = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key2, IsOk()); util::StatusOr> serialized_key2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key2, IsOk()); } class ChunkedMacConfigTest : public ::testing::TestWithParam { protected: void SetUp() override { Registry::Reset(); } }; INSTANTIATE_TEST_SUITE_P(ChunkedMacConfigTestSuite, ChunkedMacConfigTest, Values(MacKeyTemplates::AesCmac(), MacKeyTemplates::HmacSha256())); // Tests that the ChunkedMacWrapper has been properly registered and we can get // primitives. TEST_P(ChunkedMacConfigTest, ChunkedMacWrappersRegistered) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } ASSERT_THAT(MacConfig::Register(), IsOk()); KeyTemplate key_template = GetParam(); util::StatusOr> key = KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()); ASSERT_THAT(key, IsOk()); util::StatusOr> chunked_mac = (*key)->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(chunked_mac, IsOk()); util::StatusOr> computation = (*chunked_mac)->CreateComputation(); ASSERT_THAT(computation, IsOk()); ASSERT_THAT((*computation)->Update("verified text"), IsOk()); util::StatusOr tag = (*computation)->ComputeMac(); ASSERT_THAT(tag, IsOk()); util::StatusOr> verification = (*chunked_mac)->CreateVerification(*tag); ASSERT_THAT(verification, IsOk()); ASSERT_THAT((*verification)->Update("verified text"), IsOk()); EXPECT_THAT((*verification)->VerifyMac(), IsOk()); } // FIPS-only mode tests TEST_F(MacConfigTest, RegisterNonFipsTemplates) { if (!internal::IsFipsModeEnabled() || !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only supported in FIPS-only mode"; } EXPECT_THAT(MacConfig::Register(), IsOk()); std::list non_fips_key_templates; non_fips_key_templates.push_back(MacKeyTemplates::AesCmac()); for (auto key_template : non_fips_key_templates) { EXPECT_THAT( KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()) .status(), StatusIs(absl::StatusCode::kNotFound)); } } TEST_F(MacConfigTest, RegisterFipsValidTemplates) { if (!internal::IsFipsModeEnabled() || !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only supported in FIPS-only mode"; } EXPECT_THAT(MacConfig::Register(), IsOk()); std::list fips_key_templates; fips_key_templates.push_back(MacKeyTemplates::HmacSha256()); fips_key_templates.push_back(MacKeyTemplates::HmacSha256HalfSizeTag()); fips_key_templates.push_back(MacKeyTemplates::HmacSha512()); fips_key_templates.push_back(MacKeyTemplates::HmacSha512HalfSizeTag()); for (auto key_template : fips_key_templates) { EXPECT_THAT( KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()), IsOk()); } } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/mac_factory.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/mac/mac_factory.h" #include #include "tink/mac.h" #include "tink/mac/mac_wrapper.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // NOLINTBEGIN(whitespace/line_length) (Formatted when commented in) // TINK-PENDING-REMOVAL-IN-3.0.0-START // static util::StatusOr> MacFactory::GetPrimitive( const KeysetHandle& keyset_handle) { util::Status status = Registry::RegisterPrimitiveWrapper(absl::make_unique()); if (!status.ok()) { return status; } return keyset_handle.GetPrimitive(ConfigGlobalRegistry()); } // static util::StatusOr> MacFactory::GetPrimitive( const KeysetHandle& keyset_handle, const KeyManager* custom_key_manager) { util::Status status = Registry::RegisterPrimitiveWrapper(absl::make_unique()); if (!status.ok()) { return status; } return keyset_handle.GetPrimitive(custom_key_manager); } // TINK-PENDING-REMOVAL-IN-3.0.0-END // NOLINTEND(whitespace/line_length) } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/mac_factory.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_MAC_FACTORY_H_ #define TINK_MAC_MAC_FACTORY_H_ #include #include "absl/base/macros.h" #include "tink/key_manager.h" #include "tink/keyset_handle.h" #include "tink/mac.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // This class is deprecated. Call keyset_handle->GetPrimitive() instead. // // Note that in order to for this change to be safe, the AeadSetWrapper has to // be registered in your binary before this call. This happens automatically if // you call one of // * MacConfig::Register() // * AeadConfig::Register() // * HybridConfig::Register() // * TinkConfig::Register() // NOLINTBEGIN(whitespace/line_length) (Formatted when commented in) // TINK-PENDING-REMOVAL-IN-3.0.0-START class ABSL_DEPRECATED( "Call getPrimitive() on the keyset_handle after registering the " "MacWrapper instead.") MacFactory { public: // Returns a Mac-primitive that uses key material from the keyset // specified via 'keyset_handle'. static crypto::tink::util::StatusOr> GetPrimitive( const KeysetHandle& keyset_handle); // Returns a Mac-primitive that uses key material from the keyset // specified via 'keyset_handle' and is instantiated by the given // 'custom_key_manager' (instead of the key manager from the Registry). static crypto::tink::util::StatusOr> GetPrimitive( const KeysetHandle& keyset_handle, const KeyManager* custom_key_manager); private: MacFactory() {} }; // TINK-PENDING-REMOVAL-IN-3.0.0-END // NOLINTEND(whitespace/line_length) } // namespace tink } // namespace crypto #endif // TINK_MAC_MAC_FACTORY_H_ ================================================ FILE: cc/mac/mac_factory_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/mac_factory.h" #include #include #include "gtest/gtest.h" #include "tink/crypto_format.h" #include "tink/internal/key_info.h" #include "tink/keyset_handle.h" #include "tink/mac.h" #include "tink/mac/hmac_key_manager.h" #include "tink/mac/mac_config.h" #include "tink/util/status.h" #include "tink/util/test_keyset_handle.h" #include "tink/util/test_util.h" #include "proto/common.pb.h" #include "proto/hmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { // NOLINTBEGIN(whitespace/line_length) (Formatted when commented in) // TINK-PENDING-REMOVAL-IN-3.0.0-START using crypto::tink::test::AddRawKey; using crypto::tink::test::AddTinkKey; using google::crypto::tink::HashType; using google::crypto::tink::HmacKeyFormat; using google::crypto::tink::KeyData; using google::crypto::tink::Keyset; using google::crypto::tink::KeyStatusType; class MacFactoryTest : public ::testing::Test { }; TEST_F(MacFactoryTest, testBasic) { Keyset keyset; auto mac_result = MacFactory::GetPrimitive(*TestKeysetHandle::GetKeysetHandle(keyset)); EXPECT_FALSE(mac_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, mac_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "at least one key", std::string(mac_result.status().message())); } TEST_F(MacFactoryTest, testPrimitive) { // Prepare a format for generating keys for a Keyset. HmacKeyManager key_type_manager; auto key_manager = internal::MakeKeyManager(&key_type_manager); const KeyFactory& key_factory = key_manager->get_key_factory(); std::string key_type = key_manager->get_key_type(); HmacKeyFormat key_format; key_format.set_key_size(16); key_format.mutable_params()->set_tag_size(10); key_format.mutable_params()->set_hash(HashType::SHA256); // Prepare a Keyset. Keyset keyset; uint32_t key_id_1 = 1234543; auto new_key = std::move(key_factory.NewKey(key_format).value()); AddTinkKey(key_type, key_id_1, *new_key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); uint32_t key_id_2 = 726329; new_key = std::move(key_factory.NewKey(key_format).value()); AddRawKey(key_type, key_id_2, *new_key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); uint32_t key_id_3 = 7213743; new_key = std::move(key_factory.NewKey(key_format).value()); AddTinkKey(key_type, key_id_3, *new_key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset); keyset.set_primary_key_id(key_id_3); // Initialize the registry. ASSERT_TRUE(MacConfig::Register().ok());; // Create a KeysetHandle and use it with the factory. auto mac_result = MacFactory::GetPrimitive(*TestKeysetHandle::GetKeysetHandle(keyset)); EXPECT_TRUE(mac_result.ok()) << mac_result.status(); auto mac = std::move(mac_result.value()); // Test the resulting Mac-instance. std::string data = "some_data_for_mac"; auto compute_mac_result = mac->ComputeMac(data); EXPECT_TRUE(compute_mac_result.ok()) << compute_mac_result.status(); std::string mac_value = compute_mac_result.value(); std::string prefix = CryptoFormat::GetOutputPrefix(KeyInfoFromKey(keyset.key(2))).value(); EXPECT_PRED_FORMAT2(testing::IsSubstring, prefix, mac_value); util::Status status = mac->VerifyMac(mac_value, data); EXPECT_TRUE(status.ok()) << status; status = mac->VerifyMac(mac_value, "bad data for mac"); EXPECT_FALSE(status.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, status.code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "verification failed", std::string(status.message())); status = mac->VerifyMac("some bad mac value", data); EXPECT_FALSE(status.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, status.code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "verification failed", std::string(status.message())); // Create raw MAC value with 2nd key, and verify with Mac-instance. auto raw_mac = std::move(key_manager->GetPrimitive(keyset.key(1).key_data()).value()); std::string raw_mac_value = raw_mac->ComputeMac(data).value(); status = mac->VerifyMac(raw_mac_value, data); EXPECT_TRUE(status.ok()) << status; } // TINK-PENDING-REMOVAL-IN-3.0.0-END // NOLINTEND(whitespace/line_length) } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/mac_key.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_MAC_KEY_H_ #define TINK_MAC_MAC_KEY_H_ #include #include "absl/strings/string_view.h" #include "tink/key.h" #include "tink/mac/mac_parameters.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Represents a function to compute/verify a message authentication code (MAC). class MacKey : public Key { public: // Returns the bytes prefixed to every MAC tag generated by this key. // // In order to make key rotation more efficient, Tink allows every MAC key to // have an associated tag output prefix. When verifying a tag, only keys with // a matching prefix have to be tried. // // See https://developers.google.com/tink/wire-format#tink_output_prefix for // more background information on Tink output prefixes. virtual absl::string_view GetOutputPrefix() const = 0; const MacParameters& GetParameters() const override = 0; bool operator==(const Key& other) const override = 0; }; } // namespace tink } // namespace crypto #endif // TINK_MAC_MAC_KEY_H_ ================================================ FILE: cc/mac/mac_key_templates.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/mac/mac_key_templates.h" #include "proto/aes_cmac.pb.h" #include "proto/common.pb.h" #include "proto/hmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using google::crypto::tink::AesCmacKeyFormat; using google::crypto::tink::HashType; using google::crypto::tink::HmacKeyFormat; using google::crypto::tink::KeyTemplate; using google::crypto::tink::OutputPrefixType; KeyTemplate* NewHmacKeyTemplate(int key_size_in_bytes, int tag_size_in_bytes, HashType hash_type) { KeyTemplate* key_template = new KeyTemplate; key_template->set_type_url("type.googleapis.com/google.crypto.tink.HmacKey"); key_template->set_output_prefix_type(OutputPrefixType::TINK); HmacKeyFormat key_format; key_format.set_key_size(key_size_in_bytes); key_format.mutable_params()->set_tag_size(tag_size_in_bytes); key_format.mutable_params()->set_hash(hash_type); key_format.SerializeToString(key_template->mutable_value()); return key_template; } KeyTemplate* NewAesCmacKeyTemplate(int key_size_in_bytes, int tag_size_in_bytes) { KeyTemplate* key_template = new KeyTemplate; key_template->set_type_url( "type.googleapis.com/google.crypto.tink.AesCmacKey"); key_template->set_output_prefix_type(OutputPrefixType::TINK); AesCmacKeyFormat key_format; key_format.set_key_size(key_size_in_bytes); key_format.mutable_params()->set_tag_size(tag_size_in_bytes); key_format.SerializeToString(key_template->mutable_value()); return key_template; } } // anonymous namespace // static const KeyTemplate& MacKeyTemplates::HmacSha256HalfSizeTag() { static const KeyTemplate* key_template = NewHmacKeyTemplate(/* key_size_in_bytes= */ 32, /* tag_size_in_bytes= */ 16, HashType::SHA256); return *key_template; } // static const KeyTemplate& MacKeyTemplates::HmacSha256() { static const KeyTemplate* key_template = NewHmacKeyTemplate(/* key_size_in_bytes= */ 32, /* tag_size_in_bytes= */ 32, HashType::SHA256); return *key_template; } // static const KeyTemplate& MacKeyTemplates::HmacSha512HalfSizeTag() { static const KeyTemplate* key_template = NewHmacKeyTemplate(/* key_size_in_bytes= */ 64, /* tag_size_in_bytes= */ 32, HashType::SHA512); return *key_template; } // static const KeyTemplate& MacKeyTemplates::HmacSha512() { static const KeyTemplate* key_template = NewHmacKeyTemplate(/* key_size_in_bytes= */ 64, /* tag_size_in_bytes= */ 64, HashType::SHA512); return *key_template; } // static const KeyTemplate& MacKeyTemplates::AesCmac() { static const KeyTemplate* key_template = NewAesCmacKeyTemplate( /* key_size_in_bytes= */ 32, /* tag_size_in_bytes= */ 16); return *key_template; } } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/mac_key_templates.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_MAC_KEY_TEMPLATES_H_ #define TINK_MAC_MAC_KEY_TEMPLATES_H_ #include "proto/tink.pb.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Pre-generated KeyTemplate for Mac key types. One can use these templates // to generate a new KeysetHandle object with fresh keys. // To generate a new keyset that contains a single HmacKey, one can do: // // auto status = MacConfig::Register(); // if (!status.ok()) { /* fail with error */ } // auto handle_result = // KeysetHandle::GenerateNew(MacKeyTemplates::HmacSha256HalfSizeTag()); // if (!handle_result.ok()) { /* fail with error */ } // auto keyset_handle = std::move(handle_result.value()); class MacKeyTemplates { public: // Returns a KeyTemplate that generates new instances of HmacKey // with the following parameters: // - key size: 32 bytes // - tag size: 16 bytes // - hash function: SHA256 // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& HmacSha256HalfSizeTag(); // Returns a KeyTemplate that generates new instances of HmacKey // with the following parameters: // - key size: 32 bytes // - tag size: 32 bytes // - hash function: SHA256 // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& HmacSha256(); // Returns a KeyTemplate that generates new instances of HmacKey // with the following parameters: // - key size: 64 bytes // - tag size: 32 bytes // - hash function: SHA512 // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& HmacSha512HalfSizeTag(); // Returns a KeyTemplate that generates new instances of HmacKey // with the following parameters: // - key size: 64 bytes // - tag size: 64 bytes // - hash function: SHA512 // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& HmacSha512(); // Returns a KeyTemplate that generates new instances of AesCmacKey // with the following parameters: // - key size: 32 bytes // - tag size: 16 bytes // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& AesCmac(); }; } // namespace tink } // namespace crypto #endif // TINK_MAC_MAC_KEY_TEMPLATES_H_ ================================================ FILE: cc/mac/mac_key_templates_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/mac_key_templates.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/core/key_manager_impl.h" #include "tink/mac.h" #include "tink/mac/aes_cmac_key_manager.h" #include "tink/mac/hmac_key_manager.h" #include "tink/util/test_matchers.h" #include "proto/aes_cmac.pb.h" #include "proto/common.pb.h" #include "proto/hmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::google::crypto::tink::AesCmacKeyFormat; using ::google::crypto::tink::HashType; using ::google::crypto::tink::HmacKeyFormat; using ::google::crypto::tink::KeyTemplate; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::Ref; TEST(MacKeyTemplatesTest, testHmacKeyTemplates) { std::string type_url = "type.googleapis.com/google.crypto.tink.HmacKey"; { // Test Hmac128BittagSha256(). // Check that returned template is correct. const KeyTemplate& key_template = MacKeyTemplates::HmacSha256HalfSizeTag(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); HmacKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(32, key_format.key_size()); EXPECT_EQ(16, key_format.params().tag_size()); EXPECT_EQ(HashType::SHA256, key_format.params().hash()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = MacKeyTemplates::HmacSha256HalfSizeTag(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. HmacKeyManager key_type_manager; auto key_manager = internal::MakeKeyManager(&key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_format); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } { // Test Hmac256BittagSha256(). // Check that returned template is correct. const KeyTemplate& key_template = MacKeyTemplates::HmacSha256(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); HmacKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(32, key_format.key_size()); EXPECT_EQ(32, key_format.params().tag_size()); EXPECT_EQ(HashType::SHA256, key_format.params().hash()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = MacKeyTemplates::HmacSha256(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. HmacKeyManager key_type_manager; auto key_manager = internal::MakeKeyManager(&key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_format); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } { // Test Hmac256BittagSha512(). // Check that returned template is correct. const KeyTemplate& key_template = MacKeyTemplates::HmacSha512HalfSizeTag(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); HmacKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(64, key_format.key_size()); EXPECT_EQ(32, key_format.params().tag_size()); EXPECT_EQ(HashType::SHA512, key_format.params().hash()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = MacKeyTemplates::HmacSha512HalfSizeTag(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. HmacKeyManager key_type_manager; auto key_manager = internal::MakeKeyManager(&key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_format); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } { // Test Hmac512BittagSha512(). // Check that returned template is correct. const KeyTemplate& key_template = MacKeyTemplates::HmacSha512(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); HmacKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(64, key_format.key_size()); EXPECT_EQ(64, key_format.params().tag_size()); EXPECT_EQ(HashType::SHA512, key_format.params().hash()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = MacKeyTemplates::HmacSha512(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. HmacKeyManager key_type_manager; auto key_manager = internal::MakeKeyManager(&key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_format); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } } TEST(AesCmac, Basics) { EXPECT_THAT(MacKeyTemplates::AesCmac().type_url(), Eq("type.googleapis.com/google.crypto.tink.AesCmacKey")); EXPECT_THAT(MacKeyTemplates::AesCmac().type_url(), Eq(AesCmacKeyManager().get_key_type())); } TEST(AesCmac, OutputPrefixType) { EXPECT_THAT(MacKeyTemplates::AesCmac().output_prefix_type(), Eq(OutputPrefixType::TINK)); } TEST(AesCmac, MultipleCallsSameReference) { EXPECT_THAT(MacKeyTemplates::AesCmac(), Ref(MacKeyTemplates::AesCmac())); } TEST(AesCmac, WorksWithKeyTypeManager) { AesCmacKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(MacKeyTemplates::AesCmac().value())); EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(AesCmac, CheckValues) { AesCmacKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(MacKeyTemplates::AesCmac().value())); EXPECT_THAT(key_format.key_size(), Eq(32)); EXPECT_THAT(key_format.params().tag_size(), Eq(16)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/mac_parameters.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_MAC_PARAMETERS_H_ #define TINK_MAC_MAC_PARAMETERS_H_ #include "tink/parameters.h" namespace crypto { namespace tink { // `MacKey` description without the randomly chosen key material. class MacParameters : public Parameters {}; } // namespace tink } // namespace crypto #endif // TINK_MAC_MAC_PARAMETERS_H_ ================================================ FILE: cc/mac/mac_wrapper.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/mac/mac_wrapper.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/crypto_format.h" #include "tink/internal/monitoring_util.h" #include "tink/internal/registry_impl.h" #include "tink/internal/util.h" #include "tink/mac.h" #include "tink/monitoring/monitoring.h" #include "tink/primitive_set.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using google::crypto::tink::OutputPrefixType; namespace { constexpr absl::string_view kPrimitive = "mac"; constexpr absl::string_view kComputeApi = "compute"; constexpr absl::string_view kVerifyApi = "verify"; class MacSetWrapper : public Mac { public: explicit MacSetWrapper( std::unique_ptr> mac_set, std::unique_ptr monitoring_compute_client = nullptr, std::unique_ptr monitoring_verify_client = nullptr) : mac_set_(std::move(mac_set)), monitoring_compute_client_(std::move(monitoring_compute_client)), monitoring_verify_client_(std::move(monitoring_verify_client)) {} crypto::tink::util::StatusOr ComputeMac( absl::string_view data) const override; crypto::tink::util::Status VerifyMac(absl::string_view mac_value, absl::string_view data) const override; ~MacSetWrapper() override = default; private: std::unique_ptr> mac_set_; std::unique_ptr monitoring_compute_client_; std::unique_ptr monitoring_verify_client_; }; util::Status Validate(PrimitiveSet* mac_set) { if (mac_set == nullptr) { return util::Status(absl::StatusCode::kInternal, "mac_set must be non-NULL"); } if (mac_set->get_primary() == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "mac_set has no primary"); } return util::OkStatus(); } util::StatusOr MacSetWrapper::ComputeMac( absl::string_view data) const { // BoringSSL expects a non-null pointer for data, // regardless of whether the size is 0. data = internal::EnsureStringNonNull(data); auto primary = mac_set_->get_primary(); std::string local_data; if (primary->get_output_prefix_type() == OutputPrefixType::LEGACY) { local_data = std::string(data); local_data.push_back(CryptoFormat::kLegacyStartByte); data = local_data; } auto compute_mac_result = primary->get_primitive().ComputeMac(data); if (!compute_mac_result.ok()) { if (monitoring_compute_client_ != nullptr) { monitoring_compute_client_->LogFailure(); } return compute_mac_result.status(); } if (monitoring_compute_client_ != nullptr) { monitoring_compute_client_->Log(mac_set_->get_primary()->get_key_id(), data.size()); } const std::string& key_id = primary->get_identifier(); return key_id + compute_mac_result.value(); } util::Status MacSetWrapper::VerifyMac( absl::string_view mac_value, absl::string_view data) const { data = internal::EnsureStringNonNull(data); mac_value = internal::EnsureStringNonNull(mac_value); if (mac_value.length() > CryptoFormat::kNonRawPrefixSize) { absl::string_view key_id = mac_value.substr(0, CryptoFormat::kNonRawPrefixSize); auto primitives_result = mac_set_->get_primitives(key_id); if (primitives_result.ok()) { absl::string_view raw_mac_value = mac_value.substr(CryptoFormat::kNonRawPrefixSize); for (auto& mac_entry : *(primitives_result.value())) { std::string legacy_data; absl::string_view view_on_data_or_legacy_data = data; if (mac_entry->get_output_prefix_type() == OutputPrefixType::LEGACY) { legacy_data = absl::StrCat(data, std::string("\x00", 1)); view_on_data_or_legacy_data = legacy_data; } Mac& mac = mac_entry->get_primitive(); util::Status status = mac.VerifyMac(raw_mac_value, view_on_data_or_legacy_data); if (status.ok()) { if (monitoring_verify_client_ != nullptr) { monitoring_verify_client_->Log(mac_entry->get_key_id(), data.size()); } return status; } } } } // No matching key succeeded with verification, try all RAW keys. auto raw_primitives_result = mac_set_->get_raw_primitives(); if (raw_primitives_result.ok()) { for (auto& mac_entry : *(raw_primitives_result.value())) { Mac& mac = mac_entry->get_primitive(); util::Status status = mac.VerifyMac(mac_value, data); if (status.ok()) { if (monitoring_verify_client_ != nullptr) { monitoring_verify_client_->Log(mac_entry->get_key_id(), data.size()); } return status; } } } if (monitoring_verify_client_ != nullptr) { monitoring_verify_client_->LogFailure(); } return util::Status(absl::StatusCode::kInvalidArgument, "verification failed"); } } // namespace util::StatusOr> MacWrapper::Wrap( std::unique_ptr> mac_set) const { util::Status status = Validate(mac_set.get()); if (!status.ok()) return status; MonitoringClientFactory* const monitoring_factory = internal::RegistryImpl::GlobalInstance().GetMonitoringClientFactory(); // Monitoring is not enabled. Create a wrapper without monitoring clients. if (monitoring_factory == nullptr) { return {absl::make_unique(std::move(mac_set))}; } util::StatusOr keyset_info = internal::MonitoringKeySetInfoFromPrimitiveSet(*mac_set); if (!keyset_info.ok()) { return keyset_info.status(); } util::StatusOr> monitoring_compute_client = monitoring_factory->New( MonitoringContext(kPrimitive, kComputeApi, *keyset_info)); if (!monitoring_compute_client.ok()) { return monitoring_compute_client.status(); } util::StatusOr> monitoring_verify_client = monitoring_factory->New( MonitoringContext(kPrimitive, kVerifyApi, *keyset_info)); if (!monitoring_verify_client.ok()) { return monitoring_verify_client.status(); } return {absl::make_unique( std::move(mac_set), *std::move(monitoring_compute_client), *std::move(monitoring_verify_client))}; } } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/mac_wrapper.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_MAC_WRAPPER_H_ #define TINK_MAC_MAC_WRAPPER_H_ #include #include "absl/strings/string_view.h" #include "tink/mac.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // Wraps a set of Mac-instances that correspond to a keyset, // and combines them into a single Mac-primitive, that uses the provided // instances, depending on the context: // * Mac::ComputeMac(...) uses the primary instance from the set // * Mac::VerifyMac(...) uses the instance that matches the MAC prefix. class MacWrapper : public PrimitiveWrapper { public: util::StatusOr> Wrap( std::unique_ptr> mac_set) const override; }; } // namespace tink } // namespace crypto #endif // TINK_MAC_MAC_WRAPPER_H_ ================================================ FILE: cc/mac/mac_wrapper_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/mac/mac_wrapper.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_map.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/crypto_format.h" #include "tink/internal/registry_impl.h" #include "tink/mac.h" #include "tink/mac/failing_mac.h" #include "tink/monitoring/monitoring.h" #include "tink/monitoring/monitoring_client_mocks.h" #include "tink/primitive_set.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::DummyMac; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::KeysetInfo; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::OutputPrefixType; using ::testing::_; using ::testing::ByMove; using ::testing::IsNull; using ::testing::NiceMock; using ::testing::Not; using ::testing::NotNull; using ::testing::Return; using ::testing::Test; TEST(MacWrapperTest, WrapNullptr) { auto mac_result = MacWrapper().Wrap(nullptr); EXPECT_FALSE(mac_result.ok()); EXPECT_EQ(absl::StatusCode::kInternal, mac_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "non-NULL", std::string(mac_result.status().message())); } TEST(MacWrapperTest, WrapEmpty) { std::unique_ptr> mac_set(new PrimitiveSet()); auto mac_result = MacWrapper().Wrap(std::move(mac_set)); EXPECT_FALSE(mac_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, mac_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "no primary", std::string(mac_result.status().message())); } TEST(MacWrapperTest, Basic) { KeysetInfo::KeyInfo* key_info; KeysetInfo keyset_info; uint32_t key_id_0 = 1234543; key_info = keyset_info.add_key_info(); key_info->set_output_prefix_type(OutputPrefixType::TINK); key_info->set_key_id(key_id_0); key_info->set_status(KeyStatusType::ENABLED); uint32_t key_id_1 = 726329; key_info = keyset_info.add_key_info(); key_info->set_output_prefix_type(OutputPrefixType::LEGACY); key_info->set_key_id(key_id_1); key_info->set_status(KeyStatusType::ENABLED); uint32_t key_id_2 = 7213743; key_info = keyset_info.add_key_info(); key_info->set_output_prefix_type(OutputPrefixType::TINK); key_info->set_key_id(key_id_2); key_info->set_status(KeyStatusType::ENABLED); std::string mac_name_0 = "mac0"; std::string mac_name_1 = "mac1"; std::string mac_name_2 = "mac2"; std::unique_ptr> mac_set(new PrimitiveSet()); auto entry_result = mac_set->AddPrimitive( absl::make_unique(mac_name_0), keyset_info.key_info(0)); ASSERT_TRUE(entry_result.ok()); entry_result = mac_set->AddPrimitive(absl::make_unique(mac_name_1), keyset_info.key_info(1)); ASSERT_TRUE(entry_result.ok()); entry_result = mac_set->AddPrimitive(absl::make_unique(mac_name_2), keyset_info.key_info(2)); ASSERT_TRUE(entry_result.ok()); // The last key is the primary. ASSERT_THAT(mac_set->set_primary(entry_result.value()), IsOk()); // Wrap mac_set and test the resulting Mac. auto mac_result = MacWrapper().Wrap(std::move(mac_set)); EXPECT_TRUE(mac_result.ok()) << mac_result.status(); std::unique_ptr mac = std::move(mac_result.value()); std::string data = "some_data_for_mac"; auto compute_mac_result = mac->ComputeMac(data); EXPECT_TRUE(compute_mac_result.ok()) << compute_mac_result.status(); std::string mac_value = compute_mac_result.value(); EXPECT_PRED_FORMAT2(testing::IsSubstring, mac_name_2, mac_value); util::Status status = mac->VerifyMac(mac_value, data); EXPECT_TRUE(status.ok()) << status; status = mac->VerifyMac("some bad mac", data); EXPECT_FALSE(status.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, status.code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "verification failed", std::string(status.message())); } TEST(MacWrapperTest, testLegacyAuthentication) { // Prepare a set for the wrapper. KeysetInfo::KeyInfo key_info; uint32_t key_id = 1234543; key_info.set_output_prefix_type(OutputPrefixType::LEGACY); key_info.set_key_id(key_id); key_info.set_status(KeyStatusType::ENABLED); std::string mac_name = "SomeLegacyMac"; std::unique_ptr> mac_set(new PrimitiveSet()); std::unique_ptr mac(new DummyMac(mac_name)); auto entry_result = mac_set->AddPrimitive(std::move(mac), key_info); ASSERT_TRUE(entry_result.ok()); ASSERT_THAT(mac_set->set_primary(entry_result.value()), IsOk()); // Wrap mac_set and test the resulting Mac. auto mac_result = MacWrapper().Wrap(std::move(mac_set)); EXPECT_TRUE(mac_result.ok()) << mac_result.status(); mac = std::move(mac_result.value()); std::string data = "Some data to authenticate"; // Compute and verify MAC via wrapper. auto compute_mac_result = mac->ComputeMac(data); EXPECT_TRUE(compute_mac_result.ok()) << compute_mac_result.status(); std::string mac_value = compute_mac_result.value(); EXPECT_PRED_FORMAT2(testing::IsSubstring, mac_name, mac_value); auto status = mac->VerifyMac(mac_value, data); EXPECT_TRUE(status.ok()) << status; // Try verifying on raw Mac-primitive using original data. std::unique_ptr raw_mac(new DummyMac(mac_name)); // same as in wrapper std::string raw_mac_value = mac_value.substr(CryptoFormat::kNonRawPrefixSize); status = raw_mac->VerifyMac(raw_mac_value, data); EXPECT_FALSE(status.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, status.code()); // Verify on raw Mac-primitive using legacy-formatted data. std::string legacy_data = data; legacy_data.append(1, CryptoFormat::kLegacyStartByte); status = raw_mac->VerifyMac(raw_mac_value, legacy_data); EXPECT_TRUE(status.ok()) << status; } // Produces a mac which starts in the same way as a legacy non-raw signature. class TryBreakLegacyMac : public Mac { public: crypto::tink::util::StatusOr ComputeMac( absl::string_view data) const override { return absl::StrCat(std::string("\x00", 1), "\xff\xff\xff\xff", data); } crypto::tink::util::Status VerifyMac(absl::string_view mac, absl::string_view data) const override { if (mac != ComputeMac(data).value()) { return absl::InvalidArgumentError("Wrong mac"); } return util::OkStatus(); } }; // Checks that a raw tag can be verified after a legacy tag is verified with // the same output prefix. (To prevent regression of b/173013224). TEST(MacWrapperTest, VerifyRawAfterLegacy) { std::unique_ptr> mac_set(new PrimitiveSet()); KeysetInfo::KeyInfo key_info_0; key_info_0.set_output_prefix_type(OutputPrefixType::RAW); key_info_0.set_key_id(1234); key_info_0.set_status(KeyStatusType::ENABLED); ASSERT_THAT( mac_set->AddPrimitive(absl::make_unique(), key_info_0) .status(), IsOk()); KeysetInfo::KeyInfo key_info_1; key_info_1.set_output_prefix_type(OutputPrefixType::LEGACY); key_info_1.set_key_id(0xffffffff); key_info_1.set_status(KeyStatusType::ENABLED); auto entry1 = mac_set->AddPrimitive(absl::make_unique(""), key_info_1); ASSERT_THAT(entry1, IsOk()); ASSERT_THAT(mac_set->set_primary(entry1.value()), IsOk()); // Wrap mac_set and test the resulting Mac. auto wrapped_mac = MacWrapper().Wrap(std::move(mac_set)); EXPECT_THAT(wrapped_mac, IsOk()); std::string data = "some data"; std::string mac_tag = TryBreakLegacyMac().ComputeMac(data).value(); EXPECT_THAT(wrapped_mac.value()->VerifyMac(mac_tag, data), IsOk()); } KeysetInfo::KeyInfo PopulateKeyInfo(uint32_t key_id, OutputPrefixType out_prefix_type, KeyStatusType status) { KeysetInfo::KeyInfo key_info; key_info.set_output_prefix_type(out_prefix_type); key_info.set_key_id(key_id); key_info.set_status(status); return key_info; } // Creates a test keyset info object. KeysetInfo CreateTestKeysetInfo() { KeysetInfo keyset_info; *keyset_info.add_key_info() = PopulateKeyInfo(/*key_id=*/1234543, OutputPrefixType::TINK, /*status=*/KeyStatusType::ENABLED); *keyset_info.add_key_info() = PopulateKeyInfo(/*key_id=*/726329, OutputPrefixType::LEGACY, /*status=*/KeyStatusType::ENABLED); *keyset_info.add_key_info() = PopulateKeyInfo(/*key_id=*/7213743, OutputPrefixType::TINK, /*status=*/KeyStatusType::ENABLED); return keyset_info; } // Tests for the monitoring behavior. class MacSetWrapperWithMonitoringTest : public Test { protected: // Perform some common initialization: reset the global registry, set expected // calls for the mock monitoring factory and the returned clients. void SetUp() override { Registry::Reset(); // Setup mocks for catching Monitoring calls. auto monitoring_client_factory = absl::make_unique(); auto compute_monitoring_client = absl::make_unique>(); compute_monitoring_client_ = compute_monitoring_client.get(); auto verify_monitoring_client = absl::make_unique>(); verify_monitoring_client_ = verify_monitoring_client.get(); // Monitoring tests expect that the client factory will create the // corresponding MockMonitoringClients. EXPECT_CALL(*monitoring_client_factory, New(_)) .WillOnce( Return(ByMove(util::StatusOr>( std::move(compute_monitoring_client))))) .WillOnce( Return(ByMove(util::StatusOr>( std::move(verify_monitoring_client))))); ASSERT_THAT(internal::RegistryImpl::GlobalInstance() .RegisterMonitoringClientFactory( std::move(monitoring_client_factory)), IsOk()); ASSERT_THAT( internal::RegistryImpl::GlobalInstance().GetMonitoringClientFactory(), Not(IsNull())); } // Cleanup the registry to avoid mock leaks. ~MacSetWrapperWithMonitoringTest() override { Registry::Reset(); } MockMonitoringClient* compute_monitoring_client_; MockMonitoringClient* verify_monitoring_client_; }; // Tests that successful ComputeMac operations are logged. TEST_F(MacSetWrapperWithMonitoringTest, WrapKeysetWithMonitoringComputeSuccess) { // Create a primitive set and fill it with some entries KeysetInfo keyset_info = CreateTestKeysetInfo(); const absl::flat_hash_map annotations = { {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}}; auto mac_primitive_set = absl::make_unique>(annotations); ASSERT_THAT(mac_primitive_set ->AddPrimitive(absl::make_unique("mac0"), keyset_info.key_info(0)) .status(), IsOk()); ASSERT_THAT(mac_primitive_set ->AddPrimitive(absl::make_unique("mac1"), keyset_info.key_info(1)) .status(), IsOk()); // Set the last as primary. util::StatusOr::Entry*> last = mac_primitive_set->AddPrimitive(absl::make_unique("mac2"), keyset_info.key_info(2)); ASSERT_THAT(last.status(), IsOk()); ASSERT_THAT(mac_primitive_set->set_primary(*last), IsOk()); // Record the ID of the primary key. const uint32_t primary_key_id = keyset_info.key_info(2).key_id(); // Create a MAC and compute an authentication tag util::StatusOr> mac = MacWrapper().Wrap(std::move(mac_primitive_set)); ASSERT_THAT(mac, IsOkAndHolds(NotNull())); constexpr absl::string_view message = "This is some message!"; // Check that calling ComputeMac triggers a Log() call. EXPECT_CALL(*compute_monitoring_client_, Log(primary_key_id, message.size())); EXPECT_THAT((*mac)->ComputeMac(message).status(), IsOk()); } // Test that successful VerifyMac operations are logged. TEST_F(MacSetWrapperWithMonitoringTest, WrapKeysetWithMonitoringVerifySuccess) { // Create a primitive set and fill it with some entries KeysetInfo keyset_info = CreateTestKeysetInfo(); const absl::flat_hash_map annotations = { {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}}; auto mac_primitive_set = absl::make_unique>(annotations); ASSERT_THAT(mac_primitive_set ->AddPrimitive(absl::make_unique("mac0"), keyset_info.key_info(0)) .status(), IsOk()); ASSERT_THAT(mac_primitive_set ->AddPrimitive(absl::make_unique("mac1"), keyset_info.key_info(1)) .status(), IsOk()); // Set the last as primary. util::StatusOr::Entry*> last = mac_primitive_set->AddPrimitive(absl::make_unique("mac2"), keyset_info.key_info(2)); ASSERT_THAT(last.status(), IsOk()); ASSERT_THAT(mac_primitive_set->set_primary(*last), IsOk()); // Record the ID of the primary key. const uint32_t primary_key_id = keyset_info.key_info(2).key_id(); // Create a MAC, compute a Mac and verify it. util::StatusOr> mac = MacWrapper().Wrap(std::move(mac_primitive_set)); ASSERT_THAT(mac, IsOkAndHolds(NotNull())); constexpr absl::string_view message = "This is some message!"; // Check that calling VerifyMac triggers a Log() call. util::StatusOr tag = (*mac)->ComputeMac(message); EXPECT_THAT(tag.status(), IsOk()); // In the log expect the size of the message without the non-raw prefix. EXPECT_CALL(*verify_monitoring_client_, Log(primary_key_id, message.size())); EXPECT_THAT((*mac)->VerifyMac(*tag, message), IsOk()); } TEST_F(MacSetWrapperWithMonitoringTest, WrapKeysetWithMonitoringComputeFailures) { // Create a primitive set and fill it with some entries. KeysetInfo keyset_info = CreateTestKeysetInfo(); const absl::flat_hash_map annotations = { {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}}; auto mac_primitive_set = absl::make_unique>(annotations); ASSERT_THAT(mac_primitive_set ->AddPrimitive(CreateAlwaysFailingMac("mac "), keyset_info.key_info(0)) .status(), IsOk()); ASSERT_THAT(mac_primitive_set ->AddPrimitive(CreateAlwaysFailingMac("mac "), keyset_info.key_info(1)) .status(), IsOk()); // Set the last as primary. util::StatusOr::Entry*> last = mac_primitive_set->AddPrimitive(CreateAlwaysFailingMac("mac "), keyset_info.key_info(2)); ASSERT_THAT(last.status(), IsOk()); ASSERT_THAT(mac_primitive_set->set_primary(*last), IsOk()); // Create a MAC and compute a tag. util::StatusOr> mac = MacWrapper().Wrap(std::move(mac_primitive_set)); ASSERT_THAT(mac, IsOkAndHolds(NotNull())); constexpr absl::string_view message = "This is some message!"; // Check that calling ComputeMac triggers a LogFailure() call. EXPECT_CALL(*compute_monitoring_client_, LogFailure()); EXPECT_THAT((*mac)->ComputeMac(message).status(), StatusIs(absl::StatusCode::kInternal)); } // Test that monitoring logs verify failures correctly. TEST_F(MacSetWrapperWithMonitoringTest, WrapKeysetWithMonitoringVerifyFailures) { // Create a primitive set and fill it with some entries. KeysetInfo keyset_info = CreateTestKeysetInfo(); const absl::flat_hash_map annotations = { {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}}; auto mac_primitive_set = absl::make_unique>(annotations); ASSERT_THAT(mac_primitive_set ->AddPrimitive(CreateAlwaysFailingMac("mac "), keyset_info.key_info(0)) .status(), IsOk()); ASSERT_THAT(mac_primitive_set ->AddPrimitive(CreateAlwaysFailingMac("mac "), keyset_info.key_info(1)) .status(), IsOk()); // Set the last as primary. util::StatusOr::Entry*> last = mac_primitive_set->AddPrimitive(CreateAlwaysFailingMac("mac "), keyset_info.key_info(2)); ASSERT_THAT(last.status(), IsOk()); ASSERT_THAT(mac_primitive_set->set_primary(*last), IsOk()); // Create a MAC and verify a tag. util::StatusOr> mac = MacWrapper().Wrap(std::move(mac_primitive_set)); ASSERT_THAT(mac, IsOkAndHolds(NotNull())); constexpr absl::string_view message = "This is some message!"; constexpr absl::string_view tag = "some invalid tag!"; // Check that calling VerifyMac triggers a LogFailure() call. EXPECT_CALL(*verify_monitoring_client_, LogFailure()); EXPECT_THAT((*mac)->VerifyMac(tag, message), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/mac/subtle/BUILD.bazel ================================================ licenses(["notice"]) ================================================ FILE: cc/mac/subtle/CMakeLists.txt ================================================ ================================================ FILE: cc/mac.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_H_ #define TINK_MAC_H_ #include #include "absl/strings/string_view.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Interface for MACs (Message Authentication Codes). // This interface should be used for authentication only, and not for other // purposes (e.g., it should not be used to generate pseudorandom bytes). class Mac { public: // Computes and returns the message authentication code (MAC) for 'data'. virtual crypto::tink::util::StatusOr ComputeMac( absl::string_view data) const = 0; // Verifies if 'mac' is a correct authentication code (MAC) for 'data'. // Returns Status::OK if 'mac' is correct, and a non-OK-Status otherwise. virtual crypto::tink::util::Status VerifyMac( absl::string_view mac_value, absl::string_view data) const = 0; virtual ~Mac() = default; }; } // namespace tink } // namespace crypto #endif // TINK_MAC_H_ ================================================ FILE: cc/mac_config.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_CONFIG_H_ #define TINK_MAC_CONFIG_H_ #include "tink/mac/mac_config.h" // IWYU pragma: export #endif // TINK_MAC_CONFIG_H_ ================================================ FILE: cc/mac_factory.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_FACTORY_H_ #define TINK_MAC_FACTORY_H_ #include "tink/mac/mac_factory.h" // IWYU pragma: export #endif // TINK_MAC_FACTORY_H_ ================================================ FILE: cc/mac_key_templates.h ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MAC_KEY_TEMPLATES_H_ #define TINK_MAC_KEY_TEMPLATES_H_ #include "tink/mac/mac_key_templates.h" // IWYU pragma: export #endif // TINK_MAC_KEY_TEMPLATES_H_ ================================================ FILE: cc/monitoring/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "monitoring", hdrs = ["monitoring.h"], include_prefix = "tink/monitoring", deps = [ "//:key_status", "//internal:key_status_util", "//util:statusor", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "monitoring_client_mocks", testonly = 1, hdrs = ["monitoring_client_mocks.h"], include_prefix = "tink/monitoring", deps = [ ":monitoring", "//util:statusor", "@com_google_googletest//:gtest", ], ) ================================================ FILE: cc/monitoring/CMakeLists.txt ================================================ tink_module(monitoring) tink_cc_library( NAME monitoring SRCS monitoring.h DEPS absl::flat_hash_map absl::string_view tink::core::key_status tink::internal::key_status_util tink::util::statusor ) tink_cc_library( NAME monitoring_client_mocks SRCS monitoring_client_mocks.h DEPS tink::monitoring::monitoring gmock tink::util::statusor TESTONLY ) ================================================ FILE: cc/monitoring/monitoring.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MONITORING_MONITORING_H_ #define TINK_MONITORING_MONITORING_H_ #include #include #include #include #include "absl/container/flat_hash_map.h" #include "absl/strings/string_view.h" #include "tink/internal/key_status_util.h" #include "tink/key_status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Immutable representation of a KeySet in a certain point in time for the // purpose of monitoring operations involving cryptographic keys. class MonitoringKeySetInfo { public: // Description about each entry of the KeySet. class Entry { public: // Constructs a new KeySet entry with a given `status`, `key_id`, // `key_type`, and `key_prefix`. Entry(KeyStatus status, uint32_t key_id, absl::string_view key_type, absl::string_view key_prefix) : status_(status), key_id_(key_id), key_type_(key_type), key_prefix_(key_prefix) {} // Returns the status of this entry. std::string GetStatus() const { return internal::ToKeyStatusName(status_); } // Returns the ID of the entry within the keyset. uint32_t GetKeyId() const { return key_id_; } // Returns the key type. std::string GetKeyType() const { return key_type_; } // Returns the key prefix. std::string GetKeyPrefix() const { return key_prefix_; } private: const KeyStatus status_; // Identifies a key within a keyset. const uint32_t key_id_; // This field stores the key type. const std::string key_type_; // Stores the key output prefix. const std::string key_prefix_; }; // Constructs a MonitoringKeySetInfo object with the given // `keyset_annotations`, `keyset_entries` and primary key ID `primary_key_id`. MonitoringKeySetInfo( const absl::flat_hash_map& keyset_annotations, const std::vector& keyset_entries, uint32_t primary_key_id) : keyset_annotations_(keyset_annotations), keyset_entries_(keyset_entries), primary_key_id_(primary_key_id) {} // Returns a const reference to the annotations of this keyset. const absl::flat_hash_map& GetAnnotations() const { return keyset_annotations_; } // Returns a const reference to the array of entries for this keyset. const std::vector& GetEntries() const { return keyset_entries_; } // Returns the ID of the primary key in this keyset. uint32_t GetPrimaryKeyId() const { return primary_key_id_; } private: // Annotations of this keyset in the form 'key' -> 'value'. const absl::flat_hash_map keyset_annotations_; const std::vector keyset_entries_; const uint32_t primary_key_id_; }; // Defines a context for monitoring events, wich includes the primitive and API // used, and info on the keyset. class MonitoringContext { public: // Construct a new context for the given `primitive`, `api_function` and // `keyset_info`. MonitoringContext(absl::string_view primitive, absl::string_view api_function, const MonitoringKeySetInfo& keyset_info) : primitive_(primitive), api_function_(api_function), keyset_info_(keyset_info) {} // Returns the primitive. std::string GetPrimitive() const { return primitive_; } // Returns the API function. std::string GetApi() const { return api_function_; } // Returns a constant reference to the keyset info. const MonitoringKeySetInfo& GetKeySetInfo() const { return keyset_info_; } private: const std::string primitive_; const std::string api_function_; const MonitoringKeySetInfo keyset_info_; }; // Interface for a monitoring client which can be registered with Tink. A // monitoring client getis informed by Tink about certain events happening // during cryptographic operations. class MonitoringClient { public: virtual ~MonitoringClient() = default; // Logs a successful use of `key_id` on an input of `num_bytes_as_input`. Tink // primitive wrappers call this method when they successfully used a key to // carry out a primitive method, e.g. Aead::Encrypt(). As a consequence, // subclasses of MonitoringClient should be mindful on the amount of work // performed by this method, as this will be called on each cryptographic // operation. Implementations of MonitoringClient are responsible to add // context to identify, e.g., the primitive and the API function. virtual void Log(uint32_t key_id, int64_t num_bytes_as_input) = 0; // Logs a failure. Tink calls this method when a cryptographic operation // failed, e.g. no key could be found to decrypt a ciphertext. In this // case the failure is not associated with a specific key, therefore this // method has no arguments. The MonitoringClient implementation is responsible // to add context to identify where the failure comes from. virtual void LogFailure() = 0; }; // Interface for a factory class that creates monitoring clients. // // Implementations of this interface should be thread-safe. class MonitoringClientFactory { public: virtual ~MonitoringClientFactory() = default; // Create a new monitoring client that logs events related to the given // `context`. virtual crypto::tink::util::StatusOr> New( const MonitoringContext& context) = 0; }; } // namespace tink } // namespace crypto #endif // TINK_MONITORING_MONITORING_H_ ================================================ FILE: cc/monitoring/monitoring_client_mocks.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_MONITORING_MONITORING_CLIENT_MOCKS_H_ #define TINK_MONITORING_MONITORING_CLIENT_MOCKS_H_ #include #include #include "gmock/gmock.h" #include "tink/monitoring/monitoring.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Mock MonitoringClientFactory class. class MockMonitoringClientFactory : public MonitoringClientFactory { public: MOCK_METHOD(util::StatusOr>, New, (const MonitoringContext& context), (override)); }; // Mock MonitoringClient class. class MockMonitoringClient : public MonitoringClient { public: MOCK_METHOD(void, Log, (uint32_t key_id, int64_t num_bytes_as_input), (override)); MOCK_METHOD(void, LogFailure, (), (override)); }; } // namespace tink } // namespace crypto #endif // TINK_MONITORING_MONITORING_CLIENT_MOCKS_H_ ================================================ FILE: cc/output_stream.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_OUTPUT_STREAM_H_ #define TINK_OUTPUT_STREAM_H_ #include #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Abstract interface similar to an output stream, and to // Protocol Buffers' google::protobuf::io::ZeroCopyOutputStream. class OutputStream { public: OutputStream() = default; virtual ~OutputStream() = default; // Obtains a buffer into which data can be written. Any data written // into this buffer will eventually (maybe instantly, maybe later on) // be written to the output. // // Preconditions: // * "data" is not NULL. // // Postconditions: // * If the returned status is not OK, then an error occurred. // All errors are permanent. // * Otherwise, the returned value is the actual number of bytes // in the buffer and "data" points to the buffer. // * Ownership of this buffer remains with the stream, and the buffer // remains valid only until some other non-const method of the stream // is called or the stream is destroyed. // * Any data which the caller stores in this buffer will eventually be // written to the output (unless BackUp() is called). // * It is legal for the returned buffer to have zero size, as long // as repeatedly calling Next() eventually yields a buffer with non-zero // size. virtual crypto::tink::util::StatusOr Next(void** data) = 0; // Backs up a number of bytes, so that the end of the last buffer returned // by Next() is not actually written. This is needed when you finish // writing all the data you want to write, but the last buffer was bigger // than you needed. You don't want to write a bunch of garbage after the // end of your data, so you use BackUp() to back up. // // Preconditions: // * The last call to Next() must have returned status OK. // If there was no Next()-call yet, or the last one failed, // BackUp()-call is ignored. // * count must be less than or equal to the size of the last buffer // returned by Next(). Non-positive count is ignored (no action on this // stream), and count larger than the size of the last buffer is treated // as equal to the size of the last buffer. // * The caller must not have written anything to the last "count" bytes // of that buffer. // // Postconditions: // * The last "count" bytes of the last buffer returned by Next() will be // ignored. // * Repeated calls to BackUp() accumulate: // BackUp(a); // Backup(b); // is equivalent to // Backup(c); // with c = max(0, a) + max(0, b). // * The actual result of BackUp()-call can be verified via Position(). virtual void BackUp(int count) = 0; // Closes this output stream. It flushes all the data from the last buffer // returned by Next(), (except the ones backed up via BackUp(), if any) // Returns a non-OK status if some error occurred. // // Preconditions: // * The stream is not closed yet, // * The last call to Next() did not return an error. // // Postconditions: // * Writing to the stream is not possible any more, and all calls // to non-const methods will fail. virtual crypto::tink::util::Status Close() = 0; // Returns the total number of bytes written since this object was created. // Preconditions: // * The most recent call to Next() (if any) was successful, or the stream // was successfully closed. // // Postconditions: // * The returned position includes the bytes from the most recent // successful call to Next(), excluding the ones that were backed up // via BackUp() (if any). // * If the last call to Next() ended with a failure, -1 is returned; virtual int64_t Position() const = 0; }; } // namespace tink } // namespace crypto #endif // TINK_OUTPUT_STREAM_H_ ================================================ FILE: cc/output_stream_with_result.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_OUTPUT_STREAM_WITH_RESULT_H_ #define TINK_OUTPUT_STREAM_WITH_RESULT_H_ #include #include "absl/status/status.h" #include "tink/output_stream.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // TODO(tholenst): Forward declare ExtractStatus function, // as discussed in cl/269918867. namespace internal { // Closes the OutputStream and returns the status, // for when ResultType is StatusOr template auto ExtractStatus(const ResultType& result) -> decltype(std::declval().status()) { return result.status(); } // Closes the OutputStream and returns the status, // for when ResultType is Status template auto ExtractStatus(ResultType result) -> typename std::enable_if::value, util::Status>::type { return result; } } // namespace internal // An abstract OutputStream subclass that acts as a sink for data and returns a // result after the stream has been closed. // The result is only available if the stream was able to close with an ok // status. Otherwise, the status of the GetResult call will be the same status // as the Close call had. If Close is successful, GetResult is guaranteed to // return a valid result. // The return type of GetResult will be StatusOr, except for T == Status, in // which case the return type is Status. template class OutputStreamWithResult : public OutputStream { public: OutputStreamWithResult() : closed_(false) {} ~OutputStreamWithResult() override = default; // The return type is StatusOr if T != Status, and Status otherwise. using ResultType = typename std::conditional::value, util::Status, util::StatusOr>::type; // Get the result associated with this OutputStream. Can only be called on // closed streams, and will otherwise fail with FAILED_PRECONDITION as error // code. // If Close() returned an ok status, this method is guaranteed to contain a // valid result. // The return type is StatusOr if T != Status, and Status otherwise. ResultType GetResult() { if (!closed_) { return util::Status(absl::StatusCode::kFailedPrecondition, "Stream is not closed"); } return result_; } // Close the stream and return the computed result. Equivalent to calling // Close() and GetResult() if Close() returned an OK status. // The return type is StatusOr if T != Status, and Status otherwise. ResultType CloseAndGetResult() { util::Status closing_status = Close(); if (!closing_status.ok()) { return closing_status; } return GetResult(); } // Closes the OutputStream. util::Status Close() final { if (closed_) { return util::Status(absl::StatusCode::kFailedPrecondition, "Stream closed"); } result_ = CloseStreamAndComputeResult(); closed_ = true; return internal::ExtractStatus(result_); } // Getting the next OutputStream buffer. See OutputStream for detailed // description. crypto::tink::util::StatusOr Next(void** data) final { if (closed_) { return util::Status(absl::StatusCode::kFailedPrecondition, "Write on closed Stream"); } return NextBuffer(data); } protected: // Compute the result for this OutputStream. Safe for thread safety problems, // this method will only be called once. // The return type is StatusOr if T != Status, and Status otherwise. virtual ResultType CloseStreamAndComputeResult() = 0; // Getting the next OutputStream buffer. See OutputStream for detailed // description. virtual util::StatusOr NextBuffer(void** data) = 0; private: bool closed_; ResultType result_; }; } // namespace tink } // namespace crypto #endif // TINK_OUTPUT_STREAM_WITH_RESULT_H_ ================================================ FILE: cc/parameters.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_PARAMETERS_H_ #define TINK_PARAMETERS_H_ namespace crypto { namespace tink { // Represents a cryptographic function without the actual key material. // // In Tink, a `Key` represents a set of cryptographic functions. A `Parameters` // object contains all the information about the function that is not randomly // chosen with each instance. class Parameters { public: Parameters() = default; // Copyable and movable. Parameters(const Parameters& other) = default; Parameters& operator=(const Parameters& other) = default; Parameters(Parameters&& other) = default; Parameters& operator=(Parameters&& other) = default; // Returns true if a key created with these parameters has to have a // particular id when it is in a keyset. Otherwise, returns false. // // In Tink, certain keys change their behavior depending on the key id (e.g., // an `Aead` object may add a prefix containing the big endian encoding of the // key id to the ciphertext). In this case, such a key should require a unique // id in `Key::GetIdRequirement()` and return true. virtual bool HasIdRequirement() const = 0; // Returns true if all `Parameters` fields have identical values. Otherwise, // returns false. virtual bool operator==(const Parameters& other) const = 0; bool operator!=(const Parameters& other) const { return !(*this == other); } virtual ~Parameters() = default; }; } // namespace tink } // namespace crypto #endif // TINK_PARAMETERS_H_ ================================================ FILE: cc/partial_key_access.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_PARTIAL_KEY_ACCESS_H_ #define TINK_PARTIAL_KEY_ACCESS_H_ #include "tink/partial_key_access_token.h" namespace crypto { namespace tink { // Returns a `PartialKeyAccessToken`. // // Accessing parts of keys can produce unexpected incompatibilities: // https://developers.google.com/tink/design/access_control#accessing_partial_keys // // This function can be used to access partial key material. Within Google, // access to this function is restricted by the build system. Outside of Google, // users can search their codebase for `GetPartialKeyAccess()` to find // instances where it is used. inline PartialKeyAccessToken GetPartialKeyAccess() { return PartialKeyAccessToken(); } } // namespace tink } // namespace crypto #endif // TINK_PARTIAL_KEY_ACCESS_H_ ================================================ FILE: cc/partial_key_access_token.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_PARTIAL_KEY_ACCESS_TOKEN_H_ #define TINK_PARTIAL_KEY_ACCESS_TOKEN_H_ namespace crypto { namespace tink { class PartialKeyAccessToken { public: // Copyable and movable. PartialKeyAccessToken(const PartialKeyAccessToken& other) = default; PartialKeyAccessToken& operator=(const PartialKeyAccessToken& other) = default; PartialKeyAccessToken(PartialKeyAccessToken&& other) = default; PartialKeyAccessToken& operator=(PartialKeyAccessToken&& other) = default; private: // `GetPartialKeyAccess()` requires access to the constructor. friend PartialKeyAccessToken GetPartialKeyAccess(); PartialKeyAccessToken() = default; }; } // namespace tink } // namespace crypto #endif // TINK_PARTIAL_KEY_ACCESS_TOKEN_H_ ================================================ FILE: cc/prf/BUILD.bazel ================================================ package( default_visibility = ["//:__subpackages__"], ) licenses(["notice"]) cc_library( name = "hkdf_prf_key_manager", hdrs = ["hkdf_prf_key_manager.h"], include_prefix = "tink/prf", deps = [ ":prf_set", "//:core/key_type_manager", "//:core/template_util", "//:input_stream", "//proto:common_cc_proto", "//proto:hkdf_prf_cc_proto", "//proto:tink_cc_proto", "//subtle", "//subtle/prf:hkdf_streaming_prf", "//subtle/prf:prf_set_util", "//subtle/prf:streaming_prf", "//util:constants", "//util:enums", "//util:input_stream_util", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "prf_config", srcs = ["prf_config.cc"], hdrs = ["prf_config.h"], include_prefix = "tink/prf", visibility = ["//visibility:public"], deps = [ ":aes_cmac_prf_key_manager", ":hkdf_prf_key_manager", ":hmac_prf_key_manager", ":prf_set_wrapper", "//:registry", "//config:tink_fips", "//proto:tink_cc_proto", "//util:status", "@com_google_absl//absl/memory", ], ) cc_library( name = "prf_key_templates", srcs = ["prf_key_templates.cc"], hdrs = ["prf_key_templates.h"], include_prefix = "tink/prf", visibility = ["//visibility:public"], deps = [ ":aes_cmac_prf_key_manager", ":hkdf_prf_key_manager", ":hmac_prf_key_manager", "//proto:aes_cmac_prf_cc_proto", "//proto:hkdf_prf_cc_proto", "//proto:hmac_prf_cc_proto", "//proto:tink_cc_proto", "@com_google_absl//absl/memory", ], ) cc_library( name = "prf_set", srcs = ["prf_set.cc"], hdrs = ["prf_set.h"], include_prefix = "tink/prf", visibility = ["//visibility:public"], deps = [ "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "prf_set_wrapper", srcs = ["prf_set_wrapper.cc"], hdrs = ["prf_set_wrapper.h"], include_prefix = "tink/prf", deps = [ ":prf_set", "//:primitive_set", "//:primitive_wrapper", "//internal:monitoring_util", "//internal:registry_impl", "//monitoring", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "aes_cmac_prf_key_manager", hdrs = ["aes_cmac_prf_key_manager.h"], include_prefix = "tink/prf", deps = [ ":prf_set", "//:core/key_type_manager", "//:core/template_util", "//:input_stream", "//:key_manager", "//proto:aes_cmac_prf_cc_proto", "//proto:tink_cc_proto", "//subtle:random", "//subtle:stateful_cmac_boringssl", "//subtle/prf:prf_set_util", "//util:constants", "//util:errors", "//util:input_stream_util", "//util:protobuf_helper", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "hmac_prf_key_manager", srcs = ["hmac_prf_key_manager.cc"], hdrs = ["hmac_prf_key_manager.h"], include_prefix = "tink/prf", deps = [ ":prf_set", "//:core/key_type_manager", "//:core/template_util", "//:input_stream", "//:key_manager", "//internal:fips_utils", "//proto:hmac_prf_cc_proto", "//proto:tink_cc_proto", "//subtle:common_enums", "//subtle:random", "//subtle:stateful_hmac_boringssl", "//subtle/prf:prf_set_util", "//util:constants", "//util:enums", "//util:errors", "//util:input_stream_util", "//util:protobuf_helper", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_test( name = "hkdf_prf_key_manager_test", srcs = ["hkdf_prf_key_manager_test.cc"], deps = [ ":hkdf_prf_key_manager", ":prf_set", "//:input_stream", "//proto:common_cc_proto", "//proto:hkdf_prf_cc_proto", "//proto:tink_cc_proto", "//subtle", "//subtle/prf:hkdf_streaming_prf", "//subtle/prf:prf_set_util", "//subtle/prf:streaming_prf", "//util:input_stream_util", "//util:istream_input_stream", "//util:secret_data", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "prf_key_templates_test", srcs = ["prf_key_templates_test.cc"], deps = [ ":aes_cmac_prf_key_manager", ":hkdf_prf_key_manager", ":hmac_prf_key_manager", ":prf_key_templates", "//proto:aes_cmac_prf_cc_proto", "//proto:hkdf_prf_cc_proto", "//proto:hmac_prf_cc_proto", "//proto:tink_cc_proto", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "prf_set_wrapper_test", srcs = ["prf_set_wrapper_test.cc"], deps = [ ":prf_set", ":prf_set_wrapper", "//:primitive_set", "//:registry", "//internal:registry_impl", "//monitoring", "//monitoring:monitoring_client_mocks", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "prf_set_test", srcs = ["prf_set_test.cc"], deps = [ ":prf_config", ":prf_key_templates", ":prf_set", "//:keyset_handle", "//:keyset_manager", "//config:global_registry", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_cmac_prf_key_manager_test", srcs = ["aes_cmac_prf_key_manager_test.cc"], deps = [ ":aes_cmac_prf_key_manager", ":prf_set", "//:input_stream", "//proto:aes_cmac_prf_cc_proto", "//proto:tink_cc_proto", "//subtle:aes_cmac_boringssl", "//util:istream_input_stream", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hmac_prf_key_manager_test", srcs = ["hmac_prf_key_manager_test.cc"], deps = [ ":hmac_prf_key_manager", ":prf_set", "//:core/key_manager_impl", "//proto:hmac_prf_cc_proto", "//proto:tink_cc_proto", "//subtle:hmac_boringssl", "//util:enums", "//util:istream_input_stream", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "prf_config_test", srcs = ["prf_config_test.cc"], tags = ["fips"], deps = [ ":hmac_prf_key_manager", ":prf_config", ":prf_key_templates", ":prf_set", "//:tink_cc", "//config:global_registry", "//internal:fips_utils", "//proto:tink_cc_proto", "//util:status", "//util:test_matchers", "//util:test_util", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "failing_prfset", srcs = ["failing_prfset.cc"], hdrs = ["failing_prfset.h"], include_prefix = "tink/prf", deps = [ ":prf_set", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_test( name = "failing_prfset_test", srcs = ["failing_prfset_test.cc"], deps = [ ":failing_prfset", ":prf_set", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "config_v0", srcs = ["config_v0.cc"], hdrs = ["config_v0.h"], include_prefix = "tink/prf", deps = [ "//:configuration", "//prf/internal:config_v0", "@com_google_absl//absl/log:check", ], ) cc_library( name = "key_gen_config_v0", srcs = ["key_gen_config_v0.cc"], hdrs = ["key_gen_config_v0.h"], include_prefix = "tink/prf", deps = [ "//:key_gen_configuration", "//prf/internal:key_gen_config_v0", "@com_google_absl//absl/log:check", ], ) cc_test( name = "config_v0_test", srcs = ["config_v0_test.cc"], deps = [ ":config_v0", ":key_gen_config_v0", ":prf_key_templates", ":prf_set", "//:keyset_handle", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/prf/CMakeLists.txt ================================================ tink_module(prf) add_subdirectory(internal) tink_cc_library( NAME hkdf_prf_key_manager SRCS hkdf_prf_key_manager.h DEPS tink::prf::prf_set absl::memory absl::status absl::strings tink::core::key_type_manager tink::core::template_util tink::core::input_stream tink::subtle::subtle tink::subtle::prf::hkdf_streaming_prf tink::subtle::prf::prf_set_util tink::subtle::prf::streaming_prf tink::util::constants tink::util::enums tink::util::input_stream_util tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::common_cc_proto tink::proto::hkdf_prf_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME prf_config SRCS prf_config.cc prf_config.h DEPS tink::prf::aes_cmac_prf_key_manager tink::prf::hkdf_prf_key_manager tink::prf::hmac_prf_key_manager tink::prf::prf_set_wrapper absl::memory tink::core::registry tink::config::tink_fips tink::util::status tink::proto::tink_cc_proto ) tink_cc_library( NAME prf_key_templates SRCS prf_key_templates.cc prf_key_templates.h DEPS tink::prf::aes_cmac_prf_key_manager tink::prf::hkdf_prf_key_manager tink::prf::hmac_prf_key_manager absl::memory tink::proto::aes_cmac_prf_cc_proto tink::proto::hkdf_prf_cc_proto tink::proto::hmac_prf_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME prf_set SRCS prf_set.cc prf_set.h DEPS absl::status absl::strings tink::util::status tink::util::statusor ) tink_cc_library( NAME prf_set_wrapper SRCS prf_set_wrapper.cc prf_set_wrapper.h DEPS tink::prf::prf_set absl::memory absl::status absl::statusor absl::string_view tink::core::primitive_set tink::core::primitive_wrapper tink::internal::monitoring_util tink::internal::registry_impl tink::monitoring::monitoring tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME aes_cmac_prf_key_manager SRCS aes_cmac_prf_key_manager.h DEPS tink::prf::prf_set absl::memory absl::status absl::strings tink::core::key_type_manager tink::core::template_util tink::core::input_stream tink::core::key_manager tink::subtle::random tink::subtle::stateful_cmac_boringssl tink::subtle::prf::prf_set_util tink::util::constants tink::util::errors tink::util::input_stream_util tink::util::protobuf_helper tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::aes_cmac_prf_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME hmac_prf_key_manager SRCS hmac_prf_key_manager.cc hmac_prf_key_manager.h DEPS tink::prf::prf_set absl::memory absl::status absl::strings absl::optional tink::core::key_type_manager tink::core::template_util tink::core::input_stream tink::core::key_manager tink::internal::fips_utils tink::subtle::common_enums tink::subtle::random tink::subtle::stateful_hmac_boringssl tink::subtle::prf::prf_set_util tink::util::constants tink::util::enums tink::util::errors tink::util::input_stream_util tink::util::protobuf_helper tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::hmac_prf_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME hkdf_prf_key_manager_test SRCS hkdf_prf_key_manager_test.cc DEPS tink::prf::hkdf_prf_key_manager tink::prf::prf_set gmock absl::memory absl::status tink::core::input_stream tink::subtle::subtle tink::subtle::prf::hkdf_streaming_prf tink::subtle::prf::prf_set_util tink::subtle::prf::streaming_prf tink::util::input_stream_util tink::util::istream_input_stream tink::util::secret_data tink::util::statusor tink::util::test_matchers tink::proto::common_cc_proto tink::proto::hkdf_prf_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME prf_key_templates_test SRCS prf_key_templates_test.cc DEPS tink::prf::aes_cmac_prf_key_manager tink::prf::hkdf_prf_key_manager tink::prf::hmac_prf_key_manager tink::prf::prf_key_templates gmock absl::memory tink::util::test_matchers tink::proto::aes_cmac_prf_cc_proto tink::proto::hkdf_prf_cc_proto tink::proto::hmac_prf_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME prf_set_wrapper_test SRCS prf_set_wrapper_test.cc DEPS tink::prf::prf_set tink::prf::prf_set_wrapper gmock absl::flat_hash_map absl::memory absl::status absl::strings tink::core::primitive_set tink::core::registry tink::internal::registry_impl tink::monitoring::monitoring tink::monitoring::monitoring_client_mocks tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) tink_cc_test( NAME prf_set_test SRCS prf_set_test.cc DEPS tink::prf::prf_config tink::prf::prf_key_templates tink::prf::prf_set gmock absl::memory absl::strings tink::core::keyset_handle tink::core::keyset_manager tink::config::global_registry tink::util::statusor tink::util::test_matchers tink::util::test_util ) tink_cc_test( NAME aes_cmac_prf_key_manager_test SRCS aes_cmac_prf_key_manager_test.cc DEPS tink::prf::aes_cmac_prf_key_manager tink::prf::prf_set gmock absl::memory tink::core::input_stream tink::subtle::aes_cmac_boringssl tink::util::istream_input_stream tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::aes_cmac_prf_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME hmac_prf_key_manager_test SRCS hmac_prf_key_manager_test.cc DEPS tink::prf::hmac_prf_key_manager tink::prf::prf_set gmock absl::memory absl::status tink::core::key_manager_impl tink::subtle::hmac_boringssl tink::util::enums tink::util::istream_input_stream tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::hmac_prf_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME prf_config_test SRCS prf_config_test.cc DEPS tink::prf::hmac_prf_key_manager tink::prf::prf_config tink::prf::prf_key_templates tink::prf::prf_set gmock absl::status crypto tink::core::cc tink::config::global_registry tink::internal::fips_utils tink::util::status tink::util::test_matchers tink::util::test_util tink::proto::tink_cc_proto ) tink_cc_library( NAME failing_prfset SRCS failing_prfset.cc failing_prfset.h DEPS tink::prf::prf_set absl::memory absl::status absl::strings tink::util::status tink::util::statusor ) tink_cc_test( NAME failing_prfset_test SRCS failing_prfset_test.cc DEPS tink::prf::failing_prfset tink::prf::prf_set gmock absl::status tink::util::test_matchers ) tink_cc_library( NAME config_v0 SRCS config_v0.cc config_v0.h DEPS absl::check tink::core::configuration tink::prf::internal::config_v0 ) tink_cc_library( NAME key_gen_config_v0 SRCS key_gen_config_v0.cc key_gen_config_v0.h DEPS absl::check tink::core::key_gen_configuration tink::prf::internal::key_gen_config_v0 ) tink_cc_test( NAME config_v0_test SRCS config_v0_test.cc DEPS tink::prf::config_v0 tink::prf::key_gen_config_v0 tink::prf::prf_key_templates tink::prf::prf_set gmock tink::core::keyset_handle tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) ================================================ FILE: cc/prf/aes_cmac_prf_key_manager.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_PRF_AES_CMAC_PRF_KEY_MANAGER_H_ #define TINK_PRF_AES_CMAC_PRF_KEY_MANAGER_H_ #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/input_stream.h" #include "tink/key_manager.h" #include "tink/prf/prf_set.h" #include "tink/subtle/prf/prf_set_util.h" #include "tink/subtle/random.h" #include "tink/subtle/stateful_cmac_boringssl.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/input_stream_util.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/aes_cmac_prf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class AesCmacPrfKeyManager : public KeyTypeManager> { public: class PrfSetFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::AesCmacPrfKey& key) const override { return subtle::CreatePrfFromStatefulMacFactory( absl::make_unique( AesCmacPrfKeyManager::MaxOutputLength(), util::SecretDataFromStringView(key.key_value()))); } }; AesCmacPrfKeyManager() : KeyTypeManager( absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::SYMMETRIC; } static uint64_t MaxOutputLength() { return 16; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::AesCmacPrfKey& key) const override { crypto::tink::util::Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; if (key.key_value().size() != kKeySizeInBytes) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, "Invalid AesCmacPrfKey: key_value wrong length."); } return util::OkStatus(); } crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::AesCmacPrfKeyFormat& key_format) const override { crypto::tink::util::Status status = ValidateVersion(key_format.version(), get_version()); if (!status.ok()) return status; if (key_format.key_size() != kKeySizeInBytes) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, "Invalid AesCmacPrfKeyFormat: invalid key_size."); } return util::OkStatus(); } crypto::tink::util::StatusOr CreateKey( const google::crypto::tink::AesCmacPrfKeyFormat& key_format) const override { google::crypto::tink::AesCmacPrfKey key; key.set_version(get_version()); key.set_key_value(subtle::Random::GetRandomBytes(key_format.key_size())); return key; } crypto::tink::util::StatusOr DeriveKey( const google::crypto::tink::AesCmacPrfKeyFormat& key_format, InputStream* input_stream) const override { auto status = ValidateKeyFormat(key_format); if (!status.ok()) { return status; } crypto::tink::util::StatusOr randomness = ReadBytesFromStream(key_format.key_size(), input_stream); if (!randomness.status().ok()) { return randomness.status(); } google::crypto::tink::AesCmacPrfKey key; key.set_version(get_version()); key.set_key_value(randomness.value()); return key; } private: // Due to https://www.math.uwaterloo.ca/~ajmeneze/publications/tightness.pdf, // we only allow key sizes of 256 bit. const int kKeySizeInBytes = 32; const std::string key_type_ = absl::StrCat( kTypeGoogleapisCom, google::crypto::tink::AesCmacPrfKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_PRF_AES_CMAC_PRF_KEY_MANAGER_H_ ================================================ FILE: cc/prf/aes_cmac_prf_key_manager_test.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/prf/aes_cmac_prf_key_manager.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "tink/input_stream.h" #include "tink/prf/prf_set.h" #include "tink/subtle/aes_cmac_boringssl.h" #include "tink/util/istream_input_stream.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/aes_cmac_prf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::google::crypto::tink::AesCmacPrfKey; using ::google::crypto::tink::AesCmacPrfKeyFormat; using ::testing::Eq; using ::testing::Not; using ::testing::SizeIs; using ::testing::StrEq; std::unique_ptr GetInputStreamForString(const std::string& input) { return absl::make_unique( absl::make_unique(input)); } AesCmacPrfKeyFormat ValidKeyFormat() { AesCmacPrfKeyFormat format; format.set_key_size(32); return format; } TEST(AesCmacPrfKeyManagerTest, Basics) { EXPECT_THAT(AesCmacPrfKeyManager().get_version(), Eq(0)); EXPECT_THAT(AesCmacPrfKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.AesCmacPrfKey")); EXPECT_THAT(AesCmacPrfKeyManager().key_material_type(), Eq(google::crypto::tink::KeyData::SYMMETRIC)); } TEST(AesCmacPrfKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(AesCmacPrfKeyManager().ValidateKey(AesCmacPrfKey()), Not(IsOk())); } TEST(AesCmacPrfKeyManagerTest, ValidateEmptyKeyFormat) { EXPECT_THAT(AesCmacPrfKeyManager().ValidateKeyFormat(AesCmacPrfKeyFormat()), Not(IsOk())); } TEST(AesCmacPrfKeyManagerTest, ValidateSimpleKeyFormat) { EXPECT_THAT(AesCmacPrfKeyManager().ValidateKeyFormat(ValidKeyFormat()), IsOk()); } TEST(AesCmacPrfKeyManagerTest, ValidateKeyFormatKeySizes) { AesCmacPrfKeyFormat format = ValidKeyFormat(); format.set_key_size(0); EXPECT_THAT(AesCmacPrfKeyManager().ValidateKeyFormat(format), Not(IsOk())); format.set_key_size(1); EXPECT_THAT(AesCmacPrfKeyManager().ValidateKeyFormat(format), Not(IsOk())); format.set_key_size(15); EXPECT_THAT(AesCmacPrfKeyManager().ValidateKeyFormat(format), Not(IsOk())); format.set_key_size(16); EXPECT_THAT(AesCmacPrfKeyManager().ValidateKeyFormat(format), Not(IsOk())); format.set_key_size(17); EXPECT_THAT(AesCmacPrfKeyManager().ValidateKeyFormat(format), Not(IsOk())); format.set_key_size(31); EXPECT_THAT(AesCmacPrfKeyManager().ValidateKeyFormat(format), Not(IsOk())); format.set_key_size(32); EXPECT_THAT(AesCmacPrfKeyManager().ValidateKeyFormat(format), IsOk()); format.set_key_size(33); EXPECT_THAT(AesCmacPrfKeyManager().ValidateKeyFormat(format), Not(IsOk())); } TEST(AesCmacPrfKeyManagerTest, CreateKey) { AesCmacPrfKeyFormat format = ValidKeyFormat(); ASSERT_THAT(AesCmacPrfKeyManager().CreateKey(format), IsOk()); AesCmacPrfKey key = AesCmacPrfKeyManager().CreateKey(format).value(); EXPECT_THAT(key.version(), Eq(0)); EXPECT_THAT(key.key_value(), SizeIs(format.key_size())); } TEST(AesCmacPrfKeyManagerTest, ValidateKey) { AesCmacPrfKeyFormat format = ValidKeyFormat(); AesCmacPrfKey key = AesCmacPrfKeyManager().CreateKey(format).value(); EXPECT_THAT(AesCmacPrfKeyManager().ValidateKey(key), IsOk()); } TEST(AesCmacPrfKeyManagerTest, ValidateKeyInvalidVersion) { AesCmacPrfKeyFormat format = ValidKeyFormat(); AesCmacPrfKey key = AesCmacPrfKeyManager().CreateKey(format).value(); key.set_version(1); EXPECT_THAT(AesCmacPrfKeyManager().ValidateKey(key), Not(IsOk())); } TEST(AesCmacPrfKeyManagerTest, ValidateKeyShortKey) { AesCmacPrfKeyFormat format = ValidKeyFormat(); AesCmacPrfKey key = AesCmacPrfKeyManager().CreateKey(format).value(); key.set_key_value("0123456789abcdef"); EXPECT_THAT(AesCmacPrfKeyManager().ValidateKey(key), Not(IsOk())); } TEST(AesCmacPrfKeyManagerTest, GetPrimitive) { AesCmacPrfKeyFormat format = ValidKeyFormat(); AesCmacPrfKey key = AesCmacPrfKeyManager().CreateKey(format).value(); auto manager_prf_or = AesCmacPrfKeyManager().GetPrimitive(key); ASSERT_THAT(manager_prf_or, IsOk()); auto prf_value_or = manager_prf_or.value()->Compute("some plaintext", 16); ASSERT_THAT(prf_value_or, IsOk()); auto direct_prf_or = subtle::AesCmacBoringSsl::New( util::SecretDataFromStringView(key.key_value()), 16); ASSERT_THAT(direct_prf_or, IsOk()); auto direct_prf_value_or = direct_prf_or.value()->ComputeMac("some plaintext"); ASSERT_THAT(direct_prf_value_or, IsOk()); EXPECT_THAT(direct_prf_value_or.value(), StrEq(prf_value_or.value())); } TEST(AesCmacPrfKeyManagerTest, DeriveKeyValid) { std::string bytes = "0123456789abcdef0123456789abcdef"; auto inputstream = GetInputStreamForString(bytes); auto key_or = AesCmacPrfKeyManager().DeriveKey(ValidKeyFormat(), inputstream.get()); ASSERT_THAT(key_or, IsOk()); AesCmacPrfKey key = key_or.value(); EXPECT_THAT(key.version(), Eq(AesCmacPrfKeyManager().get_version())); EXPECT_THAT(key.key_value(), Eq(bytes)); } TEST(AesCmacPrfKeyManagerTest, DeriveKeyNotEnoughRandomness) { std::string bytes = "0123456789abcdef"; auto inputstream = GetInputStreamForString(bytes); auto key_or = AesCmacPrfKeyManager().DeriveKey(ValidKeyFormat(), inputstream.get()); EXPECT_THAT(key_or, Not(IsOk())); } TEST(AesCmacPrfKeyManagerTest, DeriveKeyInvalidFormat) { std::string bytes = "0123456789abcdef"; auto inputstream = GetInputStreamForString(bytes); auto format = ValidKeyFormat(); format.set_key_size(12); auto key_or = AesCmacPrfKeyManager().DeriveKey(format, inputstream.get()); EXPECT_THAT(key_or, Not(IsOk())); } TEST(AesCmacPrfKeyManagerTest, DeriveKeyInvalidVersion) { auto format = ValidKeyFormat(); format.set_version(1); std::string bytes = "0123456789abcdef0123456789abcdef"; auto inputstream = GetInputStreamForString(bytes); auto key_or = AesCmacPrfKeyManager().DeriveKey(format, inputstream.get()); EXPECT_THAT(key_or, Not(IsOk())); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/prf/config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/prf/config_v0.h" #include "absl/log/check.h" #include "tink/configuration.h" #include "tink/prf/internal/config_v0.h" namespace crypto { namespace tink { const Configuration& ConfigPrfV0() { static const Configuration* instance = [] { static Configuration* config = new Configuration(); CHECK_OK(internal::AddPrfV0(*config)); return config; }(); return *instance; } } // namespace tink } // namespace crypto ================================================ FILE: cc/prf/config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_PRF_CONFIG_V0_H_ #define TINK_PRF_CONFIG_V0_H_ #include "tink/configuration.h" namespace crypto { namespace tink { // Configuration used to generate PRF primitives with recommended key managers. const Configuration& ConfigPrfV0(); } // namespace tink } // namespace crypto #endif // TINK_PRF_CONFIG_V0_H_ ================================================ FILE: cc/prf/config_v0_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/prf/config_v0.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/keyset_handle.h" #include "tink/prf/key_gen_config_v0.h" #include "tink/prf/prf_key_templates.h" #include "tink/prf/prf_set.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::google::crypto::tink::KeyTemplate; using ::testing::Eq; using ::testing::TestWithParam; using ::testing::Values; using PrfV0KeyTypesTest = TestWithParam; INSTANTIATE_TEST_SUITE_P(PrfV0KeyTypesTestSuite, PrfV0KeyTypesTest, Values(PrfKeyTemplates::AesCmac(), PrfKeyTemplates::HkdfSha256(), PrfKeyTemplates::HmacSha256())); TEST_P(PrfV0KeyTypesTest, GetPrimitive) { util::StatusOr> handle = KeysetHandle::GenerateNew(GetParam(), KeyGenConfigPrfV0()); ASSERT_THAT(handle, IsOk()); util::StatusOr> prf = (*handle)->GetPrimitive(ConfigPrfV0()); ASSERT_THAT(prf, IsOk()); size_t output_length = 16; util::StatusOr output = (*prf)->ComputePrimary("input", output_length); ASSERT_THAT(output, IsOk()); EXPECT_THAT((*output).length(), Eq(output_length)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/prf/failing_prfset.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/prf/failing_prfset.h" #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/prf/prf_set.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { // A Prf that always returns a kInternal status on API calls. class AlwaysFailPrf : public Prf { public: explicit AlwaysFailPrf(std::string message) : message_(std::move(message)) {} util::StatusOr Compute(absl::string_view /*input*/, size_t /*output_length*/) const override { return util::Status( absl::StatusCode::kInternal, absl::StrCat( "AlwaysFailPrf will always fail on Compute (msg=", message_, ")")); } private: const std::string message_; }; // A PrfSet that always returns a kInternal status on API calls. class AlwaysFailPrfSet : public PrfSet { public: explicit AlwaysFailPrfSet(std::string message) : message_(std::move(message)), always_fail_prf_0_(absl::make_unique(message_)), always_fail_prf_1_(absl::make_unique(message_)), always_fail_prf_2_(absl::make_unique(message_)), prfs_({{0, always_fail_prf_0_.get()}, {1, always_fail_prf_1_.get()}, {2, always_fail_prf_2_.get()}}) {} uint32_t GetPrimaryId() const override { return 0; } // A map of the PRFs represented by the keys in this keyset. // The map is guaranteed to contain getPrimaryId() as a key. const std::map& GetPrfs() const override { return prfs_; }; util::StatusOr ComputePrimary(absl::string_view /*input*/, size_t /*output_length*/) const { return util::Status( absl::StatusCode::kInternal, absl::StrCat( "AlwaysFailPrfSet will always fail on ComputePrimary (msg=", message_, ")")); } private: const std::string message_; std::unique_ptr always_fail_prf_0_; std::unique_ptr always_fail_prf_1_; std::unique_ptr always_fail_prf_2_; std::map prfs_; }; } // namespace std::unique_ptr CreateAlwaysFailingPrf(std::string message) { return absl::make_unique(std::move(message)); } std::unique_ptr CreateAlwaysFailingPrfSet(std::string message) { return absl::make_unique(std::move(message)); } } // namespace tink } // namespace crypto ================================================ FILE: cc/prf/failing_prfset.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_PRF_FAILING_PRFSET_H_ #define TINK_PRF_FAILING_PRFSET_H_ #include #include #include "absl/strings/string_view.h" #include "tink/prf/prf_set.h" namespace crypto { namespace tink { // Returns a Prf that always returns an error when calling Compute. // The error message will contain `message`. std::unique_ptr CreateAlwaysFailingPrf(std::string message = ""); // Returns a PrfSet that always returns an error when calling ComputePrimary and // a set of always failing Prfs when calling GetPrfs(). // The error message will contain `message`. std::unique_ptr CreateAlwaysFailingPrfSet(std::string message = ""); } // namespace tink } // namespace crypto #endif // TINK_PRF_FAILING_PRFSET_H_ ================================================ FILE: cc/prf/failing_prfset_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/prf/failing_prfset.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/prf/prf_set.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::StatusIs; using ::testing::HasSubstr; TEST(AlwaysFailPrf, ComputePrimaryFails) { std::unique_ptr failing_prf = CreateAlwaysFailingPrf(); EXPECT_THAT(failing_prf->Compute("someinput", 16).status(), StatusIs(absl::StatusCode::kInternal)); } TEST(AlwaysFailPrf, ComputePrimaryFailsContainsMessage) { const std::string expected_message = "expected_message"; std::unique_ptr failing_prf = CreateAlwaysFailingPrf(expected_message); EXPECT_THAT( failing_prf->Compute("someinput", 16).status(), StatusIs(absl::StatusCode::kInternal, HasSubstr(expected_message))); } TEST(AlwaysFailPrfSet, ComputePrimaryFails) { std::unique_ptr failing_prf_set = CreateAlwaysFailingPrfSet(); EXPECT_THAT(failing_prf_set->ComputePrimary("someinput", 16).status(), StatusIs(absl::StatusCode::kInternal)); } TEST(AlwaysFailPrfSet, ComputePrimaryFailsContainsMessage) { const std::string expected_message = "expected_message"; std::unique_ptr failing_prf_set = CreateAlwaysFailingPrfSet(expected_message); EXPECT_THAT( failing_prf_set->ComputePrimary("someinput", 16).status(), StatusIs(absl::StatusCode::kInternal, HasSubstr(expected_message))); } TEST(AlwaysFailPrfSet, GetPrfsReturnsFailingPrfs) { const std::string expected_message = "expected_message"; std::unique_ptr failing_prf_set = CreateAlwaysFailingPrfSet(expected_message); const std::map& prfs_map = failing_prf_set->GetPrfs(); for (auto const& entry : prfs_map) { EXPECT_THAT( entry.second->Compute("someinput", 16).status(), StatusIs(absl::StatusCode::kInternal, HasSubstr(expected_message))); } } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/prf/hkdf_prf_key_manager.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_PRF_HKDF_PRF_KEY_MANAGER_H_ #define TINK_PRF_HKDF_PRF_KEY_MANAGER_H_ #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/input_stream.h" #include "tink/prf/prf_set.h" #include "tink/subtle/prf/hkdf_streaming_prf.h" #include "tink/subtle/prf/prf_set_util.h" #include "tink/subtle/prf/streaming_prf.h" #include "tink/subtle/random.h" #include "tink/util/constants.h" #include "tink/util/enums.h" #include "tink/util/input_stream_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/common.pb.h" #include "proto/hkdf_prf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class HkdfPrfKeyManager : public KeyTypeManager> { public: class StreamingPrfFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::HkdfPrfKey& key) const override { return subtle::HkdfStreamingPrf::New( crypto::tink::util::Enums::ProtoToSubtle(key.params().hash()), util::SecretDataFromStringView(key.key_value()), key.params().salt()); } }; class PrfSetFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::HkdfPrfKey& key) const override { auto hkdf_result = subtle::HkdfStreamingPrf::New( crypto::tink::util::Enums::ProtoToSubtle(key.params().hash()), util::SecretDataFromStringView(key.key_value()), key.params().salt()); if (!hkdf_result.ok()) { return hkdf_result.status(); } return subtle::CreatePrfFromStreamingPrf(std::move(hkdf_result.value())); } }; HkdfPrfKeyManager() : KeyTypeManager(absl::make_unique(), absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::SYMMETRIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::HkdfPrfKey& key) const override { crypto::tink::util::Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; status = ValidateKeySize(key.key_value().size()); if (!status.ok()) return status; return ValidateParams(key.params()); } crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::HkdfPrfKeyFormat& key_format) const override { crypto::tink::util::Status status = ValidateVersion(key_format.version(), get_version()); if (!status.ok()) return status; status = ValidateKeySize(key_format.key_size()); if (!status.ok()) return status; return ValidateParams(key_format.params()); } crypto::tink::util::StatusOr CreateKey( const google::crypto::tink::HkdfPrfKeyFormat& key_format) const override { google::crypto::tink::HkdfPrfKey key; key.set_version(get_version()); *key.mutable_params() = key_format.params(); key.set_key_value( crypto::tink::subtle::Random::GetRandomBytes(key_format.key_size())); return key; } crypto::tink::util::StatusOr DeriveKey( const google::crypto::tink::HkdfPrfKeyFormat& key_format, InputStream* input_stream) const override { auto status = ValidateKeyFormat(key_format); if (!status.ok()) { return status; } crypto::tink::util::StatusOr randomness = ReadBytesFromStream(key_format.key_size(), input_stream); if (!randomness.ok()) { return randomness.status(); } google::crypto::tink::HkdfPrfKey key; key.set_version(get_version()); *key.mutable_params() = key_format.params(); key.set_key_value(randomness.value()); return key; } private: crypto::tink::util::Status ValidateKeySize(int key_size) const { if (key_size < kMinKeySizeBytes) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, "Invalid HkdfPrfKey: key_value is too short."); } return crypto::tink::util::OkStatus(); } crypto::tink::util::Status ValidateParams( const google::crypto::tink::HkdfPrfParams& params) const { // Omitting SHA1 for the moment; there seems to be no reason to allow it. if (params.hash() != google::crypto::tink::HashType::SHA256 && params.hash() != google::crypto::tink::HashType::SHA512) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, "Invalid HkdfPrfKey: unsupported hash."); } return crypto::tink::util::OkStatus(); } // We use a somewhat larger minimum key size than usual, because PRFs might be // used by many users, in which case the security can degrade by a factor // depending on the number of users. (Discussed for example in // https://eprint.iacr.org/2012/159) const int kMinKeySizeBytes = 32; const std::string key_type_ = absl::StrCat( kTypeGoogleapisCom, google::crypto::tink::HkdfPrfKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_PRF_HKDF_PRF_KEY_MANAGER_H_ ================================================ FILE: cc/prf/hkdf_prf_key_manager_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/prf/hkdf_prf_key_manager.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/input_stream.h" #include "tink/prf/prf_set.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/prf/hkdf_streaming_prf.h" #include "tink/subtle/prf/prf_set_util.h" #include "tink/subtle/prf/streaming_prf.h" #include "tink/util/input_stream_util.h" #include "tink/util/istream_input_stream.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/common.pb.h" #include "proto/hkdf_prf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::HkdfPrfKey; using ::google::crypto::tink::HkdfPrfKeyFormat; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::Not; using ::testing::SizeIs; TEST(HkdfPrfKeyManagerTest, Basics) { EXPECT_THAT(HkdfPrfKeyManager().get_version(), Eq(0)); EXPECT_THAT(HkdfPrfKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.HkdfPrfKey")); EXPECT_THAT(HkdfPrfKeyManager().key_material_type(), Eq(google::crypto::tink::KeyData::SYMMETRIC)); } TEST(HkdfPrfKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(HkdfPrfKeyManager().ValidateKey(HkdfPrfKey()), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HkdfPrfKeyManagerTest, ValidateValid32ByteKey) { HkdfPrfKey key; key.set_version(0); key.set_key_value("01234567890123456789012345678901"); key.mutable_params()->set_hash(::google::crypto::tink::SHA256); EXPECT_THAT(HkdfPrfKeyManager().ValidateKey(key), IsOk()); } TEST(HkdfPrfKeyManagerTest, ValidateValidSha512Key) { HkdfPrfKey key; key.set_version(0); key.set_key_value("01234567890123456789012345678901"); key.mutable_params()->set_hash(::google::crypto::tink::SHA512); EXPECT_THAT(HkdfPrfKeyManager().ValidateKey(key), IsOk()); } TEST(HkdfPrfKeyManagerTest, ValidateValid33ByteKey) { HkdfPrfKey key; key.set_version(0); key.set_key_value("012345678901234567890123456789012"); key.mutable_params()->set_hash(::google::crypto::tink::SHA256); EXPECT_THAT(HkdfPrfKeyManager().ValidateKey(key), IsOk()); } TEST(HkdfPrfKeyManagerTest, ValidateValidKeyWithSalt) { HkdfPrfKey key; key.set_version(0); key.set_key_value("01234567890123456789012345678901"); key.mutable_params()->set_hash(::google::crypto::tink::SHA256); key.mutable_params()->set_salt("12345"); EXPECT_THAT(HkdfPrfKeyManager().ValidateKey(key), IsOk()); } TEST(HkdfPrfKeyManagerTest, InvalidKeySizes31Bytes) { HkdfPrfKey key; key.set_version(0); key.set_key_value("0123456789012345678901234567890"); EXPECT_THAT(HkdfPrfKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HkdfPrfKeyManagerTest, InvalidKeySha1) { HkdfPrfKey key; key.set_version(0); key.set_key_value("01234567890123456789012345678901"); key.mutable_params()->set_hash(::google::crypto::tink::SHA1); EXPECT_THAT(HkdfPrfKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HkdfPrfKeyManagerTest, InvalidKeyVersion) { HkdfPrfKey key; key.set_version(1); key.set_key_value("01234567890123456789012345678901"); key.mutable_params()->set_hash(::google::crypto::tink::SHA256); EXPECT_THAT(HkdfPrfKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HkdfPrfKeyManagerTest, ValidateEmptyKeyFormat) { EXPECT_THAT(HkdfPrfKeyManager().ValidateKeyFormat(HkdfPrfKeyFormat()), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HkdfPrfKeyManagerTest, ValidateValid32ByteKeyFormat) { HkdfPrfKeyFormat key_format; key_format.set_key_size(32); key_format.mutable_params()->set_hash(::google::crypto::tink::SHA256); EXPECT_THAT(HkdfPrfKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(HkdfPrfKeyManagerTest, ValidateValidSha512KeyFormat) { HkdfPrfKeyFormat key_format; key_format.set_key_size(32); key_format.mutable_params()->set_hash(::google::crypto::tink::SHA512); EXPECT_THAT(HkdfPrfKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(HkdfPrfKeyManagerTest, ValidateValid33ByteKeyFormat) { HkdfPrfKeyFormat key_format; key_format.set_key_size(33); key_format.mutable_params()->set_hash(::google::crypto::tink::SHA256); EXPECT_THAT(HkdfPrfKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(HkdfPrfKeyManagerTest, ValidateValidKeyFormatWithSalt) { HkdfPrfKeyFormat key_format; key_format.set_key_size(32); key_format.mutable_params()->set_hash(::google::crypto::tink::SHA256); key_format.mutable_params()->set_salt("abcdef"); EXPECT_THAT(HkdfPrfKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(HkdfPrfKeyManagerTest, InvalidKeyFormatSha1) { HkdfPrfKeyFormat key_format; key_format.set_key_size(32); key_format.mutable_params()->set_hash(::google::crypto::tink::SHA1); EXPECT_THAT(HkdfPrfKeyManager().ValidateKeyFormat(key_format), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HkdfPrfKeyManagerTest, ValidateInvalid31ByteKeyFormat) { HkdfPrfKeyFormat key_format; key_format.set_key_size(31); key_format.mutable_params()->set_hash(::google::crypto::tink::SHA256); EXPECT_THAT(HkdfPrfKeyManager().ValidateKeyFormat(key_format), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(HkdfPrfKeyManagerTest, CreateKey) { HkdfPrfKeyFormat key_format; key_format.set_key_size(32); key_format.mutable_params()->set_hash(::google::crypto::tink::SHA256); auto key_or = HkdfPrfKeyManager().CreateKey(key_format); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().key_value(), SizeIs(32)); EXPECT_THAT(key_or.value().params().hash(), Eq(::google::crypto::tink::SHA256)); EXPECT_THAT(key_or.value().params().salt(), Eq("")); EXPECT_THAT(key_or.value().version(), Eq(0)); } TEST(HkdfPrfKeyManagerTest, CreateKeyDifferetSize) { HkdfPrfKeyFormat key_format; key_format.set_key_size(77); key_format.mutable_params()->set_hash(::google::crypto::tink::SHA256); auto key_or = HkdfPrfKeyManager().CreateKey(key_format); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().key_value(), SizeIs(77)); } TEST(HkdfPrfKeyManagerTest, CreateKeyDifferetHash) { HkdfPrfKeyFormat key_format; key_format.set_key_size(32); key_format.mutable_params()->set_hash(::google::crypto::tink::SHA512); auto key_or = HkdfPrfKeyManager().CreateKey(key_format); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().params().hash(), Eq(::google::crypto::tink::SHA512)); } TEST(HkdfPrfKeyManagerTest, CreateKeyDifferetSalt) { HkdfPrfKeyFormat key_format; key_format.set_key_size(32); key_format.mutable_params()->set_hash(::google::crypto::tink::SHA512); key_format.mutable_params()->set_salt("saltstring"); auto key_or = HkdfPrfKeyManager().CreateKey(key_format); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().params().salt(), Eq("saltstring")); } TEST(HkdfPrfKeyManagerTest, CreatePrf) { HkdfPrfKeyFormat key_format; key_format.set_key_size(32); key_format.mutable_params()->set_hash(::google::crypto::tink::SHA256); key_format.mutable_params()->set_salt("salt string"); auto key_or = HkdfPrfKeyManager().CreateKey(key_format); ASSERT_THAT(key_or, IsOk()); StatusOr> prf_or = HkdfPrfKeyManager().GetPrimitive(key_or.value()); ASSERT_THAT(prf_or, IsOk()); StatusOr> direct_prf = subtle::HkdfStreamingPrf::New( subtle::SHA256, util::SecretDataFromStringView(key_or.value().key_value()), "salt string"); ASSERT_THAT(direct_prf, IsOk()); std::unique_ptr input = prf_or.value()->ComputePrf("input string"); std::unique_ptr direct_input = direct_prf.value()->ComputePrf("input string"); auto output_or = ReadBytesFromStream(100, input.get()); auto direct_output_or = ReadBytesFromStream(100, direct_input.get()); ASSERT_THAT(output_or, IsOk()); ASSERT_THAT(direct_output_or, IsOk()); EXPECT_THAT(output_or.value(), Eq(direct_output_or.value())); } TEST(HkdfPrfKeyManagerTest, DeriveKey) { HkdfPrfKeyFormat format; format.set_key_size(32); format.set_version(0); format.mutable_params()->set_hash(::google::crypto::tink::SHA256); util::IstreamInputStream input_stream{ absl::make_unique("0123456789abcdef0123456789abcdef")}; StatusOr key_or = HkdfPrfKeyManager().DeriveKey(format, &input_stream); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().key_value(), Eq("0123456789abcdef0123456789abcdef")); EXPECT_THAT(key_or.value().params().hash(), Eq(format.params().hash())); } TEST(HmacPrfKeyManagerTest, DeriveKeyNotEnoughRandomness) { HkdfPrfKeyFormat format; format.set_key_size(32); format.set_version(0); format.mutable_params()->set_hash(::google::crypto::tink::SHA256); util::IstreamInputStream input_stream{ absl::make_unique("0123456789abcdef")}; ASSERT_THAT(HkdfPrfKeyManager().DeriveKey(format, &input_stream).status(), Not(IsOk())); } TEST(HmacPrfKeyManagerTest, DeriveKeyWrongVersion) { HkdfPrfKeyFormat format; format.set_key_size(32); format.set_version(1); format.mutable_params()->set_hash(::google::crypto::tink::SHA256); util::IstreamInputStream input_stream{ absl::make_unique("0123456789abcdef0123456789abcdef")}; ASSERT_THAT( HkdfPrfKeyManager().DeriveKey(format, &input_stream).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("version"))); } TEST(HkdfPrfKeyManagerTest, CreatePrfSet) { HkdfPrfKeyFormat key_format; key_format.set_key_size(32); key_format.mutable_params()->set_hash(::google::crypto::tink::SHA256); key_format.mutable_params()->set_salt("salt string"); auto key_or = HkdfPrfKeyManager().CreateKey(key_format); ASSERT_THAT(key_or, IsOk()); StatusOr> prf_or = HkdfPrfKeyManager().GetPrimitive(key_or.value()); ASSERT_THAT(prf_or, IsOk()); StatusOr> direct_streaming_prf = subtle::HkdfStreamingPrf::New( subtle::SHA256, util::SecretDataFromStringView(key_or.value().key_value()), "salt string"); ASSERT_THAT(direct_streaming_prf, IsOk()); auto direct_prf = subtle::CreatePrfFromStreamingPrf( std::move(direct_streaming_prf.value())); util::StatusOr output_or = prf_or.value()->Compute("input string", 100); util::StatusOr direct_output_or = direct_prf->Compute("input string", 100); ASSERT_THAT(output_or, IsOk()); ASSERT_THAT(direct_output_or, IsOk()); EXPECT_THAT(output_or.value(), Eq(direct_output_or.value())); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/prf/hmac_prf_key_manager.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/prf/hmac_prf_key_manager.h" #include #include #include #include #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/input_stream.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/random.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/input_stream_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/hmac_prf.pb.h" namespace crypto { namespace tink { namespace { constexpr int kMinKeySizeInBytes = 16; } using google::crypto::tink::HmacPrfKey; using google::crypto::tink::HmacPrfKeyFormat; using google::crypto::tink::HmacPrfParams; using subtle::HashType; using util::Enums; using util::Status; using util::StatusOr; util::Status HmacPrfKeyManager::ValidateKey(const HmacPrfKey& key) const { util::Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; if (key.key_value().size() < kMinKeySizeInBytes) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid HmacPrfKey: key_value wrong length."); } return ValidateParams(key.params()); } util::Status HmacPrfKeyManager::ValidateKeyFormat( const HmacPrfKeyFormat& key_format) const { util::Status status = ValidateVersion(key_format.version(), get_version()); if (!status.ok()) return status; if (key_format.key_size() < kMinKeySizeInBytes) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid HmacPrfKeyFormat: invalid key_size."); } return ValidateParams(key_format.params()); } crypto::tink::util::StatusOr HmacPrfKeyManager::CreateKey( const HmacPrfKeyFormat& key_format) const { HmacPrfKey key; key.set_version(get_version()); key.set_key_value(subtle::Random::GetRandomBytes(key_format.key_size())); *(key.mutable_params()) = key_format.params(); return key; } StatusOr HmacPrfKeyManager::DeriveKey( const HmacPrfKeyFormat& hmac_prf_key_format, InputStream* input_stream) const { crypto::tink::util::Status status = ValidateKeyFormat(hmac_prf_key_format); if (!status.ok()) return status; crypto::tink::util::StatusOr randomness = ReadBytesFromStream(hmac_prf_key_format.key_size(), input_stream); if (!randomness.status().ok()) { return randomness.status(); } HmacPrfKey key; key.set_version(get_version()); *(key.mutable_params()) = hmac_prf_key_format.params(); key.set_key_value(randomness.value()); return key; } Status HmacPrfKeyManager::ValidateParams(const HmacPrfParams& params) const { static const std::set* supported_hash_types = new std::set({HashType::SHA1, HashType::SHA224, HashType::SHA256, HashType::SHA384, HashType::SHA512}); if (supported_hash_types->find(Enums::ProtoToSubtle(params.hash())) == supported_hash_types->end()) { return ToStatusF(absl::StatusCode::kInvalidArgument, "Invalid HmacParams: HashType '%s' not supported.", Enums::HashName(params.hash())); } return util::OkStatus(); } absl::optional HmacPrfKeyManager::MaxOutputLength( subtle::HashType hash_type) { static std::map* max_output_length = new std::map( {{subtle::HashType::SHA1, 20}, {subtle::HashType::SHA224, 28}, {subtle::HashType::SHA256, 32}, {subtle::HashType::SHA384, 48}, {subtle::HashType::SHA512, 64}}); auto length_it = max_output_length->find(hash_type); if (length_it == max_output_length->end()) { return absl::nullopt; } return length_it->second; } } // namespace tink } // namespace crypto ================================================ FILE: cc/prf/hmac_prf_key_manager.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_PRF_HMAC_PRF_KEY_MANAGER_H_ #define TINK_PRF_HMAC_PRF_KEY_MANAGER_H_ #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/input_stream.h" #include "tink/internal/fips_utils.h" #include "tink/key_manager.h" #include "tink/prf/prf_set.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/prf/prf_set_util.h" #include "tink/subtle/random.h" #include "tink/subtle/stateful_hmac_boringssl.h" #include "tink/util/constants.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/hmac_prf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class HmacPrfKeyManager : public KeyTypeManager> { public: class PrfFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::HmacPrfKey& key) const override { crypto::tink::subtle::HashType hash = util::Enums::ProtoToSubtle(key.params().hash()); absl::optional max_output_length = MaxOutputLength(hash); if (!max_output_length.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Unknown hash when constructing HMAC PRF ", HashType_Name(key.params().hash()))); } return subtle::CreatePrfFromStatefulMacFactory( absl::make_unique( hash, *max_output_length, util::SecretDataFromStringView(key.key_value()))); } }; HmacPrfKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::SYMMETRIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::HmacPrfKey& key) const override; crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::HmacPrfKeyFormat& key_format) const override; crypto::tink::util::StatusOr CreateKey( const google::crypto::tink::HmacPrfKeyFormat& key_format) const override; util::StatusOr DeriveKey( const google::crypto::tink::HmacPrfKeyFormat& hmac_prf_key_format, InputStream* input_stream) const override; internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: static absl::optional MaxOutputLength(subtle::HashType hash_type); util::Status ValidateParams( const google::crypto::tink::HmacPrfParams& params) const; const std::string key_type_ = absl::StrCat( kTypeGoogleapisCom, google::crypto::tink::HmacPrfKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_PRF_HMAC_PRF_KEY_MANAGER_H_ ================================================ FILE: cc/prf/hmac_prf_key_manager_test.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/prf/hmac_prf_key_manager.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/core/key_manager_impl.h" #include "tink/prf/prf_set.h" #include "tink/subtle/hmac_boringssl.h" #include "tink/util/enums.h" #include "tink/util/istream_input_stream.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/hmac_prf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::IstreamInputStream; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::HashType; using ::google::crypto::tink::HmacPrfKey; using ::google::crypto::tink::HmacPrfKeyFormat; using ::testing::HasSubstr; using ::testing::Not; using ::testing::SizeIs; using ::testing::StartsWith; namespace { TEST(HmacPrfKeyManagerTest, Basics) { EXPECT_EQ(HmacPrfKeyManager().get_version(), 0); EXPECT_EQ(HmacPrfKeyManager().get_key_type(), "type.googleapis.com/google.crypto.tink.HmacPrfKey"); EXPECT_EQ(HmacPrfKeyManager().key_material_type(), google::crypto::tink::KeyData::SYMMETRIC); } TEST(HmacPrfKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(HmacPrfKeyManager().ValidateKey(HmacPrfKey()), Not(IsOk())); } TEST(HmacPrfKeyManagerTest, ValidateEmptyKeyFormat) { EXPECT_THAT(HmacPrfKeyManager().ValidateKeyFormat(HmacPrfKeyFormat()), Not(IsOk())); } TEST(HmacPrfKeyManagerTest, ValidKeyFormat) { HmacPrfKeyFormat key_format; key_format.mutable_params()->set_hash(HashType::SHA256); key_format.set_key_size(16); EXPECT_THAT(HmacPrfKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(HmacPrfKeyManagerTest, InvalidKeyFormatShortKey) { HmacPrfKeyFormat key_format; key_format.mutable_params()->set_hash(HashType::SHA512); key_format.set_key_size(15); EXPECT_THAT(HmacPrfKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(HmacPrfKeyManagerTest, CreateKey) { HmacPrfKeyFormat key_format; key_format.set_key_size(16); key_format.mutable_params()->set_hash(HashType::SHA512); auto hmac_key_or = HmacPrfKeyManager().CreateKey(key_format); ASSERT_THAT(hmac_key_or, IsOk()); EXPECT_EQ(hmac_key_or.value().version(), 0); EXPECT_EQ(hmac_key_or.value().params().hash(), key_format.params().hash()); EXPECT_THAT(hmac_key_or.value().key_value(), SizeIs(key_format.key_size())); EXPECT_THAT(HmacPrfKeyManager().ValidateKey(hmac_key_or.value()), IsOk()); } TEST(HmacPrfKeyManagerTest, ValidKey) { HmacPrfKey key; key.set_version(0); key.mutable_params()->set_hash(HashType::SHA256); key.set_key_value("0123456789abcdef"); EXPECT_THAT(HmacPrfKeyManager().ValidateKey(key), IsOk()); } TEST(HmacPrfKeyManagerTest, ValidateKeyShortKey) { HmacPrfKey key; key.set_version(0); key.mutable_params()->set_hash(HashType::SHA256); key.set_key_value("0123456789abcde"); EXPECT_THAT(HmacPrfKeyManager().ValidateKey(key), Not(IsOk())); } TEST(HmacPrfKeyManagerTest, DeriveKey) { HmacPrfKeyFormat format; format.set_key_size(23); format.set_version(0); format.mutable_params()->set_hash(HashType::SHA256); IstreamInputStream input_stream{ absl::make_unique("0123456789abcdefghijklmnop")}; StatusOr key_or = HmacPrfKeyManager().DeriveKey(format, &input_stream); ASSERT_THAT(key_or, IsOk()); EXPECT_EQ(key_or.value().key_value(), "0123456789abcdefghijklm"); EXPECT_EQ(key_or.value().params().hash(), format.params().hash()); } TEST(HmacPrfKeyManagerTest, DeriveKeyNotEnoughRandomness) { HmacPrfKeyFormat format; format.set_key_size(17); format.set_version(0); format.mutable_params()->set_hash(HashType::SHA256); IstreamInputStream input_stream{ absl::make_unique("0123456789abcdef")}; ASSERT_THAT(HmacPrfKeyManager().DeriveKey(format, &input_stream).status(), Not(IsOk())); } TEST(HmacPrfKeyManagerTest, DeriveKeyWrongVersion) { HmacPrfKeyFormat format; format.set_key_size(16); format.set_version(1); format.mutable_params()->set_hash(HashType::SHA256); IstreamInputStream input_stream{ absl::make_unique("0123456789abcdef")}; ASSERT_THAT( HmacPrfKeyManager().DeriveKey(format, &input_stream).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("version"))); } TEST(HmacPrfKeyManagerTest, GetPrimitive) { HmacPrfKeyFormat key_format; key_format.mutable_params()->set_hash(HashType::SHA256); key_format.set_key_size(16); HmacPrfKey key = HmacPrfKeyManager().CreateKey(key_format).value(); auto manager_mac_or = HmacPrfKeyManager().GetPrimitive(key); ASSERT_THAT(manager_mac_or, IsOk()); auto prf_value_or = manager_mac_or.value()->Compute("some plaintext", 16); ASSERT_THAT(prf_value_or, IsOk()); auto direct_prf_or = subtle::HmacBoringSsl::New( util::Enums::ProtoToSubtle(key.params().hash()), 16, util::SecretDataFromStringView(key.key_value())); ASSERT_THAT(direct_prf_or, IsOk()); auto direct_prf_value_or = direct_prf_or.value()->ComputeMac("some plaintext"); ASSERT_THAT(direct_prf_value_or, IsOk()); EXPECT_THAT(direct_prf_value_or.value(), StartsWith(prf_value_or.value())); } TEST(HmacPrfKeyManagerTest, GetPrimitiveAllHashTypes) { for (HashType hash : {HashType::SHA1, HashType::SHA224, HashType::SHA256, HashType::SHA384, HashType::SHA512}) { SCOPED_TRACE(absl::StrCat("HashType: " + HashType_Name(hash))); HmacPrfKeyFormat key_format; key_format.mutable_params()->set_hash(HashType::SHA256); key_format.set_key_size(16); HmacPrfKey key = HmacPrfKeyManager().CreateKey(key_format).value(); auto manager_mac_or = HmacPrfKeyManager().GetPrimitive(key); ASSERT_THAT(manager_mac_or, IsOk()); EXPECT_THAT(manager_mac_or.value()->Compute("some plaintext", 16), IsOkAndHolds(SizeIs(16))); } } TEST(HmacPrfKeyManagerTest, GetPrimitiveUnknownHash) { HmacPrfKey key; key.set_version(0); key.mutable_params()->set_hash(HashType::UNKNOWN_HASH); key.set_key_value("0123456789abcdef"); util::StatusOr> prf = HmacPrfKeyManager().GetPrimitive(key); EXPECT_THAT(prf.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Unknown hash when constructing HMAC PRF"))); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/prf/internal/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "config_v0", srcs = ["config_v0.cc"], hdrs = ["config_v0.h"], include_prefix = "tink/prf/internal", deps = [ "//:configuration", "//internal:configuration_impl", "//prf:aes_cmac_prf_key_manager", "//prf:hkdf_prf_key_manager", "//prf:hmac_prf_key_manager", "//prf:prf_set_wrapper", "//util:status", "@com_google_absl//absl/memory", ], ) cc_library( name = "key_gen_config_v0", srcs = ["key_gen_config_v0.cc"], hdrs = ["key_gen_config_v0.h"], include_prefix = "tink/prf/internal", deps = [ "//:key_gen_configuration", "//internal:key_gen_configuration_impl", "//prf:aes_cmac_prf_key_manager", "//prf:hkdf_prf_key_manager", "//prf:hmac_prf_key_manager", "//util:status", "@com_google_absl//absl/memory", ], ) cc_test( name = "config_v0_test", srcs = ["config_v0_test.cc"], deps = [ ":config_v0", ":key_gen_config_v0", "//:configuration", "//:key_gen_configuration", "//:keyset_handle", "//internal:configuration_impl", "//internal:key_gen_configuration_impl", "//internal:key_type_info_store", "//internal:keyset_wrapper_store", "//prf:aes_cmac_prf_key_manager", "//prf:hkdf_prf_key_manager", "//prf:hmac_prf_key_manager", "//prf:prf_key_templates", "//prf:prf_set", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/prf/internal/CMakeLists.txt ================================================ tink_module(prf::internal) tink_cc_library( NAME config_v0 SRCS config_v0.cc config_v0.h DEPS absl::memory tink::core::configuration tink::internal::configuration_impl tink::prf::aes_cmac_prf_key_manager tink::prf::hkdf_prf_key_manager tink::prf::hmac_prf_key_manager tink::prf::prf_set_wrapper tink::util::status ) tink_cc_library( NAME key_gen_config_v0 SRCS key_gen_config_v0.cc key_gen_config_v0.h DEPS absl::memory tink::core::key_gen_configuration tink::internal::key_gen_configuration_impl tink::prf::aes_cmac_prf_key_manager tink::prf::hkdf_prf_key_manager tink::prf::hmac_prf_key_manager tink::util::status ) tink_cc_test( NAME config_v0_test SRCS config_v0_test.cc DEPS tink::prf::internal::config_v0 tink::prf::internal::key_gen_config_v0 gmock tink::core::configuration tink::core::key_gen_configuration tink::core::keyset_handle tink::internal::configuration_impl tink::internal::key_gen_configuration_impl tink::internal::key_type_info_store tink::internal::keyset_wrapper_store tink::prf::aes_cmac_prf_key_manager tink::prf::hkdf_prf_key_manager tink::prf::hmac_prf_key_manager tink::prf::prf_key_templates tink::prf::prf_set tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) ================================================ FILE: cc/prf/internal/config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/prf/internal/config_v0.h" #include "absl/memory/memory.h" #include "tink/configuration.h" #include "tink/internal/configuration_impl.h" #include "tink/prf/aes_cmac_prf_key_manager.h" #include "tink/prf/hkdf_prf_key_manager.h" #include "tink/prf/hmac_prf_key_manager.h" #include "tink/prf/prf_set_wrapper.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { util::Status AddPrfV0(Configuration& config) { util::Status status = ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config); if (!status.ok()) { return status; } status = ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); if (!status.ok()) { return status; } status = ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); if (!status.ok()) { return status; } return ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/prf/internal/config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_PRF_INTERNAL_CONFIG_V0_H_ #define TINK_PRF_INTERNAL_CONFIG_V0_H_ #include "tink/configuration.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { // Add recommended PRF primitive wrappers and key managers to `config`, used to // generate primitives. util::Status AddPrfV0(Configuration& config); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_PRF_INTERNAL_CONFIG_V0_H_ ================================================ FILE: cc/prf/internal/config_v0_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/prf/internal/config_v0.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/configuration.h" #include "tink/internal/configuration_impl.h" #include "tink/internal/key_gen_configuration_impl.h" #include "tink/internal/key_type_info_store.h" #include "tink/internal/keyset_wrapper_store.h" #include "tink/key_gen_configuration.h" #include "tink/keyset_handle.h" #include "tink/prf/aes_cmac_prf_key_manager.h" #include "tink/prf/hkdf_prf_key_manager.h" #include "tink/prf/hmac_prf_key_manager.h" #include "tink/prf/internal/key_gen_config_v0.h" #include "tink/prf/prf_key_templates.h" #include "tink/prf/prf_set.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::google::crypto::tink::KeyTemplate; using ::testing::Eq; using ::testing::TestWithParam; using ::testing::Values; TEST(PrfV0Test, PrimitiveWrapper) { Configuration config; ASSERT_THAT(AddPrfV0(config), IsOk()); util::StatusOr store = ConfigurationImpl::GetKeysetWrapperStore(config); ASSERT_THAT(store, IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); } TEST(PrfV0Test, KeyManagers) { Configuration config; ASSERT_THAT(AddPrfV0(config), IsOk()); util::StatusOr store = ConfigurationImpl::GetKeyTypeInfoStore(config); ASSERT_THAT(store, IsOk()); KeyGenConfiguration key_gen_config; ASSERT_THAT(AddPrfKeyGenV0(key_gen_config), IsOk()); util::StatusOr key_gen_store = KeyGenConfigurationImpl::GetKeyTypeInfoStore(key_gen_config); ASSERT_THAT(key_gen_store, IsOk()); for (const KeyTypeInfoStore* s : {*store, *key_gen_store}) { EXPECT_THAT(s->Get(AesCmacPrfKeyManager().get_key_type()), IsOk()); EXPECT_THAT(s->Get(HkdfPrfKeyManager().get_key_type()), IsOk()); EXPECT_THAT(s->Get(HmacPrfKeyManager().get_key_type()), IsOk()); } } using PrfV0KeyTypesTest = TestWithParam; INSTANTIATE_TEST_SUITE_P(PrfV0KeyTypesTestSuite, PrfV0KeyTypesTest, Values(PrfKeyTemplates::AesCmac(), PrfKeyTemplates::HkdfSha256(), PrfKeyTemplates::HmacSha256())); TEST_P(PrfV0KeyTypesTest, GetPrimitive) { KeyGenConfiguration key_gen_config; ASSERT_THAT(AddPrfKeyGenV0(key_gen_config), IsOk()); Configuration config; ASSERT_THAT(AddPrfV0(config), IsOk()); util::StatusOr> handle = KeysetHandle::GenerateNew(GetParam(), key_gen_config); ASSERT_THAT(handle, IsOk()); util::StatusOr> prf = (*handle)->GetPrimitive(config); ASSERT_THAT(prf, IsOk()); size_t output_length = 16; util::StatusOr output = (*prf)->ComputePrimary("input", output_length); ASSERT_THAT(output, IsOk()); EXPECT_THAT((*output).length(), Eq(output_length)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/prf/internal/key_gen_config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/prf/internal/key_gen_config_v0.h" #include "absl/memory/memory.h" #include "tink/internal/key_gen_configuration_impl.h" #include "tink/key_gen_configuration.h" #include "tink/prf/aes_cmac_prf_key_manager.h" #include "tink/prf/hkdf_prf_key_manager.h" #include "tink/prf/hmac_prf_key_manager.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { util::Status AddPrfKeyGenV0(KeyGenConfiguration& config) { util::Status status = KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); if (!status.ok()) { return status; } status = KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); if (!status.ok()) { return status; } return KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/prf/internal/key_gen_config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_PRF_INTERNAL_KEY_GEN_CONFIG_V0_H_ #define TINK_PRF_INTERNAL_KEY_GEN_CONFIG_V0_H_ #include "tink/key_gen_configuration.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { // Add recommended PRF key managers to `config`, used to generate keys. util::Status AddPrfKeyGenV0(KeyGenConfiguration& config); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_PRF_INTERNAL_KEY_GEN_CONFIG_V0_H_ ================================================ FILE: cc/prf/key_gen_config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/prf/key_gen_config_v0.h" #include "absl/log/check.h" #include "tink/key_gen_configuration.h" #include "tink/prf/internal/key_gen_config_v0.h" namespace crypto { namespace tink { const KeyGenConfiguration& KeyGenConfigPrfV0() { static const KeyGenConfiguration* instance = [] { static KeyGenConfiguration* config = new KeyGenConfiguration(); CHECK_OK(internal::AddPrfKeyGenV0(*config)); return config; }(); return *instance; } } // namespace tink } // namespace crypto ================================================ FILE: cc/prf/key_gen_config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_PRF_KEY_GEN_CONFIG_V0_H_ #define TINK_PRF_KEY_GEN_CONFIG_V0_H_ #include "tink/key_gen_configuration.h" namespace crypto { namespace tink { // KeyGenConfiguration used to generate PRF keys with recommended key managers. const KeyGenConfiguration& KeyGenConfigPrfV0(); } // namespace tink } // namespace crypto #endif // TINK_PRF_KEY_GEN_CONFIG_V0_H_ ================================================ FILE: cc/prf/prf_config.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/prf/prf_config.h" #include "absl/memory/memory.h" #include "tink/config/tink_fips.h" #include "tink/prf/aes_cmac_prf_key_manager.h" #include "tink/prf/hkdf_prf_key_manager.h" #include "tink/prf/hmac_prf_key_manager.h" #include "tink/prf/prf_set_wrapper.h" #include "tink/registry.h" #include "tink/util/status.h" namespace crypto { namespace tink { crypto::tink::util::Status PrfConfig::Register() { // Register primitive wrapper. auto status = Registry::RegisterPrimitiveWrapper(absl::make_unique()); if (!status.ok()) return status; status = Registry::RegisterKeyTypeManager( absl::make_unique(), true); if (!status.ok()) return status; // When using FIPS only mode do not register other key managers. if (IsFipsModeEnabled()) return util::OkStatus(); status = Registry::RegisterKeyTypeManager( absl::make_unique(), true); if (!status.ok()) return status; status = Registry::RegisterKeyTypeManager( absl::make_unique(), true); if (!status.ok()) { return status; } return util::OkStatus(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/prf/prf_config.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_PRF_PRF_CONFIG_H_ #define TINK_PRF_PRF_CONFIG_H_ #include "tink/util/status.h" #include "proto/tink.pb.h" /////////////////////////////////////////////////////////////////////////////// // Static methods and constants for registering with the Registry // all instances of Prf key types supported in a particular release of Tink. namespace crypto { namespace tink { class PrfConfig { public: // Registers Prf key managers for all Prf key types from the current Tink // release. static crypto::tink::util::Status Register(); }; } // namespace tink } // namespace crypto #endif // TINK_PRF_PRF_CONFIG_H_ ================================================ FILE: cc/prf/prf_config_test.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/prf/prf_config.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/config/global_registry.h" #include "tink/internal/fips_utils.h" #include "tink/keyset_handle.h" #include "tink/prf/hmac_prf_key_manager.h" #include "tink/prf/prf_key_templates.h" #include "tink/prf/prf_set.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; class PrfConfigTest : public ::testing::Test { protected: void SetUp() override { Registry::Reset(); } }; TEST_F(PrfConfigTest, RegisterWorks) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT(Registry::get_key_manager(HmacPrfKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT(PrfConfig::Register(), IsOk()); EXPECT_THAT(Registry::get_key_manager(HmacPrfKeyManager().get_key_type()) .status(), IsOk()); } // FIPS-only mode tests TEST_F(PrfConfigTest, RegisterNonFipsTemplates) { if (!internal::IsFipsModeEnabled() || !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only supported in FIPS-only mode"; } EXPECT_THAT(PrfConfig::Register(), IsOk()); std::list non_fips_key_templates; non_fips_key_templates.push_back(PrfKeyTemplates::HkdfSha256()); non_fips_key_templates.push_back(PrfKeyTemplates::AesCmac()); for (auto key_template : non_fips_key_templates) { auto new_keyset_handle_result = KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()); EXPECT_THAT(new_keyset_handle_result.status(), StatusIs(absl::StatusCode::kNotFound)); } } TEST_F(PrfConfigTest, RegisterFipsValidTemplates) { if (!internal::IsFipsModeEnabled() || !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only supported in FIPS-only mode"; } EXPECT_THAT(PrfConfig::Register(), IsOk()); std::list fips_key_templates; fips_key_templates.push_back(PrfKeyTemplates::HmacSha256()); fips_key_templates.push_back(PrfKeyTemplates::HmacSha512()); for (auto key_template : fips_key_templates) { auto new_keyset_handle_result = KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()); EXPECT_THAT(new_keyset_handle_result, IsOk()); } } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/prf/prf_key_templates.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/prf/prf_key_templates.h" #include #include #include "absl/memory/memory.h" #include "tink/prf/aes_cmac_prf_key_manager.h" #include "tink/prf/hkdf_prf_key_manager.h" #include "tink/prf/hmac_prf_key_manager.h" #include "proto/aes_cmac_prf.pb.h" #include "proto/hkdf_prf.pb.h" #include "proto/hmac_prf.pb.h" namespace crypto { namespace tink { namespace { using google::crypto::tink::AesCmacPrfKeyFormat; using google::crypto::tink::HkdfPrfKeyFormat; using google::crypto::tink::HmacPrfKeyFormat; std::unique_ptr NewHkdfSha256Template() { auto key_template = absl::make_unique(); auto hkdf_prf_key_manager = absl::make_unique(); key_template->set_type_url(hkdf_prf_key_manager->get_key_type()); key_template->set_output_prefix_type( google::crypto::tink::OutputPrefixType::RAW); HkdfPrfKeyFormat key_format; key_format.set_key_size(32); key_format.set_version(hkdf_prf_key_manager->get_version()); key_format.mutable_params()->set_hash(google::crypto::tink::HashType::SHA256); key_format.SerializeToString(key_template->mutable_value()); return key_template; } std::unique_ptr NewHmacTemplate( google::crypto::tink::HashType hash_type, uint32_t key_size) { auto key_template = absl::make_unique(); auto hmac_prf_key_manager = absl::make_unique(); key_template->set_type_url(hmac_prf_key_manager->get_key_type()); key_template->set_output_prefix_type( google::crypto::tink::OutputPrefixType::RAW); HmacPrfKeyFormat key_format; key_format.set_key_size(key_size); key_format.set_version(hmac_prf_key_manager->get_version()); key_format.mutable_params()->set_hash(hash_type); key_format.SerializeToString(key_template->mutable_value()); return key_template; } std::unique_ptr NewAesCmacTemplate() { auto key_template = absl::make_unique(); auto aes_cmac_prf_key_manager = absl::make_unique(); key_template->set_type_url(aes_cmac_prf_key_manager->get_key_type()); key_template->set_output_prefix_type( google::crypto::tink::OutputPrefixType::RAW); AesCmacPrfKeyFormat key_format; key_format.set_version(aes_cmac_prf_key_manager->get_version()); key_format.set_key_size(32); key_format.SerializeToString(key_template->mutable_value()); return key_template; } } // namespace const google::crypto::tink::KeyTemplate& PrfKeyTemplates::HkdfSha256() { static const google::crypto::tink::KeyTemplate* key_template = NewHkdfSha256Template().release(); return *key_template; } const google::crypto::tink::KeyTemplate& PrfKeyTemplates::HmacSha256() { static const google::crypto::tink::KeyTemplate* key_template = NewHmacTemplate(google::crypto::tink::HashType::SHA256, 32).release(); return *key_template; } const google::crypto::tink::KeyTemplate& PrfKeyTemplates::HmacSha512() { static const google::crypto::tink::KeyTemplate* key_template = NewHmacTemplate(google::crypto::tink::HashType::SHA512, 64).release(); return *key_template; } const google::crypto::tink::KeyTemplate& PrfKeyTemplates::AesCmac() { static const google::crypto::tink::KeyTemplate* key_template = NewAesCmacTemplate().release(); return *key_template; } } // namespace tink } // namespace crypto ================================================ FILE: cc/prf/prf_key_templates.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_PRF_PRF_KEY_TEMPLATES_H_ #define TINK_PRF_PRF_KEY_TEMPLATES_H_ #include "proto/tink.pb.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Pre-generated KeyTemplate for Prf key types. One can use these templates // to generate new KeysetHandle object with fresh keys. // To generate a new keyset that contains a single HkdfPrfKey, one can do: // // auto handle_result = // KeysetHandle::GenerateNew(PrfKeyTemplates::HkdfSha256()); // if (!handle_result.ok()) { /* fail with error */ } // auto keyset_handle = std::move(handle_result.value()); class PrfKeyTemplates { public: // Hkdf // * Hash function: SHA256 // * Key size: 256 bit // * Salt: empty static const google::crypto::tink::KeyTemplate& HkdfSha256(); static const google::crypto::tink::KeyTemplate& HmacSha256(); static const google::crypto::tink::KeyTemplate& HmacSha512(); static const google::crypto::tink::KeyTemplate& AesCmac(); }; } // namespace tink } // namespace crypto #endif // TINK_PRF_PRF_KEY_TEMPLATES_H_ ================================================ FILE: cc/prf/prf_key_templates_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/prf/prf_key_templates.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "tink/prf/aes_cmac_prf_key_manager.h" #include "tink/prf/hkdf_prf_key_manager.h" #include "tink/prf/hmac_prf_key_manager.h" #include "tink/util/test_matchers.h" #include "proto/aes_cmac_prf.pb.h" #include "proto/hkdf_prf.pb.h" #include "proto/hmac_prf.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::google::crypto::tink::HkdfPrfKeyFormat; using ::testing::Eq; using ::testing::Ref; TEST(HkdfSha256HkdfTest, Basics) { EXPECT_THAT(PrfKeyTemplates::HkdfSha256().type_url(), Eq("type.googleapis.com/google.crypto.tink.HkdfPrfKey")); EXPECT_THAT(PrfKeyTemplates::HkdfSha256().type_url(), Eq(HkdfPrfKeyManager().get_key_type())); } TEST(HkdfSha256HkdfTest, OutputPrefixType) { EXPECT_THAT(PrfKeyTemplates::HkdfSha256().output_prefix_type(), Eq(google::crypto::tink::OutputPrefixType::RAW)); } TEST(HkdfSha256HkdfTest, MultipleCallsSameReference) { EXPECT_THAT(PrfKeyTemplates::HkdfSha256(), Ref(PrfKeyTemplates::HkdfSha256())); } TEST(HkdfSha256HkdfTest, WorksWithKeyTypeManager) { const google::crypto::tink::KeyTemplate& key_template = PrfKeyTemplates::HkdfSha256(); HkdfPrfKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(HkdfPrfKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(HmacPrfTest, Basics) { EXPECT_THAT(PrfKeyTemplates::HmacSha256().type_url(), Eq("type.googleapis.com/google.crypto.tink.HmacPrfKey")); EXPECT_THAT(PrfKeyTemplates::HmacSha512().type_url(), Eq("type.googleapis.com/google.crypto.tink.HmacPrfKey")); auto manager = absl::make_unique(); EXPECT_THAT(PrfKeyTemplates::HmacSha256().type_url(), Eq(manager->get_key_type())); google::crypto::tink::HmacPrfKeyFormat format; ASSERT_TRUE(format.ParseFromString(PrfKeyTemplates::HmacSha256().value())); EXPECT_THAT(manager->ValidateKeyFormat(format), IsOk()); ASSERT_TRUE(format.ParseFromString(PrfKeyTemplates::HmacSha512().value())); EXPECT_THAT(manager->ValidateKeyFormat(format), IsOk()); } TEST(HmacPrfTest, OutputPrefixType) { EXPECT_THAT(PrfKeyTemplates::HmacSha256().output_prefix_type(), Eq(google::crypto::tink::OutputPrefixType::RAW)); EXPECT_THAT(PrfKeyTemplates::HmacSha512().output_prefix_type(), Eq(google::crypto::tink::OutputPrefixType::RAW)); } TEST(HmacPrfTest, MultipleCallsSameReference) { EXPECT_THAT(PrfKeyTemplates::HmacSha256(), Ref(PrfKeyTemplates::HmacSha256())); EXPECT_THAT(PrfKeyTemplates::HmacSha512(), Ref(PrfKeyTemplates::HmacSha512())); } TEST(CmacPrfTest, Basics) { EXPECT_THAT(PrfKeyTemplates::AesCmac().type_url(), Eq("type.googleapis.com/google.crypto.tink.AesCmacPrfKey")); auto manager = absl::make_unique(); EXPECT_THAT(PrfKeyTemplates::AesCmac().type_url(), Eq(manager->get_key_type())); google::crypto::tink::AesCmacPrfKeyFormat format; ASSERT_TRUE(format.ParseFromString(PrfKeyTemplates::AesCmac().value())); EXPECT_THAT(manager->ValidateKeyFormat(format), IsOk()); } TEST(CmacPrfTest, OutputPrefixType) { EXPECT_THAT(PrfKeyTemplates::AesCmac().output_prefix_type(), Eq(google::crypto::tink::OutputPrefixType::RAW)); } TEST(CmacPrfTest, MultipleCallsSameReference) { EXPECT_THAT(PrfKeyTemplates::AesCmac(), Ref(PrfKeyTemplates::AesCmac())); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/prf/prf_set.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/prf/prf_set.h" #include #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { util::StatusOr PrfSet::ComputePrimary(absl::string_view input, size_t output_length) const { auto prfs = GetPrfs(); auto prf_it = prfs.find(GetPrimaryId()); if (prf_it == prfs.end()) { return util::Status(absl::StatusCode::kInternal, "PrfSet has no PRF for primary ID."); } return prf_it->second->Compute(input, output_length); } } // namespace tink } // namespace crypto ================================================ FILE: cc/prf/prf_set.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_PRF_PRF_SET_H_ #define TINK_PRF_PRF_SET_H_ #include #include #include #include #include "absl/strings/string_view.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // The PRF interface is an abstraction for an element of a pseudo random // function family, selected by a key. It has the following properties: // * It is deterministic. PRF.compute(input, length) will always return the // same output if the same key is used. PRF.compute(input, length1) will be // a prefix of PRF.compute(input, length2) if length1 < length2 and the same // key is used. // * It is indistinguishable from a random function: // Given the evaluation of n different inputs, an attacker cannot // distinguish between the PRF and random bytes on an input different from // the n that are known. // Use cases for PRF are deterministic redaction of PII, keyed hash functions, // creating sub IDs that do not allow joining with the original dataset without // knowing the key. // While PRFs can be used in order to prove authenticity of a message, using the // MAC interface is recommended for that use case, as it has support for // verification, avoiding the security problems that often happen during // verification, and having automatic support for key rotation. It also allows // for non-deterministic MAC algorithms. class Prf { public: virtual ~Prf() = default; // Computes the PRF selected by the underlying key on input and // returns the first outputLength bytes. // When choosing this parameter keep the birthday paradox in mind. // If you have 2^n different inputs that your system has to handle // set the output length (in bytes) to at least // ceil(n/4 + 4) // This corresponds to 2*n + 32 bits, meaning a collision will occur with // a probability less than 1:2^32. When in doubt, request a security review. // Returns a non ok status if the algorithm fails or if the output of // algorithm is less than outputLength. virtual util::StatusOr Compute(absl::string_view input, size_t output_length) const = 0; }; // A Tink Keyset can be converted into a set of PRFs using this primitive. Every // key in the keyset corresponds to a PRF in the PRFSet. // Every PRF in the set is given an ID, which is the same ID as the key id in // the Keyset. class PrfSet { public: virtual ~PrfSet() = default; // The primary ID of the keyset. virtual uint32_t GetPrimaryId() const = 0; // A map of the PRFs represented by the keys in this keyset. // The map is guaranteed to contain getPrimaryId() as a key. virtual const std::map& GetPrfs() const = 0; // Convenience method to compute the primary PRF on a given input. // See PRF.compute for details of the parameters. util::StatusOr ComputePrimary(absl::string_view input, size_t output_length) const; }; } // namespace tink } // namespace crypto #endif // TINK_PRF_PRF_SET_H_ ================================================ FILE: cc/prf/prf_set_test.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/prf/prf_set.h" #include #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/config/global_registry.h" #include "tink/keyset_handle.h" #include "tink/keyset_manager.h" #include "tink/prf/prf_config.h" #include "tink/prf/prf_key_templates.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::testing::_; using ::testing::Eq; using ::testing::Pair; using ::testing::SizeIs; using ::testing::StrEq; using ::testing::UnorderedElementsAre; class DummyPrf : public Prf { util::StatusOr Compute(absl::string_view input, size_t output_length) const override { return std::string("DummyPRF"); } }; class DummyPrfSet : public PrfSet { public: uint32_t GetPrimaryId() const override { return 1; } const std::map& GetPrfs() const override { static const std::map* prfs = new std::map({{1, dummy_.get()}}); return *prfs; } private: std::unique_ptr dummy_ = absl::make_unique(); }; class BrokenDummyPrfSet : public PrfSet { public: uint32_t GetPrimaryId() const override { return 1; } const std::map& GetPrfs() const override { static const std::map* prfs = new std::map(); return *prfs; } }; TEST(PrfSetTest, ComputePrimary) { DummyPrfSet prfset; auto output = prfset.ComputePrimary("DummyInput", 16); EXPECT_TRUE(output.ok()) << output.status(); BrokenDummyPrfSet broken_prfset; auto broken_output = broken_prfset.ComputePrimary("DummyInput", 16); EXPECT_FALSE(broken_output.ok()) << "Expected broken PrfSet to not be able to compute the primary PRF"; } TEST(PrfSetWrapperTest, TestPrimitivesEndToEnd) { auto status = PrfConfig::Register(); ASSERT_TRUE(status.ok()) << status; auto keyset_manager_result = KeysetManager::New(PrfKeyTemplates::HkdfSha256()); ASSERT_TRUE(keyset_manager_result.ok()) << keyset_manager_result.status(); auto keyset_manager = std::move(keyset_manager_result.value()); auto id_result = keyset_manager->Add(PrfKeyTemplates::HmacSha256()); ASSERT_TRUE(id_result.ok()) << id_result.status(); uint32_t hmac_sha256_id = id_result.value(); id_result = keyset_manager->Add(PrfKeyTemplates::HmacSha512()); ASSERT_TRUE(id_result.ok()) << id_result.status(); uint32_t hmac_sha512_id = id_result.value(); id_result = keyset_manager->Add(PrfKeyTemplates::AesCmac()); ASSERT_TRUE(id_result.ok()) << id_result.status(); uint32_t aes_cmac_id = id_result.value(); auto keyset_handle = keyset_manager->GetKeysetHandle(); uint32_t hkdf_id = keyset_handle->GetKeysetInfo().primary_key_id(); auto prf_set_result = keyset_handle->GetPrimitive(ConfigGlobalRegistry()); ASSERT_TRUE(prf_set_result.ok()) << prf_set_result.status(); auto prf_set = std::move(prf_set_result.value()); EXPECT_THAT(prf_set->GetPrimaryId(), Eq(hkdf_id)); auto prf_map = prf_set->GetPrfs(); EXPECT_THAT(prf_map, UnorderedElementsAre(Pair(Eq(hkdf_id), _), Pair(Eq(hmac_sha256_id), _), Pair(Eq(hmac_sha512_id), _), Pair(Eq(aes_cmac_id), _))); std::string input = "This is an input string"; std::string input2 = "This is a second input string"; std::vector output_lengths = {15, 16, 17, 31, 32, 33, 63, 64, 65, 100}; for (size_t output_length : output_lengths) { bool aes_cmac_ok = output_length <= 16; bool hmac_sha256_ok = output_length <= 32; bool hmac_sha512_ok = output_length <= 64; bool hkdf_sha256_ok = output_length <= 8192; std::vector results; for (auto prf : prf_map) { SCOPED_TRACE(absl::StrCat("Computing prf ", prf.first, " with output_length ", output_length)); bool ok = (prf.first == aes_cmac_id && aes_cmac_ok) || (prf.first == hmac_sha256_id && hmac_sha256_ok) || (prf.first == hmac_sha512_id && hmac_sha512_ok) || (prf.first == hkdf_id && hkdf_sha256_ok); auto output_result = prf.second->Compute(input, output_length); EXPECT_THAT(output_result.ok(), Eq(ok)) << output_result.status(); if (!ok) { continue; } std::string output; if (output_result.ok()) { output = output_result.value(); results.push_back(output); } output_result = prf.second->Compute(input2, output_length); EXPECT_TRUE(output_result.ok()) << output_result.status(); if (output_result.ok()) { results.push_back(output_result.value()); } output_result = prf.second->Compute(input, output_length); EXPECT_TRUE(output_result.ok()) << output_result.status(); if (output_result.ok()) { EXPECT_THAT(output_result.value(), StrEq(output)); } } for (int i = 0; i < results.size(); i++) { EXPECT_THAT(results[i], SizeIs(output_length)); EXPECT_THAT(test::ZTestUniformString(results[i]), IsOk()); EXPECT_THAT(test::ZTestAutocorrelationUniformString(results[i]), IsOk()); for (int j = i + 1; j < results.size(); j++) { EXPECT_THAT( test::ZTestCrosscorrelationUniformStrings(results[i], results[j]), IsOk()); } } } } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/prf/prf_set_wrapper.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/prf/prf_set_wrapper.h" #include #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/string_view.h" #include "tink/internal/monitoring_util.h" #include "tink/internal/registry_impl.h" #include "tink/monitoring/monitoring.h" #include "tink/prf/prf_set.h" #include "tink/primitive_set.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using google::crypto::tink::OutputPrefixType; namespace { constexpr absl::string_view kPrimitive = "prf"; constexpr absl::string_view kComputeApi = "compute"; class MonitoredPrf : public Prf { public: explicit MonitoredPrf(uint32_t key_id, const Prf* prf, MonitoringClient* monitoring_client) : key_id_(key_id), prf_(prf), monitoring_client_(monitoring_client) {} ~MonitoredPrf() override = default; MonitoredPrf(MonitoredPrf&& other) = default; MonitoredPrf& operator=(MonitoredPrf&& other) = default; MonitoredPrf(const MonitoredPrf&) = delete; MonitoredPrf& operator=(const MonitoredPrf&) = delete; util::StatusOr Compute(absl::string_view input, size_t output_length) const override { util::StatusOr result = prf_->Compute(input, output_length); if (!result.ok()) { if (monitoring_client_ != nullptr) { monitoring_client_->LogFailure(); } return result.status(); } if (monitoring_client_ != nullptr) { monitoring_client_->Log(key_id_, input.size()); } return result.value(); } private: uint32_t key_id_; const Prf* prf_; MonitoringClient* monitoring_client_; }; class PrfSetPrimitiveWrapper : public PrfSet { public: explicit PrfSetPrimitiveWrapper( std::unique_ptr> prf_set, std::unique_ptr monitoring_client = nullptr) : prf_set_(std::move(prf_set)), monitoring_client_(std::move(monitoring_client)) { wrapped_prfs_.reserve(prf_set_->get_raw_primitives().value()->size()); for (const auto& prf : *prf_set_->get_raw_primitives().value()) { std::unique_ptr wrapped_prf = std::make_unique( prf->get_key_id(), &prf->get_primitive(), monitoring_client_.get()); prfs_.insert({prf->get_key_id(), wrapped_prf.get()}); wrapped_prfs_.push_back(std::move(wrapped_prf)); } } uint32_t GetPrimaryId() const override { return prf_set_->get_primary()->get_key_id(); } const std::map& GetPrfs() const override { return prfs_; } ~PrfSetPrimitiveWrapper() override = default; private: std::unique_ptr> prf_set_; std::unique_ptr monitoring_client_; std::vector> wrapped_prfs_; std::map prfs_; }; util::Status Validate(PrimitiveSet* prf_set) { if (prf_set == nullptr) { return util::Status(absl::StatusCode::kInternal, "prf_set must be non-NULL"); } if (prf_set->get_primary() == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "prf_set has no primary"); } for (auto prf : prf_set->get_all()) { if (prf->get_output_prefix_type() != OutputPrefixType::RAW) { return util::Status(absl::StatusCode::kInvalidArgument, "PrfSet should only be used with prefix type RAW"); } } return util::OkStatus(); } } // namespace util::StatusOr> PrfSetWrapper::Wrap( std::unique_ptr> prf_set) const { util::Status status = Validate(prf_set.get()); if (!status.ok()) return status; MonitoringClientFactory* const monitoring_factory = internal::RegistryImpl::GlobalInstance().GetMonitoringClientFactory(); // Monitoring is not enabled. Create a wrapper without monitoring clients. if (monitoring_factory == nullptr) { return {absl::make_unique(std::move(prf_set))}; } util::StatusOr keyset_info = internal::MonitoringKeySetInfoFromPrimitiveSet(*prf_set); if (!keyset_info.ok()) { return keyset_info.status(); } util::StatusOr> monitoring_client = monitoring_factory->New( MonitoringContext(kPrimitive, kComputeApi, *keyset_info)); if (!monitoring_client.ok()) { return monitoring_client.status(); } return {absl::make_unique( std::move(prf_set), *std::move(monitoring_client))}; } } // namespace tink } // namespace crypto ================================================ FILE: cc/prf/prf_set_wrapper.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_PRF_PRF_SET_WRAPPER_H_ #define TINK_PRF_PRF_SET_WRAPPER_H_ #include #include #include "tink/prf/prf_set.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Wraps a set of PrfSet-instances that correspond to a keyset, // and combines them into a single PrfSet-primitive, that uses the provided // instances, by using the keysets key ID as Prf ID and computing the union of // the provided PRFs. class PrfSetWrapper : public PrimitiveWrapper { public: util::StatusOr> Wrap( std::unique_ptr> prf_set) const override; }; } // namespace tink } // namespace crypto #endif // TINK_PRF_PRF_SET_WRAPPER_H_ ================================================ FILE: cc/prf/prf_set_wrapper_test.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/prf/prf_set_wrapper.h" #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_map.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/internal/registry_impl.h" #include "tink/monitoring/monitoring.h" #include "tink/monitoring/monitoring_client_mocks.h" #include "tink/prf/prf_set.h" #include "tink/primitive_set.h" #include "tink/registry.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::google::crypto::tink::KeysetInfo; using ::google::crypto::tink::KeyStatusType; using ::testing::_; using ::testing::ByMove; using ::testing::Key; using ::testing::NiceMock; using ::testing::Not; using ::testing::Return; using ::testing::StrEq; using ::testing::Test; using ::testing::UnorderedElementsAre; KeysetInfo::KeyInfo MakeKey(uint32_t id) { KeysetInfo::KeyInfo key; key.set_output_prefix_type(google::crypto::tink::OutputPrefixType::RAW); key.set_key_id(id); key.set_status(KeyStatusType::ENABLED); return key; } class FakePrf : public Prf { public: explicit FakePrf(const std::string& output) : output_(output) {} util::StatusOr Compute(absl::string_view input, size_t output_length) const override { return output_; } private: std::string output_; }; class PrfSetWrapperTest : public ::testing::Test { protected: void SetUp() override { prf_set_ = absl::make_unique>(); } util::StatusOr::Entry*> AddPrf( const std::string& output, const KeysetInfo::KeyInfo& key_info) { auto prf = absl::make_unique(output); return prf_set_->AddPrimitive(std::move(prf), key_info); } std::unique_ptr>& PrfSet() { return prf_set_; } private: std::unique_ptr> prf_set_; }; TEST_F(PrfSetWrapperTest, NullPrfSet) { PrfSetWrapper wrapper; EXPECT_THAT(wrapper.Wrap(nullptr), Not(IsOk())); } TEST_F(PrfSetWrapperTest, EmptyPrfSet) { PrfSetWrapper wrapper; EXPECT_THAT(wrapper.Wrap(absl::make_unique>()).status(), Not(IsOk())); } TEST_F(PrfSetWrapperTest, NonRawKeyType) { KeysetInfo::KeyInfo key_info = MakeKey(1); key_info.set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); auto entry = AddPrf("output", key_info); ASSERT_THAT(entry, IsOk()); ASSERT_THAT(PrfSet()->set_primary(entry.value()), IsOk()); PrfSetWrapper wrapper; EXPECT_THAT(wrapper.Wrap(std::move(PrfSet())), Not(IsOk())); } TEST_F(PrfSetWrapperTest, WrapOkay) { auto entry = AddPrf("output", MakeKey(1)); ASSERT_THAT(entry, IsOk()); ASSERT_THAT(PrfSet()->set_primary(entry.value()), IsOk()); PrfSetWrapper wrapper; auto wrapped = wrapper.Wrap(std::move(PrfSet())); ASSERT_THAT(wrapped, IsOk()); EXPECT_THAT(wrapped.value()->ComputePrimary("input", 6), IsOkAndHolds(StrEq("output"))); } TEST_F(PrfSetWrapperTest, WrapTwo) { std::string primary_output("output"); auto entry = AddPrf(primary_output, MakeKey(1)); ASSERT_THAT(entry, IsOk()); ASSERT_THAT(PrfSet()->set_primary(entry.value()), IsOk()); ASSERT_THAT(AddPrf(primary_output, MakeKey(1)), IsOk()); std::string secondary_output("different"); ASSERT_THAT(AddPrf(secondary_output, MakeKey(2)), IsOk()); PrfSetWrapper wrapper; auto wrapped_or = wrapper.Wrap(std::move(PrfSet())); ASSERT_THAT(wrapped_or, IsOk()); auto wrapped = std::move(wrapped_or.value()); EXPECT_THAT(wrapped->ComputePrimary("input", 6), IsOkAndHolds(StrEq("output"))); const auto& prf_map = wrapped->GetPrfs(); ASSERT_THAT(prf_map, UnorderedElementsAre(Key(1), Key(2))); EXPECT_THAT(prf_map.find(1)->second->Compute("input", 6), IsOkAndHolds(StrEq("output"))); EXPECT_THAT(prf_map.find(2)->second->Compute("input", 6), IsOkAndHolds(StrEq("different"))); } // Tests for the monitoring behavior. class PrfSetWrapperWithMonitoringTest : public Test { protected: // Reset the global registry. void SetUp() override { Registry::Reset(); // Setup mocks for catching Monitoring calls. auto monitoring_client_factory = absl::make_unique(); auto monitoring_client = absl::make_unique>(); monitoring_client_ref_ = monitoring_client.get(); // Monitoring tests expect that the client factory will create the // corresponding MockMonitoringClients. EXPECT_CALL(*monitoring_client_factory, New(_)) .WillOnce( Return(ByMove(util::StatusOr>( std::move(monitoring_client))))); ASSERT_THAT(internal::RegistryImpl::GlobalInstance() .RegisterMonitoringClientFactory( std::move(monitoring_client_factory)), IsOk()); ASSERT_THAT( internal::RegistryImpl::GlobalInstance().GetMonitoringClientFactory(), Not(testing::IsNull())); } // Cleanup the registry to avoid mock leaks. ~PrfSetWrapperWithMonitoringTest() override { Registry::Reset(); } NiceMock* monitoring_client_ref_; }; class AlwaysFailingPrf : public Prf { public: AlwaysFailingPrf() = default; util::StatusOr Compute(absl::string_view input, size_t output_length) const override { return util::Status(absl::StatusCode::kOutOfRange, "AlwaysFailingPrf"); } }; TEST_F(PrfSetWrapperWithMonitoringTest, WrapKeysetWithMonitoringFailure) { const absl::flat_hash_map annotations = { {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}}; auto primitive_set = absl::make_unique>(annotations); util::StatusOr::Entry*> entry = primitive_set->AddPrimitive(absl::make_unique(), MakeKey(/*id=*/1)); ASSERT_THAT(entry, IsOk()); ASSERT_THAT(primitive_set->set_primary(entry.value()), IsOk()); ASSERT_THAT(primitive_set ->AddPrimitive(absl::make_unique("output"), MakeKey(/*id=*/1)) .status(), IsOk()); util::StatusOr> prf_set = PrfSetWrapper().Wrap(std::move(primitive_set)); ASSERT_THAT(prf_set, IsOk()); EXPECT_CALL(*monitoring_client_ref_, LogFailure()); EXPECT_THAT((*prf_set)->ComputePrimary("input", /*output_length=*/16), Not(IsOk())); } TEST_F(PrfSetWrapperWithMonitoringTest, WrapKeysetWithMonitoringVerifySuccess) { const absl::flat_hash_map annotations = { {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}}; auto primitive_set = absl::make_unique>(annotations); util::StatusOr::Entry*> entry = primitive_set->AddPrimitive(absl::make_unique("output"), MakeKey(/*id=*/1)); ASSERT_THAT(entry, IsOk()); ASSERT_THAT(primitive_set->set_primary(entry.value()), IsOk()); ASSERT_THAT(primitive_set ->AddPrimitive(absl::make_unique("output"), MakeKey(/*id=*/1)) .status(), IsOk()); util::StatusOr> prf_set = PrfSetWrapper().Wrap(std::move(primitive_set)); ASSERT_THAT(prf_set, IsOk()); std::map prf_map = (*prf_set)->GetPrfs(); std::string input = "input"; for (const auto& entry : prf_map) { EXPECT_CALL(*monitoring_client_ref_, Log(entry.first, input.size())); EXPECT_THAT((entry.second)->Compute(input, /*output_length=*/16).status(), IsOk()); } input = "hello_world"; EXPECT_CALL(*monitoring_client_ref_, Log((*prf_set)->GetPrimaryId(), input.size())); EXPECT_THAT((*prf_set)->ComputePrimary(input, /*output_length=*/16), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/prf/subtle/BUILD.bazel ================================================ licenses(["notice"]) ================================================ FILE: cc/prf/subtle/CMakeLists.txt ================================================ ================================================ FILE: cc/primitive_set.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_PRIMITIVE_SET_H_ #define TINK_PRIMITIVE_SET_H_ #include #include #include #include #include #include #include "absl/base/attributes.h" #include "absl/base/thread_annotations.h" #include "absl/container/flat_hash_map.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" #include "tink/crypto_format.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // A container class for a set of primitives (i.e. implementations of // cryptographic primitives offered by Tink). It provides also // additional properties for the primitives it holds. In particular, // one of the primitives in the set can be distinguished as "the // primary" one. // // PrimitiveSet is an auxiliary class used for supporting key rotation: // primitives in a set correspond to keys in a keyset. Users will // usually work with primitive instances, which essentially wrap // primitive sets. For example an instance of an Aead-primitive for a // given keyset holds a set of Aead-primitivies corresponding to the // keys in the keyset, and uses the set members to do the actual // crypto operations: to encrypt data the primary Aead-primitive from // the set is used, and upon decryption the ciphertext's prefix // determines the identifier of the primitive from the set. // // PrimitiveSet is a public class to allow its use in implementations // of custom primitives. template class PrimitiveSet { public: // Entry-objects hold individual instances of primitives in the set. template class Entry { public: static crypto::tink::util::StatusOr>> New( std::unique_ptr

primitive, const google::crypto::tink::KeysetInfo::KeyInfo& key_info) { if (key_info.status() != google::crypto::tink::KeyStatusType::ENABLED) { return util::Status(absl::StatusCode::kInvalidArgument, "The key must be ENABLED."); } auto identifier_result = CryptoFormat::GetOutputPrefix(key_info); if (!identifier_result.ok()) return identifier_result.status(); if (primitive == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "The primitive must be non-null."); } std::string identifier = identifier_result.value(); return absl::WrapUnique(new Entry(std::move(primitive), identifier, key_info.status(), key_info.key_id(), key_info.output_prefix_type(), key_info.type_url())); } P2& get_primitive() const { return *primitive_; } const std::string& get_identifier() const { return identifier_; } google::crypto::tink::KeyStatusType get_status() const { return status_; } uint32_t get_key_id() const { return key_id_; } google::crypto::tink::OutputPrefixType get_output_prefix_type() const { return output_prefix_type_; } absl::string_view get_key_type_url() const { return key_type_url_; } private: Entry(std::unique_ptr primitive, const std::string& identifier, google::crypto::tink::KeyStatusType status, uint32_t key_id, google::crypto::tink::OutputPrefixType output_prefix_type, absl::string_view key_type_url) : primitive_(std::move(primitive)), identifier_(identifier), status_(status), key_id_(key_id), output_prefix_type_(output_prefix_type), key_type_url_(key_type_url) {} std::unique_ptr

primitive_; std::string identifier_; google::crypto::tink::KeyStatusType status_; uint32_t key_id_; google::crypto::tink::OutputPrefixType output_prefix_type_; const std::string key_type_url_; }; typedef std::vector>> Primitives; typedef absl::flat_hash_map CiphertextPrefixToPrimitivesMap; private: // Helper methods for mutations, used by the Builder and the deprecated // mutation methods on PrimitiveSet. static crypto::tink::util::Status SetPrimaryImpl( Entry

** output, Entry

* primary, const CiphertextPrefixToPrimitivesMap& primitives) { if (!primary) { return util::Status(absl::StatusCode::kInvalidArgument, "The primary primitive must be non-null."); } if (primary->get_status() != google::crypto::tink::KeyStatusType::ENABLED) { return util::Status(absl::StatusCode::kInvalidArgument, "Primary has to be enabled."); } if (primitives.count(primary->get_identifier()) == 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Primary cannot be set to an entry which is " "not held by this primitive set."); } *output = primary; return crypto::tink::util::OkStatus(); } static crypto::tink::util::StatusOr*> AddPrimitiveImpl( std::unique_ptr

primitive, const google::crypto::tink::KeysetInfo::KeyInfo& key_info, CiphertextPrefixToPrimitivesMap& primitives, std::vector*>& primitives_in_keyset_order) { auto entry_or = Entry

::New(std::move(primitive), key_info); if (!entry_or.ok()) return entry_or.status(); std::string identifier = entry_or.value()->get_identifier(); primitives[identifier].push_back(std::move(entry_or.value())); Entry

* stored_entry = primitives[identifier].back().get(); primitives_in_keyset_order.push_back(stored_entry); return stored_entry; } public: // Builder is used to construct PrimitiveSet objects. Objects returned by // the builder are immutable. Calling any of the non-const methods on them // will fail. class Builder { public: // Adds 'primitive' to this set for the specified 'key'. Builder& AddPrimitive( std::unique_ptr

primitive, const google::crypto::tink::KeysetInfo::KeyInfo& key_info) & { absl::MutexLock lock(&mutex_); if (!status_.ok()) return *this; status_ = AddPrimitiveImpl(std::move(primitive), key_info, primitives_, primitives_in_keyset_order_) .status(); return *this; } Builder&& AddPrimitive( std::unique_ptr

primitive, const google::crypto::tink::KeysetInfo::KeyInfo& key_info) && { return std::move(AddPrimitive(std::move(primitive), key_info)); } // Adds 'primitive' to this set for the specified 'key' and marks it // primary. Builder& AddPrimaryPrimitive( std::unique_ptr

primitive, const google::crypto::tink::KeysetInfo::KeyInfo& key_info) & { absl::MutexLock lock(&mutex_); if (!status_.ok()) return *this; auto entry_result = AddPrimitiveImpl(std::move(primitive), key_info, primitives_, primitives_in_keyset_order_); if (!entry_result.ok()) { status_ = entry_result.status(); return *this; } status_ = SetPrimaryImpl(&primary_, entry_result.value(), primitives_); return *this; } Builder&& AddPrimaryPrimitive( std::unique_ptr

primitive, const google::crypto::tink::KeysetInfo::KeyInfo& key_info) && { return std::move(AddPrimaryPrimitive(std::move(primitive), key_info)); } // Add the given annotations. Existing annotations will not be overwritten. Builder& AddAnnotations( absl::flat_hash_map annotations) & { absl::MutexLock lock(&mutex_); annotations_.merge(std::move(annotations)); return *this; } Builder&& AddAnnotations( absl::flat_hash_map annotations) && { return std::move(AddAnnotations(std::move(annotations))); } crypto::tink::util::StatusOr> Build() && { absl::MutexLock lock(&mutex_); if (!status_.ok()) return status_; return PrimitiveSet

(std::move(primitives_), primary_, std::move(primitives_in_keyset_order_), std::move(annotations_)); } private: // Owned by primitives_. Entry

* primary_ ABSL_GUARDED_BY(mutex_) = nullptr; CiphertextPrefixToPrimitivesMap primitives_ ABSL_GUARDED_BY(mutex_); // Entries in the original keyset key order, all owned by primitives_. std::vector*> primitives_in_keyset_order_ ABSL_GUARDED_BY(mutex_); absl::flat_hash_map annotations_ ABSL_GUARDED_BY(mutex_); absl::Mutex mutex_; crypto::tink::util::Status status_ ABSL_GUARDED_BY(mutex_); }; // PrimitiveSet is movable, but not copyable PrimitiveSet(PrimitiveSet&&) = default; PrimitiveSet

& operator=(PrimitiveSet&&) = default; PrimitiveSet(const PrimitiveSet&) = delete; PrimitiveSet

& operator=(const PrimitiveSet&) = delete; // Constructs an empty PrimitiveSet. // Note: This is equivalent to PrimitiveSet

(/*annotations=*/{}). ABSL_DEPRECATED( "Constructing PrimitiveSet using constructors is deprecated. Use " "PrimitiveSet<>::Builder instead.") PrimitiveSet

() = default; // Constructs an empty PrimitiveSet with `annotations`. ABSL_DEPRECATED( "Constructing PrimitiveSet using constructors is deprecated. Use " "PrimitiveSet<>::Builder instead.") explicit PrimitiveSet

( const absl::flat_hash_map& annotations) : annotations_(annotations) {} // Adds 'primitive' to this set for the specified 'key'. ABSL_DEPRECATED( "Mutating PrimitiveSets after construction is deprecated. Use " "PrimitiveSet<>::Builder instead.") crypto::tink::util::StatusOr*> AddPrimitive( std::unique_ptr

primitive, const google::crypto::tink::KeysetInfo::KeyInfo& key_info) { if (!is_mutable()) { return util::Status(absl::StatusCode::kFailedPrecondition, "PrimitiveSet is not mutable."); } absl::MutexLock lock(primitives_mutex_.get()); return AddPrimitiveImpl(std::move(primitive), key_info, primitives_, primitives_in_keyset_order_); } // Returns the entries with primitives identified by 'identifier'. crypto::tink::util::StatusOr get_primitives( absl::string_view identifier) const { absl::MutexLockMaybe lock(primitives_mutex_.get()); auto found = primitives_.find(std::string(identifier)); if (found == primitives_.end()) { return ToStatusF(absl::StatusCode::kNotFound, "No primitives found for identifier '%s'.", identifier); } return &(found->second); } // Returns all primitives that use RAW prefix. crypto::tink::util::StatusOr get_raw_primitives() const { return get_primitives(CryptoFormat::kRawPrefix); } // Sets the given 'primary' as the primary primitive of this set. ABSL_DEPRECATED( "Mutating PrimitiveSets after construction is deprecated. Use " "PrimitiveSet<>::Builder instead.") crypto::tink::util::Status set_primary(Entry

* primary) { if (!is_mutable()) { return util::Status(absl::StatusCode::kFailedPrecondition, "PrimitiveSet is not mutable."); } absl::MutexLock lock(primitives_mutex_.get()); return SetPrimaryImpl(&primary_, primary, primitives_); } // Returns the entry with the primary primitive. const Entry

* get_primary() const { absl::MutexLockMaybe lock(primitives_mutex_.get()); return primary_; } // Returns all entries. std::vector*> get_all() const { absl::MutexLockMaybe lock(primitives_mutex_.get()); std::vector*> result; for (const auto& prefix_and_vector : primitives_) { for (const auto& primitive : prefix_and_vector.second) { result.push_back(primitive.get()); } } return result; } // Returns all entries in the original keyset key order. std::vector*> get_all_in_keyset_order() const { absl::MutexLockMaybe lock(primitives_mutex_.get()); return primitives_in_keyset_order_; } const absl::flat_hash_map& get_annotations() const { return annotations_; } bool is_mutable() const { return primitives_mutex_ != nullptr; } private: // Constructs an empty PrimitiveSet. // Note: This is equivalent to PrimitiveSet

(/*annotations=*/{}). PrimitiveSet(CiphertextPrefixToPrimitivesMap primitives, Entry

* primary, std::vector*> primitives_in_keyset_order, absl::flat_hash_map annotations) : primary_(primary), primitives_mutex_(nullptr), primitives_(std::move(primitives)), primitives_in_keyset_order_(std::move(primitives_in_keyset_order)), annotations_(std::move(annotations)) {} // Owned by primitives_. Entry

* primary_ ABSL_GUARDED_BY(primitives_mutex_) = nullptr; // If primitives_mutex_ is a nullptr, PrimitiveSet is immutable and lock-free. // If not nullptr, primitives_mutex_ guards all read and write access. mutable std::unique_ptr primitives_mutex_ = absl::make_unique(); CiphertextPrefixToPrimitivesMap primitives_ ABSL_GUARDED_BY(primitives_mutex_); // Entries in the original keyset key order, all owned by primitives_. std::vector*> primitives_in_keyset_order_ ABSL_GUARDED_BY(primitives_mutex_); absl::flat_hash_map annotations_; }; } // namespace tink } // namespace crypto #endif // TINK_PRIMITIVE_SET_H_ ================================================ FILE: cc/primitive_wrapper.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_PRIMITIVE_WRAPPER_H_ #define TINK_PRIMITIVE_WRAPPER_H_ #include #include "tink/primitive_set.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // A PrimitiveWrapper knows how to wrap multiple instances of a primitive to // a single instance, enabling key-rotation. It requires a // PrimitiveSet and wraps it into a single primitive. // // PrimitiveWrappers need to be written for every new primitive. They can be // registered in the registry to be fully integrated in Tink. template class PrimitiveWrapper { public: virtual ~PrimitiveWrapper() = default; // Useful when writing templated code. using InputPrimitive = InputPrimitiveParam; using Primitive = PrimitiveParam; virtual crypto::tink::util::StatusOr> Wrap( std::unique_ptr> primitive_set) const = 0; }; } // namespace tink } // namespace crypto #endif // TINK_PRIMITIVE_WRAPPER_H_ ================================================ FILE: cc/private_key.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_PRIVATE_KEY_H_ #define TINK_PRIVATE_KEY_H_ #include "tink/key.h" namespace crypto { namespace tink { // Represents a private key. Note that private keys in Tink always include the // corresponding public key. class PrivateKey : public Key { public: virtual const Key& GetPublicKey() const = 0; }; } // namespace tink } // namespace crypto #endif // TINK_PRIVATE_KEY_H_ ================================================ FILE: cc/proto/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) # ---------------------------------------- # proto_library rules. # ---------------------------------------- proto_library( name = "common_proto", srcs = ["common.proto"], visibility = ["//visibility:public"], ) proto_library( name = "tink_proto", srcs = ["tink.proto"], visibility = ["//visibility:public"], ) proto_library( name = "config_proto", srcs = ["config.proto"], visibility = ["//visibility:public"], ) proto_library( name = "aes_siv_proto", srcs = ["aes_siv.proto"], visibility = ["//visibility:public"], ) proto_library( name = "rsa_ssa_pkcs1_proto", srcs = ["rsa_ssa_pkcs1.proto"], visibility = ["//visibility:public"], deps = [":common_proto"], ) proto_library( name = "rsa_ssa_pss_proto", srcs = ["rsa_ssa_pss.proto"], visibility = ["//visibility:public"], deps = [":common_proto"], ) proto_library( name = "ecdsa_proto", srcs = ["ecdsa.proto"], visibility = ["//visibility:public"], deps = [":common_proto"], ) proto_library( name = "jwt_rsa_ssa_pkcs1_proto", srcs = ["jwt_rsa_ssa_pkcs1.proto"], visibility = ["//visibility:public"], ) proto_library( name = "jwt_rsa_ssa_pss_proto", srcs = ["jwt_rsa_ssa_pss.proto"], visibility = ["//visibility:public"], ) proto_library( name = "jwt_ecdsa_proto", srcs = ["jwt_ecdsa.proto"], visibility = ["//visibility:public"], ) proto_library( name = "ed25519_proto", srcs = ["ed25519.proto"], visibility = ["//visibility:public"], ) proto_library( name = "aes_cmac_proto", srcs = ["aes_cmac.proto"], visibility = ["//visibility:public"], ) proto_library( name = "hmac_proto", srcs = ["hmac.proto"], visibility = ["//visibility:public"], deps = [":common_proto"], ) proto_library( name = "jwt_hmac_proto", srcs = ["jwt_hmac.proto"], visibility = ["//visibility:public"], ) proto_library( name = "aes_ctr_proto", srcs = ["aes_ctr.proto"], visibility = ["//visibility:public"], ) proto_library( name = "aes_ctr_hmac_aead_proto", srcs = ["aes_ctr_hmac_aead.proto"], visibility = ["//visibility:public"], deps = [ ":aes_ctr_proto", ":hmac_proto", ], ) proto_library( name = "aes_gcm_proto", srcs = ["aes_gcm.proto"], visibility = ["//visibility:public"], ) proto_library( name = "aes_gcm_siv_proto", srcs = ["aes_gcm_siv.proto"], visibility = ["//visibility:public"], ) proto_library( name = "aes_ctr_hmac_streaming_proto", srcs = ["aes_ctr_hmac_streaming.proto"], visibility = ["//visibility:public"], deps = [ ":common_proto", ":hmac_proto", ], ) proto_library( name = "aes_gcm_hkdf_streaming_proto", srcs = ["aes_gcm_hkdf_streaming.proto"], visibility = ["//visibility:public"], deps = [":common_proto"], ) proto_library( name = "aes_eax_proto", srcs = ["aes_eax.proto"], visibility = ["//visibility:public"], ) proto_library( name = "chacha20_poly1305_proto", srcs = ["chacha20_poly1305.proto"], visibility = ["//visibility:public"], ) proto_library( name = "kms_aead_proto", srcs = ["kms_aead.proto"], visibility = ["//visibility:public"], ) proto_library( name = "kms_envelope_proto", srcs = ["kms_envelope.proto"], visibility = ["//visibility:public"], deps = [":tink_proto"], ) proto_library( name = "ecies_aead_hkdf_proto", srcs = ["ecies_aead_hkdf.proto"], visibility = ["//visibility:public"], deps = [ ":common_proto", ":tink_proto", ], ) proto_library( name = "xchacha20_poly1305_proto", srcs = ["xchacha20_poly1305.proto"], visibility = ["//visibility:public"], ) proto_library( name = "hkdf_prf_proto", srcs = ["hkdf_prf.proto"], visibility = ["//visibility:public"], deps = [":common_proto"], ) proto_library( name = "aes_cmac_prf_proto", srcs = ["aes_cmac_prf.proto"], visibility = ["//visibility:public"], ) proto_library( name = "hmac_prf_proto", srcs = ["hmac_prf.proto"], visibility = ["//visibility:public"], deps = [":common_proto"], ) proto_library( name = "hpke_proto", srcs = ["hpke.proto"], visibility = ["//visibility:public"], ) proto_library( name = "prf_based_deriver_proto", srcs = ["prf_based_deriver.proto"], visibility = ["//visibility:public"], deps = [":tink_proto"], ) proto_library( name = "empty_proto", srcs = ["empty.proto"], visibility = ["//visibility:public"], ) proto_library( name = "test_proto_proto", testonly = True, srcs = ["test_proto.proto"], visibility = ["//visibility:public"], ) # ---------------------------------------- # cc_proto_library rules. # ---------------------------------------- cc_proto_library( name = "common_cc_proto", visibility = ["//visibility:public"], deps = [":common_proto"], ) cc_proto_library( name = "config_cc_proto", deps = [":config_proto"], ) cc_proto_library( name = "tink_cc_proto", visibility = ["//visibility:public"], deps = [":tink_proto"], ) cc_proto_library( name = "aes_gcm_siv_cc_proto", deps = [":aes_gcm_siv_proto"], ) cc_proto_library( name = "aes_siv_cc_proto", visibility = ["//visibility:public"], deps = [":aes_siv_proto"], ) cc_proto_library( name = "hmac_cc_proto", visibility = ["//visibility:public"], deps = [":hmac_proto"], ) cc_proto_library( name = "kms_envelope_cc_proto", deps = [":kms_envelope_proto"], ) cc_proto_library( name = "empty_cc_proto", deps = [":empty_proto"], ) cc_proto_library( name = "kms_aead_cc_proto", deps = [":kms_aead_proto"], ) cc_proto_library( name = "aes_eax_cc_proto", visibility = ["//visibility:public"], deps = [":aes_eax_proto"], ) cc_proto_library( name = "aes_gcm_cc_proto", visibility = ["//visibility:public"], deps = [":aes_gcm_proto"], ) cc_proto_library( name = "aes_ctr_cc_proto", visibility = ["//visibility:public"], deps = [":aes_ctr_proto"], ) cc_proto_library( name = "aes_ctr_hmac_aead_cc_proto", visibility = ["//visibility:public"], deps = [":aes_ctr_hmac_aead_proto"], ) cc_proto_library( name = "aes_cmac_cc_proto", deps = [":aes_cmac_proto"], ) cc_proto_library( name = "xchacha20_poly1305_cc_proto", visibility = ["//visibility:public"], deps = [":xchacha20_poly1305_proto"], ) cc_proto_library( name = "chacha20_poly1305_cc_proto", visibility = ["//visibility:public"], deps = [":chacha20_poly1305_proto"], ) cc_proto_library( name = "rsa_ssa_pkcs1_cc_proto", deps = [":rsa_ssa_pkcs1_proto"], ) cc_proto_library( name = "rsa_ssa_pss_cc_proto", deps = [":rsa_ssa_pss_proto"], ) cc_proto_library( name = "ecdsa_cc_proto", deps = [":ecdsa_proto"], ) cc_proto_library( name = "ed25519_cc_proto", deps = [":ed25519_proto"], ) cc_proto_library( name = "ecies_aead_hkdf_cc_proto", deps = [":ecies_aead_hkdf_proto"], ) cc_proto_library( name = "hkdf_prf_cc_proto", deps = [":hkdf_prf_proto"], ) cc_proto_library( name = "prf_based_deriver_cc_proto", deps = ["//proto:prf_based_deriver_proto"], ) cc_proto_library( name = "aes_gcm_hkdf_streaming_cc_proto", deps = ["//proto:aes_gcm_hkdf_streaming_proto"], ) cc_proto_library( name = "aes_cmac_prf_cc_proto", deps = ["//proto:aes_cmac_prf_proto"], ) cc_proto_library( name = "hmac_prf_cc_proto", deps = ["//proto:hmac_prf_proto"], ) cc_proto_library( name = "jwt_hmac_cc_proto", deps = ["//proto:jwt_hmac_proto"], ) cc_proto_library( name = "jwt_ecdsa_cc_proto", deps = ["//proto:jwt_ecdsa_proto"], ) cc_proto_library( name = "jwt_rsa_ssa_pkcs1_cc_proto", deps = ["//proto:jwt_rsa_ssa_pkcs1_proto"], ) cc_proto_library( name = "jwt_rsa_ssa_pss_cc_proto", deps = ["//proto:jwt_rsa_ssa_pss_proto"], ) cc_proto_library( name = "aes_ctr_hmac_streaming_cc_proto", deps = ["//proto:aes_ctr_hmac_streaming_proto"], ) cc_proto_library( name = "test_proto_cc_proto", testonly = True, deps = ["//proto:test_proto_proto"], ) cc_proto_library( name = "hpke_cc_proto", visibility = ["//visibility:public"], deps = ["//proto:hpke_proto"], ) filegroup( name = "public_cc_protos", srcs = [ ":config_cc_proto", ":tink_cc_proto", ], ) ================================================ FILE: cc/proto/aes_cmac.proto ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/aes_cmac_go_proto"; message AesCmacParams { uint32 tag_size = 1; } // key_type: type.googleapis.com/google.crypto.tink.AesCmacKey message AesCmacKey { uint32 version = 1; bytes key_value = 2; AesCmacParams params = 3; } message AesCmacKeyFormat { uint32 key_size = 1; AesCmacParams params = 2; } ================================================ FILE: cc/proto/aes_cmac_prf.proto ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/aes_cmac_prf_go_proto"; // key_type: type.googleapis.com/google.crypto.tink.AesCmacPrfKey message AesCmacPrfKey { uint32 version = 1; bytes key_value = 2; } message AesCmacPrfKeyFormat { uint32 version = 2; uint32 key_size = 1; } ================================================ FILE: cc/proto/aes_ctr.proto ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/aes_ctr_go_proto"; message AesCtrParams { uint32 iv_size = 1; } message AesCtrKeyFormat { AesCtrParams params = 1; uint32 key_size = 2; } // key_type: type.googleapis.com/google.crypto.tink.AesCtrKey message AesCtrKey { uint32 version = 1; AesCtrParams params = 2; bytes key_value = 3; } ================================================ FILE: cc/proto/aes_ctr_hmac_aead.proto ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; import "proto/aes_ctr.proto"; import "proto/hmac.proto"; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/aes_ctr_hmac_aead_go_proto"; message AesCtrHmacAeadKeyFormat { AesCtrKeyFormat aes_ctr_key_format = 1; HmacKeyFormat hmac_key_format = 2; } // key_type: type.googleapis.com/google.crypto.tink.AesCtrHmacAeadKey message AesCtrHmacAeadKey { uint32 version = 1; AesCtrKey aes_ctr_key = 2; HmacKey hmac_key = 3; } ================================================ FILE: cc/proto/aes_ctr_hmac_streaming.proto ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; import "proto/common.proto"; import "proto/hmac.proto"; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/aes_ctr_hmac_streaming_go_proto"; message AesCtrHmacStreamingParams { uint32 ciphertext_segment_size = 1; uint32 derived_key_size = 2; // size of AES-CTR keys derived for each segment HashType hkdf_hash_type = 3; // hash function for key derivation via HKDF HmacParams hmac_params = 4; // params for authentication tags } message AesCtrHmacStreamingKeyFormat { uint32 version = 3; AesCtrHmacStreamingParams params = 1; uint32 key_size = 2; // size of the main key (aka. "ikm", input key material) } // key_type: type.googleapis.com/google.crypto.tink.AesCtrHmacStreamingKey message AesCtrHmacStreamingKey { uint32 version = 1; AesCtrHmacStreamingParams params = 2; bytes key_value = 3; // the main key, aka. "ikm", input key material } ================================================ FILE: cc/proto/aes_eax.proto ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/aes_eax_go_proto"; // only allowing tag size in bytes = 16 message AesEaxParams { // possible value is 12 or 16 bytes. uint32 iv_size = 1; } message AesEaxKeyFormat { AesEaxParams params = 1; uint32 key_size = 2; } // key_type: type.googleapis.com/google.crypto.tink.AesEaxKey message AesEaxKey { uint32 version = 1; AesEaxParams params = 2; bytes key_value = 3; } ================================================ FILE: cc/proto/aes_gcm.proto ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/aes_gcm_go_proto"; option objc_class_prefix = "TINKPB"; message AesGcmKeyFormat { uint32 key_size = 2; uint32 version = 3; } // key_type: type.googleapis.com/google.crypto.tink.AesGcmKey // // A AesGcmKey is an AEAD key. Mathematically, it represents the functions // Encrypt and Decrypt which we define in the following. // // First, Tink computes a "output prefix" OP by considering the // "OutputPrefixType" message in Keyset.Key and the ID of the key using the // Tink function "AEAD-OutputPrefix": (AesGcmKeys must always be stored in a // keyset). // // AEAD-OutputPrefix(output_prefix_type, id): // if output_prefix_type == RAW: // return ""; // if output_prefix_type == TINK: // return 0x01 + BigEndian(id) // if output_prefix_type == CRUNCHY: // return 0x00 + BigEndian(id) // // Then, the function defined by this is defined as: // [GCM], Section 5.2.1: // * "Encrypt" maps a plaintext P and associated data A to a ciphertext given // by the concatenation OP || IV || C || T. In addition to [GCM], Tink // has the following restriction: IV is a uniformly random initialization // vector of length 12 bytes and T is restricted to 16 bytes. // // * If OP matches the result of AEAD-OutputPrefix, then "Decrypt" maps the // input OP || IV || C || T and A to the the output P in the manner as // described in [GCM], Section 5.2.2. If OP does not match, then "Decrypt" // returns an error. // [GCM]: NIST Special Publication 800-38D: Recommendation for Block Cipher // Modes of Operation: Galois/Counter Mode (GCM) and GMAC. // http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf. message AesGcmKey { uint32 version = 1; bytes key_value = 3; } ================================================ FILE: cc/proto/aes_gcm_hkdf_streaming.proto ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Definitions for streaming encryption using AES-GCM // with HKDF as key derivation function. syntax = "proto3"; package google.crypto.tink; import "proto/common.proto"; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/aes_gcm_hkdf_streaming_go_proto"; message AesGcmHkdfStreamingParams { uint32 ciphertext_segment_size = 1; uint32 derived_key_size = 2; // size of AES-GCM keys derived for each segment HashType hkdf_hash_type = 3; } message AesGcmHkdfStreamingKeyFormat { uint32 version = 3; AesGcmHkdfStreamingParams params = 1; uint32 key_size = 2; // size of the main key (aka. "ikm", input key material) } // key_type: type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey message AesGcmHkdfStreamingKey { uint32 version = 1; AesGcmHkdfStreamingParams params = 2; bytes key_value = 3; } ================================================ FILE: cc/proto/aes_gcm_siv.proto ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/aes_gcm_siv_go_proto"; // The only allowed IV size is 12 bytes and tag size is 16 bytes. // Thus, accept no params. message AesGcmSivKeyFormat { uint32 key_size = 2; uint32 version = 1; } // key_type: type.googleapis.com/google.crypto.tink.AesGcmSivKey message AesGcmSivKey { uint32 version = 1; bytes key_value = 3; } ================================================ FILE: cc/proto/aes_siv.proto ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/aes_siv_go_proto"; // Tink implements RFC 5297 (https://www.rfc-editor.org/rfc/rfc5297) for // AES-SIV, putting the SIV/Tag at the beginning of the ciphertext. // // While the RFC 5297 supports a list of associated datas, Tink only supports // exactly one associated data, which corresponds to a list with one element in // RFC 5297. An empty associated data is a list with one empty element, and not // an empty list. message AesSivKeyFormat { // Only valid value is: 64. uint32 key_size = 1; uint32 version = 2; } // key_type: type.googleapis.com/google.crypto.tink.AesSivKey message AesSivKey { uint32 version = 1; // First half is AES-CTR key, second is AES-SIV. bytes key_value = 2; } ================================================ FILE: cc/proto/chacha20_poly1305.proto ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/chacha20_poly1305_go_proto"; message ChaCha20Poly1305KeyFormat {} // key_type: type.googleapis.com/google.crypto.tink.ChaCha20Poly1305. // This key type actually implements ChaCha20Poly1305 as described // at https://tools.ietf.org/html/rfc7539#section-2.8. message ChaCha20Poly1305Key { uint32 version = 1; bytes key_value = 2; } ================================================ FILE: cc/proto/common.proto ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Definitions for common cryptographic enum types. syntax = "proto3"; package google.crypto.tink; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/common_go_proto"; enum EllipticCurveType { UNKNOWN_CURVE = 0; NIST_P256 = 2; NIST_P384 = 3; NIST_P521 = 4; CURVE25519 = 5; } enum EcPointFormat { UNKNOWN_FORMAT = 0; UNCOMPRESSED = 1; COMPRESSED = 2; // Like UNCOMPRESSED but without the \x04 prefix. Crunchy uses this format. // DO NOT USE unless you are a Crunchy user moving to Tink. DO_NOT_USE_CRUNCHY_UNCOMPRESSED = 3; } enum HashType { UNKNOWN_HASH = 0; SHA1 = 1; // Using SHA1 for digital signature is deprecated but HMAC-SHA1 is // fine. SHA384 = 2; SHA256 = 3; SHA512 = 4; SHA224 = 5; } ================================================ FILE: cc/proto/config.proto ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Definitions for configuring Tink runtime environment. syntax = "proto3"; package google.crypto.tink; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/config_go_proto"; // An entry that describes a key type to be used with Tink library, // specifying the corresponding primitive, key manager, and deprecation status. // All fields are required. message KeyTypeEntry { // KeyTypeEntry is no longer supported. option deprecated = true; string primitive_name = 1; // E.g. “Aead”, “Mac”, ... (case-insensitive) string type_url = 2; // Name of the key type. uint32 key_manager_version = 3; // Minimum required version of key manager. bool new_key_allowed = 4; // Can the key manager create new keys? string catalogue_name = 5; // Catalogue to be queried for key manager, // e.g. "Tink", "Custom", ... (case-insensitive) } // A complete configuration of Tink library: a list of key types // to be available via the Registry after initialization. // All fields are required. message RegistryConfig { // RegistryConfig is no longer supported. option deprecated = true; string config_name = 1; repeated KeyTypeEntry entry = 2; } ================================================ FILE: cc/proto/ecdsa.proto ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Definitions for Elliptic Curve Digital Signature Algorithm (ECDSA). syntax = "proto3"; package google.crypto.tink; import "proto/common.proto"; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/ecdsa_go_proto"; enum EcdsaSignatureEncoding { UNKNOWN_ENCODING = 0; // The signature's format is r || s, where r and s are zero-padded and have // the same size in bytes as the order of the curve. For example, for NIST // P-256 curve, r and s are zero-padded to 32 bytes. IEEE_P1363 = 1; // The signature is encoded using ASN.1 // (https://tools.ietf.org/html/rfc5480#appendix-A): // ECDSA-Sig-Value :: = SEQUENCE { // r INTEGER, // s INTEGER // } DER = 2; } // Protos for Ecdsa. message EcdsaParams { // Required. HashType hash_type = 1; // Required. EllipticCurveType curve = 2; // Required. EcdsaSignatureEncoding encoding = 3; } // key_type: type.googleapis.com/google.crypto.tink.EcdsaPublicKey message EcdsaPublicKey { // Required. uint32 version = 1; // Required. EcdsaParams params = 2; // Affine coordinates of the public key in bigendian representation. The // public key is a point (x, y) on the curve defined by params.curve. For // ECDH, it is crucial to verify whether the public key point (x, y) is on the // private's key curve. For ECDSA, such verification is a defense in depth. // Required. bytes x = 3; // Required. bytes y = 4; } // key_type: type.googleapis.com/google.crypto.tink.EcdsaPrivateKey message EcdsaPrivateKey { // Required. uint32 version = 1; // Required. EcdsaPublicKey public_key = 2; // Unsigned big integer in bigendian representation. // Required. bytes key_value = 3; } message EcdsaKeyFormat { // Required. EcdsaParams params = 2; uint32 version = 3; } ================================================ FILE: cc/proto/ecies_aead_hkdf.proto ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Definitions for Elliptic Curve Digital Signature Algorithm (ECDSA). syntax = "proto3"; package google.crypto.tink; import "proto/common.proto"; import "proto/tink.proto"; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/ecies_aead_hkdf_go_proto"; // Protos for keys for ECIES with HKDF and AEAD encryption. // // These definitions follow loosely ECIES ISO 18033-2 standard // (Elliptic Curve Integrated Encryption Scheme, see // http://www.shoup.net/iso/std6.pdf), with but with some differences: // * use of HKDF key derivation function (instead of KDF1 and KDF2) enabling // the use // of optional parameters to the key derivation function, which strenghten // the overall security and allow for binding the key material to // application-specific information (cf. RFC 5869, // https://tools.ietf.org/html/rfc5869) // * use of modern AEAD schemes rather than "manual composition" of symmetric // encryption // with message authentication codes (as in DEM1, DEM2, and DEM3 schemes of // ISO 18033-2) // // ECIES-keys represent HybridEncryption resp. HybridDecryption primitives. // Parameters of KEM (Key Encapsulation Mechanism) message EciesHkdfKemParams { // Required. EllipticCurveType curve_type = 1; // Required. HashType hkdf_hash_type = 2; // Optional. bytes hkdf_salt = 11; } // Parameters of AEAD DEM (Data Encapsulation Mechanism). message EciesAeadDemParams { // Required. // Contains an Aead or DeterministicAead key format (e.g: // AesCtrHmacAeadKeyFormat, AesGcmKeyFormat or AesSivKeyFormat). // The output_prefix_type in this template here is ignored (RAW is assumed). KeyTemplate aead_dem = 2; } message EciesAeadHkdfParams { // Key Encapsulation Mechanism. // Required. EciesHkdfKemParams kem_params = 1; // Data Encapsulation Mechanism. // Required. EciesAeadDemParams dem_params = 2; // EC point format. // Required. EcPointFormat ec_point_format = 3; } // EciesAeadHkdfPublicKey represents HybridEncryption primitive. // key_type: type.googleapis.com/google.crypto.tink.EciesAeadHkdfPublicKey message EciesAeadHkdfPublicKey { // Required. uint32 version = 1; // Required. EciesAeadHkdfParams params = 2; // Affine coordinates of the public key in bigendian representation. // The public key is a point (x, y) on the curve defined by // params.kem_params.curve. Required. bytes x = 3; // Required. bytes y = 4; } // EciesKdfAeadPrivateKey represents HybridDecryption primitive. // key_type: type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey message EciesAeadHkdfPrivateKey { // Required. uint32 version = 1; // Required. EciesAeadHkdfPublicKey public_key = 2; // Required. bytes key_value = 3; // Big integer in bigendian representation. } message EciesAeadHkdfKeyFormat { // Required. EciesAeadHkdfParams params = 1; } ================================================ FILE: cc/proto/ed25519.proto ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Definitions for Ed25519 Digital Signature Algorithm. // See https://ed25519.cr.yp.to/ed25519-20110926.pdf and // https://tools.ietf.org/html/rfc8032. syntax = "proto3"; package google.crypto.tink; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/ed25519_go_proto"; message Ed25519KeyFormat { uint32 version = 1; } // key_type: type.googleapis.com/google.crypto.tink.Ed25519PublicKey message Ed25519PublicKey { // Required. uint32 version = 1; // The public key is 32 bytes, encoded according to // https://tools.ietf.org/html/rfc8032#section-5.1.2. // Required. bytes key_value = 2; } // key_type: type.googleapis.com/google.crypto.tink.Ed25519PrivateKey message Ed25519PrivateKey { // Required. uint32 version = 1; // The private key is 32 bytes of cryptographically secure random data. // See https://tools.ietf.org/html/rfc8032#section-5.1.5. // Required. bytes key_value = 2; // The corresponding public key. Ed25519PublicKey public_key = 3; } ================================================ FILE: cc/proto/empty.proto ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/empty_go_proto"; message Empty {} ================================================ FILE: cc/proto/experimental/pqcrypto/BUILD.bazel ================================================ # package containing useful functions for hybrid encryption PQC primitives licenses(["notice"]) proto_library( name = "cecpq2_aead_hkdf_proto", srcs = [ "cecpq2_aead_hkdf.proto", ], visibility = ["//visibility:public"], deps = [ "//proto:common_proto", "//proto:tink_proto", ], ) ================================================ FILE: cc/proto/experimental/pqcrypto/cecpq2_aead_hkdf.proto ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; import "proto/common.proto"; import "proto/tink.proto"; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/google/tink/proto/cecpq2_aead_hkdf_go_proto"; // Protos for keys for CECPQ2 with HKDF and AEAD encryption. // // These definitions follow loosely ECIES ISO 18033-2 standard // (Elliptic Curve Integrated Encryption Scheme, see // http://www.shoup.net/iso/std6.pdf), with but with some differences: // * use of CECPQ2 as the KEM instead of ECC-only KEM // * use of HKDF key derivation function (instead of KDF1 and KDF2) enabling // the use // of optional parameters to the key derivation function, which strenghten // the overall security and allow for binding the key material to // application-specific information (cf. RFC 5869, // https://tools.ietf.org/html/rfc5869) // * use of modern AEAD schemes rather than "manual composition" of symmetric // encryption // with message authentication codes (as in DEM1, DEM2, and DEM3 schemes of // ISO 18033-2) // // CECPQ2-keys represent HybridEncryption resp. HybridDecryption primitives. // Parameters of KEM (Key Encapsulation Mechanism) message Cecpq2HkdfKemParams { // Required. EllipticCurveType curve_type = 1; // Required. EcPointFormat ec_point_format = 2; // Required. HashType hkdf_hash_type = 3; // Optional. bytes hkdf_salt = 11; } // Parameters of AEAD DEM (Data Encapsulation Mechanism). message Cecpq2AeadDemParams { // Contains e.g. AesCtrHmacAeadKeyFormat or AesGcmKeyFormat. // Required. KeyTemplate aead_dem = 2; } message Cecpq2AeadHkdfParams { // Key Encapsulation Mechanism. // Required. Cecpq2HkdfKemParams kem_params = 1; // Data Encapsulation Mechanism. // Required. Cecpq2AeadDemParams dem_params = 2; } // Cecpq2AeadHkdfPublicKey represents HybridEncryption primitive. // key_type: type.googleapis.com/google.crypto.tink.Cecpq2AeadHkdfPublicKey message Cecpq2AeadHkdfPublicKey { // Required. uint32 version = 1; // Required. Cecpq2AeadHkdfParams params = 2; // X25519 public key: Affine coordinates of the public key in bigendian // representation. The public key is a point (x, y) on the Curve25519. // Required. bytes x25519_public_key_x = 3; // Required. bytes x25519_public_key_y = 4; // HRSS public key: // Required. bytes hrss_public_key_marshalled = 5; } // Cecpq2KdfAeadPrivateKey represents HybridDecryption primitive. // key_type: type.googleapis.com/google.crypto.tink.Cecpq2AeadHkdfPrivateKey message Cecpq2AeadHkdfPrivateKey { // Required. uint32 version = 1; // Required. Cecpq2AeadHkdfPublicKey public_key = 2; // X25519 private key: // Required. bytes x25519_private_key = 3; // Big integer in bigendian representation. // HRSS private key seed: // Required. bytes hrss_private_key_seed = 4; } message Cecpq2AeadHkdfKeyFormat { // Required. Cecpq2AeadHkdfParams params = 1; } ================================================ FILE: cc/proto/experimental/pqcrypto/dilithium.proto ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; enum DilithiumSeedExpansion { SEED_EXPANSION_UNKNOWN = 0; SEED_EXPANSION_SHAKE = 1; SEED_EXPANSION_AES = 2; } // Protos for Dilithium Digital Signature Algorithm. // See https://pq-crystals.org/dilithium/data/dilithium-specification-round3.pdf message DilithiumParams { // Required int32 key_size = 1; // Required. DilithiumSeedExpansion seed_expansion = 2; } message DilithiumKeyFormat { uint32 version = 1; // Required. DilithiumParams params = 2; } // key_type: type.googleapis.com/google.crypto.tink.DilithiumPublicKey message DilithiumPublicKey { // Required. uint32 version = 1; // Required. bytes key_value = 2; // Required DilithiumParams params = 3; } // key_type: type.googleapis.com/google.crypto.tink.DilithiumPrivateKey message DilithiumPrivateKey { // Required. uint32 version = 1; // Required. bytes key_value = 2; // The corresponding public key. DilithiumPublicKey public_key = 3; } ================================================ FILE: cc/proto/experimental/pqcrypto/falcon.proto ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; // Protos for FalconDigital Signature Algorithm. // See https://falcon-sign.info/ for more details. message FalconKeyFormat { uint32 version = 1; // Required. int32 key_size = 2; } // key_type: type.googleapis.com/google.crypto.tink.FalconPublicKey message FalconPublicKey { // Required. uint32 version = 1; // Required. bytes key_value = 2; } // key_type: type.googleapis.com/google.crypto.tink.FalconPrivateKey message FalconPrivateKey { // Required. uint32 version = 1; // Required. bytes key_value = 2; // The corresponding public key. FalconPublicKey public_key = 3; } ================================================ FILE: cc/proto/experimental/pqcrypto/slh_dsa.proto ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; enum SlhDsaHashType { SLH_DSA_HASH_TYPE_UNSPECIFIED = 0; SHA2 = 1; SHAKE = 2; } enum SlhDsaSignatureType { SLH_DSA_SIGNATURE_TYPE_UNSPECIFIED = 0; FAST_SIGNING = 1; SMALL_SIGNATURE = 2; } // Protos for the Stateless Hash-Based Digital Signature Algorithm // https://csrc.nist.gov/pubs/fips/205/ipd message SlhDsaParams { // Required int32 key_size = 1; // Required. SlhDsaHashType hash_type = 2; // Required. SlhDsaSignatureType sig_type = 3; } message SlhDsaKeyFormat { uint32 version = 1; // Required. SlhDsaParams params = 2; } // key_type: type.googleapis.com/google.crypto.tink.SlhDsaPublicKey message SlhDsaPublicKey { // Required. uint32 version = 1; // Required. bytes key_value = 2; // Required SlhDsaParams params = 3; } // key_type: type.googleapis.com/google.crypto.tink.SlhDsaPrivateKey message SlhDsaPrivateKey { // Required. uint32 version = 1; // Required. bytes key_value = 2; // Required. The corresponding public key. SlhDsaPublicKey public_key = 3; } ================================================ FILE: cc/proto/experimental/pqcrypto/sphincs.proto ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; enum SphincsHashType { HASH_TYPE_UNSPECIFIED = 0; HARAKA = 1; SHA256 = 2; SHAKE256 = 3; } enum SphincsVariant { VARIANT_UNSPECIFIED = 0; ROBUST = 1; SIMPLE = 2; } enum SphincsSignatureType { SIG_TYPE_UNSPECIFIED = 0; FAST_SIGNING = 1; SMALL_SIGNATURE = 2; } // Protos for Sphincs Digital Signature Algorithm. message SphincsParams { // Required int32 key_size = 1; // Required. SphincsHashType hash_type = 2; // Required. SphincsVariant variant = 3; // Required. SphincsSignatureType sig_length_type = 4; } message SphincsKeyFormat { uint32 version = 1; // Required. SphincsParams params = 2; } // key_type: type.googleapis.com/google.crypto.tink.SphincsPublicKey message SphincsPublicKey { // Required. uint32 version = 1; // Required. bytes key_value = 2; // Required SphincsParams params = 3; } // key_type: type.googleapis.com/google.crypto.tink.SphincsPrivateKey message SphincsPrivateKey { // Required. uint32 version = 1; // Required. bytes key_value = 2; // The corresponding public key. SphincsPublicKey public_key = 3; } ================================================ FILE: cc/proto/hkdf_prf.proto ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; import "proto/common.proto"; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/hkdf_prf_proto"; message HkdfPrfParams { HashType hash = 1; // Optional. // // An unspecified or zero-length value is equivalent to a sequence of zeros // (0x00) with a length equal to the output size of hash. // // See https://rfc-editor.org/rfc/rfc5869. bytes salt = 2; } message HkdfPrfKey { uint32 version = 1; HkdfPrfParams params = 2; bytes key_value = 3; } message HkdfPrfKeyFormat { HkdfPrfParams params = 1; uint32 key_size = 2; uint32 version = 3; } ================================================ FILE: cc/proto/hmac.proto ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; import "proto/common.proto"; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/hmac_go_proto"; message HmacParams { HashType hash = 1; // HashType is an enum. uint32 tag_size = 2; } // key_type: type.googleapis.com/google.crypto.tink.HmacKey message HmacKey { uint32 version = 1; HmacParams params = 2; bytes key_value = 3; } message HmacKeyFormat { HmacParams params = 1; uint32 key_size = 2; uint32 version = 3; } ================================================ FILE: cc/proto/hmac_prf.proto ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; import "proto/common.proto"; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/hmac_prf_go_proto"; message HmacPrfParams { HashType hash = 1; // HashType is an enum. } // key_type: type.googleapis.com/google.crypto.tink.HmacPrfKey message HmacPrfKey { uint32 version = 1; HmacPrfParams params = 2; bytes key_value = 3; } message HmacPrfKeyFormat { HmacPrfParams params = 1; uint32 key_size = 2; uint32 version = 3; } ================================================ FILE: cc/proto/hpke.proto ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/hpke_proto"; enum HpkeKem { KEM_UNKNOWN = 0; DHKEM_X25519_HKDF_SHA256 = 1; DHKEM_P256_HKDF_SHA256 = 2; DHKEM_P384_HKDF_SHA384 = 3; DHKEM_P521_HKDF_SHA512 = 4; } enum HpkeKdf { KDF_UNKNOWN = 0; HKDF_SHA256 = 1; HKDF_SHA384 = 2; HKDF_SHA512 = 3; } enum HpkeAead { AEAD_UNKNOWN = 0; AES_128_GCM = 1; AES_256_GCM = 2; CHACHA20_POLY1305 = 3; } message HpkeParams { HpkeKem kem = 1; HpkeKdf kdf = 2; HpkeAead aead = 3; } message HpkePublicKey { uint32 version = 1; HpkeParams params = 2; // KEM-encoding of public key (i.e., SerializePublicKey() ) as described in // https://www.rfc-editor.org/rfc/rfc9180.html#name-cryptographic-dependencies. bytes public_key = 3; } message HpkePrivateKey { uint32 version = 1; HpkePublicKey public_key = 2; // KEM-encoding of private key (i.e., SerializePrivateKey() ) as described in // https://www.rfc-editor.org/rfc/rfc9180.html#name-cryptographic-dependencies. bytes private_key = 3; } message HpkeKeyFormat { HpkeParams params = 1; } ================================================ FILE: cc/proto/jwt_ecdsa.proto ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/jwt_ecdsa_go_proto"; // See https://datatracker.ietf.org/doc/html/rfc7518#section-3.4 enum JwtEcdsaAlgorithm { ES_UNKNOWN = 0; ES256 = 1; // ECDSA using P-256 and SHA-256 ES384 = 2; // ECDSA using P-384 and SHA-384 ES512 = 3; // ECDSA using P-521 and SHA-512 } // key_type: type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey message JwtEcdsaPublicKey { uint32 version = 1; JwtEcdsaAlgorithm algorithm = 2; // Affine coordinates of the public key in big-endian representation. The // public key is a point (x, y) on the curve defined by algorithm. bytes x = 3; bytes y = 4; // Optional, custom kid header value to be used with "RAW" keys. // "TINK" keys with this value set will be rejected. message CustomKid { string value = 1; } CustomKid custom_kid = 5; } // key_type: type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey message JwtEcdsaPrivateKey { uint32 version = 1; JwtEcdsaPublicKey public_key = 2; // Unsigned big integer in bigendian representation. bytes key_value = 3; } message JwtEcdsaKeyFormat { uint32 version = 1; JwtEcdsaAlgorithm algorithm = 2; } ================================================ FILE: cc/proto/jwt_hmac.proto ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/jwt_hmac_go_proto"; // See https://datatracker.ietf.org/doc/html/rfc7518#section-3.2 enum JwtHmacAlgorithm { HS_UNKNOWN = 0; HS256 = 1; // HMAC using SHA-256 HS384 = 2; // HMAC using SHA-384 HS512 = 3; // HMAC using SHA-512 } // key_type: type.googleapis.com/google.crypto.tink.JwtHmacKey message JwtHmacKey { uint32 version = 1; JwtHmacAlgorithm algorithm = 2; bytes key_value = 3; // Optional, custom kid header value to be used with "RAW" keys. // "TINK" keys with this value set will be rejected. message CustomKid { string value = 1; } CustomKid custom_kid = 4; } message JwtHmacKeyFormat { uint32 version = 1; JwtHmacAlgorithm algorithm = 2; uint32 key_size = 3; } ================================================ FILE: cc/proto/jwt_rsa_ssa_pkcs1.proto ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/rsa_ssa_pkcs1_go_proto"; // See https://datatracker.ietf.org/doc/html/rfc7518#section-3.3 enum JwtRsaSsaPkcs1Algorithm { RS_UNKNOWN = 0; RS256 = 1; // RSASSA-PKCS1-v1_5 using SHA-256 RS384 = 2; // RSASSA-PKCS1-v1_5 using SHA-384 RS512 = 3; // RSASSA-PKCS1-v1_5 using SHA-512 } // key_type: type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PublicKey message JwtRsaSsaPkcs1PublicKey { uint32 version = 1; JwtRsaSsaPkcs1Algorithm algorithm = 2; // Modulus. // Unsigned big integer in big-endian representation. bytes n = 3; // Public exponent. // Unsigned big integer in big-endian representation. bytes e = 4; // Optional, custom kid header value to be used with "RAW" keys. // "TINK" keys with this value set will be rejected. message CustomKid { string value = 1; } CustomKid custom_kid = 5; } // key_type: type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PrivateKey message JwtRsaSsaPkcs1PrivateKey { uint32 version = 1; JwtRsaSsaPkcs1PublicKey public_key = 2; // Private exponent. // Unsigned big integer in big-endian representation. bytes d = 3; // The following parameters are used to optimize RSA signature computation. // The prime factor p of n. // Unsigned big integer in big-endian representation. bytes p = 4; // The prime factor q of n. // Unsigned big integer in big-endian representation. bytes q = 5; // d mod (p - 1). // Unsigned big integer in big-endian representation. bytes dp = 6; // d mod (q - 1). // Unsigned big integer in big-endian representation. bytes dq = 7; // Chinese Remainder Theorem coefficient q^(-1) mod p. // Unsigned big integer in big-endian representation. bytes crt = 8; } message JwtRsaSsaPkcs1KeyFormat { uint32 version = 1; JwtRsaSsaPkcs1Algorithm algorithm = 2; uint32 modulus_size_in_bits = 3; bytes public_exponent = 4; } ================================================ FILE: cc/proto/jwt_rsa_ssa_pss.proto ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/jwt_rsa_ssa_pss_go_proto"; // See https://datatracker.ietf.org/doc/html/rfc7518#section-3.5 enum JwtRsaSsaPssAlgorithm { PS_UNKNOWN = 0; PS256 = 1; // RSASSA-PSS using SHA-256 and MGF1 with SHA-256 PS384 = 2; // RSASSA-PSS using SHA-384 and MGF1 with SHA-384 PS512 = 3; // RSASSA-PSS using SHA-512 and MGF1 with SHA-512 } // key_type: type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPublicKey message JwtRsaSsaPssPublicKey { uint32 version = 1; JwtRsaSsaPssAlgorithm algorithm = 2; // Modulus. // Unsigned big integer in big-endian representation. bytes n = 3; // Public exponent. // Unsigned big integer in big-endian representation. bytes e = 4; // Optional, custom kid header value to be used with "RAW" keys. // "TINK" keys with this value set will be rejected. message CustomKid { string value = 1; } CustomKid custom_kid = 5; } // key_type: type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPrivateKey message JwtRsaSsaPssPrivateKey { uint32 version = 1; JwtRsaSsaPssPublicKey public_key = 2; // Private exponent. // Unsigned big integer in big-endian representation. bytes d = 3; // The following parameters are used to optimize RSA signature computation. // The prime factor p of n. // Unsigned big integer in big-endian representation. bytes p = 4; // The prime factor q of n. // Unsigned big integer in big-endian representation. bytes q = 5; // d mod (p - 1). // Unsigned big integer in big-endian representation. bytes dp = 6; // d mod (q - 1). // Unsigned big integer in big-endian representation. bytes dq = 7; // Chinese Remainder Theorem coefficient q^(-1) mod p. // Unsigned big integer in big-endian representation. bytes crt = 8; } message JwtRsaSsaPssKeyFormat { uint32 version = 1; JwtRsaSsaPssAlgorithm algorithm = 2; uint32 modulus_size_in_bits = 3; bytes public_exponent = 4; } ================================================ FILE: cc/proto/kms_aead.proto ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/kms_aead_go_proto"; message KmsAeadKeyFormat { // Required. // The location of a KMS key. // With Google Cloud KMS, valid values have this format: // gcp-kms://projects/*/locations/*/keyRings/*/cryptoKeys/*. // With AWS KMS, valid values have this format: // aws-kms://arn:aws:kms:::key/ string key_uri = 1; } // There is no actual key material in the key. message KmsAeadKey { uint32 version = 1; // The key format also contains the params. KmsAeadKeyFormat params = 2; } ================================================ FILE: cc/proto/kms_envelope.proto ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; import "proto/tink.proto"; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/kms_envelope_go_proto"; message KmsEnvelopeAeadKeyFormat { // Required. // The location of the KEK in a remote KMS. // With Google Cloud KMS, valid values have this format: // gcp-kms://projects/*/locations/*/keyRings/*/cryptoKeys/*. // With AWS KMS, valid values have this format: // aws-kms://arn:aws:kms:::key/ string kek_uri = 1; // Key template of the Data Encryption Key, e.g., AesCtrHmacAeadKeyFormat. // Required. KeyTemplate dek_template = 2; } // There is no actual key material in the key. message KmsEnvelopeAeadKey { uint32 version = 1; // The key format also contains the params. KmsEnvelopeAeadKeyFormat params = 2; } ================================================ FILE: cc/proto/prf_based_deriver.proto ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; import "proto/tink.proto"; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/prf_based_deriver_go_proto"; message PrfBasedDeriverParams { KeyTemplate derived_key_template = 1; } message PrfBasedDeriverKeyFormat { KeyTemplate prf_key_template = 1; PrfBasedDeriverParams params = 2; } // key_type: type.googleapis.com/google.crypto.tink.PrfBasedDeriverKey message PrfBasedDeriverKey { uint32 version = 1; KeyData prf_key = 2; PrfBasedDeriverParams params = 3; } ================================================ FILE: cc/proto/rsa_ssa_pkcs1.proto ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Definitions for RSA SSA (Signature Schemes with Appendix) using PKCS1-v1_5 // encoding (https://tools.ietf.org/html/rfc8017#section-8.2). syntax = "proto3"; package google.crypto.tink; import "proto/common.proto"; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/rsa_ssa_pkcs1_go_proto"; message RsaSsaPkcs1Params { // Hash function used in computing hash of the signing message // (see https://tools.ietf.org/html/rfc8017#section-9.2). // Required. HashType hash_type = 1; } // key_type: type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PublicKey message RsaSsaPkcs1PublicKey { // Required. uint32 version = 1; // Required. RsaSsaPkcs1Params params = 2; // Modulus. // Unsigned big integer in bigendian representation. bytes n = 3; // Public exponent. // Unsigned big integer in bigendian representation. bytes e = 4; } // key_type: type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PrivateKey message RsaSsaPkcs1PrivateKey { // Required. uint32 version = 1; // Required. RsaSsaPkcs1PublicKey public_key = 2; // Private exponent. // Unsigned big integer in bigendian representation. // Required. bytes d = 3; // The following parameters are used to optimize RSA signature computation. // The prime factor p of n. // Unsigned big integer in bigendian representation. // Required. bytes p = 4; // The prime factor q of n. // Unsigned big integer in bigendian representation. // Required. bytes q = 5; // d mod (p - 1). // Unsigned big integer in bigendian representation. // Required. bytes dp = 6; // d mod (q - 1). // Unsigned big integer in bigendian representation. // Required. bytes dq = 7; // Chinese Remainder Theorem coefficient q^(-1) mod p. // Unsigned big integer in bigendian representation. // Required. bytes crt = 8; } message RsaSsaPkcs1KeyFormat { // Required. RsaSsaPkcs1Params params = 1; // Required. uint32 modulus_size_in_bits = 2; // Required. bytes public_exponent = 3; } ================================================ FILE: cc/proto/rsa_ssa_pss.proto ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Definitions for RSA SSA (Signature Schemes with Appendix) using PSS // (Probabilistic Signature Scheme ) encoding // (https://tools.ietf.org/html/rfc8017#section-8.1). syntax = "proto3"; package google.crypto.tink; import "proto/common.proto"; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/rsa_ssa_pss_go_proto"; message RsaSsaPssParams { // Hash function used in computing hash of the signing message // (see https://tools.ietf.org/html/rfc8017#section-9.1.1). // Required. HashType sig_hash = 1; // Hash function used in MGF1 (a mask generation function based on a // hash function) (see https://tools.ietf.org/html/rfc8017#appendix-B.2.1). // Required. HashType mgf1_hash = 2; // Salt length (see https://tools.ietf.org/html/rfc8017#section-9.1.1) // Required. int32 salt_length = 3; } // key_type: type.googleapis.com/google.crypto.tink.RsaSsaPssPublicKey message RsaSsaPssPublicKey { // Required. uint32 version = 1; // Required. RsaSsaPssParams params = 2; // Modulus. // Unsigned big integer in bigendian representation. bytes n = 3; // Public exponent. // Unsigned big integer in bigendian representation. bytes e = 4; } // key_type: type.googleapis.com/google.crypto.tink.RsaSsaPssPrivateKey message RsaSsaPssPrivateKey { // Required. uint32 version = 1; // Required. RsaSsaPssPublicKey public_key = 2; // Private exponent. // Unsigned big integer in bigendian representation. // Required. bytes d = 3; // The following parameters are used to optimize RSA signature computation. // The prime factor p of n. // Unsigned big integer in bigendian representation. // Required. bytes p = 4; // The prime factor q of n. // Unsigned big integer in bigendian representation. // Required. bytes q = 5; // d mod (p - 1). // Unsigned big integer in bigendian representation. // Required. bytes dp = 6; // d mod (q - 1). // Unsigned big integer in bigendian representation. // Required. bytes dq = 7; // Chinese Remainder Theorem coefficient q^(-1) mod p. // Unsigned big integer in bigendian representation. // Required. bytes crt = 8; } message RsaSsaPssKeyFormat { // Required. RsaSsaPssParams params = 1; // Required. uint32 modulus_size_in_bits = 2; // Required. bytes public_exponent = 3; } ================================================ FILE: cc/proto/test_proto.proto ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; message TestProto { uint64 num = 1; bytes str = 2; // Placeholder for ctype. } message NestedTestProto { TestProto a = 1; TestProto b = 2; uint64 num = 3; bytes str = 4; // Placeholder for ctype. } message TestProtoWithoutCtype { bytes str = 1; } ================================================ FILE: cc/proto/tink.proto ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Tink Proto Keyset serialization format. syntax = "proto3"; package google.crypto.tink; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/tink_go_proto"; option objc_class_prefix = "TINKPB"; // Each instantiation of a Tink primitive is identified by type_url, // which is a global URL pointing to a *Key-proto that holds key material // and other parameters of the instantiation. For standard Tink key types // the value of type_url follows the structure of type_url-field of // google.protobuf.Any-protos, and is given as: // // type.googleapis.com/packagename.messagename // // For example, for an HMAC key defined in proto google.cloud.tink.HmacKey // the value of type_url is: // // type.googleapis.com/google.cloud.tink.HmacKey // // For each type_url, in addition to the *Key proto, there exist two // related structures: // 1. *Params: parameters of an instantiation of the primitive, // needed when a key is being used. // 2. *KeyFormat: parameters needed to generate a new key; these // include the corresponding Params, since when a factory generates // a key based on KeyFormat, it must add Params to the resulting // key proto with the actual key material. // The actual *KeyFormat proto is wrapped in a KeyTemplate message. // By convention, the name of the *KeyFormat-proto must be equal // to the name of the *Key-proto from type_url-field suffixed with "Format". message KeyTemplate { // Required. The type_url of the key type in format // type.googleapis.com/packagename.messagename -- see above for details. // This is typically the protobuf type URL of the *Key proto. In particular, // this is different of the protobuf type URL of the *KeyFormat proto. string type_url = 1; // Required. The serialized *KeyFormat proto. bytes value = 2; // Required. The type of prefix used when computing some primitives to // identify the ciphertext/signature, etc. OutputPrefixType output_prefix_type = 3; } enum KeyStatusType { UNKNOWN_STATUS = 0; ENABLED = 1; // Can be used for crypto operations. DISABLED = 2; // Cannot be used, but exists and can become ENABLED. DESTROYED = 3; // Key data does not exist in this Keyset any more. } // Tink produces and accepts ciphertexts or signatures that consist // of a prefix and a payload. The payload and its format is determined // entirely by the primitive, but the prefix has to be one of the following // 4 types: // - Legacy: prefix is 5 bytes, starts with \x00 and followed by a 4-byte // key id that is computed from the key material. In addition to // that, signature schemes and MACs will add a \x00 byte to the // end of the data being signed / MACed when operating on keys // with this OutputPrefixType. // - Crunchy: prefix is 5 bytes, starts with \x00 and followed by a 4-byte // key id that is generated randomly. // - Tink : prefix is 5 bytes, starts with \x01 and followed by 4-byte // key id that is generated randomly. // - Raw : prefix is 0 byte, i.e., empty. enum OutputPrefixType { UNKNOWN_PREFIX = 0; TINK = 1; LEGACY = 2; RAW = 3; CRUNCHY = 4; } // Each *Key proto by convention contains a version field, which // identifies the version of the key. // message SomeInstantiationKey { // uint32 version = 1; // ... // } // If a key type does not mention anything else, only version 0 is currently // specified. An implementation must only accept keys with versions it knows, // and must reject all keys with unknown version. // For public key primitives, the public and private keys are distinct entities // and represent distinct primitives. However, by convention, the private key // of a public-key primitive contains the corresponding public key proto. // The actual *Key-proto is wrapped in a KeyData message, which in addition // to this serialized proto contains also type_url identifying the // definition of *Key-proto (as in KeyFormat-message), and some extra metadata // about the type key material. message KeyData { // Required. string type_url = 1; // In format type.googleapis.com/packagename.messagename // Required. // Contains specific serialized *Key proto bytes value = 2; // Placeholder for ctype. enum KeyMaterialType { UNKNOWN_KEYMATERIAL = 0; SYMMETRIC = 1; ASYMMETRIC_PRIVATE = 2; ASYMMETRIC_PUBLIC = 3; REMOTE = 4; // points to a remote key, i.e., in a KMS. } // Required. KeyMaterialType key_material_type = 3; } // A Tink user works usually not with single keys, but with keysets, // to enable key rotation. The keys in a keyset can belong to different // implementations/key types, but must all implement the same primitive. // Any given keyset (and any given key) can be used for one primitive only. message Keyset { message Key { // Contains the actual, instantiation specific key proto. // By convention, each key proto contains a version field. KeyData key_data = 1; KeyStatusType status = 2; // Identifies a key within a keyset, is a part of metadata // of a ciphertext/signature. uint32 key_id = 3; // Determines the prefix of the ciphertexts/signatures produced by this key. // This value is copied verbatim from the key template. OutputPrefixType output_prefix_type = 4; } // Identifies key used to generate new crypto data (encrypt, sign). // Required. uint32 primary_key_id = 1; // Actual keys in the Keyset. // Required. repeated Key key = 2; } // Represents a "safe" Keyset that doesn't contain any actual key material, // thus can be used for logging or monitoring. Most fields are copied from // Keyset. message KeysetInfo { message KeyInfo { // the type url of this key, // e.g., type.googleapis.com/google.crypto.tink.HmacKey. string type_url = 1; // See Keyset.Key.status. KeyStatusType status = 2; // See Keyset.Key.key_id. uint32 key_id = 3; // See Keyset.Key.output_prefix_type. OutputPrefixType output_prefix_type = 4; } // See Keyset.primary_key_id. uint32 primary_key_id = 1; // KeyInfos in the KeysetInfo. // Each KeyInfo is corresponding to a Key in the corresponding Keyset. repeated KeyInfo key_info = 2; } // Represents a keyset that is encrypted with a master key. message EncryptedKeyset { // Required. bytes encrypted_keyset = 2; // Optional. KeysetInfo keyset_info = 3; } ================================================ FILE: cc/proto/xchacha20_poly1305.proto ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package google.crypto.tink; option java_package = "com.google.crypto.tink.proto"; option java_multiple_files = true; option go_package = "github.com/tink-crypto/tink-go/v2/proto/xchacha20_poly1305_go_proto"; message XChaCha20Poly1305KeyFormat { uint32 version = 1; } // key_type: type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key message XChaCha20Poly1305Key { uint32 version = 1; bytes key_value = 3; } ================================================ FILE: cc/proto_keyset_format.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/proto_keyset_format.h" #include #include #include #include #include #include #include #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/binary_keyset_reader.h" #include "tink/binary_keyset_writer.h" #include "tink/cleartext_keyset_handle.h" #include "tink/keyset_handle.h" #include "tink/secret_key_access_token.h" #include "tink/util/secret_data.h" #include "tink/util/secret_proto.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { crypto::tink::util::StatusOr ParseKeysetFromProtoKeysetFormat( absl::string_view serialized_keyset, SecretKeyAccessToken token) { crypto::tink::util::SecretProto keyset_proto; if (!keyset_proto->ParseFromString(serialized_keyset)) { return util::Status(absl::StatusCode::kInternal, "Failed to parse keyset"); } util::StatusOr>> entries = KeysetHandle::GetEntriesFromKeyset(*keyset_proto); if (!entries.ok()) { return entries.status(); } if (entries->size() != keyset_proto->key_size()) { return util::Status(absl::StatusCode::kInternal, "Error converting keyset proto into key entries."); } return KeysetHandle(std::move(keyset_proto), *entries); } crypto::tink::util::StatusOr SerializeKeysetToProtoKeysetFormat(const KeysetHandle& keyset_handle, SecretKeyAccessToken token) { const google::crypto::tink::Keyset& keyset = CleartextKeysetHandle::GetKeyset(keyset_handle); util::SecretData result(keyset.ByteSizeLong()); if (!keyset.SerializeToArray(result.data(), result.size())) { return util::Status(absl::StatusCode::kInternal, "Failed to serialize keyset"); } return result; } crypto::tink::util::StatusOr ParseKeysetWithoutSecretFromProtoKeysetFormat( absl::string_view serialized_keyset) { std::string keyset_copy = std::string(serialized_keyset); crypto::tink::util::StatusOr> result = KeysetHandle::ReadNoSecret(keyset_copy); if (!result.ok()) { return result.status(); } return std::move(**result); } crypto::tink::util::StatusOr SerializeKeysetWithoutSecretToProtoKeysetFormat( const KeysetHandle& keyset_handle) { std::stringbuf string_buf(std::ios_base::out); crypto::tink::util::StatusOr> keyset_writer = BinaryKeysetWriter::New( std::make_unique(&string_buf)); if (!keyset_writer.ok()) { return keyset_writer.status(); } crypto::tink::util::Status status = keyset_handle.WriteNoSecret(keyset_writer->get()); if (!status.ok()) { return status; } return string_buf.str(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/proto_keyset_format.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_PROTO_KEYSET_FORMAT_H_ #define TINK_PROTO_KEYSET_FORMAT_H_ #include #include "absl/strings/string_view.h" #include "tink/keyset_handle.h" #include "tink/secret_key_access_token.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Serializes a keyset into a binary string in "ProtoKeysetFormat". // This function can serialize both keyset with or without secret key material. crypto::tink::util::StatusOr SerializeKeysetToProtoKeysetFormat(const KeysetHandle& keyset_handle, SecretKeyAccessToken token); // Parses a keyset from a binary string in "ProtoKeysetFormat". // This function can parse both keyset with or without secret key material. crypto::tink::util::StatusOr ParseKeysetFromProtoKeysetFormat( absl::string_view serialized_keyset, SecretKeyAccessToken token); // Serializes a keyset into a binary string in "ProtoKeysetFormat". // This function will fail if the keyset contains secret key material. crypto::tink::util::StatusOr SerializeKeysetWithoutSecretToProtoKeysetFormat( const KeysetHandle& keyset_handle); // Parses a keyset from a binary string in "ProtoKeysetFormat". // This function will fail if the keyset contains secret key material. crypto::tink::util::StatusOr ParseKeysetWithoutSecretFromProtoKeysetFormat( absl::string_view serialized_keyset); } // namespace tink } // namespace crypto #endif // TINK_PROTO_KEYSET_FORMAT_H_ ================================================ FILE: cc/proto_keyset_format_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/proto_keyset_format.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/escaping.h" #include "tink/config/global_registry.h" #include "tink/config/tink_config.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/legacy_proto_parameters.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/key_status.h" #include "tink/keyset_handle.h" #include "tink/keyset_handle_builder.h" #include "tink/mac.h" #include "tink/mac/mac_key_templates.h" #include "tink/signature/signature_key_templates.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::internal::LegacyProtoParameters; using ::crypto::tink::internal::ProtoParametersSerialization; using ::crypto::tink::test::IsOk; using ::crypto::tink::util::SecretData; using ::crypto::tink::util::SecretDataAsStringView; using ::testing::Eq; using ::testing::Not; class SerializeKeysetToProtoKeysetFormatTest : public ::testing::Test { protected: void SetUp() override { auto status = TinkConfig::Register(); ASSERT_THAT(status, IsOk()); } }; util::StatusOr CmacParameters() { util::StatusOr serialization = ProtoParametersSerialization::Create(MacKeyTemplates::AesCmac()); if (!serialization.ok()) return serialization.status(); return LegacyProtoParameters(*serialization); } util::StatusOr EcdsaParameters() { util::StatusOr serialization = ProtoParametersSerialization::Create(SignatureKeyTemplates::EcdsaP256()); if (!serialization.ok()) return serialization.status(); return LegacyProtoParameters(*serialization); } TEST_F(SerializeKeysetToProtoKeysetFormatTest, SerializeAndParseSingleKey) { util::StatusOr parameters = CmacParameters(); ASSERT_THAT(parameters, IsOk()); util::StatusOr handle = KeysetHandleBuilder() .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/123)) .Build(); ASSERT_THAT(handle, IsOk()); crypto::tink::util::StatusOr serialization = SerializeKeysetToProtoKeysetFormat(*handle, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization, IsOk()); util::StatusOr parsed_handle = ParseKeysetFromProtoKeysetFormat( SecretDataAsStringView(*serialization), InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_handle, IsOk()); ASSERT_THAT(handle->size(), Eq(1)); ASSERT_THAT(parsed_handle->size(), Eq(1)); EXPECT_TRUE(*(*handle)[0].GetKey() == *(*parsed_handle)[0].GetKey()); EXPECT_TRUE((*handle)[0].GetId() == (*parsed_handle)[0].GetId()); EXPECT_TRUE((*handle)[0].GetStatus() == (*parsed_handle)[0].GetStatus()); } TEST_F(SerializeKeysetToProtoKeysetFormatTest, SerializeAndParseMultipleKeys) { util::StatusOr parameters = CmacParameters(); ASSERT_THAT(parameters, IsOk()); util::StatusOr handle = KeysetHandleBuilder() .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/false, /*id=*/123)) .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/125)) .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kDisabled, /*is_primary=*/true, /*id=*/127)) .Build(); ASSERT_THAT(handle, IsOk()); crypto::tink::util::StatusOr serialization = SerializeKeysetToProtoKeysetFormat(*handle, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization, IsOk()); util::StatusOr parsed_handle = ParseKeysetFromProtoKeysetFormat( SecretDataAsStringView(*serialization), InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_handle, IsOk()); ASSERT_THAT(handle->size(), Eq(3)); ASSERT_THAT(parsed_handle->size(), Eq(3)); EXPECT_TRUE(*(*handle)[0].GetKey() == *(*parsed_handle)[0].GetKey()); EXPECT_TRUE((*handle)[0].GetId() == (*parsed_handle)[0].GetId()); EXPECT_TRUE((*handle)[0].GetStatus() == (*parsed_handle)[0].GetStatus()); EXPECT_TRUE(*(*handle)[1].GetKey() == *(*parsed_handle)[1].GetKey()); EXPECT_TRUE((*handle)[1].GetId() == (*parsed_handle)[1].GetId()); EXPECT_TRUE((*handle)[1].GetStatus() == (*parsed_handle)[1].GetStatus()); EXPECT_TRUE(*(*handle)[2].GetKey() == *(*parsed_handle)[2].GetKey()); EXPECT_TRUE((*handle)[2].GetId() == (*parsed_handle)[2].GetId()); EXPECT_TRUE((*handle)[2].GetStatus() == (*parsed_handle)[2].GetStatus()); } TEST_F(SerializeKeysetToProtoKeysetFormatTest, SerializeNoAccessFails) { util::StatusOr parameters = CmacParameters(); ASSERT_THAT(parameters, IsOk()); util::StatusOr handle = KeysetHandleBuilder() .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/123)) .Build(); ASSERT_THAT(handle, IsOk()); crypto::tink::util::StatusOr serialization = SerializeKeysetWithoutSecretToProtoKeysetFormat(*handle); ASSERT_THAT(serialization, Not(IsOk())); } TEST_F(SerializeKeysetToProtoKeysetFormatTest, ParseNoAccessFails) { util::StatusOr parameters = CmacParameters(); ASSERT_THAT(parameters, IsOk()); util::StatusOr handle = KeysetHandleBuilder() .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/123)) .Build(); ASSERT_THAT(handle, IsOk()); crypto::tink::util::StatusOr serialization = SerializeKeysetToProtoKeysetFormat(*handle, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization, IsOk()); util::StatusOr parsed_handle = ParseKeysetWithoutSecretFromProtoKeysetFormat( SecretDataAsStringView(*serialization)); ASSERT_THAT(parsed_handle, Not(IsOk())); } TEST_F(SerializeKeysetToProtoKeysetFormatTest, TestVector) { std::string serialized_keyset = absl::HexStringToBytes( "0895e59bcc0612680a5c0a2e747970652e676f6f676c65617069732e636f6d2f676f6f67" "6c652e63727970746f2e74696e6b2e486d61634b657912281a20cca20f02278003b3513f" "5d01759ac1302f7d883f2f4a40025532ee1b11f9e587120410100803180110011895e59b" "cc062001"); crypto::tink::util::StatusOr keyset_handle = ParseKeysetFromProtoKeysetFormat(serialized_keyset, InsecureSecretKeyAccess::Get()); ASSERT_THAT(keyset_handle.status(), IsOk()); crypto::tink::util::StatusOr> mac = (*keyset_handle).GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(mac.status(), IsOk()); ASSERT_THAT( (*mac)->VerifyMac( absl::HexStringToBytes("016986f2956092d259136923c6f4323557714ec499"), "data"), IsOk()); } TEST_F(SerializeKeysetToProtoKeysetFormatTest, SerializeAndParsePublicKey) { util::StatusOr parameters = EcdsaParameters(); ASSERT_THAT(parameters, IsOk()); util::StatusOr handle = KeysetHandleBuilder() .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams( *parameters, KeyStatus::kEnabled, /*is_primary=*/true, /*id=*/123)) .Build(); ASSERT_THAT(handle, IsOk()); util::StatusOr> public_handle = handle->GetPublicKeysetHandle(KeyGenConfigGlobalRegistry()); ASSERT_THAT(public_handle, IsOk()); crypto::tink::util::StatusOr serialization1 = SerializeKeysetToProtoKeysetFormat(**public_handle, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization1, IsOk()); crypto::tink::util::StatusOr serialization2 = SerializeKeysetWithoutSecretToProtoKeysetFormat(**public_handle); ASSERT_THAT(serialization2, IsOk()); util::StatusOr parsed_handle1 = ParseKeysetFromProtoKeysetFormat(SecretDataAsStringView(*serialization1), InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_handle1, IsOk()); util::StatusOr parsed_handle2 = ParseKeysetWithoutSecretFromProtoKeysetFormat( SecretDataAsStringView(*serialization1)); ASSERT_THAT(parsed_handle2, IsOk()); util::StatusOr parsed_handle3 = ParseKeysetFromProtoKeysetFormat(*serialization2, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_handle3, IsOk()); util::StatusOr parsed_handle4 = ParseKeysetWithoutSecretFromProtoKeysetFormat(*serialization2); ASSERT_THAT(parsed_handle4, IsOk()); ASSERT_THAT((*public_handle)->size(), Eq(1)); ASSERT_THAT(parsed_handle1->size(), Eq(1)); ASSERT_THAT(parsed_handle2->size(), Eq(1)); ASSERT_THAT(parsed_handle3->size(), Eq(1)); ASSERT_THAT(parsed_handle4->size(), Eq(1)); // TODO(b/277791403): Replace with KeysetHandle::Entry equality checks. EXPECT_TRUE(*(**public_handle)[0].GetKey() == *(*parsed_handle1)[0].GetKey()); EXPECT_TRUE(*(**public_handle)[0].GetKey() == *(*parsed_handle2)[0].GetKey()); EXPECT_TRUE(*(**public_handle)[0].GetKey() == *(*parsed_handle3)[0].GetKey()); EXPECT_TRUE(*(**public_handle)[0].GetKey() == *(*parsed_handle4)[0].GetKey()); EXPECT_TRUE((**public_handle)[0].GetId() == (*parsed_handle1)[0].GetId()); EXPECT_TRUE((**public_handle)[0].GetId() == (*parsed_handle2)[0].GetId()); EXPECT_TRUE((**public_handle)[0].GetId() == (*parsed_handle3)[0].GetId()); EXPECT_TRUE((**public_handle)[0].GetId() == (*parsed_handle4)[0].GetId()); EXPECT_TRUE((**public_handle)[0].GetStatus() == (*parsed_handle1)[0].GetStatus()); EXPECT_TRUE((**public_handle)[0].GetStatus() == (*parsed_handle2)[0].GetStatus()); EXPECT_TRUE((**public_handle)[0].GetStatus() == (*parsed_handle3)[0].GetStatus()); EXPECT_TRUE((**public_handle)[0].GetStatus() == (*parsed_handle4)[0].GetStatus()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/public_key_sign.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_PUBLIC_KEY_SIGN_H_ #define TINK_PUBLIC_KEY_SIGN_H_ #include #include "absl/strings/string_view.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Interface for public key signing. // Digital Signatures provide functionality of signing data and verification of // the signatures. They are represented by a pair of primitives (interfaces) // 'PublicKeySign' for signing of data, and 'PublicKeyVerify' for verification // of signatures. Implementations of these interfaces are secure against // adaptive chosen-message attacks. Signing data ensures the authenticity and // the integrity of that data, but not its secrecy. class PublicKeySign { public: // Computes the signature for 'data'. virtual crypto::tink::util::StatusOr Sign( absl::string_view data) const = 0; virtual ~PublicKeySign() = default; }; } // namespace tink } // namespace crypto #endif // TINK_PUBLIC_KEY_SIGN_H_ ================================================ FILE: cc/public_key_sign_factory.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_PUBLIC_KEY_SIGN_FACTORY_H_ #define TINK_PUBLIC_KEY_SIGN_FACTORY_H_ #include "tink/signature/public_key_sign_factory.h" // IWYU pragma: export #endif // TINK_PUBLIC_KEY_SIGN_FACTORY_H_ ================================================ FILE: cc/public_key_verify.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_PUBLIC_KEY_VERIFY_H_ #define TINK_PUBLIC_KEY_VERIFY_H_ #include "absl/strings/string_view.h" #include "tink/util/status.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Interface for public key verifying. // Digital Signatures provide functionality of signing data and verification of // the signatures. They are represented by a pair of primitives (interfaces) // 'PublicKeySign' for signing of data, and 'PublicKeyVerify' for verification // of signatures. Implementations of these interfaces are secure against // adaptive chosen-message attacks. Signing data ensures the authenticity and // the integrity of that data, but not its secrecy. class PublicKeyVerify { public: // Verifies that 'signature' is a digital signature for 'data'. virtual crypto::tink::util::Status Verify( absl::string_view signature, absl::string_view data) const = 0; virtual ~PublicKeyVerify() = default; }; } // namespace tink } // namespace crypto #endif // TINK_PUBLIC_KEY_VERIFY_H_ ================================================ FILE: cc/public_key_verify_factory.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_PUBLIC_KEY_VERIFY_FACTORY_H_ #define TINK_PUBLIC_KEY_VERIFY_FACTORY_H_ #include "tink/signature/public_key_verify_factory.h" // IWYU pragma: export #endif // TINK_PUBLIC_KEY_VERIFY_FACTORY_H_ ================================================ FILE: cc/random_access_stream.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_RANDOM_ACCESS_STREAM_H_ #define TINK_RANDOM_ACCESS_STREAM_H_ #include #include "tink/util/buffer.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Abstract interface for streams that provide random access for reading, // like regular files. class RandomAccessStream { public: RandomAccessStream() = default; virtual ~RandomAccessStream() = default; // Reads up to 'count' bytes starting at 'position' and writes them // to 'dest_buffer'. 'position' must be within the size of the stream, // 'count' must be positive, 'dest_buffer' must be non-NULL and its // allocated size must be not smaller than 'count'. // // Return values: // OK: if exactly 'count' bytes were read and written to 'dest_buffer', // or if fewer than 'count' (potentially 0) bytes were read, // but the lack of bytes is not permanent, and retrying may succeed; // in this case 'dest_buffer' contains the read bytes, and the size // of the buffer has been changed to the number of bytes read. // OUT_OF_RANGE: if the end of stream has been reached; // in this case 'dest_buffer' contains the bytes read till the end // of the stream (if any). This status is returned also when // 'position' is larger than the current size of the stream. // INVALID_ARGUMENT: if some of the arguments are not valid. // other: if some other error occurred. virtual crypto::tink::util::Status PRead( int64_t position, int count, crypto::tink::util::Buffer* dest_buffer) = 0; // Returns the size of this stream in bytes, if available. // If the size is not available, returns a non-Ok status. // The returned value is the "logical" size of a stream, i.e. of // a sequence of bytes), stating how many bytes are there in the sequence. // For a successful PRead-operation the starting position should be // in the range 0..size()-1 (otherwise PRead may return a non-Ok status). virtual crypto::tink::util::StatusOr size() = 0; }; } // namespace tink } // namespace crypto #endif // TINK_RANDOM_ACCESS_STREAM_H_ ================================================ FILE: cc/registry.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_REGISTRY_H_ #define TINK_REGISTRY_H_ #include #include #include "absl/strings/string_view.h" #include "tink/internal/registry_impl.h" #include "tink/key_manager.h" #include "tink/primitive_set.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // Registry for KeyMangers and PrimitiveWrappers. // // It is essentially a big container (map) that for each supported key type // holds a corresponding KeyManager object, which "understands" the key type // (i.e. the KeyManager can instantiate the primitive corresponding to given // key, or can generate new keys of the supported key type). It holds also // a so-called PrimitiveWrapper for each supported primitive, so that it can // wrap a set of primitives (corresponding to a keyset) into a single primitive. // // Registry is initialized at startup, and is later used to instantiate // primitives for given keys or keysets. Keeping KeyManagers for all primitives // in a single Registry (rather than having a separate KeyManager per primitive) // enables modular construction of compound primitives from "simple" ones, e.g., // AES-CTR-HMAC AEAD encryption uses IND-CPA encryption and a MAC. // // Note that regular users will usually not work directly with Registry, but // rather via KeysetHandle::GetPrimitive()-methods, which in the background // query the Registry for specific KeyManagers and PrimitiveWrappers. // Registry is public though, to enable configurations with custom primitives // and KeyManagers. class Registry { public: // Registers the given 'manager' for the key type 'manager->get_key_type()'. template static crypto::tink::util::Status RegisterKeyManager( std::unique_ptr manager, bool new_key_allowed) { return internal::RegistryImpl::GlobalInstance().RegisterKeyManager( manager.release(), new_key_allowed); } template static crypto::tink::util::Status RegisterKeyTypeManager( std::unique_ptr manager, bool new_key_allowed) { return internal::RegistryImpl::GlobalInstance() .RegisterKeyTypeManager( std::move(manager), new_key_allowed); } template static crypto::tink::util::Status RegisterAsymmetricKeyManagers( std::unique_ptr private_key_manager, std::unique_ptr public_key_manager, bool new_key_allowed) { return internal::RegistryImpl::GlobalInstance() .RegisterAsymmetricKeyManagers(private_key_manager.release(), public_key_manager.release(), new_key_allowed); } template static crypto::tink::util::Status RegisterPrimitiveWrapper( std::unique_ptr wrapper) { return internal::RegistryImpl::GlobalInstance().RegisterPrimitiveWrapper( wrapper.release()); } // Returns a key manager for the given type_url (if any found). // Keeps the ownership of the manager. Returned key_managers are guaranteed // to stay valid for the lifetime of the binary (with the exception of a user // calling Reset()). // TODO(tholenst): Remove Reset() from the interface, as it could violate this // but should be test only anyhow. template static crypto::tink::util::StatusOr*> get_key_manager( absl::string_view type_url) { return internal::RegistryImpl::GlobalInstance().get_key_manager

( type_url); } // Convenience method for creating a new primitive for the key given // in 'key_data'. It looks up a KeyManager identified by key_data.type_url, // and calls manager's GetPrimitive(key_data)-method. template static crypto::tink::util::StatusOr> GetPrimitive( const google::crypto::tink::KeyData& key_data) { return internal::RegistryImpl::GlobalInstance().GetPrimitive

(key_data); } // Generates a new KeyData for the specified 'key_template'. // It looks up a KeyManager identified by key_template.type_url, // and calls KeyManager::NewKeyData. // This method should be used solely for key management. static crypto::tink::util::StatusOr< std::unique_ptr> NewKeyData(const google::crypto::tink::KeyTemplate& key_template) { return internal::RegistryImpl::GlobalInstance().NewKeyData(key_template); } // Convenience method for extracting the public key data from the // private key given in serialized_private_key. // It looks up a KeyManager identified by type_url, whose KeyFactory must be // a PrivateKeyFactory, and calls PrivateKeyFactory::GetPublicKeyData. static crypto::tink::util::StatusOr< std::unique_ptr> GetPublicKeyData(absl::string_view type_url, absl::string_view serialized_private_key) { return internal::RegistryImpl::GlobalInstance().GetPublicKeyData( type_url, serialized_private_key); } // Looks up the globally registered PrimitiveWrapper for this primitive // and wraps the given PrimitiveSet with it. template static crypto::tink::util::StatusOr> Wrap( std::unique_ptr> primitive_set) { return internal::RegistryImpl::GlobalInstance().Wrap

( std::move(primitive_set)); } // Resets the registry. // After reset the registry is empty, i.e. it contains neither catalogues // nor key managers. This method is intended for testing only. static void Reset() { return internal::RegistryImpl::GlobalInstance().Reset(); } }; } // namespace tink } // namespace crypto #endif // TINK_REGISTRY_H_ ================================================ FILE: cc/restricted_big_integer.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_RESTRICTED_BIG_INTEGER_H_ #define TINK_RESTRICTED_BIG_INTEGER_H_ #include #include "absl/strings/string_view.h" #include "tink/secret_key_access_token.h" #include "tink/util/secret_data.h" namespace crypto { namespace tink { // Stores a RestrictedBigInteger value as a big endian encoded string, which // requires secret key access. Removes leading zeros prior to creation. // This class is particularly useful for working with certain primitives which // use secret big integers types for the key material. class RestrictedBigInteger { public: // Copyable and movable. RestrictedBigInteger(const RestrictedBigInteger& other) = default; RestrictedBigInteger& operator=(const RestrictedBigInteger& other) = default; RestrictedBigInteger(RestrictedBigInteger&& other) = default; RestrictedBigInteger& operator=(RestrictedBigInteger&& other) = default; // Creates a new RestrictedBigInteger object that wraps `secret_big_integer`, // after removing the leading zeros. Note that creating a `token` requires // access to InsecureSecretKeyAccess::Get(). explicit RestrictedBigInteger(absl::string_view secret_big_integer, SecretKeyAccessToken token); // Returns the value of this RestrictedBigInteger object. absl::string_view GetSecret(SecretKeyAccessToken token) const { return util::SecretDataAsStringView(secret_); } int64_t SizeInBytes() const { return secret_.size(); } bool operator==(const RestrictedBigInteger& other) const; bool operator!=(const RestrictedBigInteger& other) const { return !(*this == other); } private: util::SecretData secret_; }; } // namespace tink } // namespace crypto #endif // TINK_RESTRICTED_BIG_INTEGER_H_ ================================================ FILE: cc/restricted_data.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_RESTRICTED_DATA_H_ #define TINK_RESTRICTED_DATA_H_ #include #include "absl/strings/string_view.h" #include "tink/secret_key_access_token.h" #include "tink/util/secret_data.h" namespace crypto { namespace tink { // Stores secret (sensitive) data that is safely destroyed in the event of // core dumps (similar to `util::SecretData`) and access restricted via // `SecurityKeyAccessToken`. This class is particularly useful for // encapsulating cryptographic key material. // // Example: // RestrictedData restricted_data(/*num_random_bytes=*/32); // absl::string_view raw_secret = // restricted_data.GetSecret(InsecureSecretKeyAccess::Get()); class RestrictedData { public: // Copyable and movable. RestrictedData(const RestrictedData& other) = default; RestrictedData& operator=(const RestrictedData& other) = default; RestrictedData(RestrictedData&& other) = default; RestrictedData& operator=(RestrictedData&& other) = default; // Creates a new RestrictedData object that wraps `secret`. Note that creating // a `token` requires access to `InsecureSecretKeyAccess::Get()`. explicit RestrictedData(absl::string_view secret, SecretKeyAccessToken token) : secret_(util::SecretDataFromStringView(secret)) {} // Creates a new RestrictedData object that wraps a secret containing // `num_random_bytes`. The program will terminate if `num_random_bytes` is a // negative value. explicit RestrictedData(int64_t num_random_bytes); // Returns the secret for this RestrictedData object. Note that creating a // `token` requires access to `InsecureSecretKeyAccess::Get()`. absl::string_view GetSecret(SecretKeyAccessToken token) const { return util::SecretDataAsStringView(secret_); } int64_t size() const { return secret_.size(); } // Constant-time comparison operators. bool operator==(const RestrictedData& other) const; bool operator!=(const RestrictedData& other) const { return !(*this == other); } private: util::SecretData secret_; }; } // namespace tink } // namespace crypto #endif // TINK_RESTRICTED_DATA_H_ ================================================ FILE: cc/secret_key_access.h ================================================ // Copyright 2021 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SECRET_KEY_ACCESS_H_ #define TINK_SECRET_KEY_ACCESS_H_ #include "tink/key_access.h" namespace crypto { namespace tink { class SecretKeyAccess { public: static KeyAccess SecretAccess() { return KeyAccess(true); } }; } // namespace tink } // namespace crypto #endif // TINK_SECRET_KEY_ACCESS_H_ ================================================ FILE: cc/secret_key_access_token.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SECRET_KEY_ACCESS_TOKEN_H_ #define TINK_SECRET_KEY_ACCESS_TOKEN_H_ namespace crypto { namespace tink { class SecretKeyAccessToken { public: // Copyable and movable. SecretKeyAccessToken(const SecretKeyAccessToken& other) = default; SecretKeyAccessToken& operator=(const SecretKeyAccessToken& other) = default; SecretKeyAccessToken(SecretKeyAccessToken&& other) = default; SecretKeyAccessToken& operator=(SecretKeyAccessToken&& other) = default; private: // `InsecureKeyAccess` class requires access to the constructor. friend class InsecureSecretKeyAccess; SecretKeyAccessToken() = default; }; } // namespace tink } // namespace crypto #endif // TINK_SECRET_KEY_ACCESS_TOKEN_H_ ================================================ FILE: cc/signature/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "public_key_verify_wrapper", srcs = ["public_key_verify_wrapper.cc"], hdrs = ["public_key_verify_wrapper.h"], include_prefix = "tink/signature", deps = [ "//:crypto_format", "//:primitive_set", "//:primitive_wrapper", "//:public_key_verify", "//internal:monitoring_util", "//internal:registry_impl", "//internal:util", "//monitoring", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "public_key_verify_factory", srcs = ["public_key_verify_factory.cc"], hdrs = ["public_key_verify_factory.h"], include_prefix = "tink/signature", deps = [ ":public_key_verify_wrapper", "//:key_manager", "//:keyset_handle", "//:public_key_verify", "//:registry", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", ], ) cc_library( name = "public_key_sign_wrapper", srcs = ["public_key_sign_wrapper.cc"], hdrs = ["public_key_sign_wrapper.h"], include_prefix = "tink/signature", deps = [ "//:crypto_format", "//:primitive_set", "//:primitive_wrapper", "//:public_key_sign", "//internal:monitoring_util", "//internal:registry_impl", "//internal:util", "//monitoring", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "public_key_sign_factory", srcs = ["public_key_sign_factory.cc"], hdrs = ["public_key_sign_factory.h"], include_prefix = "tink/signature", deps = [ ":public_key_sign_wrapper", "//:key_manager", "//:keyset_handle", "//:public_key_sign", "//:registry", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", ], ) cc_library( name = "signature_key_templates", srcs = ["signature_key_templates.cc"], hdrs = ["signature_key_templates.h"], include_prefix = "tink/signature", visibility = ["//visibility:public"], deps = [ "//internal:bn_util", "//internal:ssl_unique_ptr", "//proto:common_cc_proto", "//proto:ecdsa_cc_proto", "//proto:ed25519_cc_proto", "//proto:rsa_ssa_pkcs1_cc_proto", "//proto:rsa_ssa_pss_cc_proto", "//proto:tink_cc_proto", "//util:constants", "@boringssl//:crypto", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/memory", "@com_google_absl//absl/strings", ], ) cc_library( name = "ecdsa_sign_key_manager", srcs = ["ecdsa_sign_key_manager.cc"], hdrs = ["ecdsa_sign_key_manager.h"], include_prefix = "tink/signature", deps = [ ":ecdsa_verify_key_manager", "//:core/private_key_type_manager", "//:core/template_util", "//:input_stream", "//:public_key_sign", "//config:tink_fips", "//internal:ec_util", "//internal:fips_utils", "//proto:ecdsa_cc_proto", "//proto:tink_cc_proto", "//subtle:ecdsa_sign_boringssl", "//util:constants", "//util:enums", "//util:errors", "//util:input_stream_util", "//util:protobuf_helper", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "ecdsa_verify_key_manager", srcs = ["ecdsa_verify_key_manager.cc"], hdrs = ["ecdsa_verify_key_manager.h"], include_prefix = "tink/signature", deps = [ "//:core/key_type_manager", "//:core/template_util", "//:public_key_verify", "//internal:ec_util", "//internal:fips_utils", "//proto:ecdsa_cc_proto", "//proto:tink_cc_proto", "//subtle:ecdsa_verify_boringssl", "//util:constants", "//util:enums", "//util:errors", "//util:protobuf_helper", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "ed25519_sign_key_manager", srcs = ["ed25519_sign_key_manager.cc"], hdrs = ["ed25519_sign_key_manager.h"], include_prefix = "tink/signature", deps = [ ":ed25519_verify_key_manager", "//:core/private_key_type_manager", "//:core/template_util", "//:input_stream", "//:public_key_sign", "//internal:ec_util", "//proto:ed25519_cc_proto", "//proto:tink_cc_proto", "//subtle:ed25519_sign_boringssl", "//util:constants", "//util:enums", "//util:errors", "//util:input_stream_util", "//util:protobuf_helper", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "ed25519_verify_key_manager", srcs = ["ed25519_verify_key_manager.cc"], hdrs = ["ed25519_verify_key_manager.h"], include_prefix = "tink/signature", deps = [ "//:core/key_type_manager", "//:core/template_util", "//:public_key_verify", "//proto:ed25519_cc_proto", "//proto:tink_cc_proto", "//subtle:ed25519_verify_boringssl", "//util:constants", "//util:errors", "//util:protobuf_helper", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "sig_util", srcs = ["sig_util.cc"], hdrs = ["sig_util.h"], include_prefix = "tink/signature", deps = [ "//:public_key_sign", "//:public_key_verify", "//util:status", ], ) cc_library( name = "rsa_ssa_pkcs1_sign_key_manager", srcs = ["rsa_ssa_pkcs1_sign_key_manager.cc"], hdrs = ["rsa_ssa_pkcs1_sign_key_manager.h"], include_prefix = "tink/signature", deps = [ ":rsa_ssa_pkcs1_verify_key_manager", ":sig_util", "//:core/private_key_type_manager", "//:core/template_util", "//:public_key_sign", "//:public_key_verify", "//internal:bn_util", "//internal:fips_utils", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//proto:rsa_ssa_pkcs1_cc_proto", "//proto:tink_cc_proto", "//subtle:rsa_ssa_pkcs1_sign_boringssl", "//util:constants", "//util:enums", "//util:errors", "//util:protobuf_helper", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "rsa_ssa_pkcs1_verify_key_manager", srcs = ["rsa_ssa_pkcs1_verify_key_manager.cc"], hdrs = ["rsa_ssa_pkcs1_verify_key_manager.h"], include_prefix = "tink/signature", deps = [ "//:core/key_type_manager", "//:core/template_util", "//:public_key_verify", "//internal:bn_util", "//internal:fips_utils", "//internal:md_util", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//proto:rsa_ssa_pkcs1_cc_proto", "//proto:tink_cc_proto", "//subtle:rsa_ssa_pkcs1_verify_boringssl", "//util:constants", "//util:enums", "//util:errors", "//util:protobuf_helper", "//util:status", "//util:statusor", "//util:validation", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/strings", ], ) cc_library( name = "rsa_ssa_pss_sign_key_manager", srcs = ["rsa_ssa_pss_sign_key_manager.cc"], hdrs = ["rsa_ssa_pss_sign_key_manager.h"], include_prefix = "tink/signature", deps = [ ":rsa_ssa_pss_verify_key_manager", ":sig_util", "//:core/key_type_manager", "//:core/private_key_type_manager", "//:core/template_util", "//:public_key_sign", "//:public_key_verify", "//internal:bn_util", "//internal:fips_utils", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//proto:rsa_ssa_pss_cc_proto", "//proto:tink_cc_proto", "//subtle:rsa_ssa_pss_sign_boringssl", "//util:constants", "//util:enums", "//util:errors", "//util:protobuf_helper", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "rsa_ssa_pss_verify_key_manager", srcs = ["rsa_ssa_pss_verify_key_manager.cc"], hdrs = ["rsa_ssa_pss_verify_key_manager.h"], include_prefix = "tink/signature", deps = [ "//:core/key_type_manager", "//:core/private_key_type_manager", "//:core/template_util", "//:public_key_sign", "//:public_key_verify", "//internal:bn_util", "//internal:fips_utils", "//internal:md_util", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//proto:rsa_ssa_pss_cc_proto", "//proto:tink_cc_proto", "//subtle:rsa_ssa_pss_verify_boringssl", "//util:constants", "//util:enums", "//util:errors", "//util:protobuf_helper", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "signature_config", srcs = ["signature_config.cc"], hdrs = ["signature_config.h"], include_prefix = "tink/signature", visibility = ["//visibility:public"], deps = [ ":ecdsa_proto_serialization", ":ecdsa_sign_key_manager", ":ecdsa_verify_key_manager", ":ed25519_sign_key_manager", ":ed25519_verify_key_manager", ":public_key_sign_wrapper", ":public_key_verify_wrapper", ":rsa_ssa_pkcs1_proto_serialization", ":rsa_ssa_pkcs1_sign_key_manager", ":rsa_ssa_pkcs1_verify_key_manager", ":rsa_ssa_pss_proto_serialization", ":rsa_ssa_pss_sign_key_manager", ":rsa_ssa_pss_verify_key_manager", "//:registry", "//config:config_util", "//config:tink_fips", "//proto:config_cc_proto", "//util:status", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/memory", ], ) cc_library( name = "signature_pem_keyset_reader", srcs = ["signature_pem_keyset_reader.cc"], hdrs = ["signature_pem_keyset_reader.h"], include_prefix = "tink/signature", deps = [ ":ecdsa_verify_key_manager", ":rsa_ssa_pkcs1_sign_key_manager", ":rsa_ssa_pkcs1_verify_key_manager", ":rsa_ssa_pss_sign_key_manager", ":rsa_ssa_pss_verify_key_manager", "//:keyset_reader", "//internal:ec_util", "//internal:rsa_util", "//proto:common_cc_proto", "//proto:ecdsa_cc_proto", "//proto:rsa_ssa_pkcs1_cc_proto", "//proto:rsa_ssa_pss_cc_proto", "//proto:tink_cc_proto", "//subtle:pem_parser_boringssl", "//util:enums", "//util:keyset_util", "//util:secret_data", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "failing_signature", srcs = ["failing_signature.cc"], hdrs = ["failing_signature.h"], include_prefix = "tink/signature", deps = [ "//:public_key_sign", "//:public_key_verify", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "signature_parameters", hdrs = ["signature_parameters.h"], include_prefix = "tink/signature", deps = ["//:parameters"], ) cc_library( name = "signature_public_key", hdrs = ["signature_public_key.h"], include_prefix = "tink/signature", deps = [ ":signature_parameters", "//:key", "@com_google_absl//absl/strings", ], ) cc_library( name = "signature_private_key", hdrs = ["signature_private_key.h"], include_prefix = "tink/signature", deps = [ ":signature_parameters", ":signature_public_key", "//:key", "//:private_key", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "ed25519_parameters", srcs = ["ed25519_parameters.cc"], hdrs = ["ed25519_parameters.h"], include_prefix = "tink/signature", deps = [ ":signature_parameters", "//:parameters", "//util:status", "//util:statusor", "@com_google_absl//absl/status", ], ) cc_library( name = "ed25519_public_key", srcs = ["ed25519_public_key.cc"], hdrs = ["ed25519_public_key.h"], include_prefix = "tink/signature", deps = [ ":ed25519_parameters", ":signature_public_key", "//:key", "//:partial_key_access_token", "//subtle:subtle_util", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "ed25519_private_key", srcs = ["ed25519_private_key.cc"], hdrs = ["ed25519_private_key.h"], include_prefix = "tink/signature", deps = [ ":ed25519_public_key", ":signature_private_key", "//:insecure_secret_key_access", "//:key", "//:partial_key_access_token", "//:restricted_data", "//internal:ec_util", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "ed25519_proto_serialization", srcs = ["ed25519_proto_serialization.cc"], hdrs = ["ed25519_proto_serialization.h"], include_prefix = "tink/signature", deps = [ ":ed25519_parameters", ":ed25519_private_key", ":ed25519_public_key", "//:insecure_secret_key_access", "//:partial_key_access", "//:restricted_data", "//:secret_key_access_token", "//internal:key_parser", "//internal:key_serializer", "//internal:mutable_serialization_registry", "//internal:parameters_parser", "//internal:parameters_serializer", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//proto:ed25519_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "rsa_ssa_pkcs1_parameters", srcs = ["rsa_ssa_pkcs1_parameters.cc"], hdrs = ["rsa_ssa_pkcs1_parameters.h"], include_prefix = "tink/signature", deps = [ ":signature_parameters", "//:big_integer", "//:parameters", "//internal:bn_util", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "rsa_ssa_pkcs1_public_key", srcs = ["rsa_ssa_pkcs1_public_key.cc"], hdrs = ["rsa_ssa_pkcs1_public_key.h"], include_prefix = "tink/signature", deps = [ ":rsa_ssa_pkcs1_parameters", ":signature_public_key", "//:big_integer", "//:key", "//:partial_key_access_token", "//subtle:subtle_util", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:str_format", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "rsa_ssa_pkcs1_private_key", srcs = ["rsa_ssa_pkcs1_private_key.cc"], hdrs = ["rsa_ssa_pkcs1_private_key.h"], include_prefix = "tink/signature", deps = [ ":rsa_ssa_pkcs1_public_key", ":signature_private_key", "//:big_integer", "//:insecure_secret_key_access", "//:key", "//:partial_key_access_token", "//:restricted_big_integer", "//internal:bn_util", "//internal:ssl_unique_ptr", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "config_v0", srcs = ["config_v0.cc"], hdrs = ["config_v0.h"], include_prefix = "tink/signature", deps = [ "//:configuration", "//signature/internal:config_v0", "@com_google_absl//absl/log:check", ], ) cc_library( name = "key_gen_config_v0", srcs = ["key_gen_config_v0.cc"], hdrs = ["key_gen_config_v0.h"], include_prefix = "tink/signature", deps = [ "//:key_gen_configuration", "//signature/internal:key_gen_config_v0", "@com_google_absl//absl/log:check", ], ) cc_library( name = "rsa_ssa_pkcs1_proto_serialization", srcs = ["rsa_ssa_pkcs1_proto_serialization.cc"], hdrs = ["rsa_ssa_pkcs1_proto_serialization.h"], include_prefix = "tink/signature", deps = [ ":rsa_ssa_pkcs1_parameters", ":rsa_ssa_pkcs1_private_key", ":rsa_ssa_pkcs1_public_key", "//:big_integer", "//:insecure_secret_key_access", "//:partial_key_access", "//:restricted_big_integer", "//:restricted_data", "//:secret_key_access_token", "//internal:key_parser", "//internal:key_serializer", "//internal:mutable_serialization_registry", "//internal:parameters_parser", "//internal:parameters_serializer", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//proto:common_cc_proto", "//proto:rsa_ssa_pkcs1_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "rsa_ssa_pss_parameters", srcs = ["rsa_ssa_pss_parameters.cc"], hdrs = ["rsa_ssa_pss_parameters.h"], include_prefix = "tink/signature", deps = [ ":signature_parameters", "//:big_integer", "//:parameters", "//internal:bn_util", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "rsa_ssa_pss_public_key", srcs = ["rsa_ssa_pss_public_key.cc"], hdrs = ["rsa_ssa_pss_public_key.h"], include_prefix = "tink/signature", deps = [ ":rsa_ssa_pss_parameters", ":signature_public_key", "//:big_integer", "//:key", "//:partial_key_access_token", "//subtle:subtle_util", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:str_format", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "rsa_ssa_pss_private_key", srcs = ["rsa_ssa_pss_private_key.cc"], hdrs = ["rsa_ssa_pss_private_key.h"], include_prefix = "tink/signature", deps = [ ":rsa_ssa_pss_public_key", ":signature_private_key", "//:big_integer", "//:insecure_secret_key_access", "//:key", "//:partial_key_access_token", "//:restricted_big_integer", "//internal:bn_util", "//internal:ssl_unique_ptr", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "rsa_ssa_pss_proto_serialization", srcs = ["rsa_ssa_pss_proto_serialization.cc"], hdrs = ["rsa_ssa_pss_proto_serialization.h"], include_prefix = "tink/signature", deps = [ ":rsa_ssa_pss_parameters", ":rsa_ssa_pss_private_key", ":rsa_ssa_pss_public_key", "//:big_integer", "//:insecure_secret_key_access", "//:partial_key_access", "//:restricted_big_integer", "//:restricted_data", "//:secret_key_access_token", "//internal:key_parser", "//internal:key_serializer", "//internal:mutable_serialization_registry", "//internal:parameters_parser", "//internal:parameters_serializer", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//proto:common_cc_proto", "//proto:rsa_ssa_pss_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "ecdsa_parameters", srcs = ["ecdsa_parameters.cc"], hdrs = ["ecdsa_parameters.h"], include_prefix = "tink/signature", deps = [ ":signature_parameters", "//:parameters", "//util:status", "//util:statusor", "@com_google_absl//absl/algorithm:container", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "ecdsa_public_key", srcs = ["ecdsa_public_key.cc"], hdrs = ["ecdsa_public_key.h"], include_prefix = "tink/signature", deps = [ ":ecdsa_parameters", ":signature_public_key", "//:ec_point", "//:key", "//:partial_key_access_token", "//internal:ec_util", "//internal:ssl_unique_ptr", "//subtle:common_enums", "//subtle:subtle_util", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) cc_library( name = "ecdsa_private_key", srcs = ["ecdsa_private_key.cc"], hdrs = ["ecdsa_private_key.h"], include_prefix = "tink/signature", deps = [ ":ecdsa_parameters", ":ecdsa_public_key", ":signature_private_key", "//:ec_point", "//:insecure_secret_key_access", "//:key", "//:partial_key_access_token", "//:restricted_big_integer", "//internal:bn_util", "//internal:ec_util", "//internal:err_util", "//internal:ssl_unique_ptr", "//subtle:common_enums", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "ecdsa_proto_serialization", srcs = ["ecdsa_proto_serialization.cc"], hdrs = ["ecdsa_proto_serialization.h"], include_prefix = "tink/signature", deps = [ ":ecdsa_parameters", ":ecdsa_private_key", ":ecdsa_public_key", "//:big_integer", "//:ec_point", "//:insecure_secret_key_access", "//:partial_key_access", "//:restricted_big_integer", "//:restricted_data", "//:secret_key_access_token", "//internal:bn_encoding_util", "//internal:key_parser", "//internal:key_serializer", "//internal:mutable_serialization_registry", "//internal:parameters_parser", "//internal:parameters_serializer", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//proto:common_cc_proto", "//proto:ecdsa_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", ], ) # tests cc_test( name = "public_key_verify_wrapper_test", size = "small", srcs = ["public_key_verify_wrapper_test.cc"], deps = [ ":failing_signature", ":public_key_verify_wrapper", "//:primitive_set", "//:public_key_sign", "//:public_key_verify", "//:registry", "//internal:registry_impl", "//monitoring", "//monitoring:monitoring_client_mocks", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "public_key_verify_factory_test", size = "small", srcs = ["public_key_verify_factory_test.cc"], deps = [ ":ecdsa_verify_key_manager", ":public_key_verify_factory", ":signature_config", "//:crypto_format", "//:keyset_handle", "//:public_key_verify", "//:registry", "//proto:ecdsa_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:test_keyset_handle", "//util:test_util", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "public_key_sign_wrapper_test", size = "small", srcs = ["public_key_sign_wrapper_test.cc"], deps = [ ":failing_signature", ":public_key_sign_wrapper", "//:crypto_format", "//:primitive_set", "//:public_key_sign", "//:public_key_verify", "//:registry", "//internal:registry_impl", "//monitoring", "//monitoring:monitoring_client_mocks", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "public_key_sign_factory_test", size = "small", srcs = ["public_key_sign_factory_test.cc"], deps = [ ":ecdsa_sign_key_manager", ":public_key_sign_factory", ":signature_config", "//:crypto_format", "//:keyset_handle", "//:public_key_sign", "//:registry", "//proto:ecdsa_cc_proto", "//proto:tink_cc_proto", "//util:status", "//util:test_keyset_handle", "//util:test_util", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ecdsa_verify_key_manager_test", size = "small", srcs = ["ecdsa_verify_key_manager_test.cc"], deps = [ ":ecdsa_sign_key_manager", ":ecdsa_verify_key_manager", "//:public_key_sign", "//:public_key_verify", "//internal:ec_util", "//proto:ecdsa_cc_proto", "//proto:tink_cc_proto", "//subtle:ecdsa_sign_boringssl", "//util:enums", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ed25519_verify_key_manager_test", size = "small", srcs = ["ed25519_verify_key_manager_test.cc"], deps = [ ":ed25519_sign_key_manager", ":ed25519_verify_key_manager", "//:public_key_sign", "//:public_key_verify", "//:registry", "//proto:ed25519_cc_proto", "//proto:tink_cc_proto", "//subtle:ed25519_sign_boringssl", "//util:enums", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "rsa_ssa_pkcs1_verify_key_manager_test", size = "large", srcs = ["rsa_ssa_pkcs1_verify_key_manager_test.cc"], deps = [ ":rsa_ssa_pkcs1_sign_key_manager", ":rsa_ssa_pkcs1_verify_key_manager", "//:public_key_sign", "//:public_key_verify", "//internal:bn_util", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//proto:rsa_ssa_pkcs1_cc_proto", "//proto:tink_cc_proto", "//subtle:common_enums", "//subtle:rsa_ssa_pkcs1_sign_boringssl", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "rsa_ssa_pss_verify_key_manager_test", size = "large", srcs = ["rsa_ssa_pss_verify_key_manager_test.cc"], deps = [ ":rsa_ssa_pss_sign_key_manager", ":rsa_ssa_pss_verify_key_manager", "//:public_key_sign", "//:public_key_verify", "//internal:bn_util", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//proto:rsa_ssa_pss_cc_proto", "//proto:tink_cc_proto", "//subtle:common_enums", "//subtle:rsa_ssa_pss_sign_boringssl", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ecdsa_sign_key_manager_test", size = "small", srcs = ["ecdsa_sign_key_manager_test.cc"], deps = [ ":ecdsa_sign_key_manager", ":ecdsa_verify_key_manager", "//:public_key_sign", "//:public_key_verify", "//internal:ec_util", "//internal:ssl_util", "//proto:ecdsa_cc_proto", "//proto:tink_cc_proto", "//subtle:ecdsa_verify_boringssl", "//util:enums", "//util:istream_input_stream", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ed25519_sign_key_manager_test", size = "small", srcs = ["ed25519_sign_key_manager_test.cc"], deps = [ ":ed25519_sign_key_manager", ":ed25519_verify_key_manager", "//:public_key_sign", "//:public_key_verify", "//:registry", "//proto:ed25519_cc_proto", "//proto:tink_cc_proto", "//subtle:ed25519_verify_boringssl", "//util:enums", "//util:istream_input_stream", "//util:protobuf_helper", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "rsa_ssa_pkcs1_sign_key_manager_test", size = "large", srcs = ["rsa_ssa_pkcs1_sign_key_manager_test.cc"], deps = [ ":rsa_ssa_pkcs1_sign_key_manager", ":rsa_ssa_pkcs1_verify_key_manager", "//:public_key_sign", "//internal:bn_util", "//internal:ssl_unique_ptr", "//proto:rsa_ssa_pkcs1_cc_proto", "//proto:tink_cc_proto", "//subtle:common_enums", "//subtle:rsa_ssa_pkcs1_verify_boringssl", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@boringssl//:crypto", "@com_google_absl//absl/container:flat_hash_set", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "rsa_ssa_pss_sign_key_manager_test", size = "large", srcs = ["rsa_ssa_pss_sign_key_manager_test.cc"], deps = [ ":rsa_ssa_pss_sign_key_manager", ":rsa_ssa_pss_verify_key_manager", ":signature_key_templates", "//:public_key_sign", "//internal:bn_util", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//proto:rsa_ssa_pss_cc_proto", "//proto:tink_cc_proto", "//subtle:common_enums", "//subtle:rsa_ssa_pss_verify_boringssl", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@boringssl//:crypto", "@com_google_absl//absl/container:flat_hash_set", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "signature_config_test", size = "small", srcs = ["signature_config_test.cc"], tags = ["fips"], deps = [ ":ecdsa_parameters", ":ecdsa_private_key", ":ecdsa_public_key", ":key_gen_config_v0", ":rsa_ssa_pkcs1_parameters", ":rsa_ssa_pkcs1_private_key", ":rsa_ssa_pkcs1_public_key", ":rsa_ssa_pss_parameters", ":rsa_ssa_pss_private_key", ":rsa_ssa_pss_public_key", ":rsa_ssa_pss_sign_key_manager", ":rsa_ssa_pss_verify_key_manager", ":signature_config", ":signature_key_templates", "//:big_integer", "//:crypto_format", "//:ec_point", "//:insecure_secret_key_access", "//:key", "//:key_status", "//:keyset_handle", "//:keyset_handle_builder", "//:parameters", "//:partial_key_access", "//:primitive_set", "//:public_key_sign", "//:public_key_verify", "//:registry", "//:restricted_big_integer", "//:restricted_data", "//config:global_registry", "//internal:bn_util", "//internal:ec_util", "//internal:fips_utils", "//internal:legacy_proto_key", "//internal:mutable_serialization_registry", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//internal:serialization", "//internal:ssl_unique_ptr", "//proto:common_cc_proto", "//proto:rsa_ssa_pkcs1_cc_proto", "//proto:rsa_ssa_pss_cc_proto", "//proto:tink_cc_proto", "//subtle:common_enums", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@boringssl//:crypto", "@com_google_absl//absl/log:check", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "signature_key_templates_test", size = "large", srcs = ["signature_key_templates_test.cc"], deps = [ ":ecdsa_sign_key_manager", ":ecdsa_verify_key_manager", ":ed25519_sign_key_manager", ":ed25519_verify_key_manager", ":rsa_ssa_pkcs1_sign_key_manager", ":rsa_ssa_pss_sign_key_manager", ":signature_key_templates", "//:core/key_manager_impl", "//:core/private_key_manager_impl", "//:public_key_sign", "//internal:bn_util", "//internal:ssl_unique_ptr", "//proto:common_cc_proto", "//proto:ecdsa_cc_proto", "//proto:ed25519_cc_proto", "//proto:rsa_ssa_pkcs1_cc_proto", "//proto:rsa_ssa_pss_cc_proto", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "signature_pem_keyset_reader_test", size = "large", srcs = ["signature_pem_keyset_reader_test.cc"], deps = [ ":ecdsa_verify_key_manager", ":rsa_ssa_pss_sign_key_manager", ":rsa_ssa_pss_verify_key_manager", ":signature_config", ":signature_pem_keyset_reader", "//:tink_cc", "//internal:rsa_util", "//internal:ssl_util", "//proto:common_cc_proto", "//proto:ecdsa_cc_proto", "//proto:rsa_ssa_pss_cc_proto", "//proto:tink_cc_proto", "//subtle:pem_parser_boringssl", "//util:enums", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "failing_signature_test", srcs = ["failing_signature_test.cc"], deps = [ ":failing_signature", "//:public_key_sign", "//:public_key_verify", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ed25519_parameters_test", srcs = ["ed25519_parameters_test.cc"], deps = [ ":ed25519_parameters", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ed25519_public_key_test", srcs = ["ed25519_public_key_test.cc"], deps = [ ":ed25519_parameters", ":ed25519_public_key", "//:partial_key_access", "//subtle:random", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ed25519_private_key_test", srcs = ["ed25519_private_key_test.cc"], deps = [ ":ed25519_parameters", ":ed25519_private_key", ":ed25519_public_key", "//:insecure_secret_key_access", "//:partial_key_access", "//:restricted_data", "//internal:ec_util", "//subtle:random", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ed25519_proto_serialization_test", srcs = ["ed25519_proto_serialization_test.cc"], deps = [ ":ed25519_parameters", ":ed25519_private_key", ":ed25519_proto_serialization", ":ed25519_public_key", "//:insecure_secret_key_access", "//:key", "//:parameters", "//:partial_key_access", "//:restricted_data", "//internal:ec_util", "//internal:mutable_serialization_registry", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//internal:serialization", "//proto:ed25519_cc_proto", "//proto:tink_cc_proto", "//subtle:random", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "rsa_ssa_pkcs1_parameters_test", srcs = ["rsa_ssa_pkcs1_parameters_test.cc"], deps = [ ":rsa_ssa_pkcs1_parameters", "//:big_integer", "//internal:bn_util", "//internal:ssl_unique_ptr", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "rsa_ssa_pkcs1_public_key_test", srcs = ["rsa_ssa_pkcs1_public_key_test.cc"], deps = [ ":rsa_ssa_pkcs1_parameters", ":rsa_ssa_pkcs1_public_key", "//:big_integer", "//:partial_key_access", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "rsa_ssa_pkcs1_private_key_test", srcs = ["rsa_ssa_pkcs1_private_key_test.cc"], deps = [ ":rsa_ssa_pkcs1_parameters", ":rsa_ssa_pkcs1_private_key", ":rsa_ssa_pkcs1_public_key", "//:big_integer", "//:insecure_secret_key_access", "//:partial_key_access", "//:restricted_big_integer", "//internal:bn_util", "//internal:ssl_unique_ptr", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/log:check", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "config_v0_test", srcs = ["config_v0_test.cc"], deps = [ ":config_v0", ":key_gen_config_v0", ":signature_key_templates", "//:keyset_handle", "//:public_key_sign", "//:public_key_verify", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "rsa_ssa_pkcs1_proto_serialization_test", srcs = ["rsa_ssa_pkcs1_proto_serialization_test.cc"], deps = [ ":rsa_ssa_pkcs1_parameters", ":rsa_ssa_pkcs1_private_key", ":rsa_ssa_pkcs1_proto_serialization", ":rsa_ssa_pkcs1_public_key", "//:big_integer", "//:insecure_secret_key_access", "//:key", "//:parameters", "//:partial_key_access", "//:restricted_big_integer", "//:restricted_data", "//internal:bn_util", "//internal:mutable_serialization_registry", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//internal:serialization", "//internal:ssl_unique_ptr", "//proto:common_cc_proto", "//proto:rsa_ssa_pkcs1_cc_proto", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/log:check", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "rsa_ssa_pss_parameters_test", srcs = ["rsa_ssa_pss_parameters_test.cc"], deps = [ ":rsa_ssa_pss_parameters", "//:big_integer", "//internal:bn_util", "//internal:ssl_unique_ptr", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "rsa_ssa_pss_public_key_test", srcs = ["rsa_ssa_pss_public_key_test.cc"], deps = [ ":rsa_ssa_pss_parameters", ":rsa_ssa_pss_public_key", "//:big_integer", "//:partial_key_access", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "rsa_ssa_pss_private_key_test", srcs = ["rsa_ssa_pss_private_key_test.cc"], deps = [ ":rsa_ssa_pss_parameters", ":rsa_ssa_pss_private_key", ":rsa_ssa_pss_public_key", "//:big_integer", "//:insecure_secret_key_access", "//:partial_key_access", "//:restricted_big_integer", "//internal:bn_util", "//internal:ssl_unique_ptr", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/log:check", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "rsa_ssa_pss_proto_serialization_test", srcs = ["rsa_ssa_pss_proto_serialization_test.cc"], deps = [ ":rsa_ssa_pss_parameters", ":rsa_ssa_pss_private_key", ":rsa_ssa_pss_proto_serialization", ":rsa_ssa_pss_public_key", "//:big_integer", "//:insecure_secret_key_access", "//:key", "//:parameters", "//:partial_key_access", "//:restricted_big_integer", "//:restricted_data", "//internal:bn_util", "//internal:mutable_serialization_registry", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//internal:serialization", "//internal:ssl_unique_ptr", "//proto:common_cc_proto", "//proto:rsa_ssa_pss_cc_proto", "//proto:tink_cc_proto", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/log:check", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ecdsa_parameters_test", srcs = ["ecdsa_parameters_test.cc"], deps = [ ":ecdsa_parameters", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ecdsa_public_key_test", srcs = ["ecdsa_public_key_test.cc"], deps = [ ":ecdsa_parameters", ":ecdsa_public_key", "//:big_integer", "//:ec_point", "//:partial_key_access", "//internal:ec_util", "//subtle:common_enums", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ecdsa_private_key_test", srcs = ["ecdsa_private_key_test.cc"], deps = [ ":ecdsa_parameters", ":ecdsa_private_key", ":ecdsa_public_key", "//:big_integer", "//:ec_point", "//:insecure_secret_key_access", "//:partial_key_access", "//:restricted_big_integer", "//internal:ec_util", "//subtle:common_enums", "//util:secret_data", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ecdsa_proto_serialization_test", srcs = ["ecdsa_proto_serialization_test.cc"], deps = [ ":ecdsa_parameters", ":ecdsa_private_key", ":ecdsa_proto_serialization", ":ecdsa_public_key", "//:big_integer", "//:ec_point", "//:insecure_secret_key_access", "//:key", "//:parameters", "//:partial_key_access", "//:restricted_big_integer", "//:restricted_data", "//internal:ec_util", "//internal:mutable_serialization_registry", "//internal:proto_key_serialization", "//internal:proto_parameters_serialization", "//internal:serialization", "//proto:common_cc_proto", "//proto:ecdsa_cc_proto", "//proto:tink_cc_proto", "//subtle:common_enums", "//util:secret_data", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/signature/CMakeLists.txt ================================================ tink_module(signature) add_subdirectory(internal) tink_cc_library( NAME public_key_verify_wrapper SRCS public_key_verify_wrapper.cc public_key_verify_wrapper.h DEPS absl::memory absl::status absl::strings tink::core::crypto_format tink::core::primitive_set tink::core::primitive_wrapper tink::core::public_key_verify tink::internal::monitoring_util tink::internal::registry_impl tink::internal::util tink::monitoring::monitoring tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME public_key_verify_factory SRCS public_key_verify_factory.cc public_key_verify_factory.h DEPS tink::signature::public_key_verify_wrapper absl::core_headers tink::core::key_manager tink::core::keyset_handle tink::core::public_key_verify tink::core::registry tink::util::status tink::util::statusor ) tink_cc_library( NAME public_key_sign_wrapper SRCS public_key_sign_wrapper.cc public_key_sign_wrapper.h DEPS absl::memory absl::status absl::strings tink::core::crypto_format tink::core::primitive_set tink::core::primitive_wrapper tink::core::public_key_sign tink::internal::monitoring_util tink::internal::registry_impl tink::internal::util tink::monitoring::monitoring tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME public_key_sign_factory SRCS public_key_sign_factory.cc public_key_sign_factory.h DEPS tink::signature::public_key_sign_wrapper absl::core_headers tink::core::key_manager tink::core::keyset_handle tink::core::public_key_sign tink::core::registry tink::util::status tink::util::statusor ) tink_cc_library( NAME signature_key_templates SRCS signature_key_templates.cc signature_key_templates.h DEPS absl::core_headers absl::memory absl::strings crypto tink::internal::bn_util tink::internal::ssl_unique_ptr tink::util::constants tink::proto::common_cc_proto tink::proto::ecdsa_cc_proto tink::proto::ed25519_cc_proto tink::proto::rsa_ssa_pkcs1_cc_proto tink::proto::rsa_ssa_pss_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME ecdsa_sign_key_manager SRCS ecdsa_sign_key_manager.cc ecdsa_sign_key_manager.h DEPS tink::signature::ecdsa_verify_key_manager absl::memory absl::status absl::strings tink::core::private_key_type_manager tink::core::template_util tink::core::input_stream tink::core::public_key_sign tink::config::tink_fips tink::internal::ec_util tink::internal::fips_utils tink::subtle::ecdsa_sign_boringssl tink::util::constants tink::util::enums tink::util::errors tink::util::input_stream_util tink::util::protobuf_helper tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::ecdsa_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME ecdsa_verify_key_manager SRCS ecdsa_verify_key_manager.cc ecdsa_verify_key_manager.h DEPS absl::memory absl::status absl::strings tink::core::key_type_manager tink::core::template_util tink::core::public_key_verify tink::internal::ec_util tink::internal::fips_utils tink::subtle::ecdsa_verify_boringssl tink::util::constants tink::util::enums tink::util::errors tink::util::protobuf_helper tink::util::status tink::util::statusor tink::util::validation tink::proto::ecdsa_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME ed25519_sign_key_manager SRCS ed25519_sign_key_manager.cc ed25519_sign_key_manager.h DEPS tink::signature::ed25519_verify_key_manager absl::memory absl::status absl::strings tink::core::private_key_type_manager tink::core::template_util tink::core::input_stream tink::core::public_key_sign tink::internal::ec_util tink::subtle::ed25519_sign_boringssl tink::util::constants tink::util::enums tink::util::errors tink::util::input_stream_util tink::util::protobuf_helper tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::ed25519_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME ed25519_verify_key_manager SRCS ed25519_verify_key_manager.cc ed25519_verify_key_manager.h DEPS absl::memory absl::status absl::strings tink::core::key_type_manager tink::core::template_util tink::core::public_key_verify tink::subtle::ed25519_verify_boringssl tink::util::constants tink::util::errors tink::util::protobuf_helper tink::util::status tink::util::statusor tink::util::validation tink::proto::ed25519_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME sig_util SRCS sig_util.cc sig_util.h DEPS tink::core::public_key_sign tink::core::public_key_verify tink::util::status ) tink_cc_library( NAME rsa_ssa_pkcs1_sign_key_manager SRCS rsa_ssa_pkcs1_sign_key_manager.cc rsa_ssa_pkcs1_sign_key_manager.h DEPS tink::signature::rsa_ssa_pkcs1_verify_key_manager tink::signature::sig_util absl::memory absl::status absl::strings tink::core::private_key_type_manager tink::core::template_util tink::core::public_key_sign tink::core::public_key_verify tink::internal::bn_util tink::internal::fips_utils tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::subtle::rsa_ssa_pkcs1_sign_boringssl tink::util::constants tink::util::enums tink::util::errors tink::util::protobuf_helper tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::rsa_ssa_pkcs1_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME rsa_ssa_pkcs1_verify_key_manager SRCS rsa_ssa_pkcs1_verify_key_manager.cc rsa_ssa_pkcs1_verify_key_manager.h DEPS absl::memory absl::strings crypto tink::core::key_type_manager tink::core::template_util tink::core::public_key_verify tink::internal::bn_util tink::internal::fips_utils tink::internal::md_util tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::subtle::rsa_ssa_pkcs1_verify_boringssl tink::util::constants tink::util::enums tink::util::errors tink::util::protobuf_helper tink::util::status tink::util::statusor tink::util::validation tink::proto::rsa_ssa_pkcs1_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME rsa_ssa_pss_sign_key_manager SRCS rsa_ssa_pss_sign_key_manager.cc rsa_ssa_pss_sign_key_manager.h DEPS tink::signature::rsa_ssa_pss_verify_key_manager tink::signature::sig_util absl::memory absl::status absl::strings tink::core::key_type_manager tink::core::private_key_type_manager tink::core::template_util tink::core::public_key_sign tink::core::public_key_verify tink::internal::bn_util tink::internal::fips_utils tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::subtle::rsa_ssa_pss_sign_boringssl tink::util::constants tink::util::enums tink::util::errors tink::util::protobuf_helper tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::rsa_ssa_pss_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME rsa_ssa_pss_verify_key_manager SRCS rsa_ssa_pss_verify_key_manager.cc rsa_ssa_pss_verify_key_manager.h DEPS absl::memory absl::status absl::strings tink::core::key_type_manager tink::core::private_key_type_manager tink::core::template_util tink::core::public_key_sign tink::core::public_key_verify tink::internal::bn_util tink::internal::fips_utils tink::internal::md_util tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::subtle::rsa_ssa_pss_verify_boringssl tink::util::constants tink::util::enums tink::util::errors tink::util::protobuf_helper tink::util::status tink::util::statusor tink::util::validation tink::proto::rsa_ssa_pss_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME signature_config SRCS signature_config.cc signature_config.h DEPS tink::signature::ecdsa_proto_serialization tink::signature::ecdsa_verify_key_manager tink::signature::ed25519_sign_key_manager tink::signature::ed25519_verify_key_manager tink::signature::public_key_sign_wrapper tink::signature::public_key_verify_wrapper tink::signature::rsa_ssa_pkcs1_proto_serialization tink::signature::rsa_ssa_pkcs1_sign_key_manager tink::signature::rsa_ssa_pkcs1_verify_key_manager tink::signature::rsa_ssa_pss_proto_serialization tink::signature::rsa_ssa_pss_sign_key_manager tink::signature::rsa_ssa_pss_verify_key_manager absl::core_headers absl::memory tink::core::registry tink::config::config_util tink::config::tink_fips tink::util::status tink::signature::ecdsa_sign_key_manager tink::proto::config_cc_proto ) tink_cc_library( NAME signature_pem_keyset_reader SRCS signature_pem_keyset_reader.cc signature_pem_keyset_reader.h DEPS tink::signature::ecdsa_verify_key_manager tink::signature::rsa_ssa_pkcs1_sign_key_manager tink::signature::rsa_ssa_pkcs1_verify_key_manager tink::signature::rsa_ssa_pss_sign_key_manager tink::signature::rsa_ssa_pss_verify_key_manager absl::memory absl::status absl::strings tink::core::keyset_reader tink::internal::ec_util tink::internal::rsa_util tink::subtle::pem_parser_boringssl tink::util::enums tink::util::keyset_util tink::util::secret_data tink::util::status tink::util::statusor tink::proto::common_cc_proto tink::proto::ecdsa_cc_proto tink::proto::rsa_ssa_pkcs1_cc_proto tink::proto::rsa_ssa_pss_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME failing_signature SRCS failing_signature.cc failing_signature.h DEPS absl::memory absl::status absl::strings tink::core::public_key_sign tink::core::public_key_verify tink::util::status tink::util::statusor ) tink_cc_library( NAME signature_parameters SRCS signature_parameters.h DEPS tink::core::parameters ) tink_cc_library( NAME signature_public_key SRCS signature_public_key.h DEPS tink::signature::signature_parameters absl::strings tink::core::key ) tink_cc_library( NAME signature_private_key SRCS signature_private_key.h DEPS tink::signature::signature_parameters tink::signature::signature_public_key absl::strings absl::optional tink::core::key tink::core::private_key ) tink_cc_library( NAME ed25519_parameters SRCS ed25519_parameters.cc ed25519_parameters.h DEPS tink::signature::signature_parameters absl::status tink::core::parameters tink::util::status tink::util::statusor ) tink_cc_library( NAME ed25519_public_key SRCS ed25519_public_key.cc ed25519_public_key.h DEPS tink::signature::ed25519_parameters tink::signature::signature_public_key absl::core_headers absl::status absl::strings absl::optional tink::core::key tink::core::partial_key_access_token tink::subtle::subtle_util tink::util::status tink::util::statusor ) tink_cc_library( NAME ed25519_private_key SRCS ed25519_private_key.cc ed25519_private_key.h DEPS tink::signature::ed25519_public_key tink::signature::signature_private_key absl::status absl::string_view crypto tink::core::insecure_secret_key_access tink::core::key tink::core::partial_key_access_token tink::core::restricted_data tink::internal::ec_util tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME ed25519_proto_serialization SRCS ed25519_proto_serialization.cc ed25519_proto_serialization.h DEPS tink::signature::ed25519_parameters tink::signature::ed25519_private_key tink::signature::ed25519_public_key absl::status absl::strings absl::optional tink::core::insecure_secret_key_access tink::core::partial_key_access tink::core::restricted_data tink::core::secret_key_access_token tink::internal::key_parser tink::internal::key_serializer tink::internal::mutable_serialization_registry tink::internal::parameters_parser tink::internal::parameters_serializer tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::util::status tink::util::statusor tink::proto::ed25519_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME rsa_ssa_pkcs1_parameters SRCS rsa_ssa_pkcs1_parameters.cc rsa_ssa_pkcs1_parameters.h DEPS tink::signature::signature_parameters absl::status absl::strings absl::optional crypto tink::core::big_integer tink::core::parameters tink::internal::bn_util tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::util::status tink::util::statusor ) tink_cc_library( NAME rsa_ssa_pkcs1_public_key SRCS rsa_ssa_pkcs1_public_key.cc rsa_ssa_pkcs1_public_key.h DEPS tink::signature::rsa_ssa_pkcs1_parameters tink::signature::signature_public_key absl::core_headers absl::status absl::strings absl::str_format absl::optional crypto tink::core::big_integer tink::core::key tink::core::partial_key_access_token tink::subtle::subtle_util tink::util::status tink::util::statusor ) tink_cc_library( NAME rsa_ssa_pkcs1_private_key SRCS rsa_ssa_pkcs1_private_key.cc rsa_ssa_pkcs1_private_key.h DEPS tink::signature::rsa_ssa_pkcs1_public_key tink::signature::signature_private_key absl::status absl::optional crypto tink::core::big_integer tink::core::insecure_secret_key_access tink::core::key tink::core::partial_key_access_token tink::core::restricted_big_integer tink::internal::bn_util tink::internal::ssl_unique_ptr tink::util::status tink::util::statusor ) tink_cc_library( NAME config_v0 SRCS config_v0.cc config_v0.h DEPS absl::check tink::core::configuration tink::signature::internal::config_v0 ) tink_cc_library( NAME key_gen_config_v0 SRCS key_gen_config_v0.cc key_gen_config_v0.h DEPS absl::check tink::core::key_gen_configuration tink::signature::internal::key_gen_config_v0 ) tink_cc_library( NAME rsa_ssa_pkcs1_proto_serialization SRCS rsa_ssa_pkcs1_proto_serialization.cc rsa_ssa_pkcs1_proto_serialization.h DEPS tink::signature::rsa_ssa_pkcs1_parameters tink::signature::rsa_ssa_pkcs1_private_key tink::signature::rsa_ssa_pkcs1_public_key absl::core_headers absl::status absl::string_view absl::optional tink::core::big_integer tink::core::insecure_secret_key_access tink::core::partial_key_access tink::core::restricted_big_integer tink::core::restricted_data tink::core::secret_key_access_token tink::internal::key_parser tink::internal::key_serializer tink::internal::mutable_serialization_registry tink::internal::parameters_parser tink::internal::parameters_serializer tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::util::status tink::util::statusor tink::proto::common_cc_proto tink::proto::rsa_ssa_pkcs1_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME rsa_ssa_pss_parameters SRCS rsa_ssa_pss_parameters.cc rsa_ssa_pss_parameters.h DEPS tink::signature::signature_parameters absl::status absl::strings absl::string_view absl::optional crypto tink::core::big_integer tink::core::parameters tink::internal::bn_util tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::util::status tink::util::statusor ) tink_cc_library( NAME rsa_ssa_pss_public_key SRCS rsa_ssa_pss_public_key.cc rsa_ssa_pss_public_key.h DEPS tink::signature::rsa_ssa_pss_parameters tink::signature::signature_public_key absl::core_headers absl::status absl::strings absl::str_format absl::string_view absl::optional tink::core::big_integer tink::core::key tink::core::partial_key_access_token tink::subtle::subtle_util tink::util::status tink::util::statusor ) tink_cc_library( NAME rsa_ssa_pss_private_key SRCS rsa_ssa_pss_private_key.cc rsa_ssa_pss_private_key.h DEPS tink::signature::rsa_ssa_pss_public_key tink::signature::signature_private_key absl::status absl::optional crypto tink::core::big_integer tink::core::insecure_secret_key_access tink::core::key tink::core::partial_key_access_token tink::core::restricted_big_integer tink::internal::bn_util tink::internal::ssl_unique_ptr tink::util::status tink::util::statusor ) tink_cc_library( NAME rsa_ssa_pss_proto_serialization SRCS rsa_ssa_pss_proto_serialization.cc rsa_ssa_pss_proto_serialization.h DEPS tink::signature::rsa_ssa_pss_parameters tink::signature::rsa_ssa_pss_private_key tink::signature::rsa_ssa_pss_public_key absl::core_headers absl::status absl::string_view absl::optional tink::core::big_integer tink::core::insecure_secret_key_access tink::core::partial_key_access tink::core::restricted_big_integer tink::core::restricted_data tink::core::secret_key_access_token tink::internal::key_parser tink::internal::key_serializer tink::internal::mutable_serialization_registry tink::internal::parameters_parser tink::internal::parameters_serializer tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::util::status tink::util::statusor tink::proto::common_cc_proto tink::proto::rsa_ssa_pss_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME ecdsa_parameters SRCS ecdsa_parameters.cc ecdsa_parameters.h DEPS tink::signature::signature_parameters absl::algorithm_container absl::status absl::string_view absl::optional tink::core::parameters tink::util::status tink::util::statusor ) tink_cc_library( NAME ecdsa_public_key SRCS ecdsa_public_key.cc ecdsa_public_key.h DEPS tink::signature::ecdsa_parameters tink::signature::signature_public_key absl::core_headers absl::status absl::strings absl::string_view absl::optional crypto tink::core::ec_point tink::core::key tink::core::partial_key_access_token tink::internal::ec_util tink::internal::ssl_unique_ptr tink::subtle::common_enums tink::subtle::subtle_util tink::util::status tink::util::statusor ) tink_cc_library( NAME ecdsa_private_key SRCS ecdsa_private_key.cc ecdsa_private_key.h DEPS tink::signature::ecdsa_parameters tink::signature::ecdsa_public_key tink::signature::signature_private_key absl::status absl::strings crypto tink::core::ec_point tink::core::insecure_secret_key_access tink::core::key tink::core::partial_key_access_token tink::core::restricted_big_integer tink::internal::bn_util tink::internal::ec_util tink::internal::err_util tink::internal::ssl_unique_ptr tink::subtle::common_enums tink::util::status tink::util::statusor ) tink_cc_library( NAME ecdsa_proto_serialization SRCS ecdsa_proto_serialization.cc ecdsa_proto_serialization.h DEPS tink::signature::ecdsa_parameters tink::signature::ecdsa_private_key tink::signature::ecdsa_public_key absl::status absl::string_view absl::optional tink::core::big_integer tink::core::ec_point tink::core::insecure_secret_key_access tink::core::partial_key_access tink::core::restricted_big_integer tink::core::restricted_data tink::core::secret_key_access_token tink::internal::bn_encoding_util tink::internal::key_parser tink::internal::key_serializer tink::internal::mutable_serialization_registry tink::internal::parameters_parser tink::internal::parameters_serializer tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::util::status tink::util::statusor tink::proto::common_cc_proto tink::proto::ecdsa_cc_proto tink::proto::tink_cc_proto ) # tests tink_cc_test( NAME public_key_verify_wrapper_test SRCS public_key_verify_wrapper_test.cc DEPS tink::signature::failing_signature tink::signature::public_key_verify_wrapper gmock absl::flat_hash_map absl::memory absl::status absl::strings absl::string_view tink::core::primitive_set tink::core::public_key_sign tink::core::public_key_verify tink::core::registry tink::internal::registry_impl tink::monitoring::monitoring tink::monitoring::monitoring_client_mocks tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::tink_cc_proto ) tink_cc_test( NAME public_key_verify_factory_test SRCS public_key_verify_factory_test.cc DEPS tink::signature::ecdsa_verify_key_manager tink::signature::public_key_verify_factory tink::signature::signature_config gmock tink::core::crypto_format tink::core::keyset_handle tink::core::public_key_verify tink::core::registry tink::util::status tink::util::test_keyset_handle tink::util::test_util tink::proto::ecdsa_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME public_key_sign_wrapper_test SRCS public_key_sign_wrapper_test.cc DEPS tink::signature::failing_signature tink::signature::public_key_sign_wrapper gmock absl::flat_hash_map absl::memory absl::status absl::string_view tink::core::crypto_format tink::core::primitive_set tink::core::public_key_sign tink::core::public_key_verify tink::core::registry tink::internal::registry_impl tink::monitoring::monitoring tink::monitoring::monitoring_client_mocks tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::tink_cc_proto ) tink_cc_test( NAME public_key_sign_factory_test SRCS public_key_sign_factory_test.cc DEPS tink::signature::ecdsa_sign_key_manager tink::signature::public_key_sign_factory tink::signature::signature_config gmock tink::core::crypto_format tink::core::keyset_handle tink::core::public_key_sign tink::core::registry tink::util::status tink::util::test_keyset_handle tink::util::test_util tink::proto::ecdsa_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME ecdsa_verify_key_manager_test SRCS ecdsa_verify_key_manager_test.cc DEPS tink::signature::ecdsa_sign_key_manager tink::signature::ecdsa_verify_key_manager gmock absl::status tink::core::public_key_sign tink::core::public_key_verify tink::internal::ec_util tink::subtle::ecdsa_sign_boringssl tink::util::enums tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::ecdsa_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME ed25519_verify_key_manager_test SRCS ed25519_verify_key_manager_test.cc DEPS tink::signature::ed25519_sign_key_manager tink::signature::ed25519_verify_key_manager gmock absl::strings tink::core::public_key_sign tink::core::public_key_verify tink::core::registry tink::subtle::ed25519_sign_boringssl tink::util::enums tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::ed25519_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME rsa_ssa_pkcs1_verify_key_manager_test SRCS rsa_ssa_pkcs1_verify_key_manager_test.cc DEPS tink::signature::rsa_ssa_pkcs1_sign_key_manager tink::signature::rsa_ssa_pkcs1_verify_key_manager gmock absl::status absl::strings crypto tink::core::public_key_sign tink::core::public_key_verify tink::internal::bn_util tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::subtle::common_enums tink::subtle::rsa_ssa_pkcs1_sign_boringssl tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::rsa_ssa_pkcs1_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME rsa_ssa_pss_verify_key_manager_test SRCS rsa_ssa_pss_verify_key_manager_test.cc DEPS tink::signature::rsa_ssa_pss_sign_key_manager tink::signature::rsa_ssa_pss_verify_key_manager gmock absl::status absl::strings crypto tink::core::public_key_sign tink::core::public_key_verify tink::internal::bn_util tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::subtle::common_enums tink::subtle::rsa_ssa_pss_sign_boringssl tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::rsa_ssa_pss_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME ecdsa_sign_key_manager_test SRCS ecdsa_sign_key_manager_test.cc DEPS tink::signature::ecdsa_sign_key_manager tink::signature::ecdsa_verify_key_manager gmock absl::memory absl::status absl::strings tink::core::public_key_sign tink::core::public_key_verify tink::internal::ec_util tink::internal::ssl_util tink::subtle::ecdsa_verify_boringssl tink::util::enums tink::util::istream_input_stream tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::ecdsa_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME ed25519_sign_key_manager_test SRCS ed25519_sign_key_manager_test.cc DEPS tink::signature::ed25519_sign_key_manager tink::signature::ed25519_verify_key_manager gmock absl::flat_hash_set absl::memory absl::status tink::core::public_key_sign tink::core::public_key_verify tink::core::registry tink::subtle::ed25519_verify_boringssl tink::util::enums tink::util::istream_input_stream tink::util::protobuf_helper tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::ed25519_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME rsa_ssa_pkcs1_sign_key_manager_test SRCS rsa_ssa_pkcs1_sign_key_manager_test.cc DEPS tink::signature::rsa_ssa_pkcs1_sign_key_manager tink::signature::rsa_ssa_pkcs1_verify_key_manager gmock absl::flat_hash_set crypto tink::core::public_key_sign tink::internal::bn_util tink::internal::ssl_unique_ptr tink::subtle::common_enums tink::subtle::rsa_ssa_pkcs1_verify_boringssl tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::rsa_ssa_pkcs1_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME rsa_ssa_pss_sign_key_manager_test SRCS rsa_ssa_pss_sign_key_manager_test.cc DEPS tink::signature::rsa_ssa_pss_sign_key_manager tink::signature::rsa_ssa_pss_verify_key_manager tink::signature::signature_key_templates gmock absl::flat_hash_set crypto tink::core::public_key_sign tink::internal::bn_util tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::subtle::common_enums tink::subtle::rsa_ssa_pss_verify_boringssl tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::rsa_ssa_pss_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME signature_config_test SRCS signature_config_test.cc DEPS tink::signature::ecdsa_parameters tink::signature::ecdsa_private_key tink::signature::ecdsa_public_key tink::signature::key_gen_config_v0 tink::signature::rsa_ssa_pkcs1_parameters tink::signature::rsa_ssa_pkcs1_private_key tink::signature::rsa_ssa_pkcs1_public_key tink::signature::rsa_ssa_pss_parameters tink::signature::rsa_ssa_pss_private_key tink::signature::rsa_ssa_pss_public_key tink::signature::rsa_ssa_pss_sign_key_manager tink::signature::rsa_ssa_pss_verify_key_manager tink::signature::signature_config tink::signature::signature_key_templates gmock absl::check absl::memory absl::status absl::strings crypto tink::core::big_integer tink::core::crypto_format tink::core::ec_point tink::core::insecure_secret_key_access tink::core::key tink::core::key_status tink::core::keyset_handle tink::core::keyset_handle_builder tink::core::parameters tink::core::partial_key_access tink::core::primitive_set tink::core::public_key_sign tink::core::public_key_verify tink::core::registry tink::core::restricted_big_integer tink::core::restricted_data tink::config::global_registry tink::internal::bn_util tink::internal::ec_util tink::internal::fips_utils tink::internal::legacy_proto_key tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::internal::serialization tink::internal::ssl_unique_ptr tink::subtle::common_enums tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::common_cc_proto tink::proto::rsa_ssa_pkcs1_cc_proto tink::proto::rsa_ssa_pss_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME signature_key_templates_test SRCS signature_key_templates_test.cc DEPS tink::signature::ecdsa_sign_key_manager tink::signature::ecdsa_verify_key_manager tink::signature::ed25519_sign_key_manager tink::signature::ed25519_verify_key_manager tink::signature::rsa_ssa_pkcs1_sign_key_manager tink::signature::rsa_ssa_pss_sign_key_manager tink::signature::signature_key_templates gmock crypto tink::core::key_manager_impl tink::core::private_key_manager_impl tink::core::public_key_sign tink::internal::bn_util tink::internal::ssl_unique_ptr tink::util::statusor tink::util::test_matchers tink::proto::common_cc_proto tink::proto::ecdsa_cc_proto tink::proto::ed25519_cc_proto tink::proto::rsa_ssa_pkcs1_cc_proto tink::proto::rsa_ssa_pss_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME signature_pem_keyset_reader_test SRCS signature_pem_keyset_reader_test.cc DEPS tink::signature::ecdsa_verify_key_manager tink::signature::rsa_ssa_pss_sign_key_manager tink::signature::rsa_ssa_pss_verify_key_manager tink::signature::signature_config tink::signature::signature_pem_keyset_reader gmock absl::status absl::strings tink::core::cc tink::internal::rsa_util tink::internal::ssl_util tink::subtle::pem_parser_boringssl tink::util::enums tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::common_cc_proto tink::proto::ecdsa_cc_proto tink::proto::rsa_ssa_pss_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME failing_signature_test SRCS failing_signature_test.cc DEPS tink::signature::failing_signature gmock absl::status tink::core::public_key_sign tink::core::public_key_verify tink::util::test_matchers ) tink_cc_test( NAME ed25519_parameters_test SRCS ed25519_parameters_test.cc DEPS tink::signature::ed25519_parameters gmock absl::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME ed25519_public_key_test SRCS ed25519_public_key_test.cc DEPS tink::signature::ed25519_parameters tink::signature::ed25519_public_key gmock absl::status absl::optional tink::core::partial_key_access tink::subtle::random tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME ed25519_private_key_test SRCS ed25519_private_key_test.cc DEPS tink::signature::ed25519_parameters tink::signature::ed25519_private_key tink::signature::ed25519_public_key gmock absl::status absl::optional tink::core::insecure_secret_key_access tink::core::partial_key_access tink::core::restricted_data tink::internal::ec_util tink::subtle::random tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME ed25519_proto_serialization_test SRCS ed25519_proto_serialization_test.cc DEPS tink::signature::ed25519_parameters tink::signature::ed25519_private_key tink::signature::ed25519_proto_serialization tink::signature::ed25519_public_key gmock absl::status absl::optional tink::core::insecure_secret_key_access tink::core::key tink::core::parameters tink::core::partial_key_access tink::core::restricted_data tink::internal::ec_util tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::internal::serialization tink::subtle::random tink::util::statusor tink::util::test_matchers tink::proto::ed25519_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME rsa_ssa_pkcs1_parameters_test SRCS rsa_ssa_pkcs1_parameters_test.cc DEPS tink::signature::rsa_ssa_pkcs1_parameters gmock absl::status crypto tink::core::big_integer tink::internal::bn_util tink::internal::ssl_unique_ptr tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME rsa_ssa_pkcs1_public_key_test SRCS rsa_ssa_pkcs1_public_key_test.cc DEPS tink::signature::rsa_ssa_pkcs1_parameters tink::signature::rsa_ssa_pkcs1_public_key gmock absl::status absl::strings absl::optional crypto tink::core::big_integer tink::core::partial_key_access tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME rsa_ssa_pkcs1_private_key_test SRCS rsa_ssa_pkcs1_private_key_test.cc DEPS tink::signature::rsa_ssa_pkcs1_parameters tink::signature::rsa_ssa_pkcs1_private_key tink::signature::rsa_ssa_pkcs1_public_key gmock absl::check absl::status absl::strings absl::optional crypto tink::core::big_integer tink::core::insecure_secret_key_access tink::core::partial_key_access tink::core::restricted_big_integer tink::internal::bn_util tink::internal::ssl_unique_ptr tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME config_v0_test SRCS config_v0_test.cc DEPS tink::signature::config_v0 tink::signature::key_gen_config_v0 tink::signature::signature_key_templates gmock tink::core::keyset_handle tink::core::public_key_sign tink::core::public_key_verify tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) tink_cc_test( NAME rsa_ssa_pkcs1_proto_serialization_test SRCS rsa_ssa_pkcs1_proto_serialization_test.cc DEPS tink::signature::rsa_ssa_pkcs1_parameters tink::signature::rsa_ssa_pkcs1_private_key tink::signature::rsa_ssa_pkcs1_proto_serialization tink::signature::rsa_ssa_pkcs1_public_key gmock absl::check absl::status absl::string_view absl::optional crypto tink::core::big_integer tink::core::insecure_secret_key_access tink::core::key tink::core::parameters tink::core::partial_key_access tink::core::restricted_big_integer tink::core::restricted_data tink::internal::bn_util tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::internal::serialization tink::internal::ssl_unique_ptr tink::util::statusor tink::util::test_matchers tink::proto::common_cc_proto tink::proto::rsa_ssa_pkcs1_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME rsa_ssa_pss_parameters_test SRCS rsa_ssa_pss_parameters_test.cc DEPS tink::signature::rsa_ssa_pss_parameters gmock absl::status crypto tink::core::big_integer tink::internal::bn_util tink::internal::ssl_unique_ptr tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME rsa_ssa_pss_public_key_test SRCS rsa_ssa_pss_public_key_test.cc DEPS tink::signature::rsa_ssa_pss_parameters tink::signature::rsa_ssa_pss_public_key gmock absl::status absl::strings absl::string_view absl::optional tink::core::big_integer tink::core::partial_key_access tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME rsa_ssa_pss_private_key_test SRCS rsa_ssa_pss_private_key_test.cc DEPS tink::signature::rsa_ssa_pss_parameters tink::signature::rsa_ssa_pss_private_key tink::signature::rsa_ssa_pss_public_key gmock absl::check absl::status absl::strings absl::string_view absl::optional crypto tink::core::big_integer tink::core::insecure_secret_key_access tink::core::partial_key_access tink::core::restricted_big_integer tink::internal::bn_util tink::internal::ssl_unique_ptr tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME rsa_ssa_pss_proto_serialization_test SRCS rsa_ssa_pss_proto_serialization_test.cc DEPS tink::signature::rsa_ssa_pss_parameters tink::signature::rsa_ssa_pss_private_key tink::signature::rsa_ssa_pss_proto_serialization tink::signature::rsa_ssa_pss_public_key gmock absl::check absl::status absl::string_view absl::optional crypto tink::core::big_integer tink::core::insecure_secret_key_access tink::core::key tink::core::parameters tink::core::partial_key_access tink::core::restricted_big_integer tink::core::restricted_data tink::internal::bn_util tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::internal::serialization tink::internal::ssl_unique_ptr tink::util::statusor tink::util::test_matchers tink::proto::common_cc_proto tink::proto::rsa_ssa_pss_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME ecdsa_parameters_test SRCS ecdsa_parameters_test.cc DEPS tink::signature::ecdsa_parameters gmock absl::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME ecdsa_public_key_test SRCS ecdsa_public_key_test.cc DEPS tink::signature::ecdsa_parameters tink::signature::ecdsa_public_key gmock absl::status absl::strings absl::string_view absl::optional crypto tink::core::big_integer tink::core::ec_point tink::core::partial_key_access tink::internal::ec_util tink::subtle::common_enums tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME ecdsa_private_key_test SRCS ecdsa_private_key_test.cc DEPS tink::signature::ecdsa_parameters tink::signature::ecdsa_private_key tink::signature::ecdsa_public_key gmock absl::status absl::optional crypto tink::core::big_integer tink::core::ec_point tink::core::insecure_secret_key_access tink::core::partial_key_access tink::core::restricted_big_integer tink::internal::ec_util tink::subtle::common_enums tink::util::secret_data tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME ecdsa_proto_serialization_test SRCS ecdsa_proto_serialization_test.cc DEPS tink::signature::ecdsa_parameters tink::signature::ecdsa_private_key tink::signature::ecdsa_proto_serialization tink::signature::ecdsa_public_key gmock absl::status absl::string_view absl::optional crypto tink::core::big_integer tink::core::ec_point tink::core::insecure_secret_key_access tink::core::key tink::core::parameters tink::core::partial_key_access tink::core::restricted_big_integer tink::core::restricted_data tink::internal::ec_util tink::internal::mutable_serialization_registry tink::internal::proto_key_serialization tink::internal::proto_parameters_serialization tink::internal::serialization tink::subtle::common_enums tink::util::secret_data tink::util::statusor tink::util::test_matchers tink::proto::common_cc_proto tink::proto::ecdsa_cc_proto tink::proto::tink_cc_proto ) ================================================ FILE: cc/signature/config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/config_v0.h" #include "absl/log/check.h" #include "tink/configuration.h" #include "tink/signature/internal/config_v0.h" namespace crypto { namespace tink { const Configuration& ConfigSignatureV0() { static const Configuration* instance = [] { static Configuration* config = new Configuration(); CHECK_OK(internal::AddSignatureV0(*config)); return config; }(); return *instance; } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_CONFIG_V0_H_ #define TINK_SIGNATURE_CONFIG_V0_H_ #include "tink/configuration.h" namespace crypto { namespace tink { // Configuration used to generate Signature primitives with recommended key // managers. const Configuration& ConfigSignatureV0(); } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_CONFIG_V0_H_ ================================================ FILE: cc/signature/config_v0_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/config_v0.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/keyset_handle.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/signature/key_gen_config_v0.h" #include "tink/signature/signature_key_templates.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::google::crypto::tink::KeyTemplate; using ::testing::TestWithParam; using ::testing::Values; using ConfigV0Test = TestWithParam; INSTANTIATE_TEST_SUITE_P( ConfigV0TestSuite, ConfigV0Test, Values(SignatureKeyTemplates::EcdsaP256(), SignatureKeyTemplates::Ed25519(), SignatureKeyTemplates::RsaSsaPkcs13072Sha256F4(), SignatureKeyTemplates::RsaSsaPss3072Sha256Sha256F4())); TEST_P(ConfigV0Test, GetPrimitive) { util::StatusOr> handle = KeysetHandle::GenerateNew(GetParam(), KeyGenConfigSignatureV0()); ASSERT_THAT(handle, IsOk()); util::StatusOr> public_handle = (*handle)->GetPublicKeysetHandle(KeyGenConfigSignatureV0()); ASSERT_THAT(public_handle, IsOk()); util::StatusOr> sign = (*handle)->GetPrimitive(ConfigSignatureV0()); ASSERT_THAT(sign, IsOk()); util::StatusOr> verify = (*public_handle)->GetPrimitive(ConfigSignatureV0()); ASSERT_THAT(verify, IsOk()); std::string data = "data"; util::StatusOr signature = (*sign)->Sign(data); ASSERT_THAT(signature, IsOk()); EXPECT_THAT((*verify)->Verify(*signature, data), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ecdsa_parameters.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ecdsa_parameters.h" #include "absl/algorithm/container.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/parameters.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { EcdsaParameters::Builder& EcdsaParameters::Builder::SetCurveType( CurveType curve_type) { curve_type_ = curve_type; return *this; } EcdsaParameters::Builder& EcdsaParameters::Builder::SetHashType( HashType hash_type) { hash_type_ = hash_type; return *this; } EcdsaParameters::Builder& EcdsaParameters::Builder::SetSignatureEncoding( SignatureEncoding signature_encoding) { signature_encoding_ = signature_encoding; return *this; } EcdsaParameters::Builder& EcdsaParameters::Builder::SetVariant( Variant variant) { variant_ = variant; return *this; } util::StatusOr EcdsaParameters::Builder::Build() { if (!curve_type_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "CurveType is not set."); } if (!hash_type_.has_value()) { return absl::InvalidArgumentError("HashType is not set."); } if (!signature_encoding_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "SignatureEncoding is not set."); } if (!variant_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Variant is not set."); } // Validate CurveType. static constexpr CurveType kSupportedCurves[] = { CurveType::kNistP256, CurveType::kNistP384, CurveType::kNistP521}; if (!absl::c_linear_search(kSupportedCurves, *curve_type_)) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create Ecdsa parameters with unknown CurveType."); } // Validate HashType. static constexpr HashType kSupportedHashes[] = { HashType::kSha256, HashType::kSha384, HashType::kSha512}; if (!absl::c_linear_search(kSupportedHashes, *hash_type_)) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create Ecdsa parameters with unknown HashType."); } // Check requirements for the curve and the hash types. switch (*curve_type_) { case CurveType::kNistP256: if (*hash_type_ != HashType::kSha256) { return util::Status(absl::StatusCode::kInvalidArgument, "NIST_P256 curve requires SHA256."); } break; case CurveType::kNistP384: if (*hash_type_ != HashType::kSha384 && *hash_type_ != HashType::kSha512) { return util::Status(absl::StatusCode::kInvalidArgument, "NIST_P384 curve requires SHA384 or SHA512."); } break; case CurveType::kNistP521: if (*hash_type_ != HashType::kSha512) { return util::Status(absl::StatusCode::kInvalidArgument, "NIST_P521 curve requires SHA512."); } break; default: return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create Ecdsa parameters with unknown CurveType."); } // Validate SignatureEncoding. static constexpr SignatureEncoding kSupportedEncodings[] = { SignatureEncoding::kDer, SignatureEncoding::kIeeeP1363}; if (!absl::c_linear_search(kSupportedEncodings, *signature_encoding_)) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create Ecdsa parameters with unknown SignatureEncoding."); } // Validate variant. static constexpr Variant kSupportedVariants[] = { Variant::kTink, Variant::kCrunchy, Variant::kLegacy, Variant::kNoPrefix}; if (!absl::c_linear_search(kSupportedVariants, *variant_)) { return util::Status(absl::StatusCode::kInvalidArgument, "Cannot create Ecdsa parameters with unknown Variant."); } return EcdsaParameters(*curve_type_, *hash_type_, *signature_encoding_, *variant_); } bool EcdsaParameters::operator==(const Parameters& other) const { const EcdsaParameters* that = dynamic_cast(&other); if (that == nullptr) return false; return curve_type_ == that->curve_type_ && hash_type_ == that->hash_type_ && signature_encoding_ == that->signature_encoding_ && variant_ == that->variant_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ecdsa_parameters.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_ECDSA_PARAMETERS_H_ #define TINK_SIGNATURE_ECDSA_PARAMETERS_H_ #include "absl/types/optional.h" #include "tink/parameters.h" #include "tink/signature/signature_parameters.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { class EcdsaParameters : public SignatureParameters { public: // Describes the output prefix prepended to the signature. enum class Variant : int { // Prepends '0x01' to signature. kTink = 1, // Prepends '0x00' to signature. kCrunchy = 2, // Appends a 0-byte to input message BEFORE computing the signature, then // prepends '0x00' to signature. kLegacy = 3, // Does not prepend any prefix (i.e., keys must have no ID requirement). kNoPrefix = 4, // Added to guard from failures that may be caused by future expansions. kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; enum class CurveType : int { kNistP256 = 1, kNistP384 = 2, kNistP521 = 3, kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; enum class HashType : int { kSha256 = 1, kSha384 = 2, kSha512 = 3, kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; enum class SignatureEncoding : int { kDer = 1, kIeeeP1363 = 2, kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Creates Ecdsa parameters instances. class Builder { public: // Copyable and movable. Builder(const Builder& other) = default; Builder& operator=(const Builder& other) = default; Builder(Builder&& other) = default; Builder& operator=(Builder&& other) = default; // Creates initially empty parameters builder. Builder() = default; Builder& SetCurveType(CurveType curve_type); Builder& SetHashType(HashType hash_type); Builder& SetSignatureEncoding(SignatureEncoding signature_encoding); Builder& SetVariant(Variant variant); // Creates Ecdsa parameters object from this builder. util::StatusOr Build(); private: absl::optional curve_type_; absl::optional hash_type_; absl::optional signature_encoding_; absl::optional variant_; }; // Copyable and movable. EcdsaParameters(const EcdsaParameters& other) = default; EcdsaParameters& operator=(const EcdsaParameters& other) = default; EcdsaParameters(EcdsaParameters&& other) = default; EcdsaParameters& operator=(EcdsaParameters&& other) = default; CurveType GetCurveType() const { return curve_type_; } HashType GetHashType() const { return hash_type_; } SignatureEncoding GetSignatureEncoding() const { return signature_encoding_; } Variant GetVariant() const { return variant_; } bool HasIdRequirement() const override { return variant_ != Variant::kNoPrefix; } bool operator==(const Parameters& other) const override; private: explicit EcdsaParameters(CurveType curve_type, HashType hash_type, SignatureEncoding signature_encoding, Variant variant) : curve_type_(curve_type), hash_type_(hash_type), signature_encoding_(signature_encoding), variant_(variant) {} CurveType curve_type_; HashType hash_type_; SignatureEncoding signature_encoding_; Variant variant_; }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_ECDSA_PARAMETERS_H_ ================================================ FILE: cc/signature/ecdsa_parameters_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ecdsa_parameters.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::IsTrue; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { EcdsaParameters::CurveType curve_type; EcdsaParameters::HashType hash_type; EcdsaParameters::SignatureEncoding signature_encoding; EcdsaParameters::Variant variant; bool has_id_requirement; }; using EcdsaParametersTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( EcdsaParametersTestSuite, EcdsaParametersTest, Values(TestCase{EcdsaParameters::CurveType::kNistP256, EcdsaParameters::HashType::kSha256, EcdsaParameters::SignatureEncoding::kDer, EcdsaParameters::Variant::kTink, /*has_id_requirement=*/true}, TestCase{EcdsaParameters::CurveType::kNistP384, EcdsaParameters::HashType::kSha384, EcdsaParameters::SignatureEncoding::kDer, EcdsaParameters::Variant::kCrunchy, /*has_id_requirement=*/true}, TestCase{EcdsaParameters::CurveType::kNistP384, EcdsaParameters::HashType::kSha512, EcdsaParameters::SignatureEncoding::kIeeeP1363, EcdsaParameters::Variant::kLegacy, /*has_id_requirement=*/true}, TestCase{EcdsaParameters::CurveType::kNistP521, EcdsaParameters::HashType::kSha512, EcdsaParameters::SignatureEncoding::kIeeeP1363, EcdsaParameters::Variant::kNoPrefix, /*has_id_requirement=*/false})); TEST_P(EcdsaParametersTest, BuildWorks) { TestCase test_case = GetParam(); util::StatusOr parameters = EcdsaParameters::Builder() .SetCurveType(test_case.curve_type) .SetHashType(test_case.hash_type) .SetSignatureEncoding(test_case.signature_encoding) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetCurveType(), Eq(test_case.curve_type)); EXPECT_THAT(parameters->GetHashType(), Eq(test_case.hash_type)); EXPECT_THAT(parameters->GetSignatureEncoding(), Eq(test_case.signature_encoding)); EXPECT_THAT(parameters->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(parameters->HasIdRequirement(), Eq(test_case.has_id_requirement)); } TEST(EcdsaParametersTest, BuildWithInvalidVariantFails) { EXPECT_THAT( EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("unknown Variant"))); } TEST(EcdsaParametersTest, BuildWithoutVariantFails) { EXPECT_THAT( EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Variant is not set"))); } TEST(EcdsaParametersTest, BuildWithInvalidCurveTypeFails) { EXPECT_THAT( EcdsaParameters::Builder() .SetCurveType( EcdsaParameters::CurveType:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kTink) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("unknown CurveType"))); } TEST(EcdsaParametersTest, BuildWithoutCurveTypeFails) { EXPECT_THAT( EcdsaParameters::Builder() .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kTink) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("CurveType is not set"))); } TEST(EcdsaParametersTest, BuildWithInvalidHashTypeFails) { EXPECT_THAT( EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType( EcdsaParameters::HashType:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kTink) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("unknown HashType"))); } TEST(EcdsaParametersTest, BuildWithoutHashTypeFails) { EXPECT_THAT( EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kTink) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("HashType is not set"))); } TEST(EcdsaParametersTest, BuildWithInvalidSignatureEncodingFails) { EXPECT_THAT(EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding( EcdsaParameters::SignatureEncoding:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .SetVariant(EcdsaParameters::Variant::kTink) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("unknown SignatureEncoding"))); } TEST(EcdsaParametersTest, BuildWithoutSignatureEncodingFails) { EXPECT_THAT(EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType(EcdsaParameters::HashType::kSha256) .SetVariant(EcdsaParameters::Variant::kTink) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("SignatureEncoding is not set"))); } TEST(EcdsaParametersTest, BuildWithIncompatibleHashTypeForCurveP256Fails) { // NIST_P256 curve requires SHA256 EXPECT_THAT( EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType(EcdsaParameters::HashType::kSha512) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kTink) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("NIST_P256 curve requires SHA256"))); } TEST(EcdsaParametersTest, BuildWithIncompatibleHashTypeForCurveP384Fails) { // NIST_P384 curve requires SHA384 or SHA512 EXPECT_THAT( EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP384) .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kTink) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("NIST_P384 curve requires SHA384 or SHA512"))); } TEST(EcdsaParametersTest, BuildWithIncompatibleHashTypeForCurveP521Fails) { // NIST_P521 curve requires SHA512 EXPECT_THAT( EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP521) .SetHashType(EcdsaParameters::HashType::kSha384) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kTink) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("NIST_P521 curve requires SHA512"))); } TEST(EcdsaParametersTest, CopyConstructor) { util::StatusOr parameters = EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); EcdsaParameters copy(*parameters); EXPECT_THAT(copy.GetCurveType(), Eq(EcdsaParameters::CurveType::kNistP256)); EXPECT_THAT(copy.GetHashType(), Eq(EcdsaParameters::HashType::kSha256)); EXPECT_THAT(copy.GetSignatureEncoding(), Eq(EcdsaParameters::SignatureEncoding::kDer)); EXPECT_THAT(copy.GetVariant(), Eq(EcdsaParameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); } TEST(EcdsaParametersTest, CopyAssignment) { util::StatusOr parameters = EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); EcdsaParameters copy = *parameters; EXPECT_THAT(copy.GetCurveType(), Eq(EcdsaParameters::CurveType::kNistP256)); EXPECT_THAT(copy.GetHashType(), Eq(EcdsaParameters::HashType::kSha256)); EXPECT_THAT(copy.GetSignatureEncoding(), Eq(EcdsaParameters::SignatureEncoding::kDer)); EXPECT_THAT(copy.GetVariant(), Eq(EcdsaParameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); } TEST_P(EcdsaParametersTest, ParametersEquals) { TestCase test_case = GetParam(); util::StatusOr parameters = EcdsaParameters::Builder() .SetCurveType(test_case.curve_type) .SetHashType(test_case.hash_type) .SetSignatureEncoding(test_case.signature_encoding) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = EcdsaParameters::Builder() .SetCurveType(test_case.curve_type) .SetHashType(test_case.hash_type) .SetSignatureEncoding(test_case.signature_encoding) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters == *other_parameters); EXPECT_TRUE(*other_parameters == *parameters); EXPECT_FALSE(*parameters != *other_parameters); EXPECT_FALSE(*other_parameters != *parameters); } TEST(EcdsaParametersTest, DifferentVariantNotEqual) { util::StatusOr parameters = EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kCrunchy) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(EcdsaParametersTest, DifferentCurveTypeNotEqual) { util::StatusOr parameters = EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP384) .SetHashType(EcdsaParameters::HashType::kSha512) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP521) .SetHashType(EcdsaParameters::HashType::kSha512) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kTink) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(EcdsaParametersTest, DifferentHashTypeNotEqual) { util::StatusOr parameters = EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP384) .SetHashType(EcdsaParameters::HashType::kSha384) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP384) .SetHashType(EcdsaParameters::HashType::kSha512) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kTink) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(EcdsaParametersTest, DifferentSignatureEncodingNotEqual) { util::StatusOr parameters = EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kIeeeP1363) .SetVariant(EcdsaParameters::Variant::kCrunchy) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ecdsa_private_key.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ecdsa_private_key.h" #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #include "openssl/ec_key.h" #else #include "openssl/ec.h" #endif #include "tink/ec_point.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/bn_util.h" #include "tink/internal/ec_util.h" #include "tink/internal/err_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_big_integer.h" #include "tink/signature/ecdsa_parameters.h" #include "tink/signature/ecdsa_public_key.h" #include "tink/subtle/common_enums.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { util::StatusOr SubtleCurveType( EcdsaParameters::CurveType curve_type) { switch (curve_type) { case EcdsaParameters::CurveType::kNistP256: return subtle::EllipticCurveType::NIST_P256; case EcdsaParameters::CurveType::kNistP384: return subtle::EllipticCurveType::NIST_P384; case EcdsaParameters::CurveType::kNistP521: return subtle::EllipticCurveType::NIST_P521; default: return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Unknown curve type: ", curve_type)); } } util::Status ValidateKeyPair(const EcdsaPublicKey& public_key, const RestrictedBigInteger& private_key_value, PartialKeyAccessToken token) { internal::SslUniquePtr key(EC_KEY_new()); util::StatusOr curve = SubtleCurveType(public_key.GetParameters().GetCurveType()); if (!curve.ok()) { return curve.status(); } util::StatusOr> group = internal::EcGroupFromCurveType(*curve); if (!group.ok()) { return group.status(); } EC_KEY_set_group(key.get(), group->get()); // Set EC_KEY public key. const EcPoint ec_point = public_key.GetPublicPoint(token); util::StatusOr> public_point = internal::GetEcPoint(*curve, ec_point.GetX().GetValue(), ec_point.GetY().GetValue()); if (!public_point.ok()) { return public_point.status(); } if (!EC_KEY_set_public_key(key.get(), public_point->get())) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid public key: ", internal::GetSslErrors())); } // Set EC_KEY private key. util::StatusOr> priv_big_num = internal::StringToBignum( private_key_value.GetSecret(InsecureSecretKeyAccess::Get())); if (!priv_big_num.ok()) { return priv_big_num.status(); } if (!EC_KEY_set_private_key(key.get(), priv_big_num->get())) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid private key: ", internal::GetSslErrors())); } // Check that EC_KEY is valid. if (!EC_KEY_check_key(key.get())) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid EC key pair: ", internal::GetSslErrors())); } return util::OkStatus(); } } // namespace util::StatusOr EcdsaPrivateKey::Create( const EcdsaPublicKey& public_key, const RestrictedBigInteger& private_key_value, PartialKeyAccessToken token) { // Validate that the public and private key match. util::Status key_pair_validation = ValidateKeyPair(public_key, private_key_value, token); if (!key_pair_validation.ok()) { return key_pair_validation; } return EcdsaPrivateKey(public_key, private_key_value); } bool EcdsaPrivateKey::operator==(const Key& other) const { const EcdsaPrivateKey* that = dynamic_cast(&other); if (that == nullptr) return false; return public_key_ == that->public_key_ && private_key_value_ == that->private_key_value_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ecdsa_private_key.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_ECDSA_PRIVATE_KEY_H_ #define TINK_SIGNATURE_ECDSA_PRIVATE_KEY_H_ #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_big_integer.h" #include "tink/signature/ecdsa_public_key.h" #include "tink/signature/signature_private_key.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Representation of the sign function for an ECDSA digital signature // primitive. class EcdsaPrivateKey : public SignaturePrivateKey { public: // Copyable and movable. EcdsaPrivateKey(const EcdsaPrivateKey& other) = default; EcdsaPrivateKey& operator=(const EcdsaPrivateKey& other) = default; EcdsaPrivateKey(EcdsaPrivateKey&& other) = default; EcdsaPrivateKey& operator=(EcdsaPrivateKey&& other) = default; static util::StatusOr Create( const EcdsaPublicKey& public_key, const RestrictedBigInteger& private_key_value, PartialKeyAccessToken token); const RestrictedBigInteger& GetPrivateKeyValue( PartialKeyAccessToken token) const { return private_key_value_; } const EcdsaPublicKey& GetPublicKey() const override { return public_key_; } bool operator==(const Key& other) const override; private: explicit EcdsaPrivateKey(const EcdsaPublicKey& public_key, const RestrictedBigInteger& private_key_value) : public_key_(public_key), private_key_value_(private_key_value) {} EcdsaPublicKey public_key_; RestrictedBigInteger private_key_value_; }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_ECDSA_PRIVATE_KEY_H_ ================================================ FILE: cc/signature/ecdsa_private_key_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ecdsa_private_key.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #include "openssl/ec_key.h" #endif #include "tink/big_integer.h" #include "tink/ec_point.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/ec_util.h" #include "tink/partial_key_access.h" #include "tink/restricted_big_integer.h" #include "tink/signature/ecdsa_parameters.h" #include "tink/signature/ecdsa_public_key.h" #include "tink/subtle/common_enums.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { subtle::EllipticCurveType curve; EcdsaParameters::CurveType curve_type; EcdsaParameters::HashType hash_type; EcdsaParameters::SignatureEncoding signature_encoding; EcdsaParameters::Variant variant; absl::optional id_requirement; std::string output_prefix; }; using EcdsaPrivateKeyTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( EcdsaPrivateKeyTestSuite, EcdsaPrivateKeyTest, Values(TestCase{subtle::EllipticCurveType::NIST_P256, EcdsaParameters::CurveType::kNistP256, EcdsaParameters::HashType::kSha256, EcdsaParameters::SignatureEncoding::kDer, EcdsaParameters::Variant::kTink, /*id_requirement=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{subtle::EllipticCurveType::NIST_P384, EcdsaParameters::CurveType::kNistP384, EcdsaParameters::HashType::kSha384, EcdsaParameters::SignatureEncoding::kDer, EcdsaParameters::Variant::kCrunchy, /*id_requirement=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{subtle::EllipticCurveType::NIST_P384, EcdsaParameters::CurveType::kNistP384, EcdsaParameters::HashType::kSha384, EcdsaParameters::SignatureEncoding::kIeeeP1363, EcdsaParameters::Variant::kLegacy, /*id_requirement=*/0x07080910, /*output_prefix=*/std::string("\x00\x07\x08\x09\x10", 5)}, TestCase{subtle::EllipticCurveType::NIST_P521, EcdsaParameters::CurveType::kNistP521, EcdsaParameters::HashType::kSha512, EcdsaParameters::SignatureEncoding::kIeeeP1363, EcdsaParameters::Variant::kNoPrefix, /*id_requirement=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(EcdsaPrivateKeyTest, CreatePrivateKeyWorks) { TestCase test_case = GetParam(); util::StatusOr parameters = EcdsaParameters::Builder() .SetCurveType(test_case.curve_type) .SetHashType(test_case.hash_type) .SetSignatureEncoding(test_case.signature_encoding) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr ec_key = internal::NewEcKey(test_case.curve); ASSERT_THAT(ec_key, IsOk()); EcPoint public_point(BigInteger(ec_key->pub_x), BigInteger(ec_key->pub_y)); util::StatusOr public_key = EcdsaPublicKey::Create(*parameters, public_point, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); RestrictedBigInteger private_key_value = RestrictedBigInteger(util::SecretDataAsStringView(ec_key->priv), InsecureSecretKeyAccess::Get()); util::StatusOr private_key = EcdsaPrivateKey::Create( *public_key, private_key_value, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); EXPECT_THAT(private_key->GetParameters(), Eq(*parameters)); EXPECT_THAT(private_key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(private_key->GetPublicKey(), Eq(*public_key)); EXPECT_THAT(private_key->GetOutputPrefix(), Eq(test_case.output_prefix)); EXPECT_THAT(private_key->GetPrivateKeyValue(GetPartialKeyAccess()), Eq(private_key_value)); } TEST_P(EcdsaPrivateKeyTest, CreateMismatchedKeyPairFails) { TestCase test_case = GetParam(); util::StatusOr parameters = EcdsaParameters::Builder() .SetCurveType(test_case.curve_type) .SetHashType(test_case.hash_type) .SetSignatureEncoding(test_case.signature_encoding) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr ec_key1 = internal::NewEcKey(test_case.curve); ASSERT_THAT(ec_key1, IsOk()); EcPoint public_point(BigInteger(ec_key1->pub_x), BigInteger(ec_key1->pub_y)); util::StatusOr public_key1 = EcdsaPublicKey::Create(*parameters, public_point, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key1, IsOk()); util::StatusOr ec_key2 = internal::NewEcKey(test_case.curve); ASSERT_THAT(ec_key2, IsOk()); RestrictedBigInteger private_key_bytes2 = RestrictedBigInteger(util::SecretDataAsStringView(ec_key2->priv), InsecureSecretKeyAccess::Get()); EXPECT_THAT(EcdsaPrivateKey::Create(*public_key1, private_key_bytes2, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Invalid EC key pair"))); } TEST_P(EcdsaPrivateKeyTest, PrivateKeyEquals) { TestCase test_case = GetParam(); util::StatusOr parameters = EcdsaParameters::Builder() .SetCurveType(test_case.curve_type) .SetHashType(test_case.hash_type) .SetSignatureEncoding(test_case.signature_encoding) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr ec_key = internal::NewEcKey(test_case.curve); ASSERT_THAT(ec_key, IsOk()); EcPoint public_point(BigInteger(ec_key->pub_x), BigInteger(ec_key->pub_y)); util::StatusOr public_key = EcdsaPublicKey::Create(*parameters, public_point, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); RestrictedBigInteger private_key_value = RestrictedBigInteger(util::SecretDataAsStringView(ec_key->priv), InsecureSecretKeyAccess::Get()); util::StatusOr private_key = EcdsaPrivateKey::Create( *public_key, private_key_value, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr other_private_key = EcdsaPrivateKey::Create( *public_key, private_key_value, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); EXPECT_TRUE(*private_key == *other_private_key); EXPECT_TRUE(*other_private_key == *private_key); EXPECT_FALSE(*private_key != *other_private_key); EXPECT_FALSE(*other_private_key != *private_key); } TEST(EcdsaPrivateKeyTest, DifferentPublicKeyNotEqual) { util::StatusOr parameters = EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr ec_key = internal::NewEcKey(subtle::EllipticCurveType::NIST_P256); ASSERT_THAT(ec_key, IsOk()); EcPoint public_point(BigInteger(ec_key->pub_x), BigInteger(ec_key->pub_y)); util::StatusOr public_key1 = EcdsaPublicKey::Create(*parameters, public_point, /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(public_key1, IsOk()); util::StatusOr public_key2 = EcdsaPublicKey::Create(*parameters, public_point, /*id_requirement=*/456, GetPartialKeyAccess()); ASSERT_THAT(public_key2, IsOk()); RestrictedBigInteger private_key_value = RestrictedBigInteger(util::SecretDataAsStringView(ec_key->priv), InsecureSecretKeyAccess::Get()); util::StatusOr private_key = EcdsaPrivateKey::Create( *public_key1, private_key_value, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr other_private_key = EcdsaPrivateKey::Create( *public_key2, private_key_value, GetPartialKeyAccess()); ASSERT_THAT(other_private_key, IsOk()); EXPECT_TRUE(*private_key != *other_private_key); EXPECT_TRUE(*other_private_key != *private_key); EXPECT_FALSE(*private_key == *other_private_key); EXPECT_FALSE(*other_private_key == *private_key); } TEST(EcdsaPrivateKeyTest, DifferentKeyTypesNotEqual) { util::StatusOr parameters = EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr ec_key = internal::NewEcKey(subtle::EllipticCurveType::NIST_P256); ASSERT_THAT(ec_key, IsOk()); EcPoint public_point(BigInteger(ec_key->pub_x), BigInteger(ec_key->pub_y)); util::StatusOr public_key = EcdsaPublicKey::Create(*parameters, public_point, /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); RestrictedBigInteger private_key_value = RestrictedBigInteger(util::SecretDataAsStringView(ec_key->priv), InsecureSecretKeyAccess::Get()); util::StatusOr private_key = EcdsaPrivateKey::Create( *public_key, private_key_value, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); EXPECT_TRUE(*private_key != *public_key); EXPECT_TRUE(*public_key != *private_key); EXPECT_FALSE(*private_key == *public_key); EXPECT_FALSE(*public_key == *private_key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ecdsa_proto_serialization.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ecdsa_proto_serialization.h" #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/big_integer.h" #include "tink/ec_point.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/bn_encoding_util.h" #include "tink/internal/key_parser.h" #include "tink/internal/key_serializer.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/parameters_parser.h" #include "tink/internal/parameters_serializer.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/partial_key_access.h" #include "tink/restricted_big_integer.h" #include "tink/restricted_data.h" #include "tink/secret_key_access_token.h" #include "tink/signature/ecdsa_parameters.h" #include "tink/signature/ecdsa_private_key.h" #include "tink/signature/ecdsa_public_key.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/common.pb.h" #include "proto/ecdsa.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::google::crypto::tink::EcdsaKeyFormat; using ::google::crypto::tink::EcdsaParams; using ::google::crypto::tink::EcdsaSignatureEncoding; using ::google::crypto::tink::EllipticCurveType; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using EcdsaProtoParametersParserImpl = internal::ParametersParserImpl; using EcdsaProtoParametersSerializerImpl = internal::ParametersSerializerImpl; using EcdsaProtoPublicKeyParserImpl = internal::KeyParserImpl; using EcdsaProtoPublicKeySerializerImpl = internal::KeySerializerImpl; using EcdsaProtoPrivateKeyParserImpl = internal::KeyParserImpl; using EcdsaProtoPrivateKeySerializerImpl = internal::KeySerializerImpl; const absl::string_view kPublicTypeUrl = "type.googleapis.com/google.crypto.tink.EcdsaPublicKey"; const absl::string_view kPrivateTypeUrl = "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey"; util::StatusOr ToVariant( OutputPrefixType output_prefix_type) { switch (output_prefix_type) { case OutputPrefixType::LEGACY: return EcdsaParameters::Variant::kLegacy; case OutputPrefixType::CRUNCHY: return EcdsaParameters::Variant::kCrunchy; case OutputPrefixType::RAW: return EcdsaParameters::Variant::kNoPrefix; case OutputPrefixType::TINK: return EcdsaParameters::Variant::kTink; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine output prefix type"); } } util::StatusOr ToOutputPrefixType( EcdsaParameters::Variant variant) { switch (variant) { case EcdsaParameters::Variant::kLegacy: return OutputPrefixType::LEGACY; case EcdsaParameters::Variant::kCrunchy: return OutputPrefixType::CRUNCHY; case EcdsaParameters::Variant::kNoPrefix: return OutputPrefixType::RAW; case EcdsaParameters::Variant::kTink: return OutputPrefixType::TINK; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine EcdsaParameters::Variant"); } } util::StatusOr ToHashType(HashType hash_type) { switch (hash_type) { case HashType::SHA256: return EcdsaParameters::HashType::kSha256; case HashType::SHA384: return EcdsaParameters::HashType::kSha384; case HashType::SHA512: return EcdsaParameters::HashType::kSha512; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine HashType"); } } util::StatusOr ToProtoHashType(EcdsaParameters::HashType hash_type) { switch (hash_type) { case EcdsaParameters::HashType::kSha256: return HashType::SHA256; case EcdsaParameters::HashType::kSha384: return HashType::SHA384; case EcdsaParameters::HashType::kSha512: return HashType::SHA512; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine EcdsaParameters::HashType"); } } util::StatusOr ToCurveType( EllipticCurveType curve_type) { switch (curve_type) { case EllipticCurveType::NIST_P256: return EcdsaParameters::CurveType::kNistP256; case EllipticCurveType::NIST_P384: return EcdsaParameters::CurveType::kNistP384; case EllipticCurveType::NIST_P521: return EcdsaParameters::CurveType::kNistP521; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine EllipticCurveType"); } } util::StatusOr ToProtoCurveType( EcdsaParameters::CurveType curve_type) { switch (curve_type) { case EcdsaParameters::CurveType::kNistP256: return EllipticCurveType::NIST_P256; case EcdsaParameters::CurveType::kNistP384: return EllipticCurveType::NIST_P384; case EcdsaParameters::CurveType::kNistP521: return EllipticCurveType::NIST_P521; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine EcdsaParameters::CurveType"); } } util::StatusOr ToSignatureEncoding( EcdsaSignatureEncoding signature_encoding) { switch (signature_encoding) { case EcdsaSignatureEncoding::DER: return EcdsaParameters::SignatureEncoding::kDer; case EcdsaSignatureEncoding::IEEE_P1363: return EcdsaParameters::SignatureEncoding::kIeeeP1363; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine EcdsaSignatureEncoding"); } } util::StatusOr ToProtoSignatureEncoding( EcdsaParameters::SignatureEncoding signature_encoding) { switch (signature_encoding) { case EcdsaParameters::SignatureEncoding::kDer: return EcdsaSignatureEncoding::DER; case EcdsaParameters::SignatureEncoding::kIeeeP1363: return EcdsaSignatureEncoding::IEEE_P1363; default: return util::Status( absl::StatusCode::kInvalidArgument, "Could not determine EcdsaParameters::SignatureEncoding"); } } util::StatusOr getEncodingLength(EcdsaParameters::CurveType curveType) { // We currently encode with one extra 0 byte at the beginning, to make sure // that parsing is correct. See also b/264525021. switch (curveType) { case EcdsaParameters::CurveType::kNistP256: return 33; case EcdsaParameters::CurveType::kNistP384: return 49; case EcdsaParameters::CurveType::kNistP521: return 67; default: return util::Status(absl::StatusCode::kInvalidArgument, "Unable to serialize CurveType"); } } util::StatusOr ToParameters( OutputPrefixType output_prefix_type, const EcdsaParams& params) { util::StatusOr variant = ToVariant(output_prefix_type); if (!variant.ok()) { return variant.status(); } util::StatusOr hash_type = ToHashType(params.hash_type()); if (!hash_type.ok()) { return hash_type.status(); } util::StatusOr curve_type = ToCurveType(params.curve()); if (!curve_type.ok()) { return curve_type.status(); } util::StatusOr encoding = ToSignatureEncoding(params.encoding()); if (!encoding.ok()) { return encoding.status(); } return EcdsaParameters::Builder() .SetVariant(*variant) .SetHashType(*hash_type) .SetCurveType(*curve_type) .SetSignatureEncoding(*encoding) .Build(); } util::StatusOr FromParameters(const EcdsaParameters& parameters) { util::StatusOr curve = ToProtoCurveType(parameters.GetCurveType()); if (!curve.ok()) { return curve.status(); } util::StatusOr hash_type = ToProtoHashType(parameters.GetHashType()); if (!hash_type.ok()) { return hash_type.status(); } util::StatusOr encoding = ToProtoSignatureEncoding(parameters.GetSignatureEncoding()); if (!encoding.ok()) { return encoding.status(); } EcdsaParams params; params.set_curve(*curve); params.set_hash_type(*hash_type); params.set_encoding(*encoding); return params; } util::StatusOr ParseParameters( const internal::ProtoParametersSerialization& serialization) { if (serialization.GetKeyTemplate().type_url() != kPrivateTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing EcdsaParameters."); } EcdsaKeyFormat proto_key_format; if (!proto_key_format.ParseFromString( serialization.GetKeyTemplate().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse EcdsaKeyFormat proto"); } if (proto_key_format.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } if (!proto_key_format.has_params()) { return util::Status(absl::StatusCode::kInvalidArgument, "EcdsaKeyFormat proto is missing params field."); } return ToParameters(serialization.GetKeyTemplate().output_prefix_type(), proto_key_format.params()); } util::StatusOr ParsePublicKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (serialization.TypeUrl() != kPublicTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing EcdsaPublicKey."); } google::crypto::tink::EcdsaPublicKey proto_key; const RestrictedData& restricted_data = serialization.SerializedKeyProto(); if (!proto_key.ParseFromString( restricted_data.GetSecret(InsecureSecretKeyAccess::Get()))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse EcdsaPublicKey proto"); } if (proto_key.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } util::StatusOr parameters = ToParameters(serialization.GetOutputPrefixType(), proto_key.params()); if (!parameters.ok()) { return parameters.status(); } EcPoint public_point(BigInteger(proto_key.x()), BigInteger(proto_key.y())); return EcdsaPublicKey::Create(*parameters, public_point, serialization.IdRequirement(), GetPartialKeyAccess()); } util::StatusOr ParsePrivateKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (serialization.TypeUrl() != kPrivateTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing EcdsaPrivateKey."); } if (!token.has_value()) { return util::Status(absl::StatusCode::kPermissionDenied, "SecretKeyAccess is required"); } google::crypto::tink::EcdsaPrivateKey proto_key; const RestrictedData& restricted_data = serialization.SerializedKeyProto(); if (!proto_key.ParseFromString(restricted_data.GetSecret(*token))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse EcdsaPrivateKey proto"); } if (proto_key.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } util::StatusOr variant = ToVariant(serialization.GetOutputPrefixType()); if (!variant.ok()) { return variant.status(); } util::StatusOr parameters = ToParameters( serialization.GetOutputPrefixType(), proto_key.public_key().params()); if (!parameters.ok()) { return parameters.status(); } EcPoint public_point(BigInteger(proto_key.public_key().x()), BigInteger(proto_key.public_key().y())); util::StatusOr public_key = EcdsaPublicKey::Create( *parameters, public_point, serialization.IdRequirement(), GetPartialKeyAccess()); RestrictedBigInteger private_key_value = RestrictedBigInteger(proto_key.key_value(), *token); return EcdsaPrivateKey::Create(*public_key, private_key_value, GetPartialKeyAccess()); } util::StatusOr SerializeParameters( const EcdsaParameters& parameters) { util::StatusOr output_prefix_type = ToOutputPrefixType(parameters.GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } util::StatusOr params = FromParameters(parameters); if (!params.ok()) { return params.status(); } EcdsaKeyFormat proto_key_format; *proto_key_format.mutable_params() = *params; proto_key_format.set_version(0); return internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, *output_prefix_type, proto_key_format.SerializeAsString()); } util::StatusOr SerializePublicKey( const EcdsaPublicKey& key, absl::optional token) { util::StatusOr params = FromParameters(key.GetParameters()); if (!params.ok()) { return params.status(); } util::StatusOr enc_length = getEncodingLength(key.GetParameters().GetCurveType()); if (!enc_length.ok()) { return enc_length.status(); } util::StatusOr x = internal::GetValueOfFixedLength( key.GetPublicPoint(GetPartialKeyAccess()).GetX().GetValue(), enc_length.value()); if (!x.ok()) { return x.status(); } util::StatusOr y = internal::GetValueOfFixedLength( key.GetPublicPoint(GetPartialKeyAccess()).GetY().GetValue(), enc_length.value()); if (!y.ok()) { return y.status(); } google::crypto::tink::EcdsaPublicKey proto_key; proto_key.set_version(0); *proto_key.mutable_params() = *params; proto_key.set_x(*x); proto_key.set_y(*y); util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetParameters().GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } RestrictedData restricted_output = RestrictedData( proto_key.SerializeAsString(), InsecureSecretKeyAccess::Get()); return internal::ProtoKeySerialization::Create( kPublicTypeUrl, restricted_output, KeyData::ASYMMETRIC_PUBLIC, *output_prefix_type, key.GetIdRequirement()); } util::StatusOr SerializePrivateKey( const EcdsaPrivateKey& key, absl::optional token) { util::StatusOr restricted_input = key.GetPrivateKeyValue(GetPartialKeyAccess()); if (!restricted_input.ok()) { return restricted_input.status(); } if (!token.has_value()) { return util::Status(absl::StatusCode::kPermissionDenied, "SecretKeyAccess is required"); } util::StatusOr params = FromParameters(key.GetPublicKey().GetParameters()); if (!params.ok()) { return params.status(); } util::StatusOr enc_length = getEncodingLength(key.GetPublicKey().GetParameters().GetCurveType()); if (!enc_length.ok()) { return enc_length.status(); } google::crypto::tink::EcdsaPublicKey proto_public_key; proto_public_key.set_version(0); *proto_public_key.mutable_params() = *params; proto_public_key.set_x(*internal::GetValueOfFixedLength( key.GetPublicKey() .GetPublicPoint(GetPartialKeyAccess()) .GetX() .GetValue(), enc_length.value())); proto_public_key.set_y(*internal::GetValueOfFixedLength( key.GetPublicKey() .GetPublicPoint(GetPartialKeyAccess()) .GetY() .GetValue(), enc_length.value())); google::crypto::tink::EcdsaPrivateKey proto_private_key; proto_private_key.set_version(0); *proto_private_key.mutable_public_key() = proto_public_key; proto_private_key.set_key_value(*internal::GetValueOfFixedLength( restricted_input->GetSecret(*token), *enc_length)); util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetPublicKey().GetParameters().GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } RestrictedData restricted_output = RestrictedData(proto_private_key.SerializeAsString(), *token); return internal::ProtoKeySerialization::Create( kPrivateTypeUrl, restricted_output, KeyData::ASYMMETRIC_PRIVATE, *output_prefix_type, key.GetIdRequirement()); } EcdsaProtoParametersParserImpl& EcdsaProtoParametersParser() { static auto* parser = new EcdsaProtoParametersParserImpl(kPrivateTypeUrl, ParseParameters); return *parser; } EcdsaProtoParametersSerializerImpl& EcdsaProtoParametersSerializer() { static auto* serializer = new EcdsaProtoParametersSerializerImpl( kPrivateTypeUrl, SerializeParameters); return *serializer; } EcdsaProtoPublicKeyParserImpl& EcdsaProtoPublicKeyParser() { static auto* parser = new EcdsaProtoPublicKeyParserImpl(kPublicTypeUrl, ParsePublicKey); return *parser; } EcdsaProtoPublicKeySerializerImpl& EcdsaProtoPublicKeySerializer() { static auto* serializer = new EcdsaProtoPublicKeySerializerImpl(SerializePublicKey); return *serializer; } EcdsaProtoPrivateKeyParserImpl& EcdsaProtoPrivateKeyParser() { static auto* parser = new EcdsaProtoPrivateKeyParserImpl(kPrivateTypeUrl, ParsePrivateKey); return *parser; } EcdsaProtoPrivateKeySerializerImpl& EcdsaProtoPrivateKeySerializer() { static auto* serializer = new EcdsaProtoPrivateKeySerializerImpl(SerializePrivateKey); return *serializer; } } // namespace util::Status RegisterEcdsaProtoSerialization() { util::Status status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersParser(&EcdsaProtoParametersParser()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersSerializer(&EcdsaProtoParametersSerializer()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(&EcdsaProtoPublicKeyParser()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(&EcdsaProtoPublicKeySerializer()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(&EcdsaProtoPrivateKeyParser()); if (!status.ok()) { return status; } return internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(&EcdsaProtoPrivateKeySerializer()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ecdsa_proto_serialization.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_ECDSA_PROTO_SERIALIZATION_H_ #define TINK_SIGNATURE_ECDSA_PROTO_SERIALIZATION_H_ #include "tink/util/status.h" namespace crypto { namespace tink { // Registers proto parsers and serializers for ECDSA parameters and keys. crypto::tink::util::Status RegisterEcdsaProtoSerialization(); } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_ECDSA_PROTO_SERIALIZATION_H_ ================================================ FILE: cc/signature/ecdsa_proto_serialization_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ecdsa_proto_serialization.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/restricted_big_integer.h" #include "tink/util/secret_data.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #include "openssl/ec_key.h" #else #include "openssl/ec.h" #endif #include "tink/big_integer.h" #include "tink/ec_point.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/ec_util.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/signature/ecdsa_parameters.h" #include "tink/signature/ecdsa_private_key.h" #include "tink/signature/ecdsa_public_key.h" #include "tink/subtle/common_enums.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/common.pb.h" #include "proto/ecdsa.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::EcdsaKeyFormat; using ::google::crypto::tink::EcdsaParams; using ::google::crypto::tink::EcdsaSignatureEncoding; using ::google::crypto::tink::EllipticCurveType; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::IsTrue; using ::testing::NotNull; using ::testing::TestWithParam; using ::testing::Values; const absl::string_view kPublicTypeUrl = "type.googleapis.com/google.crypto.tink.EcdsaPublicKey"; const absl::string_view kPrivateTypeUrl = "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey"; struct TestCase { EcdsaParameters::Variant variant = EcdsaParameters::Variant::kTink; EcdsaParameters::CurveType curve_type = EcdsaParameters::CurveType::kNistP256; EcdsaParameters::HashType hash_type = EcdsaParameters::HashType::kSha256; EcdsaParameters::SignatureEncoding signature_encoding = EcdsaParameters::SignatureEncoding::kDer; OutputPrefixType output_prefix_type = OutputPrefixType::TINK; EllipticCurveType curve = EllipticCurveType::NIST_P256; HashType hash = HashType::SHA256; EcdsaSignatureEncoding encoding = EcdsaSignatureEncoding::DER; subtle::EllipticCurveType subtle_curve = subtle::EllipticCurveType::NIST_P256; absl::optional id; std::string output_prefix; }; class EcdsaProtoSerializationTest : public TestWithParam { protected: EcdsaProtoSerializationTest() { internal::MutableSerializationRegistry::GlobalInstance().Reset(); } }; TEST_F(EcdsaProtoSerializationTest, RegisterTwiceSucceeds) { ASSERT_THAT(RegisterEcdsaProtoSerialization(), IsOk()); ASSERT_THAT(RegisterEcdsaProtoSerialization(), IsOk()); } INSTANTIATE_TEST_SUITE_P( EcdsaProtoSerializationTestSuite, EcdsaProtoSerializationTest, Values(TestCase{EcdsaParameters::Variant::kTink, EcdsaParameters::CurveType::kNistP256, EcdsaParameters::HashType::kSha256, EcdsaParameters::SignatureEncoding::kDer, OutputPrefixType::TINK, EllipticCurveType::NIST_P256, HashType::SHA256, EcdsaSignatureEncoding::DER, subtle::EllipticCurveType::NIST_P256, /*id_requirement=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{EcdsaParameters::Variant::kCrunchy, EcdsaParameters::CurveType::kNistP384, EcdsaParameters::HashType::kSha384, EcdsaParameters::SignatureEncoding::kDer, OutputPrefixType::CRUNCHY, EllipticCurveType::NIST_P384, HashType::SHA384, EcdsaSignatureEncoding::DER, subtle::EllipticCurveType::NIST_P384, /*id_requirement=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{EcdsaParameters::Variant::kLegacy, EcdsaParameters::CurveType::kNistP256, EcdsaParameters::HashType::kSha256, EcdsaParameters::SignatureEncoding::kIeeeP1363, OutputPrefixType::LEGACY, EllipticCurveType::NIST_P256, HashType::SHA256, EcdsaSignatureEncoding::IEEE_P1363, subtle::EllipticCurveType::NIST_P256, /*id_requirement=*/0x07080910, /*output_prefix=*/std::string("\x00\x07\x08\x09\x10", 5)}, TestCase{EcdsaParameters::Variant::kNoPrefix, EcdsaParameters::CurveType::kNistP521, EcdsaParameters::HashType::kSha512, EcdsaParameters::SignatureEncoding::kIeeeP1363, OutputPrefixType::RAW, EllipticCurveType::NIST_P521, HashType::SHA512, EcdsaSignatureEncoding::IEEE_P1363, subtle::EllipticCurveType::NIST_P521, /*id_requirement=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(EcdsaProtoSerializationTest, ParseParametersWorks) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterEcdsaProtoSerialization(), IsOk()); EcdsaKeyFormat key_format_proto; EcdsaParams& params = *key_format_proto.mutable_params(); params.set_curve(test_case.curve); params.set_hash_type(test_case.hash); params.set_encoding(test_case.encoding); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, test_case.output_prefix_type, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(parameters, IsOk()); EXPECT_EQ((*parameters)->HasIdRequirement(), test_case.id.has_value()); const EcdsaParameters* ecdsa_parameters = dynamic_cast(parameters->get()); ASSERT_THAT(ecdsa_parameters, NotNull()); EXPECT_THAT(ecdsa_parameters->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(ecdsa_parameters->GetCurveType(), Eq(test_case.curve_type)); EXPECT_THAT(ecdsa_parameters->GetHashType(), Eq(test_case.hash_type)); EXPECT_THAT(ecdsa_parameters->GetSignatureEncoding(), Eq(test_case.signature_encoding)); } TEST_F(EcdsaProtoSerializationTest, ParseParametersWithInvalidSerializationFails) { ASSERT_THAT(RegisterEcdsaProtoSerialization(), IsOk()); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::RAW, "invalid_serialization"); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT(internal::MutableSerializationRegistry::GlobalInstance() .ParseParameters(*serialization) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Failed to parse EcdsaKeyFormat proto"))); } TEST_F(EcdsaProtoSerializationTest, ParseParametersWithInvalidVersionFails) { ASSERT_THAT(RegisterEcdsaProtoSerialization(), IsOk()); EcdsaKeyFormat key_format_proto; key_format_proto.set_version(1); EcdsaParams& params = *key_format_proto.mutable_params(); params.set_curve(EllipticCurveType::NIST_P256); params.set_hash_type(HashType::SHA256); params.set_encoding(EcdsaSignatureEncoding::DER); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::RAW, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Only version 0 keys are accepted"))); } TEST_F(EcdsaProtoSerializationTest, ParseParametersWithUnkownOutputPrefixFails) { ASSERT_THAT(RegisterEcdsaProtoSerialization(), IsOk()); EcdsaKeyFormat key_format_proto; EcdsaParams& params = *key_format_proto.mutable_params(); params.set_curve(EllipticCurveType::NIST_P256); params.set_hash_type(HashType::SHA256); params.set_encoding(EcdsaSignatureEncoding::DER); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::UNKNOWN_PREFIX, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Could not determine output prefix type"))); } TEST_F(EcdsaProtoSerializationTest, ParseParametersKeyFormatWithoutParamsFails) { ASSERT_THAT(RegisterEcdsaProtoSerialization(), IsOk()); EcdsaKeyFormat key_format_proto; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::RAW, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("EcdsaKeyFormat proto is missing params"))); } TEST_F(EcdsaProtoSerializationTest, ParseParametersWithUnkownCurveTypeFails) { ASSERT_THAT(RegisterEcdsaProtoSerialization(), IsOk()); EcdsaKeyFormat key_format_proto; EcdsaParams& params = *key_format_proto.mutable_params(); params.set_curve(EllipticCurveType::UNKNOWN_CURVE); params.set_hash_type(HashType::SHA256); params.set_encoding(EcdsaSignatureEncoding::DER); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Could not determine EllipticCurveType"))); } TEST_F(EcdsaProtoSerializationTest, ParseParametersWithUnkownHashTypeFails) { ASSERT_THAT(RegisterEcdsaProtoSerialization(), IsOk()); EcdsaKeyFormat key_format_proto; EcdsaParams& params = *key_format_proto.mutable_params(); params.set_curve(EllipticCurveType::NIST_P256); params.set_hash_type(HashType::UNKNOWN_HASH); params.set_encoding(EcdsaSignatureEncoding::DER); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Could not determine HashType"))); } TEST_F(EcdsaProtoSerializationTest, ParseParametersWithUnkownEncodingFails) { ASSERT_THAT(RegisterEcdsaProtoSerialization(), IsOk()); EcdsaKeyFormat key_format_proto; EcdsaParams& params = *key_format_proto.mutable_params(); params.set_curve(EllipticCurveType::NIST_P256); params.set_hash_type(HashType::SHA256); params.set_encoding(EcdsaSignatureEncoding::UNKNOWN_ENCODING); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT( parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Could not determine EcdsaSignatureEncoding"))); } TEST_P(EcdsaProtoSerializationTest, SerializeParametersWorks) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterEcdsaProtoSerialization(), IsOk()); util::StatusOr parameters = EcdsaParameters::Builder() .SetVariant(test_case.variant) .SetHashType(test_case.hash_type) .SetCurveType(test_case.curve_type) .SetSignatureEncoding(test_case.signature_encoding) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( *parameters); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kPrivateTypeUrl)); const internal::ProtoParametersSerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->GetKeyTemplate().type_url(), Eq(kPrivateTypeUrl)); EXPECT_THAT(proto_serialization->GetKeyTemplate().output_prefix_type(), Eq(test_case.output_prefix_type)); EcdsaKeyFormat key_format; ASSERT_THAT( key_format.ParseFromString(proto_serialization->GetKeyTemplate().value()), IsTrue()); ASSERT_TRUE(key_format.has_params()); EXPECT_THAT(key_format.params().hash_type(), Eq(test_case.hash)); EXPECT_THAT(key_format.params().curve(), Eq(test_case.curve)); EXPECT_THAT(key_format.params().encoding(), Eq(test_case.encoding)); } TEST_P(EcdsaProtoSerializationTest, ParsePublicKeyWorks) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterEcdsaProtoSerialization(), IsOk()); EcdsaParams params; params.set_curve(test_case.curve); params.set_hash_type(test_case.hash); params.set_encoding(test_case.encoding); util::StatusOr ec_key = internal::NewEcKey(test_case.subtle_curve); ASSERT_THAT(ec_key, IsOk()); google::crypto::tink::EcdsaPublicKey key_proto; key_proto.set_version(0); key_proto.set_x(ec_key->pub_x); key_proto.set_y(ec_key->pub_y); *key_proto.mutable_params() = params; RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kPublicTypeUrl, serialized_key, KeyData::ASYMMETRIC_PUBLIC, test_case.output_prefix_type, test_case.id); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); ASSERT_THAT(key, IsOk()); EXPECT_THAT((*key)->GetIdRequirement(), Eq(test_case.id)); EXPECT_THAT((*key)->GetParameters().HasIdRequirement(), test_case.id.has_value()); util::StatusOr expected_parameters = EcdsaParameters::Builder() .SetVariant(test_case.variant) .SetHashType(test_case.hash_type) .SetCurveType(test_case.curve_type) .SetSignatureEncoding(test_case.signature_encoding) .Build(); ASSERT_THAT(expected_parameters, IsOk()); util::StatusOr expected_key = EcdsaPublicKey::Create( *expected_parameters, EcPoint(BigInteger(ec_key->pub_x), BigInteger(ec_key->pub_y)), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(expected_key, IsOk()); EXPECT_THAT(**key, Eq(*expected_key)); } TEST_F(EcdsaProtoSerializationTest, ParsePublicKeyWithInvalidSerializationFails) { ASSERT_THAT(RegisterEcdsaProtoSerialization(), IsOk()); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPublicTypeUrl, serialized_key, KeyData::ASYMMETRIC_PUBLIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Failed to parse EcdsaPublicKey proto"))); } TEST_F(EcdsaProtoSerializationTest, ParsePublicKeyWithInvalidVersionFails) { ASSERT_THAT(RegisterEcdsaProtoSerialization(), IsOk()); EcdsaParams params; params.set_curve(EllipticCurveType::NIST_P256); params.set_hash_type(HashType::SHA256); params.set_encoding(EcdsaSignatureEncoding::DER); util::StatusOr ec_key = internal::NewEcKey(subtle::EllipticCurveType::NIST_P256); ASSERT_THAT(ec_key, IsOk()); google::crypto::tink::EcdsaPublicKey key_proto; key_proto.set_version(1); key_proto.set_x(ec_key->pub_x); key_proto.set_y(ec_key->pub_y); *key_proto.mutable_params() = params; RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPublicTypeUrl, serialized_key, KeyData::ASYMMETRIC_PUBLIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Only version 0 keys are accepted"))); } TEST_P(EcdsaProtoSerializationTest, SerializePublicKeyWorks) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterEcdsaProtoSerialization(), IsOk()); util::StatusOr parameters = EcdsaParameters::Builder() .SetVariant(test_case.variant) .SetHashType(test_case.hash_type) .SetCurveType(test_case.curve_type) .SetSignatureEncoding(test_case.signature_encoding) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr ec_key = internal::NewEcKey(test_case.subtle_curve); ASSERT_THAT(ec_key, IsOk()); util::StatusOr key = EcdsaPublicKey::Create( *parameters, EcPoint(BigInteger(ec_key->pub_x), BigInteger(ec_key->pub_y)), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, /*token=*/absl::nullopt); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kPublicTypeUrl)); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq(kPublicTypeUrl)); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::ASYMMETRIC_PUBLIC)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id)); google::crypto::tink::EcdsaPublicKey proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.version(), Eq(0)); // We currently encode with one extra 0 byte at the beginning, to make sure // that parsing is correct. See also b/264525021. EXPECT_THAT(proto_key.x(), Eq('\0' + ec_key->pub_x)); EXPECT_THAT(proto_key.y(), Eq('\0' + ec_key->pub_y)); EXPECT_THAT(proto_key.has_params(), IsTrue()); EXPECT_THAT(proto_key.params().curve(), Eq(test_case.curve)); EXPECT_THAT(proto_key.params().hash_type(), Eq(test_case.hash)); EXPECT_THAT(proto_key.params().encoding(), Eq(test_case.encoding)); } TEST_P(EcdsaProtoSerializationTest, ParsePrivateKeyWorks) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterEcdsaProtoSerialization(), IsOk()); EcdsaParams params; params.set_curve(test_case.curve); params.set_hash_type(test_case.hash); params.set_encoding(test_case.encoding); util::StatusOr ec_key = internal::NewEcKey(test_case.subtle_curve); ASSERT_THAT(ec_key, IsOk()); google::crypto::tink::EcdsaPublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_x(ec_key->pub_x); public_key_proto.set_y(ec_key->pub_y); *public_key_proto.mutable_params() = params; google::crypto::tink::EcdsaPrivateKey private_key_proto; private_key_proto.set_version(0); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_key_value(util::SecretDataAsStringView(ec_key->priv)); RestrictedData serialized_key = RestrictedData( private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, test_case.output_prefix_type, test_case.id); ASSERT_THAT(serialization, IsOk()); util::StatusOr> private_key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(private_key, IsOk()); EXPECT_THAT((*private_key)->GetIdRequirement(), Eq(test_case.id)); EXPECT_THAT((*private_key)->GetParameters().HasIdRequirement(), test_case.id.has_value()); util::StatusOr expected_parameters = EcdsaParameters::Builder() .SetVariant(test_case.variant) .SetHashType(test_case.hash_type) .SetCurveType(test_case.curve_type) .SetSignatureEncoding(test_case.signature_encoding) .Build(); ASSERT_THAT(expected_parameters, IsOk()); util::StatusOr expected_public_key = EcdsaPublicKey::Create( *expected_parameters, EcPoint(BigInteger(ec_key->pub_x), BigInteger(ec_key->pub_y)), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(expected_public_key, IsOk()); util::StatusOr expected_private_key = EcdsaPrivateKey::Create( *expected_public_key, RestrictedBigInteger(util::SecretDataAsStringView(ec_key->priv), InsecureSecretKeyAccess::Get()), GetPartialKeyAccess()); EXPECT_THAT(**private_key, Eq(*expected_private_key)); } TEST_F(EcdsaProtoSerializationTest, ParsePrivateKeyWithInvalidSerializationFails) { ASSERT_THAT(RegisterEcdsaProtoSerialization(), IsOk()); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Failed to parse EcdsaPrivateKey proto"))); } TEST_F(EcdsaProtoSerializationTest, ParsePrivateKeyWithInvalidVersionFails) { ASSERT_THAT(RegisterEcdsaProtoSerialization(), IsOk()); EcdsaParams params; params.set_curve(EllipticCurveType::NIST_P256); params.set_hash_type(HashType::SHA256); params.set_encoding(EcdsaSignatureEncoding::DER); util::StatusOr ec_key = internal::NewEcKey(subtle::EllipticCurveType::NIST_P256); ASSERT_THAT(ec_key, IsOk()); google::crypto::tink::EcdsaPublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_x(ec_key->pub_x); public_key_proto.set_y(ec_key->pub_y); *public_key_proto.mutable_params() = params; google::crypto::tink::EcdsaPrivateKey private_key_proto; private_key_proto.set_version(1); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_key_value(util::SecretDataAsStringView(ec_key->priv)); RestrictedData serialized_key = RestrictedData( private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Only version 0 keys are accepted"))); } TEST_F(EcdsaProtoSerializationTest, ParsePrivateKeyNoSecretKeyAccessFails) { ASSERT_THAT(RegisterEcdsaProtoSerialization(), IsOk()); EcdsaParams params; params.set_curve(EllipticCurveType::NIST_P256); params.set_hash_type(HashType::SHA256); params.set_encoding(EcdsaSignatureEncoding::DER); util::StatusOr ec_key = internal::NewEcKey(subtle::EllipticCurveType::NIST_P256); ASSERT_THAT(ec_key, IsOk()); google::crypto::tink::EcdsaPublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_x(ec_key->pub_x); public_key_proto.set_y(ec_key->pub_y); *public_key_proto.mutable_params() = params; google::crypto::tink::EcdsaPrivateKey private_key_proto; private_key_proto.set_version(0); ; *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_key_value(util::SecretDataAsStringView(ec_key->priv)); RestrictedData serialized_key = RestrictedData( private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kPermissionDenied, HasSubstr("SecretKeyAccess is required"))); } TEST_P(EcdsaProtoSerializationTest, SerializePrivateKeyWorks) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterEcdsaProtoSerialization(), IsOk()); util::StatusOr parameters = EcdsaParameters::Builder() .SetVariant(test_case.variant) .SetHashType(test_case.hash_type) .SetCurveType(test_case.curve_type) .SetSignatureEncoding(test_case.signature_encoding) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr ec_key = internal::NewEcKey(test_case.subtle_curve); ASSERT_THAT(ec_key, IsOk()); util::StatusOr public_key = EcdsaPublicKey::Create( *parameters, EcPoint(BigInteger(ec_key->pub_x), BigInteger(ec_key->pub_y)), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = EcdsaPrivateKey::Create( *public_key, RestrictedBigInteger(util::SecretDataAsStringView(ec_key->priv), InsecureSecretKeyAccess::Get()), GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *private_key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kPrivateTypeUrl)); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq(kPrivateTypeUrl)); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::ASYMMETRIC_PRIVATE)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id)); google::crypto::tink::EcdsaPrivateKey proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.version(), Eq(0)); // We currently encode with one extra 0 byte at the beginning, to make sure // that parsing is correct. EXPECT_THAT( proto_key.key_value(), Eq('\0' + std::string(util::SecretDataAsStringView(ec_key->priv)))); EXPECT_THAT(proto_key.has_public_key(), IsTrue()); EXPECT_THAT(proto_key.public_key().version(), Eq(0)); EXPECT_THAT(proto_key.public_key().has_params(), IsTrue()); EXPECT_THAT(proto_key.public_key().params().hash_type(), Eq(test_case.hash)); EXPECT_THAT(proto_key.public_key().params().curve(), Eq(test_case.curve)); EXPECT_THAT(proto_key.public_key().params().encoding(), Eq(test_case.encoding)); EXPECT_THAT(proto_key.public_key().x(), Eq('\0' + ec_key->pub_x)); EXPECT_THAT(proto_key.public_key().y(), Eq('\0' + ec_key->pub_y)); } TEST_F(EcdsaProtoSerializationTest, SerializePrivateKeyNoSecretKeyAccessFails) { ASSERT_THAT(RegisterEcdsaProtoSerialization(), IsOk()); util::StatusOr parameters = EcdsaParameters::Builder() .SetVariant(EcdsaParameters::Variant::kNoPrefix) .SetHashType(EcdsaParameters::HashType::kSha256) .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr ec_key = internal::NewEcKey(subtle::EllipticCurveType::NIST_P256); ASSERT_THAT(ec_key, IsOk()); util::StatusOr public_key = EcdsaPublicKey::Create( *parameters, EcPoint(BigInteger(ec_key->pub_x), BigInteger(ec_key->pub_y)), /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = EcdsaPrivateKey::Create( *public_key, RestrictedBigInteger(util::SecretDataAsStringView(ec_key->priv), InsecureSecretKeyAccess::Get()), GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *private_key, /*token=*/absl::nullopt); ASSERT_THAT(serialization.status(), StatusIs(absl::StatusCode::kPermissionDenied, HasSubstr("SecretKeyAccess is required"))); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ecdsa_public_key.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ecdsa_public_key.h" #include #include "absl/base/attributes.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #include "openssl/ec_key.h" #else #include "openssl/ec.h" #endif #include "tink/ec_point.h" #include "tink/internal/ec_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/signature/ecdsa_parameters.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { util::Status ValidatePublicPoint(EcdsaParameters::CurveType curve_type, const EcPoint& point) { subtle::EllipticCurveType curve; switch (curve_type) { case EcdsaParameters::CurveType::kNistP256: curve = subtle::EllipticCurveType::NIST_P256; break; case EcdsaParameters::CurveType::kNistP384: curve = subtle::EllipticCurveType::NIST_P384; break; case EcdsaParameters::CurveType::kNistP521: curve = subtle::EllipticCurveType::NIST_P521; break; default: return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Unknown curve type: ", curve_type)); } // Internally calls EC_POINT_set_affine_coordinates_GFp, which, in BoringSSL // and OpenSSL versions > 1.1.0, already checks if the point is on the curve. util::StatusOr> ec_point = internal::GetEcPoint(curve, point.GetX().GetValue(), point.GetY().GetValue()); if (!ec_point.ok()) { return ec_point.status(); } util::StatusOr> group = internal::EcGroupFromCurveType(curve); if (!group.ok()) { return group.status(); } if (EC_POINT_is_on_curve(group->get(), ec_point->get(), /*ctx=*/nullptr) != 1) { return util::Status(absl::StatusCode::kInternal, absl::StrCat("EC public point is not on curve ", subtle::EnumToString(curve))); } return util::OkStatus(); } util::StatusOr ComputeOutputPrefix( const EcdsaParameters& parameters, absl::optional id_requirement) { switch (parameters.GetVariant()) { case EcdsaParameters::Variant::kNoPrefix: return std::string(""); // Empty prefix. case EcdsaParameters::Variant::kLegacy: ABSL_FALLTHROUGH_INTENDED; case EcdsaParameters::Variant::kCrunchy: if (!id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "ID requirement must have value with kCrunchy or kLegacy"); } return absl::StrCat(absl::HexStringToBytes("00"), subtle::BigEndian32(*id_requirement)); case EcdsaParameters::Variant::kTink: if (!id_requirement.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "ID requirement must have value with kTink"); } return absl::StrCat(absl::HexStringToBytes("01"), subtle::BigEndian32(*id_requirement)); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid variant: ", parameters.GetVariant())); } } util::Status ValidateIdRequirement(const EcdsaParameters& parameters, absl::optional id_requirement) { if (parameters.HasIdRequirement() && !id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key without ID requirement with parameters with ID " "requirement"); } if (!parameters.HasIdRequirement() && id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key with ID requirement with parameters without ID " "requirement"); } return util::OkStatus(); } } // namespace util::StatusOr EcdsaPublicKey::Create( const EcdsaParameters& parameters, const EcPoint& public_point, absl::optional id_requirement, PartialKeyAccessToken token) { util::Status id_requirement_validation = ValidateIdRequirement(parameters, id_requirement); if (!id_requirement_validation.ok()) { return id_requirement_validation; } util::Status public_key_validation = ValidatePublicPoint(parameters.GetCurveType(), public_point); if (!public_key_validation.ok()) { return public_key_validation; } util::StatusOr output_prefix = ComputeOutputPrefix(parameters, id_requirement); if (!output_prefix.ok()) { return output_prefix.status(); } return EcdsaPublicKey(parameters, public_point, id_requirement, *output_prefix); } bool EcdsaPublicKey::operator==(const Key& other) const { const EcdsaPublicKey* that = dynamic_cast(&other); if (that == nullptr) return false; return GetParameters() == that->GetParameters() && id_requirement_ == that->id_requirement_ && public_point_ == that->public_point_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ecdsa_public_key.h ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_ECDSA_PUBLIC_KEY_H_ #define TINK_SIGNATURE_ECDSA_PUBLIC_KEY_H_ #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/ec_point.h" #include "tink/signature/ecdsa_parameters.h" #include "tink/signature/signature_public_key.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Representation of the verify function for an ECDSA digital signature // primitive. class EcdsaPublicKey : public SignaturePublicKey { public: // Copyable and movable. EcdsaPublicKey(const EcdsaPublicKey& other) = default; EcdsaPublicKey& operator=(const EcdsaPublicKey& other) = default; EcdsaPublicKey(EcdsaPublicKey&& other) = default; EcdsaPublicKey& operator=(EcdsaPublicKey&& other) = default; static util::StatusOr Create( const EcdsaParameters& parameters, const EcPoint& public_point, absl::optional id_requirement, PartialKeyAccessToken token); const EcPoint& GetPublicPoint(PartialKeyAccessToken token) const { return public_point_; } absl::string_view GetOutputPrefix() const override { return output_prefix_; } const EcdsaParameters& GetParameters() const override { return parameters_; } absl::optional GetIdRequirement() const override { return id_requirement_; } bool operator==(const Key& other) const override; private: explicit EcdsaPublicKey(const EcdsaParameters& parameters, const EcPoint& public_point, absl::optional id_requirement, absl::string_view output_prefix) : parameters_(parameters), public_point_(public_point), id_requirement_(id_requirement), output_prefix_(output_prefix) {} EcdsaParameters parameters_; EcPoint public_point_; absl::optional id_requirement_; std::string output_prefix_; }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_ECDSA_PUBLIC_KEY_H_ ================================================ FILE: cc/signature/ecdsa_public_key_test.cc ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ecdsa_public_key.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/big_integer.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #endif #include "tink/ec_point.h" #include "tink/internal/ec_util.h" #include "tink/partial_key_access.h" #include "tink/signature/ecdsa_parameters.h" #include "tink/subtle/common_enums.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::TestWithParam; using ::testing::Values; // Test case for P-256 downloaded from NIST // https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/component-testing const EcPoint& kP256EcPoint = *new EcPoint( BigInteger(absl::HexStringToBytes( "700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287")), BigInteger(absl::HexStringToBytes( "db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac"))); struct TestCase { subtle::EllipticCurveType curve; EcdsaParameters::CurveType curve_type; EcdsaParameters::HashType hash_type; EcdsaParameters::SignatureEncoding signature_encoding; EcdsaParameters::Variant variant; absl::optional id_requirement; std::string output_prefix; }; using EcdsaPublicKeyTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( EcdsaPublicKeyTestSuite, EcdsaPublicKeyTest, Values(TestCase{subtle::EllipticCurveType::NIST_P256, EcdsaParameters::CurveType::kNistP256, EcdsaParameters::HashType::kSha256, EcdsaParameters::SignatureEncoding::kDer, EcdsaParameters::Variant::kTink, /*id_requirement=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{subtle::EllipticCurveType::NIST_P384, EcdsaParameters::CurveType::kNistP384, EcdsaParameters::HashType::kSha384, EcdsaParameters::SignatureEncoding::kDer, EcdsaParameters::Variant::kCrunchy, /*id_requirement=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{subtle::EllipticCurveType::NIST_P384, EcdsaParameters::CurveType::kNistP384, EcdsaParameters::HashType::kSha384, EcdsaParameters::SignatureEncoding::kIeeeP1363, EcdsaParameters::Variant::kLegacy, /*id_requirement=*/0x07080910, /*output_prefix=*/std::string("\x00\x07\x08\x09\x10", 5)}, TestCase{subtle::EllipticCurveType::NIST_P521, EcdsaParameters::CurveType::kNistP521, EcdsaParameters::HashType::kSha512, EcdsaParameters::SignatureEncoding::kIeeeP1363, EcdsaParameters::Variant::kNoPrefix, /*id_requirement=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(EcdsaPublicKeyTest, CreatePublicKeyWorks) { TestCase test_case = GetParam(); util::StatusOr parameters = EcdsaParameters::Builder() .SetCurveType(test_case.curve_type) .SetHashType(test_case.hash_type) .SetSignatureEncoding(test_case.signature_encoding) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr ec_key = internal::NewEcKey(test_case.curve); ASSERT_THAT(ec_key, IsOk()); EcPoint public_point(BigInteger(ec_key->pub_x), BigInteger(ec_key->pub_y)); util::StatusOr public_key = EcdsaPublicKey::Create(*parameters, public_point, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); EXPECT_THAT(public_key->GetParameters(), Eq(*parameters)); EXPECT_THAT(public_key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(public_key->GetOutputPrefix(), Eq(test_case.output_prefix)); EXPECT_THAT(public_key->GetPublicPoint(GetPartialKeyAccess()), Eq(public_point)); } TEST(EcdsaPublicKeyTest, CreatePublicKeyWithInvalidIdRequirementFails) { util::StatusOr no_prefix_params = EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(no_prefix_params, IsOk()); util::StatusOr tink_params = EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kTink) .Build(); ASSERT_THAT(tink_params, IsOk()); EXPECT_THAT( EcdsaPublicKey::Create(*no_prefix_params, kP256EcPoint, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("key with ID requirement with parameters without ID " "requirement"))); EXPECT_THAT(EcdsaPublicKey::Create(*tink_params, kP256EcPoint, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("key without ID requirement with parameters " "with ID requirement"))); } TEST(EcdsaPublicKeyTest, CreatePublicKeyWithInvalidPointFails) { // Creates an invalid EC point, by modifying the Y coordinate of kP256EcPoint. EcPoint invalid_point( BigInteger(absl::HexStringToBytes( "700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287")), BigInteger(absl::HexStringToBytes( "db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ad"))); util::StatusOr params = EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr public_key = EcdsaPublicKey::Create( *params, invalid_point, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); EXPECT_THAT(public_key.status(), StatusIs(absl::StatusCode::kInternal)); } TEST_P(EcdsaPublicKeyTest, PublicKeyEquals) { TestCase test_case = GetParam(); util::StatusOr parameters = EcdsaParameters::Builder() .SetCurveType(test_case.curve_type) .SetHashType(test_case.hash_type) .SetSignatureEncoding(test_case.signature_encoding) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr ec_key = internal::NewEcKey(test_case.curve); ASSERT_THAT(ec_key, IsOk()); EcPoint public_point(BigInteger(ec_key->pub_x), BigInteger(ec_key->pub_y)); util::StatusOr public_key = EcdsaPublicKey::Create(*parameters, public_point, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = EcdsaPublicKey::Create(*parameters, public_point, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key == *other_public_key); EXPECT_TRUE(*other_public_key == *public_key); EXPECT_FALSE(*public_key != *other_public_key); EXPECT_FALSE(*other_public_key != *public_key); } TEST(EcdsaPublicKeyTest, DifferentParametersNotEqual) { util::StatusOr crunchy_params = EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kCrunchy) .Build(); ASSERT_THAT(crunchy_params, IsOk()); util::StatusOr tink_params = EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kTink) .Build(); ASSERT_THAT(tink_params, IsOk()); util::StatusOr crunchy_public_key = EcdsaPublicKey::Create( *crunchy_params, kP256EcPoint, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(crunchy_public_key, IsOk()); util::StatusOr tink_public_key = EcdsaPublicKey::Create( *tink_params, kP256EcPoint, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(tink_public_key, IsOk()); EXPECT_TRUE(*tink_public_key != *crunchy_public_key); EXPECT_TRUE(*crunchy_public_key != *tink_public_key); EXPECT_FALSE(*tink_public_key == *crunchy_public_key); EXPECT_FALSE(*crunchy_public_key == *tink_public_key); } TEST(EcdsaPublicKeyTest, DifferentPublicPointsNotEqual) { util::StatusOr params = EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr ec_key1 = internal::NewEcKey(subtle::EllipticCurveType::NIST_P256); ASSERT_THAT(ec_key1, IsOk()); util::StatusOr ec_key2 = internal::NewEcKey(subtle::EllipticCurveType::NIST_P256); ASSERT_THAT(ec_key2, IsOk()); EcPoint public_point1(BigInteger(ec_key1->pub_x), BigInteger(ec_key1->pub_y)); EcPoint public_point2(BigInteger(ec_key2->pub_x), BigInteger(ec_key2->pub_y)); util::StatusOr public_key = EcdsaPublicKey::Create( *params, public_point1, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = EcdsaPublicKey::Create( *params, public_point2, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key != *other_public_key); EXPECT_TRUE(*other_public_key != *public_key); EXPECT_FALSE(*public_key == *other_public_key); EXPECT_FALSE(*other_public_key == *public_key); } TEST(EcdsaPublicKeyTest, DifferentIdRequirementsNotEqual) { util::StatusOr tink_params = EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kTink) .Build(); ASSERT_THAT(tink_params, IsOk()); util::StatusOr public_key = EcdsaPublicKey::Create( *tink_params, kP256EcPoint, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = EcdsaPublicKey::Create( *tink_params, kP256EcPoint, /*id_requirement=*/0x02030405, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key != *other_public_key); EXPECT_TRUE(*other_public_key != *public_key); EXPECT_FALSE(*public_key == *other_public_key); EXPECT_FALSE(*other_public_key == *public_key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ecdsa_sign_key_manager.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ecdsa_sign_key_manager.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/config/tink_fips.h" #include "tink/input_stream.h" #include "tink/internal/ec_util.h" #include "tink/public_key_sign.h" #include "tink/signature/ecdsa_verify_key_manager.h" #include "tink/subtle/ecdsa_sign_boringssl.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/input_stream_util.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/ecdsa.pb.h" namespace crypto { namespace tink { using crypto::tink::util::Enums; using crypto::tink::util::Status; using crypto::tink::util::StatusOr; using google::crypto::tink::EcdsaKeyFormat; using google::crypto::tink::EcdsaPrivateKey; using google::crypto::tink::EcdsaPublicKey; StatusOr EcdsaSignKeyManager::CreateKey( const EcdsaKeyFormat& ecdsa_key_format) const { // Generate new EC key. auto ec_key_result = internal::NewEcKey( util::Enums::ProtoToSubtle(ecdsa_key_format.params().curve())); if (!ec_key_result.ok()) return ec_key_result.status(); auto ec_key = ec_key_result.value(); // Build EcdsaPrivateKey. EcdsaPrivateKey ecdsa_private_key; ecdsa_private_key.set_version(get_version()); ecdsa_private_key.set_key_value( std::string(util::SecretDataAsStringView(ec_key.priv))); auto ecdsa_public_key = ecdsa_private_key.mutable_public_key(); ecdsa_public_key->set_version(get_version()); ecdsa_public_key->set_x(ec_key.pub_x); ecdsa_public_key->set_y(ec_key.pub_y); *(ecdsa_public_key->mutable_params()) = ecdsa_key_format.params(); return ecdsa_private_key; } StatusOr EcdsaSignKeyManager::DeriveKey( const EcdsaKeyFormat& ecdsa_key_format, InputStream* input_stream) const { if (IsFipsModeEnabled()) { return crypto::tink::util::Status( absl::StatusCode::kInternal, "Deriving EC keys is not allowed in FIPS mode."); } util::Status status = ValidateVersion(ecdsa_key_format.version(), get_version()); if (!status.ok()) { return status; } // Extract enough random bytes from the input_stream to match the security // level of the EC. Note that the input_stream here must come from a PRF // and will not use more bytes than required by the security level of the EC. // Providing an input_stream which has more bytes available than required, // will result in the same keys being generated. int random_bytes_used = 0; switch (ecdsa_key_format.params().curve()) { case google::crypto::tink::EllipticCurveType::NIST_P256: random_bytes_used = 16; break; case google::crypto::tink::EllipticCurveType::NIST_P384: random_bytes_used = 24; break; case google::crypto::tink::EllipticCurveType::NIST_P521: random_bytes_used = 32; break; default: return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, "Curve does not support key derivation."); } crypto::tink::util::StatusOr randomness = ReadSecretBytesFromStream(random_bytes_used, input_stream); if (!randomness.ok()) { if (randomness.status().code() == absl::StatusCode::kOutOfRange) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, "Could not get enough pseudorandomness from input stream"); } return randomness.status(); } // Generate new EC key from the seed. crypto::tink::util::StatusOr ec_key = internal::NewEcKey( util::Enums::ProtoToSubtle(ecdsa_key_format.params().curve()), *randomness); if (!ec_key.ok()) { return ec_key.status(); } // Build EcdsaPrivateKey. EcdsaPrivateKey ecdsa_private_key; ecdsa_private_key.set_version(get_version()); ecdsa_private_key.set_key_value( std::string(util::SecretDataAsStringView(ec_key->priv))); EcdsaPublicKey* ecdsa_public_key = ecdsa_private_key.mutable_public_key(); ecdsa_public_key->set_version(get_version()); ecdsa_public_key->set_x(ec_key->pub_x); ecdsa_public_key->set_y(ec_key->pub_y); *(ecdsa_public_key->mutable_params()) = ecdsa_key_format.params(); return ecdsa_private_key; } StatusOr> EcdsaSignKeyManager::PublicKeySignFactory::Create( const EcdsaPrivateKey& ecdsa_private_key) const { const EcdsaPublicKey& public_key = ecdsa_private_key.public_key(); internal::EcKey ec_key; ec_key.curve = Enums::ProtoToSubtle(public_key.params().curve()); ec_key.pub_x = public_key.x(); ec_key.pub_y = public_key.y(); ec_key.priv = util::SecretDataFromStringView(ecdsa_private_key.key_value()); auto result = subtle::EcdsaSignBoringSsl::New( ec_key, Enums::ProtoToSubtle(public_key.params().hash_type()), Enums::ProtoToSubtle(public_key.params().encoding())); if (!result.ok()) return result.status(); return {std::move(result.value())}; } Status EcdsaSignKeyManager::ValidateKey(const EcdsaPrivateKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; return EcdsaVerifyKeyManager().ValidateKey(key.public_key()); } Status EcdsaSignKeyManager::ValidateKeyFormat( const EcdsaKeyFormat& key_format) const { if (!key_format.has_params()) { return Status(absl::StatusCode::kInvalidArgument, "Missing params."); } return EcdsaVerifyKeyManager().ValidateParams(key_format.params()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ecdsa_sign_key_manager.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_ECDSA_SIGN_KEY_MANAGER_H_ #define TINK_SIGNATURE_ECDSA_SIGN_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/input_stream.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_sign.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/ecdsa.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class EcdsaSignKeyManager : public PrivateKeyTypeManager> { public: class PublicKeySignFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::EcdsaPrivateKey& private_key) const override; }; EcdsaSignKeyManager() : PrivateKeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::EcdsaPrivateKey& key) const override; crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::EcdsaKeyFormat& key_format) const override; crypto::tink::util::StatusOr CreateKey( const google::crypto::tink::EcdsaKeyFormat& key_format) const override; crypto::tink::util::StatusOr DeriveKey( const google::crypto::tink::EcdsaKeyFormat& key_format, InputStream* input_stream) const override; crypto::tink::util::StatusOr GetPublicKey( const google::crypto::tink::EcdsaPrivateKey& private_key) const override { return private_key.public_key(); } internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: const std::string key_type_ = absl::StrCat(kTypeGoogleapisCom, google::crypto::tink::EcdsaPrivateKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_ECDSA_SIGN_KEY_MANAGER_H_ ================================================ FILE: cc/signature/ecdsa_sign_key_manager_test.cc ================================================ // Copyright 2017 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ecdsa_sign_key_manager.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/internal/ec_util.h" #include "tink/internal/ssl_util.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/signature/ecdsa_verify_key_manager.h" #include "tink/subtle/ecdsa_verify_boringssl.h" #include "tink/util/enums.h" #include "tink/util/istream_input_stream.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/ecdsa.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::Enums; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::EcdsaKeyFormat; using ::google::crypto::tink::EcdsaParams; using ::google::crypto::tink::EcdsaPrivateKey; using ::google::crypto::tink::EcdsaPublicKey; using ::google::crypto::tink::EcdsaSignatureEncoding; using ::google::crypto::tink::EllipticCurveType; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::testing::Eq; using ::testing::Gt; using ::testing::Not; using ::testing::SizeIs; namespace { TEST(EcdsaSignKeyManagerTest, Basic) { EXPECT_THAT(EcdsaSignKeyManager().get_version(), Eq(0)); EXPECT_THAT(EcdsaSignKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PRIVATE)); EXPECT_THAT(EcdsaSignKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.EcdsaPrivateKey")); } TEST(EcdsaSignKeyManagerTest, ValidateEmptyKeyFormat) { EXPECT_THAT(EcdsaSignKeyManager().ValidateKeyFormat(EcdsaKeyFormat()), Not(IsOk())); } EcdsaKeyFormat CreateValidKeyFormat() { EcdsaKeyFormat key_format; EcdsaParams* params = key_format.mutable_params(); params->set_hash_type(HashType::SHA256); params->set_curve(EllipticCurveType::NIST_P256); params->set_encoding(EcdsaSignatureEncoding::DER); return key_format; } TEST(EcdsaSignKeyManagerTest, ValidateKeyFormat) { EcdsaKeyFormat format = CreateValidKeyFormat(); EXPECT_THAT(EcdsaSignKeyManager().ValidateKeyFormat(format), IsOk()); } TEST(EcdsaSignKeyManagerTest, ValidateKeyFormatUnknownCurve) { EcdsaKeyFormat format = CreateValidKeyFormat(); EcdsaParams* params = format.mutable_params(); params->set_curve(EllipticCurveType::UNKNOWN_CURVE); EXPECT_THAT(EcdsaSignKeyManager().ValidateKeyFormat(format), Not(IsOk())); } TEST(EcdsaSignKeyManagerTest, ValidateKeyFormatBadHashP256) { EcdsaKeyFormat format = CreateValidKeyFormat(); EcdsaParams* params = format.mutable_params(); params->set_curve(EllipticCurveType::NIST_P256); params->set_hash_type(HashType::SHA512); EXPECT_THAT(EcdsaSignKeyManager().ValidateKeyFormat(format), Not(IsOk())); EXPECT_THAT(EcdsaSignKeyManager().ValidateKeyFormat(format), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EcdsaSignKeyManagerTest, ValidateKeyFormatBadHashP384) { EcdsaKeyFormat format = CreateValidKeyFormat(); EcdsaParams* params = format.mutable_params(); params->set_curve(EllipticCurveType::NIST_P384); params->set_hash_type(HashType::SHA256); EXPECT_THAT(EcdsaSignKeyManager().ValidateKeyFormat(format), Not(IsOk())); EXPECT_THAT(EcdsaSignKeyManager().ValidateKeyFormat(format), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EcdsaSignKeyManagerTest, ValidateKeyFormatBadHashP521) { EcdsaKeyFormat format = CreateValidKeyFormat(); EcdsaParams* params = format.mutable_params(); params->set_curve(EllipticCurveType::NIST_P521); params->set_hash_type(HashType::SHA256); EXPECT_THAT(EcdsaSignKeyManager().ValidateKeyFormat(format), Not(IsOk())); EXPECT_THAT(EcdsaSignKeyManager().ValidateKeyFormat(format), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EcdsaSignKeyManagerTest, CreateKey) { EcdsaKeyFormat format = CreateValidKeyFormat(); StatusOr key_or = EcdsaSignKeyManager().CreateKey(format); ASSERT_THAT(key_or, IsOk()); EcdsaPrivateKey key = key_or.value(); EXPECT_THAT(key.version(), Eq(0)); EXPECT_THAT(key.public_key().version(), Eq(key.version())); EXPECT_THAT(key.public_key().params().hash_type(), Eq(format.params().hash_type())); EXPECT_THAT(key.public_key().params().curve(), Eq(format.params().curve())); EXPECT_THAT(key.public_key().params().encoding(), Eq(format.params().encoding())); EXPECT_THAT(key.public_key().x(), SizeIs(Gt(0))); EXPECT_THAT(key.public_key().y(), SizeIs(Gt(0))); EXPECT_THAT(key.key_value(), SizeIs(Gt(0))); } TEST(EcdsaSignKeyManagerTest, CreateKeyValid) { EcdsaKeyFormat format = CreateValidKeyFormat(); StatusOr key_or = EcdsaSignKeyManager().CreateKey(format); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(EcdsaSignKeyManager().ValidateKey(key_or.value()), IsOk()); } EcdsaPrivateKey CreateValidKey() { EcdsaKeyFormat format = CreateValidKeyFormat(); return EcdsaSignKeyManager().CreateKey(format).value(); } TEST(EcdsaSignKeyManagerTest, ValidateKey) { EcdsaPrivateKey key = CreateValidKey(); EXPECT_THAT(EcdsaSignKeyManager().ValidateKey(key), IsOk()); } TEST(EcdsaSignKeyManagerTest, ValidateKeyBadHashP256) { EcdsaPrivateKey key = CreateValidKey(); EcdsaParams* params = key.mutable_public_key()->mutable_params(); params->set_curve(EllipticCurveType::NIST_P256); params->set_hash_type(HashType::SHA512); EXPECT_THAT(EcdsaSignKeyManager().ValidateKey(key), Not(IsOk())); EXPECT_THAT(EcdsaSignKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EcdsaSignKeyManagerTest, ValidateKeyBadHashP384) { EcdsaPrivateKey key = CreateValidKey(); EcdsaParams* params = key.mutable_public_key()->mutable_params(); params->set_curve(EllipticCurveType::NIST_P384); params->set_hash_type(HashType::SHA256); EXPECT_THAT(EcdsaSignKeyManager().ValidateKey(key), Not(IsOk())); EXPECT_THAT(EcdsaSignKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EcdsaSignKeyManagerTest, ValidateKeyBadHashP521) { EcdsaPrivateKey key = CreateValidKey(); EcdsaParams* params = key.mutable_public_key()->mutable_params(); params->set_curve(EllipticCurveType::NIST_P521); params->set_hash_type(HashType::SHA256); EXPECT_THAT(EcdsaSignKeyManager().ValidateKey(key), Not(IsOk())); EXPECT_THAT(EcdsaSignKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EcdsaSignKeyManagerTest, GetPublicKey) { EcdsaPrivateKey key = CreateValidKey(); StatusOr public_key_or = EcdsaSignKeyManager().GetPublicKey(key); ASSERT_THAT(public_key_or, IsOk()); EcdsaPublicKey public_key = public_key_or.value(); EXPECT_THAT(public_key.version(), Eq(key.public_key().version())); EXPECT_THAT(public_key.params().hash_type(), Eq(key.public_key().params().hash_type())); EXPECT_THAT(public_key.params().curve(), Eq(key.public_key().params().curve())); EXPECT_THAT(public_key.params().encoding(), Eq(key.public_key().params().encoding())); EXPECT_THAT(public_key.x(), Eq(key.public_key().x())); EXPECT_THAT(public_key.y(), Eq(key.public_key().y())); } TEST(EcdsaSignKeyManagerTest, Create) { EcdsaPrivateKey private_key = CreateValidKey(); EcdsaPublicKey public_key = EcdsaSignKeyManager().GetPublicKey(private_key).value(); auto signer_or = EcdsaSignKeyManager().GetPrimitive(private_key); ASSERT_THAT(signer_or, IsOk()); internal::EcKey ec_key; ec_key.curve = Enums::ProtoToSubtle(public_key.params().curve()); ec_key.pub_x = public_key.x(); ec_key.pub_y = public_key.y(); auto direct_verifier_or = subtle::EcdsaVerifyBoringSsl::New( ec_key, Enums::ProtoToSubtle(public_key.params().hash_type()), Enums::ProtoToSubtle(public_key.params().encoding())); ASSERT_THAT(direct_verifier_or, IsOk()); std::string message = "Some message"; EXPECT_THAT(direct_verifier_or.value()->Verify( signer_or.value()->Sign(message).value(), message), IsOk()); } TEST(EcdsaSignKeyManagerTest, CreateDifferentKey) { EcdsaPrivateKey private_key = CreateValidKey(); // Note: we create a new key in the next line. EcdsaPublicKey public_key = EcdsaSignKeyManager().GetPublicKey(CreateValidKey()).value(); auto signer_or = EcdsaSignKeyManager().GetPrimitive(private_key); ASSERT_THAT(signer_or, IsOk()); internal::EcKey ec_key; ec_key.curve = Enums::ProtoToSubtle(public_key.params().curve()); ec_key.pub_x = public_key.x(); ec_key.pub_y = public_key.y(); auto direct_verifier_or = subtle::EcdsaVerifyBoringSsl::New( ec_key, Enums::ProtoToSubtle(public_key.params().hash_type()), Enums::ProtoToSubtle(public_key.params().encoding())); ASSERT_THAT(direct_verifier_or, IsOk()); std::string message = "Some message"; EXPECT_THAT(direct_verifier_or.value()->Verify( signer_or.value()->Sign(message).value(), message), Not(IsOk())); } TEST(EcdsaSignKeyManagerTest, DeriveKeyFailsWithOpenSsl) { if (internal::IsBoringSsl()) { GTEST_SKIP() << "OpenSSL-only test, skipping because Tink is using BoringSSL"; } EcdsaKeyFormat format = CreateValidKeyFormat(); util::IstreamInputStream input_stream{ absl::make_unique("0123456789abcdef0123456789abcdef")}; EXPECT_THAT(EcdsaSignKeyManager().DeriveKey(format, &input_stream).status(), Not(IsOk())); } TEST(EcdsaSignKeyManagerTest, DeriveKeySignVerifySucceedsWithBoringSsl) { if (!internal::IsBoringSsl()) { GTEST_SKIP() << "Key derivation from an input stream is not supported with OpenSSL"; } EcdsaKeyFormat format = CreateValidKeyFormat(); util::IstreamInputStream input_stream{ absl::make_unique("0123456789abcdef0123456789abcdef")}; util::StatusOr key = EcdsaSignKeyManager().DeriveKey(format, &input_stream); ASSERT_THAT(key, IsOk()); util::StatusOr> signer = EcdsaSignKeyManager().GetPrimitive(*key); ASSERT_THAT(signer, IsOk()); constexpr absl::string_view kMessage = "Some message"; util::StatusOr signature = (*signer)->Sign(kMessage); ASSERT_THAT(signature, IsOk()); util::StatusOr> verifier = EcdsaVerifyKeyManager().GetPrimitive(key->public_key()); ASSERT_THAT(verifier, IsOk()); EXPECT_THAT((*verifier)->Verify(*signature, kMessage), IsOk()); } TEST(EcdsaSignKeyManagerTest, DeriveKeyNotEnoughRandomness) { if (!internal::IsBoringSsl()) { GTEST_SKIP() << "Key derivation from an input stream is not supported with OpenSSL"; } EcdsaKeyFormat format = CreateValidKeyFormat(); util::IstreamInputStream input_stream{ absl::make_unique("tooshort")}; ASSERT_THAT(EcdsaSignKeyManager().DeriveKey(format, &input_stream).status(), test::StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EcdsaSignKeyManagerTest, DeriveKeyWithInvalidKeyTemplateVersionFails) { if (!internal::IsBoringSsl()) { GTEST_SKIP() << "Key derivation from an input stream is not supported with OpenSSL"; } EcdsaKeyFormat format; format.set_version(1); EcdsaParams* params = format.mutable_params(); params->set_hash_type(HashType::SHA256); params->set_curve(EllipticCurveType::NIST_P256); params->set_encoding(EcdsaSignatureEncoding::DER); util::IstreamInputStream input_stream{ absl::make_unique("tooshort")}; ASSERT_THAT(EcdsaSignKeyManager().DeriveKey(format, &input_stream).status(), test::StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EcdsaSignKeyManagerTest, DeriveKeyInvalidCurve) { if (!internal::IsBoringSsl()) { GTEST_SKIP() << "Key derivation from an input stream is not supported with OpenSSL"; } EcdsaKeyFormat format = CreateValidKeyFormat(); EcdsaParams* params = format.mutable_params(); params->set_curve(EllipticCurveType::CURVE25519); util::IstreamInputStream input_stream{ absl::make_unique("0123456789abcdef0123456789abcdef")}; ASSERT_THAT(EcdsaSignKeyManager().DeriveKey(format, &input_stream).status(), test::StatusIs(absl::StatusCode::kInvalidArgument)); } // Test vectors have been manually generated based on BoringSSL // Date: 2021/06/03 commit: 88df13d73d5a74505f046f0bf37fb2fb3e1f1a58 using NistCurveParamsDeriveTest = ::testing::TestWithParam< std::tuple>; INSTANTIATE_TEST_SUITE_P( NistCurvesParams, NistCurveParamsDeriveTest, ::testing::Values( std::make_tuple( EllipticCurveType::NIST_P256, "0123456789abcdef0123456789abcdef", "ed615ab1a0a8bc0412a02f097e747f33c61c5d1f0c720f3e232213ce4a4b7c38"), std::make_tuple( EllipticCurveType::NIST_P256, "0000000000000000", "19d85dacc6634391175a26a692af2230a1de00860bda799d90e2df6ed8e1e5c6"), std::make_tuple( EllipticCurveType::NIST_P256, "4242424242424242", "055d555a117782553a01a93544ffeced88bc08a50a22138b54c422c4a8cfb3ec"), std::make_tuple(EllipticCurveType::NIST_P384, "0123456789abcdef0123456789abcdef", "4c2204d997b64a288ce7c8dbcb9d9543f45c7de458410cd996f28a" "d123e45a146367c2d2100a4336bad949535d1d9e89"), std::make_tuple(EllipticCurveType::NIST_P384, "000000000000000000000000", "88d0af7371ae92b3aa2daea3d68d514a5c335ac6c6e5af2a7cf60a" "f71364241d318c022f7846b261c6345bc0c810d816"), std::make_tuple(EllipticCurveType::NIST_P384, "424242424242424242424242", "53cfa0a8205c69cd56173a76a99caf19b15bd56ce9a08c6d26067e" "b6b48925bd445cdf213e35b69330e47535ff8f27ad"), std::make_tuple(EllipticCurveType::NIST_P521, "0123456789abcdef0123456789abcdef", "014ef526b2a9e965227e83396387a34a441d471f5ab3fe62607e78" "e56619a698ad73bba12e42459e457c08dfa8492daaf8188f72f707" "6b8bc902d4c68729a3330b8f"), std::make_tuple(EllipticCurveType::NIST_P521, "00000000000000000000000000000000", "01effa21f65dda9fe6eacd5d4a1865a4117db0ac5617cdaaaae1cf" "f17b261a5fd1804e75e49d8cca288bd3f0a7b77d39bb230c9c5192" "c70e1af9f93403e3705a49d6"), std::make_tuple(EllipticCurveType::NIST_P521, "42424242424242424242424242424242", "013fa619e3ea1f71f923b6716619d0044d168637d36e44b828901e" "cef00f6fabcffbd6b5c2c24468a35fed8611aaeeb36b2af7be1eff" "d393151c6b5135a07789f8a4"))); TEST_P(NistCurveParamsDeriveTest, TestVectors) { if (!internal::IsBoringSsl()) { GTEST_SKIP() << "Key derivation from an input stream is not supported with OpenSSL"; } EcdsaKeyFormat key_format; key_format.mutable_params()->set_curve(std::get<0>(GetParam())); util::IstreamInputStream input_stream{ absl::make_unique(std::get<1>(GetParam()))}; util::StatusOr private_key = EcdsaSignKeyManager().DeriveKey(key_format, &input_stream); ASSERT_THAT(private_key, IsOk()); EXPECT_THAT(private_key->key_value(), Eq(test::HexDecodeOrDie(std::get<2>(GetParam())))); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ecdsa_verify_key_manager.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ecdsa_verify_key_manager.h" #include #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/internal/ec_util.h" #include "tink/public_key_verify.h" #include "tink/subtle/ecdsa_verify_boringssl.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/ecdsa.pb.h" namespace crypto { namespace tink { using crypto::tink::util::Enums; using crypto::tink::util::Status; using crypto::tink::util::StatusOr; using google::crypto::tink::EcdsaParams; using google::crypto::tink::EcdsaPublicKey; using google::crypto::tink::EcdsaSignatureEncoding; using google::crypto::tink::EllipticCurveType; using google::crypto::tink::HashType; StatusOr> EcdsaVerifyKeyManager::PublicKeyVerifyFactory::Create( const EcdsaPublicKey& ecdsa_public_key) const { internal::EcKey ec_key; ec_key.curve = Enums::ProtoToSubtle(ecdsa_public_key.params().curve()); ec_key.pub_x = ecdsa_public_key.x(); ec_key.pub_y = ecdsa_public_key.y(); auto result = subtle::EcdsaVerifyBoringSsl::New( ec_key, Enums::ProtoToSubtle(ecdsa_public_key.params().hash_type()), Enums::ProtoToSubtle(ecdsa_public_key.params().encoding())); if (!result.ok()) return result.status(); return {std::move(result.value())}; } Status EcdsaVerifyKeyManager::ValidateParams(const EcdsaParams& params) const { switch (params.encoding()) { case EcdsaSignatureEncoding::DER: // fall through case EcdsaSignatureEncoding::IEEE_P1363: break; default: return ToStatusF(absl::StatusCode::kInvalidArgument, "Unsupported signature encoding: %d", params.encoding()); } switch (params.curve()) { case EllipticCurveType::NIST_P256: // Using SHA512 for curve P256 is fine. However, only the 256 // leftmost bits of the hash is used in signature computation. // Therefore, we don't allow it here to prevent security illusion. if (params.hash_type() != HashType::SHA256) { return Status(absl::StatusCode::kInvalidArgument, "Only SHA256 is supported for NIST P256."); } break; case EllipticCurveType::NIST_P384: // Allow using SHA384 and SHA512 with NIST-P384. if ((params.hash_type() != HashType::SHA384) && (params.hash_type() != HashType::SHA512)) { return Status(absl::StatusCode::kInvalidArgument, "Only SHA384 and SHA512 are supported for this curve."); } break; case EllipticCurveType::NIST_P521: if (params.hash_type() != HashType::SHA512) { return Status(absl::StatusCode::kInvalidArgument, "Only SHA512 is supported for this curve."); } break; default: return Status(absl::StatusCode::kInvalidArgument, "Unsupported elliptic curve"); } return util::OkStatus(); } Status EcdsaVerifyKeyManager::ValidateKey(const EcdsaPublicKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; return ValidateParams(key.params()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ecdsa_verify_key_manager.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_ECDSA_VERIFY_KEY_MANAGER_H_ #define TINK_SIGNATURE_ECDSA_VERIFY_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_verify.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/ecdsa.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class EcdsaVerifyKeyManager : public KeyTypeManager> { public: class PublicKeyVerifyFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::EcdsaPublicKey& ecdsa_public_key) const override; }; EcdsaVerifyKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PUBLIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::EcdsaPublicKey& key) const override; crypto::tink::util::Status ValidateParams( const google::crypto::tink::EcdsaParams& params) const; internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: const std::string key_type_ = absl::StrCat( kTypeGoogleapisCom, google::crypto::tink::EcdsaPublicKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_ECDSA_VERIFY_KEY_MANAGER_H_ ================================================ FILE: cc/signature/ecdsa_verify_key_manager_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ecdsa_verify_key_manager.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/internal/ec_util.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/signature/ecdsa_sign_key_manager.h" #include "tink/subtle/ecdsa_sign_boringssl.h" #include "tink/util/enums.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/ecdsa.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::Enums; using ::google::crypto::tink::EcdsaKeyFormat; using ::google::crypto::tink::EcdsaParams; using ::google::crypto::tink::EcdsaPrivateKey; using ::google::crypto::tink::EcdsaPublicKey; using ::google::crypto::tink::EcdsaSignatureEncoding; using ::google::crypto::tink::EllipticCurveType; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::testing::Eq; using ::testing::Not; namespace { TEST(EcdsaVerifyKeyManagerTest, Basics) { EXPECT_THAT(EcdsaVerifyKeyManager().get_version(), Eq(0)); EXPECT_THAT(EcdsaVerifyKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PUBLIC)); EXPECT_THAT(EcdsaVerifyKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.EcdsaPublicKey")); } TEST(EcdsaVerifyKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(EcdsaVerifyKeyManager().ValidateKey(EcdsaPublicKey()), Not(IsOk())); } EcdsaPrivateKey CreateValidPrivateKey() { EcdsaKeyFormat key_format; EcdsaParams* params = key_format.mutable_params(); params->set_hash_type(HashType::SHA256); params->set_curve(EllipticCurveType::NIST_P256); params->set_encoding(EcdsaSignatureEncoding::DER); return EcdsaSignKeyManager().CreateKey(key_format).value(); } EcdsaPublicKey CreateValidPublicKey() { return EcdsaSignKeyManager().GetPublicKey(CreateValidPrivateKey()).value(); } // Checks that a public key generaed by the SignKeyManager is considered valid. TEST(EcdsaVerifyKeyManagerTest, PublicKeyValid) { EcdsaPublicKey key = CreateValidPublicKey(); EXPECT_THAT(EcdsaVerifyKeyManager().ValidateKey(key), IsOk()); } TEST(EcdsaSignKeyManagerTest, ValidateKeyBadHashP256) { EcdsaPublicKey key = CreateValidPublicKey(); EcdsaParams* params = key.mutable_params(); params->set_curve(EllipticCurveType::NIST_P256); params->set_hash_type(HashType::SHA512); EXPECT_THAT(EcdsaVerifyKeyManager().ValidateKey(key), Not(IsOk())); EXPECT_THAT(EcdsaVerifyKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EcdsaSignKeyManagerTest, ValidateKeyBadHashP384) { EcdsaPublicKey key = CreateValidPublicKey(); EcdsaParams* params = key.mutable_params(); params->set_curve(EllipticCurveType::NIST_P384); params->set_hash_type(HashType::SHA256); EXPECT_THAT(EcdsaVerifyKeyManager().ValidateKey(key), Not(IsOk())); EXPECT_THAT(EcdsaVerifyKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EcdsaSignKeyManagerTest, ValidateKeyBadHashP521) { EcdsaPublicKey key = CreateValidPublicKey(); EcdsaParams* params = key.mutable_params(); params->set_curve(EllipticCurveType::NIST_P521); params->set_hash_type(HashType::SHA256); EXPECT_THAT(EcdsaVerifyKeyManager().ValidateKey(key), Not(IsOk())); EXPECT_THAT(EcdsaVerifyKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EcdsaSignKeyManagerTest, ValidateParams) { EcdsaParams params; params.set_hash_type(HashType::SHA256); params.set_curve(EllipticCurveType::NIST_P256); params.set_encoding(EcdsaSignatureEncoding::DER); EXPECT_THAT(EcdsaVerifyKeyManager().ValidateParams(params), IsOk()); } TEST(EcdsaSignKeyManagerTest, ValidateParamsHashP384) { EcdsaParams params; params.set_hash_type(HashType::SHA384); params.set_curve(EllipticCurveType::NIST_P384); params.set_encoding(EcdsaSignatureEncoding::DER); EXPECT_THAT(EcdsaVerifyKeyManager().ValidateParams(params), IsOk()); } TEST(EcdsaSignKeyManagerTest, ValidateParamsBadHashP256) { EcdsaParams params; params.set_hash_type(HashType::SHA512); params.set_curve(EllipticCurveType::NIST_P256); params.set_encoding(EcdsaSignatureEncoding::DER); EXPECT_THAT(EcdsaVerifyKeyManager().ValidateParams(params), Not(IsOk())); EXPECT_THAT(EcdsaVerifyKeyManager().ValidateParams(params), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EcdsaSignKeyManagerTest, ValidateParamsBadHashP384) { EcdsaParams params; params.set_curve(EllipticCurveType::NIST_P384); params.set_hash_type(HashType::SHA256); params.set_encoding(EcdsaSignatureEncoding::DER); EXPECT_THAT(EcdsaVerifyKeyManager().ValidateParams(params), Not(IsOk())); EXPECT_THAT(EcdsaVerifyKeyManager().ValidateParams(params), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EcdsaSignKeyManagerTest, ValidateParamsBadHashP521) { EcdsaParams params; params.set_curve(EllipticCurveType::NIST_P521); params.set_hash_type(HashType::SHA256); params.set_encoding(EcdsaSignatureEncoding::DER); EXPECT_THAT(EcdsaVerifyKeyManager().ValidateParams(params), Not(IsOk())); EXPECT_THAT(EcdsaVerifyKeyManager().ValidateParams(params), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(EcdsaSignKeyManagerTest, Create) { EcdsaPrivateKey private_key = CreateValidPrivateKey(); EcdsaPublicKey public_key = EcdsaSignKeyManager().GetPublicKey(private_key).value(); internal::EcKey ec_key; ec_key.curve = Enums::ProtoToSubtle(public_key.params().curve()); ec_key.pub_x = public_key.x(); ec_key.pub_y = public_key.y(); ec_key.priv = util::SecretDataFromStringView(private_key.key_value()); auto direct_signer_or = subtle::EcdsaSignBoringSsl::New( ec_key, Enums::ProtoToSubtle(public_key.params().hash_type()), Enums::ProtoToSubtle(public_key.params().encoding())); ASSERT_THAT(direct_signer_or, IsOk()); auto verifier_or = EcdsaVerifyKeyManager().GetPrimitive(public_key); ASSERT_THAT(verifier_or, IsOk()); std::string message = "Some message"; EXPECT_THAT(verifier_or.value()->Verify( direct_signer_or.value()->Sign(message).value(), message), IsOk()); } TEST(EcdsaSignKeyManagerTest, CreateDifferentPrivateKey) { EcdsaPrivateKey private_key = CreateValidPrivateKey(); // Note: we create a new key in the next line. EcdsaPublicKey public_key = EcdsaSignKeyManager().GetPublicKey(CreateValidPrivateKey()).value(); internal::EcKey ec_key; ec_key.curve = Enums::ProtoToSubtle(public_key.params().curve()); ec_key.pub_x = public_key.x(); ec_key.pub_y = public_key.y(); ec_key.priv = util::SecretDataFromStringView(private_key.key_value()); auto direct_signer_or = subtle::EcdsaSignBoringSsl::New( ec_key, Enums::ProtoToSubtle(public_key.params().hash_type()), Enums::ProtoToSubtle(public_key.params().encoding())); ASSERT_THAT(direct_signer_or, IsOk()); auto verifier_or = EcdsaVerifyKeyManager().GetPrimitive(public_key); ASSERT_THAT(verifier_or, IsOk()); std::string message = "Some message"; EXPECT_THAT(verifier_or.value()->Verify( direct_signer_or.value()->Sign(message).value(), message), Not(IsOk())); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ed25519_parameters.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ed25519_parameters.h" #include #include "absl/status/status.h" #include "tink/parameters.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { util::StatusOr Ed25519Parameters::Create(Variant variant) { static const std::set* supported_variants = new std::set({Variant::kTink, Variant::kCrunchy, Variant::kLegacy, Variant::kNoPrefix}); if (supported_variants->find(variant) == supported_variants->end()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create Ed25519 parameters with unknown variant."); } return Ed25519Parameters(variant); } bool Ed25519Parameters::operator==(const Parameters& other) const { const Ed25519Parameters* that = dynamic_cast(&other); if (that == nullptr) { return false; } return variant_ == that->variant_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ed25519_parameters.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_ED25519_PARAMETERS_H_ #define TINK_SIGNATURE_ED25519_PARAMETERS_H_ #include "tink/parameters.h" #include "tink/signature/signature_parameters.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { class Ed25519Parameters : public SignatureParameters { public: // Description of the output prefix prepended to the signature. enum class Variant : int { // Prepends '0x01' to signature. kTink = 1, // Prepends '0x00' to signature. kCrunchy = 2, // Appends a 0-byte to input message BEFORE computing the signature, then // prepends '0x00' to signature. kLegacy = 3, // Does not prepend any prefix (i.e., keys must have no ID requirement). kNoPrefix = 4, // Added to guard from failures that may be caused by future expansions. kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Copyable and movable. Ed25519Parameters(const Ed25519Parameters& other) = default; Ed25519Parameters& operator=(const Ed25519Parameters& other) = default; Ed25519Parameters(Ed25519Parameters&& other) = default; Ed25519Parameters& operator=(Ed25519Parameters&& other) = default; // Creates a new Ed25519 parameters object unless `variant` is invalid. static util::StatusOr Create(Variant variant); Variant GetVariant() const { return variant_; } bool HasIdRequirement() const override { return variant_ != Variant::kNoPrefix; } bool operator==(const Parameters& other) const override; private: explicit Ed25519Parameters(Variant variant) : variant_(variant) {} Variant variant_; }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_ED25519_PARAMETERS_H_ ================================================ FILE: cc/signature/ed25519_parameters_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ed25519_parameters.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::IsTrue; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { Ed25519Parameters::Variant variant; bool has_id_requirement; }; using Ed25519ParametersTest = TestWithParam; INSTANTIATE_TEST_SUITE_P(Ed25519ParametersTestSuite, Ed25519ParametersTest, Values(TestCase{Ed25519Parameters::Variant::kTink, /*has_id_requirement=*/true}, TestCase{Ed25519Parameters::Variant::kCrunchy, /*has_id_requirement=*/true}, TestCase{Ed25519Parameters::Variant::kLegacy, /*has_id_requirement=*/true}, TestCase{Ed25519Parameters::Variant::kNoPrefix, /*has_id_requirement=*/false})); TEST_P(Ed25519ParametersTest, Create) { TestCase test_case = GetParam(); util::StatusOr parameters = Ed25519Parameters::Create(test_case.variant); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(parameters->HasIdRequirement(), Eq(test_case.has_id_requirement)); } TEST(Ed25519ParametersTest, CreateWithInvalidVariantFails) { EXPECT_THAT(Ed25519Parameters::Create( Ed25519Parameters::Variant:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(Ed25519ParametersTest, CopyConstructor) { util::StatusOr parameters = Ed25519Parameters::Create(Ed25519Parameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); Ed25519Parameters copy(*parameters); EXPECT_THAT(copy.GetVariant(), Eq(Ed25519Parameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); } TEST(Ed25519ParametersTest, CopyAssignment) { util::StatusOr parameters = Ed25519Parameters::Create(Ed25519Parameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); Ed25519Parameters copy = *parameters; EXPECT_THAT(copy.GetVariant(), Eq(Ed25519Parameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); } TEST_P(Ed25519ParametersTest, ParametersEquals) { TestCase test_case = GetParam(); util::StatusOr parameters = Ed25519Parameters::Create(test_case.variant); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = Ed25519Parameters::Create(test_case.variant); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters == *other_parameters); EXPECT_TRUE(*other_parameters == *parameters); EXPECT_FALSE(*parameters != *other_parameters); EXPECT_FALSE(*other_parameters != *parameters); } TEST(Ed25519ParametersTest, VariantNotEqual) { util::StatusOr parameters = Ed25519Parameters::Create(Ed25519Parameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = Ed25519Parameters::Create(Ed25519Parameters::Variant::kNoPrefix); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ed25519_private_key.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ed25519_private_key.h" #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "openssl/crypto.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/ec_util.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/signature/ed25519_public_key.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { util::StatusOr Ed25519PrivateKey::Create( const Ed25519PublicKey& public_key, const RestrictedData& private_key_bytes, PartialKeyAccessToken token) { if (private_key_bytes.size() != 32) { return util::Status(absl::StatusCode::kInvalidArgument, "Ed25519 private key length must be 32 bytes."); } // Confirm that private key and public key are a valid Ed25519 key pair. util::StatusOr> key_pair = internal::NewEd25519Key(util::SecretDataFromStringView( private_key_bytes.GetSecret(InsecureSecretKeyAccess::Get()))); absl::string_view expected_public_key = public_key.GetPublicKeyBytes(token); if (CRYPTO_memcmp(expected_public_key.data(), (*key_pair)->public_key.data(), 32) != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid public key for private key bytes."); } return Ed25519PrivateKey(public_key, private_key_bytes); } bool Ed25519PrivateKey::operator==(const Key& other) const { const Ed25519PrivateKey* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (public_key_ != that->public_key_) { return false; } return private_key_bytes_ == that->private_key_bytes_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ed25519_private_key.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_ED25519_PRIVATE_KEY_H_ #define TINK_SIGNATURE_ED25519_PRIVATE_KEY_H_ #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_data.h" #include "tink/signature/ed25519_public_key.h" #include "tink/signature/signature_private_key.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { class Ed25519PrivateKey : public SignaturePrivateKey { public: // Copyable and movable. Ed25519PrivateKey(const Ed25519PrivateKey& other) = default; Ed25519PrivateKey& operator=(const Ed25519PrivateKey& other) = default; Ed25519PrivateKey(Ed25519PrivateKey&& other) = default; Ed25519PrivateKey& operator=(Ed25519PrivateKey&& other) = default; // Creates a new Ed25519 private key from `private_key_bytes`. Returns an // error if `public_key` does not belong to the same key pair as // `private_key_bytes`. static util::StatusOr Create( const Ed25519PublicKey& public_key, const RestrictedData& private_key_bytes, PartialKeyAccessToken token); const RestrictedData& GetPrivateKeyBytes(PartialKeyAccessToken token) const { return private_key_bytes_; } const Ed25519PublicKey& GetPublicKey() const override { return public_key_; } bool operator==(const Key& other) const override; private: explicit Ed25519PrivateKey(const Ed25519PublicKey& public_key, const RestrictedData& private_key_bytes) : public_key_(public_key), private_key_bytes_(private_key_bytes) {} Ed25519PublicKey public_key_; RestrictedData private_key_bytes_; }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_ED25519_PRIVATE_KEY_H_ ================================================ FILE: cc/signature/ed25519_private_key_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ed25519_private_key.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/ec_util.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/signature/ed25519_parameters.h" #include "tink/signature/ed25519_public_key.h" #include "tink/subtle/random.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { Ed25519Parameters::Variant variant; absl::optional id_requirement; std::string output_prefix; }; using Ed25519PrivateKeyTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( Ed25519PrivateKeyTestSuite, Ed25519PrivateKeyTest, Values(TestCase{Ed25519Parameters::Variant::kTink, 0x02030400, std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{Ed25519Parameters::Variant::kCrunchy, 0x01030005, std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{Ed25519Parameters::Variant::kLegacy, 0x07080910, std::string("\x00\x07\x08\x09\x10", 5)}, TestCase{Ed25519Parameters::Variant::kNoPrefix, absl::nullopt, ""})); TEST_P(Ed25519PrivateKeyTest, CreateSucceeds) { TestCase test_case = GetParam(); util::StatusOr params = Ed25519Parameters::Create(test_case.variant); ASSERT_THAT(params, IsOk()); util::StatusOr> key_pair = internal::NewEd25519Key(); ASSERT_THAT(key_pair, IsOk()); util::StatusOr public_key = Ed25519PublicKey::Create(*params, (*key_pair)->public_key, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); RestrictedData private_key_bytes = RestrictedData((*key_pair)->private_key, InsecureSecretKeyAccess::Get()); util::StatusOr private_key = Ed25519PrivateKey::Create( *public_key, private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); EXPECT_THAT(private_key->GetParameters(), Eq(*params)); EXPECT_THAT(private_key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(private_key->GetPublicKey(), Eq(*public_key)); EXPECT_THAT(private_key->GetOutputPrefix(), Eq(test_case.output_prefix)); EXPECT_THAT(private_key->GetPrivateKeyBytes(GetPartialKeyAccess()), Eq(private_key_bytes)); } TEST(Ed25519PrivateKeyTest, CreateWithMismatchedPublicKeyFails) { util::StatusOr params = Ed25519Parameters::Create(Ed25519Parameters::Variant::kTink); ASSERT_THAT(params, IsOk()); util::StatusOr> key_pair = internal::NewEd25519Key(); ASSERT_THAT(key_pair, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = Ed25519PublicKey::Create(*params, public_key_bytes, /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); RestrictedData private_key_bytes = RestrictedData((*key_pair)->private_key, InsecureSecretKeyAccess::Get()); EXPECT_THAT(Ed25519PrivateKey::Create(*public_key, private_key_bytes, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(Ed25519PrivateKeyTest, CreateWithInvalidPrivateKeyLengthFails) { util::StatusOr params = Ed25519Parameters::Create(Ed25519Parameters::Variant::kTink); ASSERT_THAT(params, IsOk()); util::StatusOr> key_pair = internal::NewEd25519Key(); ASSERT_THAT(key_pair, IsOk()); util::StatusOr public_key = Ed25519PublicKey::Create(*params, (*key_pair)->public_key, /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); RestrictedData private_key_bytes = RestrictedData( (*key_pair)->private_key.substr(0, 31), InsecureSecretKeyAccess::Get()); EXPECT_THAT(Ed25519PrivateKey::Create(*public_key, private_key_bytes, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(Ed25519PrivateKeyTest, KeyEquals) { TestCase test_case = GetParam(); util::StatusOr params = Ed25519Parameters::Create(test_case.variant); ASSERT_THAT(params, IsOk()); util::StatusOr> key_pair = internal::NewEd25519Key(); ASSERT_THAT(key_pair, IsOk()); util::StatusOr public_key = Ed25519PublicKey::Create(*params, (*key_pair)->public_key, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); RestrictedData private_key_bytes = RestrictedData((*key_pair)->private_key, InsecureSecretKeyAccess::Get()); util::StatusOr private_key = Ed25519PrivateKey::Create( *public_key, private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr other_private_key = Ed25519PrivateKey::Create(*public_key, private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(other_private_key, IsOk()); EXPECT_TRUE(*private_key == *other_private_key); EXPECT_TRUE(*other_private_key == *private_key); EXPECT_FALSE(*private_key != *other_private_key); EXPECT_FALSE(*other_private_key != *private_key); } TEST(Ed25519PrivateKeyTest, DifferentPublicKeyNotEqual) { util::StatusOr params = Ed25519Parameters::Create(Ed25519Parameters::Variant::kTink); ASSERT_THAT(params, IsOk()); util::StatusOr> key_pair = internal::NewEd25519Key(); ASSERT_THAT(key_pair, IsOk()); util::StatusOr public_key123 = Ed25519PublicKey::Create(*params, (*key_pair)->public_key, /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(public_key123, IsOk()); util::StatusOr public_key456 = Ed25519PublicKey::Create(*params, (*key_pair)->public_key, /*id_requirement=*/456, GetPartialKeyAccess()); ASSERT_THAT(public_key456, IsOk()); RestrictedData private_key_bytes = RestrictedData((*key_pair)->private_key, InsecureSecretKeyAccess::Get()); util::StatusOr private_key = Ed25519PrivateKey::Create( *public_key123, private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr other_private_key = Ed25519PrivateKey::Create(*public_key456, private_key_bytes, GetPartialKeyAccess()); ASSERT_THAT(other_private_key, IsOk()); EXPECT_TRUE(*private_key != *other_private_key); EXPECT_TRUE(*other_private_key != *private_key); EXPECT_FALSE(*private_key == *other_private_key); EXPECT_FALSE(*other_private_key == *private_key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ed25519_proto_serialization.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ed25519_proto_serialization.h" #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/key_parser.h" #include "tink/internal/key_serializer.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/parameters_parser.h" #include "tink/internal/parameters_serializer.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/secret_key_access_token.h" #include "tink/signature/ed25519_parameters.h" #include "tink/signature/ed25519_private_key.h" #include "tink/signature/ed25519_public_key.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/ed25519.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::google::crypto::tink::Ed25519KeyFormat; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using Ed25519ProtoParametersParserImpl = internal::ParametersParserImpl; using Ed25519ProtoParametersSerializerImpl = internal::ParametersSerializerImpl; using Ed25519ProtoPublicKeyParserImpl = internal::KeyParserImpl; using Ed25519ProtoPublicKeySerializerImpl = internal::KeySerializerImpl; using Ed25519ProtoPrivateKeyParserImpl = internal::KeyParserImpl; using Ed25519ProtoPrivateKeySerializerImpl = internal::KeySerializerImpl; const absl::string_view kPublicTypeUrl = "type.googleapis.com/google.crypto.tink.Ed25519PublicKey"; const absl::string_view kPrivateTypeUrl = "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey"; util::StatusOr ToVariant( OutputPrefixType output_prefix_type) { switch (output_prefix_type) { case OutputPrefixType::LEGACY: return Ed25519Parameters::Variant::kLegacy; case OutputPrefixType::CRUNCHY: return Ed25519Parameters::Variant::kCrunchy; case OutputPrefixType::RAW: return Ed25519Parameters::Variant::kNoPrefix; case OutputPrefixType::TINK: return Ed25519Parameters::Variant::kTink; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine Ed25519Parameters::Variant"); } } util::StatusOr ToOutputPrefixType( Ed25519Parameters::Variant variant) { switch (variant) { case Ed25519Parameters::Variant::kLegacy: return OutputPrefixType::LEGACY; case Ed25519Parameters::Variant::kCrunchy: return OutputPrefixType::CRUNCHY; case Ed25519Parameters::Variant::kNoPrefix: return OutputPrefixType::RAW; case Ed25519Parameters::Variant::kTink: return OutputPrefixType::TINK; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine output prefix type"); } } util::StatusOr ParseParameters( const internal::ProtoParametersSerialization& serialization) { if (serialization.GetKeyTemplate().type_url() != kPrivateTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing Ed25519Parameters."); } Ed25519KeyFormat proto_key_format; if (!proto_key_format.ParseFromString( serialization.GetKeyTemplate().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse Ed25519KeyFormat proto"); } if (proto_key_format.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } util::StatusOr variant = ToVariant(serialization.GetKeyTemplate().output_prefix_type()); if (!variant.ok()) { return variant.status(); } return Ed25519Parameters::Create(*variant); } util::StatusOr ParsePublicKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (serialization.TypeUrl() != kPublicTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing Ed25519PublicKey."); } google::crypto::tink::Ed25519PublicKey proto_key; const RestrictedData& restricted_data = serialization.SerializedKeyProto(); if (!proto_key.ParseFromString( restricted_data.GetSecret(InsecureSecretKeyAccess::Get()))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse Ed25519PublicKey proto"); } if (proto_key.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } util::StatusOr variant = ToVariant(serialization.GetOutputPrefixType()); if (!variant.ok()) { return variant.status(); } util::StatusOr parameters = Ed25519Parameters::Create(*variant); if (!parameters.ok()) { return parameters.status(); } return Ed25519PublicKey::Create(*parameters, proto_key.key_value(), serialization.IdRequirement(), GetPartialKeyAccess()); } util::StatusOr ParsePrivateKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (serialization.TypeUrl() != kPrivateTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing Ed25519PrivateKey."); } if (!token.has_value()) { return util::Status(absl::StatusCode::kPermissionDenied, "SecretKeyAccess is required"); } google::crypto::tink::Ed25519PrivateKey proto_key; const RestrictedData& restricted_data = serialization.SerializedKeyProto(); if (!proto_key.ParseFromString(restricted_data.GetSecret(*token))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse Ed25519PrivateKey proto"); } if (proto_key.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } util::StatusOr variant = ToVariant(serialization.GetOutputPrefixType()); if (!variant.ok()) { return variant.status(); } util::StatusOr parameters = Ed25519Parameters::Create(*variant); if (!parameters.ok()) { return parameters.status(); } util::StatusOr public_key = Ed25519PublicKey::Create( *parameters, proto_key.public_key().key_value(), serialization.IdRequirement(), GetPartialKeyAccess()); if (!public_key.ok()) { return public_key.status(); } return Ed25519PrivateKey::Create( *public_key, RestrictedData(proto_key.key_value(), *token), GetPartialKeyAccess()); } util::StatusOr SerializeParameters( const Ed25519Parameters& parameters) { util::StatusOr output_prefix_type = ToOutputPrefixType(parameters.GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } Ed25519KeyFormat proto_key_format; proto_key_format.set_version(0); return internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, *output_prefix_type, proto_key_format.SerializeAsString()); } util::StatusOr SerializePublicKey( const Ed25519PublicKey& key, absl::optional token) { google::crypto::tink::Ed25519PublicKey proto_key; proto_key.set_version(0); // OSS proto library complains if input is not converted to a string. proto_key.set_key_value( std::string(key.GetPublicKeyBytes(GetPartialKeyAccess()))); util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetParameters().GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } RestrictedData restricted_output = RestrictedData( proto_key.SerializeAsString(), InsecureSecretKeyAccess::Get()); return internal::ProtoKeySerialization::Create( kPublicTypeUrl, restricted_output, KeyData::ASYMMETRIC_PUBLIC, *output_prefix_type, key.GetIdRequirement()); } util::StatusOr SerializePrivateKey( const Ed25519PrivateKey& key, absl::optional token) { util::StatusOr restricted_input = key.GetPrivateKeyBytes(GetPartialKeyAccess()); if (!restricted_input.ok()) { return restricted_input.status(); } if (!token.has_value()) { return util::Status(absl::StatusCode::kPermissionDenied, "SecretKeyAccess is required"); } google::crypto::tink::Ed25519PublicKey proto_public_key; proto_public_key.set_version(0); // OSS proto library complains if input is not converted to a string. proto_public_key.set_key_value( std::string(key.GetPublicKey().GetPublicKeyBytes(GetPartialKeyAccess()))); google::crypto::tink::Ed25519PrivateKey proto_private_key; proto_private_key.set_version(0); *proto_private_key.mutable_public_key() = proto_public_key; // OSS proto library complains if input is not converted to a string. proto_private_key.set_key_value( std::string(restricted_input->GetSecret(*token))); util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetPublicKey().GetParameters().GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } RestrictedData restricted_output = RestrictedData(proto_private_key.SerializeAsString(), *token); return internal::ProtoKeySerialization::Create( kPrivateTypeUrl, restricted_output, KeyData::ASYMMETRIC_PRIVATE, *output_prefix_type, key.GetIdRequirement()); } Ed25519ProtoParametersParserImpl* Ed25519ProtoParametersParser() { static auto* parser = new Ed25519ProtoParametersParserImpl(kPrivateTypeUrl, ParseParameters); return parser; } Ed25519ProtoParametersSerializerImpl* Ed25519ProtoParametersSerializer() { static auto* serializer = new Ed25519ProtoParametersSerializerImpl( kPrivateTypeUrl, SerializeParameters); return serializer; } Ed25519ProtoPublicKeyParserImpl* Ed25519ProtoPublicKeyParser() { static auto* parser = new Ed25519ProtoPublicKeyParserImpl(kPublicTypeUrl, ParsePublicKey); return parser; } Ed25519ProtoPublicKeySerializerImpl* Ed25519ProtoPublicKeySerializer() { static auto* serializer = new Ed25519ProtoPublicKeySerializerImpl(SerializePublicKey); return serializer; } Ed25519ProtoPrivateKeyParserImpl* Ed25519ProtoPrivateKeyParser() { static auto* parser = new Ed25519ProtoPrivateKeyParserImpl(kPrivateTypeUrl, ParsePrivateKey); return parser; } Ed25519ProtoPrivateKeySerializerImpl* Ed25519ProtoPrivateKeySerializer() { static auto* serializer = new Ed25519ProtoPrivateKeySerializerImpl(SerializePrivateKey); return serializer; } } // namespace util::Status RegisterEd25519ProtoSerialization() { util::Status status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersParser(Ed25519ProtoParametersParser()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersSerializer(Ed25519ProtoParametersSerializer()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(Ed25519ProtoPublicKeyParser()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(Ed25519ProtoPublicKeySerializer()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(Ed25519ProtoPrivateKeyParser()); if (!status.ok()) { return status; } return internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(Ed25519ProtoPrivateKeySerializer()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ed25519_proto_serialization.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_ED25519_PROTO_SERIALIZATION_H_ #define TINK_SIGNATURE_ED25519_PROTO_SERIALIZATION_H_ #include "tink/util/status.h" namespace crypto { namespace tink { // Registers proto parsers and serializers for Ed25519 parameters and keys. crypto::tink::util::Status RegisterEd25519ProtoSerialization(); } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_ED25519_PROTO_SERIALIZATION_H_ ================================================ FILE: cc/signature/ed25519_proto_serialization_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ed25519_proto_serialization.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/ec_util.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_data.h" #include "tink/signature/ed25519_parameters.h" #include "tink/signature/ed25519_private_key.h" #include "tink/signature/ed25519_public_key.h" #include "tink/subtle/random.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/ed25519.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::subtle::Random; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::Ed25519KeyFormat; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::IsTrue; using ::testing::NotNull; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { Ed25519Parameters::Variant variant; OutputPrefixType output_prefix_type; absl::optional id; std::string output_prefix; }; class Ed25519ProtoSerializationTest : public TestWithParam { protected: void SetUp() override { internal::MutableSerializationRegistry::GlobalInstance().Reset(); } }; TEST_F(Ed25519ProtoSerializationTest, RegisterTwiceSucceeds) { ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk()); ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk()); } INSTANTIATE_TEST_SUITE_P( Ed25519ProtoSerializationTestSuite, Ed25519ProtoSerializationTest, Values(TestCase{Ed25519Parameters::Variant::kTink, OutputPrefixType::TINK, /*id=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{Ed25519Parameters::Variant::kCrunchy, OutputPrefixType::CRUNCHY, /*id=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{Ed25519Parameters::Variant::kLegacy, OutputPrefixType::LEGACY, /*id=*/0x07080910, /*output_prefix=*/std::string("\x00\x07\x08\x09\x10", 5)}, TestCase{Ed25519Parameters::Variant::kNoPrefix, OutputPrefixType::RAW, /*id=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(Ed25519ProtoSerializationTest, ParseParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk()); Ed25519KeyFormat key_format_proto; key_format_proto.set_version(0); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey", test_case.output_prefix_type, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(params, IsOk()); EXPECT_THAT((*params)->HasIdRequirement(), test_case.id.has_value()); const Ed25519Parameters* ed25519_params = dynamic_cast(params->get()); ASSERT_THAT(ed25519_params, NotNull()); EXPECT_THAT(ed25519_params->GetVariant(), Eq(test_case.variant)); } TEST_F(Ed25519ProtoSerializationTest, ParseParametersWithInvalidSerialization) { ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk()); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey", OutputPrefixType::RAW, "invalid_serialization"); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(Ed25519ProtoSerializationTest, ParseParametersWithUnkownOutputPrefix) { ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk()); Ed25519KeyFormat key_format_proto; key_format_proto.set_version(0); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey", OutputPrefixType::UNKNOWN_PREFIX, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(Ed25519ProtoSerializationTest, ParseParametersWithInvalidVersion) { ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk()); Ed25519KeyFormat key_format_proto; key_format_proto.set_version(1); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey", OutputPrefixType::RAW, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(Ed25519ProtoSerializationTest, SerializeParameters) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk()); util::StatusOr parameters = Ed25519Parameters::Create(test_case.variant); ASSERT_THAT(parameters, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( *parameters); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq("type.googleapis.com/google.crypto.tink.Ed25519PrivateKey")); const internal::ProtoParametersSerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->GetKeyTemplate().type_url(), Eq("type.googleapis.com/google.crypto.tink.Ed25519PrivateKey")); EXPECT_THAT(proto_serialization->GetKeyTemplate().output_prefix_type(), Eq(test_case.output_prefix_type)); Ed25519KeyFormat key_format; ASSERT_THAT( key_format.ParseFromString(proto_serialization->GetKeyTemplate().value()), IsTrue()); EXPECT_THAT(key_format.version(), Eq(0)); } TEST_P(Ed25519ProtoSerializationTest, ParsePublicKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); google::crypto::tink::Ed25519PublicKey key_proto; key_proto.set_version(0); key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.Ed25519PublicKey", serialized_key, KeyData::ASYMMETRIC_PUBLIC, test_case.output_prefix_type, test_case.id); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); ASSERT_THAT(key, IsOk()); EXPECT_THAT((*key)->GetIdRequirement(), Eq(test_case.id)); EXPECT_THAT((*key)->GetParameters().HasIdRequirement(), test_case.id.has_value()); util::StatusOr expected_parameters = Ed25519Parameters::Create(test_case.variant); ASSERT_THAT(expected_parameters, IsOk()); util::StatusOr expected_key = Ed25519PublicKey::Create( *expected_parameters, raw_key_bytes, test_case.id, GetPartialKeyAccess()); ASSERT_THAT(expected_key, IsOk()); EXPECT_THAT(**key, Eq(*expected_key)); } TEST_F(Ed25519ProtoSerializationTest, ParsePublicKeyWithInvalidSerialization) { ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk()); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.Ed25519PublicKey", serialized_key, KeyData::ASYMMETRIC_PUBLIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(Ed25519ProtoSerializationTest, ParsePublicKeyWithInvalidVersion) { ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); google::crypto::tink::Ed25519PublicKey key_proto; key_proto.set_version(1); // Invalid version number. key_proto.set_key_value(raw_key_bytes); RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.Ed25519PublicKey", serialized_key, KeyData::ASYMMETRIC_PUBLIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(Ed25519ProtoSerializationTest, SerializePublicKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk()); util::StatusOr parameters = Ed25519Parameters::Create(test_case.variant); ASSERT_THAT(parameters, IsOk()); std::string raw_key_bytes = Random::GetRandomBytes(32); util::StatusOr key = Ed25519PublicKey::Create( *parameters, raw_key_bytes, test_case.id, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, /*token=*/absl::nullopt); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq("type.googleapis.com/google.crypto.tink.Ed25519PublicKey")); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq("type.googleapis.com/google.crypto.tink.Ed25519PublicKey")); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::ASYMMETRIC_PUBLIC)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id)); google::crypto::tink::Ed25519PublicKey proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.version(), Eq(0)); EXPECT_THAT(proto_key.key_value(), Eq(raw_key_bytes)); } TEST_P(Ed25519ProtoSerializationTest, ParsePrivateKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk()); util::StatusOr> key_pair = internal::NewEd25519Key(); ASSERT_THAT(key_pair, IsOk()); google::crypto::tink::Ed25519PublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_key_value((*key_pair)->public_key); google::crypto::tink::Ed25519PrivateKey private_key_proto; private_key_proto.set_version(0); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_key_value((*key_pair)->private_key); RestrictedData serialized_key = RestrictedData( private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey", serialized_key, KeyData::ASYMMETRIC_PRIVATE, test_case.output_prefix_type, test_case.id); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); EXPECT_THAT((*key)->GetIdRequirement(), Eq(test_case.id)); EXPECT_THAT((*key)->GetParameters().HasIdRequirement(), test_case.id.has_value()); util::StatusOr expected_parameters = Ed25519Parameters::Create(test_case.variant); ASSERT_THAT(expected_parameters, IsOk()); util::StatusOr expected_public_key = Ed25519PublicKey::Create(*expected_parameters, (*key_pair)->public_key, test_case.id, GetPartialKeyAccess()); ASSERT_THAT(expected_public_key, IsOk()); util::StatusOr expected_private_key = Ed25519PrivateKey::Create(*expected_public_key, RestrictedData((*key_pair)->private_key, InsecureSecretKeyAccess::Get()), GetPartialKeyAccess()); ASSERT_THAT(expected_private_key, IsOk()); EXPECT_THAT(**key, Eq(*expected_private_key)); } TEST_F(Ed25519ProtoSerializationTest, ParsePrivateKeyWithInvalidSerialization) { ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk()); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey", serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(Ed25519ProtoSerializationTest, ParsePrivateKeyWithInvalidVersion) { ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk()); util::StatusOr> key_pair = internal::NewEd25519Key(); ASSERT_THAT(key_pair, IsOk()); google::crypto::tink::Ed25519PublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_key_value((*key_pair)->public_key); google::crypto::tink::Ed25519PrivateKey private_key_proto; private_key_proto.set_version(1); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_key_value((*key_pair)->private_key); RestrictedData serialized_key = RestrictedData( private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey", serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(Ed25519ProtoSerializationTest, ParsePrivateKeyNoSecretKeyAccess) { ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk()); util::StatusOr> key_pair = internal::NewEd25519Key(); ASSERT_THAT(key_pair, IsOk()); google::crypto::tink::Ed25519PublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_key_value((*key_pair)->public_key); google::crypto::tink::Ed25519PrivateKey private_key_proto; private_key_proto.set_version(0); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_key_value((*key_pair)->private_key); RestrictedData serialized_key = RestrictedData( private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey", serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kPermissionDenied)); } TEST_P(Ed25519ProtoSerializationTest, SerializePrivateKey) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk()); util::StatusOr parameters = Ed25519Parameters::Create(test_case.variant); ASSERT_THAT(parameters, IsOk()); util::StatusOr> key_pair = internal::NewEd25519Key(); ASSERT_THAT(key_pair, IsOk()); util::StatusOr public_key = Ed25519PublicKey::Create(*parameters, (*key_pair)->public_key, test_case.id, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = Ed25519PrivateKey::Create( *public_key, RestrictedData((*key_pair)->private_key, InsecureSecretKeyAccess::Get()), GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *private_key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq("type.googleapis.com/google.crypto.tink.Ed25519PrivateKey")); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq("type.googleapis.com/google.crypto.tink.Ed25519PrivateKey")); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::ASYMMETRIC_PRIVATE)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id)); google::crypto::tink::Ed25519PrivateKey proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.version(), Eq(0)); EXPECT_THAT(proto_key.key_value(), Eq((*key_pair)->private_key)); EXPECT_THAT(proto_key.has_public_key(), IsTrue()); EXPECT_THAT(proto_key.public_key().version(), Eq(0)); EXPECT_THAT(proto_key.public_key().key_value(), Eq((*key_pair)->public_key)); } TEST_F(Ed25519ProtoSerializationTest, SerializePrivateKeyNoSecretKeyAccess) { ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk()); util::StatusOr parameters = Ed25519Parameters::Create(Ed25519Parameters::Variant::kTink); ASSERT_THAT(parameters, IsOk()); util::StatusOr> key_pair = internal::NewEd25519Key(); ASSERT_THAT(key_pair, IsOk()); util::StatusOr public_key = Ed25519PublicKey::Create(*parameters, (*key_pair)->public_key, /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = Ed25519PrivateKey::Create( *public_key, RestrictedData((*key_pair)->private_key, InsecureSecretKeyAccess::Get()), GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *private_key, /*token=*/absl::nullopt); ASSERT_THAT(serialization.status(), StatusIs(absl::StatusCode::kPermissionDenied)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ed25519_public_key.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ed25519_public_key.h" #include #include "absl/base/attributes.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/signature/ed25519_parameters.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { util::StatusOr ComputeOutputPrefix( const Ed25519Parameters& parameters, absl::optional id_requirement) { switch (parameters.GetVariant()) { case Ed25519Parameters::Variant::kNoPrefix: return std::string(""); // Empty prefix. case Ed25519Parameters::Variant::kLegacy: ABSL_FALLTHROUGH_INTENDED; case Ed25519Parameters::Variant::kCrunchy: if (!id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "ID requirement must have value with kCrunchy or kLegacy"); } return absl::StrCat(absl::HexStringToBytes("00"), subtle::BigEndian32(*id_requirement)); case Ed25519Parameters::Variant::kTink: if (!id_requirement.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "ID requirement must have value with kTink"); } return absl::StrCat(absl::HexStringToBytes("01"), subtle::BigEndian32(*id_requirement)); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid variant: ", parameters.GetVariant())); } } } // namespace util::StatusOr Ed25519PublicKey::Create( const Ed25519Parameters& parameters, absl::string_view public_key_bytes, absl::optional id_requirement, PartialKeyAccessToken token) { if (parameters.HasIdRequirement() && !id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key without ID requirement with parameters with ID " "requirement"); } if (!parameters.HasIdRequirement() && id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key with ID requirement with parameters without ID " "requirement"); } if (public_key_bytes.size() != 32) { return util::Status(absl::StatusCode::kInvalidArgument, "Ed25519 public key length must be 32 bytes."); } util::StatusOr output_prefix = ComputeOutputPrefix(parameters, id_requirement); if (!output_prefix.ok()) { return output_prefix.status(); } return Ed25519PublicKey(parameters, public_key_bytes, id_requirement, *output_prefix); } bool Ed25519PublicKey::operator==(const Key& other) const { const Ed25519PublicKey* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (GetParameters() != that->GetParameters()) { return false; } if (id_requirement_ != that->id_requirement_) { return false; } return public_key_bytes_ == that->public_key_bytes_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ed25519_public_key.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_ED25519_PUBLIC_KEY_H_ #define TINK_SIGNATURE_ED25519_PUBLIC_KEY_H_ #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/signature/ed25519_parameters.h" #include "tink/signature/signature_public_key.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { class Ed25519PublicKey : public SignaturePublicKey { public: // Copyable and movable. Ed25519PublicKey(const Ed25519PublicKey& other) = default; Ed25519PublicKey& operator=(const Ed25519PublicKey& other) = default; Ed25519PublicKey(Ed25519PublicKey&& other) = default; Ed25519PublicKey& operator=(Ed25519PublicKey&& other) = default; // Creates a new Ed25519 public key from `public_key_bytes`. If `parameters` // specify a variant that uses a prefix, then `id_requirement` is used to // compute this prefix. static util::StatusOr Create( const Ed25519Parameters& parameters, absl::string_view public_key_bytes, absl::optional id_requirement, PartialKeyAccessToken token); absl::string_view GetPublicKeyBytes(PartialKeyAccessToken token) const { return public_key_bytes_; } absl::string_view GetOutputPrefix() const override { return output_prefix_; } const Ed25519Parameters& GetParameters() const override { return parameters_; } absl::optional GetIdRequirement() const override { return id_requirement_; } bool operator==(const Key& other) const override; private: explicit Ed25519PublicKey(const Ed25519Parameters& parameters, absl::string_view public_key_bytes, absl::optional id_requirement, absl::string_view output_prefix) : parameters_(parameters), public_key_bytes_(public_key_bytes), id_requirement_(id_requirement), output_prefix_(output_prefix) {} Ed25519Parameters parameters_; std::string public_key_bytes_; absl::optional id_requirement_; std::string output_prefix_; }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_ED25519_PUBLIC_KEY_H_ ================================================ FILE: cc/signature/ed25519_public_key_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ed25519_public_key.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/types/optional.h" #include "tink/partial_key_access.h" #include "tink/signature/ed25519_parameters.h" #include "tink/subtle/random.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { Ed25519Parameters::Variant variant; absl::optional id_requirement; std::string output_prefix; }; using Ed25519PublicKeyTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( Ed25519PublicKeyTestSuite, Ed25519PublicKeyTest, Values(TestCase{Ed25519Parameters::Variant::kTink, 0x02030400, std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{Ed25519Parameters::Variant::kCrunchy, 0x01030005, std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{Ed25519Parameters::Variant::kLegacy, 0x07080910, std::string("\x00\x07\x08\x09\x10", 5)}, TestCase{Ed25519Parameters::Variant::kNoPrefix, absl::nullopt, ""})); TEST_P(Ed25519PublicKeyTest, CreateSucceeds) { TestCase test_case = GetParam(); util::StatusOr params = Ed25519Parameters::Create(test_case.variant); ASSERT_THAT(params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = Ed25519PublicKey::Create(*params, public_key_bytes, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); EXPECT_THAT(public_key->GetParameters(), Eq(*params)); EXPECT_THAT(public_key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(public_key->GetOutputPrefix(), Eq(test_case.output_prefix)); EXPECT_THAT(public_key->GetPublicKeyBytes(GetPartialKeyAccess()), Eq(public_key_bytes)); } TEST(Ed25519PublicKeyTest, CreateWithInvalidPublicKeyLength) { util::StatusOr params = Ed25519Parameters::Create(Ed25519Parameters::Variant::kTink); ASSERT_THAT(params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(31); EXPECT_THAT( Ed25519PublicKey::Create(*params, public_key_bytes, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(Ed25519PublicKeyTest, CreateKeyWithInvalidIdRequirementFails) { util::StatusOr no_prefix_params = Ed25519Parameters::Create(Ed25519Parameters::Variant::kNoPrefix); ASSERT_THAT(no_prefix_params, IsOk()); util::StatusOr tink_params = Ed25519Parameters::Create(Ed25519Parameters::Variant::kTink); ASSERT_THAT(tink_params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); EXPECT_THAT( Ed25519PublicKey::Create(*no_prefix_params, public_key_bytes, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(Ed25519PublicKey::Create(*tink_params, public_key_bytes, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(Ed25519PublicKeyTest, KeyEquals) { TestCase test_case = GetParam(); util::StatusOr params = Ed25519Parameters::Create(test_case.variant); ASSERT_THAT(params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = Ed25519PublicKey::Create(*params, public_key_bytes, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = Ed25519PublicKey::Create(*params, public_key_bytes, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key == *other_public_key); EXPECT_TRUE(*other_public_key == *public_key); EXPECT_FALSE(*public_key != *other_public_key); EXPECT_FALSE(*other_public_key != *public_key); } TEST(Ed25519PublicKeyTest, DifferentVariantNotEqual) { util::StatusOr crunchy_params = Ed25519Parameters::Create(Ed25519Parameters::Variant::kCrunchy); ASSERT_THAT(crunchy_params, IsOk()); util::StatusOr tink_params = Ed25519Parameters::Create(Ed25519Parameters::Variant::kTink); ASSERT_THAT(tink_params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = Ed25519PublicKey::Create( *crunchy_params, public_key_bytes, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = Ed25519PublicKey::Create( *tink_params, public_key_bytes, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key != *other_public_key); EXPECT_TRUE(*other_public_key != *public_key); EXPECT_FALSE(*public_key == *other_public_key); EXPECT_FALSE(*other_public_key == *public_key); } TEST(Ed25519PublicKeyTest, DifferentPublicKeyBytesNotEqual) { util::StatusOr params = Ed25519Parameters::Create(Ed25519Parameters::Variant::kTink); ASSERT_THAT(params, IsOk()); std::string public_key_bytes1 = subtle::Random::GetRandomBytes(32); std::string public_key_bytes2 = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = Ed25519PublicKey::Create( *params, public_key_bytes1, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = Ed25519PublicKey::Create( *params, public_key_bytes2, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key != *other_public_key); EXPECT_TRUE(*other_public_key != *public_key); EXPECT_FALSE(*public_key == *other_public_key); EXPECT_FALSE(*other_public_key == *public_key); } TEST(Ed25519PublicKeyTest, DifferentIdRequirementNotEqual) { util::StatusOr params = Ed25519Parameters::Create(Ed25519Parameters::Variant::kTink); ASSERT_THAT(params, IsOk()); std::string public_key_bytes = subtle::Random::GetRandomBytes(32); util::StatusOr public_key = Ed25519PublicKey::Create( *params, public_key_bytes, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = Ed25519PublicKey::Create( *params, public_key_bytes, /*id_requirement=*/0x02030405, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key != *other_public_key); EXPECT_TRUE(*other_public_key != *public_key); EXPECT_FALSE(*public_key == *other_public_key); EXPECT_FALSE(*other_public_key == *public_key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ed25519_sign_key_manager.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ed25519_sign_key_manager.h" #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/input_stream.h" #include "tink/internal/ec_util.h" #include "tink/public_key_sign.h" #include "tink/signature/ed25519_verify_key_manager.h" #include "tink/subtle/ed25519_sign_boringssl.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/input_stream_util.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/ed25519.pb.h" namespace crypto { namespace tink { using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::Ed25519KeyFormat; using ::google::crypto::tink::Ed25519PrivateKey; StatusOr Ed25519SignKeyManager::CreateKey( const Ed25519KeyFormat& key_format) const { util::StatusOr> key = internal::NewEd25519Key(); if (!key.ok()) { return key.status(); } Ed25519PrivateKey ed25519_private_key; ed25519_private_key.set_version(get_version()); ed25519_private_key.set_key_value((*key)->private_key); // Build Ed25519PublicKey. auto ed25519_public_key = ed25519_private_key.mutable_public_key(); ed25519_public_key->set_version(get_version()); ed25519_public_key->set_key_value((*key)->public_key); return ed25519_private_key; } StatusOr> Ed25519SignKeyManager::PublicKeySignFactory::Create( const Ed25519PrivateKey& private_key) const { // BoringSSL expects a 64-byte private key which contains the public key as a // suffix. util::SecretData sk = util::SecretDataFromStringView(absl::StrCat( private_key.key_value(), private_key.public_key().key_value())); return subtle::Ed25519SignBoringSsl::New(sk); } Status Ed25519SignKeyManager::ValidateKey(const Ed25519PrivateKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; if (key.key_value().length() != 32) { return Status(absl::StatusCode::kInvalidArgument, "The ED25519 private key must be 32-bytes long."); } return Ed25519VerifyKeyManager().ValidateKey(key.public_key()); } StatusOr Ed25519SignKeyManager::DeriveKey( const Ed25519KeyFormat& key_format, InputStream* input_stream) const { util::Status status = ValidateVersion(key_format.version(), get_version()); if (!status.ok()) return status; util::StatusOr randomness = ReadSecretBytesFromStream(kEd25519SecretSeedSize, input_stream); if (!randomness.ok()) { if (randomness.status().code() == absl::StatusCode::kOutOfRange) { return util::Status( absl::StatusCode::kInvalidArgument, "Could not get enough pseudorandomness from input stream"); } return randomness.status(); } util::StatusOr> key = internal::NewEd25519Key(*randomness); Ed25519PrivateKey ed25519_private_key; ed25519_private_key.set_version(get_version()); ed25519_private_key.set_key_value((*key)->private_key); // Build Ed25519PublicKey. auto ed25519_public_key = ed25519_private_key.mutable_public_key(); ed25519_public_key->set_version(get_version()); ed25519_public_key->set_key_value((*key)->public_key); return ed25519_private_key; } Status Ed25519SignKeyManager::ValidateKeyFormat( const Ed25519KeyFormat& key_format) const { return util::OkStatus(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ed25519_sign_key_manager.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_ED25519_SIGN_KEY_MANAGER_H_ #define TINK_SIGNATURE_ED25519_SIGN_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/input_stream.h" #include "tink/public_key_sign.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/input_stream_util.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/ed25519.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class Ed25519SignKeyManager : public PrivateKeyTypeManager> { public: class PublicKeySignFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::Ed25519PrivateKey& private_key) const override; }; Ed25519SignKeyManager() : PrivateKeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::Ed25519PrivateKey& key) const override; crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::Ed25519KeyFormat& key_format) const override; crypto::tink::util::StatusOr CreateKey( const google::crypto::tink::Ed25519KeyFormat& key_format) const override; crypto::tink::util::StatusOr GetPublicKey(const google::crypto::tink::Ed25519PrivateKey& private_key) const override { return private_key.public_key(); } crypto::tink::util::StatusOr DeriveKey(const google::crypto::tink::Ed25519KeyFormat& key_format, InputStream* input_stream) const override; private: const std::string key_type_ = absl::StrCat(kTypeGoogleapisCom, google::crypto::tink::Ed25519PrivateKey().GetTypeName()); static constexpr int kEd25519SecretSeedSize = 32; }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_ED25519_SIGN_KEY_MANAGER_H_ ================================================ FILE: cc/signature/ed25519_sign_key_manager_test.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ed25519_sign_key_manager.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_set.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/registry.h" #include "tink/signature/ed25519_verify_key_manager.h" #include "tink/subtle/ed25519_verify_boringssl.h" #include "tink/util/enums.h" #include "tink/util/istream_input_stream.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/ed25519.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::crypto::tink::test::IsOk; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::Ed25519KeyFormat; using ::google::crypto::tink::Ed25519PrivateKey; using ::google::crypto::tink::Ed25519PublicKey; using ::google::crypto::tink::KeyData; using ::testing::Eq; using ::testing::Not; using ::testing::SizeIs; namespace { TEST(Ed25519SignKeyManagerTest, Basic) { EXPECT_THAT(Ed25519SignKeyManager().get_version(), Eq(0)); EXPECT_THAT(Ed25519SignKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PRIVATE)); EXPECT_THAT(Ed25519SignKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.Ed25519PrivateKey")); } TEST(Ed25519SignKeyManagerTest, ValidateKeyFormat) { EXPECT_THAT(Ed25519SignKeyManager().ValidateKeyFormat(Ed25519KeyFormat()), IsOk()); } TEST(Ed25519SignKeyManagerTest, CreateKey) { StatusOr key_or = Ed25519SignKeyManager().CreateKey(Ed25519KeyFormat()); ASSERT_THAT(key_or, IsOk()); Ed25519PrivateKey key = key_or.value(); EXPECT_THAT(key.version(), Eq(0)); EXPECT_THAT(key.public_key().version(), Eq(key.version())); EXPECT_THAT(key.key_value(), SizeIs(32)); EXPECT_THAT(key.public_key().key_value(), SizeIs(32)); } TEST(Ed25519SignKeyManagerTest, CreateKeyValid) { StatusOr key_or = Ed25519SignKeyManager().CreateKey(Ed25519KeyFormat()); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(Ed25519SignKeyManager().ValidateKey(key_or.value()), IsOk()); } TEST(Ed25519SignKeyManagerTest, CreateKeyAlwaysNew) { absl::flat_hash_set keys; int num_tests = 100; for (int i = 0; i < num_tests; ++i) { StatusOr key_or = Ed25519SignKeyManager().CreateKey(Ed25519KeyFormat()); ASSERT_THAT(key_or, IsOk()); keys.insert(key_or.value().key_value()); } EXPECT_THAT(keys, SizeIs(num_tests)); } TEST(Ed25519SignKeyManagerTest, GetPublicKey) { StatusOr key_or = Ed25519SignKeyManager().CreateKey(Ed25519KeyFormat()); ASSERT_THAT(key_or, IsOk()); StatusOr public_key_or = Ed25519SignKeyManager().GetPublicKey(key_or.value()); ASSERT_THAT(public_key_or, IsOk()); EXPECT_THAT(public_key_or.value().version(), Eq(key_or.value().public_key().version())); EXPECT_THAT(public_key_or.value().key_value(), Eq(key_or.value().public_key().key_value())); } TEST(Ed25519SignKeyManagerTest, Create) { StatusOr key_or = Ed25519SignKeyManager().CreateKey(Ed25519KeyFormat()); ASSERT_THAT(key_or, IsOk()); Ed25519PrivateKey key = key_or.value(); auto signer_or = Ed25519SignKeyManager().GetPrimitive(key); ASSERT_THAT(signer_or, IsOk()); auto direct_verifier_or = subtle::Ed25519VerifyBoringSsl::New(key.public_key().key_value()); ASSERT_THAT(direct_verifier_or, IsOk()); std::string message = "Some message"; EXPECT_THAT(direct_verifier_or.value()->Verify( signer_or.value()->Sign(message).value(), message), IsOk()); } TEST(Ed25519SignKeyManagerTest, CreateDifferentKey) { StatusOr key_or = Ed25519SignKeyManager().CreateKey(Ed25519KeyFormat()); ASSERT_THAT(key_or, IsOk()); Ed25519PrivateKey key = key_or.value(); auto signer_or = Ed25519SignKeyManager().GetPrimitive(key); ASSERT_THAT(signer_or, IsOk()); auto direct_verifier_or = subtle::Ed25519VerifyBoringSsl::New("01234567890123456789012345678901"); ASSERT_THAT(direct_verifier_or, IsOk()); std::string message = "Some message"; EXPECT_THAT(direct_verifier_or.value()->Verify( signer_or.value()->Sign(message).value(), message), Not(IsOk())); } TEST(Ed25519SignKeyManagerTest, DeriveKey) { Ed25519KeyFormat format; util::IstreamInputStream input_stream{ absl::make_unique("0123456789abcdef0123456789abcdef")}; StatusOr key_or = Ed25519SignKeyManager().DeriveKey(format, &input_stream); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().key_value(), Eq("0123456789abcdef0123456789abcdef")); } TEST(Ed25519SignKeyManagerTest, DeriveKeySignVerify) { Ed25519KeyFormat format; util::IstreamInputStream input_stream{ absl::make_unique("0123456789abcdef0123456789abcdef")}; Ed25519PrivateKey key = Ed25519SignKeyManager().DeriveKey(format, &input_stream).value(); auto signer_or = Ed25519SignKeyManager().GetPrimitive(key); ASSERT_THAT(signer_or, IsOk()); std::string message = "Some message"; auto signature = signer_or.value()->Sign(message).value(); auto verifier_or = Ed25519VerifyKeyManager().GetPrimitive(key.public_key()); EXPECT_THAT(verifier_or.value()->Verify(signature, message), IsOk()); } TEST(Ed25519SignKeyManagerTest, DeriveKeyNotEnoughRandomness) { Ed25519KeyFormat format; util::IstreamInputStream input_stream{ absl::make_unique("tooshort")}; ASSERT_THAT(Ed25519SignKeyManager().DeriveKey(format, &input_stream).status(), test::StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ed25519_verify_key_manager.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ed25519_verify_key_manager.h" #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/public_key_verify.h" #include "tink/subtle/ed25519_verify_boringssl.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/ed25519.pb.h" namespace crypto { namespace tink { using crypto::tink::util::Status; using crypto::tink::util::StatusOr; using google::crypto::tink::Ed25519PublicKey; StatusOr> Ed25519VerifyKeyManager::PublicKeyVerifyFactory::Create( const Ed25519PublicKey& public_key) const { return subtle::Ed25519VerifyBoringSsl::New(public_key.key_value()); } Status Ed25519VerifyKeyManager::ValidateKey(const Ed25519PublicKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; if (key.key_value().length() != 32) { return Status(absl::StatusCode::kInvalidArgument, "The ED25519 public key must be 32-bytes long."); } return util::OkStatus(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/ed25519_verify_key_manager.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_ED25519_VERIFY_KEY_MANAGER_H_ #define TINK_SIGNATURE_ED25519_VERIFY_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/public_key_verify.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/ed25519.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class Ed25519VerifyKeyManager : public KeyTypeManager> { public: class PublicKeyVerifyFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::Ed25519PublicKey& ecdsa_public_key) const override; }; Ed25519VerifyKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PUBLIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::Ed25519PublicKey& key) const override; private: const std::string key_type_ = absl::StrCat(kTypeGoogleapisCom, google::crypto::tink::Ed25519PublicKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_ED25519_VERIFY_KEY_MANAGER_H_ ================================================ FILE: cc/signature/ed25519_verify_key_manager_test.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/ed25519_verify_key_manager.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/str_cat.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/registry.h" #include "tink/signature/ed25519_sign_key_manager.h" #include "tink/subtle/ed25519_sign_boringssl.h" #include "tink/util/enums.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/ed25519.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::crypto::tink::test::IsOk; using ::google::crypto::tink::Ed25519KeyFormat; using ::google::crypto::tink::Ed25519PrivateKey; using ::google::crypto::tink::Ed25519PublicKey; using ::google::crypto::tink::KeyData; using ::testing::Eq; using ::testing::Not; namespace { TEST(Ed25519VerifyKeyManagerTest, Basics) { EXPECT_THAT(Ed25519VerifyKeyManager().get_version(), Eq(0)); EXPECT_THAT(Ed25519VerifyKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PUBLIC)); EXPECT_THAT(Ed25519VerifyKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.Ed25519PublicKey")); } TEST(Ed25519VerifyKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(Ed25519VerifyKeyManager().ValidateKey(Ed25519PublicKey()), Not(IsOk())); } Ed25519PrivateKey CreateValidPrivateKey() { return Ed25519SignKeyManager().CreateKey(Ed25519KeyFormat()).value(); } Ed25519PublicKey CreateValidPublicKey() { return Ed25519SignKeyManager().GetPublicKey(CreateValidPrivateKey()).value(); } // Checks that a public key generaed by the SignKeyManager is considered valid. TEST(Ed25519VerifyKeyManagerTest, PublicKeyValid) { Ed25519PublicKey key = CreateValidPublicKey(); EXPECT_THAT(Ed25519VerifyKeyManager().ValidateKey(key), IsOk()); } TEST(Ed25519VerifyKeyManagerTest, PublicKeyWrongVersion) { Ed25519PublicKey key = CreateValidPublicKey(); key.set_version(1); EXPECT_THAT(Ed25519VerifyKeyManager().ValidateKey(key), Not(IsOk())); } TEST(Ed25519VerifyKeyManagerTest, PublicKeyWrongKeyLength31) { Ed25519PublicKey key = CreateValidPublicKey(); key.set_key_value(std::string(31, 'a')); EXPECT_THAT(Ed25519VerifyKeyManager().ValidateKey(key), Not(IsOk())); } TEST(Ed25519VerifyKeyManagerTest, PublicKeyWrongKeyLength64) { Ed25519PublicKey key = CreateValidPublicKey(); key.set_key_value(std::string(64, 'a')); EXPECT_THAT(Ed25519VerifyKeyManager().ValidateKey(key), Not(IsOk())); } TEST(Ed25519SignKeyManagerTest, Create) { Ed25519PrivateKey private_key = CreateValidPrivateKey(); Ed25519PublicKey public_key = Ed25519SignKeyManager().GetPublicKey(private_key).value(); auto direct_signer_or = subtle::Ed25519SignBoringSsl::New(util::SecretDataFromStringView( absl::StrCat(private_key.key_value(), public_key.key_value()))); ASSERT_THAT(direct_signer_or, IsOk()); auto verifier_or = Ed25519VerifyKeyManager().GetPrimitive(public_key); ASSERT_THAT(verifier_or, IsOk()); std::string message = "Some message"; EXPECT_THAT(verifier_or.value()->Verify( direct_signer_or.value()->Sign(message).value(), message), IsOk()); } TEST(Ed25519SignKeyManagerTest, CreateDifferentPrivateKey) { Ed25519PrivateKey private_key = CreateValidPrivateKey(); // Note: we create a new key in the next line. Ed25519PublicKey public_key = Ed25519SignKeyManager().GetPublicKey(CreateValidPrivateKey()).value(); auto direct_signer_or = subtle::Ed25519SignBoringSsl::New( util::SecretDataFromStringView(absl::StrCat( private_key.key_value(), private_key.public_key().key_value()))); ASSERT_THAT(direct_signer_or, IsOk()); auto verifier_or = Ed25519VerifyKeyManager().GetPrimitive(public_key); ASSERT_THAT(verifier_or, IsOk()); std::string message = "Some message"; EXPECT_THAT(verifier_or.value()->Verify( direct_signer_or.value()->Sign(message).value(), message), Not(IsOk())); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/failing_signature.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/signature/failing_signature.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { // A PublicKeySign that always return a kInternal status on API calls. class AlwaysFailPublicKeySign : public PublicKeySign { public: explicit AlwaysFailPublicKeySign(std::string message) : message_(std::move(message)) {} util::StatusOr Sign( absl::string_view /*message*/) const override { return util::Status( absl::StatusCode::kInternal, absl::StrCat("AlwaysFailPublicKeySign will always fail on sign (msg=", message_, ")")); } private: const std::string message_; }; // A PublicKeyVerify that always return a kInternal status on API calls. class AlwaysFailPublicKeyVerify : public PublicKeyVerify { public: explicit AlwaysFailPublicKeyVerify(std::string message) : message_(std::move(message)) {} util::Status Verify(absl::string_view /*signature*/, absl::string_view /*message*/) const override { return absl::InternalError( absl::StrCat( "AlwaysFailPublicKeyVerify will always fail on verify (msg=", message_, ")")); } private: const std::string message_; }; } // namespace std::unique_ptr CreateAlwaysFailingPublicKeySign( std::string message) { return absl::make_unique(std::move(message)); } std::unique_ptr CreateAlwaysFailingPublicKeyVerify( std::string message) { return absl::make_unique(std::move(message)); } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/failing_signature.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_FAILING_SIGNATURE_H_ #define TINK_SIGNATURE_FAILING_SIGNATURE_H_ #include #include #include "absl/strings/string_view.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" namespace crypto { namespace tink { // Returns a PublicKeySign that always return an error when calling Sign. // The error message will contain `message`. std::unique_ptr CreateAlwaysFailingPublicKeySign( std::string message = ""); // Returns a PublicKeyVerify that always returns an error when calling Verify. // The error message will contain `message`. std::unique_ptr CreateAlwaysFailingPublicKeyVerify( std::string message = ""); } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_FAILING_SIGNATURE_H_ ================================================ FILE: cc/signature/failing_signature_test.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/signature/failing_signature.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::StatusIs; using ::testing::HasSubstr; TEST(AlwaysFailPublicKeySign, SignFails) { std::unique_ptr failing_sign = CreateAlwaysFailingPublicKeySign(); EXPECT_THAT(failing_sign->Sign("message").status(), StatusIs(absl::StatusCode::kInternal)); } TEST(AlwaysFailPublicKeySign, SignFailsContainsMessage) { const std::string expected_message = "expected_message"; std::unique_ptr failing_sign = CreateAlwaysFailingPublicKeySign(expected_message); EXPECT_THAT( failing_sign->Sign("message").status(), StatusIs(absl::StatusCode::kInternal, HasSubstr(expected_message))); } TEST(AlwaysFailPublicKeyVerify, VerifyFails) { std::unique_ptr failing_verify = CreateAlwaysFailingPublicKeyVerify(); EXPECT_THAT(failing_verify->Verify("signature", "message"), StatusIs(absl::StatusCode::kInternal)); } TEST(AlwaysFailPublicKeyVerify, VerifyFailsContainsMessage) { const std::string expected_message = "expected_message"; std::unique_ptr failing_verify = CreateAlwaysFailingPublicKeyVerify(expected_message); EXPECT_THAT( failing_verify->Verify("signature", "message"), StatusIs(absl::StatusCode::kInternal, HasSubstr(expected_message))); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/internal/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "ecdsa_raw_sign_boringssl", srcs = ["ecdsa_raw_sign_boringssl.cc"], hdrs = ["ecdsa_raw_sign_boringssl.h"], include_prefix = "tink/signature/internal", deps = [ "//:public_key_sign", "//internal:bn_util", "//internal:ec_util", "//internal:err_util", "//internal:fips_utils", "//internal:md_util", "//internal:ssl_unique_ptr", "//internal:util", "//subtle:common_enums", "//subtle:subtle_util_boringssl", "//util:errors", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "config_v0", srcs = ["config_v0.cc"], hdrs = ["config_v0.h"], include_prefix = "tink/signature/internal", deps = [ "//:configuration", "//internal:configuration_impl", "//signature:ecdsa_sign_key_manager", "//signature:ecdsa_verify_key_manager", "//signature:ed25519_sign_key_manager", "//signature:ed25519_verify_key_manager", "//signature:public_key_sign_wrapper", "//signature:public_key_verify_wrapper", "//signature:rsa_ssa_pkcs1_sign_key_manager", "//signature:rsa_ssa_pkcs1_verify_key_manager", "//signature:rsa_ssa_pss_sign_key_manager", "//signature:rsa_ssa_pss_verify_key_manager", "//util:status", "@com_google_absl//absl/memory", ], ) cc_library( name = "key_gen_config_v0", srcs = ["key_gen_config_v0.cc"], hdrs = ["key_gen_config_v0.h"], include_prefix = "tink/signature/internal", deps = [ "//:key_gen_configuration", "//internal:key_gen_configuration_impl", "//signature:ecdsa_sign_key_manager", "//signature:ecdsa_verify_key_manager", "//signature:ed25519_sign_key_manager", "//signature:ed25519_verify_key_manager", "//signature:rsa_ssa_pkcs1_sign_key_manager", "//signature:rsa_ssa_pkcs1_verify_key_manager", "//signature:rsa_ssa_pss_sign_key_manager", "//signature:rsa_ssa_pss_verify_key_manager", "//util:status", "@com_google_absl//absl/memory", ], ) cc_library( name = "config_fips_140_2", srcs = ["config_fips_140_2.cc"], hdrs = ["config_fips_140_2.h"], include_prefix = "tink/signature/internal", deps = [ "//:configuration", "//internal:configuration_impl", "//internal:fips_utils", "//signature:ecdsa_sign_key_manager", "//signature:ecdsa_verify_key_manager", "//signature:public_key_sign_wrapper", "//signature:public_key_verify_wrapper", "//signature:rsa_ssa_pkcs1_sign_key_manager", "//signature:rsa_ssa_pkcs1_verify_key_manager", "//signature:rsa_ssa_pss_sign_key_manager", "//signature:rsa_ssa_pss_verify_key_manager", "//util:status", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", ], ) # tests cc_test( name = "ecdsa_raw_sign_boringssl_test", size = "small", srcs = ["ecdsa_raw_sign_boringssl_test.cc"], tags = ["fips"], deps = [ ":ecdsa_raw_sign_boringssl", "//:public_key_sign", "//:public_key_verify", "//internal:ec_util", "//internal:fips_utils", "//internal:md_util", "//subtle:common_enums", "//subtle:ecdsa_verify_boringssl", "//subtle:subtle_util_boringssl", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "config_v0_test", srcs = ["config_v0_test.cc"], deps = [ ":config_v0", ":key_gen_config_v0", "//:configuration", "//:key_gen_configuration", "//:keyset_handle", "//:public_key_sign", "//:public_key_verify", "//internal:configuration_impl", "//internal:key_gen_configuration_impl", "//internal:key_type_info_store", "//internal:keyset_wrapper_store", "//proto:tink_cc_proto", "//signature:ecdsa_verify_key_manager", "//signature:ed25519_verify_key_manager", "//signature:rsa_ssa_pkcs1_verify_key_manager", "//signature:rsa_ssa_pss_verify_key_manager", "//signature:signature_key_templates", "//util:statusor", "//util:test_matchers", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "config_fips_140_2_test", srcs = ["config_fips_140_2_test.cc"], deps = [ ":config_fips_140_2", ":key_gen_config_v0", "//:configuration", "//:key_gen_configuration", "//:keyset_handle", "//:public_key_sign", "//:public_key_verify", "//internal:configuration_impl", "//internal:fips_utils", "//internal:key_type_info_store", "//internal:keyset_wrapper_store", "//proto:tink_cc_proto", "//signature:ecdsa_verify_key_manager", "//signature:ed25519_verify_key_manager", "//signature:rsa_ssa_pkcs1_verify_key_manager", "//signature:rsa_ssa_pss_verify_key_manager", "//signature:signature_key_templates", "//util:statusor", "//util:test_matchers", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/signature/internal/CMakeLists.txt ================================================ tink_module(signature::internal) tink_cc_library( NAME ecdsa_raw_sign_boringssl SRCS ecdsa_raw_sign_boringssl.cc ecdsa_raw_sign_boringssl.h DEPS absl::memory absl::status absl::strings crypto tink::core::public_key_sign tink::internal::bn_util tink::internal::ec_util tink::internal::err_util tink::internal::fips_utils tink::internal::md_util tink::internal::ssl_unique_ptr tink::internal::util tink::subtle::common_enums tink::subtle::subtle_util_boringssl tink::util::errors tink::util::status tink::util::statusor ) tink_cc_library( NAME config_v0 SRCS config_v0.cc config_v0.h DEPS absl::memory tink::core::configuration tink::internal::configuration_impl tink::signature::ecdsa_sign_key_manager tink::signature::ecdsa_verify_key_manager tink::signature::ed25519_sign_key_manager tink::signature::ed25519_verify_key_manager tink::signature::public_key_sign_wrapper tink::signature::public_key_verify_wrapper tink::signature::rsa_ssa_pkcs1_sign_key_manager tink::signature::rsa_ssa_pkcs1_verify_key_manager tink::signature::rsa_ssa_pss_sign_key_manager tink::signature::rsa_ssa_pss_verify_key_manager tink::util::status ) tink_cc_library( NAME key_gen_config_v0 SRCS key_gen_config_v0.cc key_gen_config_v0.h DEPS absl::memory tink::core::key_gen_configuration tink::internal::key_gen_configuration_impl tink::signature::ecdsa_sign_key_manager tink::signature::ecdsa_verify_key_manager tink::signature::ed25519_sign_key_manager tink::signature::ed25519_verify_key_manager tink::signature::rsa_ssa_pkcs1_sign_key_manager tink::signature::rsa_ssa_pkcs1_verify_key_manager tink::signature::rsa_ssa_pss_sign_key_manager tink::signature::rsa_ssa_pss_verify_key_manager tink::util::status ) tink_cc_library( NAME config_fips_140_2 SRCS config_fips_140_2.cc config_fips_140_2.h DEPS absl::memory absl::status tink::core::configuration tink::internal::configuration_impl tink::internal::fips_utils tink::signature::ecdsa_sign_key_manager tink::signature::ecdsa_verify_key_manager tink::signature::public_key_sign_wrapper tink::signature::public_key_verify_wrapper tink::signature::rsa_ssa_pkcs1_sign_key_manager tink::signature::rsa_ssa_pkcs1_verify_key_manager tink::signature::rsa_ssa_pss_sign_key_manager tink::signature::rsa_ssa_pss_verify_key_manager tink::util::status ) # tests tink_cc_test( NAME ecdsa_raw_sign_boringssl_test SRCS ecdsa_raw_sign_boringssl_test.cc DEPS tink::signature::internal::ecdsa_raw_sign_boringssl gmock absl::status absl::string_view tink::core::public_key_sign tink::core::public_key_verify tink::internal::ec_util tink::internal::fips_utils tink::internal::md_util tink::subtle::common_enums tink::subtle::ecdsa_verify_boringssl tink::subtle::subtle_util_boringssl tink::util::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME config_v0_test SRCS config_v0_test.cc DEPS tink::signature::internal::config_v0 tink::signature::internal::key_gen_config_v0 gmock tink::core::configuration tink::core::key_gen_configuration tink::core::keyset_handle tink::core::public_key_sign tink::core::public_key_verify tink::internal::configuration_impl tink::internal::key_gen_configuration_impl tink::internal::key_type_info_store tink::internal::keyset_wrapper_store tink::signature::ecdsa_verify_key_manager tink::signature::ed25519_verify_key_manager tink::signature::rsa_ssa_pkcs1_verify_key_manager tink::signature::rsa_ssa_pss_verify_key_manager tink::signature::signature_key_templates tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) tink_cc_test( NAME config_fips_140_2_test SRCS config_fips_140_2_test.cc DEPS tink::signature::internal::config_fips_140_2 tink::signature::internal::key_gen_config_v0 gmock tink::core::configuration tink::core::key_gen_configuration tink::core::keyset_handle tink::core::public_key_sign tink::core::public_key_verify tink::internal::configuration_impl tink::internal::fips_utils tink::internal::key_type_info_store tink::internal::keyset_wrapper_store tink::signature::ecdsa_verify_key_manager tink::signature::ed25519_verify_key_manager tink::signature::rsa_ssa_pkcs1_verify_key_manager tink::signature::rsa_ssa_pss_verify_key_manager tink::signature::signature_key_templates tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) ================================================ FILE: cc/signature/internal/config_fips_140_2.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/internal/config_fips_140_2.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/configuration.h" #include "tink/internal/configuration_impl.h" #include "tink/internal/fips_utils.h" #include "tink/signature/ecdsa_sign_key_manager.h" #include "tink/signature/ecdsa_verify_key_manager.h" #include "tink/signature/public_key_sign_wrapper.h" #include "tink/signature/public_key_verify_wrapper.h" #include "tink/signature/rsa_ssa_pkcs1_sign_key_manager.h" #include "tink/signature/rsa_ssa_pkcs1_verify_key_manager.h" #include "tink/signature/rsa_ssa_pss_sign_key_manager.h" #include "tink/signature/rsa_ssa_pss_verify_key_manager.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { util::Status AddSignatureFips140_2(Configuration& config) { if (!IsFipsEnabledInSsl()) { return util::Status(absl::StatusCode::kFailedPrecondition, "BoringSSL must be in FIPS mode."); } util::Status status = ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config); if (!status.ok()) { return status; } status = ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config); if (!status.ok()) { return status; } status = ConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config); if (!status.ok()) { return status; } status = ConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config); if (!status.ok()) { return status; } return ConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/internal/config_fips_140_2.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_INTERNAL_CONFIG_FIPS_140_2_H_ #define TINK_SIGNATURE_INTERNAL_CONFIG_FIPS_140_2_H_ #include "tink/configuration.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { // Add FIPS 140-2-compliant Signature primitive wrappers and key managers to // `config`, used to generate primitives. util::Status AddSignatureFips140_2(Configuration& config); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_INTERNAL_CONFIG_FIPS_140_2_H_ ================================================ FILE: cc/signature/internal/config_fips_140_2_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/internal/config_fips_140_2.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/configuration.h" #include "tink/internal/configuration_impl.h" #include "tink/internal/fips_utils.h" #include "tink/internal/key_type_info_store.h" #include "tink/internal/keyset_wrapper_store.h" #include "tink/key_gen_configuration.h" #include "tink/keyset_handle.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/signature/ecdsa_verify_key_manager.h" #include "tink/signature/ed25519_verify_key_manager.h" #include "tink/signature/internal/key_gen_config_v0.h" #include "tink/signature/rsa_ssa_pkcs1_verify_key_manager.h" #include "tink/signature/rsa_ssa_pss_verify_key_manager.h" #include "tink/signature/signature_key_templates.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::google::crypto::tink::KeyTemplate; using ::testing::Not; using ::testing::TestWithParam; using ::testing::Values; TEST(SignatureV0Test, Fips) { if (IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only test in non-FIPS mode"; } Configuration config; EXPECT_THAT(AddSignatureFips140_2(config), Not(IsOk())); } TEST(SignatureV0Test, PrimitiveWrappers) { if (!IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only test in FIPS mode"; } Configuration config; ASSERT_THAT(AddSignatureFips140_2(config), IsOk()); util::StatusOr store = ConfigurationImpl::GetKeysetWrapperStore(config); ASSERT_THAT(store, IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); } TEST(SignatureV0Test, KeyManagers) { if (!IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only test in FIPS mode"; } Configuration config; ASSERT_THAT(AddSignatureFips140_2(config), IsOk()); util::StatusOr store = ConfigurationImpl::GetKeyTypeInfoStore(config); ASSERT_THAT(store, IsOk()); EXPECT_THAT((*store)->Get(EcdsaVerifyKeyManager().get_key_type()), IsOk()); EXPECT_THAT((*store)->Get(RsaSsaPkcs1VerifyKeyManager().get_key_type()), IsOk()); EXPECT_THAT((*store)->Get(RsaSsaPssVerifyKeyManager().get_key_type()), IsOk()); EXPECT_THAT((*store)->Get(Ed25519VerifyKeyManager().get_key_type()), Not(IsOk())); } using SignatureV0Test = TestWithParam; INSTANTIATE_TEST_SUITE_P( SignatureV0TestSuite, SignatureV0Test, Values(SignatureKeyTemplates::EcdsaP256(), SignatureKeyTemplates::RsaSsaPkcs13072Sha256F4(), SignatureKeyTemplates::RsaSsaPss3072Sha256Sha256F4())); TEST_P(SignatureV0Test, GetPrimitive) { if (!IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only test in FIPS mode"; } KeyGenConfiguration key_gen_config; ASSERT_THAT(AddSignatureKeyGenV0(key_gen_config), IsOk()); Configuration config; ASSERT_THAT(AddSignatureFips140_2(config), IsOk()); util::StatusOr> handle = KeysetHandle::GenerateNew(GetParam(), key_gen_config); ASSERT_THAT(handle, IsOk()); util::StatusOr> public_handle = (*handle)->GetPublicKeysetHandle(key_gen_config); ASSERT_THAT(public_handle, IsOk()); util::StatusOr> sign = (*handle)->GetPrimitive(config); ASSERT_THAT(sign, IsOk()); util::StatusOr> verify = (*public_handle)->GetPrimitive(config); ASSERT_THAT(verify, IsOk()); std::string data = "data"; util::StatusOr signature = (*sign)->Sign(data); ASSERT_THAT(signature, IsOk()); EXPECT_THAT((*verify)->Verify(*signature, data), IsOk()); } TEST(SignatureV0Test, GetPrimitiveNonFips1402KeyTypeFails) { if (!IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only test in FIPS mode"; } KeyGenConfiguration key_gen_config; ASSERT_THAT(AddSignatureKeyGenV0(key_gen_config), IsOk()); Configuration config; ASSERT_THAT(AddSignatureFips140_2(config), IsOk()); util::StatusOr> handle = KeysetHandle::GenerateNew(SignatureKeyTemplates::Ed25519(), key_gen_config); ASSERT_THAT(handle, IsOk()); util::StatusOr> public_handle = (*handle)->GetPublicKeysetHandle(key_gen_config); ASSERT_THAT(public_handle, IsOk()); EXPECT_THAT((*handle)->GetPrimitive(config), Not(IsOk())); EXPECT_THAT((*public_handle)->GetPrimitive(config), Not(IsOk())); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/internal/config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/internal/config_v0.h" #include "absl/memory/memory.h" #include "tink/configuration.h" #include "tink/internal/configuration_impl.h" #include "tink/signature/ecdsa_sign_key_manager.h" #include "tink/signature/ecdsa_verify_key_manager.h" #include "tink/signature/ed25519_sign_key_manager.h" #include "tink/signature/ed25519_verify_key_manager.h" #include "tink/signature/public_key_sign_wrapper.h" #include "tink/signature/public_key_verify_wrapper.h" #include "tink/signature/rsa_ssa_pkcs1_sign_key_manager.h" #include "tink/signature/rsa_ssa_pkcs1_verify_key_manager.h" #include "tink/signature/rsa_ssa_pss_sign_key_manager.h" #include "tink/signature/rsa_ssa_pss_verify_key_manager.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { util::Status AddSignatureV0(Configuration& config) { util::Status status = ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config); if (!status.ok()) { return status; } status = ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config); if (!status.ok()) { return status; } status = ConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config); if (!status.ok()) { return status; } status = ConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config); if (!status.ok()) { return status; } status = ConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config); if (!status.ok()) { return status; } return ConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/internal/config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_INTERNAL_CONFIG_V0_H_ #define TINK_SIGNATURE_INTERNAL_CONFIG_V0_H_ #include "tink/configuration.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { // Add recommended Signature primitive wrappers and key managers to `config`, // used to generate primitives. util::Status AddSignatureV0(Configuration& config); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_INTERNAL_CONFIG_V0_H_ ================================================ FILE: cc/signature/internal/config_v0_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/internal/config_v0.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/configuration.h" #include "tink/internal/configuration_impl.h" #include "tink/internal/key_gen_configuration_impl.h" #include "tink/internal/key_type_info_store.h" #include "tink/internal/keyset_wrapper_store.h" #include "tink/key_gen_configuration.h" #include "tink/keyset_handle.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/signature/ecdsa_verify_key_manager.h" #include "tink/signature/ed25519_verify_key_manager.h" #include "tink/signature/internal/key_gen_config_v0.h" #include "tink/signature/rsa_ssa_pkcs1_verify_key_manager.h" #include "tink/signature/rsa_ssa_pss_verify_key_manager.h" #include "tink/signature/signature_key_templates.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::google::crypto::tink::KeyTemplate; using ::testing::TestWithParam; using ::testing::Values; TEST(SignatureV0Test, PrimitiveWrappers) { Configuration config; ASSERT_THAT(AddSignatureV0(config), IsOk()); util::StatusOr store = ConfigurationImpl::GetKeysetWrapperStore(config); ASSERT_THAT(store, IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); } TEST(SignatureV0Test, KeyManagers) { Configuration config; ASSERT_THAT(AddSignatureV0(config), IsOk()); util::StatusOr store = ConfigurationImpl::GetKeyTypeInfoStore(config); ASSERT_THAT(store, IsOk()); KeyGenConfiguration key_gen_config; ASSERT_THAT(AddSignatureKeyGenV0(key_gen_config), IsOk()); util::StatusOr key_gen_store = KeyGenConfigurationImpl::GetKeyTypeInfoStore(key_gen_config); ASSERT_THAT(key_gen_store, IsOk()); for (const KeyTypeInfoStore* s : {*store, *key_gen_store}) { EXPECT_THAT(s->Get(EcdsaVerifyKeyManager().get_key_type()), IsOk()); EXPECT_THAT(s->Get(Ed25519VerifyKeyManager().get_key_type()), IsOk()); EXPECT_THAT(s->Get(RsaSsaPkcs1VerifyKeyManager().get_key_type()), IsOk()); EXPECT_THAT(s->Get(RsaSsaPssVerifyKeyManager().get_key_type()), IsOk()); } } using SignatureV0KeyTypesTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( SignatureV0KeyTypesTestSuite, SignatureV0KeyTypesTest, Values(SignatureKeyTemplates::EcdsaP256(), SignatureKeyTemplates::Ed25519(), SignatureKeyTemplates::RsaSsaPkcs13072Sha256F4(), SignatureKeyTemplates::RsaSsaPss3072Sha256Sha256F4())); TEST_P(SignatureV0KeyTypesTest, GetPrimitive) { KeyGenConfiguration key_gen_config; ASSERT_THAT(AddSignatureKeyGenV0(key_gen_config), IsOk()); Configuration config; ASSERT_THAT(AddSignatureV0(config), IsOk()); util::StatusOr> handle = KeysetHandle::GenerateNew(GetParam(), key_gen_config); ASSERT_THAT(handle, IsOk()); util::StatusOr> public_handle = (*handle)->GetPublicKeysetHandle(key_gen_config); ASSERT_THAT(public_handle, IsOk()); util::StatusOr> sign = (*handle)->GetPrimitive(config); ASSERT_THAT(sign, IsOk()); util::StatusOr> verify = (*public_handle)->GetPrimitive(config); ASSERT_THAT(verify, IsOk()); std::string data = "data"; util::StatusOr signature = (*sign)->Sign(data); ASSERT_THAT(signature, IsOk()); EXPECT_THAT((*verify)->Verify(*signature, data), IsOk()); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/internal/ecdsa_raw_sign_boringssl.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/signature/internal/ecdsa_raw_sign_boringssl.h" #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "openssl/bn.h" #include "openssl/ec.h" #include "openssl/ecdsa.h" #include "openssl/evp.h" #include "tink/internal/bn_util.h" #include "tink/internal/ec_util.h" #include "tink/internal/err_util.h" #include "tink/internal/fips_utils.h" #include "tink/internal/md_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/internal/util.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/subtle_util_boringssl.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { namespace { // Transforms ECDSA DER signature encoding to IEEE_P1363 encoding. // // The IEEE_P1363 signature's format is r || s, where r and s are zero-padded // and have the same size in bytes as the order of the curve. For example, for // NIST P-256 curve, r and s are zero-padded to 32 bytes. // // The DER signature is encoded using ASN.1 // (https://tools.ietf.org/html/rfc5480#appendix-A): ECDSA-Sig-Value :: = // SEQUENCE { r INTEGER, s INTEGER }. In particular, the encoding is: 0x30 || // totalLength || 0x02 || r's length || r || 0x02 || s's length || s. crypto::tink::util::StatusOr DerToIeee(absl::string_view der, const EC_KEY* key) { size_t field_size_in_bytes = (EC_GROUP_get_degree(EC_KEY_get0_group(key)) + 7) / 8; const uint8_t* der_ptr = reinterpret_cast(der.data()); // Note: d2i_ECDSA_SIG is deprecated in BoringSSL, but it isn't in OpenSSL. internal::SslUniquePtr ecdsa( d2i_ECDSA_SIG(nullptr, &der_ptr, der.size())); if (ecdsa == nullptr || der_ptr != reinterpret_cast(der.data() + der.size())) { return util::Status(absl::StatusCode::kInternal, "d2i_ECDSA_SIG failed"); } const BIGNUM* r_bn; const BIGNUM* s_bn; ECDSA_SIG_get0(ecdsa.get(), &r_bn, &s_bn); util::StatusOr r = internal::BignumToString(r_bn, field_size_in_bytes); if (!r.ok()) { return r.status(); } util::StatusOr s = internal::BignumToString(s_bn, field_size_in_bytes); if (!s.ok()) { return s.status(); } return absl::StrCat(*r, *s); } } // namespace // static util::StatusOr> EcdsaRawSignBoringSsl::New(const subtle::SubtleUtilBoringSSL::EcKey& ec_key, subtle::EcdsaSignatureEncoding encoding) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) return status; // Check curve. util::StatusOr> group = internal::EcGroupFromCurveType(ec_key.curve); if (!group.ok()) { return group.status(); } internal::SslUniquePtr key(EC_KEY_new()); EC_KEY_set_group(key.get(), group->get()); // Check key. util::StatusOr> pub_key = internal::GetEcPoint(ec_key.curve, ec_key.pub_x, ec_key.pub_y); if (!pub_key.ok()) { return pub_key.status(); } if (!EC_KEY_set_public_key(key.get(), pub_key->get())) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid public key: ", internal::GetSslErrors())); } internal::SslUniquePtr priv_key( BN_bin2bn(ec_key.priv.data(), ec_key.priv.size(), nullptr)); if (!EC_KEY_set_private_key(key.get(), priv_key.get())) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid private key: ", internal::GetSslErrors())); } return { absl::WrapUnique(new EcdsaRawSignBoringSsl(std::move(key), encoding))}; } util::StatusOr EcdsaRawSignBoringSsl::Sign( absl::string_view data) const { // BoringSSL expects a non-null pointer for data, // regardless of whether the size is 0. data = internal::EnsureStringNonNull(data); // Compute the raw signature. std::vector buffer(ECDSA_size(key_.get())); unsigned int sig_length; if (1 != ECDSA_sign(0 /* unused */, reinterpret_cast(data.data()), data.size(), buffer.data(), &sig_length, key_.get())) { return util::Status(absl::StatusCode::kInternal, "Signing failed."); } if (encoding_ == subtle::EcdsaSignatureEncoding::IEEE_P1363) { auto status_or_sig = DerToIeee( absl::string_view(reinterpret_cast(buffer.data()), sig_length), key_.get()); if (!status_or_sig.ok()) { return status_or_sig.status(); } return status_or_sig.value(); } return std::string(reinterpret_cast(buffer.data()), sig_length); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/internal/ecdsa_raw_sign_boringssl.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_INTERNAL_ECDSA_RAW_SIGN_BORINGSSL_H_ #define TINK_SIGNATURE_INTERNAL_ECDSA_RAW_SIGN_BORINGSSL_H_ #include #include #include #include "absl/strings/string_view.h" #include "openssl/ec.h" #include "openssl/evp.h" #include "tink/internal/ec_util.h" #include "tink/internal/fips_utils.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/public_key_sign.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/subtle_util_boringssl.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace internal { // ECDSA raw signing using Boring SSL, generating signatures in DER-encoding. class EcdsaRawSignBoringSsl : public PublicKeySign { public: static crypto::tink::util::StatusOr> New(const crypto::tink::internal::EcKey& ec_key, subtle::EcdsaSignatureEncoding encoding); // Computes the signature for 'data'. crypto::tink::util::StatusOr Sign( absl::string_view data) const override; static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kRequiresBoringCrypto; private: EcdsaRawSignBoringSsl(internal::SslUniquePtr key, subtle::EcdsaSignatureEncoding encoding) : key_(std::move(key)), encoding_(encoding) {} internal::SslUniquePtr key_; subtle::EcdsaSignatureEncoding encoding_; }; } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_INTERNAL_ECDSA_RAW_SIGN_BORINGSSL_H_ ================================================ FILE: cc/signature/internal/ecdsa_raw_sign_boringssl_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/internal/ecdsa_raw_sign_boringssl.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/internal/ec_util.h" #include "tink/internal/fips_utils.h" #include "tink/internal/md_util.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/ecdsa_verify_boringssl.h" #include "tink/subtle/subtle_util_boringssl.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::Not; using ::testing::SizeIs; util::StatusOr ComputeDigest(subtle::HashType hash_type, absl::string_view data) { util::StatusOr hash = internal::EvpHashFromHashType(hash_type); if (!hash.ok()) return hash.status(); unsigned int digest_size; uint8_t digest[EVP_MAX_MD_SIZE]; if (1 != EVP_Digest(data.data(), data.size(), digest, &digest_size, *hash, nullptr)) { return util::Status(absl::StatusCode::kInternal, "Could not compute digest."); } return std::string(reinterpret_cast(digest), digest_size); } TEST(EcdsaRawSignBoringSslTest, VerifySignature) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test is skipped if kOnlyUseFips but BoringCrypto is unavailable."; } subtle::EcdsaSignatureEncoding encodings[2] = { subtle::EcdsaSignatureEncoding::DER, subtle::EcdsaSignatureEncoding::IEEE_P1363}; for (subtle::EcdsaSignatureEncoding encoding : encodings) { util::StatusOr ec_key = subtle::SubtleUtilBoringSSL::GetNewEcKey( subtle::EllipticCurveType::NIST_P256); ASSERT_THAT(ec_key, IsOk()); util::StatusOr> signer = EcdsaRawSignBoringSsl::New(*ec_key, encoding); ASSERT_THAT(signer, IsOk()); util::StatusOr> verifier = subtle::EcdsaVerifyBoringSsl::New(*ec_key, subtle::HashType::SHA256, encoding); ASSERT_THAT(verifier, IsOk()); std::string message = "some data to be signed"; util::StatusOr message_digest = ComputeDigest(subtle::HashType::SHA256, message); ASSERT_THAT(message_digest, IsOk()); util::StatusOr signature = (*signer)->Sign(*message_digest); ASSERT_THAT(signature, IsOkAndHolds(Not(Eq(message)))); EXPECT_THAT((*verifier)->Verify(*signature, message), IsOk()); } } TEST(EcdsaRawSignBoringSslTest, VerifySignatureWithEmptyMessage) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test is skipped if kOnlyUseFips but BoringCrypto is unavailable."; } subtle::EcdsaSignatureEncoding encodings[2] = { subtle::EcdsaSignatureEncoding::DER, subtle::EcdsaSignatureEncoding::IEEE_P1363}; for (subtle::EcdsaSignatureEncoding encoding : encodings) { util::StatusOr ec_key = subtle::SubtleUtilBoringSSL::GetNewEcKey( subtle::EllipticCurveType::NIST_P256); ASSERT_THAT(ec_key, IsOk()); util::StatusOr> signer = EcdsaRawSignBoringSsl::New(*ec_key, encoding); ASSERT_THAT(signer, IsOk()); util::StatusOr> verifier = subtle::EcdsaVerifyBoringSsl::New(*ec_key, subtle::HashType::SHA256, encoding); ASSERT_THAT(verifier, IsOk()); // Message is a null string_view. const absl::string_view empty_message; util::StatusOr empty_message_digest = ComputeDigest(subtle::HashType::SHA256, empty_message); ASSERT_THAT(empty_message_digest, IsOk()); util::StatusOr empty_msg_signature = (*signer)->Sign(*empty_message_digest); ASSERT_THAT(empty_msg_signature, IsOkAndHolds(Not(Eq(empty_message)))); EXPECT_THAT((*verifier)->Verify(*empty_msg_signature, empty_message), IsOk()); } } TEST(EcdsaRawSignBoringSslTest, VerifyFailsWithInvalidMessageOrSignature) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test is skipped if kOnlyUseFips but BoringCrypto is unavailable."; } subtle::EcdsaSignatureEncoding encodings[2] = { subtle::EcdsaSignatureEncoding::DER, subtle::EcdsaSignatureEncoding::IEEE_P1363}; for (subtle::EcdsaSignatureEncoding encoding : encodings) { util::StatusOr ec_key = subtle::SubtleUtilBoringSSL::GetNewEcKey( subtle::EllipticCurveType::NIST_P256); ASSERT_THAT(ec_key, IsOk()); util::StatusOr> signer = EcdsaRawSignBoringSsl::New(*ec_key, encoding); ASSERT_THAT(signer, IsOk()); util::StatusOr> verifier = subtle::EcdsaVerifyBoringSsl::New(*ec_key, subtle::HashType::SHA256, encoding); ASSERT_THAT(verifier, IsOk()); std::string message = "some data to be signed"; util::StatusOr message_digest = ComputeDigest(subtle::HashType::SHA256, message); ASSERT_THAT(message_digest, IsOk()); util::StatusOr signature = (*signer)->Sign(*message_digest); ASSERT_THAT(signature, IsOkAndHolds(Not(Eq(message)))); EXPECT_THAT((*verifier)->Verify(*signature, message), IsOk()); EXPECT_THAT((*verifier)->Verify("some bad signature", message), Not(IsOk())); EXPECT_THAT((*verifier)->Verify(*signature, "some bad message"), Not(IsOk())); } } TEST(EcdsaRawSignBoringSslTest, VerifyFailsWhenEncodingDoesNotMatch) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test is skipped if kOnlyUseFips but BoringCrypto is unavailable."; } subtle::EcdsaSignatureEncoding encodings[2] = { subtle::EcdsaSignatureEncoding::DER, subtle::EcdsaSignatureEncoding::IEEE_P1363}; for (subtle::EcdsaSignatureEncoding encoding : encodings) { util::StatusOr ec_key = subtle::SubtleUtilBoringSSL::GetNewEcKey( subtle::EllipticCurveType::NIST_P256); ASSERT_THAT(ec_key, IsOk()); util::StatusOr> signer = EcdsaRawSignBoringSsl::New(*ec_key, encoding); ASSERT_THAT(signer, IsOk()); util::StatusOr> verifier = subtle::EcdsaVerifyBoringSsl::New( *ec_key, subtle::HashType::SHA256, encoding == subtle::EcdsaSignatureEncoding::DER ? subtle::EcdsaSignatureEncoding::IEEE_P1363 : subtle::EcdsaSignatureEncoding::DER); ASSERT_THAT(verifier, IsOk()); std::string message = "some data to be signed"; util::StatusOr message_digest = ComputeDigest(subtle::HashType::SHA256, message); ASSERT_THAT(message_digest, IsOk()); util::StatusOr signature = (*signer)->Sign(*message_digest); ASSERT_THAT(signature, IsOkAndHolds(Not(Eq(message)))); EXPECT_THAT((*verifier)->Verify(*signature, message), Not(IsOk())); } } TEST(EcdsaRawSignBoringSslTest, SignatureSizesAreCorrectWhenUsingIeeeP136Encoding) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test is skipped if kOnlyUseFips but BoringCrypto is unavailable."; } subtle::EllipticCurveType curves[3] = {subtle::EllipticCurveType::NIST_P256, subtle::EllipticCurveType::NIST_P384, subtle::EllipticCurveType::NIST_P521}; for (subtle::EllipticCurveType curve : curves) { util::StatusOr ec_key = subtle::SubtleUtilBoringSSL::GetNewEcKey(curve); ASSERT_THAT(ec_key, IsOk()); util::StatusOr> signer = EcdsaRawSignBoringSsl::New(*ec_key, subtle::EcdsaSignatureEncoding::IEEE_P1363); ASSERT_THAT(signer, IsOk()); util::StatusOr> verifier = subtle::EcdsaVerifyBoringSsl::New( *ec_key, subtle::HashType::SHA256, subtle::EcdsaSignatureEncoding::IEEE_P1363); ASSERT_THAT(verifier, IsOk()); std::string message = "some data to be signed"; util::StatusOr message_digest = ComputeDigest(subtle::HashType::SHA256, message); ASSERT_THAT(message_digest, IsOk()); util::StatusOr signature = (*signer)->Sign(*message_digest); ASSERT_THAT(signature, IsOkAndHolds(Not(Eq(message)))); EXPECT_THAT((*verifier)->Verify(*signature, message), IsOk()); // Check signature size. util::StatusOr field_size_in_bytes = internal::EcFieldSizeInBytes(curve); ASSERT_THAT(field_size_in_bytes, IsOk()); EXPECT_THAT(*signature, SizeIs(2 * (*field_size_in_bytes))); } } TEST(EcdsaRawSignBoringSslTest, CreateFailsWithBadPublicKey) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test is skipped if kOnlyUseFips but BoringCrypto is unavailable."; } util::StatusOr ec_key = subtle::SubtleUtilBoringSSL::GetNewEcKey( subtle::EllipticCurveType::NIST_P256); ASSERT_THAT(ec_key, IsOk()); ec_key->pub_x += "corrupted public key x coordinate"; EXPECT_THAT( EcdsaRawSignBoringSsl::New(*ec_key, subtle::EcdsaSignatureEncoding::DER), Not(IsOk())); } // TODO(bleichen): add Wycheproof tests. // FIPS-only mode test TEST(EcdsaRawSignBoringSslTest, FipsFailWithoutBoringCrypto) { if (!internal::IsFipsModeEnabled() || internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test assumes kOnlyUseFips but BoringCrypto is unavailable."; } util::StatusOr p256_key = subtle::SubtleUtilBoringSSL::GetNewEcKey( subtle::EllipticCurveType::NIST_P256); ASSERT_THAT(p256_key, IsOk()); EXPECT_THAT( EcdsaRawSignBoringSsl::New(*p256_key, subtle::EcdsaSignatureEncoding::DER) .status(), StatusIs(absl::StatusCode::kInternal)); util::StatusOr p384_key = subtle::SubtleUtilBoringSSL::GetNewEcKey( subtle::EllipticCurveType::NIST_P384); ASSERT_THAT(p384_key, IsOk()); EXPECT_THAT( EcdsaRawSignBoringSsl::New(*p384_key, subtle::EcdsaSignatureEncoding::DER) .status(), StatusIs(absl::StatusCode::kInternal)); util::StatusOr p521_key = *subtle::SubtleUtilBoringSSL::GetNewEcKey( subtle::EllipticCurveType::NIST_P521); ASSERT_THAT(p521_key, IsOk()); EXPECT_THAT( EcdsaRawSignBoringSsl::New(*p521_key, subtle::EcdsaSignatureEncoding::DER) .status(), StatusIs(absl::StatusCode::kInternal)); } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/internal/key_gen_config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/internal/key_gen_config_v0.h" #include "absl/memory/memory.h" #include "tink/internal/key_gen_configuration_impl.h" #include "tink/key_gen_configuration.h" #include "tink/signature/ecdsa_sign_key_manager.h" #include "tink/signature/ecdsa_verify_key_manager.h" #include "tink/signature/ed25519_sign_key_manager.h" #include "tink/signature/ed25519_verify_key_manager.h" #include "tink/signature/rsa_ssa_pkcs1_sign_key_manager.h" #include "tink/signature/rsa_ssa_pkcs1_verify_key_manager.h" #include "tink/signature/rsa_ssa_pss_sign_key_manager.h" #include "tink/signature/rsa_ssa_pss_verify_key_manager.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { util::Status AddSignatureKeyGenV0(KeyGenConfiguration& config) { util::Status status = KeyGenConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config); if (!status.ok()) { return status; } status = KeyGenConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config); if (!status.ok()) { return status; } status = KeyGenConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config); if (!status.ok()) { return status; } return KeyGenConfigurationImpl::AddAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), config); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/internal/key_gen_config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_INTERNAL_KEY_GEN_CONFIG_V0_H_ #define TINK_SIGNATURE_INTERNAL_KEY_GEN_CONFIG_V0_H_ #include "tink/key_gen_configuration.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { // Add recommended Signature key managers to `config`, used to generate keys. util::Status AddSignatureKeyGenV0(KeyGenConfiguration& config); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_INTERNAL_KEY_GEN_CONFIG_V0_H_ ================================================ FILE: cc/signature/key_gen_config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/key_gen_config_v0.h" #include "absl/log/check.h" #include "tink/key_gen_configuration.h" #include "tink/signature/internal/key_gen_config_v0.h" namespace crypto { namespace tink { const KeyGenConfiguration& KeyGenConfigSignatureV0() { static const KeyGenConfiguration* instance = [] { static KeyGenConfiguration* config = new KeyGenConfiguration(); CHECK_OK(internal::AddSignatureKeyGenV0(*config)); return config; }(); return *instance; } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/key_gen_config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_KEY_GEN_CONFIG_V0_H_ #define TINK_SIGNATURE_KEY_GEN_CONFIG_V0_H_ #include "tink/key_gen_configuration.h" namespace crypto { namespace tink { // KeyGenConfiguration used to generate Signature keys with recommended key // managers. const KeyGenConfiguration& KeyGenConfigSignatureV0(); } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_KEY_GEN_CONFIG_V0_H_ ================================================ FILE: cc/signature/public_key_sign_factory.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/signature/public_key_sign_factory.h" #include #include "tink/key_manager.h" #include "tink/keyset_handle.h" #include "tink/public_key_sign.h" #include "tink/registry.h" #include "tink/signature/public_key_sign_wrapper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // NOLINTBEGIN(whitespace/line_length) (Formatted when commented in) // TINK-PENDING-REMOVAL-IN-3.0.0-START // static util::StatusOr> PublicKeySignFactory::GetPrimitive(const KeysetHandle& keyset_handle) { util::Status status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) { return status; } return keyset_handle.GetPrimitive( ConfigGlobalRegistry()); } // static util::StatusOr> PublicKeySignFactory::GetPrimitive( const KeysetHandle& keyset_handle, const KeyManager* custom_key_manager) { util::Status status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) { return status; } return keyset_handle.GetPrimitive(custom_key_manager); } // TINK-PENDING-REMOVAL-IN-3.0.0-END // NOLINTEND(whitespace/line_length) } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/public_key_sign_factory.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_PUBLIC_KEY_SIGN_FACTORY_H_ #define TINK_SIGNATURE_PUBLIC_KEY_SIGN_FACTORY_H_ #include #include "absl/base/macros.h" #include "tink/key_manager.h" #include "tink/keyset_handle.h" #include "tink/public_key_sign.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // This class is deprecated. Call keyset_handle->GetPrimitive() // instead. // // Note that in order to for this change to be safe, the AeadSetWrapper has to // be registered in your binary before this call. This happens automatically if // you call one of // * SignatureConfig::Register() // * TinkConfig::Register() // NOLINTBEGIN(whitespace/line_length) (Formatted when commented in) // TINK-PENDING-REMOVAL-IN-3.0.0-START class ABSL_DEPRECATED( "Call getPrimitive() on the keyset_handle after registering " "the PublicKeySignWrapper instead.") PublicKeySignFactory { public: // Returns a PublicKeySign-primitive that uses key material from the keyset // specified via 'keyset_handle'. static crypto::tink::util::StatusOr> GetPrimitive(const KeysetHandle& keyset_handle); // Returns a PublicKeySign-primitive that uses key material from the keyset // specified via 'keyset_handle' and is instantiated by the given // 'custom_key_manager' (instead of the key manager from the Registry). static crypto::tink::util::StatusOr> GetPrimitive(const KeysetHandle& keyset_handle, const KeyManager* custom_key_manager); private: PublicKeySignFactory() {} }; // TINK-PENDING-REMOVAL-IN-3.0.0-END // NOLINTEND(whitespace/line_length) } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_PUBLIC_KEY_SIGN_FACTORY_H_ ================================================ FILE: cc/signature/public_key_sign_factory_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/public_key_sign_factory.h" #include #include #include "gtest/gtest.h" #include "tink/crypto_format.h" #include "tink/keyset_handle.h" #include "tink/public_key_sign.h" #include "tink/registry.h" #include "tink/signature/ecdsa_sign_key_manager.h" #include "tink/signature/signature_config.h" #include "tink/util/status.h" #include "tink/util/test_keyset_handle.h" #include "tink/util/test_util.h" #include "proto/ecdsa.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { // NOLINTBEGIN(whitespace/line_length) (Formatted when commented in) // TINK-PENDING-REMOVAL-IN-3.0.0-START using crypto::tink::test::AddTinkKey; using google::crypto::tink::EcdsaPrivateKey; using google::crypto::tink::EcdsaSignatureEncoding; using google::crypto::tink::EllipticCurveType; using google::crypto::tink::HashType; using google::crypto::tink::KeyData; using google::crypto::tink::Keyset; using google::crypto::tink::KeyStatusType; class PublicKeySignFactoryTest : public ::testing::Test { protected: void SetUp() override { auto status = SignatureConfig::Register(); ASSERT_TRUE(status.ok()) << status; } }; EcdsaPrivateKey GetNewEcdsaPrivateKey() { return test::GetEcdsaTestPrivateKey(EllipticCurveType::NIST_P256, HashType::SHA256, EcdsaSignatureEncoding::DER); } TEST_F(PublicKeySignFactoryTest, testBasic) { Keyset keyset; auto public_key_sign_result = PublicKeySignFactory::GetPrimitive( *TestKeysetHandle::GetKeysetHandle(keyset)); EXPECT_FALSE(public_key_sign_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, public_key_sign_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "at least one key", std::string(public_key_sign_result.status().message())); } TEST_F(PublicKeySignFactoryTest, testPrimitive) { // Prepare a Keyset. Keyset keyset; std::string key_type = "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey"; uint32_t key_id_1 = 1234543; AddTinkKey(key_type, key_id_1, GetNewEcdsaPrivateKey(), KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PUBLIC, &keyset); uint32_t key_id_2 = 726329; AddTinkKey(key_type, key_id_2, GetNewEcdsaPrivateKey(), KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PUBLIC, &keyset); uint32_t key_id_3 = 7213743; AddTinkKey(key_type, key_id_3, GetNewEcdsaPrivateKey(), KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PUBLIC, &keyset); keyset.set_primary_key_id(key_id_3); // Create a KeysetHandle and use it with the factory. auto public_key_sign_result = PublicKeySignFactory::GetPrimitive( *TestKeysetHandle::GetKeysetHandle(keyset)); EXPECT_TRUE(public_key_sign_result.ok()) << public_key_sign_result.status(); auto public_key_sign = std::move(public_key_sign_result.value()); std::string data = "some data to sign"; auto sign_result = public_key_sign->Sign(data); EXPECT_TRUE(sign_result.ok()) << sign_result.status(); EXPECT_NE(data, sign_result.value()); } // TINK-PENDING-REMOVAL-IN-3.0.0-END // NOLINTEND(whitespace/line_length) } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/public_key_sign_wrapper.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/signature/public_key_sign_wrapper.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/crypto_format.h" #include "tink/internal/monitoring_util.h" #include "tink/internal/registry_impl.h" #include "tink/internal/util.h" #include "tink/monitoring/monitoring.h" #include "tink/primitive_set.h" #include "tink/public_key_sign.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using google::crypto::tink::OutputPrefixType; namespace { constexpr absl::string_view kPrimitive = "public_key_sign"; constexpr absl::string_view kSignApi = "sign"; util::Status Validate(PrimitiveSet* public_key_sign_set) { if (public_key_sign_set == nullptr) { return util::Status(absl::StatusCode::kInternal, "public_key_sign_set must be non-NULL"); } if (public_key_sign_set->get_primary() == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "public_key_sign_set has no primary"); } return util::OkStatus(); } class PublicKeySignSetWrapper : public PublicKeySign { public: explicit PublicKeySignSetWrapper( std::unique_ptr> public_key_sign_set, std::unique_ptr monitoring_sign_client = nullptr) : public_key_sign_set_(std::move(public_key_sign_set)), monitoring_sign_client_(std::move(monitoring_sign_client)) {} crypto::tink::util::StatusOr Sign( absl::string_view data) const override; ~PublicKeySignSetWrapper() override = default; private: std::unique_ptr> public_key_sign_set_; std::unique_ptr monitoring_sign_client_; }; util::StatusOr PublicKeySignSetWrapper::Sign( absl::string_view data) const { // BoringSSL expects a non-null pointer for data, // regardless of whether the size is 0. data = internal::EnsureStringNonNull(data); auto primary = public_key_sign_set_->get_primary(); std::string local_data; if (primary->get_output_prefix_type() == OutputPrefixType::LEGACY) { local_data = std::string(data); local_data.append(1, CryptoFormat::kLegacyStartByte); data = local_data; } auto sign_result = primary->get_primitive().Sign(data); if (!sign_result.ok()) { if (monitoring_sign_client_ != nullptr) { monitoring_sign_client_->LogFailure(); } return sign_result.status(); } if (monitoring_sign_client_ != nullptr) { monitoring_sign_client_->Log( public_key_sign_set_->get_primary()->get_key_id(), data.size()); } const std::string& key_id = primary->get_identifier(); return key_id + sign_result.value(); } } // anonymous namespace util::StatusOr> PublicKeySignWrapper::Wrap( std::unique_ptr> primitive_set) const { util::Status status = Validate(primitive_set.get()); if (!status.ok()) return status; MonitoringClientFactory* const monitoring_factory = internal::RegistryImpl::GlobalInstance().GetMonitoringClientFactory(); // Monitoring is not enabled. Create a wrapper without monitoring clients. if (monitoring_factory == nullptr) { return { absl::make_unique(std::move(primitive_set))}; } util::StatusOr keyset_info = internal::MonitoringKeySetInfoFromPrimitiveSet(*primitive_set); if (!keyset_info.ok()) { return keyset_info.status(); } util::StatusOr> monitoring_sign_client = monitoring_factory->New( MonitoringContext(kPrimitive, kSignApi, *keyset_info)); if (!monitoring_sign_client.ok()) { return monitoring_sign_client.status(); } return {absl::make_unique( std::move(primitive_set), *std::move(monitoring_sign_client))}; } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/public_key_sign_wrapper.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_PUBLIC_KEY_SIGN_WRAPPER_H_ #define TINK_SIGNATURE_PUBLIC_KEY_SIGN_WRAPPER_H_ #include #include "absl/strings/string_view.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/public_key_sign.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // Wraps a set of PublicKeySign-instances that correspond to a keyset, // and combines them into a single PublicKeySign-primitive, // that for the actual verification uses the instance that matches the // signature prefix. class PublicKeySignWrapper : public PrimitiveWrapper { public: // Returns an PublicKeySign-primitive that uses the primary // PublicKeySign-instance provided in 'public_key_sign_set', // which must be non-NULL (and must contain a primary instance). crypto::tink::util::StatusOr> Wrap( std::unique_ptr> primitive_set) const override; }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_PUBLIC_KEY_SIGN_WRAPPER_H_ ================================================ FILE: cc/signature/public_key_sign_wrapper_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/public_key_sign_wrapper.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_map.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/crypto_format.h" #include "tink/internal/registry_impl.h" #include "tink/monitoring/monitoring.h" #include "tink/monitoring/monitoring_client_mocks.h" #include "tink/primitive_set.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/registry.h" #include "tink/signature/failing_signature.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" using ::crypto::tink::test::DummyPublicKeySign; using ::crypto::tink::test::DummyPublicKeyVerify; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::KeysetInfo; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::OutputPrefixType; using ::testing::_; using ::testing::ByMove; using ::testing::IsNull; using ::testing::StrictMock; using ::testing::Not; using ::testing::NotNull; using ::testing::Return; using ::testing::Test; namespace crypto { namespace tink { namespace { TEST(PublicKeySignSetWrapperTest, TestBasic) { { // pk_sign_set is nullptr. auto pk_sign_result = PublicKeySignWrapper().Wrap(/*primitive_set=*/nullptr); EXPECT_FALSE(pk_sign_result.ok()); EXPECT_EQ(absl::StatusCode::kInternal, pk_sign_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "non-NULL", std::string(pk_sign_result.status().message())); } { // pk_sign_set has no primary primitive. auto pk_sign_set = absl::make_unique>(); auto pk_sign_result = PublicKeySignWrapper().Wrap(std::move(pk_sign_set)); EXPECT_FALSE(pk_sign_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, pk_sign_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "no primary", std::string(pk_sign_result.status().message())); } { // Correct pk_sign_set; KeysetInfo::KeyInfo* key_info; KeysetInfo keyset_info; uint32_t key_id_0 = 1234543; key_info = keyset_info.add_key_info(); key_info->set_output_prefix_type(OutputPrefixType::TINK); key_info->set_key_id(key_id_0); key_info->set_status(KeyStatusType::ENABLED); uint32_t key_id_1 = 726329; key_info = keyset_info.add_key_info(); key_info->set_output_prefix_type(OutputPrefixType::LEGACY); key_info->set_key_id(key_id_1); key_info->set_status(KeyStatusType::ENABLED); uint32_t key_id_2 = 7213743; key_info = keyset_info.add_key_info(); key_info->set_output_prefix_type(OutputPrefixType::RAW); key_info->set_key_id(key_id_2); key_info->set_status(KeyStatusType::ENABLED); std::string signature_name_0 = "signature_0"; std::string signature_name_1 = "signature_1"; std::string signature_name_2 = "signature_2"; std::unique_ptr> pk_sign_set( new PrimitiveSet()); std::unique_ptr pk_sign( new DummyPublicKeySign(signature_name_0)); auto entry_result = pk_sign_set->AddPrimitive(std::move(pk_sign), keyset_info.key_info(0)); ASSERT_THAT(entry_result, IsOk()); pk_sign = absl::make_unique(signature_name_1); entry_result = pk_sign_set->AddPrimitive(std::move(pk_sign), keyset_info.key_info(1)); ASSERT_TRUE(entry_result.ok()); pk_sign = absl::make_unique(signature_name_2); entry_result = pk_sign_set->AddPrimitive(std::move(pk_sign), keyset_info.key_info(2)); ASSERT_TRUE(entry_result.ok()); // The last key is the primary. ASSERT_THAT(pk_sign_set->set_primary(entry_result.value()), IsOk()); // Wrap pk_sign_set and test the resulting PublicKeySign. auto pk_sign_result = PublicKeySignWrapper().Wrap(std::move(pk_sign_set)); EXPECT_TRUE(pk_sign_result.ok()) << pk_sign_result.status(); pk_sign = std::move(pk_sign_result.value()); std::string data = "some data to sign"; auto sign_result = pk_sign->Sign(data); EXPECT_TRUE(sign_result.ok()) << sign_result.status(); std::string signature = sign_result.value(); std::unique_ptr pk_verify( new DummyPublicKeyVerify(signature_name_2)); auto verify_status = pk_verify->Verify(signature, data); EXPECT_TRUE(verify_status.ok()) << verify_status; } } TEST(PublicKeySignSetWrapperTest, TestLegacySignatures) { // Prepare a set for the wrapper. KeysetInfo::KeyInfo key; uint32_t key_id = 1234543; key.set_output_prefix_type(OutputPrefixType::LEGACY); key.set_key_id(key_id); key.set_status(KeyStatusType::ENABLED); std::string signature_name = "SomeLegacySignatures"; std::unique_ptr> pk_sign_set( new PrimitiveSet()); std::string data = "Some data to sign"; std::unique_ptr pk_sign( new DummyPublicKeySign(signature_name)); auto entry_result = pk_sign_set->AddPrimitive(std::move(pk_sign), key); ASSERT_THAT(entry_result, IsOk()); ASSERT_THAT(pk_sign_set->set_primary(entry_result.value()), IsOk()); // Wrap pk_sign_set and test the resulting PublicKeySign. auto pk_sign_result = PublicKeySignWrapper().Wrap(std::move(pk_sign_set)); EXPECT_TRUE(pk_sign_result.ok()) << pk_sign_result.status(); pk_sign = std::move(pk_sign_result.value()); // Compute the signature via wrapper. auto sign_result = pk_sign->Sign(data); EXPECT_THAT(sign_result, IsOk()); std::string signature = sign_result.value(); EXPECT_PRED_FORMAT2(testing::IsSubstring, signature_name, signature); // Try verifying on raw PublicKeyVerify-primitive using original data. std::unique_ptr raw_pk_verify( new DummyPublicKeyVerify(signature_name)); std::string raw_signature = signature.substr(CryptoFormat::kNonRawPrefixSize); auto status = raw_pk_verify->Verify(raw_signature, data); EXPECT_FALSE(status.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, status.code()); // Verify on raw PublicKeyVerify-primitive using legacy-formatted data. std::string legacy_data = data; legacy_data.append(1, CryptoFormat::kLegacyStartByte); status = raw_pk_verify->Verify(raw_signature, legacy_data); EXPECT_TRUE(status.ok()) << status; } KeysetInfo::KeyInfo PopulateKeyInfo(uint32_t key_id, OutputPrefixType out_prefix_type, KeyStatusType status) { KeysetInfo::KeyInfo key_info; key_info.set_output_prefix_type(out_prefix_type); key_info.set_key_id(key_id); key_info.set_status(status); return key_info; } // Creates a test keyset info object. KeysetInfo CreateTestKeysetInfo() { KeysetInfo keyset_info; *keyset_info.add_key_info() = PopulateKeyInfo(/*key_id=*/1234543, OutputPrefixType::TINK, /*status=*/KeyStatusType::ENABLED); *keyset_info.add_key_info() = PopulateKeyInfo(/*key_id=*/726329, OutputPrefixType::LEGACY, /*status=*/KeyStatusType::ENABLED); *keyset_info.add_key_info() = PopulateKeyInfo(/*key_id=*/7213743, OutputPrefixType::TINK, /*status=*/KeyStatusType::ENABLED); return keyset_info; } // Tests for the monitoring behavior. class PublicKeySignSetWrapperWithMonitoringTest : public Test { protected: // Perform some common initialization: reset the global registry, set expected // calls for the mock monitoring factory and the returned clients. void SetUp() override { Registry::Reset(); // Setup mocks for catching Monitoring calls. auto monitoring_client_factory = absl::make_unique(); auto sign_monitoring_client = absl::make_unique>(); sign_monitoring_client_ = sign_monitoring_client.get(); // Monitoring tests expect that the client factory will create the // corresponding MockMonitoringClients. EXPECT_CALL(*monitoring_client_factory, New(_)) .WillOnce( Return(ByMove(util::StatusOr>( std::move(sign_monitoring_client))))); ASSERT_THAT(internal::RegistryImpl::GlobalInstance() .RegisterMonitoringClientFactory( std::move(monitoring_client_factory)), IsOk()); ASSERT_THAT( internal::RegistryImpl::GlobalInstance().GetMonitoringClientFactory(), Not(IsNull())); } // Cleanup the registry to avoid mock leaks. ~PublicKeySignSetWrapperWithMonitoringTest() override { Registry::Reset(); } MockMonitoringClient* sign_monitoring_client_; }; // Test that successful sign operations are logged. TEST_F(PublicKeySignSetWrapperWithMonitoringTest, WrapKeysetWithMonitoringSignSuccess) { // Create a primitive set and fill it with some entries KeysetInfo keyset_info = CreateTestKeysetInfo(); const absl::flat_hash_map kAnnotations = { {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}}; auto public_key_sign_primitive_set = absl::make_unique>(kAnnotations); ASSERT_THAT(public_key_sign_primitive_set ->AddPrimitive(absl::make_unique("sign0"), keyset_info.key_info(0)) .status(), IsOk()); ASSERT_THAT(public_key_sign_primitive_set ->AddPrimitive(absl::make_unique("sign1"), keyset_info.key_info(1)) .status(), IsOk()); // Set the last as primary. util::StatusOr::Entry*> last = public_key_sign_primitive_set->AddPrimitive( absl::make_unique("sign2"), keyset_info.key_info(2)); ASSERT_THAT(last, IsOk()); ASSERT_THAT(public_key_sign_primitive_set->set_primary(*last), IsOk()); // Record the ID of the primary key. const uint32_t kPrimaryKeyId = keyset_info.key_info(2).key_id(); // Create a PublicKeySign primitive and sign some data. util::StatusOr> public_key_sign = PublicKeySignWrapper().Wrap(std::move(public_key_sign_primitive_set)); ASSERT_THAT(public_key_sign, IsOkAndHolds(NotNull())); constexpr absl::string_view kMessage = "This is some message!"; // Check that calling Sign triggers a Log() call. EXPECT_CALL(*sign_monitoring_client_, Log(kPrimaryKeyId, kMessage.size())); EXPECT_THAT((*public_key_sign)->Sign(kMessage), IsOk()); } TEST_F(PublicKeySignSetWrapperWithMonitoringTest, WrapKeysetWithMonitoringSignFailures) { // Create a primitive set and fill it with some entries KeysetInfo keyset_info = CreateTestKeysetInfo(); const absl::flat_hash_map kAnnotations = { {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}}; auto public_key_sign_primitive_set = absl::make_unique>(kAnnotations); ASSERT_THAT(public_key_sign_primitive_set ->AddPrimitive(CreateAlwaysFailingPublicKeySign("sign0"), keyset_info.key_info(0)) .status(), IsOk()); ASSERT_THAT(public_key_sign_primitive_set ->AddPrimitive(CreateAlwaysFailingPublicKeySign("sign1"), keyset_info.key_info(1)) .status(), IsOk()); // Set the last as primary. util::StatusOr::Entry*> last = public_key_sign_primitive_set->AddPrimitive( CreateAlwaysFailingPublicKeySign("sign2"), keyset_info.key_info(2)); ASSERT_THAT(last, IsOk()); ASSERT_THAT(public_key_sign_primitive_set->set_primary(*last), IsOk()); // Create a PublicKeySign and sign some data. util::StatusOr> public_key_sign = PublicKeySignWrapper().Wrap(std::move(public_key_sign_primitive_set)); ASSERT_THAT(public_key_sign, IsOkAndHolds(NotNull())); constexpr absl::string_view kPlaintext = "This is some message!"; // Check that calling Sign triggers a LogFailure() call. EXPECT_CALL(*sign_monitoring_client_, LogFailure()); EXPECT_THAT((*public_key_sign)->Sign(kPlaintext).status(), StatusIs(absl::StatusCode::kInternal)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/public_key_verify_factory.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/signature/public_key_verify_factory.h" #include #include "tink/key_manager.h" #include "tink/keyset_handle.h" #include "tink/public_key_verify.h" #include "tink/registry.h" #include "tink/signature/public_key_verify_wrapper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // NOLINTBEGIN(whitespace/line_length) (Formatted when commented in) // TINK-PENDING-REMOVAL-IN-3.0.0-START // static util::StatusOr> PublicKeyVerifyFactory::GetPrimitive(const KeysetHandle& keyset_handle) { util::Status status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) { return status; } return keyset_handle.GetPrimitive( ConfigGlobalRegistry()); } // static util::StatusOr> PublicKeyVerifyFactory::GetPrimitive( const KeysetHandle& keyset_handle, const KeyManager* custom_key_manager) { util::Status status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) { return status; } return keyset_handle.GetPrimitive(custom_key_manager); } // TINK-PENDING-REMOVAL-IN-3.0.0-END // NOLINTEND(whitespace/line_length) } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/public_key_verify_factory.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_PUBLIC_KEY_VERIFY_FACTORY_H_ #define TINK_SIGNATURE_PUBLIC_KEY_VERIFY_FACTORY_H_ #include #include "absl/base/macros.h" #include "tink/key_manager.h" #include "tink/keyset_handle.h" #include "tink/public_key_verify.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // This class is deprecated. Call keyset_handle->GetPrimitive() // instead. // // Note that in order to for this change to be safe, the AeadSetWrapper has to // be registered in your binary before this call. This happens automatically if // you call one of // * SignatureConfig::Register() // * TinkConfig::Register() // NOLINTBEGIN(whitespace/line_length) (Formatted when commented in) // TINK-PENDING-REMOVAL-IN-3.0.0-START class ABSL_DEPRECATED( "Call getPrimitive() on the keyset_handle after " "registering the PublicKeyVerifyWrapper instead.") PublicKeyVerifyFactory { public: // Returns a PublicKeyVerify-primitive that uses key material from the keyset // specified via 'keyset_handle'. static crypto::tink::util::StatusOr> GetPrimitive(const KeysetHandle& keyset_handle); // Returns a PublicKeyVerify-primitive that uses key material from the keyset // specified via 'keyset_handle' and is instantiated by the given // 'custom_key_manager' (instead of the key manager from the Registry). static crypto::tink::util::StatusOr> GetPrimitive(const KeysetHandle& keyset_handle, const KeyManager* custom_key_manager); private: PublicKeyVerifyFactory() {} }; // TINK-PENDING-REMOVAL-IN-3.0.0-END // NOLINTEND(whitespace/line_length) } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_PUBLIC_KEY_VERIFY_FACTORY_H_ ================================================ FILE: cc/signature/public_key_verify_factory_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/public_key_verify_factory.h" #include #include #include "gtest/gtest.h" #include "tink/crypto_format.h" #include "tink/keyset_handle.h" #include "tink/public_key_verify.h" #include "tink/registry.h" #include "tink/signature/ecdsa_verify_key_manager.h" #include "tink/signature/signature_config.h" #include "tink/util/status.h" #include "tink/util/test_keyset_handle.h" #include "tink/util/test_util.h" #include "proto/ecdsa.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { // NOLINTBEGIN(whitespace/line_length) (Formatted when commented in) // TINK-PENDING-REMOVAL-IN-3.0.0-START using crypto::tink::test::AddTinkKey; using google::crypto::tink::EcdsaPublicKey; using google::crypto::tink::EcdsaSignatureEncoding; using google::crypto::tink::EllipticCurveType; using google::crypto::tink::HashType; using google::crypto::tink::KeyData; using google::crypto::tink::Keyset; using google::crypto::tink::KeyStatusType; class PublicKeyVerifyFactoryTest : public ::testing::Test { protected: void SetUp() override { auto status = SignatureConfig::Register(); ASSERT_TRUE(status.ok()) << status; } }; EcdsaPublicKey GetNewEcdsaPublicKey() { auto ecdsa_key = test::GetEcdsaTestPrivateKey(EllipticCurveType::NIST_P256, HashType::SHA256, EcdsaSignatureEncoding::DER); return ecdsa_key.public_key(); } TEST_F(PublicKeyVerifyFactoryTest, testBasic) { Keyset keyset; auto public_key_verify_result = PublicKeyVerifyFactory::GetPrimitive( *TestKeysetHandle::GetKeysetHandle(keyset)); EXPECT_FALSE(public_key_verify_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, public_key_verify_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "at least one key", std::string(public_key_verify_result.status().message())); } TEST_F(PublicKeyVerifyFactoryTest, testPrimitive) { // Prepare a Keyset. Keyset keyset; std::string key_type = "type.googleapis.com/google.crypto.tink.EcdsaPublicKey"; uint32_t key_id_1 = 1234543; AddTinkKey(key_type, key_id_1, GetNewEcdsaPublicKey(), KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PUBLIC, &keyset); uint32_t key_id_2 = 726329; AddTinkKey(key_type, key_id_2, GetNewEcdsaPublicKey(), KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PUBLIC, &keyset); uint32_t key_id_3 = 7213743; AddTinkKey(key_type, key_id_3, GetNewEcdsaPublicKey(), KeyStatusType::ENABLED, KeyData::ASYMMETRIC_PUBLIC, &keyset); keyset.set_primary_key_id(key_id_3); // Create a KeysetHandle and use it with the factory. auto public_key_verify_result = PublicKeyVerifyFactory::GetPrimitive( *TestKeysetHandle::GetKeysetHandle(keyset)); EXPECT_TRUE(public_key_verify_result.ok()) << public_key_verify_result.status(); auto public_key_verify = std::move(public_key_verify_result.value()); } // TINK-PENDING-REMOVAL-IN-3.0.0-END // NOLINTEND(whitespace/line_length) } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/public_key_verify_wrapper.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/signature/public_key_verify_wrapper.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/crypto_format.h" #include "tink/internal/monitoring_util.h" #include "tink/internal/registry_impl.h" #include "tink/internal/util.h" #include "tink/monitoring/monitoring.h" #include "tink/primitive_set.h" #include "tink/public_key_verify.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { constexpr absl::string_view kPrimitive = "public_key_verify"; constexpr absl::string_view kVerifyApi = "verify"; using ::google::crypto::tink::OutputPrefixType; util::Status Validate(PrimitiveSet* public_key_verify_set) { if (public_key_verify_set == nullptr) { return util::Status(absl::StatusCode::kInternal, "public_key_verify_set must be non-NULL"); } if (public_key_verify_set->get_primary() == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "public_key_verify_set has no primary"); } return util::OkStatus(); } class PublicKeyVerifySetWrapper : public PublicKeyVerify { public: explicit PublicKeyVerifySetWrapper( std::unique_ptr> public_key_verify_set, std::unique_ptr monitoring_verify_client = nullptr) : public_key_verify_set_(std::move(public_key_verify_set)), monitoring_verify_client_(std::move(monitoring_verify_client)) {} crypto::tink::util::Status Verify(absl::string_view signature, absl::string_view data) const override; ~PublicKeyVerifySetWrapper() override = default; private: std::unique_ptr> public_key_verify_set_; std::unique_ptr monitoring_verify_client_; }; util::Status PublicKeyVerifySetWrapper::Verify(absl::string_view signature, absl::string_view data) const { // BoringSSL expects a non-null pointer for data, // regardless of whether the size is 0. data = internal::EnsureStringNonNull(data); signature = internal::EnsureStringNonNull(signature); if (signature.length() <= CryptoFormat::kNonRawPrefixSize) { // This also rejects raw signatures with size of 4 bytes or fewer. // We're not aware of any schemes that output signatures that small. return util::Status(absl::StatusCode::kInvalidArgument, "Signature too short."); } absl::string_view key_id = signature.substr(0, CryptoFormat::kNonRawPrefixSize); auto primitives_result = public_key_verify_set_->get_primitives(key_id); if (primitives_result.ok()) { absl::string_view raw_signature = signature.substr(CryptoFormat::kNonRawPrefixSize); for (auto& entry : *(primitives_result.value())) { std::string legacy_data; absl::string_view view_on_data_or_legacy_data = data; if (entry->get_output_prefix_type() == OutputPrefixType::LEGACY) { legacy_data = absl::StrCat(data, std::string("\x00", 1)); view_on_data_or_legacy_data = legacy_data; } auto& public_key_verify = entry->get_primitive(); auto verify_result = public_key_verify.Verify(raw_signature, view_on_data_or_legacy_data); if (verify_result.ok()) { if (monitoring_verify_client_ != nullptr) { monitoring_verify_client_->Log(entry->get_key_id(), data.size()); } return util::OkStatus(); } else { // LOG that a matching key didn't verify the signature. } } } // No matching key succeeded with verification, try all RAW keys. auto raw_primitives_result = public_key_verify_set_->get_raw_primitives(); if (raw_primitives_result.ok()) { for (auto& public_key_verify_entry : *(raw_primitives_result.value())) { auto& public_key_verify = public_key_verify_entry->get_primitive(); auto verify_result = public_key_verify.Verify(signature, data); if (verify_result.ok()) { if (monitoring_verify_client_ != nullptr) { monitoring_verify_client_->Log(public_key_verify_entry->get_key_id(), data.size()); } return util::OkStatus(); } } } if (monitoring_verify_client_ != nullptr) { monitoring_verify_client_->LogFailure(); } return util::Status(absl::StatusCode::kInvalidArgument, "Invalid signature."); } } // anonymous namespace util::StatusOr> PublicKeyVerifyWrapper::Wrap( std::unique_ptr> public_key_verify_set) const { util::Status status = Validate(public_key_verify_set.get()); if (!status.ok()) return status; MonitoringClientFactory* const monitoring_factory = internal::RegistryImpl::GlobalInstance().GetMonitoringClientFactory(); // Monitoring is not enabled. Create a wrapper without monitoring clients. if (monitoring_factory == nullptr) { return {absl::make_unique( std::move(public_key_verify_set))}; } util::StatusOr keyset_info = internal::MonitoringKeySetInfoFromPrimitiveSet(*public_key_verify_set); if (!keyset_info.ok()) { return keyset_info.status(); } util::StatusOr> monitoring_verify_client = monitoring_factory->New( MonitoringContext(kPrimitive, kVerifyApi, *keyset_info)); if (!monitoring_verify_client.ok()) { return monitoring_verify_client.status(); } return {absl::make_unique( std::move(public_key_verify_set), *std::move(monitoring_verify_client))}; } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/public_key_verify_wrapper.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_PUBLIC_KEY_VERIFY_WRAPPER_H_ #define TINK_SIGNATURE_PUBLIC_KEY_VERIFY_WRAPPER_H_ #include #include "absl/strings/string_view.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/public_key_verify.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // Wraps a set of PublicKeyVerify-instances that correspond to a keyset, // and combines them into a single PublicKeyVerify-primitive, // that for the actual verification uses the instance that matches the // signature prefix. class PublicKeyVerifyWrapper : public PrimitiveWrapper { public: // Returns an PublicKeyVerify-primitive that uses the primary // PublicKeyVerify-instance provided in 'public_key_verify_set', // which must be non-NULL (and must contain a primary instance). crypto::tink::util::StatusOr> Wrap( std::unique_ptr> public_key_verify_set) const override; }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_PUBLIC_KEY_VERIFY_WRAPPER_H_ ================================================ FILE: cc/signature/public_key_verify_wrapper_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/public_key_verify_wrapper.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_map.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/internal/registry_impl.h" #include "tink/monitoring/monitoring.h" #include "tink/monitoring/monitoring_client_mocks.h" #include "tink/primitive_set.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/registry.h" #include "tink/signature/failing_signature.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::DummyPublicKeySign; using ::crypto::tink::test::DummyPublicKeyVerify; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::KeysetInfo; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::OutputPrefixType; using ::testing::_; using ::testing::ByMove; using ::testing::IsNull; using ::testing::StrictMock; using ::testing::Not; using ::testing::NotNull; using ::testing::Return; using ::testing::Test; class PublicKeyVerifySetWrapperTest : public ::testing::Test { protected: void SetUp() override { } void TearDown() override { } }; TEST_F(PublicKeyVerifySetWrapperTest, testBasic) { { // pk_verify_set is nullptr. auto pk_verify_result = PublicKeyVerifyWrapper().Wrap(nullptr); EXPECT_FALSE(pk_verify_result.ok()); EXPECT_EQ(absl::StatusCode::kInternal, pk_verify_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "non-NULL", std::string(pk_verify_result.status().message())); } { // pk_verify_set has no primary primitive. std::unique_ptr> pk_verify_set(new PrimitiveSet()); auto pk_verify_result = PublicKeyVerifyWrapper().Wrap(std::move(pk_verify_set)); EXPECT_FALSE(pk_verify_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, pk_verify_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "no primary", std::string(pk_verify_result.status().message())); } { // Correct pk_verify_set; KeysetInfo::KeyInfo* key_info; KeysetInfo keyset_info; uint32_t key_id_0 = 1234543; key_info = keyset_info.add_key_info(); key_info->set_output_prefix_type(OutputPrefixType::RAW); key_info->set_key_id(key_id_0); key_info->set_status(KeyStatusType::ENABLED); uint32_t key_id_1 = 726329; key_info = keyset_info.add_key_info(); key_info->set_output_prefix_type(OutputPrefixType::LEGACY); key_info->set_key_id(key_id_1); key_info->set_status(KeyStatusType::ENABLED); uint32_t key_id_2 = 7213743; key_info = keyset_info.add_key_info(); key_info->set_output_prefix_type(OutputPrefixType::TINK); key_info->set_key_id(key_id_2); key_info->set_status(KeyStatusType::ENABLED); std::string signature_name_0 = "signature_0"; std::string signature_name_1 = "signature_1"; std::string signature_name_2 = "signature_2"; std::unique_ptr> pk_verify_set( new PrimitiveSet()); std::unique_ptr pk_verify( new DummyPublicKeyVerify(signature_name_0)); auto entry_result = pk_verify_set->AddPrimitive(std::move(pk_verify), keyset_info.key_info(0)); ASSERT_TRUE(entry_result.ok()); pk_verify = std::make_unique(signature_name_1); entry_result = pk_verify_set->AddPrimitive(std::move(pk_verify), keyset_info.key_info(1)); ASSERT_TRUE(entry_result.ok()); pk_verify = std::make_unique(signature_name_2); entry_result = pk_verify_set->AddPrimitive(std::move(pk_verify), keyset_info.key_info(2)); ASSERT_TRUE(entry_result.ok()); // The last key is the primary. ASSERT_THAT(pk_verify_set->set_primary(entry_result.value()), IsOk()); // Wrap pk_verify_set and test the resulting PublicKeyVerify. auto pk_verify_result = PublicKeyVerifyWrapper().Wrap(std::move(pk_verify_set)); EXPECT_TRUE(pk_verify_result.ok()) << pk_verify_result.status(); pk_verify = std::move(pk_verify_result.value()); std::string data = "some data to sign"; std::unique_ptr pk_sign( new DummyPublicKeySign(signature_name_0)); std::string signature = pk_sign->Sign(data).value(); util::Status status = pk_verify->Verify(signature, data); EXPECT_TRUE(status.ok()) << status; } } KeysetInfo::KeyInfo PopulateKeyInfo(uint32_t key_id, OutputPrefixType out_prefix_type, KeyStatusType status) { KeysetInfo::KeyInfo key_info; key_info.set_output_prefix_type(out_prefix_type); key_info.set_key_id(key_id); key_info.set_status(status); return key_info; } // Creates a test keyset info object. KeysetInfo CreateTestKeysetInfo() { KeysetInfo keyset_info; *keyset_info.add_key_info() = PopulateKeyInfo(/*key_id=*/1234543, OutputPrefixType::TINK, /*status=*/KeyStatusType::ENABLED); *keyset_info.add_key_info() = PopulateKeyInfo(/*key_id=*/726329, OutputPrefixType::LEGACY, /*status=*/KeyStatusType::ENABLED); *keyset_info.add_key_info() = PopulateKeyInfo(/*key_id=*/7213743, OutputPrefixType::TINK, /*status=*/KeyStatusType::ENABLED); return keyset_info; } // Tests for the monitoring behavior. class PublicKeyVerifySetWrapperWithMonitoringTest : public Test { protected: // Perform some common initialization: reset the global registry, set expected // calls for the mock monitoring factory and the returned clients. void SetUp() override { Registry::Reset(); // Setup mocks for catching Monitoring calls. auto monitoring_client_factory = absl::make_unique(); auto verify_monitoring_client = absl::make_unique>(); verify_monitoring_client_ = verify_monitoring_client.get(); // Monitoring tests expect that the client factory will create the // corresponding MockMonitoringClients. EXPECT_CALL(*monitoring_client_factory, New(_)) .WillOnce( Return(ByMove(util::StatusOr>( std::move(verify_monitoring_client))))); ASSERT_THAT(internal::RegistryImpl::GlobalInstance() .RegisterMonitoringClientFactory( std::move(monitoring_client_factory)), IsOk()); ASSERT_THAT( internal::RegistryImpl::GlobalInstance().GetMonitoringClientFactory(), Not(IsNull())); } // Cleanup the registry to avoid mock leaks. ~PublicKeyVerifySetWrapperWithMonitoringTest() override { Registry::Reset(); } MockMonitoringClient* verify_monitoring_client_; }; // Test that successful sign operations are logged. TEST_F(PublicKeyVerifySetWrapperWithMonitoringTest, WrapKeysetWithMonitoringVerifySuccess) { // Create a primitive set and fill it with some entries KeysetInfo keyset_info = CreateTestKeysetInfo(); const absl::flat_hash_map kAnnotations = { {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}}; auto public_key_verify_primitive_set = absl::make_unique>(kAnnotations); ASSERT_THAT( public_key_verify_primitive_set ->AddPrimitive(absl::make_unique("verify0"), keyset_info.key_info(0)) .status(), IsOk()); ASSERT_THAT( public_key_verify_primitive_set ->AddPrimitive(absl::make_unique("sign1"), keyset_info.key_info(1)) .status(), IsOk()); // Set the last as primary. util::StatusOr::Entry*> last = public_key_verify_primitive_set->AddPrimitive( absl::make_unique("sign2"), keyset_info.key_info(2)); ASSERT_THAT(last.status(), IsOk()); ASSERT_THAT(public_key_verify_primitive_set->set_primary(*last), IsOk()); // Record the ID of the primary key. const uint32_t primary_key_id = keyset_info.key_info(2).key_id(); // Create a PublicKeyVerify primitive to verify a signature. util::StatusOr> public_key_verify = PublicKeyVerifyWrapper().Wrap(std::move(public_key_verify_primitive_set)); ASSERT_THAT(public_key_verify, IsOkAndHolds(NotNull())); // Create a PublicKeySign primitive and sign some data we can verify. constexpr absl::string_view message = "This is some message!"; std::string signature = absl::StrCat((*last)->get_identifier(), DummyPublicKeySign("sign2").Sign(message).value()); // Check that calling Verify triggers a Log() call. EXPECT_CALL(*verify_monitoring_client_, Log(primary_key_id, message.size())); EXPECT_THAT((*public_key_verify)->Verify(signature, message), IsOk()); } TEST_F(PublicKeyVerifySetWrapperWithMonitoringTest, WrapKeysetWithMonitoringVerifyFailures) { // Create a primitive set and fill it with some entries KeysetInfo keyset_info = CreateTestKeysetInfo(); const absl::flat_hash_map kAnnotations = { {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}}; auto public_key_verify_primitive_set = absl::make_unique>(kAnnotations); ASSERT_THAT(public_key_verify_primitive_set ->AddPrimitive(CreateAlwaysFailingPublicKeyVerify("sign0"), keyset_info.key_info(0)) .status(), IsOk()); ASSERT_THAT(public_key_verify_primitive_set ->AddPrimitive(CreateAlwaysFailingPublicKeyVerify("sign1"), keyset_info.key_info(1)) .status(), IsOk()); // Set the last as primary. util::StatusOr::Entry*> last = public_key_verify_primitive_set->AddPrimitive( CreateAlwaysFailingPublicKeyVerify("sign2"), keyset_info.key_info(2)); ASSERT_THAT(last.status(), IsOk()); ASSERT_THAT(public_key_verify_primitive_set->set_primary(*last), IsOk()); // Create a PublicKeySign and sign some data we can verify. util::StatusOr> public_key_verify = PublicKeyVerifyWrapper().Wrap(std::move(public_key_verify_primitive_set)); ASSERT_THAT(public_key_verify, IsOkAndHolds(NotNull())); constexpr absl::string_view message = "This is some message!"; constexpr absl::string_view signature = "This is some invalid signature!"; // Check that calling Verify triggers a LogFailure() call. EXPECT_CALL(*verify_monitoring_client_, LogFailure()); EXPECT_THAT((*public_key_verify)->Verify(signature, message), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pkcs1_parameters.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pkcs1_parameters.h" #include #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #else #include "openssl/bn.h" #endif #include "tink/big_integer.h" #include "tink/internal/bn_util.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/parameters.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { constexpr int kF4 = 65537; } // namespace RsaSsaPkcs1Parameters::Builder& RsaSsaPkcs1Parameters::Builder::SetModulusSizeInBits(int modulus_size_in_bits) { modulus_size_in_bits_ = modulus_size_in_bits; return *this; } RsaSsaPkcs1Parameters::Builder& RsaSsaPkcs1Parameters::Builder::SetPublicExponent( const BigInteger& public_exponent) { public_exponent_ = public_exponent; return *this; } RsaSsaPkcs1Parameters::Builder& RsaSsaPkcs1Parameters::Builder::SetHashType( HashType hash_type) { hash_type_ = hash_type; return *this; } RsaSsaPkcs1Parameters::Builder& RsaSsaPkcs1Parameters::Builder::SetVariant( Variant variant) { variant_ = variant; return *this; } util::StatusOr RsaSsaPkcs1Parameters::Builder::Build() { if (!modulus_size_in_bits_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Key size is not set."); } if (!hash_type_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Hash type is not set."); } if (!variant_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Variant is not set."); } // Validate modulus size. if (*modulus_size_in_bits_ < 2048) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid key size: must be at least 2048 bits, got ", *modulus_size_in_bits_, " bits.")); } // Validate the public exponent: public exponent needs to be odd, greater than // 65536 and (for consistency with BoringSSL), smaller that 32 bits. util::Status exponent_status = internal::ValidateRsaPublicExponent(public_exponent_.GetValue()); if (!exponent_status.ok()) { return exponent_status; } // Validate HashType. static const std::set* supported_hashes = new std::set( {HashType::kSha256, HashType::kSha384, HashType::kSha512}); if (supported_hashes->find(*hash_type_) == supported_hashes->end()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create RsaSsaPkcs1 parameters with unknown HashType."); } // Validate variant. static const std::set* supported_variants = new std::set({Variant::kTink, Variant::kCrunchy, Variant::kLegacy, Variant::kNoPrefix}); if (supported_variants->find(*variant_) == supported_variants->end()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create RsaSsaPkcs1 parameters with unknown variant."); } return RsaSsaPkcs1Parameters(*modulus_size_in_bits_, public_exponent_, *hash_type_, *variant_); } bool RsaSsaPkcs1Parameters::operator==(const Parameters& other) const { const RsaSsaPkcs1Parameters* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (modulus_size_in_bits_ != that->modulus_size_in_bits_) { return false; } if (public_exponent_ != that->public_exponent_) { return false; } if (hash_type_ != that->hash_type_) { return false; } if (variant_ != that->variant_) { return false; } return true; } // Returns the big endian encoded F4 value as a public exponent default. BigInteger RsaSsaPkcs1Parameters::Builder::CreateDefaultPublicExponent() { internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), kF4); std::string F4_string = internal::BignumToString(e.get(), BN_num_bytes(e.get())).value(); return BigInteger(F4_string); } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pkcs1_parameters.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_RSA_SSA_PKCS1_PARAMETERS_H_ #define TINK_SIGNATURE_RSA_SSA_PKCS1_PARAMETERS_H_ #include #include "absl/types/optional.h" #include "tink/big_integer.h" #include "tink/parameters.h" #include "tink/signature/signature_parameters.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { class RsaSsaPkcs1Parameters : public SignatureParameters { public: // Description of the output prefix prepended to the signature. enum class Variant : int { // Prepends '0x01' to signature. kTink = 1, // Prepends '0x00' to signature. kCrunchy = 2, // Appends a 0-byte to input message BEFORE computing the signature, then // prepends '0x00' to signature. kLegacy = 3, // Does not prepend any prefix (i.e., keys must have no ID requirement). kNoPrefix = 4, // Added to guard from failures that may be caused by future expansions. kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Describes the hash algorithm used for computation. enum class HashType : int { kSha256 = 1, kSha384 = 2, kSha512 = 3, kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Creates RsaSsaPkcs1 parameters instances. class Builder { public: // Copyable and movable. Builder(const Builder& other) = default; Builder& operator=(const Builder& other) = default; Builder(Builder&& other) = default; Builder& operator=(Builder&& other) = default; // Creates initially empty parameters builder. Builder() = default; Builder& SetModulusSizeInBits(int modulus_size_in_bits); Builder& SetPublicExponent(const BigInteger& public_exponent); Builder& SetHashType(HashType hash_type); Builder& SetVariant(Variant variant); // Creates RsaSsaPkcs1 parameters object from this builder. util::StatusOr Build(); private: static BigInteger CreateDefaultPublicExponent(); absl::optional modulus_size_in_bits_ = absl::nullopt; // Defaults to F4. BigInteger public_exponent_ = CreateDefaultPublicExponent(); absl::optional hash_type_ = absl::nullopt; absl::optional variant_ = absl::nullopt; }; // Copyable and movable. RsaSsaPkcs1Parameters(const RsaSsaPkcs1Parameters& other) = default; RsaSsaPkcs1Parameters& operator=(const RsaSsaPkcs1Parameters& other) = default; RsaSsaPkcs1Parameters(RsaSsaPkcs1Parameters&& other) = default; RsaSsaPkcs1Parameters& operator=(RsaSsaPkcs1Parameters&& other) = default; int GetModulusSizeInBits() const { return modulus_size_in_bits_; } const BigInteger& GetPublicExponent() const { return public_exponent_; } HashType GetHashType() const { return hash_type_; } Variant GetVariant() const { return variant_; } bool HasIdRequirement() const override { return variant_ != Variant::kNoPrefix; } bool operator==(const Parameters& other) const override; private: explicit RsaSsaPkcs1Parameters(int modulus_size_in_bits, const BigInteger& public_exponent, HashType hash_type, Variant variant) : modulus_size_in_bits_(modulus_size_in_bits), public_exponent_(public_exponent), hash_type_(hash_type), variant_(variant) {} int modulus_size_in_bits_; BigInteger public_exponent_; HashType hash_type_; Variant variant_; }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_RSA_SSA_PKCS1_PARAMETERS_H_ ================================================ FILE: cc/signature/rsa_ssa_pkcs1_parameters_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pkcs1_parameters.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #else #include "openssl/bn.h" #endif #include "tink/big_integer.h" #include "tink/internal/bn_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::IsTrue; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { int modulus_size_in_bits; RsaSsaPkcs1Parameters::HashType hash_type; RsaSsaPkcs1Parameters::Variant variant; bool has_id_requirement; }; using RsaSsaPkcs1ParametersTest = TestWithParam; std::string PublicExponentToString(int64_t public_exponent) { internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), public_exponent); return internal::BignumToString(e.get(), BN_num_bytes(e.get())).value(); } const BigInteger& kF4 = *(new BigInteger(PublicExponentToString(65537))); INSTANTIATE_TEST_SUITE_P( RsaSsaPkcs1ParametersTestSuite, RsaSsaPkcs1ParametersTest, Values(TestCase{/*modulus_size=*/2048, RsaSsaPkcs1Parameters::HashType::kSha256, RsaSsaPkcs1Parameters::Variant::kTink, /*has_id_requirement=*/true}, TestCase{/*modulus_size=*/3072, RsaSsaPkcs1Parameters::HashType::kSha256, RsaSsaPkcs1Parameters::Variant::kCrunchy, /*has_id_requirement=*/true}, TestCase{/*modulus_size=*/2048, RsaSsaPkcs1Parameters::HashType::kSha256, RsaSsaPkcs1Parameters::Variant::kLegacy, /*has_id_requirement=*/true}, TestCase{/*modulus_size=*/3072, RsaSsaPkcs1Parameters::HashType::kSha256, RsaSsaPkcs1Parameters::Variant::kNoPrefix, /*has_id_requirement=*/false})); TEST_P(RsaSsaPkcs1ParametersTest, Build) { TestCase test_case = GetParam(); util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(test_case.modulus_size_in_bits) .SetPublicExponent(kF4) .SetHashType(test_case.hash_type) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetModulusSizeInBits(), Eq(test_case.modulus_size_in_bits)); EXPECT_THAT(parameters->GetPublicExponent(), Eq(kF4)); EXPECT_THAT(parameters->GetHashType(), Eq(test_case.hash_type)); EXPECT_THAT(parameters->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(parameters->HasIdRequirement(), Eq(test_case.has_id_requirement)); } TEST(RsaSsaPkcs1ParametersTest, BuildWithInvalidVariantFails) { util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPkcs1ParametersTest, BuildWithoutVariantFails) { util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPkcs1ParametersTest, BuildWithInvalidHashTypeFails) { util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetHashType( RsaSsaPkcs1Parameters::HashType:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .SetVariant(RsaSsaPkcs1Parameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPkcs1ParametersTest, BuildWithoutHashTypeFails) { util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetVariant(RsaSsaPkcs1Parameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPkcs1ParametersTest, BuildWithLargeModulusSize) { util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(16789) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetModulusSizeInBits(), Eq(16789)); } TEST(RsaSsaPkcs1ParametersTest, BuildWithTooSmallModulusSize) { util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2047) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPkcs1ParametersTest, BuildWithoutModulusSize) { util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPkcs1ParametersTest, BuildWithValidNonF4PublicExponent) { BigInteger nonF4_public_exponent = BigInteger(PublicExponentToString(1234567)); util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(nonF4_public_exponent) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetPublicExponent(), Eq(nonF4_public_exponent)); } TEST(RsaSsaPkcs1ParametersTest, BuildWithoutPublicExponentDefaultsToF4) { util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetPublicExponent(), Eq(kF4)); } TEST(RsaSsaPkcs1ParametersTest, BuildWithSmallPublicExponentFails) { BigInteger small_public_exponent = BigInteger(PublicExponentToString(3)); util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(small_public_exponent) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPkcs1ParametersTest, BuildWithEvenPublicExponentFails) { BigInteger even_public_exponent = BigInteger(PublicExponentToString(123456)); util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(even_public_exponent) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPkcs1ParametersTest, BuildWithLargePublicExponent) { BigInteger large_public_exponent = BigInteger(PublicExponentToString(100000001L)); util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(large_public_exponent) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetPublicExponent(), Eq(large_public_exponent)); } TEST(RsaSsaPkcs1ParametersTest, BuildWithTooLargePublicExponent) { // Public exponent must be smaller than 32 bits. BigInteger too_large_public_exponent = BigInteger(PublicExponentToString(4294967297L)); util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(too_large_public_exponent) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPkcs1ParametersTest, CopyConstructor) { util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha512) .SetVariant(RsaSsaPkcs1Parameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); RsaSsaPkcs1Parameters copy(*parameters); EXPECT_THAT(copy.GetVariant(), Eq(RsaSsaPkcs1Parameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); EXPECT_THAT(parameters->GetModulusSizeInBits(), Eq(2048)); EXPECT_THAT(parameters->GetPublicExponent(), Eq(kF4)); EXPECT_THAT(parameters->GetHashType(), Eq(RsaSsaPkcs1Parameters::HashType::kSha512)); } TEST(RsaSsaPkcs1ParametersTest, CopyAssignment) { util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha512) .SetVariant(RsaSsaPkcs1Parameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); RsaSsaPkcs1Parameters copy = *parameters; EXPECT_THAT(copy.GetVariant(), Eq(RsaSsaPkcs1Parameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); EXPECT_THAT(parameters->GetModulusSizeInBits(), Eq(2048)); EXPECT_THAT(parameters->GetPublicExponent(), Eq(kF4)); EXPECT_THAT(parameters->GetHashType(), Eq(RsaSsaPkcs1Parameters::HashType::kSha512)); } TEST_P(RsaSsaPkcs1ParametersTest, ParametersEquals) { TestCase test_case = GetParam(); util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(test_case.modulus_size_in_bits) .SetPublicExponent(kF4) .SetHashType(test_case.hash_type) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(test_case.modulus_size_in_bits) .SetPublicExponent(kF4) .SetHashType(test_case.hash_type) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters == *other_parameters); EXPECT_TRUE(*other_parameters == *parameters); EXPECT_FALSE(*parameters != *other_parameters); EXPECT_FALSE(*other_parameters != *parameters); } TEST(RsaSsaPkcs1ParametersTest, VariantNotEqual) { util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha512) .SetVariant(RsaSsaPkcs1Parameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha512) .SetVariant(RsaSsaPkcs1Parameters::Variant::kCrunchy) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(RsaSsaPkcs1ParametersTest, HashTypeNotEqual) { util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha512) .SetVariant(RsaSsaPkcs1Parameters::Variant::kTink) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(RsaSsaPkcs1ParametersTest, ModulusSizeNotEqual) { util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(3072) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kTink) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(RsaSsaPkcs1ParametersTest, PublicExponentNotEqual) { util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetVariant(RsaSsaPkcs1Parameters::Variant::kTink) .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .Build(); ASSERT_THAT(parameters, IsOk()); BigInteger nonF4_public_exponent = BigInteger(PublicExponentToString(1234567)); util::StatusOr other_parameters = RsaSsaPkcs1Parameters::Builder() .SetVariant(RsaSsaPkcs1Parameters::Variant::kTink) .SetModulusSizeInBits(2048) .SetPublicExponent(nonF4_public_exponent) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pkcs1_private_key.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pkcs1_private_key.h" #include "absl/status/status.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #endif #include "openssl/rsa.h" #include "tink/big_integer.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/bn_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_big_integer.h" #include "tink/signature/rsa_ssa_pkcs1_public_key.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { util::Status ValidateKeyPair( const BigInteger& public_exponent, const BigInteger& modulus, const RestrictedBigInteger& p, const RestrictedBigInteger& q, const RestrictedBigInteger& d, const RestrictedBigInteger& dp, const RestrictedBigInteger& dq, const RestrictedBigInteger& q_inv) { internal::SslUniquePtr rsa(RSA_new()); if (rsa.get() == nullptr) { return util::Status(absl::StatusCode::kInternal, "Internal RSA allocation error"); } util::StatusOr> n = internal::StringToBignum(modulus.GetValue()); if (!n.ok()) { return n.status(); } util::StatusOr> e = internal::StringToBignum(public_exponent.GetValue()); if (!e.ok()) { return e.status(); } util::StatusOr> d_bn = internal::StringToBignum(d.GetSecret(InsecureSecretKeyAccess::Get())); if (!d_bn.ok()) { return d_bn.status(); } util::StatusOr> p_bn = internal::StringToBignum(p.GetSecret(InsecureSecretKeyAccess::Get())); if (!p_bn.ok()) { return p_bn.status(); } util::StatusOr> q_bn = internal::StringToBignum(q.GetSecret(InsecureSecretKeyAccess::Get())); if (!q_bn.ok()) { return q_bn.status(); } util::StatusOr> dp_bn = internal::StringToBignum(dp.GetSecret(InsecureSecretKeyAccess::Get())); if (!dp_bn.ok()) { return dp_bn.status(); } util::StatusOr> dq_bn = internal::StringToBignum(dq.GetSecret(InsecureSecretKeyAccess::Get())); if (!dq_bn.ok()) { return dq_bn.status(); } util::StatusOr> q_inv_bn = internal::StringToBignum(q_inv.GetSecret(InsecureSecretKeyAccess::Get())); if (!q_inv_bn.ok()) { return q_inv_bn.status(); } // Build RSA key from the given values. The RSA object takes ownership of the // given values after the call. if (RSA_set0_key(rsa.get(), n->release(), e->release(), d_bn->release()) != 1 || RSA_set0_factors(rsa.get(), p_bn->release(), q_bn->release()) != 1 || RSA_set0_crt_params(rsa.get(), dp_bn->release(), dq_bn->release(), q_inv_bn->release()) != 1) { return util::Status(absl::StatusCode::kInternal, "Internal RSA key loading error"); } // Validate key. int check_key_status = RSA_check_key(rsa.get()); if (check_key_status == 0) { return util::Status(absl::StatusCode::kInvalidArgument, "RSA key pair is not valid"); } if (check_key_status == -1) { return util::Status(absl::StatusCode::kInternal, "An error ocurred while checking the key"); } #ifdef OPENSSL_IS_BORINGSSL if (RSA_check_fips(rsa.get()) == 0) { return util::Status(absl::StatusCode::kInvalidArgument, "RSA key pair is not valid in FIPS mode"); } #endif return util::OkStatus(); } } // namespace RsaSsaPkcs1PrivateKey::Builder& RsaSsaPkcs1PrivateKey::Builder::SetPublicKey( const RsaSsaPkcs1PublicKey& public_key) { public_key_ = public_key; return *this; } RsaSsaPkcs1PrivateKey::Builder& RsaSsaPkcs1PrivateKey::Builder::SetPrimeP( const RestrictedBigInteger& p) { p_ = p; return *this; } RsaSsaPkcs1PrivateKey::Builder& RsaSsaPkcs1PrivateKey::Builder::SetPrimeQ( const RestrictedBigInteger& q) { q_ = q; return *this; } RsaSsaPkcs1PrivateKey::Builder& RsaSsaPkcs1PrivateKey::Builder::SetPrimeExponentP( const RestrictedBigInteger& dp) { dp_ = dp; return *this; } RsaSsaPkcs1PrivateKey::Builder& RsaSsaPkcs1PrivateKey::Builder::SetPrimeExponentQ( const RestrictedBigInteger& dq) { dq_ = dq; return *this; } RsaSsaPkcs1PrivateKey::Builder& RsaSsaPkcs1PrivateKey::Builder::SetPrivateExponent( const RestrictedBigInteger& d) { d_ = d; return *this; } RsaSsaPkcs1PrivateKey::Builder& RsaSsaPkcs1PrivateKey::Builder::SetCrtCoefficient( const RestrictedBigInteger& q_inv) { q_inv_ = q_inv; return *this; } util::StatusOr RsaSsaPkcs1PrivateKey::Builder::Build( PartialKeyAccessToken token) { if (!public_key_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Cannot build without setting the public key"); } if (!p_.has_value() || !q_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Cannot build without setting both prime factors"); } if (!dp_.has_value() || !dq_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Cannot build without setting both prime exponents"); } if (!d_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Cannot build without setting the private exponent"); } if (!q_inv_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Cannot build without setting the CRT coefficient"); } // Validate key pair. util::Status key_pair_validation = ValidateKeyPair( public_key_->GetParameters().GetPublicExponent(), public_key_->GetModulus(token), *p_, *q_, *d_, *dp_, *dq_, *q_inv_); if (!key_pair_validation.ok()) { return key_pair_validation; } return RsaSsaPkcs1PrivateKey(*public_key_, *p_, *q_, *dp_, *dq_, *d_, *q_inv_); } bool RsaSsaPkcs1PrivateKey::operator==(const Key& other) const { const RsaSsaPkcs1PrivateKey* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (GetPublicKey() != that->GetPublicKey()) { return false; } if (p_ != that->p_) { return false; } if (q_ != that->q_) { return false; } if (dp_ != that->dp_) { return false; } if (dq_ != that->dq_) { return false; } if (d_ != that->d_) { return false; } return q_inv_ == that->q_inv_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pkcs1_private_key.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_RSA_SSA_PKCS1_PRIVATE_KEY_H_ #define TINK_SIGNATURE_RSA_SSA_PKCS1_PRIVATE_KEY_H_ #include "absl/types/optional.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_big_integer.h" #include "tink/signature/rsa_ssa_pkcs1_public_key.h" #include "tink/signature/signature_private_key.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { class RsaSsaPkcs1PrivateKey : public SignaturePrivateKey { public: // Copyable and movable. RsaSsaPkcs1PrivateKey(const RsaSsaPkcs1PrivateKey& other) = default; RsaSsaPkcs1PrivateKey& operator=(const RsaSsaPkcs1PrivateKey& other) = default; RsaSsaPkcs1PrivateKey(RsaSsaPkcs1PrivateKey&& other) = default; RsaSsaPkcs1PrivateKey& operator=(RsaSsaPkcs1PrivateKey&& other) = default; // Creates RsaSsaPkcs1 private key instances. class Builder { public: // Copyable and movable. Builder(const Builder& other) = default; Builder& operator=(const Builder& other) = default; Builder(Builder&& other) = default; Builder& operator=(Builder&& other) = default; // Creates initially empty private key builder. Builder() = default; Builder& SetPublicKey(const RsaSsaPkcs1PublicKey& public_key); Builder& SetPrimeP(const RestrictedBigInteger& p); Builder& SetPrimeQ(const RestrictedBigInteger& q); Builder& SetPrimeExponentP(const RestrictedBigInteger& dp); Builder& SetPrimeExponentQ(const RestrictedBigInteger& dq); Builder& SetPrivateExponent(const RestrictedBigInteger& d); Builder& SetCrtCoefficient(const RestrictedBigInteger& q_inv); // Creates RsaSsaPkcs1 private key object from this builder. util::StatusOr Build(PartialKeyAccessToken token); private: absl::optional public_key_; absl::optional p_; absl::optional q_; absl::optional dp_; absl::optional dq_; absl::optional d_; absl::optional q_inv_; }; const RestrictedBigInteger& GetPrimeP(PartialKeyAccessToken token) const { return p_; } const RestrictedBigInteger& GetPrimeQ(PartialKeyAccessToken token) const { return q_; } const RestrictedBigInteger& GetPrivateExponent() const { return d_; } const RestrictedBigInteger& GetPrimeExponentP() const { return dp_; } const RestrictedBigInteger& GetPrimeExponentQ() const { return dq_; } const RestrictedBigInteger& GetCrtCoefficient() const { return q_inv_; } const RsaSsaPkcs1PublicKey& GetPublicKey() const override { return public_key_; } bool operator==(const Key& other) const override; private: explicit RsaSsaPkcs1PrivateKey(const RsaSsaPkcs1PublicKey& public_key, const RestrictedBigInteger& p, const RestrictedBigInteger& q, const RestrictedBigInteger& dp, const RestrictedBigInteger& dq, const RestrictedBigInteger& d, const RestrictedBigInteger& q_inv) : public_key_(public_key), p_(p), q_(q), dp_(dp), dq_(dq), d_(d), q_inv_(q_inv) {} RsaSsaPkcs1PublicKey public_key_; RestrictedBigInteger p_; RestrictedBigInteger q_; RestrictedBigInteger dp_; RestrictedBigInteger dq_; RestrictedBigInteger d_; RestrictedBigInteger q_inv_; }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_RSA_SSA_PKCS1_PRIVATE_KEY_H_ ================================================ FILE: cc/signature/rsa_ssa_pkcs1_private_key_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pkcs1_private_key.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/log/check.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #endif #include "openssl/bn.h" #include "openssl/rsa.h" #include "tink/big_integer.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/bn_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/partial_key_access.h" #include "tink/restricted_big_integer.h" #include "tink/signature/rsa_ssa_pkcs1_parameters.h" #include "tink/signature/rsa_ssa_pkcs1_public_key.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::NotNull; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { RsaSsaPkcs1Parameters::HashType hash_type; RsaSsaPkcs1Parameters::Variant variant; absl::optional id_requirement; std::string output_prefix; }; struct PrivateValues { RestrictedBigInteger p; RestrictedBigInteger q; RestrictedBigInteger dp; RestrictedBigInteger dq; RestrictedBigInteger d; RestrictedBigInteger q_inv; }; constexpr int kModulusSizeInBits = 2048; // Test vector from // https://github.com/google/wycheproof/blob/master/testvectors/rsa_pkcs1_2048_test.json constexpr absl::string_view k2048BitRsaModulus = "s1EKK81M5kTFtZSuUFnhKy8FS2WNXaWVmi_fGHG4CLw98-" "Yo0nkuUarVwSS0O9pFPcpc3kvPKOe9Tv-6DLS3Qru21aATy2PRqjqJ4CYn71OYtSwM_" "ZfSCKvrjXybzgu-sBmobdtYm-sppbdL-GEHXGd8gdQw8DDCZSR6-dPJFAzLZTCdB-Ctwe_" "RXPF-ewVdfaOGjkZIzDoYDw7n-OHnsYCYozkbTOcWHpjVevipR-IBpGPi1rvKgFnlcG6d_" "tj0hWRl_6cS7RqhjoiNEtxqoJzpXs_" "Kg8xbCxXbCchkf11STA8udiCjQWuWI8rcDwl69XMmHJjIQAqhKvOOQ8rYTQ"; constexpr absl::string_view kD = "GlAtDupse2niHVg5EB9wVFbtDvhS-0f-" "IQcfVMXzPIzrBmxi1yfjLSbFgTcyn4nTGVMlt5UmTBldhUcvdQfb0JYdKVH5NaJrNPCsJNFUkO" "ESiptxOJFbx9v6j-OWNXExxUOunJhQc2jZzrCMHGGYo-" "2nrqGFoOl2zULCLQDwA9nxnZbqTJr8v-" "FEHMyALPsGifWdgExqTk9ATBUXR0XtbLi8iO8LM7oNKoDjXkO8kPNQBS5yAW51sA01ejgcnA1G" "cGnKZgiHyYd2Y0n8xDRgtKpRa84Hnt2HuhZDB7dSwnftlSitO6C_" "GHc0ntO3lmpsJAEQQJv00PreDGj9rdhH_Q"; constexpr absl::string_view kP = "7BJc834xCi_0YmO5suBinWOQAF7IiRPU-3G9TdhWEkSYquupg9e6K9lC5k0iP-t6I69NYF7-" "6mvXDTmv6Z01o6oV50oXaHeAk74O3UqNCbLe9tybZ_-FdkYlwuGSNttMQBzjCiVy0-y0-" "Wm3rRnFIsAtd0RlZ24aN3bFTWJINIs"; constexpr absl::string_view kQ = "wnQqvNmJe9SwtnH5c_yCqPhKv1cF_4jdQZSGI6_p3KYNxlQzkHZ_" "6uvrU5V27ov6YbX8vKlKfO91oJFQxUD6lpTdgAStI3GMiJBJIZNpyZ9EWNSvwUj28H34cySpbZ" "z3s4XdhiJBShgy-fKURvBQwtWmQHZJ3EGrcOI7PcwiyYc"; constexpr absl::string_view kDp = "lql5jSUCY0ALtidzQogWJ-B87N-RGHsBuJ_0cxQYinwg-ySAAVbSyF1WZujfbO_5-YBN362A_" "1dn3lbswCnHK_bHF9-fZNqvwprPnceQj5oK1n4g6JSZNsy6GNAhosT-" "uwQ0misgR8SQE4W25dDGkdEYsz-BgCsyrCcu8J5C-tU"; constexpr absl::string_view kDq = "BVT0GwuH9opFcis74M9KseFlA0wakQAquPKenvni2rb-57JFW6-0IDfp0vflM_" "NIoUdBL9cggL58JjP12ALJHDnmvOzj5nXlmZUDPFVzcCDa2eizDQS4KK37kwStVKEaNaT1BwmH" "asWxGCNrp2pNfJopHdlgexad4dGCOFaRmZ8"; constexpr absl::string_view kQInv = "HGQBidm_6MYjgzIQp2xCDG9E5ddg4lmRbOwq4rFWRWlg_ZXidHZgw4lWIlDwVQSc-" "rflwwOVSThKeiquscgk069wlIKoz5tYcCKgCx8HIttQ8zyybcIN0iRdUmXfYe4pg8k4whZ9zuE" "h_EtEecI35yjPYzq2CowOzQT85-O6pVk"; const BigInteger& kF4 = *new BigInteger(std::string("\x1\0\x1", 3)); // 65537 std::string Base64WebSafeDecode(absl::string_view base64_string) { std::string dest; CHECK(absl::WebSafeBase64Unescape(base64_string, &dest)) << "Failed to base64 decode."; return dest; } PrivateValues GetValidPrivateValues() { return PrivateValues{ /*p=*/RestrictedBigInteger(Base64WebSafeDecode(kP), InsecureSecretKeyAccess::Get()), /*q=*/ RestrictedBigInteger(Base64WebSafeDecode(kQ), InsecureSecretKeyAccess::Get()), /*dp=*/ RestrictedBigInteger(Base64WebSafeDecode(kDp), InsecureSecretKeyAccess::Get()), /*dq=*/ RestrictedBigInteger(Base64WebSafeDecode(kDq), InsecureSecretKeyAccess::Get()), /*d=*/ RestrictedBigInteger(Base64WebSafeDecode(kD), InsecureSecretKeyAccess::Get()), /*q_inv=*/ RestrictedBigInteger(Base64WebSafeDecode(kQInv), InsecureSecretKeyAccess::Get())}; } RsaSsaPkcs1PublicKey GetValidPublicKey() { util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(kModulusSizeInBits) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kNoPrefix) .Build(); CHECK_OK(parameters.status()) << "Failed to create parameters."; BigInteger modulus(Base64WebSafeDecode(k2048BitRsaModulus)); util::StatusOr public_key = RsaSsaPkcs1PublicKey::Create(*parameters, modulus, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); CHECK_OK(public_key.status()) << "Failed to create public key."; return *public_key; } std::string FlipFirstByte(absl::string_view str) { std::string res(str); res[0] = ~res[0]; return res; } using RsaSsaPkcs1PrivateKeyTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( RsaSsaPkcs1PrivateKeyTestSuite, RsaSsaPkcs1PrivateKeyTest, Values(TestCase{RsaSsaPkcs1Parameters::HashType::kSha256, RsaSsaPkcs1Parameters::Variant::kTink, /*id_requirement=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{RsaSsaPkcs1Parameters::HashType::kSha256, RsaSsaPkcs1Parameters::Variant::kCrunchy, /*id_requirement=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{RsaSsaPkcs1Parameters::HashType::kSha384, RsaSsaPkcs1Parameters::Variant::kLegacy, /*id_requirement=*/0x07080910, /*output_prefix=*/std::string("\x00\x07\x08\x09\x10", 5)}, TestCase{RsaSsaPkcs1Parameters::HashType::kSha512, RsaSsaPkcs1Parameters::Variant::kNoPrefix, /*id_requirement=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(RsaSsaPkcs1PrivateKeyTest, BuildPrivateKeySucceeds) { TestCase test_case = GetParam(); util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(kModulusSizeInBits) .SetPublicExponent(kF4) .SetHashType(test_case.hash_type) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); BigInteger modulus(Base64WebSafeDecode(k2048BitRsaModulus)); util::StatusOr public_key = RsaSsaPkcs1PublicKey::Create(*parameters, modulus, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(*public_key) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); EXPECT_THAT(private_key->GetParameters(), Eq(*parameters)); EXPECT_THAT(private_key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(private_key->GetPublicKey(), Eq(*public_key)); EXPECT_THAT(private_key->GetOutputPrefix(), Eq(test_case.output_prefix)); EXPECT_THAT(private_key->GetPrimeP(GetPartialKeyAccess()), Eq(private_values.p)); EXPECT_THAT(private_key->GetPrimeQ(GetPartialKeyAccess()), Eq(private_values.q)); EXPECT_THAT(private_key->GetPrimeExponentP(), Eq(private_values.dp)); EXPECT_THAT(private_key->GetPrimeExponentQ(), Eq(private_values.dq)); EXPECT_THAT(private_key->GetCrtCoefficient(), Eq(private_values.q_inv)); EXPECT_THAT(private_key->GetPrivateExponent(), Eq(private_values.d)); } TEST(RsaSsaPkcs1PrivateKeyTest, BuildPrivateKeyFromBoringSsl) { internal::SslUniquePtr rsa(RSA_new()); ASSERT_THAT(rsa, NotNull()); // Set public exponent to 65537. internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), 65537); // Generate an RSA key pair and get the values. ASSERT_THAT(RSA_generate_key_ex(rsa.get(), 2048, e.get(), /*cb=*/nullptr), Eq(1)); const BIGNUM *n_bn, *e_bn, *d_bn, *p_bn, *q_bn, *dp_bn, *dq_bn, *q_inv_bn; RSA_get0_key(rsa.get(), &n_bn, &e_bn, &d_bn); RSA_get0_factors(rsa.get(), &p_bn, &q_bn); RSA_get0_crt_params(rsa.get(), &dp_bn, &dq_bn, &q_inv_bn); util::StatusOr n_str = internal::BignumToString(n_bn, BN_num_bytes(n_bn)); ASSERT_THAT(n_str, IsOk()); util::StatusOr e_str = internal::BignumToString(e_bn, BN_num_bytes(e_bn)); ASSERT_THAT(e_str, IsOk()); util::StatusOr d_str = internal::BignumToString(d_bn, BN_num_bytes(d_bn)); ASSERT_THAT(d_str, IsOk()); util::StatusOr p_str = internal::BignumToString(p_bn, BN_num_bytes(p_bn)); ASSERT_THAT(p_str, IsOk()); util::StatusOr q_str = internal::BignumToString(q_bn, BN_num_bytes(q_bn)); ASSERT_THAT(q_str, IsOk()); util::StatusOr dp_str = internal::BignumToString(dp_bn, BN_num_bytes(dp_bn)); ASSERT_THAT(dp_str, IsOk()); util::StatusOr dq_str = internal::BignumToString(dq_bn, BN_num_bytes(dq_bn)); ASSERT_THAT(dq_str, IsOk()); util::StatusOr q_inv_str = internal::BignumToString(q_inv_bn, BN_num_bytes(q_inv_bn)); ASSERT_THAT(q_inv_str, IsOk()); util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(BigInteger(*e_str)) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr public_key = RsaSsaPkcs1PublicKey::Create(*parameters, /*modulus=*/BigInteger(*n_str), /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(*public_key) .SetPrimeP( RestrictedBigInteger(*p_str, InsecureSecretKeyAccess::Get())) .SetPrimeQ( RestrictedBigInteger(*q_str, InsecureSecretKeyAccess::Get())) .SetPrimeExponentP( RestrictedBigInteger(*dp_str, InsecureSecretKeyAccess::Get())) .SetPrimeExponentQ( RestrictedBigInteger(*dq_str, InsecureSecretKeyAccess::Get())) .SetPrivateExponent( RestrictedBigInteger(*d_str, InsecureSecretKeyAccess::Get())) .SetCrtCoefficient( RestrictedBigInteger(*q_inv_str, InsecureSecretKeyAccess::Get())) .Build(GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); EXPECT_THAT(private_key->GetParameters(), Eq(*parameters)); EXPECT_THAT(private_key->GetPublicKey(), Eq(*public_key)); EXPECT_THAT(private_key->GetPrimeP(GetPartialKeyAccess()) .GetSecret(InsecureSecretKeyAccess::Get()), Eq(*p_str)); EXPECT_THAT(private_key->GetPrimeQ(GetPartialKeyAccess()) .GetSecret(InsecureSecretKeyAccess::Get()), Eq(*q_str)); EXPECT_THAT(private_key->GetPrimeExponentP().GetSecret( InsecureSecretKeyAccess::Get()), Eq(*dp_str)); EXPECT_THAT(private_key->GetPrimeExponentQ().GetSecret( InsecureSecretKeyAccess::Get()), Eq(*dq_str)); EXPECT_THAT(private_key->GetCrtCoefficient().GetSecret( InsecureSecretKeyAccess::Get()), Eq(*q_inv_str)); EXPECT_THAT(private_key->GetPrivateExponent().GetSecret( InsecureSecretKeyAccess::Get()), Eq(*d_str)); EXPECT_THAT(private_key->GetIdRequirement(), Eq(absl::nullopt)); EXPECT_THAT(private_key->GetOutputPrefix(), Eq("")); } TEST(RsaSsaPkcs1PrivateKeyTest, BuildPrivateKeyValidatesModulus) { RsaSsaPkcs1PublicKey public_key = GetValidPublicKey(); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr public_key_modified_modulus = RsaSsaPkcs1PublicKey::Create( public_key.GetParameters(), BigInteger(FlipFirstByte(Base64WebSafeDecode(k2048BitRsaModulus))), /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key_modified_modulus, IsOk()); util::StatusOr private_key_modified_modulus = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(*public_key_modified_modulus) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_modified_modulus.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPkcs1PrivateKeyTest, BuildPrivateKeyValidatesPrimeP) { RsaSsaPkcs1PublicKey public_key = GetValidPublicKey(); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_modified_prime_p = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(public_key) .SetPrimeP( RestrictedBigInteger(FlipFirstByte(Base64WebSafeDecode(kP)), InsecureSecretKeyAccess::Get())) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_modified_prime_p.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPkcs1PrivateKeyTest, BuildPrivateKeyValidatesPrimeQ) { RsaSsaPkcs1PublicKey public_key = GetValidPublicKey(); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_modified_prime_q = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(public_key) .SetPrimeP(private_values.p) .SetPrimeQ( RestrictedBigInteger(FlipFirstByte(Base64WebSafeDecode(kQ)), InsecureSecretKeyAccess::Get())) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_modified_prime_q.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPkcs1PrivateKeyTest, BuildPrivateKeyValidatesPrimeExponentP) { RsaSsaPkcs1PublicKey public_key = GetValidPublicKey(); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_modified_prime_exponent_p = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(public_key) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP( RestrictedBigInteger(FlipFirstByte(Base64WebSafeDecode(kDp)), InsecureSecretKeyAccess::Get())) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_modified_prime_exponent_p.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPkcs1PrivateKeyTest, BuildPrivateKeyValidatesPrimeExponentQ) { RsaSsaPkcs1PublicKey public_key = GetValidPublicKey(); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_modified_prime_exponent_q = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(public_key) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ( RestrictedBigInteger(FlipFirstByte(Base64WebSafeDecode(kDq)), InsecureSecretKeyAccess::Get())) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_modified_prime_exponent_q.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPkcs1PrivateKeyTest, BuildPrivateKeyValidatesPrivateExponent) { RsaSsaPkcs1PublicKey public_key = GetValidPublicKey(); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_modified_private_exponent = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(public_key) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent( RestrictedBigInteger(FlipFirstByte(Base64WebSafeDecode(kD)), InsecureSecretKeyAccess::Get())) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_modified_private_exponent.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPkcs1PrivateKeyTest, BuildPrivateKeyValidatesCrtCoefficient) { RsaSsaPkcs1PublicKey public_key = GetValidPublicKey(); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_modified_crt_coefficient = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(public_key) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient( RestrictedBigInteger(FlipFirstByte(Base64WebSafeDecode(kQInv)), InsecureSecretKeyAccess::Get())) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_modified_crt_coefficient.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPkcs1PrivateKeyTest, BuildPublicKeyNotSetFails) { PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_no_public_key_set = RsaSsaPkcs1PrivateKey::Builder() .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_no_public_key_set.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPkcs1PrivateKeyTest, BuildPrimePNotSetFails) { PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_no_prime_p_set = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(GetValidPublicKey()) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_no_prime_p_set.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPkcs1PrivateKeyTest, BuildPrimeQNotSetFails) { PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_no_prime_q_set = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(GetValidPublicKey()) .SetPrimeP(private_values.p) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_no_prime_q_set.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPkcs1PrivateKeyTest, BuildPrimeExponentPNotSetFails) { PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_no_prime_exponent_p_set = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(GetValidPublicKey()) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_no_prime_exponent_p_set.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPkcs1PrivateKeyTest, BuildPrimeExponentQNotSetFails) { PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_no_prime_exponent_q_set = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(GetValidPublicKey()) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_no_prime_exponent_q_set.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPkcs1PrivateKeyTest, BuildPrivateExponentNotSetFails) { PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_no_private_exponent_set = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(GetValidPublicKey()) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_no_private_exponent_set.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPkcs1PrivateKeyTest, BuildCrtCoefficientNotSetFails) { PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_no_crt_coefficient_set = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(GetValidPublicKey()) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_no_crt_coefficient_set.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPkcs1PrivateKeyTest, CreateMismatchedKeyPairFails) { util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); // Test value from // https://github.com/google/wycheproof/blob/master/testvectors/rsa_pkcs1_2048_test.json BigInteger mismatched_modulus(Base64WebSafeDecode( "3ZBFkDl4CMQxQyliPZATRThDJRsTuLPE_vVFmBEq8-sxxxEDxiWZUWdOU72Tp-NtGUcuR06-" "gChobZUpSE2Lr-pKBLoZVVZnYWyEeGcFlACcm8aj7-UidMumTHJHR9ftwZTk_" "t3jKjKJ2Uwxk25-" "ehXXVvVISS9bNFuSfoxhi91VCsshoXrhSDBDg9ubPHuqPkyL2OhEqITao-GNVpmMsy-" "brk1B1WoY3dQxPICJt16du5EoRwusmwh_thkoqw-" "MTIk2CwIImQCNCOi9MfkHqAfoBWrWgA3_357Z2WSpOefkgRS4SXhVGsuFyd-" "RlvPv9VKG1s1LOagiqKd2Ohggjw")); util::StatusOr public_key = RsaSsaPkcs1PublicKey::Create(*parameters, mismatched_modulus, /*id_requirement=*/0x02030400, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(*public_key) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key.status(), StatusIs(absl::StatusCode ::kInvalidArgument)); } TEST_P(RsaSsaPkcs1PrivateKeyTest, PrivateKeyEquals) { TestCase test_case = GetParam(); util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(kModulusSizeInBits) .SetPublicExponent(kF4) .SetHashType(test_case.hash_type) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); BigInteger modulus(Base64WebSafeDecode(k2048BitRsaModulus)); util::StatusOr public_key = RsaSsaPkcs1PublicKey::Create(*parameters, modulus, /*id_requirement=*/test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(*public_key) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr same_private_key = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(*public_key) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); ASSERT_THAT(same_private_key, IsOk()); EXPECT_TRUE(*private_key == *same_private_key); EXPECT_TRUE(*same_private_key == *private_key); EXPECT_FALSE(*private_key != *same_private_key); EXPECT_FALSE(*same_private_key != *private_key); } TEST(RsaSsaPkcs1PrivateKeyTest, DifferentPublicKeyNotEqual) { util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); BigInteger modulus(Base64WebSafeDecode(k2048BitRsaModulus)); util::StatusOr public_key1 = RsaSsaPkcs1PublicKey::Create(*parameters, modulus, /*id_requirement=*/0x02030400, GetPartialKeyAccess()); ASSERT_THAT(public_key1, IsOk()); util::StatusOr public_key2 = RsaSsaPkcs1PublicKey::Create(*parameters, modulus, /*id_requirement=*/0x01030005, GetPartialKeyAccess()); ASSERT_THAT(public_key2, IsOk()); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key1 = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(*public_key1) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); ASSERT_THAT(private_key1, IsOk()); util::StatusOr private_key2 = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(*public_key2) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); ASSERT_THAT(private_key2, IsOk()); EXPECT_TRUE(*private_key1 != *private_key2); EXPECT_TRUE(*private_key2 != *private_key1); EXPECT_FALSE(*private_key1 == *private_key2); EXPECT_FALSE(*private_key2 == *private_key1); } TEST(RsaSsaPkcs1PrivateKeyTest, DifferentKeyTypesNotEqual) { util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); BigInteger modulus(Base64WebSafeDecode(k2048BitRsaModulus)); util::StatusOr public_key = RsaSsaPkcs1PublicKey::Create(*parameters, modulus, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(*public_key) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); EXPECT_TRUE(*private_key != *public_key); EXPECT_TRUE(*public_key != *private_key); EXPECT_FALSE(*private_key == *public_key); EXPECT_FALSE(*public_key == *private_key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pkcs1_proto_serialization.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pkcs1_proto_serialization.h" #include #include "absl/base/attributes.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/big_integer.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/key_parser.h" #include "tink/internal/key_serializer.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/parameters_parser.h" #include "tink/internal/parameters_serializer.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/partial_key_access.h" #include "tink/restricted_big_integer.h" #include "tink/restricted_data.h" #include "tink/secret_key_access_token.h" #include "tink/signature/rsa_ssa_pkcs1_parameters.h" #include "tink/signature/rsa_ssa_pkcs1_private_key.h" #include "tink/signature/rsa_ssa_pkcs1_public_key.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/common.pb.h" #include "proto/rsa_ssa_pkcs1.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::google::crypto::tink::RsaSsaPkcs1KeyFormat; using ::google::crypto::tink::RsaSsaPkcs1Params; using RsaSsaPkcs1ProtoParametersParserImpl = internal::ParametersParserImpl; using RsaSsaPkcs1ProtoParametersSerializerImpl = internal::ParametersSerializerImpl; using RsaSsaPkcs1ProtoPublicKeyParserImpl = internal::KeyParserImpl; using RsaSsaPkcs1ProtoPublicKeySerializerImpl = internal::KeySerializerImpl; using RsaSsaPkcs1ProtoPrivateKeyParserImpl = internal::KeyParserImpl; using RsaSsaPkcs1ProtoPrivateKeySerializerImpl = internal::KeySerializerImpl; const absl::string_view kPrivateTypeUrl = "type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PrivateKey"; const absl::string_view kPublicTypeUrl = "type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PublicKey"; util::StatusOr ToVariant( OutputPrefixType output_prefix_type) { switch (output_prefix_type) { case OutputPrefixType::LEGACY: return RsaSsaPkcs1Parameters::Variant::kLegacy; case OutputPrefixType::CRUNCHY: return RsaSsaPkcs1Parameters::Variant::kCrunchy; case OutputPrefixType::RAW: return RsaSsaPkcs1Parameters::Variant::kNoPrefix; case OutputPrefixType::TINK: return RsaSsaPkcs1Parameters::Variant::kTink; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine RsaSsaPkcs1Parameters::Variant"); } } util::StatusOr ToOutputPrefixType( RsaSsaPkcs1Parameters::Variant variant) { switch (variant) { case RsaSsaPkcs1Parameters::Variant::kLegacy: return OutputPrefixType::LEGACY; case RsaSsaPkcs1Parameters::Variant::kCrunchy: return OutputPrefixType::CRUNCHY; case RsaSsaPkcs1Parameters::Variant::kNoPrefix: return OutputPrefixType::RAW; case RsaSsaPkcs1Parameters::Variant::kTink: return OutputPrefixType::TINK; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine output prefix type."); } } util::StatusOr ToEnumHashType( HashType hash_type) { switch (hash_type) { case HashType::SHA256: return RsaSsaPkcs1Parameters::HashType::kSha256; case HashType::SHA384: return RsaSsaPkcs1Parameters::HashType::kSha384; case HashType::SHA512: return RsaSsaPkcs1Parameters::HashType::kSha512; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine HashType"); } } util::StatusOr ToProtoHashType( RsaSsaPkcs1Parameters::HashType hash_type) { switch (hash_type) { case RsaSsaPkcs1Parameters::HashType::kSha256: return HashType::SHA256; case RsaSsaPkcs1Parameters::HashType::kSha384: return HashType::SHA384; case RsaSsaPkcs1Parameters::HashType::kSha512: return HashType::SHA512; default: return util::Status( absl::StatusCode::kInvalidArgument, "Could not determine RsaSsaPkcs1Parameters::HashType"); } } util::StatusOr ToParameters( OutputPrefixType output_prefix_type, const RsaSsaPkcs1Params& params, int modulus_size_in_bits, const BigInteger& public_exponent) { util::StatusOr variant = ToVariant(output_prefix_type); if (!variant.ok()) { return variant.status(); } util::StatusOr hash_type = ToEnumHashType(params.hash_type()); if (!hash_type.ok()) { return hash_type.status(); } return RsaSsaPkcs1Parameters::Builder() .SetVariant(*variant) .SetHashType(*hash_type) .SetModulusSizeInBits(modulus_size_in_bits) .SetPublicExponent(public_exponent) .Build(); } util::StatusOr ParseParameters( const internal::ProtoParametersSerialization& serialization) { if (serialization.GetKeyTemplate().type_url() != kPrivateTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing RsaSsaPkcs1Parameters."); } RsaSsaPkcs1KeyFormat proto_key_format; if (!proto_key_format.ParseFromString( serialization.GetKeyTemplate().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse RsaSsaPkcs1KeyFormat proto"); } if (!proto_key_format.has_params()) { return util::Status(absl::StatusCode::kInvalidArgument, "RsaSsaPkcs1KeyFormat proto is missing params field."); } return ToParameters(serialization.GetKeyTemplate().output_prefix_type(), proto_key_format.params(), proto_key_format.modulus_size_in_bits(), BigInteger(proto_key_format.public_exponent())); } util::StatusOr ParsePublicKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (serialization.TypeUrl() != kPublicTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing RsaSsaPkcs1PublicKey."); } google::crypto::tink::RsaSsaPkcs1PublicKey proto_key; const RestrictedData& restricted_data = serialization.SerializedKeyProto(); if (!proto_key.ParseFromString( restricted_data.GetSecret(InsecureSecretKeyAccess::Get()))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse RsaSsaPkcs1PublicKey proto"); } if (proto_key.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } BigInteger modulus(proto_key.n()); int modulus_size_in_bits = modulus.SizeInBytes() * 8; util::StatusOr parameters = ToParameters(serialization.GetOutputPrefixType(), proto_key.params(), modulus_size_in_bits, BigInteger(proto_key.e())); if (!parameters.ok()) { return parameters.status(); } return RsaSsaPkcs1PublicKey::Create(*parameters, modulus, serialization.IdRequirement(), GetPartialKeyAccess()); } util::StatusOr ParsePrivateKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (serialization.TypeUrl() != kPrivateTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing RsaSsaPkcs1PrivateKey."); } if (!token.has_value()) { return util::Status(absl::StatusCode::kPermissionDenied, "SecretKeyAccess is required"); } google::crypto::tink::RsaSsaPkcs1PrivateKey proto_key; const RestrictedData& restricted_data = serialization.SerializedKeyProto(); if (!proto_key.ParseFromString(restricted_data.GetSecret(*token))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse RsaSsaPkcs1PrivateKey proto"); } if (proto_key.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } BigInteger modulus(proto_key.public_key().n()); int modulus_size_in_bits = modulus.SizeInBytes() * 8; util::StatusOr parameters = ToParameters( serialization.GetOutputPrefixType(), proto_key.public_key().params(), modulus_size_in_bits, BigInteger(proto_key.public_key().e())); if (!parameters.ok()) { return parameters.status(); } util::StatusOr public_key = RsaSsaPkcs1PublicKey::Create(*parameters, modulus, serialization.IdRequirement(), GetPartialKeyAccess()); if (!public_key.ok()) { return public_key.status(); } return RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(*public_key) .SetPrimeP(RestrictedBigInteger(proto_key.p(), *token)) .SetPrimeQ(RestrictedBigInteger(proto_key.q(), *token)) .SetPrimeExponentP(RestrictedBigInteger(proto_key.dp(), *token)) .SetPrimeExponentQ(RestrictedBigInteger(proto_key.dq(), *token)) .SetPrivateExponent(RestrictedBigInteger(proto_key.d(), *token)) .SetCrtCoefficient(RestrictedBigInteger(proto_key.crt(), *token)) .Build(GetPartialKeyAccess()); } util::StatusOr SerializeParameters( const RsaSsaPkcs1Parameters& parameters) { util::StatusOr output_prefix_type = ToOutputPrefixType(parameters.GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } util::StatusOr hash_type = ToProtoHashType(parameters.GetHashType()); if (!hash_type.ok()) { return hash_type.status(); } RsaSsaPkcs1Params params; params.set_hash_type(*hash_type); RsaSsaPkcs1KeyFormat proto_key_format; proto_key_format.set_modulus_size_in_bits(parameters.GetModulusSizeInBits()); // OSS proto library complains if input is not converted to a string. proto_key_format.set_public_exponent( std::string(parameters.GetPublicExponent().GetValue())); *proto_key_format.mutable_params() = params; return internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, *output_prefix_type, proto_key_format.SerializeAsString()); } util::StatusOr SerializePublicKey( const RsaSsaPkcs1PublicKey& key, absl::optional token) { util::StatusOr hash_type = ToProtoHashType(key.GetParameters().GetHashType()); if (!hash_type.ok()) { return hash_type.status(); } RsaSsaPkcs1Params params; params.set_hash_type(*hash_type); google::crypto::tink::RsaSsaPkcs1PublicKey proto_key; proto_key.set_version(0); *proto_key.mutable_params() = params; // OSS proto library complains if input is not converted to a string. proto_key.set_n( std::string(key.GetModulus(GetPartialKeyAccess()).GetValue())); proto_key.set_e( std::string(key.GetParameters().GetPublicExponent().GetValue())); util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetParameters().GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } RestrictedData restricted_output = RestrictedData( proto_key.SerializeAsString(), InsecureSecretKeyAccess::Get()); return internal::ProtoKeySerialization::Create( kPublicTypeUrl, restricted_output, KeyData::ASYMMETRIC_PUBLIC, *output_prefix_type, key.GetIdRequirement()); } util::StatusOr SerializePrivateKey( const RsaSsaPkcs1PrivateKey& key, absl::optional token) { if (!token.has_value()) { return util::Status(absl::StatusCode::kPermissionDenied, "SecretKeyAccess is required"); } util::StatusOr hash_type = ToProtoHashType(key.GetPublicKey().GetParameters().GetHashType()); if (!hash_type.ok()) { return hash_type.status(); } RsaSsaPkcs1Params params; params.set_hash_type(*hash_type); google::crypto::tink::RsaSsaPkcs1PublicKey proto_public_key; proto_public_key.set_version(0); *proto_public_key.mutable_params() = params; // OSS proto library complains if input is not converted to a string. proto_public_key.set_n(std::string( key.GetPublicKey().GetModulus(GetPartialKeyAccess()).GetValue())); proto_public_key.set_e(std::string( key.GetPublicKey().GetParameters().GetPublicExponent().GetValue())); google::crypto::tink::RsaSsaPkcs1PrivateKey proto_private_key; proto_private_key.set_version(0); *proto_private_key.mutable_public_key() = proto_public_key; // OSS proto library complains if input is not converted to a string. proto_private_key.set_p( std::string(key.GetPrimeP(GetPartialKeyAccess()).GetSecret(*token))); proto_private_key.set_q( std::string(key.GetPrimeQ(GetPartialKeyAccess()).GetSecret(*token))); proto_private_key.set_dp( std::string(key.GetPrimeExponentP().GetSecret(*token))); proto_private_key.set_dq( std::string(key.GetPrimeExponentQ().GetSecret(*token))); proto_private_key.set_d( std::string(key.GetPrivateExponent().GetSecret(*token))); proto_private_key.set_crt( std::string(key.GetCrtCoefficient().GetSecret(*token))); util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetPublicKey().GetParameters().GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } RestrictedData restricted_output = RestrictedData(proto_private_key.SerializeAsString(), *token); return internal::ProtoKeySerialization::Create( kPrivateTypeUrl, restricted_output, KeyData::ASYMMETRIC_PRIVATE, *output_prefix_type, key.GetIdRequirement()); } RsaSsaPkcs1ProtoParametersParserImpl* RsaSsaPkcs1ProtoParametersParser() { static auto* parser = new RsaSsaPkcs1ProtoParametersParserImpl( kPrivateTypeUrl, ParseParameters); return parser; } RsaSsaPkcs1ProtoParametersSerializerImpl* RsaSsaPkcs1ProtoParametersSerializer() { static auto* serializer = new RsaSsaPkcs1ProtoParametersSerializerImpl( kPrivateTypeUrl, SerializeParameters); return serializer; } RsaSsaPkcs1ProtoPublicKeyParserImpl* RsaSsaPkcs1ProtoPublicKeyParser() { static auto* parser = new RsaSsaPkcs1ProtoPublicKeyParserImpl(kPublicTypeUrl, ParsePublicKey); return parser; } RsaSsaPkcs1ProtoPublicKeySerializerImpl* RsaSsaPkcs1ProtoPublicKeySerializer() { static auto* serializer = new RsaSsaPkcs1ProtoPublicKeySerializerImpl(SerializePublicKey); return serializer; } RsaSsaPkcs1ProtoPrivateKeyParserImpl* RsaSsaPkcs1ProtoPrivateKeyParser() { static auto* parser = new RsaSsaPkcs1ProtoPrivateKeyParserImpl( kPrivateTypeUrl, ParsePrivateKey); return parser; } RsaSsaPkcs1ProtoPrivateKeySerializerImpl* RsaSsaPkcs1ProtoPrivateKeySerializer() { static auto* serializer = new RsaSsaPkcs1ProtoPrivateKeySerializerImpl(SerializePrivateKey); return serializer; } } // namespace util::Status RegisterRsaSsaPkcs1ProtoSerialization() { util::Status status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersParser(RsaSsaPkcs1ProtoParametersParser()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersSerializer(RsaSsaPkcs1ProtoParametersSerializer()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(RsaSsaPkcs1ProtoPublicKeyParser()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(RsaSsaPkcs1ProtoPublicKeySerializer()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(RsaSsaPkcs1ProtoPrivateKeyParser()); if (!status.ok()) { return status; } return internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(RsaSsaPkcs1ProtoPrivateKeySerializer()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pkcs1_proto_serialization.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_RSA_SSA_PKCS1_PROTO_SERIALIZATION_H_ #define TINK_SIGNATURE_RSA_SSA_PKCS1_PROTO_SERIALIZATION_H_ #include "tink/util/status.h" namespace crypto { namespace tink { // Registers proto parsers and serializers for RsaSsaPkcs1 parameters and keys. crypto::tink::util::Status RegisterRsaSsaPkcs1ProtoSerialization(); } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_RSA_SSA_PKCS1_PROTO_SERIALIZATION_H_ ================================================ FILE: cc/signature/rsa_ssa_pkcs1_proto_serialization_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pkcs1_proto_serialization.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/log/check.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #endif #include "openssl/bn.h" #include "openssl/rsa.h" #include "tink/big_integer.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/bn_util.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_big_integer.h" #include "tink/restricted_data.h" #include "tink/signature/rsa_ssa_pkcs1_parameters.h" #include "tink/signature/rsa_ssa_pkcs1_private_key.h" #include "tink/signature/rsa_ssa_pkcs1_public_key.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/common.pb.h" #include "proto/rsa_ssa_pkcs1.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::google::crypto::tink::RsaSsaPkcs1KeyFormat; using ::google::crypto::tink::RsaSsaPkcs1Params; using ::testing::Eq; using ::testing::IsTrue; using ::testing::NotNull; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { RsaSsaPkcs1Parameters::Variant variant; OutputPrefixType output_prefix_type; RsaSsaPkcs1Parameters::HashType hash_type; HashType proto_hash_type; int modulus_size_in_bits; absl::optional id; std::string output_prefix; }; const std::string& kF4Str = *new std::string("\x1\0\x1", 3); // 65537 const absl::string_view kPrivateTypeUrl = "type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PrivateKey"; const absl::string_view kPublicTypeUrl = "type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PublicKey"; class RsaSsaPkcs1ProtoSerializationTest : public TestWithParam { protected: void SetUp() override { internal::MutableSerializationRegistry::GlobalInstance().Reset(); } }; TEST_F(RsaSsaPkcs1ProtoSerializationTest, RegisterTwiceSucceeds) { ASSERT_THAT(RegisterRsaSsaPkcs1ProtoSerialization(), IsOk()); ASSERT_THAT(RegisterRsaSsaPkcs1ProtoSerialization(), IsOk()); } INSTANTIATE_TEST_SUITE_P( RsaSsaPkcs1ProtoSerializationTestSuite, RsaSsaPkcs1ProtoSerializationTest, Values(TestCase{RsaSsaPkcs1Parameters::Variant::kTink, OutputPrefixType::TINK, RsaSsaPkcs1Parameters::HashType::kSha256, HashType::SHA256, /*modulus_size=*/2048, /*id=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{RsaSsaPkcs1Parameters::Variant::kCrunchy, OutputPrefixType::CRUNCHY, RsaSsaPkcs1Parameters::HashType::kSha256, HashType::SHA256, /*modulus_size=*/2048, /*id=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{RsaSsaPkcs1Parameters::Variant::kLegacy, OutputPrefixType::LEGACY, RsaSsaPkcs1Parameters::HashType::kSha384, HashType::SHA384, /*modulus_size=*/3072, /*id=*/0x07080910, /*output_prefix=*/std::string("\x00\x07\x08\x09\x10", 5)}, TestCase{RsaSsaPkcs1Parameters::Variant::kNoPrefix, OutputPrefixType::RAW, RsaSsaPkcs1Parameters::HashType::kSha512, HashType::SHA512, /*modulus_size=*/3072, /*id=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(RsaSsaPkcs1ProtoSerializationTest, ParseParametersSucceeds) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterRsaSsaPkcs1ProtoSerialization(), IsOk()); RsaSsaPkcs1KeyFormat key_format_proto; key_format_proto.set_modulus_size_in_bits(test_case.modulus_size_in_bits); key_format_proto.set_public_exponent(kF4Str); key_format_proto.mutable_params()->set_hash_type(test_case.proto_hash_type); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, test_case.output_prefix_type, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT((*parameters)->HasIdRequirement(), test_case.id.has_value()); const RsaSsaPkcs1Parameters* rsa_ssa_pkcs1_parameters = dynamic_cast(parameters->get()); ASSERT_THAT(rsa_ssa_pkcs1_parameters, NotNull()); EXPECT_THAT(rsa_ssa_pkcs1_parameters->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(rsa_ssa_pkcs1_parameters->GetModulusSizeInBits(), Eq(test_case.modulus_size_in_bits)); EXPECT_THAT(rsa_ssa_pkcs1_parameters->GetHashType(), Eq(test_case.hash_type)); EXPECT_THAT(rsa_ssa_pkcs1_parameters->GetPublicExponent(), Eq(BigInteger(kF4Str))); } TEST_F(RsaSsaPkcs1ProtoSerializationTest, ParseParametersWithInvalidSerializationFails) { ASSERT_THAT(RegisterRsaSsaPkcs1ProtoSerialization(), IsOk()); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::RAW, "invalid_serialization"); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(RsaSsaPkcs1ProtoSerializationTest, ParseParametersKeyFormatWithoutParamsFails) { ASSERT_THAT(RegisterRsaSsaPkcs1ProtoSerialization(), IsOk()); RsaSsaPkcs1KeyFormat key_format_proto; key_format_proto.set_modulus_size_in_bits(2048); key_format_proto.set_public_exponent(kF4Str); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::RAW, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(RsaSsaPkcs1ProtoSerializationTest, ParseParametersWithUnkownOutputPrefixFails) { ASSERT_THAT(RegisterRsaSsaPkcs1ProtoSerialization(), IsOk()); RsaSsaPkcs1KeyFormat key_format_proto; key_format_proto.set_modulus_size_in_bits(2048); key_format_proto.set_public_exponent(kF4Str); key_format_proto.mutable_params()->set_hash_type(HashType::SHA256); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::UNKNOWN_PREFIX, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(RsaSsaPkcs1ProtoSerializationTest, ParseParametersWithUnkownHashFails) { ASSERT_THAT(RegisterRsaSsaPkcs1ProtoSerialization(), IsOk()); RsaSsaPkcs1KeyFormat key_format_proto; key_format_proto.set_modulus_size_in_bits(2048); key_format_proto.set_public_exponent(kF4Str); key_format_proto.mutable_params()->set_hash_type(HashType::UNKNOWN_HASH); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(RsaSsaPkcs1ProtoSerializationTest, SerializeParametersSucceeds) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterRsaSsaPkcs1ProtoSerialization(), IsOk()); util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetVariant(test_case.variant) .SetHashType(test_case.hash_type) .SetModulusSizeInBits(test_case.modulus_size_in_bits) .SetPublicExponent(BigInteger(kF4Str)) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( *parameters); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kPrivateTypeUrl)); const internal::ProtoParametersSerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->GetKeyTemplate().type_url(), Eq(kPrivateTypeUrl)); EXPECT_THAT(proto_serialization->GetKeyTemplate().output_prefix_type(), Eq(test_case.output_prefix_type)); RsaSsaPkcs1KeyFormat key_format; ASSERT_THAT( key_format.ParseFromString(proto_serialization->GetKeyTemplate().value()), IsTrue()); ASSERT_THAT(key_format.has_params(), IsTrue()); EXPECT_THAT(key_format.params().hash_type(), Eq(test_case.proto_hash_type)); EXPECT_THAT(key_format.modulus_size_in_bits(), Eq(test_case.modulus_size_in_bits)); EXPECT_THAT(key_format.public_exponent(), Eq(kF4Str)); } struct KeyValues { std::string n; std::string e; std::string p; std::string q; std::string dp; std::string dq; std::string d; std::string q_inv; }; KeyValues GenerateKeyValues(int modulus_size_in_bits) { internal::SslUniquePtr rsa(RSA_new()); CHECK_NE(rsa.get(), nullptr); // Set public exponent to 65537. internal::SslUniquePtr e(BN_new()); CHECK_NE(e.get(), nullptr); BN_set_word(e.get(), 65537); // Generate an RSA key pair and get the values. CHECK(RSA_generate_key_ex(rsa.get(), modulus_size_in_bits, e.get(), /*cb=*/nullptr)); const BIGNUM *n_bn, *e_bn, *d_bn, *p_bn, *q_bn, *dp_bn, *dq_bn, *q_inv_bn; RSA_get0_key(rsa.get(), &n_bn, &e_bn, &d_bn); util::StatusOr n_str = internal::BignumToString(n_bn, BN_num_bytes(n_bn)); CHECK_OK(n_str); util::StatusOr e_str = internal::BignumToString(e_bn, BN_num_bytes(e_bn)); CHECK_OK(e_str); util::StatusOr d_str = internal::BignumToString(d_bn, BN_num_bytes(d_bn)); CHECK_OK(d_str); RSA_get0_factors(rsa.get(), &p_bn, &q_bn); util::StatusOr p_str = internal::BignumToString(p_bn, BN_num_bytes(p_bn)); CHECK_OK(p_str); util::StatusOr q_str = internal::BignumToString(q_bn, BN_num_bytes(q_bn)); CHECK_OK(q_str); RSA_get0_crt_params(rsa.get(), &dp_bn, &dq_bn, &q_inv_bn); util::StatusOr dp_str = internal::BignumToString(dp_bn, BN_num_bytes(dp_bn)); CHECK_OK(dp_str); util::StatusOr dq_str = internal::BignumToString(dq_bn, BN_num_bytes(dq_bn)); CHECK_OK(dq_str); util::StatusOr q_inv_str = internal::BignumToString(q_inv_bn, BN_num_bytes(q_inv_bn)); CHECK_OK(q_inv_str); return KeyValues{*n_str, *e_str, *p_str, *q_str, *dp_str, *dq_str, *d_str, *q_inv_str}; } TEST_P(RsaSsaPkcs1ProtoSerializationTest, ParsePublicKeySucceeds) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterRsaSsaPkcs1ProtoSerialization(), IsOk()); RsaSsaPkcs1Params params; params.set_hash_type(test_case.proto_hash_type); KeyValues key_values = GenerateKeyValues(test_case.modulus_size_in_bits); google::crypto::tink::RsaSsaPkcs1PublicKey key_proto; key_proto.set_version(0); key_proto.set_n(key_values.n); key_proto.set_e(key_values.e); *key_proto.mutable_params() = params; RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kPublicTypeUrl, serialized_key, KeyData::ASYMMETRIC_PUBLIC, test_case.output_prefix_type, test_case.id); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); ASSERT_THAT(key, IsOk()); EXPECT_THAT((*key)->GetIdRequirement(), Eq(test_case.id)); EXPECT_THAT((*key)->GetParameters().HasIdRequirement(), test_case.id.has_value()); util::StatusOr expected_parameters = RsaSsaPkcs1Parameters::Builder() .SetVariant(test_case.variant) .SetHashType(test_case.hash_type) .SetModulusSizeInBits(test_case.modulus_size_in_bits) .SetPublicExponent(BigInteger(key_values.e)) .Build(); ASSERT_THAT(expected_parameters, IsOk()); util::StatusOr expected_key = RsaSsaPkcs1PublicKey::Create(*expected_parameters, BigInteger(key_values.n), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(expected_key, IsOk()); EXPECT_THAT(**key, Eq(*expected_key)); } TEST_F(RsaSsaPkcs1ProtoSerializationTest, ParsePublicKeyWithInvalidSerializationFails) { ASSERT_THAT(RegisterRsaSsaPkcs1ProtoSerialization(), IsOk()); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPublicTypeUrl, serialized_key, KeyData::ASYMMETRIC_PUBLIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(RsaSsaPkcs1ProtoSerializationTest, ParsePublicKeyWithInvalidVersionFails) { ASSERT_THAT(RegisterRsaSsaPkcs1ProtoSerialization(), IsOk()); RsaSsaPkcs1Params params; params.set_hash_type(HashType::SHA256); KeyValues key_values = GenerateKeyValues(2048); google::crypto::tink::RsaSsaPkcs1PublicKey key_proto; key_proto.set_version(1); key_proto.set_n(key_values.n); key_proto.set_e(key_values.e); *key_proto.mutable_params() = params; RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPublicTypeUrl, serialized_key, KeyData::ASYMMETRIC_PUBLIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(RsaSsaPkcs1ProtoSerializationTest, SerializePublicKeySucceeds) { ASSERT_THAT(RegisterRsaSsaPkcs1ProtoSerialization(), IsOk()); TestCase test_case = GetParam(); KeyValues key_values = GenerateKeyValues(test_case.modulus_size_in_bits); util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetVariant(test_case.variant) .SetHashType(test_case.hash_type) .SetModulusSizeInBits(test_case.modulus_size_in_bits) .SetPublicExponent(BigInteger(key_values.e)) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr key = RsaSsaPkcs1PublicKey::Create(*parameters, BigInteger(key_values.n), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, /*token=*/absl::nullopt); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kPublicTypeUrl)); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq(kPublicTypeUrl)); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::ASYMMETRIC_PUBLIC)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id)); google::crypto::tink::RsaSsaPkcs1PublicKey proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.version(), Eq(0)); EXPECT_THAT(proto_key.n(), Eq(key_values.n)); EXPECT_THAT(proto_key.e(), Eq(key_values.e)); EXPECT_THAT(proto_key.has_params(), IsTrue()); EXPECT_THAT(proto_key.params().hash_type(), Eq(test_case.proto_hash_type)); } TEST_P(RsaSsaPkcs1ProtoSerializationTest, ParsePrivateKeySucceeds) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterRsaSsaPkcs1ProtoSerialization(), IsOk()); RsaSsaPkcs1Params params; params.set_hash_type(test_case.proto_hash_type); KeyValues key_values = GenerateKeyValues(test_case.modulus_size_in_bits); google::crypto::tink::RsaSsaPkcs1PublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_n(key_values.n); public_key_proto.set_e(key_values.e); *public_key_proto.mutable_params() = params; google::crypto::tink::RsaSsaPkcs1PrivateKey private_key_proto; private_key_proto.set_version(0); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_p(key_values.p); private_key_proto.set_q(key_values.q); private_key_proto.set_dp(key_values.dp); private_key_proto.set_dq(key_values.dq); private_key_proto.set_d(key_values.d); private_key_proto.set_crt(key_values.q_inv); RestrictedData serialized_key = RestrictedData( private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, test_case.output_prefix_type, test_case.id); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); EXPECT_THAT((*key)->GetIdRequirement(), Eq(test_case.id)); EXPECT_THAT((*key)->GetParameters().HasIdRequirement(), test_case.id.has_value()); util::StatusOr expected_parameters = RsaSsaPkcs1Parameters::Builder() .SetVariant(test_case.variant) .SetHashType(test_case.hash_type) .SetModulusSizeInBits(test_case.modulus_size_in_bits) .SetPublicExponent(BigInteger(key_values.e)) .Build(); ASSERT_THAT(expected_parameters, IsOk()); util::StatusOr expected_public_key = RsaSsaPkcs1PublicKey::Create(*expected_parameters, BigInteger(key_values.n), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(expected_public_key, IsOk()); util::StatusOr expected_private_key = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(*expected_public_key) .SetPrimeP(RestrictedBigInteger(key_values.p, InsecureSecretKeyAccess::Get())) .SetPrimeQ(RestrictedBigInteger(key_values.q, InsecureSecretKeyAccess::Get())) .SetPrimeExponentP(RestrictedBigInteger( key_values.dp, InsecureSecretKeyAccess::Get())) .SetPrimeExponentQ(RestrictedBigInteger( key_values.dq, InsecureSecretKeyAccess::Get())) .SetPrivateExponent(RestrictedBigInteger( key_values.d, InsecureSecretKeyAccess::Get())) .SetCrtCoefficient(RestrictedBigInteger( key_values.q_inv, InsecureSecretKeyAccess::Get())) .Build(GetPartialKeyAccess()); EXPECT_THAT(**key, Eq(*expected_private_key)); } TEST_F(RsaSsaPkcs1ProtoSerializationTest, ParsePrivateKeyWithInvalidSerializationFails) { ASSERT_THAT(RegisterRsaSsaPkcs1ProtoSerialization(), IsOk()); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(RsaSsaPkcs1ProtoSerializationTest, ParsePrivateKeyWithInvalidVersionFails) { ASSERT_THAT(RegisterRsaSsaPkcs1ProtoSerialization(), IsOk()); RsaSsaPkcs1Params params; params.set_hash_type(HashType::SHA256); KeyValues key_values = GenerateKeyValues(2048); google::crypto::tink::RsaSsaPkcs1PublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_n(key_values.n); public_key_proto.set_e(key_values.e); *public_key_proto.mutable_params() = params; google::crypto::tink::RsaSsaPkcs1PrivateKey private_key_proto; private_key_proto.set_version(1); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_p(key_values.p); private_key_proto.set_q(key_values.q); private_key_proto.set_dp(key_values.dp); private_key_proto.set_dq(key_values.dq); private_key_proto.set_d(key_values.d); private_key_proto.set_crt(key_values.q_inv); RestrictedData serialized_key = RestrictedData( private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(RsaSsaPkcs1ProtoSerializationTest, ParsePrivateKeyNoSecretKeyAccessFails) { ASSERT_THAT(RegisterRsaSsaPkcs1ProtoSerialization(), IsOk()); RsaSsaPkcs1Params params; params.set_hash_type(HashType::SHA256); KeyValues key_values = GenerateKeyValues(2048); google::crypto::tink::RsaSsaPkcs1PublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_n(key_values.n); public_key_proto.set_e(key_values.e); *public_key_proto.mutable_params() = params; google::crypto::tink::RsaSsaPkcs1PrivateKey private_key_proto; private_key_proto.set_version(0); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_p(key_values.p); private_key_proto.set_q(key_values.q); private_key_proto.set_dp(key_values.dp); private_key_proto.set_dq(key_values.dq); private_key_proto.set_d(key_values.d); private_key_proto.set_crt(key_values.q_inv); RestrictedData serialized_key = RestrictedData( private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kPermissionDenied)); } TEST_P(RsaSsaPkcs1ProtoSerializationTest, SerializePrivateKeySucceeds) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterRsaSsaPkcs1ProtoSerialization(), IsOk()); KeyValues key_values = GenerateKeyValues(test_case.modulus_size_in_bits); util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetVariant(test_case.variant) .SetHashType(test_case.hash_type) .SetModulusSizeInBits(test_case.modulus_size_in_bits) .SetPublicExponent(BigInteger(key_values.e)) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr public_key = RsaSsaPkcs1PublicKey::Create(*parameters, BigInteger(key_values.n), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(*public_key) .SetPrimeP(RestrictedBigInteger(key_values.p, InsecureSecretKeyAccess::Get())) .SetPrimeQ(RestrictedBigInteger(key_values.q, InsecureSecretKeyAccess::Get())) .SetPrimeExponentP(RestrictedBigInteger( key_values.dp, InsecureSecretKeyAccess::Get())) .SetPrimeExponentQ(RestrictedBigInteger( key_values.dq, InsecureSecretKeyAccess::Get())) .SetPrivateExponent(RestrictedBigInteger( key_values.d, InsecureSecretKeyAccess::Get())) .SetCrtCoefficient(RestrictedBigInteger( key_values.q_inv, InsecureSecretKeyAccess::Get())) .Build(GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *private_key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kPrivateTypeUrl)); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq(kPrivateTypeUrl)); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::ASYMMETRIC_PRIVATE)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id)); google::crypto::tink::RsaSsaPkcs1PrivateKey proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.version(), Eq(0)); EXPECT_THAT(proto_key.p(), Eq(key_values.p)); EXPECT_THAT(proto_key.q(), Eq(key_values.q)); EXPECT_THAT(proto_key.dp(), Eq(key_values.dp)); EXPECT_THAT(proto_key.dq(), Eq(key_values.dq)); EXPECT_THAT(proto_key.d(), Eq(key_values.d)); EXPECT_THAT(proto_key.crt(), Eq(key_values.q_inv)); EXPECT_THAT(proto_key.has_public_key(), IsTrue()); EXPECT_THAT(proto_key.public_key().version(), Eq(0)); EXPECT_THAT(proto_key.public_key().n(), Eq(key_values.n)); EXPECT_THAT(proto_key.public_key().e(), Eq(key_values.e)); EXPECT_THAT(proto_key.public_key().has_params(), IsTrue()); EXPECT_THAT(proto_key.public_key().params().hash_type(), Eq(test_case.proto_hash_type)); } TEST_F(RsaSsaPkcs1ProtoSerializationTest, SerializePrivateKeyNoSecretKeyAccessFails) { ASSERT_THAT(RegisterRsaSsaPkcs1ProtoSerialization(), IsOk()); KeyValues key_values = GenerateKeyValues(2048); util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetVariant(RsaSsaPkcs1Parameters::Variant::kTink) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetModulusSizeInBits(2048) .SetPublicExponent(BigInteger(kF4Str)) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr public_key = RsaSsaPkcs1PublicKey::Create(*parameters, BigInteger(key_values.n), /*id_requirement=*/0x23456789, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(*public_key) .SetPrimeP(RestrictedBigInteger(key_values.p, InsecureSecretKeyAccess::Get())) .SetPrimeQ(RestrictedBigInteger(key_values.q, InsecureSecretKeyAccess::Get())) .SetPrimeExponentP(RestrictedBigInteger( key_values.dp, InsecureSecretKeyAccess::Get())) .SetPrimeExponentQ(RestrictedBigInteger( key_values.dq, InsecureSecretKeyAccess::Get())) .SetPrivateExponent(RestrictedBigInteger( key_values.d, InsecureSecretKeyAccess::Get())) .SetCrtCoefficient(RestrictedBigInteger( key_values.q_inv, InsecureSecretKeyAccess::Get())) .Build(GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *private_key, /*token=*/absl::nullopt); ASSERT_THAT(serialization.status(), StatusIs(absl::StatusCode::kPermissionDenied)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pkcs1_public_key.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pkcs1_public_key.h" #include #include "absl/base/attributes.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/big_integer.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/signature/rsa_ssa_pkcs1_parameters.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { util::StatusOr ComputeOutputPrefix( const RsaSsaPkcs1Parameters& parameters, absl::optional id_requirement) { switch (parameters.GetVariant()) { case RsaSsaPkcs1Parameters::Variant::kNoPrefix: return std::string(""); // Empty prefix. case RsaSsaPkcs1Parameters::Variant::kLegacy: ABSL_FALLTHROUGH_INTENDED; case RsaSsaPkcs1Parameters::Variant::kCrunchy: if (!id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "ID requirement must have value with kCrunchy or kLegacy"); } return absl::StrCat(absl::HexStringToBytes("00"), subtle::BigEndian32(*id_requirement)); case RsaSsaPkcs1Parameters::Variant::kTink: if (!id_requirement.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "ID requirement must have value with kTink"); } return absl::StrCat(absl::HexStringToBytes("01"), subtle::BigEndian32(*id_requirement)); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid variant: ", parameters.GetVariant())); } } } // namespace util::StatusOr RsaSsaPkcs1PublicKey::Create( const RsaSsaPkcs1Parameters& parameters, const BigInteger& modulus, absl::optional id_requirement, PartialKeyAccessToken token) { if (parameters.HasIdRequirement() && !id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key without ID requirement with parameters with ID " "requirement"); } if (!parameters.HasIdRequirement() && id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key with ID requirement with parameters without ID " "requirement"); } // Check if the modulus length matches the modulus_size_in_bits parameter. if (modulus.SizeInBytes() * 8 != parameters.GetModulusSizeInBits()) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrFormat("Invalid modulus length (expected %d, got %d)", parameters.GetModulusSizeInBits(), modulus.SizeInBytes() * 8)); } util::StatusOr output_prefix = ComputeOutputPrefix(parameters, id_requirement); if (!output_prefix.ok()) { return output_prefix.status(); } return RsaSsaPkcs1PublicKey(parameters, modulus, id_requirement, *output_prefix); } bool RsaSsaPkcs1PublicKey::operator==(const Key& other) const { const RsaSsaPkcs1PublicKey* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (GetParameters() != that->GetParameters()) { return false; } if (id_requirement_ != that->id_requirement_) { return false; } return modulus_ == that->modulus_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pkcs1_public_key.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_RSA_SSA_PKCS1_PUBLIC_KEY_H_ #define TINK_SIGNATURE_RSA_SSA_PKCS1_PUBLIC_KEY_H_ #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/big_integer.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/signature/rsa_ssa_pkcs1_parameters.h" #include "tink/signature/signature_public_key.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Representation of the public key for the RsaSsaPkcs1 digital // signature scheme. class RsaSsaPkcs1PublicKey : public SignaturePublicKey { public: // Copyable and movable. RsaSsaPkcs1PublicKey(const RsaSsaPkcs1PublicKey& other) = default; RsaSsaPkcs1PublicKey& operator=(const RsaSsaPkcs1PublicKey& other) = default; RsaSsaPkcs1PublicKey(RsaSsaPkcs1PublicKey&& other) = default; RsaSsaPkcs1PublicKey& operator=(RsaSsaPkcs1PublicKey&& other) = default; // Creates a new RsaSsaPkcs1 public key from `modulus`. If // `parameters` specify a variant that uses a prefix, then `id_requirement` is // used to compute this prefix. static util::StatusOr Create( const RsaSsaPkcs1Parameters& parameters, const BigInteger& modulus, absl::optional id_requirement, PartialKeyAccessToken token); const BigInteger& GetModulus(PartialKeyAccessToken token) const { return modulus_; } absl::string_view GetOutputPrefix() const override { return output_prefix_; } const RsaSsaPkcs1Parameters& GetParameters() const override { return parameters_; } absl::optional GetIdRequirement() const override { return id_requirement_; } bool operator==(const Key& other) const override; private: explicit RsaSsaPkcs1PublicKey(const RsaSsaPkcs1Parameters& parameters, const BigInteger& modulus, absl::optional id_requirement, absl::string_view output_prefix) : parameters_(parameters), modulus_(modulus), id_requirement_(id_requirement), output_prefix_(output_prefix) {} RsaSsaPkcs1Parameters parameters_; BigInteger modulus_; absl::optional id_requirement_; std::string output_prefix_; }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_RSA_SSA_PKCS1_PUBLIC_KEY_H_ ================================================ FILE: cc/signature/rsa_ssa_pkcs1_public_key_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pkcs1_public_key.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/big_integer.h" #include "tink/partial_key_access.h" #include "tink/signature/rsa_ssa_pkcs1_parameters.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { int modulus_size_in_bits; RsaSsaPkcs1Parameters::HashType hash_type; RsaSsaPkcs1Parameters::Variant variant; absl::optional id_requirement; std::string output_prefix; }; const BigInteger& kF4 = *new BigInteger(std::string("\x1\0\x1", 3)); // 65537 // Test vector from // https://github.com/google/wycheproof/blob/master/testvectors/rsa_pkcs1_2048_test.json constexpr absl::string_view kHex2048BitRsaModulus = "00b3510a2bcd4ce644c5b594ae5059e12b2f054b658d5da5959a2fdf1871b808bc3df3e628" "d2792e51aad5c124b43bda453dca5cde4bcf28e7bd4effba0cb4b742bbb6d5a013cb63d1aa" "3a89e02627ef5398b52c0cfd97d208abeb8d7c9bce0bbeb019a86ddb589beb29a5b74bf861" "075c677c81d430f030c265247af9d3c9140ccb65309d07e0adc1efd15cf17e7b055d7da386" "8e4648cc3a180f0ee7f8e1e7b18098a3391b4ce7161e98d57af8a947e201a463e2d6bbca80" "59e5706e9dfed8f4856465ffa712ed1aa18e888d12dc6aa09ce95ecfca83cc5b0b15db09c8" "647f5d524c0f2e7620a3416b9623cadc0f097af573261c98c8400aa12af38e43cad84d"; using RsaSsaPkcs1PublicKeyTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( RsaSsaPkcs1PublicKeyTestSuite, RsaSsaPkcs1PublicKeyTest, Values(TestCase{/*modulus_size=*/2048, RsaSsaPkcs1Parameters::HashType::kSha256, RsaSsaPkcs1Parameters::Variant::kTink, /*id_requirement=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{/*modulus_size=*/2048, RsaSsaPkcs1Parameters::HashType::kSha256, RsaSsaPkcs1Parameters::Variant::kCrunchy, /*id_requirement=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{/*modulus_size=*/2048, RsaSsaPkcs1Parameters::HashType::kSha384, RsaSsaPkcs1Parameters::Variant::kLegacy, /*id_requirement=*/0x07080910, /*output_prefix=*/std::string("\x00\x07\x08\x09\x10", 5)}, TestCase{/*modulus_size=*/2048, RsaSsaPkcs1Parameters::HashType::kSha512, RsaSsaPkcs1Parameters::Variant::kNoPrefix, /*id_requirement=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(RsaSsaPkcs1PublicKeyTest, CreatePublicKeySucceeds) { TestCase test_case = GetParam(); util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(test_case.modulus_size_in_bits) .SetPublicExponent(kF4) .SetHashType(test_case.hash_type) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); BigInteger modulus(absl::HexStringToBytes(kHex2048BitRsaModulus)); util::StatusOr public_key = RsaSsaPkcs1PublicKey::Create(*parameters, modulus, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); EXPECT_THAT(public_key->GetParameters(), Eq(*parameters)); EXPECT_THAT(public_key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(public_key->GetOutputPrefix(), Eq(test_case.output_prefix)); EXPECT_THAT(public_key->GetModulus(GetPartialKeyAccess()), Eq(modulus)); } TEST(RsaSsaPkcs1PublicKeyTest, CreateWithNonMatchingModulusSizeFails) { util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(3072) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); BigInteger modulus(absl::HexStringToBytes(kHex2048BitRsaModulus)); util::StatusOr public_key = RsaSsaPkcs1PublicKey::Create(*parameters, modulus, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); EXPECT_THAT(public_key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(Ed25519PublicKeyTest, CreateKeyWithInvalidIdRequirementFails) { util::StatusOr no_prefix_parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(no_prefix_parameters, IsOk()); util::StatusOr tink_parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kTink) .Build(); ASSERT_THAT(tink_parameters, IsOk()); BigInteger modulus(absl::HexStringToBytes(kHex2048BitRsaModulus)); EXPECT_THAT(RsaSsaPkcs1PublicKey::Create(*no_prefix_parameters, modulus, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(RsaSsaPkcs1PublicKey::Create(*tink_parameters, modulus, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(RsaSsaPkcs1PublicKeyTest, KeyEquals) { TestCase test_case = GetParam(); util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(test_case.modulus_size_in_bits) .SetPublicExponent(kF4) .SetHashType(test_case.hash_type) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); BigInteger modulus(absl::HexStringToBytes(kHex2048BitRsaModulus)); util::StatusOr public_key = RsaSsaPkcs1PublicKey::Create(*parameters, modulus, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = RsaSsaPkcs1PublicKey::Create(*parameters, modulus, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key == *other_public_key); EXPECT_TRUE(*other_public_key == *public_key); EXPECT_FALSE(*public_key != *other_public_key); EXPECT_FALSE(*other_public_key != *public_key); } TEST(RsaSsaPkcs1PublicKeyTest, DifferentParametersNotEqual) { util::StatusOr tink_parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kTink) .Build(); ASSERT_THAT(tink_parameters, IsOk()); util::StatusOr crunchy_parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kCrunchy) .Build(); ASSERT_THAT(crunchy_parameters, IsOk()); BigInteger modulus(absl::HexStringToBytes(kHex2048BitRsaModulus)); util::StatusOr public_key = RsaSsaPkcs1PublicKey::Create(*tink_parameters, modulus, /*id_requirement=*/0x02030400, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = RsaSsaPkcs1PublicKey::Create(*crunchy_parameters, modulus, /*id_requirement=*/0x02030400, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key != *other_public_key); EXPECT_TRUE(*other_public_key != *public_key); EXPECT_FALSE(*public_key == *other_public_key); EXPECT_FALSE(*other_public_key == *public_key); } TEST(RsaSsaPkcs1PublicKeyTest, DifferentModulusNotEqual) { util::StatusOr parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); std::string other_modulus_bytes = absl::HexStringToBytes( "00dd904590397808c4314329623d9013453843251b13b8b3c4fef54598112af3eb31c711" "03c6259951674e53bd93a7e36d19472e474ebe8028686d9529484d8bafea4a04ba195556" "67616c8478670594009c9bc6a3efe52274cba64c724747d7edc194e4fedde32a3289d94c" "31936e7e7a15d756f548492f5b345b927e8c618bdd550acb21a17ae148304383db9b3c7b" "aa3e4c8bd8e844a884daa3e18d56998cb32f9bae4d41d56a18ddd4313c8089b75e9dbb91" "28470bac9b087fb61928ab0f8c4c89360b020899008d08e8bd31f907a807e8056ad6800d" "ffdf9ed9d964a939e7e48114b84978551acb85c9df9196f3eff55286d6cd4b39a822a8a7" "763a18208f"); BigInteger modulus(absl::HexStringToBytes(kHex2048BitRsaModulus)); BigInteger other_modulus(other_modulus_bytes); util::StatusOr public_key = RsaSsaPkcs1PublicKey::Create(*parameters, modulus, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = RsaSsaPkcs1PublicKey::Create(*parameters, other_modulus, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key != *other_public_key); EXPECT_TRUE(*other_public_key != *public_key); EXPECT_FALSE(*public_key == *other_public_key); EXPECT_FALSE(*other_public_key == *public_key); } TEST(RsaSsaPkcs1PublicKeyTest, DifferentIdRequirementNotEqual) { util::StatusOr tink_parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kTink) .Build(); ASSERT_THAT(tink_parameters, IsOk()); BigInteger modulus(absl::HexStringToBytes(kHex2048BitRsaModulus)); util::StatusOr public_key = RsaSsaPkcs1PublicKey::Create(*tink_parameters, modulus, /*id_requirement=*/0x02030400, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = RsaSsaPkcs1PublicKey::Create(*tink_parameters, modulus, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key != *other_public_key); EXPECT_TRUE(*other_public_key != *public_key); EXPECT_FALSE(*public_key == *other_public_key); EXPECT_FALSE(*other_public_key == *public_key); } TEST(RsaSsaPkcs1PublicKeyTest, PaddedWithZerosModulusEqual) { util::StatusOr tink_parameters = RsaSsaPkcs1Parameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetVariant(RsaSsaPkcs1Parameters::Variant::kTink) .Build(); ASSERT_THAT(tink_parameters, IsOk()); BigInteger modulus(absl::HexStringToBytes(kHex2048BitRsaModulus)); BigInteger padded_with_zeros_modulus( absl::HexStringToBytes("000000" + std::string(kHex2048BitRsaModulus))); ASSERT_THAT(modulus, Eq(padded_with_zeros_modulus)); util::StatusOr public_key = RsaSsaPkcs1PublicKey::Create(*tink_parameters, modulus, /*id_requirement=*/0x02030400, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = RsaSsaPkcs1PublicKey::Create(*tink_parameters, padded_with_zeros_modulus, /*id_requirement=*/0x02030400, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key == *other_public_key); EXPECT_TRUE(*other_public_key == *public_key); EXPECT_FALSE(*public_key != *other_public_key); EXPECT_FALSE(*other_public_key != *public_key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pkcs1_sign_key_manager.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pkcs1_sign_key_manager.h" #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/internal/bn_util.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/signature/rsa_ssa_pkcs1_verify_key_manager.h" #include "tink/signature/sig_util.h" #include "tink/subtle/rsa_ssa_pkcs1_sign_boringssl.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/rsa_ssa_pkcs1.pb.h" namespace crypto { namespace tink { using crypto::tink::util::Enums; using crypto::tink::util::Status; using crypto::tink::util::StatusOr; using google::crypto::tink::RsaSsaPkcs1KeyFormat; using google::crypto::tink::RsaSsaPkcs1Params; using google::crypto::tink::RsaSsaPkcs1PrivateKey; namespace { RsaSsaPkcs1PrivateKey RsaPrivateKeySubtleToProto( const internal::RsaPrivateKey& private_key) { RsaSsaPkcs1PrivateKey key_proto; key_proto.set_version(RsaSsaPkcs1SignKeyManager().get_version()); key_proto.set_d(std::string(util::SecretDataAsStringView(private_key.d))); key_proto.set_p(std::string(util::SecretDataAsStringView(private_key.p))); key_proto.set_q(std::string(util::SecretDataAsStringView(private_key.q))); key_proto.set_dp(std::string(util::SecretDataAsStringView(private_key.dp))); key_proto.set_dq(std::string(util::SecretDataAsStringView(private_key.dq))); key_proto.set_crt(std::string(util::SecretDataAsStringView(private_key.crt))); auto* public_key_proto = key_proto.mutable_public_key(); public_key_proto->set_version(RsaSsaPkcs1SignKeyManager().get_version()); public_key_proto->set_n(private_key.n); public_key_proto->set_e(private_key.e); return key_proto; } internal::RsaPrivateKey RsaPrivateKeyProtoToSubtle( const RsaSsaPkcs1PrivateKey& key_proto) { internal::RsaPrivateKey key; key.n = key_proto.public_key().n(); key.e = key_proto.public_key().e(); key.d = util::SecretDataFromStringView(key_proto.d()); key.p = util::SecretDataFromStringView(key_proto.p()); key.q = util::SecretDataFromStringView(key_proto.q()); key.dp = util::SecretDataFromStringView(key_proto.dp()); key.dq = util::SecretDataFromStringView(key_proto.dq()); key.crt = util::SecretDataFromStringView(key_proto.crt()); return key; } } // namespace StatusOr RsaSsaPkcs1SignKeyManager::CreateKey( const RsaSsaPkcs1KeyFormat& rsa_ssa_pkcs1_key_format) const { StatusOr> e = internal::StringToBignum(rsa_ssa_pkcs1_key_format.public_exponent()); if (!e.ok()) { return e.status(); } internal::RsaPrivateKey private_key; internal::RsaPublicKey public_key; util::Status status = internal::NewRsaKeyPair(rsa_ssa_pkcs1_key_format.modulus_size_in_bits(), e->get(), &private_key, &public_key); if (!status.ok()) { return status; } RsaSsaPkcs1PrivateKey key_proto = RsaPrivateKeySubtleToProto(private_key); auto* public_key_proto = key_proto.mutable_public_key(); *public_key_proto->mutable_params() = rsa_ssa_pkcs1_key_format.params(); return key_proto; } StatusOr> RsaSsaPkcs1SignKeyManager::PublicKeySignFactory::Create( const RsaSsaPkcs1PrivateKey& private_key) const { auto key = RsaPrivateKeyProtoToSubtle(private_key); internal::RsaSsaPkcs1Params params; const RsaSsaPkcs1Params& params_proto = private_key.public_key().params(); params.hash_type = Enums::ProtoToSubtle(params_proto.hash_type()); auto signer = subtle::RsaSsaPkcs1SignBoringSsl::New(key, params); if (!signer.ok()) return signer.status(); // To check that the key is correct, we sign a test message with private key // and verify with public key. auto verifier = RsaSsaPkcs1VerifyKeyManager().GetPrimitive( private_key.public_key()); if (!verifier.ok()) return verifier.status(); auto sign_verify_result = SignAndVerify(signer.value().get(), verifier.value().get()); if (!sign_verify_result.ok()) { return util::Status(absl::StatusCode::kInternal, "security bug: signing with private key followed by " "verifying with public key failed"); } return signer; } Status RsaSsaPkcs1SignKeyManager::ValidateKey( const RsaSsaPkcs1PrivateKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; return RsaSsaPkcs1VerifyKeyManager().ValidateKey(key.public_key()); } Status RsaSsaPkcs1SignKeyManager::ValidateKeyFormat( const RsaSsaPkcs1KeyFormat& key_format) const { Status modulus_status = internal::ValidateRsaModulusSize(key_format.modulus_size_in_bits()); if (!modulus_status.ok()) { return modulus_status; } Status exponent_status = internal::ValidateRsaPublicExponent(key_format.public_exponent()); if (!exponent_status.ok()) { return exponent_status; } return RsaSsaPkcs1VerifyKeyManager().ValidateParams(key_format.params()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pkcs1_sign_key_manager.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_RSA_SSA_PKCS1_SIGN_KEY_MANAGER_H_ #define TINK_SIGNATURE_RSA_SSA_PKCS1_SIGN_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_sign.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/rsa_ssa_pkcs1.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class RsaSsaPkcs1SignKeyManager : public PrivateKeyTypeManager> { public: class PublicKeySignFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::RsaSsaPkcs1PrivateKey& private_key) const override; }; RsaSsaPkcs1SignKeyManager() : PrivateKeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::RsaSsaPkcs1PrivateKey& key) const override; crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::RsaSsaPkcs1KeyFormat& key_format) const override; crypto::tink::util::StatusOr CreateKey(const google::crypto::tink::RsaSsaPkcs1KeyFormat& key_format) const override; crypto::tink::util::StatusOr GetPublicKey(const google::crypto::tink::RsaSsaPkcs1PrivateKey& private_key) const override { return private_key.public_key(); } internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: const std::string key_type_ = absl::StrCat(kTypeGoogleapisCom, google::crypto::tink::RsaSsaPkcs1PrivateKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_RSA_SSA_PKCS1_SIGN_KEY_MANAGER_H_ ================================================ FILE: cc/signature/rsa_ssa_pkcs1_sign_key_manager_test.cc ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pkcs1_sign_key_manager.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_set.h" #include "openssl/rsa.h" #include "tink/internal/bn_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/public_key_sign.h" #include "tink/signature/rsa_ssa_pkcs1_verify_key_manager.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/rsa_ssa_pkcs1_verify_boringssl.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/rsa_ssa_pkcs1.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::RsaSsaPkcs1KeyFormat; using ::google::crypto::tink::RsaSsaPkcs1PrivateKey; using ::google::crypto::tink::RsaSsaPkcs1PublicKey; using ::testing::Eq; using ::testing::Not; using ::testing::SizeIs; TEST(RsaSsaPkcsSignKeyManagerTest, Basic) { EXPECT_THAT(RsaSsaPkcs1SignKeyManager().get_version(), Eq(0)); EXPECT_THAT(RsaSsaPkcs1SignKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PRIVATE)); EXPECT_THAT( RsaSsaPkcs1SignKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PrivateKey")); } RsaSsaPkcs1KeyFormat CreateKeyFormat(HashType hash_type, int modulus_size_in_bits, int public_exponent) { RsaSsaPkcs1KeyFormat key_format; auto params = key_format.mutable_params(); params->set_hash_type(hash_type); key_format.set_modulus_size_in_bits(modulus_size_in_bits); internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), public_exponent); key_format.set_public_exponent( internal::BignumToString(e.get(), BN_num_bytes(e.get())).value()); return key_format; } RsaSsaPkcs1KeyFormat ValidKeyFormat() { return CreateKeyFormat(HashType::SHA256, 3072, RSA_F4); } TEST(RsaSsaPkcs1SignKeyManagerTest, ValidateKeyFormat) { EXPECT_THAT(RsaSsaPkcs1SignKeyManager().ValidateKeyFormat(ValidKeyFormat()), IsOk()); } TEST(RsaSsaPkcs1SignKeyManagerTest, ValidateKeyFormatSha384Allowed) { RsaSsaPkcs1KeyFormat key_format = ValidKeyFormat(); key_format.mutable_params()->set_hash_type(HashType::SHA384); EXPECT_THAT(RsaSsaPkcs1SignKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(RsaSsaPkcs1SignKeyManagerTest, ValidateKeyFormatSha512Allowed) { RsaSsaPkcs1KeyFormat key_format = ValidKeyFormat(); key_format.mutable_params()->set_hash_type(HashType::SHA512); EXPECT_THAT(RsaSsaPkcs1SignKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(RsaSsaPkcs1SignKeyManagerTest, ValidateKeyFormatSha1Disallowed) { RsaSsaPkcs1KeyFormat key_format = ValidKeyFormat(); key_format.mutable_params()->set_hash_type(HashType::SHA1); EXPECT_THAT(RsaSsaPkcs1SignKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(RsaSsaPkcs1SignKeyManagerTest, ValidateKeyFormatUnkownHashDisallowed) { RsaSsaPkcs1KeyFormat key_format = ValidKeyFormat(); key_format.mutable_params()->set_hash_type(HashType::UNKNOWN_HASH); EXPECT_THAT(RsaSsaPkcs1SignKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(RsaSsaPkcs1SignKeyManagerTest, ValidateKeyFormatSmallModulusDisallowed) { RsaSsaPkcs1KeyFormat key_format = ValidKeyFormat(); key_format.set_modulus_size_in_bits(2047); EXPECT_THAT(RsaSsaPkcs1SignKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } // Checks whether given key is compatible with the given format. void CheckNewKey(const RsaSsaPkcs1PrivateKey& private_key, const RsaSsaPkcs1KeyFormat& key_format) { RsaSsaPkcs1SignKeyManager key_manager; RsaSsaPkcs1PublicKey public_key = private_key.public_key(); EXPECT_EQ(0, private_key.version()); EXPECT_TRUE(private_key.has_public_key()); EXPECT_EQ(0, public_key.version()); EXPECT_GT(public_key.n().length(), 0); EXPECT_GT(public_key.e().length(), 0); EXPECT_EQ(public_key.params().SerializeAsString(), key_format.params().SerializeAsString()); EXPECT_EQ(key_format.public_exponent(), public_key.e()); util::StatusOr> n = internal::StringToBignum(public_key.n()); ASSERT_THAT(n, IsOk()); util::StatusOr> d = internal::StringToBignum(private_key.d()); ASSERT_THAT(d, IsOk()); util::StatusOr> p = internal::StringToBignum(private_key.p()); ASSERT_THAT(p, IsOk()); util::StatusOr> q = internal::StringToBignum(private_key.q()); ASSERT_THAT(q, IsOk()); util::StatusOr> dp = internal::StringToBignum(private_key.dp()); ASSERT_THAT(dp, IsOk()); util::StatusOr> dq = internal::StringToBignum(private_key.dq()); ASSERT_THAT(dq, IsOk()); internal::SslUniquePtr ctx(BN_CTX_new()); // Check n = p * q. auto n_calc = internal::SslUniquePtr(BN_new()); EXPECT_TRUE(BN_mul(n_calc.get(), p->get(), q->get(), ctx.get())); EXPECT_EQ(BN_cmp(n_calc.get(), n->get()), 0); // Check n size >= modulus_size_in_bits bit. EXPECT_GE(BN_num_bits(n->get()), key_format.modulus_size_in_bits()); // dp = d mod (p - 1) auto pm1 = internal::SslUniquePtr(BN_dup(p->get())); EXPECT_TRUE(BN_sub_word(pm1.get(), 1)); auto dp_calc = internal::SslUniquePtr(BN_new()); EXPECT_TRUE(BN_mod(dp_calc.get(), d->get(), pm1.get(), ctx.get())); EXPECT_EQ(BN_cmp(dp_calc.get(), dp->get()), 0); // dq = d mod (q - 1) auto qm1 = internal::SslUniquePtr(BN_dup(q->get())); EXPECT_TRUE(BN_sub_word(qm1.get(), 1)); auto dq_calc = internal::SslUniquePtr(BN_new()); EXPECT_TRUE(BN_mod(dq_calc.get(), d->get(), qm1.get(), ctx.get())); EXPECT_EQ(BN_cmp(dq_calc.get(), dq->get()), 0); } TEST(RsaSsaPkcs1SignKeyManagerTest, CreateKey) { RsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(HashType::SHA256, 3072, RSA_F4); StatusOr private_key_or = RsaSsaPkcs1SignKeyManager().CreateKey(key_format); ASSERT_THAT(private_key_or, IsOk()); CheckNewKey(private_key_or.value(), key_format); } TEST(RsaSsaPkcs1SignKeyManagerTest, CreateKeySmallKey) { RsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(HashType::SHA256, 2048, RSA_F4); StatusOr private_key_or = RsaSsaPkcs1SignKeyManager().CreateKey(key_format); ASSERT_THAT(private_key_or, IsOk()); CheckNewKey(private_key_or.value(), key_format); } TEST(RsaSsaPkcs1SignKeyManagerTest, CreateKeyLargeKey) { RsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(HashType::SHA512, 4096, RSA_F4); StatusOr private_key_or = RsaSsaPkcs1SignKeyManager().CreateKey(key_format); ASSERT_THAT(private_key_or, IsOk()); CheckNewKey(private_key_or.value(), key_format); } TEST(RsaSsaPkcs1SignKeyManagerTest, CreateKeyValid) { StatusOr key_or = RsaSsaPkcs1SignKeyManager().CreateKey(ValidKeyFormat()); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(RsaSsaPkcs1SignKeyManager().ValidateKey(key_or.value()), IsOk()); } // Check that in a bunch of CreateKey calls all generated primes are distinct. TEST(RsaSsaPkcs1SignKeyManagerTest, CreateKeyAlwaysNewRsaPair) { absl::flat_hash_set keys; // This test takes about a second per key. int num_generated_keys = 5; for (int i = 0; i < num_generated_keys; ++i) { StatusOr key_or = RsaSsaPkcs1SignKeyManager().CreateKey(ValidKeyFormat()); ASSERT_THAT(key_or, IsOk()); keys.insert(key_or.value().p()); keys.insert(key_or.value().q()); } EXPECT_THAT(keys, SizeIs(2 * num_generated_keys)); } TEST(RsaSsaPkcs1SignKeyManagerTest, GetPublicKey) { StatusOr key_or = RsaSsaPkcs1SignKeyManager().CreateKey(ValidKeyFormat()); ASSERT_THAT(key_or, IsOk()); StatusOr public_key_or = RsaSsaPkcs1SignKeyManager().GetPublicKey(key_or.value()); ASSERT_THAT(public_key_or, IsOk()); EXPECT_THAT(public_key_or.value().version(), Eq(key_or.value().public_key().version())); EXPECT_THAT(public_key_or.value().params().hash_type(), Eq(key_or.value().public_key().params().hash_type())); EXPECT_THAT(public_key_or.value().n(), Eq(key_or.value().public_key().n())); EXPECT_THAT(public_key_or.value().e(), Eq(key_or.value().public_key().e())); } TEST(EcdsaSignKeyManagerTest, Create) { RsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(HashType::SHA256, 3072, RSA_F4); StatusOr key_or = RsaSsaPkcs1SignKeyManager().CreateKey(key_format); ASSERT_THAT(key_or, IsOk()); RsaSsaPkcs1PrivateKey key = key_or.value(); auto signer_or = RsaSsaPkcs1SignKeyManager().GetPrimitive(key); ASSERT_THAT(signer_or, IsOk()); auto direct_verifier_or = subtle::RsaSsaPkcs1VerifyBoringSsl::New( {key.public_key().n(), key.public_key().e()}, {subtle::HashType::SHA256}); ASSERT_THAT(direct_verifier_or, IsOk()); std::string message = "Some message"; EXPECT_THAT(direct_verifier_or.value()->Verify( signer_or.value()->Sign(message).value(), message), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pkcs1_verify_key_manager.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pkcs1_verify_key_manager.h" #include #include #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "openssl/bn.h" #include "tink/internal/bn_util.h" #include "tink/internal/md_util.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/public_key_verify.h" #include "tink/subtle/rsa_ssa_pkcs1_verify_boringssl.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/rsa_ssa_pkcs1.pb.h" namespace crypto { namespace tink { using crypto::tink::util::Enums; using google::crypto::tink::RsaSsaPkcs1Params; using google::crypto::tink::RsaSsaPkcs1PublicKey; util::StatusOr> RsaSsaPkcs1VerifyKeyManager::PublicKeyVerifyFactory::Create( const RsaSsaPkcs1PublicKey& rsa_ssa_pkcs1_public_key) const { internal::RsaPublicKey rsa_pub_key; rsa_pub_key.n = rsa_ssa_pkcs1_public_key.n(); rsa_pub_key.e = rsa_ssa_pkcs1_public_key.e(); internal::RsaSsaPkcs1Params params; RsaSsaPkcs1Params rsa_ssa_pkcs1_params = rsa_ssa_pkcs1_public_key.params(); params.hash_type = Enums::ProtoToSubtle(rsa_ssa_pkcs1_params.hash_type()); auto rsa_ssa_pkcs1_result = subtle::RsaSsaPkcs1VerifyBoringSsl::New(rsa_pub_key, params); if (!rsa_ssa_pkcs1_result.ok()) return rsa_ssa_pkcs1_result.status(); return {std::move(rsa_ssa_pkcs1_result.value())}; } util::Status RsaSsaPkcs1VerifyKeyManager::ValidateParams( const RsaSsaPkcs1Params& params) const { return internal::IsHashTypeSafeForSignature( Enums::ProtoToSubtle(params.hash_type())); } util::Status RsaSsaPkcs1VerifyKeyManager::ValidateKey( const RsaSsaPkcs1PublicKey& key) const { util::Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; util::StatusOr> n = internal::StringToBignum(key.n()); if (!n.ok()) { return n.status(); } util::Status modulus_status = internal::ValidateRsaModulusSize(BN_num_bits(n->get())); if (!modulus_status.ok()) { return modulus_status; } util::Status exponent_status = internal::ValidateRsaPublicExponent(key.e()); if (!exponent_status.ok()) { return exponent_status; } return ValidateParams(key.params()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pkcs1_verify_key_manager.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_RSA_SSA_PKCS1_VERIFY_KEY_MANAGER_H_ #define TINK_SIGNATURE_RSA_SSA_PKCS1_VERIFY_KEY_MANAGER_H_ #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_verify.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/rsa_ssa_pkcs1.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class RsaSsaPkcs1VerifyKeyManager : public KeyTypeManager> { public: class PublicKeyVerifyFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::RsaSsaPkcs1PublicKey& rsa_ssa_pkcs1_public_key) const override; }; RsaSsaPkcs1VerifyKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PUBLIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::RsaSsaPkcs1PublicKey& key) const override; crypto::tink::util::Status ValidateParams( const google::crypto::tink::RsaSsaPkcs1Params& params) const; internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: const std::string key_type_ = absl::StrCat(kTypeGoogleapisCom, google::crypto::tink::RsaSsaPkcs1PublicKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_RSA_SSA_PKCS1_VERIFY_KEY_MANAGER_H_ ================================================ FILE: cc/signature/rsa_ssa_pkcs1_verify_key_manager_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pkcs1_verify_key_manager.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "openssl/bn.h" #include "openssl/rsa.h" #include "tink/internal/bn_util.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/signature/rsa_ssa_pkcs1_sign_key_manager.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/rsa_ssa_pkcs1_sign_boringssl.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/rsa_ssa_pkcs1.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::RsaSsaPkcs1KeyFormat; using ::google::crypto::tink::RsaSsaPkcs1PrivateKey; using ::google::crypto::tink::RsaSsaPkcs1PublicKey; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::Not; namespace { TEST(RsaSsaPkcs1VerifyKeyManagerTest, Basics) { EXPECT_THAT(RsaSsaPkcs1VerifyKeyManager().get_version(), Eq(0)); EXPECT_THAT(RsaSsaPkcs1VerifyKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PUBLIC)); EXPECT_THAT( RsaSsaPkcs1VerifyKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PublicKey")); } TEST(RsaSsaPkcs1VerifyKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(RsaSsaPkcs1VerifyKeyManager().ValidateKey(RsaSsaPkcs1PublicKey()), Not(IsOk())); } RsaSsaPkcs1KeyFormat CreateKeyFormat(HashType hash_type, int modulus_size_in_bits, int public_exponent) { RsaSsaPkcs1KeyFormat key_format; auto params = key_format.mutable_params(); params->set_hash_type(hash_type); key_format.set_modulus_size_in_bits(modulus_size_in_bits); internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), public_exponent); key_format.set_public_exponent( internal::BignumToString(e.get(), BN_num_bytes(e.get())).value()); return key_format; } RsaSsaPkcs1KeyFormat ValidKeyFormat() { return CreateKeyFormat(HashType::SHA256, 3072, RSA_F4); } RsaSsaPkcs1PrivateKey CreateValidPrivateKey() { return RsaSsaPkcs1SignKeyManager().CreateKey(ValidKeyFormat()).value(); } RsaSsaPkcs1PublicKey CreateValidPublicKey() { return RsaSsaPkcs1SignKeyManager() .GetPublicKey(CreateValidPrivateKey()) .value(); } // Checks that a public key generaed by the SignKeyManager is considered valid. TEST(RsaSsaPkcs1VerifyKeyManagerTest, PublicKeyValid) { RsaSsaPkcs1PublicKey key = CreateValidPublicKey(); EXPECT_THAT(RsaSsaPkcs1VerifyKeyManager().ValidateKey(key), IsOk()); } TEST(RsaSsaPkcs1VerifyKeyManagerTest, PublicKeyWrongVersion) { RsaSsaPkcs1PublicKey key = CreateValidPublicKey(); key.set_version(1); EXPECT_THAT(RsaSsaPkcs1VerifyKeyManager().ValidateKey(key), Not(IsOk())); } TEST(RsaSsaPkcs1VerifyKeyManagerTest, PublicKeyUnkownHashDisallowed) { RsaSsaPkcs1PublicKey key = CreateValidPublicKey(); key.mutable_params()->set_hash_type(HashType::UNKNOWN_HASH); EXPECT_THAT(RsaSsaPkcs1VerifyKeyManager().ValidateKey(key), Not(IsOk())); } TEST(RsaSsaPkcs1VerifyKeyManagerTest, ValidateKeyFormatSmallModulusDisallowed) { RsaSsaPkcs1PublicKey key = CreateValidPublicKey(); key.set_n("\x23"); key.set_e("\x3"); EXPECT_THAT(RsaSsaPkcs1VerifyKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("only modulus size >= 2048"))); } TEST(RsaSsaPkcs1SignKeyManagerTest, Create) { RsaSsaPkcs1KeyFormat key_format = CreateKeyFormat(HashType::SHA256, 3072, RSA_F4); StatusOr private_key_or = RsaSsaPkcs1SignKeyManager().CreateKey(key_format); ASSERT_THAT(private_key_or, IsOk()); RsaSsaPkcs1PrivateKey private_key = private_key_or.value(); RsaSsaPkcs1PublicKey public_key = RsaSsaPkcs1SignKeyManager().GetPublicKey(private_key).value(); internal::RsaPrivateKey private_key_subtle; private_key_subtle.n = private_key.public_key().n(); private_key_subtle.e = private_key.public_key().e(); private_key_subtle.d = util::SecretDataFromStringView(private_key.d()); private_key_subtle.p = util::SecretDataFromStringView(private_key.p()); private_key_subtle.q = util::SecretDataFromStringView(private_key.q()); private_key_subtle.dp = util::SecretDataFromStringView(private_key.dp()); private_key_subtle.dq = util::SecretDataFromStringView(private_key.dq()); private_key_subtle.crt = util::SecretDataFromStringView(private_key.crt()); auto direct_signer_or = subtle::RsaSsaPkcs1SignBoringSsl::New( private_key_subtle, {crypto::tink::subtle::HashType::SHA256}); auto verifier_or = RsaSsaPkcs1VerifyKeyManager().GetPrimitive(public_key); ASSERT_THAT(verifier_or, IsOk()); std::string message = "Some message"; EXPECT_THAT(verifier_or.value()->Verify( direct_signer_or.value()->Sign(message).value(), message), IsOk()); } TEST(RsaSsaPkcs1VerifyKeyManagerTest, NistTestVector) { // Test vector from // https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Digital-Signatures struct NistTestVector { std::string n; std::string e; std::string message; std::string signature; HashType hash_type; }; const NistTestVector nist_test_vector{ absl::HexStringToBytes( "c9548608087bed6be0a4623b9d849aa0b4b4b6114ad0a7d82578076ceefe26ce48d1" "448e16d69963510e1e5fc658f3cf8f32a489b62d93fec1cdea6e1dde3feba04bb6a0" "34518d83fd6138ea999982ab95d6a03517688ab6f8411c4a96b3e79d4141b8f68338" "a9baa99f4e2c7845b573981061c5fd29d5fc21833ff1b030b2deb651e51a291168e2" "b45ab4202dcd97b891925c75338e0e648d9d9ad325c10884e1fcdccc1c547b4a9c36" "aef939e8802b62405d6e3d358ffa88f206b976b87f8b12b827b0ee7823f9d1955f47" "f8678f7843b4cd03777e46717060e82bf149b36d4cf3d0bc7e4d0effde51a72f4ced" "8e8e5b11bdb135825ff08873e2f776929abb"), absl::HexStringToBytes("3c7bf9"), absl::HexStringToBytes( "bf082fa4b79f32849e8fae692696fc978ccb648c6e278d9bde4338d7b4632e3228b4" "77e6a0d2cd14c68d51abdeed7c8c577457ec9fa2eff93cbf03c019d4014e1dfb3115" "02d82f9265689e2d19f91b61c17a701c9ef50a69a55aae4cd57e67edc763c3f987ba" "3e46a2a6ffb680c3c25df46716e61228c832419e9f43916a4959"), absl::HexStringToBytes( "621120a71ff2a182dd2997beb2480f54be516b79a4c202d1d6f59270f8e4d4dbd625" "ac52fe0e49c5fd69dc0d15fb19ec58c9312a8161a61cb878abcb11399937f28ff080" "3877c239ce0b7c4cbc1e23eca22746b071b2716475424c12944660b929b6240aebe8" "47fcb94f63d212f3aa538515dc061e9810fdb0adeb374d0f69d24fd52c94e42668a4" "8fc0a57819952a40efb732cfa08b3d2b371780aea97be34efb5239994d7ee7c6ab91" "34b76711e76813ad5f5c3a5c95399e907650534dbfafec900c21be1308ddff6eda52" "5f35e4fb3d275de46250ea1e4b96b60bd125b85f6c52b5419a725cd69b10cefd0901" "abe7f9e15940594cf811e34c60f38768244c"), HashType::SHA256}; RsaSsaPkcs1PublicKey key; key.mutable_params()->set_hash_type(nist_test_vector.hash_type); key.set_version(0); key.set_n(nist_test_vector.n); key.set_e(nist_test_vector.e); auto result = RsaSsaPkcs1VerifyKeyManager().GetPrimitive(key); EXPECT_THAT(result, IsOk()); EXPECT_THAT(result.value()->Verify(nist_test_vector.signature, nist_test_vector.message), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pss_parameters.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pss_parameters.h" #include #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #else #include "openssl/bn.h" #endif #include "tink/big_integer.h" #include "tink/internal/bn_util.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/parameters.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { constexpr int kF4 = 65537; } // namespace RsaSsaPssParameters::Builder& RsaSsaPssParameters::Builder::SetModulusSizeInBits(int modulus_size_in_bits) { modulus_size_in_bits_ = modulus_size_in_bits; return *this; } RsaSsaPssParameters::Builder& RsaSsaPssParameters::Builder::SetPublicExponent( const BigInteger& public_exponent) { public_exponent_ = public_exponent; return *this; } RsaSsaPssParameters::Builder& RsaSsaPssParameters::Builder::SetSigHashType( HashType sig_hash_type) { sig_hash_type_ = sig_hash_type; return *this; } RsaSsaPssParameters::Builder& RsaSsaPssParameters::Builder::SetMgf1HashType( HashType mgf1_hash_type) { mgf1_hash_type_ = mgf1_hash_type; return *this; } RsaSsaPssParameters::Builder& RsaSsaPssParameters::Builder::SetSaltLengthInBytes(int salt_length_in_bytes) { salt_length_in_bytes_ = salt_length_in_bytes; return *this; } RsaSsaPssParameters::Builder& RsaSsaPssParameters::Builder::SetVariant( Variant variant) { variant_ = variant; return *this; } util::StatusOr RsaSsaPssParameters::Builder::Build() { if (!modulus_size_in_bits_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Key size is not set."); } if (!sig_hash_type_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Signature hash type is not set."); } if (!mgf1_hash_type_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "MGF1 hash type is not set."); } if (!salt_length_in_bytes_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Salt length is not set."); } if (!variant_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Variant is not set."); } if (*salt_length_in_bytes_ < 0) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid salt length in bytes: ", *salt_length_in_bytes_, ". Salt length must be positive.")); } // Validate hash. static const std::set* supported_hashes = new std::set( {HashType::kSha256, HashType::kSha384, HashType::kSha512}); if (supported_hashes->find(*sig_hash_type_) == supported_hashes->end()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create RsaSsaPss parameters with unknown SigHashType."); } if (supported_hashes->find(*mgf1_hash_type_) == supported_hashes->end()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create RsaSsaPss parameters with unknown Mgf1HashType."); } if (*sig_hash_type_ != *mgf1_hash_type_) { return util::Status(absl::StatusCode::kInvalidArgument, "Signature hash type and MGF1 hash type should match."); } // Validate modulus size. if (*modulus_size_in_bits_ < 2048) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid key size: must be at least 2048 bits, got ", *modulus_size_in_bits_, " bits.")); } // Validate the public exponent: public exponent needs to be odd, greater than // 65536 and (for consistency with BoringSSL), smaller that 32 bits. util::Status exponent_status = internal::ValidateRsaPublicExponent(public_exponent_.GetValue()); if (!exponent_status.ok()) { return exponent_status; } // Validate variant. static const std::set* supported_variants = new std::set({Variant::kTink, Variant::kCrunchy, Variant::kLegacy, Variant::kNoPrefix}); if (supported_variants->find(*variant_) == supported_variants->end()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create RsaSsaPss parameters with unknown variant."); } return RsaSsaPssParameters(*modulus_size_in_bits_, public_exponent_, *sig_hash_type_, *mgf1_hash_type_, *salt_length_in_bytes_, *variant_); } bool RsaSsaPssParameters::operator==(const Parameters& other) const { const RsaSsaPssParameters* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (modulus_size_in_bits_ != that->modulus_size_in_bits_) { return false; } if (public_exponent_ != that->public_exponent_) { return false; } if (sig_hash_type_ != that->sig_hash_type_) { return false; } if (mgf1_hash_type_ != that->mgf1_hash_type_) { return false; } if (salt_length_in_bytes_ != that->salt_length_in_bytes_) { return false; } if (variant_ != that->variant_) { return false; } return true; } // Returns the big endian encoded F4 value as a public exponent default. BigInteger RsaSsaPssParameters::Builder::CreateDefaultPublicExponent() { internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), kF4); std::string F4_string = internal::BignumToString(e.get(), BN_num_bytes(e.get())).value(); return BigInteger(F4_string); } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pss_parameters.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_RSA_SSA_PSS_PARAMETERS_H_ #define TINK_SIGNATURE_RSA_SSA_PSS_PARAMETERS_H_ #include #include "absl/types/optional.h" #include "tink/big_integer.h" #include "tink/parameters.h" #include "tink/signature/signature_parameters.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { class RsaSsaPssParameters : public SignatureParameters { public: // Description of the output prefix prepended to the signature. enum class Variant : int { // Prepends '0x01' to signature. kTink = 1, // Prepends '0x00' to signature. kCrunchy = 2, // Appends a 0-byte to input message BEFORE computing the signature, then // prepends '0x00' to signature. kLegacy = 3, // Does not prepend any prefix (i.e., keys must have no ID requirement). kNoPrefix = 4, // Added to guard from failures that may be caused by future expansions. kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Describes the hash algorithm used for computation. enum class HashType : int { kSha256 = 1, kSha384 = 2, kSha512 = 3, kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements = 20, }; // Creates RsaSsaPss parameters instances. class Builder { public: // Copyable and movable. Builder(const Builder& other) = default; Builder& operator=(const Builder& other) = default; Builder(Builder&& other) = default; Builder& operator=(Builder&& other) = default; // Creates initially empty parameters builder. Builder() = default; Builder& SetModulusSizeInBits(int modulus_size_in_bits); Builder& SetPublicExponent(const BigInteger& public_exponent); Builder& SetSigHashType(HashType sig_hash_type); Builder& SetMgf1HashType(HashType mgf1_hash_type); Builder& SetSaltLengthInBytes(int salt_length_in_bytes); Builder& SetVariant(Variant variant); // Creates RsaSsaPss parameters object from this builder. util::StatusOr Build(); private: static BigInteger CreateDefaultPublicExponent(); absl::optional modulus_size_in_bits_ = absl::nullopt; // Defaults to F4. BigInteger public_exponent_ = CreateDefaultPublicExponent(); absl::optional sig_hash_type_ = absl::nullopt; absl::optional mgf1_hash_type_ = absl::nullopt; absl::optional salt_length_in_bytes_ = absl::nullopt; absl::optional variant_ = absl::nullopt; }; // Copyable and movable. RsaSsaPssParameters(const RsaSsaPssParameters& other) = default; RsaSsaPssParameters& operator=(const RsaSsaPssParameters& other) = default; RsaSsaPssParameters(RsaSsaPssParameters&& other) = default; RsaSsaPssParameters& operator=(RsaSsaPssParameters&& other) = default; int GetModulusSizeInBits() const { return modulus_size_in_bits_; } const BigInteger& GetPublicExponent() const { return public_exponent_; } HashType GetSigHashType() const { return sig_hash_type_; } HashType GetMgf1HashType() const { return mgf1_hash_type_; } int GetSaltLengthInBytes() const { return salt_length_in_bytes_; } Variant GetVariant() const { return variant_; } bool HasIdRequirement() const override { return variant_ != Variant::kNoPrefix; } bool operator==(const Parameters& other) const override; private: explicit RsaSsaPssParameters(int modulus_size_in_bits, const BigInteger& public_exponent, HashType sig_hash_type, HashType mgf1_hash_type, int salt_length_in_bytes, Variant variant) : modulus_size_in_bits_(modulus_size_in_bits), public_exponent_(public_exponent), sig_hash_type_(sig_hash_type), mgf1_hash_type_(mgf1_hash_type), salt_length_in_bytes_(salt_length_in_bytes), variant_(variant) {} int modulus_size_in_bits_; BigInteger public_exponent_; HashType sig_hash_type_; HashType mgf1_hash_type_; int salt_length_in_bytes_; Variant variant_; }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_RSA_SSA_PSS_PARAMETERS_H_ ================================================ FILE: cc/signature/rsa_ssa_pss_parameters_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pss_parameters.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #else #include "openssl/bn.h" #endif #include "tink/big_integer.h" #include "tink/internal/bn_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::IsTrue; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { int modulus_size_in_bits; RsaSsaPssParameters::HashType hash_type; RsaSsaPssParameters::Variant variant; int salt_length_in_bytes; bool has_id_requirement; }; using RsaSsaPssParametersTest = TestWithParam; std::string PublicExponentToString(int64_t public_exponent) { internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), public_exponent); return internal::BignumToString(e.get(), BN_num_bytes(e.get())).value(); } const BigInteger& kF4 = *(new BigInteger(PublicExponentToString(65537))); INSTANTIATE_TEST_SUITE_P( RsaSsaPssParametersTestSuite, RsaSsaPssParametersTest, Values( TestCase{/*modulus_size=*/2048, RsaSsaPssParameters::HashType::kSha256, RsaSsaPssParameters::Variant::kTink, /*salt_length_in_bytes*/ 32, /*has_id_requirement=*/true}, TestCase{/*modulus_size=*/3072, RsaSsaPssParameters::HashType::kSha256, RsaSsaPssParameters::Variant::kCrunchy, /*salt_length_in_bytes*/ 32, /*has_id_requirement=*/true}, TestCase{/*modulus_size=*/2048, RsaSsaPssParameters::HashType::kSha384, RsaSsaPssParameters::Variant::kLegacy, /*salt_length_in_bytes*/ 48, /*has_id_requirement=*/true}, TestCase{/*modulus_size=*/3072, RsaSsaPssParameters::HashType::kSha512, RsaSsaPssParameters::Variant::kNoPrefix, /*salt_length_in_bytes*/ 64, /*has_id_requirement=*/false})); TEST_P(RsaSsaPssParametersTest, Build) { TestCase test_case = GetParam(); util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(test_case.modulus_size_in_bits) .SetPublicExponent(kF4) .SetSigHashType(test_case.hash_type) .SetMgf1HashType(test_case.hash_type) .SetSaltLengthInBytes(test_case.salt_length_in_bytes) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetModulusSizeInBits(), Eq(test_case.modulus_size_in_bits)); EXPECT_THAT(parameters->GetPublicExponent(), Eq(kF4)); EXPECT_THAT(parameters->GetSigHashType(), Eq(test_case.hash_type)); EXPECT_THAT(parameters->GetMgf1HashType(), Eq(test_case.hash_type)); EXPECT_THAT(parameters->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(parameters->HasIdRequirement(), Eq(test_case.has_id_requirement)); } TEST(RsaSsaPssParametersTest, BuildWithInvalidVariantFails) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssParametersTest, BuildWithoutVariantFails) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssParametersTest, BuildWithInvalidSigHashTypeFails) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType( RsaSsaPssParameters::HashType:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssParametersTest, BuildWithInvalidMgf1gHashTypeFails) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha512) .SetMgf1HashType( RsaSsaPssParameters::HashType:: kDoNotUseInsteadUseDefaultWhenWritingSwitchStatements) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssParametersTest, BuildWithDifferentSigAndMgf1HashTypesFails) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha384) .SetSaltLengthInBytes(48) .SetVariant(RsaSsaPssParameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssParametersTest, BuildWithoutSigHashTypeFails) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha512) .SetSaltLengthInBytes(64) .SetVariant(RsaSsaPssParameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssParametersTest, BuildWithoutMgf1HashTypeFails) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha512) .SetSaltLengthInBytes(64) .SetVariant(RsaSsaPssParameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssParametersTest, BuildWithLargeModulusSizeWorks) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(16789) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetModulusSizeInBits(), Eq(16789)); } TEST(RsaSsaPssParametersTest, BuildWithTooSmallModulusSizeFails) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2047) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssParametersTest, BuildWithoutModulusSizeFails) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssParametersTest, BuildWithoutSaltLengthFails) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetVariant(RsaSsaPssParameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssParametersTest, BuildWithNegativeSaltLengthFails) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(-32) .SetVariant(RsaSsaPssParameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssParametersTest, BuildWithValidNonF4PublicExponent) { BigInteger nonF4_public_exponent = BigInteger(PublicExponentToString(1234567)); util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(nonF4_public_exponent) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetPublicExponent(), Eq(nonF4_public_exponent)); } TEST(RsaSsaPssParametersTest, BuildWithoutPublicExponentDefaultsToF4) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetPublicExponent(), Eq(kF4)); } TEST(RsaSsaPssParametersTest, BuildWithSmallPublicExponentFails) { BigInteger small_public_exponent = BigInteger(PublicExponentToString(3)); util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(small_public_exponent) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssParametersTest, BuildWithEvenPublicExponentFails) { BigInteger even_public_exponent = BigInteger(PublicExponentToString(123456)); util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(even_public_exponent) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssParametersTest, BuildWithLargePublicExponent) { BigInteger large_public_exponent = BigInteger(PublicExponentToString(100000001L)); util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(large_public_exponent) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT(parameters->GetPublicExponent(), Eq(large_public_exponent)); } TEST(RsaSsaPssParametersTest, BuildWithTooLargePublicExponent) { // Public exponent must be smaller than 32 bits. BigInteger too_large_public_exponent = BigInteger(PublicExponentToString(4294967297L)); util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(too_large_public_exponent) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kNoPrefix) .Build(); EXPECT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssParametersTest, CopyConstructor) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha512) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha512) .SetSaltLengthInBytes(64) .SetVariant(RsaSsaPssParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); RsaSsaPssParameters copy(*parameters); EXPECT_THAT(copy.GetVariant(), Eq(RsaSsaPssParameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); EXPECT_THAT(parameters->GetModulusSizeInBits(), Eq(2048)); EXPECT_THAT(parameters->GetPublicExponent(), Eq(kF4)); EXPECT_THAT(parameters->GetSigHashType(), Eq(RsaSsaPssParameters::HashType::kSha512)); EXPECT_THAT(parameters->GetMgf1HashType(), Eq(RsaSsaPssParameters::HashType::kSha512)); EXPECT_THAT(parameters->GetSaltLengthInBytes(), Eq(64)); } TEST(RsaSsaPssParametersTest, CopyAssignment) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha512) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha512) .SetSaltLengthInBytes(64) .SetVariant(RsaSsaPssParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); RsaSsaPssParameters copy = *parameters; EXPECT_THAT(copy.GetVariant(), Eq(RsaSsaPssParameters::Variant::kTink)); EXPECT_THAT(copy.HasIdRequirement(), IsTrue()); EXPECT_THAT(parameters->GetModulusSizeInBits(), Eq(2048)); EXPECT_THAT(parameters->GetPublicExponent(), Eq(kF4)); EXPECT_THAT(parameters->GetSigHashType(), Eq(RsaSsaPssParameters::HashType::kSha512)); EXPECT_THAT(parameters->GetMgf1HashType(), Eq(RsaSsaPssParameters::HashType::kSha512)); EXPECT_THAT(parameters->GetSaltLengthInBytes(), Eq(64)); } TEST_P(RsaSsaPssParametersTest, ParametersEquals) { TestCase test_case = GetParam(); util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(test_case.modulus_size_in_bits) .SetPublicExponent(kF4) .SetSigHashType(test_case.hash_type) .SetMgf1HashType(test_case.hash_type) .SetSaltLengthInBytes(test_case.salt_length_in_bytes) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(test_case.modulus_size_in_bits) .SetPublicExponent(kF4) .SetSigHashType(test_case.hash_type) .SetMgf1HashType(test_case.hash_type) .SetSaltLengthInBytes(test_case.salt_length_in_bytes) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters == *other_parameters); EXPECT_TRUE(*other_parameters == *parameters); EXPECT_FALSE(*parameters != *other_parameters); EXPECT_FALSE(*other_parameters != *parameters); } TEST(RsaSsaPssParametersTest, VariantNotEqual) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha512) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha512) .SetSaltLengthInBytes(64) .SetVariant(RsaSsaPssParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha512) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha512) .SetSaltLengthInBytes(64) .SetVariant(RsaSsaPssParameters::Variant::kCrunchy) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(RsaSsaPssParametersTest, HashTypeNotEqual) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha512) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha512) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kTink) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(RsaSsaPssParametersTest, SaltLengthNotEqual) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(62) .SetVariant(RsaSsaPssParameters::Variant::kTink) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(RsaSsaPssParametersTest, ModulusSizeNotEqual) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr other_parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(3072) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kTink) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } TEST(RsaSsaPssParametersTest, PublicExponentNotEqual) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetVariant(RsaSsaPssParameters::Variant::kTink) .SetModulusSizeInBits(2048) .SetSigHashType(RsaSsaPssParameters::HashType::kSha512) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha512) .SetSaltLengthInBytes(64) .SetPublicExponent(kF4) .Build(); ASSERT_THAT(parameters, IsOk()); BigInteger nonF4_public_exponent = BigInteger(PublicExponentToString(1234567)); util::StatusOr other_parameters = RsaSsaPssParameters::Builder() .SetVariant(RsaSsaPssParameters::Variant::kTink) .SetModulusSizeInBits(2048) .SetPublicExponent(nonF4_public_exponent) .SetSigHashType(RsaSsaPssParameters::HashType::kSha512) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha512) .SetSaltLengthInBytes(64) .Build(); ASSERT_THAT(other_parameters, IsOk()); EXPECT_TRUE(*parameters != *other_parameters); EXPECT_FALSE(*parameters == *other_parameters); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pss_private_key.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pss_private_key.h" #include "absl/status/status.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #endif #include "openssl/rsa.h" #include "tink/big_integer.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/bn_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_big_integer.h" #include "tink/signature/rsa_ssa_pss_public_key.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { util::Status ValidateKeyPair( const BigInteger& public_exponent, const BigInteger& modulus, const RestrictedBigInteger& p, const RestrictedBigInteger& q, const RestrictedBigInteger& d, const RestrictedBigInteger& dp, const RestrictedBigInteger& dq, const RestrictedBigInteger& q_inv) { internal::SslUniquePtr rsa(RSA_new()); if (rsa.get() == nullptr) { return util::Status(absl::StatusCode::kInternal, "Internal RSA allocation error"); } util::StatusOr> n = internal::StringToBignum(modulus.GetValue()); if (!n.ok()) { return n.status(); } util::StatusOr> e = internal::StringToBignum(public_exponent.GetValue()); if (!e.ok()) { return e.status(); } util::StatusOr> d_bn = internal::StringToBignum(d.GetSecret(InsecureSecretKeyAccess::Get())); if (!d_bn.ok()) { return d_bn.status(); } util::StatusOr> p_bn = internal::StringToBignum(p.GetSecret(InsecureSecretKeyAccess::Get())); if (!p_bn.ok()) { return p_bn.status(); } util::StatusOr> q_bn = internal::StringToBignum(q.GetSecret(InsecureSecretKeyAccess::Get())); if (!q_bn.ok()) { return q_bn.status(); } util::StatusOr> dp_bn = internal::StringToBignum(dp.GetSecret(InsecureSecretKeyAccess::Get())); if (!dp_bn.ok()) { return dp_bn.status(); } util::StatusOr> dq_bn = internal::StringToBignum(dq.GetSecret(InsecureSecretKeyAccess::Get())); if (!dq_bn.ok()) { return dq_bn.status(); } util::StatusOr> q_inv_bn = internal::StringToBignum(q_inv.GetSecret(InsecureSecretKeyAccess::Get())); if (!q_inv_bn.ok()) { return q_inv_bn.status(); } // Build RSA key from the given values. The RSA object takes ownership of the // given values after the call. if (RSA_set0_key(rsa.get(), n->release(), e->release(), d_bn->release()) != 1 || RSA_set0_factors(rsa.get(), p_bn->release(), q_bn->release()) != 1 || RSA_set0_crt_params(rsa.get(), dp_bn->release(), dq_bn->release(), q_inv_bn->release()) != 1) { return util::Status(absl::StatusCode::kInternal, "Internal RSA key loading error"); } // Validate key. int check_key_status = RSA_check_key(rsa.get()); if (check_key_status == 0) { return util::Status(absl::StatusCode::kInvalidArgument, "RSA key pair is not valid"); } if (check_key_status == -1) { return util::Status(absl::StatusCode::kInternal, "An error ocurred while checking the key"); } #ifdef OPENSSL_IS_BORINGSSL if (RSA_check_fips(rsa.get()) == 0) { return util::Status(absl::StatusCode::kInvalidArgument, "RSA key pair is not valid in FIPS mode"); } #endif return util::OkStatus(); } } // namespace RsaSsaPssPrivateKey::Builder& RsaSsaPssPrivateKey::Builder::SetPublicKey( const RsaSsaPssPublicKey& public_key) { public_key_ = public_key; return *this; } RsaSsaPssPrivateKey::Builder& RsaSsaPssPrivateKey::Builder::SetPrimeP( const RestrictedBigInteger& p) { p_ = p; return *this; } RsaSsaPssPrivateKey::Builder& RsaSsaPssPrivateKey::Builder::SetPrimeQ( const RestrictedBigInteger& q) { q_ = q; return *this; } RsaSsaPssPrivateKey::Builder& RsaSsaPssPrivateKey::Builder::SetPrimeExponentP( const RestrictedBigInteger& dp) { dp_ = dp; return *this; } RsaSsaPssPrivateKey::Builder& RsaSsaPssPrivateKey::Builder::SetPrimeExponentQ( const RestrictedBigInteger& dq) { dq_ = dq; return *this; } RsaSsaPssPrivateKey::Builder& RsaSsaPssPrivateKey::Builder::SetPrivateExponent( const RestrictedBigInteger& d) { d_ = d; return *this; } RsaSsaPssPrivateKey::Builder& RsaSsaPssPrivateKey::Builder::SetCrtCoefficient( const RestrictedBigInteger& q_inv) { q_inv_ = q_inv; return *this; } util::StatusOr RsaSsaPssPrivateKey::Builder::Build( PartialKeyAccessToken token) { if (!public_key_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Cannot build without setting the public key"); } if (!p_.has_value() || !q_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Cannot build without setting both prime factors"); } if (!dp_.has_value() || !dq_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Cannot build without setting both prime exponents"); } if (!d_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Cannot build without setting the private exponent"); } if (!q_inv_.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "Cannot build without setting the CRT coefficient"); } // Validate key pair. util::Status key_pair_validation = ValidateKeyPair( public_key_->GetParameters().GetPublicExponent(), public_key_->GetModulus(token), *p_, *q_, *d_, *dp_, *dq_, *q_inv_); if (!key_pair_validation.ok()) { return key_pair_validation; } return RsaSsaPssPrivateKey(*public_key_, *p_, *q_, *dp_, *dq_, *d_, *q_inv_); } bool RsaSsaPssPrivateKey::operator==(const Key& other) const { const RsaSsaPssPrivateKey* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (GetPublicKey() != that->GetPublicKey()) { return false; } if (p_ != that->p_) { return false; } if (q_ != that->q_) { return false; } if (dp_ != that->dp_) { return false; } if (dq_ != that->dq_) { return false; } if (d_ != that->d_) { return false; } return q_inv_ == that->q_inv_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pss_private_key.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_RSA_SSA_PSS_PRIVATE_KEY_H_ #define TINK_SIGNATURE_RSA_SSA_PSS_PRIVATE_KEY_H_ #include "absl/types/optional.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/restricted_big_integer.h" #include "tink/signature/rsa_ssa_pss_public_key.h" #include "tink/signature/signature_private_key.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { class RsaSsaPssPrivateKey : public SignaturePrivateKey { public: // Copyable and movable. RsaSsaPssPrivateKey(const RsaSsaPssPrivateKey& other) = default; RsaSsaPssPrivateKey& operator=(const RsaSsaPssPrivateKey& other) = default; RsaSsaPssPrivateKey(RsaSsaPssPrivateKey&& other) = default; RsaSsaPssPrivateKey& operator=(RsaSsaPssPrivateKey&& other) = default; // Creates RsaSsaPss private key instances. class Builder { public: // Copyable and movable. Builder(const Builder& other) = default; Builder& operator=(const Builder& other) = default; Builder(Builder&& other) = default; Builder& operator=(Builder&& other) = default; // Creates initially empty private key builder. Builder() = default; Builder& SetPublicKey(const RsaSsaPssPublicKey& public_key); Builder& SetPrimeP(const RestrictedBigInteger& p); Builder& SetPrimeQ(const RestrictedBigInteger& q); Builder& SetPrimeExponentP(const RestrictedBigInteger& dp); Builder& SetPrimeExponentQ(const RestrictedBigInteger& dq); Builder& SetPrivateExponent(const RestrictedBigInteger& d); Builder& SetCrtCoefficient(const RestrictedBigInteger& q_inv); // Creates RsaSsaPss private key object from this builder. util::StatusOr Build(PartialKeyAccessToken token); private: absl::optional public_key_; absl::optional p_; absl::optional q_; absl::optional dp_; absl::optional dq_; absl::optional d_; absl::optional q_inv_; }; const RestrictedBigInteger& GetPrimeP(PartialKeyAccessToken token) const { return p_; } const RestrictedBigInteger& GetPrimeQ(PartialKeyAccessToken token) const { return q_; } const RestrictedBigInteger& GetPrivateExponent() const { return d_; } const RestrictedBigInteger& GetPrimeExponentP() const { return dp_; } const RestrictedBigInteger& GetPrimeExponentQ() const { return dq_; } const RestrictedBigInteger& GetCrtCoefficient() const { return q_inv_; } const RsaSsaPssPublicKey& GetPublicKey() const override { return public_key_; } bool operator==(const Key& other) const override; private: explicit RsaSsaPssPrivateKey(const RsaSsaPssPublicKey& public_key, const RestrictedBigInteger& p, const RestrictedBigInteger& q, const RestrictedBigInteger& dp, const RestrictedBigInteger& dq, const RestrictedBigInteger& d, const RestrictedBigInteger& q_inv) : public_key_(public_key), p_(p), q_(q), dp_(dp), dq_(dq), d_(d), q_inv_(q_inv) {} RsaSsaPssPublicKey public_key_; RestrictedBigInteger p_; RestrictedBigInteger q_; RestrictedBigInteger dp_; RestrictedBigInteger dq_; RestrictedBigInteger d_; RestrictedBigInteger q_inv_; }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_RSA_SSA_PSS_PRIVATE_KEY_H_ ================================================ FILE: cc/signature/rsa_ssa_pss_private_key_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pss_private_key.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/log/check.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #endif #include "openssl/bn.h" #include "openssl/rsa.h" #include "tink/big_integer.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/bn_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/partial_key_access.h" #include "tink/restricted_big_integer.h" #include "tink/signature/rsa_ssa_pss_parameters.h" #include "tink/signature/rsa_ssa_pss_public_key.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::NotNull; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { RsaSsaPssParameters::HashType hash_type; RsaSsaPssParameters::Variant variant; int salt_length_in_bytes; absl::optional id_requirement; std::string output_prefix; }; struct PrivateValues { RestrictedBigInteger p; RestrictedBigInteger q; RestrictedBigInteger dp; RestrictedBigInteger dq; RestrictedBigInteger d; RestrictedBigInteger q_inv; }; constexpr int kModulusSizeInBits = 2048; // Test vector from https://www.rfc-editor.org/rfc/rfc7517#appendix-C.1 constexpr absl::string_view k2048BitRsaModulus = "t6Q8PWSi1dkJj9hTP8hNYFlvadM7DflW9mWepOJhJ66w7nyoK1gPNqFMSQRyO125Gp-" "TEkodhWr0iujjHVx7BcV0llS4w5ACGgPrcAd6ZcSR0-Iqom-QFcNP8Sjg086MwoqQU_" "LYywlAGZ21WSdS_" "PERyGFiNnj3QQlO8Yns5jCtLCRwLHL0Pb1fEv45AuRIuUfVcPySBWYnDyGxvjYGDSM-" "AqWS9zIQ2ZilgT-GqUmipg0XOC0Cc20rgLe2ymLHjpHciCKVAbY5-L32-lSeZO-Os6U15_" "aXrk9Gw8cPUaX1_I8sLGuSiVdt3C_Fn2PZ3Z8i744FPFGGcG1qs2Wz-Q"; constexpr absl::string_view kD = "GRtbIQmhOZtyszfgKdg4u_N-R_mZGU_9k7JQ_jn1DnfTuMdSNprTeaSTyWfS" "NkuaAwnOEbIQVy1IQbWVV25NY3ybc_IhUJtfri7bAXYEReWaCl3hdlPKXy9U" "vqPYGR0kIXTQRqns-dVJ7jahlI7LyckrpTmrM8dWBo4_PMaenNnPiQgO0xnu" "ToxutRZJfJvG4Ox4ka3GORQd9CsCZ2vsUDmsXOfUENOyMqADC6p1M3h33tsu" "rY15k9qMSpG9OX_IJAXmxzAh_tWiZOwk2K4yxH9tS3Lq1yX8C1EWmeRDkK2a" "hecG85-oLKQt5VEpWHKmjOi_gJSdSgqcN96X52esAQ"; constexpr absl::string_view kP = "2rnSOV4hKSN8sS4CgcQHFbs08XboFDqKum3sc4h3GRxrTmQdl1ZK9uw-PIHf" "QP0FkxXVrx-WE-ZEbrqivH_2iCLUS7wAl6XvARt1KkIaUxPPSYB9yk31s0Q8" "UK96E3_OrADAYtAJs-M3JxCLfNgqh56HDnETTQhH3rCT5T3yJws"; constexpr absl::string_view kQ = "1u_RiFDP7LBYh3N4GXLT9OpSKYP0uQZyiaZwBtOCBNJgQxaj10RWjsZu0c6Iedis4S7B_" "coSKB0Kj9PaPaBzg-IySRvvcQuPamQu66riMhjVtG6TlV8CLCYKrYl52ziqK0E_" "ym2QnkwsUX7eYTB7LbAHRK9GqocDE5B0f808I4s"; constexpr absl::string_view kDp = "KkMTWqBUefVwZ2_Dbj1pPQqyHSHjj90L5x_" "MOzqYAJMcLMZtbUtwKqvVDq3tbEo3ZIcohbDtt6SbfmWzggabpQxNxuBpoOOf_a_HgMXK_" "lhqigI4y_kqS1wY52IwjUn5rgRrJ-yYo1h41KR-vz2pYhEAeYrhttWtxVqLCRViD6c"; constexpr absl::string_view kDq = "AvfS0-gRxvn0bwJoMSnFxYcK1WnuEjQFluMGfwGitQBWtfZ1Er7t1xDkbN9" "GQTB9yqpDoYaN06H7CFtrkxhJIBQaj6nkF5KKS3TQtQ5qCzkOkmxIe3KRbBy" "mXxkb5qwUpX5ELD5xFc6FeiafWYY63TmmEAu_lRFCOJ3xDea-ots"; constexpr absl::string_view kQInv = "lSQi-w9CpyUReMErP1RsBLk7wNtOvs5EQpPqmuMvqW57NBUczScEoPwmUqq" "abu9V0-Py4dQ57_bapoKRu1R90bvuFnU63SHWEFglZQvJDMeAvmj4sm-Fp0o" "Yu_neotgQ0hzbI5gry7ajdYy9-2lNx_76aBZoOUu9HCJ-UsfSOI8"; const BigInteger& kF4 = *new BigInteger(std::string("\x1\0\x1", 3)); // 65537 std::string Base64WebSafeDecode(absl::string_view base64_string) { std::string dest; CHECK(absl::WebSafeBase64Unescape(base64_string, &dest)) << "Failed to base64 decode."; return dest; } PrivateValues GetValidPrivateValues() { return PrivateValues{ /*p=*/RestrictedBigInteger(Base64WebSafeDecode(kP), InsecureSecretKeyAccess::Get()), /*q=*/ RestrictedBigInteger(Base64WebSafeDecode(kQ), InsecureSecretKeyAccess::Get()), /*dp=*/ RestrictedBigInteger(Base64WebSafeDecode(kDp), InsecureSecretKeyAccess::Get()), /*dq=*/ RestrictedBigInteger(Base64WebSafeDecode(kDq), InsecureSecretKeyAccess::Get()), /*d=*/ RestrictedBigInteger(Base64WebSafeDecode(kD), InsecureSecretKeyAccess::Get()), /*q_inv=*/ RestrictedBigInteger(Base64WebSafeDecode(kQInv), InsecureSecretKeyAccess::Get())}; } RsaSsaPssPublicKey GetValidPublicKey() { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(kModulusSizeInBits) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kNoPrefix) .Build(); CHECK_OK(parameters.status()) << "Failed to create parameters."; BigInteger modulus(Base64WebSafeDecode(k2048BitRsaModulus)); util::StatusOr public_key = RsaSsaPssPublicKey::Create( *parameters, modulus, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); CHECK_OK(public_key.status()) << "Failed to create public key."; return *public_key; } std::string FlipFirstByte(absl::string_view str) { std::string res(str); res[0] = ~res[0]; return res; } using RsaSsaPssPrivateKeyTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( RsaSsaPssPrivateKeyTestSuite, RsaSsaPssPrivateKeyTest, Values(TestCase{RsaSsaPssParameters::HashType::kSha256, RsaSsaPssParameters::Variant::kTink, /*salt_length_in_bytes*/ 0, /*id_requirement=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{RsaSsaPssParameters::HashType::kSha256, RsaSsaPssParameters::Variant::kCrunchy, /*salt_length_in_bytes*/ 32, /*id_requirement=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{RsaSsaPssParameters::HashType::kSha384, RsaSsaPssParameters::Variant::kLegacy, /*salt_length_in_bytes*/ 48, /*id_requirement=*/0x07080910, /*output_prefix=*/std::string("\x00\x07\x08\x09\x10", 5)}, TestCase{RsaSsaPssParameters::HashType::kSha512, RsaSsaPssParameters::Variant::kNoPrefix, /*salt_length_in_bytes*/ 64, /*id_requirement=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(RsaSsaPssPrivateKeyTest, BuildPrivateKeySucceeds) { TestCase test_case = GetParam(); util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(kModulusSizeInBits) .SetPublicExponent(kF4) .SetSigHashType(test_case.hash_type) .SetMgf1HashType(test_case.hash_type) .SetSaltLengthInBytes(test_case.salt_length_in_bytes) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); BigInteger modulus(Base64WebSafeDecode(k2048BitRsaModulus)); util::StatusOr public_key = RsaSsaPssPublicKey::Create( *parameters, modulus, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key = RsaSsaPssPrivateKey::Builder() .SetPublicKey(*public_key) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); EXPECT_THAT(private_key->GetParameters(), Eq(*parameters)); EXPECT_THAT(private_key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(private_key->GetPublicKey(), Eq(*public_key)); EXPECT_THAT(private_key->GetOutputPrefix(), Eq(test_case.output_prefix)); EXPECT_THAT(private_key->GetPrimeP(GetPartialKeyAccess()), Eq(private_values.p)); EXPECT_THAT(private_key->GetPrimeQ(GetPartialKeyAccess()), Eq(private_values.q)); EXPECT_THAT(private_key->GetPrimeExponentP(), Eq(private_values.dp)); EXPECT_THAT(private_key->GetPrimeExponentQ(), Eq(private_values.dq)); EXPECT_THAT(private_key->GetCrtCoefficient(), Eq(private_values.q_inv)); EXPECT_THAT(private_key->GetPrivateExponent(), Eq(private_values.d)); } TEST(RsaSsaPssPrivateKeyTest, BuildPrivateKeyFromBoringSsl) { internal::SslUniquePtr rsa(RSA_new()); ASSERT_THAT(rsa, NotNull()); // Set public exponent to 65537. internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), 65537); // Generate an RSA key pair and get the values. ASSERT_THAT(RSA_generate_key_ex(rsa.get(), 2048, e.get(), /*cb=*/nullptr), Eq(1)); const BIGNUM *n_bn, *e_bn, *d_bn, *p_bn, *q_bn, *dp_bn, *dq_bn, *q_inv_bn; RSA_get0_key(rsa.get(), &n_bn, &e_bn, &d_bn); RSA_get0_factors(rsa.get(), &p_bn, &q_bn); RSA_get0_crt_params(rsa.get(), &dp_bn, &dq_bn, &q_inv_bn); util::StatusOr n_str = internal::BignumToString(n_bn, BN_num_bytes(n_bn)); ASSERT_THAT(n_str, IsOk()); util::StatusOr e_str = internal::BignumToString(e_bn, BN_num_bytes(e_bn)); ASSERT_THAT(e_str, IsOk()); util::StatusOr d_str = internal::BignumToString(d_bn, BN_num_bytes(d_bn)); ASSERT_THAT(d_str, IsOk()); util::StatusOr p_str = internal::BignumToString(p_bn, BN_num_bytes(p_bn)); ASSERT_THAT(p_str, IsOk()); util::StatusOr q_str = internal::BignumToString(q_bn, BN_num_bytes(q_bn)); ASSERT_THAT(q_str, IsOk()); util::StatusOr dp_str = internal::BignumToString(dp_bn, BN_num_bytes(dp_bn)); ASSERT_THAT(dp_str, IsOk()); util::StatusOr dq_str = internal::BignumToString(dq_bn, BN_num_bytes(dq_bn)); ASSERT_THAT(dq_str, IsOk()); util::StatusOr q_inv_str = internal::BignumToString(q_inv_bn, BN_num_bytes(q_inv_bn)); ASSERT_THAT(q_inv_str, IsOk()); util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(BigInteger(*e_str)) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr public_key = RsaSsaPssPublicKey::Create( *parameters, /*modulus=*/BigInteger(*n_str), /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = RsaSsaPssPrivateKey::Builder() .SetPublicKey(*public_key) .SetPrimeP( RestrictedBigInteger(*p_str, InsecureSecretKeyAccess::Get())) .SetPrimeQ( RestrictedBigInteger(*q_str, InsecureSecretKeyAccess::Get())) .SetPrimeExponentP( RestrictedBigInteger(*dp_str, InsecureSecretKeyAccess::Get())) .SetPrimeExponentQ( RestrictedBigInteger(*dq_str, InsecureSecretKeyAccess::Get())) .SetPrivateExponent( RestrictedBigInteger(*d_str, InsecureSecretKeyAccess::Get())) .SetCrtCoefficient( RestrictedBigInteger(*q_inv_str, InsecureSecretKeyAccess::Get())) .Build(GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); EXPECT_THAT(private_key->GetParameters(), Eq(*parameters)); EXPECT_THAT(private_key->GetPublicKey(), Eq(*public_key)); EXPECT_THAT(private_key->GetPrimeP(GetPartialKeyAccess()) .GetSecret(InsecureSecretKeyAccess::Get()), Eq(*p_str)); EXPECT_THAT(private_key->GetPrimeQ(GetPartialKeyAccess()) .GetSecret(InsecureSecretKeyAccess::Get()), Eq(*q_str)); EXPECT_THAT(private_key->GetPrimeExponentP().GetSecret( InsecureSecretKeyAccess::Get()), Eq(*dp_str)); EXPECT_THAT(private_key->GetPrimeExponentQ().GetSecret( InsecureSecretKeyAccess::Get()), Eq(*dq_str)); EXPECT_THAT(private_key->GetCrtCoefficient().GetSecret( InsecureSecretKeyAccess::Get()), Eq(*q_inv_str)); EXPECT_THAT(private_key->GetPrivateExponent().GetSecret( InsecureSecretKeyAccess::Get()), Eq(*d_str)); EXPECT_THAT(private_key->GetIdRequirement(), Eq(absl::nullopt)); EXPECT_THAT(private_key->GetOutputPrefix(), Eq("")); } TEST(RsaSsaPssPrivateKeyTest, BuildPrivateKeyValidatesModulus) { RsaSsaPssPublicKey public_key = GetValidPublicKey(); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr public_key_modified_modulus = RsaSsaPssPublicKey::Create( public_key.GetParameters(), BigInteger(FlipFirstByte(Base64WebSafeDecode(k2048BitRsaModulus))), /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key_modified_modulus, IsOk()); util::StatusOr private_key_modified_modulus = RsaSsaPssPrivateKey::Builder() .SetPublicKey(*public_key_modified_modulus) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_modified_modulus.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssPrivateKeyTest, BuildPrivateKeyValidatesPrimeP) { RsaSsaPssPublicKey public_key = GetValidPublicKey(); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_modified_prime_p = RsaSsaPssPrivateKey::Builder() .SetPublicKey(public_key) .SetPrimeP( RestrictedBigInteger(FlipFirstByte(Base64WebSafeDecode(kP)), InsecureSecretKeyAccess::Get())) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_modified_prime_p.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssPrivateKeyTest, BuildPrivateKeyValidatesPrimeQ) { RsaSsaPssPublicKey public_key = GetValidPublicKey(); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_modified_prime_q = RsaSsaPssPrivateKey::Builder() .SetPublicKey(public_key) .SetPrimeP(private_values.p) .SetPrimeQ( RestrictedBigInteger(FlipFirstByte(Base64WebSafeDecode(kQ)), InsecureSecretKeyAccess::Get())) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_modified_prime_q.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssPrivateKeyTest, BuildPrivateKeyValidatesPrimeExponentP) { RsaSsaPssPublicKey public_key = GetValidPublicKey(); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_modified_prime_exponent_p = RsaSsaPssPrivateKey::Builder() .SetPublicKey(public_key) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP( RestrictedBigInteger(FlipFirstByte(Base64WebSafeDecode(kDp)), InsecureSecretKeyAccess::Get())) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_modified_prime_exponent_p.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssPrivateKeyTest, BuildPrivateKeyValidatesPrimeExponentQ) { RsaSsaPssPublicKey public_key = GetValidPublicKey(); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_modified_prime_exponent_q = RsaSsaPssPrivateKey::Builder() .SetPublicKey(public_key) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ( RestrictedBigInteger(FlipFirstByte(Base64WebSafeDecode(kDq)), InsecureSecretKeyAccess::Get())) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_modified_prime_exponent_q.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssPrivateKeyTest, BuildPrivateKeyValidatesPrivateExponent) { RsaSsaPssPublicKey public_key = GetValidPublicKey(); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_modified_private_exponent = RsaSsaPssPrivateKey::Builder() .SetPublicKey(public_key) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent( RestrictedBigInteger(FlipFirstByte(Base64WebSafeDecode(kD)), InsecureSecretKeyAccess::Get())) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_modified_private_exponent.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssPrivateKeyTest, BuildPrivateKeyValidatesCrtCoefficient) { RsaSsaPssPublicKey public_key = GetValidPublicKey(); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_modified_crt_coefficient = RsaSsaPssPrivateKey::Builder() .SetPublicKey(public_key) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient( RestrictedBigInteger(FlipFirstByte(Base64WebSafeDecode(kQInv)), InsecureSecretKeyAccess::Get())) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_modified_crt_coefficient.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssPrivateKeyTest, BuildPublicKeyNotSetFails) { PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_no_public_key_set = RsaSsaPssPrivateKey::Builder() .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_no_public_key_set.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssPrivateKeyTest, BuildPrimePNotSetFails) { PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_no_prime_p_set = RsaSsaPssPrivateKey::Builder() .SetPublicKey(GetValidPublicKey()) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_no_prime_p_set.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssPrivateKeyTest, BuildPrimeQNotSetFails) { PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_no_prime_q_set = RsaSsaPssPrivateKey::Builder() .SetPublicKey(GetValidPublicKey()) .SetPrimeP(private_values.p) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_no_prime_q_set.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssPrivateKeyTest, BuildPrimeExponentPNotSetFails) { PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_no_prime_exponent_p_set = RsaSsaPssPrivateKey::Builder() .SetPublicKey(GetValidPublicKey()) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_no_prime_exponent_p_set.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssPrivateKeyTest, BuildPrimeExponentQNotSetFails) { PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_no_prime_exponent_q_set = RsaSsaPssPrivateKey::Builder() .SetPublicKey(GetValidPublicKey()) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_no_prime_exponent_q_set.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssPrivateKeyTest, BuildPrivateExponentNotSetFails) { PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_no_private_exponent_set = RsaSsaPssPrivateKey::Builder() .SetPublicKey(GetValidPublicKey()) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_no_private_exponent_set.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssPrivateKeyTest, BuildCrtCoefficientNotSetFails) { PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key_no_crt_coefficient_set = RsaSsaPssPrivateKey::Builder() .SetPublicKey(GetValidPublicKey()) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key_no_crt_coefficient_set.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(RsaSsaPssPrivateKeyTest, CreateMismatchedKeyPairFails) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); // Test vector from // https://github.com/google/wycheproof/blob/master/testvectors/rsa_pss_2048_sha256_mgf1_32_test.json BigInteger mismatched_modulus(absl::HexStringToBytes( "00a2b451a07d0aa5f96e455671513550514a8a5b462ebef717094fa1fee82224e637f974" "6d3f7cafd31878d80325b6ef5a1700f65903b469429e89d6eac8845097b5ab393189db92" "512ed8a7711a1253facd20f79c15e8247f3d3e42e46e48c98e254a2fe9765313a03eff8f" "17e1a029397a1fa26a8dce26f490ed81299615d9814c22da610428e09c7d9658594266f5" "c021d0fceca08d945a12be82de4d1ece6b4c03145b5d3495d4ed5411eb878daf05fd7afc" "3e09ada0f1126422f590975a1969816f48698bcbba1b4d9cae79d460d8f9f85e7975005d" "9bc22c4e5ac0f7c1a45d12569a62807d3b9a02e5a530e773066f453d1f5b4c2e9cf78202" "83f742b9d5")); util::StatusOr public_key = RsaSsaPssPublicKey::Create( *parameters, mismatched_modulus, /*id_requirement=*/0x02030400, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key = RsaSsaPssPrivateKey::Builder() .SetPublicKey(*public_key) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); EXPECT_THAT(private_key.status(), StatusIs(absl::StatusCode ::kInvalidArgument)); } TEST_P(RsaSsaPssPrivateKeyTest, PrivateKeyEquals) { TestCase test_case = GetParam(); util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(kModulusSizeInBits) .SetPublicExponent(kF4) .SetSigHashType(test_case.hash_type) .SetMgf1HashType(test_case.hash_type) .SetSaltLengthInBytes(test_case.salt_length_in_bytes) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); BigInteger modulus(Base64WebSafeDecode(k2048BitRsaModulus)); util::StatusOr public_key = RsaSsaPssPublicKey::Create( *parameters, modulus, /*id_requirement=*/test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key = RsaSsaPssPrivateKey::Builder() .SetPublicKey(*public_key) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr same_private_key = RsaSsaPssPrivateKey::Builder() .SetPublicKey(*public_key) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); ASSERT_THAT(same_private_key, IsOk()); EXPECT_TRUE(*private_key == *same_private_key); EXPECT_TRUE(*same_private_key == *private_key); EXPECT_FALSE(*private_key != *same_private_key); EXPECT_FALSE(*same_private_key != *private_key); } TEST(RsaSsaPssPrivateKeyTest, DifferentPublicKeyNotEqual) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); BigInteger modulus(Base64WebSafeDecode(k2048BitRsaModulus)); util::StatusOr public_key1 = RsaSsaPssPublicKey::Create( *parameters, modulus, /*id_requirement=*/0x02030400, GetPartialKeyAccess()); ASSERT_THAT(public_key1, IsOk()); util::StatusOr public_key2 = RsaSsaPssPublicKey::Create( *parameters, modulus, /*id_requirement=*/0x01030005, GetPartialKeyAccess()); ASSERT_THAT(public_key2, IsOk()); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key1 = RsaSsaPssPrivateKey::Builder() .SetPublicKey(*public_key1) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); ASSERT_THAT(private_key1, IsOk()); util::StatusOr private_key2 = RsaSsaPssPrivateKey::Builder() .SetPublicKey(*public_key2) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); ASSERT_THAT(private_key2, IsOk()); EXPECT_TRUE(*private_key1 != *private_key2); EXPECT_TRUE(*private_key2 != *private_key1); EXPECT_FALSE(*private_key1 == *private_key2); EXPECT_FALSE(*private_key2 == *private_key1); } TEST(RsaSsaPssPrivateKeyTest, DifferentKeyTypesNotEqual) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); BigInteger modulus(Base64WebSafeDecode(k2048BitRsaModulus)); util::StatusOr public_key = RsaSsaPssPublicKey::Create( *parameters, modulus, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); PrivateValues private_values = GetValidPrivateValues(); util::StatusOr private_key = RsaSsaPssPrivateKey::Builder() .SetPublicKey(*public_key) .SetPrimeP(private_values.p) .SetPrimeQ(private_values.q) .SetPrimeExponentP(private_values.dp) .SetPrimeExponentQ(private_values.dq) .SetPrivateExponent(private_values.d) .SetCrtCoefficient(private_values.q_inv) .Build(GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); EXPECT_TRUE(*private_key != *public_key); EXPECT_TRUE(*public_key != *private_key); EXPECT_FALSE(*private_key == *public_key); EXPECT_FALSE(*public_key == *private_key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pss_proto_serialization.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pss_proto_serialization.h" #include #include "absl/base/attributes.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/big_integer.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/key_parser.h" #include "tink/internal/key_serializer.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/parameters_parser.h" #include "tink/internal/parameters_serializer.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/partial_key_access.h" #include "tink/restricted_big_integer.h" #include "tink/restricted_data.h" #include "tink/secret_key_access_token.h" #include "tink/signature/rsa_ssa_pss_parameters.h" #include "tink/signature/rsa_ssa_pss_private_key.h" #include "tink/signature/rsa_ssa_pss_public_key.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/common.pb.h" #include "proto/rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::google::crypto::tink::RsaSsaPssKeyFormat; using ::google::crypto::tink::RsaSsaPssParams; using RsaSsaPssProtoParametersParserImpl = internal::ParametersParserImpl; using RsaSsaPssProtoParametersSerializerImpl = internal::ParametersSerializerImpl; using RsaSsaPssProtoPublicKeyParserImpl = internal::KeyParserImpl; using RsaSsaPssProtoPublicKeySerializerImpl = internal::KeySerializerImpl; using RsaSsaPssProtoPrivateKeyParserImpl = internal::KeyParserImpl; using RsaSsaPssProtoPrivateKeySerializerImpl = internal::KeySerializerImpl; const absl::string_view kPrivateTypeUrl = "type.googleapis.com/google.crypto.tink.RsaSsaPssPrivateKey"; const absl::string_view kPublicTypeUrl = "type.googleapis.com/google.crypto.tink.RsaSsaPssPublicKey"; util::StatusOr ToVariant( OutputPrefixType output_prefix_type) { switch (output_prefix_type) { case OutputPrefixType::LEGACY: return RsaSsaPssParameters::Variant::kLegacy; case OutputPrefixType::CRUNCHY: return RsaSsaPssParameters::Variant::kCrunchy; case OutputPrefixType::RAW: return RsaSsaPssParameters::Variant::kNoPrefix; case OutputPrefixType::TINK: return RsaSsaPssParameters::Variant::kTink; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine RsaSsaPssParameters::Variant"); } } util::StatusOr ToOutputPrefixType( RsaSsaPssParameters::Variant variant) { switch (variant) { case RsaSsaPssParameters::Variant::kLegacy: return OutputPrefixType::LEGACY; case RsaSsaPssParameters::Variant::kCrunchy: return OutputPrefixType::CRUNCHY; case RsaSsaPssParameters::Variant::kNoPrefix: return OutputPrefixType::RAW; case RsaSsaPssParameters::Variant::kTink: return OutputPrefixType::TINK; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine output prefix type."); } } util::StatusOr ToEnumHashType( HashType hash_type) { switch (hash_type) { case HashType::SHA256: return RsaSsaPssParameters::HashType::kSha256; case HashType::SHA384: return RsaSsaPssParameters::HashType::kSha384; case HashType::SHA512: return RsaSsaPssParameters::HashType::kSha512; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine HashType"); } } util::StatusOr ToProtoHashType( RsaSsaPssParameters::HashType hash_type) { switch (hash_type) { case RsaSsaPssParameters::HashType::kSha256: return HashType::SHA256; case RsaSsaPssParameters::HashType::kSha384: return HashType::SHA384; case RsaSsaPssParameters::HashType::kSha512: return HashType::SHA512; default: return util::Status(absl::StatusCode::kInvalidArgument, "Could not determine RsaSsaPssParameters::HashType"); } } util::StatusOr ToParameters( OutputPrefixType output_prefix_type, const RsaSsaPssParams& params, int modulus_size_in_bits, const BigInteger& public_exponent) { util::StatusOr variant = ToVariant(output_prefix_type); if (!variant.ok()) { return variant.status(); } util::StatusOr sig_hash_type = ToEnumHashType(params.sig_hash()); if (!sig_hash_type.ok()) { return sig_hash_type.status(); } util::StatusOr mgf1_hash_type = ToEnumHashType(params.sig_hash()); if (!mgf1_hash_type.ok()) { return mgf1_hash_type.status(); } return RsaSsaPssParameters::Builder() .SetVariant(*variant) .SetSigHashType(*sig_hash_type) .SetMgf1HashType(*mgf1_hash_type) .SetModulusSizeInBits(modulus_size_in_bits) .SetPublicExponent(public_exponent) .SetSaltLengthInBytes(params.salt_length()) .Build(); } util::StatusOr FromParameters(RsaSsaPssParameters parameters) { util::StatusOr sig_hash_type = ToProtoHashType(parameters.GetSigHashType()); if (!sig_hash_type.ok()) { return sig_hash_type.status(); } util::StatusOr mgf1_hash_type = ToProtoHashType(parameters.GetMgf1HashType()); if (!mgf1_hash_type.ok()) { return mgf1_hash_type.status(); } RsaSsaPssParams params; params.set_sig_hash(*sig_hash_type); params.set_mgf1_hash(*mgf1_hash_type); params.set_salt_length(parameters.GetSaltLengthInBytes()); return params; } util::StatusOr ParseParameters( const internal::ProtoParametersSerialization& serialization) { if (serialization.GetKeyTemplate().type_url() != kPrivateTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing RsaSsaPssParameters."); } RsaSsaPssKeyFormat proto_key_format; if (!proto_key_format.ParseFromString( serialization.GetKeyTemplate().value())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse RsaSsaPssKeyFormat proto"); } if (!proto_key_format.has_params()) { return util::Status(absl::StatusCode::kInvalidArgument, "RsaSsaPssKeyFormat proto is missing params field."); } return ToParameters(serialization.GetKeyTemplate().output_prefix_type(), proto_key_format.params(), proto_key_format.modulus_size_in_bits(), BigInteger(proto_key_format.public_exponent())); } util::StatusOr ParsePublicKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (serialization.TypeUrl() != kPublicTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing RsaSsaPssPublicKey."); } google::crypto::tink::RsaSsaPssPublicKey proto_key; const RestrictedData& restricted_data = serialization.SerializedKeyProto(); if (!proto_key.ParseFromString( restricted_data.GetSecret(InsecureSecretKeyAccess::Get()))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse RsaSsaPssPublicKey proto"); } if (proto_key.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } BigInteger modulus(proto_key.n()); int modulus_size_in_bits = modulus.SizeInBytes() * 8; util::StatusOr parameters = ToParameters(serialization.GetOutputPrefixType(), proto_key.params(), modulus_size_in_bits, BigInteger(proto_key.e())); if (!parameters.ok()) { return parameters.status(); } return RsaSsaPssPublicKey::Create(*parameters, modulus, serialization.IdRequirement(), GetPartialKeyAccess()); } util::StatusOr ParsePrivateKey( const internal::ProtoKeySerialization& serialization, absl::optional token) { if (serialization.TypeUrl() != kPrivateTypeUrl) { return util::Status(absl::StatusCode::kInvalidArgument, "Wrong type URL when parsing RsaSsaPssPrivateKey."); } if (!token.has_value()) { return util::Status(absl::StatusCode::kPermissionDenied, "SecretKeyAccess is required"); } google::crypto::tink::RsaSsaPssPrivateKey proto_key; const RestrictedData& restricted_data = serialization.SerializedKeyProto(); if (!proto_key.ParseFromString(restricted_data.GetSecret(*token))) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to parse RsaSsaPssPrivateKey proto"); } if (proto_key.version() != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Only version 0 keys are accepted."); } BigInteger modulus(proto_key.public_key().n()); int modulus_size_in_bits = modulus.SizeInBytes() * 8; util::StatusOr parameters = ToParameters( serialization.GetOutputPrefixType(), proto_key.public_key().params(), modulus_size_in_bits, BigInteger(proto_key.public_key().e())); if (!parameters.ok()) { return parameters.status(); } util::StatusOr public_key = RsaSsaPssPublicKey::Create( *parameters, modulus, serialization.IdRequirement(), GetPartialKeyAccess()); if (!public_key.ok()) { return public_key.status(); } return RsaSsaPssPrivateKey::Builder() .SetPublicKey(*public_key) .SetPrimeP(RestrictedBigInteger(proto_key.p(), *token)) .SetPrimeQ(RestrictedBigInteger(proto_key.q(), *token)) .SetPrimeExponentP(RestrictedBigInteger(proto_key.dp(), *token)) .SetPrimeExponentQ(RestrictedBigInteger(proto_key.dq(), *token)) .SetPrivateExponent(RestrictedBigInteger(proto_key.d(), *token)) .SetCrtCoefficient(RestrictedBigInteger(proto_key.crt(), *token)) .Build(GetPartialKeyAccess()); } util::StatusOr SerializeParameters( const RsaSsaPssParameters& parameters) { util::StatusOr output_prefix_type = ToOutputPrefixType(parameters.GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } util::StatusOr params = FromParameters(parameters); if (!params.ok()) { return params.status(); } RsaSsaPssKeyFormat proto_key_format; proto_key_format.set_modulus_size_in_bits(parameters.GetModulusSizeInBits()); // OSS proto library complains if input is not converted to a string. proto_key_format.set_public_exponent( std::string(parameters.GetPublicExponent().GetValue())); *proto_key_format.mutable_params() = *params; return internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, *output_prefix_type, proto_key_format.SerializeAsString()); } util::StatusOr SerializePublicKey( const RsaSsaPssPublicKey& key, absl::optional token) { util::StatusOr params = FromParameters(key.GetParameters()); if (!params.ok()) { return params.status(); } google::crypto::tink::RsaSsaPssPublicKey proto_key; proto_key.set_version(0); *proto_key.mutable_params() = *params; // OSS proto library complains if input is not converted to a string. proto_key.set_n( std::string(key.GetModulus(GetPartialKeyAccess()).GetValue())); proto_key.set_e( std::string(key.GetParameters().GetPublicExponent().GetValue())); util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetParameters().GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } RestrictedData restricted_output = RestrictedData( proto_key.SerializeAsString(), InsecureSecretKeyAccess::Get()); return internal::ProtoKeySerialization::Create( kPublicTypeUrl, restricted_output, KeyData::ASYMMETRIC_PUBLIC, *output_prefix_type, key.GetIdRequirement()); } util::StatusOr SerializePrivateKey( const RsaSsaPssPrivateKey& key, absl::optional token) { if (!token.has_value()) { return util::Status(absl::StatusCode::kPermissionDenied, "SecretKeyAccess is required"); } util::StatusOr params = FromParameters(key.GetPublicKey().GetParameters()); if (!params.ok()) { return params.status(); } google::crypto::tink::RsaSsaPssPublicKey proto_public_key; proto_public_key.set_version(0); *proto_public_key.mutable_params() = *params; // OSS proto library complains if input is not converted to a string. proto_public_key.set_n(std::string( key.GetPublicKey().GetModulus(GetPartialKeyAccess()).GetValue())); proto_public_key.set_e(std::string( key.GetPublicKey().GetParameters().GetPublicExponent().GetValue())); google::crypto::tink::RsaSsaPssPrivateKey proto_private_key; proto_private_key.set_version(0); *proto_private_key.mutable_public_key() = proto_public_key; // OSS proto library complains if input is not converted to a string. proto_private_key.set_p( std::string(key.GetPrimeP(GetPartialKeyAccess()).GetSecret(*token))); proto_private_key.set_q( std::string(key.GetPrimeQ(GetPartialKeyAccess()).GetSecret(*token))); proto_private_key.set_dp( std::string(key.GetPrimeExponentP().GetSecret(*token))); proto_private_key.set_dq( std::string(key.GetPrimeExponentQ().GetSecret(*token))); proto_private_key.set_d( std::string(key.GetPrivateExponent().GetSecret(*token))); proto_private_key.set_crt( std::string(key.GetCrtCoefficient().GetSecret(*token))); util::StatusOr output_prefix_type = ToOutputPrefixType(key.GetPublicKey().GetParameters().GetVariant()); if (!output_prefix_type.ok()) { return output_prefix_type.status(); } RestrictedData restricted_output = RestrictedData(proto_private_key.SerializeAsString(), *token); return internal::ProtoKeySerialization::Create( kPrivateTypeUrl, restricted_output, KeyData::ASYMMETRIC_PRIVATE, *output_prefix_type, key.GetIdRequirement()); } RsaSsaPssProtoParametersParserImpl* RsaSsaPssProtoParametersParser() { static auto* parser = new RsaSsaPssProtoParametersParserImpl(kPrivateTypeUrl, ParseParameters); return parser; } RsaSsaPssProtoParametersSerializerImpl* RsaSsaPssProtoParametersSerializer() { static auto* serializer = new RsaSsaPssProtoParametersSerializerImpl( kPrivateTypeUrl, SerializeParameters); return serializer; } RsaSsaPssProtoPublicKeyParserImpl* RsaSsaPssProtoPublicKeyParser() { static auto* parser = new RsaSsaPssProtoPublicKeyParserImpl(kPublicTypeUrl, ParsePublicKey); return parser; } RsaSsaPssProtoPublicKeySerializerImpl* RsaSsaPssProtoPublicKeySerializer() { static auto* serializer = new RsaSsaPssProtoPublicKeySerializerImpl(SerializePublicKey); return serializer; } RsaSsaPssProtoPrivateKeyParserImpl* RsaSsaPssProtoPrivateKeyParser() { static auto* parser = new RsaSsaPssProtoPrivateKeyParserImpl(kPrivateTypeUrl, ParsePrivateKey); return parser; } RsaSsaPssProtoPrivateKeySerializerImpl* RsaSsaPssProtoPrivateKeySerializer() { static auto* serializer = new RsaSsaPssProtoPrivateKeySerializerImpl(SerializePrivateKey); return serializer; } } // namespace util::Status RegisterRsaSsaPssProtoSerialization() { util::Status status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersParser(RsaSsaPssProtoParametersParser()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterParametersSerializer(RsaSsaPssProtoParametersSerializer()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(RsaSsaPssProtoPublicKeyParser()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(RsaSsaPssProtoPublicKeySerializer()); if (!status.ok()) { return status; } status = internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeyParser(RsaSsaPssProtoPrivateKeyParser()); if (!status.ok()) { return status; } return internal::MutableSerializationRegistry::GlobalInstance() .RegisterKeySerializer(RsaSsaPssProtoPrivateKeySerializer()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pss_proto_serialization.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_RSA_SSA_PSS_PROTO_SERIALIZATION_H_ #define TINK_SIGNATURE_RSA_SSA_PSS_PROTO_SERIALIZATION_H_ #include "tink/util/status.h" namespace crypto { namespace tink { // Registers proto parsers and serializers for RsaSsaPss parameters and keys. crypto::tink::util::Status RegisterRsaSsaPssProtoSerialization(); } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_RSA_SSA_PSS_PROTO_SERIALIZATION_H_ ================================================ FILE: cc/signature/rsa_ssa_pss_proto_serialization_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pss_proto_serialization.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/log/check.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #endif #include "openssl/bn.h" #include "openssl/rsa.h" #include "tink/big_integer.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/bn_util.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/key.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/restricted_big_integer.h" #include "tink/restricted_data.h" #include "tink/signature/rsa_ssa_pss_parameters.h" #include "tink/signature/rsa_ssa_pss_private_key.h" #include "tink/signature/rsa_ssa_pss_public_key.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/common.pb.h" #include "proto/rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::google::crypto::tink::RsaSsaPssKeyFormat; using ::google::crypto::tink::RsaSsaPssParams; using ::testing::Eq; using ::testing::IsTrue; using ::testing::NotNull; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { RsaSsaPssParameters::Variant variant; OutputPrefixType output_prefix_type; RsaSsaPssParameters::HashType hash_type; HashType proto_hash_type; int modulus_size_in_bits; int salt_length_in_bytes; absl::optional id; std::string output_prefix; }; const std::string& kF4Str = *new std::string("\x1\0\x1", 3); // 65537 const absl::string_view kPrivateTypeUrl = "type.googleapis.com/google.crypto.tink.RsaSsaPssPrivateKey"; const absl::string_view kPublicTypeUrl = "type.googleapis.com/google.crypto.tink.RsaSsaPssPublicKey"; class RsaSsaPssProtoSerializationTest : public TestWithParam { protected: void SetUp() override { internal::MutableSerializationRegistry::GlobalInstance().Reset(); } }; TEST_F(RsaSsaPssProtoSerializationTest, RegisterTwiceSucceeds) { ASSERT_THAT(RegisterRsaSsaPssProtoSerialization(), IsOk()); ASSERT_THAT(RegisterRsaSsaPssProtoSerialization(), IsOk()); } INSTANTIATE_TEST_SUITE_P( RsaSsaPssProtoSerializationTestSuite, RsaSsaPssProtoSerializationTest, Values(TestCase{RsaSsaPssParameters::Variant::kTink, OutputPrefixType::TINK, RsaSsaPssParameters::HashType::kSha256, HashType::SHA256, /*modulus_size=*/2048, /*salt_length_in_bytes=*/0, /*id=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{RsaSsaPssParameters::Variant::kCrunchy, OutputPrefixType::CRUNCHY, RsaSsaPssParameters::HashType::kSha256, HashType::SHA256, /*modulus_size=*/2048, /*salt_length_in_bytes=*/32, /*id=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{RsaSsaPssParameters::Variant::kLegacy, OutputPrefixType::LEGACY, RsaSsaPssParameters::HashType::kSha384, HashType::SHA384, /*modulus_size=*/3072, /*salt_length_in_bytes*/ 48, /*id=*/0x07080910, /*output_prefix=*/std::string("\x00\x07\x08\x09\x10", 5)}, TestCase{RsaSsaPssParameters::Variant::kNoPrefix, OutputPrefixType::RAW, RsaSsaPssParameters::HashType::kSha512, HashType::SHA512, /*modulus_size=*/3072, /*salt_length_in_bytes=*/64, /*id=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(RsaSsaPssProtoSerializationTest, ParseParametersSucceeds) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterRsaSsaPssProtoSerialization(), IsOk()); RsaSsaPssKeyFormat key_format_proto; key_format_proto.set_modulus_size_in_bits(test_case.modulus_size_in_bits); key_format_proto.set_public_exponent(kF4Str); RsaSsaPssParams params; params.set_sig_hash(test_case.proto_hash_type); params.set_mgf1_hash(test_case.proto_hash_type); params.set_salt_length(test_case.salt_length_in_bytes); *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, test_case.output_prefix_type, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(parameters, IsOk()); EXPECT_THAT((*parameters)->HasIdRequirement(), test_case.id.has_value()); const RsaSsaPssParameters* rsa_ssa_pss_parameters = dynamic_cast(parameters->get()); ASSERT_THAT(rsa_ssa_pss_parameters, NotNull()); EXPECT_THAT(rsa_ssa_pss_parameters->GetVariant(), Eq(test_case.variant)); EXPECT_THAT(rsa_ssa_pss_parameters->GetModulusSizeInBits(), Eq(test_case.modulus_size_in_bits)); EXPECT_THAT(rsa_ssa_pss_parameters->GetSigHashType(), Eq(test_case.hash_type)); EXPECT_THAT(rsa_ssa_pss_parameters->GetMgf1HashType(), Eq(test_case.hash_type)); EXPECT_THAT(rsa_ssa_pss_parameters->GetSaltLengthInBytes(), Eq(test_case.salt_length_in_bytes)); EXPECT_THAT(rsa_ssa_pss_parameters->GetPublicExponent(), Eq(BigInteger(kF4Str))); } TEST_F(RsaSsaPssProtoSerializationTest, ParseParametersWithInvalidSerializationFails) { ASSERT_THAT(RegisterRsaSsaPssProtoSerialization(), IsOk()); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::RAW, "invalid_serialization"); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(RsaSsaPssProtoSerializationTest, ParseParametersKeyFormatWithoutParamsFails) { ASSERT_THAT(RegisterRsaSsaPssProtoSerialization(), IsOk()); RsaSsaPssKeyFormat key_format_proto; key_format_proto.set_modulus_size_in_bits(2048); key_format_proto.set_public_exponent(kF4Str); util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::RAW, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(RsaSsaPssProtoSerializationTest, ParseParametersWithUnkownOutputPrefixFails) { ASSERT_THAT(RegisterRsaSsaPssProtoSerialization(), IsOk()); RsaSsaPssKeyFormat key_format_proto; key_format_proto.set_modulus_size_in_bits(2048); key_format_proto.set_public_exponent(kF4Str); RsaSsaPssParams params; params.set_sig_hash(HashType::SHA256); params.set_mgf1_hash(HashType::SHA256); params.set_salt_length(32); *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::UNKNOWN_PREFIX, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(RsaSsaPssProtoSerializationTest, ParseParametersWithUnkownHashFails) { ASSERT_THAT(RegisterRsaSsaPssProtoSerialization(), IsOk()); RsaSsaPssKeyFormat key_format_proto; key_format_proto.set_modulus_size_in_bits(2048); key_format_proto.set_public_exponent(kF4Str); RsaSsaPssParams params; params.set_sig_hash(HashType::UNKNOWN_HASH); params.set_mgf1_hash(HashType::UNKNOWN_HASH); params.set_salt_length(32); *key_format_proto.mutable_params() = params; util::StatusOr serialization = internal::ProtoParametersSerialization::Create( kPrivateTypeUrl, OutputPrefixType::TINK, key_format_proto.SerializeAsString()); ASSERT_THAT(serialization, IsOk()); util::StatusOr> parameters = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *serialization); ASSERT_THAT(parameters.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(RsaSsaPssProtoSerializationTest, SerializeParametersSucceeds) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterRsaSsaPssProtoSerialization(), IsOk()); util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetVariant(test_case.variant) .SetSigHashType(test_case.hash_type) .SetMgf1HashType(test_case.hash_type) .SetModulusSizeInBits(test_case.modulus_size_in_bits) .SetPublicExponent(BigInteger(kF4Str)) .SetSaltLengthInBytes(test_case.salt_length_in_bytes) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters( *parameters); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kPrivateTypeUrl)); const internal::ProtoParametersSerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->GetKeyTemplate().type_url(), Eq(kPrivateTypeUrl)); EXPECT_THAT(proto_serialization->GetKeyTemplate().output_prefix_type(), Eq(test_case.output_prefix_type)); RsaSsaPssKeyFormat key_format; ASSERT_THAT( key_format.ParseFromString(proto_serialization->GetKeyTemplate().value()), IsTrue()); ASSERT_THAT(key_format.has_params(), IsTrue()); EXPECT_THAT(key_format.params().sig_hash(), Eq(test_case.proto_hash_type)); EXPECT_THAT(key_format.params().mgf1_hash(), Eq(test_case.proto_hash_type)); EXPECT_THAT(key_format.params().salt_length(), Eq(test_case.salt_length_in_bytes)); EXPECT_THAT(key_format.modulus_size_in_bits(), Eq(test_case.modulus_size_in_bits)); EXPECT_THAT(key_format.public_exponent(), Eq(kF4Str)); } struct KeyValues { std::string n; std::string e; std::string p; std::string q; std::string dp; std::string dq; std::string d; std::string q_inv; }; KeyValues GenerateKeyValues(int modulus_size_in_bits) { internal::SslUniquePtr rsa(RSA_new()); CHECK_NE(rsa.get(), nullptr); // Set public exponent to 65537. internal::SslUniquePtr e(BN_new()); CHECK_NE(e.get(), nullptr); BN_set_word(e.get(), 65537); // Generate an RSA key pair and get the values. CHECK(RSA_generate_key_ex(rsa.get(), modulus_size_in_bits, e.get(), /*cb=*/nullptr)); const BIGNUM *n_bn, *e_bn, *d_bn, *p_bn, *q_bn, *dp_bn, *dq_bn, *q_inv_bn; RSA_get0_key(rsa.get(), &n_bn, &e_bn, &d_bn); util::StatusOr n_str = internal::BignumToString(n_bn, BN_num_bytes(n_bn)); CHECK_OK(n_str); util::StatusOr e_str = internal::BignumToString(e_bn, BN_num_bytes(e_bn)); CHECK_OK(e_str); util::StatusOr d_str = internal::BignumToString(d_bn, BN_num_bytes(d_bn)); CHECK_OK(d_str); RSA_get0_factors(rsa.get(), &p_bn, &q_bn); util::StatusOr p_str = internal::BignumToString(p_bn, BN_num_bytes(p_bn)); CHECK_OK(p_str); util::StatusOr q_str = internal::BignumToString(q_bn, BN_num_bytes(q_bn)); CHECK_OK(q_str); RSA_get0_crt_params(rsa.get(), &dp_bn, &dq_bn, &q_inv_bn); util::StatusOr dp_str = internal::BignumToString(dp_bn, BN_num_bytes(dp_bn)); CHECK_OK(dp_str); util::StatusOr dq_str = internal::BignumToString(dq_bn, BN_num_bytes(dq_bn)); CHECK_OK(dq_str); util::StatusOr q_inv_str = internal::BignumToString(q_inv_bn, BN_num_bytes(q_inv_bn)); CHECK_OK(q_inv_str); return KeyValues{*n_str, *e_str, *p_str, *q_str, *dp_str, *dq_str, *d_str, *q_inv_str}; } TEST_P(RsaSsaPssProtoSerializationTest, ParsePublicKeySucceeds) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterRsaSsaPssProtoSerialization(), IsOk()); RsaSsaPssParams params; params.set_sig_hash(test_case.proto_hash_type); params.set_mgf1_hash(test_case.proto_hash_type); params.set_salt_length(test_case.salt_length_in_bytes); KeyValues key_values = GenerateKeyValues(test_case.modulus_size_in_bits); google::crypto::tink::RsaSsaPssPublicKey key_proto; key_proto.set_version(0); key_proto.set_n(key_values.n); key_proto.set_e(key_values.e); *key_proto.mutable_params() = params; RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kPublicTypeUrl, serialized_key, KeyData::ASYMMETRIC_PUBLIC, test_case.output_prefix_type, test_case.id); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); ASSERT_THAT(key, IsOk()); EXPECT_THAT((*key)->GetIdRequirement(), Eq(test_case.id)); EXPECT_THAT((*key)->GetParameters().HasIdRequirement(), test_case.id.has_value()); util::StatusOr expected_parameters = RsaSsaPssParameters::Builder() .SetVariant(test_case.variant) .SetSigHashType(test_case.hash_type) .SetMgf1HashType(test_case.hash_type) .SetSaltLengthInBytes(test_case.salt_length_in_bytes) .SetModulusSizeInBits(test_case.modulus_size_in_bits) .SetPublicExponent(BigInteger(key_values.e)) .Build(); ASSERT_THAT(expected_parameters, IsOk()); util::StatusOr expected_key = RsaSsaPssPublicKey::Create(*expected_parameters, BigInteger(key_values.n), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(expected_key, IsOk()); EXPECT_THAT(**key, Eq(*expected_key)); } TEST_F(RsaSsaPssProtoSerializationTest, ParsePublicKeyWithInvalidSerializationFails) { ASSERT_THAT(RegisterRsaSsaPssProtoSerialization(), IsOk()); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPublicTypeUrl, serialized_key, KeyData::ASYMMETRIC_PUBLIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(RsaSsaPssProtoSerializationTest, ParsePublicKeyWithInvalidVersionFails) { ASSERT_THAT(RegisterRsaSsaPssProtoSerialization(), IsOk()); RsaSsaPssParams params; params.set_sig_hash(HashType::SHA256); params.set_mgf1_hash(HashType::SHA256); params.set_salt_length(32); KeyValues key_values = GenerateKeyValues(2048); google::crypto::tink::RsaSsaPssPublicKey key_proto; key_proto.set_version(1); key_proto.set_n(key_values.n); key_proto.set_e(key_values.e); *key_proto.mutable_params() = params; RestrictedData serialized_key = RestrictedData( key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPublicTypeUrl, serialized_key, KeyData::ASYMMETRIC_PUBLIC, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(RsaSsaPssProtoSerializationTest, SerializePublicKeySucceeds) { ASSERT_THAT(RegisterRsaSsaPssProtoSerialization(), IsOk()); TestCase test_case = GetParam(); KeyValues key_values = GenerateKeyValues(test_case.modulus_size_in_bits); util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetVariant(test_case.variant) .SetSigHashType(test_case.hash_type) .SetMgf1HashType(test_case.hash_type) .SetSaltLengthInBytes(test_case.salt_length_in_bytes) .SetModulusSizeInBits(test_case.modulus_size_in_bits) .SetPublicExponent(BigInteger(key_values.e)) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr key = RsaSsaPssPublicKey::Create(*parameters, BigInteger(key_values.n), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, /*token=*/absl::nullopt); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kPublicTypeUrl)); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq(kPublicTypeUrl)); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::ASYMMETRIC_PUBLIC)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id)); google::crypto::tink::RsaSsaPssPublicKey proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.version(), Eq(0)); EXPECT_THAT(proto_key.n(), Eq(key_values.n)); EXPECT_THAT(proto_key.e(), Eq(key_values.e)); EXPECT_THAT(proto_key.has_params(), IsTrue()); EXPECT_THAT(proto_key.params().sig_hash(), Eq(test_case.proto_hash_type)); EXPECT_THAT(proto_key.params().mgf1_hash(), Eq(test_case.proto_hash_type)); EXPECT_THAT(proto_key.params().salt_length(), Eq(test_case.salt_length_in_bytes)); } TEST_P(RsaSsaPssProtoSerializationTest, ParsePrivateKeySucceeds) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterRsaSsaPssProtoSerialization(), IsOk()); RsaSsaPssParams params; params.set_sig_hash(test_case.proto_hash_type); params.set_mgf1_hash(test_case.proto_hash_type); params.set_salt_length(test_case.salt_length_in_bytes); KeyValues key_values = GenerateKeyValues(test_case.modulus_size_in_bits); google::crypto::tink::RsaSsaPssPublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_n(key_values.n); public_key_proto.set_e(key_values.e); *public_key_proto.mutable_params() = params; google::crypto::tink::RsaSsaPssPrivateKey private_key_proto; private_key_proto.set_version(0); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_p(key_values.p); private_key_proto.set_q(key_values.q); private_key_proto.set_dp(key_values.dp); private_key_proto.set_dq(key_values.dq); private_key_proto.set_d(key_values.d); private_key_proto.set_crt(key_values.q_inv); RestrictedData serialized_key = RestrictedData( private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create( kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, test_case.output_prefix_type, test_case.id); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(key, IsOk()); EXPECT_THAT((*key)->GetIdRequirement(), Eq(test_case.id)); EXPECT_THAT((*key)->GetParameters().HasIdRequirement(), test_case.id.has_value()); util::StatusOr expected_parameters = RsaSsaPssParameters::Builder() .SetVariant(test_case.variant) .SetSigHashType(test_case.hash_type) .SetMgf1HashType(test_case.hash_type) .SetSaltLengthInBytes(test_case.salt_length_in_bytes) .SetModulusSizeInBits(test_case.modulus_size_in_bits) .SetPublicExponent(BigInteger(key_values.e)) .Build(); ASSERT_THAT(expected_parameters, IsOk()); util::StatusOr expected_public_key = RsaSsaPssPublicKey::Create(*expected_parameters, BigInteger(key_values.n), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(expected_public_key, IsOk()); util::StatusOr expected_private_key = RsaSsaPssPrivateKey::Builder() .SetPublicKey(*expected_public_key) .SetPrimeP(RestrictedBigInteger(key_values.p, InsecureSecretKeyAccess::Get())) .SetPrimeQ(RestrictedBigInteger(key_values.q, InsecureSecretKeyAccess::Get())) .SetPrimeExponentP(RestrictedBigInteger( key_values.dp, InsecureSecretKeyAccess::Get())) .SetPrimeExponentQ(RestrictedBigInteger( key_values.dq, InsecureSecretKeyAccess::Get())) .SetPrivateExponent(RestrictedBigInteger( key_values.d, InsecureSecretKeyAccess::Get())) .SetCrtCoefficient(RestrictedBigInteger( key_values.q_inv, InsecureSecretKeyAccess::Get())) .Build(GetPartialKeyAccess()); EXPECT_THAT(**key, Eq(*expected_private_key)); } TEST_F(RsaSsaPssProtoSerializationTest, ParsePrivateKeyWithInvalidSerializationFails) { ASSERT_THAT(RegisterRsaSsaPssProtoSerialization(), IsOk()); RestrictedData serialized_key = RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(RsaSsaPssProtoSerializationTest, ParsePrivateKeyWithInvalidVersionFails) { ASSERT_THAT(RegisterRsaSsaPssProtoSerialization(), IsOk()); RsaSsaPssParams params; params.set_sig_hash(HashType::SHA256); params.set_mgf1_hash(HashType::SHA256); params.set_salt_length(32); KeyValues key_values = GenerateKeyValues(2048); google::crypto::tink::RsaSsaPssPublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_n(key_values.n); public_key_proto.set_e(key_values.e); *public_key_proto.mutable_params() = params; google::crypto::tink::RsaSsaPssPrivateKey private_key_proto; private_key_proto.set_version(1); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_p(key_values.p); private_key_proto.set_q(key_values.q); private_key_proto.set_dp(key_values.dp); private_key_proto.set_dq(key_values.dq); private_key_proto.set_d(key_values.d); private_key_proto.set_crt(key_values.q_inv); RestrictedData serialized_key = RestrictedData( private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, InsecureSecretKeyAccess::Get()); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(RsaSsaPssProtoSerializationTest, ParsePrivateKeyNoSecretKeyAccessFails) { ASSERT_THAT(RegisterRsaSsaPssProtoSerialization(), IsOk()); RsaSsaPssParams params; params.set_sig_hash(HashType::SHA256); params.set_mgf1_hash(HashType::SHA256); params.set_salt_length(32); KeyValues key_values = GenerateKeyValues(2048); google::crypto::tink::RsaSsaPssPublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_n(key_values.n); public_key_proto.set_e(key_values.e); *public_key_proto.mutable_params() = params; google::crypto::tink::RsaSsaPssPrivateKey private_key_proto; private_key_proto.set_version(0); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_p(key_values.p); private_key_proto.set_q(key_values.q); private_key_proto.set_dp(key_values.dp); private_key_proto.set_dq(key_values.dq); private_key_proto.set_d(key_values.d); private_key_proto.set_crt(key_values.q_inv); RestrictedData serialized_key = RestrictedData( private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()); util::StatusOr serialization = internal::ProtoKeySerialization::Create(kPrivateTypeUrl, serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/0x23456789); ASSERT_THAT(serialization, IsOk()); util::StatusOr> key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *serialization, /*token=*/absl::nullopt); EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kPermissionDenied)); } TEST_P(RsaSsaPssProtoSerializationTest, SerializePrivateKeySucceeds) { TestCase test_case = GetParam(); ASSERT_THAT(RegisterRsaSsaPssProtoSerialization(), IsOk()); KeyValues key_values = GenerateKeyValues(test_case.modulus_size_in_bits); util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetVariant(test_case.variant) .SetSigHashType(test_case.hash_type) .SetMgf1HashType(test_case.hash_type) .SetSaltLengthInBytes(test_case.salt_length_in_bytes) .SetModulusSizeInBits(test_case.modulus_size_in_bits) .SetPublicExponent(BigInteger(key_values.e)) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr public_key = RsaSsaPssPublicKey::Create(*parameters, BigInteger(key_values.n), test_case.id, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = RsaSsaPssPrivateKey::Builder() .SetPublicKey(*public_key) .SetPrimeP(RestrictedBigInteger(key_values.p, InsecureSecretKeyAccess::Get())) .SetPrimeQ(RestrictedBigInteger(key_values.q, InsecureSecretKeyAccess::Get())) .SetPrimeExponentP(RestrictedBigInteger( key_values.dp, InsecureSecretKeyAccess::Get())) .SetPrimeExponentQ(RestrictedBigInteger( key_values.dq, InsecureSecretKeyAccess::Get())) .SetPrivateExponent(RestrictedBigInteger( key_values.d, InsecureSecretKeyAccess::Get())) .SetCrtCoefficient(RestrictedBigInteger( key_values.q_inv, InsecureSecretKeyAccess::Get())) .Build(GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *private_key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialization, IsOk()); EXPECT_THAT((*serialization)->ObjectIdentifier(), Eq(kPrivateTypeUrl)); const internal::ProtoKeySerialization* proto_serialization = dynamic_cast( serialization->get()); ASSERT_THAT(proto_serialization, NotNull()); EXPECT_THAT(proto_serialization->TypeUrl(), Eq(kPrivateTypeUrl)); EXPECT_THAT(proto_serialization->KeyMaterialType(), Eq(KeyData::ASYMMETRIC_PRIVATE)); EXPECT_THAT(proto_serialization->GetOutputPrefixType(), Eq(test_case.output_prefix_type)); EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id)); google::crypto::tink::RsaSsaPssPrivateKey proto_key; ASSERT_THAT(proto_key.ParseFromString( proto_serialization->SerializedKeyProto().GetSecret( InsecureSecretKeyAccess::Get())), IsTrue()); EXPECT_THAT(proto_key.version(), Eq(0)); EXPECT_THAT(proto_key.p(), Eq(key_values.p)); EXPECT_THAT(proto_key.q(), Eq(key_values.q)); EXPECT_THAT(proto_key.dp(), Eq(key_values.dp)); EXPECT_THAT(proto_key.dq(), Eq(key_values.dq)); EXPECT_THAT(proto_key.d(), Eq(key_values.d)); EXPECT_THAT(proto_key.crt(), Eq(key_values.q_inv)); EXPECT_THAT(proto_key.has_public_key(), IsTrue()); EXPECT_THAT(proto_key.public_key().version(), Eq(0)); EXPECT_THAT(proto_key.public_key().n(), Eq(key_values.n)); EXPECT_THAT(proto_key.public_key().e(), Eq(key_values.e)); EXPECT_THAT(proto_key.public_key().has_params(), IsTrue()); EXPECT_THAT(proto_key.public_key().params().sig_hash(), Eq(test_case.proto_hash_type)); EXPECT_THAT(proto_key.public_key().params().mgf1_hash(), Eq(test_case.proto_hash_type)); EXPECT_THAT(proto_key.public_key().params().salt_length(), Eq(test_case.salt_length_in_bytes)); } TEST_F(RsaSsaPssProtoSerializationTest, SerializePrivateKeyNoSecretKeyAccessFails) { ASSERT_THAT(RegisterRsaSsaPssProtoSerialization(), IsOk()); KeyValues key_values = GenerateKeyValues(2048); util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetVariant(RsaSsaPssParameters::Variant::kTink) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetModulusSizeInBits(2048) .SetPublicExponent(BigInteger(kF4Str)) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr public_key = RsaSsaPssPublicKey::Create( *parameters, BigInteger(key_values.n), /*id_requirement=*/0x23456789, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = RsaSsaPssPrivateKey::Builder() .SetPublicKey(*public_key) .SetPrimeP(RestrictedBigInteger(key_values.p, InsecureSecretKeyAccess::Get())) .SetPrimeQ(RestrictedBigInteger(key_values.q, InsecureSecretKeyAccess::Get())) .SetPrimeExponentP(RestrictedBigInteger( key_values.dp, InsecureSecretKeyAccess::Get())) .SetPrimeExponentQ(RestrictedBigInteger( key_values.dq, InsecureSecretKeyAccess::Get())) .SetPrivateExponent(RestrictedBigInteger( key_values.d, InsecureSecretKeyAccess::Get())) .SetCrtCoefficient(RestrictedBigInteger( key_values.q_inv, InsecureSecretKeyAccess::Get())) .Build(GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); util::StatusOr> serialization = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *private_key, /*token=*/absl::nullopt); ASSERT_THAT(serialization.status(), StatusIs(absl::StatusCode::kPermissionDenied)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pss_public_key.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pss_public_key.h" #include #include "absl/base/attributes.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/big_integer.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/signature/rsa_ssa_pss_parameters.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { util::StatusOr ComputeOutputPrefix( const RsaSsaPssParameters& parameters, absl::optional id_requirement) { switch (parameters.GetVariant()) { case RsaSsaPssParameters::Variant::kNoPrefix: return std::string(""); // Empty prefix. case RsaSsaPssParameters::Variant::kLegacy: ABSL_FALLTHROUGH_INTENDED; case RsaSsaPssParameters::Variant::kCrunchy: if (!id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "ID requirement must have value with kCrunchy or kLegacy"); } return absl::StrCat(absl::HexStringToBytes("00"), subtle::BigEndian32(*id_requirement)); case RsaSsaPssParameters::Variant::kTink: if (!id_requirement.has_value()) { return util::Status(absl::StatusCode::kInvalidArgument, "ID requirement must have value with kTink"); } return absl::StrCat(absl::HexStringToBytes("01"), subtle::BigEndian32(*id_requirement)); default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid variant: ", parameters.GetVariant())); } } } // namespace util::StatusOr RsaSsaPssPublicKey::Create( const RsaSsaPssParameters& parameters, const BigInteger& modulus, absl::optional id_requirement, PartialKeyAccessToken token) { if (parameters.HasIdRequirement() && !id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key without ID requirement with parameters with ID " "requirement"); } if (!parameters.HasIdRequirement() && id_requirement.has_value()) { return util::Status( absl::StatusCode::kInvalidArgument, "Cannot create key with ID requirement with parameters without ID " "requirement"); } // Check if the modulus length matches the modulus_size_in_bits parameter. if (modulus.SizeInBytes() * 8 != parameters.GetModulusSizeInBits()) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrFormat("Invalid modulus length (expected %d, got %d)", parameters.GetModulusSizeInBits(), modulus.SizeInBytes() * 8)); } util::StatusOr output_prefix = ComputeOutputPrefix(parameters, id_requirement); if (!output_prefix.ok()) { return output_prefix.status(); } return RsaSsaPssPublicKey(parameters, modulus, id_requirement, *output_prefix); } bool RsaSsaPssPublicKey::operator==(const Key& other) const { const RsaSsaPssPublicKey* that = dynamic_cast(&other); if (that == nullptr) { return false; } if (GetParameters() != that->GetParameters()) { return false; } if (id_requirement_ != that->id_requirement_) { return false; } return modulus_ == that->modulus_; } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pss_public_key.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_RSA_SSA_PSS_PUBLIC_KEY_H_ #define TINK_SIGNATURE_RSA_SSA_PSS_PUBLIC_KEY_H_ #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/big_integer.h" #include "tink/key.h" #include "tink/partial_key_access_token.h" #include "tink/signature/rsa_ssa_pss_parameters.h" #include "tink/signature/signature_public_key.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Representation of the public key for the RsaSsaPss digital // signature scheme. class RsaSsaPssPublicKey : public SignaturePublicKey { public: // Copyable and movable. RsaSsaPssPublicKey(const RsaSsaPssPublicKey& other) = default; RsaSsaPssPublicKey& operator=(const RsaSsaPssPublicKey& other) = default; RsaSsaPssPublicKey(RsaSsaPssPublicKey&& other) = default; RsaSsaPssPublicKey& operator=(RsaSsaPssPublicKey&& other) = default; // Creates a new RsaSsaPss public key from `modulus`. If // `parameters` specify a variant that uses a prefix, then `id_requirement` is // used to compute this prefix. static util::StatusOr Create( const RsaSsaPssParameters& parameters, const BigInteger& modulus, absl::optional id_requirement, PartialKeyAccessToken token); const BigInteger& GetModulus(PartialKeyAccessToken token) const { return modulus_; } absl::string_view GetOutputPrefix() const override { return output_prefix_; } const RsaSsaPssParameters& GetParameters() const override { return parameters_; } absl::optional GetIdRequirement() const override { return id_requirement_; } bool operator==(const Key& other) const override; private: explicit RsaSsaPssPublicKey(const RsaSsaPssParameters& parameters, const BigInteger& modulus, absl::optional id_requirement, absl::string_view output_prefix) : parameters_(parameters), modulus_(modulus), id_requirement_(id_requirement), output_prefix_(output_prefix) {} RsaSsaPssParameters parameters_; BigInteger modulus_; absl::optional id_requirement_; std::string output_prefix_; }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_RSA_SSA_PSS_PUBLIC_KEY_H_ ================================================ FILE: cc/signature/rsa_ssa_pss_public_key_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pss_public_key.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/big_integer.h" #include "tink/partial_key_access.h" #include "tink/signature/rsa_ssa_pss_parameters.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::TestWithParam; using ::testing::Values; struct TestCase { int modulus_size_in_bits; RsaSsaPssParameters::HashType hash_type; int salt_length_in_bytes; RsaSsaPssParameters::Variant variant; absl::optional id_requirement; std::string output_prefix; }; const BigInteger& kF4 = *new BigInteger(std::string("\x1\0\x1", 3)); // 65537 // Test vector from // https://github.com/google/wycheproof/blob/master/testvectors/rsa_pss_2048_sha256_mgf1_32_test.json constexpr absl::string_view kHex2048BitRsaModulus = "00a2b451a07d0aa5f96e455671513550514a8a5b462ebef717094fa1fee82224e637f9746d" "3f7cafd31878d80325b6ef5a1700f65903b469429e89d6eac8845097b5ab393189db92512e" "d8a7711a1253facd20f79c15e8247f3d3e42e46e48c98e254a2fe9765313a03eff8f17e1a0" "29397a1fa26a8dce26f490ed81299615d9814c22da610428e09c7d9658594266f5c021d0fc" "eca08d945a12be82de4d1ece6b4c03145b5d3495d4ed5411eb878daf05fd7afc3e09ada0f1" "126422f590975a1969816f48698bcbba1b4d9cae79d460d8f9f85e7975005d9bc22c4e5ac0" "f7c1a45d12569a62807d3b9a02e5a530e773066f453d1f5b4c2e9cf7820283f742b9d5"; using RsaSsaPssPublicKeyTest = TestWithParam; INSTANTIATE_TEST_SUITE_P( RsaSsaPssPublicKeyTestSuite, RsaSsaPssPublicKeyTest, Values( TestCase{/*modulus_size=*/2048, RsaSsaPssParameters::HashType::kSha256, /*salt_length_in_bytes*/ 0, RsaSsaPssParameters::Variant::kTink, /*id_requirement=*/0x02030400, /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)}, TestCase{/*modulus_size=*/2048, RsaSsaPssParameters::HashType::kSha256, /*salt_length_in_bytes*/ 32, RsaSsaPssParameters::Variant::kCrunchy, /*id_requirement=*/0x01030005, /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)}, TestCase{/*modulus_size=*/2048, RsaSsaPssParameters::HashType::kSha384, /*salt_length_in_bytes*/ 48, RsaSsaPssParameters::Variant::kLegacy, /*id_requirement=*/0x07080910, /*output_prefix=*/std::string("\x00\x07\x08\x09\x10", 5)}, TestCase{/*modulus_size=*/2048, RsaSsaPssParameters::HashType::kSha512, /*salt_length_in_bytes*/ 64, RsaSsaPssParameters::Variant::kNoPrefix, /*id_requirement=*/absl::nullopt, /*output_prefix=*/""})); TEST_P(RsaSsaPssPublicKeyTest, CreatePublicKeySucceeds) { TestCase test_case = GetParam(); util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(test_case.modulus_size_in_bits) .SetPublicExponent(kF4) .SetSigHashType(test_case.hash_type) .SetMgf1HashType(test_case.hash_type) .SetSaltLengthInBytes(test_case.salt_length_in_bytes) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); BigInteger modulus(absl::HexStringToBytes(kHex2048BitRsaModulus)); util::StatusOr public_key = RsaSsaPssPublicKey::Create( *parameters, modulus, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); EXPECT_THAT(public_key->GetParameters(), Eq(*parameters)); EXPECT_THAT(public_key->GetIdRequirement(), Eq(test_case.id_requirement)); EXPECT_THAT(public_key->GetOutputPrefix(), Eq(test_case.output_prefix)); EXPECT_THAT(public_key->GetModulus(GetPartialKeyAccess()), Eq(modulus)); } TEST(RsaSsaPssPublicKeyTest, CreateWithNonMatchingModulusSizeFails) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(3072) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); BigInteger modulus(absl::HexStringToBytes(kHex2048BitRsaModulus)); util::StatusOr public_key = RsaSsaPssPublicKey::Create( *parameters, modulus, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); EXPECT_THAT(public_key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(Ed25519PublicKeyTest, CreateKeyWithInvalidIdRequirementFails) { util::StatusOr no_prefix_parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(no_prefix_parameters, IsOk()); util::StatusOr tink_parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kTink) .Build(); ASSERT_THAT(tink_parameters, IsOk()); BigInteger modulus(absl::HexStringToBytes(kHex2048BitRsaModulus)); EXPECT_THAT( RsaSsaPssPublicKey::Create(*no_prefix_parameters, modulus, /*id_requirement=*/123, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); EXPECT_THAT(RsaSsaPssPublicKey::Create(*tink_parameters, modulus, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()) .status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(RsaSsaPssPublicKeyTest, KeyEquals) { TestCase test_case = GetParam(); util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(test_case.modulus_size_in_bits) .SetPublicExponent(kF4) .SetSigHashType(test_case.hash_type) .SetMgf1HashType(test_case.hash_type) .SetSaltLengthInBytes(test_case.salt_length_in_bytes) .SetVariant(test_case.variant) .Build(); ASSERT_THAT(parameters, IsOk()); BigInteger modulus(absl::HexStringToBytes(kHex2048BitRsaModulus)); util::StatusOr public_key = RsaSsaPssPublicKey::Create( *parameters, modulus, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = RsaSsaPssPublicKey::Create(*parameters, modulus, test_case.id_requirement, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key == *other_public_key); EXPECT_TRUE(*other_public_key == *public_key); EXPECT_FALSE(*public_key != *other_public_key); EXPECT_FALSE(*other_public_key != *public_key); } TEST(RsaSsaPssPublicKeyTest, DifferentParametersNotEqual) { util::StatusOr tink_parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kTink) .Build(); ASSERT_THAT(tink_parameters, IsOk()); util::StatusOr crunchy_parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kCrunchy) .Build(); ASSERT_THAT(crunchy_parameters, IsOk()); BigInteger modulus(absl::HexStringToBytes(kHex2048BitRsaModulus)); util::StatusOr public_key = RsaSsaPssPublicKey::Create( *tink_parameters, modulus, /*id_requirement=*/0x02030400, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = RsaSsaPssPublicKey::Create(*crunchy_parameters, modulus, /*id_requirement=*/0x02030400, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key != *other_public_key); EXPECT_TRUE(*other_public_key != *public_key); EXPECT_FALSE(*public_key == *other_public_key); EXPECT_FALSE(*other_public_key == *public_key); } TEST(RsaSsaPssPublicKeyTest, DifferentModulusNotEqual) { util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kNoPrefix) .Build(); ASSERT_THAT(parameters, IsOk()); std::string other_modulus_bytes = absl::HexStringToBytes( "00c684aef47bc201764a663acdf22e67140410b3d201533b6ccaebf86eda3d81a1230a1c" "c5ce2c9e4e102d107f2418d9386f1d3734eb922629b4e7ef464f79fcac53744702a147c1" "ef8dafc8eb366284d3419d98e8cf176ccb7f65bada528c222956900e1ec0c2f21e83e3ee" "30d946a6aa267e01a28b9c1833b035a881ad1865dfd2a451086a46f38ed137237c5fe368" "261e3a46712399f3c56ac6fbde33682ba98c95e435e1dec2d5b9d681ade372622c2dbdbe" "47b419b4ba23a5defc3f792d4d8373cc27cf707dd2f3603363a0ffe643dcfda79758ad1a" "c53d46f1a5ec25df1ddd94780a8f51f88ffb32337f05395dec93267802db95243f1b62cc" "3dd8118d2d"); BigInteger modulus(absl::HexStringToBytes(kHex2048BitRsaModulus)); BigInteger other_modulus(other_modulus_bytes); util::StatusOr public_key = RsaSsaPssPublicKey::Create( *parameters, modulus, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = RsaSsaPssPublicKey::Create(*parameters, other_modulus, /*id_requirement=*/absl::nullopt, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key != *other_public_key); EXPECT_TRUE(*other_public_key != *public_key); EXPECT_FALSE(*public_key == *other_public_key); EXPECT_FALSE(*other_public_key == *public_key); } TEST(RsaSsaPssPublicKeyTest, DifferentIdRequirementNotEqual) { util::StatusOr tink_parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kTink) .Build(); ASSERT_THAT(tink_parameters, IsOk()); BigInteger modulus(absl::HexStringToBytes(kHex2048BitRsaModulus)); util::StatusOr public_key = RsaSsaPssPublicKey::Create( *tink_parameters, modulus, /*id_requirement=*/0x02030400, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = RsaSsaPssPublicKey::Create(*tink_parameters, modulus, /*id_requirement=*/0x01020304, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key != *other_public_key); EXPECT_TRUE(*other_public_key != *public_key); EXPECT_FALSE(*public_key == *other_public_key); EXPECT_FALSE(*other_public_key == *public_key); } TEST(RsaSsaPssPublicKeyTest, PaddedWithZerosModulusEqual) { util::StatusOr tink_parameters = RsaSsaPssParameters::Builder() .SetModulusSizeInBits(2048) .SetPublicExponent(kF4) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetVariant(RsaSsaPssParameters::Variant::kTink) .Build(); ASSERT_THAT(tink_parameters, IsOk()); BigInteger modulus(absl::HexStringToBytes(kHex2048BitRsaModulus)); BigInteger padded_with_zeros_modulus( absl::HexStringToBytes("000000" + std::string(kHex2048BitRsaModulus))); ASSERT_THAT(modulus, Eq(padded_with_zeros_modulus)); util::StatusOr public_key = RsaSsaPssPublicKey::Create( *tink_parameters, modulus, /*id_requirement=*/0x02030400, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr other_public_key = RsaSsaPssPublicKey::Create(*tink_parameters, padded_with_zeros_modulus, /*id_requirement=*/0x02030400, GetPartialKeyAccess()); ASSERT_THAT(other_public_key, IsOk()); EXPECT_TRUE(*public_key == *other_public_key); EXPECT_TRUE(*other_public_key == *public_key); EXPECT_FALSE(*public_key != *other_public_key); EXPECT_FALSE(*other_public_key != *public_key); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pss_sign_key_manager.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pss_sign_key_manager.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/internal/bn_util.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/signature/rsa_ssa_pss_verify_key_manager.h" #include "tink/signature/sig_util.h" #include "tink/subtle/rsa_ssa_pss_sign_boringssl.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using crypto::tink::util::Enums; using crypto::tink::util::Status; using crypto::tink::util::StatusOr; using google::crypto::tink::RsaSsaPssKeyFormat; using google::crypto::tink::RsaSsaPssParams; using google::crypto::tink::RsaSsaPssPrivateKey; namespace { std::unique_ptr RsaPrivateKeySubtleToProto( const internal::RsaPrivateKey& private_key) { auto key_proto = absl::make_unique(); key_proto->set_version(RsaSsaPssSignKeyManager().get_version()); key_proto->set_d(std::string(util::SecretDataAsStringView(private_key.d))); key_proto->set_p(std::string(util::SecretDataAsStringView(private_key.p))); key_proto->set_q(std::string(util::SecretDataAsStringView(private_key.q))); key_proto->set_dp(std::string(util::SecretDataAsStringView(private_key.dp))); key_proto->set_dq(std::string(util::SecretDataAsStringView(private_key.dq))); key_proto->set_crt( std::string(util::SecretDataAsStringView(private_key.crt))); auto* public_key_proto = key_proto->mutable_public_key(); public_key_proto->set_version(RsaSsaPssSignKeyManager().get_version()); public_key_proto->set_n(private_key.n); public_key_proto->set_e(private_key.e); return key_proto; } internal::RsaPrivateKey RsaPrivateKeyProtoToSubtle( const RsaSsaPssPrivateKey& key_proto) { internal::RsaPrivateKey key; key.n = key_proto.public_key().n(); key.e = key_proto.public_key().e(); key.d = util::SecretDataFromStringView(key_proto.d()); key.p = util::SecretDataFromStringView(key_proto.p()); key.q = util::SecretDataFromStringView(key_proto.q()); key.dp = util::SecretDataFromStringView(key_proto.dp()); key.dq = util::SecretDataFromStringView(key_proto.dq()); key.crt = util::SecretDataFromStringView(key_proto.crt()); return key; } } // namespace StatusOr RsaSsaPssSignKeyManager::CreateKey( const RsaSsaPssKeyFormat& key_format) const { util::StatusOr> e = internal::StringToBignum(key_format.public_exponent()); if (!e.ok()) { return e.status(); } internal::RsaPrivateKey private_key; internal::RsaPublicKey public_key; util::Status status = internal::NewRsaKeyPair( key_format.modulus_size_in_bits(), e->get(), &private_key, &public_key); if (!status.ok()) { return status; } RsaSsaPssPrivateKey key_proto = std::move(*RsaPrivateKeySubtleToProto(private_key)); *key_proto.mutable_public_key()->mutable_params() = key_format.params(); return key_proto; } StatusOr> RsaSsaPssSignKeyManager::PublicKeySignFactory::Create( const RsaSsaPssPrivateKey& private_key) const { auto key = RsaPrivateKeyProtoToSubtle(private_key); internal::RsaSsaPssParams params; const RsaSsaPssParams& params_proto = private_key.public_key().params(); params.sig_hash = Enums::ProtoToSubtle(params_proto.sig_hash()); params.mgf1_hash = Enums::ProtoToSubtle(params_proto.mgf1_hash()); params.salt_length = params_proto.salt_length(); auto signer = subtle::RsaSsaPssSignBoringSsl::New(key, params); if (!signer.ok()) return signer.status(); // To check that the key is correct, we sign a test message with private key // and verify with public key. auto verifier = RsaSsaPssVerifyKeyManager().GetPrimitive( private_key.public_key()); if (!verifier.ok()) return verifier.status(); auto sign_verify_result = SignAndVerify(signer.value().get(), verifier.value().get()); if (!sign_verify_result.ok()) { return util::Status(absl::StatusCode::kInternal, "security bug: signing with private key followed by " "verifying with public key failed"); } return signer; } Status RsaSsaPssSignKeyManager::ValidateKey( const RsaSsaPssPrivateKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; return RsaSsaPssVerifyKeyManager().ValidateKey(key.public_key()); } Status RsaSsaPssSignKeyManager::ValidateKeyFormat( const RsaSsaPssKeyFormat& key_format) const { Status modulus_status = internal::ValidateRsaModulusSize(key_format.modulus_size_in_bits()); if (!modulus_status.ok()) { return modulus_status; } Status exponent_status = internal::ValidateRsaPublicExponent(key_format.public_exponent()); if (!exponent_status.ok()) { return exponent_status; } return RsaSsaPssVerifyKeyManager().ValidateParams(key_format.params()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pss_sign_key_manager.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_RSA_SSA_PSS_SIGN_KEY_MANAGER_H_ #define TINK_SIGNATURE_RSA_SSA_PSS_SIGN_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/key_type_manager.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_sign.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class RsaSsaPssSignKeyManager : public PrivateKeyTypeManager> { public: class PublicKeySignFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::RsaSsaPssPrivateKey& private_key) const override; }; RsaSsaPssSignKeyManager() : PrivateKeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::RsaSsaPssPrivateKey& key) const override; crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::RsaSsaPssKeyFormat& key_format) const override; crypto::tink::util::StatusOr CreateKey(const google::crypto::tink::RsaSsaPssKeyFormat& key_format) const override; crypto::tink::util::StatusOr GetPublicKey(const google::crypto::tink::RsaSsaPssPrivateKey& private_key) const override { return private_key.public_key(); } internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: const std::string key_type_ = absl::StrCat(kTypeGoogleapisCom, google::crypto::tink::RsaSsaPssPrivateKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_RSA_SSA_PSS_SIGN_KEY_MANAGER_H_ ================================================ FILE: cc/signature/rsa_ssa_pss_sign_key_manager_test.cc ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pss_sign_key_manager.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_set.h" #include "openssl/rsa.h" #include "tink/internal/bn_util.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/public_key_sign.h" #include "tink/signature/rsa_ssa_pss_verify_key_manager.h" #include "tink/signature/signature_key_templates.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/rsa_ssa_pss_verify_boringssl.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::RsaSsaPssKeyFormat; using ::google::crypto::tink::RsaSsaPssPrivateKey; using ::google::crypto::tink::RsaSsaPssPublicKey; using ::testing::Eq; using ::testing::Gt; using ::testing::Not; using ::testing::SizeIs; TEST(RsaSsaPssSignKeyManagerTest, Basic) { EXPECT_THAT(RsaSsaPssSignKeyManager().get_version(), Eq(0)); EXPECT_THAT(RsaSsaPssSignKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PRIVATE)); EXPECT_THAT(RsaSsaPssSignKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.RsaSsaPssPrivateKey")); } RsaSsaPssKeyFormat CreateKeyFormat(HashType sig_hash, HashType mgf1_hash, int salt_length, int modulus_size_in_bits, int public_exponent) { RsaSsaPssKeyFormat key_format; auto params = key_format.mutable_params(); params->set_sig_hash(sig_hash); params->set_mgf1_hash(mgf1_hash); params->set_salt_length(salt_length); key_format.set_modulus_size_in_bits(modulus_size_in_bits); internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), public_exponent); key_format.set_public_exponent( internal::BignumToString(e.get(), BN_num_bytes(e.get())).value()); return key_format; } RsaSsaPssKeyFormat ValidKeyFormat() { return CreateKeyFormat(HashType::SHA256, HashType::SHA256, 32, 3072, RSA_F4); } TEST(RsaSsaPssSignKeyManagerTest, ValidateKeyFormat) { EXPECT_THAT(RsaSsaPssSignKeyManager().ValidateKeyFormat(ValidKeyFormat()), IsOk()); } TEST(RsaSsaPssSignKeyManagerTest, ValidateKeyFormatSha512Allowed) { RsaSsaPssKeyFormat key_format = ValidKeyFormat(); key_format.mutable_params()->set_sig_hash(HashType::SHA512); key_format.mutable_params()->set_mgf1_hash(HashType::SHA512); EXPECT_THAT(RsaSsaPssSignKeyManager().ValidateKeyFormat(ValidKeyFormat()), IsOk()); } TEST(RsaSsaPssSignKeyManagerTest, ValidateKeyFormatSha1Disallowed) { RsaSsaPssKeyFormat key_format = ValidKeyFormat(); key_format.mutable_params()->set_sig_hash(HashType::SHA1); EXPECT_THAT(RsaSsaPssSignKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(RsaSsaPssSignKeyManagerTest, ValidateKeyFormatSmallModulusDisallowed) { RsaSsaPssKeyFormat key_format = ValidKeyFormat(); key_format.set_modulus_size_in_bits(512); EXPECT_THAT(RsaSsaPssSignKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(RsaSsaPssSignKeyManagerTest, ValidateKeyFormatHashMismatchDisallowed) { RsaSsaPssKeyFormat key_format = ValidKeyFormat(); key_format.mutable_params()->set_sig_hash(HashType::SHA512); key_format.mutable_params()->set_mgf1_hash(HashType::SHA256); EXPECT_THAT(RsaSsaPssSignKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(RsaSsaPssSignKeyManagerTest, ValidateKeyFormatHashMismatchDisallowed2) { RsaSsaPssKeyFormat key_format = ValidKeyFormat(); key_format.mutable_params()->set_sig_hash(HashType::SHA256); key_format.mutable_params()->set_mgf1_hash(HashType::SHA512); EXPECT_THAT(RsaSsaPssSignKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } TEST(RsaSsaPssSignKeyManagerTest, ValidateKeyFormatUnkownHashDisallowed) { RsaSsaPssKeyFormat key_format = ValidKeyFormat(); key_format.mutable_params()->set_sig_hash(HashType::UNKNOWN_HASH); key_format.mutable_params()->set_mgf1_hash(HashType::UNKNOWN_HASH); EXPECT_THAT(RsaSsaPssSignKeyManager().ValidateKeyFormat(key_format), Not(IsOk())); } // Runs several sanity checks, checking if a given private key fits a format. void CheckNewKey(const RsaSsaPssPrivateKey& private_key, const RsaSsaPssKeyFormat& key_format) { RsaSsaPssPublicKey public_key = private_key.public_key(); EXPECT_THAT(private_key.version(), Eq(0)); EXPECT_THAT(private_key.version(), Eq(public_key.version())); EXPECT_THAT(public_key.n().length(), Gt(0)); EXPECT_THAT(public_key.e().length(), Gt(0)); EXPECT_THAT(public_key.params().sig_hash(), Eq(key_format.params().sig_hash())); EXPECT_THAT(public_key.params().mgf1_hash(), Eq(key_format.params().mgf1_hash())); EXPECT_THAT(public_key.params().salt_length(), Eq(key_format.params().salt_length())); EXPECT_THAT(key_format.public_exponent(), Eq(public_key.e())); util::StatusOr> n = internal::StringToBignum(public_key.n()); ASSERT_THAT(n, IsOk()); util::StatusOr> d = internal::StringToBignum(private_key.d()); ASSERT_THAT(d, IsOk()); util::StatusOr> p = internal::StringToBignum(private_key.p()); ASSERT_THAT(p, IsOk()); util::StatusOr> q = internal::StringToBignum(private_key.q()); ASSERT_THAT(q, IsOk()); util::StatusOr> dp = internal::StringToBignum(private_key.dp()); ASSERT_THAT(dp, IsOk()); util::StatusOr> dq = internal::StringToBignum(private_key.dq()); ASSERT_THAT(dq, IsOk()); internal::SslUniquePtr ctx(BN_CTX_new()); // Check n = p * q. auto n_calc = internal::SslUniquePtr(BN_new()); EXPECT_TRUE(BN_mul(n_calc.get(), p->get(), q->get(), ctx.get())); EXPECT_EQ(BN_cmp(n_calc.get(), n->get()), 0); // Check n size >= modulus_size_in_bits bit. EXPECT_GE(BN_num_bits(n->get()), key_format.modulus_size_in_bits()); // dp = d mod (p - 1) auto pm1 = internal::SslUniquePtr(BN_dup(p->get())); EXPECT_TRUE(BN_sub_word(pm1.get(), 1)); auto dp_calc = internal::SslUniquePtr(BN_new()); EXPECT_TRUE(BN_mod(dp_calc.get(), d->get(), pm1.get(), ctx.get())); EXPECT_EQ(BN_cmp(dp_calc.get(), dp->get()), 0); // dq = d mod (q - 1) auto qm1 = internal::SslUniquePtr(BN_dup(q->get())); EXPECT_TRUE(BN_sub_word(qm1.get(), 1)); auto dq_calc = internal::SslUniquePtr(BN_new()); EXPECT_TRUE(BN_mod(dq_calc.get(), d->get(), qm1.get(), ctx.get())); EXPECT_EQ(BN_cmp(dq_calc.get(), dq->get()), 0); } TEST(RsaSsaPssSignKeyManagerTest, CreateKey) { RsaSsaPssKeyFormat key_format = ValidKeyFormat(); StatusOr private_key_or = RsaSsaPssSignKeyManager().CreateKey(key_format); ASSERT_THAT(private_key_or, IsOk()); CheckNewKey(private_key_or.value(), key_format); } TEST(RsaSsaPssSignKeyManagerTest, CreateKeySmallKey) { RsaSsaPssKeyFormat key_format = CreateKeyFormat(HashType::SHA256, HashType::SHA256, 32, 3072, RSA_F4); StatusOr private_key_or = RsaSsaPssSignKeyManager().CreateKey(key_format); ASSERT_THAT(private_key_or, IsOk()); CheckNewKey(private_key_or.value(), key_format); } TEST(RsaSsaPssSignKeyManagerTest, CreateKeyLargeKey) { RsaSsaPssKeyFormat key_format = CreateKeyFormat(HashType::SHA512, HashType::SHA512, 64, 4096, RSA_F4); StatusOr private_key_or = RsaSsaPssSignKeyManager().CreateKey(key_format); ASSERT_THAT(private_key_or, IsOk()); CheckNewKey(private_key_or.value(), key_format); } TEST(RsaSsaPssSignKeyManagerTest, CreateKeyValid) { StatusOr key_or = RsaSsaPssSignKeyManager().CreateKey(ValidKeyFormat()); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(RsaSsaPssSignKeyManager().ValidateKey(key_or.value()), IsOk()); } // Check that in a bunch of CreateKey calls all generated primes are distinct. TEST(RsaSsaPssSignKeyManagerTest, CreateKeyAlwaysNewRsaPair) { absl::flat_hash_set keys; // This test takes about a second per key. int num_generated_keys = 5; for (int i = 0; i < num_generated_keys; ++i) { StatusOr key_or = RsaSsaPssSignKeyManager().CreateKey(ValidKeyFormat()); ASSERT_THAT(key_or, IsOk()); keys.insert(key_or.value().p()); keys.insert(key_or.value().q()); } EXPECT_THAT(keys, SizeIs(2 * num_generated_keys)); } TEST(RsaSsaPssSignKeyManagerTest, GetPublicKey) { StatusOr key_or = RsaSsaPssSignKeyManager().CreateKey(ValidKeyFormat()); ASSERT_THAT(key_or, IsOk()); StatusOr public_key_or = RsaSsaPssSignKeyManager().GetPublicKey(key_or.value()); ASSERT_THAT(public_key_or, IsOk()); EXPECT_THAT(public_key_or.value().version(), Eq(key_or.value().public_key().version())); EXPECT_THAT(public_key_or.value().n(), Eq(key_or.value().public_key().n())); EXPECT_THAT(public_key_or.value().e(), Eq(key_or.value().public_key().e())); } TEST(RsaSsaPssSignKeyManagerTest, Create) { RsaSsaPssKeyFormat key_format = CreateKeyFormat(HashType::SHA256, HashType::SHA256, 32, 3072, RSA_F4); StatusOr key_or = RsaSsaPssSignKeyManager().CreateKey(key_format); ASSERT_THAT(key_or, IsOk()); RsaSsaPssPrivateKey key = key_or.value(); auto signer_or = RsaSsaPssSignKeyManager().GetPrimitive(key); ASSERT_THAT(signer_or, IsOk()); internal::RsaSsaPssParams params; params.sig_hash = subtle::HashType::SHA256; params.mgf1_hash = subtle::HashType::SHA256; params.salt_length = 32; auto direct_verifier_or = subtle::RsaSsaPssVerifyBoringSsl::New( {key.public_key().n(), key.public_key().e()}, params); ASSERT_THAT(direct_verifier_or, IsOk()); std::string message = "Some message"; EXPECT_THAT(direct_verifier_or.value()->Verify( signer_or.value()->Sign(message).value(), message), IsOk()); } TEST(RsaSsaPssSignKeyManagerTest, CreateWrongKey) { RsaSsaPssKeyFormat key_format = CreateKeyFormat(HashType::SHA256, HashType::SHA256, 32, 3072, RSA_F4); StatusOr key_or = RsaSsaPssSignKeyManager().CreateKey(key_format); ASSERT_THAT(key_or, IsOk()); RsaSsaPssPrivateKey key = key_or.value(); auto signer_or = RsaSsaPssSignKeyManager().GetPrimitive(key); StatusOr second_key_or = RsaSsaPssSignKeyManager().CreateKey(key_format); ASSERT_THAT(second_key_or, IsOk()); RsaSsaPssPrivateKey second_key = second_key_or.value(); ASSERT_THAT(signer_or, IsOk()); internal::RsaSsaPssParams params; params.sig_hash = subtle::HashType::SHA256; params.mgf1_hash = subtle::HashType::SHA256; params.salt_length = 32; auto direct_verifier_or = subtle::RsaSsaPssVerifyBoringSsl::New( {second_key.public_key().n(), second_key.public_key().e()}, params); ASSERT_THAT(direct_verifier_or, IsOk()); std::string message = "Some message"; EXPECT_THAT(direct_verifier_or.value()->Verify( signer_or.value()->Sign(message).value(), message), Not(IsOk())); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pss_verify_key_manager.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pss_verify_key_manager.h" #include #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/internal/bn_util.h" #include "tink/internal/md_util.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/public_key_verify.h" #include "tink/subtle/rsa_ssa_pss_verify_boringssl.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using crypto::tink::util::Enums; using crypto::tink::util::Status; using crypto::tink::util::StatusOr; using google::crypto::tink::RsaSsaPssParams; using google::crypto::tink::RsaSsaPssPublicKey; StatusOr> RsaSsaPssVerifyKeyManager::PublicKeyVerifyFactory::Create( const RsaSsaPssPublicKey& rsa_ssa_pss_public_key) const { internal::RsaPublicKey rsa_pub_key; rsa_pub_key.n = rsa_ssa_pss_public_key.n(); rsa_pub_key.e = rsa_ssa_pss_public_key.e(); internal::RsaSsaPssParams params; RsaSsaPssParams rsa_ssa_pss_params = rsa_ssa_pss_public_key.params(); params.sig_hash = Enums::ProtoToSubtle(rsa_ssa_pss_params.sig_hash()); params.mgf1_hash = Enums::ProtoToSubtle(rsa_ssa_pss_params.mgf1_hash()); params.salt_length = rsa_ssa_pss_params.salt_length(); auto rsa_ssa_pss_result = subtle::RsaSsaPssVerifyBoringSsl::New(rsa_pub_key, params); if (!rsa_ssa_pss_result.ok()) return rsa_ssa_pss_result.status(); return {std::move(rsa_ssa_pss_result).value()}; } Status RsaSsaPssVerifyKeyManager::ValidateKey( const RsaSsaPssPublicKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; StatusOr> n = internal::StringToBignum(key.n()); if (!n.ok()) { return n.status(); } Status modulus_status = internal::ValidateRsaModulusSize(BN_num_bits(n->get())); if (!modulus_status.ok()) { return modulus_status; } Status exponent_status = internal::ValidateRsaPublicExponent(key.e()); if (!exponent_status.ok()) { return exponent_status; } return ValidateParams(key.params()); } Status RsaSsaPssVerifyKeyManager::ValidateParams( const RsaSsaPssParams& params) const { util::Status hash_result = internal::IsHashTypeSafeForSignature( Enums::ProtoToSubtle(params.sig_hash())); if (!hash_result.ok()) { return hash_result; } // The most common use case is that MGF1 hash is the same as signature hash. // This is recommended by RFC https://tools.ietf.org/html/rfc8017#section-8.1. // While using different hashes doesn't cause security vulnerabilities, there // is also no good reason to support different hashes. Furthermore: // // - Golang does not support different hashes. // // - BoringSSL supports different hashes just because of historical reason. // There is no real use case. // // - Conscrypt/BouncyCastle do not support different hashes. if (params.mgf1_hash() != params.sig_hash()) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("MGF1 hash '", params.mgf1_hash(), "' is different from signature hash '", params.sig_hash(), "'")); } if (params.salt_length() < 0) { return util::Status(absl::StatusCode::kInvalidArgument, "salt length is negative"); } return util::OkStatus(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/rsa_ssa_pss_verify_key_manager.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_RSA_SSA_PSS_VERIFY_KEY_MANAGER_H_ #define TINK_SIGNATURE_RSA_SSA_PSS_VERIFY_KEY_MANAGER_H_ #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/key_type_manager.h" #include "tink/core/private_key_type_manager.h" #include "tink/core/template_util.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/util/constants.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class RsaSsaPssVerifyKeyManager : public KeyTypeManager> { public: class PublicKeyVerifyFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::RsaSsaPssPublicKey& rsa_ssa_pss_public_key) const override; }; RsaSsaPssVerifyKeyManager() : KeyTypeManager(absl::make_unique()) {} uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::ASYMMETRIC_PUBLIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::RsaSsaPssPublicKey& key) const override; crypto::tink::util::Status ValidateParams( const google::crypto::tink::RsaSsaPssParams& params) const; internal::FipsCompatibility FipsStatus() const override { return internal::FipsCompatibility::kRequiresBoringCrypto; } private: const std::string key_type_ = absl::StrCat(kTypeGoogleapisCom, google::crypto::tink::RsaSsaPssPublicKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_RSA_SSA_PSS_VERIFY_KEY_MANAGER_H_ ================================================ FILE: cc/signature/rsa_ssa_pss_verify_key_manager_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/rsa_ssa_pss_verify_key_manager.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "openssl/rsa.h" #include "tink/internal/bn_util.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/signature/rsa_ssa_pss_sign_key_manager.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/rsa_ssa_pss_sign_boringssl.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::RsaSsaPssKeyFormat; using ::google::crypto::tink::RsaSsaPssPrivateKey; using ::google::crypto::tink::RsaSsaPssPublicKey; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::Not; TEST(RsaSsaPssVerifyKeyManagerTest, Basics) { EXPECT_THAT(RsaSsaPssVerifyKeyManager().get_version(), Eq(0)); EXPECT_THAT(RsaSsaPssVerifyKeyManager().key_material_type(), Eq(KeyData::ASYMMETRIC_PUBLIC)); EXPECT_THAT(RsaSsaPssVerifyKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.RsaSsaPssPublicKey")); } TEST(RsaSsaPssVerifyKeyManagerTest, ValidateEmptyKey) { EXPECT_THAT(RsaSsaPssVerifyKeyManager().ValidateKey(RsaSsaPssPublicKey()), Not(IsOk())); } RsaSsaPssKeyFormat CreateKeyFormat(HashType sig_hash, HashType mgf1_hash, int salt_length, int modulus_size_in_bits, int public_exponent) { RsaSsaPssKeyFormat key_format; auto params = key_format.mutable_params(); params->set_sig_hash(sig_hash); params->set_mgf1_hash(mgf1_hash); params->set_salt_length(salt_length); key_format.set_modulus_size_in_bits(modulus_size_in_bits); internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), public_exponent); key_format.set_public_exponent( internal::BignumToString(e.get(), BN_num_bytes(e.get())).value()); return key_format; } RsaSsaPssKeyFormat ValidKeyFormat() { return CreateKeyFormat(HashType::SHA256, HashType::SHA256, 32, 3072, RSA_F4); } RsaSsaPssPrivateKey CreateValidPrivateKey() { return RsaSsaPssSignKeyManager().CreateKey(ValidKeyFormat()).value(); } RsaSsaPssPublicKey CreateValidPublicKey() { return RsaSsaPssSignKeyManager() .GetPublicKey(CreateValidPrivateKey()) .value(); } // Checks that a public key generaed by the SignKeyManager is considered valid. TEST(RsaSsaPssVerifyKeyManagerTest, PublicKeyValid) { RsaSsaPssPublicKey key = CreateValidPublicKey(); EXPECT_THAT(RsaSsaPssVerifyKeyManager().ValidateKey(key), IsOk()); } TEST(RsaSsaPssVerifyKeyManagerTest, PublicKeyWrongVersion) { RsaSsaPssPublicKey key = CreateValidPublicKey(); key.set_version(1); EXPECT_THAT(RsaSsaPssVerifyKeyManager().ValidateKey(key), Not(IsOk())); } TEST(RsaSsaPssVerifyKeyManagerTest, PublicKeyHashMismatchDisallowed) { RsaSsaPssPublicKey key = CreateValidPublicKey(); key.mutable_params()->set_sig_hash(HashType::SHA512); key.mutable_params()->set_mgf1_hash(HashType::SHA256); EXPECT_THAT(RsaSsaPssVerifyKeyManager().ValidateKey(key), Not(IsOk())); } TEST(RsaSsaPssVerifyKeyManagerTest, PublicKeyHashMismatchDisallowed2) { RsaSsaPssPublicKey key = CreateValidPublicKey(); key.mutable_params()->set_sig_hash(HashType::SHA256); key.mutable_params()->set_mgf1_hash(HashType::SHA512); EXPECT_THAT(RsaSsaPssVerifyKeyManager().ValidateKey(key), Not(IsOk())); } TEST(RsaSsaPssVerifyKeyManagerTest, PublicKeyUnkownHashDisallowed) { RsaSsaPssPublicKey key = CreateValidPublicKey(); key.mutable_params()->set_sig_hash(HashType::UNKNOWN_HASH); key.mutable_params()->set_mgf1_hash(HashType::UNKNOWN_HASH); EXPECT_THAT(RsaSsaPssVerifyKeyManager().ValidateKey(key), Not(IsOk())); } TEST(RsaSsaPssVerifyKeyManagerTest, ValidateKeyFormatSmallModulusDisallowed) { RsaSsaPssPublicKey key = CreateValidPublicKey(); key.set_n("\x23"); key.set_e("\x3"); EXPECT_THAT(RsaSsaPssVerifyKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("only modulus size >= 2048"))); } TEST(RsaSsaPssVerifyKeyManagerTest, NegativeSaltLengthFails) { RsaSsaPssPublicKey key = CreateValidPublicKey(); key.mutable_params()->set_salt_length(-5); EXPECT_THAT(RsaSsaPssVerifyKeyManager().ValidateKey(key), Not(IsOk())); } TEST(RsaSsaPssSignKeyManagerTest, Create) { RsaSsaPssKeyFormat key_format = CreateKeyFormat(HashType::SHA256, HashType::SHA256, 32, 3072, RSA_F4); StatusOr private_key_or = RsaSsaPssSignKeyManager().CreateKey(key_format); ASSERT_THAT(private_key_or, IsOk()); RsaSsaPssPrivateKey private_key = private_key_or.value(); RsaSsaPssPublicKey public_key = RsaSsaPssSignKeyManager().GetPublicKey(private_key).value(); internal::RsaPrivateKey private_key_subtle; private_key_subtle.n = private_key.public_key().n(); private_key_subtle.e = private_key.public_key().e(); private_key_subtle.d = util::SecretDataFromStringView(private_key.d()); private_key_subtle.p = util::SecretDataFromStringView(private_key.p()); private_key_subtle.q = util::SecretDataFromStringView(private_key.q()); private_key_subtle.dp = util::SecretDataFromStringView(private_key.dp()); private_key_subtle.dq = util::SecretDataFromStringView(private_key.dq()); private_key_subtle.crt = util::SecretDataFromStringView(private_key.crt()); auto direct_signer_or = subtle::RsaSsaPssSignBoringSsl::New( private_key_subtle, {crypto::tink::subtle::HashType::SHA256, crypto::tink::subtle::HashType::SHA256, 32}); auto verifier_or = RsaSsaPssVerifyKeyManager().GetPrimitive(public_key); ASSERT_THAT(verifier_or, IsOk()); std::string message = "Some message"; EXPECT_THAT(verifier_or.value()->Verify( direct_signer_or.value()->Sign(message).value(), message), IsOk()); } // Test vector from // https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Digital-Signatures struct NistTestVector { std::string n; std::string e; std::string message; std::string signature; HashType sig_hash; HashType mgf1_hash; int salt_length; }; // clang-format off static const NistTestVector* nist_test_vector = new NistTestVector({ absl::HexStringToBytes( "a47d04e7cacdba4ea26eca8a4c6e14563c2ce03b623b768c0d49868a57121301dbf783" "d82f4c055e73960e70550187d0af62ac3496f0a3d9103c2eb7919a72752fa7ce8c688d" "81e3aee99468887a15288afbb7acb845b7c522b5c64e678fcd3d22feb84b44272700be" "527d2b2025a3f83c2383bf6a39cf5b4e48b3cf2f56eef0dfff18555e31037b91524869" "4876f3047814415164f2c660881e694b58c28038a032ad25634aad7b39171dee368e3d" "59bfb7299e4601d4587e68caaf8db457b75af42fc0cf1ae7caced286d77fac6cedb03a" "d94f1433d2c94d08e60bc1fdef0543cd2951e765b38230fdd18de5d2ca627ddc032fe0" "5bbd2ff21e2db1c2f94d8b"), absl::HexStringToBytes("10e43f"), absl::HexStringToBytes( "e002377affb04f0fe4598de9d92d31d6c786040d5776976556a2cfc55e54a1dcb3cb1b" "126bd6a4bed2a184990ccea773fcc79d246553e6c64f686d21ad4152673cafec22aeb4" "0f6a084e8a5b4991f4c64cf8a927effd0fd775e71e8329e41fdd4457b3911173187b4f" "09a817d79ea2397fc12dfe3d9c9a0290c8ead31b6690a6"), absl::HexStringToBytes( "4f9b425c2058460e4ab2f5c96384da2327fd29150f01955a76b4efe956af06dc08779a" "374ee4607eab61a93adc5608f4ec36e47f2a0f754e8ff839a8a19b1db1e884ea4cf348" "cd455069eb87afd53645b44e28a0a56808f5031da5ba9112768dfbfca44ebe63a0c057" "2b731d66122fb71609be1480faa4e4f75e43955159d70f081e2a32fbb19a48b9f162cf" "6b2fb445d2d6994bc58910a26b5943477803cdaaa1bd74b0da0a5d053d8b1dc593091d" "b5388383c26079f344e2aea600d0e324164b450f7b9b465111b7265f3b1b063089ae7e" "2623fc0fda8052cf4bf3379102fbf71d7c98e8258664ceed637d20f95ff0111881e650" "ce61f251d9c3a629ef222d"), HashType::SHA256, HashType::SHA256, 32}); // clang-format on TEST(RsaSsaPssVerifyKeyManagerTest, TestVector) { RsaSsaPssPublicKey key; key.mutable_params()->set_mgf1_hash(nist_test_vector->mgf1_hash); key.mutable_params()->set_sig_hash(nist_test_vector->sig_hash); key.mutable_params()->set_salt_length(nist_test_vector->salt_length); key.set_version(0); key.set_n(nist_test_vector->n); key.set_e(nist_test_vector->e); auto result = RsaSsaPssVerifyKeyManager().GetPrimitive(key); ASSERT_THAT(result, IsOk()); EXPECT_THAT(result.value()->Verify(nist_test_vector->signature, nist_test_vector->message), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/sig_util.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/signature/sig_util.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/util/status.h" namespace crypto { namespace tink { crypto::tink::util::Status SignAndVerify(const PublicKeySign* signer, const PublicKeyVerify* verifier) { static constexpr char kTestMessage[] = "Wycheproof and Tink."; auto sign_result = signer->Sign(kTestMessage); if (!sign_result.ok()) return sign_result.status(); return verifier->Verify(sign_result.value(), kTestMessage); } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/sig_util.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_SIG_UTIL_H_ #define TINK_SIGNATURE_SIG_UTIL_H_ #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/util/status.h" namespace crypto { namespace tink { crypto::tink::util::Status SignAndVerify(const PublicKeySign* signer, const PublicKeyVerify* verifier); } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_SIG_UTIL_H_ ================================================ FILE: cc/signature/signature_config.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/signature/signature_config.h" #include "absl/memory/memory.h" #include "tink/config/config_util.h" #include "tink/config/tink_fips.h" #include "tink/registry.h" #include "tink/signature/ecdsa_proto_serialization.h" #include "tink/signature/ecdsa_verify_key_manager.h" #include "tink/signature/ed25519_sign_key_manager.h" #include "tink/signature/ed25519_verify_key_manager.h" #include "tink/signature/public_key_sign_wrapper.h" #include "tink/signature/public_key_verify_wrapper.h" #include "tink/signature/rsa_ssa_pkcs1_proto_serialization.h" #include "tink/signature/rsa_ssa_pkcs1_sign_key_manager.h" #include "tink/signature/rsa_ssa_pkcs1_verify_key_manager.h" #include "tink/signature/rsa_ssa_pss_proto_serialization.h" #include "tink/signature/rsa_ssa_pss_sign_key_manager.h" #include "tink/signature/rsa_ssa_pss_verify_key_manager.h" #include "tink/util/status.h" #include "tink/signature/ecdsa_sign_key_manager.h" #include "proto/config.pb.h" namespace crypto { namespace tink { // static util::Status SignatureConfig::Register() { // Register primitive wrappers. auto status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) return status; status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); if (!status.ok()) return status; // Register key managers which utilize FIPS validated BoringCrypto // implementations. // ECDSA status = Registry::RegisterAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), true); if (!status.ok()) return status; status = RegisterEcdsaProtoSerialization(); if (!status.ok()) { return status; } // RSA SSA PSS status = Registry::RegisterAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), true); if (!status.ok()) return status; status = RegisterRsaSsaPssProtoSerialization(); if (!status.ok()) return status; // RSA SSA PKCS1 status = Registry::RegisterAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), true); if (!status.ok()) return status; status = RegisterRsaSsaPkcs1ProtoSerialization(); if (!status.ok()) return status; if (IsFipsModeEnabled()) { return util::OkStatus(); } // ED25519 status = Registry::RegisterAsymmetricKeyManagers( absl::make_unique(), absl::make_unique(), true); if (!status.ok()) return status; return util::OkStatus(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/signature_config.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_SIGNATURE_CONFIG_H_ #define TINK_SIGNATURE_SIGNATURE_CONFIG_H_ #include "absl/base/macros.h" #include "tink/util/status.h" #include "proto/config.pb.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Static methods and constants for registering with the Registry // all instances of signature key types supported in a particular // release of Tink, i.e. key types that correspond to primitives // PublicKeySign and PublicKeyVerify. // // To register all signature key types from the current Tink release // one can do: // // auto status = SignatureConfig::Register(); // class SignatureConfig { public: // Registers PublicKeySign and PublicKeyVerify primitive wrappers, and key // managers for all implementations of PublicKeySign and PublicKeyVerify from // the current Tink release. static crypto::tink::util::Status Register(); private: SignatureConfig() {} }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_SIGNATURE_CONFIG_H_ ================================================ FILE: cc/signature/signature_config_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/signature_config.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/log/check.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/config/global_registry.h" #include "tink/crypto_format.h" #include "tink/ec_point.h" #include "tink/internal/ec_util.h" #include "tink/internal/legacy_proto_key.h" #include "tink/key_status.h" #include "tink/keyset_handle_builder.h" #include "tink/primitive_set.h" #include "tink/signature/ecdsa_private_key.h" #include "tink/signature/ecdsa_public_key.h" #include "tink/signature/key_gen_config_v0.h" #include "tink/subtle/common_enums.h" #include "tink/util/secret_data.h" #include "proto/rsa_ssa_pss.pb.h" #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #endif #include "openssl/bn.h" #include "openssl/rsa.h" #include "tink/big_integer.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/bn_util.h" #include "tink/internal/fips_utils.h" #include "tink/internal/mutable_serialization_registry.h" #include "tink/internal/proto_key_serialization.h" #include "tink/internal/proto_parameters_serialization.h" #include "tink/internal/serialization.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/key.h" #include "tink/keyset_handle.h" #include "tink/parameters.h" #include "tink/partial_key_access.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/registry.h" #include "tink/restricted_big_integer.h" #include "tink/restricted_data.h" #include "tink/signature/ecdsa_parameters.h" #include "tink/signature/rsa_ssa_pkcs1_parameters.h" #include "tink/signature/rsa_ssa_pkcs1_private_key.h" #include "tink/signature/rsa_ssa_pkcs1_public_key.h" #include "tink/signature/rsa_ssa_pss_parameters.h" #include "tink/signature/rsa_ssa_pss_private_key.h" #include "tink/signature/rsa_ssa_pss_public_key.h" #include "tink/signature/rsa_ssa_pss_sign_key_manager.h" #include "tink/signature/rsa_ssa_pss_verify_key_manager.h" #include "tink/signature/signature_key_templates.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/common.pb.h" #include "proto/rsa_ssa_pkcs1.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::DummyPublicKeySign; using ::crypto::tink::test::DummyPublicKeyVerify; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::OutputPrefixType; using ::testing::HasSubstr; using ::testing::IsNull; using ::testing::Not; class SignatureConfigTest : public ::testing::Test { protected: void SetUp() override { Registry::Reset(); internal::MutableSerializationRegistry::GlobalInstance().Reset(); }; }; TEST_F(SignatureConfigTest, testBasic) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is " "not available"; } EXPECT_THAT(Registry::get_key_manager( RsaSsaPssSignKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT(Registry::get_key_manager( RsaSsaPssVerifyKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT(SignatureConfig::Register(), IsOk()); EXPECT_THAT(Registry::get_key_manager( RsaSsaPssSignKeyManager().get_key_type()) .status(), IsOk()); EXPECT_THAT(Registry::get_key_manager( RsaSsaPssVerifyKeyManager().get_key_type()) .status(), IsOk()); } // Tests that the PublicKeySignWrapper has been properly registered and we // can wrap primitives. TEST_F(SignatureConfigTest, PublicKeySignWrapperRegistered) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is " "not available"; } ASSERT_TRUE(SignatureConfig::Register().ok()); google::crypto::tink::KeysetInfo::KeyInfo key_info; key_info.set_status(google::crypto::tink::KeyStatusType::ENABLED); key_info.set_key_id(1234); key_info.set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); auto primitive_set = absl::make_unique>(); ASSERT_THAT( primitive_set->set_primary( primitive_set ->AddPrimitive(absl::make_unique("dummy"), key_info) .value()), IsOk()); auto wrapped = Registry::Wrap(std::move(primitive_set)); ASSERT_TRUE(wrapped.ok()) << wrapped.status(); auto signature_result = wrapped.value()->Sign("message"); ASSERT_TRUE(signature_result.ok()); std::string prefix = CryptoFormat::GetOutputPrefix(key_info).value(); EXPECT_EQ(signature_result.value(), absl::StrCat(prefix, DummyPublicKeySign("dummy").Sign("message").value())); } // Tests that the PublicKeyVerifyWrapper has been properly registered and we // can wrap primitives. TEST_F(SignatureConfigTest, PublicKeyVerifyWrapperRegistered) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is " "not available"; } ASSERT_TRUE(SignatureConfig::Register().ok()); google::crypto::tink::KeysetInfo::KeyInfo key_info; key_info.set_status(google::crypto::tink::KeyStatusType::ENABLED); key_info.set_key_id(1234); key_info.set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); auto primitive_set = absl::make_unique>(); ASSERT_THAT( primitive_set->set_primary( primitive_set ->AddPrimitive(absl::make_unique("dummy"), key_info) .value()), IsOk()); std::string prefix = CryptoFormat::GetOutputPrefix(key_info).value(); std::string signature = DummyPublicKeySign("dummy").Sign("message").value(); auto wrapped = Registry::Wrap(std::move(primitive_set)); ASSERT_TRUE(wrapped.ok()) << wrapped.status(); ASSERT_TRUE( wrapped.value()->Verify(absl::StrCat(prefix, signature), "message").ok()); } // FIPS-only mode tests TEST_F(SignatureConfigTest, RegisterNonFipsTemplates) { if (!internal::IsFipsModeEnabled() || !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only supported in FIPS-only mode with BoringCrypto."; } EXPECT_THAT(SignatureConfig::Register(), IsOk()); std::list non_fips_key_templates; non_fips_key_templates.push_back(SignatureKeyTemplates::Ed25519()); non_fips_key_templates.push_back( SignatureKeyTemplates::Ed25519WithRawOutput()); // 4096-bit RSA is not validated. non_fips_key_templates.push_back( SignatureKeyTemplates::RsaSsaPkcs14096Sha512F4()); non_fips_key_templates.push_back( SignatureKeyTemplates::RsaSsaPss4096Sha384Sha384F4()); non_fips_key_templates.push_back( SignatureKeyTemplates::RsaSsaPss4096Sha512Sha512F4()); for (auto key_template : non_fips_key_templates) { EXPECT_THAT( KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()) .status(), Not(IsOk())); } } TEST_F(SignatureConfigTest, RegisterFipsValidTemplates) { if (!internal::IsFipsModeEnabled() || !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Only supported in FIPS-only mode with BoringCrypto."; } EXPECT_THAT(SignatureConfig::Register(), IsOk()); std::list fips_key_templates; fips_key_templates.push_back(SignatureKeyTemplates::EcdsaP256()); fips_key_templates.push_back(SignatureKeyTemplates::EcdsaP256Ieee()); fips_key_templates.push_back(SignatureKeyTemplates::EcdsaP384Sha384()); fips_key_templates.push_back(SignatureKeyTemplates::EcdsaP384Sha512()); fips_key_templates.push_back(SignatureKeyTemplates::EcdsaP384Ieee()); fips_key_templates.push_back(SignatureKeyTemplates::EcdsaP521()); fips_key_templates.push_back(SignatureKeyTemplates::EcdsaP521Ieee()); fips_key_templates.push_back( SignatureKeyTemplates::RsaSsaPkcs13072Sha256F4()); fips_key_templates.push_back( SignatureKeyTemplates::RsaSsaPss3072Sha256Sha256F4()); for (auto key_template : fips_key_templates) { EXPECT_THAT( KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()), IsOk()); } } TEST_F(SignatureConfigTest, RsaSsaPkcs1ProtoParamsSerializationRegistered) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is " "not available"; } util::StatusOr proto_params_serialization = internal::ProtoParametersSerialization::Create( SignatureKeyTemplates::RsaSsaPkcs13072Sha256F4()); ASSERT_THAT(proto_params_serialization, IsOk()); util::StatusOr> parsed_params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr params = RsaSsaPkcs1Parameters::Builder() .SetVariant(RsaSsaPkcs1Parameters::Variant::kTink) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetModulusSizeInBits(3072) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr> serialized_params = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params.status(), StatusIs(absl::StatusCode::kNotFound)); // Register serialization. ASSERT_THAT(SignatureConfig::Register(), IsOk()); util::StatusOr> parsed_params2 = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params2, IsOk()); util::StatusOr> serialized_params2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params2, IsOk()); } struct RsaKeyValues { std::string n; std::string e; std::string p; std::string q; std::string dp; std::string dq; std::string d; std::string q_inv; }; // Creates the values corresponding to an RSA key using OpenSSL. RsaKeyValues GenerateRsaKeyValues(int modulus_size_in_bits) { internal::SslUniquePtr rsa(RSA_new()); CHECK_NE(rsa.get(), nullptr); // Set public exponent to 65537. internal::SslUniquePtr e(BN_new()); CHECK_NE(e.get(), nullptr); BN_set_word(e.get(), 65537); // Generate an RSA key pair and get the values. CHECK(RSA_generate_key_ex(rsa.get(), modulus_size_in_bits, e.get(), /*cb=*/nullptr)); const BIGNUM *n_bn, *e_bn, *d_bn, *p_bn, *q_bn, *dp_bn, *dq_bn, *q_inv_bn; RSA_get0_key(rsa.get(), &n_bn, &e_bn, &d_bn); util::StatusOr n_str = internal::BignumToString(n_bn, BN_num_bytes(n_bn)); CHECK_OK(n_str); util::StatusOr e_str = internal::BignumToString(e_bn, BN_num_bytes(e_bn)); CHECK_OK(e_str); util::StatusOr d_str = internal::BignumToString(d_bn, BN_num_bytes(d_bn)); CHECK_OK(d_str); RSA_get0_factors(rsa.get(), &p_bn, &q_bn); util::StatusOr p_str = internal::BignumToString(p_bn, BN_num_bytes(p_bn)); CHECK_OK(p_str); util::StatusOr q_str = internal::BignumToString(q_bn, BN_num_bytes(q_bn)); CHECK_OK(q_str); RSA_get0_crt_params(rsa.get(), &dp_bn, &dq_bn, &q_inv_bn); util::StatusOr dp_str = internal::BignumToString(dp_bn, BN_num_bytes(dp_bn)); CHECK_OK(dp_str); util::StatusOr dq_str = internal::BignumToString(dq_bn, BN_num_bytes(dq_bn)); CHECK_OK(dq_str); util::StatusOr q_inv_str = internal::BignumToString(q_inv_bn, BN_num_bytes(q_inv_bn)); CHECK_OK(q_inv_str); return RsaKeyValues{*n_str, *e_str, *p_str, *q_str, *dp_str, *dq_str, *d_str, *q_inv_str}; } TEST_F(SignatureConfigTest, RsaSsaPkcs1ProtoPublicKeySerializationRegistered) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is " "not available"; } RsaKeyValues key_values = GenerateRsaKeyValues(/*modulus_size_in_bits=*/2048); google::crypto::tink::RsaSsaPkcs1PublicKey key_proto; key_proto.set_version(0); key_proto.set_n(key_values.n); key_proto.set_e(key_values.e); key_proto.mutable_params()->set_hash_type(HashType::SHA256); util::StatusOr proto_key_serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PublicKey", RestrictedData(key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()), KeyData::ASYMMETRIC_PUBLIC, OutputPrefixType::TINK, /*id_requirement=*/123); ASSERT_THAT(proto_key_serialization, IsOk()); util::StatusOr> parsed_key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr params = RsaSsaPkcs1Parameters::Builder() .SetVariant(RsaSsaPkcs1Parameters::Variant::kTink) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetModulusSizeInBits(2048) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr key = RsaSsaPkcs1PublicKey::Create( *params, BigInteger(key_values.n), /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialized_key = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key.status(), StatusIs(absl::StatusCode::kNotFound)); // Register serialization. ASSERT_THAT(SignatureConfig::Register(), IsOk()); util::StatusOr> parsed_key2 = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key2, IsOk()); util::StatusOr> serialized_key2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key2, IsOk()); } TEST_F(SignatureConfigTest, RsaSsaPkcs1ProtoPrivateKeySerializationRegistered) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is " "not available"; } RsaKeyValues key_values = GenerateRsaKeyValues(/*modulus_size_in_bits=*/2048); google::crypto::tink::RsaSsaPkcs1PublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_n(key_values.n); public_key_proto.set_e(key_values.e); public_key_proto.mutable_params()->set_hash_type(HashType::SHA256); google::crypto::tink::RsaSsaPkcs1PrivateKey private_key_proto; private_key_proto.set_version(0); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_p(key_values.p); private_key_proto.set_q(key_values.q); private_key_proto.set_dp(key_values.dp); private_key_proto.set_dq(key_values.dq); private_key_proto.set_d(key_values.d); private_key_proto.set_crt(key_values.q_inv); util::StatusOr proto_key_serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PrivateKey", RestrictedData(private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()), KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/123); ASSERT_THAT(proto_key_serialization, IsOk()); util::StatusOr> parsed_key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr params = RsaSsaPkcs1Parameters::Builder() .SetVariant(RsaSsaPkcs1Parameters::Variant::kTink) .SetHashType(RsaSsaPkcs1Parameters::HashType::kSha256) .SetModulusSizeInBits(2048) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr public_key = RsaSsaPkcs1PublicKey::Create(*params, BigInteger(key_values.n), /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = RsaSsaPkcs1PrivateKey::Builder() .SetPublicKey(*public_key) .SetPrimeP(RestrictedBigInteger(key_values.p, InsecureSecretKeyAccess::Get())) .SetPrimeQ(RestrictedBigInteger(key_values.q, InsecureSecretKeyAccess::Get())) .SetPrimeExponentP(RestrictedBigInteger( key_values.dp, InsecureSecretKeyAccess::Get())) .SetPrimeExponentQ(RestrictedBigInteger( key_values.dq, InsecureSecretKeyAccess::Get())) .SetPrivateExponent(RestrictedBigInteger( key_values.d, InsecureSecretKeyAccess::Get())) .SetCrtCoefficient(RestrictedBigInteger( key_values.q_inv, InsecureSecretKeyAccess::Get())) .Build(GetPartialKeyAccess()); util::StatusOr> serialized_key = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *private_key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key.status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(SignatureConfig::Register(), IsOk()); util::StatusOr> parsed_key2 = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key2, IsOk()); util::StatusOr> serialized_key2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *private_key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key2, IsOk()); } TEST_F(SignatureConfigTest, RsaSsaPssProtoParamsSerializationRegistered) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is " "not available"; } util::StatusOr proto_params_serialization = internal::ProtoParametersSerialization::Create( SignatureKeyTemplates::RsaSsaPss3072Sha256Sha256F4()); ASSERT_THAT(proto_params_serialization, IsOk()); util::StatusOr> parsed_params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr params = RsaSsaPssParameters::Builder() .SetVariant(RsaSsaPssParameters::Variant::kTink) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetModulusSizeInBits(3072) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr> serialized_params = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params.status(), StatusIs(absl::StatusCode::kNotFound)); // Register serialization. ASSERT_THAT(SignatureConfig::Register(), IsOk()); util::StatusOr> parsed_params2 = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params2, IsOk()); util::StatusOr> serialized_params2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params2, IsOk()); } TEST_F(SignatureConfigTest, RsaSsaPssProtoPublicKeySerializationRegistered) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is " "not available"; } RsaKeyValues key_values = GenerateRsaKeyValues(/*modulus_size_in_bits=*/2048); google::crypto::tink::RsaSsaPssParams params; params.set_sig_hash(HashType::SHA256); params.set_mgf1_hash(HashType::SHA256); params.set_salt_length(32); google::crypto::tink::RsaSsaPssPublicKey key_proto; key_proto.set_version(0); key_proto.set_n(key_values.n); key_proto.set_e(key_values.e); *key_proto.mutable_params() = params; util::StatusOr proto_key_serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PublicKey", RestrictedData(key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()), KeyData::ASYMMETRIC_PUBLIC, OutputPrefixType::TINK, /*id_requirement=*/123); ASSERT_THAT(proto_key_serialization, IsOk()); util::StatusOr> parsed_key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetVariant(RsaSsaPssParameters::Variant::kTink) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetModulusSizeInBits(2048) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr key = RsaSsaPssPublicKey::Create(*parameters, BigInteger(key_values.n), /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(key, IsOk()); util::StatusOr> serialized_key = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key.status(), StatusIs(absl::StatusCode::kNotFound)); // Register serialization. ASSERT_THAT(SignatureConfig::Register(), IsOk()); util::StatusOr> parsed_key2 = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key2, IsOk()); util::StatusOr> serialized_key2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key2, IsOk()); } TEST_F(SignatureConfigTest, RsaSsaPssProtoPrivateKeySerializationRegistered) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is " "not available"; } RsaKeyValues key_values = GenerateRsaKeyValues(/*modulus_size_in_bits=*/2048); google::crypto::tink::RsaSsaPssParams params; params.set_sig_hash(HashType::SHA256); params.set_mgf1_hash(HashType::SHA256); params.set_salt_length(32); google::crypto::tink::RsaSsaPssPublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_n(key_values.n); public_key_proto.set_e(key_values.e); *public_key_proto.mutable_params() = params; google::crypto::tink::RsaSsaPssPrivateKey private_key_proto; private_key_proto.set_version(0); *private_key_proto.mutable_public_key() = public_key_proto; private_key_proto.set_p(key_values.p); private_key_proto.set_q(key_values.q); private_key_proto.set_dp(key_values.dp); private_key_proto.set_dq(key_values.dq); private_key_proto.set_d(key_values.d); private_key_proto.set_crt(key_values.q_inv); util::StatusOr proto_key_serialization = internal::ProtoKeySerialization::Create( "type.googleapis.com/google.crypto.tink.RsaSsaPssPrivateKey", RestrictedData(private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get()), KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK, /*id_requirement=*/123); ASSERT_THAT(proto_key_serialization, IsOk()); util::StatusOr> parsed_key = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr parameters = RsaSsaPssParameters::Builder() .SetVariant(RsaSsaPssParameters::Variant::kTink) .SetSigHashType(RsaSsaPssParameters::HashType::kSha256) .SetMgf1HashType(RsaSsaPssParameters::HashType::kSha256) .SetSaltLengthInBytes(32) .SetModulusSizeInBits(2048) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr public_key = RsaSsaPssPublicKey::Create(*parameters, BigInteger(key_values.n), /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = RsaSsaPssPrivateKey::Builder() .SetPublicKey(*public_key) .SetPrimeP(RestrictedBigInteger(key_values.p, InsecureSecretKeyAccess::Get())) .SetPrimeQ(RestrictedBigInteger(key_values.q, InsecureSecretKeyAccess::Get())) .SetPrimeExponentP(RestrictedBigInteger( key_values.dp, InsecureSecretKeyAccess::Get())) .SetPrimeExponentQ(RestrictedBigInteger( key_values.dq, InsecureSecretKeyAccess::Get())) .SetPrivateExponent(RestrictedBigInteger( key_values.d, InsecureSecretKeyAccess::Get())) .SetCrtCoefficient(RestrictedBigInteger( key_values.q_inv, InsecureSecretKeyAccess::Get())) .Build(GetPartialKeyAccess()); util::StatusOr> serialized_key = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *private_key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key.status(), StatusIs(absl::StatusCode::kNotFound)); ASSERT_THAT(SignatureConfig::Register(), IsOk()); util::StatusOr> parsed_key2 = internal::MutableSerializationRegistry::GlobalInstance().ParseKey( *proto_key_serialization, InsecureSecretKeyAccess::Get()); ASSERT_THAT(parsed_key2, IsOk()); util::StatusOr> serialized_key2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeKey( *private_key, InsecureSecretKeyAccess::Get()); ASSERT_THAT(serialized_key2, IsOk()); } TEST_F(SignatureConfigTest, EcdsaProtoParamsSerializationRegistered) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Test non FIPS-mode only"; } util::StatusOr proto_params_serialization = internal::ProtoParametersSerialization::Create( SignatureKeyTemplates::EcdsaP256()); ASSERT_THAT(proto_params_serialization, IsOk()); util::StatusOr> parsed_params = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params.status(), StatusIs(absl::StatusCode::kNotFound)); util::StatusOr params = EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kTink) .Build(); ASSERT_THAT(params, IsOk()); util::StatusOr> serialized_params = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params.status(), StatusIs(absl::StatusCode::kNotFound)); // Register serialization. ASSERT_THAT(SignatureConfig::Register(), IsOk()); util::StatusOr> parsed_params2 = internal::MutableSerializationRegistry::GlobalInstance().ParseParameters( *proto_params_serialization); ASSERT_THAT(parsed_params2, IsOk()); util::StatusOr> serialized_params2 = internal::MutableSerializationRegistry::GlobalInstance() .SerializeParameters(*params); ASSERT_THAT(serialized_params2, IsOk()); } TEST_F(SignatureConfigTest, EcdsaProtoPublicKeySerializationRegistered) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Test non FIPS-mode only"; } util::StatusOr> handle = KeysetHandle::GenerateNew(SignatureKeyTemplates::EcdsaP256(), KeyGenConfigSignatureV0()); ASSERT_THAT(handle, IsOk()); util::StatusOr> public_handle = (*handle)->GetPublicKeysetHandle(KeyGenConfigSignatureV0()); ASSERT_THAT(public_handle, IsOk()); // Fails to parse this key type, so falls back to legacy proto key. EXPECT_THAT(dynamic_cast( (*public_handle)->GetPrimary().GetKey().get()), Not(IsNull())); util::StatusOr parameters = EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr ec_key = internal::NewEcKey(subtle::EllipticCurveType::NIST_P256); ASSERT_THAT(ec_key, IsOk()); EcPoint public_point(BigInteger(ec_key->pub_x), BigInteger(ec_key->pub_y)); util::StatusOr public_key = EcdsaPublicKey::Create(*parameters, public_point, /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); // Fails to serialize this key type. EXPECT_THAT(KeysetHandleBuilder() .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableKey( *public_key, KeyStatus::kEnabled, /*is_primary=*/true)) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Failed to serialize"))); // Register serialization. ASSERT_THAT(SignatureConfig::Register(), IsOk()); util::StatusOr> public_handle2 = (*handle)->GetPublicKeysetHandle(KeyGenConfigSignatureV0()); ASSERT_THAT(public_handle2, IsOk()); // Parsing now creates the right key type. EXPECT_THAT(dynamic_cast( (*public_handle2)->GetPrimary().GetKey().get()), Not(IsNull())); EXPECT_THAT(KeysetHandleBuilder() .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableKey( *public_key, KeyStatus::kEnabled, /*is_primary=*/true)) .Build(), IsOk()); } TEST_F(SignatureConfigTest, EcdsaProtoPrivateKeySerializationRegistered) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Test non FIPS-mode only"; } util::StatusOr> handle = KeysetHandle::GenerateNew(SignatureKeyTemplates::EcdsaP256(), KeyGenConfigSignatureV0()); ASSERT_THAT(handle, IsOk()); // Fails to parse this key type, so falls back to legacy proto key. EXPECT_THAT(dynamic_cast( (*handle)->GetPrimary().GetKey().get()), Not(IsNull())); util::StatusOr parameters = EcdsaParameters::Builder() .SetCurveType(EcdsaParameters::CurveType::kNistP256) .SetHashType(EcdsaParameters::HashType::kSha256) .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer) .SetVariant(EcdsaParameters::Variant::kTink) .Build(); ASSERT_THAT(parameters, IsOk()); util::StatusOr ec_key = internal::NewEcKey(subtle::EllipticCurveType::NIST_P256); ASSERT_THAT(ec_key, IsOk()); EcPoint public_point(BigInteger(ec_key->pub_x), BigInteger(ec_key->pub_y)); RestrictedBigInteger private_key_value = RestrictedBigInteger(util::SecretDataAsStringView(ec_key->priv), InsecureSecretKeyAccess::Get()); util::StatusOr public_key = EcdsaPublicKey::Create(*parameters, public_point, /*id_requirement=*/123, GetPartialKeyAccess()); ASSERT_THAT(public_key, IsOk()); util::StatusOr private_key = EcdsaPrivateKey::Create( *public_key, private_key_value, GetPartialKeyAccess()); ASSERT_THAT(private_key, IsOk()); // Fails to serialize this key type. EXPECT_THAT(KeysetHandleBuilder() .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableKey( *private_key, KeyStatus::kEnabled, /*is_primary=*/true)) .Build() .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Failed to serialize"))); // Register serialization. ASSERT_THAT(SignatureConfig::Register(), IsOk()); util::StatusOr> handle2 = KeysetHandle::GenerateNew(SignatureKeyTemplates::EcdsaP256(), KeyGenConfigSignatureV0()); ASSERT_THAT(handle2, IsOk()); // Parsing now creates the right key type. EXPECT_THAT(dynamic_cast( (*handle2)->GetPrimary().GetKey().get()), Not(IsNull())); EXPECT_THAT(KeysetHandleBuilder() .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableKey( *private_key, KeyStatus::kEnabled, /*is_primary=*/true)) .Build(), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/signature_key_templates.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/signature/signature_key_templates.h" #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "openssl/bn.h" #include "openssl/rsa.h" #include "tink/internal/bn_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/util/constants.h" #include "proto/common.pb.h" #include "proto/ecdsa.pb.h" #include "proto/ed25519.pb.h" #include "proto/rsa_ssa_pkcs1.pb.h" #include "proto/rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using google::crypto::tink::EcdsaKeyFormat; using google::crypto::tink::EcdsaPrivateKey; using google::crypto::tink::EcdsaSignatureEncoding; using google::crypto::tink::Ed25519PrivateKey; using google::crypto::tink::EllipticCurveType; using google::crypto::tink::HashType; using google::crypto::tink::KeyTemplate; using google::crypto::tink::OutputPrefixType; using google::crypto::tink::RsaSsaPkcs1KeyFormat; using google::crypto::tink::RsaSsaPkcs1PrivateKey; using google::crypto::tink::RsaSsaPssKeyFormat; using google::crypto::tink::RsaSsaPssPrivateKey; std::unique_ptr NewEcdsaKeyTemplate( HashType hash_type, EllipticCurveType curve_type, EcdsaSignatureEncoding encoding, OutputPrefixType output_prefix_type) { auto key_template = absl::make_unique(); key_template->set_type_url( absl::StrCat(kTypeGoogleapisCom, EcdsaPrivateKey().GetTypeName())); key_template->set_output_prefix_type(output_prefix_type); EcdsaKeyFormat key_format; auto params = key_format.mutable_params(); params->set_hash_type(hash_type); params->set_curve(curve_type); params->set_encoding(encoding); key_format.SerializeToString(key_template->mutable_value()); return key_template; } std::unique_ptr NewEcdsaKeyTemplate( HashType hash_type, EllipticCurveType curve_type, EcdsaSignatureEncoding encoding) { return NewEcdsaKeyTemplate(hash_type, curve_type, encoding, OutputPrefixType::TINK); } std::unique_ptr NewRsaSsaPkcs1KeyTemplate(HashType hash_type, int modulus_size_in_bits, int public_exponent) { auto key_template = absl::make_unique(); key_template->set_type_url( absl::StrCat(kTypeGoogleapisCom, RsaSsaPkcs1PrivateKey().GetTypeName())); key_template->set_output_prefix_type(OutputPrefixType::TINK); RsaSsaPkcs1KeyFormat key_format; auto params = key_format.mutable_params(); params->set_hash_type(hash_type); key_format.set_modulus_size_in_bits(modulus_size_in_bits); internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), public_exponent); key_format.set_public_exponent( internal::BignumToString(e.get(), BN_num_bytes(e.get())).value()); key_format.SerializeToString(key_template->mutable_value()); return key_template; } std::unique_ptr NewRsaSsaPssKeyTemplate(HashType sig_hash, HashType mgf1_hash, int salt_length, int modulus_size_in_bits, int public_exponent) { auto key_template = absl::make_unique(); key_template->set_type_url( absl::StrCat(kTypeGoogleapisCom, RsaSsaPssPrivateKey().GetTypeName())); key_template->set_output_prefix_type(OutputPrefixType::TINK); RsaSsaPssKeyFormat key_format; auto params = key_format.mutable_params(); params->set_sig_hash(sig_hash); params->set_mgf1_hash(mgf1_hash); params->set_salt_length(salt_length); key_format.set_modulus_size_in_bits(modulus_size_in_bits); internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), public_exponent); key_format.set_public_exponent( internal::BignumToString(e.get(), BN_num_bytes(e.get())).value()); key_format.SerializeToString(key_template->mutable_value()); return key_template; } } // anonymous namespace // static const KeyTemplate& SignatureKeyTemplates::EcdsaP256() { static const KeyTemplate* key_template = NewEcdsaKeyTemplate(HashType::SHA256, EllipticCurveType::NIST_P256, EcdsaSignatureEncoding::DER) .release(); return *key_template; } // Deprecated, use EcdsaP384Sha384() or EcdsaP384Sha512() instead. // static const KeyTemplate& SignatureKeyTemplates::EcdsaP384() { static const KeyTemplate* key_template = NewEcdsaKeyTemplate(HashType::SHA512, EllipticCurveType::NIST_P384, EcdsaSignatureEncoding::DER) .release(); return *key_template; } // static const KeyTemplate& SignatureKeyTemplates::EcdsaP384Sha384() { static const KeyTemplate* key_template = NewEcdsaKeyTemplate(HashType::SHA384, EllipticCurveType::NIST_P384, EcdsaSignatureEncoding::DER) .release(); return *key_template; } // static const KeyTemplate& SignatureKeyTemplates::EcdsaP384Sha512() { static const KeyTemplate* key_template = NewEcdsaKeyTemplate(HashType::SHA512, EllipticCurveType::NIST_P384, EcdsaSignatureEncoding::DER) .release(); return *key_template; } // static const KeyTemplate& SignatureKeyTemplates::EcdsaP521() { static const KeyTemplate* key_template = NewEcdsaKeyTemplate(HashType::SHA512, EllipticCurveType::NIST_P521, EcdsaSignatureEncoding::DER) .release(); return *key_template; } // static const KeyTemplate& SignatureKeyTemplates::EcdsaP256Raw() { static const KeyTemplate* key_template = NewEcdsaKeyTemplate(HashType::SHA256, EllipticCurveType::NIST_P256, EcdsaSignatureEncoding::IEEE_P1363, OutputPrefixType::RAW) .release(); return *key_template; } // static const KeyTemplate& SignatureKeyTemplates::EcdsaP256Ieee() { static const KeyTemplate* key_template = NewEcdsaKeyTemplate(HashType::SHA256, EllipticCurveType::NIST_P256, EcdsaSignatureEncoding::IEEE_P1363) .release(); return *key_template; } // static const KeyTemplate& SignatureKeyTemplates::EcdsaP384Ieee() { static const KeyTemplate* key_template = NewEcdsaKeyTemplate(HashType::SHA512, EllipticCurveType::NIST_P384, EcdsaSignatureEncoding::IEEE_P1363) .release(); return *key_template; } // static const KeyTemplate& SignatureKeyTemplates::EcdsaP521Ieee() { static const KeyTemplate* key_template = NewEcdsaKeyTemplate(HashType::SHA512, EllipticCurveType::NIST_P521, EcdsaSignatureEncoding::IEEE_P1363) .release(); return *key_template; } // static const KeyTemplate& SignatureKeyTemplates::RsaSsaPkcs13072Sha256F4() { static const KeyTemplate* key_template = NewRsaSsaPkcs1KeyTemplate(HashType::SHA256, 3072, RSA_F4).release(); return *key_template; } // static const KeyTemplate& SignatureKeyTemplates::RsaSsaPkcs14096Sha512F4() { static const KeyTemplate* key_template = NewRsaSsaPkcs1KeyTemplate(HashType::SHA512, 4096, RSA_F4).release(); return *key_template; } // static const KeyTemplate& SignatureKeyTemplates::RsaSsaPss3072Sha256Sha256F4() { static const KeyTemplate* key_template = NewRsaSsaPssKeyTemplate(HashType::SHA256, HashType::SHA256, 32, 3072, RSA_F4) .release(); return *key_template; } // static const KeyTemplate& SignatureKeyTemplates::RsaSsaPss4096Sha512Sha512F4() { static const KeyTemplate* key_template = NewRsaSsaPssKeyTemplate(HashType::SHA512, HashType::SHA512, 64, 4096, RSA_F4) .release(); return *key_template; } // static const KeyTemplate& SignatureKeyTemplates::RsaSsaPss4096Sha384Sha384F4() { static const KeyTemplate* key_template = NewRsaSsaPssKeyTemplate(HashType::SHA384, HashType::SHA384, 48, 4096, RSA_F4) .release(); return *key_template; } // static const google::crypto::tink::KeyTemplate& SignatureKeyTemplates::Ed25519() { static KeyTemplate* key_template = new KeyTemplate(); key_template->set_type_url( absl::StrCat(kTypeGoogleapisCom, Ed25519PrivateKey().GetTypeName())); key_template->set_output_prefix_type(OutputPrefixType::TINK); return *key_template; } // static const google::crypto::tink::KeyTemplate& SignatureKeyTemplates::Ed25519WithRawOutput() { static KeyTemplate* key_template = new KeyTemplate(); key_template->set_type_url( absl::StrCat(kTypeGoogleapisCom, Ed25519PrivateKey().GetTypeName())); key_template->set_output_prefix_type(OutputPrefixType::RAW); return *key_template; } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/signature_key_templates.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_SIGNATURE_KEY_TEMPLATES_H_ #define TINK_SIGNATURE_SIGNATURE_KEY_TEMPLATES_H_ #include "absl/base/attributes.h" #include "absl/base/macros.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Pre-generated KeyTemplate for signature key types. One can use these // templates to generate new KeysetHandle object with fresh keys. // To generate a new keyset that contains a single EcdsaPrivateKey, one can do: // // auto status = SignatureConfig::Register(); // if (!status.ok()) { /* fail with error */ } // auto handle_result = // KeysetHandle::GenerateNew(SignatureKeyTemplates::EcdsaP256()); // if (!handle_result.ok()) { /* fail with error */ } // auto keyset_handle = std::move(handle_result.value()); class SignatureKeyTemplates { public: // Returns a KeyTemplate that generates new instances of EcdsaPrivateKey // with the following parameters: // - EC curve: NIST P-256 // - hash function: SHA256 // - signature encoding: DER // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& EcdsaP256(); // Returns a KeyTemplate that generates new instances of EcdsaPrivateKey // with the following parameters: // - EC curve: NIST P-384 // - hash function: SHA512 // - signature encoding: DER // - OutputPrefixType: TINK ABSL_DEPRECATED("Use EcdsaP384Sha384() or EcdsaP384Sha512() instead") static const google::crypto::tink::KeyTemplate& EcdsaP384(); // Returns a KeyTemplate that generates new instances of EcdsaPrivateKey // with the following parameters: // - EC curve: NIST P-384 // - hash function: SHA384 // - signature encoding: DER // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& EcdsaP384Sha384(); // Returns a KeyTemplate that generates new instances of EcdsaPrivateKey // with the following parameters: // - EC curve: NIST P-384 // - hash function: SHA512 // - signature encoding: DER // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& EcdsaP384Sha512(); // Returns a KeyTemplate that generates new instances of EcdsaPrivateKey // with the following parameters: // - EC curve: NIST P-521 // - hash function: SHA512 // - signature encoding: DER // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& EcdsaP521(); // Returns a KeyTemplate that generates new instances of EcdsaPrivateKey // with the following parameters: // - EC curve: NIST P-256 // - hash function: SHA256 // - signature encoding: IEEE_P1363 // - OutputPrefixType: RAW // This template will give you compatibility with most other libraries. static const google::crypto::tink::KeyTemplate& EcdsaP256Raw(); // Returns a KeyTemplate that generates new instances of EcdsaPrivateKey // with the following parameters: // - EC curve: NIST P-256 // - hash function: SHA256 // - signature encoding: IEEE_P1363 // - OutputPrefixType: TINK // This key template does not make sense because IEEE P1363 mandates a raw // signature. ABSL_DEPRECATED("Use EcdsaP256() or EcdsaP256Raw() instead") static const google::crypto::tink::KeyTemplate& EcdsaP256Ieee(); // Returns a KeyTemplate that generates new instances of EcdsaPrivateKey // with the following parameters: // - EC curve: NIST P-384 // - hash function: SHA512 // - signature encoding: IEEE_P1363 // - OutputPrefixType: TINK // This key template does not make sense because IEEE P1363 mandates a raw // signature. ABSL_DEPRECATED( "Use EcdsaP384Sha384(), EcdsaP384Sha512() or EcdsaP256Raw() instead") static const google::crypto::tink::KeyTemplate& EcdsaP384Ieee(); // Returns a KeyTemplate that generates new instances of EcdsaPrivateKey // with the following parameters: // - EC curve: NIST P-521 // - hash function: SHA512 // - signature encoding: IEEE_P1363 // - OutputPrefixType: TINK // This key template does not make sense because IEEE P1363 mandates a raw // signature. ABSL_DEPRECATED("Use EcdsaP521() or EcdsaP256Raw() instead") static const google::crypto::tink::KeyTemplate& EcdsaP521Ieee(); // Returns a KeyTemplate that generates new instances of RsaSsaPkcs1PrivateKey // with the following parameters: // - Modulus size in bits: 3072. // - Hash function: SHA256. // - Public Exponent: 65537 (aka F4). // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& RsaSsaPkcs13072Sha256F4(); // Returns a KeyTemplate that generates new instances of RsaSsaPkcs1PrivateKey // with the following parameters: // - Modulus size in bits: 4096. // - Hash function: SHA512. // - Public Exponent: 65537 (aka F4). // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& RsaSsaPkcs14096Sha512F4(); // Returns a KeyTemplate that generates new instances of RsaSsaPssPrivateKey // with the following parameters: // - Modulus size in bits: 3072. // - Signature hash: SHA256. // - MGF1 hash: SHA256. // - Salt length: 32 (i.e., SHA256's output length). // - Public Exponent: 65537 (aka F4). // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& RsaSsaPss3072Sha256Sha256F4(); // Returns a KeyTemplate that generates new instances of RsaSsaPssPrivateKey // with the following parameters: // - Modulus size in bits: 4096. // - Signature hash: SHA512. // - MGF1 hash: SHA512. // - Salt length: 64 (i.e., SHA512's output length). // - Public Exponent: 65537 (aka F4). // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& RsaSsaPss4096Sha512Sha512F4(); // Returns a KeyTemplate that generates new instances of RsaSsaPssPrivateKey // with the following parameters: // - Modulus size in bits: 4096. // - Signature hash: SHA384. // - MGF1 hash: SHA384. // - Salt length: 48 (i.e., SHA384's output length). // - Public Exponent: 65537 (aka F4). // - OutputPrefixType: TINK static const google::crypto::tink::KeyTemplate& RsaSsaPss4096Sha384Sha384F4(); // Returns a KeyTemplate that generates new instances of Ed25519PrivateKey. static const google::crypto::tink::KeyTemplate& Ed25519(); // Returns a KeyTemplate that generates new instances of Ed25519PrivateKey. // The difference between Ed25519WithRawOutput and Ed25519 is the format of // signatures generated. Ed25519WithRawOutput generates signatures of // OutputPrefixType::RAW format, which is 64 bytes long. static const google::crypto::tink::KeyTemplate& Ed25519WithRawOutput(); }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_SIGNATURE_KEY_TEMPLATES_H_ ================================================ FILE: cc/signature/signature_key_templates_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/signature/signature_key_templates.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "openssl/bn.h" #include "openssl/rsa.h" #include "tink/core/key_manager_impl.h" #include "tink/core/private_key_manager_impl.h" #include "tink/internal/bn_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/public_key_sign.h" #include "tink/signature/ecdsa_sign_key_manager.h" #include "tink/signature/ecdsa_verify_key_manager.h" #include "tink/signature/ed25519_sign_key_manager.h" #include "tink/signature/ed25519_verify_key_manager.h" #include "tink/signature/rsa_ssa_pkcs1_sign_key_manager.h" #include "tink/signature/rsa_ssa_pss_sign_key_manager.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/common.pb.h" #include "proto/ecdsa.pb.h" #include "proto/ed25519.pb.h" #include "proto/rsa_ssa_pkcs1.pb.h" #include "proto/rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using google::crypto::tink::EcdsaKeyFormat; using google::crypto::tink::EcdsaSignatureEncoding; using google::crypto::tink::Ed25519KeyFormat; using google::crypto::tink::EllipticCurveType; using google::crypto::tink::HashType; using google::crypto::tink::KeyTemplate; using google::crypto::tink::OutputPrefixType; using google::crypto::tink::RsaSsaPkcs1KeyFormat; using google::crypto::tink::RsaSsaPssKeyFormat; TEST(SignatureKeyTemplatesTest, KeyTemplatesWithDerEncoding) { std::string type_url = "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey"; { // Test EcdsaP256(). // Check that returned template is correct. const KeyTemplate& key_template = SignatureKeyTemplates::EcdsaP256(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); EcdsaKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(HashType::SHA256, key_format.params().hash_type()); EXPECT_EQ(EllipticCurveType::NIST_P256, key_format.params().curve()); EXPECT_EQ(EcdsaSignatureEncoding::DER, key_format.params().encoding()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = SignatureKeyTemplates::EcdsaP256(); EXPECT_EQ(&key_template, &key_template_2); // Check that the key manager works with the template. EcdsaSignKeyManager sign_key_type_manager; EcdsaVerifyKeyManager verify_key_type_manager; auto key_manager = internal::MakePrivateKeyManager( &sign_key_type_manager, &verify_key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_format); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } { // Test EcdsaP256Raw(). // Check that returned template is correct. const KeyTemplate& key_template = SignatureKeyTemplates::EcdsaP256Raw(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::RAW, key_template.output_prefix_type()); EcdsaKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(HashType::SHA256, key_format.params().hash_type()); EXPECT_EQ(EllipticCurveType::NIST_P256, key_format.params().curve()); EXPECT_EQ(EcdsaSignatureEncoding::IEEE_P1363, key_format.params().encoding()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = SignatureKeyTemplates::EcdsaP256Raw(); EXPECT_EQ(&key_template, &key_template_2); // Check that the key manager works with the template. EcdsaSignKeyManager sign_key_type_manager; EcdsaVerifyKeyManager verify_key_type_manager; auto key_manager = internal::MakePrivateKeyManager( &sign_key_type_manager, &verify_key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_format); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } { // Test EcdsaP384(). // Check that returned template is correct. const KeyTemplate& key_template = SignatureKeyTemplates::EcdsaP384(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); EcdsaKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(HashType::SHA512, key_format.params().hash_type()); EXPECT_EQ(EllipticCurveType::NIST_P384, key_format.params().curve()); EXPECT_EQ(EcdsaSignatureEncoding::DER, key_format.params().encoding()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = SignatureKeyTemplates::EcdsaP384(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. EcdsaSignKeyManager sign_key_type_manager; EcdsaVerifyKeyManager verify_key_type_manager; auto key_manager = internal::MakePrivateKeyManager( &sign_key_type_manager, &verify_key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_format); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } { // Test EcdsaP384Sha512(). // Check that returned template is correct. const KeyTemplate& key_template = SignatureKeyTemplates::EcdsaP384Sha512(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); EcdsaKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(HashType::SHA512, key_format.params().hash_type()); EXPECT_EQ(EllipticCurveType::NIST_P384, key_format.params().curve()); EXPECT_EQ(EcdsaSignatureEncoding::DER, key_format.params().encoding()); // Check that reference to the same object is returned. const KeyTemplate& key_template2 = SignatureKeyTemplates::EcdsaP384Sha512(); EXPECT_EQ(&key_template, &key_template2); // Check that the template works with the key manager. EcdsaSignKeyManager sign_key_type_manager; EcdsaVerifyKeyManager verify_key_type_manager; auto key_manager = internal::MakePrivateKeyManager( &sign_key_type_manager, &verify_key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_format); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } { // Test EcdsaP384Sha384(). // Check that returned template is correct. const KeyTemplate& key_template = SignatureKeyTemplates::EcdsaP384Sha384(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); EcdsaKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(HashType::SHA384, key_format.params().hash_type()); EXPECT_EQ(EllipticCurveType::NIST_P384, key_format.params().curve()); EXPECT_EQ(EcdsaSignatureEncoding::DER, key_format.params().encoding()); // Check that reference to the same object is returned. const KeyTemplate& key_template2 = SignatureKeyTemplates::EcdsaP384Sha384(); EXPECT_EQ(&key_template, &key_template2); // Check that the template works with the key manager. EcdsaSignKeyManager sign_key_type_manager; EcdsaVerifyKeyManager verify_key_type_manager; auto key_manager = internal::MakePrivateKeyManager( &sign_key_type_manager, &verify_key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_format); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } { // Test EcdsaP521(). // Check that returned template is correct. const KeyTemplate& key_template = SignatureKeyTemplates::EcdsaP521(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); EcdsaKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(HashType::SHA512, key_format.params().hash_type()); EXPECT_EQ(EllipticCurveType::NIST_P521, key_format.params().curve()); EXPECT_EQ(EcdsaSignatureEncoding::DER, key_format.params().encoding()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = SignatureKeyTemplates::EcdsaP521(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. EcdsaSignKeyManager sign_key_type_manager; EcdsaVerifyKeyManager verify_key_type_manager; auto key_manager = internal::MakePrivateKeyManager( &sign_key_type_manager, &verify_key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_format); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } } TEST(SignatureKeyTemplatesTest, KeyTemplatesWithIeeeEncoding) { std::string type_url = "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey"; { // Test EcdsaP256Ieee(). // Check that returned template is correct. const KeyTemplate& key_template = SignatureKeyTemplates::EcdsaP256Ieee(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); EcdsaKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(HashType::SHA256, key_format.params().hash_type()); EXPECT_EQ(EllipticCurveType::NIST_P256, key_format.params().curve()); EXPECT_EQ(EcdsaSignatureEncoding::IEEE_P1363, key_format.params().encoding()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = SignatureKeyTemplates::EcdsaP256Ieee(); EXPECT_EQ(&key_template, &key_template_2); // Check that the key manager works with the template. EcdsaSignKeyManager sign_key_type_manager; EcdsaVerifyKeyManager verify_key_type_manager; auto key_manager = internal::MakePrivateKeyManager( &sign_key_type_manager, &verify_key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_format); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } { // Test EcdsaP384Ieee(). // Check that returned template is correct. const KeyTemplate& key_template = SignatureKeyTemplates::EcdsaP384Ieee(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); EcdsaKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(HashType::SHA512, key_format.params().hash_type()); EXPECT_EQ(EllipticCurveType::NIST_P384, key_format.params().curve()); EXPECT_EQ(EcdsaSignatureEncoding::IEEE_P1363, key_format.params().encoding()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = SignatureKeyTemplates::EcdsaP384Ieee(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. EcdsaSignKeyManager sign_key_type_manager; EcdsaVerifyKeyManager verify_key_type_manager; auto key_manager = internal::MakePrivateKeyManager( &sign_key_type_manager, &verify_key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_format); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } { // Test EcdsaP521Ieee(). // Check that returned template is correct. const KeyTemplate& key_template = SignatureKeyTemplates::EcdsaP521Ieee(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); EcdsaKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(HashType::SHA512, key_format.params().hash_type()); EXPECT_EQ(EllipticCurveType::NIST_P521, key_format.params().curve()); EXPECT_EQ(EcdsaSignatureEncoding::IEEE_P1363, key_format.params().encoding()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = SignatureKeyTemplates::EcdsaP521Ieee(); EXPECT_EQ(&key_template, &key_template_2); // Check that the template works with the key manager. EcdsaSignKeyManager sign_key_type_manager; EcdsaVerifyKeyManager verify_key_type_manager; auto key_manager = internal::MakePrivateKeyManager( &sign_key_type_manager, &verify_key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_format); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } } TEST(SignatureKeyTemplatesTest, KeyTemplatesWithRsaSsaPkcs13072Sha256F4) { std::string type_url = "type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PrivateKey"; const KeyTemplate& key_template = SignatureKeyTemplates::RsaSsaPkcs13072Sha256F4(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); RsaSsaPkcs1KeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(HashType::SHA256, key_format.params().hash_type()); EXPECT_GE(key_format.modulus_size_in_bits(), 3072); internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), RSA_F4); util::StatusOr> resulting_bn = internal::StringToBignum(key_format.public_exponent()); ASSERT_THAT(resulting_bn, IsOk()); EXPECT_EQ(BN_cmp(resulting_bn->get(), e.get()), 0); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = SignatureKeyTemplates::RsaSsaPkcs13072Sha256F4(); EXPECT_EQ(&key_template, &key_template_2); // Check that the key manager works with the template. RsaSsaPkcs1SignKeyManager key_type_manager; auto key_manager = internal::MakeKeyManager(&key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_format); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } TEST(SignatureKeyTemplatesTest, KeyTemplatesWithRsaSsaPkcs14096Sha512F4) { std::string type_url = "type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PrivateKey"; const KeyTemplate& key_template = SignatureKeyTemplates::RsaSsaPkcs14096Sha512F4(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); RsaSsaPkcs1KeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(HashType::SHA512, key_format.params().hash_type()); EXPECT_GE(key_format.modulus_size_in_bits(), 4096); internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), RSA_F4); util::StatusOr> resulting_bn = internal::StringToBignum(key_format.public_exponent()); ASSERT_THAT(resulting_bn, IsOk()); EXPECT_EQ(BN_cmp(resulting_bn->get(), e.get()), 0); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = SignatureKeyTemplates::RsaSsaPkcs14096Sha512F4(); EXPECT_EQ(&key_template, &key_template_2); // Check that the key manager works with the template. RsaSsaPkcs1SignKeyManager key_type_manager; auto key_manager = internal::MakeKeyManager(&key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_format); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } TEST(SignatureKeyTemplatesTest, KeyTemplatesWithRsaSsaPss3072Sha256Sha256F4) { std::string type_url = "type.googleapis.com/google.crypto.tink.RsaSsaPssPrivateKey"; const KeyTemplate& key_template = SignatureKeyTemplates::RsaSsaPss3072Sha256Sha256F4(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); RsaSsaPssKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(HashType::SHA256, key_format.params().sig_hash()); EXPECT_EQ(HashType::SHA256, key_format.params().mgf1_hash()); EXPECT_EQ(32, key_format.params().salt_length()); EXPECT_GE(key_format.modulus_size_in_bits(), 3072); internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), RSA_F4); util::StatusOr> resulting_bn = internal::StringToBignum(key_format.public_exponent()); ASSERT_THAT(resulting_bn, IsOk()); EXPECT_EQ(BN_cmp(resulting_bn->get(), e.get()), 0); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = SignatureKeyTemplates::RsaSsaPss3072Sha256Sha256F4(); EXPECT_EQ(&key_template, &key_template_2); // Check that the key manager works with the template. RsaSsaPssSignKeyManager key_type_manager; auto key_manager = internal::MakeKeyManager(&key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_format); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } TEST(SignatureKeyTemplatesTest, KeyTemplatesWithRsaSsaPss4096Sha384Sha384F4) { std::string type_url = "type.googleapis.com/google.crypto.tink.RsaSsaPssPrivateKey"; const KeyTemplate& key_template = SignatureKeyTemplates::RsaSsaPss4096Sha384Sha384F4(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); RsaSsaPssKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(HashType::SHA384, key_format.params().sig_hash()); EXPECT_EQ(HashType::SHA384, key_format.params().mgf1_hash()); EXPECT_EQ(48, key_format.params().salt_length()); EXPECT_GE(key_format.modulus_size_in_bits(), 4096); internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), RSA_F4); util::StatusOr> resulting_bn = internal::StringToBignum(key_format.public_exponent()); ASSERT_THAT(resulting_bn, IsOk()); EXPECT_EQ(BN_cmp(resulting_bn->get(), e.get()), 0); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = SignatureKeyTemplates::RsaSsaPss4096Sha384Sha384F4(); EXPECT_EQ(&key_template, &key_template_2); // Check that the key manager works with the template. RsaSsaPssSignKeyManager key_type_manager; auto key_manager = internal::MakeKeyManager(&key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_format); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } TEST(SignatureKeyTemplatesTest, KeyTemplatesWithRsaSsaPss4096Sha512Sha512F4) { std::string type_url = "type.googleapis.com/google.crypto.tink.RsaSsaPssPrivateKey"; const KeyTemplate& key_template = SignatureKeyTemplates::RsaSsaPss4096Sha512Sha512F4(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); RsaSsaPssKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_EQ(HashType::SHA512, key_format.params().sig_hash()); EXPECT_EQ(HashType::SHA512, key_format.params().mgf1_hash()); EXPECT_EQ(64, key_format.params().salt_length()); EXPECT_GE(key_format.modulus_size_in_bits(), 4096); internal::SslUniquePtr e(BN_new()); BN_set_word(e.get(), RSA_F4); util::StatusOr> resulting_bn = internal::StringToBignum(key_format.public_exponent()); ASSERT_THAT(resulting_bn, IsOk()); EXPECT_EQ(BN_cmp(resulting_bn->get(), e.get()), 0); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = SignatureKeyTemplates::RsaSsaPss4096Sha512Sha512F4(); EXPECT_EQ(&key_template, &key_template_2); // Check that the key manager works with the template. RsaSsaPssSignKeyManager key_type_manager; auto key_manager = internal::MakeKeyManager(&key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); auto new_key_result = key_manager->get_key_factory().NewKey(key_format); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } TEST(SignatureKeyTemplatesTest, KeyTemplatesWithEd25519) { std::string type_url = "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey"; const KeyTemplate& key_template = SignatureKeyTemplates::Ed25519(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = SignatureKeyTemplates::Ed25519(); EXPECT_EQ(&key_template, &key_template_2); // Check that the key manager works with the template. Ed25519SignKeyManager sign_key_type_manager; Ed25519VerifyKeyManager verify_key_type_manager; auto key_manager = internal::MakePrivateKeyManager( &sign_key_type_manager, &verify_key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); Ed25519KeyFormat key_format; auto new_key_result = key_manager->get_key_factory().NewKey(key_format); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } TEST(SignatureKeyTemplatesTest, KeyTemplatesWithEd25519WithRawOutput) { std::string type_url = "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey"; const KeyTemplate& key_template = SignatureKeyTemplates::Ed25519WithRawOutput(); EXPECT_EQ(type_url, key_template.type_url()); EXPECT_EQ(OutputPrefixType::RAW, key_template.output_prefix_type()); // Check that reference to the same object is returned. const KeyTemplate& key_template_2 = SignatureKeyTemplates::Ed25519WithRawOutput(); EXPECT_EQ(&key_template, &key_template_2); // Check that the key manager works with the template. Ed25519SignKeyManager sign_key_type_manager; Ed25519VerifyKeyManager verify_key_type_manager; auto key_manager = internal::MakePrivateKeyManager( &sign_key_type_manager, &verify_key_type_manager); EXPECT_EQ(key_manager->get_key_type(), key_template.type_url()); Ed25519KeyFormat key_format; auto new_key_result = key_manager->get_key_factory().NewKey(key_format); EXPECT_TRUE(new_key_result.ok()) << new_key_result.status(); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/signature_parameters.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_SIGNATURE_PARAMETERS_H_ #define TINK_SIGNATURE_SIGNATURE_PARAMETERS_H_ #include "tink/parameters.h" namespace crypto { namespace tink { // Describes a digital signature key pair (e.g., key attributes), excluding the // randomly chosen key material. class SignatureParameters : public Parameters {}; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_SIGNATURE_PARAMETERS_H_ ================================================ FILE: cc/signature/signature_pem_keyset_reader.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/signature/signature_pem_keyset_reader.h" #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/internal/ec_util.h" #include "tink/internal/rsa_util.h" #include "tink/keyset_reader.h" #include "tink/signature/ecdsa_verify_key_manager.h" #include "tink/signature/rsa_ssa_pkcs1_sign_key_manager.h" #include "tink/signature/rsa_ssa_pkcs1_verify_key_manager.h" #include "tink/signature/rsa_ssa_pss_sign_key_manager.h" #include "tink/signature/rsa_ssa_pss_verify_key_manager.h" #include "tink/subtle/pem_parser_boringssl.h" #include "tink/util/enums.h" #include "tink/util/keyset_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/common.pb.h" #include "proto/ecdsa.pb.h" #include "proto/rsa_ssa_pkcs1.pb.h" #include "proto/rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::google::crypto::tink::EcdsaParams; using ::google::crypto::tink::EcdsaPublicKey; using ::google::crypto::tink::EllipticCurveType; using ::google::crypto::tink::EncryptedKeyset; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::Keyset; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::OutputPrefixType; using ::google::crypto::tink::RsaSsaPkcs1PrivateKey; using ::google::crypto::tink::RsaSsaPkcs1PublicKey; using ::google::crypto::tink::RsaSsaPssParams; using ::google::crypto::tink::RsaSsaPssPrivateKey; using ::google::crypto::tink::RsaSsaPssPublicKey; namespace { // Sets the parameters for an RSASSA-PSS key `parameters` given the PEM // parameters `pem_parameters`. util::Status SetRsaSsaPssParameters(const PemKeyParams& pem_parameters, RsaSsaPssParams* parameters) { if (parameters == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "Null parameters provided"); } parameters->set_mgf1_hash(pem_parameters.hash_type); parameters->set_sig_hash(pem_parameters.hash_type); auto salt_len_or = util::Enums::HashLength(pem_parameters.hash_type); if (!salt_len_or.ok()) return salt_len_or.status(); parameters->set_salt_length(salt_len_or.value()); return util::OkStatus(); } // Sets the parameters for an ECDSA key `parameters` given the PEM // parameters `pem_parameters`. util::Status SetEcdsaParameters(const PemKeyParams& pem_parameters, EcdsaParams* parameters) { if (parameters == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "Null parameters provided"); } if (pem_parameters.hash_type != HashType::SHA256 || pem_parameters.key_size_in_bits != 256) { return util::Status( absl::StatusCode::kInvalidArgument, "Only NIST_P256 ECDSA supported. Parameters should contain " "SHA256 and 256 bit key size."); } parameters->set_hash_type(pem_parameters.hash_type); parameters->set_curve(EllipticCurveType::NIST_P256); switch (pem_parameters.algorithm) { case PemAlgorithm::ECDSA_IEEE: { parameters->set_encoding( google::crypto::tink::EcdsaSignatureEncoding::IEEE_P1363); break; } case PemAlgorithm::ECDSA_DER: { parameters->set_encoding( google::crypto::tink::EcdsaSignatureEncoding::DER); break; } default: { return util::Status( absl::StatusCode::kInvalidArgument, "Only ECDSA supported. The algorithm parameter should be " "ECDSA_IEEE or ECDSA_DER."); } } return util::OkStatus(); } // Creates a new Keyset::Key with ID `key_id`. The key has key data // `key_data`, key type `key_type`, and key material type // `key_material_type`. Keyset::Key NewKeysetKey(uint32_t key_id, absl::string_view key_type, const KeyData::KeyMaterialType& key_material_type, const std::string& key_data) { Keyset::Key key; // Populate KeyData for the new key. key.set_key_id(key_id); key.set_status(KeyStatusType::ENABLED); // PEM keys don't add any prefix to signatures key.set_output_prefix_type(OutputPrefixType::RAW); KeyData* key_data_proto = key.mutable_key_data(); key_data_proto->set_type_url(key_type.data(), key_type.size()); key_data_proto->set_value(key_data); key_data_proto->set_key_material_type(key_material_type); return key; } // Construct a new RSASSA-PSS key proto from a subtle RSA private key // `private_key_subtle`; the key is assigned version `key_version` and // key paramters `parameters`. util::StatusOr NewRsaSsaPrivateKey( const internal::RsaPrivateKey& private_key_subtle, uint32_t key_version, const PemKeyParams& parameters) { RsaSsaPssPrivateKey private_key_proto; // RSA Private key parameters. private_key_proto.set_version(key_version); private_key_proto.set_d( std::string(util::SecretDataAsStringView(private_key_subtle.d))); private_key_proto.set_p( std::string(util::SecretDataAsStringView(private_key_subtle.p))); private_key_proto.set_q( std::string(util::SecretDataAsStringView(private_key_subtle.q))); private_key_proto.set_dp( std::string(util::SecretDataAsStringView(private_key_subtle.dp))); private_key_proto.set_dq( std::string(util::SecretDataAsStringView(private_key_subtle.dq))); private_key_proto.set_crt( std::string(util::SecretDataAsStringView(private_key_subtle.crt))); // Inner RSA public key. RsaSsaPssPublicKey* public_key_proto = private_key_proto.mutable_public_key(); public_key_proto->set_version(key_version); public_key_proto->set_n(private_key_subtle.n); public_key_proto->set_e(private_key_subtle.e); // RSASSA-PSS public key parameters. auto set_parameter_status = SetRsaSsaPssParameters(parameters, public_key_proto->mutable_params()); if (!set_parameter_status.ok()) { return set_parameter_status; } return private_key_proto; } // Construct a new RSASSA-PKCS1 key proto from a subtle RSA private key // `private_key_subtle`; the key is assigned version `key_version` and // key paramters `parameters`. RsaSsaPkcs1PrivateKey NewRsaSsaPkcs1PrivateKey( const internal::RsaPrivateKey& private_key_subtle, uint32_t key_version, const PemKeyParams& parameters) { RsaSsaPkcs1PrivateKey private_key_proto; // RSA Private key parameters. private_key_proto.set_version(key_version); private_key_proto.set_d( std::string(util::SecretDataAsStringView(private_key_subtle.d))); private_key_proto.set_p( std::string(util::SecretDataAsStringView(private_key_subtle.p))); private_key_proto.set_q( std::string(util::SecretDataAsStringView(private_key_subtle.q))); private_key_proto.set_dp( std::string(util::SecretDataAsStringView(private_key_subtle.dp))); private_key_proto.set_dq( std::string(util::SecretDataAsStringView(private_key_subtle.dq))); private_key_proto.set_crt( std::string(util::SecretDataAsStringView(private_key_subtle.crt))); // Inner RSA Public key parameters. RsaSsaPkcs1PublicKey* public_key_proto = private_key_proto.mutable_public_key(); public_key_proto->set_version(key_version); public_key_proto->set_n(private_key_subtle.n); public_key_proto->set_e(private_key_subtle.e); // RSASSA-PKCS1 Public key parameters. public_key_proto->mutable_params()->set_hash_type(parameters.hash_type); return private_key_proto; } // Adds the PEM-encoded private key `pem_key` to `keyset`. util::Status AddRsaSsaPrivateKey(const PemKey& pem_key, Keyset* keyset) { // Try to parse the PEM RSA private key. auto private_key_subtle_or = subtle::PemParser::ParseRsaPrivateKey(pem_key.serialized_key); if (!private_key_subtle_or.ok()) return private_key_subtle_or.status(); std::unique_ptr private_key_subtle = std::move(private_key_subtle_or).value(); size_t modulus_size = private_key_subtle->n.length() * 8; if (pem_key.parameters.key_size_in_bits != modulus_size) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid RSA Key modulus size; found: ", modulus_size, ", expected: ", pem_key.parameters.key_size_in_bits)); } switch (pem_key.parameters.algorithm) { case PemAlgorithm::RSASSA_PSS: { RsaSsaPssSignKeyManager key_manager; auto private_key_proto_or = NewRsaSsaPrivateKey( *private_key_subtle, key_manager.get_version(), pem_key.parameters); if (!private_key_proto_or.ok()) return private_key_proto_or.status(); RsaSsaPssPrivateKey private_key_proto = private_key_proto_or.value(); // Validate the key. auto key_validation_status = key_manager.ValidateKey(private_key_proto); if (!key_validation_status.ok()) return key_validation_status; *keyset->add_key() = NewKeysetKey(GenerateUnusedKeyId(*keyset), key_manager.get_key_type(), key_manager.key_material_type(), private_key_proto.SerializeAsString()); break; } case PemAlgorithm::RSASSA_PKCS1: { RsaSsaPkcs1SignKeyManager key_manager; RsaSsaPkcs1PrivateKey private_key_proto = NewRsaSsaPkcs1PrivateKey( *private_key_subtle, key_manager.get_version(), pem_key.parameters); // Validate the key. auto key_validation_status = key_manager.ValidateKey(private_key_proto); if (!key_validation_status.ok()) return key_validation_status; *keyset->add_key() = NewKeysetKey(GenerateUnusedKeyId(*keyset), key_manager.get_key_type(), key_manager.key_material_type(), private_key_proto.SerializeAsString()); break; } default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid RSA algorithm ", pem_key.parameters.algorithm)); } return util::OkStatus(); } // Parses a given PEM-encoded ECDSA public key `pem_key`, and adds it to the // keyset `keyset`. util::Status AddEcdsaPublicKey(const PemKey& pem_key, Keyset* keyset) { // Parse the PEM string into a ECDSA public key. auto public_key_subtle_or = subtle::PemParser::ParseEcPublicKey(pem_key.serialized_key); if (!public_key_subtle_or.ok()) return public_key_subtle_or.status(); std::unique_ptr public_key_subtle = std::move(public_key_subtle_or).value(); EcdsaPublicKey ecdsa_key; EcdsaVerifyKeyManager key_manager; // ECDSA Public Key Parameters ecdsa_key.set_x(public_key_subtle->pub_x); ecdsa_key.set_y(public_key_subtle->pub_y); auto set_parameter_status = SetEcdsaParameters(pem_key.parameters, ecdsa_key.mutable_params()); if (!set_parameter_status.ok()) return set_parameter_status; ecdsa_key.set_version(key_manager.get_version()); // Validate the key. auto key_validation_status = key_manager.ValidateKey(ecdsa_key); if (!key_validation_status.ok()) return key_validation_status; *keyset->add_key() = NewKeysetKey( GenerateUnusedKeyId(*keyset), key_manager.get_key_type(), key_manager.key_material_type(), ecdsa_key.SerializeAsString()); return util::OkStatus(); } // Parses a given PEM-encoded RSA public key `pem_key`, and adds it to the // keyset `keyset`. util::Status AddRsaSsaPublicKey(const PemKey& pem_key, Keyset* keyset) { // Parse the PEM string into a RSA public key. auto public_key_subtle_or = subtle::PemParser::ParseRsaPublicKey(pem_key.serialized_key); if (!public_key_subtle_or.ok()) return public_key_subtle_or.status(); std::unique_ptr public_key_subtle = std::move(public_key_subtle_or).value(); // Check key length is as expected. size_t modulus_size = public_key_subtle->n.length() * 8; if (pem_key.parameters.key_size_in_bits != modulus_size) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid RSA Key modulus size; found ", modulus_size, ", expected ", pem_key.parameters.key_size_in_bits)); } switch (pem_key.parameters.algorithm) { case PemAlgorithm::RSASSA_PSS: { RsaSsaPssPublicKey public_key_proto; RsaSsaPssVerifyKeyManager key_manager; // RSA Public key paramters. public_key_proto.set_e(public_key_subtle->e); public_key_proto.set_n(public_key_subtle->n); // RSASSA-PSS Public key parameters. auto set_parameter_status = SetRsaSsaPssParameters( pem_key.parameters, public_key_proto.mutable_params()); if (!set_parameter_status.ok()) return set_parameter_status; public_key_proto.set_version(key_manager.get_version()); // Validate the key. auto key_validation_status = key_manager.ValidateKey(public_key_proto); if (!key_validation_status.ok()) return key_validation_status; *keyset->add_key() = NewKeysetKey(GenerateUnusedKeyId(*keyset), key_manager.get_key_type(), key_manager.key_material_type(), public_key_proto.SerializeAsString()); break; } case PemAlgorithm::RSASSA_PKCS1: { RsaSsaPkcs1PublicKey public_key_proto; RsaSsaPkcs1VerifyKeyManager key_manager; // RSA Public key paramters. public_key_proto.set_e(public_key_subtle->e); public_key_proto.set_n(public_key_subtle->n); // RSASSA-PKCS1 Public key parameters. public_key_proto.mutable_params()->set_hash_type( pem_key.parameters.hash_type); public_key_proto.set_version(key_manager.get_version()); // Validate the key. auto key_validation_status = key_manager.ValidateKey(public_key_proto); if (!key_validation_status.ok()) return key_validation_status; *keyset->add_key() = NewKeysetKey(GenerateUnusedKeyId(*keyset), key_manager.get_key_type(), key_manager.key_material_type(), public_key_proto.SerializeAsString()); break; } default: return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid RSA algorithm ", pem_key.parameters.algorithm)); } return util::OkStatus(); } } // namespace void SignaturePemKeysetReaderBuilder::Add(const PemKey& pem_serialized_key) { pem_serialized_keys_.push_back(pem_serialized_key); } util::StatusOr> SignaturePemKeysetReaderBuilder::Build() { if (pem_serialized_keys_.empty()) { return util::Status(absl::StatusCode::kInvalidArgument, "Empty array of PEM-encoded keys"); } switch (pem_reader_type_) { case PUBLIC_KEY_SIGN: { return absl::WrapUnique( new PublicKeySignPemKeysetReader(pem_serialized_keys_)); } case PUBLIC_KEY_VERIFY: { return absl::WrapUnique( new PublicKeyVerifyPemKeysetReader(pem_serialized_keys_)); } } return util::Status(absl::StatusCode::kInvalidArgument, "Unknown pem_reader_type_"); } util::StatusOr> PublicKeySignPemKeysetReader::Read() { if (pem_serialized_keys_.empty()) { return util::Status(absl::StatusCode::kInvalidArgument, "Empty array of PEM-encoded keys"); } auto keyset = absl::make_unique(); for (const PemKey& pem_key : pem_serialized_keys_) { // Parse and add the new key to the keyset. switch (pem_key.parameters.key_type) { case PemKeyType::PEM_RSA: { auto add_rsassa_pss_status = AddRsaSsaPrivateKey(pem_key, keyset.get()); if (!add_rsassa_pss_status.ok()) return add_rsassa_pss_status; break; } default: return util::Status(absl::StatusCode::kUnimplemented, "EC Keys Parsing unimplemented"); } } // Set the 1st key as primary. keyset->set_primary_key_id(keyset->key(0).key_id()); return std::move(keyset); } util::StatusOr> PublicKeyVerifyPemKeysetReader::Read() { if (pem_serialized_keys_.empty()) { return util::Status(absl::StatusCode::kInvalidArgument, "Empty array of PEM-encoded keys"); } auto keyset = absl::make_unique(); for (const PemKey& pem_key : pem_serialized_keys_) { // Parse and add the new key to the keyset. switch (pem_key.parameters.key_type) { case PemKeyType::PEM_RSA: { auto add_rsassa_pss_status = AddRsaSsaPublicKey(pem_key, keyset.get()); if (!add_rsassa_pss_status.ok()) return add_rsassa_pss_status; break; } case PemKeyType::PEM_EC: auto add_ecdsa_status = AddEcdsaPublicKey(pem_key, keyset.get()); if (!add_ecdsa_status.ok()) return add_ecdsa_status; } } // Set the 1st key as primary. keyset->set_primary_key_id(keyset->key(0).key_id()); return std::move(keyset); } util::StatusOr> SignaturePemKeysetReader::ReadEncrypted() { return util::Status(absl::StatusCode::kUnimplemented, "Reading Encrypted PEM is not supported"); } } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/signature_pem_keyset_reader.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_SIGNATURE_PEM_KEYSET_READER_H_ #define TINK_SIGNATURE_SIGNATURE_PEM_KEYSET_READER_H_ #include #include #include #include #include #include "tink/keyset_reader.h" #include "tink/util/statusor.h" #include "proto/common.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // Type of key. // // Currently, PEM_EC only supports PublicKeyVerify. enum PemKeyType { PEM_RSA, PEM_EC }; // Algorithm to use with this key. enum PemAlgorithm { RSASSA_PSS, RSASSA_PKCS1, ECDSA_IEEE, // NIST_P256 curve with IEEE_P1363 encoding ECDSA_DER // NIST_P256 curve with DER encoding }; // Common set of parameters for the PEM key. struct PemKeyParams { PemKeyType key_type; PemAlgorithm algorithm; size_t key_size_in_bits; ::google::crypto::tink::HashType hash_type; }; // A PEM key consists of its serialized data `serialized_key`, and parameters // `parameters`. struct PemKey { std::string serialized_key; PemKeyParams parameters; }; // Base class for parsing PEM-encoded keys (RFC 7468) into a keyset. class SignaturePemKeysetReader : public KeysetReader { public: util::StatusOr> ReadEncrypted() override; protected: explicit SignaturePemKeysetReader( const std::vector& pem_serialized_keys) : pem_serialized_keys_(pem_serialized_keys) {} // PEM-serialized keys to parse. std::vector pem_serialized_keys_; }; // Builder class for creating a PEM reader. Example usage: // // std::string some_public_key_pem = ...; // PemKeyType key_type = ...; // size_t key_size_in_bits = ...; // HashType hash_type = ...; // PemAlgorithm algorithm = ...; // // auto builder = SignaturePemKeysetReaderBuilder( // PemKeysetReaderBuilder::PemReaderType::PUBLIC_KEY_VERIFY); // builder.Add( // {.serialized_key = some_rsa_public_key_pem, // .parameters = { // .key_type = key_type, // .algorithm = algorithm, // .key_size_in_bits = key_size_in_bits, // .hash_type = hash_type}}); // ... // auto reader_statusor = builder.Build(); // if (!reader_statusor.ok()) /* handle failure */ // // auto keyset_handle_statusor = // CleartextKeysetHandle::Read(*reader_statusor); class SignaturePemKeysetReaderBuilder { public: // Type of reader to build. The builder type depends on the primitive // supported by the keys to parse. enum PemReaderType { PUBLIC_KEY_SIGN, PUBLIC_KEY_VERIFY }; explicit SignaturePemKeysetReaderBuilder(PemReaderType pem_reader_type) : pem_reader_type_(pem_reader_type) {} // Adds a PEM serialized key `pem_serialized_key` to the builder. void Add(const PemKey& pem_serialized_key); // Creates an instance of keyset reader based on `pem_reader_type_`, to parse // the PEM-encoded keys in `pem_serialized_keys_`. util::StatusOr> Build(); private: // List of keys as PEM serialized items. std::vector pem_serialized_keys_; // Reader type that this reader must support. PemReaderType pem_reader_type_; }; // Keyset reader for PEM keys that support the PublicKeySign principal. class PublicKeySignPemKeysetReader : public SignaturePemKeysetReader { public: util::StatusOr> Read() override; private: // Friend builder class. friend class SignaturePemKeysetReaderBuilder; explicit PublicKeySignPemKeysetReader( const std::vector pem_serialized_keys) : SignaturePemKeysetReader(pem_serialized_keys) {} }; // Keyset reader for PEM keys that support the PublicKeyVerify principal. class PublicKeyVerifyPemKeysetReader : public SignaturePemKeysetReader { public: util::StatusOr> Read() override; private: // Friend builder class. friend class SignaturePemKeysetReaderBuilder; explicit PublicKeyVerifyPemKeysetReader( const std::vector pem_serialized_keys) : SignaturePemKeysetReader(pem_serialized_keys) {} }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_SIGNATURE_PEM_KEYSET_READER_H_ ================================================ FILE: cc/signature/signature_pem_keyset_reader_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/signature/signature_pem_keyset_reader.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_util.h" #include "tink/keyset_handle.h" #include "tink/keyset_reader.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/signature/ecdsa_verify_key_manager.h" #include "tink/signature/rsa_ssa_pss_sign_key_manager.h" #include "tink/signature/rsa_ssa_pss_verify_key_manager.h" #include "tink/signature/signature_config.h" #include "tink/subtle/pem_parser_boringssl.h" #include "tink/util/enums.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/common.pb.h" #include "proto/ecdsa.pb.h" #include "proto/rsa_ssa_pss.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::EqualsKey; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::EcdsaPublicKey; using ::google::crypto::tink::EcdsaSignatureEncoding; using ::google::crypto::tink::EllipticCurveType; using ::google::crypto::tink::HashType; using ::google::crypto::tink::KeyData; using ::google::crypto::tink::Keyset; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::OutputPrefixType; using ::google::crypto::tink::RsaSsaPssPrivateKey; using ::google::crypto::tink::RsaSsaPssPublicKey; using ::testing::Eq; using ::testing::Not; using ::testing::SizeIs; constexpr absl::string_view kEcdsaP256PublicKey = "-----BEGIN PUBLIC KEY-----\n" "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1M5IlCiYLvNDGG65DmoErfQTZjWa\n" "UI/nrGayg/BmQa4f9db4zQRCc5IwErn3JtlLDAxQ8fXUoy99klswBEMZ/A==\n" "-----END PUBLIC KEY-----\n"; constexpr absl::string_view kEcdsaP256PublicKeyX = "d4ce489428982ef343186eb90e6a04adf41366359a508fe7ac66b283f06641ae"; constexpr absl::string_view kEcdsaP256PublicKeyY = "1ff5d6f8cd044273923012b9f726d94b0c0c50f1f5d4a32f7d925b30044319fc"; constexpr absl::string_view kEcdsaP384PublicKey = "-----BEGIN PUBLIC KEY-----" "MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAESbGnhTcoHIGYTgAJLwTCLGEMrCq6ej3p" "kr9q0iMF0tVFAYdX7YI8ZDM04Y2VsuZC0qhRRFxdoL8NVD6q1f+YY0SDxUnZYEUk" "MSHtbVybpk2rZWptJeAYsBxNOrPxc4mJ" "-----END PUBLIC KEY-----"; constexpr absl::string_view kSecp256k1PublicKey = "-----BEGIN PUBLIC KEY-----\n" "MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEuDj/ROW8F3vyEYnQdmCC/J2EMiaIf8l2\n" "A3EQC37iCm/wyddb+6ezGmvKGXRJbutW3jVwcZVdg8Sxutqgshgy6Q==\n" "-----END PUBLIC KEY-----"; constexpr absl::string_view kEd25519PublicKey = "-----BEGIN PUBLIC KEY-----\n" "MCowBQYDK2VwAyEAfU0Of2FTpptiQrUiq77mhf2kQg+INLEIw72uNp71Sfo=\n" "-----END PUBLIC KEY-----\n"; constexpr absl::string_view kRsaPublicKey2048 = "-----BEGIN PUBLIC KEY-----\n" "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsll1i7Arx1tosXYSyb9o\n" "xfoFlYozTGHhZ7wgvMdXV8Em6JIQud85iQcs9iYOaIPHzUr00x3emRW2mzAfvvli\n" "3oxxvS217GJdollxL4ao3D0kHpaIyCORt78evDWDEfVcJr6RC3b2H+pAjtaS8alX\n" "imIsgsD89vae82cOOL/JD2PaTzu70IjIrno8WlXmb2R01WLTLM57ft188BScoOls\n" "tlJegfu6gVqPEnSONOUTX1crLhe3ukMAgVl+b7kDPABYhNWTURjGDXWwEPb+zn7N\n" "zBy31Y0TiWk9Qzd/Tz3pScseQQXnkrltfwSwzSYqwzz/xaiQ0mdCXmHBnpNjVQ8i\n" "hQIDAQAB\n" "-----END PUBLIC KEY-----\n"; constexpr absl::string_view kRsaPublicKey1024 = "-----BEGIN PUBLIC KEY-----\n" "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+lQMh614+1PINuxuGg8ks1DOD\n" "pxDGcbLm47clu/J3KE7htWxPaiLsVeowNURyYTLTscZ/AcD7p3ceVDWNwz5xtETI\n" "n2GcHy9Jaaph6HSYak2IOg0p5btxqbd9+UfqKhbmrtMNDNrdRJOq8Z7oLlvbzT0x\n" "pj37y294RWqIWhm1rwIDAQAB\n" "-----END PUBLIC KEY-----\n"; constexpr absl::string_view kRsaPrivateKey2048 = "-----BEGIN RSA PRIVATE KEY-----\n" "MIIEpAIBAAKCAQEAsll1i7Arx1tosXYSyb9oxfoFlYozTGHhZ7wgvMdXV8Em6JIQ\n" "ud85iQcs9iYOaIPHzUr00x3emRW2mzAfvvli3oxxvS217GJdollxL4ao3D0kHpaI\n" "yCORt78evDWDEfVcJr6RC3b2H+pAjtaS8alXimIsgsD89vae82cOOL/JD2PaTzu7\n" "0IjIrno8WlXmb2R01WLTLM57ft188BScoOlstlJegfu6gVqPEnSONOUTX1crLhe3\n" "ukMAgVl+b7kDPABYhNWTURjGDXWwEPb+zn7NzBy31Y0TiWk9Qzd/Tz3pScseQQXn\n" "krltfwSwzSYqwzz/xaiQ0mdCXmHBnpNjVQ8ihQIDAQABAoIBAHYrXf3bEXa6syh6\n" "AkLYZzRdz5tggVLHu9C+zrYmIlILsZsBRMHTDM0lCv5hAsTvI9B7LLJBJT8rKt2y\n" "SiaAGKk6RxZAljx0hHPQbXU+9N1QSYFW3nQ1VRR5NoUfs6OPfapSM8pz3OoSjQnX\n" "VG94c39GQxWzhyifCXxeuQaS1EY0F8g9HKkSdRbvsNVF/2j+rdmWeur8swtYBDCN\n" "nBymiDhEBj/Y1Ft3R6ywC14YM/af4aDWTbhQvZYPtITdoEtOWulGkqcx0j/NlMYU\n" "SZcaG3M/6UuKXGzibtO4w9LlI00HPlBDi3fQGbezk6WyLNjcE4xj/MKFg7VosgN7\n" "XDy68tUCgYEA6FovqDcya6JxivhyVZks98e22sPARwpowI3Nt+gsF5uPcqQMvbot\n" "ACzKHjqxRJyGbioMUI8Ao20/f2PxzeI5wAtH2HPNaN6bCbBXvxlCTMCAokbHSWjW\n" "stK2PXl2cqF/51ED7EPbgxABetGyfudsx22QowSR66Sq3I8UtZnQVUMCgYEAxIBC\n" "EW2oLh9ZUKxEeMuFlMN1FJCCqIx3zeVjUtAC3Vm/VvodEL0KM7w9Y123BfeoWMnG\n" "HaqNUEZRUO/bMvaiIXVykF19NTCxym4s6eKNBwGsdWvxroRm0k37uhflt9A7iVX6\n" "HmDVPYgjLJbPmLc8+Ms5ML6Od7qXKajRFOPmSJcCgYEA28JY6s/x9013+InNkdpD\n" "ZsNU1gpo9IgK1XwJQ1TrRxTRkwtIJbZN06mJLRg0C4HDv7QzW4o1f1zXvsQnsqOy\n" "HUpOFJJKiFJq7roD8/GO/Irh3xn0aSEoV4/l37Te68KF96FvhWoU1xwvWhu1qEN4\n" "ZhLhxt2OqgJfvCXz32LwYYMCgYBVEL0JNHJw/Qs6PEksDdcXLoI509FsS9r1XE9i\n" "I0CKOHb3nTEF9QA8o0nkAUbhI3RSc477esDQNpCvPBalelV3rJNa4c35P8pHuuhg\n" "m723gcb50i/+/7xPYIkP55Z/u3p6mqi7i+nkSFIJ1IOsNe8EOV3ZtzSPqkwUMcvJ\n" "gltHowKBgQDkB76QzH3xb4jABKehkCxVxqyGLKxU7SOZpLpCc/5OHbo12u/CwlwG\n" "uAeidKZk3SJEmj0F1+Aiir2KRv+RX543VvzCtEXNkVViVrirzvjZUGKPdkMWfbF8\n" "OdD7qHPPNu5jSyaroeN6VqfbELpewhYzulMEipckEZlU4+Dxu2k1eQ==\n" "-----END RSA PRIVATE KEY-----\n"; // Helper function that creates an EcdsaPublicKey from the given PEM encoded // key `pem_encoded_key`, Hash type `hash_type` and key version `key_version`. EcdsaPublicKey GetExpectedEcdsaPublicKeyProto(EcdsaSignatureEncoding encoding) { EcdsaPublicKey public_key_proto; public_key_proto.set_version(0); public_key_proto.set_x(absl::HexStringToBytes(kEcdsaP256PublicKeyX)); public_key_proto.set_y(absl::HexStringToBytes(kEcdsaP256PublicKeyY)); public_key_proto.mutable_params()->set_hash_type(HashType::SHA256); public_key_proto.mutable_params()->set_curve(EllipticCurveType::NIST_P256); public_key_proto.mutable_params()->set_encoding(encoding); return public_key_proto; } // Helper function that creates an RsaSsaPssPublicKey from the given PEM encoded // key `pem_encoded_key`, Hash type `hash_type` and key version `key_version`. util::StatusOr GetRsaSsaPssPublicKeyProto( absl::string_view pem_encoded_key, HashType hash_type, uint32_t key_version) { util::StatusOr> public_key = subtle::PemParser::ParseRsaPublicKey(pem_encoded_key); if (!public_key.ok()) { return public_key.status(); } std::unique_ptr key_subtle = *std::move(public_key); RsaSsaPssPublicKey public_key_proto; public_key_proto.set_version(key_version); public_key_proto.set_e(key_subtle->e); public_key_proto.set_n(key_subtle->n); public_key_proto.mutable_params()->set_mgf1_hash(hash_type); public_key_proto.mutable_params()->set_sig_hash(hash_type); public_key_proto.mutable_params()->set_salt_length( util::Enums::HashLength(hash_type).value()); return public_key_proto; } // Helper function that creates an RsaSsaPssPrivateKey from the given PEM // encoded key `pem_encoded_key`, Hash type `hash_type` and key version // `key_version`. util::StatusOr GetRsaSsaPssPrivateKeyProto( absl::string_view pem_encoded_key, HashType hash_type, uint32_t key_version) { // Parse the key with subtle::PemParser to make sure the proto key fields are // correct. util::StatusOr> private_key = subtle::PemParser::ParseRsaPrivateKey(pem_encoded_key); if (!private_key.ok()) { return private_key.status(); } std::unique_ptr key_subtle = *std::move(private_key); // Set the inner RSASSA-PSS public key and its parameters. RsaSsaPssPrivateKey private_key_proto; private_key_proto.set_version(key_version); private_key_proto.set_d( std::string(util::SecretDataAsStringView(key_subtle->d))); private_key_proto.set_p( std::string(util::SecretDataAsStringView(key_subtle->p))); private_key_proto.set_q( std::string(util::SecretDataAsStringView(key_subtle->q))); private_key_proto.set_dp( std::string(util::SecretDataAsStringView(key_subtle->dp))); private_key_proto.set_dq( std::string(util::SecretDataAsStringView(key_subtle->dq))); private_key_proto.set_crt( std::string(util::SecretDataAsStringView(key_subtle->crt))); // Set public key parameters. RsaSsaPssPublicKey* public_key_proto = private_key_proto.mutable_public_key(); public_key_proto->set_version(key_version); public_key_proto->set_e(key_subtle->e); public_key_proto->set_n(key_subtle->n); // Set algorithm-specific parameters. public_key_proto->mutable_params()->set_mgf1_hash(hash_type); public_key_proto->mutable_params()->set_sig_hash(hash_type); public_key_proto->mutable_params()->set_salt_length( util::Enums::HashLength(hash_type).value()); return private_key_proto; } PemKey CreatePemKey(absl::string_view serialized_key, crypto::tink::PemKeyType key_type, crypto::tink::PemAlgorithm algorithm, size_t key_size_in_bits, google::crypto::tink::HashType hash_type) { PemKey pem_key = { /*serialized_key=*/std::string(serialized_key), /*parameters=*/{key_type, algorithm, key_size_in_bits, hash_type}, }; return pem_key; } // Verify check on PEM array size not zero before creating a reader. TEST(SignaturePemKeysetReaderTest, BuildEmptyPemArray) { auto builder = SignaturePemKeysetReaderBuilder( SignaturePemKeysetReaderBuilder::PemReaderType::PUBLIC_KEY_SIGN); auto keyset_reader_or = builder.Build(); EXPECT_THAT(keyset_reader_or.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } // Make sure ReadUnencrypted returns an UNSUPPORTED error as expected. TEST(SignaturePemKeysetReaderTest, ReadEncryptedUnsupported) { auto builder = SignaturePemKeysetReaderBuilder( SignaturePemKeysetReaderBuilder::PemReaderType::PUBLIC_KEY_VERIFY); builder.Add(CreatePemKey(kRsaPublicKey2048, PemKeyType::PEM_RSA, PemAlgorithm::RSASSA_PSS, /*key_size_in_bits=*/2048, HashType::SHA384)); auto keyset_reader_or = builder.Build(); ASSERT_THAT(keyset_reader_or, IsOk()); std::unique_ptr keyset_reader = std::move(keyset_reader_or).value(); EXPECT_THAT(keyset_reader->ReadEncrypted().status(), StatusIs(absl::StatusCode::kUnimplemented)); } // Verify parsing works correctly on valid inputs. TEST(SignaturePemKeysetReaderTest, ReadRsaCorrectPublicKey) { auto builder = SignaturePemKeysetReaderBuilder( SignaturePemKeysetReaderBuilder::PemReaderType::PUBLIC_KEY_VERIFY); builder.Add(CreatePemKey(kRsaPublicKey2048, PemKeyType::PEM_RSA, PemAlgorithm::RSASSA_PSS, /*key_size_in_bits=*/2048, HashType::SHA384)); builder.Add(CreatePemKey(kRsaPublicKey2048, PemKeyType::PEM_RSA, PemAlgorithm::RSASSA_PSS, /*key_size_in_bits=*/2048, HashType::SHA256)); auto keyset_reader_or = builder.Build(); ASSERT_THAT(keyset_reader_or, IsOk()); std::unique_ptr keyset_reader = std::move(keyset_reader_or).value(); auto keyset_or = keyset_reader->Read(); ASSERT_THAT(keyset_or, IsOk()); std::unique_ptr keyset = std::move(keyset_or).value(); // Key manager to validate key type and key material type. RsaSsaPssVerifyKeyManager verify_key_manager; EXPECT_THAT(keyset->key(), SizeIs(2)); EXPECT_EQ(keyset->primary_key_id(), keyset->key(0).key_id()); EXPECT_THAT(keyset->key(0).key_id(), Not(Eq(keyset->key(1).key_id()))); // Build the expectedi primary key. Keyset::Key expected_key1; // ID is randomly generated, so we simply copy the primary key ID. expected_key1.set_key_id(keyset->primary_key_id()); expected_key1.set_status(KeyStatusType::ENABLED); expected_key1.set_output_prefix_type(OutputPrefixType::RAW); // Populate the expected primary key KeyData. KeyData* expected_keydata1 = expected_key1.mutable_key_data(); expected_keydata1->set_type_url(verify_key_manager.get_key_type()); expected_keydata1->set_key_material_type( verify_key_manager.key_material_type()); util::StatusOr rsa_ssa_pss_pub_key = GetRsaSsaPssPublicKeyProto(kRsaPublicKey2048, HashType::SHA384, verify_key_manager.get_version()); ASSERT_THAT(rsa_ssa_pss_pub_key, IsOk()); expected_keydata1->set_value(rsa_ssa_pss_pub_key->SerializeAsString()); EXPECT_THAT(keyset->key(0), EqualsKey(expected_key1)); // Build the expected second key. Keyset::Key expected_key2; // ID is randomly generated, so we simply copy the secondary key ID. expected_key2.set_key_id(keyset->key(1).key_id()); expected_key2.set_status(KeyStatusType::ENABLED); expected_key2.set_output_prefix_type(OutputPrefixType::RAW); // Populate the expected second key KeyData. KeyData* expected_keydata2 = expected_key2.mutable_key_data(); expected_keydata2->set_type_url(verify_key_manager.get_key_type()); expected_keydata2->set_key_material_type( verify_key_manager.key_material_type()); util::StatusOr rsa_ssa_pss_pub_key2 = GetRsaSsaPssPublicKeyProto(kRsaPublicKey2048, HashType::SHA256, verify_key_manager.get_version()); ASSERT_THAT(rsa_ssa_pss_pub_key2, IsOk()); expected_keydata2->set_value(rsa_ssa_pss_pub_key2->SerializeAsString()); EXPECT_THAT(keyset->key(1), EqualsKey(expected_key2)); } TEST(SignaturePemKeysetReaderTest, ReadRsaCorrectPrivateKey) { auto builder = SignaturePemKeysetReaderBuilder( SignaturePemKeysetReaderBuilder::PemReaderType::PUBLIC_KEY_SIGN); builder.Add(CreatePemKey(kRsaPrivateKey2048, PemKeyType::PEM_RSA, PemAlgorithm::RSASSA_PSS, /*key_size_in_bits=*/2048, HashType::SHA256)); builder.Add(CreatePemKey(kRsaPrivateKey2048, PemKeyType::PEM_RSA, PemAlgorithm::RSASSA_PSS, /*key_size_in_bits=*/2048, HashType::SHA384)); auto keyset_reader_or = builder.Build(); ASSERT_THAT(keyset_reader_or, IsOk()); std::unique_ptr keyset_reader = std::move(keyset_reader_or).value(); auto keyset_or = keyset_reader->Read(); ASSERT_THAT(keyset_or, IsOk()); std::unique_ptr keyset = std::move(keyset_or).value(); EXPECT_THAT(keyset->key(), SizeIs(2)); EXPECT_EQ(keyset->primary_key_id(), keyset->key(0).key_id()); EXPECT_THAT(keyset->key(0).key_id(), Not(Eq(keyset->key(1).key_id()))); // Key manager to validate key type and key material type. RsaSsaPssSignKeyManager sign_key_manager; // Build the expected primary key. Keyset::Key expected_key1; // ID is randomly generated, so we simply copy the primary key ID. expected_key1.set_key_id(keyset->primary_key_id()); expected_key1.set_status(KeyStatusType::ENABLED); expected_key1.set_output_prefix_type(OutputPrefixType::RAW); // Populate the expected primary key KeyData. KeyData* expected_keydata1 = expected_key1.mutable_key_data(); expected_keydata1->set_type_url(sign_key_manager.get_key_type()); expected_keydata1->set_key_material_type( sign_key_manager.key_material_type()); util::StatusOr rsa_pss_private_key1 = GetRsaSsaPssPrivateKeyProto(kRsaPrivateKey2048, HashType::SHA256, sign_key_manager.get_version()); ASSERT_THAT(rsa_pss_private_key1, IsOk()); expected_keydata1->set_value(rsa_pss_private_key1->SerializeAsString()); EXPECT_THAT(keyset->key(0), EqualsKey(expected_key1)); // Build the expected second key. Keyset::Key expected_key2; // ID is randomly generated, so we simply copy the one from the second key. expected_key2.set_key_id(keyset->key(1).key_id()); expected_key2.set_status(KeyStatusType::ENABLED); expected_key2.set_output_prefix_type(OutputPrefixType::RAW); // Populate the expected second key KeyData. KeyData* expected_keydata2 = expected_key2.mutable_key_data(); expected_keydata2->set_type_url(sign_key_manager.get_key_type()); expected_keydata2->set_key_material_type( sign_key_manager.key_material_type()); util::StatusOr rsa_pss_private_key2 = GetRsaSsaPssPrivateKeyProto(kRsaPrivateKey2048, HashType::SHA384, sign_key_manager.get_version()); ASSERT_THAT(rsa_pss_private_key2, IsOk()); expected_keydata2->set_value(rsa_pss_private_key2->SerializeAsString()); EXPECT_THAT(keyset->key(1), EqualsKey(expected_key2)); } // Expects an INVLID_ARGUMENT when passing a public key to a // PublicKeySignPemKeysetReader. TEST(SignaturePemKeysetReaderTest, ReadRsaPrivateKeyKeyTypeMismatch) { auto builder = SignaturePemKeysetReaderBuilder( SignaturePemKeysetReaderBuilder::PemReaderType::PUBLIC_KEY_SIGN); builder.Add(CreatePemKey(kRsaPublicKey2048, PemKeyType::PEM_RSA, PemAlgorithm::RSASSA_PSS, /*key_size_in_bits=*/2048, HashType::SHA384)); auto keyset_reader_or = builder.Build(); ASSERT_THAT(keyset_reader_or, IsOk()); std::unique_ptr keyset_reader = std::move(keyset_reader_or).value(); EXPECT_THAT(keyset_reader->Read().status(), StatusIs(absl::StatusCode::kInvalidArgument)); } // Expects an INVLID_ARGUMENT when passing a private key to a // PublicKeyVerifyPemKeysetReader. TEST(SignaturePemKeysetReaderTest, ReadRsaPublicKeyKeyTypeMismatch) { auto builder = SignaturePemKeysetReaderBuilder( SignaturePemKeysetReaderBuilder::PemReaderType::PUBLIC_KEY_VERIFY); builder.Add(CreatePemKey(kRsaPrivateKey2048, PemKeyType::PEM_RSA, PemAlgorithm::RSASSA_PSS, /*key_size_in_bits=*/2048, HashType::SHA256)); auto keyset_reader_or = builder.Build(); ASSERT_THAT(keyset_reader_or, IsOk()); std::unique_ptr keyset_reader = std::move(keyset_reader_or).value(); EXPECT_THAT(keyset_reader->Read().status(), StatusIs(absl::StatusCode::kInvalidArgument)); } // Expects an INVALID_ARGUMENT error as the key size is too small. TEST(SignaturePemKeysetReaderTest, ReadRsaPublicKeyTooSmall) { auto builder = SignaturePemKeysetReaderBuilder( SignaturePemKeysetReaderBuilder::PemReaderType::PUBLIC_KEY_VERIFY); builder.Add(CreatePemKey(kRsaPublicKey1024, PemKeyType::PEM_RSA, PemAlgorithm::RSASSA_PSS, /*key_size_in_bits=*/1024, HashType::SHA256)); auto keyset_reader_or = builder.Build(); ASSERT_THAT(keyset_reader_or, IsOk()); std::unique_ptr keyset_reader = std::move(keyset_reader_or).value(); EXPECT_THAT(keyset_reader->Read().status(), StatusIs(absl::StatusCode::kInvalidArgument)); } // Expects an INVALID_ARGUMENT error as the key is 2048 bits, but PemKeyParams // reports 3072. TEST(SignaturePemKeysetReaderTest, ReadRsaPublicKeySizeMismatch) { auto builder = SignaturePemKeysetReaderBuilder( SignaturePemKeysetReaderBuilder::PemReaderType::PUBLIC_KEY_VERIFY); builder.Add(CreatePemKey(kRsaPublicKey2048, PemKeyType::PEM_RSA, PemAlgorithm::RSASSA_PSS, /*key_size_in_bits=*/3072, HashType::SHA256)); auto keyset_reader_or = builder.Build(); ASSERT_THAT(keyset_reader_or, IsOk()); std::unique_ptr keyset_reader = std::move(keyset_reader_or).value(); EXPECT_THAT(keyset_reader->Read().status(), StatusIs(absl::StatusCode::kInvalidArgument)); } // Expects an INVALID_ARGUMENT error as SHA1 is not allowed. TEST(SignaturePemKeysetReaderTest, ReadRsaPublicKeyInvalidHashType) { auto builder = SignaturePemKeysetReaderBuilder( SignaturePemKeysetReaderBuilder::PemReaderType::PUBLIC_KEY_VERIFY); builder.Add(CreatePemKey(kRsaPublicKey2048, PemKeyType::PEM_RSA, PemAlgorithm::RSASSA_PSS, /*key_size_in_bits=*/2048, HashType::SHA1)); auto keyset_reader_or = builder.Build(); ASSERT_THAT(keyset_reader_or, IsOk()); std::unique_ptr keyset_reader = std::move(keyset_reader_or).value(); EXPECT_THAT(keyset_reader->Read().status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(SignaturePemKeysetReaderTest, ReadECDSACorrectPublicKey) { auto builder = SignaturePemKeysetReaderBuilder( SignaturePemKeysetReaderBuilder::PemReaderType::PUBLIC_KEY_VERIFY); builder.Add(CreatePemKey(kEcdsaP256PublicKey, PemKeyType::PEM_EC, PemAlgorithm::ECDSA_IEEE, /*key_size_in_bits=*/256, HashType::SHA256)); builder.Add(CreatePemKey(kEcdsaP256PublicKey, PemKeyType::PEM_EC, PemAlgorithm::ECDSA_DER, /*key_size_in_bits=*/256, HashType::SHA256)); auto reader = builder.Build(); ASSERT_THAT(reader, IsOk()); auto keyset_read = reader->get()->Read(); ASSERT_THAT(keyset_read, IsOk()); std::unique_ptr keyset = std::move(keyset_read).value(); // Key manager to validate key type and key material type. EcdsaVerifyKeyManager key_manager; EXPECT_THAT(keyset->key(), SizeIs(2)); EXPECT_THAT(keyset->primary_key_id(), keyset->key(0).key_id()); EXPECT_THAT(keyset->key(0).key_id(), Not(Eq(keyset->key(1).key_id()))); // Build the expected primary key. Keyset::Key expected_primary; // ID is randomly generated, so we simply copy the primary key ID. expected_primary.set_key_id(keyset->primary_key_id()); expected_primary.set_status(KeyStatusType::ENABLED); expected_primary.set_output_prefix_type(OutputPrefixType::RAW); // Populate the expected primary key KeyData. KeyData* expected_primary_data = expected_primary.mutable_key_data(); expected_primary_data->set_type_url(key_manager.get_key_type()); expected_primary_data->set_key_material_type(key_manager.key_material_type()); expected_primary_data->set_value( GetExpectedEcdsaPublicKeyProto( EcdsaSignatureEncoding::IEEE_P1363).SerializeAsString()); EXPECT_THAT(keyset->key(0), EqualsKey(expected_primary)); // Build the expected secondary key. Keyset::Key expected_secondary; // ID is randomly generated, so we simply copy the primary key ID. expected_secondary.set_key_id(keyset->key(1).key_id()); expected_secondary.set_status(KeyStatusType::ENABLED); expected_secondary.set_output_prefix_type(OutputPrefixType::RAW); // Populate the expected secondary key KeyData. KeyData* expected_secondary_data = expected_secondary.mutable_key_data(); expected_secondary_data->set_type_url(key_manager.get_key_type()); expected_secondary_data->set_key_material_type( key_manager.key_material_type()); expected_secondary_data->set_value( GetExpectedEcdsaPublicKeyProto( EcdsaSignatureEncoding::DER).SerializeAsString()); EXPECT_THAT(keyset->key(1), EqualsKey(expected_secondary)); } TEST(SignaturePemKeysetReaderTest, ReadECDSAWrongHashType) { auto builder = SignaturePemKeysetReaderBuilder( SignaturePemKeysetReaderBuilder::PemReaderType::PUBLIC_KEY_VERIFY); builder.Add(CreatePemKey(kEcdsaP256PublicKey, PemKeyType::PEM_EC, PemAlgorithm::ECDSA_IEEE, /*key_size_in_bits=*/256, HashType::SHA512)); auto reader = builder.Build(); ASSERT_THAT(reader, IsOk()); auto keyset_read = reader->get()->Read(); ASSERT_THAT(keyset_read.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(SignaturePemKeysetReaderTest, ReadECDSAWrongKeySize) { auto builder = SignaturePemKeysetReaderBuilder( SignaturePemKeysetReaderBuilder::PemReaderType::PUBLIC_KEY_VERIFY); builder.Add(CreatePemKey(kEcdsaP256PublicKey, PemKeyType::PEM_EC, PemAlgorithm::ECDSA_IEEE, /*key_size_in_bits=*/512, HashType::SHA256)); auto reader = builder.Build(); ASSERT_THAT(reader, IsOk()); auto keyset_read = reader->get()->Read(); ASSERT_THAT(keyset_read.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(SignaturePemKeysetReaderTest, ReadECDSAWrongAlgorithm) { auto builder = SignaturePemKeysetReaderBuilder( SignaturePemKeysetReaderBuilder::PemReaderType::PUBLIC_KEY_VERIFY); builder.Add(CreatePemKey(kEcdsaP256PublicKey, PemKeyType::PEM_EC, PemAlgorithm::RSASSA_PSS, /*key_size_in_bits=*/256, HashType::SHA256)); auto reader = builder.Build(); ASSERT_THAT(reader, IsOk()); auto keyset_read = reader->get()->Read(); ASSERT_THAT(keyset_read.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(SignaturePemKeysetReaderTest, ReadEd25519ShouldFail) { auto builder = SignaturePemKeysetReaderBuilder( SignaturePemKeysetReaderBuilder::PemReaderType::PUBLIC_KEY_VERIFY); builder.Add(CreatePemKey(kEd25519PublicKey, PemKeyType::PEM_EC, PemAlgorithm::ECDSA_IEEE, /*key_size_in_bits=*/256, HashType::SHA256)); auto reader = builder.Build(); ASSERT_THAT(reader, IsOk()); auto keyset_read = reader->get()->Read(); ASSERT_THAT(keyset_read.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(SignaturePemKeysetReaderTest, ReadSecp256k1ShouldFail) { auto builder = SignaturePemKeysetReaderBuilder( SignaturePemKeysetReaderBuilder::PemReaderType::PUBLIC_KEY_VERIFY); builder.Add(CreatePemKey(kSecp256k1PublicKey, PemKeyType::PEM_EC, PemAlgorithm::ECDSA_IEEE, /*key_size_in_bits=*/256, HashType::SHA256)); auto reader = builder.Build(); ASSERT_THAT(reader, IsOk()); auto keyset_read = reader->get()->Read(); // With BoringSSL parsing of the PEM key fails when an unsupported curve is // used [1]; Supported curves are defined here [2]. Tink doesn't distinguish // between an error caused by a malformed PEM and an unsupported group by // BoringSSL. On the other hand, with OpenSSL parsing succeeds, but this // curve is unsupported by Tink. As a consequence, this fails with two // different errors. // // [1]https://github.com/google/boringssl/blob/master/crypto/ec_extra/ec_asn1.c#L324 // [2]https://github.com/google/boringssl/blob/master/crypto/fipsmodule/ec/ec.c#L218 if (internal::IsBoringSsl()) { EXPECT_THAT(keyset_read.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } else { EXPECT_THAT(keyset_read.status(), StatusIs(absl::StatusCode::kUnimplemented)); } } TEST(SignaturePemKeysetReaderTest, ReadEcdsaP384ShouldFail) { auto builder = SignaturePemKeysetReaderBuilder( SignaturePemKeysetReaderBuilder::PemReaderType::PUBLIC_KEY_VERIFY); builder.Add(CreatePemKey(kEcdsaP384PublicKey, PemKeyType::PEM_EC, PemAlgorithm::ECDSA_IEEE, /*key_size_in_bits=*/384, HashType::SHA384)); auto reader = builder.Build(); ASSERT_THAT(reader, IsOk()); auto keyset_read = reader->get()->Read(); ASSERT_THAT(keyset_read.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/signature/signature_private_key.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_SIGNATURE_PRIVATE_KEY_H_ #define TINK_SIGNATURE_SIGNATURE_PRIVATE_KEY_H_ #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tink/key.h" #include "tink/private_key.h" #include "tink/signature/signature_parameters.h" #include "tink/signature/signature_public_key.h" namespace crypto { namespace tink { // Represents a function to compute digital signatures. class SignaturePrivateKey : public PrivateKey { public: const SignaturePublicKey& GetPublicKey() const override = 0; // Returns the bytes prefixed to every signature generated by this key. // // In order to make key rotation more efficient, Tink allows every signature // private key to have an associated signature output prefix. When verifying a // digital signature, only keys with a matching prefix have to be tried. // // See https://developers.google.com/tink/wire-format#tink_output_prefix for // more background information on Tink output prefixes. absl::string_view GetOutputPrefix() const { return GetPublicKey().GetOutputPrefix(); } absl::optional GetIdRequirement() const override { return GetPublicKey().GetIdRequirement(); } const SignatureParameters& GetParameters() const override { return GetPublicKey().GetParameters(); } bool operator==(const Key& other) const override = 0; }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_SIGNATURE_PRIVATE_KEY_H_ ================================================ FILE: cc/signature/signature_public_key.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_SIGNATURE_PUBLIC_KEY_H_ #define TINK_SIGNATURE_SIGNATURE_PUBLIC_KEY_H_ #include "absl/strings/string_view.h" #include "tink/key.h" #include "tink/signature/signature_parameters.h" namespace crypto { namespace tink { // Represents a function to verify digital signatures. class SignaturePublicKey : public Key { public: // Returns the bytes prefixed to every signature generated by the // corresponding private key. // // In order to make key rotation more efficient, Tink allows every signature // public key to have an associated signature output prefix. When verifying a // digital signature, only keys with a matching prefix have to be tried. // // See https://developers.google.com/tink/wire-format#tink_output_prefix for // more background information on Tink output prefixes. virtual absl::string_view GetOutputPrefix() const = 0; const SignatureParameters& GetParameters() const override = 0; bool operator==(const Key& other) const override = 0; }; } // namespace tink } // namespace crypto #endif // TINK_SIGNATURE_SIGNATURE_PUBLIC_KEY_H_ ================================================ FILE: cc/signature/subtle/BUILD.bazel ================================================ licenses(["notice"]) ================================================ FILE: cc/signature/subtle/CMakeLists.txt ================================================ ================================================ FILE: cc/signature_config.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_CONFIG_H_ #define TINK_SIGNATURE_CONFIG_H_ #include "tink/signature/signature_config.h" // IWYU pragma: export #endif // TINK_SIGNATURE_CONFIG_H_ ================================================ FILE: cc/signature_key_templates.h ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SIGNATURE_KEY_TEMPLATES_H_ #define TINK_SIGNATURE_KEY_TEMPLATES_H_ #include "tink/signature/signature_key_templates.h" // IWYU pragma: export #endif // TINK_SIGNATURE_KEY_TEMPLATES_H_ ================================================ FILE: cc/streaming_aead.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_STREAMING_AEAD_H_ #define TINK_STREAMING_AEAD_H_ #include #include "absl/strings/string_view.h" #include "tink/input_stream.h" #include "tink/output_stream.h" #include "tink/random_access_stream.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // An interface for streaming authenticated encryption with associated data. // Streaming encryption is typically used for encrypting large plaintexts such // as large files. Tink may eventually contain multiple interfaces for // streaming encryption depending on the supported properties. This interface // supports a streaming interface for symmetric encryption with // authentication. The underlying encryption modes are selected so that partial // plaintext can be obtained fast by decrypting and authenticating just a part // of the ciphertext. class StreamingAead { public: // Returns a wrapper around 'ciphertext_destination', such that any bytes // written via the wrapper are AEAD-encrypted using 'associated_data' as // associated authenticated data. The associated data is not included in the // ciphertext and has to be passed in as parameter for decryption. // ByteCount() of the wrapper returns the number of written plaintext bytes. // Closing the wrapper results in closing of the wrapped stream. virtual crypto::tink::util::StatusOr< std::unique_ptr> NewEncryptingStream( std::unique_ptr ciphertext_destination, absl::string_view associated_data) const = 0; // Returns a wrapper around 'ciphertext_source', such that reading // via the wrapper leads to AEAD-decryption of the underlying ciphertext, // using 'associated_data' as associated authenticated data, and the // read bytes are bytes of the resulting plaintext. // ByteCount() of the wrapper returns the number of read plaintext bytes. virtual crypto::tink::util::StatusOr< std::unique_ptr> NewDecryptingStream( std::unique_ptr ciphertext_source, absl::string_view associated_data) const = 0; // Returns a wrapper around 'ciphertext_source', such that reading // via the wrapper leads to AEAD-decryption of the underlying ciphertext, // using 'associated_data' as associated authenticated data, and the // read bytes are bytes of the resulting plaintext. // Note that the returned wrapper's size()-method reports size that is // not checked for integrity. For example, if the ciphertext file has been // truncated then size() will return a wrong result. Reading the last block // of the plaintext will verify whether size() is correct. // Reading through the wrapper is thread safe. virtual crypto::tink::util::StatusOr< std::unique_ptr> NewDecryptingRandomAccessStream( std::unique_ptr ciphertext_source, absl::string_view associated_data) const = 0; virtual ~StreamingAead() = default; }; } // namespace tink } // namespace crypto #endif // TINK_STREAMING_AEAD_H_ ================================================ FILE: cc/streaming_aead_config.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_STREAMING_AEAD_CONFIG_H_ #define TINK_STREAMING_AEAD_CONFIG_H_ // IWYU pragma: begin_exports #include "tink/streamingaead/streaming_aead_config.h" // IWYU pragma: end_exports #endif // TINK_STREAMING_AEAD_CONFIG_H_ ================================================ FILE: cc/streaming_aead_key_templates.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_STREAMING_AEAD_KEY_TEMPLATES_H_ #define TINK_STREAMING_AEAD_KEY_TEMPLATES_H_ // IWYU pragma: begin_exports #include "tink/streamingaead/streaming_aead_key_templates.h" // IWYU pragma: end_exports #endif // TINK_STREAMING_AEAD_KEY_TEMPLATES_H_ ================================================ FILE: cc/streaming_mac.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_STREAMING_MAC_H_ #define TINK_STREAMING_MAC_H_ #include #include #include "absl/strings/string_view.h" #include "tink/output_stream_with_result.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Interface for Streaming MACs (Message Authentication Codes). // This interface should be used for authentication only, and not for other // purposes (e.g., it should not be used to generate pseudorandom bytes). class StreamingMac { public: // Returns an ComputeMacOutputStream, which when closed will return the // message authentication code (MAC) of the data put into the stream. virtual util::StatusOr>> NewComputeMacOutputStream() const = 0; // Returns an VerifyMacOutputStream which verifies if 'mac' is a correct // message authentication code (MAC) for the data written to it. virtual util::StatusOr>> NewVerifyMacOutputStream(const std::string& mac_value) const = 0; virtual ~StreamingMac() = default; }; } // namespace tink } // namespace crypto #endif // TINK_STREAMING_MAC_H_ ================================================ FILE: cc/streamingaead/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "streaming_aead_wrapper", srcs = ["streaming_aead_wrapper.cc"], hdrs = ["streaming_aead_wrapper.h"], include_prefix = "tink/streamingaead", deps = [ ":decrypting_input_stream", ":decrypting_random_access_stream", "//:crypto_format", "//:input_stream", "//:output_stream", "//:primitive_set", "//:primitive_wrapper", "//:random_access_stream", "//:streaming_aead", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "streaming_aead_config", srcs = ["streaming_aead_config.cc"], hdrs = ["streaming_aead_config.h"], include_prefix = "tink/streamingaead", visibility = ["//visibility:public"], deps = [ ":aes_ctr_hmac_streaming_key_manager", ":aes_gcm_hkdf_streaming_key_manager", ":streaming_aead_wrapper", "//:registry", "//config:config_util", "//config:tink_fips", "//proto:config_cc_proto", "//util:status", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/memory", ], ) cc_library( name = "streaming_aead_key_templates", srcs = ["streaming_aead_key_templates.cc"], hdrs = ["streaming_aead_key_templates.h"], include_prefix = "tink/streamingaead", visibility = ["//visibility:public"], deps = [ "//proto:aes_ctr_hmac_streaming_cc_proto", "//proto:aes_gcm_hkdf_streaming_cc_proto", "//proto:common_cc_proto", "//proto:hmac_cc_proto", "//proto:tink_cc_proto", ], ) cc_library( name = "aes_gcm_hkdf_streaming_key_manager", srcs = ["aes_gcm_hkdf_streaming_key_manager.cc"], hdrs = ["aes_gcm_hkdf_streaming_key_manager.h"], include_prefix = "tink/streamingaead", deps = [ "//:core/key_type_manager", "//:core/template_util", "//:input_stream", "//:key_manager", "//:streaming_aead", "//proto:aes_gcm_hkdf_streaming_cc_proto", "//proto:common_cc_proto", "//proto:tink_cc_proto", "//subtle:aes_gcm_hkdf_stream_segment_encrypter", "//subtle:aes_gcm_hkdf_streaming", "//subtle:random", "//util:constants", "//util:enums", "//util:errors", "//util:input_stream_util", "//util:protobuf_helper", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "aes_ctr_hmac_streaming_key_manager", srcs = ["aes_ctr_hmac_streaming_key_manager.cc"], hdrs = ["aes_ctr_hmac_streaming_key_manager.h"], include_prefix = "tink/streamingaead", deps = [ "//:core/key_type_manager", "//:core/template_util", "//:input_stream", "//:streaming_aead", "//proto:aes_ctr_hmac_streaming_cc_proto", "//proto:common_cc_proto", "//proto:hmac_cc_proto", "//proto:tink_cc_proto", "//subtle:aes_ctr_hmac_streaming", "//subtle:random", "//util:constants", "//util:enums", "//util:errors", "//util:input_stream_util", "//util:protobuf_helper", "//util:secret_data", "//util:status", "//util:statusor", "//util:validation", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "buffered_input_stream", srcs = ["buffered_input_stream.cc"], hdrs = ["buffered_input_stream.h"], include_prefix = "tink/streamingaead", deps = [ "//:input_stream", "//util:errors", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", ], ) cc_library( name = "shared_input_stream", srcs = ["shared_input_stream.h"], hdrs = ["shared_input_stream.h"], include_prefix = "tink/streamingaead", deps = [ "//:input_stream", "//util:statusor", ], ) cc_library( name = "shared_random_access_stream", srcs = ["shared_random_access_stream.h"], hdrs = ["shared_random_access_stream.h"], include_prefix = "tink/streamingaead", deps = [ "//:random_access_stream", "//util:buffer", "//util:status", "//util:statusor", ], ) cc_library( name = "decrypting_input_stream", srcs = ["decrypting_input_stream.cc"], hdrs = ["decrypting_input_stream.h"], include_prefix = "tink/streamingaead", deps = [ ":buffered_input_stream", ":shared_input_stream", "//:input_stream", "//:primitive_set", "//:streaming_aead", "//util:errors", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "decrypting_random_access_stream", srcs = ["decrypting_random_access_stream.cc"], hdrs = ["decrypting_random_access_stream.h"], include_prefix = "tink/streamingaead", deps = [ ":shared_random_access_stream", "//:primitive_set", "//:random_access_stream", "//:streaming_aead", "//util:buffer", "//util:errors", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/synchronization", ], ) cc_library( name = "config_v0", srcs = ["config_v0.cc"], hdrs = ["config_v0.h"], include_prefix = "tink/streamingaead", deps = [ "//:configuration", "//streamingaead/internal:config_v0", "@com_google_absl//absl/log:check", ], ) cc_library( name = "key_gen_config_v0", srcs = ["key_gen_config_v0.cc"], hdrs = ["key_gen_config_v0.h"], include_prefix = "tink/streamingaead", deps = [ "//:key_gen_configuration", "//streamingaead/internal:key_gen_config_v0", "@com_google_absl//absl/log:check", ], ) # tests cc_test( name = "streaming_aead_wrapper_test", size = "small", srcs = ["streaming_aead_wrapper_test.cc"], deps = [ ":aes_gcm_hkdf_streaming_key_manager", ":streaming_aead_config", ":streaming_aead_wrapper", "//:input_stream", "//:insecure_secret_key_access", "//:keyset_handle", "//:output_stream", "//:primitive_set", "//:proto_keyset_format", "//:random_access_stream", "//:streaming_aead", "//config:global_registry", "//internal:test_random_access_stream", "//proto:aes_gcm_hkdf_streaming_cc_proto", "//proto:common_cc_proto", "//proto:tink_cc_proto", "//subtle:random", "//subtle:streaming_aead_test_util", "//subtle:test_util", "//util:buffer", "//util:istream_input_stream", "//util:ostream_output_stream", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_gcm_hkdf_streaming_key_manager_test", size = "small", srcs = ["aes_gcm_hkdf_streaming_key_manager_test.cc"], deps = [ ":aes_gcm_hkdf_streaming_key_manager", "//:streaming_aead", "//proto:aes_eax_cc_proto", "//proto:aes_gcm_hkdf_streaming_cc_proto", "//proto:common_cc_proto", "//proto:tink_cc_proto", "//subtle:aes_gcm_hkdf_streaming", "//subtle:common_enums", "//subtle:random", "//subtle:streaming_aead_test_util", "//subtle:test_util", "//util:istream_input_stream", "//util:ostream_output_stream", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_ctr_hmac_streaming_key_manager_test", size = "small", srcs = ["aes_ctr_hmac_streaming_key_manager_test.cc"], deps = [ ":aes_ctr_hmac_streaming_key_manager", "//:streaming_aead", "//proto:aes_ctr_hmac_streaming_cc_proto", "//proto:aes_eax_cc_proto", "//proto:common_cc_proto", "//proto:tink_cc_proto", "//subtle:aes_ctr_hmac_streaming", "//subtle:common_enums", "//subtle:random", "//subtle:streaming_aead_test_util", "//subtle:test_util", "//util:istream_input_stream", "//util:ostream_output_stream", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "streaming_aead_key_templates_test", size = "small", srcs = ["streaming_aead_key_templates_test.cc"], deps = [ ":aes_ctr_hmac_streaming_key_manager", ":aes_gcm_hkdf_streaming_key_manager", ":streaming_aead_key_templates", "//proto:aes_ctr_hmac_streaming_cc_proto", "//proto:aes_gcm_hkdf_streaming_cc_proto", "//proto:common_cc_proto", "//proto:tink_cc_proto", "//util:test_matchers", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "streaming_aead_config_test", size = "small", srcs = ["streaming_aead_config_test.cc"], tags = ["fips"], deps = [ ":aes_ctr_hmac_streaming_key_manager", ":aes_gcm_hkdf_streaming_key_manager", ":streaming_aead_config", ":streaming_aead_key_templates", "//:keyset_handle", "//:primitive_set", "//:registry", "//:streaming_aead", "//config:global_registry", "//config:tink_fips", "//proto:tink_cc_proto", "//util:status", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "buffered_input_stream_test", size = "small", srcs = ["buffered_input_stream_test.cc"], deps = [ ":buffered_input_stream", "//:input_stream", "//subtle:random", "//subtle:test_util", "//util:istream_input_stream", "//util:status", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "decrypting_input_stream_test", size = "small", srcs = ["decrypting_input_stream_test.cc"], deps = [ ":decrypting_input_stream", "//:input_stream", "//:output_stream", "//:primitive_set", "//:streaming_aead", "//proto:tink_cc_proto", "//subtle:random", "//subtle:test_util", "//util:istream_input_stream", "//util:ostream_output_stream", "//util:status", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "decrypting_random_access_stream_test", size = "small", srcs = ["decrypting_random_access_stream_test.cc"], deps = [ ":decrypting_random_access_stream", "//:output_stream", "//:primitive_set", "//:random_access_stream", "//:streaming_aead", "//internal:test_random_access_stream", "//proto:tink_cc_proto", "//subtle:random", "//subtle:test_util", "//util:buffer", "//util:ostream_output_stream", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "shared_input_stream_test", size = "small", srcs = ["shared_input_stream_test.cc"], deps = [ ":buffered_input_stream", ":shared_input_stream", "//:input_stream", "//subtle:random", "//subtle:test_util", "//util:istream_input_stream", "//util:status", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "shared_random_access_stream_test", size = "small", srcs = ["shared_random_access_stream_test.cc"], deps = [ ":shared_random_access_stream", "//:random_access_stream", "//internal:test_random_access_stream", "//subtle:random", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "config_v0_test", srcs = ["config_v0_test.cc"], deps = [ ":config_v0", ":key_gen_config_v0", ":streaming_aead_key_templates", "//:input_stream", "//:keyset_handle", "//:output_stream", "//:streaming_aead", "//proto:tink_cc_proto", "//subtle:test_util", "//util:istream_input_stream", "//util:ostream_output_stream", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/streamingaead/CMakeLists.txt ================================================ tink_module(streamingaead) add_subdirectory(internal) tink_cc_library( NAME streaming_aead_wrapper SRCS streaming_aead_wrapper.cc streaming_aead_wrapper.h DEPS tink::streamingaead::decrypting_input_stream tink::streamingaead::decrypting_random_access_stream absl::memory absl::status absl::strings tink::core::crypto_format tink::core::input_stream tink::core::output_stream tink::core::primitive_set tink::core::primitive_wrapper tink::core::random_access_stream tink::core::streaming_aead tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME streaming_aead_config SRCS streaming_aead_config.cc streaming_aead_config.h DEPS tink::streamingaead::aes_ctr_hmac_streaming_key_manager tink::streamingaead::aes_gcm_hkdf_streaming_key_manager tink::streamingaead::streaming_aead_wrapper absl::core_headers absl::memory tink::core::registry tink::config::config_util tink::config::tink_fips tink::util::status tink::proto::config_cc_proto ) tink_cc_library( NAME streaming_aead_key_templates SRCS streaming_aead_key_templates.cc streaming_aead_key_templates.h DEPS tink::proto::aes_ctr_hmac_streaming_cc_proto tink::proto::aes_gcm_hkdf_streaming_cc_proto tink::proto::common_cc_proto tink::proto::hmac_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME aes_gcm_hkdf_streaming_key_manager SRCS aes_gcm_hkdf_streaming_key_manager.cc aes_gcm_hkdf_streaming_key_manager.h DEPS absl::memory absl::status absl::strings tink::core::key_type_manager tink::core::template_util tink::core::input_stream tink::core::key_manager tink::core::streaming_aead tink::subtle::aes_gcm_hkdf_stream_segment_encrypter tink::subtle::aes_gcm_hkdf_streaming tink::subtle::random tink::util::constants tink::util::enums tink::util::errors tink::util::input_stream_util tink::util::protobuf_helper tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::aes_gcm_hkdf_streaming_cc_proto tink::proto::common_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME aes_ctr_hmac_streaming_key_manager SRCS aes_ctr_hmac_streaming_key_manager.cc aes_ctr_hmac_streaming_key_manager.h DEPS absl::memory absl::status absl::strings tink::core::key_type_manager tink::core::template_util tink::core::input_stream tink::core::streaming_aead tink::subtle::aes_ctr_hmac_streaming tink::subtle::random tink::util::constants tink::util::enums tink::util::errors tink::util::input_stream_util tink::util::protobuf_helper tink::util::secret_data tink::util::status tink::util::statusor tink::util::validation tink::proto::aes_ctr_hmac_streaming_cc_proto tink::proto::common_cc_proto tink::proto::hmac_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME buffered_input_stream SRCS buffered_input_stream.cc buffered_input_stream.h DEPS absl::memory absl::status tink::core::input_stream tink::util::errors tink::util::status tink::util::statusor ) tink_cc_library( NAME shared_input_stream SRCS shared_input_stream.h shared_input_stream.h DEPS tink::core::input_stream tink::util::statusor ) tink_cc_library( NAME shared_random_access_stream SRCS shared_random_access_stream.h shared_random_access_stream.h DEPS tink::core::random_access_stream tink::util::buffer tink::util::status tink::util::statusor ) tink_cc_library( NAME decrypting_input_stream SRCS decrypting_input_stream.cc decrypting_input_stream.h DEPS tink::streamingaead::buffered_input_stream tink::streamingaead::shared_input_stream absl::memory absl::status absl::string_view tink::core::input_stream tink::core::primitive_set tink::core::streaming_aead tink::util::errors tink::util::status tink::util::statusor ) tink_cc_library( NAME decrypting_random_access_stream SRCS decrypting_random_access_stream.cc decrypting_random_access_stream.h DEPS tink::streamingaead::shared_random_access_stream absl::core_headers absl::memory absl::status absl::string_view absl::synchronization tink::core::primitive_set tink::core::random_access_stream tink::core::streaming_aead tink::util::buffer tink::util::errors tink::util::status tink::util::statusor ) tink_cc_library( NAME config_v0 SRCS config_v0.cc config_v0.h DEPS absl::check tink::core::configuration tink::streamingaead::internal::config_v0 ) tink_cc_library( NAME key_gen_config_v0 SRCS key_gen_config_v0.cc key_gen_config_v0.h DEPS absl::check tink::core::key_gen_configuration tink::streamingaead::internal::key_gen_config_v0 ) # tests tink_cc_test( NAME streaming_aead_wrapper_test SRCS streaming_aead_wrapper_test.cc DEPS tink::streamingaead::aes_gcm_hkdf_streaming_key_manager tink::streamingaead::streaming_aead_config tink::streamingaead::streaming_aead_wrapper gmock absl::memory absl::status absl::strings tink::core::input_stream tink::core::insecure_secret_key_access tink::core::keyset_handle tink::core::output_stream tink::core::primitive_set tink::core::proto_keyset_format tink::core::random_access_stream tink::core::streaming_aead tink::config::global_registry tink::internal::test_random_access_stream tink::subtle::random tink::subtle::streaming_aead_test_util tink::subtle::test_util tink::util::buffer tink::util::istream_input_stream tink::util::ostream_output_stream tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::aes_gcm_hkdf_streaming_cc_proto tink::proto::common_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME aes_gcm_hkdf_streaming_key_manager_test SRCS aes_gcm_hkdf_streaming_key_manager_test.cc DEPS tink::streamingaead::aes_gcm_hkdf_streaming_key_manager gmock absl::memory absl::status absl::strings tink::core::streaming_aead tink::subtle::aes_gcm_hkdf_streaming tink::subtle::common_enums tink::subtle::random tink::subtle::streaming_aead_test_util tink::subtle::test_util tink::util::istream_input_stream tink::util::ostream_output_stream tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::aes_eax_cc_proto tink::proto::aes_gcm_hkdf_streaming_cc_proto tink::proto::common_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME aes_ctr_hmac_streaming_key_manager_test SRCS aes_ctr_hmac_streaming_key_manager_test.cc DEPS tink::streamingaead::aes_ctr_hmac_streaming_key_manager gmock absl::memory absl::status absl::strings tink::core::streaming_aead tink::subtle::aes_ctr_hmac_streaming tink::subtle::common_enums tink::subtle::random tink::subtle::streaming_aead_test_util tink::subtle::test_util tink::util::istream_input_stream tink::util::ostream_output_stream tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::proto::aes_ctr_hmac_streaming_cc_proto tink::proto::aes_eax_cc_proto tink::proto::common_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME streaming_aead_key_templates_test SRCS streaming_aead_key_templates_test.cc DEPS tink::streamingaead::aes_ctr_hmac_streaming_key_manager tink::streamingaead::aes_gcm_hkdf_streaming_key_manager tink::streamingaead::streaming_aead_key_templates gmock tink::util::test_matchers tink::proto::aes_ctr_hmac_streaming_cc_proto tink::proto::aes_gcm_hkdf_streaming_cc_proto tink::proto::common_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME streaming_aead_config_test SRCS streaming_aead_config_test.cc DEPS tink::streamingaead::aes_ctr_hmac_streaming_key_manager tink::streamingaead::aes_gcm_hkdf_streaming_key_manager tink::streamingaead::streaming_aead_config tink::streamingaead::streaming_aead_key_templates gmock absl::memory absl::status tink::core::keyset_handle tink::core::primitive_set tink::core::registry tink::core::streaming_aead tink::config::global_registry tink::config::tink_fips tink::util::status tink::util::test_matchers tink::util::test_util tink::proto::tink_cc_proto ) tink_cc_test( NAME buffered_input_stream_test SRCS buffered_input_stream_test.cc DEPS tink::streamingaead::buffered_input_stream gmock absl::memory absl::status absl::strings tink::core::input_stream tink::subtle::random tink::subtle::test_util tink::util::istream_input_stream tink::util::status tink::util::test_matchers ) tink_cc_test( NAME decrypting_input_stream_test SRCS decrypting_input_stream_test.cc DEPS tink::streamingaead::decrypting_input_stream gmock absl::memory absl::status absl::strings tink::core::input_stream tink::core::output_stream tink::core::primitive_set tink::core::streaming_aead tink::subtle::random tink::subtle::test_util tink::util::istream_input_stream tink::util::ostream_output_stream tink::util::status tink::util::test_matchers tink::util::test_util tink::proto::tink_cc_proto ) tink_cc_test( NAME decrypting_random_access_stream_test SRCS decrypting_random_access_stream_test.cc DEPS tink::streamingaead::decrypting_random_access_stream gmock absl::memory absl::status absl::strings tink::core::output_stream tink::core::primitive_set tink::core::random_access_stream tink::core::streaming_aead tink::internal::test_random_access_stream tink::subtle::random tink::subtle::test_util tink::util::buffer tink::util::ostream_output_stream tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util tink::proto::tink_cc_proto ) tink_cc_test( NAME shared_input_stream_test SRCS shared_input_stream_test.cc DEPS tink::streamingaead::buffered_input_stream tink::streamingaead::shared_input_stream gmock absl::memory absl::status absl::strings tink::core::input_stream tink::subtle::random tink::subtle::test_util tink::util::istream_input_stream tink::util::status tink::util::test_matchers ) tink_cc_test( NAME shared_random_access_stream_test SRCS shared_random_access_stream_test.cc DEPS tink::streamingaead::shared_random_access_stream gmock absl::memory absl::status absl::strings tink::core::random_access_stream tink::internal::test_random_access_stream tink::subtle::random ) tink_cc_test( NAME config_v0_test SRCS config_v0_test.cc DEPS tink::streamingaead::config_v0 tink::streamingaead::key_gen_config_v0 tink::streamingaead::streaming_aead_key_templates gmock absl::memory tink::core::input_stream tink::core::keyset_handle tink::core::output_stream tink::core::streaming_aead tink::subtle::test_util tink::util::istream_input_stream tink::util::ostream_output_stream tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) ================================================ FILE: cc/streamingaead/aes_ctr_hmac_streaming_key_manager.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/aes_ctr_hmac_streaming_key_manager.h" #include #include "absl/status/status.h" #include "tink/input_stream.h" #include "tink/subtle/aes_ctr_hmac_streaming.h" #include "tink/subtle/random.h" #include "tink/util/input_stream_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/common.pb.h" namespace crypto { namespace tink { using ::crypto::tink::subtle::AesCtrHmacStreaming; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::AesCtrHmacStreamingKey; using ::google::crypto::tink::AesCtrHmacStreamingKeyFormat; using ::google::crypto::tink::AesCtrHmacStreamingParams; using ::google::crypto::tink::HashType; namespace { Status ValidateParams(const AesCtrHmacStreamingParams& params) { if (!(params.hkdf_hash_type() == HashType::SHA1 || params.hkdf_hash_type() == HashType::SHA256 || params.hkdf_hash_type() == HashType::SHA512)) { return Status(absl::StatusCode::kInvalidArgument, "unsupported hkdf_hash_type"); } if (!(params.hmac_params().hash() == HashType::SHA1 || params.hmac_params().hash() == HashType::SHA256 || params.hmac_params().hash() == HashType::SHA512)) { return Status(absl::StatusCode::kInvalidArgument, "unsupported hmac_params.hash"); } if (params.hmac_params().tag_size() < 10) { return Status(absl::StatusCode::kInvalidArgument, "hmac_params.tag_size too small"); } if ((params.hmac_params().hash() == HashType::SHA1 && params.hmac_params().tag_size() > 20) || (params.hmac_params().hash() == HashType::SHA256 && params.hmac_params().tag_size() > 32) || (params.hmac_params().hash() == HashType::SHA512 && params.hmac_params().tag_size() > 64)) { return Status(absl::StatusCode::kInvalidArgument, "hmac_params.tag_size too big"); } int header_size = 1 + params.derived_key_size() + AesCtrHmacStreaming::kNoncePrefixSizeInBytes; if (params.ciphertext_segment_size() <= header_size + params.hmac_params().tag_size()) { return Status(absl::StatusCode::kInvalidArgument, "ciphertext_segment_size too small"); } if (params.ciphertext_segment_size() > 0x7fffffff) { return Status(absl::StatusCode::kInvalidArgument, "ciphertext_segment_size too big"); } return ValidateAesKeySize(params.derived_key_size()); } } // namespace crypto::tink::util::StatusOr AesCtrHmacStreamingKeyManager::CreateKey( const google::crypto::tink::AesCtrHmacStreamingKeyFormat& key_format) const { AesCtrHmacStreamingKey key; key.set_version(get_version()); key.set_key_value(subtle::Random::GetRandomBytes(key_format.key_size())); *key.mutable_params() = key_format.params(); return key; }; crypto::tink::util::StatusOr AesCtrHmacStreamingKeyManager::DeriveKey( const google::crypto::tink::AesCtrHmacStreamingKeyFormat& key_format, InputStream* input_stream) const { crypto::tink::util::Status status = ValidateVersion(key_format.version(), get_version()); if (!status.ok()) return status; crypto::tink::util::StatusOr randomness_or = ReadBytesFromStream(key_format.key_size(), input_stream); if (!randomness_or.ok()) { return randomness_or.status(); } AesCtrHmacStreamingKey key; key.set_version(get_version()); key.set_key_value(randomness_or.value()); *key.mutable_params() = key_format.params(); return key; } Status AesCtrHmacStreamingKeyManager::ValidateKey( const AesCtrHmacStreamingKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; if (key.key_value().size() < key.params().derived_key_size()) { return Status(absl::StatusCode::kInvalidArgument, "key_value (i.e. ikm) too short"); } return ValidateParams(key.params()); } Status AesCtrHmacStreamingKeyManager::ValidateKeyFormat( const AesCtrHmacStreamingKeyFormat& key_format) const { if (key_format.key_size() < key_format.params().derived_key_size()) { return Status(absl::StatusCode::kInvalidArgument, "key_size must not be smaller than derived_key_size"); } return ValidateParams(key_format.params()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/aes_ctr_hmac_streaming_key_manager.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_STREAMINGAEAD_AES_CTR_HMAC_STREAMING_KEY_MANAGER_H_ #define TINK_STREAMINGAEAD_AES_CTR_HMAC_STREAMING_KEY_MANAGER_H_ #include #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/input_stream.h" #include "tink/streaming_aead.h" #include "tink/subtle/aes_ctr_hmac_streaming.h" #include "tink/util/constants.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/aes_ctr_hmac_streaming.pb.h" #include "proto/hmac.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class AesCtrHmacStreamingKeyManager : public KeyTypeManager> { public: class StreamingAeadFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::AesCtrHmacStreamingKey& key) const override { subtle::AesCtrHmacStreaming::Params params; params.ikm = util::SecretDataFromStringView(key.key_value()); params.hkdf_algo = crypto::tink::util::Enums::ProtoToSubtle( key.params().hkdf_hash_type()); params.key_size = key.params().derived_key_size(); params.ciphertext_segment_size = key.params().ciphertext_segment_size(); params.ciphertext_offset = 0; params.tag_algo = crypto::tink::util::Enums::ProtoToSubtle( key.params().hmac_params().hash()); params.tag_size = key.params().hmac_params().tag_size(); auto streaming_result = crypto::tink::subtle::AesCtrHmacStreaming::New(params); if (!streaming_result.ok()) return streaming_result.status(); return {std::move(streaming_result.value())}; } }; AesCtrHmacStreamingKeyManager() : KeyTypeManager( absl::make_unique()) {} // Returns the version of this key manager. uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::SYMMETRIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::AesCtrHmacStreamingKey& key) const override; crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::AesCtrHmacStreamingKeyFormat& key_format) const override; crypto::tink::util::StatusOr CreateKey(const google::crypto::tink::AesCtrHmacStreamingKeyFormat& key_format) const override; crypto::tink::util::StatusOr DeriveKey( const google::crypto::tink::AesCtrHmacStreamingKeyFormat& key_format, InputStream* input_stream) const override; ~AesCtrHmacStreamingKeyManager() override = default; private: const std::string key_type_ = absl::StrCat( kTypeGoogleapisCom, google::crypto::tink::AesCtrHmacStreamingKey().GetTypeName()); }; } // namespace tink } // namespace crypto #endif // TINK_STREAMINGAEAD_AES_CTR_HMAC_STREAMING_KEY_MANAGER_H_ ================================================ FILE: cc/streamingaead/aes_ctr_hmac_streaming_key_manager_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/aes_ctr_hmac_streaming_key_manager.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/streaming_aead.h" #include "tink/subtle/aes_ctr_hmac_streaming.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/random.h" #include "tink/subtle/streaming_aead_test_util.h" #include "tink/subtle/test_util.h" #include "tink/util/istream_input_stream.h" #include "tink/util/ostream_output_stream.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/aes_ctr_hmac_streaming.pb.h" #include "proto/aes_eax.pb.h" #include "proto/common.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::AesCtrHmacStreamingKey; using ::google::crypto::tink::AesCtrHmacStreamingKeyFormat; using ::google::crypto::tink::HashType; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::Not; namespace { TEST(AesCtrHmacStreamingKeyManagerTest, ValidateKey) { AesCtrHmacStreamingKey key; key.set_version(0); key.set_key_value("0123456789abcdef"); key.mutable_params()->set_derived_key_size(16); key.mutable_params()->set_hkdf_hash_type(HashType::SHA256); key.mutable_params()->set_ciphertext_segment_size(1024); key.mutable_params()->mutable_hmac_params()->set_hash(HashType::SHA256); key.mutable_params()->mutable_hmac_params()->set_tag_size(32); EXPECT_THAT(AesCtrHmacStreamingKeyManager().ValidateKey(key), IsOk()); } TEST(AesCtrHmacStreamingKeyManagerTest, ValidateKeyDerivedKeySizes) { for (int derived_key_size = 0; derived_key_size < 42; derived_key_size++) { SCOPED_TRACE(absl::StrCat(" derived_key_size = ", derived_key_size)); AesCtrHmacStreamingKey key; key.set_version(0); key.set_key_value(std::string(derived_key_size, 'a')); // ikm key.mutable_params()->set_derived_key_size(derived_key_size); key.mutable_params()->set_hkdf_hash_type(HashType::SHA256); key.mutable_params()->set_ciphertext_segment_size(1024); key.mutable_params()->mutable_hmac_params()->set_hash(HashType::SHA256); key.mutable_params()->mutable_hmac_params()->set_tag_size(32); if (derived_key_size == 16 || derived_key_size == 32) { EXPECT_THAT(AesCtrHmacStreamingKeyManager().ValidateKey(key), IsOk()); } else { EXPECT_THAT(AesCtrHmacStreamingKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } } } TEST(AesCtrHmacStreamingKeyManagerTest, ValidateKeyDerivedKeyWrongVersion) { AesCtrHmacStreamingKey key; key.set_version(1); key.set_key_value("0123456789abcdef"); key.mutable_params()->set_derived_key_size(16); key.mutable_params()->set_hkdf_hash_type(HashType::SHA256); key.mutable_params()->set_ciphertext_segment_size(1024); key.mutable_params()->mutable_hmac_params()->set_hash(HashType::SHA256); key.mutable_params()->mutable_hmac_params()->set_tag_size(32); EXPECT_THAT(AesCtrHmacStreamingKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesCtrHmacStreamingKeyManagerTest, GetPrimitive) { std::string plaintext = "some plaintext"; std::string aad = "some aad"; AesCtrHmacStreamingKey key; key.set_version(0); key.set_key_value("16 bytes of key "); key.mutable_params()->set_ciphertext_segment_size(1024); key.mutable_params()->set_derived_key_size(16); key.mutable_params()->set_hkdf_hash_type(HashType::SHA256); key.mutable_params()->mutable_hmac_params()->set_hash(HashType::SHA256); key.mutable_params()->mutable_hmac_params()->set_tag_size(32); auto streaming_aead_from_manager_result = AesCtrHmacStreamingKeyManager().GetPrimitive(key); ASSERT_THAT(streaming_aead_from_manager_result, IsOk()); subtle::AesCtrHmacStreaming::Params params; params.ikm = util::SecretDataFromStringView("16 bytes of key "); params.hkdf_algo = subtle::HashType::SHA256;; params.key_size = 16; params.ciphertext_segment_size = 1024; params.ciphertext_offset = 0; params.tag_algo = subtle::HashType::SHA256; params.tag_size = 32; auto streaming_aead_direct_result = crypto::tink::subtle::AesCtrHmacStreaming::New(params); ASSERT_THAT(streaming_aead_direct_result, IsOk()); // Check that the two primitives are the same by encrypting with one, and // decrypting with the other. EXPECT_THAT( EncryptThenDecrypt(streaming_aead_from_manager_result.value().get(), streaming_aead_direct_result.value().get(), subtle::Random::GetRandomBytes(10000), "some associated data", params.ciphertext_offset), IsOk()); } TEST(AesCtrHmacStreamingKeyManagerTest, Version) { EXPECT_THAT(AesCtrHmacStreamingKeyManager().get_version(), Eq(0)); } TEST(AesCtrHmacStreamingKeyManagerTest, KeyMaterialType) { EXPECT_THAT(AesCtrHmacStreamingKeyManager().key_material_type(), Eq(google::crypto::tink::KeyData::SYMMETRIC)); } TEST(AesCtrHmacStreamingKeyManagerTest, KeyType) { EXPECT_THAT( AesCtrHmacStreamingKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.AesCtrHmacStreamingKey")); } TEST(AesCtrHmacStreamingKeyManagerTest, ValidateKeyFormatEmpty) { EXPECT_THAT(AesCtrHmacStreamingKeyManager().ValidateKeyFormat( AesCtrHmacStreamingKeyFormat()), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesCtrHmacStreamingKeyManagerTest, ValidateKeyFormat) { AesCtrHmacStreamingKeyFormat key_format; key_format.set_key_size(32); key_format.mutable_params()->set_derived_key_size(32); key_format.mutable_params()->set_hkdf_hash_type(HashType::SHA256); key_format.mutable_params()->set_ciphertext_segment_size(1024); key_format.mutable_params()->mutable_hmac_params()-> set_hash(HashType::SHA256); key_format.mutable_params()->mutable_hmac_params()->set_tag_size(32); EXPECT_THAT(AesCtrHmacStreamingKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(AesCtrHmacStreamingKeyManagerTest, ValidateKeyFormatSmallKey) { AesCtrHmacStreamingKeyFormat key_format; key_format.set_key_size(16); key_format.mutable_params()->set_derived_key_size(32); key_format.mutable_params()->set_hkdf_hash_type(HashType::SHA256); key_format.mutable_params()->set_ciphertext_segment_size(1024); key_format.mutable_params()->mutable_hmac_params()-> set_hash(HashType::SHA256); key_format.mutable_params()->mutable_hmac_params()->set_tag_size(32); EXPECT_THAT(AesCtrHmacStreamingKeyManager().ValidateKeyFormat(key_format), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("derived_key_size"))); } TEST(AesCtrHmacStreamingKeyManagerTest, ValidateKeyFormatWrongHash) { AesCtrHmacStreamingKeyFormat key_format; key_format.set_key_size(32); key_format.mutable_params()->set_derived_key_size(32); key_format.mutable_params()->set_ciphertext_segment_size(1024); key_format.mutable_params()->mutable_hmac_params()-> set_hash(HashType::SHA256); key_format.mutable_params()->mutable_hmac_params()->set_tag_size(32); EXPECT_THAT(AesCtrHmacStreamingKeyManager().ValidateKeyFormat(key_format), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("hkdf_hash_type"))); } TEST(AesCtrHmacStreamingKeyManagerTest, ValidateKeyFormatWrongHmacHash) { AesCtrHmacStreamingKeyFormat key_format; key_format.set_key_size(32); key_format.mutable_params()->set_derived_key_size(32); key_format.mutable_params()->set_hkdf_hash_type(HashType::SHA256); key_format.mutable_params()->set_ciphertext_segment_size(1024); key_format.mutable_params()->mutable_hmac_params()->set_tag_size(32); EXPECT_THAT(AesCtrHmacStreamingKeyManager().ValidateKeyFormat(key_format), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("hmac_params.hash"))); } TEST(AesCtrHmacStreamingKeyManagerTest, ValidateKeyFormatSmallSegment) { AesCtrHmacStreamingKeyFormat key_format; key_format.set_key_size(32); key_format.mutable_params()->set_derived_key_size(32); key_format.mutable_params()->set_hkdf_hash_type(HashType::SHA256); key_format.mutable_params()->set_ciphertext_segment_size(45); key_format.mutable_params()->mutable_hmac_params()-> set_hash(HashType::SHA256); key_format.mutable_params()->mutable_hmac_params()->set_tag_size(32); EXPECT_THAT(AesCtrHmacStreamingKeyManager().ValidateKeyFormat(key_format), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("ciphertext_segment_size"))); } TEST(AesCtrHmacStreamingKeyManagerTest, ValidateKeyFormatTooLargeSegment) { AesCtrHmacStreamingKeyFormat key_format; key_format.set_key_size(32); key_format.mutable_params()->set_derived_key_size(32); key_format.mutable_params()->set_hkdf_hash_type(HashType::SHA256); key_format.mutable_params()->set_ciphertext_segment_size(2147483648); key_format.mutable_params()->mutable_hmac_params()-> set_hash(HashType::SHA256); key_format.mutable_params()->mutable_hmac_params()->set_tag_size(32); EXPECT_THAT(AesCtrHmacStreamingKeyManager().ValidateKeyFormat(key_format), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("ciphertext_segment_size too big"))); } TEST(AesCtrHmacStreamingKeyManagerTest, CreateKey) { AesCtrHmacStreamingKeyFormat key_format; key_format.set_key_size(32); key_format.mutable_params()->set_derived_key_size(32); key_format.mutable_params()->set_hkdf_hash_type(HashType::SHA256); key_format.mutable_params()->set_ciphertext_segment_size(1024); key_format.mutable_params()->mutable_hmac_params()-> set_hash(HashType::SHA256); key_format.mutable_params()->mutable_hmac_params()->set_tag_size(32); auto key_or = AesCtrHmacStreamingKeyManager().CreateKey(key_format); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().version(), Eq(0)); EXPECT_THAT(key_or.value().params().ciphertext_segment_size(), Eq(key_format.params().ciphertext_segment_size())); EXPECT_THAT(key_or.value().params().derived_key_size(), Eq(key_format.params().derived_key_size())); EXPECT_THAT(key_or.value().params().hkdf_hash_type(), Eq(key_format.params().hkdf_hash_type())); EXPECT_THAT(key_or.value().key_value().size(), Eq(key_format.key_size())); EXPECT_THAT(key_or.value().params().hmac_params().hash(), Eq(key_format.params().hmac_params().hash())); EXPECT_THAT(key_or.value().params().hmac_params().tag_size(), Eq(key_format.params().hmac_params().tag_size())); } TEST(AesCtrHmacStreamingKeyManagerTest, DeriveKey) { AesCtrHmacStreamingKeyFormat key_format; key_format.set_version(0); key_format.set_key_size(32); key_format.mutable_params()->set_derived_key_size(32); key_format.mutable_params()->set_hkdf_hash_type(HashType::SHA256); key_format.mutable_params()->set_ciphertext_segment_size(1024); util::IstreamInputStream input_stream{ absl::make_unique("01234567890123456789012345678901")}; util::StatusOr key_or = AesCtrHmacStreamingKeyManager().DeriveKey(key_format, &input_stream); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().key_value(), Eq("01234567890123456789012345678901")); EXPECT_THAT(key_or.value().params().derived_key_size(), Eq(key_format.params().derived_key_size())); EXPECT_THAT(key_or.value().params().hkdf_hash_type(), Eq(key_format.params().hkdf_hash_type())); EXPECT_THAT(key_or.value().params().ciphertext_segment_size(), Eq(key_format.params().ciphertext_segment_size())); } TEST(AesCtrHmacStreamingKeyManagerTest, DeriveKeyNotEnoughRandomness) { AesCtrHmacStreamingKeyFormat key_format; key_format.set_version(0); key_format.set_key_size(32); key_format.mutable_params()->set_derived_key_size(32); key_format.mutable_params()->set_hkdf_hash_type(HashType::SHA256); key_format.mutable_params()->set_ciphertext_segment_size(1024); util::IstreamInputStream input_stream{ absl::make_unique("0123456789012345678901234567890")}; ASSERT_THAT(AesCtrHmacStreamingKeyManager() .DeriveKey(key_format, &input_stream) .status(), Not(IsOk())); } TEST(AesCtrHmacStreamingKeyManagerTest, DeriveKeyWrongVersion) { AesCtrHmacStreamingKeyFormat key_format; key_format.set_version(1); key_format.set_key_size(32); key_format.mutable_params()->set_derived_key_size(32); key_format.mutable_params()->set_hkdf_hash_type(HashType::SHA256); key_format.mutable_params()->set_ciphertext_segment_size(1024); util::IstreamInputStream input_stream{ absl::make_unique("0123456789abcdef")}; ASSERT_THAT( AesCtrHmacStreamingKeyManager() .DeriveKey(key_format, &input_stream) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("version"))); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/aes_gcm_hkdf_streaming_key_manager.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/aes_gcm_hkdf_streaming_key_manager.h" #include #include "absl/status/status.h" #include "tink/input_stream.h" #include "tink/subtle/aes_gcm_hkdf_stream_segment_encrypter.h" #include "tink/subtle/random.h" #include "tink/util/input_stream_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/validation.h" #include "proto/common.pb.h" namespace crypto { namespace tink { using ::crypto::tink::subtle::AesGcmHkdfStreamSegmentEncrypter; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::AesGcmHkdfStreamingKey; using ::google::crypto::tink::AesGcmHkdfStreamingKeyFormat; using ::google::crypto::tink::AesGcmHkdfStreamingParams; using ::google::crypto::tink::HashType; namespace { Status ValidateParams(const AesGcmHkdfStreamingParams& params) { if (!(params.hkdf_hash_type() == HashType::SHA1 || params.hkdf_hash_type() == HashType::SHA256 || params.hkdf_hash_type() == HashType::SHA512)) { return Status(absl::StatusCode::kInvalidArgument, "unsupported hkdf_hash_type"); } int header_size = 1 + params.derived_key_size() + AesGcmHkdfStreamSegmentEncrypter::kNoncePrefixSizeInBytes; if (params.ciphertext_segment_size() <= header_size + AesGcmHkdfStreamSegmentEncrypter::kTagSizeInBytes) { return Status(absl::StatusCode::kInvalidArgument, "ciphertext_segment_size too small"); } return ValidateAesKeySize(params.derived_key_size()); } } // namespace crypto::tink::util::StatusOr AesGcmHkdfStreamingKeyManager::CreateKey( const google::crypto::tink::AesGcmHkdfStreamingKeyFormat& key_format) const { AesGcmHkdfStreamingKey key; key.set_version(get_version()); key.set_key_value(subtle::Random::GetRandomBytes(key_format.key_size())); *key.mutable_params() = key_format.params(); return key; }; crypto::tink::util::StatusOr AesGcmHkdfStreamingKeyManager::DeriveKey( const google::crypto::tink::AesGcmHkdfStreamingKeyFormat& key_format, InputStream* input_stream) const { crypto::tink::util::Status status = ValidateVersion(key_format.version(), get_version()); if (!status.ok()) return status; crypto::tink::util::StatusOr randomness_or = ReadBytesFromStream(key_format.key_size(), input_stream); if (!randomness_or.ok()) { return randomness_or.status(); } AesGcmHkdfStreamingKey key; key.set_version(get_version()); key.set_key_value(randomness_or.value()); *key.mutable_params() = key_format.params(); return key; } Status AesGcmHkdfStreamingKeyManager::ValidateKey( const AesGcmHkdfStreamingKey& key) const { Status status = ValidateVersion(key.version(), get_version()); if (!status.ok()) return status; if (key.key_value().size() < key.params().derived_key_size()) { return Status(absl::StatusCode::kInvalidArgument, "key_value (i.e. ikm) too short"); } return ValidateParams(key.params()); } Status AesGcmHkdfStreamingKeyManager::ValidateKeyFormat( const AesGcmHkdfStreamingKeyFormat& key_format) const { if (key_format.key_size() < key_format.params().derived_key_size()) { return Status(absl::StatusCode::kInvalidArgument, "key_size must not be smaller than derived_key_size"); } return ValidateParams(key_format.params()); } } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/aes_gcm_hkdf_streaming_key_manager.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_STREAMINGAEAD_AES_GCM_HKDF_STREAMING_KEY_MANAGER_H_ #define TINK_STREAMINGAEAD_AES_GCM_HKDF_STREAMING_KEY_MANAGER_H_ #include #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "tink/core/key_type_manager.h" #include "tink/core/template_util.h" #include "tink/input_stream.h" #include "tink/key_manager.h" #include "tink/streaming_aead.h" #include "tink/subtle/aes_gcm_hkdf_streaming.h" #include "tink/util/constants.h" #include "tink/util/enums.h" #include "tink/util/errors.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/aes_gcm_hkdf_streaming.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class AesGcmHkdfStreamingKeyManager : public KeyTypeManager> { public: class AesGcmHkdfStreamingKeyManagerFactory : public PrimitiveFactory { crypto::tink::util::StatusOr> Create( const google::crypto::tink::AesGcmHkdfStreamingKey& key) const override { subtle::AesGcmHkdfStreaming::Params params; params.ikm = util::SecretDataFromStringView(key.key_value()); params.hkdf_hash = crypto::tink::util::Enums::ProtoToSubtle( key.params().hkdf_hash_type()); params.derived_key_size = key.params().derived_key_size(); params.ciphertext_segment_size = key.params().ciphertext_segment_size(); params.ciphertext_offset = 0; auto streaming_result = subtle::AesGcmHkdfStreaming::New(std::move(params)); if (!streaming_result.ok()) return streaming_result.status(); return {std::move(streaming_result.value())}; } }; AesGcmHkdfStreamingKeyManager() : KeyTypeManager( absl::make_unique()) {} // Returns the version of this key manager. uint32_t get_version() const override { return 0; } google::crypto::tink::KeyData::KeyMaterialType key_material_type() const override { return google::crypto::tink::KeyData::SYMMETRIC; } const std::string& get_key_type() const override { return key_type_; } crypto::tink::util::Status ValidateKey( const google::crypto::tink::AesGcmHkdfStreamingKey& key) const override; crypto::tink::util::Status ValidateKeyFormat( const google::crypto::tink::AesGcmHkdfStreamingKeyFormat& key_format) const override; crypto::tink::util::StatusOr CreateKey(const google::crypto::tink::AesGcmHkdfStreamingKeyFormat& key_format) const override; crypto::tink::util::StatusOr DeriveKey( const google::crypto::tink::AesGcmHkdfStreamingKeyFormat& key_format, InputStream* input_stream) const override; ~AesGcmHkdfStreamingKeyManager() override = default; private: const std::string key_type_ = absl::StrCat( kTypeGoogleapisCom, google::crypto::tink::AesGcmHkdfStreamingKey().GetTypeName()); static crypto::tink::util::Status Validate( const google::crypto::tink::AesGcmHkdfStreamingKeyFormat& key_format); }; } // namespace tink } // namespace crypto #endif // TINK_STREAMINGAEAD_AES_GCM_HKDF_STREAMING_KEY_MANAGER_H_ ================================================ FILE: cc/streamingaead/aes_gcm_hkdf_streaming_key_manager_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/aes_gcm_hkdf_streaming_key_manager.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/streaming_aead.h" #include "tink/subtle/aes_gcm_hkdf_streaming.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/random.h" #include "tink/subtle/streaming_aead_test_util.h" #include "tink/subtle/test_util.h" #include "tink/util/istream_input_stream.h" #include "tink/util/ostream_output_stream.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/aes_eax.pb.h" #include "proto/aes_gcm_hkdf_streaming.pb.h" #include "proto/common.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::IstreamInputStream; using ::crypto::tink::util::StatusOr; using ::google::crypto::tink::AesGcmHkdfStreamingKey; using ::google::crypto::tink::AesGcmHkdfStreamingKeyFormat; using ::google::crypto::tink::HashType; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::Not; namespace { TEST(AesGcmHkdfStreamingKeyManagerTest, ValidateKey) { AesGcmHkdfStreamingKey key; key.set_version(0); key.set_key_value("0123456789abcdef"); key.mutable_params()->set_derived_key_size(16); key.mutable_params()->set_hkdf_hash_type(HashType::SHA256); key.mutable_params()->set_ciphertext_segment_size(1024); EXPECT_THAT(AesGcmHkdfStreamingKeyManager().ValidateKey(key), IsOk()); } TEST(AesGcmHkdfStreamingKeyManagerTest, ValidateKeyDerivedKeySizes) { for (int derived_key_size = 0; derived_key_size < 42; derived_key_size++) { SCOPED_TRACE(absl::StrCat(" derived_key_size = ", derived_key_size)); AesGcmHkdfStreamingKey key; key.set_version(0); key.set_key_value(std::string(derived_key_size, 'a')); // ikm key.mutable_params()->set_derived_key_size(derived_key_size); key.mutable_params()->set_hkdf_hash_type(HashType::SHA256); key.mutable_params()->set_ciphertext_segment_size(1024); if (derived_key_size == 16 || derived_key_size == 32) { EXPECT_THAT(AesGcmHkdfStreamingKeyManager().ValidateKey(key), IsOk()); } else { EXPECT_THAT(AesGcmHkdfStreamingKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } } } TEST(AesGcmHkdfStreamingKeyManagerTest, ValidateKeyDerivedKeyWrongVersion) { AesGcmHkdfStreamingKey key; key.set_version(1); key.set_key_value("0123456789abcdef"); key.mutable_params()->set_derived_key_size(16); key.mutable_params()->set_hkdf_hash_type(HashType::SHA256); key.mutable_params()->set_ciphertext_segment_size(1024); EXPECT_THAT(AesGcmHkdfStreamingKeyManager().ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmHkdfStreamingKeyManagerTest, GetPrimitive) { std::string plaintext = "some plaintext"; std::string aad = "some aad"; AesGcmHkdfStreamingKey key; key.set_version(0); key.set_key_value("16 bytes of key "); key.mutable_params()->set_ciphertext_segment_size(1024); key.mutable_params()->set_derived_key_size(16); key.mutable_params()->set_hkdf_hash_type(HashType::SHA256); auto streaming_aead_from_manager_result = AesGcmHkdfStreamingKeyManager().GetPrimitive(key); EXPECT_THAT(streaming_aead_from_manager_result, IsOk()); int derived_key_size = 16; int ciphertext_segment_size = 1024; int ciphertext_offset = 0; subtle::AesGcmHkdfStreaming::Params params; params.ikm = util::SecretDataFromStringView("16 bytes of key "); params.hkdf_hash = crypto::tink::subtle::HashType::SHA256; params.derived_key_size = derived_key_size; params.ciphertext_segment_size = ciphertext_segment_size; params.ciphertext_offset = ciphertext_offset; auto streaming_aead_direct_result = subtle::AesGcmHkdfStreaming::New(std::move(params)); EXPECT_THAT(streaming_aead_direct_result, IsOk()); // Check that the two primitives are the same by encrypting with one, and // decrypting with the other. EXPECT_THAT( EncryptThenDecrypt(streaming_aead_from_manager_result.value().get(), streaming_aead_direct_result.value().get(), subtle::Random::GetRandomBytes(10000), "some associated data", ciphertext_offset), IsOk()); } TEST(AesGcmHkdfStreamingKeyManagerTest, Version) { EXPECT_THAT(AesGcmHkdfStreamingKeyManager().get_version(), Eq(0)); } TEST(AesGcmHkdfStreamingKeyManagerTest, KeyMaterialType) { EXPECT_THAT(AesGcmHkdfStreamingKeyManager().key_material_type(), Eq(google::crypto::tink::KeyData::SYMMETRIC)); } TEST(AesGcmHkdfStreamingKeyManagerTest, KeyType) { EXPECT_THAT( AesGcmHkdfStreamingKeyManager().get_key_type(), Eq("type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey")); } TEST(AesGcmHkdfStreamingKeyManagerTest, ValidateKeyFormatEmpty) { EXPECT_THAT(AesGcmHkdfStreamingKeyManager().ValidateKeyFormat( AesGcmHkdfStreamingKeyFormat()), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(AesGcmHkdfStreamingKeyManagerTest, ValidateKeyFormat) { AesGcmHkdfStreamingKeyFormat key_format; key_format.set_key_size(32); key_format.mutable_params()->set_derived_key_size(32); key_format.mutable_params()->set_hkdf_hash_type(HashType::SHA256); key_format.mutable_params()->set_ciphertext_segment_size(1024); EXPECT_THAT(AesGcmHkdfStreamingKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(AesGcmHkdfStreamingKeyManagerTest, ValidateKeyFormatSmallKey) { AesGcmHkdfStreamingKeyFormat key_format; key_format.set_key_size(16); key_format.mutable_params()->set_derived_key_size(32); key_format.mutable_params()->set_hkdf_hash_type(HashType::SHA256); key_format.mutable_params()->set_ciphertext_segment_size(1024); EXPECT_THAT(AesGcmHkdfStreamingKeyManager().ValidateKeyFormat(key_format), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("derived_key_size"))); } TEST(AesGcmHkdfStreamingKeyManagerTest, ValidateKeyFormatWrongHash) { AesGcmHkdfStreamingKeyFormat key_format; key_format.set_key_size(32); key_format.mutable_params()->set_derived_key_size(32); key_format.mutable_params()->set_ciphertext_segment_size(1024); EXPECT_THAT(AesGcmHkdfStreamingKeyManager().ValidateKeyFormat(key_format), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("hkdf_hash_type"))); } TEST(AesGcmHkdfStreamingKeyManagerTest, ValidateKeyFormatSmallSegment) { AesGcmHkdfStreamingKeyFormat key_format; key_format.set_key_size(32); key_format.mutable_params()->set_derived_key_size(32); key_format.mutable_params()->set_hkdf_hash_type(HashType::SHA256); key_format.mutable_params()->set_ciphertext_segment_size(45); EXPECT_THAT(AesGcmHkdfStreamingKeyManager().ValidateKeyFormat(key_format), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("ciphertext_segment_size"))); } TEST(AesGcmHkdfStreamingKeyManagerTest, CreateKey) { AesGcmHkdfStreamingKeyFormat key_format; key_format.set_key_size(32); key_format.mutable_params()->set_derived_key_size(32); key_format.mutable_params()->set_hkdf_hash_type(HashType::SHA256); key_format.mutable_params()->set_ciphertext_segment_size(1024); auto key_or = AesGcmHkdfStreamingKeyManager().CreateKey(key_format); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().version(), Eq(0)); EXPECT_THAT(key_or.value().params().ciphertext_segment_size(), Eq(key_format.params().ciphertext_segment_size())); EXPECT_THAT(key_or.value().params().derived_key_size(), Eq(key_format.params().derived_key_size())); EXPECT_THAT(key_or.value().params().hkdf_hash_type(), Eq(key_format.params().hkdf_hash_type())); EXPECT_THAT(key_or.value().key_value().size(), Eq(key_format.key_size())); } TEST(AesGcmHkdfStreamingKeyManagerTest, DeriveKey) { AesGcmHkdfStreamingKeyFormat key_format; key_format.set_version(0); key_format.set_key_size(32); key_format.mutable_params()->set_derived_key_size(32); key_format.mutable_params()->set_hkdf_hash_type(HashType::SHA256); key_format.mutable_params()->set_ciphertext_segment_size(1024); IstreamInputStream input_stream{ absl::make_unique("01234567890123456789012345678901")}; StatusOr key_or = AesGcmHkdfStreamingKeyManager().DeriveKey(key_format, &input_stream); ASSERT_THAT(key_or, IsOk()); EXPECT_THAT(key_or.value().key_value(), Eq("01234567890123456789012345678901")); EXPECT_THAT(key_or.value().params().derived_key_size(), Eq(key_format.params().derived_key_size())); EXPECT_THAT(key_or.value().params().hkdf_hash_type(), Eq(key_format.params().hkdf_hash_type())); EXPECT_THAT(key_or.value().params().ciphertext_segment_size(), Eq(key_format.params().ciphertext_segment_size())); } TEST(AesGcmHkdfStreamingKeyManagerTest, DeriveKeyNotEnoughRandomness) { AesGcmHkdfStreamingKeyFormat key_format; key_format.set_version(0); key_format.set_key_size(32); key_format.mutable_params()->set_derived_key_size(32); key_format.mutable_params()->set_hkdf_hash_type(HashType::SHA256); key_format.mutable_params()->set_ciphertext_segment_size(1024); IstreamInputStream input_stream{ absl::make_unique("0123456789012345678901234567890")}; ASSERT_THAT(AesGcmHkdfStreamingKeyManager() .DeriveKey(key_format, &input_stream) .status(), Not(IsOk())); } TEST(AesGcmHkdfStreamingKeyManagerTest, DeriveKeyWrongVersion) { AesGcmHkdfStreamingKeyFormat key_format; key_format.set_version(1); key_format.set_key_size(32); key_format.mutable_params()->set_derived_key_size(32); key_format.mutable_params()->set_hkdf_hash_type(HashType::SHA256); key_format.mutable_params()->set_ciphertext_segment_size(1024); IstreamInputStream input_stream{absl::make_unique( "0123456789abcdef")}; ASSERT_THAT( AesGcmHkdfStreamingKeyManager() .DeriveKey(key_format, &input_stream) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("version"))); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/buffered_input_stream.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/buffered_input_stream.h" #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/input_stream.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace streamingaead { using util::Status; using util::StatusOr; BufferedInputStream::BufferedInputStream( std::unique_ptr input_stream) { input_stream_ = std::move(input_stream); count_in_buffer_ = 0; count_backedup_ = 0; position_ = 0; buffer_.resize(4 * 1024); // 4 KB buffer_offset_ = 0; after_rewind_ = false; rewinding_enabled_ = true; direct_access_ = false; status_ = util::OkStatus(); } crypto::tink::util::StatusOr BufferedInputStream::Next(const void** data) { if (direct_access_) return input_stream_->Next(data); if (!status_.ok()) return status_; // We're just after rewind, so return all the data in the buffer, if any. if (after_rewind_ && count_in_buffer_ > 0) { after_rewind_ = false; *data = buffer_.data(); position_ = count_in_buffer_; return count_in_buffer_; } if (count_backedup_ > 0) { // Return the backed-up bytes. buffer_offset_ = count_in_buffer_ - count_backedup_; *data = buffer_.data() + buffer_offset_; int backedup = count_backedup_; count_backedup_ = 0; position_ = count_in_buffer_; return backedup; } // Read new bytes from input_stream_. // // If we don't allow rewind any more, all the data buffered so far // can be discarded, and from now on we go directly to input_stream_ if (!rewinding_enabled_) { direct_access_ = true; buffer_.resize(0); return input_stream_->Next(data); } // Otherwise, we read from input_stream_ the next chunk of data, // and append it to buffer_. after_rewind_ = false; const void* buf; auto next_result = input_stream_->Next(&buf); if (!next_result.ok()) { status_ = next_result.status(); return status_; } size_t count_read = next_result.value(); if (buffer_.size() < count_in_buffer_ + count_read) { buffer_.resize(buffer_.size() + std::max(buffer_.size(), count_read)); } memcpy(buffer_.data() + count_in_buffer_, buf, count_read); buffer_offset_ = count_in_buffer_; count_backedup_ = 0; count_in_buffer_ += count_read; position_ = position_ + count_read; *data = buffer_.data() + buffer_offset_; return count_read; } void BufferedInputStream::BackUp(int count) { if (direct_access_) { input_stream_->BackUp(count); return; } if (!status_.ok() || count < 1 || count_backedup_ == (count_in_buffer_ - buffer_offset_)) { return; } int actual_count = std::min( count, count_in_buffer_ - buffer_offset_ - count_backedup_); count_backedup_ += actual_count; position_ = position_ - actual_count; } void BufferedInputStream::DisableRewinding() { rewinding_enabled_ = false; } crypto::tink::util::Status BufferedInputStream::Rewind() { if (!rewinding_enabled_) { return util::Status(absl::StatusCode::kInvalidArgument, "rewinding is disabled"); } if (status_.ok() || status_.code() == absl::StatusCode::kOutOfRange) { status_ = util::OkStatus(); position_ = 0; count_backedup_ = 0; buffer_offset_ = 0; after_rewind_ = true; } return status_; } BufferedInputStream::~BufferedInputStream() = default; int64_t BufferedInputStream::Position() const { if (direct_access_) return input_stream_->Position(); return position_; } } // namespace streamingaead } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/buffered_input_stream.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_STREAMINGAEAD_BUFFERED_INPUT_STREAM_H_ #define TINK_STREAMINGAEAD_BUFFERED_INPUT_STREAM_H_ #include #include #include #include "tink/input_stream.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace streamingaead { // An InputStream that initially buffers all the read bytes, and offers // rewind-functionality, until explicitly instructed to disable // rewinding (and stop buffering). class BufferedInputStream : public crypto::tink::InputStream { public: // Constructs an InputStream that will read from 'input_stream', // buffering all the read bytes in memory, and offering rewinding // to the beginning of the stream (as long as rewinding is enabled). explicit BufferedInputStream( std::unique_ptr input_stream); ~BufferedInputStream() override; crypto::tink::util::StatusOr Next(const void** data) override; void BackUp(int count) override; int64_t Position() const override; // Rewinds this stream to the beginning (if rewinding is still enabled). crypto::tink::util::Status Rewind(); // Disables rewinding. void DisableRewinding(); private: std::unique_ptr input_stream_; bool direct_access_; // true iff we don't buffer any data any more // The fields below are valid and in use iff direct_access_ is false. // Once direct_access_ becomes true, all the calls to this stream's methods // are directly relayed to methods of input_stream_. crypto::tink::util::Status status_; std::vector buffer_; bool after_rewind_; // true iff no Next has been called after rewind bool rewinding_enabled_; // true iff this stream can be rewound int64_t position_; // current position in the stream (from the beginning) // Counters that describe the state of the data in buffer_. int count_in_buffer_; // # of bytes available in buffer_ int count_backedup_; // # of bytes available in buffer_ that were backed up int buffer_offset_; // offset at which the returned bytes start in buffer_ }; } // namespace streamingaead } // namespace tink } // namespace crypto #endif // TINK_STREAMINGAEAD_BUFFERED_INPUT_STREAM_H_ ================================================ FILE: cc/streamingaead/buffered_input_stream_test.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/buffered_input_stream.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/input_stream.h" #include "tink/subtle/random.h" #include "tink/subtle/test_util.h" #include "tink/util/istream_input_stream.h" #include "tink/util/status.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace streamingaead { namespace { using crypto::tink::test::IsOk; using crypto::tink::test::StatusIs; using subtle::test::ReadFromStream; using testing::HasSubstr; static int kBufferSize = 4096; // Creates an InputStream with the specified contents. std::unique_ptr GetInputStream(absl::string_view contents) { // Prepare ciphertext source stream. auto string_stream = absl::make_unique(std::string(contents)); std::unique_ptr input_stream( absl::make_unique( std::move(string_stream), kBufferSize)); return input_stream; } // Attempts to read 'count' bytes from 'input_stream', and writes the read // bytes to 'output'. util::Status ReadFromStream(InputStream* input_stream, int count, std::string* output) { if (input_stream == nullptr || output == nullptr || count < 0) { return util::Status(absl::StatusCode::kInternal, "Illegal read from a stream"); } const void* buffer; output->clear(); int bytes_to_read = count; while (bytes_to_read > 0) { auto next_result = input_stream->Next(&buffer); if (next_result.status().code() == absl::StatusCode::kOutOfRange) { // End of stream. return util::OkStatus(); } if (!next_result.ok()) return next_result.status(); auto read_bytes = next_result.value(); auto used_bytes = std::min(read_bytes, bytes_to_read); if (used_bytes > 0) { output->append( std::string(reinterpret_cast(buffer), used_bytes)); bytes_to_read -= used_bytes; if (bytes_to_read == 0) input_stream->BackUp(read_bytes - used_bytes); } } return util::OkStatus(); } TEST(BufferedInputStreamTest, ReadingAndRewinding) { for (auto input_size : {0, 1, 10, 100, 1000, 10000, 100000}) { std::string contents = subtle::Random::GetRandomBytes(input_size); auto input_stream = GetInputStream(contents); auto buf_stream = absl::make_unique( std::move(input_stream)); for (auto read_size : {0, 1, 10, 123, 300}) { SCOPED_TRACE(absl::StrCat("input_size = ", input_size, ", read_size = ", read_size)); // Read a prefix of the stream. std::string prefix; auto status = ReadFromStream(buf_stream.get(), read_size, &prefix); EXPECT_THAT(status, IsOk()); EXPECT_EQ(std::min(read_size, input_size), buf_stream->Position()); EXPECT_EQ(contents.substr(0, read_size), prefix); // Read the rest of the stream. std::string rest; status = ReadFromStream(buf_stream.get(), &rest); EXPECT_THAT(status, IsOk()); EXPECT_EQ(input_size, buf_stream->Position()); EXPECT_EQ(contents, prefix + rest); // Try reading again, should get an empty string. status = ReadFromStream(buf_stream.get(), &rest); EXPECT_THAT(status, IsOk()); EXPECT_EQ("", rest); // Rewind and read again, again in two parts. status = buf_stream->Rewind(); EXPECT_EQ(0, buf_stream->Position()); EXPECT_THAT(status, IsOk()); status = ReadFromStream(buf_stream.get(), read_size, &prefix); EXPECT_THAT(status, IsOk()); EXPECT_EQ(std::min(read_size, input_size), buf_stream->Position()); EXPECT_EQ(contents.substr(0, read_size), prefix); status = ReadFromStream(buf_stream.get(), &rest); EXPECT_THAT(status, IsOk()); EXPECT_EQ(input_size, buf_stream->Position()); EXPECT_EQ(contents, prefix + rest); // Rewind so that the next read iteration starts from the beginning. status = buf_stream->Rewind(); EXPECT_THAT(status, IsOk()); EXPECT_EQ(0, buf_stream->Position()); } } } TEST(BufferedInputStreamTest, SingleBackup) { for (auto input_size : {0, 1, 10, 100, 1000, 10000, 100000}) { std::string contents = subtle::Random::GetRandomBytes(input_size); for (auto read_size : {0, 1, 10, 123, 300, 1024}) { SCOPED_TRACE(absl::StrCat("input_size = ", input_size, ", read_size = ", read_size)); auto input_stream = GetInputStream(contents); auto buf_stream = absl::make_unique( std::move(input_stream)); // Read a part of the stream. std::string prefix; auto status = ReadFromStream(buf_stream.get(), read_size, &prefix); EXPECT_THAT(status, IsOk()); EXPECT_EQ(std::min(read_size, input_size), buf_stream->Position()); EXPECT_EQ(contents.substr(0, read_size), prefix); // Read the next block of the stream, and then back it up. const void* buf; int pos = buf_stream->Position(); auto next_result = buf_stream->Next(&buf); if (read_size < input_size) { EXPECT_THAT(next_result, IsOk()); auto next_size = next_result.value(); EXPECT_LE(next_size, kBufferSize); EXPECT_EQ(pos + next_size, buf_stream->Position()); buf_stream->BackUp(next_size); EXPECT_EQ(pos, buf_stream->Position()); buf_stream->BackUp(input_size); EXPECT_EQ(pos, buf_stream->Position()); } else { EXPECT_EQ(absl::StatusCode::kOutOfRange, next_result.status().code()); } // Read the rest of the input. std::string rest; status = ReadFromStream(buf_stream.get(), &rest); EXPECT_THAT(status, IsOk()); EXPECT_EQ(input_size, buf_stream->Position()); EXPECT_EQ(contents, prefix + rest); // Rewind and read prefix again. status = buf_stream->Rewind(); EXPECT_EQ(0, buf_stream->Position()); EXPECT_THAT(status, IsOk()); status = ReadFromStream(buf_stream.get(), read_size, &prefix); EXPECT_THAT(status, IsOk()); EXPECT_EQ(std::min(read_size, input_size), buf_stream->Position()); EXPECT_EQ(contents.substr(0, read_size), prefix); // The next buffer should contain the rest of the input, if any. pos = buf_stream->Position(); next_result = buf_stream->Next(&buf); if (read_size < input_size) { EXPECT_THAT(next_result, IsOk()); auto next_size = next_result.value(); EXPECT_EQ(input_size - pos, next_size); EXPECT_EQ(input_size, buf_stream->Position()); buf_stream->BackUp(next_size); EXPECT_EQ(pos, buf_stream->Position()); buf_stream->BackUp(input_size); EXPECT_EQ(pos, buf_stream->Position()); } else { EXPECT_EQ(absl::StatusCode::kOutOfRange, next_result.status().code()); } // Read the rest of the input. status = ReadFromStream(buf_stream.get(), &rest); EXPECT_THAT(status, IsOk()); EXPECT_EQ(input_size, buf_stream->Position()); EXPECT_EQ(contents, prefix + rest); } } } TEST(BufferedInputStreamTest, MultipleBackups) { int input_size = 70000; std::string contents = subtle::Random::GetRandomBytes(input_size); auto input_stream = GetInputStream(contents); auto buf_stream = absl::make_unique( std::move(input_stream)); const void* buffer; EXPECT_EQ(0, buf_stream->Position()); auto next_result = buf_stream->Next(&buffer); EXPECT_THAT(next_result, IsOk()); auto next_size = next_result.value(); EXPECT_EQ(contents.substr(0, next_size), std::string(static_cast(buffer), next_size)); // BackUp several times, but in total fewer bytes than returned by Next(). int total_backup_size = 0; for (auto backup_size : {0, 1, 5, 0, 10, 100, -42, 400, 20, -100}) { buf_stream->BackUp(backup_size); total_backup_size += std::max(0, backup_size); EXPECT_EQ(next_size - total_backup_size, buf_stream->Position()); } EXPECT_GT(next_size, total_backup_size); // Call Next(), it should return exactly the backed up bytes. next_result = buf_stream->Next(&buffer); EXPECT_THAT(next_result, IsOk()); EXPECT_EQ(total_backup_size, next_result.value()); EXPECT_EQ(next_size, buf_stream->Position()); EXPECT_EQ(contents.substr(next_size - total_backup_size, total_backup_size), std::string(static_cast(buffer), total_backup_size)); } TEST(BufferedInputStreamTest, DisableRewindingInitially) { for (auto input_size : {0, 10, 100, 1000, 10000}) { std::string contents = subtle::Random::GetRandomBytes(input_size); for (auto read_size : {0, 1, 10, 123, 300, 1024}) { SCOPED_TRACE(absl::StrCat("input_size = ", input_size, ", read_size = ", read_size)); auto input_stream = GetInputStream(contents); auto buf_stream = absl::make_unique( std::move(input_stream)); // Disable rewinding, and attempt rewind. EXPECT_EQ(0, buf_stream->Position()); buf_stream->DisableRewinding(); auto status = buf_stream->Rewind(); EXPECT_THAT(status, StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("rewinding is disabled"))); // Read a prefix of the stream. std::string prefix; status = ReadFromStream(buf_stream.get(), read_size, &prefix); EXPECT_THAT(status, IsOk()); EXPECT_EQ(std::min(read_size, input_size), buf_stream->Position()); EXPECT_EQ(contents.substr(0, read_size), prefix); // Attempt rewidning again. status = buf_stream->Rewind(); EXPECT_THAT(status, StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("rewinding is disabled"))); // Read the rest of the input. std::string rest; status = ReadFromStream(buf_stream.get(), &rest); EXPECT_THAT(status, IsOk()); EXPECT_EQ(input_size, buf_stream->Position()); EXPECT_EQ(contents, prefix + rest); } } } TEST(BufferedInputStreamTest, DisableRewindingAfterRewind) { for (auto input_size : {0, 10, 100, 1000, 10000}) { std::string contents = subtle::Random::GetRandomBytes(input_size); for (auto read_size : {0, 1, 10, 123, 300, 1024}) { SCOPED_TRACE(absl::StrCat("input_size = ", input_size, ", read_size = ", read_size)); auto input_stream = GetInputStream(contents); auto buf_stream = absl::make_unique( std::move(input_stream)); // Read a prefix of the stream. std::string prefix; auto status = ReadFromStream(buf_stream.get(), read_size, &prefix); EXPECT_THAT(status, IsOk()); EXPECT_EQ(std::min(read_size, input_size), buf_stream->Position()); EXPECT_EQ(contents.substr(0, read_size), prefix); // Rewind, and disable rewinding. status = buf_stream->Rewind(); EXPECT_THAT(status, IsOk()); EXPECT_EQ(0, buf_stream->Position()); buf_stream->DisableRewinding(); status = buf_stream->Rewind(); EXPECT_THAT(status, StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("rewinding is disabled"))); // Read the prefix again. status = ReadFromStream(buf_stream.get(), read_size, &prefix); EXPECT_THAT(status, IsOk()); EXPECT_EQ(std::min(read_size, input_size), buf_stream->Position()); EXPECT_EQ(contents.substr(0, read_size), prefix); // Read the rest of the input. std::string rest; status = ReadFromStream(buf_stream.get(), &rest); EXPECT_THAT(status, IsOk()); EXPECT_EQ(input_size, buf_stream->Position()); EXPECT_EQ(contents, prefix + rest); } } } } // namespace } // namespace streamingaead } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/config_v0.h" #include "absl/log/check.h" #include "tink/configuration.h" #include "tink/streamingaead/internal/config_v0.h" namespace crypto { namespace tink { const Configuration& ConfigStreamingAeadV0() { static const Configuration* instance = [] { static Configuration* config = new Configuration(); CHECK_OK(internal::AddStreamingAeadV0(*config)); return config; }(); return *instance; } } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_STREAMINGAEAD_CONFIG_V0_H_ #define TINK_STREAMINGAEAD_CONFIG_V0_H_ #include "tink/configuration.h" namespace crypto { namespace tink { // Configuration used to generate Streaming AEAD primitives with recommended key // managers. const Configuration& ConfigStreamingAeadV0(); } // namespace tink } // namespace crypto #endif // TINK_STREAMINGAEAD_CONFIG_V0_H_ ================================================ FILE: cc/streamingaead/config_v0_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/config_v0.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "tink/input_stream.h" #include "tink/keyset_handle.h" #include "tink/output_stream.h" #include "tink/streaming_aead.h" #include "tink/streamingaead/key_gen_config_v0.h" #include "tink/streamingaead/streaming_aead_key_templates.h" #include "tink/subtle/test_util.h" #include "tink/util/istream_input_stream.h" #include "tink/util/ostream_output_stream.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::subtle::test::ReadFromStream; using ::crypto::tink::subtle::test::WriteToStream; using ::crypto::tink::test::IsOk; using ::google::crypto::tink::KeyTemplate; using ::testing::TestWithParam; using ::testing::Values; using ConfigV0Test = TestWithParam; INSTANTIATE_TEST_SUITE_P( ConfigV0TestSuite, ConfigV0Test, Values(StreamingAeadKeyTemplates::Aes128CtrHmacSha256Segment4KB(), StreamingAeadKeyTemplates::Aes128GcmHkdf4KB())); TEST_P(ConfigV0Test, GetPrimitive) { util::StatusOr> handle = KeysetHandle::GenerateNew(GetParam(), KeyGenConfigStreamingAeadV0()); ASSERT_THAT(handle, IsOk()); util::StatusOr> saead = (*handle)->GetPrimitive(ConfigStreamingAeadV0()); ASSERT_THAT(saead, IsOk()); std::string plaintext = "plaintext"; std::string ad = "ad"; auto ciphertext = absl::make_unique(); std::stringbuf* const ciphertext_buf = ciphertext->rdbuf(); auto ciphertext_out_stream = absl::make_unique(std::move(ciphertext)); util::StatusOr> encrypt = (*saead)->NewEncryptingStream(std::move(ciphertext_out_stream), ad); ASSERT_THAT(encrypt, IsOk()); ASSERT_THAT(WriteToStream((*encrypt).get(), plaintext), IsOk()); auto ciphertext_in = absl::make_unique(ciphertext_buf->str()); auto ciphertext_in_stream = absl::make_unique(std::move(ciphertext_in)); util::StatusOr> decrypt = (*saead)->NewDecryptingStream(std::move(ciphertext_in_stream), ad); ASSERT_THAT(decrypt, IsOk()); std::string got; ASSERT_THAT(ReadFromStream((*decrypt).get(), &got), IsOk()); EXPECT_EQ(got, plaintext); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/decrypting_input_stream.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/decrypting_input_stream.h" #include #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/input_stream.h" #include "tink/primitive_set.h" #include "tink/streaming_aead.h" #include "tink/streamingaead/buffered_input_stream.h" #include "tink/streamingaead/shared_input_stream.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace streamingaead { using crypto::tink::PrimitiveSet; using crypto::tink::StreamingAead; using util::Status; using util::StatusOr; using StreamingAeadEntry = PrimitiveSet::Entry; // static StatusOr> DecryptingInputStream::New( std::shared_ptr> primitives, std::unique_ptr ciphertext_source, absl::string_view associated_data) { auto dec_stream = absl::WrapUnique(new DecryptingInputStream()); dec_stream->primitives_ = primitives; dec_stream->buffered_ct_source_ = std::make_shared(std::move(ciphertext_source)); dec_stream->associated_data_ = std::string(associated_data); dec_stream->attempted_matching_ = false; dec_stream->matching_stream_ = nullptr; return {std::move(dec_stream)}; } util::StatusOr DecryptingInputStream::Next(const void** data) { if (matching_stream_ != nullptr) { return matching_stream_->Next(data); } if (attempted_matching_) { return Status(absl::StatusCode::kInvalidArgument, "Could not find a decrypter matching the ciphertext stream."); } // Matching has not been attempted yet, so try it now. attempted_matching_ = true; std::vector all_primitives = primitives_->get_all(); for (const StreamingAeadEntry* entry : all_primitives) { StreamingAead& streaming_aead = entry->get_primitive(); auto shared_ct = std::make_unique(buffered_ct_source_.get()); auto decrypting_stream_result = streaming_aead.NewDecryptingStream( std::move(shared_ct), associated_data_); if (decrypting_stream_result.ok()) { auto next_result = decrypting_stream_result.value()->Next(data); if (next_result.status().code() == absl::StatusCode::kOutOfRange || next_result.ok()) { // Found a match. buffered_ct_source_->DisableRewinding(); matching_stream_ = std::move(decrypting_stream_result.value()); return next_result; } } // Not a match, rewind and try the next primitive. Status s = buffered_ct_source_->Rewind(); if (!s.ok()) { return s; } } return Status(absl::StatusCode::kInvalidArgument, "Could not find a decrypter matching the ciphertext stream."); } void DecryptingInputStream::BackUp(int count) { if (matching_stream_ != nullptr) { matching_stream_->BackUp(count); } } int64_t DecryptingInputStream::Position() const { if (matching_stream_ != nullptr) { return matching_stream_->Position(); } return 0; } } // namespace streamingaead } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/decrypting_input_stream.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_STREAMINGAEAD_DECRYPTING_INPUT_STREAM_H_ #define TINK_STREAMINGAEAD_DECRYPTING_INPUT_STREAM_H_ #include #include #include #include #include "absl/strings/string_view.h" #include "tink/input_stream.h" #include "tink/primitive_set.h" #include "tink/streaming_aead.h" #include "tink/streamingaead/buffered_input_stream.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace streamingaead { // A wrapper around an InputStream that holds a reference to a // set of StreamingAead-primitives and upon first Next()-call probes the // initial portion of the wrapped InputStream, to find a matching // primitive, i.e. the primitive that is able to decrypt the stream. // Once a match is found, all subsequent calls are forwarded to it. class DecryptingInputStream : public crypto::tink::InputStream { public: // Constructs an InputStream that wraps 'input_stream', and will use // (one of) provided 'primitives' to decrypt the contents of 'input_stream', // using 'associated_data' as authenticated associated data // of the decryption process. static util::StatusOr> New( std::shared_ptr< crypto::tink::PrimitiveSet> primitives, std::unique_ptr ciphertext_source, absl::string_view associated_data); ~DecryptingInputStream() override = default; util::StatusOr Next(const void** data) override; void BackUp(int count) override; int64_t Position() const override; private: DecryptingInputStream() {} std::shared_ptr< crypto::tink::PrimitiveSet> primitives_; std::shared_ptr buffered_ct_source_; std::string associated_data_; std::unique_ptr matching_stream_; bool attempted_matching_; }; } // namespace streamingaead } // namespace tink } // namespace crypto #endif // TINK_STREAMINGAEAD_DECRYPTING_INPUT_STREAM_H_ ================================================ FILE: cc/streamingaead/decrypting_input_stream_test.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/decrypting_input_stream.h" #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/input_stream.h" #include "tink/output_stream.h" #include "tink/primitive_set.h" #include "tink/streaming_aead.h" #include "tink/subtle/random.h" #include "tink/subtle/test_util.h" #include "tink/util/istream_input_stream.h" #include "tink/util/ostream_output_stream.h" #include "tink/util/status.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace streamingaead { namespace { using crypto::tink::test::DummyStreamingAead; using crypto::tink::test::IsOk; using crypto::tink::test::StatusIs; using crypto::tink::util::IstreamInputStream; using crypto::tink::util::OstreamOutputStream; using google::crypto::tink::KeysetInfo; using google::crypto::tink::KeyStatusType; using google::crypto::tink::OutputPrefixType; using subtle::test::ReadFromStream; using subtle::test::WriteToStream; static int kBufferSize = 128; // Creates an InputStream with the specified contents. std::unique_ptr GetInputStream(absl::string_view contents) { // Prepare ciphertext source stream. auto string_stream = absl::make_unique(std::string(contents)); std::unique_ptr input_stream( absl::make_unique( std::move(string_stream), kBufferSize)); return input_stream; } // Creates an InputStream that contains ciphertext resulting // from encryption of 'pt' with 'aad' as associated data, using 'saead'. std::unique_ptr GetCiphertextSource(StreamingAead* saead, absl::string_view pt, absl::string_view aad) { // Prepare ciphertext destination stream. auto ct_stream = absl::make_unique(); // A reference to the ciphertext buffer. auto ct_buf = ct_stream->rdbuf(); std::unique_ptr ct_destination( absl::make_unique(std::move(ct_stream))); // Compute the ciphertext. auto enc_stream_result = saead->NewEncryptingStream(std::move(ct_destination), aad); EXPECT_THAT(enc_stream_result, IsOk()); EXPECT_THAT(WriteToStream(enc_stream_result.value().get(), pt), IsOk()); // Return the ciphertext as InputStream. auto ct_stream3 = absl::make_unique(ct_buf->str()); auto input = absl::make_unique(std::move(ct_stream3)); std::string reads; EXPECT_THAT(ReadFromStream(input.get(), &reads), IsOk()); auto ct_stream2 = absl::make_unique(ct_buf->str()); return absl::make_unique(std::move(ct_stream2)); } // A container for specification of instances of DummyStreamingAead // to be created for testing. struct StreamingAeadSpec { uint32_t key_id; std::string saead_name; }; // Generates a PrimitiveSet with DummyStreamingAead // instances according to the specification in 'spec'. // The last entry in 'spec' will be the primary primitive in the returned set. std::shared_ptr> GetTestStreamingAeadSet( const std::vector& spec) { std::shared_ptr> saead_set = std::make_shared>(); int i = 0; for (auto& s : spec) { KeysetInfo::KeyInfo key_info; key_info.set_output_prefix_type(OutputPrefixType::RAW); key_info.set_key_id(s.key_id); key_info.set_status(KeyStatusType::ENABLED); std::unique_ptr saead = absl::make_unique(s.saead_name); auto entry_result = saead_set->AddPrimitive(std::move(saead), key_info); EXPECT_TRUE(entry_result.ok()); if (i + 1 == spec.size()) { EXPECT_THAT(saead_set->set_primary(entry_result.value()), IsOk()); } i++; } return saead_set; } TEST(DecryptingInputStreamTest, BasicDecryption) { uint32_t key_id_0 = 1234543; uint32_t key_id_1 = 726329; uint32_t key_id_2 = 7213743; std::string saead_name_0 = "streaming_aead0"; std::string saead_name_1 = "streaming_aead1"; std::string saead_name_2 = "streaming_aead2"; auto saead_set = GetTestStreamingAeadSet( {{key_id_0, saead_name_0}, {key_id_1, saead_name_1}, {key_id_2, saead_name_2}}); for (int pt_size : {0, 1, 10, 100, 10000}) { std::string plaintext = subtle::Random::GetRandomBytes(pt_size); for (std::string aad : {"some_aad", "", "some other aad"}) { SCOPED_TRACE(absl::StrCat("pt_size = ", pt_size, ", aad = '", aad, "'")); // Pre-compute ciphertexts. We create one ciphertext for each primitive // in the primitive set, so that we can test decryption with both // the primary primitive, and the non-primary ones. std::vector> ciphertexts; for (const auto& p : *(saead_set->get_raw_primitives().value())) { ciphertexts.push_back( GetCiphertextSource(&(p->get_primitive()), plaintext, aad)); } EXPECT_EQ(3, ciphertexts.size()); // Check the decryption of each of the pre-computed ciphertexts. for (auto& ct : ciphertexts) { // Wrap the primitive set and test the resulting DecryptingInputStream. auto dec_stream_result = DecryptingInputStream::New(saead_set, std::move(ct), aad); EXPECT_THAT(dec_stream_result, IsOk()); std::string decrypted; auto status = ReadFromStream(dec_stream_result.value().get(), &decrypted); EXPECT_THAT(status, IsOk()); EXPECT_EQ(plaintext, decrypted); } } } } TEST(DecryptingInputStreamTest, WrongAssociatedData) { uint32_t key_id_0 = 1234543; uint32_t key_id_1 = 726329; uint32_t key_id_2 = 7213743; std::string saead_name_0 = "streaming_aead0"; std::string saead_name_1 = "streaming_aead1"; std::string saead_name_2 = "streaming_aead2"; auto saead_set = GetTestStreamingAeadSet( {{key_id_0, saead_name_0}, {key_id_1, saead_name_1}, {key_id_2, saead_name_2}}); for (int pt_size : {0, 1, 10, 100, 10000}) { std::string plaintext = subtle::Random::GetRandomBytes(pt_size); for (std::string aad : {"some_aad", "", "some other aad"}) { SCOPED_TRACE(absl::StrCat("pt_size = ", pt_size, ", aad = '", aad, "'")); // Compute a ciphertext with the primary primitive. auto ct = GetCiphertextSource( &(saead_set->get_primary()->get_primitive()), plaintext, aad); auto dec_stream_result = DecryptingInputStream::New(saead_set, std::move(ct), "wrong aad"); EXPECT_THAT(dec_stream_result, IsOk()); std::string decrypted; auto status = ReadFromStream(dec_stream_result.value().get(), &decrypted); EXPECT_THAT(status, StatusIs(absl::StatusCode::kInvalidArgument)); } } } TEST(DecryptingInputStreamTest, WrongCiphertext) { uint32_t key_id_0 = 1234543; uint32_t key_id_1 = 726329; uint32_t key_id_2 = 7213743; std::string saead_name_0 = "streaming_aead0"; std::string saead_name_1 = "streaming_aead1"; std::string saead_name_2 = "streaming_aead2"; auto saead_set = GetTestStreamingAeadSet( {{key_id_0, saead_name_0}, {key_id_1, saead_name_1}, {key_id_2, saead_name_2}}); for (int pt_size : {0, 1, 10, 100, 10000}) { std::string plaintext = subtle::Random::GetRandomBytes(pt_size); for (std::string aad : {"some_aad", "", "some other aad"}) { SCOPED_TRACE(absl::StrCat("pt_size = ", pt_size, ", aad = '", aad, "'")); // Try decrypting a wrong ciphertext. auto wrong_ct = GetInputStream(subtle::Random::GetRandomBytes(pt_size)); auto dec_stream_result = DecryptingInputStream::New(saead_set, std::move(wrong_ct), aad); EXPECT_THAT(dec_stream_result, IsOk()); std::string decrypted; auto status = ReadFromStream(dec_stream_result.value().get(), &decrypted); EXPECT_THAT(status, StatusIs(absl::StatusCode::kInvalidArgument)); } } } } // namespace } // namespace streamingaead } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/decrypting_random_access_stream.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/decrypting_random_access_stream.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" #include "tink/primitive_set.h" #include "tink/random_access_stream.h" #include "tink/streaming_aead.h" #include "tink/streamingaead/shared_random_access_stream.h" #include "tink/util/buffer.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace streamingaead { using crypto::tink::PrimitiveSet; using crypto::tink::StreamingAead; using util::Status; using util::StatusOr; using StreamingAeadEntry = PrimitiveSet::Entry; // static StatusOr> DecryptingRandomAccessStream::New( std::shared_ptr> primitives, std::unique_ptr ciphertext_source, absl::string_view associated_data) { if (primitives == nullptr) { return Status(absl::StatusCode::kInvalidArgument, "primitives must be non-null."); } if (ciphertext_source == nullptr) { return Status(absl::StatusCode::kInvalidArgument, "ciphertext_source must be non-null."); } return {absl::WrapUnique(new DecryptingRandomAccessStream( primitives, std::move(ciphertext_source), associated_data))}; } util::Status DecryptingRandomAccessStream::PRead( int64_t position, int count, crypto::tink::util::Buffer* dest_buffer) { if (dest_buffer == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "dest_buffer must be non-null"); } if (count < 0) { return util::Status(absl::StatusCode::kInvalidArgument, "count cannot be negative"); } if (count > dest_buffer->allocated_size()) { return util::Status(absl::StatusCode::kInvalidArgument, "buffer too small"); } if (position < 0) { return util::Status(absl::StatusCode::kInvalidArgument, "position cannot be negative"); } crypto::tink::util::StatusOr matched_stream = GetMatchedStream(); if (!matched_stream.ok()) { return matched_stream.status(); } return (*matched_stream)->PRead(position, count, dest_buffer); } crypto::tink::util::StatusOr DecryptingRandomAccessStream::GetMatchedStream() const { { absl::ReaderMutexLock lock(&matching_mutex_); if (attempted_matching_) { if (matching_stream_ != nullptr) { return matching_stream_.get(); } return Status(absl::StatusCode::kInvalidArgument, "Did not find a decrypter matching the ciphertext stream."); } } // Matching has not been attempted yet, so try it now. absl::MutexLock lock(&matching_mutex_); // Re-check that matching hasn't been attempted in the meantime. if (attempted_matching_) { if (matching_stream_ != nullptr) { return matching_stream_.get(); } return Status(absl::StatusCode::kInvalidArgument, "Did not find a decrypter matching the ciphertext stream."); } attempted_matching_ = true; std::vector all_primitives = primitives_->get_all(); util::StatusOr> buffer = crypto::tink::util::Buffer::New(1); if (!buffer.ok()) { return buffer.status(); } for (const StreamingAeadEntry* entry : all_primitives) { StreamingAead& streaming_aead = entry->get_primitive(); auto shared_ct = absl::make_unique(ciphertext_source_.get()); auto decrypting_stream_result = streaming_aead.NewDecryptingRandomAccessStream(std::move(shared_ct), associated_data_); if (decrypting_stream_result.ok()) { Status read_result = decrypting_stream_result.value()->PRead(0, 1, buffer->get()); if (read_result.ok() || absl::IsOutOfRange(read_result)) { // Found a match. matching_stream_ = std::move(decrypting_stream_result.value()); return matching_stream_.get(); } } // Not a match, try the next primitive. } return Status(absl::StatusCode::kInvalidArgument, "Could not find a decrypter matching the ciphertext stream."); } StatusOr DecryptingRandomAccessStream::size() { crypto::tink::util::StatusOr matched_stream = GetMatchedStream(); if (!matched_stream.ok()) { return matched_stream.status(); } return (*matched_stream)->size(); } } // namespace streamingaead } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/decrypting_random_access_stream.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_STREAMINGAEAD_DECRYPTING_RANDOM_ACCESS_STREAM_H_ #define TINK_STREAMINGAEAD_DECRYPTING_RANDOM_ACCESS_STREAM_H_ #include #include #include #include #include #include "absl/base/thread_annotations.h" #include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" #include "tink/primitive_set.h" #include "tink/random_access_stream.h" #include "tink/streaming_aead.h" #include "tink/util/buffer.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace streamingaead { // A wrapper around a RandomAccessStream that holds a reference to a // set of StreamingAead-primitives and upon first PRead()-call attempts // to read the stream via the provided primitives to find a matching one, // i.e. the primitive that is able to decrypt the stream. // Once a match is found, all subsequent calls are forwarded to it. class DecryptingRandomAccessStream : public crypto::tink::RandomAccessStream { public: // Constructs an RandomAccessStream that wraps 'random_access_stream', // and will use (one of) provided 'primitives' to decrypt the contents // of 'random_access_stream', using 'associated_data' as authenticated // associated data of the decryption process. static util::StatusOr> New( std::shared_ptr< crypto::tink::PrimitiveSet> primitives, std::unique_ptr ciphertext_source, absl::string_view associated_data); ~DecryptingRandomAccessStream() override = default; crypto::tink::util::Status PRead(int64_t position, int count, crypto::tink::util::Buffer* dest_buffer) override; crypto::tink::util::StatusOr size() override; private: DecryptingRandomAccessStream( std::shared_ptr< crypto::tink::PrimitiveSet> primitives, std::unique_ptr ciphertext_source, absl::string_view associated_data) : primitives_(primitives), ciphertext_source_(std::move(ciphertext_source)), associated_data_(associated_data), attempted_matching_(false), matching_stream_(nullptr) {} crypto::tink::util::StatusOr GetMatchedStream() const; std::shared_ptr< crypto::tink::PrimitiveSet> primitives_; std::unique_ptr ciphertext_source_; std::string associated_data_; mutable absl::Mutex matching_mutex_; mutable bool attempted_matching_ ABSL_GUARDED_BY(matching_mutex_); mutable std::unique_ptr matching_stream_ ABSL_GUARDED_BY(matching_mutex_); }; } // namespace streamingaead } // namespace tink } // namespace crypto #endif // TINK_STREAMINGAEAD_DECRYPTING_RANDOM_ACCESS_STREAM_H_ ================================================ FILE: cc/streamingaead/decrypting_random_access_stream_test.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/decrypting_random_access_stream.h" #include #include #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/internal/test_random_access_stream.h" #include "tink/output_stream.h" #include "tink/primitive_set.h" #include "tink/random_access_stream.h" #include "tink/streaming_aead.h" #include "tink/subtle/random.h" #include "tink/subtle/test_util.h" #include "tink/util/buffer.h" #include "tink/util/ostream_output_stream.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace streamingaead { namespace { using crypto::tink::test::DummyStreamingAead; using crypto::tink::test::IsOk; using crypto::tink::test::IsOkAndHolds; using crypto::tink::test::StatusIs; using google::crypto::tink::KeysetInfo; using google::crypto::tink::KeyStatusType; using google::crypto::tink::OutputPrefixType; using subtle::test::WriteToStream; using testing::HasSubstr; // Creates an RandomAccessStream that contains ciphertext resulting // from encryption of 'pt' with 'aad' as associated data, using 'saead'. std::unique_ptr GetCiphertextSource( StreamingAead* saead, absl::string_view pt, absl::string_view aad) { // Prepare ciphertext destination stream. auto ct_stream = absl::make_unique(); // A reference to the ciphertext buffer. auto ct_buf = ct_stream->rdbuf(); std::unique_ptr ct_destination( absl::make_unique(std::move(ct_stream))); // Compute the ciphertext. auto enc_stream_result = saead->NewEncryptingStream(std::move(ct_destination), aad); EXPECT_THAT(enc_stream_result, IsOk()); EXPECT_THAT(WriteToStream(enc_stream_result.value().get(), pt), IsOk()); // Return the ciphertext as RandomAccessStream. return std::make_unique(ct_buf->str()); } // A container for specification of instances of DummyStreamingAead // to be created for testing. struct StreamingAeadSpec { uint32_t key_id; std::string saead_name; }; // Generates a PrimitiveSet with DummyStreamingAead // instances according to the specification in 'spec'. // The last entry in 'spec' will be the primary primitive in the returned set. std::shared_ptr> GetTestStreamingAeadSet( const std::vector& spec) { std::shared_ptr> saead_set = std::make_shared>(); int i = 0; for (auto& s : spec) { KeysetInfo::KeyInfo key_info; key_info.set_output_prefix_type(OutputPrefixType::RAW); key_info.set_key_id(s.key_id); key_info.set_status(KeyStatusType::ENABLED); std::unique_ptr saead = absl::make_unique(s.saead_name); auto entry_result = saead_set->AddPrimitive(std::move(saead), key_info); EXPECT_TRUE(entry_result.ok()); if (i + 1 == spec.size()) { EXPECT_THAT(saead_set->set_primary(entry_result.value()), IsOk()); } i++; } return saead_set; } TEST(DecryptingRandomAccessStreamTest, BasicDecryption) { uint32_t key_id_0 = 1234543; uint32_t key_id_1 = 726329; uint32_t key_id_2 = 7213743; std::string saead_name_0 = "streaming_aead0"; std::string saead_name_1 = "streaming_aead1"; std::string saead_name_2 = "streaming_aead2"; auto saead_set = GetTestStreamingAeadSet( {{key_id_0, saead_name_0}, {key_id_1, saead_name_1}, {key_id_2, saead_name_2}}); for (int pt_size : {0, 1, 10, 100, 10000}) { std::string plaintext = subtle::Random::GetRandomBytes(pt_size); for (std::string aad : {"some_aad", "", "some other aad"}) { SCOPED_TRACE(absl::StrCat("pt_size = ", pt_size, ", aad = '", aad, "'")); // Pre-compute ciphertexts. We create one ciphertext for each primitive // in the primitive set, so that we can test decryption with both // the primary primitive, and the non-primary ones. std::vector> ciphertexts; for (const auto& p : *(saead_set->get_raw_primitives().value())) { ciphertexts.push_back( GetCiphertextSource(&(p->get_primitive()), plaintext, aad)); } EXPECT_EQ(3, ciphertexts.size()); // Check the decryption of each of the pre-computed ciphertexts. for (auto& ct : ciphertexts) { // Wrap the primitive set and test the resulting // DecryptingRandomAccessStream. auto dec_stream_result = DecryptingRandomAccessStream::New(saead_set, std::move(ct), aad); EXPECT_THAT(dec_stream_result, IsOk()); auto dec_stream = std::move(dec_stream_result.value()); std::string decrypted; auto status = internal::ReadAllFromRandomAccessStream(dec_stream.get(), decrypted); EXPECT_THAT(status, StatusIs(absl::StatusCode::kOutOfRange, HasSubstr("EOF"))); EXPECT_EQ(pt_size, dec_stream->size().value()); EXPECT_EQ(plaintext, decrypted); } } } } TEST(DecryptingRandomAccessStreamTest, SelectiveDecryption) { uint32_t key_id_0 = 1234543; uint32_t key_id_1 = 726329; uint32_t key_id_2 = 7213743; std::string saead_name_0 = "streaming_aead0"; std::string saead_name_1 = "streaming_aead1"; std::string saead_name_2 = "streaming_aead2"; auto saead_set = GetTestStreamingAeadSet( {{key_id_0, saead_name_0}, {key_id_1, saead_name_1}, {key_id_2, saead_name_2}}); for (int pt_size : {5, 10, 100, 10000}) { std::string plaintext = subtle::Random::GetRandomBytes(pt_size); for (std::string aad : {"some_aad", "", "some other aad"}) { SCOPED_TRACE(absl::StrCat("pt_size = ", pt_size, ", aad = '", aad, "'")); // Pre-compute ciphertexts. We create one ciphertext for each primitive // in the primitive set, so that we can test decryption with both // the primary primitive, and the non-primary ones. std::vector> ciphertexts; for (const auto& p : *(saead_set->get_raw_primitives().value())) { ciphertexts.push_back( GetCiphertextSource(&(p->get_primitive()), plaintext, aad)); } EXPECT_EQ(3, ciphertexts.size()); // Check the decryption of each of the pre-computed ciphertexts. int ct_number = 0; for (auto& ct : ciphertexts) { // Wrap the primitive set and test the resulting // DecryptingRandomAccessStream. auto dec_stream_result = DecryptingRandomAccessStream::New(saead_set, std::move(ct), aad); EXPECT_THAT(dec_stream_result, IsOk()); auto dec_stream = std::move(dec_stream_result.value()); for (int position : {0, 1, 2, pt_size/2, pt_size-1}) { for (int chunk_size : {1, pt_size/2, pt_size}) { SCOPED_TRACE(absl::StrCat("ct_number = ", ct_number, ", position = ", position, ", chunk_size = ", chunk_size)); auto buffer = std::move(util::Buffer::New(chunk_size).value()); util::Status status = dec_stream->PRead(position, chunk_size, buffer.get()); EXPECT_THAT(status, testing::AnyOf( IsOk(), StatusIs(absl::StatusCode::kOutOfRange))); EXPECT_EQ(std::min(chunk_size, pt_size - position), buffer->size()); EXPECT_EQ(0, std::memcmp(plaintext.data() + position, buffer->get_mem_block(), buffer->size())); } } ct_number++; } } } } TEST(DecryptingRandomAccessStreamTest, OutOfRangeDecryption) { uint32_t key_id_0 = 1234543; uint32_t key_id_1 = 726329; uint32_t key_id_2 = 7213743; std::string saead_name_0 = "streaming_aead0"; std::string saead_name_1 = "streaming_aead1"; std::string saead_name_2 = "streaming_aead2"; auto saead_set = GetTestStreamingAeadSet( {{key_id_0, saead_name_0}, {key_id_1, saead_name_1}, {key_id_2, saead_name_2}}); for (int pt_size : {1, 5, 10, 100, 10000}) { std::string plaintext = subtle::Random::GetRandomBytes(pt_size); for (std::string aad : {"some_aad", "", "some other aad"}) { SCOPED_TRACE(absl::StrCat("pt_size = ", pt_size, ", aad = '", aad, "'")); // Pre-compute ciphertexts. We create one ciphertext for each primitive // in the primitive set, so that we can test decryption with both // the primary primitive, and the non-primary ones. std::vector> ciphertexts; for (const auto& p : *(saead_set->get_raw_primitives().value())) { ciphertexts.push_back( GetCiphertextSource(&(p->get_primitive()), plaintext, aad)); } EXPECT_EQ(3, ciphertexts.size()); // Check the decryption of each of the pre-computed ciphertexts. int ct_number = 0; for (auto& ct : ciphertexts) { // Wrap the primitive set and test the resulting // DecryptingRandomAccessStream. auto dec_stream_result = DecryptingRandomAccessStream::New(saead_set, std::move(ct), aad); EXPECT_THAT(dec_stream_result, IsOk()); auto dec_stream = std::move(dec_stream_result.value()); int chunk_size = 1; auto buffer = std::move(util::Buffer::New(chunk_size).value()); for (int position : {pt_size, pt_size + 1}) { SCOPED_TRACE(absl::StrCat("ct_number = ", ct_number, ", position = ", position)); // Negative chunk size. auto status = dec_stream->PRead(position, -1, buffer.get()); EXPECT_THAT(status, StatusIs(absl::StatusCode::kInvalidArgument)); // Negative position. status = dec_stream->PRead(-1, chunk_size, buffer.get()); EXPECT_THAT(status, StatusIs(absl::StatusCode::kInvalidArgument)); // Reading past EOF. status = dec_stream->PRead(position, chunk_size, buffer.get()); EXPECT_THAT(status, StatusIs(absl::StatusCode::kOutOfRange)); } ct_number++; } } } } TEST(DecryptingRandomAccessStreamTest, WrongAssociatedData) { uint32_t key_id_0 = 1234543; uint32_t key_id_1 = 726329; uint32_t key_id_2 = 7213743; std::string saead_name_0 = "streaming_aead0"; std::string saead_name_1 = "streaming_aead1"; std::string saead_name_2 = "streaming_aead2"; auto saead_set = GetTestStreamingAeadSet( {{key_id_0, saead_name_0}, {key_id_1, saead_name_1}, {key_id_2, saead_name_2}}); for (int pt_size : {0, 1, 10, 100, 10000}) { std::string plaintext = subtle::Random::GetRandomBytes(pt_size); for (std::string aad : {"some_aad", "", "some other aad"}) { SCOPED_TRACE(absl::StrCat("pt_size = ", pt_size, ", aad = '", aad, "'")); // Compute a ciphertext with the primary primitive. auto ct = GetCiphertextSource( &(saead_set->get_primary()->get_primitive()), plaintext, aad); auto dec_stream_result = DecryptingRandomAccessStream::New( saead_set, std::move(ct), "wrong aad"); EXPECT_THAT(dec_stream_result, IsOk()); std::string decrypted; auto status = internal::ReadAllFromRandomAccessStream( dec_stream_result.value().get(), decrypted); EXPECT_THAT(status, StatusIs(absl::StatusCode::kInvalidArgument)); } } } TEST(DecryptingRandomAccessStreamTest, WrongCiphertext) { uint32_t key_id_0 = 1234543; uint32_t key_id_1 = 726329; uint32_t key_id_2 = 7213743; std::string saead_name_0 = "streaming_aead0"; std::string saead_name_1 = "streaming_aead1"; std::string saead_name_2 = "streaming_aead2"; auto saead_set = GetTestStreamingAeadSet( {{key_id_0, saead_name_0}, {key_id_1, saead_name_1}, {key_id_2, saead_name_2}}); for (int pt_size : {0, 1, 10, 100, 10000}) { std::string plaintext = subtle::Random::GetRandomBytes(pt_size); for (std::string aad : {"some_aad", "", "some other aad"}) { SCOPED_TRACE(absl::StrCat("pt_size = ", pt_size, ", aad = '", aad, "'")); // Try decrypting a wrong ciphertext. auto wrong_ct = std::make_unique( subtle::Random::GetRandomBytes(pt_size)); auto dec_stream_result = DecryptingRandomAccessStream::New( saead_set, std::move(wrong_ct), aad); EXPECT_THAT(dec_stream_result, IsOk()); std::string decrypted; auto status = internal::ReadAllFromRandomAccessStream( dec_stream_result.value().get(), decrypted); EXPECT_THAT(status, StatusIs(absl::StatusCode::kInvalidArgument)); } } } TEST(DecryptingRandomAccessStreamTest, NullPrimitiveSet) { auto ct_stream = std::make_unique( "some ciphertext contents"); auto dec_stream_result = DecryptingRandomAccessStream::New( nullptr, std::move(ct_stream), "some aad"); EXPECT_THAT(dec_stream_result.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("primitives must be non-null"))); } TEST(DecryptingRandomAccessStreamTest, NullCiphertextSource) { uint32_t key_id = 1234543; std::string saead_name = "streaming_aead"; auto saead_set = GetTestStreamingAeadSet({{key_id, saead_name}}); auto dec_stream_result = DecryptingRandomAccessStream::New( saead_set, nullptr, "some aad"); EXPECT_THAT(dec_stream_result.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("ciphertext_source must be non-null"))); } TEST(DecryptingRandomAccessStreamTest, CallSizeBeforePReadWorks) { uint32_t key_id = 1234543; std::string saead_name = "streaming_aead"; auto saead_set = GetTestStreamingAeadSet({{key_id, saead_name}}); std::string associated_data = "associated_data"; for (int pt_size : {0, 1, 100}) { std::string plaintext = subtle::Random::GetRandomBytes(pt_size); std::unique_ptr ciphertext = GetCiphertextSource(&(saead_set->get_primary()->get_primitive()), plaintext, associated_data); util::StatusOr> dec_stream = DecryptingRandomAccessStream::New(saead_set, std::move(ciphertext), associated_data); ASSERT_THAT(dec_stream, IsOk()); EXPECT_THAT((*dec_stream)->size(), IsOkAndHolds(pt_size)); } } } // namespace } // namespace streamingaead } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/internal/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "config_v0", srcs = ["config_v0.cc"], hdrs = ["config_v0.h"], include_prefix = "tink/streamingaead/internal", deps = [ "//:configuration", "//internal:configuration_impl", "//streamingaead:aes_ctr_hmac_streaming_key_manager", "//streamingaead:aes_gcm_hkdf_streaming_key_manager", "//streamingaead:streaming_aead_wrapper", "//util:status", "@com_google_absl//absl/memory", ], ) cc_test( name = "config_v0_test", srcs = ["config_v0_test.cc"], deps = [ ":config_v0", ":key_gen_config_v0", "//:configuration", "//:input_stream", "//:key_gen_configuration", "//:keyset_handle", "//:output_stream", "//:streaming_aead", "//internal:configuration_impl", "//internal:key_gen_configuration_impl", "//internal:key_type_info_store", "//internal:keyset_wrapper_store", "//proto:tink_cc_proto", "//streamingaead:aes_ctr_hmac_streaming_key_manager", "//streamingaead:aes_gcm_hkdf_streaming_key_manager", "//streamingaead:streaming_aead_key_templates", "//subtle:test_util", "//util:istream_input_stream", "//util:ostream_output_stream", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "key_gen_config_v0", srcs = ["key_gen_config_v0.cc"], hdrs = ["key_gen_config_v0.h"], include_prefix = "tink/streamingaead/internal", deps = [ "//:key_gen_configuration", "//internal:key_gen_configuration_impl", "//streamingaead:aes_ctr_hmac_streaming_key_manager", "//streamingaead:aes_gcm_hkdf_streaming_key_manager", "//util:status", "@com_google_absl//absl/memory", ], ) ================================================ FILE: cc/streamingaead/internal/CMakeLists.txt ================================================ tink_module(streamingaead::internal) tink_cc_library( NAME config_v0 SRCS config_v0.cc config_v0.h DEPS absl::memory tink::core::configuration tink::internal::configuration_impl tink::streamingaead::aes_ctr_hmac_streaming_key_manager tink::streamingaead::aes_gcm_hkdf_streaming_key_manager tink::streamingaead::streaming_aead_wrapper tink::util::status ) tink_cc_test( NAME config_v0_test SRCS config_v0_test.cc DEPS tink::streamingaead::internal::config_v0 tink::streamingaead::internal::key_gen_config_v0 gmock absl::memory tink::core::configuration tink::core::input_stream tink::core::key_gen_configuration tink::core::keyset_handle tink::core::output_stream tink::core::streaming_aead tink::internal::configuration_impl tink::internal::key_gen_configuration_impl tink::internal::key_type_info_store tink::internal::keyset_wrapper_store tink::streamingaead::aes_ctr_hmac_streaming_key_manager tink::streamingaead::aes_gcm_hkdf_streaming_key_manager tink::streamingaead::streaming_aead_key_templates tink::subtle::test_util tink::util::istream_input_stream tink::util::ostream_output_stream tink::util::statusor tink::util::test_matchers tink::proto::tink_cc_proto ) tink_cc_library( NAME key_gen_config_v0 SRCS key_gen_config_v0.cc key_gen_config_v0.h DEPS absl::memory tink::core::key_gen_configuration tink::internal::key_gen_configuration_impl tink::streamingaead::aes_ctr_hmac_streaming_key_manager tink::streamingaead::aes_gcm_hkdf_streaming_key_manager tink::util::status ) ================================================ FILE: cc/streamingaead/internal/config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/internal/config_v0.h" #include "absl/memory/memory.h" #include "tink/configuration.h" #include "tink/internal/configuration_impl.h" #include "tink/streamingaead/aes_ctr_hmac_streaming_key_manager.h" #include "tink/streamingaead/aes_gcm_hkdf_streaming_key_manager.h" #include "tink/streamingaead/streaming_aead_wrapper.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { util::Status AddStreamingAeadV0(Configuration& config) { util::Status status = ConfigurationImpl::AddPrimitiveWrapper( absl::make_unique(), config); if (!status.ok()) { return status; } status = ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); if (!status.ok()) { return status; } return ConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/internal/config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_STREAMINGAEAD_INTERNAL_CONFIG_V0_H_ #define TINK_STREAMINGAEAD_INTERNAL_CONFIG_V0_H_ #include "tink/configuration.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { // Add recommended Streaming AEAD primitive wrappers and key managers to // `config`, used to generate primitives. util::Status AddStreamingAeadV0(Configuration& config); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_STREAMINGAEAD_INTERNAL_CONFIG_V0_H_ ================================================ FILE: cc/streamingaead/internal/config_v0_test.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/internal/config_v0.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "tink/configuration.h" #include "tink/input_stream.h" #include "tink/internal/configuration_impl.h" #include "tink/internal/key_gen_configuration_impl.h" #include "tink/internal/key_type_info_store.h" #include "tink/internal/keyset_wrapper_store.h" #include "tink/key_gen_configuration.h" #include "tink/keyset_handle.h" #include "tink/output_stream.h" #include "tink/streaming_aead.h" #include "tink/streamingaead/aes_ctr_hmac_streaming_key_manager.h" #include "tink/streamingaead/aes_gcm_hkdf_streaming_key_manager.h" #include "tink/streamingaead/internal/key_gen_config_v0.h" #include "tink/streamingaead/streaming_aead_key_templates.h" #include "tink/subtle/test_util.h" #include "tink/util/istream_input_stream.h" #include "tink/util/ostream_output_stream.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace internal { namespace { using ::crypto::tink::subtle::test::ReadFromStream; using ::crypto::tink::subtle::test::WriteToStream; using ::crypto::tink::test::IsOk; using ::google::crypto::tink::KeyTemplate; TEST(StreamingAeadV0Test, PrimitiveWrappers) { Configuration config; ASSERT_THAT(AddStreamingAeadV0(config), IsOk()); util::StatusOr store = ConfigurationImpl::GetKeysetWrapperStore(config); ASSERT_THAT(store, IsOk()); EXPECT_THAT((*store)->Get(), IsOk()); } TEST(StreamingAeadV0Test, KeyManagers) { Configuration config; ASSERT_THAT(AddStreamingAeadV0(config), IsOk()); util::StatusOr store = ConfigurationImpl::GetKeyTypeInfoStore(config); ASSERT_THAT(store, IsOk()); KeyGenConfiguration key_gen_config; ASSERT_THAT(AddStreamingAeadKeyGenV0(key_gen_config), IsOk()); util::StatusOr key_gen_store = KeyGenConfigurationImpl::GetKeyTypeInfoStore(key_gen_config); ASSERT_THAT(key_gen_store, IsOk()); for (const KeyTypeInfoStore* s : {*store, *key_gen_store}) { EXPECT_THAT(s->Get(AesCtrHmacStreamingKeyManager().get_key_type()), IsOk()); EXPECT_THAT(s->Get(AesGcmHkdfStreamingKeyManager().get_key_type()), IsOk()); } } TEST(StreamingAeadV0Test, GetPrimitive) { KeyGenConfiguration key_gen_config; ASSERT_THAT(AddStreamingAeadKeyGenV0(key_gen_config), IsOk()); Configuration config; ASSERT_THAT(AddStreamingAeadV0(config), IsOk()); for (const KeyTemplate& temp : {StreamingAeadKeyTemplates::Aes128CtrHmacSha256Segment4KB(), StreamingAeadKeyTemplates::Aes128GcmHkdf4KB()}) { util::StatusOr> handle = KeysetHandle::GenerateNew(temp, key_gen_config); ASSERT_THAT(handle, IsOk()); util::StatusOr> saead = (*handle)->GetPrimitive(config); ASSERT_THAT(saead, IsOk()); std::string plaintext = "plaintext"; std::string ad = "ad"; auto ciphertext = absl::make_unique(); std::stringbuf* const ciphertext_buf = ciphertext->rdbuf(); auto ciphertext_out_stream = absl::make_unique(std::move(ciphertext)); util::StatusOr> encrypt = (*saead)->NewEncryptingStream(std::move(ciphertext_out_stream), ad); ASSERT_THAT(encrypt, IsOk()); ASSERT_THAT(WriteToStream((*encrypt).get(), plaintext), IsOk()); auto ciphertext_in = absl::make_unique(ciphertext_buf->str()); auto ciphertext_in_stream = absl::make_unique(std::move(ciphertext_in)); util::StatusOr> decrypt = (*saead)->NewDecryptingStream(std::move(ciphertext_in_stream), ad); ASSERT_THAT(decrypt, IsOk()); std::string got; ASSERT_THAT(ReadFromStream((*decrypt).get(), &got), IsOk()); EXPECT_EQ(got, plaintext); } } } // namespace } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/internal/key_gen_config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/internal/key_gen_config_v0.h" #include "absl/memory/memory.h" #include "tink/internal/key_gen_configuration_impl.h" #include "tink/key_gen_configuration.h" #include "tink/streamingaead/aes_ctr_hmac_streaming_key_manager.h" #include "tink/streamingaead/aes_gcm_hkdf_streaming_key_manager.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { util::Status AddStreamingAeadKeyGenV0(KeyGenConfiguration& config) { util::Status status = KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); if (!status.ok()) { return status; } return KeyGenConfigurationImpl::AddKeyTypeManager( absl::make_unique(), config); } } // namespace internal } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/internal/key_gen_config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_STREAMINGAEAD_INTERNAL_KEY_GEN_CONFIG_V0_H_ #define TINK_STREAMINGAEAD_INTERNAL_KEY_GEN_CONFIG_V0_H_ #include "tink/key_gen_configuration.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace internal { // Add recommended Streaming AEAD key managers to `config`, used to generate // keys. util::Status AddStreamingAeadKeyGenV0(KeyGenConfiguration& config); } // namespace internal } // namespace tink } // namespace crypto #endif // TINK_STREAMINGAEAD_INTERNAL_KEY_GEN_CONFIG_V0_H_ ================================================ FILE: cc/streamingaead/key_gen_config_v0.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/key_gen_config_v0.h" #include "absl/log/check.h" #include "tink/key_gen_configuration.h" #include "tink/streamingaead/internal/key_gen_config_v0.h" namespace crypto { namespace tink { const KeyGenConfiguration& KeyGenConfigStreamingAeadV0() { static const KeyGenConfiguration* instance = [] { static KeyGenConfiguration* config = new KeyGenConfiguration(); CHECK_OK(internal::AddStreamingAeadKeyGenV0(*config)); return config; }(); return *instance; } } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/key_gen_config_v0.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_STREAMINGAEAD_KEY_GEN_CONFIG_V0_H_ #define TINK_STREAMINGAEAD_KEY_GEN_CONFIG_V0_H_ #include "tink/key_gen_configuration.h" namespace crypto { namespace tink { // KeyGenConfiguration used to generate Streaming AEAD keys with recommended key // managers. const KeyGenConfiguration& KeyGenConfigStreamingAeadV0(); } // namespace tink } // namespace crypto #endif // TINK_STREAMINGAEAD_KEY_GEN_CONFIG_V0_H_ ================================================ FILE: cc/streamingaead/shared_input_stream.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_STREAMINGAEAD_SHARED_INPUT_STREAM_H_ #define TINK_STREAMINGAEAD_SHARED_INPUT_STREAM_H_ #include #include "tink/input_stream.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace streamingaead { // An InputStream that wraps another InputStream as a non-owned pointer. // The wrapper forwards all calls to the wrapped InputStream, // which must remain alive as long as as the wrapper is in use. class SharedInputStream : public crypto::tink::InputStream { public: // Constructs an InputStream that wraps 'input_stream', // and will forward all the method calls to this wrapped stream. explicit SharedInputStream( crypto::tink::InputStream* input_stream) : input_stream_(input_stream) {} ~SharedInputStream() override = default; crypto::tink::util::StatusOr Next(const void** data) override { return input_stream_->Next(data); } void BackUp(int count) override { input_stream_->BackUp(count); } int64_t Position() const override { return input_stream_->Position(); } private: crypto::tink::InputStream* input_stream_; }; } // namespace streamingaead } // namespace tink } // namespace crypto #endif // TINK_STREAMINGAEAD_SHARED_INPUT_STREAM_H_ ================================================ FILE: cc/streamingaead/shared_input_stream_test.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/shared_input_stream.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/input_stream.h" #include "tink/streamingaead/buffered_input_stream.h" #include "tink/subtle/random.h" #include "tink/subtle/test_util.h" #include "tink/util/istream_input_stream.h" #include "tink/util/status.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace streamingaead { namespace { using crypto::tink::test::IsOk; using crypto::tink::test::StatusIs; using subtle::test::ReadFromStream; static int kBufferSize = 4096; // Creates an InputStream with the specified contents. std::unique_ptr GetInputStream(absl::string_view contents) { // Prepare ciphertext source stream. auto string_stream = absl::make_unique(std::string(contents)); std::unique_ptr input_stream( absl::make_unique( std::move(string_stream), kBufferSize)); return input_stream; } // Attempts to read 'count' bytes from 'input_stream', and writes the read // bytes to 'output'. util::Status ReadFromStream(InputStream* input_stream, int count, std::string* output) { if (input_stream == nullptr || output == nullptr || count < 0) { return util::Status(absl::StatusCode::kInternal, "Illegal read from a stream"); } const void* buffer; output->clear(); int bytes_to_read = count; while (bytes_to_read > 0) { auto next_result = input_stream->Next(&buffer); if (next_result.status().code() == absl::StatusCode::kOutOfRange) { // End of stream. return util::OkStatus(); } if (!next_result.ok()) return next_result.status(); auto read_bytes = next_result.value(); auto used_bytes = std::min(read_bytes, bytes_to_read); if (used_bytes > 0) { output->append( std::string(reinterpret_cast(buffer), used_bytes)); bytes_to_read -= used_bytes; if (bytes_to_read == 0) input_stream->BackUp(read_bytes - used_bytes); } } return util::OkStatus(); } TEST(SharedInputStreamTest, BasicOperations) { for (auto input_size : {0, 1, 10, 100, 1000, 10000, 100000}) { std::string contents = subtle::Random::GetRandomBytes(input_size); auto input_stream = GetInputStream(contents); auto buffered_stream = std::make_shared(std::move(input_stream)); for (auto read_size : {0, 1, 10, 123, 300}) { SCOPED_TRACE(absl::StrCat("input_size = ", input_size, ", read_size = ", read_size)); { auto shared_stream = absl::make_unique(buffered_stream.get()); // Read a prefix of the stream. std::string prefix; auto status = ReadFromStream(shared_stream.get(), read_size, &prefix); EXPECT_THAT(status, IsOk()); EXPECT_EQ(std::min(read_size, input_size), shared_stream->Position()); EXPECT_EQ(contents.substr(0, read_size), prefix); EXPECT_EQ(buffered_stream->Position(), shared_stream->Position()); // Read the rest of the stream. std::string rest; status = ReadFromStream(shared_stream.get(), &rest); EXPECT_THAT(status, IsOk()); EXPECT_EQ(input_size, shared_stream->Position()); EXPECT_EQ(contents, prefix + rest); EXPECT_EQ(buffered_stream->Position(), shared_stream->Position()); // Try reading again, should get an empty string. status = ReadFromStream(shared_stream.get(), &rest); EXPECT_THAT(status, IsOk()); EXPECT_EQ("", rest); EXPECT_EQ(buffered_stream->Position(), shared_stream->Position()); } // Now that shared_stream is out of scope, we rewind the underlying // buffered_stream, so that the next read iteration starts from // the beginning. auto status = buffered_stream->Rewind(); EXPECT_THAT(status, IsOk()); EXPECT_EQ(0, buffered_stream->Position()); } } } TEST(SharedInputStreamTest, SingleBackup) { for (auto input_size : {0, 1, 10, 100, 1000, 10000, 100000}) { std::string contents = subtle::Random::GetRandomBytes(input_size); auto input_stream = GetInputStream(contents); auto buffered_stream = std::make_shared(std::move(input_stream)); for (auto read_size : {0, 1, 10, 123, 300, 1024}) { SCOPED_TRACE(absl::StrCat("input_size = ", input_size, ", read_size = ", read_size)); { auto shared_stream = absl::make_unique( buffered_stream.get()); // Read a part of the stream. std::string prefix; auto status = ReadFromStream(shared_stream.get(), read_size, &prefix); EXPECT_THAT(status, IsOk()); EXPECT_EQ(std::min(read_size, input_size), shared_stream->Position()); EXPECT_EQ(contents.substr(0, read_size), prefix); // Read the next block of the stream, and then back it up. const void* buf; int pos = shared_stream->Position(); auto next_result = shared_stream->Next(&buf); if (read_size < input_size) { EXPECT_THAT(next_result, IsOk()); auto next_size = next_result.value(); EXPECT_EQ(pos + next_size, shared_stream->Position()); shared_stream->BackUp(next_size); EXPECT_EQ(pos, shared_stream->Position()); shared_stream->BackUp(input_size); EXPECT_EQ(pos, shared_stream->Position()); } else { EXPECT_THAT(next_result.status(), StatusIs(absl::StatusCode::kOutOfRange)); } // Read the rest of the input. std::string rest; status = ReadFromStream(shared_stream.get(), &rest); EXPECT_THAT(status, IsOk()); EXPECT_EQ(input_size, shared_stream->Position()); EXPECT_EQ(contents, prefix + rest); } // Now that shared_stream is out of scope, we rewind the underlying // buffered_stream, so that the next read iteration starts from // the beginning. auto status = buffered_stream->Rewind(); EXPECT_THAT(status, IsOk()); EXPECT_EQ(0, buffered_stream->Position()); } } } TEST(SharedInputStreamTest, MultipleBackups) { int input_size = 70000; std::string contents = subtle::Random::GetRandomBytes(input_size); auto input_stream = GetInputStream(contents); auto buffered_stream = std::make_shared(std::move(input_stream)); for (int i = 0; i < 2; i++) { // Two rounds, to test with Rewind. auto status = buffered_stream->Rewind(); EXPECT_THAT(status, IsOk()); EXPECT_EQ(0, buffered_stream->Position()); auto shared_stream = absl::make_unique( buffered_stream.get()); EXPECT_EQ(0, shared_stream->Position()); const void* buffer; auto next_result = shared_stream->Next(&buffer); EXPECT_THAT(next_result, IsOk()); auto next_size = next_result.value(); EXPECT_EQ(contents.substr(0, next_size), std::string(static_cast(buffer), next_size)); // BackUp several times, but in total fewer bytes than returned by Next(). int total_backup_size = 0; for (auto backup_size : {0, 1, 5, 0, 10, 100, -42, 400, 20, -100}) { shared_stream->BackUp(backup_size); total_backup_size += std::max(0, backup_size); EXPECT_EQ(next_size - total_backup_size, shared_stream->Position()); EXPECT_EQ(buffered_stream->Position(), shared_stream->Position()); } EXPECT_GT(next_size, total_backup_size); // Call Next(), it should return exactly the backed up bytes. next_result = shared_stream->Next(&buffer); EXPECT_THAT(next_result, IsOk()); EXPECT_EQ(total_backup_size, next_result.value()); EXPECT_EQ(next_size, shared_stream->Position()); EXPECT_EQ(buffered_stream->Position(), shared_stream->Position()); EXPECT_EQ(contents.substr(next_size - total_backup_size, total_backup_size), std::string(static_cast(buffer), total_backup_size)); } } } // namespace } // namespace streamingaead } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/shared_random_access_stream.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_STREAMINGAEAD_SHARED_RANDOM_ACCESS_STREAM_H_ #define TINK_STREAMINGAEAD_SHARED_RANDOM_ACCESS_STREAM_H_ #include #include "tink/random_access_stream.h" #include "tink/util/buffer.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace streamingaead { // A RandomAccessStream that wraps another RandomAccessStream // as a non-owned pointer. // The wrapper forwards all calls to the wrapped RandomAccessStream, // which must remain alive as long as as the wrapper is in use. class SharedRandomAccessStream : public crypto::tink::RandomAccessStream { public: // Constructs an RandomAccessStream that wraps 'random_access_stream', // and will forward all the method calls to this wrapped stream. explicit SharedRandomAccessStream( crypto::tink::RandomAccessStream* random_access_stream) : random_access_stream_(random_access_stream) {} ~SharedRandomAccessStream() override = default; crypto::tink::util::Status PRead( int64_t position, int count, crypto::tink::util::Buffer* dest_buffer) override { return random_access_stream_->PRead(position, count, dest_buffer); } crypto::tink::util::StatusOr size() override { return random_access_stream_->size(); } private: crypto::tink::RandomAccessStream* random_access_stream_; }; } // namespace streamingaead } // namespace tink } // namespace crypto #endif // TINK_STREAMINGAEAD_SHARED_RANDOM_ACCESS_STREAM_H_ ================================================ FILE: cc/streamingaead/shared_random_access_stream_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/shared_random_access_stream.h" #include #include #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/internal/test_random_access_stream.h" #include "tink/random_access_stream.h" #include "tink/subtle/random.h" namespace crypto { namespace tink { namespace streamingaead { namespace { TEST(SharedRandomAccessStreamTest, ReadingStreams) { for (auto stream_size : {0, 10, 100, 1000, 10000, 1000000}) { SCOPED_TRACE(absl::StrCat("stream_size = ", stream_size)); std::string stream_content = subtle::Random::GetRandomBytes(stream_size); auto ra_stream = absl::make_unique(stream_content); SharedRandomAccessStream shared_stream(ra_stream.get()); std::string stream_contents; auto status = internal::ReadAllFromRandomAccessStream( &shared_stream, stream_contents, /*chunk_size=*/1 + (stream_size / 10)); EXPECT_EQ(absl::StatusCode::kOutOfRange, status.code()); EXPECT_EQ("EOF", status.message()); EXPECT_EQ(stream_content, stream_contents); EXPECT_EQ(stream_size, shared_stream.size().value()); } } } // namespace } // namespace streamingaead } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/streaming_aead_config.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/streaming_aead_config.h" #include "absl/memory/memory.h" #include "tink/config/config_util.h" #include "tink/config/tink_fips.h" #include "tink/registry.h" #include "tink/streamingaead/aes_ctr_hmac_streaming_key_manager.h" #include "tink/streamingaead/aes_gcm_hkdf_streaming_key_manager.h" #include "tink/streamingaead/streaming_aead_wrapper.h" #include "tink/util/status.h" namespace crypto { namespace tink { // static util::Status StreamingAeadConfig::Register() { // Register primitive wrapper. auto status = Registry::RegisterPrimitiveWrapper( absl::make_unique()); // Currently there are no streaming encryption key managers which only use // FIPS-validated implementations, therefore none will be registered in if (IsFipsModeEnabled()) { return util::OkStatus(); } status = Registry::RegisterKeyTypeManager( absl::make_unique(), true); if (!status.ok()) return status; status = Registry::RegisterKeyTypeManager( absl::make_unique(), true); if (!status.ok()) return status; return util::OkStatus(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/streaming_aead_config.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_STREAMINGAEAD_STREAMING_AEAD_CONFIG_H_ #define TINK_STREAMINGAEAD_STREAMING_AEAD_CONFIG_H_ #include "absl/base/macros.h" #include "tink/util/status.h" #include "proto/config.pb.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Static methods and constants for registering with the Registry all instances // of StreamingAead key types supported in a particular release of Tink. // // To register all StreamingAead key types from the current Tink release // one can do: // // auto status = StreamingAeadConfig::Register(); // class StreamingAeadConfig { public: // Registers StreamingAead primitive wrapper and key managers for all // StreamingAead key types from the current Tink release. static crypto::tink::util::Status Register(); private: StreamingAeadConfig() {} }; } // namespace tink } // namespace crypto #endif // TINK_STREAMINGAEAD_STREAMING_AEAD_CONFIG_H_ ================================================ FILE: cc/streamingaead/streaming_aead_config_test.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/streaming_aead_config.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/config/global_registry.h" #include "tink/config/tink_fips.h" #include "tink/keyset_handle.h" #include "tink/primitive_set.h" #include "tink/registry.h" #include "tink/streaming_aead.h" #include "tink/streamingaead/aes_ctr_hmac_streaming_key_manager.h" #include "tink/streamingaead/aes_gcm_hkdf_streaming_key_manager.h" #include "tink/streamingaead/streaming_aead_key_templates.h" #include "tink/util/status.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::DummyStreamingAead; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; class StreamingAeadConfigTest : public ::testing::Test { protected: void SetUp() override { Registry::Reset(); } }; TEST_F(StreamingAeadConfigTest, Basic) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EXPECT_THAT(Registry::get_key_manager( AesGcmHkdfStreamingKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT(Registry::get_key_manager( AesCtrHmacStreamingKeyManager().get_key_type()) .status(), StatusIs(absl::StatusCode::kNotFound)); EXPECT_THAT(StreamingAeadConfig::Register(), IsOk()); EXPECT_THAT(Registry::get_key_manager( AesGcmHkdfStreamingKeyManager().get_key_type()) .status(), IsOk()); EXPECT_THAT(Registry::get_key_manager( AesCtrHmacStreamingKeyManager().get_key_type()) .status(), IsOk()); } // Tests that the StreamingAeadWrapper has been properly registered // and we can wrap primitives. TEST_F(StreamingAeadConfigTest, WrappersRegistered) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } ASSERT_TRUE(StreamingAeadConfig::Register().ok()); google::crypto::tink::KeysetInfo::KeyInfo key_info; key_info.set_status(google::crypto::tink::KeyStatusType::ENABLED); key_info.set_key_id(1234); key_info.set_output_prefix_type(google::crypto::tink::OutputPrefixType::RAW); auto primitive_set = absl::make_unique>(); ASSERT_THAT( primitive_set->set_primary( primitive_set ->AddPrimitive(absl::make_unique("dummy"), key_info) .value()), IsOk()); auto primitive_result = Registry::Wrap(std::move(primitive_set)); ASSERT_TRUE(primitive_result.ok()) << primitive_result.status(); } // FIPS-only mode tests TEST_F(StreamingAeadConfigTest, RegisterNonFipsTemplates) { if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Only supported in FIPS-only mode"; } EXPECT_THAT(StreamingAeadConfig::Register(), IsOk()); // Check that we can not retrieve non-FIPS keyset handle std::list non_fips_key_templates; non_fips_key_templates.push_back( StreamingAeadKeyTemplates::Aes128CtrHmacSha256Segment4KB()); non_fips_key_templates.push_back( StreamingAeadKeyTemplates::Aes128GcmHkdf4KB()); non_fips_key_templates.push_back( StreamingAeadKeyTemplates::Aes256CtrHmacSha256Segment4KB()); non_fips_key_templates.push_back( StreamingAeadKeyTemplates::Aes256GcmHkdf1MB()); non_fips_key_templates.push_back( StreamingAeadKeyTemplates::Aes256GcmHkdf4KB()); for (auto key_template : non_fips_key_templates) { EXPECT_THAT( KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()) .status(), StatusIs(absl::StatusCode::kNotFound)); } } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/streaming_aead_key_templates.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/streaming_aead_key_templates.h" #include "proto/aes_ctr_hmac_streaming.pb.h" #include "proto/aes_gcm_hkdf_streaming.pb.h" #include "proto/common.pb.h" #include "proto/hmac.pb.h" #include "proto/tink.pb.h" using google::crypto::tink::AesCtrHmacStreamingKeyFormat; using google::crypto::tink::AesGcmHkdfStreamingKeyFormat; using google::crypto::tink::HashType; using google::crypto::tink::KeyTemplate; using google::crypto::tink::OutputPrefixType; namespace crypto { namespace tink { namespace { KeyTemplate* NewAesGcmHkdfStreamingKeyTemplate(int ikm_size_in_bytes, int segment_size_in_bytes) { KeyTemplate* key_template = new KeyTemplate; key_template->set_type_url( "type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey"); key_template->set_output_prefix_type(OutputPrefixType::RAW); AesGcmHkdfStreamingKeyFormat key_format; key_format.set_key_size(ikm_size_in_bytes); auto params = key_format.mutable_params(); params->set_ciphertext_segment_size(segment_size_in_bytes); params->set_derived_key_size(ikm_size_in_bytes); params->set_hkdf_hash_type(HashType::SHA256); key_format.SerializeToString(key_template->mutable_value()); return key_template; } KeyTemplate* NewAesCtrHmacStreamingKeyTemplate(int ikm_size_in_bytes, int segment_size_in_bytes) { KeyTemplate* key_template = new KeyTemplate; key_template->set_type_url( "type.googleapis.com/google.crypto.tink.AesCtrHmacStreamingKey"); key_template->set_output_prefix_type(OutputPrefixType::RAW); AesCtrHmacStreamingKeyFormat key_format; key_format.set_key_size(ikm_size_in_bytes); auto params = key_format.mutable_params(); params->set_ciphertext_segment_size(segment_size_in_bytes); params->set_derived_key_size(ikm_size_in_bytes); params->set_hkdf_hash_type(HashType::SHA256); auto hmac_params = params->mutable_hmac_params(); hmac_params->set_hash(HashType::SHA256); hmac_params->set_tag_size(32); key_format.SerializeToString(key_template->mutable_value()); return key_template; } } // anonymous namespace // static const KeyTemplate& StreamingAeadKeyTemplates::Aes128GcmHkdf4KB() { static const KeyTemplate* key_template = NewAesGcmHkdfStreamingKeyTemplate( /* ikm_size_in_bytes= */ 16, /* segment_size_in_bytes= */ 4096); return *key_template; } // static const KeyTemplate& StreamingAeadKeyTemplates::Aes256GcmHkdf4KB() { static const KeyTemplate* key_template = NewAesGcmHkdfStreamingKeyTemplate( /* ikm_size_in_bytes= */ 32, /* segment_size_in_bytes= */ 4096); return *key_template; } // static const KeyTemplate& StreamingAeadKeyTemplates::Aes256GcmHkdf1MB() { static const KeyTemplate* key_template = NewAesGcmHkdfStreamingKeyTemplate( /* ikm_size_in_bytes= */ 32, /* segment_size_in_bytes= */ 1048576); return *key_template; } // static const KeyTemplate& StreamingAeadKeyTemplates::Aes128CtrHmacSha256Segment4KB() { static const KeyTemplate* key_template = NewAesCtrHmacStreamingKeyTemplate( /* ikm_size_in_bytes= */ 16, /* segment_size_in_bytes= */ 4096); return *key_template; } // static const KeyTemplate& StreamingAeadKeyTemplates::Aes128CtrHmacSha256Segment1MB() { static const KeyTemplate* key_template = NewAesCtrHmacStreamingKeyTemplate( /* ikm_size_in_bytes= */ 16, /* segment_size_in_bytes= */ 1048576); return *key_template; } // static const KeyTemplate& StreamingAeadKeyTemplates::Aes256CtrHmacSha256Segment4KB() { static const KeyTemplate* key_template = NewAesCtrHmacStreamingKeyTemplate( /* ikm_size_in_bytes= */ 32, /* segment_size_in_bytes= */ 4096); return *key_template; } // static const KeyTemplate& StreamingAeadKeyTemplates::Aes256CtrHmacSha256Segment1MB() { static const KeyTemplate* key_template = NewAesCtrHmacStreamingKeyTemplate( /* ikm_size_in_bytes= */ 32, /* segment_size_in_bytes= */ 1048576); return *key_template; } } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/streaming_aead_key_templates.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_STREAMINGAEAD_STREAMING_AEAD_KEY_TEMPLATES_H_ #define TINK_STREAMINGAEAD_STREAMING_AEAD_KEY_TEMPLATES_H_ #include "proto/tink.pb.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Pre-generated KeyTemplate for StreamingAead key types. One can use these // templates to generate new KeysetHandle object with fresh keys. // To generate a new keyset that contains a single AesGcmKey, one can do: // // auto status = StreamingAeadConfig::Register(); // if (!status.ok()) { /* fail with error */ } // auto handle_result = KeysetHandle::GenerateNew( // StreamingAeadKeyTemplates::Aes128GcmHkdf4KB()); // if (!handle_result.ok()) { /* fail with error */ } // auto keyset_handle = std::move(handle_result.value()); class StreamingAeadKeyTemplates { public: // Returns a KeyTemplate that generates new instances of // AesGcmHkdfStreamingKey with the following parameters: // - main key (ikm) size: 16 bytes // - HKDF algorithm: HMAC-SHA256 // - size of derived AES-GCM keys: 16 bytes // - ciphertext segment size: 4096 bytes // - OutputPrefixType: RAW static const google::crypto::tink::KeyTemplate& Aes128GcmHkdf4KB(); // Returns a KeyTemplate that generates new instances of // AesGcmHkdfStreamingKey with the following parameters: // - main key (ikm) size: 32 bytes // - HKDF algorithm: HMAC-SHA256 // - size of derived AES-GCM keys: 32 bytes // - ciphertext segment size: 4096 bytes // - OutputPrefixType: RAW static const google::crypto::tink::KeyTemplate& Aes256GcmHkdf4KB(); // Returns a KeyTemplate that generates new instances of // AesGcmHkdfStreamingKey with the following parameters: // - main key (ikm) size: 32 bytes // - HKDF algorithm: HMAC-SHA256 // - size of derived AES-GCM keys: 32 bytes // - ciphertext segment size: 1048576 bytes (1 MB) // - OutputPrefixType: RAW static const google::crypto::tink::KeyTemplate& Aes256GcmHkdf1MB(); // Returns a KeyTemplate that generates new instances of // AesCtrHmacStreamingKey with the following parameters: // - main key (ikm) size: 16 bytes // - HKDF algorithm: HMAC-SHA256 // - size of derived AES-CTR keys: 16 bytes // - tag algorithm: HMAC-SHA256 // - tag size: 32 bytes // - ciphertext segment size: 4096 bytes // - OutputPrefixType: RAW static const google::crypto::tink::KeyTemplate& Aes128CtrHmacSha256Segment4KB(); // Returns a KeyTemplate that generates new instances of // AesCtrHmacStreamingKey with the following parameters: // - main key (ikm) size: 16 bytes // - HKDF algorithm: HMAC-SHA256 // - size of derived AES-CTR keys: 16 bytes // - tag algorithm: HMAC-SHA256 // - tag size: 32 bytes // - ciphertext segment size: 1048576 bytes (1 MB) // - OutputPrefixType: RAW static const google::crypto::tink::KeyTemplate& Aes128CtrHmacSha256Segment1MB(); // Returns a KeyTemplate that generates new instances of // AesCtrHmacStreamingKey with the following parameters: // - main key (ikm) size: 32 bytes // - HKDF algorithm: HMAC-SHA256 // - size of derived AES-CTR keys: 32 bytes // - tag algorithm: HMAC-SHA256 // - tag size: 32 bytes // - ciphertext segment size: 4096 bytes // - OutputPrefixType: RAW static const google::crypto::tink::KeyTemplate& Aes256CtrHmacSha256Segment4KB(); // Returns a KeyTemplate that generates new instances of // AesCtrHmacStreamingKey with the following parameters: // - main key (ikm) size: 32 bytes // - HKDF algorithm: HMAC-SHA256 // - size of derived AES-CTR keys: 32 bytes // - tag algorithm: HMAC-SHA256 // - tag size: 32 bytes // - ciphertext segment size: 1048576 bytes (1 MB) // - OutputPrefixType: RAW static const google::crypto::tink::KeyTemplate& Aes256CtrHmacSha256Segment1MB(); }; } // namespace tink } // namespace crypto #endif // TINK_STREAMINGAEAD_STREAMING_AEAD_KEY_TEMPLATES_H_ ================================================ FILE: cc/streamingaead/streaming_aead_key_templates_test.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/streaming_aead_key_templates.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/streamingaead/aes_ctr_hmac_streaming_key_manager.h" #include "tink/streamingaead/aes_gcm_hkdf_streaming_key_manager.h" #include "tink/util/test_matchers.h" #include "proto/aes_ctr_hmac_streaming.pb.h" #include "proto/aes_gcm_hkdf_streaming.pb.h" #include "proto/common.pb.h" #include "proto/tink.pb.h" using google::crypto::tink::AesCtrHmacStreamingKeyFormat; using google::crypto::tink::AesGcmHkdfStreamingKeyFormat; using google::crypto::tink::HashType; using google::crypto::tink::KeyTemplate; using google::crypto::tink::OutputPrefixType; namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::testing::Eq; using ::testing::Ref; TEST(Aes128GcmHkdf4KBTest, TypeUrl) { EXPECT_THAT( StreamingAeadKeyTemplates::Aes128GcmHkdf4KB().type_url(), Eq("type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey")); EXPECT_THAT(StreamingAeadKeyTemplates::Aes128GcmHkdf4KB().type_url(), Eq(AesGcmHkdfStreamingKeyManager().get_key_type())); } TEST(Aes128GcmHkdf4KBTest, OutputPrefixType) { EXPECT_THAT( StreamingAeadKeyTemplates::Aes128GcmHkdf4KB().output_prefix_type(), Eq(OutputPrefixType::RAW)); } TEST(Aes128GcmHkdf4KBTest, SameReference) { // Check that reference to the same object is returned. EXPECT_THAT(StreamingAeadKeyTemplates::Aes128GcmHkdf4KB(), Ref(StreamingAeadKeyTemplates::Aes128GcmHkdf4KB())); } TEST(Aes128GcmHkdf4KBTest, WorksWithKeyTypeManager) { const KeyTemplate& key_template = StreamingAeadKeyTemplates::Aes128GcmHkdf4KB(); AesGcmHkdfStreamingKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(AesGcmHkdfStreamingKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(Aes128GcmHkdf4KBTest, CheckValues) { const KeyTemplate& key_template = StreamingAeadKeyTemplates::Aes128GcmHkdf4KB(); AesGcmHkdfStreamingKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(key_format.key_size(), Eq(16)); EXPECT_THAT(key_format.params().derived_key_size(), Eq(16)); EXPECT_THAT(key_format.params().ciphertext_segment_size(), Eq(4096)); EXPECT_THAT(key_format.params().hkdf_hash_type(), Eq(HashType::SHA256)); } TEST(Aes256GcmHkdf4KBTest, TypeUrl) { EXPECT_THAT( StreamingAeadKeyTemplates::Aes256GcmHkdf4KB().type_url(), Eq("type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey")); EXPECT_THAT(StreamingAeadKeyTemplates::Aes256GcmHkdf4KB().type_url(), Eq(AesGcmHkdfStreamingKeyManager().get_key_type())); } TEST(Aes256GcmHkdf4KBTest, OutputPrefixType) { EXPECT_THAT( StreamingAeadKeyTemplates::Aes256GcmHkdf4KB().output_prefix_type(), Eq(OutputPrefixType::RAW)); } TEST(Aes256GcmHkdf4KBTest, SameReference) { // Check that reference to the same object is returned. EXPECT_THAT(StreamingAeadKeyTemplates::Aes256GcmHkdf4KB(), Ref(StreamingAeadKeyTemplates::Aes256GcmHkdf4KB())); } TEST(Aes256GcmHkdf4KBTest, WorksWithKeyTypeManager) { const KeyTemplate& key_template = StreamingAeadKeyTemplates::Aes256GcmHkdf4KB(); AesGcmHkdfStreamingKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(AesGcmHkdfStreamingKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(Aes256GcmHkdf4KBTest, CheckValues) { const KeyTemplate& key_template = StreamingAeadKeyTemplates::Aes256GcmHkdf4KB(); AesGcmHkdfStreamingKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(key_format.key_size(), Eq(32)); EXPECT_THAT(key_format.params().derived_key_size(), Eq(32)); EXPECT_THAT(key_format.params().ciphertext_segment_size(), Eq(4096)); EXPECT_THAT(key_format.params().hkdf_hash_type(), Eq(HashType::SHA256)); } TEST(Aes256GcmHkdf1MBTest, TypeUrl) { EXPECT_THAT( StreamingAeadKeyTemplates::Aes256GcmHkdf1MB().type_url(), Eq("type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey")); EXPECT_THAT(StreamingAeadKeyTemplates::Aes256GcmHkdf1MB().type_url(), Eq(AesGcmHkdfStreamingKeyManager().get_key_type())); } TEST(Aes256GcmHkdf1MBTest, OutputPrefixType) { EXPECT_THAT( StreamingAeadKeyTemplates::Aes256GcmHkdf1MB().output_prefix_type(), Eq(OutputPrefixType::RAW)); } TEST(Aes256GcmHkdf1MBTest, SameReference) { // Check that reference to the same object is returned. EXPECT_THAT(StreamingAeadKeyTemplates::Aes256GcmHkdf1MB(), Ref(StreamingAeadKeyTemplates::Aes256GcmHkdf1MB())); } TEST(Aes256GcmHkdf1MBTest, WorksWithKeyTypeManager) { const KeyTemplate& key_template = StreamingAeadKeyTemplates::Aes256GcmHkdf1MB(); AesGcmHkdfStreamingKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(AesGcmHkdfStreamingKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(Aes256GcmHkdf1MBTest, CheckValues) { const KeyTemplate& key_template = StreamingAeadKeyTemplates::Aes256GcmHkdf1MB(); AesGcmHkdfStreamingKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(key_format.key_size(), Eq(32)); EXPECT_THAT(key_format.params().derived_key_size(), Eq(32)); EXPECT_THAT(key_format.params().ciphertext_segment_size(), Eq(1048576)); EXPECT_THAT(key_format.params().hkdf_hash_type(), Eq(HashType::SHA256)); } TEST(Aes128CtrHmacSha256Segment4KBTest, TypeUrl) { EXPECT_THAT( StreamingAeadKeyTemplates::Aes128CtrHmacSha256Segment4KB().type_url(), Eq("type.googleapis.com/google.crypto.tink.AesCtrHmacStreamingKey")); EXPECT_THAT( StreamingAeadKeyTemplates::Aes128CtrHmacSha256Segment4KB().type_url(), Eq(AesCtrHmacStreamingKeyManager().get_key_type())); } TEST(Aes128CtrHmacSha256Segment4KBTest, OutputPrefixType) { EXPECT_THAT(StreamingAeadKeyTemplates::Aes128CtrHmacSha256Segment4KB() .output_prefix_type(), Eq(OutputPrefixType::RAW)); } TEST(Aes128CtrHmacSha256Segment4KBTest, SameReference) { // Check that reference to the same object is returned. EXPECT_THAT(StreamingAeadKeyTemplates::Aes128CtrHmacSha256Segment4KB(), Ref(StreamingAeadKeyTemplates::Aes128CtrHmacSha256Segment4KB())); } TEST(Aes128CtrHmacSha256Segment4KBTest, WorksWithKeyTypeManager) { const KeyTemplate& key_template = StreamingAeadKeyTemplates::Aes128CtrHmacSha256Segment4KB(); AesCtrHmacStreamingKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(AesCtrHmacStreamingKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(Aes128CtrHmacSha256Segment4KBTest, CheckValues) { const KeyTemplate& key_template = StreamingAeadKeyTemplates::Aes128CtrHmacSha256Segment4KB(); AesCtrHmacStreamingKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(key_format.key_size(), Eq(16)); EXPECT_THAT(key_format.params().ciphertext_segment_size(), Eq(4096)); EXPECT_THAT(key_format.params().derived_key_size(), Eq(16)); EXPECT_THAT(key_format.params().hkdf_hash_type(), Eq(HashType::SHA256)); EXPECT_THAT(key_format.params().hmac_params().hash(), Eq(HashType::SHA256)); EXPECT_THAT(key_format.params().hmac_params().tag_size(), Eq(32)); } TEST(Aes128CtrHmacSha256Segment1MBTest, TypeUrl) { EXPECT_THAT( StreamingAeadKeyTemplates::Aes128CtrHmacSha256Segment1MB().type_url(), Eq("type.googleapis.com/google.crypto.tink.AesCtrHmacStreamingKey")); EXPECT_THAT( StreamingAeadKeyTemplates::Aes128CtrHmacSha256Segment1MB().type_url(), Eq(AesCtrHmacStreamingKeyManager().get_key_type())); } TEST(Aes128CtrHmacSha256Segment1MBTest, OutputPrefixType) { EXPECT_THAT(StreamingAeadKeyTemplates::Aes128CtrHmacSha256Segment1MB() .output_prefix_type(), Eq(OutputPrefixType::RAW)); } TEST(Aes128CtrHmacSha256Segment1MBTest, SameReference) { // Check that reference to the same object is returned. EXPECT_THAT(StreamingAeadKeyTemplates::Aes128CtrHmacSha256Segment1MB(), Ref(StreamingAeadKeyTemplates::Aes128CtrHmacSha256Segment1MB())); } TEST(Aes128CtrHmacSha256Segment1MBTest, WorksWithKeyTypeManager) { const KeyTemplate& key_template = StreamingAeadKeyTemplates::Aes128CtrHmacSha256Segment1MB(); AesCtrHmacStreamingKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(AesCtrHmacStreamingKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(Aes128CtrHmacSha256Segment1MBTest, CheckValues) { const KeyTemplate& key_template = StreamingAeadKeyTemplates::Aes128CtrHmacSha256Segment1MB(); AesCtrHmacStreamingKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(key_format.key_size(), Eq(16)); EXPECT_THAT(key_format.params().ciphertext_segment_size(), Eq(1048576)); EXPECT_THAT(key_format.params().derived_key_size(), Eq(16)); EXPECT_THAT(key_format.params().hkdf_hash_type(), Eq(HashType::SHA256)); EXPECT_THAT(key_format.params().hmac_params().hash(), Eq(HashType::SHA256)); EXPECT_THAT(key_format.params().hmac_params().tag_size(), Eq(32)); } TEST(Aes256CtrHmacSha256Segment4KBTest, TypeUrl) { EXPECT_THAT( StreamingAeadKeyTemplates::Aes256CtrHmacSha256Segment4KB().type_url(), Eq("type.googleapis.com/google.crypto.tink.AesCtrHmacStreamingKey")); EXPECT_THAT( StreamingAeadKeyTemplates::Aes256CtrHmacSha256Segment4KB().type_url(), Eq(AesCtrHmacStreamingKeyManager().get_key_type())); } TEST(Aes256CtrHmacSha256Segment4KBTest, OutputPrefixType) { EXPECT_THAT(StreamingAeadKeyTemplates::Aes256CtrHmacSha256Segment4KB() .output_prefix_type(), Eq(OutputPrefixType::RAW)); } TEST(Aes256CtrHmacSha256Segment4KBTest, SameReference) { // Check that reference to the same object is returned. EXPECT_THAT(StreamingAeadKeyTemplates::Aes256CtrHmacSha256Segment4KB(), Ref(StreamingAeadKeyTemplates::Aes256CtrHmacSha256Segment4KB())); } TEST(Aes256CtrHmacSha256Segment4KBTest, WorksWithKeyTypeManager) { const KeyTemplate& key_template = StreamingAeadKeyTemplates::Aes256CtrHmacSha256Segment4KB(); AesCtrHmacStreamingKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(AesCtrHmacStreamingKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(Aes256CtrHmacSha256Segment4KBTest, CheckValues) { const KeyTemplate& key_template = StreamingAeadKeyTemplates::Aes256CtrHmacSha256Segment4KB(); AesCtrHmacStreamingKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(key_format.key_size(), Eq(32)); EXPECT_THAT(key_format.params().ciphertext_segment_size(), Eq(4096)); EXPECT_THAT(key_format.params().derived_key_size(), Eq(32)); EXPECT_THAT(key_format.params().hkdf_hash_type(), Eq(HashType::SHA256)); EXPECT_THAT(key_format.params().hmac_params().hash(), Eq(HashType::SHA256)); EXPECT_THAT(key_format.params().hmac_params().tag_size(), Eq(32)); } TEST(Aes256CtrHmacSha256Segment1MBTest, TypeUrl) { EXPECT_THAT( StreamingAeadKeyTemplates::Aes256CtrHmacSha256Segment1MB().type_url(), Eq("type.googleapis.com/google.crypto.tink.AesCtrHmacStreamingKey")); EXPECT_THAT( StreamingAeadKeyTemplates::Aes256CtrHmacSha256Segment1MB().type_url(), Eq(AesCtrHmacStreamingKeyManager().get_key_type())); } TEST(Aes256CtrHmacSha256Segment1MBTest, OutputPrefixType) { EXPECT_THAT(StreamingAeadKeyTemplates::Aes256CtrHmacSha256Segment1MB() .output_prefix_type(), Eq(OutputPrefixType::RAW)); } TEST(Aes256CtrHmacSha256Segment1MBTest, SameReference) { // Check that reference to the same object is returned. EXPECT_THAT(StreamingAeadKeyTemplates::Aes256CtrHmacSha256Segment1MB(), Ref(StreamingAeadKeyTemplates::Aes256CtrHmacSha256Segment1MB())); } TEST(Aes256CtrHmacSha256Segment1MBTest, WorksWithKeyTypeManager) { const KeyTemplate& key_template = StreamingAeadKeyTemplates::Aes256CtrHmacSha256Segment1MB(); AesCtrHmacStreamingKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(AesCtrHmacStreamingKeyManager().ValidateKeyFormat(key_format), IsOk()); } TEST(Aes256CtrHmacSha256Segment1MBTest, CheckValues) { const KeyTemplate& key_template = StreamingAeadKeyTemplates::Aes256CtrHmacSha256Segment1MB(); AesCtrHmacStreamingKeyFormat key_format; EXPECT_TRUE(key_format.ParseFromString(key_template.value())); EXPECT_THAT(key_format.key_size(), Eq(32)); EXPECT_THAT(key_format.params().ciphertext_segment_size(), Eq(1048576)); EXPECT_THAT(key_format.params().derived_key_size(), Eq(32)); EXPECT_THAT(key_format.params().hkdf_hash_type(), Eq(HashType::SHA256)); EXPECT_THAT(key_format.params().hmac_params().hash(), Eq(HashType::SHA256)); EXPECT_THAT(key_format.params().hmac_params().tag_size(), Eq(32)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/streaming_aead_wrapper.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/streaming_aead_wrapper.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/crypto_format.h" #include "tink/input_stream.h" #include "tink/output_stream.h" #include "tink/primitive_set.h" #include "tink/random_access_stream.h" #include "tink/streaming_aead.h" #include "tink/streamingaead/decrypting_input_stream.h" #include "tink/streamingaead/decrypting_random_access_stream.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; namespace { Status Validate(PrimitiveSet* primitives) { if (primitives == nullptr) { return Status(absl::StatusCode::kInternal, "primitive set must be non-NULL"); } if (primitives->get_primary() == nullptr) { return Status(absl::StatusCode::kInvalidArgument, "primitive set has no primary"); } return util::OkStatus(); } class StreamingAeadSetWrapper: public StreamingAead { public: explicit StreamingAeadSetWrapper( std::unique_ptr> primitives) : primitives_(std::move(primitives)) {} crypto::tink::util::StatusOr> NewEncryptingStream( std::unique_ptr ciphertext_destination, absl::string_view associated_data) const override; crypto::tink::util::StatusOr> NewDecryptingStream( std::unique_ptr ciphertext_source, absl::string_view associated_data) const override; crypto::tink::util::StatusOr< std::unique_ptr> NewDecryptingRandomAccessStream( std::unique_ptr ciphertext_source, absl::string_view associated_data) const override; ~StreamingAeadSetWrapper() override = default; private: // We use a shared_ptr here to ensure that primitives_ stays alive // as long as it might be needed by some decrypting stream returned // by NewDecryptingStream. This can happen after this wrapper // is destroyed, as we refer to primitives_ only when the user attempts // to read some data from the decrypting stream. std::shared_ptr> primitives_; }; // class StreamingAeadSetWrapper StatusOr> StreamingAeadSetWrapper::NewEncryptingStream( std::unique_ptr ciphertext_destination, absl::string_view associated_data) const { return primitives_->get_primary()->get_primitive().NewEncryptingStream( std::move(ciphertext_destination), associated_data); } StatusOr> StreamingAeadSetWrapper::NewDecryptingStream( std::unique_ptr ciphertext_source, absl::string_view associated_data) const { return {streamingaead::DecryptingInputStream::New( primitives_, std::move(ciphertext_source), associated_data)}; } StatusOr> StreamingAeadSetWrapper::NewDecryptingRandomAccessStream( std::unique_ptr ciphertext_source, absl::string_view associated_data) const { return {streamingaead::DecryptingRandomAccessStream::New( primitives_, std::move(ciphertext_source), associated_data)}; } } // anonymous namespace StatusOr> StreamingAeadWrapper::Wrap( std::unique_ptr> streaming_aead_set) const { auto status = Validate(streaming_aead_set.get()); if (!status.ok()) return status; std::unique_ptr streaming_aead = absl::make_unique( std::move(streaming_aead_set)); return std::move(streaming_aead); } } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/streaming_aead_wrapper.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_STREAMINGAEAD_STREAMING_AEAD_WRAPPER_H_ #define TINK_STREAMINGAEAD_STREAMING_AEAD_WRAPPER_H_ #include #include "absl/strings/string_view.h" #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/streaming_aead.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // Wraps a set of StreamingAead-instances that correspond to a keyset, // and combines them into a single StreamingAead-primitive, that uses // the provided instances, depending on the context: // * StreamingAead::NewEncryptingStream(...) uses the primary instance // from the set // * StreamingAead::NewDecryptingStream(...) uses the instance that matches // the ciphertext prefix. class StreamingAeadWrapper : public PrimitiveWrapper { public: // Returns a StreamingAead-primitive that uses StreamingAead-instances // provided in 'streaming_aead_set', which must be non-NULL and must contain // a primary instance. util::StatusOr> Wrap( std::unique_ptr> streaming_aead_set) const override; }; } // namespace tink } // namespace crypto #endif // TINK_STREAMINGAEAD_STREAMING_AEAD_WRAPPER_H_ ================================================ FILE: cc/streamingaead/streaming_aead_wrapper_test.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/streamingaead/streaming_aead_wrapper.h" #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/config/global_registry.h" #include "tink/input_stream.h" #include "tink/insecure_secret_key_access.h" #include "tink/internal/test_random_access_stream.h" #include "tink/keyset_handle.h" #include "tink/output_stream.h" #include "tink/primitive_set.h" #include "tink/proto_keyset_format.h" #include "tink/random_access_stream.h" #include "tink/streaming_aead.h" #include "tink/streamingaead/aes_gcm_hkdf_streaming_key_manager.h" #include "tink/streamingaead/streaming_aead_config.h" #include "tink/subtle/random.h" #include "tink/subtle/streaming_aead_test_util.h" #include "tink/subtle/test_util.h" #include "tink/util/buffer.h" #include "tink/util/istream_input_stream.h" #include "tink/util/ostream_output_stream.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/aes_gcm_hkdf_streaming.pb.h" #include "proto/common.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::internal::ReadAllFromRandomAccessStream; using ::crypto::tink::subtle::test::ReadFromStream; using ::crypto::tink::subtle::test::WriteToStream; using ::crypto::tink::test::DummyStreamingAead; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::IstreamInputStream; using ::google::crypto::tink::KeysetInfo; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::OutputPrefixType; using ::testing::HasSubstr; // A container for specification of instances of DummyStreamingAead // to be created for testing. struct StreamingAeadSpec { uint32_t key_id; std::string saead_name; OutputPrefixType output_prefix_type; }; // Generates a PrimitiveSet with DummyStreamingAead // instances according to the specification in 'spec'. // The last entry in 'spec' will be the primary primitive in the returned set. std::unique_ptr> GetTestStreamingAeadSet( const std::vector& spec) { auto saead_set = absl::make_unique>(); int i = 0; for (auto& s : spec) { KeysetInfo::KeyInfo key_info; key_info.set_output_prefix_type(s.output_prefix_type); key_info.set_key_id(s.key_id); key_info.set_status(KeyStatusType::ENABLED); std::unique_ptr saead = absl::make_unique(s.saead_name); auto entry_result = saead_set->AddPrimitive(std::move(saead), key_info); EXPECT_TRUE(entry_result.ok()); if (i + 1 == spec.size()) { EXPECT_THAT(saead_set->set_primary(entry_result.value()), IsOk()); } i++; } return saead_set; } TEST(StreamingAeadSetWrapperTest, WrapNullptr) { StreamingAeadWrapper wrapper; auto result = wrapper.Wrap(nullptr); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInternal, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "non-NULL", std::string(result.status().message())); } TEST(StreamingAeadSetWrapperTest, WrapEmpty) { StreamingAeadWrapper wrapper; auto result = wrapper.Wrap(absl::make_unique>()); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "no primary", std::string(result.status().message())); } TEST(StreamingAeadSetWrapperTest, BasicEncryptionAndDecryption) { uint32_t key_id_0 = 1234543; uint32_t key_id_1 = 726329; uint32_t key_id_2 = 7213743; std::string saead_name_0 = "streaming_aead0"; std::string saead_name_1 = "streaming_aead1"; std::string saead_name_2 = "streaming_aead2"; auto saead_set = GetTestStreamingAeadSet( {{key_id_0, saead_name_0, OutputPrefixType::RAW}, {key_id_1, saead_name_1, OutputPrefixType::RAW}, {key_id_2, saead_name_2, OutputPrefixType::RAW}}); // Wrap saead_set and test the resulting StreamingAead. StreamingAeadWrapper wrapper; auto wrap_result = wrapper.Wrap(std::move(saead_set)); EXPECT_TRUE(wrap_result.ok()) << wrap_result.status(); auto saead = std::move(wrap_result.value()); for (int pt_size : {0, 1, 10, 100, 10000}) { std::string plaintext = subtle::Random::GetRandomBytes(pt_size); for (std::string aad : {"some_aad", "", "some other aad"}) { SCOPED_TRACE(absl::StrCat("pt_size = ", pt_size, ", aad = '", aad, "'")); // Prepare ciphertext destination stream. auto ct_stream = absl::make_unique(); // A reference to the ciphertext buffer, for later validation. auto ct_buf = ct_stream->rdbuf(); std::unique_ptr ct_destination( absl::make_unique(std::move(ct_stream))); // Encrypt the plaintext. auto enc_stream_result = saead->NewEncryptingStream(std::move(ct_destination), aad); EXPECT_THAT(enc_stream_result, IsOk()); auto enc_stream = std::move(enc_stream_result.value()); auto status = WriteToStream(enc_stream.get(), plaintext); EXPECT_THAT(status, IsOk()); EXPECT_EQ(absl::StrCat(saead_name_2, aad, plaintext), ct_buf->str()); // Prepare ciphertext source stream. auto ct_source_stream = absl::make_unique(ct_buf->str()); std::unique_ptr ct_source( absl::make_unique( std::move(ct_source_stream))); // Decrypt the ciphertext. auto dec_stream_result = saead->NewDecryptingStream(std::move(ct_source), aad); EXPECT_THAT(dec_stream_result, IsOk()); std::string decrypted; status = ReadFromStream(dec_stream_result.value().get(), &decrypted); EXPECT_THAT(status, IsOk()); EXPECT_EQ(plaintext, decrypted); } } } TEST(StreamingAeadSetWrapperTest, DecryptionWithRandomAccessStream) { uint32_t key_id_0 = 1234543; uint32_t key_id_1 = 726329; uint32_t key_id_2 = 7213743; std::string saead_name_0 = "streaming_aead0"; std::string saead_name_1 = "streaming_aead1"; std::string saead_name_2 = "streaming_aead2"; auto saead_set = GetTestStreamingAeadSet( {{key_id_0, saead_name_0, OutputPrefixType::RAW}, {key_id_1, saead_name_1, OutputPrefixType::RAW}, {key_id_2, saead_name_2, OutputPrefixType::RAW}}); // Wrap saead_set and test the resulting StreamingAead. StreamingAeadWrapper wrapper; auto wrap_result = wrapper.Wrap(std::move(saead_set)); EXPECT_TRUE(wrap_result.ok()) << wrap_result.status(); auto saead = std::move(wrap_result.value()); for (int pt_size : {0, 1, 10, 100, 10000}) { std::string plaintext = subtle::Random::GetRandomBytes(pt_size); for (std::string aad : {"some_aad", "", "some other aad"}) { SCOPED_TRACE(absl::StrCat("pt_size = ", pt_size, ", aad = '", aad, "'")); // Prepare ciphertext destination stream. auto ct_stream = absl::make_unique(); // A reference to the ciphertext buffer, for later validation. auto ct_buf = ct_stream->rdbuf(); std::unique_ptr ct_destination( absl::make_unique(std::move(ct_stream))); // Encrypt the plaintext. auto enc_stream_result = saead->NewEncryptingStream(std::move(ct_destination), aad); EXPECT_THAT(enc_stream_result, IsOk()); auto enc_stream = std::move(enc_stream_result.value()); auto status = WriteToStream(enc_stream.get(), plaintext); EXPECT_THAT(status, IsOk()); EXPECT_EQ(absl::StrCat(saead_name_2, aad, plaintext), ct_buf->str()); // Decrypt the ciphertext. auto ct_source = std::make_unique(ct_buf->str()); auto dec_stream_result = saead->NewDecryptingRandomAccessStream(std::move(ct_source), aad); EXPECT_THAT(dec_stream_result, IsOk()); std::string decrypted; status = internal::ReadAllFromRandomAccessStream( dec_stream_result.value().get(), decrypted); EXPECT_THAT(status, StatusIs(absl::StatusCode::kOutOfRange, HasSubstr("EOF"))); EXPECT_EQ(plaintext, decrypted); } } } TEST(StreamingAeadSetWrapperTest, DecryptionAfterWrapperIsDestroyed) { uint32_t key_id_0 = 1234543; uint32_t key_id_1 = 726329; uint32_t key_id_2 = 7213743; std::string saead_name_0 = "streaming_aead0"; std::string saead_name_1 = "streaming_aead1"; std::string saead_name_2 = "streaming_aead2"; auto saead_set = GetTestStreamingAeadSet( {{key_id_0, saead_name_0, OutputPrefixType::RAW}, {key_id_1, saead_name_1, OutputPrefixType::RAW}, {key_id_2, saead_name_2, OutputPrefixType::RAW}}); int pt_size = 100; std::string plaintext = subtle::Random::GetRandomBytes(pt_size); std::string aad = "some_aad"; std::unique_ptr dec_stream; { // Wrap saead_set and test the resulting StreamingAead. StreamingAeadWrapper wrapper; auto wrap_result = wrapper.Wrap(std::move(saead_set)); EXPECT_TRUE(wrap_result.ok()) << wrap_result.status(); auto saead = std::move(wrap_result.value()); // Prepare ciphertext destination stream. auto ct_stream = absl::make_unique(); // A reference to the ciphertext buffer, for later validation. auto ct_buf = ct_stream->rdbuf(); std::unique_ptr ct_destination( absl::make_unique(std::move(ct_stream))); // Encrypt the plaintext. auto enc_stream_result = saead->NewEncryptingStream(std::move(ct_destination), aad); EXPECT_THAT(enc_stream_result, IsOk()); auto enc_stream = std::move(enc_stream_result.value()); auto status = WriteToStream(enc_stream.get(), plaintext); EXPECT_THAT(status, IsOk()); EXPECT_EQ(absl::StrCat(saead_name_2, aad, plaintext), ct_buf->str()); // Prepare ciphertext source stream. auto ct_source_stream = absl::make_unique(ct_buf->str()); std::unique_ptr ct_source( absl::make_unique( std::move(ct_source_stream))); // Decrypt the ciphertext. auto dec_stream_result = saead->NewDecryptingStream(std::move(ct_source), aad); EXPECT_THAT(dec_stream_result, IsOk()); dec_stream = std::move(dec_stream_result.value()); } // Now wrapper and saead are out of scope, // but decrypting stream should still work. std::string decrypted; auto status = ReadFromStream(dec_stream.get(), &decrypted); EXPECT_THAT(status, IsOk()); EXPECT_EQ(plaintext, decrypted); } TEST(StreamingAeadSetWrapperTest, EncryptWithTink) { ASSERT_THAT(StreamingAeadConfig::Register(), IsOk()); google::crypto::tink::AesGcmHkdfStreamingKey key; key.set_key_value("0123456789012345"); google::crypto::tink::AesGcmHkdfStreamingParams& params = *key.mutable_params(); params.set_hkdf_hash_type(google::crypto::tink::HashType::SHA1); params.set_derived_key_size(16); params.set_ciphertext_segment_size(1024); std::string serialized_key_1 = key.SerializeAsString(); key.set_key_value("0123456789abcdef"); std::string serialized_key_2 = key.SerializeAsString(); google::crypto::tink::Keyset keyset; { google::crypto::tink::Keyset::Key& keyset_key = *keyset.add_key(); google::crypto::tink::KeyData& key_data = *keyset_key.mutable_key_data(); key_data.set_type_url(AesGcmHkdfStreamingKeyManager().get_key_type()); key_data.set_value(serialized_key_1); key_data.set_key_material_type(google::crypto::tink::KeyData::SYMMETRIC); keyset_key.set_key_id(1); keyset_key.set_output_prefix_type( google::crypto::tink::OutputPrefixType::TINK); keyset_key.set_status(google::crypto::tink::KeyStatusType::ENABLED); keyset.set_primary_key_id(1); } { google::crypto::tink::Keyset::Key& keyset_key = *keyset.add_key(); google::crypto::tink::KeyData& key_data = *keyset_key.mutable_key_data(); key_data.set_type_url(AesGcmHkdfStreamingKeyManager().get_key_type()); key_data.set_value(serialized_key_2); key_data.set_key_material_type(google::crypto::tink::KeyData::SYMMETRIC); keyset_key.set_key_id(2); keyset_key.set_output_prefix_type( google::crypto::tink::OutputPrefixType::RAW); keyset_key.set_status(google::crypto::tink::KeyStatusType::ENABLED); } crypto::tink::util::StatusOr handle = ParseKeysetFromProtoKeysetFormat(keyset.SerializeAsString(), InsecureSecretKeyAccess::Get()); ASSERT_THAT(handle.status(), IsOk()); crypto::tink::util::StatusOr> streaming_aead = handle->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(streaming_aead.status(), IsOk()); EXPECT_THAT(EncryptThenDecrypt(streaming_aead.value().get(), streaming_aead.value().get(), subtle::Random::GetRandomBytes(10000), "some associated data", 0), IsOk()); } // Tests that we can decrypt with an old key using NewDecryptingStream TEST(StreamingAeadSetWrapperTest, DecryptOldKeyWorks) { ASSERT_THAT(StreamingAeadConfig::Register(), IsOk()); // We use the manually created test vector from // aes_gcm_hkdf_streaming_key_test.py // on https://github.com/tink-crypto/tink-cross-lang-tests google::crypto::tink::AesGcmHkdfStreamingKey key; key.set_key_value(absl::HexStringToBytes("6eb56cdc726dfbe5d57f2fcdc6e9345b")); google::crypto::tink::AesGcmHkdfStreamingParams& params = *key.mutable_params(); params.set_hkdf_hash_type(google::crypto::tink::HashType::SHA1); params.set_derived_key_size(16); params.set_ciphertext_segment_size(64); std::string key_used_for_ciphertext = key.SerializeAsString(); // New lines are as in the above test: they split the header and ciphertext // blocks std::string ciphertext = absl::HexStringToBytes( "1893b3af5e14ab378d065addfc8484da642c0862877baea8" "db92d9c77406a406168478821c4298eab3e6d531277f4c1a051714f" "aebcaefcbca7b7be05e9445ea" "a0bb2904153398a25084dd80ae0edcd1c3079fcea2cd3770" "630ee36f7539207b8ec9d754956d486b71cdf989f0ed6fba" "6779b63558be0a66e668df14e1603cd2" "af8944844078345286d0b292e772e7190775" "c51a0f83e40c0b75821027e7e538e111"); std::string associated_data = "aad"; google::crypto::tink::Keyset keyset; { // Key 1: a different key with the same parameters, primary google::crypto::tink::Keyset::Key& keyset_key = *keyset.add_key(); google::crypto::tink::KeyData& key_data = *keyset_key.mutable_key_data(); key_data.set_type_url(AesGcmHkdfStreamingKeyManager().get_key_type()); key.set_key_value("0123456789012345"); key_data.set_value(key.SerializeAsString()); key_data.set_key_material_type(google::crypto::tink::KeyData::SYMMETRIC); keyset_key.set_key_id(1); keyset_key.set_output_prefix_type( google::crypto::tink::OutputPrefixType::TINK); keyset_key.set_status(google::crypto::tink::KeyStatusType::ENABLED); keyset.set_primary_key_id(1); } { // Key 2: the correct key for our ciphertext google::crypto::tink::Keyset::Key& keyset_key = *keyset.add_key(); google::crypto::tink::KeyData& key_data = *keyset_key.mutable_key_data(); key_data.set_type_url(AesGcmHkdfStreamingKeyManager().get_key_type()); key_data.set_value(key_used_for_ciphertext); key_data.set_key_material_type(google::crypto::tink::KeyData::SYMMETRIC); keyset_key.set_key_id(2); keyset_key.set_output_prefix_type( google::crypto::tink::OutputPrefixType::TINK); keyset_key.set_status(google::crypto::tink::KeyStatusType::ENABLED); } { // Key 3: a different key with the same parameters google::crypto::tink::Keyset::Key& keyset_key = *keyset.add_key(); google::crypto::tink::KeyData& key_data = *keyset_key.mutable_key_data(); key_data.set_type_url(AesGcmHkdfStreamingKeyManager().get_key_type()); key.set_key_value("abcdefghijklmnop"); key_data.set_value(key.SerializeAsString()); key_data.set_key_material_type(google::crypto::tink::KeyData::SYMMETRIC); keyset_key.set_key_id(3); keyset_key.set_output_prefix_type( google::crypto::tink::OutputPrefixType::TINK); keyset_key.set_status(google::crypto::tink::KeyStatusType::ENABLED); } util::StatusOr handle = ParseKeysetFromProtoKeysetFormat( keyset.SerializeAsString(), InsecureSecretKeyAccess::Get()); ASSERT_THAT(handle.status(), IsOk()); crypto::tink::util::StatusOr> streaming_aead = handle->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(streaming_aead.status(), IsOk()); auto ciphertext_input_stream = std::make_unique( absl::make_unique(ciphertext)); crypto::tink::util::StatusOr> plaintext_stream = (*streaming_aead) ->NewDecryptingStream(std::move(ciphertext_input_stream), associated_data); ASSERT_THAT(plaintext_stream.status(), IsOk()); std::string decrypted; ASSERT_THAT(ReadFromStream(plaintext_stream->get(), &decrypted), IsOk()); EXPECT_EQ(decrypted, "This is a fairly long plaintext. It is of the exact length to " "create three output blocks. "); } // Tests that we can decrypt with an old key and NewDecryptingRandomAccessStream TEST(StreamingAeadSetWrapperTest, DecryptOldKeyWorksWithRandomAccess) { ASSERT_THAT(StreamingAeadConfig::Register(), IsOk()); // We use the manually created test vector from // aes_gcm_hkdf_streaming_key_test.py // on https://github.com/tink-crypto/tink-cross-lang-tests google::crypto::tink::AesGcmHkdfStreamingKey key; key.set_key_value(absl::HexStringToBytes("6eb56cdc726dfbe5d57f2fcdc6e9345b")); google::crypto::tink::AesGcmHkdfStreamingParams& params = *key.mutable_params(); params.set_hkdf_hash_type(google::crypto::tink::HashType::SHA1); params.set_derived_key_size(16); params.set_ciphertext_segment_size(64); std::string key_used_for_ciphertext = key.SerializeAsString(); // New lines are as in the above test: they split the header and ciphertext // blocks std::string ciphertext = absl::HexStringToBytes( "1893b3af5e14ab378d065addfc8484da642c0862877baea8" "db92d9c77406a406168478821c4298eab3e6d531277f4c1a051714f" "aebcaefcbca7b7be05e9445ea" "a0bb2904153398a25084dd80ae0edcd1c3079fcea2cd3770" "630ee36f7539207b8ec9d754956d486b71cdf989f0ed6fba" "6779b63558be0a66e668df14e1603cd2" "af8944844078345286d0b292e772e7190775" "c51a0f83e40c0b75821027e7e538e111"); std::string associated_data = "aad"; google::crypto::tink::Keyset keyset; { // Key 1: a different key with the same parameters, primary google::crypto::tink::Keyset::Key& keyset_key = *keyset.add_key(); google::crypto::tink::KeyData& key_data = *keyset_key.mutable_key_data(); key_data.set_type_url(AesGcmHkdfStreamingKeyManager().get_key_type()); key.set_key_value("0123456789012345"); key_data.set_value(key.SerializeAsString()); key_data.set_key_material_type(google::crypto::tink::KeyData::SYMMETRIC); keyset_key.set_key_id(1); keyset_key.set_output_prefix_type( google::crypto::tink::OutputPrefixType::TINK); keyset_key.set_status(google::crypto::tink::KeyStatusType::ENABLED); keyset.set_primary_key_id(1); } { // Key 2: the correct key for our ciphertext google::crypto::tink::Keyset::Key& keyset_key = *keyset.add_key(); google::crypto::tink::KeyData& key_data = *keyset_key.mutable_key_data(); key_data.set_type_url(AesGcmHkdfStreamingKeyManager().get_key_type()); key_data.set_value(key_used_for_ciphertext); key_data.set_key_material_type(google::crypto::tink::KeyData::SYMMETRIC); keyset_key.set_key_id(2); keyset_key.set_output_prefix_type( google::crypto::tink::OutputPrefixType::TINK); keyset_key.set_status(google::crypto::tink::KeyStatusType::ENABLED); } { // Key 3: a different key with the same parameters google::crypto::tink::Keyset::Key& keyset_key = *keyset.add_key(); google::crypto::tink::KeyData& key_data = *keyset_key.mutable_key_data(); key_data.set_type_url(AesGcmHkdfStreamingKeyManager().get_key_type()); key.set_key_value("abcdefghijklmnop"); key_data.set_value(key.SerializeAsString()); key_data.set_key_material_type(google::crypto::tink::KeyData::SYMMETRIC); keyset_key.set_key_id(3); keyset_key.set_output_prefix_type( google::crypto::tink::OutputPrefixType::TINK); keyset_key.set_status(google::crypto::tink::KeyStatusType::ENABLED); } crypto::tink::util::StatusOr handle = ParseKeysetFromProtoKeysetFormat(keyset.SerializeAsString(), InsecureSecretKeyAccess::Get()); ASSERT_THAT(handle.status(), IsOk()); crypto::tink::util::StatusOr> streaming_aead = handle->GetPrimitive(ConfigGlobalRegistry()); ASSERT_THAT(streaming_aead.status(), IsOk()); auto ciphertext_random_access_stream = std::make_unique(ciphertext); crypto::tink::util::StatusOr< std::unique_ptr> plaintext_stream = (*streaming_aead) ->NewDecryptingRandomAccessStream( std::move(ciphertext_random_access_stream), associated_data); ASSERT_THAT(plaintext_stream.status(), IsOk()); std::string decrypted; ASSERT_THAT( ReadAllFromRandomAccessStream(plaintext_stream->get(), decrypted, 100), StatusIs(absl::StatusCode::kOutOfRange)); EXPECT_EQ(decrypted, "This is a fairly long plaintext. It is of the exact length to " "create three output blocks. "); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/streamingaead/subtle/BUILD.bazel ================================================ licenses(["notice"]) ================================================ FILE: cc/streamingaead/subtle/CMakeLists.txt ================================================ ================================================ FILE: cc/subtle/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) PUBLIC_APIS = [ "common_enums.h", "aes_gcm_boringssl.h", "aes_siv_boringssl.h", "encrypt_then_authenticate.h", "hmac_boringssl.h", "hkdf.h", "ind_cpa_cipher.h", "random.h", ] cc_library( name = "subtle", hdrs = PUBLIC_APIS, include_prefix = "tink/subtle", visibility = ["//visibility:public"], deps = [ ":aes_gcm_boringssl", ":aes_siv_boringssl", ":common_enums", ":encrypt_then_authenticate", ":hkdf", ":hmac_boringssl", ":random", "//:aead", "//:deterministic_aead", "//:hybrid_decrypt", "//:hybrid_encrypt", "//:mac", "//:public_key_sign", "//:public_key_verify", "//aead/internal:aead_from_zero_copy", "//aead/internal:zero_copy_aead", "//internal:aes_util", "//internal:ssl_unique_ptr", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", ], ) cc_library( name = "ind_cpa_cipher", hdrs = ["ind_cpa_cipher.h"], include_prefix = "tink/subtle", deps = [ "//util:statusor", "@com_google_absl//absl/strings", ], ) cc_library( name = "ecies_hkdf_recipient_kem_boringssl", srcs = ["ecies_hkdf_recipient_kem_boringssl.cc"], hdrs = ["ecies_hkdf_recipient_kem_boringssl.h"], include_prefix = "tink/subtle", deps = [ ":common_enums", ":hkdf", "//internal:ec_util", "//internal:fips_utils", "//internal:ssl_unique_ptr", "//util:errors", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "ecies_hkdf_sender_kem_boringssl", srcs = ["ecies_hkdf_sender_kem_boringssl.cc"], hdrs = ["ecies_hkdf_sender_kem_boringssl.h"], include_prefix = "tink/subtle", deps = [ ":common_enums", ":hkdf", "//internal:ec_util", "//internal:fips_utils", "//internal:ssl_unique_ptr", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "ec_util", hdrs = ["ec_util.h"], include_prefix = "tink/subtle", visibility = ["//visibility:public"], deps = [ ":common_enums", "//internal:ec_util", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/base:core_headers", ], ) cc_library( name = "ed25519_sign_boringssl", srcs = ["ed25519_sign_boringssl.cc"], hdrs = ["ed25519_sign_boringssl.h"], include_prefix = "tink/subtle", deps = [ "//:public_key_sign", "//config:tink_fips", "//internal:ec_util", "//internal:fips_utils", "//internal:ssl_unique_ptr", "//internal:util", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:str_format", ], ) cc_library( name = "ed25519_verify_boringssl", srcs = ["ed25519_verify_boringssl.cc"], hdrs = ["ed25519_verify_boringssl.h"], include_prefix = "tink/subtle", deps = [ "//:public_key_verify", "//internal:ec_util", "//internal:fips_utils", "//internal:ssl_unique_ptr", "//internal:util", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:str_format", ], ) cc_library( name = "hkdf", srcs = ["hkdf.cc"], hdrs = ["hkdf.h"], include_prefix = "tink/subtle", deps = [ ":common_enums", ":subtle_util", "//internal:md_util", "//internal:ssl_unique_ptr", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/algorithm:container", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", ], ) cc_library( name = "aes_cmac_boringssl", srcs = ["aes_cmac_boringssl.cc"], hdrs = ["aes_cmac_boringssl.h"], include_prefix = "tink/subtle", deps = [ ":subtle_util", "//:mac", "//internal:aes_util", "//internal:call_with_core_dump_protection", "//internal:fips_utils", "//internal:ssl_unique_ptr", "//internal:util", "//util:errors", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "hmac_boringssl", srcs = ["hmac_boringssl.cc"], hdrs = ["hmac_boringssl.h"], include_prefix = "tink/subtle", deps = [ ":common_enums", "//:mac", "//internal:fips_utils", "//internal:md_util", "//internal:util", "//util:errors", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "ecdsa_sign_boringssl", srcs = ["ecdsa_sign_boringssl.cc"], hdrs = ["ecdsa_sign_boringssl.h"], include_prefix = "tink/subtle", deps = [ ":common_enums", ":subtle_util_boringssl", "//:public_key_sign", "//internal:fips_utils", "//internal:md_util", "//internal:util", "//signature/internal:ecdsa_raw_sign_boringssl", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "ecdsa_verify_boringssl", srcs = ["ecdsa_verify_boringssl.cc"], hdrs = ["ecdsa_verify_boringssl.h"], include_prefix = "tink/subtle", deps = [ ":common_enums", ":subtle_util_boringssl", "//:public_key_verify", "//internal:ec_util", "//internal:err_util", "//internal:fips_utils", "//internal:md_util", "//internal:ssl_unique_ptr", "//internal:util", "//util:errors", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "rsa_ssa_pss_verify_boringssl", srcs = ["rsa_ssa_pss_verify_boringssl.cc"], hdrs = ["rsa_ssa_pss_verify_boringssl.h"], include_prefix = "tink/subtle", deps = [ ":common_enums", "//:public_key_verify", "//internal:err_util", "//internal:fips_utils", "//internal:md_util", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//internal:util", "//util:errors", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "rsa_ssa_pss_sign_boringssl", srcs = ["rsa_ssa_pss_sign_boringssl.cc"], hdrs = ["rsa_ssa_pss_sign_boringssl.h"], include_prefix = "tink/subtle", deps = [ ":common_enums", ":subtle_util", "//:public_key_sign", "//internal:err_util", "//internal:fips_utils", "//internal:md_util", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//internal:util", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", ], ) cc_library( name = "rsa_ssa_pkcs1_verify_boringssl", srcs = ["rsa_ssa_pkcs1_verify_boringssl.cc"], hdrs = ["rsa_ssa_pkcs1_verify_boringssl.h"], include_prefix = "tink/subtle", deps = [ ":common_enums", "//:public_key_verify", "//internal:fips_utils", "//internal:md_util", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//internal:util", "//util:errors", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "rsa_ssa_pkcs1_sign_boringssl", srcs = ["rsa_ssa_pkcs1_sign_boringssl.cc"], hdrs = ["rsa_ssa_pkcs1_sign_boringssl.h"], include_prefix = "tink/subtle", deps = [ ":common_enums", ":subtle_util", "//:public_key_sign", "//internal:bn_util", "//internal:err_util", "//internal:fips_utils", "//internal:md_util", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//internal:util", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "aes_gcm_boringssl", srcs = ["aes_gcm_boringssl.cc"], hdrs = ["aes_gcm_boringssl.h"], include_prefix = "tink/subtle", deps = [ "//:aead", "//aead/internal:aead_from_zero_copy", "//aead/internal:zero_copy_aead", "//aead/internal:zero_copy_aes_gcm_boringssl", "//internal:fips_utils", "//util:secret_data", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/memory", "@com_google_absl//absl/strings", ], ) cc_library( name = "aes_gcm_hkdf_stream_segment_decrypter", srcs = ["aes_gcm_hkdf_stream_segment_decrypter.cc"], hdrs = ["aes_gcm_hkdf_stream_segment_decrypter.h"], include_prefix = "tink/subtle", deps = [ ":aes_gcm_hkdf_stream_segment_encrypter", ":common_enums", ":hkdf", ":random", ":stream_segment_decrypter", "//aead/internal:ssl_aead", "//internal:err_util", "//util:secret_data", "//util:status", "//util:statusor", "@com_google_absl//absl/algorithm:container", "@com_google_absl//absl/base:config", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", ], ) cc_library( name = "aes_gcm_hkdf_stream_segment_encrypter", srcs = ["aes_gcm_hkdf_stream_segment_encrypter.cc"], hdrs = ["aes_gcm_hkdf_stream_segment_encrypter.h"], include_prefix = "tink/subtle", deps = [ ":random", ":stream_segment_encrypter", ":subtle_util", "//aead/internal:ssl_aead", "//internal:err_util", "//util:secret_data", "//util:status", "//util:statusor", "@com_google_absl//absl/algorithm:container", "@com_google_absl//absl/base:config", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", ], ) cc_library( name = "aes_gcm_hkdf_streaming", srcs = ["aes_gcm_hkdf_streaming.cc"], hdrs = ["aes_gcm_hkdf_streaming.h"], include_prefix = "tink/subtle", deps = [ ":aes_gcm_hkdf_stream_segment_decrypter", ":aes_gcm_hkdf_stream_segment_encrypter", ":common_enums", ":hkdf", ":nonce_based_streaming_aead", ":random", ":stream_segment_decrypter", ":stream_segment_encrypter", "//internal:fips_utils", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "aes_ctr_hmac_streaming", srcs = ["aes_ctr_hmac_streaming.cc"], hdrs = ["aes_ctr_hmac_streaming.h"], include_prefix = "tink/subtle", deps = [ ":common_enums", ":hkdf", ":hmac_boringssl", ":nonce_based_streaming_aead", ":random", ":stream_segment_decrypter", ":stream_segment_encrypter", ":subtle_util", "//:mac", "//internal:aes_util", "//internal:fips_utils", "//internal:ssl_unique_ptr", "//util:errors", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "aes_eax_boringssl", srcs = ["aes_eax_boringssl.cc"], hdrs = ["aes_eax_boringssl.h"], include_prefix = "tink/subtle", deps = [ ":random", ":subtle_util", "//:aead", "//internal:aes_util", "//internal:call_with_core_dump_protection", "//internal:fips_utils", "//internal:util", "//util:errors", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/algorithm:container", "@com_google_absl//absl/base:config", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", ], ) cc_library( name = "encrypt_then_authenticate", srcs = ["encrypt_then_authenticate.cc"], hdrs = ["encrypt_then_authenticate.h"], include_prefix = "tink/subtle", deps = [ ":ind_cpa_cipher", "//:aead", "//:mac", "//internal:util", "//util:errors", "//util:status", "//util:statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "aes_ctr_boringssl", srcs = ["aes_ctr_boringssl.cc"], hdrs = ["aes_ctr_boringssl.h"], include_prefix = "tink/subtle", deps = [ ":ind_cpa_cipher", ":random", ":subtle_util", "//internal:aes_util", "//internal:fips_utils", "//internal:ssl_unique_ptr", "//internal:util", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "random", srcs = ["random.cc"], hdrs = ["random.h"], include_prefix = "tink/subtle", visibility = ["//visibility:public"], deps = [ ":subtle_util", "//util:secret_data", "//util:status", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", ], ) cc_library( name = "xchacha20_poly1305_boringssl", srcs = ["xchacha20_poly1305_boringssl.cc"], hdrs = ["xchacha20_poly1305_boringssl.h"], include_prefix = "tink/subtle", tags = ["fips"], deps = [ ":random", ":subtle_util", "//:aead", "//aead/internal:ssl_aead", "//internal:fips_utils", "//internal:util", "//util:errors", "//util:secret_data", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", ], ) cc_library( name = "aes_siv_boringssl", srcs = ["aes_siv_boringssl.cc"], hdrs = ["aes_siv_boringssl.h"], include_prefix = "tink/subtle", tags = ["fips"], deps = [ ":subtle_util", "//:deterministic_aead", "//aead/internal:aead_util", "//internal:aes_util", "//internal:fips_utils", "//util:errors", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", ], ) cc_library( name = "aes_gcm_siv_boringssl", srcs = ["aes_gcm_siv_boringssl.cc"], hdrs = ["aes_gcm_siv_boringssl.h"], include_prefix = "tink/subtle", deps = [ ":random", ":subtle_util", "//:aead", "//aead/internal:ssl_aead", "//internal:fips_utils", "//util:secret_data", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", ], ) cc_library( name = "common_enums", srcs = ["common_enums.cc"], hdrs = ["common_enums.h"], include_prefix = "tink/subtle", deps = ["@com_google_absl//absl/strings"], ) cc_library( name = "subtle_util", srcs = ["subtle_util.cc"], hdrs = ["subtle_util.h"], include_prefix = "tink/subtle", visibility = ["//visibility:public"], ) cc_library( name = "subtle_util_boringssl", hdrs = ["subtle_util_boringssl.h"], include_prefix = "tink/subtle", deps = [ ":common_enums", "//aead/internal:aead_util", "//internal:aes_util", "//internal:bn_util", "//internal:ec_util", "//internal:err_util", "//internal:md_util", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//internal:util", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/strings", ], ) cc_library( name = "wycheproof_util", testonly = 1, srcs = ["wycheproof_util.cc"], hdrs = ["wycheproof_util.h"], include_prefix = "tink/subtle", deps = [ ":common_enums", "//internal:test_file_util", "//util:status", "//util:statusor", "@com_google_absl//absl/log", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@rapidjson", ], ) cc_library( name = "stream_segment_decrypter", hdrs = ["stream_segment_decrypter.h"], include_prefix = "tink/subtle", deps = ["//util:status"], ) cc_library( name = "stream_segment_encrypter", hdrs = ["stream_segment_encrypter.h"], include_prefix = "tink/subtle", deps = ["//util:status"], ) cc_library( name = "streaming_aead_decrypting_stream", srcs = ["streaming_aead_decrypting_stream.cc"], hdrs = ["streaming_aead_decrypting_stream.h"], include_prefix = "tink/subtle", deps = [ ":stream_segment_decrypter", "//:input_stream", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", ], ) cc_library( name = "streaming_aead_encrypting_stream", srcs = ["streaming_aead_encrypting_stream.cc"], hdrs = ["streaming_aead_encrypting_stream.h"], include_prefix = "tink/subtle", deps = [ ":stream_segment_encrypter", "//:output_stream", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", ], ) cc_library( name = "nonce_based_streaming_aead", srcs = ["nonce_based_streaming_aead.cc"], hdrs = ["nonce_based_streaming_aead.h"], include_prefix = "tink/subtle", deps = [ ":decrypting_random_access_stream", ":stream_segment_decrypter", ":stream_segment_encrypter", ":streaming_aead_decrypting_stream", ":streaming_aead_encrypting_stream", "//:input_stream", "//:output_stream", "//:random_access_stream", "//:streaming_aead", "//util:statusor", "@com_google_absl//absl/strings", ], ) cc_library( name = "test_util", testonly = 1, srcs = ["test_util.cc"], hdrs = ["test_util.h"], include_prefix = "tink/subtle", deps = [ ":nonce_based_streaming_aead", ":stream_segment_decrypter", ":stream_segment_encrypter", "//:input_stream", "//:output_stream", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "aead_test_util", testonly = 1, srcs = ["aead_test_util.cc"], hdrs = ["aead_test_util.h"], include_prefix = "tink/subtle", deps = [ ":test_util", "//:aead", "//aead:cord_aead", "//util:status", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:cord", ], ) cc_library( name = "streaming_aead_test_util", testonly = 1, srcs = ["streaming_aead_test_util.cc"], hdrs = ["streaming_aead_test_util.h"], include_prefix = "tink/subtle", deps = [ ":test_util", "//:input_stream", "//:random_access_stream", "//:streaming_aead", "//internal:test_random_access_stream", "//util:buffer", "//util:istream_input_stream", "//util:ostream_output_stream", "//util:status", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "hybrid_test_util", testonly = 1, srcs = ["hybrid_test_util.cc"], hdrs = ["hybrid_test_util.h"], include_prefix = "tink/subtle", deps = [ "//:hybrid_decrypt", "//:hybrid_encrypt", "//util:status", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "decrypting_random_access_stream", srcs = ["decrypting_random_access_stream.cc"], hdrs = ["decrypting_random_access_stream.h"], include_prefix = "tink/subtle", deps = [ ":stream_segment_decrypter", "//:random_access_stream", "//util:buffer", "//util:errors", "//util:status", "//util:statusor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/synchronization", ], ) cc_library( name = "streaming_mac_impl", srcs = ["streaming_mac_impl.cc"], hdrs = ["streaming_mac_impl.h"], include_prefix = "tink/subtle", deps = [ "//:output_stream_with_result", "//:streaming_mac", "//subtle/mac:stateful_mac", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "stateful_hmac_boringssl", srcs = ["stateful_hmac_boringssl.cc"], hdrs = ["stateful_hmac_boringssl.h"], include_prefix = "tink/subtle", deps = [ ":common_enums", "//internal:md_util", "//internal:ssl_unique_ptr", "//internal:util", "//subtle/mac:stateful_mac", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "stateful_cmac_boringssl", srcs = ["stateful_cmac_boringssl.cc"], hdrs = ["stateful_cmac_boringssl.h"], include_prefix = "tink/subtle", deps = [ ":common_enums", "//internal:aes_util", "//internal:ssl_unique_ptr", "//internal:util", "//subtle/mac:stateful_mac", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", ], ) cc_library( name = "pem_parser_boringssl", srcs = ["pem_parser_boringssl.cc"], hdrs = ["pem_parser_boringssl.h"], include_prefix = "tink/subtle", deps = [ ":common_enums", ":subtle_util_boringssl", "//internal:bn_util", "//internal:ec_util", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//internal:ssl_util", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) # tests cc_test( name = "ecies_hkdf_recipient_kem_boringssl_test", size = "small", srcs = ["ecies_hkdf_recipient_kem_boringssl_test.cc"], tags = ["fips"], deps = [ ":common_enums", ":ecies_hkdf_recipient_kem_boringssl", "//config:tink_fips", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ecies_hkdf_sender_kem_boringssl_test", size = "small", srcs = ["ecies_hkdf_sender_kem_boringssl_test.cc"], tags = ["fips"], deps = [ ":common_enums", ":ecies_hkdf_recipient_kem_boringssl", ":ecies_hkdf_sender_kem_boringssl", "//config:tink_fips", "//internal:ec_util", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hkdf_test", size = "small", srcs = ["hkdf_test.cc"], deps = [ ":common_enums", ":hkdf", "//util:secret_data", "//util:status", "//util:statusor", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_cmac_boringssl_test", size = "small", srcs = ["aes_cmac_boringssl_test.cc"], tags = ["fips"], deps = [ ":aes_cmac_boringssl", ":common_enums", "//:mac", "//config:tink_fips", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hmac_boringssl_test", size = "small", srcs = ["hmac_boringssl_test.cc"], tags = ["fips"], deps = [ ":common_enums", ":hmac_boringssl", "//:mac", "//internal:fips_utils", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_gcm_boringssl_test", size = "small", srcs = ["aes_gcm_boringssl_test.cc"], data = ["//testvectors:aes_gcm"], tags = ["fips"], deps = [ ":aes_gcm_boringssl", "//:aead", "//aead/internal:wycheproof_aead", "//internal:fips_utils", "//util:secret_data", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_gcm_hkdf_stream_segment_decrypter_test", size = "small", srcs = ["aes_gcm_hkdf_stream_segment_decrypter_test.cc"], deps = [ ":aes_gcm_hkdf_stream_segment_decrypter", ":aes_gcm_hkdf_stream_segment_encrypter", ":common_enums", ":hkdf", ":random", ":stream_segment_encrypter", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_util", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_gcm_hkdf_stream_segment_encrypter_test", size = "small", srcs = ["aes_gcm_hkdf_stream_segment_encrypter_test.cc"], deps = [ ":aes_gcm_hkdf_stream_segment_encrypter", ":random", "//util:status", "//util:statusor", "//util:test_util", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_gcm_hkdf_streaming_test", size = "small", srcs = ["aes_gcm_hkdf_streaming_test.cc"], tags = ["fips"], deps = [ ":aes_gcm_hkdf_streaming", ":common_enums", ":random", ":streaming_aead_test_util", ":test_util", "//:output_stream", "//:random_access_stream", "//config:tink_fips", "//internal:test_random_access_stream", "//util:istream_input_stream", "//util:ostream_output_stream", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_ctr_hmac_streaming_test", size = "small", srcs = ["aes_ctr_hmac_streaming_test.cc"], tags = ["fips"], deps = [ ":aes_ctr_hmac_streaming", ":common_enums", ":random", ":stream_segment_decrypter", ":stream_segment_encrypter", ":streaming_aead_test_util", "//:random_access_stream", "//config:tink_fips", "//internal:test_random_access_stream", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_eax_boringssl_test", size = "small", srcs = ["aes_eax_boringssl_test.cc"], data = ["//testvectors:aes_eax"], tags = ["fips"], deps = [ ":aes_eax_boringssl", ":wycheproof_util", "//config:tink_fips", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", "@rapidjson", ], ) cc_test( name = "encrypt_then_authenticate_test", srcs = ["encrypt_then_authenticate_test.cc"], deps = [ ":aes_ctr_boringssl", ":common_enums", ":encrypt_then_authenticate", ":hmac_boringssl", ":random", "//:aead", "//util:secret_data", "//util:statusor", "//util:test_util", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_ctr_boringssl_test", size = "small", srcs = ["aes_ctr_boringssl_test.cc"], tags = ["fips"], deps = [ ":aes_ctr_boringssl", ":random", "//internal:fips_utils", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_siv_boringssl_test", size = "small", srcs = ["aes_siv_boringssl_test.cc"], data = ["//testvectors:aes_siv_cmac"], tags = ["fips"], deps = [ ":aes_siv_boringssl", ":wycheproof_util", "//config:tink_fips", "//util:secret_data", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_googletest//:gtest_main", "@rapidjson", ], ) cc_test( name = "ecdsa_sign_boringssl_test", size = "small", srcs = ["ecdsa_sign_boringssl_test.cc"], tags = ["fips"], deps = [ ":common_enums", ":ecdsa_sign_boringssl", ":ecdsa_verify_boringssl", ":subtle_util_boringssl", "//:public_key_sign", "//:public_key_verify", "//internal:ec_util", "//internal:fips_utils", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ecdsa_verify_boringssl_test", size = "small", srcs = ["ecdsa_verify_boringssl_test.cc"], data = [ "//testvectors:ecdsa", "//testvectors:ecdsa_webcrypto", ], tags = ["fips"], deps = [ ":common_enums", ":ecdsa_sign_boringssl", ":ecdsa_verify_boringssl", ":subtle_util_boringssl", ":wycheproof_util", "//:public_key_sign", "//:public_key_verify", "//internal:fips_utils", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", "@rapidjson", ], ) cc_test( name = "ed25519_sign_boringssl_test", size = "small", srcs = ["ed25519_sign_boringssl_test.cc"], tags = ["fips"], deps = [ ":ed25519_sign_boringssl", ":ed25519_verify_boringssl", ":random", "//:public_key_sign", "//:public_key_verify", "//config:tink_fips", "//internal:ec_util", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ed25519_verify_boringssl_test", size = "small", srcs = ["ed25519_verify_boringssl_test.cc"], data = ["//testvectors:eddsa"], tags = ["fips"], deps = [ ":ed25519_verify_boringssl", ":wycheproof_util", "//:public_key_verify", "//config:tink_fips", "//internal:ec_util", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", "@rapidjson", ], ) cc_test( name = "rsa_ssa_pss_verify_boringssl_test", size = "small", srcs = ["rsa_ssa_pss_verify_boringssl_test.cc"], data = ["//testvectors:rsa_pss"], tags = ["fips"], deps = [ ":common_enums", ":rsa_ssa_pss_verify_boringssl", ":wycheproof_util", "//:public_key_sign", "//:public_key_verify", "//internal:err_util", "//internal:fips_utils", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//util:status", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", "@rapidjson", ], ) cc_test( name = "rsa_ssa_pss_sign_boringssl_test", srcs = ["rsa_ssa_pss_sign_boringssl_test.cc"], tags = ["fips"], deps = [ ":common_enums", ":rsa_ssa_pss_sign_boringssl", ":rsa_ssa_pss_verify_boringssl", "//internal:fips_utils", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "rsa_ssa_pkcs1_verify_boringssl_test", size = "small", srcs = ["rsa_ssa_pkcs1_verify_boringssl_test.cc"], data = ["//testvectors:rsa_signature"], tags = ["fips"], deps = [ ":common_enums", ":rsa_ssa_pkcs1_verify_boringssl", ":wycheproof_util", "//:public_key_sign", "//:public_key_verify", "//internal:err_util", "//internal:fips_utils", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//util:status", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", "@rapidjson", ], ) cc_test( name = "rsa_ssa_pkcs1_sign_boringssl_test", srcs = ["rsa_ssa_pkcs1_sign_boringssl_test.cc"], tags = ["fips"], deps = [ ":common_enums", ":rsa_ssa_pkcs1_sign_boringssl", ":rsa_ssa_pkcs1_verify_boringssl", "//internal:fips_utils", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aes_gcm_siv_boringssl_test", size = "small", srcs = ["aes_gcm_siv_boringssl_test.cc"], data = ["//testvectors:aes_gcm_siv"], tags = ["fips"], deps = [ ":aes_gcm_siv_boringssl", ":subtle_util", "//:aead", "//aead/internal:wycheproof_aead", "//config:tink_fips", "//internal:ssl_util", "//util:secret_data", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "random_test", size = "small", srcs = ["random_test.cc"], deps = [ ":random", "//util:secret_data", "//util:test_matchers", "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/types:span", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "common_enums_test", size = "small", srcs = ["common_enums_test.cc"], deps = [ ":common_enums", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "subtle_util_test", size = "small", srcs = ["subtle_util_test.cc"], deps = [ ":subtle_util", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "xchacha20_poly1305_boringssl_test", size = "small", srcs = ["xchacha20_poly1305_boringssl_test.cc"], data = ["//testvectors:chacha20_poly1305"], tags = ["fips"], deps = [ ":subtle_util", ":xchacha20_poly1305_boringssl", "//:aead", "//aead/internal:wycheproof_aead", "//config:tink_fips", "//internal:ssl_util", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "streaming_aead_decrypting_stream_test", srcs = ["streaming_aead_decrypting_stream_test.cc"], deps = [ ":random", ":stream_segment_decrypter", ":streaming_aead_decrypting_stream", ":test_util", "//:input_stream", "//util:istream_input_stream", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "streaming_aead_encrypting_stream_test", srcs = ["streaming_aead_encrypting_stream_test.cc"], deps = [ ":random", ":stream_segment_encrypter", ":streaming_aead_encrypting_stream", ":test_util", "//:output_stream", "//util:ostream_output_stream", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "aead_test_util_test", srcs = ["aead_test_util_test.cc"], deps = [ ":aead_test_util", "//util:test_matchers", "//util:test_util", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "streaming_aead_test_util_test", srcs = ["streaming_aead_test_util_test.cc"], deps = [ ":streaming_aead_test_util", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "hybrid_test_util_test", srcs = ["hybrid_test_util_test.cc"], deps = [ ":hybrid_test_util", "//util:test_matchers", "//util:test_util", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "decrypting_random_access_stream_test", size = "small", srcs = ["decrypting_random_access_stream_test.cc"], deps = [ ":decrypting_random_access_stream", ":random", ":test_util", "//:output_stream", "//:random_access_stream", "//:streaming_aead", "//internal:test_random_access_stream", "//util:buffer", "//util:ostream_output_stream", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "streaming_mac_impl_test", size = "small", srcs = ["streaming_mac_impl_test.cc"], deps = [ ":random", ":streaming_mac_impl", ":test_util", "//:output_stream_with_result", "//subtle/mac:stateful_mac", "//util:status", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "stateful_hmac_boringssl_test", size = "small", srcs = ["stateful_hmac_boringssl_test.cc"], data = ["//testvectors:hmac"], deps = [ ":common_enums", ":random", ":stateful_hmac_boringssl", "//subtle/mac:stateful_mac", "//util:secret_data", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/log", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "stateful_cmac_boringssl_test", size = "small", srcs = ["stateful_cmac_boringssl_test.cc"], data = ["//testvectors:aes_cmac"], deps = [ ":common_enums", ":stateful_cmac_boringssl", ":wycheproof_util", "//subtle/mac:stateful_mac", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", "@rapidjson", ], ) cc_test( name = "pem_parser_boringssl_test", srcs = ["pem_parser_boringssl_test.cc"], deps = [ ":common_enums", ":pem_parser_boringssl", ":subtle_util_boringssl", "//internal:bn_util", "//internal:err_util", "//internal:rsa_util", "//internal:ssl_unique_ptr", "//internal:ssl_util", "//util:secret_data", "//util:status", "//util:statusor", "//util:test_matchers", "@boringssl//:crypto", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/subtle/CMakeLists.txt ================================================ tink_module(subtle) add_subdirectory(prf) add_subdirectory(mac) tink_cc_library( NAME subtle SRCS aes_gcm_boringssl.h aes_siv_boringssl.h common_enums.h encrypt_then_authenticate.h hkdf.h hmac_boringssl.h ind_cpa_cipher.h random.h DEPS tink::subtle::aes_gcm_boringssl tink::subtle::aes_siv_boringssl tink::subtle::common_enums tink::subtle::encrypt_then_authenticate tink::subtle::hkdf tink::subtle::hmac_boringssl tink::subtle::random absl::core_headers absl::strings absl::span crypto tink::core::aead tink::core::deterministic_aead tink::core::mac tink::aead::internal::aead_from_zero_copy tink::aead::internal::zero_copy_aead tink::internal::aes_util tink::internal::fips_utils tink::internal::ssl_unique_ptr tink::util::secret_data tink::util::status tink::util::statusor PUBLIC ) add_library(tink::subtle ALIAS tink_subtle_subtle) tink_cc_library( NAME ind_cpa_cipher SRCS ind_cpa_cipher.h DEPS absl::strings tink::util::statusor ) tink_cc_library( NAME ecies_hkdf_recipient_kem_boringssl SRCS ecies_hkdf_recipient_kem_boringssl.cc ecies_hkdf_recipient_kem_boringssl.h DEPS tink::subtle::common_enums tink::subtle::hkdf absl::memory absl::status absl::strings crypto tink::internal::ec_util tink::internal::fips_utils tink::internal::ssl_unique_ptr tink::util::errors tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME ecies_hkdf_sender_kem_boringssl SRCS ecies_hkdf_sender_kem_boringssl.cc ecies_hkdf_sender_kem_boringssl.h DEPS tink::subtle::common_enums tink::subtle::hkdf absl::memory absl::status absl::strings crypto tink::internal::ec_util tink::internal::fips_utils tink::internal::ssl_unique_ptr tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME ec_util SRCS ec_util.h DEPS tink::subtle::common_enums absl::core_headers crypto tink::internal::ec_util tink::util::status tink::util::statusor ) tink_cc_library( NAME ed25519_sign_boringssl SRCS ed25519_sign_boringssl.cc ed25519_sign_boringssl.h DEPS absl::memory absl::status absl::strings absl::str_format crypto tink::core::public_key_sign tink::config::tink_fips tink::internal::ec_util tink::internal::fips_utils tink::internal::ssl_unique_ptr tink::internal::util tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME ed25519_verify_boringssl SRCS ed25519_verify_boringssl.cc ed25519_verify_boringssl.h DEPS absl::memory absl::status absl::strings absl::str_format crypto tink::core::public_key_verify tink::internal::ec_util tink::internal::fips_utils tink::internal::ssl_unique_ptr tink::internal::util tink::util::status tink::util::statusor ) tink_cc_library( NAME hkdf SRCS hkdf.cc hkdf.h DEPS tink::subtle::common_enums tink::subtle::subtle_util absl::algorithm_container absl::status absl::strings absl::span crypto tink::internal::md_util tink::internal::ssl_unique_ptr tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME aes_cmac_boringssl SRCS aes_cmac_boringssl.cc aes_cmac_boringssl.h DEPS tink::subtle::subtle_util absl::memory absl::status absl::string_view crypto tink::core::mac tink::internal::aes_util tink::internal::call_with_core_dump_protection tink::internal::fips_utils tink::internal::ssl_unique_ptr tink::internal::util tink::util::errors tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME hmac_boringssl SRCS hmac_boringssl.cc hmac_boringssl.h DEPS tink::subtle::common_enums absl::memory absl::status absl::strings crypto tink::core::mac tink::internal::fips_utils tink::internal::md_util tink::internal::util tink::util::errors tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME ecdsa_sign_boringssl SRCS ecdsa_sign_boringssl.cc ecdsa_sign_boringssl.h DEPS tink::subtle::common_enums tink::subtle::subtle_util_boringssl absl::memory absl::status absl::strings crypto tink::core::public_key_sign tink::internal::fips_utils tink::internal::md_util tink::internal::util tink::signature::internal::ecdsa_raw_sign_boringssl tink::util::status tink::util::statusor ) tink_cc_library( NAME ecdsa_verify_boringssl SRCS ecdsa_verify_boringssl.cc ecdsa_verify_boringssl.h DEPS tink::subtle::common_enums tink::subtle::subtle_util_boringssl absl::status absl::strings crypto tink::core::public_key_verify tink::internal::ec_util tink::internal::err_util tink::internal::fips_utils tink::internal::md_util tink::internal::ssl_unique_ptr tink::internal::util tink::util::errors tink::util::status tink::util::statusor ) tink_cc_library( NAME rsa_ssa_pss_verify_boringssl SRCS rsa_ssa_pss_verify_boringssl.cc rsa_ssa_pss_verify_boringssl.h DEPS tink::subtle::common_enums absl::memory absl::status absl::strings crypto tink::core::public_key_verify tink::internal::err_util tink::internal::fips_utils tink::internal::md_util tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::internal::util tink::util::errors tink::util::status tink::util::statusor ) tink_cc_library( NAME rsa_ssa_pss_sign_boringssl SRCS rsa_ssa_pss_sign_boringssl.cc rsa_ssa_pss_sign_boringssl.h DEPS tink::subtle::common_enums tink::subtle::subtle_util absl::memory absl::status absl::strings absl::span crypto tink::core::public_key_sign tink::internal::err_util tink::internal::fips_utils tink::internal::md_util tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::internal::util tink::util::status tink::util::statusor ) tink_cc_library( NAME rsa_ssa_pkcs1_verify_boringssl SRCS rsa_ssa_pkcs1_verify_boringssl.cc rsa_ssa_pkcs1_verify_boringssl.h DEPS tink::subtle::common_enums absl::status absl::strings crypto tink::core::public_key_verify tink::internal::fips_utils tink::internal::md_util tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::internal::util tink::util::errors tink::util::status tink::util::statusor ) tink_cc_library( NAME rsa_ssa_pkcs1_sign_boringssl SRCS rsa_ssa_pkcs1_sign_boringssl.cc rsa_ssa_pkcs1_sign_boringssl.h DEPS tink::subtle::common_enums tink::subtle::subtle_util absl::memory absl::status absl::strings crypto tink::core::public_key_sign tink::internal::bn_util tink::internal::err_util tink::internal::fips_utils tink::internal::md_util tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::internal::util tink::util::status tink::util::statusor ) tink_cc_library( NAME aes_gcm_boringssl SRCS aes_gcm_boringssl.cc aes_gcm_boringssl.h DEPS absl::core_headers absl::memory absl::strings tink::core::aead tink::aead::internal::aead_from_zero_copy tink::aead::internal::zero_copy_aead tink::aead::internal::zero_copy_aes_gcm_boringssl tink::internal::fips_utils tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME aes_gcm_hkdf_stream_segment_decrypter SRCS aes_gcm_hkdf_stream_segment_decrypter.cc aes_gcm_hkdf_stream_segment_decrypter.h DEPS tink::subtle::aes_gcm_hkdf_stream_segment_encrypter tink::subtle::common_enums tink::subtle::hkdf tink::subtle::random tink::subtle::stream_segment_decrypter absl::algorithm_container absl::config absl::memory absl::status absl::strings absl::span tink::aead::internal::ssl_aead tink::internal::err_util tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME aes_gcm_hkdf_stream_segment_encrypter SRCS aes_gcm_hkdf_stream_segment_encrypter.cc aes_gcm_hkdf_stream_segment_encrypter.h DEPS tink::subtle::random tink::subtle::stream_segment_encrypter tink::subtle::subtle_util absl::algorithm_container absl::config absl::memory absl::status absl::strings absl::span tink::aead::internal::ssl_aead tink::internal::err_util tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME aes_gcm_hkdf_streaming SRCS aes_gcm_hkdf_streaming.cc aes_gcm_hkdf_streaming.h DEPS tink::subtle::aes_gcm_hkdf_stream_segment_decrypter tink::subtle::aes_gcm_hkdf_stream_segment_encrypter tink::subtle::common_enums tink::subtle::hkdf tink::subtle::nonce_based_streaming_aead tink::subtle::random tink::subtle::stream_segment_decrypter tink::subtle::stream_segment_encrypter absl::memory absl::status absl::string_view crypto tink::internal::fips_utils tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME aes_ctr_hmac_streaming SRCS aes_ctr_hmac_streaming.cc aes_ctr_hmac_streaming.h DEPS tink::subtle::common_enums tink::subtle::hkdf tink::subtle::hmac_boringssl tink::subtle::nonce_based_streaming_aead tink::subtle::random tink::subtle::stream_segment_decrypter tink::subtle::stream_segment_encrypter tink::subtle::subtle_util absl::memory absl::status absl::strings crypto tink::core::mac tink::internal::aes_util tink::internal::fips_utils tink::internal::ssl_unique_ptr tink::util::errors tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME aes_eax_boringssl SRCS aes_eax_boringssl.cc aes_eax_boringssl.h DEPS tink::subtle::random tink::subtle::subtle_util absl::algorithm_container absl::config absl::memory absl::status absl::strings absl::span crypto tink::core::aead tink::internal::aes_util tink::internal::call_with_core_dump_protection tink::internal::fips_utils tink::internal::util tink::util::errors tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME encrypt_then_authenticate SRCS encrypt_then_authenticate.cc encrypt_then_authenticate.h DEPS tink::subtle::ind_cpa_cipher absl::status absl::strings tink::core::aead tink::core::mac tink::internal::util tink::util::errors tink::util::status tink::util::statusor ) tink_cc_library( NAME aes_ctr_boringssl SRCS aes_ctr_boringssl.cc aes_ctr_boringssl.h DEPS tink::subtle::ind_cpa_cipher tink::subtle::random tink::subtle::subtle_util absl::memory absl::status absl::string_view crypto tink::internal::aes_util tink::internal::fips_utils tink::internal::ssl_unique_ptr tink::internal::util tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME random SRCS random.cc random.h DEPS tink::subtle::subtle_util absl::status absl::strings absl::span crypto tink::util::secret_data tink::util::status ) tink_cc_library( NAME xchacha20_poly1305_boringssl SRCS xchacha20_poly1305_boringssl.cc xchacha20_poly1305_boringssl.h DEPS tink::subtle::random tink::subtle::subtle_util absl::memory absl::status absl::strings absl::span tink::core::aead tink::aead::internal::ssl_aead tink::internal::fips_utils tink::internal::util tink::util::errors tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME aes_siv_boringssl SRCS aes_siv_boringssl.cc aes_siv_boringssl.h DEPS tink::subtle::subtle_util absl::memory absl::status absl::strings absl::span crypto tink::core::deterministic_aead tink::aead::internal::aead_util tink::internal::aes_util tink::internal::fips_utils tink::util::errors tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME aes_gcm_siv_boringssl SRCS aes_gcm_siv_boringssl.cc aes_gcm_siv_boringssl.h DEPS tink::subtle::random tink::subtle::subtle_util absl::memory absl::status absl::strings absl::span tink::core::aead tink::aead::internal::ssl_aead tink::internal::fips_utils tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME common_enums SRCS common_enums.cc common_enums.h DEPS absl::strings ) tink_cc_library( NAME subtle_util SRCS subtle_util.cc subtle_util.h ) tink_cc_library( NAME subtle_util_boringssl SRCS subtle_util_boringssl.h DEPS tink::subtle::common_enums absl::core_headers absl::strings crypto tink::aead::internal::aead_util tink::internal::aes_util tink::internal::bn_util tink::internal::ec_util tink::internal::err_util tink::internal::md_util tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::internal::util tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME wycheproof_util SRCS wycheproof_util.cc wycheproof_util.h DEPS tink::subtle::common_enums absl::log absl::status absl::strings rapidjson tink::internal::test_file_util tink::util::status tink::util::statusor TESTONLY ) tink_cc_library( NAME stream_segment_decrypter SRCS stream_segment_decrypter.h DEPS tink::util::status ) tink_cc_library( NAME stream_segment_encrypter SRCS stream_segment_encrypter.h DEPS tink::util::status ) tink_cc_library( NAME streaming_aead_decrypting_stream SRCS streaming_aead_decrypting_stream.cc streaming_aead_decrypting_stream.h DEPS tink::subtle::stream_segment_decrypter absl::memory absl::status tink::core::input_stream tink::util::status tink::util::statusor ) tink_cc_library( NAME streaming_aead_encrypting_stream SRCS streaming_aead_encrypting_stream.cc streaming_aead_encrypting_stream.h DEPS tink::subtle::stream_segment_encrypter absl::memory absl::status tink::core::output_stream tink::util::status tink::util::statusor ) tink_cc_library( NAME nonce_based_streaming_aead SRCS nonce_based_streaming_aead.cc nonce_based_streaming_aead.h DEPS tink::subtle::decrypting_random_access_stream tink::subtle::stream_segment_decrypter tink::subtle::stream_segment_encrypter tink::subtle::streaming_aead_decrypting_stream tink::subtle::streaming_aead_encrypting_stream absl::strings tink::core::input_stream tink::core::output_stream tink::core::random_access_stream tink::core::streaming_aead tink::util::statusor ) tink_cc_library( NAME test_util SRCS test_util.cc test_util.h DEPS tink::subtle::nonce_based_streaming_aead tink::subtle::stream_segment_decrypter tink::subtle::stream_segment_encrypter absl::memory absl::status absl::strings tink::core::input_stream tink::core::output_stream tink::util::status tink::util::statusor TESTONLY ) tink_cc_library( NAME aead_test_util SRCS aead_test_util.cc aead_test_util.h DEPS tink::subtle::test_util absl::status absl::strings absl::cord tink::core::aead tink::aead::cord_aead tink::util::status TESTONLY ) tink_cc_library( NAME streaming_aead_test_util SRCS streaming_aead_test_util.cc streaming_aead_test_util.h DEPS tink::subtle::test_util absl::memory absl::status absl::strings tink::core::input_stream tink::core::random_access_stream tink::core::streaming_aead tink::internal::test_random_access_stream tink::util::buffer tink::util::istream_input_stream tink::util::ostream_output_stream tink::util::status TESTONLY ) tink_cc_library( NAME hybrid_test_util SRCS hybrid_test_util.cc hybrid_test_util.h DEPS absl::status absl::string_view tink::core::hybrid_decrypt tink::core::hybrid_encrypt tink::util::status TESTONLY ) tink_cc_library( NAME decrypting_random_access_stream SRCS decrypting_random_access_stream.cc decrypting_random_access_stream.h DEPS tink::subtle::stream_segment_decrypter absl::core_headers absl::memory absl::status absl::strings absl::synchronization tink::core::random_access_stream tink::util::buffer tink::util::errors tink::util::status tink::util::statusor ) tink_cc_library( NAME streaming_mac_impl SRCS streaming_mac_impl.cc streaming_mac_impl.h DEPS absl::memory absl::status absl::strings absl::string_view crypto tink::core::output_stream_with_result tink::core::streaming_mac tink::subtle::mac::stateful_mac tink::util::status tink::util::statusor ) tink_cc_library( NAME stateful_hmac_boringssl SRCS stateful_hmac_boringssl.cc stateful_hmac_boringssl.h DEPS tink::subtle::common_enums absl::memory absl::status absl::string_view crypto tink::internal::md_util tink::internal::ssl_unique_ptr tink::internal::util tink::subtle::mac::stateful_mac tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME stateful_cmac_boringssl SRCS stateful_cmac_boringssl.cc stateful_cmac_boringssl.h DEPS tink::subtle::common_enums absl::memory absl::status absl::string_view crypto tink::internal::aes_util tink::internal::ssl_unique_ptr tink::internal::util tink::subtle::mac::stateful_mac tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME pem_parser_boringssl SRCS pem_parser_boringssl.cc pem_parser_boringssl.h DEPS tink::subtle::common_enums tink::subtle::subtle_util_boringssl absl::memory absl::status absl::strings crypto tink::internal::bn_util tink::internal::ec_util tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::internal::ssl_util tink::util::secret_data tink::util::status tink::util::statusor ) # tests tink_cc_test( NAME ecies_hkdf_recipient_kem_boringssl_test SRCS ecies_hkdf_recipient_kem_boringssl_test.cc DEPS tink::subtle::common_enums tink::subtle::ecies_hkdf_recipient_kem_boringssl gmock absl::status absl::strings tink::config::tink_fips tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME ecies_hkdf_sender_kem_boringssl_test SRCS ecies_hkdf_sender_kem_boringssl_test.cc DEPS tink::subtle::common_enums tink::subtle::ecies_hkdf_recipient_kem_boringssl tink::subtle::ecies_hkdf_sender_kem_boringssl gmock absl::status absl::strings tink::config::tink_fips tink::internal::ec_util tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME hkdf_test SRCS hkdf_test.cc DEPS tink::subtle::common_enums tink::subtle::hkdf gmock absl::strings tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_test( NAME aes_cmac_boringssl_test SRCS aes_cmac_boringssl_test.cc DEPS tink::subtle::aes_cmac_boringssl tink::subtle::common_enums gmock absl::status absl::strings tink::core::mac tink::config::tink_fips tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME hmac_boringssl_test SRCS hmac_boringssl_test.cc DEPS tink::subtle::common_enums tink::subtle::hmac_boringssl gmock absl::status absl::strings tink::core::mac tink::internal::fips_utils tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME aes_gcm_boringssl_test SRCS aes_gcm_boringssl_test.cc DATA wycheproof::testvectors DEPS tink::subtle::aes_gcm_boringssl gmock absl::status absl::strings tink::core::aead tink::aead::internal::wycheproof_aead tink::internal::fips_utils tink::util::secret_data tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME aes_gcm_hkdf_stream_segment_decrypter_test SRCS aes_gcm_hkdf_stream_segment_decrypter_test.cc DEPS tink::subtle::aes_gcm_hkdf_stream_segment_decrypter tink::subtle::aes_gcm_hkdf_stream_segment_encrypter tink::subtle::common_enums tink::subtle::hkdf tink::subtle::random tink::subtle::stream_segment_encrypter gmock absl::status absl::strings tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_util ) tink_cc_test( NAME aes_gcm_hkdf_stream_segment_encrypter_test SRCS aes_gcm_hkdf_stream_segment_encrypter_test.cc DEPS tink::subtle::aes_gcm_hkdf_stream_segment_encrypter tink::subtle::random gmock absl::status absl::strings tink::util::status tink::util::statusor tink::util::test_util ) tink_cc_test( NAME aes_gcm_hkdf_streaming_test SRCS aes_gcm_hkdf_streaming_test.cc DEPS tink::subtle::aes_gcm_hkdf_streaming tink::subtle::common_enums tink::subtle::random tink::subtle::streaming_aead_test_util tink::subtle::test_util gmock absl::memory absl::status absl::statusor absl::strings tink::core::output_stream tink::core::random_access_stream tink::config::tink_fips tink::internal::test_random_access_stream tink::util::istream_input_stream tink::util::ostream_output_stream tink::util::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME aes_ctr_hmac_streaming_test SRCS aes_ctr_hmac_streaming_test.cc DEPS tink::subtle::aes_ctr_hmac_streaming tink::subtle::common_enums tink::subtle::random tink::subtle::stream_segment_decrypter tink::subtle::stream_segment_encrypter tink::subtle::streaming_aead_test_util gmock absl::memory absl::status absl::statusor absl::strings tink::core::random_access_stream tink::config::tink_fips tink::internal::test_random_access_stream tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util ) tink_cc_test( NAME aes_eax_boringssl_test SRCS aes_eax_boringssl_test.cc DATA wycheproof::testvectors DEPS tink::subtle::aes_eax_boringssl tink::subtle::wycheproof_util gmock absl::status absl::strings crypto rapidjson tink::config::tink_fips tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util ) tink_cc_test( NAME encrypt_then_authenticate_test SRCS encrypt_then_authenticate_test.cc DEPS tink::subtle::aes_ctr_boringssl tink::subtle::common_enums tink::subtle::encrypt_then_authenticate tink::subtle::hmac_boringssl tink::subtle::random gmock absl::strings tink::core::aead tink::util::secret_data tink::util::statusor tink::util::test_util ) tink_cc_test( NAME aes_ctr_boringssl_test SRCS aes_ctr_boringssl_test.cc DEPS tink::subtle::aes_ctr_boringssl tink::subtle::random gmock absl::status tink::internal::fips_utils tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util ) tink_cc_test( NAME aes_siv_boringssl_test SRCS aes_siv_boringssl_test.cc DATA wycheproof::testvectors DEPS tink::subtle::aes_siv_boringssl tink::subtle::wycheproof_util gmock absl::status absl::string_view rapidjson tink::config::tink_fips tink::util::secret_data tink::util::statusor tink::util::test_matchers tink::util::test_util ) tink_cc_test( NAME ecdsa_sign_boringssl_test SRCS ecdsa_sign_boringssl_test.cc DEPS tink::subtle::common_enums tink::subtle::ecdsa_sign_boringssl tink::subtle::ecdsa_verify_boringssl tink::subtle::subtle_util_boringssl gmock absl::status absl::string_view tink::core::public_key_sign tink::core::public_key_verify tink::internal::ec_util tink::internal::fips_utils tink::util::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME ecdsa_verify_boringssl_test SRCS ecdsa_verify_boringssl_test.cc DATA wycheproof::testvectors DEPS tink::subtle::common_enums tink::subtle::ecdsa_sign_boringssl tink::subtle::ecdsa_verify_boringssl tink::subtle::subtle_util_boringssl tink::subtle::wycheproof_util gmock absl::status absl::strings rapidjson tink::core::public_key_sign tink::core::public_key_verify tink::internal::fips_utils tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util ) tink_cc_test( NAME ed25519_sign_boringssl_test SRCS ed25519_sign_boringssl_test.cc DEPS tink::subtle::ed25519_sign_boringssl tink::subtle::ed25519_verify_boringssl tink::subtle::random gmock absl::status absl::strings crypto tink::core::public_key_sign tink::core::public_key_verify tink::config::tink_fips tink::internal::ec_util tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME ed25519_verify_boringssl_test SRCS ed25519_verify_boringssl_test.cc DATA wycheproof::testvectors DEPS tink::subtle::ed25519_verify_boringssl tink::subtle::wycheproof_util gmock absl::status absl::strings crypto rapidjson tink::core::public_key_verify tink::config::tink_fips tink::internal::ec_util tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME rsa_ssa_pss_verify_boringssl_test SRCS rsa_ssa_pss_verify_boringssl_test.cc DATA wycheproof::testvectors DEPS tink::subtle::common_enums tink::subtle::rsa_ssa_pss_verify_boringssl tink::subtle::wycheproof_util gmock absl::status absl::strings crypto rapidjson tink::core::public_key_sign tink::core::public_key_verify tink::internal::err_util tink::internal::fips_utils tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::util::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME rsa_ssa_pss_sign_boringssl_test SRCS rsa_ssa_pss_sign_boringssl_test.cc DEPS tink::subtle::common_enums tink::subtle::rsa_ssa_pss_sign_boringssl tink::subtle::rsa_ssa_pss_verify_boringssl gmock absl::status absl::strings crypto tink::internal::fips_utils tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::util::test_matchers ) tink_cc_test( NAME rsa_ssa_pkcs1_verify_boringssl_test SRCS rsa_ssa_pkcs1_verify_boringssl_test.cc DATA wycheproof::testvectors DEPS tink::subtle::common_enums tink::subtle::rsa_ssa_pkcs1_verify_boringssl tink::subtle::wycheproof_util gmock absl::status absl::strings crypto rapidjson tink::core::public_key_sign tink::core::public_key_verify tink::internal::err_util tink::internal::fips_utils tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::util::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME rsa_ssa_pkcs1_sign_boringssl_test SRCS rsa_ssa_pkcs1_sign_boringssl_test.cc DEPS tink::subtle::common_enums tink::subtle::rsa_ssa_pkcs1_sign_boringssl tink::subtle::rsa_ssa_pkcs1_verify_boringssl gmock absl::status absl::strings crypto tink::internal::fips_utils tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::util::test_matchers ) tink_cc_test( NAME aes_gcm_siv_boringssl_test SRCS aes_gcm_siv_boringssl_test.cc DATA wycheproof::testvectors DEPS tink::subtle::aes_gcm_siv_boringssl tink::subtle::subtle_util gmock absl::status absl::strings tink::core::aead tink::aead::internal::wycheproof_aead tink::config::tink_fips tink::internal::ssl_util tink::util::secret_data tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME random_test SRCS random_test.cc DEPS tink::subtle::random gmock absl::flat_hash_set absl::span tink::util::secret_data tink::util::test_matchers ) tink_cc_test( NAME common_enums_test SRCS common_enums_test.cc DEPS tink::subtle::common_enums gmock ) tink_cc_test( NAME subtle_util_test SRCS subtle_util_test.cc DEPS tink::subtle::subtle_util gmock ) tink_cc_test( NAME xchacha20_poly1305_boringssl_test SRCS xchacha20_poly1305_boringssl_test.cc DATA wycheproof::testvectors DEPS tink::subtle::subtle_util tink::subtle::xchacha20_poly1305_boringssl gmock absl::status absl::strings tink::core::aead tink::aead::internal::wycheproof_aead tink::config::tink_fips tink::internal::ssl_util tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME streaming_aead_decrypting_stream_test SRCS streaming_aead_decrypting_stream_test.cc DEPS tink::subtle::random tink::subtle::stream_segment_decrypter tink::subtle::streaming_aead_decrypting_stream tink::subtle::test_util gmock absl::memory absl::status absl::strings tink::core::input_stream tink::util::istream_input_stream tink::util::status tink::util::statusor ) tink_cc_test( NAME streaming_aead_encrypting_stream_test SRCS streaming_aead_encrypting_stream_test.cc DEPS tink::subtle::random tink::subtle::stream_segment_encrypter tink::subtle::streaming_aead_encrypting_stream tink::subtle::test_util gmock absl::memory absl::status absl::strings tink::core::output_stream tink::util::ostream_output_stream tink::util::status tink::util::statusor ) tink_cc_test( NAME aead_test_util_test SRCS aead_test_util_test.cc DEPS tink::subtle::aead_test_util gmock tink::util::test_matchers tink::util::test_util ) tink_cc_test( NAME streaming_aead_test_util_test SRCS streaming_aead_test_util_test.cc DEPS tink::subtle::streaming_aead_test_util gmock absl::status tink::util::test_matchers tink::util::test_util ) tink_cc_test( NAME hybrid_test_util_test SRCS hybrid_test_util_test.cc DEPS tink::subtle::hybrid_test_util gmock tink::util::test_matchers tink::util::test_util ) tink_cc_test( NAME decrypting_random_access_stream_test SRCS decrypting_random_access_stream_test.cc DEPS tink::subtle::decrypting_random_access_stream tink::subtle::random tink::subtle::test_util gmock absl::memory absl::status absl::strings tink::core::output_stream tink::core::random_access_stream tink::core::streaming_aead tink::internal::test_random_access_stream tink::util::buffer tink::util::ostream_output_stream tink::util::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME streaming_mac_impl_test SRCS streaming_mac_impl_test.cc DEPS tink::subtle::random tink::subtle::streaming_mac_impl tink::subtle::test_util gmock absl::memory absl::status tink::core::output_stream_with_result tink::subtle::mac::stateful_mac tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util ) tink_cc_test( NAME stateful_hmac_boringssl_test SRCS stateful_hmac_boringssl_test.cc DATA wycheproof::testvectors DEPS tink::subtle::common_enums tink::subtle::random tink::subtle::stateful_hmac_boringssl gmock absl::log absl::memory absl::status absl::string_view tink::subtle::mac::stateful_mac tink::util::secret_data tink::util::statusor tink::util::test_matchers tink::util::test_util ) tink_cc_test( NAME stateful_cmac_boringssl_test SRCS stateful_cmac_boringssl_test.cc DATA wycheproof::testvectors DEPS tink::subtle::common_enums tink::subtle::stateful_cmac_boringssl tink::subtle::wycheproof_util gmock absl::memory absl::status absl::strings rapidjson tink::subtle::mac::stateful_mac tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers ) tink_cc_test( NAME pem_parser_boringssl_test SRCS pem_parser_boringssl_test.cc DEPS tink::subtle::common_enums tink::subtle::pem_parser_boringssl tink::subtle::subtle_util_boringssl gmock absl::status absl::strings crypto tink::internal::bn_util tink::internal::err_util tink::internal::rsa_util tink::internal::ssl_unique_ptr tink::internal::ssl_util tink::util::secret_data tink::util::status tink::util::statusor tink::util::test_matchers ) ================================================ FILE: cc/subtle/aead_test_util.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/aead_test_util.h" #include #include "absl/status/status.h" #include "absl/strings/cord.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/aead/cord_aead.h" #include "tink/subtle/test_util.h" #include "tink/util/status.h" namespace crypto { namespace tink { using ::crypto::tink::util::StatusOr; crypto::tink::util::Status EncryptThenDecrypt(const Aead& encrypter, const Aead& decrypter, absl::string_view message, absl::string_view aad) { StatusOr encryption_or = encrypter.Encrypt(message, aad); if (!encryption_or.status().ok()) return encryption_or.status(); StatusOr decryption_or = decrypter.Decrypt(encryption_or.value(), aad); if (!decryption_or.status().ok()) return decryption_or.status(); if (decryption_or.value() != message) { return crypto::tink::util::Status(absl::StatusCode::kInternal, "Message/Decryption mismatch"); } return util::OkStatus(); } crypto::tink::util::Status EncryptThenDecrypt(const CordAead& encrypter, const CordAead& decrypter, absl::string_view message, absl::string_view aad) { absl::Cord message_cord = absl::Cord(message); absl::Cord aad_cord = absl::Cord(aad); StatusOr encryption_or = encrypter.Encrypt(message_cord, aad_cord); if (!encryption_or.status().ok()) return encryption_or.status(); StatusOr decryption_or = decrypter.Decrypt(encryption_or.value(), aad_cord); if (!decryption_or.status().ok()) return decryption_or.status(); if (decryption_or.value() != message) { return crypto::tink::util::Status(absl::StatusCode::kInternal, "Message/Decryption mismatch"); } return util::OkStatus(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/aead_test_util.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_AEAD_TEST_UTIL_H_ #define TINK_SUBTLE_AEAD_TEST_UTIL_H_ #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/aead/cord_aead.h" #include "tink/util/status.h" namespace crypto { namespace tink { // Encrypt, then decrypt. Any error will be propagated to the caller. Returns OK // if the resulting decryption is equal to the plaintext. crypto::tink::util::Status EncryptThenDecrypt(const Aead& encrypter, const Aead& decrypter, absl::string_view message, absl::string_view aad); // Encrypt, then decrypt. Any error will be propagated to the caller. Returns OK // if the resulting decryption is equal to the plaintext. crypto::tink::util::Status EncryptThenDecrypt(const CordAead& encrypter, const CordAead& decrypter, absl::string_view message, absl::string_view aad); } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_AEAD_TEST_UTIL_H_ ================================================ FILE: cc/subtle/aead_test_util_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/aead_test_util.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { using ::crypto::tink::test::IsOk; using ::testing::Not; namespace { TEST(EncryptThenDecrypt, Basic) { test::DummyAead aead("Aead 1"); EXPECT_THAT(EncryptThenDecrypt(aead, aead, "plaintext", "aad"), IsOk()); } TEST(EncryptThenDecrypt, DifferentAeads) { test::DummyAead aead_1("Aead 1"); test::DummyAead aead_2("Aead 2"); EXPECT_THAT(EncryptThenDecrypt(aead_1, aead_2, "plaintext", "aad"), Not(IsOk())); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/aes_cmac_boringssl.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/aes_cmac_boringssl.h" #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "openssl/cmac.h" #include "openssl/evp.h" #include "tink/internal/aes_util.h" #include "tink/internal/call_with_core_dump_protection.h" #include "tink/internal/fips_utils.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/internal/util.h" #include "tink/mac.h" #include "tink/subtle/subtle_util.h" #include "tink/util/errors.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // CMAC key sizes in bytes. // The small key size is used only to check RFC 4493's test vectors due to // the attack described in // https://www.math.uwaterloo.ca/~ajmeneze/publications/tightness.pdf. We // check this restriction in AesCmacManager. static constexpr size_t kSmallKeySize = 16; static constexpr size_t kBigKeySize = 32; static constexpr size_t kMaxTagSize = 16; // static util::StatusOr> AesCmacBoringSsl::New(util::SecretData key, uint32_t tag_size) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) return status; if (key.size() != kSmallKeySize && key.size() != kBigKeySize) { return ToStatusF(absl::StatusCode::kInvalidArgument, "Invalid key size: expected %d or %d, found %d", kSmallKeySize, kBigKeySize, key.size()); } if (tag_size > kMaxTagSize) { return ToStatusF(absl::StatusCode::kInvalidArgument, "Invalid tag size: expected lower than %d, found %d", kMaxTagSize, tag_size); } return {absl::WrapUnique(new AesCmacBoringSsl(std::move(key), tag_size))}; } util::StatusOr AesCmacBoringSsl::ComputeMac( absl::string_view data) const { // BoringSSL expects a non-null pointer for data, // regardless of whether the size is 0. data = internal::EnsureStringNonNull(data); std::string result; ResizeStringUninitialized(&result, kMaxTagSize); internal::SslUniquePtr context(CMAC_CTX_new()); util::StatusOr cipher = internal::GetAesCbcCipherForKeySize(key_.size()); if (!cipher.ok()) { return cipher.status(); } size_t len = 0; const uint8_t* data_ptr = reinterpret_cast(data.data()); uint8_t* result_ptr = reinterpret_cast(&result[0]); bool res = internal::CallWithCoreDumpProtection([&]() { if (CMAC_Init(context.get(), key_.data(), key_.size(), *cipher, nullptr) <= 0 || CMAC_Update(context.get(), data_ptr, data.size()) <= 0 || CMAC_Final(context.get(), result_ptr, &len) == 0) { return false; } result.resize(tag_size_); return true; }); if (!res) { return util::Status(absl::StatusCode::kInternal, "Failed to compute CMAC"); } return result; } util::Status AesCmacBoringSsl::VerifyMac(absl::string_view mac, absl::string_view data) const { if (mac.size() != tag_size_) { return ToStatusF(absl::StatusCode::kInvalidArgument, "Incorrect tag size: expected %d, found %d", tag_size_, mac.size()); } return internal::CallWithCoreDumpProtection([&]() { util::StatusOr computed_mac = ComputeMac(data); if (!computed_mac.ok()) return computed_mac.status(); if (CRYPTO_memcmp(computed_mac->data(), mac.data(), tag_size_) != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "CMAC verification failed"); } return util::OkStatus(); }); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/aes_cmac_boringssl.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_AES_CMAC_BORINGSSL_H_ #define TINK_SUBTLE_AES_CMAC_BORINGSSL_H_ #include #include #include #include #include "absl/strings/string_view.h" #include "tink/internal/fips_utils.h" #include "tink/mac.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { class AesCmacBoringSsl : public Mac { public: static crypto::tink::util::StatusOr> New( util::SecretData key, uint32_t tag_size); // Computes and returns the CMAC for 'data'. crypto::tink::util::StatusOr ComputeMac( absl::string_view data) const override; // Verifies if 'mac' is a correct CMAC for 'data'. // Returns Status::OK if 'mac' is correct, and a non-OK-Status otherwise. crypto::tink::util::Status VerifyMac(absl::string_view mac, absl::string_view data) const override; static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kNotFips; private: AesCmacBoringSsl(util::SecretData key, uint32_t tag_size) : key_(std::move(key)), tag_size_(tag_size) {} const util::SecretData key_; const uint32_t tag_size_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_AES_CMAC_BORINGSSL_H_ ================================================ FILE: cc/subtle/aes_cmac_boringssl_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/aes_cmac_boringssl.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/string_view.h" #include "tink/config/tink_fips.h" #include "tink/mac.h" #include "tink/subtle/common_enums.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Not; using ::testing::SizeIs; constexpr uint32_t kTagSize = 16; constexpr uint32_t kSmallTagSize = 10; constexpr absl::string_view kKey256Hex = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"; constexpr absl::string_view kMessage = "Some data to test."; TEST(AesCmacBoringSslTest, Basic) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::SecretData key = util::SecretDataFromStringView(absl::HexStringToBytes(kKey256Hex)); util::StatusOr> cmac = AesCmacBoringSsl::New(key, kTagSize); ASSERT_THAT(cmac, IsOk()); { // Test with some example data. util::StatusOr tag = (*cmac)->ComputeMac(kMessage); EXPECT_THAT(tag, IsOk()); EXPECT_THAT(*tag, SizeIs(kTagSize)); EXPECT_THAT((*cmac)->VerifyMac(*tag, kMessage), IsOk()) << "tag:" << absl::BytesToHexString(*tag); } { // Test with empty example data. absl::string_view data; util::StatusOr tag = (*cmac)->ComputeMac(data); EXPECT_THAT(tag, IsOk()); EXPECT_THAT(*tag, SizeIs(kTagSize)); EXPECT_THAT((*cmac)->VerifyMac(*tag, data), IsOk()) << "tag:" << absl::BytesToHexString(*tag); } } TEST(AesCmacBoringSslTest, Modification) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::SecretData key = util::SecretDataFromStringView(absl::HexStringToBytes(kKey256Hex)); util::StatusOr> cmac = AesCmacBoringSsl::New(key, kTagSize); ASSERT_THAT(cmac, IsOk()); util::StatusOr tag = (*cmac)->ComputeMac(kMessage); ASSERT_THAT(tag, IsOk()); EXPECT_THAT((*cmac)->VerifyMac(*tag, kMessage), IsOk()); const size_t num_bits = tag->size() * 8; for (size_t i = 0; i < num_bits; i++) { std::string modified_tag = *tag; modified_tag[i / 8] ^= 1 << (i % 8); EXPECT_THAT((*cmac)->VerifyMac(modified_tag, kMessage), Not(IsOk())) << "tag:" << absl::BytesToHexString(*tag) << " modified:" << absl::BytesToHexString(modified_tag); } } TEST(AesCmacBoringSslTest, Truncation) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::SecretData key = util::SecretDataFromStringView(absl::HexStringToBytes(kKey256Hex)); util::StatusOr> cmac = AesCmacBoringSsl::New(key, kTagSize); ASSERT_THAT(cmac, IsOk()); util::StatusOr tag = (*cmac)->ComputeMac(kMessage); ASSERT_THAT(tag, IsOk()); EXPECT_THAT((*cmac)->VerifyMac(*tag, kMessage), IsOk()); for (size_t i = 0; i < tag->size(); i++) { std::string modified_tag(*tag, 0, i); EXPECT_FALSE((*cmac)->VerifyMac(modified_tag, kMessage).ok()) << "tag:" << absl::BytesToHexString(*tag) << " modified:" << absl::BytesToHexString(modified_tag); } } TEST(AesCmacBoringSslTest, BasicSmallTag) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::SecretData key = util::SecretDataFromStringView(absl::HexStringToBytes(kKey256Hex)); util::StatusOr> cmac = AesCmacBoringSsl::New(key, kSmallTagSize); EXPECT_THAT(cmac, IsOk()); { // Test with some example data. std::string data = "Some data to test."; util::StatusOr tag = (*cmac)->ComputeMac(data); EXPECT_THAT(tag, IsOk()); EXPECT_EQ(kSmallTagSize, tag->size()); EXPECT_THAT((*cmac)->VerifyMac(*tag, data), IsOk()) << "tag:" << absl::BytesToHexString(*tag); } { // Test with empty example data. absl::string_view data; util::StatusOr tag = (*cmac)->ComputeMac(data); EXPECT_THAT(tag, IsOk()); EXPECT_EQ(kSmallTagSize, tag->size()); EXPECT_THAT((*cmac)->VerifyMac(*tag, data), IsOk()) << "tag:" << absl::BytesToHexString(*tag); } } TEST(AesCmacBoringSslTest, ModificationSmallTag) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::SecretData key = util::SecretDataFromStringView(absl::HexStringToBytes(kKey256Hex)); util::StatusOr> cmac = AesCmacBoringSsl::New(key, kSmallTagSize); ASSERT_THAT(cmac, IsOk()); util::StatusOr tag = (*cmac)->ComputeMac(kMessage); ASSERT_THAT(tag, IsOk()); auto status = (*cmac)->VerifyMac(*tag, kMessage); EXPECT_THAT((*cmac)->VerifyMac(*tag, kMessage), IsOk()); size_t num_bits = tag->size() * 8; for (size_t i = 0; i < num_bits; i++) { std::string modified_tag = *tag; modified_tag[i / 8] ^= 1 << (i % 8); EXPECT_THAT((*cmac)->VerifyMac(modified_tag, kMessage), Not(IsOk())) << "tag:" << absl::BytesToHexString(*tag) << " modified:" << absl::BytesToHexString(modified_tag); } } TEST(AesCmacBoringSslTest, TruncationOrAdditionSmallTag) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::SecretData key = util::SecretDataFromStringView(absl::HexStringToBytes(kKey256Hex)); util::StatusOr> cmac = AesCmacBoringSsl::New(key, kSmallTagSize); ASSERT_THAT(cmac, IsOk()); util::StatusOr tag = (*cmac)->ComputeMac(kMessage); ASSERT_THAT(tag, IsOk()); EXPECT_THAT((*cmac)->VerifyMac(*tag, kMessage), IsOk()); for (size_t i = 0; i < kSmallTagSize; i++) { std::string modified_tag(*tag, 0, i); EXPECT_THAT((*cmac)->VerifyMac(modified_tag, kMessage), Not(IsOk())) << "tag:" << absl::BytesToHexString(*tag) << " modified:" << absl::BytesToHexString(modified_tag); } for (size_t i = kSmallTagSize + 1; i < kTagSize; i++) { std::string modified_tag(*tag + std::string(i - kSmallTagSize, 'x')); EXPECT_THAT((*cmac)->VerifyMac(modified_tag, kMessage), Not(IsOk())) << "tag:" << absl::BytesToHexString(*tag) << " modified:" << absl::BytesToHexString(modified_tag); } } TEST(AesCmacBoringSslTest, InvalidKeySizes) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } for (int keysize = 0; keysize < 65; keysize++) { util::SecretData key(keysize, 'x'); util::StatusOr> cmac = AesCmacBoringSsl::New(key, kTagSize); if (keysize == 16 || keysize == 32) { EXPECT_THAT(cmac, IsOk()); } else { EXPECT_THAT(cmac, Not(IsOk())); } } } TEST(AesCmacBoringSslTest, InvalidTagSizes) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } for (int tagsize = 0; tagsize < 65; tagsize++) { util::SecretData key(32, 'x'); util::StatusOr> cmac = AesCmacBoringSsl::New(key, tagsize); if (tagsize <= 16) { EXPECT_THAT(cmac, IsOk()); } else { EXPECT_THAT(cmac, Not(IsOk())); } } } class AesCmacBoringSslTestVectorTest : public ::testing::TestWithParam> { public: // Utility to simplify testing with test vectors. Parameters are in // hexadecimal. void ExpectCmacVerifyHex(absl::string_view key_hex, absl::string_view tag_hex, absl::string_view data_hex) { util::SecretData key = util::SecretDataFromStringView(absl::HexStringToBytes(key_hex)); std::string tag = absl::HexStringToBytes(tag_hex); std::string data = absl::HexStringToBytes(data_hex); util::StatusOr> cmac = AesCmacBoringSsl::New(key, kTagSize); EXPECT_THAT(cmac, IsOk()); EXPECT_THAT((*cmac)->VerifyMac(tag, data), IsOk()); } }; TEST_P(AesCmacBoringSslTestVectorTest, RfcTestVectors) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } // Test vectors from RFC 4493. std::string key("2b7e151628aed2a6abf7158809cf4f3c"); std::string data( "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46" "a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"); ExpectCmacVerifyHex(key, GetParam().second, data.substr(0, 2 * GetParam().first)); } INSTANTIATE_TEST_SUITE_P( RfcTest, AesCmacBoringSslTestVectorTest, testing::Values(std::make_pair(0, "bb1d6929e95937287fa37d129b756746"), std::make_pair(16, "070a16b46b4d4144f79bdd9dd04a287c"), std::make_pair(40, "dfa66747de9ae63030ca32611497c827"), std::make_pair(64, "51f0bebf7e3b9d92fc49741779363cfe"))); TEST(AesCmacBoringSslTest, TestFipsOnly) { if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Only supported in FIPS-only mode"; } util::SecretData key128 = util::SecretDataFromStringView( absl::HexStringToBytes("000102030405060708090a0b0c0d0e0f")); util::SecretData key256 = util::SecretDataFromStringView(absl::HexStringToBytes(kKey256Hex)); EXPECT_THAT(subtle::AesCmacBoringSsl::New(key128, kTagSize).status(), StatusIs(absl::StatusCode::kInternal)); EXPECT_THAT(subtle::AesCmacBoringSsl::New(key256, kTagSize).status(), StatusIs(absl::StatusCode::kInternal)); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/aes_ctr_boringssl.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/aes_ctr_boringssl.h" #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "tink/internal/aes_util.h" #include "tink/internal/fips_utils.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/internal/util.h" #include "tink/subtle/ind_cpa_cipher.h" #include "tink/subtle/random.h" #include "tink/subtle/subtle_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { util::StatusOr> AesCtrBoringSsl::New( util::SecretData key, int iv_size) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) return status; util::StatusOr cipher = internal::GetAesCtrCipherForKeySize(key.size()); if (!cipher.ok()) { return cipher.status(); } if (iv_size < kMinIvSizeInBytes || iv_size > kBlockSize) { return util::Status(absl::StatusCode::kInvalidArgument, "invalid iv size"); } return { absl::WrapUnique(new AesCtrBoringSsl(std::move(key), iv_size, *cipher))}; } util::StatusOr AesCtrBoringSsl::Encrypt( absl::string_view plaintext) const { // BoringSSL expects a non-null pointer for plaintext, regardless of whether // the size is 0. plaintext = internal::EnsureStringNonNull(plaintext); internal::SslUniquePtr ctx(EVP_CIPHER_CTX_new()); if (ctx.get() == nullptr) { return util::Status(absl::StatusCode::kInternal, "could not initialize EVP_CIPHER_CTX"); } std::string ciphertext = Random::GetRandomBytes(iv_size_); // OpenSSL expects that the IV must be a full block. We pad with zeros. std::string iv_block = ciphertext; // Note that kBlockSize >= iv_size_ is checked in the factory method. // We explicitly add the '\0' argument to stress that we need to initialize // the new memory. iv_block.resize(kBlockSize, '\0'); int ret = EVP_EncryptInit_ex(ctx.get(), cipher_, nullptr /* engine */, key_.data(), reinterpret_cast(&iv_block[0])); if (ret != 1) { return util::Status(absl::StatusCode::kInternal, "could not initialize ctx"); } ResizeStringUninitialized(&ciphertext, iv_size_ + plaintext.size()); int len; ret = EVP_EncryptUpdate( ctx.get(), reinterpret_cast(&ciphertext[iv_size_]), &len, reinterpret_cast(plaintext.data()), plaintext.size()); if (ret != 1) { return util::Status(absl::StatusCode::kInternal, "encryption failed"); } if (len != plaintext.size()) { return util::Status(absl::StatusCode::kInternal, "incorrect ciphertext size"); } return ciphertext; } util::StatusOr AesCtrBoringSsl::Decrypt( absl::string_view ciphertext) const { if (ciphertext.size() < iv_size_) { return util::Status(absl::StatusCode::kInvalidArgument, "ciphertext too short"); } internal::SslUniquePtr ctx(EVP_CIPHER_CTX_new()); if (ctx.get() == nullptr) { return util::Status(absl::StatusCode::kInternal, "could not initialize EVP_CIPHER_CTX"); } // Initialise key and IV std::string iv_block = std::string(ciphertext.substr(0, iv_size_)); iv_block.resize(kBlockSize, '\0'); int ret = EVP_DecryptInit_ex(ctx.get(), cipher_, nullptr /* engine */, reinterpret_cast(key_.data()), reinterpret_cast(&iv_block[0])); if (ret != 1) { return util::Status(absl::StatusCode::kInternal, "could not initialize key or iv"); } size_t plaintext_size = ciphertext.size() - iv_size_; std::string plaintext; ResizeStringUninitialized(&plaintext, plaintext_size); size_t read = iv_size_; int len; ret = EVP_DecryptUpdate( ctx.get(), reinterpret_cast(&plaintext[0]), &len, reinterpret_cast(&ciphertext.data()[read]), plaintext_size); if (ret != 1) { return util::Status(absl::StatusCode::kInternal, "decryption failed"); } if (len != plaintext_size) { return util::Status(absl::StatusCode::kInternal, "incorrect plaintext size"); } return plaintext; } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/aes_ctr_boringssl.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_AES_CTR_BORINGSSL_H_ #define TINK_SUBTLE_AES_CTR_BORINGSSL_H_ #include #include #include #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "tink/internal/fips_utils.h" #include "tink/subtle/ind_cpa_cipher.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { class AesCtrBoringSsl : public IndCpaCipher { public: static crypto::tink::util::StatusOr> New( util::SecretData key, int iv_size); crypto::tink::util::StatusOr Encrypt( absl::string_view plaintext) const override; crypto::tink::util::StatusOr Decrypt( absl::string_view ciphertext) const override; static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kRequiresBoringCrypto; private: static constexpr int kMinIvSizeInBytes = 12; static constexpr int kBlockSize = 16; AesCtrBoringSsl(util::SecretData key, int iv_size, const EVP_CIPHER* cipher) : key_(std::move(key)), iv_size_(iv_size), cipher_(cipher) {} const util::SecretData key_; const int iv_size_; // cipher_ is a singleton owned by BoringSsl. const EVP_CIPHER *cipher_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_AES_CTR_BORINGSSL_H_ ================================================ FILE: cc/subtle/aes_ctr_boringssl_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/aes_ctr_boringssl.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/internal/fips_utils.h" #include "tink/subtle/random.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; TEST(AesCtrBoringSslTest, TestEncryptDecrypt) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test should not run in FIPS mode when BoringCrypto is unavailable."; } util::SecretData key = util::SecretDataFromStringView( test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f")); int iv_size = 12; auto res = AesCtrBoringSsl::New(key, iv_size); EXPECT_TRUE(res.ok()) << res.status(); auto cipher = std::move(res.value()); std::string message = "Some data to encrypt."; auto ct = cipher->Encrypt(message); EXPECT_TRUE(ct.ok()) << ct.status(); EXPECT_EQ(ct.value().size(), message.size() + iv_size); auto pt = cipher->Decrypt(ct.value()); EXPECT_TRUE(pt.ok()) << pt.status(); EXPECT_EQ(pt.value(), message); } TEST(AesCtrBoringSslTest, TestEncryptDecrypt_randomMessage) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test should not run in FIPS mode when BoringCrypto is unavailable."; } util::SecretData key = util::SecretDataFromStringView( test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f")); int iv_size = 12; auto res = AesCtrBoringSsl::New(key, iv_size); EXPECT_TRUE(res.ok()) << res.status(); auto cipher = std::move(res.value()); for (int i = 0; i < 256; i++) { std::string message = Random::GetRandomBytes(i); auto ct = cipher->Encrypt(message); EXPECT_TRUE(ct.ok()) << ct.status(); EXPECT_EQ(ct.value().size(), message.size() + iv_size); auto pt = cipher->Decrypt(ct.value()); EXPECT_TRUE(pt.ok()) << pt.status(); EXPECT_EQ(pt.value(), message); } } TEST(AesCtrBoringSslTest, TestEncryptDecrypt_randomKey_randomMessage) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test should not run in FIPS mode when BoringCrypto is unavailable."; } for (int i = 0; i < 256; i++) { util::SecretData key = Random::GetRandomKeyBytes(16); int iv_size = 12; auto res = AesCtrBoringSsl::New(key, iv_size); EXPECT_TRUE(res.ok()) << res.status(); auto cipher = std::move(res.value()); std::string message = Random::GetRandomBytes(i); auto ct = cipher->Encrypt(message); EXPECT_TRUE(ct.ok()) << ct.status(); EXPECT_EQ(ct.value().size(), message.size() + iv_size); auto pt = cipher->Decrypt(ct.value()); EXPECT_TRUE(pt.ok()) << pt.status(); EXPECT_EQ(pt.value(), message); } } TEST(AesCtrBoringSslTest, TestEncryptDecrypt_invalidIvSize) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test should not run in FIPS mode when BoringCrypto is unavailable."; } util::SecretData key = util::SecretDataFromStringView( test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f")); int iv_size = 11; auto res1 = AesCtrBoringSsl::New(key, iv_size); EXPECT_FALSE(res1.ok()) << res1.status(); iv_size = 17; auto res2 = AesCtrBoringSsl::New(key, iv_size); EXPECT_FALSE(res2.ok()) << res2.status(); } TEST(AesCtrBoringSslTest, TestNistTestVector) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test should not run in FIPS mode when BoringCrypto is unavailable."; } // NIST SP 800-38A pp 55. util::SecretData key = util::SecretDataFromStringView( test::HexDecodeOrDie("2b7e151628aed2a6abf7158809cf4f3c")); std::string ciphertext(test::HexDecodeOrDie( "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff874d6191b620e3261bef6864990db6ce")); std::string message(test::HexDecodeOrDie("6bc1bee22e409f96e93d7e117393172a")); int iv_size = 16; auto res = AesCtrBoringSsl::New(key, iv_size); EXPECT_TRUE(res.ok()) << res.status(); auto cipher = std::move(res.value()); auto pt = cipher->Decrypt(ciphertext); EXPECT_TRUE(pt.ok()) << pt.status(); EXPECT_EQ(pt.value(), message); } TEST(AesCtrBoringSslTest, TestMultipleEncrypt) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test should not run in FIPS mode when BoringCrypto is unavailable."; } util::SecretData key = Random::GetRandomKeyBytes(16); int iv_size = 12; auto res = AesCtrBoringSsl::New(key, iv_size); EXPECT_TRUE(res.ok()) << res.status(); auto cipher = std::move(res.value()); std::string message = "Some data to encrypt."; auto ct1 = cipher->Encrypt(message); auto ct2 = cipher->Encrypt(message); EXPECT_NE(ct1.value(), ct2.value()); } TEST(AesCtrBoringSslTest, TestFipsOnly) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test should not run in FIPS mode when BoringCrypto is unavailable."; } util::SecretData key128 = util::SecretDataFromStringView( test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f")); util::SecretData key256 = util::SecretDataFromStringView(test::HexDecodeOrDie( "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f")); EXPECT_THAT(subtle::AesCtrBoringSsl::New(key128, 16), IsOk()); EXPECT_THAT(subtle::AesCtrBoringSsl::New(key256, 16), IsOk()); } TEST(AesCtrBoringSslTest, TestFipsFailWithoutBoringCrypto) { if (!internal::IsFipsModeEnabled() || internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test assumes kOnlyUseFips but BoringCrypto is unavailable."; } util::SecretData key128 = util::SecretDataFromStringView( test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f")); util::SecretData key256 = util::SecretDataFromStringView(test::HexDecodeOrDie( "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f")); EXPECT_THAT(subtle::AesCtrBoringSsl::New(key128, 16).status(), StatusIs(absl::StatusCode::kInternal)); EXPECT_THAT(subtle::AesCtrBoringSsl::New(key256, 16).status(), StatusIs(absl::StatusCode::kInternal)); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/aes_ctr_hmac_streaming.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/aes_ctr_hmac_streaming.h" #include #include #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "openssl/err.h" #include "openssl/evp.h" #include "tink/internal/aes_util.h" #include "tink/internal/fips_utils.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/hkdf.h" #include "tink/subtle/hmac_boringssl.h" #include "tink/subtle/random.h" #include "tink/subtle/stream_segment_decrypter.h" #include "tink/subtle/stream_segment_encrypter.h" #include "tink/subtle/subtle_util.h" #include "tink/util/errors.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { static std::string NonceForSegment(absl::string_view nonce_prefix, int64_t segment_number, bool is_last_segment) { return absl::StrCat( nonce_prefix, BigEndian32(segment_number), is_last_segment ? std::string(1, '\x01') : std::string(1, '\x00'), std::string(4, '\x00')); } static util::Status DeriveKeys(const util::SecretData& ikm, HashType hkdf_algo, absl::string_view salt, absl::string_view associated_data, int key_size, util::SecretData* key_value, util::SecretData* hmac_key_value) { int derived_key_material_size = key_size + AesCtrHmacStreaming::kHmacKeySizeInBytes; auto hkdf_result = Hkdf::ComputeHkdf(hkdf_algo, ikm, salt, associated_data, derived_key_material_size); if (!hkdf_result.ok()) return hkdf_result.status(); util::SecretData key_material = std::move(hkdf_result.value()); *key_value = util::SecretData(key_material.begin(), key_material.begin() + key_size); *hmac_key_value = util::SecretData(key_material.begin() + key_size, key_material.end()); return util::OkStatus(); } static util::Status Validate(const AesCtrHmacStreaming::Params& params) { if (params.ikm.size() < std::max(16, params.key_size)) { return util::Status(absl::StatusCode::kInvalidArgument, "input key material too small"); } if (!(params.hkdf_algo == SHA1 || params.hkdf_algo == SHA256 || params.hkdf_algo == SHA512)) { return util::Status(absl::StatusCode::kInvalidArgument, "unsupported hkdf_algo"); } if (params.key_size != 16 && params.key_size != 32) { return util::Status(absl::StatusCode::kInvalidArgument, "key_size must be 16 or 32"); } int header_size = 1 + params.key_size + AesCtrHmacStreaming::kNoncePrefixSizeInBytes; if (params.ciphertext_segment_size <= params.ciphertext_offset + header_size + params.tag_size) { return util::Status(absl::StatusCode::kInvalidArgument, "ciphertext_segment_size too small"); } if (params.ciphertext_offset < 0) { return util::Status(absl::StatusCode::kInvalidArgument, "ciphertext_offset must be non-negative"); } if (params.tag_size < 10) { return util::Status(absl::StatusCode::kInvalidArgument, "tag_size too small"); } if (!(params.tag_algo == SHA1 || params.tag_algo == SHA256 || params.tag_algo == SHA512)) { return util::Status(absl::StatusCode::kInvalidArgument, "unsupported tag_algo"); } if ((params.tag_algo == SHA1 && params.tag_size > 20) || (params.tag_algo == SHA256 && params.tag_size > 32) || (params.tag_algo == SHA512 && params.tag_size > 64)) { return util::Status(absl::StatusCode::kInvalidArgument, "tag_size too big"); } return util::OkStatus(); } // AesCtrHmacStreaming // static util::StatusOr> AesCtrHmacStreaming::New( Params params) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) return status; status = Validate(params); if (!status.ok()) return status; return {absl::WrapUnique(new AesCtrHmacStreaming(std::move(params)))}; } // static util::StatusOr> AesCtrHmacStreaming::NewSegmentEncrypter( absl::string_view associated_data) const { return AesCtrHmacStreamSegmentEncrypter::New(params_, associated_data); } // static util::StatusOr> AesCtrHmacStreaming::NewSegmentDecrypter( absl::string_view associated_data) const { return AesCtrHmacStreamSegmentDecrypter::New(params_, associated_data); } // AesCtrHmacStreamSegmentEncrypter static std::string MakeHeader(absl::string_view salt, absl::string_view nonce_prefix) { uint8_t header_size = static_cast(1 + salt.size() + nonce_prefix.size()); return absl::StrCat(std::string(1, header_size), salt, nonce_prefix); } // static util::StatusOr> AesCtrHmacStreamSegmentEncrypter::New(const AesCtrHmacStreaming::Params& params, absl::string_view associated_data) { auto status = Validate(params); if (!status.ok()) return status; std::string salt = Random::GetRandomBytes(params.key_size); std::string nonce_prefix = Random::GetRandomBytes(AesCtrHmacStreaming::kNoncePrefixSizeInBytes); std::string header = MakeHeader(salt, nonce_prefix); util::SecretData key_value; util::SecretData hmac_key_value; status = DeriveKeys(params.ikm, params.hkdf_algo, salt, associated_data, params.key_size, &key_value, &hmac_key_value); if (!status.ok()) return status; util::StatusOr cipher = internal::GetAesCtrCipherForKeySize(params.key_size); if (!cipher.ok()) { return cipher.status(); } auto hmac_result = HmacBoringSsl::New(params.tag_algo, params.tag_size, std::move(hmac_key_value)); if (!hmac_result.ok()) return hmac_result.status(); auto mac = std::move(hmac_result.value()); return {absl::WrapUnique(new AesCtrHmacStreamSegmentEncrypter( std::move(key_value), header, nonce_prefix, params.ciphertext_segment_size, params.ciphertext_offset, params.tag_size, *cipher, std::move(mac)))}; } util::Status AesCtrHmacStreamSegmentEncrypter::EncryptSegment( const std::vector& plaintext, bool is_last_segment, std::vector* ciphertext_buffer) { if (plaintext.size() > get_plaintext_segment_size()) { return util::Status(absl::StatusCode::kInvalidArgument, "plaintext too long"); } if (ciphertext_buffer == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "ciphertext_buffer must be non-null"); } if (get_segment_number() > std::numeric_limits::max() || (get_segment_number() == std::numeric_limits::max() && !is_last_segment)) { return util::Status(absl::StatusCode::kInvalidArgument, "too many segments"); } int ct_size = plaintext.size() + tag_size_; ciphertext_buffer->resize(ct_size); std::string nonce = NonceForSegment(nonce_prefix_, segment_number_, is_last_segment); // Encrypt. internal::SslUniquePtr ctx(EVP_CIPHER_CTX_new()); if (ctx == nullptr) { return util::Status(absl::StatusCode::kInternal, "could not initialize EVP_CIPHER_CTX"); } if (EVP_EncryptInit_ex(ctx.get(), cipher_, nullptr /* engine */, reinterpret_cast(key_value_.data()), reinterpret_cast(nonce.data())) != 1) { return util::Status(absl::StatusCode::kInternal, "could not initialize ctx"); } int out_len; if (EVP_EncryptUpdate(ctx.get(), ciphertext_buffer->data(), &out_len, plaintext.data(), plaintext.size()) != 1) { return util::Status(absl::StatusCode::kInternal, "encryption failed"); } if (out_len != plaintext.size()) { return util::Status(absl::StatusCode::kInternal, "incorrect ciphertext size"); } // Add MAC tag. absl::string_view ciphertext_string( reinterpret_cast(ciphertext_buffer->data()), plaintext.size()); auto tag_result = mac_->ComputeMac(absl::StrCat(nonce, ciphertext_string)); if (!tag_result.ok()) return tag_result.status(); std::string tag = tag_result.value(); memcpy(ciphertext_buffer->data() + plaintext.size(), reinterpret_cast(tag.data()), tag_size_); IncSegmentNumber(); return util::OkStatus(); } // AesCtrHmacStreamSegmentDecrypter // static util::StatusOr> AesCtrHmacStreamSegmentDecrypter::New(const AesCtrHmacStreaming::Params& params, absl::string_view associated_data) { auto status = Validate(params); if (!status.ok()) return status; return {absl::WrapUnique(new AesCtrHmacStreamSegmentDecrypter( params.ikm, params.hkdf_algo, params.key_size, associated_data, params.ciphertext_segment_size, params.ciphertext_offset, params.tag_algo, params.tag_size))}; } util::Status AesCtrHmacStreamSegmentDecrypter::Init( const std::vector& header) { if (is_initialized_) { return util::Status(absl::StatusCode::kFailedPrecondition, "decrypter alreday initialized"); } if (header.size() != get_header_size()) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("wrong header size, expected ", get_header_size(), " bytes")); } if (header[0] != header.size()) { return util::Status(absl::StatusCode::kInvalidArgument, "corrupted header"); } // Extract salt and nonce prefix. std::string salt(reinterpret_cast(header.data() + 1), key_size_); nonce_prefix_ = std::string(reinterpret_cast(header.data() + 1 + key_size_), AesCtrHmacStreaming::kNoncePrefixSizeInBytes); util::SecretData hmac_key_value; auto status = DeriveKeys(ikm_, hkdf_algo_, salt, associated_data_, key_size_, &key_value_, &hmac_key_value); if (!status.ok()) return status; util::StatusOr cipher = internal::GetAesCtrCipherForKeySize(key_size_); if (!cipher.ok()) { return cipher.status(); } cipher_ = *cipher; auto hmac_result = HmacBoringSsl::New(tag_algo_, tag_size_, std::move(hmac_key_value)); if (!hmac_result.ok()) return hmac_result.status(); mac_ = std::move(hmac_result.value()); is_initialized_ = true; return util::OkStatus(); } util::Status AesCtrHmacStreamSegmentDecrypter::DecryptSegment( const std::vector& ciphertext, int64_t segment_number, bool is_last_segment, std::vector* plaintext_buffer) { if (!is_initialized_) { return util::Status(absl::StatusCode::kFailedPrecondition, "decrypter not initialized"); } if (ciphertext.size() > get_ciphertext_segment_size()) { return util::Status(absl::StatusCode::kInvalidArgument, "ciphertext too long"); } if (ciphertext.size() < tag_size_) { return util::Status(absl::StatusCode::kInvalidArgument, "ciphertext too short"); } if (plaintext_buffer == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "plaintext_buffer must be non-null"); } if (segment_number > std::numeric_limits::max() || (segment_number == std::numeric_limits::max() && !is_last_segment)) { return util::Status(absl::StatusCode::kInvalidArgument, "too many segments"); } int pt_size = ciphertext.size() - tag_size_; plaintext_buffer->resize(pt_size); std::string nonce = NonceForSegment(nonce_prefix_, segment_number, is_last_segment); // Verify MAC tag. absl::string_view tag( reinterpret_cast(ciphertext.data() + pt_size), tag_size_); absl::string_view ciphertext_string( reinterpret_cast(ciphertext.data()), pt_size); auto status = mac_->VerifyMac(tag, absl::StrCat(nonce, ciphertext_string)); if (!status.ok()) return status; // Decrypt. internal::SslUniquePtr ctx(EVP_CIPHER_CTX_new()); if (ctx.get() == nullptr) { return util::Status(absl::StatusCode::kInternal, "could not initialize EVP_CIPHER_CTX"); } if (EVP_DecryptInit_ex(ctx.get(), cipher_, nullptr /* engine */, reinterpret_cast(key_value_.data()), reinterpret_cast(nonce.data())) != 1) { return util::Status(absl::StatusCode::kInternal, "could not initialize ctx"); } int out_len; if (EVP_DecryptUpdate(ctx.get(), plaintext_buffer->data(), &out_len, ciphertext.data(), pt_size) != 1) { return util::Status(absl::StatusCode::kInternal, "decryption failed"); } if (out_len != pt_size) { return util::Status(absl::StatusCode::kInternal, "incorrect plaintext size"); } return util::OkStatus(); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/aes_ctr_hmac_streaming.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_AES_CTR_HMAC_STREAMING_H_ #define TINK_SUBTLE_AES_CTR_HMAC_STREAMING_H_ #include #include #include #include #include #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "tink/internal/fips_utils.h" #include "tink/mac.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/nonce_based_streaming_aead.h" #include "tink/subtle/stream_segment_decrypter.h" #include "tink/subtle/stream_segment_encrypter.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // Streaming encryption using AES-CTR and HMAC. // // Each ciphertext uses a new AES-CTR key and HMAC key that are derived from the // key derivation key, a randomly chosen salt of the same size as the key and a // nonce prefix using HKDF. // // The format of a ciphertext is // header || segment_0 || segment_1 || ... || segment_k. // where: // - segment_i is the i-th segment of the ciphertext. // - the size of segment_1 .. segment_{k-1} is get_ciphertext_segment_size() // - segment_0 is shorter, so that segment_0, the header and other information // of size get_ciphertext_offset() align with get_ciphertext_segment_size(). // // The format of the header is // header_size || salt || nonce_prefix // where // - header_size is 1 byte determining the size of the header // - salt is a salt used in the key derivation // - nonce_prefix is the prefix of the nonce // // In principle header_size is redundant information, since the length of the // header can be determined from the key size. class AesCtrHmacStreaming : public NonceBasedStreamingAead { public: struct Params { util::SecretData ikm; HashType hkdf_algo; int key_size; int ciphertext_segment_size; int ciphertext_offset; HashType tag_algo; int tag_size; }; // The size of the nonce for AES-CTR. static constexpr int kNonceSizeInBytes = 16; // The nonce has the format nonce_prefix || ctr || last_block || 0 0 0 0, // where: // - nonce_prefix is a constant of kNoncePrefixSizeInBytes bytes // for the whole file // - ctr is a big endian 32 bit counter // - last_block is a byte equal to 1 for the last block of the file // and 0 otherwise. static constexpr int kNoncePrefixSizeInBytes = 7; static constexpr int kHmacKeySizeInBytes = 32; static util::StatusOr> New( Params params); static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kNotFips; protected: util::StatusOr> NewSegmentEncrypter( absl::string_view associated_data) const override; util::StatusOr> NewSegmentDecrypter( absl::string_view associated_data) const override; private: explicit AesCtrHmacStreaming(Params params) : params_(std::move(params)) {} const Params params_; }; class AesCtrHmacStreamSegmentEncrypter : public StreamSegmentEncrypter { public: // A factory. static util::StatusOr> New( const AesCtrHmacStreaming::Params& params, absl::string_view associated_data); // Overridden methods of StreamSegmentEncrypter. util::Status EncryptSegment(const std::vector& plaintext, bool is_last_segment, std::vector* ciphertext_buffer) override; const std::vector& get_header() const override { return header_; } int64_t get_segment_number() const override { return segment_number_; } int get_plaintext_segment_size() const override { return ciphertext_segment_size_ - tag_size_; } int get_ciphertext_segment_size() const override { return ciphertext_segment_size_; } int get_ciphertext_offset() const override { return ciphertext_offset_; } protected: void IncSegmentNumber() override { segment_number_++; } private: AesCtrHmacStreamSegmentEncrypter(util::SecretData key_value, absl::string_view header, absl::string_view nonce_prefix, int ciphertext_segment_size, int ciphertext_offset, int tag_size, const EVP_CIPHER* cipher, std::unique_ptr mac) : key_value_(std::move(key_value)), header_(header.begin(), header.end()), nonce_prefix_(nonce_prefix), ciphertext_segment_size_(ciphertext_segment_size), ciphertext_offset_(ciphertext_offset), tag_size_(tag_size), cipher_(cipher), mac_(std::move(mac)), segment_number_(0) {} const util::SecretData key_value_; const std::vector header_; const std::string nonce_prefix_; const int ciphertext_segment_size_; const int ciphertext_offset_; const int tag_size_; const EVP_CIPHER* cipher_; const std::unique_ptr mac_; int64_t segment_number_; }; class AesCtrHmacStreamSegmentDecrypter : public StreamSegmentDecrypter { public: // A factory. static util::StatusOr> New( const AesCtrHmacStreaming::Params& params, absl::string_view associated_data); // Overridden methods of StreamSegmentDecrypter. util::Status Init(const std::vector& header) override; util::Status DecryptSegment(const std::vector& ciphertext, int64_t segment_number, bool is_last_segment, std::vector* plaintext_buffer) override; int get_header_size() const override { return 1 + key_size_ + AesCtrHmacStreaming::kNoncePrefixSizeInBytes; } int get_plaintext_segment_size() const override { return ciphertext_segment_size_ - tag_size_; } int get_ciphertext_segment_size() const override { return ciphertext_segment_size_; } int get_ciphertext_offset() const override { return ciphertext_offset_; } ~AesCtrHmacStreamSegmentDecrypter() override = default; private: AesCtrHmacStreamSegmentDecrypter(util::SecretData ikm, HashType hkdf_algo, int key_size, absl::string_view associated_data, int ciphertext_segment_size, int ciphertext_offset, HashType tag_algo, int tag_size) : ikm_(std::move(ikm)), hkdf_algo_(hkdf_algo), key_size_(key_size), associated_data_(associated_data), ciphertext_segment_size_(ciphertext_segment_size), ciphertext_offset_(ciphertext_offset), tag_algo_(tag_algo), tag_size_(tag_size) {} // Parameters set upon decrypter creation. const util::SecretData ikm_; const HashType hkdf_algo_; const int key_size_; const std::string associated_data_; const int ciphertext_segment_size_; const int ciphertext_offset_; const HashType tag_algo_; const int tag_size_; // Parameters set when initializing with data from stream header. bool is_initialized_ = false; util::SecretData key_value_; std::string nonce_prefix_; const EVP_CIPHER* cipher_; std::unique_ptr mac_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_AES_CTR_HMAC_STREAMING_H_ ================================================ FILE: cc/subtle/aes_ctr_hmac_streaming_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/aes_ctr_hmac_streaming.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "tink/config/tink_fips.h" #include "tink/internal/test_random_access_stream.h" #include "tink/random_access_stream.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/random.h" #include "tink/subtle/stream_segment_decrypter.h" #include "tink/subtle/stream_segment_encrypter.h" #include "tink/subtle/streaming_aead_test_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::HasSubstr; namespace crypto { namespace tink { namespace subtle { namespace { AesCtrHmacStreaming::Params ValidParams() { AesCtrHmacStreaming::Params params; params.ikm = Random::GetRandomKeyBytes(32); params.hkdf_algo = SHA256; params.key_size = 32; params.ciphertext_segment_size = 256; params.ciphertext_offset = 0; params.tag_algo = SHA256; params.tag_size = 16; return params; } TEST(AesCtrHmacStreamSegmentEncrypterTest, Basic) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } for (int ikm_size : {16, 32}) { for (HashType hkdf_algo : {SHA1, SHA256, SHA512}) { for (int key_size : {16, 32}) { if (ikm_size < key_size) continue; for (int ciphertext_segment_size : {80, 128, 200}) { for (int ciphertext_offset : {0, 5, 10}) { for (HashType tag_algo : {SHA1, SHA256, SHA512}) { for (int tag_size : {10, 16, 20}) { SCOPED_TRACE(absl::StrCat( "ikm_size = ", ikm_size, ", hkdf_algo = ", EnumToString(hkdf_algo), ", key_size = ", key_size, ", ciphertext_segment_size = ", ciphertext_segment_size, ", ciphertext_offset = ", ciphertext_offset, ", tag_algo = ", EnumToString(tag_algo), ", tag_size = ", tag_size)); // Construct the parameters. AesCtrHmacStreaming::Params params; params.ikm = Random::GetRandomKeyBytes(ikm_size); params.hkdf_algo = hkdf_algo; params.key_size = key_size; params.ciphertext_segment_size = ciphertext_segment_size; params.ciphertext_offset = ciphertext_offset; params.tag_algo = tag_algo; params.tag_size = tag_size; std::string associated_data = "associated data"; // Get a segment encrypter. auto enc_result = AesCtrHmacStreamSegmentEncrypter::New( params, associated_data); ASSERT_THAT(enc_result, IsOk()); auto enc = std::move(enc_result.value()); EXPECT_EQ(0, enc->get_segment_number()); int header_size = 1 + key_size + /* nonce_prefix_size = */ 7; EXPECT_EQ(header_size, enc->get_header().size()); EXPECT_EQ(header_size, enc->get_header()[0]); EXPECT_EQ(ciphertext_segment_size, enc->get_ciphertext_segment_size()); EXPECT_EQ(ciphertext_segment_size - tag_size, enc->get_plaintext_segment_size()); EXPECT_EQ(ciphertext_offset, enc->get_ciphertext_offset()); int segment_number = 0; for (int pt_size : {0, 1, 10, enc->get_plaintext_segment_size()}) { for (bool is_last_segment : {false, true}) { SCOPED_TRACE( absl::StrCat("plaintext_size = ", pt_size, ", is_last_segment = ", is_last_segment)); std::vector pt(pt_size, 'p'); std::vector ct; EXPECT_THAT(enc->EncryptSegment(pt, is_last_segment, &ct), IsOk()); EXPECT_EQ(ct.size(), pt.size() + tag_size); segment_number++; EXPECT_EQ(segment_number, enc->get_segment_number()); } } } } } } } } } } TEST(AesCtrHmacStreamSegmentEncrypterTest, EncryptLongPlaintext) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } AesCtrHmacStreaming::Params params = ValidParams(); std::string associated_data = "associated data"; auto enc_result = AesCtrHmacStreamSegmentEncrypter::New(params, associated_data); ASSERT_THAT(enc_result, IsOk()); auto enc = std::move(enc_result.value()); std::vector pt(enc->get_plaintext_segment_size() + 1, 'p'); std::vector ct; ASSERT_THAT(enc->EncryptSegment(pt, true, &ct), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("plaintext too long"))); } TEST(AesCtrHmacStreamSegmentEncrypterTest, EncryptNullCtBuffer) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } AesCtrHmacStreaming::Params params = ValidParams(); std::string associated_data = "associated data"; auto enc_result = AesCtrHmacStreamSegmentEncrypter::New(params, associated_data); ASSERT_THAT(enc_result, IsOk()); auto enc = std::move(enc_result.value()); std::vector pt(enc->get_plaintext_segment_size(), 'p'); ASSERT_THAT(enc->EncryptSegment(pt, true, nullptr), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("must be non-null"))); } TEST(AesCtrHmacStreamSegmentDecrypterTest, Basic) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } for (int ikm_size : {16, 32}) { for (HashType hkdf_algo : {SHA1, SHA256, SHA512}) { for (int key_size : {16, 32}) { if (ikm_size < key_size) continue; for (int ciphertext_segment_size : {80, 128, 200}) { for (int ciphertext_offset : {0, 5, 10}) { for (HashType tag_algo : {SHA1, SHA256, SHA512}) { for (int tag_size : {10, 16, 20}) { SCOPED_TRACE(absl::StrCat( "ikm_size = ", ikm_size, ", hkdf_algo = ", EnumToString(hkdf_algo), ", key_size = ", key_size, ", ciphertext_segment_size = ", ciphertext_segment_size, ", ciphertext_offset = ", ciphertext_offset, ", tag_algo = ", EnumToString(tag_algo), ", tag_size = ", tag_size)); // Construct the parameters. AesCtrHmacStreaming::Params params; params.ikm = Random::GetRandomKeyBytes(ikm_size); params.hkdf_algo = hkdf_algo; params.key_size = key_size; params.ciphertext_segment_size = ciphertext_segment_size; params.ciphertext_offset = ciphertext_offset; params.tag_algo = tag_algo; params.tag_size = tag_size; std::string associated_data = "associated data"; // Get a segment encrypter. auto enc_result = AesCtrHmacStreamSegmentEncrypter::New( params, associated_data); ASSERT_THAT(enc_result, IsOk()); auto enc = std::move(enc_result.value()); // Get and initialize a segment decrypter. auto dec_result = AesCtrHmacStreamSegmentDecrypter::New( params, associated_data); ASSERT_THAT(dec_result, IsOk()); auto dec = std::move(dec_result.value()); ASSERT_THAT(dec->Init(enc->get_header()), IsOk()); int header_size = 1 + key_size + /* nonce_prefix_size = */ 7; EXPECT_EQ(header_size, dec->get_header_size()); EXPECT_EQ(enc->get_header().size(), dec->get_header_size()); EXPECT_EQ(ciphertext_segment_size, dec->get_ciphertext_segment_size()); EXPECT_EQ(ciphertext_segment_size - tag_size, dec->get_plaintext_segment_size()); EXPECT_EQ(ciphertext_offset, dec->get_ciphertext_offset()); int segment_number = 0; for (int pt_size : {0, 1, 10, dec->get_plaintext_segment_size()}) { for (bool is_last_segment : {false, true}) { SCOPED_TRACE( absl::StrCat("plaintext_size = ", pt_size, ", is_last_segment = ", is_last_segment)); std::vector pt(pt_size, 'p'); std::vector ct; std::vector decrypted; auto status = enc->EncryptSegment(pt, is_last_segment, &ct); EXPECT_THAT(status, IsOk()); EXPECT_EQ(ct.size(), pt.size() + tag_size); EXPECT_THAT( dec->DecryptSegment(ct, segment_number, is_last_segment, &decrypted), IsOk()); EXPECT_EQ(pt, decrypted); segment_number++; EXPECT_EQ(segment_number, enc->get_segment_number()); } } } } } } } } } } TEST(AesCtrHmacStreamSegmentDecrypterTest, AlreadyInit) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } AesCtrHmacStreaming::Params params = ValidParams(); std::string associated_data = "associated data"; auto enc_result = AesCtrHmacStreamSegmentEncrypter::New(params, associated_data); ASSERT_THAT(enc_result, IsOk()); auto enc = std::move(enc_result.value()); auto dec_result = AesCtrHmacStreamSegmentDecrypter::New(params, associated_data); ASSERT_THAT(dec_result, IsOk()); auto dec = std::move(dec_result.value()); ASSERT_THAT(dec->Init(enc->get_header()), IsOk()); ASSERT_THAT(dec->Init(enc->get_header()), StatusIs(absl::StatusCode::kFailedPrecondition, HasSubstr("alreday initialized"))); } TEST(AesCtrHmacStreamSegmentDecrypterTest, InitWrongHeaderSize) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } AesCtrHmacStreaming::Params params = ValidParams(); std::string associated_data = "associated data"; auto enc_result = AesCtrHmacStreamSegmentEncrypter::New(params, associated_data); ASSERT_THAT(enc_result, IsOk()); auto enc = std::move(enc_result.value()); auto dec_result = AesCtrHmacStreamSegmentDecrypter::New(params, associated_data); ASSERT_THAT(dec_result, IsOk()); auto dec = std::move(dec_result.value()); auto header = enc->get_header(); header.resize(dec->get_header_size() - 1); ASSERT_THAT(dec->Init(header), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("wrong header size"))); } TEST(AesCtrHmacStreamSegmentDecrypterTest, InitCorruptedHeader) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } AesCtrHmacStreaming::Params params = ValidParams(); std::string associated_data = "associated data"; auto enc_result = AesCtrHmacStreamSegmentEncrypter::New(params, associated_data); ASSERT_THAT(enc_result, IsOk()); auto enc = std::move(enc_result.value()); auto dec_result = AesCtrHmacStreamSegmentDecrypter::New(params, associated_data); ASSERT_THAT(dec_result, IsOk()); auto dec = std::move(dec_result.value()); auto header = enc->get_header(); header[0] = 0; ASSERT_THAT(dec->Init(header), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("corrupted header"))); } TEST(AesCtrHmacStreamSegmentDecrypterTest, DecryptNotInit) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } AesCtrHmacStreaming::Params params = ValidParams(); std::string associated_data = "associated data"; auto enc_result = AesCtrHmacStreamSegmentEncrypter::New(params, associated_data); ASSERT_THAT(enc_result, IsOk()); auto enc = std::move(enc_result.value()); auto dec_result = AesCtrHmacStreamSegmentDecrypter::New(params, associated_data); ASSERT_THAT(dec_result, IsOk()); auto dec = std::move(dec_result.value()); std::vector ct(dec->get_ciphertext_segment_size(), 'c'); std::vector pt; ASSERT_THAT(dec->DecryptSegment(ct, 0, true, &pt), StatusIs(absl::StatusCode::kFailedPrecondition, HasSubstr("not initialized"))); } TEST(AesCtrHmacStreamSegmentDecrypterTest, DecryptLongCiphertext) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } AesCtrHmacStreaming::Params params = ValidParams(); std::string associated_data = "associated data"; auto enc_result = AesCtrHmacStreamSegmentEncrypter::New(params, associated_data); ASSERT_THAT(enc_result, IsOk()); auto enc = std::move(enc_result.value()); auto dec_result = AesCtrHmacStreamSegmentDecrypter::New(params, associated_data); ASSERT_THAT(dec_result, IsOk()); auto dec = std::move(dec_result.value()); ASSERT_THAT(dec->Init(enc->get_header()), IsOk()); std::vector ct(dec->get_ciphertext_segment_size() + 1, 'c'); std::vector pt; ASSERT_THAT(dec->DecryptSegment(ct, 0, true, &pt), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("ciphertext too long"))); } TEST(AesCtrHmacStreamSegmentDecrypterTest, DecryptNullPtBuffer) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } AesCtrHmacStreaming::Params params = ValidParams(); std::string associated_data = "associated data"; auto enc_result = AesCtrHmacStreamSegmentEncrypter::New(params, associated_data); ASSERT_THAT(enc_result, IsOk()); auto enc = std::move(enc_result.value()); auto dec_result = AesCtrHmacStreamSegmentDecrypter::New(params, associated_data); ASSERT_THAT(dec_result, IsOk()); auto dec = std::move(dec_result.value()); ASSERT_THAT(dec->Init(enc->get_header()), IsOk()); std::vector ct(dec->get_ciphertext_segment_size(), 'c'); ASSERT_THAT(dec->DecryptSegment(ct, 0, true, nullptr), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("must be non-null"))); } TEST(AesCtrHmacStreamingTest, Basic) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } for (int ikm_size : {16, 32}) { for (HashType hkdf_algo : {SHA1, SHA256, SHA512}) { for (int key_size : {16, 32}) { if (ikm_size < key_size) continue; for (int ciphertext_segment_size : {80, 128, 200}) { for (int ciphertext_offset : {0, 5, 10}) { for (HashType tag_algo : {SHA1, SHA256, SHA512}) { for (int tag_size : {10, 16, 20}) { for (int plaintext_size : {0, 10, 100, 1000}) { SCOPED_TRACE(absl::StrCat( "ikm_size = ", ikm_size, ", hkdf_algo = ", EnumToString(hkdf_algo), ", key_size = ", key_size, ", ciphertext_segment_size = ", ciphertext_segment_size, ", ciphertext_offset = ", ciphertext_offset, ", tag_algo = ", EnumToString(tag_algo), ", tag_size = ", tag_size, ", plaintext_size = ", plaintext_size)); // Create AesCtrHmacStreaming. AesCtrHmacStreaming::Params params; params.ikm = Random::GetRandomKeyBytes(ikm_size); params.hkdf_algo = hkdf_algo; params.key_size = key_size; params.ciphertext_segment_size = ciphertext_segment_size; params.ciphertext_offset = ciphertext_offset; params.tag_algo = tag_algo; params.tag_size = tag_size; auto result = AesCtrHmacStreaming::New(params); ASSERT_THAT(result, IsOk()); auto streaming_aead = std::move(result.value()); std::string plaintext(plaintext_size, 'p'); std::string associated_data = "associated data"; EXPECT_THAT( EncryptThenDecrypt(streaming_aead.get(), streaming_aead.get(), plaintext, associated_data, ciphertext_offset), IsOk()); } } } } } } } } } TEST(ValidateTest, ValidParams) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } AesCtrHmacStreaming::Params params = ValidParams(); ASSERT_THAT(AesCtrHmacStreaming::New(params), IsOk()); } TEST(ValidateTest, WrongIkm) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } AesCtrHmacStreaming::Params params = ValidParams(); params.ikm = Random::GetRandomKeyBytes(16); ASSERT_THAT(AesCtrHmacStreaming::New(params).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("key material too small"))); } TEST(ValidateTest, WrongHkdfAlgo) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } AesCtrHmacStreaming::Params params = ValidParams(); params.hkdf_algo = SHA384; ASSERT_THAT(AesCtrHmacStreaming::New(params).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("unsupported hkdf_algo"))); } TEST(ValidateTest, WrongKeySize) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } AesCtrHmacStreaming::Params params = ValidParams(); params.ikm = Random::GetRandomKeyBytes(64); params.key_size = 64; ASSERT_THAT(AesCtrHmacStreaming::New(params).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("key_size must be"))); } TEST(ValidateTest, WrongCtSegmentSize) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } AesCtrHmacStreaming::Params params = ValidParams(); params.ciphertext_segment_size = 10; ASSERT_THAT(AesCtrHmacStreaming::New(params).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("ciphertext_segment_size too small"))); params.ciphertext_segment_size = 1 + 32 + 7 + 16; ASSERT_THAT(AesCtrHmacStreaming::New(params).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("ciphertext_segment_size too small"))); } TEST(ValidateTest, WrongCtOffset) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } AesCtrHmacStreaming::Params params = ValidParams(); params.ciphertext_offset = -10; ASSERT_THAT(AesCtrHmacStreaming::New(params).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("ciphertext_offset must be"))); } TEST(ValidateTest, WrongTagSize) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } AesCtrHmacStreaming::Params params = ValidParams(); params.tag_size = 5; ASSERT_THAT(AesCtrHmacStreaming::New(params).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("tag_size too small"))); params.tag_algo = SHA1; params.tag_size = 21; ASSERT_THAT(AesCtrHmacStreaming::New(params).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("tag_size too big"))); params.tag_algo = SHA256; params.tag_size = 33; ASSERT_THAT(AesCtrHmacStreaming::New(params).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("tag_size too big"))); params.tag_algo = SHA512; params.tag_size = 65; ASSERT_THAT(AesCtrHmacStreaming::New(params).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("tag_size too big"))); } // Tests that the output of Size does not decrypt anything. TEST(AesCtrHmacStreamingTest, SizeIsNotAuthenticated) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } AesCtrHmacStreaming::Params params = ValidParams(); util::StatusOr> streaming_aead = AesCtrHmacStreaming::New(std::move(params)); ASSERT_THAT(streaming_aead.status(), IsOk()); std::string associated_data = "some associated data"; // The header is 40 = 0x28 bytes for this key and Tink verifies that the // ciphertext starts with 0x28 in the first byte. std::string wrong_ciphertext = absl::StrCat(absl::HexStringToBytes("28"), "some arbitrary text which does not matter at all but needs " "to be at least of length 40 bytes"); absl::StatusOr> plaintext_stream = (*streaming_aead) ->NewDecryptingRandomAccessStream( absl::make_unique( wrong_ciphertext), associated_data); ASSERT_THAT(plaintext_stream.status(), IsOk()); // 37 is the length of "wrong_ciphertext" minus the overhead. EXPECT_THAT((*plaintext_stream)->size(), IsOkAndHolds(Eq(37))); } TEST(ValidateTest, WrongTagAlgo) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } AesCtrHmacStreaming::Params params = ValidParams(); params.tag_algo = SHA384; ASSERT_THAT(AesCtrHmacStreaming::New(params).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("unsupported tag_algo"))); } // FIPS only mode tests TEST(AesCtrHmacStreamingTest, TestFipsOnly) { if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Only supported in FIPS-only mode"; } AesCtrHmacStreaming::Params params = ValidParams(); EXPECT_THAT(AesCtrHmacStreaming::New(std::move(params)).status(), StatusIs(absl::StatusCode::kInternal)); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/aes_eax_boringssl.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/aes_eax_boringssl.h" #include #include #include #include #include #include #include #include "absl/algorithm/container.h" #include "absl/base/config.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "openssl/err.h" #include "openssl/evp.h" #include "tink/aead.h" #include "tink/internal/aes_util.h" #include "tink/internal/call_with_core_dump_protection.h" #include "tink/internal/fips_utils.h" #include "tink/internal/util.h" #include "tink/subtle/random.h" #include "tink/subtle/subtle_util.h" #include "tink/util/errors.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { namespace { // Loads and stores 8 bytes. The endianness of the two routines // does not matter, as long as the two routines use the same order. uint64_t Load64(const uint8_t src[8]) { uint64_t res; std::memcpy(&res, src, 8); return res; } void Store64(uint64_t val, uint8_t dst[8]) { std::memcpy(dst, &val, 8); } uint64_t ByteSwap(uint64_t val) { val = ((val & 0xffffffff00000000) >> 32) | ((val & 0x00000000ffffffff) << 32); val = ((val & 0xffff0000ffff0000) >> 16) | ((val & 0x0000ffff0000ffff) << 16); val = ((val & 0xff00ff00ff00ff00) >> 8) | ((val & 0x00ff00ff00ff00ff) << 8); return val; } uint64_t BigEndianLoad64(const uint8_t src[8]) { #if defined(ABSL_IS_LITTLE_ENDIAN) return ByteSwap(Load64(src)); #elif defined(ABSL_IS_BIG_ENDIAN) return Load64(src); #else #error Unknown endianness #endif } void BigEndianStore64(uint64_t val, uint8_t dst[8]) { #if defined(ABSL_IS_LITTLE_ENDIAN) return Store64(ByteSwap(val), dst); #elif defined(ABSL_IS_BIG_ENDIAN) return Store64(val, dst); #else #error Unknown endianness #endif } crypto::tink::util::StatusOr> InitAesKey( const util::SecretData& key) { auto aeskey = util::MakeSecretUniquePtr(); int status = AES_set_encrypt_key(key.data(), key.size() * 8, aeskey.get()); // status != 0 happens if key_value is invalid. if (status != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid key value"); } return std::move(aeskey); } } // namespace void AesEaxBoringSsl::XorBlock(const uint8_t x[kBlockSize], Block* y) { uint64_t r0 = Load64(x) ^ Load64(y->data()); uint64_t r1 = Load64(x + 8) ^ Load64(y->data() + 8); Store64(r0, y->data()); Store64(r1, y->data() + 8); } void AesEaxBoringSsl::MultiplyByX(const uint8_t in[kBlockSize], uint8_t out[kBlockSize]) { uint64_t in_high = BigEndianLoad64(in); uint64_t in_low = BigEndianLoad64(in + 8); uint64_t out_high = (in_high << 1) ^ (in_low >> 63); // If the most significant bit is set then the result has to // be reduced by x^128 + x^7 + x^2 + x + 1. // The representation of x^7 + x^2 + x + 1 is 0x87. uint64_t out_low = (in_low << 1) ^ (0x87 & -(in_high >> 63)); BigEndianStore64(out_high, out); BigEndianStore64(out_low, out + 8); } bool AesEaxBoringSsl::EqualBlocks(const uint8_t x[kBlockSize], const uint8_t y[kBlockSize]) { uint64_t res = Load64(x) ^ Load64(y); res |= Load64(x + 8) ^ Load64(y + 8); return res == 0; } bool AesEaxBoringSsl::IsValidKeySize(size_t key_size_in_bytes) { return key_size_in_bytes == 16 || key_size_in_bytes == 32; } bool AesEaxBoringSsl::IsValidNonceSize(size_t nonce_size_in_bytes) { return nonce_size_in_bytes == 12 || nonce_size_in_bytes == 16; } util::SecretData AesEaxBoringSsl::ComputeB() const { util::SecretData block(kBlockSize, 0); EncryptBlock(&block); MultiplyByX(block.data(), block.data()); return block; } util::SecretData AesEaxBoringSsl::ComputeP() const { util::SecretData rv(kBlockSize, 0); MultiplyByX(B_.data(), rv.data()); return rv; } crypto::tink::util::StatusOr> AesEaxBoringSsl::New( const util::SecretData& key, size_t nonce_size_in_bytes) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) return status; if (!IsValidKeySize(key.size())) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid key size"); } if (!IsValidNonceSize(nonce_size_in_bytes)) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid nonce size"); } return internal::CallWithCoreDumpProtection( [&]() -> util::StatusOr> { auto aeskey_or = InitAesKey(key); if (!aeskey_or.ok()) { return aeskey_or.status(); } return absl::WrapUnique(new AesEaxBoringSsl( std::move(aeskey_or).value(), nonce_size_in_bytes)); }); } AesEaxBoringSsl::Block AesEaxBoringSsl::Pad( absl::Span data) const { // TODO(bleichen): What are we using in tink to encode assertions? // The caller must ensure that data is no longer than a block. // CHECK(0 <= len && len <= kBlockSize) << "Invalid data size"; Block padded_block; padded_block.fill(0); absl::c_copy(data, padded_block.begin()); if (data.size() == kBlockSize) { XorBlock(B_.data(), &padded_block); } else { padded_block[data.size()] = 0x80; XorBlock(P_.data(), &padded_block); } return padded_block; } void AesEaxBoringSsl::EncryptBlock(util::SecretData* block) const { AES_encrypt(block->data(), block->data(), aeskey_.get()); } void AesEaxBoringSsl::EncryptBlock(Block* block) const { AES_encrypt(block->data(), block->data(), aeskey_.get()); } AesEaxBoringSsl::Block AesEaxBoringSsl::Omac(absl::string_view blob, int tag) const { return Omac(absl::MakeSpan(reinterpret_cast(blob.data()), blob.size()), tag); } AesEaxBoringSsl::Block AesEaxBoringSsl::Omac(absl::Span data, int tag) const { Block mac; mac.fill(0); mac[15] = tag; if (data.empty()) { XorBlock(B_.data(), &mac); EncryptBlock(&mac); return mac; } EncryptBlock(&mac); int idx = 0; while (data.size() - idx > kBlockSize) { XorBlock(&data[idx], &mac); EncryptBlock(&mac); idx += kBlockSize; } const Block padded_block = Pad(absl::MakeSpan(data).subspan(idx)); XorBlock(padded_block.data(), &mac); EncryptBlock(&mac); return mac; } util::Status AesEaxBoringSsl::CtrCrypt(const Block& N, absl::string_view in, absl::Span out) const { // Make a copy of N, since BoringSsl changes ctr. uint8_t ctr[kBlockSize]; std::copy_n(N.begin(), kBlockSize, ctr); return internal::AesCtr128Crypt(in, ctr, aeskey_.get(), out); } crypto::tink::util::StatusOr AesEaxBoringSsl::Encrypt( absl::string_view plaintext, absl::string_view associated_data) const { // BoringSSL expects a non-null pointer for plaintext and associated_data, // regardless of whether the size is 0. plaintext = internal::EnsureStringNonNull(plaintext); associated_data = internal::EnsureStringNonNull(associated_data); size_t ciphertext_size = plaintext.size() + nonce_size_ + kTagSize; std::string ciphertext; ResizeStringUninitialized(&ciphertext, ciphertext_size); return internal::CallWithCoreDumpProtection( [&]() -> util::StatusOr { const std::string nonce = Random::GetRandomBytes(nonce_size_); const Block N = Omac(nonce, 0); const Block H = Omac(associated_data, 1); uint8_t* ct_start = reinterpret_cast(&ciphertext[nonce_size_]); util::Status res = CtrCrypt( N, plaintext, absl::MakeSpan(ciphertext).subspan(nonce_size_)); if (!res.ok()) { return res; } Block mac = Omac(absl::MakeSpan(ct_start, plaintext.size()), 2); XorBlock(N.data(), &mac); XorBlock(H.data(), &mac); absl::c_copy(nonce, ciphertext.begin()); std::copy_n(mac.begin(), kTagSize, &ciphertext[ciphertext_size - kTagSize]); return ciphertext; }); } crypto::tink::util::StatusOr AesEaxBoringSsl::Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const { // BoringSSL expects a non-null pointer for associated_data, // regardless of whether the size is 0. associated_data = internal::EnsureStringNonNull(associated_data); size_t ct_size = ciphertext.size(); if (ct_size < nonce_size_ + kTagSize) { return util::Status(absl::StatusCode::kInvalidArgument, "Ciphertext too short"); } size_t out_size = ct_size - kTagSize - nonce_size_; absl::string_view nonce = ciphertext.substr(0, nonce_size_); absl::string_view encrypted = ciphertext.substr(nonce_size_, out_size); absl::string_view tag = ciphertext.substr(ct_size - kTagSize, kTagSize); return internal::CallWithCoreDumpProtection( [&]() -> util::StatusOr { const Block N = Omac(nonce, 0); const Block H = Omac(associated_data, 1); Block mac = Omac(encrypted, 2); XorBlock(N.data(), &mac); XorBlock(H.data(), &mac); const uint8_t* sig = reinterpret_cast(tag.data()); if (!EqualBlocks(mac.data(), sig)) { return util::Status(absl::StatusCode::kInvalidArgument, "Tag mismatch"); } std::string plaintext; ResizeStringUninitialized(&plaintext, out_size); util::Status res = CtrCrypt(N, encrypted, absl::MakeSpan(plaintext)); if (!res.ok()) { return res; } return plaintext; }); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/aes_eax_boringssl.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_AES_EAX_BORINGSSL_H_ #define TINK_SUBTLE_AES_EAX_BORINGSSL_H_ #include #include #include #include #include #include #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "openssl/aes.h" #include "openssl/evp.h" #include "tink/aead.h" #include "tink/internal/fips_utils.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { class AesEaxBoringSsl : public Aead { public: // Constructs a new Aead cipher for Aes-EAX. // Currently supported key sizes are 128 and 256 bits. // Currently supported nonce sizes are 12 and 16 bytes. // The tag size is fixed to 16 bytes. static crypto::tink::util::StatusOr> New( const util::SecretData& key, size_t nonce_size_in_bytes); crypto::tink::util::StatusOr Encrypt( absl::string_view plaintext, absl::string_view associated_data) const override; crypto::tink::util::StatusOr Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const override; static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kNotFips; private: static constexpr int kTagSize = 16; static constexpr int kBlockSize = 16; using Block = std::array; AesEaxBoringSsl(util::SecretUniquePtr aeskey, size_t nonce_size) : aeskey_(std::move(aeskey)), nonce_size_(nonce_size), B_(ComputeB()), P_(ComputeP()) {} // Precomputes block B. Requires aeskey_ to be initialized. util::SecretData ComputeB() const; // Precomputes block P. Requires aeskey_ and B_ to be initialized. util::SecretData ComputeP() const; // Returns whether key_size_in_bytes is a supported key size. static bool IsValidKeySize(size_t key_size_in_bytes); // Returns whether nonce_size_in_bytes is a supported size for the nonce. static bool IsValidNonceSize(size_t nonce_size_in_bytes); // XORs block x with block y. // Result is: y = x ^ y static void XorBlock(const uint8_t x[kBlockSize], Block* y); // Multiplies in by X and stores result in out. static void MultiplyByX(const uint8_t in[kBlockSize], uint8_t out[kBlockSize]); // Constant-time block equality static bool EqualBlocks(const uint8_t x[kBlockSize], const uint8_t y[kBlockSize]); // Encrypts a single block with AES. void EncryptBlock(Block* block) const; void EncryptBlock(util::SecretData* block) const; // Pads a partial data block of size 0 <= len <= kBlockSize. Block Pad(absl::Span data) const; // Computes a Omac over blob. // tag is either 0, 1 or 2, depending over which value (nonce, aad, message) // the Omac is computed. Block Omac(absl::string_view blob, int tag) const; // This is the same function as above with the difference that the blob // is represented by a pointer and its length. Block Omac(absl::Span data, int tag) const; // Encrypts or decrypts some data using CTR mode. `N` is the 16 bytes result // of an OMAC computation over the nonce. `in` are the bytes that are // encrypted or decrypted, and the result is written to `out`. `in`.data() // MUST NOT be null. crypto::tink::util::Status CtrCrypt(const Block& N, absl::string_view in, absl::Span out) const; const util::SecretUniquePtr aeskey_; const size_t nonce_size_; const util::SecretData B_; const util::SecretData P_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_AES_EAX_BORINGSSL_H_ ================================================ FILE: cc/subtle/aes_eax_boringssl_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/aes_eax_boringssl.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "openssl/err.h" #include "include/rapidjson/document.h" #include "tink/config/tink_fips.h" #include "tink/subtle/wycheproof_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::StatusIs; TEST(AesEaxBoringSslTest, TestBasic) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::SecretData key = util::SecretDataFromStringView( test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f")); size_t nonce_size = 12; auto res = AesEaxBoringSsl::New(key, nonce_size); EXPECT_TRUE(res.ok()) << res.status(); auto cipher = std::move(res.value()); std::string message = "Some data to encrypt."; std::string associated_data = "Some data to authenticate."; auto ct = cipher->Encrypt(message, associated_data); EXPECT_TRUE(ct.ok()) << ct.status(); EXPECT_EQ(ct.value().size(), message.size() + nonce_size + 16); auto pt = cipher->Decrypt(ct.value(), associated_data); EXPECT_TRUE(pt.ok()) << pt.status(); EXPECT_EQ(pt.value(), message); } TEST(AesEaxBoringSslTest, TestMessageSize) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::SecretData key = util::SecretDataFromStringView( test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f")); size_t nonce_size = 12; auto res = AesEaxBoringSsl::New(key, nonce_size); EXPECT_TRUE(res.ok()) << res.status(); auto cipher = std::move(res.value()); for (size_t size = 0; size < 260; size++) { std::string message(size, 'x'); std::string associated_data = ""; auto ct = cipher->Encrypt(message, associated_data); EXPECT_TRUE(ct.ok()) << ct.status(); EXPECT_EQ(ct.value().size(), message.size() + nonce_size + 16); auto pt = cipher->Decrypt(ct.value(), associated_data); EXPECT_TRUE(pt.ok()) << pt.status(); EXPECT_EQ(pt.value(), message); } } TEST(AesEaxBoringSslTest, TestAssociatedDataSize) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::SecretData key = util::SecretDataFromStringView( test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f")); size_t nonce_size = 12; auto res = AesEaxBoringSsl::New(key, nonce_size); EXPECT_TRUE(res.ok()) << res.status(); auto cipher = std::move(res.value()); for (size_t size = 0; size < 260; size++) { std::string message("Some message"); std::string associated_data(size, 'x'); auto ct = cipher->Encrypt(message, associated_data); EXPECT_TRUE(ct.ok()) << ct.status(); EXPECT_EQ(ct.value().size(), message.size() + nonce_size + 16); auto pt = cipher->Decrypt(ct.value(), associated_data); EXPECT_TRUE(pt.ok()) << pt.status(); EXPECT_EQ(pt.value(), message); } } TEST(AesEaxBoringSslTest, TestLongNonce) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::SecretData key = util::SecretDataFromStringView( test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f")); size_t nonce_size = 16; auto res = AesEaxBoringSsl::New(key, nonce_size); EXPECT_TRUE(res.ok()) << res.status(); auto cipher = std::move(res.value()); std::string message = "Some data to encrypt."; std::string associated_data = "Some associated data."; auto ct = cipher->Encrypt(message, associated_data); EXPECT_TRUE(ct.ok()) << ct.status(); EXPECT_EQ(ct.value().size(), message.size() + nonce_size + 16); auto pt = cipher->Decrypt(ct.value(), associated_data); EXPECT_TRUE(pt.ok()) << pt.status(); EXPECT_EQ(pt.value(), message); } TEST(AesEaxBoringSslTest, TestModification) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } size_t nonce_size = 12; util::SecretData key = util::SecretDataFromStringView( test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f")); auto cipher = std::move(AesEaxBoringSsl::New(key, nonce_size).value()); std::string message = "Some data to encrypt."; std::string associated_data = "Some data to authenticate."; std::string ct = cipher->Encrypt(message, associated_data).value(); EXPECT_TRUE(cipher->Decrypt(ct, associated_data).ok()); // Modify the ciphertext for (size_t i = 0; i < ct.size() * 8; i++) { std::string modified_ct = ct; modified_ct[i / 8] ^= 1 << (i % 8); EXPECT_FALSE(cipher->Decrypt(modified_ct, associated_data).ok()) << i; } // Modify the associated data for (size_t i = 0; i < associated_data.size() * 8; i++) { std::string modified_associated_data = associated_data; modified_associated_data[i / 8] ^= 1 << (i % 8); auto decrypted = cipher->Decrypt(ct, modified_associated_data); EXPECT_FALSE(decrypted.ok()) << i << " pt:" << decrypted.value(); } // Truncate the ciphertext for (size_t i = 0; i < ct.size(); i++) { std::string truncated_ct(ct, 0, i); EXPECT_FALSE(cipher->Decrypt(truncated_ct, associated_data).ok()) << i; } } TEST(AesEaxBoringSslTest, TestInvalidKeySizes) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } size_t nonce_size = 12; for (int keysize = 0; keysize < 65; keysize++) { if (keysize == 16 || keysize == 32) { continue; } util::SecretData key(keysize, 'x'); auto cipher = AesEaxBoringSsl::New(key, nonce_size); EXPECT_FALSE(cipher.ok()); } } TEST(AesEaxBoringSslTest, TestEmpty) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } size_t nonce_size = 12; util::SecretData key = util::SecretDataFromStringView( test::HexDecodeOrDie("bedcfb5a011ebc84600fcb296c15af0d")); std::string nonce(test::HexDecodeOrDie("438a547a94ea88dce46c6c85")); // Expected tag is an empty string with an empty tag is encrypted with // the nonce above; std::string tag(test::HexDecodeOrDie("9607977cd7556b1dfedf0c73a35a5197")); std::string ciphertext = nonce + tag; auto res = AesEaxBoringSsl::New(key, nonce_size); EXPECT_TRUE(res.ok()) << res.status(); auto cipher = std::move(res.value()); // Test decryption of the arguments above. std::string empty_string(""); absl::string_view empty_string_view(""); absl::string_view null_string_view; auto pt = cipher->Decrypt(ciphertext, empty_string); EXPECT_TRUE(pt.ok()); EXPECT_EQ(0, pt.value().size()); pt = cipher->Decrypt(ciphertext, empty_string_view); EXPECT_TRUE(pt.ok()); EXPECT_EQ(0, pt.value().size()); pt = cipher->Decrypt(ciphertext, null_string_view); EXPECT_TRUE(pt.ok()); EXPECT_EQ(0, pt.value().size()); // Test encryption. auto ct = cipher->Encrypt(empty_string, empty_string); EXPECT_TRUE(ct.ok()); pt = cipher->Decrypt(ct.value(), empty_string); EXPECT_TRUE(pt.ok()); EXPECT_EQ(0, pt.value().size()); ct = cipher->Encrypt(empty_string_view, empty_string_view); EXPECT_TRUE(ct.ok()); pt = cipher->Decrypt(ct.value(), empty_string); EXPECT_TRUE(pt.ok()); EXPECT_EQ(0, pt.value().size()); ct = cipher->Encrypt(empty_string_view, empty_string_view); EXPECT_TRUE(ct.ok()); pt = cipher->Decrypt(ct.value(), empty_string); EXPECT_TRUE(pt.ok()); EXPECT_EQ(0, pt.value().size()); ct = cipher->Encrypt(null_string_view, null_string_view); EXPECT_TRUE(ct.ok()); pt = cipher->Decrypt(ct.value(), empty_string); EXPECT_TRUE(pt.ok()); EXPECT_EQ(0, pt.value().size()); } static std::string GetError() { auto err = ERR_peek_last_error(); // Sometimes there is no error message on the stack. if (err == 0) { return ""; } std::string lib(ERR_lib_error_string(err)); std::string func(ERR_func_error_string(err)); std::string reason(ERR_reason_error_string(err)); return lib + ":" + func + ":" + reason; } // Test with test vectors from project Wycheproof. // AesEaxBoringSsl does not allow to pass in IVs. Therefore this test // can only test decryption. // Currently AesEaxBoringSsl is restricted to encryption with 12 byte // IVs and 16 byte tags. Therefore it is necessary to skip tests with // other parameter sizes. bool WycheproofTest(const rapidjson::Document& root) { int errors = 0; for (const rapidjson::Value& test_group : root["testGroups"].GetArray()) { const size_t iv_size = test_group["ivSize"].GetInt(); const size_t key_size = test_group["keySize"].GetInt(); const size_t tag_size = test_group["tagSize"].GetInt(); if (key_size != 128 && key_size != 256) { // Not supported continue; } if (iv_size != 128 && iv_size != 96) { // Not supported continue; } if (tag_size != 128) { // Not supported continue; } for (const rapidjson::Value& test : test_group["tests"].GetArray()) { std::string comment = test["comment"].GetString(); util::SecretData key = util::SecretDataFromStringView(WycheproofUtil::GetBytes(test["key"])); std::string iv = WycheproofUtil::GetBytes(test["iv"]); std::string msg = WycheproofUtil::GetBytes(test["msg"]); std::string ct = WycheproofUtil::GetBytes(test["ct"]); std::string associated_data = WycheproofUtil::GetBytes(test["aad"]); std::string tag = WycheproofUtil::GetBytes(test["tag"]); std::string id = absl::StrCat(test["tcId"].GetInt()); std::string expected = test["result"].GetString(); auto cipher = std::move(AesEaxBoringSsl::New(key, iv_size / 8).value()); auto result = cipher->Decrypt(iv + ct + tag, associated_data); bool success = result.ok(); if (success) { std::string decrypted = result.value(); if (expected == "invalid") { ADD_FAILURE() << "decrypted invalid ciphertext:" << id; errors++; } else if (msg != decrypted) { ADD_FAILURE() << "Incorrect decryption:" << id; errors++; } } else { if (expected == "valid" || expected == "acceptable") { ADD_FAILURE() << "Could not decrypt test with tcId:" << id << " iv_size:" << iv_size << " tag_size:" << tag_size << " key_size:" << key_size << " error:" << GetError(); errors++; } } } } return errors == 0; } TEST(AesEaxBoringSslTest, TestVectors) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } std::unique_ptr root = WycheproofUtil::ReadTestVectors("aes_eax_test.json"); ASSERT_TRUE(WycheproofTest(*root)); } TEST(AesEaxBoringSslTest, TestFipsOnly) { if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Only supported in FIPS-only mode"; } util::SecretData key128 = util::SecretDataFromStringView( test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f")); util::SecretData key256 = util::SecretDataFromStringView(test::HexDecodeOrDie( "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f")); EXPECT_THAT(subtle::AesEaxBoringSsl::New(key128, 16).status(), StatusIs(absl::StatusCode::kInternal)); EXPECT_THAT(subtle::AesEaxBoringSsl::New(key256, 16).status(), StatusIs(absl::StatusCode::kInternal)); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/aes_gcm_boringssl.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/aes_gcm_boringssl.h" #include #include #include "absl/memory/memory.h" #include "tink/aead.h" #include "tink/aead/internal/aead_from_zero_copy.h" #include "tink/aead/internal/zero_copy_aead.h" #include "tink/aead/internal/zero_copy_aes_gcm_boringssl.h" #include "tink/internal/fips_utils.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { util::StatusOr> AesGcmBoringSsl::New( const util::SecretData& key) { util::Status status = internal::CheckFipsCompatibility(); if (!status.ok()) { return status; } util::StatusOr> zero_copy_aead = internal::ZeroCopyAesGcmBoringSsl::New(key); if (!zero_copy_aead.ok()) { return zero_copy_aead.status(); } return {absl::make_unique( *std::move(zero_copy_aead))}; } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/aes_gcm_boringssl.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_AES_GCM_BORINGSSL_H_ #define TINK_SUBTLE_AES_GCM_BORINGSSL_H_ #include #include #include "absl/base/attributes.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/internal/fips_utils.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { class AesGcmBoringSsl { public: ABSL_DEPRECATED("Use AesGcmBoringSsl::New(const util::SecretData&) instead.") static crypto::tink::util::StatusOr> New( absl::string_view key_value) { return AesGcmBoringSsl::New(util::SecretDataFromStringView(key_value)); } static crypto::tink::util::StatusOr> New( const util::SecretData& key); static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kRequiresBoringCrypto; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_AES_GCM_BORINGSSL_H_ ================================================ FILE: cc/subtle/aes_gcm_boringssl_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/aes_gcm_boringssl.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/aead/internal/wycheproof_aead.h" #include "tink/internal/fips_utils.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace subtle { namespace { constexpr absl::string_view kMessage = "Some data to encrypt."; constexpr absl::string_view kAssociatedData = "Some associated data."; constexpr absl::string_view kKey128 = "000102030405060708090a0b0c0d0e0f"; constexpr absl::string_view kKey256 = "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::AllOf; using ::testing::Eq; using ::testing::Not; using ::testing::Test; using ::testing::TestWithParam; using ::testing::ValuesIn; class AesGcmBoringSslTest : public Test { protected: void SetUp() override { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test should not run in FIPS mode when BoringCrypto is " "unavailable."; } util::SecretData key = util::SecretDataFromStringView(absl::HexStringToBytes(kKey128)); util::StatusOr> cipher = AesGcmBoringSsl::New(key); ASSERT_THAT(cipher, IsOk()); cipher_ = std::move(*cipher); } std::unique_ptr cipher_; }; TEST_F(AesGcmBoringSslTest, BasicEncryptDecrypt) { util::StatusOr ciphertext = cipher_->Encrypt(kMessage, kAssociatedData); ASSERT_THAT(ciphertext, IsOk()); EXPECT_EQ(ciphertext->size(), kMessage.size() + 12 + 16); util::StatusOr plaintext = cipher_->Decrypt(*ciphertext, kAssociatedData); ASSERT_THAT(plaintext, IsOk()); EXPECT_EQ(*plaintext, kMessage); } TEST_F(AesGcmBoringSslTest, ModifyMessageAndAssociatedData) { util::StatusOr ciphertext = cipher_->Encrypt(kMessage, kAssociatedData); ASSERT_THAT(ciphertext, IsOk()); ASSERT_THAT(cipher_->Decrypt(*ciphertext, kAssociatedData), IsOk()); // Modify the ciphertext. for (size_t i = 0; i < ciphertext->size() * 8; i++) { std::string modified_ct = *ciphertext; modified_ct[i / 8] ^= 1 << (i % 8); EXPECT_THAT(cipher_->Decrypt(modified_ct, kAssociatedData).status(), Not(IsOk())) << i; } // Modify the associated data. for (size_t i = 0; i < kAssociatedData.size() * 8; i++) { std::string modified_ad = std::string(kAssociatedData); modified_ad[i / 8] ^= 1 << (i % 8); auto decrypted = cipher_->Decrypt(*ciphertext, modified_ad); EXPECT_THAT(decrypted, Not(IsOk())) << i << " pt:" << *decrypted; } // Truncate the ciphertext. for (size_t i = 0; i < ciphertext->size(); i++) { std::string truncated_ct(*ciphertext, 0, i); EXPECT_THAT(cipher_->Decrypt(truncated_ct, kAssociatedData).status(), Not(IsOk())) << i; } } void TestDecryptWithEmptyAssociatedData(Aead* cipher, absl::string_view ct, absl::string_view message) { { // associated_data is a null string_view. const absl::string_view associated_data; util::StatusOr plaintext = cipher->Decrypt(ct, associated_data); EXPECT_THAT(plaintext, IsOk()); EXPECT_EQ(message, *plaintext); } { // associated_data is a an empty string. util::StatusOr plaintext = cipher->Decrypt(ct, ""); EXPECT_THAT(plaintext, IsOk()); EXPECT_EQ(message, *plaintext); } { // associated_data is a default constructed string_view. util::StatusOr plaintext = cipher->Decrypt(ct, absl::string_view()); EXPECT_THAT(plaintext, IsOk()); EXPECT_EQ(message, *plaintext); } } TEST_F(AesGcmBoringSslTest, AssociatedDataEmptyVersusNullStringView) { { // associated_data is a null string_view. const absl::string_view associated_data; auto ciphertext = cipher_->Encrypt(kMessage, associated_data); EXPECT_THAT(ciphertext, IsOk()); TestDecryptWithEmptyAssociatedData(cipher_.get(), *ciphertext, kMessage); } { // associated_data is a an empty string. auto ciphertext = cipher_->Encrypt(kMessage, ""); EXPECT_THAT(ciphertext, IsOk()); TestDecryptWithEmptyAssociatedData(cipher_.get(), *ciphertext, kMessage); } { // associated_data is a default constructed string_view. auto ciphertext = cipher_->Encrypt(kMessage, absl::string_view()); EXPECT_THAT(ciphertext, IsOk()); TestDecryptWithEmptyAssociatedData(cipher_.get(), *ciphertext, kMessage); } } TEST_F(AesGcmBoringSslTest, MessageEmptyVersusNullStringView) { { // Message is a null string_view. const absl::string_view message; util::StatusOr ciphertext = cipher_->Encrypt(message, kAssociatedData); ASSERT_THAT(ciphertext, IsOk()); auto plaintext = cipher_->Decrypt(*ciphertext, kAssociatedData); ASSERT_THAT(plaintext, IsOk()); EXPECT_EQ(*plaintext, ""); } { // Message is an empty string. const std::string message = ""; util::StatusOr ciphertext = cipher_->Encrypt(message, kAssociatedData); ASSERT_THAT(ciphertext, IsOk()); auto plaintext = cipher_->Decrypt(*ciphertext, kAssociatedData); ASSERT_THAT(plaintext, IsOk()); EXPECT_EQ(*plaintext, ""); } { // Message is a default constructed string_view. util::StatusOr ciphertext = cipher_->Encrypt(absl::string_view(), kAssociatedData); ASSERT_THAT(ciphertext, IsOk()); auto plaintext = cipher_->Decrypt(*ciphertext, kAssociatedData); ASSERT_THAT(plaintext, IsOk()); EXPECT_EQ(*plaintext, ""); } } TEST_F(AesGcmBoringSslTest, BothMessageAndAssociatedDataEmpty) { { // Both are null string_view. const absl::string_view message; const absl::string_view associated_data; util::StatusOr ciphertext = cipher_->Encrypt(message, associated_data); ASSERT_THAT(ciphertext, IsOk()); auto plaintext = cipher_->Decrypt(*ciphertext, associated_data); ASSERT_THAT(plaintext, IsOk()); EXPECT_EQ(*plaintext, ""); } { // Both are empty string. const std::string message = ""; const std::string associated_data = ""; util::StatusOr ciphertext = cipher_->Encrypt(message, associated_data); ASSERT_THAT(ciphertext, IsOk()); auto plaintext = cipher_->Decrypt(*ciphertext, associated_data); ASSERT_THAT(plaintext, IsOk()); EXPECT_EQ(*plaintext, ""); } { // Both are default constructed string_view. util::StatusOr ciphertext = cipher_->Encrypt(absl::string_view(), absl::string_view()); ASSERT_THAT(ciphertext, IsOk()); auto plaintext = cipher_->Decrypt(*ciphertext, absl::string_view()); ASSERT_THAT(plaintext, IsOk()); EXPECT_EQ(*plaintext, ""); } } TEST_F(AesGcmBoringSslTest, InvalidKeySizes) { for (int keysize = 0; keysize < 65; keysize++) { util::SecretData key(keysize, 'x'); util::StatusOr> cipher = AesGcmBoringSsl::New(key); if (keysize == 16 || keysize == 32) { EXPECT_THAT(cipher, IsOk()); } else { EXPECT_THAT(cipher, Not(IsOk())); } } } TEST(AesGcmBoringSslFipsTest, FipsOnly) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test should not run in FIPS mode when BoringCrypto is unavailable."; } util::SecretData key_128 = util::SecretDataFromStringView(absl::HexStringToBytes(kKey128)); util::SecretData key_256 = util::SecretDataFromStringView(absl::HexStringToBytes(kKey256)); EXPECT_THAT(AesGcmBoringSsl::New(key_128), IsOk()); EXPECT_THAT(AesGcmBoringSsl::New(key_256), IsOk()); } TEST(AesGcmBoringSslFipsTest, FipsFailWithoutBoringCrypto) { if (!internal::IsFipsModeEnabled() || internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test assumes kOnlyUseFips but BoringCrypto is unavailable."; } util::SecretData key_128 = util::SecretDataFromStringView(absl::HexStringToBytes(kKey128)); util::SecretData key_256 = util::SecretDataFromStringView(absl::HexStringToBytes(kKey256)); EXPECT_THAT(AesGcmBoringSsl::New(key_128).status(), StatusIs(absl::StatusCode::kInternal)); EXPECT_THAT(AesGcmBoringSsl::New(key_256).status(), StatusIs(absl::StatusCode::kInternal)); } class AesGcmBoringSslWycheproofTest : public TestWithParam { void SetUp() override { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test should not run in FIPS mode when BoringCrypto is " "unavailable."; } internal::WycheproofTestVector test_vector = GetParam(); if ((test_vector.key.size() != 16 && test_vector.key.size() != 32) || test_vector.nonce.size() != 12 || test_vector.tag.size() != 16) { GTEST_SKIP() << "Unsupported parameters: key size " << test_vector.key.size() << " nonce size: " << test_vector.nonce.size() << " tag size: " << test_vector.tag.size(); } } }; TEST_P(AesGcmBoringSslWycheproofTest, Decrypt) { internal::WycheproofTestVector test_vector = GetParam(); util::SecretData key = util::SecretDataFromStringView(test_vector.key); util::StatusOr> cipher = AesGcmBoringSsl::New(key); ASSERT_THAT(cipher, IsOk()); std::string ciphertext = absl::StrCat(test_vector.nonce, test_vector.ct, test_vector.tag); util::StatusOr plaintext = (*cipher)->Decrypt(ciphertext, test_vector.aad); if (plaintext.ok()) { EXPECT_NE(test_vector.expected, "invalid"); EXPECT_EQ(*plaintext, test_vector.msg); } else { EXPECT_THAT(test_vector.expected, Not(AllOf(Eq("valid"), Eq("acceptable")))) << "Could not decrypt test with tcId: " << test_vector.id << " iv_size: " << test_vector.nonce.size() << " tag_size: " << test_vector.tag.size() << " key_size: " << key.size() << "; error: " << plaintext.status(); } } INSTANTIATE_TEST_SUITE_P(AesGcmBoringSslWycheproofTests, AesGcmBoringSslWycheproofTest, ValuesIn(internal::ReadWycheproofTestVectors( /*file_name=*/"aes_gcm_test.json"))); } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/aes_gcm_hkdf_stream_segment_decrypter.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/aes_gcm_hkdf_stream_segment_decrypter.h" #include #include #include #include #include #include #include "absl/algorithm/container.h" #include "absl/base/config.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "tink/aead/internal/ssl_aead.h" #include "tink/internal/err_util.h" #include "tink/subtle/aes_gcm_hkdf_stream_segment_encrypter.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/hkdf.h" #include "tink/subtle/random.h" #include "tink/subtle/stream_segment_decrypter.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { namespace { uint32_t ByteSwap(uint32_t val) { return ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); } void BigEndianStore32(uint8_t dst[4], uint32_t val) { #if defined(ABSL_IS_LITTLE_ENDIAN) val = ByteSwap(val); #elif !defined(ABSL_IS_BIG_ENDIAN) #error Unknown endianness #endif std::memcpy(dst, &val, sizeof(val)); } util::Status Validate(const AesGcmHkdfStreamSegmentDecrypter::Params& params) { if (!(params.hkdf_hash == SHA1 || params.hkdf_hash == SHA256 || params.hkdf_hash == SHA512)) { return util::Status(absl::StatusCode::kInvalidArgument, "unsupported hkdf_hash"); } if (params.derived_key_size != 16 && params.derived_key_size != 32) { return util::Status(absl::StatusCode::kInvalidArgument, "derived_key_size must be 16 or 32"); } if (params.ikm.size() < 16 || params.ikm.size() < params.derived_key_size) { return util::Status(absl::StatusCode::kInvalidArgument, "ikm too small"); } if (params.ciphertext_offset < 0) { return util::Status(absl::StatusCode::kInvalidArgument, "ciphertext_offset must be non-negative"); } int header_size = 1 + params.derived_key_size + AesGcmHkdfStreamSegmentEncrypter::kNoncePrefixSizeInBytes; if (params.ciphertext_segment_size <= params.ciphertext_offset + header_size + AesGcmHkdfStreamSegmentEncrypter::kTagSizeInBytes) { return util::Status(absl::StatusCode::kInvalidArgument, "ciphertext_segment_size too small"); } return util::OkStatus(); } } // namespace AesGcmHkdfStreamSegmentDecrypter::AesGcmHkdfStreamSegmentDecrypter( Params params) : ikm_(std::move(params.ikm)), hkdf_hash_(params.hkdf_hash), derived_key_size_(params.derived_key_size), ciphertext_offset_(params.ciphertext_offset), ciphertext_segment_size_(params.ciphertext_segment_size), associated_data_(std::move(params.associated_data)), header_size_(1 + derived_key_size_ + AesGcmHkdfStreamSegmentEncrypter::kNoncePrefixSizeInBytes) {} // static util::StatusOr> AesGcmHkdfStreamSegmentDecrypter::New(Params params) { auto status = Validate(params); if (!status.ok()) { return status; } return {absl::WrapUnique( new AesGcmHkdfStreamSegmentDecrypter(std::move(params)))}; } util::Status AesGcmHkdfStreamSegmentDecrypter::Init( const std::vector& header) { if (is_initialized_) { return util::Status(absl::StatusCode::kFailedPrecondition, "decrypter already initialized"); } if (header.size() != header_size_) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("wrong header size, expected ", header_size_, " bytes")); } if (header[0] != header_size_) { return util::Status(absl::StatusCode::kInvalidArgument, "corrupted header"); } // Extract salt and nonce_prefix. salt_.resize(derived_key_size_); nonce_prefix_.resize( AesGcmHkdfStreamSegmentEncrypter::kNoncePrefixSizeInBytes); absl::c_copy(absl::MakeSpan(header).subspan(1, derived_key_size_), salt_.begin()); absl::c_copy(absl::MakeSpan(header).subspan( 1 + derived_key_size_, AesGcmHkdfStreamSegmentEncrypter::kNoncePrefixSizeInBytes), nonce_prefix_.begin()); // Derive symmetric key. util::StatusOr key = Hkdf::ComputeHkdf( hkdf_hash_, ikm_, absl::string_view(reinterpret_cast(salt_.data()), derived_key_size_), associated_data_, derived_key_size_); if (!key.ok()) { return key.status(); } util::StatusOr> aead_ptr = internal::CreateAesGcmOneShotCrypter(*key); if (!aead_ptr.ok()) { return aead_ptr.status(); } aead_ = *std::move(aead_ptr); is_initialized_ = true; return util::OkStatus(); } int AesGcmHkdfStreamSegmentDecrypter::get_plaintext_segment_size() const { return ciphertext_segment_size_ - AesGcmHkdfStreamSegmentEncrypter::kTagSizeInBytes; } util::Status AesGcmHkdfStreamSegmentDecrypter::DecryptSegment( const std::vector& ciphertext, int64_t segment_number, bool is_last_segment, std::vector* plaintext_buffer) { if (!is_initialized_) { return util::Status(absl::StatusCode::kFailedPrecondition, "decrypter not initialized"); } if (ciphertext.size() > get_ciphertext_segment_size()) { return util::Status(absl::StatusCode::kInvalidArgument, "ciphertext too long"); } if (ciphertext.size() < AesGcmHkdfStreamSegmentEncrypter::kTagSizeInBytes) { return util::Status(absl::StatusCode::kInvalidArgument, "ciphertext too short"); } if (plaintext_buffer == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "plaintext_buffer must be non-null"); } if (segment_number > std::numeric_limits::max() || (segment_number == std::numeric_limits::max() && !is_last_segment)) { return util::Status(absl::StatusCode::kInvalidArgument, "too many segments"); } const int64_t kPlaintextSize = ciphertext.size() - AesGcmHkdfStreamSegmentEncrypter::kTagSizeInBytes; plaintext_buffer->resize(kPlaintextSize); // Construct IV. std::vector iv(AesGcmHkdfStreamSegmentEncrypter::kNonceSizeInBytes); absl::c_copy(nonce_prefix_, iv.begin()); BigEndianStore32( iv.data() + AesGcmHkdfStreamSegmentEncrypter::kNoncePrefixSizeInBytes, static_cast(segment_number)); iv.back() = is_last_segment ? 1 : 0; util::StatusOr written_bytes = aead_->Decrypt( absl::string_view(reinterpret_cast(ciphertext.data()), ciphertext.size()), /*associated_data=*/absl::string_view(""), absl::string_view(reinterpret_cast(iv.data()), iv.size()), absl::Span(reinterpret_cast(plaintext_buffer->data()), plaintext_buffer->size())); if (!written_bytes.ok()) { return written_bytes.status(); } return util::OkStatus(); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/aes_gcm_hkdf_stream_segment_decrypter.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_AES_GCM_HKDF_STREAM_SEGMENT_DECRYPTER_H_ #define TINK_SUBTLE_AES_GCM_HKDF_STREAM_SEGMENT_DECRYPTER_H_ #include #include #include #include #include "tink/aead/internal/ssl_aead.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/stream_segment_decrypter.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // StreamSegmentDecrypter for streaming decryption using AES-GCM with HKDF as // key derivation function. // // Each ciphertext uses a new AES-GCM key that is derived from the key // derivation key, a randomly chosen salt of the same size as the key and a // nonce prefix. // // The format of a ciphertext is // other || header || segment_0 || segment_1 || ... || segment_k. // where: // - segment_i is the i-th segment of the ciphertext. // - the size of segment_1 .. segment_{k-1} is get_ciphertext_segment_size() // - segment_0 is shorter, so that segment_0, the header, and other information // of size get_ciphertext_offset() align with get_ciphertext_segment_size(). // // The format of the header is // header_size || salt || nonce_prefix // where // - header_size is 1 byte determining the size of the header // - salt is a salt used in the key derivation // - nonce_prefix is the prefix of the nonce // // In principle header_size is redundant information, since the length of the // header can be determined from the key size. class AesGcmHkdfStreamSegmentDecrypter : public StreamSegmentDecrypter { public: // All sizes are in bytes. struct Params { util::SecretData ikm; HashType hkdf_hash; int derived_key_size; int ciphertext_offset; int ciphertext_segment_size; std::string associated_data; }; static util::StatusOr> New( Params params); util::Status Init(const std::vector& header) override; util::Status DecryptSegment( const std::vector& ciphertext, int64_t segment_number, bool is_last_segment, std::vector* plaintext_buffer) override; int get_header_size() const override { return header_size_; } int get_plaintext_segment_size() const override; int get_ciphertext_segment_size() const override { return ciphertext_segment_size_; } int get_ciphertext_offset() const override { return ciphertext_offset_; } private: explicit AesGcmHkdfStreamSegmentDecrypter(Params params); // Parameters set upon decrypter creation. // All sizes are in bytes. const util::SecretData ikm_; const HashType hkdf_hash_; const int derived_key_size_; const int ciphertext_offset_; const int ciphertext_segment_size_; const std::string associated_data_; const int header_size_; // Parameters set when initializing with data from stream header. bool is_initialized_ = false; std::vector salt_; std::vector nonce_prefix_; std::unique_ptr aead_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_AES_GCM_HKDF_STREAM_SEGMENT_DECRYPTER_H_ ================================================ FILE: cc/subtle/aes_gcm_hkdf_stream_segment_decrypter_test.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/aes_gcm_hkdf_stream_segment_decrypter.h" #include #include #include #include #include #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/subtle/aes_gcm_hkdf_stream_segment_encrypter.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/hkdf.h" #include "tink/subtle/random.h" #include "tink/subtle/stream_segment_encrypter.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace subtle { namespace { util::StatusOr> GetEncrypter( const util::SecretData& ikm, HashType hkdf_hash, int derived_key_size, int ciphertext_offset, int ciphertext_segment_size, absl::string_view associated_data) { AesGcmHkdfStreamSegmentEncrypter::Params params; params.salt = Random::GetRandomBytes(derived_key_size); auto hkdf_result = Hkdf::ComputeHkdf( hkdf_hash, ikm, params.salt, associated_data, derived_key_size); if (!hkdf_result.ok()) return hkdf_result.status(); params.key = hkdf_result.value(); params.ciphertext_offset = ciphertext_offset; params.ciphertext_segment_size = ciphertext_segment_size; return AesGcmHkdfStreamSegmentEncrypter::New(params); } TEST(AesGcmHkdfStreamSegmentDecrypterTest, testBasic) { for (int ikm_size : {16, 32}) { for (HashType hkdf_hash : {SHA1, SHA256, SHA512}) { for (int derived_key_size = 16; derived_key_size <= ikm_size; derived_key_size += 16) { for (int ciphertext_offset : {0, 5, 10}) { for (int ct_segment_size : {80, 128, 200}) { for (std::string associated_data : {"associated data", "42", ""}) { SCOPED_TRACE(absl::StrCat( "hkdf_hash = ", EnumToString(hkdf_hash), ", ikm_size = ", ikm_size, ", associated_data = '", associated_data, "'", ", derived_key_size = ", derived_key_size, ", ciphertext_offset = ", ciphertext_offset, ", ciphertext_segment_size = ", ct_segment_size)); // Construct a decrypter. AesGcmHkdfStreamSegmentDecrypter::Params params; params.ikm = Random::GetRandomKeyBytes(ikm_size); params.hkdf_hash = hkdf_hash; params.derived_key_size = derived_key_size; params.ciphertext_offset = ciphertext_offset; params.ciphertext_segment_size = ct_segment_size; params.associated_data = associated_data; auto result = AesGcmHkdfStreamSegmentDecrypter::New(params); EXPECT_TRUE(result.ok()) << result.status(); auto dec = std::move(result.value()); // Try to use the decrypter. std::vector pt; auto status = dec->DecryptSegment(pt, 42, false, nullptr); EXPECT_FALSE(status.ok()); EXPECT_EQ(absl::StatusCode::kFailedPrecondition, status.code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "not initialized", std::string(status.message())); // Get an encrypter and initialize the decrypter. auto enc = std::move(GetEncrypter(params.ikm, hkdf_hash, derived_key_size, ciphertext_offset, ct_segment_size, associated_data) .value()); status = dec->Init(enc->get_header()); EXPECT_TRUE(status.ok()) << status; // Use the constructed decrypter. int header_size = derived_key_size + /* nonce_prefix_size = */ 7 + 1; EXPECT_EQ(header_size, dec->get_header_size()); EXPECT_EQ(enc->get_header().size(), dec->get_header_size()); EXPECT_EQ(ct_segment_size, dec->get_ciphertext_segment_size()); EXPECT_EQ(ct_segment_size - /* tag_size = */ 16, dec->get_plaintext_segment_size()); EXPECT_EQ(ciphertext_offset, dec->get_ciphertext_offset()); int segment_number = 0; for (int pt_size : {1, 10, dec->get_plaintext_segment_size()}) { for (bool is_last_segment : {false, true}) { SCOPED_TRACE(absl::StrCat( "plaintext_size = ", pt_size, ", is_last_segment = ", is_last_segment)); std::vector pt(pt_size, 'p'); std::vector ct; std::vector decrypted; auto status = enc->EncryptSegment(pt, is_last_segment, &ct); EXPECT_TRUE(status.ok()) << status; status = dec->DecryptSegment(ct, segment_number, is_last_segment, &decrypted); EXPECT_TRUE(status.ok()) << status; EXPECT_EQ(pt, decrypted); segment_number++; EXPECT_EQ(segment_number, enc->get_segment_number()); } } // Try decryption with wrong params. std::vector ct( dec->get_ciphertext_segment_size() + 1, 'c'); status = dec->DecryptSegment(ct, 42, true, nullptr); EXPECT_FALSE(status.ok()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "ciphertext too long", std::string(status.message())); ct.resize(dec->get_plaintext_segment_size()); status = dec->DecryptSegment(ct, 42, true, nullptr); EXPECT_FALSE(status.ok()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "must be non-null", std::string(status.message())); } } } } } } } TEST(AesGcmHkdfStreamSegmentDecrypterTest, testWrongDerivedKeySize) { for (int derived_key_size : {12, 24, 64}) { for (HashType hkdf_hash : {SHA1, SHA256, SHA512}) { for (int ct_segment_size : {128, 200}) { SCOPED_TRACE(absl::StrCat( "derived_key_size = ", derived_key_size, ", hkdf_hash = ", EnumToString(hkdf_hash), ", ciphertext_segment_size = ", ct_segment_size)); AesGcmHkdfStreamSegmentDecrypter::Params params; params.ikm = Random::GetRandomKeyBytes(derived_key_size); params.hkdf_hash = hkdf_hash; params.derived_key_size = derived_key_size; params.ciphertext_offset = 0; params.ciphertext_segment_size = ct_segment_size; params.associated_data = "associated data"; auto result = AesGcmHkdfStreamSegmentDecrypter::New(params); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "must be 16 or 32", std::string(result.status().message())); } } } } TEST(AesGcmHkdfStreamSegmentDecrypterTest, testWrongIkmSize) { for (int derived_key_size : {16, 32}) { for (HashType hkdf_hash : {SHA1, SHA256, SHA512}) { for (int ikm_size_delta : {-8, -4, -2, -1}) { SCOPED_TRACE(absl::StrCat( "derived_key_size = ", derived_key_size, ", hkdf_hash = ", EnumToString(hkdf_hash), ", ikm_size_delta = ", ikm_size_delta)); AesGcmHkdfStreamSegmentDecrypter::Params params; params.ikm = Random::GetRandomKeyBytes(derived_key_size + ikm_size_delta); params.hkdf_hash = hkdf_hash; params.derived_key_size = derived_key_size; params.ciphertext_offset = 0; params.ciphertext_segment_size = 128; params.associated_data = "associated data"; auto result = AesGcmHkdfStreamSegmentDecrypter::New(params); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "ikm too small", std::string(result.status().message())); } } } } TEST(AesGcmHkdfStreamSegmentDecrypterTest, testWrongCiphertextOffset) { for (int derived_key_size : {16, 32}) { for (HashType hkdf_hash : {SHA1, SHA256, SHA512}) { for (int ciphertext_offset : {-16, -10, -3, -1}) { SCOPED_TRACE(absl::StrCat( "derived_key_size = ", derived_key_size, ", hkdf_hash = ", EnumToString(hkdf_hash), ", ciphertext_offset = ", ciphertext_offset)); AesGcmHkdfStreamSegmentDecrypter::Params params; params.ikm = Random::GetRandomKeyBytes(derived_key_size); params.hkdf_hash = hkdf_hash; params.derived_key_size = derived_key_size; params.ciphertext_offset = ciphertext_offset; params.ciphertext_segment_size = 128; params.associated_data = "associated data"; auto result = AesGcmHkdfStreamSegmentDecrypter::New(params); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "must be non-negative", std::string(result.status().message())); } } } } TEST(AesGcmHkdfStreamSegmentDecrypterTest, testWrongCiphertextSegmentSize) { for (int derived_key_size : {16, 32}) { for (HashType hkdf_hash : {SHA1, SHA256, SHA512}) { for (int ciphertext_offset : {0, 1, 5, 10}) { int min_ct_segment_size = derived_key_size + ciphertext_offset + 8 + // nonce_prefix_size + 1 16 + // tag_size 1; for (int ct_segment_size : {min_ct_segment_size - 5, min_ct_segment_size - 1, min_ct_segment_size, min_ct_segment_size + 1, min_ct_segment_size + 10}) { SCOPED_TRACE(absl::StrCat( "derived_key_size = ", derived_key_size, ", ciphertext_offset = ", ciphertext_offset, ", ciphertext_segment_size = ", ct_segment_size)); AesGcmHkdfStreamSegmentDecrypter::Params params; params.ikm = Random::GetRandomKeyBytes(derived_key_size); params.hkdf_hash = hkdf_hash; params.derived_key_size = derived_key_size; params.ciphertext_offset = ciphertext_offset; params.ciphertext_segment_size = ct_segment_size; auto result = AesGcmHkdfStreamSegmentDecrypter::New(params); if (ct_segment_size < min_ct_segment_size) { EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "too small", std::string(result.status().message())); } else { EXPECT_TRUE(result.ok()) << result.status(); } } } } } } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/aes_gcm_hkdf_stream_segment_encrypter.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/aes_gcm_hkdf_stream_segment_encrypter.h" #include #include #include #include #include #include #include #include "absl/algorithm/container.h" #include "absl/base/config.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "tink/aead/internal/ssl_aead.h" #include "tink/internal/err_util.h" #include "tink/subtle/random.h" #include "tink/subtle/stream_segment_encrypter.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { namespace { uint32_t ByteSwap(uint32_t val) { return ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); } void BigEndianStore32(uint8_t dst[4], uint32_t val) { #if defined(ABSL_IS_LITTLE_ENDIAN) val = ByteSwap(val); #elif !defined(ABSL_IS_BIG_ENDIAN) #error Unknown endianness #endif std::memcpy(dst, &val, sizeof(val)); } util::Status Validate(const AesGcmHkdfStreamSegmentEncrypter::Params& params) { if (params.key.size() != 16 && params.key.size() != 32) { return util::Status(absl::StatusCode::kInvalidArgument, "key must have 16 or 32 bytes"); } if (params.key.size() != params.salt.size()) { return util::Status(absl::StatusCode::kInvalidArgument, "salt must have same size as the key"); } if (params.ciphertext_offset < 0) { return util::Status(absl::StatusCode::kInvalidArgument, "ciphertext_offset must be non-negative"); } int header_size = 1 + params.salt.size() + AesGcmHkdfStreamSegmentEncrypter::kNoncePrefixSizeInBytes; if (params.ciphertext_segment_size <= params.ciphertext_offset + header_size + AesGcmHkdfStreamSegmentEncrypter::kTagSizeInBytes) { return util::Status(absl::StatusCode::kInvalidArgument, "ciphertext_segment_size too small"); } return util::OkStatus(); } std::vector CreateHeader(absl::string_view salt, absl::string_view nonce_prefix) { uint8_t header_size = static_cast( 1 + salt.size() + AesGcmHkdfStreamSegmentEncrypter::kNoncePrefixSizeInBytes); std::vector header(header_size); header[0] = header_size; absl::c_copy(salt, header.begin() + 1); absl::c_copy(nonce_prefix, header.begin() + 1 + salt.size()); return header; } // Constructs the nonce as | `nonce_prefix` | `segment_number` | 0 if // `is_last_segment` or 1 |. std::string ConstructNonce(absl::string_view nonce_prefix, uint32_t segment_number, bool is_last_segment) { std::string iv; ResizeStringUninitialized( &iv, AesGcmHkdfStreamSegmentEncrypter::kNonceSizeInBytes); absl::c_copy(nonce_prefix, absl::MakeSpan(iv).begin()); BigEndianStore32( reinterpret_cast(&iv[0]) + AesGcmHkdfStreamSegmentEncrypter::kNoncePrefixSizeInBytes, segment_number); iv.back() = is_last_segment ? 1 : 0; return iv; } } // namespace int AesGcmHkdfStreamSegmentEncrypter::get_plaintext_segment_size() const { return ciphertext_segment_size_ - kTagSizeInBytes; } AesGcmHkdfStreamSegmentEncrypter::AesGcmHkdfStreamSegmentEncrypter( std::unique_ptr aead, const Params& params) : aead_(std::move(aead)), nonce_prefix_(Random::GetRandomBytes(kNoncePrefixSizeInBytes)), header_(CreateHeader(params.salt, nonce_prefix_)), ciphertext_segment_size_(params.ciphertext_segment_size), ciphertext_offset_(params.ciphertext_offset) {} util::StatusOr> AesGcmHkdfStreamSegmentEncrypter::New(Params params) { util::Status status = Validate(params); if (!status.ok()) { return status; } util::StatusOr> aead = internal::CreateAesGcmOneShotCrypter(params.key); if (!aead.ok()) { return aead.status(); } return {absl::WrapUnique( new AesGcmHkdfStreamSegmentEncrypter(*std::move(aead), params))}; } util::Status AesGcmHkdfStreamSegmentEncrypter::EncryptSegment( const std::vector& plaintext, bool is_last_segment, std::vector* ciphertext_buffer) { if (plaintext.size() > get_plaintext_segment_size()) { return util::Status(absl::StatusCode::kInvalidArgument, "plaintext too long"); } if (ciphertext_buffer == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "ciphertext_buffer must be non-null"); } if (get_segment_number() > std::numeric_limits::max() || (get_segment_number() == std::numeric_limits::max() && !is_last_segment)) { return util::Status(absl::StatusCode::kInvalidArgument, "too many segments"); } const int64_t kCiphertextSize = plaintext.size() + kTagSizeInBytes; ciphertext_buffer->resize(kCiphertextSize); // Construct IV. std::string iv = ConstructNonce(nonce_prefix_, static_cast(get_segment_number()), is_last_segment); util::StatusOr written_bytes = aead_->Encrypt( absl::string_view(reinterpret_cast(plaintext.data()), plaintext.size()), /*associated_data=*/absl::string_view(""), iv, absl::MakeSpan(reinterpret_cast(ciphertext_buffer->data()), ciphertext_buffer->size())); if (!written_bytes.ok()) { return written_bytes.status(); } IncSegmentNumber(); return util::OkStatus(); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/aes_gcm_hkdf_stream_segment_encrypter.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_AES_GCM_HKDF_STREAM_SEGMENT_ENCRYPTER_H_ #define TINK_SUBTLE_AES_GCM_HKDF_STREAM_SEGMENT_ENCRYPTER_H_ #include #include #include #include #include "tink/aead/internal/ssl_aead.h" #include "tink/subtle/stream_segment_encrypter.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // StreamSegmentEncrypter for streaming encryption using AES-GCM with HKDF as // key derivation function. // // Each ciphertext uses a new AES-GCM key that is derived from the key // derivation key, a randomly chosen salt of the same size as the key and a // nonce prefix. // // The format of a ciphertext is // header || segment_0 || segment_1 || ... || segment_k. // where: // - segment_i is the i-th segment of the ciphertext. // - the size of segment_1 .. segment_{k-1} is get_ciphertext_segment_size() // - segment_0 is shorter, so that segment_0, the header and other information // of size get_ciphertext_offset() align with get_ciphertext_segment_size(). // // The format of the header is // header_size || salt || nonce_prefix // where // - header_size is 1 byte determining the size of the header // - salt is a salt used in the key derivation // - nonce_prefix is the prefix of the nonce // // In principle header_size is redundant information, since the length of the // header can be determined from the key size. class AesGcmHkdfStreamSegmentEncrypter : public StreamSegmentEncrypter { public: // The size of the IVs for GCM. static constexpr int kNonceSizeInBytes = 12; // The nonce has the format nonce_prefix || ctr || last_block, where: // - nonce_prefix is a constant of kNoncePrefixSizeInBytes bytes // for the whole file // - ctr is a 32 bit counter // - last_block is a byte equal to 1 for the last block of the file // and 0 otherwise. static constexpr int kNoncePrefixSizeInBytes = 7; // The size of the tags of each ciphertext segment. static constexpr int kTagSizeInBytes = 16; struct Params { util::SecretData key; std::string salt; int ciphertext_offset; int ciphertext_segment_size; }; static util::StatusOr> New( Params params); util::Status EncryptSegment(const std::vector& plaintext, bool is_last_segment, std::vector* ciphertext_buffer) override; const std::vector& get_header() const override { return header_; } int64_t get_segment_number() const override { return segment_number_; } int get_plaintext_segment_size() const override; int get_ciphertext_segment_size() const override { return ciphertext_segment_size_; } int get_ciphertext_offset() const override { return ciphertext_offset_; } protected: void IncSegmentNumber() override { segment_number_++; } private: AesGcmHkdfStreamSegmentEncrypter( std::unique_ptr aead, const Params& params); // When OpenSSL is used, this uses a thread-safe implementation that makes a // copy of the context for each EncryptSegment call, which may result in some // extra latency compared to BoringSSL. const std::unique_ptr aead_; const std::string nonce_prefix_; const std::vector header_; const int ciphertext_segment_size_; const int ciphertext_offset_; int64_t segment_number_ = 0; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_AES_GCM_HKDF_STREAM_SEGMENT_ENCRYPTER_H_ ================================================ FILE: cc/subtle/aes_gcm_hkdf_stream_segment_encrypter_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/aes_gcm_hkdf_stream_segment_encrypter.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/subtle/random.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace subtle { namespace { using ::testing::HasSubstr; TEST(AesGcmHkdfStreamSegmentEncrypterTest, testBasic) { for (int key_size : {16, 32}) { for (int ciphertext_offset : {0, 5, 10}) { for (int ct_segment_size : {80, 128, 200}) { SCOPED_TRACE(absl::StrCat( "key_size = ", key_size, ", ciphertext_offset = ", ciphertext_offset, ", ciphertext_segment_size = ", ct_segment_size)); // Construct an encrypter. AesGcmHkdfStreamSegmentEncrypter::Params params; params.key = Random::GetRandomKeyBytes(key_size); params.salt = Random::GetRandomBytes(key_size); params.ciphertext_offset = ciphertext_offset; params.ciphertext_segment_size = ct_segment_size; auto result = AesGcmHkdfStreamSegmentEncrypter::New(params); EXPECT_TRUE(result.ok()) << result.status(); // Use the Constructed encrypter. auto enc = std::move(result.value()); EXPECT_EQ(0, enc->get_segment_number()); int header_size = key_size + /* nonce_prefix_size = */ 7 + 1; EXPECT_EQ(header_size, enc->get_header().size()); EXPECT_EQ(header_size, enc->get_header()[0]); EXPECT_EQ(params.salt, std::string(reinterpret_cast( enc->get_header().data() + 1), key_size)); EXPECT_EQ(ct_segment_size, enc->get_ciphertext_segment_size()); EXPECT_EQ(ct_segment_size - /* tag_size = */ 16, enc->get_plaintext_segment_size()); EXPECT_EQ(ciphertext_offset, enc->get_ciphertext_offset()); int segment_number = 0; for (int pt_size : {1, 10, enc->get_plaintext_segment_size()}) { for (bool is_last_segment : {false, true}) { SCOPED_TRACE(absl::StrCat( "plaintext_size = ", pt_size, ", is_last_segment = ", is_last_segment)); std::vector pt(pt_size, 'p'); std::vector ct; auto status = enc->EncryptSegment(pt, is_last_segment, &ct); EXPECT_TRUE(status.ok()) << status; EXPECT_EQ(pt_size + /* tag_size = */ 16, ct.size()); segment_number++; EXPECT_EQ(segment_number, enc->get_segment_number()); } } // Try encryption with wrong params. std::vector pt(enc->get_plaintext_segment_size() + 1, 'p'); auto status = enc->EncryptSegment(pt, true, nullptr); EXPECT_FALSE(status.ok()); EXPECT_THAT(std::string(status.message()), HasSubstr("plaintext too long")); pt.resize(enc->get_plaintext_segment_size()); status = enc->EncryptSegment(pt, true, nullptr); EXPECT_FALSE(status.ok()); EXPECT_THAT(std::string(status.message()), HasSubstr("must be non-null")); } } } } TEST(AesGcmHkdfStreamSegmentEncrypterTest, testWrongKeySize) { for (int key_size : {12, 24, 64}) { for (int ciphertext_offset : {0, 5, 10}) { for (int ct_segment_size : {128, 200}) { SCOPED_TRACE(absl::StrCat( "key_size = ", key_size, ", ciphertext_offset = ", ciphertext_offset, ", ciphertext_segment_size = ", ct_segment_size)); AesGcmHkdfStreamSegmentEncrypter::Params params; params.key = Random::GetRandomKeyBytes(key_size); params.salt = Random::GetRandomBytes(key_size); params.ciphertext_offset = ciphertext_offset; params.ciphertext_segment_size = ct_segment_size; auto result = AesGcmHkdfStreamSegmentEncrypter::New(params); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_THAT(std::string(result.status().message()), HasSubstr("must have 16 or 32 bytes")); } } } } TEST(AesGcmHkdfStreamSegmentEncrypterTest, testWrongSaltSize) { for (int key_size : {16, 32}) { for (int salt_size_delta : {-3, -1, 1, 5, 16}) { SCOPED_TRACE(absl::StrCat( "key_size = ", key_size, ", salt_size = ", key_size + salt_size_delta)); AesGcmHkdfStreamSegmentEncrypter::Params params; params.key = Random::GetRandomKeyBytes(key_size); params.salt = Random::GetRandomBytes(key_size + salt_size_delta); params.ciphertext_offset = 0; params.ciphertext_segment_size = 128; auto result = AesGcmHkdfStreamSegmentEncrypter::New(params); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_THAT(std::string(result.status().message()), HasSubstr("same size as the key")); } } } TEST(AesGcmHkdfStreamSegmentEncrypterTest, testWrongCiphertextOffset) { for (int key_size : {16, 32}) { for (int ciphertext_offset : {-16, -10, -3, -1}) { SCOPED_TRACE(absl::StrCat( "key_size = ", key_size, ", ciphertext_offset = ", ciphertext_offset)); AesGcmHkdfStreamSegmentEncrypter::Params params; params.key = Random::GetRandomKeyBytes(key_size); params.salt = Random::GetRandomBytes(key_size); params.ciphertext_offset = ciphertext_offset; params.ciphertext_segment_size = 128; auto result = AesGcmHkdfStreamSegmentEncrypter::New(params); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_THAT(std::string(result.status().message()), HasSubstr("must be non-negative")); } } } TEST(AesGcmHkdfStreamSegmentEncrypterTest, testWrongCiphertextSegmentSize) { for (int key_size : {16, 32}) { for (int ciphertext_offset : {0, 1, 5, 10}) { int min_ct_segment_size = key_size + ciphertext_offset + 8 + // nonce_prefix_size + 1 16 + // tag_size 1; for (int ct_segment_size : {min_ct_segment_size - 5, min_ct_segment_size - 1, min_ct_segment_size, min_ct_segment_size + 1, min_ct_segment_size + 10}) { SCOPED_TRACE(absl::StrCat( "key_size = ", key_size, ", ciphertext_offset = ", ciphertext_offset, ", ciphertext_segment_size = ", ct_segment_size)); AesGcmHkdfStreamSegmentEncrypter::Params params; params.key = Random::GetRandomKeyBytes(key_size); params.salt = Random::GetRandomBytes(key_size); params.ciphertext_offset = ciphertext_offset; params.ciphertext_segment_size = ct_segment_size; auto result = AesGcmHkdfStreamSegmentEncrypter::New(params); if (ct_segment_size < min_ct_segment_size) { EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_THAT(std::string(result.status().message()), HasSubstr("too small")); } else { EXPECT_TRUE(result.ok()) << result.status(); } } } } } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/aes_gcm_hkdf_streaming.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/aes_gcm_hkdf_streaming.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/internal/fips_utils.h" #include "tink/subtle/aes_gcm_hkdf_stream_segment_decrypter.h" #include "tink/subtle/aes_gcm_hkdf_stream_segment_encrypter.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/hkdf.h" #include "tink/subtle/random.h" #include "tink/subtle/stream_segment_decrypter.h" #include "tink/subtle/stream_segment_encrypter.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { namespace { util::Status Validate(const AesGcmHkdfStreaming::Params& params) { if (!(params.hkdf_hash == SHA1 || params.hkdf_hash == SHA256 || params.hkdf_hash == SHA512)) { return util::Status(absl::StatusCode::kInvalidArgument, "unsupported hkdf_hash"); } if (params.ikm.size() < 16 || params.ikm.size() < params.derived_key_size) { return util::Status(absl::StatusCode::kInvalidArgument, "ikm too small"); } if (params.derived_key_size != 16 && params.derived_key_size != 32) { return util::Status(absl::StatusCode::kInvalidArgument, "derived_key_size must be 16 or 32"); } if (params.ciphertext_offset < 0) { return util::Status(absl::StatusCode::kInvalidArgument, "ciphertext_offset must be non-negative"); } if (params.ciphertext_segment_size <= params.ciphertext_offset + params.derived_key_size + AesGcmHkdfStreamSegmentEncrypter::kTagSizeInBytes) { return util::Status(absl::StatusCode::kInvalidArgument, "ciphertext_segment_size too small"); } return util::OkStatus(); } } // namespace util::StatusOr> AesGcmHkdfStreaming::New( Params params) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) return status; status = Validate(params); if (!status.ok()) return status; return {absl::WrapUnique(new AesGcmHkdfStreaming(std::move(params)))}; } util::StatusOr> AesGcmHkdfStreaming::NewSegmentEncrypter( absl::string_view associated_data) const { AesGcmHkdfStreamSegmentEncrypter::Params params; params.salt = Random::GetRandomBytes(derived_key_size_); auto hkdf_result = Hkdf::ComputeHkdf(hkdf_hash_, ikm_, params.salt, associated_data, derived_key_size_); if (!hkdf_result.ok()) return hkdf_result.status(); params.key = std::move(hkdf_result).value(); params.ciphertext_offset = ciphertext_offset_; params.ciphertext_segment_size = ciphertext_segment_size_; return AesGcmHkdfStreamSegmentEncrypter::New(std::move(params)); } util::StatusOr> AesGcmHkdfStreaming::NewSegmentDecrypter( absl::string_view associated_data) const { AesGcmHkdfStreamSegmentDecrypter::Params params; params.ikm = ikm_; params.hkdf_hash = hkdf_hash_; params.derived_key_size = derived_key_size_; params.ciphertext_offset = ciphertext_offset_; params.ciphertext_segment_size = ciphertext_segment_size_; params.associated_data = std::string(associated_data); return AesGcmHkdfStreamSegmentDecrypter::New(std::move(params)); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/aes_gcm_hkdf_streaming.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_AES_GCM_HKDF_STREAMING_H_ #define TINK_SUBTLE_AES_GCM_HKDF_STREAMING_H_ #include #include #include "absl/strings/string_view.h" #include "tink/internal/fips_utils.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/nonce_based_streaming_aead.h" #include "tink/subtle/stream_segment_decrypter.h" #include "tink/subtle/stream_segment_encrypter.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { class AesGcmHkdfStreaming : public NonceBasedStreamingAead { public: struct Params { util::SecretData ikm; HashType hkdf_hash; int derived_key_size; int ciphertext_segment_size; int ciphertext_offset; }; static util::StatusOr> New( Params params); static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kNotFips; protected: util::StatusOr> NewSegmentEncrypter( absl::string_view associated_data) const override; util::StatusOr> NewSegmentDecrypter( absl::string_view associated_data) const override; private: explicit AesGcmHkdfStreaming(Params params) : ikm_(std::move(params.ikm)), hkdf_hash_(params.hkdf_hash), derived_key_size_(params.derived_key_size), ciphertext_segment_size_(params.ciphertext_segment_size), ciphertext_offset_(params.ciphertext_offset) {} const util::SecretData ikm_; const HashType hkdf_hash_; const int derived_key_size_; const int ciphertext_segment_size_; const int ciphertext_offset_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_AES_GCM_HKDF_STREAMING_H_ ================================================ FILE: cc/subtle/aes_gcm_hkdf_streaming_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/aes_gcm_hkdf_streaming.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "tink/config/tink_fips.h" #include "tink/internal/test_random_access_stream.h" #include "tink/output_stream.h" #include "tink/random_access_stream.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/random.h" #include "tink/subtle/streaming_aead_test_util.h" #include "tink/subtle/test_util.h" #include "tink/util/istream_input_stream.h" #include "tink/util/ostream_output_stream.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; using ::testing::Eq; TEST(AesGcmHkdfStreamingTest, testBasic) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } for (HashType hkdf_hash : {SHA1, SHA256, SHA512}) { for (int ikm_size : {16, 32}) { for (int derived_key_size = 16; derived_key_size <= ikm_size; derived_key_size += 16) { for (int ct_segment_size : {80, 128, 200}) { for (int ciphertext_offset : {0, 10, 16}) { SCOPED_TRACE(absl::StrCat( "hkdf_hash = ", EnumToString(hkdf_hash), ", ikm_size = ", ikm_size, ", derived_key_size = ", derived_key_size, ", ciphertext_segment_size = ", ct_segment_size, ", ciphertext_offset = ", ciphertext_offset)); // Create AesGcmHkdfStreaming. AesGcmHkdfStreaming::Params params; params.ikm = Random::GetRandomKeyBytes(ikm_size); params.hkdf_hash = hkdf_hash; params.derived_key_size = derived_key_size; params.ciphertext_segment_size = ct_segment_size; params.ciphertext_offset = ciphertext_offset; auto result = AesGcmHkdfStreaming::New(std::move(params)); EXPECT_TRUE(result.ok()) << result.status(); auto streaming_aead = std::move(result.value()); // Try to get an encrypting stream to a "null" ct_destination. std::string associated_data = "some associated data"; auto failed_result = streaming_aead->NewEncryptingStream( nullptr, associated_data); EXPECT_FALSE(failed_result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, failed_result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "non-null", std::string(failed_result.status().message())); for (int pt_size : {0, 16, 100, 1000, 10000}) { SCOPED_TRACE(absl::StrCat(" pt_size = ", pt_size)); std::string pt = Random::GetRandomBytes(pt_size); EXPECT_THAT( EncryptThenDecrypt(streaming_aead.get(), streaming_aead.get(), pt, associated_data, ciphertext_offset), IsOk()); } } } } } } } TEST(AesGcmHkdfStreamingTest, testIkmSmallerThanDerivedKey) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } AesGcmHkdfStreaming::Params params; int ikm_size = 16; params.ikm = Random::GetRandomKeyBytes(ikm_size); params.derived_key_size = 17; params.ciphertext_segment_size = 100; params.ciphertext_offset = 10; params.hkdf_hash = SHA256; auto result = AesGcmHkdfStreaming::New(std::move(params)); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "ikm too small", std::string(result.status().message())); } TEST(AesGcmHkdfStreamingTest, testIkmSize) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } for (int ikm_size : {5, 10, 15}) { AesGcmHkdfStreaming::Params params; params.ikm = Random::GetRandomKeyBytes(ikm_size); params.derived_key_size = 17; params.ciphertext_segment_size = 100; params.ciphertext_offset = 0; params.hkdf_hash = SHA256; auto result = AesGcmHkdfStreaming::New(std::move(params)); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "ikm too small", std::string(result.status().message())); } } TEST(AesGcmHkdfStreamingTest, testWrongHkdfHash) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } AesGcmHkdfStreaming::Params params; int ikm_size = 16; params.ikm = Random::GetRandomKeyBytes(ikm_size); params.derived_key_size = 16; params.ciphertext_segment_size = 100; params.ciphertext_offset = 10; params.hkdf_hash = SHA384; auto result = AesGcmHkdfStreaming::New(std::move(params)); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "unsupported hkdf_hash", std::string(result.status().message())); } TEST(AesGcmHkdfStreamingTest, testWrongDerivedKeySize) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } AesGcmHkdfStreaming::Params params; int ikm_size = 20; params.ikm = Random::GetRandomKeyBytes(ikm_size); params.derived_key_size = 20; params.ciphertext_segment_size = 100; params.ciphertext_offset = 10; params.hkdf_hash = SHA256; auto result = AesGcmHkdfStreaming::New(std::move(params)); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "must be 16 or 32", std::string(result.status().message())); } TEST(AesGcmHkdfStreamingTest, testWrongCiphertextOffset) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } AesGcmHkdfStreaming::Params params; int ikm_size = 32; params.ikm = Random::GetRandomKeyBytes(ikm_size); params.derived_key_size = 32; params.ciphertext_segment_size = 100; params.ciphertext_offset = -5; params.hkdf_hash = SHA256; auto result = AesGcmHkdfStreaming::New(std::move(params)); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "must be non-negative", std::string(result.status().message())); } TEST(AesGcmHkdfStreamingTest, testWrongCiphertextSegmentSize) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } AesGcmHkdfStreaming::Params params; int ikm_size = 32; params.ikm = Random::GetRandomKeyBytes(ikm_size); params.derived_key_size = 32; params.ciphertext_segment_size = 64; params.ciphertext_offset = 40; params.hkdf_hash = SHA256; auto result = AesGcmHkdfStreaming::New(std::move(params)); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "ciphertext_segment_size too small", std::string(result.status().message())); } TEST(AesGcmHkdfStreamingTest, SizeIsUnauthenticated) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } AesGcmHkdfStreaming::Params params; params.ikm = Random::GetRandomKeyBytes(16); params.hkdf_hash = SHA1; params.derived_key_size = 16; params.ciphertext_segment_size = 100; params.ciphertext_offset = 0; util::StatusOr> streaming_aead = AesGcmHkdfStreaming::New(std::move(params)); ASSERT_THAT(streaming_aead.status(), IsOk()); std::string associated_data = "some associated data"; // The header is 24 = 0x18 bytes for this key and Tink verifies that the // ciphertext starts with 0x18 in the first byte. std::string wrong_ciphertext = absl::StrCat(absl::HexStringToBytes("18"), "some arbitrary text which does not matter at all but needs " "to be at least of length 24 bytes"); absl::StatusOr> plaintext_stream = (*streaming_aead) ->NewDecryptingRandomAccessStream( absl::make_unique( wrong_ciphertext), associated_data); ASSERT_THAT(plaintext_stream.status(), IsOk()); // 53 is the length of "wrong_ciphertext" minus the overhead (header + tag). EXPECT_THAT((*plaintext_stream)->size(), IsOkAndHolds(Eq(53))); } // FIPS only mode tests TEST(AesGcmHkdfStreamingTest, TestFipsOnly) { if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Only supported in FIPS-only mode"; } AesGcmHkdfStreaming::Params params; int ikm_size = 32; params.ikm = Random::GetRandomKeyBytes(ikm_size); params.derived_key_size = 32; params.ciphertext_segment_size = 64; params.ciphertext_offset = 40; params.hkdf_hash = SHA256; EXPECT_THAT(AesGcmHkdfStreaming::New(std::move(params)).status(), StatusIs(absl::StatusCode::kInternal)); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/aes_gcm_siv_boringssl.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/aes_gcm_siv_boringssl.h" #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "tink/aead.h" #include "tink/aead/internal/ssl_aead.h" #include "tink/internal/fips_utils.h" #include "tink/subtle/random.h" #include "tink/subtle/subtle_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { constexpr int kIvSizeInBytes = 12; constexpr int kTagSizeInBytes = 16; util::StatusOr> AesGcmSivBoringSsl::New( const util::SecretData& key) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) { return status; } util::StatusOr> aead = internal::CreateAesGcmSivOneShotCrypter(key); if (!aead.ok()) { return aead.status(); } return {absl::WrapUnique(new AesGcmSivBoringSsl(*std::move(aead)))}; } util::StatusOr AesGcmSivBoringSsl::Encrypt( absl::string_view plaintext, absl::string_view associated_data) const { const int64_t kCiphertextSize = kIvSizeInBytes + aead_->CiphertextSize(plaintext.size()); std::string ct; ResizeStringUninitialized(&ct, kCiphertextSize); util::Status res = Random::GetRandomBytes(absl::MakeSpan(ct).subspan(0, kIvSizeInBytes)); if (!res.ok()) { return res; } auto nonce = absl::string_view(ct).substr(0, kIvSizeInBytes); auto ciphertext_and_tag_buffer = absl::MakeSpan(ct).subspan(kIvSizeInBytes); util::StatusOr written_bytes = aead_->Encrypt( plaintext, associated_data, nonce, ciphertext_and_tag_buffer); if (!written_bytes.ok()) { return written_bytes.status(); } return ct; } util::StatusOr AesGcmSivBoringSsl::Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const { if (ciphertext.size() < kIvSizeInBytes + kTagSizeInBytes) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Ciphertext too short; expected at least ", kIvSizeInBytes + kTagSizeInBytes, " got ", ciphertext.size())); } const int64_t kPlaintextSize = aead_->PlaintextSize(ciphertext.size() - kIvSizeInBytes); std::string plaintext; ResizeStringUninitialized(&plaintext, kPlaintextSize); auto nonce = ciphertext.substr(0, kIvSizeInBytes); auto encrypted = ciphertext.substr(kIvSizeInBytes); util::StatusOr written_bytes = aead_->Decrypt( encrypted, associated_data, nonce, absl::MakeSpan(plaintext)); if (!written_bytes.ok()) { return written_bytes.status(); } return plaintext; } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/aes_gcm_siv_boringssl.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_AES_GCM_SIV_BORINGSSL_H_ #define TINK_SUBTLE_AES_GCM_SIV_BORINGSSL_H_ #include #include #include #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/aead/internal/ssl_aead.h" #include "tink/internal/fips_utils.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // AES-GCM-SIV is based on the paper // “GCM-SIV: full nonce misuse-resistant authenticated encryption at under one // cycle per byte.” by S.Gueron, and Y.Lindell, // Proceedings of the 22nd ACM SIGSAC Conference on Computer and Communications // Security. ACM, 2015. // The implementation uses AES-GCM-SIV as defined in draft-irtf-cfrg-gcmsiv-08 // https://datatracker.ietf.org/doc/draft-irtf-cfrg-gcmsiv/ // // This encryption mode is intended for authenticated encryption with // associated data. A major security problem with AES-GCM is // that reusing the same nonce twice leaks the authentication key. // AES-GCM-SIV on the other hand has been designed to avoid this vulnerability. // // Usage bounds for the encryption mode can be found on // https://cyber.biu.ac.il/aes-gcm-siv/ // or Section 6.3 of this paper: // https://eprint.iacr.org/2017/702.pdf class AesGcmSivBoringSsl : public Aead { public: static crypto::tink::util::StatusOr> New( const util::SecretData& key); crypto::tink::util::StatusOr Encrypt( absl::string_view plaintext, absl::string_view associated_data) const override; crypto::tink::util::StatusOr Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const override; static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kNotFips; private: explicit AesGcmSivBoringSsl(std::unique_ptr aead) : aead_(std::move(aead)) {} const std::unique_ptr aead_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_AES_GCM_SIV_BORINGSSL_H_ ================================================ FILE: cc/subtle/aes_gcm_siv_boringssl_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/aes_gcm_siv_boringssl.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/aead/internal/wycheproof_aead.h" #include "tink/config/tink_fips.h" #include "tink/internal/ssl_util.h" #include "tink/subtle/subtle_util.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace subtle { namespace { constexpr absl::string_view kKey256Hex = "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"; constexpr absl::string_view kMessage = "Some data to encrypt."; constexpr absl::string_view kAssociatedData = "Some data to authenticate."; constexpr int kIvSizeInBytes = 12; constexpr int kTagSizeInBytes = 16; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::AllOf; using ::testing::Eq; using ::testing::Not; using ::testing::SizeIs; using ::testing::TestWithParam; using ::testing::ValuesIn; TEST(AesGcmSivBoringSslTest, EncryptDecrypt) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::SecretData key = util::SecretDataFromStringView(absl::HexStringToBytes(kKey256Hex)); if (!internal::IsBoringSsl()) { EXPECT_THAT(AesGcmSivBoringSsl::New(key).status(), StatusIs(absl::StatusCode::kUnimplemented)); } else { util::StatusOr> aead = AesGcmSivBoringSsl::New(key); ASSERT_THAT(aead, IsOk()); util::StatusOr ciphertext = (*aead)->Encrypt(kMessage, kAssociatedData); ASSERT_THAT(ciphertext, IsOk()); EXPECT_THAT(*ciphertext, SizeIs(kMessage.size() + kIvSizeInBytes + kTagSizeInBytes)); util::StatusOr plaintext = (*aead)->Decrypt(*ciphertext, kAssociatedData); ASSERT_THAT(plaintext, IsOk()); EXPECT_EQ(*plaintext, kMessage); } } TEST(AesGcmSivBoringSslTest, DecryptFailsIfCiphertextTooSmall) { if (!internal::IsBoringSsl()) { GTEST_SKIP() << "Unimplemented with OpenSSL"; } if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::SecretData key = util::SecretDataFromStringView(absl::HexStringToBytes(kKey256Hex)); util::StatusOr> aead = AesGcmSivBoringSsl::New(key); ASSERT_THAT(aead, IsOk()); for (int i = 1; i < kIvSizeInBytes + kTagSizeInBytes; i++) { std::string ciphertext; ResizeStringUninitialized(&ciphertext, i); EXPECT_THAT((*aead)->Decrypt(ciphertext, kAssociatedData).status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } TEST(AesGcmSivBoringSslTest, TestFipsOnly) { if (!internal::IsBoringSsl()) { GTEST_SKIP() << "Unimplemented with OpenSSL"; } if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Only supported in FIPS-only mode"; } util::SecretData key128 = util::SecretDataFromStringView( absl::HexStringToBytes("000102030405060708090a0b0c0d0e0f")); util::SecretData key256 = util::SecretDataFromStringView(absl::HexStringToBytes( "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f")); EXPECT_THAT(AesGcmSivBoringSsl::New(key128).status(), StatusIs(absl::StatusCode::kInternal)); EXPECT_THAT(AesGcmSivBoringSsl::New(key256).status(), StatusIs(absl::StatusCode::kInternal)); } class AesGcmSivBoringSslWycheproofTest : public TestWithParam { void SetUp() override { if (!internal::IsBoringSsl()) { GTEST_SKIP() << "Unimplemented with OpenSSL"; } if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } internal::WycheproofTestVector test_vector = GetParam(); if ((test_vector.key.size() != 16 && test_vector.key.size() != 32) || test_vector.nonce.size() != kIvSizeInBytes || test_vector.tag.size() != kTagSizeInBytes) { GTEST_SKIP() << "Unsupported parameters: key size " << test_vector.key.size() << " nonce size: " << test_vector.nonce.size() << " tag size: " << test_vector.tag.size(); } } }; TEST_P(AesGcmSivBoringSslWycheproofTest, Decrypt) { internal::WycheproofTestVector test_vector = GetParam(); util::SecretData key = util::SecretDataFromStringView(test_vector.key); util::StatusOr> cipher = AesGcmSivBoringSsl::New(key); ASSERT_THAT(cipher, IsOk()); std::string ciphertext = absl::StrCat(test_vector.nonce, test_vector.ct, test_vector.tag); util::StatusOr plaintext = (*cipher)->Decrypt(ciphertext, test_vector.aad); if (plaintext.ok()) { EXPECT_NE(test_vector.expected, "invalid"); EXPECT_EQ(*plaintext, test_vector.msg); } else { EXPECT_THAT(test_vector.expected, Not(AllOf(Eq("valid"), Eq("acceptable")))) << "Could not decrypt test with tcId: " << test_vector.id << " iv_size: " << test_vector.nonce.size() << " tag_size: " << test_vector.tag.size() << " key_size: " << key.size() << "; error: " << plaintext.status(); } } INSTANTIATE_TEST_SUITE_P(AesGcmSivBoringSslWycheproofTests, AesGcmSivBoringSslWycheproofTest, ValuesIn(internal::ReadWycheproofTestVectors( /*file_name=*/"aes_gcm_siv_test.json"))); } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/aes_siv_boringssl.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/aes_siv_boringssl.h" #include #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "openssl/aes.h" #include "openssl/crypto.h" #include "tink/aead/internal/aead_util.h" #include "tink/deterministic_aead.h" #include "tink/internal/aes_util.h" #include "tink/internal/fips_utils.h" #include "tink/subtle/subtle_util.h" #include "tink/util/errors.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { namespace { crypto::tink::util::StatusOr> InitializeAesKey( absl::Span key) { util::SecretUniquePtr aes_key = util::MakeSecretUniquePtr(); if (AES_set_encrypt_key(reinterpret_cast(key.data()), 8 * key.size(), aes_key.get()) != 0) { return util::Status(absl::StatusCode::kInternal, "could not initialize aes key"); } return std::move(aes_key); } } // namespace // static crypto::tink::util::StatusOr> AesSivBoringSsl::New(const util::SecretData& key) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) return status; if (!IsValidKeySizeInBytes(key.size())) { return util::Status(absl::StatusCode::kInvalidArgument, "invalid key size"); } auto k1_or = InitializeAesKey(absl::MakeSpan(key).subspan(0, key.size() / 2)); if (!k1_or.ok()) { return k1_or.status(); } util::SecretUniquePtr k1 = std::move(k1_or).value(); auto k2_or = InitializeAesKey(absl::MakeSpan(key).subspan(key.size() / 2)); if (!k2_or.ok()) { return k2_or.status(); } util::SecretUniquePtr k2 = std::move(k2_or).value(); return {absl::WrapUnique(new AesSivBoringSsl(std::move(k1), std::move(k2)))}; } util::SecretData AesSivBoringSsl::ComputeCmacK1() const { util::SecretData cmac_k1(kBlockSize, 0); EncryptBlock(cmac_k1.data(), cmac_k1.data()); MultiplyByX(cmac_k1.data()); return cmac_k1; } util::SecretData AesSivBoringSsl::ComputeCmacK2() const { util::SecretData cmac_k2(cmac_k1_); MultiplyByX(cmac_k2.data()); return cmac_k2; } void AesSivBoringSsl::EncryptBlock(const uint8_t in[kBlockSize], uint8_t out[kBlockSize]) const { AES_encrypt(in, out, k1_.get()); } // static void AesSivBoringSsl::MultiplyByX(uint8_t block[kBlockSize]) { // Carry over 0x87 if msb is 1 0x00 if msb is 0. uint8_t carry = 0x87 & -(block[0] >> 7); for (size_t i = 0; i < kBlockSize - 1; ++i) { block[i] = (block[i] << 1) | (block[i + 1] >> 7); } block[kBlockSize - 1] = (block[kBlockSize - 1] << 1) ^ carry; } // static void AesSivBoringSsl::XorBlock(const uint8_t x[kBlockSize], const uint8_t y[kBlockSize], uint8_t res[kBlockSize]) { for (int i = 0; i < kBlockSize; ++i) { res[i] = x[i] ^ y[i]; } } void AesSivBoringSsl::Cmac(absl::Span data, uint8_t mac[kBlockSize]) const { const size_t blocks = std::max(size_t{1}, (data.size() + kBlockSize - 1) / kBlockSize); const size_t last_block_idx = kBlockSize * (blocks - 1); const size_t last_block_size = data.size() - last_block_idx; uint8_t block[kBlockSize]; std::fill(std::begin(block), std::end(block), 0); for (size_t idx = 0; idx < last_block_idx; idx += kBlockSize) { XorBlock(block, &data[idx], block); EncryptBlock(block, block); } for (size_t j = 0; j < last_block_size; j++) { block[j] ^= data[last_block_idx + j]; } if (last_block_size == kBlockSize) { XorBlock(block, cmac_k1_.data(), block); } else { block[last_block_size] ^= 0x80; XorBlock(block, cmac_k2_.data(), block); } EncryptBlock(block, mac); } // Computes Cmac(XorEnd(data, last)) void AesSivBoringSsl::CmacLong(absl::Span data, const uint8_t last[kBlockSize], uint8_t mac[kBlockSize]) const { uint8_t block[kBlockSize]; std::copy_n(data.begin(), kBlockSize, block); size_t idx = kBlockSize; while (kBlockSize <= data.size() - idx) { EncryptBlock(block, block); XorBlock(block, &data[idx], block); idx += kBlockSize; } size_t remaining = data.size() - idx; for (int j = 0; j < kBlockSize - remaining; ++j) { block[remaining + j] ^= last[j]; } if (remaining == 0) { XorBlock(block, cmac_k1_.data(), block); } else { EncryptBlock(block, block); for (int j = 0; j < remaining; ++j) { block[j] ^= last[kBlockSize - remaining + j]; block[j] ^= data[idx + j]; } block[remaining] ^= 0x80; XorBlock(block, cmac_k2_.data(), block); } EncryptBlock(block, mac); } void AesSivBoringSsl::S2v(absl::Span aad, absl::Span msg, uint8_t siv[kBlockSize]) const { // This stuff could be precomputed. uint8_t block[kBlockSize]; std::fill(std::begin(block), std::end(block), 0); Cmac(block, block); MultiplyByX(block); uint8_t aad_mac[kBlockSize]; Cmac(aad, aad_mac); XorBlock(block, aad_mac, block); if (msg.size() >= kBlockSize) { CmacLong(msg, block, siv); } else { MultiplyByX(block); for (size_t i = 0; i < msg.size(); ++i) { block[i] ^= msg[i]; } block[msg.size()] ^= 0x80; Cmac(block, siv); } } util::Status AesSivBoringSsl::AesCtrCrypt(absl::string_view in, const uint8_t siv[kBlockSize], const AES_KEY* key, absl::Span out) const { uint8_t iv[kBlockSize]; std::copy_n(siv, kBlockSize, iv); iv[8] &= 0x7f; iv[12] &= 0x7f; return internal::AesCtr128Crypt(in, iv, key, out); } util::StatusOr AesSivBoringSsl::EncryptDeterministically( absl::string_view plaintext, absl::string_view associated_data) const { uint8_t siv[kBlockSize]; S2v(absl::MakeSpan(reinterpret_cast(associated_data.data()), associated_data.size()), absl::MakeSpan(reinterpret_cast(plaintext.data()), plaintext.size()), siv); size_t ciphertext_size = plaintext.size() + kBlockSize; std::string ciphertext; ResizeStringUninitialized(&ciphertext, ciphertext_size); std::copy(std::begin(siv), std::end(siv), ciphertext.begin()); util::Status res = AesCtrCrypt(plaintext, siv, k2_.get(), absl::MakeSpan(ciphertext).subspan(kBlockSize)); if (!res.ok()) { return res; } return ciphertext; } util::StatusOr AesSivBoringSsl::DecryptDeterministically( absl::string_view ciphertext, absl::string_view associated_data) const { if (ciphertext.size() < kBlockSize) { return util::Status(absl::StatusCode::kInvalidArgument, "ciphertext too short"); } size_t plaintext_size = ciphertext.size() - kBlockSize; std::string plaintext; ResizeStringUninitialized(&plaintext, plaintext_size); const uint8_t* siv = reinterpret_cast(&ciphertext[0]); util::Status res = AesCtrCrypt(ciphertext.substr(kBlockSize), siv, k2_.get(), absl::MakeSpan(plaintext)); if (!res.ok()) { return res; } uint8_t s2v[kBlockSize]; S2v(absl::MakeSpan(reinterpret_cast(associated_data.data()), associated_data.size()), absl::MakeSpan(reinterpret_cast(plaintext.data()), plaintext_size), s2v); if (CRYPTO_memcmp(siv, s2v, kBlockSize) != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "invalid ciphertext"); } return plaintext; } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/aes_siv_boringssl.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_AES_SIV_BORINGSSL_H_ #define TINK_SUBTLE_AES_SIV_BORINGSSL_H_ #include #include #include #include #include #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "openssl/aes.h" #include "tink/deterministic_aead.h" #include "tink/internal/aes_util.h" #include "tink/internal/fips_utils.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // AesSivBoringSsl is an implemenatation of AES-SIV-CMAC as defined in // https://tools.ietf.org/html/rfc5297 . // AesSivBoringSsl implements a deterministic encryption with associated // data (i.e. the DeterministicAead interface). Hence the implementation // below is restricted to one AD component. // // Thread safety: This class is thread safe and thus can be used // concurrently. // // Security: // ========= // Chatterjee, Menezes and Sarkar analyze AES-SIV in Section 5.1 of // https://www.math.uwaterloo.ca/~ajmeneze/publications/tightness.pdf // Their analysis shows that AES-SIV is susceptible to an attack in // a multi-user setting. Concretely, if an attacker knows the encryption // of a message m encrypted and authenticated with k different keys, // then it is possible to find one of the MAC keys in time 2^b / k // where b is the size of the MAC key. A consequence of this attack // is that 128-bit MAC keys give unsufficient security. // Since 192-bit AES keys are not supported by tink for voodoo reasons // and RFC 5297 only supports same size encryption and MAC keys this // implies that keys must be 64 bytes (2*256 bits) long. class AesSivBoringSsl : public DeterministicAead { public: static crypto::tink::util::StatusOr> New( const util::SecretData& key); crypto::tink::util::StatusOr EncryptDeterministically( absl::string_view plaintext, absl::string_view associated_data) const override; crypto::tink::util::StatusOr DecryptDeterministically( absl::string_view ciphertext, absl::string_view associated_data) const override; static bool IsValidKeySizeInBytes(size_t size) { return size == 64; } static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kNotFips; private: static constexpr size_t kBlockSize = internal::AesBlockSize(); AesSivBoringSsl(util::SecretUniquePtr k1, util::SecretUniquePtr k2) : k1_(std::move(k1)), k2_(std::move(k2)), cmac_k1_(ComputeCmacK1()), cmac_k2_(ComputeCmacK2()) {} // Precomputes cmac_k1 util::SecretData ComputeCmacK1() const; // Precomputes cmac_k2 util::SecretData ComputeCmacK2() const; // Encrypts a single block using k2_. // This is used for CMACs. void EncryptBlock(const uint8_t in[kBlockSize], uint8_t out[kBlockSize]) const; // Computes a CMAC of some data. void Cmac(absl::Span data, uint8_t mac[kBlockSize]) const; // Computes CMAC(XorEnd(data, last)), where XorEnd // xors the bytes in last to the last bytes in data. // The size of the data must be at least 16 bytes. void CmacLong(absl::Span data, const uint8_t last[kBlockSize], uint8_t mac[kBlockSize]) const; // Multiplying an element in GF(2^128) by its generator. // This functions is incorrectly named "doubling" in section 2.3 of RFC 5297. static void MultiplyByX(uint8_t block[kBlockSize]); // Xors a block // res = x ^ y static void XorBlock(const uint8_t x[kBlockSize], const uint8_t y[kBlockSize], uint8_t res[kBlockSize]); void S2v(absl::Span aad, absl::Span msg, uint8_t siv[kBlockSize]) const; // Encrypts (or decrypts) `in` using an SIV `siv` and key `key`, and writes // the result to `out`. util::Status AesCtrCrypt(absl::string_view in, const uint8_t siv[kBlockSize], const AES_KEY* key, absl::Span out) const; const util::SecretUniquePtr k1_; const util::SecretUniquePtr k2_; const util::SecretData cmac_k1_; const util::SecretData cmac_k2_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_AES_SIV_BORINGSSL_H_ ================================================ FILE: cc/subtle/aes_siv_boringssl_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/aes_siv_boringssl.h" #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "include/rapidjson/document.h" #include "tink/config/tink_fips.h" #include "tink/subtle/wycheproof_util.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::StatusIs; TEST(AesSivBoringSslTest, testCarryComputation) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } uint8_t value = 0; for (int i = 0; i < 256; i++) { uint8_t carry = static_cast(value) >> 7; if (i < 128) { EXPECT_EQ(carry, 0x00); } else { EXPECT_EQ(carry, 0xff); } value++; } } TEST(AesSivBoringSslTest, testEncryptDecrypt) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::SecretData key = util::SecretDataFromStringView(test::HexDecodeOrDie( "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" "00112233445566778899aabbccddeefff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff")); auto res = AesSivBoringSsl::New(key); EXPECT_TRUE(res.ok()) << res.status(); auto cipher = std::move(res.value()); std::string associated_data = "Associated data"; std::string message = "Some data to encrypt."; auto ct = cipher->EncryptDeterministically(message, associated_data); EXPECT_TRUE(ct.ok()) << ct.status(); auto pt = cipher->DecryptDeterministically(ct.value(), associated_data); EXPECT_TRUE(pt.ok()) << pt.status(); EXPECT_EQ(pt.value(), message); } TEST(AesSivBoringSslTest, testNullPtrStringView) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::SecretData key = util::SecretDataFromStringView(test::HexDecodeOrDie( "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" "00112233445566778899aabbccddeefff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff")); auto res = AesSivBoringSsl::New(key); EXPECT_TRUE(res.ok()) << res.status(); // Checks that a default constructed string_view works. auto cipher = std::move(res.value()); absl::string_view null; auto ct = cipher->EncryptDeterministically(null, null); EXPECT_TRUE(ct.ok()) << ct.status(); auto pt = cipher->DecryptDeterministically(ct.value(), null); EXPECT_TRUE(pt.ok()) << pt.status(); EXPECT_EQ("", pt.value()); // Decryption with ct == null should return an appropriate status. pt = cipher->DecryptDeterministically(null, ""); EXPECT_FALSE(pt.ok()); // Associated data with an empty string view is the same an empty string. std::string message("123456789abcdefghijklmnop"); ct = cipher->EncryptDeterministically(message, null); pt = cipher->DecryptDeterministically(ct.value(), ""); EXPECT_TRUE(pt.ok()) << pt.status(); EXPECT_EQ(message, pt.value()); ct = cipher->EncryptDeterministically(message, ""); pt = cipher->DecryptDeterministically(ct.value(), null); EXPECT_TRUE(pt.ok()) << pt.status(); EXPECT_EQ(message, pt.value()); } // Only 64 byte key sizes are supported. TEST(AesSivBoringSslTest, testEncryptDecryptKeySizes) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::SecretData keymaterial = util::SecretDataFromStringView(test::HexDecodeOrDie( "198371900187498172316311acf81d238ff7619873a61983d619c87b63a1987f" "987131819803719b847126381cd763871638aa71638176328761287361231321" "812731321de508761437195ff231765aa4913219873ac6918639816312130011" "abc900bba11400187984719827431246bbab1231eb4145215ff7141436616beb" "9817298148712fed3aab61000ff123313e")); for (int keysize = 0; keysize < keymaterial.size(); ++keysize) { util::SecretData key(&keymaterial[0], &keymaterial[keysize]); auto cipher = AesSivBoringSsl::New(key); if (keysize == 64) { EXPECT_TRUE(cipher.ok()); } else { EXPECT_FALSE(cipher.ok()) << "Accepted invalid key size:" << keysize; } } } // Checks a range of message sizes. TEST(AesSivBoringSslTest, testEncryptDecryptMessageSize) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::SecretData key = util::SecretDataFromStringView(test::HexDecodeOrDie( "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" "00112233445566778899aabbccddeefff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff")); auto res = AesSivBoringSsl::New(key); EXPECT_TRUE(res.ok()) << res.status(); auto cipher = std::move(res.value()); std::string associated_data = "Associated data"; for (int i = 0; i < 1024; ++i) { std::string message = std::string(i, 'a'); auto ct = cipher->EncryptDeterministically(message, associated_data); EXPECT_TRUE(ct.ok()) << ct.status(); auto pt = cipher->DecryptDeterministically(ct.value(), associated_data); EXPECT_TRUE(pt.ok()) << pt.status(); EXPECT_EQ(pt.value(), message); } for (int i = 1024; i < 100000; i += 5000) { std::string message = std::string(i, 'a'); auto ct = cipher->EncryptDeterministically(message, associated_data); EXPECT_TRUE(ct.ok()) << ct.status(); auto pt = cipher->DecryptDeterministically(ct.value(), associated_data); EXPECT_TRUE(pt.ok()) << pt.status(); EXPECT_EQ(pt.value(), message); } } // Checks a range of associated_data sizes. TEST(AesSivBoringSslTest, testEncryptDecryptAssociatedDataSize) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::SecretData key = util::SecretDataFromStringView(test::HexDecodeOrDie( "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" "00112233445566778899aabbccddeefff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff")); auto res = AesSivBoringSsl::New(key); EXPECT_TRUE(res.ok()) << res.status(); auto cipher = std::move(res.value()); std::string message = "Some plaintext"; for (int i = 0; i < 1028; ++i) { std::string associated_data = std::string(i, 'a'); auto ct = cipher->EncryptDeterministically(message, associated_data); EXPECT_TRUE(ct.ok()) << ct.status(); auto pt = cipher->DecryptDeterministically(ct.value(), associated_data); EXPECT_TRUE(pt.ok()) << pt.status(); EXPECT_EQ(pt.value(), message); } } TEST(AesSivBoringSslTest, testDecryptModification) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::SecretData key = util::SecretDataFromStringView(test::HexDecodeOrDie( "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" "00112233445566778899aabbccddeefff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff")); auto res = AesSivBoringSsl::New(key); EXPECT_TRUE(res.ok()) << res.status(); auto cipher = std::move(res.value()); std::string associated_data = "Associated data"; for (int i = 0; i < 50; ++i) { std::string message = std::string(i, 'a'); auto ct = cipher->EncryptDeterministically(message, associated_data); EXPECT_TRUE(ct.ok()) << ct.status(); std::string ciphertext = ct.value(); for (size_t b = 0; b < ciphertext.size(); ++b) { for (int bit = 0; bit < 8; ++bit) { std::string modified = ciphertext; modified[b] ^= (1 << bit); auto pt = cipher->DecryptDeterministically(modified, associated_data); EXPECT_FALSE(pt.ok()) << "Modified ciphertext decrypted." << " byte:" << b << " bit:" << bit; } } } } // Test with test vectors from project Wycheproof. void WycheproofTest(const rapidjson::Document& root) { for (const rapidjson::Value& test_group : root["testGroups"].GetArray()) { const size_t key_size = test_group["keySize"].GetInt(); if (!AesSivBoringSsl::IsValidKeySizeInBytes(key_size / 8)) { // Currently the key size is restricted to two 256-bit AES keys. continue; } for (const rapidjson::Value& test : test_group["tests"].GetArray()) { std::string comment = test["comment"].GetString(); util::SecretData key = util::SecretDataFromStringView(WycheproofUtil::GetBytes(test["key"])); std::string msg = WycheproofUtil::GetBytes(test["msg"]); std::string ct = WycheproofUtil::GetBytes(test["ct"]); std::string associated_data = WycheproofUtil::GetBytes(test["aad"]); int id = test["tcId"].GetInt(); std::string result = test["result"].GetString(); auto cipher = std::move(AesSivBoringSsl::New(key).value()); // Test encryption. // Encryption should always succeed since msg and aad are valid inputs. std::string encrypted = cipher->EncryptDeterministically(msg, associated_data).value(); std::string encrypted_hex = test::HexEncode(encrypted); std::string ct_hex = test::HexEncode(ct); if (result == "valid" || result == "acceptable") { EXPECT_EQ(ct_hex, encrypted_hex) << "incorrect encryption: " << id << " " << comment; } else { EXPECT_NE(ct_hex, encrypted_hex) << "invalid encryption: " << id << " " << comment; } // Test decryption auto decrypted = cipher->DecryptDeterministically(ct, associated_data); if (decrypted.ok()) { if (result == "invalid") { ADD_FAILURE() << "decrypted invalid ciphertext:" << id; } else { EXPECT_EQ(test::HexEncode(msg), test::HexEncode(decrypted.value())) << "incorrect decryption: " << id << " " << comment; } } else { EXPECT_NE(result, "valid") << "failed to decrypt: " << id << " " << comment; } } } } TEST(AesSivBoringSslTest, TestVectors) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } std::unique_ptr root = WycheproofUtil::ReadTestVectors("aes_siv_cmac_test.json"); WycheproofTest(*root); } TEST(AesEaxBoringSslTest, TestFipsOnly) { if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Only supported in FIPS-only mode"; } util::SecretData key128 = util::SecretDataFromStringView( test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f")); util::SecretData key256 = util::SecretDataFromStringView(test::HexDecodeOrDie( "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f")); EXPECT_THAT(subtle::AesSivBoringSsl::New(key128).status(), StatusIs(absl::StatusCode::kInternal)); EXPECT_THAT(subtle::AesSivBoringSsl::New(key256).status(), StatusIs(absl::StatusCode::kInternal)); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/common_enums.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/common_enums.h" #include #include "absl/strings/str_cat.h" namespace crypto { namespace tink { namespace subtle { std::string EnumToString(EllipticCurveType type) { switch (type) { case EllipticCurveType::NIST_P256: return "NIST_P256"; case EllipticCurveType::NIST_P384: return "NIST_P384"; case EllipticCurveType::NIST_P521: return "NIST_P521"; case EllipticCurveType::CURVE25519: return "CURVE25519"; case EllipticCurveType::UNKNOWN_CURVE: return "UNKNOWN_CURVE"; default: return absl::StrCat("UNKNOWN_CURVE: ", type); } } std::string EnumToString(EcPointFormat format) { switch (format) { case EcPointFormat::UNCOMPRESSED: return "UNCOMPRESSED"; case EcPointFormat::COMPRESSED: return "COMPRESSED"; case EcPointFormat::DO_NOT_USE_CRUNCHY_UNCOMPRESSED: return "DO_NOT_USE_CRUNCHY_UNCOMPRESSED"; case EcPointFormat::UNKNOWN_FORMAT: return "UNKNOWN_FORMAT"; default: return absl::StrCat("UNKNOWN_FORMAT: ", format); } } std::string EnumToString(HashType type) { switch (type) { case HashType::SHA1: return "SHA1"; case HashType::SHA224: return "SHA224"; case HashType::SHA256: return "SHA256"; case HashType::SHA384: return "SHA384"; case HashType::SHA512: return "SHA512"; case HashType::UNKNOWN_HASH: return "UNKNOWN_HASH"; default: return absl::StrCat("UNKNOWN_HASH: ", type); } } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/common_enums.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_COMMON_ENUMS_H_ #define TINK_SUBTLE_COMMON_ENUMS_H_ #include namespace crypto { namespace tink { namespace subtle { // Common enums used by classes in subtle. enum EllipticCurveType { UNKNOWN_CURVE = 0, NIST_P256 = 2, NIST_P384 = 3, NIST_P521 = 4, CURVE25519 = 5, }; enum EcPointFormat { UNKNOWN_FORMAT = 0, UNCOMPRESSED = 1, COMPRESSED = 2, // Like UNCOMPRESSED but without the \x04 prefix. Crunchy uses this format. // DO NOT USE unless you are a Crunchy user moving to Tink. DO_NOT_USE_CRUNCHY_UNCOMPRESSED = 3, }; enum HashType { UNKNOWN_HASH = 0, SHA1 = 1, // SHA1 for digital signature is deprecated but HMAC-SHA1 is fine. SHA384 = 2, SHA256 = 3, SHA512 = 4, SHA224 = 5, }; enum EcdsaSignatureEncoding { UNKNOWN_ENCODING = 0, IEEE_P1363 = 1, DER = 2, }; std::string EnumToString(EllipticCurveType type); std::string EnumToString(EcPointFormat format); std::string EnumToString(HashType type); } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_COMMON_ENUMS_H_ ================================================ FILE: cc/subtle/common_enums_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/common_enums.h" #include "gtest/gtest.h" namespace crypto { namespace tink { namespace subtle { namespace { class CommonEnumsTest : public ::testing::Test {}; TEST_F(CommonEnumsTest, testEllipticCurveTypeToString) { EXPECT_EQ("NIST_P256", EnumToString(EllipticCurveType::NIST_P256)); EXPECT_EQ("NIST_P384", EnumToString(EllipticCurveType::NIST_P384)); EXPECT_EQ("NIST_P521", EnumToString(EllipticCurveType::NIST_P521)); EXPECT_EQ("UNKNOWN_CURVE", EnumToString(EllipticCurveType::UNKNOWN_CURVE)); } TEST_F(CommonEnumsTest, testHashTypeToString) { EXPECT_EQ("SHA1", EnumToString(HashType::SHA1)); EXPECT_EQ("SHA224", EnumToString(HashType::SHA224)); EXPECT_EQ("SHA256", EnumToString(HashType::SHA256)); EXPECT_EQ("SHA384", EnumToString(HashType::SHA384)); EXPECT_EQ("SHA512", EnumToString(HashType::SHA512)); EXPECT_EQ("UNKNOWN_HASH", EnumToString(HashType::UNKNOWN_HASH)); } TEST_F(CommonEnumsTest, testEcPointFormatToString) { EXPECT_EQ("UNCOMPRESSED", EnumToString(EcPointFormat::UNCOMPRESSED)); EXPECT_EQ("COMPRESSED", EnumToString(EcPointFormat::COMPRESSED)); EXPECT_EQ("DO_NOT_USE_CRUNCHY_UNCOMPRESSED", EnumToString(EcPointFormat::DO_NOT_USE_CRUNCHY_UNCOMPRESSED)); EXPECT_EQ("UNKNOWN_FORMAT", EnumToString(EcPointFormat::UNKNOWN_FORMAT)); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/decrypting_random_access_stream.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/decrypting_random_access_stream.h" #include #include #include #include #include #include #include #include "absl/base/thread_annotations.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/synchronization/mutex.h" #include "tink/random_access_stream.h" #include "tink/subtle/stream_segment_decrypter.h" #include "tink/util/buffer.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { using crypto::tink::RandomAccessStream; using crypto::tink::ToStatusF; using crypto::tink::util::Buffer; using crypto::tink::util::Status; using crypto::tink::util::StatusOr; // static StatusOr> DecryptingRandomAccessStream::New( std::unique_ptr segment_decrypter, std::unique_ptr ciphertext_source) { if (segment_decrypter == nullptr) { return Status(absl::StatusCode::kInvalidArgument, "segment_decrypter must be non-null"); } if (ciphertext_source == nullptr) { return Status(absl::StatusCode::kInvalidArgument, "cipertext_source must be non-null"); } std::unique_ptr dec_stream( new DecryptingRandomAccessStream()); absl::MutexLock lock(&(dec_stream->status_mutex_)); dec_stream->segment_decrypter_ = std::move(segment_decrypter); dec_stream->ct_source_ = std::move(ciphertext_source); if (dec_stream->segment_decrypter_->get_ciphertext_offset() < 0) { return util::Status(absl::StatusCode::kInvalidArgument, "The ciphertext offset must be non-negative"); } int first_segment_size = dec_stream->segment_decrypter_->get_plaintext_segment_size() - dec_stream->segment_decrypter_->get_ciphertext_offset() - dec_stream->segment_decrypter_->get_header_size(); if (first_segment_size <= 0) { return Status(absl::StatusCode::kInvalidArgument, "Size of the first segment must be greater than 0."); } dec_stream->status_ = Status(absl::StatusCode::kUnavailable, "The header hasn't been read yet."); return {std::move(dec_stream)}; } util::Status DecryptingRandomAccessStream::PRead(int64_t position, int count, Buffer* dest_buffer) { if (dest_buffer == nullptr) { return Status(absl::StatusCode::kInvalidArgument, "dest_buffer must be non-null"); } auto status = dest_buffer->set_size(0); if (!status.ok()) return status; if (count < 0) { return Status(absl::StatusCode::kInvalidArgument, "count cannot be negative"); } if (count > dest_buffer->allocated_size()) { return Status(absl::StatusCode::kInvalidArgument, "buffer too small"); } if (position < 0) { return Status(absl::StatusCode::kInvalidArgument, "position cannot be negative"); } { // Initialize, if not initialized yet. absl::MutexLock lock(&status_mutex_); InitializeIfNeeded(); if (!status_.ok()) return status_; } if (position > pt_size_) { return Status(absl::StatusCode::kInvalidArgument, "position too large"); } return PReadAndDecrypt(position, count, dest_buffer); } // NOTE: As the initialization below requires availability of size() of the // underlying ciphertext stream, the current implementation does not support // dynamic encrypted streams, whose size is not known or can change over time // (e.g. when one process produces an encrypted file/stream, while concurrently // another process consumes the resulting encrypted stream). // // This is consistent with Java implementation of SeekableDecryptingChannel, // and detects ciphertext truncation attacks. However, a support for dynamic // streams can be added in the future if needed. void DecryptingRandomAccessStream::InitializeIfNeeded() ABSL_EXCLUSIVE_LOCKS_REQUIRED(status_mutex_) { if (status_.code() != absl::StatusCode::kUnavailable) { // Already initialized or stream failed permanently. return; } // Initialize segment decrypter from data in the stream header. header_size_ = segment_decrypter_->get_header_size(); ct_offset_ = segment_decrypter_->get_ciphertext_offset(); auto buf_result = Buffer::New(header_size_); if (!buf_result.ok()) { status_ = buf_result.status(); return; } auto buf = std::move(buf_result.value()); status_ = ct_source_->PRead(ct_offset_, header_size_, buf.get()); if (!status_.ok()) { if (status_.code() == absl::StatusCode::kOutOfRange) { status_ = Status(absl::StatusCode::kInvalidArgument, "could not read header"); } return; } status_ = segment_decrypter_->Init(std::vector( buf->get_mem_block(), buf->get_mem_block() + header_size_)); if (!status_.ok()) return; ct_segment_size_ = segment_decrypter_->get_ciphertext_segment_size(); pt_segment_size_ = segment_decrypter_->get_plaintext_segment_size(); ct_segment_overhead_ = ct_segment_size_ - pt_segment_size_; // Calculate the number of segments and the plaintext size. StatusOr ct_size_result = ct_source_->size(); if (!ct_size_result.ok()) { status_ = ct_size_result.status(); return; } int64_t ct_size = ct_size_result.value(); // ct_segment_size_ is always larger than 1, thus full_segment_count is always // smaller than std::numeric_limits::max(). int64_t full_segment_count = ct_size / ct_segment_size_; int64_t remainder_size = ct_size % ct_segment_size_; if (remainder_size > 0) { // This does not overflow because full_segment_count < // std::numeric_limits::max(). segment_count_ = full_segment_count + 1; } else { segment_count_ = full_segment_count; } // Tink supports up to 2^32 segments. if (segment_count_ - 1 > std::numeric_limits::max()) { status_ = Status(absl::StatusCode::kInvalidArgument, absl::StrCat("too many segments: ", segment_count_)); return; } // This should not overflow because: // * segment_count is int64 and smaller than 2^32, and // * ct_segment_overhead_, ct_offset_ and header_size_ are small int numbers. auto overhead = ct_segment_overhead_ * segment_count_ + ct_offset_ + header_size_; if (overhead > ct_size) { status_ = Status(absl::StatusCode::kInvalidArgument, "ciphertext stream is too short"); return; } pt_size_ = ct_size - overhead; } int DecryptingRandomAccessStream::GetPlaintextOffset(int64_t pt_position) { if (GetSegmentNr(pt_position) == 0) return pt_position; // Computed according to the formula: // (pt_position - (pt_segment_size_ - ct_offset_ - header_size_)) // % pt_segment_size_; // pt_position + ct_offset_ + header_size_ is always smaller than size of // the ciphertext, thus it should never overflow. return (pt_position + ct_offset_ + header_size_) % pt_segment_size_; } int64_t DecryptingRandomAccessStream::GetSegmentNr(int64_t pt_position) { return (pt_position + ct_offset_ + header_size_) / pt_segment_size_; } util::Status DecryptingRandomAccessStream::ReadAndDecryptSegment( int64_t segment_nr, Buffer* ct_buffer, std::vector* pt_segment) { int64_t ct_position = segment_nr * ct_segment_size_; if (ct_position / ct_segment_size_ != segment_nr /* overflow occured! */) { return Status(absl::StatusCode::kOutOfRange, absl::StrCat("segment_nr * ct_segment_size too large: ", segment_nr, ct_segment_size_)); } int segment_size = ct_segment_size_; if (segment_nr == 0) { // The sum of ct_offset_ and header_size is always smaller than // ct_segment_size_, which is an int, therefore the next two statements // should never overflow. ct_position = ct_offset_ + header_size_; segment_size = ct_segment_size_ - ct_position; } bool is_last_segment = (segment_nr == segment_count_ - 1); auto pread_status = ct_source_->PRead(ct_position, segment_size, ct_buffer); if (pread_status.ok() || (is_last_segment && ct_buffer->size() > 0 && pread_status.code() == absl::StatusCode::kOutOfRange)) { // some bytes were read auto dec_status = segment_decrypter_->DecryptSegment( std::vector(ct_buffer->get_mem_block(), ct_buffer->get_mem_block() + ct_buffer->size()), segment_nr, is_last_segment, pt_segment); if (dec_status.ok()) { return is_last_segment ? Status(absl::StatusCode::kOutOfRange, "EOF") : util::OkStatus(); } return dec_status; } return pread_status; } util::Status DecryptingRandomAccessStream::PReadAndDecrypt( int64_t position, int count, Buffer* dest_buffer) { if (position < 0 || count < 0 || dest_buffer == nullptr || count > dest_buffer->allocated_size() || dest_buffer->size() != 0) { return Status(absl::StatusCode::kInternal, "Invalid parameters to PReadAndDecrypt"); } if (position > std::numeric_limits::max() - count) { return Status( absl::StatusCode::kOutOfRange, absl::StrCat( "Invalid parameters to PReadAndDecrypt; position too large: ", position)); } auto pt_size_result = size(); if (pt_size_result.ok()) { auto pt_size = pt_size_result.value(); if (position > pt_size) { return Status(absl::StatusCode::kOutOfRange, "position is larger than stream size"); } } auto ct_buffer_result = Buffer::New(ct_segment_size_); if (!ct_buffer_result.ok()) { return ToStatusF(absl::StatusCode::kInvalidArgument, "Invalid ciphertext segment size %d.", ct_segment_size_); } auto ct_buffer = std::move(ct_buffer_result.value()); std::vector pt_segment; int remaining = count; int read_count = 0; int pt_offset = GetPlaintextOffset(position); while (remaining > 0) { auto segment_nr = GetSegmentNr(position + read_count); auto status = ReadAndDecryptSegment(segment_nr, ct_buffer.get(), &pt_segment); if (status.ok() || status.code() == absl::StatusCode::kOutOfRange) { int pt_count = pt_segment.size() - pt_offset; int to_copy_count = std::min(pt_count, remaining); auto s = dest_buffer->set_size(read_count + to_copy_count); if (!s.ok()) return s; std::memcpy(dest_buffer->get_mem_block() + read_count, pt_segment.data() + pt_offset, to_copy_count); pt_offset = 0; if (status.code() == absl::StatusCode::kOutOfRange && to_copy_count == pt_count) return status; read_count += to_copy_count; remaining = count - dest_buffer->size(); } else { // some other error happened return status; } } return util::OkStatus(); } StatusOr DecryptingRandomAccessStream::size() { { // Initialize, if not initialized yet. absl::MutexLock lock(&status_mutex_); InitializeIfNeeded(); if (!status_.ok()) return status_; } return pt_size_; } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/decrypting_random_access_stream.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_DECRYPTING_RANDOM_ACCESS_STREAM_H_ #define TINK_SUBTLE_DECRYPTING_RANDOM_ACCESS_STREAM_H_ #include #include #include #include "absl/base/thread_annotations.h" #include "absl/synchronization/mutex.h" #include "tink/random_access_stream.h" #include "tink/subtle/stream_segment_decrypter.h" #include "tink/util/buffer.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // A RandomAccessStream that wraps another RandomAccessStream // as a ciphertext source, and provides a "plaintext access" to // the plaintext data contained in the ciphertext: // - PRead()-calls to this class read appropriate segments // of the ciphertext, decrypt them, and return the resulting // plaintext, where the 'position' and 'count' arguments // refer to the plaintext bytes. // - size()-call returns the size of the entire plaintext // if it were to be decrypted. // Instances of this class are thread safe. class DecryptingRandomAccessStream : public crypto::tink::RandomAccessStream { public: // A factory that produces decrypting random access streams. // The returned stream is a wrapper around 'ciphertext_source', // such that any bytes written via the wrapper are AEAD-decrypted // by 'segment_decrypter' using 'associated_data' as associated // authenticated data. static crypto::tink::util::StatusOr< std::unique_ptr> New(std::unique_ptr segment_decrypter, std::unique_ptr ciphertext_source); // ----------------------- // Methods of RandomAccessStream-interface implemented by this class. crypto::tink::util::Status PRead( int64_t position, int count, crypto::tink::util::Buffer* dest_buffer) override; crypto::tink::util::StatusOr size() override; private: DecryptingRandomAccessStream() {} crypto::tink::util::Status PReadAndDecrypt( int64_t position, int count, crypto::tink::util::Buffer* dest_buffer); // Reads the specified ciphertext segment from ct_source_, decrypts it, // and writes the resulting plaintext bytes to pt_segment. // Uses the provided ct_buffer as a buffer for the ciphertext segment. crypto::tink::util::Status ReadAndDecryptSegment( int64_t segment_nr, crypto::tink::util::Buffer* ct_buffer, std::vector* pt_segment); // Returns the segment number that contains the specified 'pt_position'. int64_t GetSegmentNr(int64_t pt_position); // Returns the offset within a segment for the specified 'pt_position'. int GetPlaintextOffset(int64_t pt_position); // Initializes this stream (if not initialized yet or in a permantent error) // by reading the stream header from ct_source_ and using it initialize // segment_decrypter_. void InitializeIfNeeded(); std::unique_ptr segment_decrypter_; std::unique_ptr ct_source_; mutable absl::Mutex status_mutex_; crypto::tink::util::Status status_ ABSL_GUARDED_BY(status_mutex_); int header_size_; int ct_offset_; int ct_segment_size_; int pt_segment_size_; int ct_segment_overhead_; int64_t segment_count_; int64_t pt_size_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_DECRYPTING_RANDOM_ACCESS_STREAM_H_ ================================================ FILE: cc/subtle/decrypting_random_access_stream_test.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/decrypting_random_access_stream.h" #include #include #include #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/internal/test_random_access_stream.h" #include "tink/output_stream.h" #include "tink/random_access_stream.h" #include "tink/streaming_aead.h" #include "tink/subtle/random.h" #include "tink/subtle/test_util.h" #include "tink/util/buffer.h" #include "tink/util/ostream_output_stream.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::internal::TestRandomAccessStream; using crypto::tink::subtle::test::DummyStreamingAead; using crypto::tink::subtle::test::DummyStreamSegmentDecrypter; using crypto::tink::test::IsOk; using crypto::tink::test::StatusIs; using subtle::test::WriteToStream; using testing::HasSubstr; // A dummy RandomAccessStream that fakes its size. class DummyRandomAccessStream : public RandomAccessStream { public: explicit DummyRandomAccessStream(int64_t size, int ct_offset) : size_(size), ct_offset_(ct_offset) {} crypto::tink::util::Status PRead( int64_t position, int count, crypto::tink::util::Buffer* dest_buffer) override { if (position == ct_offset_) { // Someone attempts to read the header, return the same dummy value that // DummyStreamSegmentDecrypter expects. auto status = dest_buffer->set_size(count); if (!status.ok()) return status; std::memset(dest_buffer->get_mem_block(), 'h', count); } return util::OkStatus(); } crypto::tink::util::StatusOr size() override { return size_; } private: int64_t size_; int ct_offset_; }; // Returns a ciphertext resulting from encryption of 'pt' with 'aad' as // associated data, using 'saead'. std::string GetCiphertext(StreamingAead* saead, absl::string_view pt, absl::string_view aad, int ct_offset) { // Prepare ciphertext destination stream. auto ct_stream = absl::make_unique(); // Write ct_offset 'o'-characters for the ciphertext offset. *ct_stream << std::string(ct_offset, 'o'); // A reference to the ciphertext buffer. auto ct_buf = ct_stream->rdbuf(); std::unique_ptr ct_destination( absl::make_unique(std::move(ct_stream))); // Compute the ciphertext. auto enc_stream_result = saead->NewEncryptingStream(std::move(ct_destination), aad); EXPECT_THAT(enc_stream_result, IsOk()); EXPECT_THAT(WriteToStream(enc_stream_result.value().get(), pt), IsOk()); return ct_buf->str(); } // Creates an RandomAccessStream that contains ciphertext resulting // from encryption of 'pt' with 'aad' as associated data, using 'saead'. std::unique_ptr GetCiphertextSource(StreamingAead* saead, absl::string_view pt, absl::string_view aad, int ct_offset) { return std::make_unique( GetCiphertext(saead, pt, aad, ct_offset)); } TEST(DecryptingRandomAccessStreamTest, NegativeCiphertextOffset) { int pt_segment_size = 100; int header_size = 20; int ct_offset = -1; auto seg_decrypter = absl::make_unique( pt_segment_size, header_size, ct_offset); int64_t ciphertext_size = 100; EXPECT_THAT( DecryptingRandomAccessStream::New( std::move(seg_decrypter), absl::make_unique( ciphertext_size, ct_offset)) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("The ciphertext offset must be non-negative"))); } TEST(DecryptingRandomAccessStreamTest, SizeOfFirstSegmentIsSmallerOrEqualToZero) { int header_size = 20; int ct_offset = 0; // Make pt_segment_size equal to ct_offset + header_size. This means size of // the first segment is zero. int pt_segment_size = ct_offset + header_size; auto seg_decrypter = absl::make_unique( pt_segment_size, header_size, ct_offset); int64_t ciphertext_size = 100; EXPECT_THAT( DecryptingRandomAccessStream::New( std::move(seg_decrypter), absl::make_unique( ciphertext_size, ct_offset)) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("greater than 0"))); } TEST(DecryptingRandomAccessStreamTest, TooManySegments) { int header_size = 1; int ct_offset = 0; // Use a valid pt_segment_size which is larger than ct_offset + header_size. int pt_segment_size = ct_offset + header_size + 1; auto seg_decrypter = absl::make_unique( pt_segment_size, header_size, ct_offset); // Use an invalid segment_count larger than 2^32. int64_t segment_count = static_cast(std::numeric_limits::max()) + 2; // Based on this calculation: // segment_count = ciphertext_size / ciphertext_segment_size // -> ciphertext_size = segment_count * ciphertext_segment_size int64_t ciphertext_size = segment_count * seg_decrypter->get_ciphertext_segment_size(); auto dec_stream_result = DecryptingRandomAccessStream::New( std::move(seg_decrypter), absl::make_unique(ciphertext_size, ct_offset)); EXPECT_THAT(dec_stream_result, IsOk()); auto dec_stream = std::move(dec_stream_result.value()); auto result = dec_stream->size(); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_THAT(std::string(result.status().message()), HasSubstr("too many segments")); } TEST(DecryptingRandomAccessStreamTest, BasicDecryption) { for (int pt_size : {1, 5, 20, 42, 100, 1000, 10000}) { std::string plaintext = subtle::Random::GetRandomBytes(pt_size); for (int pt_segment_size : {50, 100, 123}) { for (int header_size : {5, 10, 15}) { for (int ct_offset : {0, 1, 5, 12}) { SCOPED_TRACE(absl::StrCat( "pt_size = ", pt_size, ", pt_segment_size = ", pt_segment_size, ", header_size = ", header_size, ", ct_offset = ", ct_offset)); DummyStreamingAead saead(pt_segment_size, header_size, ct_offset); // Pre-compute the ciphertext. auto ciphertext = GetCiphertextSource(&saead, plaintext, "some aad", ct_offset); // Check the decryption of the pre-computed ciphertext. auto seg_decrypter = absl::make_unique( pt_segment_size, header_size, ct_offset); auto dec_stream_result = DecryptingRandomAccessStream::New( std::move(seg_decrypter), std::move(ciphertext)); EXPECT_THAT(dec_stream_result, IsOk()); auto dec_stream = std::move(dec_stream_result.value()); EXPECT_EQ(pt_size, dec_stream->size().value()); std::string decrypted; auto status = internal::ReadAllFromRandomAccessStream( dec_stream.get(), decrypted); EXPECT_THAT(status, StatusIs(absl::StatusCode::kOutOfRange, HasSubstr("EOF"))); EXPECT_EQ(plaintext, decrypted); } } } } } TEST(DecryptingRandomAccessStreamTest, SelectiveDecryption) { for (int pt_size : {1, 20, 42, 100, 1000, 10000}) { std::string plaintext = subtle::Random::GetRandomBytes(pt_size); for (int pt_segment_size : {50, 100, 200}) { for (int header_size : {5, 10, 20}) { for (int ct_offset : {0, 1, 10}) { SCOPED_TRACE(absl::StrCat( "pt_size = ", pt_size, ", pt_segment_size = ", pt_segment_size, ", header_size = ", header_size, ", ct_offset = ", ct_offset)); DummyStreamingAead saead(pt_segment_size, header_size, ct_offset); // Pre-compute the ciphertext. auto ciphertext = GetCiphertextSource(&saead, plaintext, "some aad", ct_offset); // Check the decryption of the pre-computed ciphertext. auto seg_decrypter = absl::make_unique( pt_segment_size, header_size, ct_offset); auto dec_stream_result = DecryptingRandomAccessStream::New( std::move(seg_decrypter), std::move(ciphertext)); EXPECT_THAT(dec_stream_result, IsOk()); auto dec_stream = std::move(dec_stream_result.value()); for (int position : {0, 1, 2, pt_size / 2, pt_size - 1}) { for (int chunk_size : {1, pt_size / 2, pt_size}) { SCOPED_TRACE(absl::StrCat("position = ", position, ", chunk_size = ", chunk_size)); auto buffer = std::move(util::Buffer::New(std::max(chunk_size, 1)).value()); auto status = dec_stream->PRead(position, chunk_size, buffer.get()); if (position <= pt_size) { EXPECT_TRUE(status.ok() || status.code() == absl::StatusCode::kOutOfRange); } else { EXPECT_THAT(status, StatusIs(absl::StatusCode::kInvalidArgument)); } EXPECT_EQ(std::min(chunk_size, std::max(pt_size - position, 0)), buffer->size()); EXPECT_EQ(0, std::memcmp(plaintext.data() + position, buffer->get_mem_block(), buffer->size())); } } } } } } } TEST(DecryptingRandomAccessStreamTest, TruncatedCiphertextDecryption) { for (int pt_size : {100, 200, 1000}) { std::string plaintext = subtle::Random::GetRandomBytes(pt_size); for (int pt_segment_size : {50, 70}) { for (int header_size : {5, 10, 20}) { for (int ct_offset : {0, 1, 10}) { SCOPED_TRACE(absl::StrCat( "pt_size = ", pt_size, ", pt_segment_size = ", pt_segment_size, ", header_size = ", header_size, ", ct_offset = ", ct_offset)); DummyStreamingAead saead(pt_segment_size, header_size, ct_offset); // Pre-compute the ciphertext. auto ct = GetCiphertext(&saead, plaintext, "some aad", ct_offset); // Check the decryption of a truncated ciphertext. auto seg_decrypter = absl::make_unique( pt_segment_size, header_size, ct_offset); for (int trunc_ct_size : {header_size + ct_offset, static_cast(ct.size()) - 1, static_cast(ct.size()) - pt_segment_size, static_cast(ct.size()) - seg_decrypter->get_ciphertext_segment_size()}) { for (int chunk_size : {pt_size}) { SCOPED_TRACE(absl::StrCat("ct_size = ", ct.size(), ", trunc_ct_size = ", trunc_ct_size, ", chunk_size = ", chunk_size)); auto trunc_ct = std::make_unique( ct.substr(0, trunc_ct_size)); int position = 0; auto per_stream_seg_decrypter = absl::make_unique( pt_segment_size, header_size, ct_offset); auto dec_stream_result = DecryptingRandomAccessStream::New( std::move(per_stream_seg_decrypter), std::move(trunc_ct)); EXPECT_THAT(dec_stream_result, IsOk()); auto dec_stream = std::move(dec_stream_result.value()); auto buffer = std::move(util::Buffer::New(chunk_size).value()); auto status = dec_stream->PRead(position, chunk_size, buffer.get()); EXPECT_THAT(status, StatusIs(absl::StatusCode::kInvalidArgument)); } } } } } } } TEST(DecryptingRandomAccessStreamTest, OutOfRangeDecryption) { for (int pt_size : {0, 20, 42, 100, 1000, 10000}) { std::string plaintext = subtle::Random::GetRandomBytes(pt_size); for (int pt_segment_size : {50, 100, 123}) { for (int header_size : {5, 10, 20}) { SCOPED_TRACE(absl::StrCat("pt_size = ", pt_size, ", pt_segment_size = ", pt_segment_size, ", header_size = ", header_size)); int ct_offset = 0; DummyStreamingAead saead(pt_segment_size, header_size, ct_offset); // Pre-compute the ciphertext. auto ciphertext = GetCiphertextSource(&saead, plaintext, "some aad", ct_offset); // Check the decryption of the pre-computed ciphertext. auto seg_decrypter = absl::make_unique( pt_segment_size, header_size, ct_offset); auto dec_stream_result = DecryptingRandomAccessStream::New( std::move(seg_decrypter), std::move(ciphertext)); EXPECT_THAT(dec_stream_result, IsOk()); auto dec_stream = std::move(dec_stream_result.value()); int chunk_size = 1; auto buffer = std::move(util::Buffer::New(chunk_size).value()); int position = pt_size; // Negative chunk size. auto status = dec_stream->PRead(position, -1, buffer.get()); EXPECT_THAT(status, StatusIs(absl::StatusCode::kInvalidArgument)); // Negative position. status = dec_stream->PRead(-1, chunk_size, buffer.get()); EXPECT_THAT(status, StatusIs(absl::StatusCode::kInvalidArgument)); // Reading at EOF. status = dec_stream->PRead(position, chunk_size, buffer.get()); EXPECT_THAT(status, StatusIs(absl::StatusCode::kOutOfRange)); // Reading past EOF. status = dec_stream->PRead(position + 1 , chunk_size, buffer.get()); EXPECT_THAT(status, StatusIs(absl::StatusCode::kInvalidArgument)); } } } } TEST(DecryptingRandomAccessStreamTest, WrongCiphertext) { int pt_segment_size = 42; int header_size = 10; int ct_offset = 0; for (int ct_size : {0, 10, 100}) { SCOPED_TRACE(absl::StrCat("ct_size = ", ct_size)); // Try decrypting a wrong ciphertext. auto wrong_ct = std::make_unique( subtle::Random::GetRandomBytes(ct_size)); auto seg_decrypter = absl::make_unique( pt_segment_size, header_size, ct_offset); auto dec_stream_result = DecryptingRandomAccessStream::New( std::move(seg_decrypter), std::move(wrong_ct)); EXPECT_THAT(dec_stream_result, IsOk()); auto dec_stream = std::move(dec_stream_result.value()); std::string decrypted; int chunk_size = 1; int position = 0; auto buffer = std::move(util::Buffer::New(chunk_size).value()); auto status = dec_stream->PRead(position, chunk_size, buffer.get()); EXPECT_THAT(status, StatusIs(absl::StatusCode::kInvalidArgument)); } } TEST(DecryptingRandomAccessStreamTest, NullSegmentDecrypter) { auto ct_stream = std::make_unique("some ciphertext contents"); auto dec_stream_result = DecryptingRandomAccessStream::New(nullptr, std::move(ct_stream)); EXPECT_THAT(dec_stream_result.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("segment_decrypter must be non-null"))); } TEST(DecryptingRandomAccessStreamTest, NullCiphertextSource) { int pt_segment_size = 42; int header_size = 10; int ct_offset = 0; auto seg_decrypter = absl::make_unique( pt_segment_size, header_size, ct_offset); auto dec_stream_result = DecryptingRandomAccessStream::New(std::move(seg_decrypter), nullptr); EXPECT_THAT(dec_stream_result.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("cipertext_source must be non-null"))); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/ec_util.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_EC_UTIL_H_ #define TINK_SUBTLE_EC_UTIL_H_ #include #include "absl/base/attributes.h" #include "absl/base/macros.h" #include "tink/internal/ec_util.h" #include "tink/subtle/common_enums.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { class EcUtil { public: // Returns the encoding size of a point on the specified elliptic curve // when the given 'point_format' is used. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline crypto::tink::util::StatusOr EncodingSizeInBytes( EllipticCurveType curve_type, EcPointFormat point_format) { return internal::EcPointEncodingSizeInBytes(curve_type, point_format); } // Returns the size (in bytes) of an element of the field over which // the curve is defined. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline uint32_t FieldSizeInBytes(EllipticCurveType curve_type) { util::StatusOr size = internal::EcFieldSizeInBytes(curve_type); if (!size.ok()) { return 0; } return *size; } }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_EC_UTIL_H_ ================================================ FILE: cc/subtle/ecdsa_sign_boringssl.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/ecdsa_sign_boringssl.h" #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "tink/internal/fips_utils.h" #include "tink/internal/md_util.h" #include "tink/internal/util.h" #include "tink/signature/internal/ecdsa_raw_sign_boringssl.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/subtle_util_boringssl.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { util::StatusOr> EcdsaSignBoringSsl::New( const SubtleUtilBoringSSL::EcKey& ec_key, HashType hash_type, EcdsaSignatureEncoding encoding) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) return status; // Check if the hash type is safe to use. util::Status is_safe = internal::IsHashTypeSafeForSignature(hash_type); if (!is_safe.ok()) { return is_safe; } util::StatusOr hash = internal::EvpHashFromHashType(hash_type); if (!hash.ok()) { return hash.status(); } util::StatusOr> raw_sign = internal::EcdsaRawSignBoringSsl::New(ec_key, encoding); if (!raw_sign.ok()) return raw_sign.status(); return { absl::WrapUnique(new EcdsaSignBoringSsl(*hash, std::move(*raw_sign)))}; } util::StatusOr EcdsaSignBoringSsl::Sign( absl::string_view data) const { // BoringSSL expects a non-null pointer for data, // regardless of whether the size is 0. data = internal::EnsureStringNonNull(data); // Compute the digest. unsigned int digest_size; uint8_t digest[EVP_MAX_MD_SIZE]; if (1 != EVP_Digest(data.data(), data.size(), digest, &digest_size, hash_, nullptr)) { return util::Status(absl::StatusCode::kInternal, "Could not compute digest."); } // Compute the signature. return raw_signer_->Sign( absl::string_view(reinterpret_cast(digest), digest_size)); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/ecdsa_sign_boringssl.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_ECDSA_SIGN_BORINGSSL_H_ #define TINK_SUBTLE_ECDSA_SIGN_BORINGSSL_H_ #include #include #include #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_sign.h" #include "tink/signature/internal/ecdsa_raw_sign_boringssl.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/subtle_util_boringssl.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // ECDSA signing using Boring SSL, generating signatures in DER-encoding. class EcdsaSignBoringSsl : public PublicKeySign { public: static crypto::tink::util::StatusOr> New( const SubtleUtilBoringSSL::EcKey& ec_key, HashType hash_type, EcdsaSignatureEncoding encoding); // Computes the signature for 'data'. crypto::tink::util::StatusOr Sign( absl::string_view data) const override; static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kRequiresBoringCrypto; private: explicit EcdsaSignBoringSsl( const EVP_MD* hash, std::unique_ptr raw_signer) : hash_(hash), raw_signer_(std::move(raw_signer)) {} const EVP_MD* hash_; // Owned by BoringSSL. std::unique_ptr raw_signer_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_ECDSA_SIGN_BORINGSSL_H_ ================================================ FILE: cc/subtle/ecdsa_sign_boringssl_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/ecdsa_sign_boringssl.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/internal/ec_util.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/ecdsa_verify_boringssl.h" #include "tink/subtle/subtle_util_boringssl.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; class EcdsaSignBoringSslTest : public ::testing::Test {}; TEST_F(EcdsaSignBoringSslTest, testBasicSigning) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test is skipped if kOnlyUseFips but BoringCrypto is unavailable."; } subtle::EcdsaSignatureEncoding encodings[2] = { EcdsaSignatureEncoding::DER, EcdsaSignatureEncoding::IEEE_P1363}; for (EcdsaSignatureEncoding encoding : encodings) { auto ec_key = SubtleUtilBoringSSL::GetNewEcKey(EllipticCurveType::NIST_P256).value(); auto signer_result = EcdsaSignBoringSsl::New(ec_key, HashType::SHA256, encoding); ASSERT_TRUE(signer_result.ok()) << signer_result.status(); auto signer = std::move(signer_result.value()); auto verifier_result = EcdsaVerifyBoringSsl::New(ec_key, HashType::SHA256, encoding); ASSERT_TRUE(verifier_result.ok()) << verifier_result.status(); auto verifier = std::move(verifier_result.value()); std::string message = "some data to be signed"; std::string signature = signer->Sign(message).value(); EXPECT_NE(signature, message); auto status = verifier->Verify(signature, message); EXPECT_TRUE(status.ok()) << status; status = verifier->Verify("some bad signature", message); EXPECT_FALSE(status.ok()); status = verifier->Verify(signature, "some bad message"); EXPECT_FALSE(status.ok()); // Message is a null string_view. const absl::string_view empty_message; signature = signer->Sign(empty_message).value(); EXPECT_NE(signature, empty_message); status = verifier->Verify(signature, empty_message); EXPECT_TRUE(status.ok()) << status; } } TEST_F(EcdsaSignBoringSslTest, testEncodingsMismatch) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test is skipped if kOnlyUseFips but BoringCrypto is unavailable."; } subtle::EcdsaSignatureEncoding encodings[2] = { EcdsaSignatureEncoding::DER, EcdsaSignatureEncoding::IEEE_P1363}; for (EcdsaSignatureEncoding encoding : encodings) { auto ec_key = SubtleUtilBoringSSL::GetNewEcKey(EllipticCurveType::NIST_P256).value(); auto signer_result = EcdsaSignBoringSsl::New(ec_key, HashType::SHA256, encoding); ASSERT_TRUE(signer_result.ok()) << signer_result.status(); auto signer = std::move(signer_result.value()); auto verifier_result = EcdsaVerifyBoringSsl::New(ec_key, HashType::SHA256, encoding == EcdsaSignatureEncoding::DER ? EcdsaSignatureEncoding::IEEE_P1363 : EcdsaSignatureEncoding::DER); ASSERT_TRUE(verifier_result.ok()) << verifier_result.status(); auto verifier = std::move(verifier_result.value()); std::string message = "some data to be signed"; std::string signature = signer->Sign(message).value(); EXPECT_NE(signature, message); auto status = verifier->Verify(signature, message); EXPECT_FALSE(status.ok()) << status; } } TEST_F(EcdsaSignBoringSslTest, testSignatureSizesWithIEEE_P1364Encoding) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test is skipped if kOnlyUseFips but BoringCrypto is unavailable."; } EllipticCurveType curves[3] = {EllipticCurveType::NIST_P256, EllipticCurveType::NIST_P384, EllipticCurveType::NIST_P521}; for (EllipticCurveType curve : curves) { auto ec_key = SubtleUtilBoringSSL::GetNewEcKey(curve).value(); auto signer_result = EcdsaSignBoringSsl::New( ec_key, HashType::SHA256, EcdsaSignatureEncoding::IEEE_P1363); ASSERT_TRUE(signer_result.ok()) << signer_result.status(); auto signer = std::move(signer_result.value()); auto verifier_result = EcdsaVerifyBoringSsl::New( ec_key, HashType::SHA256, EcdsaSignatureEncoding::IEEE_P1363); ASSERT_TRUE(verifier_result.ok()) << verifier_result.status(); auto verifier = std::move(verifier_result.value()); std::string message = "some data to be signed"; std::string signature = signer->Sign(message).value(); EXPECT_NE(signature, message); auto status = verifier->Verify(signature, message); EXPECT_TRUE(status.ok()) << status; // Check signature size. util::StatusOr field_size_in_bytes = internal::EcFieldSizeInBytes(curve); ASSERT_THAT(field_size_in_bytes, IsOk()); EXPECT_EQ(signature.size(), 2 * (*field_size_in_bytes)); } } TEST_F(EcdsaSignBoringSslTest, testNewErrors) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test is skipped if kOnlyUseFips but BoringCrypto is unavailable."; } auto ec_key = SubtleUtilBoringSSL::GetNewEcKey(EllipticCurveType::NIST_P256).value(); auto signer_result = EcdsaSignBoringSsl::New(ec_key, HashType::SHA1, EcdsaSignatureEncoding::DER); EXPECT_FALSE(signer_result.ok()) << signer_result.status(); } // TODO(bleichen): add Wycheproof tests. // FIPS-only mode test TEST_F(EcdsaSignBoringSslTest, TestFipsFailWithoutBoringCrypto) { if (!internal::IsFipsModeEnabled() || internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test assumes kOnlyUseFips but BoringCrypto is unavailable."; } auto ec_key = SubtleUtilBoringSSL::GetNewEcKey(EllipticCurveType::NIST_P256).value(); EXPECT_THAT(EcdsaSignBoringSsl::New(ec_key, HashType::SHA256, EcdsaSignatureEncoding::DER) .status(), StatusIs(absl::StatusCode::kInternal)); ec_key = SubtleUtilBoringSSL::GetNewEcKey(EllipticCurveType::NIST_P384).value(); EXPECT_THAT(EcdsaSignBoringSsl::New(ec_key, HashType::SHA256, EcdsaSignatureEncoding::DER) .status(), StatusIs(absl::StatusCode::kInternal)); ec_key = SubtleUtilBoringSSL::GetNewEcKey(EllipticCurveType::NIST_P521).value(); EXPECT_THAT(EcdsaSignBoringSsl::New(ec_key, HashType::SHA256, EcdsaSignatureEncoding::DER) .status(), StatusIs(absl::StatusCode::kInternal)); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/ecdsa_verify_boringssl.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/ecdsa_verify_boringssl.h" #include #include #include #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "openssl/bn.h" #include "openssl/ec.h" #include "openssl/ecdsa.h" #include "openssl/evp.h" #include "tink/internal/ec_util.h" #include "tink/internal/err_util.h" #include "tink/internal/fips_utils.h" #include "tink/internal/md_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/internal/util.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/subtle_util_boringssl.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { util::StatusOr> EcdsaVerifyBoringSsl::New( const SubtleUtilBoringSSL::EcKey& ec_key, HashType hash_type, EcdsaSignatureEncoding encoding) { // Check curve. auto group_result = internal::EcGroupFromCurveType(ec_key.curve); if (!group_result.ok()) return group_result.status(); internal::SslUniquePtr group = std::move(group_result.value()); internal::SslUniquePtr key(EC_KEY_new()); EC_KEY_set_group(key.get(), group.get()); // Check key. auto ec_point_result = internal::GetEcPoint(ec_key.curve, ec_key.pub_x, ec_key.pub_y); if (!ec_point_result.ok()) return ec_point_result.status(); internal::SslUniquePtr pub_key = std::move(ec_point_result.value()); if (!EC_KEY_set_public_key(key.get(), pub_key.get())) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid public key: ", internal::GetSslErrors())); } return New(std::move(key), hash_type, encoding); } util::StatusOr> EcdsaVerifyBoringSsl::New( internal::SslUniquePtr ec_key, HashType hash_type, EcdsaSignatureEncoding encoding) { util::Status status = internal::CheckFipsCompatibility(); if (!status.ok()) { return status; } // Check if the hash type is safe to use. util::Status is_safe = internal::IsHashTypeSafeForSignature(hash_type); if (!is_safe.ok()) { return is_safe; } util::StatusOr hash = internal::EvpHashFromHashType(hash_type); if (!hash.ok()) { return hash.status(); } std::unique_ptr verify( new EcdsaVerifyBoringSsl(std::move(ec_key), *hash, encoding)); return std::move(verify); } util::Status EcdsaVerifyBoringSsl::Verify(absl::string_view signature, absl::string_view data) const { // BoringSSL expects a non-null pointer for data, // regardless of whether the size is 0. data = internal::EnsureStringNonNull(data); // Compute the digest. unsigned int digest_size; uint8_t digest[EVP_MAX_MD_SIZE]; if (1 != EVP_Digest(data.data(), data.size(), digest, &digest_size, hash_, nullptr)) { return util::Status(absl::StatusCode::kInternal, "Could not compute digest."); } std::string derSig(signature); if (encoding_ == subtle::EcdsaSignatureEncoding::IEEE_P1363) { const EC_GROUP* group = EC_KEY_get0_group(key_.get()); auto status_or_der = internal::EcSignatureIeeeToDer(group, signature); if (!status_or_der.ok()) { return status_or_der.status(); } derSig = status_or_der.value(); } // Verify the signature. if (1 != ECDSA_verify(0 /* unused */, digest, digest_size, reinterpret_cast(derSig.data()), derSig.size(), key_.get())) { // signature is invalid return util::Status(absl::StatusCode::kInvalidArgument, "Signature is not valid."); } // signature is valid return util::OkStatus(); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/ecdsa_verify_boringssl.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_ECDSA_VERIFY_BORINGSSL_H_ #define TINK_SUBTLE_ECDSA_VERIFY_BORINGSSL_H_ #include #include #include "absl/strings/string_view.h" #include "openssl/ec.h" #include "openssl/evp.h" #include "tink/internal/fips_utils.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/public_key_verify.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/subtle_util_boringssl.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // ECDSA verification using Boring SSL, accepting signatures in DER-encoding. class EcdsaVerifyBoringSsl : public PublicKeyVerify { public: static crypto::tink::util::StatusOr> New(const SubtleUtilBoringSSL::EcKey& ec_key, HashType hash_type, EcdsaSignatureEncoding encoding); static crypto::tink::util::StatusOr> New(internal::SslUniquePtr ec_key, HashType hash_type, EcdsaSignatureEncoding encoding); // Verifies that 'signature' is a digital signature for 'data'. crypto::tink::util::Status Verify( absl::string_view signature, absl::string_view data) const override; static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kRequiresBoringCrypto; private: EcdsaVerifyBoringSsl(internal::SslUniquePtr key, const EVP_MD* hash, EcdsaSignatureEncoding encoding) : key_(std::move(key)), hash_(hash), encoding_(encoding) {} internal::SslUniquePtr key_; const EVP_MD* hash_; // Owned by BoringSSL. EcdsaSignatureEncoding encoding_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_ECDSA_VERIFY_BORINGSSL_H_ ================================================ FILE: cc/subtle/ecdsa_verify_boringssl_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/ecdsa_verify_boringssl.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "include/rapidjson/document.h" #include "tink/internal/fips_utils.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/ecdsa_sign_boringssl.h" #include "tink/subtle/subtle_util_boringssl.h" #include "tink/subtle/wycheproof_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::StatusIs; class EcdsaVerifyBoringSslTest : public ::testing::Test {}; TEST_F(EcdsaVerifyBoringSslTest, BasicSigning) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test is skipped if kOnlyUseFips but BoringCrypto is unavailable."; } subtle::EcdsaSignatureEncoding encodings[2] = { EcdsaSignatureEncoding::DER, EcdsaSignatureEncoding::IEEE_P1363}; for (EcdsaSignatureEncoding encoding : encodings) { auto ec_key_result = SubtleUtilBoringSSL::GetNewEcKey(EllipticCurveType::NIST_P256); ASSERT_TRUE(ec_key_result.ok()) << ec_key_result.status(); auto ec_key = std::move(ec_key_result.value()); auto signer_result = EcdsaSignBoringSsl::New(ec_key, HashType::SHA256, encoding); ASSERT_TRUE(signer_result.ok()) << signer_result.status(); auto signer = std::move(signer_result.value()); auto verifier_result = EcdsaVerifyBoringSsl::New(ec_key, HashType::SHA256, encoding); ASSERT_TRUE(verifier_result.ok()) << verifier_result.status(); auto verifier = std::move(verifier_result.value()); std::string message = "some data to be signed"; auto sign_result = signer->Sign(message); ASSERT_TRUE(sign_result.ok()) << sign_result.status(); std::string signature = sign_result.value(); EXPECT_NE(signature, message); auto status = verifier->Verify(signature, message); EXPECT_TRUE(status.ok()) << status; status = verifier->Verify(signature + "some trailing data", message); EXPECT_FALSE(status.ok()) << status; status = verifier->Verify("some bad signature", message); EXPECT_FALSE(status.ok()); status = verifier->Verify(signature, "some bad message"); EXPECT_FALSE(status.ok()); } } TEST_F(EcdsaVerifyBoringSslTest, EncodingsMismatch) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test is skipped if kOnlyUseFips but BoringCrypto is unavailable."; } subtle::EcdsaSignatureEncoding encodings[2] = { EcdsaSignatureEncoding::DER, EcdsaSignatureEncoding::IEEE_P1363}; for (EcdsaSignatureEncoding encoding : encodings) { auto ec_key_result = SubtleUtilBoringSSL::GetNewEcKey(EllipticCurveType::NIST_P256); ASSERT_TRUE(ec_key_result.ok()) << ec_key_result.status(); auto ec_key = std::move(ec_key_result.value()); auto signer_result = EcdsaSignBoringSsl::New(ec_key, HashType::SHA256, encoding); ASSERT_TRUE(signer_result.ok()) << signer_result.status(); auto signer = std::move(signer_result.value()); auto verifier_result = EcdsaVerifyBoringSsl::New(ec_key, HashType::SHA256, encoding == EcdsaSignatureEncoding::DER ? EcdsaSignatureEncoding::IEEE_P1363 : EcdsaSignatureEncoding::DER); ASSERT_TRUE(verifier_result.ok()) << verifier_result.status(); auto verifier = std::move(verifier_result.value()); std::string message = "some data to be signed"; auto sign_result = signer->Sign(message); ASSERT_TRUE(sign_result.ok()) << sign_result.status(); std::string signature = sign_result.value(); EXPECT_NE(signature, message); auto status = verifier->Verify(signature, message); EXPECT_FALSE(status.ok()) << status; } } TEST_F(EcdsaVerifyBoringSslTest, NewErrors) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test is skipped if kOnlyUseFips but BoringCrypto is unavailable."; } auto ec_key = SubtleUtilBoringSSL::GetNewEcKey(EllipticCurveType::NIST_P256).value(); auto verifier_result = EcdsaVerifyBoringSsl::New( ec_key, HashType::SHA1, EcdsaSignatureEncoding::IEEE_P1363); EXPECT_FALSE(verifier_result.ok()) << verifier_result.status(); } static util::StatusOr> GetVerifier( const rapidjson::Value& test_group, subtle::EcdsaSignatureEncoding encoding) { SubtleUtilBoringSSL::EcKey key; key.pub_x = WycheproofUtil::GetInteger(test_group["key"]["wx"]); key.pub_y = WycheproofUtil::GetInteger(test_group["key"]["wy"]); key.curve = WycheproofUtil::GetEllipticCurveType(test_group["key"]["curve"]); HashType md = WycheproofUtil::GetHashType(test_group["sha"]); auto result = EcdsaVerifyBoringSsl::New(key, md, encoding); if (!result.ok()) { std::cout << "Failed: " << result.status() << "\n"; } return result; } // Tests signature verification using the test vectors in the specified file. // allow_skipping determines whether it is OK to skip a test because // a verfier cannot be constructed. This option can be used for // if a file contains test vectors that are not necessarily supported // by tink. bool TestSignatures(const std::string& filename, bool allow_skipping, subtle::EcdsaSignatureEncoding encoding) { std::unique_ptr root = WycheproofUtil::ReadTestVectors(filename); std::cout << (*root)["algorithm"].GetString(); std::cout << "generator version " << (*root)["generatorVersion"].GetString(); std::cout << "expected version 0.2.5"; int passed_tests = 0; int failed_tests = 0; for (const rapidjson::Value& test_group : (*root)["testGroups"].GetArray()) { auto verifier_result = GetVerifier(test_group, encoding); if (!verifier_result.ok()) { std::string curve = test_group["key"]["curve"].GetString(); if (allow_skipping) { std::cout << "Could not construct verifier for curve " << curve << verifier_result.status(); } else { ADD_FAILURE() << "Could not construct verifier for curve " << curve << verifier_result.status(); failed_tests += test_group["tests"].GetArray().Size(); } continue; } auto verifier = std::move(verifier_result.value()); for (const rapidjson::Value& test : test_group["tests"].GetArray()) { std::string expected = test["result"].GetString(); std::string msg = WycheproofUtil::GetBytes(test["msg"]); std::string sig = WycheproofUtil::GetBytes(test["sig"]); std::string id = absl::StrCat(test["tcId"].GetInt(), " ", test["comment"].GetString()); auto status = verifier->Verify(sig, msg); if (expected == "valid") { if (status.ok()) { ++passed_tests; } else { ++failed_tests; ADD_FAILURE() << "Valid signature not verified:" << id << " status:" << status; } } else if (expected == "invalid") { if (!status.ok()) { ++passed_tests; } else { ++failed_tests; ADD_FAILURE() << "Invalid signature verified:" << id; } } else if (expected == "acceptable") { // The validity of the signature is undefined. Hence the test passes // but we log the result since we might still want to know if the // library is strict or forgiving. ++passed_tests; std::cout << "Acceptable signature:" << id << ":" << status; } else { ++failed_tests; ADD_FAILURE() << "Invalid field result:" << expected; } } } int num_tests = (*root)["numberOfTests"].GetInt(); std::cout << "total number of tests: " << num_tests; std::cout << "number of tests passed:" << passed_tests; std::cout << "number of tests failed:" << failed_tests; return failed_tests == 0; } TEST_F(EcdsaVerifyBoringSslTest, WycheproofCurveP256) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test is skipped if kOnlyUseFips but BoringCrypto is unavailable."; } ASSERT_TRUE(TestSignatures("ecdsa_secp256r1_sha256_test.json", false, subtle::EcdsaSignatureEncoding::DER)); } TEST_F(EcdsaVerifyBoringSslTest, WycheproofCurveP384) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test is skipped if kOnlyUseFips but BoringCrypto is unavailable."; } ASSERT_TRUE(TestSignatures("ecdsa_secp384r1_sha512_test.json", false, subtle::EcdsaSignatureEncoding::DER)); } TEST_F(EcdsaVerifyBoringSslTest, WycheproofCurveP521) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test is skipped if kOnlyUseFips but BoringCrypto is unavailable."; } ASSERT_TRUE(TestSignatures("ecdsa_secp521r1_sha512_test.json", false, subtle::EcdsaSignatureEncoding::DER)); } TEST_F(EcdsaVerifyBoringSslTest, WycheproofWithIeeeP1363Encoding) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test is skipped if kOnlyUseFips but BoringCrypto is unavailable."; } ASSERT_TRUE(TestSignatures("ecdsa_webcrypto_test.json", true, subtle::EcdsaSignatureEncoding::IEEE_P1363)); } // FIPS-only mode test TEST_F(EcdsaVerifyBoringSslTest, TestFipsFailWithoutBoringCrypto) { if (!internal::IsFipsModeEnabled() || internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test assumes kOnlyUseFips but BoringCrypto is unavailable."; } auto ec_key = SubtleUtilBoringSSL::GetNewEcKey(EllipticCurveType::NIST_P256).value(); EXPECT_THAT(EcdsaVerifyBoringSsl::New(ec_key, HashType::SHA256, EcdsaSignatureEncoding::DER) .status(), StatusIs(absl::StatusCode::kInternal)); ec_key = SubtleUtilBoringSSL::GetNewEcKey(EllipticCurveType::NIST_P384).value(); EXPECT_THAT(EcdsaVerifyBoringSsl::New(ec_key, HashType::SHA256, EcdsaSignatureEncoding::DER) .status(), StatusIs(absl::StatusCode::kInternal)); ec_key = SubtleUtilBoringSSL::GetNewEcKey(EllipticCurveType::NIST_P521).value(); EXPECT_THAT(EcdsaVerifyBoringSsl::New(ec_key, HashType::SHA256, EcdsaSignatureEncoding::DER) .status(), StatusIs(absl::StatusCode::kInternal)); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/ecies_hkdf_recipient_kem_boringssl.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/ecies_hkdf_recipient_kem_boringssl.h" #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "openssl/bn.h" #include "openssl/ec.h" #include "openssl/evp.h" #include "tink/internal/ec_util.h" #include "tink/internal/fips_utils.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/hkdf.h" #include "tink/util/errors.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // static util::StatusOr> EciesHkdfRecipientKemBoringSsl::New(EllipticCurveType curve, util::SecretData priv_key) { switch (curve) { case EllipticCurveType::NIST_P256: case EllipticCurveType::NIST_P384: case EllipticCurveType::NIST_P521: return EciesHkdfNistPCurveRecipientKemBoringSsl::New(curve, std::move(priv_key)); case EllipticCurveType::CURVE25519: return EciesHkdfX25519RecipientKemBoringSsl::New(curve, std::move(priv_key)); default: return util::Status(absl::StatusCode::kUnimplemented, "Unsupported elliptic curve"); } } // static util::StatusOr> EciesHkdfNistPCurveRecipientKemBoringSsl::New(EllipticCurveType curve, util::SecretData priv_key) { auto status = internal::CheckFipsCompatibility< EciesHkdfNistPCurveRecipientKemBoringSsl>(); if (!status.ok()) return status; if (priv_key.empty()) { return util::Status(absl::StatusCode::kInvalidArgument, "empty priv_key"); } auto status_or_ec_group = internal::EcGroupFromCurveType(curve); if (!status_or_ec_group.ok()) return status_or_ec_group.status(); // TODO(przydatek): consider refactoring internal/ec_util, // so that the saved group can be used for KEM operations. return {absl::WrapUnique(new EciesHkdfNistPCurveRecipientKemBoringSsl( curve, std::move(priv_key), std::move(status_or_ec_group.value())))}; } EciesHkdfNistPCurveRecipientKemBoringSsl:: EciesHkdfNistPCurveRecipientKemBoringSsl( EllipticCurveType curve, util::SecretData priv_key_value, internal::SslUniquePtr ec_group) : curve_(curve), priv_key_value_(std::move(priv_key_value)), ec_group_(std::move(ec_group)) {} util::StatusOr EciesHkdfNistPCurveRecipientKemBoringSsl::GenerateKey( absl::string_view kem_bytes, HashType hash, absl::string_view hkdf_salt, absl::string_view hkdf_info, uint32_t key_size_in_bytes, EcPointFormat point_format) const { auto status_or_ec_point = internal::EcPointDecode(curve_, point_format, kem_bytes); if (!status_or_ec_point.ok()) { return ToStatusF(absl::StatusCode::kInvalidArgument, "Invalid KEM bytes: %s", status_or_ec_point.status().message()); } internal::SslUniquePtr pub_key = std::move(status_or_ec_point.value()); internal::SslUniquePtr priv_key( BN_bin2bn(priv_key_value_.data(), priv_key_value_.size(), nullptr)); auto shared_secret_or = internal::ComputeEcdhSharedSecret(curve_, priv_key.get(), pub_key.get()); if (!shared_secret_or.ok()) { return shared_secret_or.status(); } util::SecretData shared_secret = shared_secret_or.value(); return Hkdf::ComputeEciesHkdfSymmetricKey( hash, kem_bytes, shared_secret, hkdf_salt, hkdf_info, key_size_in_bytes); } EciesHkdfX25519RecipientKemBoringSsl::EciesHkdfX25519RecipientKemBoringSsl( internal::SslUniquePtr private_key) : private_key_(std::move(private_key)) {} // static util::StatusOr> EciesHkdfX25519RecipientKemBoringSsl::New(EllipticCurveType curve, util::SecretData priv_key) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) return status; if (curve != CURVE25519) { return util::Status(absl::StatusCode::kInvalidArgument, "curve is not CURVE25519"); } if (priv_key.size() != internal::X25519KeyPubKeySize()) { return util::Status(absl::StatusCode::kInvalidArgument, "pubx has unexpected length"); } internal::SslUniquePtr ssl_priv_key(EVP_PKEY_new_raw_private_key( /*type=*/EVP_PKEY_X25519, /*unused=*/nullptr, /*in=*/priv_key.data(), /*len=*/internal::Ed25519KeyPrivKeySize())); if (ssl_priv_key == nullptr) { return util::Status(absl::StatusCode::kInternal, "EVP_PKEY_new_raw_private_key failed"); } return {absl::WrapUnique( new EciesHkdfX25519RecipientKemBoringSsl(std::move(ssl_priv_key)))}; } crypto::tink::util::StatusOr EciesHkdfX25519RecipientKemBoringSsl::GenerateKey( absl::string_view kem_bytes, HashType hash, absl::string_view hkdf_salt, absl::string_view hkdf_info, uint32_t key_size_in_bytes, EcPointFormat point_format) const { if (point_format != EcPointFormat::COMPRESSED) { return util::Status( absl::StatusCode::kInvalidArgument, "X25519 only supports compressed elliptic curve points"); } if (kem_bytes.size() != internal::X25519KeyPubKeySize()) { return util::Status(absl::StatusCode::kInvalidArgument, "kem_bytes has unexpected size"); } internal::SslUniquePtr peer_key(EVP_PKEY_new_raw_public_key( /*type=*/EVP_PKEY_X25519, /*unused=*/nullptr, /*in=*/reinterpret_cast(kem_bytes.data()), /*len=*/internal::Ed25519KeyPubKeySize())); if (peer_key == nullptr) { return util::Status(absl::StatusCode::kInternal, "EVP_PKEY_new_raw_public_key failed"); } util::StatusOr shared_secret = internal::ComputeX25519SharedSecret(private_key_.get(), peer_key.get()); if (!shared_secret.ok()) { return shared_secret.status(); } return Hkdf::ComputeEciesHkdfSymmetricKey( hash, kem_bytes, *shared_secret, hkdf_salt, hkdf_info, key_size_in_bytes); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/ecies_hkdf_recipient_kem_boringssl.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_ECIES_HKDF_RECIPIENT_KEM_BORINGSSL_H_ #define TINK_SUBTLE_ECIES_HKDF_RECIPIENT_KEM_BORINGSSL_H_ #include #include #include "absl/strings/string_view.h" #include "openssl/ec.h" #include "openssl/evp.h" #include "tink/internal/fips_utils.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/subtle/common_enums.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // HKDF-based KEM (key encapsulation mechanism) for ECIES recipient, // using Boring SSL for the underlying cryptographic operations. class EciesHkdfRecipientKemBoringSsl { public: // Constructs a recipient KEM for the specified curve and recipient's // private key, which must be a big-endian byte array. static crypto::tink::util::StatusOr< std::unique_ptr> New(EllipticCurveType curve, util::SecretData priv_key); // Computes the ecdh's shared secret from our private key and peer's encoded // public key, then uses hkdf to derive the symmetric key from the shared // secret, hkdf info and hkdf salt. virtual crypto::tink::util::StatusOr GenerateKey( absl::string_view kem_bytes, HashType hash, absl::string_view hkdf_salt, absl::string_view hkdf_info, uint32_t key_size_in_bytes, EcPointFormat point_format) const = 0; virtual ~EciesHkdfRecipientKemBoringSsl() = default; }; // Implementation of EciesHkdfRecipientKemBoringSsl for the NIST P-curves. class EciesHkdfNistPCurveRecipientKemBoringSsl : public EciesHkdfRecipientKemBoringSsl { public: // Constructs a recipient KEM for the specified curve and recipient's // private key, which must be a big-endian byte array. static crypto::tink::util::StatusOr< std::unique_ptr> New(EllipticCurveType curve, util::SecretData priv_key); // Computes the ecdh's shared secret from our private key and peer's encoded // public key, then uses hkdf to derive the symmetric key from the shared // secret, hkdf info and hkdf salt. crypto::tink::util::StatusOr GenerateKey( absl::string_view kem_bytes, HashType hash, absl::string_view hkdf_salt, absl::string_view hkdf_info, uint32_t key_size_in_bytes, EcPointFormat point_format) const override; static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kNotFips; private: EciesHkdfNistPCurveRecipientKemBoringSsl( EllipticCurveType curve, util::SecretData priv_key_value, internal::SslUniquePtr ec_group); EllipticCurveType curve_; util::SecretData priv_key_value_; internal::SslUniquePtr ec_group_; }; // Implementation of EciesHkdfRecipientKemBoringSsl for curve25519. class EciesHkdfX25519RecipientKemBoringSsl : public EciesHkdfRecipientKemBoringSsl { public: // Constructs a recipient KEM for the specified curve and recipient's // private key, which must be a big-endian byte array. static crypto::tink::util::StatusOr< std::unique_ptr> New(EllipticCurveType curve, util::SecretData priv_key); // Computes the ecdh's shared secret from our private key and peer's encoded // public key, then uses hkdf to derive the symmetric key from the shared // secret, hkdf info and hkdf salt. crypto::tink::util::StatusOr GenerateKey( absl::string_view kem_bytes, HashType hash, absl::string_view hkdf_salt, absl::string_view hkdf_info, uint32_t key_size_in_bytes, EcPointFormat point_format) const override; static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kNotFips; private: explicit EciesHkdfX25519RecipientKemBoringSsl( internal::SslUniquePtr private_key); const internal::SslUniquePtr private_key_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_ECIES_HKDF_RECIPIENT_KEM_BORINGSSL_H_ ================================================ FILE: cc/subtle/ecies_hkdf_recipient_kem_boringssl_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/ecies_hkdf_recipient_kem_boringssl.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "tink/config/tink_fips.h" #include "tink/subtle/common_enums.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::StatusIs; class EciesHkdfRecipientKemBoringSslTest : public ::testing::Test {}; struct TestVector { EllipticCurveType curve; HashType hash; EcPointFormat point_format; std::string pub_encoded_hex; std::string priv_hex; std::string salt_hex; std::string info_hex; int out_len; std::string out_key_hex; }; static const char kSaltHex[] = "0b0b0b0b"; static const char kInfoHex[] = "0b0b0b0b0b0b0b0b"; static const char kNistP256PublicValueHex[] = "04700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287db71e509" "e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac"; static const char kNistP256PrivateKeyHex[] = "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534"; static const char kNistP256SharedKeyHex[] = "0f19c0f322fc0a4b73b32bac6a66baa274de261db38a57f11ee4896ede24dbba"; static const char kX25519PublicValueHex[] = "bef00c1a15e0601678ef4899a8506f751cd0c1f4d210a2852ac9d42151d0e160"; static const char kX25519PrivateKeyHex[] = "df4320cecfd87a5a928355241c9d0e491be499cedf7b2b70687193124039eb92"; static const char kX25519SharedKeyHex[] = "4c77c4d086e2d267052bad906f8c00092f8ea944fc1dc69eb2fe8bb29df400cc"; static const std::vector test_vector( {{EllipticCurveType::NIST_P256, HashType::SHA256, EcPointFormat::UNCOMPRESSED, kNistP256PublicValueHex, kNistP256PrivateKeyHex, kSaltHex, kInfoHex, 32, kNistP256SharedKeyHex}, {EllipticCurveType::CURVE25519, HashType::SHA256, EcPointFormat::COMPRESSED, kX25519PublicValueHex, kX25519PrivateKeyHex, kSaltHex, kInfoHex, 32, kX25519SharedKeyHex}}); TEST_F(EciesHkdfRecipientKemBoringSslTest, TestBasic) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } for (const TestVector& test : test_vector) { auto ecies_kem_or = EciesHkdfRecipientKemBoringSsl::New( test.curve, util::SecretDataFromStringView(absl::HexStringToBytes(test.priv_hex))); ASSERT_TRUE(ecies_kem_or.ok()); auto ecies_kem = std::move(ecies_kem_or).value(); auto kem_key_or = ecies_kem->GenerateKey( absl::HexStringToBytes(test.pub_encoded_hex), test.hash, absl::HexStringToBytes(test.salt_hex), absl::HexStringToBytes(test.info_hex), test.out_len, test.point_format); ASSERT_TRUE(kem_key_or.ok()); EXPECT_EQ(test.out_key_hex, absl::BytesToHexString( util::SecretDataAsStringView(kem_key_or.value()))); } } TEST_F(EciesHkdfRecipientKemBoringSslTest, TestNewUnimplementedCurve) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } auto status_or_recipient_kem = EciesHkdfRecipientKemBoringSsl::New(EllipticCurveType::UNKNOWN_CURVE, {}); EXPECT_EQ(status_or_recipient_kem.status().code(), absl::StatusCode::kUnimplemented); } class EciesHkdfNistPCurveRecipientKemBoringSslTest : public ::testing::Test {}; TEST_F(EciesHkdfNistPCurveRecipientKemBoringSslTest, TestNew) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } auto status_or_recipient_kem = EciesHkdfNistPCurveRecipientKemBoringSsl::New( EllipticCurveType::NIST_P256, util::SecretDataFromStringView( absl::HexStringToBytes(kNistP256PrivateKeyHex))); ASSERT_TRUE(status_or_recipient_kem.ok()); } TEST_F(EciesHkdfNistPCurveRecipientKemBoringSslTest, TestNewInvalidCurve) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } auto status_or_recipient_kem = EciesHkdfNistPCurveRecipientKemBoringSsl::New( EllipticCurveType::CURVE25519, util::SecretDataFromStringView( absl::HexStringToBytes(kNistP256PrivateKeyHex))); EXPECT_EQ(status_or_recipient_kem.status().code(), absl::StatusCode::kUnimplemented); } TEST_F(EciesHkdfNistPCurveRecipientKemBoringSslTest, TestNewEmptyPrivateKey) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } auto status_or_recipient_kem = EciesHkdfNistPCurveRecipientKemBoringSsl::New( EllipticCurveType::CURVE25519, {}); EXPECT_EQ(status_or_recipient_kem.status().code(), absl::StatusCode::kInvalidArgument); } TEST_F(EciesHkdfNistPCurveRecipientKemBoringSslTest, TestGenerateKey) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } auto status_or_recipient_kem = EciesHkdfNistPCurveRecipientKemBoringSsl::New( EllipticCurveType::NIST_P256, util::SecretDataFromStringView( absl::HexStringToBytes(kNistP256PrivateKeyHex))); ASSERT_TRUE(status_or_recipient_kem.ok()); auto recipient_kem = std::move(status_or_recipient_kem.value()); auto status_or_shared_key = recipient_kem->GenerateKey( absl::HexStringToBytes(kNistP256PublicValueHex), HashType::SHA256, absl::HexStringToBytes(kSaltHex), absl::HexStringToBytes(kInfoHex), 32, EcPointFormat::UNCOMPRESSED); ASSERT_TRUE(status_or_shared_key.ok()); EXPECT_EQ(absl::BytesToHexString( util::SecretDataAsStringView(status_or_shared_key.value())), kNistP256SharedKeyHex); } class EciesHkdfX25519RecipientKemBoringSslTest : public ::testing::Test {}; TEST_F(EciesHkdfX25519RecipientKemBoringSslTest, TestNew) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } auto status_or_recipient_kem = EciesHkdfX25519RecipientKemBoringSsl::New( EllipticCurveType::CURVE25519, util::SecretDataFromStringView( absl::HexStringToBytes(kX25519PrivateKeyHex))); ASSERT_TRUE(status_or_recipient_kem.ok()); } TEST_F(EciesHkdfX25519RecipientKemBoringSslTest, TestNewInvalidCurve) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } auto status_or_recipient_kem = EciesHkdfX25519RecipientKemBoringSsl::New( EllipticCurveType::NIST_P256, util::SecretDataFromStringView( absl::HexStringToBytes(kX25519PrivateKeyHex))); EXPECT_EQ(status_or_recipient_kem.status().code(), absl::StatusCode::kInvalidArgument); } TEST_F(EciesHkdfX25519RecipientKemBoringSslTest, TestNewShortKey) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::SecretData private_key = util::SecretDataFromStringView( absl::HexStringToBytes(kX25519PrivateKeyHex)); private_key.resize(private_key.size() / 2); auto status_or_recipient_kem = EciesHkdfX25519RecipientKemBoringSsl::New( EllipticCurveType::CURVE25519, private_key); EXPECT_EQ(status_or_recipient_kem.status().code(), absl::StatusCode::kInvalidArgument); } // Tests for FIPS only mode TEST_F(EciesHkdfNistPCurveRecipientKemBoringSslTest, TestFipsOnly) { if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Only supported in FIPS-only mode"; } util::SecretData private_key = util::SecretDataFromStringView( absl::HexStringToBytes(kNistP256PrivateKeyHex)); EXPECT_THAT(EciesHkdfRecipientKemBoringSsl::New(EllipticCurveType::NIST_P256, private_key) .status(), StatusIs(absl::StatusCode::kInternal)); } TEST_F(EciesHkdfX25519RecipientKemBoringSslTest, TestFipsOnly) { if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Only supported in FIPS-only mode"; } util::SecretData private_key = util::SecretDataFromStringView( absl::HexStringToBytes(kX25519PrivateKeyHex)); EXPECT_THAT(EciesHkdfX25519RecipientKemBoringSsl::New( EllipticCurveType::CURVE25519, private_key) .status(), StatusIs(absl::StatusCode::kInternal)); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/ecies_hkdf_sender_kem_boringssl.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/ecies_hkdf_sender_kem_boringssl.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "openssl/bn.h" #include "openssl/evp.h" #include "tink/internal/ec_util.h" #include "tink/internal/fips_utils.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/hkdf.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // static util::StatusOr> EciesHkdfSenderKemBoringSsl::New(subtle::EllipticCurveType curve, const std::string& pubx, const std::string& puby) { switch (curve) { case EllipticCurveType::NIST_P256: case EllipticCurveType::NIST_P384: case EllipticCurveType::NIST_P521: return EciesHkdfNistPCurveSendKemBoringSsl::New(curve, pubx, puby); case EllipticCurveType::CURVE25519: return EciesHkdfX25519SendKemBoringSsl::New(curve, pubx, puby); default: return util::Status(absl::StatusCode::kUnimplemented, "Unsupported elliptic curve"); } } EciesHkdfNistPCurveSendKemBoringSsl::EciesHkdfNistPCurveSendKemBoringSsl( subtle::EllipticCurveType curve, const std::string& pubx, const std::string& puby, internal::SslUniquePtr peer_pub_key) : curve_(curve), pubx_(pubx), puby_(puby), peer_pub_key_(std::move(peer_pub_key)) {} // static util::StatusOr> EciesHkdfNistPCurveSendKemBoringSsl::New(subtle::EllipticCurveType curve, const std::string& pubx, const std::string& puby) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) return status; auto status_or_ec_point = internal::GetEcPoint(curve, pubx, puby); if (!status_or_ec_point.ok()) return status_or_ec_point.status(); return absl::WrapUnique(new EciesHkdfNistPCurveSendKemBoringSsl( curve, pubx, puby, std::move(status_or_ec_point.value()))); } util::StatusOr> EciesHkdfNistPCurveSendKemBoringSsl::GenerateKey( subtle::HashType hash, absl::string_view hkdf_salt, absl::string_view hkdf_info, uint32_t key_size_in_bytes, subtle::EcPointFormat point_format) const { if (peer_pub_key_.get() == nullptr) { return util::Status(absl::StatusCode::kInternal, "peer_pub_key_ wasn't initialized"); } auto status_or_ec_group = internal::EcGroupFromCurveType(curve_); if (!status_or_ec_group.ok()) { return status_or_ec_group.status(); } internal::SslUniquePtr group = std::move(status_or_ec_group.value()); internal::SslUniquePtr ephemeral_key(EC_KEY_new()); if (1 != EC_KEY_set_group(ephemeral_key.get(), group.get())) { return util::Status(absl::StatusCode::kInternal, "EC_KEY_set_group failed"); } if (1 != EC_KEY_generate_key(ephemeral_key.get())) { return util::Status(absl::StatusCode::kInternal, "EC_KEY_generate_key failed"); } const BIGNUM* ephemeral_priv = EC_KEY_get0_private_key(ephemeral_key.get()); const EC_POINT* ephemeral_pub = EC_KEY_get0_public_key(ephemeral_key.get()); auto status_or_string_kem = internal::EcPointEncode(curve_, point_format, ephemeral_pub); if (!status_or_string_kem.ok()) { return status_or_string_kem.status(); } std::string kem_bytes = status_or_string_kem.value(); auto status_or_string_shared_secret = internal::ComputeEcdhSharedSecret( curve_, ephemeral_priv, peer_pub_key_.get()); if (!status_or_string_shared_secret.ok()) { return status_or_string_shared_secret.status(); } util::SecretData shared_secret = status_or_string_shared_secret.value(); auto symmetric_key_or = Hkdf::ComputeEciesHkdfSymmetricKey( hash, kem_bytes, shared_secret, hkdf_salt, hkdf_info, key_size_in_bytes); if (!symmetric_key_or.ok()) { return symmetric_key_or.status(); } util::SecretData symmetric_key = symmetric_key_or.value(); return absl::make_unique(std::move(kem_bytes), std::move(symmetric_key)); } EciesHkdfX25519SendKemBoringSsl::EciesHkdfX25519SendKemBoringSsl( internal::SslUniquePtr peer_public_key) : peer_public_key_(std::move(peer_public_key)) {} // static util::StatusOr> EciesHkdfX25519SendKemBoringSsl::New(subtle::EllipticCurveType curve, const std::string& pubx, const std::string& puby) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) return status; if (curve != CURVE25519) { return util::Status(absl::StatusCode::kInvalidArgument, "curve is not CURVE25519"); } if (pubx.size() != internal::X25519KeyPubKeySize()) { return util::Status(absl::StatusCode::kInvalidArgument, "pubx has unexpected length"); } if (!puby.empty()) { return util::Status(absl::StatusCode::kInvalidArgument, "puby is not empty"); } internal::SslUniquePtr peer_public_key(EVP_PKEY_new_raw_public_key( /*type=*/EVP_PKEY_X25519, /*unused=*/nullptr, /*in=*/reinterpret_cast(pubx.data()), /*len=*/internal::Ed25519KeyPubKeySize())); if (peer_public_key == nullptr) { return util::Status(absl::StatusCode::kInternal, "EVP_PKEY_new_raw_public_key failed"); } return absl::WrapUnique( new EciesHkdfX25519SendKemBoringSsl(std::move(peer_public_key))); } util::StatusOr> EciesHkdfX25519SendKemBoringSsl::GenerateKey( subtle::HashType hash, absl::string_view hkdf_salt, absl::string_view hkdf_info, uint32_t key_size_in_bytes, subtle::EcPointFormat point_format) const { if (point_format != EcPointFormat::COMPRESSED) { return util::Status( absl::StatusCode::kInvalidArgument, "X25519 only supports compressed elliptic curve points"); } // Generate an ephemeral key pair; the public key is the KEM key to use. util::StatusOr> ephemeral_key = internal::NewX25519Key(); internal::SslUniquePtr ssl_priv_key(EVP_PKEY_new_raw_private_key( /*type=*/EVP_PKEY_X25519, /*unused=*/nullptr, /*in=*/(*ephemeral_key)->private_key, /*len=*/internal::Ed25519KeyPrivKeySize())); if (ssl_priv_key == nullptr) { return util::Status(absl::StatusCode::kInternal, "EVP_PKEY_new_raw_private_key failed"); } util::StatusOr shared_secret = internal::ComputeX25519SharedSecret(ssl_priv_key.get(), peer_public_key_.get()); auto public_key = absl::string_view( reinterpret_cast((*ephemeral_key)->public_value), internal::X25519KeyPubKeySize()); util::StatusOr symmetric_key = Hkdf::ComputeEciesHkdfSymmetricKey(hash, public_key, *shared_secret, hkdf_salt, hkdf_info, key_size_in_bytes); if (!symmetric_key.ok()) { return symmetric_key.status(); } return std::make_unique(std::string(public_key), *symmetric_key); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/ecies_hkdf_sender_kem_boringssl.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_ECIES_HKDF_SENDER_KEM_BORINGSSL_H_ #define TINK_SUBTLE_ECIES_HKDF_SENDER_KEM_BORINGSSL_H_ #include #include #include #include #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "tink/internal/fips_utils.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/subtle/common_enums.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // HKDF-based KEM (key encapsulation mechanism) for ECIES sender, // using Boring SSL for the underlying cryptographic operations. class EciesHkdfSenderKemBoringSsl { public: // Container for data of keys generated by the KEM. class KemKey { public: KemKey() = default; explicit KemKey(std::string kem_bytes, util::SecretData symmetric_key) : kem_bytes_(std::move(kem_bytes)), symmetric_key_(std::move(symmetric_key)) {} const std::string& get_kem_bytes() const { return kem_bytes_; } const util::SecretData& get_symmetric_key() const { return symmetric_key_; } private: std::string kem_bytes_; util::SecretData symmetric_key_; }; // Constructs a sender KEM for the specified curve and recipient's // public key point. The public key's coordinates are big-endian byte array. static crypto::tink::util::StatusOr< std::unique_ptr> New(EllipticCurveType curve, const std::string& pubx, const std::string& puby); // Generates ephemeral key pairs, computes ECDH's shared secret based on // generated ephemeral key and recipient's public key, then uses HKDF // to derive the symmetric key from the shared secret, 'hkdf_info' and // hkdf_salt. virtual crypto::tink::util::StatusOr> GenerateKey(HashType hash, absl::string_view hkdf_salt, absl::string_view hkdf_info, uint32_t key_size_in_bytes, EcPointFormat point_format) const = 0; virtual ~EciesHkdfSenderKemBoringSsl() = default; }; // Implementation of EciesHkdfSenderKemBoringSsl for the NIST P-curves. class EciesHkdfNistPCurveSendKemBoringSsl : public EciesHkdfSenderKemBoringSsl { public: // Constructs a sender KEM for the specified curve and recipient's // public key point. The public key's coordinates are big-endian byte array. static crypto::tink::util::StatusOr< std::unique_ptr> New(EllipticCurveType curve, const std::string& pubx, const std::string& puby); // Generates ephemeral key pairs, computes ECDH's shared secret based on // generated ephemeral key and recipient's public key, then uses HKDF // to derive the symmetric key from the shared secret, 'hkdf_info' and // hkdf_salt. crypto::tink::util::StatusOr> GenerateKey( HashType hash, absl::string_view hkdf_salt, absl::string_view hkdf_info, uint32_t key_size_in_bytes, EcPointFormat point_format) const override; static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kNotFips; private: EciesHkdfNistPCurveSendKemBoringSsl( EllipticCurveType curve, const std::string& pubx, const std::string& puby, internal::SslUniquePtr peer_pub_key); EllipticCurveType curve_; std::string pubx_; std::string puby_; internal::SslUniquePtr peer_pub_key_; }; // Implementation of EciesHkdfSenderKemBoringSsl for curve25519. class EciesHkdfX25519SendKemBoringSsl : public EciesHkdfSenderKemBoringSsl { public: // Constructs a sender KEM for the specified curve and recipient's // public key point. The public key's coordinates are big-endian byte array. static crypto::tink::util::StatusOr< std::unique_ptr> New(EllipticCurveType curve, const std::string& pubx, const std::string& puby); // Generates ephemeral key pairs, computes ECDH's shared secret based on // generated ephemeral key and recipient's public key, then uses HKDF // to derive the symmetric key from the shared secret, 'hkdf_info' and // hkdf_salt. crypto::tink::util::StatusOr> GenerateKey( HashType hash, absl::string_view hkdf_salt, absl::string_view hkdf_info, uint32_t key_size_in_bytes, EcPointFormat point_format) const override; static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kNotFips; private: explicit EciesHkdfX25519SendKemBoringSsl( internal::SslUniquePtr peer_public_key); const internal::SslUniquePtr peer_public_key_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_ECIES_HKDF_SENDER_KEM_BORINGSSL_H_ ================================================ FILE: cc/subtle/ecies_hkdf_sender_kem_boringssl_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/ecies_hkdf_sender_kem_boringssl.h" #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "tink/config/tink_fips.h" #include "tink/internal/ec_util.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/ecies_hkdf_recipient_kem_boringssl.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" // TODO(quannguyen): Add extensive tests. // It's important to test compatibility with Java. namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::StatusIs; class EciesHkdfSenderKemBoringSslTest : public ::testing::Test {}; struct TestVector { EllipticCurveType curve; HashType hash; EcPointFormat point_format; std::string salt_hex; std::string info_hex; int out_len; }; static const std::vector test_vector( {{ EllipticCurveType::NIST_P256, HashType::SHA256, EcPointFormat::UNCOMPRESSED, "0b0b0b0b", "0b0b0b0b0b0b0b0b", 32, }, { EllipticCurveType::NIST_P256, HashType::SHA256, EcPointFormat::COMPRESSED, "0b0b0b0b", "0b0b0b0b0b0b0b0b", 32, }, { EllipticCurveType::CURVE25519, HashType::SHA256, EcPointFormat::COMPRESSED, "0b0b0b0b", "0b0b0b0b0b0b0b0b", 32, }}); TEST_F(EciesHkdfSenderKemBoringSslTest, TestSenderRecipientBasic) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } for (const TestVector& test : test_vector) { auto status_or_test_key = internal::NewEcKey(test.curve); ASSERT_TRUE(status_or_test_key.ok()); auto test_key = status_or_test_key.value(); auto status_or_sender_kem = EciesHkdfSenderKemBoringSsl::New( test.curve, test_key.pub_x, test_key.pub_y); ASSERT_TRUE(status_or_sender_kem.ok()); auto sender_kem = std::move(status_or_sender_kem.value()); auto status_or_kem_key = sender_kem->GenerateKey( test.hash, absl::HexStringToBytes(test.salt_hex), absl::HexStringToBytes(test.info_hex), test.out_len, test.point_format); ASSERT_TRUE(status_or_kem_key.ok()); auto kem_key = std::move(status_or_kem_key.value()); auto ecies_recipient( std::move(EciesHkdfRecipientKemBoringSsl::New(test.curve, test_key.priv) .value())); auto status_or_shared_secret = ecies_recipient->GenerateKey( kem_key->get_kem_bytes(), test.hash, absl::HexStringToBytes(test.salt_hex), absl::HexStringToBytes(test.info_hex), test.out_len, test.point_format); std::cout << absl::BytesToHexString(kem_key->get_kem_bytes()) << '\n'; EXPECT_EQ(absl::BytesToHexString( util::SecretDataAsStringView(kem_key->get_symmetric_key())), absl::BytesToHexString(util::SecretDataAsStringView( status_or_shared_secret.value()))); } } TEST_F(EciesHkdfSenderKemBoringSslTest, TestNewUnknownCurve) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } auto status_or_sender_kem = EciesHkdfSenderKemBoringSsl::New( EllipticCurveType::UNKNOWN_CURVE, "", ""); EXPECT_EQ(absl::StatusCode::kUnimplemented, status_or_sender_kem.status().code()); } class EciesHkdfNistPCurveSendKemBoringSslTest : public ::testing::Test {}; TEST_F(EciesHkdfNistPCurveSendKemBoringSslTest, TestNew) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EllipticCurveType curve = EllipticCurveType::NIST_P256; auto status_or_test_key = internal::NewEcKey(curve); ASSERT_TRUE(status_or_test_key.ok()); auto test_key = status_or_test_key.value(); auto status_or_sender_kem = EciesHkdfNistPCurveSendKemBoringSsl::New( curve, test_key.pub_x, test_key.pub_y); ASSERT_TRUE(status_or_sender_kem.ok()); } TEST_F(EciesHkdfNistPCurveSendKemBoringSslTest, TestNewInvalidCurve) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EllipticCurveType curve = EllipticCurveType::NIST_P256; auto status_or_test_key = internal::NewEcKey(curve); ASSERT_TRUE(status_or_test_key.ok()); auto test_key = status_or_test_key.value(); auto status_or_sender_kem = EciesHkdfNistPCurveSendKemBoringSsl::New( EllipticCurveType::CURVE25519, test_key.pub_x, test_key.pub_y); EXPECT_EQ(status_or_sender_kem.status().code(), absl::StatusCode::kUnimplemented); } TEST_F(EciesHkdfNistPCurveSendKemBoringSslTest, TestGenerateKey) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EllipticCurveType curve = EllipticCurveType::NIST_P256; auto status_or_test_key = internal::NewEcKey(curve); ASSERT_TRUE(status_or_test_key.ok()); auto test_key = status_or_test_key.value(); auto status_or_sender_kem = EciesHkdfNistPCurveSendKemBoringSsl::New( curve, test_key.pub_x, test_key.pub_y); ASSERT_TRUE(status_or_sender_kem.ok()); auto sender_kem = std::move(status_or_sender_kem.value()); uint32_t key_size_in_bytes = 128; auto status_or_kem_key = sender_kem->GenerateKey(HashType::SHA256, "hkdf_salt", "hkdf_info", key_size_in_bytes, EcPointFormat::COMPRESSED); ASSERT_TRUE(status_or_kem_key.ok()); auto kem_key = std::move(status_or_kem_key.value()); EXPECT_FALSE(kem_key->get_kem_bytes().empty()); EXPECT_EQ(kem_key->get_symmetric_key().size(), key_size_in_bytes); } class EciesHkdfX25519SendKemBoringSslTest : public ::testing::Test {}; TEST_F(EciesHkdfX25519SendKemBoringSslTest, TestNew) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EllipticCurveType curve = EllipticCurveType::CURVE25519; auto status_or_test_key = internal::NewEcKey(curve); ASSERT_TRUE(status_or_test_key.ok()); auto test_key = status_or_test_key.value(); auto status_or_sender_kem = EciesHkdfX25519SendKemBoringSsl::New( curve, test_key.pub_x, test_key.pub_y); ASSERT_TRUE(status_or_sender_kem.ok()); } TEST_F(EciesHkdfX25519SendKemBoringSslTest, TestNewInvalidCurve) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EllipticCurveType curve = EllipticCurveType::CURVE25519; auto status_or_test_key = internal::NewEcKey(curve); ASSERT_TRUE(status_or_test_key.ok()); auto test_key = status_or_test_key.value(); auto status_or_sender_kem = EciesHkdfX25519SendKemBoringSsl::New( EllipticCurveType::NIST_P256, test_key.pub_x, test_key.pub_y); EXPECT_EQ(status_or_sender_kem.status().code(), absl::StatusCode::kInvalidArgument); } TEST_F(EciesHkdfX25519SendKemBoringSslTest, TestNewPubxTooLong) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EllipticCurveType curve = EllipticCurveType::CURVE25519; auto status_or_test_key = internal::NewEcKey(curve); ASSERT_TRUE(status_or_test_key.ok()); auto test_key = status_or_test_key.value(); test_key.pub_x.resize(test_key.pub_x.size() / 2); auto status_or_sender_kem = EciesHkdfX25519SendKemBoringSsl::New( curve, test_key.pub_x, test_key.pub_y); EXPECT_EQ(status_or_sender_kem.status().code(), absl::StatusCode::kInvalidArgument); } TEST_F(EciesHkdfX25519SendKemBoringSslTest, TestNewPubyNotEmpty) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EllipticCurveType curve = EllipticCurveType::CURVE25519; auto status_or_test_key = internal::NewEcKey(curve); ASSERT_TRUE(status_or_test_key.ok()); auto test_key = status_or_test_key.value(); test_key.pub_y = test_key.pub_x; auto status_or_sender_kem = EciesHkdfX25519SendKemBoringSsl::New( curve, test_key.pub_x, test_key.pub_y); EXPECT_EQ(status_or_sender_kem.status().code(), absl::StatusCode::kInvalidArgument); } TEST_F(EciesHkdfX25519SendKemBoringSslTest, TestGenerateKey) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EllipticCurveType curve = EllipticCurveType::CURVE25519; auto status_or_test_key = internal::NewEcKey(curve); ASSERT_TRUE(status_or_test_key.ok()); auto test_key = status_or_test_key.value(); auto status_or_sender_kem = EciesHkdfX25519SendKemBoringSsl::New( curve, test_key.pub_x, test_key.pub_y); ASSERT_TRUE(status_or_sender_kem.ok()); auto sender_kem = std::move(status_or_sender_kem.value()); uint32_t key_size_in_bytes = 128; auto status_or_kem_key = sender_kem->GenerateKey(HashType::SHA256, "hkdf_salt", "hkdf_info", key_size_in_bytes, EcPointFormat::COMPRESSED); ASSERT_TRUE(status_or_kem_key.ok()); auto kem_key = std::move(status_or_kem_key.value()); EXPECT_EQ(kem_key->get_kem_bytes().size(), internal::Ed25519KeyPubKeySize()); EXPECT_EQ(kem_key->get_symmetric_key().size(), key_size_in_bytes); } TEST_F(EciesHkdfX25519SendKemBoringSslTest, TestGenerateKeyUncompressed) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } EllipticCurveType curve = EllipticCurveType::CURVE25519; auto status_or_test_key = internal::NewEcKey(curve); ASSERT_TRUE(status_or_test_key.ok()); auto test_key = status_or_test_key.value(); auto status_or_sender_kem = EciesHkdfX25519SendKemBoringSsl::New( curve, test_key.pub_x, test_key.pub_y); ASSERT_TRUE(status_or_sender_kem.ok()); auto sender_kem = std::move(status_or_sender_kem.value()); auto status_or_kem_key = sender_kem->GenerateKey(HashType::SHA256, "hkdf_salt", "hkdf_info", 32, EcPointFormat::UNCOMPRESSED); EXPECT_EQ(status_or_kem_key.status().code(), absl::StatusCode::kInvalidArgument); } // Tests for FIPS only mode TEST_F(EciesHkdfNistPCurveSendKemBoringSslTest, TestFipsOnly) { if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Only supported in FIPS-only mode"; } EllipticCurveType curve = EllipticCurveType::NIST_P256; auto status_or_test_key = internal::NewEcKey(curve); auto test_key = status_or_test_key.value(); EXPECT_THAT(EciesHkdfNistPCurveSendKemBoringSsl::New(curve, test_key.pub_x, test_key.pub_y) .status(), StatusIs(absl::StatusCode::kInternal)); } TEST_F(EciesHkdfX25519SendKemBoringSslTest, TestFipsOnly) { if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Only supported in FIPS-only mode"; } EllipticCurveType curve = EllipticCurveType::NIST_P256; auto status_or_test_key = internal::NewEcKey(curve); auto test_key = status_or_test_key.value(); EXPECT_THAT(EciesHkdfX25519SendKemBoringSsl::New(curve, test_key.pub_x, test_key.pub_y) .status(), StatusIs(absl::StatusCode::kInternal)); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/ed25519_sign_boringssl.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/ed25519_sign_boringssl.h" #include #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "tink/internal/ec_util.h" #include "tink/internal/fips_utils.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/internal/util.h" #include "tink/public_key_sign.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { constexpr int kEd25519SignatureLenInBytes = 64; // static util::StatusOr> Ed25519SignBoringSsl::New( util::SecretData private_key) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) return status; // OpenSSL/BoringSSL consider the ED25519's private key to be: private_key || // public_key. const int kSslPrivateKeySize = internal::Ed25519KeyPrivKeySize() + internal::Ed25519KeyPubKeySize(); if (private_key.size() != kSslPrivateKeySize) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrFormat("Invalid ED25519 private key size (%d). " "The only valid size is %d.", private_key.size(), kSslPrivateKeySize)); } internal::SslUniquePtr ssl_priv_key(EVP_PKEY_new_raw_private_key( EVP_PKEY_ED25519, /*unused=*/nullptr, private_key.data(), internal::Ed25519KeyPrivKeySize())); if (ssl_priv_key == nullptr) { return util::Status(absl::StatusCode::kInternal, "EVP_PKEY_new_raw_private_key failed"); } return {absl::WrapUnique(new Ed25519SignBoringSsl(std::move(ssl_priv_key)))}; } util::StatusOr Ed25519SignBoringSsl::Sign( absl::string_view data) const { data = internal::EnsureStringNonNull(data); uint8_t out_sig[kEd25519SignatureLenInBytes]; std::fill(std::begin(out_sig), std::end(out_sig), 0); internal::SslUniquePtr md_ctx(EVP_MD_CTX_create()); size_t sig_len = kEd25519SignatureLenInBytes; // type must be set to nullptr with Ed25519. // See https://www.openssl.org/docs/man1.1.1/man3/EVP_DigestSignInit.html. if (EVP_DigestSignInit(md_ctx.get(), /*pctx=*/nullptr, /*type=*/nullptr, /*e=*/nullptr, priv_key_.get()) != 1 || EVP_DigestSign(md_ctx.get(), out_sig, &sig_len, /*data=*/reinterpret_cast(data.data()), data.size()) != 1) { return util::Status(absl::StatusCode::kInternal, "Signing failed."); } return std::string(reinterpret_cast(out_sig), kEd25519SignatureLenInBytes); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/ed25519_sign_boringssl.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_ED25519_SIGN_BORINGSSL_H_ #define TINK_SUBTLE_ED25519_SIGN_BORINGSSL_H_ #include #include #include #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "tink/config/tink_fips.h" #include "tink/internal/fips_utils.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/public_key_sign.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { class Ed25519SignBoringSsl : public PublicKeySign { public: static crypto::tink::util::StatusOr> New( util::SecretData private_key); // Computes the signature for 'data'. crypto::tink::util::StatusOr Sign( absl::string_view data) const override; static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kNotFips; private: explicit Ed25519SignBoringSsl(internal::SslUniquePtr priv_key) : priv_key_(std::move(priv_key)) {} const internal::SslUniquePtr priv_key_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_ED25519_SIGN_BORINGSSL_H_ ================================================ FILE: cc/subtle/ed25519_sign_boringssl_test.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/ed25519_sign_boringssl.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/config/tink_fips.h" #include "tink/internal/ec_util.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/subtle/ed25519_verify_boringssl.h" #include "tink/subtle/random.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; constexpr int kEd25519SignatureLenInBytes = 64; class Ed25519SignBoringSslTest : public ::testing::Test {}; struct Ed25519KeyPair { std::string public_key; util::SecretData private_key; }; util::StatusOr NewKeyPair() { util::StatusOr> key = internal::NewEd25519Key(); if (!key.ok()) { return key.status(); } return {{(*key)->public_key, util::SecretDataFromStringView(absl::StrCat( (*key)->private_key, (*key)->public_key))}}; } TEST_F(Ed25519SignBoringSslTest, testBasicSign) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } // Generate a new key pair. util::StatusOr key = NewKeyPair(); ASSERT_THAT(key, IsOk()); // Create a new signer. auto signer_result = Ed25519SignBoringSsl::New(key->private_key); ASSERT_TRUE(signer_result.ok()) << signer_result.status(); auto signer = std::move(signer_result.value()); // Create a new verifier. auto verifier_result = Ed25519VerifyBoringSsl::New(key->public_key); ASSERT_TRUE(verifier_result.ok()) << verifier_result.status(); auto verifier = std::move(verifier_result.value()); // Sign a message. std::string message = "some data to be signed"; std::string signature = signer->Sign(message).value(); EXPECT_NE(signature, message); EXPECT_EQ(signature.size(), kEd25519SignatureLenInBytes); auto status = verifier->Verify(signature, message); EXPECT_TRUE(status.ok()) << status; status = verifier->Verify("some bad signature", message); EXPECT_FALSE(status.ok()); status = verifier->Verify(signature, "some bad message"); EXPECT_FALSE(status.ok()); // Loop 100 times, sign a random message twice using the signer and verify // that the signatures are the same. for (size_t i = 0; i < 100; i++) { message = subtle::Random::GetRandomBytes(i); std::string signature1 = signer->Sign(message).value(); std::string signature2 = signer->Sign(message).value(); EXPECT_EQ(signature1, signature2); // Verify that the signatures are valid. status = verifier->Verify(signature1, message); EXPECT_TRUE(status.ok()) << status; } } TEST_F(Ed25519SignBoringSslTest, testInvalidPrivateKeys) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } for (int keysize = 0; keysize < 128; keysize++) { // Ed25519SignBoringSsl::New expects a private key: private part || public // part. if (keysize == internal::Ed25519KeyPrivKeySize() + internal::Ed25519KeyPubKeySize()) { // Valid key size. continue; } util::SecretData key(keysize, 'x'); EXPECT_FALSE(Ed25519SignBoringSsl::New(key).ok()); } } TEST_F(Ed25519SignBoringSslTest, testMessageEmptyVersusNullStringView) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } // Generate a new key pair. util::StatusOr key = NewKeyPair(); ASSERT_THAT(key, IsOk()); // Create a new signer. auto signer_result = Ed25519SignBoringSsl::New(key->private_key); ASSERT_TRUE(signer_result.ok()) << signer_result.status(); auto signer = std::move(signer_result.value()); // Create a new verifier. auto verifier_result = Ed25519VerifyBoringSsl::New(key->public_key); ASSERT_TRUE(verifier_result.ok()) << verifier_result.status(); auto verifier = std::move(verifier_result.value()); // Message is a null string_view. const absl::string_view empty_message; auto signature = signer->Sign(empty_message).value(); EXPECT_NE(signature, empty_message); EXPECT_EQ(signature.size(), kEd25519SignatureLenInBytes); auto status = verifier->Verify(signature, empty_message); EXPECT_TRUE(status.ok()) << status; // Message is an empty string. const std::string message = ""; signature = signer->Sign(message).value(); EXPECT_EQ(signature.size(), kEd25519SignatureLenInBytes); EXPECT_NE(signature, message); status = verifier->Verify(signature, message); EXPECT_TRUE(status.ok()) << status; // Message is a default constructed string_view. signature = signer->Sign(absl::string_view()).value(); EXPECT_EQ(signature.size(), kEd25519SignatureLenInBytes); status = verifier->Verify(signature, absl::string_view()); EXPECT_TRUE(status.ok()) << status; } struct TestVector { std::string public_key; std::string private_key; std::string expected_signature; std::string message; }; TEST_F(Ed25519SignBoringSslTest, testWithTestVectors) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } // These test vectors are taken from: // https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-02#section-6. TestVector ed25519_vectors[] = { { /*TEST 1*/ /*public_key= */ absl::HexStringToBytes( "d75a980182b10ab7d54bfed3c964073a" "0ee172f3daa62325af021a68f707511a"), /*private_key=*/ absl::HexStringToBytes("9d61b19deffd5a60ba844af492ec2cc4" "4449c5697b326919703bac031cae7f60"), /*signature = */ absl::HexStringToBytes("e5564300c360ac729086e2cc806e828a" "84877f1eb8e5d974d873e06522490155" "5fb8821590a33bacc61e39701cf9b46b" "d25bf5f0595bbe24655141438e7a100b"), /*message = */ "", }, { /*TEST 2*/ /*public_key= */ absl::HexStringToBytes( "3d4017c3e843895a92b70aa74d1b7ebc" "9c982ccf2ec4968cc0cd55f12af4660c"), /*private_key=*/ absl::HexStringToBytes("4ccd089b28ff96da9db6c346ec114e0f" "5b8a319f35aba624da8cf6ed4fb8a6fb"), /*signature = */ absl::HexStringToBytes("92a009a9f0d4cab8720e820b5f642540" "a2b27b5416503f8fb3762223ebdb69da" "085ac1e43e15996e458f3613d0f11d8c" "387b2eaeb4302aeeb00d291612bb0c00"), /*message = */ "\x72", }, { /*TEST 3*/ /*public_key= */ absl::HexStringToBytes( "fc51cd8e6218a1a38da47ed00230f058" "0816ed13ba3303ac5deb911548908025"), /*private_key=*/ absl::HexStringToBytes("c5aa8df43f9f837bedb7442f31dcb7b1" "66d38535076f094b85ce3a2e0b4458f7"), /*signature = */ absl::HexStringToBytes("6291d657deec24024827e69c3abe01a3" "0ce548a284743a445e3680d7db5ac3ac" "18ff9b538d16f290ae67f760984dc659" "4a7c15e9716ed28dc027beceea1ec40a"), /*message = */ "\xaf\x82", }, { /*TEST 1024*/ /*public_key= */ absl::HexStringToBytes( "278117fc144c72340f67d0f2316e8386" "ceffbf2b2428c9c51fef7c597f1d426e"), /*private_key=*/ absl::HexStringToBytes("f5e5767cf153319517630f226876b86c" "8160cc583bc013744c6bf255f5cc0ee5"), /*signature = */ absl::HexStringToBytes("0aab4c900501b3e24d7cdf4663326a3a" "87df5e4843b2cbdb67cbf6e460fec350" "aa5371b1508f9f4528ecea23c436d94b" "5e8fcd4f681e30a6ac00a9704a188a03"), /*message = */ absl::HexStringToBytes("08b8b2b733424243760fe426a4b54908" "632110a66c2f6591eabd3345e3e4eb98" "fa6e264bf09efe12ee50f8f54e9f77b1" "e355f6c50544e23fb1433ddf73be84d8" "79de7c0046dc4996d9e773f4bc9efe57" "38829adb26c81b37c93a1b270b20329d" "658675fc6ea534e0810a4432826bf58c" "941efb65d57a338bbd2e26640f89ffbc" "1a858efcb8550ee3a5e1998bd177e93a" "7363c344fe6b199ee5d02e82d522c4fe" "ba15452f80288a821a579116ec6dad2b" "3b310da903401aa62100ab5d1a36553e" "06203b33890cc9b832f79ef80560ccb9" "a39ce767967ed628c6ad573cb116dbef" "efd75499da96bd68a8a97b928a8bbc10" "3b6621fcde2beca1231d206be6cd9ec7" "aff6f6c94fcd7204ed3455c68c83f4a4" "1da4af2b74ef5c53f1d8ac70bdcb7ed1" "85ce81bd84359d44254d95629e9855a9" "4a7c1958d1f8ada5d0532ed8a5aa3fb2" "d17ba70eb6248e594e1a2297acbbb39d" "502f1a8c6eb6f1ce22b3de1a1f40cc24" "554119a831a9aad6079cad88425de6bd" "e1a9187ebb6092cf67bf2b13fd65f270" "88d78b7e883c8759d2c4f5c65adb7553" "878ad575f9fad878e80a0c9ba63bcbcc" "2732e69485bbc9c90bfbd62481d9089b" "eccf80cfe2df16a2cf65bd92dd597b07" "07e0917af48bbb75fed413d238f5555a" "7a569d80c3414a8d0859dc65a46128ba" "b27af87a71314f318c782b23ebfe808b" "82b0ce26401d2e22f04d83d1255dc51a" "ddd3b75a2b1ae0784504df543af8969b" "e3ea7082ff7fc9888c144da2af58429e" "c96031dbcad3dad9af0dcbaaaf268cb8" "fcffead94f3c7ca495e056a9b47acdb7" "51fb73e666c6c655ade8297297d07ad1" "ba5e43f1bca32301651339e22904cc8c" "42f58c30c04aafdb038dda0847dd988d" "cda6f3bfd15c4b4c4525004aa06eeff8" "ca61783aacec57fb3d1f92b0fe2fd1a8" "5f6724517b65e614ad6808d6f6ee34df" "f7310fdc82aebfd904b01e1dc54b2927" "094b2db68d6f903b68401adebf5a7e08" "d78ff4ef5d63653a65040cf9bfd4aca7" "984a74d37145986780fc0b16ac451649" "de6188a7dbdf191f64b5fc5e2ab47b57" "f7f7276cd419c17a3ca8e1b939ae49e4" "88acba6b965610b5480109c8b17b80e1" "b7b750dfc7598d5d5011fd2dcc5600a3" "2ef5b52a1ecc820e308aa342721aac09" "43bf6686b64b2579376504ccc493d97e" "6aed3fb0f9cd71a43dd497f01f17c0e2" "cb3797aa2a2f256656168e6c496afc5f" "b93246f6b1116398a346f1a641f3b041" "e989f7914f90cc2c7fff357876e506b5" "0d334ba77c225bc307ba537152f3f161" "0e4eafe595f6d9d90d11faa933a15ef1" "369546868a7f3a45a96768d40fd9d034" "12c091c6315cf4fde7cb68606937380d" "b2eaaa707b4c4185c32eddcdd306705e" "4dc1ffc872eeee475a64dfac86aba41c" "0618983f8741c5ef68d3a101e8a3b8ca" "c60c905c15fc910840b94c00a0b9d0"), }, }; for (const TestVector &v : ed25519_vectors) { // Add the public as a suffix to the private key. This is needed by the // boringssl API. util::SecretData private_key = util::SecretDataFromStringView( absl::StrCat(v.private_key, v.public_key)); // Create a new signer. auto signer_result = Ed25519SignBoringSsl::New(private_key); ASSERT_TRUE(signer_result.ok()) << signer_result.status(); auto signer = std::move(signer_result.value()); // Create a new verifier. auto verifier_result = Ed25519VerifyBoringSsl::New(v.public_key); ASSERT_TRUE(verifier_result.ok()) << verifier_result.status(); auto verifier = std::move(verifier_result.value()); std::string signature = signer->Sign(v.message).value(); EXPECT_TRUE(signature == v.expected_signature); auto status = verifier->Verify(signature, v.message); EXPECT_TRUE(status.ok()) << status; } } TEST_F(Ed25519SignBoringSslTest, testFipsMode) { if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips."; } // Generate a new key pair. util::StatusOr key = NewKeyPair(); ASSERT_THAT(key, IsOk()); // Create a new signer. EXPECT_THAT(Ed25519SignBoringSsl::New(key->private_key).status(), StatusIs(absl::StatusCode::kInternal)); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/ed25519_verify_boringssl.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/ed25519_verify_boringssl.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "tink/internal/ec_util.h" #include "tink/internal/fips_utils.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/internal/util.h" #include "tink/public_key_verify.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { constexpr int kEd25519SignatureLenInBytes = 64; util::StatusOr> Ed25519VerifyBoringSsl::New( absl::string_view public_key) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) return status; if (public_key.length() != internal::Ed25519KeyPubKeySize()) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrFormat("Invalid ED25519 public key size (%d). " "The only valid size is %d.", public_key.length(), internal::Ed25519KeyPubKeySize())); } // Generate a new EVP_PKEY key and populate it with the public key data. internal::SslUniquePtr ssl_pub_key(EVP_PKEY_new_raw_public_key( EVP_PKEY_ED25519, /*unused=*/nullptr, reinterpret_cast(public_key.data()), internal::Ed25519KeyPrivKeySize())); if (ssl_pub_key == nullptr) { return util::Status(absl::StatusCode::kInternal, "EVP_PKEY_new_raw_public_key failed"); } return {absl::WrapUnique(new Ed25519VerifyBoringSsl(std::move(ssl_pub_key)))}; } util::Status Ed25519VerifyBoringSsl::Verify(absl::string_view signature, absl::string_view data) const { signature = internal::EnsureStringNonNull(signature); data = internal::EnsureStringNonNull(data); if (signature.size() != kEd25519SignatureLenInBytes) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrFormat("Invalid ED25519 signature size (%d). " "The signature must be %d bytes long.", signature.size(), kEd25519SignatureLenInBytes)); } internal::SslUniquePtr md_ctx(EVP_MD_CTX_create()); // `type` must be set to nullptr with Ed25519. if (EVP_DigestVerifyInit(md_ctx.get(), /*pctx=*/nullptr, /*type=*/nullptr, /*e=*/nullptr, public_key_.get()) != 1) { return util::Status(absl::StatusCode::kInternal, "EVP_DigestVerifyInit failed."); } if (EVP_DigestVerify( md_ctx.get(), /*sig=*/reinterpret_cast(signature.data()), signature.size(), /*data=*/reinterpret_cast(data.data()), data.size()) != 1) { return util::Status(absl::StatusCode::kInternal, "Signature is not valid."); } return util::OkStatus(); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/ed25519_verify_boringssl.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_ED25519_VERIFY_BORINGSSL_H_ #define TINK_SUBTLE_ED25519_VERIFY_BORINGSSL_H_ #include #include #include #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "tink/internal/fips_utils.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/public_key_verify.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { class Ed25519VerifyBoringSsl : public PublicKeyVerify { public: static crypto::tink::util::StatusOr> New( absl::string_view public_key); // Verifies that 'signature' is a digital signature for 'data'. crypto::tink::util::Status Verify(absl::string_view signature, absl::string_view data) const override; static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kNotFips; private: explicit Ed25519VerifyBoringSsl(internal::SslUniquePtr public_key) : public_key_(std::move(public_key)) {} const internal::SslUniquePtr public_key_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_ED25519_VERIFY_BORINGSSL_H_ ================================================ FILE: cc/subtle/ed25519_verify_boringssl_test.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/ed25519_verify_boringssl.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "include/rapidjson/document.h" #include "tink/config/tink_fips.h" #include "tink/internal/ec_util.h" #include "tink/public_key_verify.h" #include "tink/subtle/wycheproof_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Not; using ::testing::Test; using ::testing::TestWithParam; using ::testing::ValuesIn; // Non-FIPS tests. class Ed25519VerifyBoringSslTest : public Test { private: void SetUp() override { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } } }; // Test vector taken from // https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-02#section-6. struct TestVector { int id; std::string public_key; std::string private_key; std::string signature; std::string message; }; std::vector GetTestVectors() { return { { /*id=*/1, /*public_key=*/ absl::HexStringToBytes( "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511" "a"), /*private_key=*/ absl::HexStringToBytes("9d61b19deffd5a60ba844af492ec2cc44449c5697b326" "919703bac031cae7f60"), /*signature=*/ absl::HexStringToBytes("e5564300c360ac729086e2cc806e828a84877f1eb8e5d" "974d873e065224901555fb8821590a33bacc61e39701c" "f9b46bd25bf5f0595bbe24655141438e7a100b"), /*message=*/"", }, { /*id=*/2, /*public_key=*/ absl::HexStringToBytes( "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660" "c"), /*private_key=*/ absl::HexStringToBytes("4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba" "624da8cf6ed4fb8a6fb"), /*signature=*/ absl::HexStringToBytes("92a009a9f0d4cab8720e820b5f642540a2b27b5416503" "f8fb3762223ebdb69da085ac1e43e15996e458f3613d0" "f11d8c387b2eaeb4302aeeb00d291612bb0c00"), /*message=*/"\x72", }, { /*id=*/3, /*public_key=*/ absl::HexStringToBytes( "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb91154890802" "5"), /*private_key=*/ absl::HexStringToBytes("c5aa8df43f9f837bedb7442f31dcb7b166d38535076f0" "94b85ce3a2e0b4458f7"), /*signature=*/ absl::HexStringToBytes("6291d657deec24024827e69c3abe01a30ce548a284743" "a445e3680d7db5ac3ac18ff9b538d16f290ae67f76098" "4dc6594a7c15e9716ed28dc027beceea1ec40a"), /*message=*/"\xaf\x82", }, { /*id=*/1024, /*public_key=*/ absl::HexStringToBytes( "278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426" "e"), /*private_key=*/ absl::HexStringToBytes("f5e5767cf153319517630f226876b86c8160cc583bc01" "3744c6bf255f5cc0ee5"), /*signature=*/ absl::HexStringToBytes("0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2c" "bdb67cbf6e460fec350aa5371b1508f9f4528ecea23c4" "36d94b5e8fcd4f681e30a6ac00a9704a188a03"), /*message=*/ absl::HexStringToBytes( "08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98" "fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d8" "79de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d" "658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc" "1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4fe" "ba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e" "06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbef" "efd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7" "aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed1" "85ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2" "d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24" "554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f270" "88d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc" "2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b07" "07e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128ba" "b27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51a" "ddd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429e" "c96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb7" "51fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c" "42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8" "ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34df" "f7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08" "d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649" "de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e4" "88acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a3" "2ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e" "6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5f" "b93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b5" "0d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1" "369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380d" "b2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c" "0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0"), }, }; } TEST_F(Ed25519VerifyBoringSslTest, InvalidPublicKey) { // Null public key. const absl::string_view null_public_key; EXPECT_THAT(Ed25519VerifyBoringSsl::New(null_public_key).status(), Not(IsOk())); for (int keysize = 0; keysize < 128; keysize++) { if (keysize == internal::Ed25519KeyPubKeySize()) { // Valid key size. continue; } std::string key(keysize, 'x'); EXPECT_THAT(Ed25519VerifyBoringSsl::New(key), Not(IsOk())); } } // Using the test vector with id=1, this makes sure verification succeeds // passing an empty string_view, an empty string and a default-constructed // string_view. TEST_F(Ed25519VerifyBoringSslTest, MessageEmptyVersusNullStringView) { TestVector empty_message_test_vector = GetTestVectors()[0]; util::StatusOr> verifier = Ed25519VerifyBoringSsl::New(empty_message_test_vector.public_key); ASSERT_THAT(verifier, IsOk()); // Message is a null string_view. const absl::string_view kEmptyStringView; EXPECT_THAT((*verifier)->Verify(empty_message_test_vector.signature, kEmptyStringView), IsOk()); // Message is an empty string. const std::string kEmptyStr = ""; EXPECT_THAT( (*verifier)->Verify(empty_message_test_vector.signature, kEmptyStr), IsOk()); // Message is a default constructed string_view. EXPECT_THAT((*verifier)->Verify(empty_message_test_vector.signature, absl::string_view()), IsOk()); } using Ed25519VerifyBoringSslParamsTest = TestWithParam; TEST_P(Ed25519VerifyBoringSslParamsTest, VerifiesCorrectly) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips is false."; } TestVector test_vector = GetParam(); util::StatusOr> verifier = Ed25519VerifyBoringSsl::New(test_vector.public_key); ASSERT_THAT(verifier, IsOk()); EXPECT_THAT((*verifier)->Verify(test_vector.signature, test_vector.message), IsOk()); } INSTANTIATE_TEST_SUITE_P(Ed25519VerifyBoringSslParamsTests, Ed25519VerifyBoringSslParamsTest, ValuesIn(GetTestVectors())); static util::StatusOr> GetVerifier( const rapidjson::Value& test_group) { std::string public_key = WycheproofUtil::GetBytes(test_group["key"]["pk"]); auto result = Ed25519VerifyBoringSsl::New(public_key); if (!result.ok()) { std::cout << "Failed: " << result.status() << "\n"; } return result; } // Tests signature verification using the test vectors in the specified file. // allow_skipping determines whether it is OK to skip a test because // a verfier cannot be constructed. This option can be used for // if a file contains test vectors that are not necessarily supported // by tink. bool TestSignatures(const std::string& filename, bool allow_skipping) { std::unique_ptr root = WycheproofUtil::ReadTestVectors(filename); std::cout << (*root)["algorithm"].GetString(); std::cout << "generator version " << (*root)["generatorVersion"].GetString(); int passed_tests = 0; int failed_tests = 0; for (const rapidjson::Value& test_group : (*root)["testGroups"].GetArray()) { auto verifier_result = GetVerifier(test_group); if (!verifier_result.ok()) { std::string curve = test_group["key"]["curve"].GetString(); if (allow_skipping) { std::cout << "Could not construct verifier for curve " << curve << verifier_result.status(); } else { ADD_FAILURE() << "Could not construct verifier for curve " << curve << verifier_result.status(); failed_tests += test_group["tests"].GetArray().Size(); } continue; } auto verifier = std::move(verifier_result.value()); for (const rapidjson::Value& test : test_group["tests"].GetArray()) { std::string expected = test["result"].GetString(); std::string msg = WycheproofUtil::GetBytes(test["msg"]); std::string sig = WycheproofUtil::GetBytes(test["sig"]); std::string id = absl::StrCat(test["tcId"].GetInt(), " ", test["comment"].GetString()); auto status = verifier->Verify(sig, msg); if (expected == "valid") { if (status.ok()) { ++passed_tests; } else { ++failed_tests; ADD_FAILURE() << "Valid signature not verified:" << id << " status:" << status; } } else if (expected == "invalid") { if (!status.ok()) { ++passed_tests; } else { ++failed_tests; ADD_FAILURE() << "Invalid signature verified:" << id; } } else if (expected == "acceptable") { // The validity of the signature is undefined. Hence the test passes // but we log the result since we might still want to know if the // library is strict or forgiving. ++passed_tests; std::cout << "Acceptable signature:" << id << ":" << status; } else { ++failed_tests; ADD_FAILURE() << "Invalid field result:" << expected; } } } int num_tests = (*root)["numberOfTests"].GetInt(); std::cout << "total number of tests: " << num_tests; std::cout << "number of tests passed:" << passed_tests; std::cout << "number of tests failed:" << failed_tests; return failed_tests == 0; } TEST_F(Ed25519VerifyBoringSslTest, WycheproofCurve25519) { ASSERT_TRUE(TestSignatures("eddsa_test.json", false)); } TEST(Ed25519VerifyBoringSslFipsTest, testFipsMode) { if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Test assumes kOnlyUseFips."; } constexpr absl::string_view kPublicKey = "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025"; // Create a new signer. EXPECT_THAT( Ed25519VerifyBoringSsl::New(absl::HexStringToBytes(kPublicKey)).status(), StatusIs(absl::StatusCode::kInternal)); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/encrypt_then_authenticate.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/encrypt_then_authenticate.h" #include #include #include #include #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/internal/util.h" #include "tink/mac.h" #include "tink/subtle/ind_cpa_cipher.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { static std::string longToBigEndianStr(uint64_t value) { uint8_t bytes[8]; for (int i = sizeof(bytes) - 1; i >= 0; i--) { bytes[i] = value & 0xff; value >>= 8; } return std::string(reinterpret_cast(&bytes[0]), sizeof(bytes)); } util::StatusOr> EncryptThenAuthenticate::New( std::unique_ptr ind_cpa_cipher, std::unique_ptr mac, uint8_t tag_size) { if (tag_size < kMinTagSizeInBytes) { return util::Status(absl::StatusCode::kInvalidArgument, "tag size too small"); } std::unique_ptr aead(new EncryptThenAuthenticate( std::move(ind_cpa_cipher), std::move(mac), tag_size)); return std::move(aead); } util::StatusOr EncryptThenAuthenticate::Encrypt( absl::string_view plaintext, absl::string_view associated_data) const { // BoringSSL expects a non-null pointer for plaintext and associated_data, // regardless of whether the size is 0. plaintext = internal::EnsureStringNonNull(plaintext); associated_data = internal::EnsureStringNonNull(associated_data); uint64_t associated_data_size_in_bytes = associated_data.size(); uint64_t associated_data_size_in_bits = associated_data_size_in_bytes * 8; if (associated_data_size_in_bits / 8 != associated_data_size_in_bytes /* overflow occured! */) { return util::Status(absl::StatusCode::kInvalidArgument, "associated data too long"); } auto ciphertext = ind_cpa_cipher_->Encrypt(plaintext); if (!ciphertext.ok()) { return ciphertext.status(); } auto tag = mac_->ComputeMac( absl::StrCat(associated_data, *ciphertext, longToBigEndianStr(associated_data_size_in_bits))); if (!tag.ok()) { return tag.status(); } if (tag->size() != tag_size_) { return util::Status(absl::StatusCode::kInternal, "invalid tag size"); } return ciphertext->append(tag.value()); } util::StatusOr EncryptThenAuthenticate::Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const { // BoringSSL expects a non-null pointer for associated_data, // regardless of whether the size is 0. associated_data = internal::EnsureStringNonNull(associated_data); if (ciphertext.size() < tag_size_) { return util::Status(absl::StatusCode::kInvalidArgument, "ciphertext too short"); } uint64_t associated_data_size_in_bytes = associated_data.size(); uint64_t associated_data_size_in_bits = associated_data_size_in_bytes * 8; if (associated_data_size_in_bits / 8 != associated_data_size_in_bytes /* overflow occured! */) { return util::Status(absl::StatusCode::kInvalidArgument, "additional data too long"); } auto payload = ciphertext.substr(0, ciphertext.size() - tag_size_); auto tag = ciphertext.substr(ciphertext.size() - tag_size_, tag_size_); auto verified = mac_->VerifyMac( tag, absl::StrCat(associated_data, payload, longToBigEndianStr(associated_data_size_in_bits))); if (!verified.ok()) { return verified; } auto pt = ind_cpa_cipher_->Decrypt(payload); if (!pt.ok()) { return pt.status(); } return pt.value(); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/encrypt_then_authenticate.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_ENCRYPT_THEN_AUTHENTICATE_H_ #define TINK_SUBTLE_ENCRYPT_THEN_AUTHENTICATE_H_ #include #include #include #include #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/mac.h" #include "tink/subtle/ind_cpa_cipher.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // This primitive performs an encrypt-then-Mac operation on plaintext and // associated data (ad). The Mac is computed over (ad || // ciphertext || size of ad). This implementation is based on // http://tools.ietf.org/html/draft-mcgrew-aead-aes-cbc-hmac-sha2-05. class EncryptThenAuthenticate : public Aead { public: static crypto::tink::util::StatusOr> New( std::unique_ptr ind_cpa_cipher, std::unique_ptr mac, uint8_t tag_size); // Encrypts 'plaintext' with 'associated_data'. The resulting ciphertext // allows for checking authenticity and integrity of associated_data (ad), but // does not guarantee its secrecy. // // The plaintext is encrypted with an IndCpaCipher, then MAC is computed over // (associated_data || ciphertext || t) where t is associated_data's length // in bits represented as 64-bit bigendian unsigned integer. The final // ciphertext format is (ind-cpa ciphertext || mac). crypto::tink::util::StatusOr Encrypt( absl::string_view plaintext, absl::string_view associated_data) const override; crypto::tink::util::StatusOr Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const override; private: static constexpr int kMinTagSizeInBytes = 10; EncryptThenAuthenticate(std::unique_ptr ind_cpa_cipher, std::unique_ptr mac, uint8_t tag_size) : ind_cpa_cipher_(std::move(ind_cpa_cipher)), mac_(std::move(mac)), tag_size_(tag_size) {} const std::unique_ptr ind_cpa_cipher_; const std::unique_ptr mac_; const uint8_t tag_size_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_ENCRYPT_THEN_AUTHENTICATE_H_ ================================================ FILE: cc/subtle/encrypt_then_authenticate_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/encrypt_then_authenticate.h" #include #include #include #include #include #include #include "gtest/gtest.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/subtle/aes_ctr_boringssl.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/hmac_boringssl.h" #include "tink/subtle/random.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace subtle { namespace { // Copied from // https://tools.ietf.org/html/draft-mcgrew-aead-aes-cbc-hmac-sha2-05. // We use CTR but the RFC uses CBC mode, so it's not possible to compare // plaintexts. However, the tests are still valueable to ensure that we correcly // compute HMAC over ciphertext and associated_data. struct TestVector { absl::string_view mac_key; absl::string_view enc_key; absl::string_view ciphertext; absl::string_view associated_data; HashType hash_type; int iv_size; int tag_size; }; constexpr TestVector test_vectors[] = { {"000102030405060708090a0b0c0d0e0f", "101112131415161718191a1b1c1d1e1f", "1af38c2dc2b96ffdd86694092341bc04" "c80edfa32ddf39d5ef00c0b468834279" "a2e46a1b8049f792f76bfe54b903a9c9" "a94ac9b47ad2655c5f10f9aef71427e2" "fc6f9b3f399a221489f16362c7032336" "09d45ac69864e3321cf82935ac4096c8" "6e133314c54019e8ca7980dfa4b9cf1b" "384c486f3a54c51078158ee5d79de59f" "bd34d848b3d69550a67646344427ade5" "4b8851ffb598f7f80074b9473c82e2db" "652c3fa36b0a7c5b3219fab3a30bc1c4", "546865207365636f6e64207072696e63" "69706c65206f66204175677573746520" "4b6572636b686f666673", HashType::SHA256, 16, 16}, {"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "1af38c2dc2b96ffdd86694092341bc04" "4affaaadb78c31c5da4b1b590d10ffbd" "3dd8d5d302423526912da037ecbcc7bd" "822c301dd67c373bccb584ad3e9279c2" "e6d12a1374b77f077553df829410446b" "36ebd97066296ae6427ea75c2e0846a1" "1a09ccf5370dc80bfecbad28c73f09b3" "a3b75e662a2594410ae496b2e2e6609e" "31e6e02cc837f053d21f37ff4f51950b" "be2638d09dd7a4930930806d0703b1f6" "4dd3b4c088a7f45c216839645b2012bf" "2e6269a8c56a816dbc1b267761955bc5", "546865207365636f6e64207072696e63" "69706c65206f66204175677573746520" "4b6572636b686f666673", HashType::SHA512, 16, 32}, }; util::StatusOr> createAead2( util::SecretData encryption_key, int iv_size, util::SecretData mac_key, uint8_t tag_size, HashType hash_type) { auto ind_cipher_res = AesCtrBoringSsl::New(std::move(encryption_key), iv_size); if (!ind_cipher_res.ok()) { return ind_cipher_res.status(); } auto mac_res = HmacBoringSsl::New(hash_type, tag_size, std::move(mac_key)); if (!mac_res.ok()) { return mac_res.status(); } auto cipher_res = EncryptThenAuthenticate::New( std::move(ind_cipher_res.value()), std::move(mac_res.value()), tag_size); if (!cipher_res.ok()) { return cipher_res.status(); } return std::move(cipher_res.value()); } util::StatusOr> createAead(int encryption_key_size, int iv_size, int mac_key_size, int tag_size, HashType hash_type) { util::SecretData encryption_key = Random::GetRandomKeyBytes(encryption_key_size); util::SecretData mac_key = Random::GetRandomKeyBytes(mac_key_size); return createAead2(std::move(encryption_key), iv_size, std::move(mac_key), tag_size, hash_type); } TEST(AesGcmBoringSslTest, testRfcVectors) { for (const TestVector& test : test_vectors) { util::SecretData mac_key = util::SecretDataFromStringView(test::HexDecodeOrDie(test.mac_key)); util::SecretData enc_key = util::SecretDataFromStringView(test::HexDecodeOrDie(test.enc_key)); std::string ct = test::HexDecodeOrDie(test.ciphertext); std::string associated_data = test::HexDecodeOrDie(test.associated_data); auto res = createAead2(std::move(enc_key), test.iv_size, std::move(mac_key), test.tag_size, test.hash_type); EXPECT_TRUE(res.ok()) << res.status(); auto cipher = std::move(res.value()); auto pt = cipher->Decrypt(ct, associated_data); EXPECT_TRUE(pt.ok()) << pt.status(); } } TEST(EncryptThenAuthenticateTest, testEncryptDecrypt) { int encryption_key_size = 16; int iv_size = 12; int mac_key_size = 16; int tag_size = 16; auto res = createAead(encryption_key_size, iv_size, mac_key_size, tag_size, HashType::SHA1); EXPECT_TRUE(res.ok()) << res.status(); auto cipher = std::move(res.value()); std::string message = "Some data to encrypt."; std::string associated_data = "Some associated data."; auto ct = cipher->Encrypt(message, associated_data); EXPECT_TRUE(ct.ok()) << ct.status(); EXPECT_EQ(ct.value().size(), message.size() + iv_size + tag_size); auto pt = cipher->Decrypt(ct.value(), associated_data); EXPECT_TRUE(pt.ok()) << pt.status(); EXPECT_EQ(pt.value(), message); } TEST(EncryptThenAuthenticateTest, testEncryptDecrypt_randomMessage) { int encryption_key_size = 16; int iv_size = 12; int mac_key_size = 16; int tag_size = 16; auto res = createAead(encryption_key_size, iv_size, mac_key_size, tag_size, HashType::SHA1); EXPECT_TRUE(res.ok()) << res.status(); auto cipher = std::move(res.value()); for (int i = 0; i < 256; i++) { std::string message = Random::GetRandomBytes(i); std::string associated_data = Random::GetRandomBytes(i); auto ct = cipher->Encrypt(message, associated_data); EXPECT_TRUE(ct.ok()) << ct.status(); EXPECT_EQ(ct.value().size(), message.size() + iv_size + tag_size); auto pt = cipher->Decrypt(ct.value(), associated_data); EXPECT_TRUE(pt.ok()) << pt.status(); EXPECT_EQ(pt.value(), message); } } TEST(AesCtrBoringSslTest, testMultipleEncrypt) { int encryption_key_size = 16; int iv_size = 12; int mac_key_size = 16; int tag_size = 16; auto res = createAead(encryption_key_size, iv_size, mac_key_size, tag_size, HashType::SHA1); EXPECT_TRUE(res.ok()) << res.status(); auto cipher = std::move(res.value()); std::string message = Random::GetRandomBytes(20); std::string associated_data = Random::GetRandomBytes(20); auto ct1 = cipher->Encrypt(message, associated_data); auto ct2 = cipher->Encrypt(message, associated_data); EXPECT_NE(ct1.value(), ct2.value()); } TEST(EncryptThenAuthenticateTest, testEncryptDecrypt_invalidTagSize) { int encryption_key_size = 16; int iv_size = 12; int mac_key_size = 16; int tag_size = 9; auto res = createAead(encryption_key_size, iv_size, mac_key_size, tag_size, HashType::SHA1); EXPECT_FALSE(res.ok()) << res.status(); } TEST(EncryptThenAuthenticateTest, testDecrypt_modifiedCiphertext) { int encryption_key_size = 16; int iv_size = 12; int mac_key_size = 16; int tag_size = 16; auto res = createAead(encryption_key_size, iv_size, mac_key_size, tag_size, HashType::SHA1); EXPECT_TRUE(res.ok()) << res.status(); auto cipher = std::move(res.value()); std::string message = "Some data to encrypt."; std::string associated_data = "Some data to authenticate."; std::string ct = cipher->Encrypt(message, associated_data).value(); EXPECT_TRUE(cipher->Decrypt(ct, associated_data).ok()); // Modify the ciphertext for (size_t i = 0; i < ct.size() * 8; i++) { std::string modified_ct = ct; modified_ct[i / 8] ^= 1 << (i % 8); EXPECT_FALSE(cipher->Decrypt(modified_ct, associated_data).ok()) << i; } // Modify the associated data for (size_t i = 0; i < associated_data.size() * 8; i++) { std::string modified_associated_data = associated_data; modified_associated_data[i / 8] ^= 1 << (i % 8); auto decrypted = cipher->Decrypt(ct, modified_associated_data); EXPECT_FALSE(decrypted.ok()) << i << " pt:" << decrypted.value(); } // Truncate the ciphertext for (size_t i = 0; i < ct.size(); i++) { std::string truncated_ct(ct, 0, i); EXPECT_FALSE(cipher->Decrypt(truncated_ct, associated_data).ok()) << i; } } TEST(EncryptThenAuthenticateTest, testParamsEmptyVersusNullStringView) { int encryption_key_size = 16; int iv_size = 12; int mac_key_size = 16; int tag_size = 16; auto cipher = std::move(createAead(encryption_key_size, iv_size, mac_key_size, tag_size, HashType::SHA1) .value()); { // associated_data null string_view. const std::string message = "Some data to encrypt."; const absl::string_view associated_data; const std::string ct = cipher->Encrypt(message, "").value(); EXPECT_TRUE(cipher->Decrypt(ct, associated_data).ok()); } { // Both message and associated_data null string_view. const absl::string_view message; const absl::string_view associated_data; const std::string ct = cipher->Encrypt(message, "").value(); EXPECT_TRUE(cipher->Decrypt(ct, associated_data).ok()); } } // EncryptThenAuthenticate computes the MAC over associated_data || ciphertext // || associated_data_size_in_bits, where associated_data_size_in_bits = // associated_data.size() * 8 [1]. associated_data.size() returns a size_t which // is usually unsigned long or unsigned long long. On 32-bit machines (and maybe // others), long is 32-bit int. If associated_data.size() returns a number equal // to or larger than 2^29, an overflow will occur when multiplying with 8 to get // the size in bits. This leads to an authentication bypass vulnerability. This // test ensures that the overflow issue and the auth bypass vulnerability are // fixed. TEST(EncryptThenAuthenticateTest, testAuthBypassShouldNotWork) { int encryption_key_size = 16; int iv_size = 12; int mac_key_size = 16; int tag_size = 16; auto cipher = std::move(createAead(encryption_key_size, iv_size, mac_key_size, tag_size, HashType::SHA1) .value()); // Encrypt a message... const std::string message = "Some data to encrypt."; // ...with a long associated_data whose size in bits converted to an unsigned // 32-bit integer is 0. std::string associated_data; constexpr size_t kAssociatedDataSize = 1 << 29; constexpr size_t kCiphertextSpace = 1000; associated_data.reserve(kAssociatedDataSize + kCiphertextSpace); associated_data.resize(kAssociatedDataSize, 'a'); auto encrypted = cipher->Encrypt(message, associated_data); EXPECT_TRUE(encrypted.ok()) << encrypted.status(); auto ct = encrypted.value(); auto decrypted = cipher->Decrypt(ct, associated_data); EXPECT_TRUE(decrypted.ok()) << decrypted.status(); // Test that the 2^29-byte associated_data is NOT considered equal to an empty // associated_data. That is, test that a valid tag for (ciphertext, // associated_data) is INVALID for (associated_data + ciphertext, ""). ct = std::move(associated_data) + ct; decrypted = cipher->Decrypt(ct, ""); EXPECT_FALSE(decrypted.ok()); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/hkdf.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/hkdf.h" #include #include #include #include "absl/algorithm/container.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "openssl/evp.h" // BoringSSL and OpenSSL have incompatible ways to compute HKDF: BoringSSL // provides a one-shot API HKDF, while OpenSSL doesn't make that API public, but // instead provides this functionality over the EVP interface, which in turn // doesn't provide means to compute HKDF in BoringSSL. As a consequence, we need // to selectively include the correct header and use different implementations. #ifdef OPENSSL_IS_BORINGSSL #include "openssl/base.h" #include "openssl/hkdf.h" #else #include "openssl/kdf.h" #endif #include "tink/internal/md_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/subtle_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { namespace { // Compute HKDF using `evp_md` hashing, key `ikm`, salt `salt` and info `info`. // The result is written to `key`. util::Status SslHkdf(const EVP_MD *evp_md, absl::string_view ikm, absl::string_view salt, absl::string_view info, absl::Span out_key) { const uint8_t *ikm_ptr = reinterpret_cast(ikm.data()); const uint8_t *salt_ptr = reinterpret_cast(salt.data()); const uint8_t *info_ptr = reinterpret_cast(info.data()); #ifdef OPENSSL_IS_BORINGSSL if (HKDF(out_key.data(), out_key.size(), evp_md, ikm_ptr, ikm.size(), salt_ptr, salt.size(), info_ptr, info.size()) != 1) { return util::Status(absl::StatusCode::kInternal, "HKDF failed"); } return util::OkStatus(); #else internal::SslUniquePtr pctx( EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, /*e=*/nullptr)); if (pctx == nullptr || EVP_PKEY_derive_init(pctx.get()) <= 0 || EVP_PKEY_CTX_set_hkdf_md(pctx.get(), evp_md) <= 0 || EVP_PKEY_CTX_set1_hkdf_salt(pctx.get(), salt_ptr, salt.size()) <= 0 || EVP_PKEY_CTX_set1_hkdf_key(pctx.get(), ikm_ptr, ikm.size()) <= 0 || EVP_PKEY_CTX_add1_hkdf_info(pctx.get(), info_ptr, info.size()) <= 0) { return util::Status(absl::StatusCode::kInternal, "EVP_PKEY_CTX setup failed"); } size_t output_length = out_key.size(); if (EVP_PKEY_derive(pctx.get(), out_key.data(), &output_length) <= 0) { return util::Status(absl::StatusCode::kInternal, "HKDF failed"); } return util::OkStatus(); #endif } } // namespace util::StatusOr Hkdf::ComputeHkdf(HashType hash, const util::SecretData &ikm, absl::string_view salt, absl::string_view info, size_t out_len) { util::StatusOr evp_md = internal::EvpHashFromHashType(hash); if (!evp_md.ok()) { return evp_md.status(); } util::SecretData out_key(out_len); util::Status result = SslHkdf(*evp_md, util::SecretDataAsStringView(ikm), salt, info, absl::MakeSpan(out_key.data(), out_key.size())); if (!result.ok()) { return result; } return out_key; } util::StatusOr Hkdf::ComputeHkdf(HashType hash, absl::string_view ikm, absl::string_view salt, absl::string_view info, size_t out_len) { util::StatusOr evp_md = internal::EvpHashFromHashType(hash); if (!evp_md.ok()) { return evp_md.status(); } std::string out_key; ResizeStringUninitialized(&out_key, out_len); util::Status result = SslHkdf( *evp_md, ikm, salt, info, absl::MakeSpan(reinterpret_cast(&out_key[0]), out_key.size())); if (!result.ok()) { return result; } return out_key; } util::StatusOr Hkdf::ComputeEciesHkdfSymmetricKey( HashType hash, absl::string_view kem_bytes, const util::SecretData &shared_secret, absl::string_view salt, absl::string_view info, size_t out_len) { util::SecretData ikm(kem_bytes.size() + shared_secret.size()); absl::c_copy(kem_bytes, ikm.begin()); absl::c_copy(shared_secret, ikm.begin() + kem_bytes.size()); return Hkdf::ComputeHkdf(hash, ikm, salt, info, out_len); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/hkdf.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_HKDF_H_ #define TINK_SUBTLE_HKDF_H_ #include #include #include "absl/strings/string_view.h" #include "tink/subtle/common_enums.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // TODO(wiktorg) delete non-SecretData variant once all clients are migrated class Hkdf { public: // Computes hkdf according to RFC5869. static crypto::tink::util::StatusOr ComputeHkdf( HashType hash, absl::string_view ikm, absl::string_view salt, absl::string_view info, size_t out_len); static crypto::tink::util::StatusOr ComputeHkdf( HashType hash, const util::SecretData& ikm, absl::string_view salt, absl::string_view info, size_t out_len); // Computes symmetric key for ECIES with HKDF from the provided parameters. // This function follows Shoup's recommendation of including ECIES // ephemeral KEM bytes into the commputation of the symmetric key // (cf. http://eprint.iacr.org/2001/112.pdf, Sections 15.6 and 15.6.1) static crypto::tink::util::StatusOr ComputeEciesHkdfSymmetricKey(HashType hash, absl::string_view kem_bytes, const util::SecretData& shared_secret, absl::string_view salt, absl::string_view info, size_t out_len); }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_HKDF_H_ ================================================ FILE: cc/subtle/hkdf_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/hkdf.h" #include #include #include #include "gtest/gtest.h" #include "absl/strings/escaping.h" #include "tink/subtle/common_enums.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { namespace { class HkdfTest : public ::testing::Test {}; struct TestVector { HashType hash_type; std::string ikm_hex; std::string salt_hex; std::string info_hex; size_t out_len; std::string out_key_hex; }; // Tests vectors from RFC 5869. static const std::vector test_vector( {{ HashType::SHA256, "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "000102030405060708090a0b0c", "f0f1f2f3f4f5f6f7f8f9", 42, "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007" "208" "d5b887185865", }, { HashType::SHA256, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" "404142434445464748494a4b4c4d4e4f", "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecf" "d0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeef" "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", 82, "b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c" "59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71" "cc30c58179ec3e87c14c01d5c1f3434f1d87", }, {HashType::SHA256, "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "", "", 42, "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d" "9d201395faa4b61a96c8"}, {HashType::SHA1, "0b0b0b0b0b0b0b0b0b0b0b", "000102030405060708090a0b0c", "f0f1f2f3f4f5f6f7f8f9", 42, "085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e4224" "78d305f3f896"}, {HashType::SHA1, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" "404142434445464748494a4b4c4d4e4f", "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecf" "d0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeef" "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", 82, "0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe" "8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e" "927336d0441f4c4300e2cff0d0900b52d3b4"}, {HashType::SHA1, "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "", "", 42, "0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0" "ea00033de03984d34918"}}); TEST_F(HkdfTest, testBasic) { for (const TestVector& test : test_vector) { auto hkdf_or = Hkdf::ComputeHkdf(test.hash_type, absl::HexStringToBytes(test.ikm_hex), absl::HexStringToBytes(test.salt_hex), absl::HexStringToBytes(test.info_hex), test.out_len); ASSERT_TRUE(hkdf_or.ok()); EXPECT_EQ(absl::BytesToHexString(hkdf_or.value()), test.out_key_hex); } } TEST_F(HkdfTest, testBasicSecretData) { for (const TestVector& test : test_vector) { auto hkdf_or = Hkdf::ComputeHkdf( test.hash_type, util::SecretDataFromStringView(absl::HexStringToBytes(test.ikm_hex)), absl::HexStringToBytes(test.salt_hex), absl::HexStringToBytes(test.info_hex), test.out_len); ASSERT_TRUE(hkdf_or.ok()); EXPECT_EQ( absl::BytesToHexString(util::SecretDataAsStringView(hkdf_or.value())), test.out_key_hex); } } TEST_F(HkdfTest, testLongOutput) { TestVector test = test_vector[0]; auto status_or_string = Hkdf::ComputeHkdf(test.hash_type, absl::HexStringToBytes(test.ikm_hex), absl::HexStringToBytes(test.salt_hex), absl::HexStringToBytes(test.info_hex), 255 * 32 + 1 /* 255 * hashLength + 1 */); EXPECT_FALSE(status_or_string.ok()); EXPECT_EQ(status_or_string.status().message(), "HKDF failed"); } TEST_F(HkdfTest, ComputeEciesHkdfSecretData) { for (const TestVector& test : test_vector) { std::string ikm = absl::HexStringToBytes(test.ikm_hex); std::string kem_bytes = ikm.substr(0, ikm.size() / 2); util::SecretData shared_secret(ikm.begin() + ikm.size() / 2, ikm.end()); auto hkdf_or = Hkdf::ComputeEciesHkdfSymmetricKey( test.hash_type, kem_bytes, shared_secret, absl::HexStringToBytes(test.salt_hex), absl::HexStringToBytes(test.info_hex), test.out_len); ASSERT_TRUE(hkdf_or.ok()); EXPECT_EQ( absl::BytesToHexString(util::SecretDataAsStringView(hkdf_or.value())), test.out_key_hex); } } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/hmac_boringssl.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/hmac_boringssl.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "openssl/crypto.h" #include "openssl/evp.h" #include "openssl/hmac.h" #include "tink/internal/fips_utils.h" #include "tink/internal/md_util.h" #include "tink/internal/util.h" #include "tink/mac.h" #include "tink/subtle/common_enums.h" #include "tink/util/errors.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { util::StatusOr> HmacBoringSsl::New(HashType hash_type, uint32_t tag_size, util::SecretData key) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) return status; util::StatusOr md = internal::EvpHashFromHashType(hash_type); if (!md.ok()) { return md.status(); } if (EVP_MD_size(*md) < tag_size) { // The key manager is responsible to security policies. // The checks here just ensure the preconditions of the primitive. // If this fails then something is wrong with the key manager. return util::Status(absl::StatusCode::kInvalidArgument, "invalid tag size"); } if (key.size() < kMinKeySize) { return util::Status(absl::StatusCode::kInvalidArgument, "invalid key size"); } return {absl::WrapUnique(new HmacBoringSsl(*md, tag_size, std::move(key)))}; } util::StatusOr HmacBoringSsl::ComputeMac( absl::string_view data) const { // BoringSSL expects a non-null pointer for data, // regardless of whether the size is 0. data = internal::EnsureStringNonNull(data); uint8_t buf[EVP_MAX_MD_SIZE]; unsigned int out_len; const uint8_t* res = HMAC(md_, key_.data(), key_.size(), reinterpret_cast(data.data()), data.size(), buf, &out_len); if (res == nullptr) { // TODO(bleichen): We expect that BoringSSL supports the // hashes that we use. Maybe we should have a status that indicates // such mismatches between expected and actual behaviour. return util::Status(absl::StatusCode::kInternal, "BoringSSL failed to compute HMAC"); } return std::string(reinterpret_cast(buf), tag_size_); } util::Status HmacBoringSsl::VerifyMac(absl::string_view mac, absl::string_view data) const { // BoringSSL expects a non-null pointer for data, // regardless of whether the size is 0. data = internal::EnsureStringNonNull(data); if (mac.size() != tag_size_) { return util::Status(absl::StatusCode::kInvalidArgument, "incorrect tag size"); } uint8_t buf[EVP_MAX_MD_SIZE]; unsigned int out_len; const uint8_t* res = HMAC(md_, key_.data(), key_.size(), reinterpret_cast(data.data()), data.size(), buf, &out_len); if (res == nullptr) { return util::Status(absl::StatusCode::kInternal, "BoringSSL failed to compute HMAC"); } if (CRYPTO_memcmp(buf, mac.data(), tag_size_) != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "verification failed"); } return util::OkStatus(); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/hmac_boringssl.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_HMAC_BORINGSSL_H_ #define TINK_SUBTLE_HMAC_BORINGSSL_H_ #include #include #include #include #include #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "tink/internal/fips_utils.h" #include "tink/mac.h" #include "tink/subtle/common_enums.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { class HmacBoringSsl : public Mac { public: static crypto::tink::util::StatusOr> New( HashType hash_type, uint32_t tag_size, util::SecretData key); // Computes and returns the HMAC for 'data'. crypto::tink::util::StatusOr ComputeMac( absl::string_view data) const override; // Verifies if 'mac' is a correct HMAC for 'data'. // Returns Status::OK if 'mac' is correct, and a non-OK-Status otherwise. crypto::tink::util::Status VerifyMac( absl::string_view mac, absl::string_view data) const override; static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kRequiresBoringCrypto; private: // Minimum HMAC key size in bytes. static constexpr size_t kMinKeySize = 16; HmacBoringSsl(const EVP_MD* md, uint32_t tag_size, util::SecretData key) : md_(md), tag_size_(tag_size), key_(std::move(key)) {} // HmacBoringSsl is not owner of md (it is owned by BoringSSL). const EVP_MD* const md_; const uint32_t tag_size_; const util::SecretData key_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_HMAC_BORINGSSL_H_ ================================================ FILE: cc/subtle/hmac_boringssl_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/hmac_boringssl.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/string_view.h" #include "tink/internal/fips_utils.h" #include "tink/mac.h" #include "tink/subtle/common_enums.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::StatusIs; class HmacBoringSslTest : public ::testing::Test { public: // Utility to simplify testing with test vectors. // Arguments and result are hexadecimal. bool HmacVerifyHex(HashType hash, uint32_t tag_size, const std::string &key_hex, const std::string &tag_hex, const std::string &data_hex) { util::SecretData key = util::SecretDataFromStringView(absl::HexStringToBytes(key_hex)); std::string tag = absl::HexStringToBytes(tag_hex); std::string data = absl::HexStringToBytes(data_hex); auto hmac_result = HmacBoringSsl::New(hash, tag_size, key); EXPECT_TRUE(hmac_result.ok()) << hmac_result.status(); auto hmac = std::move(hmac_result.value()); auto result = hmac->VerifyMac(tag, data); return result.ok(); } }; TEST_F(HmacBoringSslTest, testBasic) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test should not run in FIPS mode when BoringCrypto is unavailable."; } util::SecretData key = util::SecretDataFromStringView( absl::HexStringToBytes("000102030405060708090a0b0c0d0e0f")); size_t tag_size = 16; auto hmac_result = HmacBoringSsl::New(HashType::SHA1, tag_size, key); EXPECT_TRUE(hmac_result.ok()) << hmac_result.status(); auto hmac = std::move(hmac_result.value()); { // Test with some example data. std::string data = "Some data to test."; auto res = hmac->ComputeMac(data); EXPECT_TRUE(res.ok()) << res.status(); std::string tag = res.value(); EXPECT_EQ(tag_size, tag.size()); EXPECT_EQ(tag, absl::HexStringToBytes("9ccdca5b7fffb690df396e4ac49b9cd4")); auto status = hmac->VerifyMac(tag, data); EXPECT_TRUE(status.ok()) << "tag:" << absl::BytesToHexString(tag) << " status:" << status; } { // Test with empty example data. absl::string_view data; auto res = hmac->ComputeMac(data); EXPECT_TRUE(res.ok()) << res.status(); std::string tag = res.value(); EXPECT_EQ(tag_size, tag.size()); EXPECT_EQ(tag, absl::HexStringToBytes("5433122f77bcf8a4d9b874b4149823ef")); auto status = hmac->VerifyMac(tag, data); EXPECT_TRUE(status.ok()) << "tag:" << absl::BytesToHexString(tag) << " status:" << status; } } TEST_F(HmacBoringSslTest, testModification) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test should not run in FIPS mode when BoringCrypto is unavailable."; } util::SecretData key = util::SecretDataFromStringView( absl::HexStringToBytes("000102030405060708090a0b0c0d0e0f")); auto hmac_result = HmacBoringSsl::New(HashType::SHA1, 16, key); EXPECT_TRUE(hmac_result.ok()) << hmac_result.status(); auto hmac = std::move(hmac_result.value()); std::string data = "Some data to test"; std::string tag = hmac->ComputeMac(data).value(); auto status = hmac->VerifyMac(tag, data); EXPECT_TRUE(status.ok()) << status; size_t bits = tag.size() * 8; for (size_t i = 0; i < bits; i++) { std::string modified_tag = tag; modified_tag[i / 8] ^= 1 << (i % 8); EXPECT_FALSE(hmac->VerifyMac(modified_tag, data).ok()) << "tag:" << absl::BytesToHexString(tag) << " modified:" << absl::BytesToHexString(modified_tag); } } TEST_F(HmacBoringSslTest, testTruncation) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test should not run in FIPS mode when BoringCrypto is unavailable."; } util::SecretData key = util::SecretDataFromStringView( absl::HexStringToBytes("000102030405060708090a0b0c0d0e0f")); auto hmac_result = HmacBoringSsl::New(HashType::SHA1, 20, key); EXPECT_TRUE(hmac_result.ok()) << hmac_result.status(); auto hmac = std::move(hmac_result.value()); std::string data = "Some data to test"; std::string tag = hmac->ComputeMac(data).value(); auto status = hmac->VerifyMac(tag, data); EXPECT_TRUE(status.ok()) << status; for (size_t i = 0; i < tag.size(); i++) { std::string modified_tag(tag, 0, i); EXPECT_FALSE(hmac->VerifyMac(modified_tag, data).ok()) << "tag:" << absl::BytesToHexString(tag) << " modified:" << absl::BytesToHexString(modified_tag); } } TEST_F(HmacBoringSslTest, testInvalidKeySizes) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test should not run in FIPS mode when BoringCrypto is unavailable."; } size_t tag_size = 16; for (int keysize = 0; keysize < 65; keysize++) { util::SecretData key(keysize, 'x'); auto hmac_result = HmacBoringSsl::New(HashType::SHA1, tag_size, key); if (keysize >= 16) { EXPECT_TRUE(hmac_result.ok()); } else { EXPECT_FALSE(hmac_result.ok()); } } } TEST_F(HmacBoringSslTest, TestFipsFailWithoutBoringCrypto) { if (!internal::IsFipsModeEnabled() || internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test assumes kOnlyUseFips but BoringCrypto is unavailable."; } util::SecretData key128 = util::SecretDataFromStringView( absl::HexStringToBytes("000102030405060708090a0b0c0d0e0f")); util::SecretData key256 = util::SecretDataFromStringView(absl::HexStringToBytes( "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f")); EXPECT_THAT(subtle::HmacBoringSsl::New(HashType::SHA1, 16, key128).status(), StatusIs(absl::StatusCode::kInternal)); EXPECT_THAT(subtle::HmacBoringSsl::New(HashType::SHA224, 16, key128).status(), StatusIs(absl::StatusCode::kInternal)); EXPECT_THAT(subtle::HmacBoringSsl::New(HashType::SHA256, 16, key128).status(), StatusIs(absl::StatusCode::kInternal)); EXPECT_THAT(subtle::HmacBoringSsl::New(HashType::SHA384, 16, key128).status(), StatusIs(absl::StatusCode::kInternal)); EXPECT_THAT(subtle::HmacBoringSsl::New(HashType::SHA512, 16, key128).status(), StatusIs(absl::StatusCode::kInternal)); } // TODO(bleichen): Stuff to test // - Generate test vectors and share with Wycheproof. // - Tag size wrong for construction // - Tag size wrong during verification // - Generate invalid tags with 0s in the middle to catch comparison with // strcmp or similar. // - Generate invalid tags with equal diffs (e.g. to catch broken constant // time comparisons. // - wrong size of tag during verification // - Hmac key size must not be 0 (see RFC) // - Generate test vectors with key sizes larger than the block size of the // hash. (HMAC hashes these keys). } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/hybrid_test_util.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/hybrid_test_util.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/hybrid_decrypt.h" #include "tink/hybrid_encrypt.h" #include "tink/util/status.h" namespace crypto { namespace tink { crypto::tink::util::Status HybridEncryptThenDecrypt( HybridEncrypt* encrypter, HybridDecrypt* decrypter, absl::string_view plaintext, absl::string_view context_info) { auto ciphertext = encrypter->Encrypt(plaintext, context_info); if (!ciphertext.ok()) return ciphertext.status(); auto decryption = decrypter->Decrypt(ciphertext.value(), context_info); if (!decryption.ok()) return decryption.status(); if (decryption.value() != plaintext) { return crypto::tink::util::Status(absl::StatusCode::kInvalidArgument, "decryption and encryption differ"); } return util::OkStatus(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/hybrid_test_util.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_HYBRID_TEST_UTIL_H_ #define TINK_SUBTLE_HYBRID_TEST_UTIL_H_ #include "absl/strings/string_view.h" #include "tink/hybrid_decrypt.h" #include "tink/hybrid_encrypt.h" #include "tink/util/status.h" // Encrypt with the encrypter, then decrypt with the decrypter. Returns OK if // the resulting decryption is equal to the plaintext. Errors are propagated. namespace crypto { namespace tink { crypto::tink::util::Status HybridEncryptThenDecrypt( HybridEncrypt* encrypter, HybridDecrypt* decrypter, absl::string_view plaintext, absl::string_view context_info); } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_HYBRID_TEST_UTIL_H_ ================================================ FILE: cc/subtle/hybrid_test_util_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/hybrid_test_util.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::DummyHybridDecrypt; using ::crypto::tink::test::DummyHybridEncrypt; using ::crypto::tink::test::IsOk; using ::testing::Not; TEST(EncryptThenDecrypt, Basic) { DummyHybridEncrypt hybrid_encrypt("Encrypt1"); DummyHybridDecrypt hybrid_decrypt("Encrypt1"); EXPECT_THAT(HybridEncryptThenDecrypt(&hybrid_encrypt, &hybrid_decrypt, "plaintext", "aad"), IsOk()); } TEST(EncryptThenDecrypt, Failing) { DummyHybridEncrypt hybrid_encrypt("Encrypt1"); DummyHybridDecrypt hybrid_decrypt("Encrypt2"); EXPECT_THAT(HybridEncryptThenDecrypt(&hybrid_encrypt, &hybrid_decrypt, "plaintext", "aad"), Not(IsOk())); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/ind_cpa_cipher.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_IND_CPA_CIPHER_H_ #define TINK_SUBTLE_IND_CPA_CIPHER_H_ #include #include "absl/strings/string_view.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { /////////////////////////////////////////////////////////////////////////////// // This interface for symmetric key ciphers that are indistinguishable against // chosen-plaintext attacks. Said primitives do not provide authentication, // thus should not be used directly, but only to construct safer primitives // such as Aead. class IndCpaCipher { public: // Encrypts 'plaintext'. The resulting ciphertext is indistinguishable under // chosen-plaintext attack. However, it does not have integrity protection. virtual crypto::tink::util::StatusOr Encrypt( absl::string_view plaintext) const = 0; // Decrypts 'ciphertext' and returns the resulting plaintext. virtual crypto::tink::util::StatusOr Decrypt( absl::string_view ciphertext) const = 0; virtual ~IndCpaCipher() = default; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_IND_CPA_CIPHER_H_ ================================================ FILE: cc/subtle/mac/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "stateful_mac", hdrs = ["stateful_mac.h"], include_prefix = "tink/subtle/mac", deps = [ "//util:status", "//util:statusor", "@com_google_absl//absl/strings", ], ) ================================================ FILE: cc/subtle/mac/CMakeLists.txt ================================================ tink_module(subtle::mac) tink_cc_library( NAME stateful_mac SRCS stateful_mac.h DEPS absl::strings tink::util::status tink::util::statusor ) ================================================ FILE: cc/subtle/mac/stateful_mac.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// // The interface for stateful message authentication codes. // // WARNING: implementations of this interface are thread-compatible, // but not thread-safe. Therefore, a streaming mac implemented with this // interface is required to additionally enforce thread safety. // // This interface supports the implementation of both streaming // and non-streaming MACs. It does not enforce thread-safety in order to avoid // an unnecessary performance overhead for non-streaming MAC implementations. #ifndef TINK_SUBTLE_MAC_STATEFUL_MAC_H_ #define TINK_SUBTLE_MAC_STATEFUL_MAC_H_ #include #include #include "absl/strings/string_view.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { class StatefulMac { public: StatefulMac() = default; virtual ~StatefulMac() = default; virtual util::Status Update(absl::string_view data) = 0; virtual util::StatusOr Finalize() = 0; }; class StatefulMacFactory { public: virtual ~StatefulMacFactory() = default; virtual util::StatusOr> Create() const = 0; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_MAC_STATEFUL_MAC_H_ ================================================ FILE: cc/subtle/nonce_based_streaming_aead.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/nonce_based_streaming_aead.h" #include #include #include "absl/strings/string_view.h" #include "tink/input_stream.h" #include "tink/output_stream.h" #include "tink/random_access_stream.h" #include "tink/streaming_aead.h" #include "tink/subtle/decrypting_random_access_stream.h" #include "tink/subtle/stream_segment_decrypter.h" #include "tink/subtle/stream_segment_encrypter.h" #include "tink/subtle/streaming_aead_decrypting_stream.h" #include "tink/subtle/streaming_aead_encrypting_stream.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { crypto::tink::util::StatusOr> NonceBasedStreamingAead::NewEncryptingStream( std::unique_ptr ciphertext_destination, absl::string_view associated_data) const { auto segment_encrypter_result = NewSegmentEncrypter(associated_data); if (!segment_encrypter_result.ok()) return segment_encrypter_result.status(); return StreamingAeadEncryptingStream::New( std::move(segment_encrypter_result.value()), std::move(ciphertext_destination)); } crypto::tink::util::StatusOr> NonceBasedStreamingAead::NewDecryptingStream( std::unique_ptr ciphertext_source, absl::string_view associated_data) const { auto segment_decrypter_result = NewSegmentDecrypter(associated_data); if (!segment_decrypter_result.ok()) return segment_decrypter_result.status(); return StreamingAeadDecryptingStream::New( std::move(segment_decrypter_result.value()), std::move(ciphertext_source)); } crypto::tink::util::StatusOr> NonceBasedStreamingAead::NewDecryptingRandomAccessStream( std::unique_ptr ciphertext_source, absl::string_view associated_data) const { auto segment_decrypter_result = NewSegmentDecrypter(associated_data); if (!segment_decrypter_result.ok()) return segment_decrypter_result.status(); return DecryptingRandomAccessStream::New( std::move(segment_decrypter_result.value()), std::move(ciphertext_source)); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/nonce_based_streaming_aead.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_NONCE_BASED_STREAMING_AEAD_H_ #define TINK_SUBTLE_NONCE_BASED_STREAMING_AEAD_H_ #include #include "absl/strings/string_view.h" #include "tink/input_stream.h" #include "tink/output_stream.h" #include "tink/random_access_stream.h" #include "tink/streaming_aead.h" #include "tink/subtle/stream_segment_decrypter.h" #include "tink/subtle/stream_segment_encrypter.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // An abstract class for StreamingAead using the nonce based online encryption // scheme proposed in "Online Authenticated-Encryption and its Nonce-Reuse // Misuse-Resistance" by Hoang, Reyhanitabar, Rogaway and Vizár // (https://eprint.iacr.org/2015/189.pdf) class NonceBasedStreamingAead : public StreamingAead { public: // Methods of StreamingAead-interface implemented by this class. crypto::tink::util::StatusOr> NewEncryptingStream( std::unique_ptr ciphertext_destination, absl::string_view associated_data) const override; crypto::tink::util::StatusOr> NewDecryptingStream( std::unique_ptr ciphertext_source, absl::string_view associated_data) const override; crypto::tink::util::StatusOr< std::unique_ptr> NewDecryptingRandomAccessStream( std::unique_ptr ciphertext_source, absl::string_view associated_data) const override; protected: // Methods to be implemented by a subclass of this class. // Returns a new StreamSegmentEncrypter that uses `associated_data` for AEAD. virtual crypto::tink::util::StatusOr> NewSegmentEncrypter(absl::string_view associated_data) const = 0; // Returns a new StreamSegmentDecrypter that uses `associated_data` for AEAD. virtual crypto::tink::util::StatusOr> NewSegmentDecrypter(absl::string_view associated_data) const = 0; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_NONCE_BASED_STREAMING_AEAD_H_ ================================================ FILE: cc/subtle/pem_parser_boringssl.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/pem_parser_boringssl.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "openssl/bio.h" #include "openssl/bn.h" #include "openssl/ec.h" #include "openssl/evp.h" #include "openssl/pem.h" #include "openssl/rsa.h" #include "tink/internal/bn_util.h" #include "tink/internal/ec_util.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/internal/ssl_util.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/subtle_util_boringssl.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { namespace { constexpr int kBsslOk = 1; // Verifies that the given RSA pointer `rsa_key` points to a valid RSA key. util::Status VerifyRsaKey(const RSA* rsa_key) { if (rsa_key == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid RSA key format"); } // Check the key parameters. if (RSA_check_key(rsa_key) != kBsslOk) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid RSA key format"); } return util::OkStatus(); } // Verifies that the given ECDSA pointer `ecdsa_key` points to a valid ECDSA // key. util::Status VerifyEcdsaKey(const EC_KEY* ecdsa_key) { if (ecdsa_key == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid ECDSA key format"); } // Check the key parameters. if (EC_KEY_check_key(ecdsa_key) != kBsslOk) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid ECDSA key format"); } return util::OkStatus(); } // Converts the public portion of a given SubtleUtilBoringSSL::EcKey, // `subtle_ec_key`, into an OpenSSL EC key, `openssl_ec_key`. util::Status EcKeyToSslEcPublicKey( const SubtleUtilBoringSSL::EcKey& subtle_ec_key, EC_KEY* openssl_ec_key) { if (openssl_ec_key == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "`openssl_ec_key` arg cannot be NULL"); } util::StatusOr> group = internal::EcGroupFromCurveType(subtle_ec_key.curve); if (!group.ok()) { return group.status(); } util::StatusOr> ec_point = internal::GetEcPoint(subtle_ec_key.curve, subtle_ec_key.pub_x, subtle_ec_key.pub_y); if (!ec_point.ok()) { return ec_point.status(); } // Set key's group and EC point. if (!EC_KEY_set_group(openssl_ec_key, group->get())) { return util::Status( absl::StatusCode::kInternal, absl::StrCat("Failed to set key group from EC group for curve ", EnumToString(subtle_ec_key.curve))); } if (!EC_KEY_set_public_key(openssl_ec_key, ec_point->get())) { return util::Status(absl::StatusCode::kInternal, "Failed to set public key"); } return util::OkStatus(); } // Converts a given SubtleUtilBoringSSL::EcKey, `subtle_ec_key`, into an OpenSSL // EC key, `openssl_ec_key`. util::Status EcKeyToSslEcPrivateKey( const SubtleUtilBoringSSL::EcKey& subtle_ec_key, EC_KEY* openssl_ec_key) { if (openssl_ec_key == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "`openssl_ec_key` arg cannot be NULL"); } util::Status status = EcKeyToSslEcPublicKey(subtle_ec_key, openssl_ec_key); if (!status.ok()) { return status; } util::StatusOr> x = internal::StringToBignum(absl::string_view( reinterpret_cast(subtle_ec_key.priv.data()), subtle_ec_key.priv.size())); if (!x.ok()) { return x.status(); } if (!EC_KEY_set_private_key(openssl_ec_key, x->get())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to set private key"); } return VerifyEcdsaKey(openssl_ec_key); } // Converts an OpenSSL BIO (i.e., basic IO stream), `bio`, into a string. util::StatusOr ConvertBioToString(BIO* bio) { BUF_MEM* mem = nullptr; BIO_get_mem_ptr(bio, &mem); std::string pem_material; if (mem->data && mem->length) { pem_material.assign(mem->data, mem->length); } if (pem_material.empty()) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to retrieve key material from BIO"); } return pem_material; } size_t ScalarSizeInBytes(const EC_GROUP* group) { return BN_num_bytes(EC_GROUP_get0_order(group)); } size_t FieldElementSizeInBytes(const EC_GROUP* group) { unsigned degree_bits = EC_GROUP_get_degree(group); return (degree_bits + 7) / 8; } // We explicitly set a failing passphrase callback function to make sure no // default callback routine is used. static int FailingPassphraseCallback(char* buf, int buf_size, int rwflag, void* u) { return -1; } } // namespace util::StatusOr> PemParser::ParseRsaPublicKey(absl::string_view pem_serialized_key) { // Read the RSA key into EVP_PKEY. internal::SslUniquePtr rsa_key_bio(BIO_new(BIO_s_mem())); BIO_write(rsa_key_bio.get(), pem_serialized_key.data(), pem_serialized_key.size()); internal::SslUniquePtr evp_rsa_key( PEM_read_bio_PUBKEY(rsa_key_bio.get(), /*x=*/nullptr, &FailingPassphraseCallback, /*u=*/nullptr)); if (evp_rsa_key == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "PEM Public Key parsing failed"); } // No need to free bssl_rsa_key after use. const RSA* bssl_rsa_key = EVP_PKEY_get0_RSA(evp_rsa_key.get()); util::Status verification_res = internal::RsaCheckPublicKey(bssl_rsa_key); if (!verification_res.ok()) { return verification_res; } // Get the public key parameters. const BIGNUM *n_bn, *e_bn, *d_bn; RSA_get0_key(bssl_rsa_key, &n_bn, &e_bn, &d_bn); // Public key should not have d_bn set. if (d_bn != nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid RSA Public Key format"); } // We are only interested in e and n. auto n_str = internal::BignumToString(n_bn, BN_num_bytes(n_bn)); auto e_str = internal::BignumToString(e_bn, BN_num_bytes(e_bn)); if (!n_str.ok()) { return n_str.status(); } if (!e_str.ok()) { return e_str.status(); } auto rsa_public_key = absl::make_unique(); rsa_public_key->e = *std::move(e_str); rsa_public_key->n = *std::move(n_str); return std::move(rsa_public_key); } util::StatusOr> PemParser::ParseRsaPrivateKey(absl::string_view pem_serialized_key) { // Read the private key into EVP_PKEY. internal::SslUniquePtr rsa_key_bio(BIO_new(BIO_s_mem())); BIO_write(rsa_key_bio.get(), pem_serialized_key.data(), pem_serialized_key.size()); // BoringSSL APIs to parse the PEM data. internal::SslUniquePtr evp_rsa_key( PEM_read_bio_PrivateKey(rsa_key_bio.get(), /*x=*/nullptr, &FailingPassphraseCallback, /*u=*/nullptr)); if (evp_rsa_key == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "PEM Private Key parsing failed"); } // No need to free bssl_rsa_key after use. const RSA* bssl_rsa_key = EVP_PKEY_get0_RSA(evp_rsa_key.get()); auto is_valid_key = VerifyRsaKey(bssl_rsa_key); if (!is_valid_key.ok()) { return is_valid_key; } const BIGNUM *n_bn, *e_bn, *d_bn; RSA_get0_key(bssl_rsa_key, &n_bn, &e_bn, &d_bn); // Save exponents. auto rsa_private_key = absl::make_unique(); auto n_str = internal::BignumToString(n_bn, BN_num_bytes(n_bn)); auto e_str = internal::BignumToString(e_bn, BN_num_bytes(e_bn)); auto d_str = internal::BignumToSecretData(d_bn, BN_num_bytes(d_bn)); if (!n_str.ok()) { return n_str.status(); } if (!e_str.ok()) { return e_str.status(); } if (!d_str.ok()) { return d_str.status(); } rsa_private_key->n = *std::move(n_str); rsa_private_key->e = *std::move(e_str); rsa_private_key->d = *std::move(d_str); // Save factors. const BIGNUM *p_bn, *q_bn; RSA_get0_factors(bssl_rsa_key, &p_bn, &q_bn); auto p_str = internal::BignumToSecretData(p_bn, BN_num_bytes(p_bn)); auto q_str = internal::BignumToSecretData(q_bn, BN_num_bytes(q_bn)); if (!p_str.ok()) { return p_str.status(); } if (!q_str.ok()) { return q_str.status(); } rsa_private_key->p = *std::move(p_str); rsa_private_key->q = *std::move(q_str); // Save CRT parameters. const BIGNUM *dp_bn, *dq_bn, *crt_bn; RSA_get0_crt_params(bssl_rsa_key, &dp_bn, &dq_bn, &crt_bn); auto dp_str = internal::BignumToSecretData(dp_bn, BN_num_bytes(dp_bn)); auto dq_str = internal::BignumToSecretData(dq_bn, BN_num_bytes(dq_bn)); auto crt_str = internal::BignumToSecretData(crt_bn, BN_num_bytes(crt_bn)); if (!dp_str.ok()) { return dp_str.status(); } if (!dq_str.ok()) { return dq_str.status(); } if (!crt_str.ok()) { return crt_str.status(); } rsa_private_key->dp = *std::move(dp_str); rsa_private_key->dq = *std::move(dq_str); rsa_private_key->crt = *std::move(crt_str); return std::move(rsa_private_key); } util::StatusOr PemParser::WriteRsaPublicKey( const internal::RsaPublicKey& rsa_public_key) { auto rsa_statusor = internal::RsaPublicKeyToRsa(rsa_public_key); if (!rsa_statusor.ok()) { return rsa_statusor.status(); } internal::SslUniquePtr rsa = *std::move(rsa_statusor); internal::SslUniquePtr bio(BIO_new(BIO_s_mem())); if (!PEM_write_bio_RSA_PUBKEY(bio.get(), rsa.get())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to write openssl RSA key to write bio"); } return ConvertBioToString(bio.get()); } util::StatusOr PemParser::WriteRsaPrivateKey( const internal::RsaPrivateKey& rsa_private_key) { auto rsa_statusor = internal::RsaPrivateKeyToRsa(rsa_private_key); if (!rsa_statusor.ok()) { return rsa_statusor.status(); } internal::SslUniquePtr rsa = *std::move(rsa_statusor); internal::SslUniquePtr evp(EVP_PKEY_new()); EVP_PKEY_set1_RSA(evp.get(), rsa.get()); internal::SslUniquePtr bio(BIO_new(BIO_s_mem())); if (!PEM_write_bio_PrivateKey(bio.get(), evp.get(), /*enc=*/nullptr, /*kstr=*/nullptr, /*klen=*/0, /*cb=*/nullptr, /*u=*/nullptr)) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to write openssl RSA key to write bio"); } return ConvertBioToString(bio.get()); } util::StatusOr> PemParser::ParseEcPublicKey(absl::string_view pem_serialized_key) { // Read the ECDSA key into EVP_PKEY. internal::SslUniquePtr ecdsa_key_bio(BIO_new(BIO_s_mem())); BIO_write(ecdsa_key_bio.get(), pem_serialized_key.data(), pem_serialized_key.size()); internal::SslUniquePtr evp_ecdsa_key( PEM_read_bio_PUBKEY(ecdsa_key_bio.get(), /*x=*/nullptr, &FailingPassphraseCallback, /*u=*/nullptr)); if (evp_ecdsa_key == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "PEM Public Key parsing failed"); } // No need to free bssl_ecdsa_key after use. const EC_KEY* bssl_ecdsa_key = EVP_PKEY_get0_EC_KEY(evp_ecdsa_key.get()); auto is_valid = VerifyEcdsaKey(bssl_ecdsa_key); if (!is_valid.ok()) { return is_valid; } // Get the public key parameters. const EC_POINT* public_point = EC_KEY_get0_public_key(bssl_ecdsa_key); const EC_GROUP* ec_group = EC_KEY_get0_group(bssl_ecdsa_key); internal::SslUniquePtr x_coordinate(BN_new()); internal::SslUniquePtr y_coordinate(BN_new()); EC_POINT_get_affine_coordinates(ec_group, public_point, x_coordinate.get(), y_coordinate.get(), nullptr); // Convert public key parameters and construct Subtle ECKey util::StatusOr x_string = internal::BignumToString( x_coordinate.get(), FieldElementSizeInBytes(ec_group)); if (!x_string.ok()) { return x_string.status(); } util::StatusOr y_string = internal::BignumToString( y_coordinate.get(), FieldElementSizeInBytes(ec_group)); if (!y_string.ok()) { return y_string.status(); } util::StatusOr curve = internal::CurveTypeFromEcGroup(ec_group); if (!curve.ok()) { return curve.status(); } auto ecdsa_public_key = absl::make_unique(); ecdsa_public_key->pub_x = *std::move(x_string); ecdsa_public_key->pub_y = *std::move(y_string); ecdsa_public_key->curve = *std::move(curve); return std::move(ecdsa_public_key); } util::StatusOr> PemParser::ParseEcPrivateKey(absl::string_view pem_serialized_key) { internal::SslUniquePtr ecdsa_key_bio(BIO_new(BIO_s_mem())); BIO_write(ecdsa_key_bio.get(), pem_serialized_key.data(), pem_serialized_key.size()); internal::SslUniquePtr evp_ecdsa_key( PEM_read_bio_PrivateKey(ecdsa_key_bio.get(), /*x=*/nullptr, &FailingPassphraseCallback, /*u=*/nullptr)); if (evp_ecdsa_key == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "PEM Private Key parsing failed"); } // No need to free bssl_ecdsa_key after use. const EC_KEY* bssl_ecdsa_key = EVP_PKEY_get0_EC_KEY(evp_ecdsa_key.get()); util::Status verify_result = VerifyEcdsaKey(bssl_ecdsa_key); if (!verify_result.ok()) { return verify_result; } internal::SslUniquePtr x_coordinate(BN_new()); internal::SslUniquePtr y_coordinate(BN_new()); const EC_POINT* public_point = EC_KEY_get0_public_key(bssl_ecdsa_key); const EC_GROUP* ec_group = EC_KEY_get0_group(bssl_ecdsa_key); EC_POINT_get_affine_coordinates(ec_group, public_point, x_coordinate.get(), y_coordinate.get(), nullptr); const BIGNUM* priv_key = EC_KEY_get0_private_key(bssl_ecdsa_key); util::StatusOr priv = internal::BignumToSecretData(priv_key, ScalarSizeInBytes(ec_group)); if (!priv.ok()) { return priv.status(); } util::StatusOr x_string = internal::BignumToString( x_coordinate.get(), FieldElementSizeInBytes(ec_group)); if (!x_string.ok()) { return x_string.status(); } util::StatusOr y_string = internal::BignumToString( y_coordinate.get(), FieldElementSizeInBytes(ec_group)); if (!y_string.ok()) { return y_string.status(); } util::StatusOr curve = internal::CurveTypeFromEcGroup(ec_group); if (!curve.ok()) { return curve.status(); } auto ecdsa_private_key = absl::make_unique(); ecdsa_private_key->pub_x = *std::move(x_string); ecdsa_private_key->pub_y = *std::move(y_string); ecdsa_private_key->priv = *std::move(priv); ecdsa_private_key->curve = *std::move(curve); return std::move(ecdsa_private_key); } util::StatusOr PemParser::WriteEcPublicKey( const SubtleUtilBoringSSL::EcKey& ec_key) { internal::SslUniquePtr openssl_ec_key(EC_KEY_new()); util::Status status = EcKeyToSslEcPublicKey(ec_key, openssl_ec_key.get()); if (!status.ok()) { return status; } internal::SslUniquePtr bio(BIO_new(BIO_s_mem())); if (!PEM_write_bio_EC_PUBKEY(bio.get(), openssl_ec_key.get())) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to write openssl EC key to write bio"); } return ConvertBioToString(bio.get()); } util::StatusOr PemParser::WriteEcPrivateKey( const SubtleUtilBoringSSL::EcKey& ec_key) { internal::SslUniquePtr openssl_ec_key(EC_KEY_new()); util::Status status = EcKeyToSslEcPrivateKey(ec_key, openssl_ec_key.get()); if (!status.ok()) { return status; } internal::SslUniquePtr bio(BIO_new(BIO_s_mem())); if (!PEM_write_bio_ECPrivateKey(bio.get(), openssl_ec_key.get(), /*enc=*/nullptr, /*kstr=*/nullptr, /*klen=*/0, /*cb=*/nullptr, /*u=*/nullptr)) { return util::Status(absl::StatusCode::kInvalidArgument, "Failed to write openssl EC key to write bio"); } return ConvertBioToString(bio.get()); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/pem_parser_boringssl.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_PEM_PARSER_BORINGSSL_H_ #define TINK_SUBTLE_PEM_PARSER_BORINGSSL_H_ #include #include #include "absl/strings/string_view.h" #include "tink/internal/rsa_util.h" #include "tink/subtle/subtle_util_boringssl.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // Parses keys in in PEM format (RFC 7468). // This is essentially a wrapper aroung BoringSSL APIs. class PemParser { public: // Parses a given PEM serialized RSA public key `pem_serialized_key` into a // internal::RsaPublicKey. static util::StatusOr> ParseRsaPublicKey(absl::string_view pem_serialized_key); // Parses a given PEM serialized RSA private key `pem_serialized_key` into a // internal::RsaPublicKey. static util::StatusOr> ParseRsaPrivateKey(absl::string_view pem_serialized_key); // Writes a given internal::RsaPublicKey `rsa_key` into a PEM // serialized RSA public key. static util::StatusOr WriteRsaPublicKey( const internal::RsaPublicKey& rsa_public_key); // Writes a given internal::RsaPrivateKey `rsa_key` into a PEM // serialized RSA private key. static util::StatusOr WriteRsaPrivateKey( const internal::RsaPrivateKey& rsa_private_key); // Parses a given PEM serialized EC public key `pem_serialized_key` into a // SubtleUtilBoringSSL::EcKey. static util::StatusOr> ParseEcPublicKey(absl::string_view pem_serialized_key); // Parses a given PEM serialized EC private key `pem_serialized_key` into a // SubtleUtilBoringSSL::EcKey. static util::StatusOr> ParseEcPrivateKey(absl::string_view pem_serialized_key); // Writes a given SubtleUtilBoringSSL::EcKey `ec_key` into a PEM serialized // EC public key. static util::StatusOr WriteEcPublicKey( const SubtleUtilBoringSSL::EcKey& ec_key); // Writes a given SubtleUtilBoringSSL::EcKey `ec_key` into a PEM serialized // EC private key. static util::StatusOr WriteEcPrivateKey( const SubtleUtilBoringSSL::EcKey& ec_key); }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_PEM_PARSER_BORINGSSL_H_ ================================================ FILE: cc/subtle/pem_parser_boringssl_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/pem_parser_boringssl.h" #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/ascii.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "openssl/bio.h" #include "openssl/bn.h" #include "openssl/evp.h" #include "openssl/pem.h" #include "openssl/rsa.h" #include "tink/internal/bn_util.h" #include "tink/internal/err_util.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/internal/ssl_util.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/subtle_util_boringssl.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::Not; using ::testing::NotNull; using ::testing::Test; using ::testing::TestWithParam; using ::testing::ValuesIn; // Test vectors for ECDSA were generated using the `openssl` command. // // 1. Generate private PEM file. In the command below, the following values were // used for the -name flag: {prime256v1, secp384r1, secp521r1}. // // $ openssl ecparam -genkey -name prime256v1 -noout -out ec-key-pair.pem // // 2. Generate public PEM file from private PEM file. // // $ openssl ec -in ec-key-pair.pem -pubout -out pub.pem // // 3. Print public X, Y and private key components. The public component is // obtained by removing the leading "04" character (which indicates that the key // is not compressed) and splitting the remaning bytes in two. The first half is // X and the 2nd half is Y. // // $ openssl ec -in ec-key-pair.pem -text -param_enc explicit -noout struct EcKeyTestVector { // EC format subtle::EllipticCurveType curve; std::string pub_x_hex_str; std::string pub_y_hex_str; std::string priv_hex_str; // PEM format std::string pub_pem; std::string priv_pem; }; std::vector GetEcKeyTestVectors() { return { { /*.curve=*/subtle::NIST_P256, /*.pub_x_hex_str=*/ "1455cfd594d44df125f1ff643636740c6cc59972091fee6fa9b8d3897d59b0e0", /*.pub_y_hex_str=*/ "d0b655238d8c0cebbfde77b1fda62ad19ccc6bf25a4ebf5637d3597983094363", /*.priv_hex_str=*/ "8485FB768E109D14BE1E219D4D806523308E0E401DB1DE95DC938E8903C49B2C", /*.pub_pem=*/R"(-----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFFXP1ZTUTfEl8f9kNjZ0DGzFmXIJ H+5vqbjTiX1ZsODQtlUjjYwM67/ed7H9pirRnMxr8lpOv1Y301l5gwlDYw== -----END PUBLIC KEY-----)", /*.priv_pem=*/R"(-----BEGIN EC PRIVATE KEY----- MHcCAQEEIISF+3aOEJ0Uvh4hnU2AZSMwjg5AHbHeldyTjokDxJssoAoGCCqGSM49 AwEHoUQDQgAEFFXP1ZTUTfEl8f9kNjZ0DGzFmXIJH+5vqbjTiX1ZsODQtlUjjYwM 67/ed7H9pirRnMxr8lpOv1Y301l5gwlDYw== -----END EC PRIVATE KEY-----)", }, { /*.curve=*/subtle::NIST_P256, /*.pub_x_hex_str=*/ "ee21893b340260360f1ae3d26bf0a066eadc8c63690b2f1de308220800d9d1ab", /*.pub_y_hex_str=*/ "d334a5917d2be49475af2454feea41d4418ea99eec791d1a0cc1c2890f8b33ee", /*.priv_hex_str=*/ "cac853f79a95c7d8697d0469ccda4faf940d80d1e0c81ffa0e6082ed9a85654b", /*.pub_pem=*/R"(-----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7iGJOzQCYDYPGuPSa/CgZurcjGNp Cy8d4wgiCADZ0avTNKWRfSvklHWvJFT+6kHUQY6pnux5HRoMwcKJD4sz7g== -----END PUBLIC KEY-----)", /*.priv_pem=*/R"(-----BEGIN EC PRIVATE KEY----- MHcCAQEEIMrIU/ealcfYaX0EaczaT6+UDYDR4Mgf+g5ggu2ahWVLoAoGCCqGSM49 AwEHoUQDQgAE7iGJOzQCYDYPGuPSa/CgZurcjGNpCy8d4wgiCADZ0avTNKWRfSvk lHWvJFT+6kHUQY6pnux5HRoMwcKJD4sz7g== -----END EC PRIVATE KEY-----)", }, { // example EcKey with a pub_x with a leading zero. /*.curve=*/subtle::NIST_P256, /*.pub_x_hex_str=*/ "00b02778da7b7bfd7094c36f847eb32b3077547da49c8ecf667f7acc3145693c", /*.pub_y_hex_str=*/ "710f3044af1cfe55f10d75de077297f7f2745cf2cd6cd4306f2aa72e367f7331", /*.priv_hex_str=*/ "f4b9b38fd2817527e5b6ef7910bce594f06d87990f31a2e9005594951e2a2f2f", /*.pub_pem=*/R"(-----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEALAneNp7e/1wlMNvhH6zKzB3VH2k nI7PZn96zDFFaTxxDzBErxz+VfENdd4Hcpf38nRc8s1s1DBvKqcuNn9zMQ== -----END PUBLIC KEY-----)", /*.priv_pem=*/R"(-----BEGIN EC PRIVATE KEY----- MHcCAQEEIPS5s4/SgXUn5bbveRC85ZTwbYeZDzGi6QBVlJUeKi8voAoGCCqGSM49 AwEHoUQDQgAEALAneNp7e/1wlMNvhH6zKzB3VH2knI7PZn96zDFFaTxxDzBErxz+ VfENdd4Hcpf38nRc8s1s1DBvKqcuNn9zMQ== -----END EC PRIVATE KEY-----)", }, { // example EcKey with a priv with a leading zero. /*.curve=*/subtle::NIST_P256, /*.pub_x_hex_str=*/ "8b348ef165b90ea991c28f254a5caed293e42d6c64fa2db1f3991c007442bf68", /*.pub_y_hex_str=*/ "2d45951a61ac6f99d9c6745fe129e86c74001d3c13f506f9bb2d10fd492069b4", /*.priv_hex_str=*/ "006484950d48016cc524078de3e3216258d2bc563f2318cc49f0301059f5fd61", /*.pub_pem=*/R"(-----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEizSO8WW5DqmRwo8lSlyu0pPkLWxk +i2x85kcAHRCv2gtRZUaYaxvmdnGdF/hKehsdAAdPBP1Bvm7LRD9SSBptA== -----END PUBLIC KEY-----)", /*.priv_pem=*/R"(-----BEGIN EC PRIVATE KEY----- MHcCAQEEIABkhJUNSAFsxSQHjePjIWJY0rxWPyMYzEnwMBBZ9f1hoAoGCCqGSM49 AwEHoUQDQgAEizSO8WW5DqmRwo8lSlyu0pPkLWxk+i2x85kcAHRCv2gtRZUaYaxv mdnGdF/hKehsdAAdPBP1Bvm7LRD9SSBptA== -----END EC PRIVATE KEY-----)", }, { /*.curve=*/subtle::NIST_P384, /*.pub_x_hex_str=*/ "49b1a78537281c81984e00092f04c22c610cac2aba7a3de992bf6ad22305d2d54501" "87" "57ed823c643334e18d95b2e642", /*.pub_y_hex_str=*/ "d2a851445c5da0bf0d543eaad5ff98634483c549d96045243121ed6d5c9ba64dab65" "6a" "6d25e018b01c4d3ab3f1738989", /*.priv_hex_str=*/ "0254cd5840eec13b0d68ba08fdbc147c22906046ecb2fca2625294be74dea29aa370" "fd" "830985d278099644ecf89167cd", /*.pub_pem=*/R"(-----BEGIN PUBLIC KEY----- MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAESbGnhTcoHIGYTgAJLwTCLGEMrCq6ej3p kr9q0iMF0tVFAYdX7YI8ZDM04Y2VsuZC0qhRRFxdoL8NVD6q1f+YY0SDxUnZYEUk MSHtbVybpk2rZWptJeAYsBxNOrPxc4mJ -----END PUBLIC KEY-----)", /*.priv_pem=*/R"(-----BEGIN EC PRIVATE KEY----- MIGkAgEBBDACVM1YQO7BOw1ougj9vBR8IpBgRuyy/KJiUpS+dN6imqNw/YMJhdJ4 CZZE7PiRZ82gBwYFK4EEACKhZANiAARJsaeFNygcgZhOAAkvBMIsYQysKrp6PemS v2rSIwXS1UUBh1ftgjxkMzThjZWy5kLSqFFEXF2gvw1UPqrV/5hjRIPFSdlgRSQx Ie1tXJumTatlam0l4BiwHE06s/FziYk= -----END EC PRIVATE KEY-----)", }, { /*.curve=*/subtle::NIST_P384, /*.pub_x_hex_str=*/ "82de2530a8d589149c8a60fdd529ed7a465db62d7412771a7ec40a69be139226b609" "06" "cc784007d8e28a79dca528e66c", /*.pub_y_hex_str=*/ "c41f7532b8325aad3f1dddebddb702ebe70259bb5730e6bc4a75baec0d85c52d0d00" "c8" "e372d1da0d1ca10136e4cfd262", /*.priv_hex_str=*/ "a6a8415b526418966758cfda45c19b4fe0ac4cf06d301b195ffea231d0eda67a54fb" "7c" "bc12470296e29e86359de53aee", /*.pub_pem=*/R"(-----BEGIN PUBLIC KEY----- MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEgt4lMKjViRScimD91SntekZdti10Enca fsQKab4Tkia2CQbMeEAH2OKKedylKOZsxB91MrgyWq0/Hd3r3bcC6+cCWbtXMOa8 SnW67A2FxS0NAMjjctHaDRyhATbkz9Ji -----END PUBLIC KEY-----)", /*.priv_pem=*/R"(-----BEGIN EC PRIVATE KEY----- MIGkAgEBBDCmqEFbUmQYlmdYz9pFwZtP4KxM8G0wGxlf/qIx0O2melT7fLwSRwKW 4p6GNZ3lOu6gBwYFK4EEACKhZANiAASC3iUwqNWJFJyKYP3VKe16Rl22LXQSdxp+ xAppvhOSJrYJBsx4QAfY4op53KUo5mzEH3UyuDJarT8d3evdtwLr5wJZu1cw5rxK dbrsDYXFLQ0AyONy0doNHKEBNuTP0mI= -----END EC PRIVATE KEY-----)", }, { /*.curve=*/subtle::NIST_P521, /*.pub_x_hex_str=*/ "01d09ee2f33ce601d8594b09e668e128a7708ce752ef589d1a2c405523db0b68a0cb" "58" "60359b12c5371fc462f4142339ca7ff2550833f0a64887951ddb64e7d139d5", /*.pub_y_hex_str=*/ "01b45ce12804afcf17fbd60728d362d4787b750d561e52144fd517807ddaa2b396be" "d9" "98227a5696d9c997a1cf0b6f1a3724ce25c7396dc2ea62c4bdf467061916e3", /*.priv_hex_str=*/ "01f1913a921271c06686482a51dbf2c853aefbcc62b2b23d473a4c818d570e555667" "42" "edd9f05d0532f73d40c11d3d31c3734e4470cc0491ad911a209f1e88dcd712", /*.pub_pem=*/R"(-----BEGIN PUBLIC KEY----- MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQB0J7i8zzmAdhZSwnmaOEop3CM51Lv WJ0aLEBVI9sLaKDLWGA1mxLFNx/EYvQUIznKf/JVCDPwpkiHlR3bZOfROdUBtFzh KASvzxf71gco02LUeHt1DVYeUhRP1ReAfdqis5a+2ZgielaW2cmXoc8Lbxo3JM4l xzltwupixL30ZwYZFuM= -----END PUBLIC KEY-----)", /*.priv_pem=*/R"(-----BEGIN EC PRIVATE KEY----- MIHcAgEBBEIB8ZE6khJxwGaGSCpR2/LIU677zGKysj1HOkyBjVcOVVZnQu3Z8F0F Mvc9QMEdPTHDc05EcMwEka2RGiCfHojc1xKgBwYFK4EEACOhgYkDgYYABAHQnuLz POYB2FlLCeZo4SincIznUu9YnRosQFUj2wtooMtYYDWbEsU3H8Ri9BQjOcp/8lUI M/CmSIeVHdtk59E51QG0XOEoBK/PF/vWByjTYtR4e3UNVh5SFE/VF4B92qKzlr7Z mCJ6VpbZyZehzwtvGjckziXHOW3C6mLEvfRnBhkW4w== -----END EC PRIVATE KEY-----)", }, { /*.curve=*/subtle::NIST_P521, /*.pub_x_hex_str=*/ "0108803f92f8449fdfca02c8c2b49643f407f63dda728ad38e3598b887b5831ab063" "d9" "60c5fd321ee597f4273fc0596015ce406515a2ab24a7c96a44802d74c3ac7b", /*.pub_y_hex_str=*/ "01f216dc0f590b920d9c026e0aedc2b1cfe85d4f2d607db632395c7f64c053285936" "33" "635b6ad8bf51d2ee70c88000e96fd340601211c1d1eb0b32773806506b47b0", /*.priv_hex_str=*/ "0010a207e650cf531c98c0c6d1cfdb88a5ee57f02734cbab93b8ae30d9dac0845d17" "61" "9be33f9aeaeab35401e63a149a87ae45b45bf2fea125d96c5d418d96bcda85", /*.pub_pem=*/R"(-----BEGIN PUBLIC KEY----- MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBCIA/kvhEn9/KAsjCtJZD9Af2Pdpy itOONZi4h7WDGrBj2WDF/TIe5Zf0Jz/AWWAVzkBlFaKrJKfJakSALXTDrHsB8hbc D1kLkg2cAm4K7cKxz+hdTy1gfbYyOVx/ZMBTKFk2M2Nbati/UdLucMiAAOlv00Bg EhHB0esLMnc4BlBrR7A= -----END PUBLIC KEY-----)", /*.priv_pem=*/R"(-----BEGIN EC PRIVATE KEY----- MIHcAgEBBEIAEKIH5lDPUxyYwMbRz9uIpe5X8Cc0y6uTuK4w2drAhF0XYZvjP5rq 6rNUAeY6FJqHrkW0W/L+oSXZbF1BjZa82oWgBwYFK4EEACOhgYkDgYYABAEIgD+S +ESf38oCyMK0lkP0B/Y92nKK0441mLiHtYMasGPZYMX9Mh7ll/QnP8BZYBXOQGUV oqskp8lqRIAtdMOsewHyFtwPWQuSDZwCbgrtwrHP6F1PLWB9tjI5XH9kwFMoWTYz Y1tq2L9R0u5wyIAA6W/TQGASEcHR6wsydzgGUGtHsA== -----END EC PRIVATE KEY-----)", }, }; } // Holds test vectors for the PemParser. The original private-key pem text was // taken from // google3/third_party/tink/java_src/src/test/java/com/google/crypto/tink/subtle/PemKeyTypeTest.java. // The components and public-key PEM version were extracted using // // $ openssl rsa -in -pubout -text struct RsaKeyTestVector { // RSA parameters. absl::string_view modulus_hex_str; absl::string_view public_exponent_hex_str; absl::string_view private_exponent_hex_str; absl::string_view p_hex_str; absl::string_view q_hex_str; absl::string_view dp_hex_str; absl::string_view dq_hex_str; absl::string_view coefficient_hex_str; // PEM forms. absl::string_view public_pem; absl::string_view private_pem; }; std::vector GetRsaKeyTestVectors() { return { {/*.modulus_hex_str=*/ "00bc067ea9038c24b063cac6146b26793499cc8a93985208596b9700acd4e51a580413" "316cc5acc5b499d4781421ba9b0d8af75ae56b6179d5a7fc2098f2fc4d366a6a4166b1" "5f2254db1cb3ce5dd4ab80bd8bd5adb5df34b602c319d4d004299c06e5e2437fd626e2" "84c29eeb79d1820b830b706072efa2fd1c8898d1eaaf39fb9f54ce7671ea2b5512a429" "0d3ec58bb41639a19be6630b1c27059b9a32505bebc6f42b301f9fb2cf2b624c1b6598" "702bbeaed38b5fd9941d661ff6adca65ffb251d1f314bced0861fa30ec676e2129e5ac" "ba03a6cb7594f93c60cef9b2aeee45edc6aadd31f841ee1f37fd63ccff3cebbb018a3d" "631b3d498a79348704bb419f", /*.public_exponent_hex_str=*/"010001", /*.private_exponent_hex_str=*/ "718b1a81c5faa34d4175fa17ea7cd944c27b9a5376f052ca6d064b0a13a6263a707b86" "a540da0ca9fb1b2b483cf60b1c2a872504d5cb8f5f4e8a1ac54236ca09ca4950254b87" "3f9c2e952e9fb859ed17595f50320e5a33e295d86b88eff5138b7d3ee55c0d9eacecad" "6f39b8c95f9340906a1ffa9e6dc7e7418bdb7d28539897297c7da5358867e60dfe8c76" "fbf5a6a4c064e0f6af1bf3c9640cbee007aea3be81017b726d088b69957b844f951fac" "323ff3e79fd67daf32a3dce862320ab0f4a78255f740f7381396ab8d55f80c1b38a149" "f2418a2747795b44b14092fa17d215ae0e33c78997471ab971628b897776a80bbdee7e" "ddf60eca6cecba50f32281", /*.p_hex_str=*/ "00e3f152467849f4c2d87f5a6506453878b7547996b14067966e336399e2be6a8c2ea8" "f065251f05e8bdcde4733d7084523432f3aad6b75990efadbedbce91cb097ce2b85dfa" "22fd3ca12a86198d76d31009531351f07246937cd7b1d81d3675f8afd759d1279edb13" "06e12f757baf368e265fb429775b1b4d16d88a7b009f00c7", /*.q_hex_str=*/ "00d32b57f3d29f741c33ccf95d98b93b4efd56af0f9bc98f9089d8761ecccf65e0ba7f" "eebfbef8fce3bb38a4a5f9614d47a28f137238518ab47f0a12912dc951b1d540632bc5" "70338b17ee4f866767b7ba98ac6a057f1a2b27101ee584e9e82d4a83f31ef14d11f1d9" "105dc38e3052a506982ff3679e760c7ad186f361284c9069", /*.dp_hex_str=*/ "00c536bf9694f077c2350a4aad69756e5c9351953959f67d295c033e43a0385b7b19cb" "b4e1edf21f6cb4fb7492782fe76c30197d54ec1d0a7329cbcb7be607a2017d79b3462b" "eb25ead50e33a3dc0f58a1614fed4151a5ad8661d744d9d4bc8fe9304a443d7fe82367" "1ce6abe71bb206a38a73f72e8143e4251885159b42784f75", /*.dq_hex_str=*/ "367023116147e807e936bb466cbbbbd5662bf59f617af9beba3a8a60f04dbb26cf0d72" "000e7c63bd55a389969c0e807caa24964fc8c304adf95e20613adb7e6b08ddbb732a47" "fd91ab0ead83a99eac57b74a235edd6062a5845b62b1fc16f5ae130c16fafff25355b1" "096b0379e3a45569e05ab068c267ff358ac3ad55553f99", /*.coefficient_hex_str=*/ "3a47030f3e868a1457f0290ae5e8e1a95fef23f9b8d90b20d8e75d138c94bc01e9922d" "60126a8af6c7142ebb32ced086b52cf1fa5dd389bce61bf6c66ec4c9d47cd08a8b5aad" "7d9f48202003cc19bdce05d1e41b568e60c43aec44a23031282bd46ac47ea77ddf2b8a" "303a784e27c73f9e0dd5b5f93e7be71361c2db675130d4", /*.public_pem=*/ R"(-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvAZ+qQOMJLBjysYUayZ5 NJnMipOYUghZa5cArNTlGlgEEzFsxazFtJnUeBQhupsNivda5WthedWn/CCY8vxN NmpqQWaxXyJU2xyzzl3Uq4C9i9Wttd80tgLDGdTQBCmcBuXiQ3/WJuKEwp7redGC C4MLcGBy76L9HIiY0eqvOfufVM52ceorVRKkKQ0+xYu0Fjmhm+ZjCxwnBZuaMlBb 68b0KzAfn7LPK2JMG2WYcCu+rtOLX9mUHWYf9q3KZf+yUdHzFLztCGH6MOxnbiEp 5ay6A6bLdZT5PGDO+bKu7kXtxqrdMfhB7h83/WPM/zzruwGKPWMbPUmKeTSHBLtB nwIDAQAB -----END PUBLIC KEY-----)", /*.private_pem=*/ R"(-----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC8Bn6pA4wksGPK xhRrJnk0mcyKk5hSCFlrlwCs1OUaWAQTMWzFrMW0mdR4FCG6mw2K91rla2F51af8 IJjy/E02ampBZrFfIlTbHLPOXdSrgL2L1a213zS2AsMZ1NAEKZwG5eJDf9Ym4oTC nut50YILgwtwYHLvov0ciJjR6q85+59UznZx6itVEqQpDT7Fi7QWOaGb5mMLHCcF m5oyUFvrxvQrMB+fss8rYkwbZZhwK76u04tf2ZQdZh/2rcpl/7JR0fMUvO0IYfow 7GduISnlrLoDpst1lPk8YM75sq7uRe3Gqt0x+EHuHzf9Y8z/POu7AYo9Yxs9SYp5 NIcEu0GfAgMBAAECggEAcYsagcX6o01BdfoX6nzZRMJ7mlN28FLKbQZLChOmJjpw e4alQNoMqfsbK0g89gscKoclBNXLj19OihrFQjbKCcpJUCVLhz+cLpUun7hZ7RdZ X1AyDloz4pXYa4jv9ROLfT7lXA2erOytbzm4yV+TQJBqH/qebcfnQYvbfShTmJcp fH2lNYhn5g3+jHb79aakwGTg9q8b88lkDL7gB66jvoEBe3JtCItplXuET5UfrDI/ 8+ef1n2vMqPc6GIyCrD0p4JV90D3OBOWq41V+AwbOKFJ8kGKJ0d5W0SxQJL6F9IV rg4zx4mXRxq5cWKLiXd2qAu97n7d9g7KbOy6UPMigQKBgQDj8VJGeEn0wth/WmUG RTh4t1R5lrFAZ5ZuM2OZ4r5qjC6o8GUlHwXovc3kcz1whFI0MvOq1rdZkO+tvtvO kcsJfOK4Xfoi/TyhKoYZjXbTEAlTE1HwckaTfNex2B02dfiv11nRJ57bEwbhL3V7 rzaOJl+0KXdbG00W2Ip7AJ8AxwKBgQDTK1fz0p90HDPM+V2YuTtO/VavD5vJj5CJ 2HYezM9l4Lp/7r+++PzjuzikpflhTUeijxNyOFGKtH8KEpEtyVGx1UBjK8VwM4sX 7k+GZ2e3upisagV/GisnEB7lhOnoLUqD8x7xTRHx2RBdw44wUqUGmC/zZ552DHrR hvNhKEyQaQKBgQDFNr+WlPB3wjUKSq1pdW5ck1GVOVn2fSlcAz5DoDhbexnLtOHt 8h9stPt0kngv52wwGX1U7B0KcynLy3vmB6IBfXmzRivrJerVDjOj3A9YoWFP7UFR pa2GYddE2dS8j+kwSkQ9f+gjZxzmq+cbsgajinP3LoFD5CUYhRWbQnhPdQKBgDZw IxFhR+gH6Ta7Rmy7u9VmK/WfYXr5vro6imDwTbsmzw1yAA58Y71Vo4mWnA6AfKok lk/IwwSt+V4gYTrbfmsI3btzKkf9kasOrYOpnqxXt0ojXt1gYqWEW2Kx/Bb1rhMM Fvr/8lNVsQlrA3njpFVp4FqwaMJn/zWKw61VVT+ZAoGAOkcDDz6GihRX8CkK5ejh qV/vI/m42Qsg2OddE4yUvAHpki1gEmqK9scULrsyztCGtSzx+l3TibzmG/bGbsTJ 1HzQiotarX2fSCAgA8wZvc4F0eQbVo5gxDrsRKIwMSgr1GrEfqd93yuKMDp4TifH P54N1bX5PnvnE2HC22dRMNQ= -----END PRIVATE KEY-----)"}}; } class PemParserRsaTest : public Test { public: PemParserRsaTest() : rsa_(RSA_new()) {} void SetUp() override { // Create a new RSA key and output to PEM. ASSERT_THAT(rsa_, NotNull()); internal::SslUniquePtr e(BN_new()); ASSERT_THAT(e, NotNull()); ASSERT_EQ(BN_set_word(e.get(), RSA_F4), 1); // Generate a 2048 bits RSA key pair. ASSERT_EQ(RSA_generate_key_ex(rsa_.get(), 2048, e.get(), /*cb=*/nullptr), 1) << internal::GetSslErrors(); // Write keys to PEM. internal::SslUniquePtr pub_key_pem_bio(BIO_new(BIO_s_mem())); internal::SslUniquePtr prv_key_pem_bio(BIO_new(BIO_s_mem())); // Write in PEM format. ASSERT_EQ(PEM_write_bio_RSA_PUBKEY(pub_key_pem_bio.get(), rsa_.get()), 1) << internal::GetSslErrors(); ASSERT_EQ(PEM_write_bio_RSAPrivateKey(prv_key_pem_bio.get(), rsa_.get(), /*enc=*/nullptr, /*kstr=*/nullptr, /*klen=*/0, /*cb=*/nullptr, /*u=*/nullptr), 1) << internal::GetSslErrors(); pem_rsa_pub_key_.resize(BIO_number_written(pub_key_pem_bio.get())); pem_rsa_prv_key_.resize(BIO_number_written(prv_key_pem_bio.get())); ASSERT_EQ(BIO_read(pub_key_pem_bio.get(), &pem_rsa_pub_key_[0], BIO_number_written(pub_key_pem_bio.get())), BIO_number_written(pub_key_pem_bio.get())); ASSERT_EQ(BIO_read(prv_key_pem_bio.get(), &pem_rsa_prv_key_[0], BIO_number_written(prv_key_pem_bio.get())), BIO_number_written(prv_key_pem_bio.get())); } // Utility function that sets expectations to test that `bn_str` equals `bn`. void ExpectBnEqual(absl::string_view bn_str, const BIGNUM *bn) { util::StatusOr expected_bn_str = internal::BignumToString(bn, BN_num_bytes(bn)); ASSERT_THAT(expected_bn_str, IsOk()); EXPECT_EQ(bn_str, *expected_bn_str); } protected: // PEM encoded 2048 bit RSA key pair. std::string pem_rsa_pub_key_; std::string pem_rsa_prv_key_; // Holds the RSA object. const internal::SslUniquePtr rsa_; }; // Corrupts `container` by modifying one the elements in the middle. template void Corrupt(ContainerType *container) { if (container->empty()) { return; } std::vector corrupted(container->begin(), container->end()); size_t pos = corrupted.size() / 2; corrupted[pos] ^= 1; container->assign(corrupted.begin(), corrupted.end()); } // Test we can correctly parse an RSA public key. TEST_F(PemParserRsaTest, ReadRsaPublicKey) { auto key = PemParser::ParseRsaPublicKey( absl::string_view(pem_rsa_pub_key_.data(), pem_rsa_pub_key_.size())); ASSERT_THAT(key, IsOk()) << internal::GetSslErrors(); // Verify exponent and modulus are correctly set. const BIGNUM *e_bn, *n_bn; RSA_get0_key(rsa_.get(), &n_bn, &e_bn, nullptr); ExpectBnEqual((*key)->e, e_bn); ExpectBnEqual((*key)->n, n_bn); } // Test we can correctly parse an RSA private key. TEST_F(PemParserRsaTest, ReadRsaPrivatekey) { auto key_statusor = PemParser::ParseRsaPrivateKey( absl::string_view(pem_rsa_prv_key_.data(), pem_rsa_prv_key_.size())); ASSERT_THAT(key_statusor, IsOk()) << internal::GetSslErrors(); // Verify exponents and modulus. auto key = *std::move(key_statusor); const BIGNUM *e_bn, *n_bn, *d_bn; RSA_get0_key(rsa_.get(), &n_bn, &e_bn, &d_bn); ExpectBnEqual(key->e, e_bn); ExpectBnEqual(key->n, n_bn); ExpectBnEqual(util::SecretDataAsStringView(key->d), d_bn); // Verify private key factors. const BIGNUM *p_bn, *q_bn; RSA_get0_factors(rsa_.get(), &p_bn, &q_bn); ExpectBnEqual(util::SecretDataAsStringView(key->p), p_bn); ExpectBnEqual(util::SecretDataAsStringView(key->q), q_bn); // Verify CRT parameters. const BIGNUM *dp_bn, *dq_bn, *crt_bn; RSA_get0_crt_params(rsa_.get(), &dp_bn, &dq_bn, &crt_bn); ExpectBnEqual(util::SecretDataAsStringView(key->dp), dp_bn); ExpectBnEqual(util::SecretDataAsStringView(key->dq), dq_bn); ExpectBnEqual(util::SecretDataAsStringView(key->crt), crt_bn); } using ParametrizedPemParserRsaTest = TestWithParam; TEST_P(ParametrizedPemParserRsaTest, WriteRsaPrivateKey) { RsaKeyTestVector test_vector = GetParam(); internal::RsaPrivateKey key; key.n = absl::HexStringToBytes(test_vector.modulus_hex_str); key.e = absl::HexStringToBytes(test_vector.public_exponent_hex_str); key.d = util::SecretDataFromStringView( absl::HexStringToBytes(test_vector.private_exponent_hex_str)); key.p = util::SecretDataFromStringView( absl::HexStringToBytes(test_vector.p_hex_str)); key.q = util::SecretDataFromStringView( absl::HexStringToBytes(test_vector.q_hex_str)); key.dp = util::SecretDataFromStringView( absl::HexStringToBytes(test_vector.dp_hex_str)); key.dq = util::SecretDataFromStringView( absl::HexStringToBytes(test_vector.dq_hex_str)); key.crt = util::SecretDataFromStringView( absl::HexStringToBytes(test_vector.coefficient_hex_str)); util::StatusOr pem_result = PemParser::WriteRsaPrivateKey(key); EXPECT_THAT(pem_result, IsOk()) << internal::GetSslErrors(); EXPECT_EQ(absl::StripAsciiWhitespace(*pem_result), test_vector.private_pem); } TEST_P(ParametrizedPemParserRsaTest, WriteRsaPublicKey) { RsaKeyTestVector test_vector = GetParam(); internal::RsaPublicKey key; key.n = absl::HexStringToBytes(test_vector.modulus_hex_str); key.e = absl::HexStringToBytes(test_vector.public_exponent_hex_str); auto pem_result = PemParser::WriteRsaPublicKey(key); EXPECT_THAT(pem_result, IsOk()); EXPECT_EQ(absl::StripAsciiWhitespace(*pem_result), test_vector.public_pem); } INSTANTIATE_TEST_SUITE_P(ParametrizedPemParserRsaTests, ParametrizedPemParserRsaTest, ValuesIn(GetRsaKeyTestVectors())); TEST_F(PemParserRsaTest, ReadRsaPublicKeyInvalid) { Corrupt(&pem_rsa_pub_key_); EXPECT_THAT( PemParser::ParseRsaPrivateKey( absl::string_view(pem_rsa_pub_key_.data(), pem_rsa_pub_key_.size())) .status(), Not(IsOk())); } TEST_F(PemParserRsaTest, ReadRsaPrivateKeyInvalid) { Corrupt(&pem_rsa_prv_key_); EXPECT_THAT( PemParser::ParseRsaPrivateKey( absl::string_view(pem_rsa_prv_key_.data(), pem_rsa_prv_key_.size())) .status(), Not(IsOk())); } using ParametrizedPemParserEcTest = TestWithParam; TEST_P(ParametrizedPemParserEcTest, ReadEcPublicKeySuccess) { EcKeyTestVector test_vector = GetParam(); auto ecdsa_key = PemParser::ParseEcPublicKey( absl::StripAsciiWhitespace(test_vector.pub_pem)); EXPECT_THAT(ecdsa_key, IsOk()) << internal::GetSslErrors(); auto x_hex_result = absl::BytesToHexString(ecdsa_key->get()->pub_x); auto y_hex_result = absl::BytesToHexString(ecdsa_key->get()->pub_y); EXPECT_EQ(test_vector.pub_x_hex_str, x_hex_result); EXPECT_EQ(test_vector.pub_y_hex_str, y_hex_result); EXPECT_EQ(test_vector.curve, ecdsa_key->get()->curve); } TEST_P(ParametrizedPemParserEcTest, ReadEcPrivateKeySuccess) { EcKeyTestVector test_vector = GetParam(); util::StatusOr> ecdsa_key = PemParser::ParseEcPrivateKey( absl::StripAsciiWhitespace(test_vector.priv_pem)); EXPECT_THAT(ecdsa_key, IsOk()) << internal::GetSslErrors(); std::string x_hex = absl::BytesToHexString((*ecdsa_key)->pub_x); std::string y_hex = absl::BytesToHexString((*ecdsa_key)->pub_y); std::string priv_hex = absl::BytesToHexString(util::SecretDataAsStringView((*ecdsa_key)->priv)); EXPECT_THAT(x_hex, Eq(test_vector.pub_x_hex_str)); EXPECT_THAT(y_hex, Eq(test_vector.pub_y_hex_str)); EXPECT_THAT(priv_hex, Eq(absl::AsciiStrToLower(test_vector.priv_hex_str))); EXPECT_THAT((*ecdsa_key)->curve, test_vector.curve); } TEST_P(ParametrizedPemParserEcTest, ReadEcPublicKeyInvalid) { EcKeyTestVector test_vector = GetParam(); std::string corrupt_pem = test_vector.pub_pem; Corrupt(&corrupt_pem); auto ecdsa_key = PemParser::ParseEcPublicKey(absl::StripAsciiWhitespace(corrupt_pem)); EXPECT_THAT(ecdsa_key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(ParametrizedPemParserEcTest, ReadEcPrivateKeyInvalid) { EcKeyTestVector test_vector = GetParam(); std::string corrupt_pem = test_vector.pub_pem; Corrupt(&corrupt_pem); util::StatusOr> ecdsa_key = PemParser::ParseEcPrivateKey(absl::StripAsciiWhitespace(corrupt_pem)); EXPECT_THAT(ecdsa_key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_P(ParametrizedPemParserEcTest, WriteEcPublicKeySucceeds) { EcKeyTestVector test_vector = GetParam(); // Load an EcKey with the test vector. SubtleUtilBoringSSL::EcKey ec_key; ec_key.curve = test_vector.curve; ec_key.pub_x = absl::HexStringToBytes(test_vector.pub_x_hex_str); ec_key.pub_y = absl::HexStringToBytes(test_vector.pub_y_hex_str); ec_key.priv = util::SecretDataFromStringView( absl::HexStringToBytes(test_vector.priv_hex_str)); // Check that converting the public key with WriteEcPublicKey() succeeds. util::StatusOr pem_material = PemParser::WriteEcPublicKey(ec_key); ASSERT_THAT(pem_material, IsOk()) << internal::GetSslErrors(); EXPECT_EQ(absl::StripAsciiWhitespace(*pem_material), absl::StripAsciiWhitespace(test_vector.pub_pem)); } TEST_P(ParametrizedPemParserEcTest, WriteEcPrivateKeySucceeds) { EcKeyTestVector test_vector = GetParam(); // Load an EcKey with the test vector. SubtleUtilBoringSSL::EcKey ec_key; ec_key.curve = test_vector.curve; ec_key.pub_x = absl::HexStringToBytes(test_vector.pub_x_hex_str); ec_key.pub_y = absl::HexStringToBytes(test_vector.pub_y_hex_str); ec_key.priv = util::SecretDataFromStringView( absl::HexStringToBytes(test_vector.priv_hex_str)); // Check that converting the private key with WriteEcPrivateKey() succeeds. util::StatusOr pem_material = PemParser::WriteEcPrivateKey(ec_key); ASSERT_THAT(pem_material, IsOk()); EXPECT_EQ(absl::StripAsciiWhitespace(*pem_material), absl::StripAsciiWhitespace(test_vector.priv_pem)); } INSTANTIATE_TEST_SUITE_P(ParametrizedPemParserEcTest, ParametrizedPemParserEcTest, ValuesIn(GetEcKeyTestVectors())); TEST(PemParserEcTest, NewKeyWriteAndReadPublicKeySuccess) { util::StatusOr ec_key = SubtleUtilBoringSSL::GetNewEcKey(EllipticCurveType::NIST_P256); ASSERT_THAT(ec_key, IsOk()); util::StatusOr public_pem = PemParser::WriteEcPublicKey(*ec_key); ASSERT_THAT(public_pem, IsOk()); util::StatusOr> public_key = PemParser::ParseEcPublicKey(*public_pem); EXPECT_THAT(public_key, IsOk()) << internal::GetSslErrors(); EXPECT_EQ((*public_key)->pub_x, ec_key->pub_x); EXPECT_EQ((*public_key)->pub_y, ec_key->pub_y); EXPECT_EQ((*public_key)->curve, ec_key->curve); } TEST(PemParserEcTest, NewKeyWriteAndReadPrivateKeySuccess) { util::StatusOr ec_key = SubtleUtilBoringSSL::GetNewEcKey(EllipticCurveType::NIST_P256); ASSERT_THAT(ec_key, IsOk()); util::StatusOr private_pem = PemParser::WriteEcPrivateKey(*ec_key); ASSERT_THAT(private_pem, IsOk()); util::StatusOr> parsed_ec_key = PemParser::ParseEcPrivateKey(*private_pem); EXPECT_THAT(parsed_ec_key, IsOk()) << internal::GetSslErrors(); EXPECT_EQ((*parsed_ec_key)->pub_x, ec_key->pub_x); EXPECT_EQ((*parsed_ec_key)->pub_y, ec_key->pub_y); EXPECT_EQ((*parsed_ec_key)->priv, ec_key->priv); EXPECT_EQ((*parsed_ec_key)->curve, ec_key->curve); } TEST(PemParserEcTest, ReadEcPublicKeyP224_Unimplemented) { constexpr absl::string_view kP224PublicKey = R"(-----BEGIN PUBLIC KEY----- ME4wEAYHKoZIzj0CAQYFK4EEACEDOgAE9PcDd+z3cVYhKnNbDVAXwDmShKBCPc88 sEUoYDu3Oi24YuZAFbwVIdX69RME4FB5PbxISleynMI= -----END PUBLIC KEY-----)"; auto ecdsa_key = PemParser::ParseEcPublicKey(absl::StripAsciiWhitespace(kP224PublicKey)); EXPECT_THAT(ecdsa_key.status(), StatusIs(absl::StatusCode::kUnimplemented)); } TEST(PemParserEcTest, ReadInvalidEcPublicKey) { util::StatusOr> ecdsa_key = PemParser::ParseEcPublicKey("invalid"); EXPECT_THAT(ecdsa_key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(PemParserEcTest, ReadInvalidEcPrivateKey) { util::StatusOr> ecdsa_key = PemParser::ParseEcPrivateKey("invalid"); EXPECT_THAT(ecdsa_key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } // Makes sure parsing of a valid EC public key on secp256k1 fails because the // curve is unsupported. TEST(PemParserEcTest, ReadEcPublicKeyFailsBecauseSecp256k1Unsupported) { // Generate private key with: // > openssl ecparam -genkey -name secp256k1 -noout -out ec-key-pair.pem // Extract the public key: // > openssl ec -in ec-key-pair.pem -pubout constexpr absl::string_view kSecp256k1PublicKey = R"(-----BEGIN PUBLIC KEY----- MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEC9naJNDkHKVBjfDK90szJegpzatlUcFO BLrJS8EVf4tMw52zdhXpKBF2FGpD54dNo+Ut2s6JIE+LoaX/FSvifw== -----END PUBLIC KEY-----)"; util::StatusOr> ecdsa_key = PemParser::ParseEcPublicKey( absl::StripAsciiWhitespace(kSecp256k1PublicKey)); // With BoringSSL parsing of the PEM key fails when an unsupported curve is // used [1]; Supported curves are defined here [2]. Tink doesn't distinguish // between an error caused by a malformed PEM and an unsupported group by // BoringSSL. On the other hand, with OpenSSL parsing succeeds, but this // curve is unsupported by Tink. As a consequence, this fails with two // different errors. // // [1]https://github.com/google/boringssl/blob/master/crypto/ec_extra/ec_asn1.c#L324 // [2]https://github.com/google/boringssl/blob/master/crypto/fipsmodule/ec/ec.c#L218 if (internal::IsBoringSsl()) { EXPECT_THAT(ecdsa_key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } else { EXPECT_THAT(ecdsa_key.status(), StatusIs(absl::StatusCode::kUnimplemented)); } } // Makes sure parsing of a valid EC private key on secp256k1 fails because the // curve is unsupported. TEST(PemParserEcTest, ReadEcPrivateKeyFailsBecauseSecp256k1Unsupported) { // Generate private key with: // > openssl ecparam -genkey -name secp256k1 -noout constexpr absl::string_view kSecp256k1PrivateKey = R"(-----BEGIN EC PRIVATE KEY----- MHQCAQEEIKSqexQyySWB705oPctFx2roLMHdfJ/W/WBISaRNu1UHoAcGBSuBBAAK oUQDQgAEC9naJNDkHKVBjfDK90szJegpzatlUcFOBLrJS8EVf4tMw52zdhXpKBF2 FGpD54dNo+Ut2s6JIE+LoaX/FSvifw== -----END EC PRIVATE KEY-----)"; util::StatusOr> ecdsa_key = PemParser::ParseEcPrivateKey( absl::StripAsciiWhitespace(kSecp256k1PrivateKey)); // PEM parsing fails in BoringSSL when the curve is unsupported, and Tink // doesn't distinguish between an error caused by a malformed PEM and an // unsupported group by BoringSSL. With OpenSSL parsing succeeds, but this // curve is unsupported by Tink. As a consequence, this fails with two // different errors. if (internal::IsBoringSsl()) { EXPECT_THAT(ecdsa_key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } else { EXPECT_THAT(ecdsa_key.status(), StatusIs(absl::StatusCode::kUnimplemented)); } } TEST(PemParserEcTest, ParseEncryptedEcPrivateKey_Invalid) { // This key was generated with the command: // openssl genpkey -algorithm ec -pkeyopt ec_paramgen_curve:prime256v1 // -aes128 using pass phrase "mypassword" constexpr absl::string_view kPrivateKey = R"(-----BEGIN ENCRYPTED PRIVATE KEY----- MIHsMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAjurwMnDwdrOwICCAAw DAYIKoZIhvcNAgkFADAdBglghkgBZQMEAQIEEJHshE1SbT5XZN1bToPLsuAEgZAA xmCJjv1kTjWzwbE1SEM6lwMippywDf0JH+de4JwlrPiQAb5NExq96m6Per70tX4W iJ76WplZagsJzsAg/5gIJ/YcTry266rP2SBVTsuCY/GOh2vU/x6XFbPi9JCM0nvH GTi1cWyqIwzGqfw8ZGejtvg4SAGulZ7/MWVCZV51C6JakfY1v3z24BQG1m50jMs= -----END ENCRYPTED PRIVATE KEY-----)"; util::StatusOr> ecdsa_key = PemParser::ParseEcPrivateKey(absl::StripAsciiWhitespace(kPrivateKey)); EXPECT_THAT(ecdsa_key.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(PemParserEcTest, WriteEcPublicKeyWithBadXFails) { util::StatusOr ec_key_statusor = SubtleUtilBoringSSL::GetNewEcKey(subtle::NIST_P256); ASSERT_THAT(ec_key_statusor, IsOk()); SubtleUtilBoringSSL::EcKey ec_key = *ec_key_statusor; Corrupt(&ec_key.pub_x); // Bad coordinates should generate a BoringSSL/OpenSSL's internal error. EXPECT_THAT(PemParser::WriteEcPublicKey(ec_key).status(), StatusIs(absl::StatusCode::kInternal)); } TEST(PemParserEcTest, WriteEcPublicKeyWithBadYFails) { util::StatusOr ec_key_statusor = SubtleUtilBoringSSL::GetNewEcKey(subtle::NIST_P256); ASSERT_THAT(ec_key_statusor, IsOk()); SubtleUtilBoringSSL::EcKey ec_key = *ec_key_statusor; Corrupt(&ec_key.pub_y); EXPECT_THAT(PemParser::WriteEcPublicKey(ec_key).status(), StatusIs(absl::StatusCode::kInternal)); } TEST(PemParserEcTest, WriteEcPrivateKeyWithBadPrivFails) { util::StatusOr ec_key_statusor = SubtleUtilBoringSSL::GetNewEcKey(subtle::NIST_P256); ASSERT_THAT(ec_key_statusor, IsOk()); SubtleUtilBoringSSL::EcKey ec_key = *ec_key_statusor; std::string priv = std::string(util::SecretDataAsStringView(ec_key.priv)); Corrupt(&priv); ec_key.priv = util::SecretDataFromStringView(priv); EXPECT_THAT(PemParser::WriteEcPrivateKey(ec_key).status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/prf/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "streaming_prf", hdrs = ["streaming_prf.h"], include_prefix = "tink/subtle/prf", deps = [ "//:input_stream", "@com_google_absl//absl/strings", ], ) cc_library( name = "hkdf_streaming_prf", srcs = ["hkdf_streaming_prf.cc"], hdrs = ["hkdf_streaming_prf.h"], include_prefix = "tink/subtle/prf", deps = [ ":streaming_prf", "//:input_stream", "//internal:fips_utils", "//internal:md_util", "//internal:ssl_unique_ptr", "//subtle", "//subtle:subtle_util", "//util:secret_data", "//util:status", "//util:statusor", "@boringssl//:crypto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "streaming_prf_wrapper", srcs = ["streaming_prf_wrapper.cc"], hdrs = ["streaming_prf_wrapper.h"], include_prefix = "tink/subtle/prf", deps = [ ":streaming_prf", "//:input_stream", "//:primitive_set", "//:primitive_wrapper", "//proto:tink_cc_proto", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "prf_set_util", srcs = ["prf_set_util.cc"], hdrs = ["prf_set_util.h"], include_prefix = "tink/subtle/prf", deps = [ ":streaming_prf", "//prf:prf_set", "//subtle/mac:stateful_mac", "//util:input_stream_util", "//util:status", "//util:statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_test( name = "hkdf_streaming_prf_test", srcs = ["hkdf_streaming_prf_test.cc"], tags = ["fips"], deps = [ ":hkdf_streaming_prf", "//:input_stream", "//config:tink_fips", "//subtle", "//util:input_stream_util", "//util:secret_data", "//util:statusor", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:string_view", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "streaming_prf_wrapper_test", srcs = ["streaming_prf_wrapper_test.cc"], deps = [ ":streaming_prf", ":streaming_prf_wrapper", "//:input_stream", "//:primitive_set", "//proto:tink_cc_proto", "//util:input_stream_util", "//util:istream_input_stream", "//util:test_matchers", "//util:test_util", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "prf_set_util_test", srcs = ["prf_set_util_test.cc"], deps = [ ":prf_set_util", ":streaming_prf", "//:input_stream", "//prf:prf_set", "//subtle/mac:stateful_mac", "//util:istream_input_stream", "//util:status", "//util:statusor", "//util:test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/subtle/prf/CMakeLists.txt ================================================ tink_module(subtle::prf) tink_cc_library( NAME streaming_prf SRCS streaming_prf.h DEPS absl::strings tink::core::input_stream ) tink_cc_library( NAME streaming_prf_wrapper SRCS streaming_prf_wrapper.cc streaming_prf_wrapper.h DEPS tink::subtle::prf::streaming_prf absl::memory absl::status absl::strings tink::core::input_stream tink::core::primitive_set tink::core::primitive_wrapper tink::util::status tink::util::statusor tink::proto::tink_cc_proto ) tink_cc_library( NAME hkdf_streaming_prf SRCS hkdf_streaming_prf.cc hkdf_streaming_prf.h DEPS tink::subtle::prf::streaming_prf absl::memory absl::status absl::strings crypto tink::core::input_stream tink::internal::fips_utils tink::internal::md_util tink::internal::ssl_unique_ptr tink::subtle::subtle tink::subtle::subtle_util tink::util::secret_data tink::util::status tink::util::statusor ) tink_cc_library( NAME prf_set_util SRCS prf_set_util.cc prf_set_util.h DEPS tink::subtle::prf::streaming_prf absl::memory absl::status absl::strings tink::prf::prf_set tink::subtle::mac::stateful_mac tink::util::input_stream_util tink::util::status tink::util::statusor ) tink_cc_test( NAME hkdf_streaming_prf_test SRCS hkdf_streaming_prf_test.cc DEPS tink::subtle::prf::hkdf_streaming_prf gmock absl::status absl::string_view tink::core::input_stream tink::config::tink_fips tink::subtle::subtle tink::util::input_stream_util tink::util::secret_data tink::util::statusor tink::util::test_matchers tink::util::test_util ) tink_cc_test( NAME streaming_prf_wrapper_test SRCS streaming_prf_wrapper_test.cc DEPS tink::subtle::prf::streaming_prf tink::subtle::prf::streaming_prf_wrapper gmock absl::memory absl::status absl::strings tink::core::input_stream tink::core::primitive_set tink::util::input_stream_util tink::util::istream_input_stream tink::util::test_matchers tink::util::test_util tink::proto::tink_cc_proto ) tink_cc_test( NAME prf_set_util_test SRCS prf_set_util_test.cc DEPS tink::subtle::prf::prf_set_util tink::subtle::prf::streaming_prf gmock absl::memory absl::status absl::strings tink::core::input_stream tink::prf::prf_set tink::subtle::mac::stateful_mac tink::util::istream_input_stream tink::util::status tink::util::statusor tink::util::test_matchers ) ================================================ FILE: cc/subtle/prf/hkdf_streaming_prf.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/prf/hkdf_streaming_prf.h" #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "openssl/hmac.h" #include "tink/input_stream.h" #include "tink/internal/fips_utils.h" #include "tink/internal/md_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/prf/streaming_prf.h" #include "tink/subtle/subtle_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { namespace { class HkdfInputStream : public InputStream { public: HkdfInputStream(const EVP_MD *digest, const util::SecretData &secret, absl::string_view salt, absl::string_view input) : input_(input) { stream_status_ = Init(digest, secret, salt); } crypto::tink::util::StatusOr Next(const void **data) override { if (!stream_status_.ok()) { return stream_status_; } if (position_in_ti_ < ti_.size()) { return returnDataFromPosition(data); } if (i_ == 255) { stream_status_ = crypto::tink::util::Status(absl::StatusCode::kOutOfRange, "EOF"); return stream_status_; } stream_status_ = UpdateTi(); if (!stream_status_.ok()) { return stream_status_; } return returnDataFromPosition(data); } void BackUp(int count) override { position_in_ti_ -= std::min(std::max(0, count), position_in_ti_); } int64_t Position() const override { if (i_ == 0) return 0; return (i_ - 1) * ti_.size() + position_in_ti_; } private: util::Status Init(const EVP_MD *digest, const util::SecretData &secret, absl::string_view salt) { // PRK as by RFC 5869, Section 2.2 util::SecretData prk(EVP_MAX_MD_SIZE); if (!digest) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid digest"); } const size_t digest_size = EVP_MD_size(digest); if (digest_size == 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid digest size (0)"); } ti_.resize(digest_size); // BoringSSL's `HKDF_extract` function is implemented as an HMAC [1]. We // replace calls to `HKDF_extract` with a direct call to `HMAC` to make this // compatible to OpenSSL, which doesn't expose `HKDF*` functions. // // [1] https://github.com/google/boringssl/blob/master/crypto/hkdf/hkdf.c#L42 unsigned prk_len; if (HMAC(digest, reinterpret_cast(salt.data()), salt.size(), secret.data(), secret.size(), prk.data(), &prk_len) == nullptr || prk_len != digest_size) { return util::Status(absl::StatusCode::kInternal, "HKDF-Extract failed"); } prk.resize(prk_len); if (!hmac_ctx_) { return util::Status(absl::StatusCode::kInternal, "HMAC_CTX_new failed"); } if (!HMAC_Init_ex(hmac_ctx_.get(), prk.data(), prk.size(), digest, nullptr)) { return util::Status(absl::StatusCode::kInternal, "HMAC_Init_ex failed"); } return UpdateTi(); } int returnDataFromPosition(const void **data) { // There's still data in ti to return. *data = ti_.data() + position_in_ti_; int result = ti_.size() - position_in_ti_; position_in_ti_ = ti_.size(); return result; } // Sets T(i+i) = HMAC-Hash(PRK, T(i) | info | i + 1) as in RFC 5869, // Section 2.3 // Unfortunately, boringSSL does not provide a function which updates T(i) // for a single round; hence we implement this ourselves. util::Status UpdateTi() { if (!HMAC_Init_ex(hmac_ctx_.get(), nullptr, 0, nullptr, nullptr)) { return util::Status(absl::StatusCode::kInternal, "HMAC_Init_ex failed"); } if (i_ != 0 && !HMAC_Update(hmac_ctx_.get(), ti_.data(), ti_.size())) { return util::Status(absl::StatusCode::kInternal, "HMAC_Update failed on ti_"); } if (!HMAC_Update(hmac_ctx_.get(), reinterpret_cast(&input_[0]), input_.size())) { return util::Status(absl::StatusCode::kInternal, "HMAC_Update failed on input_"); } uint8_t i_as_uint8 = i_ + 1; if (!HMAC_Update(hmac_ctx_.get(), &i_as_uint8, 1)) { return util::Status(absl::StatusCode::kInternal, "HMAC_Update failed on i_"); } if (!HMAC_Final(hmac_ctx_.get(), ti_.data(), nullptr)) { return util::Status(absl::StatusCode::kInternal, "HMAC_Final failed"); } i_++; position_in_ti_ = 0; return util::OkStatus(); } // OUT_OF_RANGE_ERROR in case we returned all the data. Other errors indicate // problems and are permanent. util::Status stream_status_ = util::OkStatus(); internal::SslUniquePtr hmac_ctx_{HMAC_CTX_new()}; // Current value T(i). util::SecretData ti_; // By RFC 5869: 0 <= i_ <= 255*HashLen int i_ = 0; std::string input_; // The current position of ti which we returned. int position_in_ti_ = 0; }; } // namespace std::unique_ptr HkdfStreamingPrf::ComputePrf( absl::string_view input) const { return absl::make_unique(hash_, secret_, salt_, input); } // static crypto::tink::util::StatusOr> HkdfStreamingPrf::New(HashType hash, util::SecretData secret, absl::string_view salt) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) return status; if (hash != SHA256 && hash != SHA512 && hash != SHA1) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Hash ", hash, " not acceptable for HkdfStreamingPrf")); } if (secret.size() < 10) { return util::Status(absl::StatusCode::kInvalidArgument, "Too short secret for HkdfStreamingPrf"); } util::StatusOr evp_md = internal::EvpHashFromHashType(hash); if (!evp_md.ok()) { return util::Status(absl::StatusCode::kUnimplemented, "Unsupported hash"); } return { absl::WrapUnique(new HkdfStreamingPrf(*evp_md, std::move(secret), salt))}; } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/prf/hkdf_streaming_prf.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_PRF_HKDF_STREAMING_PRF_H_ #define TINK_SUBTLE_PRF_HKDF_STREAMING_PRF_H_ #include #include #include #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "tink/input_stream.h" #include "tink/internal/fips_utils.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/prf/streaming_prf.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { class HkdfStreamingPrf : public StreamingPrf { public: static crypto::tink::util::StatusOr> New( HashType hash, util::SecretData secret, absl::string_view salt); std::unique_ptr ComputePrf( absl::string_view input) const override; static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kNotFips; private: HkdfStreamingPrf(const EVP_MD* hash, util::SecretData secret, absl::string_view salt) : hash_(hash), secret_(std::move(secret)), salt_(salt) {} const EVP_MD* hash_; const util::SecretData secret_; const std::string salt_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_PRF_HKDF_STREAMING_PRF_H_ ================================================ FILE: cc/subtle/prf/hkdf_streaming_prf_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/prf/hkdf_streaming_prf.h" #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/config/tink_fips.h" #include "tink/input_stream.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/hkdf.h" #include "tink/subtle/random.h" #include "tink/util/input_stream_util.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::HexDecodeOrDie; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::Ge; using ::testing::Ne; using ::testing::Not; using ::testing::SizeIs; // GENERIC TESTS =============================================================== // // These should be satisfied for any streaming prf which generates enough // output. TEST(HkdfStreamingPrf, Basic) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } auto streaming_prf_or = HkdfStreamingPrf::New( SHA512, util::SecretDataFromStringView("key0123456"), "salt"); ASSERT_THAT(streaming_prf_or, IsOk()); std::unique_ptr stream = streaming_prf_or.value()->ComputePrf("input"); auto result_or = ReadBytesFromStream(10, stream.get()); ASSERT_THAT(result_or, IsOk()); EXPECT_THAT(result_or.value(), SizeIs(10)); } TEST(HkdfStreamingPrf, EmptySalt) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } crypto::tink::subtle::HashType hash_type = SHA512; const int hash_length = 64; util::SecretData secret = util::SecretDataFromStringView("key0123456"); absl::string_view input = "input"; int num_bytes = 10; std::string prf_empty_salt; std::string prf_zeroed_salt; { auto streaming_prf = HkdfStreamingPrf::New(hash_type, secret, ""); ASSERT_THAT(streaming_prf, IsOk()); std::unique_ptr stream = (*streaming_prf)->ComputePrf(input); auto result = ReadBytesFromStream(num_bytes, stream.get()); ASSERT_THAT(result, IsOk()); prf_empty_salt = *result; } { uint8_t zeroedSalt[hash_length]; std::fill(std::begin(zeroedSalt), std::end(zeroedSalt), 0); auto streaming_prf = HkdfStreamingPrf::New(hash_type, secret, std::string((char*)zeroedSalt)); ASSERT_THAT(streaming_prf, IsOk()); std::unique_ptr stream = (*streaming_prf)->ComputePrf(input); auto result = ReadBytesFromStream(num_bytes, stream.get()); ASSERT_THAT(result, IsOk()); prf_zeroed_salt = *result; } EXPECT_THAT(prf_empty_salt, SizeIs(num_bytes)); EXPECT_THAT(prf_zeroed_salt, SizeIs(num_bytes)); ASSERT_EQ(prf_empty_salt, prf_zeroed_salt); } TEST(HkdfStreamingPrf, DifferentInputsGiveDifferentvalues) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } auto streaming_prf_or = HkdfStreamingPrf::New( SHA512, util::SecretDataFromStringView("key0123456"), "salt"); ASSERT_THAT(streaming_prf_or, IsOk()); std::unique_ptr stream = streaming_prf_or.value()->ComputePrf("input"); auto result_or = ReadBytesFromStream(10, stream.get()); ASSERT_THAT(result_or, IsOk()); // Different input. std::unique_ptr stream2 = streaming_prf_or.value()->ComputePrf("input2"); auto result_or2 = ReadBytesFromStream(10, stream2.get()); ASSERT_THAT(result_or2, IsOk()); EXPECT_THAT(result_or2.value(), Ne(result_or.value())); } TEST(HkdfStreamingPrf, SameInputTwice) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } auto streaming_prf_or = HkdfStreamingPrf::New( SHA512, util::SecretDataFromStringView("key0123456"), "salt"); ASSERT_THAT(streaming_prf_or, IsOk()); std::unique_ptr stream = streaming_prf_or.value()->ComputePrf("input"); auto result_or = ReadBytesFromStream(10, stream.get()); ASSERT_THAT(result_or, IsOk()); // Same input. std::unique_ptr stream2 = streaming_prf_or.value()->ComputePrf("input"); auto result_or2 = ReadBytesFromStream(10, stream2.get()); ASSERT_THAT(result_or2, IsOk()); EXPECT_THAT(result_or2.value(), Eq(result_or.value())); } // STREAM HANDLING TESTS ======================================================= // // These check that the buffer handling of the implementation is correct. They // should be satisfied with any input stream. // Tests that after Backing up the full stream, we get back the same data. TEST(HkdfStreamingPrf, BackupFullStream) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } auto streaming_prf_or = HkdfStreamingPrf::New( SHA256, util::SecretDataFromStringView("key0123456"), "salt"); ASSERT_THAT(streaming_prf_or, IsOk()); std::unique_ptr stream = streaming_prf_or.value()->ComputePrf("input"); const void* data; crypto::tink::util::StatusOr result = stream->Next(&data); ASSERT_THAT(result, IsOk()); int bytes_read = result.value(); std::string first_read = std::string(static_cast(data), bytes_read); stream->BackUp(bytes_read); result = stream->Next(&data); ASSERT_THAT(result, IsOk()); // We typically read at least as many bytes the second time -- strictly // speaking this might not be satisfied by every InputStream, but it usually // will be. ASSERT_THAT(result.value(), Ge(bytes_read)); std::string second_read = std::string(static_cast(data), bytes_read); EXPECT_THAT(first_read, Eq(second_read)); } // Tests that after Backing up half the stream, we get back the same data. TEST(HkdfStreamingPrf, BackupHalf) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } auto streaming_prf_or = HkdfStreamingPrf::New( SHA256, util::SecretDataFromStringView("key0123456"), "salt"); ASSERT_THAT(streaming_prf_or, IsOk()); std::unique_ptr stream = streaming_prf_or.value()->ComputePrf("input"); const void* data; crypto::tink::util::StatusOr result = stream->Next(&data); ASSERT_THAT(result, IsOk()); int bytes_read = result.value(); int backup_amount = bytes_read / 2; std::string first_read = std::string(static_cast(data) + bytes_read - backup_amount, backup_amount); stream->BackUp(backup_amount); result = stream->Next(&data); ASSERT_THAT(result, IsOk()); // We typically read at least as many bytes the second time -- strictly // speaking this might not be satisfied by every InputStream, but it usually // will be. ASSERT_THAT(result.value(), Ge(backup_amount)); std::string second_read = std::string(static_cast(data), backup_amount); EXPECT_THAT(first_read, Eq(second_read)); } // Tests that after Position is correct initially (i.e., 0). TEST(HkdfStreamingPrf, PositionOneRead) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } auto streaming_prf_or = HkdfStreamingPrf::New( SHA256, util::SecretDataFromStringView("key0123456"), "salt"); ASSERT_THAT(streaming_prf_or, IsOk()); std::unique_ptr stream = streaming_prf_or.value()->ComputePrf("input"); EXPECT_THAT(stream->Position(), Eq(0)); } // Tests that after Position is correct after a single read. TEST(HkdfStreamingPrf, PositionSingleRead) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } auto streaming_prf_or = HkdfStreamingPrf::New( SHA256, util::SecretDataFromStringView("key0123456"), "salt"); ASSERT_THAT(streaming_prf_or, IsOk()); std::unique_ptr stream = streaming_prf_or.value()->ComputePrf("input"); const void* data; crypto::tink::util::StatusOr result = stream->Next(&data); ASSERT_THAT(result, IsOk()); EXPECT_THAT(stream->Position(), Eq(result.value())); } // Tests that after Position is correct after a two reads. TEST(HkdfStreamingPrf, PositionTwoReads) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } auto streaming_prf_or = HkdfStreamingPrf::New( SHA256, util::SecretDataFromStringView("key0123456"), "salt"); ASSERT_THAT(streaming_prf_or, IsOk()); std::unique_ptr stream = streaming_prf_or.value()->ComputePrf("input"); const void* data; crypto::tink::util::StatusOr result = stream->Next(&data); ASSERT_THAT(result, IsOk()); crypto::tink::util::StatusOr result2 = stream->Next(&data); ASSERT_THAT(result, IsOk()); EXPECT_THAT(stream->Position(), Eq(result.value() + result2.value())); } // Tests that we can backup the first read completely. TEST(HkdfStreamingPrf, BackupSingleRead) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } auto streaming_prf_or = HkdfStreamingPrf::New( SHA256, util::SecretDataFromStringView("key0123456"), "salt"); ASSERT_THAT(streaming_prf_or, IsOk()); std::unique_ptr stream = streaming_prf_or.value()->ComputePrf("input"); const void* data; crypto::tink::util::StatusOr result = stream->Next(&data); ASSERT_THAT(result, IsOk()); stream->BackUp(result.value()); EXPECT_THAT(stream->Position(), Eq(0)); } // Tests that we can backup the second read completely. TEST(HkdfStreamingPrf, BackupSecondRead) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } auto streaming_prf_or = HkdfStreamingPrf::New( SHA256, util::SecretDataFromStringView("key0123456"), "salt"); ASSERT_THAT(streaming_prf_or, IsOk()); std::unique_ptr stream = streaming_prf_or.value()->ComputePrf("input"); const void* data; crypto::tink::util::StatusOr result = stream->Next(&data); ASSERT_THAT(result, IsOk()); crypto::tink::util::StatusOr result2 = stream->Next(&data); ASSERT_THAT(result, IsOk()); stream->BackUp(result2.value()); EXPECT_THAT(stream->Position(), Eq(result.value())); } // Tests that we can partially backup and position is correct. TEST(HkdfStreamingPrf, PartialBackup) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } auto streaming_prf_or = HkdfStreamingPrf::New( SHA256, util::SecretDataFromStringView("key0123456"), "salt"); ASSERT_THAT(streaming_prf_or, IsOk()); std::unique_ptr stream = streaming_prf_or.value()->ComputePrf("input"); const void* data; crypto::tink::util::StatusOr result = stream->Next(&data); ASSERT_THAT(result, IsOk()); stream->BackUp(result.value() / 2); EXPECT_THAT(stream->Position(), Eq(result.value() - result.value() / 2)); } // HKDF Specific tests ========================================================= // Tests which only apply for Hkdf. TEST(HkdfStreamingPrf, ExhaustInput) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } auto streaming_prf_or = HkdfStreamingPrf::New( SHA512, util::SecretDataFromStringView("key0123456"), "salt"); ASSERT_THAT(streaming_prf_or, IsOk()); const int max_output_length = 255 * (512 / 8); std::unique_ptr stream = streaming_prf_or.value()->ComputePrf("input"); auto result_or = ReadBytesFromStream(max_output_length, stream.get()); ASSERT_THAT(result_or, IsOk()); EXPECT_THAT(result_or.value(), SizeIs(max_output_length)); result_or = ReadBytesFromStream(50, stream.get()); ASSERT_THAT(result_or, Not(IsOk())); } // TEST VECTORS AND COMPARISON ================================================= // These test are Hkdf specific. We test with the test vectors from RFC 5869 and // compare with our implementation. TEST(HkdfStreamingPrf, TestVector1) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } // https://tools.ietf.org/html/rfc5869#appendix-A.1 HashType hash = SHA256; util::SecretData ikm = util::SecretDataFromStringView( HexDecodeOrDie("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b")); std::string salt = HexDecodeOrDie("000102030405060708090a0b0c"); std::string info = HexDecodeOrDie("f0f1f2f3f4f5f6f7f8f9"); std::string expected_result = HexDecodeOrDie( "3cb25f25faacd57a90434f64d0362f2a" "2d2d0a90cf1a5a4c5db02d56ecc4c5bf" "34007208d5b887185865"); auto streaming_prf_or = HkdfStreamingPrf::New(hash, ikm, salt); ASSERT_THAT(streaming_prf_or, IsOk()); std::unique_ptr stream = streaming_prf_or.value()->ComputePrf(info); auto result_or = ReadBytesFromStream(expected_result.size(), stream.get()); ASSERT_THAT(result_or, IsOk()); EXPECT_THAT(result_or.value(), Eq(expected_result)); } crypto::tink::util::StatusOr ComputeWithHkdfStreamingPrf( HashType hash, util::SecretData ikm, std::string salt, std::string info, int length) { auto streaming_prf_or = HkdfStreamingPrf::New(hash, std::move(ikm), salt); if (!streaming_prf_or.status().ok()) { return streaming_prf_or.status(); } std::unique_ptr stream = streaming_prf_or.value()->ComputePrf(info); return ReadBytesFromStream(length, stream.get()); } TEST(HkdfStreamingPrf, TestVector2) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } // https://tools.ietf.org/html/rfc5869#appendix-A.2 HashType hash = SHA256; util::SecretData ikm = util::SecretDataFromStringView( HexDecodeOrDie("000102030405060708090a0b0c0d0e0f" "101112131415161718191a1b1c1d1e1f" "202122232425262728292a2b2c2d2e2f" "303132333435363738393a3b3c3d3e3f" "404142434445464748494a4b4c4d4e4f")); std::string salt = HexDecodeOrDie( "606162636465666768696a6b6c6d6e6f" "707172737475767778797a7b7c7d7e7f" "808182838485868788898a8b8c8d8e8f" "909192939495969798999a9b9c9d9e9f" "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"); std::string info = HexDecodeOrDie( "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"); std::string expected_result = HexDecodeOrDie( "b11e398dc80327a1c8e7f78c596a4934" "4f012eda2d4efad8a050cc4c19afa97c" "59045a99cac7827271cb41c65e590e09" "da3275600c2f09b8367793a9aca3db71" "cc30c58179ec3e87c14c01d5c1f3434f" "1d87"); auto result_or = ComputeWithHkdfStreamingPrf(hash, std::move(ikm), salt, info, expected_result.size()); ASSERT_THAT(result_or, IsOk()); EXPECT_THAT(result_or.value(), Eq(expected_result)); } TEST(HkdfStreamingPrf, TestVector3) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } // https://tools.ietf.org/html/rfc5869#appendix-A.3 HashType hash = SHA256; util::SecretData ikm = util::SecretDataFromStringView( HexDecodeOrDie("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b")); std::string salt = HexDecodeOrDie(""); std::string info = HexDecodeOrDie(""); std::string expected_result = HexDecodeOrDie( "8da4e775a563c18f715f802a063c5a31" "b8a11f5c5ee1879ec3454e5f3c738d2d" "9d201395faa4b61a96c8"); auto result_or = ComputeWithHkdfStreamingPrf(hash, std::move(ikm), salt, info, expected_result.size()); ASSERT_THAT(result_or, IsOk()); EXPECT_THAT(result_or.value(), Eq(expected_result)); } TEST(HkdfStreamingPrf, TestVector4) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } // https://tools.ietf.org/html/rfc5869#appendix-A.4 HashType hash = SHA1; util::SecretData ikm = util::SecretDataFromStringView(HexDecodeOrDie("0b0b0b0b0b0b0b0b0b0b0b")); std::string salt = HexDecodeOrDie("000102030405060708090a0b0c"); std::string info = HexDecodeOrDie("f0f1f2f3f4f5f6f7f8f9"); std::string expected_result = HexDecodeOrDie( "085a01ea1b10f36933068b56efa5ad81" "a4f14b822f5b091568a9cdd4f155fda2" "c22e422478d305f3f896"); auto result_or = ComputeWithHkdfStreamingPrf(hash, std::move(ikm), salt, info, expected_result.size()); ASSERT_THAT(result_or, IsOk()); EXPECT_THAT(result_or.value(), Eq(expected_result)); } TEST(HkdfStreamingPrf, TestVector5) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } // https://tools.ietf.org/html/rfc5869#appendix-A.5 HashType hash = SHA1; util::SecretData ikm = util::SecretDataFromStringView( HexDecodeOrDie("000102030405060708090a0b0c0d0e0f" "101112131415161718191a1b1c1d1e1f" "202122232425262728292a2b2c2d2e2f" "303132333435363738393a3b3c3d3e3f" "404142434445464748494a4b4c4d4e4f")); std::string salt = HexDecodeOrDie( "606162636465666768696a6b6c6d6e6f" "707172737475767778797a7b7c7d7e7f" "808182838485868788898a8b8c8d8e8f" "909192939495969798999a9b9c9d9e9f" "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"); std::string info = HexDecodeOrDie( "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"); std::string expected_result = HexDecodeOrDie( "0bd770a74d1160f7c9f12cd5912a06eb" "ff6adcae899d92191fe4305673ba2ffe" "8fa3f1a4e5ad79f3f334b3b202b2173c" "486ea37ce3d397ed034c7f9dfeb15c5e" "927336d0441f4c4300e2cff0d0900b52" "d3b4"); auto result_or = ComputeWithHkdfStreamingPrf(hash, std::move(ikm), salt, info, expected_result.size()); ASSERT_THAT(result_or, IsOk()); EXPECT_THAT(result_or.value(), Eq(expected_result)); } TEST(HkdfStreamingPrf, TestVector6) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } // https://tools.ietf.org/html/rfc5869#appendix-A.6 HashType hash = SHA1; util::SecretData ikm = util::SecretDataFromStringView( HexDecodeOrDie("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b")); std::string salt = HexDecodeOrDie(""); std::string info = HexDecodeOrDie(""); std::string expected_result = HexDecodeOrDie( "0ac1af7002b3d761d1e55298da9d0506" "b9ae52057220a306e07b6b87e8df21d0" "ea00033de03984d34918"); auto result_or = ComputeWithHkdfStreamingPrf(hash, std::move(ikm), salt, info, expected_result.size()); ASSERT_THAT(result_or, IsOk()); EXPECT_THAT(result_or.value(), Eq(expected_result)); } TEST(HkdfStreamingPrf, TestVector7) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } // https://tools.ietf.org/html/rfc5869#appendix-A.7 HashType hash = SHA1; util::SecretData ikm = util::SecretDataFromStringView( HexDecodeOrDie("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b")); // Since HMAC anyhow pads, this is the same as an absent salt. std::string salt = HexDecodeOrDie(""); std::string info = HexDecodeOrDie(""); std::string expected_result = HexDecodeOrDie( "0ac1af7002b3d761d1e55298da9d0506" "b9ae52057220a306e07b6b87e8df21d0" "ea00033de03984d34918"); auto result_or = ComputeWithHkdfStreamingPrf(hash, std::move(ikm), salt, info, expected_result.size()); ASSERT_THAT(result_or, IsOk()); EXPECT_THAT(result_or.value(), Eq(expected_result)); } TEST(HkdfStreamingPrf, TestAgainstHkdfUtil) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } HashType hash = SHA1; util::SecretData ikm = Random::GetRandomKeyBytes(123); std::string salt = Random::GetRandomBytes(234); std::string info = Random::GetRandomBytes(345); auto streaming_result_or = ComputeWithHkdfStreamingPrf(hash, ikm, salt, info, 456); ASSERT_THAT(streaming_result_or, IsOk()); auto compute_hkdf_result_or = Hkdf::ComputeHkdf(hash, ikm, salt, info, 456); ASSERT_THAT(compute_hkdf_result_or, IsOk()); util::SecretData compute_hkdf_result = std::move(compute_hkdf_result_or).value(); EXPECT_THAT(streaming_result_or.value(), Eq(util::SecretDataAsStringView(compute_hkdf_result))); } TEST(HkdfStreamingPrf, TestFipsOnly) { if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Only supported in FIPS-only mode"; } HashType hash = SHA1; util::SecretData ikm = Random::GetRandomKeyBytes(123); std::string salt = Random::GetRandomBytes(234); std::string info = Random::GetRandomBytes(345); EXPECT_THAT(HkdfStreamingPrf::New(hash, std::move(ikm), salt).status(), StatusIs(absl::StatusCode::kInternal)); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/prf/prf_set_util.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/prf/prf_set_util.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/prf/prf_set.h" #include "tink/subtle/mac/stateful_mac.h" #include "tink/subtle/prf/streaming_prf.h" #include "tink/util/input_stream_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { namespace { class PrfFromStreamingPrf : public Prf { public: explicit PrfFromStreamingPrf(std::unique_ptr streaming_prf) : streaming_prf_(std::move(streaming_prf)) {} util::StatusOr Compute(absl::string_view input, size_t output_length) const override { auto inputstream = streaming_prf_->ComputePrf(input); auto output_result = ReadBytesFromStream(output_length, inputstream.get()); if (!output_result.ok()) { return output_result.status(); } std::string output = output_result.value(); return output; } private: std::unique_ptr streaming_prf_; }; class PrfFromStatefulMacFactory : public Prf { public: explicit PrfFromStatefulMacFactory( std::unique_ptr stateful_mac_factory) : stateful_mac_factory_(std::move(stateful_mac_factory)) {} util::StatusOr Compute(absl::string_view input, size_t output_length) const override { auto stateful_mac_result = stateful_mac_factory_->Create(); if (!stateful_mac_result.ok()) { return stateful_mac_result.status(); } auto stateful_mac = std::move(stateful_mac_result.value()); auto status = stateful_mac->Update(input); if (!status.ok()) { return status; } auto output_result = stateful_mac->Finalize(); if (!output_result.ok()) { return output_result.status(); } std::string output = std::move(output_result.value()); if (output.size() < output_length) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("PRF only supports outputs up to ", output.size(), " bytes, but ", output_length, " bytes were requested")); } return output.substr(0, output_length); } private: std::unique_ptr stateful_mac_factory_; }; } // namespace std::unique_ptr CreatePrfFromStreamingPrf( std::unique_ptr streaming_prf) { return absl::make_unique(std::move(streaming_prf)); } std::unique_ptr CreatePrfFromStatefulMacFactory( std::unique_ptr stateful_mac_factory) { return absl::make_unique( std::move(stateful_mac_factory)); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/prf/prf_set_util.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_PRF_PRF_SET_UTIL_H_ #define TINK_SUBTLE_PRF_PRF_SET_UTIL_H_ #include #include "tink/prf/prf_set.h" #include "tink/subtle/mac/stateful_mac.h" #include "tink/subtle/prf/streaming_prf.h" namespace crypto { namespace tink { namespace subtle { // Creates a Prf from a StreamingPrf, taking ownership of the StreamingPrf. std::unique_ptr CreatePrfFromStreamingPrf( std::unique_ptr streaming_prf); // Creates a Prf from a StatefulMacFactory, taking ownership of the factory. // Note that this should only be used with StatefulMacs that actually are a Prf, // like HMAC and CMAC and not with any MACs that are non-deterministic or that // do not produce output indistinguishable from random numbers. std::unique_ptr CreatePrfFromStatefulMacFactory( std::unique_ptr mac_factory); } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_PRF_PRF_SET_UTIL_H_ ================================================ FILE: cc/subtle/prf/prf_set_util_test.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/prf/prf_set_util.h" #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/input_stream.h" #include "tink/prf/prf_set.h" #include "tink/subtle/mac/stateful_mac.h" #include "tink/subtle/prf/streaming_prf.h" #include "tink/util/istream_input_stream.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::IsOk; using ::testing::_; using ::testing::AnyNumber; using ::testing::DefaultValue; using ::testing::Eq; using ::testing::NiceMock; using ::testing::Not; using ::testing::Return; using ::testing::StrEq; class MockPrf : public Prf { public: MOCK_METHOD(util::StatusOr, Compute, (absl::string_view input, size_t output_length), (const)); }; class MockStatefulMac : public StatefulMac { public: MOCK_METHOD(util::Status, Update, (absl::string_view data), (override)); MOCK_METHOD(util::StatusOr, Finalize, (), (override)); }; class FakeStatefulMacFactory : public StatefulMacFactory { public: FakeStatefulMacFactory(util::Status update_status, util::StatusOr finalize_result) : update_status_(update_status), finalize_result_(finalize_result) {} util::StatusOr> Create() const override { auto mac_mock = absl::make_unique>(); ON_CALL(*mac_mock, Update(_)).WillByDefault(Return(update_status_)); ON_CALL(*mac_mock, Finalize()).WillByDefault(Return(finalize_result_)); std::unique_ptr result = std::move(mac_mock); return std::move(result); } private: util::Status update_status_; util::StatusOr finalize_result_; }; class MockStreamingPrf : public StreamingPrf { public: MOCK_METHOD(std::unique_ptr, ComputePrf, (absl::string_view input), (const)); }; std::unique_ptr GetInputStreamForString(const std::string& input) { return absl::make_unique( absl::make_unique(input)); } class PrfFromStatefulMacFactoryTest : public ::testing::Test { protected: void SetUpWithResult(util::Status update_status, util::StatusOr finalize_result) { prf_ = CreatePrfFromStatefulMacFactory( absl::make_unique(update_status, finalize_result)); } Prf* prf() { return prf_.get(); } private: std::unique_ptr prf_; }; TEST_F(PrfFromStatefulMacFactoryTest, ComputePrf) { SetUpWithResult(util::OkStatus(), std::string("mock_stateful_mac")); auto output_result = prf()->Compute("test_input", 5); ASSERT_TRUE(output_result.ok()) << output_result.status(); EXPECT_THAT(output_result.value(), StrEq("mock_")); } TEST_F(PrfFromStatefulMacFactoryTest, ComputePrfUpdateFails) { SetUpWithResult(util::Status(absl::StatusCode::kInternal, "UpdateFailed"), std::string("mock_stateful_mac")); auto output_result = prf()->Compute("test_input", 5); EXPECT_FALSE(output_result.ok()); EXPECT_THAT(output_result.status().message(), Eq("UpdateFailed")); } TEST_F(PrfFromStatefulMacFactoryTest, ComputePrfFinalizeFails) { SetUpWithResult(util::OkStatus(), util::Status(absl::StatusCode::kInternal, "FinalizeFailed")); auto output_result = prf()->Compute("test_input", 5); EXPECT_FALSE(output_result.ok()); EXPECT_THAT(output_result.status().message(), Eq("FinalizeFailed")); } TEST_F(PrfFromStatefulMacFactoryTest, ComputePrfTooMuchOutputRequested) { SetUpWithResult(util::OkStatus(), std::string("mock_stateful_mac")); auto output_result = prf()->Compute("test_input", 100); EXPECT_FALSE(output_result.ok()); } class PrfFromStreamingPrfTest : public ::testing::Test { protected: void SetUp() override { auto streaming_prf = absl::make_unique>(); DefaultValue>::SetFactory( [] { return GetInputStreamForString("output"); }); EXPECT_CALL(*streaming_prf, ComputePrf(Eq("input"))).Times(AnyNumber()); prf_ = CreatePrfFromStreamingPrf(std::move(streaming_prf)); } Prf* prf() { return prf_.get(); } private: std::unique_ptr prf_; }; TEST_F(PrfFromStreamingPrfTest, ComputePrfBasic) { auto output_result = prf()->Compute("input", 5); ASSERT_THAT(output_result, IsOk()); EXPECT_THAT(output_result.value(), StrEq("outpu")); } TEST_F(PrfFromStreamingPrfTest, ComputeTwice) { auto output_result = prf()->Compute("input", 5); ASSERT_THAT(output_result, IsOk()); EXPECT_THAT(output_result.value(), StrEq("outpu")); output_result = prf()->Compute("input", 5); ASSERT_THAT(output_result, IsOk()); EXPECT_THAT(output_result.value(), StrEq("outpu")); } TEST_F(PrfFromStreamingPrfTest, ComputeSubstring) { auto output_result = prf()->Compute("input", 5); ASSERT_THAT(output_result, IsOk()); EXPECT_THAT(output_result.value(), StrEq("outpu")); output_result = prf()->Compute("input", 6); ASSERT_THAT(output_result, IsOk()); EXPECT_THAT(output_result.value(), StrEq("output")); output_result = prf()->Compute("input", 2); ASSERT_THAT(output_result, IsOk()); EXPECT_THAT(output_result.value(), StrEq("ou")); } TEST_F(PrfFromStreamingPrfTest, ComputeTooMuch) { auto output_result = prf()->Compute("input", 5); ASSERT_THAT(output_result, IsOk()); EXPECT_THAT(output_result.value(), StrEq("outpu")); output_result = prf()->Compute("input", 100); EXPECT_THAT(output_result, Not(IsOk())) << "Output should not be okay, too much output requested"; } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/prf/streaming_prf.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_PRF_STREAMING_PRF_H_ #define TINK_SUBTLE_PRF_STREAMING_PRF_H_ #include #include "absl/strings/string_view.h" #include "tink/input_stream.h" namespace crypto { namespace tink { /////////////////////////////////////////////////////////////////////////////// // Streaming API interface for PseudoRandomFunctions. // // Implementations of this are indistinguishable from true random functions. // // For a formal description of the security properties, see the documentation in // the corresponding Java class. class StreamingPrf { public: // Returns a stream of pseudorandom bytes for this input. Calling Get twice // with the same input will return a copy of the same input stream. virtual std::unique_ptr ComputePrf( absl::string_view input) const = 0; virtual ~StreamingPrf() = default; }; } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_PRF_STREAMING_PRF_H_ ================================================ FILE: cc/subtle/prf/streaming_prf_wrapper.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/prf/streaming_prf_wrapper.h" #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/input_stream.h" #include "tink/primitive_set.h" #include "tink/subtle/prf/streaming_prf.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { class StreamingPrfSetWrapper : public StreamingPrf { public: explicit StreamingPrfSetWrapper( std::unique_ptr> streaming_prf_set) : streaming_prf_set_(std::move(streaming_prf_set)) {} std::unique_ptr ComputePrf( absl::string_view input) const override { return streaming_prf_set_->get_primary()->get_primitive().ComputePrf(input); } ~StreamingPrfSetWrapper() override = default; private: std::unique_ptr> streaming_prf_set_; }; ::crypto::tink::util::StatusOr> StreamingPrfWrapper::Wrap(std::unique_ptr> streaming_prf_set) const { if (!streaming_prf_set) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, "Passed in streaming_prf_set must be non-NULL"); } auto entries = streaming_prf_set->get_all(); if (entries.size() != 1) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("StreamingPrfWrapper can only create StreamingPrf objects " "from keysets " "with exactly one key, but the but the given set has ", entries.size(), " keys.")); } auto* entry = entries[0]; if (entry->get_status() != google::crypto::tink::KeyStatusType::ENABLED) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("StreamingPrfWrapper can only create StreamingPrf objects " "from keysets " "with an enabled keys, but the key is ", entry->get_status())); } if (entry->get_output_prefix_type() != google::crypto::tink::OutputPrefixType::RAW) { return crypto::tink::util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("StreamingPrfWrapper can only create StreamingPrf objects " "from keysets with a single enabled key with " "OutputPrefixType::RAW, " "but output_prefix_type is ", entry->get_output_prefix_type())); } return { absl::make_unique(std::move(streaming_prf_set))}; } } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/prf/streaming_prf_wrapper.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_PRF_STREAMING_PRF_WRAPPER_H_ #define TINK_SUBTLE_PRF_STREAMING_PRF_WRAPPER_H_ #include #include "tink/primitive_set.h" #include "tink/primitive_wrapper.h" #include "tink/subtle/prf/streaming_prf.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // Wraps a set of StreamingPrf-instances containing a single StreamingPrf with a // raw key into a StreamingPrf (essentially just returning the initial prf). // // It is unclear how key rotation should work for Prfs; we use this one to // produce a single one in case the keyset is compatible, and fail otherwise. class StreamingPrfWrapper : public PrimitiveWrapper { public: util::StatusOr> Wrap( std::unique_ptr> streaming_prf_set) const override; }; } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_PRF_STREAMING_PRF_WRAPPER_H_ ================================================ FILE: cc/subtle/prf/streaming_prf_wrapper_test.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/prf/streaming_prf_wrapper.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/input_stream.h" #include "tink/primitive_set.h" #include "tink/subtle/prf/streaming_prf.h" #include "tink/util/input_stream_util.h" #include "tink/util/istream_input_stream.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::KeysetInfo; using ::google::crypto::tink::KeyStatusType; using ::google::crypto::tink::OutputPrefixType; using ::testing::Eq; using ::testing::HasSubstr; class DummyStreamingPrf : public StreamingPrf { public: explicit DummyStreamingPrf(absl::string_view name) : name_(name) {} std::unique_ptr ComputePrf( absl::string_view input) const override { return absl::make_unique( absl::make_unique( absl::StrCat(name_.length(), ":", name_, input))); } private: std::string name_; }; TEST(AeadSetWrapperTest, WrapNullptr) { StreamingPrfWrapper wrapper; EXPECT_THAT( wrapper.Wrap(nullptr).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("non-NULL"))); } TEST(KeysetDeriverWrapperTest, WrapEmpty) { EXPECT_THAT(StreamingPrfWrapper() .Wrap(absl::make_unique>()) .status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("exactly one key"))); } TEST(KeysetDeriverWrapperTest, WrapSingle) { auto prf_set = absl::make_unique>(); KeysetInfo::KeyInfo key_info; key_info.set_key_id(1234); key_info.set_status(KeyStatusType::ENABLED); key_info.set_output_prefix_type(OutputPrefixType::RAW); auto entry_or = prf_set->AddPrimitive( absl::make_unique("single_key"), key_info); ASSERT_THAT(entry_or, IsOk()); EXPECT_THAT(prf_set->set_primary(entry_or.value()), IsOk()); auto wrapped_prf = StreamingPrfWrapper().Wrap(std::move(prf_set)); ASSERT_THAT(wrapped_prf, IsOk()); auto prf_output = ReadBytesFromStream( 23, wrapped_prf.value()->ComputePrf("input_text").get()); ASSERT_THAT(prf_output, IsOk()); EXPECT_THAT(prf_output.value(), Eq("10:single_keyinput_text")); } TEST(KeysetDeriverWrapperTest, WrapNonRaw) { auto prf_set = absl::make_unique>(); KeysetInfo::KeyInfo key_info; key_info.set_key_id(1234); key_info.set_status(KeyStatusType::ENABLED); key_info.set_output_prefix_type(OutputPrefixType::TINK); auto entry_or = prf_set->AddPrimitive( absl::make_unique("single_key"), key_info); ASSERT_THAT(entry_or, IsOk()); EXPECT_THAT(prf_set->set_primary(entry_or.value()), IsOk()); EXPECT_THAT(StreamingPrfWrapper().Wrap(std::move(prf_set)).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("output_prefix_type"))); } TEST(KeysetDeriverWrapperTest, WrapMultiple) { auto prf_set = absl::make_unique>(); KeysetInfo::KeyInfo key_info; key_info.set_key_id(1234); key_info.set_status(KeyStatusType::ENABLED); key_info.set_output_prefix_type(OutputPrefixType::RAW); auto entry_or = prf_set->AddPrimitive( absl::make_unique("single_key"), key_info); ASSERT_THAT(entry_or, IsOk()); EXPECT_THAT(prf_set->set_primary(entry_or.value()), IsOk()); key_info.set_key_id(2345); EXPECT_THAT( prf_set ->AddPrimitive(absl::make_unique("second_key"), key_info) .status(), IsOk()); EXPECT_THAT(StreamingPrfWrapper().Wrap(std::move(prf_set)).status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("given set has 2 keys"))); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/random.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/random.h" #include #include #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/types/span.h" #include "openssl/rand.h" #include "tink/subtle/subtle_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace subtle { namespace { template UintType GetRandomUint() { UintType result; Random::GetRandomBytes( absl::MakeSpan(reinterpret_cast(&result), sizeof(result))) .IgnoreError(); return result; } } // namespace // BoringSSL documentation says that it always returns 1; while // OpenSSL documentation says that it returns "1 on success, -1 if not supported // by the current RAND method, or 0 on other failure" // (https://www.openssl.org/docs/man1.1.1/man3/RAND_bytes.html). // // In case of insufficient entropy at the time of the call, BoringSSL's // RAND_bytes will behave in different ways depending on the operating system, // version, and FIPS mode. For Linux with a semi-recent kernel, it will block // until the system has collected at least 128 bits since boot. For old // kernels without getrandom support (and not in FIPS mode), it will resort to // /dev/urandom. util::Status Random::GetRandomBytes(absl::Span buffer) { auto buffer_ptr = reinterpret_cast(buffer.data()); if (RAND_bytes(buffer_ptr, buffer.size()) <= 0) { return util::Status(absl::StatusCode::kInternal, absl::StrCat("RAND_bytes failed to generate ", buffer.size(), " bytes")); } return util::OkStatus(); } std::string Random::GetRandomBytes(size_t length) { std::string buffer; ResizeStringUninitialized(&buffer, length); // TODO(b/207466225): Modify the return to be a StatusOr as // OpenSSL can return an error. GetRandomBytes(absl::MakeSpan(buffer)).IgnoreError(); return buffer; } uint32_t Random::GetRandomUInt32() { return GetRandomUint(); } uint16_t Random::GetRandomUInt16() { return GetRandomUint(); } uint8_t Random::GetRandomUInt8() { return GetRandomUint(); } util::SecretData Random::GetRandomKeyBytes(size_t length) { util::SecretData buf(length, 0); GetRandomBytes( absl::MakeSpan(reinterpret_cast(buf.data()), buf.size())) .IgnoreError(); return buf; } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/random.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_RANDOM_H_ #define TINK_SUBTLE_RANDOM_H_ #include #include #include #include #include "absl/types/span.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace subtle { class Random { public: // Fills the given `buffer` with random bytes. static util::Status GetRandomBytes(absl::Span buffer); // Returns a random string of desired length. static std::string GetRandomBytes(size_t length); static uint32_t GetRandomUInt32(); static uint16_t GetRandomUInt16(); static uint8_t GetRandomUInt8(); // Returns length bytes of random data stored in specialized key container. static util::SecretData GetRandomKeyBytes(size_t length); }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_RANDOM_H_ ================================================ FILE: cc/subtle/random_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/random.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/flat_hash_set.h" #include "absl/types/span.h" #include "tink/util/secret_data.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace subtle { namespace { // Iterations for statistic tests. constexpr int kTests = 10000; using ::testing::Gt; using ::testing::Lt; using ::testing::SizeIs; using ::crypto::tink::test::IsOk; TEST(RandomTest, MultipleFilledBuffersAreUnique) { constexpr int kNumRandomItems = 32; absl::flat_hash_set random_strings; for (int i = 0; i < kNumRandomItems; i++) { std::string s(16, '\0'); EXPECT_THAT(Random::GetRandomBytes(absl::MakeSpan(s)), IsOk()); random_strings.insert(s); } EXPECT_THAT(random_strings, SizeIs(kNumRandomItems)); } TEST(RandomTest, MultipleGeneratedRandomStringAreUnique) { constexpr int kNumRandomItems = 32; absl::flat_hash_set random_strings; for (int i = 0; i < kNumRandomItems; i++) { std::string s = Random::GetRandomBytes(16); EXPECT_THAT(s, SizeIs(16)); random_strings.insert(s); } EXPECT_THAT(random_strings, SizeIs(kNumRandomItems)); } TEST(RandomTest, MultipleGeneratedSecretDataAreUnique) { constexpr int kNumRandomItems = 32; absl::flat_hash_set random_keys; for (int i = 0; i < kNumRandomItems; i++) { util::SecretData key = Random::GetRandomKeyBytes(16); EXPECT_THAT(key, SizeIs(16)); random_keys.insert(key); } EXPECT_THAT(random_keys, SizeIs(kNumRandomItems)); } TEST(RandomTest, KeyBytesRandomGenerationIsUniform) { constexpr int kKeyLengthInBytes = 32; std::vector bit_counts(8 * kKeyLengthInBytes); for (int i = 0; i < kTests; ++i) { util::SecretData random = Random::GetRandomKeyBytes(kKeyLengthInBytes); for (int bit = 0; bit < 8 * kKeyLengthInBytes; ++bit) { if (random[bit / 8] & (1 << (bit % 8))) { ++bit_counts[bit]; } } } for (int i = 0; i < 8 * kKeyLengthInBytes; ++i) { EXPECT_THAT(bit_counts[i], Gt(kTests * 0.4)) << i; EXPECT_THAT(bit_counts[i], Lt(kTests * 0.6)) << i; } } TEST(RandomTest, UInt8RandomGenerationIsUniform) { const int kNumBits = 8; std::vector bit_counts(kNumBits); for (int i = 0; i < kTests; ++i) { uint8_t random = Random::GetRandomUInt8(); for (int bit = 0; bit < kNumBits; ++bit) { if (random & (1 << bit)) { ++bit_counts[bit]; } } } for (int i = 0; i < kNumBits; ++i) { EXPECT_THAT(bit_counts[i], Gt(kTests * 0.4)) << i; EXPECT_THAT(bit_counts[i], Lt(kTests * 0.6)) << i; } } TEST(RandomTest, UInt16RandomGenerationIsUniform) { const int kNumBits = 16; std::vector bit_counts(kNumBits); for (int i = 0; i < kTests; ++i) { uint16_t random = Random::GetRandomUInt16(); for (int bit = 0; bit < kNumBits; ++bit) { if (random & (1 << bit)) { ++bit_counts[bit]; } } } for (int i = 0; i < kNumBits; ++i) { EXPECT_THAT(bit_counts[i], Gt(kTests * 0.4)) << i; EXPECT_THAT(bit_counts[i], Lt(kTests * 0.6)) << i; } } TEST(RandomTest, UInt32RandomGenerationIsUniform) { const int kNumBits = 32; std::vector bit_counts(kNumBits); for (int i = 0; i < kTests; ++i) { uint32_t random = Random::GetRandomUInt32(); for (int bit = 0; bit < kNumBits; ++bit) { if (random & (1 << bit)) { ++bit_counts[bit]; } } } for (int i = 0; i < kNumBits; ++i) { EXPECT_THAT(bit_counts[i], Gt(kTests * 0.4)) << i; EXPECT_THAT(bit_counts[i], Lt(kTests * 0.6)) << i; } } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/rsa_ssa_pkcs1_sign_boringssl.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/rsa_ssa_pkcs1_sign_boringssl.h" #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "openssl/rsa.h" #include "tink/internal/bn_util.h" #include "tink/internal/err_util.h" #include "tink/internal/fips_utils.h" #include "tink/internal/md_util.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/internal/util.h" #include "tink/public_key_sign.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { util::StatusOr> RsaSsaPkcs1SignBoringSsl::New( const internal::RsaPrivateKey& private_key, const internal::RsaSsaPkcs1Params& params) { util::Status status = internal::CheckFipsCompatibility(); if (!status.ok()) { return status; } // Check if the hash type is safe to use. util::Status is_safe = internal::IsHashTypeSafeForSignature(params.hash_type); if (!is_safe.ok()) { return is_safe; } util::StatusOr sig_hash = internal::EvpHashFromHashType(params.hash_type); if (!sig_hash.ok()) { return sig_hash.status(); } // Check RSA's modulus. util::StatusOr> n = internal::StringToBignum(private_key.n); if (!n.ok()) { return n.status(); } auto modulus_status = internal::ValidateRsaModulusSize(BN_num_bits(n->get())); if (!modulus_status.ok()) { return modulus_status; } // The RSA modulus and exponent are checked as part of the conversion to // internal::SslUniquePtr. util::StatusOr> rsa = internal::RsaPrivateKeyToRsa(private_key); if (!rsa.ok()) { return rsa.status(); } return {absl::WrapUnique( new RsaSsaPkcs1SignBoringSsl(*std::move(rsa), *sig_hash))}; } util::StatusOr RsaSsaPkcs1SignBoringSsl::Sign( absl::string_view data) const { data = internal::EnsureStringNonNull(data); util::StatusOr digest = internal::ComputeHash(data, *sig_hash_); if (!digest.ok()) { return digest.status(); } std::string signature; ResizeStringUninitialized(&signature, RSA_size(private_key_.get())); unsigned int signature_length = 0; if (RSA_sign(/*hash_nid=*/EVP_MD_type(sig_hash_), /*digest=*/reinterpret_cast(digest->data()), /*digest_len=*/digest->size(), /*out=*/reinterpret_cast(&signature[0]), /*out_len=*/&signature_length, /*rsa=*/private_key_.get()) != 1) { // TODO(b/112581512): Decide if it's safe to propagate the BoringSSL error. // For now, just empty the error stack. internal::GetSslErrors(); return util::Status(absl::StatusCode::kInternal, "Signing failed."); } signature.resize(signature_length); return signature; } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/rsa_ssa_pkcs1_sign_boringssl.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_RSA_SSA_PKCS1_SIGN_BORINGSSL_H_ #define TINK_SUBTLE_RSA_SSA_PKCS1_SIGN_BORINGSSL_H_ #include #include #include #include "absl/strings/string_view.h" #include "openssl/ec.h" #include "openssl/rsa.h" #include "tink/internal/fips_utils.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/public_key_sign.h" #include "tink/subtle/common_enums.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // The RSA SSA (Signature Schemes with Appendix) using PKCS1 (Public-Key // Cryptography Standards) encoding is defined at // https://tools.ietf.org/html/rfc8017#section-8.2). This implemention uses // Boring SSL for the underlying cryptographic operations. class RsaSsaPkcs1SignBoringSsl : public PublicKeySign { public: static crypto::tink::util::StatusOr> New( const internal::RsaPrivateKey& private_key, const internal::RsaSsaPkcs1Params& params); // Computes the signature for 'data'. crypto::tink::util::StatusOr Sign( absl::string_view data) const override; ~RsaSsaPkcs1SignBoringSsl() override = default; static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kRequiresBoringCrypto; private: RsaSsaPkcs1SignBoringSsl(internal::SslUniquePtr private_key, const EVP_MD* sig_hash) : private_key_(std::move(private_key)), sig_hash_(sig_hash) {} const internal::SslUniquePtr private_key_; const EVP_MD* const sig_hash_; // Owned by BoringSSL. }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_RSA_SSA_PKCS1_SIGN_BORINGSSL_H_ ================================================ FILE: cc/subtle/rsa_ssa_pkcs1_sign_boringssl_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/rsa_ssa_pkcs1_sign_boringssl.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "openssl/bn.h" #include "openssl/crypto.h" #include "openssl/rsa.h" #include "tink/internal/fips_utils.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/rsa_ssa_pkcs1_verify_boringssl.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::IsEmpty; using ::testing::Not; class RsaPkcs1SignBoringsslTest : public ::testing::Test { public: RsaPkcs1SignBoringsslTest() : rsa_f4_(BN_new()) { EXPECT_TRUE(BN_set_word(rsa_f4_.get(), RSA_F4)); EXPECT_THAT( internal::NewRsaKeyPair(/*modulus_size_in_bits=*/2048, rsa_f4_.get(), &private_key_, &public_key_), IsOk()); } protected: internal::SslUniquePtr rsa_f4_; internal::RsaPrivateKey private_key_; internal::RsaPublicKey public_key_; }; TEST_F(RsaPkcs1SignBoringsslTest, EncodesPkcs1) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Test not run in FIPS-only mode"; } internal::RsaSsaPkcs1Params params{/*sig_hash=*/HashType::SHA256}; auto signer_or = RsaSsaPkcs1SignBoringSsl::New(private_key_, params); ASSERT_THAT(signer_or, IsOk()); auto signature_or = signer_or.value()->Sign("testdata"); ASSERT_THAT(signature_or, IsOk()); EXPECT_THAT(signature_or.value(), Not(IsEmpty())); auto verifier_or = RsaSsaPkcs1VerifyBoringSsl::New(public_key_, params); ASSERT_THAT(verifier_or, IsOk()); EXPECT_THAT(verifier_or.value()->Verify(signature_or.value(), "testdata"), IsOk()); } TEST_F(RsaPkcs1SignBoringsslTest, EncodesPkcs1WithSeparateHashes) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Test not run in FIPS-only mode"; } internal::RsaSsaPkcs1Params params{/*sig_hash=*/HashType::SHA256}; auto signer_or = RsaSsaPkcs1SignBoringSsl::New(private_key_, params); ASSERT_THAT(signer_or, IsOk()); auto signature_or = signer_or.value()->Sign("testdata"); ASSERT_THAT(signature_or, IsOk()); EXPECT_THAT(signature_or.value(), Not(IsEmpty())); auto verifier_or = RsaSsaPkcs1VerifyBoringSsl::New(public_key_, params); ASSERT_THAT(verifier_or, IsOk()); EXPECT_THAT(verifier_or.value()->Verify(signature_or.value(), "testdata"), IsOk()); } TEST_F(RsaPkcs1SignBoringsslTest, RejectsUnsafeHash) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Test not run in FIPS-only mode"; } internal::RsaSsaPkcs1Params params{/*sig_hash=*/HashType::SHA1}; ASSERT_THAT(RsaSsaPkcs1SignBoringSsl::New(private_key_, params).status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(RsaPkcs1SignBoringsslTest, RejectsInvalidCrtParams) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Test not run in FIPS-only mode"; } internal::RsaSsaPkcs1Params params{/*sig_hash=*/HashType::SHA256}; ASSERT_THAT(private_key_.crt, Not(IsEmpty())); ASSERT_THAT(private_key_.dq, Not(IsEmpty())); ASSERT_THAT(private_key_.dp, Not(IsEmpty())); // Flip a few bits in the CRT parameters; check that creation fails. { internal::RsaPrivateKey key = private_key_; key.crt[0] ^= 0x80; auto signer_or = RsaSsaPkcs1SignBoringSsl::New(key, params); EXPECT_THAT(signer_or.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } { internal::RsaPrivateKey key = private_key_; key.dq[0] ^= 0x08; auto signer_or = RsaSsaPkcs1SignBoringSsl::New(key, params); EXPECT_THAT(signer_or.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } { internal::RsaPrivateKey key = private_key_; key.dp[0] ^= 0x04; auto signer_or = RsaSsaPkcs1SignBoringSsl::New(key, params); EXPECT_THAT(signer_or.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } // FIPS-only mode test TEST_F(RsaPkcs1SignBoringsslTest, TestFipsFailWithoutBoringCrypto) { if (!internal::IsFipsModeEnabled() || internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test assumes kOnlyUseFips but BoringCrypto is unavailable."; } internal::RsaSsaPkcs1Params params{/*sig_hash=*/HashType::SHA256}; EXPECT_THAT(RsaSsaPkcs1SignBoringSsl::New(private_key_, params).status(), StatusIs(absl::StatusCode::kInternal)); } TEST_F(RsaPkcs1SignBoringsslTest, TestRestrictedFipsModuli) { if (!internal::IsFipsModeEnabled() || !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test assumes kOnlyUseFips and BoringCrypto."; } internal::RsaPrivateKey private_key; internal::RsaPublicKey public_key; EXPECT_THAT(internal::NewRsaKeyPair(/*modulus_size_in_bits=*/4096, rsa_f4_.get(), &private_key, &public_key), IsOk()); internal::RsaSsaPkcs1Params params{/*sig_hash=*/HashType::SHA256}; EXPECT_THAT(RsaSsaPkcs1SignBoringSsl::New(private_key, params).status(), StatusIs(absl::StatusCode::kInternal)); } TEST_F(RsaPkcs1SignBoringsslTest, TestAllowedFipsModuli) { if (!internal::IsFipsModeEnabled() || !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test assumes kOnlyUseFips and BoringCrypto."; } internal::RsaPrivateKey private_key; internal::RsaPublicKey public_key; EXPECT_THAT(internal::NewRsaKeyPair(/*modulus_size_in_bits=*/3072, rsa_f4_.get(), &private_key, &public_key), IsOk()); internal::RsaSsaPkcs1Params params{/*sig_hash=*/HashType::SHA256}; EXPECT_THAT(RsaSsaPkcs1SignBoringSsl::New(private_key, params).status(), IsOk()); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/rsa_ssa_pkcs1_verify_boringssl.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/rsa_ssa_pkcs1_verify_boringssl.h" #include #include #include #include #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "openssl/bn.h" #include "openssl/evp.h" #include "openssl/rsa.h" #include "tink/internal/fips_utils.h" #include "tink/internal/md_util.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/internal/util.h" #include "tink/subtle/common_enums.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { util::StatusOr> RsaSsaPkcs1VerifyBoringSsl::New(const internal::RsaPublicKey& pub_key, const internal::RsaSsaPkcs1Params& params) { util::Status status = internal::CheckFipsCompatibility(); if (!status.ok()) { return status; } // Check if the hash type is safe to use. util::Status is_safe = internal::IsHashTypeSafeForSignature(params.hash_type); if (!is_safe.ok()) { return is_safe; } util::StatusOr sig_hash = internal::EvpHashFromHashType(params.hash_type); if (!sig_hash.ok()) { return sig_hash.status(); } // The RSA modulus and exponent are checked as part of the conversion to // internal::SslUniquePtr. util::StatusOr> rsa = internal::RsaPublicKeyToRsa(pub_key); if (!rsa.ok()) { return rsa.status(); } std::unique_ptr verify( new RsaSsaPkcs1VerifyBoringSsl(*std::move(rsa), *sig_hash)); return std::move(verify); } util::Status RsaSsaPkcs1VerifyBoringSsl::Verify(absl::string_view signature, absl::string_view data) const { // BoringSSL expects a non-null pointer for data, // regardless of whether the size is 0. data = internal::EnsureStringNonNull(data); util::StatusOr digest = internal::ComputeHash(data, *sig_hash_); if (!digest.ok()) { return digest.status(); } if (RSA_verify(EVP_MD_type(sig_hash_), /*digest=*/reinterpret_cast(digest->data()), /*digest_len=*/digest->size(), /*sig=*/reinterpret_cast(signature.data()), /*sig_len=*/signature.length(), /*rsa=*/rsa_.get()) != 1) { // Signature is invalid. return util::Status(absl::StatusCode::kInvalidArgument, "Signature is not valid."); } return util::OkStatus(); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/rsa_ssa_pkcs1_verify_boringssl.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_RSA_SSA_PKCS1_VERIFY_BORINGSSL_H_ #define TINK_SUBTLE_RSA_SSA_PKCS1_VERIFY_BORINGSSL_H_ #include #include #include #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "openssl/rsa.h" #include "tink/internal/fips_utils.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/public_key_verify.h" #include "tink/subtle/common_enums.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // RSA SSA (Signature Schemes with Appendix) using PKCS1 (Public-Key // Cryptography Standards) encoding is defined at // https://tools.ietf.org/html/rfc8017#section-8.2). This implemention uses // BoringSSL for the underlying cryptographic operations. class RsaSsaPkcs1VerifyBoringSsl : public PublicKeyVerify { public: static crypto::tink::util::StatusOr< std::unique_ptr> New(const internal::RsaPublicKey& pub_key, const internal::RsaSsaPkcs1Params& params); // Verifies that 'signature' is a digital signature for 'data'. crypto::tink::util::Status Verify(absl::string_view signature, absl::string_view data) const override; ~RsaSsaPkcs1VerifyBoringSsl() override = default; static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kRequiresBoringCrypto; private: // To reach 128-bit security strength, RSA's modulus must be at least 3072-bit // while 2048-bit RSA key only has 112-bit security. Nevertheless, a 2048-bit // RSA key is considered safe by NIST until 2030 (see // https://www.keylength.com/en/4/). static constexpr size_t kMinModulusSizeInBits = 2048; RsaSsaPkcs1VerifyBoringSsl(internal::SslUniquePtr rsa, const EVP_MD* sig_hash) : rsa_(std::move(rsa)), sig_hash_(sig_hash) {} const internal::SslUniquePtr rsa_; const EVP_MD* const sig_hash_; // Owned by BoringSSL. }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_RSA_SSA_PKCS1_VERIFY_BORINGSSL_H_ ================================================ FILE: cc/subtle/rsa_ssa_pkcs1_verify_boringssl_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/rsa_ssa_pkcs1_verify_boringssl.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "openssl/bn.h" #include "include/rapidjson/document.h" #include "tink/internal/err_util.h" #include "tink/internal/fips_utils.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/wycheproof_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; class RsaSsaPkcs1VerifyBoringSslTest : public ::testing::Test {}; // Test vector from // https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Digital-Signatures struct NistTestVector { std::string n; std::string e; std::string message; std::string signature; HashType sig_hash; }; static const NistTestVector nist_test_vector{ absl::HexStringToBytes( "c47abacc2a84d56f3614d92fd62ed36ddde459664b9301dcd1d61781cfcc026bcb2399" "bee7e75681a80b7bf500e2d08ceae1c42ec0b707927f2b2fe92ae852087d25f1d260cc" "74905ee5f9b254ed05494a9fe06732c3680992dd6f0dc634568d11542a705f83ae96d2" "a49763d5fbb24398edf3702bc94bc168190166492b8671de874bb9cecb058c6c8344aa" "8c93754d6effcd44a41ed7de0a9dcd9144437f212b18881d042d331a4618a9e630ef9b" "b66305e4fdf8f0391b3b2313fe549f0189ff968b92f33c266a4bc2cffc897d1937eeb9" "e406f5d0eaa7a14782e76af3fce98f54ed237b4a04a4159a5f6250a296a902880204e6" "1d891c4da29f2d65f34cbb"), absl::HexStringToBytes("49d2a1"), absl::HexStringToBytes( "95123c8d1b236540b86976a11cea31f8bd4e6c54c235147d20ce722b03a6ad756fbd91" "8c27df8ea9ce3104444c0bbe877305bc02e35535a02a58dcda306e632ad30b3dc3ce0b" "a97fdf46ec192965dd9cd7f4a71b02b8cba3d442646eeec4af590824ca98d74fbca934" "d0b6867aa1991f3040b707e806de6e66b5934f05509bea"), absl::HexStringToBytes( "51265d96f11ab338762891cb29bf3f1d2b3305107063f5f3245af376dfcc7027d39365" "de70a31db05e9e10eb6148cb7f6425f0c93c4fb0e2291adbd22c77656afc196858a11e" "1c670d9eeb592613e69eb4f3aa501730743ac4464486c7ae68fd509e896f63884e9424" "f69c1c5397959f1e52a368667a598a1fc90125273d9341295d2f8e1cc4969bf228c860" "e07a3546be2eeda1cde48ee94d062801fe666e4a7ae8cb9cd79262c017b081af874ff0" "0453ca43e34efdb43fffb0bb42a4e2d32a5e5cc9e8546a221fe930250e5f5333e0efe5" "8ffebf19369a3b8ae5a67f6a048bc9ef915bda25160729b508667ada84a0c27e7e26cf" "2abca413e5e4693f4a9405"), HashType::SHA256}; TEST_F(RsaSsaPkcs1VerifyBoringSslTest, BasicVerify) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Test not run in FIPS-only mode"; } internal::RsaPublicKey pub_key{nist_test_vector.n, nist_test_vector.e}; internal::RsaSsaPkcs1Params params{nist_test_vector.sig_hash}; auto verifier_result = RsaSsaPkcs1VerifyBoringSsl::New(pub_key, params); ASSERT_TRUE(verifier_result.ok()) << verifier_result.status(); auto verifier = std::move(verifier_result.value()); auto status = verifier->Verify(nist_test_vector.signature, nist_test_vector.message); EXPECT_TRUE(status.ok()) << status << internal::GetSslErrors(); } TEST_F(RsaSsaPkcs1VerifyBoringSslTest, NewErrors) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Test not run in FIPS-only mode"; } internal::RsaPublicKey nist_pub_key{nist_test_vector.n, nist_test_vector.e}; internal::RsaSsaPkcs1Params nist_params{nist_test_vector.sig_hash}; internal::RsaPublicKey small_pub_key{std::string("\x23"), std::string("\x3")}; internal::RsaSsaPkcs1Params sha1_hash_params{HashType::SHA1}; { // Small modulus. auto result = RsaSsaPkcs1VerifyBoringSsl::New(small_pub_key, nist_params); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "only modulus size >= 2048-bit is supported", std::string(result.status().message())); } { // Use SHA1 for digital signature. auto result = RsaSsaPkcs1VerifyBoringSsl::New(nist_pub_key, sha1_hash_params); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "SHA1 is not safe for digital signature", std::string(result.status().message())); } } TEST_F(RsaSsaPkcs1VerifyBoringSslTest, Modification) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Test not run in FIPS-only mode"; } internal::RsaPublicKey pub_key{nist_test_vector.n, nist_test_vector.e}; internal::RsaSsaPkcs1Params params{nist_test_vector.sig_hash}; auto verifier_result = RsaSsaPkcs1VerifyBoringSsl::New(pub_key, params); ASSERT_TRUE(verifier_result.ok()) << verifier_result.status(); auto verifier = std::move(verifier_result.value()); // Modify the message. for (std::size_t i = 0; i < nist_test_vector.message.length(); i++) { std::string modified_message = nist_test_vector.message; modified_message[i / 8] ^= 1 << (i % 8); auto status = verifier->Verify(nist_test_vector.signature, modified_message); EXPECT_FALSE(status.ok()) << status << internal::GetSslErrors(); } // Modify the signature. for (std::size_t i = 0; i < nist_test_vector.signature.length(); i++) { std::string modified_signature = nist_test_vector.signature; modified_signature[i / 8] ^= 1 << (i % 8); auto status = verifier->Verify(modified_signature, nist_test_vector.message); EXPECT_FALSE(status.ok()) << status << internal::GetSslErrors(); } // Truncate the signature. for (std::size_t i = 0; i < nist_test_vector.signature.length(); i++) { std::string truncated_signature(nist_test_vector.signature, 0, i); auto status = verifier->Verify(truncated_signature, nist_test_vector.message); EXPECT_FALSE(status.ok()) << status << internal::GetSslErrors(); } } static util::StatusOr> GetVerifier( const rapidjson::Value& test_group) { internal::RsaPublicKey key; key.n = WycheproofUtil::GetInteger(test_group["n"]); key.e = WycheproofUtil::GetInteger(test_group["e"]); HashType md = WycheproofUtil::GetHashType(test_group["sha"]); internal::RsaSsaPkcs1Params params; params.hash_type = md; auto result = RsaSsaPkcs1VerifyBoringSsl::New(key, params); if (!result.ok()) { std::cout << "Failed: " << result.status() << "\n"; } return result; } // Tests signature verification using the test vectors in the specified file. // allow_skipping determines whether it is OK to skip a test because // a verfier cannot be constructed. This option can be used for // if a file contains test vectors that are not necessarily supported // by tink. bool TestSignatures(const std::string& filename, bool allow_skipping) { std::unique_ptr root = WycheproofUtil::ReadTestVectors(filename); std::cout << (*root)["algorithm"].GetString(); std::cout << "generator version " << (*root)["generatorVersion"].GetString(); std::cout << "expected version 0.4.12"; int passed_tests = 0; int failed_tests = 0; int group_count = 0; for (const rapidjson::Value& test_group : (*root)["testGroups"].GetArray()) { group_count++; auto verifier_result = GetVerifier(test_group); if (!verifier_result.ok()) { std::string type = test_group["type"].GetString(); if (allow_skipping) { std::cout << "Could not construct verifier for " << type << " group " << group_count << ": " << verifier_result.status(); } else { ADD_FAILURE() << "Could not construct verifier for " << type << " group " << group_count << ": " << verifier_result.status(); failed_tests += test_group["tests"].GetArray().Size(); } continue; } auto verifier = std::move(verifier_result.value()); for (const rapidjson::Value& test : test_group["tests"].GetArray()) { std::string expected = test["result"].GetString(); std::string msg = WycheproofUtil::GetBytes(test["msg"]); std::string sig = WycheproofUtil::GetBytes(test["sig"]); std::string id = absl::StrCat(test["tcId"].GetInt(), " ", test["comment"].GetString()); auto status = verifier->Verify(sig, msg); if (expected == "valid") { if (status.ok()) { ++passed_tests; } else { ++failed_tests; ADD_FAILURE() << "Valid signature not verified:" << id << " status:" << status; } } else if (expected == "invalid") { if (!status.ok()) { ++passed_tests; } else { ++failed_tests; ADD_FAILURE() << "Invalid signature verified:" << id; } } else if (expected == "acceptable") { // The validity of the signature is undefined. Hence the test passes // but we log the result since we might still want to know if the // library is strict or forgiving. ++passed_tests; std::cout << "Acceptable signature:" << id << ":" << status; } else { ++failed_tests; ADD_FAILURE() << "Invalid field result:" << expected; } } } int num_tests = (*root)["numberOfTests"].GetInt(); std::cout << "total number of tests: " << num_tests; std::cout << "number of tests passed:" << passed_tests; std::cout << "number of tests failed:" << failed_tests; return failed_tests == 0; } TEST_F(RsaSsaPkcs1VerifyBoringSslTest, WycheproofRsaPkcs12048SHA256) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Test not run in FIPS-only mode"; } ASSERT_TRUE(TestSignatures("rsa_signature_2048_sha256_test.json", /*allow_skipping=*/true)); } TEST_F(RsaSsaPkcs1VerifyBoringSslTest, WycheproofRsaPkcs13072SHA256) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test is skipped if kOnlyUseFips but BoringCrypto is unavailable."; } ASSERT_TRUE(TestSignatures("rsa_signature_3072_sha256_test.json", /*allow_skipping=*/true)); } TEST_F(RsaSsaPkcs1VerifyBoringSslTest, WycheproofRsaPkcs13072SHA512) { if (internal::IsFipsModeEnabled() && !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test is skipped if kOnlyUseFips but BoringCrypto is unavailable."; } ASSERT_TRUE(TestSignatures("rsa_signature_3072_sha512_test.json", /*allow_skipping=*/true)); } TEST_F(RsaSsaPkcs1VerifyBoringSslTest, WycheproofRsaPkcs14096SHA512) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Test not run in FIPS-only mode"; } ASSERT_TRUE(TestSignatures("rsa_signature_4096_sha512_test.json", /*allow_skipping=*/true)); } // FIPS-only mode test TEST_F(RsaSsaPkcs1VerifyBoringSslTest, TestFipsFailWithoutBoringCrypto) { if (!internal::IsFipsModeEnabled() || internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test assumes kOnlyUseFips but BoringCrypto is unavailable."; } internal::RsaPublicKey pub_key{nist_test_vector.n, nist_test_vector.e}; internal::RsaSsaPkcs1Params params{/*sig_hash=*/HashType::SHA256}; EXPECT_THAT(RsaSsaPkcs1VerifyBoringSsl::New(pub_key, params).status(), StatusIs(absl::StatusCode::kInternal)); } TEST_F(RsaSsaPkcs1VerifyBoringSslTest, TestAllowedFipsModuli) { if (!internal::IsFipsModeEnabled() || !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test assumes kOnlyUseFips and BoringCrypto."; } internal::SslUniquePtr rsa_f4(BN_new()); internal::RsaPrivateKey private_key; internal::RsaPublicKey public_key; BN_set_word(rsa_f4.get(), RSA_F4); EXPECT_THAT( internal::NewRsaKeyPair(3072, rsa_f4.get(), &private_key, &public_key), IsOk()); internal::RsaSsaPkcs1Params params{/*sig_hash=*/HashType::SHA256}; EXPECT_THAT(RsaSsaPkcs1VerifyBoringSsl::New(public_key, params).status(), IsOk()); } TEST_F(RsaSsaPkcs1VerifyBoringSslTest, TestRestrictedFipsModuli) { if (!internal::IsFipsModeEnabled() || !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test assumes kOnlyUseFips and BoringCrypto."; } internal::SslUniquePtr rsa_f4(BN_new()); internal::RsaPrivateKey private_key; internal::RsaPublicKey public_key; internal::RsaSsaPkcs1Params params{/*sig_hash=*/HashType::SHA256}; BN_set_word(rsa_f4.get(), RSA_F4); EXPECT_THAT( internal::NewRsaKeyPair(2560, rsa_f4.get(), &private_key, &public_key), IsOk()); EXPECT_THAT(RsaSsaPkcs1VerifyBoringSsl::New(public_key, params).status(), StatusIs(absl::StatusCode::kInternal)); EXPECT_THAT( internal::NewRsaKeyPair(4096, rsa_f4.get(), &private_key, &public_key), IsOk()); EXPECT_THAT(RsaSsaPkcs1VerifyBoringSsl::New(public_key, params).status(), StatusIs(absl::StatusCode::kInternal)); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/rsa_ssa_pss_sign_boringssl.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/rsa_ssa_pss_sign_boringssl.h" #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "openssl/evp.h" #include "openssl/rsa.h" #include "tink/internal/err_util.h" #include "tink/internal/fips_utils.h" #include "tink/internal/md_util.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/internal/util.h" #include "tink/public_key_sign.h" #include "tink/subtle/subtle_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { namespace { // Computes an RSA-SSA PSS signature using `rsa_private_key` over `digest`; // `digest` is the digest of the message to sign computed with `sig_md`, // `mgf1_md` is the hash function for generating the mask (if nullptr, `sig_md` // is used), and `salt_length` the salt length in bytes. // // This function is equivalent to BoringSSL's `RSA_sign_pss_mgf1`[1], and // differs from it only in that it uses `RSA_private_encrypt` instead of // `RSA_sign_raw`, because the latter is not defined in OpenSSL. In BoringSSL // `RSA_private_encrypt` is essentially an alias for `RSA_sign_raw` [2]. // // OpenSSL uses the same sequence of API calls [3]. // // [1]https://github.com/google/boringssl/blob/master/crypto/fipsmodule/rsa/rsa.c#L557 // [2]https://github.com/google/boringssl/blob/master/crypto/fipsmodule/rsa/rsa.c#L315 // [3]https://github.com/openssl/openssl/blob/master/crypto/rsa/rsa_pmeth.c#L181 util::StatusOr SslRsaSsaPssSign(RSA* rsa_private_key, absl::string_view digest, const EVP_MD* sig_md, const EVP_MD* mgf1_md, int32_t salt_length) { const int kHashSize = EVP_MD_size(sig_md); // Make sure the size of the digest is correct. if (digest.size() != kHashSize) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Size of the digest doesn't match the one " "of the hashing algorithm; expected ", kHashSize, " got ", digest.size())); } const int kModulusSize = RSA_size(rsa_private_key); std::vector temporary_buffer(kModulusSize); // This will write exactly kModulusSize bytes to temporary_buffer. if (RSA_padding_add_PKCS1_PSS_mgf1( /*rsa=*/rsa_private_key, /*EM=*/temporary_buffer.data(), /*mHash=*/reinterpret_cast(digest.data()), /*Hash=*/sig_md, /*mgf1Hash=*/mgf1_md, /*sLen=*/salt_length) != 1) { internal::GetSslErrors(); return util::Status(absl::StatusCode::kInternal, "RSA_padding_add_PKCS1_PSS_mgf1 failed."); } std::string signature; ResizeStringUninitialized(&signature, kModulusSize); int signature_length = RSA_private_encrypt( /*flen=*/kModulusSize, /*from=*/temporary_buffer.data(), /*to=*/reinterpret_cast(&signature[0]), /*rsa=*/rsa_private_key, /*padding=*/RSA_NO_PADDING); if (signature_length < 0) { internal::GetSslErrors(); return util::Status(absl::StatusCode::kInternal, "RSA_private_encrypt failed."); } signature.resize(signature_length); return signature; } } // namespace util::StatusOr> RsaSsaPssSignBoringSsl::New( const internal::RsaPrivateKey& private_key, const internal::RsaSsaPssParams& params) { util::Status status = internal::CheckFipsCompatibility(); if (!status.ok()) { return status; } // Check if the hash type is safe to use. util::Status is_safe = internal::IsHashTypeSafeForSignature(params.sig_hash); if (!is_safe.ok()) { return is_safe; } util::StatusOr sig_hash = internal::EvpHashFromHashType(params.sig_hash); if (!sig_hash.ok()) { return sig_hash.status(); } util::StatusOr mgf1_hash = internal::EvpHashFromHashType(params.mgf1_hash); if (!mgf1_hash.ok()) { return mgf1_hash.status(); } // The RSA modulus and exponent are checked as part of the conversion to // internal::SslUniquePtr. util::StatusOr> rsa = internal::RsaPrivateKeyToRsa(private_key); if (!rsa.ok()) { return rsa.status(); } return {absl::WrapUnique(new RsaSsaPssSignBoringSsl( *std::move(rsa), *sig_hash, *mgf1_hash, params.salt_length))}; } util::StatusOr RsaSsaPssSignBoringSsl::Sign( absl::string_view data) const { data = internal::EnsureStringNonNull(data); util::StatusOr digest = internal::ComputeHash(data, *sig_hash_); if (!digest.ok()) { return digest.status(); } util::StatusOr signature = SslRsaSsaPssSign( private_key_.get(), *digest, sig_hash_, mgf1_hash_, salt_length_); if (!signature.ok()) { return util::Status(absl::StatusCode::kInternal, "Signing failed."); } return signature; } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/rsa_ssa_pss_sign_boringssl.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_RSA_SSA_PSS_SIGN_BORINGSSL_H_ #define TINK_SUBTLE_RSA_SSA_PSS_SIGN_BORINGSSL_H_ #include #include #include #include #include "absl/strings/string_view.h" #include "openssl/ec.h" #include "openssl/rsa.h" #include "tink/internal/fips_utils.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/public_key_sign.h" #include "tink/subtle/common_enums.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // The RSA SSA (Signature Schemes with Appendix) using PSS (Probabilistic // Signature Scheme) encoding is defined at // https://tools.ietf.org/html/rfc8017#section-8.1). class RsaSsaPssSignBoringSsl : public PublicKeySign { public: static crypto::tink::util::StatusOr> New( const crypto::tink::internal::RsaPrivateKey& private_key, const crypto::tink::internal::RsaSsaPssParams& params); ~RsaSsaPssSignBoringSsl() override = default; crypto::tink::util::StatusOr Sign( absl::string_view data) const override; static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kRequiresBoringCrypto; private: RsaSsaPssSignBoringSsl(crypto::tink::internal::SslUniquePtr private_key, const EVP_MD* sig_hash, const EVP_MD* mgf1_hash, int32_t salt_length) : private_key_(std::move(private_key)), sig_hash_(sig_hash), mgf1_hash_(mgf1_hash), salt_length_(salt_length) {} const crypto::tink::internal::SslUniquePtr private_key_; // Pointers to singletons owned by OpenSSL/BoringSSL. const EVP_MD* sig_hash_; const EVP_MD* mgf1_hash_; const int32_t salt_length_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_RSA_SSA_PSS_SIGN_BORINGSSL_H_ ================================================ FILE: cc/subtle/rsa_ssa_pss_sign_boringssl_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/rsa_ssa_pss_sign_boringssl.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "openssl/bn.h" #include "openssl/rsa.h" #include "tink/internal/fips_utils.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/rsa_ssa_pss_verify_boringssl.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::IsEmpty; using ::testing::Not; class RsaPssSignBoringsslTest : public ::testing::Test { public: RsaPssSignBoringsslTest() : rsa_f4_(BN_new()) { EXPECT_TRUE(BN_set_word(rsa_f4_.get(), RSA_F4)); EXPECT_THAT( internal::NewRsaKeyPair(/*modulus_size_in_bits=*/2048, rsa_f4_.get(), &private_key_, &public_key_), IsOk()); } protected: internal::SslUniquePtr rsa_f4_; internal::RsaPrivateKey private_key_; internal::RsaPublicKey public_key_; }; TEST_F(RsaPssSignBoringsslTest, EncodesPss) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Test not run in FIPS-only mode"; } internal::RsaSsaPssParams params{/*sig_hash=*/HashType::SHA256, /*mgf1_hash=*/HashType::SHA256, /*salt_length=*/32}; auto signer_or = RsaSsaPssSignBoringSsl::New(private_key_, params); ASSERT_THAT(signer_or, IsOk()); auto signature_or = signer_or.value()->Sign("testdata"); ASSERT_THAT(signature_or, IsOk()); EXPECT_THAT(signature_or.value(), Not(IsEmpty())); auto verifier_or = RsaSsaPssVerifyBoringSsl::New(public_key_, params); ASSERT_THAT(verifier_or, IsOk()); EXPECT_THAT(verifier_or.value()->Verify(signature_or.value(), "testdata"), IsOk()); } TEST_F(RsaPssSignBoringsslTest, EncodesPssWithSeparateHashes) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Test not run in FIPS-only mode"; } internal::RsaSsaPssParams params{/*sig_hash=*/HashType::SHA256, /*mgf1_hash=*/HashType::SHA1, /*salt_length=*/32}; auto signer_or = RsaSsaPssSignBoringSsl::New(private_key_, params); ASSERT_THAT(signer_or, IsOk()); auto signature_or = signer_or.value()->Sign("testdata"); ASSERT_THAT(signature_or, IsOk()); EXPECT_THAT(signature_or.value(), Not(IsEmpty())); auto verifier_or = RsaSsaPssVerifyBoringSsl::New(public_key_, params); ASSERT_THAT(verifier_or, IsOk()); EXPECT_THAT(verifier_or.value()->Verify(signature_or.value(), "testdata"), IsOk()); } TEST_F(RsaPssSignBoringsslTest, RejectsInvalidPaddingHash) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Test not run in FIPS-only mode"; } internal::RsaSsaPssParams params{/*sig_hash=*/HashType::SHA256, /*mgf1_hash=*/HashType::UNKNOWN_HASH, /*salt_length=*/0}; ASSERT_THAT(RsaSsaPssSignBoringSsl::New(private_key_, params).status(), StatusIs(absl::StatusCode::kUnimplemented)); } TEST_F(RsaPssSignBoringsslTest, RejectsUnsafePaddingHash) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Test not run in FIPS-only mode"; } internal::RsaSsaPssParams params{/*sig_hash=*/HashType::SHA1, /*mgf1_hash=*/HashType::SHA1, /*salt_length=*/0}; ASSERT_THAT(RsaSsaPssSignBoringSsl::New(private_key_, params).status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST_F(RsaPssSignBoringsslTest, RejectsInvalidCrtParams) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Test not run in FIPS-only mode"; } internal::RsaSsaPssParams params{/*sig_hash=*/HashType::SHA256, /*mgf1_hash=*/HashType::SHA256, /*salt_length=*/32}; ASSERT_THAT(private_key_.crt, Not(IsEmpty())); ASSERT_THAT(private_key_.dq, Not(IsEmpty())); ASSERT_THAT(private_key_.dp, Not(IsEmpty())); // Flip a few bits in the CRT parameters; check that creation fails. { internal::RsaPrivateKey key = private_key_; key.crt[0] ^= 0x80; auto signer_or = RsaSsaPssSignBoringSsl::New(key, params); EXPECT_THAT(signer_or.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } { internal::RsaPrivateKey key = private_key_; key.dq[0] ^= 0x08; auto signer_or = RsaSsaPssSignBoringSsl::New(key, params); EXPECT_THAT(signer_or.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } { internal::RsaPrivateKey key = private_key_; key.dp[0] ^= 0x04; auto signer_or = RsaSsaPssSignBoringSsl::New(key, params); EXPECT_THAT(signer_or.status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } // FIPS-only mode test TEST_F(RsaPssSignBoringsslTest, TestFipsFailWithoutBoringCrypto) { if (!internal::IsFipsModeEnabled() || internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test assumes kOnlyUseFips but BoringCrypto is unavailable."; } internal::RsaSsaPssParams params{/*sig_hash=*/HashType::SHA256, /*mgf1_hash=*/HashType::SHA256, /*salt_length=*/32}; EXPECT_THAT(RsaSsaPssSignBoringSsl::New(private_key_, params).status(), StatusIs(absl::StatusCode::kInternal)); } TEST_F(RsaPssSignBoringsslTest, TestRestrictedFipsModuli) { if (!internal::IsFipsModeEnabled() || !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test assumes kOnlyUseFips and BoringCrypto."; } internal::RsaPrivateKey private_key; internal::RsaPublicKey public_key; EXPECT_THAT(internal::NewRsaKeyPair(/*modulus_size_in_bits=*/4096, rsa_f4_.get(), &private_key, &public_key), IsOk()); internal::RsaSsaPssParams params{/*sig_hash=*/HashType::SHA256, /*mgf1_hash=*/HashType::SHA256, /*salt_length=*/32}; EXPECT_THAT(RsaSsaPssSignBoringSsl::New(private_key, params).status(), StatusIs(absl::StatusCode::kInternal)); } TEST_F(RsaPssSignBoringsslTest, TestAllowedFipsModuli) { if (!internal::IsFipsModeEnabled() || !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test assumes kOnlyUseFips and BoringCrypto."; } internal::RsaPrivateKey private_key; internal::RsaPublicKey public_key; EXPECT_THAT(internal::NewRsaKeyPair(/*modulus_size_in_bits=*/3072, rsa_f4_.get(), &private_key, &public_key), IsOk()); internal::RsaSsaPssParams params{/*sig_hash=*/HashType::SHA256, /*mgf1_hash=*/HashType::SHA256, /*salt_length=*/32}; EXPECT_THAT(RsaSsaPssSignBoringSsl::New(private_key, params).status(), IsOk()); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/rsa_ssa_pss_verify_boringssl.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/rsa_ssa_pss_verify_boringssl.h" #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "openssl/rsa.h" #include "tink/internal/err_util.h" #include "tink/internal/fips_utils.h" #include "tink/internal/md_util.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/internal/util.h" #include "tink/subtle/common_enums.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { namespace { // Verifies an RSA-SSA PSS signature using `rsa_public_key` over // `message_digest`; `message_digest` is the digest of the original message // computed with `sig_md`, `mgf1_md` is the hash function for generating the // mask (if nullptr, `sig_md` is used), and `salt_length` the salt length in // bytes. // // This function is equivalent to BoringSSL's `RSA_verify_pss_mgf1`[1], and // differs from it only in that it uses `RSA_public_decrypt` instead of // `RSA_sign_raw`, because the latter is not defined in OpenSSL. In BoringSSL // `RSA_public_decrypt` is essentially an alias for `RSA_verify_raw` [2]. // // OpenSSL uses the same sequence of API calls [3]. // // [1]https://github.com/google/boringssl/blob/master/crypto/fipsmodule/rsa/rsa.c#L633 // [2]https://github.com/google/boringssl/blob/master/crypto/fipsmodule/rsa/rsa.c#L354 // [3]https://github.com/openssl/openssl/blob/master/crypto/rsa/rsa_pmeth.c#L279 util::Status SslRsaSsaPssVerify(RSA* rsa_public_key, absl::string_view signature, absl::string_view message_digest, const EVP_MD* sig_md, const EVP_MD* mgf1_md, int32_t salt_length) { const int kHashSize = EVP_MD_size(sig_md); // Make sure the size of the digest is correct. if (message_digest.size() != kHashSize) { return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Size of the digest doesn't match the one " "of the hashing algorithm; expected ", kHashSize, " got ", message_digest.size())); } const int kRsaModulusSize = RSA_size(rsa_public_key); std::vector recovered_message_digest(kRsaModulusSize); int recovered_message_digest_size = RSA_public_decrypt( /*flen=*/signature.size(), /*from=*/reinterpret_cast(signature.data()), /*to=*/recovered_message_digest.data(), /*rsa=*/rsa_public_key, /*padding=*/RSA_NO_PADDING); if (recovered_message_digest_size != kRsaModulusSize) { internal::GetSslErrors(); return util::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Invalid signature size (likely an incorrect key is " "used); expected ", kRsaModulusSize, " got ", recovered_message_digest_size)); } if (RSA_verify_PKCS1_PSS_mgf1( rsa_public_key, reinterpret_cast(message_digest.data()), sig_md, mgf1_md, recovered_message_digest.data(), salt_length) != 1) { internal::GetSslErrors(); return util::Status(absl::StatusCode::kInvalidArgument, "PSS padding verification failed."); } return util::OkStatus(); } } // namespace util::StatusOr> RsaSsaPssVerifyBoringSsl::New(const internal::RsaPublicKey& pub_key, const internal::RsaSsaPssParams& params) { util::Status res = internal::CheckFipsCompatibility(); if (!res.ok()) { return res; } // Check if the hash type is safe to use. util::Status is_safe = internal::IsHashTypeSafeForSignature(params.sig_hash); if (!is_safe.ok()) { return is_safe; } util::StatusOr sig_hash = internal::EvpHashFromHashType(params.sig_hash); if (!sig_hash.ok()) { return sig_hash.status(); } // TODO(quannguyen): check mgf1_hash function and salt length. util::StatusOr mgf1_hash = internal::EvpHashFromHashType(params.mgf1_hash); if (!mgf1_hash.ok()) { return mgf1_hash.status(); } // The RSA modulus and exponent are checked as part of the conversion to // internal::SslUniquePtr. util::StatusOr> rsa = internal::RsaPublicKeyToRsa(pub_key); if (!rsa.ok()) { return rsa.status(); } return {absl::WrapUnique(new RsaSsaPssVerifyBoringSsl( *std::move(rsa), *sig_hash, *mgf1_hash, params.salt_length))}; } util::Status RsaSsaPssVerifyBoringSsl::Verify(absl::string_view signature, absl::string_view data) const { // BoringSSL expects a non-null pointer for data, // regardless of whether the size is 0. data = internal::EnsureStringNonNull(data); util::StatusOr digest = internal::ComputeHash(data, *sig_hash_); if (!digest.ok()) { return digest.status(); } return SslRsaSsaPssVerify(rsa_.get(), signature, *digest, sig_hash_, mgf1_hash_, salt_length_); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/rsa_ssa_pss_verify_boringssl.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_RSA_SSA_PSS_VERIFY_BORINGSSL_H_ #define TINK_SUBTLE_RSA_SSA_PSS_VERIFY_BORINGSSL_H_ #include #include #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "openssl/rsa.h" #include "tink/internal/fips_utils.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/public_key_verify.h" #include "tink/subtle/common_enums.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // RSA SSA (Signature Schemes with Appendix) using PSS (Probabilistic // Signature Scheme) encoding is defined at // https://tools.ietf.org/html/rfc8017#section-8.1). class RsaSsaPssVerifyBoringSsl : public PublicKeyVerify { public: static crypto::tink::util::StatusOr> New(const internal::RsaPublicKey& pub_key, const internal::RsaSsaPssParams& params); ~RsaSsaPssVerifyBoringSsl() override = default; crypto::tink::util::Status Verify(absl::string_view signature, absl::string_view data) const override; static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kRequiresBoringCrypto; private: RsaSsaPssVerifyBoringSsl(internal::SslUniquePtr rsa, const EVP_MD* sig_hash, const EVP_MD* mgf1_hash, int salt_length) : rsa_(std::move(rsa)), sig_hash_(sig_hash), mgf1_hash_(mgf1_hash), salt_length_(salt_length) {} const internal::SslUniquePtr rsa_; const EVP_MD* const sig_hash_; // Owned by BoringSSL. const EVP_MD* const mgf1_hash_; // Owned by BoringSSL. int salt_length_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_RSA_SSA_PSS_VERIFY_BORINGSSL_H_ ================================================ FILE: cc/subtle/rsa_ssa_pss_verify_boringssl_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/rsa_ssa_pss_verify_boringssl.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "openssl/bn.h" #include "include/rapidjson/document.h" #include "tink/internal/err_util.h" #include "tink/internal/fips_utils.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/wycheproof_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" // TODO(quannguyen): // + Add tests for parameters validation. namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::TestParamInfo; using ::testing::ValuesIn; // Test vector from // https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Digital-Signatures struct NistTestVector { std::string n; std::string e; std::string message; std::string signature; HashType sig_hash; HashType mgf1_hash; int salt_length; }; NistTestVector GetNistTestVector() { NistTestVector test_vector = { absl::HexStringToBytes( "a47d04e7cacdba4ea26eca8a4c6e14563c2ce03b623b768c0d49868a57121301dbf7" "83d82f4c055e73960e70550187d0af62ac3496f0a3d9103c2eb7919a72752fa7ce8c" "688d81e3aee99468887a15288afbb7acb845b7c522b5c64e678fcd3d22feb84b4427" "2700be527d2b2025a3f83c2383bf6a39cf5b4e48b3cf2f56eef0dfff18555e31037b" "915248694876f3047814415164f2c660881e694b58c28038a032ad25634aad7b3917" "1dee368e3d59bfb7299e4601d4587e68caaf8db457b75af42fc0cf1ae7caced286d7" "7fac6cedb03ad94f1433d2c94d08e60bc1fdef0543cd2951e765b38230fdd18de5d2" "ca627ddc032fe05bbd2ff21e2db1c2f94d8b"), absl::HexStringToBytes("10e43f"), absl::HexStringToBytes( "e002377affb04f0fe4598de9d92d31d6c786040d5776976556a2cfc55e54a1dcb3cb" "1b126bd6a4bed2a184990ccea773fcc79d246553e6c64f686d21ad4152673cafec22" "aeb40f6a084e8a5b4991f4c64cf8a927effd0fd775e71e8329e41fdd4457b3911173" "187b4f09a817d79ea2397fc12dfe3d9c9a0290c8ead31b6690a6"), absl::HexStringToBytes( "4f9b425c2058460e4ab2f5c96384da2327fd29150f01955a76b4efe956af06dc0877" "9a374ee4607eab61a93adc5608f4ec36e47f2a0f754e8ff839a8a19b1db1e884ea4c" "f348cd455069eb87afd53645b44e28a0a56808f5031da5ba9112768dfbfca44ebe63" "a0c0572b731d66122fb71609be1480faa4e4f75e43955159d70f081e2a32fbb19a48" "b9f162cf6b2fb445d2d6994bc58910a26b5943477803cdaaa1bd74b0da0a5d053d8b" "1dc593091db5388383c26079f344e2aea600d0e324164b450f7b9b465111b7265f3b" "1b063089ae7e2623fc0fda8052cf4bf3379102fbf71d7c98e8258664ceed637d20f9" "5ff0111881e650ce61f251d9c3a629ef222d"), HashType::SHA256, HashType::SHA256, 32, }; return test_vector; } TEST(RsaSsaPssVerifyBoringSslTest, BasicVerify) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Test not run in FIPS-only mode"; } const NistTestVector kNistTestVector = GetNistTestVector(); internal::RsaPublicKey pub_key{kNistTestVector.n, kNistTestVector.e}; internal::RsaSsaPssParams params = { kNistTestVector.sig_hash, kNistTestVector.mgf1_hash, kNistTestVector.salt_length, }; util::StatusOr> verifier = RsaSsaPssVerifyBoringSsl::New(pub_key, params); ASSERT_THAT(verifier, IsOk()); util::Status status = (*verifier)->Verify(kNistTestVector.signature, kNistTestVector.message); EXPECT_TRUE(status.ok()) << status << internal::GetSslErrors(); } TEST(RsaSsaPssVerifyBoringSslTest, NewErrors) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Test not run in FIPS-only mode"; } const NistTestVector kNistTestVector = GetNistTestVector(); internal::RsaPublicKey nist_pub_key{kNistTestVector.n, kNistTestVector.e}; internal::RsaSsaPssParams nist_params = { kNistTestVector.sig_hash, kNistTestVector.mgf1_hash, kNistTestVector.salt_length, }; internal::RsaPublicKey small_pub_key{std::string("\x23"), std::string("\x3")}; internal::RsaSsaPssParams sha1_hash_params = { HashType::SHA1, kNistTestVector.mgf1_hash, kNistTestVector.salt_length}; { // Small modulus. auto result = RsaSsaPssVerifyBoringSsl::New(small_pub_key, nist_params); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "only modulus size >= 2048-bit is supported", std::string(result.status().message())); } { // Use SHA1 for digital signature. auto result = RsaSsaPssVerifyBoringSsl::New(nist_pub_key, sha1_hash_params); EXPECT_FALSE(result.ok()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code()); EXPECT_PRED_FORMAT2(testing::IsSubstring, "SHA1 is not safe for digital signature", std::string(result.status().message())); } } TEST(RsaSsaPssVerifyBoringSslTest, Modification) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Test not run in FIPS-only mode"; } const NistTestVector kNistTestVector = GetNistTestVector(); internal::RsaPublicKey pub_key{kNistTestVector.n, kNistTestVector.e}; internal::RsaSsaPssParams params = { kNistTestVector.sig_hash, kNistTestVector.mgf1_hash, kNistTestVector.salt_length, }; util::StatusOr> verifier = RsaSsaPssVerifyBoringSsl::New(pub_key, params); ASSERT_THAT(verifier, IsOk()); // Modify the message. for (std::size_t i = 0; i < kNistTestVector.message.length(); i++) { std::string modified_message = kNistTestVector.message; modified_message[i / 8] ^= 1 << (i % 8); util::Status status = (*verifier)->Verify(kNistTestVector.signature, modified_message); EXPECT_FALSE(status.ok()) << status << internal::GetSslErrors(); } // Modify the signature. for (std::size_t i = 0; i < kNistTestVector.signature.length(); i++) { std::string modified_signature = kNistTestVector.signature; modified_signature[i / 8] ^= 1 << (i % 8); util::Status status = (*verifier)->Verify(modified_signature, kNistTestVector.message); EXPECT_FALSE(status.ok()) << status << internal::GetSslErrors(); } // Truncate the signature. for (std::size_t i = 0; i < kNistTestVector.signature.length(); i++) { std::string truncated_signature(kNistTestVector.signature, 0, i); util::Status status = (*verifier)->Verify(truncated_signature, kNistTestVector.message); EXPECT_FALSE(status.ok()) << status << internal::GetSslErrors(); } } // Wycheproof test vector for RSA-SSA PSS. struct RsaSsaPssWycheproofTestVector { std::string file_name; internal::RsaPublicKey key; HashType hash_type; HashType mgf_hash_type; int salt_length; std::string expected; std::string msg; std::string sig; std::string id; std::string comment; }; // Reads the RSA-SSA PSS wycheproof test vectors from a given `file_name` and // returns a vector of RsaSsaPssWycheproofTestVector. std::vector ReadTestVectors( absl::string_view file_name) { std::vector test_vectors; std::unique_ptr root = WycheproofUtil::ReadTestVectors(std::string(file_name)); for (const rapidjson::Value& test_group : (*root)["testGroups"].GetArray()) { for (const rapidjson::Value& test : test_group["tests"].GetArray()) { test_vectors.push_back({ /*file_name=*/std::string(file_name), /*key=*/ { WycheproofUtil::GetInteger(test_group["n"]), WycheproofUtil::GetInteger(test_group["e"]), }, /*hash_type=*/WycheproofUtil::GetHashType(test_group["sha"]), /*mgf_hash_type=*/WycheproofUtil::GetHashType(test_group["mgfSha"]), /*salt_length=*/test_group["sLen"].GetInt(), /*expected=*/test["result"].GetString(), /*msg=*/WycheproofUtil::GetBytes(test["msg"]), /*sig=*/WycheproofUtil::GetBytes(test["sig"]), /*id=*/absl::StrCat(test["tcId"].GetInt()), /*comment=*/test["comment"].GetString(), }); } } return test_vectors; } // Creates a verifier using the parameters in `test_vector`. util::StatusOr> GetVerifier( const RsaSsaPssWycheproofTestVector& test_vector) { internal::RsaPublicKey key = test_vector.key; internal::RsaSsaPssParams params = { test_vector.hash_type, test_vector.mgf_hash_type, test_vector.salt_length, }; return RsaSsaPssVerifyBoringSsl::New(key, params); } using RsaSsaPssWycheproofTest = testing::TestWithParam; // Tests signature verification using a test vector. TEST_P(RsaSsaPssWycheproofTest, SignatureVerify) { if (internal::IsFipsModeEnabled()) { GTEST_SKIP() << "Test not run in FIPS-only mode"; } RsaSsaPssWycheproofTestVector params = GetParam(); util::StatusOr> verifier = GetVerifier(params); ASSERT_THAT(verifier, IsOk()); util::Status result = (*verifier)->Verify(params.sig, params.msg); if (params.expected == "valid") { EXPECT_THAT(result, IsOk()); } else if (params.expected == "acceptable") { // The validity of the signature is undefined. Hence we skip the test but we // log the result since we might still want to know if the library is strict // or forgiving. GTEST_SKIP() << "Verification of an acceptable signature " << params.id << " resulted in: " << result; } else { EXPECT_THAT(result, testing::Not(IsOk())); } } std::vector GetTestParameters() { std::vector test_vectors = ReadTestVectors( /*file_name=*/"rsa_pss_2048_sha256_mgf1_0_test.json"); std::vector others = ReadTestVectors( /*file_name=*/"rsa_pss_2048_sha256_mgf1_32_test.json"); test_vectors.insert(test_vectors.end(), others.begin(), others.end()); others = ReadTestVectors( /*file_name=*/"rsa_pss_3072_sha256_mgf1_32_test.json"); test_vectors.insert(test_vectors.end(), others.begin(), others.end()); others = ReadTestVectors( /*file_name=*/"rsa_pss_4096_sha256_mgf1_32_test.json"); test_vectors.insert(test_vectors.end(), others.begin(), others.end()); others = ReadTestVectors( /*file_name=*/"rsa_pss_4096_sha512_mgf1_32_test.json"); test_vectors.insert(test_vectors.end(), others.begin(), others.end()); return test_vectors; } INSTANTIATE_TEST_SUITE_P( RsaSsaPssWycheproofTests, RsaSsaPssWycheproofTest, ValuesIn(GetTestParameters()), [](const TestParamInfo& info) { // Testcase name is partly using the test name. std::vector parts = absl::StrSplit(info.param.file_name, "."); return absl::StrCat(parts[0], "_tid", info.param.id); }); // FIPS-only mode test TEST(RsaSsaPssVerifyBoringSslTest, TestFipsFailWithoutBoringCrypto) { if (!internal::IsFipsModeEnabled() || internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test assumes kOnlyUseFips but BoringCrypto is unavailable."; } const NistTestVector kNistTestVector = GetNistTestVector(); internal::RsaPublicKey pub_key{kNistTestVector.n, kNistTestVector.e}; internal::RsaSsaPssParams params = { /*sig_hash=*/HashType::SHA256, /*mgf1_hash=*/HashType::SHA256, /*salt_length=*/32, }; EXPECT_THAT(RsaSsaPssVerifyBoringSsl::New(pub_key, params).status(), StatusIs(absl::StatusCode::kInternal)); } TEST(RsaSsaPssVerifyBoringSslTest, TestAllowedFipsModuli) { if (!internal::IsFipsModeEnabled() || !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test assumes kOnlyUseFips and BoringCrypto."; } internal::SslUniquePtr rsa_f4(BN_new()); internal::RsaPrivateKey private_key; internal::RsaPublicKey public_key; internal::RsaSsaPssParams params = { /*sig_hash=*/HashType::SHA256, /*mgf1_hash=*/HashType::SHA256, /*salt_length=*/32, }; BN_set_word(rsa_f4.get(), RSA_F4); ASSERT_THAT( internal::NewRsaKeyPair(3072, rsa_f4.get(), &private_key, &public_key), IsOk()); EXPECT_THAT(RsaSsaPssVerifyBoringSsl::New(public_key, params).status(), IsOk()); } TEST(RsaSsaPssVerifyBoringSslTest, TestRestrictedFipsModuli) { if (!internal::IsFipsModeEnabled() || !internal::IsFipsEnabledInSsl()) { GTEST_SKIP() << "Test assumes kOnlyUseFips and BoringCrypto."; } internal::SslUniquePtr rsa_f4(BN_new()); internal::RsaPrivateKey private_key; internal::RsaPublicKey public_key; internal::RsaSsaPssParams params = { /*sig_hash=*/HashType::SHA256, /*mgf1_hash=*/HashType::SHA256, /*salt_length=*/32, }; BN_set_word(rsa_f4.get(), RSA_F4); ASSERT_THAT( internal::NewRsaKeyPair(2560, rsa_f4.get(), &private_key, &public_key), IsOk()); EXPECT_THAT(RsaSsaPssVerifyBoringSsl::New(public_key, params).status(), StatusIs(absl::StatusCode::kInternal)); ASSERT_THAT( internal::NewRsaKeyPair(4096, rsa_f4.get(), &private_key, &public_key), IsOk()); EXPECT_THAT(RsaSsaPssVerifyBoringSsl::New(public_key, params).status(), StatusIs(absl::StatusCode::kInternal)); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/stateful_cmac_boringssl.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/stateful_cmac_boringssl.h" #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "tink/internal/aes_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/internal/util.h" #include "tink/subtle/mac/stateful_mac.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { util::StatusOr> StatefulCmacBoringSsl::New( uint32_t tag_size, const util::SecretData& key_value) { util::StatusOr cipher = internal::GetAesCbcCipherForKeySize(key_value.size()); if (!cipher.ok()) { return cipher.status(); } if (tag_size > kMaxTagSize) { return util::Status(absl::StatusCode::kInvalidArgument, "invalid tag size"); } // Create and initialize the CMAC context internal::SslUniquePtr ctx(CMAC_CTX_new()); // Initialize the CMAC if (!CMAC_Init(ctx.get(), key_value.data(), key_value.size(), *cipher, nullptr /* engine */)) { return util::Status(absl::StatusCode::kFailedPrecondition, "CMAC initialization failed"); } return { absl::WrapUnique(new StatefulCmacBoringSsl(tag_size, std::move(ctx)))}; } util::Status StatefulCmacBoringSsl::Update(absl::string_view data) { // BoringSSL expects a non-null pointer for data, // regardless of whether the size is 0. data = internal::EnsureStringNonNull(data); if (!CMAC_Update(cmac_context_.get(), reinterpret_cast(data.data()), data.size())) { return util::Status(absl::StatusCode::kInternal, "Inputs to CMAC Update invalid"); } return util::OkStatus(); } util::StatusOr StatefulCmacBoringSsl::Finalize() { uint8_t buf[EVP_MAX_MD_SIZE]; size_t out_len; if (!CMAC_Final(cmac_context_.get(), buf, &out_len)) { return util::Status(absl::StatusCode::kInternal, "CMAC finalization failed"); } return std::string(reinterpret_cast(buf), tag_size_); } StatefulCmacBoringSslFactory::StatefulCmacBoringSslFactory( uint32_t tag_size, const util::SecretData& key_value) : tag_size_(tag_size), key_value_(key_value) {} util::StatusOr> StatefulCmacBoringSslFactory::Create() const { return StatefulCmacBoringSsl::New(tag_size_, key_value_); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/stateful_cmac_boringssl.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_STATEFUL_CMAC_BORINGSSL_H_ #define TINK_SUBTLE_STATEFUL_CMAC_BORINGSSL_H_ #include #include #include #include #include #include "absl/strings/string_view.h" #include "openssl/cmac.h" #include "openssl/evp.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/mac/stateful_mac.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // A BoringSSL CMAC implementation of Stateful Mac interface. class StatefulCmacBoringSsl : public subtle::StatefulMac { public: // Key must be 16 or 32 bytes, all other sizes will be rejected. static util::StatusOr> New( uint32_t tag_size, const util::SecretData& key_value); util::Status Update(absl::string_view data) override; util::StatusOr Finalize() override; private: static constexpr size_t kSmallKeySize = 16; static constexpr size_t kBigKeySize = 32; static constexpr size_t kMaxTagSize = 16; StatefulCmacBoringSsl(uint32_t tag_size, internal::SslUniquePtr ctx) : cmac_context_(std::move(ctx)), tag_size_(tag_size) {} const internal::SslUniquePtr cmac_context_; const uint32_t tag_size_; }; class StatefulCmacBoringSslFactory : public subtle::StatefulMacFactory { public: StatefulCmacBoringSslFactory(uint32_t tag_size, const util::SecretData& key_value); util::StatusOr> Create() const override; private: const uint32_t tag_size_; const util::SecretData key_value_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_STATEFUL_CMAC_BORINGSSL_H_ ================================================ FILE: cc/subtle/stateful_cmac_boringssl_test.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/stateful_cmac_boringssl.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "include/rapidjson/document.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/mac/stateful_mac.h" #include "tink/subtle/wycheproof_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace subtle { namespace { constexpr size_t kTagSize = 16; constexpr size_t kSmallTagSize = 10; constexpr absl::string_view kKeyHex = "000102030405060708090a0b0c0d0e0f"; constexpr absl::string_view kData = "Some data to test."; constexpr absl::string_view kCmacOnEmptyInputRegularTagSizeHex = "97dd6e5a882cbd564c39ae7d1c5a31aa"; constexpr absl::string_view kCmacOnEmptyInputSmallTagSizeHex = "97dd6e5a882cbd564c39"; constexpr absl::string_view kCmacOnDataRegularTagSizeHex = "c856e183e8dee9bb99402d54c34f3222"; constexpr absl::string_view kCmacOnDataSmallTagSizeHex = "c856e183e8dee9bb9940"; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::testing::Not; using ::testing::TestWithParam; using ::testing::ValuesIn; TEST(StatefulCmacBoringSslTest, CmacEmptyInputRegularTagSize) { util::SecretData key = util::SecretDataFromStringView(absl::HexStringToBytes(kKeyHex)); util::StatusOr> cmac = StatefulCmacBoringSsl::New(kTagSize, key); ASSERT_THAT(cmac, IsOk()); EXPECT_THAT( (*cmac)->Finalize(), IsOkAndHolds(absl::HexStringToBytes(kCmacOnEmptyInputRegularTagSizeHex))); } TEST(StatefulCmacBoringSslTest, CmacEmptyInputSmallTag) { util::SecretData key = util::SecretDataFromStringView(absl::HexStringToBytes(kKeyHex)); util::StatusOr> cmac = StatefulCmacBoringSsl::New(kSmallTagSize, key); ASSERT_THAT(cmac, IsOk()); EXPECT_THAT( (*cmac)->Finalize(), IsOkAndHolds(absl::HexStringToBytes(kCmacOnEmptyInputSmallTagSizeHex))); } TEST(StatefulCmacBoringSslTest, CmacSomeDataRegularTagSize) { util::SecretData key = util::SecretDataFromStringView(absl::HexStringToBytes(kKeyHex)); util::StatusOr> cmac = StatefulCmacBoringSsl::New(kTagSize, key); ASSERT_THAT(cmac, IsOk()); EXPECT_THAT((*cmac)->Update(kData), IsOk()); EXPECT_THAT( (*cmac)->Finalize(), IsOkAndHolds(absl::HexStringToBytes(kCmacOnDataRegularTagSizeHex))); } TEST(StatefulCmacBoringSslTest, CmacSomeDataSmallTag) { util::SecretData key = util::SecretDataFromStringView(absl::HexStringToBytes(kKeyHex)); util::StatusOr> cmac = StatefulCmacBoringSsl::New(kSmallTagSize, key); ASSERT_THAT(cmac, IsOk()); EXPECT_THAT((*cmac)->Update(kData), IsOk()); EXPECT_THAT((*cmac)->Finalize(), IsOkAndHolds(absl::HexStringToBytes(kCmacOnDataSmallTagSizeHex))); } TEST(StatefulCmacBoringSslTest, CmacMultipleUpdatesSameAsOneForWholeInputRegularTagSize) { util::SecretData key = util::SecretDataFromStringView(absl::HexStringToBytes(kKeyHex)); util::StatusOr> cmac = StatefulCmacBoringSsl::New(kTagSize, key); ASSERT_THAT(cmac, IsOk()); for (const std::string &token : {"Some ", "data ", "to ", "test."}) { EXPECT_THAT((*cmac)->Update(token), IsOk()); } EXPECT_THAT( (*cmac)->Finalize(), IsOkAndHolds(absl::HexStringToBytes(kCmacOnDataRegularTagSizeHex))); } TEST(StatefulCmacBoringSslTest, CmacMultipleUpdatesSameAsOneForWholeInputSmallTagSize) { util::SecretData key = util::SecretDataFromStringView(absl::HexStringToBytes(kKeyHex)); util::StatusOr> cmac = StatefulCmacBoringSsl::New(kSmallTagSize, key); ASSERT_THAT(cmac, IsOk()); for (const std::string &token : {"Some ", "data ", "to ", "test."}) { EXPECT_THAT((*cmac)->Update(token), IsOk()); } EXPECT_THAT((*cmac)->Finalize(), IsOkAndHolds(absl::HexStringToBytes(kCmacOnDataSmallTagSizeHex))); } TEST(StatefulCmacFactoryTest, FactoryGeneratesValidInstances) { auto factory = absl::make_unique( kTagSize, util::SecretDataFromStringView(absl::HexStringToBytes(kKeyHex))); util::StatusOr> cmac = factory->Create(); ASSERT_THAT(cmac, IsOk()); EXPECT_THAT((*cmac)->Update(kData), IsOk()); EXPECT_THAT( (*cmac)->Finalize(), IsOkAndHolds(absl::HexStringToBytes(kCmacOnDataRegularTagSizeHex))); } struct StatefulCmacTestVector { std::string key; std::string msg; std::string tag; std::string id; std::string expected_result; }; // Reads the Wycheproof test vectors for AES-CMAC. std::vector GetWycheproofCmakeTestVectors() { std::unique_ptr root = WycheproofUtil::ReadTestVectors("aes_cmac_test.json"); std::vector test_vectors; for (const rapidjson::Value &test_group : (*root)["testGroups"].GetArray()) { // Ignore test vectors of invalid key sizes; valid sizes are {16, 32} bytes. int key_size_bits = test_group["keySize"].GetInt(); if (key_size_bits != 128 && key_size_bits != 256) { continue; } for (const rapidjson::Value &test : test_group["tests"].GetArray()) { test_vectors.push_back({ /*key=*/WycheproofUtil::GetBytes(test["key"]), /*msg=*/WycheproofUtil::GetBytes(test["msg"]), /*tag=*/WycheproofUtil::GetBytes(test["tag"]), /*id=*/absl::StrCat(test["tcId"].GetInt()), /*expected_result=*/test["result"].GetString(), }); } } return test_vectors; } using StatefulCmacBoringSslWycheproofTest = TestWithParam; TEST_P(StatefulCmacBoringSslWycheproofTest, WycheproofTest) { StatefulCmacTestVector test_vector = GetParam(); util::SecretData key = util::SecretDataFromStringView(absl::HexStringToBytes(kKeyHex)); util::StatusOr> cmac = StatefulCmacBoringSsl::New( test_vector.tag.length(), util::SecretDataFromStringView(test_vector.key)); ASSERT_THAT(cmac, IsOk()); EXPECT_THAT((*cmac)->Update(test_vector.msg), IsOk()); if (test_vector.expected_result == "invalid") { EXPECT_THAT((*cmac)->Finalize(), Not(IsOkAndHolds(test_vector.tag))); } else { EXPECT_THAT((*cmac)->Finalize(), IsOkAndHolds(test_vector.tag)); } } INSTANTIATE_TEST_SUITE_P(StatefulCmacBoringSslWycheproofTest, StatefulCmacBoringSslWycheproofTest, ValuesIn(GetWycheproofCmakeTestVectors())); } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/stateful_hmac_boringssl.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/stateful_hmac_boringssl.h" #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "tink/internal/md_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/internal/util.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/mac/stateful_mac.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { util::StatusOr> StatefulHmacBoringSsl::New( HashType hash_type, uint32_t tag_size, const util::SecretData& key_value) { util::StatusOr md = internal::EvpHashFromHashType(hash_type); if (!md.ok()) { return md.status(); } if (EVP_MD_size(*md) < tag_size) { // The key manager is responsible to security policies. // The checks here just ensure the preconditions of the primitive. // If this fails then something is wrong with the key manager. return util::Status(absl::StatusCode::kInvalidArgument, "invalid tag size"); } if (key_value.size() < kMinKeySize) { return util::Status(absl::StatusCode::kInvalidArgument, "invalid key size"); } // Create and initialize the HMAC context internal::SslUniquePtr ctx(HMAC_CTX_new()); // Initialize the HMAC if (!HMAC_Init(ctx.get(), key_value.data(), key_value.size(), *md)) { return util::Status(absl::StatusCode::kFailedPrecondition, "HMAC initialization failed"); } return std::unique_ptr( new StatefulHmacBoringSsl(tag_size, std::move(ctx))); } util::Status StatefulHmacBoringSsl::Update(absl::string_view data) { // BoringSSL expects a non-null pointer for data, // regardless of whether the size is 0. data = internal::EnsureStringNonNull(data); if (!HMAC_Update(hmac_context_.get(), reinterpret_cast(data.data()), data.size())) { return util::Status(absl::StatusCode::kFailedPrecondition, "Inputs to HMAC Update invalid"); } return util::OkStatus(); } util::StatusOr StatefulHmacBoringSsl::Finalize() { uint8_t buf[EVP_MAX_MD_SIZE]; unsigned int out_len; if (!HMAC_Final(hmac_context_.get(), buf, &out_len)) { return util::Status(absl::StatusCode::kInternal, "HMAC finalization failed"); } return std::string(reinterpret_cast(buf), tag_size_); } StatefulHmacBoringSslFactory::StatefulHmacBoringSslFactory( HashType hash_type, uint32_t tag_size, const util::SecretData& key_value) : hash_type_(hash_type), tag_size_(tag_size), key_value_(key_value) {} util::StatusOr> StatefulHmacBoringSslFactory::Create() const { return StatefulHmacBoringSsl::New(hash_type_, tag_size_, key_value_); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/stateful_hmac_boringssl.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_STATEFUL_HMAC_BORINGSSL_H_ #define TINK_SUBTLE_STATEFUL_HMAC_BORINGSSL_H_ #include #include #include #include #include #include "absl/strings/string_view.h" #include "openssl/evp.h" #include "openssl/hmac.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/mac/stateful_mac.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { // A BoringSSL HMAC implementation of Stateful Mac interface. class StatefulHmacBoringSsl : public subtle::StatefulMac { public: static util::StatusOr> New( HashType hash_type, uint32_t tag_size, const util::SecretData& key_value); util::Status Update(absl::string_view data) override; util::StatusOr Finalize() override; private: // Minimum HMAC key size in bytes. static constexpr size_t kMinKeySize = 16; StatefulHmacBoringSsl(uint32_t tag_size, internal::SslUniquePtr ctx) : hmac_context_(std::move(ctx)), tag_size_(tag_size) {} const internal::SslUniquePtr hmac_context_; const uint32_t tag_size_; }; class StatefulHmacBoringSslFactory : public subtle::StatefulMacFactory { public: StatefulHmacBoringSslFactory(HashType hash_type, uint32_t tag_size, const util::SecretData& key_value); util::StatusOr> Create() const override; private: const HashType hash_type_; const uint32_t tag_size_; const util::SecretData key_value_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_STATEFUL_HMAC_BORINGSSL_H_ ================================================ FILE: cc/subtle/stateful_hmac_boringssl_test.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/stateful_hmac_boringssl.h" #include #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/log/log.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/mac/stateful_mac.h" #include "tink/subtle/random.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace subtle { namespace { constexpr size_t kTagSize = 16; constexpr size_t kSmallTagSize = 10; using crypto::tink::test::HexDecodeOrDie; using crypto::tink::test::HexEncode; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::SizeIs; struct TestVector { TestVector(std::string test_name, std::string hex_key, HashType hash_type, uint32_t tag_size, std::string message, std::string hex_tag) : test_name(test_name), hex_key(hex_key), hash_type(hash_type), tag_size(tag_size), message(message), hex_tag(hex_tag) {} std::string test_name; std::string hex_key; HashType hash_type; uint32_t tag_size; std::string message; std::string hex_tag; }; using StatefulHmacBoringSslTest = testing::TestWithParam; std::vector GetTestVectors() { return { TestVector(/*test_name=*/"EmptyMsgSha224", /*hex_key=*/"000102030405060708090a0b0c0d0e0f", /*hash_type=*/HashType::SHA224, /*tag_size=*/16, /*message=*/"", /*hex_tag=*/"4e496054842798a861acb67a9fe85fb7"), TestVector(/*test_name=*/"EmptyMsgSha256", /*hex_key=*/"000102030405060708090a0b0c0d0e0f", /*hash_type=*/HashType::SHA256, /*tag_size=*/16, /*message=*/"", /*hex_tag=*/"07eff8b326b7798c9ccfcbdbe579489a"), TestVector(/*test_name=*/"EmptyMsgSha384", /*hex_key=*/"000102030405060708090a0b0c0d0e0f", /*hash_type=*/HashType::SHA384, /*tag_size=*/16, /*message=*/"", /*hex_tag=*/"6a0fdc1c54c664ad91c7c157d2670c5d"), TestVector(/*test_name=*/"EmptyMsgSha512", /*hex_key=*/"000102030405060708090a0b0c0d0e0f", /*hash_type=*/HashType::SHA512, /*tag_size=*/16, /*message=*/"", /*hex_tag=*/"2fec800ca276c44985a35aec92067e5e"), TestVector(/*test_name=*/"EmptyMsgSha256TagSize10", /*hex_key=*/"000102030405060708090a0b0c0d0e0f", /*hash_type=*/HashType::SHA256, /*tag_size=*/10, /*message=*/"", /*hex_tag=*/"07eff8b326b7798c9ccf"), TestVector(/*test_name=*/"EmptyMsgSha512TagSize10", /*hex_key=*/"000102030405060708090a0b0c0d0e0f", /*hash_type=*/HashType::SHA512, /*tag_size=*/10, /*message=*/"", /*hex_tag=*/"2fec800ca276c44985a3"), TestVector(/*test_name=*/"BasicMessageSha256", /*hex_key=*/"000102030405060708090a0b0c0d0e0f", /*hash_type=*/HashType::SHA256, /*tag_size=*/16, /*message=*/"Some data to test.", /*hex_tag=*/"1d6eb74bc283f7947e92c72bd985ce6e"), TestVector(/*test_name=*/"BasicMessageSha512", /*hex_key=*/"000102030405060708090a0b0c0d0e0f", /*hash_type=*/HashType::SHA512, /*tag_size=*/16, /*message=*/"Some data to test.", /*hex_tag=*/"72b8ff800f57f9aeec41265a29b69b6a"), TestVector(/*test_name=*/"BasicMessageSha256TagSize10", /*hex_key=*/"000102030405060708090a0b0c0d0e0f", /*hash_type=*/HashType::SHA256, /*tag_size=*/10, /*message=*/"Some data to test.", /*hex_tag=*/"1d6eb74bc283f7947e92"), TestVector(/*test_name=*/"BasicMessageSha512TagSize10", /*hex_key=*/"000102030405060708090a0b0c0d0e0f", /*hash_type=*/HashType::SHA512, /*tag_size=*/10, /*message=*/"Some data to test.", /*hex_tag=*/"72b8ff800f57f9aeec41"), TestVector(/*test_name=*/"LongMessageSha224", /*hex_key=*/"000102030405060708090a0b0c0d0e0f", /*hash_type=*/HashType::SHA224, /*tag_size=*/16, /*message=*/ "Some very long message which can be split in " "multiple ways. The contents are not really important, " "but we want the message to be quite long", /*hex_tag=*/"0165b6a416a44d1558816f75ff1e13f3"), TestVector(/*test_name=*/"LongMessageSha256", /*hex_key=*/"000102030405060708090a0b0c0d0e0f", /*hash_type=*/HashType::SHA256, /*tag_size=*/16, /*message=*/ "Some very long message which can be split in " "multiple ways. The contents are not really important, " "but we want the message to be quite long", /*hex_tag=*/"aa85d0f6f3c46330e65f814535f6ad8e"), }; } TEST_P(StatefulHmacBoringSslTest, OnlyEmptyMessages) { TestVector test_vector = GetParam(); if (!test_vector.message.empty()) { GTEST_SKIP() << "Test tests only empty messages"; } util::StatusOr> hmac_result = StatefulHmacBoringSsl::New( test_vector.hash_type, test_vector.tag_size, util::SecretDataFromStringView(HexDecodeOrDie(test_vector.hex_key))); ASSERT_THAT(hmac_result, IsOk()); auto hmac = std::move(hmac_result.value()); util::StatusOr tag = hmac->Finalize(); ASSERT_THAT(tag, IsOk()); EXPECT_THAT(*tag, SizeIs(test_vector.tag_size)); EXPECT_THAT(HexEncode(*tag), Eq(test_vector.hex_tag)); } TEST_P(StatefulHmacBoringSslTest, SingleUpdate) { TestVector test_vector = GetParam(); auto hmac_result = StatefulHmacBoringSsl::New( test_vector.hash_type, test_vector.tag_size, util::SecretDataFromStringView(HexDecodeOrDie(test_vector.hex_key))); ASSERT_THAT(hmac_result, IsOk()); auto hmac = std::move(hmac_result.value()); ASSERT_THAT(hmac->Update(test_vector.message), IsOk()); util::StatusOr tag = hmac->Finalize(); ASSERT_THAT(tag, IsOk()); EXPECT_THAT(*tag, SizeIs(test_vector.tag_size)); EXPECT_THAT(HexEncode(*tag), Eq(test_vector.hex_tag)); } TEST_P(StatefulHmacBoringSslTest, MultipleUpdates) { TestVector test_vector = GetParam(); auto hmac_result = StatefulHmacBoringSsl::New( test_vector.hash_type, test_vector.tag_size, util::SecretDataFromStringView(HexDecodeOrDie(test_vector.hex_key))); ASSERT_THAT(hmac_result, IsOk()); auto hmac = std::move(hmac_result.value()); absl::string_view remaining_message = test_vector.message; LOG(INFO) << "Starting to update"; while (!remaining_message.empty()) { int random_byte = Random::GetRandomUInt8() % 15; int amount_to_consume = std::min(remaining_message.size(), random_byte); LOG(INFO) << "Consuming " << amount_to_consume << " bytes"; ASSERT_THAT(hmac->Update(remaining_message.substr(0, amount_to_consume)), IsOk()); remaining_message.remove_prefix(amount_to_consume); } LOG(INFO) << "Done updating "; util::StatusOr tag = hmac->Finalize(); ASSERT_THAT(tag, IsOk()); EXPECT_THAT(*tag, SizeIs(test_vector.tag_size)); EXPECT_THAT(HexEncode(*tag), Eq(test_vector.hex_tag)); } TEST_P(StatefulHmacBoringSslTest, MultipleUpdatesObjectFromFactory) { TestVector test_vector = GetParam(); auto factory = absl::make_unique( test_vector.hash_type, test_vector.tag_size, util::SecretDataFromStringView(HexDecodeOrDie(test_vector.hex_key))); util::StatusOr> hmac = factory->Create(); ASSERT_THAT(hmac, IsOk()); absl::string_view remaining_message = test_vector.message; while (!remaining_message.empty()) { int random_byte = Random::GetRandomUInt8() % 15; int amount_to_consume = std::min(remaining_message.size(), random_byte); ASSERT_THAT((*hmac)->Update(remaining_message.substr(0, amount_to_consume)), IsOk()); remaining_message.remove_prefix(amount_to_consume); } util::StatusOr tag = (*hmac)->Finalize(); ASSERT_THAT(tag, IsOk()); EXPECT_THAT(*tag, SizeIs(test_vector.tag_size)); EXPECT_THAT(HexEncode(*tag), Eq(test_vector.hex_tag)); } INSTANTIATE_TEST_SUITE_P( StatefulHmacBoringSslTest, StatefulHmacBoringSslTest, testing::ValuesIn(GetTestVectors()), [](const testing::TestParamInfo& info) { return info.param.test_name; }); TEST(StatefulHmacBoringSslTest, InvalidKeySizes) { size_t tag_size = 16; for (int keysize = 0; keysize < 65; keysize++) { std::string key(keysize, 'x'); auto hmac_result = StatefulHmacBoringSsl::New( HashType::SHA256, tag_size, util::SecretDataFromStringView(key)); if (keysize >= 16) { EXPECT_THAT(hmac_result, IsOk()); } else { EXPECT_THAT(hmac_result.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("invalid key size"))); } } } class StatefulHmacBoringSslTestVectorTest : public ::testing::TestWithParam> { public: // Utility to simplify testing with test vectors. // Arguments and result are hexadecimal. void StatefulHmacVerifyHex(const std::string &key_hex, const std::string &msg_hex, const std::string &tag_hex) { std::string key = test::HexDecodeOrDie(key_hex); std::string tag = test::HexDecodeOrDie(tag_hex); std::string msg = test::HexDecodeOrDie(msg_hex); auto create_result = StatefulHmacBoringSsl::New( HashType::SHA1, tag.size(), util::SecretDataFromStringView(key)); EXPECT_THAT(create_result, IsOk()); auto hmac = std::move(create_result.value()); auto update_result = hmac->Update(msg); EXPECT_THAT(update_result, IsOk()); auto finalize_result = hmac->Finalize(); EXPECT_THAT(finalize_result, IsOk()); auto result = finalize_result.value(); EXPECT_EQ(result, tag); } }; // Wycheproof HMAC tests are not enabled because the test vectors are in // "rc" (release candidate) state, and are not yet exported for use. // TODO(cathieyun): re-enable Wycheproof HMAC tests once vectors are exported. /* // Test with test vectors from Wycheproof project. bool WycheproofTest(const rapidjson::Document &root, HashType hash_type) { int errors = 0; for (const rapidjson::Value &test_group : root["testGroups"].GetArray()) { // Get the key size in bytes. Wycheproof contains tests for keys smaller // than MIN_KEY_SIZE, which is 16, so the test will skip those. if (test_group["keySize"].GetInt() / 8 < 16) { continue; } for (const rapidjson::Value &test : test_group["tests"].GetArray()) { std::string comment = test["comment"].GetString(); std::string key = WycheproofUtil::GetBytes(test["key"]); std::string msg = WycheproofUtil::GetBytes(test["msg"]); std::string tag = WycheproofUtil::GetBytes(test["tag"]); std::string id = absl::StrCat(test["tcId"].GetInt()); std::string expected = test["result"].GetString(); auto create_result = StatefulHmacBoringSsl::New(hash_type, tag.length(), key); EXPECT_THAT(create_result, IsOk()); auto hmac = std::move(create_result.value()); auto update_result = hmac->Update(msg); EXPECT_THAT(update_result, IsOk()); auto finalize_result = hmac->Finalize(); auto result = finalize_result.value(); bool success = result == tag; if (success) { // std::string result_tag = result.value(); if (expected == "invalid") { ADD_FAILURE() << "verified incorrect tag:" << id; errors++; } } else { if (expected == "valid") { ADD_FAILURE() << "Could not create tag for test with tcId:" << id << " tag_size:" << tag.length() << " key_size:" << key.length() << " error:" << result; errors++; } } } } return errors == 0; } TEST_F(StatefulHmacBoringSslTest, TestVectors) { // Test Hmac with SHA256 std::unique_ptr root256 = WycheproofUtil::ReadTestVectors("hmac_sha256_test.json"); ASSERT_TRUE(WycheproofTest(*root256, HashType::SHA256)); // Test Hmac with SHA512 std::unique_ptr root512 = WycheproofUtil::ReadTestVectors("hmac_sha512_test.json"); ASSERT_TRUE(WycheproofTest(*root512, HashType::SHA512)); } */ } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/stream_segment_decrypter.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_STREAM_SEGMENT_DECRYPTER_H_ #define TINK_SUBTLE_STREAM_SEGMENT_DECRYPTER_H_ #include #include #include "tink/util/status.h" namespace crypto { namespace tink { namespace subtle { // StreamSegmentDecrypter is a helper class that decrypts individual // segments of a stream. // // Instances of this are passed to an ...DecryptingStream. Each instance // of a segment decrypter must be initialized with a header of a ciphertext // stream and is used to decrypt that stream. // // See stream_segment_encrypter.h for more info on the structure of // a ciphertext stream. class StreamSegmentDecrypter { public: // Decrypts 'ciphertext' as a segment, and writes the resulting plaintext // to 'plaintext_buffer', adjusting its size as needed. // 'ciphertext' and 'plaintext_buffer' must refer to distinct and // non-overlapping space. // Decryption uses the current value returned by get_segment_number() // as the segment number, and subsequently increments the current // segment number. virtual util::Status DecryptSegment( const std::vector& ciphertext, int64_t segment_number, bool is_last_segment, std::vector* plaintext_buffer) = 0; // Initializes this decrypter, using the information from 'header', // which must be of size exactly get_header_size(). virtual util::Status Init(const std::vector& header) = 0; // Returns the size (in bytes) of the header of a ciphertext stream. virtual int get_header_size() const = 0; // Returns the size (in bytes) of a plaintext segment. virtual int get_plaintext_segment_size() const = 0; // Returns the size (in bytes) of a ciphertext segment. virtual int get_ciphertext_segment_size() const = 0; // Returns the offset (in bytes) of the ciphertext within an decrypted stream. // The offset is non-negative, and not larger than // ciphertext_segment_size - (header_size + segment_overhead) // where // ciphertext_segment_size = get_ciphertext_segment_size() // header_size = get_header_size() // segment_overhead = ciphertext_segment_size - get_plaintext_segment_size() virtual int get_ciphertext_offset() const = 0; virtual ~StreamSegmentDecrypter() = default; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_STREAM_SEGMENT_DECRYPTER_H_ ================================================ FILE: cc/subtle/stream_segment_encrypter.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_STREAM_SEGMENT_ENCRYPTER_H_ #define TINK_SUBTLE_STREAM_SEGMENT_ENCRYPTER_H_ #include #include #include "tink/util/status.h" namespace crypto { namespace tink { namespace subtle { // StreamSegmentEncrypter is a helper class that encrypts individual // segments of a stream. // // Instances of this are passed to an ...EncryptingStream. Each instance // of a segment encrypter is used to encrypt one stream. // // Typically, construction of a new StreamSegmentEncrypter results // in a generation of a new symmetric key, which is used to // the segments of the stream. The key itself wrapped with or derived // from the key from StreamingAead instance. The wrapped key or the salt // used to derive the symmetric key is part of the header. // // StreamSegmentEncrypter has a state: it keeps the number of segments // encrypted so far. This state is used to encrypt each segment with different // parameters, so that segments in the ciphertext cannot be switched. // // Values returned by StreamSegmentEncrypter's methods effectively define // the layout of the resulting ciphertext stream: // // | other | header | 1st ciphertext segment | // | ...... 2nd ciphertext segment ..... | // | ...... 3rd ciphertext segment ..... | // | ...... ... ..... | // | ...... last ciphertext segment | // // where the following holds: // * each line above, except for the last one, // contains get_ciphertext_segment_size() bytes // * each segment, except for the 1st and the last one, // encrypts get_plaintext_segment_size() bytes of plaintext // * if the ciphertext stream encrypts at least one byte of plaintext, // then the last segment encrypts at least one byte of plaintext // * 'other' is get_ciphertext_offset() bytes long, and represents potential // other bytes already written to the stream; the purpose of ciphertext // offset is to allow alignment of ciphertext segments with segments // of the underlying storage or transmission stream. class StreamSegmentEncrypter { public: // Encrypts 'plaintext' as a segment, and writes the resulting ciphertext // to 'ciphertext_buffer', adjusting its size as needed. // 'plaintext' and 'ciphertext_buffer' must refer to distinct and // non-overlapping space. // Encryption uses the current value returned by get_segment_number() // as the segment number, and subsequently increments the current // segment number. virtual util::Status EncryptSegment( const std::vector& plaintext, bool is_last_segment, std::vector* ciphertext_buffer) = 0; // Returns the header of the ciphertext stream. virtual const std::vector& get_header() const = 0; // Returns the segment number that will be used for encryption // of the next segment. virtual int64_t get_segment_number() const = 0; // Returns the size (in bytes) of a plaintext segment. virtual int get_plaintext_segment_size() const = 0; // Returns the size (in bytes) of a ciphertext segment. virtual int get_ciphertext_segment_size() const = 0; // Returns the offset (in bytes) of the ciphertext within an encrypted stream. // The offset is non-negative, and not larger than // ciphertext_segment_size - (header_size + segment_overhead) // where // ciphertext_segment_size = get_ciphertext_segment_size() // header_size = get_header().size() // segment_overhead = ciphertext_segment_size - get_plaintext_segment_size() virtual int get_ciphertext_offset() const = 0; virtual ~StreamSegmentEncrypter() = default; protected: // Increments the segment number. virtual void IncSegmentNumber() = 0; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_STREAM_SEGMENT_ENCRYPTER_H_ ================================================ FILE: cc/subtle/streaming_aead_decrypting_stream.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/streaming_aead_decrypting_stream.h" #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/input_stream.h" #include "tink/subtle/stream_segment_decrypter.h" #include "tink/util/status.h" #include "tink/util/statusor.h" using crypto::tink::InputStream; using crypto::tink::util::Status; using crypto::tink::util::StatusOr; namespace crypto { namespace tink { namespace subtle { namespace { // Reads at most 'count' bytes from the specified 'input_stream', // and puts them into 'output', where both 'input_stream' and 'output' // must be non-null. // Will try to read exactly 'count' bytes, unless the end of stream // is reached (then returns status OUT_OF_RANGE) or an error occurs // (an other non-OK status). // Before returning, resizes 'output' accordingly, to reflect // the actual number of bytes read. util::Status ReadFromStream(InputStream* input_stream, int count, std::vector* output) { if (count <= 0 || input_stream == nullptr || output == nullptr) { return Status(absl::StatusCode::kInternal, "Illegal read from a stream"); } const void* buffer; int bytes_to_be_read = count; int read_bytes; // bytes read in one Next()-call int needed_bytes; // bytes actually needed output->resize(count); while (bytes_to_be_read > 0) { auto next_result = input_stream->Next(&buffer); if (next_result.status().code() == absl::StatusCode::kOutOfRange) { // End of stream. output->resize(count - bytes_to_be_read); return next_result.status(); } if (!next_result.ok()) return next_result.status(); read_bytes = next_result.value(); needed_bytes = std::min(read_bytes, bytes_to_be_read); memcpy(output->data() + (count - bytes_to_be_read), buffer, needed_bytes); bytes_to_be_read -= needed_bytes; } if (read_bytes > needed_bytes) { input_stream->BackUp(read_bytes - needed_bytes); } return util::OkStatus(); } } // anonymous namespace // static StatusOr> StreamingAeadDecryptingStream::New( std::unique_ptr segment_decrypter, std::unique_ptr ciphertext_source) { if (segment_decrypter == nullptr) { return Status(absl::StatusCode::kInvalidArgument, "segment_decrypter must be non-null"); } if (ciphertext_source == nullptr) { return Status(absl::StatusCode::kInvalidArgument, "cipertext_source must be non-null"); } std::unique_ptr dec_stream( new StreamingAeadDecryptingStream()); dec_stream->segment_decrypter_ = std::move(segment_decrypter); dec_stream->ct_source_ = std::move(ciphertext_source); int first_segment_size = dec_stream->segment_decrypter_->get_ciphertext_segment_size() - dec_stream->segment_decrypter_->get_ciphertext_offset() - dec_stream->segment_decrypter_->get_header_size(); if (first_segment_size <= 0) { return Status(absl::StatusCode::kInternal, "Size of the first segment must be greater than 0."); } dec_stream->ct_buffer_.resize(first_segment_size); dec_stream->position_ = 0; dec_stream->segment_number_ = 0; dec_stream->is_initialized_ = false; dec_stream->read_last_segment_ = false; dec_stream->count_backedup_ = first_segment_size; dec_stream->pt_buffer_offset_ = 0; dec_stream->status_ = util::OkStatus(); return {std::move(dec_stream)}; } StatusOr StreamingAeadDecryptingStream::Next(const void** data) { if (!status_.ok()) return status_; // The first call to Next(). if (!is_initialized_) { std::vector header; status_ = ReadFromStream(ct_source_.get(), segment_decrypter_->get_header_size(), &header); if (status_.code() == absl::StatusCode::kOutOfRange) { status_ = Status(absl::StatusCode::kInvalidArgument, "Could not read stream header."); } if (!status_.ok()) return status_; status_ = segment_decrypter_->Init(header); if (!status_.ok()) return status_; is_initialized_ = true; count_backedup_ = 0; status_ = ReadFromStream(ct_source_.get(), ct_buffer_.size(), &ct_buffer_); if (!status_.ok() && (status_.code() != absl::StatusCode::kOutOfRange)) { return status_; } read_last_segment_ = (status_.code() == absl::StatusCode::kOutOfRange); status_ = segment_decrypter_->DecryptSegment( ct_buffer_, /* segment_number = */ segment_number_, /* is_last_segment = */ read_last_segment_, &pt_buffer_); if (!status_.ok() && !read_last_segment_) { // Try decrypting as the last segment, if haven't tried yet. read_last_segment_ = true; status_ = segment_decrypter_->DecryptSegment( ct_buffer_, /* segment_number = */ segment_number_, /* is_last_segment = */ read_last_segment_, &pt_buffer_); } if (!status_.ok()) return status_; *data = pt_buffer_.data(); position_ = pt_buffer_.size(); return pt_buffer_.size(); } // If some bytes were backed up, return them first. if (count_backedup_ > 0) { position_ += count_backedup_; pt_buffer_offset_ = pt_buffer_.size() - count_backedup_; int backedup = count_backedup_; count_backedup_ = 0; *data = pt_buffer_.data() + pt_buffer_offset_; return backedup; } // We're past the first segment, and no space was backed up, so we // try to get and decrypt the next ciphertext segment, if any. if (read_last_segment_) { status_ = Status(absl::StatusCode::kOutOfRange, "Reached end of stream."); return status_; } segment_number_++; ct_buffer_.resize(segment_decrypter_->get_ciphertext_segment_size()); status_ = ReadFromStream(ct_source_.get(), ct_buffer_.size(), &ct_buffer_); if (!status_.ok() && (status_.code() != absl::StatusCode::kOutOfRange)) { return status_; } read_last_segment_ = (status_.code() == absl::StatusCode::kOutOfRange); status_ = segment_decrypter_->DecryptSegment( ct_buffer_, /* segment_number = */ segment_number_, /* is_last_segment = */ read_last_segment_, &pt_buffer_); if (!status_.ok() && !read_last_segment_) { // Try decrypting as the last segment, if haven't tried yet. read_last_segment_ = true; status_ = segment_decrypter_->DecryptSegment( ct_buffer_, /* segment_number = */ segment_number_, /* is_last_segment = */ read_last_segment_, &pt_buffer_); } if (!status_.ok()) return status_; *data = pt_buffer_.data(); pt_buffer_offset_ = 0; position_ += pt_buffer_.size(); return pt_buffer_.size(); } void StreamingAeadDecryptingStream::BackUp(int count) { if (!is_initialized_ || !status_.ok() || count < 1) return; int curr_buffer_size = pt_buffer_.size() - pt_buffer_offset_; int actual_count = std::min(count, curr_buffer_size - count_backedup_); count_backedup_ += actual_count; position_ -= actual_count; } int64_t StreamingAeadDecryptingStream::Position() const { return position_; } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/streaming_aead_decrypting_stream.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_STREAMING_AEAD_DECRYPTING_STREAM_H_ #define TINK_SUBTLE_STREAMING_AEAD_DECRYPTING_STREAM_H_ #include #include #include #include "tink/input_stream.h" #include "tink/subtle/stream_segment_decrypter.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { class StreamingAeadDecryptingStream : public InputStream { public: // A factory that produces decrypting streams. // The returned stream is a wrapper around 'ciphertext_source', // such that reading via the wrapper leads to AEAD-decryption of the // underlying ciphertext by 'segment_decrypter', using 'associated_data' as // associated authenticated data, and the read bytes are bytes of the // resulting plaintext. static crypto::tink::util::StatusOr> New(std::unique_ptr segment_decrypter, std::unique_ptr ciphertext_source); // ----------------------- // Methods of InputStream-interface implemented by this class. crypto::tink::util::StatusOr Next(const void** data) override; void BackUp(int count) override; int64_t Position() const override; private: StreamingAeadDecryptingStream() {} std::unique_ptr segment_decrypter_; std::unique_ptr ct_source_; std::vector ct_buffer_; // ciphertext buffer std::vector pt_buffer_; // plaintext buffer int64_t position_; // number of plaintext bytes read from this stream int64_t segment_number_; // current segment number crypto::tink::util::Status status_; // status of the stream // Counters that describe the state of the data in pt_buffer_. int count_backedup_; // # bytes in pt_buffer_ that were backed up int pt_buffer_offset_; // offset at which *data starts in pt_buffer_ // Flag that indicates whether the decrypting stream has been initialized. // If true, the header of the ciphertext stream has been already read // and processed. bool is_initialized_; bool read_last_segment_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_STREAMING_AEAD_DECRYPTING_STREAM_H_ ================================================ FILE: cc/subtle/streaming_aead_decrypting_stream_test.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/streaming_aead_decrypting_stream.h" #include #include #include #include #include #include #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/input_stream.h" #include "tink/subtle/random.h" #include "tink/subtle/stream_segment_decrypter.h" #include "tink/subtle/test_util.h" #include "tink/util/istream_input_stream.h" #include "tink/util/status.h" #include "tink/util/statusor.h" using crypto::tink::InputStream; using crypto::tink::subtle::test::DummyStreamSegmentDecrypter; using crypto::tink::subtle::test::DummyStreamSegmentEncrypter; using crypto::tink::util::IstreamInputStream; namespace crypto { namespace tink { namespace subtle { namespace { // References to objects used for test validation. // The objects pointed to are not owned by this structure. struct ValidationRefs { DummyStreamSegmentDecrypter* seg_dec; // segment decrypter }; // A helper for creating StreamingAeadDecryptingStream together // with references to internal objects, used for test validation. std::unique_ptr GetDecryptingStream( int pt_segment_size, int header_size, int ct_offset, absl::string_view ciphertext, ValidationRefs* refs) { // Prepare ciphertext source stream. auto ct_stream = absl::make_unique(std::string(ciphertext)); std::unique_ptr ct_source( absl::make_unique(std::move(ct_stream))); auto seg_dec = absl::make_unique( pt_segment_size, header_size, ct_offset); // A reference to the segment decrypter, for later validation. refs->seg_dec = seg_dec.get(); auto dec_stream = std::move(StreamingAeadDecryptingStream::New( std::move(seg_dec), std::move(ct_source)) .value()); EXPECT_EQ(0, dec_stream->Position()); return dec_stream; } class StreamingAeadDecryptingStreamTest : public ::testing::Test { }; TEST_F(StreamingAeadDecryptingStreamTest, WritingStreams) { std::vector pt_sizes = {0, 10, 100, 1000, 10000, 100000, 1000000}; std::vector pt_segment_sizes = {64, 100, 128, 1000, 1024}; std::vector header_sizes = {5, 10, 32}; std::vector ct_offsets = {0, 1, 5, 15}; for (auto pt_size : pt_sizes) { for (auto pt_segment_size : pt_segment_sizes) { for (auto header_size : header_sizes) { for (auto ct_offset : ct_offsets) { SCOPED_TRACE(absl::StrCat("pt_size = ", pt_size, ", pt_segment_size = ", pt_segment_size, ", header_size = ", header_size, ", ct_offset = ", ct_offset)); // Get a decrypting stream. std::string pt = Random::GetRandomBytes(pt_size); DummyStreamSegmentEncrypter seg_enc(pt_segment_size, header_size, ct_offset); std::string ct = seg_enc.GenerateCiphertext(pt); ValidationRefs refs; auto dec_stream = GetDecryptingStream(pt_segment_size, header_size, ct_offset, ct, &refs); // First buffer returned by Next(); const void* buffer; auto next_result = dec_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); int buffer_size = next_result.value(); int exp_buffer_size = pt_segment_size - (header_size + ct_offset); if (exp_buffer_size > pt_size) exp_buffer_size = pt_size; EXPECT_EQ(exp_buffer_size, buffer_size); EXPECT_EQ(buffer_size, dec_stream->Position()); // Backup the entire first buffer. dec_stream->BackUp(buffer_size); EXPECT_EQ(0, dec_stream->Position()); // Read the entire plaintext to the stream. std::string decrypted; auto status = test::ReadFromStream(dec_stream.get(), &decrypted); EXPECT_TRUE(status.ok()) << status; EXPECT_EQ(dec_stream->Position(), pt.size()); EXPECT_EQ(pt, decrypted); } } } } } TEST_F(StreamingAeadDecryptingStreamTest, EmptyCiphertext) { int pt_segment_size = 512; int header_size = 64; // Get a decrypting stream. ValidationRefs refs; auto dec_stream = GetDecryptingStream(pt_segment_size, header_size, /* ct_offset = */ 0, /* ciphertext = */ "", &refs); // First buffer returned by Next(); const void* buffer; auto next_result = dec_stream->Next(&buffer); EXPECT_FALSE(next_result.ok()); EXPECT_EQ(next_result.status().code(), absl::StatusCode::kInvalidArgument); EXPECT_PRED_FORMAT2(testing::IsSubstring, "Could not read stream header", std::string(next_result.status().message())); } TEST_F(StreamingAeadDecryptingStreamTest, InvalidStreamHeader) { int pt_segment_size = 512; int header_size = 64; // Get a decrypting stream. ValidationRefs refs; auto dec_stream = GetDecryptingStream(pt_segment_size, header_size, /* ct_offset = */ 0, std::string(header_size, 'a'), &refs); // First buffer returned by Next(); const void* buffer; auto next_result = dec_stream->Next(&buffer); EXPECT_FALSE(next_result.ok()); EXPECT_EQ(next_result.status().code(), absl::StatusCode::kInvalidArgument); EXPECT_PRED_FORMAT2(testing::IsSubstring, "Invalid stream header", std::string(next_result.status().message())); } TEST_F(StreamingAeadDecryptingStreamTest, TruncatedLastSegment) { int pt_segment_size = 120; int pt_size = 500; int header_size = 64; // Get a decrypting stream. std::string pt = Random::GetRandomBytes(pt_size); DummyStreamSegmentEncrypter seg_enc(pt_segment_size, header_size, /* ct_offset = */ 0); std::string ct = seg_enc.GenerateCiphertext(pt); ValidationRefs refs; auto dec_stream = GetDecryptingStream(pt_segment_size, header_size, /* ct_offset = */ 0, ct.substr(0, ct.size()-2), &refs); // First buffer returned by Next(); std::string decrypted; auto status = test::ReadFromStream(dec_stream.get(), &decrypted); EXPECT_FALSE(status.ok()); EXPECT_EQ(status.code(), absl::StatusCode::kInvalidArgument); EXPECT_PRED_FORMAT2(testing::IsSubstring, "unexpected last-segment marker", std::string(status.message())); } TEST_F(StreamingAeadDecryptingStreamTest, OneSegmentPlaintext) { int pt_segment_size = 512; int header_size = 64; // Get a decrypting stream. std::string pt = Random::GetRandomBytes(pt_segment_size - header_size); DummyStreamSegmentEncrypter seg_enc(pt_segment_size, header_size, /* ct_offset = */ 0); std::string ct = seg_enc.GenerateCiphertext(pt); EXPECT_EQ(seg_enc.get_ciphertext_segment_size(), ct.size()); ValidationRefs refs; auto dec_stream = GetDecryptingStream(pt_segment_size, header_size, /* ct_offset = */ 0, ct, &refs); // Get the first segment. const void* buffer; auto next_result = dec_stream->Next(&buffer); int buffer_size = pt_segment_size - header_size; EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(buffer_size, dec_stream->Position()); EXPECT_EQ(pt, std::string(reinterpret_cast(buffer), buffer_size)); // Try getting another segment. next_result = dec_stream->Next(&buffer); EXPECT_FALSE(next_result.ok()); EXPECT_EQ(absl::StatusCode::kOutOfRange, next_result.status().code()); } TEST_F(StreamingAeadDecryptingStreamTest, OneSegmentAndOneBytePlaintext) { int pt_segment_size = 512; int header_size = 64; // Get a decrypting stream. std::string pt = Random::GetRandomBytes(pt_segment_size - header_size + 1); DummyStreamSegmentEncrypter seg_enc(pt_segment_size, header_size, /* ct_offset = */ 0); std::string ct = seg_enc.GenerateCiphertext(pt); EXPECT_EQ(seg_enc.get_ciphertext_segment_size() + DummyStreamSegmentEncrypter::kSegmentTagSize + 1, ct.size()); ValidationRefs refs; auto dec_stream = GetDecryptingStream(pt_segment_size, header_size, /* ct_offset = */ 0, ct, &refs); // Get the first segment. const void* buffer; auto next_result = dec_stream->Next(&buffer); int buffer_size = pt_segment_size - header_size; EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(buffer_size, dec_stream->Position()); EXPECT_EQ(pt.substr(0, buffer_size), std::string(reinterpret_cast(buffer), buffer_size)); // Get the second segment. next_result = dec_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(1, next_result.value()); EXPECT_EQ(pt.size(), dec_stream->Position()); EXPECT_EQ(pt.at(pt.size()-1), *(reinterpret_cast(buffer))); // Try getting another segment. next_result = dec_stream->Next(&buffer); EXPECT_FALSE(next_result.ok()); EXPECT_EQ(absl::StatusCode::kOutOfRange, next_result.status().code()); } TEST_F(StreamingAeadDecryptingStreamTest, NextAfterBackUp) { int pt_segment_size = 97; int pt_size = 334; int header_size = 30; // Get a decrypting stream. std::string pt = Random::GetRandomBytes(pt_size); DummyStreamSegmentEncrypter seg_enc(pt_segment_size, header_size, /* ct_offset = */ 0); std::string ct = seg_enc.GenerateCiphertext(pt); ValidationRefs refs; auto dec_stream = GetDecryptingStream(pt_segment_size, header_size, /* ct_offset = */ 0, ct, &refs); // Get the first segment. const void* buffer; auto next_result = dec_stream->Next(&buffer); int buffer_size = pt_segment_size - header_size; EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(buffer_size, dec_stream->Position()); EXPECT_EQ(pt.substr(0, buffer_size), std::string(reinterpret_cast(buffer), buffer_size)); std::string decrypted_first_segment(reinterpret_cast(buffer), buffer_size); // Backup part of the first segment, and call Next again. int backup_size = buffer_size / 2; dec_stream->BackUp(backup_size); EXPECT_EQ(buffer_size - backup_size, dec_stream->Position()); next_result = dec_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(backup_size, next_result.value()); EXPECT_EQ(buffer_size, dec_stream->Position()); EXPECT_EQ(pt.substr(buffer_size - backup_size, backup_size), std::string(reinterpret_cast(buffer), backup_size)); // Backup a smaller part of the first segment, and call Next again. int backup2_size = buffer_size / 4; dec_stream->BackUp(backup2_size); EXPECT_EQ(buffer_size - backup2_size, dec_stream->Position()); next_result = dec_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(backup2_size, next_result.value()); EXPECT_EQ(buffer_size, dec_stream->Position()); EXPECT_EQ(pt.substr(buffer_size - backup2_size, backup2_size), std::string(reinterpret_cast(buffer), backup2_size)); // Read the stream to the end. std::string decrypted_rest; auto status = test::ReadFromStream(dec_stream.get(), &decrypted_rest); EXPECT_TRUE(status.ok()) << status; EXPECT_EQ(pt_size, dec_stream->Position()); EXPECT_EQ(pt, (decrypted_first_segment + decrypted_rest)); } TEST_F(StreamingAeadDecryptingStreamTest, BackupAndPosition) { int pt_segment_size = 555; int pt_size = 2313; int header_size = 33; // Get a decrypting stream. std::string pt = Random::GetRandomBytes(pt_size); DummyStreamSegmentEncrypter seg_enc(pt_segment_size, header_size, /* ct_offset = */ 0); std::string ct = seg_enc.GenerateCiphertext(pt); ValidationRefs refs; auto dec_stream = GetDecryptingStream(pt_segment_size, header_size, /* ct_offset = */ 0, ct, &refs); // The first segment. const void* buffer; auto next_result = dec_stream->Next(&buffer); int buffer_size = pt_segment_size - header_size; EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(buffer_size, dec_stream->Position()); std::string decrypted_first_segment(reinterpret_cast(buffer), buffer_size); // BackUp several times, but in total fewer bytes than returned by Next(). std::vector backup_sizes = {0, 1, 5, 0, 10, 78, -42, 60, 120, -120}; int total_backup_size = 0; for (auto backup_size : backup_sizes) { dec_stream->BackUp(backup_size); total_backup_size += std::max(0, backup_size); EXPECT_EQ(buffer_size - total_backup_size, dec_stream->Position()); } EXPECT_LT(total_backup_size, next_result.value()); // Call Next(), it should succeed (backuped bytes of 1st segment). next_result = dec_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(total_backup_size, next_result.value()); EXPECT_EQ(buffer_size, dec_stream->Position()); // BackUp() some bytes, again fewer than returned by Next(). backup_sizes = {0, 72, -94, 37, 82}; total_backup_size = 0; for (auto backup_size : backup_sizes) { dec_stream->BackUp(backup_size); total_backup_size += std::max(0, backup_size); EXPECT_EQ(buffer_size - total_backup_size, dec_stream->Position()); } EXPECT_LT(total_backup_size, next_result.value()); // Call Next(), it should succeed (backuped bytes of 1st segment). next_result = dec_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(total_backup_size, next_result.value()); EXPECT_EQ(buffer_size, dec_stream->Position()); // Call Next() again, it should return a full block (2nd segment). auto prev_position = dec_stream->Position(); buffer_size = pt_segment_size; next_result = dec_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(prev_position + buffer_size, dec_stream->Position()); // BackUp a few times, with total over the returned buffer_size. backup_sizes = {0, 72, -100, buffer_size / 2, 200, -25, buffer_size / 2, 42}; total_backup_size = 0; for (auto backup_size : backup_sizes) { SCOPED_TRACE(absl::StrCat("backup_size = ", backup_size, ", total_backup_size = ", total_backup_size)); dec_stream->BackUp(backup_size); total_backup_size = std::min(buffer_size, total_backup_size + std::max(0, backup_size)); EXPECT_EQ(prev_position + buffer_size - total_backup_size, dec_stream->Position()); } EXPECT_EQ(total_backup_size, buffer_size); EXPECT_EQ(prev_position, dec_stream->Position()); // Call Next() again, it should return a full segment (2nd segment); next_result = dec_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(prev_position + buffer_size, dec_stream->Position()); EXPECT_EQ(2 * pt_segment_size - header_size, dec_stream->Position()); // Backup the 2nd segment again, and read the stream to the end. dec_stream->BackUp(buffer_size); EXPECT_EQ(prev_position, dec_stream->Position()); std::string decrypted_rest; auto status = test::ReadFromStream(dec_stream.get(), &decrypted_rest); EXPECT_TRUE(status.ok()) << status; EXPECT_EQ(pt_size, dec_stream->Position()); EXPECT_EQ(pt, decrypted_first_segment + decrypted_rest); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/streaming_aead_encrypting_stream.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/streaming_aead_encrypting_stream.h" #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/output_stream.h" #include "tink/subtle/stream_segment_encrypter.h" #include "tink/util/status.h" #include "tink/util/statusor.h" using crypto::tink::OutputStream; using crypto::tink::util::Status; using crypto::tink::util::StatusOr; namespace crypto { namespace tink { namespace subtle { namespace { // Writes 'contents' to the specified 'output_stream', which must be non-null. // In case of errors returns the first non-OK status of // output_stream->Next()-operation. util::Status WriteToStream(const std::vector& contents, OutputStream* output_stream) { void* buffer; int pos = 0; int remaining = contents.size(); int available_space = 0; int available_bytes = 0; while (remaining > 0) { auto next_result = output_stream->Next(&buffer); if (!next_result.ok()) return next_result.status(); available_space = next_result.value(); available_bytes = std::min(available_space, remaining); memcpy(buffer, contents.data() + pos, available_bytes); remaining -= available_bytes; pos += available_bytes; } if (available_space > available_bytes) { output_stream->BackUp(available_space - available_bytes); } return util::OkStatus(); } } // anonymous namespace // static StatusOr> StreamingAeadEncryptingStream::New( std::unique_ptr segment_encrypter, std::unique_ptr ciphertext_destination) { if (segment_encrypter == nullptr) { return Status(absl::StatusCode::kInvalidArgument, "segment_encrypter must be non-null"); } if (ciphertext_destination == nullptr) { return Status(absl::StatusCode::kInvalidArgument, "cipertext_destination must be non-null"); } std::unique_ptr enc_stream( new StreamingAeadEncryptingStream()); enc_stream->segment_encrypter_ = std::move(segment_encrypter); enc_stream->ct_destination_ = std::move(ciphertext_destination); int first_segment_size = enc_stream->segment_encrypter_->get_plaintext_segment_size() - enc_stream->segment_encrypter_->get_ciphertext_offset() - enc_stream->segment_encrypter_->get_header().size(); if (first_segment_size <= 0) { return Status(absl::StatusCode::kInternal, "Size of the first segment must be greater than 0."); } enc_stream->pt_buffer_.resize(first_segment_size); enc_stream->pt_to_encrypt_.resize(0); enc_stream->position_ = 0; enc_stream->is_first_segment_ = true; enc_stream->count_backedup_ = first_segment_size; enc_stream->pt_buffer_offset_ = 0; enc_stream->status_ = util::OkStatus(); return {std::move(enc_stream)}; } StatusOr StreamingAeadEncryptingStream::Next(void** data) { if (!status_.ok()) return status_; // The first call to Next(). if (is_first_segment_) { is_first_segment_ = false; count_backedup_ = 0; status_ = WriteToStream(segment_encrypter_->get_header(), ct_destination_.get()); if (!status_.ok()) return status_; *data = pt_buffer_.data(); position_ = pt_buffer_.size(); return pt_buffer_.size(); } // If some space was backed up, return it first. if (count_backedup_ > 0) { position_ += count_backedup_; pt_buffer_offset_ = pt_buffer_.size() - count_backedup_; int backedup = count_backedup_; count_backedup_ = 0; *data = pt_buffer_.data() + pt_buffer_offset_; return backedup; } // We're past the first segment, and no space was backed up, so we: // 1. encrypt pt_to_encrypt_ (if non-empty) as a not-last segment // and attempt to write the ciphertext to ct_destination_. // 2. move contents of pt_buffer_ to pt_to_encrypt_ (for later encryption, // as we don't know yet whether it will be the last segment or not. // 3. prepare and return "fresh" pt_buffer_. // // Step 1. if (!pt_to_encrypt_.empty()) { status_ = segment_encrypter_->EncryptSegment( pt_to_encrypt_, /* is_last_segment = */ false, &ct_buffer_); if (!status_.ok()) return status_; status_ = WriteToStream(ct_buffer_, ct_destination_.get()); if (!status_.ok()) return status_; } // Step 2. pt_buffer_.swap(pt_to_encrypt_); // Step 3. pt_buffer_.resize(segment_encrypter_->get_plaintext_segment_size()); *data = pt_buffer_.data(); pt_buffer_offset_ = 0; position_ += pt_buffer_.size(); return pt_buffer_.size(); } void StreamingAeadEncryptingStream::BackUp(int count) { if (is_first_segment_ || !status_.ok() || count < 1) return; int curr_buffer_size = pt_buffer_.size() - pt_buffer_offset_; int actual_count = std::min(count, curr_buffer_size - count_backedup_); count_backedup_ += actual_count; position_ -= actual_count; } Status StreamingAeadEncryptingStream::Close() { if (!status_.ok()) return status_; if (is_first_segment_) { // Next() was never called. status_ = WriteToStream(segment_encrypter_->get_header(), ct_destination_.get()); if (!status_.ok()) return status_; } // The last segment encrypts plaintext from pt_to_encrypt_, // unless the current pt_buffer_ has some plaintext bytes. std::vector* pt_last_segment = &pt_to_encrypt_; if ((!pt_buffer_.empty()) && count_backedup_ < pt_buffer_.size()) { // The last segment encrypts plaintext from pt_buffer_. pt_buffer_.resize(pt_buffer_.size() - count_backedup_); pt_last_segment = &pt_buffer_; } if (pt_last_segment != &pt_to_encrypt_ && (!pt_to_encrypt_.empty())) { // Before writing the last segment we must encrypt pt_to_encrypt_. status_ = segment_encrypter_->EncryptSegment( pt_to_encrypt_, /* is_last_segment = */ false, &ct_buffer_); if (!status_.ok()) { ct_destination_->Close().IgnoreError(); return status_; } status_ = WriteToStream(ct_buffer_, ct_destination_.get()); if (!status_.ok()) { ct_destination_->Close().IgnoreError(); return status_; } } // Encrypt pt_last_segment, write the ciphertext, and close the stream. status_ = segment_encrypter_->EncryptSegment( *pt_last_segment, /* is_last_segment = */ true, &ct_buffer_); if (!status_.ok()) { ct_destination_->Close().IgnoreError(); return status_; } status_ = WriteToStream(ct_buffer_, ct_destination_.get()); if (!status_.ok()) { ct_destination_->Close().IgnoreError(); return status_; } status_ = Status(absl::StatusCode::kFailedPrecondition, "Stream closed"); return ct_destination_->Close(); } int64_t StreamingAeadEncryptingStream::Position() const { return position_; } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/streaming_aead_encrypting_stream.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_STREAMING_AEAD_ENCRYPTING_STREAM_H_ #define TINK_SUBTLE_STREAMING_AEAD_ENCRYPTING_STREAM_H_ #include #include #include #include "tink/output_stream.h" #include "tink/subtle/stream_segment_encrypter.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { class StreamingAeadEncryptingStream : public OutputStream { public: // A factory that produces encrypting streams. // The returned stream is a wrapper around 'ciphertext_destination', // such that any bytes written via the wrapper are AEAD-encrypted // by 'segment_encrypter' using 'associated_data' as associated // authenticated data. static crypto::tink::util::StatusOr> New(std::unique_ptr segment_encrypter, std::unique_ptr ciphertext_destination); // ----------------------- // Methods of OutputStream-interface implemented by this class. crypto::tink::util::StatusOr Next(void** data) override; void BackUp(int count) override; crypto::tink::util::Status Close() override; int64_t Position() const override; private: StreamingAeadEncryptingStream() {} std::unique_ptr segment_encrypter_; std::unique_ptr ct_destination_; std::vector pt_buffer_; // plaintext buffer std::vector ct_buffer_; // ciphertext buffer std::vector pt_to_encrypt_; // plaintext to be encrypted int64_t position_; // number of plaintext bytes written to this stream crypto::tink::util::Status status_; // status of the stream // Counters that describe the state of the data in pt_buffer_. int count_backedup_; // # bytes in pt_buffer_ that were backed up int pt_buffer_offset_; // offset at which *data starts in pt_buffer_ // Flag that indicates whether the user has obtained a buffer to write // the data of the first segment. // If true, Next() was not called yet, which implies that neither // header has been written to ct_destination_, nor the user had // a chance to write any data to this stream. bool is_first_segment_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_STREAMING_AEAD_ENCRYPTING_STREAM_H_ ================================================ FILE: cc/subtle/streaming_aead_encrypting_stream_test.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/streaming_aead_encrypting_stream.h" #include #include #include #include #include #include #include #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/output_stream.h" #include "tink/subtle/random.h" #include "tink/subtle/stream_segment_encrypter.h" #include "tink/subtle/test_util.h" #include "tink/util/ostream_output_stream.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { using crypto::tink::OutputStream; using crypto::tink::subtle::test::DummyStreamSegmentEncrypter; using crypto::tink::util::OstreamOutputStream; namespace { // References to objects used for test validation. // The objects pointed to are not owned by this structure. struct ValidationRefs { std::stringbuf* ct_buf; // buffer that contains the resulting ciphertext DummyStreamSegmentEncrypter* seg_enc; // segment encrypter }; // A helper for creating StreamingAeadEncryptingStream together // with references to internal objects, used for test validation. std::unique_ptr GetEncryptingStream( int pt_segment_size, int header_size, int ct_offset, ValidationRefs* refs) { // Prepare ciphertext destination stream. auto ct_stream = absl::make_unique(); // A reference to the ciphertext buffer, for later validation. refs->ct_buf = ct_stream->rdbuf(); std::unique_ptr ct_destination( absl::make_unique(std::move(ct_stream))); auto seg_enc = absl::make_unique( pt_segment_size, header_size, ct_offset); // A reference to the segment encrypter, for later validation. refs->seg_enc = seg_enc.get(); auto enc_stream = std::move(StreamingAeadEncryptingStream::New( std::move(seg_enc), std::move(ct_destination)) .value()); EXPECT_EQ(0, enc_stream->Position()); return enc_stream; } class StreamingAeadEncryptingStreamTest : public ::testing::Test { }; TEST_F(StreamingAeadEncryptingStreamTest, WritingStreams) { std::vector pt_sizes = {0, 10, 100, 1000, 10000, 100000, 1000000}; std::vector pt_segment_sizes = {64, 100, 128, 1000, 1024}; std::vector header_sizes = {5, 10, 32}; std::vector ct_offsets = {0, 1, 5, 15}; for (auto pt_size : pt_sizes) { for (auto pt_segment_size : pt_segment_sizes) { for (auto header_size : header_sizes) { for (auto ct_offset : ct_offsets) { SCOPED_TRACE(absl::StrCat("pt_size = ", pt_size, ", pt_segment_size = ", pt_segment_size, ", header_size = ", header_size, ", ct_offset = ", ct_offset)); // Get an encrypting stream. ValidationRefs refs; auto enc_stream = GetEncryptingStream(pt_segment_size, header_size, ct_offset, &refs); // First buffer returned by Next(); void* buffer; auto next_result = enc_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); int buffer_size = next_result.value(); EXPECT_EQ(pt_segment_size - (header_size + ct_offset), buffer_size); EXPECT_EQ(buffer_size, enc_stream->Position()); // Backup the entire first buffer. enc_stream->BackUp(buffer_size); EXPECT_EQ(0, enc_stream->Position()); // Write plaintext to the stream, and close the stream. std::string pt = Random::GetRandomBytes(pt_size); auto status = test::WriteToStream(enc_stream.get(), pt); EXPECT_TRUE(status.ok()) << status; EXPECT_EQ(enc_stream->Position(), pt.size()); EXPECT_EQ(refs.seg_enc->get_generated_output_size(), refs.ct_buf->str().size()); auto exp_ciphertext = refs.seg_enc->GenerateCiphertext(pt); EXPECT_EQ(exp_ciphertext.size(), refs.ct_buf->str().size()); EXPECT_EQ(exp_ciphertext, refs.ct_buf->str()); // Try closing the stream again. status = enc_stream->Close(); EXPECT_FALSE(status.ok()); EXPECT_EQ(absl::StatusCode::kFailedPrecondition, status.code()); } } } } } TEST_F(StreamingAeadEncryptingStreamTest, EmptyPlaintext) { int pt_segment_size = 512; int header_size = 64; // Get an encrypting stream. ValidationRefs refs; auto enc_stream = GetEncryptingStream( pt_segment_size, header_size, /* ct_offset = */ 0, &refs); // Close the stream. auto close_status = enc_stream->Close(); EXPECT_TRUE(close_status.ok()) << close_status; EXPECT_EQ(refs.seg_enc->get_generated_output_size(), refs.ct_buf->str().size()); // Ciphertext contains only the header and an "empty" first segment. EXPECT_EQ(header_size + DummyStreamSegmentEncrypter::kSegmentTagSize, refs.ct_buf->str().size()); // The last segment is marked as such. EXPECT_EQ(DummyStreamSegmentEncrypter::kLastSegment, refs.ct_buf->str().back()); // Try closing the stream again. close_status = enc_stream->Close(); EXPECT_FALSE(close_status.ok()); EXPECT_EQ(absl::StatusCode::kFailedPrecondition, close_status.code()); } TEST_F(StreamingAeadEncryptingStreamTest, EmptyPlaintextWithBackup) { int pt_segment_size = 512; int header_size = 64; void* buffer; // Get an encrypting stream. ValidationRefs refs; auto enc_stream = GetEncryptingStream( pt_segment_size, header_size, /* ct_offset = */ 0, &refs); // Get the first segment. auto next_result = enc_stream->Next(&buffer); int buffer_size = pt_segment_size - header_size; EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(buffer_size, enc_stream->Position()); // Backup the entire segment, and close the stream. enc_stream->BackUp(buffer_size); EXPECT_EQ(0, enc_stream->Position()); auto close_status = enc_stream->Close(); EXPECT_TRUE(close_status.ok()) << close_status; EXPECT_EQ(refs.seg_enc->get_generated_output_size(), refs.ct_buf->str().size()); // Ciphertext contains only the header and an "empty" first segment. EXPECT_EQ(header_size + DummyStreamSegmentEncrypter::kSegmentTagSize, refs.ct_buf->str().size()); // The last segment is marked as such. EXPECT_EQ(DummyStreamSegmentEncrypter::kLastSegment, refs.ct_buf->str().back()); // Try closing the stream again. close_status = enc_stream->Close(); EXPECT_FALSE(close_status.ok()); EXPECT_EQ(absl::StatusCode::kFailedPrecondition, close_status.code()); } TEST_F(StreamingAeadEncryptingStreamTest, OneSegmentPlaintext) { int pt_segment_size = 512; int header_size = 64; void* buffer; // Get an encrypting stream. ValidationRefs refs; auto enc_stream = GetEncryptingStream( pt_segment_size, header_size, /* ct_offset = */ 0, &refs); // Get the first segment, and close the stream. auto next_result = enc_stream->Next(&buffer); int buffer_size = pt_segment_size - header_size; EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(buffer_size, enc_stream->Position()); auto close_status = enc_stream->Close(); EXPECT_TRUE(close_status.ok()) << close_status; EXPECT_EQ(refs.seg_enc->get_generated_output_size(), refs.ct_buf->str().size()); // Ciphertext contains only header and a full first segment. EXPECT_EQ(pt_segment_size + DummyStreamSegmentEncrypter::kSegmentTagSize, refs.ct_buf->str().size()); // The last segment is marked as such. EXPECT_EQ(DummyStreamSegmentEncrypter::kLastSegment, refs.ct_buf->str().back()); // Try closing the stream again. close_status = enc_stream->Close(); EXPECT_FALSE(close_status.ok()); EXPECT_EQ(absl::StatusCode::kFailedPrecondition, close_status.code()); } TEST_F(StreamingAeadEncryptingStreamTest, NextAfterBackup) { int pt_segment_size = 512; int part1_size = 123; int part2_size = 74; int header_size = 64; void* buffer; // Get an encrypting stream. ValidationRefs refs; auto enc_stream = GetEncryptingStream( pt_segment_size, header_size, /* ct_offset = */ 0, &refs); // Get the first segment. auto next_result = enc_stream->Next(&buffer); int buffer_size = pt_segment_size - header_size; EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(buffer_size, enc_stream->Position()); // Backup so that only part1_size bytes are written. enc_stream->BackUp(buffer_size - part1_size); EXPECT_EQ(part1_size, enc_stream->Position()); // Get backed up space. void* backedup_buffer; next_result = enc_stream->Next(&backedup_buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size - part1_size, next_result.value()); EXPECT_EQ(reinterpret_cast(buffer) + part1_size, reinterpret_cast(backedup_buffer)); // Backup so again that (part1_size + part2_size) bytes are written. enc_stream->BackUp(buffer_size - (part1_size + part2_size)); EXPECT_EQ(part1_size + part2_size, enc_stream->Position()); // Get backed up space again. next_result = enc_stream->Next(&backedup_buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size - (part1_size + part2_size), next_result.value()); EXPECT_EQ(reinterpret_cast(buffer) + part1_size + part2_size, reinterpret_cast(backedup_buffer)); // Close the stream. auto close_status = enc_stream->Close(); EXPECT_TRUE(close_status.ok()) << close_status; } TEST_F(StreamingAeadEncryptingStreamTest, OneSegmentPlaintextWithBackup) { int pt_segment_size = 512; int pt_size = 200; int header_size = 64; void* buffer; // Get an encrypting stream. ValidationRefs refs; auto enc_stream = GetEncryptingStream( pt_segment_size, header_size, /* ct_offset = */ 0, &refs); // Get the first segment. auto next_result = enc_stream->Next(&buffer); int buffer_size = pt_segment_size - header_size; EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(buffer_size, enc_stream->Position()); // Backup so that only pt_size bytes are written, and close the stream. enc_stream->BackUp(buffer_size - pt_size); EXPECT_EQ(pt_size, enc_stream->Position()); auto close_status = enc_stream->Close(); EXPECT_TRUE(close_status.ok()) << close_status; EXPECT_EQ(refs.seg_enc->get_generated_output_size(), refs.ct_buf->str().size()); // Ciphertext contains only the header and partial first segment. EXPECT_EQ( header_size + pt_size + DummyStreamSegmentEncrypter::kSegmentTagSize, refs.ct_buf->str().size()); // The last segment is marked as such. EXPECT_EQ(DummyStreamSegmentEncrypter::kLastSegment, refs.ct_buf->str().back()); // Try closing the stream again. close_status = enc_stream->Close(); EXPECT_FALSE(close_status.ok()); EXPECT_EQ(absl::StatusCode::kFailedPrecondition, close_status.code()); } TEST_F(StreamingAeadEncryptingStreamTest, ManySegmentsPlaintext) { int pt_segment_size = 512; int header_size = 64; void* buffer; // Get an encrypting stream. ValidationRefs refs; auto enc_stream = GetEncryptingStream( pt_segment_size, header_size, /* ct_offset = */ 0, &refs); int seg_count = 5; // Get the first segment. auto next_result = enc_stream->Next(&buffer); int first_buffer_size = pt_segment_size - header_size; EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(first_buffer_size, next_result.value()); EXPECT_EQ(first_buffer_size, enc_stream->Position()); // Get remaining segments. for (int i = 1; i < seg_count; i++) { next_result = enc_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(pt_segment_size, next_result.value()); EXPECT_EQ(first_buffer_size + i * pt_segment_size, enc_stream->Position()); } // Close the stream. auto close_status = enc_stream->Close(); EXPECT_TRUE(close_status.ok()) << close_status; EXPECT_EQ(refs.seg_enc->get_generated_output_size(), refs.ct_buf->str().size()); // Ciphertext contains seg_count full segments. int ct_segment_size = pt_segment_size + DummyStreamSegmentEncrypter::kSegmentTagSize; EXPECT_EQ(refs.seg_enc->get_ciphertext_segment_size(), ct_segment_size); EXPECT_EQ(ct_segment_size * seg_count, refs.ct_buf->str().size()); // The last segment is marked as such. EXPECT_EQ(DummyStreamSegmentEncrypter::kLastSegment, refs.ct_buf->str().back()); // The previous segments are marked as not-last ones. for (int i = 1; i < seg_count - 1; i++) { EXPECT_EQ(DummyStreamSegmentEncrypter::kNotLastSegment, refs.ct_buf->str()[(ct_segment_size * i)-1]); } // Try closing the stream again. close_status = enc_stream->Close(); EXPECT_FALSE(close_status.ok()); EXPECT_EQ(absl::StatusCode::kFailedPrecondition, close_status.code()); } TEST_F(StreamingAeadEncryptingStreamTest, ManySegmentsPlaintextWithBackup) { int pt_segment_size = 512; int backup_size = 100; int header_size = 64; void* buffer; // Get an encrypting stream. ValidationRefs refs; auto enc_stream = GetEncryptingStream( pt_segment_size, header_size, /* ct_offset = */ 0, &refs); int seg_count = 5; // Get the first segment. auto next_result = enc_stream->Next(&buffer); int first_buffer_size = pt_segment_size - header_size; EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(first_buffer_size, next_result.value()); EXPECT_EQ(first_buffer_size, enc_stream->Position()); // Get remaining segments. for (int i = 1; i < seg_count; i++) { next_result = enc_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(pt_segment_size, next_result.value()); EXPECT_EQ(first_buffer_size + i * pt_segment_size, enc_stream->Position()); } // Backup part of the last segment, and close the stream. enc_stream->BackUp(backup_size); EXPECT_EQ(first_buffer_size + (seg_count - 1) * pt_segment_size - backup_size, enc_stream->Position()); auto close_status = enc_stream->Close(); EXPECT_TRUE(close_status.ok()) << close_status; EXPECT_EQ(refs.seg_enc->get_generated_output_size(), refs.ct_buf->str().size()); // Ciphertext contains seg_count full segments, minus the size of the backup. int ct_segment_size = pt_segment_size + DummyStreamSegmentEncrypter::kSegmentTagSize; EXPECT_EQ(refs.seg_enc->get_ciphertext_segment_size(), ct_segment_size); EXPECT_EQ(ct_segment_size * seg_count - backup_size, refs.ct_buf->str().size()); // The last segment is marked as such. EXPECT_EQ(DummyStreamSegmentEncrypter::kLastSegment, refs.ct_buf->str().back()); // The previous segments are marked as not-last ones. for (int i = 1; i < seg_count - 1; i++) { EXPECT_EQ(DummyStreamSegmentEncrypter::kNotLastSegment, refs.ct_buf->str()[(ct_segment_size * i)-1]); } // Try closing the stream again. close_status = enc_stream->Close(); EXPECT_FALSE(close_status.ok()); EXPECT_EQ(absl::StatusCode::kFailedPrecondition, close_status.code()); } TEST_F(StreamingAeadEncryptingStreamTest, ManySegmentsPlaintextWithFullBackup) { int pt_segment_size = 512; int header_size = 64; void* buffer; // Get an encrypting stream. ValidationRefs refs; auto enc_stream = GetEncryptingStream( pt_segment_size, header_size, /* ct_offset = */ 0, &refs); int seg_count = 5; // Get the first segment. auto next_result = enc_stream->Next(&buffer); int first_buffer_size = pt_segment_size - header_size; EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(first_buffer_size, next_result.value()); EXPECT_EQ(first_buffer_size, enc_stream->Position()); // Get remaining segments. for (int i = 1; i < seg_count; i++) { next_result = enc_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(pt_segment_size, next_result.value()); EXPECT_EQ(first_buffer_size + i * pt_segment_size, enc_stream->Position()); } // Backup the entire last segment, and close the stream. enc_stream->BackUp(pt_segment_size); EXPECT_EQ(first_buffer_size + (seg_count - 2) * pt_segment_size, enc_stream->Position()); auto close_status = enc_stream->Close(); EXPECT_TRUE(close_status.ok()) << close_status; EXPECT_EQ(refs.seg_enc->get_generated_output_size(), refs.ct_buf->str().size()); // Ciphertext contains (seg_count - 1) full segments. int ct_segment_size = pt_segment_size + DummyStreamSegmentEncrypter::kSegmentTagSize; EXPECT_EQ(refs.seg_enc->get_ciphertext_segment_size(), ct_segment_size); EXPECT_EQ(ct_segment_size * (seg_count - 1), refs.ct_buf->str().size()); // The last segment is marked as such. EXPECT_EQ(DummyStreamSegmentEncrypter::kLastSegment, refs.ct_buf->str().back()); // The previous segments are marked as not-last ones. for (int i = 1; i < seg_count - 1; i++) { EXPECT_EQ(DummyStreamSegmentEncrypter::kNotLastSegment, refs.ct_buf->str()[(ct_segment_size * i)-1]); } // Try closing the stream again. close_status = enc_stream->Close(); EXPECT_FALSE(close_status.ok()); EXPECT_EQ(absl::StatusCode::kFailedPrecondition, close_status.code()); } TEST_F(StreamingAeadEncryptingStreamTest, BackupAndPosition) { int pt_segment_size = 512; int header_size = 64; void* buffer; // Get an encrypting stream. ValidationRefs refs; auto enc_stream = GetEncryptingStream( pt_segment_size, header_size, /* ct_offset = */ 0, &refs); // The first buffer. auto next_result = enc_stream->Next(&buffer); int buffer_size = pt_segment_size - header_size; EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(buffer_size, enc_stream->Position()); // BackUp several times, but in total fewer bytes than returned by Next(). std::vector backup_sizes = {0, 1, 5, 0, 10, 78, -42, 60, 120, -120}; int total_backup_size = 0; for (auto backup_size : backup_sizes) { enc_stream->BackUp(backup_size); total_backup_size += std::max(0, backup_size); EXPECT_EQ(buffer_size - total_backup_size, enc_stream->Position()); } EXPECT_LT(total_backup_size, next_result.value()); // Call Next(), it should succeed (backuped bytes of 1st segment). next_result = enc_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(total_backup_size, next_result.value()); EXPECT_EQ(buffer_size, enc_stream->Position()); // BackUp() some bytes, again fewer than returned by Next(). backup_sizes = {0, 72, -94, 37, 82}; total_backup_size = 0; for (auto backup_size : backup_sizes) { enc_stream->BackUp(backup_size); total_backup_size += std::max(0, backup_size); EXPECT_EQ(buffer_size - total_backup_size, enc_stream->Position()); } EXPECT_LT(total_backup_size, next_result.value()); // Call Next(), it should succeed (backuped bytes of 1st segment). next_result = enc_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(total_backup_size, next_result.value()); EXPECT_EQ(buffer_size, enc_stream->Position()); // Call Next() again, it should return a full segment (2nd segment). auto prev_position = enc_stream->Position(); buffer_size = pt_segment_size; next_result = enc_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(prev_position + buffer_size, enc_stream->Position()); // BackUp a few times, with total over the returned buffer_size. backup_sizes = {0, 72, -100, buffer_size / 2, 200, -25, buffer_size / 2, 42}; total_backup_size = 0; for (auto backup_size : backup_sizes) { SCOPED_TRACE(absl::StrCat("backup_size = ", backup_size, ", total_backup_size = ", total_backup_size)); enc_stream->BackUp(backup_size); total_backup_size = std::min(buffer_size, total_backup_size + std::max(0, backup_size)); EXPECT_EQ(prev_position + buffer_size - total_backup_size, enc_stream->Position()); } EXPECT_EQ(total_backup_size, buffer_size); EXPECT_EQ(prev_position, enc_stream->Position()); // Call Next() again, it should return a full segment (2nd segment); next_result = enc_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(prev_position + buffer_size, enc_stream->Position()); EXPECT_EQ(2 * pt_segment_size - header_size, enc_stream->Position()); // Backup the entire segment, and close the stream. enc_stream->BackUp(buffer_size); EXPECT_EQ(pt_segment_size - header_size, enc_stream->Position()); auto close_status = enc_stream->Close(); EXPECT_TRUE(close_status.ok()) << close_status; EXPECT_EQ(refs.seg_enc->get_generated_output_size(), refs.ct_buf->str().size()); // Ciphertext contains 1st segment (with header), and no traces // of the "empty" (backed-up) segment. EXPECT_EQ((pt_segment_size + DummyStreamSegmentEncrypter::kSegmentTagSize), refs.ct_buf->str().size()); // Try closing the stream again. close_status = enc_stream->Close(); EXPECT_FALSE(close_status.ok()); EXPECT_EQ(absl::StatusCode::kFailedPrecondition, close_status.code()); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/streaming_aead_test_util.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/streaming_aead_test_util.h" #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/input_stream.h" #include "tink/internal/test_random_access_stream.h" #include "tink/random_access_stream.h" #include "tink/streaming_aead.h" #include "tink/subtle/test_util.h" #include "tink/util/buffer.h" #include "tink/util/istream_input_stream.h" #include "tink/util/ostream_output_stream.h" #include "tink/util/status.h" namespace crypto { namespace tink { using ::crypto::tink::internal::TestRandomAccessStream; using ::crypto::tink::util::IstreamInputStream; using ::crypto::tink::util::OstreamOutputStream; using ::crypto::tink::util::Status; namespace { // Reads up to 'count' bytes from 'ras' starting at position 'pos' // and verifies that the read bytes are equal to the corresponding // subsequence in 'full_contents'. Status ReadAndVerifyFragment(RandomAccessStream* ras, int pos, int count, absl::string_view full_contents) { auto buf_result = util::Buffer::New(count); if (!buf_result.ok()) { return Status(absl::StatusCode::kInternal, absl::StrCat("Could not allocate buffer of size ", count)); } auto buf = std::move(buf_result.value()); int full_size = full_contents.size(); auto status = ras->PRead(pos, count, buf.get()); if (!status.ok() && status.code() != absl::StatusCode::kOutOfRange) { return Status( absl::StatusCode::kInternal, absl::StrCat("PRead failed with status: ", status.ToString())); } int exp_size = std::min(count, full_size - pos); if (exp_size != buf->size()) { return Status(absl::StatusCode::kInternal, absl::StrCat("PRead returned ", buf->size(), " bytes, while ", exp_size, " bytes were expected.")); } if (std::memcmp(full_contents.data() + pos, buf->get_mem_block(), exp_size)) { return Status( absl::StatusCode::kInternal, absl::StrCat("PRead returned bytes [", std::string(buf->get_mem_block(), exp_size), "] while [", full_contents.substr(pos, exp_size), "] were expected.")); } return util::OkStatus(); } } // namespace crypto::tink::util::Status EncryptThenDecrypt(StreamingAead* encrypter, StreamingAead* decrypter, absl::string_view plaintext, absl::string_view associated_data, int ciphertext_offset) { // Prepare ciphertext destination stream. auto ct_stream = absl::make_unique(); // A reference to the ciphertext buffer, for later validation. auto ct_buf = ct_stream->rdbuf(); auto ct_destination = absl::make_unique(std::move(ct_stream)); auto status = subtle::test::WriteToStream( ct_destination.get(), std::string(ciphertext_offset, 'o'), false); if (!status.ok()) return status; // Use encrypter to encrypt some data. auto enc_stream_result = encrypter->NewEncryptingStream( std::move(ct_destination), associated_data); if (!enc_stream_result.ok()) return enc_stream_result.status(); auto enc_stream = std::move(enc_stream_result.value()); status = subtle::test::WriteToStream(enc_stream.get(), plaintext); if (!status.ok()) return status; if (plaintext.size() != enc_stream->Position()) { return ::crypto::tink::util::Status( absl::StatusCode::kInternal, "Plaintext size different from stream position."); } // Prepare an InputStream with the ciphertext. auto ct_bytes = absl::make_unique( ct_buf->str().substr(ciphertext_offset)); std::unique_ptr ct_source( absl::make_unique(std::move(ct_bytes))); // Decrypt the ciphertext using the decrypter. auto dec_stream_result = decrypter->NewDecryptingStream( std::move(ct_source), associated_data); if (!dec_stream_result.ok()) return dec_stream_result.status(); auto dec_stream = std::move(dec_stream_result.value()); std::string decrypted; status = subtle::test::ReadFromStream(dec_stream.get(), &decrypted); if (!status.ok()) { return status; } if (plaintext != decrypted) { return ::crypto::tink::util::Status(absl::StatusCode::kInternal, "Decryption differs from plaintext."); } // Prepare a RandomAccessStream with the ciphertext. auto ct_ras = std::make_unique(std::string(ct_buf->str())); // Decrypt fragments of the ciphertext using the decrypter. auto dec_ras_result = decrypter->NewDecryptingRandomAccessStream( std::move(ct_ras), associated_data); if (!dec_ras_result.ok()) return dec_ras_result.status(); auto dec_ras = std::move(dec_ras_result.value()); int pt_size = plaintext.size(); for (int pos : {0, pt_size / 2, std::max(pt_size - 10, 0)}) { for (int count : {1, 10, std::max(pt_size / 2, 1), std::max(pt_size, 1)}) { auto status = ReadAndVerifyFragment(dec_ras.get(), pos, count, plaintext); if (!status.ok()) { return Status( absl::StatusCode::kInternal, absl::StrCat("Random access decryption failed at position=", pos, " with count=", count, " and status: ", status.ToString())); } } } return crypto::tink::util::OkStatus(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/streaming_aead_test_util.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_STREAMING_AEAD_TEST_UTIL_H_ #define TINK_SUBTLE_STREAMING_AEAD_TEST_UTIL_H_ #include "absl/strings/string_view.h" #include "tink/streaming_aead.h" #include "tink/util/status.h" namespace crypto { namespace tink { // Encrypt with NewEncryptingStream, then decrypt using NewDecryptingStream, // and NewDecryptingRandomAccessStream (for a few fragments). // 'ciphertext_offset' is the offset of the actual ciphertext in the // computed ciphertext stream (cf. description of StreamSegmentEncrypter // in stream_segment_encrypter.h). // Any error will be propagated to the caller. Returns OK if the resulting // decryptions are equal to the plaintext. crypto::tink::util::Status EncryptThenDecrypt(StreamingAead* encrypter, StreamingAead* decrypter, absl::string_view plaintext, absl::string_view associated_data, int ciphertext_offset); } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_STREAMING_AEAD_TEST_UTIL_H_ ================================================ FILE: cc/subtle/streaming_aead_test_util_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/streaming_aead_test_util.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { using ::crypto::tink::test::DummyStreamingAead; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; namespace { TEST(EncryptThenDecrypt, Basic) { DummyStreamingAead streaming_aead("Aead 1"); int ciphertext_offset = 0; EXPECT_THAT(EncryptThenDecrypt(&streaming_aead, &streaming_aead, "plaintext", "aad", ciphertext_offset), IsOk()); } TEST(EncryptThenDecrypt, DifferentAeads) { DummyStreamingAead streaming_aead_1("Aead 1"); DummyStreamingAead streaming_aead_2("Aead 2"); int ciphertext_offset = 0; EXPECT_THAT(EncryptThenDecrypt(&streaming_aead_1, &streaming_aead_2, "plaintext", "aad", ciphertext_offset), StatusIs(absl::StatusCode::kInvalidArgument)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/streaming_mac_impl.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/streaming_mac_impl.h" #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "openssl/crypto.h" #include "tink/output_stream_with_result.h" #include "tink/subtle/mac/stateful_mac.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { namespace { constexpr size_t kBufferSize = 4096; } class ComputeMacOutputStream : public OutputStreamWithResult { public: explicit ComputeMacOutputStream(std::unique_ptr mac) : status_(util::OkStatus()), mac_(std::move(mac)), position_(0), buffer_position_(0), buffer_("") { buffer_.resize(kBufferSize); } util::StatusOr NextBuffer(void** buffer) override; util::StatusOr CloseStreamAndComputeResult() override; void BackUp(int count) override; int64_t Position() const override { return position_; } private: void WriteIntoMac(); util::Status status_; const std::unique_ptr mac_; int64_t position_; int buffer_position_; std::string buffer_; }; util::StatusOr>> StreamingMacImpl::NewComputeMacOutputStream() const { util::StatusOr> mac_status = mac_factory_->Create(); if (!mac_status.ok()) { return mac_status.status(); } std::unique_ptr> string_to_return = absl::make_unique(std::move(mac_status.value())); return std::move(string_to_return); } util::StatusOr ComputeMacOutputStream::NextBuffer(void** buffer) { if (!status_.ok()) { return status_; } WriteIntoMac(); *buffer = &buffer_[0]; position_ += kBufferSize; buffer_position_ = kBufferSize; return buffer_position_; } util::StatusOr ComputeMacOutputStream::CloseStreamAndComputeResult() { if (!status_.ok()) { return status_; } WriteIntoMac(); status_ = util::Status(absl::StatusCode::kFailedPrecondition, "Stream Closed"); return mac_->Finalize(); } void ComputeMacOutputStream::BackUp(int count) { count = std::min(count, buffer_position_); buffer_position_ -= count; position_ -= count; } // Writes the data in buffer_ into mac_, and clears buffer_. void ComputeMacOutputStream::WriteIntoMac() { // Remove the suffix of the buffer (all data after buffer_position_). status_ = mac_->Update(absl::string_view(buffer_.data(), buffer_position_)); // Clear the buffer, so that any sensitive information that // was written to the buffer cannot be accessed later. // Write buffer_position_ number of 0's to the buffer, starting from idx 0. buffer_.replace(0, buffer_position_, buffer_position_, 0); } class VerifyMacOutputStream : public OutputStreamWithResult { public: VerifyMacOutputStream(const std::string& expected, std::unique_ptr mac) : status_(util::OkStatus()), mac_(std::move(mac)), position_(0), buffer_position_(0), buffer_(""), expected_(expected) { buffer_.resize(kBufferSize); } util::StatusOr NextBuffer(void** buffer) override; util::Status CloseStreamAndComputeResult() override; void BackUp(int count) override; int64_t Position() const override { return position_; } private: void WriteIntoMac(); // Stream status: Initialized as OK, and // changed to ERROR:FAILED_PRECONDITION when the stream is closed. util::Status status_; std::unique_ptr mac_; int64_t position_; int buffer_position_; std::string buffer_; std::string expected_; }; util::StatusOr VerifyMacOutputStream::NextBuffer(void** buffer) { if (!status_.ok()) { return status_; } WriteIntoMac(); *buffer = &buffer_[0]; position_ += kBufferSize; buffer_position_ = kBufferSize; return buffer_position_; } util::Status VerifyMacOutputStream::CloseStreamAndComputeResult() { if (!status_.ok()) { return status_; } WriteIntoMac(); status_ = util::Status(absl::StatusCode::kFailedPrecondition, "Stream Closed"); util::StatusOr mac_actual = mac_->Finalize(); if (!mac_actual.ok()) { return mac_actual.status(); } if (mac_actual->size() != expected_.size()) { return absl::InvalidArgumentError( absl::StrCat("Invalid MAC size; expected ", expected_.size(), ", got ", mac_actual->size())); } if (!CRYPTO_memcmp(mac_actual->data(), expected_.data(), mac_actual->size())) { return util::OkStatus(); } return absl::InvalidArgumentError("Incorrect MAC"); } void VerifyMacOutputStream::BackUp(int count) { count = std::min(count, buffer_position_); buffer_position_ -= count; position_ -= count; } // Writes the data in buffer_ into mac_, and clears buffer_. void VerifyMacOutputStream::WriteIntoMac() { // Remove the suffix of the buffer (all data after buffer_position_). status_ = mac_->Update(absl::string_view(buffer_.data(), buffer_position_)); // Clear the buffer, so that any sensitive information that // was written to the buffer cannot be accessed later. // Write buffer_position_ number of 0's to the buffer, starting from idx 0. buffer_.replace(0, buffer_position_, buffer_position_, 0); } util::StatusOr>> StreamingMacImpl::NewVerifyMacOutputStream(const std::string& mac_value) const { util::StatusOr> mac_status = mac_factory_->Create(); if (!mac_status.ok()) { return mac_status.status(); } return std::unique_ptr>( absl::make_unique(mac_value, std::move(mac_status.value()))); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/streaming_mac_impl.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_STREAMING_MAC_IMPL_H_ #define TINK_SUBTLE_STREAMING_MAC_IMPL_H_ #include #include #include #include "tink/output_stream_with_result.h" #include "tink/streaming_mac.h" #include "tink/subtle/mac/stateful_mac.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { class StreamingMacImpl : public StreamingMac { public: // Constructor explicit StreamingMacImpl(std::unique_ptr mac_factory) : mac_factory_(std::move(mac_factory)) {} // Implement streaming mac class functions // Returns an ComputeMacOutputStream, which when closed will return the // message authentication code (MAC) of the data put into the stream. util::StatusOr>> NewComputeMacOutputStream() const override; // Returns an VerifyMacOutputStream which verifies if 'mac' is a correct // message authentication code (MAC) for the data written to it. util::StatusOr>> NewVerifyMacOutputStream(const std::string& mac_value) const override; private: std::unique_ptr mac_factory_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_STREAMING_MAC_IMPL_H_ ================================================ FILE: cc/subtle/streaming_mac_impl_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/streaming_mac_impl.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/output_stream_with_result.h" #include "tink/subtle/mac/stateful_mac.h" #include "tink/subtle/random.h" #include "tink/subtle/test_util.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace subtle { namespace { using ::crypto::tink::test::DummyStatefulMac; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::HasSubstr; class DummyStatefulMacFactory : public StatefulMacFactory { public: DummyStatefulMacFactory() = default; ~DummyStatefulMacFactory() override = default; // Constructs a StatefulMac using the DummyStatefulMac, which creates // returns a MAC of the header concatenated with the plaintext. util::StatusOr> Create() const override { return std::unique_ptr( absl::make_unique("streaming mac:")); } }; // A helper for creating an OutputStreamWithResult, // used for test validation for mac computation. std::unique_ptr> GetComputeMacOutputStream() { auto mac_factory = std::unique_ptr( absl::make_unique()); auto streaming_mac = absl::make_unique(std::move(mac_factory)); util::StatusOr>> stream_status = streaming_mac->NewComputeMacOutputStream(); EXPECT_THAT(stream_status, IsOk()); return std::move(*stream_status); } // A helper for creating an OutputStreamWithResult, // used for test validation for mac verification. std::unique_ptr> GetVerifyMacOutputStream( std::string expected_mac) { auto mac_factory = std::unique_ptr( absl::make_unique()); auto streaming_mac = absl::make_unique(std::move(mac_factory)); util::StatusOr>> stream_status = streaming_mac->NewVerifyMacOutputStream(expected_mac); EXPECT_THAT(stream_status, IsOk()); return std::move(*stream_status); } TEST(StreamingMacImplTest, ComputeEmptyMac) { std::string expected_mac = "23:0:DummyMac:streaming mac:"; auto output_stream = GetComputeMacOutputStream(); // Close stream and check result auto close_status = output_stream->CloseAndGetResult(); EXPECT_THAT(close_status, IsOk()); EXPECT_EQ(*close_status, expected_mac); } TEST(StreamingMacImplTest, ComputeSmallMac) { std::string text = "I am a small message"; std::string expected_mac = "23:20:DummyMac:streaming mac:I am a small message"; auto output_stream = GetComputeMacOutputStream(); // Write to the ComputeMacOutputStream auto status = test::WriteToStream(output_stream.get(), text, false); EXPECT_THAT(status, IsOk()); EXPECT_EQ(output_stream->Position(), text.size()); // Close stream and check result auto close_status = output_stream->CloseAndGetResult(); EXPECT_THAT(close_status, IsOk()); EXPECT_EQ(*close_status, expected_mac); } TEST(StreamingMacImplTest, ComputeRandMac) { std::vector text_sizes = {0, 10, 100, 1000, 10000, 1000000}; for (auto text_size : text_sizes) { std::string text = Random::GetRandomBytes(text_size); std::string expected_mac = "23:" + std::to_string(text_size) + ":DummyMac:streaming mac:" + text; auto output_stream = GetComputeMacOutputStream(); // Write to the ComputeMacOutputStream auto status = test::WriteToStream(output_stream.get(), text, false); EXPECT_THAT(status, IsOk()); EXPECT_EQ(output_stream->Position(), text.size()); // Close stream and check result auto close_status = output_stream->CloseAndGetResult(); EXPECT_THAT(close_status, IsOk()); EXPECT_EQ(*close_status, expected_mac); } } TEST(StreamingMacImplTest, ComputeCheckStreamPosition) { std::string text = "I am a small message"; auto output_stream = GetComputeMacOutputStream(); // Check position in first buffer returned by Next(); void* buffer; util::StatusOr next_result = output_stream->Next(&buffer); EXPECT_THAT(next_result, IsOk()); int buffer_size = *next_result; EXPECT_EQ(buffer_size, output_stream->Position()); // Check position after calling BackUp output_stream->BackUp(10); EXPECT_EQ(buffer_size - 10, output_stream->Position()); } TEST(StreamingMacImplTest, ComputeCloseTwiceError) { auto output_stream = GetComputeMacOutputStream(); // Close stream auto close_status = output_stream->CloseAndGetResult(); // Try closing the stream again. auto reclose_status = output_stream->Close(); EXPECT_FALSE(reclose_status.ok()); EXPECT_EQ(absl::StatusCode::kFailedPrecondition, reclose_status.code()); } TEST(StreamingMacImplTest, VerifyEmptyMac) { std::string expected_mac = "23:0:DummyMac:streaming mac:"; auto output_stream = GetVerifyMacOutputStream(expected_mac); // Close stream and check result auto close_status = output_stream->CloseAndGetResult(); EXPECT_THAT(close_status, IsOk()); } TEST(StreamingMacImplTest, VerifySmallMac) { std::string text = "I am a small message"; std::string expected_mac = "23:20:DummyMac:streaming mac:I am a small message"; auto output_stream = GetVerifyMacOutputStream(expected_mac); // Write to the VerifyMacOutputStream auto status = test::WriteToStream(output_stream.get(), text, false); EXPECT_THAT(status, IsOk()); EXPECT_EQ(output_stream->Position(), text.size()); // Close stream and check result auto close_status = output_stream->CloseAndGetResult(); EXPECT_THAT(close_status, IsOk()); } TEST(StreamingMacImplTest, VerifyEmptyMacFail) { std::string expected_mac = "23:1:DummyMac:streaming mac:"; auto output_stream = GetVerifyMacOutputStream(expected_mac); // Close stream and check result EXPECT_THAT( output_stream->CloseAndGetResult(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Incorrect MAC"))); } TEST(StreamingMacImplTest, VerifySmallMacFail) { std::string text = "I am a small message"; std::string expected_mac = "23:20:DummyMac:streaming mac:I am wrong message"; auto output_stream = GetVerifyMacOutputStream(expected_mac); // Write to the VerifyMacOutputStream auto status = test::WriteToStream(output_stream.get(), text, false); EXPECT_THAT(status, IsOk()); EXPECT_EQ(output_stream->Position(), text.size()); // Close stream and check result EXPECT_THAT( output_stream->CloseAndGetResult(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Invalid MAC"))); } TEST(StreamingMacImplTest, VerifyRandMac) { std::vector text_sizes = {0, 10, 100, 1000, 10000, 1000000}; for (auto text_size : text_sizes) { std::string text = Random::GetRandomBytes(text_size); std::string expected_mac = "23:" + std::to_string(text_size) + ":DummyMac:streaming mac:" + text; auto output_stream = GetVerifyMacOutputStream(expected_mac); // Write to the VerifyMacOutputStream auto status = test::WriteToStream(output_stream.get(), text, false); EXPECT_THAT(status, IsOk()); EXPECT_EQ(output_stream->Position(), text.size()); // Close stream and check result auto close_status = output_stream->CloseAndGetResult(); EXPECT_THAT(close_status, IsOk()); } } TEST(StreamingMacImplTest, VerifyCheckStreamPosition) { std::string text = "I am a small message"; std::string expected_mac = "23:1:DummyMac:streaming mac:"; auto output_stream = GetVerifyMacOutputStream(expected_mac); // Check position in first buffer returned by Next(); void* buffer; util::StatusOr next_result = output_stream->Next(&buffer); EXPECT_THAT(next_result, IsOk()); int buffer_size = *next_result; EXPECT_EQ(buffer_size, output_stream->Position()); // Check position after calling BackUp output_stream->BackUp(10); EXPECT_EQ(buffer_size - 10, output_stream->Position()); } TEST(StreamingMacImplTest, VerifyCloseTwiceError) { std::string expected_mac = "23:0:DummyMac:streaming mac:"; auto output_stream = GetVerifyMacOutputStream(expected_mac); // Close stream auto close_status = output_stream->CloseAndGetResult(); // Try closing the stream again. auto reclose_status = output_stream->Close(); EXPECT_FALSE(reclose_status.ok()); EXPECT_EQ(absl::StatusCode::kFailedPrecondition, reclose_status.code()); } } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/subtle_util.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/subtle_util.h" #include #include #include // placeholder_subtle_util_cc namespace crypto { namespace tink { namespace subtle { std::string BigEndian32(uint32_t val) { std::string result(4, '\0'); result[0] = (val >> 24) & 0xff; result[1] = (val >> 16) & 0xff; result[2] = (val >> 8) & 0xff; result[3] = val & 0xff; return result; } void ResizeStringUninitialized(std::string* s, size_t new_size) { s->resize(new_size); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/subtle_util.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_SUBTLE_UTIL_H_ #define TINK_SUBTLE_SUBTLE_UTIL_H_ #include #include #include namespace crypto { namespace tink { namespace subtle { // Returnes big endian order representation of `val`. std::string BigEndian32(uint32_t val); // Like string::resize, but the newly allocated storage may be left // uninitialized. C++11 provides no portable way to do this. Using this function // allows us to do this on a per compiler/library version basis. void ResizeStringUninitialized(std::string* s, size_t new_size); } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_SUBTLE_UTIL_H_ ================================================ FILE: cc/subtle/subtle_util_boringssl.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_SUBTLE_UTIL_BORINGSSL_H_ #define TINK_SUBTLE_SUBTLE_UTIL_BORINGSSL_H_ #include #include #include #include #include #include #include "absl/base/attributes.h" #include "absl/base/macros.h" #include "absl/strings/string_view.h" #include "openssl/bn.h" #include "openssl/evp.h" #include "tink/aead/internal/aead_util.h" #include "tink/internal/aes_util.h" #include "tink/internal/bn_util.h" #include "tink/internal/ec_util.h" #include "tink/internal/err_util.h" #include "tink/internal/md_util.h" #include "tink/internal/rsa_util.h" #include "tink/internal/ssl_unique_ptr.h" #include "tink/internal/util.h" #include "tink/subtle/common_enums.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { class SubtleUtilBoringSSL { public: using EcKey ABSL_DEPRECATED("Use of this type is dicouraged outside Tink.") = internal::EcKey; using X25519Key ABSL_DEPRECATED( "Use of this type is dicouraged outside Tink.") = internal::X25519Key; using Ed25519Key ABSL_DEPRECATED( "Use of this type is dicouraged outside Tink.") = internal::Ed25519Key; using RsaPublicKey ABSL_DEPRECATED( "Use of this type is dicouraged outside Tink.") = internal::RsaPublicKey; using RsaSsaPssParams ABSL_DEPRECATED( "Use of this type is dicouraged outside Tink.") = internal::RsaSsaPssParams; using RsaSsaPkcs1Params ABSL_DEPRECATED( "Use of this type is dicouraged outside Tink.") = internal::RsaSsaPkcs1Params; using RsaPrivateKey ABSL_DEPRECATED( "Use of this type is dicouraged outside Tink.") = internal::RsaPrivateKey; // Returns BoringSSL's BIGNUM constructed from bigendian string // representation. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline util::StatusOr> str2bn( absl::string_view s) { return internal::StringToBignum(s); } // Returns a SecretData of size 'len' that holds BIGNUM 'bn'. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline util::StatusOr bn2str(const BIGNUM *bn, size_t len) { return internal::BignumToString(bn, len); } // Returns a string of size 'len' that holds BIGNUM 'bn'. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline util::StatusOr BignumToSecretData( const BIGNUM *bn, size_t len) { return internal::BignumToSecretData(bn, len); } // Returns BoringSSL error strings accumulated in the error queue, // thus emptying the queue. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline std::string GetErrors() { return internal::GetSslErrors(); } // Returns BoringSSL's EC_GROUP constructed from the curve type. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline crypto::tink::util::StatusOr GetEcGroup( EllipticCurveType curve_type) { util::StatusOr> ec_group = internal::EcGroupFromCurveType(curve_type); if (!ec_group.ok()) { return ec_group.status(); } return ec_group->release(); } // Returns the curve type associated with the EC_GROUP ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline crypto::tink::util::StatusOr GetCurve( const EC_GROUP *group) { return internal::CurveTypeFromEcGroup(group); } // Returns BoringSSL's EC_POINT constructed from the curve type, big-endian // representation of public key's x-coordinate and y-coordinate. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline crypto::tink::util::StatusOr GetEcPoint( EllipticCurveType curve, absl::string_view pubx, absl::string_view puby) { util::StatusOr> ec_point = internal::GetEcPoint(curve, pubx, puby); if (!ec_point.ok()) { return ec_point.status(); } return ec_point->release(); } // Returns a new EC key for the specified curve. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline crypto::tink::util::StatusOr GetNewEcKey( EllipticCurveType curve_type) { return internal::NewEcKey(curve_type); } // Returns a new EC key for the specified curve derived from a seed. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline crypto::tink::util::StatusOr GetNewEcKeyFromSeed( EllipticCurveType curve_type, const util::SecretData &secret_seed) { return internal::NewEcKey(curve_type, secret_seed); } // Returns a new X25519 key, or nullptr if generation fails. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline std::unique_ptr GenerateNewX25519Key() { util::StatusOr> key = internal::NewX25519Key(); if (!key.ok()) { return nullptr; } return *std::move(key); } // Returns a X25519Key matching the specified EcKey. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline crypto::tink::util::StatusOr> X25519KeyFromEcKey(const EcKey &ec_key) { return internal::X25519KeyFromEcKey(ec_key); } // Returns an EcKey matching the specified X25519Key. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline EcKey EcKeyFromX25519Key(const X25519Key *x25519_key) { return internal::EcKeyFromX25519Key(x25519_key); } // Returns a new ED25519 key. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline std::unique_ptr GetNewEd25519Key() { util::StatusOr> key = internal::NewEd25519Key(); if (!key.ok()) { return nullptr; } return *std::move(key); } // Returns a new ED25519 key generated from a 32-byte secret seed. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline std::unique_ptr GetNewEd25519KeyFromSeed( const util::SecretData &secret_seed) { util::StatusOr> key = internal::NewEd25519Key(secret_seed); if (!key.ok()) { return nullptr; } return *std::move(key); } // Returns BoringSSL's EC_POINT constructed from curve type, point format and // encoded public key's point. The uncompressed point is encoded as // 0x04 || x || y where x, y are curve_size_in_bytes big-endian byte array. // The compressed point is encoded as 1-byte || x where x is // curve_size_in_bytes big-endian byte array and if the least significant bit // of y is 1, the 1st byte is 0x03, otherwise it's 0x02. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline crypto::tink::util::StatusOr> EcPointDecode(EllipticCurveType curve, EcPointFormat format, absl::string_view encoded) { return internal::EcPointDecode(curve, format, encoded); } // Returns the encoded public key based on curve type, point format and // BoringSSL's EC_POINT public key point. The uncompressed point is encoded as // 0x04 || x || y where x, y are curve_size_in_bytes big-endian byte array. // The compressed point is encoded as 1-byte || x where x is // curve_size_in_bytes big-endian byte array and if the least significant bit // of y is 1, the 1st byte is 0x03, otherwise it's 0x02. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline crypto::tink::util::StatusOr EcPointEncode( EllipticCurveType curve, EcPointFormat format, const EC_POINT *point) { return internal::EcPointEncode(curve, format, point); } // Returns the ECDH's shared secret based on our private key and peer's public // key. Returns error if the public key is not on private key's curve. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline crypto::tink::util::StatusOr ComputeEcdhSharedSecret(EllipticCurveType curve, const BIGNUM *priv_key, const EC_POINT *pub_key) { return internal::ComputeEcdhSharedSecret(curve, priv_key, pub_key); } // Transforms ECDSA IEEE_P1363 signature encoding to DER encoding. // // The IEEE_P1363 signature's format is r || s, where r and s are zero-padded // and have the same size in bytes as the order of the curve. For example, for // NIST P-256 curve, r and s are zero-padded to 32 bytes. // // The DER signature is encoded using ASN.1 // (https://tools.ietf.org/html/rfc5480#appendix-A): // ECDSA-Sig-Value :: = SEQUENCE { r INTEGER, s INTEGER }. // In particular, the encoding is: // 0x30 || totalLength || 0x02 || r's length || r || 0x02 || s's length || s ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline crypto::tink::util::StatusOr EcSignatureIeeeToDer( const EC_GROUP *group, absl::string_view ieee_sig) { return internal::EcSignatureIeeeToDer(group, ieee_sig); } // Returns an EVP structure for a hash function. // The EVP_MD instances are sigletons owned by BoringSSL. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline crypto::tink::util::StatusOr EvpHash( HashType hash_type) { return internal::EvpHashFromHashType(hash_type); } // Validates whether 'sig_hash' is safe to use for digital signature. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline crypto::tink::util::Status ValidateSignatureHash( subtle::HashType sig_hash) { return internal::IsHashTypeSafeForSignature(sig_hash); } // Return an empty string if str.data() is nullptr; otherwise return str. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline absl::string_view EnsureNonNull(absl::string_view str) { return internal::EnsureStringNonNull(str); } ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline crypto::tink::util::Status ValidateRsaModulusSize( size_t modulus_size) { return internal::ValidateRsaModulusSize(modulus_size); } ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline crypto::tink::util::Status ValidateRsaPublicExponent( absl::string_view exponent) { return internal::ValidateRsaPublicExponent(exponent); } ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline util::Status GetNewRsaKeyPair(int modulus_size_in_bits, const BIGNUM *e, RsaPrivateKey *private_key, RsaPublicKey *public_key) { return internal::NewRsaKeyPair(modulus_size_in_bits, e, private_key, public_key); } // Copies n, e and d into the RSA key. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline util::Status CopyKey(const RsaPrivateKey &key, RSA *rsa) { return internal::GetRsaModAndExponents(key, rsa); } // Copies the prime factors (p, q) into the RSA key. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline util::Status CopyPrimeFactors(const RsaPrivateKey &key, RSA *rsa) { return internal::GetRsaPrimeFactors(key, rsa); } // Copies the CRT params and dp, dq into the RSA key. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline util::Status CopyCrtParams(const RsaPrivateKey &key, RSA *rsa) { return internal::GetRsaCrtParams(key, rsa); } // Creates a BoringSSL RSA key from an RsaPrivateKey. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline util::StatusOr> BoringSslRsaFromRsaPrivateKey(const RsaPrivateKey &key) { return internal::RsaPrivateKeyToRsa(key); } // Creates a BoringSSL RSA key from an RsaPublicKey. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline util::StatusOr> BoringSslRsaFromRsaPublicKey(const RsaPublicKey &key) { return internal::RsaPublicKeyToRsa(key); } // Returns BoringSSL's AES CTR EVP_CIPHER for the key size. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline const EVP_CIPHER *GetAesCtrCipherForKeySize( uint32_t size_in_bytes) { util::StatusOr res = internal::GetAesCtrCipherForKeySize(size_in_bytes); if (!res.ok()) { return nullptr; } return *res; } // Returns BoringSSL's AES GCM EVP_CIPHER for the key size. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline const EVP_CIPHER *GetAesGcmCipherForKeySize( uint32_t size_in_bytes) { util::StatusOr res = internal::GetAesGcmCipherForKeySize(size_in_bytes); if (!res.ok()) { return nullptr; } return *res; } #ifdef OPENSSL_IS_BORINGSSL // Returns BoringSSL's AES GCM EVP_AEAD for the key size. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") static inline const EVP_AEAD *GetAesGcmAeadForKeySize( uint32_t size_in_bytes) { util::StatusOr res = internal::GetAesGcmAeadForKeySize(size_in_bytes); if (!res.ok()) { return nullptr; } return *res; } #endif }; namespace boringssl { // Computes hash of 'input' using the hash function 'hasher'. ABSL_DEPRECATED("Use of this function is dicouraged outside Tink.") inline util::StatusOr> ComputeHash(absl::string_view input, const EVP_MD &hasher) { util::StatusOr res = internal::ComputeHash(input, hasher); if (!res.ok()) { return res.status(); } return std::vector(res->begin(), res->end()); } } // namespace boringssl } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_SUBTLE_UTIL_BORINGSSL_H_ ================================================ FILE: cc/subtle/subtle_util_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/subtle_util.h" #include #include "gmock/gmock.h" #include "gtest/gtest.h" namespace crypto { namespace tink { namespace subtle { using ::testing::Eq; TEST(SubtleUtilTest, Basic) { std::string result = BigEndian32(0x12345678); EXPECT_EQ(result[0], 0x12); EXPECT_EQ(result[1], 0x34); EXPECT_EQ(result[2], 0x56); EXPECT_EQ(result[3], 0x78); } TEST(SubtleUtilTest, ResizeStringUninitialized) { std::string s; for (int len = 0; len <= 123; len += 17) { int old_len = s.size(); ResizeStringUninitialized(&s, len); for (int i = old_len; i < len; ++i) { s[i] = 'a'; } EXPECT_THAT(s, Eq(std::string(len, 'a'))); } for (int len = 100; len >= 0; len -= 20) { ResizeStringUninitialized(&s, len); EXPECT_THAT(s, Eq(std::string(len, 'a'))); } } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/test_util.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/test_util.h" #include #include #include #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "tink/input_stream.h" #include "tink/output_stream.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace subtle { namespace test { const int DummyStreamSegmentEncrypter::kSegmentTagSize; const char DummyStreamSegmentEncrypter::kLastSegment; const char DummyStreamSegmentEncrypter::kNotLastSegment; util::Status WriteToStream(OutputStream* output_stream, absl::string_view contents, bool close_stream) { void* buffer; int pos = 0; int remaining = contents.length(); int available_space = 0; int available_bytes = 0; while (remaining > 0) { auto next_result = output_stream->Next(&buffer); if (!next_result.ok()) return next_result.status(); available_space = next_result.value(); available_bytes = std::min(available_space, remaining); memcpy(buffer, contents.data() + pos, available_bytes); remaining -= available_bytes; pos += available_bytes; } if (available_space > available_bytes) { output_stream->BackUp(available_space - available_bytes); } return close_stream ? output_stream->Close() : util::OkStatus(); } util::Status ReadFromStream(InputStream* input_stream, std::string* output) { if (input_stream == nullptr || output == nullptr) { return util::Status(absl::StatusCode::kInternal, "Illegal read from a stream"); } const void* buffer; output->clear(); while (true) { auto next_result = input_stream->Next(&buffer); if (next_result.status().code() == absl::StatusCode::kOutOfRange) { // End of stream. return util::OkStatus(); } if (!next_result.ok()) return next_result.status(); auto read_bytes = next_result.value(); if (read_bytes > 0) { output->append( std::string(reinterpret_cast(buffer), read_bytes)); } } return util::OkStatus(); } } // namespace test } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/test_util.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_TEST_UTIL_H_ #define TINK_SUBTLE_TEST_UTIL_H_ #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/input_stream.h" #include "tink/output_stream.h" #include "tink/subtle/nonce_based_streaming_aead.h" #include "tink/subtle/stream_segment_decrypter.h" #include "tink/subtle/stream_segment_encrypter.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { namespace test { // Various utilities for testing. /////////////////////////////////////////////////////////////////////////////// // Writes 'contents' the specified 'output_stream', and if 'close_stream' // is true, then closes the stream. // Returns the status of output_stream->Close()-operation, or a non-OK status // of a prior output_stream->Next()-operation, if any. util::Status WriteToStream(OutputStream* output_stream, absl::string_view contents, bool close_stream = true); // Reads all bytes from the specified 'input_stream', and puts // them into 'output', where both 'input_stream' and 'output must be non-null. // Returns a non-OK status only if reading fails for some reason. // If the end of stream is reached ('input_stream' returns OUT_OF_RANGE), // then this function returns OK. util::Status ReadFromStream(InputStream* input_stream, std::string* output); // A dummy encrypter that "encrypts" by just appending to the plaintext // the current segment number and a marker byte indicating whether // the segment is last one. class DummyStreamSegmentEncrypter : public StreamSegmentEncrypter { public: // Size of the per-segment tag added upon encryption. static constexpr int kSegmentTagSize = sizeof(int64_t) + 1; // Bytes for marking whether a given segment is the last one. static constexpr char kLastSegment = 'l'; static constexpr char kNotLastSegment = 'n'; DummyStreamSegmentEncrypter(int pt_segment_size, int header_size, int ct_offset) : pt_segment_size_(pt_segment_size), ct_offset_(ct_offset), segment_number_(0) { // Fill the header with 'header_size' copies of letter 'h' header_.resize(0); header_.resize(header_size, static_cast('h')); generated_output_size_ = header_size; } // Generates an expected ciphertext for the given 'plaintext'. std::string GenerateCiphertext(absl::string_view plaintext) { std::string ct(header_.begin(), header_.end()); int64_t seg_no = 0; int pos = 0; do { int seg_len = pt_segment_size_; if (pos == 0) { // The first segment. seg_len -= (ct_offset_ + header_.size()); } if (seg_len > plaintext.size() - pos) { // The last segment. seg_len = plaintext.size() - pos; } ct.append(plaintext.substr(pos, seg_len).data(), seg_len); pos += seg_len; ct.append(reinterpret_cast(&seg_no), sizeof(seg_no)); ct.append(1, pos < plaintext.size() ? kNotLastSegment : kLastSegment); seg_no++; } while (pos < plaintext.size()); return ct; } util::Status EncryptSegment( const std::vector& plaintext, bool is_last_segment, std::vector* ciphertext_buffer) override { ciphertext_buffer->resize(plaintext.size() + kSegmentTagSize); memcpy(ciphertext_buffer->data(), plaintext.data(), plaintext.size()); memcpy(ciphertext_buffer->data() + plaintext.size(), &segment_number_, sizeof(segment_number_)); // The last byte of the a ciphertext segment. ciphertext_buffer->back() = is_last_segment ? kLastSegment : kNotLastSegment; generated_output_size_ += ciphertext_buffer->size(); IncSegmentNumber(); return util::OkStatus(); } const std::vector& get_header() const override { return header_; } int64_t get_segment_number() const override { return segment_number_; } int get_plaintext_segment_size() const override { return pt_segment_size_; } int get_ciphertext_segment_size() const override { return pt_segment_size_ + kSegmentTagSize; } int get_ciphertext_offset() const override { return ct_offset_; } ~DummyStreamSegmentEncrypter() override = default; int get_generated_output_size() { return generated_output_size_; } protected: void IncSegmentNumber() override { segment_number_++; } private: std::vector header_; int pt_segment_size_; int ct_offset_; int64_t segment_number_; int64_t generated_output_size_; }; // class DummyStreamSegmentEncrypter // A dummy decrypter that "decrypts" segments encrypted by // DummyStreamSegmentEncrypter. class DummyStreamSegmentDecrypter : public StreamSegmentDecrypter { public: DummyStreamSegmentDecrypter(int pt_segment_size, int header_size, int ct_offset) : pt_segment_size_(pt_segment_size), ct_offset_(ct_offset) { // Fill the header with 'header_size' copies of letter 'h' header_.resize(0); header_.resize(header_size, static_cast('h')); generated_output_size_ = 0; } util::Status Init(const std::vector& header) override { if (header_.size() != header.size() || memcmp(header_.data(), header.data(), header_.size()) != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid stream header"); } return util::OkStatus(); } int get_header_size() const override { return header_.size(); } util::Status DecryptSegment( const std::vector& ciphertext, int64_t segment_number, bool is_last_segment, std::vector* plaintext_buffer) override { if (ciphertext.size() < DummyStreamSegmentEncrypter::kSegmentTagSize) { return util::Status(absl::StatusCode::kInvalidArgument, "Ciphertext segment too short"); } if (ciphertext.back() != (is_last_segment ? DummyStreamSegmentEncrypter::kLastSegment : DummyStreamSegmentEncrypter::kNotLastSegment)) { return util::Status(absl::StatusCode::kInvalidArgument, "unexpected last-segment marker"); } int pt_size = ciphertext.size() - DummyStreamSegmentEncrypter::kSegmentTagSize; if (memcmp(ciphertext.data() + pt_size, reinterpret_cast(&segment_number), sizeof(segment_number)) != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "wrong segment number"); } plaintext_buffer->resize(pt_size); memcpy(plaintext_buffer->data(), ciphertext.data(), pt_size); generated_output_size_ += pt_size; return util::OkStatus(); } int get_plaintext_segment_size() const override { return pt_segment_size_; } int get_ciphertext_segment_size() const override { return pt_segment_size_ + DummyStreamSegmentEncrypter::kSegmentTagSize; } int get_ciphertext_offset() const override { return ct_offset_; } ~DummyStreamSegmentDecrypter() override = default; int get_generated_output_size() { return generated_output_size_; } private: std::vector header_; int pt_segment_size_; int ct_offset_; int64_t generated_output_size_; }; // class DummyStreamSegmentDecrypter class DummyStreamingAead : public NonceBasedStreamingAead { public: DummyStreamingAead(int pt_segment_size, int header_size, int ct_offset) : pt_segment_size_(pt_segment_size), header_size_(header_size), ct_offset_(ct_offset) {} protected: util::StatusOr> NewSegmentEncrypter( absl::string_view associated_data) const override { return {absl::make_unique( pt_segment_size_, header_size_, ct_offset_)}; } util::StatusOr> NewSegmentDecrypter( absl::string_view associated_data) const override { return {absl::make_unique( pt_segment_size_, header_size_, ct_offset_)}; } private: int pt_segment_size_; int header_size_; int ct_offset_; }; } // namespace test } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_TEST_UTIL_H_ ================================================ FILE: cc/subtle/wycheproof_util.cc ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/wycheproof_util.h" #include #include #include #include #include #include #include "absl/log/log.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "include/rapidjson/document.h" #include "include/rapidjson/istreamwrapper.h" #include "include/rapidjson/rapidjson.h" #include "tink/internal/test_file_util.h" #include "tink/subtle/common_enums.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { namespace { // TODO(tholenst): factor these helpers out to an "util"-class. util::StatusOr HexDecode(absl::string_view hex) { if (hex.size() % 2 != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Input has odd size."); } std::string decoded(hex.size() / 2, static_cast(0)); for (size_t i = 0; i < hex.size(); ++i) { char c = hex[i]; char val; if ('0' <= c && c <= '9') val = c - '0'; else if ('a' <= c && c <= 'f') val = c - 'a' + 10; else if ('A' <= c && c <= 'F') val = c - 'A' + 10; else return util::Status(absl::StatusCode::kInvalidArgument, "Not hexadecimal"); decoded[i / 2] = (decoded[i / 2] << 4) | val; } return decoded; } std::string HexDecodeOrDie(absl::string_view hex) { return HexDecode(hex).value(); } } // namespace std::string WycheproofUtil::GetBytes(const rapidjson::Value &val) { std::string s(val.GetString()); if (s.size() % 2 != 0) { // ECDH private key may have odd length. s = "0" + s; } return HexDecodeOrDie(s); } std::unique_ptr WycheproofUtil::ReadTestVectors( const std::string &filename) { std::string test_vectors_path = crypto::tink::internal::RunfilesPath( absl::StrCat("testvectors/", filename)); std::ifstream input_stream; input_stream.open(test_vectors_path); rapidjson::IStreamWrapper input(input_stream); auto root = std::make_unique(rapidjson::kObjectType); if (root->ParseStream(input).HasParseError()) { LOG(FATAL) << "Failure parsing of test vectors from " << test_vectors_path; } return root; } HashType WycheproofUtil::GetHashType(const rapidjson::Value &val) { std::string md(val.GetString()); if (md == "SHA-1") { return HashType::SHA1; } else if (md == "SHA-256") { return HashType::SHA256; } else if (md == "SHA-384") { return HashType::UNKNOWN_HASH; } else if (md == "SHA-512") { return HashType::SHA512; } else { return HashType::UNKNOWN_HASH; } } EllipticCurveType WycheproofUtil::GetEllipticCurveType( const rapidjson::Value &val) { std::string curve(val.GetString()); if (curve == "secp256r1") { return EllipticCurveType::NIST_P256; } else if (curve == "secp384r1") { return EllipticCurveType::NIST_P384; } else if (curve == "secp521r1") { return EllipticCurveType::NIST_P521; } else { return EllipticCurveType::UNKNOWN_CURVE; } } std::string WycheproofUtil::GetInteger(const rapidjson::Value &val) { std::string hex(val.GetString()); // Since val is a hexadecimal integer it can have an odd length. if (hex.size() % 2 == 1) { // Avoid a leading 0 byte. if (hex[0] == '0') { hex = std::string(hex, 1, hex.size() - 1); } else { hex = "0" + hex; } } return HexDecode(hex).value(); } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/wycheproof_util.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_WYCHEPROOF_UTIL_H_ #define TINK_SUBTLE_WYCHEPROOF_UTIL_H_ #include #include #include "include/rapidjson/document.h" #include "tink/subtle/common_enums.h" namespace crypto { namespace tink { namespace subtle { // WycheproofUtil is a util that is used to read test vectors from project // Wycheproof and convert the values in the test vectors into corresponding // values for tink. class WycheproofUtil { public: // Converts a JSON value into a byte array. // Byte arrays are always hexadecimal representation. static std::string GetBytes(const rapidjson::Value &val); // Reads test vector from a file. // The filename is relative to the directory with the test vectors. static std::unique_ptr ReadTestVectors( const std::string &filename); static HashType GetHashType(const rapidjson::Value &val); static EllipticCurveType GetEllipticCurveType(const rapidjson::Value &val); // Integers in Wycheproof are represented as signed bigendian hexadecimal // strings in twos complement representation. // Integers in EcKey are unsigned and are represented as an array of bytes // using bigendian order. // GetInteger can assume that val is always 0 or a positive integer, since // they are values from the key: a convention in Wycheproof is that parameters // in the test group are valid, only values in the test vector itself may // be invalid. static std::string GetInteger(const rapidjson::Value &val); }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_WYCHEPROOF_UTIL_H_ ================================================ FILE: cc/subtle/xchacha20_poly1305_boringssl.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/xchacha20_poly1305_boringssl.h" #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "tink/aead.h" #include "tink/aead/internal/ssl_aead.h" #include "tink/internal/fips_utils.h" #include "tink/internal/util.h" #include "tink/subtle/random.h" #include "tink/subtle/subtle_util.h" #include "tink/util/errors.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { constexpr int kNonceSizeInBytes = 24; constexpr int kTagSizeInBytes = 16; util::StatusOr> XChacha20Poly1305BoringSsl::New( util::SecretData key) { auto status = internal::CheckFipsCompatibility(); if (!status.ok()) { return status; } util::StatusOr> aead = internal::CreateXchacha20Poly1305OneShotCrypter(key); if (!aead.ok()) { return aead.status(); } std::unique_ptr aead_impl = absl::WrapUnique(new XChacha20Poly1305BoringSsl(*std::move(aead))); return std::move(aead_impl); } util::StatusOr XChacha20Poly1305BoringSsl::Encrypt( absl::string_view plaintext, absl::string_view associated_data) const { const int64_t kCiphertextSize = kNonceSizeInBytes + aead_->CiphertextSize(plaintext.size()); std::string ct; ResizeStringUninitialized(&ct, kCiphertextSize); util::Status res = Random::GetRandomBytes(absl::MakeSpan(ct).subspan(0, kNonceSizeInBytes)); if (!res.ok()) { return res; } auto nonce = absl::string_view(ct).substr(0, kNonceSizeInBytes); auto ciphertext_and_tag_buffer = absl::MakeSpan(ct).subspan(kNonceSizeInBytes); util::StatusOr written_bytes = aead_->Encrypt( plaintext, associated_data, nonce, ciphertext_and_tag_buffer); if (!written_bytes.ok()) { return written_bytes.status(); } return ct; } util::StatusOr XChacha20Poly1305BoringSsl::Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const { if (ciphertext.size() < kNonceSizeInBytes + kTagSizeInBytes) { return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Ciphertext too short; expected at least ", kNonceSizeInBytes + kTagSizeInBytes, " got ", ciphertext.size())); } const int64_t kPlaintextSize = aead_->PlaintextSize(ciphertext.size() - kNonceSizeInBytes); std::string plaintext; ResizeStringUninitialized(&plaintext, kPlaintextSize); auto nonce = ciphertext.substr(0, kNonceSizeInBytes); auto encrypted = ciphertext.substr(kNonceSizeInBytes); util::StatusOr written_bytes = aead_->Decrypt( encrypted, associated_data, nonce, absl::MakeSpan(plaintext)); if (!written_bytes.ok()) { return written_bytes.status(); } return plaintext; } } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/subtle/xchacha20_poly1305_boringssl.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_SUBTLE_XCHACHA20_POLY1305_BORINGSSL_H_ #define TINK_SUBTLE_XCHACHA20_POLY1305_BORINGSSL_H_ #include #include #include #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/aead/internal/ssl_aead.h" #include "tink/internal/fips_utils.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace subtle { class XChacha20Poly1305BoringSsl : public Aead { public: // Constructs a new Aead cipher for XChacha20-Poly1305. // Currently supported key size is 256 bits. // Currently supported nonce size is 24 bytes. // The tag size is fixed to 16 bytes. static crypto::tink::util::StatusOr> New( util::SecretData key); crypto::tink::util::StatusOr Encrypt( absl::string_view plaintext, absl::string_view associated_data) const override; crypto::tink::util::StatusOr Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const override; static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus = crypto::tink::internal::FipsCompatibility::kNotFips; private: explicit XChacha20Poly1305BoringSsl( std::unique_ptr aead) : aead_(std::move(aead)) {} const std::unique_ptr aead_; }; } // namespace subtle } // namespace tink } // namespace crypto #endif // TINK_SUBTLE_XCHACHA20_POLY1305_BORINGSSL_H_ ================================================ FILE: cc/subtle/xchacha20_poly1305_boringssl_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/subtle/xchacha20_poly1305_boringssl.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/aead/internal/wycheproof_aead.h" #include "tink/config/tink_fips.h" #include "tink/internal/ssl_util.h" #include "tink/subtle/subtle_util.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace subtle { namespace { constexpr int kNonceSizeInBytes = 24; constexpr int kTagSizeInBytes = 16; constexpr absl::string_view kKey256Hex = "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"; constexpr absl::string_view kMessage = "Some data to encrypt."; constexpr absl::string_view kAssociatedData = "Some data to authenticate."; using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::testing::AllOf; using ::testing::Eq; using ::testing::Not; using ::testing::SizeIs; using ::testing::TestWithParam; using ::testing::ValuesIn; TEST(XChacha20Poly1305BoringSslTest, EncryptDecrypt) { if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::SecretData key = util::SecretDataFromStringView(absl::HexStringToBytes(kKey256Hex)); if (!internal::IsBoringSsl()) { EXPECT_THAT(XChacha20Poly1305BoringSsl::New(key).status(), StatusIs(absl::StatusCode::kUnimplemented)); } else { util::StatusOr> aead = XChacha20Poly1305BoringSsl::New(key); ASSERT_THAT(aead, IsOk()); util::StatusOr ciphertext = (*aead)->Encrypt(kMessage, kAssociatedData); ASSERT_THAT(ciphertext, IsOk()); EXPECT_THAT(*ciphertext, SizeIs(kMessage.size() + kNonceSizeInBytes + kTagSizeInBytes)); util::StatusOr plaintext = (*aead)->Decrypt(*ciphertext, kAssociatedData); ASSERT_THAT(plaintext, IsOk()); EXPECT_EQ(*plaintext, kMessage); } } // Test decryption with a known ciphertext, message, associated_data and key // tuple to make sure this is using the correct algorithm. The values are taken // from the test vector tcId 1 of the Wycheproof tests: // https://github.com/google/wycheproof/blob/master/testvectors/xchacha20_poly1305_test.json#L21 TEST(XChacha20Poly1305BoringSslTest, SimpleDecrypt) { if (!internal::IsBoringSsl()) { GTEST_SKIP() << "Unimplemented with OpenSSL"; } if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } std::string message = absl::HexStringToBytes( "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66" "202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e6520" "74697020666f7220746865206675747572652c2073756e73637265656e20776f756c6420" "62652069742e"); std::string raw_ciphertext = absl::HexStringToBytes( "bd6d179d3e83d43b9576579493c0e939572a1700252bfaccbed2902c21396cbb731c7f1b" "0b4aa6440bf3a82f4eda7e39ae64c6708c54c216cb96b72e1213b4522f8c9ba40db5d945" "b11b69b982c1bb9e3f3fac2bc369488f76b2383565d3fff921f9664c97637da9768812f6" "15c68b13b52e"); std::string iv = absl::HexStringToBytes( "404142434445464748494a4b4c4d4e4f5051525354555657"); std::string tag = absl::HexStringToBytes("c0875924c1c7987947deafd8780acf49"); std::string associated_data = absl::HexStringToBytes("50515253c0c1c2c3c4c5c6c7"); util::SecretData key = util::SecretDataFromStringView(absl::HexStringToBytes( "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f")); util::StatusOr> aead = XChacha20Poly1305BoringSsl::New(key); ASSERT_THAT(aead, IsOk()); util::StatusOr plaintext = (*aead)->Decrypt(absl::StrCat(iv, raw_ciphertext, tag), associated_data); ASSERT_THAT(plaintext, IsOk()); EXPECT_EQ(*plaintext, message); } TEST(XChacha20Poly1305BoringSslTest, DecryptFailsIfCiphertextTooSmall) { if (!internal::IsBoringSsl()) { GTEST_SKIP() << "Unimplemented with OpenSSL"; } if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } util::SecretData key = util::SecretDataFromStringView(absl::HexStringToBytes(kKey256Hex)); util::StatusOr> aead = XChacha20Poly1305BoringSsl::New(key); ASSERT_THAT(aead, IsOk()); for (int i = 1; i < kNonceSizeInBytes + kTagSizeInBytes; i++) { std::string ciphertext; ResizeStringUninitialized(&ciphertext, i); EXPECT_THAT((*aead)->Decrypt(ciphertext, kAssociatedData).status(), StatusIs(absl::StatusCode::kInvalidArgument)); } } TEST(XChacha20Poly1305BoringSslTest, FailisOnFipsOnlyMode) { if (!internal::IsBoringSsl()) { GTEST_SKIP() << "Unimplemented with OpenSSL"; } if (!IsFipsModeEnabled()) { GTEST_SKIP() << "Only ran in in FIPS-only mode"; } util::SecretData key256 = util::SecretDataFromStringView(absl::HexStringToBytes(kKey256Hex)); EXPECT_THAT(XChacha20Poly1305BoringSsl::New(key256).status(), StatusIs(absl::StatusCode::kInternal)); } class XChacha20Poly1305BoringSslWycheproofTest : public TestWithParam { void SetUp() override { if (!internal::IsBoringSsl()) { GTEST_SKIP() << "Unimplemented with OpenSSL"; } if (IsFipsModeEnabled()) { GTEST_SKIP() << "Not supported in FIPS-only mode"; } internal::WycheproofTestVector test_vector = GetParam(); if (test_vector.key.size() != 32 || test_vector.nonce.size() != kNonceSizeInBytes || test_vector.tag.size() != kTagSizeInBytes) { GTEST_SKIP() << "Unsupported parameters: key size " << test_vector.key.size() << " nonce size: " << test_vector.nonce.size() << " tag size: " << test_vector.tag.size(); } } }; TEST_P(XChacha20Poly1305BoringSslWycheproofTest, Decrypt) { internal::WycheproofTestVector test_vector = GetParam(); util::SecretData key = util::SecretDataFromStringView(test_vector.key); util::StatusOr> cipher = XChacha20Poly1305BoringSsl::New(key); ASSERT_THAT(cipher, IsOk()); std::string ciphertext = absl::StrCat(test_vector.nonce, test_vector.ct, test_vector.tag); util::StatusOr plaintext = (*cipher)->Decrypt(ciphertext, test_vector.aad); if (plaintext.ok()) { EXPECT_NE(test_vector.expected, "invalid") << "Decrypted invalid ciphertext with ID " << test_vector.id; EXPECT_EQ(*plaintext, test_vector.msg) << "Incorrect decryption: " << test_vector.id; } else { EXPECT_THAT(test_vector.expected, Not(AllOf(Eq("valid"), Eq("acceptable")))) << "Could not decrypt test with tcId: " << test_vector.id << " iv_size: " << test_vector.nonce.size() << " tag_size: " << test_vector.tag.size() << " key_size: " << key.size() << "; error: " << plaintext.status(); } } INSTANTIATE_TEST_SUITE_P(XChacha20Poly1305BoringSslWycheproofTests, XChacha20Poly1305BoringSslWycheproofTest, ValuesIn(internal::ReadWycheproofTestVectors( /*file_name=*/"xchacha20_poly1305_test.json"))); } // namespace } // namespace subtle } // namespace tink } // namespace crypto ================================================ FILE: cc/template_rule.bzl ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Rule for simple expansion of template files.""" def _template_rule_impl(ctx): """Modifies ctx.file.src keys in ctx.attr.substitutions with corresponding values.""" ctx.actions.expand_template( template = ctx.file.src, output = ctx.outputs.out, substitutions = ctx.attr.substitutions, ) # Rule for simple expansion of template files. Modifies the templates in src substituting the keys # in substitutions with the corresponding values; the result is output to out. # # Borrowed from TensorFlow (https://github.com/tensorflow/tensorflow) # # Typical usage: # template_rule( # name = "ExpandMyTemplate", # src = "my.template", # out = "my.txt", # substitutions = { # "$VAR1": "foo", # "$VAR2": "bar", # } # ) # # Args: # name: The name of the rule. # src: The template file to expand # out: The destination of the expanded file # substitutions: A dictionary mapping strings to their substitutions template_rule = rule( attrs = { "src": attr.label( mandatory = True, allow_single_file = True, ), "substitutions": attr.string_dict(mandatory = True), "out": attr.output(mandatory = True), }, implementation = _template_rule_impl, ) ================================================ FILE: cc/testvectors/BUILD.bazel ================================================ """Defines a set of genrules to copy test vectors from Wycheproof. This is needed to assist the transition to using Bazel Modules, in that Bazel Modules packages use a different folder naming for dependencies compared to WORKSPACE-based packages. """ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) genrule( name = "aes_cmac", srcs = ["@wycheproof//testvectors:aes_cmac"], outs = ["aes_cmac_test.json"], cmd = "cp $(SRCS) $(@D)/", testonly = 1, ) genrule( name = "aes_gcm", srcs = ["@wycheproof//testvectors:aes_gcm"], outs = ["aes_gcm_test.json"], cmd = "cp $(SRCS) $(@D)/", testonly = 1, ) genrule( name = "aes_gcm_siv", srcs = ["@wycheproof//testvectors:aes_gcm_siv"], outs = ["aes_gcm_siv_test.json"], cmd = "cp $(SRCS) $(@D)/", testonly = 1, ) genrule( name = "aes_eax", srcs = ["@wycheproof//testvectors:aes_eax"], outs = ["aes_eax_test.json"], cmd = "cp $(SRCS) $(@D)/", testonly = 1, ) genrule( name = "aes_siv_cmac", srcs = ["@wycheproof//testvectors:aes_siv_cmac"], outs = [ "aead_aes_siv_cmac_test.json", "aes_siv_cmac_test.json", ], cmd = "cp $(SRCS) $(@D)/", testonly = 1, ) genrule( name = "chacha20_poly1305", srcs = ["@wycheproof//testvectors:chacha20_poly1305"], outs = [ "chacha20_poly1305_test.json", "xchacha20_poly1305_test.json", ], cmd = "cp $(SRCS) $(@D)/", testonly = 1, ) genrule( name = "hmac", srcs = ["@wycheproof//testvectors:hmac"], outs = [ "hmac_sha1_test.json", "hmac_sha224_test.json", "hmac_sha256_test.json", "hmac_sha384_test.json", "hmac_sha3_224_test.json", "hmac_sha3_256_test.json", "hmac_sha3_384_test.json", "hmac_sha3_512_test.json", "hmac_sha512_test.json", ], cmd = "cp $(SRCS) $(@D)/", testonly = 1, ) genrule( name = "rsa_pss", srcs = ["@wycheproof//testvectors:rsa_pss"], outs = [ "rsa_pss_2048_sha1_mgf1_20_test.json", "rsa_pss_2048_sha256_mgf1_0_test.json", "rsa_pss_2048_sha256_mgf1_32_test.json", "rsa_pss_3072_sha256_mgf1_32_test.json", "rsa_pss_4096_sha256_mgf1_32_test.json", "rsa_pss_4096_sha512_mgf1_32_test.json", "rsa_pss_misc_test.json", ], cmd = "cp $(SRCS) $(@D)/", testonly = 1, ) genrule( name = "rsa_signature", srcs = ["@wycheproof//testvectors:rsa_signature"], outs = [ # Signature verification "rsa_signature_2048_sha224_test.json", "rsa_signature_2048_sha256_test.json", "rsa_signature_2048_sha512_test.json", "rsa_signature_3072_sha256_test.json", "rsa_signature_3072_sha384_test.json", "rsa_signature_3072_sha512_test.json", "rsa_signature_4096_sha384_test.json", "rsa_signature_4096_sha512_test.json", "rsa_signature_2048_sha3_224_test.json", "rsa_signature_2048_sha3_256_test.json", "rsa_signature_2048_sha3_384_test.json", "rsa_signature_2048_sha3_512_test.json", "rsa_signature_3072_sha3_256_test.json", "rsa_signature_3072_sha3_384_test.json", "rsa_signature_3072_sha3_512_test.json", "rsa_signature_test.json", # Signature generation "rsa_sig_gen_misc_test.json", ], cmd = "cp $(SRCS) $(@D)/", testonly = 1, ) genrule( name = "ecdsa_webcrypto", srcs = ["@wycheproof//testvectors:ecdsa_webcrypto"], outs = ["ecdsa_webcrypto_test.json"], cmd = "cp $(SRCS) $(@D)/", testonly = 1, ) genrule( name = "ecdsa", srcs = ["@wycheproof//testvectors:ecdsa"], outs = [ "ecdsa_brainpoolP224r1_sha224_test.json", "ecdsa_brainpoolP256r1_sha256_test.json", "ecdsa_brainpoolP320r1_sha384_test.json", "ecdsa_brainpoolP384r1_sha384_test.json", "ecdsa_brainpoolP512r1_sha512_test.json", "ecdsa_secp224r1_sha224_test.json", "ecdsa_secp224r1_sha256_test.json", "ecdsa_secp224r1_sha3_224_test.json", "ecdsa_secp224r1_sha3_256_test.json", "ecdsa_secp224r1_sha3_512_test.json", "ecdsa_secp224r1_sha512_test.json", "ecdsa_secp256k1_sha256_test.json", "ecdsa_secp256k1_sha3_256_test.json", "ecdsa_secp256k1_sha3_512_test.json", "ecdsa_secp256k1_sha512_test.json", "ecdsa_secp256r1_sha256_test.json", "ecdsa_secp256r1_sha3_256_test.json", "ecdsa_secp256r1_sha3_512_test.json", "ecdsa_secp256r1_sha512_test.json", "ecdsa_secp384r1_sha384_test.json", "ecdsa_secp384r1_sha3_384_test.json", "ecdsa_secp384r1_sha3_512_test.json", "ecdsa_secp384r1_sha512_test.json", "ecdsa_secp521r1_sha3_512_test.json", "ecdsa_secp521r1_sha512_test.json", "ecdsa_test.json", # deprecated: use the files above ], cmd = "cp $(SRCS) $(@D)/", testonly = 1, ) genrule( name = "eddsa", srcs = ["@wycheproof//testvectors:eddsa"], outs = [ "ed448_test.json", "eddsa_test.json", ], cmd = "cp $(SRCS) $(@D)/", testonly = 1, ) genrule( name = "ecdh", srcs = ["@wycheproof//testvectors:ecdh"], outs = [ "ecdh_brainpoolP224r1_test.json", "ecdh_brainpoolP256r1_test.json", "ecdh_brainpoolP320r1_test.json", "ecdh_brainpoolP384r1_test.json", "ecdh_brainpoolP512r1_test.json", "ecdh_secp224r1_test.json", "ecdh_secp256k1_test.json", "ecdh_secp256r1_test.json", "ecdh_secp384r1_test.json", "ecdh_secp521r1_test.json", "ecdh_test.json", # deprecated use the files above ], cmd = "cp $(SRCS) $(@D)/", testonly = 1, ) ================================================ FILE: cc/third_party/BUILD.bazel ================================================ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) ================================================ FILE: cc/third_party/boringssl_fips/BUILD.bazel ================================================ licenses(["notice"]) boringssl_headers = [ "boringssl/include/openssl/aead.h", "boringssl/include/openssl/aes.h", "boringssl/include/openssl/arm_arch.h", "boringssl/include/openssl/asn1.h", "boringssl/include/openssl/asn1_mac.h", "boringssl/include/openssl/asn1t.h", "boringssl/include/openssl/base64.h", "boringssl/include/openssl/base.h", "boringssl/include/openssl/bio.h", "boringssl/include/openssl/blowfish.h", "boringssl/include/openssl/bn.h", "boringssl/include/openssl/buffer.h", "boringssl/include/openssl/buf.h", "boringssl/include/openssl/bytestring.h", "boringssl/include/openssl/cast.h", "boringssl/include/openssl/chacha.h", "boringssl/include/openssl/cipher.h", "boringssl/include/openssl/cmac.h", "boringssl/include/openssl/conf.h", "boringssl/include/openssl/cpu.h", "boringssl/include/openssl/crypto.h", "boringssl/include/openssl/curve25519.h", "boringssl/include/openssl/des.h", "boringssl/include/openssl/dh.h", "boringssl/include/openssl/digest.h", "boringssl/include/openssl/dsa.h", "boringssl/include/openssl/dtls1.h", "boringssl/include/openssl/ecdh.h", "boringssl/include/openssl/ecdsa.h", "boringssl/include/openssl/ec.h", "boringssl/include/openssl/ec_key.h", "boringssl/include/openssl/engine.h", "boringssl/include/openssl/e_os2.h", "boringssl/include/openssl/err.h", "boringssl/include/openssl/evp.h", "boringssl/include/openssl/ex_data.h", "boringssl/include/openssl/hkdf.h", "boringssl/include/openssl/hmac.h", "boringssl/include/openssl/hrss.h", "boringssl/include/openssl/is_boringssl.h", "boringssl/include/openssl/lhash.h", "boringssl/include/openssl/md4.h", "boringssl/include/openssl/md5.h", "boringssl/include/openssl/mem.h", "boringssl/include/openssl/nid.h", "boringssl/include/openssl/objects.h", "boringssl/include/openssl/obj.h", "boringssl/include/openssl/obj_mac.h", "boringssl/include/openssl/opensslconf.h", "boringssl/include/openssl/opensslv.h", "boringssl/include/openssl/ossl_typ.h", "boringssl/include/openssl/pem.h", "boringssl/include/openssl/pkcs12.h", "boringssl/include/openssl/pkcs7.h", "boringssl/include/openssl/pkcs8.h", "boringssl/include/openssl/poly1305.h", "boringssl/include/openssl/pool.h", "boringssl/include/openssl/rand.h", "boringssl/include/openssl/rc4.h", "boringssl/include/openssl/ripemd.h", "boringssl/include/openssl/rsa.h", "boringssl/include/openssl/safestack.h", "boringssl/include/openssl/sha.h", "boringssl/include/openssl/siphash.h", "boringssl/include/openssl/span.h", "boringssl/include/openssl/srtp.h", "boringssl/include/openssl/ssl3.h", "boringssl/include/openssl/ssl.h", "boringssl/include/openssl/stack.h", "boringssl/include/openssl/thread.h", "boringssl/include/openssl/tls1.h", "boringssl/include/openssl/type_check.h", "boringssl/include/openssl/x509.h", "boringssl/include/openssl/x509v3.h", "boringssl/include/openssl/x509_vfy.h", ] cc_library( name = "crypto", srcs = [ "libcrypto.so", ], hdrs = boringssl_headers, includes = ["boringssl/include/"], tags = [ "manual", # This target will only work on Linux and should not be included in wildcard builds ], visibility = ["//visibility:public"], ) cc_library( name = "ssl", srcs = [ "libssl.so", ], hdrs = boringssl_headers, includes = ["boringssl/include/"], tags = [ "manual", # This target will only work on Linux and should not be included in wildcard builds ], visibility = ["//visibility:public"], deps = [ ":crypto", ], ) genrule( name = "build_fipsmodule", srcs = [ "boringssl_fips.sh", ], outs = [ "libcrypto.so", "libssl.so", ] + boringssl_headers, cmd = """ ./$(location boringssl_fips.sh) cp boringssl/build/crypto/libcrypto.so $(location libcrypto.so) cp boringssl/build/ssl/libssl.so $(location libssl.so) """ + "".join(["cp " + header + " " + "$(location " + header + ")\n" for header in boringssl_headers]), tags = [ "manual", # This target will only work on Linux and should not be included in wildcard builds ], ) ================================================ FILE: cc/third_party/boringssl_fips/README.md ================================================ # BoringSSL FIPS This WORKSPACE facilitates building BoringSSL with the FIPS validated module [BoringCrypto](https://csrc.nist.gov/Projects/Cryptographic-Module-Validation-Program/Certificate/3678), which can then be used in Tink. Note that this gives no guarantee that you use BoringSSL in a FIPS compliant manner when used. It is strongly recommended to read the official [security policy](https://csrc.nist.gov/CSRC/media/projects/cryptographic-module-validation-program/documents/security-policies/140sp3678.pdf) for BoringCrypto. To use the BoringCrypto module with Tink, you must update the Tink [WORKSPACE file](https://github.com/google/tink/blob/master/cc/WORKSPACE) to use the BoringSSL targets in this WORKSPACE. Tink then offers a [FIPS-only mode](../../../docs/FIPS.md) which will restrict the usage to algorithms which are FIPS approved *and* utilize the BoringCrypto module. ================================================ FILE: cc/third_party/boringssl_fips/WORKSPACE ================================================ workspace(name = "boringssl") ================================================ FILE: cc/third_party/boringssl_fips/boringssl_fips.sh ================================================ #!/bin/bash # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ################################################################################ # This script builds BoringSSL as described in the security policy # https://csrc.nist.gov/CSRC/media/projects/cryptographic-module-validation-program/documents/security-policies/140sp3678.pdf set -e if [[ "$(uname)" != "Linux" ]]; then echo "ERROR: BoringSSL only supports FIPS mode in Linux." exit 1 fi # Install required build tools # # Clang 7.0.1 CLANG_PLATFORM="x86_64-linux-gnu-ubuntu-16.04" CLANG_SHA256SUM=02ad925add5b2b934d64c3dd5cbd1b2002258059f7d962993ba7f16524c3089c curl -OLsS https://releases.llvm.org/7.0.1/clang+llvm-7.0.1-"${CLANG_PLATFORM}".tar.xz echo "${CLANG_SHA256SUM}" clang+llvm-7.0.1-"${CLANG_PLATFORM}".tar.xz | sha256sum --check tar -xf clang+llvm-7.0.1-"${CLANG_PLATFORM}".tar.xz rm clang+llvm-7.0.1-"${CLANG_PLATFORM}".tar.xz export HOME="${PWD}" printf "set(CMAKE_C_COMPILER \"clang\")\nset(CMAKE_CXX_COMPILER \"clang++\")\n" > "${HOME}/toolchain" export PATH="${PWD}/clang+llvm-7.0.1-${CLANG_PLATFORM}/bin:${PATH}" # Go 1.12.7 GO_PLATFORM="linux-amd64" GO_SHA256SUM="66d83bfb5a9ede000e33c6579a91a29e6b101829ad41fffb5c5bb6c900e109d9" curl -OLsS https://dl.google.com/go/go1.12.7."${GO_PLATFORM}".tar.gz echo "${GO_SHA256SUM}" go1.12.7."${GO_PLATFORM}".tar.gz | sha256sum --check tar -xf go1.12.7."${GO_PLATFORM}".tar.gz rm go1.12.7."${GO_PLATFORM}".tar.gz export PATH="${PWD}/go/bin:${PATH}" # Ninja 1.9.0 NINJA_SHA256SUM="1b1235f2b0b4df55ac6d80bbe681ea3639c9d2c505c7ff2159a3daf63d196305" curl -OLsS https://github.com/ninja-build/ninja/releases/download/v1.9.0/ninja-linux.zip echo "${NINJA_SHA256SUM}" ninja-linux.zip | sha256sum --check unzip ninja-linux.zip rm ninja-linux.zip export PATH="${PWD}:${PATH}" # Download BoringSSL and verify BORINGSSL_SHA256SUM="3b5fdf23274d4179c2077b5e8fa625d9debd7a390aac1d165b7e47234f648bb8" # Download archive and verify checksum curl -OLsS https://commondatastorage.googleapis.com/chromium-boringssl-fips/boringssl-ae223d6138807a13006342edfeef32e813246b39.tar.xz echo "${BORINGSSL_SHA256SUM}" boringssl-ae223d6138807a13006342edfeef32e813246b39.tar.xz | sha256sum --check tar -xf boringssl-ae223d6138807a13006342edfeef32e813246b39.tar.xz rm boringssl-ae223d6138807a13006342edfeef32e813246b39.tar.xz # Build BoringSSL ( cd boringssl mkdir build && cd build && cmake -GNinja -DCMAKE_TOOLCHAIN_FILE=${HOME}/toolchain -DFIPS=1 -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=1 .. ninja ninja run_tests if [[ "$(tool/bssl isfips)" != "1" ]]; then echo "ERROR: BoringSSL FIPS build check failed." exit 1 fi ) # Cleanup build tools rm -rf clang+llvm-7.0.1-"${CLANG_PLATFORM}" rm -rf go rm ninja rm toolchain ================================================ FILE: cc/third_party/rapidjson.BUILD.bazel ================================================ licenses(["notice"]) # MIT cc_library( name = "rapidjson", srcs = [ "include/rapidjson/internal/biginteger.h", "include/rapidjson/internal/diyfp.h", "include/rapidjson/internal/dtoa.h", "include/rapidjson/internal/ieee754.h", "include/rapidjson/internal/itoa.h", "include/rapidjson/internal/meta.h", "include/rapidjson/internal/pow10.h", "include/rapidjson/internal/regex.h", "include/rapidjson/internal/stack.h", "include/rapidjson/internal/strfunc.h", "include/rapidjson/internal/strtod.h", "include/rapidjson/internal/swap.h", ], hdrs = [ "include/rapidjson/allocators.h", "include/rapidjson/document.h", "include/rapidjson/encodedstream.h", "include/rapidjson/encodings.h", "include/rapidjson/error/en.h", "include/rapidjson/error/error.h", "include/rapidjson/filereadstream.h", "include/rapidjson/filewritestream.h", "include/rapidjson/fwd.h", "include/rapidjson/istreamwrapper.h", "include/rapidjson/memorybuffer.h", "include/rapidjson/memorystream.h", "include/rapidjson/ostreamwrapper.h", "include/rapidjson/pointer.h", "include/rapidjson/prettywriter.h", "include/rapidjson/rapidjson.h", "include/rapidjson/reader.h", "include/rapidjson/schema.h", "include/rapidjson/stream.h", "include/rapidjson/stringbuffer.h", "include/rapidjson/writer.h", ], includes = ["include"], visibility = ["//visibility:public"], ) ================================================ FILE: cc/tink_cc_deps.bzl ================================================ """Dependencies of Tink C++.""" load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") def tink_cc_deps(): """Loads dependencies of C++ Tink.""" # Basic rules we need to add to bazel. # Release from 2023-11-06. maybe( http_archive, name = "bazel_skylib", sha256 = "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94", urls = [ "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz", "https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz", ], ) # ------------------------------------------------------------------------- # Protobuf. # ------------------------------------------------------------------------- # proto_library, cc_proto_library and java_proto_library rules implicitly # depend respectively on: # * @com_google_protobuf//:proto # * @com_google_protobuf//:cc_toolchain # * @com_google_protobuf//:java_toolchain # This statement defines the @com_google_protobuf repo. # Release X.25.1 from 2023-11-15. maybe( http_archive, name = "com_google_protobuf", sha256 = "5c86c077b0794c3e9bb30cac872cf883043febfb0f992137f0a8b1c3d534617c", strip_prefix = "protobuf-25.1", urls = ["https://github.com/protocolbuffers/protobuf/releases/download/v25.1/protobuf-25.1.zip"], ) # ------------------------------------------------------------------------- # Abseil. # ------------------------------------------------------------------------- # Release from 2023-09-18. maybe( http_archive, name = "com_google_absl", sha256 = "497ebdc3a4885d9209b9bd416e8c3f71e7a1fb8af249f6c2a80b7cbeefcd7e21", strip_prefix = "abseil-cpp-20230802.1", urls = ["https://github.com/abseil/abseil-cpp/archive/refs/tags/20230802.1.zip"], ) # ------------------------------------------------------------------------- # BoringSSL. # ------------------------------------------------------------------------- # Commit from 2023-09-08. maybe( http_archive, name = "boringssl", sha256 = "21b2086e9242b87415767fd6d2d13bd0481e2eb3c336c7ffa24b1f3d7afb09ae", strip_prefix = "boringssl-667d54c96acda029523c5bf425e8eb9079dbe94a", url = "https://github.com/google/boringssl/archive/667d54c96acda029523c5bf425e8eb9079dbe94a.zip", ) # ------------------------------------------------------------------------- # Rapidjson. # ------------------------------------------------------------------------- # Release from 2016-08-25 (still the latest release as of 2022-05-05). maybe( http_archive, build_file = "@tink_cc//:third_party/rapidjson.BUILD.bazel", name = "rapidjson", sha256 = "bf7ced29704a1e696fbccf2a2b4ea068e7774fa37f6d7dd4039d0787f8bed98e", strip_prefix = "rapidjson-1.1.0", url = "https://github.com/Tencent/rapidjson/archive/v1.1.0.tar.gz", ) def tink_cc_testonly_deps(): """Test only dependencies for tink-cc.""" # ------------------------------------------------------------------------- # Wycheproof. # ------------------------------------------------------------------------- # Commit from 2019-12-17. maybe( http_archive, name = "wycheproof", sha256 = "eb1d558071acf1aa6d677d7f1cabec2328d1cf8381496c17185bd92b52ce7545", strip_prefix = "wycheproof-d8ed1ba95ac4c551db67f410c06131c3bc00a97c", url = "https://github.com/google/wycheproof/archive/d8ed1ba95ac4c551db67f410c06131c3bc00a97c.zip", ) # ------------------------------------------------------------------------- # GoogleTest/GoogleMock. # ------------------------------------------------------------------------- # Release from 2023-08-02. maybe( http_archive, name = "com_google_googletest", sha256 = "1f357c27ca988c3f7c6b4bf68a9395005ac6761f034046e9dde0896e3aba00e4", strip_prefix = "googletest-1.14.0", url = "https://github.com/google/googletest/archive/refs/tags/v1.14.0.zip", ) ================================================ FILE: cc/tink_cc_deps_init.bzl ================================================ """Initialization of dependencies of C++ Tink.""" load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") def tink_cc_deps_init(): """Initializes dependencies of C++ Tink.""" # Initialize Protobuf dependencies. protobuf_deps() ================================================ FILE: cc/tink_config.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_TINK_CONFIG_H_ #define TINK_TINK_CONFIG_H_ #include "tink/config/tink_config.h" // IWYU pragma: export #endif // TINK_TINK_CONFIG_H_ ================================================ FILE: cc/tink_version.bzl ================================================ """ Version of the current release of Tink """ TINK_VERSION_LABEL = "1.7.0" ================================================ FILE: cc/util/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) cc_library( name = "buffer", srcs = ["buffer.cc"], hdrs = ["buffer.h"], include_prefix = "tink/util", visibility = ["//visibility:public"], deps = [ ":status", ":statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", ], ) cc_library( name = "constants", srcs = ["constants.cc"], hdrs = ["constants.h"], include_prefix = "tink/util", deps = ["@com_google_absl//absl/base:core_headers"], ) cc_library( name = "secret_data_internal", hdrs = ["secret_data_internal.h"], include_prefix = "tink/util", visibility = ["//visibility:private"], deps = [ "@boringssl//:crypto", "@com_google_absl//absl/base:config", "@com_google_absl//absl/base:core_headers", ], ) cc_library( name = "secret_data", hdrs = ["secret_data.h"], include_prefix = "tink/util", visibility = ["//visibility:public"], deps = [ ":secret_data_internal", "@com_google_absl//absl/strings", ], ) cc_library( name = "secret_proto", hdrs = ["secret_proto.h"], include_prefix = "tink/util", visibility = ["//visibility:public"], deps = [ ":secret_data", ":status", ":statusor", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_protobuf//:protobuf", ], ) cc_library( name = "errors", hdrs = ["errors.h"], include_prefix = "tink/util", deps = [ ":status", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:str_format", ], ) cc_library( name = "enums", srcs = ["enums.cc"], hdrs = ["enums.h"], include_prefix = "tink/util", visibility = ["//visibility:public"], deps = [ ":status", ":statusor", "//proto:common_cc_proto", "//proto:ecdsa_cc_proto", "//proto:tink_cc_proto", "//subtle:common_enums", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) cc_library( name = "status", hdrs = ["status.h"], include_prefix = "tink/util", visibility = ["//visibility:public"], deps = ["@com_google_absl//absl/status"], ) cc_library( name = "statusor", hdrs = ["statusor.h"], include_prefix = "tink/util", visibility = ["//visibility:public"], deps = [ ":status", "@com_google_absl//absl/status:statusor", ], ) cc_library( name = "validation", srcs = ["validation.cc"], hdrs = ["validation.h"], include_prefix = "tink/util", deps = [ ":errors", ":status", "//proto:tink_cc_proto", "@com_google_absl//absl/status", ], ) cc_library( name = "file_input_stream", srcs = ["file_input_stream.cc"], hdrs = ["file_input_stream.h"], include_prefix = "tink/util", target_compatible_with = select({ "@platforms//os:windows": ["@platforms//:incompatible"], "//conditions:default": [], }), visibility = ["//visibility:public"], deps = [ ":errors", ":status", ":statusor", "//:input_stream", "@com_google_absl//absl/status", ], ) cc_library( name = "file_output_stream", srcs = ["file_output_stream.cc"], hdrs = ["file_output_stream.h"], include_prefix = "tink/util", target_compatible_with = select({ "@platforms//os:windows": ["@platforms//:incompatible"], "//conditions:default": [], }), visibility = ["//visibility:public"], deps = [ ":errors", ":status", ":statusor", "//:output_stream", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", ], ) cc_library( name = "file_random_access_stream", srcs = ["file_random_access_stream.cc"], hdrs = ["file_random_access_stream.h"], include_prefix = "tink/util", target_compatible_with = select({ "@platforms//os:windows": ["@platforms//:incompatible"], "//conditions:default": [], }), visibility = ["//visibility:public"], deps = [ ":buffer", ":errors", ":status", ":statusor", "//:random_access_stream", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", ], ) cc_library( name = "istream_input_stream", srcs = ["istream_input_stream.cc"], hdrs = ["istream_input_stream.h"], include_prefix = "tink/util", visibility = ["//visibility:public"], deps = [ ":errors", ":status", ":statusor", "//:input_stream", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", ], ) cc_library( name = "ostream_output_stream", srcs = ["ostream_output_stream.cc"], hdrs = ["ostream_output_stream.h"], include_prefix = "tink/util", visibility = ["//visibility:public"], deps = [ ":errors", ":status", ":statusor", "//:output_stream", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", ], ) cc_library( name = "test_util", testonly = 1, srcs = ["test_util.cc"], hdrs = ["test_util.h"], include_prefix = "tink/util", visibility = ["//visibility:public"], deps = [ ":buffer", ":constants", ":enums", ":protobuf_helper", ":secret_data", ":status", ":statusor", "//:aead", "//:cleartext_keyset_handle", "//:deterministic_aead", "//:hybrid_decrypt", "//:hybrid_encrypt", "//:input_stream", "//:keyset_handle", "//:keyset_writer", "//:kms_client", "//:mac", "//:output_stream", "//:public_key_sign", "//:public_key_verify", "//:random_access_stream", "//:streaming_aead", "//aead:aes_ctr_hmac_aead_key_manager", "//aead:aes_gcm_key_manager", "//aead:cord_aead", "//aead:xchacha20_poly1305_key_manager", "//daead:aes_siv_key_manager", "//internal:ec_util", "//keyderivation:keyset_deriver", "//proto:aes_ctr_cc_proto", "//proto:aes_ctr_hmac_aead_cc_proto", "//proto:aes_gcm_cc_proto", "//proto:aes_siv_cc_proto", "//proto:common_cc_proto", "//proto:ecdsa_cc_proto", "//proto:ecies_aead_hkdf_cc_proto", "//proto:ed25519_cc_proto", "//proto:hmac_cc_proto", "//proto:tink_cc_proto", "//proto:xchacha20_poly1305_cc_proto", "//subtle:common_enums", "//subtle:random", "//subtle/mac:stateful_mac", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:cord", "@com_google_absl//absl/synchronization", ], ) cc_library( name = "test_matchers", testonly = 1, hdrs = ["test_matchers.h"], include_prefix = "tink/util", visibility = ["//visibility:public"], deps = [ ":status", ":statusor", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest", ], ) cc_library( name = "protobuf_helper", hdrs = ["protobuf_helper.h"], include_prefix = "tink/util", deps = ["@com_google_protobuf//:protobuf"], ) cc_library( name = "test_keyset_handle", testonly = 1, srcs = ["test_keyset_handle.cc"], hdrs = ["test_keyset_handle.h"], include_prefix = "tink/util", deps = [ ":secret_proto", "//:keyset_handle", "//proto:tink_cc_proto", "@com_google_absl//absl/memory", ], ) cc_library( name = "input_stream_util", srcs = ["input_stream_util.cc"], hdrs = ["input_stream_util.h"], include_prefix = "tink/util", deps = [ ":secret_data", ":statusor", "//:input_stream", "@com_google_absl//absl/algorithm:container", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", ], ) cc_library( name = "keyset_util", srcs = ["keyset_util.cc"], hdrs = ["keyset_util.h"], include_prefix = "tink/util", deps = ["//proto:tink_cc_proto"], ) cc_library( name = "fake_kms_client", testonly = 1, srcs = ["fake_kms_client.cc"], hdrs = ["fake_kms_client.h"], include_prefix = "tink/util", visibility = ["//visibility:public"], deps = [ ":errors", ":status", ":statusor", "//:aead", "//:binary_keyset_reader", "//:binary_keyset_writer", "//:cleartext_keyset_handle", "//:keyset_handle", "//:kms_client", "//:kms_clients", "//aead:aead_key_templates", "//config:global_registry", "//proto:tink_cc_proto", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], ) # tests cc_test( name = "buffer_test", size = "small", srcs = ["buffer_test.cc"], deps = [ ":buffer", ":status", ":test_matchers", "//subtle:random", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "errors_test", size = "small", srcs = ["errors_test.cc"], deps = [ ":errors", ":status", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "enums_test", size = "small", srcs = ["enums_test.cc"], deps = [ ":enums", "//proto:common_cc_proto", "//proto:ecdsa_cc_proto", "//proto:tink_cc_proto", "//subtle:common_enums", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "file_input_stream_test", srcs = ["file_input_stream_test.cc"], target_compatible_with = select({ "@platforms//os:windows": ["@platforms//:incompatible"], "//conditions:default": [], }), deps = [ ":file_input_stream", ":status", ":statusor", ":test_matchers", ":test_util", "//internal:test_file_util", "//subtle:random", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "file_output_stream_test", srcs = ["file_output_stream_test.cc"], target_compatible_with = select({ "@platforms//os:windows": ["@platforms//:incompatible"], "//conditions:default": [], }), deps = [ ":file_output_stream", ":status", ":statusor", ":test_matchers", ":test_util", "//internal:test_file_util", "//subtle:random", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "file_random_access_stream_test", srcs = ["file_random_access_stream_test.cc"], target_compatible_with = select({ "@platforms//os:windows": ["@platforms//:incompatible"], "//conditions:default": [], }), deps = [ ":buffer", ":file_random_access_stream", ":status", ":statusor", ":test_matchers", ":test_util", "//:random_access_stream", "//internal:test_file_util", "//subtle:random", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "istream_input_stream_test", srcs = ["istream_input_stream_test.cc"], deps = [ ":istream_input_stream", ":status", ":test_util", "//internal:test_file_util", "//subtle:random", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "ostream_output_stream_test", srcs = ["ostream_output_stream_test.cc"], deps = [ ":ostream_output_stream", ":status", ":test_util", "//internal:test_file_util", "//subtle:random", "@com_google_absl//absl/memory", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "secret_data_test", srcs = ["secret_data_test.cc"], deps = [ ":secret_data", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "secret_proto_test", srcs = ["secret_proto_test.cc"], deps = [ ":secret_data", ":secret_proto", ":statusor", "//proto:test_proto_cc_proto", "@com_google_absl//absl/memory", "@com_google_googletest//:gtest_main", "@com_google_protobuf//:protobuf", ], ) cc_test( name = "test_util_test", srcs = ["test_util_test.cc"], deps = [ ":buffer", ":ostream_output_stream", ":status", ":statusor", ":test_matchers", ":test_util", "//:keyset_handle", "//:output_stream", "//:random_access_stream", "//internal:test_random_access_stream", "//proto:aes_gcm_cc_proto", "//proto:tink_cc_proto", "//subtle", "//subtle:test_util", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:cord", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "validation_test", srcs = ["validation_test.cc"], deps = [ ":test_matchers", ":validation", "//proto:tink_cc_proto", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "input_stream_util_test", srcs = ["input_stream_util_test.cc"], deps = [ ":input_stream_util", ":istream_input_stream", ":secret_data", ":status", ":test_matchers", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "fake_kms_client_test", srcs = ["fake_kms_client_test.cc"], deps = [ ":fake_kms_client", ":status", ":statusor", ":test_matchers", ":test_util", "//:aead", "//:keyset_handle", "//aead:aead_config", "//aead:aead_key_templates", "//config:global_registry", "//proto:kms_aead_cc_proto", "//proto:kms_envelope_cc_proto", "//proto:tink_cc_proto", "@com_google_googletest//:gtest_main", ], ) ================================================ FILE: cc/util/CMakeLists.txt ================================================ tink_module(util) tink_cc_library( NAME buffer SRCS buffer.cc buffer.h DEPS tink::util::status tink::util::statusor absl::memory absl::status ) tink_cc_library( NAME constants SRCS constants.cc constants.h DEPS absl::core_headers ) tink_cc_library( NAME errors SRCS errors.h DEPS tink::util::status absl::status absl::str_format ) tink_cc_library( NAME enums SRCS enums.cc enums.h DEPS tink::util::status tink::util::statusor absl::status absl::strings tink::subtle::common_enums tink::proto::common_cc_proto tink::proto::ecdsa_cc_proto tink::proto::tink_cc_proto ) tink_cc_library( NAME status SRCS status.h DEPS absl::status PUBLIC ) tink_cc_library( NAME statusor SRCS statusor.h DEPS tink::util::status absl::statusor PUBLIC ) tink_cc_library( NAME validation SRCS validation.cc validation.h DEPS tink::util::errors tink::util::status absl::status tink::proto::tink_cc_proto ) tink_cc_library( NAME file_input_stream SRCS file_input_stream.cc file_input_stream.h DEPS tink::util::errors tink::util::status tink::util::statusor absl::status tink::core::input_stream TAGS exclude_if_windows ) tink_cc_library( NAME file_output_stream SRCS file_output_stream.cc file_output_stream.h DEPS tink::util::errors tink::util::status tink::util::statusor absl::memory absl::status tink::core::output_stream TAGS exclude_if_windows ) tink_cc_library( NAME file_random_access_stream SRCS file_random_access_stream.cc file_random_access_stream.h DEPS tink::util::buffer tink::util::errors tink::util::status tink::util::statusor absl::memory absl::status tink::core::random_access_stream TAGS exclude_if_windows ) tink_cc_library( NAME istream_input_stream SRCS istream_input_stream.cc istream_input_stream.h DEPS tink::util::errors tink::util::status tink::util::statusor absl::memory absl::status tink::core::input_stream ) tink_cc_library( NAME ostream_output_stream SRCS ostream_output_stream.cc ostream_output_stream.h DEPS tink::util::errors tink::util::status tink::util::statusor absl::memory absl::status tink::core::output_stream ) tink_cc_library( NAME test_util SRCS test_util.cc test_util.h DEPS tink::util::buffer tink::util::constants tink::util::enums tink::util::protobuf_helper tink::util::secret_data tink::util::status tink::util::statusor absl::core_headers absl::memory absl::status absl::strings absl::cord absl::synchronization tink::core::aead tink::core::cleartext_keyset_handle tink::core::deterministic_aead tink::core::hybrid_decrypt tink::core::hybrid_encrypt tink::core::input_stream tink::core::keyset_handle tink::core::keyset_writer tink::core::kms_client tink::core::mac tink::core::output_stream tink::core::public_key_sign tink::core::public_key_verify tink::core::random_access_stream tink::core::streaming_aead tink::aead::aes_ctr_hmac_aead_key_manager tink::aead::aes_gcm_key_manager tink::aead::cord_aead tink::aead::xchacha20_poly1305_key_manager tink::daead::aes_siv_key_manager tink::internal::ec_util tink::keyderivation::keyset_deriver tink::subtle::common_enums tink::subtle::random tink::subtle::mac::stateful_mac tink::proto::aes_ctr_cc_proto tink::proto::aes_ctr_hmac_aead_cc_proto tink::proto::aes_gcm_cc_proto tink::proto::aes_siv_cc_proto tink::proto::common_cc_proto tink::proto::ecdsa_cc_proto tink::proto::ecies_aead_hkdf_cc_proto tink::proto::ed25519_cc_proto tink::proto::hmac_cc_proto tink::proto::tink_cc_proto tink::proto::xchacha20_poly1305_cc_proto TESTONLY ) tink_cc_library( NAME test_matchers SRCS test_matchers.h DEPS tink::util::status tink::util::statusor gmock absl::status absl::strings TESTONLY ) tink_cc_library( NAME protobuf_helper SRCS protobuf_helper.h DEPS protobuf::libprotobuf-lite ) tink_cc_library( NAME test_keyset_handle SRCS test_keyset_handle.cc test_keyset_handle.h DEPS tink::util::secret_proto absl::memory tink::core::keyset_handle tink::proto::tink_cc_proto TESTONLY ) tink_cc_library( NAME input_stream_util SRCS input_stream_util.cc input_stream_util.h DEPS tink::util::secret_data tink::util::statusor absl::algorithm_container absl::strings absl::span tink::core::input_stream ) tink_cc_library( NAME keyset_util SRCS keyset_util.cc keyset_util.h DEPS tink::proto::tink_cc_proto ) # tests tink_cc_test( NAME buffer_test SRCS buffer_test.cc DEPS tink::util::buffer tink::util::status tink::util::test_matchers gmock absl::memory absl::status absl::strings tink::subtle::random ) tink_cc_test( NAME errors_test SRCS errors_test.cc DEPS tink::util::errors tink::util::status gmock absl::status ) tink_cc_test( NAME enums_test SRCS enums_test.cc DEPS tink::util::enums gmock tink::subtle::common_enums tink::proto::common_cc_proto tink::proto::ecdsa_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME file_input_stream_test SRCS file_input_stream_test.cc DEPS tink::util::file_input_stream tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util gmock absl::memory absl::status absl::strings tink::internal::test_file_util tink::subtle::random TAGS exclude_if_windows ) tink_cc_test( NAME file_output_stream_test SRCS file_output_stream_test.cc DEPS tink::util::file_output_stream tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util gmock absl::memory absl::status absl::strings tink::internal::test_file_util tink::subtle::random TAGS exclude_if_windows ) tink_cc_test( NAME file_random_access_stream_test SRCS file_random_access_stream_test.cc DEPS tink::util::buffer tink::util::file_random_access_stream tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util gmock absl::memory absl::status absl::strings tink::core::random_access_stream tink::internal::test_file_util tink::subtle::random TAGS exclude_if_windows ) tink_cc_test( NAME istream_input_stream_test SRCS istream_input_stream_test.cc DEPS tink::util::istream_input_stream tink::util::status tink::util::test_util gmock absl::memory absl::status absl::statusor absl::strings tink::internal::test_file_util tink::subtle::random ) tink_cc_test( NAME ostream_output_stream_test SRCS ostream_output_stream_test.cc DEPS tink::util::ostream_output_stream tink::util::status tink::util::test_util gmock absl::memory absl::strings tink::internal::test_file_util tink::subtle::random ) tink_cc_test( NAME test_util_test SRCS test_util_test.cc DEPS tink::util::buffer tink::util::ostream_output_stream tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util gmock absl::status absl::strings absl::cord tink::core::keyset_handle tink::core::output_stream tink::core::random_access_stream tink::internal::test_random_access_stream tink::subtle::subtle tink::subtle::test_util tink::proto::aes_gcm_cc_proto tink::proto::tink_cc_proto ) tink_cc_test( NAME validation_test SRCS validation_test.cc DEPS tink::util::test_matchers tink::util::validation gmock absl::status tink::proto::tink_cc_proto ) tink_cc_test( NAME input_stream_util_test SRCS input_stream_util_test.cc DEPS tink::util::input_stream_util tink::util::istream_input_stream tink::util::secret_data tink::util::status tink::util::test_matchers gmock absl::memory absl::status ) tink_cc_library( NAME secret_data_internal SRCS secret_data_internal.h DEPS absl::config absl::core_headers crypto ) tink_cc_library( NAME secret_data SRCS secret_data.h DEPS tink::util::secret_data_internal absl::strings ) tink_cc_test( NAME secret_data_test SRCS secret_data_test.cc DEPS tink::util::secret_data gmock absl::strings ) tink_cc_library( NAME secret_proto SRCS secret_proto.h DEPS tink::util::secret_data tink::util::status tink::util::statusor protobuf::libprotobuf absl::memory absl::status ) tink_cc_test( NAME secret_proto_test SRCS secret_proto_test.cc DEPS tink::util::secret_data tink::util::secret_proto tink::util::statusor protobuf::libprotobuf gmock absl::memory tink::proto::test_proto_cc_proto ) tink_cc_library( NAME fake_kms_client SRCS fake_kms_client.cc fake_kms_client.h DEPS tink::util::errors tink::util::status tink::util::statusor absl::memory absl::status absl::strings tink::core::aead tink::core::binary_keyset_reader tink::core::binary_keyset_writer tink::core::cleartext_keyset_handle tink::core::keyset_handle tink::core::kms_client tink::core::kms_clients tink::aead::aead_key_templates tink::config::global_registry tink::proto::tink_cc_proto TESTONLY ) tink_cc_test( NAME fake_kms_client_test SRCS fake_kms_client_test.cc DEPS tink::util::fake_kms_client tink::util::status tink::util::statusor tink::util::test_matchers tink::util::test_util gmock tink::core::aead tink::core::keyset_handle tink::aead::aead_config tink::aead::aead_key_templates tink::config::global_registry tink::proto::kms_aead_cc_proto tink::proto::kms_envelope_cc_proto tink::proto::tink_cc_proto ) ================================================ FILE: cc/util/buffer.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/buffer.h" #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace util { namespace { class OwningBuffer : public Buffer { public: // Constructs a new Buffer which allocates a new memory block // of size 'allocated_size' and uses it for the actual data. // The allocated memory block is owned by this Buffer. // It is assumed that 'allocated_size' is positive. explicit OwningBuffer(int allocated_size) : allocated_size_(allocated_size), size_(allocated_size) { owned_mem_block_ = absl::make_unique(allocated_size); } char* const get_mem_block() const override { return owned_mem_block_.get(); } int allocated_size() const override { return allocated_size_; } int size() const override { return size_; } util::Status set_size(int new_size) override { if (new_size < 0 || new_size > allocated_size_) { return Status(absl::StatusCode::kInvalidArgument, "new_size must satisfy 0 <= new_size <= allocated_size()"); } size_ = new_size; return OkStatus(); } ~OwningBuffer() override = default; private: std::unique_ptr owned_mem_block_; const int allocated_size_; int size_; }; class NonOwningBuffer : public Buffer { public: // Constructs a new Buffer which uses the given 'mem_block' as a buffer // for the actual data. // Does NOT take the ownership of 'mem_block' which must be non-null, // must allocate at least 'allocated_size' bytes, and must remain alive // as long as the returned Buffer is in use. // It is assumed that 'mem_block' is non-null, and that // 'allocated_size' is positive. NonOwningBuffer(char* mem_block, int allocated_size) : mem_block_(mem_block), allocated_size_(allocated_size), size_(allocated_size) {} char* const get_mem_block() const override { return mem_block_; }; int allocated_size() const override { return allocated_size_; } int size() const override { return size_; } util::Status set_size(int new_size) override { if (new_size < 0 || new_size > allocated_size_) { return Status(absl::StatusCode::kInvalidArgument, "new_size must satisfy 0 <= new_size <= allocated_size()"); } size_ = new_size; return OkStatus(); } ~NonOwningBuffer() override = default; private: char* const mem_block_; const int allocated_size_; int size_; }; } // namespace // static StatusOr> Buffer::New(int allocated_size) { if (allocated_size <= 0) { return Status(absl::StatusCode::kInvalidArgument, "allocated_size must be positive"); } return {absl::make_unique(allocated_size)}; } // static StatusOr> Buffer::NewNonOwning( char* mem_block, int allocated_size) { if (allocated_size <= 0) { return Status(absl::StatusCode::kInvalidArgument, "allocated_size must be positive"); } if (mem_block == nullptr) { return Status(absl::StatusCode::kInvalidArgument, "mem_block must be non-null"); } return {absl::make_unique(mem_block, allocated_size)}; } } // namespace util } // namespace tink } // namespace crypto ================================================ FILE: cc/util/buffer.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_UTIL_BUFFER_H_ #define TINK_UTIL_BUFFER_H_ #include #include "absl/memory/memory.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace util { class Buffer { public: // Creates a new Buffer which allocates a new memory block // of size 'allocated_size' and uses it for the actual data. // The allocated memory block is owned by this Buffer. static util::StatusOr> New(int allocated_size); // Creates a new Buffer which uses the given 'mem_block' as a buffer // for the actual data. // Does NOT take the ownership of 'mem_block' which must be non-null, // must allocate at least 'allocated_size' bytes, and must remain alive // as long as the returned Buffer is in use. static util::StatusOr> NewNonOwning( char* mem_block, int allocated_size); // Returns the internal memory block of this Buffer, // that holds the actual data. // A reading caller may read up to size() bytes from the block. // A writing caller may write up to allocated_size() bytes to the block, // and should accordingly adjust size via set_size(int). virtual char* const get_mem_block() const = 0; // Returns the allocated size of this buffer. virtual int allocated_size() const = 0; // Returns the current size of this buffer. virtual int size() const = 0; // Sets the size of this buffer to 'new_size', which must // be in range 0..allocated_size(). // Returns OK iff 0 <= new_size <= allocated_size(); virtual util::Status set_size(int new_size) = 0; virtual ~Buffer() = default; }; } // namespace util } // namespace tink } // namespace crypto #endif // TINK_UTIL_BUFFER_H_ ================================================ FILE: cc/util/buffer_test.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/buffer.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/subtle/random.h" #include "tink/util/status.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace util { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using testing::HasSubstr; TEST(BufferTest, ExternalMemoryBlock) { for (auto buf_size : {1, 10, 100, 1000, 10000, 100000, 1000000}) { SCOPED_TRACE(absl::StrCat("buf_size = ", buf_size)); auto mem_block = absl::make_unique(buf_size); auto buf_result = Buffer::NewNonOwning(mem_block.get(), buf_size); ASSERT_THAT(buf_result, IsOk()); auto buf = std::move(buf_result.value()); EXPECT_EQ(buf_size, buf->size()); EXPECT_EQ(buf_size, buf->allocated_size()); EXPECT_EQ(mem_block.get(), buf->get_mem_block()); for (auto new_size : {0, 1, buf_size/2, buf_size}) { SCOPED_TRACE(absl::StrCat("new_size = ", buf_size)); ASSERT_THAT(buf->set_size(new_size), IsOk()); EXPECT_EQ(new_size, buf->size()); EXPECT_EQ(buf_size, buf->allocated_size()); EXPECT_EQ(mem_block.get(), buf->get_mem_block()); auto data = subtle::Random::GetRandomBytes(new_size); std::memcpy(buf->get_mem_block(), data.data(), new_size); EXPECT_EQ(0, std::memcmp(data.data(), buf->get_mem_block(), new_size)); } } } TEST(BufferTest, InternalMemoryBlock) { for (auto buf_size : {1, 10, 100, 1000, 10000, 100000, 1000000}) { SCOPED_TRACE(absl::StrCat("buf_size = ", buf_size)); auto buf_result = Buffer::New(buf_size); ASSERT_THAT(buf_result, IsOk()); auto buf = std::move(buf_result.value()); EXPECT_EQ(buf_size, buf->size()); EXPECT_EQ(buf_size, buf->allocated_size()); for (auto new_size : {0, 1, buf_size/2, buf_size}) { SCOPED_TRACE(absl::StrCat("new_size = ", buf_size)); ASSERT_THAT(buf->set_size(new_size), IsOk()); EXPECT_EQ(new_size, buf->size()); EXPECT_EQ(buf_size, buf->allocated_size()); auto data = subtle::Random::GetRandomBytes(new_size); std::memcpy(buf->get_mem_block(), data.data(), new_size); EXPECT_EQ(0, std::memcmp(data.data(), buf->get_mem_block(), new_size)); } } } TEST(BufferTest, NullMemoryBlock) { auto buf_result = Buffer::NewNonOwning(nullptr, 42); EXPECT_THAT(buf_result.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("non-null"))); } TEST(BufferTest, BadAllocatedSize_ExternalMemoryBlock) { for (auto allocated_size : {-10, -1, 0}) { SCOPED_TRACE(absl::StrCat("allocated_size = ", allocated_size)); auto mem_block = absl::make_unique(42); auto buf_result = Buffer::NewNonOwning(mem_block.get(), allocated_size); EXPECT_THAT(buf_result.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("allocated_size"))); } } TEST(BufferTest, BadAllocatedSize_InternalMemoryBlock) { for (auto allocated_size : {-10, -1, 0}) { SCOPED_TRACE(absl::StrCat("allocated_size = ", allocated_size)); auto buf_result = Buffer::New(allocated_size); EXPECT_THAT(buf_result.status(), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("allocated_size"))); } } TEST(BufferTest, BadNewSize_ExternalMemoryBlock) { for (auto buf_size : {1, 10, 100, 1000, 10000}) { SCOPED_TRACE(absl::StrCat("buf_size = ", buf_size)); auto buf = std::move(Buffer::New(buf_size).value()); for (auto new_size : {-10, -1, buf_size + 1, 2 * buf_size}) { SCOPED_TRACE(absl::StrCat("new_size = ", buf_size)); EXPECT_THAT(buf->set_size(new_size), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("new_size must satisfy"))); } } } TEST(BufferTest, BadNewSize_InternalMemoryBlock) { for (auto buf_size : {1, 10, 100, 1000, 10000}) { SCOPED_TRACE(absl::StrCat("buf_size = ", buf_size)); auto mem_block = absl::make_unique(buf_size); auto buf = std::move(Buffer::NewNonOwning(mem_block.get(), buf_size).value()); for (auto new_size : {-10, -1, buf_size + 1, 2 * buf_size}) { SCOPED_TRACE(absl::StrCat("new_size = ", buf_size)); EXPECT_THAT(buf->set_size(new_size), StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("new_size must satisfy"))); } } } } // namespace } // namespace util } // namespace tink } // namespace crypto ================================================ FILE: cc/util/constants.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/constants.h" #include "absl/base/attributes.h" namespace crypto { namespace tink { ABSL_CONST_INIT const char kTypeGoogleapisCom[] = "type.googleapis.com/"; } // namespace tink } // namespace crypto ================================================ FILE: cc/util/constants.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_UTIL_CONSTANTS_H_ #define TINK_UTIL_CONSTANTS_H_ namespace crypto { namespace tink { extern const char kTypeGoogleapisCom[]; } // namespace tink } // namespace crypto #endif // TINK_UTIL_CONSTANTS_H_ ================================================ FILE: cc/util/enums.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/enums.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/subtle/common_enums.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/common.pb.h" #include "proto/ecdsa.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace util { namespace pb = google::crypto::tink; // static pb::EllipticCurveType Enums::SubtleToProto(subtle::EllipticCurveType type) { switch (type) { case subtle::EllipticCurveType::NIST_P256: return pb::EllipticCurveType::NIST_P256; case subtle::EllipticCurveType::NIST_P384: return pb::EllipticCurveType::NIST_P384; case subtle::EllipticCurveType::NIST_P521: return pb::EllipticCurveType::NIST_P521; case subtle::EllipticCurveType::CURVE25519: return pb::EllipticCurveType::CURVE25519; default: return pb::EllipticCurveType::UNKNOWN_CURVE; } } // static subtle::EllipticCurveType Enums::ProtoToSubtle(pb::EllipticCurveType type) { switch (type) { case pb::EllipticCurveType::NIST_P256: return subtle::EllipticCurveType::NIST_P256; case pb::EllipticCurveType::NIST_P384: return subtle::EllipticCurveType::NIST_P384; case pb::EllipticCurveType::NIST_P521: return subtle::EllipticCurveType::NIST_P521; case pb::EllipticCurveType::CURVE25519: return subtle::EllipticCurveType::CURVE25519; default: return subtle::EllipticCurveType::UNKNOWN_CURVE; } } // static pb::EcPointFormat Enums::SubtleToProto(subtle::EcPointFormat format) { switch (format) { case subtle::EcPointFormat::UNCOMPRESSED: return pb::EcPointFormat::UNCOMPRESSED; case subtle::EcPointFormat::DO_NOT_USE_CRUNCHY_UNCOMPRESSED: return pb::EcPointFormat::DO_NOT_USE_CRUNCHY_UNCOMPRESSED; case subtle::EcPointFormat::COMPRESSED: return pb::EcPointFormat::COMPRESSED; default: return pb::EcPointFormat::UNKNOWN_FORMAT; } } // static subtle::EcPointFormat Enums::ProtoToSubtle(pb::EcPointFormat format) { switch (format) { case pb::EcPointFormat::UNCOMPRESSED: return subtle::EcPointFormat::UNCOMPRESSED; case pb::EcPointFormat::DO_NOT_USE_CRUNCHY_UNCOMPRESSED: return subtle::EcPointFormat::DO_NOT_USE_CRUNCHY_UNCOMPRESSED; case pb::EcPointFormat::COMPRESSED: return subtle::EcPointFormat::COMPRESSED; default: return subtle::EcPointFormat::UNKNOWN_FORMAT; } } // static pb::HashType Enums::SubtleToProto(subtle::HashType type) { switch (type) { case subtle::HashType::SHA1: return pb::HashType::SHA1; case subtle::HashType::SHA224: return pb::HashType::SHA224; case subtle::HashType::SHA256: return pb::HashType::SHA256; case subtle::HashType::SHA384: return pb::HashType::SHA384; case subtle::HashType::SHA512: return pb::HashType::SHA512; default: return pb::HashType::UNKNOWN_HASH; } } // static subtle::HashType Enums::ProtoToSubtle(pb::HashType type) { switch (type) { case pb::HashType::SHA1: return subtle::HashType::SHA1; case pb::HashType::SHA224: return subtle::HashType::SHA224; case pb::HashType::SHA256: return subtle::HashType::SHA256; case pb::HashType::SHA384: return subtle::HashType::SHA384; case pb::HashType::SHA512: return subtle::HashType::SHA512; default: return subtle::HashType::UNKNOWN_HASH; } } // static subtle::EcdsaSignatureEncoding Enums::ProtoToSubtle( pb::EcdsaSignatureEncoding encoding) { switch (encoding) { case pb::EcdsaSignatureEncoding::DER: return subtle::EcdsaSignatureEncoding::DER; case pb::EcdsaSignatureEncoding::IEEE_P1363: return subtle::EcdsaSignatureEncoding::IEEE_P1363; default: return subtle::EcdsaSignatureEncoding::UNKNOWN_ENCODING; } } // static pb::EcdsaSignatureEncoding Enums::SubtleToProto( subtle::EcdsaSignatureEncoding encoding) { switch (encoding) { case subtle::EcdsaSignatureEncoding::DER: return pb::EcdsaSignatureEncoding::DER; case subtle::EcdsaSignatureEncoding::IEEE_P1363: return pb::EcdsaSignatureEncoding::IEEE_P1363; default: return pb::EcdsaSignatureEncoding::UNKNOWN_ENCODING; } } // static const char* Enums::KeyStatusName(pb::KeyStatusType key_status_type) { switch (key_status_type) { case pb::KeyStatusType::ENABLED: return "ENABLED"; case pb::KeyStatusType::DISABLED: return "DISABLED"; case pb::KeyStatusType::DESTROYED: return "DESTROYED"; default: return "UNKNOWN_STATUS"; } } // static const char* Enums::HashName(pb::HashType hash_type) { switch (hash_type) { case pb::HashType::SHA1: return "SHA1"; case pb::HashType::SHA224: return "SHA224"; case pb::HashType::SHA256: return "SHA256"; case pb::HashType::SHA384: return "SHA384"; case pb::HashType::SHA512: return "SHA512"; default: return "UNKNOWN_HASH"; } } // static util::StatusOr Enums::HashLength(pb::HashType hash_type) { switch (hash_type) { case pb::HashType::SHA224: return 28; case pb::HashType::SHA256: return 32; case pb::HashType::SHA384: return 48; case pb::HashType::SHA512: return 64; default: return util::Status(absl::StatusCode::kInvalidArgument, absl::StrCat("Unsupported hashing algorithm ", util::Enums::HashName(hash_type))); } } // static const char* Enums::KeyMaterialName( pb::KeyData::KeyMaterialType key_material_type) { switch (key_material_type) { case pb::KeyData::SYMMETRIC: return "SYMMETRIC"; case pb::KeyData::ASYMMETRIC_PRIVATE: return "ASYMMETRIC_PRIVATE"; case pb::KeyData::ASYMMETRIC_PUBLIC: return "ASYMMETRIC_PUBLIC"; case pb::KeyData::REMOTE: return "REMOTE"; default: return "UNKNOWN_KEYMATERIAL"; } } // static const char* Enums::OutputPrefixName(pb::OutputPrefixType output_prefix_type) { switch (output_prefix_type) { case pb::OutputPrefixType::TINK: return "TINK"; case pb::OutputPrefixType::LEGACY: return "LEGACY"; case pb::OutputPrefixType::RAW: return "RAW"; case pb::OutputPrefixType::CRUNCHY: return "CRUNCHY"; default: return "UNKNOWN_PREFIX"; } } // static pb::KeyStatusType Enums::KeyStatus(absl::string_view name) { if (name == "ENABLED") return pb::KeyStatusType::ENABLED; if (name == "DISABLED") return pb::KeyStatusType::DISABLED; if (name == "DESTROYED") return pb::KeyStatusType::DESTROYED; return pb::KeyStatusType::UNKNOWN_STATUS; } // static pb::HashType Enums::Hash(absl::string_view name) { if (name == "SHA1") return pb::HashType::SHA1; if (name == "SHA224") return pb::HashType::SHA224; if (name == "SHA256") return pb::HashType::SHA256; if (name == "SHA384") return pb::HashType::SHA384; if (name == "SHA512") return pb::HashType::SHA512; return pb::HashType::UNKNOWN_HASH; } // static pb::KeyData::KeyMaterialType Enums::KeyMaterial(absl::string_view name) { if (name == "SYMMETRIC") return pb::KeyData::SYMMETRIC; if (name == "ASYMMETRIC_PRIVATE") return pb::KeyData::ASYMMETRIC_PRIVATE; if (name == "ASYMMETRIC_PUBLIC") return pb::KeyData::ASYMMETRIC_PUBLIC; if (name == "REMOTE") return pb::KeyData::REMOTE; return pb::KeyData::UNKNOWN_KEYMATERIAL; } // static pb::OutputPrefixType Enums::OutputPrefix(absl::string_view name) { if (name == "TINK") return pb::OutputPrefixType::TINK; if (name == "LEGACY") return pb::OutputPrefixType::LEGACY; if (name == "RAW") return pb::OutputPrefixType::RAW; if (name == "CRUNCHY") return pb::OutputPrefixType::CRUNCHY; return pb::OutputPrefixType::UNKNOWN_PREFIX; } } // namespace util } // namespace tink } // namespace crypto ================================================ FILE: cc/util/enums.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_UTIL_ENUMS_H_ #define TINK_UTIL_ENUMS_H_ #include "absl/strings/string_view.h" #include "tink/subtle/common_enums.h" #include "tink/util/statusor.h" #include "proto/common.pb.h" #include "proto/ecdsa.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace util { // Helpers for translation of common enums between protocol buffer enums, // their string representation, and common enums used in subtle. class Enums { public: // EllipticCurveType. static google::crypto::tink::EllipticCurveType SubtleToProto( crypto::tink::subtle::EllipticCurveType type); static crypto::tink::subtle::EllipticCurveType ProtoToSubtle( google::crypto::tink::EllipticCurveType type); // EcPointFormat. static google::crypto::tink::EcPointFormat SubtleToProto( crypto::tink::subtle::EcPointFormat format); static crypto::tink::subtle::EcPointFormat ProtoToSubtle( google::crypto::tink::EcPointFormat format); // HashType. static google::crypto::tink::HashType SubtleToProto( crypto::tink::subtle::HashType type); static crypto::tink::subtle::HashType ProtoToSubtle( google::crypto::tink::HashType type); // Returns the length in bytes of the given hash type `hash_type`. Returns // INVALID_ARGUMENT if the algorithm is unsupported. static util::StatusOr HashLength( google::crypto::tink::HashType hash_type); // EcdsaSignatureEncoding. static google::crypto::tink::EcdsaSignatureEncoding SubtleToProto( crypto::tink::subtle::EcdsaSignatureEncoding encoding); static crypto::tink::subtle::EcdsaSignatureEncoding ProtoToSubtle( google::crypto::tink::EcdsaSignatureEncoding encoding); // Printable names for common enums. static const char* KeyStatusName( google::crypto::tink::KeyStatusType key_status_type); static const char* HashName(google::crypto::tink::HashType hash_type); static const char* KeyMaterialName( google::crypto::tink::KeyData::KeyMaterialType key_material_type); static const char* OutputPrefixName( google::crypto::tink::OutputPrefixType output_prefix_type); static google::crypto::tink::KeyStatusType KeyStatus(absl::string_view name); static google::crypto::tink::HashType Hash(absl::string_view name); static google::crypto::tink::KeyData::KeyMaterialType KeyMaterial( absl::string_view name); static google::crypto::tink::OutputPrefixType OutputPrefix( absl::string_view name); }; } // namespace util } // namespace tink } // namespace crypto #endif // TINK_UTIL_ENUMS_H_ ================================================ FILE: cc/util/enums_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/enums.h" #include #include "gtest/gtest.h" #include "tink/subtle/common_enums.h" #include "proto/common.pb.h" #include "proto/ecdsa.pb.h" #include "proto/tink.pb.h" using crypto::tink::util::Enums; namespace crypto { namespace pb = google::crypto::tink; namespace tink { namespace { class EnumsTest : public ::testing::Test {}; TEST_F(EnumsTest, testEllipticCurveType) { EXPECT_EQ(pb::EllipticCurveType::NIST_P256, Enums::SubtleToProto(subtle::EllipticCurveType::NIST_P256)); EXPECT_EQ(pb::EllipticCurveType::NIST_P384, Enums::SubtleToProto(subtle::EllipticCurveType::NIST_P384)); EXPECT_EQ(pb::EllipticCurveType::NIST_P521, Enums::SubtleToProto(subtle::EllipticCurveType::NIST_P521)); EXPECT_EQ(pb::EllipticCurveType::CURVE25519, Enums::SubtleToProto(subtle::EllipticCurveType::CURVE25519)); EXPECT_EQ(pb::EllipticCurveType::UNKNOWN_CURVE, Enums::SubtleToProto(subtle::EllipticCurveType::UNKNOWN_CURVE)); EXPECT_EQ(subtle::EllipticCurveType::NIST_P256, Enums::ProtoToSubtle(pb::EllipticCurveType::NIST_P256)); EXPECT_EQ(subtle::EllipticCurveType::NIST_P384, Enums::ProtoToSubtle(pb::EllipticCurveType::NIST_P384)); EXPECT_EQ(subtle::EllipticCurveType::NIST_P521, Enums::ProtoToSubtle(pb::EllipticCurveType::NIST_P521)); EXPECT_EQ(subtle::EllipticCurveType::CURVE25519, Enums::ProtoToSubtle(pb::EllipticCurveType::CURVE25519)); EXPECT_EQ(subtle::EllipticCurveType::UNKNOWN_CURVE, Enums::ProtoToSubtle(pb::EllipticCurveType::UNKNOWN_CURVE)); // Check that enum conversion covers the entire range of the proto-enum. int count = 0; for (int int_type = static_cast(pb::EllipticCurveType_MIN); int_type <= static_cast(pb::EllipticCurveType_MAX); int_type++) { if (pb::EllipticCurveType_IsValid(int_type)) { pb::EllipticCurveType type = static_cast(int_type); EXPECT_EQ(type, Enums::SubtleToProto(Enums::ProtoToSubtle(type))); count++; } } EXPECT_EQ(5, count); } TEST_F(EnumsTest, testHashType) { EXPECT_EQ(pb::HashType::SHA1, Enums::SubtleToProto(subtle::HashType::SHA1)); EXPECT_EQ(pb::HashType::SHA224, Enums::SubtleToProto(subtle::HashType::SHA224)); EXPECT_EQ(pb::HashType::SHA256, Enums::SubtleToProto(subtle::HashType::SHA256)); EXPECT_EQ(pb::HashType::SHA384, Enums::SubtleToProto(subtle::HashType::SHA384)); EXPECT_EQ(pb::HashType::SHA512, Enums::SubtleToProto(subtle::HashType::SHA512)); EXPECT_EQ(pb::HashType::UNKNOWN_HASH, Enums::SubtleToProto(subtle::HashType::UNKNOWN_HASH)); EXPECT_EQ(subtle::HashType::SHA1, Enums::ProtoToSubtle(pb::HashType::SHA1)); EXPECT_EQ(subtle::HashType::SHA224, Enums::ProtoToSubtle(pb::HashType::SHA224)); EXPECT_EQ(subtle::HashType::SHA256, Enums::ProtoToSubtle(pb::HashType::SHA256)); EXPECT_EQ(subtle::HashType::SHA384, Enums::ProtoToSubtle(pb::HashType::SHA384)); EXPECT_EQ(subtle::HashType::SHA512, Enums::ProtoToSubtle(pb::HashType::SHA512)); EXPECT_EQ(subtle::HashType::UNKNOWN_HASH, Enums::ProtoToSubtle(pb::HashType::UNKNOWN_HASH)); // Check that enum conversion covers the entire range of the proto-enum. int count = 0; for (int int_type = static_cast(pb::HashType_MIN); int_type <= static_cast(pb::HashType_MAX); int_type++) { if (pb::HashType_IsValid(int_type)) { pb::HashType type = static_cast(int_type); EXPECT_EQ(type, Enums::SubtleToProto(Enums::ProtoToSubtle(type))); count++; } } EXPECT_EQ(6, count); } TEST_F(EnumsTest, testHashSize) { EXPECT_EQ(Enums::HashLength(pb::HashType::SHA256).value(), 32); EXPECT_EQ(Enums::HashLength(pb::HashType::SHA384).value(), 48); EXPECT_EQ(Enums::HashLength(pb::HashType::SHA512).value(), 64); EXPECT_TRUE(!Enums::HashLength(pb::HashType::UNKNOWN_HASH).ok()); EXPECT_TRUE(!Enums::HashLength(pb::HashType::SHA1).ok()); } TEST_F(EnumsTest, testEcPointFormat) { EXPECT_EQ(pb::EcPointFormat::UNCOMPRESSED, Enums::SubtleToProto(subtle::EcPointFormat::UNCOMPRESSED)); EXPECT_EQ(pb::EcPointFormat::DO_NOT_USE_CRUNCHY_UNCOMPRESSED, Enums::SubtleToProto( subtle::EcPointFormat::DO_NOT_USE_CRUNCHY_UNCOMPRESSED)); EXPECT_EQ(pb::EcPointFormat::COMPRESSED, Enums::SubtleToProto(subtle::EcPointFormat::COMPRESSED)); EXPECT_EQ(pb::EcPointFormat::UNKNOWN_FORMAT, Enums::SubtleToProto(subtle::EcPointFormat::UNKNOWN_FORMAT)); EXPECT_EQ(pb::EcPointFormat::UNKNOWN_FORMAT, Enums::SubtleToProto((subtle::EcPointFormat)42)); EXPECT_EQ(subtle::EcPointFormat::UNCOMPRESSED, Enums::ProtoToSubtle(pb::EcPointFormat::UNCOMPRESSED)); EXPECT_EQ( subtle::EcPointFormat::DO_NOT_USE_CRUNCHY_UNCOMPRESSED, Enums::ProtoToSubtle(pb::EcPointFormat::DO_NOT_USE_CRUNCHY_UNCOMPRESSED)); EXPECT_EQ(subtle::EcPointFormat::COMPRESSED, Enums::ProtoToSubtle(pb::EcPointFormat::COMPRESSED)); EXPECT_EQ(subtle::EcPointFormat::UNKNOWN_FORMAT, Enums::ProtoToSubtle(pb::EcPointFormat::UNKNOWN_FORMAT)); // Check that enum conversion covers the entire range of the proto-enum. int count = 0; for (int int_format = static_cast(pb::EcPointFormat_MIN); int_format <= static_cast(pb::EcPointFormat_MAX); int_format++) { if (pb::EcPointFormat_IsValid(int_format)) { pb::EcPointFormat format = static_cast(int_format); EXPECT_EQ(format, Enums::SubtleToProto(Enums::ProtoToSubtle(format))); count++; } } EXPECT_EQ(4, count); } TEST_F(EnumsTest, testEcdsaSignatureEncoding) { EXPECT_EQ( pb::EcdsaSignatureEncoding::UNKNOWN_ENCODING, Enums::SubtleToProto(subtle::EcdsaSignatureEncoding::UNKNOWN_ENCODING)); EXPECT_EQ(pb::EcdsaSignatureEncoding::IEEE_P1363, Enums::SubtleToProto(subtle::EcdsaSignatureEncoding::IEEE_P1363)); EXPECT_EQ(pb::EcdsaSignatureEncoding::DER, Enums::SubtleToProto(subtle::EcdsaSignatureEncoding::DER)); EXPECT_EQ(subtle::EcdsaSignatureEncoding::UNKNOWN_ENCODING, Enums::ProtoToSubtle(pb::EcdsaSignatureEncoding::UNKNOWN_ENCODING)); EXPECT_EQ(subtle::EcdsaSignatureEncoding::IEEE_P1363, Enums::ProtoToSubtle(pb::EcdsaSignatureEncoding::IEEE_P1363)); EXPECT_EQ(subtle::EcdsaSignatureEncoding::DER, Enums::ProtoToSubtle(pb::EcdsaSignatureEncoding::DER)); // Check that enum conversion covers the entire range of the proto-enum. int count = 0; for (int int_encoding = static_cast(pb::EcdsaSignatureEncoding_MIN); int_encoding <= static_cast(pb::EcdsaSignatureEncoding_MAX); int_encoding++) { if (pb::EcdsaSignatureEncoding_IsValid(int_encoding)) { pb::EcdsaSignatureEncoding encoding = static_cast(int_encoding); EXPECT_EQ(encoding, Enums::SubtleToProto(Enums::ProtoToSubtle(encoding))); count++; } } EXPECT_EQ(3, count); } TEST_F(EnumsTest, testKeyStatusName) { EXPECT_EQ("ENABLED", std::string(Enums::KeyStatusName(pb::KeyStatusType::ENABLED))); EXPECT_EQ("DISABLED", std::string(Enums::KeyStatusName(pb::KeyStatusType::DISABLED))); EXPECT_EQ("DESTROYED", std::string(Enums::KeyStatusName(pb::KeyStatusType::DESTROYED))); EXPECT_EQ( "UNKNOWN_STATUS", std::string(Enums::KeyStatusName(pb::KeyStatusType::UNKNOWN_STATUS))); EXPECT_EQ(pb::KeyStatusType::ENABLED, Enums::KeyStatus("ENABLED")); EXPECT_EQ(pb::KeyStatusType::DISABLED, Enums::KeyStatus("DISABLED")); EXPECT_EQ(pb::KeyStatusType::DESTROYED, Enums::KeyStatus("DESTROYED")); EXPECT_EQ(pb::KeyStatusType::UNKNOWN_STATUS, Enums::KeyStatus("Other string")); EXPECT_EQ(pb::KeyStatusType::UNKNOWN_STATUS, Enums::KeyStatus("UNKNOWN_STATUS")); // Check that enum conversion covers the entire range of the proto-enum. int count = 0; for (int int_status = static_cast(pb::KeyStatusType_MIN); int_status <= static_cast(pb::KeyStatusType_MAX); int_status++) { if (pb::KeyStatusType_IsValid(int_status)) { pb::KeyStatusType status = static_cast(int_status); EXPECT_EQ(status, Enums::KeyStatus(Enums::KeyStatusName(status))); count++; } } EXPECT_EQ(4, count); } TEST_F(EnumsTest, testHashName) { EXPECT_EQ("SHA1", std::string(Enums::HashName(pb::HashType::SHA1))); EXPECT_EQ("SHA256", std::string(Enums::HashName(pb::HashType::SHA256))); EXPECT_EQ("SHA512", std::string(Enums::HashName(pb::HashType::SHA512))); EXPECT_EQ("UNKNOWN_HASH", std::string(Enums::HashName(pb::HashType::UNKNOWN_HASH))); EXPECT_EQ("UNKNOWN_HASH", std::string(Enums::HashName((pb::HashType)42))); EXPECT_EQ(pb::HashType::SHA1, Enums::Hash("SHA1")); EXPECT_EQ(pb::HashType::SHA224, Enums::Hash("SHA224")); EXPECT_EQ(pb::HashType::SHA256, Enums::Hash("SHA256")); EXPECT_EQ(pb::HashType::SHA384, Enums::Hash("SHA384")); EXPECT_EQ(pb::HashType::SHA512, Enums::Hash("SHA512")); EXPECT_EQ(pb::HashType::UNKNOWN_HASH, Enums::Hash("Other string")); EXPECT_EQ(pb::HashType::UNKNOWN_HASH, Enums::Hash("UNKNOWN_HASH")); // Check that enum conversion covers the entire range of the proto-enum. int count = 0; for (int int_hash = static_cast(pb::HashType_MIN); int_hash <= static_cast(pb::HashType_MAX); int_hash++) { if (pb::HashType_IsValid(int_hash)) { pb::HashType hash = static_cast(int_hash); EXPECT_EQ(hash, Enums::Hash(Enums::HashName(hash))); count++; } } EXPECT_EQ(6, count); } TEST_F(EnumsTest, testKeyMaterialName) { EXPECT_EQ("SYMMETRIC", std::string(Enums::KeyMaterialName(pb::KeyData::SYMMETRIC))); EXPECT_EQ( "ASYMMETRIC_PRIVATE", std::string(Enums::KeyMaterialName(pb::KeyData::ASYMMETRIC_PRIVATE))); EXPECT_EQ( "ASYMMETRIC_PUBLIC", std::string(Enums::KeyMaterialName(pb::KeyData::ASYMMETRIC_PUBLIC))); EXPECT_EQ("REMOTE", std::string(Enums::KeyMaterialName(pb::KeyData::REMOTE))); EXPECT_EQ( "UNKNOWN_KEYMATERIAL", std::string(Enums::KeyMaterialName(pb::KeyData::UNKNOWN_KEYMATERIAL))); EXPECT_EQ( "UNKNOWN_KEYMATERIAL", std::string(Enums::KeyMaterialName((pb::KeyData::KeyMaterialType)42))); EXPECT_EQ(pb::KeyData::SYMMETRIC, Enums::KeyMaterial("SYMMETRIC")); EXPECT_EQ(pb::KeyData::ASYMMETRIC_PRIVATE, Enums::KeyMaterial("ASYMMETRIC_PRIVATE")); EXPECT_EQ(pb::KeyData::ASYMMETRIC_PUBLIC, Enums::KeyMaterial("ASYMMETRIC_PUBLIC")); EXPECT_EQ(pb::KeyData::REMOTE, Enums::KeyMaterial("REMOTE")); EXPECT_EQ(pb::KeyData::UNKNOWN_KEYMATERIAL, Enums::KeyMaterial("Other string")); EXPECT_EQ(pb::KeyData::UNKNOWN_KEYMATERIAL, Enums::KeyMaterial("UNKNOWN_KEYMATERIAL")); // Check that enum conversion covers the entire range of the proto-enum. int count = 0; for (int int_type = static_cast(pb::KeyData::KeyMaterialType_MIN); int_type <= static_cast(pb::KeyData::KeyMaterialType_MAX); int_type++) { if (pb::KeyData::KeyMaterialType_IsValid(int_type)) { pb::KeyData::KeyMaterialType type = static_cast(int_type); EXPECT_EQ(type, Enums::KeyMaterial(Enums::KeyMaterialName(type))); count++; } } EXPECT_EQ(5, count); } TEST_F(EnumsTest, testOutputPrefixName) { EXPECT_EQ("TINK", std::string(Enums::OutputPrefixName(pb::OutputPrefixType::TINK))); EXPECT_EQ("LEGACY", std::string(Enums::OutputPrefixName(pb::OutputPrefixType::LEGACY))); EXPECT_EQ("RAW", std::string(Enums::OutputPrefixName(pb::OutputPrefixType::RAW))); EXPECT_EQ( "CRUNCHY", std::string(Enums::OutputPrefixName(pb::OutputPrefixType::CRUNCHY))); EXPECT_EQ("UNKNOWN_PREFIX", std::string(Enums::OutputPrefixName( pb::OutputPrefixType::UNKNOWN_PREFIX))); EXPECT_EQ("UNKNOWN_PREFIX", std::string(Enums::OutputPrefixName((pb::OutputPrefixType)42))); EXPECT_EQ(pb::OutputPrefixType::TINK, Enums::OutputPrefix("TINK")); EXPECT_EQ(pb::OutputPrefixType::LEGACY, Enums::OutputPrefix("LEGACY")); EXPECT_EQ(pb::OutputPrefixType::RAW, Enums::OutputPrefix("RAW")); EXPECT_EQ(pb::OutputPrefixType::CRUNCHY, Enums::OutputPrefix("CRUNCHY")); EXPECT_EQ(pb::OutputPrefixType::UNKNOWN_PREFIX, Enums::OutputPrefix("Other string")); EXPECT_EQ(pb::OutputPrefixType::UNKNOWN_PREFIX, Enums::OutputPrefix("UNKNOWN_PREFIX")); // Check that enum conversion covers the entire range of the proto-enum. int count = 0; for (int int_type = static_cast(pb::OutputPrefixType_MIN); int_type <= static_cast(pb::OutputPrefixType_MAX); int_type++) { if (pb::OutputPrefixType_IsValid(int_type)) { pb::OutputPrefixType type = static_cast(int_type); EXPECT_EQ(type, Enums::OutputPrefix(Enums::OutputPrefixName(type))); count++; } } EXPECT_EQ(5, count); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/util/errors.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_UTIL_ERRORS_H_ #define TINK_UTIL_ERRORS_H_ #include "absl/status/status.h" #include "absl/strings/str_format.h" #include "tink/util/status.h" namespace crypto { namespace tink { // Constructs a Status with formatted error message using absl::StatusCode. template util::Status ToStatusF(absl::StatusCode code, const absl::FormatSpec& format, const Args&... args) { return util::Status(code, absl::StrFormat(format, args...)); } } // namespace tink } // namespace crypto #endif // TINK_UTIL_ERRORS_H_ ================================================ FILE: cc/util/errors_test.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/errors.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/util/status.h" namespace crypto { namespace tink { namespace { TEST(ErrorsTest, ToStatusFAbslStatusCodeTest) { const char* const msg = "test message %s 2 %d"; const char* expected_msg = "test message asdf 2 42"; util::Status status = ToStatusF(absl::StatusCode::kUnknown, msg, "asdf", 42); EXPECT_FALSE(status.ok()); EXPECT_EQ(expected_msg, status.message()); EXPECT_EQ(absl::StatusCode::kUnknown, status.code()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/util/fake_kms_client.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/fake_kms_client.h" #include #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/ascii.h" #include "absl/strings/escaping.h" #include "absl/strings/match.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/aead/aead_key_templates.h" #include "tink/binary_keyset_reader.h" #include "tink/binary_keyset_writer.h" #include "tink/cleartext_keyset_handle.h" #include "tink/config/global_registry.h" #include "tink/keyset_handle.h" #include "tink/kms_client.h" #include "tink/kms_clients.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace test { namespace { using crypto::tink::ToStatusF; using crypto::tink::util::Status; using crypto::tink::util::StatusOr; using google::crypto::tink::KeyTemplate; static constexpr char kKeyUriPrefix[] = "fake-kms://"; // Returns the encoded keyset contained in 'key_uri'. // If 'key_uri' does not refer to an fake KMS key, returns an empty string. std::string GetEncodedKeyset(absl::string_view key_uri) { if (!absl::StartsWithIgnoreCase(key_uri, kKeyUriPrefix)) return ""; return std::string(key_uri.substr(std::string(kKeyUriPrefix).length())); } } // namespace // static StatusOr> FakeKmsClient::New( absl::string_view key_uri, absl::string_view credentials_path) { std::unique_ptr client(new FakeKmsClient()); if (!key_uri.empty()) { client->encoded_keyset_ = GetEncodedKeyset(key_uri); if (client->encoded_keyset_.empty()) { return ToStatusF(absl::StatusCode::kInvalidArgument, "Key '%s' not supported", key_uri); } } return std::move(client); } bool FakeKmsClient::DoesSupport(absl::string_view key_uri) const { if (!encoded_keyset_.empty()) { return encoded_keyset_ == GetEncodedKeyset(key_uri); } return !GetEncodedKeyset(key_uri).empty(); } StatusOr> FakeKmsClient::GetAead( absl::string_view key_uri) const { if (!DoesSupport(key_uri)) { if (!encoded_keyset_.empty()) { return ToStatusF(absl::StatusCode::kInvalidArgument, "This client is bound to a different key, and cannot " "use key '%s'.", key_uri); } else { return ToStatusF(absl::StatusCode::kInvalidArgument, "This client does not support key '%s'.", key_uri); } } std::string keyset; if (!absl::WebSafeBase64Unescape(GetEncodedKeyset(key_uri), &keyset)) { return util::Status(absl::StatusCode::kInvalidArgument, "Invalid Keyset"); } auto reader_result = BinaryKeysetReader::New(keyset); if (!reader_result.ok()) { return reader_result.status(); } auto handle_result = CleartextKeysetHandle::Read(std::move(reader_result.value())); if (!handle_result.ok()) { return handle_result.status(); } return handle_result.value()->GetPrimitive( ConfigGlobalRegistry()); } Status FakeKmsClient::RegisterNewClient(absl::string_view key_uri, absl::string_view credentials_path) { auto client_result = FakeKmsClient::New(key_uri, credentials_path); if (!client_result.ok()) { return client_result.status(); } return KmsClients::Add(std::move(client_result.value())); } StatusOr FakeKmsClient::CreateFakeKeyUri() { // The key_uri contains an encoded keyset with a new Aes128Gcm key. const KeyTemplate& key_template = AeadKeyTemplates::Aes128Gcm(); auto handle_result = KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()); if (!handle_result.ok()) { return handle_result.status(); } std::stringbuf keyset; auto writer_result = BinaryKeysetWriter::New(absl::make_unique(&keyset)); if (!writer_result.ok()) { return writer_result.status(); } auto status = CleartextKeysetHandle::Write(writer_result.value().get(), *handle_result.value()); if (!status.ok()) { return status; } std::string encoded_keyset; absl::WebSafeBase64Escape(keyset.str(), &encoded_keyset); return absl::StrCat(kKeyUriPrefix, encoded_keyset); } } // namespace test } // namespace tink } // namespace crypto ================================================ FILE: cc/util/fake_kms_client.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_UTIL_FAKE_KMS_CLIENT_H_ #define TINK_UTIL_FAKE_KMS_CLIENT_H_ #include #include #include "absl/strings/string_view.h" #include "tink/aead.h" #include "tink/keyset_handle.h" #include "tink/kms_client.h" #include "tink/kms_clients.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace test { // FakeKmsClient is a fake implementation of KmsClient. // // Normally, the 'key_uri' identifies a key that is stored remotely by the KMS, // and every operation is executed remotely using a RPC call to the KMS, since // the key should not be sent to the client. // In this fake implementation we want to avoid these RPC calls. We achieve this // by encoding the key in the 'key_uri'. So the client simply needs to decode // the key and generate an AEAD out of it. This is of course insecure and should // only be used in testing. class FakeKmsClient : public crypto::tink::KmsClient { public: // Creates a new FakeKmsClient that is bound to the key specified in // 'key_uri'. // // Either of arguments can be empty. // If 'key_uri' is empty, then the client is not bound to any particular key. // credentials_path is ignored at the moment. static crypto::tink::util::StatusOr> New( absl::string_view key_uri, absl::string_view credentials_path); // Creates a new client and registers it in KMSClients. static crypto::tink::util::Status RegisterNewClient( absl::string_view key_uri, absl::string_view credentials_path); // Returns a new, random fake key_uri. static crypto::tink::util::StatusOr CreateFakeKeyUri(); // Returns true iff this client does support KMS key specified by 'key_uri'. bool DoesSupport(absl::string_view key_uri) const override; // Returns an Aead-primitive backed by KMS key specified by 'key_uri', // provided that this KmsClient does support 'key_uri'. crypto::tink::util::StatusOr> GetAead(absl::string_view key_uri) const override; private: FakeKmsClient() {} std::string encoded_keyset_; }; } // namespace test } // namespace tink } // namespace crypto #endif // TINK_UTIL_FAKE_KMS_CLIENT_H_ ================================================ FILE: cc/util/fake_kms_client_test.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "tink/util/fake_kms_client.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "tink/aead.h" #include "tink/aead/aead_config.h" #include "tink/aead/aead_key_templates.h" #include "tink/config/global_registry.h" #include "tink/keyset_handle.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" #include "proto/kms_aead.pb.h" #include "proto/kms_envelope.pb.h" #include "proto/tink.pb.h" using google::crypto::tink::KeyTemplate; using google::crypto::tink::KmsAeadKeyFormat; using google::crypto::tink::KmsEnvelopeAeadKeyFormat; using google::crypto::tink::OutputPrefixType; namespace crypto { namespace tink { namespace test { namespace { // TODO(b/174740983) Add this function to aead_key_templates. KeyTemplate NewKmsAeadKeyTemplate(std::string key_uri) { KeyTemplate key_template; key_template.set_type_url( "type.googleapis.com/google.crypto.tink.KmsAeadKey"); key_template.set_output_prefix_type(OutputPrefixType::TINK); KmsAeadKeyFormat key_format; key_format.set_key_uri(key_uri); key_format.SerializeToString(key_template.mutable_value()); return key_template; } // TODO(b/174740983) Add this function to aead_key_templates. KeyTemplate NewKmsEnvelopeKeyTemplate(std::string key_uri, const KeyTemplate& dek_template) { KeyTemplate key_template; key_template.set_type_url( "type.googleapis.com/google.crypto.tink.KmsEnvelopeAeadKey"); key_template.set_output_prefix_type(OutputPrefixType::TINK); KmsEnvelopeAeadKeyFormat key_format; key_format.set_kek_uri(key_uri); key_format.mutable_dek_template()->MergeFrom(dek_template); key_format.SerializeToString(key_template.mutable_value()); return key_template; } class FakeKmsClientTest : public ::testing::Test { protected: static void SetUpTestSuite() { ASSERT_TRUE(AeadConfig::Register().ok()); } }; TEST_F(FakeKmsClientTest, CreateNewAeadSuccess) { auto uri_result = FakeKmsClient::CreateFakeKeyUri(); EXPECT_TRUE(uri_result.ok()) << uri_result.status(); std::string key_uri = uri_result.value(); auto client_result = FakeKmsClient::New(key_uri, ""); EXPECT_TRUE(client_result.ok()) << client_result.status(); auto client = std::move(client_result.value()); EXPECT_TRUE(client->DoesSupport(key_uri)); auto aead_result = client->GetAead(key_uri); EXPECT_TRUE(aead_result.ok()) << aead_result.status(); auto aead = std::move(aead_result.value()); std::string plaintext = "some_plaintext"; std::string aad = "some_aad"; auto encrypt_result = aead->Encrypt(plaintext, aad); EXPECT_TRUE(encrypt_result.ok()) << encrypt_result.status(); std::string ciphertext = encrypt_result.value(); auto decrypt_result = aead->Decrypt(ciphertext, aad); EXPECT_TRUE(decrypt_result.ok()) << decrypt_result.status(); EXPECT_EQ(plaintext, decrypt_result.value()); } TEST_F(FakeKmsClientTest, ClientIsBound) { std::string key_uri = "fake-kms://" "CL3oi0kSVwpMCjB0eXBlLmdvb2dsZWFwaXMuY29tL2dvb2dsZS5jcnlwdG8udGluay5BZXNF" "YXhLZXkSFhICCBAaEPFnQNgtxEG0vEek8bBfgL8YARABGL3oi0kgAQ"; auto client_result = FakeKmsClient::New(key_uri, ""); EXPECT_TRUE(client_result.ok()) << client_result.status(); auto client = std::move(client_result.value()); // No other key_uri is accepted, even a valid one. std::string another_key_uri = "fake-kms://" "CO3y2NgHElgKTAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuQWVz" "RWF4S2V5EhYSAggQGhALi4dQMjUR0faRYElRXi__GAEQARjt8tjYByAB"; EXPECT_FALSE(client->DoesSupport(another_key_uri)); auto aead_result = client->GetAead(another_key_uri); EXPECT_FALSE(aead_result.ok()); } TEST_F(FakeKmsClientTest, ClientIsUnbound) { auto client_result = FakeKmsClient::New("", ""); EXPECT_TRUE(client_result.ok()) << client_result.status(); auto client = std::move(client_result.value()); // All valid 'fake-kms' key_uris are accepted. std::string uri = "fake-kms://" "CL3oi0kSVwpMCjB0eXBlLmdvb2dsZWFwaXMuY29tL2dvb2dsZS5jcnlwdG8udGluay5BZXNF" "YXhLZXkSFhICCBAaEPFnQNgtxEG0vEek8bBfgL8YARABGL3oi0kgAQ"; EXPECT_TRUE(client->DoesSupport(uri)); auto aead_result = client->GetAead(uri); EXPECT_TRUE(aead_result.ok()); std::string another_uri = "fake-kms://" "CO3y2NgHElgKTAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuQWVz" "RWF4S2V5EhYSAggQGhALi4dQMjUR0faRYElRXi__GAEQARjt8tjYByAB"; EXPECT_TRUE(client->DoesSupport(another_uri)); auto another_aead_result = client->GetAead(another_uri); EXPECT_TRUE(another_aead_result.ok()) << another_aead_result.status(); } TEST_F(FakeKmsClientTest, RegisterAndEncryptDecryptWithKmsAead) { auto uri_result = FakeKmsClient::CreateFakeKeyUri(); EXPECT_TRUE(uri_result.ok()) << uri_result.status(); std::string key_uri = uri_result.value(); auto status = FakeKmsClient::RegisterNewClient(key_uri, ""); EXPECT_THAT(status, IsOk()); KeyTemplate key_template = NewKmsAeadKeyTemplate(key_uri); auto handle_result = KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()); EXPECT_TRUE(handle_result.ok()) << handle_result.status(); auto aead_result = handle_result.value()->GetPrimitive( ConfigGlobalRegistry()); EXPECT_TRUE(aead_result.ok()) << aead_result.status(); auto aead = std::move(aead_result.value()); std::string plaintext = "some_plaintext"; std::string aad = "some_aad"; auto encrypt_result = aead->Encrypt(plaintext, aad); EXPECT_TRUE(encrypt_result.ok()) << encrypt_result.status(); std::string ciphertext = encrypt_result.value(); auto decrypt_result = aead->Decrypt(ciphertext, aad); EXPECT_TRUE(decrypt_result.ok()) << decrypt_result.status(); EXPECT_EQ(plaintext, decrypt_result.value()); } TEST_F(FakeKmsClientTest, RegisterAndEncryptDecryptWithKmsEnvelopeAead) { auto uri_result = FakeKmsClient::CreateFakeKeyUri(); EXPECT_TRUE(uri_result.ok()) << uri_result.status(); std::string key_uri = uri_result.value(); auto status = FakeKmsClient::RegisterNewClient(key_uri, ""); EXPECT_THAT(status, IsOk()); KeyTemplate key_template = NewKmsEnvelopeKeyTemplate(key_uri, AeadKeyTemplates::Aes128Gcm()); auto handle_result = KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry()); EXPECT_TRUE(handle_result.ok()) << handle_result.status(); auto aead_result = handle_result.value()->GetPrimitive( ConfigGlobalRegistry()); EXPECT_TRUE(aead_result.ok()) << aead_result.status(); auto aead = std::move(aead_result.value()); std::string plaintext = "some_plaintext"; std::string aad = "some_aad"; auto encrypt_result = aead->Encrypt(plaintext, aad); EXPECT_TRUE(encrypt_result.ok()) << encrypt_result.status(); std::string ciphertext = encrypt_result.value(); auto decrypt_result = aead->Decrypt(ciphertext, aad); EXPECT_TRUE(decrypt_result.ok()) << decrypt_result.status(); EXPECT_EQ(plaintext, decrypt_result.value()); } // TODO(b/174740983): Add test where an unbounded KeyClient is registered. // This is not yet implemented as it would break the isolation of the tests: // Once a unbounded client is registered, it can't currently be unregistered. } // namespace } // namespace test } // namespace tink } // namespace crypto ================================================ FILE: cc/util/file_input_stream.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/file_input_stream.h" #include #include #include #include #include #include "absl/status/status.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace util { namespace { constexpr int kDefaultBufferSize = 128 * 1024; // Attempts to close file descriptor fd, while ignoring EINTR. // (code borrowed from ZeroCopy-streams) int close_ignoring_eintr(int fd) { int result; do { result = close(fd); } while (result < 0 && errno == EINTR); return result; } // Attempts to read 'count' bytes of data data from file descriptor fd // to 'buf' while ignoring EINTR. int read_ignoring_eintr(int fd, void *buf, size_t count) { int result; do { result = read(fd, buf, count); } while (result < 0 && errno == EINTR); return result; } } // anonymous namespace FileInputStream::FileInputStream(int file_descriptor, int buffer_size) : status_(util::OkStatus()), fd_(file_descriptor), buffer_(buffer_size > 0 ? buffer_size : kDefaultBufferSize) {} util::StatusOr FileInputStream::Next(const void** data) { if (data == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "Data pointer must not be nullptr"); } if (!status_.ok()) return status_; if (count_backedup_ > 0) { // Return the backed-up bytes. buffer_offset_ = buffer_offset_ + (count_in_buffer_ - count_backedup_); count_in_buffer_ = count_backedup_; count_backedup_ = 0; *data = buffer_.data() + buffer_offset_; position_ = position_ + count_in_buffer_; return count_in_buffer_; } // Read new bytes to buffer_. int read_result = read_ignoring_eintr(fd_, buffer_.data(), buffer_.size()); if (read_result <= 0) { // EOF or an I/O error. if (read_result == 0) { status_ = Status(absl::StatusCode::kOutOfRange, "EOF"); } else { status_ = ToStatusF(absl::StatusCode::kInternal, "I/O error: %d", read_result); } return status_; } buffer_offset_ = 0; count_backedup_ = 0; count_in_buffer_ = read_result; position_ = position_ + count_in_buffer_; *data = buffer_.data(); return count_in_buffer_; } void FileInputStream::BackUp(int count) { if (!status_.ok() || count < 1 || count_backedup_ == count_in_buffer_) return; int actual_count = std::min(count, count_in_buffer_ - count_backedup_); count_backedup_ = count_backedup_ + actual_count; position_ = position_ - actual_count; } FileInputStream::~FileInputStream() { close_ignoring_eintr(fd_); } int64_t FileInputStream::Position() const { return position_; } } // namespace util } // namespace tink } // namespace crypto ================================================ FILE: cc/util/file_input_stream.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_UTIL_FILE_INPUT_STREAM_H_ #define TINK_UTIL_FILE_INPUT_STREAM_H_ #include #include #include #include "tink/input_stream.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace util { // An InputStream that reads from a file descriptor. // // NOTE: This class in not available when building on Windows. class FileInputStream : public crypto::tink::InputStream { public: // Constructs an InputStream that will read from the file specified // via `file_descriptor`, using a buffer of the specified size, if any // (if no legal `buffer_size` is given, a reasonable default will be used). // Takes the ownership of the file, and will close it upon destruction. explicit FileInputStream(int file_descriptor, int buffer_size = -1); ~FileInputStream() override; crypto::tink::util::StatusOr Next(const void** data) override; void BackUp(int count) override; int64_t Position() const override; private: // Status of the stream. util::Status status_ = util::OkStatus(); int fd_; std::vector buffer_; // Current position in the stream (from the beginning). int64_t position_ = 0; // Counters that describe the state of the data in buffer_. // # of bytes available in buffer_. int count_in_buffer_ = 0; // # of bytes available in buffer_ that were backed up. int count_backedup_ = 0; // offset at which the returned bytes start in buffer_. int buffer_offset_ = 0; }; } // namespace util } // namespace tink } // namespace crypto #endif // TINK_UTIL_FILE_INPUT_STREAM_H_ ================================================ FILE: cc/util/file_input_stream_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/file_input_stream.h" #include #include #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/internal/test_file_util.h" #include "tink/subtle/random.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::IsOkAndHolds; using ::crypto::tink::test::StatusIs; constexpr int kDefaultTestStreamSize = 100 * 1024; // 100 KB. // Opens test file `filename` and returns a file descriptor to it. util::StatusOr OpenTestFileToRead(absl::string_view filename) { std::string full_filename = absl::StrCat(test::TmpDir(), "/", filename); int fd = open(full_filename.c_str(), O_RDONLY); if (fd == -1) { return util::Status(absl::StatusCode::kInternal, absl::StrCat("Cannot open file ", full_filename, " error: ", std::strerror(errno))); } return fd; } // Reads the specified `input_stream` until no more bytes can be read, // and puts the read bytes into `contents`. // Returns the status of the last input_stream->Next()-operation. util::Status ReadAll(util::FileInputStream* input_stream, std::string* contents) { contents->clear(); const void* buffer; auto next_result = input_stream->Next(&buffer); while (next_result.ok()) { contents->append(static_cast(buffer), next_result.value()); next_result = input_stream->Next(&buffer); } return next_result.status(); } using FileInputStreamTestDefaultBufferSize = testing::TestWithParam; TEST_P(FileInputStreamTestDefaultBufferSize, ReadAllfFromInputStreamSucceeds) { int stream_size = GetParam(); SCOPED_TRACE(absl::StrCat("stream_size = ", stream_size)); std::string file_contents = subtle::Random::GetRandomBytes(stream_size); std::string filename = absl::StrCat( stream_size, "_", internal::GetTestFileNamePrefix(), "_file.bin"); ASSERT_THAT(internal::CreateTestFile(filename, file_contents), IsOk()); util::StatusOr input_fd = OpenTestFileToRead(filename); ASSERT_THAT(input_fd.status(), IsOk()); EXPECT_EQ(stream_size, file_contents.size()); auto input_stream = absl::make_unique(*input_fd); std::string stream_contents; auto status = ReadAll(input_stream.get(), &stream_contents); EXPECT_THAT(status, StatusIs(absl::StatusCode::kOutOfRange)); EXPECT_EQ(status.message(), "EOF"); EXPECT_EQ(file_contents, stream_contents); } INSTANTIATE_TEST_SUITE_P(FileInputStreamTest, FileInputStreamTestDefaultBufferSize, testing::ValuesIn({0, 10, 100, 1000, 10000, 100000, 1000000})); using FileInputStreamTestCustomBufferSizes = testing::TestWithParam; TEST_P(FileInputStreamTestCustomBufferSizes, ReadAllWithCustomBufferSizeSucceeds) { int buffer_size = GetParam(); SCOPED_TRACE(absl::StrCat("buffer_size = ", buffer_size)); std::string file_contents = subtle::Random::GetRandomBytes(kDefaultTestStreamSize); std::string filename = absl::StrCat( buffer_size, "_", internal::GetTestFileNamePrefix(), "_file.bin"); ASSERT_THAT(internal::CreateTestFile(filename, file_contents), IsOk()); util::StatusOr input_fd = OpenTestFileToRead(filename); ASSERT_THAT(input_fd.status(), IsOk()); EXPECT_EQ(kDefaultTestStreamSize, file_contents.size()); auto input_stream = absl::make_unique(*input_fd, buffer_size); const void* buffer; auto next_result = input_stream->Next(&buffer); ASSERT_THAT(next_result, IsOk()); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(file_contents.substr(0, buffer_size), std::string(static_cast(buffer), buffer_size)); } INSTANTIATE_TEST_SUITE_P(FileInputStreamTest, FileInputStreamTestCustomBufferSizes, testing::ValuesIn({1, 10, 100, 1000, 10000})); TEST(FileInputStreamTest, NextFailsIfFdIsInvalid) { int buffer_size = 4 * 1024; auto input_stream = absl::make_unique(-1, buffer_size); const void* buffer = nullptr; EXPECT_THAT(input_stream->Next(&buffer).status(), StatusIs(absl::StatusCode::kInternal)); } TEST(FileInputStreamTest, NextFailsIfDataIsNull) { int buffer_size = 4 * 1024; std::string file_contents = subtle::Random::GetRandomBytes(kDefaultTestStreamSize); std::string filename = absl::StrCat( buffer_size, "_", internal::GetTestFileNamePrefix(), "_file.bin"); ASSERT_THAT(internal::CreateTestFile(filename, file_contents), IsOk()); util::StatusOr input_fd = OpenTestFileToRead(filename); ASSERT_THAT(input_fd.status(), IsOk()); EXPECT_EQ(kDefaultTestStreamSize, file_contents.size()); auto input_stream = absl::make_unique(*input_fd, buffer_size); EXPECT_THAT(input_stream->Next(nullptr).status(), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(FileInputStreamTest, NextReadsExactlyOneBlockOfData) { int buffer_size = 4 * 1024; std::string file_contents = subtle::Random::GetRandomBytes(kDefaultTestStreamSize); std::string filename = absl::StrCat( buffer_size, "_", internal::GetTestFileNamePrefix(), "_file.bin"); ASSERT_THAT(internal::CreateTestFile(filename, file_contents), IsOk()); util::StatusOr input_fd = OpenTestFileToRead(filename); ASSERT_THAT(input_fd.status(), IsOk()); EXPECT_EQ(kDefaultTestStreamSize, file_contents.size()); auto input_stream = absl::make_unique(*input_fd, buffer_size); auto expected_file_content_block = absl::string_view(file_contents).substr(0, buffer_size); const void* buffer = nullptr; util::StatusOr next_result = input_stream->Next(&buffer); ASSERT_THAT(next_result, IsOkAndHolds(buffer_size)); // Check that we advanced of buffer_size bytes. EXPECT_EQ(input_stream->Position(), buffer_size); EXPECT_EQ(absl::string_view(static_cast(buffer), buffer_size), expected_file_content_block); } TEST(FileInputStreamTest, BackupForNegativeOrZeroBytesIsANoop) { int buffer_size = 4 * 1024; std::string file_contents = subtle::Random::GetRandomBytes(kDefaultTestStreamSize); std::string filename = absl::StrCat( buffer_size, "_", internal::GetTestFileNamePrefix(), "_file.bin"); ASSERT_THAT(internal::CreateTestFile(filename, file_contents), IsOk()); util::StatusOr input_fd = OpenTestFileToRead(filename); ASSERT_THAT(input_fd.status(), IsOk()); EXPECT_EQ(kDefaultTestStreamSize, file_contents.size()); auto input_stream = absl::make_unique(*input_fd, buffer_size); EXPECT_EQ(input_stream->Position(), 0); auto expected_file_content_block = absl::string_view(file_contents).substr(0, buffer_size); const void* buffer = nullptr; ASSERT_THAT(input_stream->Next(&buffer), IsOkAndHolds(buffer_size)); // Check that we advanced of buffer_size bytes. EXPECT_EQ(input_stream->Position(), buffer_size); EXPECT_EQ(absl::string_view(static_cast(buffer), buffer_size), expected_file_content_block); // The calls below are noops. input_stream->BackUp(0); EXPECT_EQ(input_stream->Position(), buffer_size); input_stream->BackUp(-12); EXPECT_EQ(input_stream->Position(), buffer_size); // A subsequent call to `Next` returns the 2nd block. auto expected_2nd_file_content_block = absl::string_view(file_contents).substr(buffer_size, buffer_size); ASSERT_THAT(input_stream->Next(&buffer), IsOkAndHolds(buffer_size)); // Check that we advanced of buffer_size bytes. EXPECT_EQ(input_stream->Position(), 2 * buffer_size); EXPECT_EQ(absl::string_view(static_cast(buffer), buffer_size), expected_2nd_file_content_block); } TEST(FileInputStreamTest, BackupForLessThanOneBlockOfData) { int buffer_size = 4 * 1024; std::string file_contents = subtle::Random::GetRandomBytes(kDefaultTestStreamSize); std::string filename = absl::StrCat( buffer_size, "_", internal::GetTestFileNamePrefix(), "_file.bin"); ASSERT_THAT(internal::CreateTestFile(filename, file_contents), IsOk()); util::StatusOr input_fd = OpenTestFileToRead(filename); ASSERT_THAT(input_fd.status(), IsOk()); EXPECT_EQ(kDefaultTestStreamSize, file_contents.size()); auto input_stream = absl::make_unique(*input_fd, buffer_size); auto expected_file_content_block = absl::string_view(file_contents).substr(0, buffer_size); const void* buffer = nullptr; ASSERT_THAT(input_stream->Next(&buffer), IsOkAndHolds(buffer_size)); // Check that we advanced of buffer_size bytes. EXPECT_EQ(input_stream->Position(), buffer_size); EXPECT_EQ(absl::string_view(static_cast(buffer), buffer_size), expected_file_content_block); int64_t position_after_next = input_stream->Position(); // Number of bytes that were backed up. int num_backed_up_bytes = 0; input_stream->BackUp(0); // This should be a noop. EXPECT_EQ(input_stream->Position(), position_after_next); input_stream->BackUp(-12); // This should be a noop. EXPECT_EQ(input_stream->Position(), position_after_next); input_stream->BackUp(10); num_backed_up_bytes += 10; EXPECT_EQ(input_stream->Position(), position_after_next - num_backed_up_bytes); input_stream->BackUp(5); num_backed_up_bytes += 5; EXPECT_EQ(input_stream->Position(), position_after_next - num_backed_up_bytes); // A subsequent call to Next should return only the backed up bytes. auto expected_backed_up_bytes = absl::string_view(file_contents) .substr(buffer_size - num_backed_up_bytes, num_backed_up_bytes); ASSERT_THAT(input_stream->Next(&buffer), IsOkAndHolds(expected_backed_up_bytes.size())); EXPECT_EQ(absl::string_view(static_cast(buffer), expected_backed_up_bytes.size()), expected_backed_up_bytes); } // When backing up of a number of bytes larger than the size of a block, backup // of one block. TEST(FileInputStreamTest, BackupAtMostOfOneBlock) { int buffer_size = 4 * 1024; std::string file_contents = subtle::Random::GetRandomBytes(kDefaultTestStreamSize); std::string filename = absl::StrCat( buffer_size, "_", internal::GetTestFileNamePrefix(), "_file.bin"); ASSERT_THAT(internal::CreateTestFile(filename, file_contents), IsOk()); util::StatusOr input_fd = OpenTestFileToRead(filename); ASSERT_THAT(input_fd.status(), IsOk()); EXPECT_EQ(kDefaultTestStreamSize, file_contents.size()); auto input_stream = absl::make_unique(*input_fd, buffer_size); // Read two blocks of size buffer_size, then back up of more than buffer_size // bytes. auto expected_1st_file_content_block = absl::string_view(file_contents).substr(0, buffer_size); const void* buffer = nullptr; ASSERT_THAT(input_stream->Next(&buffer), IsOkAndHolds(buffer_size)); // Check that we advanced of buffer_size bytes. EXPECT_EQ(input_stream->Position(), buffer_size); EXPECT_EQ(absl::string_view(static_cast(buffer), buffer_size), expected_1st_file_content_block); auto expected_2nd_file_content_block = absl::string_view(file_contents).substr(buffer_size, buffer_size); ASSERT_THAT(input_stream->Next(&buffer), IsOkAndHolds(buffer_size)); // Check that we advanced of buffer_size bytes. EXPECT_EQ(input_stream->Position(), 2 * buffer_size); EXPECT_EQ(absl::string_view(static_cast(buffer), buffer_size), expected_2nd_file_content_block); int64_t position_after_next = input_stream->Position(); EXPECT_EQ(input_stream->Position(), position_after_next); input_stream->BackUp(10); EXPECT_EQ(input_stream->Position(), position_after_next - 10); input_stream->BackUp(buffer_size); EXPECT_EQ(input_stream->Position(), position_after_next - buffer_size); // This call to Next is expected to read the second block again. ASSERT_THAT(input_stream->Next(&buffer), IsOkAndHolds(buffer_size)); EXPECT_EQ(absl::string_view(static_cast(buffer), buffer_size), expected_2nd_file_content_block); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/util/file_output_stream.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/file_output_stream.h" #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/output_stream.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace util { namespace { // Attempts to close file descriptor fd, while ignoring EINTR. // (code borrowed from ZeroCopy-streams) int close_ignoring_eintr(int fd) { int result; do { result = close(fd); } while (result < 0 && errno == EINTR); return result; } // Attempts to write 'count' bytes of data data from 'buf' // to file descriptor fd, while ignoring EINTR. int write_ignoring_eintr(int fd, const void *buf, size_t count) { int result; do { result = write(fd, buf, count); } while (result < 0 && errno == EINTR); return result; } } // anonymous namespace FileOutputStream::FileOutputStream(int file_descriptor, int buffer_size) : buffer_size_(buffer_size > 0 ? buffer_size : 128 * 1024) { // 128 KB fd_ = file_descriptor; count_in_buffer_ = 0; count_backedup_ = 0; buffer_ = nullptr; position_ = 0; buffer_offset_ = 0; status_ = OkStatus(); } crypto::tink::util::StatusOr FileOutputStream::Next(void** data) { if (!status_.ok()) return status_; if (buffer_ == nullptr) { // possible only at the first call to Next() buffer_ = absl::make_unique(buffer_size_); *data = buffer_.get(); count_in_buffer_ = buffer_size_; position_ = buffer_size_; return buffer_size_; } // If some space was backed up, return it first. if (count_backedup_ > 0) { position_ = position_ + count_backedup_; buffer_offset_ = count_in_buffer_; count_in_buffer_ = count_in_buffer_ + count_backedup_; int backedup = count_backedup_; count_backedup_ = 0; *data = buffer_.get() + buffer_offset_; return backedup; } // No space was backed up, so count_in_buffer_ == buffer_size_ holds here. // Write the data from the buffer, and return available space in buffer_. // The available space might not span the entire buffer_, as writing // may succeed only for a prefix of buffer_ -- in this case the data still // to be written is shifted in buffer_ and the remaining space is returned. int write_result = write_ignoring_eintr(fd_, buffer_.get(), buffer_size_); if (write_result <= 0) { // No data written or an I/O error occurred. if (write_result == 0) { return 0; } status_ = ToStatusF(absl::StatusCode::kInternal, "I/O error upon write: %d", errno); return status_; } // Some data was written, so we can return some portion of buffer_. position_ = position_ + write_result; count_in_buffer_ = buffer_size_; count_backedup_ = 0; buffer_offset_ = buffer_size_ - write_result; *data = buffer_.get() + buffer_offset_; if (write_result < buffer_size_) { // Only part of the data was written, shift the remaining data in buffer_. // Using memmove, as source and destination may overlap. std::memmove(buffer_.get(), buffer_.get() + write_result, buffer_offset_); } return write_result; } void FileOutputStream::BackUp(int count) { if (!status_.ok() || count < 1 || count_in_buffer_ == 0) return; int curr_buffer_size = buffer_size_ - buffer_offset_; int actual_count = std::min(count, curr_buffer_size - count_backedup_); count_backedup_ += actual_count; count_in_buffer_ -= actual_count; position_ -= actual_count; } FileOutputStream::~FileOutputStream() { Close().IgnoreError(); } Status FileOutputStream::Close() { if (!status_.ok()) return status_; if (count_in_buffer_ > 0) { // Try to write the remaining bytes. int total_written = 0; while (total_written < count_in_buffer_) { int write_result = write_ignoring_eintr( fd_, buffer_.get() + total_written, count_in_buffer_ - total_written); if (write_result < 0) { // An I/O error occurred. status_ = ToStatusF(absl::StatusCode::kInternal, "I/O error upon write: %d", errno); return status_; } else if (write_result == 0) { // No progress, hence abort. status_ = ToStatusF(absl::StatusCode::kInternal, "I/O error: failed to write %d bytes before closing.", count_in_buffer_ - total_written); return status_; } // Managed to write some bytes, hence continue. total_written += write_result; } } if (close_ignoring_eintr(fd_) == -1) { status_ = ToStatusF(absl::StatusCode::kInternal, "I/O error upon close: %d", errno); return status_; } status_ = Status(absl::StatusCode::kFailedPrecondition, "Stream closed"); return OkStatus(); } int64_t FileOutputStream::Position() const { return position_; } } // namespace util } // namespace tink } // namespace crypto ================================================ FILE: cc/util/file_output_stream.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_UTIL_FILE_OUTPUT_STREAM_H_ #define TINK_UTIL_FILE_OUTPUT_STREAM_H_ #include #include #include "tink/output_stream.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace util { // An OutputStream that writes to a file descriptor. // // NOTE: This class in not available when building on Windows. class FileOutputStream : public crypto::tink::OutputStream { public: // Constructs an OutputStream that will write to the file specified // via 'file_descriptor', using a buffer of the specified size, if any // (if no legal 'buffer_size' is given, a reasonable default will be used). // Takes the ownership of the file, and will close it upon destruction. explicit FileOutputStream(int file_descriptor, int buffer_size = -1); ~FileOutputStream() override; crypto::tink::util::StatusOr Next(void** data) override; void BackUp(int count) override; crypto::tink::util::Status Close() override; int64_t Position() const override; private: util::Status status_; int fd_; std::unique_ptr buffer_; const int buffer_size_; int64_t position_; // current position in the file (from the beginning) // Counters that describe the state of the data in buffer_. // count_in_buffer_ is always equal to (buffer_size_ - count_backedup_), // except initially (before the first call to Next()). // In other words, we have an invariant: // (count_in_buffer_ == buffer_size_ - count_backedup_) || buffer_ == nullptr int count_in_buffer_; // # bytes in buffer_ that will be eventually written int count_backedup_; // # bytes in buffer_ that were backed up int buffer_offset_; // offset where the returned *data starts in buffer_ }; } // namespace util } // namespace tink } // namespace crypto #endif // TINK_UTIL_FILE_OUTPUT_STREAM_H_ ================================================ FILE: cc/util/file_output_stream_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/file_output_stream.h" #include #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/internal/test_file_util.h" #include "tink/subtle/random.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; // Opens test file `filename` and returns a file descriptor to it. util::StatusOr OpenTestFileToWrite(absl::string_view filename) { std::string full_filename = absl::StrCat(test::TmpDir(), "/", filename); mode_t mode = S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH; int fd = open(full_filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, mode); if (fd == -1) { return util::Status(absl::StatusCode::kInternal, absl::StrCat("Cannot open file ", full_filename, " error: ", std::strerror(errno))); } return fd; } // Writes 'contents' the specified 'output_stream', and closes the stream. // Returns the status of output_stream->Close()-operation, or a non-OK status // of a prior output_stream->Next()-operation, if any. util::Status WriteToStream(util::FileOutputStream* output_stream, absl::string_view contents) { void* buffer; int pos = 0; int remaining = contents.length(); int available_space = 0; int available_bytes = 0; while (remaining > 0) { auto next_result = output_stream->Next(&buffer); if (!next_result.ok()) return next_result.status(); available_space = next_result.value(); available_bytes = std::min(available_space, remaining); memcpy(buffer, contents.data() + pos, available_bytes); remaining -= available_bytes; pos += available_bytes; } if (available_space > available_bytes) { output_stream->BackUp(available_space - available_bytes); } return output_stream->Close(); } class FileOutputStreamTest : public ::testing::Test { }; TEST_F(FileOutputStreamTest, WritingStreams) { for (auto stream_size : {0, 10, 100, 1000, 10000, 100000, 1000000}) { SCOPED_TRACE(absl::StrCat("stream_size = ", stream_size)); std::string stream_contents = subtle::Random::GetRandomBytes(stream_size); std::string filename = absl::StrCat( stream_size, internal::GetTestFileNamePrefix(), "_test.bin"); ASSERT_THAT(internal::CreateTestFile(filename, stream_contents), IsOk()); util::StatusOr output_fd = OpenTestFileToWrite(filename); ASSERT_THAT(output_fd.status(), IsOk()); auto output_stream = absl::make_unique(*output_fd); auto status = WriteToStream(output_stream.get(), stream_contents); EXPECT_TRUE(status.ok()) << status; std::string file_contents = test::ReadTestFile(filename); EXPECT_EQ(stream_size, file_contents.size()); EXPECT_EQ(stream_contents, file_contents); } } TEST_F(FileOutputStreamTest, CustomBufferSizes) { int stream_size = 1024 * 1024; std::string stream_contents = subtle::Random::GetRandomBytes(stream_size); for (auto buffer_size : {1, 10, 100, 1000, 10000, 100000, 1000000}) { SCOPED_TRACE(absl::StrCat("buffer_size = ", buffer_size)); std::string filename = absl::StrCat( buffer_size, internal::GetTestFileNamePrefix(), "_test.bin"); ASSERT_THAT(internal::CreateTestFile(filename, stream_contents), IsOk()); util::StatusOr output_fd = OpenTestFileToWrite(filename); ASSERT_THAT(output_fd.status(), IsOk()); auto output_stream = absl::make_unique(*output_fd, buffer_size); void* buffer; auto next_result = output_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); output_stream->BackUp(buffer_size); auto status = WriteToStream(output_stream.get(), stream_contents); EXPECT_TRUE(status.ok()) << status; std::string file_contents = test::ReadTestFile(filename); EXPECT_EQ(stream_size, file_contents.size()); EXPECT_EQ(stream_contents, file_contents); } } TEST_F(FileOutputStreamTest, BackupAndPosition) { int stream_size = 1024 * 1024; int buffer_size = 1234; void* buffer; std::string stream_contents = subtle::Random::GetRandomBytes(stream_size); std::string filename = absl::StrCat(buffer_size, internal::GetTestFileNamePrefix(), "_test.bin"); ASSERT_THAT(internal::CreateTestFile(filename, stream_contents), IsOk()); util::StatusOr output_fd = OpenTestFileToWrite(filename); ASSERT_THAT(output_fd.status(), IsOk()); // Prepare the stream and do the first call to Next(). auto output_stream = absl::make_unique(*output_fd, buffer_size); EXPECT_EQ(0, output_stream->Position()); auto next_result = output_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(buffer_size, output_stream->Position()); std::memcpy(buffer, stream_contents.data(), buffer_size); // BackUp several times, but in total fewer bytes than returned by Next(). int total_backup_size = 0; for (auto backup_size : {0, 1, 5, 0, 10, 100, -42, 400, 20, -100}) { SCOPED_TRACE(absl::StrCat("backup_size = ", backup_size)); output_stream->BackUp(backup_size); total_backup_size += std::max(0, backup_size); EXPECT_EQ(buffer_size - total_backup_size, output_stream->Position()); } EXPECT_LT(total_backup_size, next_result.value()); // Call Next(), it should succeed. next_result = output_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); // BackUp() some bytes, again fewer than returned by Next(). total_backup_size = 0; for (auto backup_size : {0, 72, -94, 37, 82}) { SCOPED_TRACE(absl::StrCat("backup_size = ", backup_size)); output_stream->BackUp(backup_size); total_backup_size += std::max(0, backup_size); EXPECT_EQ(buffer_size - total_backup_size, output_stream->Position()); } EXPECT_LT(total_backup_size, next_result.value()); // Call Next(), it should succeed; next_result = output_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); // Call Next() again, it should return a full block. auto prev_position = output_stream->Position(); next_result = output_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(prev_position + buffer_size, output_stream->Position()); std::memcpy(buffer, stream_contents.data() + buffer_size, buffer_size); // BackUp a few times, with total over the returned buffer_size. total_backup_size = 0; for (auto backup_size : {0, 72, -100, buffer_size / 2, 200, -25, buffer_size / 2, 42}) { SCOPED_TRACE(absl::StrCat("backup_size = ", backup_size)); output_stream->BackUp(backup_size); total_backup_size = std::min(buffer_size, total_backup_size + std::max(0, backup_size)); EXPECT_EQ(prev_position + buffer_size - total_backup_size, output_stream->Position()); } EXPECT_EQ(total_backup_size, buffer_size); EXPECT_EQ(prev_position, output_stream->Position()); // Call Next() again, it should return a full block. next_result = output_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(prev_position + buffer_size, output_stream->Position()); std::memcpy(buffer, stream_contents.data() + buffer_size, buffer_size); // Write the remaining stream contents to stream. auto status = WriteToStream( output_stream.get(), stream_contents.substr(output_stream->Position())); EXPECT_TRUE(status.ok()) << status; std::string file_contents = test::ReadTestFile(filename); EXPECT_EQ(stream_size, file_contents.size()); EXPECT_EQ(stream_contents, file_contents); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/util/file_random_access_stream.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/file_random_access_stream.h" #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/random_access_stream.h" #include "tink/util/buffer.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace util { using crypto::tink::util::Status; using crypto::tink::util::StatusOr; namespace { // Attempts to close file descriptor fd, while ignoring EINTR. // (code borrowed from ZeroCopy-streams) int close_ignoring_eintr(int fd) { int result; do { result = close(fd); } while (result < 0 && errno == EINTR); return result; } } // anonymous namespace FileRandomAccessStream::FileRandomAccessStream(int file_descriptor) { fd_ = file_descriptor; } Status FileRandomAccessStream::PRead(int64_t position, int count, Buffer* dest_buffer) { if (dest_buffer == nullptr) { return util::Status(absl::StatusCode::kInvalidArgument, "dest_buffer must be non-null"); } if (count <= 0) { return util::Status(absl::StatusCode::kInvalidArgument, "count must be positive"); } if (count > dest_buffer->allocated_size()) { return util::Status(absl::StatusCode::kInvalidArgument, "buffer too small"); } if (position < 0) { return util::Status(absl::StatusCode::kInvalidArgument, "position cannot be negative"); } crypto::tink::util::Status status = dest_buffer->set_size(count); if (!status.ok()) return status; int read_count = pread(fd_, dest_buffer->get_mem_block(), count, position); if (read_count == 0) { dest_buffer->set_size(0).IgnoreError(); return Status(absl::StatusCode::kOutOfRange, "EOF"); } if (read_count < 0) { dest_buffer->set_size(0).IgnoreError(); return ToStatusF(absl::StatusCode::kUnknown, "I/O error: %d", errno); } status = dest_buffer->set_size(read_count); if (!status.ok()) return status; return util::OkStatus(); } FileRandomAccessStream::~FileRandomAccessStream() { close_ignoring_eintr(fd_); } StatusOr FileRandomAccessStream::size() { struct stat s; if (fstat(fd_, &s) == -1) { return Status(absl::StatusCode::kUnavailable, "size unavailable"); } else { return s.st_size; } } } // namespace util } // namespace tink } // namespace crypto ================================================ FILE: cc/util/file_random_access_stream.h ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_UTIL_FILE_RANDOM_ACCESS_STREAM_H_ #define TINK_UTIL_FILE_RANDOM_ACCESS_STREAM_H_ #include #include #include "tink/random_access_stream.h" #include "tink/util/buffer.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace util { // An RandomAccessStream that reads from a file descriptor. // // NOTE: This class in not available when building on Windows. class FileRandomAccessStream : public crypto::tink::RandomAccessStream { public: // Constructs a FileRandomAccessStream that will read from the file specified // via 'file_descriptor'. // Takes the ownership of the file, and will close it upon destruction. explicit FileRandomAccessStream(int file_descriptor); ~FileRandomAccessStream() override; crypto::tink::util::Status PRead(int64_t position, int count, Buffer* dest_buffer) override; crypto::tink::util::StatusOr size() override; private: int fd_; }; } // namespace util } // namespace tink } // namespace crypto #endif // TINK_UTIL_FILE_RANDOM_ACCESS_STREAM_H_ ================================================ FILE: cc/util/file_random_access_stream_test.cc ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/file_random_access_stream.h" #include #include #include #include #include #include #include #include #include // NOLINT(build/c++11) #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/internal/test_file_util.h" #include "tink/random_access_stream.h" #include "tink/subtle/random.h" #include "tink/util/buffer.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace util { namespace { using ::crypto::tink::test::IsOk; // Opens test file `filename` and returns a file descriptor to it. util::StatusOr OpenTestFileToRead(absl::string_view filename) { std::string full_filename = absl::StrCat(test::TmpDir(), "/", filename); int fd = open(full_filename.c_str(), O_RDONLY); if (fd == -1) { return util::Status(absl::StatusCode::kInternal, absl::StrCat("Cannot open file ", full_filename, " error: ", std::strerror(errno))); } return fd; } // Reads the entire 'ra_stream' in chunks of size 'chunk_size', // until no more bytes can be read, and puts the read bytes into 'contents'. // Returns the status of the last ra_stream->Next()-operation. util::Status ReadAll(RandomAccessStream* ra_stream, int chunk_size, std::string* contents) { contents->clear(); auto buffer = std::move(Buffer::New(chunk_size).value()); int64_t position = 0; auto status = ra_stream->PRead(position, chunk_size, buffer.get()); while (status.ok()) { contents->append(buffer->get_mem_block(), buffer->size()); position = contents->size(); status = ra_stream->PRead(position, chunk_size, buffer.get()); } if (status.code() == absl::StatusCode::kOutOfRange) { // EOF EXPECT_EQ(0, buffer->size()); } return status; } // Reads from 'ra_stream' a chunk of 'count' bytes starting offset 'position', // and compares the read bytes to the corresponding bytes in 'file_contents'. void ReadAndVerifyChunk(RandomAccessStream* ra_stream, int64_t position, int count, absl::string_view file_contents) { SCOPED_TRACE(absl::StrCat("stream_size = ", file_contents.size(), ", position = ", position, ", count = ", count)); auto buffer = std::move(Buffer::New(count).value()); int stream_size = ra_stream->size().value(); EXPECT_EQ(file_contents.size(), stream_size); auto status = ra_stream->PRead(position, count, buffer.get()); EXPECT_TRUE(status.ok()); int read_count = buffer->size(); int expected_count = count; if (position + count > stream_size) { expected_count = stream_size - position; } EXPECT_EQ(expected_count, read_count); EXPECT_EQ(0, memcmp(&file_contents[position], buffer->get_mem_block(), read_count)); } TEST(FileRandomAccessStreamTest, ReadingStreams) { for (auto stream_size : {1, 10, 100, 1000, 10000, 1000000}) { SCOPED_TRACE(absl::StrCat("stream_size = ", stream_size)); std::string file_contents = subtle::Random::GetRandomBytes(stream_size); std::string filename = absl::StrCat( stream_size, crypto::tink::internal::GetTestFileNamePrefix(), "_file.bin"); ASSERT_THAT(crypto::tink::internal::CreateTestFile(filename, file_contents), IsOk()); util::StatusOr input_fd = OpenTestFileToRead(filename); ASSERT_THAT(input_fd.status(), IsOk()); EXPECT_EQ(stream_size, file_contents.size()); auto ra_stream = absl::make_unique(*input_fd); std::string stream_contents; auto status = ReadAll(ra_stream.get(), 1 + (stream_size / 10), &stream_contents); EXPECT_EQ(absl::StatusCode::kOutOfRange, status.code()); EXPECT_EQ("EOF", status.message()); EXPECT_EQ(file_contents, stream_contents); EXPECT_EQ(stream_size, ra_stream->size().value()); } } TEST(FileRandomAccessStreamTest, ReadingStreamsTillLastByte) { for (auto stream_size : {1, 10, 100, 1000, 10000}) { SCOPED_TRACE(absl::StrCat("stream_size = ", stream_size)); std::string file_contents = subtle::Random::GetRandomBytes(stream_size); std::string filename = absl::StrCat( stream_size, crypto::tink::internal::GetTestFileNamePrefix(), "_file.bin"); ASSERT_THAT(crypto::tink::internal::CreateTestFile(filename, file_contents), IsOk()); util::StatusOr input_fd = OpenTestFileToRead(filename); ASSERT_THAT(input_fd.status(), IsOk()); EXPECT_EQ(stream_size, file_contents.size()); auto ra_stream = absl::make_unique(*input_fd); auto buffer = std::move(Buffer::New(stream_size).value()); // Read from the beginning till the last byte. auto status = ra_stream->PRead(/* position = */ 0, stream_size, buffer.get()); EXPECT_TRUE(status.ok()); EXPECT_EQ(stream_size, ra_stream->size().value()); EXPECT_EQ(0, memcmp(&file_contents[0], buffer->get_mem_block(), stream_size)); } } TEST(FileRandomAccessStreamTest, ConcurrentReads) { for (auto stream_size : {100, 1000, 10000, 100000}) { std::string file_contents = subtle::Random::GetRandomBytes(stream_size); std::string filename = absl::StrCat( stream_size, crypto::tink::internal::GetTestFileNamePrefix(), "_file.bin"); ASSERT_THAT(crypto::tink::internal::CreateTestFile(filename, file_contents), IsOk()); util::StatusOr input_fd = OpenTestFileToRead(filename); ASSERT_THAT(input_fd.status(), IsOk()); EXPECT_EQ(stream_size, file_contents.size()); auto ra_stream = absl::make_unique(*input_fd); std::thread read_0(ReadAndVerifyChunk, ra_stream.get(), 0, stream_size / 2, file_contents); std::thread read_1(ReadAndVerifyChunk, ra_stream.get(), stream_size / 4, stream_size / 2, file_contents); std::thread read_2(ReadAndVerifyChunk, ra_stream.get(), stream_size / 2, stream_size / 2, file_contents); std::thread read_3(ReadAndVerifyChunk, ra_stream.get(), 3 * stream_size / 4, stream_size / 2, file_contents); read_0.join(); read_1.join(); read_2.join(); read_3.join(); } } TEST(FileRandomAccessStreamTest, NegativeReadPosition) { for (auto stream_size : {0, 10, 100, 1000, 10000}) { std::string file_contents = subtle::Random::GetRandomBytes(stream_size); std::string filename = absl::StrCat( stream_size, crypto::tink::internal::GetTestFileNamePrefix(), "_file.bin"); ASSERT_THAT(crypto::tink::internal::CreateTestFile(filename, file_contents), IsOk()); util::StatusOr input_fd = OpenTestFileToRead(filename); ASSERT_THAT(input_fd.status(), IsOk()); auto ra_stream = absl::make_unique(*input_fd); int count = 42; auto buffer = std::move(Buffer::New(count).value()); for (auto position : {-100, -10, -1}) { SCOPED_TRACE(absl::StrCat("stream_size = ", stream_size, " position = ", position)); auto status = ra_stream->PRead(position, count, buffer.get()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, status.code()); } } } TEST(FileRandomAccessStreamTest, NotPositiveReadCount) { for (auto stream_size : {0, 10, 100, 1000, 10000}) { std::string file_contents = subtle::Random::GetRandomBytes(stream_size); std::string filename = absl::StrCat( stream_size, crypto::tink::internal::GetTestFileNamePrefix(), "_file.bin"); ASSERT_THAT(crypto::tink::internal::CreateTestFile(filename, file_contents), IsOk()); util::StatusOr input_fd = OpenTestFileToRead(filename); ASSERT_THAT(input_fd.status(), IsOk()); auto ra_stream = absl::make_unique(*input_fd); auto buffer = std::move(Buffer::New(42).value()); int64_t position = 0; for (auto count : {-100, -10, -1, 0}) { SCOPED_TRACE(absl::StrCat("stream_size = ", stream_size, " count = ", count)); auto status = ra_stream->PRead(position, count, buffer.get()); EXPECT_EQ(absl::StatusCode::kInvalidArgument, status.code()); } } } TEST(FileRandomAccessStreamTest, ReadPositionAfterEof) { for (auto stream_size : {0, 10, 100, 1000, 10000}) { std::string file_contents = subtle::Random::GetRandomBytes(stream_size); std::string filename = absl::StrCat( stream_size, crypto::tink::internal::GetTestFileNamePrefix(), "_file.bin"); ASSERT_THAT(crypto::tink::internal::CreateTestFile(filename, file_contents), IsOk()); util::StatusOr input_fd = OpenTestFileToRead(filename); ASSERT_THAT(input_fd.status(), IsOk()); auto ra_stream = absl::make_unique(*input_fd); int count = 42; auto buffer = std::move(Buffer::New(count).value()); for (auto position : {stream_size + 1, stream_size + 10}) { SCOPED_TRACE(absl::StrCat("stream_size = ", stream_size, " position = ", position)); auto status = ra_stream->PRead(position, count, buffer.get()); EXPECT_EQ(absl::StatusCode::kOutOfRange, status.code()); EXPECT_EQ(0, buffer->size()); } } } } // namespace } // namespace util } // namespace tink } // namespace crypto ================================================ FILE: cc/util/input_stream_util.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/input_stream_util.h" #include #include #include "absl/algorithm/container.h" #include "absl/strings/str_cat.h" #include "absl/types/span.h" #include "tink/input_stream.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace { template util::StatusOr ReadBytesFromStreamImpl(int num_bytes, InputStream* input_stream) { const void* buffer; Result result; if (num_bytes > 0) { result.resize(num_bytes); } int num_bytes_read = 0; while (num_bytes_read < num_bytes) { auto next_result = input_stream->Next(&buffer); if (!next_result.ok()) return next_result.status(); int num_bytes_in_chunk = next_result.value(); int num_bytes_to_copy = std::min(num_bytes - num_bytes_read, num_bytes_in_chunk); absl::c_copy(absl::MakeSpan(reinterpret_cast(buffer), num_bytes_to_copy), result.begin() + num_bytes_read); input_stream->BackUp(num_bytes_in_chunk - num_bytes_to_copy); num_bytes_read += num_bytes_to_copy; } return result; } } // namespace util::StatusOr ReadBytesFromStream(int num_bytes, InputStream* input_stream) { return ReadBytesFromStreamImpl(num_bytes, input_stream); } util::StatusOr ReadSecretBytesFromStream( int num_bytes, InputStream* input_stream) { return ReadBytesFromStreamImpl(num_bytes, input_stream); } } // namespace tink } // namespace crypto ================================================ FILE: cc/util/input_stream_util.h ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_UTIL_INPUT_STREAM_UTIL_H_ #define TINK_UTIL_INPUT_STREAM_UTIL_H_ #include #include "tink/input_stream.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { // A utility function which reads num_bytes from the given input stream, calling // Next repeatedly until 'num_bytes' are obtained. All stream errors are // propagated. This can loop indefinitely (in case Next() repeatedly returns 0). util::StatusOr ReadBytesFromStream(int num_bytes, InputStream* input_stream); // A SecretData variant of ReadBytesFromStream util::StatusOr ReadSecretBytesFromStream( int num_bytes, InputStream* input_stream); } // namespace tink } // namespace crypto #endif // TINK_UTIL_INPUT_STREAM_UTIL_H_ ================================================ FILE: cc/util/input_stream_util_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/input_stream_util.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/util/istream_input_stream.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/test_matchers.h" namespace crypto { namespace tink { namespace { using ::crypto::tink::test::IsOk; using ::crypto::tink::test::StatusIs; using ::crypto::tink::util::IstreamInputStream; using ::testing::Eq; TEST(ReadBytesTest, ReadExact) { const std::string content = "Some content"; IstreamInputStream input_stream{ absl::make_unique(content)}; auto text_or = ReadBytesFromStream(content.size(), &input_stream); ASSERT_THAT(text_or, IsOk()); std::string text = std::move(text_or).value(); EXPECT_THAT(text, Eq(content)); } TEST(ReadBytesTest, ShortRead) { IstreamInputStream input_stream{ absl::make_unique("Some content")}; auto text_or = ReadBytesFromStream(100, &input_stream); EXPECT_THAT(text_or.status(), StatusIs(absl::StatusCode::kOutOfRange)); } TEST(ReadBytesTest, ReadLess) { IstreamInputStream input_stream{ absl::make_unique("0123456789abcdefghijklmnop")}; auto text_or = ReadBytesFromStream(7, &input_stream); ASSERT_THAT(text_or, IsOk()); EXPECT_THAT(text_or.value(), Eq("0123456")); } TEST(ReadBytesTest, ReadTwice) { IstreamInputStream input_stream{ absl::make_unique("0123456789abcdefghijklmnop")}; auto text_or = ReadBytesFromStream(7, &input_stream); ASSERT_THAT(text_or, IsOk()); EXPECT_THAT(text_or.value(), Eq("0123456")); text_or = ReadBytesFromStream(5, &input_stream); ASSERT_THAT(text_or, IsOk()); EXPECT_THAT(text_or.value(), Eq("789ab")); } TEST(ReadBytesTest, ReadMoreThanBlockSize) { // Use a block size of 4 such that ReadAtMost has to call the input multiple // times. IstreamInputStream input_stream{ absl::make_unique("0123456789abcdefghijklmnop"), 4}; auto text_or = ReadBytesFromStream(11, &input_stream); ASSERT_THAT(text_or, IsOk()); EXPECT_THAT(text_or.value(), Eq("0123456789a")); text_or = ReadBytesFromStream(5, &input_stream); ASSERT_THAT(text_or, IsOk()); EXPECT_THAT(text_or.value(), Eq("bcdef")); } TEST(ReadBytesTest, Request0) { IstreamInputStream input_stream( absl::make_unique("012345678")); auto text_or = ReadBytesFromStream(4, &input_stream); ASSERT_THAT(text_or, IsOk()); EXPECT_THAT(text_or.value(), Eq("0123")); text_or = ReadBytesFromStream(0, &input_stream); ASSERT_THAT(text_or, IsOk()); EXPECT_THAT(text_or.value(), Eq("")); text_or = ReadBytesFromStream(5, &input_stream); ASSERT_THAT(text_or, IsOk()); EXPECT_THAT(text_or.value(), Eq("45678")); text_or = ReadBytesFromStream(0, &input_stream); ASSERT_THAT(text_or, IsOk()); EXPECT_THAT(text_or.value(), Eq("")); } TEST(ReadBytesTest, RequestNegative) { IstreamInputStream input_stream( absl::make_unique("012345678")); auto text_or = ReadBytesFromStream(-1, &input_stream); ASSERT_THAT(text_or, IsOk()); EXPECT_THAT(text_or.value(), Eq("")); } TEST(ReadBytesTest, EmptyInput) { IstreamInputStream input_stream(absl::make_unique("")); auto text_or = ReadBytesFromStream(0, &input_stream); ASSERT_THAT(text_or, IsOk()); EXPECT_THAT(text_or.value(), Eq("")); text_or = ReadBytesFromStream(1, &input_stream); EXPECT_THAT(text_or.status(), StatusIs(absl::StatusCode::kOutOfRange)); } TEST(ReadSecretBytesTest, ReadExact) { const std::string content = "Some content"; IstreamInputStream input_stream{ absl::make_unique(content)}; auto text_or = ReadSecretBytesFromStream(content.size(), &input_stream); ASSERT_THAT(text_or, IsOk()); std::string text(util::SecretDataAsStringView(std::move(text_or).value())); EXPECT_THAT(text, Eq(content)); } TEST(ReadSecretBytesTest, ShortRead) { IstreamInputStream input_stream{ absl::make_unique("Some content")}; auto text_or = ReadSecretBytesFromStream(100, &input_stream); EXPECT_THAT(text_or.status(), StatusIs(absl::StatusCode::kOutOfRange)); } TEST(ReadSecretBytesTest, ReadLess) { IstreamInputStream input_stream{ absl::make_unique("0123456789abcdefghijklmnop")}; auto text_or = ReadSecretBytesFromStream(7, &input_stream); ASSERT_THAT(text_or, IsOk()); std::string text(util::SecretDataAsStringView(std::move(text_or).value())); EXPECT_THAT(text, Eq("0123456")); } TEST(ReadSecretBytesTest, ReadTwice) { IstreamInputStream input_stream{ absl::make_unique("0123456789abcdefghijklmnop")}; auto text_or = ReadSecretBytesFromStream(7, &input_stream); std::string text(util::SecretDataAsStringView(std::move(text_or).value())); EXPECT_THAT(text, Eq("0123456")); text_or = ReadSecretBytesFromStream(5, &input_stream); ASSERT_THAT(text_or, IsOk()); text = std::string(util::SecretDataAsStringView(std::move(text_or).value())); EXPECT_THAT(text, Eq("789ab")); } TEST(ReadSecretBytesTest, ReadMoreThanBlockSize) { // Use a block size of 4 such that ReadAtMost has to call the input multiple // times. IstreamInputStream input_stream{ absl::make_unique("0123456789abcdefghijklmnop"), 4}; auto text_or = ReadSecretBytesFromStream(11, &input_stream); ASSERT_THAT(text_or, IsOk()); std::string text(util::SecretDataAsStringView(std::move(text_or).value())); EXPECT_THAT(text, Eq("0123456789a")); text_or = ReadSecretBytesFromStream(5, &input_stream); ASSERT_THAT(text_or, IsOk()); text = std::string(util::SecretDataAsStringView(std::move(text_or).value())); EXPECT_THAT(text, Eq("bcdef")); } TEST(ReadSecretBytesTest, Request0) { IstreamInputStream input_stream( absl::make_unique("012345678")); auto text_or = ReadSecretBytesFromStream(4, &input_stream); ASSERT_THAT(text_or, IsOk()); std::string text(util::SecretDataAsStringView(std::move(text_or).value())); EXPECT_THAT(text, Eq("0123")); text_or = ReadSecretBytesFromStream(0, &input_stream); ASSERT_THAT(text_or, IsOk()); text = std::string(util::SecretDataAsStringView(std::move(text_or).value())); EXPECT_THAT(text, Eq("")); text_or = ReadSecretBytesFromStream(5, &input_stream); ASSERT_THAT(text_or, IsOk()); text = std::string(util::SecretDataAsStringView(std::move(text_or).value())); EXPECT_THAT(text, Eq("45678")); text_or = ReadSecretBytesFromStream(0, &input_stream); ASSERT_THAT(text_or, IsOk()); text = std::string(util::SecretDataAsStringView(std::move(text_or).value())); EXPECT_THAT(text, Eq("")); } TEST(ReadSecretBytesTest, RequestNegative) { IstreamInputStream input_stream( absl::make_unique("012345678")); auto text_or = ReadSecretBytesFromStream(-1, &input_stream); ASSERT_THAT(text_or, IsOk()); std::string text(util::SecretDataAsStringView(std::move(text_or).value())); EXPECT_THAT(text, Eq("")); } TEST(ReadSecretBytesTest, EmptyInput) { IstreamInputStream input_stream( absl::make_unique("")); auto text_or = ReadSecretBytesFromStream(0, &input_stream); ASSERT_THAT(text_or, IsOk()); std::string text(util::SecretDataAsStringView(std::move(text_or).value())); EXPECT_THAT(text, Eq("")); text_or = ReadSecretBytesFromStream(1, &input_stream); EXPECT_THAT(text_or.status(), StatusIs(absl::StatusCode::kOutOfRange)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/util/istream_input_stream.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/istream_input_stream.h" #include #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace util { IstreamInputStream::IstreamInputStream(std::unique_ptr input, int buffer_size) : buffer_size_(buffer_size > 0 ? buffer_size : 128 * 1024) { // 128 KB input_ = std::move(input); count_in_buffer_ = 0; count_backedup_ = 0; position_ = 0; buffer_ = absl::make_unique(buffer_size_); buffer_offset_ = 0; status_ = util::OkStatus(); } crypto::tink::util::StatusOr IstreamInputStream::Next(const void** data) { if (!status_.ok()) return status_; if (count_backedup_ > 0) { // Return the backed-up bytes. buffer_offset_ = buffer_offset_ + (count_in_buffer_ - count_backedup_); count_in_buffer_ = count_backedup_; count_backedup_ = 0; *data = buffer_.get() + buffer_offset_; position_ = position_ + count_in_buffer_; return count_in_buffer_; } // Read new bytes to buffer_. input_->read(reinterpret_cast(buffer_.get()), buffer_size_); int count_read = input_->gcount(); if (count_read == 0) { // Could not read bytes, EOF or an I/O error. if (input_->good()) return count_read; // No bytes could be read. // If !good(), distinguish EOF from other failures. if (input_->eof()) { status_ = Status(absl::StatusCode::kOutOfRange, "EOF"); } else { status_ = ToStatusF(absl::StatusCode::kInternal, "I/O error: %s", strerror(errno)); } return status_; } buffer_offset_ = 0; count_backedup_ = 0; count_in_buffer_ = count_read; position_ = position_ + count_in_buffer_; *data = buffer_.get(); return count_in_buffer_; } void IstreamInputStream::BackUp(int count) { if (!status_.ok() || count < 1 || count_backedup_ == count_in_buffer_) return; int actual_count = std::min(count, count_in_buffer_ - count_backedup_); count_backedup_ = count_backedup_ + actual_count; position_ = position_ - actual_count; } IstreamInputStream::~IstreamInputStream() = default; int64_t IstreamInputStream::Position() const { return position_; } } // namespace util } // namespace tink } // namespace crypto ================================================ FILE: cc/util/istream_input_stream.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_UTIL_ISTREAM_INPUT_STREAM_H_ #define TINK_UTIL_ISTREAM_INPUT_STREAM_H_ #include #include #include #include "tink/input_stream.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace util { // An InputStream that reads from a std::istream. class IstreamInputStream : public crypto::tink::InputStream { public: // Constructs an InputStream that will read from the 'input' istream, // using a buffer of the specified size, if any (if no legal 'buffer_size' // is given, a reasonable default will be used). explicit IstreamInputStream(std::unique_ptr input, int buffer_size = -1); ~IstreamInputStream() override; crypto::tink::util::StatusOr Next(const void** data) override; void BackUp(int count) override; int64_t Position() const override; private: util::Status status_; std::unique_ptr input_; std::unique_ptr buffer_; const int buffer_size_; int64_t position_; // current position in the istream (from the beginning) // Counters that describe the state of the data in buffer_. int count_in_buffer_; // # of bytes available in buffer_ int count_backedup_; // # of bytes available in buffer_ that were backed up int buffer_offset_; // offset at which the returned bytes start in buffer_ }; } // namespace util } // namespace tink } // namespace crypto #endif // TINK_UTIL_ISTREAM_INPUT_STREAM_H_ ================================================ FILE: cc/util/istream_input_stream_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/istream_input_stream.h" #include #include #include #include #include #include #include #include #include #include #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/internal/test_file_util.h" #include "tink/subtle/random.h" #include "tink/util/status.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace { // Creates a new test file with the specified 'filename', writes 'size' random // bytes to the file, and returns an istream for reading from the file. // A copy of the bytes written to the file is returned in 'file_contents'. std::unique_ptr GetTestIstream(absl::string_view filename, int size, std::string* file_contents) { std::string full_filename = absl::StrCat(crypto::tink::test::TmpDir(), "/", filename); (*file_contents) = subtle::Random::GetRandomBytes(size); std::ofstream output (full_filename, std::ofstream::binary); if (!output.write(file_contents->data(), size) || output.tellp() != size) { std::clog << "Failed to write " << size << " bytes to file " << full_filename << " error: " << errno << '\n'; exit(1); } output.close(); auto test_istream = absl::make_unique( full_filename, std::ofstream::binary); return std::move(test_istream); } // Reads the specified 'input_stream' until no more bytes can be read, // and puts the read bytes into 'contents'. // Returns the status of the last input_stream->Next()-operation. util::Status ReadTillEnd(util::IstreamInputStream* input_stream, std::string* contents) { contents->clear(); const void* buffer; auto next_result = input_stream->Next(&buffer); while (next_result.ok()) { contents->append(static_cast(buffer), next_result.value()); next_result = input_stream->Next(&buffer); } return next_result.status(); } class IstreamInputStreamTest : public ::testing::Test { }; TEST_F(IstreamInputStreamTest, testReadingStreams) { for (int stream_size : {0, 10, 100, 1000, 10000, 100000, 1000000}) { std::string file_contents; std::string filename = absl::StrCat( stream_size, "_", internal::GetTestFileNamePrefix(), "_file.bin"); auto input = GetTestIstream(filename, stream_size, &file_contents); EXPECT_EQ(stream_size, file_contents.size()); auto input_stream = absl::make_unique( std::move(input)); std::string stream_contents; auto status = ReadTillEnd(input_stream.get(), &stream_contents); EXPECT_EQ(absl::StatusCode::kOutOfRange, status.code()); EXPECT_EQ("EOF", status.message()); EXPECT_EQ(file_contents, stream_contents); } } TEST_F(IstreamInputStreamTest, testCustomBufferSizes) { int stream_size = 100000; for (int buffer_size : {1, 10, 100, 1000, 10000}) { std::string file_contents; std::string filename = absl::StrCat( buffer_size, "_", internal::GetTestFileNamePrefix(), "_file.bin"); auto input = GetTestIstream(filename, stream_size, &file_contents); EXPECT_EQ(stream_size, file_contents.size()); auto input_stream = absl::make_unique( std::move(input), buffer_size); const void* buffer; auto next_result = input_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(file_contents.substr(0, buffer_size), std::string(static_cast(buffer), buffer_size)); } } TEST_F(IstreamInputStreamTest, testBackupAndPosition) { int stream_size = 100000; int buffer_size = 1234; const void* buffer; std::string file_contents; std::string filename = absl::StrCat(buffer_size, internal::GetTestFileNamePrefix(), "_file.bin"); auto input = GetTestIstream(filename, stream_size, &file_contents); EXPECT_EQ(stream_size, file_contents.size()); // Prepare the stream and do the first call to Next(). auto input_stream = absl::make_unique( std::move(input), buffer_size); EXPECT_EQ(0, input_stream->Position()); auto next_result = input_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(buffer_size, input_stream->Position()); EXPECT_EQ(file_contents.substr(0, buffer_size), std::string(static_cast(buffer), buffer_size)); // BackUp several times, but in total fewer bytes than returned by Next(). int total_backup_size = 0; for (auto backup_size : {0, 1, 5, 0, 10, 100, -42, 400, 20, -100}) { input_stream->BackUp(backup_size); total_backup_size += std::max(0, backup_size); EXPECT_EQ(buffer_size - total_backup_size, input_stream->Position()); } // Call Next(), it should return exactly the backed up bytes. next_result = input_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(total_backup_size, next_result.value()); EXPECT_EQ(buffer_size, input_stream->Position()); EXPECT_EQ( file_contents.substr(buffer_size - total_backup_size, total_backup_size), std::string(static_cast(buffer), total_backup_size)); // BackUp() some bytes, again fewer than returned by Next(). total_backup_size = 0; for (int backup_size : {0, 72, -94, 37, 82}) { input_stream->BackUp(backup_size); total_backup_size += std::max(0, backup_size); EXPECT_EQ(buffer_size - total_backup_size, input_stream->Position()); } // Call Next(), it should return exactly the backed up bytes. next_result = input_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(total_backup_size, next_result.value()); EXPECT_EQ(buffer_size, input_stream->Position()); EXPECT_EQ( file_contents.substr(buffer_size - total_backup_size, total_backup_size), std::string(static_cast(buffer), total_backup_size)); // Call Next() again, it should return the second block. next_result = input_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(2 * buffer_size, input_stream->Position()); EXPECT_EQ(file_contents.substr(buffer_size, buffer_size), std::string(static_cast(buffer), buffer_size)); // BackUp a few times, with total over the returned buffer_size. total_backup_size = 0; for (int backup_size : {0, 72, -100, buffer_size/2, 200, -25, buffer_size, 42}) { input_stream->BackUp(backup_size); total_backup_size = std::min(buffer_size, total_backup_size + std::max(0, backup_size)); EXPECT_EQ(2 * buffer_size - total_backup_size, input_stream->Position()); } // Call Next() again, it should return the second block. next_result = input_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(2 * buffer_size, input_stream->Position()); EXPECT_EQ(file_contents.substr(buffer_size, buffer_size), std::string(static_cast(buffer), buffer_size)); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/util/keyset_util.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/keyset_util.h" #include #include #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using google::crypto::tink::Keyset; uint32_t NewKeyId() { std::random_device rd; std::minstd_rand0 gen(rd()); std::uniform_int_distribution dist; return dist(gen); } } // namespace uint32_t GenerateUnusedKeyId(const Keyset& keyset) { while (true) { uint32_t key_id = NewKeyId(); bool already_exists = false; for (auto& key : keyset.key()) { if (key.key_id() == key_id) { already_exists = true; break; } } if (!already_exists) return key_id; } } } // namespace tink } // namespace crypto ================================================ FILE: cc/util/keyset_util.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_UTIL_KEYSET_UTIL_H_ #define TINK_UTIL_KEYSET_UTIL_H_ #include #include "proto/tink.pb.h" namespace crypto { namespace tink { // Generate a new random key ID not previously used in `keyset`. uint32_t GenerateUnusedKeyId(const google::crypto::tink::Keyset& keyset); } // namespace tink } // namespace crypto #endif // TINK_UTIL_KEYSET_UTIL_H_ ================================================ FILE: cc/util/ostream_output_stream.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/ostream_output_stream.h" #include #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/output_stream.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace util { OstreamOutputStream::OstreamOutputStream(std::unique_ptr output, int buffer_size) : buffer_size_(buffer_size > 0 ? buffer_size : 128 * 1024) { // 128 KB output_ = std::move(output); count_in_buffer_ = 0; count_backedup_ = 0; buffer_ = nullptr; position_ = 0; buffer_offset_ = 0; status_ = OkStatus(); } crypto::tink::util::StatusOr OstreamOutputStream::Next(void** data) { if (!status_.ok()) return status_; if (buffer_ == nullptr) { // possible only at the first call to Next() buffer_ = absl::make_unique(buffer_size_); *data = buffer_.get(); count_in_buffer_ = buffer_size_; position_ = buffer_size_; return buffer_size_; } // If some space was backed up, return it first. if (count_backedup_ > 0) { position_ = position_ + count_backedup_; buffer_offset_ = count_in_buffer_; count_in_buffer_ = count_in_buffer_ + count_backedup_; int backedup = count_backedup_; count_backedup_ = 0; *data = buffer_.get() + buffer_offset_; return backedup; } // No space was backed up, so count_in_buffer_ == buffer_size_ holds here. // Write the data from the buffer, and return available space in buffer_. // The available space might not span the entire buffer_, as writing // may succeed only for a prefix of buffer_ -- in this case the data still // to be written is shifted in buffer_ and the remaining space is returned. int write_result = output_->rdbuf()->sputn( reinterpret_cast(buffer_.get()), buffer_size_); if (write_result == 0) { // No data written or an I/O error occurred. if (output_->good()) return 0; status_ = ToStatusF(absl::StatusCode::kInternal, "I/O error upon write: %s", std::strerror(errno)); return status_; } // Some data was written, so we can return some portion of buffer_. position_ = position_ + write_result; count_in_buffer_ = buffer_size_; count_backedup_ = 0; buffer_offset_ = buffer_size_ - write_result; *data = buffer_.get() + buffer_offset_; if (write_result < buffer_size_) { // Only part of the data was written, shift the remaining data in buffer_. // Using memmove, as source and destination may overlap. std::memmove(buffer_.get(), buffer_.get() + write_result, buffer_offset_); } return write_result; } void OstreamOutputStream::BackUp(int count) { if (!status_.ok() || count < 1 || count_in_buffer_ == 0) return; int curr_buffer_size = buffer_size_ - buffer_offset_; int actual_count = std::min(count, curr_buffer_size - count_backedup_); count_backedup_ += actual_count; count_in_buffer_ -= actual_count; position_ -= actual_count; } OstreamOutputStream::~OstreamOutputStream() { Close().IgnoreError(); } Status OstreamOutputStream::Close() { if (!status_.ok()) return status_; if (count_in_buffer_ > 0) { // Try to write the remaining bytes. output_->write(reinterpret_cast(buffer_.get()), count_in_buffer_); if (!output_->good()) { // An I/O error occurred. status_ = ToStatusF(absl::StatusCode::kInternal, "I/O error upon write: %d", errno); return status_; } } output_->flush(); if (!output_->good()) { status_ = ToStatusF(absl::StatusCode::kInternal, "I/O error upon flushing: %d", errno); return status_; } status_ = Status(absl::StatusCode::kFailedPrecondition, "Stream closed"); return OkStatus(); } int64_t OstreamOutputStream::Position() const { return position_; } } // namespace util } // namespace tink } // namespace crypto ================================================ FILE: cc/util/ostream_output_stream.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_UTIL_OSTREAM_OUTPUT_STREAM_H_ #define TINK_UTIL_OSTREAM_OUTPUT_STREAM_H_ #include #include #include #include "tink/output_stream.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace util { // An OutputStream that writes to an ostream. class OstreamOutputStream : public crypto::tink::OutputStream { public: // Constructs an OutputStream that will write to the ostream specified // via 'output', using a buffer of the specified size, if any // (if no legal 'buffer_size' is given, a reasonable default will be used). explicit OstreamOutputStream(std::unique_ptr output, int buffer_size = -1); ~OstreamOutputStream() override; crypto::tink::util::StatusOr Next(void** data) override; void BackUp(int count) override; crypto::tink::util::Status Close() override; int64_t Position() const override; private: util::Status status_; std::unique_ptr output_; std::unique_ptr buffer_; const int buffer_size_; int64_t position_; // current position in the ostream (from the beginning) // Counters that describe the state of the data in buffer_. // count_in_buffer_ is always equal to (buffer_size_ - count_backedup_), // except initially (before the first call to Next()). // In other words, we have an invariant: // (count_in_buffer_ == buffer_size_ - count_backedup_) || buffer_ == nullptr int count_in_buffer_; // # bytes in buffer_ that will be eventually written int count_backedup_; // # bytes in buffer_ that were backed up int buffer_offset_; // offset where the returned *data starts in buffer_ }; } // namespace util } // namespace tink } // namespace crypto #endif // TINK_UTIL_OSTREAM_OUTPUT_STREAM_H_ ================================================ FILE: cc/util/ostream_output_stream_test.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/ostream_output_stream.h" #include #include #include #include #include #include #include #include #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "tink/internal/test_file_util.h" #include "tink/subtle/random.h" #include "tink/util/status.h" #include "tink/util/test_util.h" namespace crypto { namespace tink { namespace { // Creates a new test ostream which will write to the file 'filename'. std::unique_ptr GetTestOstream(absl::string_view filename) { std::string full_filename = absl::StrCat(crypto::tink::test::TmpDir(), "/", filename); auto test_ostream = absl::make_unique( full_filename, std::ofstream::binary); return std::move(test_ostream); } // Writes 'contents' to the specified 'output_stream', and closes the stream. // Returns the status of output_stream->Close()-operation, or a non-OK status // of a prior output_stream->Next()-operation, if any. util::Status WriteToStream(util::OstreamOutputStream* output_stream, absl::string_view contents) { void* buffer; int pos = 0; int remaining = contents.length(); int available_space = 0; int available_bytes = 0; while (remaining > 0) { auto next_result = output_stream->Next(&buffer); if (!next_result.ok()) return next_result.status(); available_space = next_result.value(); available_bytes = std::min(available_space, remaining); memcpy(buffer, contents.data() + pos, available_bytes); remaining -= available_bytes; pos += available_bytes; } if (available_space > available_bytes) { output_stream->BackUp(available_space - available_bytes); } return output_stream->Close(); } class OstreamOutputStreamTest : public ::testing::Test { }; TEST_F(OstreamOutputStreamTest, WritingStreams) { for (size_t stream_size : {0, 10, 100, 1000, 10000, 100000, 1000000}) { SCOPED_TRACE(absl::StrCat("stream_size = ", stream_size)); std::string stream_contents = subtle::Random::GetRandomBytes(stream_size); std::string filename = absl::StrCat( stream_size, internal::GetTestFileNamePrefix(), "_file.bin"); auto output = GetTestOstream(filename); auto output_stream = absl::make_unique( std::move(output)); auto status = WriteToStream(output_stream.get(), stream_contents); EXPECT_TRUE(status.ok()) << status; std::string ostream_contents = test::ReadTestFile(filename); EXPECT_EQ(stream_size, ostream_contents.size()); EXPECT_EQ(stream_contents, ostream_contents); } } TEST_F(OstreamOutputStreamTest, CustomBufferSizes) { int stream_size = 1024 * 1024; std::string stream_contents = subtle::Random::GetRandomBytes(stream_size); for (int buffer_size : {1, 10, 100, 1000, 10000, 100000, 1000000}) { SCOPED_TRACE(absl::StrCat("buffer_size = ", buffer_size)); std::string filename = absl::StrCat( buffer_size, internal::GetTestFileNamePrefix(), "_file.bin"); auto output = GetTestOstream(filename); auto output_stream = absl::make_unique( std::move(output), buffer_size); void* buffer; auto next_result = output_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); output_stream->BackUp(buffer_size); auto status = WriteToStream(output_stream.get(), stream_contents); EXPECT_TRUE(status.ok()) << status; std::string ostream_contents = test::ReadTestFile(filename); EXPECT_EQ(stream_size, ostream_contents.size()); EXPECT_EQ(stream_contents, ostream_contents); } } TEST_F(OstreamOutputStreamTest, BackupAndPosition) { int stream_size = 1024 * 1024; int buffer_size = 1234; void* buffer; std::string stream_contents = subtle::Random::GetRandomBytes(stream_size); std::string filename = absl::StrCat(buffer_size, internal::GetTestFileNamePrefix(), "_file.bin"); auto output = GetTestOstream(filename); // Prepare the stream and do the first call to Next(). auto output_stream = absl::make_unique( std::move(output), buffer_size); EXPECT_EQ(0, output_stream->Position()); auto next_result = output_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(buffer_size, output_stream->Position()); std::memcpy(buffer, stream_contents.data(), buffer_size); // BackUp several times, but in total fewer bytes than returned by Next(). int total_backup_size = 0; for (int backup_size : {0, 1, 5, 0, 10, 100, -42, 400, 20, -100}) { SCOPED_TRACE(absl::StrCat("backup_size = ", backup_size)); output_stream->BackUp(backup_size); total_backup_size += std::max(backup_size, 0); EXPECT_EQ(buffer_size - total_backup_size, output_stream->Position()); } EXPECT_LT(total_backup_size, next_result.value()); // Call Next(), it should succeed. next_result = output_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); // BackUp() some bytes, again fewer than returned by Next(). total_backup_size = 0; for (int backup_size : {0, 72, -94, 37, 82}) { SCOPED_TRACE(absl::StrCat("backup_size = ", backup_size)); output_stream->BackUp(backup_size); total_backup_size += std::max(0, backup_size); EXPECT_EQ(buffer_size - total_backup_size, output_stream->Position()); } EXPECT_LT(total_backup_size, next_result.value()); // Call Next(), it should succeed; next_result = output_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); // Call Next() again, it should return a full block. auto prev_position = output_stream->Position(); next_result = output_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(prev_position + buffer_size, output_stream->Position()); std::memcpy(buffer, stream_contents.data() + buffer_size, buffer_size); // BackUp a few times, with total over the returned buffer_size. total_backup_size = 0; for (int backup_size : {0, 72, -100, buffer_size / 2, 200, -25, buffer_size / 2, 42}) { SCOPED_TRACE(absl::StrCat("backup_size = ", backup_size)); output_stream->BackUp(backup_size); total_backup_size = std::min(buffer_size, total_backup_size + std::max(backup_size, 0)); EXPECT_EQ(prev_position + buffer_size - total_backup_size, output_stream->Position()); } EXPECT_EQ(total_backup_size, buffer_size); EXPECT_EQ(prev_position, output_stream->Position()); // Call Next() again, it should return a full block. next_result = output_stream->Next(&buffer); EXPECT_TRUE(next_result.ok()) << next_result.status(); EXPECT_EQ(buffer_size, next_result.value()); EXPECT_EQ(prev_position + buffer_size, output_stream->Position()); std::memcpy(buffer, stream_contents.data() + buffer_size, buffer_size); // Write the remaining stream contents to stream. auto status = WriteToStream( output_stream.get(), stream_contents.substr(output_stream->Position())); EXPECT_TRUE(status.ok()) << status; std::string ostream_contents = test::ReadTestFile(filename); EXPECT_EQ(stream_size, ostream_contents.size()); EXPECT_EQ(stream_contents, ostream_contents); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/util/protobuf_helper.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_UTIL_PROTOBUF_HELPER_H_ #define TINK_UTIL_PROTOBUF_HELPER_H_ #include "google/protobuf/message_lite.h" // IWYU pragma: export // NOLINTNEXTLINE(misc-unused-alias-decls) namespace portable_proto = ::google::protobuf; #endif // TINK_UTIL_PROTOBUF_HELPER_H_ ================================================ FILE: cc/util/secret_data.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_UTIL_SECRET_DATA_H_ #define TINK_UTIL_SECRET_DATA_H_ #include #include // IWYU pragma: keep #include #include #include #include // IWYU pragma: keep #include "absl/strings/string_view.h" #include "tink/util/secret_data_internal.h" namespace crypto { namespace tink { namespace util { namespace internal { template struct SanitizingDeleter { void operator()(T* ptr) { ptr->~T(); // Invoke destructor. Must do this before sanitize. SanitizingAllocator().deallocate(ptr, 1); } }; } // namespace internal // Stores secret (sensitive) data and makes sure it's marked as such and // destroyed in a safe way. // This should be the first choice when handling key/key derived values. // // Example: // class MyCryptoPrimitive { // public: // MyCryptoPrimitive(absl::string_view key_value) : // key_(SecretDataFromStringView(key_value)) {} // [...] // private: // const util::SecretData key_; // } using SecretData = std::vector>; // Stores secret (sensitive) object and makes sure it's marked as such and // destroyed in a safe way. // SecretUniquePtr MUST be constructed using MakeSecretUniquePtr function. // Generally SecretUniquePtr should be used iff SecretData is unsuitable. // // Example: // class MyCryptoPrimitive { // public: // MyEncryptionPrimitive(absl::string_view key_value) { // AES_set_encrypt_key(key_value.data(), key_value.size() * 8, key_.get()); // } // [...] // private: // util::SecretUniquePtr key_ = util::MakeSecretUniquePtr(); // } // // NOTE: SecretUniquePtr will only protect the data which is stored in the // memory which a T object takes on the stack. In particular, std::string and // std::vector SHOULD NOT be used as arguments of T: they allocate memory // on the heap, and hence the data stored in them will NOT be protected. template class SecretUniquePtr { private: using Value = std::unique_ptr>; public: using pointer = typename Value::pointer; using element_type = typename Value::element_type; using deleter_type = typename Value::deleter_type; SecretUniquePtr() = default; pointer get() const { return value_.get(); } deleter_type& get_deleter() { return value_.get_deleter(); } const deleter_type& get_deleter() const { return value_.get_deleter(); } void swap(SecretUniquePtr& other) noexcept { value_.swap(other.value_); } void reset() { value_.reset(); } typename std::add_lvalue_reference::type operator*() const { return value_.operator*(); } pointer operator->() const { return value_.operator->(); } explicit operator bool() const { return value_.operator bool(); } private: template friend SecretUniquePtr MakeSecretUniquePtr(Args&&... args); explicit SecretUniquePtr(Value&& value) : value_(std::move(value)) {} Value value_; }; template SecretUniquePtr MakeSecretUniquePtr(Args&&... args) { T* ptr = internal::SanitizingAllocator().allocate(1); new (ptr) T(std::forward(args)...); // Invoke constructor "placement new" return SecretUniquePtr({ptr, internal::SanitizingDeleter()}); } // Convenience conversion functions inline absl::string_view SecretDataAsStringView(const SecretData& secret) { return {reinterpret_cast(secret.data()), secret.size()}; } inline SecretData SecretDataFromStringView(absl::string_view secret) { return {secret.begin(), secret.end()}; } // The same as SecretUniquePtr, but with value semantics. // // NOTE: SecretValue will only protect the data which is stored in the // memory which a T object takes on the stack. In particular, std::string and // std::vector SHOULD NOT be used as arguments of T: they allocate memory // on the heap, and hence the data stored in them will NOT be protected. template class SecretValue { public: explicit SecretValue(T t = T()) : ptr_(MakeSecretUniquePtr(std::move(t))) {} SecretValue(const SecretValue& other) { ptr_ = MakeSecretUniquePtr(*other.ptr_); } SecretValue& operator=(const SecretValue& other) { *ptr_ = *other.ptr_; return *this; } T& value() { return *ptr_; } const T& value() const { return *ptr_; } private: SecretUniquePtr ptr_; }; inline void SafeZeroMemory(void* ptr, std::size_t size) { internal::SafeZeroMemory(ptr, size); } inline void SafeZeroString(std::string* str) { SafeZeroMemory(&(*str)[0], str->size()); } } // namespace util } // namespace tink } // namespace crypto #endif // TINK_UTIL_SECRET_DATA_H_ ================================================ FILE: cc/util/secret_data_internal.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_UTIL_SECRET_DATA_INTERNAL_H_ #define TINK_UTIL_SECRET_DATA_INTERNAL_H_ #include #include #include #include #include "absl/base/attributes.h" #include "absl/base/config.h" #include "openssl/crypto.h" namespace crypto { namespace tink { namespace util { namespace internal { inline void SafeZeroMemory(void* ptr, std::size_t size) { OPENSSL_cleanse(ptr, size); } template struct SanitizingAllocatorImpl { // If aligned operator new is not supported this only supports under aligned // types. #ifndef __cpp_aligned_new static_assert(alignof(T) <= alignof(std::max_align_t), "SanitizingAllocator only supports fundamental alignment " "before C++17"); #endif static T* allocate(std::size_t n) { if (n > std::numeric_limits::max() / sizeof(T)) { #ifdef ABSL_HAVE_EXCEPTIONS throw std::bad_array_new_length(); #else std::abort(); #endif } std::size_t size = n * sizeof(T); #ifdef __cpp_aligned_new return static_cast(::operator new(size, std::align_val_t(alignof(T)))); #else return static_cast(::operator new(size)); #endif } static void deallocate(void* ptr, std::size_t n) { SafeZeroMemory(ptr, n * sizeof(T)); #ifdef __cpp_aligned_new ::operator delete(ptr, std::align_val_t(alignof(T))); #else ::operator delete(ptr); #endif } }; // Specialization for malloc-like aligned storage. template <> struct SanitizingAllocatorImpl { static void* allocate(std::size_t n) { return std::malloc(n); } static void deallocate(void* ptr, std::size_t n) { SafeZeroMemory(ptr, n); return std::free(ptr); } }; template struct SanitizingAllocator { typedef T value_type; SanitizingAllocator() = default; template explicit constexpr SanitizingAllocator( const SanitizingAllocator&) noexcept {} ABSL_MUST_USE_RESULT T* allocate(std::size_t n) { return SanitizingAllocatorImpl::allocate(n); } void deallocate(T* ptr, std::size_t n) noexcept { SanitizingAllocatorImpl::deallocate(ptr, n); } // Allocator requirements mandate definition of eq and neq operators bool operator==(const SanitizingAllocator&) { return true; } bool operator!=(const SanitizingAllocator&) { return false; } }; } // namespace internal } // namespace util } // namespace tink } // namespace crypto #endif // TINK_UTIL_SECRET_DATA_INTERNAL_H_ ================================================ FILE: cc/util/secret_data_test.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/secret_data.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/string_view.h" namespace crypto { namespace tink { namespace util { namespace { using ::testing::AnyOf; using ::testing::ElementsAreArray; using ::testing::Eq; constexpr int kEightKb = 8192; struct alignas(kEightKb) TwoMbAlignedStruct { int data; }; // If we don't have __cpp_aligned_new we currently do not support types // whose alginment requirement is greater than the default. #ifdef __cpp_aligned_new TEST(SecretUniqueptrTest, Alignment) { SecretUniquePtr s = MakeSecretUniquePtr(); EXPECT_THAT(reinterpret_cast(s.get()) % kEightKb, Eq(0)); } #endif TEST(SecretDataTest, OneByOneInsertion) { constexpr unsigned char kContents[] = {41, 42, 64, 12, 41, 0, 52, 56, 6, 12, 127, 13}; SecretData data; for (unsigned char c : kContents) { data.push_back(c); } EXPECT_THAT(data, ElementsAreArray(kContents)); } TEST(SecretDataTest, SecretDataFromStringViewConstructor) { constexpr unsigned char kContents[] = {41, 42, 64, 12, 41, 0, 52, 56, 6, 12, 124, 16}; std::string s; for (unsigned char c : kContents) { s.push_back(c); } SecretData data = SecretDataFromStringView(s); EXPECT_THAT(data, ElementsAreArray(kContents)); } TEST(SecretDataTest, StringViewFromSecretData) { constexpr unsigned char kContents[] = {41, 42, 64, 12, 41, 0, 52, 56, 6, 12, 124, 16}; std::string s; for (unsigned char c : kContents) { s.push_back(c); } SecretData data = SecretDataFromStringView(s); absl::string_view data_view = SecretDataAsStringView(data); EXPECT_THAT(data_view, Eq(s)); } TEST(SecretDataTest, SecretDataCopy) { constexpr unsigned char kContents[] = {41, 42, 64, 12, 41, 0, 52, 56, 6, 12, 127, 13}; SecretData data; for (unsigned char c : kContents) { data.push_back(c); } SecretData data_copy = data; EXPECT_THAT(data_copy, ElementsAreArray(kContents)); } TEST(SecretValueTest, DefaultConstructor) { SecretValue s; EXPECT_THAT(s.value(), Eq(0)); } TEST(SecretValueTest, Constructor) { SecretValue s(102); EXPECT_THAT(s.value(), Eq(102)); } TEST(SecretValueTest, CopyConstructor) { SecretValue s(102); SecretValue t(s); EXPECT_THAT(t.value(), Eq(102)); } TEST(SecretValueTest, AssignmentOperator) { SecretValue s(102); SecretValue t(101); t = s; EXPECT_THAT(t.value(), Eq(102)); } TEST(SecretValueTest, MoveConstructor) { SecretValue s(102); SecretValue t(std::move(s)); EXPECT_THAT(t.value(), Eq(102)); // NOLINTNEXTLINE(bugprone-use-after-move) EXPECT_THAT(s.value(), AnyOf(Eq(0), Eq(102))); } TEST(SecretValueTest, MoveAssignment) { SecretValue s(102); SecretValue t; t = std::move(s); EXPECT_THAT(t.value(), Eq(102)); // NOLINTNEXTLINE(bugprone-use-after-move) EXPECT_THAT(s.value(), AnyOf(Eq(0), Eq(102))); } } // namespace } // namespace util } // namespace tink } // namespace crypto ================================================ FILE: cc/util/secret_proto.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_UTIL_SECRET_PROTO_H_ #define TINK_UTIL_SECRET_PROTO_H_ #include #include #include #include "google/protobuf/arena.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace util { namespace internal { inline google::protobuf::ArenaOptions SecretArenaOptions() { google::protobuf::ArenaOptions options; options.block_alloc = [](size_t sz) { return SanitizingAllocator().allocate(sz); }; options.block_dealloc = [](void* ptr, size_t sz) { return SanitizingAllocator().deallocate(ptr, sz); }; return options; } } // namespace internal // Stores secret (sensitive) protobuf and makes sure it's marked as such and // destroyed in a safe way. // // Note: Currently does not protect fields of type "string" and "bytes" // (depends on https://github.com/protocolbuffers/protobuf/issues/1896) template class SecretProto { public: static StatusOr> ParseFromSecretData(const SecretData& data) { SecretProto proto; if (!proto->ParseFromArray(data.data(), data.size())) { return Status(absl::StatusCode::kInternal, "Could not parse proto"); } return proto; } SecretProto() = default; SecretProto(const SecretProto& other) { *value_ = *other.value_; } SecretProto(SecretProto&& other) noexcept { *this = std::move(other); } explicit SecretProto(const T& value) { *value_ = value; } SecretProto& operator=(const SecretProto& other) { *value_ = *other.value_; return *this; } SecretProto& operator=(SecretProto&& other) noexcept { using std::swap; swap(arena_, other.arena_); swap(value_, other.value_); return *this; } inline T* get() { return value_; } // Accessors to the underlying message. inline T* operator->() { return value_; } inline const T* operator->() const { return value_; } inline T& operator*() { return *value_; } inline const T& operator*() const { return *value_; } StatusOr SerializeAsSecretData() const { SecretData data(value_->ByteSizeLong()); if (!value_->SerializeToArray(data.data(), data.size())) { return Status(absl::StatusCode::kInternal, "Could not serialize proto"); } return data; } private: std::unique_ptr arena_ = absl::make_unique(internal::SecretArenaOptions()); T* value_ = google::protobuf::Arena::Create(arena_.get()); }; } // namespace util } // namespace tink } // namespace crypto #endif // TINK_UTIL_SECRET_PROTO_H_ ================================================ FILE: cc/util/secret_proto_test.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/secret_proto.h" #include #include #include "google/protobuf/util/message_differencer.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "tink/util/secret_data.h" #include "tink/util/statusor.h" #include "proto/test_proto.pb.h" namespace crypto { namespace tink { namespace util { namespace { using ::google::crypto::tink::NestedTestProto; using ::google::crypto::tink::TestProto; using ::google::protobuf::util::MessageDifferencer; template class SecretProtoTest : public testing::Test {}; using MyTypes = ::testing::Types; TYPED_TEST_SUITE(SecretProtoTest, MyTypes); template T CreateProto(); template <> TestProto CreateProto() { TestProto proto; proto.set_num(123); proto.set_str("Single proto"); return proto; } template <> NestedTestProto CreateProto() { NestedTestProto proto; proto.mutable_a()->set_num(12); proto.mutable_a()->set_str("A proto"); proto.mutable_b()->set_num(14); proto.mutable_b()->set_str("B proto"); proto.set_num(42); proto.set_str("Main proto"); return proto; } TYPED_TEST(SecretProtoTest, DefaultConstructor) { SecretProto s; EXPECT_TRUE(MessageDifferencer::Equals(*s, TypeParam())); } TYPED_TEST(SecretProtoTest, Constructor) { TypeParam proto = CreateProto(); SecretProto s(proto); EXPECT_TRUE(MessageDifferencer::Equals(*s, proto)); } TYPED_TEST(SecretProtoTest, CopyConstructor) { TypeParam proto = CreateProto(); SecretProto s(proto); SecretProto t(s); EXPECT_TRUE(MessageDifferencer::Equals(*s, proto)); EXPECT_TRUE(MessageDifferencer::Equals(*t, proto)); } TYPED_TEST(SecretProtoTest, SourceDestroyedAfterCopyConstructor) { TypeParam proto = CreateProto(); auto s = absl::make_unique>(proto); SecretProto t(*s); EXPECT_TRUE(MessageDifferencer::Equals(**s, proto)); EXPECT_TRUE(MessageDifferencer::Equals(*t, proto)); // Test with source destroyed after the copy s.reset(); EXPECT_TRUE(MessageDifferencer::Equals(*t, proto)); } TYPED_TEST(SecretProtoTest, AssignmentOperator) { TypeParam proto = CreateProto(); SecretProto t; { SecretProto s(proto); t = s; EXPECT_TRUE(MessageDifferencer::Equals(*s, proto)); EXPECT_TRUE(MessageDifferencer::Equals(*t, proto)); } // Test with source destroyed after the copy EXPECT_TRUE(MessageDifferencer::Equals(*t, proto)); } TYPED_TEST(SecretProtoTest, MoveConstructor) { TypeParam proto = CreateProto(); SecretProto s(proto); SecretProto t(std::move(s)); EXPECT_TRUE(MessageDifferencer::Equals(*t, proto)); // NOLINTNEXTLINE: bugprone-use-after-move EXPECT_TRUE(MessageDifferencer::Equals(*s, TypeParam()) || MessageDifferencer::Equals(*s, proto)); } TYPED_TEST(SecretProtoTest, MoveAssignment) { TypeParam proto = CreateProto(); SecretProto t; { SecretProto s(proto); t = std::move(s); EXPECT_TRUE(MessageDifferencer::Equals(*t, proto)); // NOLINTNEXTLINE: bugprone-use-after-move EXPECT_TRUE(MessageDifferencer::Equals(*s, TypeParam()) || MessageDifferencer::Equals(*s, proto)); } // Test with source destroyed after the move EXPECT_TRUE(MessageDifferencer::Equals(*t, proto)); } TYPED_TEST(SecretProtoTest, FromSecretData) { TypeParam proto = CreateProto(); SecretData data; data.resize(proto.ByteSizeLong()); ASSERT_TRUE(proto.SerializeToArray(data.data(), data.size())); StatusOr> secret_proto = SecretProto::ParseFromSecretData(data); ASSERT_TRUE(secret_proto.ok()) << secret_proto.status(); EXPECT_TRUE(MessageDifferencer::Equals(**secret_proto, proto)); } TYPED_TEST(SecretProtoTest, AsSecretData) { TypeParam proto = CreateProto(); std::string serialized = proto.SerializeAsString(); SecretProto secret_proto(proto); StatusOr secret_serialized = secret_proto.SerializeAsSecretData(); ASSERT_TRUE(secret_serialized.ok()) << secret_serialized.status(); EXPECT_EQ(serialized, SecretDataAsStringView(*secret_serialized)); } } // namespace } // namespace util } // namespace tink } // namespace crypto ================================================ FILE: cc/util/status.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// // This code was unceremoniously lifted from the version at // github.com/google/lmctfy with a few minor modifications mainly to reduce the // dependencies. #ifndef TINK_UTIL_STATUS_H_ #define TINK_UTIL_STATUS_H_ #include "absl/status/status.h" #define TINK_USE_ABSL_STATUS namespace crypto { namespace tink { namespace util { using Status = absl::Status; // Returns an OK status, equivalent to a default constructed instance. inline Status OkStatus() { return Status(); } } // namespace util } // namespace tink } // namespace crypto #endif // TINK_UTIL_STATUS_H_ ================================================ FILE: cc/util/statusor.h ================================================ // Copyright 2013 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_UTIL_STATUSOR_H_ #define TINK_UTIL_STATUSOR_H_ #include "absl/status/statusor.h" #include "tink/util/status.h" #define TINK_USE_ABSL_STATUSOR namespace crypto { namespace tink { namespace util { template using StatusOr = absl::StatusOr; } // namespace util } // namespace tink } // namespace crypto #endif // TINK_UTIL_STATUSOR_H_ ================================================ FILE: cc/util/test_keyset_handle.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/test_keyset_handle.h" #include #include #include "absl/memory/memory.h" #include "tink/keyset_handle.h" #include "tink/util/secret_proto.h" #include "proto/tink.pb.h" using google::crypto::tink::Keyset; namespace crypto { namespace tink { // static std::unique_ptr TestKeysetHandle::GetKeysetHandle( const Keyset& keyset) { std::unique_ptr handle = absl::WrapUnique(new KeysetHandle(util::SecretProto(keyset))); return handle; } // static const Keyset& TestKeysetHandle::GetKeyset(const KeysetHandle& keyset_handle) { return keyset_handle.get_keyset(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/util/test_keyset_handle.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_UTIL_TEST_KEYSET_HANDLE_H_ #define TINK_UTIL_TEST_KEYSET_HANDLE_H_ #include #include "tink/keyset_handle.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // The helpers below are "packed" in a class to allow for an easier // addition of them as a "friend class". class TestKeysetHandle { public: // Creates a KeysetHandle object for the given 'keyset'. static std::unique_ptr GetKeysetHandle( const google::crypto::tink::Keyset& keyset); // Returns a Keyset-proto from the given 'keyset_handle'. static const google::crypto::tink::Keyset& GetKeyset( const KeysetHandle& keyset_handle); }; } // namespace tink } // namespace crypto #endif // TINK_UTIL_TEST_KEYSET_HANDLE_H_ ================================================ FILE: cc/util/test_matchers.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef TINK_UTIL_TEST_MATCHERS_H_ #define TINK_UTIL_TEST_MATCHERS_H_ #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "tink/util/status.h" #include "tink/util/statusor.h" namespace crypto { namespace tink { namespace test { namespace internal { //////////////////////////////////////////////////////////// // Implementation of IsOkAndHolds(). // Monomorphic implementation of matcher IsOkAndHolds(m). StatusOrType is a // reference to StatusOr. template class IsOkAndHoldsMatcherImpl : public ::testing::MatcherInterface { public: using value_type = typename std::remove_reference::type::value_type; template explicit IsOkAndHoldsMatcherImpl(InnerMatcher&& inner_matcher) : inner_matcher_(::testing::SafeMatcherCast( std::forward(inner_matcher))) {} void DescribeTo(std::ostream* os) const override { *os << "is OK and has a value that "; inner_matcher_.DescribeTo(os); } void DescribeNegationTo(std::ostream* os) const override { *os << "isn't OK or has a value that "; inner_matcher_.DescribeNegationTo(os); } bool MatchAndExplain( StatusOrType actual_value, ::testing::MatchResultListener* result_listener) const override { if (!actual_value.ok()) { *result_listener << "which has status " << actual_value.status(); return false; } ::testing::StringMatchResultListener inner_listener; const bool matches = inner_matcher_.MatchAndExplain(*actual_value, &inner_listener); const std::string inner_explanation = inner_listener.str(); if (!inner_explanation.empty()) { *result_listener << "which contains value " << ::testing::PrintToString(*actual_value) << ", " << inner_explanation; } return matches; } private: const ::testing::Matcher inner_matcher_; }; // Implements IsOkAndHolds(m) as a polymorphic matcher. template class IsOkAndHoldsMatcher { public: explicit IsOkAndHoldsMatcher(InnerMatcher inner_matcher) : inner_matcher_(std::move(inner_matcher)) {} // Converts this polymorphic matcher to a monomorphic matcher of the // given type. StatusOrType can be either StatusOr or a // reference to StatusOr. template operator ::testing::Matcher() const { // NOLINT return ::testing::Matcher( new IsOkAndHoldsMatcherImpl(inner_matcher_)); } private: const InnerMatcher inner_matcher_; }; } // namespace internal inline std::string StatusToString(const util::Status& s) { return s.ToString(); } template std::string StatusToString(const util::StatusOr& s) { return s.status().ToString(); } // Matches a util::StatusOk() value. // This is better than EXPECT_TRUE(status.ok()) // because the error message is a part of the failure messsage. MATCHER(IsOk, absl::StrCat(negation ? "isn't" : "is", " a Status with an OK value")) { if (arg.ok()) { return true; } *result_listener << StatusToString(arg); return false; } // Returns a gMock matcher that matches a StatusOr<> whose status is // OK and whose value matches the inner matcher. template internal::IsOkAndHoldsMatcher::type> IsOkAndHolds(InnerMatcher&& inner_matcher) { return internal::IsOkAndHoldsMatcher::type>( std::forward(inner_matcher)); } // Matches a Status with the specified 'code' as code(). MATCHER_P(StatusIs, code, "is a Status with a " + absl::StatusCodeToString(code) + " code") { if (arg.code() == code) { return true; } *result_listener << ::testing::PrintToString(arg); return false; } // Matches a Status whose code() equals 'code', and whose message() matches // 'message_macher'. MATCHER_P2(StatusIs, code, message_matcher, "") { return (arg.code() == code) && testing::Matches(message_matcher)(std::string(arg.message())); } // Matches a Keyset::Key with `key`. MATCHER_P(EqualsKey, key, "is equals to the expected key") { if (arg.key_id() == key.key_id() && arg.status() == key.status() && arg.output_prefix_type() == key.output_prefix_type() && arg.key_data().type_url() == key.key_data().type_url() && arg.key_data().key_material_type() == key.key_data().key_material_type() && arg.key_data().value() == key.key_data().value()) { return true; } *result_listener << "Expected: " << arg.key_id() << ", " << arg.output_prefix_type() << arg.key_data().type_url() << ", " << arg.key_data().key_material_type() << ", " << arg.key_data().value(); *result_listener << "\nActual: " << key.key_id() << ", " << key.output_prefix_type() << key.key_data().type_url() << ", " << key.key_data().key_material_type() << ", " << key.key_data().value(); return false; } } // namespace test } // namespace tink } // namespace crypto #endif // TINK_UTIL_TEST_MATCHERS_H_ ================================================ FILE: cc/util/test_util.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/test_util.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_join.h" #include "absl/strings/string_view.h" #include "tink/aead/aes_ctr_hmac_aead_key_manager.h" #include "tink/aead/aes_gcm_key_manager.h" #include "tink/aead/xchacha20_poly1305_key_manager.h" #include "tink/cleartext_keyset_handle.h" #include "tink/daead/aes_siv_key_manager.h" #include "tink/internal/ec_util.h" #include "tink/keyset_handle.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/random.h" #include "tink/util/enums.h" #include "tink/util/protobuf_helper.h" #include "tink/util/secret_data.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/aes_ctr.pb.h" #include "proto/aes_ctr_hmac_aead.pb.h" #include "proto/aes_gcm.pb.h" #include "proto/aes_siv.pb.h" #include "proto/common.pb.h" #include "proto/ecdsa.pb.h" #include "proto/ecies_aead_hkdf.pb.h" #include "proto/ed25519.pb.h" #include "proto/hmac.pb.h" #include "proto/tink.pb.h" #include "proto/xchacha20_poly1305.pb.h" using crypto::tink::util::Enums; using crypto::tink::util::Status; using google::crypto::tink::AesGcmKeyFormat; using google::crypto::tink::EcdsaPrivateKey; using google::crypto::tink::EciesAeadHkdfPrivateKey; using google::crypto::tink::Ed25519PrivateKey; using google::crypto::tink::Keyset; using google::crypto::tink::OutputPrefixType; namespace crypto { namespace tink { namespace test { std::string ReadTestFile(absl::string_view filename) { std::string full_filename = absl::StrCat(test::TmpDir(), "/", filename); std::ifstream input_stream(full_filename, std::ios::binary); if (!input_stream) { std::clog << "Cannot open file " << full_filename << '\n'; exit(1); } std::stringstream buffer; buffer << input_stream.rdbuf(); return buffer.str(); } util::StatusOr HexDecode(absl::string_view hex) { if (hex.size() % 2 != 0) { return util::Status(absl::StatusCode::kInvalidArgument, "Input has odd size."); } std::string decoded(hex.size() / 2, static_cast(0)); for (size_t i = 0; i < hex.size(); ++i) { char c = hex[i]; char val; if ('0' <= c && c <= '9') val = c - '0'; else if ('a' <= c && c <= 'f') val = c - 'a' + 10; else if ('A' <= c && c <= 'F') val = c - 'A' + 10; else return util::Status(absl::StatusCode::kInvalidArgument, "Not hexadecimal"); decoded[i / 2] = (decoded[i / 2] << 4) | val; } return decoded; } std::string HexDecodeOrDie(absl::string_view hex) { return HexDecode(hex).value(); } std::string HexEncode(absl::string_view bytes) { std::string hexchars = "0123456789abcdef"; std::string res(bytes.size() * 2, static_cast(255)); for (size_t i = 0; i < bytes.size(); ++i) { uint8_t c = static_cast(bytes[i]); res[2 * i] = hexchars[c / 16]; res[2 * i + 1] = hexchars[c % 16]; } return res; } std::string TmpDir() { // Try the following environment variables in order: // - TEST_TMPDIR: Set by `bazel test`. // - TMPDIR: Set by some Tink tests. // - TEMP, TMP: Set on Windows; they contain the tmp dir's path. for (const std::string& tmp_env_variable : {"TEST_TMPDIR", "TMPDIR", "TEMP", "TMP"}) { const char* env = getenv(tmp_env_variable.c_str()); if (env && env[0] != '\0') { return env; } } // Tmp dir on Linux/macOS. return "/tmp"; } void AddKeyData(const google::crypto::tink::KeyData& key_data, uint32_t key_id, google::crypto::tink::OutputPrefixType output_prefix, google::crypto::tink::KeyStatusType key_status, google::crypto::tink::Keyset* keyset) { Keyset::Key* key = keyset->add_key(); key->set_output_prefix_type(output_prefix); key->set_key_id(key_id); key->set_status(key_status); *key->mutable_key_data() = key_data; } void AddKey(const std::string& key_type, uint32_t key_id, const portable_proto::MessageLite& new_key, google::crypto::tink::OutputPrefixType output_prefix, google::crypto::tink::KeyStatusType key_status, google::crypto::tink::KeyData::KeyMaterialType material_type, google::crypto::tink::Keyset* keyset) { google::crypto::tink::KeyData key_data; key_data.set_type_url(key_type); key_data.set_key_material_type(material_type); key_data.set_value(new_key.SerializeAsString()); AddKeyData(key_data, key_id, output_prefix, key_status, keyset); } void AddTinkKey(const std::string& key_type, uint32_t key_id, const portable_proto::MessageLite& key, google::crypto::tink::KeyStatusType key_status, google::crypto::tink::KeyData::KeyMaterialType material_type, google::crypto::tink::Keyset* keyset) { AddKey(key_type, key_id, key, OutputPrefixType::TINK, key_status, material_type, keyset); } void AddLegacyKey(const std::string& key_type, uint32_t key_id, const portable_proto::MessageLite& key, google::crypto::tink::KeyStatusType key_status, google::crypto::tink::KeyData::KeyMaterialType material_type, google::crypto::tink::Keyset* keyset) { AddKey(key_type, key_id, key, OutputPrefixType::LEGACY, key_status, material_type, keyset); } void AddRawKey(const std::string& key_type, uint32_t key_id, const portable_proto::MessageLite& key, google::crypto::tink::KeyStatusType key_status, google::crypto::tink::KeyData::KeyMaterialType material_type, google::crypto::tink::Keyset* keyset) { AddKey(key_type, key_id, key, OutputPrefixType::RAW, key_status, material_type, keyset); } EciesAeadHkdfPrivateKey GetEciesAesGcmHkdfTestKey( subtle::EllipticCurveType curve_type, subtle::EcPointFormat ec_point_format, subtle::HashType hash_type, uint32_t aes_gcm_key_size) { return GetEciesAesGcmHkdfTestKey( Enums::SubtleToProto(curve_type), Enums::SubtleToProto(ec_point_format), Enums::SubtleToProto(hash_type), aes_gcm_key_size); } EciesAeadHkdfPrivateKey GetEciesAeadHkdfTestKey( google::crypto::tink::EllipticCurveType curve_type, google::crypto::tink::EcPointFormat ec_point_format, google::crypto::tink::HashType hash_type) { auto test_key = internal::NewEcKey(Enums::ProtoToSubtle(curve_type)).value(); EciesAeadHkdfPrivateKey ecies_key; ecies_key.set_version(0); ecies_key.set_key_value( std::string(util::SecretDataAsStringView(test_key.priv))); auto public_key = ecies_key.mutable_public_key(); public_key->set_version(0); public_key->set_x(test_key.pub_x); public_key->set_y(test_key.pub_y); auto params = public_key->mutable_params(); params->set_ec_point_format(ec_point_format); params->mutable_kem_params()->set_curve_type(curve_type); params->mutable_kem_params()->set_hkdf_hash_type(hash_type); return ecies_key; } EciesAeadHkdfPrivateKey GetEciesAesGcmHkdfTestKey( google::crypto::tink::EllipticCurveType curve_type, google::crypto::tink::EcPointFormat ec_point_format, google::crypto::tink::HashType hash_type, uint32_t aes_gcm_key_size) { auto ecies_key = GetEciesAeadHkdfTestKey(curve_type, ec_point_format, hash_type); auto params = ecies_key.mutable_public_key()->mutable_params(); AesGcmKeyFormat key_format; key_format.set_key_size(aes_gcm_key_size); auto aead_dem = params->mutable_dem_params()->mutable_aead_dem(); auto key_manager = std::make_unique(); std::string dem_key_type = key_manager->get_key_type(); aead_dem->set_type_url(dem_key_type); aead_dem->set_value(key_format.SerializeAsString()); return ecies_key; } EciesAeadHkdfPrivateKey GetEciesAesCtrHmacHkdfTestKey( google::crypto::tink::EllipticCurveType curve_type, google::crypto::tink::EcPointFormat ec_point_format, google::crypto::tink::HashType hash_type, uint32_t aes_ctr_key_size, uint32_t aes_ctr_iv_size, google::crypto::tink::HashType hmac_hash_type, uint32_t hmac_tag_size, uint32_t hmac_key_size) { auto ecies_key = GetEciesAeadHkdfTestKey(curve_type, ec_point_format, hash_type); google::crypto::tink::AesCtrHmacAeadKeyFormat key_format; auto aes_ctr_key_format = key_format.mutable_aes_ctr_key_format(); auto aes_ctr_params = aes_ctr_key_format->mutable_params(); aes_ctr_params->set_iv_size(aes_ctr_iv_size); aes_ctr_key_format->set_key_size(aes_ctr_key_size); auto hmac_key_format = key_format.mutable_hmac_key_format(); auto hmac_params = hmac_key_format->mutable_params(); hmac_params->set_hash(hmac_hash_type); hmac_params->set_tag_size(hmac_tag_size); hmac_key_format->set_key_size(hmac_key_size); auto params = ecies_key.mutable_public_key()->mutable_params(); auto aead_dem = params->mutable_dem_params()->mutable_aead_dem(); auto key_manager = std::make_unique(); std::string dem_key_type = key_manager->get_key_type(); aead_dem->set_type_url(dem_key_type); aead_dem->set_value(key_format.SerializeAsString()); return ecies_key; } EciesAeadHkdfPrivateKey GetEciesXChaCha20Poly1305HkdfTestKey( google::crypto::tink::EllipticCurveType curve_type, google::crypto::tink::EcPointFormat ec_point_format, google::crypto::tink::HashType hash_type) { auto ecies_key = GetEciesAeadHkdfTestKey(curve_type, ec_point_format, hash_type); auto params = ecies_key.mutable_public_key()->mutable_params(); google::crypto::tink::XChaCha20Poly1305KeyFormat key_format; auto aead_dem = params->mutable_dem_params()->mutable_aead_dem(); auto key_manager = std::make_unique(); std::string dem_key_type = key_manager->get_key_type(); aead_dem->set_type_url(dem_key_type); aead_dem->set_value(key_format.SerializeAsString()); return ecies_key; } google::crypto::tink::EciesAeadHkdfPrivateKey GetEciesAesSivHkdfTestKey( google::crypto::tink::EllipticCurveType curve_type, google::crypto::tink::EcPointFormat ec_point_format, google::crypto::tink::HashType hash_type) { auto ecies_key = GetEciesAeadHkdfTestKey(curve_type, ec_point_format, hash_type); auto params = ecies_key.mutable_public_key()->mutable_params(); google::crypto::tink::AesSivKeyFormat key_format; key_format.set_key_size(64); auto aead_dem = params->mutable_dem_params()->mutable_aead_dem(); AesSivKeyManager key_manager; std::string dem_key_type = key_manager.get_key_type(); aead_dem->set_type_url(dem_key_type); aead_dem->set_value(key_format.SerializeAsString()); return ecies_key; } EcdsaPrivateKey GetEcdsaTestPrivateKey( subtle::EllipticCurveType curve_type, subtle::HashType hash_type, subtle::EcdsaSignatureEncoding encoding) { return GetEcdsaTestPrivateKey(Enums::SubtleToProto(curve_type), Enums::SubtleToProto(hash_type), Enums::SubtleToProto(encoding)); } EcdsaPrivateKey GetEcdsaTestPrivateKey( google::crypto::tink::EllipticCurveType curve_type, google::crypto::tink::HashType hash_type, google::crypto::tink::EcdsaSignatureEncoding encoding) { auto test_key = internal::NewEcKey(Enums::ProtoToSubtle(curve_type)).value(); EcdsaPrivateKey ecdsa_key; ecdsa_key.set_version(0); ecdsa_key.set_key_value( std::string(util::SecretDataAsStringView(test_key.priv))); auto public_key = ecdsa_key.mutable_public_key(); public_key->set_version(0); public_key->set_x(test_key.pub_x); public_key->set_y(test_key.pub_y); auto params = public_key->mutable_params(); params->set_hash_type(hash_type); params->set_curve(curve_type); params->set_encoding(encoding); return ecdsa_key; } Ed25519PrivateKey GetEd25519TestPrivateKey() { auto test_key = internal::NewEd25519Key().value(); Ed25519PrivateKey ed25519_key; ed25519_key.set_version(0); ed25519_key.set_key_value(test_key->private_key); auto public_key = ed25519_key.mutable_public_key(); public_key->set_version(0); public_key->set_key_value(test_key->public_key); return ed25519_key; } util::Status ZTestUniformString(absl::string_view bytes) { double expected = bytes.size() * 8.0 / 2.0; double stddev = std::sqrt(static_cast(bytes.size()) * 8.0 / 4.0); uint64_t num_set_bits = 0; for (uint8_t byte : bytes) { // Counting the number of bits set in byte: while (byte != 0) { num_set_bits++; byte = byte & (byte - 1); } } // Check that the number of bits is within 10 stddevs. if (abs(static_cast(num_set_bits) - expected) < 10.0 * stddev) { return util::OkStatus(); } return util::Status( absl::StatusCode::kInternal, absl::StrCat("Z test for uniformly distributed variable out of bounds; " "Actual number of set bits was ", num_set_bits, " expected was ", expected, " 10 * standard deviation is 10 * ", stddev, " = ", 10.0 * stddev)); } std::string Rotate(absl::string_view bytes) { std::string result(bytes.size(), '\0'); for (int i = 0; i < bytes.size(); i++) { result[i] = (static_cast(bytes[i]) >> 1) | (bytes[(i == 0 ? bytes.size() : i) - 1] << 7); } return result; } util::Status ZTestCrosscorrelationUniformStrings(absl::string_view bytes1, absl::string_view bytes2) { if (bytes1.size() != bytes2.size()) { return util::Status(absl::StatusCode::kInvalidArgument, "Strings are not of equal length"); } std::string crossed(bytes1.size(), '\0'); for (int i = 0; i < bytes1.size(); i++) { crossed[i] = bytes1[i] ^ bytes2[i]; } return ZTestUniformString(crossed); } util::Status ZTestAutocorrelationUniformString(absl::string_view bytes) { std::string rotated(bytes); std::vector violations; for (int i = 1; i < bytes.size() * 8; i++) { rotated = Rotate(rotated); auto status = ZTestCrosscorrelationUniformStrings(bytes, rotated); if (!status.ok()) { violations.push_back(i); } } if (violations.empty()) { return util::OkStatus(); } return util::Status( absl::StatusCode::kInternal, absl::StrCat("Autocorrelation exceeded 10 standard deviation at ", violations.size(), " indices: ", absl::StrJoin(violations, ", "))); } } // namespace test } // namespace tink } // namespace crypto ================================================ FILE: cc/util/test_util.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_UTIL_TEST_UTIL_H_ #define TINK_UTIL_TEST_UTIL_H_ #include #include #include #include #include #include #include "absl/base/thread_annotations.h" #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/cord.h" #include "absl/strings/match.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" #include "tink/aead.h" #include "tink/aead/cord_aead.h" #include "tink/cleartext_keyset_handle.h" #include "tink/deterministic_aead.h" #include "tink/hybrid_decrypt.h" #include "tink/hybrid_encrypt.h" #include "tink/input_stream.h" #include "tink/keyderivation/keyset_deriver.h" #include "tink/keyset_handle.h" #include "tink/keyset_writer.h" #include "tink/kms_client.h" #include "tink/mac.h" #include "tink/output_stream.h" #include "tink/public_key_sign.h" #include "tink/public_key_verify.h" #include "tink/random_access_stream.h" #include "tink/streaming_aead.h" #include "tink/subtle/common_enums.h" #include "tink/subtle/mac/stateful_mac.h" #include "tink/util/buffer.h" #include "tink/util/constants.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "proto/common.pb.h" #include "proto/ecdsa.pb.h" #include "proto/ecies_aead_hkdf.pb.h" #include "proto/ed25519.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace test { // Various utilities for testing. /////////////////////////////////////////////////////////////////////////////// // Reads the test file specified by `filename`, and returns its contents. std::string ReadTestFile(absl::string_view filename); // Converts a hexadecimal string into a string of bytes. // Returns a status if the size of the input is odd or if the input contains // characters that are not hexadecimal. crypto::tink::util::StatusOr HexDecode(absl::string_view hex); // Converts a hexadecimal string into a string of bytes. // Dies if the input is not a valid hexadecimal string. std::string HexDecodeOrDie(absl::string_view hex); // Converts a string of bytes into a hexadecimal string. std::string HexEncode(absl::string_view bytes); // Returns a temporary directory suitable for temporary testing files. std::string TmpDir(); // Adds the given 'keyData' with specified status, key_id, and // output_prefix_type to the keyset. void AddKeyData(const google::crypto::tink::KeyData& key_data, uint32_t key_id, google::crypto::tink::OutputPrefixType output_prefix, google::crypto::tink::KeyStatusType key_status, google::crypto::tink::Keyset* keyset); // Adds the given 'key' with specified parameters and output_prefix_type=TINK // to the specified 'keyset'. void AddTinkKey(const std::string& key_type, uint32_t key_id, const portable_proto::MessageLite& key, google::crypto::tink::KeyStatusType key_status, google::crypto::tink::KeyData::KeyMaterialType material_type, google::crypto::tink::Keyset* keyset); // Adds the given 'key' with specified parameters and output_prefix_type=LEGACY // to the specified 'keyset'. void AddLegacyKey(const std::string& key_type, uint32_t key_id, const portable_proto::MessageLite& key, google::crypto::tink::KeyStatusType key_status, google::crypto::tink::KeyData::KeyMaterialType material_type, google::crypto::tink::Keyset* keyset); // Adds the given 'key' with specified parameters and output_prefix_type=RAW // to the specified 'keyset'. void AddRawKey(const std::string& key_type, uint32_t key_id, const portable_proto::MessageLite& key, google::crypto::tink::KeyStatusType key_status, google::crypto::tink::KeyData::KeyMaterialType material_type, google::crypto::tink::Keyset* keyset); // Generates a fresh test key for ECIES-AEAD-HKDF for the given curve, // using AesGcm with the specified key size as AEAD, and HKDF with 'hash_type'. google::crypto::tink::EciesAeadHkdfPrivateKey GetEciesAesGcmHkdfTestKey( subtle::EllipticCurveType curve_type, subtle::EcPointFormat ec_point_format, subtle::HashType hash_type, uint32_t aes_gcm_key_size); // Generates a fresh test key for ECIES-AEAD-HKDF for the given curve, // using AesGcm with the specified key size as AEAD, and HKDF with 'hash_type'. google::crypto::tink::EciesAeadHkdfPrivateKey GetEciesAesGcmHkdfTestKey( google::crypto::tink::EllipticCurveType curve_type, google::crypto::tink::EcPointFormat ec_point_format, google::crypto::tink::HashType hash_type, uint32_t aes_gcm_key_size); // Generates a fresh test key for ECIES-AEAD-HKDF for the given curve, // using XChaCha20Poly1305 as AEAD, and HKDF with 'hash_type'. google::crypto::tink::EciesAeadHkdfPrivateKey GetEciesXChaCha20Poly1305HkdfTestKey( google::crypto::tink::EllipticCurveType curve_type, google::crypto::tink::EcPointFormat ec_point_format, google::crypto::tink::HashType hash_type); // Generates a fresh test key for ECIES-AEAD-HKDF for the given curve, // using AesCtrHmac with the specified AEAD params, and HKDF with 'hash_type'. google::crypto::tink::EciesAeadHkdfPrivateKey GetEciesAesCtrHmacHkdfTestKey( google::crypto::tink::EllipticCurveType curve_type, google::crypto::tink::EcPointFormat ec_point_format, google::crypto::tink::HashType hash_type, uint32_t aes_ctr_key_size, uint32_t aes_ctr_iv_size, google::crypto::tink::HashType hmac_hash_type, uint32_t hmac_tag_size, uint32_t hmac_key_size); // Generates a fresh test key for ECIES-AEAD-HKDF for the given curve, // using AesSiv as the determinisitic AEAD, and HKDF with 'hash_type'. google::crypto::tink::EciesAeadHkdfPrivateKey GetEciesAesSivHkdfTestKey( google::crypto::tink::EllipticCurveType curve_type, google::crypto::tink::EcPointFormat ec_point_format, google::crypto::tink::HashType hash_type); // Generates a fresh test key for EC DSA for the given 'curve_type', 'hash_type' // and 'encoding'. google::crypto::tink::EcdsaPrivateKey GetEcdsaTestPrivateKey( subtle::EllipticCurveType curve_type, subtle::HashType hash_type, subtle::EcdsaSignatureEncoding encoding); // Generates a fresh test key for EC DSA for the given 'curve_type', 'hash_type' // and 'encoding'. google::crypto::tink::EcdsaPrivateKey GetEcdsaTestPrivateKey( google::crypto::tink::EllipticCurveType curve_type, google::crypto::tink::HashType hash_type, google::crypto::tink::EcdsaSignatureEncoding encoding); // TODO(ambrosin): Remove because it is unused. // Generates a fresh test key for ED25519. google::crypto::tink::Ed25519PrivateKey GetEd25519TestPrivateKey(); // Embeds the given Proto into a KeyData proto. template google::crypto::tink::KeyData AsKeyData( const Proto& proto, google::crypto::tink::KeyData::KeyMaterialType key_material_type) { google::crypto::tink::KeyData result; result.set_value(proto.SerializeAsString()); result.set_type_url(absl::StrCat(kTypeGoogleapisCom, proto.GetTypeName())); result.set_key_material_type(key_material_type); return result; } // Uses a z test on the given byte string, expecting all bits to be uniformly // set with probability 1/2. Returns non ok status if the z test fails by more // than 10 standard deviations. // // With less statistics jargon: This counts the number of bits set and expects // the number to be roughly half of the length of the string. The law of large // numbers suggests that we can assume that the longer the string is, the more // accurate that estimate becomes for a random string. This test is useful to // detect things like strings that are entirely zero. // // Note: By itself, this is a very weak test for randomness. util::Status ZTestUniformString(absl::string_view bytes); // Tests that the crosscorrelation of two strings of equal length points to // independent and uniformly distributed strings. Returns non ok status if the z // test fails by more than 10 standard deviations. // // With less statistics jargon: This xors two strings and then performs the // ZTestUniformString on the result. If the two strings are independent and // uniformly distributed, the xor'ed string is as well. A cross correlation test // will find whether two strings overlap more or less than it would be expected. // // Note: Having a correlation of zero is only a necessary but not sufficient // condition for independence. util::Status ZTestCrosscorrelationUniformStrings(absl::string_view bytes1, absl::string_view bytes2); // Tests that the autocorrelation of a string points to the bits being // independent and uniformly distributed. Rotates the string in a cyclic // fashion. Returns non ok status if the z test fails by more than 10 standard // deviations. // // With less statistics jargon: This rotates the string bit by bit and performs // ZTestCrosscorrelationUniformStrings on each of the rotated strings and the // original. This will find self similarity of the input string, especially // periodic self similarity. For example, it is a decent test to find English // text (needs about 180 characters with the current settings). // // Note: Having a correlation of zero is only a necessary but not sufficient // condition for independence. util::Status ZTestAutocorrelationUniformString(absl::string_view bytes); // A dummy implementation of Aead-interface. // An instance of DummyAead can be identified by a name specified // as a parameter of the constructor. class DummyAead : public Aead { public: explicit DummyAead(absl::string_view aead_name) : aead_name_(aead_name) {} // Computes a dummy ciphertext, which is concatenation of provided 'plaintext' // with the name of this DummyAead. crypto::tink::util::StatusOr Encrypt( absl::string_view plaintext, absl::string_view associated_data) const override { return absl::StrCat(aead_name_.size(), ":", associated_data.size(), ":", aead_name_, associated_data, plaintext); } crypto::tink::util::StatusOr Decrypt( absl::string_view ciphertext, absl::string_view associated_data) const override { std::string prefix = absl::StrCat(aead_name_.size(), ":", associated_data.size(), ":", aead_name_, associated_data); if (!absl::StartsWith(ciphertext, prefix)) { return crypto::tink::util::Status(absl::StatusCode::kInvalidArgument, "Dummy operation failed."); } ciphertext.remove_prefix(prefix.size()); return std::string(ciphertext); } private: std::string aead_name_; }; // A dummy implementation of CordAead-interface. // An instance of DummyCordAead can be identified by a name specified // as a parameter of the constructor. class DummyCordAead : public CordAead { public: explicit DummyCordAead(absl::string_view aead_name) : aead_(aead_name) {} // Computes a dummy ciphertext, which is concatenation of provided 'plaintext' // with the name of this DummyCordAead. crypto::tink::util::StatusOr Encrypt( absl::Cord plaintext, absl::Cord associated_data) const override { auto ciphertext = aead_.Encrypt(plaintext.Flatten(), associated_data.Flatten()); if (!ciphertext.ok()) return ciphertext.status(); absl::Cord ciphertext_cord; ciphertext_cord.Append(ciphertext.value()); return ciphertext_cord; } crypto::tink::util::StatusOr Decrypt( absl::Cord ciphertext, absl::Cord associated_data) const override { auto plaintext = aead_.Decrypt(ciphertext.Flatten(), associated_data.Flatten()); if (!plaintext.ok()) return plaintext.status(); absl::Cord plaintext_cord; plaintext_cord.Append(plaintext.value()); return plaintext_cord; } private: DummyAead aead_; }; // A dummy implementation of DeterministicAead-interface. // An instance of DummyDeterministicAead can be identified by a name specified // as a parameter of the constructor. // The implementation is the same as DummyAead. class DummyDeterministicAead : public DeterministicAead { public: explicit DummyDeterministicAead(absl::string_view daead_name) : aead_(daead_name) {} crypto::tink::util::StatusOr EncryptDeterministically( absl::string_view plaintext, absl::string_view associated_data) const override { return aead_.Encrypt(plaintext, associated_data); } crypto::tink::util::StatusOr DecryptDeterministically( absl::string_view ciphertext, absl::string_view associated_data) const override { return aead_.Decrypt(ciphertext, associated_data); } private: DummyAead aead_; }; // A dummy implementation of StreamingAead-interface. An instance of // DummyStreamingAead can be identified by a name specified as a parameter of // the constructor. This name concatenated with 'associated_data' for a // specific stream yields a header of an encrypted stream produced/consumed // by DummyStreamingAead. class DummyStreamingAead : public StreamingAead { public: explicit DummyStreamingAead(absl::string_view streaming_aead_name) : streaming_aead_name_(streaming_aead_name) {} crypto::tink::util::StatusOr> NewEncryptingStream( std::unique_ptr ciphertext_destination, absl::string_view associated_data) const override { return {absl::make_unique( std::move(ciphertext_destination), absl::StrCat(streaming_aead_name_, associated_data))}; } crypto::tink::util::StatusOr> NewDecryptingStream( std::unique_ptr ciphertext_source, absl::string_view associated_data) const override { return {absl::make_unique( std::move(ciphertext_source), absl::StrCat(streaming_aead_name_, associated_data))}; } crypto::tink::util::StatusOr< std::unique_ptr> NewDecryptingRandomAccessStream( std::unique_ptr ciphertext_source, absl::string_view associated_data) const override { return {absl::make_unique( std::move(ciphertext_source), absl::StrCat(streaming_aead_name_, associated_data))}; } // Upon first call to Next() writes to 'ct_dest' the specifed 'header', // and subsequently forwards all methods calls to the corresponding // methods of 'cd_dest'. class DummyEncryptingStream : public crypto::tink::OutputStream { public: DummyEncryptingStream(std::unique_ptr ct_dest, absl::string_view header) : ct_dest_(std::move(ct_dest)), header_(header), after_init_(false), status_(util::OkStatus()) {} crypto::tink::util::StatusOr Next(void** data) override { if (!after_init_) { // Try to initialize. after_init_ = true; auto next_result = ct_dest_->Next(data); if (!next_result.ok()) { status_ = next_result.status(); return status_; } if (next_result.value() < header_.size()) { status_ = util::Status(absl::StatusCode::kInternal, "Buffer too small"); } else { memcpy(*data, header_.data(), static_cast(header_.size())); ct_dest_->BackUp(next_result.value() - header_.size()); } } if (!status_.ok()) return status_; return ct_dest_->Next(data); } void BackUp(int count) override { if (after_init_ && status_.ok()) { ct_dest_->BackUp(count); } } int64_t Position() const override { if (after_init_ && status_.ok()) { return ct_dest_->Position() - header_.size(); } else { return 0; } } util::Status Close() override { if (!after_init_) { // Call Next() to write the header to ct_dest_. void* buf; auto next_result = Next(&buf); if (next_result.ok()) { BackUp(next_result.value()); } else { status_ = next_result.status(); return status_; } } return ct_dest_->Close(); } private: std::unique_ptr ct_dest_; std::string header_; bool after_init_; util::Status status_; }; // class DummyEncryptingStream // Upon first call to Next() tries to read from 'ct_source' a header // that is expected to be equal to 'expected_header'. If this // header matching succeeds, all subsequent method calls are forwarded // to the corresponding methods of 'cd_source'. class DummyDecryptingStream : public crypto::tink::InputStream { public: DummyDecryptingStream(std::unique_ptr ct_source, absl::string_view expected_header) : ct_source_(std::move(ct_source)), exp_header_(expected_header), after_init_(false), status_(util::OkStatus()) {} crypto::tink::util::StatusOr Next(const void** data) override { if (!after_init_) { // Try to initialize. after_init_ = true; auto next_result = ct_source_->Next(data); if (!next_result.ok()) { status_ = next_result.status(); if (status_.code() == absl::StatusCode::kOutOfRange) { status_ = util::Status(absl::StatusCode::kInvalidArgument, "Could not read header"); } return status_; } if (next_result.value() < exp_header_.size()) { status_ = util::Status(absl::StatusCode::kInternal, "Buffer too small"); } else if (memcmp((*data), exp_header_.data(), static_cast(exp_header_.size()))) { status_ = util::Status(absl::StatusCode::kInvalidArgument, "Corrupted header"); } if (status_.ok()) { ct_source_->BackUp(next_result.value() - exp_header_.size()); } } if (!status_.ok()) return status_; return ct_source_->Next(data); } void BackUp(int count) override { if (after_init_ && status_.ok()) { ct_source_->BackUp(count); } } int64_t Position() const override { if (after_init_ && status_.ok()) { return ct_source_->Position() - exp_header_.size(); } else { return 0; } } private: std::unique_ptr ct_source_; std::string exp_header_; bool after_init_; util::Status status_; }; // class DummyDecryptingStream // Upon first call to PRead() tries to read from `ct_source` a header // that is expected to be equal to `expected_header`. If this // header matching succeeds, all subsequent method calls are forwarded // to `ct_source->PRead`. class DummyDecryptingRandomAccessStream : public crypto::tink::RandomAccessStream { public: DummyDecryptingRandomAccessStream( std::unique_ptr ct_source, absl::string_view expected_header) : ct_source_(std::move(ct_source)), exp_header_(expected_header) {} crypto::tink::util::Status PRead( int64_t position, int count, crypto::tink::util::Buffer* dest_buffer) override { util::Status status = CheckHeader(); if (!status.ok()) { return status; } status = dest_buffer->set_size(0); if (!status.ok()) return status; return ct_source_->PRead(position + exp_header_.size(), count, dest_buffer); } util::StatusOr size() override { util::Status status = CheckHeader(); if (!status.ok()) { return status; } auto ct_size_result = ct_source_->size(); if (!ct_size_result.ok()) return ct_size_result.status(); auto pt_size = ct_size_result.value() - exp_header_.size(); if (pt_size >= 0) return pt_size; return util::Status(absl::StatusCode::kUnavailable, "size not available"); } private: util::Status CheckHeader() ABSL_LOCKS_EXCLUDED(header_check_status_mutex_) { absl::MutexLock lock(&header_check_status_mutex_); if (header_check_status_.code() != absl::StatusCode::kUnavailable) { return header_check_status_; } auto buf = std::move(util::Buffer::New(exp_header_.size()).value()); header_check_status_ = ct_source_->PRead(0, exp_header_.size(), buf.get()); if (!header_check_status_.ok() && header_check_status_.code() != absl::StatusCode::kOutOfRange) { return header_check_status_; } // EOF or Ok indicate a valid read has happened. header_check_status_ = util::OkStatus(); // Invalid header. if (buf->size() < exp_header_.size()) { header_check_status_ = util::Status(absl::StatusCode::kInvalidArgument, "Could not read header"); } else if (memcmp(buf->get_mem_block(), exp_header_.data(), static_cast(exp_header_.size()))) { header_check_status_ = util::Status(absl::StatusCode::kInvalidArgument, "Corrupted header"); } return header_check_status_; } std::unique_ptr ct_source_; std::string exp_header_; mutable absl::Mutex header_check_status_mutex_; util::Status header_check_status_ ABSL_GUARDED_BY(header_check_status_mutex_) = util::Status(absl::StatusCode::kUnavailable, "Uninitialized"); }; // class DummyDecryptingRandomAccessStream private: std::string streaming_aead_name_; }; // class DummyStreamingAead // A dummy implementation of HybridEncrypt-interface. // An instance of DummyHybridEncrypt can be identified by a name specified // as a parameter of the constructor. class DummyHybridEncrypt : public HybridEncrypt { public: explicit DummyHybridEncrypt(absl::string_view hybrid_name) : dummy_aead_(absl::StrCat("DummyHybrid:", hybrid_name)) {} // Computes a dummy ciphertext, which is concatenation of provided 'plaintext' // with the name of this DummyHybridEncrypt. crypto::tink::util::StatusOr Encrypt( absl::string_view plaintext, absl::string_view context_info) const override { return dummy_aead_.Encrypt(plaintext, context_info); } private: DummyAead dummy_aead_; }; // A dummy implementation of HybridDecrypt-interface. // An instance of DummyHybridDecrypt can be identified by a name specified // as a parameter of the constructor. class DummyHybridDecrypt : public HybridDecrypt { public: explicit DummyHybridDecrypt(absl::string_view hybrid_name) : dummy_aead_(absl::StrCat("DummyHybrid:", hybrid_name)) {} // Decrypts a dummy ciphertext, which should be a concatenation // of a plaintext with the name of this DummyHybridDecrypt. crypto::tink::util::StatusOr Decrypt( absl::string_view ciphertext, absl::string_view context_info) const override { return dummy_aead_.Decrypt(ciphertext, context_info); } private: DummyAead dummy_aead_; }; // A dummy implementation of PublicKeySign-interface. // An instance of DummyPublicKeySign can be identified by a name specified // as a parameter of the constructor. class DummyPublicKeySign : public PublicKeySign { public: explicit DummyPublicKeySign(absl::string_view signature_name) : dummy_aead_(absl::StrCat("DummySign:", signature_name)) {} // Computes a dummy signature, which is a concatenation of 'data' // with the name of this DummyPublicKeySign. crypto::tink::util::StatusOr Sign( absl::string_view data) const override { return dummy_aead_.Encrypt("", data); } private: DummyAead dummy_aead_; }; // A dummy implementation of PublicKeyVerify-interface. // An instance of DummyPublicKeyVerify can be identified by a name specified // as a parameter of the constructor. class DummyPublicKeyVerify : public PublicKeyVerify { public: explicit DummyPublicKeyVerify(absl::string_view signature_name) : dummy_aead_(absl::StrCat("DummySign:", signature_name)) {} // Verifies a dummy signature, should be a concatenation of the name // of this DummyPublicKeyVerify with the provided 'data'. crypto::tink::util::Status Verify(absl::string_view signature, absl::string_view data) const override { return dummy_aead_.Decrypt(signature, data).status(); } private: DummyAead dummy_aead_; }; // A dummy implementation of Mac-interface. // An instance of DummyMac can be identified by a name specified // as a parameter of the constructor. class DummyMac : public Mac { public: explicit DummyMac(const std::string& mac_name) : dummy_aead_(absl::StrCat("DummyMac:", mac_name)) {} // Computes a dummy MAC, which is concatenation of provided 'data' // with the name of this DummyMac. crypto::tink::util::StatusOr ComputeMac( absl::string_view data) const override { return dummy_aead_.Encrypt("", data); } crypto::tink::util::Status VerifyMac(absl::string_view mac, absl::string_view data) const override { return dummy_aead_.Decrypt(mac, data).status(); } private: DummyAead dummy_aead_; }; // A dummy implementation of Stateful Mac interface. // An instance of DummyStatefulMac can be identified by a name specified // as a parameter of the constructor. // Over the same inputs, the DummyStatefulMac and DummyMac should give the same // output; DummyStatefulMac builds and internal_state_ and calls DummyMac. class DummyStatefulMac : public subtle::StatefulMac { public: explicit DummyStatefulMac(const std::string& mac_name) : dummy_aead_(absl::StrCat("DummyMac:", mac_name)), buffer_("") {} util::Status Update(absl::string_view data) override { absl::StrAppend(&buffer_, data); return util::OkStatus(); } util::StatusOr Finalize() override { return dummy_aead_.Encrypt("", buffer_); } private: DummyAead dummy_aead_; std::string buffer_; }; // A dummy implementation of KeysetWriter-interface. class DummyKeysetWriter : public KeysetWriter { public: static util::StatusOr> New( std::unique_ptr destination_stream) { return absl::WrapUnique( new DummyKeysetWriter(std::move(destination_stream))); } util::Status Write(const google::crypto::tink::Keyset& keyset) override { return util::OkStatus(); } util::Status Write( const google::crypto::tink::EncryptedKeyset& encrypted_keyset) override { return util::OkStatus(); } private: explicit DummyKeysetWriter(std::unique_ptr destination_stream) : destination_stream_(std::move(destination_stream)) {} std::unique_ptr destination_stream_; }; // A dummy implementation of KmsClient-interface. class DummyKmsClient : public KmsClient { public: DummyKmsClient(absl::string_view uri_prefix, absl::string_view key_uri) : uri_prefix_(uri_prefix), key_uri_(key_uri) {} bool DoesSupport(absl::string_view key_uri) const override { if (key_uri.empty()) return false; if (key_uri_.empty()) return absl::StartsWith(key_uri, uri_prefix_); return key_uri == key_uri_; } crypto::tink::util::StatusOr> GetAead( absl::string_view key_uri) const override { if (!DoesSupport(key_uri)) return crypto::tink::util::Status(absl::StatusCode::kInvalidArgument, "key_uri not supported"); return {absl::make_unique(key_uri)}; } ~DummyKmsClient() override = default; private: std::string uri_prefix_; std::string key_uri_; }; class FakeKeysetDeriver : public KeysetDeriver { public: explicit FakeKeysetDeriver(absl::string_view name) : name_(name) {} util::StatusOr> DeriveKeyset( absl::string_view salt) const override { google::crypto::tink::Keyset::Key key; key.mutable_key_data()->set_type_url( absl::StrCat(name_.size(), ":", name_, salt)); key.set_status(google::crypto::tink::KeyStatusType::UNKNOWN_STATUS); key.set_key_id(119); key.set_output_prefix_type( google::crypto::tink::OutputPrefixType::UNKNOWN_PREFIX); google::crypto::tink::Keyset keyset; *keyset.add_key() = key; keyset.set_primary_key_id(119); return CleartextKeysetHandle::GetKeysetHandle(keyset); } private: std::string name_; }; } // namespace test } // namespace tink } // namespace crypto #endif // TINK_UTIL_TEST_UTIL_H_ ================================================ FILE: cc/util/test_util_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/test_util.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "absl/strings/cord.h" #include "absl/strings/string_view.h" #include "tink/internal/test_random_access_stream.h" #include "tink/keyset_handle.h" #include "tink/output_stream.h" #include "tink/random_access_stream.h" #include "tink/subtle/random.h" #include "tink/subtle/test_util.h" #include "tink/util/buffer.h" #include "tink/util/ostream_output_stream.h" #include "tink/util/status.h" #include "tink/util/statusor.h" #include "tink/util/test_matchers.h" #include "proto/aes_gcm.pb.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace test { namespace { using ::crypto::tink::internal::TestRandomAccessStream; using ::crypto::tink::test::StatusIs; using ::google::crypto::tink::AesGcmKey; using ::google::crypto::tink::KeyData; using ::testing::Eq; using ::testing::Not; TEST(AsKeyDataTest, Basic) { AesGcmKey key; key.set_key_value(crypto::tink::subtle::Random::GetRandomBytes(11)); KeyData key_data = AsKeyData(key, KeyData::SYMMETRIC); EXPECT_THAT(key_data.type_url(), Eq("type.googleapis.com/google.crypto.tink.AesGcmKey")); EXPECT_THAT(key_data.key_material_type(), Eq(KeyData::SYMMETRIC)); AesGcmKey deserialized_key; EXPECT_TRUE(deserialized_key.ParseFromString(key_data.value())); EXPECT_THAT(deserialized_key.key_value(), Eq(key.key_value())); } TEST(DummyTests, Aead) { EXPECT_THAT(DummyAead("dummy").Encrypt("foo", "bar").value(), Eq("5:3:dummybarfoo")); } TEST(DummyTests, AeadCord) { absl::Cord plaintext; plaintext.Append("foo"); absl::Cord aad; aad.Append("bar"); EXPECT_THAT(DummyCordAead("dummy").Encrypt(plaintext, aad).value(), Eq("5:3:dummybarfoo")); } TEST(DummyTests, AeadCordMultipleChunks) { absl::Cord plaintext; plaintext.Append("f"); plaintext.Append("o"); plaintext.Append("o"); absl::Cord aad; aad.Append("b"); aad.Append("a"); aad.Append("r"); EXPECT_THAT(DummyCordAead("dummy").Encrypt(plaintext, aad).value(), Eq("5:3:dummybarfoo")); } TEST(ZTests, UniformString) { EXPECT_THAT(ZTestUniformString(std::string(32, 0xaa)), IsOk()); EXPECT_THAT(ZTestUniformString(std::string(32, 0x00)), Not(IsOk())); EXPECT_THAT(ZTestUniformString(subtle::Random::GetRandomBytes(32)), IsOk()); } TEST(ZTests, CrossCorrelationUniformString) { EXPECT_THAT(ZTestCrosscorrelationUniformStrings(std::string(32, 0xaa), std::string(32, 0x99)), IsOk()); EXPECT_THAT(ZTestCrosscorrelationUniformStrings(std::string(32, 0xaa), std::string(32, 0xaa)), Not(IsOk())); EXPECT_THAT( ZTestCrosscorrelationUniformStrings(subtle::Random::GetRandomBytes(32), subtle::Random::GetRandomBytes(32)), IsOk()); } TEST(ZTests, AutocorrelationUniformString) { EXPECT_THAT(ZTestAutocorrelationUniformString(std::string(32, 0xaa)), Not(IsOk())); EXPECT_THAT(ZTestAutocorrelationUniformString(std::string( "This is a text that is only ascii characters and therefore " "not random. It needs quite a few characters before it has " "enough to find a pattern, though, as it is text.")), Not(IsOk())); EXPECT_THAT( ZTestAutocorrelationUniformString(subtle::Random::GetRandomBytes(32)), IsOk()); } TEST(DummyStreamingAead, DummyDecryptingStreamPreadAllAtOnceSucceeds) { const int stream_size = 1024; std::string stream_content = subtle::Random::GetRandomBytes(stream_size); auto ostream = std::make_unique(); auto string_stream_buffer = ostream->rdbuf(); auto output_stream = std::make_unique(std::move(ostream)); DummyStreamingAead streaming_aead("Some AEAD"); util::StatusOr> encrypting_output_stream = streaming_aead.NewEncryptingStream(std::move(output_stream), "Some AAD"); ASSERT_THAT(encrypting_output_stream.status(), IsOk()); ASSERT_THAT(subtle::test::WriteToStream( encrypting_output_stream.value().get(), stream_content), IsOk()); std::string ciphertext = string_stream_buffer->str(); auto test_random_access_stream = std::make_unique(ciphertext); util::StatusOr> decrypting_random_access_stream = streaming_aead.NewDecryptingRandomAccessStream( std::move(test_random_access_stream), "Some AAD"); ASSERT_THAT(decrypting_random_access_stream.status(), IsOk()); auto buffer = util::Buffer::New(ciphertext.size()); EXPECT_THAT((*decrypting_random_access_stream) ->PRead(/*position=*/0, ciphertext.size(), buffer->get()), StatusIs(absl::StatusCode::kOutOfRange)); EXPECT_EQ(stream_content, std::string((*buffer)->get_mem_block(), (*buffer)->size())); } TEST(DummyStreamingAead, DummyDecryptingStreamPreadInChunksSucceeds) { const int stream_size = 1024; std::string stream_content = subtle::Random::GetRandomBytes(stream_size); auto ostream = std::make_unique(); auto string_stream_buffer = ostream->rdbuf(); auto output_stream = std::make_unique(std::move(ostream)); DummyStreamingAead streaming_aead("Some AEAD"); util::StatusOr> encrypting_output_stream = streaming_aead.NewEncryptingStream(std::move(output_stream), "Some AAD"); ASSERT_THAT(encrypting_output_stream.status(), IsOk()); ASSERT_THAT(subtle::test::WriteToStream( encrypting_output_stream.value().get(), stream_content), IsOk()); std::string ciphertext = string_stream_buffer->str(); auto test_random_access_stream = std::make_unique(ciphertext); util::StatusOr> decrypting_random_access_stream = streaming_aead.NewDecryptingRandomAccessStream( std::move(test_random_access_stream), "Some AAD"); ASSERT_THAT(decrypting_random_access_stream.status(), IsOk()); int chunk_size = 10; auto buffer = util::Buffer::New(chunk_size); std::string plaintext; int64_t position = 0; util::Status status = (*decrypting_random_access_stream) ->PRead(position, chunk_size, buffer->get()); while (status.ok()) { plaintext.append((*buffer)->get_mem_block(), (*buffer)->size()); position += (*buffer)->size(); status = (*decrypting_random_access_stream) ->PRead(position, chunk_size, buffer->get()); } EXPECT_THAT(status, StatusIs(absl::StatusCode::kOutOfRange)); plaintext.append((*buffer)->get_mem_block(), (*buffer)->size()); EXPECT_EQ(stream_content, plaintext); } TEST(DummyStreamingAead, DummyDecryptingStreamPreadWithSmallerHeaderFails) { const int stream_size = 1024; std::string stream_content = subtle::Random::GetRandomBytes(stream_size); auto ostream = std::make_unique(); auto output_stream = std::make_unique(std::move(ostream)); constexpr absl::string_view kStreamingAeadName = "Some AEAD"; constexpr absl::string_view kStreamingAeadAad = "Some associated data"; DummyStreamingAead streaming_aead(kStreamingAeadName); util::StatusOr> encrypting_output_stream = streaming_aead.NewEncryptingStream(std::move(output_stream), kStreamingAeadAad); ASSERT_THAT(encrypting_output_stream.status(), IsOk()); ASSERT_THAT(subtle::test::WriteToStream( encrypting_output_stream.value().get(), stream_content), IsOk()); // Stream content size is too small; DummyDecryptingStream expects // absl::StrCat(kStreamingAeadName, kStreamingAeadAad). std::string ciphertext = "Invalid header"; auto test_random_access_stream = std::make_unique(ciphertext); util::StatusOr> decrypting_random_access_stream = streaming_aead.NewDecryptingRandomAccessStream( std::move(test_random_access_stream), kStreamingAeadAad); ASSERT_THAT(decrypting_random_access_stream.status(), IsOk()); int chunk_size = 10; auto buffer = util::Buffer::New(chunk_size); EXPECT_THAT( (*decrypting_random_access_stream) ->PRead(/*position=*/0, chunk_size, buffer->get()), StatusIs(absl::StatusCode::kInvalidArgument, "Could not read header")); EXPECT_THAT( (*decrypting_random_access_stream) ->PRead(/*position=*/0, chunk_size, buffer->get()), StatusIs(absl::StatusCode::kInvalidArgument, "Could not read header")); EXPECT_THAT( (*decrypting_random_access_stream)->size().status(), StatusIs(absl::StatusCode::kInvalidArgument, "Could not read header")); } TEST(DummyStreamingAead, DummyDecryptingStreamPreadWithCorruptedAadFails) { const int stream_size = 1024; std::string stream_content = subtle::Random::GetRandomBytes(stream_size); auto ostream = std::make_unique(); auto string_stream_buffer = ostream->rdbuf(); auto output_stream = std::make_unique(std::move(ostream)); constexpr absl::string_view kStreamingAeadName = "Some AEAD"; constexpr absl::string_view kStreamingAeadAad = "Some associated data"; DummyStreamingAead streaming_aead(kStreamingAeadName); util::StatusOr> encrypting_output_stream = streaming_aead.NewEncryptingStream(std::move(output_stream), kStreamingAeadAad); ASSERT_THAT(encrypting_output_stream.status(), IsOk()); ASSERT_THAT(subtle::test::WriteToStream( encrypting_output_stream.value().get(), stream_content), IsOk()); // Invalid associated data. std::string ciphertext = string_stream_buffer->str(); auto test_random_access_stream = std::make_unique(ciphertext); util::StatusOr> decrypting_random_access_stream = streaming_aead.NewDecryptingRandomAccessStream( std::move(test_random_access_stream), "Some wrong AAD"); ASSERT_THAT(decrypting_random_access_stream.status(), IsOk()); int chunk_size = 10; auto buffer = util::Buffer::New(chunk_size); EXPECT_THAT((*decrypting_random_access_stream) ->PRead(/*position=*/0, chunk_size, buffer->get()), StatusIs(absl::StatusCode::kInvalidArgument, "Corrupted header")); EXPECT_THAT((*decrypting_random_access_stream) ->PRead(/*position=*/0, chunk_size, buffer->get()), StatusIs(absl::StatusCode::kInvalidArgument, "Corrupted header")); EXPECT_THAT((*decrypting_random_access_stream)->size().status(), StatusIs(absl::StatusCode::kInvalidArgument, "Corrupted header")); } TEST(FakeKeysetDeriver, DeriveKeyset) { FakeKeysetDeriver deriver("hello"); util::StatusOr> handle = deriver.DeriveKeyset("salty"); EXPECT_THAT(handle, IsOk()); EXPECT_THAT((*handle)->GetKeysetInfo().primary_key_id(), Eq(119)); EXPECT_THAT((*handle)->GetKeysetInfo().key_info_size(), Eq(1)); google::crypto::tink::KeysetInfo::KeyInfo info = (*handle)->GetKeysetInfo().key_info(0); EXPECT_THAT(info.type_url(), Eq("5:hellosalty")); EXPECT_THAT(info.status(), Eq(google::crypto::tink::KeyStatusType::UNKNOWN_STATUS)); EXPECT_THAT(info.key_id(), Eq(119)); EXPECT_THAT(info.output_prefix_type(), Eq(google::crypto::tink::OutputPrefixType::UNKNOWN_PREFIX)); } } // namespace } // namespace test } // namespace tink } // namespace crypto ================================================ FILE: cc/util/validation.cc ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/validation.h" #include #include "absl/status/status.h" #include "tink/util/errors.h" #include "tink/util/status.h" #include "proto/tink.pb.h" using google::crypto::tink::KeyData; using google::crypto::tink::Keyset; using google::crypto::tink::KeyStatusType; namespace crypto { namespace tink { util::Status ValidateAesKeySize(uint32_t key_size) { if (key_size != 16 && key_size != 32) { return ToStatusF(absl::StatusCode::kInvalidArgument, "AES key has %d bytes; supported sizes: 16 or 32 bytes.", key_size); } return util::OkStatus(); } util::Status ValidateKey(const Keyset::Key& key) { if (!key.has_key_data()) { return ToStatusF(absl::StatusCode::kInvalidArgument, "key %d, has no key data", key.key_id()); } if (key.output_prefix_type() == google::crypto::tink::OutputPrefixType::UNKNOWN_PREFIX) { return ToStatusF(absl::StatusCode::kInvalidArgument, "key %d has unknown prefix", key.key_id()); } if (key.status() == google::crypto::tink::KeyStatusType::UNKNOWN_STATUS) { return ToStatusF(absl::StatusCode::kInvalidArgument, "key %d has unknown status", key.key_id()); } return util::OkStatus(); } util::Status ValidateKeyset(const Keyset& keyset) { if (keyset.key_size() < 1) { return util::Status(absl::StatusCode::kInvalidArgument, "A valid keyset must contain at least one key."); } uint32_t primary_key_id = keyset.primary_key_id(); bool has_primary_key = false; bool contains_only_public_key_material = true; int enabled_keys = 0; for (int i = 0; i < keyset.key_size(); i++) { const Keyset::Key& key = keyset.key(i); if (key.status() != KeyStatusType::ENABLED) { continue; } enabled_keys += 1; auto validation_result = ValidateKey(key); if (!validation_result.ok()) { return validation_result; } if (key.status() == KeyStatusType::ENABLED && key.key_id() == primary_key_id) { if (has_primary_key) { return util::Status(absl::StatusCode::kInvalidArgument, "keyset contains multiple primary keys"); } has_primary_key = true; } if (key.key_data().key_material_type() != KeyData::ASYMMETRIC_PUBLIC) { contains_only_public_key_material = false; } } if (enabled_keys == 0) { return util::Status(absl::StatusCode::kInvalidArgument, "keyset must contain at least one ENABLED key"); } // A public key can be used for verification without being set as the primary // key. Therefore, it is okay to have a keyset that contains public but // doesn't have a primary key set. if (!has_primary_key && !contains_only_public_key_material) { return util::Status(absl::StatusCode::kInvalidArgument, "keyset doesn't contain a valid primary key"); } return util::OkStatus(); } util::Status ValidateVersion(uint32_t candidate, uint32_t max_expected) { if (candidate > max_expected) { return ToStatusF(absl::StatusCode::kInvalidArgument, "Key has version '%d'; " "only keys with version in range [0..%d] are supported.", candidate, max_expected); } return util::OkStatus(); } } // namespace tink } // namespace crypto ================================================ FILE: cc/util/validation.h ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_UTIL_VALIDATION_H_ #define TINK_UTIL_VALIDATION_H_ #include #include "tink/util/status.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { // Various validation helpers. crypto::tink::util::Status ValidateAesKeySize(uint32_t key_size); crypto::tink::util::Status ValidateKey( const google::crypto::tink::Keyset::Key& key); crypto::tink::util::Status ValidateKeyset( const google::crypto::tink::Keyset& keyset); crypto::tink::util::Status ValidateVersion( uint32_t candidate, uint32_t max_expected); } // namespace tink } // namespace crypto #endif // TINK_UTIL_VALIDATION_H_ ================================================ FILE: cc/util/validation_test.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "tink/util/validation.h" #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/status/status.h" #include "tink/util/test_matchers.h" #include "proto/tink.pb.h" namespace crypto { namespace tink { namespace { using crypto::tink::test::IsOk; using crypto::tink::test::StatusIs; using google::crypto::tink::KeyData; using testing::Not; TEST(ValidateKey, ValidKey) { google::crypto::tink::Keyset::Key key; key.set_key_id(100); key.mutable_key_data()->set_value("some value"); key.set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); key.set_status(google::crypto::tink::KeyStatusType::ENABLED); EXPECT_THAT(crypto::tink::ValidateKey(key), IsOk()); } TEST(ValidateKey, MissingOutputPrefixType) { google::crypto::tink::Keyset::Key key; key.set_key_id(100); key.mutable_key_data()->set_value("some value"); key.set_status(google::crypto::tink::KeyStatusType::ENABLED); EXPECT_THAT(crypto::tink::ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(ValidateKey, MissingKeyData) { google::crypto::tink::Keyset::Key key; key.set_key_id(100); key.set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); key.set_status(google::crypto::tink::KeyStatusType::ENABLED); EXPECT_THAT(crypto::tink::ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(ValidateKey, MissingStatus) { google::crypto::tink::Keyset::Key key; key.set_key_id(100); key.mutable_key_data()->set_value("some value"); key.set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); EXPECT_THAT(crypto::tink::ValidateKey(key), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(ValidateKeyset, Valid) { google::crypto::tink::Keyset keyset; google::crypto::tink::Keyset::Key* key = keyset.add_key(); key->set_key_id(100); key->mutable_key_data()->set_value("some value"); key->set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); key->set_status(google::crypto::tink::KeyStatusType::ENABLED); keyset.set_primary_key_id(100); EXPECT_THAT(crypto::tink::ValidateKeyset(keyset), IsOk()); } TEST(ValidateKeyset, ValidMultipleKeys) { google::crypto::tink::Keyset keyset; google::crypto::tink::Keyset::Key* key = keyset.add_key(); key->set_key_id(32); key->mutable_key_data()->set_value("some value"); key->set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); key->set_status(google::crypto::tink::KeyStatusType::ENABLED); key = keyset.add_key(); key->set_key_id(100); key->mutable_key_data()->set_value("some other value"); key->set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); key->set_status(google::crypto::tink::KeyStatusType::ENABLED); key = keyset.add_key(); key->set_key_id(18); key->mutable_key_data()->set_value("some third value"); key->set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); key->set_status(google::crypto::tink::KeyStatusType::ENABLED); keyset.set_primary_key_id(100); EXPECT_THAT(crypto::tink::ValidateKeyset(keyset), IsOk()); } // Tests that a keyset with duplicate primary id is rejected TEST(ValidateKeyset, DuplicatePrimaryId) { google::crypto::tink::Keyset keyset; google::crypto::tink::Keyset::Key* key = keyset.add_key(); key->set_key_id(100); key->mutable_key_data()->set_value("some value"); key->set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); key->set_status(google::crypto::tink::KeyStatusType::ENABLED); key = keyset.add_key(); key->set_key_id(100); key->mutable_key_data()->set_value("some other value"); key->set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); key->set_status(google::crypto::tink::KeyStatusType::ENABLED); keyset.set_primary_key_id(100); EXPECT_THAT(crypto::tink::ValidateKeyset(keyset), Not(IsOk())); } // Tests that a keyset with public keys only doesn't need a primary id TEST(ValidateKeyset, OnlyPublicKeys) { google::crypto::tink::Keyset keyset; google::crypto::tink::Keyset::Key* key = keyset.add_key(); key->set_key_id(32); key->mutable_key_data()->set_value("some value"); key->mutable_key_data()->set_key_material_type(KeyData::ASYMMETRIC_PUBLIC); key->set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); key->set_status(google::crypto::tink::KeyStatusType::ENABLED); key = keyset.add_key(); key->set_key_id(100); key->mutable_key_data()->set_value("some other value"); key->mutable_key_data()->set_key_material_type(KeyData::ASYMMETRIC_PUBLIC); key->set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); key->set_status(google::crypto::tink::KeyStatusType::ENABLED); key = keyset.add_key(); key->set_key_id(18); key->mutable_key_data()->set_value("some third value"); key->mutable_key_data()->set_key_material_type(KeyData::ASYMMETRIC_PUBLIC); key->set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); key->set_status(google::crypto::tink::KeyStatusType::ENABLED); EXPECT_THAT(crypto::tink::ValidateKeyset(keyset), IsOk()); } TEST(ValidateKeyset, PrimaryIdNonExistent) { google::crypto::tink::Keyset keyset; google::crypto::tink::Keyset::Key* key = keyset.add_key(); key->set_key_id(100); key->mutable_key_data()->set_value("some value"); key->set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); key->set_status(google::crypto::tink::KeyStatusType::ENABLED); keyset.set_primary_key_id(99); EXPECT_THAT(crypto::tink::ValidateKeyset(keyset), StatusIs(absl::StatusCode::kInvalidArgument)); } TEST(ValidateKeyset, ValidHighId) { google::crypto::tink::Keyset keyset; google::crypto::tink::Keyset::Key* key = keyset.add_key(); key->set_key_id(std::numeric_limits::max()); key->mutable_key_data()->set_value("some value"); key->set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK); key->set_status(google::crypto::tink::KeyStatusType::ENABLED); keyset.set_primary_key_id(std::numeric_limits::max()); EXPECT_THAT(crypto::tink::ValidateKeyset(keyset), IsOk()); } } // namespace } // namespace tink } // namespace crypto ================================================ FILE: cc/version.h.templ ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #ifndef TINK_VERSION_H_ #define TINK_VERSION_H_ namespace crypto { namespace tink { class Version { public: static constexpr char kTinkVersion[] = "@TINK_VERSION_LABEL@"; }; } // namespace tink } // namespace crypto #endif // TINK_VERSION_H_ ================================================ FILE: cc/version_script.lds ================================================ VERS_2.1.2 { global: *tink*; *absl*; local: *; }; ================================================ FILE: cmake/HttpArchive.cmake ================================================ # Copyright 2019 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. include(FetchContent) include(CMakeParseArguments) # Download, unpack and configure a dependency. # # The project is added as a subdirectory of Tink, unless DATA_ONLY is # specified. This makes all target defined by it available as dependencies. # # This rule also defines two variables: # - _SOURCE_DIR points to the root directory of the downloaded package; # it can be used to reference data in tests, or append extra include/link # paths in the Workspace file. # - _BINARY_DIR points to the build directory. # # Parameters: # NAME name of the dependency. # URL url to fetch a source archive from. # SHA256 hash of the file downloaded from URL. # # Optional parameters: # CMAKE_SUBDIR subdirectory of the downloaded archive where the root # CMakeLists.txt file for the project is located. Defaults to the root. # CMAKE_ARGS any additional argument that should be passed to cmake when # configuring the downloaded archive. Defaults to empty. # DATA_ONLY flag, if present the package will only be downloaded, verified and # unpacked. No configuration step is performed, and no target included. This # is useful for downloading archives of test vectors or artifacts. # False by default. # function(http_archive) cmake_parse_arguments(PARSE_ARGV 0 http_archive "DATA_ONLY" "NAME;URL;SHA256;CMAKE_SUBDIR" "CMAKE_ARGS" ) FetchContent_Declare( ${http_archive_NAME} URL ${http_archive_URL} URL_HASH SHA256=${http_archive_SHA256} ) message(STATUS "Fetching ${http_archive_NAME}") FetchContent_GetProperties(${http_archive_NAME}) if(NOT ${http_archive_NAME}_POPULATED) FetchContent_Populate(${http_archive_NAME}) if (NOT http_archive_DATA_ONLY) add_subdirectory( ${${http_archive_NAME}_SOURCE_DIR}/${http_archive_CMAKE_SUBDIR} ${${http_archive_NAME}_BINARY_DIR} EXCLUDE_FROM_ALL) endif() # Expose these variables to the caller. set( "${http_archive_NAME}_SOURCE_DIR" "${${http_archive_NAME}_SOURCE_DIR}" PARENT_SCOPE) set( "${http_archive_NAME}_BINARY_DIR" "${${http_archive_NAME}_BINARY_DIR}" PARENT_SCOPE) endif() endfunction(http_archive) ================================================ FILE: cmake/TinkBuildRules.cmake ================================================ # Copyright 2019 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Partially adapted from Abseil's CMake helpers # https://github.com/abseil/abseil-cpp/blob/master/CMake/AbseilHelpers.cmake # Rules for declaring Tink targets in a way similar to Bazel. # # These functions are intended to reduce the difficulty of supporting completely # different build systems, and are designed for Tink internal usage only. # They may work outside this project too, but we don't support that. # # A set of global variables influences the behavior of the rules: # # TINK_MODULE name used to build more descriptive names and for namespaces. # TINK_GENFILE_DIR generated content root, such pb.{cc,h} files. # TINK_INCLUDE_DIRS list of global include paths. # TINK_CXX_STANDARD C++ standard to enforce, 11 for now. # TINK_BUILD_TESTS flag, set to false to disable tests (default false). # # Sensible defaults are provided for all variables, except TINK_MODULE, which is # defined by calls to tink_module(). Please don't alter it directly. include(CMakeParseArguments) if (TINK_BUILD_TESTS) enable_testing() endif() if (NOT DEFINED TINK_GENFILE_DIR) set(TINK_GENFILE_DIR "${PROJECT_BINARY_DIR}/__generated") endif() if (NOT DEFINED TINK_CXX_STANDARD) set(TINK_CXX_STANDARD 14) if (DEFINED CMAKE_CXX_STANDARD_REQUIRED AND CMAKE_CXX_STANDARD_REQUIRED AND DEFINED CMAKE_CXX_STANDARD) set(TINK_CXX_STANDARD ${CMAKE_CXX_STANDARD}) endif() endif() set(TINK_DEFAULT_COPTS "") if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") # This is required to avoid error C1128. # See https://learn.microsoft.com/en-us/cpp/error-messages/compiler-errors-1/fatal-error-c1128?view=msvc-170. set(TINK_DEFAULT_COPTS "/bigobj") endif() list(APPEND TINK_INCLUDE_DIRS "${TINK_GENFILE_DIR}") set(TINK_IDE_FOLDER "Tink") set(TINK_TARGET_EXCLUDE_IF_BORINGSSL "exclude_if_boringssl") set(TINK_TARGET_EXCLUDE_IF_OPENSSL "exclude_if_openssl") set(TINK_TARGET_EXCLUDE_IF_WINDOWS "exclude_if_windows") # Declare the beginning of a new Tink library namespace. # # As a rule of thumb, every CMakeLists.txt should be a different module, named # after the directory that contains it, and this function should appear at the # top of each CMakeLists script. # # This is not a requirement, though. Targets should be grouped logically, and # multiple directories can be part of the same module as long as target names # do not collide. # macro(tink_module NAME) set(TINK_MODULE ${NAME}) endmacro() # Declare a Tink library. Produces a static library that can be linked into # other test, binary or library targets. Tink libraries are mainly meant as # a way to organise code and speed up compilation. # # Arguments: # NAME base name of the target. See below for target naming conventions. # SRCS list of source files, including headers. # DEPS list of dependency targets. # PUBLIC flag, signals that this target is intended for external use. # TESTONLY flag, signals that this target should be ignored if # TINK_BUILD_TESTS=OFF. # # If SRCS contains only headers, an INTERFACE rule is created. This rule carries # include path and link library information, but is not directly buildable. # # The corresponding build target is named tink__ if PUBLIC is # specified, or tink_internal__ otherwise. An alias is also # defined for use in CMake scripts, in the tink:::: form. # # Unlike Bazel, CMake does not enforce the rule that all dependencies must be # listed. CMake DEPS just carry include, build and link flags that are passed # to the compiler. Because of this, a target might compile even if a dependency # is not specified, but that could break at any time. So make sure that all # dependencies are explicitly specified. # function(tink_cc_library) cmake_parse_arguments(PARSE_ARGV 0 tink_cc_library "PUBLIC;TESTONLY" "NAME" "SRCS;DEPS;TAGS" ) if (tink_cc_library_TESTONLY AND NOT TINK_BUILD_TESTS) return() endif() if (NOT DEFINED TINK_MODULE) message(FATAL_ERROR "TINK_MODULE not defined, perhaps you are missing a tink_module() statement?") endif() # Check if this target must be skipped. foreach(_tink_cc_library_tag ${tink_cc_library_TAGS}) # Exclude if using BoringSSL. if (${_tink_cc_library_tag} STREQUAL ${TINK_TARGET_EXCLUDE_IF_BORINGSSL} AND NOT TINK_USE_SYSTEM_OPENSSL) return() endif() # Exclude if using OpenSSL. if (${_tink_cc_library_tag} STREQUAL ${TINK_TARGET_EXCLUDE_IF_OPENSSL} AND TINK_USE_SYSTEM_OPENSSL) return() endif() # Exclude if building on Windows. if (${_tink_cc_library_tag} STREQUAL ${TINK_TARGET_EXCLUDE_IF_WINDOWS} AND WIN32) return() endif() endforeach() # We replace :: with __ in targets, because :: may not appear in target names. # However, the module name should still span multiple name spaces. STRING(REPLACE "::" "__" _ESCAPED_TINK_MODULE ${TINK_MODULE}) set(_is_headers_only_lib true) foreach(_src_file ${tink_cc_library_SRCS}) if(${_src_file} MATCHES "\\.cc$") set(_is_headers_only_lib false) break() endif() endforeach() if (tink_cc_library_PUBLIC) set(_target_name "tink_${_ESCAPED_TINK_MODULE}_${tink_cc_library_NAME}") else() set(_target_name "tink_internal_${_ESCAPED_TINK_MODULE}_${tink_cc_library_NAME}") endif() if(NOT _is_headers_only_lib) add_library(${_target_name} STATIC "") target_sources(${_target_name} PRIVATE ${tink_cc_library_SRCS}) target_include_directories(${_target_name} PUBLIC ${TINK_INCLUDE_DIRS}) target_link_libraries(${_target_name} PUBLIC ${tink_cc_library_DEPS}) target_compile_options(${_target_name} PRIVATE ${TINK_DEFAULT_COPTS}) set_property(TARGET ${_target_name} PROPERTY CXX_STANDARD ${TINK_CXX_STANDARD}) set_property(TARGET ${_target_name} PROPERTY CXX_STANDARD_REQUIRED true) if (tink_cc_library_PUBLIC) set_property(TARGET ${_target_name} PROPERTY FOLDER "${TINK_IDE_FOLDER}") else() set_property(TARGET ${_target_name} PROPERTY FOLDER "${TINK_IDE_FOLDER}/Internal") endif() else() add_library(${_target_name} INTERFACE) target_include_directories(${_target_name} INTERFACE ${TINK_INCLUDE_DIRS}) target_link_libraries(${_target_name} INTERFACE ${tink_cc_library_DEPS}) endif() add_library( tink::${TINK_MODULE}::${tink_cc_library_NAME} ALIAS ${_target_name}) endfunction(tink_cc_library) # Declare a Tink test using googletest, with a syntax similar to Bazel. # # Parameters: # NAME base name of the test. # SRCS list of test source files, headers included. # DEPS list of dependencies, see tink_cc_library above. # DATA list of non-code dependencies, such as test vectors. # # Tests added with this macro are automatically registered. # Each test produces a build target named tink_test__. # function(tink_cc_test) cmake_parse_arguments(PARSE_ARGV 0 tink_cc_test "" "NAME" "SRCS;DEPS;DATA;TAGS" ) if (NOT TINK_BUILD_TESTS) return() endif() if (NOT DEFINED TINK_MODULE) message(FATAL_ERROR "TINK_MODULE not defined") endif() # Check if this target must be skipped. foreach(_tink_cc_test_tag ${tink_cc_test_TAGS}) # Exclude if using BoringSSL. if (${_tink_cc_test_tag} STREQUAL ${TINK_TARGET_EXCLUDE_IF_BORINGSSL} AND NOT TINK_USE_SYSTEM_OPENSSL) return() endif() # Exclude if using OpenSSL. if (${_tink_cc_test_tag} STREQUAL ${TINK_TARGET_EXCLUDE_IF_OPENSSL} AND TINK_USE_SYSTEM_OPENSSL) return() endif() # Exclude if building on Windows. if (${_tink_cc_test_tag} STREQUAL ${TINK_TARGET_EXCLUDE_IF_WINDOWS} AND WIN32) return() endif() endforeach() # We replace :: with __ in targets, because :: may not appear in target names. # However, the module name should still span multiple name spaces. STRING(REPLACE "::" "__" _ESCAPED_TINK_MODULE ${TINK_MODULE}) set(_target_name "tink_test_${_ESCAPED_TINK_MODULE}_${tink_cc_test_NAME}") add_executable(${_target_name} ${tink_cc_test_SRCS} ) target_link_libraries(${_target_name} gtest_main ${tink_cc_test_DEPS} ) set_property(TARGET ${_target_name} PROPERTY FOLDER "${TINK_IDE_FOLDER}/Tests") set_property(TARGET ${_target_name} PROPERTY CXX_STANDARD ${TINK_CXX_STANDARD}) set_property(TARGET ${_target_name} PROPERTY CXX_STANDARD_REQUIRED true) # Note: This was preferred over using gtest_discover_tests because of [1]. # [1] https://gitlab.kitware.com/cmake/cmake/-/issues/23039 add_test(NAME ${_target_name} COMMAND ${_target_name} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) endfunction(tink_cc_test) # Declare a C++ Proto library. # # Parameters: # NAME base name of the library. # SRCS list of .proto source files. # DEPS list of proto library dependencies, produced by tink_cc_proto or not. # # The resulting library follows the same naming convention as tink_cc_library. # function(tink_cc_proto) cmake_parse_arguments(PARSE_ARGV 0 tink_cc_proto "" "NAME" "SRCS;DEPS" ) set(tink_cc_proto_GEN_SRCS) foreach(_src_path ${tink_cc_proto_SRCS}) get_filename_component(_src_absolute_path "${_src_path}" ABSOLUTE) get_filename_component(_src_basename "${_src_path}" NAME_WE) get_filename_component(_src_dir "${_src_absolute_path}" DIRECTORY) file(RELATIVE_PATH _src_rel_path "${PROJECT_SOURCE_DIR}" "${_src_dir}") set(_gen_srcs) foreach(_gen_ext .pb.h .pb.cc) list(APPEND _gen_srcs "${TINK_GENFILE_DIR}/${_src_rel_path}/${_src_basename}${_gen_ext}") endforeach() list(APPEND tink_cc_proto_GEN_SRCS ${_gen_srcs}) add_custom_command( COMMAND protobuf::protoc ARGS --cpp_out "${TINK_GENFILE_DIR}" -I "${PROJECT_SOURCE_DIR}" "${_src_absolute_path}" OUTPUT ${_gen_srcs} DEPENDS protobuf::protoc ${_src_absolute_path} COMMENT "Running CXX protocol buffer compiler on ${_src_path}" VERBATIM ) endforeach() set_source_files_properties( ${tink_cc_proto_GEN_SRCS} PROPERTIES GENERATED true) tink_cc_library( NAME ${tink_cc_proto_NAME} SRCS ${tink_cc_proto_GEN_SRCS} DEPS protobuf::libprotobuf protobuf::libprotoc ${tink_cc_proto_DEPS} ) endfunction() # Declare an empty target, that depends on all those specified. Use this rule # to group dependencies that are logically related and give them a single name. # # Parameters: # NAME base name of the target. # DEPS list of dependencies to group. # # Each tink_target_group produces a target named tink__. function(tink_target_group) cmake_parse_arguments(PARSE_ARGV 0 tink_target_group "" "NAME" "DEPS") set(_target_name "tink_${TINK_MODULE}_${tink_target_group_NAME}") add_custom_target(${_target_name}) add_dependencies(${_target_name} ${tink_target_group_DEPS}) endfunction() ================================================ FILE: cmake/TinkUtil.cmake ================================================ # Copyright 2019 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Create an alias for SOURCE, called DESTINATION. # # On platforms that support them, this rule will effectively create a symlink. # # SOURCE may be relative to CMAKE_CURRENT_SOURCE_DIR, or absolute. # DESTINATION may relative to CMAKE_CURRENT_BINARY_DIR, or absolute. # # Adapted from https://github.com/google/binexport/blob/master/util.cmake function(add_directory_alias SOURCE DESTINATION) get_filename_component(_destination_parent "${DESTINATION}" DIRECTORY) file(MAKE_DIRECTORY "${_destination_parent}") if (WIN32) file(TO_NATIVE_PATH "${SOURCE}" _native_source) file(TO_NATIVE_PATH "${DESTINATION}" _native_destination) execute_process(COMMAND $ENV{ComSpec} /c mklink /J "${_native_destination}" "${_native_source}" ERROR_QUIET) else() execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${SOURCE}" "${DESTINATION}") endif() endfunction(add_directory_alias) ================================================ FILE: cmake/TinkWorkspace.cmake ================================================ # Copyright 2019 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Download, unpack and setup Tink dependencies. # # Despite the looks, http_archive rules are not purely declarative, and order # matters. All variables defined before a rule are visible when configuring the # dependency it declares, and the targets provided by a dependency are visible # (only) after it has been declared. Following dependencies may rely on targets # defined by a previous one, for instance on gtest or absl. # # Some rules imported from dependencies require small fixes, which are specified # after the relative http_archive rule. Please always document the intended # purpose of such statements, and why they are necessary. # # In general, when adding a new dependency you should follow this structure: # # # # # # Many projects provide switches to disable tests or examples, which you should # specify, in order to speed up the compilation process. include(HttpArchive) include(TinkUtil) # Creates an interface target from an imported one. # # Parameters: # INTERFACE_TARGET Name of the interface target. # IMPORTED_TARGET Name of the imported target (e.g., with find_package). # macro(_create_interface_target INTERFACE_TARGET IMPORTED_TARGET) add_library(${INTERFACE_TARGET} INTERFACE) target_link_libraries(${INTERFACE_TARGET} INTERFACE ${IMPORTED_TARGET}) target_include_directories(${INTERFACE_TARGET} INTERFACE ${IMPORTED_TARGET}) endmacro() set(gtest_force_shared_crt ON CACHE BOOL "Tink dependency override" FORCE) if (TINK_BUILD_TESTS) if (TINK_USE_INSTALLED_GOOGLETEST) # This uses the CMake's FindGTest module; if successful, this call to # find_package generates the targets GTest::gmock, GTest::gtest and # GTest::gtest_main. find_package(GTest CONFIG REQUIRED) _create_interface_target(gmock GTest::gmock) _create_interface_target(gtest_main GTest::gtest_main) else() http_archive( NAME googletest URL https://github.com/google/googletest/archive/refs/tags/v1.14.0.zip SHA256 1f357c27ca988c3f7c6b4bf68a9395005ac6761f034046e9dde0896e3aba00e4 ) endif() http_archive( NAME wycheproof URL https://github.com/google/wycheproof/archive/d8ed1ba95ac4c551db67f410c06131c3bc00a97c.zip SHA256 eb1d558071acf1aa6d677d7f1cabec2328d1cf8381496c17185bd92b52ce7545 DATA_ONLY ) # Symlink the Wycheproof test data. # Tests expect Wycheproof test vectors to be in a local testvectors/ folder. add_directory_alias("${wycheproof_SOURCE_DIR}/testvectors" "${CMAKE_BINARY_DIR}/testvectors") endif() if (NOT TINK_USE_INSTALLED_ABSEIL) # Release from 2023-09-18. http_archive( NAME abseil URL https://github.com/abseil/abseil-cpp/archive/refs/tags/20230802.1.zip SHA256 497ebdc3a4885d9209b9bd416e8c3f71e7a1fb8af249f6c2a80b7cbeefcd7e21 ) else() # This is everything that needs to be done here. Abseil already defines its # targets, which gets linked in tink_cc_(library|test). find_package(absl REQUIRED) endif() # Don't fetch BoringSSL or look for OpenSSL if target `crypto` is already # defined. if (NOT TARGET crypto) if (NOT TINK_USE_SYSTEM_OPENSSL) # Commit from 2023-09-08. # TODO(b/319145660): Use a later version once we can force /std:c11 on MSVC. http_archive( NAME boringssl URL https://github.com/google/boringssl/archive/667d54c96acda029523c5bf425e8eb9079dbe94a.zip SHA256 21b2086e9242b87415767fd6d2d13bd0481e2eb3c336c7ffa24b1f3d7afb09ae CMAKE_SUBDIR src ) # BoringSSL targets do not carry include directory info, this fixes it. target_include_directories(crypto PUBLIC "$") else() # Support for ED25519 was added from 1.1.1. find_package(OpenSSL 1.1.1 REQUIRED) _create_interface_target(crypto OpenSSL::Crypto) endif() else() message(STATUS "Using an already declared `crypto` target") get_target_property(crypto_INCLUDE_DIR crypto INTERFACE_INCLUDE_DIRECTORIES) message(STATUS "crypto Include Dir: ${crypto_INCLUDE_DIR}") endif() set(RAPIDJSON_BUILD_DOC OFF CACHE BOOL "Tink dependency override" FORCE) set(RAPIDJSON_BUILD_EXAMPLES OFF CACHE BOOL "Tink dependency override" FORCE) set(RAPIDJSON_BUILD_TESTS OFF CACHE BOOL "Tink dependency override" FORCE) http_archive( NAME rapidjson URL https://github.com/Tencent/rapidjson/archive/v1.1.0.tar.gz SHA256 bf7ced29704a1e696fbccf2a2b4ea068e7774fa37f6d7dd4039d0787f8bed98e ) # Rapidjson is a header-only library with no explicit target. Here we create one. add_library(rapidjson INTERFACE) target_include_directories(rapidjson INTERFACE "${rapidjson_SOURCE_DIR}") if (NOT TINK_USE_INSTALLED_PROTOBUF) set(protobuf_BUILD_TESTS OFF CACHE BOOL "Tink dependency override" FORCE) set(protobuf_BUILD_EXAMPLES OFF CACHE BOOL "Tink dependency override" FORCE) set(protobuf_INSTALL OFF CACHE BOOL "Tink dependency override" FORCE) http_archive( NAME com_google_protobuf URL https://github.com/protocolbuffers/protobuf/releases/download/v25.1/protobuf-25.1.zip SHA256 5c86c077b0794c3e9bb30cac872cf883043febfb0f992137f0a8b1c3d534617c ) else() find_package(Protobuf REQUIRED CONFIG) include_directories(${Protobuf_INCLUDE_DIRS}) include_directories(${CMAKE_CURRENT_BINARY_DIR}) endif() ================================================ FILE: docs/CMAKE-HOWTO.md ================================================ # CMake for Tink HOW-TO # Incorporating Tink into your project If you are developing a project that uses Tink, you might incorporate the library using one of the following approaches. At the moment, only the in-tree dependency is supported, although all of them should work. ## In-tree dependency Tink can be embedded directly in your CMake project and statically linked in your executable. This is the approach we currently recommend. Assuming the Tink source tree has been copied in the `third_party/tink` directory of your project, your top-level CMake script should look like this: cmake_minimum_required(VERSION 3.13) project(YourProject CXX) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD 14) add_subdirectory(third_party/tink) add_executable(your_app your_app.cc) target_link_libraries(your_app tink::static) NOTES: * You need at least CMake 3.13 to build Tink and its dependencies. * Tink defines the C++ standard to use via the `TINK_CXX_STANDARD` variable, which is `14` by default. If you want to propagate to the value of `CMAKE_CXX_STANDARD` to Tink use `set(CMAKE_CXX_STANDARD_REQUIRED ON)`. Include Tink headers in `your_app.cc` as follows: #include "tink/config.h" #include "tink/json_keyset_reader.h" // ... NOTE: `tink::static` provides the `tink/...` include path. It is just a shortcut for your convenience, and you might still refer to Tink headers using a filesystem path, such as `third_party/tink/cc/...`, if you prefer or need to. You can see a full example in `examples/cc/helloworld/hello_world.cc`. Generate the build directory as you normally would and invoke your build system of choice: $ ls CMakeLists.txt your_app.cc third_party/ $ mkdir build && cd build $ cmake .. $ make $ ./your_app If you have the option, we recommend using [Ninja](https://ninja-build.org/) to build your project: $ cmake -DCMAKE_GENERATOR=Ninja .. $ ninja # Developing Tink with CMake If you are developing Tink, Bazel is the primary build system, but you should test all your changes with CMake too. Build Tink as a regular CMake project, but enable tests and build the shared library as well: $ ls tink/ $ mkdir tink-build && cd tink-build $ cmake ../tink -DTINK_BUILD_TESTS=ON -DCMAKE_GENERATOR=Ninja $ ninja $ CTEST_OUTPUT_ON_FAILURE=1 ninja test $ ninja package This combination of options ensures that the entire CMake configuration is evaluated. WARNING: When editing a `BUILD.bazel` file, remember to keep it in sync with the corresponding `CMakeLists.txt` file. ================================================ FILE: docs/CONTRIBUTING.md ================================================ # How to contribute Please see the [developer documentation](https://developers.google.com/tink/contributing) on how to contribute to Tink. ================================================ FILE: docs/CPP-HOWTO.md ================================================ # Tink for C++ HOW-TO This document contains instructions and C++ code snippets for common tasks in [Tink](https://github.com/google/tink). ## Setup instructions Tink can be built using [Bazel](https://www.bazel.build) or [CMake](http://cmake.org). Using any other build system is currently not supported. This implies that you need to build your binary from scratch. ### Bazel Using Tink in projects built with Bazel is straightforward and is the recommended approach. For reference, see [the C++ examples](https://github.com/google/tink/tree/master/cc/examples). ### CMake Using Tink with CMake is supported, see [CMAKE-HOWTO](CMAKE-HOWTO.md) for a detailed description. ## Initializing Tink Tink provides customizable initialization, which allows for choosing specific implementations (identified by _key types_) of desired primitives. This initialization happens via _registration_ of the implementations. For example, if you want to use all standard implementations of all primitives in the current release of Tink, the initialization would be: ```cpp #include "tink/config/tink_config.h" // ... auto status = TinkConfig::Register(); if (!status.ok()) /* ... handle failure */; // ... ``` To use standard implementations of only one primitive, say AEAD: ```cpp #include "tink/aead/aead_config.h" // ... auto status = AeadConfig::Register(); if (!status.ok()) /* ... handle failure */; // ... ``` The registration of custom key managers can proceed directly via `Registry` class: ```cpp #include "tink/registry.h" #include "custom_project/custom_aead_key_manager.h" // ... auto status = Registry::RegisterKeyManager(absl::make_unique()); if (!status.ok()) /* ... handle failure */; ``` ## Generating new keys and keysets Each `KeyManager` implementation provides a `NewKey(template)` method that generates new keys of the corresponding key type. However, to avoid accidental leakage of sensitive key material, you should avoid mixing key(set) generation with key(set) usage in code. To support the separation between these activities, Tink provides a command-line tool called [Tinkey](TINKEY.md), which can be used for common key management tasks. Still, if there is a need to generate a KeysetHandle with fresh key material directly in C++ code, you can use [`KeysetHandle`](https://github.com/google/tink/blob/master/cc/keyset_handle.h): ```cpp auto new_keyset_handle_result = KeysetHandle::GenerateNew(key_template); if (!new_keyset_handle_result.ok()) return new_keyset_handle_result.status(); auto keyset_handle = std::move(new_keyset_handle_result.ValueOrDie()); // use the keyset... ``` Recommended key templates can be obtained from util classes corresponding to Tink primitives, e.g. [MacKeyTemplates](https://github.com/google/tink/blob/master/cc/mac/mac_key_templates.h), [AeadKeyTemplates](https://github.com/google/tink/blob/master/cc/aead/aead_key_templates.h), and [HybridKeyTemplates](https://github.com/google/tink/blob/master/cc/hybrid/hybrid_key_templates.h). ## Loading existing keysets To load encrypted keysets, use [`KeysetHandle`](https://github.com/google/tink/blob/master/cc/keyset_handle.h) and an appropriate [`KeysetReader`](https://github.com/google/tink/blob/master/cc/keyset_reader.h) depending on the wire format of the stored keyset, for example a [`BinaryKeysetReader`](https://github.com/google/tink/blob/master/cc/binary_keyset_reader.h) or a [`JsonKeysetReader`](https://github.com/google/tink/blob/master/cc/json_keyset_reader.h): ```cpp #include "tink/aead.h" #include "tink/json_keyset_reader.h" #include "tink/cleartext_keyset_handle.h" #include "tink/integration/aws_kms_client.h" // ... std::string json_encrypted_keyset = ...; auto reader_result = JsonKeysetReader::New(json_encrypted_keyset); if (!reader_result.ok()) return reader_result.status(); auto reader = std::move(reader_result.ValueOrDie()); std::string master_key_uri = "aws-kms://arn:aws:kms:us-east-1:007084425826:key/84a65985-f868-4bfc-83c2-366618acf147"; auto aead = std::move(AwsKmsClient::NewAead(master_key_uri).ValueOrDie()); auto handle_result = KeysetHandle::Read(std::move(reader), *aead); if (!handle_result.ok()) return handle_result.status(); auto keyset_handle = std::move(handle_result.ValueOrDie()); ``` To load cleartext keysets, use [`CleartextKeysetHandle`](https://github.com/google/tink/blob/master/cc/cleartext_keyset_handle.h) and an appropriate [`KeysetReader`](https://github.com/google/tink/blob/master/cc/keyset_reader.h), ```cpp #include "tink/binary_keyset_reader.h" #include "tink/cleartext_keyset_handle.h" // ... std::string binary_keyset = ...; auto reader_result = BinaryKeysetReader::New(binary_keyset); if (!reader_result.ok()) return reader_result.status(); auto reader = std::move(reader_result.ValueOrDie()); auto handle_result = CleartextKeysetHandle::Read(std::move(reader)); if (!handle_result.ok()) return handle_result.status(); auto keyset_handle = std::move(handle_result.ValueOrDie()); ``` ## Obtaining and using primitives [_Primitives_](PRIMITIVES.md) represent cryptographic operations offered by Tink, hence they form the core of the Tink API. A primitive is an interface that specifies what operations are offered by the primitive. A primitive can have multiple implementations, and you choose a desired implementation by using a key of a corresponding type (see [this document](KEY-MANAGEMENT.md#key-keyset-and-keysethandle) for further details). A list of primitives and the implementations currently supported by Tink in C++ can be found [here](PRIMITIVES.md#c). You obtain a primitive by calling the method `GetPrimitive<>` of a `KeysetHandle`. ### Symmetric key encryption You can use an [AEAD (Authenticated Encryption with Associated Data)](PRIMITIVES.md#authenticated-encryption-with-associated-data) primitive to encrypt or decrypt data: ```cpp #include "tink/aead.h" #include "tink/keyset_handle.h" // 1. Get a handle to the key material. KeysetHandle keyset_handle = ...; // 2. Get the primitive. auto aead_result= keyset_handle.GetPrimitive(); if (!aead_result.ok()) return aead_result.status(); auto aead = std::move(aead_result.ValueOrDie()); // 3. Use the primitive. auto ciphertext_result = aead.Encrypt(plaintext, aad); if (!ciphertext_result.ok()) return ciphertext_result.status(); auto ciphertext = std::move(ciphertext_result.ValueOrDie()); ``` ### Hybrid encryption You can encrypt and decrypt using [a combination of public key encryption and symmetric key encryption](PRIMITIVES.md#hybrid-encryption): ```cpp #include "tink/hybrid_decrypt.h" #include "tink/keyset_handle.h" // 1. Get a handle to the key material. KeysetHandle keyset_handle = ...; // 2. Get the primitive. auto hybrid_decrypt_result = keyset_handle.GetPrimitive(); if (!hybrid_decrypt_result.ok()) return hybrid_decrypt_result.status(); auto hybrid_decrypt = std::move(hybrid_decrypt_result.ValueOrDie()); // 3. Use the primitive. auto plaintext_result = hybrid_decrypt.Decrypt(ciphertext, context_info); if (!plaintext_result.ok()) return plaintext_result.status(); auto plaintext = std::move(plaintext_result.ValueOrDie()); ``` ### Envelope encryption Via the AEAD interface, Tink supports [envelope encryption](KEY-MANAGEMENT.md#envelope-encryption). For example, you can perform envelope encryption with a Google Cloud KMS key at `gcp-kms://projects/tink-examples/locations/global/keyRings/foo/cryptoKeys/bar` using the credentials in `credentials.json` as follows: ```cpp #include "tink/aead.h" #include "tink/aead_key_templates.h" #include "tink/keyset_handle.h" #include "tink/integration/gcpkms/gcp_kms_client.h" using crypto::tink::Aead; using crypto::tink::integration::gcpkms::GcpKmsClient; std::string kek_uri = "gcp-kms://projects/tink-examples/locations/global/keyRings/foo/cryptoKeys/bar"; std::string credentials = "credentials.json"; const KeyTemplate& dek_template = AeadKeyTemplates::Aes128Gcm(); // Register GcpKmsClient. auto client_result = GcpKmsClient::RegisterNewClient(kek_uri, credentials); if (!client_result.ok()) { std::clog << "GCP KMS client registration failed: " << client_result.status().error_message() << "\n"; exit(1); } // 1. Get a handle to the key material. const KeyTemplate& envelope_kt = AeadKeyTemplates::KmsEnvelopeAead(kek_uri, dek_template); auto new_keyset_handle_result = KeysetHandle::GenerateNew(envelope_kt); if (!new_keyset_handle_result.ok()) return new_keyset_handle_result.status(); // The nice thing about envelope encryption is that you don't have to store // this keyset handle because it only contains a reference to the remote KEK. auto keyset_handle = std::move(new_keyset_handle_result.ValueOrDie()); // 2. Get the primitive. auto aead_result= keyset_handle.GetPrimitive(); if (!aead_result.ok()) return aead_result.status(); auto aead = std::move(aead_result.ValueOrDie()); // 3. Use the primitive. auto ciphertext_result = aead->Encrypt(plaintext, aad); if (!ciphertext_result.ok()) return ciphertext_result.status(); auto ciphertext = std::move(ciphertext_result.ValueOrDie()); ``` ================================================ FILE: docs/FIPS.md ================================================ # Tink - FIPS 140-2 With Tink you can use [BoringSSLs BoringCrypto](https://csrc.nist.gov/Projects/Cryptographic-Module-Validation-Program/Certificate/3678) as a [FIPS 140-2](https://csrc.nist.gov/publications/detail/fips/140/2/final) validated backend. For further details see [Use Tink to meet FIPS 140-2 security requirements](https://developers.google.com/tink/FIPS). ================================================ FILE: docs/GOLANG-HOWTO.md ================================================ # Tink for Go HOW-TO This document contains instructions for common tasks in [Tink](https://github.com/google/tink). Example code snippets for these tasks and API documentation can be found on [pkg.go.dev](https://pkg.go.dev/github.com/google/tink/go). ## Setup instructions To install Tink locally run: ```sh go get github.com/google/tink/go/... ``` to run all the tests locally: ```sh cd $GOPATH/go/src/github.com/google/tink/go go test ./... ``` Golang Tink API also supports [Bazel](https://www.bazel.build) builds. To run the tests using bazel: ```sh cd $GOPATH/go/src/github.com/google/tink/go bazel build ... && bazel test ... ``` ## Generating new keys and keysets To take advantage of key rotation and other key management features, you usually do not work with single keys, but with keysets. Keysets are just sets of keys with some additional parameters and metadata. Internally Tink stores keysets as Protocol Buffers, but you can work with keysets via a wrapper called a keyset handle. You can generate a new keyset and obtain its handle using a KeyTemplate. KeysetHandle objects enforce certain restrictions that prevent accidental leakage of the sensitive key material. ```go package main import ( "fmt" "log" "github.com/google/tink/go/aead" "github.com/google/tink/go/keyset" ) func main() { // Other key templates can also be used. kh, err := keyset.NewHandle(aead.AES128GCMKeyTemplate()) if err != nil { log.Fatal(err) } fmt.Println(kh.String()) } ``` Key templates are available for MAC, digital signatures, AEAD encryption, DAEAD encryption and hybrid encryption. Key Template Type | Key Template ----------------- | ------------------------------------------------ AEAD | aead.AES128CTRHMACSHA256KeyTemplate() AEAD | aead.AES128GCMKeyTemplate() AEAD | aead.AES256CTRHMACSHA256KeyTemplate() AEAD | aead.AES256GCMKeyTemplate() AEAD | aead.ChaCha20Poly1305KeyTemplate() AEAD | aead.XChaCha20Poly1305KeyTemplate() DAEAD | daead.AESSIVKeyTemplate() MAC | mac.HMACSHA256Tag128KeyTemplate() MAC | mac.HMACSHA256Tag256KeyTemplate() MAC | mac.HMACSHA512Tag256KeyTemplate() MAC | mac.HMACSHA512Tag512KeyTemplate() Signature | signature.ECDSAP256KeyTemplate() Signature | signature.ECDSAP384KeyTemplate() Signature | signature.ECDSAP521KeyTemplate() Hybrid | hybrid.ECIESHKDFAES128GCMKeyTemplate() Hybrid | hybrid.ECIESHKDFAES128CTRHMACSHA256KeyTemplate() To avoid accidental leakage of sensitive key material, you should avoid mixing keyset generation and usage in code. To support the separation of these activities Tink provides a command-line tool, [Tinkey](TINKEY.md), which can be used for common key management tasks. ## Storing and loading existing keysets After generating key material, you might want to persist it to a storage system. Tink supports encrypting and persisting the keys to any io.Writer and io.Reader implementations. ```go package main import ( "fmt" "log" "github.com/google/tink/go/aead" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/integration/gcpkms" "github.com/google/tink/go/keyset" ) const ( // Change this. AWS KMS, Google Cloud KMS and HashiCorp Vault are supported out of the box. keyURI = "gcp-kms://projects/tink-examples/locations/global/keyRings/foo/cryptoKeys/bar" credentialsPath = "credentials.json" ) func main() { // Generate a new keyset handle. handle1, err := keyset.NewHandle(aead.AES128GCMKeyTemplate()) if err != nil { log.Fatal(err) } // Get the key encryption AEAD from a KMS. gcpClient, err := gcpkms.NewClientWithCredentials(keyURI, credentialsPath) if err != nil { log.Fatal(err) } registry.RegisterKMSClient(gcpClient) keyEncryptionAEAD, err := gcpClient.GetAEAD(keyURI) if err != nil { log.Fatal(err) } // Serialize and encrypt the keyset handle using the key encryption AEAD. // We strongly recommend that you encrypt the keyset handle before persisting // it. buf := new(bytes.Buffer) writer := keyset.NewBinaryWriter(buf) err = handle1.Write(writer, keyEncryptionAEAD) if err != nil { log.Fatal(err) } encryptedHandle := buf.Bytes() // Decrypt and parse the encrypted keyset using the key encryption AEAD. reader := keyset.NewBinaryReader(bytes.NewReader(encryptedHandle)) handle2, err := keyset.Read(reader, keyEncryptionAEAD) if err != nil { log.Fatal(err) } } ``` ## AEAD The AEAD primitive (authenticated encryption with associated data) is the most common primitive to ***encrypt*** data. It is symmetric, and using the same key for encryption and decryption. Check out the [AEAD examples](https://pkg.go.dev/github.com/google/tink/go/aead#example-package). The `Play` button at the corner right allows you to run them on the Go Playground. ## Deterministic AEAD The Deterministic AEAD primitive (authenticated encryption with associated data) is used to ***deterministically encrypt*** data. It is symmetric, and using the same key for encryption and decryption. Unlike AEAD, implementations of this interface are not semantically secure, because encrypting the same plaintext always yields the same ciphertext. Check out the [Deterministic AEAD examples](https://pkg.go.dev/github.com/google/tink/go/daead#example-package). The `Play` button at the corner right allows you to run them on the Go Playground. ## MAC The MAC primitive allows you to ensure that nobody tampers with data you own. It is symmetric, and using the same key for authentication and verification. Check out the [MAC examples](https://pkg.go.dev/github.com/google/tink/go/mac#example-package). The `Play` button at the corner right allows you to run them on the Go Playground. ## Digital signature The digital signature primitives allow you to ensure that nobody tampers with your data. It is asymmetric, and hence comes with a pair of keys (public key and private key). The private key allows to sign messages, and the public key allows to verify. Check out the [digital signature examples](https://pkg.go.dev/github.com/google/tink/go/signature#example-package). The `Play` button at the corner right allows you to run them on the Go Playground. ## Hybrid encryption The hybrid encryption primitives allow you to encrypt data with a public key. Only users with the secret key will be able to decrypt the data. Check out the [hybrid encryption examples](https://pkg.go.dev/github.com/google/tink/go/hybrid#example-package). The `Play` button at the corner right allows you to run them on the Go Playground. ## Envelope encryption Via the AEAD interface, Tink supports [envelope encryption](KEY-MANAGEMENT.md#envelope-encryption). Check out the [GCP KMS example](https://pkg.go.dev/github.com/tink-crypto/tink-go-gcpkms/v2@v2.0.0/integration/gcpkms#example-package). ================================================ FILE: docs/JAVA-HOWTO.md ================================================ # Tink for Java HOW-TO This document contains instructions and Java code snippets for common tasks in [Tink](https://github.com/tink-crypto/tink-java). ## Setup instructions See https://developers.google.com/tink/tink-setup#java for setup instructions. ## API documentation * Java: * [1.9.0](https://google.github.io/tink/javadoc/tink/1.9.0) * [HEAD-SNAPSHOT](https://google.github.io/tink/javadoc/tink/HEAD-SNAPSHOT) * Android: * [1.9.0](https://google.github.io/tink/javadoc/tink-android/1.9.0) * [HEAD-SNAPSHOT](https://google.github.io/tink/javadoc/tink-android/HEAD-SNAPSHOT) ## Important warnings **Do not use APIs which have fields or methods marked with the `@Alpha` annotation.** They can be modified in any way, or even removed, at any time. They are in the package, but not for official, production release, but only for testing. **Do not use APIs in `com.google.crypto.tink.subtle`.** While they're generally safe to use, they're not meant for public consumption and can be modified in any way, or even removed, at any time. ## Initializing Tink Tink provides customizable initialization, which allows you to choose specific implementations (identified by _key types_) of desired primitives. This initialization happens via _registration_ of the implementations. For example, if you want to use all implementations of all primitives in Tink, the initialization would be: ```java import com.google.crypto.tink.config.TinkConfig; TinkConfig.register(); ``` To use only implementations of the AEAD primitive: ```java import com.google.crypto.tink.aead.AeadConfig; AeadConfig.register(); ``` For custom initialization the registration proceeds directly via the `Registry` class: ```java import com.google.crypto.tink.Registry; import my.custom.package.aead.MyAeadKeyManager; // Register a custom implementation of AEAD. Registry.registerKeyManager(new MyAeadKeyManager()); ``` ## Generating new keys and keysets Each `KeyManager`-implementation provides `newKey(..)`-methods that generate new keys of the corresponding key type. However, to avoid accidental leakage of sensitive key material, you should avoid mixing key(set) generation with key(set) usage in code. To support the separation between these activities, Tink provides a command-line tool called [Tinkey](TINKEY.md), which can be used for common key management tasks. Still, if there is a need to generate a KeysetHandle with fresh key material directly in Java code, you can use [`KeysetHandle`](https://github.com/tink-crypto/tink-java/blob/main/src/main/java/com/google/crypto/tink/KeysetHandle.java). For example, you can generate a keyset containing a randomly generated AES128-GCM key as follows. ```java import com.google.crypto.tink.KeysetHandle; import com.google.crypto.tink.aead.PredefinedAeadParameters; KeysetHandle keysetHandle = KeysetHandle.generateNew( PredefinedAeadParameters.AES128_GCM); ``` ## Serializing keysets After generating key material, you might want to serialize it in order to persist it to a storage system, e.g., writing to a file. ```java import com.google.crypto.tink.InsecureSecretKeyAccess; import com.google.crypto.tink.KeysetHandle; import com.google.crypto.tink.TinkJsonProtoKeysetFormat; import com.google.crypto.tink.aead.PredefinedAeadParameters; // Generate the key material... KeysetHandle keysetHandle = KeysetHandle.generateNew( PredefinedAeadParameters.AES128_GCM); // and serialize it to a string. String keysetFilename = "my_keyset.json"; String serializedKeyset = TinkJsonProtoKeysetFormat.serializeKeyset(handle, InsecureSecretKeyAccess.get()); ``` Parsing can be done with `TinkJsonProtoKeysetFormat.parseKeyset`. If the keyset has no secret key material, the method `serializeKeysetWithoutSecret` can be used (which does not require `InsecureSecretKeyAccess`). Storing keysets unencrypted on disk is not recommended. Tink supports encrypting keysets with master keys stored in remote key management systems, see for example https://developers.google.com/tink/client-side-encryption#java. ## Obtaining and using primitives [Primitives](PRIMITIVES.md) represent cryptographic operations offered by Tink, hence they form the core of the Tink API. A primitive is an interface which specifies what operations are offered by the primitive. A primitive can have multiple implementations, and you choose a desired implementation by using a key of a corresponding type (see [this document](KEY-MANAGEMENT.md#key-keyset-and-keysethandle) for further details). A list of primitives and the implementations currently supported by Tink in Java can be found [here](PRIMITIVES.md#java). You obtain a primitive by calling the method `getPrimitive(classObject)` of a `KeysetHandle`, where the `classObject` is the class object corresponding to the primitive (for example `Aead.class` for AEAD). ### Symmetric Key Encryption You can obtain and use an [AEAD](PRIMITIVES.md#authenticated-encryption-with-associated-data) (Authenticated Encryption with Associated Data) primitive to encrypt or decrypt data: ```java import com.google.crypto.tink.Aead; import com.google.crypto.tink.aead.PredefinedAeadParameters; // 1. Generate the key material. KeysetHandle keysetHandle = KeysetHandle.generateNew( PredefinedAeadParameters.AES128_GCM); // 2. Get the primitive. Aead aead = keysetHandle.getPrimitive(Aead.class); // 3. Use the primitive to encrypt a plaintext, byte[] ciphertext = aead.encrypt(plaintext, aad); // ... or to decrypt a ciphertext. byte[] decrypted = aead.decrypt(ciphertext, aad); ``` ### Deterministic symmetric key encryption You can obtain and use a [DeterministicAEAD](PRIMITIVES.md#deterministic-authenticated-encryption-with-associated-data) (Deterministic Authenticated Encryption with Associated Data primitive to encrypt or decrypt data: ```java import com.google.crypto.tink.daead.PredefinedDeterministicAeadParameters; import com.google.crypto.tink.KeysetHandle; // 1. Generate the key material. KeysetHandle keysetHandle = KeysetHandle.generateNew( PredefinedDeterministicAeadParameters.AES256_SIV); // 2. Get the primitive. DeterministicAead daead = keysetHandle.getPrimitive(DeterministicAead.class); // 3. Use the primitive to deterministically encrypt a plaintext, byte[] ciphertext = daead.encryptDeterministically(plaintext, aad); // ... or to deterministically decrypt a ciphertext. byte[] decrypted = daead.decryptDeterministically(ciphertext, aad); ``` ### Symmetric key encryption of streaming data See https://developers.google.com/tink/encrypt-large-files-or-data-streams#java ### Message Authentication Code See https://developers.google.com/tink/protect-data-from-tampering#java ### Digital signatures See https://developers.google.com/tink/digitally-sign-data ### Hybrid encryption See https://developers.google.com/tink/exchange-data#java ### Envelope encryption Via the AEAD interface, Tink supports [envelope encryption](KEY-MANAGEMENT.md#envelope-encryption). For example, you can perform envelope encryption with a Google Cloud KMS key at `gcp-kms://projects/tink-examples/locations/global/keyRings/foo/cryptoKeys/bar` using the credentials in `credentials.json` as follows: ```java import com.google.crypto.tink.Aead; import com.google.crypto.tink.KeyTemplates; import com.google.crypto.tink.KeysetHandle; import com.google.crypto.tink.KmsClients; import com.google.crypto.tink.aead.KmsEnvelopeAeadKeyManager; import com.google.crypto.tink.integration.gcpkms.GcpKmsClient; // 1. Generate the key material. String kmsKeyUri = "gcp-kms://projects/tink-examples/locations/global/keyRings/foo/cryptoKeys/bar"; KeysetHandle handle = KeysetHandle.generateNew( KmsEnvelopeAeadKeyManager.createKeyTemplate( kmsKeyUri, KeyTemplates.get("AES128_GCM"))); // 2. Register the KMS client. KmsClients.add(new GcpKmsClient() .withCredentials("credentials.json")); // 3. Get the primitive. Aead aead = handle.getPrimitive(Aead.class); // 4. Use the primitive. byte[] ciphertext = aead.encrypt(plaintext, aad); ``` ## Key rotation Support for key rotation in Tink is provided via the [`KeysetHandle.Builder`](https://github.com/tink-crypto/tink-java/blob/main/src/main/java/com/google/crypto/tink/KeysetHandle.java) class. You have to provide a `KeysetHandle`-object that contains the keyset that should be rotated, and a specification of the new key via a [`Parameters`](https://github.com/tink-crypto/tink-java/blob/main/src/main/java/com/google/crypto/tink/Parameters.java) object. ```java import com.google.crypto.tink.KeysetHandle; import com.google.crypto.tink.KeysetManager; KeysetHandle keysetHandle = ...; // existing keyset KeysetHandle.Builder builder = KeysetHandle.newBuilder(keysetHandle); builder.addEntry(KeysetHandle.generateEntryFromParameters( ChaCha20Poly1305Parameters.create()).withRandomId()); KeysetHandle keysetHandleWithAdditionalEntry = builder.build(); ``` After a successful rotation, the resulting keyset contains a new key generated according to the specification in the parameters object. For the rotation to succeed the `Registry` must contain a key manager for the key type specified in `keyTemplate`. Alternatively, you can use [Tinkey](TINKEY.md) to rotate or manage a keyset. ## Custom implementation of a primitive **NOTE**: The usage of **custom key managers should be enjoyed responsibly**. We (i.e. Tink developers) have no way of checking or enforcing that a custom implementation satisfies security properties of the corresponding primitive interface, so it is up to the implementer and the user of the custom implementation ensure the required properties are met. The main cryptographic operations offered by Tink are accessible via so-called _primitives_, which are interfaces that represent corresponding cryptographic functionalities. While Tink comes with several standard implementations of common primitives, it also allows for adding custom implementations of primitives. Such implementations allow for seamless integration of Tink with custom third-party cryptographic schemes or hardware modules, and in combination with [key rotation](#key-rotation) features, enables the painless migration between cryptographic schemes. To create a custom implementation of a primitive proceed as follows: 1. Determine for which _primitive_ a custom implementation is needed. 2. Define protocol buffers that hold key material and parameters for the custom cryptographic scheme; the name of the key protocol buffer (a.k.a. type URL) determines the _key type_ for the custom implementation. 3. Implement a [`KeyManager`](https://github.com/google/tink/blob/master/java_src/src/main/java/com/google/crypto/tink/KeyManager.java) interface for the _primitive_ from step #1 and the _key type_ from step #2. To use a custom implementation of a primitive in an application, register with the [`Registry`](https://github.com/google/tink/blob/master/java_src/src/main/java/com/google/crypto/tink/Registry.java) the custom `KeyManager` implementation (from step #3 above) for the custom key type (from step #2 above): ```java Registry.registerKeyManager(keyManager); ``` Afterwards the implementation will be accessed automatically by the `keysetHandle.getPrimitive` corresponding to the primitive (when keys of the specific key type are in use). It can also be retrieved directly via `Registry.getKeyManager(keyType)`. When defining the protocol buffers for the key material and parameters (step #2 above), you should provide definitions of three messages: * `...Params`: parameters of an instantiation of the primitive, needed when a key is being used. * `...Key`: the actual key proto, contains the key material and the corresponding `...Params` proto. * `...KeyFormat`: parameters needed to generate a new key. Here are a few conventions/recommendations when defining these messages (see [tink.proto](https://github.com/google/tink/blob/master/proto/tink.proto) and definitions of [existing key types](https://github.com/google/tink/blob/master/proto/) for details): * `...Key` should contain a version field (a monotonic counter, `uint32 version;`), which identifies the version of implementation that can work with this key. * `...Params` should be a field of `...Key`, as by definition `...Params` contains parameters needed when the key is being used. * `...Params` should be also a field of `...KeyFormat`, so that given `...KeyFormat` one has all information it needs to generate a new `...Key` message. Alternatively, depending on the use case requirements, you can skip step #2 entirely and re-use an existing protocol buffer messages for the key material. In such a case, you should not configure the Registry via the `Config`-class, but rather register the needed `KeyManager`-instances manually. For a concrete example, let's assume that we'd like a custom implementation of the [`Aead`](https://github.com/google/tink/blob/master/java_src/src/main/java/com/google/crypto/tink/Aead.java) primitive (step #1). We define then three protocol buffer messages (step #2): * `MyCustomAeadParams`: holds parameters needed for the use of the key material. * `MyCustomAeadKey`: holds the actual key material and parameters needed for its use. * `MyCustomAeadKeyFormat`: holds parameters needed for generation of a new `MyCustomAeadKey`-key. ```proto syntax = "proto3"; package mycompany.mypackage; message MyCustomAeadParams { uint32 iv_size = 1; // size of initialization vector in bytes } message MyCustomAeadKeyFormat { MyCustomAeadParams params = 1; uint32 key_size = 2; // key size in bytes } // key_type: type.googleapis.com/mycompany.mypackage.MyCustomAeadKey message MyCustomAeadKey { uint32 version = 1; MyCustomAeadParams params = 2; bytes key_value = 3; // the actual key material } ``` The corresponding _key type_ in Java is defined as ```java String keyType = "type.googleapis.com/mycompany.mypackage.MyCustomAeadKey";` ``` and the corresponding _key manager_ implements (step #3) the interface [`KeyManager`](https://github.com/google/tink/blob/master/java_src/src/main/java/com/google/crypto/tink/KeyManager.java) ```java class MyCustomAeadKeyManager implements KeyManager { // ... } ``` After registering `MyCustomAeadKeyManager` with the Registry, it will be used when you call `keysetHandle.getPrimitive(Aead.class)`. ================================================ FILE: docs/JWT-HOWTO.md ================================================ # Tink's JWT HOW-TO This is a short introduction on the JSON Web Token (JWT) library in [Tink](https://github.com/google/tink). The JWT standard is defined in [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519). The standard has many options, and many options are rarely used and some options are difficult to use correctly. The goal of Tink's JWT implementation is provide as subset of the JWT standard that we consider safe to use, and fit well into Tink. These are the limitations of Tink's JWT library: - Tink only supports the [JWS Compact Serialization](https://datatracker.ietf.org/doc/html/rfc7515#section-3.1) format. [JWS JSON Serialization](https://datatracker.ietf.org/doc/html/rfc7515#section-3.2) and [JWE](https://datatracker.ietf.org/doc/html/rfc7516) is not supported. - Tink does not support the `None` value in the `alg` header. - Tink only supports the headers `typ`, `alg` and `kid`. All other headers are not supported. - Tink does not allow tokens to be parsed before the signature/mac is verified. ## JWT Primitives and Key Types Tink's JWT library provides primitives for both MAC and signatures. The interfaces for these primitives are called `JwtMac`, `JwtPublicKeySign` and `JwtPublicKeyVerify`. As with normal MACs and signatures, symmetric and asymmetric primitives are kept separate. Note that even though the JWT library uses the same MAC and signature algorithms as the normal MAC and signature primitives, the JWT library uses *different* key types. This is needed because some metadata (such as `alg` and `kid`) needs to be stored with the key. If tokens are generated and verified by different entities, then you should use asymmetric keys with the primitives `JwtPublicKeySign` and `JwtPublicKeyVerify`. The private key is used to generate tokens, and the public key is used to verify tokens. The algorithms supported by these primitives are: `ES256`, `ES384`, `ES512`, `RS256`, `RS384`, `RS512`, `PS256`, `PS384` and `PS512`. Only use the `JwtMac` primitive if the tokens are generated and verified by the same entity. The algorithms supported by this primitive are `HS256`, `HS384` and `HS512`. In [Tinkey](TINKEY.md), all templates that can be used with the JWT primitives start with `JWT_`, followed by the algorithm and some additional parameters. For example `JWT_HS256`, `JWT_ES256`, `JWT_RS256_3072_F4` or `JWT_PS256_3072_F4`. ## Public keyset distribution In most cases, JWTs are generated by one party using a private keyset and verified by another party using the public keyset. This requires that the public keyset can be exported and shared. Tink allows public keyset to be converted to and from the standard [JWK Set](https://datatracker.ietf.org/doc/html/rfc7517#section-5) format, which most JWT libraries will understand. (Note that while Tink's `JsonKeysetWriter` will also produce keysets in JSON format, the output is *not* a JWK Set and other libraries will not be able to read it.) Tink does not support exporting public JWT keysets in any other format. The reason for this is that other formats do not contain the `alg` and the `kid` metadata to be used in the verification, which makes using them more error-prone and may make it more difficult to rotate keys. It is preferable to not just share the public keyset once, but to provide a way to *automatically* update the public keyset. (If not, rotating to a new key will be very hard.) Often, this is done by publishing the public keyset on a trusted and secured URL. A server that verifies tokens then simply has to periodically re-fetch the public keyset from that URL, for example once per day. To rotate the key, the new public key needs to be added to the public keyset *at least one day before* it is used to sign tokens. Otherwise the new tokens signed with the new private key will be rejected by servers that still use the old public keyset. Some implementations re-fetch the public key as soon as a token with an unknown `kid` header is received. Implementing this logic is not possible in Tink, since we don't parse the token before they are verified. We also don't recommend doing this, as it may result in lots of extra requests to the keyset URL if malicious tokens with random `kid` headers are sent. ## Headers and Claims #### Algorithm Header `alg` The `alg` header is always set and verified automatically by the Tink primitives and cannot be accessed by the user. This makes it easier to rotate to a different key type, as the user code does not depend on the particular key type used. #### Key ID Header `kid` The `kid` header is set and verified automatically by the Tink primitives. Tink supports both tokens with and without a `kid` header. They can be used in exactly the same way, both support key rotation. Tokens without a `kid` header are a bit shorter, but the difference is small. It is usually safer to generate tokens with the `kid` header set, as other JWT libraries may require them to be set. Tinkey JWT key templates without a `_RAW` suffix (such as `JWT_ES256`) generate tokens with `kid` header. Templates with `_RAW` suffix (such as `JWT_ES256_RAW`) generate tokens without `kid` header. #### Type Header `typ` The goal of the `typ` header is to clearly separate different types of token from each other. Not doing this separation correctly may result in security issues. But there are other ways to do this separation, for example by distinguishing different tokens by the claim names they use, or simply by using different keyset for different tokens. We therefore don't enforce the usage of the `typ` header. But, when a token with a `typ` header is verified, we require that the verifier explicitly validates it, or explicitly ignores it. This makes sure that the validation of this header is not forgotten. Setting the `typ` header always to the constant value `JWT` is not needed. #### Issuer claim `iss` This claim identifies the party that signed the token. This claim is usually a constant value for a given keyset, and globally unique. Often a URI is used to make it unique. Often, identity of the issuer is already clear by the fact that only the owner of the private keyset (which is the issuer) can generate tokens. In these cases, it may not be necessary to set the issuer claim in the token. But if the issuer claim is set, then we require that the verifier explicitly checks it, or explicitly ignores it. Tink does not support to dynamically look-up a keyset based on the issuer claim, as this may lead to security problems if the lookup is done without proper validation. We require that the verifier know the issuer and the keyset used to verify the token before looking at the token. #### Audiences claim `aud` This claim identifies a list of verifier that may accept this token. If this claim is set the verifier is required to pass its identity as expected audience. We do allow to explicitly ignore this claim, as it may be needed in some cases, for example if verifier's identity changed, and both the old and the new identity need to be accepted. #### Expiration `exp`, not-before `nbf` and issued-at `iat` claims In most use cases, tokens should have an expiration date set. That's why Tink by default expects the user to set an expiration. There are some tokens that don't have expiration dates, see for example [RFC 8417](https://datatracker.ietf.org/doc/html/rfc8417). Tink allows this, but requires the user to explicitly pass a parameter without_expiration when creating a token, to make sure that this is on purpose. * The expiration date claim `exp` is *always* validated. Tink does not allow to turn this off, because the content of an expired token could be outdated or invalid, and should not be used. * The not-before claim `nbf` is rarly used, but it is supported and will always be validated. * Tink optionally supports validating that the issued-at claim `iat` is not in the pass. #### Validating any other claim Your application may have other claims that need to be validated. For example, maybe the token has a `sub` claim that needs to be in a special format, or it requires an `email` claim to be present. Tink can't really help the verifier in validating these claims, as validating these is different for different types of tokens. We recommend validating these claims immediately after Tink has successfully verified the token. ## Code Examples Here are some small examples on how to use Tink's JWT library: * [examples/cc/jwt](https://github.com/google/tink/tree/master/cc/examples/jwt) * [examples/java_src/jwt](https://github.com/google/tink/tree/master/java_src/examples/jwt) * [examples/python/jwt](https://github.com/google/tink/tree/master/python/examples/jwt) ================================================ FILE: docs/KEY-MANAGEMENT.md ================================================ # Key Management with Tink Improper key management is a major source of risk. Tink has built-in support for industry-leading options to help you secure your keys. Please see the [developer documentation](https://developers.google.com/tink/key-management-overview) on how to implement proper key management. ================================================ FILE: docs/KNOWN-ISSUES.md ================================================ # Known Issues in Tink See https://developers.google.com/tink/known-issues. ================================================ FILE: docs/OBJC-HOWTO.md ================================================ # Tink for Obj-C HOW-TO This document contains instructions and Obj-C code snippets for common tasks in [Tink](https://github.com/google/tink). ## Setup instructions Tink is released as a [Cocoapod](https://cocoapods.org/). It can be installed by using the pod command as described below, which is the recommended way to use Tink. We also provide step-by-step instructions on building and using Tink from source. #### Supported platforms * iOS 9.0 or newer * Xcode 9.2 or newer ### Installing via Cocoapods 1. Change into the directory that contains your Xcode project. ```sh cd /path/to/your/Xcode project/ ``` 2. Initialize Cocoapods. ```sh pod init ``` This command creates a file called Podfile. 3. Edit the Podfile. For the current stable release, add the following line: ``` pod 'Tink' ``` For a particular version, use a line like the following instead: ``` pod 'Tink', '1.2.0-rc2' ``` Note: Replace 1.2.0-rc2 with the pre-release version you want to install. 4. Install the pod. ```sh $ pod install ``` 5. Open the newly generated .xcworkspace and start using Tink. You can import the umbrella header: ```objc #import "Tink/Tink.h" ``` Or individual headers: ```objc #import "Tink/TINKAeadConfig.h" #import "Tink/TINKAeadKeyTemplate.h" #import "Tink/TINKAead.h" ``` ### Installing from source #### Prerequisites To install Tink from the source code, the following prerequisites must be installed: * [git](https://git-scm.com/) - to download the source of Tink * [Bazel](https://www.bazel.build) v0.15.0 or newer - to build Tink #### Step-by-step instructions 1. Clone Tink from GitHub. ```sh git clone https://github.com/google/tink/ ``` 2. Build the library and generate a static iOS framework. ```sh cd tink export XCODE_VERSION=9.2 export IOS_SDK=11.2 bazel build -c opt --ios_multi_cpus=i386,x86_64,armv7,arm64 --xcode_version="${XCODE_VERSION}" --ios_sdk_version="${IOS_SDK}" //objc:Tink_framework ``` Adjust the following options according to your build environment: * Set `XCODE_VERSION` to the Xcode version you are using to build your application. * Set `IOS_SDK` to the version of the iOS SDK you are using in your application. * The option `ios_multi_cpus` is used to generate a fat library that includes multiple architectures. Before submitting your application to the App Store you should generate a framework that includes only the ARM architectures and link it to your binary. 3. Unzip Tink\_framework.zip into your Xcode project folder. ```sh unzip bazel-bin/objc/Tink_framework.zip -d /path/to/your/project/folder/ ``` 4. Add the static framework to your Xcode project options: * Open your Xcode project * Navigate to your project's folder and drag Tink.framework into your Xcode's left pane. * In the following dialog select `Copy items if needed` and the target of your application that will use Tink. Click `Finish`. * Select your project on the left pane and click on "Build Settings" * Find `Other Linker Flags` and add `-lc++` 5. Start using Tink in your code. You can import the umbrella header: ```objc #import "Tink/Tink.h" ``` Or individual headers: ```objc #import "Tink/TINKAeadConfig.h" #import "Tink/TINKAeadKeyTemplate.h" #import "Tink/TINKAead.h" ``` ## Initializing Tink Tink provides customizable initialization, which allows for choosing specific implementations (identified by _key types_) of desired primitives. This initialization happens via _registration_ of the implementations. For example, if you want to use all implementations of all primitives in the current version of Tink, the initialization would look as follows: ```objc #import "Tink/TINKAllConfig.h" #import "Tink/TINKConfig.h" NSError *error = nil; TINKAllConfig *config = [[TINKAllConfig alloc] initWithError:&error]; if (!config || error) { // handle error. } if (![TINKConfig registerConfig:config error:&error]) { // handle error. } ``` To use only implementations of the AEAD primitive: ```objc #import "Tink/TINKAeadConfig.h" #import "Tink/TINKConfig.h" NSError *error = nil; TINKAeadConfig *aeadConfig = [[TINKAeadConfig alloc] initWithError:&error]; if (!aeadConfig || error) { // handle error. } if (![TINKConfig registerConfig:aeadConfig error:&error]) { // handle error. } ``` ## Generating new keys and keysets To avoid accidental leakage of sensitive key material, you should avoid mixing keyset generation and usage in code. To support the separation between these activities the Tink package provides a command-line tool called [Tinkey](TINKEY.md), which can be used for common key management tasks. Still, if there is a need to generate a KeysetHandle with fresh key material directly in Obj-C code, one can use [`TINKKeysetHandle`](https://github.com/google/tink/blob/master/objc/TINKKeysetHandle.h) with one of the available KeyTemplates (AeadKeyTemplate, HybridKeyTemplate, etc.): ```objc #import "Tink/TINKAeadKeyTemplate.h" #import "Tink/TINKKeysetHandle.h" NSError *error = nil; TINKAeadKeyTemplate *tpl = [[TINKAeadKeyTemplate alloc] initWithKeyTemplate:TINKAes128Gcm error:&error]; if (!tpl || error) { // handle error. } TINKKeysetHandle *handle = [[TINKKeysetHandle alloc] initWithKeyTemplate:tpl error:&error]; if (!handle || error) { // handle error. } ``` ## Storing keysets After generating key material, you might want to persist it to a storage system. Tink supports storing keysets to the iOS keychain where they remain encrypted: ```objc #import "Tink/TINKKeysetHandle.h" NSError *error = nil; TINKKeysetHandle *handle = [[TINKKeysetHandle alloc] initWithKeyTemplate:tpl error:&error]; if (!handle || error) { // handle error. } NSString *keysetName = @"com.yourcompany.yourapp.uniqueKeysetName"; if (![handle writeToKeychainWithName:keysetName overwrite:NO error:&error]) { // handle error. } ``` The keysets are stored in the keychain with the following options set: * kSecAttrAccessible = kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly * kSecAttrSynchronizable = False These settings prevent the keysets from leaving the device and keep them encrypted until the device is unlocked once. ## Loading existing keysets To load keysets from the iOS keychain: ```objc #import "Tink/TINKKeysetHandle.h" NSError *error = nil; NSString *keysetName = @"com.yourcompany.yourapp.uniqueKeysetName"; TINKKeysetHandle *handle = [[TINKKeysetHandle alloc] initFromKeychainWithName:keysetName error:&error]; if (!handle || error) { // handle error. } ``` To load cleartext keysets, use [`TINKKeysetHandle+Cleartext`](https://github.com/google/tink/blob/master/objc/TINKKeysetHandle+Cleartext.h) and an appropriate [`KeysetReader`](https://github.com/google/tink/blob/master/objc/TINKKeysetReader.h), depending on the wire format of the stored keyset, for example a [`TINKBinaryKeysetReader`](https://github.com/google/tink/blob/master/objc/TINKBinaryKeysetReader.h). Note: We don't recommend storing keysets in cleartext in the filesystem. Instead, use the iOS keychain as demonstrated above. ```objc #import "Tink/TINKBinaryKeysetReader.h" #import "Tink/TINKKeysetHandle+Cleartext.h" NSError *error = nil; NSData *binaryKeyset = ...; TINKBinaryKeysetReader *reader = [[TINKBinaryKeysetReader alloc] initWithSerializedKeyset:binaryKeyset error:&error]; if (!reader || error) { // handle error. } TINKKeysetHandle *handle = [[TINKKeysetHandle alloc] initCleartextKeysetHandleWithKeysetReader:reader error:&error]; if (!handle || error) { // handle error. } ``` ## Obtaining and using primitives [_Primitives_](PRIMITIVES.md) represent cryptographic operations offered by Tink, hence they form the core of Tink API. A primitive is just an interface that specifies what operations are offered by the primitive. A primitive can have multiple implementations, and you choose a desired implementation by using a key of corresponding type (see the [this section](KEY-MANAGEMENT.md#key-keyset-and-keysethandle) for details). A list of primitives and their implementations currently supported by Tink in Objective-C can be found [here](PRIMITIVES.md#objective-c). You access implementations of a primitive via a factory that corresponds to the primitive which offers corresponding `primitiveWithKeysetHandle:error:` methods. * AEAD via `TINKAeadFactory` * MAC via `TINKMacFactory` * etc. ### Symmetric key encryption You can use an [AEAD (Authenticated Encryption with Associated Data)](PRIMITIVES.md#authenticated-encryption-with-associated-data) primitive to encrypt or decrypt data: ```objc #import "Tink/TINKAead.h" #import "Tink/TINKKeysetHandle.h" #import "Tink/TINKAeadFactory.h" // 1. Get a handle to the key material. TINKKeysetHandle *keysetHandle = ...; // 2. Get the primitive. NSError *error = nil; id aead = [TINKAeadFactory primitiveWithKeysetHandle:keysetHandle error:&error]; if (!aead || error) { // handle error. } // 3. Use the primitive. NSData *ciphertext = [aead encrypt:plaintext withAdditionalData:aad error:&error]; if (!ciphertext || error) { // handle error. } ``` ### Hybrid encryption To decrypt using [a combination of public key encryption and symmetric key encryption](PRIMITIVES.md#hybrid-encryption): ```objc #import "Tink/TINKHybridDecrypt.h" #import "Tink/TINKKeysetHandle.h" #import "Tink/TINKHybridDecryptFactory.h" // 1. Get a handle to the key material. TINKKeysetHandle *keysetHandle = ...; // 2. Get the primitive. NSError *error = nil; id hybridDecrypt = [TINKHybridDecryptFactory primitiveWithKeysetHandle:keysetHandle error:&error]; if (!hybridDecrypt || error) { // handle error. } // 3. Use the primitive. NSData *plaintext = [hybridDecrypt decrypt:ciphertext withContextInfo:contextInfo error:&error]; if (!plaintext || error) { // handle error. } ``` ================================================ FILE: docs/PRIMITIVES.md ================================================ # Tink Primitives [Tink](https://github.com/google/tink) performs cryptographic tasks via so-called [*primitives* and *interfaces*](https://developers.google.com/tink/design/primitives_and_interfaces). ## Supported primitives and their implementations ### Primitives supported by language See https://developers.google.com/tink/primitives-by-language ### Primitive implementations supported by language See https://developers.google.com/tink/supported-key-types ## General properties of all primitives - stateless (hence thread-safe) - copy-safe (for the parameters) - at least 128-bit security (with an exception for RSA) ## Authenticated Encryption with Associated Data See https://developers.google.com/tink/aead ## Streaming Authenticated Encryption with Associated Data See https://developers.google.com/tink/streaming-aead ## Deterministic Authenticated Encryption with Associated Data See https://developers.google.com/tink/deterministic-aead ## Message Authentication Code See https://developers.google.com/tink/mac ## Pseudo Random Function Families See https://developers.google.com/tink/prf ## Hybrid Encryption See https://developers.google.com/tink/hybrid ## Digital Signatures See https://developers.google.com/tink/digital-signature ================================================ FILE: docs/PYTHON-HOWTO.md ================================================ # Tink for Python HOW-TO This document presents instructions and Python code snippets for common tasks in [Tink](https://github.com/google/tink). ## Setup instructions Tink requires Python 3.7 or above. The simplest way is to install a binary release from [PyPi](https://pypi.org/project/tink/): ```shell pip3 install tink ``` Currently, the following set of binary wheels are published: * Linux * Python 3.7 * Python 3.8 * Python 3.9 * macOS * Python 3.7 * Python 3.8 * Python 3.9 In addition to the binary wheels, a source distribution is also published. If `pip` does not find a suitable binary wheel for your environment, it will fall back to building the project using the source distribution. This process has the same requirements as building from source instructions below. ### Common setup issues * If you get an error regarding the root certs when using the GCP KMS integration, you will have to install the [root certs](https://github.com/googleapis/google-cloud-cpp/blob/master/google/cloud/bigtable/examples/README.md#configure-grpc-root-certificates). ## Building from source Tink currently supports two build systems for use with Python: * [Bazel](https://bazel.build/) * Setuptools to create a Python package Note that in both cases [Bazel](https://bazel.build/) is required, as it is needed to compile the wrapper around the C++ implementation which uses [pybind11](https://github.com/pybind/pybind11). ### Build with Bazel To build the Python implementation: ```shell cd python bazel build ... ``` ### Build a Python package using pip A setup script is provided which allows building a Python package using pip. The setup script requires: * Bazel * [protobuf compiler](https://github.com/protocolbuffers/protobuf#protocol-compiler-installation). To build and install the Python package: ```shell cd python pip3 install . ``` ### Running tests To run all tests, you can: ```shell cd python bazel test ... ``` ## Initializing Tink Tink provides customizable initialization, which allows for choosing specific implementations (identified by _key types_) of desired primitives. This initialization happens via _registration_ of the implementations. For example, if you want to use all standard implementations of all primitives in the current release of Tink, the initialization would look as follows: ```python import tink from tink import tink_config tink_config.register() ``` To use standard implementations of only one primitive, say AEAD: ```python import tink from tink import aead aead.register() ``` The registration of custom key managers can proceed directly via the `core.Registry` class: ```python import tink from tink import core core.Registry.register_key_manager(CustomAeadKeyManager()) ``` ## Generating new keys and keysets Each `KeyManager` implementation provides a `new_key_data(key_template)` method that generates new keys of the corresponding key type. However, to avoid accidental leakage of sensitive key material you should avoid mixing key(set) generation with key(set) usage in code. To support the separation between these activities Tink package provides a command-line tool called [Tinkey](TINKEY.md), which can be used for common key management tasks. Still, if there is a need to generate a KeysetHandle with fresh key material directly in Python code, you can use `tink.new_keyset_handle`: ```python import tink from tink import aead key_template = aead.aead_key_templates.AES128_EAX keyset_handle = tink.new_keyset_handle(key_template) # use the keyset... ``` where `key_template` can be obtained from util classes corresponding to Tink primitives, e.g. [mac_key_templates](https://github.com/google/tink/blob/master/python/tink/mac/_mac_key_templates.py), [aead_key_templates](https://github.com/google/tink/blob/master/python/tink/aead/_aead_key_templates.py), or [hybrid_key_templates](https://github.com/google/tink/blob/master/python/tink/hybrid/_hybrid_key_templates.py). ## Loading existing keysets To load encrypted keysets, use `tink.read_keyset_handle` and an appropriate [`KeysetReader`](https://github.com/google/tink/blob/master/python/tink/_keyset_reader.py), depending on the wire format of the stored keyset, for example a `tink.BinaryKeysetReader` or a `tink.JsonKeysetReader`. ```python import tink json_encrypted_keyset = ... reader = tink.JsonKeysetReader(json_encrypted_keyset) keyset_handle = tink.read_keyset_handle(reader, master_key_aead) ``` To load cleartext keysets, use [`cleartext_keyset_handle`](https://github.com/google/tink/blob/master/python/tink/cleartext_keyset_handle.py) and an appropriate `KeysetReader`. ```python import tink from tink import cleartext_keyset_handle json_keyset = ... reader = tink.JsonKeysetReader(json_keyset) keyset_handle = cleartext_keyset_handle.read(reader) ``` ## Obtaining and using primitives [_Primitives_](PRIMITIVES.md) represent cryptographic operations offered by Tink, hence they form the core of the Tink API. A primitive is just an interface that specifies what operations are offered by the primitive. A primitive can have multiple implementations, and you choose a desired implementation by using a key of corresponding type (see [this section](KEY-MANAGEMENT.md#key-keyset-and-keysethandle) for further details). Tink for Python supports the same primitives as Tink for C++. A list of primitives and their implementations currently supported by Tink in C++ can be found [here](PRIMITIVES.md#c). You obtain a primitive by calling the method `primitive` of the `KeysetHandle`. ### Symmetric key encryption You can obtain and use an [AEAD (Authenticated Encryption with Associated Data)](PRIMITIVES.md#authenticated-encryption-with-associated-data) primitive to encrypt or decrypt data: ```python import tink from tink import aead plaintext = b'your data...' associated_data = b'context' # Register all AEAD primitives aead.register() # 1. Get a handle to the key material. keyset_handle = tink.new_keyset_handle(aead.aead_key_templates.AES256_GCM) # 2. Get the primitive. aead_primitive = keyset_handle.primitive(aead.Aead) # 3. Use the primitive. ciphertext = aead_primitive.encrypt(plaintext, associated_data) ``` ### Deterministic symmetric key encryption You can obtain and use a [DeterministicAEAD (Deterministic Authenticated Encryption with Associated Data](PRIMITIVES.md#deterministic-authenticated-encryption-with-associated-data) primitive to encrypt or decrypt data: ```python import tink from tink import daead plaintext = b'your data...' associated_data = b'context' # Register all deterministic AEAD primitives daead.register() # 1. Get a handle to the key material. keyset_handle = tink.new_keyset_handle(daead.deterministic_aead_key_templates.AES256_SIV) # 2. Get the primitive. daead_primitive = keyset_handle.primitive(daead.DeterministicAead) # 3. Use the primitive. ciphertext = daead_primitive.encrypt_deterministically(plaintext, associated_data) ``` ### Symmetric key encryption of streaming data You can obtain and use a [Streaming AEAD (Streaming Authenticated Encryption with Associated Data)](PRIMITIVES.md#streaming-authenticated-encryption-with-associated-data) primitive to encrypt or decrypt data streams: ```python import tink from tink import streaming_aead long_plaintext = b'your data...' associated_data = b'context' # Register all streaming AEAD primitives streaming_aead.register() # 1. Get a handle to the key material keyset_handle = tink.new_keyset_handle(streaming_aead.streaming_aead_key_templates.AES256_CTR_HMAC_SHA256_4KB) # 2. Get the primitive. streaming_aead_primitive = keyset_handle.primitive(streaming_aead.StreamingAead) # 3. Use the primitive. output_file = open("ciphertext.out", 'wb') with streaming_aead_primitive.new_encrypting_stream(output_file, associated_data) as enc_stream: bytes_written = enc_stream.write(long_plaintext) ``` ### Message Authentication Code You can compute or verify a [MAC (Message Authentication Code)](PRIMITIVES.md#message-authentication-code): ```python import tink from tink import mac data = b'your data...' # Register all MAC primitives mac.register() # 1. Get a handle to the key material. keyset_handle = tink.new_keyset_handle(mac.mac_key_templates.HMAC_SHA256_128BITTAG) # 2. Get the primitive. mac_primitive = keyset_handle.primitive(mac.Mac) # 3. Use the primitive to compute a tag, tag = mac_primitive.compute_mac(data) # ... or to verify a tag. mac_primitive.verify_mac(tag, data) ``` ### Hybrid Encryption To encrypt or decrypt using [a combination of public key encryption and symmetric key encryption](PRIMITIVES.md#hybrid-encryption) one can use the following: ```python import tink from tink import hybrid plaintext = b'your data...' context = b'context' # Register all Hybrid primitives hybrid.register() # 1. Generate the private key material. private_keyset_handle = tink.new_keyset_handle(hybrid.hybrid_key_templates.ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM) # Obtain the public key material. public_keyset_handle = private_keyset_handle.public_keyset_handle() # Encryption # 2. Get the primitive. hybrid_encrypt = public_keyset_handle.primitive(hybrid.HybridEncrypt) # 3. Use the primitive. ciphertext = hybrid_encrypt.encrypt(plaintext, context) # Decryption # 2. Get the primitive. hybrid_decrypt = private_keyset_handle.primitive(hybrid.HybridDecrypt) # 3. Use the primitive. plaintext = hybrid_decrypt.decrypt(ciphertext, context) ``` ### Digital Signatures You can sign or verify using a [digital signature](PRIMITIVES.md#digital-signatures): ```python import tink from tink import signature # Register key manager for signatures signature.register() # Signing # 1. Generate the private key material. keyset_handle = tink.new_keyset_handle(signature.signature_key_templates.ED25519) # 2. Get the primitive. signer = keyset_handle.primitive(signature.PublicKeySign) # 3. Use the primitive to sign. signature_data = signer.sign(b'your data') # Verifying # 1. Obtain the public key material. public_keyset_handle = keyset_handle.public_keyset_handle() # 2. Get the primitive. verifier = public_keyset_handle.primitive(signature.PublicKeyVerify) # 3. Use the primitive to verify. verifier.verify(signature_data, b'your data') ``` ### Envelope encryption Via the AEAD interface, Tink supports [envelope encryption](KEY-MANAGEMENT.md#envelope-encryption). For example, you can perform envelope encryption with a Google Cloud KMS key at `gcp-kms://projects/tink-examples/locations/global/keyRings/foo/cryptoKeys/bar` using the credentials in `credentials.json` as follows: ```python import tink from tink import aead from tink.integration import gcpkms key_uri = 'gcp-kms://projects/tink-examples/locations/global/keyRings/foo/cryptoKeys/bar' gcp_credentials = 'credentials.json' plaintext = b'your data...' associated_data = b'context' # Read the GCP credentials and setup client try: gcp_client = gcpkms.GcpKmsClient(key_uri, gcp_credentials) gcp_aead = gcp_client.get_aead(key_uri) except tink.TinkError as e: logging.error('Error initializing GCP client: %s', e) return 1 # Create envelope AEAD primitive using AES256 GCM for encrypting the data try: key_template = aead.aead_key_templates.AES256_GCM env_aead = aead.KmsEnvelopeAead(key_template, gcp_aead) except tink.TinkError as e: logging.error('Error creating primitive: %s', e) return 1 # Use env_aead to encrypt data ciphertext = env_aead.encrypt(plaintext, associated_data) ``` ================================================ FILE: docs/SECURITY-USABILITY.md ================================================ # Tink's Security and Usability Design Goals The work on Tink is guided by the design goals discussed below. To get a quick overview of Tink design you can also take a look at [slides](Tink-a_cryptographic_library--RealWorldCrypto2019.pdf) from [a talk about Tink](https://www.youtube.com/watch?v=pqev9r3rUJs&t=9665) presented at [Real World Crypto 2019](https://rwc.iacr.org/2019/). * **Security** Tink is built on top of existing libraries such as BoringSSL and Java Cryptography Architecture, but includes countermeasures to many weaknesses in these libraries, which were discovered by Project Wycheproof, another project from our team. * **Easiness** Most crypto operations such as data encryption, digital signatures, etc. can be done with only a few lines of code. Tink's interfaces abstract away from the underlying implementations. Interfaces are usable without knowing the underlying class that implements it. * **Hard-to-misuse** Tink aims to eliminate as many potential misuses as possible. For example, if the underlying encryption mode requires nonces and is insecure if nonces are reused, then Tink does not allow the passing of nonces by the user. Interfaces have security guarantees that must be satisfied by each primitive implementing the interface. This may exclude some encryption modes. Rather than adding them to existing interfaces and weakening the guarantees of the interface it is possible to add new interfaces and describe the security guarantees appropriately. * **Readability** Tink shows the security guarantees (e.g., safe against chosen-ciphertext attacks) right in the interfaces, allowing security auditors and automated tools to quickly discover usages where the security guarantees don’t match the security requirements. Tink also separates APIs for potential dangerous operations (e.g., loading cleartext keys from disk), allowing discovering, restricting, monitoring and logging their usages. * **Extensibility** Tink makes it easy to support new primitives, new algorithms, new ciphertext formats, new key management systems, etc. * **Agility** Tink provides built-in crypto agility. It supports key rotation, deprecation of obsolete schemes and adaptation of new ones. For example, if an implementation of a crypto primitive is found broken, you can switch to a different implementation by rotating keys, without changing or recompiling code. * **Interoperability** Tink produces and consumes ciphertexts that are compatible with existing crypto libraries. Tink supports encrypting or storing keys in Amazon KMS, Google Cloud KMS, Android Keystore, iOS Keychain, and it is easy to add support for custom key management systems. * **Versatility** No part of Tink is hard to replace or remove. All components are recombinant, and can be selected and assembled in various combinations. For example, if you need only digital signatures, you can exclude symmetric key encryption components. ================================================ FILE: docs/SECURITY.md ================================================ To report a security issue, please use http://g.co/vulnz. We use http://g.co/vulnz for our intake and coordination, and disclose vulnerabilities using GitHub Security Advisory. The Google Security Team will respond within 5 working days of your report on g.co/vulnz. ================================================ FILE: docs/TINKEY.md ================================================ # Tinkey This utility allows generating and manipulating Tink keysets. For more information see https://developers.google.com/tink/tinkey-overview. ================================================ FILE: docs/WIRE-FORMAT.md ================================================ # Tink Wire Format Please see the [developer documentation](https://developers.google.com/tink/wire-format) for details on Tink's wire format for keys and primitive output. ================================================ FILE: go/.bazelversion ================================================ 6.0.0 ================================================ FILE: go/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "nogo") load("@bazel_gazelle//:def.bzl", "gazelle") package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) nogo( name = "tink_nogo", vet = True, visibility = ["//visibility:public"], ) # gazelle:prefix github.com/google/tink/go gazelle( name = "gazelle", args = [ "-go_naming_convention=import_alias", ], ) gazelle( name = "gazelle-update-repos", args = [ "-from_file=go.mod", "-to_macro=deps.bzl%go_dependencies", "-prune", ], command = "update-repos", ) ================================================ FILE: go/README.md ================================================ # Tink Go This is the Go implementation of Tink v1.7.0. > **NOTE**: **This library has migrated to > https://github.com/tink-crypto/tink-go > ([godoc](https://pkg.go.dev/github.com/tink-crypto/tink-go/tink))** ================================================ FILE: go/WORKSPACE ================================================ workspace(name = "tink_go") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file") http_file( name = "google_root_pem", executable = 0, sha256 = "1acf0d4780541758be2c0f998e1e0275232626ed3f8793d8e2fe8e2753750613", urls = ["https://pki.goog/roots.pem"], ) # ------------------------------------------------------------------------- # Bazel Skylib. # ------------------------------------------------------------------------- # Release from 2023-02-09 # Protobuf vX.21.9 imports a version of bazel-skylib [1] that is incompatible # with the one required by bazel-gazelle, so we make sure we have a newer # version [2]. # # [1] https://github.com/protocolbuffers/protobuf/blob/90b73ac3f0b10320315c2ca0d03a5a9b095d2f66/protobuf_deps.bzl#L28 # [2] https://github.com/bazelbuild/bazel-gazelle/issues/1290#issuecomment-1312809060 http_archive( name = "bazel_skylib", sha256 = "b8a1527901774180afc798aeb28c4634bdccf19c4d98e7bdd1ce79d1fe9aaad7", urls = [ "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.4.1/bazel-skylib-1.4.1.tar.gz", "https://github.com/bazelbuild/bazel-skylib/releases/download/1.4.1/bazel-skylib-1.4.1.tar.gz", ], ) # ------------------------------------------------------------------------- # Wycheproof. # ------------------------------------------------------------------------- # Commit from 2019-12-17 http_archive( name = "wycheproof", sha256 = "eb1d558071acf1aa6d677d7f1cabec2328d1cf8381496c17185bd92b52ce7545", strip_prefix = "wycheproof-d8ed1ba95ac4c551db67f410c06131c3bc00a97c", url = "https://github.com/google/wycheproof/archive/d8ed1ba95ac4c551db67f410c06131c3bc00a97c.zip", ) # ------------------------------------------------------------------------- # Protobuf. # ------------------------------------------------------------------------- # proto_library, cc_proto_library and java_proto_library rules implicitly # depend respectively on: # * @com_google_protobuf//:proto # * @com_google_protobuf//:cc_toolchain # * @com_google_protobuf//:java_toolchain # This statement defines the @com_google_protobuf repo. # Release X.21.9 from 2022-10-26. http_archive( name = "com_google_protobuf", strip_prefix = "protobuf-21.9", urls = ["https://github.com/protocolbuffers/protobuf/archive/refs/tags/v21.9.zip"], sha256 = "5babb8571f1cceafe0c18e13ddb3be556e87e12ceea3463d6b0d0064e6cc1ac3", ) load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") protobuf_deps() # ------------------------------------------------------------------------- # Bazel rules for Go. # ------------------------------------------------------------------------- # Release from 2023-04-20 http_archive( name = "io_bazel_rules_go", sha256 = "6dc2da7ab4cf5d7bfc7c949776b1b7c733f05e56edc4bcd9022bb249d2e2a996", urls = [ "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.39.1/rules_go-v0.39.1.zip", "https://github.com/bazelbuild/rules_go/releases/download/v0.39.1/rules_go-v0.39.1.zip", ], ) # ------------------------------------------------------------------------- # Bazel Gazelle. # ------------------------------------------------------------------------- # Release from 2023-01-14 http_archive( name = "bazel_gazelle", sha256 = "ecba0f04f96b4960a5b250c8e8eeec42281035970aa8852dda73098274d14a1d", urls = [ "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.29.0/bazel-gazelle-v0.29.0.tar.gz", "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.29.0/bazel-gazelle-v0.29.0.tar.gz", ], ) load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies") # ------------------------------------------------------------------------- # Tink Go Deps. # ------------------------------------------------------------------------- load("//:deps.bzl", "go_dependencies") # gazelle:repository_macro deps.bzl%go_dependencies go_dependencies() load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") go_rules_dependencies() go_register_toolchains( nogo = "@//:tink_nogo", version = "1.19.9", ) gazelle_dependencies() ================================================ FILE: go/aead/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep licenses(["notice"]) # keep go_library( name = "aead", srcs = [ "aead.go", "aead_factory.go", "aead_key_templates.go", "aes_ctr_hmac_aead_key_manager.go", "aes_gcm_key_manager.go", "aes_gcm_siv_key_manager.go", "chacha20poly1305_key_manager.go", "kms_envelope_aead.go", "kms_envelope_aead_key_manager.go", "xchacha20poly1305_key_manager.go", ], importpath = "github.com/google/tink/go/aead", visibility = ["//visibility:public"], deps = [ "//aead/subtle", "//core/cryptofmt", "//core/primitiveset", "//core/registry", "//internal/internalregistry", "//internal/monitoringutil", "//internal/tinkerror", "//keyset", "//mac/subtle", "//monitoring", "//proto/aes_ctr_go_proto", "//proto/aes_ctr_hmac_aead_go_proto", "//proto/aes_gcm_go_proto", "//proto/aes_gcm_siv_go_proto", "//proto/chacha20_poly1305_go_proto", "//proto/common_go_proto", "//proto/hmac_go_proto", "//proto/kms_envelope_go_proto", "//proto/tink_go_proto", "//proto/xchacha20_poly1305_go_proto", "//subtle/random", "//tink", "@org_golang_google_protobuf//proto", "@org_golang_x_crypto//chacha20poly1305", ], ) go_test( name = "aead_test", srcs = [ "aead_benchmark_test.go", "aead_factory_test.go", "aead_init_test.go", "aead_key_templates_test.go", "aead_test.go", "aes_ctr_hmac_aead_key_manager_test.go", "aes_gcm_key_manager_test.go", "aes_gcm_siv_key_manager_test.go", "chacha20poly1305_key_manager_test.go", "kms_envelope_aead_example_test.go", "kms_envelope_aead_key_manager_test.go", "kms_envelope_aead_test.go", "xchacha20poly1305_key_manager_test.go", ], deps = [ ":aead", "//aead/subtle", "//core/cryptofmt", "//core/registry", "//insecurecleartextkeyset", "//internal/internalregistry", "//internal/testing/stubkeymanager", "//internal/tinkerror/tinkerrortest", "//keyset", "//mac", "//monitoring", "//proto/aes_ctr_go_proto", "//proto/aes_ctr_hmac_aead_go_proto", "//proto/aes_gcm_go_proto", "//proto/aes_gcm_siv_go_proto", "//proto/chacha20_poly1305_go_proto", "//proto/common_go_proto", "//proto/hmac_go_proto", "//proto/kms_envelope_go_proto", "//proto/tink_go_proto", "//proto/xchacha20_poly1305_go_proto", "//signature", "//subtle/random", "//testing/fakekms", "//testing/fakemonitoring", "//testkeyset", "//testutil", "//tink", "@com_github_google_go_cmp//cmp", "@com_github_google_go_cmp//cmp/cmpopts", "@org_golang_google_protobuf//proto", "@org_golang_x_crypto//chacha20poly1305", ], ) alias( name = "go_default_library", actual = ":aead", visibility = ["//visibility:public"], ) ================================================ FILE: go/aead/aead.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package aead provides implementations of the AEAD primitive. // // AEAD encryption assures the confidentiality and authenticity of the data. This primitive is CPA secure. package aead import ( "fmt" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/internalregistry" ) func init() { if err := registry.RegisterKeyManager(new(aesCTRHMACAEADKeyManager)); err != nil { panic(fmt.Sprintf("aead.init() failed: %v", err)) } if err := registry.RegisterKeyManager(new(aesGCMKeyManager)); err != nil { panic(fmt.Sprintf("aead.init() failed: %v", err)) } if err := internalregistry.AllowKeyDerivation(aesGCMTypeURL); err != nil { panic(fmt.Sprintf("aead.init() failed: %v", err)) } if err := registry.RegisterKeyManager(new(chaCha20Poly1305KeyManager)); err != nil { panic(fmt.Sprintf("aead.init() failed: %v", err)) } if err := registry.RegisterKeyManager(new(xChaCha20Poly1305KeyManager)); err != nil { panic(fmt.Sprintf("aead.init() failed: %v", err)) } if err := internalregistry.AllowKeyDerivation(xChaCha20Poly1305TypeURL); err != nil { panic(fmt.Sprintf("aead.init() failed: %v", err)) } if err := registry.RegisterKeyManager(new(kmsEnvelopeAEADKeyManager)); err != nil { panic(fmt.Sprintf("aead.init() failed: %v", err)) } if err := registry.RegisterKeyManager(new(aesGCMSIVKeyManager)); err != nil { panic(fmt.Sprintf("aead.init() failed: %v", err)) } } ================================================ FILE: go/aead/aead_benchmark_test.go ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead_test import ( "testing" "github.com/google/tink/go/aead" "github.com/google/tink/go/keyset" "github.com/google/tink/go/subtle/random" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // Benchmarks for AEAD algorithms. func BenchmarkEncryptDecrypt(b *testing.B) { const ( plaintextSize = 16 * 1024 associatedDataSize = 256 ) testCases := []struct { name string template *tinkpb.KeyTemplate }{ { name: "AES128_GCM", template: aead.AES128GCMKeyTemplate(), }, { name: "AES256_GCM", template: aead.AES256GCMKeyTemplate(), }, { name: "CHACHA20_POLY1305", template: aead.ChaCha20Poly1305KeyTemplate(), }, { name: "XCHACHA20_POLY1305", template: aead.XChaCha20Poly1305KeyTemplate(), }, { name: "AES128_CTR_HMAC", template: aead.AES128CTRHMACSHA256KeyTemplate(), }, { name: "AES256_CTR_HMAC", template: aead.AES256CTRHMACSHA256KeyTemplate(), }, { name: "AES128_GCM_SIV", template: aead.AES128GCMSIVKeyTemplate(), }, { name: "AES256_GCM_SIV", template: aead.AES256GCMSIVKeyTemplate(), }, } for _, tc := range testCases { b.Run(tc.name, func(b *testing.B) { b.ReportAllocs() handle, err := keyset.NewHandle(tc.template) if err != nil { b.Fatal(err) } primitive, err := aead.New(handle) if err != nil { b.Fatal(err) } plaintext := random.GetRandomBytes(plaintextSize) associatedData := random.GetRandomBytes(associatedDataSize) b.ResetTimer() for i := 0; i < b.N; i++ { ciphertext, err := primitive.Encrypt(plaintext, associatedData) if err != nil { b.Fatal(err) } if _, err = primitive.Decrypt(ciphertext, associatedData); err != nil { b.Error(err) } } }) } } ================================================ FILE: go/aead/aead_factory.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead import ( "fmt" "github.com/google/tink/go/core/cryptofmt" "github.com/google/tink/go/core/primitiveset" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/internal/monitoringutil" "github.com/google/tink/go/keyset" "github.com/google/tink/go/monitoring" "github.com/google/tink/go/tink" ) // New returns an AEAD primitive from the given keyset handle. func New(handle *keyset.Handle) (tink.AEAD, error) { ps, err := handle.Primitives() if err != nil { return nil, fmt.Errorf("aead_factory: cannot obtain primitive set: %s", err) } return newWrappedAead(ps) } // wrappedAead is an AEAD implementation that uses the underlying primitive set for encryption // and decryption. type wrappedAead struct { ps *primitiveset.PrimitiveSet encLogger monitoring.Logger decLogger monitoring.Logger } func newWrappedAead(ps *primitiveset.PrimitiveSet) (*wrappedAead, error) { if _, ok := (ps.Primary.Primitive).(tink.AEAD); !ok { return nil, fmt.Errorf("aead_factory: not an AEAD primitive") } for _, primitives := range ps.Entries { for _, p := range primitives { if _, ok := (p.Primitive).(tink.AEAD); !ok { return nil, fmt.Errorf("aead_factory: not an AEAD primitive") } } } encLogger, decLogger, err := createLoggers(ps) if err != nil { return nil, err } return &wrappedAead{ ps: ps, encLogger: encLogger, decLogger: decLogger, }, nil } func createLoggers(ps *primitiveset.PrimitiveSet) (monitoring.Logger, monitoring.Logger, error) { if len(ps.Annotations) == 0 { return &monitoringutil.DoNothingLogger{}, &monitoringutil.DoNothingLogger{}, nil } client := internalregistry.GetMonitoringClient() keysetInfo, err := monitoringutil.KeysetInfoFromPrimitiveSet(ps) if err != nil { return nil, nil, err } encLogger, err := client.NewLogger(&monitoring.Context{ Primitive: "aead", APIFunction: "encrypt", KeysetInfo: keysetInfo, }) if err != nil { return nil, nil, err } decLogger, err := client.NewLogger(&monitoring.Context{ Primitive: "aead", APIFunction: "decrypt", KeysetInfo: keysetInfo, }) if err != nil { return nil, nil, err } return encLogger, decLogger, nil } // Encrypt encrypts the given plaintext with the given associatedData. // It returns the concatenation of the primary's identifier and the ciphertext. func (a *wrappedAead) Encrypt(plaintext, associatedData []byte) ([]byte, error) { primary := a.ps.Primary p, ok := (primary.Primitive).(tink.AEAD) if !ok { return nil, fmt.Errorf("aead_factory: not an AEAD primitive") } ct, err := p.Encrypt(plaintext, associatedData) if err != nil { a.encLogger.LogFailure() return nil, err } a.encLogger.Log(primary.KeyID, len(plaintext)) if len(primary.Prefix) == 0 { return ct, nil } output := make([]byte, 0, len(primary.Prefix)+len(ct)) output = append(output, primary.Prefix...) output = append(output, ct...) return output, nil } // Decrypt decrypts the given ciphertext and authenticates it with the given // associatedData. It returns the corresponding plaintext if the // ciphertext is authenticated. func (a *wrappedAead) Decrypt(ciphertext, associatedData []byte) ([]byte, error) { // try non-raw keys prefixSize := cryptofmt.NonRawPrefixSize if len(ciphertext) > prefixSize { prefix := ciphertext[:prefixSize] ctNoPrefix := ciphertext[prefixSize:] entries, err := a.ps.EntriesForPrefix(string(prefix)) if err == nil { for i := 0; i < len(entries); i++ { p, ok := (entries[i].Primitive).(tink.AEAD) if !ok { return nil, fmt.Errorf("aead_factory: not an AEAD primitive") } pt, err := p.Decrypt(ctNoPrefix, associatedData) if err == nil { a.decLogger.Log(entries[i].KeyID, len(ctNoPrefix)) return pt, nil } } } } // try raw keys entries, err := a.ps.RawEntries() if err == nil { for i := 0; i < len(entries); i++ { p, ok := (entries[i].Primitive).(tink.AEAD) if !ok { return nil, fmt.Errorf("aead_factory: not an AEAD primitive") } pt, err := p.Decrypt(ciphertext, associatedData) if err == nil { a.decLogger.Log(entries[i].KeyID, len(ciphertext)) return pt, nil } } } // nothing worked a.decLogger.LogFailure() return nil, fmt.Errorf("aead_factory: decryption failed") } ================================================ FILE: go/aead/aead_factory_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead_test import ( "bytes" "errors" "fmt" "strings" "testing" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/tink/go/aead" "github.com/google/tink/go/core/cryptofmt" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/insecurecleartextkeyset" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/internal/testing/stubkeymanager" "github.com/google/tink/go/keyset" "github.com/google/tink/go/monitoring" "github.com/google/tink/go/signature" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testing/fakemonitoring" "github.com/google/tink/go/testkeyset" "github.com/google/tink/go/testutil" "github.com/google/tink/go/tink" "github.com/google/tink/go/aead/subtle" agpb "github.com/google/tink/go/proto/aes_gcm_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestFactoryMultipleKeys(t *testing.T) { // encrypt with non-raw key keyset := testutil.NewTestAESGCMKeyset(tinkpb.OutputPrefixType_TINK) primaryKey := keyset.Key[0] if primaryKey.OutputPrefixType == tinkpb.OutputPrefixType_RAW { t.Errorf("expect a non-raw key") } keysetHandle, err := testkeyset.NewHandle(keyset) if err != nil { t.Fatalf("testkeyset.NewHandle() err = %s, want err", err) } a, err := aead.New(keysetHandle) if err != nil { t.Errorf("aead.New failed: %s", err) } expectedPrefix, err := cryptofmt.OutputPrefix(primaryKey) if err != nil { t.Errorf("cryptofmt.OutputPrefix() err = %s, want nil", err) } if err := validateAEADFactoryCipher(a, a, expectedPrefix); err != nil { t.Errorf("invalid cipher: %s", err) } // encrypt with a non-primary RAW key and decrypt with the keyset rawKey := keyset.Key[1] if rawKey.OutputPrefixType != tinkpb.OutputPrefixType_RAW { t.Errorf("expect a raw key") } keyset2 := testutil.NewKeyset(rawKey.KeyId, []*tinkpb.Keyset_Key{rawKey}) keysetHandle2, err := testkeyset.NewHandle(keyset2) if err != nil { t.Fatalf("testkeyset.NewHandle() err = %s, want err", err) } a2, err := aead.New(keysetHandle2) if err != nil { t.Errorf("aead.New failed: %s", err) } if err := validateAEADFactoryCipher(a2, a, cryptofmt.RawPrefix); err != nil { t.Errorf("invalid cipher: %s", err) } // encrypt with a random key not in the keyset, decrypt with the keyset should fail keyset2 = testutil.NewTestAESGCMKeyset(tinkpb.OutputPrefixType_TINK) primaryKey = keyset2.Key[0] expectedPrefix, err = cryptofmt.OutputPrefix(primaryKey) if err != nil { t.Errorf("cryptofmt.OutputPrefix() err = %s, want err", err) } keysetHandle2, err = testkeyset.NewHandle(keyset2) if err != nil { t.Fatalf("testkeyset.NewHandle() err = %s, want err", err) } a2, err = aead.New(keysetHandle2) if err != nil { t.Errorf("aead.New failed: %s", err) } err = validateAEADFactoryCipher(a2, a, expectedPrefix) if err == nil || !strings.Contains(err.Error(), "decryption failed") { t.Errorf("expect decryption to fail with random key: %s", err) } } func TestFactoryRawKeyAsPrimary(t *testing.T) { keyset := testutil.NewTestAESGCMKeyset(tinkpb.OutputPrefixType_RAW) if keyset.Key[0].OutputPrefixType != tinkpb.OutputPrefixType_RAW { t.Errorf("primary key is not a raw key") } keysetHandle, err := testkeyset.NewHandle(keyset) if err != nil { t.Fatalf("testkeyset.NewHandle() err = %s, want err", err) } a, err := aead.New(keysetHandle) if err != nil { t.Errorf("cannot get primitive from keyset handle: %s", err) } if err := validateAEADFactoryCipher(a, a, cryptofmt.RawPrefix); err != nil { t.Errorf("invalid cipher: %s", err) } } func validateAEADFactoryCipher(encryptCipher, decryptCipher tink.AEAD, expectedPrefix string) error { prefixSize := len(expectedPrefix) // regular plaintext pt := random.GetRandomBytes(20) ad := random.GetRandomBytes(20) ct, err := encryptCipher.Encrypt(pt, ad) if err != nil { return fmt.Errorf("encryption failed with regular plaintext: %s", err) } decrypted, err := decryptCipher.Decrypt(ct, ad) if err != nil || !bytes.Equal(decrypted, pt) { return fmt.Errorf("decryption failed with regular plaintext: err: %s, pt: %s, decrypted: %s", err, pt, decrypted) } if string(ct[:prefixSize]) != expectedPrefix { return fmt.Errorf("incorrect prefix with regular plaintext") } if prefixSize+len(pt)+subtle.AESGCMIVSize+subtle.AESGCMTagSize != len(ct) { return fmt.Errorf("lengths of plaintext and ciphertext don't match with regular plaintext") } // short plaintext pt = random.GetRandomBytes(1) ct, err = encryptCipher.Encrypt(pt, ad) if err != nil { return fmt.Errorf("encryption failed with short plaintext: %s", err) } decrypted, err = decryptCipher.Decrypt(ct, ad) if err != nil || !bytes.Equal(decrypted, pt) { return fmt.Errorf("decryption failed with short plaintext: err: %s, pt: %s, decrypted: %s", err, pt, decrypted) } if string(ct[:prefixSize]) != expectedPrefix { return fmt.Errorf("incorrect prefix with short plaintext") } if prefixSize+len(pt)+subtle.AESGCMIVSize+subtle.AESGCMTagSize != len(ct) { return fmt.Errorf("lengths of plaintext and ciphertext don't match with short plaintext") } return nil } func TestFactoryWithInvalidPrimitiveSetType(t *testing.T) { wrongKH, err := keyset.NewHandle(signature.ECDSAP256KeyTemplate()) if err != nil { t.Fatalf("failed to build *keyset.Handle: %s", err) } _, err = aead.New(wrongKH) if err == nil { t.Fatalf("calling New() with wrong *keyset.Handle should fail") } } func TestFactoryWithValidPrimitiveSetType(t *testing.T) { goodKH, err := keyset.NewHandle(aead.AES128GCMKeyTemplate()) if err != nil { t.Fatalf("failed to build *keyset.Handle: %s", err) } _, err = aead.New(goodKH) if err != nil { t.Fatalf("calling New() with good *keyset.Handle failed: %s", err) } } func TestPrimitiveFactoryWithMonitoringAnnotationsLogsEncryptionDecryptionWithPrefix(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } kh, err := keyset.NewHandle(aead.AES128GCMKeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } // Annotations are only supported throught the `insecurecleartextkeyset` API. buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } p, err := aead.New(mh) if err != nil { t.Fatalf("aead.New() err = %v, want nil", err) } data := []byte("HELLO_WORLD") ad := []byte("_!") ct, err := p.Encrypt(data, ad) if err != nil { t.Fatalf("p.Encrypt() err = %v, want nil", err) } if _, err := p.Decrypt(ct, ad); err != nil { t.Fatalf("p.Decrypt() err = %v, want nil", err) } failures := client.Failures() if len(failures) != 0 { t.Errorf("len(client.Failures()) = %d, want = 0", len(failures)) } got := client.Events() wantKeysetInfo := monitoring.NewKeysetInfo( annotations, kh.KeysetInfo().GetPrimaryKeyId(), []*monitoring.Entry{ { KeyID: kh.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.AesGcmKey", KeyPrefix: "TINK", }, }, ) want := []*fakemonitoring.LogEvent{ { KeyID: mh.KeysetInfo().GetPrimaryKeyId(), NumBytes: len(data), Context: monitoring.NewContext("aead", "encrypt", wantKeysetInfo), }, { KeyID: mh.KeysetInfo().GetPrimaryKeyId(), // ciphertext was encrypted with a key that has TINK ouput prefix. This adds a 5 bytes prefix // to the ciphertext. This prefix is not included in `Log` call. NumBytes: len(ct) - cryptofmt.NonRawPrefixSize, Context: monitoring.NewContext("aead", "decrypt", wantKeysetInfo), }, } if cmp.Diff(got, want) != "" { t.Errorf("%v", cmp.Diff(got, want)) } } func TestPrimitiveFactoryWithMonitoringAnnotationsLogsEncryptionDecryptionWithoutPrefix(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } kh, err := keyset.NewHandle(aead.AES256GCMNoPrefixKeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } // Annotations are only supported throught the `insecurecleartextkeyset` API. buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } p, err := aead.New(mh) if err != nil { t.Fatalf("aead.New() err = %v, want nil", err) } data := []byte("HELLO_WORLD") ct, err := p.Encrypt(data, nil) if err != nil { t.Fatalf("p.Encrypt() err = %v, want nil", err) } if _, err := p.Decrypt(ct, nil); err != nil { t.Fatalf("p.Decrypt() err = %v, want nil", err) } failures := client.Failures() if len(failures) != 0 { t.Errorf("len(client.Failures()) = %d, want = 0", len(failures)) } got := client.Events() wantKeysetInfo := monitoring.NewKeysetInfo( annotations, kh.KeysetInfo().GetPrimaryKeyId(), []*monitoring.Entry{ { KeyID: kh.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.AesGcmKey", KeyPrefix: "RAW", }, }, ) want := []*fakemonitoring.LogEvent{ { KeyID: mh.KeysetInfo().GetPrimaryKeyId(), NumBytes: len(data), Context: monitoring.NewContext("aead", "encrypt", wantKeysetInfo), }, { KeyID: mh.KeysetInfo().GetPrimaryKeyId(), NumBytes: len(ct), Context: monitoring.NewContext("aead", "decrypt", wantKeysetInfo), }, } if cmp.Diff(got, want) != "" { t.Errorf("%v", cmp.Diff(got, want)) } } func TestPrimitiveFactoryMonitoringWithAnnotatiosMultipleKeysLogsEncryptionDecryption(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("registry.RegisterMonitoringClient() err = %v, want nil", err) } manager := keyset.NewManager() keyTemplates := []*tinkpb.KeyTemplate{ aead.AES128GCMKeyTemplate(), aead.AES256GCMNoPrefixKeyTemplate(), aead.AES128CTRHMACSHA256KeyTemplate(), aead.XChaCha20Poly1305KeyTemplate(), } keyIDs := make([]uint32, len(keyTemplates), len(keyTemplates)) var err error for i, kt := range keyTemplates { keyIDs[i], err = manager.Add(kt) if err != nil { t.Fatalf("manager.Add(%v) err = %v, want nil", kt, err) } } if err := manager.SetPrimary(keyIDs[1]); err != nil { t.Fatalf("manager.SetPrimary(%d) err = %v, want nil", keyIDs[1], err) } if err := manager.Disable(keyIDs[0]); err != nil { t.Fatalf("manager.Disable(%d) err = %v, want nil", keyIDs[0], err) } kh, err := manager.Handle() if err != nil { t.Fatalf("manager.Handle() err = %v, want nil", err) } // Annotations are only supported throught the `insecurecleartextkeyset` API. buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } p, err := aead.New(mh) if err != nil { t.Fatalf("aead.New() err = %v, want nil", err) } failures := len(client.Failures()) if failures != 0 { t.Errorf("len(client.Failures()) = %d, want 0", failures) } data := []byte("YELLOW_ORANGE") ct, err := p.Encrypt(data, nil) if err != nil { t.Fatalf("p.Encrypt() err = %v, want nil", err) } if _, err := p.Decrypt(ct, nil); err != nil { t.Fatalf("p.Decrypt() err = %v, want nil", err) } got := client.Events() wantKeysetInfo := monitoring.NewKeysetInfo(annotations, keyIDs[1], []*monitoring.Entry{ { KeyID: keyIDs[1], Status: monitoring.Enabled, KeyType: "tink.AesGcmKey", KeyPrefix: "RAW", }, { KeyID: keyIDs[2], Status: monitoring.Enabled, KeyType: "tink.AesCtrHmacAeadKey", KeyPrefix: "TINK", }, { KeyID: keyIDs[3], Status: monitoring.Enabled, KeyType: "tink.XChaCha20Poly1305Key", KeyPrefix: "TINK", }, }) want := []*fakemonitoring.LogEvent{ { KeyID: keyIDs[1], NumBytes: len(data), Context: monitoring.NewContext( "aead", "encrypt", wantKeysetInfo, ), }, { KeyID: keyIDs[1], NumBytes: len(ct), Context: monitoring.NewContext( "aead", "decrypt", wantKeysetInfo, ), }, } // sort by keyID to avoid non deterministic order. entryLessFunc := func(a, b *monitoring.Entry) bool { return a.KeyID < b.KeyID } if !cmp.Equal(got, want, cmpopts.SortSlices(entryLessFunc)) { t.Errorf("got = %v, want = %v, with diff: %v", got, want, cmp.Diff(got, want)) } } func TestPrimitiveFactoryWithMonitoringAnnotationsEncryptionFailureIsLogged(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := &fakemonitoring.Client{Name: ""} if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } typeURL := "TestFactoryWithMonitoringPrimitiveEncryptionFailureIsLogged" template := &tinkpb.KeyTemplate{ TypeUrl: typeURL, OutputPrefixType: tinkpb.OutputPrefixType_LEGACY, } km := &stubkeymanager.StubKeyManager{ URL: typeURL, Key: &agpb.AesGcmKey{}, Prim: &testutil.AlwaysFailingAead{Error: errors.New("failed")}, KeyData: &tinkpb.KeyData{ TypeUrl: typeURL, KeyMaterialType: tinkpb.KeyData_SYMMETRIC, Value: []byte("serialized_key"), }, } if err := registry.RegisterKeyManager(km); err != nil { t.Fatalf("registry.RegisterKeyManager() err = %v, want nil", err) } kh, err := keyset.NewHandle(template) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } // Annotations are only supported throught the `insecurecleartextkeyset` API. buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } p, err := aead.New(mh) if err != nil { t.Fatalf("aead.New() err = %v, want nil", err) } if _, err := p.Encrypt(nil, nil); err == nil { t.Fatalf("Encrypt() err = nil, want error") } got := client.Failures() want := []*fakemonitoring.LogFailure{ { Context: monitoring.NewContext( "aead", "encrypt", monitoring.NewKeysetInfo( annotations, kh.KeysetInfo().GetPrimaryKeyId(), []*monitoring.Entry{ { KeyID: kh.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: typeURL, KeyPrefix: "LEGACY", }, }, ), ), }, } if cmp.Diff(got, want) != "" { t.Errorf("%v", cmp.Diff(got, want)) } } func TestPrimitiveFactoryWithMonitoringAnnotationsDecryptionFailureIsLogged(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } kh, err := keyset.NewHandle(aead.AES128GCMKeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } // Annotations are only supported throught the `insecurecleartextkeyset` API. buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } p, err := aead.New(mh) if err != nil { t.Fatalf("aead.New() err = %v, want nil", err) } if _, err := p.Decrypt([]byte("invalid_data"), nil); err == nil { t.Fatalf("Decrypt() err = nil, want error") } got := client.Failures() want := []*fakemonitoring.LogFailure{ { Context: monitoring.NewContext( "aead", "decrypt", monitoring.NewKeysetInfo( annotations, kh.KeysetInfo().GetPrimaryKeyId(), []*monitoring.Entry{ { KeyID: kh.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.AesGcmKey", KeyPrefix: "TINK", }, }, ), ), }, } if cmp.Diff(got, want) != "" { t.Errorf("%v", cmp.Diff(got, want)) } } func TestFactoryWithMonitoringMultiplePrimitivesLogOperations(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := &fakemonitoring.Client{Name: ""} if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } kh1, err := keyset.NewHandle(aead.AES128GCMKeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } // Annotations are only supported throught the `insecurecleartextkeyset` API. buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(kh1, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} mh1, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } p1, err := aead.New(mh1) if err != nil { t.Fatalf("aead.New() err = %v, want nil", err) } kh2, err := keyset.NewHandle(aead.AES128CTRHMACSHA256KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } buff.Reset() if err := insecurecleartextkeyset.Write(kh2, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } mh2, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } p2, err := aead.New(mh2) if err != nil { t.Fatalf("aead.New() err = %v, want nil", err) } d1 := []byte("YELLOW_ORANGE") if _, err := p1.Encrypt(d1, nil); err != nil { t.Fatalf("p1.Encrypt() err = %v, want nil", err) } d2 := []byte("ORANGE_BLUE") if _, err := p2.Encrypt(d2, nil); err != nil { t.Fatalf("p2.Encrypt() err = %v, want nil", err) } got := client.Events() want := []*fakemonitoring.LogEvent{ { KeyID: kh1.KeysetInfo().GetPrimaryKeyId(), NumBytes: len(d1), Context: monitoring.NewContext( "aead", "encrypt", monitoring.NewKeysetInfo( annotations, kh1.KeysetInfo().GetPrimaryKeyId(), []*monitoring.Entry{ { KeyID: kh1.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.AesGcmKey", KeyPrefix: "TINK", }, }, ), ), }, { KeyID: kh2.KeysetInfo().GetPrimaryKeyId(), NumBytes: len(d2), Context: monitoring.NewContext( "aead", "encrypt", monitoring.NewKeysetInfo( annotations, kh2.KeysetInfo().GetPrimaryKeyId(), []*monitoring.Entry{ { KeyID: kh2.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.AesCtrHmacAeadKey", KeyPrefix: "TINK", }, }, ), ), }, } if !cmp.Equal(got, want) { t.Errorf("got = %v, want = %v, with diff: %v", got, want, cmp.Diff(got, want)) } } func TestPrimitiveFactoryEncryptDecryptWithoutAnnotationsDoesNothing(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } kh, err := keyset.NewHandle(aead.AES128GCMKeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } p, err := aead.New(kh) if err != nil { t.Fatalf("aead.New() err = %v, want nil", err) } data := []byte("YELLOW_ORANGE") ct, err := p.Encrypt(data, nil) if err != nil { t.Fatalf("p.Encrypt() err = %v, want nil", err) } if _, err := p.Decrypt(ct, nil); err != nil { t.Fatalf("p.Decrypt() err = %v, want nil", err) } got := client.Events() if len(got) != 0 { t.Errorf("len(client.Events()) = %d, want 0", len(got)) } failures := len(client.Failures()) if failures != 0 { t.Errorf("len(client.Failures()) = %d, want 0", failures) } } ================================================ FILE: go/aead/aead_init_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead_test import ( "testing" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/testutil" ) func TestAEADInit(t *testing.T) { // Check that the AES-GCM key manager is in the global registry. _, err := registry.GetKeyManager(testutil.AESGCMTypeURL) if err != nil { t.Errorf("unexpected error: %s", err) } // Check that the ChaCha20Poly1305 key manager is in the global registry. _, err = registry.GetKeyManager(testutil.ChaCha20Poly1305TypeURL) if err != nil { t.Errorf("unexpected error: %s", err) } // Check that the XChaCha20Poly1305 key manager is in the global registry. _, err = registry.GetKeyManager(testutil.XChaCha20Poly1305TypeURL) if err != nil { t.Errorf("unexpected error: %s", err) } } ================================================ FILE: go/aead/aead_key_templates.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead import ( "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/internal/tinkerror" ctrpb "github.com/google/tink/go/proto/aes_ctr_go_proto" ctrhmacpb "github.com/google/tink/go/proto/aes_ctr_hmac_aead_go_proto" gcmpb "github.com/google/tink/go/proto/aes_gcm_go_proto" gcmsivpb "github.com/google/tink/go/proto/aes_gcm_siv_go_proto" commonpb "github.com/google/tink/go/proto/common_go_proto" hmacpb "github.com/google/tink/go/proto/hmac_go_proto" kmsenvpb "github.com/google/tink/go/proto/kms_envelope_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // This file contains pre-generated KeyTemplates for AEAD keys. One can use these templates // to generate new Keysets. // AES128GCMKeyTemplate is a KeyTemplate that generates an AES-GCM key with the following parameters: // - Key size: 16 bytes // - Output prefix type: TINK func AES128GCMKeyTemplate() *tinkpb.KeyTemplate { return createAESGCMKeyTemplate(16, tinkpb.OutputPrefixType_TINK) } // AES256GCMKeyTemplate is a KeyTemplate that generates an AES-GCM key with the following parameters: // - Key size: 32 bytes // - Output prefix type: TINK func AES256GCMKeyTemplate() *tinkpb.KeyTemplate { return createAESGCMKeyTemplate(32, tinkpb.OutputPrefixType_TINK) } // AES256GCMNoPrefixKeyTemplate is a KeyTemplate that generates an AES-GCM key with the following parameters: // - Key size: 32 bytes // - Output prefix type: RAW func AES256GCMNoPrefixKeyTemplate() *tinkpb.KeyTemplate { return createAESGCMKeyTemplate(32, tinkpb.OutputPrefixType_RAW) } // AES128GCMSIVKeyTemplate is a KeyTemplate that generates an AES-GCM-SIV key with the following parameters: // - Key size: 16 bytes // - Output prefix type: TINK func AES128GCMSIVKeyTemplate() *tinkpb.KeyTemplate { return createAESGCMSIVKeyTemplate(16, tinkpb.OutputPrefixType_TINK) } // AES256GCMSIVKeyTemplate is a KeyTemplate that generates an AES-GCM-SIV key with the following parameters: // - Key size: 32 bytes // - Output prefix type: TINK func AES256GCMSIVKeyTemplate() *tinkpb.KeyTemplate { return createAESGCMSIVKeyTemplate(32, tinkpb.OutputPrefixType_TINK) } // AES256GCMSIVNoPrefixKeyTemplate is a KeyTemplate that generates an AES-GCM key with the following parameters: // - Key size: 32 bytes // - Output prefix type: RAW func AES256GCMSIVNoPrefixKeyTemplate() *tinkpb.KeyTemplate { return createAESGCMSIVKeyTemplate(32, tinkpb.OutputPrefixType_RAW) } // AES128CTRHMACSHA256KeyTemplate is a KeyTemplate that generates an AES-CTR-HMAC-AEAD key with the following parameters: // - AES key size: 16 bytes // - AES CTR IV size: 16 bytes // - HMAC key size: 32 bytes // - HMAC tag size: 16 bytes // - HMAC hash function: SHA256 func AES128CTRHMACSHA256KeyTemplate() *tinkpb.KeyTemplate { return createAESCTRHMACAEADKeyTemplate(16, 16, 32, 16, commonpb.HashType_SHA256) } // AES256CTRHMACSHA256KeyTemplate is a KeyTemplate that generates an AES-CTR-HMAC-AEAD key with the following parameters: // - AES key size: 32 bytes // - AES CTR IV size: 16 bytes // - HMAC key size: 32 bytes // - HMAC tag size: 32 bytes // - HMAC hash function: SHA256 func AES256CTRHMACSHA256KeyTemplate() *tinkpb.KeyTemplate { return createAESCTRHMACAEADKeyTemplate(32, 16, 32, 32, commonpb.HashType_SHA256) } // ChaCha20Poly1305KeyTemplate is a KeyTemplate that generates a CHACHA20_POLY1305 key. func ChaCha20Poly1305KeyTemplate() *tinkpb.KeyTemplate { return &tinkpb.KeyTemplate{ // Don't set value because KeyFormat is not required. TypeUrl: chaCha20Poly1305TypeURL, OutputPrefixType: tinkpb.OutputPrefixType_TINK, } } // XChaCha20Poly1305KeyTemplate is a KeyTemplate that generates a XCHACHA20_POLY1305 key. func XChaCha20Poly1305KeyTemplate() *tinkpb.KeyTemplate { return &tinkpb.KeyTemplate{ // Don't set value because KeyFormat is not required. TypeUrl: xChaCha20Poly1305TypeURL, OutputPrefixType: tinkpb.OutputPrefixType_TINK, } } // CreateKMSEnvelopeAEADKeyTemplate returns a key template that generates a // KMSEnvelopeAEAD key for a given key encryption key (KEK) in a remote key // management service (KMS). // // When performing encrypt operations, a data encryption key (DEK) is generated // for each ciphertext. The DEK is wrapped by the remote KMS using the KEK and // stored alongside the ciphertext. // // dekTemplate must be a KeyTemplate for any of these Tink AEAD key types (any // other key template will be rejected): // - AesCtrHmacAeadKey // - AesGcmKey // - ChaCha20Poly1305Key // - XChaCha20Poly1305 // - AesGcmSivKey // // DEKs generated by this key template use the RAW output prefix to make them // compatible with remote KMS encrypt/decrypt operations. // // Unlike other templates, when you generate new keys with this template, Tink // does not generate new key material, but only creates a reference to the // remote KEK. // // If either uri or dekTemplate contain invalid input, an error is returned. // // It is often not necessary to use this function. Instead, you can call // kmsClient.GetAEAD to get a remote AEAD, and create an envelope AEAD using // [NewKMSEnvelopeAEAD2]. // // There is no need to call registry.RegisterKMSClient anymore. func CreateKMSEnvelopeAEADKeyTemplate(uri string, dekTemplate *tinkpb.KeyTemplate) (*tinkpb.KeyTemplate, error) { if !isSupporedKMSEnvelopeDEK(dekTemplate.GetTypeUrl()) { return nil, fmt.Errorf("unsupported DEK key type %s. Only Tink AEAD key types are supported", dekTemplate.GetTypeUrl()) } f := &kmsenvpb.KmsEnvelopeAeadKeyFormat{ KekUri: uri, DekTemplate: dekTemplate, } serializedFormat, err := proto.Marshal(f) if err != nil { return nil, fmt.Errorf("failed to marshal key format: %s", err) } return &tinkpb.KeyTemplate{ Value: serializedFormat, TypeUrl: kmsEnvelopeAEADTypeURL, OutputPrefixType: tinkpb.OutputPrefixType_RAW, }, nil } // KMSEnvelopeAEADKeyTemplate returns a KeyTemplate that generates a // KMSEnvelopeAEAD key for a given key encryption key (KEK) in a remote key // management service (KMS). // // If either uri or dekTemplate contain invalid input, program execution will // be interrupted. // // Deprecated: Use [CreateKMSEnvelopeAEADKeyTemplate], which returns an error // value instead of interrupting the program. func KMSEnvelopeAEADKeyTemplate(uri string, dekTemplate *tinkpb.KeyTemplate) *tinkpb.KeyTemplate { t, err := CreateKMSEnvelopeAEADKeyTemplate(uri, dekTemplate) if err != nil { tinkerror.Fail(err.Error()) } return t } // createAESGCMKeyTemplate creates a new AES-GCM key template with the given key // size in bytes. func createAESGCMKeyTemplate(keySize uint32, outputPrefixType tinkpb.OutputPrefixType) *tinkpb.KeyTemplate { format := &gcmpb.AesGcmKeyFormat{ KeySize: keySize, } serializedFormat, err := proto.Marshal(format) if err != nil { tinkerror.Fail(fmt.Sprintf("failed to marshal key format: %s", err)) } return &tinkpb.KeyTemplate{ TypeUrl: aesGCMTypeURL, Value: serializedFormat, OutputPrefixType: outputPrefixType, } } // createAESGCMSIVKeyTemplate creates a new AES-GCM-SIV key template with the given key // size in bytes. func createAESGCMSIVKeyTemplate(keySize uint32, outputPrefixType tinkpb.OutputPrefixType) *tinkpb.KeyTemplate { format := &gcmsivpb.AesGcmSivKeyFormat{ KeySize: keySize, } serializedFormat, err := proto.Marshal(format) if err != nil { tinkerror.Fail(fmt.Sprintf("failed to marshal key format: %s", err)) } return &tinkpb.KeyTemplate{ TypeUrl: aesGCMSIVTypeURL, Value: serializedFormat, OutputPrefixType: outputPrefixType, } } func createAESCTRHMACAEADKeyTemplate(aesKeySize, ivSize, hmacKeySize, tagSize uint32, hash commonpb.HashType) *tinkpb.KeyTemplate { format := &ctrhmacpb.AesCtrHmacAeadKeyFormat{ AesCtrKeyFormat: &ctrpb.AesCtrKeyFormat{ Params: &ctrpb.AesCtrParams{IvSize: ivSize}, KeySize: aesKeySize, }, HmacKeyFormat: &hmacpb.HmacKeyFormat{ Params: &hmacpb.HmacParams{Hash: hash, TagSize: tagSize}, KeySize: hmacKeySize, }, } serializedFormat, err := proto.Marshal(format) if err != nil { tinkerror.Fail(fmt.Sprintf("failed to marshal key format: %s", err)) } return &tinkpb.KeyTemplate{ Value: serializedFormat, TypeUrl: aesCTRHMACAEADTypeURL, OutputPrefixType: tinkpb.OutputPrefixType_TINK, } } ================================================ FILE: go/aead/aead_key_templates_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead_test import ( "bytes" "fmt" "testing" "github.com/google/tink/go/aead" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/tinkerror/tinkerrortest" "github.com/google/tink/go/keyset" "github.com/google/tink/go/mac" "github.com/google/tink/go/testing/fakekms" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestKeyTemplates(t *testing.T) { var testCases = []struct { name string template *tinkpb.KeyTemplate }{ { name: "AES128_GCM", template: aead.AES128GCMKeyTemplate(), }, { name: "AES256_GCM", template: aead.AES256GCMKeyTemplate(), }, { name: "AES256_GCM_NO_PREFIX", template: aead.AES256GCMNoPrefixKeyTemplate(), }, { name: "AES128_GCM_SIV", template: aead.AES128GCMSIVKeyTemplate(), }, { name: "AES256_GCM_SIV", template: aead.AES256GCMSIVKeyTemplate(), }, { name: "AES256_GCM_SIV_NO_PREFIX", template: aead.AES256GCMSIVNoPrefixKeyTemplate(), }, { name: "AES128_CTR_HMAC_SHA256", template: aead.AES128CTRHMACSHA256KeyTemplate(), }, { name: "AES256_CTR_HMAC_SHA256", template: aead.AES256CTRHMACSHA256KeyTemplate(), }, { name: "CHACHA20_POLY1305", template: aead.ChaCha20Poly1305KeyTemplate(), }, { name: "XCHACHA20_POLY1305", template: aead.XChaCha20Poly1305KeyTemplate(), }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { if err := testEncryptDecrypt(tc.template); err != nil { t.Errorf("%v", err) } }) } } func TestKMSEnvelopeAEADKeyTemplate(t *testing.T) { fakeKmsClient, err := fakekms.NewClient("fake-kms://") if err != nil { t.Fatalf("fakekms.NewClient('fake-kms://') failed: %v", err) } registry.RegisterKMSClient(fakeKmsClient) fixedKeyURI := "fake-kms://CM2b3_MDElQKSAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuQWVzR2NtS2V5EhIaEIK75t5L-adlUwVhWvRuWUwYARABGM2b3_MDIAE" newKeyURI, err := fakekms.NewKeyURI() if err != nil { t.Fatalf("fakekms.NewKeyURI() failed: %v", err) } fixedKeyTemplate, err := aead.CreateKMSEnvelopeAEADKeyTemplate(fixedKeyURI, aead.AES128GCMKeyTemplate()) if err != nil { t.Fatalf("CreateKMSEnvelopeAEADKeyTemplate() err = %v", err) } newKeyTemplate, err := aead.CreateKMSEnvelopeAEADKeyTemplate(newKeyURI, aead.AES128GCMKeyTemplate()) if err != nil { t.Fatalf("CreateKMSEnvelopeAEADKeyTemplate() err = %v", err) } var testCases = []struct { name string template *tinkpb.KeyTemplate }{ { name: "Fixed Fake KMS Envelope AEAD Key with AES128_GCM", template: fixedKeyTemplate, }, { name: "New Fake KMS Envelope AEAD Key with AES128_GCM", template: newKeyTemplate, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { if tc.template.GetOutputPrefixType() != tinkpb.OutputPrefixType_RAW { t.Errorf("KMS envelope template %s does not use RAW prefix, found '%s'", tc.name, tc.template.GetOutputPrefixType()) } if err := testEncryptDecrypt(tc.template); err != nil { t.Errorf("%v", err) } }) } } // Tests that two KMSEnvelopeAEAD keys that use the same KEK and DEK template // should be able to decrypt each other's ciphertexts. func TestKMSEnvelopeAEADKeyTemplateMultipleKeysSameKEK(t *testing.T) { fakeKmsClient, err := fakekms.NewClient("fake-kms://") if err != nil { t.Fatalf("fakekms.NewClient('fake-kms://') failed: %v", err) } registry.RegisterKMSClient(fakeKmsClient) fixedKeyURI := "fake-kms://CM2b3_MDElQKSAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuQWVzR2NtS2V5EhIaEIK75t5L-adlUwVhWvRuWUwYARABGM2b3_MDIAE" template1, err := aead.CreateKMSEnvelopeAEADKeyTemplate(fixedKeyURI, aead.AES128GCMKeyTemplate()) if err != nil { t.Fatalf("CreateKMSEnvelopeAEADKeyTemplate() err = %v", err) } template2, err := aead.CreateKMSEnvelopeAEADKeyTemplate(fixedKeyURI, aead.AES128GCMKeyTemplate()) if err != nil { t.Fatalf("CreateKMSEnvelopeAEADKeyTemplate() err = %v", err) } handle1, err := keyset.NewHandle(template1) if err != nil { t.Fatalf("keyset.NewHandle(template1) failed: %v", err) } aead1, err := aead.New(handle1) if err != nil { t.Fatalf("aead.New(handle) failed: %v", err) } handle2, err := keyset.NewHandle(template2) if err != nil { t.Fatalf("keyset.NewHandle(template2) failed: %v", err) } aead2, err := aead.New(handle2) if err != nil { t.Fatalf("aead.New(handle) failed: %v", err) } plaintext := []byte("some data to encrypt") aad := []byte("extra data to authenticate") ciphertext, err := aead1.Encrypt(plaintext, aad) if err != nil { t.Fatalf("encryption failed, error: %v", err) } decrypted, err := aead2.Decrypt(ciphertext, aad) if err != nil { t.Fatalf("decryption failed, error: %v", err) } if !bytes.Equal(plaintext, decrypted) { t.Fatalf("decrypted data doesn't match plaintext, got: %q, want: %q", decrypted, plaintext) } } // This test shows how migrate away from CreateKMSEnvelopeAEADKeyTemplate. func TestMigrateFromCreateKMSEnvelopeAEADKeyTemplateToNewKMSEnvelopeAEAD2(t *testing.T) { kmsClient, err := fakekms.NewClient("fake-kms://") if err != nil { t.Fatalf("fakekms.NewClient('fake-kms://') failed: %v", err) } kekURI := "fake-kms://CM2b3_MDElQKSAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuQWVzR2NtS2V5EhIaEIK75t5L-adlUwVhWvRuWUwYARABGM2b3_MDIAE" // This code: registry.RegisterKMSClient(kmsClient) kmsEnvelopeAEADTemplate, err := aead.CreateKMSEnvelopeAEADKeyTemplate(kekURI, aead.AES128GCMKeyTemplate()) if err != nil { t.Fatalf("CreateKMSEnvelopeAEADKeyTemplate() failed: %v", err) } handle, err := keyset.NewHandle(kmsEnvelopeAEADTemplate) if err != nil { t.Fatalf("keyset.NewHandle(kmsEnvelopeAEADTemplate) failed: %v", err) } aead1, err := aead.New(handle) if err != nil { t.Fatalf("aead.New(handle) failed: %v", err) } // can be replace by this: kekAEAD, err := kmsClient.GetAEAD(kekURI) if err != nil { t.Fatalf("kmsClient.GetAEAD(kekURI) failed: %v", err) } aead2 := aead.NewKMSEnvelopeAEAD2(aead.AES128GCMKeyTemplate(), kekAEAD) // Check that aead1 and aead2 are compatible. plaintext := []byte("plaintext") associatedData := []byte("associatedData") ciphertext, err := aead1.Encrypt(plaintext, associatedData) if err != nil { t.Fatalf("aead1.Encrypt(plaintext, associatedData) failed: %v", err) } decrypted, err := aead2.Decrypt(ciphertext, associatedData) if err != nil { t.Fatalf("aead2.Decrypt(ciphertext, associatedData) failed: %v", err) } if !bytes.Equal(plaintext, decrypted) { t.Fatalf("decrypted data doesn't match plaintext, got: %q, want: %q", decrypted, plaintext) } } // Testing deprecated function, ignoring GoDeprecated. func TestCreateKMSEnvelopeAEADKeyTemplateCompatibleWithKMSEnevelopeAEADKeyTemplate(t *testing.T) { fakeKmsClient, err := fakekms.NewClient("fake-kms://") if err != nil { t.Fatalf("fakekms.NewClient('fake-kms://') failed: %v", err) } registry.RegisterKMSClient(fakeKmsClient) fixedKeyURI := "fake-kms://CM2b3_MDElQKSAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuQWVzR2NtS2V5EhIaEIK75t5L-adlUwVhWvRuWUwYARABGM2b3_MDIAE" template1, err := aead.CreateKMSEnvelopeAEADKeyTemplate(fixedKeyURI, aead.AES128GCMKeyTemplate()) if err != nil { t.Fatalf("CreateKMSEnvelopeAEADKeyTemplate() err = %v", err) } template2 := aead.KMSEnvelopeAEADKeyTemplate(fixedKeyURI, aead.AES128GCMKeyTemplate()) handle1, err := keyset.NewHandle(template1) if err != nil { t.Fatalf("keyset.NewHandle(template1) failed: %v", err) } aead1, err := aead.New(handle1) if err != nil { t.Fatalf("aead.New(handle) failed: %v", err) } handle2, err := keyset.NewHandle(template2) if err != nil { t.Fatalf("keyset.NewHandle(template2) failed: %v", err) } aead2, err := aead.New(handle2) if err != nil { t.Fatalf("aead.New(handle) failed: %v", err) } plaintext := []byte("some data to encrypt") aad := []byte("extra data to authenticate") ciphertext, err := aead1.Encrypt(plaintext, aad) if err != nil { t.Fatalf("encryption failed, error: %v", err) } decrypted, err := aead2.Decrypt(ciphertext, aad) if err != nil { t.Fatalf("decryption failed, error: %v", err) } if !bytes.Equal(plaintext, decrypted) { t.Fatalf("decrypted data doesn't match plaintext, got: %q, want: %q", decrypted, plaintext) } } // Testing deprecated function, ignoring GoDeprecated. func TestKMSEnvelopeAEADKeyTemplateFails(t *testing.T) { keyURI, err := fakekms.NewKeyURI() if err != nil { t.Fatalf("fakekms.NewKeyURI() err = %v", err) } invalidTemplate := &tinkpb.KeyTemplate{ // String fields cannot contain invalid UTF-8 characters. TypeUrl: "\xff", } var template *tinkpb.KeyTemplate err = tinkerrortest.RecoverFromFail(func() { template = aead.KMSEnvelopeAEADKeyTemplate(keyURI, invalidTemplate) }) if err == nil { t.Errorf("aead.KMSEnvelopAEADKeyTemplate() err = nil, want non-nil") } t.Logf("template: %+v", template) } func TestCreateKMSEnvelopeAEADKeyTemplateFails(t *testing.T) { keyURI, err := fakekms.NewKeyURI() if err != nil { t.Fatalf("fakekms.NewKeyURI() err = %v", err) } invalidTemplate := &tinkpb.KeyTemplate{ // String fields cannot contain invalid UTF-8 characters. TypeUrl: "\xff", } if _, err := aead.CreateKMSEnvelopeAEADKeyTemplate(keyURI, invalidTemplate); err == nil { t.Errorf("aead.CreateKMSEnvelopAEADKeyTemplate(keyURI, invalidTemplate) err = nil, want non-nil") } } func TestCreateKMSEnvelopeAEADKeyTemplateWithUnsupportedTemplateFails(t *testing.T) { keyURI, err := fakekms.NewKeyURI() if err != nil { t.Fatalf("fakekms.NewKeyURI() err = %v", err) } unsupportedTemplate := mac.HMACSHA256Tag128KeyTemplate() if _, err := aead.CreateKMSEnvelopeAEADKeyTemplate(keyURI, unsupportedTemplate); err == nil { t.Errorf("aead.CreateKMSEnvelopAEADKeyTemplate(keyURI, unsupportedTemplate) err = nil, want non-nil") } } func testEncryptDecrypt(template *tinkpb.KeyTemplate) error { handle, err := keyset.NewHandle(template) if err != nil { return fmt.Errorf("keyset.NewHandle(template) failed: %v", err) } primitive, err := aead.New(handle) if err != nil { return fmt.Errorf("aead.New(handle) failed: %v", err) } var testInputs = []struct { plaintext []byte aad1 []byte aad2 []byte }{ { plaintext: []byte("some data to encrypt"), aad1: []byte("extra data to authenticate"), aad2: []byte("extra data to authenticate"), }, { plaintext: []byte("some data to encrypt"), aad1: []byte(""), aad2: []byte(""), }, { plaintext: []byte("some data to encrypt"), aad1: nil, aad2: nil, }, { plaintext: []byte(""), aad1: nil, aad2: nil, }, { plaintext: nil, aad1: []byte("extra data to authenticate"), aad2: []byte("extra data to authenticate"), }, { plaintext: nil, aad1: []byte(""), aad2: []byte(""), }, { plaintext: nil, aad1: nil, aad2: nil, }, { plaintext: []byte("some data to encrypt"), aad1: []byte(""), aad2: nil, }, { plaintext: []byte("some data to encrypt"), aad1: nil, aad2: []byte(""), }, } for _, ti := range testInputs { ciphertext, err := primitive.Encrypt(ti.plaintext, ti.aad1) if err != nil { return fmt.Errorf("encryption failed, error: %v", err) } decrypted, err := primitive.Decrypt(ciphertext, ti.aad2) if err != nil { return fmt.Errorf("decryption failed, error: %v", err) } if !bytes.Equal(ti.plaintext, decrypted) { return fmt.Errorf("decrypted data doesn't match plaintext, got: %q, want: %q", decrypted, ti.plaintext) } } return nil } ================================================ FILE: go/aead/aead_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead_test // [START aead-example] import ( "bytes" "fmt" "log" "github.com/google/tink/go/aead" "github.com/google/tink/go/insecurecleartextkeyset" "github.com/google/tink/go/keyset" ) func Example() { // A keyset created with "tinkey create-keyset --key-template=AES256_GCM". Note // that this keyset has the secret key information in cleartext. jsonKeyset := `{ "key": [{ "keyData": { "keyMaterialType": "SYMMETRIC", "typeUrl": "type.googleapis.com/google.crypto.tink.AesGcmKey", "value": "GiBWyUfGgYk3RTRhj/LIUzSudIWlyjCftCOypTr0jCNSLg==" }, "keyId": 294406504, "outputPrefixType": "TINK", "status": "ENABLED" }], "primaryKeyId": 294406504 }` // Create a keyset handle from the cleartext keyset in the previous // step. The keyset handle provides abstract access to the underlying keyset to // limit the exposure of accessing the raw key material. WARNING: In practice, // it is unlikely you will want to use a insecurecleartextkeyset, as it implies // that your key material is passed in cleartext, which is a security risk. // Consider encrypting it with a remote key in Cloud KMS, AWS KMS or HashiCorp Vault. // See https://github.com/google/tink/blob/master/docs/GOLANG-HOWTO.md#storing-and-loading-existing-keysets. keysetHandle, err := insecurecleartextkeyset.Read( keyset.NewJSONReader(bytes.NewBufferString(jsonKeyset))) if err != nil { log.Fatal(err) } // Retrieve the AEAD primitive we want to use from the keyset handle. primitive, err := aead.New(keysetHandle) if err != nil { log.Fatal(err) } // Use the primitive to encrypt a message. In this case the primary key of the // keyset will be used (which is also the only key in this example). plaintext := []byte("message") associatedData := []byte("associated data") ciphertext, err := primitive.Encrypt(plaintext, associatedData) if err != nil { log.Fatal(err) } // Use the primitive to decrypt the message. Decrypt finds the correct key in // the keyset and decrypts the ciphertext. If no key is found or decryption // fails, it returns an error. decrypted, err := primitive.Decrypt(ciphertext, associatedData) if err != nil { log.Fatal(err) } fmt.Println(string(decrypted)) // Output: message } // [END aead-example] ================================================ FILE: go/aead/aes_ctr_hmac_aead_key_manager.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead import ( "errors" "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/aead/subtle" "github.com/google/tink/go/keyset" subtleMac "github.com/google/tink/go/mac/subtle" "github.com/google/tink/go/subtle/random" ctrpb "github.com/google/tink/go/proto/aes_ctr_go_proto" aeadpb "github.com/google/tink/go/proto/aes_ctr_hmac_aead_go_proto" commonpb "github.com/google/tink/go/proto/common_go_proto" hmacpb "github.com/google/tink/go/proto/hmac_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( aesCTRHMACAEADKeyVersion = 0 aesCTRHMACAEADTypeURL = "type.googleapis.com/google.crypto.tink.AesCtrHmacAeadKey" minHMACKeySizeInBytes = 16 minTagSizeInBytes = 10 ) // common errors var errInvalidAESCTRHMACAEADKey = fmt.Errorf("aes_ctr_hmac_aead_key_manager: invalid key") var errInvalidAESCTRHMACAEADKeyFormat = fmt.Errorf("aes_ctr_hmac_aead_key_manager: invalid key format") // aesCTRHMACAEADKeyManager is an implementation of KeyManager interface. // It generates new AESCTRHMACAEADKey keys and produces new instances of EncryptThenAuthenticate subtle. type aesCTRHMACAEADKeyManager struct{} // Primitive creates an AEAD for the given serialized AESCTRHMACAEADKey proto. func (km *aesCTRHMACAEADKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidAESCTRHMACAEADKey } key := new(aeadpb.AesCtrHmacAeadKey) if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errInvalidAESCTRHMACAEADKey } if err := km.validateKey(key); err != nil { return nil, err } ctr, err := subtle.NewAESCTR(key.GetAesCtrKey().GetKeyValue(), int(key.GetAesCtrKey().GetParams().GetIvSize())) if err != nil { return nil, fmt.Errorf("aes_ctr_hmac_aead_key_manager: cannot create new primitive: %v", err) } hmacKey := key.GetHmacKey() hmac, err := subtleMac.NewHMAC(hmacKey.GetParams().GetHash().String(), hmacKey.GetKeyValue(), hmacKey.GetParams().GetTagSize()) if err != nil { return nil, fmt.Errorf("aes_ctr_hmac_aead_key_manager: cannot create mac primitive, error: %v", err) } aead, err := subtle.NewEncryptThenAuthenticate(ctr, hmac, int(hmacKey.GetParams().GetTagSize())) if err != nil { return nil, fmt.Errorf("aes_ctr_hmac_aead_key_manager: cannot create encrypt then authenticate primitive, error: %v", err) } return aead, nil } // NewKey creates a new key according to the given serialized AesCtrHmacAeadKeyFormat. func (km *aesCTRHMACAEADKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errInvalidAESCTRHMACAEADKeyFormat } keyFormat := new(aeadpb.AesCtrHmacAeadKeyFormat) if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, errInvalidAESCTRHMACAEADKeyFormat } if err := km.validateKeyFormat(keyFormat); err != nil { return nil, fmt.Errorf("aes_ctr_hmac_aead_key_manager: invalid key format: %v", err) } return &aeadpb.AesCtrHmacAeadKey{ Version: aesCTRHMACAEADKeyVersion, AesCtrKey: &ctrpb.AesCtrKey{ Version: aesCTRHMACAEADKeyVersion, KeyValue: random.GetRandomBytes(keyFormat.GetAesCtrKeyFormat().GetKeySize()), Params: keyFormat.GetAesCtrKeyFormat().GetParams(), }, HmacKey: &hmacpb.HmacKey{ Version: aesCTRHMACAEADKeyVersion, KeyValue: random.GetRandomBytes(keyFormat.GetHmacKeyFormat().GetKeySize()), Params: keyFormat.GetHmacKeyFormat().GetParams(), }, }, nil } // NewKeyData creates a new KeyData according to specification in the given serialized // AesCtrHmacAeadKeyFormat. // It should be used solely by the key management API. func (km *aesCTRHMACAEADKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { key, err := km.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: km.TypeURL(), Value: serializedKey, KeyMaterialType: tinkpb.KeyData_SYMMETRIC, }, nil } // DoesSupport indicates if this key manager supports the given key type. func (km *aesCTRHMACAEADKeyManager) DoesSupport(typeURL string) bool { return typeURL == aesCTRHMACAEADTypeURL } // TypeURL returns the key type of keys managed by this key manager. func (km *aesCTRHMACAEADKeyManager) TypeURL() string { return aesCTRHMACAEADTypeURL } // validateKey validates the given AesCtrHmacAeadKey proto. func (km *aesCTRHMACAEADKeyManager) validateKey(key *aeadpb.AesCtrHmacAeadKey) error { if err := keyset.ValidateKeyVersion(key.GetVersion(), aesCTRHMACAEADKeyVersion); err != nil { return fmt.Errorf("aes_ctr_hmac_aead_key_manager: %v", err) } if err := keyset.ValidateKeyVersion(key.GetAesCtrKey().GetVersion(), aesCTRHMACAEADKeyVersion); err != nil { return fmt.Errorf("aes_ctr_hmac_aead_key_manager: %v", err) } if err := keyset.ValidateKeyVersion(key.GetHmacKey().GetVersion(), aesCTRHMACAEADKeyVersion); err != nil { return fmt.Errorf("aes_ctr_hmac_aead_key_manager: %v", err) } // Validate AesCtrKey. keySize := uint32(len(key.GetAesCtrKey().GetKeyValue())) if err := subtle.ValidateAESKeySize(keySize); err != nil { return fmt.Errorf("aes_ctr_hmac_aead_key_manager: %v", err) } params := key.GetAesCtrKey().GetParams() if params.GetIvSize() < subtle.AESCTRMinIVSize || params.GetIvSize() > 16 { return errors.New("aes_ctr_hmac_aead_key_manager: invalid AesCtrHmacAeadKey: IV size out of range") } return nil } // validateKeyFormat validates the given AesCtrHmacAeadKeyFormat proto. func (km *aesCTRHMACAEADKeyManager) validateKeyFormat(format *aeadpb.AesCtrHmacAeadKeyFormat) error { // Validate AesCtrKeyFormat. if err := subtle.ValidateAESKeySize(format.GetAesCtrKeyFormat().GetKeySize()); err != nil { return fmt.Errorf("aes_ctr_hmac_aead_key_manager: %s", err) } if format.GetAesCtrKeyFormat().GetParams().GetIvSize() < subtle.AESCTRMinIVSize || format.GetAesCtrKeyFormat().GetParams().GetIvSize() > 16 { return errors.New("aes_ctr_hmac_aead_key_manager: invalid AesCtrHmacAeadKeyFormat: IV size out of range") } // Validate HmacKeyFormat. hmacKeyFormat := format.GetHmacKeyFormat() if hmacKeyFormat.GetKeySize() < minHMACKeySizeInBytes { return errors.New("aes_ctr_hmac_aead_key_manager: HMAC KeySize is too small") } if hmacKeyFormat.GetParams().GetTagSize() < minTagSizeInBytes { return fmt.Errorf("aes_ctr_hmac_aead_key_manager: invalid HmacParams: TagSize %d is too small", hmacKeyFormat.GetParams().GetTagSize()) } maxTagSizes := map[commonpb.HashType]uint32{ commonpb.HashType_SHA1: 20, commonpb.HashType_SHA224: 28, commonpb.HashType_SHA256: 32, commonpb.HashType_SHA384: 48, commonpb.HashType_SHA512: 64} maxTagSize, ok := maxTagSizes[hmacKeyFormat.GetParams().GetHash()] if !ok { return fmt.Errorf("aes_ctr_hmac_aead_key_manager: invalid HmacParams: HashType %q not supported", hmacKeyFormat.GetParams().GetHash()) } if hmacKeyFormat.GetParams().GetTagSize() > maxTagSize { return fmt.Errorf("aes_ctr_hmac_aead_key_manager: invalid HmacParams: tagSize %d is too big for HashType %q", hmacKeyFormat.GetParams().GetTagSize(), hmacKeyFormat.GetParams().GetHash()) } return nil } ================================================ FILE: go/aead/aes_ctr_hmac_aead_key_manager_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead_test import ( "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/aead" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/testutil" ctrpb "github.com/google/tink/go/proto/aes_ctr_go_proto" aeadpb "github.com/google/tink/go/proto/aes_ctr_hmac_aead_go_proto" ctrhmacpb "github.com/google/tink/go/proto/aes_ctr_hmac_aead_go_proto" commonpb "github.com/google/tink/go/proto/common_go_proto" hmacpb "github.com/google/tink/go/proto/hmac_go_proto" ) func TestAESCTRHMACNewKeyMultipleTimes(t *testing.T) { keyTemplate := aead.AES128CTRHMACSHA256KeyTemplate() aeadKeyFormat := new(ctrhmacpb.AesCtrHmacAeadKeyFormat) if err := proto.Unmarshal(keyTemplate.Value, aeadKeyFormat); err != nil { t.Fatalf("cannot unmarshal AES128CTRHMACSHA256 key template") } keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACAEADTypeURL) if err != nil { t.Errorf("cannot obtain AES-CTR-HMAC-AEAD key manager: %s", err) } keys := make(map[string]bool) const numTests = 24 for i := 0; i < numTests/2; i++ { k, err := keyManager.NewKey(keyTemplate.Value) if err != nil { t.Fatalf("keyManager.NewKey() err = %q, want nil", err) } sk, err := proto.Marshal(k) if err != nil { t.Fatalf("cannot serialize key, error: %v", err) } key := new(ctrhmacpb.AesCtrHmacAeadKey) proto.Unmarshal(sk, key) keys[string(key.AesCtrKey.KeyValue)] = true keys[string(key.HmacKey.KeyValue)] = true if len(key.AesCtrKey.KeyValue) != 16 { t.Errorf("unexpected AES key size, got: %d, want: 16", len(key.AesCtrKey.KeyValue)) } if len(key.HmacKey.KeyValue) != 32 { t.Errorf("unexpected HMAC key size, got: %d, want: 32", len(key.HmacKey.KeyValue)) } } if len(keys) != numTests { t.Errorf("unexpected number of keys in set, got: %d, want: %d", len(keys), numTests) } } func TestAESCTRHMACNewKeyWithInvalidSerializedKeyFormat(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACAEADTypeURL) if err != nil { t.Errorf("cannot obtain AES-CTR-HMAC-AEAD key manager: %s", err) } testcases := []struct { name string serializedKeyFormat []byte keyFormat *ctrhmacpb.AesCtrHmacAeadKeyFormat }{ { name: "empty", serializedKeyFormat: make([]byte, 128), }, { name: "params_unset", keyFormat: &ctrhmacpb.AesCtrHmacAeadKeyFormat{ AesCtrKeyFormat: &ctrpb.AesCtrKeyFormat{ Params: nil, KeySize: 32, }, HmacKeyFormat: &hmacpb.HmacKeyFormat{ Params: nil, KeySize: 32, }, }, }, { name: "nested_key_formats_unset", keyFormat: &ctrhmacpb.AesCtrHmacAeadKeyFormat{ AesCtrKeyFormat: nil, HmacKeyFormat: nil, }, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { serializedKeyFormat := tc.serializedKeyFormat if serializedKeyFormat == nil { var err error serializedKeyFormat, err = proto.Marshal(tc.keyFormat) if err != nil { t.Fatalf("failed to marshal key format: %s", err) } } _, err = keyManager.NewKey(serializedKeyFormat) if err == nil { t.Error("NewKey() err = nil, want not error") } _, err = keyManager.NewKeyData(serializedKeyFormat) if err == nil { t.Error("NewKeyData() err = nil, want error") } }) } } func TestAESCTRHMACPrimitive(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACAEADTypeURL) if err != nil { t.Errorf("cannot obtain AES-CTR-HMAC-AEAD key manager: %s", err) } key := &aeadpb.AesCtrHmacAeadKey{ Version: 0, AesCtrKey: &ctrpb.AesCtrKey{ Version: 0, KeyValue: make([]byte, 32), Params: &ctrpb.AesCtrParams{IvSize: 16}, }, HmacKey: &hmacpb.HmacKey{ Version: 0, KeyValue: make([]byte, 32), Params: &hmacpb.HmacParams{Hash: commonpb.HashType_SHA256, TagSize: 32}, }, } serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("failed to marshal key: %s", err) } _, err = keyManager.Primitive(serializedKey) if err != nil { t.Errorf("Primitive() err = %v, want nil", err) } } func TestAESCTRHMACPrimitiveWithInvalidKey(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACAEADTypeURL) if err != nil { t.Errorf("cannot obtain AES-CTR-HMAC-AEAD key manager: %s", err) } testcases := []struct { name string key *ctrhmacpb.AesCtrHmacAeadKey }{ { name: "nil_nested_keys", key: &aeadpb.AesCtrHmacAeadKey{ Version: 0, AesCtrKey: nil, HmacKey: nil, }, }, { name: "nil_key_params", key: &aeadpb.AesCtrHmacAeadKey{ Version: 0, AesCtrKey: &ctrpb.AesCtrKey{ Version: 0, KeyValue: make([]byte, 32), Params: nil, }, HmacKey: &hmacpb.HmacKey{ Version: 0, KeyValue: make([]byte, 32), Params: nil, }, }, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { serializedKey, err := proto.Marshal(tc.key) if err != nil { t.Fatalf("failed to marshal key: %s", err) } _, err = keyManager.Primitive(serializedKey) if err == nil { t.Error("Primitive() err = nil, want error") } }) } } ================================================ FILE: go/aead/aes_gcm_key_manager.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead import ( "fmt" "io" "google.golang.org/protobuf/proto" "github.com/google/tink/go/aead/subtle" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/keyset" "github.com/google/tink/go/subtle/random" gcmpb "github.com/google/tink/go/proto/aes_gcm_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( aesGCMKeyVersion = 0 aesGCMTypeURL = "type.googleapis.com/google.crypto.tink.AesGcmKey" ) // common errors var errInvalidAESGCMKey = fmt.Errorf("aes_gcm_key_manager: invalid key") var errInvalidAESGCMKeyFormat = fmt.Errorf("aes_gcm_key_manager: invalid key format") // aesGCMKeyManager is an implementation of KeyManager interface. // It generates new AESGCMKey keys and produces new instances of AESGCM subtle. type aesGCMKeyManager struct{} // Assert that aesGCMKeyManager implements the KeyManager interface. var _ registry.KeyManager = (*aesGCMKeyManager)(nil) // Primitive creates an AESGCM subtle for the given serialized AESGCMKey proto. func (km *aesGCMKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidAESGCMKey } key := new(gcmpb.AesGcmKey) if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errInvalidAESGCMKey } if err := km.validateKey(key); err != nil { return nil, err } ret, err := subtle.NewAESGCM(key.KeyValue) if err != nil { return nil, fmt.Errorf("aes_gcm_key_manager: cannot create new primitive: %s", err) } return ret, nil } // NewKey creates a new key according to specification the given serialized AESGCMKeyFormat. func (km *aesGCMKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errInvalidAESGCMKeyFormat } keyFormat := new(gcmpb.AesGcmKeyFormat) if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, errInvalidAESGCMKeyFormat } if err := km.validateKeyFormat(keyFormat); err != nil { return nil, fmt.Errorf("aes_gcm_key_manager: invalid key format: %s", err) } keyValue := random.GetRandomBytes(keyFormat.KeySize) return &gcmpb.AesGcmKey{ Version: aesGCMKeyVersion, KeyValue: keyValue, }, nil } // NewKeyData creates a new KeyData according to specification in the given serialized // AESGCMKeyFormat. // It should be used solely by the key management API. func (km *aesGCMKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { key, err := km.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: aesGCMTypeURL, Value: serializedKey, KeyMaterialType: km.KeyMaterialType(), }, nil } // DoesSupport indicates if this key manager supports the given key type. func (km *aesGCMKeyManager) DoesSupport(typeURL string) bool { return typeURL == aesGCMTypeURL } // TypeURL returns the key type of keys managed by this key manager. func (km *aesGCMKeyManager) TypeURL() string { return aesGCMTypeURL } // KeyMaterialType returns the key material type of the key manager. func (km *aesGCMKeyManager) KeyMaterialType() tinkpb.KeyData_KeyMaterialType { return tinkpb.KeyData_SYMMETRIC } // DeriveKey derives a new key from serializedKeyFormat and pseudorandomness. func (km *aesGCMKeyManager) DeriveKey(serializedKeyFormat []byte, pseudorandomness io.Reader) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errInvalidAESGCMKeyFormat } keyFormat := new(gcmpb.AesGcmKeyFormat) if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, errInvalidAESGCMKeyFormat } if err := km.validateKeyFormat(keyFormat); err != nil { return nil, fmt.Errorf("aes_gcm_key_manager: invalid key format: %s", err) } if err := keyset.ValidateKeyVersion(keyFormat.GetVersion(), aesGCMKeyVersion); err != nil { return nil, fmt.Errorf("aes_gcm_key_manager: invalid key version: %s", err) } keyValue := make([]byte, keyFormat.GetKeySize()) if _, err := io.ReadFull(pseudorandomness, keyValue); err != nil { return nil, fmt.Errorf("aes_gcm_key_manager: not enough pseudorandomness given") } return &gcmpb.AesGcmKey{ Version: aesGCMKeyVersion, KeyValue: keyValue, }, nil } // validateKey validates the given AESGCMKey. func (km *aesGCMKeyManager) validateKey(key *gcmpb.AesGcmKey) error { if err := keyset.ValidateKeyVersion(key.Version, aesGCMKeyVersion); err != nil { return fmt.Errorf("aes_gcm_key_manager: %s", err) } keySize := uint32(len(key.KeyValue)) if err := subtle.ValidateAESKeySize(keySize); err != nil { return fmt.Errorf("aes_gcm_key_manager: %s", err) } return nil } // validateKeyFormat validates the given AESGCMKeyFormat. func (km *aesGCMKeyManager) validateKeyFormat(format *gcmpb.AesGcmKeyFormat) error { if err := subtle.ValidateAESKeySize(format.KeySize); err != nil { return fmt.Errorf("aes_gcm_key_manager: %s", err) } return nil } ================================================ FILE: go/aead/aes_gcm_key_manager_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead_test import ( "bytes" "fmt" "testing" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/proto" "github.com/google/tink/go/aead/subtle" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" gcmpb "github.com/google/tink/go/proto/aes_gcm_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) var keySizes = []uint32{16, 32} func TestAESGCMGetPrimitiveBasic(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMTypeURL) if err != nil { t.Errorf("cannot obtain AES-GCM key manager: %s", err) } for _, keySize := range keySizes { key := testutil.NewAESGCMKey(testutil.AESGCMKeyVersion, keySize) serializedKey, err := proto.Marshal(key) if err != nil { t.Errorf("proto.Marshal() err = %q, want nil", err) } p, err := keyManager.Primitive(serializedKey) if err != nil { t.Errorf("unexpected error: %s", err) } if err := validateAESGCMPrimitive(p, key); err != nil { t.Errorf("%s", err) } } } func TestAESGCMGetPrimitiveWithInvalidInput(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMTypeURL) if err != nil { t.Errorf("cannot obtain AES-GCM key manager: %s", err) } // invalid AESGCMKey testKeys := genInvalidAESGCMKeys() for i := 0; i < len(testKeys); i++ { serializedKey, err := proto.Marshal(testKeys[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := keyManager.Primitive(serializedKey); err == nil { t.Errorf("expect an error in test case %d", i) } } // nil if _, err := keyManager.Primitive(nil); err == nil { t.Errorf("expect an error when input is nil") } // empty array if _, err := keyManager.Primitive([]byte{}); err == nil { t.Errorf("expect an error when input is empty") } } func TestAESGCMNewKeyMultipleTimes(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMTypeURL) if err != nil { t.Errorf("cannot obtain AES-GCM key manager: %s", err) } format := testutil.NewAESGCMKeyFormat(32) serializedFormat, err := proto.Marshal(format) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } keys := make(map[string]bool) nTest := 26 for i := 0; i < nTest; i++ { key, err := keyManager.NewKey(serializedFormat) if err != nil { t.Fatalf("keyManager.NewKey() err = %q, want nil", err) } serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } keys[string(serializedKey)] = true keyData, err := keyManager.NewKeyData(serializedFormat) if err != nil { t.Fatalf("keyManager.NewKeyData() err = %q, want nil", err) } serializedKey = keyData.Value keys[string(serializedKey)] = true } if len(keys) != nTest*2 { t.Errorf("key is repeated") } } func TestAESGCMNewKeyBasic(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMTypeURL) if err != nil { t.Errorf("cannot obtain AES-GCM key manager: %s", err) } for _, keySize := range keySizes { format := testutil.NewAESGCMKeyFormat(keySize) serializedFormat, err := proto.Marshal(format) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } m, err := keyManager.NewKey(serializedFormat) if err != nil { t.Errorf("unexpected error: %s", err) } key := m.(*gcmpb.AesGcmKey) if err := validateAESGCMKey(key, format); err != nil { t.Errorf("%s", err) } } } func TestAESGCMNewKeyWithInvalidInput(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMTypeURL) if err != nil { t.Errorf("cannot obtain AES-GCM key manager: %s", err) } // bad format badFormats := genInvalidAESGCMKeyFormats() for i := 0; i < len(badFormats); i++ { serializedFormat, err := proto.Marshal(badFormats[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := keyManager.NewKey(serializedFormat); err == nil { t.Errorf("expect an error in test case %d", i) } } // nil if _, err := keyManager.NewKey(nil); err == nil { t.Errorf("expect an error when input is nil") } // empty array if _, err := keyManager.NewKey([]byte{}); err == nil { t.Errorf("expect an error when input is empty") } } func TestAESGCMNewKeyDataBasic(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMTypeURL) if err != nil { t.Errorf("cannot obtain AES-GCM key manager: %s", err) } for _, keySize := range keySizes { format := testutil.NewAESGCMKeyFormat(keySize) serializedFormat, err := proto.Marshal(format) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } keyData, err := keyManager.NewKeyData(serializedFormat) if err != nil { t.Errorf("unexpected error: %s", err) } if keyData.TypeUrl != testutil.AESGCMTypeURL { t.Errorf("incorrect type url") } if keyData.KeyMaterialType != tinkpb.KeyData_SYMMETRIC { t.Errorf("incorrect key material type") } key := new(gcmpb.AesGcmKey) if err := proto.Unmarshal(keyData.Value, key); err != nil { t.Errorf("incorrect key value") } if err := validateAESGCMKey(key, format); err != nil { t.Errorf("%s", err) } } } func TestAESGCMNewKeyDataWithInvalidInput(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMTypeURL) if err != nil { t.Errorf("cannot obtain AES-GCM key manager: %s", err) } badFormats := genInvalidAESGCMKeyFormats() for i := 0; i < len(badFormats); i++ { serializedFormat, err := proto.Marshal(badFormats[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := keyManager.NewKeyData(serializedFormat); err == nil { t.Errorf("expect an error in test case %d", i) } } // nil input if _, err := keyManager.NewKeyData(nil); err == nil { t.Errorf("expect an error when input is nil") } // empty input if _, err := keyManager.NewKeyData([]byte{}); err == nil { t.Errorf("expect an error when input is empty") } } func TestAESGCMDoesSupport(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMTypeURL) if err != nil { t.Errorf("cannot obtain AES-GCM key manager: %s", err) } if !keyManager.DoesSupport(testutil.AESGCMTypeURL) { t.Errorf("AESGCMKeyManager must support %s", testutil.AESGCMTypeURL) } if keyManager.DoesSupport("some bad type") { t.Errorf("AESGCMKeyManager must support only %s", testutil.AESGCMTypeURL) } } func TestAESGCMTypeURL(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMTypeURL) if err != nil { t.Errorf("cannot obtain AES-GCM key manager: %s", err) } if keyManager.TypeURL() != testutil.AESGCMTypeURL { t.Errorf("incorrect key type") } } func TestAESGCMKeyMaterialType(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESGCMTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.AESGCMTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } if got, want := keyManager.KeyMaterialType(), tinkpb.KeyData_SYMMETRIC; got != want { t.Errorf("KeyMaterialType() = %v, want %v", got, want) } } func TestAESGCMDeriveKey(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESGCMTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.AESGCMTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } for _, test := range []struct { name string keySize uint32 }{ { name: "AES-128-GCM", keySize: 16, }, { name: "AES-256-GCM", keySize: 32, }, } { t.Run(test.name, func(t *testing.T) { keyFormat := testutil.NewAESGCMKeyFormat(test.keySize) serializedKeyFormat, err := proto.Marshal(keyFormat) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", keyFormat, err) } rand := random.GetRandomBytes(test.keySize) buf := &bytes.Buffer{} buf.Write(rand) // never returns a non-nil error k, err := keyManager.DeriveKey(serializedKeyFormat, buf) if err != nil { t.Fatalf("keyManager.DeriveKey() err = %v, want nil", err) } key := k.(*gcmpb.AesGcmKey) if got, want := len(key.GetKeyValue()), int(test.keySize); got != want { t.Errorf("key length = %d, want %d", got, want) } if diff := cmp.Diff(key.GetKeyValue(), rand); diff != "" { t.Errorf("incorrect derived key: diff = %v", diff) } }) } } func TestAESGCMDeriveKeyFailsWithInvalidKeyFormats(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESGCMTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.AESGCMTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } for _, test := range []struct { name string keyFormat *gcmpb.AesGcmKeyFormat randLen uint32 }{ { name: "invalid key size", keyFormat: &gcmpb.AesGcmKeyFormat{KeySize: 50, Version: 0}, randLen: 50, }, { name: "not enough randomness", keyFormat: &gcmpb.AesGcmKeyFormat{KeySize: 32, Version: 0}, randLen: 10, }, { name: "invalid version", keyFormat: &gcmpb.AesGcmKeyFormat{KeySize: 32, Version: 100000}, randLen: 32, }, { name: "empty key format", keyFormat: &gcmpb.AesGcmKeyFormat{}, randLen: 16, }, { name: "nil key format", randLen: 16, }, } { t.Run(test.name, func(t *testing.T) { serializedKeyFormat, err := proto.Marshal(test.keyFormat) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", test.keyFormat, err) } buf := bytes.NewBuffer(random.GetRandomBytes(test.randLen)) if _, err := keyManager.DeriveKey(serializedKeyFormat, buf); err == nil { t.Error("keyManager.DeriveKey() err = nil, want non-nil") } }) } } func TestAESGCMDeriveKeyFailsWithMalformedSerializedKeyFormat(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESGCMTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.AESGCMTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } size := proto.Size(&gcmpb.AesGcmKeyFormat{KeySize: 16, Version: 0}) malformedSerializedKeyFormat := random.GetRandomBytes(uint32(size)) buf := bytes.NewBuffer(random.GetRandomBytes(32)) if _, err := keyManager.DeriveKey(malformedSerializedKeyFormat, buf); err == nil { t.Error("keyManager.DeriveKey() err = nil, want non-nil") } } func TestAESGCMDeriveKeyFailsWithInsufficientRandomness(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESGCMTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.AESGCMTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } var keySize uint32 = 16 keyFormat, err := proto.Marshal(testutil.NewAESGCMKeyFormat(keySize)) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } { buf := bytes.NewBuffer(random.GetRandomBytes(keySize)) if _, err := keyManager.DeriveKey(keyFormat, buf); err != nil { t.Errorf("keyManager.DeriveKey() err = %v, want nil", err) } } { insufficientBuf := bytes.NewBuffer(random.GetRandomBytes(keySize - 1)) if _, err := keyManager.DeriveKey(keyFormat, insufficientBuf); err == nil { t.Errorf("keyManager.DeriveKey() err = nil, want non-nil") } } } func genInvalidAESGCMKeys() []proto.Message { return []proto.Message{ // not a AESGCMKey testutil.NewAESGCMKeyFormat(32), // bad key size testutil.NewAESGCMKey(testutil.AESGCMKeyVersion, 17), testutil.NewAESGCMKey(testutil.AESGCMKeyVersion, 25), testutil.NewAESGCMKey(testutil.AESGCMKeyVersion, 33), // bad version testutil.NewAESGCMKey(testutil.AESGCMKeyVersion+1, 16), } } func genInvalidAESGCMKeyFormats() []proto.Message { return []proto.Message{ // not AESGCMKeyFormat testutil.NewAESGCMKey(testutil.AESGCMKeyVersion, 16), // invalid key size testutil.NewAESGCMKeyFormat(uint32(15)), testutil.NewAESGCMKeyFormat(uint32(23)), testutil.NewAESGCMKeyFormat(uint32(31)), } } func validateAESGCMKey(key *gcmpb.AesGcmKey, format *gcmpb.AesGcmKeyFormat) error { if uint32(len(key.KeyValue)) != format.KeySize { return fmt.Errorf("incorrect key size") } if key.Version != testutil.AESGCMKeyVersion { return fmt.Errorf("incorrect key version") } // try to encrypt and decrypt p, err := subtle.NewAESGCM(key.KeyValue) if err != nil { return fmt.Errorf("invalid key") } return validateAESGCMPrimitive(p, key) } func validateAESGCMPrimitive(p any, key *gcmpb.AesGcmKey) error { cipher := p.(*subtle.AESGCM) // try to encrypt and decrypt pt := random.GetRandomBytes(32) aad := random.GetRandomBytes(32) ct, err := cipher.Encrypt(pt, aad) if err != nil { return fmt.Errorf("encryption failed") } decrypted, err := cipher.Decrypt(ct, aad) if err != nil { return fmt.Errorf("decryption failed") } if !bytes.Equal(decrypted, pt) { return fmt.Errorf("decryption failed") } return nil } ================================================ FILE: go/aead/aes_gcm_siv_key_manager.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead import ( "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/aead/subtle" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/keyset" "github.com/google/tink/go/subtle/random" gcmsivpb "github.com/google/tink/go/proto/aes_gcm_siv_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( aesGCMSIVKeyVersion = 0 aesGCMSIVTypeURL = "type.googleapis.com/google.crypto.tink.AesGcmSivKey" ) // common errors var errInvalidAESGCMSIVKey = fmt.Errorf("aes_gcm_siv_key_manager: invalid key") var errInvalidAESGCMSIVKeyFormat = fmt.Errorf("aes_gcm_siv_key_manager: invalid key format") // aesGCMSIVKeyManager is an implementation of KeyManager interface. // It generates new AESGCMSIVKey keys and produces new instances of AESGCMSIV subtle. type aesGCMSIVKeyManager struct{} // Assert that aesGCMSIVKeyManager implements the KeyManager interface. var _ registry.KeyManager = (*aesGCMSIVKeyManager)(nil) // Primitive creates an AESGCMSIV subtle for the given serialized AESGCMSIVKey proto. func (km *aesGCMSIVKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidAESGCMSIVKey } key := new(gcmsivpb.AesGcmSivKey) if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errInvalidAESGCMSIVKey } if err := km.validateKey(key); err != nil { return nil, err } ret, err := subtle.NewAESGCMSIV(key.KeyValue) if err != nil { return nil, fmt.Errorf("aes_gcm_siv_key_manager: cannot create new primitive: %s", err) } return ret, nil } // NewKey creates a new key according to specification the given serialized AESGCMSIVKeyFormat. func (km *aesGCMSIVKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errInvalidAESGCMSIVKeyFormat } keyFormat := new(gcmsivpb.AesGcmSivKeyFormat) if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, errInvalidAESGCMSIVKeyFormat } if err := km.validateKeyFormat(keyFormat); err != nil { return nil, fmt.Errorf("aes_gcm_siv_key_manager: invalid key format: %s", err) } keyValue := random.GetRandomBytes(keyFormat.KeySize) return &gcmsivpb.AesGcmSivKey{ Version: aesGCMSIVKeyVersion, KeyValue: keyValue, }, nil } // NewKeyData creates a new KeyData according to specification in the given serialized // AESGCMSIVKeyFormat. // It should be used solely by the key management API. func (km *aesGCMSIVKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { key, err := km.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: aesGCMSIVTypeURL, Value: serializedKey, KeyMaterialType: tinkpb.KeyData_SYMMETRIC, }, nil } // DoesSupport indicates if this key manager supports the given key type. func (km *aesGCMSIVKeyManager) DoesSupport(typeURL string) bool { return typeURL == aesGCMSIVTypeURL } // TypeURL returns the key type of keys managed by this key manager. func (km *aesGCMSIVKeyManager) TypeURL() string { return aesGCMSIVTypeURL } // validateKey validates the given AESGCMSIVKey. func (km *aesGCMSIVKeyManager) validateKey(key *gcmsivpb.AesGcmSivKey) error { err := keyset.ValidateKeyVersion(key.Version, aesGCMSIVKeyVersion) if err != nil { return fmt.Errorf("aes_gcm_siv_key_manager: %s", err) } keySize := uint32(len(key.KeyValue)) if err := subtle.ValidateAESKeySize(keySize); err != nil { return fmt.Errorf("aes_gcm_siv_key_manager: %s", err) } return nil } // validateKeyFormat validates the given AESGCMSIVKeyFormat. func (km *aesGCMSIVKeyManager) validateKeyFormat(format *gcmsivpb.AesGcmSivKeyFormat) error { if err := subtle.ValidateAESKeySize(format.KeySize); err != nil { return fmt.Errorf("aes_gcm_siv_key_manager: %s", err) } return nil } ================================================ FILE: go/aead/aes_gcm_siv_key_manager_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead_test import ( "bytes" "fmt" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/aead/subtle" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" gcmsivpb "github.com/google/tink/go/proto/aes_gcm_siv_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) var aesGCMSIVKeySizes = []uint32{16, 32} func TestAESGCMSIVGetPrimitiveBasic(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMSIVTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(typeURL=%s): Cannot obtain AES-GCM-SIV key manager; err=%v", testutil.AESGCMSIVTypeURL, err) } for _, keySize := range aesGCMSIVKeySizes { key := testutil.NewAESGCMSIVKey(testutil.AESGCMSIVKeyVersion, uint32(keySize)) serializedKey, err := proto.Marshal(key) if err != nil { t.Errorf("proto.Marshal(data=%+v): Failed to serialize key for keySize=%d, skipping test iteration; err=%v", key, keySize, err) continue } p, err := keyManager.Primitive(serializedKey) if err != nil { t.Errorf("Primitive(serializedKey=%v): Unexpected error creating AES-GCM-SIV primitive with keySize=%d, skipping test iteration; err=%v", serializedKey, keySize, err) continue } if err := validateAESGCMSIVPrimitive(p, key); err != nil { t.Errorf("validateAESGCMSIVPrimitive(key=%v): Error validating AES-GCM-SIV primitive with keySize=%d, skipping test iteration; err=%v", key, keySize, err) continue } } } func TestAESGCMSIVGetPrimitiveWithInvalidInput(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMSIVTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(typeURL=%s): Cannot obtain AES-GCM-SIV key manager; err=%v", testutil.AESGCMSIVTypeURL, err) } // invalid AESGCMSIVKey testKeys := genInvalidAESGCMSIVKeys() for i := 0; i < len(testKeys); i++ { serializedKey, err := proto.Marshal(testKeys[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := keyManager.Primitive(serializedKey); err == nil { t.Errorf("Primitive(serializedKey=%v): Key %d, got err = nil, want err != nil.", serializedKey, i) } } // nil if _, err := keyManager.Primitive(nil); err == nil { t.Errorf("Primitive(serializedKey=nil): Key nil, got err = nil, want err != nil.") } // empty array if _, err := keyManager.Primitive([]byte{}); err == nil { t.Errorf("Primitive(serializedKey=[]): Key empty, got err = nil, want err != nil.") } } func TestAESGCMSIVNewKeyMultipleTimes(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMSIVTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(typeURL=%s): Cannot obtain AES-GCM-SIV key manager; err=%v", testutil.AESGCMSIVTypeURL, err) } format := testutil.NewAESGCMSIVKeyFormat(32) serializedFormat, err := proto.Marshal(format) if err != nil { t.Fatalf("proto.Marshal(data=%+v): Failed to serialize key format; err=%v", format, err) } keys := make(map[string]bool) nTest := 26 for i := 0; i < nTest; i++ { key, err := keyManager.NewKey(serializedFormat) if err != nil { t.Errorf("NewKey(serializedKeyFormat=%v): Failed to create new key on iteration %d; err=%v", serializedFormat, i, err) } serializedKey, err := proto.Marshal(key) if err != nil { t.Errorf("proto.Marshal(data=%+v): Failed to serialize key on iteration %d; err=%v", key, i, err) } keys[string(serializedKey)] = true keyData, err := keyManager.NewKeyData(serializedFormat) if err != nil { t.Errorf("NewKeyData(serializedFormat=%v): Failed to create new key data on iteration %d; err=%v", serializedFormat, i, err) } serializedKey = keyData.Value keys[string(serializedKey)] = true } if len(keys) != nTest*2 { t.Errorf("TestAESGCMSIVNewKeyMultipleTimes(): Got %d unique keys, want %d.", len(keys), nTest*2) } } func TestAESGCMSIVNewKeyBasic(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMSIVTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(typeURL=%s): Cannot obtain AES-GCM-SIV key manager; err=%v", testutil.AESGCMSIVTypeURL, err) } for _, keySize := range aesGCMSIVKeySizes { format := testutil.NewAESGCMSIVKeyFormat(uint32(keySize)) serializedFormat, err := proto.Marshal(format) if err != nil { t.Errorf("proto.Marshal(data=%+v): Failed to serialize key format for keySize=%d, skipping remainder of test iteration; err=%v", format, keySize, err) continue } m, err := keyManager.NewKey(serializedFormat) if err != nil { t.Errorf("NewKey(serializedKeyFormat=%v): Unexpected error for keySize=%d, skipping remainder of test iteration; err=%v", serializedFormat, keySize, err) continue } key := m.(*gcmsivpb.AesGcmSivKey) if err := validateAESGCMSIVKey(key, format); err != nil { t.Errorf("validateAESGCMSIVKey(key=%v): Error trying to validate key for keySize=%d; err=%v", key, keySize, err) } } } func TestAESGCMSIVNewKeyWithInvalidInput(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMSIVTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(typeURL=%s): Cannot obtain AES-GCM-SIV key manager; err=%v", testutil.AESGCMSIVTypeURL, err) } // bad format badFormats := genInvalidAESGCMSIVKeyFormats() for i := 0; i < len(badFormats); i++ { serializedFormat, err := proto.Marshal(badFormats[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := keyManager.NewKey(serializedFormat); err == nil { t.Errorf("NewKey(serializedKeyFormat=%v): Key %d, got err = nil, want err != nil", serializedFormat, i) } } // nil if _, err := keyManager.NewKey(nil); err == nil { t.Errorf("NewKey(serializedKeyFormat=nil): Key nil, got err = nil, want err != nil") } // empty array if _, err := keyManager.NewKey([]byte{}); err == nil { t.Errorf("NewKey(serializedKeyFormat=[]): Key empty, got err = nil, want err != nil") } } func TestAESGCMSIVNewKeyDataBasic(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMSIVTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(typeURL=%s): Cannot obtain AES-GCM-SIV key manager; err=%v", testutil.AESGCMSIVTypeURL, err) } for _, keySize := range aesGCMSIVKeySizes { format := testutil.NewAESGCMSIVKeyFormat(uint32(keySize)) serializedFormat, err := proto.Marshal(format) if err != nil { t.Errorf("proto.Marshal(data=%+v): Failed to serialize key format for keySize=%d, skipping remainder of test iteration; err=%v", format, keySize, err) continue } keyData, err := keyManager.NewKeyData(serializedFormat) if err != nil { t.Errorf("NewKeyData(serializedKeyFormat=%v): Failed to create keyData for keySize=%d, skipping remainder of test iteration; err=%v", serializedFormat, keySize, err) continue } if keyData.TypeUrl != testutil.AESGCMSIVTypeURL { t.Errorf("NewKeyData(serializedKeyFormat=%v): Incorrect type url for keySize=%d, got %s, want %s.", serializedFormat, keySize, keyData.TypeUrl, testutil.AESGCMSIVTypeURL) } if keyData.KeyMaterialType != tinkpb.KeyData_SYMMETRIC { t.Errorf("NewKeyData(serializedKeyFormat=%v): Incorrect key material type for keySize=%d, got %d, want %d.", serializedFormat, keySize, keyData.KeyMaterialType, tinkpb.KeyData_SYMMETRIC) } key := new(gcmsivpb.AesGcmSivKey) if err := proto.Unmarshal(keyData.Value, key); err != nil { t.Errorf("proto.Unmarshal(data=%v): Failed to load keyData into key for keySize=%d, skipping remainder of test iteration; err=%v", keyData.Value, keySize, err) continue } if err := validateAESGCMSIVKey(key, format); err != nil { t.Errorf("validateAESGCMSIVKey(key=%v): Failed to validate key for keySize=%d; err=%v", key, keySize, err) } p, err := registry.PrimitiveFromKeyData(keyData) if err != nil { t.Errorf("registry.PrimitiveFromKeyData(keyData) err = %v, want nil", err) } _, ok := p.(*subtle.AESGCMSIV) if !ok { t.Error("registry.PrimitiveFromKeyData(keyData) did not return a AESGCMSIV primitive") } } } func TestAESGCMSIVNewKeyDataWithInvalidInput(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMSIVTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(typeURL=%s): Cannot obtain AES-GCM-SIV key manager; err=%v", testutil.AESGCMSIVTypeURL, err) } badFormats := genInvalidAESGCMSIVKeyFormats() for i := 0; i < len(badFormats); i++ { serializedFormat, err := proto.Marshal(badFormats[i]) if err != nil { t.Errorf("proto.Marshal(data=%+v): Key %d, failed to serialize key format, skipping remainder of test iteration; err=%v", badFormats[i], i, err) continue } if _, err := keyManager.NewKeyData(serializedFormat); err == nil { t.Errorf("NewKeyData(serializedKeyFormat=%v): Key %d, got err = nil, want err != nil.", serializedFormat, i) } } // nil input if _, err := keyManager.NewKeyData(nil); err == nil { t.Errorf("NewKeyData(serializedKeyFormat=nil): Key nil, got err = nil, want err != nil") } // empty input if _, err := keyManager.NewKeyData([]byte{}); err == nil { t.Errorf("NewKeyData(serializedKeyFormat=[]): Key empty, got err = nil, want err != nil") } } func TestAESGCMSIVDoesSupport(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMSIVTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(typeURL=%s): Cannot obtain AES-GCM-SIV key manager; err=%v", testutil.AESGCMSIVTypeURL, err) } if !keyManager.DoesSupport(testutil.AESGCMSIVTypeURL) { t.Errorf("DoesSupport(typeURL=%s): got false, want true", testutil.AESGCMSIVTypeURL) } if keyManager.DoesSupport("some bad type") { t.Errorf("DoesSupport(typeURL=\"some bad type\"): got true, want false") } } func TestAESGCMSIVTypeURL(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMSIVTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(typeURL=%s): Cannot obtain AES-GCM-SIV key manager; err=%v", testutil.AESGCMSIVTypeURL, err) } if keyManager.TypeURL() != testutil.AESGCMSIVTypeURL { t.Errorf("GetKeyManager(%s): Incorrect key type for key manager, got %s, want %s.", testutil.AESGCMSIVTypeURL, keyManager.TypeURL(), testutil.AESGCMSIVTypeURL) } } func genInvalidAESGCMSIVKeys() []proto.Message { return []proto.Message{ // not a AESGCMSIVKey testutil.NewAESGCMSIVKeyFormat(32), // bad key size testutil.NewAESGCMSIVKey(testutil.AESGCMSIVKeyVersion, 17), testutil.NewAESGCMSIVKey(testutil.AESGCMSIVKeyVersion, 25), testutil.NewAESGCMSIVKey(testutil.AESGCMSIVKeyVersion, 33), // bad version testutil.NewAESGCMSIVKey(testutil.AESGCMSIVKeyVersion+1, 16), } } func genInvalidAESGCMSIVKeyFormats() []proto.Message { return []proto.Message{ // not AESGCMSIVKeyFormat testutil.NewAESGCMSIVKey(testutil.AESGCMSIVKeyVersion, 16), // invalid key size testutil.NewAESGCMSIVKeyFormat(uint32(15)), testutil.NewAESGCMSIVKeyFormat(uint32(23)), testutil.NewAESGCMSIVKeyFormat(uint32(31)), } } func validateAESGCMSIVKey(key *gcmsivpb.AesGcmSivKey, format *gcmsivpb.AesGcmSivKeyFormat) error { if uint32(len(key.KeyValue)) != format.KeySize { return fmt.Errorf("Incorrect key size, got %d, want %d", uint32(len(key.KeyValue)), format.KeySize) } if key.Version != testutil.AESGCMSIVKeyVersion { return fmt.Errorf("Incorrect key version, got %d, want %d", key.Version, testutil.AESGCMSIVKeyVersion) } // Try to encrypt and decrypt random data. p, err := subtle.NewAESGCMSIV(key.KeyValue) if err != nil { return fmt.Errorf("subtle.NewAESGCMSIV(key=%v): Invalid key; err=%v", key.KeyValue, err) } return validateAESGCMSIVPrimitive(p, key) } func validateAESGCMSIVPrimitive(p any, key *gcmsivpb.AesGcmSivKey) error { cipher := p.(*subtle.AESGCMSIV) // Try to encrypt and decrypt random data. pt := random.GetRandomBytes(32) aad := random.GetRandomBytes(32) ct, err := cipher.Encrypt(pt, aad) if err != nil { return fmt.Errorf("subtle.AESGCMSIV.Encrypt(pt=%v, aad=%v): Encryption failed; err=%v", pt, aad, err) } decrypted, err := cipher.Decrypt(ct, aad) if err != nil { return fmt.Errorf("subtle.AESGCMSIV.Decrypt(ct=%v, aad=%v): Decryption failed; err=%v", ct, aad, err) } if !bytes.Equal(decrypted, pt) { return fmt.Errorf("subtle.AESGCMSIV.Decrypt(ct=%v, aad=%v): Decrypted bytes did not match original, got %v, want %v", ct, aad, decrypted, pt) } return nil } ================================================ FILE: go/aead/chacha20poly1305_key_manager.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead import ( "fmt" "golang.org/x/crypto/chacha20poly1305" "google.golang.org/protobuf/proto" "github.com/google/tink/go/aead/subtle" "github.com/google/tink/go/keyset" "github.com/google/tink/go/subtle/random" cppb "github.com/google/tink/go/proto/chacha20_poly1305_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( chaCha20Poly1305KeyVersion = 0 chaCha20Poly1305TypeURL = "type.googleapis.com/google.crypto.tink.ChaCha20Poly1305Key" ) // Common errors. var errInvalidChaCha20Poly1305Key = fmt.Errorf("chacha20poly1305_key_manager: invalid key") var errInvalidChaCha20Poly1305KeyFormat = fmt.Errorf("chacha20poly1305_key_manager: invalid key format") // chaCha20Poly1305KeyManager is an implementation of KeyManager interface. // It generates new ChaCha20Poly1305Key keys and produces new instances of ChaCha20Poly1305 subtle. type chaCha20Poly1305KeyManager struct{} // Primitive creates an ChaCha20Poly1305 subtle for the given serialized ChaCha20Poly1305Key proto. func (km *chaCha20Poly1305KeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidChaCha20Poly1305Key } key := new(cppb.ChaCha20Poly1305Key) if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errInvalidChaCha20Poly1305Key } if err := km.validateKey(key); err != nil { return nil, err } ret, err := subtle.NewChaCha20Poly1305(key.KeyValue) if err != nil { return nil, fmt.Errorf("chacha20poly1305_key_manager: cannot create new primitive: %s", err) } return ret, nil } // NewKey creates a new key, ignoring the specification in the given serialized key format // because the key size and other params are fixed. func (km *chaCha20Poly1305KeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { return km.newChaCha20Poly1305Key(), nil } // NewKeyData creates a new KeyData ignoring the specification in the given serialized key format // because the key size and other params are fixed. // It should be used solely by the key management API. func (km *chaCha20Poly1305KeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { key := km.newChaCha20Poly1305Key() serializedKey, err := proto.Marshal(key) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: chaCha20Poly1305TypeURL, Value: serializedKey, KeyMaterialType: tinkpb.KeyData_SYMMETRIC, }, nil } // DoesSupport indicates if this key manager supports the given key type. func (km *chaCha20Poly1305KeyManager) DoesSupport(typeURL string) bool { return typeURL == chaCha20Poly1305TypeURL } // TypeURL returns the key type of keys managed by this key manager. func (km *chaCha20Poly1305KeyManager) TypeURL() string { return chaCha20Poly1305TypeURL } func (km *chaCha20Poly1305KeyManager) newChaCha20Poly1305Key() *cppb.ChaCha20Poly1305Key { keyValue := random.GetRandomBytes(chacha20poly1305.KeySize) return &cppb.ChaCha20Poly1305Key{ Version: chaCha20Poly1305KeyVersion, KeyValue: keyValue, } } // validateKey validates the given ChaCha20Poly1305Key. func (km *chaCha20Poly1305KeyManager) validateKey(key *cppb.ChaCha20Poly1305Key) error { err := keyset.ValidateKeyVersion(key.Version, chaCha20Poly1305KeyVersion) if err != nil { return fmt.Errorf("chacha20poly1305_key_manager: %s", err) } keySize := uint32(len(key.KeyValue)) if keySize != chacha20poly1305.KeySize { return fmt.Errorf("chacha20poly1305_key_manager: keySize != %d", chacha20poly1305.KeySize) } return nil } ================================================ FILE: go/aead/chacha20poly1305_key_manager_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead_test import ( "bytes" "fmt" "testing" "golang.org/x/crypto/chacha20poly1305" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" "github.com/google/tink/go/aead/subtle" cppb "github.com/google/tink/go/proto/chacha20_poly1305_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestChaCha20Poly1305GetPrimitive(t *testing.T) { km, err := registry.GetKeyManager(testutil.ChaCha20Poly1305TypeURL) if err != nil { t.Fatalf("cannot obtain ChaCha20Poly1305 key manager: %s", err) } m, err := km.NewKey(nil) if err != nil { t.Fatalf("km.NewKey(nil) err = %q, want nil", err) } key, ok := m.(*cppb.ChaCha20Poly1305Key) if !ok { t.Fatalf("m is not a *cppb.ChaCha20Poly1305Key") } serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } p, err := km.Primitive(serializedKey) if err != nil { t.Fatalf("km.Primitive(%v) = %v; want nil", serializedKey, err) } if err := validateChaCha20Poly1305Primitive(p, key); err != nil { t.Errorf("validateChaCha20Poly1305Primitive(p, key) = %v; want nil", err) } } func TestChaCha20Poly1305GetPrimitiveWithInvalidKeys(t *testing.T) { km, err := registry.GetKeyManager(testutil.ChaCha20Poly1305TypeURL) if err != nil { t.Errorf("cannot obtain ChaCha20Poly1305 key manager: %s", err) } invalidKeys := genInvalidChaCha20Poly1305Keys() for _, key := range invalidKeys { serializedKey, err := proto.Marshal(key) if err != nil { t.Errorf("proto.Marshal() err = %q, want nil", err) } if _, err := km.Primitive(serializedKey); err == nil { t.Errorf("km.Primitive(%v) = _, nil; want _, err", serializedKey) } } } func TestChaCha20Poly1305NewKey(t *testing.T) { km, err := registry.GetKeyManager(testutil.ChaCha20Poly1305TypeURL) if err != nil { t.Errorf("cannot obtain ChaCha20Poly1305 key manager: %s", err) } m, err := km.NewKey(nil) if err != nil { t.Errorf("km.NewKey(nil) = _, %v; want _, nil", err) } key, ok := m.(*cppb.ChaCha20Poly1305Key) if !ok { t.Fatalf("m is not a *cppb.ChaCha20Poly1305Key") } if err := validateChaCha20Poly1305Key(key); err != nil { t.Errorf("validateChaCha20Poly1305Key(%v) = %v; want nil", key, err) } } func TestChaCha20Poly1305NewKeyData(t *testing.T) { km, err := registry.GetKeyManager(testutil.ChaCha20Poly1305TypeURL) if err != nil { t.Errorf("cannot obtain ChaCha20Poly1305 key manager: %s", err) } kd, err := km.NewKeyData(nil) if err != nil { t.Errorf("km.NewKeyData(nil) = _, %v; want _, nil", err) } if kd.TypeUrl != testutil.ChaCha20Poly1305TypeURL { t.Errorf("TypeUrl: %v != %v", kd.TypeUrl, testutil.ChaCha20Poly1305TypeURL) } if kd.KeyMaterialType != tinkpb.KeyData_SYMMETRIC { t.Errorf("KeyMaterialType: %v != SYMMETRIC", kd.KeyMaterialType) } key := new(cppb.ChaCha20Poly1305Key) if err := proto.Unmarshal(kd.Value, key); err != nil { t.Errorf("proto.Unmarshal(%v, key) = %v; want nil", kd.Value, err) } if err := validateChaCha20Poly1305Key(key); err != nil { t.Errorf("validateChaCha20Poly1305Key(%v) = %v; want nil", key, err) } p, err := registry.PrimitiveFromKeyData(kd) if err != nil { t.Errorf("registry.PrimitiveFromKeyData(kd) err = %v, want nil", err) } _, ok := p.(*subtle.ChaCha20Poly1305) if !ok { t.Error("registry.PrimitiveFromKeyData(kd) did not return a ChaCha20Poly1305 primitive") } } func TestChaCha20Poly1305DoesSupport(t *testing.T) { km, err := registry.GetKeyManager(testutil.ChaCha20Poly1305TypeURL) if err != nil { t.Errorf("cannot obtain ChaCha20Poly1305 key manager: %s", err) } if !km.DoesSupport(testutil.ChaCha20Poly1305TypeURL) { t.Errorf("ChaCha20Poly1305KeyManager must support %s", testutil.ChaCha20Poly1305TypeURL) } if km.DoesSupport("some bad type") { t.Errorf("ChaCha20Poly1305KeyManager must only support %s", testutil.ChaCha20Poly1305TypeURL) } } func TestChaCha20Poly1305TypeURL(t *testing.T) { km, err := registry.GetKeyManager(testutil.ChaCha20Poly1305TypeURL) if err != nil { t.Errorf("cannot obtain ChaCha20Poly1305 key manager: %s", err) } if kt := km.TypeURL(); kt != testutil.ChaCha20Poly1305TypeURL { t.Errorf("km.TypeURL() = %s; want %s", kt, testutil.ChaCha20Poly1305TypeURL) } } func genInvalidChaCha20Poly1305Keys() []*cppb.ChaCha20Poly1305Key { return []*cppb.ChaCha20Poly1305Key{ // Bad key size. &cppb.ChaCha20Poly1305Key{ Version: testutil.ChaCha20Poly1305KeyVersion, KeyValue: random.GetRandomBytes(17), }, &cppb.ChaCha20Poly1305Key{ Version: testutil.ChaCha20Poly1305KeyVersion, KeyValue: random.GetRandomBytes(25), }, &cppb.ChaCha20Poly1305Key{ Version: testutil.ChaCha20Poly1305KeyVersion, KeyValue: random.GetRandomBytes(33), }, // Bad version. &cppb.ChaCha20Poly1305Key{ Version: testutil.ChaCha20Poly1305KeyVersion + 1, KeyValue: random.GetRandomBytes(chacha20poly1305.KeySize), }, } } func validateChaCha20Poly1305Primitive(p any, key *cppb.ChaCha20Poly1305Key) error { cipher := p.(*subtle.ChaCha20Poly1305) if !bytes.Equal(cipher.Key, key.KeyValue) { return fmt.Errorf("key and primitive don't match") } // Try to encrypt and decrypt. pt := random.GetRandomBytes(32) aad := random.GetRandomBytes(32) ct, err := cipher.Encrypt(pt, aad) if err != nil { return fmt.Errorf("encryption failed") } decrypted, err := cipher.Decrypt(ct, aad) if err != nil { return fmt.Errorf("decryption failed") } if !bytes.Equal(decrypted, pt) { return fmt.Errorf("decryption failed") } return nil } func validateChaCha20Poly1305Key(key *cppb.ChaCha20Poly1305Key) error { if key.Version != testutil.ChaCha20Poly1305KeyVersion { return fmt.Errorf("incorrect key version: keyVersion != %d", testutil.ChaCha20Poly1305KeyVersion) } if uint32(len(key.KeyValue)) != chacha20poly1305.KeySize { return fmt.Errorf("incorrect key size: keySize != %d", chacha20poly1305.KeySize) } // Try to encrypt and decrypt. p, err := subtle.NewChaCha20Poly1305(key.KeyValue) if err != nil { return fmt.Errorf("invalid key: %v", key.KeyValue) } return validateChaCha20Poly1305Primitive(p, key) } ================================================ FILE: go/aead/internal/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) # keep licenses(["notice"]) # keep ================================================ FILE: go/aead/internal/testing/BUILD.bazel ================================================ package(default_visibility = ["//:__subpackages__"]) # keep licenses(["notice"]) # keep ================================================ FILE: go/aead/internal/testing/kmsaead/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep licenses(["notice"]) # keep go_library( name = "kmsaead", testonly = 1, srcs = ["key_manager.go"], importpath = "github.com/google/tink/go/aead/internal/testing/kmsaead", visibility = ["//visibility:public"], deps = [ "//core/registry", "//keyset", "//proto/kms_aead_go_proto", "//proto/tink_go_proto", "@org_golang_google_protobuf//proto", ], ) go_test( name = "kmsaead_test", testonly = 1, srcs = ["key_manager_test.go"], deps = [ ":kmsaead", "//aead", "//core/registry", "//keyset", "//testing/fakekms", ], ) alias( name = "go_default_library", actual = ":kmsaead", visibility = ["//aead:__subpackages__"], ) ================================================ FILE: go/aead/internal/testing/kmsaead/key_manager.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package kmsaead provides a keymanager for KmsAeadKey that may only be used in tests. // // Golang currently doesn't implement KmsAeadKey. This is an internal implementation // to be used by the cross-language tests. package kmsaead import ( "errors" "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/keyset" kmsaeadpb "github.com/google/tink/go/proto/kms_aead_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const kmsAEADTypeURL = "type.googleapis.com/google.crypto.tink.KmsAeadKey" type keyManager struct{} func (km *keyManager) Primitive(protoSerializedKey []byte) (any, error) { if len(protoSerializedKey) == 0 { return nil, errors.New("kmsaead.keyManager: invalid key") } key := new(kmsaeadpb.KmsAeadKey) if err := proto.Unmarshal(protoSerializedKey, key); err != nil { return nil, errors.New("kmsaead.keyManager: invalid key") } err := keyset.ValidateKeyVersion(key.Version, 0) if err != nil { return nil, errors.New("kmsaead.keyManager: invalid version") } uri := key.GetParams().GetKeyUri() kmsClient, err := registry.GetKMSClient(uri) if err != nil { return nil, err } return kmsClient.GetAEAD(uri) } func (km *keyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errors.New("kmsaead.keyManager: invalid key format") } keyFormat := new(kmsaeadpb.KmsAeadKeyFormat) if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, errors.New("kmsaead.keyManager: invalid key format") } return &kmsaeadpb.KmsAeadKey{ Version: 0, Params: keyFormat, }, nil } func (km *keyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { key, err := km.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: kmsAEADTypeURL, Value: serializedKey, KeyMaterialType: tinkpb.KeyData_REMOTE, }, nil } func (km *keyManager) DoesSupport(typeURL string) bool { return typeURL == kmsAEADTypeURL } func (km *keyManager) TypeURL() string { return kmsAEADTypeURL } // NewKeyManager returns a new KeyManager for the KMS AEAD key type. func NewKeyManager() registry.KeyManager { return new(keyManager) } // CreateKeyTemplate creates a new KMS AEAD key template. func CreateKeyTemplate(uri string) (*tinkpb.KeyTemplate, error) { f := &kmsaeadpb.KmsAeadKeyFormat{KeyUri: uri} serializedFormat, err := proto.Marshal(f) if err != nil { return nil, fmt.Errorf("failed to marshal key format: %s", err) } return &tinkpb.KeyTemplate{ Value: serializedFormat, TypeUrl: kmsAEADTypeURL, OutputPrefixType: tinkpb.OutputPrefixType_RAW, }, nil } ================================================ FILE: go/aead/internal/testing/kmsaead/key_manager_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package kmsaead_test import ( "bytes" "testing" "github.com/google/tink/go/aead" "github.com/google/tink/go/aead/internal/testing/kmsaead" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/keyset" "github.com/google/tink/go/testing/fakekms" ) // The fake KMS should only be used in tests. It is not secure. const keyURI = "fake-kms://CM2b3_MDElQKSAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuQWVzR2NtS2V5EhIaEIK75t5L-adlUwVhWvRuWUwYARABGM2b3_MDIAE" func TestCreateEncryptDecrypt(t *testing.T) { registry.RegisterKeyManager(kmsaead.NewKeyManager()) client, err := fakekms.NewClient(keyURI) if err != nil { t.Fatalf("fakekms.NewClient(keyURI) err = %q, want nil", err) } registry.RegisterKMSClient(client) template, err := kmsaead.CreateKeyTemplate(keyURI) if err != nil { t.Fatalf("kmsaead.CreateKeyTemplate(keyURI) err = %q, want nil", err) } handle, err := keyset.NewHandle(template) if err != nil { t.Fatalf("keyset.NewHandle(template) err = %q, want nil", err) } primitive, err := aead.New(handle) if err != nil { t.Fatalf("aead.New(handle) err = %q, want nil", err) } plaintext := []byte("plaintext") associatedData := []byte("associatedData") ciphertext, err := primitive.Encrypt(plaintext, associatedData) if err != nil { t.Fatalf("primitive.Encrypt(plaintext, associatedData) err = %q, want nil", err) } gotPlaintext, err := primitive.Decrypt(ciphertext, associatedData) if err != nil { t.Fatalf("primitive.Decrypt(ciphertext, associatedData) err = %q, want nil", err) } if !bytes.Equal(gotPlaintext, plaintext) { t.Fatalf("gotPlaintext = %q, want %q", gotPlaintext, plaintext) } _, err = primitive.Decrypt(ciphertext, []byte("invalidAssociatedData")) if err == nil { t.Fatalf("primitive.Decrypt(ciphertext, []byte(\"invalidAssociatedData\")) err = nil, want error") } // Verify that the AEAD primitive returned by client is also able to decrypt. primitive2, err := client.GetAEAD(keyURI) if err != nil { t.Fatalf("client.GetAEAD(keyURI) err = %q, want nil", err) } gotPlaintext2, err := primitive2.Decrypt(ciphertext, associatedData) if err != nil { t.Fatalf("primitive2.Decrypt(ciphertext, associatedData) err = %q, want nil", err) } if !bytes.Equal(gotPlaintext2, plaintext) { t.Fatalf("gotPlaintext2 = %q, want %q", gotPlaintext, plaintext) } } ================================================ FILE: go/aead/kms_envelope_aead.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead import ( "encoding/binary" "errors" "fmt" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/tink" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( lenDEK = 4 maxUint32Size = 4294967295 ) // KMSEnvelopeAEAD represents an instance of Envelope AEAD. type KMSEnvelopeAEAD struct { dekTemplate *tinkpb.KeyTemplate remote tink.AEAD // if err != nil, then the primitive will always fail with this error. // this is needed because NewKMSEnvelopeAEAD2 doesn't return an error. err error } var tinkAEADKeyTypes map[string]bool = map[string]bool{ aesCTRHMACAEADTypeURL: true, aesGCMTypeURL: true, chaCha20Poly1305TypeURL: true, xChaCha20Poly1305TypeURL: true, aesGCMSIVTypeURL: true, } func isSupporedKMSEnvelopeDEK(dekKeyTypeURL string) bool { _, found := tinkAEADKeyTypes[dekKeyTypeURL] return found } // NewKMSEnvelopeAEAD2 creates an new instance of KMSEnvelopeAEAD. // // dekTemplate must be a KeyTemplate for any of these Tink AEAD key types (any // other key template will be rejected): // - AesCtrHmacAeadKey // - AesGcmKey // - ChaCha20Poly1305Key // - XChaCha20Poly1305 // - AesGcmSivKey func NewKMSEnvelopeAEAD2(dekTemplate *tinkpb.KeyTemplate, remote tink.AEAD) *KMSEnvelopeAEAD { if !isSupporedKMSEnvelopeDEK(dekTemplate.GetTypeUrl()) { return &KMSEnvelopeAEAD{ remote: nil, dekTemplate: nil, err: fmt.Errorf("unsupported DEK key type %s", dekTemplate.GetTypeUrl()), } } return &KMSEnvelopeAEAD{ remote: remote, dekTemplate: dekTemplate, err: nil, } } // Encrypt implements the tink.AEAD interface for encryption. func (a *KMSEnvelopeAEAD) Encrypt(pt, aad []byte) ([]byte, error) { if a.err != nil { return nil, a.err } dekKeyData, err := registry.NewKeyData(a.dekTemplate) if err != nil { return nil, err } dek := dekKeyData.GetValue() encryptedDEK, err := a.remote.Encrypt(dek, []byte{}) if err != nil { return nil, err } if len(encryptedDEK) == 0 { return nil, errors.New("encrypted dek is empty") } p, err := registry.Primitive(a.dekTemplate.TypeUrl, dek) if err != nil { return nil, err } primitive, ok := p.(tink.AEAD) if !ok { return nil, errors.New("kms_envelope_aead: failed to convert AEAD primitive") } payload, err := primitive.Encrypt(pt, aad) if err != nil { return nil, err } if len(encryptedDEK) > maxUint32Size { return nil, errors.New("kms_envelope_aead: encrypted dek too large") } res := make([]byte, 0, lenDEK+len(encryptedDEK)+len(payload)) res = binary.BigEndian.AppendUint32(res, uint32(len(encryptedDEK))) res = append(res, encryptedDEK...) res = append(res, payload...) return res, nil } // Decrypt implements the tink.AEAD interface for decryption. func (a *KMSEnvelopeAEAD) Decrypt(ct, aad []byte) ([]byte, error) { if a.err != nil { return nil, a.err } // Verify we have enough bytes for the length of the encrypted DEK. if len(ct) <= lenDEK { return nil, errors.New("kms_envelope_aead: invalid ciphertext") } // Extract length of encrypted DEK and advance past that length. ed := int(binary.BigEndian.Uint32(ct[:lenDEK])) ct = ct[lenDEK:] // Verify we have enough bytes for the encrypted DEK. if ed <= 0 || len(ct) < ed { return nil, errors.New("kms_envelope_aead: invalid ciphertext") } // Extract the encrypted DEK and the payload. encryptedDEK := ct[:ed] payload := ct[ed:] ct = nil // Decrypt the DEK. dek, err := a.remote.Decrypt(encryptedDEK, []byte{}) if err != nil { return nil, err } // Get an AEAD primitive corresponding to the DEK. p, err := registry.Primitive(a.dekTemplate.TypeUrl, dek) if err != nil { return nil, fmt.Errorf("kms_envelope_aead: %s", err) } primitive, ok := p.(tink.AEAD) if !ok { return nil, errors.New("kms_envelope_aead: failed to convert AEAD primitive") } // Decrypt the payload. return primitive.Decrypt(payload, aad) } ================================================ FILE: go/aead/kms_envelope_aead_example_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead_test // [START kms-envelope-aead-example] import ( "fmt" "log" "github.com/google/tink/go/aead" "github.com/google/tink/go/testing/fakekms" ) // The fake KMS should only be used in tests. It is not secure. const keyURI = "fake-kms://CM2b3_MDElQKSAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuQWVzR2NtS2V5EhIaEIK75t5L-adlUwVhWvRuWUwYARABGM2b3_MDIAE" func Example_kmsEnvelopeAEAD() { // Get a KEK (key encryption key) AEAD. This is usually a remote AEAD to a KMS. In this example, // we use a fake KMS to avoid making RPCs. client, err := fakekms.NewClient(keyURI) if err != nil { log.Fatal(err) } kekAEAD, err := client.GetAEAD(keyURI) if err != nil { log.Fatal(err) } // Get the KMS envelope AEAD primitive. primitive := aead.NewKMSEnvelopeAEAD2(aead.AES256GCMKeyTemplate(), kekAEAD) // Use the primitive. plaintext := []byte("message") associatedData := []byte("example KMS envelope AEAD encryption") ciphertext, err := primitive.Encrypt(plaintext, associatedData) if err != nil { log.Fatal(err) } decrypted, err := primitive.Decrypt(ciphertext, associatedData) if err != nil { log.Fatal(err) } fmt.Println(string(decrypted)) // Output: message } // [END kms-envelope-aead-example] ================================================ FILE: go/aead/kms_envelope_aead_key_manager.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead import ( "errors" "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/keyset" kmsepb "github.com/google/tink/go/proto/kms_envelope_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( kmsEnvelopeAEADKeyVersion = 0 kmsEnvelopeAEADTypeURL = "type.googleapis.com/google.crypto.tink.KmsEnvelopeAeadKey" ) // kmsEnvelopeAEADKeyManager is an implementation of KeyManager interface. // It generates new KMSEnvelopeAEADKey keys and produces new instances of KMSEnvelopeAEAD subtle. type kmsEnvelopeAEADKeyManager struct{} // Primitive creates an KMSEnvelopeAEAD subtle for the given serialized KMSEnvelopeAEADKey proto. func (km *kmsEnvelopeAEADKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errors.New("kms_envelope_aead_key_manager: invalid key") } key := new(kmsepb.KmsEnvelopeAeadKey) if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errors.New("kms_envelope_aead_key_manager: invalid key") } if err := km.validateKey(key); err != nil { return nil, fmt.Errorf("kms_envelope_aead_key_manager: %v", err) } uri := key.GetParams().GetKekUri() kmsClient, err := registry.GetKMSClient(uri) if err != nil { return nil, err } backend, err := kmsClient.GetAEAD(uri) if err != nil { return nil, errors.New("kms_envelope_aead_key_manager: invalid aead backend") } return NewKMSEnvelopeAEAD2(key.GetParams().GetDekTemplate(), backend), nil } // NewKey creates a new key according to specification the given serialized KMSEnvelopeAEADKeyFormat. func (km *kmsEnvelopeAEADKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errors.New("kms_envelope_aead_key_manager: invalid key format") } keyFormat := new(kmsepb.KmsEnvelopeAeadKeyFormat) if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, errors.New("kms_envelope_aead_key_manager: invalid key format") } if err := km.validateKeyFormat(keyFormat); err != nil { return nil, fmt.Errorf("kms_envelope_aead_key_manager: %v", err) } return &kmsepb.KmsEnvelopeAeadKey{ Version: kmsEnvelopeAEADKeyVersion, Params: keyFormat, }, nil } // NewKeyData creates a new KeyData according to specification in the given serialized // KMSEnvelopeAEADKeyFormat. // It should be used solely by the key management API. func (km *kmsEnvelopeAEADKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { key, err := km.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: kmsEnvelopeAEADTypeURL, Value: serializedKey, KeyMaterialType: tinkpb.KeyData_REMOTE, }, nil } // DoesSupport indicates if this key manager supports the given key type. func (km *kmsEnvelopeAEADKeyManager) DoesSupport(typeURL string) bool { return typeURL == kmsEnvelopeAEADTypeURL } // TypeURL returns the key type of keys managed by this key manager. func (km *kmsEnvelopeAEADKeyManager) TypeURL() string { return kmsEnvelopeAEADTypeURL } // validateKey validates the given KmsEnvelopeAeadKey. func (km *kmsEnvelopeAEADKeyManager) validateKey(key *kmsepb.KmsEnvelopeAeadKey) error { if err := keyset.ValidateKeyVersion(key.Version, kmsEnvelopeAEADKeyVersion); err != nil { return err } if err := km.validateKeyFormat(key.GetParams()); err != nil { return err } return nil } func (km *kmsEnvelopeAEADKeyManager) validateKeyFormat(keyFormat *kmsepb.KmsEnvelopeAeadKeyFormat) error { dekKeyType := keyFormat.GetDekTemplate().GetTypeUrl() if !isSupporedKMSEnvelopeDEK(dekKeyType) { return fmt.Errorf("unsupported DEK key type %s. Only Tink AEAD key types are supported with KMSEnvelopeAEAD", dekKeyType) } return nil } ================================================ FILE: go/aead/kms_envelope_aead_key_manager_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead_test import ( "bytes" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/aead" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/insecurecleartextkeyset" "github.com/google/tink/go/keyset" "github.com/google/tink/go/mac" "github.com/google/tink/go/testing/fakekms" "github.com/google/tink/go/testutil" ctrpb "github.com/google/tink/go/proto/aes_ctr_go_proto" ctrhmacpb "github.com/google/tink/go/proto/aes_ctr_hmac_aead_go_proto" hmacpb "github.com/google/tink/go/proto/hmac_go_proto" kmsenvpb "github.com/google/tink/go/proto/kms_envelope_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestNewKMSEnvelopeAEADKeyWithInvalidDEK(t *testing.T) { keyURI, err := fakekms.NewKeyURI() if err != nil { t.Fatalf("fakekms.NewKeyURI() err = %v", err) } // Create a KmsEnvelopeAeadKeyFormat with a DekTemplate that is not supported. format := &kmsenvpb.KmsEnvelopeAeadKeyFormat{ KekUri: keyURI, DekTemplate: mac.HMACSHA256Tag128KeyTemplate(), } serializedFormat, err := proto.Marshal(format) if err != nil { t.Fatalf("failed to marshal key format: %s", err) } keyTemplate := &tinkpb.KeyTemplate{ Value: serializedFormat, TypeUrl: testutil.KMSEnvelopeAEADTypeURL, OutputPrefixType: tinkpb.OutputPrefixType_RAW, } _, err = keyset.NewHandle(keyTemplate) if err == nil { t.Errorf("keyset.NewHandle(keyTemplate) err = nil, want error") } } func TestNewKMSEnvelopeAEADKeyWithInvalidSerializedKeyFormat(t *testing.T) { keyURI, err := fakekms.NewKeyURI() if err != nil { t.Fatalf("fakekms.NewKeyURI() err = %v", err) } fakeClient, err := fakekms.NewClient(keyURI) if err != nil { t.Fatalf("fakekms.NewClient() err = %v", err) } registry.RegisterKMSClient(fakeClient) defer registry.ClearKMSClients() // Create DEK template with unset embedded key parameters. dekFormat := &ctrhmacpb.AesCtrHmacAeadKeyFormat{ AesCtrKeyFormat: &ctrpb.AesCtrKeyFormat{ Params: nil, KeySize: 32, }, HmacKeyFormat: &hmacpb.HmacKeyFormat{ Params: nil, KeySize: 32, }, } serializedDEKFormat, err := proto.Marshal(dekFormat) if err != nil { t.Fatalf("failed to marshal key format: %s", err) } dekTemplate := &tinkpb.KeyTemplate{ Value: serializedDEKFormat, TypeUrl: testutil.AESCTRHMACAEADTypeURL, OutputPrefixType: tinkpb.OutputPrefixType_TINK, } format := &kmsenvpb.KmsEnvelopeAeadKeyFormat{ KekUri: keyURI, DekTemplate: dekTemplate, } serializedFormat, err := proto.Marshal(format) if err != nil { t.Fatalf("failed to marshal key format: %s", err) } keyTemplate := &tinkpb.KeyTemplate{ Value: serializedFormat, TypeUrl: testutil.KMSEnvelopeAEADTypeURL, OutputPrefixType: tinkpb.OutputPrefixType_RAW, } // Currently, the DEK template isn't checked for validatiy during creation // of a KMSEnvelopeAEAD key. It's only exercised when a cryptographic // operation is attempted. // // TODO(ckl): Rework if DEK template is exercised during initialization. handle, err := keyset.NewHandle(keyTemplate) if err != nil { t.Fatalf("keyset.NewHandle(keyTemplate) err = %v, want nil", err) } a, err := aead.New(handle) if err != nil { t.Fatalf("handle.NewAEAD(keyURI) err = %v, want nil", err) } _, err = a.Encrypt([]byte{}, []byte{}) if err == nil { t.Errorf("a.Encrypt() err = nil, want error") } } func TestKMSEnvelopeAEADWithTinkPrefix(t *testing.T) { keyURI := "fake-kms://CM2b3_MDElQKSAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuQWVzR2NtS2V5EhIaEIK75t5L-adlUwVhWvRuWUwYARABGM2b3_MDIAE" client, err := fakekms.NewClient(keyURI) if err != nil { t.Fatal(err) } registry.RegisterKMSClient(client) defer registry.ClearKMSClients() // Keyset that was created with // aead.CreateKMSEnvelopeAEADKeyTemplate(keyURI, aead.AES256GCMKeyTemplate()), and then serialized // with Tink's JSON keyset witer. Then, the output prefix type was changed from "RAW" to "TINK". jsonKeysetWithTinkPrefix := `{"primaryKeyId":3980895889, "key":[{"keyData":{"typeUrl":"type.googleapis.com/google.crypto.tink.KmsEnvelopeAeadKey", "value":"EsMBCoYBZmFrZS1rbXM6Ly9DTTJiM19NREVsUUtTQW93ZEhsd1pTNW5iMjluYkdWaGNHbHpMbU52YlM5bmIyOW5iR1V1WTNKNWNIUnZMblJwYm1zdVFXVnpSMk50UzJWNUVoSWFFSUs3NXQ1TC1hZGxVd1ZoV3ZSdVdVd1lBUkFCR00yYjNfTURJQUUSOAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuQWVzR2NtS2V5EgIQIBgB", "keyMaterialType":"REMOTE"}, "status":"ENABLED", "keyId":3980895889, "outputPrefixType":"TINK"}]}` parsedHandle, err := insecurecleartextkeyset.Read( keyset.NewJSONReader(bytes.NewBuffer([]byte(jsonKeysetWithTinkPrefix)))) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } primitive, err := aead.New(parsedHandle) if err != nil { t.Fatal(err) } plaintext := []byte("message") associatedData := []byte("example KMS envelope AEAD encryption") ciphertext, err := primitive.Encrypt(plaintext, associatedData) if err != nil { t.Fatal(err) } gotPlaintext, err := primitive.Decrypt(ciphertext, associatedData) if err != nil { t.Fatal(err) } if !bytes.Equal(gotPlaintext, plaintext) { t.Fatalf("got plaintext %q, want %q", gotPlaintext, plaintext) } // Also verify that the ciphertext has a TINK prefix gotPrefix := ciphertext[:5] // The Tink prefix is 0x01 followed by the 4 bytes key ID. The key ID is 3980895889, which is // equal to 0xed47a691. wantPrefix := []byte{0x01, 0xed, 0x47, 0xa6, 0x91} if !bytes.Equal(gotPrefix, wantPrefix) { t.Fatalf("ciphertext[:5] = %q, want %q", gotPrefix, wantPrefix) } } ================================================ FILE: go/aead/kms_envelope_aead_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead_test import ( "bytes" "testing" "github.com/google/tink/go/aead" "github.com/google/tink/go/testing/fakekms" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestKMSEnvelopeWorksWithTinkKeyTemplatesAsDekTemplate(t *testing.T) { keyURI := "fake-kms://CM2b3_MDElQKSAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuQWVzR2NtS2V5EhIaEIK75t5L-adlUwVhWvRuWUwYARABGM2b3_MDIAE" client, err := fakekms.NewClient(keyURI) if err != nil { t.Fatal(err) } kekAEAD, err := client.GetAEAD(keyURI) if err != nil { t.Fatal(err) } plaintext := []byte("plaintext") associatedData := []byte("associatedData") invalidAssociatedData := []byte("invalidAssociatedData") var kmsEnvelopeAeadDekTestCases = []struct { name string dekTemplate *tinkpb.KeyTemplate }{ { name: "AES128_GCM", dekTemplate: aead.AES128GCMKeyTemplate(), }, { name: "AES256_GCM", dekTemplate: aead.AES256GCMKeyTemplate(), }, { name: "AES256_GCM_NO_PREFIX", dekTemplate: aead.AES256GCMNoPrefixKeyTemplate(), }, { name: "AES128_GCM_SIV", dekTemplate: aead.AES128GCMSIVKeyTemplate(), }, { name: "AES256_GCM_SIV", dekTemplate: aead.AES256GCMSIVKeyTemplate(), }, { name: "AES256_GCM_SIV_NO_PREFIX", dekTemplate: aead.AES256GCMSIVNoPrefixKeyTemplate(), }, { name: "AES128_CTR_HMAC_SHA256", dekTemplate: aead.AES128CTRHMACSHA256KeyTemplate(), }, { name: "AES256_CTR_HMAC_SHA256", dekTemplate: aead.AES256CTRHMACSHA256KeyTemplate(), }, { name: "CHACHA20_POLY1305", dekTemplate: aead.ChaCha20Poly1305KeyTemplate(), }, { name: "XCHACHA20_POLY1305", dekTemplate: aead.XChaCha20Poly1305KeyTemplate(), }, } for _, tc := range kmsEnvelopeAeadDekTestCases { t.Run(tc.name, func(t *testing.T) { a := aead.NewKMSEnvelopeAEAD2(tc.dekTemplate, kekAEAD) ciphertext, err := a.Encrypt(plaintext, associatedData) if err != nil { t.Fatalf("a.Encrypt(plaintext, associatedData) err = %q, want nil", err) } gotPlaintext, err := a.Decrypt(ciphertext, associatedData) if err != nil { t.Fatalf("a.Decrypt(ciphertext, associatedData) err = %q, want nil", err) } if !bytes.Equal(gotPlaintext, plaintext) { t.Fatalf("got plaintext %q, want %q", gotPlaintext, plaintext) } if _, err = a.Decrypt(ciphertext, invalidAssociatedData); err == nil { t.Error("a.Decrypt(ciphertext, invalidAssociatedData) err = nil, want error") } }) } } func TestKMSEnvelopeWithKmsEnvelopeKeyTemplatesAsDekTemplate_fails(t *testing.T) { keyURI := "fake-kms://CM2b3_MDElQKSAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuQWVzR2NtS2V5EhIaEIK75t5L-adlUwVhWvRuWUwYARABGM2b3_MDIAE" client, err := fakekms.NewClient(keyURI) if err != nil { t.Fatalf("fakekms.NewClient(keyURI) err = %q, want nil", err) } kekAEAD, err := client.GetAEAD(keyURI) if err != nil { t.Fatalf("client.GetAEAD(keyURI) err = %q, want nil", err) } plaintext := []byte("plaintext") associatedData := []byte("associatedData") // Use a KmsEnvelopeAeadKeyTemplate as DEK template. dekTemplate, err := aead.CreateKMSEnvelopeAEADKeyTemplate(keyURI, aead.AES128GCMKeyTemplate()) if err != nil { t.Fatalf("aead.CreateKMSEnvelopAEADKeyTemplate() err = %q, want nil", err) } a := aead.NewKMSEnvelopeAEAD2(dekTemplate, kekAEAD) _, err = a.Encrypt(plaintext, associatedData) if err == nil { t.Error("a.Encrypt(plaintext, associatedData) err = nil, want error") } } func TestKMSEnvelopeShortCiphertext(t *testing.T) { keyURI := "fake-kms://CM2b3_MDElQKSAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuQWVzR2NtS2V5EhIaEIK75t5L-adlUwVhWvRuWUwYARABGM2b3_MDIAE" client, err := fakekms.NewClient(keyURI) if err != nil { t.Fatal(err) } kekAEAD, err := client.GetAEAD(keyURI) if err != nil { t.Fatal(err) } a := aead.NewKMSEnvelopeAEAD2(aead.AES256GCMKeyTemplate(), kekAEAD) if _, err = a.Decrypt([]byte{1}, nil); err == nil { t.Error("a.Decrypt([]byte{1}, nil) err = nil, want error") } } type invalidAEAD struct { } func (a *invalidAEAD) Encrypt(plaintext, associatedData []byte) ([]byte, error) { return []byte{}, nil } func (a *invalidAEAD) Decrypt(ciphertext, associatedData []byte) ([]byte, error) { return []byte{}, nil } func TestKMSEnvelopeEncryptWithInvalidAEADFails(t *testing.T) { invalidKEKAEAD := &invalidAEAD{} envAEADWithInvalidKEK := aead.NewKMSEnvelopeAEAD2(aead.AES256GCMKeyTemplate(), invalidKEKAEAD) if _, err := envAEADWithInvalidKEK.Encrypt([]byte("plaintext"), []byte("associatedData")); err == nil { t.Error("envAEADWithInvalidKEK.Encrypt(plaintext, associatedData) err = nil, want error") } } ================================================ FILE: go/aead/subtle/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep go_library( name = "subtle", srcs = [ "aes_ctr.go", "aes_gcm.go", "aes_gcm_siv.go", "chacha20poly1305.go", "encrypt_then_authenticate.go", "ind_cpa.go", "polyval.go", "subtle.go", "xchacha20poly1305.go", ], importpath = "github.com/google/tink/go/aead/subtle", visibility = ["//visibility:public"], deps = [ "//internal/aead", "//subtle/random", "//tink", "@org_golang_x_crypto//chacha20poly1305", ], ) go_test( name = "subtle_test", srcs = [ "aes_ctr_test.go", "aes_gcm_siv_test.go", "aes_gcm_test.go", "chacha20poly1305_test.go", "chacha20poly1305_vectors_test.go", "encrypt_then_authenticate_test.go", "polyval_test.go", "subtle_test.go", "xchacha20poly1305_test.go", "xchacha20poly1305_vectors_test.go", ], data = [ "//testdata/testvectors:aes_gcm", "//testdata/testvectors:aes_gcm_siv", "//testdata/testvectors:chacha20_poly1305", ], deps = [ ":subtle", "//mac/subtle", "//subtle/random", "//testutil", "//tink", "@org_golang_x_crypto//chacha20poly1305", ], ) alias( name = "go_default_library", actual = ":subtle", visibility = ["//:__subpackages__"], ) ================================================ FILE: go/aead/subtle/aes_ctr.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "crypto/aes" "crypto/cipher" "fmt" // Placeholder for internal crypto/cipher allowlist, please ignore. "github.com/google/tink/go/subtle/random" ) const ( // AESCTRMinIVSize is the minimum IV size that this implementation supports. AESCTRMinIVSize = 12 ) // AESCTR is an implementation of AEAD interface. type AESCTR struct { key []byte IVSize int } // NewAESCTR returns an AESCTR instance. // The key argument should be the AES key, either 16 or 32 bytes to select // AES-128 or AES-256. // ivSize specifies the size of the IV in bytes. func NewAESCTR(key []byte, ivSize int) (*AESCTR, error) { keySize := uint32(len(key)) if err := ValidateAESKeySize(keySize); err != nil { return nil, fmt.Errorf("aes_ctr: %s", err) } if ivSize < AESCTRMinIVSize || ivSize > aes.BlockSize { return nil, fmt.Errorf("aes_ctr: invalid IV size: %d", ivSize) } return &AESCTR{key: key, IVSize: ivSize}, nil } // Encrypt encrypts plaintext using AES in CTR mode. // The resulting ciphertext consists of two parts: // (1) the IV used for encryption and (2) the actual ciphertext. func (a *AESCTR) Encrypt(plaintext []byte) ([]byte, error) { if len(plaintext) > maxInt-a.IVSize { return nil, fmt.Errorf("aes_ctr: plaintext too long") } iv := a.newIV() stream, err := newCipher(a.key, iv) if err != nil { return nil, err } ciphertext := make([]byte, a.IVSize+len(plaintext)) if n := copy(ciphertext, iv); n != a.IVSize { return nil, fmt.Errorf("aes_ctr: failed to copy IV (copied %d/%d bytes)", n, a.IVSize) } stream.XORKeyStream(ciphertext[a.IVSize:], plaintext) return ciphertext, nil } // Decrypt decrypts ciphertext. func (a *AESCTR) Decrypt(ciphertext []byte) ([]byte, error) { if len(ciphertext) < a.IVSize { return nil, fmt.Errorf("aes_ctr: ciphertext too short") } iv := ciphertext[:a.IVSize] stream, err := newCipher(a.key, iv) if err != nil { return nil, err } plaintext := make([]byte, len(ciphertext)-a.IVSize) stream.XORKeyStream(plaintext, ciphertext[a.IVSize:]) return plaintext, nil } // newIV creates a new IV for encryption. func (a *AESCTR) newIV() []byte { return random.GetRandomBytes(uint32(a.IVSize)) } // newCipher creates a new AES-CTR cipher using the given key, IV and the crypto library. func newCipher(key, iv []byte) (cipher.Stream, error) { block, err := aes.NewCipher(key) if err != nil { return nil, fmt.Errorf("aes_ctr: failed to create block cipher, error: %v", err) } // If the IV is less than BlockSize bytes we need to pad it with zeros // otherwise NewCTR will panic. if len(iv) < aes.BlockSize { paddedIV := make([]byte, aes.BlockSize) if n := copy(paddedIV, iv); n != len(iv) { return nil, fmt.Errorf("aes_ctr: failed to pad IV") } return cipher.NewCTR(block, paddedIV), nil } return cipher.NewCTR(block, iv), nil } ================================================ FILE: go/aead/subtle/aes_ctr_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "bytes" "crypto/aes" "encoding/hex" "strings" "testing" "github.com/google/tink/go/aead/subtle" "github.com/google/tink/go/subtle/random" ) func TestNewAESCTR(t *testing.T) { key := make([]byte, 64) // Test various key sizes with a fixed IV size. for i := 0; i < 64; i++ { k := key[:i] c, err := subtle.NewAESCTR(k, subtle.AESCTRMinIVSize) switch len(k) { case 16: fallthrough case 32: // Valid key sizes. if err != nil { t.Errorf("want: valid cipher (key size=%d), got: error %v", len(k), err) } if c.IVSize != subtle.AESCTRMinIVSize { t.Errorf("want: IV size=%d, got: IV size=%d", subtle.AESCTRMinIVSize, c.IVSize) } default: // Invalid key sizes. if !strings.Contains(err.Error(), "aes_ctr: invalid AES key size; want 16 or 32") { t.Errorf("wrong error message; want a string starting with \"aes_ctr: invalid AES key size; want 16 or 32\", got %v", err) } } } // Test different IV sizes with a fixed key. for i := 0; i < 64; i++ { k := key[:16] c, err := subtle.NewAESCTR(k, i) if i >= subtle.AESCTRMinIVSize && i <= aes.BlockSize { if err != nil { t.Errorf("want: valid cipher (IV size=%d), got: error %v", i, err) } if c.IVSize != i { t.Errorf("want: IV size=%d, got: IV size=%d", i, c.IVSize) } continue } if !strings.Contains(err.Error(), "aes_ctr: invalid IV size:") { t.Errorf("want: error invalid IV size, got: %v", err) } } } func TestNistTestVector(t *testing.T) { // NIST SP 800-38A pp 55 key, err := hex.DecodeString("2b7e151628aed2a6abf7158809cf4f3c") if err != nil { t.Fatalf("failed to hex decode key, error: %v", err) } // NIST IV iv := "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff" // NIST ciphertext blocks c := "874d6191b620e3261bef6864990db6ce" + "9806f66b7970fdff8617187bb9fffdff" + "5ae4df3edbd5d35e5b4f09020db03eab" + "1e031dda2fbe03d1792170a0f3009cee" ciphertext, err := hex.DecodeString(iv + c) if err != nil { t.Fatalf("failed to hex decode ciphertext, error: %v", err) } // NIST plaintext blocks p := "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710" message, err := hex.DecodeString(p) if err != nil { t.Fatalf("failed to hex decode message, error: %v", err) } stream, err := subtle.NewAESCTR(key, len(iv)/2) if err != nil { t.Fatalf("failed to create AESCTR instance, error: %v", err) } plaintext, err := stream.Decrypt(ciphertext) if err != nil { t.Errorf("failed to decrypt ciphertext, error: %v", err) } if !bytes.Equal(plaintext, message) { t.Errorf("plaintext doesn't match message") } } func TestMultipleEncrypt(t *testing.T) { key := random.GetRandomBytes(16) stream, err := subtle.NewAESCTR(key, subtle.AESCTRMinIVSize) if err != nil { t.Fatalf("failed to create AESCTR instance, error: %v", err) } plaintext := []byte("Some data to encrypt.") ct1, err := stream.Encrypt(plaintext) if err != nil { t.Errorf("encryption failed, error: %v", err) } ct2, err := stream.Encrypt(plaintext) if err != nil { t.Errorf("encryption failed, error: %v", err) } if bytes.Equal(ct1, ct2) { t.Error("the two ciphertexts cannot be equal") } // Encrypt 100 times and verify that the result is 100 different ciphertexts. ciphertexts := map[string]bool{} for i := 0; i < 100; i++ { c, err := stream.Encrypt(plaintext) if err != nil { t.Errorf("encryption failed for iteration %d, error: %v", i, err) } ciphertexts[string(c)] = true } if len(ciphertexts) != 100 { t.Errorf("got: %d ciphertexts, want: 100 ciphertexts", len(ciphertexts)) } } func TestEncryptDecrypt(t *testing.T) { key, err := hex.DecodeString("000102030405060708090a0b0c0d0e0f") if err != nil { t.Fatal("failed to hex decode key") } stream, err := subtle.NewAESCTR(key, subtle.AESCTRMinIVSize) if err != nil { t.Fatalf("failed to get AESCTR instance, error: %v", err) } message := []byte("Some data to encrypt.") ciphertext, err := stream.Encrypt(message) if err != nil { t.Errorf("encryption failed, error: %v", err) } if len(ciphertext) != len(message)+subtle.AESCTRMinIVSize { t.Errorf("ciphertext incorrect size, got: %d, want: %d", len(ciphertext), len(message)+subtle.AESCTRMinIVSize) } plaintext, err := stream.Decrypt(ciphertext) if err != nil { t.Errorf("decryption failed, error: %v", err) } if !bytes.Equal(message, plaintext) { t.Errorf("decryption result mismatch, got: %v, want: %v", plaintext, message) } } func TestEncryptRandomMessage(t *testing.T) { key := random.GetRandomBytes(16) stream, err := subtle.NewAESCTR(key, subtle.AESCTRMinIVSize) if err != nil { t.Errorf("failed to instantiate AESCTR, error: %v", err) } for i := 0; i < 256; i++ { message := random.GetRandomBytes(uint32(i)) ciphertext, err := stream.Encrypt(message) if err != nil { t.Errorf("encryption failed at iteration %d, error: %v", i, err) } if len(ciphertext) != len(message)+subtle.AESCTRMinIVSize { t.Errorf("invalid ciphertext length for i = %d", i) } plaintext, err := stream.Decrypt(ciphertext) if err != nil { t.Errorf("decryption failed at iteration %d, error: %v", i, err) } if !bytes.Equal(plaintext, message) { t.Errorf("plaintext doesn't match message, i = %d", i) } } } func TestEncryptRandomKeyAndMessage(t *testing.T) { for i := 0; i < 256; i++ { key := random.GetRandomBytes(16) stream, err := subtle.NewAESCTR(key, subtle.AESCTRMinIVSize) if err != nil { t.Errorf("failed to instantiate AESCTR, error: %v", err) } message := random.GetRandomBytes(uint32(i)) ciphertext, err := stream.Encrypt(message) if err != nil { t.Errorf("encryption failed at iteration %d, error: %v", i, err) } if len(ciphertext) != len(message)+subtle.AESCTRMinIVSize { t.Errorf("invalid ciphertext length for i = %d", i) } plaintext, err := stream.Decrypt(ciphertext) if err != nil { t.Errorf("decryption failed at iteration %d, error: %v", i, err) } if !bytes.Equal(plaintext, message) { t.Errorf("plaintext doesn't match message, i = %d", i) } } } ================================================ FILE: go/aead/subtle/aes_gcm.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "fmt" internalaead "github.com/google/tink/go/internal/aead" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/tink" ) const ( // AESGCMIVSize is the acceptable IV size defined by RFC 5116. AESGCMIVSize = 12 // AESGCMTagSize is the acceptable tag size defined by RFC 5116. AESGCMTagSize = 16 ) // AESGCM is an implementation of AEAD interface. type AESGCM struct { aesGCMInsecureIV *internalaead.AESGCMInsecureIV } // Assert that AESGCM implements the AEAD interface. var _ tink.AEAD = (*AESGCM)(nil) // NewAESGCM returns an AESGCM instance, where key is the AES key with length // 16 bytes (AES-128) or 32 bytes (AES-256). func NewAESGCM(key []byte) (*AESGCM, error) { aesGCMInsecureIV, err := internalaead.NewAESGCMInsecureIV(key, true /*=prependIV*/) return &AESGCM{aesGCMInsecureIV}, err } // Encrypt encrypts plaintext with associatedData. The returned ciphertext // contains both the IV used for encryption and the actual ciphertext. // // Note: The crypto library's AES-GCM implementation always returns the // ciphertext with an AESGCMTagSize (16-byte) tag. func (a *AESGCM) Encrypt(plaintext, associatedData []byte) ([]byte, error) { iv := random.GetRandomBytes(AESGCMIVSize) return a.aesGCMInsecureIV.Encrypt(iv, plaintext, associatedData) } // Decrypt decrypts ciphertext with associatedData. func (a *AESGCM) Decrypt(ciphertext, associatedData []byte) ([]byte, error) { if len(ciphertext) < AESGCMIVSize { return nil, fmt.Errorf("ciphertext with size %d is too short", len(ciphertext)) } iv := ciphertext[:AESGCMIVSize] return a.aesGCMInsecureIV.Decrypt(iv, ciphertext, associatedData) } ================================================ FILE: go/aead/subtle/aes_gcm_siv.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "crypto/aes" "crypto/subtle" "encoding/binary" "fmt" "math" // Placeholder for internal crypto/cipher allowlist, please ignore. // Placeholder for internal crypto/subtle allowlist, please ignore. // to allow import of "crypto/subte" "github.com/google/tink/go/subtle/random" ) const ( // AESGCMSIVNonceSize is the acceptable IV size defined by RFC 8452. AESGCMSIVNonceSize = 12 // aesgcmsivBlockSize is the block size that AES-GCM-SIV uses. This is the // size for the tag, the KDF etc. // Note: this value is the same as AES block size. aesgcmsivBlockSize = 16 // aesgcmsivTagSize is the byte-length of the authentication tag produced by // AES-GCM-SIV. aesgcmsivTagSize = aesgcmsivBlockSize // aesgcmsivPolyvalSize is the byte-length of result produced by the // POLYVAL function. aesgcmsivPolyvalSize = aesgcmsivBlockSize ) // AESGCMSIV is an implementation of AEAD interface. type AESGCMSIV struct { key []byte } // NewAESGCMSIV returns an AESGCMSIV instance. // The key argument should be the AES key, either 16 or 32 bytes to select // AES-128 or AES-256. func NewAESGCMSIV(key []byte) (*AESGCMSIV, error) { keySize := uint32(len(key)) if err := ValidateAESKeySize(keySize); err != nil { return nil, fmt.Errorf("aes_gcm_siv: %s", err) } return &AESGCMSIV{key: key}, nil } // Encrypt encrypts plaintext with associatedData. // // The resulting ciphertext consists of three parts: // (1) the Nonce used for encryption // (2) the actual ciphertext // (3) the authentication tag. func (a *AESGCMSIV) Encrypt(plaintext, associatedData []byte) ([]byte, error) { if len(plaintext) > math.MaxInt32-AESGCMSIVNonceSize-aesgcmsivTagSize { return nil, fmt.Errorf("aes_gcm_siv: plaintext too long") } if len(associatedData) > math.MaxInt32 { return nil, fmt.Errorf("aes_gcm_siv: associatedData too long") } nonce := random.GetRandomBytes(uint32(AESGCMSIVNonceSize)) authKey, encKey, err := a.deriveKeys(nonce) if err != nil { return nil, err } polyval, err := a.computePolyval(authKey, plaintext, associatedData) if err != nil { return nil, err } tag, err := a.computeTag(polyval, nonce, encKey) if err != nil { return nil, err } ct, err := a.aesCTR(encKey, tag, plaintext) if err != nil { return nil, err } ret := make([]byte, 0, AESGCMSIVNonceSize+aesgcmsivTagSize+len(plaintext)) ret = append(ret, nonce...) ret = append(ret, ct...) ret = append(ret, tag...) return ret, nil } // Decrypt decrypts ciphertext with associatedData. func (a *AESGCMSIV) Decrypt(ciphertext, associatedData []byte) ([]byte, error) { if len(ciphertext) < AESGCMSIVNonceSize+aesgcmsivTagSize { return nil, fmt.Errorf("aes_gcm_siv: ciphertext too short") } if len(ciphertext) > math.MaxInt32 { return nil, fmt.Errorf("aes_gcm_siv: ciphertext too long") } if len(associatedData) > math.MaxInt32 { return nil, fmt.Errorf("aes_gcm_siv: associatedData too long") } nonce := ciphertext[:AESGCMSIVNonceSize] tag := ciphertext[len(ciphertext)-aesgcmsivTagSize:] ciphertext = ciphertext[AESGCMSIVNonceSize : len(ciphertext)-aesgcmsivTagSize] authKey, encKey, err := a.deriveKeys(nonce) if err != nil { return nil, err } pt, err := a.aesCTR(encKey, tag, ciphertext) if err != nil { return nil, err } polyval, err := a.computePolyval(authKey, pt, associatedData) if err != nil { return nil, err } expectedTag, err := a.computeTag(polyval, nonce, encKey) if err != nil { return nil, err } if subtle.ConstantTimeCompare(expectedTag, tag) != 1 { return nil, fmt.Errorf("aes_gcm_siv: message authentication failure") } return pt, nil } // The KDF as described by the RFC #8452. This uses the AES-GCM-SIV key and // nonce to generate the authentication key and the encryption key. func (a *AESGCMSIV) deriveKeys(nonce []byte) ([]byte, []byte, error) { if len(nonce) != AESGCMSIVNonceSize { return nil, nil, fmt.Errorf("aes_gcm_siv: invalid nonce size") } nonceBlock := make([]byte, aesgcmsivBlockSize) copy(nonceBlock[aesgcmsivBlockSize-AESGCMSIVNonceSize:], nonce) block, err := aes.NewCipher(a.key) if err != nil { return nil, nil, fmt.Errorf("aes_gcm_siv: failed to create block cipher, error: %v", err) } encBlock := make([]byte, block.BlockSize()) kdfAes := func(counter uint32, dst []byte) { binary.LittleEndian.PutUint32(nonceBlock[:4], counter) block.Encrypt(encBlock, nonceBlock) copy(dst, encBlock[0:8]) } authKey := make([]byte, aesgcmsivBlockSize) kdfAes(0, authKey[0:8]) kdfAes(1, authKey[8:16]) encKey := make([]byte, len(a.key)) kdfAes(2, encKey[0:8]) kdfAes(3, encKey[8:16]) if len(a.key) == 32 { kdfAes(4, encKey[16:24]) kdfAes(5, encKey[24:32]) } return authKey, encKey, nil } func (a *AESGCMSIV) computePolyval(authKey, pt, ad []byte) ([]byte, error) { lengthBlock := make([]byte, aesgcmsivBlockSize) binary.LittleEndian.PutUint64(lengthBlock[:8], uint64(len(ad))*8) binary.LittleEndian.PutUint64(lengthBlock[8:], uint64(len(pt))*8) p, err := NewPolyval(authKey) if err != nil { return nil, fmt.Errorf("aes_gcm_siv: failed to create polyval, error: %v", err) } p.Update(ad) p.Update(pt) p.Update(lengthBlock) polyval := p.Finish() return polyval[:], nil } func (a *AESGCMSIV) computeTag(polyval, nonce, encKey []byte) ([]byte, error) { if len(polyval) != aesgcmsivPolyvalSize { return nil, fmt.Errorf("aes_gcm_siv: polyval returned invalid sized response") } for i, val := range nonce { polyval[i] ^= val } polyval[aesgcmsivPolyvalSize-1] &= 0x7f block, err := aes.NewCipher(encKey) if err != nil { return nil, fmt.Errorf("aes_gcm_siv: failed to create block cipher, error: %v", err) } tag := make([]byte, aesgcmsivTagSize) block.Encrypt(tag, polyval) return tag, nil } // aesCTR implements the AES-CTR operation in AES-GCM-SIV. // Note that RFC 8452 defines AES-CTR differently compared to standard AES // in CTR mode: the way they increment the counter block is completely different. func (a *AESGCMSIV) aesCTR(key, tag, in []byte) ([]byte, error) { if len(tag) != aesgcmsivTagSize { return nil, fmt.Errorf("aes_gcm_siv: incorrect IV size for stream cipher") } block, err := aes.NewCipher(key) if err != nil { return nil, fmt.Errorf( "aes_gcm_siv: failed to create block cipher, error: %v", err) } counter := make([]byte, aesgcmsivBlockSize) copy(counter, tag) counter[aesgcmsivBlockSize-1] |= 0x80 counterInc := binary.LittleEndian.Uint32(counter[0:4]) output := make([]byte, len(in)) outputIdx := 0 keystreamBlock := make([]byte, block.BlockSize()) for len(in) > 0 { block.Encrypt(keystreamBlock, counter) counterInc++ binary.LittleEndian.PutUint32(counter[0:4], counterInc) n := xorBytes(output[outputIdx:], in, keystreamBlock) outputIdx += n in = in[n:] } return output, nil } // It would have been better to call xorBytes function defined in // "crypto/cipher/xor_*.go" to make use of the architechture optimisations. func xorBytes(dst, a, b []byte) int { n := len(a) if len(b) < n { n = len(b) } if n == 0 { return 0 } for i := 0; i < n; i++ { dst[i] = a[i] ^ b[i] } return n } ================================================ FILE: go/aead/subtle/aes_gcm_siv_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "bytes" "encoding/hex" "fmt" "testing" "github.com/google/tink/go/aead/subtle" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" ) func TestAESGCMSIVRejectsInvalidKeyLength(t *testing.T) { invalidKeySizes := []uint32{4, 8, 12, 15, 17, 24, 30, 31, 33, 64, 128} for _, keySize := range invalidKeySizes { key := random.GetRandomBytes(keySize) if _, err := subtle.NewAESGCMSIV(key); err == nil { t.Errorf("expected error with invalid key-size %d", keySize) } } } func TestAESGCMSIVRandomNonceProducesDifferentCiphertexts(t *testing.T) { nSample := 1 << 17 key := random.GetRandomBytes(16) pt := []byte{} ad := []byte{} a, err := subtle.NewAESGCMSIV(key) if err != nil { t.Fatalf("subtle.NewAESGCMSIV() err = %v, want nil", err) } ctSet := make(map[string]bool) for i := 0; i < nSample; i++ { ct, err := a.Encrypt(pt, ad) if err != nil { t.Fatalf("a.Encrypt() err = %v, want nil", err) } ctHex := hex.EncodeToString(ct) if _, existed := ctSet[ctHex]; existed { t.Errorf("nonce is repeated after %d samples", i) } ctSet[ctHex] = true } } func TestAESGCMSIVModifyCiphertext(t *testing.T) { ad := random.GetRandomBytes(33) key := random.GetRandomBytes(16) pt := random.GetRandomBytes(32) a, err := subtle.NewAESGCMSIV(key) if err != nil { t.Fatalf("subtle.NewAESGCMSIV() err = %v, want nil", err) } ct, err := a.Encrypt(pt, ad) if err != nil { t.Fatalf("a.Encrypt() err = %v, want nil", err) } // flipping bits for i := 0; i < len(ct); i++ { tmp := ct[i] for j := 0; j < 8; j++ { ct[i] ^= 1 << uint8(j) if _, err := a.Decrypt(ct, ad); err == nil { t.Errorf("expect an error when flipping bit of ciphertext: byte %d, bit %d", i, j) } ct[i] = tmp } } // truncated ciphertext for i := 1; i < len(ct); i++ { if _, err := a.Decrypt(ct[:i], ad); err == nil { t.Errorf("expect an error ciphertext is truncated until byte %d", i) } } // modify associated data for i := 0; i < len(ad); i++ { tmp := ad[i] for j := 0; j < 8; j++ { ad[i] ^= 1 << uint8(j) if _, err := a.Decrypt(ct, ad); err == nil { t.Errorf("expect an error when flipping bit of ad: byte %d, bit %d", i, j) } ad[i] = tmp } } } func TestAESGCMSIVWycheproofCases(t *testing.T) { testutil.SkipTestIfTestSrcDirIsNotSet(t) suite := new(AEADSuite) if err := testutil.PopulateSuite(suite, "aes_gcm_siv_test.json"); err != nil { t.Fatalf("failed populating suite: %s", err) } for _, group := range suite.TestGroups { for _, test := range group.Tests { caseName := fmt.Sprintf("%s-%s(%d):Case-%d", suite.Algorithm, group.Type, group.KeySize, test.CaseID) t.Run("DecryptOnly/"+caseName, func(t *testing.T) { runWycheproofDecryptOnly(t, test) }) t.Run("EncryptDecrypt/"+caseName, func(t *testing.T) { runWycheproofEncryptDecrypt(t, test) }) } } } func runWycheproofDecryptOnly(t *testing.T, testCase *AEADCase) { aead, err := subtle.NewAESGCMSIV(testCase.Key) if err != nil { t.Fatalf("cannot create aead, error: %v", err) } var combinedCt []byte combinedCt = append(combinedCt, testCase.Iv...) combinedCt = append(combinedCt, testCase.Ct...) combinedCt = append(combinedCt, testCase.Tag...) decrypted, err := aead.Decrypt(combinedCt, testCase.Aad) switch testCase.Result { case "valid": if err != nil { t.Errorf("unexpected error in test-case: %v", err) } else if !bytes.Equal(decrypted, testCase.Msg) { t.Errorf( "incorrect decryption: actual: %s; expected %s", hex.EncodeToString(decrypted), hex.EncodeToString(testCase.Msg)) } case "invalid": if err == nil && bytes.Equal(testCase.Ct, decrypted) { t.Error("successfully decrypted invalid test-case") } default: t.Errorf("unknown test-case result: %s", testCase.Result) } } func runWycheproofEncryptDecrypt(t *testing.T, testCase *AEADCase) { aead, err := subtle.NewAESGCMSIV(testCase.Key) if err != nil { t.Fatalf("cannot create aead, error: %v", err) } ct, err := aead.Encrypt(testCase.Msg, testCase.Aad) if err != nil { if testCase.Result != "invalid" { t.Errorf("unexpected error in test-case: %v", err) } return } decrypted, err := aead.Decrypt(ct, testCase.Aad) switch testCase.Result { case "valid": if err != nil { t.Errorf("unexpected error in test-case: %v", err) } else if !bytes.Equal(decrypted, testCase.Msg) { t.Errorf( "incorrect decryption: actual: %s; expected %s", hex.EncodeToString(decrypted), hex.EncodeToString(testCase.Msg)) } case "invalid": if err == nil && bytes.Equal(ct, decrypted) { t.Error("successfully decrypted invalid test-case") } default: t.Errorf("unknown test-case result: %s", testCase.Result) } } ================================================ FILE: go/aead/subtle/aes_gcm_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "bytes" "encoding/hex" "fmt" "testing" "github.com/google/tink/go/aead/subtle" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" ) var aesKeySizes = []uint32{ 16, /*AES-128*/ 32, /*AES-256*/ } // Since the tag size depends on the Seal() function of crypto library, // this test checks that the tag size is always 128 bit. func TestAESGCMTagLength(t *testing.T) { for _, keySize := range aesKeySizes { key := random.GetRandomBytes(keySize) a, err := subtle.NewAESGCM(key) if err != nil { t.Fatalf("subtle.NewAESGCM() err = %q, want nil", err) } ad := random.GetRandomBytes(32) pt := random.GetRandomBytes(32) ct, err := a.Encrypt(pt, ad) if err != nil { t.Fatalf("a.Encrypt() err = %q, want nil", err) } actualTagSize := len(ct) - subtle.AESGCMIVSize - len(pt) if actualTagSize != subtle.AESGCMTagSize { t.Errorf("tag size is not 128 bit, it is %d bit", actualTagSize*8) } } } func TestAESGCMKeySize(t *testing.T) { for _, keySize := range aesKeySizes { if _, err := subtle.NewAESGCM(make([]byte, keySize)); err != nil { t.Errorf("unexpected error when key size is %d btyes", keySize) } if _, err := subtle.NewAESGCM(make([]byte, keySize+1)); err == nil { t.Errorf("expect an error when key size is not supported %d", keySize) } } } func TestAESGCMEncryptDecrypt(t *testing.T) { for _, keySize := range aesKeySizes { key := random.GetRandomBytes(keySize) a, err := subtle.NewAESGCM(key) if err != nil { t.Errorf("unexpected error when creating new cipher: %s", err) } ad := random.GetRandomBytes(5) for ptSize := 0; ptSize < 75; ptSize++ { pt := random.GetRandomBytes(uint32(ptSize)) ct, err := a.Encrypt(pt, ad) if err != nil { t.Errorf("unexpected error in encryption: keySize %v, ptSize %v", keySize, ptSize) } decrypted, err := a.Decrypt(ct, ad) if err != nil { t.Errorf("unexpected error in decryption: keySize %v, ptSize %v", keySize, ptSize) } if !bytes.Equal(pt, decrypted) { t.Errorf("decrypted text and plaintext don't match: keySize %v, ptSize %v", keySize, ptSize) } } } } func TestAESGCMLongMessages(t *testing.T) { ptSize := 16 for ptSize <= 1<<24 { pt := random.GetRandomBytes(uint32(ptSize)) ad := random.GetRandomBytes(uint32(ptSize / 3)) for _, keySize := range aesKeySizes { key := random.GetRandomBytes(keySize) a, err := subtle.NewAESGCM(key) if err != nil { t.Fatalf("subtle.NewAESGCM() err = %q, want nil", err) } ct, err := a.Encrypt(pt, ad) if err != nil { t.Fatalf("a.Encrypt() err = %q, want nil", err) } decrypted, err := a.Decrypt(ct, ad) if err != nil { t.Fatalf("a.Decrypt() err = %q, want nil", err) } if !bytes.Equal(pt, decrypted) { t.Errorf("decrypted text and plaintext don't match: keySize %v, ptSize %v", keySize, ptSize) } } ptSize += 5 * ptSize / 11 } } func TestAESGCMModifyCiphertext(t *testing.T) { ad := random.GetRandomBytes(33) key := random.GetRandomBytes(16) pt := random.GetRandomBytes(32) a, err := subtle.NewAESGCM(key) if err != nil { t.Fatalf("subtle.NewAESGCM() err = %q, want nil", err) } ct, err := a.Encrypt(pt, ad) if err != nil { t.Fatalf("a.Encrypt() err = %q, want nil", err) } // flipping bits for i := 0; i < len(ct); i++ { tmp := ct[i] for j := 0; j < 8; j++ { ct[i] ^= 1 << uint8(j) if _, err := a.Decrypt(ct, ad); err == nil { t.Errorf("expect an error when flipping bit of ciphertext: byte %d, bit %d", i, j) } ct[i] = tmp } } // truncated ciphertext for i := 1; i < len(ct); i++ { if _, err := a.Decrypt(ct[:i], ad); err == nil { t.Errorf("expect an error ciphertext is truncated until byte %d", i) } } // modify associated data for i := 0; i < len(ad); i++ { tmp := ad[i] for j := 0; j < 8; j++ { ad[i] ^= 1 << uint8(j) if _, err := a.Decrypt(ct, ad); err == nil { t.Errorf("expect an error when flipping bit of ad: byte %d, bit %d", i, j) } ad[i] = tmp } } // replace ciphertext with a random string with a small, unacceptable size for _, ctSize := range []uint32{subtle.AESGCMIVSize / 2, subtle.AESGCMIVSize - 1} { smallCT := random.GetRandomBytes(ctSize) emptyAD := []byte{} if _, err := a.Decrypt(smallCT, emptyAD); err == nil { t.Error("Decrypt: got success, want err") } } } /** * This is a very simple test for the randomness of the nonce. * The test simply checks that the multiple ciphertexts of the same * message are distinct. */ func TestAESGCMRandomNonce(t *testing.T) { nSample := 1 << 17 key := random.GetRandomBytes(16) pt := []byte{} ad := []byte{} a, err := subtle.NewAESGCM(key) if err != nil { t.Fatalf("subtle.NewAESGCM() err = %q, want nil", err) } ctSet := make(map[string]bool) for i := 0; i < nSample; i++ { ct, err := a.Encrypt(pt, ad) if err != nil { t.Fatalf("a.Encrypt() err = %q, want nil", err) } ctHex := hex.EncodeToString(ct) _, existed := ctSet[ctHex] if existed { t.Errorf("nonce is repeated after %d samples", i) } ctSet[ctHex] = true } } func TestAESGCMWycheproofCases(t *testing.T) { testutil.SkipTestIfTestSrcDirIsNotSet(t) suite := new(AEADSuite) if err := testutil.PopulateSuite(suite, "aes_gcm_test.json"); err != nil { t.Fatalf("failed populating suite: %s", err) } for _, group := range suite.TestGroups { if err := subtle.ValidateAESKeySize(group.KeySize / 8); err != nil { continue } if group.IvSize != subtle.AESGCMIVSize*8 { continue } for _, test := range group.Tests { caseName := fmt.Sprintf("%s-%s(%d,%d):Case-%d", suite.Algorithm, group.Type, group.KeySize, group.TagSize, test.CaseID) t.Run(caseName, func(t *testing.T) { runAESGCMWycheproofCase(t, test) }) } } } func runAESGCMWycheproofCase(t *testing.T, tc *AEADCase) { var combinedCt []byte combinedCt = append(combinedCt, tc.Iv...) combinedCt = append(combinedCt, tc.Ct...) combinedCt = append(combinedCt, tc.Tag...) // create cipher and do encryption cipher, err := subtle.NewAESGCM(tc.Key) if err != nil { t.Fatalf("cannot create new instance of AESGCM in test case: %s", err) } decrypted, err := cipher.Decrypt(combinedCt, tc.Aad) if err != nil { if tc.Result == "valid" { t.Errorf("unexpected error in test case: %s", err) } } else { if tc.Result == "invalid" { t.Error("decrypted invalid test case") } if !bytes.Equal(decrypted, tc.Msg) { t.Error("incorrect decryption in test case") } } } ================================================ FILE: go/aead/subtle/chacha20poly1305.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "errors" "fmt" "golang.org/x/crypto/chacha20poly1305" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/tink" ) const ( poly1305TagSize = 16 ) // ChaCha20Poly1305 is an implementation of AEAD interface. type ChaCha20Poly1305 struct { Key []byte } // Assert that ChaCha20Poly1305 implements the AEAD interface. var _ tink.AEAD = (*ChaCha20Poly1305)(nil) // NewChaCha20Poly1305 returns an ChaCha20Poly1305 instance. // The key argument should be a 32-bytes key. func NewChaCha20Poly1305(key []byte) (*ChaCha20Poly1305, error) { if len(key) != chacha20poly1305.KeySize { return nil, errors.New("chacha20poly1305: bad key length") } return &ChaCha20Poly1305{Key: key}, nil } // Encrypt encrypts plaintext with associatedData. // // The resulting ciphertext consists of two parts: // 1. the nonce used for encryption // 2. the actual ciphertext func (ca *ChaCha20Poly1305) Encrypt(plaintext []byte, associatedData []byte) ([]byte, error) { if len(plaintext) > maxInt-chacha20poly1305.NonceSize-poly1305TagSize { return nil, fmt.Errorf("chacha20poly1305: plaintext too long") } c, err := chacha20poly1305.New(ca.Key) if err != nil { return nil, err } nonce := random.GetRandomBytes(chacha20poly1305.NonceSize) // Set dst's capacity to fit the nonce and ciphertext. dst := make([]byte, 0, chacha20poly1305.NonceSize+len(plaintext)+c.Overhead()) dst = append(dst, nonce...) // Seal appends the ciphertext to dst. So the final output is: nonce || ciphertext. return c.Seal(dst, nonce, plaintext, associatedData), nil } // Decrypt decrypts ciphertext with associatedData. // // ciphertext consists of two parts: // 1. the nonce used for encryption // 2. the actual ciphertext func (ca *ChaCha20Poly1305) Decrypt(ciphertext []byte, associatedData []byte) ([]byte, error) { if len(ciphertext) < chacha20poly1305.NonceSize+poly1305TagSize { return nil, fmt.Errorf("chacha20poly1305: ciphertext too short") } c, err := chacha20poly1305.New(ca.Key) if err != nil { return nil, err } nonce := ciphertext[:chacha20poly1305.NonceSize] pt, err := c.Open(nil, nonce, ciphertext[chacha20poly1305.NonceSize:] /*=ciphertext*/, associatedData) if err != nil { return nil, fmt.Errorf("ChaCha20Poly1305.Decrypt: %v", err) } return pt, nil } ================================================ FILE: go/aead/subtle/chacha20poly1305_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "bytes" "encoding/hex" "fmt" "math/rand" "testing" "golang.org/x/crypto/chacha20poly1305" "github.com/google/tink/go/aead/subtle" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" ) func TestChaCha20Poly1305EncryptDecrypt(t *testing.T) { for i, test := range chaCha20Poly1305Tests { key, err := hex.DecodeString(test.key) if err != nil { t.Fatalf("hex.DecodeString(test.key) err = %q, want nil", err) } pt, err := hex.DecodeString(test.plaintext) if err != nil { t.Fatalf("hex.DecodeString(test.plaintext) err = %q, want nil", err) } ad, err := hex.DecodeString(test.associatedData) if err != nil { t.Fatalf("hex.DecodeString(test.associatedData) err = %q, want nil", err) } nonce, err := hex.DecodeString(test.nonce) if err != nil { t.Fatalf("hex.DecodeString(test.nonce) err = %q, want nil", err) } out, err := hex.DecodeString(test.out) if err != nil { t.Fatalf("hex.DecodeString(test.out) err = %q, want nil", err) } ca, err := subtle.NewChaCha20Poly1305(key) if err != nil { t.Errorf("#%d, cannot create new instance of ChaCha20Poly1305: %s", i, err) continue } _, err = ca.Encrypt(pt, ad) if err != nil { t.Errorf("#%d, unexpected encryption error: %s", i, err) continue } var combinedCT []byte combinedCT = append(combinedCT, nonce...) combinedCT = append(combinedCT, out...) if got, err := ca.Decrypt(combinedCT, ad); err != nil { t.Errorf("#%d, unexpected decryption error: %s", i, err) continue } else if !bytes.Equal(pt, got) { t.Errorf("#%d, plaintext's don't match: got %x vs %x", i, got, pt) continue } } } func TestChaCha20Poly1305EmptyAssociatedData(t *testing.T) { key := random.GetRandomBytes(chacha20poly1305.KeySize) emptyAD := []byte{} badAD := []byte{1, 2, 3} ca, err := subtle.NewChaCha20Poly1305(key) if err != nil { t.Fatal(err) } for i := 0; i < 75; i++ { pt := random.GetRandomBytes(uint32(i)) // Encrypting with associatedData as a 0-length array { ct, err := ca.Encrypt(pt, emptyAD) if err != nil { t.Errorf("Encrypt(%x, %x) failed", pt, emptyAD) continue } if got, err := ca.Decrypt(ct, emptyAD); err != nil || !bytes.Equal(pt, got) { t.Errorf("Decrypt(Encrypt(pt, %x)): plaintext's don't match: got %x vs %x", emptyAD, got, pt) } if got, err := ca.Decrypt(ct, nil); err != nil || !bytes.Equal(pt, got) { t.Errorf("Decrypt(Encrypt(pt, nil)): plaintext's don't match: got %x vs %x", got, pt) } if _, err := ca.Decrypt(ct, badAD); err == nil { t.Errorf("Decrypt(Encrypt(pt, %x)) = _, nil; want: _, err", badAD) } } // Encrypting with associatedData equal to nil { ct, err := ca.Encrypt(pt, nil) if err != nil { t.Errorf("Encrypt(%x, nil) failed", pt) } if got, err := ca.Decrypt(ct, emptyAD); err != nil || !bytes.Equal(pt, got) { t.Errorf("Decrypt(Encrypt(pt, %x)): plaintext's don't match: got %x vs %x; error: %v", emptyAD, got, pt, err) } if got, err := ca.Decrypt(ct, nil); err != nil || !bytes.Equal(pt, got) { t.Errorf("Decrypt(Encrypt(pt, nil)): plaintext's don't match: got %x vs %x; error: %v", got, pt, err) } if _, err := ca.Decrypt(ct, badAD); err == nil { t.Errorf("Decrypt(Encrypt(pt, %x)) = _, nil; want: _, err", badAD) } } } } func TestChaCha20Poly1305LongMessages(t *testing.T) { dataSize := uint32(16) // Encrypts and decrypts messages of size <= 8192. for dataSize <= 1<<24 { pt := random.GetRandomBytes(dataSize) ad := random.GetRandomBytes(dataSize / 3) key := random.GetRandomBytes(chacha20poly1305.KeySize) ca, err := subtle.NewChaCha20Poly1305(key) if err != nil { t.Fatal(err) } ct, err := ca.Encrypt(pt, ad) if err != nil { t.Errorf("Encrypt(%x, %x) failed", pt, ad) continue } if got, err := ca.Decrypt(ct, ad); err != nil || !bytes.Equal(pt, got) { t.Errorf("Decrypt(Encrypt(pt, %x)): plaintext's don't match: got %x vs %x; error: %v", ad, got, pt, err) } dataSize += 5 * dataSize / 11 } } func TestChaCha20Poly1305ModifyCiphertext(t *testing.T) { for i, test := range chaCha20Poly1305Tests { key, err := hex.DecodeString(test.key) if err != nil { t.Fatalf("hex.DecodeString(test.key) err = %q, want nil", err) } pt, err := hex.DecodeString(test.plaintext) if err != nil { t.Fatalf("hex.DecodeString(test.plaintext) err = %q, want nil", err) } ad, err := hex.DecodeString(test.associatedData) if err != nil { t.Fatalf("hex.DecodeString(test.associatedData) err = %q, want nil", err) } ca, err := subtle.NewChaCha20Poly1305(key) if err != nil { t.Fatal(err) } ct, err := ca.Encrypt(pt, ad) if err != nil { t.Errorf("#%d: Encrypt failed", i) continue } if len(ad) > 0 { alteredIndex := rand.Intn(len(ad)) ad[alteredIndex] ^= 0x80 if _, err := ca.Decrypt(ct, ad); err == nil { t.Errorf("#%d: Decrypt was successful after altering associated data", i) continue } ad[alteredIndex] ^= 0x80 } alterCtIdx := rand.Intn(len(ct)) ct[alterCtIdx] ^= 0x80 if _, err := ca.Decrypt(ct, ad); err == nil { t.Errorf("#%d: Decrypt was successful after altering ciphertext", i) continue } ct[alterCtIdx] ^= 0x80 } } // This is a very simple test for the randomness of the nonce. // The test simply checks that the multiple ciphertexts of the same message are distinct. func TestChaCha20Poly1305RandomNonce(t *testing.T) { key := random.GetRandomBytes(chacha20poly1305.KeySize) ca, err := subtle.NewChaCha20Poly1305(key) if err != nil { t.Fatal(err) } cts := make(map[string]bool) pt, ad := []byte{}, []byte{} for i := 0; i < 1<<10; i++ { ct, err := ca.Encrypt(pt, ad) ctHex := hex.EncodeToString(ct) if err != nil || cts[ctHex] { t.Errorf("TestRandomNonce failed: %v", err) } else { cts[ctHex] = true } } } func TestChaCha20Poly1305WycheproofCases(t *testing.T) { testutil.SkipTestIfTestSrcDirIsNotSet(t) suite := new(AEADSuite) if err := testutil.PopulateSuite(suite, "chacha20_poly1305_test.json"); err != nil { t.Fatalf("failed populating suite: %s", err) } for _, group := range suite.TestGroups { if group.KeySize/8 != chacha20poly1305.KeySize { continue } if group.IvSize/8 != chacha20poly1305.NonceSize { continue } for _, test := range group.Tests { caseName := fmt.Sprintf("%s-%s:Case-%d", suite.Algorithm, group.Type, test.CaseID) t.Run(caseName, func(t *testing.T) { runChaCha20Poly1305WycheproofCase(t, test) }) } } } func runChaCha20Poly1305WycheproofCase(t *testing.T, tc *AEADCase) { var combinedCT []byte combinedCT = append(combinedCT, tc.Iv...) combinedCT = append(combinedCT, tc.Ct...) combinedCT = append(combinedCT, tc.Tag...) ca, err := subtle.NewChaCha20Poly1305(tc.Key) if err != nil { t.Fatalf("cannot create new instance of ChaCha20Poly1305: %s", err) } _, err = ca.Encrypt(tc.Msg, tc.Aad) if err != nil { t.Fatalf("unexpected encryption error: %s", err) } decrypted, err := ca.Decrypt(combinedCT, tc.Aad) if err != nil { if tc.Result == "valid" { t.Errorf("unexpected error: %s", err) } } else { if tc.Result == "invalid" { t.Error("decrypted invalid") } if !bytes.Equal(decrypted, tc.Msg) { t.Error("incorrect decryption") } } } ================================================ FILE: go/aead/subtle/chacha20poly1305_vectors_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test var chaCha20Poly1305Tests = []struct { plaintext, associatedData, key, nonce, out string }{ { "", "", "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "070000004041424344454647", "a0784d7a4716f3feb4f64e7f4b39bf04", }, { "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e", "50515253c0c1c2c3c4c5c6c7", "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "070000004041424344454647", "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd0600691", }, { "1400000cebccee3bf561b292340fec60", "00000000000000001603030010", "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", "129039b5572e8a7a8131f76a", "2b487a2941bc07f3cc76d1a531662588ee7c2598e59778c24d5b27559a80d163", }, { "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000", "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", "129039b5572e8a7a8131f76a", "3f487a25aa70e9c8391763370569c9e83b7650dd1921c8b78869f241f25d2096c910b180930c5b8747fd90959fe8ca2dcadb4fa50fa1439f916b2301e1cc0810d6725775d3ab86721700f96e22709b0a7a8bef32627dd929b2dd3ba15772b669062bb558bc92e6c241a1d60d9f0035e80c335f854815fe1138ab8af653eab3e122135feeec7dfaba1cc24af82a2b7acccdd824899a7e03cc29c25be8a4f56a66673845b93bae1556f09dafc89a0d22af207718e2a6bb022e9d917597295992ea3b750cc0e7a7c3d33b23c5a8aeab45f5bb542f6c9e6c1747ae5a344aff483ba38577ad534b33b3abc7d284776ea33ed488c2a2475648a4fcda561745ea7787ed60f2368deb27c75adce6ff9b6cc6de1f5e72a741e2d59f64751b3ae482d714e0c90e83c671ff98ed611823afb39e6e5019a6ba548a2a72e829c7b7b4a101ac9deb90a25d3e0c50d22e1fc26c7c02296fa13c6d9c14767f68aaf46450a8d0fd5feb60d9d73c6e68623425b4984a79d619dd6bf896459aa77a681ec9c1a97f645e121f47779b051f8948a817f84d1f55da170d5bbbaf2f64e18b97ed3fd822db2819f523314f1e5ac72e8f69bbe6c87c22daddb0e1ac6790f8534071de2f258064b99789bfb165b065b8fe96f9127cd7dca9f7cb0368420f1e802faa3ca23792f2a5b93773dd405e71c320b211b54f7a26626b03c060e1ab87f32ac588abfa056ce090bd7c69913a700c80f325bfe824fa", }, { "0967de57eefe1aaa999b9b746d88a1a248000d8734e0e938c6aa87", "e4f0a3a4f90a8250f8806aa319053e8d73c62f150e2f239563037e9cc92823ad18c65111d0d462c954cc6c6ed2aafb45702a5a7e597d13bd8091594ab97cf7d1", "f2db28620582e05f00f31c808475ca3df1c20e340bf14828352499466d79295f", "4349e2131d44dc711148dfe3", "bd06cc144fdc0d8b735fa4452eabbf78fd4ad2966ea41a84f68da40ca2da439777bc2ba6c4ec2de0d003eb", }, { "c4c920fb52a56fe66eaa8aa3fa187c543e3db8e5c8094c4313dc4ed35dfc5821c5791d171e8cfe8d37883031a0ad", "85deea3dc4", "05ff881d1e151bab4ca3db7d44880222733fe62686f71ce1e4610f2ea19599a7", "b34710f65aed442e4a40866b", "b154452fb7e85d175dd0b0db08591565c5587a725cf22386922f5d27a01015aba778975510b38754b2182e24352f019b7ad493e1ed255906715644aec6e0", }, { "c4b337df5e83823900c6c202e93541cf5bc8c677a9aad8b8d87a4d7221e294e595cbc4f34e462d4e0def50f62491c57f598cf60236cfba0f4908816aea154f80e013732e59a07c668fcc5cb35d2232b7ae29b9e4f874f3417c74ab6689fae6690d5a9766fa13cd8adf293d3d4b70f4f999adde9121d1d29d467d04cf77ea398444d0ea3fe4b7c9c3e106002c76f4260fa204a0c3d5", "72611bef65eb664f24ea94f4d5d3d88c9c9c6da29c9a1991c02833c4c9f6993b57b5", "dd0f2d4bb1c9e5ca5aa5f38d69bc8402f7dbb7229857b4a41b3044d481b7655e", "2bbca0910cc47ca0b8517391", "83aa28d6d98901e2981d21d3758ae4db8cce07fe08d82ca6f036a68daa88a7dda56eeb38040c942bdda0fd2d369eec44bd070e2c9314992f68dc16989a6ac0c3912c378cf3254f4bae74a66b075e828df6f855c0d8a827ffed3c03582c12a9112eeb7be43dfe8bd78beb2d1e56678b99a0372531727cb7f2b98d2f917ec10de93fe86267100c20356e80528c5066688c8b7acba76e591449952343f663993d5b642e59eb0f", }, { "a9775b8e42b63335439cf1c79fe8a3560b3baebfdfc9ef239d70da02cea0947817f00659a63a8ee9d67fb1756854cc738f7a326e432191e1916be35f0b78d72268de7c0e180af7ee8aa864f2fc30658baa97f9edb88ace49f5b2a8002a8023925e9fa076a997643340c8253cf88ac8a221c190d94c5e224110cb423a4b65cca9046c1fad0483e1444c0680449148e7b20a778c56d5ae97e679d920c43eed6d42598cf05d10d1a15cd722a0686a871b74fea7cad45562bacf3bda937ac701bc218dac7e9d7d20f955429abdac21d821207febf4d54daea4898837035038bf71c66cef63e90f5d3e51f7fcfe18d41f38540a2c2958dacde16304e4b33da324030f1366f923c337", "74ba3372d308910b5c9c3885f41252d57556", "9cf77bd06a4ed8fb59349791b98ba40b6019611942f5768e8be2ee88477149e3", "b928935c4c966c60fd6583c0", "ec7fd64fd75b254961a2b7fc942470d8620f439258b871d0d00f58028b5e0bee5e139e8108ac439391465d6658f559b1df57aa21cf826ede1a28bc11af885e13eebfc009870928fae8abfdd943a60c54fca93f0502dc23d29c2fd5340f9bc0e6ef2a18b66ef627af95f796d5bbca50de22c8ec802da9397089b25c6ba5262468e3977b45dc112e51896c70731b0a52d7efec7c93b41995823436bf4b0c477ae79684407c9831b487928b2b8303caca752b3edf1f0598e15831155462706f94ef3fa3a9e5f937f37085afa9b4bbf939d275796a61b78f70597acfd25cd87f967021cd99328fc371b5eb5739869520657b30e4a5b0db7c8715cbe275dee78e719b357d3a9731f9eaba95986479bb2004a77822fc115a3d", }, { "b3d3128bce6bbf66fd78f1a18352bae56bfcdae18b65c379ee0aeb37ee54fba1270d2df578ec5b75654d16e89fd1cd0acda7ec580dafd2fbbabd32a8112d49383a762db2638928c8d63eb0750f7e7fdd256b35321b072dd5c45f7dd58cc60dc63d3b79a0c4a1689adf180fef968eccbcfa01ee15091ceacd7b67a3082db0ce6aeb470aafe87249c88b58b721e783dde184ccf68de8e05b6347fe6b74ae3adf9a81e9496a5c9332e7ebe908d26ce6b3f0b2a97e9a89d9fdd0d7694585a3241f240d698e69fcc050e7a959ba153f6d06f117848ba05d887134f1b6b994dad9b9e74247513e08a125b1fadfc7394dcd2a6451b504ae3e75e22f2b9bc405747dedb6c43ef4ccdf1a7edaf9451346123eaa63f3af113124f361508e255503a242b96680ae3360c8b13ac1f64d08088bb26b7f617cb0866f11d6fd362b00d86eba3fee68724e302388f119d6f92161ac8ce00d08919377a26974d99575b1032ff0f1976240c785c8b89e9eb2bf005e4be06b5371ffca14683fedfdb49e00e38ff27af1324177faf91599abd5990920797574eb743effdc7decda318ada1419cc8e0bfecf82f9c99792746c2b", "7e8da4f3018f673f8e43bd7a1dee05f8031ec49129c361abbc2a434e9eaf791c3c1d0f3dad767d3bba3ab6d728bbcf2bd994bd03571eae1348f161e6a1da03ddf7121ba4", "7ee32dd501dce849cd492f6e23324c1a4567bfceff9f11d1352bcb8615f1b093", "8998e043d2961afa51ea262a", "ba85e72af18cb5ba85a4a0d6c28b4ac1e5509a3a2fdb0e3255cbc559df5e6a661fc560c756a0264dd99b72c61c51a4b7ad56ca4c8ccb7e8edfc48ff3cceac5d1e8ac5fc87096adc4d0e9a27492857b17604c3a694cfe0e70b22df106c8f3c61f840bcd634964cdb571840e125e381e7dd3a0d97972e965f16f775fa4ce555124318290bf508beb7bd77e633042deb0e863631478fc3dc9122862b3c31264471bcce54e0b74040c8bafd481cf798f332e8940f1134d3027d6f28e771d15e154fc89c6c25fe18a5d312807cc2e623bb1bbb4f0b6ec71d009407eb54bb0759f03682f65d0da8812f84d8e97483f6a8d76a8417efcd9526444abba24288647609791578887ef49780b0b89f51b072cae81c5b5014463da3633dda105b82add0f9c2f065dca46eedd2928be2570493c79a996fa78ea6aec0996497fe2dc444432ade4eaa662ee2255f0f4b92d593288a8e3ffe7a15a10e9d33b0203af23f4c9fd2cfcb6160db63b52810869ff1e65423dbe2c4415884b9f8dec3c968e14cd74f323c89053a96111bc9ce59ec483832c49c53a648e5f0f797f53642ac60170c94b473f1f2e7d8a38e46460b81219b52081263027f74cbf63a75af3a7", }, { "68d5ba501e87994ef6bc8042d7c5a99693a835a4796ad044f0e536a0790a7ee1e03832fec0cb4cb688cdf85f92a1f526492acac2949a0684803c24f947a3da27db0c259bd87251603f49bfd1eab4f733dec2f5725cfcf6dc381ad57fbdb0a699bccc34943e86f47dcfb34eba6746ed4508e3b764dfad4117c8169785c63d1e8309531747d90cc4a8bf13622759506c613324c512d10629991dc01fe3fe3d6607907e4f698a1312492674707fc4dde0f701a609d2ac336cc9f38badf1c813f9599148c21b5bd4658249d5010db2e205b3880e863441f2fe357dab2645be1f9e5067616bc335d0457ea6468c5828910cb09f92e5e184e316018e3c464c5ce59cc34608867bd8cbfa7e1286d73a17e3ebb675d097f9b3adfa41ea408d46252a096b3290e70a5be1896d6760a87e439334b863ccb11679ab5763ebe4a9110eb37c4043634b9e44d40cab34b42977475e2faa2ae0c0a38b170776fbb0870a63044aa6679545ac6951579d0581144cdf43f60923b6acaecdb325c864acd2c7b01d6e18b2b3c41c041bb9099cce557b114b84350131e3cee4089648b5691065867e7d38314154355d0e3ef9dc9375eddef922df2a06ad0f0e4357c3ac672932e5a66b16e8bf4b45cd893ea91cb397faadb9d9d7bf86e6ceca3e9176a5baa98b6114a149d3ed8ea176cc4a9380e18d2d9b67045aedeb28b729ba2ece74d759d5ebfb1ebee8ac5f5e79aaf1f98b7f2626e62a81d315a98b3e", "63b90dd89066ad7b61cc39497899a8f14399eace1810f5fe3b76d2501f5d8f83169c5ba602082164d45aad4df3553e36ef29050739fa067470d8c58f3554124bf06df1f27612564a6c04976059d69648ff9b50389556ad052e729563c6a7", "7d5c4314a542aff57a454b274a7999dfdc5f878a159c29be27dabdfcf7c06975", "aeb6159fa88bb1ffd51d036d", "7597f7f44191e815a409754db7fea688e0105c987fa065e621823ea6dea617aed613092ad566c487cfa1a93f556615d2a575fb30ac34b11e19cd908d74545906f929dc9e59f6f1e1e6eaaabe182748ef87057ef7820ffcf254c40237d3ea9ff004472db783ed54b5a294a46cf90519bf89367b04fc01ce544c5bcdd3197eb1237923ce2c0c99921ca959c53b54176d292e97f6d9696ded6054711721aebda543e3e077c90e6f216cdc275b86d45603521c5aab24f08fd06833b0743c388382f941e19e0283ac7c4ef22383e1b9b08572882769c1382bab9ad127e7f3e09b5330b82d3e0c7d6f0df46edc93265999eef8e7afa0cb1db77df7accf5bff8631a320d146a5c751a637a80f627b0c9a41b44f09212f38c154226de02f4906ef34139bbeacc3f06739c8540e37334392d38ba1cbf4bc7debe77c09b35d2200216db15ed4389f43bfd8ae9bf76fd8243c3d869546e16b8e44a6cd1edbd2c58ef890b5a84cda889131e5cd9402ca4d8271052c6b4fe3f2dff54fb77bcb575c315b9109f90b14bc8e109919808a581c1809e2a188d29fd34ce639088a6683f641925f5b4b3529baa34e080bb47fb7ad9b43d0d67c9e6ae7cacb50527fa74e56d0c8b20149f5d332d686d48ebbe634c2b5d35fc84c69a5bcc93b93dedcf9fdf19a1fb9b75f6df9692d16f6c3490377a06294499e4b8ebeaa0cfd840bfa05fde21c0b5e94d13063b3f5da7b537caefe89069cfa9de9eb8f06e4d30125de64716f821bcc8279c0c7ea2e", }, { "89c1ee38b6697d0190c87a2aa756892ee09fca095df1e31aeedbda5750f604d9b8f2116e5b8f70ec57ea16fe419f2d213ef72b9be90eb5d7e98f2e398632123e2524ac80b31c6c0a07820848223569602d94fc16a3b1ed8c411bc6c74ed80573fcb1f3afce60b9d5e2c21d04f78665241b613abe12274a5343101a91e91f04e5d1f7959f574e743a10913e0817a32c320467f0178e3b6ad14b856234a4661a755eaf14b5fd88ef0e192e1631d14263d6a954ed388f5709dadc6c0f81d229f630d80be6d593d5e3ad03f9ded53c41abe595981d24ef27ffcc930e4d653743960f4e7ce4e251c88f55c16d2afdaed5e3446d00685c276728ba757520acb9b6bb0732a0e9836878d829e5022794d70ad8440a40a132a8c9ec1d3f0ccaf8c285fff425e9788d6150b74753dedb2ae8b36ff2f310249bd911b9181d8310e00810d42ef94cbb5a9d72a1f0507c1a382f892b23994fbe7360778b7efa9c5e03ac3231a57fecff1c5fa10caf1d26e84db0137049622ebcc3a64841a0e49fa390d1d43550c1346c20d578cff39fb7404fcab0982dde55f0849d312581d0c811a19d46f25e7a5e7e50d74d43760583c5cf335dfc11b2ec964f1dbbd0ed83e18f2027817ea2dffcf2b64a352c4fb8f11eeb4f1bfc01079251254d2112d103a1f12a2270cc026cbeb8b6f3e505abd62496253f93274625786b73997e449c1f35c742a593441252fcc845e1cef1b8f287dd311a0477407ce3b31661f7b2802c79c2d20d06e45f03aca4e47a959c6c1d7a9d377e1577fbf82a115921c3d94e3d9c204aa204a9a5b04d8a2be3269700a035371f4aaf1a42d92b9bfbee74492b106975b36d1e581d6ce2484f09e04fa91586c85f35e2a10f0d3c0afcb05327c1bc9d7429bbcc4627af8f76b86fc561844c2ae3810c84901ac09a1670ed3d31a9daa5d296", "7219bd21a834d917f93a9b45647ec77102578bc2f2a132dfde6489b9095b4f7b740c9c1c4075333ab0ce7f14", "a7f849b054982cc8a4c8e5e53e181feee79e0233e58882839892134ad582da7c", "4c46854e9e101090b1436f90", "ab2e189baf60886bed88eb751bf3560a8bd3cdb6ee621d8c18b5fb3aa418f350048ecf359a7d542daf7090ec8688c3b0fe85914aa49d83be4ae3396f7bdc48051afae6a97fca7b42c0bf612a42d3c79ef6aadceb57f5cfe8d67f89d49add0ea1ffd423da058297239e72a85fa6cd1d82e243a503b1b0e12d7510a9ee98d7921dae2754d7581e52acb8ab9e7f9df3c73410789115cef6ce7c937a5441ad4edf2b7a8c0c6d152d5a5909c4ce839d59594a6163364038c4c71a1507389717f61e2bda1ea66a83ef477762e7834ebcfaa8f2ee61ced1605ba1380108236e1763bf40af5259da07dd3e3d0fb2801868c2e7c839e318678687cbe33384e2ef5750a0a0e2d2e19e869a4277e32a315ed4de79357f6a12a8a25d5b18291316d9bf40dad2d05d1b523ade76650669c700a1c2965f4e51337aa5d45ec7b4981072779401d6d30ed69034053334bccb18425ac68460becf2aeccc75aacd3d6709f07ee10366ed848c8a54904af4ea71fc2117de133f01e1cc031f2a4d0779b997b82682433ee615202d5dfffba6c916f11a00551d56ffde8c36b303263e14adaf45b6eab0bedf344e5214ce52f071d2f40154d788c6870020791a03d2fd4ec5879d9026241954ed45cfddef4937ea3d0d45647f252be31411237983a1be340fc65ebab9a5620abb0e8d475af4e89e842e895eda0cbd283bb5d0bf20236c62d956de733d60ebceb42fc0c9adbf9b69f8d66551b0aca0e260625ad41cad75d752a234af7caf7902c2c5b62f04b6a8e019a6179d44feeb2ad5859ef1c45371e66f1af1fe0de63997266c290e27f0dd62185c53f81e0a50c296a51ace7c90d9cf0dda8b2d7e72a347f64c44262e2a544d1acc7bb05734dc1783bbc1903279092fe7fe434610aa95fc2ce5fc5ee45858f5e8337d8fcb0a468464becb1cef6b7e5ea48ba383ad8a406df9c581f1cac057d8711fcb", }, { "2dcfbb59975f217c445f95634d7c0250afe7d8316a70c47dba99ff94167ab74349729ce1d2bd5d161df27a6a6e7cba1e63924fcd03134abdad4952c3c409060d7ca2ee4e5f4c647c3edee7ad5aa1cbbd341a8a372ed4f4db1e469ee250a4efcc46de1aa52a7e22685d0915b7aae075defbff1529d40a04f250a2d4a046c36c8ca18631cb055334625c4919072a8ee5258efb4e6205525455f428f63aeb62c68de9f758ee4b8c50a7d669ae00f89425868f73e894c53ce9b964dff34f42b9dc2bb03519fbc169a397d25197cae5bc50742f3808f474f2add8d1a0281359043e0a395705fbc0a89293fa2a5ddfe6ae5416e65c0a5b4eb83320585b33b26072bc99c9c1948a6a271d64517a433728974d0ff4586a42109d6268f9961a5908d6f2d198875b02ae7866fff3a9361b41842a35dc9477ec32da542b706f8478457649ddfda5dfab1d45aa10efe12c3065566541ebdc2d1db6814826f0cc9e3642e813408df3ebaa3896bb2777e757dc3dbc1d28994a454fcb8d76bc5914f29cfc05dc89f8c734315def58d4d6b0b0136ccd3c05178155e30fcb9f68df9104dc96e0658fa899c0058818da5ec88a723558ae3a6f2f8f523e5af1a73a82ab16198c7ba8341568399d8013fc499e6e7ef61cb8654b48b88aa2a931dc2cdcf245686eed9c8355d620d5e91c1e878a9c7da655e3f29d9b7c3f44ad1c70890eb5f27ca28efff76420cd4e3cebd5c788536ddd365f7ad1dbb91588d58612e43b0460de9260d5f780a245bc8e1a83166df1f3a3506d742c268ab4fc10c6e04bca40295da0ff5420a199dd2fb36045215138c4a2a539ceccc382c8d349a81e13e848708947c4a9e85d861811e75d323896f6da3b2fa807f22bcfc57477e487602cf8e973bc925b1a19732b00d15d38675313a283bbaa75e6793b5af11fe2514bda3abe96cc19b0e58ddbe55e381ec58c31670fec1184d38bbf2d7cde0fcd29e907e780d30130b98e0c9eec44bcb1d0ed18dfda2a64adb523da3102eafe2bd3051353d8148491a290308ed4ec3fa5da5784b481e861360c3b670e256539f96a4c4c4360d0d40260049035f1cfdacb275e7fa847e0df531b466141ac9a3a16e7865947572e4ab732daec23aac6eed1256d796c4d58bf699f20aa4bbae461a16abbe9c1e9", "33791b0d653fb72c2d88519b02bde85a7c51f99cfb4456dfa6f84a61e10b4a14846521", "a0a7b73ca2fc9282a28acc036bd74d7f5cb2a146577a5c29dbc3963fe7ebfd87", "eaa4d916d261676d632455be", "c9a631de470fd04dcbf8ea9f4d8ac37c3988878b6381707ac2c91d3720edbb31576ba90731f433a5e13582aca2b3c76ae75ca8881a463ecfa789910d3a776a9ad4800521c6baa120b2f1afd10f32ef8da63f5b69f5e5fd88ee84bf66b0666b15d05c4050f5358a050b9d5cf1503719f56cd48ceba78f29efe2ae8092e37f5134df526831532f86ccb9339637e2c9e9b9036f83cc058fda23e826a188456e7fd3f4ee20f4e4a3221883fe3232b49db607b90a8956133ab95051c9ec33a908ea7e81a1bfa7bd06c09f0143d07bb23a3feeac7f0d7720269c93e2df19d03605828c8713b84d183c9a50954c12fe3b047511ad15ef03a63355520cbd224d06a34de67a671368e6a8f9feeefe48fc273764a8c69c00314e5d693f159cb5270544f3c4e1760b0529e3303ab308e9a6d03835a3a42aef2df5f7643696f707a574d1dcc676aeecdd9947ebe8c13bcf15d30b2d10d2cd95445a307c1d22d39450615ad38f9302c6eb9dc05764b0503d6a7eaff9feb94834853b47bc25660207be3e7c0e27cb3127b5402cb016396e5ff07ddc3df29861dd68a17f53bf660b23352b739d6da72381b8d19a9fc95da7efb79330a2b360dce4309860af429e3fd10cab235c4acc1d80d9e20d67019375bd161ab65648400f308815afe63cfc717f7d0eea150e687caac25b6603287d44dca4a7cc2f67c3bdd54450bd3170340253b03ba054ec003070eddf9c14fb9dc595e228e4968524900cb5d85af6d1e658a42d744e0e7eb6995023823a8dc33528c6715b2e1aa607782c8e1ddddad72026d657bf122ece8685f6e92236e809139325e4a3c069facf94c10b7896995bba01eb22c7b3a87ea2114a7649d7ed3e83d223e5e785c66a75119beab0968d3eaf0cbcc2d7ede95d024041e6db39a880ce3e19efea32fb89a40a2aae22f407e5fd615e51e48dbd50a8b4ec27ce95e2ba1928bf699d0418705482ed0ed7acc858dfbd690403c74667a88dd5221bb79940c6c4a268379c10343aaefb635982c14f33ad83d47ced9682961540bd4f75804d3d48ba8aa67fb2e3a1db83fbcbe57fec9e4ffb1b575e947f8bd8263c680357960e3a39382974774b5a013f2f8514b3c63c21dbfd314fd5d927d82ba616d76629ac018879f54ff84b5808e94af4fcfe1cf8845b65208ca5510b5b593ce6c109611652cd", }, { "c335b055b752e083554b5aa2cbb6556cfcace658d5c11b6b000256fd89e9b24c1e62a2d5b582580acdb2ad9869020465aeeabe83acd9eeacdc44aa652d5cb24bbe542073d6787ea32b2b3c942d40f9db2bb75ed7914c836d902dd2be89840948d82abbaea23952cd648e6191ce5b6cf912cad0a3165410a781e3650b676e5340980eee3b484008acce6a3e9dc5aa96d775677b8bbb8b323c6e9747d6069a169ea904d9f145e29d134cdbb0118647e8fbae638669efb9a55d50ed33568749f5304ece2193b0bfa6fc9a570d209ef61b4c59a2b5485b5aa6ab47d902cf23f7ff71c5210476e0aa727a01809b9f76b6ebcf58a018b3fbbe5f42976111ba58112b1d322f9312da068cdb86277bfcde66cb3607e3ea02a1494439aa56f302671f1f994eb3ab28b937043f5f7f3b3de50673ecea5dee8ba633c45089b852f0d772892525344ede6b521dcad15807b65e7ba348d891d47fc498cf4d50223d2794c64db9fa9b9766edb430be0c38746ab317b38ba9870a6d1fdabb70fcf89790bfe449b97fe01f6c94502aa0889f0a3bb6bdc65f44d1cd64ab88d4a7806b373f5080f9cf60183cf4686694f0059e2bbc5cf21ba0c3e8046e70d815f1444c3094cc29632c429f20aa06b49b0b52c6c7aeb8e34f7bcb53e93c2cfe2d704a5d0416876742c90762730d160e1869d5e0178dc366098ebaf2cae6f1f7563b555a52dcc194a5c8f718d50d27ee76fcce8e8991f4921fae85ea9476e1eab1364403120698b7ce8fd0a49cf79213f360a17cf1950f104494fad80adcc3bb1207bf250d57dcdce6ac8082a312959672361363cc227310b66ee8c04aab7b5cb33a81c0915e9c770a1cfaae2e8f44a0c65703927977a22fe58aef2f366b8be9a50da9376b46ae7562a82391386831febf359039ac326891bc58c0f2c34bdb6858859fc3cb4e392df65cbe2ec4f02c8425bcbdd1ee2562ab7d229d406d79a9c6fe4889c996c2f68d1fb5bbe3a5e867caa4249b934afd3ec71fdb088c54b15252f9dc1b909e121dbdc7d8a16cc00836652dd1f877ce363eed11467966f7ccb8f1a8d48146e69e04ad76a51937ad4f9cda209451eeca90dbdbd65441ce20fabfc8ce400fb4de136154b87a8b65c92740e9bb91d78521b261f806a2c6279c85ef6ac5fe1ea3117ff7c9f9832fc2aa6fab660082eb22344c1a3befe0628b6551f62a5014cd6194c42b8d475a50f2c9fb58c97e43ebb29005ed7fe54f0a4aa10074f1154152a9067d364dd7863fa082976a00db55b26b5ba0ea40eff48b90", "f5ff810a41d4b34751e9942970d4c9f26b33f24689a4b1e4449b243490afc485af468ff01a42376b2bcb949b9f5e8d0b917f511a", "a74271c184a82cb074c14b131fd91eb05870cb7c73c9e511ec8140bfe2f34089", "2403fe689e239c2ed261b381", "af9be893d5fd23aab42e6a2e59a8e7cb13d4f543db02af87cb0802bc1af7c717cd0093cc8244994cf21189146922b69927ffd5745e57118bea07a6afe7c21d952c13ab636b3c2e461dc9ffb3ae701175360156338be94b1fa7115799831019455cfaf5114010fe45f8fb9c77ec50fe06f2c5a32423edccb3b2210ee1200a78e1a3130c567542377827586ca8cf0c14c19fa1449a2cce9c039bb441b04e9c0a3f9a743b31c828032174fcdb7c894349aa68f5adf97dfe9294d24e6b5fed95eb994397883f58487bf5c57b0aea5268be7cee9efeab370f89805ebe5373ab2e93658fc078955ccf68b554dd5605005751ee8531c35ca5336a5d0ce273370c0dc9307779b86e96d2d1daf2620d67d43e1fb7800ccf250ca3c02eb74047c1d2a2bc7f29fff8320301694b80d0fd975f834337d00d5f0e4215044d52aa4ca21e6a9d7e03f186d7cdd5c48e3765dc926fb0a46bb0f05c50d9f69c9c507527a60366b7dc251aae1d6bb0d9c73735dcfab959f6fd4382fe2a1f6ad07affb0601bb9040f81b55a48f6a6c5f8ac4a2acc2b0c9a6c439198f7926460695fa11e0b0b017e39de5cf0d5d5f84d972b5eee7b5d1e0343b5485cd84b92ad892e5b23f3e803f5b363f2398c11c15be9f13e59922b0d49902dc8483fb142850b4226da2fb84e9b434a34f6bb67f575a9e57fde3354bc3077a876e260311bb2481bb139aa9af55df5074749fe532d7b8a554218a90cc7e7ac69db280bae5d55a174dfc8d325b9909a8da1016d4e162fe5ba70cf8726cdf291f5e47083d9929cd5e32021cbfd982fd0975f6f9baf4322b553cb3174b11c007559879f308419ff9e4e18eee8d3640cec8aea082b90f69cf3c7676c28af0265c24c91cd58a06513198892ce6ce1ab3ee9ac0a2e937b973a9cac06a039a54f8d994c13d42c59187f677352e5feb32a417aebec4d852b2595e7e67450e06dbd183279e3b63022a3813b37257b085bf8454d6890875a2950d20210a8df4f9da746722f62687e92f0e9efc3e5d526d65ccfbcc042fcac7964dbe147932c73924bdcdf62f9eae58d29e8567ffed90048bcf0566b952e986efeae4c477944af18bd243c3eccf8d88c06d07279adad037450cb8547a8aa0a74223f4851747c803cb21a2dd027e7080aed75038cdcecbc4639d87763cdd41829a1b72cedf0d722b180d0d492a5740ea7607b95f3201df352fb1ab28149124d2df5d5ec106867897b537302c3431402348f94d28eebc701ae1b49d10adedea38f1654fbc48885e59e6e6dfd413c6b5a97d8c35dfb07a6cdefe317bf61cf91", }, { "4aba5a776ace38b6e2578f0007e770d264e39c49f588ca3547ad2888365e3a811994f8836330394587c8458eb0b6611499fd5d8e8527c3cdd4ec550b4a8f8c632384e786b420cb3be911c999c72aad60270aefad31b27a069ecf11e95e9d4c81213308d554d3103de4d9d6ab04830c2b8dfbd8bead52c44c21d5357f72810193b5096809dc7846c1521c6c569f78812c735aea21acaf6dce84a24df7234e8ad857f3e1346b27f5bd436113e2da950e4deff96e9ba8db692c7db723a105ae795da15b910c8286cac6e7dda8c172b70f61b07dfd58596684d61da8772356f180f74c1103ce97cd947eab3d401df44f7fa4cc7cfc25e280fc002873237e64a375b0b4797f4b4613c9f150090f44588ee8250ae44aec6546ec8dba0f0c1eb281cf66fa4eb141617b32b28441f6ddcfdf02d9c34cc62893b2b64dc2c26b74433adb3e888c7fea07b19c8cf39269c2716b9c35b7625d4a141397d6d5034b193d2657c6b2d6b0ba874c467adeaf3d501ad985d13be21c4ff6b326cbb671e4f4973bba49116a0399b6491394f850e4122969e4644c00b442b3da0d6a4bf25ee22d182b3f822fd83878ebcc713cb183651a67ca66677ea81b58b685a3a8e385d5fbb0147ddfecb558d881c914324c794db443b31bc15c361912bbbcba9e418f99f2a416d190cb29684df27c7f3ff6ccf339800efbdc4514ee00d1a89f12373804db4fd66c1affd467f251e73147b3248033327b0f7790fd7861a51773dd4f78b89e4e24b94df9203f4a077091bb9411eec78dfe3e1dfbb67ea1cdf17e1d6936bbb75b74055495449e9cb52f5749404610cd444fea3f0568e0d35a5ef0c395ab7bf0208044b5c4e2517911a9c351efd31f33220972287253fbccb1eb8f46960a36b68a7a6b4f5cbdc86d668bbf555fde8881e7faa9594da425ff8fb54526bf7cdc4af64899530561c06bed7fc04c5d48cd4542779e901bc48fab79d4d13850ad8247f51b9afa7d5a656ada25b6376d837cb0fa1b4016dfcfc158a39290f43f133b352ed52fab2f951509bacb41284fbdd849d8185fb7e7200f8ab2a07ef2b3b927e18e568dbeeba2c7a66e08cebdc6a6069ebe6656a586652f3905ae2bb867529af6a827b494c97b3a378408f44aaefbe86c613e11e7a44020a9ee4b62569dfc4c462300daec7b1424ff1c1849ca1332367470475c14877cbe76c820cc651c18ab3f18852b93994f93b568dc7f7b0eb5f07ffc4c9384c851fa9071c6f68ddea1ccf627f889c0471c76aff9f52b07ab1b86a7671a2b2f6b25c0ddebb66ac95737bf7e2f493f7665b5265eaa5166556cecfdd3062802724ec24f3978b903d0f0c24e1f0b8d967142bccfed0d354279223f4c28684e9ab611e9ef89a3f25993b5a8b3c0354931780501651236a78b58e7d7814f251b053605f4c0a8e7193b9cc1ee5cf7378e6f3c8fd44ec57bd91e62b09fb1d6bab60cbfabcc6792e6a32ea7918a9ec9180d05a7e1546d5d2d8bbfde2a71b4e427c0a4d28d0b6473ae", "921a401db90935c60edda8624a0590d5c46eff3522e35de2872f6f9394e24126fd8143b68a797c995624fba0298b75eef974", "6a4d35ae03bf277f587da4541dcddf92bbd906dff45d5ff23c0f60ae53b062be", "231b5780fedfb06d724450b3", "ba40968282d98849b19d867f8b564ea5a81d657516099362926bca4cb6e9ae02719d10c8061f53008c727a0eeea5e1e36c9e55c117e9434e213316c96840231a1e356b254a9981d4a6ca3c66cfc61018bcaade1a4486506559e6aa3a86bac980d391d835fd5ded98d10f1394d84bf1bbf2cd3397890d704154802f7864ecc753db782fd3d19213ae65ace4770e1bacf32d61c6730aa5adcab4d7e2e437888c11c29abba4890a17a00f67a53b660becd94092df0598df5ac57326f6860593a519e28bd4a39f6481e1a4748881fd5f0456a3cd9f28d1d1e78dc64030cbd8fdb2c5abdab3f13d6ccccd187e71e989f8c486929efcdbf2a763effa95af62db5cef95e9081b818275c69267022fda4b7fdb8c650b491a785b03d4d0186625962b6326ec3f4e176373da4dc1f83a14815adf82c6bffa7c6967d77528d0249754bb4d17656bc4a89449b16152a4a1aea7eb0054a8892f271138971507d2f3b237ba5b620f444544e4a8c2b1ab4f9168762c27478c9f776c47ee2e9ff05bfa35ed127f0cabe7cc053640bb8aa01f8359b74bf89ef43ca94c48fcd201eae39d1835957eeccd6b3a852f4e1bbfef9a469f42c764481ff8408fe5871afeeae7676b58f4202199aad50a596626dff97c8e60d750cc59da9f595ce12ce9afdce14481cb1e39994de8fe4cce07845110d6703dc59d34734e93e9e57e1c52d61f44143a2d290220a4bad5098d098ee65ea4b6757d8a9bf5485aa3d697a7826d4a285186f5da10eff707566c23c6a15033365bcb498c44487c72d96402d1834753fdbf86770239761f03e0dc8963766441da99c0813e4f1df5a1d018c8799861a396562eb24ce305ca15f4022d83ea3c56b68d9a7ceac4742ec0ce50f4d36273df26005ec2b051fa071b319be2d8a5ed26eb75bc1ea83761b8454db234d15d84d6706cd178981c1f156e6d28f774aee3e9a4fade022e71b52b50aa532b8bc7fe464f22d6eb169c69671875d614e987658820c2f584a4fea3008afdcbb646dba3d69020fbf503f121be3480344db23efdda0d255aa058c3ff66abd3a5fe35db977521608bba7eddae72ae801f4fbb12a1de4133039e046ceb8db87e465e5ede1d79a08c857d59076d7ff858942c31e15cbbdae6fc15c3f9545a0825d6ff8583c0aba8a7d143d27b93f6caefb98c0d83bd8715abcab2a49087f55a9daf9090eacdf45be08ad80b5df5070e1719f68c4cc8f8711083f0f7823a09ec092f22df95fe9e95114fdf82a3f6eed0bfc9c0aa65222609442776154a474dbc9e662cd5dce66846572e52417ee5d7eb59287d07ef60a9537fe1f85c7fa74fe84dea0da235ac7574335e6649b54a6bd33397df4bf4a7976c4ab868aa702766d2bc8d2c82c2d1c2653fc8428b8d1e61852ac185a3a0b416dbcf8eb54c44967ff43c44f2b32c6d4a9dbf2c2f3a587b430aef50f0375cdb4c1b319ac9aca486d9bb321141b065f52f7b6decaf1985531ca7bbc3772a561eb1efb8a6297075920bc432131a5b211bf25e35fa31e12833bc77a9de14c7", }, { "6c0056937faf1023032df1e2bfacbbc58bb022eba25ffa020d4eb26f0caf0678af5d0b2f0c1b520f4843f107f0adcc7b5dee66ff4d61025bafb4cabb64d133132e3e423a599549a1d83aa8c8e774444462aa44b00b460bbafad5755ea6a872d4e6b40e3f4957e0229288ea79fc2ebe5fd9020fe4481a9f42ef14a196bd136aa3c779e311d0c333624c1ddc484c9aa7259cb609e4d0a826c0bdc7567adac01da23900b30ac4e66c100348584fe200747eb67e6287268947e3509d5d2b5d7bcd977b80a13f660d4f6956a8b938a82db75eab19e5d2a22cb5f3c9131e278eebbe096b5f49d16c983ac240f3fbe821b247cccb2c9e6e59546122677f49f56a07fed56647a6d3e0e09520d49009f54250c10e7c607cd5b4ddf81b5c4110c6490e9baf56418236211856f5a85feaebafacf92c0c7501c052f9dbae3beb7484f90f334f50b68571cedc67763b5161ebfd5a1709cf18c92112a4cf4d8f43d1895204d8a2ba5e14883a7bff75cc6060cabb77d38a909daca2417befd1bfc05a11c432b47f90c807ca4306400f67a0d92218adaca84a584a8bd4395c93f9b6a4bde9583c79204444634a8473b1244cd33cf980e443d82ecfac672b3f60e2e41ecb3c5a445d9e88c0e90c339a31806e6d79ee52bdc6808c73e8b7b24899966664d3c1a9305f31f0483e24e36fa451dc1d3f2eda05af6678971e2bdfb7c1461c9407c5c466f6b5af34d992a37de3809a22ae75275ddba0f4f9cbd4b18c1acd212192e587889a36bd73c860f0abe08bcd8f00f5ecdb95e1d560b586eccf530df0e5f3776d8dae2a01768bf1226b7ceffa7ce4e75879c82dd97db3c64c06d33cebc6b35854618355d80e46fa79c3e9743fce5b974723c421a077e7ec7dba286881dbc1d53d442a1552700fcb33f83f73c69a0a0ebdcf2f5d461649c4d0712c514ded268a31509f83c1ae4ff4a68e676d29727be641aa4487c08d4b90ff78e24c6508d69759751a1a23690ec9f8763621e8b107295b4bb01bd9fcacd8748e24d996fa70ef6f8b0992f4185bec8e920d7643159f9f604fba394b6611bff435998b2f097a9e948430899c8c752a1e83a061983f00f88ebb32da214399167932a1a83c1b47d09f77593b03cf6521520583ea4483e2d33e14ad60584676d1791779b532c085d238df0d3bae735d0078e0eabd63cc90a2e13d023983780afc8f83b1c14437937c16a1b7c41414c48cf4ae49587ad9fa5b16fc949a749e96032248c4667f58e295f999590dae1d99a2cbe3fa45bcf4a1d3f0356d64d40367f64b2c5cca843e5f7dd7b88a85d52328a00622e6c317879607bc036c9006d38652ffe21c83207c00f8348a7d0aaea5aab4c89077df170de6d41052641726eb6925cd85a9ee01a9e636346340e209ea96d17b0eb0921b96662ce9cb430fb6ac348331dd7133875769bbbba99dc49333950e4145a15ddb0789c4d2ccd38878080ca9e57ddc6cd5452790eec45482f8e990392e319609391fce0beba19463a9a00d8f1de9fbf22f23821de7d69fdfbf3019ed61aff79acfc5a6ba663a1e10da2b9ff7149aea43bd6c61a543008402309df0924de72c1cacd2d6120cf422e61fc1de345cc8771934d8be77d9437a09e06a9b2d51c849fd9a200fa714328d34f36b684f33df6968b827df916a599a4bc3367814fec21198e2213ff653cd2a463892966c72ffd42a26b3bb91", "0d55dcd08b54e58916f622f81761ef6a2e19b167ac47d3", "e42e1d6d44138f3d2bf12c951f454686f18d590fd30057405b5a3dc2b317fa97", "1e46a7486c5a03fd6758d938", "fd3c1fac10cc82e49235fd57f5aea0ee7a7bd6d539b138d4b3fb623aee591615c1a61228ef9673113a3a90a3687a12d4c6367d5f7bc67d422fdc4106455084d79c2c42c5e86368dd164bcbce7925bfffe7d96c13a2f49aac8e9d1ada3554e3fdc21aab00455a0f33b0c1fdea91b3588e7ad301bfccf9940027332fbdf966463491f7a33c093e0a13831ea9d2183294f89f414cf7b5876af04fa68d594430194429df74fa5915394427259e832bc545c13400aef6cf16620d48280798a6e49773c9316d79fa1dc758e54cde2e2cdb856092d83f4e9b698385cb976fd6cc2538abe055273a5b34a784182ea5e7d3ac9019a05de5e5afe4308a7ed2d363cd50ed6a52df1c616e4a82f607ced768445d13ae4884f2ae1f9fd8313924e8a1a8a23905c92eb231f638dfa6f4cb27bbb9844e05afbbe2ca4d1a3b3a5b371bf33c9ab6f82a7387d61cf8bf662097624145a983839b0cb9f4bd07556800b4054fb3d0bac94f44bcc9b4ac49c39f5571fac4e02ff09f08b3ed5add4bf8bba934e9feb773c0590b45c45fa036382f3fe9782ad19107d4630321e414b7b442b64f18fdd5219039e5740f34b3ce8925d1afe8a39e35ce8db086060bab63b9720700499f82db19a62897c6d845389461260303f9cf2bc7235a898b4620c2191ef05604a5c8c783d58009533a86b27c12b0772635d34ac53993ccf174c9087073e5e69b26c0c3d9f768507ac4d4e2af847b65e3a6e1b7a6dafb0aefc190871cdae6c60f0b1d6137c351d4cb211870791cf4cb8af2ea446f6401eb9ec8a5bcebccce898d1dfb13454df6b35b81ed6d7637e6e261e004080c60944f3a08e8e5fc7e2e4939e7c2607c8cf07d1d10883ba3ad43e2611826f245df571857ae0a7a867df9659f2082c19f94ce400132e48c7f8de2b102c7f83ba5cd1e785597a0ba0d73bb81bba0c00300d4bcd6ec25fb73105a46122873bfa729c0979d8d314ab7ea52391aabab513dbfd1cf01c2990c0a3612f4511c2bcf0f5a07e659a881a7f99c3f1fc4a46e66904427fe26a4a80a904c047d090c861a075c0ae4e29bfbc18b9620aaa42237f4c6fa76ee7491ee638ab5f1cf0b440759828e1ec519679efc776eb1468999a00f667e87199ad6891e98b95fb682e02517b024a6bb803ed23c944010cb7bad0733eccc12d6ab6030c6e88d510ce92e2f98fdcfaa1e37e41fbfb4e99589c0e8efbefd40473db42b3a73b57b22a2f8c9bdaab16831f1b117dd83a77dd01ee8d0c2e92203adb670f4fd65e618823ad196220d70e014c1aafd8863797c61c16382c2600062683ed3a180c70891717c52da15191b02f25d1715ebf33a5e6037092421989c942082f4b836423cc3e976c9bcda185de36f06265dfc250a27d2de0bc48c73b3bff704f3b386f962522f572108458bdb283c6ab3fd33b3ac13a406268fd5d97e17db9c0f780b4b2a8f761d15a4d8b3a0cd73357ecf4d26a6492ee069f19325823ef50bcb2f73326719a57b67eeef506fe8915a1b1ba1a637592268257b91e9c7c5d33cdd947967efc1952005d82ccef9a3ad7ef8ffbb6b658983d64c51242ba53f8f8963245b87a25aa9324c527e53f8c11d55f30aab598401589acd13f090541b3b057b162190f27910718b02a6b8ddbb8ca6cf40bf0d2848f4b76341bd5e78f476862bcdbe2d1bac84c0566fb45b21388221ecd8483d99fe603646b1a9f38a49230cf4dbe5d7883d73eece01bf", }, { "04892b94c65685f2eba438322b29bf8439938590d3e0eb10a29e279d356cb439f6dfcdbc3552af21f7e753221012a649a52bda780bc589ae63b04b981dffd113df9fcf14f17e35e865880a769bb1bf40dc99b9e85e4296c1f2e1590fe02b22bfcaf2d4bb7009a4d692ae4c2d5f0b6d3ca526240368bac55b9b1e6a7b498d3b137f0fcfef1873c5aa2111d7811d45bdc26be1c5d49b8a2f36a999b1f226ec06a5fbd59514485abe696c96ea89dba74b4688101a239b495944e30b3609f73caff3114407599ec5c30a5bad933655de7dddef97018ae15acec46504cd5d417c5052c057ac5f1c6f69781cfdae71db2b4fcac35054a4aa22681027356d68b2bdba721466d130d53ba8f23857631382b2de450232e9ad5551bd7c872ae439e79eabfb057d2bdab8d4ccf02b3003ade2e1f3e514dc92692e4fe5b579c9ee6067995b6c168647ce5a13be8543c23326a3260bb7029d2030ec05e565ced3c5366d20a283a6e95201fd108640d2b96676df712de20e4e12fa53f85f22cb24583844fabcebe40eece11e7221f12c88670bf994ed08e2000236f86258c386b0fccbaab8b68ec6a26fe41491d540193c4c12d1391ab3391de9317f41f505f1f1d09ca9862a6f289a533d2b297d4465c956360371ea3c8ed36e0d1563120654e3a2fd69cd6c9267bfcf92e84cd64e162c84199d6e552b42c33857264b5d7a2e007797cde32934a3f8c68b459cd95bc85e7466ccc9910e8dca65b315c32e43c3a5da908904c42cfc8ab74126919ceeef1054bbdae6ca67b02f1ac5f24808b5eee24577e609a3e3935a24b9ebc1a8dad1fc96abe26012928f2d5782755f3763427dda28867d0b1ad830d3c3f17b9ec278346e5a9480ed23ad44a523a4dd86e65a610ee0de1afab64ace7a3b4918fdc14c6b1ce0ec0903994da9bcf18643d7e0a4e6c08200bb394a89b385d2cb829417eeb0f7dab9fa7306a330f82973cf0917b5ca99b585d2ff0e8584e050077467f5245ecfdd5942e4fc72dc26e5ab2ffc61f996167e68168cee9a6d3ea1e1a696060465e35da8c75a1aa380004faffcb0a992c627fbdcb4e97721271802cdaf08d214ec2fbcb389d75709d7a6b9d35662661c8961f93d4a705e7188613f3769114c55400809cadf60d3b6068c8a5ceef078785171b59be1140c6a754ba1de5ced349df63d67d59d3a8ca3c716ffb506772d57e9e3f2caf7fe346c4ad64aa6c37e43b9bbaa8f58e51bfbac31fa6137728f8e5b728025697e5ad5c8301f6ff39eb2ad595d3cb24257adee88a84fbf1ade4d7550cd9ab94bf48e1424ae83184c35c5a5920157d45805c2e0ad129fc7f0ec3c41b9d6fa04cb8918ef379b0783d1cc2863cd80382585fa05320ca4f9fd90353e490b384ed6c166c6f802cd7bd39aa43667246e8da96992db7537d472c709b01114e95febaac5b1a3c77e1e9a18c2d180e63f0d8fa89f6a1ed63e909e4741af5c2a0e47d4d3f8779b7696358f58060f3f461cceeebb390c92779d30bfdedf1b08ed62dcc05a545bd0ea915f42976e81dd8a50cc4689d8d8007508bf53e7da5bd43c3894968cf0677681c6b818353af6bf8ac205139add1310e5d363ccadbfa0eaf735808325e7f9a6aeb1bee3ebb4a27576a88811859c216b6f84371c43d8063a0d87bd326eb6d81c6896ff534ba2c9c14a51d2cfedf33a5c787279bb4a7ff65706b389756a6191d2f791254233ee047d40d64c2dca878a42f903fd4382f39a89a723fe11848fe37b2008be53f7c2d037981d6462a4eea49df1a2e074957afd3c9dfb4d218a309cab395afe301ccf", "67b5eccb1790babc2dab5e0d1ff3871c3024177d45a2ae", "259603e1c3af3fd0ce3257eb627b02e0c0a48ea2f175de3d8c36570a445e5369", "e14de73c4b17581a7e0d0649", "33522e67ef932da5fa8abe628b51f3abd5049951dbc982ea95b7769652d4830c588fa45e3fcff094c8602b9008d7b2f9bf6c1c4a8cfb515401c7c44a7ec42ccb967722a710199e121a41160b1ec581507e9bd2e2e506b10c4b5a8d6977435aa08e27504957cd49e756e1574c4ccbbdde937de35128b7ee3455d2e665c596c2e97c253c94e405f85eb5de84874c099b4a97eb8f492d28f2e4bc64b228dd5984e76ca08376d7f1355ba8e0fa60fca96635075417d8b436278e0fb91e3bfc7d61ca8c7407086933c061b2d318f46f352099e1d317d6c44098539d1d2c1b7894db668e7a82ff991864fae236570cc420a4229883f1e2242d05aa07e175bc6abe11cc643cf1786a4456a2de8c066fb1a70fe387f149ffbe8cca7b110e256fd0c09b1d3bd7381cfa82fa700c8db1e79809ccf75ea52d0b349264557046e8703a191ddaace00ccfc513db5e78810eaac0a99d7bb1a5725e722d4e595216a0e12f3a7aab2e623ea9e1dad06169914bcd51b643016fea7dc3f2743b1e65877f1fd5581bee5ef206d86494a587ec8462a170746fcedb2c9f99090674ee687382711b4610ddac599732453dc063518aa36f5b4129098fb9fddc02eb8f8cfc2fdf0d904ef4d6d06014f977b29d0e9aab4044ce9c662a18b1a8db1ceea97854e90704430fe9b1046b221b27ac79054fcc68c3abd6fab7da66e255ff0cbd0506c852e961e619615c944cd9a05c25abb63742f5da7bd9939feb0f2f2208c8ce82f551a9d4d70e935dad018e3e4e6998e39670221601c3e34716ba75eb4e2fdf53c4d471c444330514986de45cf44d77f793c17e36a271fc65e6bf08943aef4c66547dc310c7a430e3fe7a54898de48f69f282f52bbdc4daabdb325cec7ab66fce1aea4e2fd932dc1a316c821f5220ea437447feae2fa478adade7cd515a27d8c132d0299b3ca1bc8516c9d9e7c65c38c238c69f03e104eb42a29cacc8d79b808ea6fb233a5056201e3697f81a2d49ccd8b8efd1ab0fd407c16a210767d1d3ca798ee53a4bbf1ce5090d321b1a64fc2c5f013c23829f5b0d2737936ca71595a1d02711c8a7b0e74654e5d76376ae26977dd49c68e3c0a7b36e047d44be42d732c31f681bd7b1b4b339f004ecd847960377acd005debfab13d0fb88355025877630aff753a7cfddf6851e8bcc8ec37b8f9149830f47e6b601098b2ba19a4c0808e31e8927b2525cb82bfddc9b4bcba2b46bbe768ee278fb89010243d16f9679f5ba4f13cfe76b5beb16c7b28daf99b0873098115c2233ee3402ac0f6c899a2cfcc83b2ccc06676999ad48017c4ace507080a26501993327ebdcbd1e2eaaaa99f4998b716cd9e36eb26b4573a03fd1d18047198fdf675ef4f979864ac85d230a011c69d8b6c45e9efbdc2a03f195c9731b4cefa60208ba845c0978e73d082bf6d6a513b93dc805a4f5973f4158f60a200167ca88704a15ac5ab1f38ed455a426f7c6a96b6bfea2ebc1ae1247cfe5ff29ee81bdbcb53b03b89568bae9a6f311d2b20e31c2d91bd18fd93a37be266d0de8015d52e325f78356dea0b77cc76f28e0f06e4ec705d1328340013a77b0b6196f44b7712fff4ae0ac7f6afab9456a95012b7c6d387285487476d189977e28f6c9d1a3f736320d61302c2d627d5a7ac8cde4988056b55eeba27efe7e640f94c115762ad5849423ae138c76f15b47bd2a2bde2c492489b7980aaf1c4e32a155f858d7be4fcd0f8a18e7b5d97c5a08d7885d6d56222ef49542c7f80498a14a8eed1c092543aac3439966d5b5d0cb9e602f4fd795c09d652b64f9ab67e38f48c88d18e30a9774f37e9c77b7a94cc7310d", }, { "4ab8068988d4bbe0bf1e5bc2fe1c668cbe58019c958dd2ec97164aea7f3f41c9f747527f1c0e5fdb2cbb9d2ad704b6955cb731f14403dddb1a28c5996707635e4eb5dd6ac33d46eff8e319cfe7cf6443869534ca9812a5b23a6b4ca172afffc064dc2b28197117115431e03c00447f87d9b45172c6f724006270a1d41fa094847cbfac9630c3a785f488c1f5cc407ca6f4cd18bac43cba26ad5bfaccfb8f50784efc0e7fc0b504b43dc5a90a0525b0faf3c8b4b7046fdeb1cad87ec667ce3eb6cb4c358b01393f3ffee949030ef9fd01c1b2b9c5219777eb6ff5b1d7c3ef8d8e3bc2193dfb597cf942c5fc50befa527fac0b44cda2bbb811b06ae87459750295371cd232754e2bb7132807d1225950ce64949b0650531800bd0074177677acad937ee008cc0bbfdf33c6b0552000238494be8be412a3e5cfa359e619d092c76310a76bdcb22abbe6f16b3b116b5f95001d20e42fc3c9ff6723e580f378475788eec265a1ed2087de8cc2eff72184f73fa5dc6e68a56dcfc85350bccb97135386d5b827c2d9aea065708f5c921454d1b9303f21d5adf19e00415acbd86d1e5e42d78505b033a515a435713649c50702f54623cbf31469f355c3be2e30dd8c72b4127764451d79e952ea1f9bb0269da56dc07060d5d9542a9c1258ccefe53fa3f7b6073cd38026256b45c01b6c5dc0d91e3139f30a8d1da7a076738f5bb23352693a8e3cbbb46226fa22416680013f9e3278913d06aee4a62457357f0a68d173a360af5e1411840e34c574b4c6b352f92ce33632911ad8b6710d357b7607ee19679e777baffb8ae3c0fe9786b2e97fdeccb5105ecfe81441f549bc6b50ab84b749fb33f8f6bddcb6bb733d6d5dbc4b29725b8741439b8239e53fa435ea29ed3324202b1bdd07d1987b0e06d8cb51013dad897ef02401290940ce3f2af72c5d1b4c8836299008c10b16c7e3e119e41ec66d9db6929ee09bdeaeda08a50665c052edf77b7dff3d8815046bf71d5015e3bdb29a4f507aeb2e28c536cdcc9b8d1e89849a0683d78f99dbfa90f94aa5dc08587657a8f042d718080de5d4a973f232f78c387b63c7143fc2a4380c491414a18b6c4a7bae2194b62e798ad7ec7d09e409425f6d0973accb17e4d860f8ec0283584cff076d93bd9b0c4873f9c57cddcebe3c3bc8afe793c6cb6b26c4582847b07446b7e1d9757de6bdf0df826cbc502bf88cf3a773866d3ff293034abc4afa3091b2126a278f50e47f2f66ebebb616e342098ab690f7f5828bf8cc4742c677d378893e9f188e8397bee983a9a0998de2a31798330f8db59a8581e1c847589bc0e2d95ffa68e39226cc15cf6cae5c4f5174e7848375391dfabafec202565ec2383721339f04c5c5d1da953d88f18cda65745ee8e99805e35203a6545a0416923b38c5db3c8aa00d64354bed27d7c78c4b257534bd7a18107ebe64d8c27b6afdb330d8efba79fd1fae480cd51fd3626bf8d79fb651b7c6cf752aa737a5123558420d48fc86451b358d270aacfa6c17f343b7a9956e6f64e4990c1b3f1e5097605edf5ce4247819b19f245e9a90758dd42c36699ba5cd7f3ed99a7df7eb155749f4b42d192c47cacb6b2865fb9ef2cfca283865cd06e40cdf7f89d76a9e2eb393e2e0ac0e2776da929f3f8e3d325d075a966d289c51347bd0bd523a5c81edef63ce9b72f5114c88b08b16edbd73f518096240a5b37421843173be8df4ac7c587a17ca6f2916f7d9a10dc75f81bc778a1eb730d12b51555cc414eab9c066113a7edba9a7f1a18092ae47f12f0368ba211feaf34a3b48a7ff5c91b81cf7c95675a4001c95a19d284fe4197fe8823909a123fcec5e45935da12416be1bdf14918414ad19b54a41052f5b8417ddbd207ee01d6a3e62fd9b0321b1c13d91d6ce15ea7b2ea0c670a5f5cb290ca8e62c26c6499104ab8e9fafb05170ede246bbf7313625d1fc9576f1609ffd08852a2f4b73c04f1f4eeecefe3f3eeb2185a618b6dd3e87d9d3fdcb349cc83c21f26b6c662bbb857aa95378e991640a160a23cce76153c134508c68ec54a5", "0d471079ad3c3432b6de852ec71692d12d9df4f984554d458a9dd1f28a2697976da8111ae4454c9a23d1c8eae75bbc14f8b00e7c065bc290f8938282b91a1a26c22b40a6708c40945d087e45633a595beb67d8f1c29a81", "f3dac58738ce057d3140d68d2b3e651c00ff9dbb2ca0f913be50219dd36f23c6", "bb2d033de71d570ddf824e85", "238c4e6be84bfb151557327095c88f6dc2889bce2d6f0329e0c42a5cd7554ab16c8b5a4db26eab30f519c24766b1085e11d40823053ca77adfe2af387b4dcde12bc38502229510606ff086265f45b1087375dc4a022eb0b641101c74ad566ab6f230133b7aa61861aa8202b67beddc30dda506691a42032357010d45adc7ee633b536a2fefb3b2143837bb46db04f66a6e2bc628d6041b3d306ff78e96205ab66847036efa1fb6e6a387cf8d5a105738be7163df9da0db48e3d8fd6a786f0f887968e180ad6888e110fb3d7919c42a7f8c92491d795c813f30ea645fafcddf877f5035f133f864fd0ba1415b3d698f2349ebe03d9e76610355e7fc23221c5c72b1b2628a40b14badf93288fc4abeaff5306d274f21938650ab236a39496d3f8a6e9086eac058e365d4335b51eafac813f9175bb7bebb75605909ec3fde6515694e119f7b6e96aa1d6d6454c3a7dddeacc83bf0c1f5f6c2a9dd2f460f3e5b074a33b8d7904e6988ae43a22a87f0933f812e45c4c518bf83e606bad4c3c55422ab2207e9d3cfcbc5819049f55e35b9663273d9d3a6f8a897fa38b0dca77eb6c344290cc007b68d913187f2cd480a40262623a4e95d90d5701ac2b9d858d70a27f0672f919c2ded1fb89134ac9a8ba6ac62931c832372abb70e811dc50cce264ece65e87338231f18ac007c5f68f3b1c5904ffbb2e1dc361d53914917770d66afe28c547d8cd5896d892cbdadc34cd6af348c93bdb8b072f38b085361e62ded7a38b4368824c759ec7d2cf4caddb9191e5deedc8b8388bc4ba2c0672321bcda3a7343c9ea71ef03750912f35624d81da5fa8a6ee676c4efd99d0c7258b844ded7b35d8c8233a316b508d79c7c0b3edabad5db9543615179b1c111bfd78b79327ac5b4155336d670baa592d441c810cb1b7c07f3d35473a45b57e780b7d997782aeecfc0363976fb608d6967844ed00b63ba75996054d090aeb605c195b1ff86f9d9ab5892d27632cbb59c06b3ccd69d33ed5dea9398f00b7c6404fcfe2fcb5924e4cb75cbcae0a1b084ea8b15eaa5847431e9ab70e4afe15b4c82239f6165e243e3b76d6c91d23b16edecad8bcb16898641f8e323671452034a8ec9b42b29cec0db210bad0444f1c5bf3505cc41d514d5a270d556f0a34333bd06cd6509ba253a6ba7a6db8f1a60c99f0c3d566a038a72f1271a178cc3ff890b0df1e7438c0c1a12d9873643e2d7bfeb92379545de50834abe2a345faf7ca49beeab87ee516dd8598b71196b8cdb15e7200cb5bd814338babd74c565faaf33d9a8ed4209b417345a1ae611880ea22ab2e894d5d14a28fe3835d3b2718125f0e6daabd85327455646290ceab89e579ed5e1d72a0172e4a6d8da70290b5022c941f3866f96cc4218de5d2622d13af6dab15760a1ec5d10918267f9585284058aba611ba07b1d5711cef505869831699bedc2b190fe1d578814065c91d87a8c8dc9b0d4dae0c80cd241f0bda3a6d5e714c894b7a48b1e5eed4555f103eb03c9db30efcb855df422d7451a6d70f28174c7ebff536dd2cd2891f6c3f264d632ca924c4e0d84b37cf8e06e6f2e29efac6cf008cc27f062441278dbc9f09cf44987e0e9ca088a48437b0b89efb9cf00d3d0c5fb449fd4b64e21dc48cf300c2d80a502cb583219f1881e78e647783d91dd2f3b389a1594eefd8ea07d4786f983d13e33cf7a34e4c9a0ec4b791f1666a4eef4e63bde7a241f49b5cf615888bd8130743bc8a6d502bfc73ab64d1184ead9a611832b7e24483a1a0fc475d9ff6166b86a18a3dc96910ff182cf326456c4461ce8acb3467f801890eaf1ce0b24791da9c650876e718c0bf43c475174f9712dd4a228695e8f8b2b23fc4a06358b4a6a8e1afa87a0280c3e098f218f7a6d6bd716f8c105a7eb799ba0220837fa5a96c8a22a826a6f7ea9d7216a24acbc7b0133210cc17c8190507badb421bc54997ff9340cdc1ee415126ac46a4fec9fee12d40f06300f7e397b228250f36d6f0d2ddad5fe1898ea690e4c7cc3a116a70bfaf6d2dc996753fffae40ba5280b8356b7ab4ffbc914ec74eaa070581fdd1d9e5aa2", }, { "4d81b652fee892d575bd13dad913d976cf0517c819d5183a72eba995b1f27efe743451721ce34791a15a6b7a6e44f13d4a080563dd1d9d4f0946e5ba3863b9ac970a1fb4ed66458ec1b1092ff5fa6c3f0271a2df8e3f2e97851352be760b6a0e1589c202f00791b1b89ae0ae944ced96bd90754bcfa3e355b735132d407d3b5507fd57f705e8a8bd82886b16d459ac91e921dcb8c5bf0d7cf420a9349ee589a5e2e19ce7c944a54ccc1062a0690f3152300d0bf5cd1871c1391bf6d7007f7ce26018ca2a5c6f76287fd8c8e9e7f93b1806460dd35f7f95989a8b6f9a0aeb7c6b0346955fb50b8735e34f1ecb4859e34ea0f022ff6fb797094206a34cf120b7f4664c531c57da513b296f0671c8e9bf68d9e1674998fe52da04f627f516dee97c2b3c988216e9bd3f58c3b021ac70898651f1cfeaef21c4f417ebe92dcad3aaf50f4277262c356584f816a5a5862f2bd720fac10f1b86033371ed603bc00a30cf4da8f579dd5bfdd571a37af7d2a5cef29f9001bb1605ee87f24ec3b259f381a69b771f78d21c4e43bfc83a916e08830d9885c8ae8ab6367c05f92e5eecaf0488262300f83f4e3bff177590857e149216995bc52311fb9f16f4cd74e07c7868a39b699bdbb7d7dace4c6a53ca7ee6e11741a63a52a1d96995a6dd752356dec6f14761ccfe38a6cd8511204f8f0630a747d6e19a77bb030c61e0828436604a28a7acf4a5e49b7269ac93b93b99e9e2e1c0c47b377f7e44e05ec6659526afbdcd5bb172404ce5a9f8786234114c16f20cda6d4359eb873a4a4d9fdf734e9c40aa4db3ea9a98939210f6c62142dd144eb78191116d194bb766ea96da38321ae27fcdcc196560ac75567297984fabe6072c771899906350f74de6d18518eb6898b934b11e945d94ead02b821fd6682602e03e9c70a1ec67eed33874eb24dc83dd1035fba5928f8f62ba1282907aa8935ae72fcb881b3277ee6bebda8fc75d6cd792677c25f70c87b11e094298b2d5f39904be211ff0980e5b83e8ea4a455622d8be9efdb5aa8466c88ea861407d54d98112faa10293af5e16974861dc9f83b45d21b112cc367894c421f5049e49dd205bd7c15e6a70bc810704e2e3a3659800864912527f8be743acdc474a26246a81fc2bdf669b9be7a2a0c986432e1e44b5675607e7e1ee2a8dcb72d8f1964272926e52f909ede0ac8daa32d1d850158db76b959e4d83c9da4e3bb23fd1f5b26463045d6cf13d187fe74a50c09a654d52d0e2f01d66b9f8b4f4aaf4c69fa62a02aa876f9bc4871aacd26a6c6ccfb9bea09cafbd0268b5b65d60aa23ff504d02fad4719698f8b044ca1bb037ea6af58a06a448080dfdbe6a5d698d5db9da5fb4aed04a46c8fa8b93153bca00a5bf8aab64d2b371d072db2ddb688a9442e948f0b99236828dc115a2fddfa2a29e2d4e02ff0173cf734efd4eb687e3f8712be82abe1fac4be0c1eddda090803fbdce41bccfb58c43038991ba1074b281a09bac5eba58a99a1a9678ba26f8f9e3c63ba095f02cd8f3b56aadc5de60477efbf3dcb54b854f651cc72042bf19268554c61b44f2f338a75de56c3c45b3ba40a697f5f21c4557380c777bcc91a151e5676c2a59606200bd476cf98d20b4cdc64bc3b8670810a014871be018bc32fe239e287cfe8a7cbcd1e8b55e08692ccfb4ef871cf797bc0b1fd7ec37931e35b6bc5d32bbe7ae77b9962c179f96436e4a32f566298d2235acf921e38c3f1942fb7674b65e222d17b95a2e58f072c63aa4bba1ce48c303f4bd24d84963f18c5e670015c52342dcdc9c0b348c7dfac721b568effe2bf2f2e816ca3279bbbed823beede8e12fc5bdccd0f1584deb1f6ea1875e9fb350919b675ccde0178bb83a4aa5232bd5e8e9a1b8daf905c6197367a0d106532297ef89f3bc690b48224592c768bd9c50a63d0881370d475081aef052b444744b33fd3fef674a37898fc950f887ed482d2a51ae615ef5b1dfa3a23257e6a6a319a4e2080b2c4094bb09e4b390d1fcbefc4d6c5dab620f8b05b1bd5d976300b007e2b8120ef8a6c9028b7d925c795058c6bdb6711fc5fc2476b9810d1d81bd24637537716edd3b7068b802c531531df710d3682f9865530e1ed51b3b56d860ba4e972bbc74662cdd1e2ea24f81bf469193afc02b14143a32e9556e3f2ecef97c65", "2538d98b64b6aa9258f9141840a5abef66d6037a10356366a3a294719c10d6c148b04cac66f63ebff052d730f8821f5e5822d869573bcffbdd636c7973433abbf38767597da5186df8ef9df071bc4ecade2633366102313e659db8d8e0f293d379fa2df79f456497", "a5049b0aa153e282457555bf6f82b60fc81aa6fd1c2ea3db031478ffb74b5b5d", "350287a6bed5709dfba3d35c", "849670914f5fe318eb01e8849e536374ec11e813acdbbe6a5e82a506f6aef4f916a3a7fb2e41db3adf990175e21f2386d1805af9bbc32a6ac156b13b1a9505958f68599019c4b7297314229c467114754277b10e9f49a4d12837ef24184629c8902ebe2a23f740dc826b01f8963d47100bf617b314835e436104eb207fa9a1079b8feba06d9369b9aa8222d38d87096b73678bc5db9a1add59394530e678b6ec93a80efc6e8320f2909e3e891306d69b016ade0d30cde64c2c903b401f9d01a29b5cb8619dc68ad6c21900b365a6b657f7d9ca4c145fe598a94eeea741e20a9329996b17aba5d7115c93623f2f5d6927068d0f190b49eb885429d771bbbb3980e9293e4d664a71c3cb629d869dc97e58fc3d328331b11df19a38d61e1705ec4c3d779168abe049e9d675337ff658e00d2d610c8f227d1341d1c41f1c01d8b5d83c4b1b30ae4318da9822f46402ee8cd5cfe9f3f22d90a5ec2d0aaa0baa85e10f5295cc6005c5a0887287b0c867a23da1a4c2196f91fe0bd4f0db1ab324c26fe6088d7583f3cd052b7f6fca38e8b21f98fd07fe78b7657da1f586f1fbd3d2b4079e20f21dccc0d269d53a29deb7c7fb63cc291d1d2c50ff163e08ce612310d3bd622f2416e193078ce4e1463f8a3490578af96ca98e665468281f1af9117a2ed23367df19b570885de9d6594f09aaba4090bdd1079720b08d54311793c97bbe14433b031c865b059cb4f75db74779b82c4f83eb4bd829c62eab995027b548063d7cab7d1a6f9642da6cf7181c0ac71594b97fc2c84b1768f81eb287091f63c76623c61e7ba90c922c74d46b9ae5d8094d9752bc1e8020a82601c356a201e0473d540053c707a88f4baad37826152dd245c4cee6b0019583c61e4327fdf6bdcae53584cdba8a503b835bfb5df9d649705fcc1f09376eec96c3da1e105accc1cbc21d90f527041a9beb85f8cbb1ee8db798838bb45374b741618f83b5d0801a3af2f640abdbe74ec3dc15d6711b4c1480aa8d6084defba82ed221ba359c9744705c4feee0955c27ef468cbb816694516f73fb541e0ad4ccf99ec8b67ef090505d1f7c4c3a8ed7e291c820261f12d92bbc6609da6c275349819848c9112826674f243acb9a29ab73f17c8f8af12c7437c11972c824f00db7ad284e51b9b508a925f0664bb259b4443d56463bffc9e5d845c9b9f79b24c1f457088fadd281f48238866e0b92d6253638eb188bbaa8bf6a81d2b1087904974752697cffb00b4ba05e5b7b842a3d2c0a743e4bd691625788fbe9df14600643b1d161bb2916176b6ee40aee38dbb594ec2735d41369ed3a0c6dd9073f1eb51d1b77eb9a967b53670a8ed755f3b2b73a6cb50a9e1ea7549346646dbe4b801c8aa642779d8761b6c2d2e1a9995e758ab92f07c4eb4a23c042171a4b354f434ced5f6d9ccd26cd6c2506e5023dc076ced15566fdabc7364f4a8594cd6ec404e1a9470f52a83052390e4f7789ade9179b069d9f84ca2c7ac9eea51035db817845aded7405bee90cbe92364c8c7cf8a366cbebd7a972438f2a9881395a8610a2cd0c06c46b60cdae5b1f473f4fd6ec48479cf35101656f05485198a470cd36af22838e7ba3e28863cd8ba7bbba7e3c2625c1106a6be44c9e3d9b9938679b26f0713c62c3757a2dc8b2d9eed5e652220a7711cd220bc91a9afd7c940dd8be71616ebb8b2cb0686dfa161c6ef56994a3cafaec5e79bd0a2531fd1c1a42771acb101a38988bcba51ad85bffcd8c67aebec5b37d526b29f7b9d31388e1e7ad7154f8e65516f0d80a30b88c2b868be2541d19ea1d2bcbadd30e2fbb1b4678bfef7f200e0f8309ac0701000c52ebbcd6fa00cb85c8d3ea9c5aceeb3adcf3773cfb3bfc9ac764d031d7c63ab888e9b03eb9fa74554dab4719d426d0875a508c8c86b22cabfeeb70b0f1461db4e5f639d2a2d28a089dbcc48e3f34394ff1acb887b89f75d3236c8143bb9b06273c3878744340ea1858a9f383f8bbdc259250e23a3c3992bf8b7ca7e1a66913547710402bb538a8866772d11cf4214060ed091d403e1c9ca3af75859259f88656a1cfecfdb49d57c193e60a2223627c681a2fbc7390140aeddc19df035a5207adde4f5736bc542bfdc943ae8b094f4a8701618688fadc2284fb423f602c41ad8ee11e5d9fdfa67fb7dc7d4dce7847d4875b3af667168ebb6082f6911c95", }, { "67f0494a728fbfc84e2f4a043e121ee40f3b12b31616c78e157ed970db28674318b08d8b3f4c538d7b9d91b9b0b09ebfebb07201c6398fdbb8684c9390b3d6a8636333a3b086302b24c2e5d47283935d33065efa3fedd5f755218be5d4618d38c5c1db75470ba06bcd853f3f08d39c3cd9fa3618e70b103c2d9b2101fcaf39c1701436b720d723ed5c622d6535c9a10ec4d727abe237e80fd20911ceb84a90285fc6e07f9d036cfa65995f9b6300a927d7d0d2b907bac9d9c4daa87c2438a583fe85029c886f96ed08f5886bf53292cc0265850a1f4ee3e3288b604dc305d0c28ad35e1242f4ff4ae988b6deba48aabcad2fc6cd7eaab0a63510f3f915c4bb9f9719b1d90db123f639d9d4f3227eafcfad769c2b204dd2555dc54e738909122022c4f92f751d25aef6f9a1187750e825c68450e6d1223c2fe88aa27194b492b6788be6eda80b9b9f053cb77c8d9fa15324f23af5147624fc00c66e947b004bf38b31e1343c7cd341b98abe462a5f994e51d343664968624a2ed0dea9d0299d5c5a7e9097fa63d8b3ed96f917f693654766a9adb01110fa3fe0d8e9b102860d5c049df3fe00ccb2ed62ab05583e6aa0a5134d55245d4f643e274def29d3fc86d79979d599458786a8338b0071f6a01609ee6b2e4bba9289e2df780bb27491890d0b5ea650e62df819b8f98aae99a1b8870ce6d3c7785ca957d5b4094946925751f0fda1d62a9aefe3937a912c1b49b4272f87eea7e397feb84c0702929959e38a568460811e5064b1caf5dee53f920c6e19fb16fc9214b5de1cb770b510533f66d8a0e7f6f04ba8ba41869f8018abee31a6042d3919e217359988eaa9db2a10b3caf7aaba43527484d81304f0bef22165f74e9e1031b545ca3d2f74195984cc237b76ddbec85142a06446902339b1883000264031db85fb19b46f320ef3fe316f750f2d3d6070dec5b66ee8ef20701f20965f5171e44c8a99bcbca7afbbd81e30e74c6d48bc4b0d72baf562da6581fafbe14b6cc597f75e53b305036ede219ec56d0c0d29571a9c110ffeeb747fe56f6030dc26c8d3841b868a1ef56840932dad9f3bd7f75573086571f4d9f0d949510a2577d2f8fbed7e850c73ed4c071bf9a656d09dab43a610b49aeaa57333f67d586d4f50683dceee4942db9549f68eef4c5f8df8a2330857cdf2fc4025f2be7d5f0dcdc74a9cb593de91282787b716d416a3ccb8d6d40fa3c70be4ecfda26a5caf3724fad3d98db16ab6d8f26defc68392923b69664b0c2d56f01a549284b042bbd43c8faec940187f190aec08d06f9a62ab03c9f610f64c0010a0939451d5502511dfd3da1fec5a38f64640c7b6db2961def257eee9a3eff944828e9557deba68bd8e42dc7a9c1570e35537993061fa0f5351fd3cf4ec36386ec4cdc5a2882d5f16703b900c5000efa63888d69982e5ecd3e329c8cf5f003e23ce03c55631246ca15ffcadb0fc9d5634252ccda812ba7bf5e343c44244026512062a68374ed4d8add0855dcc22b30148e0cef0f2886be76bafabadf3ae1205b43c6deb8a41c338114895dd6b49deb329ada31b350e02a1bdad4eb05b61b50f9d22fa2863bd607406f552713e302467ddc78213d584b4933202438d63f99d011b97297f5589f35b7e45ccbd76f02453b7a7668c2b1a1f5d1d63eb805c8881771faaf67433eacfb22f9b6fa58b93f9423a5fcf667aeec39751ae17ad36992556431bca77059a29353598dac12bd3036633d2ccadc18f44123e5bc074f4e5ca380095af062fd83b647015259be929011cfbcdc9bc5d0dcf9b688f0f5d74da95746f447a9e1cb5028ccb2827b45129d04cf6990953a6d8ee0e67fe6bdbd8004f4744cae5607fe7ec4a0f14fe603dcead3367b6870d8e751cf57387d04b881f92cce9772d695f19b36e2db2cf6a807c9ee83225f5c09a11b50e99855921a4eced8e631af7c234aa31615c00ccdd7c6ac5ae8fba6e29cc233765a891864c7d73dae08ed1a3c27cd423d8d4efb550597afee8356c12018f496637daec83575f5e38ed2fdbafabafd38483c239d31cb4d104e93d16eacc6050033a3c86929be4ca8914a538bf540b43d7ce7daaea317bee1ab80504846554879f900d312bf2fbb406a0edc5f4f809cbc68675b0b7f09fd1a8a4d52c0929b3a8b9c1dae4b3d599b976867e6a7e8736450dabf5c49c949544386a71419324ea4ce5c4319899ca510f50d07ace57b013655b0929f79dbf3cd629ad17bdd10109b7c53a4f5f04a16e5471e823c898362df43f57ebdd1627b33fd4cafca6cc065d9140acf0454d5f99be47bc87e0f3b4d4320bbf0f21e7c261bb8d5d615963beeaa46bdbe9b83a8277813ffe6132b23564bef5", "74dfdc364097c39ef91c01b707a522e28edb1c11529d5050ff820234e6c0295aa00591e09d547e9671804d7825705ab44b76c59d1315ed1297ef477db070d85076693013bdafa92e2ff6a654660008b176cd4e8ae23b9c792be3f7db54cf2bca385bddf50a8624397cca8ee3cb96944164e3cb461e68", "b3b5ccd7ef49a27d2c6d13c0ae77a37abec2e27e0b2d3530cdbb7f36792a7d2c", "c0494bb7249f864f69beab46", "ed8d6e964bcde1df68e7f362243073941fd68ac77929c8e480c89f519f748b3dc337b1af6231632c975167a8425b174b42c2c60dfc0ec85a0a212bf5c9aada818a83f9664c8712d96de1036b5e5d8c8298786b753638de3a8da958549f16eb9c723355cdf7b999aac464ec39df7d6c1607e81b88b63043d1c847dab618f1b19336911b4b0145c2a694e61db71e021282006d48e37f10f3b6314dd012a07618228532c28ca84a936e0eff83723d117b2f2db857d14af5bbd5948a0e53018b31e57cc2a81f36aa013a844990753ccb347fe98fab294cbd252a8b8f7246276275d2780511fd3cb7baa2fd1548184f968c422230f7ad73ae9dde91295f79f6b799e7d234dfd6573fee6d6ae748b0a8cd7ed4862ebd957390826f276c2afb01fbb4b64b61a1bfc138508efd630e77580867bdc1e96a48a694cf0db6c2a11f05dd0bc8769e7200bb0749f5798b6f3559de55d0c281eb5df22b731fbbc109da9c68f209b888e61240c4c0ca006d105c0a7f43144021547d3316e5a99f6c429f9ea2f17d77dc68bc9d5125b6260f79bc8b3b8061972e6757d87b6544f21645c0b4debe5224f7c48142c09f35b8e144c0c1e6521f04c170519ff744d61abd59a56d25a26c5ed5972191b25e78e2140f3ce68fe17be9e59a79f6c69619a79b83614c670c7736d19c27fd22515fb5b896a6418cc0b4850e85c07b38b995cffafd9f69763cbbcfa9d1bbea6868244a66a5cc82e815fae09f5775d28437634926d571c2b0d200855e09cbdc67d10f85bd4cc334ded4c83aeea57f8e373a950f135997666b653e8de47a3bc0059525720045996bff500a47baeec97808fe971d7693dfde339e8beca3598fbc053121536c30d0af10f8f5d8e5eeaaaa9586d7abb563fd69e88351f93bcc46520f6d97c1a49ba9f8f6a25cdcfc11b2a722910aabe7435ac8f0dcda9f824fdde80850f21a2d4bcbfd2e9fcbd14dec05c117a9796db49e2f0dc55e74c7f0f615bd049fa7d0bfcf197dcda3ef3de90762e6f6f9f8a8936bd04fcf2a97cf18ecc8f2f118ffbf02b67f252097e4289d02f264161f6f90f79e1e1ef8414b01a9e1a77b88c039ad6eda6df1e28fcfe9370f0d574aa9e857dcebb19eb7ce8af9b19b4481c9fb3e1f0db3b02af483f737ce3ea824b2165e7c0fca8585383d4b0a16eab2c7e3ee5c038f939a97bc8e1c093cc5372ee45d81836c988f3ab3e6ee0e5f9549e4b7bc381a2afac2074cf75ed56b0e757e7966cb253d549fb0902da98294c6dd4de3c2e166b7e45098d2729b1393deb68471d4d3218dea3dfd0183b654ae4092a79357945eea4b28cfd06b40d30d1b4b8f19827895f6f908f0fe511f74ec84cbab2483ca4bdfc6ef50178eabad79b18b58529c9328c13c52c2869858cc20ec36ef7717e1c743d13f9607bbdb0b701d9df6aca7366814e883d23e51ee5b0f20ef70e2c4134ab037d213315fddc89009260981329a1872e541767adbd5ee9501e7df4ef0cdfae9769961f8716ee7dfbab0ec89b3f62e987387d5842e124a69b07245d359052ada50cfd67472d27ce2c4eacb5421b62dd7331da54ebf0989803797f4c8c781d0e2e6477b421c7d5cefc8146aacc0012af3f1f7cd71ce2b1045d86bf48c9a13fe469a1865294e160b4975023d0eb24ed26837afefc250a914f86f8b1f5d67d65e9737e841519148d4dd5dbf2b5a8b073861288ec9793d4b113d71c01727f67d791852fc3946dc912d60fc66bffccf4c45d859eed9f0bfc7f89086df5d5cd830ac919aa7cdb4504018052d67f6a3ca012ed69187cd5fbe91875cfade381bff1e804ba59cd59f0f75cb46dcfba234ab9832c3fb9aa8dde19fc1fb30677ac1793a38d94aefd9ffcd4e777e9e4f6d49e0cdac6c16a36bc2f3ed8e23b80350e3be6d866aaafbc8cbf7c69fe44c2aa80651164803150c23ebe262aa669c77ca94d215895d2ee9c3e325a0bf2c61e419a41e0f7b1ba8ee0508307d49301abccd5b74c054b6c7bd1aa67cffeafee033761d8226d9dbd7214b130a867764062cf4da685deefa23693b8549d5ef5e53df85c19bfb3c43c6bd073e7a836f849587a4747e1a9a3c7194f6d5472d2e3e4c81784a3061fc9bd3b94862c4784974d859134369486f2651f1db94f511c6f59f41da0d75307191602730b88e4e6101fc8d392c87687f3be454dd92fb8ec380715bcd88aadb63717cbce4db91a36821a572c363759d8d0a2ab007e5981b78731dfdea20d900b14f0c5ee6a4a9b532ed2134e6edb4dc267f001cb88dbe43aac4aad453b839d035697df7de98ca7a9ee7601228a79004b89796e9ab971aeb8e62c789bb21f38b77b492c57db402bf6a42ad0cee169e9251d865ea3e5f79b1801ef1e53797aa6c7060d6f9486081", }, { "04cf92a64cbe135f7fc1d7223b95e41d13f04b482018039f4e7ccacba8aa15ac79a752c5666524e527fb076290ec80a3dccbebfce3ee9b316a65fd130f12bf88b9124d1f7772049e6d0c01fef881a1d44c8dd02f7b6b60e6d15df9e06fb86929cab64842284de09659e19451623525aec2f5dd3e603e24319b1d120bd57b34a0317ce25ac9c2f022a4847306b998b57c8d92baeed0de1f6cfb3177d0acab70de275238f1152813b9ac87bf651f74e1ad079b9bd779ba4374ecba459865b5768d08ae7e1dd691d6821895e8380ac9e5116580e8de3a2c5326e698bf4c4d35d955e45772bae8483d01de2539e8ee1ef9539ee132d80d85fff41dbe406af319c0d7703292587bcf5959f49241e2b03a364e1b682729ed261d0ae45d74d77634afe667413ee210983b042a7ce6dbb61c29d18450fa7176177b5a74f032ea24e1d08b220f6d32a7a836d1241cacda39d6acbd26a62f9dbeaaf7329a291dbf0aed4a2cfcb85ea360947585b1215feaf70ba71eb2d6bb7081b2a21bdcbfdae6ad2513a9dd714d3d06c2c2b7e322a1db2d48f9df1fb44fa066f2bb42b196295ebb3c0898ad55d5b317986afaba0bd5e754cec773821613e908ce2bba6454181f9020b73e758df18c255c87df675cc6bb2b8d2eada44196ac10c26674167f94a79f4be515d8d6a1fd3228dc9a85a355b030845dd4c5f481d5b6e74acc66de730629581b022fbcff61e5dcfb6a7f511aafd577849a6b057021ecbaee53986159c1ba74c3e930c34a159f467f1e9799cd6c1151067c56769e43308c96c8edef8aa7634d909310dba9af2128cdb8c29b24d3ec2a4f43a1ed86d1791c9a670b240e6e719f01827aaa319bd3ff53959a776886a1b7c942a54f141e6bae8576d294e44333e6c5ad90f74863f69bf890126016b318e0f6bd2f0adb9bb861118af5f6cd28dc93d56c8a1dd080b8c810ca29267d410673fe367dd9d1353ae2bf2fd88d57b4202c21aa49f12a01b93acbe260492367bc219d3afb6e6f35502f6529bcbcdddce9fe8632efb034a9eaff8b4a48afb105d04e3fcbbcae010ddd6636992213750b12fb3e01ab72aa957136e0bae591bfb5e0fe819cac82a98ae8df230af399160594540640c6b1d537e7b5f1cc47b08127ae02c35b846de56c4c08773fa18d4436e14b76a7fc4bdee301d0af4880306f2f33328ab79f6f24ec779b2b1928704f09bbc5b0b7108e9a115e4959df79c80eacfb98649a0788867e23b2974b22e654ddab0494bc922ecdf17727d0f0efde9dea7601857d890bfbacbd93f7df794bbc254f50e1e17eaed2f5d5a2e6c58083aff68434730d406fb9fd02b0dd7bfb99a04aea812b6830fe5e05a044ca21c77a174bae8b58eefa11ecfcc1c977bc6218064c9931b5c92f13cfd05799f11e130869c293c1b08dd29c899365014fc8195514b286c97cb6dc4b8633e47751f87fbaba137b6aa04d072ae06c2b2f34448449f60b1272c1efbd4722a2be749a3d2e5450aabef1f7c51bd8324607668a8caf8097c2f358b1b09fd3525d47ec9a7640eb20ffdc17c4f7eff63df75dc7830c471ace3a727feb11533d6e9a2a08106af33069cf482ec63724032e81cab18e12cb5c4c3ddc374e2f75bcc99fc5da09b80a738852a14e8ac552b8471c6ad52e35317b730db2c13c277e06c643e0d0fbea43833de4d2c7a9247ff040e9c56f1ff7ea92049c5341c4d1478a14275a10119d934e8165152b89951bca7ee1399dd8232fdcbf831d8354640e698b68799d060ceb877201b2fb96cec514affeb28721e163e1648164b9e5722271db9b0ee1a7f96819fa1b1590e9daa598d9571ffa3882db9d034056e9b2785a8d13686eba61d7d45cf2e9ecdbc391739ce89297211472be18b21401658c5bf29fc3615924382d802a166d05dafe7876e70a0d081e80c63632da379766928a0555eb5e7a238cfa4da267527c66caf34dd40055f2801b29b3f5604a5bf3d46048bfbec2e24abd2fed2481698a4b5cd71f5d2c12dd473b903c9bdb978eaff7d76fb69951005681ed7b0257054eb3dd6d10097fee51ba7e8d565925e4091cbb78d255c9d3ab4ac0264d172c9bcb0908db1288c9634248f198a1167daa323822058decd83936985f83b08b1e7b942756a7af200af168fb8a091107b4443fd649cdc22106f9b9657c69f19be485c23b2c715b3762c332eccc44f380883357d10019f20612ab6b8f155c2af9e2ec340e5d8f45bf5278ac1fbc9f9f44d2f615d21007d822b244b1c7a0dbc182c7f5912485d6e4d74e90f60a2f964e028c63d49c6aadbf1df170e4914ca514139ba538207b1cf7caaceed4db8423dd1086b2adf15f6c0e50dcf2e12898f53c339a745316904ae03c38b417bcd7f5cd5ea77a4f06e65d56c24f37ebe72d271ac79b6ddd2bb8bd67f0727ead49737aa71af4f620da53769ca3ae878adbaea5a249128074ca3ddbbbaf5a68f9cde2a0e8d69708b0ea7f4c8d2dd4180882bdaacccf2a409a681c551776bd10439fb12b7548342532b371c0e045d8e8c895929464bdd4fe25f0533c66104daaaffed52446094978bcbb389c", "001084c8a5175c0ad43108f9215c35886c82321c800740c6118a3fcd45776a4588ee0e2d056a37d99b40d2bd9c0845088a77240b7e65d18fef105d3488c77910b5873dbbf275948db5", "d614d2e671066e387f7eee07bca9f9313d86e6a4d1371360900d670e11ecf1e7", "674a516f8f59f9067e0485e3", "1ee376e9e3c89b2147bcf75480ff0dec1d0e8cd45ba812f34c84124871d484b4ca87bfc8cf99f85ad452c482933801426e2737a97468809fa36caebebe8eed07a626b3bc3614ef1ceb54f9221ecb16f413f0bd9ed4b3010c40632f05223484af7bf5948c2fb8a3d2ce04c53e3f2682494f3969a0f8eb738cf93c0141799c9e6b68924433f0326991e19626bb19e6fbb5dd46baf39f92e830f9b1ff465a007f031891fb1f1799cc122d3ae7a55624356b5297bd5d948d9ff2e414cd8adf00a53524df43f398938d33c93b2c06bcde2679566c0a7b0177b4a873f35874739d550712d5cfe3d25c19292ba97c01d84224738bb25546e5c252fe5e5f260ca881aaf176a271a6fca2edbb2cf23ae6d4c56c20daadadb8205c2e33881867cd67ae6e59132edccc3601f014b744ff8eb6aef5e09b358607695d3af42ab8fa30e9fdf99ce54427ba9da3699de19f7a8f9be368df47ff0607601a91e7a5fa6e72be50bb32b825427cdeda3972a18a23af290986cde14f5fb9cbddad336f5efcd2d7a0cf3d5b23e54b702352fd5ee52d7e3479441497d56e17d5868574c56cfc421ee47bb00e9c75b84262a1b9e2cbfcccfed9c4c386ef0d2c1be9a7b7556909b5d72a38b7258acdd624de2396c75386e077c34f005f92a2203c82d1072c8998f03b1df22de832ac733977705453b1d72336b8d371cf1ed3923f462ecd22075de5df68c83ab1e6648ede7fd5ee5794a744abcb32af73bcb182cf97d36f37c15535c4107b7c8f2321f9fe0e2b6ccbe74204df3d748c05bc1e0e2c55ae1aee2d4aa4a52e98ca7229d6d06576196ac8e4b14a9ce807075cdc876aaf904c9962741efa8c6caf41e6b87b2ecd6636e2e58f3ecf576e5d8b895162545e618960ff6e336ff17eacd5a1eb335001633fa78c41ed05466d904ef9b81b643a043298c0e291a085e4e67da72e329adfccc407f800709865147db49cbdf4232073b7bc7ad89b3dd901d927ee08ae6497e0f2f9d052ca8d7444d2e2ae2197f930a7b1c8af38d8739ad298464169823684612cb628c484f710cf9c552551b6837b575a43275100bf800b7a3d777adc44d07f67cee5000422b9049dcfbedfccded0f2aa4d189621579b01e3fdaedc4d772dcc593316ca85e7aa248d219dac21c561d318a4936ac0d3bd5c75311486c174e0e2182affdf69bdd6a086534e4a602efba2b9363beeb5346539b45336cbaf479da6b15b226a9ac026482216dedb84ae3443b306820d9f05f78dca7090d727c7481d82c6e5df80e189e24e46f5758e453e542bd91a58eb51a89e07c50afb543c6b998704432e863dc4c0d0236e0672835a7b0b64e14f5ced2904e54da4287597f920bb4d542c35d3b0271cf0eec055656d523d7d2cbd667445d3e8634854f8616b7d7a7f3e14fd32651e9df40e1daedfdff1371f16d5549ed5646adf2d417e4b3a4d145bbe0974ab388c2716861a08296b862e4fd035163281457877eff89dadb160eb2b780414435784804bf4fd36602699d8c2f6a8cbcb509198c38e2df2edaae7bd7c93313ca98a9c2d24419a12ce35b0b3d68c18840e3ff8739d70969927c7db9a6569787bdedf5c99948a9e79b2302a83a71159f4c789b3b3f05f1e574f8a24c899ae3457f8e73f9bd86976fbddd83b1af337eb8da4c0dbac3792921597e18a2fd3a0ac89a270794529d370d36bb6dc7452e754e903781cbf57c8646b92d5d02842e7df229b3d721f9b981f9d61a48f00e53948a5dbc4f739849609d94aba3e3f5f8163d40321576cb8eb8e89953b608a01184d41aafc13f40c47b12240e3ad49413473c26b6843f4514be221c2af632d1a54cba230457f23f00b2608485c381ae03b389ad0a1671fb416de4659cc7f7a9c4b6d9807789c307d061fcf613b96a2d79e5e3e20b863c8b1b75f35c982b40ac8dcb7d2712ef7df94901facef783e8015a9a48574aa6f0cfb0bf6c1a3409028f8d62137c347f5a35ad6a3cd60d71aeb29bae56bb4590f69226fb4e08fab7a9f41e58f4d5784540a70e7a97720c549c8440b089eabd0eb3e4d37a2e54b1160572ce568f4256dd244decec31fec555017ebf488e878945383750eff26a8a1cca73e7d6f52d8cb229d5603360a3bffec23029ee34145c4aade82d486758e0aea9e1b7bf0b4bfbd4fcc96aab66a27fb463b48c6a6c5c5a60253e2fbc5716ef55629277a5f3b89c300e21bf1226241ce0d587fe3f5b11e47f35614169dcfaa375ee1aa589be33a4363765368f5666d155cf72e851d426fa67b982aac4dbbc29356d71deb0715b34e00b9fd8876bbb09ca0701b15615f05cc45e128b3864b26003e6ffe801c4e27402f37b8997e0c29ebc273dc03358cd22fdb68d9cd3b56ff8248a727c2d4ac65acda4d0e0f511bc07ab06cefcf444f1002c151b953d7f7b19695668a86683497c2a2d2e69f19a4997148d2e8d158da859c8f44437d9ce9db92f84a88e89cbffc74c0ef4295088e2543a4f7c6ae9c908bd987bcfd7a074f83ffaf3888bd7f430dc5a5bb70d223c21b1bcd8bff2103408460df864dcc168486f6a66d67ded366c6e10f50bcddada93627cda711764a57ec36035ebc", }, { "ce72c93caa49bb9850774149a87fcf8e23a0c53701554468645554553d54190bc6e247712b02097b794bc421ca94afed34742435ca689d2ebef183fb469c060c7f4d7daa508726c9d2eaeb9c7e9a89b30faee8d9168607d4778acfbd27d5caa623475073ce763ca061273cdfc2c692d1747baa8a01b15f783b2e36620400082747599a16cfd6b630fef310c0b9a2912d1d3bb71eec16972745cd8a49cd927014eb0a2abbe0e1ebded4fb9e8d9e2fbabb6a71da5688717ecd3e08160b9a861f86904a41702b2c4fff28ed8cc61d468187b75bde3fcc5c0c0a642215fea83584387fc5a9aaf2f8a91ae535e0027b618a32bd687289c47e9428a1a92649deab825d702b076223b07c08e55c0b60be95937bfd0504c18398e924420f6e20baf07e2b1b858d3e360a461b66517c24e60f9fe314a4a4973c8dbc7e9d2a9f571a1d8235a21073d81ab9f4800b70a5f17f44d593e8792a2507e6a3a41042fb2a5f7e5f028ed2daa88cce28973ecd88bd125d50fad77b1fde61c38272057d9c65fbfc6789ce41315a105af14e277a0c39d75c34aed7538c39160eab1c8c47818743e8111229426c399c5e88c4d894fdaff0315ec885ea019bf9acb785f3380c37201d494a60b583fc130bc0eb9fbe9b90eff95874e35910dc05c761f8006e2f208b786aeb2eeee841f9a82d9966c82956c181caa4dada81dfa2e2d7a25007c2dc7f2dc7ad1bafef14581cadbee4d614a557df4931b9ca105bade8fdfdefc0d96eeda11c08500b1ca827ca670ba07bb0f85af92914c43a6f71226d6e112d487f1ae99b2239a63ee2cd0849d8a9c488a11f82ca334604a2b7260f25373c6db75656527890f9b772c6bfbb9f687f27099ea9d4d1efd874a6ff83cc36c039ed1690408f20394692ff054d9e6eccc6776b6f4b3c5f24b0052334d159f40b470a9b8799bbc0df4dbfe59a5e536624cad193160ef23abef85df2c9b6e6d4fdf16f848a2a446a77044f1162a278866c491982570cbc16041908cdd0efa2cde011526a3c96d4b39a23c5fcc53d8232869cb4dea871f4ac8afc795aeb1b28cb2d7a3669100a1cab2ee1a7f31e2a25a5c6da836e4b771ad57393305faf582adcd26045e26b618d9943358c615fb206258c8993d700adac7440dcd3ef34fdcb065e10e9c9727662b5abee160aa01d2f2ca6c203a76fb01bb08cee9fc1eb6bc7497bb012ed2774a2d263b9dd03d60c307ccf33233ee33eee702c8e3118f9f86174a97462d0e804a24bbd7f4f938c7f105bb23399967288069e1637b60f2f1883d88ce5a874ea4bc0a7ca0f3b568e4bb1407e4bd6f0d3dc8fe91345f8435d7b1be961c45e4b0f1ef2d92d2d30bb78e1fbf72cd2e7ffae76e8c2bce005195c2003bde46108f37ffacdac28fd67a0de62970b347f0ae3f5f3a5b1d3aacb2fcaceecaf2ff4a2aeef6f5a176cc1b74b234f5658ce603bc353e075278a4056540e43033d37a6eb2615453d8206f5cd294423811283bcd5d79c4afe268a547b98977ed5cf24c0f53a0533bc0b2889356cacb67e2f7353060f9e04362859b1c1f02f96bf5457b58e5ce84a6810d39d7c7f53faaec64db5d6ebb90c1412bdd503ec6bc240c277ce1f5f18876feb24eb6a77e5193e33ce141e8720329add079dc9735f0a35d7d85436f1dba6dcff9147777760b5aa2ec9c8b5e9fb4fc602ec8f754c99ab2372ff5963dbff3fda91865108e606b214cf7acab875197e78060eed52a798751998ce7c73cebc4d5f429f6729a5193d7593072d0921ac8127ba6e796107ee7b9fbcf7128ab35fe9f6fe501fa4695c19fd64460685f287acacf5250efc13899bcf80ad5a340d432a0b9449affda5c8fa090f008e01873aae7d5fbc7972451542c5c29cf9cfdf23db736c8a7112536b1b626caa63f3e4117044cdeab612fff8d8c194d19174f56ce761f6587349c48fab30390f231d209461ee7e18007d10d83ea5aacf199f3b00003259747b1d03274d3c3670595604bb4482d345ffe31d3e88c70da16649a2677bfbdbf618de1d651a53d573aada2eee5c01335ce5519a6d18a70f7ff0b1e66bacc162c49f7f29b9d3fe2c7dd85b6b355c9f9141f02baf08d2be87c36f6d2e1b2e90dfcd100886e306b360df0ecb146a6aa5ac5ad05b63a219ea65885894a386248254348ada17908d776f9b438306ad28b208f80d6b9b265500aead945134b9d388ed5d6205edf07c5d8bbfe0916d0943750150e09c76359d24e3317517ea489fd8a501dd93f159f07d19d00e86d952fbdba2db771910143df346b30a30fba908a1abe5349c3f241958f428dece7ad9a91cb42035c43573b87b26c2ab216cb4c21799f6b3d81acd300ff50edd6fe7868b9ba6c160db3418565ada027b46b63e5d4f3411284fde585ed3673b424ec1cdea678e4a43c262991c3c9b988351d6e0a10af1c959cf21b7a288f2e4d7b3b2c11b400b5e036df71fa993b72ce48d0d8598fe4ef1ce70a970f89b55cf4f07906a479bc84a08bf6ab25221de37afebbc47ea0b38b87be128737d7d43cc84d336cc6ffe1677bd802910a2084751f30398dd0ed09589b2befd2f3b40fbc013318c822fa2faec2323fcc52b43161f47aefc557e92df3050dc5f8b1c5a4b2f8bd7b2ba7aaca79dcfa362fbe7781a2e261683a4a862d5f83e34845a8fcf8a1aa73cd521e87cbeb71f20b20698cc34bee3b8628b1a3784596c", "08b3fbd73d157e79ea9f61665d19867dcb8c1598c1d37b793606936d8aecd992a0d46addeae857d488b83be5d1c1639d4d78350e4cb08782b61bef4107c9d3a79d3d85", "a56f38b4bbe83b3d9e562cdf5ef5b30593f08a1a166676c4fb0d5861654e640b", "8726dc5cae9497936658f603", "88420357d1ad70e7c7bfd55b3cfd4bf06cd4e9b4ed5cba681045199a06985956d35fe86b28b9a4599964930d05d230a23c55a6a152f67082a453fc31f68489df05c553f9ae5cdb3f611445db384d79af865e52440a876fc4153d896b7a2318dbc2a4495ecdbb2e9dc68022326d35289e82aa55197aedc266dd91ba3018c7b474ba22b4e773773f3e9890ea84bc16a6b235e4bb69e785c40c1adc15b0e0ef03aa147b0d14e62341e27398b84a53f72c9199cc1c94cbcad2bd31aa69c96b06d01775b8c0f80278a43f526664bdd430164863c9c9140ad87798a5b8f38dfe90d37f54d1137709d5311136b728e6c799da244294daa4c8b44bfb0acc603a16c088a081129a0d2cff55ce1c4ccb486fa0ecc3098ef2196f47c49f9d253112bd5746fd99df5d2be577617dc2519c0ad04ee49ee1d7be3d50492017108fffc9a414ea227af39fe49fb2c895fcf00d927bf4a2d78c466fd44df4768e6775d39fa5c834b60979ca27ee9f00faf37a090838f56275a894ddadd265a8d2de74265e4d8d286639ce8f01eccd4f551cf6b4429eae3f08902b6ce6ef422cf91ce8946d9403fe8064784895b62a7f5df76ea294132c59da6b9f53d4195c1e9000bec499c14cf8bad460aebb024a76ac50616f0dcda71c0f56dd3239b11764f3ed6ed06c049b2ad673e4beea391dbb854fde1f01b1900858b9809259f3906b34f95a1c6ce8d24fdf0cf7c2ab7bde2202a7f1482baa6e51caaccef9f541c377da620bfbc63955cae0e6644ec8ed6878f704f1dea30d6b50d4291892bad19b0234582d50c6cc0b4165322cff24a9dc2ce1be35be0fdb3bb7abb777ff0b2f4cf16277388af5a89220d59f1f45ee9cc2a0fd7af9aa8e9e8d548fd65be4e47e7f8ef58f7701f93a42e7ff78f70e807fb63513157fcba96ad9731b2e8f80da85ef407d5c368ad16f0657620bfc122ba1b10d7ac2bf46d8133a9c6fec1fe04882f3d5765da8f825e1984a4313f72b67d806ed45c000dd3ddedd524d474b9b5788547d0712e8edb4c6c586d0cdf8f2384f1e093a7f6dffea6e79df9cb9398f5d0b9a7cbd63d489430fbfa397a0d03ef916b7702f33a54ebab84a7055b7ec6179b0ab7722f03e126ed343b1cdf2af3763df7e3a070162535514b01ad86c6cb051859aba1cc4766b12c8cd57b73fdd3c65af6961c45395aa7b885dd59e115db885f644e1c94bfa26b3804f767601c86e2c7dcecd4daa59955e6a40991a4b4701e63fc82b46dc0ccf59af40a8583171375551c868436ede535705f2e6380c5899cddfcaf9e94314794bab98846cd5ba9e9afbdbe1ea7fec5e22e7b2aae59fa598f4d6c0cc6f936a616e11bf01a2acc891cbfa2bc53c511a8a3a3da2e3aa5907d123ab2a4a3c0009fdb5235a3c33718fe4c504e1539abac6370e06150c402b5fc2f8c32608db4ce2eca9d1e4b96371ee195f6cd632f5b972385f9d5d357b87c78cb4e2c27aa9851534de14de923543f5fd9d55e34d6e8b7e1f3f2735df80046de01f79d0321066f9bbd76299c7386d285f7bf4ac15e033e89a040710c90f87aacc09fb8159f93c8b4860247eef079e32d05707e88aac734a2eadaa853f528d9986e0af3435b5c5f44ddfdab9b0c9ab3eea97676e920f80d1794740067f9b229fb018c804e595aa997533a5e967cb79ee58eea18995a90ac08333f1c69600b17ef4f454f540dbfa8b502457761bc4daa876d9053ae1f55001b6916ce559dc6268d01841255990e56614e6f4ee4ce04472dff0657360d75da4e83a71c852a2585110e53137e91bd89d64d99b5614ab2a5691c876f15d9931b092fc6729c0732db5cc40f966fe440ff99d7d05b24a872f552c27fb0cf2af443340b153214b407fb9ca3750d9c157aa75763b0b7600959663889d00f392d6ebc12835bd2f03ad802a21d0228f1d2e9731d0f0051eb2d5369ab790d1134c38e28d2bc2d5d57d6d897244742c176559961a1e40c84ee5c8225c8d72b92352a011e3785c262aac115cafccc2fe1b5e81a677a0220f207ebadd786b93f58e40eb6ade68ddda5b66c5f0f6b4b95cdb8241156110ba3303beb79acbd54423315768bb43b4fe8c4a465e50c4e63bce272c4d731ea4c797e14b2de31ce4264e2479179b906f67af4a23c56e817abafedc2c7a65aa45f0c89fcd0baba60561a8d013e2d5e0bdf9fbcc1346d3edb20e6e9f9c410982e1ac43039ad8fd0ebd453a6788376951fc20374b59946a6803498929d9fdf2e0f5e58c441329a79d1232e957b3a9ed17231c663b4819dcb6b4e33d205edaeb7d7ec466930bd84a064b40aa67fd76f6ca005408062b45b5aed6f8161836c7160a8c8313dc9aa1c6d42c2c16972a1065e41aea9c58db7916e1670cb42a8b54d85498561b4401761506860b19b446655f8988101fb4c45067e30edc3f00df8d88ee34111dd6626d605d993ff207be09704fd8dc242ce514bae77cecd20f10d4a38435a3f5e545882fdc224586a04ca6a162e118d23716240fa67892b78faf98a17916471f7f121fb9f85497a0b34bf5aaa4ee1ed8a4681bec55d1b4973d4368600115bea70f20a37c9e942b87f6cd1e2ab70fd401e703e3c8334c75fc338508e06d6370779578fbe737a75954b4701bfd92028ec32d3d7ae606caaf9f049d9774f70efa707c1c1174d9fcb5b0a0ae2a961c6f58e48ba82c2db14ebbbdc24288e42879f547b855c86dea9a3b9877e4b105515bd78cc43465", }, { "bf7884fab52251e202afd7b5b46aa53f85bca5fb80a009d8016e276579e401385d853312a884f4aa33cc5fe7360426bbc0ccb7416cc0196e2e40d3a825d5e0825a1394029789acca550bb28b10d847d0a4fe1111be2b7fec6b5294902775128288a784203031ea853c9c104c75571d19552e2a1359a900c5fc9455230968a5920f2ab23f5b9cc49739d4e4ae2c01c7812ff295899b954e9729a3bb330b60c51a8a7759e5131d7d4cf261fa1e62c29f91b4341a4fc968e7f30ca2261702eb328d628b7275a9efc29b50bcb9b27e5844328d5e8256c76949d30b6fea0d5a1c9abca80d3251fcf4ec4db0a5ff2ffd43618aa2e3e1694c2a3c579a2665f443ffb1eb0ce33c09d7285687cd55b6ca9918553bfb36a44860e09ffa0604ef4904a034108370195a986fe165c598305eb08599abbb3df31b1d93162397056d9ba5a1ac2812c582aa356310fafb4058abc5f157802e4a9b4bddb16e75b6db105b7dbc838f820539b76949b1648909104efa67ce28b16a738f1be104d2bd142d3ad1b1c953b6020a1f4cbb84d5c49424befbf2e6ac5c593b783a3f4af75477312528fa78dffd82fe493d821e011642bf1135a5be91fef909383953308dcb61b2f35c2ad259acd1a2e953c0ea6a03a97b384e39c94c33d3846c26b4f9f116abe572d5b7cb81886d6adc2d544630fdc1684bfb32972e051b9a2bd0931de63e025813b923944290fe1ebd5264ee4f25569a2088314e8d4ce8b91c7bd602b9d85acc917d60d30d5ef1cbb055b9ff7b0f999b98caea2517d2de334eb436078c90d41e0e34f11b93e3e643389f43b3afdc4f47a7396cbe0b4bf159ff27618cb835aac6699be1fc7ec840b767836a165fb95d06f2cac4fe15b65714ddb8a095ed4a5b57e63d536405931b6c168683763fe07c32aa4130bff787d4d440746a2dbfc584a502d809076b257482abf7f8ead7741c82b54c41acd41581148aeb4149b0c6eeb39ef7ba091c2e8bc72583b2fdf8ce7fad1bc05aefd6db0360c644a9760a9729a88ee4b2ab123d7238c12435b9f3b4660e74c0fd4a9b00aa614453d84fea01f779e5a924f8e79630a8bb6561ae19c7bc8d88b9d823b98285fdd65d4cc05e443944ed5d3cd4f46c7cafd1dd5deaa519772dd24f508bd2d588a832d5689119a2d506ff11dbf37d57a24e35ff38da18af07eaff5775d12dfe795fd3e1f0ec83c5f283d6cd76532519a15a18d93431893b1b88929159bf8fd21f62b30f4e37d540baab0e30ff3349a08d627ac19303fcae8b8e3fe44eceb66d30697c7ea051bf5afdcd8bfc00d49c8d36164ec9194a78a4d8b78826863e93b6a810354861f4a35ec12e5ac102f74e390d9c0227e67acbbe3254e5b892786e3a88a383ea9726485854a319569a678fa70392cee90c9aa83eee8df6800565bb8e083e78a064c0f8b863120efd799ea57d3073663c0d0e7bfb9b717ca1d6372fdf75a77fd9677791cb899fc8033d6d806de1e6aaeef525ea909666316d9d604c1207cbeb6f427c3acc1b02cf59704fc65135703f2a9529bb2c8fec992c4de53e54b029c3f2a5fdbec1008d1a70dce0c11251003ce62af712b9e4abe631902485404e4933f346f1b4467fceb65baf776d0078aae6a2a1f95b85a441b635663c75b485a8a7cb9a5c12192ac874d940e2d9b88cc05a2db9b5b35df769925da508112ab0b8f64a1408633fd0d81810baf2c846b222736bd826c8cf905b2c35633d6013f5565e0a5ec1492e99613f53530799052a0d70023339d1c394fdf9f73a590a2faf68390d2a823bc3e47a173782b03dacbdadaef1e67fb47a7cad71b6067ce5b5e41fc20ea1fed28578e9bdfa99faa657a754488ed3fc084faa7a05b0f6eb66da0a28e9ab26bb319fa4ee993de840948f94dc1d68d926b783a0bd3396a89970b2c2595de8148e87b87c21f664618af4f567115d403715c3d7d2f66d7a90de2c5237893a4c18c20494e3faf94485ed39ecfe972c36acef0d7ee57bf8755924c790ad02dcc5c4e15aa7db53eb6040244c3ebb7874676782e54dfdddc256018ae6af8cc37450a4cef77f21e2e061062ca0c2a514290c960f5993ec1ce9eea6d09d3293118237e079b6015b966361c3032368174d74ae5cce4148ea2b3690fbd3c28ee544c5c5bd7bc618122979d52c9d3d44eab1f2467f338e695ec5f95998bbe77dffac42bc2809d43a324e0f5feb4ca3d5fd951b7dc8a9e6276ee080079b68849b14c7573cd02c76027a856165d1043acf99554c62fe32896d120974ae71f84986bfa0c28fcc399246bef3ab90f8e55f913aabf339dd7ca6f0861a9ef712e77dd28740615479f39a37e746c7df2b267066d1649fafe0459f665f3d5e7124db43ab1ba5ff94989acc7fe0935e0bbacf718b33103a1355d97ab416d8263ab369e6cf0ee563a77f2f265fc3856b7d54dc0887ed439a421c14f733ec1d6da086536f9539d23cb8026218c5e783423b5f4ac24c8d5d8faa7186dd5ea34afe299e6dbed73ffa8f415da706442a48808a9342d6209f65ca11eba76f8ef26db890da76671971f65bce9e6112c8aa92523dd5295d748e28857acff408c161c0513b37b855a8afb0764d118815bb1b68f8f09156641f7eea994ddea20f4062607b9919d041c880b71592402a4d5b92464b239caf431a99dc67787e76b8e1d7337af004bcb88473cd16b3f7640e8aaa59ad4609f060a2cdc71a4b3ed22c1506a7050a63bd8ed68aa58a8109980bb3f2b9f9fba9599d7620b8c25e8aee739095789af83529cfbfce5941d7f14c8ae30583deafdc7c25fc34e75bbed6ce4f6b47e9647c12333ce08c7db77dc94161cfc43f7ea0bba39def8bf8ae61c6fdcc0de6308af963c6d9ef43916d0cd2cedb970d5937c9fdd4b888cc66e99363b5a04ae62a4349f01c3933ada64080741b1781754e4a722303faef69e382cd9823177e4d5ac83e76017124a7b1a41bcdbb9c4209e7b42c", "eaae1c53919e2029c137a80f91704d0871be2c1870d0333d8bcf7f94", "4c434cddb399e52457113cc7e16f046c3f8301f5b6c296979f8a091a9ea557ea", "b633c1a0e1ddf4727b149b3d", "f1de487001a580cee6edadb1ef6b700c861a70c6ef16274447b8c61bb10d2d1efbf104d5f7d7172c6a5cf9c06d886165a2919ee9418e2e8f803d47832dae5ef232ee300d1f973a6298c22d777a1b16264353cc731a7a683cfe31e0abc704460788c555c0c24f281b81d7761235a955c736f17f213a896b40a034609ca8456ec3cf5906d01121b7580ce19d89347b6a59c81add318df487b2442a7a8b5e30df78467abbf46bcd5ee5b994a39ca5bd8846caba6f02f4f1335b73d4e20be0b6ad85966f86d1bb857713ebf947ae936782f1f4929498bbd66bdd5ad6fa252364a5a6b46180e93b54cc321b3cf63cf23d55392475c6b8c8c9dc707924b55544151c7c55ae0bf391f793e52bed70829fcd32b2926600f65be0943d6a9a96547675426b0dca9cc7b0f5dbc9d5439d0281014c6c159d055d6bd89d67828ba7fd2a0570ba82996037f7dcce297fe6518331270f6fd5ee63d406cc5081472bc5f2298a9208dba9398ccf807ce9af982885897715b3c5742456f756d79c70434a9baf7b4b6664c9d9f5696c5256b74099e593f97a2d4a469cb3430d0c3eb06083398cabd58af598945a85c9235a3fdd9ba7686e54d0de9afb594b1bb030be8e6bb839f6b45699dbcd2f771db64b0c62bbf6c8672fb412d60c00b3d87f82ffff6512e8308877573323c5a2d6a216ce3e2ce07c9763835ae59d44d7958fd873e3995b62b1b347e489ce86e023ae27a6cb03ddec27a38fb233499a714acd89232a91d38abce30299f38f437f7a46df647f2be862c1e7bcc1e4263c2147b13ee5b345b7fcb973f3ac71db8bc12309f67ddb62659bd73fbd20664eadcd23a79233386aeec1a6fcc8c592053954ee53826cb9b6bba22400648887311cdfa5414c96d5956fe193a3729be1434d923a3f9849f6c419f77ea05fb72f3c4f75ccec03b7f7aef8c8e55c8c5480ee505ae1a7594e6a911dfbc39dbb0ae8656f5972eb644c64203a920fe0078f3d050cc5666ed9747c23df7853d6913005d0156e741a5ead3bb1b22e5bd802c303a73a961f0b60d0fa698041c22577b44eba5d6071de4b545d9f5de24944c151de6a189bfdc223e0507c74ff929f06a2e7497e8c63073294b4aba110a006a6e9510a9617405d9ee711831e085940006761822672549d1d1c70e50002c2227f6f304b9a7f11dc05751be2dfd297087044d2e20ecfa0c091478d62c1bf5f0aacd25bb0384853762a51144b77d30418b633c4c10a6eda7b2eac46905641da0b685f85349749a91cdbaa4027fc50eb97a7dea9e8cbb5b5f386ace0363803ba579cd16ef80dc40ba1044b4ecd0e81e382635d7855e2341b18e0ca705ff46990282fe25093a248ca04a1fff64ebee25065350ea4b9e5990da4dd2e28688ab08b6d6fcb54d70f6d74fd7e5e05d21c12f5b140839aa966aea9ee094a923ee5ec704b5b709ff009c20ed89a75468c48b505d07c7a5ba1ad54ed610886c9d84468eaa598c71b017578404c909dbca431703e0cb1cfb975a696a1677bc015a75db007eccdcb21b9e5e119c48f148c2cffcf29e245e52156ba5ba0a8b0031570e4cbe7b3ac4646353594f0c4a9424c9d97845c5e1a4b4016df9be8df3013e5269484cf32258849afbdd733189ea11783f0f64d3aba9b4f48818011e868cc03ecaa44ff0ab83ed12981a6df445294ff672f3a16d6e0d19b90007d4646e967e0fb1763b3c879f548e1103a75c94f3a7f72be78555eafc086c1c58d1761aac60b843704f234c55b951a1303a12705f2120f784c2bc1494432a94c835d908f0edd5cbb169afd2d38087ca5bc5e5df9c3bd970dd2da4fb2a00933538148ebf669a20b5beef0402e53dbfc3a0f289b33b41ca27eb2f036a22f0d02e0617bd01e8c74be264515c9b46b9ab6fc67403a35837844580794088a9d3c14ad9309435daa0396f48017be524856ab6c191350529962ead64bab33171a01bb3c144b23bed406cb05102c693ce5df36eb541c47e871acf56f2b47de687eb9b3511ae83d06b1f69fbcef3225c3469c304741437fcd0ff4ae3484c117f51d24b6ae1363beb7d85d9b61e01e3dee901b90f2d3272eedb384ddb4d3b9594b9c0926595e500f8ce2e5cd407bd7a4e2c8e6f4315bf693e8c961ba5b8a6c7f5030c68a6b995e9d3f9eaee9eebc9d679eaf72a5f1cb6b2fc66edc7dffa2370dd778ea7ff446121999afba7bb35ceabf626c6269bc466d65f7f812c663bcb2fd87d3e09ab7d71e727f66d20ec48a5d2bf0aaf0aca05d1546d6e974f90df85c1393e3d45731f71ec7b5cb6cfb4e5c29976ead6944a99df2045056e198b19905362d4e9b765adb65eb089233a8b3777352665489c9456cceed593c6590d9f3cc4024d0bb92e1a0dc619bf8ae65be77456c18f8171e4d2d846073cf5c57ba93adbc0db9799e3d98934aa6899372acfa4d7d2ea32e20164b79c71d7bd33c94f9a781a25cbcafe563462eeacaec0e8d9d6c0199de85558a3a05d1ee3483351915d8a4e65ca0ab129a2386a9e26aff9b912c588babbcf25f8c467145061b9b8fbbff19d8c6ded8527d457be7c926c8f490bbcd627b3002044b7729a52e94147f95772591616f6074047e758597f410b3100f9efafaa4137dedfd0edfa85b0927804f0b4fcea1a174622116222004d42b36c2c73d04781f2f49d080f351e57154a3980005bcfb0ea34288e2fafec5bfd01e1f7901b3efc71ae58bf8df4cd7c045856103b77bd78073f0174aaaef4a3c0e8b5b46dc92db55478f012dc1b7d513e215e735573257f105d2390b5366f49b61809033c13ed4e1ebe19ab89313c947f2585f0788a0c5de90b41ad0dbbfc604a0d414d0e5390a0f3c9616cfce4097e38e05888b8bc6e55e40368bacdba7e5b76f4bd8fe619746155c30b38807a1ad325b00ecc3dbcf23014e79f1c39af7cdd0dc7ea58ce733e6611b7eae069deb047aeadfc21960e614db19d2e7e0905a9873268b9a24f856c28059321a742cd6cb3d1527", }, { "c89c3cadc094bffd5ba06c600dabe30ea19ad037316fc13b895fe0e14ac8841264c1bf25557e22b01f8e102c3af43adb8e0a12bf79d3fa0232dae37ca3688e07294e2c7ecc4e2eebdd3f17173351f2c15b0480d4d77bd70955ba86f82214004b622cc92f7bf81a5837326f6a83612bdf65abb33c268a457c45cb7467e074b342a17c711c748c74abbee31541444020a9ecd4e5125e2a8ea3f6030bd677be18183a8a34af16a85ad48b7015cfb036789c0a5daf68883d0c7e401754b8d56cd00ff605be0cad19e03989f608392c81d636de859e66c2aae403c138bb96a58ba69b9064a83e7d8877067e7f40aa0016e0df9b7f455d292a60eb621b8107a727a3378c4b7509d3ec10526c50fc6c66dd4b015c915e85bbbf701ddaf2258119c8b9a5132eafe61bbf38870f35f375123f766ed0d4f38b9364a86e56cdef6f95a815a8d7c48ff283c77992fc6c070eab7d7c7b517006e5d4af532a7c429912ebaebac27249b4f5112d870d998e1c450b98c05d08c742dc769506f2d7a004c24ebf84c10838b619653e27ffcc4344d8db0435e4cb77c0410cc734e36738a6b5f72a7600632d19c86b40c737830b0f5f104443dbbb031dc7ca51ab318951e7817b5d81de8a9aa7f5db6e2d5e7a3cbd8a8100653c048204ced3af005d00e7de7b445f5acff901c4d46ff133e92ef073aff1d9ebf55befc32f9ec38c9eaa6a1aefc974bec2758297e474cacea2ba4151ab1a3ca0762c64a5ca273169d29b83c164f77f266c01bd5075871e17426068ed7aa58ef0d1f2959b19c604eb6187acc57e2becea2da93ba23159ba73b9226034c7ee2498e0ba34fa8038e5e2c092a73ebd9329ea3d648d6ebd47e1776941ab3130cfc91089fd0a0a36f0ecf68293343f275d2a64c1b7d27ffeb3f667f4a19824706235fa5f3f04952ff08bb183c0f1aa1d1b0edfd2e05ed093543788f5d0ac6532e15f912163275053b202d772f381900e906fe070cdb00421e78c16b7387be91adb7b3b3ea28b92548d69c780ea578e7ac66eeb931eefb4067bcabdb345a7cd2022085fc494f118215adfa2443630bffc9faa8fbd9943c3140d81c7532895734a9dd20e31c326531d06f5623c252139c4cbc882640c457819c63f6ceed4e03872b246a3766df69373ebf5af1116e8d5e1b15745bd9dbdd663fd4352d1238a43d5d1e74b3edddfb1c9d460daeb49afccfa0712b7a4cf8d07ccd0599ef3e4e1c9b5c814f3a6f3a46fc80449b34df87f47ff91fea3618cab2d5c04cb50e8ad199d752d901b21348ae939d39c86cc1bcecbadcc6f0e581a3bb51e070507b41ea4294b35456c69cf55a2a3f1296f0df73abac3a9c81cc303d1e20ad6e9bef48de83fc22dac2cfc01ce9ff3f70e00ee49bab2f282ceb6859f989075814e690e36a8d16354fd6056cbff49c30e49b1570363498531ff0ad0979a4518e9ae271f57f883abf5e301c0e24a83f09335479698911bca90269a28c0e040a98e67c9e55f4c91542f921511dd980270cd490766da22306b48ca9309aad3b2393b7b1e9ac7afeff64204081f9c0a8f6a5396d02eb9009901ca2c0a75ffbdae3a38ccd5007cc4f6bec8fedd64086cce5c039e8abc9e23bd694fc8de4e858c89bd585ebdd422b492eab26f4ebbdc1d17dfbba19b5ac458c31320a161a52dea638548205a6ad4ec54875ca34238c059177bfab2d5be0a98d12b3932d0661d33ec655446d0283224af8ec7f1c6874add03448fd8029a71d3c5aa06951123c9fd881d435845757df50444e6cacc31a8cf7537a778d1184b96c3512cd474f5d1fd1214555789d24c8d173358e36400b2d937595109729d9f35eecb0963c0da60d2eeb52a778876059fa95d820d5d34e7948d389dffd53d34c4083d27c917879b053cc57dc43c8263e5dfe5f33c19dad0a7126ea6e8abdbacb318d37c305a183596ddb25b1934beff13a4f24fbdcc2064de8e0bc639e672ecfe45692e9f8164365e1691784b4f775ef369aeb135ce15135c20da95064c810592ea33316b9767caaef842f948b9573b2205ec57d3026a2f2244c42991462e233061549cf9bc66a7b4a8a0fc61f73883fd24dad02644004989c4721a0aa03d3b0191d7fa4d3da102e541fe463936c9365ba30681e706ca70cb3c8ad5dcc710de59e7d8a6247aa809bba74ff4dd182a38bb31baa337841302c19ed89d65e87bbed05465f4ce0dfe89b44d7e9266a8ca21d984c41109d813ca76eb67dbd4e39aa437ff98050c968ec1e40c534ab51d6b8ea2309fab08b3757e9edc5972bff316f6f2affbff458ac0299613734b30dfdad20f797d172cf295cbcfee3d8ee25485d40380d3480a9372a1a6e5ecd7c4c6a9d34027ea6c197f37e86e757750c9fc24cc7cf814878b8628326c140930dbb2041bd9ee87f36ebfdbdc34522cfd4e50c9cb48dd52d4647a06d08e0f0069c104849bf30c8e61cb693dffbc69fc0ab9c5d502a227d606a1dcd630ebd799acdb1e47ce2ad52ff53f6cf4fbd5f0058fb5db915702675ea44334d42e0b6ddae78b22b5b5f7e5aa36519e31278e37b64312479b14aef9b8f12d8c1f39faf920851bd53b13bae5490c847b3312b2e956c430f1d8deea91cf171dee5017e7709d0346d81600bd5f0c41da3f548c28aa50589b293685ba059cd7f3edefdb5d8cdea364f4a42153b0632ef0b7ba18610b71fc34a781eead1dc5a00ab47b6840590ba44dafc6a16029cf50e089684194d93dc881beb62edb7ccee6304a4e71a35915f109db92690461b9e4ea21257ffb62477c20feaafc7a78e2aac2301b66893157920ce9fb114ab4f534d61bb3d17dfb4d9ef9f79a736f7c1d32ac3998356aefc876d8c38722787d564e980a1f15056cb3fe634d71d2c98e0475c79cab318b73a863362f85aeacdcfc44e61b5aeb870de9ea5b5abd24e8c19ab05e45e1e9b8894deeb9d29d65ae99aa94b5047f3c1168276cc2e491aba52b5b03703ced28c63a167f0cb3e4bb4d8e4f0292cf3ea4376510fa49a1a5efcc00f23c3cdf6402197b81262e66e17bf4307d87ffbc2b37213b316bddd65aa9d64ce6122c4a1545c5966bf4fc4c6ff17ded787ca9a3b3cadee435bbba8f6590dc4ba30895b84d5b4eb94f4b05be3c", "82abb4ff5457b21f359754f151e456e2c0a185c8363d15918bcee0d6d49f12564ac655", "b63b577e719494032062e3f63682098dcdcfe26cedea2a40893c847a331e4ce9", "9f1d08be539f1244f0f69ad2", "88dcdb0309f8c4a96ad5560f8210eda1f5afb31b85b7a8b15525777748967d4ed77c063f65d64ef19b31044f2adc690f5e457faa1abe2e127b38c626eaa94053c9ae1b6b4d0db1f02c8404b50f58210cc9fcc6fa4ecc615631da631031cd6253b4a13a3e88295ffdc775fd4bdf29655d9780dbe02b0a82aad4c4088e90b51f170909c0f98ff93ca3926067ec94be05841603db4f913b7025a9ee34b8d8bc629ed827a2a9857e0814d36b83cba21e670f8f94ceb4be5757e0b8782895b5d8605868e4f584b5bb6a5f3a94edd9b23fc2b6fa06914aec970c260fc370aa245ca68888c90c43eecb68474c9e45c53a7da055f5bfe39b56769fa56264dc8bf4c1616e30262bd501ff9fc5cd78f73ad89e093feba0393a11c6b2cbca765ba025c40dd0417dfa644fce96db5a0362235ad37a317145e7b5f3c7213c7fb3c393be57a1cb55035f06da1f0bf665653c5fe8a0f3ca67dbcbfc59852694d34819d0978cd09b508d103017168f6848258493be737cc24c2112f2afeabf41038bea1f74bc8656d9910b77d33cc691a0d9b12f7c518ecef93423cb4871949a518d2f06e5427823324275b97110f8f88b0d14788741e617f4b194e679a1627da50376a08d4f23b005c0446b46d4f534ed85e4692e7946ec818437089425ee30e47de995e8774b61003801de67939d9fed7bf0cdaf625798d0d0d04a61a2482217b890168e36f20cf1d6b81f9daf1a49a781567c4363ac2f3ebf0252d5adfbed17f98cc264ed2765aa279b7437410ee8b4cf42932e5055f4884deefd2a979ab1328f97cb750b3b7e4615b9c1c61659c90a5ff6d1c736e785587ec85040fb2c6decf789c2707974bfcbd0c7f699627b31e0762321d55bcc6acf1aabbd44abd7766d397bfbb68c424b311611d9eeb6598ca3126f569f688455da8d5ab86eb01f9c96186858c4b5e447aa2b9ca11aa5453f731beed4e09f95bb7376e200212e2f03551b8b09a19d6910f25898d692bc20bf6ed3ac9a0276db560de5c9e264f4db8fec6577042fbbd4510bb7070086508ac451a1fda26582c259412fbf1bd60cd5e921160c2604fde559b5ed4df52b805010b225f999450adadc6e108b70f169a3d8da6efbe1cce1c4908b004e928e3cdfdd0b4c5f742fd72a11c9585aa3517486201b6d9a98739b77970a88072750d29d005a291546f13b576b4249d71f04a9abf8f653ca206d98f738af2a1203bf0975f0a40138df054ee834ab73a3b1d7036567369a7ae15f808904e08adfc84b34a0e1356009d8a82e51c3e8f2170908179bfe47be8ad819cb12e85b6b76bba7c9b9398dfc00f550e32c171b4d5f2d9676063efee0b0b49660c10260ce052dd00addc3359e35c25dc33066d4b05bec7d93f71e0ad7d5ab83d844c7f33137894327f464260688ea4ce9847046e7dd0bfa48d4e15277a9586b4742daf0c5ecc59aceea6867068b03c20aad38d04a814472287d809a9285cd4dcdbf68f3f4ffb794701f4c265b2dff4aee55c9815938689162e08309df150538e60dccc03d495adcc560fb831444b922a6375845cef5dec56eff2910b5bde5f25f0e550ab5a13205de91d20896fe04a8ecc2c83d1371cf381424f8c43d2a5ced374878405f52bb92f4fa3c15d29ec151508488f9b4e42527921e245a8ee4b5d6ee95797f6ec4374d79acd7b467454a1d7eda05a8ae104534b23c46b27581abed6afc3ca555202dda94fc2b93501fe78867730a84f6f726dfd7364bc240b65d6c3022a04e09c89e36a809fbf244cc5522315110e9e33c8a4e1f1396e3e51fcdd53d9ae94fe7bf6c6ccef0ce02048a11441de3c25aa9787c577501977e486f8dfaa4c81e3183e648311148ce5cf3de56878847a9d14c0645777022c158670377dd9553eb63eb17e19ebb06202be8fd9bc2b24878cc86f9938e5996751ad9ca04b636497199f7f27dfa0f5ba2a01c3a491bec6dc5113d127f6aae38fa07ce7539a0c1817f7f0de0da538f4d85ffa394784a42eb50994e28530e3997e3345db28bafbb836fa463d34146d9f46d8d2b28b3954b9bc7f84046828e9b55e2fd663e562aa95caa97873f48f0a003d2251fb3ddbce0b6072fc17e0d3f99b655b8f41e8e6986ef7526544222e2d402489eabed4c219540605b9f5dd321ad902708601e85bc874c11efedd072aab7e10272c87b08b9457223de9fbc3abc2d1346656a524e9c67d79d4053c4257e886d6b430f5b7f57b2e5e92ae69273c1705a3074d5066def69fadea1af8fa9b3bf4890f9cda4b1833e5ed27f22bc4fe4cf452880c7b53320bc7cb748c0af6e7550ffa84e4714ec18d208131ae9e3edc6cd6fa2c60ab8ebc1ee56eafc01fbfba061e55014b9711eb58fdd01f8936d29dd081565de0b175b02989c5ff374e6f58c3383e9bc00d8a93903e6a221c7475e15aaef77594849af877f3807a76e03bdd54ff0b192bf34385d24d858d6f454810ee48141d73e3acf1aa3d19cd4c723a634cd8e25b4fb604c744e408dfd82961e46e8444f001d0991af24b3b6ec57ba41fb45122afc73ec6b25f501f1abd46181247945729337bf5083e5821968502a5a696043ee696c290095feac000957f968ac61ccb572ab2f37008830ab9a81d02456190af99873450b52df1888c3d8b6b13df65a9bb36a4b6d0538a0f179daebca2bed6f94b4670560fc5471c3770f2d004b6a138b8243068d754fd246e9881242638c6675f1611f237146f6e0f72ff2fba96f479fe0a662a81f40928f5400a0bbfb5ed07a87f457d5febdbdd6f323e2a59f749e6fc8a51d08b023734c762a91cc517401be57ffdf6a52b9174ea153abf2190ae2642955c3c02b4a15d72456c9d2f323de6fabbf56dfa3b566f1aa688c86b662bd34cf2511cc4a30621b6f1f1ac382bc1c4fa4c0d4d5a30ae90a5e54a9fb4afc1475e7c612eeb7f0e09e894c2004cd04126df9359d525d7f090e4b531916207c38c3512341c84218c86fc50061043ba1b89ddfb21cd756b391cb53e8c1cd55352be05efe562669e3986c022e30c79a97bdf087889a392e6da0d72cc7ea208aaf23408df23f3a9ea9bf9a935e49c9994a37a5dd0faf1267d5f7db47cf64ae1d3ec166466b2f882eb21698aa375cb50146c0e660e9bbb38d7bbc1c1c6d8333f7031d6a", }, { "68ca38fccd585eb14f953358220027046c14ef965478d3d8f206f63fef4fe3571a1b53e774b298c347cc1b69cc426d39575ccfabd5a284c7a87a0698cae9efe40543cb79f5643c3c3057a5fc991235f06f059c44a7200b509a12e864fbd748001a14790f78b54ba80cf0a4a603da9672df32b68652c1d6edd3be51cf969acfb0ae49c026fe0bce0bfc72b1ff4c47712b7a27b2cce888b9bc470b8bdda55a8d53a34d79a25947ad55b95e5406a5c5311fece3ecd46ca590b3b01b9055761da8196b21bbc468681922c66d286c32598b1e3d77f2a91d835ccd9eec231409cb2e74ede9385552517718be9f84f0f9100e368701dfa4843b7222279537306065a54d4edda3a02f1ab9edba3ddeb34dece9d5edc8797103eb942a80cb5ae130ff2e7eddd11f0cecd8f9a615d75963c44238b10ab1230d9db7371d8291feb2912d306efe4f7aea2773903d4be9a00f2bd8c03589e342269a79441c0b42ce9c6fff0a6e4e845876f7e9b342d25351fe2b1233b4f576db90ef1facfa617b96d17aa03fc824973e1c80f15e5344b0516fc28424b7faff47ea1ef4e47f6f7b50e91b8fb14027f05ca7e1bafa266a4b952cd0b9e4cab82bb4d61f99568e14a6772f36296f5d19cb04fa86ff20f04ab61d1a6f01e5282c99fe4c3254da46fb5276317be58e94b1928e3791af27dc6544f6d445dbfc7275fbbea74f98ee4aea647b654909f9fa9c88312d3759099c9d0070e3db6d55506813f8b7abe602964a7dfb9387f58e237dbf50b4185a50b65ac099352dee8695017e4dac644f42aecc3e415333cf76b08fc764a721b45d7b74f6b0a2e43637e5b4849218d3d4c6a01208f345d76af56631590e520d6bcd82627d2446b45b2c68e0be81b3924753a54f47ea27b1e08de2399b34470701c9697eedaf3248db9b28991cdc2c632fd1b376bbda279b6709d5033d1c0a3ee573bdd222ef1afe8a4397a61fc30a4e94bdc55097ecebfef6c00133dc0b72c17e2f93a11eae9fa9f1364f10fa595e8e1623dead10caac068aad3967b9ab2837dabcd8f96a77a25baef16ba84bc93661ed150ffddfbb0369683cd021e8f959c2b531bb1fa95d7a574fe5ff9aae35fb9b4a0a9829c59b932ed8634fc05ca88211da3e30839baadaea8fd9843e0e80d9598a7282500d157ee579cda5d57628e7506617d301c2adec5186708f94f069ed7bdb70cbe88549cefe1673d48c9bbbdc01d2af03945cefe6e25f757750de64cbb9d496a25adf7058f5e32c827fe75e80ba0e834e6a72344dd2aac4228828ed42fd83e4576254af5737dcd9b6c338377d46baccb02d00fdffaac12133ea0e75e791593ef3aded4ae4c9249b8d5cd20aa28cd652b9d750b88111d9b4fbe729e27882206b2f0eb614d7daaf6436816fd80d452ac71c7a7f9e8c595287407c6ab9fe8a242e98da4270b4f1d4ea7243c27f89ed46a567c643f31f967b5f12e518106f3d3e08178078cc714cb6e39079631966a9becd6f02c18e983ceeaa2106ba9043f9985b791027eb5dddceed563106bcdbc48a4ac64bd95e87c708a8cdc33811bcd16c35e193203e70ef2bc7203183fbf60d46bc581f1bdfe62387b3e6c0c4a29130d872c3f8b134e7dcfb080e7e03048c49c0e468dbc44eff4b02e50bc6889cf7600fba58c0ee409ce948aa684baef4956fd8fd4a9c4c49e84e2ff314b7900b179fc66f5fb4affb9ef7a6064354fad8c3d2d50e6f2157576f864a843dda8f547955c4d80a73d4a86b7aaeaecea886927a5ba0e97df740ec7e8b70bb650010df55d4b75f478b07b205b560d45de666d84206c1bffd02ab7b8d1c37f21c47d1711b89d16214d8151a8e75eeeb5c54c39e5a855d578708d314240a064051d8b26c6183ce755be38fe9597dd5b5d198532b1db083a4b856b8dd60bf1db197cf1df852eb6daecffd97287a6cdd4c05307722e0fac798507f75b03e9361d5627ecdb56a3b633938fa61b2673efe6c6e768e4e7055e6c1d55c7113efd3e95151b606bbf169f4296455dccb93da370150c54fc11b3682f092f30381c6ecd218a3d9d39442c8bea61d9a71b174a8b2c56e028689380879cafb7c4bc2691dda0cf6ada039755edf93f851446df9f63267f8b8f030c069fabbe6457d4f63575b5905fb927a5a720d52c351bfbc48f12440a91471697e6b2564b1a2b314fa0e6dff090079637287b635d875f120671561102ad27aa83d9f0cee41bf023bcd703ad670b43ae23bf01713650834cc1e95dd486757f0a4f6fc9337bb95738805ad5e756198579c886eb0ee77e4ba957997dde0eecd84e4c9171c84ad8f0cb23c6a289e037f3a8beeea7965ce34fa47cbd727baa4ac9e6dc3baf17049fd2386674b246aca5ef6b8496f1d17a3175f6fee86299232c7fff682f066cbed895155d475bf9fd4b5571d257534c88c93377b1a600d4c280d42aafda975eb32c740073cffa610b5fd2dda7262a2fff5da7a0f3a875c62949e0c9247827d7a49bd8185bc27967124c34b9725ee961bc8102a029786652c2571be6cf33be63cf867c2b48e5826b31b714a415fe05c27f0862a870d8fb33200719ef4ac8530a4ecf2597b4a7f2e66f078a7505803774889a1cf963083c831f46725a1ec5545d8489e53921d81f80ef99f5e51a2d5992c7769c2a7ec8bd8e0f2fd81de53c7b69b650a2d838b269185c5efd668c470943bd956e3c5e1bba5d3b927b10cee68a75372d4d6fdfa6782c05659281bc9bc56a2123967f4f50cc7ae3379ba21e1617553354b5030b3d3f0092c1824f5d47b97e6b4fedaa90aa2573e1b115ffc72d44fa8209fd8d372c8dc9ee00193b47c2a9a302875da331731713243d02eb5a57d5dc51c35988ffd742ddd75c191f1eb2c2214a1fc47b82db8ea708818262d9583f2b1b98a40b6ff6e94742f25661a51882ef28475aab12d9422b6ac48e341cbd6f38460333b5fa1cfd4d0f43aeb46c21938468fe3f7bc771972246156652d2c58b18c8cecec2dbbc0feb0fae9f6bc022e029111f94e8913c0ad741612a1426b53cff73fbb24fb7b22ab750ba1310ecf339fe12ced6a3fae17b4c429550794a8d68be891b0e30cd28e81de2fb2ecfee58bdf11794951276005eb8a5af21e03c8aaeb595ace652c5ce60a8b98f6897d82698ffbb2e02213e50d9d3f00bb42c8652d22bffb87ec576ef6e206ed6c846fd5136a87f38c9ad899371799f35a6258878418830b04da79fabd80e7290456fe17c0850a4c20e2e657f97f4a53e1a3db65bb5e71bf38eab9f56aa11e6ef71c85b8a28f04c271", "ea196b6a64be4b0799b1c2f72281300c3a2577db44e5d3606b8b02fa8fc46c7aded7e442", "7c86a2c06b7520d60023d18fe73d09c514ed07a91d50d8fd5bff00e7550faed1", "952f492fe00b26028c560fc6", "b3f3294815ce461c8843172efe93f73a8254e58a0e71953e35c15aa89a7bd9dfee967853dcbfba73d3b87fa60449cbcabf13b1206d0cb27d2c3fedcfa695b6d41efda37bb6db35449bd470a23787619ee48f981d3f0b1c8e121725b2289b6d67858a4f9ab41683bdaec8a913ca2cc292a9640efe50fb85a1d1f7b286f45d4448f85b3242f45ab44e3281d759db24dfabbae4259f127d6546ecb914d7e93e2c19230c67fba8a6cba6069023ff7ea3d8a170289c2b4391bb97a7b899228d032b36186dfbb29ae8f0e6c06d753f4c6b21982d49ee682bef50a5c2c8434510c5fa2b9c0349592f33f8d7ad6f7243d42b292aee6d210c61e3f898875b91a17a89148275031b74cb34e628d7b701775dbfcf87c79ab279a73dad14d8eed365eb9f29a007b7d2ccc07ceb8cdcdaece67fa0166e135c9a4b939426882eeca98ab887ed2e4888bbebd5afc9f2da3e9162527262b0fa85903246bc8b80df3060c890ebaa516781a2b2a138b98001287e12a9c68471912dd297bc0beadccdc31a27b7c726baf31510cd355a28e4ef786b30084af66ef135909795aa73814cbbc6552270d5e11d46e9497ba30d6d8cecf343d16e7e3357bc9bbfbc7c1dcaa5fafd8a9b07056129da02e6228886463474c5af1d670bc14cf2868b816cc71578ad807a37477341c8192bfc2e8b1f7bfd58827e041f70384f92bb4c6acc415dde5099a1c2b27b709f9e53d1dab07c87a042ca4af7a2a6ee57b37bf2bb42259d372ecfeaf1dc55ac3a9f211f16fef3b2d5f11dc19fd1f425c14779580b2501ec6e0a84220e7e12baf9e0fee3e8cf499a7fba6721a746f598f04ee8ab4df31fb8fa5ce2d2419d5551155c009f2780cdd225ec2c19f94fb9c8b785ad4574b4da766eabfa696a1994e64a2518d1bcade6390cc683a6e80cf8b163c3e58cfa1134ee743079347f08a89c81478668df32ce9cdd7b853db5cf7af13436f3bbb11bcfa8f6b6d727a1df84f99fb3a5c248b8fd5baf669b68fd9af45298030f3251bf0351fa9b58b0b9fba53ecfd838300790ebd689744c1b7b333fbed76c8fb96fc669ecc6695ff5bf8379dd2a3c270af858cc60894be8922d69fb9707bd2a7825f2eec4a5056e5e91714f4dcfa86974259fcbfd5f20d55923a0a9936fb20e5ae9670e2019336e15f530c0be449fe355a7a02c0938d60720d5b8f4f59d2e4213ad5251c6058312b43d47c44ffc8946a98797f5ace279d3e126da63633c0eff1c412febdd47817aaee466c639e43637c1e179f606780ab490d3f0b3c2d79709f1262305fc87c02f68da2dc32f8c544e7b358c3a5d2c27986a19d13fe736c60a3524e94caa55e853eedeece985d16bfa6c487bed6583436cf82077fcdcf90a05f49db50588f46550f7a0c3a1cfca902d66d25dba8d2c53bb5557cc1d87c8a407898b3c30c4f0852df92d839859c191228d0a47324ea9ec2e0ae84513cbe4ff4aff85e77b8587f1044bcb9775099ebc2f28fbcd1cad58a8ce1f072f2228f559fbfdd8405d86f8262c27c3d95e01016b343c6a4e59dec81b59bb6e3c6109a4cffffa85e9752ed2149b5624417c0dfd1a27bd2630bf59814f15820c43bfa317be59ef6f433c95e8be154a8ae94765bcedadebb717f0d8c24e01e1952bd104ba9620f067554ae0faeb78f13c622c45d97b2b5774a3e30cb07f2cf0e8b19d1266d8a8861f3772305e24ec5c9cb714806c7d705a3bed6385f8be4e12562e17ec3df01afb4ef6f7427c48a1bc0e64fc65eb1c3d3ff2d6687e4c275a019f5ab5c63bbe47e3680fb1802d5835c4d494f0f394de1ae47f81eef005127d0971c4589c456ae6a69855f35635c28b590c1b93f155fabcab59b6c7cd8ea1c4ed1f67093aa782c54329cdcf9bf84a40400de707b894587d6e08cf7fd72fa45b6709a26e97ff5ec1269b8042358f872a79e8c2db1c7ebffac014d6b6f71b0c1c1945ddedaf5b6911668059b61b55eea4737aa307c829309c9ea548fba2bede023849bd61b5a467cd1ab1c61205ce64301e2531e5d58d03c74ecdafe1f5b74627be8716cad0d0a0be60984c9f9dfeae24a6c4949170ce2f589326e0a76c447a578ea3a5e4bd9f18884f18843eb1a78aa2fae06a7569a97551b227c34d429c8e1c8c5417ced93c30dcc607cb32a365d87328aaecb4ce57ab8e74f0d9099e267cfb747a3bca9f76b5f6dfb543bc4b5c06c3646062ec14f511058eb2939601913f8a0f1785249cb72b0bb1c12a9508b23caf490537eec53f614f3e06592eb61f75c1cecfa514cf7b500b0375095d5db74556220131390b77d0db72711c0c7229a5769b1d2b3f5105f3a4370beb1cacbd93ce32f89f1fc833c7949211dd204616c013a3399a22f5325f1a00008f4c8ee7dc5bd7476848721fef843123a6213cb0c0b6ae84233ed01a77a115d06e08990b8e60cfa4f41dbc9505cfae76463278b6c6b5ac7c3b83284caaba4a6a1d739c392528ff5b06bc3b82e98060e3001279a44aabaacc661fb14e7581d1235940cbe067c6b386da09454e0467c785ed0b65d41ff4cf36ba5f63d3ff2b45c11c6c22d3ea8ebbf1d52d770e0ebf2ba0c67c7d3641c145cab474a88119335990137fa82a340c2cc8c453752a3aa801127a47aeefe66d1af1a26ee1cd0e6d935bd548f6ce33a9c204be02ba08f9fa03c685665375db7c0c656ddf3e441ddd96b0d2018beff5086cc63339f26bc8332a5e6a1422bfedb69187a3443c23b630a28b02f8075faf3ff2fbeef6cdf02ba4af47a765003de2254b69f487bb5d038759a33ce6885611198b81b0b6fc5d7a531a7a90dbc3556aa758db1657698cb3698b8207b1c1b589efe5d52790667ac483dde9543953c6392d5eb8afdafa205d325e314f810e9c7722cbf5bb76fd6502733149bf21c60717ff5bc366b85ee9f206bb1f330ea72f61a9766090eabde747b1eb9c046cc8713d5a4f8d4b7dcd7c61f2496c5b467608cd9260382b8f11b04c318a5ebb6411a4c7fa060e08c295c6062ac644bd3d10bcbfcfe2e3748eba66f65d904ff21147faa8475f508f21238d42f62b697249b9fceb905127f7684c8130cb8663f09cd25ea038078e1980237389337d1446c3a77bce41b37b50b9c3a020526e7b7b3bef370cd7af71b225700627060eb65693899d277ed130ec5ed9eee75d4886f31aa93bbf302e0c69c9c4499396b43dceb67c02fafaff8b56698308393a03f60babde883f00de2c66831f024fafaf98b2fcf37a9ce01d4f34e95c9408395716dcf83fe86c7a0f5e3e6741c3b63b6ebe9964f1d5005eeb732ce66402007beb3e6a087053", }, { "9100c5b2d7c5d5a854bce55e82f94b89a268da7b66357a661dcf75cba10a1b320ae0e4e1a5b989f9766e57f867a3810a0b5b857191ffd7aece4c796f5694a2617486421940cc12b63a6aaea20d2fac188b318a1c3061cafeae436e04d710654b96a864d674768caee03a50ed6afc06f52d90115df1db5c9f1ecaa4f5da094070b1a447251ad3d4fb0e24e87821ee6d4e7e7eac7059080f77d2b36cacbdac1c6e5063946a376865458c4ebdad3c2afcbba8a82b01b03a7882eee42eab904a19e0aead4ae515b02aa2fee74f3a114bf5b9f320baa35b3225491653f4a69e0d864cbbd031d0805b727e42c2b9530dae0c01cfc6a42af8ca730e1d67b4bb743a072f0a38008b937209d534c2284271344340fae76af2b1dd00cf44b48ab8ee92e8f9cae8845e5a8d338f505cd1c19014018bfb6b7dad487e7c8c32064421982c1a63149ec16f2bf4fe7b50cf3ce1e33d6cdea8e98bf067077c9a0ec1bba6edd5090273ca719ebf6f1a0f3e56f021945cff3c468b2dad92a947a06a024758d7505a4a1bcbe9da3a03e97859da99ed36982a7c23572ab60071566b749dc34bee1d9609e87fe32282cc9adba633c9ddcbf359ef4a83a54af5fbb5699978b487954a907dc9739f4b3f3927e66cf0c338e31c272da0cc7795c72dfe60a5b2e73bfd77b8c6ea58122a913910fe29d3360cef5d398f29b024f0dd225183d538bed2b076989aceaac460e3d45e0ca7941897f151261a024b0adf6d5b62429420144497adde6557a3c53b7723471fb760b6a8b1dcc2b327cd939528f5d7bc16ec00ad99df12f082d82bf9fb7318b3d3ce5b84ab1e38d2ebcb6713c03fd0d62bd083c4af96b4316ee02b6953431c261278aabd96e28f81adf7946e3664446135c825e45ed916ccb941350c84523296cadd5360bfe3e16dda75db10da1f710fe796f3456f0911294a4735cf9968656345b9c3049ca47176194c86f36cf702538df699fcffaa254af15b198ac37eed0837b00cd3547e496ecacf6136c6648a535a235059cd75a3bfd0bc49933b379b72e7a8463c268faaf05f0b27256fb179c9d4c923a13ec6600f83aaa2bee13e30c8e676040c06aefc65ba238a29d403f3a8cc164a0bdcaa1a5f54bc1d35fa4efee0c402eccab1e92f6b0cba94e1bd87898a9dd3957a7eafd9d26bf70866450646090833d4b91c032428bdb9097b409305de669a58e44931b7b428bf1a6dc56177cd944b87b04eabd80c64e287a5758c83db26dbc06f0c772335363ea2fb9f19c833644fe3b3fbbbbf5f9d460412d287eef862ae676f258aa45bc8465667601e9ac46e7d77693936c8d67ccde94e54d746b785ad26aa38ca0500105b6870790235e780ac50b9e3198f5fe678ae3a4ff4f1d4a2177edae183daf2de42625845973fc544907e27a90d868f8634c9d529bbaacbd228a5b4ac7fa68ac208e207a022cce4b24a0b5b5791eaddc6b3b3ef6e5dba41855ff531de9bbca0a39ea743c0732772bd32cd15c4b7f28a6ba579d902331a88920fb970aa75114e14b891d42cb947e9eb14feafccf1393796b21099e52b21773adae8e550f93364b1c438dd7d7fc76994c51860b652974d04a7e6ead207610de149f231422595f4e9ced1674d98d0e15ee841143ad8613f804729524e8a5f30d451611676f70a60c5dcc7127497f4d27f35e7ba0e48f98e9022e0deac400e809170970867a1682c7d2f3ef2c632c44568abff76f4f804841ae462c7247147b6e1debe48802674fd55b2ef1be5b4604d5f60c35358c7d773ab3a3ad0ab81868c6044d4e06a48ddbffacddadf813a2ce09aef34f3b60b666245a032f021b87c81fc506166983f25930cff728d399f6dd48ea1c745ad2da7f2cdd9e3ee915f708db0d1f3481018db1c174ea950ed17247bb8ebc065186758e5403bd4d19a445e4a15519326696e4280bcecd1a903f525bbe1e521f94d79df8db4b35f4ef7bd990c0f2c32789a75f95761ca0064bf251fa00b409a58b979e56d2c44bc2302552f118162891bd78272384c739c0c98bbaca3fc46fbb5bfe123eb25df0e27343e38b5a0c2d0774443af91b64b9d4e0649f20290edb84fcedb3bf4ba491bee8754a32716739e5ab64deb6c9888bb9fd2ada1629a59b16934ec5dee3678dcbdcc7fe5e2f3833da9d1281669b1d108837eaae5180396813883de26b957037623825b0675df431fb06b35191c06229f84cc849ccf1b1e079efc2e575331cd77b3297d2908c048b82b7dd14883f3e707bf6ca38f87c19625bec47c11f54988a97205d27ac51a32f19704391af72021b78cc4461386dc3844a1b45596fede3f70e311eba92b1d9ac221d3dc19f3fdd080c2169348f2cc8c9380e12a7ebf69efa37bda4ca6f7e66919b94532ac43022c0518c04d0a8cd99e0cbac88b7a317a1dac5469534b4fbc64080196b44498e149b0a196bb2d6f59392a21c4a4523ec1ff922a52de790e42810fd9355471169d22b734dde4a3361ecd57e271a92132a8b35cfa91d508d45618ad8c6c1ea209405a3d1d3ee1535caeaa3f20546052fc13aff7a584ff79db1726678344098d8563caa2a2abf6fe5aa03d7af49dccf1b17be85600e7cfdbfff54282394b0fbeafda615185574fdff78d59ec2a26dddba1c531a1ac007cabf5be2e2f0a3dedb9174e0a9da5597c9de6d68911fc66ec9d2b1e3fd71ebb83147ab14384ee303d067f47a324a01fc187f54a98f1b0848fdba2ceb3c18936d503e71887d548c4dbc70b7eecac9ead3393f8cb85a84f1484f2e237b36b6d886f54a0f629e8bb05b0c6839c722149a5b541703aeac04e6eb230a5659b12ed0a668d018f75bc94258218c1f5390b9aee4c0b2836cb76a47da649e2425bcf4cc15c4d51d109e5f78cfdb88137c31b2510264e46f1c4eb6e6b3450ad901ff9517b47a24d508844dc85fc5dbcc079e2d09f301691f401ff5f36500cc66f0617eb4dba389d427c7ac778d78438506608f0961f818a2080ea56d0f61c40fc342b49ee63e730df61f757387b9089e1987977b7fa02d87aec2e4be24b8bdf7fb6286d190f9df870944fa910df32f178ab692fa56b071f57366a3981f51800ab416dc4500abcc19e0c6aaeeb9ca063470993ec749a0bcbd07604516b1d51175ebedbaec8986f67a4d9158f75b5f3bcbe86a83220b4fdf12a0242951f94ac7d52882b1b209b82c4749753ea4d46a60bcc4f3eed033bde2d3d20c25cb46fd907f7052217a0a4db143b2efe8875a59441f4d22ef70d0c244b2de6a7e15581e84c860a6326ae3e3aea6d3972e2de0623d2d852c9e65eed318bd3d86d29595575df60d9050e1740f884796b6657718a294adcf2303adf61c6b23933db93885172e82a78f741b8efc6315a2c88ccb6b11692a346cd82a79334e0c610734e61e6378b5e2ecc161d924778bfcf4475805a0823a0d5a54768d9272ee99b7c4a81b3d5dfe1a2f5ff34", "3c77f30bbb698b1571aeb54653fcae2c23dc16be58603f0c361eedd813ec0c4f63005a1e69e533da93e820e6e4ce1308aa29c60289060ebf24fc9738e8a4874ca4e26a0dc79ee75b8607416bd554737f", "0223c0a6052bb3cdc99a284fa169ba76be2df53b677642a606090a9267a60769", "7d3981073f90c6648c5e9c74", "61ec5230306b70113f67b340575b77ef76d521ff75b754d551e4177591a02351ad382b2a4067f2b3af7e8e15431c7133e98be9d8293d17ef40161dbad9a4f1a4f30cdd557bb9a8b03b5f1b277c850e23ecfa0fc2ab1102e4b1d5e836a606883c3d43527fc3aa26955964b144a9a56cafa7b174d72a0635b80e7b4f871ead3838a955a14c4b8c5c3c66fd86a5e4ff10dfaa92105378bbc5f76ad29727e5bc4779ba3e6dc19bf45020f6ce4dfb3400df05cac51577d58eec21b22839b8f055226b204e641783bb3305b4461172f1c1d48eec56fe6f82aae564ac6688d7b0994747d9b23a24418e69f8a4fc548f854f86baacbdec78b7597b138c453349034c8cad2ff272781e0e6799ef2f8addaf18528736aef21ef8c2d213161e36b2c7815fcfc40747626e0165684e46a9a2275c533d548e52a9952a556168195d602ead86f6bd699e97ca59f4cb2050ff148f5bdfec358dc4542ff2f700db9861dfe5ba377ec7fdc0fcb2501e72fe6873c7cc76b95b4f300857f76e6e6e370119f403b556115b19fee7009f4f6675ad2d174f44002e35ddc360f309f20a3a1dbf39d90d7e5fa2106c53afb0bf445e4cede59cb50b8a7a2c0961d00b2c251f2d815309f74a46a424838ee87f1229273ff3b66dfb79e3b1ce11bd60e061e60e3f37bd7ac896b618cd78388590f44b1a276b965a4b95f2e3a7a175b30fb45dc7a71d4b3a1a33e98af30dbb46a217c50046ac21b8bbe9537c02f05a5780c8a5d796bd6424fd9e9f3ed5932069bc050bf4a1898a0ef0ca756aa2e2269b709cc92e0c5192ab49d692143388ede2bde4923c85eae8f59db5c7711dabeb33743c692be6dfebd815456958b5e1384a109f891f433e7b4a1031d4f30478b05766dd97eb964a28f2f7b55aa6c27c7f4ebf4d47ee8709bf99915426b3896412a855798e392e111789213af537cff7a976b4509e0eb6ffbb8e886a3596a242d16d95109b0ff562c624e06636a3611f804f9b2e252afe8a4e5e868b48e9e734f688f2da2012d7fdfe2d3aca75fd74730a85aae90353417fd52b92d28a5098b6af358a096b859859916bcd5a8f779676c6e04ea461fe62872050af92d08cdf1124bde1e889ace3c923457ecfe0a635ec757907a131ad7c2ca3f60e1317880f843c5e63f4ba59ab2882a492dd1e070b070af6f60e18cca29541206a7b267c3f75a5327fd9b8ffc9b36b57b73b36e586541d15c85253e17a2581e8f8a1518f275cc79afcf2b5c88a16e9bf553e757df089b5db90a9dcdc1867b788fe75abb5161dd7ee1cf37d3f0faa793ddb1bbf1eca13f4220ea63af8ef7c0e7144d999ba1c5a983e74d48cef708c1d28d3c0a168ab87d0ef70f381693f0d438ce013ffa2cba65a8cf6b498a7120209564535b7372690329cdbd74eaa76765962720f06aae58338a10064ad80f5a67395db2c31d36b1f5eb777306395f192599d2f737327afdcd9f14b3f24155a3f974915d3302427494fad756703b13afcd1764ef9735e7dbff920f1253cb668e9f40632aea1e0b4620db162138e4a97e6f0729b14be4a7c3256250d5e7423ba1238c704503c51cfc9cb68db7001b2f597a15e77138beea02e11e0bb98a72f2a77b7260e9172fe7e60483114ddd836addd966b69570db5eb26a0cfc4f8a8b80d26357ed51a70165bc0dd11ad7467688025bdb532e7222ea12f23c44d08d111b0ad4acb2f5b3d6b45c387d541ffc84466ed57acacefb1436ef00bcb5b6211dfd0650113ac369b9f3e4891acb2693c377467b1e9c949cc0ea6c4a72ef9292964275ed397cd2b1ed25fe1aa8f47e90cde362392da5e53893eef6e4f61decae1a75e3b726f0596f09c3cba62aa08bea89984b484d5768296a5afa8b0759dceba530a169d22b81979212b3343db35ce4e4766dd251ea6a47f5033cc090d6577efbed441bb4f8944937e812f12ef17ede76df621bd4cfa31567ade18b74583a2b783279150d584ca13c0d4784b70156afdf9be8ae96666b82def888465cd3df349de427d5f5b3572e4f963d33f968e6780e381ca196bc04a6664fe93fdc8558b21b84130dfa2a646950eb2e927885925af46d7a28d1507bcc3c02ba98318bfebe5b9eea1bd47935ad869eb701cbc35a9aef5efad88ff54eb350a34ccef2e159de8e16135b81105bf799fbd86aa11653b5ef93a1ab1c367231d61b42b8bdb4f04d8d05396d53247d51890be9b56c51cb19eec0fd1e6b8cdc98376b6c6b30963ac7ab02656ff94dec0e3a0eb3f3ffb8bebd99d5889df98e6c77093c370373dd5f17871fb334c7eb12c6ca22deb75bdac9eaf24281c965dffe03da9c940e13fb382fb6be332797813710a7cd2e7720f5b9e53fc0d98fcceeea4a8e9f787e670d60bfc4a849f34571e5d09b9e9c28cdf2b2d888eca9bb31ea8b9239bd19dca86880ad3e12b1583acc3a6d1f0a438ce3b5a337487279dc4ead1b214272d455e6a2c8cce4ae3bb29abfdbe77a67ababeaff5dd9c96b17f589cd4615c0209eba5e4b1c7167b4b739ca4b9957185961529d1082226f85068890c94aa1f1c244259ef7b120e40114926a49c4412b67b4caef1ff3ce6f3aea3c6107b830cd34df9f4d73d7d978b6b9d5c481e9d76e83d649e742b098334838fe50d80975fb567642d3b72c461ef3072ebb1d03c0099e97575bae6a12cd2352d9d296351df6965d736d7568c2911394a73d199743526ba54dd62c56c598f4e78495c0172739274c0b8c96755e489765723a24a8704093a94544f6c8764dcd1ce6b4bf2917cfad27d85e4442b4e5bd577ea1a88c2b79d61cc1be01ee9028235b36444483b4e45da1087bf6d45ca540620de5aacc644a0d5c4b807b582c7b058e140eebca539947502bf73c9abc81a0e3a618b39d3a38c4ff7f94767fd7e6b9eb61e629806bc3d183bdade7e369d180dd2f57fef677e22ce41be7224f11723a85a3f1d14d7b72dc98ccb2816b77e625ce3db3e2c5753af8b079e0d63939079a01910ee4699cb405d4d9c60e4ac86a7fda3a4c9c290662afbdb7678c3a84c87ff83470fa8a416511a06d3216a1445699d7ad7e6980491fd596d39762d576b08fcbf0825243c1fc01ec8300780857c429c607113160a8354f6699b368a87983464472a5754fd58943fca6f6779764fbe6cbb510d5280292df02c4a7ed9acec8c95ad67ebcda71d0f519ac18db9b43b28244cd34fe02c5d694df57410eb54c5e1ca0f8501e7776a811d7ee81eb9d8c80b2ca50a012b5eecd5428af965b217e7fdac80be88a01f76d473105b027eb557a523f13c55e1670ff34627667649573e0f19dda41c525a8c96c2866a88bd73e66c786767e1657960f6676d8a22be1c6024158a0f0e4ec761148b5a3d8ea481d8fed94855be82479ba23213190054f937838f0e35e00aa74c89b294c29ea25ad7e96b4b6fa952ea8f1cbe5397b7c86d0b74ccc25e22c88736b045fe86110bffa0679f28a1f27162b51410498cb7", }, { "0fcff2c29cbb5cc40bfd2ec573ecf368275ade6a00e5730b77dab17e437b46524b3814e7f470acff6ddac4e0c6b748ed112657120bca1d83a4ce01e74a473995804d7c74bd28732a02370ac8ef52b600790d1284d82f077cfe096448509dddd0eb5944a882b7d384efdd4dde3003dea910f12de82035651e3ec9668e66435f519da3fa1f5bcda34aaaf028daf3068304f7b1ec18e65136241a9db281e011d27db5cc9c1099405a4430821e2488a228805314983966ce5d806b0f014c21d4c9d6a066e63aa6407ed6c29cfa4a3e22ca913762ca9d31271d9c371fe858f3b22e931814cdbe544b9416e88f6026b12bb8e88d8285beaaa35be1c24339b5f567480d7b16cbcf6160e549ef4570a0702889feaa0ebc54b11735735b6e2850d5715e5087291fe8890432784aa219bacaa2b874b075c9628cfed5e76dfe38426f9693f6bfb2de49b710c101b2dabb7c7c74f12de9ba8f75b8645d25629568d12bfbc7eaada63364b6f56569cf21e54c95d6797e9008f3496c506ecfe5d6a010d168fb7f0e2ee3c423492df36a133fffe9b87d7ac070c32cc131fba6089cb7d904b25812e03cd6048504f7ef1736ee00ee6b7aaedb3dda9c6fd6437772fa5076aca9888ce55e906a62875979bd477aabb2f4598d32342aa10a6d187c6768f213117a9ff6d830603bb7b9b475002e20b2237a4055ae6af6b8d70e343e76265188a0f07e7820dfb3d898684d99966d4bb9e78b0e95f5044dcc12810a89a75b11474c8fc06c6e734407db91a072ffeb2be6773a7c6c3ec939514b43daf29feb3aeb7afa57e96d9cf0492d90bb2c7be613f2208f5f5f5898b0a3db8a967a75d065efcabdd83759c88086583bb3d422c6c6425525a1adbd515199dbe71350b77940813618b88fe139153974c80d968ed4d9e3f97a91b7cce250a7c963f880dc38011250b9a131f2b76b677f78fd0e4cd6f1465182fd1d644dc42db0bcad8df4ae9f456841765af8e1c1775abf85a69577ece6f9e9035e36c88be784397479e713be4f5434aa4c166bc4702a4916c0c003a6baecaa182372a30af6dc7e6fc4912d13e662bd327829f6e85340fe130001babaee64d211d6761bcc52993c162a692a10cbe7434310392b64792a777a2b31341995072a6b7d4538cfde74e609dd1019a9f75cec0896186c0f42e3896d15be87aac5b11642f74e11d5c2f7de9f07f848ff543507ea4d73fa8f5683fc6b41831606352c482c7a5a013c51e0db59d824582c595f17a6d2113528943194d6b5aadcead62516507f178cd0f76729cf8b81fce4e0138ab224bfdbb8f16f8ea6196b90ef90a63f0fbdcbdfb5320984be8a80a26b932d1db7ecf870dd67fe838069136ff9b9ae087779e82cacf1b06a7b310ce6c439047c26fcec0364ea87e4549a544d540256cb7c3ef7282fa792aad89e919dd89519fe910501f5ef88da43232e917730e742ac2539d454e066feb9058f56dd246fdbb674dcab636585a788b338ffe41f4190447a65985acb9613d02669ad4ad888004c65acb0ca315752e58f51c9ae9259f20cbe8a668a207a5a46e30891bc909108f53db8bf6f0f11549e621d4cf4763e0035c867bfe9e1192fc421c080b25289a78f4167fe517852efdb6f3ccfe67ad01b4337da2c18f35bdc151c5dc76ee66efd27d5fc784e4e6829bea4f8a41ec8bf61ff998d178ce9f4a10551687337d7705eac6cd7fabb3f2379e31c1d01e4dc63e475f0fb01d9efa3de400b5177e2c2d68f2ead89e9ecad62cfc97fd0ad5b3391d0248dd2fd7c75dcbd802d3463ef0af21eb77b07a3286a72f1e9439f457630159abde7983a5c74f7dda12b40913632afedadb691d62003c70a46664fbd976457544cef8ea863858505b1c596e7f745d4a5fb657b1c694226afa9756c40d9c49425b323ce17a8531c5919b24010f715b5f27a300ee37334931ca9ff5c83c3f0a87713768ebccaaa15e35c56f3536ba945e5d954c94c885c68325bc4b51fb55d96c8d424849ece9a812af0747d5b1dc240f71609439f65acd1c17086e025e376eeb79a7255680cd692fc4b0f5768d1985fe8a1a387074f58c8bfdea8e5c11ed379b845ce2052a5b24ef0c1a658923eb87adf5b01e6aa59ae6937564ef97421722c67404cb9e5fe07d5bfad2e52ebe6cccb41ceb1eb2760545fb6a3582bc4ca572b0aa4e4f0a2ecc56299f3b485d980501a4e010576615ad518fd2d43c1f79aed013ed1f1e1bdb74357aaf7dc84772c9ec62da43c8ffe11a7fb3eeabc3584a936c37b28a438dfe78f89de6b0d5597ac1bc55057544e68fb49a6e505db69af122c2a3ad06219b7f2a2955db0ebf55c06baac5e0efac609436dee484857f75a8421945484ad0c7650a1d3008cc85c938208f19002b7994524878d6ddf85c763a65cb72a09c3a059657459f13cb584bfbd754fbf2de904517092be4f1786b2bde26ae8eb2d884592fc9e84395408f8117e47d1ab30d5fca167bbf07e41a33c230d240e3aac53cda9f251e24659da57d721288252fe7ff3653ae3e47b86209e9344accef0009b99f2ec7b3845558f1d77b89fc9b61ebc1b589fffd3261f71b9631e87541e22ed100e694854bed771358f10fe452fba61875a605b8080cc39e3eac13708e32518f28e60464c38b782c7c7800df63b6e7e95ced9154ea54e32900f6998f38eb1e51c112b6949e2eb11a96b1ea0a68c1e3b5af750a99c9fdb2cae44c5a1d37686ef87b158d19343e23daf00dd558cfb91e6f2e18f8e806abb2faf80d082f657717d08ca4e9c0d30d9bc30b612bcb1a3a3a3843231059dec344c6c04ce625b3fe064092e00175fd9d38f8fe54c4088efe30d211412be01460a6d4ad8d0a618b00a21de0a383de30ccd72f119b27a08958729a999e8aadff21829cbe8cfe398d90476e33db4c64981383a9aeab4a27f3bcb29d4b3d3b3a6ebdd71d3ac546b8658e269959630de176819b153cd53d2091efbddd2cf9178ba6ee98e1a3df9a095db0a2b713a0988a22239f5f08cc8f9abc3d67d9267f54dd5dedbf01bd490b0b09adb21d4e5aa7707e36cf77034f01bf8c7988a2e8dd7046bb2f486878436371f1258f3f7026afee6d7f6560be67103ad098edc9665e00118d4879f58bdd677cf2e6bc631d5c517acbb6db8a1debb4fe7492b7daf0b7ec7df056637c23caf926a1a589bef1db29cd81f547afd0fc9e459f46108ffdfcfdee43515a771c439dbde9177ceaf296a8749be0146cdca2b26be8c2ebd6cfd9b5032b1f7a375307f54c2f622711f8cf8684afaaf17c4da3e83666c40d26adc239c8d1a40024bbf560db5787ed404763d4e70ec6635c6a4b82c10f8ff7ad42217613c57648716ba94cb33129f3789dc86f9c8ec2e8e90e6bba0dfba1bb3dc3215188979a09f33346a6647099ed0e624c9ae10f83da0def840bdb25b718e8d86a616ff46b5327b1f99c22937920f5b5bbd6b53fa0b32f24befa4a7603234e6d94be51f00189a20b15c49e8ee58434a15ae9d10b9cf0204bfa7ab1fd9e006b22bebd22b036c4bb4c9949cb7ecdf01028d9f12466e144b2dbbf64d95d65347013e192d428678f64f0d9306f97208fb00a70d4615229143dd8890725ee3ba6021d38d6359055aa812edaf", "0c5fb7075f5e15a6733737b614bf46871e29417e4b140bae6e10081623f5c52f557c36b4da4b5a4e82920497514b1e6f745fedbf73f86ee10976f82c6cbd5bc13a917514ddd062", "e70954c812cac03e367e99f7b82a6dcc073d2f679f965d524872756ee58654cc", "5f6267f6b3b21423267310e6", "c53868c0fdc14e891ae1bc257fbb13be210a5d9cdbd9d18fe1b474f9a1929dbba3f25222d8fe8c1be3eef22352100064b922fd9642ad128a202b6382ae0a67c8affb0c5bfa1a80e55c1084cc372485243df872d677a80a3ef1ca3589908bca621f6f50133eb762cb9c05775d13db7dd3eb65ffd3eef96e8dd42928facc68390f6bbc50b17e1ef5ea6310d8756dd177be2cceb63a97bcceaa046794915589ca022d90756b02c22e8634c0ed44192abc3b8b1e2814c855ab27aaae3bdd801a73e6209fdd559ceb59a94fd98a66d12a31a643ca2f4b07ed910bc390f77ab89395d5cd1d783d8940dad4447f0452991b209cfcd998b0c814cebd08f9ff15052818bab0bf51c3b72ac1020d3b0974fbdf4ff941b1ab9c01f284fe82f2fd89c0aeb4b9fbb0a74ece08b3debc7b65e7263e2922fd4aba15ae3cba7885d04127c8e06a67f244e7aa4556f8694a5db6653f6e48d6de54f9e4024d25d3236d4f933205b6a358aa1506f832ef7d556c6a1bfe4aabfce51f3b5ac64bf6ab1e665bddb12fe13db9f07a55db3da3886df36ddb89f3a4939b1e9e5b701301570e3d01c0b947f498dcc6af438cc15e6038cb78a78986da0316cab67bca3e28c95e6b7e6b36cae9202cf4a77a0e15d3c3291d267aeee172dd587a944719b9fbe077603b4d39d4302b9a6415aa07af309a5e1cf7a9379552becdb4bc6a0b5c85d2e63bb141c405afc58a8b2b4188b3883a24eedf98dd50fc54725c440ccdb03514a6f37cab49296b6826b6bc7d7ad8cac0a3425eeb6866d94119acdad468cefe162a29e8831c77aa83321e8ae3e20e968cfe51dbf2b63f4e26c61536e6be4f63d61bbd06af38023b15f4fccb8ae0356d924dbf646bff69d1ac0d6e1c7f40b12d6d16e52d1c15958add5708bd38c514e47fe623a67c9ec211cd625b398fa7fd67a23e6e9f65d42dda2bae94524372fbc1a7e0ab3f1c451c126135536e73c573749aa60177dfb68843752b010e2cb9c1afaf51c94a48cf8ac7aab3fb200aaebcedefc6cccb581848da0121af92d9f4be002f0c2beffdfa65c36bec80e7f62d7009b1eb719d24b96e97059e6b50a52662c2c833738849f342391514349305228b29bfa9c7cf2a931558ca8e704c600148a28bd871465b23af499c11784aa45acd051f276d82789c58b14f12619372be4bc3a285f6cee21d65648d18e61752d6e7957736d3385f8ad36702c451c61ed475997d6d9f11c8be5257d8febce329aa701028aa2b5644b8515a95b5e866780e32754ac2e6f2e31b2c04a4ad35cbcbc25b23e9bf49cb1a5d877ca30880741757c29303af8676546760016f1538991b37cf0cd24ad3b1d877e5e1bd083e4b990af6ff5c0b28e530db3f463d21e76c928c8e1ffaa6c045937ea171a9071827a173e231f50e95430ae4895932c88ce048058ce6d0a50ca5c1842506158e98bb2912a61c7991a2256c97cb9050a4bb3ca32594622756291340561e9e584dd2e096263b6ff8eb898ae86f5f24500320d2d0ebb30d84cb4ef876a877dad23a611b39bf0cba5e22f2850e11c298fa23fed40691b83acc87136f8fa540b1dc40d1b0d0bd489ee9dad785c121955a094a2c6bd3353e142c04f7b88b2eb3305fd00d5eddb391b73fa2b16a6357aaa2abf2059ec979bd3ce06d5fff1c325bbe5c833a101615750613047d8155ac0c3a0734cc6aaeae7cb65d7501cb95f9d6d1161d09c961c0681547faf7983ed2efaf4e0fbb87a06169ecff1d0ee540a9223a73f75584441d4669cac09c2dbdb8aa2aed74eb9a2870f2021eb16e5f5c3e79a24d7110af4bece22a1086d27642550cadfa4f0e03f2c032a2745e1c9277a4f67fa4dc74ba056110fed3a63f643567d079c9430b8d5b3bf57a9b3f02d486d870229fee5462043b6bda8d265c745ddc1b8952bf91828d6db2edcfca7051e74df9dd456dca5e04ba469b9ff6a8130aab3903c05659b8f31cf4ba4c22511493a36541ff9d88c708dfb714d52a3c0356543e6efad37530b598bb63c3724772907abe4cad39c896c62daf5b30cd7d37eb36a7be2494353028c76e8d148b018c7bb755c45d2a33f61944071bae8316881e9aa37e4ec2374aac4f8436ed3c7db2092326538f07fc6644e0239899e3335f73c1e3c4602b12d19d7b639d4968974b6b2703ec1add8cd930cbafff4158f68f06aaac83bb4a2e31466e2ddc247ad71c5f4c49af7defd1394e21819cc24c78380caefb2ce87c0d1050680313037def12ca21cf67bb6692d6e4a9e90a9c9a0b7118ac300c6c6f636337aa25bc59cf1d9749dc183803cc0ccd1ff53210352795c6edb49ff1e5e8ebaee7b3eda6e3c0c340fa60594115e37fab60133b8a3b39d2e63db0bc6a03973e236fca801553912f93feafd8b96766049dd2066f3c5ac9222121ee9d36cbcd8f713adc8779949941f8a8dcc92ade62e46e9f1b292d5f7eced14c3bff50a811cb762ced1f103652773ef946e18569eb5892626627e085d4ffb3102c1586ddf88acbaeed903b22d3e7ccd8b8ddcdfddb872403240bc8e0e46a068f55bbddaf90fffb9a914187aac2ceedf21fefa1fe32fc7bdbb9fd76dcda1fca7b39107d308d11a118e47499dc4092ef0cd28d0d9af84440f095b4feb7adcba198894cd89a324c60ed0b996c520d4b33391bbbef1997256af7ba7ec1069244359066af81543ca23105742fee3480f890373d3205236bed566cd22a62bf69f8c0f27b714f84a203bca1605865e2cc2f9211389e0df7a4b3aab9d10826639357efe1f5fe64a1bd6d06d0b5605658c4d2d12e1bec77e70ea393b0a09043dd7d6684bd53f4c883f2f6928d99ba91873d063d43600f9105d503b11d8dc2b05e34b4fcf18e78b2b6c97d3b2c9249a2f6566ddab2a8a67fed6c9f8af2f4ef98dd579f2d4fb572e178489c503df5d5f03bee9920db347a6e734ed72ec7233387f1579c13725599a33a90915ddf03725dce20fd3806abc1029a20732380596057830ed63b6edcaa4d4418871bbfd58de1d1f2800588ed207f2016e11abd1baf1895f6096e2c75cc5916836a9ddc09cab4c28e53fadbd7d3080088131cc270095315b61011b0cea5b4d64b647bbcea54d20be1eec0992c72fc9c9771cae19191cf6a6f1840acec1deff605626d0a0d79ea8fe0af63ea75e80f8141fa8d7ca6f4c99dc7e78aeacc67762ed0134f1a0b053debfb9ccb145800b9818c2deb46f7124e8655f37c3291af107ed75384afcedb44518ca14cdea341c9657ec638531011cb957ed6b3434b736ae8c8199684cc58862638c5f6c07e1cbe8ae68c5582b1697ca9dbdd01e97023138a9173d6b1294cd99514a28102e6912b1c87ef22cdc611133bcc111e95c355a26b20a3d6f0ead66e932c5e1229b0fc17a7d6f78134c69beb362ca75017b1bf1105ac8970fad48acb8313cb3ff10e9d72c4ff11f95c2dab59575525c98653a9c7d31585a3742267c062d6ffc7a4303a3e81a45bf39e1ce2097623bba70f216aa612c64ba06ed6d596ad6abbdde69d56ab45e25ebcd4e485824449550232be26f987c14008f67c9db9d0f709f567fa44502b9e0839457e5f0aadec0395bf5c38ed8de7529708e58c0a895198fc8b2570fb6e68547630ca7f313526d392ac4776be973205f971854c300454d5", }, { "95a17355dfa9d378a18ba20e58aa4b8711ea1d6e3c65e0b2d3c6382892c7d02768437d47ed50bf8edc619c340be7bb1cd1d88b0d3d6bbf1031f738c4be09eb264c686d39b92cc7958e63c9994a84b61b5c412999ace8a9dee0e2a29eeb8dc537f63271af5f3844ed9c0d86e6913c02ed7d2b862a132f08f311aa92fc3757342d89a5dce8dd20d5792d5c60be9862ab168d3140a061489472f2266f297da357064833ef2554c49f8120ff40b961ebcfee1d0f8e7e5722f049485f72c502c9cc4afdbb70517f0fd2a00e12596ffe285d1b37eb998e0e89d756e9491ceb13e83610a3a66122b533c2c3461b3244438f5f7a7af8088881dfdf6a29fb563ce38c4c8632ada8e7e06baa2686dc6aca6bc944e5c14d6e432c4dad554803912b8fddb1c18a59a86bc452914b2efc1599c5597f87a6edcad33a7728827bbaad0a975ecc22b7748d7cc71ec7f51adc8fe0350e67dcfb31af35a8d7b72391642e29c2fa4b796ed8f535f6bc2b1198baf1cec858aac38959f83130af55c21383ebd57d364eeb0e442104004c1599060667ce5e1191e76a89199a386e5c4bf147206e7d6e598bb27a90b3c6a54cccacb39a0ac42bf22eb40bc8ec7925376a6c57d8eac6317578ac052b72ab773f572ad961ee05531cb95ee5a6d70add4176351960fb4bd673f7db9f698616a8dd41823f2f87924c40f131e6c83bc40ab1f92312f46ee86765c306cf4a1d77275ef9668d80f9d9c1ea0aa7b2456bbcf764e009584ef1c0b4b4c683fee3fa2641f48ccf7485a8356fb3dd22f848deefadbef8050de9c5c19e8c449c6f3ec2b1324f80a7d428dc44dbb966d40244c3af03bcb410a57ad1430615e07553a22686f1a62dc6cf090aaac3707ec5b44274b7fe28c7a3a298e7a8adc71e016944875bebb421babd2b64809be3454f25b90723e2cec68467ad2d14744b15de8f9c397a505a340e85998e207cd46fa18d76c46f458af4ac3821c0ac6cd68afb72c376c31daad1a2435fc2bf333260c1a82430edaf2499e7455a93b1301eada2e12365ffcd36a1119664d0c996318a3e55bb2c04dfc5eb251f7fd64f9d83f27ea6577d748e1f85248355ed19867857dc3383e01249cc37684b0eb8e891aa663801e4ac8f0331b38686a19f0d19f6e94c7ac95ec395962be0a4e3c8358d2f6d8f13191e164ad29cd1733bde8c31c7d8ab90366e26cc9a06707dcfa60bfe139a112db827778ac348fdfe26892fed61db7e9849a464e3aad561797b6c778e0688bbbeaf3349727b4670a2d0a08f317b0dc9c4b12ea85c0309d57e754d0c7bd5c83985fb82f776c968189908a8ca83b5944767c2efc3c5f898436de54fe8bb17224012a437896d9fa106a749d12aff657266276129ec5ac12fc7a77eb06296d2a2a876d931e479d3ea201cbb4b1b20bd81471eaa33786c624013e1f07577c2171f38f0511c6924078a40c2d55ce392dd2ab0885e29f4c06907a1597c181b933853838970edad7777ed394c491cde27478eafa5b7a36520aa0779261f94b957e83ce058298dcfa07b08ecc425caeb6c599a11103d7631e77daa0d9d3fc6f42703d57f2c624ecddd56b9a27b848de7dd28f8ed656f1e4decc95a8908217e2f2453ae50b5fc1d9352d735ce5bc2b538eaae25501d449d090df793151811443c64f28d19eeaaac4081e10edca4c4148e723ade8f7e7b988b732ba08b3ce4c8a0d655bac4ff66048148135decd7727a49ac59d82ad470b5479c55d3d8399b790ff033d3ef99d770e1eacecdc140480aeca1e2167553cbbdef2090c7592b40681b733b0a0d127beefd49bcbe8904c975a5ab8b1afe56d7ed7667b5cf92f537ad6972b876843364817c20400524097ac9b405e4b35bbba0d12355a0b54bd763b4491b2acd4e8e4fcaaf8fcfd398499d4c4e81ffa93ca07a5ff51a1540f178f43a931e07e1ad56ab5ce57a2f7dc3ccca114dc9ba8a6934e95f4efe9f3f76947909b280ea5fd795bbbc0feb3ad2b704e305cd9d8f37d178961f77355eedc9d7f77c58e1db2f7797eb8682255939293c3ef7dacd2eab46c4cbbdf929aac301a13f59831a88fab173803399d96dc216abb9f079e79bbfab667ca590266891c8a7ea4bc1724573e5c5a67e9f1341b5bffaa538e240f78da7733237999ac86141b2ac0324f17609b71c885630c90befc3b027a5f01e33979165ce2a00968c414838446c2aba76e1d7fe3707c742f68af21d30e23b637accc848f6c8df820a27bb4e94e5090ac6e008fde7cf3fdd5931fa891335ec8d01b5d6f77db57a87dc35d6701adf7ae0bf82dda6511c83ab4d7d3460b221eeb3d6c4aa537924db5559b1c6739040534fc330f5144c78bf99f5f4faa715e85aebac043e2529197a82ca40f65a8149a9447a9e58c61618600b0c5ab221420c0cee114a133a648dbc2eceb2894ffc329376d1eb3ce7039cf30ff6a53038b23c26c38739fdebc7b919956ca2e468d577dea6621a8d66b78075ad26a6e6d8e20c9b694698540d516ea2bd108625e5fd038b5f1e19c5d5993b82bfe16897c375322dbbca81c81cef6ad900f0ffe5ed02714c208a12f5234d78e32ee07af155ad1e1077a0d8938f426d8f326c751f6ee66c8f707e8493cbfc76f9ddf1ea329e094315a91ba9385e16c890823db0f0231c7f939a042665009d5edd8e48102c515341fa6eea33cc00fb5d82380d735b29f2eec3f61428f7b186d43fcee46b2037ad1aa6974d729848cf1a80dc8ddb0580c9c876def06d8f7642cf45263a655ee77f047fcd76171546319622bf71283f3bf0b519e123a85765779c8bb201e99981ed184e642f63aa61f9cc206bf45fa6e514bfc637671d9cdfba2891bb112a3cff438a6372ee0dd3e7d9f352ce52f8b367b7799e1f963bfe50638f0c74b94873fcd3d66fc1e342a8bd36fb8b88f33eefabb78eca4dc9c89e2c57aaa010f2140dc5ea7c86cebe2f8bf42a167d1d546cc80bfa9258c35af6efb1a090c293a4cf588e4bdf5c090ee7fe38fd7b5551e71e5ce2b0b5a50bab95bc4c257edfc94d37579816b4a2249ba05c991bb2ea02d047e480fc8a8ba71f48f344c6d20d140a64ac20184e45b4eea14d0953370c237ef0a47a7a2f22997715dd3ee8ea52f24ffe12674d571b3bf968454ca051701e411499bc43bb55bbd033f9b81d4baa6c49bdd49614efd20d58175af868ca16a9deaf65216abbdc3beed5f30b209e786a5b4c006f3bd27d93e9d78b51a1a2fb7f5160a0bc1b7df70952ea1573888ddde3d9dd5314b0d0a899a733eb48d5e6c7274667e362e4da6b37c480aa4d0d8730e66483fb1453a3aefad69942ac7f09d3c571b6275590938c541336a121bdd20722550236a9a5e4a37c7de628fceffbc260b1e9b6417c4295907937b13609b8585ebb8f076073abdcf19104ed80ffafe1b09997f115d987a552be5689c70fe125ca702d2ae4d807d5690bc2e90b72cabb0b61ad203b34c68df21c16b92bf8def5680b204ce327214c32e4363d5600f96162a6819dda472acc6441858f396385a16fa5ee52cc0f9ffef3d53c49d535aa37db2cd4b573ff81d74006677969ec1ad891082b5d18ca5b0b9f975574ccffaca72b805c9f7fdd76bfe3dd384dc953255a5b50b7731a137fb9aad42e77d3da1eff5a7b9eda5814993cf2d289bb25ae1680ffcdf419e073d38b4701021adb2019359bb70ff4cca930be7bb979a0678f20665d14803d8753c8ce54cae92feb026486ba747a861daa449863bd38cb4d5831aa6db1e7f404b0c3587aac8765aeecec686066ee7d11321574f04d3f3da571e71222ce07277eca7ff97607", "5e24f34a8d53b17bd0c2aee5369e3276dbd7e7c2ea0990f1300fbbb00831b76655aab1e2fd625ecd", "c1d796f1e651a1ee825855d80206baff6818cc8c247ee6ce62b7531e6e9ac32f", "240cb25aaae4d085bbb747a5", "319e968ad291ea5d4a057c38f7afa4ddb9c9565962fa1a7b231e397a268ad8e0c5030a2df09dc4f99402ddf2e0d06e753bf55e1b318b3e5ff0108de2328d3b8d53e23e08bf7d84d59fededd60d47bbb52736b0491f82c616eb5f779c496abd6499555035e4513c8613e7204e6bff8d06dfecd9ce38c6b83efd8d0e41f84f7cfc9ae07113237987a4b2eaa87f7e0a310155e282e57858244e9071712fa026cb781e5a4bfe6fa1bc480e534096394459a3d1354e2d9a54aac6926a60b388410fd0b53f7a3a9116292f37406369c22ea674418c4deeead171e00f74f5cabae5d24a0686a4bcd8ba99aea613a23edd0a019a319daa3779c212fbdca9d772fc3fe612cf178c2aca2aeaf6bce2433494027a474eff699bba95fc7dcf79ca1d77b1e097439a9050a5cc78e0b78bf2e7f50f959ea2986a59be3880519cd84d0a673acb0432feb1945c603e70748445c74600ccfec60efcf9e4d02a7df5f967de4b473f63b0b0499ff4ba350ec1182f3a0ac17ef9ae28945fc9bc714c49909a7c1e2f311aa6ad7652e22e1f48bb51cf53814a2125152813752d86c7f9468a991d0ac84b1a2f3969b8081c228b7f5760718036e26a10e211ff04ea323acdaaddf9b06a08c92ed663d0fdf13fa601cda45c416c2d3803dd9b5ca29cba57e59cf4ad93176c65c64507b1995d638541c90b381ff758833a2ad67b0de44c280fdfd82b3c6d4353ae30b33768863cd3169a2032f26e37ddd57e7da1673cfc7375bf6e6792495a2b434155d684f2a6f2b919f944469d47be5aa7da74eed69d871e6f65c3ae08904a9ad042ba39905188f0b9158fd14094bd6a408fba6ef57566d69eccda86bb54cd3ca7381f51bffeaf8bcc1ae8df91d22c359888e21b70f640d6f3726a34e6100ee269124747f0ca05110f63deee07e3628bd6aacf926036ccec02c0b6bd7259db52ea8b7a686b36ba1d0296c85e43e25d72ce46c66a1e646301dafd2f4c502281e6f949011cea69459c026c65bd130d6ef06be17b23a9c9a84746e39d017b144135025ac527c1e653f233770cd68e9f232c3b623ceda836843b3e9ea313cc6a57d28ce71ccfb7265ce73b06bce1447220645e6f66caeb06b55129b97c8dd8db54c94d771504d24cedc86a8ec706a9f7dcbbcd7fc7cf38005b2913b1cfb77370bd23183ac7b5ca5135a2738cc91d05b2b22640469e3daeb6a7b0f14fc6652563663520f7754aba624a35e5d24529a6ee9f5ef0d019d83c04f5a93a38b68cbce0cecd42a11aae305475806326aebb4f673791f50c9f90894add51a0fd7c02807efd8c1bd21fa717a860e224bc9fa3f40975fd8d558e4844a09f8920256528450d77e546604e2ce2d38efadaf39a0ea3ea12156174aa8a20481e6c1190e448564675f9ca60bcef37cacec5aa218122e7bd25b571ff10f54979d62018b779a2a3d5d7d6cd56ae31efef2c844ba50ff9da88eba7a8e0d9fc5388a805ba4ad35eaa4798e395d2fe112083cce2f11cc850d25ca5c6e60a9996cee4789ca99d519daedb62f4fb1e535b742a35d71d7390117e93821ff18948a78c1fcdcb90a5f1211327d7ee0663ef16ff446e0e22d8cb7b2d3d05469b1c02864f4a87e2d9715f60c9e7be841e308d0a5f6c50161a4a0464aebafb88e0d2df8cefcead93c9623106d5518a9852f320235594be10c45bc0cf06c9daa007100ff97959357f9be8e49c870d0a11c884213e266c35e9131439fb3654fd5f1abd1e778ccb02b8c262753a22653a09272a0c33b6b2683c9045e8f967af756b98dc1797ff605c64ac5bda8252e9ebfe0e4d8d7ca754fcca5e3de3c4b63678da095281d76d60fa12ff4ca818825f346b9c4e426cee16db5818d78a527a901cd088bc2983f9b83430b50683018996996717a1738439680b68e3f61cbdcd0f0e1a6b436af8fa05d3ce2228054e319bad1dc6ac970c75313c552fc1136fabc302fcd1d09ef1b9138d18133a772cbd9cb197ff58c6e898f9e83e4e27206f3b15b6bf2778aaf9fb38e0d50152f8dbf5763816132a04b4b2e9639584b3dc8ea6d95ade024f9497944200ab0aeab206ef099859b9240aaa15f737c1e0fe6d015d04f47261ade4928e3c2ca21d1f5ab4a3f571f2ed92ebeeebf2493e6e39f0063ba931e165384ee1b5081f5f8d26ec24716757037f5158d35effbe67009080ad7b0381292a513f312eb28328cf5ff47a6599e36c14277c3eb5053c5aca530ff5954c21c03fb3fd5fc0facdac36dd819b0495fde421411e0440991da0cc4a20d294446115c0b79045037fbfacfeac574da3bf192fec4bf38c27cef71d03787430223b6069ba6d9273ec8679736a832277c657862ca791b559a5054ee8c7c07618083f75480c8aa01cb086c7317315911802e6cefb15bbe20494b14d97e3a885806db775c216dc15949e3b724f7cbb30bd2c46bd5a2fd6132352c2b21cc2b47891dd9794975f70a6fa7a0791ee761ccf4c263f27f64790826c1aa656c39483e029baef0855935e7e6c133a4035a3699925fbde131ca62948879373346af35bd7fa52b8d6c3338f213bbd9c79977c0d710028d1d386df614c5faf4a1f8fe5506a9af7059370893ff6d07d91383baba67a617b5d829e0e2eb20e541ed5c34be7ef0eaf6c6f6f52d7ca01933a2a4e8de46e422dc95161ba8ad354f6bc7c8e4cf8ab5e08607530147fcd7c9481afc621c5a3230a05e2c4db79db9e1e73f43556a8e8f0dff7ffe420282212f23d4c5f6f8d2febe129b9fe5ba7ddf27f72ae898a4eba270b5d2bb3b6b06e38c546ba80a9b2bc46097d0b47db5ae72485ef2c6419e856c33c2d66a861b9d474699e730eb8a8992e3ea9c1ed74316687d5d9fc611189eba2aa31af5ba8e81179866dc016bda977c59c595e40001c8ab3a4a44cec00ff84c6dbd9ad4be30bcc080e69b9398089d6ea464a70f536ace3b447693301c94850606d0de1299770b5f45e6d28f8ab83e3ffe52178522eb91fdaa9e4a696674ba0f52ee18e960b04415782f018d67479081b1bf9b4c9b90de026cbb66bf7d9d12cddccdd9b2c8ee2f010892571c6f0c0feac9555c71bf61f9cd69553cf7fc2be8d058e0c3430e134adb1ba28985fdc4f0cf71bd3cd09f5f82f303cded0de62f98404477bdd0a846c6c51e3e82ebf72f475afc8e6388aec57206018ba2528ede194345cc1ee95cb2023793f692f708aac3c9e8a682af36b078f5d6c7a3ed07475e9fe73b95d1eee048ab898edfee3fac4beda45f03eeb64b2128f6df9453ed77c6010e13c0270c068f704f49e62fb7410be90ffee47584ca2efc5287dae1f63bcc1819e7548eb9f0d8a3182f9ed00da3817255a2ff735876b75cd21cb25e86aa4b2893f9e5089dfac76194563f9a14335dd37ef06a501c89623caaf6feb4afb792092dfed515ba7518e278c341834a9dd17b50a0fc860b62ec621b69408cb3fbf7d4ab88a3e367fda84c82357376fa9b1161b739361c313b99dcbf4122f3870c8175093298cf432174217398928983ab6cea4759f18e7a21d71fe1b0f3cda05d241e12db0818b8763bd23d958d6e52981ce8d84cd6d82640d2000874a53c0bd14949ec99e48ce6c954ef0d08e6e319de5ebf7e142f25c0f50ff13f6acecde6a270c8d8de05ef4c310ce9e92f40f6f2b77d6e7aa3f056d4a20f7faa7cd0b93d82e3972343a50a26ff462caada10621bc953b73913944246d2a4da25fa52cc6ee1293c436ab9031ee2dc79cce39f139f44d473c236731257c6f65ca4d383e39cf8d33923afea3c80244021d36e0ed43230c44e7d1a1297d35464861f9149d869f26cc51879027169803e43c898d1b4a2a2480197500", }, { "2158abc2472e1b9c061da2c01d0ad9e996fd687cccca331fe8a2baacd12c06f284b1b5cbdfd067e5ed09a60a137ff4a97c5c26482659680ffb22bbcd4ec1bfd272749e52440537320fdd3c225c30ccd98cf221b34b89c247ab7d14f93ed3ccb0486a028c6f3abe7e17fba1742b6d4db85f6e6baaf82df1a3aa059de8d9699821d39bad42d56cc1ec67626092cfad4a2e1cb5d814e2cab78ccf5474a8bd0dc990a877d37de394694af6cadcc57727f393dccba7bf955f4b65b3c00d71cdd701754ed4f231685b7b5e2557239d7e16305be2d81a773765dcea25ea5bf2c15d670f3159409ab5bbf8da121c779132a8ec1480068cb76b68a19152fd83135aeb228b446225f91d1ed4303a4bc16cf3ad8173b30d2a1e75ccafc8c933db231efeae6260d45c7ef230ae2c7b6f986f1c19e2cf260ded9cd99d64a2d03fc5ee3d73509e47ac1c39dcca655839fec75517a9243eb611da8fae3e317e7df66cbb6abd59b16975eb463f509e784e65cd660ef1a4c5027e54b1bc862f397c9cf4e6594d98c2c2830801d3a679220b46881a372cdf3aaa33eb66b91a9f36b6941c0fe1b4d2a437daa50b811f2d8c65b5a69de185d78bb9c2f172dc90a89324c5a2067974aab14f4fbcd06ee95cd49e03717f88480a410afbb4e68b5c79b0211cb69b90604cdfaf08af1ef10cf28f0f630e97ab18d9b5138d9b9ee9154e0b3104a6c164f2a114fa5032eb5c247a6b87880332a0dce7b36982515297a05dc8a4038a09f52b1def7b4fdad8735443fadc462c7c22132f8b9581de2d213bf5c53f7fce34aaeb24263afefead5341a72f88d3acaae6db367c5c14a97d4f9e438e1e11c3c8fde7ee37e5ece5382e8c68b660146046ef96c24caa6bc9fa0a0c88281e4bf01b32df5218cb3750f9c4b8af24cc106abca62d085198d14ba2ded3cafc1fbb17519a696965a1ba5f65720e893f1ef3fbc5200316b9d4615bb23426ae53e1c5a57b2f0ee0d0c83f353b4ebe7a6cb17531d278478b4ca8e6ffdd0cad30ed73d568a2e44972ac88a7e7d665614316d674e84ebc739b645a9a4166477254ba47bc5c2b05ced88e75bf64da21a7f1f71cd946d84de13ca77b7e0dc2f0617d371ed96323a83bb11dfa16f81bbde913d9c259b10f3aeeb6b56cc4775c25f49343cef667763118932c2e8b47ec745ac537b37746ed65fda2d1c11a2de60ec02adcb79152e8a9e614d8715cc4e6b6891d6a0063576560fa3621146308222432ffdbc351c36c37d844a934088fea92ac54920facf870a62e91ba9299dcb6cbdb918e2d54fb642c3f0d60489c4bda489f6c584b64c8f19359ab25f388dbbe636c4d90c048f5ed87024dcf9f98a9e738163f837a07750d61203254a80d120c795f9c3aa791272f9474fe330da81a45be5ac838613d46c25e781606862912ff88af393040605fd4d55d07e2052227c37ceffcdd2d42a08bbab69140dfa4406853799893daf768af546f915a91b81d0da719ebd45b8b5f1641f15621959689e810217bea18e3996c532ac6e4e2e4f289fddd5e5968bd6fa9aec5ca435c532b6c74a7568c8aeff9dd19bfc2fba3b484a191e2faf9a069a24e2e6d928ac0bdf635644cc1ef3bbacc547a8e4f1d42d4bed3b6b8cc56216fa550dc37da9cf4d1d1591d9348594d14adc7a3fde5e5d1a3b9875c85de7df483cdd0baa86dae793e0796d14fef1f649de6079acbec6b6fa5f2cb2bd0481f5316f00dbe5dbc379bc3cd6d13bd8c775a727ef43e6a5fad1051783b22c05a75d64a8394a73fcb430299b015563c8cb0ae0aa4ec750399855411c076d21aeca8656f3d0cae084fb0a1ffc6f73b52a7ea5d4bd6d24e7057a3811719533105fc967439a32241f2d3e3f299da2deb821748cdee1a1c5e71bfdf88d833bade2f505268f375a9e6488cd8e16705cce91d15b60b2fd269a19148296a7be348aa349a12270fbc0d5748e538afeb0598081a4f1349217ceab3c4141d40f765ea2bfffd530fb9606601469fb131a44939be984c07bac8f26d8c068accfdefb729eeb47cfd6ddc646e22031f53a7698c6501d86cbba05e282d64b2f962a1b08b9064078dd1e3f14006f45f599bc8e600cabe6d855fcbae8c3060859202361d929a241f6c0711ac0d050b67a1d44da19e0b0e236adad1f60a327c9c34b2b9c64cdde5b8e4f664f2fc70599d44a63ee2b14d051c27d71231098ecd3d4086038d63e84547dfaa39db1a92785e38b640ea0345062a1c185b25a72862e7ae6574114eba592d6492087e2580dc5d361c473a614d647e66c0a30de806f4976b69a8b92301e68794ee05b96ee116a5fd5edf5eab43dc1103801eec861383f17c2bab9f2d9126c1802b7aee0c909309ee72679ab644abb9c4caa54add283b5954e6f881781e42f849bce6554c7a5e3becc5d5a209805ccd4a0117272a53807e3978ffb19641a9dffd9034490a9284f658599961daf52f24f6464c2099cc9ed3459d84dbde2ebbdbbeef25c882a9beda03573bdd4c6a0143b14d634a1a021d5f9fa23a7ed0f5598ee57e56672814412b6c7c08b8e709fb98575fe2716100d000a20a7e7200d800e556564c7e6a8da9d609b18ff0bb8a8812e96b834a6b534b0d5dc97f5da17f42f8d58e763f1b201625d1a5158c2f9e9e190921637474ae81d278002f197f7211540088931ca8a941794e56067ef4a497fdc6fa713aa9f20c21f23c3a71ae4cc5aed459ca7c020bf55162fbcf56a066546660c5a009b8ad2aaae9651c97b1e145853a10013d1bf68e7df25dd492c328f823ed982da54557502ebc6cc56d4d0bf2881bf3c536ea53b4dcb0886e73b066969dfec343441b9372d7ff38454c4337d45e2b999415ec48f19cd05f0f80c5a61ec369610784f47a5cf3b2a13ff5d8145303ade7189a300936006846812dec9ff15500f8daf47236e724d72619af3a6cb3e854cb8284d5b8843dfe056beaa45c40a4541a98c7507feb27a605d6e07189c8c5554a492a03ce6701d3d2ec782e2c1c8346b54a963435bdda3a93bbac1d837172cebb9cd18903d25cd6bed404eaf18730a6d1c6da0783b5411770ed34f35fa6c11a4292a34565ff1b23d4200ec5a73e6b7905458088fac19f6aafd35e0e791f28bbb2cb0117ca1c3a9e3c4863e487ce5d8c14dd140e9eb4794d87d75b01f683bca84ebdbf19dafab716421bfac9e95755fd346a0cd31e8520a55c7ca652ff63fb4e20ba67fab41e11f7390bc02363162097802c6a9eb18b430d07ea60064d5b546d15bb68cada79c113848136e797577f1783e9b53574f9427be3a28230fdd69d139205dd6c7e9e7f031fb6eab70d69ce905384c5c77d084360aac590a89b2dbb2d339899b13619b455cf9f0cdc08db6c5b5f3223dc3a663ce42bcc8cc6f947f42cdf8dde15a6926b753177513a52be95b1f0b88d2a1ec90e49959b108fe204bbc29199d7382c42ad5dbaff970cbd2dbeade54bd70415e54daa805d396361f525f38efc2bba3fd818f9d7af0594dcc341c20f18c624fe13ce7e7108e1d2fd06c58b03f04642c95e3ba00d4035ea0476ac138f72378d85050bf60dedc90af38e96f67fdc38483a73e847b41d31b894ddcb234f02b0d507bbcb15a8941f9c23b592a291cbeacb3ed213f2f044aa842275a7717757467f121294bba6b357c969e96bfab455c6f328d9e5181d909c3f0543b17d9af7fcac099067b043be79aca8e5a75c3a6d4f6246357a63c516a3ca595447f34b43a055d3070517c67ec36e636aca9ed71a001d4f7b81149124deeb7826dec3697e183d861d544c9c17baff82849d599e9e77ed19f801aa1ce095940674576ff270ac788d00c429187e299a03c6f3a1646a8f7d6290287e70bd1276316ae624da929c67936191abdfba45e2803884e5a3136205a38a841448968a7900709dda033a42969bd3417a8d865d0dbee1f261f4556797dfebab278136a182a63e5ca9789e3f1371808efe06eb0cc5ccfe26c0538d573378035afa39fb7cdf3ad889b277c8c6e84954e74f3ff3140bf13bcb45c822784125d23b5eceb73e", "088fc7ba068f80efd8d4d62813c93c1eba77e9ff400c7781314abc901873ce200295da09245bf8fd2fce254397616151d94b511957c89a881256182ac9e64acb7b25d4a080cc9daf9ac2f231235483fc9fd415f69caf7eaf0597", "78d5f86b071bbf8a185e5e2d54faddd2a9e26983b1e7a74be0f0b979b9f4af31", "d9ce7d249af9496e99c93b36", "ad542824b49fc520f0b7ff8ce2bff8b3d47baacb4a1c95ed56a306483aac551fffba48e8a8f5e4cc536e9266182f6811d070fb9282f5c542cefb4993ccc7044b42cfd6fc71793dc8dd2de23c630f9ceaeddba45efed9d7fca25fcb07d193c000822478b19c2ee9fb31760cfe01475ba8a003db469d1130318a79345a29d054a9f9412dca1edf6d8f1498af5bb6fdbbd3d5f9a244ff176f62742c53779291ef6294df6540d841f4ee8c7c58fc8497ba74d9cf7947add5373427d81ae928305b93dd26cfc65e63b0ed0812ce759511bfbb10aca98f2abdbc9055c4e5ab82637f6a965bb74f592bdf11118b8eb79d50331e76cb4d10c6b4428cd4ec2ef4cb727bdba2b5375f5184d77772d0f9fd3a3c579a4a548b9c2dadc22c805ae959617af49a514b43f47af834313ed2e4d1fcec2c4b9ea87f328fa3d23129a36e6c54bcd08f7e30645de86e98ebb11bcaf99543503eb1e024bc9fd51fe6bd5e6d749033f2452cdf28b3d0f8a304111bdd26dbde641c02fcb15dc21b1a9baac5e86d35b4126ed1cc8a2c3c2a5b94c99fb9b2008daf1a0c090633bf9e31326428c75a50e821b1e72a6504c9d7bcfcaabecd929163d365832e8971f5efebff99ee3f5b95f957e8904d05b410936d8a81c60b4947f8605c58e5b727d491995c76fbe06e556c8ab5cc661a0c09ebc98d61010050f68b31fbe1f9de8f6481b2704204b0164d8433ba4dc1076908c782826e9b555e8d608463581099a466f92bfd6ac9796eacc0ab771a3f11d03806b0f33ec04c69cef6b87d58c11acb5d1374450ce61ba159456b915043c5c17cb03f0ba66d027105bb6fff41e6422f13e2a466f073358bf68149a3b577cfba7ea08b42f83fbc5a2aff17c5ee7dbdac3ff97389f5b8d1f3750e5c9be651209eeb9574127ea81bd7619da16d1cfab85754883543f6474c8c0cc9d5b80e34bf8262d2b4798f9917bcab4b880339397907a5bafe7d149247fd735523df3cbb17ae5e298846ad3bfb7d4f902aa549b7667d3ea945b002e7b209bc83842a7b120d6d27ce80631404371f31d1f61efc5423e1822032a1cbf4fa1a6b6fe79934a202d5add8c6e3595e49be3dd9553a569521c50e9653bc684ef2b73c3526ff7a0843fcac9cc9ecf46e63df5b9328a54c576bd299a366bbdc0f83a9de67b03f1da16244bd6d52e7e4b52c4ed693827735554b05b3a260cd01a41d7c944d0b7b58ae4b0eb052da34bc22b779d7ad46f90f3d4049c097e0adeaf71bbb30ed24b32ff5c7a65177db77492c2571e9cd99f15e613797e319ea7377038d53b28a4cd66a697e5e8f84cf16bd0f0430b34826114b4e1d1ebaaf2939dff7f9f4ce7c0861e51701c42d9cc9e871018b447ccaf4e402e3d63be164dcdf6799314a389ada8bf5e51a35148acf627e51481b9b0e4bec09c9e6d59229721b151fa9adf8323001fcf33afbc9a949643172f39b0d10ef57b37973683fdd9b9eb46e63054fd05ffbef889ff8fc8f251b0ab41fb00757ec1964ef373fceb8f6d148a7f7c89944b3cfc240d091601b23046188ba70a7cdf7b6f96eb93dcd3d24d4aebdc4a29a749bfe3cf5f6e1a025b62982ce188e6b57245d829c9fc1dcaaa5309a8b9557b8824a78eceef6e977721de4065b474ae008642b974001a5565ef5fe4250194e8b861cc45a8691c461817f10b646fb526bf0fe7790bb0db29d1356e8c7a197ec78df8310431d632a032b5490c2a458eb8d4327a9679d7e8ef8739797b0e820e2c567ce3562592e862a1dfcecd50bf77fcfcd00518db65ee0effb9eb3655d5d401a4a47808faa596d17b316f828cbbc14a7e018a0593da9320140a752f3824b5fcb66aa4c3cb94366ee8b821b09e7bea2c04ece15e8a7be1f58463b525e8cfcfc3fdd395ec5b0575094313557e632d0a65e3099e3c653111a5fb4f0eb2aa710229fc055a2bfd8a7147cbecc10823f1244fbb6894af1408ff9047d6483ef83573b5421b9798ee387dc38f166b11de6c33e9785e9b3d9d28bc24c37890e4f8f8ff24cca298b44d6fb1c6aad28cc634a67dd427205285521a172c2a4884ac5b038e261e38faf0086a02aa29195713cea335c47d03d67fa0dec7a8cb21db741519f5f0ba0143f14d71e33d82c75d6a19b3f7a42e6c16d762354daa2670ffa55bd400637de9cddf9e7964a03b4c8956f36bf54d89cf16de23e8c52957b52eb4572a11d1398be72bdb129e2c1abb58c65cc291bb7b0d2dc326c6125a441863a6c92de0f47a355222d58bf10af0d297a86a98b4e933a8f844fc7f1bbc8ba77919dfc50c41219e3db309b92ba056349faa758daf360b8ac05e43fc2069cd46e63fec399cd7764b111467fc65407ac06f5f84a3179930f6215ac5ec906146c19e0d3e162e77a2bca3582128284282b251cdcac03ecc204266ac3a9cfe8d8854008baf89c0ea0096a400d6a0d2f7c681c99462cf0105f7a3dde690ece0438fbb820b9c73c6cdf6208c336831101b904526cf8ac331d879d71615d8b1f750ac7f0ec692d97a5e21e17e194a98c10172b5c4bc1049a8743188ae7c4d70384a7e68c1353aab7882bb91aa383821046ed0ebabb4b2dd126ccb935f48646b299095cdb71ecd5cc402e4635a3f7a3c8a6f54f4076ba028dedb402bcc92f5668dec3d91dda7319f58382017e306237e42480ee2c1f5930564cf16fdf37a3434585336b8e4535bba87311cd47722b9da727250560624a5dde48a2090ee44592d2fc06edda634b600fad9f843c6b2eaa0697b42858afee8191dd2a31e5685bd104188e2ccb057dd0a8d4d1205d7c846f5b8ec0f06bff61c7f47ac4da30e1bc80a4e95af79b14a83e9af2e0f195cb92d14f752a5f12ff90a05765be453075d799694848fcddb07859336ec101c8052bdc273d4abc313cfb351b543fa340dcd01bf32fea59881ddb8f33c6023ccea70532814ce4a2d0c66c846347b86c29dfc34f6fa4db298911d4367c59939020a3d078194e6a3a3c5126c24ed182398468e77fd61a5b1271f5cb2a97868876954c3f7179d6a045f4bd770f681cd82216cd2b1ceeb4e724b3fddeb74481e662fbd7f5dd45bed6d4f89d21b8dd9c1009ad2b0b16954e97993ab8f3fdd9d61f8db102a945591b4552f419971a9e46a792dd8392c8d9502767c82d9b4f69e66071eb579859e9ca070cad5fe3b7fcb77b8474926ea991ce7ad201421f8a79c051b762a066027ab2b9595a1c97ad57f3149f5872ed4d8e99195d47bd3c03bbee590a50a99d8048e912aaeed797977b52f0240a6cf2c865b108456881adbfda60cf701454da17bae879cf098df808f34e50bccaada2d3edeb1aa73cfe3c512d814eb33897b6ff9d67d3d682517cc333c3c2552adc99860b1f0d1076390de9f84fcc9e802581f77e14f5254da01831c70cb8581630dadb44209377d90447a1a21cc8a2d6d897db62d8420afbcc6ed85ce42f3281255bd43e0afd3e86b27d3b957104ef54959282b0e1b381a26f16057246704c7888126055af5a1f494540f01897e8781e1a5c0193b7bef4b5588d0e9b9c8de74dcdb63f03f7b15cf48fbb71c7c3bbe9329e3d326988bad7d0cb85537c1e0b3cd88f37a3c7765f548f99e495ddc29daed8c7f15dadf2e5b79def91dbbea277c51a5da250e66c305604bcce4789ca2df9a10614d72824ba8e4f179f35ccae7119fd962cce13b282f0f970ca6c4776374c4bc438f0de98aa04fb3cf23d2c6800a4a666c15bd20c486e88e688ff9e5fce906b4ae96ec7c3388d7567ce6c8bc61f6d2373b93f9ddbb02b384084b3f28f54c9ddda232d3084daa5fac5ca356ac0059f2fd3fde5d6a9516d0954653b699aa986f70733538e19721daa41329abb95058450e602eb5726ad5a8b81aa474650659c6f7f6f53f8a6e635bf35f4b1191e0dbefad3be756c6141c7d55f007f4fd131e5d5eaa120ba31cc32b8d4c69d4fa784fe0af7dc272898789c774e7995cb252eb6c8e8053c9e7adb59c27f675952d161dba78bdfb15859fdfe4fe4a44c01efd394bf51d43c600aa9a527d9c490971e188e28b980e77a9c6ea0a4ef6bd38d11b47f5745ecdb", }, { "9cd1c25b5bdab9b9080db3e5e05dc749e0783087c310777d89307138613bdffe0ca259677c13208420d4690031314a11a97a986d8b0fea143f5b4da0972c9ea3cef80b4b0b2bcf2bff392c306a764113f0d9807be86a9027c6ddc85d096600d85e0b236937f295362bc1679537a8a9278229a36a9433925a105ab719c0b7f11fc31488fa071d3032de97c81540713dc29ae02c2e13be8823183f3cd9f72ef8ba4280b4499ee47c7c7c4492bcb5cf7e4fafaa7ec26906e58146215a3d4f52f792d3abdb718f57ed0b9b7fc7504e45a0fdf01ebf5924a4da6ac635a715879ea75a4983cbd9dab9e47638acc687f16684e184443aa9e81513ae4abbc4d1596b2ca3eef77cc9b0603fe90c0570fe6cf4dff0381a99212fadcf7968934ac1ff7664ed6ee0b61e41f5074dfb774b676c2b57a445f1c5749e95ed062837c727ae2c151c0ccb3a4dc1429bbcb9e62325117aca566b8fca0924b70f4defd7749d0389b90f55f35d1635f8d2efdef514f06fde46db6e11e492c8f4dfb7cb5454cedd0ddd32013a4836321a25110f3a017f18475a86583e192132f8d8fd4c2dcb2a3aa95c3be3a57216bf9727cfd1284eea6fa870c8e689e91982c116ceeee2f8298b55646efad684b96eab883fd3d629437e9a0b6523f47ea5b59474a4766ccd01c13170bb08f47576a0fdb573d4dfb65279c1b79cb535426bcab60f4022dc42e40db29f15a6148b461241bae62070389932f035e7257752ef2d6130503d72344b24d360cae8ec11fa2dcbe04d3b18e66d081b552e93a71dc0094d1046bf4491e318f2ae00debffa0b8ada58c5f23e33fb598829ec2f46ad3894bd7f530210371a02e51ae0a414eb2eee43f3e08126dbdbae04c7de4b7416df32953234a6694ea84e6889f27c74206ab8144a393a2614e92adcc77550dd54827387b619f004c13f6c4a31e8bf525277669db0a0c3c589eda15063f12eb774a13e2aba2f2f7b6e9bc69f8485f1d6fc5773acf83671812412d28704003e78a17da25bacd1d61a6d9cb9f121abc71d023bcafa713b7c954e4e1c524e5bcaefd86c4a843e209eabbd579cde0263fc059ec6ff10017ba54fc9c2a1171d6b06f5d85079167117c12e6e5d0c71c008765fce756fd0f1141fbad6c1d2f32cd8e80429611a9a78dbc8e738d458f9ddce58ab43c77b34db9befb25cc1a588998e8dc2efa75c6883244fbbf9a7b4d6750c81b8d3fdedaf98dc61f49d067c369409f984b155ec347a3bef73e2a44957b0ca0f84c7fc335fd89453759ad0ac2fd9a5b38afa9fbe74daaee7bc52301302fb2286c21fb922f74d756de84519171fbecaa9b869682d431614ff6845126a4034f10253aa244bf89ab8e0dfd1f7fe8fc1a8472a10746d26896c8ece7ef80eb2e910069435518ccf096caeda63ad692455b04e6525bb8bae27197ca5118a57fb9a5d8fcfae1b9eb7874d91eafafa0e4fab5cb4d0173f7e3e58fae369843a641e98f3ee460e8cfe95d98f7fd38a8d2235e9d6050015833e6d7d21d7015c3b1ff42f0d3a3d9a38d373c8524752e06987c9408cca550f08c38c2a9a8d86d5ac7a04bab44254ed15c7b5670e0747788e11b81adb0d29e3d0b50d6a429340ee0d44a8c286fcaf9bc46403d26b4a4af95b021336103c1ae0f1274b33bb8b21c8cfca8a56c639f18a9df45d083fa7019aaa14d1ba50eb9a4112e574cd70969640602096265a87b1f77c0e00bbb501555f1626196611b4a824991cf10ab2874a12a8e0390267eaf9e3f8f99eadfbf40d111a26772cda1f50743c417eeec9c80171a83a730f246cf31c6691c96185d672a0fde9ccd7091c4b455dc93326913497396e0a4992773caeddcd783e534eb0f34b99bf23a2db6ee738381b5fc94ff603be014c507888ff55557793a8c5439b11dc5a347f35a2666eda81cda4d1c3a78fc4f3df3c7bde91d05524791b67142c446f60c3a4022912ddabdf817ca3280b671beaa496c935661e5adf39c1f4650563c5c807c8f21aa59df926199c4e2404690ea8ffd7dd65f637452ff93995fe9c5ac7a322b9bdc756b7ed6f533b9357a4a1ffa379dd096f144e9e0d87330c238ed3c6b08c8478e23b65518ea1e4e64585e5e9fec2f26dd7400ce4c73ff0eacdc3b07e4f34f6316f5b82fefc66e442ecc92bea8c1d58635d644724a3380e71fbbeef4bf3e57c6240ff603d65447f510eaa3c9ac794fd24f844489b7c560c7814fbc307e03f6a213eca5ea40fddf51d8731b74ec5b472bdf8ba59751065ed2461b02c41ef96622e60c0d26f9dc78c24f94372bef7e47cf09ed565ae3a52d39b02ffddf1953f1ff500f1659db9f1c2b23534702c19ec1cb7c18166fcd33997d53874c7cdb4e6c2b4d82751911913434e48b37a61a0971861187e5decb7f5c1ef6988bc1d6f7fd147a623d8bf361b0d7ece88df6e1ff8d037762d232e22e51d8c6ddaa9dc597b23ff9efbbfd416cc53e5543253732a23aba151cecf73b3ecff21c6a9fd1f24211fc21cde9633aae918ff1c6b72468f1de7e0ecb6539fa353c069fcbe8920dfa8e2fb86782e3062462f7eb2a2c441bfac21ab62744b05c70b6fc3c9f8e3a8a0c5a4263ed256a019861ecb28e20ce78e2d93f1a1def669e9652cb35d105bfdd5ff2313d27ab3eb00d1b628b4c20f42efa23390802af96a8f261ded3678ea0b780e1f4a88d23588a4ebb058adbf9a9c62ce2ce2f8264c874c697482e25f8d5a6daca4f57fd97d23c42d7b71ec150d4ee33931db5f7d63abe7d72dc936bb23a367c798e6a01509644284d52f9ae27d7d1bae597b2cbc26139354dcca0fff6d76c6065d661b66ca5eeb9f8d85810a029cb95b17e5173ef8ab92d475a1d3e21799e874ff04dbc962c668ef4be9f94d85b2a99d97c0db8f6b6d63e00e36c325cfab9aceaf7597113bff0086e8fad36eac7c0b443de6d3a8533789616d4c863df7200ba795a3b8d0a2b9568bb32af95fa604a3e3ea778c3dae159e1b612458584564ffda07b8aba9710134242b2d83d23127b51b9e41584c56f667b71bc01060240f3a2bc7e5d438e7095c1236e0e468079a83a5dbdcf132d258e9ed18f94d3c098867d06d3c09544565677b454be34ce567f1c143e2f3153bdc0353d65090dfd8f7af4633b89a781e01f4634dd7b0323ea1f38184e697bfc39a1299eaa278c39a2709cde0a346fea53a61f211112450b318d137fe68f6c102085aedabd2b045fab912da5c58d8019239f3a44b18f4fe30c5352e2e2bf030334a1dde1dcd23178636f1e38ec9e42102d8c54df0b94b207e804eacab3edddf89fabda6c8e1bd4e17ae31a57716c679ee8bc7de4412fec3934c6f3e8b4c1d1447dbba0fbc775dd3258f789ca53f1593cadc710fef6fd282bb41c0468ede5ad5b914e4758b4148b0d0c04c75ff6208ca3e79d92de8abafa4ec70ea7a4e454f0759337ce575c4954584e2bb8444c34e823d27b025d25fc9becfb4391df9882452bca0373164cd76e9af316df3f5bb7532e22557b485217254d5ab72ce349620f03758219b259784d4c9f1c7beac3cf08e624742e768b53b3d60ad0b94442c847b84a516a93d9b7d068c44c43980b4c7e2fb0ac964bf05a11fb2adb4f6d938715dde88061b238321afc7e5e84799b02a94baf3f879f89a98ab474ca12085137d639b837ebe069f6dcd8456141d063eb1c032aa392a44d1d58b1e77aba38a280625ab84e3b123507ea7a692c4acd1756c031fa52d637703ee957a993804c13e296cc20c1de55c9b8c032e50afffc51c02e5c12f48383237cdacd005b09243d9fe05e51cea42b77645e5c6f4e48c10e671d216b90a48f0d8f5c1dda553217f5126646d11a62587eb0a4ee0efdaf0d54bc2eb04cd34f5a529b682ce09a34d5acab2c8db58ed6244f7b024e68a14bcd5d7a7daa4dbcf490485cbd38e6f20e839d2b0142b9d766f9527937bb1a737877edf6122ba306bbfb5379243a6b22bdf85dcf3b079691f0e90b28a4259c1c9d8a02afa5b5a661a0f9dac52435e7d22e3591593d37eb2e10f646b51be2d1a96cd4490289ef642ad93eeffd64d7cf830d60dc4a98c768a9bdbf6ec9923062ff04abf19e8b65b95494a9420971018c7e6268b8fb2021a4ddd103976333fa52389643c711a980664e29a8479aa9c4091c2cc2074ce3ac1ab4afa217d39c6a1", "c22add33457539a957d32dd07ec9110f8cdd2f00ab6ac256b4bc7732f63dd3b867b0ecac262555", "e71f9a3dd457b4064df1d9055889f105af175a2d10dd7b8729da0d0116c2d9fd", "7df9824e774c5f86d83cb5d8", "689683c9e7aa9c48b9fda0cfffea0458ea0c3dedccd21efeb06126f1194780917c9f4f2f44b1daceec3f6b1f75506f4169bdacf12c1f65958784851056fe0b4b42a22aeb043ab35ca73747346ac58c550324c4b849a404c94b8860967b6fc58aff25dad0556f1952c045b91f56ec8eebf6f552c18b2a0641c037e6c6538b289601e1fd5a7bbe7b6e0b224124fec341bf77615183abafb52b3e30082a0abfc2cf224324338c132426011d9f800b382e6b834896ea48a8247f149d92ded7e69c7800096076cd2a729a1fe41c70dafb1f855ffa2ffc27b93e2f5f6827ade7118af60730033675d84de9cde6c260d3d615a945dfe0ed25f33b6cbd2c0e204ee919219d85c7536f4700f06fa61937f8dbbe9bda88db1f4ba8a8d195cd385eec62edd9ce673880800be9aa4430e5c10a5908f6dd349af70f32b32d8db38a7d73821af47b993b622bf168565082d07e88fc48231a440469adeca59263302438ece96d89de11cf8057454d1bfe8e4e36965a4d82618834a0847af39dd8776866d9558a5cff79a1cc9d1e3c22e050677e54ead68b3cf0094daa01330d41bb66708a8bbb8a196fae5c77dc6774629d38905e81d97c5b16d755182f687a8046e55d148419cf9c12139fee50c0533b0f04a805723ce1ea5595fca5b668e58f6b3b396f438308372489b640317cfa3a79392cf6d1afdd8c3359557a83790021a4eb418fa189ad15ba9be0f74182ac76076f102ec171117a3d16ca20b4d200e03e54f1f0ee6308e463a148c0c85aac3ccbe5781cf45b53a313f7c9975a45d1853ed9104a860c08634a8211b87500b5ffa3d8d9d56f22256d485b9b45b24d3873159adb8ae25966cc40f164f342519e88d1ead1e711e1b2bbd4be64c7e83f056f797c2d3a5cf7c5025f92be5637fa7738a1bbba55f761dcd1451ce4b1e85a6628b629a2f7917a86363b01516472c0f8614abe2ad1c9d5501b2a44a68e3eeeb34a64541125bf49138bcd15b7c82dfd40708414b85107d8b982c4f99783a03c707a37787a91a7198063f0e8a2d52dca61755105faaa09c063c7a0849570cba1aa7ddb3600eeba602c7e7c9b90ed00ec731d4d1d8e4bb42f9e9db21616c4aca48dc27b939428834404331288f03c2b5e887103c51748d0257519c3988f6492eb70cabbc2dd8a8a910d737a678d0970ec48bef3b81673bd10b687b37e11d49e7cf90c03c54826ecd833bfd9dbb8174274dd45b139d08371d5d248ee33298193194734c5863adf4bca92bc282bae2f47da5201fc240dd0710a22a8d922faf92c2071a7eede7ee17232d3b6ee5f3ebb1a8b230600b243c860968ab427a5f540912e5e7bfa0271201f288727f2bd5173539d5318e5c1c0a71cba4d9501b91c3bffa7bb61b3713f1751efe94a66e17d2b42da51d13c3df40f4db988dace42a6a1b9d138c4f590b7227990711afbf8f56fa63f2800cc019bbd4a7b3a0983c9b9e5f77562dcad6de96e3b2eb85cd99d28a021a10d6734400a91369236b48ed68528afc68f247d45c79318fc5d634ecb0f3ef8536d8ec2e877adc3308be906c5b96777d0e05970023e5c5dffed12310cc97249e4b95e32451c9acca8394fde699deda57e938bed7167e62e2cb62357f82fbe821ee73b4e09c6e2f512515412c2f27805762a8493e74a3d30bb409e499002a97354381318af28311ce484bdf7c39db53f08f73ca5793945e13fc8c66d503fa95506b37ce134ce2945d75b424ca6367ef4ed47b9cb8ba7de80e773279bf23ac888eb105385ea958b1b49b27c8db6b1e14a5c8ed5d28808a7d0b6bff1a58f24f9c57fd8b8f477a9d1365f89c698b8ba923896181299d474b93e05d3c915b10a69e61910761a6d8644933c593661b0828afeca590ca18e702322d9140d98fcf836c2f7a4f72b59eb529823a52ab05d919c3eee4db2cae1067213c5070450a160fd52fa44bc9bacc5c136701cd7adb1faf484da376477da08f6a4dcaa37af47c7b026c2da9d5fd0b30741357104cb2bc0d3cebd132b5fc7c873ebeceec5492aecab95ab393f35b93b923d2ca071e6bd8522c3ad8598a05e96646504f1620c045aa5734d665acbdda0ef73612be4ca4d95ba069041e042497f7b10445869989ce30f55206a1feb4e64890b7d1f7e9df2e88a352674a52ae4267c06592d425ed1d88101cf94588135892218ac11f3976ab2b47a27f02eb887696c94b13d48b4370eb11222274b5513a0fef905c66d0c1893832ffdb9b333178b65338fd8b81094d8f86f2e4e96a47e72032cd6fd47af87eec295c6e980f595b57f79abeb4654c4039fa03ade732b1e579551898b801ecd6e0fb1c5fd198335834b51673d074a8222640d2a969998f5b878bf897fdcf3426c4e24a7c599e5567643fa79ea5d20e7de581a873ee0181e3632a4e304f9dae09a81f882d4061ec17e588793b160c93a926874d5a8b78727f88de9bc125589a9562db5bb1c01012bbea1b2eeab68877871ce83455db43cc48455effbc71c436aebe362af22c6a319d134f65681c4d0d51f9aa42fb20f48ae3f7065664aeff5d8349624a5d79eb0bef3cbb2a1244ee445f560a6bf7a796b2c950a37dfb85ed5be11e8e305e835c9e077e676aa5ce23edb1f74806278548e3fa35059abc2f032289f9bd76043c8dd1352b6131cf34f66bcd0e7f1d13081f5b08ed0c69136f3b7ad8e05e9fe99a9b73624095f96740c1f40074e5d92ffeccdc0f15502082fdfcfc97a800be511c22b875f2832b2b891cb1aad2a17c7bd0be4427a4549404172f7c14d5e425e14498237c26a7813cd8612d048703cb180f1a6194f688b4644304950b078692faec7a2a5c5bbc482f3a7e8ef2825c4c19032a7a79a2908ca9774c6403e6b15625c485f2dd078902aff769dfee2dca9373704bf63ad981b51f61253910fd48c49ef10e3938f35ca8dd491a8e569baef675df30367b093f1088ebe8f876191dc32055481d074e5e47a4bd728efaea9fee3e83d8556255ffb2fa08194bdc66897d97d1557186d5f873169461494a83368ed8065b9a033fa4c2f07f7c60f945b60479e3c89233d58f674c0c6fa5918150bae0c6de2b65a09ccd490e2ad8571745bc37e70982411af667f3e8e9b9f7f75d863e5fef05c1f0d2acc7c86585a83ee32e0a64a9e67e75b80def5bfeb7cffe6e6822efa7a9cf049689b58336b081c039696e0fd3b2a2a6b0d177c9b3f8fe5cbb1c69ea93c1235b2c5b6934f603127eeafc4ed0728161612acdb2ba894a5ac376c4ef1fa8d49b4722379e5cb39752837395c413dd29a2a88c03849b6fb2221fd85ba6d5a50ba7ee9c09ecc5e6dc66afdaa1b021282cadc68f19529eadab809341187d57cfdfe01d0798ab8a94277b9b868612e575bd98f70de80ebe5f57637c511800373262eb5ac3836b03808ca5d5f732f286a5f18a7b7fb8cd8f60e4debe54731c9c524b84694c5469975443964ed28ccff2f4e8e0cf4c60c1c8a092e986cf12fa90a994e4f26ac89fabe8a0d1e27fdc00f1d3d3fdb73bb76809f93ea113e336cb0a5438147e454e262fbb7d656aa1be1288839bc342b48ba7d0e72c85a2e24be1a97dfb2db85b5d850481e62f3b11a28c6407686e73d550b9f1d0f010602e82af26813d2484a8db2da0814782c8404b2865abfbe3c98a07ffb37eea6de7992cad73a9b81ae96a9acb13ba213eb4111d868cc73b0432d2b6c2d7e0e0ca7ccbdce86d01576e1136871a07c76498eae53fb7ebf2e85fb8561d10dfba740400ef4495ece7eb33ce3bce26344eddd88cf1ed8028ec5fe8e71edda54dbdae08f50f8df6295f6d7ef1163f62262a200456a7777d0565d7f5832fcc7ac144b5c3e0ce3e5c9b7f880a54ed5e80662e96b356ff58f2e372b1dc0d73cb8b96c72caa9e5dd312841a8be23f838bc706d893e1a8a48b2c069874c293c41d00226f73f987aec8686046ac4c0c972c991c38b98cabce30e7255dbf16039b95dc7d103fde630b03441b15bd2c214763fece9d6778d1c6354d2c9478c226175c02cb006006715fffc879a6a2b4111f6234ee330d6c84d453c9ffac08efda1f380110a8ef8c2fe44e2ed644cc3e0146b4d02f76586fbb6d69b827be38b9add444e2bac4d7165007cdbf2ea8c4b967fc1bb70c68b229f19bc3f79cb13ee6265264885f04c09a96583f331ed46de3e5dcaf08313ba6053f3d0c1916a0f", }, { "3ab6cbeebc18df951d371e0f3cce2697fb367476bd9d50ca9e668c77636eeb9d24b68be0ce6a75eca194fbde6221755d57e9d3148623de24896a9becd98789fd3d14de0c7e53f81fe7f3fd491472a66b5b797fe19c5d0525c7a111a0289a9e65ae7c712ccf694cb75c490070bca7db17205af9bdb7fee27f9ff41fc78ebd2d3d399e690908b5c064ffc0d5bb67b0d2880bcb45c2ca2741691b6131aa1e5ee758fc50610406216905e13ec049ee92d1f95e16bc283dfd91595ec2037d20ead51d3a362140578a4538c80581b79852b0f6686c1ea66aafffc872024592ec1aaf2650d167a75bace024b261db4ab48b401cf85ec2620dc12a7fc37012af8ac1d6db923d82eee962129bc4ede578782594708357d29118fd10dc6d228bf7e461d2769e556488b776237b6309f3dc2e884cb2df1f43f71c53d389765f805ac053d05fa835e75fab0adb0f13ceeb425637f43556372d728a00fb005f7c5a20cf2b7f776066d60b70b11a848005c6d63dba0c93f139067b39017c997dd6b94c0138c3619e9a6d0e4b8792cb8d58a2ca12ae5d03e7637f2065fbb9e2d1722fd3aaf234488ca157d829e9a3b642458054f3dd58da41d7fba6d2b488a327b776d1aaab1a364c710e755ab22b9cf7abf1eb8949c5ca20c070f275f8959cb00c6d5ab7879003f89f795351a4ef4850e033d929f9a349b9133b2e0bd1cabbdd381594bfa697b845100b96b5fade05db12de040b814ec49489f39f5abd5b37f570cbb516636d5b7378f12872d02d4de20b52ed8ca0b12029a4c084621bbb578b870ca2ea79fd5df1ef8664bfb3b1a1bf038e4ba33f6ccde42c5146470c9dd293aa747d2372db1561617920142ac1d32e4f1fd18e8b9e72b7efb8fefc56d08f00450d23b7e8381849b1385ddcf9310a4850dbd6db7a4992690190655760f557a5027b5ceab3743365ac9041a5c14bed1126c4eca00d7e0a0e0e6f666f64bd1466387150ece5835192149237d5dd25e703e9d3a4f652ae04601d6acf8228e4e86055394c3abc9dccd02f04a60c298d101260b408b2620c137f77e2019fc6eaff1b234c56dfe922b0192656254fe3356143e969f64b7609cbedebcc8cb2b68bcdd9d723b9c14669da6cbfffbca2351de51e87db6afde435ead0017682b8014f91d9734a9ab9b374257273e114a8fffac786d53183ba666d8a67e30c1fe45bb1bdcefb5787afcbad213f8e36e78d30ae1305df96bf450349ade655cccbb17d887f79e00728abb449ea427fd2d0af80e3b5607a74a57dbe5264131f2fc49cb74415974b3d43ff872d4106ff11b680f56be06fdf85ec9dd850b1f77f759337b9a9ce04e611036d3f45743e562abe4b959eba7424a712fcf7c3f3773886aef22f7cf6168efa83cd3ff70b9521cae1b6689b2b8c423d883a007bb138025f2a31db2147691bcb365ac242efe40cd09a746cc501ae0289e80205993b07f86538d486803da14b74fb0db6ebf1c2bb8c36275137d654c1be56c65891cd50f705247d85621fd0d61ade8c05cf4ec15b84e8adbcbe017d7d5743d5e91025e0154a5d9bac7c6b8297490e9c195c5d74e046219c042219817a5c56636c7c4382c6a01d721d88f4b4d20250eb5eae5f3ef481dbf8a3f47a1d51d080bd4cc33f12645c8481e57835b77a85a2d83301172782f22026e69a43376ac4f5b78734c9eb914e6c76c6a12d4127cf195ad030825322a279093cbc40a680355d086a27f3fb7560713b019e7c286d96833dc60590e9a709f2e3c632894668e74ed20e42cd83a23ebea3dc3bcc49d14f8697541780fb2072dee6a5672d0d4e7bdf5cbdacdf5fea9e03c6d9cf0faa1e954172acc26dcd344bb3d9b2e0e6015cc55d19713d795bdb7c21b44b305e69c69fdb7261483f9693f36f45d356462f1ba4498de1c2e8bc3e0a70893acef2006dcd73cf15b265a8a5d4ed792a34a846d8f1d3b9b3bb75f1c5e57a00b36c00203973ef4e2654f6cb29e4445318ed99f0de6ca992281e83ed03feedb66aeed6a461c6f2871ae95343cd9797e58430d5639d7ef5c59c78b29f76a055e18e2b85eff177770c60ca4f2d61e612e617e749b4653e7901b62ba02dcbf50e59219349120ac01e6b8a6e98eb54abd16b921a1ff85898f90fc49a3c8f8f4ae9b0dd32c3e7f2e1527c4feb67a496390f28532f20acc71abb8bb4f71b434104f41e36b705289858a4e8430b8cd9449b0198ca2244923cff1df0f63833373c275572de5a9a77b23e5ff54aebce8e86d02651f26ae32e69001e5f3951967579ebe8574682cef8c12dee0b18bc999f8cc0f07e2ad3ac94d3caf30c1c8a8295756aecbbecbbb4ade8a2b8015e52a0eb1290693c6316d036e0c443fc4ec591c32f7e7f1b3933c921d5812233d3c21ee5528822b59ef2ec7eb62f7b04f40cc8238a473ec37a07e54f8907825ccaa1421c2964d2c756be450dedc011e1cdd9045720421b9a4a00e9d3076c2fd10d71ee36d5c0fd2c7e42396b034a4cd0245027449242dfdc42c8af4a34df1b4150097726c9745247b78bb2bad5fe8af94eb13ee1f41dbd36e56d801a4c9c5b9ca5d3c26f4714b6fe9f69b87567426eb6f4ac97e8c9541eafc19fc90d3b24aae0f76c4f3f81063d206ff695d638048c2cb023147a78332939d2f2470d16f1ed0e5d3d4dde438affb2809488b99815e54938fac3b02deceaffde310cf422f9027f364f5e79da5d2b5af1b4138ac9f9d301f396b220829c1f60cd2b54ef24576e5ba6ccd4802900db1bb4eea57de7787eda0e30fa90cc19f099444488699bf7c442c398c2ed989d084c8cadc97325484e337848c34562b3dea6f7670f935ed3d5216c970e04351651c1c31a34e862821bdbcbde202d91fed38965e31cc3b6f1e52288f327bd0a787ecd92b3b6f535d1d000b0f02d41ee01ca54e4e6179ad7fcbd60f0e41dfa5c9cc7ee4f7de3844fb385ffa3b24092b30be697f1fd32c9faef29ead346e42fe2ab1d312901b678b43b7758edb7eaa1c2d038b4cd6a7dc759a6b12cec955bcf4179006a7ab6e22ef15986df107080d340b8870e2304d57caa87a9961c04655d7d66c7f71ca9260e02aced131d6de65d256d6b487141c51bc86eb1e4721742f07d09e799b30da7b5ba94c8d701ae34271ba06f8ce134a7a9a2598d1570cf05edd9ec868cfa2e41b4c20a8bc4b8bfebd45f5a60408f08e931617746d1464bbe1f3844ab3272ede635f771f9af30e483903ee4d0cdecbaff4d31451e7791dc97c92042fb932fe1c82652c1d682a55912e33de3b1299db076cef594458670dc4f911f4a244e2bec757dad4b0052a41235e2f5e60b929682608c16a61287826218a1ac3cf0d8286555d5b0552754685c365d4342f0d9c45065daf6786179da791a86b50a5edd6fb4b21f09d9747136aacf79ecbf52b00fb88b0630ec7f0a6699901ba4eff913a3ab33ac85a71ebb51ed343eac86eebb3e79c16e664078ccda09e77ef8e0919b8cc447116b65ccbd5200fbfe86e9bac5637b33c9bcac9596b57c14ad5da548e96a8ffad5f5c69247c68d464c770011da7b45a337f138cda6b4e15311879bfaf12af4c61fba596780e6adcd5dadde372823da6014122dbac70f0dd896a8d387d3c74df282a659028d06cfeab3ae22dcd1fc3ce60f69a0d678aeae0e5681952949e31ccb8975cd167c9d012f4b230b1c1f47022eb1a3042951b338a734cdd17db0ed483a621650deb3510efe74191a94611dc212c0c73b117a73b8ae41892cf176742bd98a7cb73dcdc53b42df56d640739852335f8d44d901fc884286b433fc285fd5b3db8df0a8522cea3182c071f559c328b8516c9252681a94eecec7ebf626c0a9014d9aaaa0c694d14855433dae06656657d1f8a939123d28e00513d72bd3802d211ad7c1e06b9228c0d5656edccad5339bcdddd5e01afdc01f10974be3187804324fc513ba583b7b2da1e9096bbe3d078c1adc6c34d92c54e9c49fccdc17d10e66962120ee5d9b1cfe852569436270cf7c4c3bb12568050e2ca4db08bbac16214238413195dd4d936272fca5d56d7551b9b002df1807ed44abc84c66746387b79bc9e830a635c308a7bfad7c2c22cee6d3d0c5ebd8b230837b7ceaefdf71a67a3a8eaae0c36de86b2d96e759b8b53f8b8604775eb7a7e13223cb21033dc87d775628581a954085c2d66c1c8f225b1aa86091061738e7495cb36a5ff032dc678904bfa39a00285cd6947865b6d4805e3411644b4a4c94a6fffe05ef31e156bae6165d801685dcec195552d029d22e5de393a82ddf3cd3de3ad8cd6bba2325a03982204f07fc3c21518ef17a601fd743b27f7191bb446ff61d3c61d7608777990997e911932532e5b3235f13423756f5b6c786720cf6682932c90092", "50772c5a0e156ba13a9d86edc0e600021d56f7d31e7e452a74ad53a6775339c7ca6521d87a8c79b42900a1e9e6a1ec03f7e3d615611c3fd5c9927c40e5b508af1a298794b60148df01e9c9e78ab5ea8198c097fadcd6cfa6694be64e00eefe1a1885aece86f6ad87df766e692b58ebc41982bef5", "93a2561a9904a1787a10e2a668cd6a814f2877a7b512698e94796805875c8d1a", "588d9bc1d98210d9700ef488", "165d8c9eabcd5e93e6eff7be122c8c242e1a7f284790c93324f924efabcec4a4ce48262011b7360c2833143d645ff295453853c92f0c48c6dfc2af7ec58d9bec0d13239c7e5593cdb39d49376c6341263df80c0ed2ed79fe9899d0c07de93f6ea95a5dfd307e49bdb5672b158a4df623ee86d54cd1a0fa9a60ce39d1f5f4b6b0ce9daf2a61a907cff3bdd3f29156ac439638e0910d728843ae17ea7368814ad7734732e7c023d4954e1cd5fd19fc9b76e9bb84b61dd4371478917757b14b366b4bfab4eab0d9de746088ad43d8742e2b9e58faff15c2eff084df5f4316111d5dd7d23cc0b1ee1000253f26cd260aa636f03f64a8342e531ca1515b3beecc3ee07a29184988325322d5c09754c278231f92c0d980adc919d4fccf4a1da1d37f1ddb58ca997d6d700946199fa007c43853b6caf5f8049233584087fb23c3952414ac487e452f0c3898486d04e5b008b843122501f9c8a294da9159a04119ad5c8e9f5c211411e34559d3a7bcf2ac10e0174f94f3f2968c80ebdf4498de172884dbdad0acc3a887f9bfe896a6004d54cc424567d53f1198ba33c56aa460edc6af0e437b34322c1144854bafb2434f00703c1992dbad0ceaa0616aec60a380676ca11558cece57a936959d6c2ffe0647eeffd37524fbafa9691f31499701b202d9dc9980e79ea517089eced779aa45b522c9ad193e63ea8b64e8a942f630d44370f23b7e9acfedac51dd9f139f8806b09a8fbbabc76fec3c3721fad5087a6d41f93973af8d787d8bc74a3122d99ea14e2f30a3c90be4b695c8b269784eefafa52d6a79e785eb47a23d72f037ca572b7029d2f37baabce57658119fb02c5b659e3aadfe0052f1cc3c0afc6fe4624533d9700388713945c20c1d175da53738fc73f48fe57fef8305e796b474b6f8d3fc5040042373a13384237d95bb045ce0c20934a964a8372acedfd6e559aa84180a86311a3996cc17bf7f73e5d85d4db2529989e5836edad490aaa5f56d17326825aa20608fd209903335de4b36b79f68b6a52194f6ea8ce42570533df650e65b50c367f69b9f08c32b3ce3e75318106b8b2c6b6d09369c781fbf2aaa35053af215b621f833814ec4778ac683de0dc22c418b077a917a6e405ccbde9f72ed523aa696be1a6f247b096b9235217bcf19b88d43178cce5a7d82335fccb4c079e00280bfd272b9f16ffefa7fea38d09dfb2e4874553b135052595812aed3fa15096abf1eebf9abd598289e0d156974de4c2654c60825d42b662ca7439816d9d3a0255f40a4965504f643f029da535d4b109e8658ec570e99859382ca0ede0b0495d508c63c7f1eff3f648c60e9b773590cc663a751178ba7603a11985ff519056661b9460c1aabc30e83bb0073a927682a06d1b8050c345f7920c1a37546d79587fae2a92c803a986248f90547f0b6c0ad0552d8260d2a0dc3cc76d092ab76b8c12f05dcf141167a6ea300bc23227933396ef6fe9d51a1ba5a754485950f06cfa6964db2d0fd1d4393cc36f0592fca25ac1a6aacda2a32f548ed20287e3d291661848a62d41504e4fcb1cd1785617fa5786712b3005f1a1041733df6cf838ea3ea0b93685889bc6b2857d80a9bc0e7a66f7fb3d805770402f049889311fc112dccc72a25bd127777fd87bf5ab56d39bfe6be2b45a8301c2f324dcc50b27540200d522c24941701f7293b8877ac84cf35638507c7d912a3a94e4384b68c507412df65d0c4ca8ec2da704bd4483eb2e0d13b68c0c2b68c106a55b9710ad0a1436d655a3cf3c419d5e6f027ddf5dcfc896a5b316a7dae9290a7bf81aed539a647c8c98e24e7ed6a4f7f00a11134ca715e5826625c250500f8f16b40de048b095b5dd08268407f58a91c86c36ca5a2bf4f8fc682adf1bf601da24414c74956e1a8fd2888b5260e980c32f6678a4dc4ff73220c22593d23144b84c2ff56920342248876d15ea54fc100c09a81b802dd15f030bda9aa08727ea49e34f0ca8693e0a06d0af06ea7ceddbf0584adfdebeb20510bbac683451d9f84cf0f4e85c34d979e550e07e7f414d6f1011cb3dc28d0df6d4aac113f2d5b04e4486ee2cdcd4157dafcbbd55e8330a7176d1b231d9f47a63da9ee30fec6cc2c5aba3a8c6154f79997af89d972743255355647235ee939f4f305ec655271e0cd562ff6f401b86dd5826c769298445108ad0d9e13c504551f74c507436911331db60ef0ea99dc259b13cfcb0596fa9b3c95cd7fc3b1611e3b012b6719afbcee7548939676dffc372276aecd08e6a14251407cf995266545427d49ae5ab245cd5d534c52542fc71b3973f0b766f3d234c8baaec8b74eaa8ba90abe160b4504769d02e08d7af4e7ecc167780c619cefa58865169b674b2b1e10d82f6560ba0be41a781f4afa46bd722566d941a8e6f87e4a5c03d89685a22a3470354f2922e2915f9d46288a5e8896ed13617dce694a595e379f25fe621dde8ba73d865976950954e5bd07db147a0fb74f87cb06aba49b073942b82fab33a878651df73df2721ef800b658bdc6c359d396f684598e93f38e79639b8736b02dfcc124fb9fc199c35f2fa1d0dc39939c57286e58a7deed7b6c76e02b99a14d9bbf11f65d8eb7fa096fe4baf0f78cb34736499a0ca550f10d7edc8909dc34b039e3abdf1aa67a51d37a2eaf4c07022897d4d8355d3325bcf392d91d02d462488ead90b366e9645b956c3802e4249d34b5b2b2484a1dec15a9477821df6bef5e1626ec5ee9832fc3bd0b63a3c4100d32fac3e9085f0b5ba43123f54beaa7ccbe6ba68231649f35a28acfcbbf97dea2d6cfd96025032b3950ec8437108d0f07baf1bc89e3afbc2cdbb5031d3cd9e20b19018adda466382059229e4c8c54b455eda4280bde43b36afa96e146e408c7104523d5f565d22ef86d4c7cbf9c6e0d0b30e37b37feb9332939c642eacfe19d0dae1259d3267635051ea5f9b518dd74786e45fb8bdf72cbe3753bd50bea2a961b49cc0e2d589e77fd25ebd962463fc728b1d288c38a79a182b124d345872afbcfe792d259e7e5334311244edc75d05f9a12eadb61fd3ff79fe8c097eb01a4ac1f0c339d3be74be3d96b0b6a15e8868d043a0f2007ee8aa51756d78b7a78ad90fd9a26afbcb51fdc20ed7a3947f715c833e363bb87504d8efc9f8b93a993e2e26430f79f3cce203b09093c9b456b1967212eb0db4f7688d4dccd4a523866f75c9d9e7ce07825ae34399c5607a60b771866a647b6d5e1e20795ca906e451f367d8c40ffe79a2cecfe7aa47a402f8d49be9084661c96ebb11f1b48e7e8abd2978ee626f962e98f99db4eb3c6a52aa2bb2e62194120ce1e773b9db784e8c9b5adcfb70e3bd5717293eebf014e9872c5c1bdf3fb296cb88eab5e97a5ac320092033b49f37d840dac23021c19ab2a89190f3c8dde927f6e6b41874bf71ba7747a616682bd5b3f17a1dad40f4993a1b186ce4f44afb4e36af7715450bac62cb1527eb8db1d87bbc4d9c99415d16660e48efd911e02f5777a77e72733af3c3f5315dd0c785d5212b79c46c3bccd74582c57cfac0d50fc0c85370476913f9d8e8e10d0f6602f2271994972de49ab1a91728713c3cfcedb0e61c270b5fb331a980965bcfe10b41251a0f7915d5943f49fb139626f1c424524f2fba3a407e77dd7513669894fd09fff4185fbb997b4e4677f6ea0b52892f013f1691bdb38eee9307a565e396bab484d91cea9268f49aed29e319b0add900b6a75f7461db5486aaf5366f98df05674361308931de753c70777de73337a996f6d4b0e06d63a69849ba7533bb0e446f062edbd6250e61a49f4120f84efc1cf74c1bd30cc61a2d719fa76991dab119fc814a7c56f48bd584c7935679c53bb0ac78905b5d961fcd89a4b567d17a5182651cb07146aa9a94972ce613e8ff9c878a8433c0244052f09980a52d800e97ba65e8ac186862def58c72b9feec91266e26aa5075b3337c7bb8716b3acafe666ffe2df32b78f9995661d3ba28f8a8780436aae1da2a3e6a0a16dc562b8d5df6f68391aab73a10508e0f55208f974a0505f0fc0d8a55049a7b631fc94fab91459ae1f199527362695b41972e50faee34c5cca9e35e8682099f5e9652f88cfe9fa990ff2154c89c1c2a4ed6bb8a889fecfdf048ee0aae7798c55d6cdfd062cbca97ca289578c832d658ceaf26faba54c9c3ee9eb5bac80698c1441b9cba287f749a5e30d5cc715a01c89353ceab0974ae77fecc1d2dfb31a5101783cbc002c73cd155dfd14685c2f9acc170dc437c649b6b4720b676848a7f9b56cc4787eabe72f6e3f2aed776f9bb1432fba93a63bfa44fbcfcb6eaa9ef4b79b32bdbd68cddbb9897cf5a02c6f99fc765790092edf0d5bca7c55cf232a03fbb6f3eae09b12e09a9b49a538e0589394700d16ebd3", }, { "3497e8d61062e6f2084ebf72d00e9a47b550591edeee9746f31ea28039a1646d384c4348af293ab778f92a4807c48fbd14e8dbf3d67339c991dc4aca7dae38b5fb7bfeaaa538611d328b653950f4f664dcd257b345917cd66dc6a1ea75d99f70549d1af9d67b1608077b41576f38bb4c0a13ff4fa47b251142c6fbb79f9a27f43841ed0ebc0416c37f571aef8fd63b99e93ae88db50e9ef7d499ae7433d5686b165579d3598f96d9e7b1c876870310703df8fdf2069beadb34984f676eb7d3840c4c5766dcee3fc39f0739260a499647429339482e232362bc72c92a299cae36e9069cc5f4db8893e2c1b9ec0b4f334de26c951090b9724c2b3b7655d8248bc12a27861e020eb1e4cf6ad0dab903279b6fbdabff761d4ba159c1f631e681f210a8782faa86e08e554b5e30046157a0d1144bd08a691c2cc2dd22f3c3a4e5d44c5d03f7e3e385382ee4683345c0d316d41ee75f87038b49e0ad3ca45121789e7e7b95615e1a9a8dfe02c044c2935a97b141f639448182252ebfc980e0411e5fbcb3c01acd5aa7cc5d67101ffa6ab6acacace5f02d67155c26dedc071ffa66dbad26f67a819d46de0556fdffc1b4ab6d60905d8ef873ea1e51c62571c08b4c6db242e733e02e11e5840ee445c290b2232010b118839b37d4615c4521e8928e9ad475cdb4a3de9928ec7e6daf0e20d22e308347b31e7e877fdacda0c25f2e5c33a329e84707816ff4ffdca30dfc753c2cf883df16016795db34359e9363fac60624ae4d2b30bc1f2f99c23d953779c22ffca145fd08dad83c0f76cf727196799544c6c07483e0a41ca2e1b1da5a730956154f531d292b5a39a229ab13bf24a804eb68786e481c8aebfd3bc557afceadc41d00e1472c3b80ce652be1245089283bf1a1a93abd3325bb6eea121db8c0e1d6c0c31decfe9dba63c89b881824b0531651fc500f2f75ca9e5fdcbb179c9ded5d600a495ea704c2709f4a88c4fadcda4cd82a5b089f25a6fe0161159efe03fb5e0d44bdb5487f25e8c9adacc389860f62b06a6a4f8f104d9171622f70652ace736e8b28b70a4d9fd3fa4b9784d1a6e6811150d0a0601d31d17f6041e58a1058f99b80b0a6cd4f79c79a104b6bb731ecc881bc68e1d99ab358faf43d8504957ea0152e46e27dbfaa17d0f58287276e4fa82ab78a03513d5b4c3199d1362e4fd6447d1c26fadbd011abc69332ed0181952b391f2e8a5c89d68e22a7c451f69a9573b6bb6d918c7e3d52116f3f12f1d43d2af46bb450f58bde1732a268293cfd9cf2b90a844588c1979a30d6ac21aaea4b9e5500ef4a8bcd62bd70cae6acc8839f818d23c615e45daf14335c36dd46817c9b816be60c3848caa812b055da33f45bc01721d6fb7e850fb1e1458f27c70bc34876a955aef11f5703cfacde03a039c3b75b99b2d91fc18b00071a28ce25eb169b946b49858aa0885a4c665deca020a3fbba55d4d9175fd91e7901ec9eec0239806e8305f8238e5270f4af5c94d0008f8a5564636cc33c8a3d3e76db2a7915abe798b0dfbb3e322b33e188c7b188573bddbb9e4a7edbd4bb194b9743c4aceeab449f8affddbc2b109eb3d84f3b2f8b18ea2962680437241d82bb6146674ff1abee7baacc38d5dcd688b425c3e3b0dccdda3e36de755afcf7155d3d7cac2e279baad167e2a743b82ff8ddf3db8ecfa9680ddf468339427a4e9fb8ca4ce6f1e790c24e7269912a9989088c65965b0efe68ed44eb26876674261e3e72042f5995f1a7075b3932f4c23a8027d0db35ce4322122f489995bcc0b3fa32b7298c4c1b3354766c866a2fc0ea5690c58c5e08ae7037f70accb3ca7faefc37d78883f2bcd768285dd2571dbcaead813a0b8ae87cc1df868e93500d414c4418d5c80b919f73b9fd46111a02bfc884f9d30ee14fcfc1d55d54256b9572afad4777b8d8172c911472a22e7461f6f85aca063c19d6fdef3351149ee6864e93cdc54ca5dc7837f0ead91f5e3b155795df5dd1f933cee8671ffc05058353995019e5f6f55d2de6470605a5411afcd7fa5aa8f38d77dbf496d7fa9c5a4d35ab661aa15c77ce42bed44763166160ed5bba954e470c293ca301363f5b837406ea8ea746057588c34acf266030864d8c40e2da88ef04c49205fad1607d456767d30eadd884359bce04c12e35487bc1885d9b104c9fd4dea4ceaf054cf46cb3c77a619ffe963acc9bfcfad0447591ccd32cdd1fccb1fe7080ad75cca2e17f695ce0095a774327123f21e2839773506a9f2d896bde87dc5e35512ad733aa408f8a49e9018d1013cc32f550c968a03308cdbc73ab444f0a79a13450d4de906369da4c6a675d7e338f738358dc238be4f047579c8ba7a60448da541cb9e57f22bfcb8c26280a59b77edd0f5a009a3ef1e2958d6d3c3372840dc6a0c6ab1fe86aeb7590137feacbfdc7da57c77595b8572b45c4677836ec86fd8c4ca8ac351397aaa3aa298d752754507e1cc514d41c3f1ae0a692179218141f65bccb9acf6244730c6d00829455d21371972745b3665f930cf2aa9f0abebe6f7b89094aeb4dbdf7bbbe794f134b6284e289c995ef2929fc1bd39b259259950de29e57cdec15c4a7d33ef6e689596a6ce23301d25c2ace77fe699d90c2329da4d0f471bc093563dc735ac2fdb32c6995606a67bc953534939ed1236003c004d3b47590beabf39a1e4d5d1b00898496e9effda68433da17d1ab3a32aefa3681aeac116c5705077552649153ed15e9d704e67d8819579feb02d91db0d3533182ff43ee5648f5cc9a595ded4772d61e77bd9bffd6f29fc1f478dea44c32d5ce3118bc8860b254fb0bb1e85223bf709a7c0b9a52fd3914f1b1f295fd246bcb568388dee43a32df45e3c798068608a102143b5511746903255b98238003eed68776b46bb0e64af6c9118ecf9896709aaaabefbc1f58bf45b45768345b560ae2cdbe4d7da497736da8013c4098addb4258cafe7823bdbdd715250b707b155248d39fc6773639e4de3b201fd3cdfa1526c4149ee7d15bbee680c956fbdea844b1470a287d430c5c7e2d7b51fa756720397bbe214c19df3399a989958732d93979e361f7266e53a59bcef695435db67cd8749d258e7d582726e1bcad1395e68d7848849fb6d74451a53ae6e8989c64701102959f7fedc6a5cf8352e218396f9181f33037ca74886fae6e57460bbcb71cbe4cbb3d3a81e2090434eb1d6d5baeee4ede251952ad88001ce047279cfe435a4afe97847f798d84ad79a11bd44f09222d2f3b7fdcc47ff8a4c61f40c4629a0f603193e0aa2164579a05726e547c9081abcc0087907f8034469f740a020e19623fad42e9cea64068abb3d6ff2f6680da328061c200e1f646816a5083786ae5b71728a0e5cee14d7a942379c389fa9dbc7afe7e7ae075c061df11e4587bc90f92f1b077c091c43a25e7b3e870ad852c2883aba2632063c4ff74a857ef7267816317f823a8bc5dcda311b513be3a40e6bdeb89210bece50a608e624f00c9d063e0c8878884e45527f50a3ab4447a9a01652322700f087b6f96ddbe96a68ef98656800eda6563015a6d3c0eb1b6a9b21cccd58cdcdd074b73e40a098a980210ef831ec9e881cb42ee07519fbdfa52d9c62766a2046dee7752f880dc9082ed7f050b49ed8d14307b1b811bd87b6db2419418e49885d20fd7ca8fb45a11a1da17ac2304393734b552b5d02a303ddc72d1f456697a287851f207054c18a6262f5349348c806841d21e11fd4e4ed9c01fce1688483e009930079f7d2045a34f98ed83256dec66400a783d58c61619e6e42f6e2c6e6fc69e76651b96aabfe643ac69681955ce595f4696b80dadd1f3910061be6ed0840d47e928dd93e7c3d6932d3ead820d06e2539d9a604a6b53db6bb599da851de7cc060faa9af76d708a9aaf371dbc3eff0fdb99702504c3006f789a49feb730cabe40745837e2c8c17c77f999333798431231b337357637a5efd1eeed891fb7475f2c9f960e67578adf50241287bc5599ee08d0237f08c86ed9b75b62d612a9353e48cb4cb022d78f73fba1fab7f794a5ff64c97e6c91ec464847a81e5a5253989a1ee54a41bcd9b4b77bae6e72421471a7ddf0136edc59b72402d57e542916ee47fb3988b7123c6e8debddff2df171d4ce61e83c3d41f36143c9df97f2f68639f1bfc2a9d1fe175fe9f45e17e5cfebb330d3f06e15e3cf58acaff09ea576d896359a3f06985765824bc499319384e4c458d4326db801c564b0b503552bdbec60752b670d82cc8fce9028ff24ade3e805b81a72701b37d4ccedd72118b20d792739e035bbacc4893ded88619a6c499f246311947e48684a35406c4ef279c71ab2a74f6e5313f7900080f19aec3a39109d4aa41c930c66c84cd2163f4cdd59fe84a86cd8bb6468bce45a56d09490e032da844e6d90b436dd874c1cd32a75d1ae1d3e86d8a2ef948649eb56dd7b360f55ba5dc34a12f9279945436c6fb83d1ed57ba4ae1d9342a3dc2df9baa82fc9fee927c13439ba5bd2ff9f3e6f577b8d2df731db14c51db8a14bb15bf3e125f1ca4cb2fe856c5a576cf995db5010687d0799581c5e76d400c1855bb46680a631cc582f51c589a831", "823d0cd34e7450550da9716c1f456ce0cbc79431483a6214939266581b0e899e4c95719a09c1ef166a618289a6ee6971b6fea3fe380512cb977823b387ac51d341c26d4a835c61eebde37764d2e1d588df7886177e98e3151106c898b3196bf4dbd83f5f", "a4639c22fc7f370d8500a53819102df5e86c541c0ca10e8f6564e50b90c28f34", "34a04df283c45655a52bdd84", "cd8d1b2e5f65ddb3c0da8f12096134da22ad4d541444964077610aafc1f77f8da5ffc75bee807541cb6eb0526e78d57fd88fa9d9608914cf391ae7ccb8eedb0aa711889f9b6192601163b271c90df5d69fef487b6c05a24fc667469cf16cbd5afd58fc830119fc9f61b26dd50a96ed84c96825a615a3aee84ea4c950152323b20884346b25c9e2a6be3a93505ba059fbb114c224bed8f05f54eab76b2c9c23a0fd942eef9696ff67484b542c8347f1b1fd7df7242872b3528c9e45030447b2bc85eaf191963291e4223b75778335e5f1256618ff87bbd68b5a9e5cbd2ca1dc8aff4625c834edf8fb0d879b1f75ba9b85895a6bb4d7569a41bb3be6cdd020065bcc69b44a8fa335d9418ea2d090d8061e042e8e1a6ac03a6d5525079f14274079734ed42c5c9ab9986f0fee6bc9ee6c485e233e9b4d6de70664902529a135a5675ae129353eb2c00b73f226e84fe8c594272d6eceaca28b6da30492c92074250ec80beddb7208f9b5418944305b0864009b3bbb3dfbfb4cc2bba3313f8f7c6c19860f1dc0f5d7aa06e3b551adfc63dddac980a79d72bd2225d54a87a93717291c7b78bdfc5521f7f3239d5564fe9c9559dfefe76b77efc2e75991f31a0134529a6611ab9ef076491f2d2d81ffc5774ba8f8009dd7e5881e09ddf5116fcb5a44e576aef6cea91ebf52c56c742049639392cfb8b280dc2229252e04d8d394ffafa539290acdd8118656e7e1a4f7bfc0bb689448379e8cedff7590a09a3f5a29bf819fd87297b96ca07431a29a07ae126eb9d65e21824c16707db89868e127f17614a536de6ed268b1600a8b02aac2bca54a09b7cccf8e184448df334f95b9f0221187d56da7bd422f09b4d94228098b563df53414a5a86728962a2ea63023d8c3f03847b36db7cd189ccfef3e623b14842b8cccb18b4f80f01b32a4cec48f3009b98ffa25dbad76089c8700e90848da74aeca81d01f4dab2b7e844a3e48bef21f33c92734b821ab382bdf6d0b1048a9866e676b78ac9398678ff626d5c173a15a0a7514b2544405dd54eccaa2791605c87d7117bc9f8c0ad84623a9d3a2b1733304b492d4dec38f7981db9361b03a2837a95fe937976c7f4341a802dbf583366fbe368a3af3f92618046bb55696cf7af1f465a5a57ec5908621f431ffc762f35abe892f772a60a3f75ad8401321f67981e90083fdd1cce40903ce56a629120d6e13c8871523c4d848664331966298c8b31a5bc8174a8c14f61cbe98ae7ee3e90bc832b04318864d19a9b8b6d49a260f42bb120cef9afbe704faecf0f428d917ead9f020f5e9d772bc8f29600f8a7623d8971c1e3c5f1a3b094191e497bd70f85de124137cc4b9fe0617cb73cd44b89aada072625e25976e7aaa5a8fe9d9e3f32db47d1565aaef0e84d256bfce6aedfa1a2dce5a94976a2bb9a0da95941fb7ed444990b0e0e87627e35f3235a998019650a5e5cae804ecab8cf729a5c712f1e7d17486082dd50cbeb2ee1b0be6a7bf08a66ab3cf1fe9f49c7083f5b8ad183f32fb35fb8a41230e4041bcf0e5ef54bc3d21ecc1fceb08d95d745a997e8f2fc3c0f6b1b6c1c02e03ff02ae0d879d13eedd42d9f9949ca7ebb785764162ceb6c6f9944dcb3927b2f4eab23ab566b2b2bcc0c7d77b82579e88203602264064ce98b5b1ed992c1bb13edce579ae7f5e11697b493749f308b33e47512533350df5c07c3dadff656197884f359cdfcb736d29231aea1524b56e06c92f5a98ea663543f67e44003f5b41907a951dd792468c84c5e0e1b46149a5c9751295e153990b78c0cc712889a21b299b0315150dc50aa3b4f7fb0079ddd39d263a754b1dcc595c76ea9fea6c120384afb38d4bd40491c4689b1afc9dd096dd0327c84802bda6bb6b7a8830bc6c06b308ae9665a8666a5551ec954eb72adb827ef38f036c51698a28c92dc1c9e25c267532da2c04c1bf27f5b683ac750c3ef53a8460dc186331549bf82868f9327422c09afe1cd15e161bc41a70cab2f973efcfc8f01a380b86a432e1ae540e09d404d93d22a20dd5f685a52f0acb863dadea236288b1714700f23d1c19e40e219e8ed21f6a393e541abba850ffbbd4030e5f6567b7202fb66d86cc2a0beabd495814f6a50690e8d74cb8b093e4d43261fff80e7a67ca06dfe808899cbef84c09ece01414baac740cbe4c656b17991868e2a136f4785a0de311aeb18cc95ed33fbece22aaed8cc1e47f58cf6c09a6f92c96f37d2d2485b369093506f5e9f8534f8569655277d0399ddd3d33861bd40c71ac53a44d1981cd744d79202322d47a0228356c0e27efa2ff1009cf2a416fb6e8844eb76b8077a4a3961ff193e1c95b222e72688ba48be82ec5da498e58861ea613782ed1ab50a95b5cc236834af98e61528ab18453c20ff978551b81e1bcc0ff4b7092bdd9ab0b946b7324b7361ef05e1f7d7f6a336281b4bb2c671a95a6ab84be6bef1b9c8c3d2536edb8d79b40637e16d7281ec5243016232d7c9fc07ed9dfcf555055d8ae65f12ad150da81f62f2e1e82b3adacf6d623ee4759ad61a09038905bcf1dbbab671dd28fc1d10a0b7eaaef73a5862ab449bd84c8698d061e79fbe52a86739ba945a01353e0f3916667bd7b4356cc65451c7003927f2aa738d98245760550156dda529be741ce3ae1afdea0de35ada26ac241fcb5d518e6ee7f9930baf88bacf8bdaccbecfdb920f3b26285439912a8902ae029b07f28c1dbcfde780cd2bee6c6e5f4520c5c7ff3ab5448ec86cfb270c39586f80041f3764b5dc77dc5ced0695c89671cf90ed34c4067b4bd938b1493c7902dd94be824810a00bbde4915d138fcc7584790bb0b6682fc0799cd415441ac90c1caa008c7fde3ab4a3aae478c64991ebe07e6c4587d3046c9ebb8e125e795f0be9266bcee5a4e4355a2830c5b34e583b0355b34b89c08011db6f6b8371de003074704e8cdda37ce42c7e395b6a37bae3dfbe67bcfd1f125c9a262d56883ddc028773988270aa30c6dd326cbffee589f38286533e1d5c9486011170be591beab5e0ce98837cf91f0a58d69d872e364aa88daf9cfa71bad167129420282d99ed5884a1276dfffb2c4100c74a8b863b063c07937f2e9c12523deac4ea16178863d975e3a5be5efb5ffbea994d07f7ddc5326bed1f5c9415c1d4ee1667e3a581499bb573595158636ad94d84f7c6e4b8efc2b141f2bfab7932a050fd88a8c7b21877cddd488543db5b11138cc808e1248b6e2ef492faa8a32f9d93e3c060b5cec10f03794248f9662ed8c283a8e0eb493824e2750ec75b3b1292d80ce002083a3c64cc487afc31b20f84a778f386b012ef7bef46e638d0f1cd75487ea46e05621d608482637b3e642a9a2c5371bead4386eff968b3e007fc263086d8a930dc76a8431a4e6907ae35c7b3291075d1c723f02e4895714803c0e97d65b04c0f27d01d5d68001bdb3bbd44dfee1eff1754fe8c182cd9bc6ee273beb2a444ca1766f747d86f36cd8cef6eb1dafe0c38b9327a8cac6e83e076099188f02721cc4de3d940c3ef19d9b067be07b890c798a79ee8c44d96c5e05ee5d5202d941a674378386233a83bc85134dc8c46a7531b2b952fb277d8089cfb13e882bcf7545f0605271fe38bf4754f98dfa13fe6b635a62bcf962553882a8f28a9a5fc0b3f85509b702d4a7555d40c4f7d10fbe80d48b4826995fda7d15f14aa9b95fc6526101cf09c97fd74baca6bd26b4fce8a57b0726e0f68118969ec067e9ca39b2ba59fb0d78eb5cec5b872613b1b76763b3217d859bd6d991bbb5448bd4e49dd6597ddec9e46afb3f71d254aba828c91de51904139ab19138e36e6996a207da80323d96077c97a3e8994296376d4dcb602f1e77371efe8b020b7b6f6f7bd2bd733ad9c06c45b77a2893d73b4a8a57707969af74ba06b2fe7d4079bcad1cfeb3689ab95c8b1215fe0a855eb431f67df4ea589dadbf055086924e42cb142c9031e25b81e8e1167a54008ba1ad7fec6794f203b27f3092dd72bb766c9653a72b2e25c965f53487cf3baf74eb7742702380303af8c0a61cca3eec78d4b709e35e2cc5bd586263d9f56fc12454547bc6165e3f070ce7b2bcace5c8cbf52f987568dd90237cf190dabd4ee7a80494692a5379b013611f4eebeef8e1ab9a9c5ba61926095545e19c3dd61b7b404230729aff7d82b6bbbed6b4a926f6e49189e3bccb578fcb3537951fe9c78ac842350ddd80133275ac0bce3a669183776fee8288f874d29190b452d65bb7d8edfedc6fa0ae147102b92041af6dd8a566932e016763b60a5b9b1e3667f228cab075f966d1c525ac19d12046c6409345799adfd7154b6d8b51eeb1eab3a132ac6a2e08acd1a34bbbbdd019195af9f8a93c6ed5463765173e669cb0d42b6cffee1a4b45987853d43c02f920819f45a4fe0905d8c65aca182b4bf56fa0dc51cb53c642fef003d92c13ef4bc1bac571cbe2ba3673a49694f6311b7dfc17a4069759177930b179748d4403c7259e10a5d221cd0a6b745966e598f894e607b779dd5289fbdae0b4348141ad373a62c76aa454b35b39a7be875598bb30007fc300606ee2537cfcd7c22b6149880fb3cd8eb53054d698a0d20f26a5c3ce468255737a68706784", }, { "5622aa8d2f308dd468a7e4959ccc01f0e80d91f79df65b8201eb44911f6abc758c6703bb97908fff377395d33f96c328a4541f414b7ac34c6607dd85729afbfe01feba988e4997c6bd2c99fcc35d2467b143a8fcbe6b49247226a9e4c0a4e3c1a29d5931e6f1f7a31d90a0e0edc4479f08ef9bc65ae4eacd0b93b1cb38948dda31e60b18d702bbf5935bd580201d1f280cbbee679fd834aa6be576a37a037eabe989c3c18c7fb61fda8b9ffaa8bf22b57a101c19e850c454353af7af3d755b26ff1ee78b9d9daa78294972d108958682a5a29c8ef260e2289ad9d7d74f32fd4e51e5d9ee828366abccd97dd56e035713a6f3a1985383c0ed5d98c4accac2fa1ba7d30a295670d5224952f7b7554fcbfb426c9496f054834dec48f9b70af3d2b1c6dcda1c4daf3e9601364e57851952c785e65d753be1c22729bbde33aeb1e4748dbe90da6ecf716f05bfc68ad819515dffafd33a909562b95140ecfff1d0747f8e0459fcd3ca6cd8893262614bb4bf4b639285f327e7ac782898781968ec98f6f0f2f3c4bc5f9c4691ffa7ddb3662816f8ad092095b598bd4d10d6b5fc6fabed619eb11dfd4d638f4c0b6cff7194156a411e8ad6d3229320336ad52fd9811c3a1fcd571d1bbbac67c6186737ac7ca1ed9b2bc46e4e578f81c164b09ae5cdd4059a2c22b5e7ce1dade684e49200867f9bb1430aff9b99805cfd31f7e3fecbe898f70a4eded86b8bbeef7050eff6cf8ba71395a7ae2e270a2b58010e56cdf6efc4003da3d8a82e96979ee68694b6113cc9a6e377d40a810063830eb95005a81405e5b7de8de67424845bab1911bc55da6338513742d237a555465fa54b07ba50ed712e7a57a39fdcfe4af50f064ae969823aa1c40cd86a621ec90769d0c1babd33e8388a8bd76689215b9827a5819127bb32ecc80a562a291f3192eff34cad2635e5b0c0bc174add72e2041864953f1fc72be7d28111fba0438d9036da3d5c0f220ccfde2319bb96fcbfae6055ed7f1c1967ee9a78e93bbb77cbf151084d602a5a2f087d49c3134582c1a5d7af24f4c88be26204cc9dbf4368b19470fef49a5823a2d66c65e9b1e8ab56bf5a7bb3220696840a6222caa58a7b39fb792d95d25038a8bd9d916e853cc5459640f8b8468e3d51f05f1b95e996cee40ffb7ae14cb289094f1b77d5573c1aee7c12a6c3a1e31491422f272cc5f510d4f18ab63d3c3f468c5abd61b2fa7ba0768d46392e2a4dc06c7ce79841dca916cd33cc0a700b50fc660e5d1808d8b87e65feb89428055495823b2dc317d6d9e50aa5ef7ab14076174ed32f56abe7d410e58ca40e92f8a31433d0d74ba7b130b1561f2b075fa11ead744d031f34d82f1a64d428f6cccb0a009be24b42937bf3e99a1ef1fabf0fa7335dab52918382abe756d3de229ee8223aca6d7c5de87047838e387d4e472481a4cfd4365256e13aacb518ce5300f18dcb5e0a28477a6fca08a74756ef6bd8933bacc98d02abc7ae60df7cb3e06d41abcc4bd313c543ddcdea2424d98ffc6dcaa83658aae11f5841ffd4f5df42368a0e815d2146a0fe138b223764b133d17cdb08d485e9f3dd2bf2b220d1f4565b02d7b9231d592130e4436849f49b1a70772244fc0c38da372a8c57fc80ad57828410a5a16ac6d14e093997fdd5b26e4cd4b248e0ea221715ae6e112e1b68b09f795540e31b1231244bc922207b906c4f42b5302dd7474286b653b4d1bb657134bab117d6c349fa0f121c2f8dac9cdcef510c1c28545eae0ab163db6cc84ca182feb858c10153d0136f00a01c9c7d0bed892715dd85c4e73627c3a2ef0f43710dfccacffd1d9f118c9fb1a83b2eb328b8da3e955f027d95294038184f7b895d77532c7570cb86fd6b37a5a66659cf1e330db3930f302838706050c0dcd91d532d49c89d144e9a7f864026ec99f50acc02bd5f11ee88495ee8991ec4723b189f84e03d992fd718b5173ea1b033ab7d3568dc4656648fb54d28d3119b0f293a930a772c394f45ee66838f17b73a94eca27033f9d5c2ae22eb813386905dc024673850a087958eed191d04d05798bcf909eff2deb2a0009d223323b290e3d6f71b2797a2bc2590d54294a5992d629336518514032614a04847c3fad8a7d1cfc2f86765b48cf58acf892f68b691fbece38100e6a71487ef5c4ae934f1ba03b4b26a1967f70ef1c697202e4eb22a3a95ab3b7b524f0241ab4d2adf3ee5e3f2974d0bfe4419ef0ab11039ffc26339570e74d260c4d5a16f22cb4f60b03253487f5e46c47836ce29460728086a615f78d631d89a06790928455889f58adc3d0a3a84ceb2ba9cdb00a403080e6567873b985fd59fd9dec71e375013c12c51cb67d599198f36f58fdaf897e85dfe6f9896cf6d35a84cfdc6834dd9447a2a10e1ffa9fa8edfef1db9e8b4a245b211de49e04b7e88977b4e1ac9285f43526f2452181ee0f80efeb1f6b2533b656519ae45652ccefca81c17714476b497e5d8e9fdf6c9f504c7a7fa7afa36df5f4f8da5b4b973b1618fc8d2d43e866b235e5420551d1659e5bd545fb78a3e17d9cbbc8e842f3fe6be07b892453ffd689d5188f26f9e4c545ba0b3132af12a03bce6914015d026d3d7df661c1e6384bbb50dae24abfa78079a2b1ac41c44c7d82a59183f293f12011e781d3cdca2f791afa5b55a9f2d6139587bfd74bfc54ce91e642847a33b48c1b366fd8f08f520b79ad5113a0273735aee71ceae361a97547fc09b22fbe4e4ae4ae13e52d65e0971341aab368d1e917c8f5f2ac57ac119f981b51b7c99ff2be3e16935b7c73e28fb58d332e6f2c36281228c479c4d6095cf15b14baeb0769191dfc649a70471a25d45d4433797a5b8ba31ff567e60ec4d759d99244d0fb5dfef7c2896809938ddde0d2015a4c5ce5ef6cdb5752da1c2a33e5bc78b6b7c6a5af892f0792c28560a357720da3cee3833bbeda8e98e6a8cccc6535831cfc28bc8557b4181a3978bd90eabb34b99eb7e55d9263e6790ca34561d8c87ec4e12b4a38df524318db00a9b5bbde6f5a8644a818a88e91b521d716fa9f95bf70b109b9905bfca926fd42ecb9114c039790abb0392a41ee4c190536a89ae6194befc2dc4bcf7562bcb84f65c99b69612c0511552f53436b6c489204d3881e1f67e0fba3a061165d2955c2e2e12c440d31556250a8a5cc04ee5e09b1d627c14e08bce1a92df7f6475db92a3ee57e4c16c3ae677c44237122818ad457a29595ab528744707f3ab7ccf3d20bd94047e013e647802a7af14cfc7c11441ea6e9b9f960fe69d03911ad2cf3a8f633e0d647c71dc7e188c92e75353fc953d6a30dd0040c39d4355b71524f1a4872fb1ecab22c8293b54bb22a80e1e3d4c886d2988adec26f041dd0565cfa9edfe5ad9aa7da1d3b8f68fda9e9df9dbe98148120af6ff30e6400deca6dc9593dbf06c856d0d582503e7ffa185f87c6e7ac58184bb80b4a1c0c18d669e23f9791365fe807356a5763ea418c39d94311759b29b14324fb6f3104359ae66532779b825f92b7c9ea2ba43ba7de04eaef7a86192bc93e17286f1b6e0a01c33c796ebed8f17692eb9237173a051c14e4869afda2643bb98c9ac4ea94c6bdc1401c80190df6abe988d2f0b2d80cc7bc8362ba25c6e5df4370a43e156aebd6aaf856b3f64d5fefc622d078faed40b760a361966a4765adb809dbcd74b7a41faffad3a64823860e5656874133c7f8a46b5a3ac591906359aa4f171ef6bb2ea6b5f24cfe25c2fc7c1973bd5d3bb5f197002c5ca1bccffb570f0265f5cd949c7386d961ac9c5e18b5d1d6030d8bf4a48c10f12dcdb11924b02b8ab5e91f425ca62bbe42b80c6b6dde3160ebbd55803966716734327058e29bd39874f2eac199067fdbbe8c372c5a688d3615e2b65f4937b67d6a26c64cc2a9e5379cc00925c678f174f538915f912e85b7014c064a73bcc7ddd38e1a9627ffddb4bfd6da764fdbfb45048c9495ab1a4cac5642f6c9ffbe97d33cb26964a23719620df3d85dcfc392c4502759fb31a6a797e99e51e94cf9bc79ac15de4e5cf7a05aeb88a8ab4c3b6f9c52b99794503f2c49cd7e230a67df7403e552523249f29d257b35c0c7712053c3d9eb583a1a7473d7f296d25a66566e4ba8b08de2a31b082e40c8e5b1e93985b324dded3f52511744e7e99f4e3ffd99d8ae17bb5122b37f637c5525558eab18a378f5e2cb56fa003ed3af8d139d16ec4b2ea79c415b0ba4d750ca2cdf653582ee3b65a9825fb9b123593e36e645232163cabda515b959ed0a1419e9894f6c677ac200fd11babe3503ec7bfa319f1b9559d94a6f82945c9ca8667621a5d28920949a1da644cbdb58b84742e9d65e7f2027b99fba4dec46f642bd17e88fa109143b26ba7fe285c89add0b74a369f3d381ad633bfb4f72e1822ff96aaf9a73b3c59a6e457cf40e17c1198c64737037f52d9b3118daa3fa5cd3e3c7738e3b3743c595893289974a4aa0d6bf1446e70964823a7d5cee67b9b25b7125d9ac5d1d61f2a6947c3deec6deb575e2fc5cec60df26de3c0545e5b79156dd6af33a78552d1ee9994cc8501b7dc5fe7a22eadaf201a92e06ef03be705a8bdb4db65392d3628c7cbf44cccac292c93cb5a407a7a5a0d5ac9fd95b0033d6eb719d3f14609190dd40d5aa1b983cd4c4e278cc8a1e7d5fbb0d39060d6cdce8de6a17e2dab973a7fa594205e17edab6514372eb51e03b0ced6402fac0efd3af49fb8214a505cc9f5f0ea5308d7fe6dec369ba154", "9f522375925222a04f5c95ee14b6386412025903ecad0bc3ab78afe1145136b3a3592835ab4ad6faa66be9", "d1ba82b3ced3e9817642aaacedf482e79bedd0560ef2754215ee792514bbf8e6", "bb21211f342379370f2642d3", "1a6683805d3f478ca1c1512b9846468378f83be27393db63956e151ec408368b47334afe610249182f54c4d0a01b704db2aa90a9755b8feb67ef9301f0715d7d6bdfa5cc4497cef1142a43eeb42f7c413e8f489af30d742a706d05a40a0c4a5991f9e2cc5d9fbca6ad3767682e20c146ac35aef38dfb2a77388b738fa022158d5c802e5f0761096bb45b50815ebf09172759521b5c5d459703ebe9ff669ee4d14a86e5d0650b597f4a082ba0aef366a924ea378b91c3262d99f48189eea19c76c0f644079f8415c11033cf24d30d6c149ab13ca5c29deafdc816e457257361c1af4b915da312d2e6c7fc712faa27be3e67c893f9005a0e2c28369991c1dab22d38961d1abd6d94c4d549cf491aa1f8d522be3ffa6d214825a5fde3c94c4e35c29b8d05b2627eb12c9d94f450a85eec6bc963a279a37c2344ca36eb604c4bd11c2bf2ecc0dc16c2c365bbbcad3541bd54f8d0bdbb3ca4a087b62fc19fcc1c13984eab807d2a6a1386643d90d412d027bcd0a638765498cdbb1f4cc1b91b69bd241eab3645f225ece85a56e5008d6094041f8cca6b9a0ae3b15585de6fe0695d79d348f8619431ece40e736957a7627224fe92bbe30df5124f476d97e36b5b08b3787e8e00f0c10013068eb156f82f3494a35d6edd5f7048d1e91954f1013ede22eca8b4ba41699ee08decedde87139180a567c6d169b672af0f12aa09ce20e9cac4e78b8067d31ba4f63606c00d1d787b868cf7643fbb170f8074667c9f7584d36af80b4e6557724013618c28d0dd40bfe9d4b25761b3c99558af528c2d290d04b09821bd7f992c044dd61dde9395bd0c9ddec6d0bf6e044ddf0b4b2d6753f5acf2e9c904caa4e9f310578527b85e6738803758da646919989f735b09c9a5744e63fed2c3982e59fd29d2baeb9771316bf8d29213a4956b66c78d5654436ffdd82d0d572530fd09507b988d13fd743f35333237681f8abbb301a8ea870159f802a57760659094d0e4902036c5a62c563f1fc86c4238e1ce89f5176ecaea194ca112fbdeefbef4fa7c203678cafd34486fe58b2af04f84a1cb620c6e123bfd96301e0a5e5e5abcc95d28b852d0cee2f51faa73e42f22fc335f50de4c3812ee14038633a195083f3944284c1086c34995832c3cceb7d385b4ce86af10685c16005495121105272d1d739c584a07ec7801c3667bb280987a8aa41f9537e9d1812a5dba5b385a0b71d2e9573c6f3e9ebf0bf7267528946a6aa6f43efce908d32525cdc3b825bb11c7239f1de412704d24c17455b9382fd6a873180f0d5d44dc449320973d5cd0d4e67e83946b6ef47e5fc3dabadd80751f1421404e56b1bce748b7bde63c6975ca81f3eaf52586a55242c9745dee3f7c796d4508e818eaa4fa50490c1a79624561b98d2e1139a328806414c905372356a22393ea0da51c83957029edd8c2dfcf46d9564264d74c1c0497034ec018b1dd4c14acebc34b6d2c1a616937c37b8b4a0ee5dcdf787a0de1173798ab929b72e0fa83a6c9b9a99d8024328d9c236a8f57550a4f83e8071eac76adb55939f85f5b5f514174b670a3e8dc2b54656f6201940a81fe4953d2680ae4ec58635ba74d15efab3e06dca6ac269711ef2d4dd49f731e24a92a3b935ebbb3fe8d001cd4062669ae4baa62c2947033afcfaca227d88a11769f87456d5cd1bb6606891e71d63aff9cd5a7d23263a78768ac2ac54ece1441fd37d096cd27e916e68891137fc3cca427febd1947cfb4d7ccfad75b2ec5e809c132111eadf25a73043d68333139bd2435de9941bbc61c5c509897cfc19a21645019eaaccb6d06371e3d0570c09c7556e41a727e44d9bd672fccd1f89cc7d58761c16df8fb75fb8a1dde2caaf088f02dad91b6489114398740e6798f3ea8c7b0cfd974e160a0106d703d9589ab09aae79108e3212f19cb950ea9c0798a1532bc2a065d5900a12054395c0545b0878ac0b1d461f553dccfc2a22bf254ced88dcb538e3889549960b77ba6237ab1458e158f4f46606372e797ec9d9ecc6534acaa1218e7540eef11030bb9c3e5a7816f3b33a590d970619bdd2dc04d5c6f4ec38b7cb4d525234b836eab57f65dd045e02367eede9049e219b8712b8d6fe178080c5f77b821f1a475259ae571a5578eb3b48863162d45486f71a28ecbcedb35b320e5b6401f9e7870aa5418449bf47502626e1f42abf481b48d5a6819c640bfdb64f873d583fc4e40187940a6c3373ea7b47195270a8657898f55568985018abcea9bce1c155d95b426f91a734b2a14ec2c7ca2011a4d30019fd9b3ef63a804e9c30c3de2651c4213e90285a4ba100b31ee402e8a7f23cf9d4dba003bbf982526bc63be5af102dca34e7d362d6fbf6f56046160d7af33b364f2a86074d1c0fdd54aae89b19480efde2a9caef9de7c0f9491e1cf43a48752cef405a0ff16b0fc67bbe433a3c1b9661406c3726092efdc076febd60c436476f24dab1b0b8f8893986d951ed72282990e8b1526f4dcf539b22c01c6a7eb5577cd540a16a81296ebeeb7ddda72e60fcf2840c5b42c5cba30eaea5402f267d1d04bc80da5ef0dd2bf3c7a2be986507617c9bdbc96c6273a0c9e586a0c48c98b4552113149c6f79557fc8ace0b1a512fec3aa09ef191f95c2163113ac5cdd940f0c2120509bc53c3ea493c54703effb902ef752c830c61e85636ca95429bf16937bf6786b3eae1b277bf08dcd69f521a0078d633beb33c9aa0cb33b238e1021ca67df122a403a3698452740bdcac81d22ccfe4ab5f835d1961708d1faf6d40f115f16c6094ea37a7ff15e0534f62c19a6f4ded0967be337cdbdd2a7c58ba16ba2e4c3686e9d075c6fa7d29b2a0335ab4940d2a95c4500295f4db84ae65e46c54b7300909cc5411c725a31fd962d239aa0e2007c285586b4c778e2ac7afec42cd8409a63d7cd9c677031f43f4aaf04258dcf1270c02a4764177aa66db2d8f860eeb1fd06d0b27587537410bcb641f90aaa7bfc6f12bd143f66e7c933a0f3ce6b5048913e1b2d79eaa6c19e7255d5eabd24d5f12426339541a22d600cdfd1781a1a3894740887840aa82e5a461fc324285b0223ac9b95c3eb88160353f168b3d4ae8a2e87b7715b5fd2671f66e6eaaf9365b3d9e3acd9a749faefba6009783771177aa4dc91f72fed7a5bf6b1b7738b84ac0a07b4a5a3f0a9134a39e1e7e3e2f9a92d5644295f31c5a356092bf07c709b4c34305ebf50e857a4f593dd1cce0439d3fd125c1ede1a48f583bbbe0eec7058345129ef78868a96f8a76ba7fbfd1c5eebf75f3e0eeeb9db87474b96f321b87fffc02433513fb467fb74e2fc8feb498d51530c753e9a173e95e0edc5ba9802641a45db281b2e2d87d409057b4fb1925e834e90fa5619ae3a9237d5b104e7ac67c2bdc31001eedb4ec7064b2f72e0379bf8780f67ec4b195db014a2d130e77b1778efe3dc703f1310a566a6d3b5c9b12b1d4e25815493ed1510a516a31ced3b64ca49a783ad63ea71a57290727fa31386d2fbfe41f12d36a618c6c28d8f10405eb3e0a33e8ac2e4133ba75c688c8c9a2bb33c8fa032eaf3ea0d2c27bf89269c4aec55f8232b292e7fa9fc24527184f19187d9d8a3f52335e2feb5dc6d997b9b773a79a31db832b752e5738963ee5d61a1b426414975693f986e165e52d46cb059fdd4f48f008e96d4c1a48306b7c002fd0c861721656074cf11173ca65cbdb694c79f58a3f3365e872b24670b691682c10261eb1ffb2b65da031d070e31542f49704b77970a78bcfb4c4ca517b4c966a4e8e27664704f633e90cb7d7917dc1d3a8b8b7fcf59ea3a8a81305761923cb182cebdd59255803a14ca8a75fd007670d79a25eacda1138d67a0fd1da981529dbf182fc4d7a700ba498e4476a1d415381c9e2ffa3bd46201cf2e454c4aaedbbe3893bb4121a6de02cbecc1f319155eb8c99d1030103bb6194bee51e74fa01f28dbe16092955b9599d5c1f1c3f356e26d48fcad7c4cdf0eef25c25273dd62171785c9d2c5a01b1f3da9b4786b1b399d890e2049b73c12de2fb7177f2bc3d9c645398111ebcfd83b73119897bb994f998f4a6fae1b3d6361e171059dba0bf9de9af7a5a1b21641790baf82a36278945d649cf5d310f3792fdefe8c58986a48118fd94647b786e47733ae703701e18992bc1b143b1da6110a98030bb9895c14d7b8eae1a155a550e219a5b6301b6d26d7956ecfe4c7023eec1ff62538b3606ebc7906a1243bf8357f593b6cfff32e3fc6b51f6a0ffaecb658d526f7a5e9faa6294e4808b779f4832318cc184e49e8957b72bea0d67366e040cf76a85889fc6b04e84afab0d02947d0d83e0de19f12966fa8372f6e82ff402bd7a69195eb1a7864a3375aa9e23736fa4d4b0224647e416474c01f72b7d4af240d7f43395b5b04c8fdef1165ce1d56ee8ba0e350e6ada893e0594facbfb5f0d8829ae203929525951584c21371b86deb0f76ef5daad5e847135a6488b35ea33e3a165fea502975d6421d4567a229bf3ce94605885453610eb9c82f9ea743bee9e14776bc3076a29af268cc72d9092a492d9ff08c345dc2eb2f8003b561d9912ae1198c58107f8b37a08b35075af9863110e6770425e9d59c2dfff9d9942c8bc3bf7904c2a952bcd573706caf1ee14420564ffc433c0f5871c4bda916f2530ac75819ade49fa1de21edacbbf6b7075dba21a84989411c566b7c356b81803c7215ab0f326a6b8910dbc62c1bee3af51f105fcdebc0dbc56a50b22cf81eda563bf8c2eff98b476e8", }, { "99444e82c6c4c47070b164f298ffdf6955ee5bcb3070b9aa95ce658db4db084d2056cfe61a93568b44ba7ddcba5d450f4ba0da7b119425a6628b3416663c638692326cacc5c237097db5e537122b465dcb21d8dcb5fe831789b72deff3907685c2e23187a56990221e755930a09f8d6cc065487563cb8cec82b9dc754952fa0b342c92d99522fbb39854e338f470a4b4d5ed2a39b8b6253b7001b0b953abc588d757616c7a5d1f12b1024aa572ef5a47dc8480943aa6cfaaa78064fb2b29830280e46efa418d0cf38f57980146f2482276c9b6b16f865b1606bf1131e894336979a163ba2e70adbdc746be0d38062fafcfe5603e6bbb55717b66a263fbd5cc7476302ea4a0dc6167221f745a26a309f5886934f4258965a0ef0803eaddd05e54008df8a0695a078b797be59f1eef95a658c99a7d52001d4108212ce5f18a39f1173291808c980b0513f1a531e03ad7380372b65572d3967af4c25fe54d99d664cb67e557fff05c12e10143c13b1bfa3e8db093ff832a7978ecd85d3971349e3c9b83939b73f0ad55f1f1162d0c106b99c0ff98442911bc15e9194f5b4ded97e9702b84e31b31380c224f392e5fa5c720a45f64cd7020e25a3931b5871e4c708e77f4729225aa9f48f9d876597d3e79219dddee0efdd16836021dbd21692dafe121217347cc128fc5eb051e6843978ae17478ef714957a84c74656ddd931cbeb43e32fb0a448acf2f90ee98d38522b4fa9aa36be4fa13306e799d4c0cb90ac0f73cbc018146d1b0d6bf48aa446a5e3e0502aae9fcbd196b36b6b7426fc10367febf687f05392fdcf878863de2e47be7e625d0e3e3e94e199f055c0fc65f76c41ede43231873ff10eb854dcd6ac9b550ee8533d16f81eb0e86471d4da69311c47255e78ac8e79ab36ce880d6b135279fbb5a712adc5c3862a356af49e9c10d5b16f4e5dedb80914868111e194745b802a0292c7c8564de28ba8e71a44f7eff6573e5434e65d496cde5b5e62cfa9e2e9ac85a164dbff5767983e71dd2661d37d9027a27674ebe3433731a606db88e0880e91ecea8134421962b3f68915c9f6a5e1992c56750f99bc313fb30cb89384c72571a1a6a5e3c01897b691bd70985352217fa8a67f3252a06205bd1a9931d1cea3736559572561fedbf3ac4c8bff9ebd7f3753ee69a69ecbac4be6357db7f4213b697a828edc716ac01da75c1d46098c7d5d6ae6f3f9a2903588c5b340c9d47c234efea21b700cdb8db4279afa2117677e824e627bf0f2b179c864ba823926a57825478395545f130886bdf2a7c55a2647a888c3998b750343d9cdc602e46b7b09a2fe9ef74db1ffc46fe27c254c927ce51b307e96a571da7f3f907223fbed2daedbcc96197e95edde7859f3b4ec6099f791089e368a68a5ba0917ddf4f50b93c0c839ea36cfc8053811f8fcfe6986e5fa9f743119ecd6c3e5fea1dae3ad7eb465a89e9c68569190688a8d56e4143ceea3b11fbd9de67173d5134ec8b0bd7d16560ba2be52345ebacedc01a2e03e8183ef91317d87b2e15cc6301586ed829d438e4ff1d074408b332c8ce60ccb6790ab08c228807509dd4b39f2c227755f6b039f5cd413ad6f46c9ec2cc6a79457529d297b1d9e74ead9bedd9bd652fb31568a8e2a9e2b89e4e57601bc1d960360232cdb30cb502b950ef930d54c2c0692a684cd44b0472995bd2b41dac1553ae47216253d6640d2653a033a862f3118c5b5d60a662d240bda5f4da51092eff514f61a425c5b14b19517ec1b371d240cc30a0739273b34f18a72a69b1586802a7caa6cc8f5817a8a995695d063c9dd26c3d45feb0f84dc8a0773151cf9a537664f942f351599cfbee0558f441f5c7ad320cabe305f9aba570ddf6407749b6db42f9ce94526a8f4170e735b1dcfc5f0e090af10e039db3747aa9b4f1f26acc34639ac8b60557f7753e2c261a29852932901a4093b7f307319cbb228e26eec289898b3f8ee236032163293b8caf64be3f7ffed236f1da688d958a1bbb79dd45026884904bbb936c1ebca7aa6b0c68aa8b667dc1575729e4ecb4ffa82ddced2f4571bf902c52fc4a0ea3f47aaf5c243ac2a1fc19f825fde5d9fc8d06d97a351eebf4ae1846aa62554d57cffdb3f3377695338f8d598d723289ff3962796e8065632e7da9d8dffe2636cd23eac15a60568eefe3e77c561906555268cfc1e9342417b1cdf090cc16c79939b15a9311b0210094087dea22833f74eb0e35d44259ecf327dc84f3f24b8c2bfce7be0d97e00d2be88a150a0d557ff963b4cda60eb99935951d288768b4b2649b717133517f5e3909744417c9c3102c77ddd285976cba2c89e2b4f297665632d7c8652847c4625038a6670169772de0550066ec6c2018f503cce79a333ecc0a0632334df6959d2e3b052fa47c5c84d15ceabdc80bd6be0ea2a5a8d5e374e0e9a613369ca8d4cae3d9f98755560b27b2f6e47b01ba390f5ddeb732c22b12abd225e26ecdb639b08f3237e488430b3b39f0b63aaaef4907cd003a8f2b4c3bfd721d6c3fd3a5f062d72746606a529ba34251ddec4026f40d262e9d527ad84fecf5bb2cc8601c2a38437098aec2335104842ff1c455e5d17c136ece8d461d7a3bd9a60339c22d71059e09b3603c0565c0345684893b56054ec4d3db0bf15546cafb4a03bd7775c3157e7676bb7bdb7baf3100396c563eba1a12952503eb6ccde6b6d0a42d456743c4ddb97f5994fa08c5fa41315080eb6b928090956bfc6252b232f6e0785d233c3adcbb9370b59c35b0dd66005d516befd1fc843df8e68fab19858b91e2aecd1c8a88b0fa3d4c2fed2995ee87e65976b755fbf44ee183f9fa08848bea325807bce0b7b61e03e50b2c7af9b360532a17a8250cf6068fef0198738c82a5e58961c54017e343fcef7076e823d63b4deee472fada7989ca7a213d06a4e3eb2d44b16e5c94b1588321cf6c45a5a792938b058d667e1730f8386dfedc50ea0a959b78f12f2949b34b181f90bec622515227dfb8a5f6e89d2e559c0ba686153b218d2c50b67503018e22914ce9b49d3bdb7cf38172db1ea130baacd640c111614e3db204b3b50641d8978dc14b2afc27a7efa819cac6bafa8166d1c127e2237520d57ad38a80146217a12363cb1f8a720e328cd8f846d379ada43bd4865e4aa633c479bd448d205b2e43befa63486c717af84a733f1dececc127c047850aeeb8ce677612f5966e23d92c1d3c758aaeef82f862c1154fadd6766e1dfc780bb447732a5968c0c78b9af4a9d669338458b57cbb77910a24678092857c0b903152035bab6b1c73f7b667a08cd0d31128888de3ff1fed24866eb60beac19c1b139f77bf0b9332024999a2d56975e691fd7475fd93622119d0d725bb99c1d6ac604d6b6be09d6d29360fff9f84e5318259a67fec08a006d9772b9410ec6abd4cb828b898c625c2fc35c19cb9a6cd3b0073baec7b5af254d21de8e209539f560bc80ea38e33658a68262622cdf35dcd6618b9e272ac3644c91f27d372c6297d8e37201c6a86a7d3accdf579c15246276a0009ddac4021755f4848d10f714e9da86eba13f461e6a12edb1aef2d6117986120750d609682bfdfcb90ee3cde8be54d45f841a6dee2d5b9fdc4e65edb7ebffcf3cc5c8a4e1c6919ac57568be23bd8283319ce11fca3caf968b057432f163f22e29cac30b8154a646ca0ef4fdbc7770ee1451fdde9e9d651992d94c843d4eb2570975528ad9f8c193f7c681a43df28242547010e30d75fca04f39247c77d6c3715c25fc261ecdba16844bbab23e4d0482bd1565ca9b526ada9b8f5703661a84b23070d85f3e8265b2ce10750c5d798f1a8ef4d51a473ff4d2bf4be615566ac796db9fe61a224bcce05c31ecb9ab7bc43a609944a7c9398a7875609ddbcb556296f548a117847df7d0afe48a5b504e85b0d7ca589103d3197933a744fefca795e1e036f964a4f14554d5cfa0261e25d6e5e02f86e402906d3637a2352459cb1639f20faea6f0e3fbc6a39becb1b1b3a791e32e85e5bee31be685410adf0c11190e20b7a5119b90e83f2cc4f0de8898606bb6e64165c95d4c5eae472daa6836a888ee4d9a79de72b8fb47a9c9c0323a2be9106d4ee9ba8b3858c256032a9caba37af94df4c7b0adc2f8478cb879b6d452d73191b0fc1ce944df3f4809cbf3ad46eceb3ba4abd9679410f45c8aab20dd72626f235e7c0c934b4beb4507def24ebbdd7a507943c81d54bc69df578aacd9ed0bfd3b7809dec345ba084d88fa9c34d80685415a4d5eaef9b88e51432b2b2037186baf123a6257e47aa56d6531923d38178e8264dd315e95bfafd8dacaf901e354b0f58f135d638df2c0f32453205c7aaeeedf8c102e11cfddea9a98d3ac7c385d71b760cf2afeb1ebe1d64f0222b9b101893d11a74ed175297c1dfd188a2565fbecc6bb07b56ce3973322a965dc5a675587890cc65a71efc68fdcdf1a023505ef0bc0e6b12dca5860fcf1c6c94c2e2ec3a72b8a019d69c82d36a73738dc3d17d7fdfe992bc8e18cb5d3437f1f619dd318b95d1a56b6d273ed79ab2655d83e2dd63cb6f1f5987eab6bb21a7b13b84e2c619b36b842192c3f82c755d8af840675b0bd67a655d641b1886c3c9c147ac87615ff3e58085a879b21dd63c1616a3712279ec87d650a2eed665b797ad631f0ec312f343979cbc49b99385cfa92841cba12d52777df565545a1deb07800a15431c0987b4a543fd5ed6832e80ab6f4b4d9c9ec419932a6ded4759f5c7630a0b80139234b8d53117acb4452c60b477ad50157169a89bd796e2308baa9395b513a94747611c7978c82dbdf48d716c3ac181ac2b2a4702c02a324bd4c5e089d989d020ebec9963b5c721a95492158f54973b7fc1828181acb3cc8078ac095136d97221c60b847bd2a52427383ab68cd1f10b92738c13203fdfa0b78baa09c1837be2498667c459", "0ce980442336d0f427db869a6799baa6785b5e030567c588e2a7d2680e96c11b7f415fa27730969e0b1c3973b5f3192d4e773153def6dcc09dae29ac44eac7c42c2666a356fd4262197bd5cf6eeefcbd662d104423ec05c19a2e6ddf1834a3445a09e8b1062a1320a5e8ef13d6ebd03c19e1813ccd86fd68b46a", "1ac8a509db7bf4acb80d8d394a5abf47c273b2093f50f35049e749f3e16cb0fb", "47cc9eea11f9f3f9aafa23bd", "088888333340b3a057b05491fb2402301c8654948aa6d5ee1ec75eb045858c22056fef0873d6675f897126052923a47a30675b266ffb6181cbd29ce2da3720e36a227e4c6e53328d789913c0d9cd149a6e49293996b1be7d6c513b24d876445a950e723ade3efc36907c840b9b8cfdb1503811b4044d931a0009b381fd60a5bf1e73d16348cb57eea672709875fb9d56908dbc729d5d7d322a17a41d0f62c9af9a013ab1e19fb7b6c6e7fa0c0b18bec5e3d3e92546c77e3753193389e5fcdb6a6a1896cba461343e71ef7a156b136b27ae6f45be9368301cfade203e9b53824d70f07de9abfea1968b8ff8489b9804422ba05ac3c3adf23ba0848817fa51febab5e9b5500100310479e710b663f064c1ef101c9a5320367cd8bc6e52081a32f070e7d3fd6f4210cdffdb9fcab1de4af5b06a7c6d191dcc12b25b3053e58952bfd1f723afbf570796946c1df9579ad14ea9c8c30389c1de4d1e845c764fec5eb8faaf4c558c5eb5113018c6a21ef653ac7d7f5b6c7e1a8fd48c6f423e9913436202da176a86731287db7331db055508acc94168888040ee37b3c119c8a0d88360241d68745825fe480324a944d56e7cd0375d4d33a5fe7a3863c2aaa899b2d24f65b70bd804039116fe959c32442c9f0b5470463523eb4336985b71125fe5235cbca0c88a6f92416d038e144de5ff8ef6ca749a9e239f02db505bff8e16fad1cba8b1500445f067a674142b6413e9dc0f432242d8301879bfc11fa86d1ac9992ab12319fea8b703e10a13bfd4b017496222be26b56af3ef67610f904f0ca8a3e7cc249ca8122735a542b289f13922904ff23dd197f8883c7ac77150d7331316ef94e0cf13b6ad95070420513599100b0a6d117640b781c622ed7ef7ead29476b3c835bd9dbda2203930bcee7ac01c3b9c89da405ee436ee652ddcc3e96c7f1a94e200eec9a4a226f3cf7ae5725068916e73b61149497d11dd85157f895669f51978d1bea8fd2afabb18d082365daba2682ef623109988b7d0e27ae57bc14d86603f93b5ac040ae52d8db404ee27e6c34cd4246f40eccf9d3f8637a4615a4006918b01d34709bcbebd02ea72958d54db3e87d69e6d783de2f1841029d6975eb11f9b076c247108797d5368c656f888092b82aa81aa26e164e038b359bd68801c22fc107e4083a9d85fc254b002ece9d4545310b0cb22ec1af04a7ee31d210ede4b605dbdbcb70e4301989422ef46edf63f9c96de9cb3f70638b51df5c0abe79b7af8cd97148f2b7bf394bea0f7bbbf6925f83b901b87a6079f2c3b38a98fe1a86dc7f48bf97553701834f557451df4b41e7db984a34432823585380b45c1b84813d6aa21107cae252923fb4673cf660a541e65610ac0127d238285f53bf329b62169f3e42d5efe268dea62578e97da59a58a1314a1bd46cf7a7cae772814130b51411082e30062fdbda1c9e14d6b2bfff89d0379d32461f3b8e833b105f6a89532ae748b5fb43f283fc86450404e8befb8442b65e338aa0408303a70e9c27a1d923d9f2a06e7c6159c50bf2e3ba5b035420ecbd9d0b5fae478eb1ab72fa714f99d00188bb10e60380fa3a3a318c2d359ea3805c2fa0dde17ee52a504f70d6b466bd38d1dd4196be336a9ab4a9e573d1bc6404018a119f688c1dc2a8ed1433e8a8ebf455ce3808c245f0220f0c12d28c771757763bd111ab829294e2429a6f7a59858dfa1fe0b806e986d40aaff934589fefd75ab91097a979f26bc9352267efb2d82c4738e4e6c451b0d5adc398f546c646b9e6b8fc84e91651a1252d5b805a857c7798d102d1e6f90749252bc53588348ecec0897c79f514442fe3b27608c95d0cba999a7e0fbd7f601689b4dc63ecb9ff553ff12eca3e9b26e3eccbde28770bb6aff7c864ad6be77fc09f81f90df6efd0c4025d0916ab5197ab846dfe6121c462761d9cc87112ebbca197b0a222fd34a15b824b7eda06a56a6ffda760fae5f0b527e2798f01e205a3f47947a4bd190f6abfb1dab2e3a53131af95d593bb57e4f4af506440cf20636d9fccc449d9565bf43dec8b6877337ca5a43900c1dc600c877b290342914e909aad8c5f0755bc25652781535c057ed5ab2ff8ad4322a8edf3fc1b5311dae6361a7395919725f4cd87ce0ccba37c64eb3618f9c5a53644ada569b90cd07184fc048f1b589eb29852909e75e7116ef96a268ea85c2bd257cefdde9222d7eda875a2a3abcd3a02a1fb470ba967b20beb54914b8b0c6ed464ba978088d7f8b30d098966b0bde82a8f1210f5d0c3405c9bc73f703134d0b6ee13326f65fa0b8154f4e30808997d4afbd060285942ca1dededc3410a099881492b5730ab7bdc2a4cfd0068f67766d60b5d4945f121459d2083334ac878d067bef644b9ee427bbbd6c9351d7b019bfc051c05ac301ff3792a1c687546dbf6a07a0cf56717374bfa1191c22b7753f6ae02392f8aac9207d1ad0fcd57c5c8b35817574b7dd90a00cab75f508f8a234eabce6618305f94746cb6a8573389d336bb67e1b0d2b6e9bd3959ef344e1eb245b522c35222813b8c6e82df48987436b5592025e9786ca63b6d1a064223bfacf59ada713c2a3116611393aa8446ea79b3cb21e96d13b659ada2d6524686fd46ec66c1b4d8f5ae7831840c9e3db64d528f83a1cef1e0a586a783f8306cb261ed9c2905493e74d35883fcb39cfc5745c282104cc3ce804999231d13e1bc6f2c022f05999fb57575bbdaf00d7a990e17dd2f8b9dfe66a637b42f58ee49ba60f2dd9718d09d7025b6061b2087bc35f0a8c884f5b67a5e18c2b4e857d3b48b79dc7cab6b72f572d22987566238a7153ed6264578424f1ce091fd05b7f14563fe12c76104d3373367af3ed3aca694a21127b5912c0b7eb1ddf9d4a9f03f660d49f7a7f0fb42797fd112414c3eba2b75a04282dcb9645191fd3dbe376e7f60ab40bb7ca1e991053a1912854a68d7dcf854201d1f2c26c6cfaea32e29d80847e6288274713d2ca973b91dab97884326b280c6f06c65b8fd25d314be29139961051a1d8699467d02b67991baabc9b05629660c243ca3b0477362d5e6bf9eaa33beeb52cf399846c77fcae11a89cbfdb2058e443ddd44fe202a3ba5c2efce937d78b9639781b8b2b99077b433189cf3b0733ed73b59bb194c9a98c5aa0cba6e71d1c5522f193defb9e31fd2cd60f22bedaf7008c2fb0b55a8dd52731dfa2bc69b40f835ae95db040cda6a4a1588a5ba4769edfeb7369c1e9a3b1cda293255b4942881d94d771b7b82460004875e71be64c582f2830c5e80dd6de421a311c5852f4912bea1451b0328d01c7029867cf9af99284cdfc1e1f0aa0d8c19ba9bc035dc270b45724247137da5d3fc4daa09e7014fe1439889968eb23fe124f067825d5f7b304f17a983580e009e0e51630ea0006dbc74a30b512cd9eb4d0b315a0ffdbfb581609ea9661b0007cd234ce43c17c92269a7519bfe99c2ca94b5cd3e7654946e67b37d4270a369266db6804336a446022677a024d44cc02cb04108292dc12f790578a0d61cb6fada738902eed3afdf1850bafcb279f18b5798d7466752c6368a594533baff5dbd17974638ecc41753b184845206c79bbab84dfef148eb7f1390f8cb7346a14c88caf540c241cad11ce8869be3bec85d029ef490fc5edacf94fa962be39a33c8efefcbb6b43960d5bc35f8fb72038af3801466aed141b50e9ac7dcf1921f7a6abaf320ff02ac34bbfac265e05e27495e6e027e673a48a874e6f0c33827a050fa21c2efa789c1e3df2ecda95fc52ca7be35dbf17ff6c73f37cb236e5131542e002913d177ffb21ac450e2542e24b894650007c36c52d90f83731009a7c3239ccf11829cf0fb6510d9924e927f14d6a06f8dc772fc9b028a8bbd2d3388985f3e2609abbd08434c46642b97240c9380a831bbafdc5db77be63a1400cc9a4f7362a689b07a77162022c6ba7a1bb9f0446a0b6b460ebdd9111132694fa5f1b29da39be66c5179849ae9720b2da0a012d4bdfd1b18b8fbef0d5c32b92c351dcf2c599f069c3b53f622fc8e904f27584b2d97d43f779abcde6dc1413c0a677dd187b28cfbcf7fa6316f0967b53977432d45944ce8ebd2e265c0bf6b2870c75ae808fed52aa35421ef55667ecd6f9d279c9b91c9314bd9411bce267d6ad52b1d910b3e65147c3eb6021a0af98707408e66bb11ca5abf5e34b2bc85b144fd06ea56f5d7f8939fe0cfa4862e7f306de069cf85f4aa7aa97c6848594f5a6dbcc718d2af77497f4b9d5ffa217fc301127071e9bc9c2c9222ba90e286506e384f321e622f05d81c114953d0f7e9626b74f4a6bea8cfb86ceb4575e5cf4fb84e9efac8291d1f4153ad3cd9a34ce0ffcfbe30b6829c0f986a4f85d63b602ab99ff3934b1e0c46e55d56eb479b79ca0729beb59aed783e9a3ccd55db8d884733dbd93f9fd7a7209fb92fcc49826b2d4356ca676f01b0981637897b3d2f90f37bfd73b214a398a8e4e2f9e5abec01d8192ca690191255dd8304a2d95a69331288bce00385f462e942f4d694dc3560a263c8ac2b5cd1d2c63b90ec67c32eaf5bd947bd8ac730da9c09ebc6888b0b4f3bead157aa9d31c2802df8ff0e4d69b7abfed6f184bf35a16ffb5677ddfc4682322128932d57fe4c32f21e190e1147d8e673ae407b1dbbca31331310b299e9f3db08ebfd2dad3158562c2e47addcbcc831cef0194ac8ba9778d0103c2955c886d439967bf788eae688f2a7459b0ef3bd16808e8d768b8962a24588d918ceb2cd1cd611b504019f65216beca212f44600cb7fac77216b7645c49f18064a3acdc01399315084dc9ea151ee28534fb31628d190bc540ac6b6aba572ba51aee89544015e6fbca2b3c2330f2ac1f68849e99e1a1f7f523599eaee22720392ea52259e26f1101614d4edae481b3783af4e99082d75dcca549049290731bbadd1ec0a93789ad5c9afe8bae44e35b3e59e562362964", }, { "0410d1f8bc890649c250a3819766f4496f339a6384e34acdd72b3a87266edd2a7eae223a372883f978277a108d6e59fca1f35f25d7a9f3aed42d35fa9b12241ac04754f76fd8f0e8ff6af88cd851887a45e89f1c9192ca66bfff605b128575d2ccc9ca3ba1ba23a0251b2cfd6db577b29d17ce2ea998946997f5c4a97a397c46024681a400a54425c071232d269adfc3b1adf15b4586c4dd7b8886f5c1023bc348bc674961ac6e221d914f432c2f06dddcf738227dfcfff88485ed45882809d0e57019461c88683919b87c45e78223c37a5be5f758e4f0dc6add22f2062bc2eb9bdc31b8649af17d526ec339f0e6fc6a41e26299c65276302f982235c3e5205ec1521625ec08a23e766577664b73d18d5533261c859c4cb4346feaf7540a56155c6c3a4874dc86ea42fd518d71221ac65541e2dadd2f8e129e7809f2835f07dfcc4128401dae2b5fac7ced1d9e07e3f348c6cd26f55b3893d4418557a18c366dcd5eadea0dd84ab95437d6f23eb9e5877fb2ad740ee507e2268c39c7186f34e5cee2d0dbba1a940f516a018f23e716a399c317a7a81f89cfabc296c432cba900ad79db67936f76e4d97874fc5f8a9ff84eb7a0f6d629c581ec5c451e27ef1ed468f93bfc68b2e0412a543d89dfdd812d9421236a4be9eb374531556c207340886c7b84d42d651557b952e0982f62c5c383e92dced21905174a5a836acdc3f2393e770d6cdc22c39575a42ea406f36889dc9558aeae5dc5f8b84862850b55bf4accccb6a8ef793d641d6b08235f70ad3b0605eab462afad1af80fa003645f4d302b03d81a7d167e9a8187bee0f76b1cfd7006b2d2b55fedad6e8db1d3ecfe031702dc327ff2b0197337d7542f42702cb276de852b3d72d9acff8a7feb8882028a5e340950e523c41cfa184b3d8878effe56742994e60240e58cbfd01541d39fa007a9f0ecccb409c6cc540354ccf35223677cb74e7ef7330bb60420f7d7bf97de6888cb343cd4fb0928fe5df5f1b018592ccfa7aac6dab57cded573b5950b94fd935f32cf332dd85b2b36501de6687612371dbcfdf77279d647ed8bdcf81fda8b7e0c5ab139330d64695d814fc6f761fd141dfb0c8f74e2d7616db3598d8de40b993fbdd272ca37db27b82aedb08bebc4a8e6d0385ab20fbc20c215ad50fab8e93975bcab3ff38667abb0545b3b3f20e325f01b80a32a3cc3ed51703d4b2826849ee22fddd5b544816599dca0d8fc84feed9f7e90caba53b70bc3f457eb1adb89fd0b67d2c0ab53264430c61d2c4a1b19ea99a9b453fc6b5ebf5fb5ab799134769c9b495c479c828bcc49a8f993c3127d5cbc31afb89c0e78fbc323755457ebf0f3344d3ad1cfc59d186e96ac31a9298e655b3d1df74b95f30fb868631053540388a13d597002f689708d35a2365e309bb96db8b1b94ea4c8060c2b165f7f19e72056409159371ac9c44f6bfaad9b9567094d18c29bbc8aa2c8b5b82735d20f55284fe68186004b4a4fb644fd52d9645b277c1dc238a764005c1d2791ef36e71786cd990ccee4571d9a9b1aec757e479cfa645e320bc33268e05af9cf90e0e616ae7f237c637a99fe15b4ea8a3232262d96855fa248920a28ec03f77ce4dd93925db60ec030a7be455ba9d08edbf6bb717b1a13c3ac1deb9821e21505c0a8971d5ea5dd8e4c9cd3a845a336209af191150ba5d9b8c2c450e3a765e8670d7f846b2461f971fdcd1942704f620a40f4204b99f9035bbd543f64b927cbc7a74f32cbb12c3caef955f169a45374e4479430e08d333c4a877baf41a27a0849ca3a157b6651295fa71ac94b6e3d30b5d160965e93d2a81b4d575cefd264399c9e4e17059f4064465b2d92c96ac27e3b221499b5e642d033992c236b905c072faa1e34495f9890bac6228330e4016c061605bbfc478c30e1b8534c49af54785972aca2d144328b0a540e3b3810a73e26acfa22f48652d53ea521875475ffade8ab50b9f08245fad753350f63dc4e898948ac7dcefe520ca47394f8e993a6d13ff68a2f78cf294f235f5f863bad10c4f5bc41c3ba93cf5e076357f0f7fdc136f34b656b1b8ebb3eed1ac429c7d4edbc902f7f4bc24ea9c9b200b9a9fd7adff0c6445ce1d2171fc031e3e9f8b8d6b448053393c8813d91333d4bdc3bc5bb2b8bff876cd29e8b92cf6f7bc727517b6f57ae031f3040b0637dfb40b8c1fbe44cfb6bb9cd0a445fd9b3daa1da2b1c4a82cb4da1fb8d525e0a4d9ec30e9aa75b951214621c58c1f60c9b97e6c6b330497e7dea790a3cd8158a76d898107ff3a5910707ae60c8a46c633b522aee83736d005de60b9abe202435f8bc4577b0eb08b7f2b617bb5a831e95d6488459bbf15919d764b39684d7cb7c9310f343fbfcfbeeb212a90d96c7a26c1026c5cb171ee4ef839785076e5084026077455c73404a2653f333e9bad555cafc1a9613387a02bb1287c380d7478238bec8943208de585bd18b448b6099565cb3ec70ec6672a778fa6af9d1b17b0970439da24c7bfaa74c85ecd8e5852e42391ab2258024ccf91e37f2f0e86df958b197fafd12f4a45f7990375f1665a14f7f5374ff7740f89677ea8660587fb80916b30629a7aa88213bbf80512421a0a37414a2eb549b81cc85072cdd87e4e69d97ecc63f974e60d20de0233101c3d475d777602b12e2f797e9237570085b0e9f48d4dedf233eb1301ed4621f9736946eadf599bfd79157c0b4cc31bc273f5c6f133a4e3679ff6797d3c9b76aff4bd8ad40726c1703c3d8b78f0974b748d0265b0a75928374f91b48c2d2b2c11d8b6e5efddb75009e4db72e562be59efb0bfa06808c89f585a43d4776ef08947a77f277526777f0b52f1e0b5a03aa560fa45c8f30e584b58ac1fc00b104942b7b86a3cdee1abea349dcaea4e058faeffc567e2c3b03e1c5c4ddc675e25aa15de1442bcf5ee972a8c5204ca5794694759c13a2d716839dda61635043bdf1a09e35cb6d93b4df3b7a00871f79cdb4ee69c79041dd14deb7754107b8fef8589d2d240ac1d8eafc52ea847263512651bbede2fccaf6da816b1b892319817bb6af9fc17078ab6cca95f03cf8426249fd4f2bf91921d39b8cee24af07a52bbe54ca7fc4422a310dbf2149b763ac0060fb2c59154d2cb0da1ad4892279b4e0ce7f5f92c189c3ce48e518ff48c4ffa9bf2b02d4792f84534958dc6bd2914ba010aa32d133f6a07bdbb87a237c7acc3ba5cf101efe947147ed4eb3bfdffe5fefa991c0dc8760586218d286944c52d0f221e0101f74826761d01a20af187f9ec1115e9e98bff6fbd7c8816c15d33c07f51c171490997bf269951218ae92b66fa3150d3bd40336abccb717e18b53e8806fff94009910f202a5041b5396d1c339e6d075bad4ab66a0637d81eed1696e4068024001123204b8371f0bcdf0ce07d79f7c917327f7138a75947846fde68665e9c767fbf96bb3308abffe7a8d05512c81e39fa8dab2334f46ab9543921ca97be31076dc7b2a0d05e90b7f7610d1a391b442398ef56cde3b18737faa8f282572389b4fb3c55cb8ae6737257708c808bc0a414bffae293bc69cba702ce2959e1a30edcdf64985a4b0bcc927c5912f819c71cc9b1ff5d6e5929055be72ea5c8c1a4a591093deb5449b7e6b60109be1ac0cae472ba31e1035ae65f3214f50ad699a077a2de52f7180addde0bd78c2698470b1af13cfbf497d243c9e738c4cdc265356543885c5b933a299f01a5b5a9ecb0b4ddfda0c28573064f6a3f142801795d66bcd5c31868fd3207fee7bd98c47e4da26bee64e1617b20cbaa34e3abbe31126b06d5737fc2b577b19d255a519397f3ff8668d0e7d401a37e368729e4b83c5fbf01c32ec478967605cbc0675f685b5eeeb42fc688216a0667e1204c995c9c485e6f7712d80d88edc9594528b1907790549756dcc8b0d32091f36d2b4009639e68daa130e83a1ea18353ca34f431c548d91c1591ccf8b25eec1f7a3c18ddca71b87bb290a5c13229250c5e193e1352072f6798ec504b3b4c6aa578737332f52baea7bc4468fe6d8dfabb9728cee93fee50c8caa113f5ed7e9b55e21e98d73a377ef68be7e4e965dfa50cf863e6285236f11ce80512c573ae2b55bcb43cf6ebabed6783c250f991f5f68a59dcb2ac13a3c8fba8dbb11c79dc6236809f2d7c4b0ad3cecd24b85f1aaed9748b8c109f2fd98ac8a53bd52f18475598d67305117de8e03b0d988a2847539cc2efad520f86dcd82c08ad4b10e490b9cb03bedc7197bcaca55526cd9c8a5a5f69f7a1697e7e31aa76eee597c386418e89f06b0b9817a83d6cdefaf9594548b33cea1cbb585e55df3d3b66f0b1a88f4b98ea4720f1ef5e6ebe4958078ea0bacb8ad776e325ccb252f81943b9b1c2f54aad3c7baf1bca0dda1355d191f69c5d8163c464898116dc89201032d1e3281c8054882f60522d3a65831bf779a854fb0c195f85aa66522386625658457e74d5c2fcf5234f226da4a579ac1f11f11a1e0a6993a4dfe5c856481ebe9d8d2363401058736f7ad104104aa03f5c91496aaba2fe4072d418d91c2787a9b4ab0cf4bb65681ad0392ef073cf2fc060692b0c0c194c8eed5558098cdfa3317ab02626159e40e5c76fd64b2ef60b8f5f368b6b4fd7ea3d2d3236aa01d9db7c8a01929f9fd38557335b926251ade1a0d47d0c1444e6416218781c1a51e786dbe9297b78fcf0d0304c62929e00744ed4e14af926313a9849b2a464048bead075044bee013cbe318920c4172138560629a0ff4fd229d81bdc7c7fd1086ab17d6efd5b603a1991b33a55ca5b9e2051b7c140f7937adfaf474c2f284489d9b1e8c71d58f126eaa451407eacde9f0e86504f7de3ba4d830199a229de2bf39014baad6dbbc448501588ceb2575db0ddae005b81ba9914bc22b6d600e2c990f7843e553ff29d8008265eba7dac7b5b5a7ba6dc263fe0e262a7b8638a81f4720622c7361554b61d7b04c7f8b133440baeead7d51ac8b77d606fd0eae1c55ce7e8141dfd68d40ae3d8d2dc8a061085b4fb6d8a06263183869154618329be6b01c2890f2b5d0a0f25dcdbbfe2ec3597d79311edb943613fd4b59157df4fc2e1024be03d98ea3cbec7186ea9f4a431dc3743b9f0871b205bc0c1b3a001768", "113b261414b4b7dfa028668ac8b0cde5734120124991c54f4dd16a87d181efe2bc15f6d0caaeaf6ad615f59ec5c2833904a34b4d34109c82e10609b387f995430e8c13d83ac34310d838af9efa32d7fed6224c0a33", "cd762390b93369f1e207eb15deeaeb0036f5331e82480d180f84a76c3e44550b", "e88c14ef96c7768f5dba9de9", "8d6aaa27892a76fb05a2e96cef9a9b4b7ae0670a12cff95f7b076372456889fbd3b9b4fb5fd98b3bd85b247f15009be2f4e7a0329dd118b6872199b314e159618ede0381dd97db28743461ace1a694c0383d8458150a501d6c45f4b50d5b1bd47e61a51f9ed4929bf2e564f201ed0e6825170027d93e482c1ce268459d2f81cab41f0e7ff281430c16b34a29b5c76630dba72ab9e751bae41122b26121d91f2af271a23e818263f46e05fdd52f319d58330bcabf66637a368c0a8aeeb20cad1916d966e5e0b0de74cc67ebe57e3d1fe01e9743d42a931cb4b98bb762ea43ab937d1e5c42eb08fd56e70e911bdcc1ca4ca0604a329c5364b262ce2de282b4732ea657b89300cc7b7127ba4a2d08c13f581f024fd093ac09c2bc245be60c80e102405597fa8082f4d28cc954a93217edffaba3d2a397bb59ee89c8cc0f33eded78f21183bd1acdce64a923dd609a0620d2911f61e81fb2c8ccad8ad9d81157223253a121ea2bc60d6a3670c563fe06bd75688572b3be83cd31dfeac6b17cf8455267b481219c42034b2252977f32b8e6588fb05166498fa37d17c2b002a655b5711bbc21175348225fdcca041b1f97fae48fb1e222c5bb46b5202191c00666b7e1b2d84aca3edbee7a97dc0f6d1330e929226f8a76c155e973c1ab62c867e1f87be37788754e51825ba31af9f4722b5782ef782fbb70c391a664f252d14e49a805e94790135ff6bd881a687f98b42da96fd34bf240eae4914488af739ec15f13f048a7eb5fa94af14e8b6ac5fae714cbef6268b114813ca2a3920a7a9d5eb506a2ca211758de292047eefdb5a97e18530dcd8410495fc42abed91b1204d9b8ba9d6aed11d2d0fa0d931d46f93f2c1a560ef9f5f7cee1497be770d3cb07c534215cec12c1458bb57aab4d95cf4a15a5e3a3bf8e650206d5cac4af3193d169f1a57638d9a50f6b7c6985d42f7138b9226451670d7359351c2affbca65680557693d03458341198b8e13d0ea6abb7496edea3cd4dee2eb93695e668c7c0901c6809b8ef434e88b85a8b22cab6508b9560fae62900056b7c5c29a8c899bed45a2b5159a1d4929476ef350101317f77f02d48a039cf4cf01c56319cbba16fe908c49ed6f3face88867c0ad3703452baa7b86fe58a00ab8f740b4e8055164b0385dd3fa44502ffbb99cdd843bc3287ea468aafe4cc298a3fc180f284dbf78aa09e0a2f7d8593356eab016ad8dc505420edd376b66598a3d0aaa848fd68c4e07419b8b50e40febe2b6b17ad07726fae1f87e86abd01490a0ce24fb57b533c765504ee0a9ca154187bcf5e6828e3addc7597532643cfd992558d63b1acd00e7aa41b9765094217480c08c43f4f0b3f0127120699b7f2a5ac07c655b6143e467777cdad4bc21d4b57da4d8f9b9a7e4523d8c6fba3614b7f7281e80ff0f9004577adcff1b79fe443c80ca9655ecc102d5df6aab2ff6c3401f344b77666c59ac7d5b92bf4f1e2322f74b75e6ef2bf43ad9e018f164ae76a91451e5221bdf5b65a4fbbaa8dc31e6063b451edbbf4965307f8e65bfae87b15f2453083bea8484017228a9cdc6edab1a28834eed8ce07430f776b916b3bdd2340798955ce9ffcf114c3f6a88bcc4c7b6f2e3842426488c340d00f2c4d2d6fd3b6263dcf7a57f5cea6c77efba7013297bd3320accf033acc0833aaa8e8f95cecba469704214f54a1ed581349878a591f9993371f1daf92e55b2a4faf8f952cf785c687a59b3c258daef1b6d7bf9f904123c7384a859933c3ac31e33edf648a1be4d6264ffade860915bd118f0b9aaec2eb8e16b2015fc25e68caac77a3accea53b9b178f6cf48d15029fac12963b4277df037b7a494cb29b1d9e6d2148531a1f7360519cba5657c080254f130a1cc3ccaadb4298d7ea0223897e63d798b4f4909577cf9b491a82de0275a246bb1211bc4144574c8ef176b382262c0e087975cbef33cc616d32e0131a9efdbe8ad3d9cb5f935d3f4f409852acca22ae2a6e7450e9a426ec3b9183f93b4b7f89d850e1c7053c661936e0cde23e831a261b319b430da45772f0fc0113679d06f025983bbf37ecfba35eeca28de5ff4815a490570491266e92faaf8d0ad4ac8df106faff8fe3c8d050ae9dfc03a01ad177c21d7b653509a80369a668a97eaa532dc9867c32aebaf89ed36586e1ebbe1045347766a354a86ec1e8b2f30c8fdfbb6c5d549e7a84db81b73fb828499c5c4be0d4b2b7ffb197133a0ee18abb5a4e371be0ec0a6535507029316f8decde30833ca47493ffcab781d028edfb91c138609baf1054ad52a5d8ccb98b3ca5b138f253d99bd556afd80f71b39f36e0d96fba4e0cbdb18926894968aa825392f12d98b6497ff85a0e4a91c97f37ba1dcad30fe688b54008b925805104a61dc22b712685202ecdb073fad9b10b5b9ee2ff781f23fd41ecdec87f85b369a304b85bd2af126d08f79d8a9e2bff0b18607a95c4efe35941c5493c94e3f2f3902e79f4cfe84c138b83c7f32d7c5a125b28c6107921e8ac92f1af7da015b46a2f9169369cede770292eee8a5f40d080ea1c267c33cb7d4187093d486dc3911bb2d6cae036cb508e81ca783ab5e95cec751e39f3038003081a252eefa7cd913baf136d4e27076251da9cbf0c7d2586fe02b62ec786790ef08fb3ff3d79bd06868eb1abd9875920e14fccf6dc144e898f578b7295fb5f4e84cbf683722ce3597aafe3195e194736fc317ed03ebbb00d956ce89f7a41a334020e1a88da355d3b47d5bd3965a290f6fbf5dfdc8c8e6347b4eb85151e53a960311582235f3b546ca80a670dcb628fef572dfae0c101bc08c80f78d5630a793bdfe402592c316227f2333b386839a67e6ee8d9396fabc9648ea656a407670efaf80966034958f4a70fe7b920c79dea3d5a0ff05f3ed0516537d51a686efcb258520936fdd415345251c9ac1143a41be295cf12da5d4319e78e1c57ce20507490e5213ca7be92afca8ec8b6a07b33571afe6940daa2afb0dd4dcc1c329474ff8e13d740488e5ced552074fff695a04fc1b70755245895a1e9c387fd9514261dbb0f600ae03f4896e795d1e72f421d8572543243d662f6811eb9402b6a3b8dbb0f32de95bb1ac01b1287663d3b6a3f52339a4f6b27789e15519b2b59f2f4fc8fd33ad1a6e4d02cf0ddf8499f45746da424ee78e72847e3cd3833551b6e6fd6b1aa98c688252b57a1d97660ff006ea1b970a0b8fc7d2e313ffd0b0b85299ded47b60cd2fe9bdd7ebace4b0c1072cdf67231a475045990b35ec761e1dc1dfbd0c402296566eb4b9462979d33c9d652a9295ae70943f38adb212b48bd8ebe82722b1712ab6a3be6060297e2aa54e7d0158e4aba6975237e7c7a1e22b29560b8d262125ff2a6e5c1332acd0f6b5ba15b4a82d3631891a01530321830aa8f2e8ab6b41bc5b5356957a4d0c3bc3eab04df7700305a95d0f9cd18d486c675c963876b25b1a0f78e245deb40dedd14dafdaa9d614fb06eb2538c5411e13be116c76fbd3377ff212eb07c5c035612e4cd7a1de2ceafe95832eff88a9bdb3595cc19287fa40b8d244afe9bd24dca40db49893602a59640d7a1b8e7475825b09cb0cee111864deba9d3d1beac03664279910accb9fac534ef099e398d7f6e3235cef7685fd1ae46e47da093135741894273c0c3486197c26057044b10faa57244721328b47e611633d16d3e4776d90309d68ce4a60d3ecda26c9f39c1c6da67ff79fde4977efc5653d79ad86c3b53090003bb72e78aeedcf4c8107185d9aa65221df4e2104640a1a083845c01000370371fea2a6bc8ae43fbe290949da4e559d3867c16df16b143fdc807616f51ebce8d05bb03c2b0bd587b95e3f6a15d907aa9a5b11622ddf4c81ff9fda4bb49d3e9577551bae649cf64ac0cfd646b02f6f16cdefde09a55e77afd16c74e8a3d777d80b7cc42c51f618a3c467968631119f11ca4385f0f5713e37ab1133b692de475db1d44fbfe9d274b9a09e673dac88aea74ba88cde8db3c831e9b5a0f1e40261281e5aea9d4dfd48c5d9e173f4d9cd56fe7fd610909c838bcbe1d6c729e151ecb4caef511a36a14b03cca7ec5d0feacb4647ea5212a11d18cbcbedf78443127680ac0b1bb65120b4197570288226830e2a92b380e32387bbcd3be2c77d6c7722054d849be9de459cc1832ec3ac8e7f60fba9c81cf5fbad37d228eba137a23227d56cd24970340f2b7599aada9d2424cdba8b50c2b97244dc83f7391e2ceba5bc0a11ba547c142126c791265b33a3db6238321a5f3273ffb01e42adee17b898153e41818b91413ec4f6386ab3dd48db875afe659db9eac94d16f850ac179d087d93784d607349e8711f5f96fd514e8d096de8b4a74122ba914520e93a11fa4adf006700e122e2531e1f39340cccbab4862708d69c117d3efbebabc14a0231916ae1ee8285727c9fc980051360346d53dfc76aa5a11fb1fc8f36f95f741e913bd2cd1031e508b320abd2d3a62baa400dc439969eb44e6abf8223b29d4025c3d1ca08d2dbdbbf9927c625270543e8c0cb5ac5bb5d504d224e66a1895719e4f975d819a95e54cecfa59ec8e385aaacbb023772fdddbe093afaf5a75e63a62d51926254e5b47da1e9b05851196644b9180734d05810dcf3502747c4ece652b67674c02aae74f20d07de2ad5993b3a68d10207eab6be5be34e52ada655aa96c1d82df9b24c2acec35e8f0bec9131c20d0ad8936880af87215611b80d07d7a741a12d8145bd05066c6ac171afd8684b92f72237bb0e4ca4aec1ec280e39f36928852d5d8d02fe463acbad8ecefc103083fd4298f399bb254e7bfa166638460b760ccf2b0f5fec0e3875206bdc8ce096274643824acfad71ba06441c74788356caebdd2208f6f077b056fa9d85aa4357e93bf064a776f5f3b0f288d0afdc51558c8f25cbee17247364c2bb24637dd69017f92bbb43024d9c773439626a02bd0cd44136a642c9c5ae593f32eada790c31a6704030f2e07f1173cbc0dabc410bf9864214c298a6283b3631acbf94b8371681ba81eed1aa81ccf258252d7f90fe733ac770b9744d0170cb554b39e6c72e05919cc237f8f4d7f3545f4d2732f4c9473c77401dcba04c0fd33efc73219f31c08dfab26abee9a7cd4ad3584730768fae899fc", }, { "9c73ac05648e0c50a3ea3a8eea70841e8e06669c1e7520c5e25e093769c4b005375c0a9cea16ec8e00261ceb96a00924a66fc0c4e4e089c63e93fea857aead8e0ab82af4ce1682cf3c9fbad23fc3f7e632b7aa169834ddd6c7db7e1e892cac93e4d787b2ed0a812aa93bfce8fef3ce30ab794743ad241974ff989288c43e1ba815a25a03acdc2d5517293e161d0c46c8858d0b32b124a6b0bc3838807753288cf6838fa25fbcf876e6368c0342d3cbc860d6fa12faa1c2b7d9fb37504e60dd44e36ce74229dfb80f1545125718dd1f78b31a8aadbb4d6494489ce596fcc2dbdf2ec22157a1d966b61e780d36552daf084739b602861a96ceb67b65b23d40916c02b2c3a38c2a59aaa266e1f8939000dac9b6dc50d1731e87ee833a2cc3cb98c57e5b680a85c1b428289520bb252096efd7723fa8e55d2fd4e16900a435986ab3f3d2bd799471a1bc07c1772ce10d1bb8805a6065b8903999f9393d2ed1a7e1c57a9e3e0e10dfca17a04143814f5f3acfb99a34712a6e0a24a7485279ef343e69d27c77e25b41f9fb833d7cd29cb6a15551d5c77b43d19feb19f2640926a272f81eeadb792bd474ae11f080ada72103f8f7ca733a9b1325b50589be2b2b3023491afec246d336f4e4277592ce9695c68d5f39c8fa4cedaf51776d7ca29ea0ecb89eaefe71e5f3560c68e8dafe7da08cdcd954d626418677b8f3f45b9194474a32f548a4da3bfae6a3e2c0a25f602e3b3a821160c397d77c8bcbd71c5f1e669213af36eeea30d48e12953071f55eac2fe0bd8fa355671fe032f6fc9214632428125a16fc8aea8a9c7fba0d7518b9a4f876349ccb9bbbabcdb2a85fc60b83ee1ddd041967efa4036e5e10e377c9886f40bc0b0b57c7b724795f843f6a072e87e532a04c21445090a360731a2afb896ab795750e5c2c33d58bb714f5be427ca3751df09661402604a09a1eca95a8344d3daa5b99d68e6e6245825704c5d4a73af197d052d7f75778917542261d77735a21cff3f75d6159a3e4b1a7a9854ee376e6b3c8bdaa1f353b957862b2efd50d10a40007026261a546124cef979ad20d8085d53e30f5736b8aebcd3cdaa349ea474af249ac53eef2653ae1fcd5b3095538de9368d307d45df2a19acd44e3b78c2da9d5d9fcc4cb61feac5dd35f66299845bc0018c3d476b6761083baf33a4621e41cfae0e0c642de729fb2d206db6a4b976a635b3fd911b5e9946fddceb6feb2d2f893b2bed590317442037a1d6dc5b5d72910160221cbecb53bc983f1c736c3bfc9757e9e05af1248b28d651f521af67b2a0d7e4bd86a0013338404fabac7b9833c372142e6338a98c0efb7130aae8e34bb0c80937680a7a904aba3be735d41af9462f17b967b13566bcb697579f8a9340429c77baa6e24ae1ac86d8d25ae3cb9112e34a7a948fd141367898c5f33c0635c87de06f603b510cb229df0d0d9a9e107de88b12686c539ed4fc54c8285afde0c8ee502919a125cbcaf4c8c89f56e90d3f641f97c07326956f7b5d87c65b689f39b8b84359ee0f14d2c7ed621ec67f5e2a8ee5faf21c805187edd95e3941ed62fa95a65473a569566d46b87c0d27ca37b6b022a8cca30a4480d392ba15701d1015b3648958cddfb614983211bffc4966ac6c1f691f19bd9fed405a02c06712d62a775f73353f3949c76b6b7757a4ee0410fd6d20071abfe46b09e72b70f9f19b61410ea67037e037934bbefaf09cff018a5c218176d165d1eb5cfd5c46eee7b82fe65ea02e3ed7b18a86ac7b139b7c9df79e1f6e6f85304ad22d97190c7ec12c651fcc835ea434d92ae1444e7cb0dc644efbc2ae70f2f94310805c1d0f2d49643d05e78baa1c54d4fd99137a49efde88dba1374c94208fb4a0ebc1a0090b043610ebc1bb08168ff5bf936ff9834e825eefb9ab73da2b287b06fa2b0ff52f46061b07c1131e4108cde478c767b749b696f3520acd8d3338842d53941282da289dd1e9a0e02aa9be0f127566c9bf2d50a27f6b6ffc9e9880bbfc14ce7eeee70cb0c0ad90fb474efa69b46123638e8405fdef65fa7e0e7b29fa8fe8696edf661f9003a08b4aff85a4a3e6d817655c1d533b834da981b8c37c38abd5977b3ba71b3f57967a471c2eeaf2f6f258431fbb7e92f91814b1db80ea775681f282290db170942bb7b04aa2a331950b74a4b6e337affb4c51c6cd4c4e13ce3095e73e4767c2731f72bdb225ff572163fbd8573378427fda194d165750d487f6bbb63e1378a132fb6ee5115e3c32b2380b096b735bdb4d651853bc7928346fe3ea9df7534f2a4eae1f5ffc4b82ae738db7df0103ba4e68c2a2153bca499bae2439a57778cfc616df16032aa8a19e26597d275d2775b5ea17cb25d204b18028eb25a053e5666ac47c6def151f7d4b68ea62c601d87bfbe04711c24bc34274be6815024d7b7d01e7dae10cea6e485348ab195a83854663cc5826181b688cc9c091dc1e0d491fe51400e20e6f2a51a7d56af258e038bcbc80e2c4ac4b41661bd33229d07b39b59f3aa79d99c1ef41974a33e02a7cacd6fd8f9b99cadd0fd6a031f070bd3a364c64ddda0e9fb94036f374171de0b3f4ee3380780e6d77d50db9d58e670fb4a364827d631226a3491a27602808141ce657ad6e560ad62b088ff086e6f03b8a64bdf7c7d01e7b19289279509a9d6d80e50aef3b05b5561e4556952c46d0b6ab8eae735eccee77e570e1360b7ea38c53ae6b8eb420e4c2663b57827228392db6e79105a47f7d89e06ecfebdd63783101d3bfb5f494785acfdfed41f8166faefdf0b49260222c4080ec2c6e4f949f41784f076ce37fc7a34fa4e547bb44e6b9359b4b95cd67d64e4402ac83973bd50f8adc7c6e4c34019bd8f6d3843bba3d7155890712e0ed5134e00db877398d86b459f312a6272431f01b057446bfb1b8053acf181bac79408c7708f3a0867a64e06d7786849bb874a6bdf8fd6daaa572d5648ae100f4318d6b3a811bb0fb709168e817ed83c0622a7e5b17ebf5cd5ecb21d9ac32ddddb039083144c93cb55a95ad72732132d54bb120639d1620ebd142b58d75835b35cc6367012c93c6772963e9ac852c71c0dda2246ab845469997fc170d8f62334bc5aa4ce23e036967674303ec6f75bd3d17d197d026de69beda70bc59d2ff95a899d28ac7e5e42f4d37233996a8e6d3b0b86b80df49ea8e145b4a6e3e39f3d6c3c6518bac45baf97cde23037709d737b242b8918ca31f90fe59ff2c83e2f347a954d3559a8e4f075c620ad36be20b1e24b3afa156cf3255192171ad0474e4adc9b7f35436325b92945665f038611e5d14bdfe7b7d20c09642323346a717f460dfe7b5062a0098be66febe9f5fccfc747aeaeff81ba08e5dd2b1a489c998ea9970afaf9aa03859073707a686c492fb3f7ddb27897ba5e75e578bd82114b2ba85525a2002927909c970a04035334b64b1169c3a923211e0999db8baa26b6537cdcf57c051c0ca1b317a5b66ad96cb5ebd57994f99ab202348d8ddeb343312f1f26ab2442b8c5f5cf6bab394418ef2fed68c3e60275e836027515b6b946e5d86d91fdaf49c2a5182d5051726840a156a8653cabda25e1dd9af693533d782caa09295952ebfe6a194fbc8bb7fc2c0da5914a506c6f31490928dc5d6554890f5eb268b09d671bb6b6d7416dd36e7b78ffc5c86b34fab43d22909a87e5239643d5fef373650e291be56b89b9d90431d8c9fa44fdf4f83a1689d59d6ef833b1ce31a44197b36ab298d53b51ae3f8387087dcb0571c340874c1524ba0d576bdb88101c1fc387d25b5c0dad0b4d309255ad5d5b1e209ba56db0c927bd209399a8a3b5c8663c9ac199a76ea4f49e364a4b93a569b3400e20f0d748adf7db46a07efc68e43802a5d1a914759eb2abe8fe3e8d67f2cd7612bd4d5a6a4535b1e5b3ad4d97e54f3db7f8512c9603d87e01160b6908d8df1b952c750071abb1565e5ea3f643f233faeb84278187ff0089150bf21ee4d13979fdae796f592ac5b88869aecc5be1c64665edc8ececc87502d36720b73859313607aaa561d56a195dd3c7292fa8f0750ddd3df9ca056fccd9d6ec900f45c1454c6ceaad4154c69e288dc85735b8cc42950a3c5f0fab2be8811779905c3ad5a9a6bf56e7141d863caa4e93e0065f229b695efb790926618b3eda1b9a15f143bbb09aa3c4b72900617793417df364185cc213d5cc3a375778117212266356e214f085d8a7aed908256c4aa25faebabc70ce913c08c89380da06920069e8e27dd867567f152f883a9bd2dcfb8097b7f065482d6d11c0edebc67feb3068cead403503c04b324885ce1a62c99af9808a5ec8b7cbd978b8c43e37b06e9f7e1ce0b31fa0fe52e8842002e6e99cdf69263d31de080b56c0cf94f77f0397fd1f77b13e17af90ff33b00119999df802c33534a13d3ff7fd0e8cf58e8f8c8bae033cec1aec7d191f2d1a39c7b731c97a67fd1ca43c13a24b9f97d92e2364dc26a1c9408d4659ac7373e53a2a1704a47e01c0223ed4c489735b62a27ec67ea46747e4f48d3da101b0863bda9d3f7f1b413f3e7f130208875e6a29dc30a78198ef658c7ca32d7d53b4b92e51f8ad6d39ecabb800adc0870b2ab0e85b5769f346ce7fc371ad40c561f9f3b2f2a01f2b8ccae48c78a41383cfc36b2a1bd41d61a39c24144965d9aa5ecc5d506c7c7cf9476085bf049942d35caefd77821ad925b7fd3a006213abc1e008114c848d45cbedcb8af264cdc5c07bc338fddd1123940e5d95717040325048439dccd1e298bead22b011ef76d26a390a68161b8bab29e8409a5880cca9c8104694e1282c9fd64f50e73ec6b9a9ffc31115de9cc0088400a2dc806f85487fcbdd60f409ffca584fb197156b40142e512a0dedea1571ebb74d6b26d3b4a59e9105929a055cf3540e8a6a79ca7ea71ba8b40893c9797e81c6e9a7999d4d382e52cac95727bcac354616ae1094552b3d0a33d0d3ac4e547237fc0cd54944039b0eccf335889f6aceb518de496e0986783c564be8a4a05bdc9c67b1e5abb480b98173ef091259d8c772b611e0c09758fceea3e59243406edfa71fc452d4450b55b8fa5ecb543692c6eda3a6ad3bfea929a18ebbe5ce2ac4754989c71dced37286cdd1512107e4e7f4878da1c28b4beb2dd9a712a8d1d61d1a5fe5382db8aab4857b05a783e98e77711c1933a7641fd43dc6e6e597bd03b11ce8e94aa094fe250f03cc92ed5b0a5e7723911e87b0f3c476d9aa0d96adbfb395a8fd353cfb5a4cfe27deeb82e849f90bdb17928b0a5702e4010f7aaece2d43772a78b325d2ff24f9de0f7bc65974d2348c64", "bf96bbc17abcd1f56a9f22ad164d25ca72f8c996f1a7a66d6effe140336da4f20460b47e1c8573872496343be35a055552ceec437692b0e4919224c4ffc8b603286a8245eff5cc148b004f6e5a54c4ac22b0f09842a07cd332a09732694d3591b8b7d6a7ada2bb38a30aa7fd5e6baa811b9a195d3a96306d", "aa2f714d3a184a9883f4199e8e33fbc9c92b36fff2d59f07a9d0d335d7476e81", "36c79f9f14d431cc8c077439", "873d0617c986dc9d83e9cdfc50b1f916626a9d9e1c595dc7ccd99d1e993d25d89b04a893c89e205952eef8f1733054bbb55fa5e1b07135787d4fcfae226737b50cafa2c11276e8708451be9b4d7f662e98ef6b705c5c4fc64588728eab1dfee22a0a92bae61828a7394977b0ae8a3b6d0126a23583fec025becf0a72a28891391ac1495732a7a4a1d43a63ed8eb37b280b6d886096fbc4f77aadbc5e441e996334d0e10cd7f3dbba9bb7efb147297986509a07735385c681e0543186dc166291edc3b4664f5c8ffb0965c85bc30ff5e7769a69609c69ebb68f35d104bafe3dbd3e2a40e13865f19bca3612e48592aa930eaee29440b4ebc1c0a59f1c54519857c929709b086bfddd6d4a30940b592be48e0067976099efe71f45f956182dbb300e8076e1207baa32d59c1afef7f34171bd66099d2d7f07b39d16d0f8b085185bf2554c6ad66bcd656f07979e8f19575a116f5c4fb9700ec3b46a3254f28afa1ed51348c1af6dba26fd398098a76d7bfa2ff195eebab41330ef290bf75205a2ee570a2fa46bbaa74aa6ba68a0e63e2731dc1974eb44794f3c89ba58cf96f7a070fcca678185711d97cd9d7d8202351ed589e0b05a7a190e60ae4aa109254a7bcf7013f8addd07a64145e21226795ff7c7b1c225f40ed7c3552da8eb18b9bc9bc70c2e7ecb10c8b20c54f04b6e27b5044a7a67b558407eb330f2083444375c022565c45fe817dc00c7d24c23db320d15949b0b64fbbaedd310e73e423fcebe6e1e98a5cd232d97e6466642e5e3b23f06525ac1cdf8688650cd366b1b7ba2a9033e62d836b14bb73717757b76b9673671bd3d3b2a56628f5a309f3b86ad32abac0590c50f7c5a22e0a920d88dc9fbcb3add08b900a2a2fae4178aa100a0e645ab428e0e79bd90baf4af2755e48262b64838a6fbc21226e323c0a1ba5703e30738fc7b5a7df9eabec6199df5ff6ad58f9df5a734ccd6509e53ecb3de1c881732e26e52ab848a0335b04b25f2254aaf8c130c78b0c9a40b60d402673ac7ec7311d0b00c45bd176bc73ad81c2478611804f59e3c145110aacce922e473ef346f8acaabdbb9f313dd3f8d0a937d0c048e5af789e2e09a816146f9ea28170909caf2572a2f6e2d0d511242909de2815e9ec586b2d12183ddbeb7dd70f32424097e2ec28b4ba62cf78f547e2057a4c050cccdf6b582172343742ec8c85e2847efb1595bccf89ece3b3ebba824d2f097b1987ec26c6e5710544739d54a714060fa91b7995cff0161415eaf55758078772c0271d9d282354e47a25b673eb11497a6ed8db82267d65ad47412300ed525af96f943c5336b1de88676dc346e7339230032463d305b0442f934018bdf0242768511d20474c6ecc82fd752c0c0ca5cee1f3e06e679fa5835540f97870d47ccc6bab233290be7a3bbd4a73f1dc7682049bf7b3cbfb6687479c18d246e3c07161df5c889ee95d39cccd989625a8c9e80f951f8b1832f6378e05daa8566477d7fe547e49ae6e822a68de4df9fc4d6500d5219c3d3bd8887bd7f695151ba378da17c2e750399f7482973510a386721c59683a86003edb9f0ce1ea89bd7bb8a25c222df7ebedcc1b56c8ce18f367b2cae720e0591b477f6ffb498c3d7ce59cabb1b01d7cba84d7180b4b2a165d4b889a6ac361720e768f2913aa50b0b5c88e55c35bb4df4fbc4460338809605f1fd445a2bcd97ec1d2f269b5e779a18c8f215bbc5555c745424484ee5436119eb8754f5e9e91f51fe715353596baa1fbb0a690e99691636e6027cbd4b7be752bc278661e2677070ddc12dccc262d3dd47160345de51359ee8dcf2f61044f95dfdaf323881b2bbff68af6572348f786f6e52d1309cff871ad58148307d7eaedc93ef037922b6092ac62171433adc4934884efdee3052ebd60ee115f76f9dbd0eab7c4c0a77b4ce8078209d23d81d957335f331965b556ebd54732327b5aacc899f9ed0edacad9eb98cb845867f249efb0e1a5fa2483227f78decbf7f1f32d060ab0c01eb985d83920b2cc24b5f9a0d5d869e980129d3b78277fb87e5cda61e340a729d86b6617b8828dffc7c37d4c38080ef3515c2784935973dd184e0a8160f84bb78bcd8a5e691760be4a4d41ed6512ee436ce24650c0e17e7d74b5e01cc39b21e21514a84db262d673f24a82cfd5dfe2a162976171c538b24af16429bf8ed5fa8e37f89ec6e7d63ea1d83ac1087cf89e8f43161f225108889e922493d973e36b510074533cb1cb22174d21c4076959e4191a5df880a8b868b95a9cb5151a7ad47375fcd87725660cc0b59c88ceb86984941268493c49b8aa2baa8c531ecf497853ffc3d26b926a379e72188e246d42073041fbca453bd558f328881c8f8d9e099e898a912530c4be499f2b32229c359ea10e0befe6d94cba5ddafe51d164898166e890b22fd1eebd5724451511dce1f8f7431d712a3f1e50fa5f609da686253311af255b84b2106b09b803e94b51729cfa0826869945d46b9606547e7e33fd9961cf15b400d0f5e01d8fd4d92a83ae526934059d4514b9e0005317a70466aa0b6086d5fcfed201d958a0de55fd23f0919ea29b8aa02440031a9fc206b9feef362a73430a4204869354ec81b6fff92eca97e7f1bb12d25228eae466b8137b4806895ce34b57dc14bdcd107fe160776b0e5daab150ba06976eb884eaa574da393af4de355381c7caa4f611a2ee70a0c78df93a4276f55e6281997b4aeb36888a6d9638cc95444047e5202f41f8bdd787f1ff44a648cc7d39f05e49e5d6989fedb194c526780709763da81a780db0d1534a466cce57e11dd3a4c0e273d9873af1040d52a90e20101e1f80ef296d45769d204cd5417a84e022b6b336675d36d9cbdb16b0cbb08f5e240012967c8067c92f97f981cd19d449084400d76adfb7c610abb73bf21e161db04debe6665fca79d71c8cc50adc3ecf0e52d07773478ca97b8e9821a5704dc58acc647a5bc618d2b681f17942c46c266c73ec211ca403a7d47e42e12c775b370cd500d70a4aac7124f5f6d2d4ca78e1c17a96426c326bb60379ceb0c84a86200f3b450e5e9aaa11f45440f5260eee7675a8b9c47fbc58cf18a651a1dc7b39a911442504f12c103054bb50f15381e512dc6e3af7b414b3db26fe767d83a2a53d7181fec8f6b196c7874befd6628b31797ee3c9260c7b7853b137893e36696e2a47277add98462ea9a0edeb7d2d3c0f2805fd7db64c2c7eff353ff2b36f4de862a42779ffd4dbe77b6a79bc9f4ea3e909474ead915fa3fa990bc82b83a670b163e79300b627fb91c4502e96bb9dde00f716ae6ad14dac647c9f7c2e5b2e505708b5fee996b8e9113a8f4f2caaf414061ee72e76b8bf47ec4f781bd7c589adebc2c267448247e30d659998d8037783494a1fdadcc819d7ad7ea2674f75e10639c3d3055046a00814ddda0e463185454a4455d60b9780250183d591c3db6f27373cd2ce4f02f206ae10a8c32d71226e7cb8d5b05909445977164983c0073434d6c0f2bb62bda66a16792d6e53a49ccb5ac3e285a6baba935f30e9d1ddb812a018ce04f29e2009ad678ba72b6a7112d6e7cfcd3ee7b058ec954a6fd7fd01018a6eba6209687c3130de58147b07bcfa02ec1caf30b59daf87db4618b4a5fad34cbc8014a7529b9458e05eccb9a77ef1621aa95513c6fa4003b0877ffa6d48805e7867dcf53447caf348228ce926233f65d553146584d6ff3dc3ed3296db9bfe69dec6a07add13037b3aade118b2ac3c52350b9691a6cb32356ad93377059fb8ceab68de38d96876d6d383db01f3cf620e47cbfd471bf6dd1f601210482f7c3bdd4c3bd37dd0a7507e1f0fe515151634813dd4ecefe97b52eda28e7a7129993b0af311abd3a07bc463f3cbbcb4fb0eb265a5835663fdbab0d8b8b5a73837ac98ced6582348fdeb41ac8ea9e36f9818ab9c0a41bac1389a6b518ea17df043dd50550f32471645791bf59855ed695b84919aa5cb688e569122786660f06e3a919ef9cf18c355bb397b86710c367362cddb0239aa1d32d489328e4bf92b3abdc3d0dacd76ef1a1efa28fdb848e708aed6780e2d8efb19a2e26fea56b4440dc3eafd796896d73fd150bbd967871f5e6ee5db58995f2f85cc2a15077d7d472bec2e30430af6891193ef03dfc7761e2b3b3b54a72d4f1084a8fc541526fdeb0633dcba14e9485b43065aee8750397ea88d9ff13417149e0fa145be666e6f4afdabe7ad8e4864e777c20ee7a2842db44dedee22f3ce2f97d72919b9ff6059352083be816a7515c48c5140a99af8e81b9e18b10074dc73dab55fae66261421629c8e323d8134f08beefbda555660a51e4b55a9ba4573bdf0396cc413145a941c4175aa672586f7676027f9fe211db87fe07a23962f5b1ad8f566f0d5b13c5146457276f307a02e1e13d00c5032a06d225248215e4bc4be1b672f1eaff16ca95da42513fc4315c7a6663f9101aba80224acbf0c87fd3a2ee9dedd1808c1247c5bebf3cb8d77377a508ddb484ed91203a438ef5ed3ca14e087102bc5f3828d8c3437ecf5c92eeec0331ed93ae33520740abae9b7bfc45f097da70adbb9b9b879e46a7d655dbf75d89773f737b66fd8a8c13506cff7b44bd85dee279ea7053f3ed8447fe79c400cf23726fae800449d27af5e342ecf776378e2eb449a3af27a40fe4a9806487b81c942bfe1a4b0fc146c971a13f83669e0189e337cc9fa2024864436189a9165ade6b864698ecb797ea05fed0d60f0ab4b92cbae36c72ccb5aa45337cc02dd086afed9e5522ecdb75ccf389fcd63c5a4abbf60908e39cb3268c76a08687588be67a856a841eeaaee8ed016f6640ef0f5acce12ab8bb58dda380696e3fb22d0bae0788c4fb79d00cfa5ae3e479dcf7d08b45f4592c2d2a7f8081d5a9398659613ba4932ebfd7382d516b2648ec4ff4477648069b9b2e4decc89547c16ab82a0ad9cf293fee5adb17cea4c95ab7b8e386dcae6acac63ad0d1d13656dfd97d5623dbe45230de597751321bbe5a03c879c303fd7a0d837d48141decb6df4f0865717628c85dbfda29df9a8a69b2c956c75fc66e45c08960c23bbbc706e48395057f989dfe675305067b3ed8d046db339e504d5b2bc978ab4dc261d8afb325c5e794ec79d63d8db53f9dd24b623fbcc202679fae8f7d39f7f7e0667b142c714b6a723996e5254ad2ebafd63c3577f8909981ce6b3eb1a6ad67a4e93c45ac3b34587d153ec5ab67a2697a9741610d5a176cb9b5856bdccb98f69421061c84811dd6660495d9f30548efaa69e36ead246d997c95bad0ca3fdc1a08b4be31b12daf211d3e29d585cdac48af8f2268ec304bb35d", }, { "ceb1f819497c0d631a9c9616655f419b5e3470fd3b19cd0e4fa556bd26cd9df57e960ec7121b2a2cb7c0421c1f84b77eb8277bf341490190ee574d1424eb09a281176a933394bfea5502077486bef23ee66e3127b732b7a58a04b9aeefc35170dabb030d4fc3f8a4c5ff194bbd0b89a379baca30ec81d576868f25755276e62c31e93a80ac322571313ebcee494592c3ff5cf3ecdec962645887d9aafdbfd62ea910af5542d4c7731283625bc9f41ec85012b42edb1792339e6cdd9c2bb3cad4c4792a064df17a5f74dcbb3dd0d90620ebba4fc6d1e1f9704dd60c798ad64d4e5077549d68cefdddaab81a7a91209b7ddbea43accb3d1c191328929dffdfeb4f5740ecbf0ee99cb9a1b73333d7ceb0b2b8f35f84307b9d44a42fe1a30ecdf2650dde251bc8c1d46978089c50d64c028f40611370ddb0b481df9624ed63165370f4788bbc396026b268c2023e0f04cd4f66e0bf439074c46f0ae85d6dfeb0ddf22868af61c8d5133097156fa61a3cf5801db5c3ad29871d336f7aa06d2a7d5f52e50eb3aee3c7de7bdc4d21f68a1776a7cc3954f5c071282febc89c1545fc672a0a1bd8eee2b769be048ab58ea12b356d658a6225fb8a55e752f1fc97ed64c2f87f9ae661514f1f56d9d4e47b001ae865a44b8a9fd5df8628d183bfbee781b6661c9cc76debe6c3c5bba840bbc228206673aa05498a8c715b0f3019f6b2d05cce6c233b5809ff1dc4a75d7f69859fcff94ad442d460b32f6fe348659518c16385e49fddee9efab2455732aedcd17dd51b5117efb2ca1e21ae6787437f48a7042d46e11be4dbcd2932ffd70fd154e4eca5fcdc57c6fa79746100b8e1485fe575a5c79089a25eb2d55d89e42eddc81b82c4f7da8bf153ff5353b7349b161911bbe0a14483fff6585d7f3c8b5c04a6dfc99db9548f0c53e25f0b16fa212f0bdd10ad2193ac18eb09972795f42b3bd3f4d98c4868989c4af7a760f1c88ffda59faac73256df1d607644f56a70303d6409c9ad716149bb58f01b4ab8ab475e4af1257d47049aa77adf9ce54fcd22b3d6ec60484da903a6991ff052ca37b01428d5916fd92c17530bb3385a805b0d57476e9f9417a23ab1c12a038b61b3a0898831f9615d10b468c3edc24448d09b8f3e3a2355dc5e069e880929eabcc97344fb6ca5587c5ac1404783848f531f1e915941e7359fedd328f7fd12b3c685f8c1f29d1a6ef7dbae3e5e32cdb251eb43aa2d2ae0cc18b3f40fb006c2778cba387e5852ec4f2d9b8e8ccd5b3e1f4781c974aca940c45d35d30d3b9584c750bd45a80f32f73dcd85c99ae107b92888839c342cdcf88911cb974d611b14b1d85a59e88c502559d6eef3b7f5addf7d307bb25c57aae669767db6d798ca887124e159b0317e09076cfdbe61aa9ddeda189036703b1cd9b1998f88325910a37ef1fc2e227a382ae635e847df8625b99eb6ef0ef10ce7a2a5762ad7d03a7a4e2b767c4df0b477d6e9601dc8e6438184f97193ea7d7a8c22f1b6fac1f0740f1beb8b68db40e0b22940cff2261273aa0be43df561b88184a9377e6a27f27942dd04abb9448b6b6ecb3a60f14dd39b58b8d94e1991cf9d3a071ba42e0e1d71eb211ca466a70fd4724a34639707feefbfd73dd9680d76a214924642a063b38b85cf30eb763fbfe889f34b20fa4a10ba214d938a5a092c6e9b73b13bd664c75b34f746aa360593c0f8dee0f328f0ad4a3e40d498490007e573b8204a1ce7a550deecfb15f18ed5ea6cb5dd95a68adfe4cab37c13b383f8273b1971580016a8df02a3f4f431c9de9e7ebb33244512080fc5852278081b9f4434109c3427441329e8071d19d0fbb74fb6ea73fbfc7c0ac1012d3a0948d94d7ceae9b0112ec43a16cb582f9c53e7eb0ad15e05ceda108fdb3dc9e585a332018d1cb19e4a75d86041308fdd8476c88e4826931601a3a5dce06fc16512f4669f10183d5a8d15bace4649abcac07358089aeb1e9b8fc3776f3239d5442d3be33d532097e13651af7c9a5b465ace9e626889800318447b8876b45dbbe1989e1eecbfb5cdf5067c71a0d7b7fba6555d0edede12f7228d7f9841dc532274f24060b1f52da6fbaa179b81ce962723f43601d248f8f4d5778c1653e038c8d27828836d562968004003810e9aa9318edf3260272b54fca2e012f6c04abe92c2e6152f3c3e973c7e9abe8c3467bdc246f0226d1b7669bd577bb317c571aa8758bfb694fe4dd17ce78f091cf6c6de3cb601a9d177128fce8d42e652b490d90c4f8fa04ddc71cac300d3dff699be3250bfdb2136edb0057af3ebcca77ba5b3ca34531810c5e2d4c5b5b3bc4e71ee9e30cac067b7706c326357fe0ad2a4bd9cd811b4e9d696bd9b4b70579ae246381210f879c769e5f9cc3cf8d70e9c94ab74a55f5d7bf61a17418b6edb6db4147fc40cf98c75de85421b7d192919add48e5334ebce2a06e56b915447fe085b7dcd677659dd55de1f705c389975e56e0338a2ef07ccf5ec3786407e8449d9011641786f1ecd4d3d3da975d61f5a442293e6119ab20686ea8cc7681010421226838a95a157e2de948c536aabadafcd4095dfda48e5613272289a8238dc945e5f1ef30075d5de096131740cdf23da1fb8b9fa009e5b321083cd93bba9271909460c09bbe1e8c54319394ff85c291814e21215816d4791f01424abbe4cc4c792d0d04db1b812f4d24b44caa76de2bc50f4d1d1611862512d87fcebd3c0b2659082b2423bc5360d107ad7b8e8ba7438ae4509105d6b618af25e75c51e272aafaaddf1e5a227f2b2a2c96a8a83dec23223cb428136a30b290181ee20a819cf52f6c03798e7294a89f3b5137693d5a8b7a0ea38d78e43008fc4eeaf6d077ebffd3ef7952620e0af1395c38a289832df391d1710ab5b103a1ffeea8c06684c03a74399cd63797c770e3f0136d8331611502d21fb883136a82f2034358880392fc3d2fc274b799e59b89f8f90d2a5a123d3c21e5bf3540323743858fdb8912c7c6329a3aea241075ae097ebb23c8cd50f4ff46b42486e65bda6beba5f4fe6dbb30f7e61b1bf690c9f00f7513c83274cd21bb71563257a20cc38da2b88c1063bd0849c8243058ee205853342085a8edb7545f0d96a6af936a3d4612b95676665eb02e72e0875100dfa444f039eddde1422ceed8d38e6c3dbba25064f8c6cb5786f9ca67712b7840cfbd40f99b1edadd4bb9a61f48124cf3b49d68bd642404eb1dcf428eeabadfba6810a4032f8ed06b38867a7098c7744d54dcfab8f0ff941ecee69da9916d54097e080cad86dd08bf53833fec4aa4399f7124586223ec70e2c31e8c647be06df9e86a976f37901e9b134e775de2a0fd53d545c5f92236dbf5455859c138b7bb1112427049d29ed4f5dd5c43cffd3113c276d9bba910879e55efe817189fc239a204a9ebe738c0dd161d10d60a51e9dcc8c38861d41ff029ffd841086803320a17ebf5ff14b6cc2ac3dcf0ce2eea9af7ae23597233599c2321dd2b99e06d93f84989e75e30a388f47079c2af545d96f270e064a43a00c76bddf2f5be5089a69a138de844216148a1eb0b413f58d831d9b8967df297455e7538442388cdda12d157fb25896c6e2b47696c76b234a88bed4f09dfd64f2e4b77627ef03049030190fe271a5a853591ee9218a0c6b12cb3f02683d665b211dd1480cd44c9c0566ace7d751902babae14cc3821374bec774d54b4b4afd5d1811ede556a7a5ad02642a878d2d32380e7efb9082604f49d51495105f827d77945b5cfaf2f2980566b28ce3dfbf1bee2e077eb067bdfa4cc28f5d2211ca99a615e69118d9391e3feb9b13cb4a2fa9682718189ec612db889228aaa3f3345a091aeb11f41420240fbb47caf567646d9e7c762d3288f8bb2b1165cf049a191db5042fa9185fcd180b04d3007c376e0aa3d427d66d10918821f74736816044366463df7cb3ac94cea167cf1daf2d1842f130295e40bad672a22da9238ded69e241395f04d5e3c3875b8294faafbd3d90ed56ff3e01c5a0a3e349d761273143686aa26d408620c7d1a35ccc430a09e3f750d3256298c6068c0fdded270f308f79d2fcba591d723ac0cef703d8f0e7c051bae5b453abbadfab98bcc297ed4201b03ebc195c2e441cfd3b10c63c08868db36c320707ecd6a37593661d70a81f30e6db4a32f98e4fe6b950ace55923631c8f95138781fa2af78d8104fe39242f1fff6942e8e782dfa0d37c863caff9492f8e5cb70046d207c4630cc29c20e1ac105aef093261d8d335456961e552ab14d107cbe14e9de912f0e5d58d16b729270208204469f917af4e710123c3bc38a4b3f485f2926f058344db105b9239829441a2d8ababf04aea615c0e350846d9bc3b5faecdbeb450f38f615f119ad1b5dc748e88107ec2fae01f0915174feec37b3e7248ed2699d0a5fb2fc785f17d6275fbea867aad815acc8a6fd3ca4ea7357d197e5a30082ad5f35a9d894c0aebb206c6487163c9cc20442c040e6aab33d7b4b221e4ba4cbabd975836e353129559d8ddcb3c97876cdba360da0e0c1dd5b0cff7957a444027db985ebefb6154453a221076c997d3954b347f49308d2ee14d1676b75ab6ef365f3de54aaf398fd96b9040253813ba734829bc78a6db59e3f1c0ab4c878a72d6b8681157919130fd3171126994dcdcdcf68955ad64af8156702c92f7a715ce6f7ddfb70f60e80c92691efbfdebc8cae252108fb6c0010d303d9027d4a5e63413b5fb2316d32fb93c3ea52a2a7df50cc0058c76c58d73f5bb041d9fb9f3c3cda9bee0c0920079ce4f1ef8698ced664ce2e2b3b86027ae2b3bcbbae5bf7ea3693d9429cf94938dd3a2763d3f53937c46763ffee6579d018358bc69182b1c7158a09b18352ea618c11c45f07fe97cb65faca535f43237879ae3e0a31efd14679daf8fd2ce25eb8f32218fa20afc586a98fd908d3fd804cabbf56dcae272328011b252dfd83e5f0a5fdebc6acb04c5540255e1322de5fce9db5aa4cdccd74dde8990ae51cefd6c1edc1879971d3efb1f94dc41b2b23e9c9d89415b46189914a229b2f3e8b05ff78c68711385a00e9534dae6f79d15842aaec575e4ee0f098028bc74016cd3f8e93c6a0cb21a0b574ee63e367343ca9de28003d76e02d0ee2b8d622cfa3615d3628fd02499eb7bd8c1aa1f34edd9c2d059c6a7c7c978a5e4f60801e03e17c3a09793c5217f310a30db1965b8e328893cef20f4a899aa8d9fa28f7fe0a733813ed7466046776a874273ecfb57158483f4a588ad4f232adec5ba4ea651822780596de09fd54b1717bf04130619979a0e3d12ab7c35d64afb8099a1d21bc952653742f50c8e1c244d10374329cedd27fbefd37815a9b3112a4cb2fc587c4ebda381b2b01fced45cdf0b9ff8ca7d10b65ce42e728de183a82e369486a2e3345664e70674a5dac174d6616d90de8e472b62759df057119875483cfbfb103041751747f9cd12bb31e91caf79eb2db1168026a4707dc618f30", "e45eef9561f3acb3672b4f38570256e8cc4d877e2998e72b022e33de8fc20f7320fe0882f2b53559e084923786e8205336a7d15f3fb88a41e7bd20767f2feaa02df2221fa7577988db0bbf61f3dfb429868688c53e130725d0279c505686f083", "475a44cde0cc931edf9a44b0c1e0001766f09ade023dfe6b59a6af800e549b55", "7812a320691ca8442767a51a", "eaa577bd67fe79ce4586f43355c94528e306c1678946e4f7a907d2a8ee7f4281270502522119a8b09b6f05d864921cb515fddf6a1000fc2f67b52d0627998591e2acf5b6faf71c278e5754b2703662ce670dd049da8d6e280c2b84d6a9b29ce28980563c40e03381a49c54608b72faec9b272ef05cfa41957d9eaf3e944b22610c725d8efea90aaac6e782848d368ffc08784d7fe37ea1effbbbb34952def29fc511fb10a1282bb0b6334328e4d00529a44de3259b522553a07d524dc75f431cc9670127c15670c0df419826617cfb5ebdd8788d5f528a9eb1e61324eac5c1746f339aae2e2e2fae598642a389da671482128acf2d69814258d83de98f186468136868b729aa5f0874fef2ff2575a1f87439d64e049e4d0637e9c99ecb7275417af654541306615f30b75a6caaa563e4790dfb28fe9f0e7881ea2d885eefdba99efa7f878925ce7d33e86d888154a1b03189429fe20af8fa3a68d65ced9b690a709031121425cfcd7e1890ed9614f9dc3ecbd0e38c6c84e453e3204978ddc1ef8d7fc6cae28c61a472d8e089e23209f0c36e80c994af771e6505e72ba90e5543f6bad6dcd31fdd468b13533a0254e44797825764ac1f63747d8d6ca019ff16fa732068ee94be382c46b168050ba725379df31a98ab81ec8eb266a3c3f2e1cd95e5f12b3bc79b8b435e4d94098c6184631cec57e9d8913458889223a2a4541f34d2f9df380f34c3e541fc587f0a6cf08c82e99476060eb84709a292f4c7a8551bda3a9eb6735787dbb9d7f1e83937c2e0e49f2cf6e0ab0ad84c40fbafc3c7e61886a8629bea816972fa0afd0f617b6340b1af19e341875e97565c8eb0b25fcf68696ee674d2abdc29396bfd0f282543d2b72a239c6470f76d3b5bff6d1d064e6e2d06f9deef2aae8a259c034373efc820f9a2fdbce36cc27f35dd6386de3b49509d0c305757257f8674d958c580a09e768c0f6ef237416fd53c31511badb2e7cdfee636508482f01899e72052b46b5d844799cf94708520178cfec2b61c8980fa7dfaad8915b0b75ce6eb57ed4a01edcb4a35c1dfcdf8d60f3191bbcdfd522a0e321ea41c2cd87a303522d0f98b82dcbe53232ecbf0e2528de7e1be75569584bf2ec574687fde67ffe9827ebbe78f2e5bc4fb368f3c9b0f588c97f7a139bd82fe86eb605b8e29cee75d07b510da1b24fd62cd2fb366f1621e7dbf268b15937f7f7ea4acf6e615775a32c90733769996dd2c5aebe08ecba73e0bc4781d33971992b2764c1b08aa972859cb61b003406479423254a01ea85a348ef249d408157cc0962d1e24cd9c426e6e6a3784dec6fe935be1f6730b01e8683d97e21d8774b2e2655f85db7149e930a44524d4f86004cd687d8a528b6ceadd890707458cab62809110ee28f61a7277ed79dc41e573fd4a59fabf15393ed4c21bf4d5138ac843e80bbf5e1c39ac2d7f2147f35996eb51a9e835db63faaa196b8aef1823ad72523fbfcb35b5560582a48a25ab770e7528e4b3ef291e6f62f5fac916e2162b3b56304287e46839858daf322b0de083d1691d6bda44d66d085ef0d0ad364eebacdd0a43a4456035e58910d0b2dacce45b1c0beabc784f3620a3e4390c345df6117b86d4fc386523b7ceeaecc21233a2865ec6b63bffba6689fb3323402119db8f0665a4730b2e26ca6411db04f1bcc78ce6272159ed2665a286f1ad7758d6d90090a6fd320e697dafbdfef575077e282b825bd64a4dbcf92d1fc0c6f795154e8466ee4b318f2d44b6f81c52523ab68ff8367e01090c2623e00b4008e784049df873a35c29e0abcfae7acbf27236adba0b913d19a15b4af4996669aba4c656c317084347ca962ac8df15cd2f849f522016eb92de4de62944b917d88200ef9aa2def0d13e5f4ae09d2eb4a2d0800af1d704cb01975f6d59768a2b50e39e78116147fd6dcdfbc08354c1b4033bf6772fa127856a4072556a9f07bd7516d01ef41bcb519005c0a3b2a04400427ec033f1b52fe5fdc1aed8e2521fd0fff663e203defc39d7546281a98a502b8a470af16cc62a6581c9985d7ca516864b799fcc55a803ce80711484f6b81591d2402bb1499c95dfb1dee9846679c22853be87c84b4547138dc4fd46b4e79ad12773a5392540a595954112f0cb1d9be4d4eb3aaa4286b6c01520558d58587d9d7f0df3a0282011ce01c9c17111d10ad61b3675b1826c1ad37fc562bdde951b43f890555d6f74ac4fbdb9abbe8bc1e80bb6d52c13de8960a3ff8f65201265e82981dbe39e0d65cf3f1fb6c56e11f9786210383d0150a5e0cbbdb52ca8b2bc45c12fb572657380df369082685b3de9847d5014beaeef815d63e203cc911061eb53d89a312d187f9f02760bfa71083fb643f5d8c324c410070b7ebde250a185e7359837899bb1568a43fa3418f39c12feb03b148b924bfb98b99352b1fbad3f07ac8e4302f85d1fe9ee4bf7507972670ff8beca105cdeb037f1cc4f944d6ca869d0281653de5ee93a7362420fdba8b01a375ff08fe27873655953ec1c00f53613c6ab8b244e2fc1b6babdca5311428d06f57aa4882dc870165deff75ba877dd2a04d1799f26ebfac97a1be53a83ab77dbc2cd4aa45bd779f61b1283eae1a1866ec8a9c150dd0a4deceb2ddea1bc0f4206cd435600a8f190b999b952337d9eb2bdeb3aba2cb2e7000319056629dc1f00901f0880278509417223a3ea0919fcdcf12bff0771c7cc725bdca292068478ccb2e1f35ae8964e0601789a73e7e7c1769ba53f865910fc3d0085c922d7f7849d27b6e7503d521371351f9d7dfd5afc5df0effdf6ac49617fa228501ad72154a73e07781dc4b07765dbfa721d95cf1dc41e161cbd34fc7883a25e3ba6b03e504b2c3b98c8b12ff629b965c2aefc26d74faff7f784baf09c3fc38c487a9d1f5818261162f97e9dff70cf42eb5dbcd7bebb66d68f26d917ddf2a3efc0db1e3372b170b4cd18da507e44c467943f73648dba74db1053b53f989e481c3054bac22c6342fca2c26d30a859a1312e9c353bf921f68136de2b1589747bc765153927c31ebe749dcdff98b5da84c4b66085451b4c87fe1ba2142f98636bcb268c33f7b8c2b96a6525298814578377aa189dd73d5bb27ec5cd2110d8751c18a3110273df2595d4c3a00809bdeda70d86c4a8169b7010c9cdeabfbc3dd3266518226d0ade9bcc4825f18198c854de329fb8fe456dd3bf35d89bd9d2384f3f3282f6872351a18a2f852bf173ea4426de6d01b3ef4b4685aa82df7dc45b99617a8b8c8a0c65a2237b3eaae8267e1f6c453f485432529d973924a080f6a1cc2cc18f804f53209383ce3601ad9361afc331707be1c88b4370404cb7fe0bc538df04adc5c8d9ced94b4c474b19619a53dca3fddb434cac09ce10c0293fea04e8e1b19fd3ff3d174baa988d91cb604fadc59ac0b61f4f87bfd07eee20f7f3ffd96766dd6f3555cd48da7ecd71d2fef34ab082678bfc4dd007669b3fc7a937a5a46269baa7e4e4e43eff1b2b847ea70b6c6c23905d6fb2fbccd944251087ac00c35c2eedba30641797d36ef9d3cb1afc0e3e8930f5b605a847ee77106995bd44047294d04350194369c5a7bf246d1108e1d18d9a638be0c051f695ce86579db613cd8922e86c683c91800b9a34fe6339e0dd79472daa662f78f04f0151a3acd18f11faa4e1216222843b521fb998c8490ab8bab27fde36395b456501307d07b484b453b189fa339282a634af30fea99c9af8f877e61871fe743238b2cee6cb69dbd17d574b5106ebe4b0fde4ef42fab469a5ba7d62c23b67d857f1af6ac981c320db70cdbb6be41bbca60bb7a159ee1c85cb82e0a220064359c06c660b75de6b49839eea68c80283b75d9d627aa4500c0c0f21edafe4a2cf7ee079d5310479da06ba58b142614fe69cb236c51447d63db31cdff91485b46325c26d40dc6d608d46a5e2fb01df06064a022ddf6d5cce0147d5b2a5aba5f9fadc5e778010a924e00a13e21daeea2cd330f45536ef4f42c2e77be00bb53b3f9a93d3eb327dbf30baccee5d26849cfad654ff3ef2b035b78dd3ef42de3302e5514551a968a205b823dffb040ac9452ae3efb43219b02436d0761ca11470405510e534d56caeaacc40eaf9c47a39475adad266f5ddc813e71223800dd46fa7c02b078353f870049806ed7ba57b40b7c3c6272296667500c4b97dd2d7026698b6bc4985bc01be99e0097013a2632c71740888ffaf902a02bf644b38cf9a42528880d9dd142de967cc2ad3e1f1737f0cb8dc5c59c252496e8cfe4e53c82f4a28d9ba2bfa62b6415ba3e5e09040d7f3e3abfeba53e46575e8817ac5eca806ec8a84c7cf77c9fa86c9dd2940f5b96b25a92d4a8f894d4717c8f80a62a35a51d8511f1e822fd79e6fc27cc3f3097d9e3272447de6f223971657ded9e660ee4f8836359742ce7616fd0ca2de6656c71b212b34b8edc71ff36bc84ac4af58eb1adcba4b2c0cb31468dbd2c2b7ee6752981ee1d152c4e4a9b25b2ce87796820def34b662381806d2e4fc77f0b69d7a87de43d94d62a6a6526a7f8c588392890e96f9c51bb58b4f438eb5d197477ce9b160d1c898c89ab408b3c1d648be93b531a5bb4988592c5a8999ae3acbe586d947fe6dd507cddb92dff4974ae17ab99aad5aec9d07b96bd29489876f51afa67570e86b69321d9e565d86001514638403f86666dbf93f18e0a62bf65db333bb85a3ae12d8411aa3c2a423a29bacbbfeebb8a5bafd90436bfded16f992232360211086a3084d9fd1980dd96631820a2cf25c3ac5c19d164cf5ab9a852399491962100ca4fd640146b7ea5460b4fb9e46bf8d23d508a4eeb8a3e9fad8249ece3648c2ec7705a7414eb8e8d602549204cb437f589161fe40de1447d14efa4d738b775d0333526c845cef5ffcbaf5c957df1d8022176b56eeb198e7ad2dfc3d7ea46b125ed432cd04c77efc011a2dad8573345080d7c3cdf5cc160fbc86c4ee1959ee1b8258056b0f3d9343c22dbb2f7858c5f162f08cffdca1acc866aa68e5f1c00b74f66544e8a61e429335adf6f73e32fa87e48e1adf15bb6c7aeacc93713dbc31cdccc9b0e52f922842679494039c395cc1d95eb97ae4df3bb8aba9a2584d97a236f87cb22f00c0a078b045044a5c456e22b2b94a76a559de2672c880660f9785b76bcc2aaed780e05212415c6e73880ca110654ed155a1004af45d5f15ae8e5bfd4817440c5d3d5589eea2c6c344ca0d85d91460638b37f877ea4cbbed35ea75678ef2335a5922cc8541987cc256c8f58045028d33a1c4899cc32265c619ac782ff998a478996be6a0c5b102a664831b395a884f18e77885d860d6b236c52a8066d2ced25432bce79a31b23117f405ef4ebdf3517de98d288f8c3baf04b63b6817c46c14b646308e9f97170b7dbbf9d1a36480338d8eb7466df56feb6baef42cba75512954fd7e33961d247b7393726e46c6e94e156d5776a89ad3e288554470ca0bc4cf4d2d2b0c01ae4fcafcb65ccd6ead03df1d4d6577bb", }, { "228eabb5ad8b4ff13b10d13b27372bc2152dff149859ba47d9c89b741d4a5340d8fff5858a4576c55547007d7e2b3f94583ea8f0976237712bd2e5481c3988f5387e7ac2c3f18718388795b7b2d44b0a13f3faaa55311b800301c9203a511572cf8f349280bbabb9424070f415bbfe28aef8d20329ee842cef4d4c299e619b6ef1cf00718aab2accec9ac00155be2903b6fb07dfe98b0bd8d8580176b99ce4aa6be51cf59046c17ce1817d363fa63af5a241d48bcce064a438651af102ff9c6de4b86374fe24f1dfa66e16e51550dbb791af425d8fa601c70c1bb90e1a557bfe0dde730b0364eba9d2018ee751699ee219e13fa8874070935b29a1767e1d748bfbe796fe4b81a71e823605d39fa4b5b885f4610c34d1a090fa4106785e7a035a629958ad1b00cb9d36d171d575268efa1bef064fc0a6dfbae8e532466035a0c2cef96fe9f93b872f0cf804811e927b39818189412868fb104e2d56ae62f77031f0df1ae91aa11826991ca7b8af22f130a47a72cce36ddc319b32dffd294f2e192e490249ea1a6f8437173ce6392d16dda888a98bf685bc91b89b8ee1eabdfb1806fd61f018d1744fe8b03521de4bff86d4a811ca2ecd5be668e9c752a6c26aacc0cc9dd89d112785c25ca6a0a7a5267b4e37457c04a0626c8a29be30ec28ddacf47a84918bab164d07bdedae62132ab04a6f2c4e108eba9ab878caa4a1a7509521d427ad7f3dfa86fae8345dfb5e0d46ce3a94dec84f7880c7422468ea74fe0b4825b8c762b34d5d9b82ba96e0c7dcae01718ccac0044a87476ff031e3ee3c2c13f5f375a841d243c38cd9a354b6525527de1fe7e36a6e2ad95e5bbc4c97e85f8cdcd5341da777e03451838807d5dd2eb4fd15976783c140e21cfc2eb3e58e40c16374de0aecbe3e3d41c64417a472cba18762080a2348ec3f441bf229a932ea0ca7c816938655d0c81b14dfbf86aa600d0c68172fb0046ef51f601ec89309d43ad1eacd583f9d205bb1ff1a37a97b44b5e35be4945f52897eb2a74645b01a7f82054cda44e9fa9f9af9bad1a235155718713bacd08d354f3fdd95858db0040fb551e9f93ae399d5dc53a67e88bcd5a02d104dfd9d824cdd5fe262ed9266fc47b7e640f2c9d9c7a62c6d24b429fa55560aa254a824a0858482e771144d6d5b05539cf71d75bec3a22be75655e1ababec4dff9472a019f6220067374dd49252282e4945a407084633ef9c88d14833bd95335107d36afdf56a642cb739bf0a61ed53a6915baed78e9d74166ebc492b517c7c594fe6564550bb7108f43012551e65fbafc0a9874e46fb64b5b7aee0082a5d617a43b8bf9473309c6761aebc7f13b72ed460b522a6b0875b67353c705f99d1d9dc899870fcc90c632aba1fa9ced6d7a2368dc4dd3d4b38a5807415e00de6b9ea70525a6c1b67d04521efeeefc6c591fc5256d990a1123522864a029430bb7ea00dd80d283fdd6d61cc5b509221e28f73386803d97a38fb0182fd95b3b91353c6eb60ef2b3d5c8c0ab8dc9cd9be2b4cf69450d00e88cb0f0bc9a4be82b71148a37237ceaf945ab94c365625f58171eb15c1bb244a87335550d813d28f241a3296520046e65aff3291555786d7c871ec8a2d10d4b44429041c3cd6ab60f0def742de3d28393c5aca92b150697ac15504ee66d8a2aa01a6c63d7c719d6d4f94af2ed1d8670e3231a0e481095e425e6231c43ad36e3b7a3478f6a61563f5aa13237beb8a891dbb29013c325f7f91c1b055fb83c436fdf8aef49ec457946e6ab7e955427373fd9c743acfd4b9609569b591ec79c7ea7276de103a35a4a8a05c91f59e04689ba1ddd570b18ed046f785d7e4ff9fce7115ac814fe126f781828877208ddfbb2ebc919e6d1f6eb417f38bfbf22ac9633f75e58e560b85d88d0e4fad9b2e68c9ebf9675819d50c30c8982bbbc2f41e02690390bf0e16979b24e648bf15b18800aaef58c3c465f38cfd1e47bf1266c17b69523b7868d2138cb95c4bce0dd3ceb7c2267b868b6e12888d5a489fc0091b295b56a1c328b54fe1119aaf1e6d7dd52fa450b52fbfc8b84c2200ebe209060b655cad288562786673121691809366af37b76567762d1fc24f1fad3128b43c8d10e9b6954b2efcbe40124fc0a5b670dd6dd544e30263a551825282aa06be3817a8eeacf31ca8b25cba011d60b78d3d2462810764e4acb566ff371005f5481c9d36c991527143af2c44cc8cfc59c920bb4a281f2ed4d494d30ba4d900edf59e23be2f763072255cb6f1e8b24ab1d305fbfb2429cff8bda303617c034e71a17230d0e860420dbcf9fea4ab48557e4d50797179496936ec6c97686fe6d9115809e14069244d251d4bc9c8931e47e06ec051e709ba1df526b55d959b37a6f3408833aaac80cfc9cb99915eb7d83e26998f0da2492b986fe0f5047b2cab6e6d33a117df21e6a8ec7f394a3712885dab176a4d6095e5cf75dbd3f0077e5e74b1ff8b902072380cf172562884de852ff5f07c55856224fb3df8eb44764ab9284944b86ab6f176a863cdd0e7ab5616a14692f6cbf41bc63113b27689fc2fb145736aaf2a5b26d2bef3a2a59ef8bb3f3e4d360a4251d0736482e9ed7e189fc48c0973b6649988228c2ac72b23826a61cfa06b11f13c8555be6e433d87e20113eb74c94f0e51719a7b38c59eba300089d06b9bc2a72017668e5aa3153ca4282718f1762642e7c1be1f865cd9b65c6387c8fe496f1e60d5acbb78c2f71cea1f35dc955b1e7d1cdc9ca339765995d9e05dd729cdf58aa2a1451b633c374e5b6c2af1c8486ee4250a875e80e1f359c15130eb1e2575c0c7badb2af61378527fa24347ebb12c10bbb36e3c94619556b2c641d0ebb691b2706cdd667f55b8fff8fb46e3ac72f3682661a4bac2391075ff5145eb07d69d77437adec2d096c1c89208ab3e7a9ea6a0ff4a5bc1846b3683bd7c6ec4520c3c95861a5856b0191e4221c9819c67273c66729728f6035e79c0dae8842df4c0c27ada1ad18b34efcd55b94ef120762e87e8c5afdec80d5788e83f0d1533cdd7aea8f27f33266e007b274f6d48c59bcfad607e8b298be2b17322be88558c60033452826778f167f318b660607bfb2f285cadb385399636acb8f5350d819511b5e7931c5f8483529d3ab3fdb5ae2dde0ada918f1327c6c0dfbbf5ed3c8afef171910dd0169022b3cad5b08084dd5e8eb8ef1ecb17e48bf69f80e3db0ae1cc7b73d94b89696e3c3443ecb4c7ca12568201744d1858d90ff759f2d264d49edf47772bd0e0990c14dcf8c8a4c2dafa44dc6e92f4c66b03bdc4f68f28ca2d0811a433e184cced99a8e5614ca83c46ec18b47e0c7ae91037ae06c6d6d0f3dee19711c21cddafb5869416d23c5219296acda7774891877f3f8d46155d39f43ed10500ede3afa26943b83b800b54a9752250ec6ae173e920002f365d692a9b3a2f9b27124ac97b8e81b70e8c0bb7022d07ee97e962810962b03fc019695b5399f77aab414327cfc5dedd51e99453179c42ae85a42f8e06e0cec6f937224dd019c77c5a0ba32ad08107216a9c758138b730bd5b5f4b613f192839514a8621634d9dbd5840e728c1ef4a2c8bbfadc376dd80d13dcb327ce55ab536a43b570789f5c5e135ac0af79b54232613d0e989ae695aeb358c671ae71d508b58a793e19c58c3d204cdc9a021ecc634bcb0bd6a1917554ea3bd688adab8163260a914fc01d7ce05a497a5c5836cf9401cb6aa35cd008470bdecfb97a511c905badd01bbb4d0c05867661debd2162beeccd52399d5a70a929405293916f33ed0d03f8b850f4bdd77b1fb6283118d71de629577383c81cad086f4099ce7476cb787f73c96431a0df4156f7826fce9045f7e7c97bbfd618b845595203cdc8df4638430fac74a07bc5f773486731d8ad29c06695704cbe2882077a85d543551b7ba81b181ccb93d2b3071b1a38f3c762b42df8246aa64cecbdc772830ac79e766fa99e8c65225f28297a32526df9b51227bd368253737f013ae18435a912bc18cc4a95216ce449865e8bd8bc759dce9d4af52f9e789eafa37023e91946952202dfb7243cab7db2f9f98bb66f19750c547a2bf2e2ba92862ab66f33fcf465ffc41d23f0b891a3b28b3f68ea48dde6ad4802902abd22b0d7d9101bd61471c5d88ee9d9477b7cf9f6ac52e0f520c79278da22938745446f1e647ae478ecba416b941aa31f979d0633efe72910bebb8988de1d0013616f31c5da163eb6c07022649ac57422627a5642618f53103adc9918f9992c5b085e10d2744f9934bfbb994a710d6cd387c325e94278f97d5582864f1bb29a1400aaf674ea8fb99a3b42e4ac50418fd804a5b1471eaac4642d4aa338fd3d5d0dd84372b2c32c5cfe7f319acf731a9787b048cedee3833300dde639cb1386c8fbca4bae8d67fb7bd72d1696a0212e27e166e6b04a79e34b47c98502ed0bdbd8d61777537f72df569fe5ed30071b57e8724e98ccb88c07f0458cf32298cefb6ed672b255e581ac756789b57e950d57174bffd3f47bdbe4b168e7e3f1a6df508d4202d327947facfbf9526a9e5fc1a5abb179902d4584deae6cb2900391e080d3f3540b87c3a873ccfaee5b4aaff0e6516a867ea00b4d5e680fee6b91defc65c240614a1409bdd0f49c2c4f3c1d258d77abfc17a749660f49547adb236730e5a7a22fbbabdd8ca079a8efa5b605332db12f455868ab67a1ffd27d1339bdf8d150189cfbf6199c6fc27c05788138a63267eb8ac086e27286b4ef99ee9d92cfedab5ce9916675f128f206a1733f47a597232067aa12da20c7b9cab6575d7634f8c31e9a29948b528681f3f9c13b9f585ebfbff8c28a299a43e4409b31b6c02a79eeb493734fe5f9c1d9e3830572eb54229b5cf525768f695acff48c76b4a6e0936b7406ab69f06d33d3f04946db9d7966ea6e8c50ede5abadda28149edef5223a6938d5c32933070d234043feddbd65c81be218f9d7c497a1ecac30bb9162e60a9bbbcdb4fec4b212050610e2b376aadf58b3c9207860d2650d0310ae6606a8f1b266b6a13b68c3306ed413224abdf19371bac3ea1b964f28996fc70f666ff118c6a7c9f2108d327f5145919c03832f754de35f5979ae72130e39126499037d6fbb3751cbb4843b05d9dc91dd5fc1429da491f72e3069313ea243933b47109af247fcbe0c70f9024ac5a41815655ab309fcaa282d03596ba59cfee0e40f7bd657689453e98d562442fa4c585f970b6983a581b0b8eb1c5e780b3f5c1abb326213c6b5fd440c2187066ddf55f4eabf88804139392c45979440c6f05b7222bd95e963832d7fa4a4760273cc075e8b8feeccb917e8feaf7d3f766d9ae880487e69bc01872ba62b91b8af5dbffdd93fdc95e8f47ed793fc070a5991f2e9ea61439662dab218f643c1959171937aa160008a548f51f87b58f2c4fae5aed556f26bb9cd1dc2b3518458e2f5ec5d974c6e11a0ed639958cc8c1db771cc8cc8bee8727bf6452f47c9782acf548856a0e67841c3dbdb1c98572a4fc8e6cc8195a504019b4930d302a90dc20d8628ae6c90e0206cbb3d05025744db4e115cd3b650e5519a1624acbf226ebca8875b05183b2584e65289f8b9cec3f7d010cb9671a0e80bb70ca8763f1722d79e8decb6b9023baf64b5981e745c06546cc1e", "ade72c2ea29cf829ffe99c2d63840b2eef9b51a9919c02128347d2e88e9f063b86326928cf6252ce4beefbae7206dc61a22d0b33c90d464d551835e3b73c1e3d6e88663deab80c35a607e4180ec079b0ee84e3b7922904e7423acaf976e837", "43348cf32211d7daa300de8a4218543c8e3c7373ad10950765c39760f80b733c", "e4709d225a552e90fb357413", "562050bfb40451f27b1181c389508550a0f46b53d14ca73143da9dae3d3d2b466e9618db39e3219675d2b6eadded7dd9c741d7c9bf3c5619a521189607acbcf6b3964d469d966fa134444aa06d80749c873f0f976e0c5efc5be8d00a2729f03eda6a7b8630575df8b3a19388ff88daf0d00bb3e7c35a525ded90a4511ce815fe6c8904406cf72d7bfa14ca533566f7b54268835285c5402e22a63f98b5d90c86dae0a76d65eacc1ba85b3f5a1499d5f3432dd5455fab9e8bfbd266e99283c2bddf9b556410956b2f061603d1fc91194766f90da841699ba7da3d53ed5abdd8e98034f8fe734446d92b458a731aa4c578552ec1ac5d1baaccc4153a67b48a290602d5f955d61a08436b27cfb0786a80afef76e1266310a42d90feeb3bcc40ae5c4506432dcc92f7e5758ceaf277255401f5c5f4b10df93a249e38edd9effe7bacdf7fecc451d3b2cea77c9bab0403450c41929775b8c0ace46f6928f4d9cf3adf86832d298ea32b236d3201464e2ff506ef01da0e1e389e26e2b3ddc553b369b48d1aa5dd43edd5cab065e276aeff72a4c43206063fc7eea3bcc783ba2221f5b615a7a43a75cecda6bca5aa159e9208bf66af61e2e465c2daee630c4c62077ea6ef0e8b4b4e272d4e93a5f5284f9da463e1a60f815a8a31698ecdc09dff2b62f00e37aea5fd4b07a110cef27e12466c1814d3b10017cb9b8e12f2f38f10cbe31296de2570d5662b16639fcdc05db81e0d48178d055ef873501148d00903ec771400fa4873c5579dc3265028f531538f6dab1e5607a15c8b90cbfa4835107cba6f453bbdc71d08c7e423f58b44be38a9c8a610469f2551ee6177edf639cde35fe8e02f76b7ed106d691a876a4fda3b42d8ace3e0d3d4e026206c5d7d4d56fdda9dcd30fd7b74217fab3c617903f1aeffb8363443ed128af94c391810e327704d6f655e57dece97658d41e074029823850ddf7c5937af41c64465046d8544bba65c691ac69121bd272107f7eef8cfdb6a25da5da16d1033cede09129d51f6abfe63905a6fba9a64d7832fa35825447150595a60163af848eea878fb31a5fb97b1859efbfcc8586eebce8cfe64386461a9b88aa5efc1db43c64dfd5d4a45aa74803fd178f9e16a3f59acfb6e13a564d645cedd73890d0a82fb6dffeef527694a7cf2a89aed9750c3675a67505bff77de8d046087bd39a85c90aedb085e99baf04c7e3bf92e350b332da1b8af85550a00d68904ca426da61add864496d6ff442bb0b848e9aa463bb0c2085cff1a83a47d6f702bd184cfb5c139752754c8978d27b58d364bd88722b9097ee3a6ae28eabb14ca7c31e40461101e92448dbbc63b55cfe56efd078d0058c5e6146c73bcd949c4b3ec9f881b9a5f7b41ca83301261e0c674f2d35d96761baa00ce0675c082bf73dc52dc726a3e605067569a372d2bb47fc8fe1e74f00078ce6f352a6d9d97fd2834670ba3a45aa6751eafc7ed6694e1e07542860c8ea516f296ee901a3ee16b00b40419c74bf6db12c7230325e85a918f412bc2f6469c1a13a5aa77f028e327749efd05b91053f49d9f1edf49aa552c58c68257233a168db60ac55b4086ddaea275b078869cda7b69493c4b371b4e9c8361357a7ac7d3d3bbb464c960addfa8df2b208b21b090d540c440241598212d33273203d484e0930e22469c2a8e866579a4a2b3db8f8344dbf8baa1b97be0c4d976f6aaf14cc09ec52630139b894b2b6f4dad3a205a7b286253f1522b1d6e43bfa37beaf06f831c6f0945cefb2593b9b298da13b0d910582086c5d7e256ed4067bfb476dbe01bcddb437d46ba716d6ace2ff9912c8e460ad33ab3d8f97b7b08dd4ba9e01968d1949ff85b4b9d5b8da291fc0f90ab1eab1d246f67d76092b7a37528ceb388dd76f8a8f0aabb7490f02a2c8bc6498cb26350d859c466dd611bf0ceb81a8b7899c67742c22697ccee21c4963acb003d15c1a2078112bab05595917584e417db3872a0ff0a29138bbca7314449b19827525340370d7e48fdf9f7c6b4a280e78d00775a291081a5e78e7a00ff915015dd5af5f0a45690baba8b1b503bf85f326c23136f4424be4a559aed03fbc81400ac27a33dadb2155d1704950d98043dcd86df1eee78f3f266c4d14deb8126708f74b59aa15e8b497c6a52924a473f999aaf0abd3d148fee8503a1568efec7bfb0bd463402f563e4019cc9c9e1eb498aa54dcb659f43b86df0a34de4e51ec558bbbade3d69511d3fea2baf44f67e85ada7398d7f72ecadcd9e981f82b0743ed74bd33088ba4cbc85b0c99dc5382c599706dd2d51aa9f470c25a98e7e8248dec216a155495630662bf6ba0b7a4baa2cdad30e9ce3e1a65e3c23d69d5f946606ee8504dd70830aa5a8ddd84f10e064695469727d2efeb46186c9d3b7a170057636f05b9ec4c2de7d935fba504a1e7eddf7a5a95226b253b0b9eccec976ca3c57599850db40c27a51ae755c1f30d392467cb74e5c8235861d11d0f8461b0e1d84f5718d64ea92da62f4de184a6499dba473e82b3d197305de0e494f118a263237c7b4c0652327977edb427ccded35552c00a5804b9557ccf2bca2484d9da2c33f6c1bbf2c666ea10b4644a21e3905e5c4eb417ac3572e783428d23dd7222e75c356b99e8183d033034e29e618c90e66ec2f1e9fca47d82c1cffda8ad14c96045159d9437e91ecef41d24cff89009ff57e18c1a422860aa9cd31dd2a85b07422c72a5decc614a9742e62a4988f394421b6918e51c2412d749bb53b1e8fed7b2ef0873ffe14fa77bc366bbd5fa1432be465f5e25266c6c12b55df1f19b1a491acfc5c9019f122c422243d751d8eaa8ff721397915171556e999b34425f7d3ad6f6c3323b8133b4618c65ac16cb5941edc979472734bdccafc73c08939c0b1e306ae3015faa9cfa09ed6560269a1dc54c2c046a12a178144f4381f7b6fd3fd2d28f778d444d9f7a0dae00ea96c6969b78ef326a962d23275f1518f0e6a2469440612f3710b53538fe99a6179471be8c5b2d682ab3e9a5126e41ed6de000cd9e92fec3974e0f4cb2d2245d03d6ee80d6a793b16efa829d75c796f34d4e918250f457703559bb48ff78f0896be1bda403b7f1fd6a319d68478ff70d88238f2b8afc7d20e51757bb9db3bffb35a8040fc0db913c4f03d48619af7fd24cb8986b3e139058be3cc253b3de9b3bb3f8dab7b8818638279b2e6a0c29cfe16fa7250d3c74362ffa07e2977cf562140fe28afba8f61d81f7c73bdd4a2faddb00752bb049d0a57d05c6475c7387e6716ee31974169930c9fd830cef138659cf56f2212de185186c3d683fc6b7fd36e7821f69d0de041a569765066dc4a1934870a7b80f174e8f9e484942e62404a42b21658467873865ef94fc262c231527f39e82dfec91215947b99567daf75c6a28073ee4e67d4307e4b35b46f85433abd9812f35438b34598ff3b6dbd60b60747ad64565391df45ac80b272d0141702ab807fa27c6a6ba2f42c3facfae0c773940cb2943bb1353b41298258bc0d07542b69483e17ab9ce709e4160b80a0968dae9af8fc7c0324c753ca4a11a6df32dfa79a87b445c988154bb3c503e6884cf6d8f5e062a16b4ff230fbda109a6127d35e3bf2b29bfd3b18ba275af773b1981d603300035e046ef023d51874aa105d136bfcc9c7323bd0513a6b2b397ffea71afb7a8d4695411d86164917099eef504f6cff3c5cefb88f23f56c4ae3e2b09a3f353fa55630f45f06c29e8912e8c3c4f493f25eda781680585580595bba43dca9cfd400d9eaf5081d2c6697da59e012dfd0b875336b88fe16609c2e9876737b9afb868ed52417ed0c6b359d582d585ff82d98edd4e63c6b65cf43d4f69eee2af4819157b8a433966953862d1ff2c6d0cba382644a1b0033ddb7be3d1fa9a204042d7b821b293bd659dca980c108ad1db740800b9bd2fc1a163f9b4066f7604f160a7910bd947cb48ce6c81e680fc6571ff0cd12a3ded9c8cd560970ca5cb480a70a8322d5072edcd257604eba8dcf55f9ec97ea2b14fdcc72fbf615131836fb14e42b8d7171d0a06d2fb3caec2e0759e86b0d8f21e312d9211ed7fe0b48669934ffb892baf1db9aa457c07820723e5446420334bf6479f2099e01ef8adf273adfdd9ed0b741931284515d69c211cc2efead8339e450b13be71b35c36c1f00c2b8ed0cfa9792e422912e14b5b1455ef6abdbbec0035480c6cb69d21321d12ee19d528dd48f43b142cf0502eae5304ce52b7fb827552db9ab885b93e83d56a33346135aef11b7e48efca7cd52e2499a7edab0bd0562862187ff4599b2446bff11c37181092fbb05d0e05220ca6bc37f529d6599e8c29acb9f25616c27df291d4fb07430188e6470df7002f73cfe5fe6907dab0b4f90bb58130fe90241c29c6063a22c9f45d032b282eb92c93736692bd5cbde2a17552e942b595b08e6ba0c91a03b9079e9117fbba8f26ce6c5d0500c69bb6e22e3562a50baece49109c2d42b6714250665afd0f0a7e951182012f21aef4b917cd434d9ca22661437608e32666497516be34652500def6c28ef8f56f2273de5416142ce9606faf7df92ab779ed6aa74cb99bb1bfe758ffd344e1d31f479807326d1a7b98f6811e275545d69198707b0fbf027dc6a5e4815d62ef191535569a452c27c4e25ecf139df949d70dd5935bddc04f33b2f0bcf5073c51fc51c15067963a20569b5659f0e7413b347d6d5ee38a92b7e6e656c199149f07ebafe5281db6b1b2ecd9e0384b6f5a8e27ecea9a0249c61b16564964054f5f9621471a98de132e102f518c1419829e2ae2c8c5fffd1270f0a0b33a383437b0034783d50bce8bd7420c059d16364eecbd55b6ac8df8a70382734d8127f4f5895cc9e508b13c000ea053ab59b87ee639745418ffc566ceebad37a17b842d24d3423ac3f086142c622eceaadc4106f8c90c5dae1f52f407fa0bf1e6bf9385cbcbf3b61006ea3b1e66b693ce704577ca9598587f41e05d36d1de424e0e51290a5f2e2f99f1960c0253a046a49b19eef249ca2dda2af1e8dd78411088eff1e9c23c31bd20abd4fc9e7eab19500827d202f76270fe9f90e95309516343e0fca48e5a12182e91c78ebf2cdd4644629afdc90bbccb77546cd765135910ba1cd8a3e3c00fa77e585865e898bfecd06c01a0a4d7be483801099c61941c4967154af5620b171b426cf229df59d2944ba50754140c3f305c16956953be376fe6e7cf31a2e9c276bb09cc24c4b86b2b26f039b0d8511853adcb7feb8502e7641a34e3242bf2c538006bb1983345ec3cacbf219ef10efc1681d52e6e1b1c60bb556b6b8a63d1d1f6869077841d1b816f3165a35833e33d39a8c6e62a2f7c482c395768fc6a0e3cbfc7a1a6d64da53adad66c8016f76eaa73df1b8ef83012ecbe75c92a8e39b48169433f951a539b28a034d5fdd00639a5e3e17ef14dafe869064d130c90c68be4d5ceddabed1bc94e97e2cdf7313f780cd6e175a9e3eba3eaed896fe464073fcf07ae7b5bd41d58c3160f66ac95a76fdaa7a8cbaebb304fe3c8f03cef927a1182ac2281c3b32378813b24bb99e42cb0774331ad78b74d46b8ce48bbf4ef8431a82d4240edfd61b910c38570ba0bfbd4a41665117e6d5f5a97908462e62d0b76160d06aa56cc6e17aaf4607ba8263648f2a0077e306c25486f5f39a75", }, { "2f6210063cb3071b3d49339185c2cef8357b08ca826d8d1acd852540c16540f1c850f70404fe1f414853d3cd15a1c64a1cce149e3ca1b80926de4ae8438ad90bdad010decf2f201782f3e49794aae1b079f54eb59607bebde508a528927e346d4e444b1d736b34f65e198df2c36fa23c64f1f1fbf8b0b8ddb85d054bdb39b8297d0347f16f7be7cd9474c058e36294485386434b36fb28ee582e393367f15ce5f5a3d6641fbd31b331f10b1554a05da726a0f35c9b1b4af3498426b17582966a266cce452900f85af1046f45a4ccedca6ce02607fb70fa45f420f66aa38cd4c9f8a30e21a3067b940aebdaaeb7c77824a79e2ba20f26e70346dd6de96942b261e5c08288c7fe1cd1e9f680a0bdf8c46497f007a616eea95ccc17463559f8973eb919c68017e25100d9d1a196ca65fb615502076bf0b0c8bcc70ef22006895ebfa2243fba0791bae0625b762cc1718d1673948264454a200c58122d5e9b8b1e3eb05df8b7eeb297510e0d7dcf7f0be5f29f6756e4b177f109891e6825a9866359e35b10d20da7231bb5a0ea34abd0264b377d2fe9f420f27d3e5aa2e8e00541c46052966ef9b989ae5974e2054409507b867f647aa057f7deb19ac6929f0856005aec6e53a5f702fe6be403afed532b73d38fed73e6e551987f182a1e20801e7a6c8ccd1184cf0fefb4139fa166ca15395902ac40e7fed8661602853682a3b0ee307dffb44d0ea3012142a2880cb7c166ba6ea6a16c7e0882808db8023068f060e5ef1432fdb8331ffad6a7078d686d47d613e94291f1c4117e7c13aee4030fcaf223fcefdb300ed606b5dd931e4adbf45dc437eeb5fbff337812e15c15f026071423f6ef5305c559baa2ecd8ecc7cd498b043740ff3673774855d45d45fa64591d5b4970600ec91ab1b6f39d7dc0e709c41e49c355bd3b9d120ffb57095fb127bafa971a086135b917285794e83e9dac5ce76fb1a4aa4fb6b94a0dc3a9beea64b8817ec1e2b37af9dbd18ec30f2b6f6c12df1db6896c6c43b67a066038f0c4f17142b254f62c4dd1fedb950d07047919e397d06d033cb0bab6b61aefa6dee01720926b16beb9e8bc947dca9b8143b565da85d2dec182987838b267de9047f5b0d961c7971aaf54ae2c1e4aad61ff123c84e41a4566b2bd9e64247cf46b72a444d36bdced1a309b464ee5f4afe406eb68eb05ae51b76bf01b906c0ffbdeb440b11f1c9e3a4c3a809a1f7449047b356c663a1ab7f286a70d16141d11f2d151a4f06d422ab97cab539c1f9da09ad20c000c27b8fead5f0cc37329d466fa260aea934c154dc9c0a065df3d057a0f117a1c38321ae59226a8054f7d6b49a3753436c249838b0924f0e861f5627106dd8d3f0fa724a1cecda71d4a1267ed889b234ae4a7d5edcbc5d52cba389dc0152aff24d224c6a0f16dbd3b7f242807bf4b51a3f22690bdeb66eaa59e8766b3b265d784899d247a0ae1b58a06dd91c529e3691b09f9d9f55fc39afd4a00b0fc668880ef25a46a30861fba8cfd4b51262eba4138b41a2d13ddc71128c8c1242e49a51d6f49879fcfa7595ba4a4adcad3670b0b1b26382f03ff402bc70150f54bf513ba3e9a590e41b269e55616af297ebb3499e16cc8e46c0810330a602955553c0f93d668a1181a0bfd7021ad9a9f68ce39493b012da70a3dda149d0369f23f788616e0272efa322b6a54d804f340d32c890e2eb7b538f48f4c9293b584d22d0ae80d321607644271b81a76ac5b49d8e457069b0c3e909b8a222e3fa6016cb1e979e300804742f2005c68acb7b1849c088b3714c9c7af54e9de9390df0041c87924c8fa6b0aec6b6754171e059cba0d27f221f0b9d044a3aed8338dd8745651981e4b0329376f908b86ae9022699d495bbe3a148f7eb73d56eacb2e5e2180f63fcbfa680369f88eefa71f1210bc5b6b7b957f0a1437476a2112998033197673e470dbe7d9d476c97b95db8b5136f6cccc75d6e0ac1e4ace30e34e64fcc4d7e135b2c80e863ed701d3b28c25e982f1b5f8c895a4e6df7216c3c07abf8551a0ba0469c88aa7a08c7b5218a03b9b91f0935985373f65aa56286ad0e7ef2288a926f172b098123c136455b3a0f04590839e16bade7b6434a3cf048abe2612684c03dafd9cec39af508e63f07ea881014697bc24122058b5ef5d3fae835216d055f0cdf1dc06a12c95041d13ac9e15f235d11747f16ffce1cc3b8f508da520e395edd471f3759d8879ba9c2558b1188d822fd4739ed0546b0ce3bb9988db7c1dc8518ebbc62c4440e6e0653f917dcc13aca1864b71dbb67dbe7117474c936414e4f3cfab1f13eb05f3504484ce11977ab21ec523f97ba1b7ecb8fe384b634c30561cdb752fc67a2316bfa7e4d03f5f825d24a556a0460d8cfe0cc54a6f117ac52d553a5d1bb48031732716436675c5c3996b1939b127c6b0338bfaa29c7467cac9a127e455a715c9ce2b0c35a0d2f83a3d1273ee39399e6cc4980e610c752bd51652b96bf9cf34c7fa41fc9b13f5d55007483e4082ddac4675baa7822fd257452411b01de0e5e5da26e17539d64a89dd93c71d15a4c95b1a83039cb2d5f3f7fa04a817e48dfcbfb3de34ecb47f7592123caf27e17982fbfc8597af5b8aa6558f4e6c73db69328e47677afbe6ef8df82c3d1f0db6a108b2279f61822908d7b856432c32ac5ec0f3c53befab2a7ca356b9c2636f646b228b0a830d348be4ece2271814d477d4c73c0fb6e83a338b90ec4ef45cb25f7e3d6a014a9e8d2e8a6f55a383291a57f15667a73ea1daca31c7182523ca85a107efa2518d2f7f179ed4ba21fed479ef2be09669817133b2384bd85b155dfc1c4c9e6dd9ceecf06cc1ab8ebf7f07aeaae7441468b5471aed93f248a84f44c59be33274b11f651de010ab9f8fb24d3a99914e0147951c34280e7dd15ec196f9a4c86e55e7d373c7e31e6672d1b3ac6a45fa6c8c9088c0b8963d89f4ff1feea3e85cf9cf2f6c97128afd845bb131c6f62b3282bbba42745080fd457f1d3322058f1bd4be876bd01269546d1a853310b165926c1fd4e07054deb5d3fbe8f6007711d435994005aba95918c3df4cd390b165fcd139dd418ebbf661b6de57b655698a8a02ca8fad73e8c536c7110957c36e5494a831d536eccb97a2a9ef58fe58e2885aad170720ffcc57c7de601ea1cf723577a30aad8fd544317e33897c8b6c04e5191bec391ab990e197f10038c0726d371677e4a54c28d7ca5c6046e7cc4acde565b91f7f72af6109a0614160d3ae97e9257b8f71a4663b00c681e793cbb478306e97b0e04711eae7722b4845dadf2fff5bbe71ff24acffea2ee67df99bf62a098ddae9d4ebd3bc5dff04a2d9e3d1d83e8f493db3f63c9e24231b1dbe1147c79f21b0730c842f6983330c5c17dd34556d7e932074cfbe98f2dab5b0ebfd778a1e28fe2bac2d942f61a08b787ebfcdeb3d600bb130ca4922a4ffd38ffc4a1a1a7218451e45da4da67ad81ef898ece3d54cef877cb9d09f5dcf72eccbbc06e62f1e2b4d64059b0a807329780b155ce1614b68de04387d6108ef4dd3ab54b9da72e528d6eac3e16a360ae3421f3f23808a8b5e8ec3dbefcbca3c9f76905850033d78d9283bba9272c475b4e3b4d7643e62c2cc259ebbf168f890de88e82f8b26a7654ee31fe055e45609c70ae02b4942ee15678cd158f4c9e8d351d102ddf7a942458c6125e1457bea0d86ca38cf0c26e474b2b5cca77eb57ad0867cad7d25efc2b250e79396637ea3e948dbb855029cc9b452955bd04ad5a0d0514d4d773c0f298df7bc235a3ac64383a1fbd8a397a158e936b3ba81895a51daa89f51e4ae7a71a53794ff715a42f4fc3dcc9fd56df7bea4ab782534d3760e7b15605fc4dad16911656983c0ab77bce9445bbeb1537c55fef57a32c8f1404306a0a2ca7b73348cd99d0f9948875531cbb0ef7c036cd201614c33293d746c44140e0e8f82421c5bdf2bf428b249597df949fafdb5ccfe1618323f56a6ab9abab9a84a3beb6696ca918af244d34cc1cd95bbca4a87c860a0fa9ff6a04a905b0338a53f230bd5ee9c60e0e0332ca200c15dca0be5936b858d0a7b2e540b8958432e9767396c55d5cc35b60062580023b5cb2f9a5e9a1feba59a19f9a5a251e9d0e8500955a5df21da95213ced2260a2ed8f3d4b295c36cef750c89cf21985c302d5cc577aab7855409a912dbcf1d0a9800df4aa692a78607a40fd6d5a82305c58fcb3d2a82b27e8c5b91681aae62a2bf31ed55c494dbdc38eba30e83c6044945df76705228eede8470369f2e9941ddcb2f239fb3ff6bfcdb0efb5ec50f981adf0e8b213769ffbbea364b08cf8cd69abbfa2a6fe9865cc48558134a57bb5526b9d047e14a379d246de82d3d64f3c810ede280c768dd8bee25af287d5a8d94045ddbf5981382bc716ad9aedfcd66e0ab496172a24efe80649db8e1e83675fc8451e22c6564d8d6dfb285af7fec802b35f19dd8308c68952a11770247fcfecc4ed0e8a445c17b1573f0b4e3ed350f13269ceb572943fc435563459d5044699f1542335b03be6077af156b8c5a6a9f71078ad820cec4642427a9b187ee1b17036d5a5e6108cee8a7d444342eaec3afa64e77c71d3c2b3153d4e2dbb30df2b66b4d14cc45d3a4eda7e911d697e5763e23ee05311a20626df55549b8533c6ebe79737abf472f9cff08bec590943bdeb819d3f923f45b81f9a0cba1f3f800a261842d10cb4cbdba456c7fe5f0abb4a8b58891d97cfd6b669e2708922f1934809d51a1589e5f12e3bb82c9ac3e7e44e3f6e6cd63d428da624fd2f46eec38ff798a90d228efe50c9b67c63796347c8a2b53478f27605999a03c8e1f18b70e92419f646a7f49670aa12d324751aec17d0208fc296955b3098241189af8172d39a6819415cafb107c1842b369f174d6f37dd31cd728dfd0ab10f93609006342b6e4d6ccbfd1ed2bea2fdf5411442b04b1fe218916f159b20242f80b535b4e0a3024c6eff6a40bd0d3db24e51f5ff9c14e1b4a650ca4170ee70f0a3a5a58349a7d0b7a63af86347351696870b95231f76d8c5c6a20736907726341dcbb76672871d18c2157c094b929fd29d34f5bcaacd82706f89a60000cd341d98eb830b73a12335b69f3e0131ded3ce12c98bbd960d2d0696d40696a13ab43925374498d868cd8f070c9039ea6407fc2d92b9c39fe7c935bbcfcc5c0980952fb7dac79042951f49a1af828b138a87401c4104bc28cdf1e39dbd3fa63dd4d5f5ae9d85f032a43ad353bc5e6746e5a76326ab1f4e79103116ce70bc0b459200f32f85e461291e347dda92e421778b849e37a3ecb0b31ec6818e828dd3148dc74313aba43cc9d8b9a36a9dc4e229488060eb6c109f8ad6201958adec6d3bb3b04e5e558a272d44cb98e18f7a0ad8fa6ac3667a62f150830aa930f6166baac6b9081b44304988fbe1698a5b746255de26bb5988aca90bb6523cad68a7572f615f4aa58f932d8a749615cf0a7724e99de042268ceb31433e6df0a61547d576a6201b36b348c028ded5f7e94d1cd2eafc141088ff42cb3dafbbe4c402b93aa9d955df8d9d9fb57c75ac65c2c837acc44bbd4d4aff1888aed46c73d625ad7fff035e8ca0fe411c73ed8135b6b8e17a039ec74e9de0d64cb442bf8a676c0a666f68f21066332cd921ae0ed766f0516a8e19b82cf98e78add0373737a3419e13aa902310c44feae5fdf8bc64e80dce772686a31f141bcce452041bf545b908ef4a2b000e7beaf378e2afdccbbcaa42e330e5024400cf2852d3444718", "fd5008477b0855f6f2486fd4f74b9fb4f6e19726c6996bc66893183bd76054d5b05c1c2b64722256ba912ab2dcca66d2abfdf972966438fff7513acfb18ea461eac08c4e32aea4ed3fcf9f1c9905ee4402e7b6984bef974340d212f160b6524b76de99a98d3e96cc0d35e8a63ad7ea3cbea1d40a906c4dd03e5fc19e1513e9", "390a5e75c9ff4ad38fb6205ff47f209294337c1f25ff54a3c01eee8e1e220257", "8bf183347ec1ca4bceff3374", "19fa2641519e21293094e9d767ee1237f9e0715dc57172794867c3bbe2cb647f9b28a8d3f85c0ff557b91bad66f5ea16e0107757b0277fdd3ca05bf47c19bcb92a958a57e8c142a51af29bddb20af84377b6db65f77494e0dc4d2634a776b3a5d777319873bc0dacbbd4b9ebccfae849fa7e9769cdf54660ecca0d5cf4fa5190713726d54d02b3a3f21857125b8a808c0ca2f99d11dc430ed5113ee49ff8f00bcc08f0370dd510e8100e1285659a7b2c7457a6049f2af7786c4db1471ce5bd164e11c7a2165e83e03a135ae2b3429f82f677de044a067e99e0bda2d65a7270d629c00e1d528212d3aeb2896e58ee5145a93ed06a9c00705ad5c5988d3a192304c1d17661d45257c5d16799ef70771964435b12e3b2ee9d5b467c3b1992f45b7a59871b40d8daa1c280747ecb3d170257b91df1f549ce6d66455b5b6f60b7c6e95c92a67e20cffe8599ceb183de53f1dedfe19bae836447af8e053ba419660e0912cad064d6125b9e978e8d0d5f28f8a4e43ca3cdf2d4c0e9a11221d8184e9eb6c90761b0beac82d0d22793279aedb1c7db3632adbee323bc3bbde4801152694831abf5676979af26af7dcbadfba1cad1306b635840cbca76c558b37db0803b4c12befa27d16f21506b07ade4a838d6beba1816eb29ed5e3c4f132a752fc747bd9ba879156e87e6c1584e911da9f796e1fa4a055e427272559e4bd6d0f54b8257100f8a55d84c27b702bb1fe2f995425c85fd48b0a0610db5b39f7a5031407a12dae9f508b21b1378f14952d1beb2dea81d016b2d9b7f1a67b814569b69c0e619adea02a8683242d63a11d3317d060e5b4d85df5ad73127541ba5314715d187990735aa81f438f8b94070ec506ba536274d98b766c1694e54367891a602b99e370425b47a70b819277a249fa429c5bbd0530267f987e6022f25030c30f3baeedc0d13c95f3d5e4b2b87465d179a3a23b9f9e76a42ceea55226ce072f9488392f40621289124d786109d2498e74fb37e2ef466fe8bf3016d96e34204c32978775765aa80461cac48518157f86d59f6187bad4ee62fba1ddbe166b29452f4a59af1e057300c353440644a8e40ae8171ea028be2fa315804abf518847c7945e8228b7766cfdb08d3a3116b59aab8e94b6d8c8c9ef442c2dc7f923bc2cd3e5c663baca7dded976bf191fe36da16948c89c385fe71434f4aa5dd15fe0e925d2459e3b068b9d82a9cc8b8f9786bd9f5fef9baaaf2d67027d9bfd58bb2c58ec7c746b747ab62f9242e4b53ed14d6fc75f5280eca0de23717c97a2293826e19cc8eb47f946421516c349dc4ba49225b91e4e868874bdebd373700df1f3792aaa140597e58b88f90e163397dbad3941705b53d754e3e0c9003df836a7fb8d23f40362fcb5f3947a4281b24240be4ee89aa8e917b194f94345eeca224df0adc15f22a617b6427f29410bc48ea3f92216163785723efc36301d23ed52780c6fd7924bcfaa03269b13582b7c7ea9c0e4a451f38a469fbdb585dcb7c81452da77945ebe27eb26ff6e8c7b2decea289aac5af74746dc257c9bea44a0847f02c4f586e1d76f39d5bf952355a0875f177a666d1d354ad86ce5ec0aba2c2b20cab050eaffd31095395132f5af80a2d2d53b77bda49f948bbb37bdf31c8a690476488e14e542ff6841e7fbfc2eb84795696562d079dc1612274b6dff362567084f793f0bc2dd8de23392d05aeeeeac6991c9f74387153a4b7da94790375e336a00c8293bad0fcef2dd1880e7094e2e53f738247c860780ebe308410ca02ae409ae720e841f48c9677acc6e7d4ccd18c219c400f8b7e1257f692e09eaef96802b17a1cb7d93eb81d3bfcbc7af4cdf05b98e22556b3d1a8b56d6d83bb5f5724696f8f329839dbe477483ec3c09fa2e0628faeba1bf285c224bea3f6cdc7bbd768133c6ef1da14f248cc3b819b196588811b073a7291817bd1e89c65760435d8d17cbf9423744a92143e0f956e2977b39c54fdead5a57f3a04a0facca01bbf44d3b1fb9c4fa83ae1046985e3f26aa0a437999004dd8adc04c5111759849f919b93558dbc559173a23b069b59f800096d9fcf077c7640f59170bb9a6fffe64778bac272365d27ea62aa956559e90edd3f6393cc8775597bcf7d91990ab9511973d948324a27261059e93f4b5dd2f70caf12e1a08e0493cb05588618764391f355379578cf94dd33e616136eea997ec11c0d4ff064ff51a767e5558433a2e3a9a74c232d8e187f47b8cca010709eb9fea0dac8f1ea53bf18822e154ecd929c83b0eac366e30fffbd5ba6a46d734f58d26e7f5df538e18b3d827884aa857a680823131bcf30a76f1a555bcabb17b02b53aefad96fe76f7312da69719434c580d3ff1bcdcd594e6375935003d5d732cc577e11ea2abb1d04259f50aed4c3af9866e8c4a52a09809046ee330f05c4403acbc297a9416c5208fadb31ed4eb7a3b01b87bf08c75cf44c2b0df84df30872d021d6567ea649859268e5e1b5b6405e1b41e350a32c1af13722959c17c01b52c42241313b26b25995a1c89a53e248488724d280647226195746901929501df36d1e94815d7fe6c4ca2731f3181293217f71b9d7f59c2474856972013924ae4796db4cbd22d8905a6043c959941ca6b556c53d1688c439036c715d33a47a7dfc2fe40e53424c5093020d2e85e4b04aa4c704ea5bfe5a2384878da38319c59d41d66b6add2a443d9ea11edd8d18fa41004251653857733b388b453943eb33df93dcd5d549757fa2967ef0f9a5105836c48826c47fcccb2d9bc349032b286962136b848632bdcf186a08cbeaa52d195efcfc3a440bac154971d11ff4994f293b14fb8c3214ebe7ab8b3d0f2fe0b03ed7b145fafd7730a173e3cc1847f0cdf2cf629f5ea81a07bef716b1a67dd9e3b7a52fea1aaa7a393f53b5bdb5988df78a57a9dad19a8253316835acab8a6b9a9fb42d97bf29b2443322f46de386fd82bd3453ed68e2370c6eac4497b1bde7b42d569c452f377bd38bd50fa5a6792ef5c9ec6c647001149b86fedb3e2f18d4271e9cc4801aa16ecddb31b6a795fecabc613bfbc8e4f5636d71e74595c841fd11b6a6bc7f169317c1added56b82a71fc36d774bb4d661685363e9da5fd2e1f357006dc5b5bbf8b42ee3f869e75a541586fba558a8f490d641b78c27368b9b4c2db046354e9358ae9140e91cd95ebeffc6c0d2676a3ff4ab10d463bf32bed97023a80a79df191ab9858c43537a03072a17c30b1bd99efbd361590ed6b7d5b0ec4e2326fa35904ab9a48596f44491cbbc0112890f9386ed04dec30126be359a05e99b2b77fa2c8f6b7460a6cd590d71c73b2a1b23312ff89306b6e41c76ddc0a099bfa79498e36ae5cf0c560b8854dff32d2b690ce0ac4aabfa723ac6f2e97ad1083235196b464ad67fdd649aec01695d55c8b4bb198f30630ca635aa5a1915f3718341bcfd8b522f764015fa5479004d28eceea7fe67df7ee24a97a9708d528b89589f1899f13242a0d00f7464c3cdfce213699340e754533b934f4a8410224e111f31cf8e54d7b5e90cd8c68bf96edbc8d183894deefdf4fcc1a83162a3f6341dcd9a9aecf171c0df28257a68b1af1b67c54c43c3cff27fed89cc64bc46e23a49ec74a9efbab7981d9f0a018247441e4f0f5b5f68ba9325582f92de4cca4a5f878a0c5c387581e64324e3246d8f3205c838a29f1abeea24446e496421f0e742d411adb55f70272ae4a992e825a3d327e44b8b3762b25aa451d07eb4eac0322b431fa676462632daba2aba7bdeee1b438f051d21d4b1897e2ac2f95ee7c23f9996a805de8fffb3b30b855cd6c5b84c011accf4bf94d304d944079f04b5cadf8fcd6751c22a0f9165ab98998b2d89e6514641f1f3b91b8c0bf057d69c3d893fc4e041e06a2229e2ee58082ffb58cb920972ede58483287d0ace94c1becef26a410b93e4ff402e61dcc574b790d49679f18f4e2004f8b7cc357faba34a80e56821bb5b883d1a8b49c6605002152f270bbc36bc79095644e29ab08cc988deda765d67e4fff12b726d5de135ff9d0cbd9d5f9d440e548836633b93a38330d638468b59a32642da3375cdf70b062d14b46a78569c24a706e179baa2058dcae5c61fb6cadd9e015b017f26e9dbe3e6366cf5f1ec839aa3bbb21dd6c9b8e910245fa95b09b7d6cbf08a4c6c84bef257a70389be962dad14d97a893c128b73bf6580689e540d004f21edf8403f36b1ad7c9a2e83ffceb141af59700c316c8c1e3347187f24819c2ff0c9f9a2360dce354f3374374eab1643d2d8831310a8e3ca6768200ea7759822b82f7027cd450479fcc7f6d04802b15735a137ad489f1e1ee78434a253a9dd16684ad58fc91960cde6754f82e8b38edd5e798fdbbbf8fc2e2380a4e21dd94f8c1c063b18f29d8cd8d89f65deac5640799d4ca2caa29c1e72ad8bc417490d11e4051d94956fbc74289857e5f8e9e87b9a2d83074a994de0b10bc7782f6650cfbdb8c835c81cd88bdce5f04ca939b3c5cd010d4dc5d51224fcacbca9851694b8bf55b22dead859d023eee5a7ad3436a912c3fc0284456d5d72ea5f1afa8545c856676ac2dd9a057028bd3ca0f50e7070fa74152f13997c95c1834c3e67504f1a4165d2b49a96919b88f72caed60f56ca7ab5a3204fb12ad3592c725fdebb048732fc189c7dfed185c6c184a626e07d7356860d00389862d5b9701eaa4e5f7889e6db0f54633369b8d26805c08471de8fc3f8fa1fb0b0711d9e015add5373f7f8b64abaddbac3399c756244b1b07c579d33e4967e5e0cf16de29cb8a7efad07ff9039ca305772a6e45c76bd9b77e24949556766a8b8425c5e595efb431bde4ee222f9eb3fc2d002a1e2d14db2b23135266c942eea33bffd30eb0218405373240e0cd3040436ca895093bf056fd001c00ba59d90502042e6e6c0167105051628895c8164c9ab959400898309cabafdef12be53604fa57df44e0a90a81bd63c331291a93bffefe809e80db0679568f6e94e0d8e2edec0087c35bcb3c4f4725e6013bcf197156cd9d90612423348123383e45c14d27d8833f56ddb04083c069fd6e282fe69c940840f5f747dfb72ad72fd8cf9f3ded15c9e2f4727fd60b4f40e95dbe77a89b47dde7d5326942600554905d9dade9d145ab6da802643f2081678392609c2fdd1b79dd8caec137cbed315374c6f05c0758070f3bb17e23d81ccc39c6aa89913897e487fde889c5aacd422278f8571641cc4f0a93d9768aef9e45d6bd187d1ba637ce0fbd3c573d6778cf7bf5188c00dcdf13be3fd599143952b376220283e34e014e83b214bd5f64eb0ecb098ae8bef883949907cc36e22ece60b893b963cfa73d120513e285aaf70ce5add34edbdac60b3aa7b385b90e339058fb9b3cf984b06f79788016035c5ce490f2de7995b98a8c1c9c80f29603ae2b7fc41886663163e604275cb085f8453b27f4d795b9bad19ade2f98a1c99b43a7581bd991e5d0e5e1a6e713acc522ba9fe8302658a9782558e35436e714ac6bc85ad1d3cd008f24106901fa954f5fefb61210d6f8dc9ff35c480f1d14e59c0e501917a31ee9d00c6bdb06a00af5a8b08c3928cc5f37476248223627cb77eaf0e96213cb0a13e97d3fe9b9814d462690e8d68d02655a32fc271ee73db4f88a33386ea88a5857e15a28d9b3e3a96f00c7cd85aa53f9282ab8c8ca6d6a8afed43aa87fe7fc1ad59b0f0db2dd25c20af96e8c282c19fc883ef01a4060398926a1c82f07bcd3bc314580d7636b623b7bad8ddba05850291a6344df0f346fa4a321a85ee3e9c", }, { "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b", "0942e506c433afcda3847f2dad", "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", "129039b5572e8a7a8131f76a", "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff4b4086fbbd1b6cec23e45481eac5a25d", }, { "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314", "d3d934f75ea0f210a8f6059401", "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", "129039b5572e8a7a8131f76a", "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f685eb7731024bbf6794c3f4c7c5a1cf925", }, { "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314", "d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9bbce9e525cf08f5e9e25e5360aad2b2d085fa54d835e8d466826498d9a8877565705a8a3f62802944de7ca5894e5759d351adac869580ec17e485f18c0c66f17cc07cbb", "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", "129039b5572e8a7a8131f76a", "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68a12d0f1cc99e132db9014100d9668c91", }, { "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9b", "bc", "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", "129039b5572e8a7a8131f76a", "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68d1f05b5662cd6e04de896d3ef5dae4149485a5a2093ff4ec74b20b5e5bf8e61b5c65515938c202beab3eea5a498d2f32d4d00a24b826b6efb16013ef54cbe170", }, { "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9bbce9e525cf08f5e9e25e5360aad2b2d085fa54d835e8d466826498d9a8877565705a8a3f62802944de7ca5894e5759d351adac869580ec17e485f18c0c66f17cc0", "7cbb22fce466da610b63af62bc83b4692f3affaf271693ac071fb86d11342d", "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", "129039b5572e8a7a8131f76a", "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68d1f05b5662cd6e04de896d3ef5dae4149485a5a2093ff4ec74b20b5e5bf8e61b5c65515938c202beab3eea5a498d2f32c38dbb37d04f8272e741da2802c54a9d9aaf8ecf38b36fc9ad0079523f6a4abd5281a22697a3180bc02662a7c13ee23599d18e5c48300dbb831509df4c172f53e524b3c15124a87ac73e5028cde6c94d8d", }, { "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9bbce9e525", "", "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", "129039b5572e8a7a8131f76a", "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68d1f05b5662cd6e04de896d3ef5dae4149485a5a2093ff4ec74b20b5e5bf8e61b5c65515938c202beab3eea5a498d2f32c38dbb370a9bbc3187cc260ddac991f94ce4f0d5", }, { "0fb826ddb2eb5e708de203d0438be12cf708d635ebdbae56278be09077009586b9bc646ba7c2db35a5de05e86ae71461efea96dac64430edcf117d461113cccacf303576f310ab98efb180599894ba877e50614494923163a3afa9b4c2757f91a6b40799c5b331b464b10dfc45c783c317e408ab76390e19e8b7ceaa2c4d3bd201436bc6f69c7a5a4d8756924ed95665bd5e1034971e4d80d51b2a", "026866d46aa940309fdcabf92a324fbc", "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", "129039b5572e8a7a8131f76a", "30f05cf8189bb7b8b4f560e746e228c4cc7e86e8f2fa66e1afe212d1855db51070acd5eb34ce80b2e223957df50fde4c2531d97fc9e573725e7a5e47f0dfc4da1942620320bb2deaf8b17937bae4218d04db8e76f6efe84a117292159507c9f8a09fb2c17921d7762510dbf1dac7b62b1bd7572e3e2cf008d01c445c7fa78833235034281ae180e051451c6a64f22ca9708634bd0d604e4cfcd971b13742efa5b6363e662a875daccb2b00", }, { "c7d4f8790e4c47d4daecbddf5939973521ddbf3b832e564afc66f03b5583c41c58bd956609dc3ae3c8f7c2213059575236168dba44e3044049f47c9e7840bbd0fd5036062d70e9f567ac1797056ee93c8476f6c959fa09a3ee854166c6fc36c34d6cca7adcb36f435f86db65f4c4a1793b974294914b377fd179e697751c5ac289243c65d8aca93732849c27483da083d4e218652d4fe5fec8cb953ee7f00070143dd6ece97f241b03c0424bfee2cfd2c4e738f2361df0ffe8863dcf763d408a7a167763959b7f985bc1e359a4b22c6899645ad0814bcf69d10c38474978d1c48e482723e3a6bb3f689f980c51c474eb28cfbba91a8a12eb964b32dfc303a3524ccb752f71316ed9d007e521cb5a0cf429c79d4351b02ee7fb60c7be636a10af3586dfa7b74d80875466a820c0b514e97cb12cce615ab55cba7c1b1de72bcd1cb1acc368f944ef4eaa986e6a4d8253c9337f9795d94df193c90cb0b0387dcde929905223d441717ed9dfe826613bf094ba872993d41b269e27d74e5f541b497eac9ba180dc12ffb6f1e7dc5223cce6dd541071282b97c6526e15b2c330fb41dc96e25d72f45c28e543053766d11d44252db54e584c14abbb295d7e5a58bf36eea1936095ef897a338eb1995fcedd85fc92d354dfe7ff9a115c186bb4d7a1a27835030d248c87571a38f17906cefe0261d15740b9", "56", "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", "129039b5572e8a7a8131f76a", "f89c825ca43cae1ce3fbdee85c505edd1aabefe69a0f9efd740f027aa7dee48a91ad24e69ad061648f0a52b4afb19d7ffccdc21f4b4247dfd89f5f9f998cb3c02b226173fedb6f8770aceef9271e7236fefd19fb3b87d08a5c587ac7918e80aa4b477f22602189811e270d686bc4949137a41d11d95ec96ee9d26c6126f6e923ab37638b34d1538d2e46d6df6216da4f193a3cecb731e632e109ced643056a1673059355d2d1314df35ded8364efed7de490201090a6f2d1751748585f64d26041637ba3723cbc4b60e226f10a19699d223075bc1f27d82e7f560c0db630ea670b3f8a70a8950894af4d1c7b3f674a3fa00d19ee4cc2b6174c1d259a297424bf2c3943a29a16a9830ce11abaa79cd2eb77b53a02b365b1838e7bfd5ae1bd044ffc885c61c6b2186a357e8b8f732b7ab96517969aeb70c7b493bbaca9462a61815a3c6135c748bf9c8487ac0631807aa69243fa09cd3b8efb63f8d4e090ad30b6c2f08bf4e82f191cedfa5cbe2b42268d67ecd105918181e44fc9879efd642d20be84e6f74717e03fb94fcbaa6ed3b307431d2a9384b8a2b3e5825ffce8d99af48f177e43bb4272226d8a5edd37d53807f768feb9e0733b437a1d0f84779ab68a1804e92a5eecca56364f0fa6dca152203b249fdc8fbd950fdc37c1887596308a90ba3a5751c7096bfbd1cb177bb17847b33c4379b43938a67674459cd9a06e3017ccac5b", }, { "135a28170fe89066da7bcff3a9ccc1b27dfe942a6f47b23835ef746aaea63dc10066d90f4e697528e5451b8e11dd408fdbd4b94a1c6c82515bf7bc099df9cb9d5fa4acad0d22d5f267f18078cec107a995c1f3b12d7603886dbf910ab85ca7180053c50e759b00dc8c81555a425c03d71df6894a6c8cd2d94b64e303c08a1bc1dee1cf537ccf300850856292e1656aff5bf349c87f1ca1ca8085cd400fe901edcad04146a0714ef0f6b083d715edd670e020385f3cda29bc5ff6fc6edffe5ca9ce9def6e0e3d5f04ede2db02cfb2", "73afd2ab0e0e8537cae42dc6530dc4afb6934ca6", "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", "129039b5572e8a7a8131f76a", "2c125232a59879aee36cacc4aca5085a4688c4f776667a8fbd86862b5cfb1d57c976688fdd652eafa2b88b1b8e358aa2110ff6ef13cdc1ceca9c9f087c35c38d89d6fbd8de89538070f17916ecb19ca3ef4a1c834f0bdaa1df62aaabef2e117106787056c909e61ecd208357dd5c363f11c5d6cf24992cc873cf69f59360a820fcf290bd90b2cab24c47286acb4e1033962b6d41e562a206a94796a8ab1c6b8bade804ff9bdf5ba6062d2c1f8fe0f4dfc05720bd9a612b92c26789f9f6a7ce43f5e8e3aee99a9cd7d6c11eaa611983c36935b0dda57d898a60a0ab7c4b54", }, } ================================================ FILE: go/aead/subtle/encrypt_then_authenticate.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "encoding/binary" "errors" "fmt" "github.com/google/tink/go/tink" ) // EncryptThenAuthenticate performs an encrypt-then-MAC operation on plaintext // and associated data (ad). The MAC is computed over (ad || // ciphertext || size of ad). This implementation is based on // http://tools.ietf.org/html/draft-mcgrew-aead-aes-cbc-hmac-sha2-05. type EncryptThenAuthenticate struct { indCPACipher INDCPACipher mac tink.MAC tagSize int } const ( minTagSizeInBytes = 10 ) // Assert that EncryptThenAuthenticate implements the AEAD interface. var _ tink.AEAD = (*EncryptThenAuthenticate)(nil) // uint64ToByte stores a uint64 to a slice of bytes in big endian format. func uint64ToByte(n uint64) []byte { buf := make([]byte, 8) binary.BigEndian.PutUint64(buf, n) return buf } // NewEncryptThenAuthenticate returns a new instance of EncryptThenAuthenticate. func NewEncryptThenAuthenticate(indCPACipher INDCPACipher, mac tink.MAC, tagSize int) (*EncryptThenAuthenticate, error) { if tagSize < minTagSizeInBytes { return nil, fmt.Errorf("encrypt_then_authenticate: tag size too small") } return &EncryptThenAuthenticate{indCPACipher, mac, tagSize}, nil } // Encrypt encrypts plaintext with associatedData. // The resulting ciphertext allows for checking authenticity and // integrity of associatedData, but does not guarantee its secrecy. // // The plaintext is encrypted with an INDCPACipher, then MAC is computed over // (associatedData || ciphertext || n) where n is associatedData's length // in bits represented as a 64-bit bigendian unsigned integer. The final // ciphertext format is (IND-CPA ciphertext || mac). func (e *EncryptThenAuthenticate) Encrypt(plaintext, associatedData []byte) ([]byte, error) { ciphertext, err := e.indCPACipher.Encrypt(plaintext) if err != nil { return nil, fmt.Errorf("encrypt_then_authenticate: %v", err) } adSizeInBits := uint64(len(associatedData)) * 8 adSizeInBitsEncoded := uint64ToByte(adSizeInBits) toAuthData := make([]byte, 0, len(associatedData)+len(ciphertext)+len(adSizeInBitsEncoded)) toAuthData = append(toAuthData, associatedData...) toAuthData = append(toAuthData, ciphertext...) toAuthData = append(toAuthData, adSizeInBitsEncoded...) tag, err := e.mac.ComputeMAC(toAuthData) if err != nil { return nil, fmt.Errorf("encrypt_then_authenticate: %v", err) } if len(tag) != e.tagSize { return nil, errors.New("encrypt_then_authenticate: invalid tag size") } ciphertext = append(ciphertext, tag...) return ciphertext, nil } // Decrypt decrypts ciphertext with associatedData. func (e *EncryptThenAuthenticate) Decrypt(ciphertext, associatedData []byte) ([]byte, error) { if len(ciphertext) < e.tagSize { return nil, errors.New("ciphertext too short") } // payload contains everything except the tag. payload := ciphertext[:len(ciphertext)-e.tagSize] // Authenticate the following data: // associatedData || payload || adSizeInBits adSizeInBits := uint64(len(associatedData)) * 8 adSizeInBitsEncoded := uint64ToByte(adSizeInBits) toAuthData := make([]byte, 0, len(associatedData)+len(payload)+len(adSizeInBitsEncoded)) toAuthData = append(toAuthData, associatedData...) toAuthData = append(toAuthData, payload...) toAuthData = append(toAuthData, adSizeInBitsEncoded...) err := e.mac.VerifyMAC(ciphertext[len(ciphertext)-e.tagSize:], toAuthData) if err != nil { return nil, fmt.Errorf("encrypt_then_authenticate: %v", err) } plaintext, err := e.indCPACipher.Decrypt(payload) if err != nil { return nil, fmt.Errorf("encrypt_then_authenticate: %v", err) } return plaintext, nil } ================================================ FILE: go/aead/subtle/encrypt_then_authenticate_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "bytes" "encoding/hex" "testing" "github.com/google/tink/go/aead/subtle" subtleMac "github.com/google/tink/go/mac/subtle" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/tink" ) func createAEADWithKeys(encryptionKey []byte, ivSize int, hashAlgo string, macKey []byte, tagSize int) (tink.AEAD, error) { ctr, err := subtle.NewAESCTR(encryptionKey, ivSize) if err != nil { return nil, err } mac, err := subtleMac.NewHMAC(hashAlgo, macKey, uint32(tagSize)) if err != nil { return nil, err } cipher, err := subtle.NewEncryptThenAuthenticate(ctr, mac, tagSize) if err != nil { return nil, err } return cipher, nil } func createAEAD(keySize, ivSize int, hashAlgo string, macKeySize int, tagSize int) (tink.AEAD, error) { encryptionKey := random.GetRandomBytes(uint32(keySize)) ctr, err := subtle.NewAESCTR(encryptionKey, ivSize) if err != nil { return nil, err } macKey := random.GetRandomBytes(uint32(macKeySize)) mac, err := subtleMac.NewHMAC(hashAlgo, macKey, uint32(tagSize)) if err != nil { return nil, err } cipher, err := subtle.NewEncryptThenAuthenticate(ctr, mac, tagSize) if err != nil { return nil, err } return cipher, nil } // Copied from // https://tools.ietf.org/html/draft-mcgrew-aead-aes-cbc-hmac-sha2-05. // // We use CTR but the RFC uses CBC mode, so it's not possible to compare // plaintexts. However, the tests are still valueable to ensure that we // correcly compute HMAC over ciphertext and associatedData. var rfcTestVectors = []struct { macKey string encryptionKey string ciphertext string associatedData string hashAlgo string ivSize int tagSize int }{ { macKey: "000102030405060708090a0b0c0d0e0f", encryptionKey: "101112131415161718191a1b1c1d1e1f", ciphertext: "" + "1af38c2dc2b96ffdd86694092341bc04" + "c80edfa32ddf39d5ef00c0b468834279" + "a2e46a1b8049f792f76bfe54b903a9c9" + "a94ac9b47ad2655c5f10f9aef71427e2" + "fc6f9b3f399a221489f16362c7032336" + "09d45ac69864e3321cf82935ac4096c8" + "6e133314c54019e8ca7980dfa4b9cf1b" + "384c486f3a54c51078158ee5d79de59f" + "bd34d848b3d69550a67646344427ade5" + "4b8851ffb598f7f80074b9473c82e2db" + "652c3fa36b0a7c5b3219fab3a30bc1c4", associatedData: "" + "546865207365636f6e64207072696e63" + "69706c65206f66204175677573746520" + "4b6572636b686f666673", hashAlgo: "SHA256", ivSize: 16, tagSize: 16, }, { macKey: "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", encryptionKey: "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", ciphertext: "" + "1af38c2dc2b96ffdd86694092341bc04" + "4affaaadb78c31c5da4b1b590d10ffbd" + "3dd8d5d302423526912da037ecbcc7bd" + "822c301dd67c373bccb584ad3e9279c2" + "e6d12a1374b77f077553df829410446b" + "36ebd97066296ae6427ea75c2e0846a1" + "1a09ccf5370dc80bfecbad28c73f09b3" + "a3b75e662a2594410ae496b2e2e6609e" + "31e6e02cc837f053d21f37ff4f51950b" + "be2638d09dd7a4930930806d0703b1f6" + "4dd3b4c088a7f45c216839645b2012bf" + "2e6269a8c56a816dbc1b267761955bc5", associatedData: "" + "546865207365636f6e64207072696e63" + "69706c65206f66204175677573746520" + "4b6572636b686f666673", hashAlgo: "SHA512", ivSize: 16, tagSize: 32, }, } func hexDecode(t *testing.T, data string) []byte { t.Helper() decoded, err := hex.DecodeString(data) if err != nil { t.Fatal(err) } return decoded } func TestETARFCTestVectors(t *testing.T) { for _, v := range rfcTestVectors { macKey := hexDecode(t, v.macKey) encryptionKey := hexDecode(t, v.encryptionKey) ciphertext := hexDecode(t, v.ciphertext) associatedData := hexDecode(t, v.associatedData) cipher, err := createAEADWithKeys(encryptionKey, v.ivSize, v.hashAlgo, macKey, v.tagSize) if err != nil { t.Fatalf("failed to create AEAD from RFC test vector: %v", v) } if _, err := cipher.Decrypt(ciphertext, associatedData); err != nil { t.Errorf("decryption failed to RFC test vector: %v, error: %v", v, err) } } } func TestETAEncryptDecrypt(t *testing.T) { const keySize = 16 const ivSize = 12 const macKeySize = 16 const tagSize = 16 cipher, err := createAEAD(keySize, ivSize, "SHA1", macKeySize, tagSize) if err != nil { t.Fatalf("got: %v, want: success", err) } message := []byte("Some data to encrypt.") associatedData := []byte("Some data to authenticate.") ciphertext, err := cipher.Encrypt(message, associatedData) if err != nil { t.Fatalf("encryption failed, error: %v", err) } if len(ciphertext) != len(message)+ivSize+tagSize { t.Errorf("invalid ciphertext size, got: %d, want: %d", len(ciphertext), len(message)+ivSize+tagSize) } plaintext, err := cipher.Decrypt(ciphertext, associatedData) if err != nil { t.Fatalf("decryption failed, error: %v", err) } if !bytes.Equal(plaintext, message) { t.Errorf("invalid plaintext, got: %q, want: %q", plaintext, message) } } func TestETAWithAssociatedDataSlice(t *testing.T) { const keySize = 16 const ivSize = 12 const macKeySize = 16 const tagSize = 16 cipher, err := createAEAD(keySize, ivSize, "SHA1", macKeySize, tagSize) if err != nil { t.Fatalf("got: %v, want: success", err) } message := []byte("message") largeData := []byte("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") associatedData := largeData[:1] _, err = cipher.Encrypt(message, associatedData) if err != nil { t.Fatalf("encryption failed, error: %v", err) } wantLargeData := []byte("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") if !bytes.Equal(largeData, wantLargeData) { t.Errorf("largeData = %q, want: %q", largeData, wantLargeData) } } func TestETAEncryptDecryptRandomMessage(t *testing.T) { const keySize = 16 const ivSize = 12 const macKeySize = 16 const tagSize = 16 cipher, err := createAEAD(keySize, ivSize, "SHA1", macKeySize, tagSize) if err != nil { t.Fatalf("got: %v, want: success", err) } for i := 0; i < 256; i++ { message := random.GetRandomBytes(uint32(i)) associatedData := random.GetRandomBytes(uint32(i)) ciphertext, err := cipher.Encrypt(message, associatedData) if err != nil { t.Fatalf("encryption failed, error: %v", err) } if len(ciphertext) != len(message)+ivSize+tagSize { t.Errorf("invalid ciphertext size, got: %d, want: %d", len(ciphertext), len(message)+ivSize+tagSize) } plaintext, err := cipher.Decrypt(ciphertext, associatedData) if err != nil { t.Fatalf("decryption failed, error: %v", err) } if !bytes.Equal(plaintext, message) { t.Errorf("invalid plaintext, got: %q, want: %q", plaintext, message) } } } func TestETAMultipleEncrypt(t *testing.T) { const keySize = 16 const ivSize = 12 const macKeySize = 16 const tagSize = 16 cipher, err := createAEAD(keySize, ivSize, "SHA1", macKeySize, tagSize) if err != nil { t.Fatalf("got: %v, want: success", err) } message := []byte("Some data to encrypt.") associatedData := []byte("Some data to authenticate.") ciphertext1, err := cipher.Encrypt(message, associatedData) if err != nil { t.Fatalf("encryption failed, error: %v", err) } ciphertext2, err := cipher.Encrypt(message, associatedData) if err != nil { t.Fatalf("encryption failed, error: %v", err) } if bytes.Equal(ciphertext1, ciphertext2) { t.Error("ciphertexts must not be the same") } } func TestETAInvalidTagSize(t *testing.T) { const keySize = 16 const ivSize = 12 const macKeySize = 16 const tagSize = 9 // Invalid! if _, err := createAEAD(keySize, ivSize, "SHA1", macKeySize, tagSize); err == nil { t.Error("got: success, want: error invalid tag size") } } func TestETADecryptModifiedCiphertext(t *testing.T) { const keySize = 16 const ivSize = 12 const macKeySize = 16 const tagSize = 16 cipher, err := createAEAD(keySize, ivSize, "SHA1", macKeySize, tagSize) if err != nil { t.Fatalf("got: %v, want: success", err) } message := []byte("Some data to encrypt.") associatedData := []byte("Some data to authenticate.") ciphertext, err := cipher.Encrypt(message, associatedData) if err != nil { t.Fatalf("encryption failed, error: %v", err) } // Modify the ciphertext and try to decrypt. modCiphertext := make([]byte, len(ciphertext)) copy(modCiphertext, ciphertext) for i := 0; i < len(ciphertext)*8; i++ { // Save the byte to be modified. b := modCiphertext[i/8] modCiphertext[i/8] ^= (1 << uint(i%8)) if bytes.Equal(ciphertext, modCiphertext) { t.Errorf("modCiphertext shouldn't be the same as ciphertext") } if _, err := cipher.Decrypt(modCiphertext, associatedData); err == nil { t.Errorf("successfully decrypted modified ciphertext (i = %d)", i) } // Restore the modified byte. modCiphertext[i/8] = b } // Modify the associated data. modAssociatedData := make([]byte, len(associatedData)) copy(modAssociatedData, associatedData) for i := 0; i < len(associatedData)*8; i++ { // Save the byte to be modified. b := modAssociatedData[i/8] modAssociatedData[i/8] ^= (1 << uint(i%8)) if bytes.Equal(associatedData, modAssociatedData) { t.Errorf("modAssociatedData shouldn't be the same as associatedData") } if _, err := cipher.Decrypt(ciphertext, modAssociatedData); err == nil { t.Errorf("successfully decrypted with modified associated data (i = %d)", i) } // Restore the modified byte. modAssociatedData[i/8] = b } // Truncate the ciphertext. truncatedCiphertext := make([]byte, len(ciphertext)) copy(truncatedCiphertext, ciphertext) for i := 1; i <= len(ciphertext); i++ { truncatedCiphertext = truncatedCiphertext[:len(ciphertext)-i] if _, err := cipher.Decrypt(truncatedCiphertext, associatedData); err == nil { t.Errorf("successfully decrypted truncated ciphertext (i = %d)", i) } } } func TestETAEmptyParams(t *testing.T) { const keySize = 16 const ivSize = 12 const macKeySize = 16 const tagSize = 16 cipher, err := createAEAD(keySize, ivSize, "SHA1", macKeySize, tagSize) if err != nil { t.Fatalf("got: %v, want: success", err) } message := []byte("Some data to encrypt.") if _, err := cipher.Encrypt(message, []byte{}); err != nil { t.Errorf("encryption failed with empty associatedData") } if _, err := cipher.Encrypt([]byte{}, []byte{}); err != nil { t.Errorf("encryption failed with empty ciphertext and associatedData") } } ================================================ FILE: go/aead/subtle/ind_cpa.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle // INDCPACipher provides an interface for symmetric key ciphers that are // indistinguishable against chosen-plaintext attacks. Said primitives do not // provide authentication, thus should not be used directly, but only to // construct safer primitives such as AEAD. type INDCPACipher interface { // Encrypt encrypts plaintext. The resulting ciphertext is indistinguishable under // chosen-plaintext attack. However, it does not have integrity protection. Encrypt(plaintext []byte) ([]byte, error) // Decrypt decrypts ciphertext and returns the resulting plaintext. Decrypt(ciphertext []byte) ([]byte, error) } ================================================ FILE: go/aead/subtle/polyval.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "encoding/binary" "fmt" ) const ( // PolyvalBlockSize is the block size (in bytes) that POLYVAL uses. PolyvalBlockSize = 16 u32Sel0 uint32 = 0x11111111 u32Sel1 uint32 = 0x22222222 u32Sel2 uint32 = 0x44444444 u32Sel3 uint32 = 0x88888888 u64Sel0 uint64 = 0x1111111111111111 u64Sel1 uint64 = 0x2222222222222222 u64Sel2 uint64 = 0x4444444444444444 u64Sel3 uint64 = 0x8888888888888888 ) // Polyval (RFC 8452) is a universal hash function which operates on GF(2^128) // and can be used for constructing a Message Authentication Code (MAC). // See Section 3 of go/rfc/8452 for definition. type Polyval interface { // update the accumulator in the object with the blocks from data. If data // is not a multiple of 16 bytes, it is automatically zero padded. Update(data []byte) // finish completes the polyval computation and returns the result. Finish() [PolyvalBlockSize]byte } // fieldElement represents a value in GF(2^128). // In order to reflect the Polyval standard and make binary.LittleEndian suitable // for marshaling these values, the bits are stored in little endian order. // For example: // the coefficient of x^0 can be obtained by v.lo & 1. // the coefficient of x^63 can be obtained by v.lo >> 63. // the coefficient of x^64 can be obtained by v.hi & 1. // the coefficient of x^127 can be obtained by v.hi >> 63. type fieldElement struct { lo, hi uint64 } // polyval implements the POLYVAL function as defined by go/rfc/8452. type polyval struct { key fieldElement acc fieldElement } // Assert that polyval implements Polyval interface var _ Polyval = (*polyval)(nil) // mul32 multiplies two 32 bit polynomials in GF(2^128) using Karatsuba multiplication. func mul32(a uint32, b uint32) uint64 { a0 := uint64(a & u32Sel0) a1 := uint64(a & u32Sel1) a2 := uint64(a & u32Sel2) a3 := uint64(a & u32Sel3) b0 := uint64(b & u32Sel0) b1 := uint64(b & u32Sel1) b2 := uint64(b & u32Sel2) b3 := uint64(b & u32Sel3) c0 := (a0 * b0) ^ (a1 * b3) ^ (a2 * b2) ^ (a3 * b1) c1 := (a0 * b1) ^ (a1 * b0) ^ (a2 * b3) ^ (a3 * b2) c2 := (a0 * b2) ^ (a1 * b1) ^ (a2 * b0) ^ (a3 * b3) c3 := (a0 * b3) ^ (a1 * b2) ^ (a2 * b1) ^ (a3 * b0) return (c0 & u64Sel0) | (c1 & u64Sel1) | (c2 & u64Sel2) | (c3 & u64Sel3) } // mul64 multiplies two 64 bit polynomials in GF(2^128) using Karatsuba multiplication. func mul64(a uint64, b uint64) fieldElement { a0 := uint32(a & 0xffffffff) a1 := uint32(a >> 32) b0 := uint32(b & 0xffffffff) b1 := uint32(b >> 32) lo := mul32(a0, b0) hi := mul32(a1, b1) mid := mul32(a0^a1, b0^b1) ^ lo ^ hi return fieldElement{lo: lo ^ (mid << 32), hi: hi ^ (mid >> 32)} } // polyvalDot implements the dot operation defined by go/rfc/8452. // dot(a, b) = a * b * x^-128. // The value of the field element x^-128 is equal to x^127 + x^124 + x^121 + x^114 + 1. // The result of this multiplication, dot(a, b), is another field element. // The implementation here is inspired from BoringSSL's implementation of gcm_polyval_nohw(). // Ref: https://boringssl.googlesource.com/boringssl/+/master/crypto/fipsmodule/modes/gcm_nohw.c func polyvalDot(a fieldElement, b fieldElement) fieldElement { // Karatsuba multiplication. The product of |a| and |b| is stored in |r0| and |r1| // Note there is no byte or bit reversal because we are evaluating POLYVAL. r0 := mul64(a.lo, b.lo) r1 := mul64(a.hi, b.hi) mid := mul64(a.lo^a.hi, b.lo^b.hi) mid.lo ^= r0.lo ^ r1.lo mid.hi ^= r0.hi ^ r1.hi r1.lo ^= mid.hi r0.hi ^= mid.lo // Now we multiply our 256-bit result by x^-128 and reduce. // |r1| shifts into position and we must multiply |r0| by x^-128. We have: // // 1 = x^121 + x^126 + x^127 + x^128 // x^-128 = x^-7 + x^-2 + x^-1 + 1 // // This is the GHASH reduction step, but with bits flowing in reverse. // The x^-7, x^-2, and x^-1 terms shift bits past x^0, which would require // another reduction steps. Instead, we gather the excess bits, incorporate // them into |r0| and reduce once. // Ref: slides 17-19 of https://crypto.stanford.edu/RealWorldCrypto/slides/gueron.pdf. r0.hi ^= (r0.lo << 63) ^ (r0.lo << 62) ^ (r0.lo << 57) // 1 r1.lo ^= r0.lo r1.hi ^= r0.hi // x^-1 r1.lo ^= r0.lo >> 1 r1.lo ^= r0.hi << 63 r1.hi ^= r0.hi >> 1 // x^-2 r1.lo ^= r0.lo >> 2 r1.lo ^= r0.hi << 62 r1.hi ^= r0.hi >> 2 // x^-7 r1.lo ^= r0.lo >> 7 r1.lo ^= r0.hi << 57 r1.hi ^= r0.hi >> 7 return r1 } // NewPolyval returns a Polyval instance. func NewPolyval(key []byte) (Polyval, error) { if len(key) != PolyvalBlockSize { return nil, fmt.Errorf("polyval: Invalid key size: %d", len(key)) } return &polyval{ key: fieldElement{ lo: binary.LittleEndian.Uint64(key[:8]), hi: binary.LittleEndian.Uint64(key[8:]), }, }, nil } func (p *polyval) Update(data []byte) { var block []byte for len(data) > 0 { if len(data) >= PolyvalBlockSize { block = data[:PolyvalBlockSize] data = data[PolyvalBlockSize:] } else { var partialBlock [PolyvalBlockSize]byte copy(partialBlock[:], data) block = partialBlock[:] data = data[len(data):] } p.acc.lo ^= binary.LittleEndian.Uint64(block[:8]) p.acc.hi ^= binary.LittleEndian.Uint64(block[8:]) p.acc = polyvalDot(p.acc, p.key) } } func (p *polyval) Finish() (hash [PolyvalBlockSize]byte) { binary.LittleEndian.PutUint64(hash[:8], p.acc.lo) binary.LittleEndian.PutUint64(hash[8:], p.acc.hi) return } ================================================ FILE: go/aead/subtle/polyval_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "bytes" "encoding/hex" "testing" "github.com/google/tink/go/aead/subtle" "github.com/google/tink/go/subtle/random" ) // These test vectors have been taken from Appendix C in go/rfc/8452. var testVectors = []struct { Key, Input, Hash string }{ { // Test Case 0 Key: "25629347589242761d31f826ba4b757b", Input: "4f4f95668c83dfb6401762bb2d01a262d1a24ddd2721d006bbe45f20d3c9f362", Hash: "f7a3b47b846119fae5b7866cf5e5b77e", }, { // Test Case 1 Key: "d9b360279694941ac5dbc6987ada7377", Input: "00000000000000000000000000000000", Hash: "00000000000000000000000000000000", }, { // Test Case 2 Key: "d9b360279694941ac5dbc6987ada7377", Input: "01000000000000000000000000000000000000000000000040", Hash: "eb93b7740962c5e49d2a90a7dc5cec74", }, { // Test Case 3 Key: "d9b360279694941ac5dbc6987ada7377", Input: "01000000000000000000000000000000000000000000000060", Hash: "48eb6c6c5a2dbe4a1dde508fee06361b", }, { // Test Case 4 Key: "d9b360279694941ac5dbc6987ada7377", Input: "01000000000000000000000000000000000000000000000080", Hash: "20806c26e3c1de019e111255708031d6", }, { // Test Case 5 Key: "d9b360279694941ac5dbc6987ada7377", Input: "010000000000000000000000000000000200000000000000000000000000000000000000000000000001", Hash: "ce6edc9a50b36d9a98986bbf6a261c3b", }, { // Test Case 6 Key: "0533fd71f4119257361a3ff1469dd4e5", Input: "489c8fde2be2cf97e74e932d4ed87d00c9882e5386fd9f92ec00000000000000780000000000000048", Hash: "bf160bc9ded8c63057d2c38aae552fb4", }, { // Test Case 7 Key: "64779ab10ee8a280272f14cc8851b727", Input: "0da55210cc1c1b0abde3b2f204d1e9f8b06bc47f0000000000000000000000001db2316fd568378da107b52b00000000a00000000000000060", Hash: "cc86ee22c861e1fd474c84676b42739c", }, { // Test Case 8 Key: "27c2959ed4daea3b1f52e849478de376", Input: "f37de21c7ff901cfe8a69615a93fdf7a98cad481796245709f0000000000000021702de0de18baa9c9596291b0846600c80000000000000078", Hash: "c4fa5e5b713853703bcf8e6424505fa5", }, { // Test Case 9 Key: "670b98154076ddb59b7a9137d0dcc0f0", Input: "9c2159058b1f0fe91433a5bdc20e214eab7fecef4454a10ef0657df21ac70000b202b370ef9768ec6561c4fe6b7e7296fa850000000000000000000000000000f00000000000000090", Hash: "4e4108f09f41d797dc9256f8da8d58c7", }, { // Test Case 10 Key: "cb8c3aa3f8dbaeb4b28a3e86ff6625f8", Input: "734320ccc9d9bbbb19cb81b2af4ecbc3e72834321f7aa0f70b7282b4f33df23f16754100000000000000000000000000ced532ce4159b035277d4dfbb7db62968b13cd4eec00000000000000000000001801000000000000a8", Hash: "ffd503c7dd712eb3791b7114b17bb0cf", }, } func TestPolyval(t *testing.T) { for id, tc := range testVectors { key, err := hex.DecodeString(tc.Key) if err != nil { t.Errorf("cannot decode key in test case %d: %s", id, err) continue } input, err := hex.DecodeString(tc.Input) if err != nil { t.Errorf("cannot decode aad in test case %d: %s", id, err) continue } expectedHash, err := hex.DecodeString(tc.Hash) if err != nil { t.Errorf("cannot decode msg in test case %d: %s", id, err) continue } p, err := subtle.NewPolyval(key) if err != nil { t.Errorf("Unexpected error: %v", err) continue } p.Update(input) hash := p.Finish() actualHash := hash[:] if !bytes.Equal(actualHash, expectedHash) { t.Errorf("Hash values don't match in test case %d: actual %s, expected %s", id, hex.EncodeToString(actualHash), hex.EncodeToString(expectedHash)) } } } func TestPolyvalRejectsInvalidKeyLength(t *testing.T) { invalidKeySizes := []uint32{4, 8, 12, 15, 17, 24, 32} for id, keySize := range invalidKeySizes { key := random.GetRandomBytes(keySize) _, err := subtle.NewPolyval(key) if err == nil { t.Errorf("Expected error with invalid key-size %d case %d", keySize, id) } } } ================================================ FILE: go/aead/subtle/subtle.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package subtle provides subtle implementations of the AEAD primitive. package subtle import internalaead "github.com/google/tink/go/internal/aead" const ( intSize = 32 << (^uint(0) >> 63) // 32 or 64 maxInt = 1<<(intSize-1) - 1 ) // ValidateAESKeySize checks if the given key size is a valid AES key size. func ValidateAESKeySize(sizeInBytes uint32) error { return internalaead.ValidateAESKeySize(sizeInBytes) } ================================================ FILE: go/aead/subtle/subtle_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "testing" "github.com/google/tink/go/aead/subtle" "github.com/google/tink/go/testutil" ) type AEADSuite struct { testutil.WycheproofSuite TestGroups []*AEADGroup `json:"testGroups"` } type AEADGroup struct { testutil.WycheproofGroup IvSize uint32 `json:"ivSize"` KeySize uint32 `json:"keySize"` TagSize uint32 `json:"tagSize"` Type string `json:"type"` Tests []*AEADCase `json:"tests"` } type AEADCase struct { testutil.WycheproofCase Aad testutil.HexBytes `json:"aad"` Ct testutil.HexBytes `json:"ct"` Iv testutil.HexBytes `json:"iv"` Key testutil.HexBytes `json:"key"` Msg testutil.HexBytes `json:"msg"` Tag testutil.HexBytes `json:"tag"` } func TestValidateAESKeySize(t *testing.T) { for _, keySize := range []uint32{8, 16, 24, 32, 40} { err := subtle.ValidateAESKeySize(keySize) if keySize == 16 || keySize == 32 { if err != nil { t.Errorf("ValidateAESKeySize(%d): got err %q, want success", keySize, err) } } else if err == nil { t.Errorf("ValidateAESKeySize(%d): got success, want error", keySize) } } } ================================================ FILE: go/aead/subtle/xchacha20poly1305.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "errors" "fmt" "golang.org/x/crypto/chacha20poly1305" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/tink" ) // XChaCha20Poly1305 is an implementation of AEAD interface. type XChaCha20Poly1305 struct { key []byte } // Assert that XChaCha20Poly1305 implements the AEAD interface. var _ tink.AEAD = (*XChaCha20Poly1305)(nil) // NewXChaCha20Poly1305 returns an XChaCha20Poly1305 instance. // The key argument should be a 32-bytes key. func NewXChaCha20Poly1305(key []byte) (*XChaCha20Poly1305, error) { if len(key) != chacha20poly1305.KeySize { return nil, errors.New("xchacha20poly1305: bad key length") } return &XChaCha20Poly1305{key: key}, nil } // Encrypt encrypts plaintext with associatedData. // // The resulting ciphertext consists of two parts: // 1. the nonce used for encryption // 2. the actual ciphertext func (x *XChaCha20Poly1305) Encrypt(plaintext []byte, associatedData []byte) ([]byte, error) { if len(plaintext) > maxInt-chacha20poly1305.NonceSizeX-poly1305TagSize { return nil, fmt.Errorf("xchacha20poly1305: plaintext too long") } c, err := chacha20poly1305.NewX(x.key) if err != nil { return nil, err } nounce := random.GetRandomBytes(chacha20poly1305.NonceSizeX) // Make the capacity of dst large enough so that both the nounce and the ciphertext fit inside. dst := make([]byte, 0, chacha20poly1305.NonceSizeX+len(plaintext)+c.Overhead()) dst = append(dst, nounce...) // Seal appends the ciphertext to dst. So the final output is: nounce || ciphertext. return c.Seal(dst, nounce, plaintext, associatedData), nil } // Decrypt decrypts ciphertext with associatedData. // // ciphertext consists of two parts: // 1. the nonce used for encryption // 2. the actual ciphertext func (x *XChaCha20Poly1305) Decrypt(ciphertext []byte, associatedData []byte) ([]byte, error) { if len(ciphertext) < chacha20poly1305.NonceSizeX+poly1305TagSize { return nil, fmt.Errorf("xchacha20poly1305: ciphertext too short") } c, err := chacha20poly1305.NewX(x.key) if err != nil { return nil, err } n := ciphertext[:chacha20poly1305.NonceSizeX] pt, err := c.Open(nil, n, ciphertext[chacha20poly1305.NonceSizeX:], associatedData) if err != nil { return nil, fmt.Errorf("XChaCha20Poly1305.Decrypt: %s", err) } return pt, nil } ================================================ FILE: go/aead/subtle/xchacha20poly1305_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "bytes" "encoding/hex" "fmt" "math/rand" "testing" "golang.org/x/crypto/chacha20poly1305" "github.com/google/tink/go/aead/subtle" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" ) func TestXChaCha20Poly1305EncryptDecrypt(t *testing.T) { for i, test := range xChaCha20Poly1305Tests { key, err := hex.DecodeString(test.key) if err != nil { t.Fatalf("hex.DecodeString(test.key) err = %q, want nil", err) } pt, err := hex.DecodeString(test.plaintext) if err != nil { t.Fatalf("hex.DecodeString(test.plaintext) err = %q, want nil", err) } aad, err := hex.DecodeString(test.aad) if err != nil { t.Fatalf("hex.DecodeString(test.aad) err = %q, want nil", err) } nonce, err := hex.DecodeString(test.nonce) if err != nil { t.Fatalf("hex.DecodeString(test.nonce) err = %q, want nil", err) } out, err := hex.DecodeString(test.out) if err != nil { t.Fatalf("hex.DecodeString(test.out) err = %q, want nil", err) } tag, err := hex.DecodeString(test.tag) if err != nil { t.Fatalf("hex.DecodeString(test.tag) err = %q, want nil", err) } x, err := subtle.NewXChaCha20Poly1305(key) if err != nil { t.Errorf("#%d, cannot create new instance of XChaCha20Poly1305: %s", i, err) continue } _, err = x.Encrypt(pt, aad) if err != nil { t.Errorf("#%d, unexpected encryption error: %s", i, err) continue } var combinedCt []byte combinedCt = append(combinedCt, nonce...) combinedCt = append(combinedCt, out...) combinedCt = append(combinedCt, tag...) if got, err := x.Decrypt(combinedCt, aad); err != nil { t.Errorf("#%d, unexpected decryption error: %s", i, err) continue } else if !bytes.Equal(pt, got) { t.Errorf("#%d, plaintext's don't match: got %x vs %x", i, got, pt) continue } } } func TestXChaCha20Poly1305EmptyAssociatedData(t *testing.T) { key := random.GetRandomBytes(chacha20poly1305.KeySize) aad := []byte{} badAad := []byte{1, 2, 3} x, err := subtle.NewXChaCha20Poly1305(key) if err != nil { t.Fatal(err) } for i := 0; i < 75; i++ { pt := random.GetRandomBytes(uint32(i)) // Encrpting with aad as a 0-length array { ct, err := x.Encrypt(pt, aad) if err != nil { t.Errorf("Encrypt(%x, %x) failed", pt, aad) continue } if got, err := x.Decrypt(ct, aad); err != nil || !bytes.Equal(pt, got) { t.Errorf("Decrypt(Encrypt(pt, %x)): plaintext's don't match: got %x vs %x", aad, got, pt) } if got, err := x.Decrypt(ct, nil); err != nil || !bytes.Equal(pt, got) { t.Errorf("Decrypt(Encrypt(pt, nil)): plaintext's don't match: got %x vs %x", got, pt) } if _, err := x.Decrypt(ct, badAad); err == nil { t.Errorf("Decrypt(Encrypt(pt, %x)) = _, nil; want: _, err", badAad) } } // Encrpting with aad equal to null { ct, err := x.Encrypt(pt, nil) if err != nil { t.Errorf("Encrypt(%x, nil) failed", pt) } if got, err := x.Decrypt(ct, aad); err != nil || !bytes.Equal(pt, got) { t.Errorf("Decrypt(Encrypt(pt, %x)): plaintext's don't match: got %x vs %x; error: %v", aad, got, pt, err) } if got, err := x.Decrypt(ct, nil); err != nil || !bytes.Equal(pt, got) { t.Errorf("Decrypt(Encrypt(pt, nil)): plaintext's don't match: got %x vs %x; error: %v", got, pt, err) } if _, err := x.Decrypt(ct, badAad); err == nil { t.Errorf("Decrypt(Encrypt(pt, %x)) = _, nil; want: _, err", badAad) } } } } func TestXChaCha20Poly1305LongMessages(t *testing.T) { dataSize := uint32(16) // Encrypts and decrypts messages of size <= 8192. for dataSize <= 1<<24 { pt := random.GetRandomBytes(dataSize) aad := random.GetRandomBytes(dataSize / 3) key := random.GetRandomBytes(chacha20poly1305.KeySize) x, err := subtle.NewXChaCha20Poly1305(key) if err != nil { t.Fatal(err) } ct, err := x.Encrypt(pt, aad) if err != nil { t.Errorf("Encrypt(%x, %x) failed", pt, aad) continue } if got, err := x.Decrypt(ct, aad); err != nil || !bytes.Equal(pt, got) { t.Errorf("Decrypt(Encrypt(pt, %x)): plaintext's don't match: got %x vs %x; error: %v", aad, got, pt, err) } dataSize += 5 * dataSize / 11 } } func TestXChaCha20Poly1305ModifyCiphertext(t *testing.T) { for i, test := range xChaCha20Poly1305Tests { key, err := hex.DecodeString(test.key) if err != nil { t.Fatalf("hex.DecodeString(test.key) err = %q, want nil", err) } pt, err := hex.DecodeString(test.plaintext) if err != nil { t.Fatalf("hex.DecodeString(test.plaintext) err = %q, want nil", err) } aad, err := hex.DecodeString(test.aad) if err != nil { t.Fatalf("hex.DecodeString(test.aad) err = %q, want nil", err) } x, err := subtle.NewXChaCha20Poly1305(key) if err != nil { t.Fatal(err) } ct, err := x.Encrypt(pt, aad) if err != nil { t.Errorf("#%d: Encrypt failed", i) continue } if len(aad) > 0 { alterAadIdx := rand.Intn(len(aad)) aad[alterAadIdx] ^= 0x80 if _, err := x.Decrypt(ct, aad); err == nil { t.Errorf("#%d: Decrypt was successful after altering additional data", i) continue } aad[alterAadIdx] ^= 0x80 } alterCtIdx := rand.Intn(len(ct)) ct[alterCtIdx] ^= 0x80 if _, err := x.Decrypt(ct, aad); err == nil { t.Errorf("#%d: Decrypt was successful after altering ciphertext", i) continue } ct[alterCtIdx] ^= 0x80 } } // This is a very simple test for the randomness of the nonce. // The test simply checks that the multiple ciphertexts of the same message are distinct. func TestXChaCha20Poly1305RandomNonce(t *testing.T) { key := random.GetRandomBytes(chacha20poly1305.KeySize) x, err := subtle.NewXChaCha20Poly1305(key) if err != nil { t.Fatal(err) } cts := make(map[string]bool) pt, aad := []byte{}, []byte{} for i := 0; i < 1<<10; i++ { ct, err := x.Encrypt(pt, aad) ctHex := hex.EncodeToString(ct) if err != nil || cts[ctHex] { t.Errorf("TestRandomNonce failed: %v", err) } else { cts[ctHex] = true } } } func TestXChaCha20Poly1305WycheproofCases(t *testing.T) { testutil.SkipTestIfTestSrcDirIsNotSet(t) suite := new(AEADSuite) if err := testutil.PopulateSuite(suite, "xchacha20_poly1305_test.json"); err != nil { t.Fatalf("failed populating suite: %s", err) } for _, group := range suite.TestGroups { if group.KeySize/8 != chacha20poly1305.KeySize { continue } if group.IvSize/8 != chacha20poly1305.NonceSizeX { continue } for _, test := range group.Tests { caseName := fmt.Sprintf("%s-%s:Case-%d", suite.Algorithm, group.Type, test.CaseID) t.Run(caseName, func(t *testing.T) { runXChaCha20Poly1305WycheproofCase(t, test) }) } } } func runXChaCha20Poly1305WycheproofCase(t *testing.T, tc *AEADCase) { var combinedCt []byte combinedCt = append(combinedCt, tc.Iv...) combinedCt = append(combinedCt, tc.Ct...) combinedCt = append(combinedCt, tc.Tag...) ca, err := subtle.NewXChaCha20Poly1305(tc.Key) if err != nil { t.Fatalf("cannot create new instance of ChaCha20Poly1305: %s", err) } _, err = ca.Encrypt(tc.Msg, tc.Aad) if err != nil { t.Fatalf("unexpected encryption error: %s", err) } decrypted, err := ca.Decrypt(combinedCt, tc.Aad) if err != nil { if tc.Result == "valid" { t.Errorf("unexpected error: %s", err) } } else { if tc.Result == "invalid" { t.Error("decrypted invalid") } if !bytes.Equal(decrypted, tc.Msg) { t.Error("incorrect decryption") } } } func TestPreallocatedCiphertextMemoryInXChaCha20Poly1305IsExact(t *testing.T) { key := random.GetRandomBytes(chacha20poly1305.KeySize) a, err := subtle.NewXChaCha20Poly1305(key) if err != nil { t.Fatalf("aead.NewAESGCMInsecureIV() err = %v, want nil", err) } plaintext := random.GetRandomBytes(13) associatedData := random.GetRandomBytes(17) ciphertext, err := a.Encrypt(plaintext, associatedData) if err != nil { t.Fatalf("a.Encrypt() err = %v, want nil", err) } // Encrypt() uses cipher.Overhead() to pre-allocate the memory needed store the ciphertext. // For ChaCha20Poly1305, the size of the allocated memory should always be exact. If this check // fails, the pre-allocated memory was too large or too small. If it was too small, the system had // to re-allocate more memory, which is expensive and should be avoided. if len(ciphertext) != cap(ciphertext) { t.Errorf("want len(ciphertext) == cap(ciphertext), got %d != %d", len(ciphertext), cap(ciphertext)) } } ================================================ FILE: go/aead/subtle/xchacha20poly1305_vectors_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test // # Test vectors generated from libsodium with this code: // // #include // #include // #include // // void hexdump(const uint8_t *in, size_t in_len) { // for (size_t i = 0; i < in_len; i++) { // printf("%02x", in[i]); // } // printf("\n"); // } // // int main() { // uint8_t nonce[24]; // uint8_t key[32]; // uint8_t m[64], c[64]; // uint8_t ad[16], tag[16]; // // for (size_t ad_len = 0; ad_len < sizeof(ad); ad_len += 4) { // for (size_t m_len = 0; m_len < sizeof(m); m_len += 5) { // randombytes(nonce, sizeof(nonce)); // randombytes(key, sizeof(key)); // randombytes(m, m_len); // randombytes(ad, ad_len); // // unsigned long long tag_len = sizeof(tag); // // if (crypto_aead_xchacha20poly1305_ietf_encrypt_detached( // c, tag, &tag_len, m, m_len, ad, ad_len, NULL, nonce, key)) { // abort(); // } // // printf("KEY: "); // hexdump(key, sizeof(key)); // printf("NONCE: "); // hexdump(nonce, sizeof(nonce)); // printf("IN: "); // hexdump(m, m_len); // printf("AD: "); // hexdump(ad, ad_len); // printf("CT: "); // hexdump(c, m_len); // printf("TAG: "); // hexdump(tag, sizeof(tag)); // printf("\n"); // } // } // // return 0; // } var xChaCha20Poly1305Tests = []struct { key, nonce, plaintext, aad, out, tag string }{ { "1f4774fbe6324700d62dd6a104e7b3ca7160cfd958413f2afdb96695475f007e", "029174e5102710975a8a4a936075eb3e0f470d436884d250", "", "", "", "f55cf0949af356f977479f1f187d7291", }, { "eb27969c7abf9aff79348e1e77f1fcba7508ceb29a7471961b017aef9ceaf1c2", "990009311eab3459c1bee84b5b860bb5bdf93c7bec8767e2", "e7ec3d4b9f", "", "66bd484861", "07e31b4dd0f51f0819a0641c86380f32", }, { "4b6d89dbd7d019c0e1683d4c2a497305c778e2089ddb0f383f2c7fa2a5a52153", "97525eb02a8d347fcf38c81b1be5c3ba59406241cf251ba6", "074db54ef9fbc680b41a", "", "1221898afd6f516f770f", "75e7182e7d715f5a32ee6733fd324539", }, { "766997b1dc6c3c73b1f50e8c28c0fcb90f206258e685aff320f2d4884506c8f4", "30e7a9454892ef304776b6dc3d2c2f767ed97041b331c173", "b8250c93ac6cf28902137b4522cc67", "", "e2a13eeff8831a35d9336cb3b5c5d9", "62fdf67735cad0172f9b88603b5f3c13", }, { "6585031b5649fcabd9d4971d4ac5646fc7dca22f991dfa7dac39647001004e20", "705ee25d03fec430e24c9c6ccaa633f5b86dd43682778278", "9a4ca0633886a742e0241f132e8f90794c34dfd4", "", "0a8e6fd4cd1640be77c4c87dde4ae6222c887ed7", "edc4fbc91dfa07021e74ae0d9d1c98dc", }, { "dfc6f7c86a10a319ebcb6362997e585f55b67f3434f47dc4039c2d67973e3077", "6097f30fd75229d928454c7d59a2d2c58bfddcb14c16438e", "74c946a7f0733377e852a23087506a28dccef86e101a4359c0", "", "6e8ea0bb4c2f1323841d8e236816c61c3295866b75cefb5c25", "f16c0e9487ca7de5e7cb2a1b8bb370fc", }, { "59b8d488773767c4804d918709cfec6c69a193371145bb94f183899851aaadac", "ad5bdf8f190ca2d2cc02a75bb62aa22274cb3c98fe2d25f2", "066b9ed10f16d3dc132b409aae02d8cac209dd9b4fb789c4d34725ab2a1f", "", "2bbd4542489006df66ad1462a932524642b139ddcbf86b6b480e9e6d976c", "ca4835419ba029bc57010a8cc8bca80c", }, { "8c0cb4633cf8dc6b4b9552d1035f85517cb1ba4c36bcbc43338a8c6c7d15ce20", "8418b9655a0376fadefa3cdf8805815c4f7b56f467a74a95", "50c205a9c5d4088ba8e59a96fcd837f5170669854547678288199f1078ff2a81f0b19a", "", "8b55a12df1a85dd3fb19c34ab047a85849d15a30225bb5360bad1f0a8f5f2bd49f5898", "bce13201df6e4a7e6d896262e45d969d", }, { "b45386a75a5772e34bd193e1946f69ebfb90c37ae4581d39c9669d75e4584f50", "9fb763d0926585b5f726af9b8e3babdb331e9aa97f8d99ed", "64df0e341145d9e4a0d090153591a74893bc36cb9dae1e9570d8fee62e907cf004f9d8a360343483", "", "3146d8a5c898edd832ec9d126e93b3a433ec97dc47dce0e1985bda88c88c6aeca46fc7d9a68e30ab", "44fdb0d69abd8068442cb2ea6df8b2f2", }, { "f2efbd358dd353639a162be39a957d27c0175d5ab72aeba4a266aeda434e4a58", "65a6f7ebe48de78beb183b518589a0afacf71b40a949fa59", "f7473947996e6682a3b9c720f03cfaf26bbcdaf76c83342d2ad922435e227a5d1eacbd9bd6ea1727ec19fb0e42", "", "778a0fb701b9d671ccfaf1454e8928158ede9bb4395119356a8133036840c1bcbb8fe5e19922fbbcf8b18596e7", "9d195a89fdd29ca271405d3330f996f9", }, { "9dd674fb4a30a7bb85fc78050479ab0e2c3cc9f9f5b8689a7a67413aca304b21", "ad9e8fe15940694725f232e88f79cda7c82fe1b8aae58ba4", "7272bb6609cbd1399a0b89f6ea255165f99330aeb170ac88fccdd8e226df0952407e35718fb5edc9e987faabb271cc69f7e7", "", "846901650cb38974463a18c367676e1579ebdaf3e96b57224e842f5d5f678f3270b9a15f01241795662befb3db0768800e25", "900004db3613acbeb33d65d74dd437d7", }, { "280cbe7380a0d8bb4d8dd4476012f2eeb388a37b8b71067969abb99f6a888007", "2e1854617c67002599e6b077a812c326deb22fe29d093cbb", "d0901ec3d31ece2832685ff577f383bdff26c31341ea254acee7c5929a5df74fea2aa964524dc680b2f55fbd4fea900e956c304cc4ac3c", "", "546370726cc63068d3520d67f4f57f65d03b9ecec21c2a8c7b1133089ad28b07025a7181bddeb4a49f514fac1a44f64ee3af33d778fb98", "39084e33e42a1b05f58da65ba487d138", }, { "887564f75afa78f595cdadcea7340d20f5c5a2df169d0ad14b15fe32ce337004", "54c11df13d1f444da80b0964caeb59474b17b23a650a33f5", "f0f008eece79ecb24b715dff8a3456dfe253924b99f98f2f1b18564cced50925fca860d1c2d4785bdf4a964c76c3079efa6b37c4ba2cacc534fb590c", "", "32bb077268568d569b39e8ccdeeeb447ef424eaa2ffab565209a19b16a25952f897e5405bb0d67d8c9005d1c0b32687164d17fa4d0f412b80414c025", "0bac7c0f8dce12917fbd4ed1738ac0cc", }, { "21c6aa88eb1a320d251f71a4b312ca75347040990d869a1dd2a1982c30fda2c7", "7dead2f1a3d9d45a9124a40efe8994300976991a4417ef4d", "", "e1bf7de4", "", "341e9d0687006f981bced2f985f953e6", }, { "0c97b9a65ffcd80b8f7c20c3904d0d6dd8809a7f97d7f46d39a12c198a85da5d", "1f2c1dbc5f52fc9c8f9ca7695515d01d15904b86f703fba3", "ecaf65b66d", "bd8a6f18", "8d1b2b0e38", "27a7c7ac8bda627085414f0f31206a07", }, { "4ab5e3595f39c4379a924e5f8ebcf3279075c08d18daff01d9ddfa40e03faf12", "94e6ddc294f5f1531924ec018823343ebcc220a88ea5ee33", "c91b73abe5316c3effc6", "c576f6ea", "abe960fbc64b339c53b1", "7ebae48a2ff10117069324f04619ad6f", }, { "a1e6146c71c2ea22300e9063455f621e15bd5bf1a3762e17f845e1aba5dd5a9c", "82ddb6929abff8a9ad03dfb86c0bb3e7c092d45ebfa60a1b", "f011f32ccc2955158c117f53cf7b12", "5d14bc05", "44592321c665f51e9ffea052df1fea", "d556798b97f9b647729801419424affc", }, { "7a1af30362c27fd55b8c24b7fca324d350decee1d1f8fae56b66253a9dd127dd", "61201d6247992002e24e1a893180d4f0c19a3ae4cc74bf0c", "5c7150b6a4daa362e62f82f676fdc4c4b558df64", "00c49210", "27d9e2730b6809c08efbd4b0d24639c7b67486f3", "5889fdee25379960038778e36b2cedb2", }, { "0b3fd9073e545ac44a7967263ead139c9547f7a54f06228fd3c8609fa2620784", "6450e1097d6f9ea76eb42e8e65972d501041c3a58baf8770", "d679ae442b0351e5bff9906b099d45aab4f6aea5306a7a794f", "318d292b", "a3f9ee45316d7b0f948a26145ee4fd0552bc6dc25e577e777a", "0068a401a194b8417ec0e198baa81830", }, { "047c7d378fe80c02ee48df6f679a859253aed534fdcdd87023eb3d2f93fcafe3", "ed240b0ff6f8ac585b3ea1ab2dab8080fc2f6401b010c5d0", "7288afb4e0fa5c58602090a75c10d84b5f5f1c0e03498519afe457251aa7", "e4310302", "87906b14ca3e32ab01523b31ae0bb74590ce9e1df0811e743a2c7a93415a", "3a0abeab93792b1ffe768d316da74741", }, { "1ad4e42acc5dfd07eb0a2456e9103cd0e150a36c667eb2f2b73c0d1ac1089ce3", "48efb52387284c5d38b4940c75f0c39a3f81f60bfebb48cb", "da7edb5b3193b4484f09efa85fcf85600968ecdc537d3829a469c866ee67b0df677866", "446be8e3", "b76457ca99e95b6539b12f1d6bdac55a6d5c6469b1ff274459363ec05241f7e6e5d3ce", "06880ee508ce929da5a81f8b9de0031c", }, { "702a554c1b703d4dd69ad51234293ab787a01e15bdb3ce88bf89e18c01a67164", "ea535d9c371241b9850b8b4a596b63db79eea60bd2cd9fbb", "a97156e9b39d05c00b811552d22088d7ee090a117a7f08adac574820d592021f16207720d49fb5fd", "ba5790e3", "8d0b2b04479c33287096f0c6276a73f6c037edc1a2b28f8d3b2b8e6d4c5f9dc5113309dd3ecb15e6", "3cf303305e12924d29c223976699fb73", }, { "1bb7303fefa4d8d344bb9a215901b2314324bf1f3aeb9df5d1c1532c3a55ebf1", "a304551e5f0dc98995ddfee6215a9995023a3696debfd302", "6cf6819ce3e7ed9d4f85f4a5699701dbcaf3161adc210c0b7825ddfd83d6d7c685db62f68b3801ccc8a786066d", "901c5feb", "bc5ef09c111f76e54f897e6fce4aee1d25b6ed934f641ed5262d0c5eed45f610a6aea3b58b7771e34256d43a16", "b83f73f7995ba1b243dbf48ddfeb8e3a", }, { "24b294f6cbac10d87158d1c6aca83b337d596132afac7633f69a3b3e58823f11", "805772ff619cc6fcc5ec0e9965435d6f74a2290c055ec754", "65e8581286868caabcec1a9814db00b805edc660b94ee3babc6ce19a3ca868bd322105484d59b4ce02ced4071bc16642a1f2", "7ae1c561", "fe1d463b1466e8e411f0b0700f90760472ee5141f3e5afef43fd729f1623dca75cd4d00576765b335f8b2b77b00527599cb3", "111d8540fd5ec04b9ba16ed810133026", }, { "38e63e8b6402ac3f6d1641a1e3b74d2074be0fe41129975a3ff62b74ca52af05", "228d671b036710cbdaa72e9bf1d9ed6982b0bb3428a69fd6", "20a8d18878924d09aac32853c10e73dbd741134b7050ae6999839f2dbc727cb0052b5497c4bbd2a89e716278f15c81b871953614a49693", "e9e6ac73", "80e0fe8eb26e5df229c6d939c944d440a37aa3cabf76eab5b9a420095513021ea4241ab367f6f44a20817b14631549ae6c96aa963970e1", "1e80fbafcc7168e0494fce4cd76d692c", }, { "4325dd8406fdb8431a81f1b5db3603995256de36121019724cca2190c87a6e83", "dcbf3077b36d5d678d668fd2d0c99284c780b55c4658ea75", "4f599ad04f79be9add10fdc649b8be53e1062ea5e9c2bed22265dc6fb30d5ab4fd4425b38ff14d8e68013405bec1eff8c9ef3069902e492aac73dcd9", "6fa0d757", "7decbdc7043495c59ecc64e720436bb0708b586a46f8745f74391477f5a2520905dfcebc3765a330999013d309dfaa997bf70bab6a0b8f4f2a2a3cdf", "051ec4ecce208d9be0cd17f434e13be3", }, { "2d3d9ed4bc9eb9668733bafbb73e88be2cd17021c3a23be69b981d9f0df71df1", "84cae69639240c82b58895997511f145e474ebe1b008f391", "", "64db597c26a4c3da", "", "2a22c4a962d46a719014ab7b0ffaf6d3", }, { "09ec4e79a02db53b19b54dd2d3592afc92c74ef57d1e0f51f3726a6631b1b73f", "2907ced16e0777fedb1e2de30df11b3fd712af41dd714a4b", "b6e50cd4ea", "b5488e9b7f339b7b", "0163e75330", "e29401c6d756adcc516580ae656852aa", }, { "9d5ac25a417b8a57b85332979e8a7cbad23617bb27772bbccc2acb0acae7b755", "ff152421688dd6af7fef87817b508493a32d97a06fbda4f3", "92f4b9bc809be77e6a0d", "892b793f7a6e0727", "bcc594f59de8ee8c22c6", "1a8275816c0d32a1b6cfd41fa3889558", }, { "eccf80c5f744d2ecc932f95ade0d9fe9327e19795023db1846d68d04720a2401", "abc050fad8876589633b222d6a0f2e0bf709f73610aa23ee", "45a380e438405314510c166bac6840", "c32c9a1ce6852046", "9fa452dc9ca04c16ff7bde9925e246", "3d5e826162fa78de3fc043af26044a08", }, { "b1912d6bc3cff47f0c3beccff85d7cd915b70ab88d0d3a8a59e994e1b0da8ac8", "d8756090a42eea14ff25be890e66bfe4949fad498776ea20", "e2f85df2ebcfa6045bd521abfe8af37fc88a0be1", "4576bb59b78032c8", "5eb6324aa48e0a4f72f5cb0a4917faf93af4209c", "774f8077f039588495045fee07950e14", }, { "85162b111c9f3163f57c2cbc311a1e9aeed9dd6136b5784bc9c0b5052f8bffbd", "23cdb8b546bb8a5a746b24446f0ab4199f0543d915ff51f1", "dc81000077d5743beef09ac91663885d984212bbccf3dbe6f3", "3084f3e9c4d0a15f", "692d17ae0b524ec6edc0cf49b69ac90c99bed44691f7ae63b7", "efe72ff84b3bccb4d83a27ddc574bc21", }, { "b05ca358d8ca79f51283d83e2673bfb741c379ba271a773b8dd9c6a108e758d3", "9a53ad79f535c6e9da011463063c896f2ec7645e6e3548fc", "44e793742c774020e7349c996418042dc0dc30ee2bfd2654008c8929a436", "71ab5948c5e0f4c6", "c5eddb7aeaa175b5f3dab68cf746f2acaf56fc62b29804629e25e2d63879", "bec3b7a8b8dad22ff3d14d26273294d2", }, { "abb5136a01354c765a96e832df58bec3b088bd19dc4d6bd6674f2f02007ebdaa", "71267ac9f4fe5caa1d52cd85948a170a778f0141d54dbffe", "afb526fe41c4e2a767ce77c4145b9d054268f5f3b279237dec97f8bc46f9d158868b86", "047baa2b04748b62", "0032d4c1e65da2266539464c5d3c2b1618454a6af0e7f1e3cfc87845c75f2f4ae8b03f", "b526a95a33f17ab61f2cdfc1e2dd486a", }, { "bb826ed38008a0d7fb34c0c1a1a1149d2cad16b691d5129cc83f5eff2b3e5748", "4e02fe0915d81e9d5a62e5b3551b9db882e3873c0aaa230d", "20270d291a8d9791b0f5e35a64387bb4237bad61169841d7e1667c994ad49869c7d5580ffa752a2d", "db852a275081e29b", "d740012efb7e1bb986ce2c535134a45f658b92163c109bdecf1ce5b836879fe9e006a56be1fac8d7", "21e931042e7df80695262198a06286c9", }, { "938d2c59f6f3e2e7316726537932372e05e8c1b5577aae0ee870bf712ff001ab", "fb4d71cf7eb2f70df9759a64c76a36b75203f88bf64f4edb", "8910415d674a93c54c8f5e4aa88e59648d9a0a5039a66837d58ab14f0665a5f6d9af9b839f9033d0fe8bc58f19", "a3fca278a63bf944", "1905c6987a702980b7f87f1ed2d3ae073abe1401b23434f3db43b5c37c979c2068ce9a92afedcdc218003848ea", "1bd712f64777381f68be5ccc73f364a3", }, { "dd0521842f498d23236692a22db0eb2f0f14fef57577e5fb194503e206b0973d", "519e0eee8f86c75c7a364e0905a5d10d82073e11b91083a5", "61ff13acb99c5a7fd1921ec787c8de23c1a712ff002b08cecc644a78c47341eab78e7680380c93c7d53d5e56ef050d6ff192", "bb5c4e5ae8f7e461", "9bfdb0fd195fa5d37da3416b3b1e8f67bd2a456eb0317c02aabf9aac9d833a19bda299e6388e7b7119be235761477a34d49e", "0f0c03b8423583cb8305a74f622fa1f9", }, { "189bd84be3fb02723539b29cf76d41507c8b85b7217777ee1fb8f84a24aa7fee", "ef1bf39f22ba2edf86853505c24fafdf62c1a067963c63ba", "d5f96e240b5dd77b9fb2bf11c154fcbff312a791c3eb0717684e4fd84bf943e788050b47e76c427f42f3e5344b2636091603ba3b1d7a91", "93368a8e0900c7b6", "c55a8b7f587bee4f97514582c5115582abffd6312914d76c2568be6836f62ba098789ed897c9a7508a5dc214bf8c218664f29941ccdfd6", "78f87352dcb1143038c95dc6e7352cfd", }, { "23a2dbfcd02d265805169fa86e6927c7d49c9a24d2707884e18955e32dafc542", "305c7851f46f23ea8d832d5ed09d266714fd14f82ba0f69c", "224de94a938d49cad46144e657e548bd86690a1b57b81558095eace59df1c552600dea389aaa609304fbc1eadf2241f2118c8bdf04522e1898efe1d4", "0075b20502bd29b2", "8e10c59369bbb0d72958100b05788498f59588795e075b8bce21d92d320206348b04010ced9b8cd3d651e825488915ce4a6e4f1af2f4d2f77b955376", "c39f0595ae8112dea6ef96df1c12458b", }, { "264e3c3f47bdf795cdde57d9a30be5a4da8b18463c0e3e05df28b7bf4e56410b", "3ee09b6e205c261bf48ac53a9ba0afa460a5d5c0f2d80be8", "", "8eeec09d8972cb8ab0069554", "", "245a034d84edab9fa6f0decb6b984766", }, { "d8ba98a272b5f91797b04b114311c3b92b7f2e3bb72edb7f78ed311b9f8ea2ad", "481de9a06eee76a501e3c2b9d7423d90596193ad9d8a6564", "9ee1a3134d", "928653701f6d6c8429b08c0d", "459a07898f", "9188ec8d8e3bd91dcfda48fcc76773f7", }, { "ac9afd627a745df682bb003517056f07876eb94d2f8c610c61b6ac0d34ec4ec0", "eaae7b8704530db1e8c3dcc968a00604a333c7c27ba51b16", "f7c3f6ee2e9c03394dc8", "796620b367d5f041821baf69", "d4a69005790cc91d8d34", "e4c83def113afcf83a1ea8cb204a0eae", }, { "ea1a07c1fd60a5421f1fb6c43b4318090e290c97aa3bfa037e6fc5ee00fd47d4", "37327805cce92b38a669affbca1de92e068727fcf6fbb09a", "7002ca765b91913ee719e7521ef5ac", "64e7c48fc3041eac0734737f", "9d8857a8c52a9ab3bf44b024b191b6", "d072c31714a7d0fe1596fd443a96e715", }, { "b3beb34fe0229fc8f49b354e941025bde6a788f25017a60e8a49591ed5d7e7da", "dd0e9fec76de1f6efb022b12164f7e9248b8e8c01d14ac02", "acf360d7529a42be1f132f74745a940da9e823f2", "1489ca8d852f0a8547dbe8bc", "2e8718372d6e8167213cf112dc41c80377244f5a", "e4f31e8f84b9356999dc60989009e698", }, { "9357cecd10bab8d2e42ed88c0386204827c3b76e9e51150d09fd4e3b4e0e1e6f", "81f2106a5379e0ed861cf76b3cf95afb17515478b5cbcae9", "ee51a0f25d091288b5e2b91ad11d491329e48b35a18a3a8685", "b80cb677f4b409cd1537363b", "f681f19fa8de1fdea3538001a46f30fa6333b76d6439337e68", "afad5e6d282d9df6d8119c32237b3e60", }, { "9f868600fbf81e40398b7dfb201fcae35d34bba10908860b0b2bf8b942b4e8fa", "2ddcc13c97185614095d437900b8c0a9170e0a4a50e46ba5", "133fa3ac176fee6df67472752e41c6834f13300c0064ff5b190f903b7ac7", "0d61321fbee8bb1f3f5cb454", "b93abb311ec0bf018dc300c7d511b42ade72780373186e231820b44f22f0", "f8bd2f649a337783ff911e37966037bd", }, { "05affcdfce0a28539924370db8d80a78b835254778ec41acbff52bfab092fa33", "3edaeb185f7273b1a7cccba54f84c5f7d6583433b49d3694", "7657581faad266cc1037962a380c8aa5306f88000427d0a05397696b503790ad2643c6", "d7c213e9e6f4a40f3e5b662c", "5eb19080aadc89f2329da4f5c41dc60568651c424c1b05d827f2bfb8dbff42c5a08224", "2da20087b5674f0b967d1baa664bbd82", }, { "645ed60ec74ddfe1f02694792db4436c262d20405d8645cd9755d64876219799", "d83665b44c1fdf567299f2b8501e9c0e7ae2dda0bb8f2c82", "ceee69d32ad4667a00909964d9611bf34fd98be41ad7f0feaaaff8169060d64cf310c13bcb9394cf", "57379f8f44191ec9cf3b1a07", "4496a0666f0f895ebce224b448a04502f2ae7b354d868b7c54295bf051162e82c530c767d1ffd2cc", "1ffc56da4fb961ffdfabe66d82ec8f29", }, { "06624c9a75bb7dbe224a3f23791281f53c40b407a14161a3f82f34924623dc02", "e647b8b4739bf542a81d72d695e1cd6ba348fa593987ac47", "2658763f8d70e8c3303582d66ba3d736ce9d407e9507f6c6627e382d0144da157d73d0aee10ef034083cdd9013", "75536443a6c2189a57d553bb", "305cab5c2f9a6edccac307d6965febe3c86f2a1e31ac8c74e88924a10c2a29106bce980c803b7886985bba8ec5", "8c12bb58c84175b9f601b704d0f8a25c", }, { "63aeb46083100bbcc430f4f09bcc34410df9cfd5883d629e4af8645ffabb89c2", "b09830874dc549195a5d6da93b9dcc12aa1ec8af201c96bd", "1b3c9050e0a062f5a5cff7bec8706864cf8648142ec5cb1f9867ace384e9b2bba33aab8dc83e83b2d2fac70cd5189f2b5ab5", "7dcc05b0940198bd5c68cdf1", "d8b22e5d381de08a50b163c00dbbca6c07d61c80199cebd52234c7bd4f7ed0a90d47ef05617cdb8e3f782875ae629c0f0ad6", "194077f0e6d415bf7307d171e8484a9c", }, { "4826c1bf8b48088fece4008922173c500ff45790f945b1027f36110da4fecc92", "3a78fc7397944d762303b0a75974ac92a60e250bf112600a", "d26e3a2b92120ff8056bb992660cc8a2364792589c16a518b8d232b8184aed05ba8d4fd0b2ad2b928cd873e11905a21ffece5f1e63c974", "904d2cd3e50f7bfb9352f142", "21f4cf679662fad36f57945fc0c0753c3791261eb58d643278dfe1f14bfb585c5a01370ba96f18dc3f6b6945a2c6997330b24f12f5219a", "95397c54428f9d069c511b5c82e0151c", }, { "ec526c03d8a08e8a63751112428a76399c399e8b83d98c9247c73164805ac8fe", "2cc1a6ae89c2a091415fa2964b44a0e5da629d40d77b77f1", "567377f5b6df5442e70bc9a31bc450bd4febfcf89d7ca611353c7e612d8b7e36e859f6365ec7e5e99e9e0e882532666dd7203d06f6e25439ed871237", "35575b56716868b66cd21e24", "6b738274fe974438f1f5fca8ef1ee7df664f1e72bc54ccd3fb58c4a3df67ef9a73261df41ffe9c52aeafc8be4f6524baf9efb1558d4a57defec7bee3", "92599d4b14a795e8c375ec2a8960b4dc", }, } ================================================ FILE: go/aead/xchacha20poly1305_key_manager.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead import ( "fmt" "io" "golang.org/x/crypto/chacha20poly1305" "google.golang.org/protobuf/proto" "github.com/google/tink/go/aead/subtle" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/keyset" "github.com/google/tink/go/subtle/random" tpb "github.com/google/tink/go/proto/tink_go_proto" xpb "github.com/google/tink/go/proto/xchacha20_poly1305_go_proto" ) const ( xChaCha20Poly1305KeyVersion = 0 xChaCha20Poly1305TypeURL = "type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key" ) var ( errInvalidXChaCha20Poly1305Key = fmt.Errorf("xchacha20poly1305_key_manager: invalid key") errInvalidXChaCha20Poly1305KeyFormat = fmt.Errorf("xchacha20poly1305_key_manager: invalid key format") ) // xChaCha20Poly1305KeyManager generates XChaCha20Poly1305Key keys and produces // instances of XChaCha20Poly1305. type xChaCha20Poly1305KeyManager struct{} // Assert that xChaCha20Poly1305KeyManager implements the KeyManager interface. var _ registry.KeyManager = (*xChaCha20Poly1305KeyManager)(nil) // Primitive constructs a XChaCha20Poly1305 for the given serialized // XChaCha20Poly1305Key. func (km *xChaCha20Poly1305KeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidXChaCha20Poly1305Key } key := new(xpb.XChaCha20Poly1305Key) if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errInvalidXChaCha20Poly1305Key } if err := km.validateKey(key); err != nil { return nil, err } ret, err := subtle.NewXChaCha20Poly1305(key.KeyValue) if err != nil { return nil, fmt.Errorf("xchacha20poly1305_key_manager: cannot create new primitive: %v", err) } return ret, nil } // NewKey generates a new XChaCha20Poly1305Key. It ignores serializedKeyFormat // because the key size and other params are fixed. func (km *xChaCha20Poly1305KeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { return &xpb.XChaCha20Poly1305Key{ Version: xChaCha20Poly1305KeyVersion, KeyValue: random.GetRandomBytes(chacha20poly1305.KeySize), }, nil } // NewKeyData generates a new KeyData. It ignores serializedKeyFormat because // the key size and other params are fixed. This should be used solely by the // key management API. func (km *xChaCha20Poly1305KeyManager) NewKeyData(serializedKeyFormat []byte) (*tpb.KeyData, error) { key := &xpb.XChaCha20Poly1305Key{ Version: xChaCha20Poly1305KeyVersion, KeyValue: random.GetRandomBytes(chacha20poly1305.KeySize), } serializedKey, err := proto.Marshal(key) if err != nil { return nil, err } return &tpb.KeyData{ TypeUrl: xChaCha20Poly1305TypeURL, Value: serializedKey, KeyMaterialType: km.KeyMaterialType(), }, nil } // DoesSupport checks whether this key manager supports the given key type. func (km *xChaCha20Poly1305KeyManager) DoesSupport(typeURL string) bool { return typeURL == xChaCha20Poly1305TypeURL } // TypeURL returns the type URL of keys managed by this key manager. func (km *xChaCha20Poly1305KeyManager) TypeURL() string { return xChaCha20Poly1305TypeURL } // KeyMaterialType returns the key material type of this key manager. func (km *xChaCha20Poly1305KeyManager) KeyMaterialType() tpb.KeyData_KeyMaterialType { return tpb.KeyData_SYMMETRIC } // DeriveKey derives a new key from serializedKeyFormat and pseudorandomness. // Unlike NewKey, DeriveKey validates serializedKeyFormat's version. func (km *xChaCha20Poly1305KeyManager) DeriveKey(serializedKeyFormat []byte, pseudorandomness io.Reader) (proto.Message, error) { keyFormat := new(xpb.XChaCha20Poly1305KeyFormat) if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, fmt.Errorf("xchacha20poly1305_key_manager: %v", err) } err := keyset.ValidateKeyVersion(keyFormat.Version, xChaCha20Poly1305KeyVersion) if err != nil { return nil, fmt.Errorf("xchacha20poly1305_key_manager: %v", err) } keyValue := make([]byte, chacha20poly1305.KeySize) if _, err := io.ReadFull(pseudorandomness, keyValue); err != nil { return nil, fmt.Errorf("xchacha20poly1305_key_manager: not enough pseudorandomness given") } return &xpb.XChaCha20Poly1305Key{ Version: xChaCha20Poly1305KeyVersion, KeyValue: keyValue, }, nil } // validateKey validates the given XChaCha20Poly1305Key. func (km *xChaCha20Poly1305KeyManager) validateKey(key *xpb.XChaCha20Poly1305Key) error { err := keyset.ValidateKeyVersion(key.Version, xChaCha20Poly1305KeyVersion) if err != nil { return fmt.Errorf("xchacha20poly1305_key_manager: %v", err) } keySize := uint32(len(key.KeyValue)) if keySize != chacha20poly1305.KeySize { return fmt.Errorf("xchacha20poly1305_key_manager: key size != %d", chacha20poly1305.KeySize) } return nil } ================================================ FILE: go/aead/xchacha20poly1305_key_manager_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead_test import ( "bytes" "encoding/hex" "fmt" "testing" "github.com/google/go-cmp/cmp" "golang.org/x/crypto/chacha20poly1305" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" "github.com/google/tink/go/aead/subtle" tpb "github.com/google/tink/go/proto/tink_go_proto" xpb "github.com/google/tink/go/proto/xchacha20_poly1305_go_proto" ) func TestXChaCha20Poly1305GetPrimitive(t *testing.T) { km, err := registry.GetKeyManager(testutil.XChaCha20Poly1305TypeURL) if err != nil { t.Errorf("cannot obtain XChaCha20Poly1305 key manager: %s", err) } m, err := km.NewKey(nil) if err != nil { t.Fatalf("km.NewKey(nil) err = %q, want nil", err) } key, ok := m.(*xpb.XChaCha20Poly1305Key) if !ok { t.Fatal("m is not a *xpb.XChaCha20Poly1305Key") } serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } p, err := km.Primitive(serializedKey) if err != nil { t.Errorf("km.Primitive(%v) = %v; want nil", serializedKey, err) } if err := validateXChaCha20Poly1305Primitive(p, key); err != nil { t.Errorf("validateXChaCha20Poly1305Primitive(p, key) = %v; want nil", err) } } func TestXChaCha20Poly1305GetPrimitiveWithInvalidKeys(t *testing.T) { km, err := registry.GetKeyManager(testutil.XChaCha20Poly1305TypeURL) if err != nil { t.Errorf("cannot obtain XChaCha20Poly1305 key manager: %s", err) } invalidKeys := []*xpb.XChaCha20Poly1305Key{ // Bad key size. &xpb.XChaCha20Poly1305Key{ Version: testutil.XChaCha20Poly1305KeyVersion, KeyValue: random.GetRandomBytes(17), }, &xpb.XChaCha20Poly1305Key{ Version: testutil.XChaCha20Poly1305KeyVersion, KeyValue: random.GetRandomBytes(25), }, &xpb.XChaCha20Poly1305Key{ Version: testutil.XChaCha20Poly1305KeyVersion, KeyValue: random.GetRandomBytes(33), }, // Bad version. &xpb.XChaCha20Poly1305Key{ Version: testutil.XChaCha20Poly1305KeyVersion + 1, KeyValue: random.GetRandomBytes(chacha20poly1305.KeySize), }, } for _, key := range invalidKeys { serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := km.Primitive(serializedKey); err == nil { t.Errorf("km.Primitive(%v) = _, nil; want _, err", serializedKey) } } } func TestXChaCha20Poly1305NewKey(t *testing.T) { km, err := registry.GetKeyManager(testutil.XChaCha20Poly1305TypeURL) if err != nil { t.Errorf("cannot obtain XChaCha20Poly1305 key manager: %s", err) } m, err := km.NewKey(nil) if err != nil { t.Errorf("km.NewKey(nil) = _, %v; want _, nil", err) } key, ok := m.(*xpb.XChaCha20Poly1305Key) if !ok { t.Errorf("m is not a *xpb.XChaCha20Poly1305Key") } if err := validateXChaCha20Poly1305Key(key); err != nil { t.Errorf("validateXChaCha20Poly1305Key(%v) = %v; want nil", key, err) } } func TestXChaCha20Poly1305NewKeyData(t *testing.T) { km, err := registry.GetKeyManager(testutil.XChaCha20Poly1305TypeURL) if err != nil { t.Errorf("cannot obtain XChaCha20Poly1305 key manager: %s", err) } kd, err := km.NewKeyData(nil) if err != nil { t.Errorf("km.NewKeyData(nil) = _, %v; want _, nil", err) } if kd.TypeUrl != testutil.XChaCha20Poly1305TypeURL { t.Errorf("TypeUrl: %v != %v", kd.TypeUrl, testutil.XChaCha20Poly1305TypeURL) } if kd.KeyMaterialType != tpb.KeyData_SYMMETRIC { t.Errorf("KeyMaterialType: %v != SYMMETRIC", kd.KeyMaterialType) } key := new(xpb.XChaCha20Poly1305Key) if err := proto.Unmarshal(kd.Value, key); err != nil { t.Errorf("proto.Unmarshal(%v, key) = %v; want nil", kd.Value, err) } if err := validateXChaCha20Poly1305Key(key); err != nil { t.Errorf("validateXChaCha20Poly1305Key(%v) = %v; want nil", key, err) } p, err := registry.PrimitiveFromKeyData(kd) if err != nil { t.Errorf("registry.PrimitiveFromKeyData(kd) err = %v, want nil", err) } _, ok := p.(*subtle.XChaCha20Poly1305) if !ok { t.Error("registry.PrimitiveFromKeyData(kd) did not return a XChaCha20Poly1305 primitive") } } func TestXChaCha20Poly1305DoesSupport(t *testing.T) { km, err := registry.GetKeyManager(testutil.XChaCha20Poly1305TypeURL) if err != nil { t.Errorf("cannot obtain XChaCha20Poly1305 key manager: %s", err) } if !km.DoesSupport(testutil.XChaCha20Poly1305TypeURL) { t.Errorf("XChaCha20Poly1305KeyManager must support %s", testutil.XChaCha20Poly1305TypeURL) } if km.DoesSupport("some bad type") { t.Errorf("XChaCha20Poly1305KeyManager must only support %s", testutil.XChaCha20Poly1305TypeURL) } } func TestXChaCha20Poly1305TypeURL(t *testing.T) { km, err := registry.GetKeyManager(testutil.XChaCha20Poly1305TypeURL) if err != nil { t.Errorf("cannot obtain XChaCha20Poly1305 key manager: %s", err) } if kt := km.TypeURL(); kt != testutil.XChaCha20Poly1305TypeURL { t.Errorf("km.TypeURL() = %s; want %s", kt, testutil.XChaCha20Poly1305TypeURL) } } func TestXChaCha20Poly1305KeyMaterialType(t *testing.T) { km, err := registry.GetKeyManager(testutil.XChaCha20Poly1305TypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.XChaCha20Poly1305TypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } if got, want := keyManager.KeyMaterialType(), tpb.KeyData_SYMMETRIC; got != want { t.Errorf("KeyMaterialType() = %v, want %v", got, want) } } func TestXChaCha20Poly1305DeriveKey(t *testing.T) { km, err := registry.GetKeyManager(testutil.XChaCha20Poly1305TypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.XChaCha20Poly1305TypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } keyFormat, err := proto.Marshal(&xpb.XChaCha20Poly1305KeyFormat{Version: 0}) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } for _, test := range []struct { name string keyFormat []byte }{ { // nil unmarshals to an empty proto, which implies version = 0. name: "nil", keyFormat: nil, }, { // An empty proto implies version = 0. name: "empty", keyFormat: []byte{}, }, { name: "specified", keyFormat: keyFormat, }, } { t.Run(test.name, func(t *testing.T) { rand := random.GetRandomBytes(chacha20poly1305.KeySize) buf := &bytes.Buffer{} buf.Write(rand) // never returns a non-nil error k, err := keyManager.DeriveKey(test.keyFormat, buf) if err != nil { t.Fatalf("keyManager.DeriveKey() err = %v, want nil", err) } key := k.(*xpb.XChaCha20Poly1305Key) if got, want := len(key.GetKeyValue()), chacha20poly1305.KeySize; got != want { t.Errorf("key length = %d, want %d", got, want) } if diff := cmp.Diff(key.GetKeyValue(), rand); diff != "" { t.Errorf("incorrect derived key: diff = %v", diff) } }) } } func TestXChaCha20Poly1305DeriveKeyFailsWithInvalidKeyFormats(t *testing.T) { km, err := registry.GetKeyManager(testutil.XChaCha20Poly1305TypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.XChaCha20Poly1305TypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } invalidVersion, err := proto.Marshal(&xpb.XChaCha20Poly1305KeyFormat{Version: 10}) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } // Proto messages start with a VarInt, which always ends with a byte with the // MSB unset, so 0x80 is invalid. invalidSerialization, err := hex.DecodeString("80") if err != nil { t.Errorf("hex.DecodeString() err = %v, want nil", err) } for _, test := range []struct { name string keyFormat []byte }{ { name: "invalid version", keyFormat: invalidVersion, }, { name: "invalid serialization", keyFormat: invalidSerialization, }, } { t.Run(test.name, func(t *testing.T) { buf := bytes.NewBuffer(random.GetRandomBytes(chacha20poly1305.KeySize)) if _, err := keyManager.DeriveKey(test.keyFormat, buf); err == nil { t.Errorf("keyManager.DeriveKey() err = nil, want non-nil") } }) } } func TestXChaCha20Poly1305DeriveKeyFailsWithInsufficientRandomness(t *testing.T) { km, err := registry.GetKeyManager(testutil.XChaCha20Poly1305TypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.XChaCha20Poly1305TypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } keyFormat, err := proto.Marshal(&xpb.XChaCha20Poly1305KeyFormat{Version: 0}) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } { buf := bytes.NewBuffer(random.GetRandomBytes(chacha20poly1305.KeySize)) if _, err := keyManager.DeriveKey(keyFormat, buf); err != nil { t.Errorf("keyManager.DeriveKey() err = %v, want nil", err) } } { insufficientBuf := bytes.NewBuffer(random.GetRandomBytes(chacha20poly1305.KeySize - 1)) if _, err := keyManager.DeriveKey(keyFormat, insufficientBuf); err == nil { t.Errorf("keyManager.DeriveKey() err = nil, want non-nil") } } } func validateXChaCha20Poly1305Primitive(p any, key *xpb.XChaCha20Poly1305Key) error { cipher := p.(*subtle.XChaCha20Poly1305) // Try to encrypt and decrypt. pt := random.GetRandomBytes(32) aad := random.GetRandomBytes(32) ct, err := cipher.Encrypt(pt, aad) if err != nil { return fmt.Errorf("encryption failed") } decrypted, err := cipher.Decrypt(ct, aad) if err != nil { return fmt.Errorf("decryption failed") } if !bytes.Equal(decrypted, pt) { return fmt.Errorf("decryption failed") } return nil } func validateXChaCha20Poly1305Key(key *xpb.XChaCha20Poly1305Key) error { if key.Version != testutil.XChaCha20Poly1305KeyVersion { return fmt.Errorf("incorrect key version: keyVersion != %d", testutil.XChaCha20Poly1305KeyVersion) } if uint32(len(key.KeyValue)) != chacha20poly1305.KeySize { return fmt.Errorf("incorrect key size: keySize != %d", chacha20poly1305.KeySize) } // Try to encrypt and decrypt. p, err := subtle.NewXChaCha20Poly1305(key.KeyValue) if err != nil { return fmt.Errorf("invalid key: %v", key.KeyValue) } return validateXChaCha20Poly1305Primitive(p, key) } ================================================ FILE: go/core/cryptofmt/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep licenses(["notice"]) # keep go_library( name = "cryptofmt", srcs = ["cryptofmt.go"], importpath = "github.com/google/tink/go/core/cryptofmt", visibility = ["//visibility:public"], deps = ["//proto/tink_go_proto"], ) go_test( name = "cryptofmt_test", srcs = ["cryptofmt_test.go"], deps = [ ":cryptofmt", "//proto/tink_go_proto", ], ) alias( name = "go_default_library", actual = ":cryptofmt", visibility = ["//:__subpackages__"], ) ================================================ FILE: go/core/cryptofmt/cryptofmt.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package cryptofmt provides constants and convenience methods that define the // format of ciphertexts and signatures. package cryptofmt import ( "encoding/binary" "fmt" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( // NonRawPrefixSize is the prefix size of Tink and Legacy key types. NonRawPrefixSize = 5 // LegacyPrefixSize is the prefix size of legacy key types. // The prefix starts with \x00 and followed by a 4-byte key id. LegacyPrefixSize = NonRawPrefixSize // LegacyStartByte is the first byte of the prefix of legacy key types. LegacyStartByte = byte(0) // TinkPrefixSize is the prefix size of Tink key types. // The prefix starts with \x01 and followed by a 4-byte key id. TinkPrefixSize = NonRawPrefixSize // TinkStartByte is the first byte of the prefix of Tink key types. TinkStartByte = byte(1) // RawPrefixSize is the prefix size of Raw key types. // Raw prefix is empty. RawPrefixSize = 0 // RawPrefix is the empty prefix of Raw key types. RawPrefix = "" ) // OutputPrefix generates the prefix of ciphertexts produced by the crypto // primitive obtained from key. The prefix can be either empty (for RAW-type // prefix), or consists of a 1-byte indicator of the type of the prefix, // followed by 4 bytes of the key ID in big endian encoding. func OutputPrefix(key *tinkpb.Keyset_Key) (string, error) { switch key.OutputPrefixType { case tinkpb.OutputPrefixType_LEGACY, tinkpb.OutputPrefixType_CRUNCHY: return createOutputPrefix(LegacyPrefixSize, LegacyStartByte, key.KeyId), nil case tinkpb.OutputPrefixType_TINK: return createOutputPrefix(TinkPrefixSize, TinkStartByte, key.KeyId), nil case tinkpb.OutputPrefixType_RAW: return RawPrefix, nil default: return "", fmt.Errorf("crypto_format: unknown output prefix type") } } func createOutputPrefix(size int, startByte byte, keyID uint32) string { prefix := make([]byte, size) prefix[0] = startByte binary.BigEndian.PutUint32(prefix[1:], keyID) return string(prefix) } ================================================ FILE: go/core/cryptofmt/cryptofmt_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cryptofmt_test import ( "testing" "github.com/google/tink/go/core/cryptofmt" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) var tests = []struct { keyID uint32 result string // expected prefix }{ { keyID: 1000000, result: string([]byte{0, 15, 66, 64}), }, { keyID: 4294967295, result: string([]byte{255, 255, 255, 255}), }, { keyID: 0, result: string([]byte{0, 0, 0, 0}), }, } func TestOutputPrefix(t *testing.T) { key := new(tinkpb.Keyset_Key) for i, test := range tests { key.KeyId = test.keyID // legacy type key.OutputPrefixType = tinkpb.OutputPrefixType_LEGACY prefix, err := cryptofmt.OutputPrefix(key) if err != nil || !validatePrefix(prefix, cryptofmt.LegacyStartByte, test.result) { t.Errorf("incorrect legacy prefix in test %d", i) } // crunchy type key.OutputPrefixType = tinkpb.OutputPrefixType_CRUNCHY prefix, err = cryptofmt.OutputPrefix(key) if err != nil || !validatePrefix(prefix, cryptofmt.LegacyStartByte, test.result) { t.Errorf("incorrect legacy prefix in test %d", i) } // tink type key.OutputPrefixType = tinkpb.OutputPrefixType_TINK prefix, err = cryptofmt.OutputPrefix(key) if err != nil || !validatePrefix(prefix, cryptofmt.TinkStartByte, test.result) { t.Errorf("incorrect tink prefix in test %d", i) } // raw type key.OutputPrefixType = tinkpb.OutputPrefixType_RAW prefix, err = cryptofmt.OutputPrefix(key) if err != nil || prefix != cryptofmt.RawPrefix { t.Errorf("incorrect raw prefix in test %d", i) } } // unknown prefix type key.OutputPrefixType = tinkpb.OutputPrefixType_UNKNOWN_PREFIX if _, err := cryptofmt.OutputPrefix(key); err == nil { t.Errorf("expect an error when prefix type is unknown") } } func validatePrefix(prefix string, startByte byte, key string) bool { if prefix[0] != startByte { return false } return prefix[1:] == key } ================================================ FILE: go/core/primitiveset/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep licenses(["notice"]) # keep go_library( name = "primitiveset", srcs = ["primitiveset.go"], importpath = "github.com/google/tink/go/core/primitiveset", visibility = ["//visibility:public"], deps = [ "//core/cryptofmt", "//proto/tink_go_proto", ], ) go_test( name = "primitiveset_test", srcs = ["primitiveset_test.go"], deps = [ ":primitiveset", "//proto/tink_go_proto", "//testutil", "@com_github_google_go_cmp//cmp", ], ) alias( name = "go_default_library", actual = ":primitiveset", visibility = ["//visibility:public"], ) ================================================ FILE: go/core/primitiveset/primitiveset.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package primitiveset provides a container for a set of cryptographic // primitives. // // It provides also additional properties for the primitives it holds. In // particular, one of the primitives in the set can be distinguished as "the // primary" one. package primitiveset import ( "fmt" "github.com/google/tink/go/core/cryptofmt" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // Entry represents a single entry in the keyset. In addition to the actual // primitive, it holds the identifier and status of the primitive. type Entry struct { KeyID uint32 Primitive any Prefix string PrefixType tinkpb.OutputPrefixType Status tinkpb.KeyStatusType TypeURL string } func newEntry(keyID uint32, primitive any, prefix string, prefixType tinkpb.OutputPrefixType, status tinkpb.KeyStatusType, typeURL string) *Entry { return &Entry{ KeyID: keyID, Primitive: primitive, Prefix: prefix, Status: status, PrefixType: prefixType, TypeURL: typeURL, } } // PrimitiveSet is used for supporting key rotation: primitives in a set // correspond to keys in a keyset. Users will usually work with primitive // instances, which essentially wrap primitive sets. For example an instance of // an AEAD-primitive for a given keyset holds a set of AEAD-primitives // corresponding to the keys in the keyset, and uses the set members to do the // actual crypto operations: to encrypt data the primary AEAD-primitive from // the set is used, and upon decryption the ciphertext's prefix determines the // id of the primitive from the set. // // PrimitiveSet is a public to allow its use in implementations of custom // primitives. type PrimitiveSet struct { // Primary entry. Primary *Entry // The primitives are stored in a map of (ciphertext prefix, list of // primitives sharing the prefix). This allows quickly retrieving the // primitives sharing some particular prefix. Entries map[string][]*Entry // Stores entries in the original keyset key order. EntriesInKeysetOrder []*Entry Annotations map[string]string } // New returns an empty instance of PrimitiveSet. func New() *PrimitiveSet { return &PrimitiveSet{ Primary: nil, Entries: make(map[string][]*Entry), EntriesInKeysetOrder: make([]*Entry, 0), Annotations: nil, } } // RawEntries returns all primitives in the set that have RAW prefix. func (ps *PrimitiveSet) RawEntries() ([]*Entry, error) { return ps.EntriesForPrefix(cryptofmt.RawPrefix) } // EntriesForPrefix returns all primitives in the set that have the given prefix. func (ps *PrimitiveSet) EntriesForPrefix(prefix string) ([]*Entry, error) { result, found := ps.Entries[prefix] if !found { return []*Entry{}, nil } return result, nil } // Add creates a new entry in the primitive set and returns the added entry. func (ps *PrimitiveSet) Add(primitive any, key *tinkpb.Keyset_Key) (*Entry, error) { if key == nil || primitive == nil { return nil, fmt.Errorf("primitive_set: key and primitive must not be nil") } if key.GetKeyData() == nil { return nil, fmt.Errorf("primitive_set: keyData must not be nil") } if key.GetStatus() != tinkpb.KeyStatusType_ENABLED { return nil, fmt.Errorf("primitive_set: The key must be ENABLED") } prefix, err := cryptofmt.OutputPrefix(key) if err != nil { return nil, fmt.Errorf("primitive_set: %s", err) } e := newEntry( key.GetKeyId(), primitive, prefix, key.GetOutputPrefixType(), key.GetStatus(), key.GetKeyData().GetTypeUrl(), ) ps.Entries[prefix] = append(ps.Entries[prefix], e) ps.EntriesInKeysetOrder = append(ps.EntriesInKeysetOrder, e) return e, nil } ================================================ FILE: go/core/primitiveset/primitiveset_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package primitiveset_test import ( "fmt" "testing" "github.com/google/go-cmp/cmp" "github.com/google/tink/go/core/primitiveset" "github.com/google/tink/go/testutil" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func makeTestKey(keyID int, status tinkpb.KeyStatusType, outputPrefixType tinkpb.OutputPrefixType, typeURL string) *tinkpb.Keyset_Key { k := testutil.NewDummyKey(keyID, status, outputPrefixType) k.GetKeyData().TypeUrl = typeURL return k } func TestPrimitvesetNew(t *testing.T) { ps := primitiveset.New() if ps.Primary != nil || ps.Entries == nil || ps.EntriesInKeysetOrder == nil { t.Errorf("expect primary to be nil and primitives is initialized") } } func TestPrimitivesetAddAndEntriesInKeysetOrder(t *testing.T) { keys := []*tinkpb.Keyset_Key{ makeTestKey(1234543, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_TINK, "type.url.1"), makeTestKey(7213743, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_LEGACY, "type.url.2"), makeTestKey(5294722, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_RAW, "type.url.3"), } macs := make([]testutil.DummyMAC, len(keys)) for i := 0; i < len(macs); i++ { macs[i] = testutil.DummyMAC{Name: fmt.Sprintf("%d", i)} } ps := primitiveset.New() got := []*primitiveset.Entry{} for i := 0; i < len(macs); i++ { e, err := ps.Add(&macs[i], keys[i]) if err != nil { t.Fatalf("ps.Add(%q) err = %v, want nil", macs[i].Name, err) } got = append(got, e) } want := []*primitiveset.Entry{ { KeyID: 1234543, Status: tinkpb.KeyStatusType_ENABLED, Primitive: &testutil.DummyMAC{Name: "0"}, PrefixType: tinkpb.OutputPrefixType_TINK, TypeURL: "type.url.1", Prefix: string([]byte{1, 0, 18, 214, 111}), }, { KeyID: 7213743, Status: tinkpb.KeyStatusType_ENABLED, Primitive: &testutil.DummyMAC{Name: "1"}, PrefixType: tinkpb.OutputPrefixType_LEGACY, TypeURL: "type.url.2", Prefix: string([]byte{0, 0, 110, 18, 175}), }, { KeyID: 5294722, Status: tinkpb.KeyStatusType_ENABLED, Primitive: &testutil.DummyMAC{Name: "2"}, PrefixType: tinkpb.OutputPrefixType_RAW, TypeURL: "type.url.3", Prefix: "", }, } if !cmp.Equal(got, want) { t.Errorf("got = %v, want = %v", got, want) } if !cmp.Equal(ps.EntriesInKeysetOrder, want) { t.Errorf("EntriesInKeysetOrder = %v, want = %v", ps.EntriesInKeysetOrder, want) } } func TestPrimitivesetRawEntries(t *testing.T) { keys := []*tinkpb.Keyset_Key{ makeTestKey(1234543, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_TINK, "type.url.1"), makeTestKey(7213743, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_LEGACY, "type.url.2"), makeTestKey(9473277, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_RAW, "type.url.3"), makeTestKey(5294722, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_RAW, "type.url.4"), } macs := make([]testutil.DummyMAC, len(keys)) for i := 0; i < len(macs); i++ { macs[i] = testutil.DummyMAC{Name: fmt.Sprintf("Mac#%d", i)} } ps := primitiveset.New() for i := 0; i < len(macs); i++ { if _, err := ps.Add(macs[i], keys[i]); err != nil { t.Fatalf("ps.Add(%q) err = %v, want nil", macs[i].Name, err) } } got, err := ps.RawEntries() if err != nil { t.Errorf("RawEntries() err = %v, want nil", err) } want := []*primitiveset.Entry{ { KeyID: keys[2].GetKeyId(), Status: keys[2].GetStatus(), PrefixType: keys[2].GetOutputPrefixType(), TypeURL: keys[2].GetKeyData().GetTypeUrl(), Primitive: macs[2], }, { KeyID: keys[3].GetKeyId(), Status: keys[3].GetStatus(), PrefixType: keys[3].GetOutputPrefixType(), TypeURL: keys[3].GetKeyData().GetTypeUrl(), Primitive: macs[3], }, } if !cmp.Equal(got, want) { t.Errorf("Raw primitives got = %v, want = %v", got, want) } } func TestPrimitivesetPrefixedEntries(t *testing.T) { type testCase struct { tag string prefix string keys []*tinkpb.Keyset_Key primitives []any want []*primitiveset.Entry } for _, tc := range []testCase{ { tag: "legacy Prefix", prefix: string([]byte{0, 0, 18, 214, 111}), // LEGACY_PREFIX + 1234543, keys: []*tinkpb.Keyset_Key{ makeTestKey(1234543, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_LEGACY, "type.url.1"), makeTestKey(7213743, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_TINK, "type.url.2"), }, primitives: []any{ &testutil.DummyMAC{Name: "1"}, &testutil.DummyMAC{Name: "2"}, }, want: []*primitiveset.Entry{ { KeyID: 1234543, Status: tinkpb.KeyStatusType_ENABLED, Primitive: &testutil.DummyMAC{Name: "1"}, PrefixType: tinkpb.OutputPrefixType_LEGACY, TypeURL: "type.url.1", Prefix: string([]byte{0, 0, 18, 214, 111}), }, }, }, { tag: "raw prefix", prefix: "", keys: []*tinkpb.Keyset_Key{ makeTestKey(1234543, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_RAW, "type.url.1"), makeTestKey(7213743, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_TINK, "type.url.2"), }, primitives: []any{ &testutil.DummyMAC{Name: "1"}, &testutil.DummyMAC{Name: "2"}, }, want: []*primitiveset.Entry{ { KeyID: 1234543, Status: tinkpb.KeyStatusType_ENABLED, Primitive: &testutil.DummyMAC{Name: "1"}, PrefixType: tinkpb.OutputPrefixType_RAW, TypeURL: "type.url.1", Prefix: "", }, }, }, { tag: "tink prefix multiple entries", prefix: string([]byte{1, 0, 18, 214, 111}), // TINK_PREFIX + 1234543 keys: []*tinkpb.Keyset_Key{ makeTestKey(1234543, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_TINK, "type.url.1"), makeTestKey(1234543, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_TINK, "type.url.2"), makeTestKey(1234543, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_RAW, "type.url.3"), makeTestKey(7213743, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_TINK, "type.url.4"), }, primitives: []any{ &testutil.DummyMAC{Name: "1"}, &testutil.DummyMAC{Name: "2"}, &testutil.DummyMAC{Name: "3"}, &testutil.DummyMAC{Name: "4"}, }, want: []*primitiveset.Entry{ { KeyID: 1234543, Status: tinkpb.KeyStatusType_ENABLED, Primitive: &testutil.DummyMAC{Name: "1"}, PrefixType: tinkpb.OutputPrefixType_TINK, TypeURL: "type.url.1", Prefix: string([]byte{1, 0, 18, 214, 111}), }, { KeyID: 1234543, Status: tinkpb.KeyStatusType_ENABLED, Primitive: &testutil.DummyMAC{Name: "2"}, PrefixType: tinkpb.OutputPrefixType_TINK, TypeURL: "type.url.2", Prefix: string([]byte{1, 0, 18, 214, 111}), }, }, }, } { ps := primitiveset.New() for i := 0; i < len(tc.keys); i++ { if _, err := ps.Add(tc.primitives[i], tc.keys[i]); err != nil { t.Fatalf("ps.Add(%q) err = %v, want nil", tc.primitives[i], err) } } got, err := ps.EntriesForPrefix(tc.prefix) if err != nil { t.Errorf("EntriesForPrefix() err = %v, want nil", err) } if !cmp.Equal(got, tc.want) { t.Errorf("got = %v, want = %v", got, tc.want) } } } func TestAddWithInvalidInput(t *testing.T) { ps := primitiveset.New() type testCase struct { tag string primitive any key *tinkpb.Keyset_Key } for _, tc := range []testCase{ { tag: "nil primitive", primitive: nil, key: makeTestKey(0, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_TINK, "type.url.1"), }, { tag: "nil key", primitive: &testutil.DummyMAC{}, key: nil, }, { tag: "unknown prefix type", primitive: &testutil.DummyMAC{}, key: makeTestKey(0, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_UNKNOWN_PREFIX, "type.url.1"), }, { tag: "disabled key", primitive: &testutil.DummyMAC{}, key: makeTestKey(0, tinkpb.KeyStatusType_DISABLED, tinkpb.OutputPrefixType_TINK, "type.url.1"), }, { tag: "nil keyData", primitive: &testutil.DummyMAC{}, key: &tinkpb.Keyset_Key{ KeyData: nil, Status: tinkpb.KeyStatusType_ENABLED, OutputPrefixType: tinkpb.OutputPrefixType_TINK, KeyId: 0, }, }, } { if _, err := ps.Add(tc.primitive, tc.key); err == nil { t.Errorf("Add() err = nil, want error") } } } ================================================ FILE: go/core/registry/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep licenses(["notice"]) # keep go_library( name = "registry", srcs = [ "key_manager.go", "kms_client.go", "private_key_manager.go", "registry.go", ], importpath = "github.com/google/tink/go/core/registry", visibility = ["//visibility:public"], deps = [ "//proto/tink_go_proto", "//tink", "@org_golang_google_protobuf//proto", ], ) go_test( name = "registry_test", srcs = [ "custom_key_manager_test.go", "registry_test.go", ], deps = [ ":registry", "//aead", "//aead/subtle", "//insecurecleartextkeyset", "//internal/tinkerror", "//keyset", "//mac", "//mac/subtle", "//proto/aes_gcm_go_proto", "//proto/common_go_proto", "//proto/hmac_go_proto", "//proto/tink_go_proto", "//subtle/random", "//testing/fakekms", "//testutil", "@org_golang_google_protobuf//proto", "@org_golang_google_protobuf//types/known/wrapperspb", ], ) alias( name = "go_default_library", actual = ":registry", visibility = ["//visibility:public"], ) ================================================ FILE: go/core/registry/custom_key_manager_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package registry_test import ( "bytes" "errors" "fmt" "testing" wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" "google.golang.org/protobuf/proto" "github.com/google/tink/go/aead" "github.com/google/tink/go/aead/subtle" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/insecurecleartextkeyset" "github.com/google/tink/go/internal/tinkerror" "github.com/google/tink/go/keyset" "github.com/google/tink/go/subtle/random" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( customTypeURL = "type.googleapis.com/google.crypto.tink.CustomAesGcmKey" ) // customKeyManager is a custom implementation of registry.KeyManager for AES GCM 128. type customKeyManager struct{} // Assert that customKeyManager implements the KeyManager interface. var _ registry.KeyManager = (*customKeyManager)(nil) func (km *customKeyManager) Primitive(serializedKey []byte) (any, error) { key := new(wrapperspb.BytesValue) if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, fmt.Errorf("invalid key") } if len(key.GetValue()) != 16 { return nil, fmt.Errorf("invalid key") } return subtle.NewAESGCM(key.GetValue()) } // NewKey is only used by registry.NewKey, and that function is only used by KMSEnvelopeAEAD. // So there is no need to implement it. func (km *customKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { return nil, errors.New("not implemented") } func (km *customKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { keyFormat := new(wrapperspb.StringValue) if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, fmt.Errorf("invalid key format") } if keyFormat.GetValue() != "AEAD_AES_GCM_128" { return nil, fmt.Errorf("invalid key format") } keyValue := random.GetRandomBytes(16) key := &wrapperspb.BytesValue{ Value: keyValue, } serializedKey, err := proto.Marshal(key) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: customTypeURL, Value: serializedKey, KeyMaterialType: km.KeyMaterialType(), }, nil } func (km *customKeyManager) DoesSupport(typeURL string) bool { return typeURL == customTypeURL } func (km *customKeyManager) TypeURL() string { return customTypeURL } func (km *customKeyManager) KeyMaterialType() tinkpb.KeyData_KeyMaterialType { return tinkpb.KeyData_SYMMETRIC } // aesGCM128KeyTemplate creates a AES GCM 128 KeyTemplate for customKeyManager. func aesGCM128KeyTemplate() *tinkpb.KeyTemplate { format := &wrapperspb.StringValue{ Value: "AEAD_AES_GCM_128", } serializedFormat, err := proto.Marshal(format) if err != nil { tinkerror.Fail(fmt.Sprintf("failed to marshal key format: %s", err)) } return &tinkpb.KeyTemplate{ TypeUrl: customTypeURL, Value: serializedFormat, OutputPrefixType: tinkpb.OutputPrefixType_RAW, } } // aesGCM128KeyToKeysetHandle creates a keyset.Handle with one custom AES GCM 128 key. func aesGCM128KeyToKeysetHandle(rawAESKey []byte, keyID uint32, prefixType tinkpb.OutputPrefixType) (*keyset.Handle, error) { if len(rawAESKey) != 16 { return nil, fmt.Errorf("invalid key length") } key := &wrapperspb.BytesValue{Value: rawAESKey} serializedKey, err := proto.Marshal(key) if err != nil { return nil, err } keyData := &tinkpb.KeyData{ TypeUrl: customTypeURL, Value: serializedKey, KeyMaterialType: tinkpb.KeyData_SYMMETRIC, } ks := &tinkpb.Keyset{ PrimaryKeyId: keyID, Key: []*tinkpb.Keyset_Key{ &tinkpb.Keyset_Key{ KeyData: keyData, Status: tinkpb.KeyStatusType_ENABLED, KeyId: keyID, OutputPrefixType: prefixType, }, }, } serializedKeyset, err := proto.Marshal(ks) if err != nil { return nil, err } return insecurecleartextkeyset.Read(keyset.NewBinaryReader(bytes.NewBuffer(serializedKeyset))) } func TestCreateEncryptDecrypt(t *testing.T) { handle, err := keyset.NewHandle(aesGCM128KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle(aesGCM128KeyTemplate()) err = %v, want nil", err) } primitive, err := aead.New(handle) if err != nil { t.Fatalf("aead.New(handle) err = %v, want nil", err) } plaintext := []byte("plaintext") associatedData := []byte("associatedData") ciphertext, err := primitive.Encrypt(plaintext, associatedData) if err != nil { t.Fatalf("primitive.Encrypt(plaintext, associatedData) err = %v, want nil", err) } decrypted, err := primitive.Decrypt(ciphertext, associatedData) if err != nil { t.Fatalf("primitive.Decrypt(ciphertext, associatedData) err = %v, want nil", err) } if !bytes.Equal(plaintext, decrypted) { t.Errorf("primitive.Decrypt(ciphertext, associatedData) = %q, want: %q", decrypted, plaintext) } } func TestImportExistingKeyDecryptsExistingCiphertext(t *testing.T) { rawAesKey := random.GetRandomBytes(16) plaintext := []byte("plaintext") associatedData := []byte("associatedData") // Create a AES GCM 128 ciphertext using rawAesKey. aesGCMForRawAesKey, err := subtle.NewAESGCM(rawAesKey) if err != nil { t.Fatalf("subtle.NewAESGCM(rawAesKey) err = %v, want nil", err) } ciphertext, err := aesGCMForRawAesKey.Encrypt(plaintext, associatedData) if err != nil { t.Fatalf("aesGCMForRawAesKey.Encrypt(plaintext, associatedData) err = %v, want nil", err) } // Import rawAesKey into a Tink keyset.Handle, and decrypt the ciphertext. handle, err := aesGCM128KeyToKeysetHandle(rawAesKey, 123, tinkpb.OutputPrefixType_RAW) if err != nil { t.Fatalf("aesGCM128KeyToKeysetHandle() err = %v, want nil", err) } primitive, err := aead.New(handle) if err != nil { t.Fatalf("aead.New(handle) err = %v, want nil", err) } gotPlaintext, err := primitive.Decrypt(ciphertext, associatedData) if err != nil { t.Fatalf("primitive.Decrypt(ciphertext, associatedData) err = %v, want nil", err) } if !bytes.Equal(plaintext, gotPlaintext) { t.Fatalf("primitive.Decrypt(ciphertext, associatedData) = %q, want: %q", gotPlaintext, plaintext) } } func TestEncryptAndDecryptWithTinkPrefix(t *testing.T) { // Create an AEAD for rawAesKey with output prefix type TINK. rawAesKey := random.GetRandomBytes(16) handle, err := aesGCM128KeyToKeysetHandle(rawAesKey, 0x11223344, tinkpb.OutputPrefixType_TINK) if err != nil { t.Fatalf("aesGCM128KeyToKeysetHandle() err = %v, want nil", err) } primitive, err := aead.New(handle) if err != nil { t.Fatalf("aead.New(handle) err = %v, want nil", err) } // Encrypt and decrypt. plaintext := []byte("plaintext") associatedData := []byte("associatedData") ciphertext, err := primitive.Encrypt(plaintext, associatedData) if err != nil { t.Fatalf("primitive.Encrypt(plaintext, associatedData) err = %v, want nil", err) } gotPlaintext, err := primitive.Decrypt(ciphertext, associatedData) if err != nil { t.Fatalf("primitive.Decrypt(ciphertext, associatedData) err = %v, want nil", err) } if !bytes.Equal(plaintext, gotPlaintext) { t.Fatalf("primitive.Decrypt(ciphertext, associatedData) = %q, want: %q", gotPlaintext, plaintext) } // Check that ciphertext has the correct prefix. gotPrefix := ciphertext[:5] wantPrefix := []byte{0x01, 0x11, 0x22, 0x33, 0x44} if !bytes.Equal(gotPrefix, wantPrefix) { t.Fatalf("ciphertext[:5] = %q, want: %q", gotPrefix, wantPrefix) } // Check that subtle.NewAESGCM with rawAesKey can decrypt the ciphertext if the prefix is removed. aesGCMForRawAesKey, err := subtle.NewAESGCM(rawAesKey) if err != nil { t.Fatalf("subtle.NewAESGCM(rawAesKey) err = %v, want nil", err) } gotPlaintext, err = aesGCMForRawAesKey.Decrypt(ciphertext[5:], associatedData) if err != nil { t.Fatalf("aesGCMForRawAesKey.Decrypt() err = %v, want nil", err) } if !bytes.Equal(plaintext, gotPlaintext) { t.Fatalf("aesGCMForRawAesKey.Decrypt() = %q, want: %q", gotPlaintext, plaintext) } } func TestMixedKeysetWorks(t *testing.T) { rawAesKey := random.GetRandomBytes(16) // Create a AES GCM 128 ciphertext using rawAesKey. subtlePrimitive, err := subtle.NewAESGCM(rawAesKey) if err != nil { t.Fatalf("subtle.NewAESGCM(rawAesKey) err = %v, want nil", err) } plaintext := []byte("plaintext") associatedData := []byte("associatedData") ciphertext, err := subtlePrimitive.Encrypt(plaintext, associatedData) if err != nil { t.Fatalf("subtlePrimitive.Encrypt(plaintext, associatedData) err = %v, want nil", err) } // Create handle2, which is a keyset.Handle that contains a customKeyManager key of rawAesKey and // a new, non-customKeyManager key. handle1, err := aesGCM128KeyToKeysetHandle(rawAesKey, 123, tinkpb.OutputPrefixType_RAW) if err != nil { t.Fatalf("aesGCM128KeyToKeysetHandle() err = %v, want nil", err) } manager := keyset.NewManagerFromHandle(handle1) keyID, err := manager.Add(aead.AES128CTRHMACSHA256KeyTemplate()) if err != nil { t.Fatalf("manager.Add(aead.AES128CTRHMACSHA256KeyTemplate()) err = %v, want nil", err) } err = manager.SetPrimary(keyID) if err != nil { t.Fatalf("manager.SetPrimary(keyID) = %v", err) } handle2, err := manager.Handle() if err != nil { t.Fatalf("manager.Handle() err = %v", err) } primitive, err := aead.New(handle2) if err != nil { t.Fatalf("aead.New(handle2) err = %v", err) } gotPlaintext, err := primitive.Decrypt(ciphertext, associatedData) if err != nil { t.Fatalf("primitive.Decrypt(ciphertext, associatedData) err = %v, want nil", err) } if !bytes.Equal(plaintext, gotPlaintext) { t.Errorf("primitive.Decrypt(ciphertext, associatedData) = %q, want: %q", gotPlaintext, plaintext) } } func TestSerializeAndParseKeysetWorks(t *testing.T) { handle, err := keyset.NewHandle(aesGCM128KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle(aesGCM128KeyTemplate()) err = %v, want nil", err) } primitive, err := aead.New(handle) if err != nil { t.Fatalf("aead.New(handle) err = %v, want nil", err) } plaintext := []byte("plaintext") associatedData := []byte("associatedData") ciphertext, err := primitive.Encrypt(plaintext, associatedData) if err != nil { t.Fatalf("primitive.Encrypt(plaintext, associatedData) err = %v, want nil", err) } // Serialize the keyset. buff := &bytes.Buffer{} err = insecurecleartextkeyset.Write(handle, keyset.NewBinaryWriter(buff)) if err != nil { t.Fatalf("insecurecleartextkeyset.Write(handle, keyset.NewBinaryWriter(buff)) = %v, want nil", err) } serializedKeyset := buff.Bytes() // Parse the keyset. parsedHandle, err := insecurecleartextkeyset.Read( keyset.NewBinaryReader(bytes.NewBuffer(serializedKeyset))) if err != nil { t.Fatalf("insecurecleartextkeyset.Read(keyset.NewBinaryReader(bytes.NewBuffer(serializedKeyset))) = %v, want nil", err) } primitive2, err := aead.New(parsedHandle) if err != nil { t.Fatalf("aead.New(parsedHandle) err = %v, want nil", err) } gotPlaintext, err := primitive2.Decrypt(ciphertext, associatedData) if err != nil { t.Fatalf("primitive2.Decrypt(ciphertext, associatedData) err = %v, want nil", err) } if !bytes.Equal(plaintext, gotPlaintext) { t.Errorf("primitive2.Decrypt(ciphertext, associatedData) = %q, want: %q", gotPlaintext, plaintext) } } func init() { registry.RegisterKeyManager(&customKeyManager{}) } ================================================ FILE: go/core/registry/key_manager.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package registry import ( "google.golang.org/protobuf/proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // KeyManager "understands" keys of a specific key types: it can generate keys of a supported type // and create primitives for supported keys. A key type is identified by the global name of the // protocol buffer that holds the corresponding key material, and is given by type_url-field of // KeyData-protocol buffer. type KeyManager interface { // Primitive constructs a primitive instance for the key given in serializedKey, which must be a // serialized key protocol buffer handled by this manager. Primitive(serializedKey []byte) (any, error) // NewKey generates a new key according to specification in serializedKeyFormat, which must be // supported by this manager. // // Deprecated: Tink always used [NewKeyData] to create new keys. This function is // unused (except in the unused and deprecated function [registry.NewKey]). It doesn't need to be // implemented. NewKey(serializedKeyFormat []byte) (proto.Message, error) // DoesSupport returns true iff this KeyManager supports key type identified by typeURL. DoesSupport(typeURL string) bool // TypeURL returns the type URL that identifies the key type of keys managed by this key manager. TypeURL() string // APIs for Key Management // NewKeyData generates a new KeyData according to specification in serializedkeyFormat. // This should be used solely by the key management API. NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) } ================================================ FILE: go/core/registry/kms_client.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package registry import "github.com/google/tink/go/tink" // KMSClient knows how to produce primitives backed by keys stored in remote KMS services. type KMSClient interface { // Supported true if this client does support keyURI Supported(keyURI string) bool // GetAEAD gets an AEAD backend by keyURI. GetAEAD(keyURI string) (tink.AEAD, error) } ================================================ FILE: go/core/registry/private_key_manager.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package registry import ( tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // PrivateKeyManager is a special type of KeyManager that understands private key types. type PrivateKeyManager interface { KeyManager // PublicKeyData extracts the public key data from the private key. PublicKeyData(serializedKey []byte) (*tinkpb.KeyData, error) } ================================================ FILE: go/core/registry/registry.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package registry provides a container that for each supported key type holds // a corresponding KeyManager object, which can generate new keys or // instantiate the primitive corresponding to given key. // // Registry is initialized at startup, and is later used to instantiate // primitives for given keys or keysets. Keeping KeyManagers for all primitives // in a single Registry (rather than having a separate KeyManager per // primitive) enables modular construction of compound primitives from "simple" // ones, e.g., AES-CTR-HMAC AEAD encryption uses IND-CPA encryption and a MAC. // // Note that regular users will usually not work directly with Registry, but // rather via primitive factories, which in the background query the Registry // for specific KeyManagers. Registry is public though, to enable // configurations with custom primitives and KeyManagers. package registry import ( "fmt" "sync" "google.golang.org/protobuf/proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) var ( keyManagersMu sync.RWMutex keyManagers = make(map[string]KeyManager) // typeURL -> KeyManager kmsClientsMu sync.RWMutex kmsClients = []KMSClient{} ) // RegisterKeyManager registers the given key manager. // Does not allow to overwrite existing key managers. func RegisterKeyManager(keyManager KeyManager) error { keyManagersMu.Lock() defer keyManagersMu.Unlock() typeURL := keyManager.TypeURL() if _, existed := keyManagers[typeURL]; existed { return fmt.Errorf("registry.RegisterKeyManager: type %s already registered", typeURL) } keyManagers[typeURL] = keyManager return nil } // GetKeyManager returns the key manager for the given typeURL if existed. func GetKeyManager(typeURL string) (KeyManager, error) { keyManagersMu.RLock() defer keyManagersMu.RUnlock() keyManager, existed := keyManagers[typeURL] if !existed { return nil, fmt.Errorf("registry.GetKeyManager: unsupported key type: %s", typeURL) } return keyManager, nil } // NewKeyData generates a new KeyData for the given key template. func NewKeyData(template *tinkpb.KeyTemplate) (*tinkpb.KeyData, error) { if template == nil { return nil, fmt.Errorf("registry.NewKeyData: invalid key template") } keyManager, err := GetKeyManager(template.TypeUrl) if err != nil { return nil, err } return keyManager.NewKeyData(template.Value) } // NewKey generates a new key for the given key template. // // Deprecated: use [NewKeyData] instead. func NewKey(template *tinkpb.KeyTemplate) (proto.Message, error) { if template == nil { return nil, fmt.Errorf("registry.NewKey: invalid key template") } keyManager, err := GetKeyManager(template.TypeUrl) if err != nil { return nil, err } return keyManager.NewKey(template.Value) } // PrimitiveFromKeyData creates a new primitive for the key given in the given KeyData. // Note that the returned primitive does not add/remove the output prefix. // It is the caller's responsibility to handle this correctly, based on the key's output_prefix_type. func PrimitiveFromKeyData(keyData *tinkpb.KeyData) (any, error) { if keyData == nil { return nil, fmt.Errorf("registry.PrimitiveFromKeyData: invalid key data") } return Primitive(keyData.TypeUrl, keyData.Value) } // Primitive creates a new primitive for the given serialized key using the KeyManager // identified by the given typeURL. // Note that the returned primitive does not add/remove the output prefix. // It is the caller's responsibility to handle this correctly, based on the key's output_prefix_type. func Primitive(typeURL string, serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, fmt.Errorf("registry.Primitive: invalid serialized key") } keyManager, err := GetKeyManager(typeURL) if err != nil { return nil, err } return keyManager.Primitive(serializedKey) } // RegisterKMSClient is used to register a new KMS client. // // This function adds an object to a global list. It should only be called on // startup. // // In many cases, registering a KMS client is not needed. Instead, call // kmsClient.GetAEAD to get a remote AEAD, and then use it to encrypt // a keyset with keyset.Write, or to create an envelope AEAD using // aead.NewKMSEnvelopeAEAD2. func RegisterKMSClient(kmsClient KMSClient) { kmsClientsMu.Lock() defer kmsClientsMu.Unlock() kmsClients = append(kmsClients, kmsClient) } // GetKMSClient fetches a KMSClient by a given URI. func GetKMSClient(keyURI string) (KMSClient, error) { kmsClientsMu.RLock() defer kmsClientsMu.RUnlock() for _, kmsClient := range kmsClients { if kmsClient.Supported(keyURI) { return kmsClient, nil } } return nil, fmt.Errorf("KMS client supporting %s not found", keyURI) } // ClearKMSClients removes all registered KMS clients. // // Should only be used in tests. func ClearKMSClients() { kmsClientsMu.Lock() defer kmsClientsMu.Unlock() kmsClients = []KMSClient{} } ================================================ FILE: go/core/registry/registry_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package registry_test import ( "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/aead" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/mac" "github.com/google/tink/go/mac/subtle" "github.com/google/tink/go/testing/fakekms" "github.com/google/tink/go/testutil" gcmpb "github.com/google/tink/go/proto/aes_gcm_go_proto" commonpb "github.com/google/tink/go/proto/common_go_proto" hmacpb "github.com/google/tink/go/proto/hmac_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestRegisterKeyManager(t *testing.T) { // get HMACKeyManager _, err := registry.GetKeyManager(testutil.HMACTypeURL) if err != nil { t.Errorf("unexpected error: %s", err) } // get AESGCMKeyManager _, err = registry.GetKeyManager(testutil.AESGCMTypeURL) if err != nil { t.Errorf("unexpected error: %s", err) } // some random typeurl if _, err = registry.GetKeyManager("some url"); err == nil { t.Errorf("expect an error when a type url doesn't exist in the registry") } } func TestRegisterKeyManagerWithCollision(t *testing.T) { // dummyKeyManager's typeURL is equal to that of AESGCM var dummyKeyManager = new(testutil.DummyAEADKeyManager) // This should fail because overwriting is disallowed. err := registry.RegisterKeyManager(dummyKeyManager) if err == nil { t.Errorf("%s shouldn't be registered again", testutil.AESGCMTypeURL) } km, err := registry.GetKeyManager(testutil.AESGCMTypeURL) if err != nil { t.Errorf("unexpected error: %s", err) } // This should fail because overwriting is disallowed, even with the same key manager. err = registry.RegisterKeyManager(km) if err == nil { t.Errorf("%s shouldn't be registered again", testutil.AESGCMTypeURL) } } func TestNewKeyData(t *testing.T) { // new Keydata from a Hmac KeyTemplate keyData, err := registry.NewKeyData(mac.HMACSHA256Tag128KeyTemplate()) if err != nil { t.Errorf("unexpected error: %s", err) } if keyData.TypeUrl != testutil.HMACTypeURL { t.Errorf("invalid key data") } key := new(hmacpb.HmacKey) if err := proto.Unmarshal(keyData.Value, key); err != nil { t.Errorf("unexpected error when unmarshal HmacKey: %s", err) } // nil if _, err := registry.NewKeyData(nil); err == nil { t.Errorf("expect an error when key template is nil") } // unregistered type url template := &tinkpb.KeyTemplate{TypeUrl: "some url", Value: []byte{0}} if _, err := registry.NewKeyData(template); err == nil { t.Errorf("expect an error when key template contains unregistered typeURL") } } func TestNewKey(t *testing.T) { // aead template aesGcmTemplate := aead.AES128GCMKeyTemplate() key, err := registry.NewKey(aesGcmTemplate) if err != nil { t.Errorf("unexpected error: %s", err) } var aesGcmKey = key.(*gcmpb.AesGcmKey) aesGcmFormat := new(gcmpb.AesGcmKeyFormat) if err := proto.Unmarshal(aesGcmTemplate.Value, aesGcmFormat); err != nil { t.Errorf("unexpected error: %s", err) } if aesGcmFormat.KeySize != uint32(len(aesGcmKey.KeyValue)) { t.Errorf("key doesn't match template") } //nil if _, err := registry.NewKey(nil); err == nil { t.Errorf("expect an error when key template is nil") } // unregistered type url template := &tinkpb.KeyTemplate{TypeUrl: "some url", Value: []byte{0}} if _, err := registry.NewKey(template); err == nil { t.Errorf("expect an error when key template is not registered") } } func TestPrimitiveFromKeyData(t *testing.T) { // hmac keydata keyData := testutil.NewHMACKeyData(commonpb.HashType_SHA256, 16) p, err := registry.PrimitiveFromKeyData(keyData) if err != nil { t.Errorf("unexpected error: %s", err) } var _ *subtle.HMAC = p.(*subtle.HMAC) // unregistered url keyData.TypeUrl = "some url" if _, err := registry.PrimitiveFromKeyData(keyData); err == nil { t.Errorf("expect an error when typeURL has not been registered") } // unmatched url keyData.TypeUrl = testutil.AESGCMTypeURL if _, err := registry.PrimitiveFromKeyData(keyData); err == nil { t.Errorf("expect an error when typeURL doesn't match key") } // nil if _, err := registry.PrimitiveFromKeyData(nil); err == nil { t.Errorf("expect an error when key data is nil") } } func TestPrimitive(t *testing.T) { // hmac key key := testutil.NewHMACKey(commonpb.HashType_SHA256, 16) serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal() err = %s, want nil", err) } p, err := registry.Primitive(testutil.HMACTypeURL, serializedKey) if err != nil { t.Fatalf("registry.Primitive() err = %s, want nil", err) } if _, ok := p.(*subtle.HMAC); !ok { t.Error("object returned by registry.Primitive() does not implement *subtle.HMAC") } // unregistered url if _, err := registry.Primitive("some url", serializedKey); err == nil { t.Errorf("expect an error when typeURL has not been registered") } // unmatched url if _, err := registry.Primitive(testutil.AESGCMTypeURL, serializedKey); err == nil { t.Errorf("expect an error when typeURL doesn't match key") } // void key if _, err := registry.Primitive(testutil.AESGCMTypeURL, nil); err == nil { t.Errorf("expect an error when key is nil") } if _, err := registry.Primitive(testutil.AESGCMTypeURL, []byte{}); err == nil { t.Errorf("expect an error when key is nil") } if _, err := registry.Primitive(testutil.AESGCMTypeURL, []byte{0}); err == nil { t.Errorf("expect an error when key is nil") } } func TestRegisterKmsClient(t *testing.T) { client1, err := fakekms.NewClient("fake-kms://prefix1") if err != nil { t.Fatalf("fakekms.NewClient('fake-kms://prefix1') failed: %v", err) } client2, err := fakekms.NewClient("fake-kms://prefix2") if err != nil { t.Fatalf("fakekms.NewClient('fake-kms://prefix2') failed: %v", err) } registry.RegisterKMSClient(client1) registry.RegisterKMSClient(client2) output1, err := registry.GetKMSClient("fake-kms://prefix1-postfix") if err != nil { t.Errorf("registry.GetKMSClient('fake-kms://prefix1-postfix') failed: %v", err) } if output1 != client1 { t.Errorf("registry.GetKMSClient('fake-kms://prefix1-postfix') did not return client1") } output2, err := registry.GetKMSClient("fake-kms://prefix2-postfix") if err != nil { t.Errorf("registry.GetKMSClient('fake-kms://prefix2-postfix') failed: %v", err) } if output2 != client2 { t.Errorf("registry.GetKMSClient('fake-kms://prefix2-postfix') did not return client2") } _, err = registry.GetKMSClient("fake-kms://unknown-prefix") if err == nil { t.Errorf("registry.GetKMSClient('fake-kms://unknown-prefix') succeeded, want fail") } _, err = registry.GetKMSClient("bad-kms://unknown-prefix") if err == nil { t.Errorf("registry.GetKMSClient('bad-kms://unknown-prefix') succeeded, want fail") } } func TestRegisterTwoKmsClientsForSameUri_firstGetsReturned(t *testing.T) { abcClient, err := fakekms.NewClient("fake-kms://abc") if err != nil { t.Fatalf("fakekms.NewClient(\"fake-kms://abc\") err = %q, want nil", err) } registry.RegisterKMSClient(abcClient) abc123Client, err := fakekms.NewClient("fake-kms://abc123") if err != nil { t.Fatalf("fakekms.NewClient(\"fake-kms://abc123\") err = %q, want nil", err) } registry.RegisterKMSClient(abc123Client) // Both clients support "fake-kms://abc123". But abcClient was registered first. got, err := registry.GetKMSClient("fake-kms://abc123") if err != nil { t.Fatalf("registry.GetKMSClient(\"fake-kms://abc123\") err = %q, want nil", err) } if got != abcClient { t.Errorf("registry.GetKMSClient(\"fake-kms://abc123\") = %q, want abcClient", got) } } func TestClearKMSClients(t *testing.T) { client, err := fakekms.NewClient("fake-kms://xyz") if err != nil { t.Fatalf("fakekms.NewClient('fake-kms://xyz') failed: %v", err) } registry.RegisterKMSClient(client) _, err = registry.GetKMSClient("fake-kms://xyz-123") if err != nil { t.Errorf("registry.GetKMSClient('fake-kms://xyz-123') failed: %v", err) } registry.ClearKMSClients() _, err = registry.GetKMSClient("fake-kms://xyz-123") if err == nil { t.Errorf("registry.GetKMSClient('fake-kms://xyz-123') succeeded, want fail") } } ================================================ FILE: go/daead/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep licenses(["notice"]) # keep go_library( name = "daead", srcs = [ "aes_siv_key_manager.go", "daead.go", "daead_factory.go", "daead_key_templates.go", ], importpath = "github.com/google/tink/go/daead", visibility = ["//visibility:public"], deps = [ "//core/cryptofmt", "//core/primitiveset", "//core/registry", "//daead/subtle", "//internal/internalregistry", "//internal/monitoringutil", "//internal/tinkerror", "//keyset", "//monitoring", "//proto/aes_siv_go_proto", "//proto/tink_go_proto", "//subtle/random", "//tink", "@org_golang_google_protobuf//proto", ], ) go_test( name = "daead_test", srcs = [ "aes_siv_key_manager_test.go", "daead_benchmark_test.go", "daead_factory_test.go", "daead_init_test.go", "daead_key_templates_test.go", "daead_test.go", ], deps = [ ":daead", "//core/cryptofmt", "//core/registry", "//daead/subtle", "//insecurecleartextkeyset", "//internal/internalregistry", "//internal/testing/stubkeymanager", "//keyset", "//monitoring", "//proto/aes_siv_go_proto", "//proto/tink_go_proto", "//signature", "//subtle/random", "//testing/fakemonitoring", "//testkeyset", "//testutil", "//tink", "@com_github_google_go_cmp//cmp", "@com_github_google_go_cmp//cmp/cmpopts", "@org_golang_google_protobuf//proto", ], ) alias( name = "go_default_library", actual = ":daead", visibility = ["//visibility:public"], ) ================================================ FILE: go/daead/aes_siv_key_manager.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package daead import ( "errors" "fmt" "io" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/daead/subtle" "github.com/google/tink/go/keyset" "github.com/google/tink/go/subtle/random" aspb "github.com/google/tink/go/proto/aes_siv_go_proto" tpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( aesSIVKeyVersion = 0 aesSIVTypeURL = "type.googleapis.com/google.crypto.tink.AesSivKey" ) var ( errInvalidAESSIVKeyFormat = errors.New("aes_siv_key_manager: invalid key format") errInvalidAESSIVKeySize = fmt.Errorf("aes_siv_key_manager: key size != %d", subtle.AESSIVKeySize) ) // aesSIVKeyManager generates AES-SIV keys and produces instances of AES-SIV. type aesSIVKeyManager struct{} // Assert that aesSIVKeyManager implements the KeyManager interface. var _ registry.KeyManager = (*aesSIVKeyManager)(nil) // Primitive constructs an AES-SIV for the given serialized AesSivKey. func (km *aesSIVKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errors.New("aes_siv_key_manager: invalid key") } key := new(aspb.AesSivKey) if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, err } if err := km.validateKey(key); err != nil { return nil, err } ret, err := subtle.NewAESSIV(key.KeyValue) if err != nil { return nil, fmt.Errorf("aes_siv_key_manager: cannot create new primitive: %v", err) } return ret, nil } // NewKey generates a new AesSivKey. serializedKeyFormat is optional because // there is only one valid key format. func (km *aesSIVKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { // A nil serializedKeyFormat is acceptable. If specified, validate. if serializedKeyFormat != nil { keyFormat := new(aspb.AesSivKeyFormat) if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, errInvalidAESSIVKeyFormat } if keyFormat.KeySize != subtle.AESSIVKeySize { return nil, errInvalidAESSIVKeySize } } return &aspb.AesSivKey{ Version: aesSIVKeyVersion, KeyValue: random.GetRandomBytes(subtle.AESSIVKeySize), }, nil } // NewKeyData generates a new KeyData. serializedKeyFormat is optional because // there is only one valid key format. This should be used solely by the key // management API. func (km *aesSIVKeyManager) NewKeyData(serializedKeyFormat []byte) (*tpb.KeyData, error) { key, err := km.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, fmt.Errorf("aes_siv_key_manager: %v", err) } return &tpb.KeyData{ TypeUrl: aesSIVTypeURL, Value: serializedKey, KeyMaterialType: km.KeyMaterialType(), }, nil } // DoesSupport checks whether this key manager supports the given key type. func (km *aesSIVKeyManager) DoesSupport(typeURL string) bool { return typeURL == aesSIVTypeURL } // TypeURL returns the type URL of keys managed by this key manager. func (km *aesSIVKeyManager) TypeURL() string { return aesSIVTypeURL } // KeyMaterialType returns the key material type of this key manager. func (km *aesSIVKeyManager) KeyMaterialType() tpb.KeyData_KeyMaterialType { return tpb.KeyData_SYMMETRIC } // DeriveKey derives a new key from serializedKeyFormat and pseudorandomness. // Unlike NewKey, DeriveKey validates serializedKeyFormat. func (km *aesSIVKeyManager) DeriveKey(serializedKeyFormat []byte, pseudorandomness io.Reader) (proto.Message, error) { keyFormat := new(aspb.AesSivKeyFormat) if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, errInvalidAESSIVKeyFormat } if keyFormat.GetKeySize() != subtle.AESSIVKeySize { return nil, errInvalidAESSIVKeySize } if err := keyset.ValidateKeyVersion(keyFormat.GetVersion(), aesSIVKeyVersion); err != nil { return nil, fmt.Errorf("aes_siv_key_manager: invalid key version: %s", err) } keyValue := make([]byte, subtle.AESSIVKeySize) if _, err := io.ReadFull(pseudorandomness, keyValue); err != nil { return nil, fmt.Errorf("aes_siv_key_manager: not enough pseudorandomness given") } return &aspb.AesSivKey{ Version: aesSIVKeyVersion, KeyValue: keyValue, }, nil } // validateKey validates the given AesSivKey. func (km *aesSIVKeyManager) validateKey(key *aspb.AesSivKey) error { err := keyset.ValidateKeyVersion(key.Version, aesSIVKeyVersion) if err != nil { return fmt.Errorf("aes_siv_key_manager: %v", err) } keySize := uint32(len(key.KeyValue)) if keySize != subtle.AESSIVKeySize { return errInvalidAESSIVKeySize } return nil } ================================================ FILE: go/daead/aes_siv_key_manager_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package daead_test import ( "bytes" "encoding/hex" "fmt" "testing" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" "github.com/google/tink/go/daead/subtle" aspb "github.com/google/tink/go/proto/aes_siv_go_proto" tpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestAESSIVPrimitive(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESSIVTypeURL) if err != nil { t.Fatalf("cannot obtain AESSIV key manager: %s", err) } m, err := km.NewKey(nil) if err != nil { t.Errorf("km.NewKey(nil) = _, %v; want _, nil", err) } key, ok := m.(*aspb.AesSivKey) if !ok { t.Errorf("m is not *aspb.AesSivKey") } serializedKey, err := proto.Marshal(key) if err != nil { t.Errorf("proto.Marshal() = %q; want nil", err) } p, err := km.Primitive(serializedKey) if err != nil { t.Errorf("km.Primitive(%v) = %v; want nil", serializedKey, err) } if err := validateAESSIVPrimitive(p, key); err != nil { t.Errorf("validateAESSIVPrimitive(p, key) = %v; want nil", err) } } func TestAESSIVPrimitiveWithInvalidKeys(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESSIVTypeURL) if err != nil { t.Errorf("cannot obtain AESSIV key manager: %s", err) } invalidKeys := []*aspb.AesSivKey{ // Bad key size. &aspb.AesSivKey{ Version: testutil.AESSIVKeyVersion, KeyValue: random.GetRandomBytes(16), }, &aspb.AesSivKey{ Version: testutil.AESSIVKeyVersion, KeyValue: random.GetRandomBytes(32), }, &aspb.AesSivKey{ Version: testutil.AESSIVKeyVersion, KeyValue: random.GetRandomBytes(63), }, &aspb.AesSivKey{ Version: testutil.AESSIVKeyVersion, KeyValue: random.GetRandomBytes(65), }, // Bad version. &aspb.AesSivKey{ Version: testutil.AESSIVKeyVersion + 1, KeyValue: random.GetRandomBytes(subtle.AESSIVKeySize), }, } for _, key := range invalidKeys { serializedKey, err := proto.Marshal(key) if err != nil { t.Errorf("proto.Marshal() = %q; want nil", err) } if _, err := km.Primitive(serializedKey); err == nil { t.Errorf("km.Primitive(%v) = _, nil; want _, err", serializedKey) } } } func TestAESSIVNewKey(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESSIVTypeURL) if err != nil { t.Errorf("cannot obtain AESSIV key manager: %s", err) } m, err := km.NewKey(nil) if err != nil { t.Errorf("km.NewKey(nil) = _, %v; want _, nil", err) } key, ok := m.(*aspb.AesSivKey) if !ok { t.Errorf("m is not *aspb.AesSivKey") } if err := validateAESSIVKey(key); err != nil { t.Errorf("validateAESSIVKey(%v) = %v; want nil", key, err) } } func TestAESSIVNewKeyData(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESSIVTypeURL) if err != nil { t.Errorf("cannot obtain AESSIV key manager: %s", err) } kd, err := km.NewKeyData(nil) if err != nil { t.Errorf("km.NewKeyData(nil) = _, %v; want _, nil", err) } if kd.TypeUrl != testutil.AESSIVTypeURL { t.Errorf("TypeUrl: %v != %v", kd.TypeUrl, testutil.AESSIVTypeURL) } if kd.KeyMaterialType != tpb.KeyData_SYMMETRIC { t.Errorf("KeyMaterialType: %v != SYMMETRIC", kd.KeyMaterialType) } key := new(aspb.AesSivKey) if err := proto.Unmarshal(kd.Value, key); err != nil { t.Errorf("proto.Unmarshal(%v, key) = %v; want nil", kd.Value, err) } if err := validateAESSIVKey(key); err != nil { t.Errorf("validateAESSIVKey(%v) = %v; want nil", key, err) } } func TestAESSIVNewKeyInvalid(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESSIVTypeURL) if err != nil { t.Errorf("registry.GetKeyManager(%q) err = %v, want nil", testutil.AESSIVTypeURL, err) } invalidKeySize, err := proto.Marshal(&aspb.AesSivKeyFormat{ KeySize: subtle.AESSIVKeySize - 1, Version: testutil.AESSIVKeyVersion, }) if err != nil { t.Errorf("proto.Marshal() err = %v, want nil", err) } // Proto messages start with a VarInt, which always ends with a byte with the // MSB unset, so 0x80 is invalid. invalidSerialization, err := hex.DecodeString("80") if err != nil { t.Errorf("hex.DecodeString() err = %v, want nil", err) } for _, test := range []struct { name string keyFormat []byte }{ { name: "invalid key size", keyFormat: invalidKeySize, }, { name: "invalid serialization", keyFormat: invalidSerialization, }, } { t.Run(test.name, func(t *testing.T) { if _, err = km.NewKey(test.keyFormat); err == nil { t.Error("km.NewKey() err = nil, want non-nil") } }) } } func TestAESSIVDoesSupport(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESSIVTypeURL) if err != nil { t.Errorf("cannot obtain AESSIV key manager: %s", err) } if !km.DoesSupport(testutil.AESSIVTypeURL) { t.Errorf("AESSIVKeyManager must support %s", testutil.AESSIVTypeURL) } if km.DoesSupport("some bad type") { t.Errorf("AESSIVKeyManager must only support %s", testutil.AESSIVTypeURL) } } func TestAESSIVTypeURL(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESSIVTypeURL) if err != nil { t.Errorf("cannot obtain AESSIV key manager: %s", err) } if kt := km.TypeURL(); kt != testutil.AESSIVTypeURL { t.Errorf("km.TypeURL() = %s; want %s", kt, testutil.AESSIVTypeURL) } } func TestAESSIVKeyMaterialType(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESSIVTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.AESSIVTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } if got, want := keyManager.KeyMaterialType(), tpb.KeyData_SYMMETRIC; got != want { t.Errorf("KeyMaterialType() = %v, want %v", got, want) } } func TestAESSIVDeriveKey(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESSIVTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.AESSIVTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } keyFormat, err := proto.Marshal(&aspb.AesSivKeyFormat{ KeySize: subtle.AESSIVKeySize, Version: testutil.AESSIVKeyVersion, }) if err != nil { t.Errorf("proto.Marshal() = %v; want nil", err) } rand := random.GetRandomBytes(subtle.AESSIVKeySize) buf := &bytes.Buffer{} buf.Write(rand) // never returns a non-nil error k, err := keyManager.DeriveKey(keyFormat, buf) if err != nil { t.Fatalf("keyManager.DeriveKey() err = %v, want nil", err) } key := k.(*aspb.AesSivKey) if got, want := len(key.GetKeyValue()), subtle.AESSIVKeySize; got != want { t.Errorf("key length = %d, want %d", got, want) } if diff := cmp.Diff(key.GetKeyValue(), rand); diff != "" { t.Errorf("incorrect derived key: diff = %v", diff) } } func TestAESSIVDeriveKeyFailsWithInvalidKeyFormats(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESSIVTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.AESSIVTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } for _, test := range []struct { name string keySize uint32 version uint32 }{ { name: "invalid key size", keySize: subtle.AESSIVKeySize - 1, version: testutil.AESSIVKeyVersion, }, { name: "invalid version", keySize: subtle.AESSIVKeySize, version: testutil.AESSIVKeyVersion + 1, }, { name: "zero key size and version", keySize: 0, version: 0, }, } { t.Run(test.name, func(t *testing.T) { keyFormat := &aspb.AesSivKeyFormat{ KeySize: test.keySize, Version: test.version, } serializedKeyFormat, err := proto.Marshal(keyFormat) if err != nil { t.Errorf("proto.Marshal() = %v; want nil", err) } buf := bytes.NewBuffer(random.GetRandomBytes(subtle.AESSIVKeySize)) if _, err := keyManager.DeriveKey(serializedKeyFormat, buf); err == nil { t.Errorf("keyManager.DeriveKey() err = nil, want non-nil") } }) } } func TestAESSIVDeriveKeyFailsWithMalformedKeyFormats(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESSIVTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.AESSIVTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } // Proto messages start with a VarInt, which always ends with a byte with the // MSB unset, so 0x80 is invalid. invalidSerialization, err := hex.DecodeString("80") if err != nil { t.Errorf("hex.DecodeString() err = %v, want nil", err) } for _, test := range []struct { name string keyFormat []byte }{ { name: "nil", keyFormat: nil, }, { name: "invalid serialization", keyFormat: invalidSerialization, }, } { t.Run(test.name, func(t *testing.T) { buf := bytes.NewBuffer(random.GetRandomBytes(subtle.AESSIVKeySize)) if _, err := keyManager.DeriveKey(test.keyFormat, buf); err == nil { t.Errorf("keyManager.DeriveKey() err = nil, want non-nil") } }) } } func TestAESSIVDeriveKeyFailsWithInsufficientRandomness(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESSIVTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.AESSIVTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } keyFormat, err := proto.Marshal(&aspb.AesSivKeyFormat{ KeySize: subtle.AESSIVKeySize, Version: testutil.AESSIVKeyVersion, }) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } { buf := bytes.NewBuffer(random.GetRandomBytes(subtle.AESSIVKeySize)) if _, err := keyManager.DeriveKey(keyFormat, buf); err != nil { t.Errorf("keyManager.DeriveKey() err = %v, want nil", err) } } { insufficientBuf := bytes.NewBuffer(random.GetRandomBytes(subtle.AESSIVKeySize - 1)) if _, err := keyManager.DeriveKey(keyFormat, insufficientBuf); err == nil { t.Errorf("keyManager.DeriveKey() err = nil, want non-nil") } } } func validateAESSIVPrimitive(p any, key *aspb.AesSivKey) error { cipher := p.(*subtle.AESSIV) // try to encrypt and decrypt pt := random.GetRandomBytes(32) aad := random.GetRandomBytes(32) ct, err := cipher.EncryptDeterministically(pt, aad) if err != nil { return fmt.Errorf("encryption failed") } decrypted, err := cipher.DecryptDeterministically(ct, aad) if err != nil { return fmt.Errorf("decryption failed") } if !bytes.Equal(decrypted, pt) { return fmt.Errorf("decryption failed") } return nil } func validateAESSIVKey(key *aspb.AesSivKey) error { if key.Version != testutil.AESSIVKeyVersion { return fmt.Errorf("incorrect key version: keyVersion != %d", testutil.AESSIVKeyVersion) } if uint32(len(key.KeyValue)) != subtle.AESSIVKeySize { return fmt.Errorf("incorrect key size: keySize != %d", subtle.AESSIVKeySize) } // Try to encrypt and decrypt. p, err := subtle.NewAESSIV(key.KeyValue) if err != nil { return fmt.Errorf("invalid key: %v", key.KeyValue) } return validateAESSIVPrimitive(p, key) } ================================================ FILE: go/daead/daead.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package daead provides implementations of the DeterministicAEAD primitive. // // Unlike AEAD, implementations of this interface are not semantically secure, because // encrypting the same plaintex always yields the same ciphertext. package daead import ( "fmt" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/internalregistry" ) func init() { if err := registry.RegisterKeyManager(new(aesSIVKeyManager)); err != nil { panic(fmt.Sprintf("daead.init() failed: %v", err)) } if err := internalregistry.AllowKeyDerivation(aesSIVTypeURL); err != nil { panic(fmt.Sprintf("daead.init() failed: %v", err)) } } ================================================ FILE: go/daead/daead_benchmark_test.go ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // ////////////////////////////////////////////////////////////////////////////// package daead_test import ( "testing" "github.com/google/tink/go/daead" "github.com/google/tink/go/keyset" "github.com/google/tink/go/subtle/random" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // Benchmarks for Deterministic AEAD algorithms. func BenchmarkAESSIV(b *testing.B) { const ( plaintextSize = 16 * 1024 associatedDataSize = 256 ) testCases := []struct { name string template *tinkpb.KeyTemplate }{ { name: "AES256_SIV", template: daead.AESSIVKeyTemplate(), }, } for _, tc := range testCases { b.Run(tc.name, func(b *testing.B) { b.ReportAllocs() handle, err := keyset.NewHandle(tc.template) if err != nil { b.Fatal(err) } primitive, err := daead.New(handle) if err != nil { b.Fatal(err) } plaintext := random.GetRandomBytes(plaintextSize) associatedData := random.GetRandomBytes(associatedDataSize) b.ResetTimer() for i := 0; i < b.N; i++ { ciphertext, err := primitive.EncryptDeterministically(plaintext, associatedData) if err != nil { b.Fatal(err) } _, err = primitive.DecryptDeterministically(ciphertext, associatedData) if err != nil { b.Error(err) } } }) } } ================================================ FILE: go/daead/daead_factory.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package daead import ( "fmt" "github.com/google/tink/go/core/cryptofmt" "github.com/google/tink/go/core/primitiveset" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/internal/monitoringutil" "github.com/google/tink/go/keyset" "github.com/google/tink/go/monitoring" "github.com/google/tink/go/tink" ) // New returns a DeterministicAEAD primitive from the given keyset handle. func New(handle *keyset.Handle) (tink.DeterministicAEAD, error) { ps, err := handle.Primitives() if err != nil { return nil, fmt.Errorf("daead_factory: cannot obtain primitive set: %s", err) } return newWrappedDeterministicAEAD(ps) } // wrappedDeterministicAEAD is a DeterministicAEAD implementation that uses an underlying primitive set // for deterministic encryption and decryption. type wrappedDeterministicAEAD struct { ps *primitiveset.PrimitiveSet encLogger monitoring.Logger decLogger monitoring.Logger } // Asserts that wrappedDeterministicAEAD implements the DeterministicAEAD interface. var _ tink.DeterministicAEAD = (*wrappedDeterministicAEAD)(nil) func newWrappedDeterministicAEAD(ps *primitiveset.PrimitiveSet) (*wrappedDeterministicAEAD, error) { if _, ok := (ps.Primary.Primitive).(tink.DeterministicAEAD); !ok { return nil, fmt.Errorf("daead_factory: not a DeterministicAEAD primitive") } for _, primitives := range ps.Entries { for _, p := range primitives { if _, ok := (p.Primitive).(tink.DeterministicAEAD); !ok { return nil, fmt.Errorf("daead_factory: not a DeterministicAEAD primitive") } } } encLogger, decLogger, err := createLoggers(ps) if err != nil { return nil, err } return &wrappedDeterministicAEAD{ ps: ps, encLogger: encLogger, decLogger: decLogger, }, nil } func createLoggers(ps *primitiveset.PrimitiveSet) (monitoring.Logger, monitoring.Logger, error) { if len(ps.Annotations) == 0 { return &monitoringutil.DoNothingLogger{}, &monitoringutil.DoNothingLogger{}, nil } client := internalregistry.GetMonitoringClient() keysetInfo, err := monitoringutil.KeysetInfoFromPrimitiveSet(ps) if err != nil { return nil, nil, err } encLogger, err := client.NewLogger(&monitoring.Context{ Primitive: "daead", APIFunction: "encrypt", KeysetInfo: keysetInfo, }) if err != nil { return nil, nil, err } decLogger, err := client.NewLogger(&monitoring.Context{ Primitive: "daead", APIFunction: "decrypt", KeysetInfo: keysetInfo, }) if err != nil { return nil, nil, err } return encLogger, decLogger, nil } // EncryptDeterministically deterministically encrypts plaintext with additionalData as additional authenticated data. // It returns the concatenation of the primary's identifier and the ciphertext. func (d *wrappedDeterministicAEAD) EncryptDeterministically(pt, aad []byte) ([]byte, error) { primary := d.ps.Primary p, ok := (primary.Primitive).(tink.DeterministicAEAD) if !ok { return nil, fmt.Errorf("daead_factory: not a DeterministicAEAD primitive") } ct, err := p.EncryptDeterministically(pt, aad) if err != nil { d.encLogger.LogFailure() return nil, err } d.encLogger.Log(primary.KeyID, len(pt)) if len(primary.Prefix) == 0 { return ct, nil } output := make([]byte, 0, len(primary.Prefix)+len(ct)) output = append(output, primary.Prefix...) output = append(output, ct...) return output, nil } // DecryptDeterministically deterministically decrypts ciphertext with additionalData as // additional authenticated data. It returns the corresponding plaintext if the // ciphertext is authenticated. func (d *wrappedDeterministicAEAD) DecryptDeterministically(ct, aad []byte) ([]byte, error) { // try non-raw keys prefixSize := cryptofmt.NonRawPrefixSize if len(ct) > prefixSize { prefix := ct[:prefixSize] ctNoPrefix := ct[prefixSize:] entries, err := d.ps.EntriesForPrefix(string(prefix)) if err == nil { for i := 0; i < len(entries); i++ { p, ok := (entries[i].Primitive).(tink.DeterministicAEAD) if !ok { return nil, fmt.Errorf("daead_factory: not a DeterministicAEAD primitive") } pt, err := p.DecryptDeterministically(ctNoPrefix, aad) if err == nil { d.decLogger.Log(entries[i].KeyID, len(ctNoPrefix)) return pt, nil } } } } // try raw keys entries, err := d.ps.RawEntries() if err == nil { for i := 0; i < len(entries); i++ { p, ok := (entries[i].Primitive).(tink.DeterministicAEAD) if !ok { return nil, fmt.Errorf("daead_factory: not a DeterministicAEAD primitive") } pt, err := p.DecryptDeterministically(ct, aad) if err == nil { d.decLogger.Log(entries[i].KeyID, len(ct)) return pt, nil } } } // nothing worked d.decLogger.LogFailure() return nil, fmt.Errorf("daead_factory: decryption failed") } ================================================ FILE: go/daead/daead_factory_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package daead_test import ( "bytes" "fmt" "strings" "testing" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/tink/go/core/cryptofmt" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/daead" "github.com/google/tink/go/insecurecleartextkeyset" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/internal/testing/stubkeymanager" "github.com/google/tink/go/keyset" "github.com/google/tink/go/monitoring" "github.com/google/tink/go/signature" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testing/fakemonitoring" "github.com/google/tink/go/testkeyset" "github.com/google/tink/go/testutil" "github.com/google/tink/go/tink" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestFactoryMultipleKeys(t *testing.T) { // encrypt with non-raw key. keyset := testutil.NewTestAESSIVKeyset(tinkpb.OutputPrefixType_TINK) primaryKey := keyset.Key[0] if primaryKey.OutputPrefixType == tinkpb.OutputPrefixType_RAW { t.Errorf("expect a non-raw key") } keysetHandle, err := testkeyset.NewHandle(keyset) if err != nil { t.Fatalf("testkeyset.NewHandle() err = %s, want nil", err) } d, err := daead.New(keysetHandle) if err != nil { t.Errorf("daead.New failed: %s", err) } expectedPrefix, err := cryptofmt.OutputPrefix(primaryKey) if err != nil { t.Fatalf("cryptofmt.OutputPrefix() err = %s, want nil", err) } if err := validateDAEADFactoryCipher(d, d, expectedPrefix); err != nil { t.Errorf("invalid cipher: %s", err) } // encrypt with a non-primary RAW key in keyset and decrypt with the keyset. { rawKey := keyset.Key[1] if rawKey.OutputPrefixType != tinkpb.OutputPrefixType_RAW { t.Errorf("expect a raw key") } keyset2 := testutil.NewKeyset(rawKey.KeyId, []*tinkpb.Keyset_Key{rawKey}) keysetHandle2, err := testkeyset.NewHandle(keyset2) if err != nil { t.Fatalf("testkeyset.NewHandle() err = %s, want nil", err) } d2, err := daead.New(keysetHandle2) if err != nil { t.Errorf("daead.New failed: %s", err) } if err := validateDAEADFactoryCipher(d2, d, cryptofmt.RawPrefix); err != nil { t.Errorf("invalid cipher: %s", err) } } // encrypt with a random key from a new keyset, decrypt with the original keyset should fail. { keyset2 := testutil.NewTestAESSIVKeyset(tinkpb.OutputPrefixType_TINK) newPK := keyset2.Key[0] if newPK.OutputPrefixType == tinkpb.OutputPrefixType_RAW { t.Errorf("expect a non-raw key") } keysetHandle2, err := testkeyset.NewHandle(keyset2) if err != nil { t.Fatalf("testkeyset.NewHandle() err = %s, want nil", err) } d2, err := daead.New(keysetHandle2) if err != nil { t.Errorf("daead.New failed: %s", err) } expectedPrefix, err = cryptofmt.OutputPrefix(newPK) if err != nil { t.Fatalf("cryptofmt.OutputPrefix() err = %s, want nil", err) } err = validateDAEADFactoryCipher(d2, d, expectedPrefix) if err == nil || !strings.Contains(err.Error(), "decryption failed") { t.Errorf("expect decryption to fail with random key: %s", err) } } } func TestFactoryRawKeyAsPrimary(t *testing.T) { keyset := testutil.NewTestAESSIVKeyset(tinkpb.OutputPrefixType_RAW) if keyset.Key[0].OutputPrefixType != tinkpb.OutputPrefixType_RAW { t.Errorf("primary key is not a raw key") } keysetHandle, err := testkeyset.NewHandle(keyset) if err != nil { t.Errorf("testkeyset.NewHandle() err = %s, want nil", err) } d, err := daead.New(keysetHandle) if err != nil { t.Errorf("cannot get primitive from keyset handle: %s", err) } if err := validateDAEADFactoryCipher(d, d, cryptofmt.RawPrefix); err != nil { t.Errorf("invalid cipher: %s", err) } } func validateDAEADFactoryCipher(encryptCipher, decryptCipher tink.DeterministicAEAD, expectedPrefix string) error { prefixSize := len(expectedPrefix) // regular plaintext. pt := random.GetRandomBytes(20) aad := random.GetRandomBytes(20) ct, err := encryptCipher.EncryptDeterministically(pt, aad) if err != nil { return fmt.Errorf("encryption failed with regular plaintext: %s", err) } decrypted, err := decryptCipher.DecryptDeterministically(ct, aad) if err != nil || !bytes.Equal(decrypted, pt) { return fmt.Errorf("decryption failed with regular plaintext: err: %s, pt: %s, decrypted: %s", err, pt, decrypted) } if string(ct[:prefixSize]) != expectedPrefix { return fmt.Errorf("incorrect prefix with regular plaintext") } // short plaintext. pt = random.GetRandomBytes(1) ct, err = encryptCipher.EncryptDeterministically(pt, aad) if err != nil { return fmt.Errorf("encryption failed with short plaintext: %s", err) } decrypted, err = decryptCipher.DecryptDeterministically(ct, aad) if err != nil || !bytes.Equal(decrypted, pt) { return fmt.Errorf("decryption failed with short plaintext: err: %s, pt: %s, decrypted: %s", err, pt, decrypted) } if string(ct[:prefixSize]) != expectedPrefix { return fmt.Errorf("incorrect prefix with short plaintext") } return nil } func TestFactoryWithInvalidPrimitiveSetType(t *testing.T) { wrongKH, err := keyset.NewHandle(signature.ECDSAP256KeyTemplate()) if err != nil { t.Fatalf("failed to build *keyset.Handle: %s", err) } _, err = daead.New(wrongKH) if err == nil { t.Fatal("calling New() with wrong *keyset.Handle should fail") } } func TestFactoryWithValidPrimitiveSetType(t *testing.T) { goodKH, err := keyset.NewHandle(daead.AESSIVKeyTemplate()) if err != nil { t.Fatalf("failed to build *keyset.Handle: %s", err) } _, err = daead.New(goodKH) if err != nil { t.Fatalf("calling New() with good *keyset.Handle failed: %s", err) } } func TestPrimitiveFactoryWithMonitoringAnnotationsLogsEncryptionDecryptionWithPrefix(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } kh, err := keyset.NewHandle(daead.AESSIVKeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } // Annotations are only supported throught the `insecurecleartextkeyset` API. buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } p, err := daead.New(mh) if err != nil { t.Fatalf("daead.New() err = %v, want nil", err) } pt := []byte("HELLO_WORLD") ct, err := p.EncryptDeterministically(pt, nil) if err != nil { t.Fatalf("p.EncryptDeterministically() err = %v, want nil", err) } if _, err := p.DecryptDeterministically(ct, nil); err != nil { t.Fatalf("p.DecryptDeterministically() err = %v, want nil", err) } got := client.Events() wantKeysetInfo := monitoring.NewKeysetInfo( annotations, kh.KeysetInfo().GetPrimaryKeyId(), []*monitoring.Entry{ { Status: monitoring.Enabled, KeyID: kh.KeysetInfo().GetPrimaryKeyId(), KeyType: "tink.AesSivKey", KeyPrefix: "TINK", }, }, ) want := []*fakemonitoring.LogEvent{ { KeyID: mh.KeysetInfo().GetPrimaryKeyId(), NumBytes: len(pt), Context: monitoring.NewContext("daead", "encrypt", wantKeysetInfo), }, { KeyID: mh.KeysetInfo().GetPrimaryKeyId(), // Ciphertext was encrypted with a key that has a TINK output prefix. This adds a 5-byte prefix // to the ciphertext. This prefix is not included in `Log` call. NumBytes: len(ct) - cryptofmt.NonRawPrefixSize, Context: monitoring.NewContext("daead", "decrypt", wantKeysetInfo), }, } if !cmp.Equal(got, want) { t.Errorf("got = %v, want = %v, with diff: %v", got, want, cmp.Diff(got, want)) } } func TestPrimitiveFactoryWithMonitoringAnnotationsLogsEncryptionDecryptionWithoutPrefix(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } template := daead.AESSIVKeyTemplate() // There's currently not a raw template in the public API, but // we add a test by customizing the output prefix of an existing one. template.OutputPrefixType = tinkpb.OutputPrefixType_RAW kh, err := keyset.NewHandle(template) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } // Annotations are only supported throught the `insecurecleartextkeyset` API. buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } p, err := daead.New(mh) if err != nil { t.Fatalf("daead.New() err = %v, want nil", err) } data := []byte("hello_world") aad := []byte("_!") ct, err := p.EncryptDeterministically(data, aad) if err != nil { t.Fatalf("p.EncryptDeterministically() err = %v, want nil", err) } if _, err := p.DecryptDeterministically(ct, aad); err != nil { t.Fatalf("p.DecryptDeterministically() err = %v, want nil", err) } got := client.Events() wantKeysetInfo := monitoring.NewKeysetInfo( annotations, kh.KeysetInfo().GetPrimaryKeyId(), []*monitoring.Entry{ { Status: monitoring.Enabled, KeyID: kh.KeysetInfo().GetPrimaryKeyId(), KeyType: "tink.AesSivKey", KeyPrefix: "RAW", }, }, ) want := []*fakemonitoring.LogEvent{ { Context: monitoring.NewContext("daead", "encrypt", wantKeysetInfo), KeyID: wantKeysetInfo.PrimaryKeyID, NumBytes: len(data), }, { Context: monitoring.NewContext("daead", "decrypt", wantKeysetInfo), KeyID: wantKeysetInfo.PrimaryKeyID, NumBytes: len(ct), }, } if !cmp.Equal(got, want) { t.Errorf("got = %v, want = %v, with diff: %v", got, want, cmp.Diff(got, want)) } } func TestFactoryWithMonitoringPrimitiveWithMultipleKeysLogsEncryptionDecryption(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } manager := keyset.NewManager() numKeys := 4 keyIDs := make([]uint32, numKeys, numKeys) var err error for i := 0; i < numKeys; i++ { keyIDs[i], err = manager.Add(daead.AESSIVKeyTemplate()) if err != nil { t.Fatalf("manager.Add() err = %v, want nil", err) } } if err := manager.SetPrimary(keyIDs[1]); err != nil { t.Fatalf("manager.SetPrimary(%d) err = %v, want nil", keyIDs[1], err) } if err := manager.Disable(keyIDs[0]); err != nil { t.Fatalf("manager.Disable(%d) err = %v, want nil", keyIDs[0], err) } kh, err := manager.Handle() if err != nil { t.Fatalf("manager.Handle() err = %v, want nil", err) } // Annotations are only supported throught the `insecurecleartextkeyset` API. buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } p, err := daead.New(mh) if err != nil { t.Fatalf("daead.New() err = %v, want nil", err) } data := []byte("YELLOW_ORANGE") ct, err := p.EncryptDeterministically(data, nil) if err != nil { t.Fatalf("p.EncryptDeterministically() err = %v, want nil", err) } if _, err := p.DecryptDeterministically(ct, nil); err != nil { t.Fatalf("p.DecryptDeterministically() err = %v, want nil", err) } failures := len(client.Failures()) if failures != 0 { t.Errorf("len(client.Failures()) = %d, want 0", failures) } got := client.Events() wantKeysetInfo := monitoring.NewKeysetInfo(annotations, kh.KeysetInfo().GetPrimaryKeyId(), []*monitoring.Entry{ { KeyID: kh.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.AesSivKey", KeyPrefix: "TINK", }, { KeyID: keyIDs[2], Status: monitoring.Enabled, KeyType: "tink.AesSivKey", KeyPrefix: "TINK", }, { KeyID: keyIDs[3], Status: monitoring.Enabled, KeyType: "tink.AesSivKey", KeyPrefix: "TINK", }, }) want := []*fakemonitoring.LogEvent{ { KeyID: kh.KeysetInfo().GetPrimaryKeyId(), NumBytes: len(data), Context: monitoring.NewContext( "daead", "encrypt", wantKeysetInfo, ), }, { KeyID: kh.KeysetInfo().GetPrimaryKeyId(), NumBytes: len(ct) - cryptofmt.NonRawPrefixSize, Context: monitoring.NewContext( "daead", "decrypt", wantKeysetInfo, ), }, } // sort by keyID to avoid non deterministic order. entryLessFunc := func(a, b *monitoring.Entry) bool { return a.KeyID < b.KeyID } if !cmp.Equal(got, want, cmpopts.SortSlices(entryLessFunc)) { t.Errorf("got = %v, want = %v, with diff: %v", got, want, cmp.Diff(got, want)) } } func TestPrimitiveFactoryWithMonitoringAnnotationsEncryptionFailureIsLogged(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := &fakemonitoring.Client{Name: ""} if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } typeURL := "TestFactoryWithMonitoringPrimitiveEncryptionFailureIsLogged" km := &stubkeymanager.StubKeyManager{ URL: typeURL, Prim: &testutil.AlwaysFailingDeterministicAead{Error: fmt.Errorf("failed")}, KeyData: &tinkpb.KeyData{ TypeUrl: typeURL, Value: []byte("serialized_key"), KeyMaterialType: tinkpb.KeyData_SYMMETRIC, }, } if err := registry.RegisterKeyManager(km); err != nil { t.Fatalf("registry.RegisterKeyManager() err = %v, want nil", err) } template := &tinkpb.KeyTemplate{ TypeUrl: typeURL, OutputPrefixType: tinkpb.OutputPrefixType_LEGACY, } kh, err := keyset.NewHandle(template) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } // Annotations are only supported throught the `insecurecleartextkeyset` API. buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } p, err := daead.New(mh) if err != nil { t.Fatalf("daead.New() err = %v, want nil", err) } if _, err := p.EncryptDeterministically(nil, nil); err == nil { t.Fatalf("EncryptDeterministically() err = nil, want error") } got := client.Failures() want := []*fakemonitoring.LogFailure{ { Context: monitoring.NewContext( "daead", "encrypt", monitoring.NewKeysetInfo( annotations, kh.KeysetInfo().GetPrimaryKeyId(), []*monitoring.Entry{ { KeyID: kh.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: typeURL, KeyPrefix: "LEGACY", }, }, ), ), }, } if !cmp.Equal(got, want) { t.Errorf("got = %v, want = %v, with diff: %v", got, want, cmp.Diff(got, want)) } } func TestPrimitiveFactoryWithMonitoringAnnotationsDecryptionFailureIsLogged(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := &fakemonitoring.Client{Name: ""} if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } kh, err := keyset.NewHandle(daead.AESSIVKeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } // Annotations are only supported throught the `insecurecleartextkeyset` API. buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } p, err := daead.New(mh) if err != nil { t.Fatalf("daead.New() err = %v, want nil", err) } if _, err := p.DecryptDeterministically([]byte("invalid_data"), nil); err == nil { t.Fatalf("DecryptDeterministically() err = nil, want error") } got := client.Failures() want := []*fakemonitoring.LogFailure{ { Context: monitoring.NewContext( "daead", "decrypt", monitoring.NewKeysetInfo( annotations, kh.KeysetInfo().GetPrimaryKeyId(), []*monitoring.Entry{ { KeyID: kh.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.AesSivKey", KeyPrefix: "TINK", }, }, ), ), }, } if !cmp.Equal(got, want) { t.Errorf("got = %v, want = %v, with diff: %v", got, want, cmp.Diff(got, want)) } } func TestFactoryWithMonitoringMultiplePrimitivesLogOperations(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := &fakemonitoring.Client{Name: ""} if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } kh1, err := keyset.NewHandle(daead.AESSIVKeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } // Annotations are only supported throught the `insecurecleartextkeyset` API. buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(kh1, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} mh1, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } p1, err := daead.New(mh1) if err != nil { t.Fatalf("daead.New() err = %v, want nil", err) } kh2, err := keyset.NewHandle(daead.AESSIVKeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } buff.Reset() if err := insecurecleartextkeyset.Write(kh2, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } mh2, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } p2, err := daead.New(mh2) if err != nil { t.Fatalf("daead.New() err = %v, want nil", err) } d1 := []byte("YELLOW_ORANGE") if _, err := p1.EncryptDeterministically(d1, nil); err != nil { t.Fatalf("p1.EncryptDeterministically() err = %v, want nil", err) } d2 := []byte("ORANGE_BLUE") if _, err := p2.EncryptDeterministically(d2, nil); err != nil { t.Fatalf("p2.EncryptDeterministically() err = %v, want nil", err) } got := client.Events() want := []*fakemonitoring.LogEvent{ { KeyID: kh1.KeysetInfo().GetPrimaryKeyId(), NumBytes: len(d1), Context: monitoring.NewContext( "daead", "encrypt", monitoring.NewKeysetInfo( annotations, kh1.KeysetInfo().GetPrimaryKeyId(), []*monitoring.Entry{ { KeyID: kh1.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.AesSivKey", KeyPrefix: "TINK", }, }, ), ), }, { KeyID: kh2.KeysetInfo().GetPrimaryKeyId(), NumBytes: len(d2), Context: monitoring.NewContext( "daead", "encrypt", monitoring.NewKeysetInfo( annotations, kh2.KeysetInfo().GetPrimaryKeyId(), []*monitoring.Entry{ { KeyID: kh2.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.AesSivKey", KeyPrefix: "TINK", }, }, ), ), }, } if !cmp.Equal(got, want) { t.Errorf("got = %v, want = %v, with diff: %v", got, want, cmp.Diff(got, want)) } } func TestPrimitiveFactoryEncryptDecryptWithoutAnnotationsDoesNotMonitor(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } kh, err := keyset.NewHandle(daead.AESSIVKeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } p, err := daead.New(kh) if err != nil { t.Fatalf("daead.New() err = %v, want nil", err) } data := []byte("hello_world") ct, err := p.EncryptDeterministically(data, nil) if err != nil { t.Fatalf("p.EncryptDeterministically() err = %v, want nil", err) } if _, err := p.DecryptDeterministically(ct, nil); err != nil { t.Fatalf("p.DecryptDeterministically() err = %v, want nil", err) } got := client.Events() if len(got) != 0 { t.Errorf("len(client.Events()) = %d, want 0", len(got)) } } ================================================ FILE: go/daead/daead_init_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package daead_test import ( "testing" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/testutil" ) func TestDeterministicAEADInit(t *testing.T) { // Check that the AES-SIV key manager is in the global registry. _, err := registry.GetKeyManager(testutil.AESSIVTypeURL) if err != nil { t.Errorf("unexpected error: %s", err) } } ================================================ FILE: go/daead/daead_key_templates.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package daead import ( "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/internal/tinkerror" aspb "github.com/google/tink/go/proto/aes_siv_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // AESSIVKeyTemplate is a KeyTemplate that generates a AES-SIV key. func AESSIVKeyTemplate() *tinkpb.KeyTemplate { format := &aspb.AesSivKeyFormat{ KeySize: 64, } serializedFormat, err := proto.Marshal(format) if err != nil { tinkerror.Fail(fmt.Sprintf("failed to marshal key format: %s", err)) } return &tinkpb.KeyTemplate{ TypeUrl: aesSIVTypeURL, OutputPrefixType: tinkpb.OutputPrefixType_TINK, Value: serializedFormat, } } ================================================ FILE: go/daead/daead_key_templates_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package daead_test import ( "bytes" "fmt" "testing" "github.com/google/tink/go/daead" "github.com/google/tink/go/keyset" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestKeyTemplates(t *testing.T) { var testCases = []struct { name string template *tinkpb.KeyTemplate }{ {name: "AES256_SIV", template: daead.AESSIVKeyTemplate()}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { if err := testEncryptDecrypt(tc.template); err != nil { t.Errorf("%v", err) } }) } } func testEncryptDecrypt(template *tinkpb.KeyTemplate) error { handle, err := keyset.NewHandle(template) if err != nil { return fmt.Errorf("keyset.NewHandle(template) failed: %v", err) } primitive, err := daead.New(handle) if err != nil { return fmt.Errorf("daead.New(handle) failed: %v", err) } var testInputs = []struct { plaintext []byte aad1 []byte aad2 []byte }{ { plaintext: []byte("some data to encrypt"), aad1: []byte("extra data to authenticate"), aad2: []byte("extra data to authenticate"), }, { plaintext: []byte("some data to encrypt"), aad1: []byte(""), aad2: []byte(""), }, { plaintext: []byte("some data to encrypt"), aad1: nil, aad2: nil, }, { plaintext: []byte(""), aad1: nil, aad2: nil, }, { plaintext: nil, aad1: []byte("extra data to authenticate"), aad2: []byte("extra data to authenticate"), }, { plaintext: nil, aad1: []byte(""), aad2: []byte(""), }, { plaintext: nil, aad1: nil, aad2: nil, }, { plaintext: []byte("some data to encrypt"), aad1: []byte(""), aad2: nil, }, { plaintext: []byte("some data to encrypt"), aad1: nil, aad2: []byte(""), }, } for _, ti := range testInputs { ciphertext, err := primitive.EncryptDeterministically(ti.plaintext, ti.aad1) if err != nil { return fmt.Errorf("encryption failed, error: %v", err) } decrypted, err := primitive.DecryptDeterministically(ciphertext, ti.aad2) if err != nil { return fmt.Errorf("decryption failed, error: %v", err) } if !bytes.Equal(ti.plaintext, decrypted) { return fmt.Errorf("decrypted data doesn't match plaintext, got: %q, want: %q", decrypted, ti.plaintext) } } return nil } ================================================ FILE: go/daead/daead_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package daead_test // [START deterministic-aead-example] import ( "bytes" "fmt" "log" "github.com/google/tink/go/daead" "github.com/google/tink/go/insecurecleartextkeyset" "github.com/google/tink/go/keyset" ) func Example() { // A keyset created with "tinkey create-keyset --key-template=AES256_SIV". Note // that this keyset has the secret key information in cleartext. jsonKeyset := `{ "key": [{ "keyData": { "keyMaterialType": "SYMMETRIC", "typeUrl": "type.googleapis.com/google.crypto.tink.AesSivKey", "value": "EkAl9HCMmKTN1p3V186uhZpJQ+tivyc4IKyE+opg6SsEbWQ/WesWHzwCRrlgRuxdaggvgMzwWhjPnkk9gptBnGLK" }, "keyId": 1919301694, "outputPrefixType": "TINK", "status": "ENABLED" }], "primaryKeyId": 1919301694 }` // Create a keyset handle from the cleartext keyset in the previous // step. The keyset handle provides abstract access to the underlying keyset to // limit the exposure of accessing the raw key material. WARNING: In practice, // it is unlikely you will want to use a insecurecleartextkeyset, as it implies // that your key material is passed in cleartext, which is a security risk. // Consider encrypting it with a remote key in Cloud KMS, AWS KMS or HashiCorp Vault. // See https://github.com/google/tink/blob/master/docs/GOLANG-HOWTO.md#storing-and-loading-existing-keysets. keysetHandle, err := insecurecleartextkeyset.Read( keyset.NewJSONReader(bytes.NewBufferString(jsonKeyset))) if err != nil { log.Fatal(err) } // Retrieve the DAEAD primitive we want to use from the keyset handle. primitive, err := daead.New(keysetHandle) if err != nil { log.Fatal(err) } // Use the primitive to encrypt a message. In this case the primary key of the // keyset will be used (which is also the only key in this example). plaintext := []byte("message") associatedData := []byte("associated data") ciphertext, err := primitive.EncryptDeterministically(plaintext, associatedData) if err != nil { log.Fatal(err) } // Use the primitive to decrypt the message. Decrypt finds the correct key in // the keyset and decrypts the ciphertext. If no key is found or decryption // fails, it returns an error. decrypted, err := primitive.DecryptDeterministically(ciphertext, associatedData) if err != nil { log.Fatal(err) } fmt.Println(ciphertext) fmt.Println(string(decrypted)) // Output: // [1 114 102 56 62 150 98 146 84 99 211 36 127 214 229 231 157 56 143 192 250 132 32 153 124 244 238 112] // message } // [END deterministic-aead-example] ================================================ FILE: go/daead/subtle/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep go_library( name = "subtle", srcs = ["aes_siv.go"], importpath = "github.com/google/tink/go/daead/subtle", ) go_test( name = "subtle_test", srcs = ["aes_siv_test.go"], data = ["//testdata/testvectors:aes_siv_cmac"], deps = [ ":subtle", "//subtle/random", "//testutil", ], ) alias( name = "go_default_library", actual = ":subtle", visibility = ["//:__subpackages__"], ) ================================================ FILE: go/daead/subtle/aes_siv.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package subtle provides subtle implementations of the DeterministicAEAD // primitive. package subtle import ( "crypto/aes" "crypto/cipher" "crypto/subtle" "errors" "fmt" "math" // Placeholder for internal crypto/cipher allowlist, please ignore. // Placeholder for internal crypto/subtle allowlist, please ignore. ) // AESSIV is an implementation of AES-SIV-CMAC as defined in // https://tools.ietf.org/html/rfc5297. // // AESSIV implements a deterministic encryption with associated data (i.e. the // DeterministicAEAD interface). Hence the implementation below is restricted // to one AD component. // // Security Note: // // Chatterjee, Menezes and Sarkar analyze AES-SIV in Section 5.1 of // https://www.math.uwaterloo.ca/~ajmeneze/publications/tightness.pdf // // Their analysis shows that AES-SIV is susceptible to an attack in // a multi-user setting. Concretely, if an attacker knows the encryption // of a message m encrypted and authenticated with k different keys, // then it is possible to find one of the MAC keys in time 2^b / k // where b is the size of the MAC key. A consequence of this attack // is that 128-bit MAC keys give unsufficient security. // Since 192-bit AES keys are not supported by tink for voodoo reasons // and RFC 5297 only supports same size encryption and MAC keys this // implies that keys must be 64 bytes (2*256 bits) long. type AESSIV struct { k1 []byte k2 []byte cmacK1 []byte cmacK2 []byte cipher cipher.Block } const ( // AESSIVKeySize is the key size in bytes. AESSIVKeySize = 64 intSize = 32 << (^uint(0) >> 63) // 32 or 64 maxInt = 1<<(intSize-1) - 1 ) // NewAESSIV returns an AESSIV instance. func NewAESSIV(key []byte) (*AESSIV, error) { if len(key) != AESSIVKeySize { return nil, fmt.Errorf("aes_siv: invalid key size %d", len(key)) } k1 := key[:32] k2 := key[32:] c, err := aes.NewCipher(k1) if err != nil { return nil, fmt.Errorf("aes_siv: aes.NewCipher() failed: %v", err) } block := make([]byte, aes.BlockSize) c.Encrypt(block, block) multiplyByX(block) cmacK1 := make([]byte, aes.BlockSize) copy(cmacK1, block) multiplyByX(block) cmacK2 := make([]byte, aes.BlockSize) copy(cmacK2, block) return &AESSIV{ k1: k1, k2: k2, cmacK1: cmacK1, cmacK2: cmacK2, cipher: c, }, nil } // multiplyByX multiplies an element in GF(2^128) by its generator. // // This function is incorrectly named "doubling" in section 2.3 of RFC 5297. func multiplyByX(block []byte) { carry := int(block[0] >> 7) for i := 0; i < aes.BlockSize-1; i++ { block[i] = (block[i] << 1) | (block[i+1] >> 7) } block[aes.BlockSize-1] = (block[aes.BlockSize-1] << 1) ^ byte(subtle.ConstantTimeSelect(carry, 0x87, 0x00)) } // EncryptDeterministically deterministically encrypts plaintext with associatedData. func (asc *AESSIV) EncryptDeterministically(plaintext, associatedData []byte) ([]byte, error) { if len(plaintext) > maxInt-aes.BlockSize { return nil, fmt.Errorf("aes_siv: plaintext too long") } siv := make([]byte, aes.BlockSize) asc.s2v(plaintext, associatedData, siv) ct := make([]byte, len(plaintext)+aes.BlockSize) copy(ct[:aes.BlockSize], siv) if err := asc.ctrCrypt(siv, plaintext, ct[aes.BlockSize:]); err != nil { return nil, err } return ct, nil } // DecryptDeterministically deterministically decrypts ciphertext with associatedData. func (asc *AESSIV) DecryptDeterministically(ciphertext, associatedData []byte) ([]byte, error) { if len(ciphertext) < aes.BlockSize { return nil, errors.New("aes_siv: ciphertext is too short") } pt := make([]byte, len(ciphertext)-aes.BlockSize) siv := ciphertext[:aes.BlockSize] asc.ctrCrypt(siv, ciphertext[aes.BlockSize:], pt) s2v := make([]byte, aes.BlockSize) asc.s2v(pt, associatedData, s2v) diff := byte(0) for i := 0; i < aes.BlockSize; i++ { diff |= siv[i] ^ s2v[i] } if diff != 0 { return nil, errors.New("aes_siv: invalid ciphertext") } return pt, nil } // ctrCrypt encrypts (or decrypts) the bytes in in using an SIV and writes the // result to out. func (asc *AESSIV) ctrCrypt(siv, in, out []byte) error { // siv might be used outside of ctrCrypt(), so making a copy of it. iv := make([]byte, aes.BlockSize) copy(iv, siv) iv[8] &= 0x7f iv[12] &= 0x7f c, err := aes.NewCipher(asc.k2) if err != nil { return fmt.Errorf("aes_siv: aes.NewCipher() failed: %v", err) } steam := cipher.NewCTR(c, iv) steam.XORKeyStream(out, in) return nil } // s2v is a Pseudo-Random Function (PRF) construction: // https://tools.ietf.org/html/rfc5297. func (asc *AESSIV) s2v(msg, ad, siv []byte) { block := make([]byte, aes.BlockSize) asc.cmac(block, block) multiplyByX(block) adMac := make([]byte, aes.BlockSize) asc.cmac(ad, adMac) xorBlock(adMac, block) if len(msg) >= aes.BlockSize { asc.cmacLong(msg, block, siv) } else { multiplyByX(block) for i := 0; i < len(msg); i++ { block[i] ^= msg[i] } block[len(msg)] ^= 0x80 asc.cmac(block, siv) } } // cmacLong computes CMAC(XorEnd(data, last)), where XorEnd xors the bytes in // last to the last bytes in data. // // The size of the data must be at least 16 bytes. func (asc *AESSIV) cmacLong(data, last, mac []byte) { block := make([]byte, aes.BlockSize) copy(block, data[:aes.BlockSize]) idx := aes.BlockSize for aes.BlockSize <= len(data)-idx { asc.cipher.Encrypt(block, block) xorBlock(data[idx:idx+aes.BlockSize], block) idx += aes.BlockSize } remaining := len(data) - idx for i := 0; i < aes.BlockSize-remaining; i++ { block[remaining+i] ^= last[i] } if remaining == 0 { xorBlock(asc.cmacK1, block) } else { asc.cipher.Encrypt(block, block) for i := 0; i < remaining; i++ { block[i] ^= last[aes.BlockSize-remaining+i] block[i] ^= data[idx+i] } block[remaining] ^= 0x80 xorBlock(asc.cmacK2, block) } asc.cipher.Encrypt(mac, block) } // cmac computes a CMAC of some data. func (asc *AESSIV) cmac(data, mac []byte) { numBs := int(math.Ceil(float64(len(data)) / aes.BlockSize)) if numBs == 0 { numBs = 1 } lastBSize := len(data) - (numBs-1)*aes.BlockSize block := make([]byte, aes.BlockSize) idx := 0 for i := 0; i < numBs-1; i++ { xorBlock(data[idx:idx+aes.BlockSize], block) asc.cipher.Encrypt(block, block) idx += aes.BlockSize } for j := 0; j < lastBSize; j++ { block[j] ^= data[idx+j] } if lastBSize == aes.BlockSize { xorBlock(asc.cmacK1, block) } else { block[lastBSize] ^= 0x80 xorBlock(asc.cmacK2, block) } asc.cipher.Encrypt(mac, block) } // xorBlock sets block[i] = x[i] ^ block[i]. func xorBlock(x, block []byte) { for i := 0; i < aes.BlockSize; i++ { block[i] ^= x[i] } } ================================================ FILE: go/daead/subtle/aes_siv_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "bytes" "encoding/hex" "testing" "github.com/google/tink/go/daead/subtle" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" ) type AESSIVSuite struct { Algorithm string GeneratorVersion string NumberOfTests uint32 TestGroups []*testGroup } type testGroup struct { KeySize uint32 Type string Tests []*testCase } type testCase struct { TcID uint32 Key string Aad string Msg string Ct string Result string } func TestAESSIV_EncryptDecrypt(t *testing.T) { keyStr := "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "00112233445566778899aabbccddeefff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff" key, err := hex.DecodeString(keyStr) if err != nil { t.Fatalf("hex.DecodeString() err = %q, want nil", err) } msg := []byte("Some data to encrypt.") aad := []byte("Additional data") a, err := subtle.NewAESSIV(key) if err != nil { t.Errorf("NewAESSIV(key) = _, %v, want _, nil", err) } ct, err := a.EncryptDeterministically(msg, aad) if err != nil { t.Errorf("Unexpected encryption error: %v", err) } if pt, err := a.DecryptDeterministically(ct, aad); err != nil { t.Errorf("Unexpected decryption error: %v", err) } else if !bytes.Equal(pt, msg) { t.Errorf("Mismatched plaintexts: got %v, want %v", pt, msg) } } func TestAESSIV_EmptyPlaintext(t *testing.T) { keyStr := "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "00112233445566778899aabbccddeefff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff" key, err := hex.DecodeString(keyStr) if err != nil { t.Fatalf("hex.DecodeString() err = %q, want nil", err) } aad := []byte("Additional data") a, err := subtle.NewAESSIV(key) if err != nil { t.Errorf("NewAESSIV(key) = _, %v, want _, nil", err) } ct, err := a.EncryptDeterministically(nil, aad) if err != nil { t.Errorf("Unexpected encryption error: %v", err) } if pt, err := a.DecryptDeterministically(ct, aad); err != nil { t.Errorf("Unexpected decryption error: %v", err) } else if !bytes.Equal(pt, []byte{}) { t.Errorf("Mismatched plaintexts: got %v, want []", pt) } ct, err = a.EncryptDeterministically([]byte{}, aad) if err != nil { t.Errorf("Unexpected encryption error: %v", err) } if pt, err := a.DecryptDeterministically(ct, aad); err != nil { t.Errorf("Unexpected decryption error: %v", err) } else if !bytes.Equal(pt, []byte{}) { t.Errorf("Mismatched plaintexts: got %v, want []", pt) } } func TestAESSIV_EmptyAdditionalData(t *testing.T) { keyStr := "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "00112233445566778899aabbccddeefff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff" key, err := hex.DecodeString(keyStr) if err != nil { t.Fatalf("hex.DecodeString() err = %q, want nil", err) } a, err := subtle.NewAESSIV(key) if err != nil { t.Errorf("NewAESSIV(key) = _, %v, want _, nil", err) } ct, err := a.EncryptDeterministically(nil, nil) if err != nil { t.Errorf("Unexpected encryption error: %v", err) } if pt, err := a.DecryptDeterministically(ct, nil); err != nil { t.Errorf("Unexpected decryption error: %v", err) } else if !bytes.Equal(pt, []byte{}) { t.Errorf("Mismatched plaintexts: got %v, want []", pt) } if pt, err := a.DecryptDeterministically(ct, []byte{}); err != nil { t.Errorf("Unexpected decryption error: %v", err) } else if !bytes.Equal(pt, []byte{}) { t.Errorf("Mismatched plaintexts: got %v, want []", pt) } } func TestAESSIV_KeySizes(t *testing.T) { keyStr := "198371900187498172316311acf81d238ff7619873a61983d619c87b63a1987f" + "987131819803719b847126381cd763871638aa71638176328761287361231321" + "812731321de508761437195ff231765aa4913219873ac6918639816312130011" + "abc900bba11400187984719827431246bbab1231eb4145215ff7141436616beb" + "9817298148712fed3aab61000ff123313e" key, err := hex.DecodeString(keyStr) if err != nil { t.Fatalf("hex.DecodeString() err = %q, want nil", err) } for i := 0; i < len(key); i++ { _, err := subtle.NewAESSIV(key[:i]) if i == subtle.AESSIVKeySize && err != nil { t.Errorf("Rejected valid key size: %v, %v", i, err) } if i != subtle.AESSIVKeySize && err == nil { t.Errorf("Allowed invalid key size: %v", i) } } } func TestAESSIV_MessageSizes(t *testing.T) { keyStr := "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "00112233445566778899aabbccddeefff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff" key, err := hex.DecodeString(keyStr) if err != nil { t.Fatalf("hex.DecodeString() err = %q, want nil", err) } aad := []byte("Additional data") a, err := subtle.NewAESSIV(key) if err != nil { t.Errorf("NewAESSIV(key) = _, %v, want _, nil", err) } for i := uint32(0); i < 1024; i++ { msg := random.GetRandomBytes(i) ct, err := a.EncryptDeterministically(msg, aad) if err != nil { t.Errorf("Unexpected encryption error: %v", err) } if pt, err := a.DecryptDeterministically(ct, aad); err != nil { t.Errorf("Unexpected decryption error: %v", err) } else if !bytes.Equal(pt, msg) { t.Errorf("Mismatched plaintexts: got %v, want %v", pt, msg) } } for i := uint32(1024); i < 100000; i += 5000 { msg := random.GetRandomBytes(i) ct, err := a.EncryptDeterministically(msg, aad) if err != nil { t.Errorf("Unexpected encryption error: %v", err) } if pt, err := a.DecryptDeterministically(ct, aad); err != nil { t.Errorf("Unexpected decryption error: %v", err) } else if !bytes.Equal(pt, msg) { t.Errorf("Mismatched plaintexts: got %v, want %v", pt, msg) } } } func TestAESSIV_AdditionalDataSizes(t *testing.T) { keyStr := "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "00112233445566778899aabbccddeefff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff" key, err := hex.DecodeString(keyStr) if err != nil { t.Fatalf("hex.DecodeString() err = %q, want nil", err) } msg := []byte("Some data to encrypt.") a, err := subtle.NewAESSIV(key) if err != nil { t.Errorf("NewAESSIV(key) = _, %v, want _, nil", err) } for i := uint32(0); i < 1024; i++ { aad := random.GetRandomBytes(i) ct, err := a.EncryptDeterministically(msg, aad) if err != nil { t.Errorf("Unexpected encryption error: %v", err) } if pt, err := a.DecryptDeterministically(ct, aad); err != nil { t.Errorf("Unexpected decryption error: %v", err) } else if !bytes.Equal(pt, msg) { t.Errorf("Mismatched plaintexts: got %v, want %v", pt, msg) } } } func TestAESSIV_CiphertextModifications(t *testing.T) { keyStr := "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "00112233445566778899aabbccddeefff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff" key, err := hex.DecodeString(keyStr) if err != nil { t.Fatalf("hex.DecodeString() err = %q, want nil", err) } aad := []byte("Additional data") a, err := subtle.NewAESSIV(key) if err != nil { t.Errorf("NewAESSIV(key) = _, %v, want _, nil", err) } for i := uint32(0); i < 50; i++ { msg := random.GetRandomBytes(i) ct, err := a.EncryptDeterministically(msg, aad) if err != nil { t.Errorf("Unexpected encryption error: %v", err) } for j := 0; j < len(ct); j++ { for b := uint32(0); b < 8; b++ { ct[j] ^= 1 << b if _, err := a.DecryptDeterministically(ct, aad); err == nil { t.Errorf("Modified ciphertext decrypted: byte %d, bit %d", j, b) } ct[j] ^= 1 << b } } } } func TestAESSIV_WycheproofVectors(t *testing.T) { testutil.SkipTestIfTestSrcDirIsNotSet(t) suite := new(AESSIVSuite) if err := testutil.PopulateSuite(suite, "aes_siv_cmac_test.json"); err != nil { t.Fatalf("testutil.PopulateSuite: %v", err) } for _, g := range suite.TestGroups { if g.KeySize/8 != subtle.AESSIVKeySize { continue } for _, tc := range g.Tests { key, err := hex.DecodeString(tc.Key) if err != nil { t.Errorf("#%d, cannot decode key: %s", tc.TcID, err) } aad, err := hex.DecodeString(tc.Aad) if err != nil { t.Errorf("#%d, cannot decode aad: %s", tc.TcID, err) } msg, err := hex.DecodeString(tc.Msg) if err != nil { t.Errorf("#%d, cannot decode msg: %s", tc.TcID, err) } ct, err := hex.DecodeString(tc.Ct) if err != nil { t.Errorf("#%d, cannot decode ct: %s", tc.TcID, err) } a, err := subtle.NewAESSIV(key) if err != nil { t.Errorf("NewAESSIV(key) = _, %v, want _, nil", err) continue } // EncryptDeterministically should always succeed since msg and aad are valid inputs. gotCt, err := a.EncryptDeterministically(msg, aad) if err != nil { t.Errorf("#%d, unexpected encryption error: %v", tc.TcID, err) } else { if tc.Result == "valid" && !bytes.Equal(gotCt, ct) { t.Errorf("#%d, incorrect encryption: got %v, want %v", tc.TcID, gotCt, ct) } if tc.Result == "invalid" && bytes.Equal(gotCt, ct) { t.Errorf("#%d, invalid encryption: got %v, want %v", tc.TcID, gotCt, ct) } } pt, err := a.DecryptDeterministically(ct, aad) if tc.Result == "valid" { if err != nil { t.Errorf("#%d, unexpected decryption error: %v", tc.TcID, err) } else if !bytes.Equal(pt, msg) { t.Errorf("#%d, incorrect decryption: got %v, want %v", tc.TcID, pt, msg) } } else { if err == nil { t.Errorf("#%d, decryption error expected: got nil", tc.TcID) } } } } } ================================================ FILE: go/deps.bzl ================================================ """Tink Go dependencies.""" load("@bazel_gazelle//:deps.bzl", "go_repository") # Placeholder for internal instructions to autogenerate dependencies. def go_dependencies(): """Loads Tink Go dependencies. These are autogenerated running `go mod tidy && bazel run //:gazelle-update-repos`. """ go_repository( name = "co_honnef_go_tools", importpath = "honnef.co/go/tools", sum = "h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs=", version = "v0.0.0-20190523083050-ea95bdfd59fc", ) go_repository( name = "com_github_antihax_optional", importpath = "github.com/antihax/optional", sum = "h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg=", version = "v1.0.0", ) go_repository( name = "com_github_armon_go_radix", importpath = "github.com/armon/go-radix", sum = "h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to=", version = "v0.0.0-20180808171621-7fddfc383310", ) go_repository( name = "com_github_aws_aws_sdk_go", importpath = "github.com/aws/aws-sdk-go", sum = "h1:Asrp6EMqqRxZvjK0NjzkWcrOk15RnWtupuUrUuZMabk=", version = "v1.44.267", ) go_repository( name = "com_github_bgentry_speakeasy", importpath = "github.com/bgentry/speakeasy", sum = "h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=", version = "v0.1.0", ) go_repository( name = "com_github_burntsushi_toml", importpath = "github.com/BurntSushi/toml", sum = "h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=", version = "v0.3.1", ) go_repository( name = "com_github_cenkalti_backoff_v3", importpath = "github.com/cenkalti/backoff/v3", sum = "h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c=", version = "v3.0.0", ) go_repository( name = "com_github_census_instrumentation_opencensus_proto", importpath = "github.com/census-instrumentation/opencensus-proto", sum = "h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g=", version = "v0.4.1", ) go_repository( name = "com_github_cespare_xxhash_v2", importpath = "github.com/cespare/xxhash/v2", sum = "h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=", version = "v2.2.0", ) go_repository( name = "com_github_client9_misspell", importpath = "github.com/client9/misspell", sum = "h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=", version = "v0.3.4", ) go_repository( name = "com_github_cncf_udpa_go", importpath = "github.com/cncf/udpa/go", sum = "h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk=", version = "v0.0.0-20220112060539-c52dc94e7fbe", ) go_repository( name = "com_github_cncf_xds_go", importpath = "github.com/cncf/xds/go", sum = "h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=", version = "v0.0.0-20230607035331-e9ce68804cb4", ) go_repository( name = "com_github_davecgh_go_spew", importpath = "github.com/davecgh/go-spew", sum = "h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=", version = "v1.1.1", ) go_repository( name = "com_github_envoyproxy_go_control_plane", importpath = "github.com/envoyproxy/go-control-plane", sum = "h1:7T++XKzy4xg7PKy+bM+Sa9/oe1OC88yz2hXQUISoXfA=", version = "v0.11.1-0.20230524094728-9239064ad72f", ) go_repository( name = "com_github_envoyproxy_protoc_gen_validate", importpath = "github.com/envoyproxy/protoc-gen-validate", sum = "h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8=", version = "v0.10.1", ) go_repository( name = "com_github_fatih_color", importpath = "github.com/fatih/color", sum = "h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=", version = "v1.7.0", ) go_repository( name = "com_github_ghodss_yaml", importpath = "github.com/ghodss/yaml", sum = "h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=", version = "v1.0.0", ) go_repository( name = "com_github_go_test_deep", importpath = "github.com/go-test/deep", sum = "h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw=", version = "v1.0.2", ) go_repository( name = "com_github_golang_glog", importpath = "github.com/golang/glog", sum = "h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE=", version = "v1.1.0", ) go_repository( name = "com_github_golang_groupcache", importpath = "github.com/golang/groupcache", sum = "h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=", version = "v0.0.0-20200121045136-8c9f03a8e57e", ) go_repository( name = "com_github_golang_mock", importpath = "github.com/golang/mock", sum = "h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=", version = "v1.1.1", ) go_repository( name = "com_github_golang_protobuf", importpath = "github.com/golang/protobuf", sum = "h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=", version = "v1.5.3", ) go_repository( name = "com_github_google_go_cmp", importpath = "github.com/google/go-cmp", sum = "h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=", version = "v0.5.9", ) go_repository( name = "com_github_google_s2a_go", importpath = "github.com/google/s2a-go", sum = "h1:FAgZmpLl/SXurPEZyCMPBIiiYeTbqfjlbdnCNTAkbGE=", version = "v0.1.3", ) go_repository( name = "com_github_google_uuid", importpath = "github.com/google/uuid", sum = "h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=", version = "v1.3.0", ) go_repository( name = "com_github_googleapis_enterprise_certificate_proxy", importpath = "github.com/googleapis/enterprise-certificate-proxy", sum = "h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k=", version = "v0.2.3", ) go_repository( name = "com_github_googleapis_gax_go_v2", importpath = "github.com/googleapis/gax-go/v2", sum = "h1:UBtEZqx1bjXtOQ5BVTkuYghXrr3N4V123VKJK67vJZc=", version = "v2.8.0", ) go_repository( name = "com_github_grpc_ecosystem_grpc_gateway", importpath = "github.com/grpc-ecosystem/grpc-gateway", sum = "h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=", version = "v1.16.0", ) go_repository( name = "com_github_hashicorp_errwrap", importpath = "github.com/hashicorp/errwrap", sum = "h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=", version = "v1.1.0", ) go_repository( name = "com_github_hashicorp_go_cleanhttp", importpath = "github.com/hashicorp/go-cleanhttp", sum = "h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=", version = "v0.5.2", ) go_repository( name = "com_github_hashicorp_go_hclog", importpath = "github.com/hashicorp/go-hclog", sum = "h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs=", version = "v0.16.2", ) go_repository( name = "com_github_hashicorp_go_multierror", importpath = "github.com/hashicorp/go-multierror", sum = "h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=", version = "v1.1.1", ) go_repository( name = "com_github_hashicorp_go_retryablehttp", importpath = "github.com/hashicorp/go-retryablehttp", sum = "h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM=", version = "v0.6.6", ) go_repository( name = "com_github_hashicorp_go_rootcerts", importpath = "github.com/hashicorp/go-rootcerts", sum = "h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=", version = "v1.0.2", ) go_repository( name = "com_github_hashicorp_go_secure_stdlib_parseutil", importpath = "github.com/hashicorp/go-secure-stdlib/parseutil", sum = "h1:om4Al8Oy7kCm/B86rLCLah4Dt5Aa0Fr5rYBG60OzwHQ=", version = "v0.1.6", ) go_repository( name = "com_github_hashicorp_go_secure_stdlib_strutil", importpath = "github.com/hashicorp/go-secure-stdlib/strutil", sum = "h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts=", version = "v0.1.2", ) go_repository( name = "com_github_hashicorp_go_sockaddr", importpath = "github.com/hashicorp/go-sockaddr", sum = "h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=", version = "v1.0.2", ) go_repository( name = "com_github_hashicorp_hcl", importpath = "github.com/hashicorp/hcl", sum = "h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=", version = "v1.0.0", ) go_repository( name = "com_github_hashicorp_vault_api", importpath = "github.com/hashicorp/vault/api", sum = "h1:LtY/I16+5jVGU8rufyyAkwopgq/HpUnxFBg+QLOAV38=", version = "v1.9.1", ) go_repository( name = "com_github_jmespath_go_jmespath", importpath = "github.com/jmespath/go-jmespath", sum = "h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=", version = "v0.4.0", ) go_repository( name = "com_github_jmespath_go_jmespath_internal_testify", importpath = "github.com/jmespath/go-jmespath/internal/testify", sum = "h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=", version = "v1.5.1", ) go_repository( name = "com_github_mattn_go_colorable", importpath = "github.com/mattn/go-colorable", sum = "h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=", version = "v0.1.6", ) go_repository( name = "com_github_mattn_go_isatty", importpath = "github.com/mattn/go-isatty", sum = "h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=", version = "v0.0.12", ) go_repository( name = "com_github_mitchellh_cli", importpath = "github.com/mitchellh/cli", sum = "h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y=", version = "v1.0.0", ) go_repository( name = "com_github_mitchellh_go_homedir", importpath = "github.com/mitchellh/go-homedir", sum = "h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=", version = "v1.1.0", ) go_repository( name = "com_github_mitchellh_go_wordwrap", importpath = "github.com/mitchellh/go-wordwrap", sum = "h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=", version = "v1.0.0", ) go_repository( name = "com_github_mitchellh_mapstructure", importpath = "github.com/mitchellh/mapstructure", sum = "h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=", version = "v1.5.0", ) go_repository( name = "com_github_pkg_errors", importpath = "github.com/pkg/errors", sum = "h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=", version = "v0.9.1", ) go_repository( name = "com_github_pmezard_go_difflib", importpath = "github.com/pmezard/go-difflib", sum = "h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=", version = "v1.0.0", ) go_repository( name = "com_github_posener_complete", importpath = "github.com/posener/complete", sum = "h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w=", version = "v1.1.1", ) go_repository( name = "com_github_prometheus_client_model", importpath = "github.com/prometheus/client_model", sum = "h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=", version = "v0.0.0-20190812154241-14fe0d1b01d4", ) go_repository( name = "com_github_rogpeppe_fastuuid", importpath = "github.com/rogpeppe/fastuuid", sum = "h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s=", version = "v1.2.0", ) go_repository( name = "com_github_ryanuber_columnize", importpath = "github.com/ryanuber/columnize", sum = "h1:j1Wcmh8OrK4Q7GXY+V7SVSY8nUWQxHW5TkBe7YUl+2s=", version = "v2.1.0+incompatible", ) go_repository( name = "com_github_ryanuber_go_glob", importpath = "github.com/ryanuber/go-glob", sum = "h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=", version = "v1.0.0", ) go_repository( name = "com_github_stretchr_objx", importpath = "github.com/stretchr/objx", sum = "h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=", version = "v0.5.0", ) go_repository( name = "com_github_stretchr_testify", importpath = "github.com/stretchr/testify", sum = "h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=", version = "v1.8.1", ) go_repository( name = "com_github_yuin_goldmark", importpath = "github.com/yuin/goldmark", sum = "h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=", version = "v1.4.13", ) go_repository( name = "com_google_cloud_go", importpath = "cloud.google.com/go", sum = "h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys=", version = "v0.110.0", ) go_repository( name = "com_google_cloud_go_accessapproval", importpath = "cloud.google.com/go/accessapproval", sum = "h1:x0cEHro/JFPd7eS4BlEWNTMecIj2HdXjOVB5BtvwER0=", version = "v1.6.0", ) go_repository( name = "com_google_cloud_go_accesscontextmanager", importpath = "cloud.google.com/go/accesscontextmanager", sum = "h1:MG60JgnEoawHJrbWw0jGdv6HLNSf6gQvYRiXpuzqgEA=", version = "v1.7.0", ) go_repository( name = "com_google_cloud_go_aiplatform", importpath = "cloud.google.com/go/aiplatform", sum = "h1:zTw+suCVchgZyO+k847wjzdVjWmrAuehxdvcZvJwfGg=", version = "v1.37.0", ) go_repository( name = "com_google_cloud_go_analytics", importpath = "cloud.google.com/go/analytics", sum = "h1:LqAo3tAh2FU9+w/r7vc3hBjU23Kv7GhO/PDIW7kIYgM=", version = "v0.19.0", ) go_repository( name = "com_google_cloud_go_apigateway", importpath = "cloud.google.com/go/apigateway", sum = "h1:ZI9mVO7x3E9RK/BURm2p1aw9YTBSCQe3klmyP1WxWEg=", version = "v1.5.0", ) go_repository( name = "com_google_cloud_go_apigeeconnect", importpath = "cloud.google.com/go/apigeeconnect", sum = "h1:sWOmgDyAsi1AZ48XRHcATC0tsi9SkPT7DA/+VCfkaeA=", version = "v1.5.0", ) go_repository( name = "com_google_cloud_go_apigeeregistry", importpath = "cloud.google.com/go/apigeeregistry", sum = "h1:E43RdhhCxdlV+I161gUY2rI4eOaMzHTA5kNkvRsFXvc=", version = "v0.6.0", ) go_repository( name = "com_google_cloud_go_apikeys", importpath = "cloud.google.com/go/apikeys", sum = "h1:B9CdHFZTFjVti89tmyXXrO+7vSNo2jvZuHG8zD5trdQ=", version = "v0.6.0", ) go_repository( name = "com_google_cloud_go_appengine", importpath = "cloud.google.com/go/appengine", sum = "h1:aBGDKmRIaRRoWJ2tAoN0oVSHoWLhtO9aj/NvUyP4aYs=", version = "v1.7.1", ) go_repository( name = "com_google_cloud_go_area120", importpath = "cloud.google.com/go/area120", sum = "h1:ugckkFh4XkHJMPhTIx0CyvdoBxmOpMe8rNs4Ok8GAag=", version = "v0.7.1", ) go_repository( name = "com_google_cloud_go_artifactregistry", importpath = "cloud.google.com/go/artifactregistry", sum = "h1:o1Q80vqEB6Qp8WLEH3b8FBLNUCrGQ4k5RFj0sn/sgO8=", version = "v1.13.0", ) go_repository( name = "com_google_cloud_go_asset", importpath = "cloud.google.com/go/asset", sum = "h1:YAsssO08BqZ6mncbb6FPlj9h6ACS7bJQUOlzciSfbNk=", version = "v1.13.0", ) go_repository( name = "com_google_cloud_go_assuredworkloads", importpath = "cloud.google.com/go/assuredworkloads", sum = "h1:VLGnVFta+N4WM+ASHbhc14ZOItOabDLH1MSoDv+Xuag=", version = "v1.10.0", ) go_repository( name = "com_google_cloud_go_automl", importpath = "cloud.google.com/go/automl", sum = "h1:50VugllC+U4IGl3tDNcZaWvApHBTrn/TvyHDJ0wM+Uw=", version = "v1.12.0", ) go_repository( name = "com_google_cloud_go_baremetalsolution", importpath = "cloud.google.com/go/baremetalsolution", sum = "h1:2AipdYXL0VxMboelTTw8c1UJ7gYu35LZYUbuRv9Q28s=", version = "v0.5.0", ) go_repository( name = "com_google_cloud_go_batch", importpath = "cloud.google.com/go/batch", sum = "h1:YbMt0E6BtqeD5FvSv1d56jbVsWEzlGm55lYte+M6Mzs=", version = "v0.7.0", ) go_repository( name = "com_google_cloud_go_beyondcorp", importpath = "cloud.google.com/go/beyondcorp", sum = "h1:UkY2BTZkEUAVrgqnSdOJ4p3y9ZRBPEe1LkjgC8Bj/Pc=", version = "v0.5.0", ) go_repository( name = "com_google_cloud_go_bigquery", importpath = "cloud.google.com/go/bigquery", sum = "h1:RscMV6LbnAmhAzD893Lv9nXXy2WCaJmbxYPWDLbGqNQ=", version = "v1.50.0", ) go_repository( name = "com_google_cloud_go_billing", importpath = "cloud.google.com/go/billing", sum = "h1:JYj28UYF5w6VBAh0gQYlgHJ/OD1oA+JgW29YZQU+UHM=", version = "v1.13.0", ) go_repository( name = "com_google_cloud_go_binaryauthorization", importpath = "cloud.google.com/go/binaryauthorization", sum = "h1:d3pMDBCCNivxt5a4eaV7FwL7cSH0H7RrEnFrTb1QKWs=", version = "v1.5.0", ) go_repository( name = "com_google_cloud_go_certificatemanager", importpath = "cloud.google.com/go/certificatemanager", sum = "h1:5C5UWeSt8Jkgp7OWn2rCkLmYurar/vIWIoSQ2+LaTOc=", version = "v1.6.0", ) go_repository( name = "com_google_cloud_go_channel", importpath = "cloud.google.com/go/channel", sum = "h1:GpcQY5UJKeOekYgsX3QXbzzAc/kRGtBq43fTmyKe6Uw=", version = "v1.12.0", ) go_repository( name = "com_google_cloud_go_cloudbuild", importpath = "cloud.google.com/go/cloudbuild", sum = "h1:GHQCjV4WlPPVU/j3Rlpc8vNIDwThhd1U9qSY/NPZdko=", version = "v1.9.0", ) go_repository( name = "com_google_cloud_go_clouddms", importpath = "cloud.google.com/go/clouddms", sum = "h1:E7v4TpDGUyEm1C/4KIrpVSOCTm0P6vWdHT0I4mostRA=", version = "v1.5.0", ) go_repository( name = "com_google_cloud_go_cloudtasks", importpath = "cloud.google.com/go/cloudtasks", sum = "h1:uK5k6abf4yligFgYFnG0ni8msai/dSv6mDmiBulU0hU=", version = "v1.10.0", ) go_repository( name = "com_google_cloud_go_compute", importpath = "cloud.google.com/go/compute", sum = "h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY=", version = "v1.19.1", ) go_repository( name = "com_google_cloud_go_compute_metadata", importpath = "cloud.google.com/go/compute/metadata", sum = "h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=", version = "v0.2.3", ) go_repository( name = "com_google_cloud_go_contactcenterinsights", importpath = "cloud.google.com/go/contactcenterinsights", sum = "h1:jXIpfcH/VYSE1SYcPzO0n1VVb+sAamiLOgCw45JbOQk=", version = "v1.6.0", ) go_repository( name = "com_google_cloud_go_container", importpath = "cloud.google.com/go/container", sum = "h1:NKlY/wCDapfVZlbVVaeuu2UZZED5Dy1z4Zx1KhEzm8c=", version = "v1.15.0", ) go_repository( name = "com_google_cloud_go_containeranalysis", importpath = "cloud.google.com/go/containeranalysis", sum = "h1:EQ4FFxNaEAg8PqQCO7bVQfWz9NVwZCUKaM1b3ycfx3U=", version = "v0.9.0", ) go_repository( name = "com_google_cloud_go_datacatalog", importpath = "cloud.google.com/go/datacatalog", sum = "h1:4H5IJiyUE0X6ShQBqgFFZvGGcrwGVndTwUSLP4c52gw=", version = "v1.13.0", ) go_repository( name = "com_google_cloud_go_dataflow", importpath = "cloud.google.com/go/dataflow", sum = "h1:eYyD9o/8Nm6EttsKZaEGD84xC17bNgSKCu0ZxwqUbpg=", version = "v0.8.0", ) go_repository( name = "com_google_cloud_go_dataform", importpath = "cloud.google.com/go/dataform", sum = "h1:Dyk+fufup1FR6cbHjFpMuP4SfPiF3LI3JtoIIALoq48=", version = "v0.7.0", ) go_repository( name = "com_google_cloud_go_datafusion", importpath = "cloud.google.com/go/datafusion", sum = "h1:sZjRnS3TWkGsu1LjYPFD/fHeMLZNXDK6PDHi2s2s/bk=", version = "v1.6.0", ) go_repository( name = "com_google_cloud_go_datalabeling", importpath = "cloud.google.com/go/datalabeling", sum = "h1:ch4qA2yvddGRUrlfwrNJCr79qLqhS9QBwofPHfFlDIk=", version = "v0.7.0", ) go_repository( name = "com_google_cloud_go_dataplex", importpath = "cloud.google.com/go/dataplex", sum = "h1:RvoZ5T7gySwm1CHzAw7yY1QwwqaGswunmqEssPxU/AM=", version = "v1.6.0", ) go_repository( name = "com_google_cloud_go_dataproc", importpath = "cloud.google.com/go/dataproc", sum = "h1:W47qHL3W4BPkAIbk4SWmIERwsWBaNnWm0P2sdx3YgGU=", version = "v1.12.0", ) go_repository( name = "com_google_cloud_go_dataqna", importpath = "cloud.google.com/go/dataqna", sum = "h1:yFzi/YU4YAdjyo7pXkBE2FeHbgz5OQQBVDdbErEHmVQ=", version = "v0.7.0", ) go_repository( name = "com_google_cloud_go_datastore", importpath = "cloud.google.com/go/datastore", sum = "h1:iF6I/HaLs3Ado8uRKMvZRvF/ZLkWaWE9i8AiHzbC774=", version = "v1.11.0", ) go_repository( name = "com_google_cloud_go_datastream", importpath = "cloud.google.com/go/datastream", sum = "h1:BBCBTnWMDwwEzQQmipUXxATa7Cm7CA/gKjKcR2w35T0=", version = "v1.7.0", ) go_repository( name = "com_google_cloud_go_deploy", importpath = "cloud.google.com/go/deploy", sum = "h1:otshdKEbmsi1ELYeCKNYppwV0UH5xD05drSdBm7ouTk=", version = "v1.8.0", ) go_repository( name = "com_google_cloud_go_dialogflow", importpath = "cloud.google.com/go/dialogflow", sum = "h1:uVlKKzp6G/VtSW0E7IH1Y5o0H48/UOCmqksG2riYCwQ=", version = "v1.32.0", ) go_repository( name = "com_google_cloud_go_dlp", importpath = "cloud.google.com/go/dlp", sum = "h1:1JoJqezlgu6NWCroBxr4rOZnwNFILXr4cB9dMaSKO4A=", version = "v1.9.0", ) go_repository( name = "com_google_cloud_go_documentai", importpath = "cloud.google.com/go/documentai", sum = "h1:KM3Xh0QQyyEdC8Gs2vhZfU+rt6OCPF0dwVwxKgLmWfI=", version = "v1.18.0", ) go_repository( name = "com_google_cloud_go_domains", importpath = "cloud.google.com/go/domains", sum = "h1:2ti/o9tlWL4N+wIuWUNH+LbfgpwxPr8J1sv9RHA4bYQ=", version = "v0.8.0", ) go_repository( name = "com_google_cloud_go_edgecontainer", importpath = "cloud.google.com/go/edgecontainer", sum = "h1:O0YVE5v+O0Q/ODXYsQHmHb+sYM8KNjGZw2pjX2Ws41c=", version = "v1.0.0", ) go_repository( name = "com_google_cloud_go_errorreporting", importpath = "cloud.google.com/go/errorreporting", sum = "h1:kj1XEWMu8P0qlLhm3FwcaFsUvXChV/OraZwA70trRR0=", version = "v0.3.0", ) go_repository( name = "com_google_cloud_go_essentialcontacts", importpath = "cloud.google.com/go/essentialcontacts", sum = "h1:gIzEhCoOT7bi+6QZqZIzX1Erj4SswMPIteNvYVlu+pM=", version = "v1.5.0", ) go_repository( name = "com_google_cloud_go_eventarc", importpath = "cloud.google.com/go/eventarc", sum = "h1:fsJmNeqvqtk74FsaVDU6cH79lyZNCYP8Rrv7EhaB/PU=", version = "v1.11.0", ) go_repository( name = "com_google_cloud_go_filestore", importpath = "cloud.google.com/go/filestore", sum = "h1:ckTEXN5towyTMu4q0uQ1Mde/JwTHur0gXs8oaIZnKfw=", version = "v1.6.0", ) go_repository( name = "com_google_cloud_go_firestore", importpath = "cloud.google.com/go/firestore", sum = "h1:IBlRyxgGySXu5VuW0RgGFlTtLukSnNkpDiEOMkQkmpA=", version = "v1.9.0", ) go_repository( name = "com_google_cloud_go_functions", importpath = "cloud.google.com/go/functions", sum = "h1:pPDqtsXG2g9HeOQLoquLbmvmb82Y4Ezdo1GXuotFoWg=", version = "v1.13.0", ) go_repository( name = "com_google_cloud_go_gaming", importpath = "cloud.google.com/go/gaming", sum = "h1:7vEhFnZmd931Mo7sZ6pJy7uQPDxF7m7v8xtBheG08tc=", version = "v1.9.0", ) go_repository( name = "com_google_cloud_go_gkebackup", importpath = "cloud.google.com/go/gkebackup", sum = "h1:za3QZvw6ujR0uyqkhomKKKNoXDyqYGPJies3voUK8DA=", version = "v0.4.0", ) go_repository( name = "com_google_cloud_go_gkeconnect", importpath = "cloud.google.com/go/gkeconnect", sum = "h1:gXYKciHS/Lgq0GJ5Kc9SzPA35NGc3yqu6SkjonpEr2Q=", version = "v0.7.0", ) go_repository( name = "com_google_cloud_go_gkehub", importpath = "cloud.google.com/go/gkehub", sum = "h1:TqCSPsEBQ6oZSJgEYZ3XT8x2gUadbvfwI32YB0kuHCs=", version = "v0.12.0", ) go_repository( name = "com_google_cloud_go_gkemulticloud", importpath = "cloud.google.com/go/gkemulticloud", sum = "h1:8I84Q4vl02rJRsFiinBxl7WCozfdLlUVBQuSrqr9Wtk=", version = "v0.5.0", ) go_repository( name = "com_google_cloud_go_gsuiteaddons", importpath = "cloud.google.com/go/gsuiteaddons", sum = "h1:1mvhXqJzV0Vg5Fa95QwckljODJJfDFXV4pn+iL50zzA=", version = "v1.5.0", ) go_repository( name = "com_google_cloud_go_iam", importpath = "cloud.google.com/go/iam", sum = "h1:+CmB+K0J/33d0zSQ9SlFWUeCCEn5XJA0ZMZ3pHE9u8k=", version = "v0.13.0", ) go_repository( name = "com_google_cloud_go_iap", importpath = "cloud.google.com/go/iap", sum = "h1:PxVHFuMxmSZyfntKXHXhd8bo82WJ+LcATenq7HLdVnU=", version = "v1.7.1", ) go_repository( name = "com_google_cloud_go_ids", importpath = "cloud.google.com/go/ids", sum = "h1:fodnCDtOXuMmS8LTC2y3h8t24U8F3eKWfhi+3LY6Qf0=", version = "v1.3.0", ) go_repository( name = "com_google_cloud_go_iot", importpath = "cloud.google.com/go/iot", sum = "h1:39W5BFSarRNZfVG0eXI5LYux+OVQT8GkgpHCnrZL2vM=", version = "v1.6.0", ) go_repository( name = "com_google_cloud_go_kms", importpath = "cloud.google.com/go/kms", sum = "h1:7hm1bRqGCA1GBRQUrp831TwJ9TWhP+tvLuP497CQS2g=", version = "v1.10.1", ) go_repository( name = "com_google_cloud_go_language", importpath = "cloud.google.com/go/language", sum = "h1:7Ulo2mDk9huBoBi8zCE3ONOoBrL6UXfAI71CLQ9GEIM=", version = "v1.9.0", ) go_repository( name = "com_google_cloud_go_lifesciences", importpath = "cloud.google.com/go/lifesciences", sum = "h1:uWrMjWTsGjLZpCTWEAzYvyXj+7fhiZST45u9AgasasI=", version = "v0.8.0", ) go_repository( name = "com_google_cloud_go_logging", importpath = "cloud.google.com/go/logging", sum = "h1:CJYxlNNNNAMkHp9em/YEXcfJg+rPDg7YfwoRpMU+t5I=", version = "v1.7.0", ) go_repository( name = "com_google_cloud_go_longrunning", importpath = "cloud.google.com/go/longrunning", sum = "h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM=", version = "v0.4.1", ) go_repository( name = "com_google_cloud_go_managedidentities", importpath = "cloud.google.com/go/managedidentities", sum = "h1:ZRQ4k21/jAhrHBVKl/AY7SjgzeJwG1iZa+mJ82P+VNg=", version = "v1.5.0", ) go_repository( name = "com_google_cloud_go_maps", importpath = "cloud.google.com/go/maps", sum = "h1:mv9YaczD4oZBZkM5XJl6fXQ984IkJNHPwkc8MUsdkBo=", version = "v0.7.0", ) go_repository( name = "com_google_cloud_go_mediatranslation", importpath = "cloud.google.com/go/mediatranslation", sum = "h1:anPxH+/WWt8Yc3EdoEJhPMBRF7EhIdz426A+tuoA0OU=", version = "v0.7.0", ) go_repository( name = "com_google_cloud_go_memcache", importpath = "cloud.google.com/go/memcache", sum = "h1:8/VEmWCpnETCrBwS3z4MhT+tIdKgR1Z4Tr2tvYH32rg=", version = "v1.9.0", ) go_repository( name = "com_google_cloud_go_metastore", importpath = "cloud.google.com/go/metastore", sum = "h1:QCFhZVe2289KDBQ7WxaHV2rAmPrmRAdLC6gbjUd3HPo=", version = "v1.10.0", ) go_repository( name = "com_google_cloud_go_monitoring", importpath = "cloud.google.com/go/monitoring", sum = "h1:2qsrgXGVoRXpP7otZ14eE1I568zAa92sJSDPyOJvwjM=", version = "v1.13.0", ) go_repository( name = "com_google_cloud_go_networkconnectivity", importpath = "cloud.google.com/go/networkconnectivity", sum = "h1:ZD6b4Pk1jEtp/cx9nx0ZYcL3BKqDa+KixNDZ6Bjs1B8=", version = "v1.11.0", ) go_repository( name = "com_google_cloud_go_networkmanagement", importpath = "cloud.google.com/go/networkmanagement", sum = "h1:8KWEUNGcpSX9WwZXq7FtciuNGPdPdPN/ruDm769yAEM=", version = "v1.6.0", ) go_repository( name = "com_google_cloud_go_networksecurity", importpath = "cloud.google.com/go/networksecurity", sum = "h1:sOc42Ig1K2LiKlzG71GUVloeSJ0J3mffEBYmvu+P0eo=", version = "v0.8.0", ) go_repository( name = "com_google_cloud_go_notebooks", importpath = "cloud.google.com/go/notebooks", sum = "h1:Kg2K3K7CbSXYJHZ1aGQpf1xi5x2GUvQWf2sFVuiZh8M=", version = "v1.8.0", ) go_repository( name = "com_google_cloud_go_optimization", importpath = "cloud.google.com/go/optimization", sum = "h1:dj8O4VOJRB4CUwZXdmwNViH1OtI0WtWL867/lnYH248=", version = "v1.3.1", ) go_repository( name = "com_google_cloud_go_orchestration", importpath = "cloud.google.com/go/orchestration", sum = "h1:Vw+CEXo8M/FZ1rb4EjcLv0gJqqw89b7+g+C/EmniTb8=", version = "v1.6.0", ) go_repository( name = "com_google_cloud_go_orgpolicy", importpath = "cloud.google.com/go/orgpolicy", sum = "h1:XDriMWug7sd0kYT1QKofRpRHzjad0bK8Q8uA9q+XrU4=", version = "v1.10.0", ) go_repository( name = "com_google_cloud_go_osconfig", importpath = "cloud.google.com/go/osconfig", sum = "h1:PkSQx4OHit5xz2bNyr11KGcaFccL5oqglFPdTboyqwQ=", version = "v1.11.0", ) go_repository( name = "com_google_cloud_go_oslogin", importpath = "cloud.google.com/go/oslogin", sum = "h1:whP7vhpmc+ufZa90eVpkfbgzJRK/Xomjz+XCD4aGwWw=", version = "v1.9.0", ) go_repository( name = "com_google_cloud_go_phishingprotection", importpath = "cloud.google.com/go/phishingprotection", sum = "h1:l6tDkT7qAEV49MNEJkEJTB6vOO/onbSOcNtAT09HPuA=", version = "v0.7.0", ) go_repository( name = "com_google_cloud_go_policytroubleshooter", importpath = "cloud.google.com/go/policytroubleshooter", sum = "h1:yKAGC4p9O61ttZUswaq9GAn1SZnEzTd0vUYXD7ZBT7Y=", version = "v1.6.0", ) go_repository( name = "com_google_cloud_go_privatecatalog", importpath = "cloud.google.com/go/privatecatalog", sum = "h1:EPEJ1DpEGXLDnmc7mnCAqFmkwUJbIsaLAiLHVOkkwtc=", version = "v0.8.0", ) go_repository( name = "com_google_cloud_go_pubsub", importpath = "cloud.google.com/go/pubsub", sum = "h1:vCge8m7aUKBJYOgrZp7EsNDf6QMd2CAlXZqWTn3yq6s=", version = "v1.30.0", ) go_repository( name = "com_google_cloud_go_pubsublite", importpath = "cloud.google.com/go/pubsublite", sum = "h1:cb9fsrtpINtETHiJ3ECeaVzrfIVhcGjhhJEjybHXHao=", version = "v1.7.0", ) go_repository( name = "com_google_cloud_go_recaptchaenterprise_v2", importpath = "cloud.google.com/go/recaptchaenterprise/v2", sum = "h1:6iOCujSNJ0YS7oNymI64hXsjGq60T4FK1zdLugxbzvU=", version = "v2.7.0", ) go_repository( name = "com_google_cloud_go_recommendationengine", importpath = "cloud.google.com/go/recommendationengine", sum = "h1:VibRFCwWXrFebEWKHfZAt2kta6pS7Tlimsnms0fjv7k=", version = "v0.7.0", ) go_repository( name = "com_google_cloud_go_recommender", importpath = "cloud.google.com/go/recommender", sum = "h1:ZnFRY5R6zOVk2IDS1Jbv5Bw+DExCI5rFumsTnMXiu/A=", version = "v1.9.0", ) go_repository( name = "com_google_cloud_go_redis", importpath = "cloud.google.com/go/redis", sum = "h1:JoAd3SkeDt3rLFAAxEvw6wV4t+8y4ZzfZcZmddqphQ8=", version = "v1.11.0", ) go_repository( name = "com_google_cloud_go_resourcemanager", importpath = "cloud.google.com/go/resourcemanager", sum = "h1:NRM0p+RJkaQF9Ee9JMnUV9BQ2QBIOq/v8M+Pbv/wmCs=", version = "v1.7.0", ) go_repository( name = "com_google_cloud_go_resourcesettings", importpath = "cloud.google.com/go/resourcesettings", sum = "h1:8Dua37kQt27CCWHm4h/Q1XqCF6ByD7Ouu49xg95qJzI=", version = "v1.5.0", ) go_repository( name = "com_google_cloud_go_retail", importpath = "cloud.google.com/go/retail", sum = "h1:1Dda2OpFNzIb4qWgFZjYlpP7sxX3aLeypKG6A3H4Yys=", version = "v1.12.0", ) go_repository( name = "com_google_cloud_go_run", importpath = "cloud.google.com/go/run", sum = "h1:ydJQo+k+MShYnBfhaRHSZYeD/SQKZzZLAROyfpeD9zw=", version = "v0.9.0", ) go_repository( name = "com_google_cloud_go_scheduler", importpath = "cloud.google.com/go/scheduler", sum = "h1:NpQAHtx3sulByTLe2dMwWmah8PWgeoieFPpJpArwFV0=", version = "v1.9.0", ) go_repository( name = "com_google_cloud_go_secretmanager", importpath = "cloud.google.com/go/secretmanager", sum = "h1:pu03bha7ukxF8otyPKTFdDz+rr9sE3YauS5PliDXK60=", version = "v1.10.0", ) go_repository( name = "com_google_cloud_go_security", importpath = "cloud.google.com/go/security", sum = "h1:PYvDxopRQBfYAXKAuDpFCKBvDOWPWzp9k/H5nB3ud3o=", version = "v1.13.0", ) go_repository( name = "com_google_cloud_go_securitycenter", importpath = "cloud.google.com/go/securitycenter", sum = "h1:AF3c2s3awNTMoBtMX3oCUoOMmGlYxGOeuXSYHNBkf14=", version = "v1.19.0", ) go_repository( name = "com_google_cloud_go_servicecontrol", importpath = "cloud.google.com/go/servicecontrol", sum = "h1:d0uV7Qegtfaa7Z2ClDzr9HJmnbJW7jn0WhZ7wOX6hLE=", version = "v1.11.1", ) go_repository( name = "com_google_cloud_go_servicedirectory", importpath = "cloud.google.com/go/servicedirectory", sum = "h1:SJwk0XX2e26o25ObYUORXx6torSFiYgsGkWSkZgkoSU=", version = "v1.9.0", ) go_repository( name = "com_google_cloud_go_servicemanagement", importpath = "cloud.google.com/go/servicemanagement", sum = "h1:fopAQI/IAzlxnVeiKn/8WiV6zKndjFkvi+gzu+NjywY=", version = "v1.8.0", ) go_repository( name = "com_google_cloud_go_serviceusage", importpath = "cloud.google.com/go/serviceusage", sum = "h1:rXyq+0+RSIm3HFypctp7WoXxIA563rn206CfMWdqXX4=", version = "v1.6.0", ) go_repository( name = "com_google_cloud_go_shell", importpath = "cloud.google.com/go/shell", sum = "h1:wT0Uw7ib7+AgZST9eCDygwTJn4+bHMDtZo5fh7kGWDU=", version = "v1.6.0", ) go_repository( name = "com_google_cloud_go_spanner", importpath = "cloud.google.com/go/spanner", sum = "h1:7VdjZ8zj4sHbDw55atp5dfY6kn1j9sam9DRNpPQhqR4=", version = "v1.45.0", ) go_repository( name = "com_google_cloud_go_speech", importpath = "cloud.google.com/go/speech", sum = "h1:JEVoWGNnTF128kNty7T4aG4eqv2z86yiMJPT9Zjp+iw=", version = "v1.15.0", ) go_repository( name = "com_google_cloud_go_storagetransfer", importpath = "cloud.google.com/go/storagetransfer", sum = "h1:5T+PM+3ECU3EY2y9Brv0Sf3oka8pKmsCfpQ07+91G9o=", version = "v1.8.0", ) go_repository( name = "com_google_cloud_go_talent", importpath = "cloud.google.com/go/talent", sum = "h1:nI9sVZPjMKiO2q3Uu0KhTDVov3Xrlpt63fghP9XjyEM=", version = "v1.5.0", ) go_repository( name = "com_google_cloud_go_texttospeech", importpath = "cloud.google.com/go/texttospeech", sum = "h1:H4g1ULStsbVtalbZGktyzXzw6jP26RjVGYx9RaYjBzc=", version = "v1.6.0", ) go_repository( name = "com_google_cloud_go_tpu", importpath = "cloud.google.com/go/tpu", sum = "h1:/34T6CbSi+kTv5E19Q9zbU/ix8IviInZpzwz3rsFE+A=", version = "v1.5.0", ) go_repository( name = "com_google_cloud_go_trace", importpath = "cloud.google.com/go/trace", sum = "h1:olxC0QHC59zgJVALtgqfD9tGk0lfeCP5/AGXL3Px/no=", version = "v1.9.0", ) go_repository( name = "com_google_cloud_go_translate", importpath = "cloud.google.com/go/translate", sum = "h1:GvLP4oQ4uPdChBmBaUSa/SaZxCdyWELtlAaKzpHsXdA=", version = "v1.7.0", ) go_repository( name = "com_google_cloud_go_video", importpath = "cloud.google.com/go/video", sum = "h1:upIbnGI0ZgACm58HPjAeBMleW3sl5cT84AbYQ8PWOgM=", version = "v1.15.0", ) go_repository( name = "com_google_cloud_go_videointelligence", importpath = "cloud.google.com/go/videointelligence", sum = "h1:Uh5BdoET8XXqXX2uXIahGb+wTKbLkGH7s4GXR58RrG8=", version = "v1.10.0", ) go_repository( name = "com_google_cloud_go_vision_v2", importpath = "cloud.google.com/go/vision/v2", sum = "h1:8C8RXUJoflCI4yVdqhTy9tRyygSHmp60aP363z23HKg=", version = "v2.7.0", ) go_repository( name = "com_google_cloud_go_vmmigration", importpath = "cloud.google.com/go/vmmigration", sum = "h1:Azs5WKtfOC8pxvkyrDvt7J0/4DYBch0cVbuFfCCFt5k=", version = "v1.6.0", ) go_repository( name = "com_google_cloud_go_vmwareengine", importpath = "cloud.google.com/go/vmwareengine", sum = "h1:b0NBu7S294l0gmtrT0nOJneMYgZapr5x9tVWvgDoVEM=", version = "v0.3.0", ) go_repository( name = "com_google_cloud_go_vpcaccess", importpath = "cloud.google.com/go/vpcaccess", sum = "h1:FOe6CuiQD3BhHJWt7E8QlbBcaIzVRddupwJlp7eqmn4=", version = "v1.6.0", ) go_repository( name = "com_google_cloud_go_webrisk", importpath = "cloud.google.com/go/webrisk", sum = "h1:IY+L2+UwxcVm2zayMAtBhZleecdIFLiC+QJMzgb0kT0=", version = "v1.8.0", ) go_repository( name = "com_google_cloud_go_websecurityscanner", importpath = "cloud.google.com/go/websecurityscanner", sum = "h1:AHC1xmaNMOZtNqxI9Rmm87IJEyPaRkOxeI0gpAacXGk=", version = "v1.5.0", ) go_repository( name = "com_google_cloud_go_workflows", importpath = "cloud.google.com/go/workflows", sum = "h1:FfGp9w0cYnaKZJhUOMqCOJCYT/WlvYBfTQhFWV3sRKI=", version = "v1.10.0", ) go_repository( name = "in_gopkg_check_v1", importpath = "gopkg.in/check.v1", sum = "h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=", version = "v0.0.0-20161208181325-20d25e280405", ) go_repository( name = "in_gopkg_square_go_jose_v2", importpath = "gopkg.in/square/go-jose.v2", sum = "h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=", version = "v2.5.1", ) go_repository( name = "in_gopkg_yaml_v2", importpath = "gopkg.in/yaml.v2", sum = "h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=", version = "v2.2.8", ) go_repository( name = "in_gopkg_yaml_v3", importpath = "gopkg.in/yaml.v3", sum = "h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=", version = "v3.0.1", ) go_repository( name = "io_opencensus_go", importpath = "go.opencensus.io", sum = "h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=", version = "v0.24.0", ) go_repository( name = "io_opentelemetry_go_proto_otlp", importpath = "go.opentelemetry.io/proto/otlp", sum = "h1:rwOQPCuKAKmwGKq2aVNnYIibI6wnV7EvzgfTCzcdGg8=", version = "v0.7.0", ) go_repository( name = "org_golang_google_api", importpath = "google.golang.org/api", sum = "h1:yHVU//vA+qkOhm4reEC9LtzHVUCN/IqqNRl1iQ9xE20=", version = "v0.123.0", ) go_repository( name = "org_golang_google_appengine", importpath = "google.golang.org/appengine", sum = "h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=", version = "v1.6.7", ) go_repository( name = "org_golang_google_genproto", importpath = "google.golang.org/genproto", sum = "h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=", version = "v0.0.0-20230410155749-daa745c078e1", ) go_repository( name = "org_golang_google_grpc", build_file_proto_mode = "disable", importpath = "google.golang.org/grpc", sum = "h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc=", version = "v1.56.3", ) go_repository( name = "org_golang_google_protobuf", importpath = "google.golang.org/protobuf", sum = "h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=", version = "v1.30.0", ) go_repository( name = "org_golang_x_crypto", importpath = "golang.org/x/crypto", sum = "h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=", version = "v0.17.0", ) go_repository( name = "org_golang_x_exp", importpath = "golang.org/x/exp", sum = "h1:c2HOrn5iMezYjSlGPncknSEr/8x5LELb/ilJbXi9DEA=", version = "v0.0.0-20190121172915-509febef88a4", ) go_repository( name = "org_golang_x_lint", importpath = "golang.org/x/lint", sum = "h1:XQyxROzUlZH+WIQwySDgnISgOivlhjIEwaQaJEJrrN0=", version = "v0.0.0-20190313153728-d0100b6bd8b3", ) go_repository( name = "org_golang_x_mod", importpath = "golang.org/x/mod", sum = "h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=", version = "v0.8.0", ) go_repository( name = "org_golang_x_net", importpath = "golang.org/x/net", sum = "h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=", version = "v0.17.0", ) go_repository( name = "org_golang_x_oauth2", importpath = "golang.org/x/oauth2", sum = "h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g=", version = "v0.7.0", ) go_repository( name = "org_golang_x_sync", importpath = "golang.org/x/sync", sum = "h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=", version = "v0.1.0", ) go_repository( name = "org_golang_x_sys", importpath = "golang.org/x/sys", sum = "h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=", version = "v0.15.0", ) go_repository( name = "org_golang_x_term", importpath = "golang.org/x/term", sum = "h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=", version = "v0.15.0", ) go_repository( name = "org_golang_x_text", importpath = "golang.org/x/text", sum = "h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=", version = "v0.14.0", ) go_repository( name = "org_golang_x_time", importpath = "golang.org/x/time", sum = "h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI=", version = "v0.0.0-20200416051211-89c76fbcd5d1", ) go_repository( name = "org_golang_x_tools", importpath = "golang.org/x/tools", sum = "h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=", version = "v0.6.0", ) go_repository( name = "org_golang_x_xerrors", importpath = "golang.org/x/xerrors", sum = "h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=", version = "v0.0.0-20200804184101-5ec99f83aff1", ) ================================================ FILE: go/go.mod ================================================ module github.com/google/tink/go go 1.20 require ( github.com/aws/aws-sdk-go v1.44.267 github.com/google/go-cmp v0.5.9 github.com/hashicorp/vault/api v1.9.1 golang.org/x/crypto v0.17.0 google.golang.org/api v0.123.0 google.golang.org/protobuf v1.30.0 ) require ( cloud.google.com/go/compute v1.19.1 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect github.com/cenkalti/backoff/v3 v3.0.0 // indirect github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/s2a-go v0.1.3 // indirect github.com/google/uuid v1.3.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect github.com/googleapis/gax-go/v2 v2.8.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-retryablehttp v0.6.6 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 // indirect github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect github.com/hashicorp/go-sockaddr v1.0.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect go.opencensus.io v0.24.0 // indirect golang.org/x/net v0.17.0 // indirect golang.org/x/oauth2 v0.7.0 // indirect golang.org/x/sys v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect google.golang.org/grpc v1.56.3 // indirect gopkg.in/square/go-jose.v2 v2.5.1 // indirect ) ================================================ FILE: go/go.sum ================================================ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY= cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aws/aws-sdk-go v1.44.267 h1:Asrp6EMqqRxZvjK0NjzkWcrOk15RnWtupuUrUuZMabk= github.com/aws/aws-sdk-go v1.44.267/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/s2a-go v0.1.3 h1:FAgZmpLl/SXurPEZyCMPBIiiYeTbqfjlbdnCNTAkbGE= github.com/google/s2a-go v0.1.3/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/gax-go/v2 v2.8.0 h1:UBtEZqx1bjXtOQ5BVTkuYghXrr3N4V123VKJK67vJZc= github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM= github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 h1:om4Al8Oy7kCm/B86rLCLah4Dt5Aa0Fr5rYBG60OzwHQ= github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U= github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts= github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/vault/api v1.9.1 h1:LtY/I16+5jVGU8rufyyAkwopgq/HpUnxFBg+QLOAV38= github.com/hashicorp/vault/api v1.9.1/go.mod h1:78kktNcQYbBGSrOjQfHjXN32OhhxXnbYl3zxpd2uPUs= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g= golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.123.0 h1:yHVU//vA+qkOhm4reEC9LtzHVUCN/IqqNRl1iQ9xE20= google.golang.org/api v0.123.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc= google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= ================================================ FILE: go/hybrid/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "hybrid", srcs = [ "ecies_aead_hkdf_dem_helper.go", "ecies_aead_hkdf_private_key_manager.go", "ecies_aead_hkdf_public_key_manager.go", "hpke_private_key_manager.go", "hpke_public_key_manager.go", "hybrid.go", "hybrid_decrypt_factory.go", "hybrid_encrypt_factory.go", "hybrid_key_templates.go", ], importpath = "github.com/google/tink/go/hybrid", visibility = ["//visibility:public"], deps = [ "//aead", "//core/cryptofmt", "//core/primitiveset", "//core/registry", "//hybrid/internal/hpke", "//hybrid/subtle", "//internal/internalregistry", "//internal/monitoringutil", "//internal/tinkerror", "//keyset", "//monitoring", "//proto/aes_ctr_hmac_aead_go_proto", "//proto/aes_gcm_go_proto", "//proto/aes_siv_go_proto", "//proto/common_go_proto", "//proto/ecies_aead_hkdf_go_proto", "//proto/hpke_go_proto", "//proto/tink_go_proto", "//subtle", "//tink", "@org_golang_google_protobuf//proto", ], ) go_test( name = "hybrid_test", srcs = [ "ecies_aead_hkdf_dem_helper_test.go", "ecies_aead_hkdf_hybrid_decrypt_test.go", "ecies_aead_hkdf_hybrid_encrypt_test.go", "ecies_aead_hkdf_private_key_manager_test.go", "ecies_aead_hkdf_public_key_manager_test.go", "ecies_aead_hkdf_test.go", "hpke_private_key_manager_test.go", "hpke_public_key_manager_test.go", "hybrid_benchmark_test.go", "hybrid_factory_test.go", "hybrid_key_templates_test.go", "hybrid_test.go", ], embed = [":hybrid"], deps = [ "//aead", "//core/cryptofmt", "//core/registry", "//daead", "//hybrid/internal/hpke", "//hybrid/subtle", "//insecurecleartextkeyset", "//internal/internalregistry", "//internal/tinkerror", "//keyset", "//mac", "//monitoring", "//proto/common_go_proto", "//proto/ecies_aead_hkdf_go_proto", "//proto/hpke_go_proto", "//proto/tink_go_proto", "//signature", "//subtle", "//subtle/random", "//testing/fakemonitoring", "//testkeyset", "//testutil", "//tink", "@com_github_google_go_cmp//cmp", "@com_github_google_go_cmp//cmp/cmpopts", "@org_golang_google_protobuf//proto", "@org_golang_google_protobuf//testing/protocmp", ], ) alias( name = "go_default_library", actual = ":hybrid", visibility = ["//visibility:public"], ) ================================================ FILE: go/hybrid/ecies_aead_hkdf_dem_helper.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hybrid import ( "errors" "fmt" "strings" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/hybrid/subtle" "github.com/google/tink/go/tink" ctrhmacpb "github.com/google/tink/go/proto/aes_ctr_hmac_aead_go_proto" gcmpb "github.com/google/tink/go/proto/aes_gcm_go_proto" sivpb "github.com/google/tink/go/proto/aes_siv_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( aesGCMTypeURL = "type.googleapis.com/google.crypto.tink.AesGcmKey" aesCTRHMACAEADTypeURL = "type.googleapis.com/google.crypto.tink.AesCtrHmacAeadKey" aesSIVTypeURL = "type.googleapis.com/google.crypto.tink.AesSivKey" ) // eciesAEADHKDFDEMHelper generates AEAD or DeterministicAEAD primitives for the specified KeyTemplate and key material. // in order to implement the EciesAEADHKDFDEMHelper interface. type eciesAEADHKDFDEMHelper struct { demKeyURL string keyData []byte symmetricKeySize uint32 aesCTRSize uint32 } var _ subtle.EciesAEADHKDFDEMHelper = (*eciesAEADHKDFDEMHelper)(nil) // newRegisterECIESAEADHKDFDemHelper initializes and returns a RegisterECIESAEADHKDFDemHelper func newRegisterECIESAEADHKDFDemHelper(k *tinkpb.KeyTemplate) (*eciesAEADHKDFDEMHelper, error) { var len uint32 var aesCTRSize uint32 var keyFormat []byte if strings.Compare(k.TypeUrl, aesGCMTypeURL) == 0 { gcmKeyFormat := new(gcmpb.AesGcmKeyFormat) var err error if err = proto.Unmarshal(k.Value, gcmKeyFormat); err != nil { return nil, err } len = gcmKeyFormat.KeySize keyFormat, err = proto.Marshal(gcmKeyFormat) if err != nil { return nil, fmt.Errorf("failed to serialize key format, error :%v", err) } } else if strings.Compare(k.TypeUrl, aesCTRHMACAEADTypeURL) == 0 { aeadKeyFormat := new(ctrhmacpb.AesCtrHmacAeadKeyFormat) var err error if err = proto.Unmarshal(k.Value, aeadKeyFormat); err != nil { return nil, err } if aeadKeyFormat.AesCtrKeyFormat == nil || aeadKeyFormat.HmacKeyFormat == nil { return nil, fmt.Errorf("failed to deserialize key format") } aesCTRSize = aeadKeyFormat.AesCtrKeyFormat.KeySize len = aesCTRSize + aeadKeyFormat.HmacKeyFormat.KeySize keyFormat, err = proto.Marshal(aeadKeyFormat) if err != nil { return nil, fmt.Errorf("failed to serialize key format, error :%v", err) } } else if strings.Compare(k.TypeUrl, aesSIVTypeURL) == 0 { daeadKeyFormat := new(sivpb.AesSivKeyFormat) var err error if err = proto.Unmarshal(k.Value, daeadKeyFormat); err != nil { return nil, err } len = daeadKeyFormat.KeySize keyFormat, err = proto.Marshal(daeadKeyFormat) if err != nil { return nil, fmt.Errorf("failed to serialize key format, error :%v", err) } } else { return nil, fmt.Errorf("unsupported AEAD DEM key type: %s", k.TypeUrl) } km, err := registry.GetKeyManager(k.TypeUrl) if err != nil { return nil, fmt.Errorf("failed to fetch KeyManager, error: %v", err) } key, err := km.NewKey(keyFormat) if err != nil { return nil, fmt.Errorf("failed to fetch key, error: %v", err) } sk, err := proto.Marshal(key) if err != nil { return nil, fmt.Errorf("failed to serialize key, error: %v", err) } return &eciesAEADHKDFDEMHelper{ demKeyURL: k.TypeUrl, keyData: sk, symmetricKeySize: len, aesCTRSize: aesCTRSize, }, nil } // GetSymmetricKeySize returns the symmetric key size func (r *eciesAEADHKDFDEMHelper) GetSymmetricKeySize() uint32 { return r.symmetricKeySize } // GetAEADOrDAEAD returns the AEAD or deterministic AEAD primitive from the DEM func (r *eciesAEADHKDFDEMHelper) GetAEADOrDAEAD(symmetricKeyValue []byte) (any, error) { var sk []byte if uint32(len(symmetricKeyValue)) != r.GetSymmetricKeySize() { return nil, errors.New("symmetric key has incorrect length") } if strings.Compare(r.demKeyURL, aesGCMTypeURL) == 0 { gcmKey := new(gcmpb.AesGcmKey) var err error if err := proto.Unmarshal(r.keyData, gcmKey); err != nil { return nil, err } gcmKey.KeyValue = symmetricKeyValue sk, err = proto.Marshal(gcmKey) if err != nil { return nil, fmt.Errorf("failed to serialize key, error: %v", err) } } else if strings.Compare(r.demKeyURL, aesCTRHMACAEADTypeURL) == 0 { aesCTR := new(ctrhmacpb.AesCtrHmacAeadKey) var err error if err := proto.Unmarshal(r.keyData, aesCTR); err != nil { return nil, err } aesCTR.AesCtrKey.KeyValue = symmetricKeyValue[:r.aesCTRSize] aesCTR.HmacKey.KeyValue = symmetricKeyValue[r.aesCTRSize:] sk, err = proto.Marshal(aesCTR) if err != nil { return nil, fmt.Errorf("failed to serialize key, error: %v", err) } } else if strings.Compare(r.demKeyURL, aesSIVTypeURL) == 0 { sivKey := new(sivpb.AesSivKey) var err error if err := proto.Unmarshal(r.keyData, sivKey); err != nil { return nil, err } sivKey.KeyValue = symmetricKeyValue sk, err = proto.Marshal(sivKey) if err != nil { return nil, fmt.Errorf("failed to serialize key, error: %v", err) } } else { return nil, fmt.Errorf("unsupported AEAD DEM key type: %s", r.demKeyURL) } p, err := registry.Primitive(r.demKeyURL, sk) if err != nil { return nil, err } switch p.(type) { case tink.AEAD, tink.DeterministicAEAD: return p, nil default: return nil, fmt.Errorf("Unexpected primitive type returned by the registry for the DEM: %T", p) } } ================================================ FILE: go/hybrid/ecies_aead_hkdf_dem_helper_test.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hybrid import ( "bytes" "testing" "github.com/google/tink/go/aead" "github.com/google/tink/go/daead" "github.com/google/tink/go/mac" "github.com/google/tink/go/signature" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/tink" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) type eciesAEADHKDFDEMHelperTestCase struct { name string template *tinkpb.KeyTemplate keySize uint32 } var ( eciesAEADHKDFDEMHelperSupportedAEADs = []eciesAEADHKDFDEMHelperTestCase{ { name: "AESCTRHMACSHA256", template: aead.AES256CTRHMACSHA256KeyTemplate(), keySize: 64, }, { name: "AES128CTRHMACSHA256", template: aead.AES128CTRHMACSHA256KeyTemplate(), keySize: 48, }, { name: "AES256GCM", template: aead.AES256GCMKeyTemplate(), keySize: 32, }, { name: "AES128GCM", template: aead.AES128GCMKeyTemplate(), keySize: 16, }, } eciesAEADHKDFDEMHelperSupportedDAEADs = []eciesAEADHKDFDEMHelperTestCase{ { name: "AESSIV", template: daead.AESSIVKeyTemplate(), keySize: 64, }, } ) func TestECIESAEADHKDFDEMHelper_AEADKeyTemplates(t *testing.T) { plaintext := random.GetRandomBytes(20) associatedData := random.GetRandomBytes(20) for _, tc := range eciesAEADHKDFDEMHelperSupportedAEADs { t.Run(tc.name, func(t *testing.T) { dem, err := newRegisterECIESAEADHKDFDemHelper(tc.template) if err != nil { t.Fatalf("newRegisterECIESAEADHKDFDEMHelper(tc.template) err = %s, want nil", err) } sk := random.GetRandomBytes(dem.GetSymmetricKeySize()) primitive, err := dem.GetAEADOrDAEAD(sk) if err != nil { t.Fatalf("dem.GetAEADorDAEAD(sk) err = %v, want nil", err) } a, ok := primitive.(tink.AEAD) if !ok { t.Fatalf("primitive is not of type tink.AEAD") } var ciphertext []byte ciphertext, err = a.Encrypt(plaintext, associatedData) if err != nil { t.Fatalf("a.Encrypt() err = %v, want nil", err) } var decrypted []byte decrypted, err = a.Decrypt(ciphertext, associatedData) if err != nil { t.Fatalf("a.Decrypt() err = %v, want nil", err) } if !bytes.Equal(decrypted, plaintext) { t.Errorf("a.Decrypt() = %x, want: %x", decrypted, plaintext) } }) } } func TestECIESAEADHKDFDEMHelper_DAEADKeyTemplates(t *testing.T) { plaintext := random.GetRandomBytes(20) associatedData := random.GetRandomBytes(20) for _, tc := range eciesAEADHKDFDEMHelperSupportedDAEADs { t.Run(tc.name, func(t *testing.T) { dem, err := newRegisterECIESAEADHKDFDemHelper(tc.template) if err != nil { t.Fatalf("newRegisterECIESAEADHKDFDEMHelper(tc.template) err = %s, want nil", err) } sk := random.GetRandomBytes(dem.GetSymmetricKeySize()) primitive, err := dem.GetAEADOrDAEAD(sk) if err != nil { t.Fatalf("dem.GetAEADorDAEAD(sk) err = %v, want nil", err) } d, ok := primitive.(tink.DeterministicAEAD) if !ok { t.Fatalf("primitive is not of type tink.DeterministicAEAD") } var ciphertext []byte ciphertext, err = d.EncryptDeterministically(plaintext, associatedData) if err != nil { t.Fatalf("d.Encrypt() err = %v, want nil", err) } var decrypted []byte decrypted, err = d.DecryptDeterministically(ciphertext, associatedData) if err != nil { t.Fatalf("d.Decrypt() err = %v, want nil", err) } if !bytes.Equal(decrypted, plaintext) { t.Errorf("d.Decrypt() = %x, want: %x", decrypted, plaintext) } }) } } func TestECIESAEADHKDFDEMHelper_KeySizes(t *testing.T) { var testCases []eciesAEADHKDFDEMHelperTestCase testCases = append(testCases, eciesAEADHKDFDEMHelperSupportedAEADs...) testCases = append(testCases, eciesAEADHKDFDEMHelperSupportedDAEADs...) for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { dem, err := newRegisterECIESAEADHKDFDemHelper(tc.template) if err != nil { t.Fatalf("newRegisterECIESAEADHKDFDemHelper(tc.template): %s", err) } if dem.GetSymmetricKeySize() != tc.keySize { t.Errorf("dem.GetSymmetricKeySize() = %d, want: %d", dem.GetSymmetricKeySize(), tc.keySize) } shortKey := make([]byte, tc.keySize-1) if _, err = dem.GetAEADOrDAEAD(shortKey); err == nil { t.Errorf("dem.GetAEADOrDAEAD(shortKey) err = nil, want non-nil") } longKey := make([]byte, tc.keySize+1) if _, err = dem.GetAEADOrDAEAD(longKey); err == nil { t.Errorf("dem.GetAEADOrDAEAD(longKey) err = nil, want non-nil") } }) } } func TestECIESAEADHKDFDEMHelper_UnsupportedKeyTemplates(t *testing.T) { testCases := []struct { name string template *tinkpb.KeyTemplate }{ { name: "signature", template: signature.ECDSAP256KeyTemplate(), }, { name: "mac", template: mac.HMACSHA256Tag256KeyTemplate(), }, { name: "invalid_type_and_value", template: &tinkpb.KeyTemplate{TypeUrl: "some url", Value: []byte{0}}, }, { name: "aesctrhmac_empty_value", template: &tinkpb.KeyTemplate{TypeUrl: aesCTRHMACAEADTypeURL}, }, { name: "aesgcm_empty_value", template: &tinkpb.KeyTemplate{TypeUrl: aesGCMTypeURL}, }, { name: "aessiv_empty_value", template: &tinkpb.KeyTemplate{TypeUrl: aesSIVTypeURL}, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { if _, err := newRegisterECIESAEADHKDFDemHelper(tc.template); err == nil { t.Errorf("newRegisterECIESAEADHKDFDemHelper() err = nil, want non-nil") } }) } } ================================================ FILE: go/hybrid/ecies_aead_hkdf_hybrid_decrypt_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hybrid import ( "bytes" "encoding/hex" "testing" "github.com/google/tink/go/aead" "github.com/google/tink/go/daead" "github.com/google/tink/go/hybrid/subtle" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func modifyDecrypt(t *testing.T, c string, k *tinkpb.KeyTemplate) { t.Helper() curve, err := subtle.GetCurve(c) if err != nil { t.Fatalf("error getting %s curve: %s ", c, err) } pvt, err := subtle.GenerateECDHKeyPair(curve) if err != nil { t.Fatalf("error generating ECDH key pair: %s", err) } salt := random.GetRandomBytes(8) pt := random.GetRandomBytes(4) context := random.GetRandomBytes(4) rDem, err := newRegisterECIESAEADHKDFDemHelper(k) if err != nil { t.Fatalf("error generating a DEM helper :%s", err) } e, err := subtle.NewECIESAEADHKDFHybridEncrypt(&pvt.PublicKey, salt, "SHA256", "UNCOMPRESSED", rDem) if err != nil { t.Fatalf("error generating an encryption construct :%s", err) } d, err := subtle.NewECIESAEADHKDFHybridDecrypt(pvt, salt, "SHA256", "UNCOMPRESSED", rDem) if err != nil { t.Fatalf("error generating an decryption construct :%s", err) } ct, err := e.Encrypt(pt, context) if err != nil { t.Fatalf("encryption error :%s", err) } dt, err := d.Decrypt(ct, context) if err != nil { t.Fatalf("decryption error :%s", err) } if !bytes.Equal(dt, pt) { t.Fatalf("decryption not inverse of encryption") } for _, g := range testutil.GenerateMutations(ct) { if _, err := d.Decrypt(g, context); err == nil { t.Fatalf("invalid cipher text should throw exception") } } for _, g := range testutil.GenerateMutations(context) { if _, err := d.Decrypt(ct, g); err == nil { t.Fatalf("invalid context should throw exception") } } mSalt := make([]byte, len(salt)) for i := 0; i < len(salt); i++ { for j := 0; j < 8; j++ { copy(mSalt, salt) mSalt[i] ^= (1 << uint8(j)) d, err = subtle.NewECIESAEADHKDFHybridDecrypt(pvt, mSalt, "SHA256", "UNCOMPRESSED", rDem) if err != nil { t.Fatalf("subtle.NewECIESAEADHKDFHybridDecrypt:%v", err) } if _, err := d.Decrypt(ct, context); err == nil { t.Fatalf("invalid salt should throw exception") } } } } func TestECAESCTRHMACSHA256Decrypt(t *testing.T) { modifyDecrypt(t, "NIST_P256", aead.AES256CTRHMACSHA256KeyTemplate()) modifyDecrypt(t, "NIST_P384", aead.AES256CTRHMACSHA256KeyTemplate()) modifyDecrypt(t, "NIST_P521", aead.AES256CTRHMACSHA256KeyTemplate()) modifyDecrypt(t, "NIST_P224", aead.AES256CTRHMACSHA256KeyTemplate()) modifyDecrypt(t, "NIST_P256", aead.AES128CTRHMACSHA256KeyTemplate()) modifyDecrypt(t, "NIST_P384", aead.AES128CTRHMACSHA256KeyTemplate()) modifyDecrypt(t, "NIST_P521", aead.AES128CTRHMACSHA256KeyTemplate()) modifyDecrypt(t, "NIST_P224", aead.AES128CTRHMACSHA256KeyTemplate()) } func TestECAES256GCMDecrypt(t *testing.T) { modifyDecrypt(t, "NIST_P256", aead.AES256GCMKeyTemplate()) modifyDecrypt(t, "NIST_P384", aead.AES256GCMKeyTemplate()) modifyDecrypt(t, "NIST_P521", aead.AES256GCMKeyTemplate()) modifyDecrypt(t, "NIST_P224", aead.AES256GCMKeyTemplate()) modifyDecrypt(t, "NIST_P256", aead.AES128GCMKeyTemplate()) modifyDecrypt(t, "NIST_P384", aead.AES128GCMKeyTemplate()) modifyDecrypt(t, "NIST_P521", aead.AES128GCMKeyTemplate()) modifyDecrypt(t, "NIST_P224", aead.AES128GCMKeyTemplate()) } func TestECAESSIVDecrypt(t *testing.T) { modifyDecrypt(t, "NIST_P256", daead.AESSIVKeyTemplate()) modifyDecrypt(t, "NIST_P384", daead.AESSIVKeyTemplate()) modifyDecrypt(t, "NIST_P521", daead.AESSIVKeyTemplate()) modifyDecrypt(t, "NIST_P224", daead.AESSIVKeyTemplate()) } func TestECAESSIVTestVectors(t *testing.T) { // These are the same test vectors used to test the c++ implementation in // //third_party/tink/cc/hybrid/ecies_aead_hkdf_hybrid_decrypt_test.cc. testvectors := []struct { name, key, ciphertext, context, plaintext string }{ { name: "Empty plaintext", key: "32588172ed65830571bb83748f7fddd383323208a7825c80a71bef846333eb02", ciphertext: "0401b11f8c9bafe30ae13f8bd15528714e752631a4328bf146009068e99489c8e9fae1ec39e3fe9994723711417fcab2af4b3c9b60117d47d33d35175c87b483b8935a73312940d1fbf8da3944a89b5e8b", context: "some context info", plaintext: "", }, { name: "Small plaintext", key: "32588172ed65830571bb83748f7fddd383323208a7825c80a71bef846333eb02", ciphertext: "040230023d1547b55af5a735a7f460722612126d7539d7cd0f677d308b29c6f52a964e66e7b0cb44cff1673df9e2c793f1477ca755807bfbeadcae1ab20b45ecb1501ca5e3f5b0626d3ca40aa5d010443d506e4df90b", context: "some context info", plaintext: "hello", }, { name: "Large plaintext", key: "32588172ed65830571bb83748f7fddd383323208a7825c80a71bef846333eb02", ciphertext: "0441ddd246cea0825bd68bddff05cec54a4ee678da35b2f5cfbbb32e5350bdd817214bfb7b5ed5528131bde56916062cfbd8b9952d9e0907a6e87e1de54db5df3aaccddd328efcf7771ce061e647488f66b8c11a9fca171dcff813e90b44b2739573f9f23b60202491870c7ff8aaf0ae46838e48f17f8dc1ad55b67809699dd31eb6ca50dfa9beeee32d30bdc00a1eb1d8b0cbcedbe50b1e24619cc5e79042f25f49e2c2d5a35c79e833c0d68e31a93da4173aacd0428b367594ed4636763d16c23e4f8c115d44bddc83bcefcaea13587238ce8b7a5d5fad53beeb59aaa1d7483eb4bac93ed50ed4d3e9fd5af760283fd38080b58744b73212a36039179ce6f96ef1ecaa05b5186967d81c06b9cd91140dfbd54084ddcfd941527719848a2eecb84278f6a0fe9357a3964f87222fcd16a12a353e1f64fd45dc227a4a2112da6f61269f22f16b41e68eadf0b6b3a48c67b9e7e3ec1c66eecce50dda8ecbce99d3778299aa28741b7247fbc46a1b8a908dc23943c2dd17210a270bb12b096c2c6a00400a95c62894a15b9fc44e709d27348f2f2644a786cd9e96caf42ea9b949f76e85e6f7365e15fa2902e851222c025f6c208269d799fcfc4c0b37aba8979ed9e6ccf543c217ee0b6ad05f0e3ffb92943d308c801b25efedab5bf93a733bdae611132d774d4b9ee4fb5e88ae63014315ae9571039a8c8c7020e2b3a1bbd4235b65af94771c8417c87fd6cab423b82a557f60a99ae7402dba205e05136dd34f0026fce87899d4b9819cc2b2ba686512d62c41a1e3a667a705ea45404aafa489cd7f53f42455fff3f9b22f960d12a2587efd6ed0fa3e00dd4645face1b2f1268e6019be70999eab00f0aeff3cb0e77b7c4a1ab1fdf15d00c4eedd7b75e8cf5c90119346894089ee0299d58f1d7ebac9b592da2325a5a738ea2baecc1468670f5aec880bce32efecfb2a7c5ad3ae4096b0a07aa9bfe6cbaf53da6757377bb692e55ec8caf5f0af28dafdc42e1d6e5893140945a853f56652c575b99d64399aad2d042948575134c8fe638fb0b80ac3a0f08a60f3aa817fe0a24c1fffee6933bd72ea460e0b241d3f5d98b2321ee25d8c0302353fcfd41bce964d73ff670422864506cc56f3470362c90144586ccbfc8e5e6fefbb70429b0a517e4b1badb449cd11092790aba6e19b914899872f4fb481c8dc47a33422fc05072ac99c958e40dae53d96ebd87cfbde67a0f050203a89e487da5e03364951830e43771d36abfbe8f5a7da8e7aa891f36a68dbe9a3b0e3dfbd1afd6327a3ced4a5cd8a5b256fef46d200df4af2e2da4dbb786ea0404bb968b6d961e4fc76f89e70ad7c9e11d6aee6526b75b399811f73c053a29582ba9295ea4d5a8fffb5a8ccbac008d291dd60e2041371acfc4c432a0ae0fcd8fa25c9551123c95da64caa134edaee5893e19c3c76075bef419c09681a67f4ede6f28d747b53afd61ddc937d7de96a22c7db10ad8700cade888de5d6f450c15d796978ddb5e6a52e5044e90247c988686d992105c85f6d198e2de859330f973ded4d7e5d90de57051dbaf0db0febd4cf9d44da155e55293b0930f89c1d21cc227eba9615ca47cce41d16eaddb5bf5dc9bc8477df5cf21f460b83241e7d0fa3707f9d2b322b9aaa42747d0653168b095ca0a83f38426688f6f10143cbd1b84c08583b09ed6192c7366ecc23af528fc2e8c585560f9bd0fcc255b82fc70723a92506bb475ebc1f5ae34a902bf2aa75997ed90a54762c8e83720833b2fd607eee1beb347a75d3bd0f174ed450a72cce79f1be426de9d6f1a6feff052674af141b3cea89f8e749118392e9533c62ddad870e60d509fd7abfa0bc33c2774b29a0170089b30d82047d6e130c49f6965f9871d1928b7f13e3e40ad8e3dc85195f4b312f9f6d8e4158aca23a611f6c6c798983555139942536f6ac59bbd6cc88b9933f22e81429e835bfd4fec27c67520d64a0ad8fd7feb6a3fbe52dc56cbbf59644b0fad0c462ed02ffbf7258e4b94bdedefb187fbdb729a0d56a36e876ac76de766eed416f39ab4e8b1982b8d0a87cd33182ae81ecf1d1d5202cc3e82c5762646d15db5f13cde3e81c83715195f9af9f27e01e1829ce529fa0f715db1f5d227bb201c7c127ea8d0e9c21739c7e9c6a0d8d5a1aaea5216c549f3715f889e583555ac1bfd77339f3eff1bee75ee2fc45457f5c3ffe9401b8b67f5bb3f305f3269fe6153ba34de3fa90016c76811cd54b4b49b17b244b1a4f6edfa2eaf46e2819aded26005b4ed712e8b700ae7b6123fa2c179640ee523f864360d116ee243f13c66d2cd61d422709648d905ab17edf0d0075d2fed443889e15344069b69b2d3d8273f197f8468baf167074bf6dfdeea5871f0c0652ab2801f394ef6fbf841e8072c8bf65026d85d441ca61e78785a2e7ca1e743640fecd6dfad8b77adcbb8bcb8ce8532ad0cd8b3e51269c26ad037545273f756c1a5511925408a5045af469ca947f9a3f5457bcc325d05291a192abe75b4da7c97a61adc2fa247984edb5a03285f1c3b99f13f6a22f007029faffdd38b62f7bf909ce602e4e06ab1ec4543013d354d0dd86d8933a53c17ead02faf0cc740d7191fe475be2f7940c234f8c73420774a7213fd2a477847527172c02a54928de5fde5f15616760e6f7ff3c03a233aec880a939d9f1ca68be7f474fd13184fe8f6deb0c4ea01617ea207d5d765d067fddba58b94f3b59d5996e9f5434f483e2f0079c48050f3ba941b589294c41a0f350451d566fe58a9c9688cc3a75da314ff4b3473eeac58664c5922ae4efae850fe0f7f11dcc089bc0b4df9a64547a35b2559f4a4a3e7d3782d850997baa589534921becde8dc3f76380ae36bd9730956aae9f59b121d8ae4dbbc586c6b45ad9d5c17cf6821b746177bc9fcb727db3f4aa190688c48826421de5ebcd429e0d9b479e66e676e8f9a3b4bd92621f47357a7b1b27942121f5a6e0087e4192a5f8cf4da942cc9d86eac5e", context: "some context info", plaintext: "08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d879de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f27088d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b0707e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51addd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb751fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e488acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b50d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380db2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0", }, } for _, tv := range testvectors { t.Run(tv.name, func(t *testing.T) { key, err := hex.DecodeString(tv.key) if err != nil { t.Fatalf("error decoding test vector key :%s", err) } ct, err := hex.DecodeString(tv.ciphertext) if err != nil { t.Fatalf("error decoding test vector ciphertext :%s", err) } ctx := []byte(tv.context) pt := []byte(tv.plaintext) curve, err := subtle.GetCurve("NIST_P256") if err != nil { t.Fatalf("subtle.GetCurve() err = %q, want nil", err) } pvt := subtle.GetECPrivateKey(curve, key) var salt []byte helper, err := newRegisterECIESAEADHKDFDemHelper(daead.AESSIVKeyTemplate()) if err != nil { t.Fatalf("error generating a DEM helper :%s", err) } d, err := subtle.NewECIESAEADHKDFHybridDecrypt(pvt, salt, "SHA256", "UNCOMPRESSED", helper) if err != nil { t.Fatalf("error generating an decryption construct :%s", err) } dt, err := d.Decrypt(ct, ctx) if err != nil { t.Fatalf("decryption error :%s", err) } if !bytes.Equal(dt, pt) { t.Errorf("Decryption did not match test vector's plaintext") } }) } } ================================================ FILE: go/hybrid/ecies_aead_hkdf_hybrid_encrypt_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hybrid import ( "bytes" "testing" "github.com/google/tink/go/aead" "github.com/google/tink/go/daead" "github.com/google/tink/go/hybrid/subtle" "github.com/google/tink/go/subtle/random" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func basicMultipleEncrypts(t *testing.T, c string, k *tinkpb.KeyTemplate) { t.Helper() curve, err := subtle.GetCurve(c) if err != nil { t.Fatalf("error getting %s curve: %s ", c, err) } pvt, err := subtle.GenerateECDHKeyPair(curve) if err != nil { t.Fatalf("error generating ECDH key pair: %s", err) } salt := []byte("some salt") pt := random.GetRandomBytes(20) context := []byte("context info") rDem, err := newRegisterECIESAEADHKDFDemHelper(k) if err != nil { t.Fatalf("error generating a DEM helper :%s", err) } e, err := subtle.NewECIESAEADHKDFHybridEncrypt(&pvt.PublicKey, salt, "SHA256", "UNCOMPRESSED", rDem) if err != nil { t.Fatalf("error generating an encryption construct :%s", err) } d, err := subtle.NewECIESAEADHKDFHybridDecrypt(pvt, salt, "SHA256", "UNCOMPRESSED", rDem) if err != nil { t.Fatalf("error generating an decryption construct :%s", err) } cl := [][]byte{} for i := 0; i < 8; i++ { ct, err := e.Encrypt(pt, context) if err != nil { t.Fatalf("encryption error :%s", err) } for _, c := range cl { if bytes.Equal(ct, c) { t.Fatalf("encryption is not randomized") } } cl = append(cl, ct) dt, err := d.Decrypt(ct, context) if err != nil { t.Fatalf("decryption error :%s", err) } if !bytes.Equal(dt, pt) { t.Fatalf("decryption not inverse of encryption") } } if len(cl) != 8 { t.Errorf("randomized encryption check failed") } } func TestECAESCTRHMACSHA256Encrypt(t *testing.T) { basicMultipleEncrypts(t, "NIST_P256", aead.AES256CTRHMACSHA256KeyTemplate()) basicMultipleEncrypts(t, "NIST_P384", aead.AES256CTRHMACSHA256KeyTemplate()) basicMultipleEncrypts(t, "NIST_P521", aead.AES256CTRHMACSHA256KeyTemplate()) basicMultipleEncrypts(t, "NIST_P224", aead.AES256CTRHMACSHA256KeyTemplate()) basicMultipleEncrypts(t, "NIST_P256", aead.AES128CTRHMACSHA256KeyTemplate()) basicMultipleEncrypts(t, "NIST_P384", aead.AES128CTRHMACSHA256KeyTemplate()) basicMultipleEncrypts(t, "NIST_P521", aead.AES128CTRHMACSHA256KeyTemplate()) basicMultipleEncrypts(t, "NIST_P224", aead.AES128CTRHMACSHA256KeyTemplate()) } func TestECAES256GCMEncrypt(t *testing.T) { basicMultipleEncrypts(t, "NIST_P256", aead.AES256GCMKeyTemplate()) basicMultipleEncrypts(t, "NIST_P384", aead.AES256GCMKeyTemplate()) basicMultipleEncrypts(t, "NIST_P521", aead.AES256GCMKeyTemplate()) basicMultipleEncrypts(t, "NIST_P224", aead.AES256GCMKeyTemplate()) basicMultipleEncrypts(t, "NIST_P256", aead.AES128GCMKeyTemplate()) basicMultipleEncrypts(t, "NIST_P384", aead.AES128GCMKeyTemplate()) basicMultipleEncrypts(t, "NIST_P521", aead.AES128GCMKeyTemplate()) basicMultipleEncrypts(t, "NIST_P224", aead.AES128GCMKeyTemplate()) } func TestECAESSIVEncrypt(t *testing.T) { basicMultipleEncrypts(t, "NIST_P256", daead.AESSIVKeyTemplate()) basicMultipleEncrypts(t, "NIST_P384", daead.AESSIVKeyTemplate()) basicMultipleEncrypts(t, "NIST_P521", daead.AESSIVKeyTemplate()) basicMultipleEncrypts(t, "NIST_P224", daead.AESSIVKeyTemplate()) } ================================================ FILE: go/hybrid/ecies_aead_hkdf_private_key_manager.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hybrid import ( "errors" "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/hybrid/subtle" "github.com/google/tink/go/keyset" commonpb "github.com/google/tink/go/proto/common_go_proto" eahpb "github.com/google/tink/go/proto/ecies_aead_hkdf_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( eciesAEADHKDFPrivateKeyKeyVersion = 0 eciesAEADHKDFPrivateKeyTypeURL = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey" ) // common errors var errInvalidECIESAEADHKDFPrivateKeyKey = fmt.Errorf("ecies_aead_hkdf_private_key_manager: invalid key") var errInvalidECIESAEADHKDFPrivateKeyKeyFormat = fmt.Errorf("ecies_aead_hkdf_private_key_manager: invalid key format") // eciesAEADHKDFPrivateKeyKeyManager is an implementation of PrivateKeyManager interface. // It generates new ECIESAEADHKDFPrivateKeyKey keys and produces new instances of ECIESAEADHKDFPrivateKey subtle. type eciesAEADHKDFPrivateKeyKeyManager struct{} // Assert that eciesAEADHKDFPrivateKeyKeyManager implements the PrivateKeyManager interface. var _ registry.PrivateKeyManager = (*eciesAEADHKDFPrivateKeyKeyManager)(nil) // Primitive creates an ECIESAEADHKDFPrivateKey subtle for the given serialized ECIESAEADHKDFPrivateKey proto. func (km *eciesAEADHKDFPrivateKeyKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidECIESAEADHKDFPrivateKeyKey } key := new(eahpb.EciesAeadHkdfPrivateKey) if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errInvalidECIESAEADHKDFPrivateKeyKey } if err := km.validateKey(key); err != nil { return nil, errInvalidECIESAEADHKDFPrivateKeyKey } params := key.GetPublicKey().GetParams() curve, err := subtle.GetCurve(params.GetKemParams().GetCurveType().String()) if err != nil { return nil, err } pvt := subtle.GetECPrivateKey(curve, key.GetKeyValue()) rDem, err := newRegisterECIESAEADHKDFDemHelper(params.GetDemParams().GetAeadDem()) if err != nil { return nil, err } salt := params.GetKemParams().GetHkdfSalt() hash := params.GetKemParams().GetHkdfHashType().String() pointFormat := params.GetEcPointFormat().String() return subtle.NewECIESAEADHKDFHybridDecrypt(pvt, salt, hash, pointFormat, rDem) } // NewKey creates a new key according to specification the given serialized ECIESAEADHKDFPrivateKeyKeyFormat. func (km *eciesAEADHKDFPrivateKeyKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errInvalidECIESAEADHKDFPrivateKeyKeyFormat } keyFormat := new(eahpb.EciesAeadHkdfKeyFormat) if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, errInvalidECIESAEADHKDFPrivateKeyKeyFormat } if err := km.validateKeyFormat(keyFormat); err != nil { return nil, errInvalidECIESAEADHKDFPrivateKeyKeyFormat } params := keyFormat.GetParams() curve, err := subtle.GetCurve(params.GetKemParams().GetCurveType().String()) if err != nil { return nil, err } pvt, err := subtle.GenerateECDHKeyPair(curve) if err != nil { return nil, err } return &eahpb.EciesAeadHkdfPrivateKey{ Version: eciesAEADHKDFPrivateKeyKeyVersion, KeyValue: pvt.D.Bytes(), PublicKey: &eahpb.EciesAeadHkdfPublicKey{ Version: eciesAEADHKDFPrivateKeyKeyVersion, Params: keyFormat.Params, X: pvt.PublicKey.Point.X.Bytes(), Y: pvt.PublicKey.Point.Y.Bytes(), }, }, nil } // NewKeyData creates a new KeyData according to specification in the given serialized // ECIESAEADHKDFPrivateKeyKeyFormat. // It should be used solely by the key management API. func (km *eciesAEADHKDFPrivateKeyKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { key, err := km.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: eciesAEADHKDFPrivateKeyTypeURL, Value: serializedKey, KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PRIVATE, }, nil } func (km *eciesAEADHKDFPrivateKeyKeyManager) PublicKeyData(serializedPrivKey []byte) (*tinkpb.KeyData, error) { privKey := new(eahpb.EciesAeadHkdfPrivateKey) if err := proto.Unmarshal(serializedPrivKey, privKey); err != nil { return nil, errInvalidECIESAEADHKDFPrivateKeyKey } serializedPubKey, err := proto.Marshal(privKey.GetPublicKey()) if err != nil { return nil, errInvalidECIESAEADHKDFPrivateKeyKey } return &tinkpb.KeyData{ TypeUrl: eciesAEADHKDFPublicKeyTypeURL, Value: serializedPubKey, KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC, }, nil } // DoesSupport indicates if this key manager supports the given key type. func (km *eciesAEADHKDFPrivateKeyKeyManager) DoesSupport(typeURL string) bool { return typeURL == eciesAEADHKDFPrivateKeyTypeURL } // TypeURL returns the key type of keys managed by this key manager. func (km *eciesAEADHKDFPrivateKeyKeyManager) TypeURL() string { return eciesAEADHKDFPrivateKeyTypeURL } // validateKey validates the given ECDSAPrivateKey. func (km *eciesAEADHKDFPrivateKeyKeyManager) validateKey(key *eahpb.EciesAeadHkdfPrivateKey) error { if err := keyset.ValidateKeyVersion(key.GetVersion(), eciesAEADHKDFPrivateKeyKeyVersion); err != nil { return fmt.Errorf("ecies_aead_hkdf_private_key_manager: invalid key: %s", err) } return checkECIESAEADHKDFParams(key.GetPublicKey().GetParams()) } // validateKeyFormat validates the given ECDSAKeyFormat. func (km *eciesAEADHKDFPrivateKeyKeyManager) validateKeyFormat(format *eahpb.EciesAeadHkdfKeyFormat) error { return checkECIESAEADHKDFParams(format.Params) } func checkECIESAEADHKDFParams(params *eahpb.EciesAeadHkdfParams) error { _, err := subtle.GetCurve(params.GetKemParams().GetCurveType().String()) if err != nil { return err } if params.GetKemParams().GetHkdfHashType() == commonpb.HashType_UNKNOWN_HASH { return errors.New("hash unsupported for HMAC") } if params.EcPointFormat == commonpb.EcPointFormat_UNKNOWN_FORMAT { return errors.New("unknown EC point format") } km, err := registry.GetKeyManager(params.GetDemParams().GetAeadDem().GetTypeUrl()) if err != nil { return err } _, err = km.NewKeyData(params.GetDemParams().GetAeadDem().GetValue()) if err != nil { return err } return nil } ================================================ FILE: go/hybrid/ecies_aead_hkdf_private_key_manager_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hybrid_test import ( "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/aead" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/hybrid/subtle" commonpb "github.com/google/tink/go/proto/common_go_proto" eahpb "github.com/google/tink/go/proto/ecies_aead_hkdf_go_proto" ) func TestECIESAEADHKDFPrivateKeyManagerPrimitive(t *testing.T) { km, err := registry.GetKeyManager(eciesAEADHKDFPrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", eciesAEADHKDFPrivateKeyTypeURL, err) } serializedPrivateKey := mustMarshal(t, makeValidECIESAEADHKDFPrivateKey(t)) primitive, err := km.Primitive(serializedPrivateKey) if err != nil { t.Fatalf("km.Primitive(serilizedPrivateKey) err = %v, want nil", err) } if _, ok := primitive.(*subtle.ECIESAEADHKDFHybridDecrypt); !ok { t.Errorf("primitive is not ECIESAEADHKDFHybridDecrypt") } } func TestECIESAEADHKDFPrivateKeyManagerPrimitiveErrors(t *testing.T) { km, err := registry.GetKeyManager(eciesAEADHKDFPrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", eciesAEADHKDFPrivateKeyTypeURL, err) } testCases := []struct { name string key []byte }{ { name: "nil_key", key: nil, }, { name: "invalid_version", key: func() []byte { k := makeValidECIESAEADHKDFPrivateKey(t) k.Version = eciesAEADHKDFPrivateKeyKeyVersion + 1 return mustMarshal(t, k) }(), }, { name: "nil_public_key", key: func() []byte { k := makeValidECIESAEADHKDFPrivateKey(t) k.PublicKey = nil return mustMarshal(t, k) }(), }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { if _, err := km.Primitive(tc.key); err == nil { t.Fatalf("km.Primitive(serilizedPrivateKey) err = nil, want non-nil") } }) } } func TestECIESAEADHKDFPrivateKeyManagerNewKey(t *testing.T) { km, err := registry.GetKeyManager(eciesAEADHKDFPrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", eciesAEADHKDFPrivateKeyTypeURL, err) } serializedKeyFormat := mustMarshal(t, makeValidECIESAEADHKDFKeyFormat(t)) if _, err := km.NewKey(serializedKeyFormat); err != nil { t.Errorf("km.NewKey(serializedKeyFormat) err = %v, want nil", err) } if _, err := km.NewKeyData(serializedKeyFormat); err != nil { t.Errorf("km.NewKeyData(serializedKeyFormat) err = %v, want nil", err) } } func TestECIESAEADHKDFPrivateKeyManagerNewKeyErrors(t *testing.T) { km, err := registry.GetKeyManager(eciesAEADHKDFPrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", eciesAEADHKDFPrivateKeyTypeURL, err) } testCases := []struct { name string keyFormat []byte }{ { name: "nil_keyFormat", keyFormat: nil, }, { name: "nil_params", keyFormat: func() []byte { kf := makeValidECIESAEADHKDFKeyFormat(t) kf.Params = nil return mustMarshal(t, kf) }(), }, { name: "nil_kem_params", keyFormat: func() []byte { kf := makeValidECIESAEADHKDFKeyFormat(t) kf.GetParams().KemParams = nil return mustMarshal(t, kf) }(), }, { name: "nil_dem_params", keyFormat: func() []byte { kf := makeValidECIESAEADHKDFKeyFormat(t) kf.GetParams().DemParams = nil return mustMarshal(t, kf) }(), }, { name: "unknown_kem_curve_type", keyFormat: func() []byte { kf := makeValidECIESAEADHKDFKeyFormat(t) kf.GetParams().GetKemParams().CurveType = commonpb.EllipticCurveType_UNKNOWN_CURVE return mustMarshal(t, kf) }(), }, { name: "unknown_kem_hash_type", keyFormat: func() []byte { kf := makeValidECIESAEADHKDFKeyFormat(t) kf.GetParams().GetKemParams().HkdfHashType = commonpb.HashType_UNKNOWN_HASH return mustMarshal(t, kf) }(), }, { name: "nil_dem_aead", keyFormat: func() []byte { kf := makeValidECIESAEADHKDFKeyFormat(t) kf.GetParams().GetDemParams().AeadDem = nil return mustMarshal(t, kf) }(), }, { name: "unknown_point_format", keyFormat: func() []byte { kf := makeValidECIESAEADHKDFKeyFormat(t) kf.GetParams().EcPointFormat = commonpb.EcPointFormat_UNKNOWN_FORMAT return mustMarshal(t, kf) }(), }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { if _, err := km.NewKey(tc.keyFormat); err == nil { t.Errorf("km.NewKey(tc.keyFormat) err == nil, want non-nil") } if _, err := km.NewKeyData(tc.keyFormat); err == nil { t.Errorf("km.NewKeyData(tc.keyFormat) err == nil, want non-nil") } }) } } func makeValidECIESAEADHKDFKeyFormat(t *testing.T) *eahpb.EciesAeadHkdfKeyFormat { t.Helper() return &eahpb.EciesAeadHkdfKeyFormat{ Params: &eahpb.EciesAeadHkdfParams{ KemParams: &eahpb.EciesHkdfKemParams{ CurveType: commonpb.EllipticCurveType_NIST_P256, HkdfHashType: commonpb.HashType_SHA256, HkdfSalt: []byte{}, }, DemParams: &eahpb.EciesAeadDemParams{ AeadDem: aead.AES128GCMKeyTemplate(), }, EcPointFormat: commonpb.EcPointFormat_UNCOMPRESSED, }, } } func makeValidECIESAEADHKDFPrivateKey(t *testing.T) *eahpb.EciesAeadHkdfPrivateKey { t.Helper() keyFormat := makeValidECIESAEADHKDFKeyFormat(t) curve, err := subtle.GetCurve(keyFormat.GetParams().GetKemParams().GetCurveType().String()) if err != nil { t.Fatal(err) } privateKey, err := subtle.GenerateECDHKeyPair(curve) if err != nil { t.Fatal(err) } return &eahpb.EciesAeadHkdfPrivateKey{ Version: eciesAEADHKDFPrivateKeyKeyVersion, KeyValue: privateKey.D.Bytes(), PublicKey: &eahpb.EciesAeadHkdfPublicKey{ Version: 0, Params: keyFormat.GetParams(), X: privateKey.PublicKey.Point.X.Bytes(), Y: privateKey.PublicKey.Point.Y.Bytes(), }, } } func mustMarshal(t *testing.T, msg proto.Message) []byte { t.Helper() serialized, err := proto.Marshal(msg) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", msg, err) } return serialized } ================================================ FILE: go/hybrid/ecies_aead_hkdf_public_key_manager.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hybrid import ( "errors" "fmt" "math/big" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/hybrid/subtle" "github.com/google/tink/go/keyset" eahpb "github.com/google/tink/go/proto/ecies_aead_hkdf_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( eciesAEADHKDFPublicKeyKeyVersion = 0 eciesAEADHKDFPublicKeyTypeURL = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPublicKey" ) // common errors var errInvalidECIESAEADHKDFPublicKeyKey = fmt.Errorf("ecies_aead_hkdf_public_key_manager: invalid key") var errInvalidECIESAEADHKDFPublicKeyKeyFormat = fmt.Errorf("ecies_aead_hkdf_public_key_manager: invalid key format") // eciesAEADHKDFPublicKeyKeyManager is an implementation of KeyManager interface. // It generates new ECIESAEADHKDFPublicKeyKey keys and produces new instances of ECIESAEADHKDFPublicKey subtle. type eciesAEADHKDFPublicKeyKeyManager struct{} // Assert that eciesAEADHKDFPublicKeyKeyManager implements the KeyManager interface. var _ registry.KeyManager = (*eciesAEADHKDFPublicKeyKeyManager)(nil) // Primitive creates an ECIESAEADHKDFPublicKey subtle for the given serialized ECIESAEADHKDFPublicKey proto. func (km *eciesAEADHKDFPublicKeyKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidECIESAEADHKDFPublicKeyKey } key := new(eahpb.EciesAeadHkdfPublicKey) if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errInvalidECIESAEADHKDFPublicKeyKey } if err := km.validateKey(key); err != nil { return nil, errInvalidECIESAEADHKDFPublicKeyKey } params := key.GetParams() curve, err := subtle.GetCurve(params.GetKemParams().GetCurveType().String()) if err != nil { return nil, err } pub := subtle.ECPublicKey{ Curve: curve, Point: subtle.ECPoint{ X: new(big.Int).SetBytes(key.GetX()), Y: new(big.Int).SetBytes(key.GetY()), }, } rDem, err := newRegisterECIESAEADHKDFDemHelper(params.GetDemParams().GetAeadDem()) if err != nil { return nil, err } salt := params.GetKemParams().GetHkdfSalt() hash := params.GetKemParams().GetHkdfHashType().String() pointFormat := params.GetEcPointFormat().String() return subtle.NewECIESAEADHKDFHybridEncrypt(&pub, salt, hash, pointFormat, rDem) } // DoesSupport indicates if this key manager supports the given key type. func (km *eciesAEADHKDFPublicKeyKeyManager) DoesSupport(typeURL string) bool { return typeURL == eciesAEADHKDFPublicKeyTypeURL } // TypeURL returns the key type of keys managed by this key manager. func (km *eciesAEADHKDFPublicKeyKeyManager) TypeURL() string { return eciesAEADHKDFPublicKeyTypeURL } // validateKey validates the given ECDSAPrivateKey. func (km *eciesAEADHKDFPublicKeyKeyManager) validateKey(key *eahpb.EciesAeadHkdfPublicKey) error { if err := keyset.ValidateKeyVersion(key.GetVersion(), eciesAEADHKDFPublicKeyKeyVersion); err != nil { return fmt.Errorf("ecies_aead_hkdf_public_key_manager: invalid key: %s", err) } return checkECIESAEADHKDFParams(key.Params) } // NewKey is not implemented for public key manager. func (km *eciesAEADHKDFPublicKeyKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { return nil, errors.New("public key manager does not implement NewKey") } // NewKeyData is not implemented for public key manager. func (km *eciesAEADHKDFPublicKeyKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { return nil, errors.New("public key manager does not implement NewKeyData") } ================================================ FILE: go/hybrid/ecies_aead_hkdf_public_key_manager_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hybrid_test import ( "testing" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/hybrid/subtle" commonpb "github.com/google/tink/go/proto/common_go_proto" eahpb "github.com/google/tink/go/proto/ecies_aead_hkdf_go_proto" ) func TestECIESAEADHKDFPublicKeyManagerPrimitive(t *testing.T) { km, err := registry.GetKeyManager(eciesAEADHKDFPublicKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", eciesAEADHKDFPrivateKeyTypeURL, err) } serializedPublicKey := mustMarshal(t, makeValidECIESAEADHKDFPublicKey(t)) primitive, err := km.Primitive(serializedPublicKey) if err != nil { t.Fatalf("km.Primitive(serilizedPublicKey) err = %v, want nil", err) } if _, ok := primitive.(*subtle.ECIESAEADHKDFHybridEncrypt); !ok { t.Errorf("primitive is not ECIESAEADHKDFHybridEncrypt") } } func TestECIESAEADHKDFPublicKeyManagerPrimitiveErrors(t *testing.T) { km, err := registry.GetKeyManager(eciesAEADHKDFPublicKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", eciesAEADHKDFPrivateKeyTypeURL, err) } testCases := []struct { name string key []byte }{ { name: "nil_key", key: nil, }, { name: "invalid_version", key: func() []byte { k := makeValidECIESAEADHKDFPublicKey(t) k.Version = eciesAEADHKDFPublicKeyKeyVersion + 1 return mustMarshal(t, k) }(), }, { name: "nil_params", key: func() []byte { k := makeValidECIESAEADHKDFPublicKey(t) k.Params = nil return mustMarshal(t, k) }(), }, { name: "nil_kem_params", key: func() []byte { k := makeValidECIESAEADHKDFPublicKey(t) k.GetParams().KemParams = nil return mustMarshal(t, k) }(), }, { name: "nil_dem_params", key: func() []byte { k := makeValidECIESAEADHKDFPublicKey(t) k.GetParams().DemParams = nil return mustMarshal(t, k) }(), }, { name: "unknown_kem_curve_type", key: func() []byte { k := makeValidECIESAEADHKDFPublicKey(t) k.GetParams().GetKemParams().CurveType = commonpb.EllipticCurveType_UNKNOWN_CURVE return mustMarshal(t, k) }(), }, { name: "unknown_kem_hash_type", key: func() []byte { k := makeValidECIESAEADHKDFPublicKey(t) k.GetParams().GetKemParams().HkdfHashType = commonpb.HashType_UNKNOWN_HASH return mustMarshal(t, k) }(), }, { name: "nil_dem_aead", key: func() []byte { k := makeValidECIESAEADHKDFPublicKey(t) k.GetParams().GetDemParams().AeadDem = nil return mustMarshal(t, k) }(), }, { name: "unknown_point_format", key: func() []byte { k := makeValidECIESAEADHKDFPublicKey(t) k.GetParams().EcPointFormat = commonpb.EcPointFormat_UNKNOWN_FORMAT return mustMarshal(t, k) }(), }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { if _, err := km.Primitive(tc.key); err == nil { t.Fatalf("km.Primitive(serilizedPublicKey) err = nil, want non-nil") } }) } } func makeValidECIESAEADHKDFPublicKey(t *testing.T) *eahpb.EciesAeadHkdfPublicKey { t.Helper() privateKey := makeValidECIESAEADHKDFPrivateKey(t) return privateKey.GetPublicKey() } ================================================ FILE: go/hybrid/ecies_aead_hkdf_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hybrid_test const ( eciesAEADHKDFPrivateKeyKeyVersion = 0 eciesAEADHKDFPrivateKeyTypeURL = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey" eciesAEADHKDFPublicKeyKeyVersion = 0 eciesAEADHKDFPublicKeyTypeURL = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPublicKey" ) ================================================ FILE: go/hybrid/hpke_private_key_manager.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hybrid import ( "errors" "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/hybrid/internal/hpke" "github.com/google/tink/go/keyset" "github.com/google/tink/go/subtle" hpkepb "github.com/google/tink/go/proto/hpke_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( // maxSupportedHPKEPrivateKeyVersion is the max supported private key // version. It must be incremented when support for new versions are // implemented. maxSupportedHPKEPrivateKeyVersion uint32 = 0 hpkePrivateKeyTypeURL = "type.googleapis.com/google.crypto.tink.HpkePrivateKey" ) var ( errInvalidHPKEPrivateKey = errors.New("invalid HPKE private key") errInvalidHPKEPrivateKeyFormat = errors.New("invalid HPKE private key format") ) // hpkePrivateKeyManager implements the KeyManager interface for HybridDecrypt. type hpkePrivateKeyManager struct{} var _ registry.PrivateKeyManager = (*hpkePrivateKeyManager)(nil) func (p *hpkePrivateKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidHPKEPrivateKey } key := new(hpkepb.HpkePrivateKey) if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errInvalidHPKEPrivateKey } if err := keyset.ValidateKeyVersion(key.GetVersion(), maxSupportedHPKEPrivateKeyVersion); err != nil { return nil, err } return hpke.NewDecrypt(key) } // NewKey returns a set of private and public keys of key version 0. func (p *hpkePrivateKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errInvalidHPKEPrivateKeyFormat } keyFormat := new(hpkepb.HpkeKeyFormat) if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, errInvalidHPKEPrivateKeyFormat } if err := validateKeyFormat(keyFormat); err != nil { return nil, err } privKeyBytes, err := subtle.GeneratePrivateKeyX25519() if err != nil { return nil, fmt.Errorf("generate X25519 private key: %v", err) } pubKeyBytes, err := subtle.PublicFromPrivateX25519(privKeyBytes) if err != nil { return nil, fmt.Errorf("get X25519 public key from private key: %v", err) } return &hpkepb.HpkePrivateKey{ Version: 0, PublicKey: &hpkepb.HpkePublicKey{ Version: 0, Params: keyFormat.GetParams(), PublicKey: pubKeyBytes, }, PrivateKey: privKeyBytes, }, nil } func (p *hpkePrivateKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { key, err := p.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: hpkePrivateKeyTypeURL, Value: serializedKey, KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PRIVATE, }, nil } func (p *hpkePrivateKeyManager) PublicKeyData(serializedPrivKey []byte) (*tinkpb.KeyData, error) { privKey := new(hpkepb.HpkePrivateKey) if err := proto.Unmarshal(serializedPrivKey, privKey); err != nil { return nil, errInvalidHPKEPrivateKey } serializedPubKey, err := proto.Marshal(privKey.GetPublicKey()) if err != nil { return nil, errInvalidHPKEPrivateKey } return &tinkpb.KeyData{ TypeUrl: hpkePublicKeyTypeURL, Value: serializedPubKey, KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC, }, nil } func (p *hpkePrivateKeyManager) DoesSupport(typeURL string) bool { return typeURL == hpkePrivateKeyTypeURL } func (p *hpkePrivateKeyManager) TypeURL() string { return hpkePrivateKeyTypeURL } func validateKeyFormat(kf *hpkepb.HpkeKeyFormat) error { params := kf.GetParams() kem, kdf, aead := params.GetKem(), params.GetKdf(), params.GetAead() if kem != hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256 || kdf != hpkepb.HpkeKdf_HKDF_SHA256 || (aead != hpkepb.HpkeAead_AES_128_GCM && aead != hpkepb.HpkeAead_AES_256_GCM && aead != hpkepb.HpkeAead_CHACHA20_POLY1305) { return errInvalidHPKEPrivateKeyFormat } return nil } ================================================ FILE: go/hybrid/hpke_private_key_manager_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hybrid import ( "bytes" "testing" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/testing/protocmp" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/hybrid/internal/hpke" "github.com/google/tink/go/subtle/random" hpkepb "github.com/google/tink/go/proto/hpke_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestPrivateKeyManagerPrimitiveRejectsInvalidKeyVersion(t *testing.T) { km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err) } params := &hpkepb.HpkeParams{ Kem: hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256, Kdf: hpkepb.HpkeKdf_HKDF_SHA256, Aead: hpkepb.HpkeAead_AES_256_GCM, } _, privKey := pubPrivKeys(t, params) privKey.Version = 1 serializedPrivKey, err := proto.Marshal(privKey) if err != nil { t.Fatal(err) } if _, err := km.Primitive(serializedPrivKey); err == nil { t.Error("Primitive() err = nil, want error") } } func TestPrivateKeyManagerPrimitiveRejectsInvalidParams(t *testing.T) { km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err) } tests := []struct { name string params *hpkepb.HpkeParams }{ { name: "invalid_kem", params: &hpkepb.HpkeParams{ Kem: hpkepb.HpkeKem_KEM_UNKNOWN, Kdf: hpkepb.HpkeKdf_HKDF_SHA256, Aead: hpkepb.HpkeAead_AES_256_GCM, }, }, { name: "invalid_kdf", params: &hpkepb.HpkeParams{ Kem: hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256, Kdf: hpkepb.HpkeKdf_KDF_UNKNOWN, Aead: hpkepb.HpkeAead_AES_256_GCM, }, }, { name: "invalid_aead", params: &hpkepb.HpkeParams{ Kem: hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256, Kdf: hpkepb.HpkeKdf_HKDF_SHA256, Aead: hpkepb.HpkeAead_AEAD_UNKNOWN, }, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { _, serializedPrivKey := serializedPubPrivKeys(t, test.params) if _, err := km.Primitive(serializedPrivKey); err == nil { t.Error("Primitive() err = nil, want error") } }) } } func TestPrivateKeyManagerPrimitiveRejectsMissingParams(t *testing.T) { km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err) } _, serializedPrivKey := serializedPubPrivKeys(t, nil) if _, err := km.Primitive(serializedPrivKey); err == nil { t.Error("Primitive() err = nil, want error") } } func TestPrivateKeyManagerPrimitiveRejectsNilKey(t *testing.T) { km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err) } if _, err := km.Primitive(nil); err == nil { t.Error("Primitive() err = nil, want error") } } func TestPrivateKeyManagerPrimitiveEncryptDecrypt(t *testing.T) { km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err) } pt := random.GetRandomBytes(200) ctxInfo := random.GetRandomBytes(100) for _, aeadID := range hpkeAEADs { params := &hpkepb.HpkeParams{ Kem: hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256, Kdf: hpkepb.HpkeKdf_HKDF_SHA256, Aead: aeadID, } pubKey, privKey := pubPrivKeys(t, params) serializedPrivKey, err := proto.Marshal(privKey) if err != nil { t.Fatal(err) } enc, err := hpke.NewEncrypt(pubKey) if err != nil { t.Fatalf("hpke.NewEncrypt() err = %v, want nil", err) } d, err := km.Primitive(serializedPrivKey) if err != nil { t.Fatalf("Primitive() err = %v, want nil", err) } dec, ok := d.(*hpke.Decrypt) if !ok { t.Fatal("primitive is not Decrypt") } ct, err := enc.Encrypt(pt, ctxInfo) if err != nil { t.Fatalf("Encrypt() err = %v, want nil", err) } gotPT, err := dec.Decrypt(ct, ctxInfo) if err != nil { t.Fatalf("Decrypt() err = %v, want nil", err) } if want := pt; !bytes.Equal(gotPT, want) { t.Errorf("Decrypt() = %x, want %x", gotPT, want) } } } func TestPrivateKeyManagerNewKeyRejectsNilKeyFormat(t *testing.T) { km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err) } if _, err := km.NewKey(nil); err == nil { t.Error("NewKey() err = nil, want error") } } func TestPrivateKeyManagerNewKeyRejectsInvalidKeyFormat(t *testing.T) { km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err) } serializedKeyFormatUnknownKEM, err := proto.Marshal( &hpkepb.HpkeParams{ Kem: hpkepb.HpkeKem_KEM_UNKNOWN, Kdf: hpkepb.HpkeKdf_HKDF_SHA256, Aead: hpkepb.HpkeAead_AES_256_GCM, }) if err != nil { t.Fatal(err) } serializedKeyFormatUnknownKDF, err := proto.Marshal( &hpkepb.HpkeParams{ Kem: hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256, Kdf: hpkepb.HpkeKdf_KDF_UNKNOWN, Aead: hpkepb.HpkeAead_AES_256_GCM, }) if err != nil { t.Fatal(err) } serializedKeyFormatUnknownAEAD, err := proto.Marshal( &hpkepb.HpkeParams{ Kem: hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256, Kdf: hpkepb.HpkeKdf_HKDF_SHA256, Aead: hpkepb.HpkeAead_AEAD_UNKNOWN, }) if err != nil { t.Fatal(err) } tests := []struct { name string keyFormat []byte }{ {"kem", serializedKeyFormatUnknownKEM}, {"kdf", serializedKeyFormatUnknownKDF}, {"aead", serializedKeyFormatUnknownAEAD}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { if _, err := km.NewKey(test.keyFormat); err == nil { t.Error("NewKey() err = nil, want error") } }) } } func TestPrivateKeyManagerNewKeyEncryptDecrypt(t *testing.T) { km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err) } wantPT := random.GetRandomBytes(200) ctxInfo := random.GetRandomBytes(100) for _, aeadID := range hpkeAEADs { keyFormat := &hpkepb.HpkeKeyFormat{ Params: &hpkepb.HpkeParams{ Kem: hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256, Kdf: hpkepb.HpkeKdf_HKDF_SHA256, Aead: aeadID, }, } serializedKeyFormat, err := proto.Marshal(keyFormat) if err != nil { t.Fatal(err) } privKeyProto, err := km.NewKey(serializedKeyFormat) if err != nil { t.Fatalf("NewKey() err = %v, want nil", err) } privKey, ok := privKeyProto.(*hpkepb.HpkePrivateKey) if !ok { t.Fatal("primitive is not HpkePrivateKey") } if privKey.GetVersion() != 0 { t.Errorf("private key version = %d, want %d", privKey.GetVersion(), 0) } if len(privKey.GetPrivateKey()) == 0 { t.Error("private key is missing") } pubKey := privKey.GetPublicKey() if pubKey.GetVersion() != 0 { t.Errorf("public key version = %d, want %d", pubKey.GetVersion(), 0) } if !cmp.Equal(pubKey.GetParams(), keyFormat.GetParams(), protocmp.Transform()) { t.Errorf("key params = %v, want %v", pubKey.GetParams(), keyFormat.GetParams()) } if len(pubKey.GetPublicKey()) == 0 { t.Error("public key is missing") } enc, err := hpke.NewEncrypt(pubKey) if err != nil { t.Fatalf("hpke.NewEncrypt() err = %v, want nil", err) } serializedPrivKey, err := proto.Marshal(privKeyProto) if err != nil { t.Fatal(err) } d, err := km.Primitive(serializedPrivKey) if err != nil { t.Fatalf("Primitive() err = %v, want nil", err) } dec, ok := d.(*hpke.Decrypt) if !ok { t.Fatal("primitive is not Decrypt") } ct, err := enc.Encrypt(wantPT, ctxInfo) if err != nil { t.Fatalf("Encrypt() err = %v, want nil", err) } gotPT, err := dec.Decrypt(ct, ctxInfo) if err != nil { t.Fatalf("Decrypt() err = %v, want nil", err) } if !bytes.Equal(gotPT, wantPT) { t.Errorf("Decrypt() = %x, want %x", gotPT, wantPT) } } } func TestPrivateKeyManagerNewKeyDataRejectsNilKeyFormat(t *testing.T) { km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err) } if _, err := km.NewKeyData(nil); err == nil { t.Error("NewKey() err = nil, want error") } } func TestPrivateKeyManagerNewKeyData(t *testing.T) { km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err) } for _, aeadID := range hpkeAEADs { keyFormat := &hpkepb.HpkeKeyFormat{ Params: &hpkepb.HpkeParams{ Kem: hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256, Kdf: hpkepb.HpkeKdf_HKDF_SHA256, Aead: aeadID, }, } serializedKeyFormat, err := proto.Marshal(keyFormat) if err != nil { t.Fatal(err) } keyData, err := km.NewKeyData(serializedKeyFormat) if err != nil { t.Fatalf("NewKeyData() err = %v, want nil", err) } if got, want := keyData.GetTypeUrl(), hpkePrivateKeyTypeURL; got != want { t.Errorf("type URL = %q, want %q", got, want) } if got, want := keyData.GetKeyMaterialType(), tinkpb.KeyData_ASYMMETRIC_PRIVATE; got != want { t.Errorf("key material type = %d, want %d", got, want) } privKey := new(hpkepb.HpkePrivateKey) if err := proto.Unmarshal(keyData.GetValue(), privKey); err != nil { t.Fatalf("Unmarshal err = %v, want nil", err) } if privKey.GetVersion() != 0 { t.Errorf("private key version = %d, want %d", privKey.GetVersion(), 0) } if len(privKey.GetPrivateKey()) == 0 { t.Error("private key is missing") } pubKey := privKey.GetPublicKey() if pubKey.GetVersion() != 0 { t.Errorf("public key version = %d, want %d", pubKey.GetVersion(), 0) } if !cmp.Equal(pubKey.GetParams(), keyFormat.GetParams(), protocmp.Transform()) { t.Errorf("key params = %v, want %v", pubKey.GetParams(), keyFormat.GetParams()) } if len(pubKey.GetPublicKey()) == 0 { t.Error("public key is missing") } } } func TestPrivateKeyManagerPublicKeyDataAcceptsNilKey(t *testing.T) { k, err := registry.GetKeyManager(hpkePrivateKeyTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err) } km, ok := k.(registry.PrivateKeyManager) if !ok { t.Errorf("primitive is not PrivateKeyManager") } if _, err := km.PublicKeyData(nil); err != nil { t.Errorf("PublicKeyData() err = %v, want nil", err) } } func TestPrivateKeyManagerPublicKeyData(t *testing.T) { k, err := registry.GetKeyManager(hpkePrivateKeyTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err) } km, ok := k.(registry.PrivateKeyManager) if !ok { t.Errorf("primitive is not PrivateKeyManager") } params := &hpkepb.HpkeParams{ Kem: hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256, Kdf: hpkepb.HpkeKdf_HKDF_SHA256, Aead: hpkepb.HpkeAead_AES_256_GCM, } _, privKey := pubPrivKeys(t, params) serializedPrivKey, err := proto.Marshal(privKey) if err != nil { t.Fatal(err) } wantPubKey := privKey.GetPublicKey() serializedPubKey, err := proto.Marshal(wantPubKey) if err != nil { t.Fatal(err) } pubKey, err := km.PublicKeyData(serializedPrivKey) if err != nil { t.Fatalf("PublicKeyData() err = %v, want nil", err) } if got, want := pubKey.GetTypeUrl(), hpkePublicKeyTypeURL; got != want { t.Errorf("type URL = %q, want %q", got, want) } if !bytes.Equal(pubKey.GetValue(), serializedPubKey) { t.Errorf("value = %v, want %v", pubKey.GetValue(), serializedPubKey) } if got, want := pubKey.GetKeyMaterialType(), tinkpb.KeyData_ASYMMETRIC_PUBLIC; got != want { t.Errorf("Key material type = %d, want %d", got, want) } } func TestPrivateKeyManagerDoesSupport(t *testing.T) { km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err) } if !km.DoesSupport(hpkePrivateKeyTypeURL) { t.Errorf("DoesSupport(%q) = false, want true", hpkePrivateKeyTypeURL) } unsupportedKeyTypeURL := "unsupported.key.type" if km.DoesSupport(unsupportedKeyTypeURL) { t.Errorf("DoesSupport(%q) = true, want false", unsupportedKeyTypeURL) } } func TestPrivateKeyManagerTypeURL(t *testing.T) { km, err := registry.GetKeyManager(hpkePrivateKeyTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePrivateKeyTypeURL, err) } if km.TypeURL() != hpkePrivateKeyTypeURL { t.Errorf("TypeURL = %q, want %q", km.TypeURL(), hpkePrivateKeyTypeURL) } } ================================================ FILE: go/hybrid/hpke_public_key_manager.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hybrid import ( "errors" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/hybrid/internal/hpke" "github.com/google/tink/go/keyset" hpkepb "github.com/google/tink/go/proto/hpke_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( // maxSupportedHPKEPublicKeyVersion is the max supported public key version. // It must be incremented when support for new versions are implemented. maxSupportedHPKEPublicKeyVersion = 0 hpkePublicKeyTypeURL = "type.googleapis.com/google.crypto.tink.HpkePublicKey" ) var ( errInvalidHPKEPublicKey = errors.New("invalid HPKE public key") errNotSupportedOnHPKE = errors.New("not supported on HPKE public key manager") ) // hpkePublicKeyManager implements the KeyManager interface for HybridEncrypt. type hpkePublicKeyManager struct{} var _ registry.KeyManager = (*hpkePublicKeyManager)(nil) func (p *hpkePublicKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidHPKEPublicKey } key := new(hpkepb.HpkePublicKey) if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errInvalidHPKEPublicKey } if err := keyset.ValidateKeyVersion(key.GetVersion(), maxSupportedHPKEPublicKeyVersion); err != nil { return nil, err } return hpke.NewEncrypt(key) } func (p *hpkePublicKeyManager) DoesSupport(typeURL string) bool { return typeURL == hpkePublicKeyTypeURL } func (p *hpkePublicKeyManager) TypeURL() string { return hpkePublicKeyTypeURL } func (p *hpkePublicKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { return nil, errNotSupportedOnHPKE } func (p *hpkePublicKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { return nil, errNotSupportedOnHPKE } ================================================ FILE: go/hybrid/hpke_public_key_manager_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hybrid import ( "bytes" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/hybrid/internal/hpke" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/subtle" hpkepb "github.com/google/tink/go/proto/hpke_go_proto" ) var hpkeAEADs = []hpkepb.HpkeAead{ hpkepb.HpkeAead_AES_128_GCM, hpkepb.HpkeAead_AES_256_GCM, hpkepb.HpkeAead_CHACHA20_POLY1305, } func TestPublicKeyManagerPrimitiveRejectsInvalidKeyVersion(t *testing.T) { km, err := registry.GetKeyManager(hpkePublicKeyTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePublicKeyTypeURL, err) } params := &hpkepb.HpkeParams{ Kem: hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256, Kdf: hpkepb.HpkeKdf_HKDF_SHA256, Aead: hpkepb.HpkeAead_AES_256_GCM, } pubKey, _ := pubPrivKeys(t, params) pubKey.Version = 1 serializedPubKey, err := proto.Marshal(pubKey) if err != nil { t.Fatal(err) } if _, err := km.Primitive(serializedPubKey); err == nil { t.Error("Primitive() err = nil, want error") } } func TestPublicKeyManagerPrimitiveRejectsInvalidParams(t *testing.T) { km, err := registry.GetKeyManager(hpkePublicKeyTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePublicKeyTypeURL, err) } tests := []struct { name string params *hpkepb.HpkeParams }{ {"kem", &hpkepb.HpkeParams{ Kem: hpkepb.HpkeKem_KEM_UNKNOWN, Kdf: hpkepb.HpkeKdf_HKDF_SHA256, Aead: hpkepb.HpkeAead_AES_256_GCM, }}, {"kdf", &hpkepb.HpkeParams{ Kem: hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256, Kdf: hpkepb.HpkeKdf_KDF_UNKNOWN, Aead: hpkepb.HpkeAead_AES_256_GCM, }}, {"aead", &hpkepb.HpkeParams{ Kem: hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256, Kdf: hpkepb.HpkeKdf_HKDF_SHA256, Aead: hpkepb.HpkeAead_AEAD_UNKNOWN, }}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { serializedPubKey, _ := serializedPubPrivKeys(t, test.params) if _, err := km.Primitive(serializedPubKey); err == nil { t.Error("Primitive() err = nil, want error") } }) } } func TestPublicKeyManagerPrimitiveRejectsMissingParams(t *testing.T) { km, err := registry.GetKeyManager(hpkePublicKeyTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePublicKeyTypeURL, err) } serializedPubKey, _ := serializedPubPrivKeys(t, nil) if _, err := km.Primitive(serializedPubKey); err == nil { t.Error("Primitive() err = nil, want error") } } func TestPublicKeyManagerPrimitiveRejectsNilKey(t *testing.T) { km, err := registry.GetKeyManager(hpkePublicKeyTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePublicKeyTypeURL, err) } if _, err := km.Primitive(nil); err == nil { t.Error("Primitive() err = nil, want error") } } func TestPublicKeyManagerPrimitiveEncryptDecrypt(t *testing.T) { km, err := registry.GetKeyManager(hpkePublicKeyTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePublicKeyTypeURL, err) } wantPT := random.GetRandomBytes(200) ctxInfo := random.GetRandomBytes(100) for _, aeadID := range hpkeAEADs { params := &hpkepb.HpkeParams{ Kem: hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256, Kdf: hpkepb.HpkeKdf_HKDF_SHA256, Aead: aeadID, } pubKey, privKey := pubPrivKeys(t, params) serializedPubKey, err := proto.Marshal(pubKey) if err != nil { t.Fatal(err) } e, err := km.Primitive(serializedPubKey) if err != nil { t.Fatalf("Primitive() err = %v, want nil", err) } enc, ok := e.(*hpke.Encrypt) if !ok { t.Fatal("primitive is not Encrypt") } dec, err := hpke.NewDecrypt(privKey) if err != nil { t.Fatalf("hpke.NewDecrypt() err = %v, want nil", err) } ct, err := enc.Encrypt(wantPT, ctxInfo) if err != nil { t.Fatalf("Encrypt() err = %v, want nil", err) } gotPT, err := dec.Decrypt(ct, ctxInfo) if err != nil { t.Fatalf("Decrypt() err = %v, want nil", err) } if !bytes.Equal(gotPT, wantPT) { t.Errorf("Decrypt() = %x, want %x", gotPT, wantPT) } } } func TestPublicKeyManagerDoesSupport(t *testing.T) { km, err := registry.GetKeyManager(hpkePublicKeyTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePublicKeyTypeURL, err) } if !km.DoesSupport(hpkePublicKeyTypeURL) { t.Errorf("DoesSupport(%q) = false, want true", hpkePublicKeyTypeURL) } unsupportedKeyTypeURL := "unsupported.key.type" if km.DoesSupport(unsupportedKeyTypeURL) { t.Errorf("DoesSupport(%q) = true, want false", unsupportedKeyTypeURL) } } func TestPublicKeyManagerTypeURL(t *testing.T) { km, err := registry.GetKeyManager(hpkePublicKeyTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePublicKeyTypeURL, err) } if km.TypeURL() != hpkePublicKeyTypeURL { t.Errorf("TypeURL = %q, want %q", km.TypeURL(), hpkePublicKeyTypeURL) } } func TestPublicKeyManagerNotSupported(t *testing.T) { km, err := registry.GetKeyManager(hpkePublicKeyTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", hpkePublicKeyTypeURL, err) } if _, err := km.NewKey(nil); err == nil { t.Error("NewKey(nil) err = nil, want error") } if _, err := km.NewKeyData(nil); err == nil { t.Error("NewKeyData(nil) err = nil, want error") } } func serializedPubPrivKeys(t *testing.T, params *hpkepb.HpkeParams) ([]byte, []byte) { t.Helper() pub, priv := pubPrivKeys(t, params) serializedPub, err := proto.Marshal(pub) if err != nil { t.Fatal(err) } serializedPriv, err := proto.Marshal(priv) if err != nil { t.Fatal(err) } return serializedPub, serializedPriv } func pubPrivKeys(t *testing.T, params *hpkepb.HpkeParams) (*hpkepb.HpkePublicKey, *hpkepb.HpkePrivateKey) { t.Helper() priv, err := subtle.GeneratePrivateKeyX25519() if err != nil { t.Fatalf("GeneratePrivateKeyX25519: err %q", err) } pub, err := subtle.PublicFromPrivateX25519(priv) if err != nil { t.Fatalf("PublicFromPrivateX25519: err %q", err) } pubKey := &hpkepb.HpkePublicKey{ Version: 0, Params: params, PublicKey: pub, } privKey := &hpkepb.HpkePrivateKey{ Version: 0, PublicKey: pubKey, PrivateKey: priv, } return pubKey, privKey } ================================================ FILE: go/hybrid/hybrid.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package hybrid provides implementations of the Hybrid Encryption primitive. // // The functionality of Hybrid Encryption is represented as a pair of // interfaces: // // * HybridEncrypt for encryption of data // * HybridDecrypt for decryption of data // // Implementations of these interfaces are secure against adaptive chosen // ciphertext attacks. In addition to plaintext the encryption takes an extra // parameter contextInfo, which usually is public data implicit from the // context, but should be bound to the resulting ciphertext, i.e. the // ciphertext allows for checking the integrity of contextInfo (but there are // no guarantees wrt. the secrecy or authenticity of contextInfo). package hybrid import ( "fmt" "github.com/google/tink/go/core/registry" ) func init() { if err := registry.RegisterKeyManager(new(hpkePublicKeyManager)); err != nil { panic(fmt.Sprintf("hybrid.init() failed: %v", err)) } if err := registry.RegisterKeyManager(new(hpkePrivateKeyManager)); err != nil { panic(fmt.Sprintf("hybrid.init() failed: %v", err)) } if err := registry.RegisterKeyManager(new(eciesAEADHKDFPrivateKeyKeyManager)); err != nil { panic(fmt.Sprintf("hybrid.init() failed: %v", err)) } if err := registry.RegisterKeyManager(new(eciesAEADHKDFPublicKeyKeyManager)); err != nil { panic(fmt.Sprintf("hybrid.init() failed: %v", err)) } } ================================================ FILE: go/hybrid/hybrid_benchmark_test.go ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hybrid_test import ( "testing" "github.com/google/tink/go/hybrid" "github.com/google/tink/go/keyset" "github.com/google/tink/go/subtle/random" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // Benchmarks for Hybrid Encryption algorithms. const benchmarkPlaintextSize = 1 * 1024 const benchmarkContextInfoSize = 256 var benchmarkTestCases = []struct { name string template *tinkpb.KeyTemplate }{ { name: "HPKE_X25519_AES128GCM", template: hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Key_Template(), }, { name: "HPKE_X25519_Chacha20Poly1305", template: hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Key_Template(), }, { name: "ECIES_P256_AES128GCM", template: hybrid.ECIESHKDFAES128GCMKeyTemplate(), }, { name: "ECIES_P256_AES128CTRHMAC", template: hybrid.ECIESHKDFAES128CTRHMACSHA256KeyTemplate(), }, { name: "ECIES_P384_AES128GCM", template: eciesP384AES256GCMKeyTemplate(), }, { name: "ECIES_P521_AES128GCM", template: eciesP521AES256GCMKeyTemplate(), }, { name: "ECIES_P256_AESSIV", template: eciesP256AESSIVKeyTemplate(), }, } func BenchmarkEncrypt(b *testing.B) { for _, tc := range benchmarkTestCases { b.Run(tc.name, func(b *testing.B) { b.ReportAllocs() privHandle, err := keyset.NewHandle(tc.template) if err != nil { b.Fatal(err) } pubHandle, err := privHandle.Public() if err != nil { b.Fatal(err) } primitive, err := hybrid.NewHybridEncrypt(pubHandle) if err != nil { b.Fatal(err) } plaintext := random.GetRandomBytes(benchmarkPlaintextSize) contextInfo := random.GetRandomBytes(benchmarkContextInfoSize) b.ResetTimer() for i := 0; i < b.N; i++ { _, err = primitive.Encrypt(plaintext, contextInfo) if err != nil { b.Fatal(err) } } }) } } func BenchmarkDecrypt(b *testing.B) { for _, tc := range benchmarkTestCases { b.Run(tc.name, func(b *testing.B) { b.ReportAllocs() privHandle, err := keyset.NewHandle(tc.template) if err != nil { b.Fatal(err) } pubHandle, err := privHandle.Public() if err != nil { b.Fatal(err) } plaintext := random.GetRandomBytes(benchmarkPlaintextSize) contextInfo := random.GetRandomBytes(benchmarkContextInfoSize) encrypter, err := hybrid.NewHybridEncrypt(pubHandle) if err != nil { b.Fatal(err) } ciphertext, err := encrypter.Encrypt(plaintext, contextInfo) if err != nil { b.Fatal(err) } primitive, err := hybrid.NewHybridDecrypt(privHandle) if err != nil { b.Fatal(err) } b.ResetTimer() for i := 0; i < b.N; i++ { _, err = primitive.Decrypt(ciphertext, contextInfo) if err != nil { b.Fatal(err) } } }) } } ================================================ FILE: go/hybrid/hybrid_decrypt_factory.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hybrid import ( "fmt" "github.com/google/tink/go/core/cryptofmt" "github.com/google/tink/go/core/primitiveset" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/internal/monitoringutil" "github.com/google/tink/go/keyset" "github.com/google/tink/go/monitoring" "github.com/google/tink/go/tink" ) // NewHybridDecrypt returns an HybridDecrypt primitive from the given keyset handle. func NewHybridDecrypt(handle *keyset.Handle) (tink.HybridDecrypt, error) { ps, err := handle.Primitives() if err != nil { return nil, fmt.Errorf("hybrid_factory: cannot obtain primitive set: %s", err) } return newWrappedHybridDecrypt(ps) } // wrappedHybridDecrypt is an HybridDecrypt implementation that uses the underlying primitive set // for decryption. type wrappedHybridDecrypt struct { ps *primitiveset.PrimitiveSet logger monitoring.Logger } // compile time assertion that wrappedHybridDecrypt implements the HybridDecrypt interface. var _ tink.HybridDecrypt = (*wrappedHybridDecrypt)(nil) func newWrappedHybridDecrypt(ps *primitiveset.PrimitiveSet) (*wrappedHybridDecrypt, error) { if err := isHybridDecrypt(ps.Primary.Primitive); err != nil { return nil, err } for _, primitives := range ps.Entries { for _, p := range primitives { if err := isHybridDecrypt(p.Primitive); err != nil { return nil, err } } } logger, err := createDecryptLogger(ps) if err != nil { return nil, err } return &wrappedHybridDecrypt{ ps: ps, logger: logger, }, nil } func createDecryptLogger(ps *primitiveset.PrimitiveSet) (monitoring.Logger, error) { if len(ps.Annotations) == 0 { return &monitoringutil.DoNothingLogger{}, nil } keysetInfo, err := monitoringutil.KeysetInfoFromPrimitiveSet(ps) if err != nil { return nil, err } return internalregistry.GetMonitoringClient().NewLogger(&monitoring.Context{ KeysetInfo: keysetInfo, Primitive: "hybrid_decrypt", APIFunction: "decrypt", }) } // Decrypt decrypts the given ciphertext, verifying the integrity of contextInfo. // It returns the corresponding plaintext if the ciphertext is authenticated. func (a *wrappedHybridDecrypt) Decrypt(ciphertext, contextInfo []byte) ([]byte, error) { // try non-raw keys prefixSize := cryptofmt.NonRawPrefixSize if len(ciphertext) > prefixSize { prefix := ciphertext[:prefixSize] ctNoPrefix := ciphertext[prefixSize:] entries, err := a.ps.EntriesForPrefix(string(prefix)) if err == nil { for i := 0; i < len(entries); i++ { p := entries[i].Primitive.(tink.HybridDecrypt) // verified in newWrappedHybridDecrypt pt, err := p.Decrypt(ctNoPrefix, contextInfo) if err == nil { a.logger.Log(entries[i].KeyID, len(ctNoPrefix)) return pt, nil } } } } // try raw keys entries, err := a.ps.RawEntries() if err == nil { for i := 0; i < len(entries); i++ { p := entries[i].Primitive.(tink.HybridDecrypt) // verified in newWrappedHybridDecrypt pt, err := p.Decrypt(ciphertext, contextInfo) if err == nil { a.logger.Log(entries[i].KeyID, len(ciphertext)) return pt, nil } } } // nothing worked a.logger.LogFailure() return nil, fmt.Errorf("hybrid_factory: decryption failed") } // Asserts `p` implements tink.HybridDecrypt and not tink.AEAD. The latter check // is required as implementations of tink.AEAD also satisfy tink.HybridDecrypt. func isHybridDecrypt(p any) error { if _, ok := p.(tink.AEAD); ok { return fmt.Errorf("hybrid_factory: tink.AEAD is not tink.HybridDecrypt") } if _, ok := p.(tink.HybridDecrypt); !ok { return fmt.Errorf("hybrid_factory: not tink.HybridDecrypt") } return nil } ================================================ FILE: go/hybrid/hybrid_encrypt_factory.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hybrid import ( "fmt" "github.com/google/tink/go/core/primitiveset" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/internal/monitoringutil" "github.com/google/tink/go/keyset" "github.com/google/tink/go/monitoring" "github.com/google/tink/go/tink" ) // NewHybridEncrypt returns an HybridEncrypt primitive from the given keyset handle. func NewHybridEncrypt(handle *keyset.Handle) (tink.HybridEncrypt, error) { ps, err := handle.Primitives() if err != nil { return nil, fmt.Errorf("hybrid_factory: cannot obtain primitive set: %s", err) } return newEncryptPrimitiveSet(ps) } // encryptPrimitiveSet is an HybridEncrypt implementation that uses the underlying primitive set for encryption. type wrappedHybridEncrypt struct { ps *primitiveset.PrimitiveSet logger monitoring.Logger } // compile time assertion that wrappedHybridEncrypt implements the HybridEncrypt interface. var _ tink.HybridEncrypt = (*wrappedHybridEncrypt)(nil) func newEncryptPrimitiveSet(ps *primitiveset.PrimitiveSet) (*wrappedHybridEncrypt, error) { if err := isHybridEncrypt(ps.Primary.Primitive); err != nil { return nil, err } for _, primitives := range ps.Entries { for _, p := range primitives { if err := isHybridEncrypt(p.Primitive); err != nil { return nil, err } } } logger, err := createEncryptLogger(ps) if err != nil { return nil, err } return &wrappedHybridEncrypt{ ps: ps, logger: logger, }, nil } func createEncryptLogger(ps *primitiveset.PrimitiveSet) (monitoring.Logger, error) { if len(ps.Annotations) == 0 { return &monitoringutil.DoNothingLogger{}, nil } keysetInfo, err := monitoringutil.KeysetInfoFromPrimitiveSet(ps) if err != nil { return nil, err } return internalregistry.GetMonitoringClient().NewLogger(&monitoring.Context{ KeysetInfo: keysetInfo, Primitive: "hybrid_encrypt", APIFunction: "encrypt", }) } // Encrypt encrypts the given plaintext binding contextInfo to the resulting ciphertext. // It returns the concatenation of the primary's identifier and the ciphertext. func (a *wrappedHybridEncrypt) Encrypt(plaintext, contextInfo []byte) ([]byte, error) { primary := a.ps.Primary p := primary.Primitive.(tink.HybridEncrypt) // verified in newEncryptPrimitiveSet ct, err := p.Encrypt(plaintext, contextInfo) if err != nil { a.logger.LogFailure() return nil, err } a.logger.Log(primary.KeyID, len(plaintext)) if len(primary.Prefix) == 0 { return ct, nil } output := make([]byte, 0, len(primary.Prefix)+len(ct)) output = append(output, primary.Prefix...) output = append(output, ct...) return output, nil } // Asserts `p` implements tink.HybridEncrypt and not tink.AEAD. The latter check // is required as implementations of tink.AEAD also satisfy tink.HybridEncrypt. func isHybridEncrypt(p any) error { if _, ok := p.(tink.AEAD); ok { return fmt.Errorf("hybrid_factory: tink.AEAD is not tink.HybridEncrypt") } if _, ok := p.(tink.HybridEncrypt); !ok { return fmt.Errorf("hybrid_factory: not tink.HybridEncrypt") } return nil } ================================================ FILE: go/hybrid/hybrid_factory_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hybrid_test import ( "bytes" "testing" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "google.golang.org/protobuf/proto" "github.com/google/tink/go/aead" "github.com/google/tink/go/core/cryptofmt" "github.com/google/tink/go/hybrid" "github.com/google/tink/go/insecurecleartextkeyset" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/keyset" "github.com/google/tink/go/monitoring" "github.com/google/tink/go/signature" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testing/fakemonitoring" "github.com/google/tink/go/testkeyset" "github.com/google/tink/go/testutil" commonpb "github.com/google/tink/go/proto/common_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestHybridFactoryTest(t *testing.T) { c := commonpb.EllipticCurveType_NIST_P256 ht := commonpb.HashType_SHA256 primaryPtFmt := commonpb.EcPointFormat_UNCOMPRESSED rawPtFmt := commonpb.EcPointFormat_COMPRESSED primaryDek := aead.AES128CTRHMACSHA256KeyTemplate() rawDek := aead.AES128CTRHMACSHA256KeyTemplate() primarySalt := []byte("some salt") rawSalt := []byte("other salt") primaryPrivProto, err := testutil.GenerateECIESAEADHKDFPrivateKey(c, ht, primaryPtFmt, primaryDek, primarySalt) if err != nil { t.Fatalf("testutil.GenerateECIESAEADHKDFPrivateKey(c, ht, primaryPtFmt, primaryDek, primarySalt) err = %v, want nil", err) } sPrimaryPriv, err := proto.Marshal(primaryPrivProto) if err != nil { t.Fatalf("proto.Marshal(primaryPrivProto) err = %v, want nil", err) } primaryPrivKey := testutil.NewKey( testutil.NewKeyData(eciesAEADHKDFPrivateKeyTypeURL, sPrimaryPriv, tinkpb.KeyData_ASYMMETRIC_PRIVATE), tinkpb.KeyStatusType_ENABLED, 8, tinkpb.OutputPrefixType_RAW) rawPrivProto, err := testutil.GenerateECIESAEADHKDFPrivateKey(c, ht, rawPtFmt, rawDek, rawSalt) if err != nil { t.Fatalf("testutil.GenerateECIESAEADHKDFPrivateKey(c, ht, rawPtFmt, rawDek, rawSalt) err = %v, want nil", err) } sRawPriv, err := proto.Marshal(rawPrivProto) if err != nil { t.Fatalf("proto.Marshal(rawPrivProto) err = %v, want nil", err) } rawPrivKey := testutil.NewKey( testutil.NewKeyData(eciesAEADHKDFPrivateKeyTypeURL, sRawPriv, tinkpb.KeyData_ASYMMETRIC_PRIVATE), tinkpb.KeyStatusType_ENABLED, 11, tinkpb.OutputPrefixType_RAW) privKeys := []*tinkpb.Keyset_Key{primaryPrivKey, rawPrivKey} privKeyset := testutil.NewKeyset(privKeys[0].KeyId, privKeys) khPriv, err := testkeyset.NewHandle(privKeyset) if err != nil { t.Fatalf("testkeyset.NewHandle(privKeyset) err = %v, want nil", err) } khPub, err := khPriv.Public() if err != nil { t.Fatalf("khPriv.Public() err = %v, want nil", err) } e, err := hybrid.NewHybridEncrypt(khPub) if err != nil { t.Fatalf("hybrid.NewHybridEncrypt(khPub) err = %v, want nil", err) } d, err := hybrid.NewHybridDecrypt(khPriv) if err != nil { t.Fatalf("hybrid.NewHybridDecrypt(khPriv) err = %v, want nil", err) } for i := 0; i < 1000; i++ { pt := random.GetRandomBytes(20) ci := random.GetRandomBytes(20) ct, err := e.Encrypt(pt, ci) if err != nil { t.Fatalf("e.Encrypt(pt, ci) err = %v, want nil", err) } gotpt, err := d.Decrypt(ct, ci) if err != nil { t.Fatalf("d.Decrypt(ct, ci) err = %v, want nil", err) } if !bytes.Equal(pt, gotpt) { t.Errorf("got plaintext %q, want %q", gotpt, pt) } } } func TestFactoryWithInvalidPrimitiveSetType(t *testing.T) { wrongKH, err := keyset.NewHandle(signature.ECDSAP256KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle(signature.ECDSAP256KeyTemplate()) err = %v, want nil", err) } _, err = hybrid.NewHybridEncrypt(wrongKH) if err == nil { t.Error("hybrid.NewHybridEncrypt(wrongKH) err = nil, want not nil") } _, err = hybrid.NewHybridDecrypt(wrongKH) if err == nil { t.Error("hybrid.NewHybridDecrypt(wrongKH) err = nil, want not nil") } } func TestFactoryWithValidPrimitiveSetType(t *testing.T) { goodKH, err := keyset.NewHandle(hybrid.ECIESHKDFAES128GCMKeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle(hybrid.ECIESHKDFAES128GCMKeyTemplate()) err = %v, want nil", err) } goodPublicKH, err := goodKH.Public() if err != nil { t.Fatalf("goodKH.Public() err = %v, want nil", err) } _, err = hybrid.NewHybridEncrypt(goodPublicKH) if err != nil { t.Errorf("hybrid.NewHybridEncrypt(goodPublicKH) err = %v, want nil", err) } _, err = hybrid.NewHybridDecrypt(goodKH) if err != nil { t.Errorf("hybrid.NewHybridDecrypt(goodKH) err = %v, want nil", err) } } func TestPrimitiveFactoryFailsWhenKeysetHasNoPrimary(t *testing.T) { curve := commonpb.EllipticCurveType_NIST_P256 hash := commonpb.HashType_SHA256 format := commonpb.EcPointFormat_UNCOMPRESSED dek := aead.AES128CTRHMACSHA256KeyTemplate() salt := []byte("some salt") privProto, err := testutil.GenerateECIESAEADHKDFPrivateKey(curve, hash, format, dek, salt) if err != nil { t.Fatalf("testutil.GenerateECIESAEADHKDFPrivateKey(curve, hash, format, dek, salt) failed: %s", err) } serialized, err := proto.Marshal(privProto) if err != nil { t.Fatalf("proto.Marshal(privateProto) err = %v, want nil", err) } privKey := testutil.NewKey( testutil.NewKeyData(eciesAEADHKDFPrivateKeyTypeURL, serialized, tinkpb.KeyData_ASYMMETRIC_PRIVATE), tinkpb.KeyStatusType_ENABLED, 8, tinkpb.OutputPrefixType_RAW) privKeysetWithoutPrimary := &tinkpb.Keyset{ Key: []*tinkpb.Keyset_Key{privKey}, } privHandleWithoutPrimary, err := testkeyset.NewHandle(privKeysetWithoutPrimary) if err != nil { t.Fatalf("testkeyset.NewHandle(privKeysetWithoutPrimary) err = %v, want nil", err) } pubHandleWithoutPrimary, err := privHandleWithoutPrimary.Public() if err != nil { t.Fatalf("privateHandleWithoutPrimary.Public() err = %v, want nil", err) } if _, err = hybrid.NewHybridEncrypt(pubHandleWithoutPrimary); err == nil { t.Errorf("NewHybridEncrypt(pubHandleWithoutPrimary) err = nil, want not nil") } if _, err = hybrid.NewHybridDecrypt(privHandleWithoutPrimary); err == nil { t.Errorf("NewHybridDecrypt(privHandleWithoutPrimary) err = nil, want not nil") } } func TestPrimitiveFactoryMonitoringWithAnnotationsLogsEncryptAndDecryptWithPrefix(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("registry.RegisterMonitoringClient() err = %v, want nil", err) } handle, err := keyset.NewHandle(hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Key_Template()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(handle, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} privHandle, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } pubHandle, err := privHandle.Public() if err != nil { t.Fatalf("privHandle.Public() err = %v, want nil", err) } buff.Reset() if err := insecurecleartextkeyset.Write(pubHandle, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } pubHandle, err = insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } e, err := hybrid.NewHybridEncrypt(pubHandle) if err != nil { t.Fatalf("hybrid.NewHybridEncrypt() err = %v, want nil", err) } d, err := hybrid.NewHybridDecrypt(privHandle) if err != nil { t.Fatalf("hybrid.NewHybridDecrypt() err = %v, want nil", err) } data := []byte("some_secret_piece_of_data") aad := []byte("some_non_secret_piece_of_data") ct, err := e.Encrypt(data, aad) if err != nil { t.Fatalf("e.Encrypt() err = %v, want nil", err) } if _, err := d.Decrypt(ct, aad); err != nil { t.Fatalf("d.Decrypt() err = %v, want nil", err) } got := client.Events() wantEncryptKeysetInfo := &monitoring.KeysetInfo{ Annotations: annotations, PrimaryKeyID: privHandle.KeysetInfo().GetPrimaryKeyId(), Entries: []*monitoring.Entry{ { KeyID: pubHandle.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.HpkePublicKey", KeyPrefix: "TINK", }, }, } wantDecryptKeysetInfo := &monitoring.KeysetInfo{ Annotations: annotations, PrimaryKeyID: privHandle.KeysetInfo().GetPrimaryKeyId(), Entries: []*monitoring.Entry{ { KeyID: privHandle.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.HpkePrivateKey", KeyPrefix: "TINK", }, }, } want := []*fakemonitoring.LogEvent{ { Context: monitoring.NewContext("hybrid_encrypt", "encrypt", wantEncryptKeysetInfo), KeyID: privHandle.KeysetInfo().GetPrimaryKeyId(), NumBytes: len(data), }, { Context: monitoring.NewContext("hybrid_decrypt", "decrypt", wantDecryptKeysetInfo), KeyID: privHandle.KeysetInfo().GetPrimaryKeyId(), // ciphertext was encrypted with a key that has a TINK output prefix. This adds a // 5-byte prefix to the ciphertext. This prefix is not included in the `Log` call. NumBytes: len(ct) - cryptofmt.NonRawPrefixSize, }, } if diff := cmp.Diff(want, got); diff != "" { t.Errorf("%v", diff) } } func TestPrimitiveFactoryMonitoringWithAnnotationsLogsEncryptAndDecryptWithoutPrefix(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("registry.RegisterMonitoringClient() err = %v, want nil", err) } handle, err := keyset.NewHandle(hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Raw_Key_Template()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(handle, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} privHandle, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } pubHandle, err := privHandle.Public() if err != nil { t.Fatalf("privHandle.Public() err = %v, want nil", err) } buff.Reset() if err := insecurecleartextkeyset.Write(pubHandle, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } pubHandle, err = insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } e, err := hybrid.NewHybridEncrypt(pubHandle) if err != nil { t.Fatalf("hybrid.NewHybridEncrypt() err = %v, want nil", err) } d, err := hybrid.NewHybridDecrypt(privHandle) if err != nil { t.Fatalf("hybrid.NewHybridDecrypt() err = %v, want nil", err) } data := []byte("some_secret_piece_of_data") aad := []byte("some_non_secret_piece_of_data") ct, err := e.Encrypt(data, aad) if err != nil { t.Fatalf("e.Encrypt() err = %v, want nil", err) } if _, err := d.Decrypt(ct, aad); err != nil { t.Fatalf("d.Decrypt() err = %v, want nil", err) } got := client.Events() wantEncryptKeysetInfo := &monitoring.KeysetInfo{ Annotations: annotations, PrimaryKeyID: privHandle.KeysetInfo().GetPrimaryKeyId(), Entries: []*monitoring.Entry{ { KeyID: pubHandle.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.HpkePublicKey", KeyPrefix: "RAW", }, }, } wantDecryptKeysetInfo := &monitoring.KeysetInfo{ Annotations: annotations, PrimaryKeyID: privHandle.KeysetInfo().GetPrimaryKeyId(), Entries: []*monitoring.Entry{ { KeyID: privHandle.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.HpkePrivateKey", KeyPrefix: "RAW", }, }, } want := []*fakemonitoring.LogEvent{ { Context: monitoring.NewContext("hybrid_encrypt", "encrypt", wantEncryptKeysetInfo), KeyID: pubHandle.KeysetInfo().GetPrimaryKeyId(), NumBytes: len(data), }, { Context: monitoring.NewContext("hybrid_decrypt", "decrypt", wantDecryptKeysetInfo), KeyID: privHandle.KeysetInfo().GetPrimaryKeyId(), NumBytes: len(ct), }, } if diff := cmp.Diff(want, got); diff != "" { t.Errorf("%v", diff) } } func TestPrimitiveFactoryWithMonitoringWithMultipleKeysLogsEncryptionDecryption(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } manager := keyset.NewManager() templates := []*tinkpb.KeyTemplate{ hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Key_Template(), hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM_Raw_Key_Template(), hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Key_Template(), hybrid.ECIESHKDFAES128GCMKeyTemplate(), } keyIDs := make([]uint32, 4, 4) var err error for i, tm := range templates { keyIDs[i], err = manager.Add(tm) if err != nil { t.Fatalf("manager.Add() err = %v, want nil", err) } } if err := manager.SetPrimary(keyIDs[1]); err != nil { t.Fatalf("manager.SetPrimary(%d) err = %v, want nil", keyIDs[1], err) } if err := manager.Disable(keyIDs[0]); err != nil { t.Fatalf("manager.Disable(%d) err = %v, want nil", keyIDs[0], err) } handle, err := manager.Handle() if err != nil { t.Fatalf("manager.Handle() err = %v, want nil", err) } buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(handle, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} privHandle, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } pubHandle, err := privHandle.Public() if err != nil { t.Fatalf("privHandle.Public() err = %v, want nil", err) } buff.Reset() if err := insecurecleartextkeyset.Write(pubHandle, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } pubHandle, err = insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } e, err := hybrid.NewHybridEncrypt(pubHandle) if err != nil { t.Fatalf("hybrid.NewHybridEncrypt() err = %v, want nil", err) } d, err := hybrid.NewHybridDecrypt(privHandle) if err != nil { t.Fatalf("hybrid.NewHybridDecrypt() err = %v, want nil", err) } data := []byte("some_secret_piece_of_data") aad := []byte("some_non_secret_piece_of_data") ct, err := e.Encrypt(data, aad) if err != nil { t.Fatalf("e.Encrypt() err = %v, want nil", err) } if _, err := d.Decrypt(ct, aad); err != nil { t.Fatalf("d.Decrypt() err = %v, want nil", err) } failures := len(client.Failures()) if failures != 0 { t.Errorf("len(client.Failures()) = %d, want 0", failures) } got := client.Events() wantEncryptKeysetInfo := &monitoring.KeysetInfo{ Annotations: annotations, PrimaryKeyID: privHandle.KeysetInfo().GetPrimaryKeyId(), Entries: []*monitoring.Entry{ { KeyID: pubHandle.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.HpkePublicKey", KeyPrefix: "RAW", }, { KeyID: keyIDs[2], Status: monitoring.Enabled, KeyType: "tink.HpkePublicKey", KeyPrefix: "TINK", }, { KeyID: keyIDs[3], Status: monitoring.Enabled, KeyType: "tink.EciesAeadHkdfPublicKey", KeyPrefix: "TINK", }, }, } wantDecryptKeysetInfo := &monitoring.KeysetInfo{ Annotations: annotations, PrimaryKeyID: privHandle.KeysetInfo().GetPrimaryKeyId(), Entries: []*monitoring.Entry{ { KeyID: privHandle.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.HpkePrivateKey", KeyPrefix: "RAW", }, { KeyID: keyIDs[2], Status: monitoring.Enabled, KeyType: "tink.HpkePrivateKey", KeyPrefix: "TINK", }, { KeyID: keyIDs[3], Status: monitoring.Enabled, KeyType: "tink.EciesAeadHkdfPrivateKey", KeyPrefix: "TINK", }, }, } want := []*fakemonitoring.LogEvent{ { Context: monitoring.NewContext("hybrid_encrypt", "encrypt", wantEncryptKeysetInfo), KeyID: privHandle.KeysetInfo().GetPrimaryKeyId(), NumBytes: len(data), }, { Context: monitoring.NewContext("hybrid_decrypt", "decrypt", wantDecryptKeysetInfo), KeyID: privHandle.KeysetInfo().GetPrimaryKeyId(), NumBytes: len(ct), }, } // sort by keyID to avoid non deterministic order. entryLessFunc := func(a, b *monitoring.Entry) bool { return a.KeyID < b.KeyID } if diff := cmp.Diff(want, got, cmpopts.SortSlices(entryLessFunc)); diff != "" { t.Errorf("%v", diff) } } func TestPrimitiveFactoryMonitoringWithAnnotationsEncryptFailureIsLogged(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } handle, err := keyset.NewHandle(hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Key_Template()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(handle, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} privHandle, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } buff.Reset() pubHandle, err := privHandle.Public() if err != nil { t.Fatalf("privHandle.Public() err = %v, want nil", err) } if err := insecurecleartextkeyset.Write(pubHandle, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } pubHandle, err = insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } e, err := hybrid.NewHybridEncrypt(pubHandle) if err != nil { t.Fatalf("NewHybridEncrypt() err = %v, want nil", err) } d, err := hybrid.NewHybridDecrypt(privHandle) if err != nil { t.Fatalf("NewHybridDecrypt() err = %v, want nil", err) } ct, err := e.Encrypt([]byte("plaintext"), []byte("info")) if err != nil { t.Fatalf("Encrypt() err = nil, want non-nil") } if _, err := d.Decrypt(ct, []byte("wrong info")); err == nil { t.Fatalf("Decrypt() err = nil, want non-nil") } got := client.Failures() primaryKeyID := privHandle.KeysetInfo().GetPrimaryKeyId() want := []*fakemonitoring.LogFailure{ { Context: monitoring.NewContext( "hybrid_decrypt", "decrypt", monitoring.NewKeysetInfo( annotations, primaryKeyID, []*monitoring.Entry{ { KeyID: primaryKeyID, Status: monitoring.Enabled, KeyType: "tink.HpkePrivateKey", KeyPrefix: "TINK", }, }, ), ), }, } if diff := cmp.Diff(want, got); diff != "" { t.Errorf("%v", diff) } } func TestPrimitiveFactoryMonitoringWithAnnotationsDecryptFailureIsLogged(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("registry.RegisterMonitoringClient() err = %v, want nil", err) } handle, err := keyset.NewHandle(hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Key_Template()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(handle, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} privHandle, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } e, err := hybrid.NewHybridDecrypt(privHandle) if err != nil { t.Fatalf("hybrid.NewHybridDecrypt() err = %v, want nil", err) } if _, err := e.Decrypt([]byte("invalid_data"), nil); err == nil { t.Fatalf("e.Decrypt() err = nil, want non-nil error") } got := client.Failures() want := []*fakemonitoring.LogFailure{ { Context: monitoring.NewContext( "hybrid_decrypt", "decrypt", monitoring.NewKeysetInfo( annotations, privHandle.KeysetInfo().GetPrimaryKeyId(), []*monitoring.Entry{ { KeyID: privHandle.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.HpkePrivateKey", KeyPrefix: "TINK", }, }, ), ), }, } if diff := cmp.Diff(want, got); diff != "" { t.Errorf("%v", diff) } } func TestPrimitiveFactoryEncryptDecryptWithoutAnnotationsDoesNotMonitor(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("registry.RegisterMonitoringClient() err = %v, want nil", err) } privHandle, err := keyset.NewHandle(hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Key_Template()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } pubHandle, err := privHandle.Public() if err != nil { t.Fatalf("privHandle.Public() err = %v, want nil", err) } e, err := hybrid.NewHybridEncrypt(pubHandle) if err != nil { t.Fatalf("hybrid.NewHybridEncrypt() err = %v, want nil", err) } d, err := hybrid.NewHybridDecrypt(privHandle) if err != nil { t.Fatalf("hybrid.NewHybridDecrypt() err = %v, want nil", err) } data := []byte("some_secret_piece_of_data") aad := []byte("some_non_secret_piece_of_data") ct, err := e.Encrypt(data, aad) if err != nil { t.Fatalf("e.Encrypt() err = %v, want nil", err) } if _, err := d.Decrypt(ct, aad); err != nil { t.Fatalf("d.Decrypt() err = %v, want nil", err) } if len(client.Events()) != 0 { t.Errorf("len(client.Events()) = %d, want 0", len(client.Events())) } if len(client.Failures()) != 0 { t.Errorf("len(client.Failures()) = %d, want 0", len(client.Failures())) } } // Since the HybridEncrypt interface is a subset of the AEAD interface, verify // that a HybridEncrypt primitive cannot be obtained from a keyset handle // containing an AEAD key. func TestEncryptFactoryFailsOnAEADHandle(t *testing.T) { handle, err := keyset.NewHandle(hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Key_Template()) if err != nil { t.Fatalf("keyset.NewHandle gives err = '%v', want nil", err) } pub, err := handle.Public() if err != nil { t.Fatalf("handle.Public gives err = '%v', want nil", err) } manager := keyset.NewManagerFromHandle(pub) _, err = manager.Add(aead.AES128GCMKeyTemplate()) if err != nil { t.Fatalf("manager.Add gives err = '%v', want nil", err) } mixedHandle, err := manager.Handle() if err != nil { t.Fatalf("manager.Handle gives err = '%v', want nil", err) } if _, err := hybrid.NewHybridEncrypt(mixedHandle); err == nil { t.Error("hybrid.NewHybridDecrypt err = nil, want err") } } // Similar to the above but for HybridDecrypt. func TestDecryptFactoryFailsOnAEADHandle(t *testing.T) { manager := keyset.NewManager() id, err := manager.Add(aead.AES256GCMKeyTemplate()) if err != nil { t.Fatalf("manager.Add gives err = '%v', want nil", err) } err = manager.SetPrimary(id) if err != nil { t.Fatalf("manager.SetPrimary gives err = '%v', want nil", err) } _, err = manager.Add(hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Key_Template()) if err != nil { t.Fatalf("manager.Add gives err = '%v', want nil", err) } handle, err := manager.Handle() if err != nil { t.Fatalf("manager.Handle gives err = '%v', want nil", err) } if _, err := hybrid.NewHybridDecrypt(handle); err == nil { t.Error("hybrid.NewHybridDecrypt err = nil, want err") } } ================================================ FILE: go/hybrid/hybrid_key_templates.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hybrid import ( "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/aead" "github.com/google/tink/go/internal/tinkerror" commonpb "github.com/google/tink/go/proto/common_go_proto" eciespb "github.com/google/tink/go/proto/ecies_aead_hkdf_go_proto" hpkepb "github.com/google/tink/go/proto/hpke_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // This file contains pre-generated KeyTemplates for HybridEncrypt keys. One // can use these templates to generate new Keysets. // DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Key_Template creates a HPKE // key template with: // - KEM: DHKEM_X25519_HKDF_SHA256, // - KDF: HKDF_SHA256, and // - AEAD: AES_128_GCM. // // It adds the 5-byte Tink prefix to ciphertexts. func DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Key_Template() *tinkpb.KeyTemplate { return createHPKEKeyTemplate( hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256, hpkepb.HpkeKdf_HKDF_SHA256, hpkepb.HpkeAead_AES_128_GCM, tinkpb.OutputPrefixType_TINK, ) } // DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Raw_Key_Template creates a // HPKE key template with: // - KEM: DHKEM_X25519_HKDF_SHA256, // - KDF: HKDF_SHA256, and // - AEAD: AES_128_GCM. // // It does not add a prefix to ciphertexts. func DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Raw_Key_Template() *tinkpb.KeyTemplate { return createHPKEKeyTemplate( hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256, hpkepb.HpkeKdf_HKDF_SHA256, hpkepb.HpkeAead_AES_128_GCM, tinkpb.OutputPrefixType_RAW, ) } // DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM_Key_Template creates a HPKE // key template with: // - KEM: DHKEM_X25519_HKDF_SHA256, // - KDF: HKDF_SHA256, and // - AEAD: AES_256_GCM. // // It adds the 5-byte Tink prefix to ciphertexts. func DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM_Key_Template() *tinkpb.KeyTemplate { return createHPKEKeyTemplate( hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256, hpkepb.HpkeKdf_HKDF_SHA256, hpkepb.HpkeAead_AES_256_GCM, tinkpb.OutputPrefixType_TINK, ) } // DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM_Raw_Key_Template creates a // HPKE key template with: // - KEM: DHKEM_X25519_HKDF_SHA256, // - KDF: HKDF_SHA256, and // - AEAD: AES_256_GCM. // // It does not add a prefix to ciphertexts. func DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM_Raw_Key_Template() *tinkpb.KeyTemplate { return createHPKEKeyTemplate( hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256, hpkepb.HpkeKdf_HKDF_SHA256, hpkepb.HpkeAead_AES_256_GCM, tinkpb.OutputPrefixType_RAW, ) } // DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Key_Template creates // a HPKE key template with: // - KEM: DHKEM_X25519_HKDF_SHA256, // - KDF: HKDF_SHA256, and // - AEAD: CHACHA20_POLY1305. // // It adds the 5-byte Tink prefix to ciphertexts. func DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Key_Template() *tinkpb.KeyTemplate { return createHPKEKeyTemplate( hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256, hpkepb.HpkeKdf_HKDF_SHA256, hpkepb.HpkeAead_CHACHA20_POLY1305, tinkpb.OutputPrefixType_TINK, ) } // DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Raw_Key_Template creates // a HPKE key template with: // - KEM: DHKEM_X25519_HKDF_SHA256, // - KDF: HKDF_SHA256, and // - AEAD: CHACHA20_POLY1305. // // It does not add a prefix to ciphertexts. func DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Raw_Key_Template() *tinkpb.KeyTemplate { return createHPKEKeyTemplate( hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256, hpkepb.HpkeKdf_HKDF_SHA256, hpkepb.HpkeAead_CHACHA20_POLY1305, tinkpb.OutputPrefixType_RAW, ) } // createHPKEKeyTemplate creates a new HPKE key template with the given // parameters. func createHPKEKeyTemplate(kem hpkepb.HpkeKem, kdf hpkepb.HpkeKdf, aead hpkepb.HpkeAead, outputPrefixType tinkpb.OutputPrefixType) *tinkpb.KeyTemplate { format := &hpkepb.HpkeKeyFormat{ Params: &hpkepb.HpkeParams{ Kem: kem, Kdf: kdf, Aead: aead, }, } serializedFormat, err := proto.Marshal(format) if err != nil { tinkerror.Fail(fmt.Sprintf("failed to marshal key format: %s", err)) } return &tinkpb.KeyTemplate{ TypeUrl: hpkePrivateKeyTypeURL, Value: serializedFormat, OutputPrefixType: outputPrefixType, } } // ECIESHKDFAES128GCMKeyTemplate creates an ECIES-AEAD-HKDF key template with: // - KEM: ECDH over NIST P-256 // - DEM: AES128-GCM // - KDF: HKDF-HMAC-SHA256 with an empty salt func ECIESHKDFAES128GCMKeyTemplate() *tinkpb.KeyTemplate { salt := []byte{} return createECIESAEADHKDFKeyTemplate(commonpb.EllipticCurveType_NIST_P256, commonpb.HashType_SHA256, commonpb.EcPointFormat_UNCOMPRESSED, aead.AES128GCMKeyTemplate(), salt) } // ECIESHKDFAES128CTRHMACSHA256KeyTemplate creates an ECIES-AEAD-HKDF key // template with: // - KEM: ECDH over NIST P-256 // - DEM: AES128-CTR-HMAC-SHA256 // - KDF: HKDF-HMAC-SHA256 with an empty salt // // The DEM parameters are: // - AES key size: 16 bytes // - AES CTR IV size: 16 bytes // - HMAC key size: 32 bytes // - HMAC tag size: 16 bytes func ECIESHKDFAES128CTRHMACSHA256KeyTemplate() *tinkpb.KeyTemplate { salt := []byte{} return createECIESAEADHKDFKeyTemplate(commonpb.EllipticCurveType_NIST_P256, commonpb.HashType_SHA256, commonpb.EcPointFormat_UNCOMPRESSED, aead.AES128CTRHMACSHA256KeyTemplate(), salt) } // createEciesAEADHKDFKeyTemplate creates a new ECIES-AEAD-HKDF key template // with the given parameters. func createECIESAEADHKDFKeyTemplate(c commonpb.EllipticCurveType, ht commonpb.HashType, ptfmt commonpb.EcPointFormat, dekT *tinkpb.KeyTemplate, salt []byte) *tinkpb.KeyTemplate { format := &eciespb.EciesAeadHkdfKeyFormat{ Params: &eciespb.EciesAeadHkdfParams{ KemParams: &eciespb.EciesHkdfKemParams{ CurveType: c, HkdfHashType: ht, HkdfSalt: salt, }, DemParams: &eciespb.EciesAeadDemParams{ AeadDem: dekT, }, EcPointFormat: ptfmt, }, } serializedFormat, err := proto.Marshal(format) if err != nil { tinkerror.Fail(fmt.Sprintf("failed to marshal key format: %s", err)) } return &tinkpb.KeyTemplate{ TypeUrl: eciesAEADHKDFPrivateKeyTypeURL, Value: serializedFormat, OutputPrefixType: tinkpb.OutputPrefixType_TINK, } } ================================================ FILE: go/hybrid/hybrid_key_templates_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hybrid_test import ( "bytes" "fmt" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/aead" "github.com/google/tink/go/daead" "github.com/google/tink/go/hybrid" "github.com/google/tink/go/internal/tinkerror" "github.com/google/tink/go/keyset" commonpb "github.com/google/tink/go/proto/common_go_proto" eciespb "github.com/google/tink/go/proto/ecies_aead_hkdf_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func createECIESKeyTemplate(curveType commonpb.EllipticCurveType, hashType commonpb.HashType, dekTemplate *tinkpb.KeyTemplate) *tinkpb.KeyTemplate { format := &eciespb.EciesAeadHkdfKeyFormat{ Params: &eciespb.EciesAeadHkdfParams{ KemParams: &eciespb.EciesHkdfKemParams{ CurveType: curveType, HkdfHashType: hashType, HkdfSalt: []byte{}, }, DemParams: &eciespb.EciesAeadDemParams{ AeadDem: dekTemplate, }, EcPointFormat: commonpb.EcPointFormat_UNCOMPRESSED, }, } serializedFormat, err := proto.Marshal(format) if err != nil { tinkerror.Fail(fmt.Sprintf("failed to marshal key format: %s", err)) } return &tinkpb.KeyTemplate{ TypeUrl: eciesAEADHKDFPrivateKeyTypeURL, Value: serializedFormat, OutputPrefixType: tinkpb.OutputPrefixType_TINK, } } func eciesP384AES256GCMKeyTemplate() *tinkpb.KeyTemplate { return createECIESKeyTemplate(commonpb.EllipticCurveType_NIST_P384, commonpb.HashType_SHA384, aead.AES256GCMKeyTemplate()) } func eciesP521AES256GCMKeyTemplate() *tinkpb.KeyTemplate { return createECIESKeyTemplate(commonpb.EllipticCurveType_NIST_P521, commonpb.HashType_SHA512, aead.AES256GCMKeyTemplate()) } func eciesP256AESSIVKeyTemplate() *tinkpb.KeyTemplate { return createECIESKeyTemplate(commonpb.EllipticCurveType_NIST_P256, commonpb.HashType_SHA256, daead.AESSIVKeyTemplate()) } func TestKeyTemplates(t *testing.T) { var testCases = []struct { name string template *tinkpb.KeyTemplate }{ { name: "ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM", template: hybrid.ECIESHKDFAES128GCMKeyTemplate(), }, { name: "ECIES_P384_HKDF_HMAC_SHA384_AES256_GCM", template: eciesP384AES256GCMKeyTemplate(), }, { name: "ECIES_P521_HKDF_HMAC_SHA512_AES256_GCM", template: eciesP521AES256GCMKeyTemplate(), }, { name: "ECIES_P256_AESSIV", template: eciesP256AESSIVKeyTemplate(), }, { name: "ECIES_P256_HKDF_HMAC_SHA256_AES128_CTR_HMAC_SHA256", template: hybrid.ECIESHKDFAES128CTRHMACSHA256KeyTemplate(), }, { name: "DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM", template: hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Key_Template(), }, { name: "DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_RAW", template: hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Raw_Key_Template(), }, { name: "DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM", template: hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM_Key_Template(), }, { name: "DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM_RAW", template: hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM_Raw_Key_Template(), }, { name: "DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305", template: hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Key_Template(), }, { name: "DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_RAW", template: hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Raw_Key_Template(), }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { privateHandle, err := keyset.NewHandle(tc.template) if err != nil { t.Fatalf("keyset.NewHandle(tc.template) failed: %s", err) } publicHandle, err := privateHandle.Public() if err != nil { t.Fatalf("privateHandle.Public() failed: %s", err) } enc, err := hybrid.NewHybridEncrypt(publicHandle) if err != nil { t.Fatalf("NewHybridEncrypt(publicHandle) err = %v, want nil", err) } dec, err := hybrid.NewHybridDecrypt(privateHandle) if err != nil { t.Fatalf("NewHybridDecrypt(privateHandle) err = %v, want nil", err) } var testInputs = []struct { plaintext []byte context1 []byte context2 []byte }{ { plaintext: []byte("this data needs to be encrypted"), context1: []byte("encryption context"), context2: []byte("encryption context"), }, { plaintext: []byte("this data needs to be encrypted"), context1: []byte(""), context2: []byte(""), }, { plaintext: []byte("this data needs to be encrypted"), context1: nil, context2: nil, }, { plaintext: []byte(""), context1: nil, context2: nil, }, { plaintext: nil, context1: []byte("encryption context"), context2: []byte("encryption context"), }, { plaintext: nil, context1: []byte(""), context2: []byte(""), }, { plaintext: nil, context1: nil, context2: nil, }, { plaintext: []byte("this data needs to be encrypted"), context1: []byte(""), context2: nil, }, { plaintext: []byte("this data needs to be encrypted"), context1: nil, context2: []byte(""), }, } for _, ti := range testInputs { ciphertext, err := enc.Encrypt(ti.plaintext, ti.context1) if err != nil { t.Fatalf("enc.Encrypt(ti.plaintext, ti.context1) err = %v, want nil", err) } decrypted, err := dec.Decrypt(ciphertext, ti.context2) if err != nil { t.Fatalf("dec.Decrypt(ciphertext, ti.context2) err = %v, want nil", err) } if !bytes.Equal(ti.plaintext, decrypted) { t.Errorf("decrypted data doesn't match plaintext, got: %q, want: %q", decrypted, ti.plaintext) } } }) } } ================================================ FILE: go/hybrid/hybrid_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hybrid_test // [START hybrid-example] import ( "bytes" "fmt" "log" "github.com/google/tink/go/hybrid" "github.com/google/tink/go/insecurecleartextkeyset" "github.com/google/tink/go/keyset" ) func Example() { // A private keyset created with // "tinkey create-keyset --key-template=DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM --out private_keyset.cfg". // Note that this keyset has the secret key information in cleartext. privateJSONKeyset := `{ "key": [{ "keyData": { "keyMaterialType": "ASYMMETRIC_PRIVATE", "typeUrl": "type.googleapis.com/google.crypto.tink.HpkePrivateKey", "value": "EioSBggBEAEYAhogVWQpmQoz74jcAp5WOD36KiBQ71MVCpn2iWfOzWLtKV4aINfn8qlMbyijNJcCzrafjsgJ493ZZGN256KTfKw0WN+p" }, "keyId": 958452012, "outputPrefixType": "TINK", "status": "ENABLED" }], "primaryKeyId": 958452012 }` // The corresponding public keyset created with // "tinkey create-public-keyset --in private_keyset.cfg". publicJSONKeyset := `{ "key": [{ "keyData": { "keyMaterialType": "ASYMMETRIC_PUBLIC", "typeUrl": "type.googleapis.com/google.crypto.tink.HpkePublicKey", "value": "EgYIARABGAIaIFVkKZkKM++I3AKeVjg9+iogUO9TFQqZ9olnzs1i7Sle" }, "keyId": 958452012, "outputPrefixType": "TINK", "status": "ENABLED" }], "primaryKeyId": 958452012 }` // Create a keyset handle from the keyset containing the public key. Because the // public keyset does not contain any secrets, we can use [keyset.ReadWithNoSecrets]. publicKeysetHandle, err := keyset.ReadWithNoSecrets( keyset.NewJSONReader(bytes.NewBufferString(publicJSONKeyset))) if err != nil { log.Fatal(err) } // Retrieve the HybridEncrypt primitive from publicKeysetHandle. encPrimitive, err := hybrid.NewHybridEncrypt(publicKeysetHandle) if err != nil { log.Fatal(err) } plaintext := []byte("message") encryptionContext := []byte("encryption context") ciphertext, err := encPrimitive.Encrypt(plaintext, encryptionContext) if err != nil { log.Fatal(err) } // Create a keyset handle from the cleartext private keyset in the previous // step. The keyset handle provides abstract access to the underlying keyset to // limit the access of the raw key material. WARNING: In practice, // it is unlikely you will want to use a insecurecleartextkeyset, as it implies // that your key material is passed in cleartext, which is a security risk. // Consider encrypting it with a remote key in Cloud KMS, AWS KMS or HashiCorp Vault. // See https://github.com/google/tink/blob/master/docs/GOLANG-HOWTO.md#storing-and-loading-existing-keysets. privateKeysetHandle, err := insecurecleartextkeyset.Read( keyset.NewJSONReader(bytes.NewBufferString(privateJSONKeyset))) if err != nil { log.Fatal(err) } // Retrieve the HybridDecrypt primitive from privateKeysetHandle. decPrimitive, err := hybrid.NewHybridDecrypt(privateKeysetHandle) if err != nil { log.Fatal(err) } decrypted, err := decPrimitive.Decrypt(ciphertext, encryptionContext) if err != nil { log.Fatal(err) } fmt.Println(string(decrypted)) // Output: message } // [END hybrid-example] ================================================ FILE: go/hybrid/internal/hpke/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep go_library( name = "hpke", srcs = [ "aead.go", "aes_gcm_aead.go", "chacha20poly1305_aead.go", "context.go", "decrypt.go", "encrypt.go", "hkdf_kdf.go", "hpke.go", "kdf.go", "kem.go", "primitive_factory.go", "x25519_kem.go", ], importpath = "github.com/google/tink/go/hybrid/internal/hpke", deps = [ "//internal/aead", "//proto/hpke_go_proto", "//subtle", "//tink", "@org_golang_x_crypto//chacha20poly1305", "@org_golang_x_crypto//hkdf", ], ) go_test( name = "hpke_test", srcs = [ "aes_gcm_aead_test.go", "chacha20poly1305_aead_test.go", "context_test.go", "encrypt_decrypt_test.go", "hkdf_kdf_test.go", "hpke_test.go", "primitive_factory_test.go", "x25519_kem_test.go", ], data = ["//testdata/testvectors:hpke_boringssl"], embed = [":hpke"], deps = [ "//proto/hpke_go_proto", "//subtle", "//subtle/random", "//testutil", ], ) alias( name = "go_default_library", actual = ":hpke", visibility = ["//:__subpackages__"], ) ================================================ FILE: go/hybrid/internal/hpke/aead.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hpke // aead is a package-internal interface for the Hybrid Public Key Encryption // (HPKE) authenticated encryption with associated data (AEAD). // // The HPKE RFC is available at // https://www.rfc-editor.org/rfc/rfc9180.html. type aead interface { // seal performs authenticated encryption of plaintext and associatedData // using key and nonce. // // https://www.rfc-editor.org/rfc/rfc9180.html#section-5.2 seal(key, nonce, plaintext, associatedData []byte) ([]byte, error) // open performs authenticated decryption of ciphertext and associatedData // using key and nonce. // // https://www.rfc-editor.org/rfc/rfc9180.html#section-5.2 open(key, nonce, ciphertext, associatedData []byte) ([]byte, error) // id returns the HPKE AEAD algorithm identifier for the underlying AEAD // implementation. // // https://www.rfc-editor.org/rfc/rfc9180.html#section-7.3 id() uint16 // keyLength returns the length of the key. keyLength() int // nonceLength returns the length of the nonce. nonceLength() int } ================================================ FILE: go/hybrid/internal/hpke/aes_gcm_aead.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hpke import ( "fmt" internalaead "github.com/google/tink/go/internal/aead" ) // aesGCMAEAD is an AES GCM HPKE AEAD variant that implements interface // aead. type aesGCMAEAD struct { // HPKE AEAD algorithm identifier. aeadID uint16 keyLen int } var _ aead = (*aesGCMAEAD)(nil) // newAESGCMAEAD constructs an AES-GCM HPKE AEAD using keyLength. func newAESGCMAEAD(keyLength int) (*aesGCMAEAD, error) { switch keyLength { case 16: return &aesGCMAEAD{aeadID: aes128GCM, keyLen: 16}, nil case 32: return &aesGCMAEAD{aeadID: aes256GCM, keyLen: 32}, nil default: return nil, fmt.Errorf("key length %d is not supported", keyLength) } } func (a *aesGCMAEAD) seal(key, nonce, plaintext, associatedData []byte) ([]byte, error) { if len(key) != a.keyLen { return nil, fmt.Errorf("unexpected key length: got %d, want %d", len(key), a.keyLen) } i, err := internalaead.NewAESGCMInsecureIV(key, false /*=prependIV*/) if err != nil { return nil, fmt.Errorf("NewAESGCMInsecureIV: %v", err) } return i.Encrypt(nonce, plaintext, associatedData) } func (a *aesGCMAEAD) open(key, nonce, ciphertext, associatedData []byte) ([]byte, error) { if len(key) != a.keyLen { return nil, fmt.Errorf("unexpected key length: got %d, want %d", len(key), a.keyLen) } i, err := internalaead.NewAESGCMInsecureIV(key, false /*=prependIV*/) if err != nil { return nil, fmt.Errorf("NewAESGCMInsecureIV: %v", err) } return i.Decrypt(nonce, ciphertext, associatedData) } func (a *aesGCMAEAD) id() uint16 { return a.aeadID } func (a *aesGCMAEAD) keyLength() int { return a.keyLen } func (a *aesGCMAEAD) nonceLength() int { return internalaead.AESGCMIVSize } ================================================ FILE: go/hybrid/internal/hpke/aes_gcm_aead_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hpke import ( "bytes" "fmt" "testing" ) func TestAESGCMAEADSealOpen(t *testing.T) { i := 0 vecs := aeadRFCVectors(t) for k, v := range vecs { if k.aeadID != aes128GCM && k.aeadID != aes256GCM { continue } i++ t.Run(fmt.Sprintf("%d", k.id), func(t *testing.T) { { aead, err := newAEAD(k.aeadID) if err != nil { t.Fatalf("newAEAD(%d): got err %q, want success", k.aeadID, err) } ciphertext, err := aead.seal(v.key, v.nonce, v.plaintext, v.associatedData) if err != nil { t.Fatalf("seal: got err %q, want success", err) } if !bytes.Equal(ciphertext, v.ciphertext) { t.Errorf("seal: got %x, want %x", ciphertext, v.ciphertext) } plaintext, err := aead.open(v.key, v.nonce, v.ciphertext, v.associatedData) if err != nil { t.Fatalf("open: got err %q, want success", err) } if !bytes.Equal(plaintext, v.plaintext) { t.Errorf("open: got %x, want %x", plaintext, v.plaintext) } } // Test exactly as above, except instantiate aesGcmHpkeAead with a key // length that does not match the length of the key passed into seal and // open. { var wrongID uint16 switch k.aeadID { case aes128GCM: wrongID = aes256GCM case aes256GCM: wrongID = aes128GCM default: t.Fatalf("AEAD ID %d is not supported", k.aeadID) } aead, err := newAEAD(wrongID) if err != nil { t.Fatalf("newAEAD(%d): got err %q, want success", wrongID, err) } if _, err := aead.seal(v.key, v.nonce, v.plaintext, v.associatedData); err == nil { t.Error("seal with unexpected key length: got success, want err") } if _, err := aead.open(v.key, v.nonce, v.ciphertext, v.associatedData); err == nil { t.Error("open with unexpected key length: got success, want err") } } }) } if i < 2 { t.Errorf("number of vectors tested = %d, want > %d", i, 2) } } ================================================ FILE: go/hybrid/internal/hpke/chacha20poly1305_aead.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hpke import ( "fmt" "golang.org/x/crypto/chacha20poly1305" internalaead "github.com/google/tink/go/internal/aead" ) // chaCha20Poly1305AEAD is a ChaCha20-Poly1305 HPKE AEAD variant that // implements interface aead. type chaCha20Poly1305AEAD struct{} var _ aead = (*chaCha20Poly1305AEAD)(nil) func (c *chaCha20Poly1305AEAD) seal(key, nonce, plaintext, associatedData []byte) ([]byte, error) { if len(key) != chacha20poly1305.KeySize { return nil, fmt.Errorf("unexpected key length: got %d, want %d", len(key), chacha20poly1305.KeySize) } cc, err := internalaead.NewChaCha20Poly1305InsecureNonce(key) if err != nil { return nil, fmt.Errorf("NewChaCha20Poly1305InsecureNonce: %v", err) } return cc.Encrypt(nonce, plaintext, associatedData) } func (c *chaCha20Poly1305AEAD) open(key, nonce, ciphertext, associatedData []byte) ([]byte, error) { if len(key) != chacha20poly1305.KeySize { return nil, fmt.Errorf("unexpected key length: got %d, want %d", len(key), chacha20poly1305.KeySize) } cc, err := internalaead.NewChaCha20Poly1305InsecureNonce(key) if err != nil { return nil, fmt.Errorf("NewChaCha20Poly1305InsecureNonce: %v", err) } return cc.Decrypt(nonce, ciphertext, associatedData) } func (c *chaCha20Poly1305AEAD) id() uint16 { return chaCha20Poly1305 } func (c *chaCha20Poly1305AEAD) keyLength() int { return chacha20poly1305.KeySize } func (c *chaCha20Poly1305AEAD) nonceLength() int { return chacha20poly1305.NonceSize } ================================================ FILE: go/hybrid/internal/hpke/chacha20poly1305_aead_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hpke import ( "bytes" "fmt" "testing" ) func TestChaCha20Poly1305AEADSealOpen(t *testing.T) { i := 0 vecs := aeadRFCVectors(t) for k, v := range vecs { if k.aeadID != chaCha20Poly1305 { continue } i++ t.Run(fmt.Sprintf("%d", k.id), func(t *testing.T) { aead, err := newAEAD(k.aeadID) if err != nil { t.Fatalf("newAEAD(%d) err = %v, want nil", k.aeadID, err) } ciphertext, err := aead.seal(v.key, v.nonce, v.plaintext, v.associatedData) if err != nil { t.Fatalf("seal err = %v, want nil", err) } if !bytes.Equal(ciphertext, v.ciphertext) { t.Errorf("seal = %x, want %x", ciphertext, v.ciphertext) } plaintext, err := aead.open(v.key, v.nonce, v.ciphertext, v.associatedData) if err != nil { t.Fatalf("open err = %v, want nil", err) } if !bytes.Equal(plaintext, v.plaintext) { t.Errorf("open = %x, want %x", plaintext, v.plaintext) } }) } if i < 2 { t.Errorf("number of vectors tested = %d, want > %d", i, 2) } } ================================================ FILE: go/hybrid/internal/hpke/context.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hpke import ( "errors" "fmt" "math/big" pb "github.com/google/tink/go/proto/hpke_go_proto" ) type context struct { aead aead maxSequenceNumber *big.Int sequenceNumber *big.Int key []byte baseNonce []byte encapsulatedKey []byte } // newSenderContext creates the HPKE sender context as per KeySchedule() // https://www.rfc-editor.org/rfc/rfc9180.html#section-5.1-10. func newSenderContext(recipientPubKey *pb.HpkePublicKey, kem kem, kdf kdf, aead aead, info []byte) (*context, error) { if recipientPubKey.GetPublicKey() == nil { return nil, errors.New("HpkePublicKey has an empty PublicKey") } sharedSecret, encapsulatedKey, err := kem.encapsulate(recipientPubKey.GetPublicKey()) if err != nil { return nil, fmt.Errorf("encapsulate: %v", err) } return createContext(encapsulatedKey, sharedSecret, kem, kdf, aead, info) } // newRecipientContext creates the HPKE recipient context as per KeySchedule() // https://www.rfc-editor.org/rfc/rfc9180.html#section-5.1-10. func newRecipientContext(encapsulatedKey []byte, recipientPrivKey *pb.HpkePrivateKey, kem kem, kdf kdf, aead aead, info []byte) (*context, error) { if recipientPrivKey.GetPrivateKey() == nil { return nil, errors.New("HpkePrivateKey has an empty PrivateKey") } sharedSecret, err := kem.decapsulate(encapsulatedKey, recipientPrivKey.GetPrivateKey()) if err != nil { return nil, fmt.Errorf("decapsulate: %v", err) } return createContext(encapsulatedKey, sharedSecret, kem, kdf, aead, info) } func createContext(encapsulatedKey []byte, sharedSecret []byte, kem kem, kdf kdf, aead aead, info []byte) (*context, error) { suiteID := hpkeSuiteID(kem.id(), kdf.id(), aead.id()) // In base mode, both the pre-shared key (default_psk) and pre-shared key ID // (default_psk_id) are empty strings, see // https://www.rfc-editor.org/rfc/rfc9180.html#section-5.1.1-4. pskIDHash := kdf.labeledExtract(emptySalt, emptyIKM /*= default PSK ID*/, "psk_id_hash", suiteID) infoHash := kdf.labeledExtract(emptySalt, info, "info_hash", suiteID) keyScheduleCtx := keyScheduleContext(baseMode, pskIDHash, infoHash) secret := kdf.labeledExtract(sharedSecret, emptyIKM /*= default PSK*/, "secret", suiteID) key, err := kdf.labeledExpand(secret, keyScheduleCtx, "key", suiteID, aead.keyLength()) if err != nil { return nil, fmt.Errorf("labeledExpand of key: %v", err) } baseNonce, err := kdf.labeledExpand(secret, keyScheduleCtx, "base_nonce", suiteID, aead.nonceLength()) if err != nil { return nil, fmt.Errorf("labeledExpand of base nonce: %v", err) } return &context{ aead: aead, maxSequenceNumber: maxSequenceNumber(aead.nonceLength()), sequenceNumber: big.NewInt(0), key: key, baseNonce: baseNonce, encapsulatedKey: encapsulatedKey, }, nil } // maxSequenceNumber returns the maximum sequence number indicating that the // message limit is reached, calculated as per // https://www.rfc-editor.org/rfc/rfc9180.html#section-5.2-11. func maxSequenceNumber(nonceLength int) *big.Int { res := new(big.Int) one := big.NewInt(1) res.Lsh(one, uint(8*nonceLength)).Sub(res, one) return res } func (c *context) incrementSequenceNumber() error { c.sequenceNumber.Add(c.sequenceNumber, big.NewInt(1)) if c.sequenceNumber.Cmp(c.maxSequenceNumber) > 0 { return errors.New("message limit reached") } return nil } // computeNonce computes the nonce as per // https://www.rfc-editor.org/rfc/rfc9180.html#section-5.2-12. func (c *context) computeNonce() ([]byte, error) { nonce := make([]byte, len(c.baseNonce)) // Write the big-endian c.sequenceNumber value at the end of nonce. sequenceNumber := c.sequenceNumber.Bytes() index := len(nonce) - len(sequenceNumber) if index < 0 { return nil, fmt.Errorf("sequence number length (%d) is larger than nonce length (%d)", len(sequenceNumber), len(nonce)) } copy(nonce[index:], sequenceNumber) // nonce XOR c.baseNonce. for i, b := range c.baseNonce { nonce[i] ^= b } return nonce, nil } // seal allows the sender's context to encrypt plaintext with associatedData, // defined as ContextS.Seal in // https://www.rfc-editor.org/rfc/rfc9180.html#section-5.2-7. func (c *context) seal(plaintext, associatedData []byte) ([]byte, error) { nonce, err := c.computeNonce() if err != nil { return nil, fmt.Errorf("computeNonce: %v", err) } ciphertext, err := c.aead.seal(c.key, nonce, plaintext, associatedData) if err != nil { return nil, fmt.Errorf("seal: %v", err) } if err := c.incrementSequenceNumber(); err != nil { return nil, err } return ciphertext, nil } // open allows the receiver's context to decrypt ciphertext with // associatedData, defined as ContextR.Open in // https://www.rfc-editor.org/rfc/rfc9180.html#section-5.2-9. func (c *context) open(ciphertext, associatedData []byte) ([]byte, error) { nonce, err := c.computeNonce() if err != nil { return nil, fmt.Errorf("computeNonce: %v", err) } plaintext, err := c.aead.open(c.key, nonce, ciphertext, associatedData) if err != nil { return nil, fmt.Errorf("open: %v", err) } if err := c.incrementSequenceNumber(); err != nil { return nil, err } return plaintext, nil } ================================================ FILE: go/hybrid/internal/hpke/context_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hpke import ( "bytes" "math/big" "testing" "github.com/google/tink/go/subtle" pb "github.com/google/tink/go/proto/hpke_go_proto" ) // TODO(b/201070904): Write tests using baseModeX25519HKDFSHA256Vectors. func TestContextSender(t *testing.T) { id, vec := internetDraftVector(t) kem, err := newKEM(id.kemID) if err != nil { t.Fatalf("newKEM(%d): err %q", id.kemID, err) } x25519KEMGeneratePrivateKey = func() ([]byte, error) { return vec.senderPrivKey, nil } kdf, err := newKDF(id.kdfID) if err != nil { t.Fatalf("newKDF(%d): err %q", id.kdfID, err) } aead, err := newAEAD(id.aeadID) if err != nil { t.Fatalf("newAEAD(%d): err %q", id.aeadID, err) } recipientPubKey := &pb.HpkePublicKey{PublicKey: vec.recipientPubKey} senderCtx, err := newSenderContext(recipientPubKey, kem, kdf, aead, vec.info) if err != nil { t.Fatalf("newSenderContext: err %q", err) } for _, enc := range vec.consecutiveEncryptions { if got, want := senderCtx.sequenceNumber, enc.sequenceNumber; got.Cmp(want) != 0 { t.Fatalf("sequence number: got %s, want %s", got.String(), want.String()) } ct, err := senderCtx.seal(enc.plaintext, enc.associatedData) if err != nil { t.Fatal(err) } if !bytes.Equal(ct, enc.ciphertext) { t.Errorf("ciphertext: got %x, want %x", ct, enc.ciphertext) } } for _, enc := range vec.otherEncryptions { senderCtx.sequenceNumber.Set(enc.sequenceNumber) ct, err := senderCtx.seal(enc.plaintext, enc.associatedData) if err != nil { t.Fatal(err) } if !bytes.Equal(ct, enc.ciphertext) { t.Errorf("ciphertext: got %x, want %x", ct, enc.ciphertext) } } x25519KEMGeneratePrivateKey = subtle.GeneratePrivateKeyX25519 } func TestContextRecipient(t *testing.T) { id, vec := internetDraftVector(t) kem, err := newKEM(id.kemID) if err != nil { t.Fatalf("newKEM(%d): err %q", id.kemID, err) } kdf, err := newKDF(id.kdfID) if err != nil { t.Fatalf("newKDF(%d): err %q", id.kdfID, err) } aead, err := newAEAD(id.aeadID) if err != nil { t.Fatalf("newAEAD(%d): err %q", id.aeadID, err) } recipientPrivKey := &pb.HpkePrivateKey{PrivateKey: vec.recipientPrivKey} recipientCtx, err := newRecipientContext(vec.encapsulatedKey, recipientPrivKey, kem, kdf, aead, vec.info) if err != nil { t.Fatalf("newRecipientContext: err %q", err) } for _, enc := range vec.consecutiveEncryptions { if got, want := recipientCtx.sequenceNumber, enc.sequenceNumber; got.Cmp(want) != 0 { t.Fatalf("sequence number: got %s, want %s", got.String(), want.String()) } pt, err := recipientCtx.open(enc.ciphertext, enc.associatedData) if err != nil { t.Fatal(err) } if !bytes.Equal(pt, enc.plaintext) { t.Errorf("plaintext: got %x, want %x", pt, enc.plaintext) } } for _, enc := range vec.otherEncryptions { recipientCtx.sequenceNumber.Set(enc.sequenceNumber) pt, err := recipientCtx.open(enc.ciphertext, enc.associatedData) if err != nil { t.Fatal(err) } if !bytes.Equal(pt, enc.plaintext) { t.Errorf("plaintext: got %x, want %x", pt, enc.plaintext) } } } func TestContextMaxSequenceNumber(t *testing.T) { got := maxSequenceNumber(12 /*=AESGCMIVSize*/) want, ok := new(big.Int).SetString("79228162514264337593543950335", 10) // (1 << (8*12)) - 1 if !ok { t.Fatalf("SetString(\"79228162514264337593543950335\", 10): got err, want success") } if got.Cmp(want) != 0 { t.Errorf("maxSequenceNumber(12): got %s, want %s", got.String(), want.String()) } } func TestComputeNonce(t *testing.T) { id, vec := internetDraftVector(t) kem, err := newKEM(id.kemID) if err != nil { t.Fatalf("newKEM(%d): err %q", id.kemID, err) } kdf, err := newKDF(id.kdfID) if err != nil { t.Fatalf("newKDF(%d): err %q", id.kdfID, err) } aead, err := newAEAD(id.aeadID) if err != nil { t.Fatalf("newAEAD(%d): err %q", id.aeadID, err) } recipientPrivKey := &pb.HpkePrivateKey{PrivateKey: vec.recipientPrivKey} ctx, err := newRecipientContext(vec.encapsulatedKey, recipientPrivKey, kem, kdf, aead, vec.info) if err != nil { t.Fatalf("newRecipientContext: err %q", err) } if !bytes.Equal(ctx.baseNonce, vec.baseNonce) { t.Fatalf("base nonce: got %x, want %x", ctx.baseNonce, vec.baseNonce) } for _, enc := range vec.consecutiveEncryptions { nonce, err := ctx.computeNonce() if err != nil { t.Fatal(err) } if !bytes.Equal(nonce, enc.nonce) { t.Errorf("computeNonce: got %x, want %x", nonce, enc.nonce) } if err := ctx.incrementSequenceNumber(); err != nil { t.Fatal(err) } } for _, enc := range vec.otherEncryptions { ctx.sequenceNumber.Set(enc.sequenceNumber) nonce, err := ctx.computeNonce() if err != nil { t.Fatal(err) } if !bytes.Equal(nonce, enc.nonce) { t.Errorf("computeNonce: got %x, want %x", nonce, enc.nonce) } if err := ctx.incrementSequenceNumber(); err != nil { t.Fatal(err) } } } ================================================ FILE: go/hybrid/internal/hpke/decrypt.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hpke import ( "errors" "fmt" "github.com/google/tink/go/tink" pb "github.com/google/tink/go/proto/hpke_go_proto" ) // Decrypt for HPKE implements interface HybridDecrypt. type Decrypt struct { recipientPrivKey *pb.HpkePrivateKey kem kem kdf kdf aead aead encapsulatedKeyLen int } var _ tink.HybridDecrypt = (*Decrypt)(nil) // NewDecrypt constructs a Decrypt using HpkePrivateKey. func NewDecrypt(recipientPrivKey *pb.HpkePrivateKey) (*Decrypt, error) { if recipientPrivKey.GetPrivateKey() == nil || len(recipientPrivKey.GetPrivateKey()) == 0 { return nil, errors.New("HpkePrivateKey.PrivateKey bytes are missing") } kem, kdf, aead, err := newPrimitivesFromProto(recipientPrivKey.GetPublicKey().GetParams()) if err != nil { return nil, err } return &Decrypt{recipientPrivKey, kem, kdf, aead, kem.encapsulatedKeyLength()}, nil } // Decrypt decrypts ciphertext, verifying the integrity of contextInfo. func (d *Decrypt) Decrypt(ciphertext, contextInfo []byte) ([]byte, error) { if len(ciphertext) < d.encapsulatedKeyLen { return nil, fmt.Errorf("ciphertext (size %d) is too short", len(ciphertext)) } encapsulatedKey := ciphertext[:d.encapsulatedKeyLen] aeadCiphertext := ciphertext[d.encapsulatedKeyLen:] ctx, err := newRecipientContext(encapsulatedKey, d.recipientPrivKey, d.kem, d.kdf, d.aead, contextInfo) if err != nil { return nil, fmt.Errorf("newRecipientContext: %v", err) } return ctx.open(aeadCiphertext, emptyAssociatedData) } ================================================ FILE: go/hybrid/internal/hpke/encrypt.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hpke import ( "errors" "fmt" "github.com/google/tink/go/tink" pb "github.com/google/tink/go/proto/hpke_go_proto" ) // Encrypt for HPKE implements interface HybridEncrypt. type Encrypt struct { recipientPubKey *pb.HpkePublicKey kem kem kdf kdf aead aead } var _ tink.HybridEncrypt = (*Encrypt)(nil) // NewEncrypt constructs an Encrypt using HpkePublicKey. func NewEncrypt(recipientPubKey *pb.HpkePublicKey) (*Encrypt, error) { if recipientPubKey.GetPublicKey() == nil || len(recipientPubKey.GetPublicKey()) == 0 { return nil, errors.New("HpkePublicKey.PublicKey bytes are missing") } kem, kdf, aead, err := newPrimitivesFromProto(recipientPubKey.GetParams()) if err != nil { return nil, err } return &Encrypt{recipientPubKey, kem, kdf, aead}, nil } // Encrypt encrypts plaintext, binding contextInfo to the resulting ciphertext. func (e *Encrypt) Encrypt(plaintext, contextInfo []byte) ([]byte, error) { ctx, err := newSenderContext(e.recipientPubKey, e.kem, e.kdf, e.aead, contextInfo) if err != nil { return nil, fmt.Errorf("newSenderContext: %v", err) } ciphertext, err := ctx.seal(plaintext, emptyAssociatedData) if err != nil { return nil, fmt.Errorf("seal: %v", err) } return append(ctx.encapsulatedKey, ciphertext...), nil } ================================================ FILE: go/hybrid/internal/hpke/encrypt_decrypt_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hpke import ( "bytes" "math/rand" "testing" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/subtle" pb "github.com/google/tink/go/proto/hpke_go_proto" ) func TestNewEncryptDecryptUnknownKEM(t *testing.T) { params := validParams(t) params.Kem = pb.HpkeKem_KEM_UNKNOWN pubKey, privKey := pubPrivKeys(t, params) if _, err := NewEncrypt(pubKey); err == nil { t.Error("NewEncrypt(unknown KEM): got success, want err") } if _, err := NewDecrypt(privKey); err == nil { t.Error("NewDecrypt(unknown KEM): got success, want err") } } func TestNewEncryptDecryptUnknownKDF(t *testing.T) { params := validParams(t) params.Kdf = pb.HpkeKdf_KDF_UNKNOWN pubKey, privKey := pubPrivKeys(t, params) if _, err := NewEncrypt(pubKey); err == nil { t.Error("NewEncrypt(unknown KDF): got success, want err") } if _, err := NewDecrypt(privKey); err == nil { t.Error("NewDecrypt(unknown KDF): got success, want err") } } func TestNewEncryptDecryptUnknownAEAD(t *testing.T) { params := validParams(t) params.Aead = pb.HpkeAead_AEAD_UNKNOWN pubKey, privKey := pubPrivKeys(t, params) if _, err := NewEncrypt(pubKey); err == nil { t.Error("NewEncrypt(unknown AEAD): got success, want err") } if _, err := NewDecrypt(privKey); err == nil { t.Error("NewDecrypt(unknown AEAD): got success, want err") } } func TestNewEncryptDecryptMissingParams(t *testing.T) { pubKey, privKey := pubPrivKeys(t, nil) if _, err := NewEncrypt(pubKey); err == nil { t.Error("NewEncrypt(missing params): got success, want err") } if _, err := NewDecrypt(privKey); err == nil { t.Error("NewDecrypt(missing params): got success, want err") } } func TestNewEncryptMissingPubKeyBytes(t *testing.T) { pubKey, _ := pubPrivKeys(t, validParams(t)) pubKey.PublicKey = nil if _, err := NewEncrypt(pubKey); err == nil { t.Error("NewEncrypt(nil pub key): got success, want err") } pubKey.PublicKey = []byte{} if _, err := NewEncrypt(pubKey); err == nil { t.Error("NewEncrypt(zero-length pub key): got success, want err") } } func TestNewDecryptMissingPrivKeyBytes(t *testing.T) { _, privKey := pubPrivKeys(t, validParams(t)) privKey.PrivateKey = nil if _, err := NewDecrypt(privKey); err == nil { t.Error("NewDecrypt(nil priv key): got success, want err") } privKey.PrivateKey = []byte{} if _, err := NewDecrypt(privKey); err == nil { t.Error("NewDecrypt(zero-length priv key): got success, want err") } } func TestEncryptDecrypt(t *testing.T) { aeadIDs := []pb.HpkeAead{pb.HpkeAead_AES_128_GCM, pb.HpkeAead_AES_256_GCM, pb.HpkeAead_CHACHA20_POLY1305} for _, aeadID := range aeadIDs { params := &pb.HpkeParams{ Kem: pb.HpkeKem_DHKEM_X25519_HKDF_SHA256, Kdf: pb.HpkeKdf_HKDF_SHA256, Aead: aeadID, } pubKey, privKey := pubPrivKeys(t, params) enc, err := NewEncrypt(pubKey) if err != nil { t.Fatalf("NewEncrypt: err %q", err) } dec, err := NewDecrypt(privKey) if err != nil { t.Fatalf("NewDecrypt: err %q", err) } wantPT := random.GetRandomBytes(200) ctxInfo := random.GetRandomBytes(100) ct, err := enc.Encrypt(wantPT, ctxInfo) if err != nil { t.Fatalf("Encrypt: err %q", err) } gotPT, err := dec.Decrypt(ct, ctxInfo) if err != nil { t.Fatalf("Decrypt: err %q", err) } if !bytes.Equal(gotPT, wantPT) { t.Errorf("Decrypt: got %q, want %q", gotPT, wantPT) } } } func TestDecryptModifiedCiphertextOrContextInfo(t *testing.T) { pubKey, privKey := pubPrivKeys(t, validParams(t)) enc, err := NewEncrypt(pubKey) if err != nil { t.Fatalf("NewEncrypt: err %q", err) } dec, err := NewDecrypt(privKey) if err != nil { t.Fatalf("NewDecrypt: err %q", err) } wantPT := random.GetRandomBytes(200) ctxInfo := random.GetRandomBytes(100) ct, err := enc.Encrypt(wantPT, ctxInfo) if err != nil { t.Fatalf("Encrypt: err %q", err) } gotPT, err := dec.Decrypt(ct, ctxInfo) if err != nil { t.Fatalf("Decrypt: err %q", err) } if !bytes.Equal(gotPT, wantPT) { t.Errorf("Decrypt: got %q, want %q", gotPT, wantPT) } tests := []struct { name string ct []byte ctxInfo []byte }{ {"extended ct", append(ct, []byte("hi there")...), ctxInfo}, {"flip byte ct", flipRandByte(t, ct), ctxInfo}, {"short ct", ct[:len(ct)-5], ctxInfo}, {"empty ct", []byte{}, ctxInfo}, {"extended ctxInfo", ct, append(ctxInfo, []byte("hi there")...)}, {"flip byte ctxInfo", ct, flipRandByte(t, ctxInfo)}, {"short ctxInfo", ct, ctxInfo[:len(ctxInfo)-5]}, {"empty ctxInfo", ct, []byte{}}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { if _, err := dec.Decrypt(test.ct, test.ctxInfo); err == nil { t.Error("Decrypt: got success, want err") } }) } } func TestEncryptDecryptEmptyContextInfo(t *testing.T) { pubKey, privKey := pubPrivKeys(t, validParams(t)) enc, err := NewEncrypt(pubKey) if err != nil { t.Fatalf("NewEncrypt: err %q", err) } dec, err := NewDecrypt(privKey) if err != nil { t.Fatalf("NewDecrypt: err %q", err) } wantPT := random.GetRandomBytes(200) ctxInfo := []byte{} ct, err := enc.Encrypt(wantPT, ctxInfo) if err != nil { t.Fatalf("Encrypt: err %q", err) } gotPT, err := dec.Decrypt(ct, ctxInfo) if err != nil { t.Fatalf("Decrypt: err %q", err) } if !bytes.Equal(gotPT, wantPT) { t.Errorf("Decrypt: got %q, want %q", gotPT, wantPT) } } // TestDecryptEncapsulatedKeyWithFlippedMSB checks that ciphertexts with its // encapsulated key MSB flipped fails to decrypt. See details at b/213886185. func TestDecryptEncapsulatedKeyWithFlippedMSB(t *testing.T) { pubKey, privKey := pubPrivKeys(t, validParams(t)) enc, err := NewEncrypt(pubKey) if err != nil { t.Fatalf("NewEncrypt: err %q", err) } dec, err := NewDecrypt(privKey) if err != nil { t.Fatalf("NewDecrypt: err %q", err) } wantPT := random.GetRandomBytes(200) ctxInfo := random.GetRandomBytes(100) ct, err := enc.Encrypt(wantPT, ctxInfo) if err != nil { t.Fatalf("Encrypt: err %q", err) } gotPT, err := dec.Decrypt(ct, ctxInfo) if err != nil { t.Fatalf("Decrypt: err %q", err) } if !bytes.Equal(gotPT, wantPT) { t.Errorf("Decrypt: got %q, want %q", gotPT, wantPT) } // Flip the MSB of the encapsulated key, which is the first 32 bytes of ct. ct[31] = ct[31] ^ 128 if _, err := dec.Decrypt(ct, ctxInfo); err == nil { t.Error("Decrypt with encapsulated key MSB flipped: got success, want err") } } func validParams(t *testing.T) *pb.HpkeParams { t.Helper() return &pb.HpkeParams{ Kem: pb.HpkeKem_DHKEM_X25519_HKDF_SHA256, Kdf: pb.HpkeKdf_HKDF_SHA256, Aead: pb.HpkeAead_AES_256_GCM, } } func pubPrivKeys(t *testing.T, params *pb.HpkeParams) (*pb.HpkePublicKey, *pb.HpkePrivateKey) { t.Helper() priv, err := subtle.GeneratePrivateKeyX25519() if err != nil { t.Fatalf("GeneratePrivateKeyX25519: err %q", err) } pub, err := subtle.PublicFromPrivateX25519(priv) if err != nil { t.Fatalf("PublicFromPrivateX25519: err %q", err) } pubKey := &pb.HpkePublicKey{ Version: 0, Params: params, PublicKey: pub, } privKey := &pb.HpkePrivateKey{ Version: 0, PublicKey: pubKey, PrivateKey: priv, } return pubKey, privKey } func flipRandByte(t *testing.T, b []byte) []byte { t.Helper() ret := make([]byte, len(b)) copy(ret, b) randByte := rand.Intn(len(b)) ret[randByte] = ret[randByte] ^ 255 return ret } ================================================ FILE: go/hybrid/internal/hpke/hkdf_kdf.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hpke import ( "crypto" "fmt" "io" "golang.org/x/crypto/hkdf" ) // hkdfKDF is a HKDF HPKE KDF variant that implements interface kdf. type hkdfKDF struct { // HPKE KDF algorithm identifier. kdfID uint16 hashFunction crypto.Hash } var _ kdf = (*hkdfKDF)(nil) // newHKDFKDF constructs a HKDF HPKE KDF using hashFunction. func newHKDFKDF(hashFunction string) (*hkdfKDF, error) { if hashFunction == sha256 { return &hkdfKDF{kdfID: hkdfSHA256, hashFunction: crypto.SHA256}, nil } return nil, fmt.Errorf("hash function %s is not supported", hashFunction) } func (h *hkdfKDF) labeledExtract(salt, ikm []byte, ikmLabel string, suiteID []byte) []byte { return hkdf.Extract(h.hashFunction.New, labelIKM(ikmLabel, ikm, suiteID), salt) } func (h *hkdfKDF) labeledExpand(prk, info []byte, infoLabel string, suiteID []byte, length int) ([]byte, error) { labeledInfo, err := labelInfo(infoLabel, info, suiteID, length) if err != nil { return nil, err } reader := hkdf.Expand(h.hashFunction.New, prk, labeledInfo) key := make([]byte, length) if _, err := io.ReadFull(reader, key); err != nil { return nil, err } return key, nil } func (h *hkdfKDF) extractAndExpand(salt, ikm []byte, ikmLabel string, info []byte, infoLabel string, suiteID []byte, length int) ([]byte, error) { prk := h.labeledExtract(salt, ikm, ikmLabel, suiteID) return h.labeledExpand(prk, info, infoLabel, suiteID, length) } func (h *hkdfKDF) id() uint16 { return h.kdfID } ================================================ FILE: go/hybrid/internal/hpke/hkdf_kdf_test.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hpke import ( "bytes" "encoding/hex" "fmt" "math" "testing" "github.com/google/tink/go/subtle" ) // TODO(b/201070904): Write tests using baseModeX25519HKDFSHA256Vectors. func TestHKDFKDFLabeledExtract(t *testing.T) { kdf, err := newKDF(hkdfSHA256) if err != nil { t.Fatalf("newKDF(hkdfSHA256): got err %q, want success", err) } id, v := internetDraftVector(t) suiteID := hpkeSuiteID(id.kemID, id.kdfID, id.aeadID) // Base mode uses a default empty value for the pre-shared key (PSK), see // https://www.rfc-editor.org/rfc/rfc9180.html#section-5.1.1-4. pskIDHash := kdf.labeledExtract(emptySalt, emptyIKM /*= default PSK ID*/, "psk_id_hash", suiteID) infoHash := kdf.labeledExtract(emptySalt, v.info, "info_hash", suiteID) keyScheduleCtx := keyScheduleContext(id.mode, pskIDHash, infoHash) if !bytes.Equal(keyScheduleCtx, v.keyScheduleCtx) { t.Errorf("labeledExtract: got %x, want %x", keyScheduleCtx, v.keyScheduleCtx) } secret := kdf.labeledExtract(v.sharedSecret, emptyIKM /*= default PSK*/, "secret", suiteID) if !bytes.Equal(secret, v.secret) { t.Errorf("labeledExtract: got %x, want %x", secret, v.secret) } } func TestHKDFKDFLabeledExpand(t *testing.T) { kdf, err := newKDF(hkdfSHA256) if err != nil { t.Fatalf("newKDF(hkdfSHA256): got err %q, want success", err) } id, v := internetDraftVector(t) suiteID := hpkeSuiteID(id.kemID, id.kdfID, id.aeadID) tests := []struct { infoLabel string length int want []byte wantErr bool }{ {"key", 16, v.key, false}, {"base_nonce", 12, v.baseNonce, false}, {"large_length", int(math.Pow(2, 16)), []byte{}, true}, } for _, test := range tests { t.Run(test.infoLabel, func(t *testing.T) { got, err := kdf.labeledExpand(v.secret, v.keyScheduleCtx, test.infoLabel, suiteID, test.length) if test.wantErr { if err == nil { t.Error("labeledExpand: got success, want err") } return } if err != nil { t.Errorf("labeledExpand: got err %q, want success", err) } if !bytes.Equal(got, test.want) { t.Errorf("labeledExpand: got %x, want %x", got, test.want) } }) } } func TestHKDFKDFLabeledExpandRFCVectors(t *testing.T) { kdf, err := newKDF(hkdfSHA256) if err != nil { t.Fatalf("newKDF(hkdfSHA256): got err %q, want success", err) } suiteID := hpkeSuiteID(x25519HKDFSHA256, hkdfSHA256, aes128GCM) // Vectors are defined at // https://datatracker.ietf.org/doc/html/rfc5869#appendix-A. var tests = []struct { name string info string prk string length int want string // Generated manually. }{ { name: "basic", info: "f0f1f2f3f4f5f6f7f8f9", prk: "077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5", length: 42, want: "2f1a8eb86971cd1850d04a1b98f9a63d52d56c5a4d5fcb68103e57c7a85a1df2c9be1346ae041007712d", }, { name: "longer inputs", info: "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", prk: "06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244", length: 82, want: "3961afd1985cb4d811e261b3568c44b88ae7e5d5909d33a5419e954eb245fe03fd3635769d88cec8adb709e900fa399e1a68bdb9d5c879e385845eeb99034fd232e30d1acc58f7fa37791fe0c433221b1fec", }, { name: "zero-length info", info: "", prk: "19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04", length: 42, want: "bdb2761a4f8504177b10ecc354f41153a3964435b9072d1f349c2993afbaa77a05ed426c384e195dba76", }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { info, err := hex.DecodeString(test.info) if err != nil { t.Fatal("hex.DecodeString(info) failed") } prk, err := hex.DecodeString(test.prk) if err != nil { t.Fatal("hex.DecodeString(prk) failed") } want, err := hex.DecodeString(test.want) if err != nil { t.Fatal("hex.DecodeString(want) failed") } got, err := kdf.labeledExpand(prk, info, "info_label", suiteID, test.length) if err != nil { t.Errorf("labeledExpand: got err %q, want success", err) } if !bytes.Equal(got, want) { t.Errorf("labeledExpand: got %x, want %x", got, want) } }) } } func TestHKDFKDFExtractAndExpand(t *testing.T) { kdf, err := newKDF(hkdfSHA256) if err != nil { t.Fatalf("newKDF(hkdfSHA256): got err %q, want success", err) } _, v := internetDraftVector(t) dhSharedSecret, err := subtle.ComputeSharedSecretX25519(v.senderPrivKey, v.recipientPubKey) if err != nil { t.Fatalf("ComputeSharedSecretX25519: got err %q, want success", err) } kemCtx := []byte{} kemCtx = append(kemCtx, v.senderPubKey...) kemCtx = append(kemCtx, v.recipientPubKey...) var tests = []struct { length int want []byte wantErr bool }{ {32, v.sharedSecret, false}, {int(math.Pow(2, 16)), nil, true}, } for _, test := range tests { t.Run(fmt.Sprintf("%d", test.length), func(t *testing.T) { sharedSecret, err := kdf.extractAndExpand( emptySalt, dhSharedSecret, "eae_prk", kemCtx, "shared_secret", kemSuiteID(x25519HKDFSHA256), test.length) if test.wantErr { if err == nil { t.Error("extractAndExpand: got success, want err") } return } if err != nil { t.Errorf("extractAndExpand: got err %q, want success", err) } if !bytes.Equal(sharedSecret, v.sharedSecret) { t.Errorf("extractAndExpand: got %x, want %x", sharedSecret, v.sharedSecret) } }) } } ================================================ FILE: go/hybrid/internal/hpke/hpke.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package hpke provides implementations of Hybrid Public Key Encryption. package hpke import ( "encoding/binary" "fmt" ) const ( // All identifier values are specified in // https://www.rfc-editor.org/rfc/rfc9180.html. // Mode identifiers. baseMode uint8 = 0x00 // KEM algorithm identifiers. x25519HKDFSHA256 uint16 = 0x0020 // KDF algorithm identifiers. hkdfSHA256 uint16 = 0x0001 // AEAD algorithm identifiers. aes128GCM uint16 = 0x0001 aes256GCM uint16 = 0x0002 chaCha20Poly1305 uint16 = 0x0003 sha256 = "SHA256" hpkeV1 = "HPKE-v1" ) var ( emptySalt = []byte{} emptyIKM = []byte{} emptyAssociatedData = []byte{} ) // kemSuiteID generates the KEM suite ID from kemID according to // https://www.rfc-editor.org/rfc/rfc9180.html#section-4.1-5. func kemSuiteID(kemID uint16) []byte { return binary.BigEndian.AppendUint16([]byte("KEM"), kemID) } // hpkeSuiteID generates the HPKE suite ID according to // https://www.rfc-editor.org/rfc/rfc9180.html#section-5.1-8. func hpkeSuiteID(kemID, kdfID, aeadID uint16) []byte { // Allocate memory for the return value with the exact amount of bytes needed. res := make([]byte, 0, 4+2+2+2) res = append(res, "HPKE"...) res = binary.BigEndian.AppendUint16(res, kemID) res = binary.BigEndian.AppendUint16(res, kdfID) res = binary.BigEndian.AppendUint16(res, aeadID) return res } // keyScheduleContext creates the key_schedule_context defined at // https://www.rfc-editor.org/rfc/rfc9180.html#section-5.1-10. func keyScheduleContext(mode uint8, pskIDHash, infoHash []byte) []byte { // Allocate memory for the return value with the exact amount of bytes needed. res := make([]byte, 0, 1+len(pskIDHash)+len(infoHash)) res = append(res, mode) res = append(res, pskIDHash...) res = append(res, infoHash...) return res } // labelIKM returns a labeled IKM according to LabeledExtract() defined at // https://www.rfc-editor.org/rfc/rfc9180.html#section-4. func labelIKM(label string, ikm, suiteID []byte) []byte { // Allocate memory for the return value with the exact amount of bytes needed. res := make([]byte, 0, len(hpkeV1)+len(suiteID)+len(label)+len(ikm)) res = append(res, hpkeV1...) res = append(res, suiteID...) res = append(res, label...) res = append(res, ikm...) return res } // labelInfo returns a labeled info according to LabeledExpand() defined at // https://www.rfc-editor.org/rfc/rfc9180.html#section-4. func labelInfo(label string, info, suiteID []byte, length int) ([]byte, error) { length16 := uint16(length) if int(length16) != length { return nil, fmt.Errorf("length %d must be a valid uint16 value", length) } // Allocate memory for the return value with the exact amount of bytes needed. res := make([]byte, 0, 2+len(hpkeV1)+len(suiteID)+len(label)+len(info)) res = binary.BigEndian.AppendUint16(res, length16) res = append(res, hpkeV1...) res = append(res, suiteID...) res = append(res, label...) res = append(res, info...) return res, nil } ================================================ FILE: go/hybrid/internal/hpke/hpke_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hpke import ( "encoding/hex" "encoding/json" "math/big" "os" "path/filepath" "testing" "github.com/google/tink/go/testutil" ) // TODO(b/201070904): Separate tests into internal_test package. // aeadIDs are specified at // https://www.rfc-editor.org/rfc/rfc9180.html#section-7.3. var aeadIDs = []struct { name string aeadID uint16 keyLength int }{ {"AES128GCM", aes128GCM, 16}, {"AES256GCM", aes256GCM, 32}, {"ChaCha20Poly1305", chaCha20Poly1305, 32}, } type hpkeID struct { id int mode uint8 kemID uint16 kdfID uint16 aeadID uint16 } type vector struct { info []byte senderPubKey []byte senderPrivKey []byte recipientPubKey []byte recipientPrivKey []byte encapsulatedKey []byte sharedSecret []byte keyScheduleCtx []byte secret []byte key []byte baseNonce []byte consecutiveEncryptions []encryptionVector otherEncryptions []encryptionVector } type encryptionVector struct { key []byte plaintext []byte associatedData []byte nonce []byte ciphertext []byte sequenceNumber *big.Int } type encryptionString struct { sequenceNumber uint64 plaintext string associatedData string nonce string ciphertext string } // TODO(b/201070904): Include all Tink-supported RFC vectors. func internetDraftVector(t *testing.T) (hpkeID, vector) { t.Helper() // Test vector from HPKE RFC // https://www.rfc-editor.org/rfc/rfc9180.html#appendix-A.1.1. v := struct { mode uint8 kemID, kdfID, aeadID uint16 info, pkEm, skEm, pkRm, skRm, enc, sharedSecret, keyScheduleCtx, secret, key, baseNonce string consecutiveEncryptions, otherEncryptions []encryptionString }{ mode: 0, kemID: 32, kdfID: 1, aeadID: 1, info: "4f6465206f6e2061204772656369616e2055726e", pkEm: "37fda3567bdbd628e88668c3c8d7e97d1d1253b6d4ea6d44c150f741f1bf4431", skEm: "52c4a758a802cd8b936eceea314432798d5baf2d7e9235dc084ab1b9cfa2f736", pkRm: "3948cfe0ad1ddb695d780e59077195da6c56506b027329794ab02bca80815c4d", skRm: "4612c550263fc8ad58375df3f557aac531d26850903e55a9f23f21d8534e8ac8", enc: "37fda3567bdbd628e88668c3c8d7e97d1d1253b6d4ea6d44c150f741f1bf4431", sharedSecret: "fe0e18c9f024ce43799ae393c7e8fe8fce9d218875e8227b0187c04e7d2ea1fc", keyScheduleCtx: "00725611c9d98c07c03f60095cd32d400d8347d45ed67097bbad50fc56da742d07cb6cffde367bb0565ba28bb02c90744a20f5ef37f30523526106f637abb05449", secret: "12fff91991e93b48de37e7daddb52981084bd8aa64289c3788471d9a9712f397", key: "4531685d41d65f03dc48f6b8302c05b0", baseNonce: "56d890e5accaaf011cff4b7d", consecutiveEncryptions: []encryptionString{ { sequenceNumber: 0, plaintext: "4265617574792069732074727574682c20747275746820626561757479", associatedData: "436f756e742d30", nonce: "56d890e5accaaf011cff4b7d", ciphertext: "f938558b5d72f1a23810b4be2ab4f84331acc02fc97babc53a52ae8218a355a96d8770ac83d07bea87e13c512a", }, { sequenceNumber: 1, plaintext: "4265617574792069732074727574682c20747275746820626561757479", associatedData: "436f756e742d31", nonce: "56d890e5accaaf011cff4b7c", ciphertext: "af2d7e9ac9ae7e270f46ba1f975be53c09f8d875bdc8535458c2494e8a6eab251c03d0c22a56b8ca42c2063b84", }, { sequenceNumber: 2, plaintext: "4265617574792069732074727574682c20747275746820626561757479", associatedData: "436f756e742d32", nonce: "56d890e5accaaf011cff4b7f", ciphertext: "498dfcabd92e8acedc281e85af1cb4e3e31c7dc394a1ca20e173cb72516491588d96a19ad4a683518973dcc180", }, }, otherEncryptions: []encryptionString{ { sequenceNumber: 4, plaintext: "4265617574792069732074727574682c20747275746820626561757479", associatedData: "436f756e742d34", nonce: "56d890e5accaaf011cff4b79", ciphertext: "583bd32bc67a5994bb8ceaca813d369bca7b2a42408cddef5e22f880b631215a09fc0012bc69fccaa251c0246d", }, { sequenceNumber: 255, plaintext: "4265617574792069732074727574682c20747275746820626561757479", associatedData: "436f756e742d323535", nonce: "56d890e5accaaf011cff4b82", ciphertext: "7175db9717964058640a3a11fb9007941a5d1757fda1a6935c805c21af32505bf106deefec4a49ac38d71c9e0a", }, { sequenceNumber: 256, plaintext: "4265617574792069732074727574682c20747275746820626561757479", associatedData: "436f756e742d323536", nonce: "56d890e5accaaf011cff4a7d", ciphertext: "957f9800542b0b8891badb026d79cc54597cb2d225b54c00c5238c25d05c30e3fbeda97d2e0e1aba483a2df9f2", }, }, } var info, senderPubKey, senderPrivKey, recipientPubKey, recipientPrivKey, encapsulatedKey, sharedSecret, keyScheduleCtx, secret, key, baseNonce []byte var err error if info, err = hex.DecodeString(v.info); err != nil { t.Fatalf("hex.DecodeString(info): err %q", err) } if senderPubKey, err = hex.DecodeString(v.pkEm); err != nil { t.Fatalf("hex.DecodeString(pkEm): err %q", err) } if senderPrivKey, err = hex.DecodeString(v.skEm); err != nil { t.Fatalf("hex.DecodeString(skEm): err %q", err) } if recipientPubKey, err = hex.DecodeString(v.pkRm); err != nil { t.Fatalf("hex.DecodeString(pkRm): err %q", err) } if recipientPrivKey, err = hex.DecodeString(v.skRm); err != nil { t.Fatalf("hex.DecodeString(skRm): err %q", err) } if encapsulatedKey, err = hex.DecodeString(v.enc); err != nil { t.Fatalf("hex.DecodeString(enc): err %q", err) } if sharedSecret, err = hex.DecodeString(v.sharedSecret); err != nil { t.Fatalf("hex.DecodeString(sharedSecret): err %q", err) } if keyScheduleCtx, err = hex.DecodeString(v.keyScheduleCtx); err != nil { t.Fatalf("hex.DecodeString(keyScheduleCtx): err %q", err) } if secret, err = hex.DecodeString(v.secret); err != nil { t.Fatalf("hex.DecodeString(secret): err %q", err) } if key, err = hex.DecodeString(v.key); err != nil { t.Fatalf("hex.DecodeString(key): err %q", err) } if baseNonce, err = hex.DecodeString(v.baseNonce); err != nil { t.Fatalf("hex.DecodeString(baseNonce): err %q", err) } return hpkeID{0 /*=id */, v.mode, v.kemID, v.kdfID, v.aeadID}, vector{ info: info, senderPubKey: senderPubKey, senderPrivKey: senderPrivKey, recipientPubKey: recipientPubKey, recipientPrivKey: recipientPrivKey, encapsulatedKey: encapsulatedKey, sharedSecret: sharedSecret, keyScheduleCtx: keyScheduleCtx, secret: secret, key: key, baseNonce: baseNonce, consecutiveEncryptions: parseEncryptions(t, v.consecutiveEncryptions), otherEncryptions: parseEncryptions(t, v.otherEncryptions), } } func parseEncryptions(t *testing.T, encs []encryptionString) []encryptionVector { t.Helper() var res []encryptionVector for _, e := range encs { var plaintext, associatedData, nonce, ciphertext []byte var err error if plaintext, err = hex.DecodeString(e.plaintext); err != nil { t.Fatalf("hex.DecodeString(plaintext): err %q", err) } if associatedData, err = hex.DecodeString(e.associatedData); err != nil { t.Fatalf("hex.DecodeString(associatedData): err %q", err) } if nonce, err = hex.DecodeString(e.nonce); err != nil { t.Fatalf("hex.DecodeString(nonce): err %q", err) } if ciphertext, err = hex.DecodeString(e.ciphertext); err != nil { t.Fatalf("hex.DecodeString(ciphertext): err %q", err) } res = append(res, encryptionVector{ plaintext: plaintext, associatedData: associatedData, nonce: nonce, ciphertext: ciphertext, sequenceNumber: big.NewInt(int64(e.sequenceNumber)), }) } return res } // aeadRFCVectors returns RFC test vectors for AEAD IDs aes128GCM, aes256GCM, // and chaCha20Poly1305. func aeadRFCVectors(t *testing.T) map[hpkeID]encryptionVector { t.Helper() vecs := []struct { mode uint8 kemID, kdfID, aeadID uint16 key, plaintext, associatedData, nonce, ciphertext string }{ // https://www.rfc-editor.org/rfc/rfc9180.html#appendix-A.1.1.1 { mode: 0, kemID: 32, kdfID: 1, aeadID: 1, key: "4531685d41d65f03dc48f6b8302c05b0", plaintext: "4265617574792069732074727574682c20747275746820626561757479", associatedData: "436f756e742d30", nonce: "56d890e5accaaf011cff4b7d", ciphertext: "f938558b5d72f1a23810b4be2ab4f84331acc02fc97babc53a52ae8218a355a96d8770ac83d07bea87e13c512a", }, { mode: 0, kemID: 32, kdfID: 1, aeadID: 1, key: "4531685d41d65f03dc48f6b8302c05b0", plaintext: "4265617574792069732074727574682c20747275746820626561757479", associatedData: "436f756e742d31", nonce: "56d890e5accaaf011cff4b7c", ciphertext: "af2d7e9ac9ae7e270f46ba1f975be53c09f8d875bdc8535458c2494e8a6eab251c03d0c22a56b8ca42c2063b84", }, // https://www.rfc-editor.org/rfc/rfc9180.html#appendix-A.6.1.1 { mode: 0, kemID: 18, kdfID: 3, aeadID: 2, key: "751e346ce8f0ddb2305c8a2a85c70d5cf559c53093656be636b9406d4d7d1b70", plaintext: "4265617574792069732074727574682c20747275746820626561757479", associatedData: "436f756e742d30", nonce: "55ff7a7d739c69f44b25447b", ciphertext: "170f8beddfe949b75ef9c387e201baf4132fa7374593dfafa90768788b7b2b200aafcc6d80ea4c795a7c5b841a", }, { mode: 0, kemID: 18, kdfID: 3, aeadID: 2, key: "751e346ce8f0ddb2305c8a2a85c70d5cf559c53093656be636b9406d4d7d1b70", plaintext: "4265617574792069732074727574682c20747275746820626561757479", associatedData: "436f756e742d31", nonce: "55ff7a7d739c69f44b25447a", ciphertext: "d9ee248e220ca24ac00bbbe7e221a832e4f7fa64c4fbab3945b6f3af0c5ecd5e16815b328be4954a05fd352256", }, // https://www.rfc-editor.org/rfc/rfc9180.html#appendix-A.2.1.1 { mode: 0, kemID: 32, kdfID: 1, aeadID: 3, key: "ad2744de8e17f4ebba575b3f5f5a8fa1f69c2a07f6e7500bc60ca6e3e3ec1c91", plaintext: "4265617574792069732074727574682c20747275746820626561757479", associatedData: "436f756e742d30", nonce: "5c4d98150661b848853b547f", ciphertext: "1c5250d8034ec2b784ba2cfd69dbdb8af406cfe3ff938e131f0def8c8b60b4db21993c62ce81883d2dd1b51a28", }, { mode: 0, kemID: 32, kdfID: 1, aeadID: 3, key: "ad2744de8e17f4ebba575b3f5f5a8fa1f69c2a07f6e7500bc60ca6e3e3ec1c91", plaintext: "4265617574792069732074727574682c20747275746820626561757479", associatedData: "436f756e742d31", nonce: "5c4d98150661b848853b547e", ciphertext: "6b53c051e4199c518de79594e1c4ab18b96f081549d45ce015be002090bb119e85285337cc95ba5f59992dc98c", }, } m := make(map[hpkeID]encryptionVector) for i, v := range vecs { var key, plaintext, associatedData, nonce, ciphertext []byte var err error if key, err = hex.DecodeString(v.key); err != nil { t.Fatalf("hex.DecodeString(key): err %q", err) } if plaintext, err = hex.DecodeString(v.plaintext); err != nil { t.Fatalf("hex.DecodeString(plaintext): err %q", err) } if associatedData, err = hex.DecodeString(v.associatedData); err != nil { t.Fatalf("hex.DecodeString(associatedData): err %q", err) } if nonce, err = hex.DecodeString(v.nonce); err != nil { t.Fatalf("hex.DecodeString(nonce): err %q", err) } if ciphertext, err = hex.DecodeString(v.ciphertext); err != nil { t.Fatalf("hex.DecodeString(ciphertext): err %q", err) } id := hpkeID{i, v.mode, v.kemID, v.kdfID, v.aeadID} m[id] = encryptionVector{ key: key, plaintext: plaintext, associatedData: associatedData, nonce: nonce, ciphertext: ciphertext, } } return m } // baseModeX25519HKDFSHA256Vectors returns BoringSSL test vectors for HPKE base // mode with Diffie-Hellman-based X25519, HKDF-SHA256 KEM as per // https://www.rfc-editor.org/rfc/rfc9180.html#section-7.1. func baseModeX25519HKDFSHA256Vectors(t *testing.T) map[hpkeID]vector { testutil.SkipTestIfTestSrcDirIsNotSet(t) t.Helper() srcDir, ok := os.LookupEnv("TEST_SRCDIR") if !ok { t.Fatal("TEST_SRCDIR not set") } path := filepath.Join(srcDir, os.Getenv("TEST_WORKSPACE"), "/testdata/testvectors/hpke_boringssl.json") f, err := os.Open(path) if err != nil { t.Fatal(err) } var vecs []struct { Mode uint8 `json:"mode"` KEMID uint16 `json:"kem_id"` KDFID uint16 `json:"kdf_id"` AEADID uint16 `json:"aead_id"` Info testutil.HexBytes `json:"info"` SenderPubKey testutil.HexBytes `json:"pkEm"` SenderPrivKey testutil.HexBytes `json:"skEm"` RecipientPubKey testutil.HexBytes `json:"pkRm"` RecipientPrivKey testutil.HexBytes `json:"skRm"` EncapsulatedKey testutil.HexBytes `json:"enc"` SharedSecret testutil.HexBytes `json:"shared_secret"` KeyScheduleCtx testutil.HexBytes `json:"key_schedule_context"` Secret testutil.HexBytes `json:"secret"` Key testutil.HexBytes `json:"key"` BaseNonce testutil.HexBytes `json:"base_nonce"` } parser := json.NewDecoder(f) if err := parser.Decode(&vecs); err != nil { t.Fatal(err) } m := make(map[hpkeID]vector) for i, v := range vecs { if v.Mode != baseMode || v.KEMID != x25519HKDFSHA256 { continue } id := hpkeID{i, v.Mode, v.KEMID, v.KDFID, v.AEADID} m[id] = vector{ info: v.Info, senderPubKey: v.SenderPubKey, senderPrivKey: v.SenderPrivKey, recipientPubKey: v.RecipientPubKey, recipientPrivKey: v.RecipientPrivKey, encapsulatedKey: v.EncapsulatedKey, sharedSecret: v.SharedSecret, keyScheduleCtx: v.KeyScheduleCtx, secret: v.Secret, key: v.Key, baseNonce: v.BaseNonce, } } return m } func TestHpkeSuiteIDMemoryAllocatedIsExact(t *testing.T) { suiteID := hpkeSuiteID(1, 2, 3) if len(suiteID) != cap(suiteID) { t.Errorf("want len(suiteID) == cap(suiteID), got %d != %d", len(suiteID), cap(suiteID)) } } func TestKeyScheduleContextMemoryAllocatedIsExact(t *testing.T) { context := keyScheduleContext(1, []byte{1, 2, 3}, []byte{1, 2, 3, 4, 5}) if len(context) != cap(context) { t.Errorf("want len(context) == cap(context), got %d != %d", len(context), cap(context)) } } func TestLabelIKMMemoryAllocatedIsExact(t *testing.T) { ikm := labelIKM("abcde", []byte{1, 2, 3}, []byte{1, 2, 3, 4, 5}) if len(ikm) != cap(ikm) { t.Errorf("want len(ikm) == cap(ikm), got %d != %d", len(ikm), cap(ikm)) } } func TestLabelInfoMemoryAllocatedIsExact(t *testing.T) { info, err := labelInfo("abcde", []byte{1, 2, 3}, []byte{1, 2, 3, 4, 5}, 42) if err != nil { t.Errorf("labelInfo() err = %v, want nil", err) } if len(info) != cap(info) { t.Errorf("want len(info) == cap(info), got %d != %d", len(info), cap(info)) } } ================================================ FILE: go/hybrid/internal/hpke/kdf.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hpke // kdf is a package-internal interface for the Hybrid Public Key Encryption // (HPKE) key derivation function (KDF). // // The HPKE RFC is available at // https://www.rfc-editor.org/rfc/rfc9180.html. type kdf interface { // labeledExtract extracts a pseudorandom key from salt, ikm using the // HPKE-specified values suiteID, ikmLabel to facilitate domain separation // and context binding. // // https://www.rfc-editor.org/rfc/rfc9180.html#section-4-9 labeledExtract(salt, ikm []byte, ikmLabel string, suiteID []byte) []byte // labeledExpand expands the pseudorandom key prk into length pseudorandom // bytes using info with other HPKE-specific values infoLabel, suiteID to // facilitate domain separation and context binding. // // https://www.rfc-editor.org/rfc/rfc9180.html#section-4-9 labeledExpand(prk, info []byte, infoLabel string, suiteID []byte, length int) ([]byte, error) // extractAndExpand calls labeledExtract and labeledExpand in order. // // https://www.rfc-editor.org/rfc/rfc9180.html#section-4.1-3 extractAndExpand(salt, ikm []byte, ikmLabel string, info []byte, infoLabel string, suiteID []byte, length int) ([]byte, error) // id returns the HPKE KDF algorithm identifier for the underlying KDF // implementation. // // https://www.rfc-editor.org/rfc/rfc9180.html#section-7.2 id() uint16 } ================================================ FILE: go/hybrid/internal/hpke/kem.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hpke // kem is a package-internal interface for the Hybrid Public Key Encryption // (HPKE) key encapsulation mechanism (KEM). // // The HPKE RFC is available at // https://www.rfc-editor.org/rfc/rfc9180.html. type kem interface { // encapsulate generates and encapsulates a shared secret using // recipientPubKey. It returns the raw shared secret and encapsulated key. // The HPKE RFC refers to this function as Encap(). It is used by the sender. encapsulate(recipientPubKey []byte) ([]byte, []byte, error) // decapsulate extracts the shared secret from encapsulatedKey using // recipientPrivKey. It returns the raw shared secret. The HPKE RFC refers // to this function as Decap(). It is used by the recipient. decapsulate(encapsulatedKey, recipientPrivKey []byte) ([]byte, error) // id returns the HPKE KEM algorithm identifier for the underlying KEM // implementation. // // https://www.rfc-editor.org/rfc/rfc9180.html#section-7.1 id() uint16 // encapsulatedKeyLength returns the length of the encapsulated key, // corresponding to Nenc in the following table. // // https://www.rfc-editor.org/rfc/rfc9180.html#section-7.1 encapsulatedKeyLength() int } ================================================ FILE: go/hybrid/internal/hpke/primitive_factory.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hpke import ( "fmt" pb "github.com/google/tink/go/proto/hpke_go_proto" ) // newPrimitivesFromProto constructs new KEM, KDF, AEADs from HpkeParams. func newPrimitivesFromProto(params *pb.HpkeParams) (kem, kdf, aead, error) { kemID, err := kemIDFromProto(params.GetKem()) if err != nil { return nil, nil, nil, fmt.Errorf("kemIDFromProto(%d): %v", params.GetKem(), err) } kem, err := newKEM(kemID) if err != nil { return nil, nil, nil, fmt.Errorf("newKEM(%d): %v", kemID, err) } kdfID, err := kdfIDFromProto(params.GetKdf()) if err != nil { return nil, nil, nil, fmt.Errorf("kdfIDFromProto(%d): %v", params.GetKdf(), err) } kdf, err := newKDF(kdfID) if err != nil { return nil, nil, nil, fmt.Errorf("newKDF(%d): %v", kdfID, err) } aeadID, err := aeadIDFromProto(params.GetAead()) if err != nil { return nil, nil, nil, fmt.Errorf("aeadIDFromProto(%d): %v", params.GetAead(), err) } aead, err := newAEAD(aeadID) if err != nil { return nil, nil, nil, fmt.Errorf("newAEAD(%d): %v", aeadID, err) } return kem, kdf, aead, nil } // newKEM constructs a HPKE KEM using kemID, which are specified at // https://www.rfc-editor.org/rfc/rfc9180.html#section-7.1. func newKEM(kemID uint16) (kem, error) { if kemID == x25519HKDFSHA256 { return newX25519KEM(sha256) } return nil, fmt.Errorf("KEM ID %d is not supported", kemID) } // kemIDFromProto returns the KEM ID from the HpkeKem enum value. KEM IDs are // specified at // https://www.rfc-editor.org/rfc/rfc9180.html#section-7.1. func kemIDFromProto(enum pb.HpkeKem) (uint16, error) { if enum == pb.HpkeKem_DHKEM_X25519_HKDF_SHA256 { return x25519HKDFSHA256, nil } return 0, fmt.Errorf("HpkeKem enum value %d is not supported", enum) } // newKDF constructs a HPKE KDF using kdfID, which are specified at // https://www.rfc-editor.org/rfc/rfc9180.html#section-7.2. func newKDF(kdfID uint16) (kdf, error) { if kdfID == hkdfSHA256 { return newHKDFKDF(sha256) } return nil, fmt.Errorf("KDF ID %d is not supported", kdfID) } // kdfIDFromProto returns the KDF ID from the HpkeKdf enum value. KDF IDs are // specified at // https://www.rfc-editor.org/rfc/rfc9180.html#section-7.2. func kdfIDFromProto(enum pb.HpkeKdf) (uint16, error) { if enum == pb.HpkeKdf_HKDF_SHA256 { return hkdfSHA256, nil } return 0, fmt.Errorf("HpkeKdf enum value %d is not supported", enum) } // newAEAD constructs a HPKE AEAD using aeadID, which are specified at // https://www.rfc-editor.org/rfc/rfc9180.html#section-7.3. func newAEAD(aeadID uint16) (aead, error) { switch aeadID { case aes128GCM: return newAESGCMAEAD(16) case aes256GCM: return newAESGCMAEAD(32) case chaCha20Poly1305: return &chaCha20Poly1305AEAD{}, nil default: return nil, fmt.Errorf("AEAD ID %d is not supported", aeadID) } } // aeadIDFromProto returns the AEAD ID from the HpkeAead enum value. AEAD IDs // are specified at // https://www.rfc-editor.org/rfc/rfc9180.html#section-7.3. func aeadIDFromProto(enum pb.HpkeAead) (uint16, error) { switch enum { case pb.HpkeAead_AES_128_GCM: return aes128GCM, nil case pb.HpkeAead_AES_256_GCM: return aes256GCM, nil case pb.HpkeAead_CHACHA20_POLY1305: return chaCha20Poly1305, nil default: return 0, fmt.Errorf("HpkeAead enum value %d is not supported", enum) } } ================================================ FILE: go/hybrid/internal/hpke/primitive_factory_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hpke import ( "testing" pb "github.com/google/tink/go/proto/hpke_go_proto" ) func TestNewKEM(t *testing.T) { kemID, err := kemIDFromProto(pb.HpkeKem_DHKEM_X25519_HKDF_SHA256) if err != nil { t.Fatal(err) } if kemID != x25519HKDFSHA256 { t.Errorf("kemID: got %d, want %d", kemID, x25519HKDFSHA256) } kem, err := newKEM(kemID) if err != nil { t.Fatal(err) } if kem.id() != x25519HKDFSHA256 { t.Errorf("id: got %d, want %d", kem.id(), x25519HKDFSHA256) } } func TestNewKEMUnsupportedID(t *testing.T) { if _, err := newKEM(0x0010 /*= DHKEM(P-256, HKDF-SHA256)*/); err == nil { t.Fatal("newKEM(unsupported ID): got success, want err") } } func TestKEMIDFromProtoUnsupportedID(t *testing.T) { if _, err := kemIDFromProto(pb.HpkeKem_KEM_UNKNOWN); err == nil { t.Fatal("kemIDFromProto(unsupported ID): got success, want err") } } func TestNewKDF(t *testing.T) { kdfID, err := kdfIDFromProto(pb.HpkeKdf_HKDF_SHA256) if err != nil { t.Fatal(err) } if kdfID != hkdfSHA256 { t.Errorf("kdfID: got %d, want %d", kdfID, hkdfSHA256) } kdf, err := newKDF(kdfID) if err != nil { t.Fatal(err) } if kdf.id() != hkdfSHA256 { t.Errorf("id: got %d, want %d", kdf.id(), hkdfSHA256) } } func TestNewKDFUnsupportedID(t *testing.T) { if _, err := newKDF(0x0002 /*= HKDF-SHA384*/); err == nil { t.Fatal("newKDF(unsupported ID): got success, want err") } } func TestKDFIDFromProtoUnsupportedID(t *testing.T) { if _, err := kdfIDFromProto(pb.HpkeKdf_KDF_UNKNOWN); err == nil { t.Fatal("kdfIDFromProto(unsupported ID): got success, want err") } } var aeads = []struct { name string proto pb.HpkeAead id uint16 }{ {"AES-128-GCM", pb.HpkeAead_AES_128_GCM, aes128GCM}, {"AES-256-GCM", pb.HpkeAead_AES_256_GCM, aes256GCM}, {"ChaCha20Poly1305", pb.HpkeAead_CHACHA20_POLY1305, chaCha20Poly1305}, } func TestNewAEAD(t *testing.T) { for _, a := range aeads { t.Run(a.name, func(t *testing.T) { aeadID, err := aeadIDFromProto(a.proto) if err != nil { t.Fatal(err) } if aeadID != a.id { t.Errorf("aeadID: got %d, want %d", aeadID, a.id) } aead, err := newAEAD(aeadID) if err != nil { t.Fatal(err) } if aead.id() != a.id { t.Errorf("id: got %d, want %d", aead.id(), a.id) } }) } } func TestNewAEADUnsupportedID(t *testing.T) { if _, err := newAEAD(0xFFFF /*= Export-only*/); err == nil { t.Fatal("newAEAD(unsupported ID): got success, want err") } } func TestAEADIDFromProtoUnsupportedID(t *testing.T) { if _, err := aeadIDFromProto(pb.HpkeAead_AEAD_UNKNOWN); err == nil { t.Fatal("aeadIDFromProto(unsupported ID): got success, want err") } } func TestNewPrimitivesFromProto(t *testing.T) { for _, a := range aeads { t.Run("", func(t *testing.T) { params := &pb.HpkeParams{ Kem: pb.HpkeKem_DHKEM_X25519_HKDF_SHA256, Kdf: pb.HpkeKdf_HKDF_SHA256, Aead: a.proto, } kem, kdf, aead, err := newPrimitivesFromProto(params) if err != nil { t.Fatalf("newPrimitivesFromProto: %v", err) } if kem.id() != x25519HKDFSHA256 { t.Errorf("kem.id: got %d, want %d", kem.id(), x25519HKDFSHA256) } if kdf.id() != hkdfSHA256 { t.Errorf("kdf.id: got %d, want %d", kdf.id(), hkdfSHA256) } if aead.id() != a.id { t.Errorf("aead.id: got %d, want %d", aead.id(), a.id) } }) } } func TestNewPrimitivesFromProtoUnsupportedID(t *testing.T) { tests := []struct { name string params *pb.HpkeParams }{ { "KEM", &pb.HpkeParams{ Kem: pb.HpkeKem_KEM_UNKNOWN, Kdf: pb.HpkeKdf_HKDF_SHA256, Aead: pb.HpkeAead_AES_256_GCM, }, }, {"KDF", &pb.HpkeParams{ Kem: pb.HpkeKem_DHKEM_X25519_HKDF_SHA256, Kdf: pb.HpkeKdf_KDF_UNKNOWN, Aead: pb.HpkeAead_AES_256_GCM, }, }, {"AEAD", &pb.HpkeParams{ Kem: pb.HpkeKem_DHKEM_X25519_HKDF_SHA256, Kdf: pb.HpkeKdf_HKDF_SHA256, Aead: pb.HpkeAead_AEAD_UNKNOWN, }, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { if _, _, _, err := newPrimitivesFromProto(test.params); err == nil { t.Error("newPrimitivesFromProto: got success, want err") } }) } } ================================================ FILE: go/hybrid/internal/hpke/x25519_kem.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hpke import ( "fmt" "github.com/google/tink/go/subtle" ) var ( x25519KEMGeneratePrivateKey = subtle.GeneratePrivateKeyX25519 x25519KEMPublicFromPrivate = subtle.PublicFromPrivateX25519 ) // x25519KEM is a Diffie-Hellman-based X25519 HPKE KEM variant that implements // interface kem. type x25519KEM struct { // HPKE KEM algorithm identifier. kemID uint16 macAlg string } var _ kem = (*x25519KEM)(nil) // newX25519KEM constructs a X25519 HPKE KEM using macAlg. func newX25519KEM(macAlg string) (*x25519KEM, error) { if macAlg == sha256 { return &x25519KEM{kemID: x25519HKDFSHA256, macAlg: sha256}, nil } return nil, fmt.Errorf("MAC algorithm %s is not supported", macAlg) } func (x *x25519KEM) encapsulate(recipientPubKey []byte) (sharedSecret, senderPubKey []byte, err error) { senderPrivKey, err := x25519KEMGeneratePrivateKey() if err != nil { return nil, nil, err } dh, err := subtle.ComputeSharedSecretX25519(senderPrivKey, recipientPubKey) if err != nil { return nil, nil, err } senderPubKey, err = x25519KEMPublicFromPrivate(senderPrivKey) if err != nil { return nil, nil, err } sharedSecret, err = x.deriveKEMSharedSecret(dh, senderPubKey, recipientPubKey) if err != nil { return nil, nil, err } return sharedSecret, senderPubKey, nil } func (x *x25519KEM) decapsulate(encapsulatedKey, recipientPrivKey []byte) ([]byte, error) { dh, err := subtle.ComputeSharedSecretX25519(recipientPrivKey, encapsulatedKey) if err != nil { return nil, err } recipientPubKey, err := x25519KEMPublicFromPrivate(recipientPrivKey) if err != nil { return nil, err } return x.deriveKEMSharedSecret(dh, encapsulatedKey, recipientPubKey) } func (x *x25519KEM) id() uint16 { return x.kemID } func (x *x25519KEM) encapsulatedKeyLength() int { return 32 } // deriveKEMSharedSecret returns a pseudorandom key obtained via HKDF SHA256. func (x *x25519KEM) deriveKEMSharedSecret(dh, senderPubKey, recipientPubKey []byte) ([]byte, error) { ctx := make([]byte, 0, len(senderPubKey)+len(recipientPubKey)) ctx = append(ctx, senderPubKey...) ctx = append(ctx, recipientPubKey...) suiteID := kemSuiteID(x25519HKDFSHA256) macLength, err := subtle.GetHashDigestSize(x.macAlg) if err != nil { return nil, err } hkdfKDF, err := newHKDFKDF(x.macAlg) if err != nil { return nil, err } return hkdfKDF.extractAndExpand( nil, /*=salt*/ dh, "eae_prk", ctx, "shared_secret", suiteID, int(macLength)) } ================================================ FILE: go/hybrid/internal/hpke/x25519_kem_test.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hpke import ( "bytes" "errors" "fmt" "testing" "github.com/google/tink/go/subtle" ) // TODO(b/201070904): Write tests using internetDraftVector. func TestX25519KEMEncapsulateBoringSSLVectors(t *testing.T) { i := 0 vecs := baseModeX25519HKDFSHA256Vectors(t) for key, vec := range vecs { if key.mode != baseMode || key.kemID != x25519HKDFSHA256 || key.kdfID != hkdfSHA256 || (key.aeadID != aes128GCM && key.aeadID != aes256GCM && key.aeadID != chaCha20Poly1305) { continue } i++ t.Run(fmt.Sprintf("%d", key.id), func(t *testing.T) { kem, err := newKEM(x25519HKDFSHA256) if err != nil { t.Fatal(err) } x25519KEMGeneratePrivateKey = func() ([]byte, error) { return vec.senderPrivKey, nil } secret, enc, err := kem.encapsulate(vec.recipientPubKey) if err != nil { t.Errorf("encapsulate for vector %v: got err %q, want success", key, err) } if !bytes.Equal(secret, vec.sharedSecret) { t.Errorf("encapsulate for vector %v: got shared secret %v, want %v", key, secret, vec.sharedSecret) } if !bytes.Equal(enc, vec.encapsulatedKey) { t.Errorf("encapsulate for vector %v: got encapsulated key %v, want %v", key, enc, vec.encapsulatedKey) } }) } x25519KEMGeneratePrivateKey = subtle.GeneratePrivateKeyX25519 if i < 2 { t.Errorf("number of vectors tested = %d, want > %d", i, 2) } } func TestX25519KEMEncapsulateBadRecipientPubKey(t *testing.T) { _, v := internetDraftVector(t) kem, err := newKEM(x25519HKDFSHA256) if err != nil { t.Fatal(err) } badRecipientPubKey := append(v.recipientPubKey, []byte("hello")...) if _, _, err := kem.encapsulate(badRecipientPubKey); err == nil { t.Error("encapsulate: got success, want err") } } func TestX25519KEMEncapsulateBadSenderPrivKey(t *testing.T) { _, v := internetDraftVector(t) kem, err := newKEM(x25519HKDFSHA256) if err != nil { t.Fatal(err) } x25519KEMPublicFromPrivate = func(privKey []byte) ([]byte, error) { return nil, errors.New("failed to compute public key") } if _, _, err := kem.encapsulate(v.recipientPubKey); err == nil { t.Error("encapsulate: got success, want err") } x25519KEMPublicFromPrivate = subtle.PublicFromPrivateX25519 } func TestX25519KEMDecapsulateBoringSSLVectors(t *testing.T) { i := 0 vecs := baseModeX25519HKDFSHA256Vectors(t) for key, vec := range vecs { if key.mode != baseMode || key.kemID != x25519HKDFSHA256 || key.kdfID != hkdfSHA256 || (key.aeadID != aes128GCM && key.aeadID != aes256GCM && key.aeadID != chaCha20Poly1305) { continue } i++ t.Run(fmt.Sprintf("%d", key.id), func(t *testing.T) { kem, err := newKEM(x25519HKDFSHA256) if err != nil { t.Fatal(err) } secret, err := kem.decapsulate(vec.encapsulatedKey, vec.recipientPrivKey) if err != nil { t.Errorf("decapsulate for vector %v: got err %q, want success", key, err) } if !bytes.Equal(secret, vec.sharedSecret) { t.Errorf("decapsulate for vector %v: got shared secret %v, want %v", key, secret, vec.sharedSecret) } }) } if i < 2 { t.Errorf("number of vectors tested = %d, want > %d", i, 2) } } // TestX25519KEMDecapsulateEncapsulatedKeyPrefixesLargerSlice checks--if the // encapsulated key is part of a larger slice, as in HPKE Encrypt // https://github.com/google/tink/blob/619b6c1bb1f8573ca56de50cfc6ba23d355670db/go/hybrid/hpke/encrypt.go#L61 // --that decapsulate does not modify the larger slice. func TestX25519KEMDecapsulateEncapsulatedKeyPrefixesLargerSlice(t *testing.T) { _, v := internetDraftVector(t) kem, err := newKEM(x25519HKDFSHA256) if err != nil { t.Fatal(err) } largerSlice := make([]byte, 3*len(v.encapsulatedKey)) suffix := largerSlice[len(v.encapsulatedKey):] zeroedSlice := make([]byte, len(suffix)) if !bytes.Equal(suffix, zeroedSlice) { t.Errorf("suffix: got %x, want %x", suffix, zeroedSlice) } copy(largerSlice, v.encapsulatedKey) if !bytes.Equal(suffix, zeroedSlice) { t.Errorf("suffix: got %x, want %x", suffix, zeroedSlice) } encapsulatedKey := largerSlice[:len(v.encapsulatedKey)] if _, err := kem.decapsulate(encapsulatedKey, v.recipientPrivKey); err != nil { t.Errorf("decapsulate: got err %q, want success", err) } if !bytes.Equal(suffix, zeroedSlice) { t.Errorf("suffix: got %x, want %x", suffix, zeroedSlice) } } func TestX25519KEMDecapsulateBadEncapsulatedKey(t *testing.T) { _, v := internetDraftVector(t) kem, err := newKEM(x25519HKDFSHA256) if err != nil { t.Fatal(err) } badEncapsulatedKey := append(v.encapsulatedKey, []byte("hello")...) if _, err := kem.decapsulate(badEncapsulatedKey, v.recipientPrivKey); err == nil { t.Error("decapsulate: got success, want err") } } func TestX25519KEMDecapsulateBadRecipientPrivKey(t *testing.T) { _, v := internetDraftVector(t) kem, err := newKEM(x25519HKDFSHA256) if err != nil { t.Fatal(err) } badRecipientPrivKey := append(v.recipientPrivKey, []byte("hello")...) if _, err := kem.decapsulate(v.encapsulatedKey, badRecipientPrivKey); err == nil { t.Error("decapsulate: got success, want err") } } func TestX25519KEMEncapsulatedKeyLength(t *testing.T) { kem, err := newKEM(x25519HKDFSHA256) if err != nil { t.Fatal(err) } if kem.encapsulatedKeyLength() != 32 { t.Errorf("encapsulatedKeyLength: got %d, want 32", kem.encapsulatedKeyLength()) } } ================================================ FILE: go/hybrid/subtle/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep go_library( name = "subtle", srcs = [ "ecies_aead_hkdf_dem_helper.go", "ecies_aead_hkdf_hybrid_decrypt.go", "ecies_aead_hkdf_hybrid_encrypt.go", "ecies_hkdf_recipient_kem.go", "ecies_hkdf_sender_kem.go", "elliptic_curves.go", "public_key.go", "subtle.go", ], importpath = "github.com/google/tink/go/hybrid/subtle", visibility = ["//visibility:public"], # keep; used by non-Tink library deps = [ "//keyset", "//proto/hpke_go_proto", "//proto/tink_go_proto", "//subtle", "//tink", "@org_golang_google_protobuf//proto", ], ) go_test( name = "subtle_test", srcs = [ "elliptic_curves_test.go", "public_key_test.go", "subtle_test.go", ], data = [ "//testdata/testvectors:ecdh", "//testdata/testvectors:ecdh_ecpoint", ], deps = [ ":subtle", "//hybrid", "//keyset", "//proto/hpke_go_proto", "//proto/tink_go_proto", "//subtle/random", "//testutil", "@org_golang_google_protobuf//proto", ], ) alias( name = "go_default_library", actual = ":subtle", visibility = ["//visibility:public"], # keep; used by non-Tink library ) ================================================ FILE: go/hybrid/subtle/ecies_aead_hkdf_dem_helper.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle // EciesAEADHKDFDEMHelper a helper for DEM (data encapsulation mechanism) of ECIES-AEAD-HKDF. type EciesAEADHKDFDEMHelper interface { // GetSymmetricKeySize gives the size of the DEM-key in bytes GetSymmetricKeySize() uint32 // GetAEADOrDAEAD returns the newly created AEAD or Deterministic Aead primitive. GetAEADOrDAEAD(symmetricKeyValue []byte) (any, error) } ================================================ FILE: go/hybrid/subtle/ecies_aead_hkdf_hybrid_decrypt.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "errors" "github.com/google/tink/go/tink" ) // ECIESAEADHKDFHybridDecrypt is an instance of ECIES decryption with HKDF-KEM (key encapsulation mechanism) // and AEAD-DEM (data encapsulation mechanism). type ECIESAEADHKDFHybridDecrypt struct { privateKey *ECPrivateKey hkdfSalt []byte hkdfHMACAlgo string pointFormat string demHelper EciesAEADHKDFDEMHelper } // NewECIESAEADHKDFHybridDecrypt returns ECIES decryption construct with HKDF-KEM (key encapsulation mechanism) // and AEAD-DEM (data encapsulation mechanism). func NewECIESAEADHKDFHybridDecrypt(pvt *ECPrivateKey, hkdfSalt []byte, hkdfHMACAlgo string, ptFormat string, demHelper EciesAEADHKDFDEMHelper) (*ECIESAEADHKDFHybridDecrypt, error) { return &ECIESAEADHKDFHybridDecrypt{ privateKey: pvt, hkdfSalt: hkdfSalt, hkdfHMACAlgo: hkdfHMACAlgo, pointFormat: ptFormat, demHelper: demHelper, }, nil } // Decrypt is used to decrypt using ECIES with a HKDF-KEM and AEAD-DEM mechanisms. func (e *ECIESAEADHKDFHybridDecrypt) Decrypt(ciphertext, contextInfo []byte) ([]byte, error) { curve := e.privateKey.PublicKey.Curve headerSize, err := encodingSizeInBytes(curve, e.pointFormat) if err != nil { return nil, err } if len(ciphertext) < headerSize { return nil, errors.New("ciphertext too short") } var kemBytes = make([]byte, headerSize) var ct = make([]byte, len(ciphertext)-headerSize) copy(kemBytes, ciphertext[:headerSize]) copy(ct, ciphertext[headerSize:]) rKem := &ECIESHKDFRecipientKem{ recipientPrivateKey: e.privateKey, } symmetricKey, err := rKem.decapsulate(kemBytes, e.hkdfHMACAlgo, e.hkdfSalt, contextInfo, e.demHelper.GetSymmetricKeySize(), e.pointFormat) if err != nil { return nil, err } prim, err := e.demHelper.GetAEADOrDAEAD(symmetricKey) if err != nil { return nil, err } switch a := prim.(type) { case tink.AEAD: return a.Decrypt(ct, []byte{}) case tink.DeterministicAEAD: return a.DecryptDeterministically(ct, []byte{}) default: return nil, errors.New("Internal error: unexpected primitive type") } } ================================================ FILE: go/hybrid/subtle/ecies_aead_hkdf_hybrid_encrypt.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "bytes" "errors" "github.com/google/tink/go/tink" ) // ECIESAEADHKDFHybridEncrypt is an instance of ECIES encryption with HKDF-KEM (key encapsulation mechanism) // and AEAD-DEM (data encapsulation mechanism). type ECIESAEADHKDFHybridEncrypt struct { publicKey *ECPublicKey hkdfSalt []byte hkdfHMACAlgo string pointFormat string demHelper EciesAEADHKDFDEMHelper } // NewECIESAEADHKDFHybridEncrypt returns ECIES encryption construct with HKDF-KEM (key encapsulation mechanism) // and AEAD-DEM (data encapsulation mechanism). func NewECIESAEADHKDFHybridEncrypt(pub *ECPublicKey, hkdfSalt []byte, hkdfHMACAlgo string, ptFormat string, demHelper EciesAEADHKDFDEMHelper) (*ECIESAEADHKDFHybridEncrypt, error) { c, err := GetCurve(pub.Curve.Params().Name) if err != nil { return nil, err } return &ECIESAEADHKDFHybridEncrypt{ publicKey: &ECPublicKey{ Curve: c, Point: pub.Point, }, hkdfSalt: hkdfSalt, hkdfHMACAlgo: hkdfHMACAlgo, pointFormat: ptFormat, demHelper: demHelper, }, nil } // Encrypt is used to encrypt using ECIES with a HKDF-KEM and AEAD-DEM mechanisms. func (e *ECIESAEADHKDFHybridEncrypt) Encrypt(plaintext, contextInfo []byte) ([]byte, error) { var b bytes.Buffer sKem := &ECIESHKDFSenderKem{ recipientPublicKey: e.publicKey, } kemKey, err := sKem.encapsulate(e.hkdfHMACAlgo, e.hkdfSalt, contextInfo, e.demHelper.GetSymmetricKeySize(), e.pointFormat) if err != nil { return nil, err } prim, err := e.demHelper.GetAEADOrDAEAD(kemKey.SymmetricKey) if err != nil { return nil, err } var ct []byte switch a := prim.(type) { case tink.AEAD: ct, err = a.Encrypt(plaintext, []byte{}) case tink.DeterministicAEAD: ct, err = a.EncryptDeterministically(plaintext, []byte{}) default: err = errors.New("Internal error: unexpected primitive type") } if err != nil { return nil, err } b.Write(kemKey.Kem) b.Write(ct) return b.Bytes(), nil } ================================================ FILE: go/hybrid/subtle/ecies_hkdf_recipient_kem.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import "github.com/google/tink/go/subtle" // ECIESHKDFRecipientKem represents a HKDF-based KEM (key encapsulation mechanism) // for ECIES recipient. type ECIESHKDFRecipientKem struct { recipientPrivateKey *ECPrivateKey } // decapsulate uses the KEM to generate a new HKDF-based key. func (s *ECIESHKDFRecipientKem) decapsulate(kem []byte, hashAlg string, salt []byte, info []byte, keySize uint32, pointFormat string) ([]byte, error) { pubPoint, err := PointDecode(s.recipientPrivateKey.PublicKey.Curve, pointFormat, kem) if err != nil { return nil, err } secret, err := ComputeSharedSecret(pubPoint, s.recipientPrivateKey) if err != nil { return nil, err } i := make([]byte, 0, len(kem)+len(secret)) i = append(i, kem...) i = append(i, secret...) return subtle.ComputeHKDF(hashAlg, i, salt, info, keySize) } ================================================ FILE: go/hybrid/subtle/ecies_hkdf_sender_kem.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import "github.com/google/tink/go/subtle" // KEMKey represents a KEM managed key. type KEMKey struct { Kem, SymmetricKey []byte } // ECIESHKDFSenderKem represents HKDF-based ECIES-KEM (key encapsulation mechanism) // for ECIES sender. type ECIESHKDFSenderKem struct { recipientPublicKey *ECPublicKey } // encapsulate generates an HKDF-based KEMKey. func (s *ECIESHKDFSenderKem) encapsulate(hashAlg string, salt []byte, info []byte, keySize uint32, pointFormat string) (*KEMKey, error) { pvt, err := GenerateECDHKeyPair(s.recipientPublicKey.Curve) if err != nil { return nil, err } pub := pvt.PublicKey secret, err := ComputeSharedSecret(&s.recipientPublicKey.Point, pvt) if err != nil { return nil, err } sdata, err := PointEncode(pub.Curve, pointFormat, pub.Point) if err != nil { return nil, err } i := make([]byte, 0, len(sdata)+len(secret)) i = append(i, sdata...) i = append(i, secret...) sKey, err := subtle.ComputeHKDF(hashAlg, i, salt, info, keySize) if err != nil { return nil, err } return &KEMKey{ Kem: sdata, SymmetricKey: sKey, }, nil } ================================================ FILE: go/hybrid/subtle/elliptic_curves.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "bytes" "crypto/elliptic" "crypto/rand" "errors" "fmt" "math/big" ) // ECPublicKey represents a elliptic curve public key. type ECPublicKey struct { elliptic.Curve Point ECPoint } // ECPrivateKey represents a elliptic curve private key. type ECPrivateKey struct { PublicKey ECPublicKey D *big.Int } // GetECPrivateKey converts a stored private key to ECPrivateKey. func GetECPrivateKey(c elliptic.Curve, b []byte) *ECPrivateKey { d := new(big.Int) d.SetBytes(b) x, y := c.Params().ScalarBaseMult(b) pub := ECPublicKey{ Curve: c, Point: ECPoint{ X: x, Y: y, }, } return &ECPrivateKey{ PublicKey: pub, D: d, } } // ECPoint represents a point on the elliptic curve. type ECPoint struct { X, Y *big.Int } func (p *ECPrivateKey) getParams() *elliptic.CurveParams { return p.PublicKey.Curve.Params() } func getModulus(c elliptic.Curve) *big.Int { return c.Params().P } func fieldSizeInBits(c elliptic.Curve) int { t := big.NewInt(1) r := t.Sub(getModulus(c), t) return r.BitLen() } func fieldSizeInBytes(c elliptic.Curve) int { return (fieldSizeInBits(c) + 7) / 8 } func encodingSizeInBytes(c elliptic.Curve, p string) (int, error) { cSize := fieldSizeInBytes(c) switch p { case "UNCOMPRESSED": return 2*cSize + 1, nil case "DO_NOT_USE_CRUNCHY_UNCOMPRESSED": return 2 * cSize, nil case "COMPRESSED": return cSize + 1, nil } return 0, fmt.Errorf("invalid point format :%s", p) } // PointEncode encodes a point into the format specified. func PointEncode(c elliptic.Curve, pFormat string, pt ECPoint) ([]byte, error) { if !c.IsOnCurve(pt.X, pt.Y) { return nil, errors.New("curve check failed") } cSize := fieldSizeInBytes(c) y := pt.Y.Bytes() x := pt.X.Bytes() switch pFormat { case "UNCOMPRESSED": encoded := make([]byte, 2*cSize+1) copy(encoded[1+2*cSize-len(y):], y) copy(encoded[1+cSize-len(x):], x) encoded[0] = 4 return encoded, nil case "DO_NOT_USE_CRUNCHY_UNCOMPRESSED": encoded := make([]byte, 2*cSize) if len(x) > cSize { x = bytes.Replace(x, []byte("\x00"), []byte{}, -1) } if len(y) > cSize { y = bytes.Replace(y, []byte("\x00"), []byte{}, -1) } copy(encoded[2*cSize-len(y):], y) copy(encoded[cSize-len(x):], x) return encoded, nil case "COMPRESSED": encoded := make([]byte, cSize+1) copy(encoded[1+cSize-len(x):], x) encoded[0] = 2 if pt.Y.Bit(0) > 0 { encoded[0] = 3 } return encoded, nil } return nil, errors.New("invalid point format") } // PointDecode decodes a encoded point to return an ECPoint func PointDecode(c elliptic.Curve, pFormat string, e []byte) (*ECPoint, error) { cSize := fieldSizeInBytes(c) x, y := new(big.Int), new(big.Int) switch pFormat { case "UNCOMPRESSED": if len(e) != (2*cSize + 1) { return nil, errors.New("invalid point size") } if e[0] != 4 { return nil, errors.New("invalid point format") } x.SetBytes(e[1 : cSize+1]) y.SetBytes(e[cSize+1:]) if !c.IsOnCurve(x, y) { return nil, errors.New("invalid point") } return &ECPoint{ X: x, Y: y, }, nil case "DO_NOT_USE_CRUNCHY_UNCOMPRESSED": if len(e) != 2*cSize { return nil, errors.New("invalid point size") } x.SetBytes(e[:cSize]) y.SetBytes(e[cSize:]) if !c.IsOnCurve(x, y) { return nil, errors.New("invalid point") } return &ECPoint{ X: x, Y: y, }, nil case "COMPRESSED": if len(e) != cSize+1 { return nil, errors.New("compressed point has wrong length") } lsb := false if e[0] == 2 { lsb = false } else if e[0] == 3 { lsb = true } else { return nil, errors.New("invalid format") } x := new(big.Int) x.SetBytes(e[1:]) if (x.Sign() == -1) || (x.Cmp(c.Params().P) != -1) { return nil, errors.New("x is out of range") } y := getY(x, lsb, c) return &ECPoint{ X: x, Y: y, }, nil } return nil, fmt.Errorf("invalid format: %s", pFormat) } func getY(x *big.Int, lsb bool, c elliptic.Curve) *big.Int { // y² = x³ - 3x + b x3 := new(big.Int).Mul(x, x) x3.Mul(x3, x) threeX := new(big.Int).Lsh(x, 1) threeX.Add(threeX, x) b := c.Params().B p := c.Params().P x3.Sub(x3, threeX) x3.Add(x3, b) x3.ModSqrt(x3, p) e := uint(1) if lsb { e = 0 } if e == x3.Bit(0) { x3 := x3.Sub(p, x3) x3.Mod(x3, p) } return x3 } func validatePublicPoint(pub *ECPoint, priv *ECPrivateKey) error { if priv.PublicKey.Curve.IsOnCurve(pub.X, pub.Y) { return nil } return errors.New("invalid public key") } // ComputeSharedSecret is used to compute a shared secret using given private key and peer public key. func ComputeSharedSecret(pub *ECPoint, priv *ECPrivateKey) ([]byte, error) { if err := validatePublicPoint(pub, priv); err != nil { return nil, err } x, y := priv.PublicKey.Curve.ScalarMult(pub.X, pub.Y, priv.D.Bytes()) if x == nil { return nil, errors.New("shared key compute error") } // check if x,y are on the curve if err := validatePublicPoint(&ECPoint{X: x, Y: y}, priv); err != nil { return nil, errors.New("invalid shared key") } sharedSecret := make([]byte, maxSharedKeyLength(priv.PublicKey)) return x.FillBytes(sharedSecret), nil } func maxSharedKeyLength(pub ECPublicKey) int { return (pub.Curve.Params().BitSize + 7) / 8 } // GenerateECDHKeyPair will create a new private key for a given curve. func GenerateECDHKeyPair(c elliptic.Curve) (*ECPrivateKey, error) { p, x, y, err := elliptic.GenerateKey(c, rand.Reader) if err != nil { return nil, err } return &ECPrivateKey{ PublicKey: ECPublicKey{ Curve: c, Point: ECPoint{ X: x, Y: y, }, }, D: new(big.Int).SetBytes(p), }, nil } // GetCurve returns the elliptic.Curve for a given standard curve name. func GetCurve(c string) (elliptic.Curve, error) { switch c { case "secp224r1", "NIST_P224", "P-224": return elliptic.P224(), nil case "secp256r1", "NIST_P256", "P-256", "EllipticCurveType_NIST_P256": return elliptic.P256(), nil case "secp384r1", "NIST_P384", "P-384", "EllipticCurveType_NIST_P384": return elliptic.P384(), nil case "secp521r1", "NIST_P521", "P-521", "EllipticCurveType_NIST_P521": return elliptic.P521(), nil default: return nil, errors.New("unsupported curve") } } ================================================ FILE: go/hybrid/subtle/elliptic_curves_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "bytes" "crypto/ecdsa" "crypto/elliptic" "crypto/x509" "encoding/hex" "errors" "fmt" "math/big" "strings" "testing" "github.com/google/tink/go/hybrid/subtle" "github.com/google/tink/go/testutil" ) // The tests are from // http://google.github.io/end-to-end/api/source/src/javascript/crypto/e2e/ecc/ecdh_testdata.js.src.html. type testEC1 struct { elliptic.Curve pubX, pubY string } type testEC2 struct { elliptic.Curve pointFormat string encoded string X, Y string } var ( tEC1 = []testEC1{ { elliptic.P256(), "700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287", "db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac", }, { elliptic.P256(), "809f04289c64348c01515eb03d5ce7ac1a8cb9498f5caa50197e58d43a86a7ae", "b29d84e811197f25eba8f5194092cb6ff440e26d4421011372461f579271cda3", }, { elliptic.P256(), "df3989b9fa55495719b3cf46dccd28b5153f7808191dd518eff0c3cff2b705ed", "422294ff46003429d739a33206c8752552c8ba54a270defc06e221e0feaf6ac4", }, { elliptic.P256(), "356c5a444c049a52fee0adeb7e5d82ae5aa83030bfff31bbf8ce2096cf161c4b", "57d128de8b2a57a094d1a001e572173f96e8866ae352bf29cddaf92fc85b2f92", }, { elliptic.P384(), "a7c76b970c3b5fe8b05d2838ae04ab47697b9eaf52e764592efda27fe7513272" + "734466b400091adbf2d68c58e0c50066", "ac68f19f2e1cb879aed43a9969b91a0839c4c38a49749b661efedf243451915e" + "d0905a32b060992b468c64766fc8437a", }, { elliptic.P384(), "30f43fcf2b6b00de53f624f1543090681839717d53c7c955d1d69efaf0349b736" + "3acb447240101cbb3af6641ce4b88e0", "25e46c0c54f0162a77efcc27b6ea792002ae2ba82714299c860857a68153ab62e" + "525ec0530d81b5aa15897981e858757", }, { elliptic.P521(), "000000685a48e86c79f0f0875f7bc18d25eb5fc8c0b07e5da4f4370f3a9490340" + "854334b1e1b87fa395464c60626124a4e70d0f785601d37c09870ebf176666877a2" + "046d", "000001ba52c56fc8776d9e8f5db4f0cc27636d0b741bbe05400697942e80b7398" + "84a83bde99e0f6716939e632bc8986fa18dccd443a348b6c3e522497955a4f3c302" + "f676", }, { elliptic.P521(), "000001df277c152108349bc34d539ee0cf06b24f5d3500677b4445453ccc21409" + "453aafb8a72a0be9ebe54d12270aa51b3ab7f316aa5e74a951c5e53f74cd95fc29a" + "ee7a", "0000013d52f33a9f3c14384d1587fa8abe7aed74bc33749ad9c570b471776422c" + "7d4505d9b0a96b3bfac041e4c6a6990ae7f700e5b4a6640229112deafa0cd8bb0d0" + "89b0", }, { elliptic.P521(), "00000092db3142564d27a5f0006f819908fba1b85038a5bc2509906a497daac67" + "fd7aee0fc2daba4e4334eeaef0e0019204b471cd88024f82115d8149cc0cf4f7ce1" + "a4d5", "0000016bad0623f517b158d9881841d2571efbad63f85cbe2e581960c5d670601" + "a6760272675a548996217e4ab2b8ebce31d71fca63fcc3c08e91c1d8edd91cf6fe8" + "45f8", }, { elliptic.P521(), "0000004f38816681771289ce0cb83a5e29a1ab06fc91f786994b23708ff08a08a" + "0f675b809ae99e9f9967eb1a49f196057d69e50d6dedb4dd2d9a81c02bdcc8f7f51" + "8460", "0000009efb244c8b91087de1eed766500f0e81530752d469256ef79f6b965d8a2" + "232a0c2dbc4e8e1d09214bab38485be6e357c4200d073b52f04e4a16fc6f5247187" + "aecb", }, { elliptic.P521(), "000001a32099b02c0bd85371f60b0dd20890e6c7af048c8179890fda308b359db" + "bc2b7a832bb8c6526c4af99a7ea3f0b3cb96ae1eb7684132795c478ad6f962e4a6f" + "446d", "0000017627357b39e9d7632a1370b3e93c1afb5c851b910eb4ead0c9d387df67c" + "de85003e0e427552f1cd09059aad0262e235cce5fba8cedc4fdc1463da76dcd4b6d" + "1a46", }, } tEC2 = []testEC2{ // NIST_P256 { elliptic.P256(), "UNCOMPRESSED", "04" + "b0cfc7bc02fc980d858077552947ffb449b10df8949dee4e56fe21e016dcb25a" + "1886ccdca5487a6772f9401888203f90587cc00a730e2b83d5c6f89b3b568df7", "79974177209371530366349631093481213364328002500948308276357601809416549347930", "11093679777528052772423074391650378811758820120351664471899251711300542565879", }, { elliptic.P256(), "DO_NOT_USE_CRUNCHY_UNCOMPRESSED", "b0cfc7bc02fc980d858077552947ffb449b10df8949dee4e56fe21e016dcb25a" + "1886ccdca5487a6772f9401888203f90587cc00a730e2b83d5c6f89b3b568df7", "79974177209371530366349631093481213364328002500948308276357601809416549347930", "11093679777528052772423074391650378811758820120351664471899251711300542565879", }, { elliptic.P256(), "COMPRESSED", "03b0cfc7bc02fc980d858077552947ffb449b10df8949dee4e56fe21e016dcb25a", "79974177209371530366349631093481213364328002500948308276357601809416549347930", "11093679777528052772423074391650378811758820120351664471899251711300542565879", }, // Exceptional point: x==0 { elliptic.P256(), "UNCOMPRESSED", "04" + "0000000000000000000000000000000000000000000000000000000000000000" + "66485c780e2f83d72433bd5d84a06bb6541c2af31dae871728bf856a174f93f4", "0", "46263761741508638697010950048709651021688891777877937875096931459006746039284", }, { elliptic.P256(), "DO_NOT_USE_CRUNCHY_UNCOMPRESSED", "0000000000000000000000000000000000000000000000000000000000000000" + "66485c780e2f83d72433bd5d84a06bb6541c2af31dae871728bf856a174f93f4", "0", "46263761741508638697010950048709651021688891777877937875096931459006746039284", }, { elliptic.P256(), "COMPRESSED", "020000000000000000000000000000000000000000000000000000000000000000", "0", "46263761741508638697010950048709651021688891777877937875096931459006746039284", }, // Exceptional point: x==-3 { elliptic.P256(), "UNCOMPRESSED", "04" + "ffffffff00000001000000000000000000000000fffffffffffffffffffffffc" + "19719bebf6aea13f25c96dfd7c71f5225d4c8fc09eb5a0ab9f39e9178e55c121", "115792089210356248762697446949407573530086143415290314195533631308867097853948", "11508551065151498768481026661199445482476508121209842448718573150489103679777", }, { elliptic.P256(), "DO_NOT_USE_CRUNCHY_UNCOMPRESSED", "ffffffff00000001000000000000000000000000fffffffffffffffffffffffc" + "19719bebf6aea13f25c96dfd7c71f5225d4c8fc09eb5a0ab9f39e9178e55c121", "115792089210356248762697446949407573530086143415290314195533631308867097853948", "11508551065151498768481026661199445482476508121209842448718573150489103679777", }, { elliptic.P256(), "COMPRESSED", "03ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", "115792089210356248762697446949407573530086143415290314195533631308867097853948", "11508551065151498768481026661199445482476508121209842448718573150489103679777", }, // NIST_P384 { elliptic.P384(), "UNCOMPRESSED", "04aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a" + "385502f25dbf55296c3a545e3872760ab73617de4a96262c6f5d9e98bf9292dc" + "29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e" + "5f", "2624703509579968926862315674456698189185292349110921338781561590" + "0925518854738050089022388053975719786650872476732087", "8325710961489029985546751289520108179287853048861315594709205902" + "480503199884419224438643760392947333078086511627871", }, { elliptic.P384(), "COMPRESSED", "03aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a" + "385502f25dbf55296c3a545e3872760ab7", "2624703509579968926862315674456698189185292349110921338781561590" + "0925518854738050089022388053975719786650872476732087", "8325710961489029985546751289520108179287853048861315594709205902" + "480503199884419224438643760392947333078086511627871", }, // x = 0 { elliptic.P384(), "UNCOMPRESSED", "0400000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000003cf99ef04f51a5ea630ba3f9f960dd" + "593a14c9be39fd2bd215d3b4b08aaaf86bbf927f2c46e52ab06fb742b8850e52" + "1e", "0", "9384923975005507693384933751151973636103286582194273515051780595" + "652610803541482195894618304099771370981414591681054", }, { elliptic.P384(), "COMPRESSED", "0200000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000", "0", "9384923975005507693384933751151973636103286582194273515051780595" + "652610803541482195894618304099771370981414591681054", }, // x = 2 { elliptic.P384(), "UNCOMPRESSED", "0400000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000002732152442fb6ee5c3e6ce1d920c059" + "bc623563814d79042b903ce60f1d4487fccd450a86da03f3e6ed525d02017bfd" + "b3", "2", "1772015366480916228638409476801818679957736647795608728422858375" + "4887974043472116432532980617621641492831213601947059", }, { elliptic.P384(), "COMPRESSED", "0300000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000002", "2", "1772015366480916228638409476801818679957736647795608728422858375" + "4887974043472116432532980617621641492831213601947059", }, // x = -3 { elliptic.P384(), "UNCOMPRESSED", "04ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "feffffffff0000000000000000fffffffc2de9de09a95b74e6b2c430363e1afb" + "8dff7164987a8cfe0a0d5139250ac02f797f81092a9bdc0e09b574a8f43bf80c" + "17", "3940200619639447921227904010014361380507973927046544666794829340" + "4245721771496870329047266088258938001861606973112316", "7066741234775658874139271223692271325950306561732202191471600407" + "582071247913794644254895122656050391930754095909911", }, { elliptic.P384(), "COMPRESSED", "03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "feffffffff0000000000000000fffffffc", "3940200619639447921227904010014361380507973927046544666794829340" + "4245721771496870329047266088258938001861606973112316", "7066741234775658874139271223692271325950306561732202191471600407" + "582071247913794644254895122656050391930754095909911", }, // NIST_P521 { elliptic.P521(), "UNCOMPRESSED", "0400c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b" + "4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2" + "e5bd66011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd" + "17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94" + "769fd16650", "2661740802050217063228768716723360960729859168756973147706671368" + "4188029449964278084915450806277719023520942412250655586621571135" + "45570916814161637315895999846", "3757180025770020463545507224491183603594455134769762486694567779" + "6155444774405563166912344050129455395621444445372894285225856667" + "29196580810124344277578376784", }, { elliptic.P521(), "COMPRESSED", "0200c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b" + "4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2" + "e5bd66", "2661740802050217063228768716723360960729859168756973147706671368" + "4188029449964278084915450806277719023520942412250655586621571135" + "45570916814161637315895999846", "3757180025770020463545507224491183603594455134769762486694567779" + "6155444774405563166912344050129455395621444445372894285225856667" + "29196580810124344277578376784", }, // x = 0 { elliptic.P521(), "UNCOMPRESSED", "0400000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "00000000d20ec9fea6b577c10d26ca1bb446f40b299e648b1ad508aad068896f" + "ee3f8e614bc63054d5772bf01a65d412e0bcaa8e965d2f5d332d7f39f846d440" + "ae001f4f87", "0", "2816414230262626695230339754503506208598534788872316917808418392" + "0894686826982898181454171638541149642517061885689521392260532032" + "30035588176689756661142736775", }, { elliptic.P521(), "COMPRESSED", "0300000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "000000", "0", "2816414230262626695230339754503506208598534788872316917808418392" + "0894686826982898181454171638541149642517061885689521392260532032" + "30035588176689756661142736775", }, // x = 1 { elliptic.P521(), "UNCOMPRESSED", "0400000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "0000010010e59be93c4f269c0269c79e2afd65d6aeaa9b701eacc194fb3ee03d" + "f47849bf550ec636ebee0ddd4a16f1cd9406605af38f584567770e3f272d688c" + "832e843564", "1", "2265505274322546447629271557184988697103589068170534253193208655" + "0778100463909972583865730916407864371153050622267306901033104806" + "9570407113457901669103973732", }, { elliptic.P521(), "COMPRESSED", "0200000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "000001", "1", "2265505274322546447629271557184988697103589068170534253193208655" + "0778100463909972583865730916407864371153050622267306901033104806" + "9570407113457901669103973732", }, // x = 2 { elliptic.P521(), "UNCOMPRESSED", "0400000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "00000200d9254fdf800496acb33790b103c5ee9fac12832fe546c632225b0f7f" + "ce3da4574b1a879b623d722fa8fc34d5fc2a8731aad691a9a8bb8b554c95a051" + "d6aa505acf", "2", "2911448509017565583245824537994174021964465504209366849707937264" + "0417919148200722009442607963590225526059407040161685364728526719" + "10134103604091376779754756815", }, { elliptic.P521(), "COMPRESSED", "0300000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "000002", "2", "2911448509017565583245824537994174021964465504209366849707937264" + "0417919148200722009442607963590225526059407040161685364728526719" + "10134103604091376779754756815", }, // x = -2 { elliptic.P521(), "UNCOMPRESSED", "0401ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "fffffd0010e59be93c4f269c0269c79e2afd65d6aeaa9b701eacc194fb3ee03d" + "f47849bf550ec636ebee0ddd4a16f1cd9406605af38f584567770e3f272d688c" + "832e843564", "6864797660130609714981900799081393217269435300143305409394463459" + "1855431833976560521225596406614545549772963113914808580371219879" + "99716643812574028291115057149", "2265505274322546447629271557184988697103589068170534253193208655" + "0778100463909972583865730916407864371153050622267306901033104806" + "9570407113457901669103973732", }, { elliptic.P521(), "COMPRESSED", "0201ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "fffffd", "6864797660130609714981900799081393217269435300143305409394463459" + "1855431833976560521225596406614545549772963113914808580371219879" + "99716643812574028291115057149", "2265505274322546447629271557184988697103589068170534253193208655" + "0778100463909972583865730916407864371153050622267306901033104806" + "9570407113457901669103973732", }, } ) func TestPointOnCurve(t *testing.T) { for i := 0; i < len(tEC1); i++ { x, y, ye := new(big.Int), new(big.Int), new(big.Int) x.SetString(tEC1[i].pubX, 16) y.SetString(tEC1[i].pubY, 16) ye.Sub(y, big.NewInt(1)) if !tEC1[i].Curve.IsOnCurve(x, y) { t.Fatalf("valid points not on curve for test case :%d", i) } if tEC1[i].Curve.IsOnCurve(x, ye) { t.Fatalf("invalid points is on curve for test case :%d", i) } } } func TestPointEncode(t *testing.T) { for i := 0; i < len(tEC2); i++ { x, y := new(big.Int), new(big.Int) x.SetString(tEC2[i].X, 10) y.SetString(tEC2[i].Y, 10) p := subtle.ECPoint{ X: x, Y: y, } encodedpoint, err := subtle.PointEncode(tEC2[i].Curve, tEC2[i].pointFormat, p) if err != nil { t.Errorf("error in point encoding in test case %d : %v", i, err) } want, err := hex.DecodeString(tEC2[i].encoded) if err != nil { t.Errorf("error reading encoded point in test case %d", i) } if !bytes.Equal(encodedpoint, want) { t.Errorf("mismatch point encoding in test case %d", i) } } } func TestPointDecode(t *testing.T) { for i := 0; i < len(tEC2); i++ { x, y := new(big.Int), new(big.Int) x.SetString(tEC2[i].X, 10) y.SetString(tEC2[i].Y, 10) e, err := hex.DecodeString(tEC2[i].encoded) if err != nil { t.Errorf("error reading encoded point in test case %d", i) } pt, err := subtle.PointDecode(tEC2[i].Curve, tEC2[i].pointFormat, e) if err != nil { t.Errorf("error in point decoding in test case %d: %v", i, err) } spt := subtle.ECPoint{ X: x, Y: y, } if pt.X.Cmp(spt.X) != 0 || pt.Y.Cmp(spt.Y) != 0 { t.Errorf("mismatch point decoding in test case %d", i) } } } func checkFlag(t *testing.T, flags []string, check []string) bool { t.Helper() for _, f := range flags { for _, c := range check { if strings.Compare(f, c) == 0 { return true } } } return false } // convertX509PublicKey converts an encoded public key to an ECPublicKey. func convertX509PublicKey(t *testing.T, b []byte) (*subtle.ECPublicKey, error) { t.Helper() pkey, err := x509.ParsePKIXPublicKey(b) if err != nil { return nil, err } ecdsaP, ok := pkey.(*ecdsa.PublicKey) if !ok { return nil, errors.New("invalid elliptic curve key") } return &subtle.ECPublicKey{ Curve: ecdsaP.Curve, Point: subtle.ECPoint{ X: ecdsaP.X, Y: ecdsaP.Y, }, }, nil } // convertPointPublicKey converts an EC point public key to an ECPublicKey. func convertPointPublicKey(t *testing.T, pk []byte, curve elliptic.Curve, flags []string) (*subtle.ECPublicKey, error) { ptFormat := "UNCOMPRESSED" if checkFlag(t, flags, []string{"CompressedPoint"}) { ptFormat = "COMPRESSED" } pt, err := subtle.PointDecode(curve, ptFormat, pk) if err != nil { return nil, err } return &subtle.ECPublicKey{ Curve: curve, Point: *pt, }, nil } func TestECWycheproofCases(t *testing.T) { testutil.SkipTestIfTestSrcDirIsNotSet(t) vectors := []string{ "ecdh_test.json", "ecdh_secp224r1_ecpoint_test.json", "ecdh_secp256r1_ecpoint_test.json", "ecdh_secp384r1_ecpoint_test.json", "ecdh_secp521r1_ecpoint_test.json", } for _, v := range vectors { suite := new(ecdhSuite) if err := testutil.PopulateSuite(suite, v); err != nil { t.Fatalf("failed populating suite: %s", err) } for _, group := range suite.TestGroups { curve, err := subtle.GetCurve(group.Curve) if err != nil { t.Logf("unsupported curve: %s", group.Curve) continue } for _, test := range group.Tests { caseName := fmt.Sprintf("%s-%s:Case-%d", suite.Algorithm, group.Type, test.CaseID) t.Run(caseName, func(t *testing.T) { pvtKey := subtle.GetECPrivateKey(curve, test.Private) var pubKey *subtle.ECPublicKey var errPub error switch suite.Schema { case "ecdh_test_schema.json": pubKey, errPub = convertX509PublicKey(t, test.Public) case "ecdh_ecpoint_test_schema.json": pubKey, errPub = convertPointPublicKey(t, test.Public, curve, test.Flags) default: t.Logf("Unsupported schema: %q", suite.Schema) return } switch test.Result { case "valid": if errPub != nil { t.Fatalf("failed decoding public key: %s", errPub) } shared, err := subtle.ComputeSharedSecret(&pubKey.Point, pvtKey) if err != nil { t.Errorf("subtle.ComputeSharedSecret() failed: %s", err) } if !bytes.Equal(shared, test.Shared) { t.Error("valid test case, incorrect shared secret") } case "invalid": if errPub != nil { // Public key not decoded. OK for invalid test case. return } shared, err := subtle.ComputeSharedSecret(&pubKey.Point, pvtKey) if err != nil { // Shared secret was not computed. OK for invalid test case. return } validReason := checkFlag(t, test.Flags, []string{"WrongOrder", "WeakPublicKey", "UnnamedCurve"}) if validReason && bytes.Equal(shared, test.Shared) { t.Log("accepted invalid parameters but shared secret is correct") return } t.Error("accepted invalid parameters") case "acceptable": if errPub != nil { // Public key not decoded. OK for acceptable test case. return } shared, err := subtle.ComputeSharedSecret(&pubKey.Point, pvtKey) if err != nil { // Shared secret was not computed. OK for acceptable test case. return } if !bytes.Equal(shared, test.Shared) { t.Error("acceptable test case, incorrect shared secret") } default: t.Errorf("unsupported test result: %q", test.Result) } }) } } } } ================================================ FILE: go/hybrid/subtle/public_key.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "bytes" "errors" "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/keyset" hpkepb "github.com/google/tink/go/proto/hpke_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( // HPKE public key length from // https://www.rfc-editor.org/rfc/rfc9180.html#section-7.1. hpkeX25519HKDFSHA256PubKeyLen = 32 hpkePublicKeyTypeURL = "type.googleapis.com/google.crypto.tink.HpkePublicKey" hpkePrivateKeyTypeURL = "type.googleapis.com/google.crypto.tink.HpkePrivateKey" ) // SerializePrimaryPublicKey serializes a public keyset handle's primary key if // the primary key is a public key and matches both the template argument and a // supported template. // // Supported templates are the same as KeysetHandleFromSerializedPublicKey's: // - DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Raw_Key_Template, // which returns the KEM-encoding of the public key, i.e. SerializePublicKey // in https://www.rfc-editor.org/rfc/rfc9180.html#section-7.1.1. func SerializePrimaryPublicKey(handle *keyset.Handle, template *tinkpb.KeyTemplate) ([]byte, error) { templateParams, err := hpkeParamsFromTemplate(template) if err != nil { return nil, fmt.Errorf("failed to verify key template: %v", err) } // Create keyset from handle. w := new(bytes.Buffer) if err := handle.WriteWithNoSecrets(keyset.NewBinaryWriter(w)); err != nil { return nil, fmt.Errorf("failed to write key: %v", err) } ks := &tinkpb.Keyset{} if err := proto.Unmarshal(w.Bytes(), ks); err != nil { return nil, fmt.Errorf("failed to unmarshal Keyset %v: %v", ks, err) } if len(ks.GetKey()) < 1 { return nil, errors.New("empty keyset") } // Verify and return handle's primary key. for _, key := range ks.GetKey() { if key.GetStatus() != tinkpb.KeyStatusType_ENABLED || key.GetOutputPrefixType() != tinkpb.OutputPrefixType_RAW || key.GetKeyId() != ks.GetPrimaryKeyId() { continue } keyData := key.GetKeyData() if keyData.GetKeyMaterialType() != tinkpb.KeyData_ASYMMETRIC_PUBLIC { return nil, errors.New("primary key is not asymmetric public") } if keyData.GetTypeUrl() != hpkePublicKeyTypeURL { return nil, fmt.Errorf("primary key does not have key type URL %s", hpkePublicKeyTypeURL) } hpkeKey := &hpkepb.HpkePublicKey{} if err := proto.Unmarshal(keyData.GetValue(), hpkeKey); err != nil { return nil, fmt.Errorf("failed to unmarshal HpkePublicKey %v: %v", hpkeKey, err) } // Check equality between HPKE params in handle's primary key and in // template, as template's params have already been verified. if !proto.Equal(templateParams, hpkeKey.GetParams()) { return nil, errors.New("HPKE params in handle and template are not equal") } return hpkeKey.GetPublicKey(), nil } return nil, errors.New("no valid primary HPKE public key in keyset") } // KeysetHandleFromSerializedPublicKey returns a keyset handle containing a // primary key that has the specified pubKeyBytes and matches template. // // Supported templates are the same as PublicKeyFromPrimaryKey's: // - DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Raw_Key_Template, // which requires pubKeyBytes to be the KEM-encoding of the public key, i.e. // SerializePublicKey in // https://www.rfc-editor.org/rfc/rfc9180.html#section-7.1.1. func KeysetHandleFromSerializedPublicKey(pubKeyBytes []byte, template *tinkpb.KeyTemplate) (*keyset.Handle, error) { params, err := hpkeParamsFromTemplate(template) if err != nil { return nil, fmt.Errorf("failed to verify key template: %v", err) } if len(pubKeyBytes) != hpkeX25519HKDFSHA256PubKeyLen { return nil, fmt.Errorf("pubKeyBytes length is %d but should be %d", len(pubKeyBytes), hpkeX25519HKDFSHA256PubKeyLen) } pubKey := &hpkepb.HpkePublicKey{ Version: 0, Params: params, PublicKey: pubKeyBytes, } serializedPubKey, err := proto.Marshal(pubKey) if err != nil { return nil, fmt.Errorf("failed to marshal HpkePublicKey %v: %v", pubKey, err) } ks := &tinkpb.Keyset{ PrimaryKeyId: 1, Key: []*tinkpb.Keyset_Key{ { KeyData: &tinkpb.KeyData{ TypeUrl: hpkePublicKeyTypeURL, Value: serializedPubKey, KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC, }, Status: tinkpb.KeyStatusType_ENABLED, KeyId: 1, OutputPrefixType: tinkpb.OutputPrefixType_RAW, }, }, } return keyset.NewHandleWithNoSecrets(ks) } // hpkeParamsFromTemplate returns HPKE params after verifying that template is // supported. // // Supported templates include: // - DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Raw_Key_Template. func hpkeParamsFromTemplate(template *tinkpb.KeyTemplate) (*hpkepb.HpkeParams, error) { if template.GetTypeUrl() != hpkePrivateKeyTypeURL { return nil, fmt.Errorf("not key type URL %s", hpkePrivateKeyTypeURL) } if template.GetOutputPrefixType() != tinkpb.OutputPrefixType_RAW { return nil, errors.New("not raw output prefix type") } keyFormat := &hpkepb.HpkeKeyFormat{} if err := proto.Unmarshal(template.GetValue(), keyFormat); err != nil { return nil, fmt.Errorf("failed to unmarshal HpkeKeyFormat(%v): %v", template.GetValue(), err) } params := keyFormat.GetParams() if kem := params.GetKem(); kem != hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256 { return nil, fmt.Errorf("HPKE KEM %s not supported", kem) } if kdf := params.GetKdf(); kdf != hpkepb.HpkeKdf_HKDF_SHA256 { return nil, fmt.Errorf("HPKE KDF %s not supported", kdf) } if aead := params.GetAead(); aead != hpkepb.HpkeAead_CHACHA20_POLY1305 { return nil, fmt.Errorf("HPKE AEAD %s not supported", aead) } return params, nil } ================================================ FILE: go/hybrid/subtle/public_key_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "bytes" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/hybrid" "github.com/google/tink/go/hybrid/subtle" "github.com/google/tink/go/keyset" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" hpkepb "github.com/google/tink/go/proto/hpke_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestHPKEPublicKeySerialization(t *testing.T) { // Obtain private and public keyset handles via key template. keyTemplate := hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Raw_Key_Template() privHandle, err := keyset.NewHandle(keyTemplate) if err != nil { t.Fatalf("NewHandle(%v) err = %v, want nil", keyTemplate, err) } pubHandle, err := privHandle.Public() if err != nil { t.Fatalf("Public() err = %v, want nil", err) } // Export public key as bytes. pubKeyBytes, err := subtle.SerializePrimaryPublicKey(pubHandle, keyTemplate) if err != nil { t.Fatalf("SerializePrimaryPublicKey(%v) err = %v, want nil", pubHandle, err) } // Import public key bytes as keyset handle. gotPubHandle, err := subtle.KeysetHandleFromSerializedPublicKey(pubKeyBytes, keyTemplate) if err != nil { t.Fatalf("KeysetHandleFromSerializedPublicKey(%v, %v) err = %v, want nil", pubKeyBytes, keyTemplate, err) } plaintext := random.GetRandomBytes(200) ctxInfo := random.GetRandomBytes(100) // Encrypt with public keyset handle constructed from public key bytes. enc, err := hybrid.NewHybridEncrypt(gotPubHandle) if err != nil { t.Fatalf("NewHybridEncrypt(%v) err = %v, want nil", gotPubHandle, err) } ciphertext, err := enc.Encrypt(plaintext, ctxInfo) if err != nil { t.Fatalf("Encrypt(%x, %x) err = %v, want nil", plaintext, ctxInfo, err) } // Decrypt with original private keyset handle. dec, err := hybrid.NewHybridDecrypt(privHandle) if err != nil { t.Fatalf("NewHybridDecrypt(%v) err = %v, want nil", privHandle, err) } gotPlaintext, err := dec.Decrypt(ciphertext, ctxInfo) if err != nil { t.Fatalf("Decrypt(%x, %x) err = %v, want nil", plaintext, ctxInfo, err) } if !bytes.Equal(gotPlaintext, plaintext) { t.Errorf("Decrypt(%x, %x) = %x, want %x", plaintext, ctxInfo, gotPlaintext, plaintext) } } func TestSerializePrimaryPublicKeyInvalidTemplateFails(t *testing.T) { keyTemplate := hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Raw_Key_Template() privHandle, err := keyset.NewHandle(keyTemplate) if err != nil { t.Fatalf("NewHandle(%v) err = %v, want nil", keyTemplate, err) } pubHandle, err := privHandle.Public() if err != nil { t.Fatalf("Public() err = %v, want nil", err) } tests := []struct { name string template *tinkpb.KeyTemplate }{ {"AES_128_GCM", hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Key_Template()}, {"AES_128_GCM_Raw", hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Raw_Key_Template()}, {"AES_256_GCM", hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM_Key_Template()}, {"AES_256_GCM_Raw", hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM_Raw_Key_Template()}, {"CHACHA20_POLY1305", hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Key_Template()}, {"invalid type URL", &tinkpb.KeyTemplate{ TypeUrl: "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey", Value: keyTemplate.GetValue(), OutputPrefixType: tinkpb.OutputPrefixType_RAW, }}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { if _, err := subtle.SerializePrimaryPublicKey(pubHandle, test.template); err == nil { t.Errorf("SerializePrimaryPublicKey(%v, %v) err = nil, want error", pubHandle, test.template) } }) } } func TestSerializePrimaryPublicKeyInvalidHandleFails(t *testing.T) { // Build valid key data. keyTemplate := hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Raw_Key_Template() privHandle, err := keyset.NewHandle(keyTemplate) if err != nil { t.Fatalf("NewHandle(%v) err = %v, want nil", keyTemplate, err) } pubHandle, err := privHandle.Public() if err != nil { t.Fatalf("Public() err = %v, want nil", err) } pubKeyBytes, err := subtle.SerializePrimaryPublicKey(pubHandle, keyTemplate) if err != nil { t.Fatalf("SerializePrimaryPublicKey(%v, %v) err = %v, want nil", pubHandle, keyTemplate, err) } typeURL := "type.googleapis.com/google.crypto.tink.HpkePublicKey" validKD, err := keyDataFromBytes(t, pubKeyBytes, hpkepb.HpkeAead_CHACHA20_POLY1305, typeURL) if err != nil { t.Fatalf("keyDataFromBytes(%v, %v, %v) err = %v, want nil", pubKeyBytes, hpkepb.HpkeAead_CHACHA20_POLY1305, typeURL, err) } // Build key data with invalid type URL. invalidTypeURL := "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPublicKey" invalidTypeURLKD, err := keyDataFromBytes(t, pubKeyBytes, hpkepb.HpkeAead_CHACHA20_POLY1305, invalidTypeURL) if err != nil { t.Fatalf("keyDataFromBytes(%v, %v, %v) err = %v, want nil", pubKeyBytes, hpkepb.HpkeAead_CHACHA20_POLY1305, invalidTypeURL, err) } // Build key data with invalid HPKE params. randomPubKeyBytes := random.GetRandomBytes(32) invalidAEAD := hpkepb.HpkeAead_AES_128_GCM invalidParamsKD, err := keyDataFromBytes(t, randomPubKeyBytes, invalidAEAD, typeURL) if err != nil { t.Fatalf("keyDataFromBytes(%v, %v, %v) err = %v, want nil", randomPubKeyBytes, invalidAEAD, typeURL, err) } tests := []struct { name string primaryKeyID uint32 key *tinkpb.Keyset_Key }{ { "empty", 123, nil, }, { "invalid status type", 123, testutil.NewKey(validKD, tinkpb.KeyStatusType_DISABLED, 123, tinkpb.OutputPrefixType_RAW), }, { "invalid prefix type", 123, testutil.NewKey(validKD, tinkpb.KeyStatusType_ENABLED, 123, tinkpb.OutputPrefixType_TINK), }, { "no primary key", 0, testutil.NewKey(validKD, tinkpb.KeyStatusType_ENABLED, 123, tinkpb.OutputPrefixType_RAW), }, { "invalid type URL", 123, testutil.NewKey(invalidTypeURLKD, tinkpb.KeyStatusType_ENABLED, 123, tinkpb.OutputPrefixType_RAW), }, { "invalid HPKE params", 123, testutil.NewKey(invalidParamsKD, tinkpb.KeyStatusType_ENABLED, 123, tinkpb.OutputPrefixType_RAW), }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { ks := testutil.NewKeyset(test.primaryKeyID, []*tinkpb.Keyset_Key{test.key}) handle, err := keyset.NewHandleWithNoSecrets(ks) if err != nil { t.Fatalf("NewHandleWithNoSecrets(%v) err = %v, want nil", ks, err) } if _, err := subtle.SerializePrimaryPublicKey(handle, keyTemplate); err == nil { t.Errorf("SerializePrimaryPublicKey(%v, %v) err = nil, want error", handle, keyTemplate) } }) } } func TestKeysetHandleFromSerializedPublicKeyInvalidTemplateFails(t *testing.T) { keyTemplate := hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Raw_Key_Template() privHandle, err := keyset.NewHandle(keyTemplate) if err != nil { t.Fatalf("NewHandle(%v) err = %v, want nil", keyTemplate, err) } pubHandle, err := privHandle.Public() if err != nil { t.Fatalf("Public() err = %v, want nil", err) } pubKeyBytes, err := subtle.SerializePrimaryPublicKey(pubHandle, keyTemplate) if err != nil { t.Fatalf("SerializePrimaryPublicKey(%v) err = %v, want nil", pubHandle, err) } tests := []struct { name string template *tinkpb.KeyTemplate }{ {"AES_128_GCM", hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Key_Template()}, {"AES_128_GCM_Raw", hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Raw_Key_Template()}, {"AES_256_GCM", hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM_Key_Template()}, {"AES_256_GCM_Raw", hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM_Raw_Key_Template()}, {"CHACHA20_POLY1305", hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Key_Template()}, {"invalid type URL", &tinkpb.KeyTemplate{ TypeUrl: "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey", Value: keyTemplate.GetValue(), OutputPrefixType: tinkpb.OutputPrefixType_RAW, }}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { if _, err := subtle.KeysetHandleFromSerializedPublicKey(pubKeyBytes, test.template); err == nil { t.Errorf("KeysetHandleFromSerializedPublicKey(%v, %v) err = nil, want error", pubKeyBytes, test.template) } }) } } func keyDataFromBytes(t *testing.T, pubKeyBytes []byte, aeadID hpkepb.HpkeAead, typeURL string) (*tinkpb.KeyData, error) { t.Helper() pubKey := &hpkepb.HpkePublicKey{ Version: 0, Params: &hpkepb.HpkeParams{ Kem: hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256, Kdf: hpkepb.HpkeKdf_HKDF_SHA256, Aead: aeadID, }, PublicKey: pubKeyBytes, } serializedPubKey, err := proto.Marshal(pubKey) if err != nil { return nil, err } return testutil.NewKeyData(typeURL, serializedPubKey, tinkpb.KeyData_ASYMMETRIC_PUBLIC), nil } ================================================ FILE: go/hybrid/subtle/subtle.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package subtle provides subtle implementations of the Hybrid Encryption // primitive. package subtle ================================================ FILE: go/hybrid/subtle/subtle_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import "github.com/google/tink/go/testutil" type ecdhSuite struct { testutil.WycheproofSuite Schema string `json:"schema"` TestGroups []*ecdhGroup `json:"testGroups"` } type ecdhGroup struct { testutil.WycheproofGroup Curve string `json:"curve"` Encoding string `json:"encoding"` Type string `json:"type"` Tests []*ecdhCase `json:"tests"` } type ecdhCase struct { testutil.WycheproofCase Public testutil.HexBytes `json:"public"` Private testutil.HexBytes `json:"private"` Shared testutil.HexBytes `json:"shared"` } ================================================ FILE: go/insecurecleartextkeyset/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep licenses(["notice"]) # keep go_library( name = "insecurecleartextkeyset", srcs = ["insecurecleartextkeyset.go"], importpath = "github.com/google/tink/go/insecurecleartextkeyset", visibility = ["//visibility:public"], deps = [ "//internal", "//keyset", "//proto/tink_go_proto", ], ) go_test( name = "insecurecleartextkeyset_test", srcs = [ "example_test.go", "insecurecleartextkeyset_test.go", ], deps = [ ":insecurecleartextkeyset", "//aead", "//hybrid", "//internal/internalregistry", "//keyset", "//mac", "//proto/tink_go_proto", "//testing/fakemonitoring", "@com_github_google_go_cmp//cmp", "@org_golang_google_protobuf//proto", "@org_golang_google_protobuf//testing/protocmp", ], ) alias( name = "go_default_library", actual = ":insecurecleartextkeyset", visibility = ["//visibility:public"], ) ================================================ FILE: go/insecurecleartextkeyset/example_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package insecurecleartextkeyset_test // [START cleartext-keyset-example] import ( "bytes" "fmt" "log" "github.com/google/tink/go/aead" "github.com/google/tink/go/insecurecleartextkeyset" "github.com/google/tink/go/keyset" ) func Example_cleartextKeysetInBinary() { // Generate a new keyset handle for the primitive we want to use. handle, err := keyset.NewHandle(aead.AES256GCMKeyTemplate()) if err != nil { log.Fatal(err) } // Serialize the keyset. buff := &bytes.Buffer{} err = insecurecleartextkeyset.Write(handle, keyset.NewBinaryWriter(buff)) if err != nil { log.Fatal(err) } serializedKeyset := buff.Bytes() // serializedKeyset can now be stored at a secure location. // WARNING: Storing the keyset in cleartext to disk is not recommended! // Parse the keyset. parsedHandle, err := insecurecleartextkeyset.Read( keyset.NewBinaryReader(bytes.NewBuffer(serializedKeyset))) if err != nil { log.Fatal(err) } // Get the primitive. primitive, err := aead.New(parsedHandle) if err != nil { log.Fatal(err) } // Use the primitive. plaintext := []byte("message") associatedData := []byte("example encryption") ciphertext, err := primitive.Encrypt(plaintext, associatedData) if err != nil { log.Fatal(err) } decrypted, err := primitive.Decrypt(ciphertext, associatedData) if err != nil { log.Fatal(err) } fmt.Println(string(decrypted)) // Output: message } // [END cleartext-keyset-example] func Example_cleartextKeysetInJSON() { // Generate a new keyset handle for the primitive we want to use. handle, err := keyset.NewHandle(aead.AES256GCMKeyTemplate()) if err != nil { log.Fatal(err) } // Serialize the keyset. buff := &bytes.Buffer{} err = insecurecleartextkeyset.Write(handle, keyset.NewJSONWriter(buff)) if err != nil { log.Fatal(err) } serializedKeyset := buff.Bytes() // serializedKeyset can now be stored at a secure location. // WARNING: Storing the keyset in cleartext to disk is not recommended! // Parse the keyset. parsedHandle, err := insecurecleartextkeyset.Read(keyset.NewJSONReader(bytes.NewBuffer(serializedKeyset))) if err != nil { log.Fatal(err) } // Get the primitive. primitive, err := aead.New(parsedHandle) if err != nil { log.Fatal(err) } // Use the primitive. plaintext := []byte("message") associatedData := []byte("example encryption") ciphertext, err := primitive.Encrypt(plaintext, associatedData) if err != nil { log.Fatal(err) } decrypted, err := primitive.Decrypt(ciphertext, associatedData) if err != nil { log.Fatal(err) } fmt.Println(string(decrypted)) // Output: message } ================================================ FILE: go/insecurecleartextkeyset/insecurecleartextkeyset.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package insecurecleartextkeyset provides methods to read or write cleartext // keyset material. // // This package contains dangerous functions, and is separate from the rest of // Tink so that its usage can be restricted and audited. package insecurecleartextkeyset import ( "errors" "github.com/google/tink/go/internal" "github.com/google/tink/go/keyset" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) var ( keysetHandle = internal.KeysetHandle.(func(*tinkpb.Keyset, ...keyset.Option) (*keyset.Handle, error)) keysetMaterial = internal.KeysetMaterial.(func(*keyset.Handle) *tinkpb.Keyset) errInvalidKeyset = errors.New("insecurecleartextkeyset: invalid keyset") errInvalidHandle = errors.New("insecurecleartextkeyset: invalid handle") errInvalidReader = errors.New("insecurecleartextkeyset: invalid reader") errInvalidWriter = errors.New("insecurecleartextkeyset: invalid writer") ) // Read creates a keyset.Handle from a cleartext keyset obtained via r. func Read(r keyset.Reader, opts ...keyset.Option) (*keyset.Handle, error) { if r == nil { return nil, errInvalidReader } ks, err := r.Read() if err != nil || ks == nil || len(ks.Key) == 0 { return nil, errInvalidKeyset } return keysetHandle(ks, opts...) } // Write exports the keyset from handle to the given writer w without encrypting it. // // Storing secret key material in an unencrypted fashion is dangerous. If // feasible, you should use [keyset.Handle.Write] instead. func Write(handle *keyset.Handle, w keyset.Writer) error { if handle == nil { return errInvalidHandle } if w == nil { return errInvalidWriter } return w.Write(KeysetMaterial(handle)) } // KeysetMaterial returns the key material contained in a keyset.Handle. func KeysetMaterial(handle *keyset.Handle) *tinkpb.Keyset { return keysetMaterial(handle) } // KeysetHandle creates a keyset.Handle from cleartext key material. // // Callers should verify that the returned *keyset.Handle isn't nil. // // Deprecated: Use [Read] instead with a serialized keyset. // // sks, err := proto.Marshal(ks) // if err != nil { // return err // } // h, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(bytes.NewBuffer(sks))) // if err != nil { // return err // } func KeysetHandle(ks *tinkpb.Keyset) *keyset.Handle { kh, err := keysetHandle(ks) if err != nil { // this *keyset.Handle can only return errors when *keyset.Option arguments // are provided. To maintain backwards compatibility and avoid panic, it returns // a nil value if an error happens. return nil } return kh } ================================================ FILE: go/insecurecleartextkeyset/insecurecleartextkeyset_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package insecurecleartextkeyset_test import ( "bytes" "testing" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/testing/protocmp" "github.com/google/tink/go/aead" "github.com/google/tink/go/hybrid" "github.com/google/tink/go/insecurecleartextkeyset" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/keyset" "github.com/google/tink/go/mac" "github.com/google/tink/go/testing/fakemonitoring" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // A KeysetReader that always returns nil. type NilKeysetReader struct { } func (m *NilKeysetReader) Read() (*tinkpb.Keyset, error) { return nil, nil } func (m *NilKeysetReader) ReadEncrypted() (*tinkpb.EncryptedKeyset, error) { return nil, nil } func TestReadWithNilKeysetFails(t *testing.T) { if _, err := insecurecleartextkeyset.Read(&NilKeysetReader{}); err == nil { t.Error("insecurecleartextkeyset.Read(&NilKeysetReader{}) err = nil, want error") } } func TestReadWithNilReaderFails(t *testing.T) { if _, err := insecurecleartextkeyset.Read(nil); err == nil { t.Error("insecurecleartextkeyset.Read(nil) err = nil, want error") } } func TestWriteWithNilHandleFails(t *testing.T) { buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(nil, keyset.NewBinaryWriter(buff)); err == nil { t.Error("insecurecleartextkeyset.Write(nil, _) err = nil, want error") } } func TestWriteWithNilWriterFails(t *testing.T) { handle, err := keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle(aead.HMACSHA256Tag128KeyTemplate()) err = %v, want nil", err) } if err := insecurecleartextkeyset.Write(handle, nil); err == nil { t.Error("insecurecleartextkeyset.Write(_, nil) err = nil, want error") } } func TestWriteAndReadInBinary(t *testing.T) { handle, err := keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) err = %v, want nil", err) } buff := &bytes.Buffer{} err = insecurecleartextkeyset.Write(handle, keyset.NewBinaryWriter(buff)) if err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } serialized := buff.Bytes() parsedHandle, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(bytes.NewBuffer(serialized))) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } want := insecurecleartextkeyset.KeysetMaterial(handle) got := insecurecleartextkeyset.KeysetMaterial(parsedHandle) if !proto.Equal(got, want) { t.Errorf("KeysetMaterial(Read()) = %q, want %q", got, want) } } func TestWriteAndReadInJson(t *testing.T) { handle, err := keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) err = %v, want nil", err) } buff := &bytes.Buffer{} err = insecurecleartextkeyset.Write(handle, keyset.NewJSONWriter(buff)) if err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } serialized := buff.Bytes() parsedHandle, err := insecurecleartextkeyset.Read(keyset.NewJSONReader(bytes.NewBuffer(serialized))) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } want := insecurecleartextkeyset.KeysetMaterial(handle) got := insecurecleartextkeyset.KeysetMaterial(parsedHandle) if !proto.Equal(got, want) { t.Errorf("KeysetMaterial(Read()) = %q, want %q", got, want) } } func TestLegacyKeysetHandle(t *testing.T) { handle, err := keyset.NewHandle(hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Key_Template()) if err != nil { t.Fatalf(" keyset.NewHandle(hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Key_Template()) err = %v, want nil", err) } ks := insecurecleartextkeyset.KeysetMaterial(handle) gotHandle1 := insecurecleartextkeyset.KeysetHandle(ks) if !cmp.Equal(gotHandle1.KeysetInfo(), handle.KeysetInfo(), protocmp.Transform()) { t.Errorf("gotHandle1.KeysetInfo() = %v, want %v", gotHandle1.KeysetInfo(), handle.KeysetInfo()) } serializedKeyset, err := proto.Marshal(ks) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } gotHandle2, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(bytes.NewBuffer(serializedKeyset))) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } if !cmp.Equal(gotHandle2.KeysetInfo(), handle.KeysetInfo(), protocmp.Transform()) { t.Errorf("gotHandle2.KeysetInfo() = %v, want %v", gotHandle2.KeysetInfo(), handle.KeysetInfo()) } } func TestHandleFromReaderWithAnnotationsGetsMonitored(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := &fakemonitoring.Client{} if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } handle, err := keyset.NewHandle(aead.AES256GCMKeyTemplate()) if err != nil { t.Fatalf(" keyset.NewHandle(aead.AES256GCMKeyTemplate()) err = %v, want nil", err) } buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(handle, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } wantAnnotations := map[string]string{"foo": "bar"} annotatedHandle, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(wantAnnotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } p, err := aead.New(annotatedHandle) if err != nil { t.Fatalf("aead.New() err = %v, want nil", err) } if _, err := p.Encrypt([]byte("some_data"), nil); err != nil { t.Fatalf("Encrypt() err = %v, want nil", err) } events := client.Events() gotAnnotations := events[0].Context.KeysetInfo.Annotations if !cmp.Equal(gotAnnotations, wantAnnotations) { t.Errorf("Annotations = %v, want %v", gotAnnotations, wantAnnotations) } } func TestHandleFromReaderWithAnnotationsTwiceFails(t *testing.T) { handle, err := keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) if err != nil { t.Fatalf(" keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) err = %v, want nil", err) } buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(handle, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} if _, err := insecurecleartextkeyset.Read( keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations), keyset.WithAnnotations(annotations)); err == nil { t.Fatalf("insecurecleartextkeyset.Read() err = nil, want error") } } func TestHandleFromReaderWithoutAnnotationsDoesNotGetMonitored(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := &fakemonitoring.Client{} if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } handle, err := keyset.NewHandle(aead.AES256GCMKeyTemplate()) if err != nil { t.Fatalf(" keyset.NewHandle(aead.AES256GCMKeyTemplate()) err = %v, want nil", err) } buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(handle, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } unannotatedHandle, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } p, err := aead.New(unannotatedHandle) if err != nil { t.Fatalf("aead.New() err = %v, want nil", err) } if _, err := p.Encrypt([]byte("some_data"), nil); err != nil { t.Fatalf("Encrypt() err = %v, want nil", err) } if len(client.Events()) != 0 { t.Errorf("len(client.Events()) = %d, want 0", len(client.Events())) } } ================================================ FILE: go/integration/awskms/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) # keep go_library( name = "awskms", srcs = [ "aws_kms_aead.go", "aws_kms_client.go", ], importpath = "github.com/google/tink/go/integration/awskms", visibility = ["//visibility:public"], deps = [ "//core/registry", "//tink", "@com_github_aws_aws_sdk_go//aws", "@com_github_aws_aws_sdk_go//aws/credentials", "@com_github_aws_aws_sdk_go//aws/session", "@com_github_aws_aws_sdk_go//service/kms", "@com_github_aws_aws_sdk_go//service/kms/kmsiface", ], ) go_test( name = "awskms_test", srcs = [ "aws_kms_client_test.go", "aws_kms_integration_test.go", ], data = [ "//testdata/aws:bad_credentials", "//testdata/aws:credentials", "@google_root_pem//file", #keep ], embed = [":awskms"], tags = [ "manual", "no_rbe", ], deps = [ "//aead", "//core/registry", "//integration/awskms/internal/fakeawskms", "//tink", "@com_github_aws_aws_sdk_go//aws", "@com_github_aws_aws_sdk_go//service/kms", ], ) alias( name = "go_default_library", actual = ":awskms", visibility = ["//visibility:public"], ) ================================================ FILE: go/integration/awskms/aws_kms_aead.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package awskms provides integration with the AWS Key Management Service. package awskms import ( "encoding/hex" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/kms" "github.com/aws/aws-sdk-go/service/kms/kmsiface" ) // AWSAEAD is an implementation of the AEAD interface which performs // cryptographic operations remotely via the AWS KMS service using a specific // key URI. type AWSAEAD struct { keyURI string kms kmsiface.KMSAPI encryptionContextName EncryptionContextName } // newAWSAEAD returns a new AWSAEAD instance. // // keyURI must have the following format: // // aws-kms://arn::kms::[] // // See http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html. func newAWSAEAD(keyURI string, kms kmsiface.KMSAPI, name EncryptionContextName) *AWSAEAD { return &AWSAEAD{ keyURI: keyURI, kms: kms, encryptionContextName: name, } } // Encrypt encrypts the plaintext with associatedData. func (a *AWSAEAD) Encrypt(plaintext, associatedData []byte) ([]byte, error) { req := &kms.EncryptInput{ KeyId: aws.String(a.keyURI), Plaintext: plaintext, } if len(associatedData) > 0 { ad := hex.EncodeToString(associatedData) req.EncryptionContext = map[string]*string{a.encryptionContextName.String(): &ad} } resp, err := a.kms.Encrypt(req) if err != nil { return nil, err } return resp.CiphertextBlob, nil } // Decrypt decrypts the ciphertext and verifies the associated data. func (a *AWSAEAD) Decrypt(ciphertext, associatedData []byte) ([]byte, error) { req := &kms.DecryptInput{ KeyId: aws.String(a.keyURI), CiphertextBlob: ciphertext, } if len(associatedData) > 0 { ad := hex.EncodeToString(associatedData) req.EncryptionContext = map[string]*string{a.encryptionContextName.String(): &ad} } resp, err := a.kms.Decrypt(req) if err != nil { return nil, err } return resp.Plaintext, nil } ================================================ FILE: go/integration/awskms/aws_kms_client.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package awskms import ( "encoding/csv" "errors" "fmt" "os" "regexp" "strconv" "strings" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/kms" "github.com/aws/aws-sdk-go/service/kms/kmsiface" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/tink" ) const ( awsPrefix = "aws-kms://" ) var ( errCred = errors.New("invalid credential path") errBadFile = errors.New("cannot open credential path") errCredCSV = errors.New("malformed credential CSV file") ) // awsClient is a wrapper around an AWS SDK provided KMS client that can // instantiate Tink primitives. type awsClient struct { keyURIPrefix string kms kmsiface.KMSAPI encryptionContextName EncryptionContextName } // ClientOption is an interface for defining options that are passed to // [NewClientWithOptions]. type ClientOption interface{ set(*awsClient) error } type option func(*awsClient) error func (o option) set(a *awsClient) error { return o(a) } // WithCredentialPath instantiates the underlying AWS KMS client using the // credentials located at credentialPath. // // credentialPath can specify a file in CSV format as provided in the IAM // console or an INI-style credentials file. // // See https://docs.aws.amazon.com/cli/latest/userguide/cli-authentication-user.html#cli-authentication-user-configure-csv // and https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html#cli-configure-files-format. func WithCredentialPath(credentialPath string) ClientOption { return option(func(a *awsClient) error { if a.kms != nil { return errors.New("WithCredentialPath option cannot be used, KMS client already set") } k, err := getKMSFromCredentialPath(a.keyURIPrefix, credentialPath) if err != nil { return err } a.kms = k return nil }) } // WithKMS sets the underlying AWS KMS client to kms, a preexisting AWS KMS // client instance. // // It's the callers responsibility to ensure that the configured region of kms // aligns with the region in key URIs passed to this client. Otherwise, API // requests will fail. func WithKMS(kms kmsiface.KMSAPI) ClientOption { return option(func(a *awsClient) error { if a.kms != nil { return errors.New("WithKMS option cannot be used, KMS client already set") } a.kms = kms return nil }) } // EncryptionContextName specifies the name used in the EncryptionContext field // of EncryptInput and DecryptInput requests. See [WithEncryptionContextName] // for further details. type EncryptionContextName uint const ( // AssociatedData will set the EncryptionContext name to "associatedData". AssociatedData EncryptionContextName = 1 + iota // LegacyAdditionalData will set the EncryptionContext name to "additionalData". LegacyAdditionalData ) var encryptionContextNames = map[EncryptionContextName]string{ AssociatedData: "associatedData", LegacyAdditionalData: "additionalData", } func (n EncryptionContextName) valid() bool { _, ok := encryptionContextNames[n] return ok } func (n EncryptionContextName) String() string { if !n.valid() { return "unrecognized value " + strconv.Itoa(int(n)) } return encryptionContextNames[n] } // WithEncryptionContextName sets the name which maps to the base64 encoded // associated data within the EncryptionContext field of EncrypInput and // DecryptInput requests. // // The default is [AssociatedData], which is compatible with the Tink AWS KMS // extensions in other languages. In older versions of this packge, before this // option was present, "additionalData" was hardcoded. // // This option is provided to facilitate compatibility with older ciphertexts. func WithEncryptionContextName(name EncryptionContextName) ClientOption { return option(func(a *awsClient) error { if !name.valid() { return fmt.Errorf("invalid EncryptionContextName: %v", name) } if a.encryptionContextName != 0 { return errors.New("encryptionContextName already set") } a.encryptionContextName = name return nil }) } // NewClientWithOptions returns a [registry.KMSClient] which wraps an AWS KMS // client and will handle keys whose URIs start with uriPrefix. // // By default, the client will use default credentials. // // AEAD primitives produced by this client will use [AssociatedData] when // serializing associated data. func NewClientWithOptions(uriPrefix string, opts ...ClientOption) (registry.KMSClient, error) { if !strings.HasPrefix(strings.ToLower(uriPrefix), awsPrefix) { return nil, fmt.Errorf("uriPrefix must start with %q, but got %q", awsPrefix, uriPrefix) } a := &awsClient{ keyURIPrefix: uriPrefix, } // Process options, if any. for _, opt := range opts { if err := opt.set(a); err != nil { return nil, fmt.Errorf("failed setting option: %v", err) } } // Populate values not defined via options. if a.kms == nil { k, err := getKMS(uriPrefix) if err != nil { return nil, err } a.kms = k } if a.encryptionContextName == 0 { a.encryptionContextName = AssociatedData } return a, nil } // NewClient returns a KMSClient backed by AWS KMS using default credentials to // handle keys whose URIs start with uriPrefix. // // uriPrefix must have the following format: // // aws-kms://arn::kms::[] // // See https://docs.aws.amazon.com/IAM/latest/UserGuide/reference-arns.html // // AEAD primitives produced by this client will use [LegacyAdditionalData] when // serializing associated data. // // Deprecated: Instead, use [NewClientWithOptions]. // // awskms.NewClientWithOptions(uriPrefix) func NewClient(uriPrefix string) (registry.KMSClient, error) { return NewClientWithOptions(uriPrefix, WithEncryptionContextName(LegacyAdditionalData)) } // NewClientWithCredentials returns a KMSClient backed by AWS KMS using the given // credentials to handle keys whose URIs start with uriPrefix. // // uriPrefix must have the following format: // // aws-kms://arn::kms::[] // // See https://docs.aws.amazon.com/IAM/latest/UserGuide/reference-arns.html // // credentialPath can specify a file in CSV format as provided in the IAM // console or an INI-style credentials file. // // See https://docs.aws.amazon.com/cli/latest/userguide/cli-authentication-user.html#cli-authentication-user-configure-csv // and https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html#cli-configure-files-format. // // AEAD primitives produced by this client will use [LegacyAdditionalData] when // serializing associated data. // // Deprecated: Instead use [NewClientWithOptions] and [WithCredentialPath]. // // awskms.NewClientWithOptions(uriPrefix, awskms.WithCredentialPath(credentialPath)) func NewClientWithCredentials(uriPrefix string, credentialPath string) (registry.KMSClient, error) { return NewClientWithOptions(uriPrefix, WithCredentialPath(credentialPath), WithEncryptionContextName(LegacyAdditionalData)) } // NewClientWithKMS returns a KMSClient backed by AWS KMS using the provided // instance of the AWS SDK KMS client. // // The caller is responsible for ensuring that the region specified in the KMS // client is consitent with the region specified within uriPrefix. // // uriPrefix must have the following format: // // aws-kms://arn::kms::[] // // See https://docs.aws.amazon.com/IAM/latest/UserGuide/reference-arns.html // // AEAD primitives produced by this client will use [LegacyAdditionalData] when // serializing associated data. // // Deprecated: Instead use [NewClientWithOptions] and [WithKMS]. // // awskms.NewClientWithOptions(uriPrefix, awskms.WithKMS(kms)) func NewClientWithKMS(uriPrefix string, kms kmsiface.KMSAPI) (registry.KMSClient, error) { return NewClientWithOptions(uriPrefix, WithKMS(kms), WithEncryptionContextName(LegacyAdditionalData)) } // Supported returns true if keyURI starts with the URI prefix provided when // creating the client. func (c *awsClient) Supported(keyURI string) bool { return strings.HasPrefix(keyURI, c.keyURIPrefix) } // GetAEAD returns an implementation of the AEAD interface which performs // cryptographic operations remotely via AWS KMS using keyURI. // // keyUri must be supported by this client and must have the following format: // // aws-kms://arn::kms:: // // See https://docs.aws.amazon.com/IAM/latest/UserGuide/reference-arns.html func (c *awsClient) GetAEAD(keyURI string) (tink.AEAD, error) { if !c.Supported(keyURI) { return nil, fmt.Errorf("keyURI must start with prefix %s, but got %s", c.keyURIPrefix, keyURI) } uri := strings.TrimPrefix(keyURI, awsPrefix) return newAWSAEAD(uri, c.kms, c.encryptionContextName), nil } func getKMS(uriPrefix string) (*kms.KMS, error) { r, err := getRegion(uriPrefix) if err != nil { return nil, err } session, err := session.NewSession(&aws.Config{ Region: aws.String(r), }) if err != nil { return nil, err } return kms.New(session), nil } func getKMSFromCredentialPath(uriPrefix string, credentialPath string) (*kms.KMS, error) { r, err := getRegion(uriPrefix) if err != nil { return nil, err } var creds *credentials.Credentials if len(credentialPath) == 0 { return nil, errCred } c, err := extractCredsCSV(credentialPath) switch err { case nil: creds = credentials.NewStaticCredentialsFromCreds(*c) case errBadFile, errCredCSV: return nil, err default: // Fallback to load the credential path as .ini shared credentials. creds = credentials.NewSharedCredentials(credentialPath, "default") } session, err := session.NewSession(&aws.Config{ Credentials: creds, Region: aws.String(r), }) if err != nil { return nil, err } return kms.New(session), nil } // extractCredsCSV extracts credentials from a CSV file. // // A CSV formatted credentials file can be obtained when an AWS IAM user is // created through the IAM console. // // Properties of a properly formatted CSV file: // // 1. The first line consists of the headers: // "User name,Password,Access key ID,Secret access key,Console login link" // 2. The second line contains 5 comma separated values. func extractCredsCSV(file string) (*credentials.Value, error) { f, err := os.Open(file) if err != nil { return nil, errBadFile } defer f.Close() lines, err := csv.NewReader(f).ReadAll() if err != nil { return nil, err } // It is possible that the file is an AWS .ini credential file, and it can be // parsed as 1-column CSV file as well. A real AWS credentials.csv is never 1 column. if len(lines) > 0 && len(lines[0]) == 1 { return nil, errors.New("not a valid CSV credential file") } if len(lines) < 2 { return nil, errCredCSV } if len(lines[1]) < 4 { return nil, errCredCSV } return &credentials.Value{ AccessKeyID: lines[1][2], SecretAccessKey: lines[1][3], }, nil } // getRegion extracts the region from keyURI. func getRegion(keyURI string) (string, error) { re1, err := regexp.Compile(`aws-kms://arn:(aws[a-zA-Z0-9-_]*):kms:([a-z0-9-]+):`) if err != nil { return "", err } r := re1.FindStringSubmatch(keyURI) if len(r) != 3 { return "", errors.New("extracting region from URI failed") } return r[2], nil } ================================================ FILE: go/integration/awskms/aws_kms_client_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package awskms import ( "bytes" "encoding/hex" "os" "path/filepath" "strings" "testing" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/kms" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/integration/awskms/internal/fakeawskms" ) func TestNewClientWithOptions_URIPrefix(t *testing.T) { srcDir, ok := os.LookupEnv("TEST_SRCDIR") if !ok { t.Skip("TEST_SRCDIR not set") } workspaceDir, ok := os.LookupEnv("TEST_WORKSPACE") if !ok { t.Skip("TEST_WORKSPACE not set") } // Necessary for testing deprecated factory functions. credFile := filepath.Join(srcDir, workspaceDir, "testdata/aws/credentials.csv") keyARN := "arn:aws:kms:us-east-2:235739564943:key/3ee50705-5a82-4f5b-9753-05c4f473922f" fakekms, err := fakeawskms.New([]string{keyARN}) if err != nil { t.Fatalf("fakeawskms.New() failed: %v", err) } tests := []struct { name string uriPrefix string valid bool }{ { name: "AWS partition", uriPrefix: "aws-kms://arn:aws:kms:us-east-2:235739564943:key/3ee50705-5a82-4f5b-9753-05c4f473922f", valid: true, }, { name: "AWS US government partition", uriPrefix: "aws-kms://arn:aws-us-gov:kms:us-gov-east-1:235739564943:key/3ee50705-5a82-4f5b-9753-05c4f473922f", valid: true, }, { name: "AWS CN partition", uriPrefix: "aws-kms://arn:aws-cn:kms:cn-north-1:235739564943:key/3ee50705-5a82-4f5b-9753-05c4f473922f", valid: true, }, { name: "invalid", uriPrefix: "bad-prefix://arn:aws-cn:kms:cn-north-1:235739564943:key/3ee50705-5a82-4f5b-9753-05c4f473922f", valid: false, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { _, err := NewClientWithOptions(test.uriPrefix) if test.valid && err != nil { t.Errorf("NewClientWithOptions(%q) err = %v, want nil", test.uriPrefix, err) } if !test.valid && err == nil { t.Errorf("NewClientWithOptions(%q) err = nil, want error", test.uriPrefix) } // Test deprecated factory functions. _, err = NewClient(test.uriPrefix) if test.valid && err != nil { t.Errorf("NewClient(%q) err = %v, want nil", test.uriPrefix, err) } if !test.valid && err == nil { t.Errorf("NewClient(%q) err = nil, want error", test.uriPrefix) } _, err = NewClientWithCredentials(test.uriPrefix, credFile) if test.valid && err != nil { t.Errorf("NewClientWithCredentialPath(%q, _) err = %v, want nil", test.uriPrefix, err) } if !test.valid && err == nil { t.Errorf("NewClientWithCredentialPath(%q, _) err = nil, want error", test.uriPrefix) } _, err = NewClientWithKMS(test.uriPrefix, fakekms) if test.valid && err != nil { t.Errorf("NewClientWithKMS(%q, _) err = %v, want nil", test.uriPrefix, err) } if !test.valid && err == nil { t.Errorf("NewClientWithKMS(%q, _) err = nil, want error", test.uriPrefix) } }) } } func TestNewClientWithOptions_WithCredentialPath(t *testing.T) { srcDir, ok := os.LookupEnv("TEST_SRCDIR") if !ok { t.Skip("TEST_SRCDIR not set") } workspaceDir, ok := os.LookupEnv("TEST_WORKSPACE") if !ok { t.Skip("TEST_WORKSPACE not set") } uriPrefix := "aws-kms://arn:aws-us-gov:kms:us-gov-east-1:235739564943:key/" tests := []struct { name string credFile string valid bool }{ { name: "valid CSV credentials file", credFile: filepath.Join(srcDir, workspaceDir, "testdata/aws/credentials.csv"), valid: true, }, { name: "valid INI credentials file", credFile: filepath.Join(srcDir, workspaceDir, "testdata/aws/credentials.cred"), valid: true, }, { name: "invalid credentials file", credFile: filepath.Join(srcDir, workspaceDir, "testdata/aws/access_keys_bad.csv"), valid: false, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { _, err := NewClientWithOptions(uriPrefix, WithCredentialPath(test.credFile)) if test.valid && err != nil { t.Errorf("NewClientWithOptions(uriPrefix, WithCredentialPath(%q)) err = %v, want nil", test.credFile, err) } if !test.valid && err == nil { t.Errorf("NewClientWithOptions(uriPrefix, WithCredentialPath(%q)) err = nil, want error", test.credFile) } // Test deprecated factory function. _, err = NewClientWithCredentials(uriPrefix, test.credFile) if test.valid && err != nil { t.Errorf("NewClientWithCredentials(uriPrefix, %q) err = %v, want nil", test.credFile, err) } if !test.valid && err == nil { t.Errorf("NewClientWithCredentials(uriPrefix, %q) err = nil, want error", test.credFile) } }) } } func TestNewClientWithOptions_RepeatedWithKMSFails(t *testing.T) { keyARN := "arn:aws:kms:us-east-2:235739564943:key/3ee50705-5a82-4f5b-9753-05c4f473922f" fakekms, err := fakeawskms.New([]string{keyARN}) if err != nil { t.Fatalf("fakekms.New() failed: %v", err) } _, err = NewClientWithOptions("aws-kms://", WithKMS(fakekms), WithKMS(fakekms)) if err == nil { t.Fatalf("NewClientWithOptions(_, WithKMS(_), WithKMS(_)) err = nil, want error") } } func TestNewClientWithOptions_RepeatedWithEncryptionContextNameFails(t *testing.T) { _, err := NewClientWithOptions("aws-kms://", WithEncryptionContextName(LegacyAdditionalData), WithEncryptionContextName(AssociatedData)) if err == nil { t.Fatalf("NewClientWithOptions(_, WithEncryptionContextName(_), WithEncryptionContextName(_)) err = nil, want error") } } func TestSupported(t *testing.T) { uriPrefix := "aws-kms://arn:aws-us-gov:kms:us-gov-east-1:235739564943:key/" supportedKeyURI := "aws-kms://arn:aws-us-gov:kms:us-gov-east-1:235739564943:key/3ee50705-5a82-4f5b-9753-05c4f473922f" nonSupportedKeyURI := "aws-kms://arn:aws-us-gov:kms:us-gov-east-DOES-NOT-EXIST:key/" client, err := NewClientWithOptions(uriPrefix) if err != nil { t.Fatalf("NewClientWithOptions() failed: %v", err) } if !client.Supported(supportedKeyURI) { t.Errorf("client with URI prefix %q should support key URI %q", uriPrefix, supportedKeyURI) } if client.Supported(nonSupportedKeyURI) { t.Errorf("client with URI prefix %q should NOT support key URI %q", uriPrefix, nonSupportedKeyURI) } } func TestGetAEADSupportedURI(t *testing.T) { uriPrefix := "aws-kms://arn:aws-us-gov:kms:us-gov-east-1:235739564943:key/" supportedKeyURI := "aws-kms://arn:aws-us-gov:kms:us-gov-east-1:235739564943:key/3ee50705-5a82-4f5b-9753-05c4f473922f" client, err := NewClientWithOptions(uriPrefix) if err != nil { t.Fatalf("NewClientWithOptions() failed: %v", err) } _, err = client.GetAEAD(supportedKeyURI) if err != nil { t.Errorf("client with URI prefix %q should support key URI %q", uriPrefix, supportedKeyURI) } } func TestGetAEADEncryptDecrypt(t *testing.T) { keyARN := "arn:aws:kms:us-east-2:235739564943:key/3ee50705-5a82-4f5b-9753-05c4f473922f" keyURI := "aws-kms://arn:aws:kms:us-east-2:235739564943:key/3ee50705-5a82-4f5b-9753-05c4f473922f" fakekms, err := fakeawskms.New([]string{keyARN}) if err != nil { t.Fatalf("fakekms.New() failed: %v", err) } client, err := NewClientWithOptions("aws-kms://", WithKMS(fakekms)) if err != nil { t.Fatalf("NewClientWithOptions() failed: %v", err) } a, err := client.GetAEAD(keyURI) if err != nil { t.Fatalf("client.GetAEAD(keyURI) err = %v, want nil", err) } plaintext := []byte("plaintext") associatedData := []byte("associatedData") ciphertext, err := a.Encrypt(plaintext, associatedData) if err != nil { t.Fatalf("a.Encrypt(plaintext, associatedData) err = %v, want nil", err) } decrypted, err := a.Decrypt(ciphertext, associatedData) if err != nil { t.Fatalf("a.Decrypt(ciphertext, associatedData) err = %v, want nil", err) } if !bytes.Equal(decrypted, plaintext) { t.Errorf("decrypted = %q, want %q", decrypted, plaintext) } _, err = a.Decrypt(ciphertext, []byte("invalidAssociatedData")) if err == nil { t.Error("a.Decrypt(ciphertext, []byte(\"invalidAssociatedData\")) err = nil, want error") } _, err = a.Decrypt([]byte("invalidCiphertext"), associatedData) if err == nil { t.Error("a.Decrypt([]byte(\"invalidCiphertext\"), associatedData) err = nil, want error") } } func TestUsesAdditionalDataAsContextName(t *testing.T) { keyARN := "arn:aws:kms:us-east-2:235739564943:key/3ee50705-5a82-4f5b-9753-05c4f473922f" keyURI := "aws-kms://arn:aws:kms:us-east-2:235739564943:key/3ee50705-5a82-4f5b-9753-05c4f473922f" fakekms, err := fakeawskms.New([]string{keyARN}) if err != nil { t.Fatalf("fakeawskms.New() failed: %v", err) } client, err := NewClientWithKMS("aws-kms://", fakekms) if err != nil { t.Fatalf("NewClientWithKMS() failed: %v", err) } a, err := client.GetAEAD(keyURI) if err != nil { t.Fatalf("client.GetAEAD(keyURI) failed: %s", err) } plaintext := []byte("plaintext") associatedData := []byte("associatedData") ciphertext, err := a.Encrypt(plaintext, associatedData) if err != nil { t.Fatalf("a.Encrypt(plaintext, associatedData) err = %v, want nil", err) } hexAD := hex.EncodeToString(associatedData) context := map[string]*string{"additionalData": &hexAD} decRequest := &kms.DecryptInput{ KeyId: aws.String(keyARN), CiphertextBlob: ciphertext, EncryptionContext: context, } decResponse, err := fakekms.Decrypt(decRequest) if err != nil { t.Fatalf("fakeKMS.Decrypt(decRequest) err = %s, want nil", err) } if !bytes.Equal(decResponse.Plaintext, plaintext) { t.Errorf("decResponse.Plaintext = %q, want %q", decResponse.Plaintext, plaintext) } if strings.Compare(*decResponse.KeyId, keyARN) != 0 { t.Errorf("decResponse.KeyId = %q, want %q", *decResponse.KeyId, keyARN) } } func TestEncryptionContextName(t *testing.T) { keyARN := "arn:aws:kms:us-east-2:235739564943:key/3ee50705-5a82-4f5b-9753-05c4f473922f" keyURI := "aws-kms://arn:aws:kms:us-east-2:235739564943:key/3ee50705-5a82-4f5b-9753-05c4f473922f" fakekms, err := fakeawskms.New([]string{keyARN}) if err != nil { t.Fatalf("fakeawskms.New() failed: %v", err) } tests := []struct { contextName EncryptionContextName wantContextName string }{ { contextName: LegacyAdditionalData, wantContextName: "additionalData", }, { contextName: AssociatedData, wantContextName: "associatedData", }, } for _, test := range tests { t.Run(test.wantContextName, func(t *testing.T) { client, err := NewClientWithOptions("aws-kms://", WithKMS(fakekms), WithEncryptionContextName(test.contextName)) if err != nil { t.Fatalf("NewClientWithOptions() failed: %v", err) } a, err := client.GetAEAD(keyURI) if err != nil { t.Fatalf("client.GetAEAD(keyURI) failed: %s", err) } plaintext := []byte("plaintext") associatedData := []byte("associatedData") ciphertext, err := a.Encrypt(plaintext, associatedData) if err != nil { t.Fatalf("a.Encrypt(plaintext, associatedData) err = %v, want nil", err) } hexAD := hex.EncodeToString(associatedData) context := map[string]*string{test.wantContextName: &hexAD} decRequest := &kms.DecryptInput{ KeyId: aws.String(keyARN), CiphertextBlob: ciphertext, EncryptionContext: context, } decResponse, err := fakekms.Decrypt(decRequest) if err != nil { t.Fatalf("fakeKMS.Decrypt(decRequest) err = %s, want nil", err) } if !bytes.Equal(decResponse.Plaintext, plaintext) { t.Errorf("decResponse.Plaintext = %q, want %q", decResponse.Plaintext, plaintext) } if strings.Compare(*decResponse.KeyId, keyARN) != 0 { t.Errorf("decResponse.KeyId = %q, want %q", *decResponse.KeyId, keyARN) } }) } } func TestEncryptionContextName_defaultEncryptionContextName(t *testing.T) { keyARN := "arn:aws:kms:us-east-2:235739564943:key/3ee50705-5a82-4f5b-9753-05c4f473922f" keyURI := "aws-kms://arn:aws:kms:us-east-2:235739564943:key/3ee50705-5a82-4f5b-9753-05c4f473922f" fakekms, err := fakeawskms.New([]string{keyARN}) if err != nil { t.Fatalf("fakeawskms.New() failed: %v", err) } tests := []struct { name string client func(t *testing.T) registry.KMSClient wantContextName string }{ { name: "NewClientWithOptions", client: func(t *testing.T) registry.KMSClient { t.Helper() c, err := NewClientWithOptions(keyURI, WithKMS(fakekms)) if err != nil { t.Fatalf("NewClientWithOptions() failed: %v", err) } return c }, wantContextName: "associatedData", }, // Test deprecated factory function. { name: "NewClientWithKMS", client: func(t *testing.T) registry.KMSClient { t.Helper() c, err := NewClientWithKMS(keyURI, fakekms) if err != nil { t.Fatalf("NewClientWithKMS() failed: %v", err) } return c }, wantContextName: "additionalData", }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { client := test.client(t) a, err := client.GetAEAD(keyURI) if err != nil { t.Fatalf("client.GetAEAD(keyURI) failed: %s", err) } plaintext := []byte("plaintext") associatedData := []byte("associatedData") ciphertext, err := a.Encrypt(plaintext, associatedData) if err != nil { t.Fatalf("a.Encrypt(plaintext, associatedData) err = %v, want nil", err) } hexAD := hex.EncodeToString(associatedData) context := map[string]*string{test.wantContextName: &hexAD} decRequest := &kms.DecryptInput{ KeyId: aws.String(keyARN), CiphertextBlob: ciphertext, EncryptionContext: context, } decResponse, err := fakekms.Decrypt(decRequest) if err != nil { t.Fatalf("fakeKMS.Decrypt(decRequest) err = %s, want nil", err) } if !bytes.Equal(decResponse.Plaintext, plaintext) { t.Errorf("decResponse.Plaintext = %q, want %q", decResponse.Plaintext, plaintext) } if strings.Compare(*decResponse.KeyId, keyARN) != 0 { t.Errorf("decResponse.KeyId = %q, want %q", *decResponse.KeyId, keyARN) } }) } } ================================================ FILE: go/integration/awskms/aws_kms_integration_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package awskms_test import ( "bytes" "errors" "os" "path/filepath" "testing" "flag" // context is used to cancel outstanding requests "github.com/google/tink/go/aead" "github.com/google/tink/go/tink" "github.com/google/tink/go/integration/awskms" ) const ( keyPrefix = "aws-kms://arn:aws:kms:us-east-2:235739564943:" keyAliasURI = "aws-kms://arn:aws:kms:us-east-2:235739564943:alias/unit-and-integration-testing" keyURI = "aws-kms://arn:aws:kms:us-east-2:235739564943:key/3ee50705-5a82-4f5b-9753-05c4f473922f" keyURI2 = "aws-kms://arn:aws:kms:us-east-2:235739564943:key/b3ca2efd-a8fb-47f2-b541-7e20f8c5cd11" ) var ( credCSVFile = "testdata/aws/credentials.csv" credINIFile = "testdata/aws/credentials.ini" ) func init() { certPath := filepath.Join(os.Getenv("TEST_SRCDIR"), "tink_base/roots.pem") flag.Set("cacerts", certPath) os.Setenv("SSL_CERT_FILE", certPath) } func getTestFilePath(filename string) (string, error) { srcDir, ok := os.LookupEnv("TEST_SRCDIR") if !ok { return "", errors.New("TEST_SRCDIR not set") } workspaceDir, ok := os.LookupEnv("TEST_WORKSPACE") if !ok { return "", errors.New("TEST_WORKSPACE not set") } return filepath.Join(srcDir, workspaceDir, filename), nil } func TestNewClientWithCredentialsGetAEADEncryptDecrypt(t *testing.T) { credFilePath, err := getTestFilePath(credCSVFile) if err != nil { t.Skip(err) } client, err := awskms.NewClientWithOptions(keyURI, awskms.WithCredentialPath(credFilePath)) if err != nil { t.Fatalf("error setting up AWS client: %v", err) } a, err := client.GetAEAD(keyURI) if err != nil { t.Fatalf("client.GetAEAD(keyURI) err = %v, want nil", err) } plaintext := []byte("plaintext") associatedData := []byte("associatedData") ciphertext, err := a.Encrypt(plaintext, associatedData) if err != nil { t.Fatalf("a.Encrypt(plaintext, associatedData) err = %v, want nil", err) } gotPlaintext, err := a.Decrypt(ciphertext, associatedData) if err != nil { t.Fatalf("a.Decrypt(ciphertext, associatedData) err = %v, want nil", err) } if !bytes.Equal(gotPlaintext, plaintext) { t.Errorf("a.Decrypt() = %q, want %q", gotPlaintext, plaintext) } invalidAssociatedData := []byte("invalidAssociatedData") _, err = a.Decrypt(ciphertext, invalidAssociatedData) if err == nil { t.Error("a.Decrypt(ciphertext, invalidAssociatedData) err = nil, want error") } } func TestEmptyAssociatedDataEncryptDecrypt(t *testing.T) { credFilePath, err := getTestFilePath(credCSVFile) if err != nil { t.Skip(err) } client, err := awskms.NewClientWithOptions(keyURI, awskms.WithCredentialPath(credFilePath)) if err != nil { t.Fatalf("error setting up AWS client: %v", err) } a, err := client.GetAEAD(keyURI) if err != nil { t.Fatalf("client.GetAEAD(keyURI) err = %v, want nil", err) } plaintext := []byte("plaintext") emptyAssociatedData := []byte{} ciphertext, err := a.Encrypt(plaintext, emptyAssociatedData) if err != nil { t.Fatalf("a.Encrypt(plaintext, emptyAssociatedData) err = %v, want nil", err) } gotPlaintext, err := a.Decrypt(ciphertext, emptyAssociatedData) if err != nil { t.Fatalf("a.Decrypt(ciphertext, associatedData) err = %v, want nil", err) } if !bytes.Equal(gotPlaintext, plaintext) { t.Errorf("a.Decrypt() = %q, want %q", gotPlaintext, plaintext) } gotPlaintext2, err := a.Decrypt(ciphertext, nil) if err != nil { t.Fatalf("a.Decrypt(ciphertext, nil) err = %v, want nil", err) } if !bytes.Equal(gotPlaintext2, plaintext) { t.Errorf("a.Decrypt() = %q, want %q", gotPlaintext, plaintext) } } func TestKeyCommitment(t *testing.T) { credFilePath, err := getTestFilePath(credCSVFile) if err != nil { t.Skip(err) } client, err := awskms.NewClientWithOptions(keyPrefix, awskms.WithCredentialPath(credFilePath)) if err != nil { t.Fatalf("error setting up AWS client: %v", err) } // Create AEAD primitives for two keys. keys := []string{keyURI, keyURI2} aeads := make([]tink.AEAD, 0, len(keys)) for _, k := range keys { a, err := client.GetAEAD(k) if err != nil { t.Fatalf("client.GetAEAD(keyURI) err = %v, want nil", err) } aeads = append(aeads, a) } // Create a ciphertext using the first primitive. plaintext := []byte("plaintext") associatedData := []byte("associated data") ciphertext, err := aeads[0].Encrypt(plaintext, associatedData) if err != nil { t.Fatalf("aeads[0].Encrypt(plaintext, associatedData) err = %v, want nil", err) } gotPlaintext, err := aeads[0].Decrypt(ciphertext, associatedData) if err != nil { t.Fatalf("aeads[0].Decrypt(ciphertext, associatedData) err = %v, want nil", err) } if !bytes.Equal(gotPlaintext, plaintext) { t.Errorf("aeads[0].Decrypt() = %q, want %q", gotPlaintext, plaintext) } // Attempt to decrypt using the other primitive. _, err = aeads[1].Decrypt(ciphertext, associatedData) if err == nil { t.Fatalf("aeads[1].Decrypt(ciphertext, associatedData) err = nil, want non-nil") } } func TestKMSEnvelopeAEADEncryptAndDecrypt(t *testing.T) { for _, credFile := range []string{credCSVFile, credINIFile} { credFilePath, err := getTestFilePath(credFile) if err != nil { t.Skip(err) } client, err := awskms.NewClientWithOptions(keyURI, awskms.WithCredentialPath(credFilePath)) if err != nil { t.Fatalf("awskms.NewClientWithOptions() err = %q, want nil", err) } kekAEAD, err := client.GetAEAD(keyURI) if err != nil { t.Fatalf("client.GetAEAD(keyURI) err = %q, want nil", err) } dekTemplate := aead.AES128CTRHMACSHA256KeyTemplate() a := aead.NewKMSEnvelopeAEAD2(dekTemplate, kekAEAD) if err != nil { t.Fatalf("aead.NewKMSEnvelopeAEAD2(dekTemplate, kekAEAD) err = %q, want nil", err) } plaintext := []byte("plaintext") for _, associatedData := range [][]byte{nil, []byte("associated data")} { ciphertext, err := a.Encrypt(plaintext, associatedData) if err != nil { t.Fatalf("a.Encrypt(plaintext, associatedData) err = %q, want nil", err) } gotPlaintext, err := a.Decrypt(ciphertext, associatedData) if err != nil { t.Fatalf("a.Decrypt(ciphertext, associatedData) err = %q, want nil", err) } if !bytes.Equal(gotPlaintext, plaintext) { t.Errorf("a.Decrypt() = %q, want %q", gotPlaintext, plaintext) } } } } ================================================ FILE: go/integration/awskms/internal/fakeawskms/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) # keep go_library( name = "fakeawskms", srcs = ["fakeawskms.go"], importpath = "github.com/google/tink/go/integration/awskms/internal/fakeawskms", deps = [ "//aead", "//keyset", "//tink", "@com_github_aws_aws_sdk_go//service/kms", "@com_github_aws_aws_sdk_go//service/kms/kmsiface", ], ) go_test( name = "fakeawskms_test", srcs = ["fakeawskms_test.go"], embed = [":fakeawskms"], deps = [ "@com_github_aws_aws_sdk_go//aws", "@com_github_aws_aws_sdk_go//service/kms", ], ) alias( name = "go_default_library", actual = ":fakeawskms", visibility = ["//integration/awskms:__subpackages__"], ) ================================================ FILE: go/integration/awskms/internal/fakeawskms/fakeawskms.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package fakeawskms provides a partial fake implementation of kmsiface.KMSAPI. package fakeawskms import ( "bytes" "errors" "fmt" "sort" "github.com/aws/aws-sdk-go/service/kms" "github.com/aws/aws-sdk-go/service/kms/kmsiface" "github.com/google/tink/go/aead" "github.com/google/tink/go/keyset" "github.com/google/tink/go/tink" ) type fakeAWSKMS struct { kmsiface.KMSAPI aeads map[string]tink.AEAD keyIDs []string } // serializeContext serializes the context map in a canonical way into a byte array. func serializeContext(context map[string]*string) []byte { names := make([]string, 0, len(context)) for name := range context { names = append(names, name) } sort.Strings(names) b := new(bytes.Buffer) b.WriteString("{") for i, name := range names { if i > 0 { b.WriteString(",") } fmt.Fprintf(b, "%q:%q", name, *context[name]) } b.WriteString("}") return b.Bytes() } // New returns a new fake AWS KMS API. func New(validKeyIDs []string) (kmsiface.KMSAPI, error) { aeads := make(map[string]tink.AEAD) for _, keyID := range validKeyIDs { handle, err := keyset.NewHandle(aead.AES256GCMKeyTemplate()) if err != nil { return nil, err } a, err := aead.New(handle) if err != nil { return nil, err } aeads[keyID] = a } return &fakeAWSKMS{ aeads: aeads, keyIDs: validKeyIDs, }, nil } func (f *fakeAWSKMS) Encrypt(request *kms.EncryptInput) (*kms.EncryptOutput, error) { a, ok := f.aeads[*request.KeyId] if !ok { return nil, fmt.Errorf("Unknown keyID: %q not in %q", *request.KeyId, f.keyIDs) } serializedContext := serializeContext(request.EncryptionContext) ciphertext, err := a.Encrypt(request.Plaintext, serializedContext) if err != nil { return nil, err } return &kms.EncryptOutput{ CiphertextBlob: ciphertext, KeyId: request.KeyId, }, nil } func (f *fakeAWSKMS) Decrypt(request *kms.DecryptInput) (*kms.DecryptOutput, error) { serializedContext := serializeContext(request.EncryptionContext) if request.KeyId != nil { a, ok := f.aeads[*request.KeyId] if !ok { return nil, fmt.Errorf("Unknown keyID: %q not in %q", *request.KeyId, f.keyIDs) } plaintext, err := a.Decrypt(request.CiphertextBlob, serializedContext) if err != nil { return nil, fmt.Errorf("Decryption with keyID %q failed", *request.KeyId) } return &kms.DecryptOutput{ Plaintext: plaintext, KeyId: request.KeyId, }, nil } // When KeyId is not set, try out all AEADs. for keyID, a := range f.aeads { plaintext, err := a.Decrypt(request.CiphertextBlob, serializedContext) if err == nil { return &kms.DecryptOutput{ Plaintext: plaintext, KeyId: &keyID, }, nil } } return nil, errors.New("unable to decrypt message") } ================================================ FILE: go/integration/awskms/internal/fakeawskms/fakeawskms_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package fakeawskms import ( "bytes" "strings" "testing" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/kms" ) const validKeyID = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab" const validKeyID2 = "arn:aws:kms:us-west-2:123:key/different" func TestEncyptDecryptWithValidKeyId(t *testing.T) { fakeKMS, err := New([]string{validKeyID}) if err != nil { t.Fatalf("New() err = %s, want nil", err) } plaintext := []byte("plaintext") contextValue := "contextValue" context := map[string]*string{"contextName": &contextValue} encRequest := &kms.EncryptInput{ KeyId: aws.String(validKeyID), Plaintext: plaintext, EncryptionContext: context, } encResponse, err := fakeKMS.Encrypt(encRequest) if err != nil { t.Fatalf("fakeKMS.Encrypt(encRequest) err = %s, want nil", err) } ciphertext := encResponse.CiphertextBlob decRequest := &kms.DecryptInput{ KeyId: aws.String(validKeyID), CiphertextBlob: ciphertext, EncryptionContext: context, } decResponse, err := fakeKMS.Decrypt(decRequest) if err != nil { t.Fatalf("fakeKMS.Decrypt(decRequest) err = %s, want nil", err) } if !bytes.Equal(decResponse.Plaintext, plaintext) { t.Fatalf("decResponse.Plaintext = %q, want %q", decResponse.Plaintext, plaintext) } if strings.Compare(*decResponse.KeyId, validKeyID) != 0 { t.Fatalf("decResponse.KeyId = %q, want %q", *decResponse.KeyId, validKeyID) } // decrypt with a different context should fail otherContextValue := "otherContextValue" otherContext := map[string]*string{"contextName": &otherContextValue} otherDecRequest := &kms.DecryptInput{ KeyId: aws.String(validKeyID), CiphertextBlob: ciphertext, EncryptionContext: otherContext, } if _, err := fakeKMS.Decrypt(otherDecRequest); err == nil { t.Fatal("fakeKMS.Decrypt(otherDecRequest) err = nil, want not nil") } } func TestEncyptWithUnknownKeyID(t *testing.T) { fakeKMS, err := New([]string{validKeyID}) if err != nil { t.Fatalf("New() err = %s, want nil", err) } plaintext := []byte("plaintext") contextValue := "contextValue" context := map[string]*string{"contextName": &contextValue} encRequestWithUnknownKeyID := &kms.EncryptInput{ KeyId: aws.String(validKeyID2), Plaintext: plaintext, EncryptionContext: context, } if _, err := fakeKMS.Encrypt(encRequestWithUnknownKeyID); err == nil { t.Fatal("fakeKMS.Encrypt(encRequestWithvalidKeyID2) err = nil, want not nil") } } func TestDecryptWithInvalidCiphertext(t *testing.T) { fakeKMS, err := New([]string{validKeyID}) if err != nil { t.Fatalf("New() err = %s, want nil", err) } invalidCiphertext := []byte("plaintext") contextValue := "contextValue" context := map[string]*string{"contextName": &contextValue} decRequest := &kms.DecryptInput{ CiphertextBlob: invalidCiphertext, EncryptionContext: context, } if _, err := fakeKMS.Decrypt(decRequest); err == nil { t.Fatal("fakeKMS.Decrypt(decRequest) err = nil, want not nil") } } func TestDecryptWithUnknownKeyId(t *testing.T) { fakeKMS, err := New([]string{validKeyID}) if err != nil { t.Fatalf("New() err = %s, want nil", err) } ciphertext := []byte("invalidCiphertext") contextValue := "contextValue" context := map[string]*string{"contextName": &contextValue} decRequest := &kms.DecryptInput{ KeyId: aws.String(validKeyID2), CiphertextBlob: ciphertext, EncryptionContext: context, } if _, err := fakeKMS.Decrypt(decRequest); err == nil { t.Fatal("fakeKMS.Decrypt(decRequest) err = nil, want not nil") } } func TestDecryptWithWrongKeyId(t *testing.T) { fakeKMS, err := New([]string{validKeyID, validKeyID2}) if err != nil { t.Fatalf("New() err = %s, want nil", err) } plaintext := []byte("plaintext") contextValue := "contextValue" context := map[string]*string{"contextName": &contextValue} encRequest := &kms.EncryptInput{ KeyId: aws.String(validKeyID), Plaintext: plaintext, EncryptionContext: context, } encResponse, err := fakeKMS.Encrypt(encRequest) if err != nil { t.Fatalf("fakeKMS.Encrypt(encRequest) err = %s, want nil", err) } ciphertext := encResponse.CiphertextBlob decRequest := &kms.DecryptInput{ KeyId: aws.String(validKeyID2), // wrong key id CiphertextBlob: ciphertext, EncryptionContext: context, } if _, err := fakeKMS.Decrypt(decRequest); err == nil { t.Fatal("fakeKMS.Decrypt(decRequest) err = nil, want not nil") } } func TestDecryptWithoutKeyId(t *testing.T) { // setting the keyId in DecryptInput is not required, see // https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/kms#DecryptInput fakeKMS, err := New([]string{validKeyID, validKeyID2}) if err != nil { t.Fatalf("New() err = %s, want nil", err) } plaintext := []byte("plaintext") plaintext2 := []byte("plaintext2") contextValue := "contextValue" context := map[string]*string{"contextName": &contextValue} encRequest := &kms.EncryptInput{ KeyId: aws.String(validKeyID), Plaintext: plaintext, EncryptionContext: context, } encResponse, err := fakeKMS.Encrypt(encRequest) if err != nil { t.Fatalf("fakeKMS.Encrypt(encRequest) err = %s, want nil", err) } if strings.Compare(*encResponse.KeyId, validKeyID) != 0 { t.Fatalf("encResponse.KeyId = %q, want %q", *encResponse.KeyId, validKeyID) } encRequest2 := &kms.EncryptInput{ KeyId: aws.String(validKeyID2), Plaintext: plaintext2, EncryptionContext: context, } encResponse2, err := fakeKMS.Encrypt(encRequest2) if err != nil { t.Fatalf("fakeKMS.Encrypt(encRequest2) err = %s, want nil", err) } if strings.Compare(*encResponse2.KeyId, validKeyID2) != 0 { t.Fatalf("encResponse2.KeyId = %q, want %q", *encResponse2.KeyId, validKeyID2) } decRequest := &kms.DecryptInput{ // KeyId is not set CiphertextBlob: encResponse.CiphertextBlob, EncryptionContext: context, } decResponse, err := fakeKMS.Decrypt(decRequest) if err != nil { t.Fatalf("fakeKMS.Decrypt(decRequest) err = %s, want nil", err) } if !bytes.Equal(decResponse.Plaintext, plaintext) { t.Fatalf("decResponse.Plaintext = %q, want %q", decResponse.Plaintext, plaintext) } if strings.Compare(*decResponse.KeyId, validKeyID) != 0 { t.Fatalf("decResponse.KeyId = %q, want %q", *decResponse.KeyId, validKeyID) } decRequest2 := &kms.DecryptInput{ // KeyId is not set CiphertextBlob: encResponse2.CiphertextBlob, EncryptionContext: context, } decResponse2, err := fakeKMS.Decrypt(decRequest2) if err != nil { t.Fatalf("fakeKMS.Decrypt(decRequest2) err = %s, want nil", err) } if !bytes.Equal(decResponse2.Plaintext, plaintext2) { t.Fatalf("decResponse.Plaintext = %q, want %q", decResponse.Plaintext, plaintext2) } if strings.Compare(*decResponse2.KeyId, validKeyID2) != 0 { t.Fatalf("decResponse2.KeyId = %q, want %q", *decResponse2.KeyId, validKeyID2) } } func TestSerializeContext(t *testing.T) { uvw := "uvw" xyz := "xyz" rst := "rst" context := map[string]*string{"def": &uvw, "abc": &xyz, "ghi": &rst} got := string(serializeContext(context)) want := "{\"abc\":\"xyz\",\"def\":\"uvw\",\"ghi\":\"rst\"}" if got != want { t.Fatalf("SerializeContext(context) = %s, want %s", got, want) } gotEscaped := string(serializeContext(map[string]*string{"a\"b": &xyz})) wantEscaped := "{\"a\\\"b\":\"xyz\"}" if gotEscaped != wantEscaped { t.Fatalf("SerializeContext(context) = %s, want %s", gotEscaped, wantEscaped) } gotEmpty := string(serializeContext(map[string]*string{})) if gotEmpty != "{}" { t.Fatalf("SerializeContext(context) = %s, want %s", gotEmpty, "{}") } } ================================================ FILE: go/integration/gcpkms/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) # keep go_library( name = "gcpkms", srcs = [ "gcp_kms_aead.go", "gcp_kms_client.go", ], importpath = "github.com/google/tink/go/integration/gcpkms", visibility = ["//visibility:public"], deps = [ "//core/registry", "//tink", "@org_golang_google_api//cloudkms/v1:cloudkms", "@org_golang_google_api//option", ], ) go_test( name = "gcpkms_test", srcs = [ "gcp_kms_aead_test.go", "gcp_kms_client_test.go", "gcp_kms_integration_test.go", ], data = [ # Google Cloud KMS credentials to be used. "//testdata/gcp:credentials", "@google_root_pem//file", #keep ], embed = [":gcpkms"], tags = ["manual"], deps = [ "//aead", "@org_golang_google_api//cloudkms/v1:cloudkms", "@org_golang_google_api//option", ], ) alias( name = "go_default_library", actual = ":gcpkms", visibility = ["//visibility:public"], ) ================================================ FILE: go/integration/gcpkms/gcp_kms_aead.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package gcpkms import ( "encoding/base64" "fmt" "hash/crc32" "google.golang.org/api/cloudkms/v1" "github.com/google/tink/go/tink" ) // gcpAEAD represents a GCP KMS service to a particular URI. type gcpAEAD struct { keyName string kms cloudkms.Service } var _ tink.AEAD = (*gcpAEAD)(nil) // newGCPAEAD returns a new GCP KMS service. func newGCPAEAD(keyName string, kms *cloudkms.Service) tink.AEAD { return &gcpAEAD{ keyName: keyName, kms: *kms, } } // Encrypt calls GCP KMS to encrypt the plaintext with associatedData and returns the resulting ciphertext. // It returns an error if the call to KMS fails or if the response returned by KMS does not pass integrity verification // (http://cloud.google.com/kms/docs/data-integrity-guidelines#calculating_and_verifying_checksums). func (a *gcpAEAD) Encrypt(plaintext, associatedData []byte) ([]byte, error) { req := &cloudkms.EncryptRequest{ Plaintext: base64.URLEncoding.EncodeToString(plaintext), PlaintextCrc32c: computeChecksum(plaintext), AdditionalAuthenticatedData: base64.URLEncoding.EncodeToString(associatedData), AdditionalAuthenticatedDataCrc32c: computeChecksum(associatedData), // Send the integrity verification fields even if their value is 0. ForceSendFields: []string{"PlaintextCrc32c", "AdditionalAuthenticatedDataCrc32c"}, } resp, err := a.kms.Projects.Locations.KeyRings.CryptoKeys.Encrypt(a.keyName, req).Do() if err != nil { return nil, err } if !resp.VerifiedPlaintextCrc32c { return nil, fmt.Errorf("KMS request for %q is missing the checksum field plaintext_crc32c, and other information may be missing from the response. Please retry a limited number of times in case the error is transient", a.keyName) } if !resp.VerifiedAdditionalAuthenticatedDataCrc32c { return nil, fmt.Errorf("KMS request for %q is missing the checksum field additional_authenticated_data_crc32c, and other information may be missing from the response. Please retry a limited number of times in case the error is transient", a.keyName) } ciphertext, err := base64.StdEncoding.DecodeString(resp.Ciphertext) if err != nil { return nil, err } if resp.CiphertextCrc32c != computeChecksum(ciphertext) { return nil, fmt.Errorf("KMS response corrupted in transit for %q: the checksum in field ciphertext_crc32c did not match the data in field ciphertext. Please retry in case this is a transient error", a.keyName) } return ciphertext, nil } // Decrypt calls GCP KMS to decrypt the ciphertext with with associatedData and returns the resulting plaintext. // It returns an error if the call to KMS fails or if the response returned by KMS does not pass integrity verification // (http://cloud.google.com/kms/docs/data-integrity-guidelines#calculating_and_verifying_checksums). func (a *gcpAEAD) Decrypt(ciphertext, associatedData []byte) ([]byte, error) { req := &cloudkms.DecryptRequest{ Ciphertext: base64.URLEncoding.EncodeToString(ciphertext), CiphertextCrc32c: computeChecksum(ciphertext), AdditionalAuthenticatedData: base64.URLEncoding.EncodeToString(associatedData), AdditionalAuthenticatedDataCrc32c: computeChecksum(associatedData), // Send the integrity verification fields even if their value is 0. ForceSendFields: []string{"CiphertextCrc32c", "AdditionalAuthenticatedDataCrc32c"}, } resp, err := a.kms.Projects.Locations.KeyRings.CryptoKeys.Decrypt(a.keyName, req).Do() if err != nil { return nil, err } plaintext, err := base64.StdEncoding.DecodeString(resp.Plaintext) if err != nil { return nil, err } if resp.PlaintextCrc32c != computeChecksum(plaintext) { return nil, fmt.Errorf("KMS response corrupted in transit for %q: the checksum in field plaintext_crc32c did not match the data in field plaintext. Please retry in case this is a transient error", a.keyName) } return plaintext, nil } // crc32cTable is used to compute checksums. It is defined as a package level variable to avoid // re-computation on every CRC calculation. var crc32cTable = crc32.MakeTable(crc32.Castagnoli) // computeChecksum returns the checksum that corresponds to the input value as an int64. func computeChecksum(value []byte) int64 { return int64(crc32.Checksum(value, crc32cTable)) } ================================================ FILE: go/integration/gcpkms/gcp_kms_aead_test.go ================================================ // Copyright 2024 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package gcpkms import ( "bytes" "context" "encoding/base64" "encoding/json" "hash/crc32" "net/http" "net/http/httptest" "testing" "google.golang.org/api/cloudkms/v1" "google.golang.org/api/option" ) func initializeServerWithResponse(ctx context.Context, t *testing.T, response any) (*httptest.Server, *cloudkms.Service) { t.Helper() var b []byte switch r := response.(type) { case *cloudkms.EncryptResponse, *cloudkms.DecryptResponse: var err error b, err = json.Marshal(r) if err != nil { t.Fatalf("unable to marshal response: %v", err) } default: t.Fatalf("unsupported response type: %T", r) } ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write(b) })) svc, err := cloudkms.NewService(ctx, option.WithoutAuthentication(), option.WithEndpoint(ts.URL)) if err != nil { t.Fatalf("unable to create client: %v", err) } return ts, svc } func TestEncrypt_FailsWhenPlaintextUnverifed(t *testing.T) { additionalData := []byte("additional data") ciphertext := []byte("ciphertext") ciphertextCrc32c := int64(crc32.Checksum(ciphertext, crc32.MakeTable(crc32.Castagnoli))) testcases := []struct { name string encryptResponse *cloudkms.EncryptResponse }{ { name: "verified_plaintext_crc32c is false", encryptResponse: &cloudkms.EncryptResponse{ Ciphertext: base64.StdEncoding.EncodeToString(ciphertext), CiphertextCrc32c: ciphertextCrc32c, VerifiedPlaintextCrc32c: false, VerifiedAdditionalAuthenticatedDataCrc32c: true, }, }, { name: "verified_plaintext_crc32c missing", encryptResponse: &cloudkms.EncryptResponse{ Ciphertext: base64.StdEncoding.EncodeToString(ciphertext), CiphertextCrc32c: ciphertextCrc32c, VerifiedAdditionalAuthenticatedDataCrc32c: true, }, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { ctx := context.Background() ts, svc := initializeServerWithResponse(ctx, t, tc.encryptResponse) defer ts.Close() aead := newGCPAEAD("key name", svc) // Encryption should fail for all plaintexts (empty or non-empty) _, err := aead.Encrypt([]byte("plaintext"), additionalData) if err == nil { t.Errorf("a.Encrypt err = nil, want error") } _, err = aead.Encrypt([]byte(""), additionalData) if err == nil { t.Errorf("a.Encrypt err = nil, want error") } }) } } func TestEncrypt_FailsWhenAdditionalAuthenticatedDataUnverifed(t *testing.T) { plaintext := []byte("plaintext") ciphertext := []byte("ciphertext") ciphertextCrc32c := int64(crc32.Checksum(ciphertext, crc32.MakeTable(crc32.Castagnoli))) testcases := []struct { name string encryptResponse *cloudkms.EncryptResponse }{ { name: "verified_additional_authenticated_data_crc32c is false", encryptResponse: &cloudkms.EncryptResponse{ Ciphertext: base64.StdEncoding.EncodeToString(ciphertext), CiphertextCrc32c: ciphertextCrc32c, VerifiedPlaintextCrc32c: true, VerifiedAdditionalAuthenticatedDataCrc32c: false, }, }, { name: "verified_additional_authenticated_data_crc32c missing", encryptResponse: &cloudkms.EncryptResponse{ Ciphertext: base64.StdEncoding.EncodeToString(ciphertext), CiphertextCrc32c: ciphertextCrc32c, VerifiedPlaintextCrc32c: true, }, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { ctx := context.Background() ts, svc := initializeServerWithResponse(ctx, t, tc.encryptResponse) defer ts.Close() aead := newGCPAEAD("key name", svc) // Encryption should fail for all additional authenticated data (empty or non-empty) _, err := aead.Encrypt(plaintext, []byte("additional data")) if err == nil { t.Errorf("a.Encrypt err = nil, want error") } _, err = aead.Encrypt(plaintext, []byte("")) if err == nil { t.Errorf("a.Encrypt err = nil, want error") } }) } } func TestEncrypt_FailsWithInvalidCiphertextCrc32c(t *testing.T) { testcases := []struct { name string encryptResponse *cloudkms.EncryptResponse }{ { name: "ciphertext_crc32c does not match ciphertext", encryptResponse: &cloudkms.EncryptResponse{ Ciphertext: base64.StdEncoding.EncodeToString([]byte("ciphertext")), CiphertextCrc32c: int64(1), VerifiedPlaintextCrc32c: true, VerifiedAdditionalAuthenticatedDataCrc32c: true, }, }, { name: "ciphertext_crc32c missing", encryptResponse: &cloudkms.EncryptResponse{ Ciphertext: base64.StdEncoding.EncodeToString([]byte("ciphertext")), VerifiedPlaintextCrc32c: true, VerifiedAdditionalAuthenticatedDataCrc32c: true, }, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { ctx := context.Background() ts, svc := initializeServerWithResponse(ctx, t, tc.encryptResponse) defer ts.Close() aead := newGCPAEAD("key name", svc) _, err := aead.Encrypt([]byte("plaintext"), []byte("additional data")) if err == nil { t.Errorf("a.Encrypt err = nil, want error") } }) } } func TestEncrypt_Success(t *testing.T) { ciphertext := []byte("ciphertext") ciphertextCrc32c := int64(crc32.Checksum(ciphertext, crc32.MakeTable(crc32.Castagnoli))) ctx := context.Background() ts, svc := initializeServerWithResponse(ctx, t, &cloudkms.EncryptResponse{ Ciphertext: base64.StdEncoding.EncodeToString(ciphertext), CiphertextCrc32c: ciphertextCrc32c, VerifiedPlaintextCrc32c: true, VerifiedAdditionalAuthenticatedDataCrc32c: true, }) defer ts.Close() aead := newGCPAEAD("key name", svc) gotCiphertext, err := aead.Encrypt([]byte("plaintext"), []byte("additional data")) if err != nil { t.Errorf("a.Encrypt err = %q, want nil", err) } if !bytes.Equal(gotCiphertext, ciphertext) { t.Errorf("Returned ciphertext: %q, want: %q", gotCiphertext, ciphertext) } } func TestDecrypt_FailsWithInvalidPlaintextCrc32c(t *testing.T) { testcases := []struct { name string decryptResponse *cloudkms.DecryptResponse }{ { name: "plaintext_crc32c does not match plaintext", decryptResponse: &cloudkms.DecryptResponse{ Plaintext: base64.StdEncoding.EncodeToString([]byte("plaintext")), PlaintextCrc32c: int64(1), }, }, { name: "plaintext_crc32c missing", decryptResponse: &cloudkms.DecryptResponse{ Plaintext: base64.StdEncoding.EncodeToString([]byte("plaintext")), }, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { ctx := context.Background() ts, svc := initializeServerWithResponse(ctx, t, tc.decryptResponse) defer ts.Close() aead := newGCPAEAD("key name", svc) _, err := aead.Decrypt([]byte("ciphertext"), []byte("additional data")) if err == nil { t.Errorf("a.Decrypt err = nil, want error") } }) } } func TestDecrypt_Success(t *testing.T) { plaintext := []byte("plaintext") plaintextCrc32c := int64(crc32.Checksum(plaintext, crc32.MakeTable(crc32.Castagnoli))) ctx := context.Background() ts, svc := initializeServerWithResponse(ctx, t, &cloudkms.DecryptResponse{ Plaintext: base64.StdEncoding.EncodeToString(plaintext), PlaintextCrc32c: plaintextCrc32c, }) defer ts.Close() aead := newGCPAEAD("key name", svc) gotPlaintext, err := aead.Decrypt([]byte("ciphertext"), []byte("additional data")) if err != nil { t.Errorf("a.Decrypt err = %q, want nil", err) } if !bytes.Equal(gotPlaintext, plaintext) { t.Errorf("Returned plaitext: %q, want: %q", gotPlaintext, plaintext) } } ================================================ FILE: go/integration/gcpkms/gcp_kms_client.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package gcpkms provides integration with the GCP Cloud KMS. // Tink APIs work with GCP and AWS KMS. package gcpkms import ( "context" "errors" "fmt" "runtime" "strings" "google.golang.org/api/cloudkms/v1" "google.golang.org/api/option" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/tink" ) const ( gcpPrefix = "gcp-kms://" ) var ( errCred = errors.New("invalid credential path") tinkUserAgent = "Tink/" + tink.Version + " Golang/" + runtime.Version() ) // gcpClient represents a client that connects to the GCP KMS backend. type gcpClient struct { keyURIPrefix string kms *cloudkms.Service } var _ registry.KMSClient = (*gcpClient)(nil) // NewClientWithOptions returns a new GCP KMS client with provided Google API // options to handle keys with uriPrefix prefix. // uriPrefix must have the following format: 'gcp-kms://[:path]'. func NewClientWithOptions(ctx context.Context, uriPrefix string, opts ...option.ClientOption) (registry.KMSClient, error) { if !strings.HasPrefix(strings.ToLower(uriPrefix), gcpPrefix) { return nil, fmt.Errorf("uriPrefix must start with %s", gcpPrefix) } opts = append(opts, option.WithUserAgent(tinkUserAgent)) kmsService, err := cloudkms.NewService(ctx, opts...) if err != nil { return nil, err } return &gcpClient{ keyURIPrefix: uriPrefix, kms: kmsService, }, nil } // Supported true if this client does support keyURI func (c *gcpClient) Supported(keyURI string) bool { return strings.HasPrefix(keyURI, c.keyURIPrefix) } // GetAEAD gets an AEAD backend by keyURI. func (c *gcpClient) GetAEAD(keyURI string) (tink.AEAD, error) { if !c.Supported(keyURI) { return nil, errors.New("unsupported keyURI") } keyName := strings.TrimPrefix(keyURI, gcpPrefix) return newGCPAEAD(keyName, c.kms), nil } ================================================ FILE: go/integration/gcpkms/gcp_kms_client_test.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package gcpkms_test import ( "context" "log" "google.golang.org/api/option" "github.com/google/tink/go/aead" "github.com/google/tink/go/integration/gcpkms" ) func Example() { const keyURI = "gcp-kms://......" ctx := context.Background() gcpclient, err := gcpkms.NewClientWithOptions(ctx, keyURI, option.WithCredentialsFile("/mysecurestorage/credentials.json")) if err != nil { log.Fatal(err) } kekAEAD, err := gcpclient.GetAEAD(keyURI) if err != nil { log.Fatal(err) } // Get the KMS envelope AEAD primitive. dekTemplate := aead.AES128CTRHMACSHA256KeyTemplate() primitive := aead.NewKMSEnvelopeAEAD2(dekTemplate, kekAEAD) if err != nil { log.Fatal(err) } // Use the primitive. plaintext := []byte("message") associatedData := []byte("example KMS envelope AEAD encryption") ciphertext, err := primitive.Encrypt(plaintext, associatedData) if err != nil { log.Fatal(err) } _, err = primitive.Decrypt(ciphertext, associatedData) if err != nil { log.Fatal(err) } } ================================================ FILE: go/integration/gcpkms/gcp_kms_integration_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package gcpkms_test import ( "bytes" "context" "os" "path/filepath" "testing" "flag" // context is used to cancel outstanding requests "google.golang.org/api/option" "github.com/google/tink/go/aead" "github.com/google/tink/go/integration/gcpkms" ) const ( keyURI = "gcp-kms://projects/tink-test-infrastructure/locations/global/keyRings/unit-and-integration-testing/cryptoKeys/aead-key" ) var ( credFile = "testdata/gcp/credential.json" ) func init() { certPath := filepath.Join(os.Getenv("TEST_SRCDIR"), "tink_base/roots.pem") flag.Set("cacerts", certPath) os.Setenv("SSL_CERT_FILE", certPath) } func TestGetAeadWithEnvelopeAead(t *testing.T) { srcDir, ok := os.LookupEnv("TEST_SRCDIR") if !ok { t.Skip("TEST_SRCDIR not set") } workspaceDir, ok := os.LookupEnv("TEST_WORKSPACE") if !ok { t.Skip("TEST_WORKSPACE not set") } ctx := context.Background() gcpClient, err := gcpkms.NewClientWithOptions( ctx, keyURI, option.WithCredentialsFile(filepath.Join(srcDir, workspaceDir, credFile))) if err != nil { t.Fatalf("gcpkms.NewClientWithOptions() err = %q, want nil", err) } kekAEAD, err := gcpClient.GetAEAD(keyURI) if err != nil { t.Fatalf("gcpClient.GetAEAD(keyURI) err = %q, want nil", err) } dekTemplate := aead.AES128CTRHMACSHA256KeyTemplate() a := aead.NewKMSEnvelopeAEAD2(dekTemplate, kekAEAD) if err != nil { t.Fatalf("a.Encrypt(plaintext, associatedData) err = %q, want nil", err) } plaintext := []byte("message") associatedData := []byte("example KMS envelope AEAD encryption") ciphertext, err := a.Encrypt(plaintext, associatedData) if err != nil { t.Fatalf("a.Encrypt(plaintext, associatedData) err = %q, want nil", err) } gotPlaintext, err := a.Decrypt(ciphertext, associatedData) if err != nil { t.Fatalf("a.Decrypt(ciphertext, associatedData) err = %q, want nil", err) } if !bytes.Equal(gotPlaintext, plaintext) { t.Errorf("a.Decrypt() = %q, want %q", gotPlaintext, plaintext) } _, err = a.Decrypt(ciphertext, []byte("invalid associatedData")) if err == nil { t.Error("a.Decrypt(ciphertext, []byte(\"invalid associatedData\")) err = nil, want error") } } func TestAead(t *testing.T) { srcDir, ok := os.LookupEnv("TEST_SRCDIR") if !ok { t.Skip("TEST_SRCDIR not set") } workspaceDir, ok := os.LookupEnv("TEST_WORKSPACE") if !ok { t.Skip("TEST_WORKSPACE not set") } ctx := context.Background() gcpClient, err := gcpkms.NewClientWithOptions( ctx, keyURI, option.WithCredentialsFile(filepath.Join(srcDir, workspaceDir, credFile))) if err != nil { t.Fatalf("gcpkms.NewClientWithOptions() err = %q, want nil", err) } aead, err := gcpClient.GetAEAD(keyURI) if err != nil { t.Fatalf("gcpClient.GetAEAD(keyURI) err = %q, want nil", err) } testcases := []struct { name string plaintext []byte associatedData []byte }{ { name: "empty_plaintext", plaintext: []byte(""), associatedData: []byte("authenticated data"), }, { name: "empty_associated_data", plaintext: []byte("plaintext"), associatedData: []byte(""), }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { ciphertext, err := aead.Encrypt(tc.plaintext, tc.associatedData) if err != nil { t.Fatalf("aead.Encrypt(plaintext, associatedData) err = %q, want nil", err) } gotPlaintext, err := aead.Decrypt(ciphertext, tc.associatedData) if err != nil { t.Fatalf("aead.Decrypt(ciphertext, associatedData) err = %q, want nil", err) } if !bytes.Equal(gotPlaintext, tc.plaintext) { t.Errorf("aead.Decrypt() = %q, want %q", gotPlaintext, tc.plaintext) } }) } } ================================================ FILE: go/integration/hcvault/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) # keep go_library( name = "hcvault", srcs = [ "hcvault_aead.go", "hcvault_client.go", ], importpath = "github.com/google/tink/go/integration/hcvault", visibility = ["//visibility:public"], deps = [ "//core/registry", "//tink", "@com_github_hashicorp_vault_api//:api", ], ) go_test( name = "hcvault_test", srcs = [ "hcvault_aead_internal_test.go", "hcvault_aead_test.go", "hcvault_client_test.go", ], embed = [":hcvault"], deps = [ "//aead", "@com_github_hashicorp_vault_api//:api", ], ) alias( name = "go_default_library", actual = ":hcvault", visibility = ["//:__subpackages__"], ) ================================================ FILE: go/integration/hcvault/hcvault_aead.go ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hcvault import ( "encoding/base64" "errors" "fmt" "strings" "github.com/hashicorp/vault/api" "github.com/google/tink/go/tink" ) // vaultAEAD represents a HashiCorp Vault service to a particular URI. type vaultAEAD struct { encKeyPath string decKeyPath string client *api.Logical associatedDataName string } var _ tink.AEAD = (*vaultAEAD)(nil) const ( encryptSegment = "encrypt" decryptSegment = "decrypt" defaultAssociatedDataName = "associated_data" legacyAssociatedDataName = "context" ) // AEADOption is an interface for defining options that are passed to [NewAEAD]. type AEADOption interface{ set(*vaultAEAD) error } type option func(*vaultAEAD) error func (o option) set(a *vaultAEAD) error { return o(a) } // WithLegacyContextParamater lets the remote AEAD populate the "context" parameter // in encrypt and decrypt requests instead of the "associated_data". // // Using this option makes the AEAD compatible with the instance returned by GetAEAD // from the KMSClient returned by NewClient. For new keys, this option should not be used. // // ## Warning // // Vault only uses the "context" parameter for keys which have derivation enabled // (with "derived=true") and ignores it otherwise. For such keys, the "context" // parameter is required to be non-empty. // // Therefore: // - for keys with "derived=false", you should only use empty associated data. // - for keys with "derived=true", you should only use non-empty associated data. // // With Tink's "KMS envelope AEAD", always use a key with "derived=false". // // For reference, see https://developer.hashicorp.com/vault/api-docs/secret/transit. func WithLegacyContextParamater() AEADOption { return option(func(a *vaultAEAD) error { a.associatedDataName = legacyAssociatedDataName return nil }) } // NewAEAD returns a new remote AEAD primitive for a HashiCorp Vault service. func NewAEAD(keyPath string, client *api.Logical, opts ...AEADOption) (tink.AEAD, error) { encKeyPath, decKeyPath, err := getEndpointPaths(keyPath) if err != nil { return nil, err } a := &vaultAEAD{ encKeyPath: encKeyPath, decKeyPath: decKeyPath, client: client, associatedDataName: defaultAssociatedDataName, } // Process options, if any. for _, opt := range opts { if err := opt.set(a); err != nil { return nil, fmt.Errorf("failed setting option: %v", err) } } return a, nil } func extractCiphertext(secret *api.Secret) ([]byte, error) { if secret == nil { return nil, errors.New("secret is nil") } c, ok := secret.Data["ciphertext"] if !ok { return nil, errors.New("no ciphertext") } ciphertext, ok := c.(string) if !ok { return nil, errors.New("invalid ciphertext") } if len(ciphertext) == 0 { return nil, errors.New("empty ciphertext") } return []byte(ciphertext), nil } // Encrypt encrypts the plaintext data using a key stored in HashiCorp Vault. func (a *vaultAEAD) Encrypt(plaintext, associatedData []byte) ([]byte, error) { // Create an encryption request map according to Vault REST API: // https://www.vaultproject.io/api/secret/transit/index.html#encrypt-data. req := map[string]any{ "plaintext": base64.StdEncoding.EncodeToString(plaintext), a.associatedDataName: base64.StdEncoding.EncodeToString(associatedData), } secret, err := a.client.Write(a.encKeyPath, req) if err != nil { return nil, err } return extractCiphertext(secret) } func extractPlaintext(secret *api.Secret) ([]byte, error) { // Note that when a valid ciphertext of the empty string is decrypted, // secret.Data["plaintext"] may not be set. So we allow that. if secret == nil { return []byte{}, nil } p, ok := secret.Data["plaintext"] if !ok { return []byte{}, nil } plaintext64, ok := p.(string) if !ok { return nil, errors.New("invalid plaintext") } plaintext, err := base64.StdEncoding.DecodeString(plaintext64) if err != nil { return nil, err } return plaintext, nil } // Decrypt decrypts the ciphertext using a key stored in HashiCorp Vault. func (a *vaultAEAD) Decrypt(ciphertext, associatedData []byte) ([]byte, error) { // Create a decryption request map according to Vault REST API: // https://www.vaultproject.io/api/secret/transit/index.html#decrypt-data. req := map[string]any{ "ciphertext": string(ciphertext), a.associatedDataName: base64.StdEncoding.EncodeToString(associatedData), } secret, err := a.client.Write(a.decKeyPath, req) if err != nil { return nil, err } return extractPlaintext(secret) } // getEndpointPaths transforms keyPath into the Vault transit encrypt and decrypt // paths. The keyPath is expected to have the form "/{mount-path}/keys/{keyName}", which will // be transformed to // "{mount-path}/encrypt/{keyName}" and "{mount-path}/decrypt/{keyName}". func getEndpointPaths(keyPath string) (encryptPath, decryptPath string, err error) { parts := strings.Split(keyPath, "/") length := len(parts) if length < 4 || parts[0] != "" || parts[length-2] != "keys" { return "", "", errors.New("malformed keyPath") } parts[length-2] = encryptSegment encryptPath = strings.Join(parts[1:], "/") parts[length-2] = decryptSegment decryptPath = strings.Join(parts[1:], "/") return encryptPath, decryptPath, nil } ================================================ FILE: go/integration/hcvault/hcvault_aead_internal_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hcvault import ( "bytes" "testing" "github.com/hashicorp/vault/api" ) func TestGetEndpointPaths(t *testing.T) { for _, tc := range []struct { desc string path string enc string dec string err string }{ { desc: "simple", path: "/transit/keys/foo", enc: "transit/encrypt/foo", dec: "transit/decrypt/foo", }, { desc: "escaped", path: "/transit/keys/this%2Band+that", enc: "transit/encrypt/this%2Band+that", dec: "transit/decrypt/this%2Band+that", }, { desc: "sub-path", path: "/teams/billing/something/transit/keys/pci-key", enc: "teams/billing/something/transit/encrypt/pci-key", dec: "teams/billing/something/transit/decrypt/pci-key", }, { desc: "transit-twice", path: "/transit/keys/something/transit/keys/my-key", enc: "transit/keys/something/transit/encrypt/my-key", dec: "transit/keys/something/transit/decrypt/my-key", }, { desc: "mount-not-named-transit", path: "/cipher/keys/hi", enc: "cipher/encrypt/hi", dec: "cipher/decrypt/hi", }, { desc: "no leading slash", path: "transit/keys/foo", err: "malformed keyPath", }, { desc: "empty", path: "", err: "malformed keyPath", }, { desc: "slash-only", path: "/", err: "malformed keyPath", }, { desc: "not-transit", path: "/foo/bar/baz", err: "malformed keyPath", }, { desc: "not-end-of-path", path: "/transit/keys/bar/baz", err: "malformed keyPath", }, } { t.Run(tc.desc, func(t *testing.T) { encPath, decPath, err := getEndpointPaths(tc.path) if err == nil { if tc.err != "" { t.Errorf("getEndpointPaths(%q) err is nil, want %q", tc.path, tc.err) } } else { if tc.err != err.Error() { t.Errorf("getEndpointPaths(%q) err = %v; want %q", tc.path, err, tc.err) } } if encPath != tc.enc { t.Errorf("getEndpointPaths(%q) encryptPath = %q, want %q", tc.path, encPath, tc.enc) } if decPath != tc.dec { t.Errorf("getEndpointPaths(%q) decryptPath = %q, want %q", tc.path, decPath, tc.dec) } }) } } func TestExtractCiphertextFails(t *testing.T) { for _, tc := range []struct { desc string secret *api.Secret }{ { desc: "nil", secret: nil, }, { desc: "empty data", secret: &api.Secret{ Data: map[string]any{}, }, }, { desc: "empty ciphertext", secret: &api.Secret{ Data: map[string]any{"ciphertext": ""}, }, }, { desc: "wrong type", secret: &api.Secret{ Data: map[string]any{"ciphertext": 123}, }, }, } { t.Run(tc.desc, func(t *testing.T) { _, err := extractCiphertext(tc.secret) if err == nil { t.Error("extractCiphertext() err is nil, want error") } }) } } func TestExtractCiphertextWorks(t *testing.T) { secret := &api.Secret{ Data: map[string]any{"ciphertext": "ciphertext"}, } got, err := extractCiphertext(secret) if err != nil { t.Fatalf("extractCiphertext() err = %q, want nil", err) } want := []byte("ciphertext") if !bytes.Equal(got, want) { t.Errorf("extractCiphertext() = %q, want %q", got, want) } } func TestExtractPlaintextFails(t *testing.T) { for _, tc := range []struct { desc string secret *api.Secret }{ { desc: "wrong type", secret: &api.Secret{ Data: map[string]any{"plaintext": 123}, }, }, } { t.Run(tc.desc, func(t *testing.T) { _, err := extractPlaintext(tc.secret) if err == nil { t.Error("extractPlaintext() err is nil, want error") } }) } } func TestExtractPlaintextWorks(t *testing.T) { for _, tc := range []struct { desc string secret *api.Secret want []byte }{ { desc: "normal", secret: &api.Secret{ Data: map[string]any{"plaintext": "cGxhaW50ZXh0"}, }, want: []byte("plaintext"), }, { desc: "empty plaintext", secret: &api.Secret{ Data: map[string]any{"plaintext": ""}, }, want: []byte{}, }, { desc: "empty data", secret: &api.Secret{ Data: map[string]any{}, }, want: []byte{}, }, } { t.Run(tc.desc, func(t *testing.T) { got, err := extractPlaintext(tc.secret) if err != nil { t.Fatalf("extractPlaintext() err = %q, want nil", err) } if !bytes.Equal(got, tc.want) { t.Errorf("extractPlaintext() = %q, want %q", got, tc.want) } }) } } ================================================ FILE: go/integration/hcvault/hcvault_aead_test.go ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hcvault_test import ( "bytes" "crypto/tls" "crypto/x509" "encoding/base64" "encoding/json" "fmt" "net/http" "net/http/httptest" "strings" "testing" vault_api "github.com/hashicorp/vault/api" "github.com/google/tink/go/integration/hcvault" ) const ( keyURITmpl = "%s/transit/keys/key-1" token = "mytoken" ) func TestVaultNewAEAD_EncryptDecrypt(t *testing.T) { server, _, tlsConfig := newServer(t) defer server.Close() client := newVaultAPIClient(t, server.URL, token, tlsConfig) aead, err := hcvault.NewAEAD("/transit/keys/key-1", client.Logical()) if err != nil { t.Fatalf("hcvault.NewAEAD() err = %v, want nil", err) } plaintext := []byte("plaintext") associatedData := []byte("associatedData") ciphertext, err := aead.Encrypt(plaintext, associatedData) if err != nil { t.Fatalf("aead.Encrypt(plaintext, associatedData) err = %v, want nil", err) } gotPlaintext, err := aead.Decrypt(ciphertext, associatedData) if err != nil { t.Fatalf("aead.Decrypt(ciphertext, associatedData) err = %v, want nil", err) } if !bytes.Equal(gotPlaintext, plaintext) { t.Fatalf("aead.Decrypt(ciphertext, associatedData) = %s, want %s", gotPlaintext, plaintext) } otherAssociatedData := []byte("otherAssociatedData") _, err = aead.Decrypt(ciphertext, otherAssociatedData) if err == nil { t.Error("aead.Decrypt(ciphertext, otherAssociatedData) err = nil, want error") } } func TestVaultNewAEAD_DecryptWithFixedCiphertext(t *testing.T) { server, _, tlsConfig := newServer(t) defer server.Close() client := newVaultAPIClient(t, server.URL, token, tlsConfig) aead, err := hcvault.NewAEAD("/transit/keys/key-1", client.Logical()) if err != nil { t.Fatalf("hcvault.NewAEAD() err = %v, want nil", err) } // associatedData is passed as "context" parameter to vault decrypt. plaintext := []byte("plaintext") associatedData := []byte("associatedData") ciphertext := fakeEncrypt(plaintext, associatedData, nil) gotPlaintext, err := aead.Decrypt(ciphertext, associatedData) if err != nil { t.Fatalf("aead.Decrypt(ciphertext, associatedData) err = %v, want nil", err) } if !bytes.Equal(gotPlaintext, plaintext) { t.Fatalf("aead.Decrypt(ciphertext, associatedData) = %s, want %s", gotPlaintext, associatedData) } } func TestVaultNewAEADWithLegacyContextParamater_isCompatible(t *testing.T) { server, uriPrefix, tlsConfig := newServer(t) defer server.Close() client := newVaultAPIClient(t, server.URL, token, tlsConfig) // Create AEAD with WithLegacyContextParamater. aead1, err := hcvault.NewAEAD("/transit/keys/key-1", client.Logical(), hcvault.WithLegacyContextParamater()) if err != nil { t.Fatalf("hcvault.NewAEAD() err = %v, want nil", err) } // Create AEAD with hcvault.NewClient and GetAEAD. hcvaultClient, err := hcvault.NewClient(uriPrefix, tlsConfig, token) if err != nil { t.Fatalf("hcvault.NewClient() err = %v, want nil", err) } keyURI := fmt.Sprintf("%s/transit/keys/key-1", uriPrefix) aead2, err := hcvaultClient.GetAEAD(keyURI) if err != nil { t.Fatalf("hcvaultClient.GetAEAD(%q) err = %v, want nil", keyURI, err) } plaintext := []byte("plaintext") associatedData := []byte("associatedData") ciphertext2, err := aead2.Encrypt(plaintext, associatedData) if err != nil { t.Fatalf("aead2.Encrypt(plaintext, associatedData) err = %v, want nil", err) } gotPlaintext1, err := aead1.Decrypt(ciphertext2, associatedData) if err != nil { t.Fatalf("aead1.Decrypt(ciphertext, associatedData) err = %v, want nil", err) } if !bytes.Equal(gotPlaintext1, plaintext) { t.Fatalf("aead1.Decrypt(ciphertext2, associatedData) = %s, want %s", gotPlaintext1, plaintext) } ciphertext1, err := aead1.Encrypt(plaintext, associatedData) if err != nil { t.Fatalf("aead2.Encrypt(plaintext, associatedData) err = %v, want nil", err) } gotPlaintext2, err := aead2.Decrypt(ciphertext1, associatedData) if err != nil { t.Fatalf("aead2.Decrypt(ciphertext1, associatedData) err = %v, want nil", err) } if !bytes.Equal(gotPlaintext2, plaintext) { t.Fatalf("aead2.Decrypt(ciphertext1, associatedData) = %s, want %s", gotPlaintext2, plaintext) } } func TestVaultClientAEAD_EncryptDecrypt(t *testing.T) { server, uriPrefix, tlsConfig := newServer(t) defer server.Close() client, err := hcvault.NewClient(uriPrefix, tlsConfig, token) if err != nil { t.Fatalf("hcvault.NewClient() err = %v, want nil", err) } keyURI := fmt.Sprintf(keyURITmpl, uriPrefix) aead, err := client.GetAEAD(keyURI) if err != nil { t.Fatalf("client.GetAEAD(%q) err = %v, want nil", keyURI, err) } plaintext := []byte("plaintext") context := []byte("context") ciphertext, err := aead.Encrypt(plaintext, context) if err != nil { t.Fatalf("aead.Encrypt(plaintext, context) err = %v, want nil", err) } gotPlaintext, err := aead.Decrypt(ciphertext, context) if err != nil { t.Fatalf("aead.Decrypt(ciphertext, context) err = %v, want nil", err) } if !bytes.Equal(gotPlaintext, plaintext) { t.Fatalf("aead.Decrypt(ciphertext, context) = %s, want %s", gotPlaintext, plaintext) } invalidContext := []byte("invalidContext") _, err = aead.Decrypt(ciphertext, invalidContext) if err == nil { t.Error("aead.Decrypt(ciphertext, invalidContext) err = nil, want error") } } func TestVaultClientAEAD_DecryptWithFixedCiphertext(t *testing.T) { server, uriPrefix, tlsConfig := newServer(t) defer server.Close() client, err := hcvault.NewClient(uriPrefix, tlsConfig, token) if err != nil { t.Fatalf("hcvault.NewClient() err = %v, want nil", err) } keyURI := fmt.Sprintf(keyURITmpl, uriPrefix) aead, err := client.GetAEAD(keyURI) if err != nil { t.Fatalf("client.GetAEAD(%q) err = %v, want nil", keyURI, err) } // associatedData is passed as "context" parameter to vault decrypt. plaintext := []byte("plaintext") context := []byte("context") ciphertext := fakeEncrypt(plaintext, nil, context) gotPlaintext, err := aead.Decrypt(ciphertext, context) if err != nil { t.Fatalf("aead.Decrypt(ciphertext, context) err = %v, want nil", err) } if !bytes.Equal(gotPlaintext, plaintext) { t.Fatalf("aead.Decrypt(ciphertext, context) = %s, want %s", gotPlaintext, plaintext) } } func TestGetAEADFailWithBadKeyURI(t *testing.T) { server, uriPrefix, tlsConfig := newServer(t) defer server.Close() client, err := hcvault.NewClient(uriPrefix, tlsConfig, token) if err != nil { t.Fatalf("hcvault.NewClient() err = %v, want nil", err) } for _, test := range []struct { name string keyURI string }{ { name: "empty", keyURI: fmt.Sprintf("%s/", uriPrefix), }, { name: "without slash", keyURI: fmt.Sprintf("%s/badKeyUri", uriPrefix), }, { name: "with one slash", keyURI: fmt.Sprintf("%s/bad/KeyUri", uriPrefix), }, { name: "with three slash", keyURI: fmt.Sprintf("%s/one/two/three/four", uriPrefix), }, } { t.Run(test.name, func(t *testing.T) { if _, err := client.GetAEAD(test.keyURI); err == nil { t.Errorf("client.GetAEAD(%q) err = nil, want error", test.keyURI) } }) } } // newVaultAPIClient creates a new vault API client func newVaultAPIClient(t *testing.T, url string, token string, tlsConfig *tls.Config) *vault_api.Client { t.Helper() httpClient := vault_api.DefaultConfig().HttpClient transport := httpClient.Transport.(*http.Transport) transport.TLSClientConfig = tlsConfig.Clone() cfg := &vault_api.Config{ Address: url, HttpClient: httpClient, } client, err := vault_api.NewClient(cfg) if err != nil { t.Fatal(err) } client.SetToken(token) return client } type closeFunc func() error // newServer returns a fake, TLS-enabled Vault server, an "hcvault://" URI // prefix for accessing it, and a TLS configuration which trusts the servers // certificate. // // Once finished with the server, it's Close() method should be called. // // The URL and TLS configuration can be passed to hcvault.NewClient(). // // The URL can also be used to construct valid key URIs for the server. func newServer(t *testing.T) (server *httptest.Server, uriPrefix string, clientTLSConfig *tls.Config) { server = httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.RequestURI { // Encrypt case "/v1/transit/encrypt/key-1": decoder := json.NewDecoder(r.Body) var encReq = make(map[string]string) if err := decoder.Decode(&encReq); err != nil { http.Error(w, fmt.Sprintf("Cannot decode encryption request: %s", err), 400) return } plaintext, err := base64.StdEncoding.DecodeString(encReq["plaintext"]) if err != nil { http.Error(w, "plaintext must be base64 encoded", 400) return } context, err := base64.StdEncoding.DecodeString(encReq["context"]) if err != nil { http.Error(w, "context must be base64 encoded", 400) return } associatedData, err := base64.StdEncoding.DecodeString(encReq["associated_data"]) if err != nil { http.Error(w, "associated_data must be base64 encoded", 400) return } ciphertext := fakeEncrypt(plaintext, associatedData, context) resp := map[string]any{ "data": map[string]string{ "ciphertext": string(ciphertext), }, } respBytes, err := json.Marshal(resp) if err != nil { t.Fatalf("Cannot encode encrypted data: %v", err) } if _, err := w.Write(respBytes); err != nil { t.Fatalf("Cannot send encrypted data response: %v", err) } // Decrypt case "/v1/transit/decrypt/key-1": decoder := json.NewDecoder(r.Body) var decReq = make(map[string]string) if err := decoder.Decode(&decReq); err != nil { http.Error(w, fmt.Sprintf("Cannot decode decryption request: %s", err), 400) return } ciphertext := []byte(decReq["ciphertext"]) context, err := base64.StdEncoding.DecodeString(decReq["context"]) if err != nil { http.Error(w, "context must be base64 encoded", 400) return } associatedData, err := base64.StdEncoding.DecodeString(decReq["associated_data"]) if err != nil { http.Error(w, "associated_data must be base64 encoded", 400) return } plaintext, err := fakeDecrypt(ciphertext, associatedData, context) if err != nil { http.Error(w, fmt.Sprintf("Cannot decrypt ciphertext: %s", err), 400) return } resp := map[string]any{ "data": map[string]string{ "plaintext": base64.StdEncoding.EncodeToString(plaintext), }, } respBytes, err := json.Marshal(resp) if err != nil { t.Fatalf("Cannot encode encrypted data: %v", err) } if _, err := w.Write(respBytes); err != nil { t.Fatalf("Cannot send encrypted data response: %v", err) } default: http.NotFound(w, r) } })) uriPrefix = strings.Replace(server.URL, "https", "hcvault", 1) certpool := x509.NewCertPool() certpool.AddCert(server.Certificate()) clientTLSConfig = &tls.Config{RootCAs: certpool} return server, uriPrefix, clientTLSConfig } // The ciphertext returned by HC Vault is of the form: // // vault:v1: // // where ciphertext is base64-encoded. See: // https://developer.hashicorp.com/vault/api-docs/secret/transit#sample-request-13 // // The ciphertext returned by this fake implementation is of the form: // // enc:::

// // where context, associatedData and plaintext are base64-encoded. // It is deterministic and not secure. func fakeEncrypt(plaintext, associatedData, context []byte) []byte { s := fmt.Sprintf( "enc:%s:%s:%s", base64.StdEncoding.EncodeToString(context), base64.StdEncoding.EncodeToString(associatedData), base64.StdEncoding.EncodeToString(plaintext), ) return []byte(s) } func TestFakeEncrypt(t *testing.T) { want := []byte("enc:Y29udGV4dA==:YXNzb2NpYXRlZERhdGE=:cGxhaW50ZXh0") got := fakeEncrypt([]byte("plaintext"), []byte("associatedData"), []byte("context")) if !bytes.Equal(got, want) { t.Errorf("fakeEncrypt(plaintext, associatedData, context) = %q, want %q", got, want) } } func TestFakeEncryptWithoutAssociatedData(t *testing.T) { want := []byte("enc:Y29udGV4dA==::cGxhaW50ZXh0") got := fakeEncrypt([]byte("plaintext"), nil, []byte("context")) if !bytes.Equal(got, want) { t.Errorf("fakeEncrypt(plaintext, nil, context) = %q, want %q", got, want) } } func TestFakeEncryptWithoutContext(t *testing.T) { want := []byte("enc::YXNzb2NpYXRlZERhdGE=:cGxhaW50ZXh0") got := fakeEncrypt([]byte("plaintext"), []byte("associatedData"), nil) if !bytes.Equal(got, want) { t.Errorf("fakeEncrypt(plaintext, associatedData, nil) = %q, want %q", got, want) } } func fakeDecrypt(ciphertext, associatedData, context []byte) ([]byte, error) { ct := string(ciphertext) parts := strings.Split(ct, ":") if len(parts) != 4 || parts[0] != "enc" { return nil, fmt.Errorf("malformed ciphertext: %s", ciphertext) } context2, err := base64.StdEncoding.DecodeString(parts[1]) if err != nil { return nil, err } if !bytes.Equal(context, context2) { return nil, fmt.Errorf("invalid context: %s != %s", context2, context) } associatedData2, err := base64.StdEncoding.DecodeString(parts[2]) if err != nil { return nil, err } if !bytes.Equal(associatedData2, associatedData) { return nil, fmt.Errorf("invalid associatedData: %s != %s", associatedData2, associatedData) } plaintext, err := base64.StdEncoding.DecodeString(parts[3]) if err != nil { return nil, err } return plaintext, nil } func TestFakeEncryptDecrypt(t *testing.T) { ciphertext := fakeEncrypt([]byte("plaintext"), []byte("associatedData"), []byte("context")) got, err := fakeDecrypt(ciphertext, []byte("associatedData"), []byte("context")) if err != nil { t.Errorf("fakeDecrypt() err = %v, want nil", err) } if want := []byte("plaintext"); !bytes.Equal(got, want) { t.Errorf("fakeDecrypt() = %q, want %q", got, want) } } ================================================ FILE: go/integration/hcvault/hcvault_client.go ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package hcvault provides integration with the [HashiCorp Vault]. // // [HashiCorp Vault]: https://www.vaultproject.io/. package hcvault import ( "crypto/tls" "errors" "fmt" "net/http" "net/url" "strings" "github.com/hashicorp/vault/api" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/tink" ) const ( vaultPrefix = "hcvault://" ) // vaultClient represents a client that connects to the HashiCorp Vault backend. type vaultClient struct { keyURIPrefix string client *api.Logical } var _ registry.KMSClient = (*vaultClient)(nil) // NewClient returns a new client to HashiCorp Vault. // uriPrefix parameter is a valid URI which must have "hcvault" scheme and // vault server address and port. Specific key URIs will be matched against this // prefix to determine if the client supports the key or not. // tlsCfg represents tls.Config which will be used to communicate with Vault // server via HTTPS protocol. If not specified a default tls.Config{} will be // used. func NewClient(uriPrefix string, tlsCfg *tls.Config, token string) (registry.KMSClient, error) { if !strings.HasPrefix(strings.ToLower(uriPrefix), vaultPrefix) { return nil, fmt.Errorf("key URI must start with %s", vaultPrefix) } httpClient := api.DefaultConfig().HttpClient transport := httpClient.Transport.(*http.Transport) if tlsCfg == nil { tlsCfg = &tls.Config{} } else { tlsCfg = tlsCfg.Clone() } transport.TLSClientConfig = tlsCfg vurl, err := url.Parse(uriPrefix) if err != nil { return nil, err } cfg := &api.Config{ Address: "https://" + vurl.Host, HttpClient: httpClient, } client, err := api.NewClient(cfg) if err != nil { return nil, err } client.SetToken(token) return &vaultClient{ keyURIPrefix: uriPrefix, client: client.Logical(), }, nil } // Supported returns true if this client does support keyURI. func (c *vaultClient) Supported(keyURI string) bool { return strings.HasPrefix(keyURI, c.keyURIPrefix) } // GetAEAD gets an AEAD backed by keyURI. // // ## Warning regarding associated data // // This AEAD implementation uses the associated_data value to populate the // "context" parameter in encrypt and decrypt requests, instead of using the // "associated_data" request parameter. This is an artifact of the "associated_data" // parameter not being present when this package was implemented. // // Vault only uses the "context" parameter for keys which have derivation enabled // (with "derived=true") and ignores it otherwise. For such keys, the "context" // parameter is required to be non-empty. // // Therefore: // - for keys with "derived=false", you should only use empty associated data. // - for keys with "derived=true", you should only use non-empty associated data. // // With Tink's "KMS envelope AEAD", always use a key with "derived=false". // // For reference, see https://developer.hashicorp.com/vault/api-docs/secret/transit. func (c *vaultClient) GetAEAD(keyURI string) (tink.AEAD, error) { if !c.Supported(keyURI) { return nil, errors.New("unsupported keyURI") } u, err := url.Parse(keyURI) if err != nil || u.Scheme != "hcvault" { return nil, errors.New("malformed keyURI") } keyPath := u.EscapedPath() return NewAEAD(keyPath, c.client, WithLegacyContextParamater()) } ================================================ FILE: go/integration/hcvault/hcvault_client_test.go ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hcvault_test import ( "crypto/tls" "log" "github.com/google/tink/go/aead" "github.com/google/tink/go/integration/hcvault" ) func Example() { // Use a key with key derivation enabled (with "derived=true") if you use a non-empty // associated_data. const keyURI = "hcvault://hcvault.corp.com:8200/transit/keys/key-1" vaultClient, err := hcvault.NewClient(keyURI, tlsConfig(), vaultToken()) if err != nil { log.Fatal(err) } kekAEAD, err := vaultClient.GetAEAD(keyURI) if err != nil { log.Fatal(err) } dekTemplate := aead.AES128CTRHMACSHA256KeyTemplate() a := aead.NewKMSEnvelopeAEAD2(dekTemplate, kekAEAD) if err != nil { log.Fatal(err) } if err != nil { log.Fatal(err) } plaintext := []byte("plaintext") associatedData := []byte("associatedData") ciphertext, err := a.Encrypt(plaintext, associatedData) if err != nil { log.Fatal(err) } _, err = a.Decrypt(ciphertext, associatedData) if err != nil { log.Fatal(err) } } func tlsConfig() *tls.Config { // Return a TLS configuration used to communicate with Vault server via HTTPS. return nil } func vaultToken() string { return "" // Your Vault token. } ================================================ FILE: go/internal/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") package(default_visibility = ["//:__subpackages__"]) # keep licenses(["notice"]) # keep go_library( name = "internal", srcs = ["internal.go"], importpath = "github.com/google/tink/go/internal", visibility = [ "//insecurecleartextkeyset:__pkg__", "//keyderivation:__pkg__", "//keyset:__pkg__", "//testkeyset:__pkg__", ], ) alias( name = "go_default_library", actual = ":internal", visibility = ["//:__subpackages__"], ) ================================================ FILE: go/internal/aead/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep go_library( name = "aead", srcs = [ "aead.go", "aes_gcm_insecure_iv.go", "chacha20poly1305_insecure_nonce.go", ], importpath = "github.com/google/tink/go/internal/aead", deps = ["@org_golang_x_crypto//chacha20poly1305"], ) go_test( name = "aead_test", srcs = [ "aead_test.go", "aes_gcm_insecure_iv_test.go", "chacha20poly1305_insecure_nonce_test.go", "chacha20poly1305_insecure_nonce_vectors_test.go", ], data = [ "//testdata/testvectors:aes_gcm", "//testdata/testvectors:chacha20_poly1305", ], deps = [ ":aead", "//subtle/random", "//testutil", "@org_golang_x_crypto//chacha20poly1305", ], ) alias( name = "go_default_library", actual = ":aead", visibility = ["//:__subpackages__"], ) ================================================ FILE: go/internal/aead/aead.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package aead provides internal implementations of the AEAD primitive. package aead import "fmt" const ( // AESGCMIVSize is the acceptable IV size defined by RFC 5116. AESGCMIVSize = 12 // AESGCMTagSize is the acceptable tag size defined by RFC 5116. AESGCMTagSize = 16 ) // ValidateAESKeySize checks if the given key size is a valid AES key size. func ValidateAESKeySize(sizeInBytes uint32) error { switch sizeInBytes { case 16, 32: return nil default: return fmt.Errorf("invalid AES key size; want 16 or 32, got %d", sizeInBytes) } } ================================================ FILE: go/internal/aead/aead_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead_test import ( "testing" "github.com/google/tink/go/internal/aead" "github.com/google/tink/go/testutil" ) type AEADSuite struct { testutil.WycheproofSuite TestGroups []*AEADGroup `json:"testGroups"` } type AEADGroup struct { testutil.WycheproofGroup IVSize uint32 `json:"ivSize"` KeySize uint32 `json:"keySize"` TagSize uint32 `json:"tagSize"` Type string `json:"type"` Tests []*AEADCase `json:"tests"` } type AEADCase struct { testutil.WycheproofCase AD testutil.HexBytes `json:"aad"` CT testutil.HexBytes `json:"ct"` IV testutil.HexBytes `json:"iv"` Key testutil.HexBytes `json:"key"` Message testutil.HexBytes `json:"msg"` Tag testutil.HexBytes `json:"tag"` } func TestValidateAESKeySize(t *testing.T) { for _, keySize := range []uint32{8, 16, 24, 32, 40} { err := aead.ValidateAESKeySize(keySize) if keySize == 16 || keySize == 32 { if err != nil { t.Errorf("ValidateAESKeySize(%d): got err %q, want success", keySize, err) } } else if err == nil { t.Errorf("ValidateAESKeySize(%d): got success, want error", keySize) } } } ================================================ FILE: go/internal/aead/aes_gcm_insecure_iv.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead import ( "bytes" "crypto/aes" "crypto/cipher" "errors" "fmt" ) // TODO(b/201070904): Rename to AESGCMInsecureNonce and simplify by getting rid // of the prependIV bool. const ( // aesGCMMaxPlaintextSize is the maximum plaintext size defined by RFC 5116. aesGCMMaxPlaintextSize = (1 << 36) - 31 intSize = 32 << (^uint(0) >> 63) // 32 or 64 maxInt = 1<<(intSize-1) - 1 maxIntPlaintextSize = maxInt - AESGCMIVSize - AESGCMTagSize minNoIVCiphertextSize = AESGCMTagSize minPrependIVCiphertextSize = AESGCMIVSize + AESGCMTagSize ) // AESGCMInsecureIV is an insecure implementation of the AEAD interface that // permits the user to set the IV. type AESGCMInsecureIV struct { key []byte prependIV bool } // NewAESGCMInsecureIV returns an AESGCMInsecureIV instance, where key is the // AES key with length 16 bytes (AES-128) or 32 bytes (AES-256). // // If prependIV is true, both the ciphertext returned from Encrypt and passed // into Decrypt are prefixed with the IV. func NewAESGCMInsecureIV(key []byte, prependIV bool) (*AESGCMInsecureIV, error) { keySize := uint32(len(key)) if err := ValidateAESKeySize(keySize); err != nil { return nil, fmt.Errorf("invalid AES key size: %s", err) } return &AESGCMInsecureIV{ key: key, prependIV: prependIV, }, nil } // Encrypt encrypts plaintext with iv as the initialization vector and // associatedData as associated data. // // If prependIV is true, the returned ciphertext contains both the IV used for // encryption and the actual ciphertext. // If false, the returned ciphertext contains only the actual ciphertext. // // Note: The crypto library's AES-GCM implementation always returns the // ciphertext with an AESGCMTagSize (16-byte) tag. func (i *AESGCMInsecureIV) Encrypt(iv, plaintext, associatedData []byte) ([]byte, error) { if got, want := len(iv), AESGCMIVSize; got != want { return nil, fmt.Errorf("unexpected IV size: got %d, want %d", got, want) } // Seal() checks plaintext length, but this duplicated check avoids panic. var maxPlaintextSize uint64 = maxIntPlaintextSize if maxIntPlaintextSize > aesGCMMaxPlaintextSize { maxPlaintextSize = aesGCMMaxPlaintextSize } if uint64(len(plaintext)) > maxPlaintextSize { return nil, fmt.Errorf("plaintext too long: got %d", len(plaintext)) } cipher, err := i.newCipher() if err != nil { return nil, err } if !i.prependIV { return cipher.Seal(nil, iv, plaintext, associatedData), nil } // Make the capacity of dst large enough so that both the IV and the ciphertext fit inside. dst := make([]byte, 0, AESGCMIVSize+len(plaintext)+cipher.Overhead()) dst = append(dst, iv...) // Seal appends the ciphertext to dst. So the final output is: iv || ciphertext. return cipher.Seal(dst, iv, plaintext, associatedData), nil } // Decrypt decrypts ciphertext with iv as the initialization vector and // associatedData as associated data. // // If prependIV is true, the iv argument and the first AESGCMIVSize bytes of // ciphertext must be equal. The ciphertext argument is as follows: // // | iv | actual ciphertext | tag | // // If false, the ciphertext argument is as follows: // // | actual ciphertext | tag | func (i *AESGCMInsecureIV) Decrypt(iv, ciphertext, associatedData []byte) ([]byte, error) { if len(iv) != AESGCMIVSize { return nil, fmt.Errorf("unexpected IV size: got %d, want %d", len(iv), AESGCMIVSize) } var actualCiphertext []byte if i.prependIV { if len(ciphertext) < minPrependIVCiphertextSize { return nil, fmt.Errorf("ciphertext too short: got %d, want >= %d", len(ciphertext), minPrependIVCiphertextSize) } if !bytes.Equal(iv, ciphertext[:AESGCMIVSize]) { return nil, fmt.Errorf("unequal IVs: iv argument %x, ct prefix %x", iv, ciphertext[:AESGCMIVSize]) } actualCiphertext = ciphertext[AESGCMIVSize:] } else { if len(ciphertext) < minNoIVCiphertextSize { return nil, fmt.Errorf("ciphertext too short: got %d, want >= %d", len(ciphertext), minNoIVCiphertextSize) } actualCiphertext = ciphertext } cipher, err := i.newCipher() if err != nil { return nil, err } plaintext, err := cipher.Open(nil, iv, actualCiphertext, associatedData) if err != nil { return nil, err } return plaintext, nil } // newCipher creates a new AES-GCM cipher using the given key and the crypto // library. func (i *AESGCMInsecureIV) newCipher() (cipher.AEAD, error) { aesCipher, err := aes.NewCipher(i.key) if err != nil { return nil, errors.New("failed to initialize cipher") } ret, err := cipher.NewGCM(aesCipher) if err != nil { return nil, errors.New("failed to initialize cipher") } return ret, nil } ================================================ FILE: go/internal/aead/aes_gcm_insecure_iv_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead_test import ( "bytes" "fmt" "math/rand" "testing" "github.com/google/tink/go/internal/aead" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" ) var aesKeySizes = []uint32{ 16, /*AES-128*/ 32, /*AES-256*/ } func TestAESGCMInsecureIVCiphertextSize(t *testing.T) { for _, keySize := range aesKeySizes { for _, prependIV := range []bool{true, false} { t.Run(fmt.Sprintf("keySize-%d/prependIV-%t", keySize, prependIV), func(t *testing.T) { key := random.GetRandomBytes(uint32(keySize)) a, err := aead.NewAESGCMInsecureIV(key, prependIV) if err != nil { t.Fatalf("NewAESGCMInsecureIV: got err %q, want success", err) } iv := random.GetRandomBytes(aead.AESGCMIVSize) pt := random.GetRandomBytes(32) ad := random.GetRandomBytes(32) ct, err := a.Encrypt(iv, pt, ad) if err != nil { t.Fatalf("Encrypt: got err %q, want success", err) } wantSize := len(pt) + aead.AESGCMTagSize if prependIV { wantSize += aead.AESGCMIVSize } if len(ct) != wantSize { t.Errorf("unexpected ciphertext length: got %d, want %d", len(ct), wantSize) } }) } } } func TestAESGCMInsecureIVKeySize(t *testing.T) { for _, keySize := range aesKeySizes { for _, prependIV := range []bool{true, false} { t.Run(fmt.Sprintf("keySize-%d/prependIV-%t", keySize, prependIV), func(t *testing.T) { if _, err := aead.NewAESGCMInsecureIV(make([]byte, keySize), prependIV); err != nil { t.Errorf("NewAESGCMInsecureIV: got err %q, want success", err) } if _, err := aead.NewAESGCMInsecureIV(make([]byte, keySize+1), prependIV); err == nil { t.Error("NewAESGCMInsecureIV: got success, want err") } if _, err := aead.NewAESGCMInsecureIV(make([]byte, keySize-1), prependIV); err == nil { t.Error("NewAESGCMInsecureIV: got success, want err") } }) } } } func TestAESGCMInsecureIVMismatchedIV(t *testing.T) { for _, keySize := range aesKeySizes { t.Run(fmt.Sprintf("keySize-%d", keySize), func(t *testing.T) { key := random.GetRandomBytes(uint32(keySize)) a, err := aead.NewAESGCMInsecureIV(key, true /*=prependIV*/) if err != nil { t.Fatalf("NewAESGCMInsecureIV: got err %q, want success", err) } iv := random.GetRandomBytes(aead.AESGCMIVSize) pt := random.GetRandomBytes(32) ad := random.GetRandomBytes(32) ct, err := a.Encrypt(iv, pt, ad) if err != nil { t.Fatalf("Encrypt: got err %q, want success", err) } newIV := iv randByte, randBit := rand.Intn(aead.AESGCMIVSize), rand.Intn(8) newIV[randByte] ^= (1 << uint8(randBit)) if _, err := a.Decrypt(newIV, ct, ad); err == nil { t.Error("Decrypt with wrong iv argument: want err, got success") } ctPrefixedWithNewIV := append(newIV, ct[aead.AESGCMIVSize:]...) if _, err := a.Decrypt(iv, ctPrefixedWithNewIV, ad); err == nil { t.Error("Decrypt with ct prefixed with wrong IV: want err, got success") } }) } } func TestAESGCMInsecureIV(t *testing.T) { for _, keySize := range aesKeySizes { for _, prependIV := range []bool{true, false} { for ptSize := 0; ptSize < 75; ptSize++ { t.Run(fmt.Sprintf("keySize-%d/prependIV-%t/ptSize-%d", keySize, prependIV, ptSize), func(t *testing.T) { key := random.GetRandomBytes(uint32(keySize)) a, err := aead.NewAESGCMInsecureIV(key, prependIV) if err != nil { t.Fatalf("NewAESGCMInsecureIV: got err %q, want success", err) } iv := random.GetRandomBytes(aead.AESGCMIVSize) pt := random.GetRandomBytes(uint32(ptSize)) ad := random.GetRandomBytes(uint32(5)) ct, err := a.Encrypt(iv, pt, ad) if err != nil { t.Fatalf("Encrypt: got err %q, want success", err) } got, err := a.Decrypt(iv, ct, ad) if err != nil { t.Fatalf("Decrypt: got err %q, want success", err) } if !bytes.Equal(got, pt) { t.Errorf("Decrypt: got %x, want %x", got, pt) } }) } } } } func TestAESGCMInsecureIVLongPlaintext(t *testing.T) { for _, keySize := range aesKeySizes { for _, prependIV := range []bool{true, false} { ptSize := 16 for ptSize <= 1<<24 { t.Run(fmt.Sprintf("keySize-%d/prependIV-%t/ptSize-%d", keySize, prependIV, ptSize), func(t *testing.T) { key := random.GetRandomBytes(uint32(keySize)) a, err := aead.NewAESGCMInsecureIV(key, prependIV) if err != nil { t.Fatalf("NewAESGCMInsecureIV: got err %q, want success", err) } iv := random.GetRandomBytes(aead.AESGCMIVSize) pt := random.GetRandomBytes(uint32(ptSize)) ad := random.GetRandomBytes(uint32(ptSize / 3)) ct, err := a.Encrypt(iv, pt, ad) if err != nil { t.Fatalf("Encrypt: got err %q, want success", err) } got, err := a.Decrypt(iv, ct, ad) if err != nil { t.Fatalf("Decrypt: got err %q, want success", err) } if !bytes.Equal(got, pt) { t.Errorf("Decrypt: got %x, want %x", got, pt) } }) ptSize += 5 * ptSize / 11 } } } } func TestAESGCMInsecureIVModifyCiphertext(t *testing.T) { key := random.GetRandomBytes(16) for _, prependIV := range []bool{true, false} { t.Run(fmt.Sprintf("prependIV-%t", prependIV), func(t *testing.T) { a, err := aead.NewAESGCMInsecureIV(key, prependIV) if err != nil { t.Fatalf("NewAESGCMInsecureIV: got err %q, want success", err) } iv := random.GetRandomBytes(aead.AESGCMIVSize) pt := random.GetRandomBytes(32) ad := random.GetRandomBytes(33) ct, err := a.Encrypt(iv, pt, ad) if err != nil { t.Fatalf("Encrypt: got err %q, want success", err) } // Flip bits. for i := 0; i < len(ct); i++ { tmpCT := ct[i] for j := 0; j < 8; j++ { ct[i] ^= 1 << uint8(j) tmpIV := iv if prependIV { tmpIV = ct[:aead.AESGCMIVSize] } if _, err := a.Decrypt(tmpIV, ct, ad); err == nil { t.Errorf("ciphertext with flipped byte %d, bit %d: expected err, got success", i, j) } ct[i] = tmpCT } } // Truncate ciphertext. for i := 1; i < len(ct); i++ { if _, err := a.Decrypt(iv, ct[:i], ad); err == nil { t.Errorf("ciphertext truncated to byte %d: expected err, got success", i) } } // Modify associated data. for i := 0; i < len(ad); i++ { tmp := ad[i] for j := 0; j < 8; j++ { ad[i] ^= 1 << uint8(j) if _, err := a.Decrypt(iv, ct, ad); err == nil { t.Errorf("associated data with flipped byte %d, bit %d: expected err, got success", i, j) } ad[i] = tmp } } }) } } func TestAESGCMInsecureIVWycheproofVectors(t *testing.T) { testutil.SkipTestIfTestSrcDirIsNotSet(t) suite := new(AEADSuite) if err := testutil.PopulateSuite(suite, "aes_gcm_test.json"); err != nil { t.Fatalf("failed to populate suite: %s", err) } for _, group := range suite.TestGroups { if err := aead.ValidateAESKeySize(group.KeySize / 8); err != nil { continue } if group.IVSize != aead.AESGCMIVSize*8 { continue } for _, tc := range group.Tests { name := fmt.Sprintf("%s-%s(%d,%d):Case-%d", suite.Algorithm, group.Type, group.KeySize, group.TagSize, tc.CaseID) t.Run(name, func(t *testing.T) { a, err := aead.NewAESGCMInsecureIV(tc.Key, false /*=prependIV*/) if err != nil { t.Fatalf("NewAESGCMInsecureIV: got err %q, want success", err) } var combinedCT []byte combinedCT = append(combinedCT, tc.CT...) combinedCT = append(combinedCT, tc.Tag...) got, err := a.Decrypt(tc.IV, combinedCT, tc.AD) if err != nil { if tc.Result == "valid" { t.Errorf("Decrypt: got err %q, want success", err) } } else { if tc.Result == "invalid" { t.Error("Decrypt: got success, want error") } if !bytes.Equal(got, tc.Message) { t.Errorf("Decrypt: got %x, want %x", got, tc.Message) } } }) } } } func TestPreallocatedCiphertextMemoryIsExact(t *testing.T) { key := random.GetRandomBytes(16) a, err := aead.NewAESGCMInsecureIV(key, true /*=prependIV*/) if err != nil { t.Fatalf("aead.NewAESGCMInsecureIV() err = %v, want nil", err) } iv := random.GetRandomBytes(aead.AESGCMIVSize) plaintext := random.GetRandomBytes(13) associatedData := random.GetRandomBytes(17) ciphertext, err := a.Encrypt(iv, plaintext, associatedData) if err != nil { t.Fatalf("a.Encrypt() err = %v, want nil", err) } // Encrypt() uses cipher.Overhead() to pre-allocate the memory needed store the ciphertext. // For AES GCM, the size of the allocated memory should always be exact. If this check fails, the // pre-allocated memory was too large or too small. If it was too small, the system had to // re-allocate more memory, which is expensive and should be avoided. if len(ciphertext) != cap(ciphertext) { t.Errorf("want len(ciphertext) == cap(ciphertext), got %d != %d", len(ciphertext), cap(ciphertext)) } } ================================================ FILE: go/internal/aead/chacha20poly1305_insecure_nonce.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead import ( "errors" "fmt" "golang.org/x/crypto/chacha20poly1305" ) const poly1305TagSize = 16 // ChaCha20Poly1305InsecureNonce is an insecure implementation of the AEAD // interface that permits the user to set the nonce. type ChaCha20Poly1305InsecureNonce struct { Key []byte } // NewChaCha20Poly1305InsecureNonce returns a ChaCha20Poly1305InsecureNonce instance. // The key argument should be a 32-bytes key. func NewChaCha20Poly1305InsecureNonce(key []byte) (*ChaCha20Poly1305InsecureNonce, error) { if len(key) != chacha20poly1305.KeySize { return nil, errors.New("bad key length") } return &ChaCha20Poly1305InsecureNonce{Key: key}, nil } // Encrypt encrypts plaintext with nonce and associatedData. func (ca *ChaCha20Poly1305InsecureNonce) Encrypt(nonce, plaintext, associatedData []byte) ([]byte, error) { if len(plaintext) > maxInt-chacha20poly1305.NonceSize-poly1305TagSize { return nil, fmt.Errorf("plaintext too long") } c, err := chacha20poly1305.New(ca.Key) if err != nil { return nil, err } return c.Seal(nil, nonce, plaintext, associatedData), nil } // Decrypt decrypts ciphertext with nonce and associatedData. func (ca *ChaCha20Poly1305InsecureNonce) Decrypt(nonce, ciphertext, associatedData []byte) ([]byte, error) { if len(nonce) != chacha20poly1305.NonceSize { return nil, fmt.Errorf("bad nonce length") } if len(ciphertext) < poly1305TagSize { return nil, fmt.Errorf("ciphertext too short") } c, err := chacha20poly1305.New(ca.Key) if err != nil { return nil, err } return c.Open(nil, nonce, ciphertext, associatedData) } ================================================ FILE: go/internal/aead/chacha20poly1305_insecure_nonce_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead_test import ( "bytes" "encoding/hex" "fmt" "math/rand" "testing" "golang.org/x/crypto/chacha20poly1305" "github.com/google/tink/go/internal/aead" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" ) // TODO(b/201070904): Improve tests and rename aad to ad. func TestChaCha20Poly1305EncryptDecrypt(t *testing.T) { for i, test := range chaCha20Poly1305Tests { key, err := hex.DecodeString(test.key) if err != nil { t.Fatalf("hex.DecodeString(test.key) err = %q, want nil", err) } pt, err := hex.DecodeString(test.plaintext) if err != nil { t.Fatalf("hex.DecodeString(test.plaintext) err = %q, want nil", err) } aad, err := hex.DecodeString(test.aad) if err != nil { t.Fatalf("hex.DecodeString(test.aad) err = %q, want nil", err) } nonce, err := hex.DecodeString(test.nonce) if err != nil { t.Fatalf("hex.DecodeString(test.nonce) err = %q, want nil", err) } ct, err := hex.DecodeString(test.out) if err != nil { t.Fatalf("hex.DecodeString(test.out) err = %q, want nil", err) } ca, err := aead.NewChaCha20Poly1305InsecureNonce(key) if err != nil { t.Errorf("#%d, cannot create new instance of ChaCha20Poly1305: %s", i, err) continue } _, err = ca.Encrypt(nonce, pt, aad) if err != nil { t.Errorf("#%d, unexpected encryption error: %s", i, err) continue } if got, err := ca.Decrypt(nonce, ct, aad); err != nil { t.Errorf("#%d, unexpected decryption error: %s", i, err) continue } else if !bytes.Equal(pt, got) { t.Errorf("#%d, plaintext's don't match: got %x vs %x", i, got, pt) continue } } } func TestChaCha20Poly1305EmptyAssociatedData(t *testing.T) { key := random.GetRandomBytes(chacha20poly1305.KeySize) ca, err := aead.NewChaCha20Poly1305InsecureNonce(key) if err != nil { t.Fatal(err) } for i := 0; i < 75; i++ { pt := random.GetRandomBytes(uint32(i)) emptyAADs := [][]byte{[]byte{}, nil} for _, encAAD := range emptyAADs { nonce := random.GetRandomBytes(chacha20poly1305.NonceSize) ct, err := ca.Encrypt(nonce, pt, encAAD) if err != nil { t.Errorf("Encrypt() err = %v, want nil", err) continue } for _, decAAD := range emptyAADs { got, err := ca.Decrypt(nonce, ct, decAAD) if err != nil { t.Errorf("Decrypt() err = %v, want nil", err) } if want := pt; !bytes.Equal(want, got) { t.Errorf("Decrypt() = %x, want %x", got, want) } } badAAD := []byte{1, 2, 3} if _, err := ca.Decrypt(nonce, ct, badAAD); err == nil { t.Errorf("Decrypt() err = nil, want error") } } } } func TestChaCha20Poly1305LongMessages(t *testing.T) { dataSize := uint32(16) // Encrypts and decrypts messages of size <= 8192. for dataSize <= 1<<24 { pt := random.GetRandomBytes(dataSize) aad := random.GetRandomBytes(dataSize / 3) key := random.GetRandomBytes(chacha20poly1305.KeySize) ca, err := aead.NewChaCha20Poly1305InsecureNonce(key) if err != nil { t.Fatal(err) } nonce := random.GetRandomBytes(chacha20poly1305.NonceSize) ct, err := ca.Encrypt(nonce, pt, aad) if err != nil { t.Errorf("Encrypt(%x, %x) failed", pt, aad) continue } if got, err := ca.Decrypt(nonce, ct, aad); err != nil || !bytes.Equal(pt, got) { t.Errorf("Decrypt(Encrypt(pt, %x)): plaintext's don't match: got %x vs %x; error: %v", aad, got, pt, err) } dataSize += 5 * dataSize / 11 } } func TestChaCha20Poly1305ModifyCiphertext(t *testing.T) { for i, test := range chaCha20Poly1305Tests { key, err := hex.DecodeString(test.key) if err != nil { t.Fatalf("hex.DecodeString(test.key) err = %q, want nil", err) } pt, err := hex.DecodeString(test.plaintext) if err != nil { t.Fatalf("hex.DecodeString(test.plaintext) err = %q, want nil", err) } aad, err := hex.DecodeString(test.aad) if err != nil { t.Fatalf("hex.DecodeString(test.aad) err = %q, want nil", err) } ca, err := aead.NewChaCha20Poly1305InsecureNonce(key) if err != nil { t.Fatal(err) } nonce := random.GetRandomBytes(chacha20poly1305.NonceSize) ct, err := ca.Encrypt(nonce, pt, aad) if err != nil { t.Errorf("#%d: Encrypt failed", i) continue } if len(aad) > 0 { alterAadIdx := rand.Intn(len(aad)) aad[alterAadIdx] ^= 0x80 if _, err := ca.Decrypt(nonce, ct, aad); err == nil { t.Errorf("#%d: Decrypt was successful after altering additional data", i) continue } aad[alterAadIdx] ^= 0x80 } alterCtIdx := rand.Intn(len(ct)) ct[alterCtIdx] ^= 0x80 if _, err := ca.Decrypt(nonce, ct, aad); err == nil { t.Errorf("#%d: Decrypt was successful after altering ciphertext", i) continue } ct[alterCtIdx] ^= 0x80 } } // This is a very simple test for the randomness of the nonce. // The test simply checks that the multiple ciphertexts of the same message are distinct. func TestChaCha20Poly1305RandomNonce(t *testing.T) { key := random.GetRandomBytes(chacha20poly1305.KeySize) ca, err := aead.NewChaCha20Poly1305InsecureNonce(key) if err != nil { t.Fatal(err) } cts := make(map[string]bool) pt, aad := []byte{}, []byte{} for i := 0; i < 1<<10; i++ { nonce := random.GetRandomBytes(chacha20poly1305.NonceSize) ct, err := ca.Encrypt(nonce, pt, aad) ctHex := hex.EncodeToString(ct) if err != nil || cts[ctHex] { t.Errorf("TestRandomNonce failed: %v", err) } else { cts[ctHex] = true } } } func TestChaCha20Poly1305WycheproofCases(t *testing.T) { testutil.SkipTestIfTestSrcDirIsNotSet(t) suite := new(AEADSuite) if err := testutil.PopulateSuite(suite, "chacha20_poly1305_test.json"); err != nil { t.Fatalf("failed populating suite: %s", err) } for _, group := range suite.TestGroups { if group.KeySize/8 != chacha20poly1305.KeySize { continue } if group.IVSize/8 != chacha20poly1305.NonceSize { continue } for _, test := range group.Tests { caseName := fmt.Sprintf("%s-%s:Case-%d", suite.Algorithm, group.Type, test.CaseID) t.Run(caseName, func(t *testing.T) { runChaCha20Poly1305WycheproofCase(t, test) }) } } } func runChaCha20Poly1305WycheproofCase(t *testing.T, tc *AEADCase) { ca, err := aead.NewChaCha20Poly1305InsecureNonce(tc.Key) if err != nil { t.Fatalf("cannot create new instance of ChaCha20Poly1305: %s", err) } nonce := random.GetRandomBytes(chacha20poly1305.NonceSize) _, err = ca.Encrypt(nonce, tc.Message, tc.AD) if err != nil { t.Fatalf("unexpected encryption error: %s", err) } ct := append(tc.CT, tc.Tag...) decrypted, err := ca.Decrypt(tc.IV, ct, tc.AD) if err != nil { if tc.Result == "valid" { t.Errorf("unexpected error: %s", err) } } else { if tc.Result == "invalid" { t.Error("decrypted invalid") } if !bytes.Equal(decrypted, tc.Message) { t.Error("incorrect decryption") } } } ================================================ FILE: go/internal/aead/chacha20poly1305_insecure_nonce_vectors_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aead_test var chaCha20Poly1305Tests = []struct { plaintext, aad, key, nonce, out string }{ { "", "", "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "070000004041424344454647", "a0784d7a4716f3feb4f64e7f4b39bf04", }, { "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e", "50515253c0c1c2c3c4c5c6c7", "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "070000004041424344454647", "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd0600691", }, { "1400000cebccee3bf561b292340fec60", "00000000000000001603030010", "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", "129039b5572e8a7a8131f76a", "2b487a2941bc07f3cc76d1a531662588ee7c2598e59778c24d5b27559a80d163", }, { "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000", "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", "129039b5572e8a7a8131f76a", "3f487a25aa70e9c8391763370569c9e83b7650dd1921c8b78869f241f25d2096c910b180930c5b8747fd90959fe8ca2dcadb4fa50fa1439f916b2301e1cc0810d6725775d3ab86721700f96e22709b0a7a8bef32627dd929b2dd3ba15772b669062bb558bc92e6c241a1d60d9f0035e80c335f854815fe1138ab8af653eab3e122135feeec7dfaba1cc24af82a2b7acccdd824899a7e03cc29c25be8a4f56a66673845b93bae1556f09dafc89a0d22af207718e2a6bb022e9d917597295992ea3b750cc0e7a7c3d33b23c5a8aeab45f5bb542f6c9e6c1747ae5a344aff483ba38577ad534b33b3abc7d284776ea33ed488c2a2475648a4fcda561745ea7787ed60f2368deb27c75adce6ff9b6cc6de1f5e72a741e2d59f64751b3ae482d714e0c90e83c671ff98ed611823afb39e6e5019a6ba548a2a72e829c7b7b4a101ac9deb90a25d3e0c50d22e1fc26c7c02296fa13c6d9c14767f68aaf46450a8d0fd5feb60d9d73c6e68623425b4984a79d619dd6bf896459aa77a681ec9c1a97f645e121f47779b051f8948a817f84d1f55da170d5bbbaf2f64e18b97ed3fd822db2819f523314f1e5ac72e8f69bbe6c87c22daddb0e1ac6790f8534071de2f258064b99789bfb165b065b8fe96f9127cd7dca9f7cb0368420f1e802faa3ca23792f2a5b93773dd405e71c320b211b54f7a26626b03c060e1ab87f32ac588abfa056ce090bd7c69913a700c80f325bfe824fa", }, { "0967de57eefe1aaa999b9b746d88a1a248000d8734e0e938c6aa87", "e4f0a3a4f90a8250f8806aa319053e8d73c62f150e2f239563037e9cc92823ad18c65111d0d462c954cc6c6ed2aafb45702a5a7e597d13bd8091594ab97cf7d1", "f2db28620582e05f00f31c808475ca3df1c20e340bf14828352499466d79295f", "4349e2131d44dc711148dfe3", "bd06cc144fdc0d8b735fa4452eabbf78fd4ad2966ea41a84f68da40ca2da439777bc2ba6c4ec2de0d003eb", }, { "c4c920fb52a56fe66eaa8aa3fa187c543e3db8e5c8094c4313dc4ed35dfc5821c5791d171e8cfe8d37883031a0ad", "85deea3dc4", "05ff881d1e151bab4ca3db7d44880222733fe62686f71ce1e4610f2ea19599a7", "b34710f65aed442e4a40866b", "b154452fb7e85d175dd0b0db08591565c5587a725cf22386922f5d27a01015aba778975510b38754b2182e24352f019b7ad493e1ed255906715644aec6e0", }, { "c4b337df5e83823900c6c202e93541cf5bc8c677a9aad8b8d87a4d7221e294e595cbc4f34e462d4e0def50f62491c57f598cf60236cfba0f4908816aea154f80e013732e59a07c668fcc5cb35d2232b7ae29b9e4f874f3417c74ab6689fae6690d5a9766fa13cd8adf293d3d4b70f4f999adde9121d1d29d467d04cf77ea398444d0ea3fe4b7c9c3e106002c76f4260fa204a0c3d5", "72611bef65eb664f24ea94f4d5d3d88c9c9c6da29c9a1991c02833c4c9f6993b57b5", "dd0f2d4bb1c9e5ca5aa5f38d69bc8402f7dbb7229857b4a41b3044d481b7655e", "2bbca0910cc47ca0b8517391", "83aa28d6d98901e2981d21d3758ae4db8cce07fe08d82ca6f036a68daa88a7dda56eeb38040c942bdda0fd2d369eec44bd070e2c9314992f68dc16989a6ac0c3912c378cf3254f4bae74a66b075e828df6f855c0d8a827ffed3c03582c12a9112eeb7be43dfe8bd78beb2d1e56678b99a0372531727cb7f2b98d2f917ec10de93fe86267100c20356e80528c5066688c8b7acba76e591449952343f663993d5b642e59eb0f", }, { "a9775b8e42b63335439cf1c79fe8a3560b3baebfdfc9ef239d70da02cea0947817f00659a63a8ee9d67fb1756854cc738f7a326e432191e1916be35f0b78d72268de7c0e180af7ee8aa864f2fc30658baa97f9edb88ace49f5b2a8002a8023925e9fa076a997643340c8253cf88ac8a221c190d94c5e224110cb423a4b65cca9046c1fad0483e1444c0680449148e7b20a778c56d5ae97e679d920c43eed6d42598cf05d10d1a15cd722a0686a871b74fea7cad45562bacf3bda937ac701bc218dac7e9d7d20f955429abdac21d821207febf4d54daea4898837035038bf71c66cef63e90f5d3e51f7fcfe18d41f38540a2c2958dacde16304e4b33da324030f1366f923c337", "74ba3372d308910b5c9c3885f41252d57556", "9cf77bd06a4ed8fb59349791b98ba40b6019611942f5768e8be2ee88477149e3", "b928935c4c966c60fd6583c0", "ec7fd64fd75b254961a2b7fc942470d8620f439258b871d0d00f58028b5e0bee5e139e8108ac439391465d6658f559b1df57aa21cf826ede1a28bc11af885e13eebfc009870928fae8abfdd943a60c54fca93f0502dc23d29c2fd5340f9bc0e6ef2a18b66ef627af95f796d5bbca50de22c8ec802da9397089b25c6ba5262468e3977b45dc112e51896c70731b0a52d7efec7c93b41995823436bf4b0c477ae79684407c9831b487928b2b8303caca752b3edf1f0598e15831155462706f94ef3fa3a9e5f937f37085afa9b4bbf939d275796a61b78f70597acfd25cd87f967021cd99328fc371b5eb5739869520657b30e4a5b0db7c8715cbe275dee78e719b357d3a9731f9eaba95986479bb2004a77822fc115a3d", }, { "b3d3128bce6bbf66fd78f1a18352bae56bfcdae18b65c379ee0aeb37ee54fba1270d2df578ec5b75654d16e89fd1cd0acda7ec580dafd2fbbabd32a8112d49383a762db2638928c8d63eb0750f7e7fdd256b35321b072dd5c45f7dd58cc60dc63d3b79a0c4a1689adf180fef968eccbcfa01ee15091ceacd7b67a3082db0ce6aeb470aafe87249c88b58b721e783dde184ccf68de8e05b6347fe6b74ae3adf9a81e9496a5c9332e7ebe908d26ce6b3f0b2a97e9a89d9fdd0d7694585a3241f240d698e69fcc050e7a959ba153f6d06f117848ba05d887134f1b6b994dad9b9e74247513e08a125b1fadfc7394dcd2a6451b504ae3e75e22f2b9bc405747dedb6c43ef4ccdf1a7edaf9451346123eaa63f3af113124f361508e255503a242b96680ae3360c8b13ac1f64d08088bb26b7f617cb0866f11d6fd362b00d86eba3fee68724e302388f119d6f92161ac8ce00d08919377a26974d99575b1032ff0f1976240c785c8b89e9eb2bf005e4be06b5371ffca14683fedfdb49e00e38ff27af1324177faf91599abd5990920797574eb743effdc7decda318ada1419cc8e0bfecf82f9c99792746c2b", "7e8da4f3018f673f8e43bd7a1dee05f8031ec49129c361abbc2a434e9eaf791c3c1d0f3dad767d3bba3ab6d728bbcf2bd994bd03571eae1348f161e6a1da03ddf7121ba4", "7ee32dd501dce849cd492f6e23324c1a4567bfceff9f11d1352bcb8615f1b093", "8998e043d2961afa51ea262a", "ba85e72af18cb5ba85a4a0d6c28b4ac1e5509a3a2fdb0e3255cbc559df5e6a661fc560c756a0264dd99b72c61c51a4b7ad56ca4c8ccb7e8edfc48ff3cceac5d1e8ac5fc87096adc4d0e9a27492857b17604c3a694cfe0e70b22df106c8f3c61f840bcd634964cdb571840e125e381e7dd3a0d97972e965f16f775fa4ce555124318290bf508beb7bd77e633042deb0e863631478fc3dc9122862b3c31264471bcce54e0b74040c8bafd481cf798f332e8940f1134d3027d6f28e771d15e154fc89c6c25fe18a5d312807cc2e623bb1bbb4f0b6ec71d009407eb54bb0759f03682f65d0da8812f84d8e97483f6a8d76a8417efcd9526444abba24288647609791578887ef49780b0b89f51b072cae81c5b5014463da3633dda105b82add0f9c2f065dca46eedd2928be2570493c79a996fa78ea6aec0996497fe2dc444432ade4eaa662ee2255f0f4b92d593288a8e3ffe7a15a10e9d33b0203af23f4c9fd2cfcb6160db63b52810869ff1e65423dbe2c4415884b9f8dec3c968e14cd74f323c89053a96111bc9ce59ec483832c49c53a648e5f0f797f53642ac60170c94b473f1f2e7d8a38e46460b81219b52081263027f74cbf63a75af3a7", }, { "68d5ba501e87994ef6bc8042d7c5a99693a835a4796ad044f0e536a0790a7ee1e03832fec0cb4cb688cdf85f92a1f526492acac2949a0684803c24f947a3da27db0c259bd87251603f49bfd1eab4f733dec2f5725cfcf6dc381ad57fbdb0a699bccc34943e86f47dcfb34eba6746ed4508e3b764dfad4117c8169785c63d1e8309531747d90cc4a8bf13622759506c613324c512d10629991dc01fe3fe3d6607907e4f698a1312492674707fc4dde0f701a609d2ac336cc9f38badf1c813f9599148c21b5bd4658249d5010db2e205b3880e863441f2fe357dab2645be1f9e5067616bc335d0457ea6468c5828910cb09f92e5e184e316018e3c464c5ce59cc34608867bd8cbfa7e1286d73a17e3ebb675d097f9b3adfa41ea408d46252a096b3290e70a5be1896d6760a87e439334b863ccb11679ab5763ebe4a9110eb37c4043634b9e44d40cab34b42977475e2faa2ae0c0a38b170776fbb0870a63044aa6679545ac6951579d0581144cdf43f60923b6acaecdb325c864acd2c7b01d6e18b2b3c41c041bb9099cce557b114b84350131e3cee4089648b5691065867e7d38314154355d0e3ef9dc9375eddef922df2a06ad0f0e4357c3ac672932e5a66b16e8bf4b45cd893ea91cb397faadb9d9d7bf86e6ceca3e9176a5baa98b6114a149d3ed8ea176cc4a9380e18d2d9b67045aedeb28b729ba2ece74d759d5ebfb1ebee8ac5f5e79aaf1f98b7f2626e62a81d315a98b3e", "63b90dd89066ad7b61cc39497899a8f14399eace1810f5fe3b76d2501f5d8f83169c5ba602082164d45aad4df3553e36ef29050739fa067470d8c58f3554124bf06df1f27612564a6c04976059d69648ff9b50389556ad052e729563c6a7", "7d5c4314a542aff57a454b274a7999dfdc5f878a159c29be27dabdfcf7c06975", "aeb6159fa88bb1ffd51d036d", "7597f7f44191e815a409754db7fea688e0105c987fa065e621823ea6dea617aed613092ad566c487cfa1a93f556615d2a575fb30ac34b11e19cd908d74545906f929dc9e59f6f1e1e6eaaabe182748ef87057ef7820ffcf254c40237d3ea9ff004472db783ed54b5a294a46cf90519bf89367b04fc01ce544c5bcdd3197eb1237923ce2c0c99921ca959c53b54176d292e97f6d9696ded6054711721aebda543e3e077c90e6f216cdc275b86d45603521c5aab24f08fd06833b0743c388382f941e19e0283ac7c4ef22383e1b9b08572882769c1382bab9ad127e7f3e09b5330b82d3e0c7d6f0df46edc93265999eef8e7afa0cb1db77df7accf5bff8631a320d146a5c751a637a80f627b0c9a41b44f09212f38c154226de02f4906ef34139bbeacc3f06739c8540e37334392d38ba1cbf4bc7debe77c09b35d2200216db15ed4389f43bfd8ae9bf76fd8243c3d869546e16b8e44a6cd1edbd2c58ef890b5a84cda889131e5cd9402ca4d8271052c6b4fe3f2dff54fb77bcb575c315b9109f90b14bc8e109919808a581c1809e2a188d29fd34ce639088a6683f641925f5b4b3529baa34e080bb47fb7ad9b43d0d67c9e6ae7cacb50527fa74e56d0c8b20149f5d332d686d48ebbe634c2b5d35fc84c69a5bcc93b93dedcf9fdf19a1fb9b75f6df9692d16f6c3490377a06294499e4b8ebeaa0cfd840bfa05fde21c0b5e94d13063b3f5da7b537caefe89069cfa9de9eb8f06e4d30125de64716f821bcc8279c0c7ea2e", }, { "89c1ee38b6697d0190c87a2aa756892ee09fca095df1e31aeedbda5750f604d9b8f2116e5b8f70ec57ea16fe419f2d213ef72b9be90eb5d7e98f2e398632123e2524ac80b31c6c0a07820848223569602d94fc16a3b1ed8c411bc6c74ed80573fcb1f3afce60b9d5e2c21d04f78665241b613abe12274a5343101a91e91f04e5d1f7959f574e743a10913e0817a32c320467f0178e3b6ad14b856234a4661a755eaf14b5fd88ef0e192e1631d14263d6a954ed388f5709dadc6c0f81d229f630d80be6d593d5e3ad03f9ded53c41abe595981d24ef27ffcc930e4d653743960f4e7ce4e251c88f55c16d2afdaed5e3446d00685c276728ba757520acb9b6bb0732a0e9836878d829e5022794d70ad8440a40a132a8c9ec1d3f0ccaf8c285fff425e9788d6150b74753dedb2ae8b36ff2f310249bd911b9181d8310e00810d42ef94cbb5a9d72a1f0507c1a382f892b23994fbe7360778b7efa9c5e03ac3231a57fecff1c5fa10caf1d26e84db0137049622ebcc3a64841a0e49fa390d1d43550c1346c20d578cff39fb7404fcab0982dde55f0849d312581d0c811a19d46f25e7a5e7e50d74d43760583c5cf335dfc11b2ec964f1dbbd0ed83e18f2027817ea2dffcf2b64a352c4fb8f11eeb4f1bfc01079251254d2112d103a1f12a2270cc026cbeb8b6f3e505abd62496253f93274625786b73997e449c1f35c742a593441252fcc845e1cef1b8f287dd311a0477407ce3b31661f7b2802c79c2d20d06e45f03aca4e47a959c6c1d7a9d377e1577fbf82a115921c3d94e3d9c204aa204a9a5b04d8a2be3269700a035371f4aaf1a42d92b9bfbee74492b106975b36d1e581d6ce2484f09e04fa91586c85f35e2a10f0d3c0afcb05327c1bc9d7429bbcc4627af8f76b86fc561844c2ae3810c84901ac09a1670ed3d31a9daa5d296", "7219bd21a834d917f93a9b45647ec77102578bc2f2a132dfde6489b9095b4f7b740c9c1c4075333ab0ce7f14", "a7f849b054982cc8a4c8e5e53e181feee79e0233e58882839892134ad582da7c", "4c46854e9e101090b1436f90", "ab2e189baf60886bed88eb751bf3560a8bd3cdb6ee621d8c18b5fb3aa418f350048ecf359a7d542daf7090ec8688c3b0fe85914aa49d83be4ae3396f7bdc48051afae6a97fca7b42c0bf612a42d3c79ef6aadceb57f5cfe8d67f89d49add0ea1ffd423da058297239e72a85fa6cd1d82e243a503b1b0e12d7510a9ee98d7921dae2754d7581e52acb8ab9e7f9df3c73410789115cef6ce7c937a5441ad4edf2b7a8c0c6d152d5a5909c4ce839d59594a6163364038c4c71a1507389717f61e2bda1ea66a83ef477762e7834ebcfaa8f2ee61ced1605ba1380108236e1763bf40af5259da07dd3e3d0fb2801868c2e7c839e318678687cbe33384e2ef5750a0a0e2d2e19e869a4277e32a315ed4de79357f6a12a8a25d5b18291316d9bf40dad2d05d1b523ade76650669c700a1c2965f4e51337aa5d45ec7b4981072779401d6d30ed69034053334bccb18425ac68460becf2aeccc75aacd3d6709f07ee10366ed848c8a54904af4ea71fc2117de133f01e1cc031f2a4d0779b997b82682433ee615202d5dfffba6c916f11a00551d56ffde8c36b303263e14adaf45b6eab0bedf344e5214ce52f071d2f40154d788c6870020791a03d2fd4ec5879d9026241954ed45cfddef4937ea3d0d45647f252be31411237983a1be340fc65ebab9a5620abb0e8d475af4e89e842e895eda0cbd283bb5d0bf20236c62d956de733d60ebceb42fc0c9adbf9b69f8d66551b0aca0e260625ad41cad75d752a234af7caf7902c2c5b62f04b6a8e019a6179d44feeb2ad5859ef1c45371e66f1af1fe0de63997266c290e27f0dd62185c53f81e0a50c296a51ace7c90d9cf0dda8b2d7e72a347f64c44262e2a544d1acc7bb05734dc1783bbc1903279092fe7fe434610aa95fc2ce5fc5ee45858f5e8337d8fcb0a468464becb1cef6b7e5ea48ba383ad8a406df9c581f1cac057d8711fcb", }, { "2dcfbb59975f217c445f95634d7c0250afe7d8316a70c47dba99ff94167ab74349729ce1d2bd5d161df27a6a6e7cba1e63924fcd03134abdad4952c3c409060d7ca2ee4e5f4c647c3edee7ad5aa1cbbd341a8a372ed4f4db1e469ee250a4efcc46de1aa52a7e22685d0915b7aae075defbff1529d40a04f250a2d4a046c36c8ca18631cb055334625c4919072a8ee5258efb4e6205525455f428f63aeb62c68de9f758ee4b8c50a7d669ae00f89425868f73e894c53ce9b964dff34f42b9dc2bb03519fbc169a397d25197cae5bc50742f3808f474f2add8d1a0281359043e0a395705fbc0a89293fa2a5ddfe6ae5416e65c0a5b4eb83320585b33b26072bc99c9c1948a6a271d64517a433728974d0ff4586a42109d6268f9961a5908d6f2d198875b02ae7866fff3a9361b41842a35dc9477ec32da542b706f8478457649ddfda5dfab1d45aa10efe12c3065566541ebdc2d1db6814826f0cc9e3642e813408df3ebaa3896bb2777e757dc3dbc1d28994a454fcb8d76bc5914f29cfc05dc89f8c734315def58d4d6b0b0136ccd3c05178155e30fcb9f68df9104dc96e0658fa899c0058818da5ec88a723558ae3a6f2f8f523e5af1a73a82ab16198c7ba8341568399d8013fc499e6e7ef61cb8654b48b88aa2a931dc2cdcf245686eed9c8355d620d5e91c1e878a9c7da655e3f29d9b7c3f44ad1c70890eb5f27ca28efff76420cd4e3cebd5c788536ddd365f7ad1dbb91588d58612e43b0460de9260d5f780a245bc8e1a83166df1f3a3506d742c268ab4fc10c6e04bca40295da0ff5420a199dd2fb36045215138c4a2a539ceccc382c8d349a81e13e848708947c4a9e85d861811e75d323896f6da3b2fa807f22bcfc57477e487602cf8e973bc925b1a19732b00d15d38675313a283bbaa75e6793b5af11fe2514bda3abe96cc19b0e58ddbe55e381ec58c31670fec1184d38bbf2d7cde0fcd29e907e780d30130b98e0c9eec44bcb1d0ed18dfda2a64adb523da3102eafe2bd3051353d8148491a290308ed4ec3fa5da5784b481e861360c3b670e256539f96a4c4c4360d0d40260049035f1cfdacb275e7fa847e0df531b466141ac9a3a16e7865947572e4ab732daec23aac6eed1256d796c4d58bf699f20aa4bbae461a16abbe9c1e9", "33791b0d653fb72c2d88519b02bde85a7c51f99cfb4456dfa6f84a61e10b4a14846521", "a0a7b73ca2fc9282a28acc036bd74d7f5cb2a146577a5c29dbc3963fe7ebfd87", "eaa4d916d261676d632455be", "c9a631de470fd04dcbf8ea9f4d8ac37c3988878b6381707ac2c91d3720edbb31576ba90731f433a5e13582aca2b3c76ae75ca8881a463ecfa789910d3a776a9ad4800521c6baa120b2f1afd10f32ef8da63f5b69f5e5fd88ee84bf66b0666b15d05c4050f5358a050b9d5cf1503719f56cd48ceba78f29efe2ae8092e37f5134df526831532f86ccb9339637e2c9e9b9036f83cc058fda23e826a188456e7fd3f4ee20f4e4a3221883fe3232b49db607b90a8956133ab95051c9ec33a908ea7e81a1bfa7bd06c09f0143d07bb23a3feeac7f0d7720269c93e2df19d03605828c8713b84d183c9a50954c12fe3b047511ad15ef03a63355520cbd224d06a34de67a671368e6a8f9feeefe48fc273764a8c69c00314e5d693f159cb5270544f3c4e1760b0529e3303ab308e9a6d03835a3a42aef2df5f7643696f707a574d1dcc676aeecdd9947ebe8c13bcf15d30b2d10d2cd95445a307c1d22d39450615ad38f9302c6eb9dc05764b0503d6a7eaff9feb94834853b47bc25660207be3e7c0e27cb3127b5402cb016396e5ff07ddc3df29861dd68a17f53bf660b23352b739d6da72381b8d19a9fc95da7efb79330a2b360dce4309860af429e3fd10cab235c4acc1d80d9e20d67019375bd161ab65648400f308815afe63cfc717f7d0eea150e687caac25b6603287d44dca4a7cc2f67c3bdd54450bd3170340253b03ba054ec003070eddf9c14fb9dc595e228e4968524900cb5d85af6d1e658a42d744e0e7eb6995023823a8dc33528c6715b2e1aa607782c8e1ddddad72026d657bf122ece8685f6e92236e809139325e4a3c069facf94c10b7896995bba01eb22c7b3a87ea2114a7649d7ed3e83d223e5e785c66a75119beab0968d3eaf0cbcc2d7ede95d024041e6db39a880ce3e19efea32fb89a40a2aae22f407e5fd615e51e48dbd50a8b4ec27ce95e2ba1928bf699d0418705482ed0ed7acc858dfbd690403c74667a88dd5221bb79940c6c4a268379c10343aaefb635982c14f33ad83d47ced9682961540bd4f75804d3d48ba8aa67fb2e3a1db83fbcbe57fec9e4ffb1b575e947f8bd8263c680357960e3a39382974774b5a013f2f8514b3c63c21dbfd314fd5d927d82ba616d76629ac018879f54ff84b5808e94af4fcfe1cf8845b65208ca5510b5b593ce6c109611652cd", }, { "c335b055b752e083554b5aa2cbb6556cfcace658d5c11b6b000256fd89e9b24c1e62a2d5b582580acdb2ad9869020465aeeabe83acd9eeacdc44aa652d5cb24bbe542073d6787ea32b2b3c942d40f9db2bb75ed7914c836d902dd2be89840948d82abbaea23952cd648e6191ce5b6cf912cad0a3165410a781e3650b676e5340980eee3b484008acce6a3e9dc5aa96d775677b8bbb8b323c6e9747d6069a169ea904d9f145e29d134cdbb0118647e8fbae638669efb9a55d50ed33568749f5304ece2193b0bfa6fc9a570d209ef61b4c59a2b5485b5aa6ab47d902cf23f7ff71c5210476e0aa727a01809b9f76b6ebcf58a018b3fbbe5f42976111ba58112b1d322f9312da068cdb86277bfcde66cb3607e3ea02a1494439aa56f302671f1f994eb3ab28b937043f5f7f3b3de50673ecea5dee8ba633c45089b852f0d772892525344ede6b521dcad15807b65e7ba348d891d47fc498cf4d50223d2794c64db9fa9b9766edb430be0c38746ab317b38ba9870a6d1fdabb70fcf89790bfe449b97fe01f6c94502aa0889f0a3bb6bdc65f44d1cd64ab88d4a7806b373f5080f9cf60183cf4686694f0059e2bbc5cf21ba0c3e8046e70d815f1444c3094cc29632c429f20aa06b49b0b52c6c7aeb8e34f7bcb53e93c2cfe2d704a5d0416876742c90762730d160e1869d5e0178dc366098ebaf2cae6f1f7563b555a52dcc194a5c8f718d50d27ee76fcce8e8991f4921fae85ea9476e1eab1364403120698b7ce8fd0a49cf79213f360a17cf1950f104494fad80adcc3bb1207bf250d57dcdce6ac8082a312959672361363cc227310b66ee8c04aab7b5cb33a81c0915e9c770a1cfaae2e8f44a0c65703927977a22fe58aef2f366b8be9a50da9376b46ae7562a82391386831febf359039ac326891bc58c0f2c34bdb6858859fc3cb4e392df65cbe2ec4f02c8425bcbdd1ee2562ab7d229d406d79a9c6fe4889c996c2f68d1fb5bbe3a5e867caa4249b934afd3ec71fdb088c54b15252f9dc1b909e121dbdc7d8a16cc00836652dd1f877ce363eed11467966f7ccb8f1a8d48146e69e04ad76a51937ad4f9cda209451eeca90dbdbd65441ce20fabfc8ce400fb4de136154b87a8b65c92740e9bb91d78521b261f806a2c6279c85ef6ac5fe1ea3117ff7c9f9832fc2aa6fab660082eb22344c1a3befe0628b6551f62a5014cd6194c42b8d475a50f2c9fb58c97e43ebb29005ed7fe54f0a4aa10074f1154152a9067d364dd7863fa082976a00db55b26b5ba0ea40eff48b90", "f5ff810a41d4b34751e9942970d4c9f26b33f24689a4b1e4449b243490afc485af468ff01a42376b2bcb949b9f5e8d0b917f511a", "a74271c184a82cb074c14b131fd91eb05870cb7c73c9e511ec8140bfe2f34089", "2403fe689e239c2ed261b381", "af9be893d5fd23aab42e6a2e59a8e7cb13d4f543db02af87cb0802bc1af7c717cd0093cc8244994cf21189146922b69927ffd5745e57118bea07a6afe7c21d952c13ab636b3c2e461dc9ffb3ae701175360156338be94b1fa7115799831019455cfaf5114010fe45f8fb9c77ec50fe06f2c5a32423edccb3b2210ee1200a78e1a3130c567542377827586ca8cf0c14c19fa1449a2cce9c039bb441b04e9c0a3f9a743b31c828032174fcdb7c894349aa68f5adf97dfe9294d24e6b5fed95eb994397883f58487bf5c57b0aea5268be7cee9efeab370f89805ebe5373ab2e93658fc078955ccf68b554dd5605005751ee8531c35ca5336a5d0ce273370c0dc9307779b86e96d2d1daf2620d67d43e1fb7800ccf250ca3c02eb74047c1d2a2bc7f29fff8320301694b80d0fd975f834337d00d5f0e4215044d52aa4ca21e6a9d7e03f186d7cdd5c48e3765dc926fb0a46bb0f05c50d9f69c9c507527a60366b7dc251aae1d6bb0d9c73735dcfab959f6fd4382fe2a1f6ad07affb0601bb9040f81b55a48f6a6c5f8ac4a2acc2b0c9a6c439198f7926460695fa11e0b0b017e39de5cf0d5d5f84d972b5eee7b5d1e0343b5485cd84b92ad892e5b23f3e803f5b363f2398c11c15be9f13e59922b0d49902dc8483fb142850b4226da2fb84e9b434a34f6bb67f575a9e57fde3354bc3077a876e260311bb2481bb139aa9af55df5074749fe532d7b8a554218a90cc7e7ac69db280bae5d55a174dfc8d325b9909a8da1016d4e162fe5ba70cf8726cdf291f5e47083d9929cd5e32021cbfd982fd0975f6f9baf4322b553cb3174b11c007559879f308419ff9e4e18eee8d3640cec8aea082b90f69cf3c7676c28af0265c24c91cd58a06513198892ce6ce1ab3ee9ac0a2e937b973a9cac06a039a54f8d994c13d42c59187f677352e5feb32a417aebec4d852b2595e7e67450e06dbd183279e3b63022a3813b37257b085bf8454d6890875a2950d20210a8df4f9da746722f62687e92f0e9efc3e5d526d65ccfbcc042fcac7964dbe147932c73924bdcdf62f9eae58d29e8567ffed90048bcf0566b952e986efeae4c477944af18bd243c3eccf8d88c06d07279adad037450cb8547a8aa0a74223f4851747c803cb21a2dd027e7080aed75038cdcecbc4639d87763cdd41829a1b72cedf0d722b180d0d492a5740ea7607b95f3201df352fb1ab28149124d2df5d5ec106867897b537302c3431402348f94d28eebc701ae1b49d10adedea38f1654fbc48885e59e6e6dfd413c6b5a97d8c35dfb07a6cdefe317bf61cf91", }, { "4aba5a776ace38b6e2578f0007e770d264e39c49f588ca3547ad2888365e3a811994f8836330394587c8458eb0b6611499fd5d8e8527c3cdd4ec550b4a8f8c632384e786b420cb3be911c999c72aad60270aefad31b27a069ecf11e95e9d4c81213308d554d3103de4d9d6ab04830c2b8dfbd8bead52c44c21d5357f72810193b5096809dc7846c1521c6c569f78812c735aea21acaf6dce84a24df7234e8ad857f3e1346b27f5bd436113e2da950e4deff96e9ba8db692c7db723a105ae795da15b910c8286cac6e7dda8c172b70f61b07dfd58596684d61da8772356f180f74c1103ce97cd947eab3d401df44f7fa4cc7cfc25e280fc002873237e64a375b0b4797f4b4613c9f150090f44588ee8250ae44aec6546ec8dba0f0c1eb281cf66fa4eb141617b32b28441f6ddcfdf02d9c34cc62893b2b64dc2c26b74433adb3e888c7fea07b19c8cf39269c2716b9c35b7625d4a141397d6d5034b193d2657c6b2d6b0ba874c467adeaf3d501ad985d13be21c4ff6b326cbb671e4f4973bba49116a0399b6491394f850e4122969e4644c00b442b3da0d6a4bf25ee22d182b3f822fd83878ebcc713cb183651a67ca66677ea81b58b685a3a8e385d5fbb0147ddfecb558d881c914324c794db443b31bc15c361912bbbcba9e418f99f2a416d190cb29684df27c7f3ff6ccf339800efbdc4514ee00d1a89f12373804db4fd66c1affd467f251e73147b3248033327b0f7790fd7861a51773dd4f78b89e4e24b94df9203f4a077091bb9411eec78dfe3e1dfbb67ea1cdf17e1d6936bbb75b74055495449e9cb52f5749404610cd444fea3f0568e0d35a5ef0c395ab7bf0208044b5c4e2517911a9c351efd31f33220972287253fbccb1eb8f46960a36b68a7a6b4f5cbdc86d668bbf555fde8881e7faa9594da425ff8fb54526bf7cdc4af64899530561c06bed7fc04c5d48cd4542779e901bc48fab79d4d13850ad8247f51b9afa7d5a656ada25b6376d837cb0fa1b4016dfcfc158a39290f43f133b352ed52fab2f951509bacb41284fbdd849d8185fb7e7200f8ab2a07ef2b3b927e18e568dbeeba2c7a66e08cebdc6a6069ebe6656a586652f3905ae2bb867529af6a827b494c97b3a378408f44aaefbe86c613e11e7a44020a9ee4b62569dfc4c462300daec7b1424ff1c1849ca1332367470475c14877cbe76c820cc651c18ab3f18852b93994f93b568dc7f7b0eb5f07ffc4c9384c851fa9071c6f68ddea1ccf627f889c0471c76aff9f52b07ab1b86a7671a2b2f6b25c0ddebb66ac95737bf7e2f493f7665b5265eaa5166556cecfdd3062802724ec24f3978b903d0f0c24e1f0b8d967142bccfed0d354279223f4c28684e9ab611e9ef89a3f25993b5a8b3c0354931780501651236a78b58e7d7814f251b053605f4c0a8e7193b9cc1ee5cf7378e6f3c8fd44ec57bd91e62b09fb1d6bab60cbfabcc6792e6a32ea7918a9ec9180d05a7e1546d5d2d8bbfde2a71b4e427c0a4d28d0b6473ae", "921a401db90935c60edda8624a0590d5c46eff3522e35de2872f6f9394e24126fd8143b68a797c995624fba0298b75eef974", "6a4d35ae03bf277f587da4541dcddf92bbd906dff45d5ff23c0f60ae53b062be", "231b5780fedfb06d724450b3", "ba40968282d98849b19d867f8b564ea5a81d657516099362926bca4cb6e9ae02719d10c8061f53008c727a0eeea5e1e36c9e55c117e9434e213316c96840231a1e356b254a9981d4a6ca3c66cfc61018bcaade1a4486506559e6aa3a86bac980d391d835fd5ded98d10f1394d84bf1bbf2cd3397890d704154802f7864ecc753db782fd3d19213ae65ace4770e1bacf32d61c6730aa5adcab4d7e2e437888c11c29abba4890a17a00f67a53b660becd94092df0598df5ac57326f6860593a519e28bd4a39f6481e1a4748881fd5f0456a3cd9f28d1d1e78dc64030cbd8fdb2c5abdab3f13d6ccccd187e71e989f8c486929efcdbf2a763effa95af62db5cef95e9081b818275c69267022fda4b7fdb8c650b491a785b03d4d0186625962b6326ec3f4e176373da4dc1f83a14815adf82c6bffa7c6967d77528d0249754bb4d17656bc4a89449b16152a4a1aea7eb0054a8892f271138971507d2f3b237ba5b620f444544e4a8c2b1ab4f9168762c27478c9f776c47ee2e9ff05bfa35ed127f0cabe7cc053640bb8aa01f8359b74bf89ef43ca94c48fcd201eae39d1835957eeccd6b3a852f4e1bbfef9a469f42c764481ff8408fe5871afeeae7676b58f4202199aad50a596626dff97c8e60d750cc59da9f595ce12ce9afdce14481cb1e39994de8fe4cce07845110d6703dc59d34734e93e9e57e1c52d61f44143a2d290220a4bad5098d098ee65ea4b6757d8a9bf5485aa3d697a7826d4a285186f5da10eff707566c23c6a15033365bcb498c44487c72d96402d1834753fdbf86770239761f03e0dc8963766441da99c0813e4f1df5a1d018c8799861a396562eb24ce305ca15f4022d83ea3c56b68d9a7ceac4742ec0ce50f4d36273df26005ec2b051fa071b319be2d8a5ed26eb75bc1ea83761b8454db234d15d84d6706cd178981c1f156e6d28f774aee3e9a4fade022e71b52b50aa532b8bc7fe464f22d6eb169c69671875d614e987658820c2f584a4fea3008afdcbb646dba3d69020fbf503f121be3480344db23efdda0d255aa058c3ff66abd3a5fe35db977521608bba7eddae72ae801f4fbb12a1de4133039e046ceb8db87e465e5ede1d79a08c857d59076d7ff858942c31e15cbbdae6fc15c3f9545a0825d6ff8583c0aba8a7d143d27b93f6caefb98c0d83bd8715abcab2a49087f55a9daf9090eacdf45be08ad80b5df5070e1719f68c4cc8f8711083f0f7823a09ec092f22df95fe9e95114fdf82a3f6eed0bfc9c0aa65222609442776154a474dbc9e662cd5dce66846572e52417ee5d7eb59287d07ef60a9537fe1f85c7fa74fe84dea0da235ac7574335e6649b54a6bd33397df4bf4a7976c4ab868aa702766d2bc8d2c82c2d1c2653fc8428b8d1e61852ac185a3a0b416dbcf8eb54c44967ff43c44f2b32c6d4a9dbf2c2f3a587b430aef50f0375cdb4c1b319ac9aca486d9bb321141b065f52f7b6decaf1985531ca7bbc3772a561eb1efb8a6297075920bc432131a5b211bf25e35fa31e12833bc77a9de14c7", }, { "6c0056937faf1023032df1e2bfacbbc58bb022eba25ffa020d4eb26f0caf0678af5d0b2f0c1b520f4843f107f0adcc7b5dee66ff4d61025bafb4cabb64d133132e3e423a599549a1d83aa8c8e774444462aa44b00b460bbafad5755ea6a872d4e6b40e3f4957e0229288ea79fc2ebe5fd9020fe4481a9f42ef14a196bd136aa3c779e311d0c333624c1ddc484c9aa7259cb609e4d0a826c0bdc7567adac01da23900b30ac4e66c100348584fe200747eb67e6287268947e3509d5d2b5d7bcd977b80a13f660d4f6956a8b938a82db75eab19e5d2a22cb5f3c9131e278eebbe096b5f49d16c983ac240f3fbe821b247cccb2c9e6e59546122677f49f56a07fed56647a6d3e0e09520d49009f54250c10e7c607cd5b4ddf81b5c4110c6490e9baf56418236211856f5a85feaebafacf92c0c7501c052f9dbae3beb7484f90f334f50b68571cedc67763b5161ebfd5a1709cf18c92112a4cf4d8f43d1895204d8a2ba5e14883a7bff75cc6060cabb77d38a909daca2417befd1bfc05a11c432b47f90c807ca4306400f67a0d92218adaca84a584a8bd4395c93f9b6a4bde9583c79204444634a8473b1244cd33cf980e443d82ecfac672b3f60e2e41ecb3c5a445d9e88c0e90c339a31806e6d79ee52bdc6808c73e8b7b24899966664d3c1a9305f31f0483e24e36fa451dc1d3f2eda05af6678971e2bdfb7c1461c9407c5c466f6b5af34d992a37de3809a22ae75275ddba0f4f9cbd4b18c1acd212192e587889a36bd73c860f0abe08bcd8f00f5ecdb95e1d560b586eccf530df0e5f3776d8dae2a01768bf1226b7ceffa7ce4e75879c82dd97db3c64c06d33cebc6b35854618355d80e46fa79c3e9743fce5b974723c421a077e7ec7dba286881dbc1d53d442a1552700fcb33f83f73c69a0a0ebdcf2f5d461649c4d0712c514ded268a31509f83c1ae4ff4a68e676d29727be641aa4487c08d4b90ff78e24c6508d69759751a1a23690ec9f8763621e8b107295b4bb01bd9fcacd8748e24d996fa70ef6f8b0992f4185bec8e920d7643159f9f604fba394b6611bff435998b2f097a9e948430899c8c752a1e83a061983f00f88ebb32da214399167932a1a83c1b47d09f77593b03cf6521520583ea4483e2d33e14ad60584676d1791779b532c085d238df0d3bae735d0078e0eabd63cc90a2e13d023983780afc8f83b1c14437937c16a1b7c41414c48cf4ae49587ad9fa5b16fc949a749e96032248c4667f58e295f999590dae1d99a2cbe3fa45bcf4a1d3f0356d64d40367f64b2c5cca843e5f7dd7b88a85d52328a00622e6c317879607bc036c9006d38652ffe21c83207c00f8348a7d0aaea5aab4c89077df170de6d41052641726eb6925cd85a9ee01a9e636346340e209ea96d17b0eb0921b96662ce9cb430fb6ac348331dd7133875769bbbba99dc49333950e4145a15ddb0789c4d2ccd38878080ca9e57ddc6cd5452790eec45482f8e990392e319609391fce0beba19463a9a00d8f1de9fbf22f23821de7d69fdfbf3019ed61aff79acfc5a6ba663a1e10da2b9ff7149aea43bd6c61a543008402309df0924de72c1cacd2d6120cf422e61fc1de345cc8771934d8be77d9437a09e06a9b2d51c849fd9a200fa714328d34f36b684f33df6968b827df916a599a4bc3367814fec21198e2213ff653cd2a463892966c72ffd42a26b3bb91", "0d55dcd08b54e58916f622f81761ef6a2e19b167ac47d3", "e42e1d6d44138f3d2bf12c951f454686f18d590fd30057405b5a3dc2b317fa97", "1e46a7486c5a03fd6758d938", "fd3c1fac10cc82e49235fd57f5aea0ee7a7bd6d539b138d4b3fb623aee591615c1a61228ef9673113a3a90a3687a12d4c6367d5f7bc67d422fdc4106455084d79c2c42c5e86368dd164bcbce7925bfffe7d96c13a2f49aac8e9d1ada3554e3fdc21aab00455a0f33b0c1fdea91b3588e7ad301bfccf9940027332fbdf966463491f7a33c093e0a13831ea9d2183294f89f414cf7b5876af04fa68d594430194429df74fa5915394427259e832bc545c13400aef6cf16620d48280798a6e49773c9316d79fa1dc758e54cde2e2cdb856092d83f4e9b698385cb976fd6cc2538abe055273a5b34a784182ea5e7d3ac9019a05de5e5afe4308a7ed2d363cd50ed6a52df1c616e4a82f607ced768445d13ae4884f2ae1f9fd8313924e8a1a8a23905c92eb231f638dfa6f4cb27bbb9844e05afbbe2ca4d1a3b3a5b371bf33c9ab6f82a7387d61cf8bf662097624145a983839b0cb9f4bd07556800b4054fb3d0bac94f44bcc9b4ac49c39f5571fac4e02ff09f08b3ed5add4bf8bba934e9feb773c0590b45c45fa036382f3fe9782ad19107d4630321e414b7b442b64f18fdd5219039e5740f34b3ce8925d1afe8a39e35ce8db086060bab63b9720700499f82db19a62897c6d845389461260303f9cf2bc7235a898b4620c2191ef05604a5c8c783d58009533a86b27c12b0772635d34ac53993ccf174c9087073e5e69b26c0c3d9f768507ac4d4e2af847b65e3a6e1b7a6dafb0aefc190871cdae6c60f0b1d6137c351d4cb211870791cf4cb8af2ea446f6401eb9ec8a5bcebccce898d1dfb13454df6b35b81ed6d7637e6e261e004080c60944f3a08e8e5fc7e2e4939e7c2607c8cf07d1d10883ba3ad43e2611826f245df571857ae0a7a867df9659f2082c19f94ce400132e48c7f8de2b102c7f83ba5cd1e785597a0ba0d73bb81bba0c00300d4bcd6ec25fb73105a46122873bfa729c0979d8d314ab7ea52391aabab513dbfd1cf01c2990c0a3612f4511c2bcf0f5a07e659a881a7f99c3f1fc4a46e66904427fe26a4a80a904c047d090c861a075c0ae4e29bfbc18b9620aaa42237f4c6fa76ee7491ee638ab5f1cf0b440759828e1ec519679efc776eb1468999a00f667e87199ad6891e98b95fb682e02517b024a6bb803ed23c944010cb7bad0733eccc12d6ab6030c6e88d510ce92e2f98fdcfaa1e37e41fbfb4e99589c0e8efbefd40473db42b3a73b57b22a2f8c9bdaab16831f1b117dd83a77dd01ee8d0c2e92203adb670f4fd65e618823ad196220d70e014c1aafd8863797c61c16382c2600062683ed3a180c70891717c52da15191b02f25d1715ebf33a5e6037092421989c942082f4b836423cc3e976c9bcda185de36f06265dfc250a27d2de0bc48c73b3bff704f3b386f962522f572108458bdb283c6ab3fd33b3ac13a406268fd5d97e17db9c0f780b4b2a8f761d15a4d8b3a0cd73357ecf4d26a6492ee069f19325823ef50bcb2f73326719a57b67eeef506fe8915a1b1ba1a637592268257b91e9c7c5d33cdd947967efc1952005d82ccef9a3ad7ef8ffbb6b658983d64c51242ba53f8f8963245b87a25aa9324c527e53f8c11d55f30aab598401589acd13f090541b3b057b162190f27910718b02a6b8ddbb8ca6cf40bf0d2848f4b76341bd5e78f476862bcdbe2d1bac84c0566fb45b21388221ecd8483d99fe603646b1a9f38a49230cf4dbe5d7883d73eece01bf", }, { "04892b94c65685f2eba438322b29bf8439938590d3e0eb10a29e279d356cb439f6dfcdbc3552af21f7e753221012a649a52bda780bc589ae63b04b981dffd113df9fcf14f17e35e865880a769bb1bf40dc99b9e85e4296c1f2e1590fe02b22bfcaf2d4bb7009a4d692ae4c2d5f0b6d3ca526240368bac55b9b1e6a7b498d3b137f0fcfef1873c5aa2111d7811d45bdc26be1c5d49b8a2f36a999b1f226ec06a5fbd59514485abe696c96ea89dba74b4688101a239b495944e30b3609f73caff3114407599ec5c30a5bad933655de7dddef97018ae15acec46504cd5d417c5052c057ac5f1c6f69781cfdae71db2b4fcac35054a4aa22681027356d68b2bdba721466d130d53ba8f23857631382b2de450232e9ad5551bd7c872ae439e79eabfb057d2bdab8d4ccf02b3003ade2e1f3e514dc92692e4fe5b579c9ee6067995b6c168647ce5a13be8543c23326a3260bb7029d2030ec05e565ced3c5366d20a283a6e95201fd108640d2b96676df712de20e4e12fa53f85f22cb24583844fabcebe40eece11e7221f12c88670bf994ed08e2000236f86258c386b0fccbaab8b68ec6a26fe41491d540193c4c12d1391ab3391de9317f41f505f1f1d09ca9862a6f289a533d2b297d4465c956360371ea3c8ed36e0d1563120654e3a2fd69cd6c9267bfcf92e84cd64e162c84199d6e552b42c33857264b5d7a2e007797cde32934a3f8c68b459cd95bc85e7466ccc9910e8dca65b315c32e43c3a5da908904c42cfc8ab74126919ceeef1054bbdae6ca67b02f1ac5f24808b5eee24577e609a3e3935a24b9ebc1a8dad1fc96abe26012928f2d5782755f3763427dda28867d0b1ad830d3c3f17b9ec278346e5a9480ed23ad44a523a4dd86e65a610ee0de1afab64ace7a3b4918fdc14c6b1ce0ec0903994da9bcf18643d7e0a4e6c08200bb394a89b385d2cb829417eeb0f7dab9fa7306a330f82973cf0917b5ca99b585d2ff0e8584e050077467f5245ecfdd5942e4fc72dc26e5ab2ffc61f996167e68168cee9a6d3ea1e1a696060465e35da8c75a1aa380004faffcb0a992c627fbdcb4e97721271802cdaf08d214ec2fbcb389d75709d7a6b9d35662661c8961f93d4a705e7188613f3769114c55400809cadf60d3b6068c8a5ceef078785171b59be1140c6a754ba1de5ced349df63d67d59d3a8ca3c716ffb506772d57e9e3f2caf7fe346c4ad64aa6c37e43b9bbaa8f58e51bfbac31fa6137728f8e5b728025697e5ad5c8301f6ff39eb2ad595d3cb24257adee88a84fbf1ade4d7550cd9ab94bf48e1424ae83184c35c5a5920157d45805c2e0ad129fc7f0ec3c41b9d6fa04cb8918ef379b0783d1cc2863cd80382585fa05320ca4f9fd90353e490b384ed6c166c6f802cd7bd39aa43667246e8da96992db7537d472c709b01114e95febaac5b1a3c77e1e9a18c2d180e63f0d8fa89f6a1ed63e909e4741af5c2a0e47d4d3f8779b7696358f58060f3f461cceeebb390c92779d30bfdedf1b08ed62dcc05a545bd0ea915f42976e81dd8a50cc4689d8d8007508bf53e7da5bd43c3894968cf0677681c6b818353af6bf8ac205139add1310e5d363ccadbfa0eaf735808325e7f9a6aeb1bee3ebb4a27576a88811859c216b6f84371c43d8063a0d87bd326eb6d81c6896ff534ba2c9c14a51d2cfedf33a5c787279bb4a7ff65706b389756a6191d2f791254233ee047d40d64c2dca878a42f903fd4382f39a89a723fe11848fe37b2008be53f7c2d037981d6462a4eea49df1a2e074957afd3c9dfb4d218a309cab395afe301ccf", "67b5eccb1790babc2dab5e0d1ff3871c3024177d45a2ae", "259603e1c3af3fd0ce3257eb627b02e0c0a48ea2f175de3d8c36570a445e5369", "e14de73c4b17581a7e0d0649", "33522e67ef932da5fa8abe628b51f3abd5049951dbc982ea95b7769652d4830c588fa45e3fcff094c8602b9008d7b2f9bf6c1c4a8cfb515401c7c44a7ec42ccb967722a710199e121a41160b1ec581507e9bd2e2e506b10c4b5a8d6977435aa08e27504957cd49e756e1574c4ccbbdde937de35128b7ee3455d2e665c596c2e97c253c94e405f85eb5de84874c099b4a97eb8f492d28f2e4bc64b228dd5984e76ca08376d7f1355ba8e0fa60fca96635075417d8b436278e0fb91e3bfc7d61ca8c7407086933c061b2d318f46f352099e1d317d6c44098539d1d2c1b7894db668e7a82ff991864fae236570cc420a4229883f1e2242d05aa07e175bc6abe11cc643cf1786a4456a2de8c066fb1a70fe387f149ffbe8cca7b110e256fd0c09b1d3bd7381cfa82fa700c8db1e79809ccf75ea52d0b349264557046e8703a191ddaace00ccfc513db5e78810eaac0a99d7bb1a5725e722d4e595216a0e12f3a7aab2e623ea9e1dad06169914bcd51b643016fea7dc3f2743b1e65877f1fd5581bee5ef206d86494a587ec8462a170746fcedb2c9f99090674ee687382711b4610ddac599732453dc063518aa36f5b4129098fb9fddc02eb8f8cfc2fdf0d904ef4d6d06014f977b29d0e9aab4044ce9c662a18b1a8db1ceea97854e90704430fe9b1046b221b27ac79054fcc68c3abd6fab7da66e255ff0cbd0506c852e961e619615c944cd9a05c25abb63742f5da7bd9939feb0f2f2208c8ce82f551a9d4d70e935dad018e3e4e6998e39670221601c3e34716ba75eb4e2fdf53c4d471c444330514986de45cf44d77f793c17e36a271fc65e6bf08943aef4c66547dc310c7a430e3fe7a54898de48f69f282f52bbdc4daabdb325cec7ab66fce1aea4e2fd932dc1a316c821f5220ea437447feae2fa478adade7cd515a27d8c132d0299b3ca1bc8516c9d9e7c65c38c238c69f03e104eb42a29cacc8d79b808ea6fb233a5056201e3697f81a2d49ccd8b8efd1ab0fd407c16a210767d1d3ca798ee53a4bbf1ce5090d321b1a64fc2c5f013c23829f5b0d2737936ca71595a1d02711c8a7b0e74654e5d76376ae26977dd49c68e3c0a7b36e047d44be42d732c31f681bd7b1b4b339f004ecd847960377acd005debfab13d0fb88355025877630aff753a7cfddf6851e8bcc8ec37b8f9149830f47e6b601098b2ba19a4c0808e31e8927b2525cb82bfddc9b4bcba2b46bbe768ee278fb89010243d16f9679f5ba4f13cfe76b5beb16c7b28daf99b0873098115c2233ee3402ac0f6c899a2cfcc83b2ccc06676999ad48017c4ace507080a26501993327ebdcbd1e2eaaaa99f4998b716cd9e36eb26b4573a03fd1d18047198fdf675ef4f979864ac85d230a011c69d8b6c45e9efbdc2a03f195c9731b4cefa60208ba845c0978e73d082bf6d6a513b93dc805a4f5973f4158f60a200167ca88704a15ac5ab1f38ed455a426f7c6a96b6bfea2ebc1ae1247cfe5ff29ee81bdbcb53b03b89568bae9a6f311d2b20e31c2d91bd18fd93a37be266d0de8015d52e325f78356dea0b77cc76f28e0f06e4ec705d1328340013a77b0b6196f44b7712fff4ae0ac7f6afab9456a95012b7c6d387285487476d189977e28f6c9d1a3f736320d61302c2d627d5a7ac8cde4988056b55eeba27efe7e640f94c115762ad5849423ae138c76f15b47bd2a2bde2c492489b7980aaf1c4e32a155f858d7be4fcd0f8a18e7b5d97c5a08d7885d6d56222ef49542c7f80498a14a8eed1c092543aac3439966d5b5d0cb9e602f4fd795c09d652b64f9ab67e38f48c88d18e30a9774f37e9c77b7a94cc7310d", }, { "4ab8068988d4bbe0bf1e5bc2fe1c668cbe58019c958dd2ec97164aea7f3f41c9f747527f1c0e5fdb2cbb9d2ad704b6955cb731f14403dddb1a28c5996707635e4eb5dd6ac33d46eff8e319cfe7cf6443869534ca9812a5b23a6b4ca172afffc064dc2b28197117115431e03c00447f87d9b45172c6f724006270a1d41fa094847cbfac9630c3a785f488c1f5cc407ca6f4cd18bac43cba26ad5bfaccfb8f50784efc0e7fc0b504b43dc5a90a0525b0faf3c8b4b7046fdeb1cad87ec667ce3eb6cb4c358b01393f3ffee949030ef9fd01c1b2b9c5219777eb6ff5b1d7c3ef8d8e3bc2193dfb597cf942c5fc50befa527fac0b44cda2bbb811b06ae87459750295371cd232754e2bb7132807d1225950ce64949b0650531800bd0074177677acad937ee008cc0bbfdf33c6b0552000238494be8be412a3e5cfa359e619d092c76310a76bdcb22abbe6f16b3b116b5f95001d20e42fc3c9ff6723e580f378475788eec265a1ed2087de8cc2eff72184f73fa5dc6e68a56dcfc85350bccb97135386d5b827c2d9aea065708f5c921454d1b9303f21d5adf19e00415acbd86d1e5e42d78505b033a515a435713649c50702f54623cbf31469f355c3be2e30dd8c72b4127764451d79e952ea1f9bb0269da56dc07060d5d9542a9c1258ccefe53fa3f7b6073cd38026256b45c01b6c5dc0d91e3139f30a8d1da7a076738f5bb23352693a8e3cbbb46226fa22416680013f9e3278913d06aee4a62457357f0a68d173a360af5e1411840e34c574b4c6b352f92ce33632911ad8b6710d357b7607ee19679e777baffb8ae3c0fe9786b2e97fdeccb5105ecfe81441f549bc6b50ab84b749fb33f8f6bddcb6bb733d6d5dbc4b29725b8741439b8239e53fa435ea29ed3324202b1bdd07d1987b0e06d8cb51013dad897ef02401290940ce3f2af72c5d1b4c8836299008c10b16c7e3e119e41ec66d9db6929ee09bdeaeda08a50665c052edf77b7dff3d8815046bf71d5015e3bdb29a4f507aeb2e28c536cdcc9b8d1e89849a0683d78f99dbfa90f94aa5dc08587657a8f042d718080de5d4a973f232f78c387b63c7143fc2a4380c491414a18b6c4a7bae2194b62e798ad7ec7d09e409425f6d0973accb17e4d860f8ec0283584cff076d93bd9b0c4873f9c57cddcebe3c3bc8afe793c6cb6b26c4582847b07446b7e1d9757de6bdf0df826cbc502bf88cf3a773866d3ff293034abc4afa3091b2126a278f50e47f2f66ebebb616e342098ab690f7f5828bf8cc4742c677d378893e9f188e8397bee983a9a0998de2a31798330f8db59a8581e1c847589bc0e2d95ffa68e39226cc15cf6cae5c4f5174e7848375391dfabafec202565ec2383721339f04c5c5d1da953d88f18cda65745ee8e99805e35203a6545a0416923b38c5db3c8aa00d64354bed27d7c78c4b257534bd7a18107ebe64d8c27b6afdb330d8efba79fd1fae480cd51fd3626bf8d79fb651b7c6cf752aa737a5123558420d48fc86451b358d270aacfa6c17f343b7a9956e6f64e4990c1b3f1e5097605edf5ce4247819b19f245e9a90758dd42c36699ba5cd7f3ed99a7df7eb155749f4b42d192c47cacb6b2865fb9ef2cfca283865cd06e40cdf7f89d76a9e2eb393e2e0ac0e2776da929f3f8e3d325d075a966d289c51347bd0bd523a5c81edef63ce9b72f5114c88b08b16edbd73f518096240a5b37421843173be8df4ac7c587a17ca6f2916f7d9a10dc75f81bc778a1eb730d12b51555cc414eab9c066113a7edba9a7f1a18092ae47f12f0368ba211feaf34a3b48a7ff5c91b81cf7c95675a4001c95a19d284fe4197fe8823909a123fcec5e45935da12416be1bdf14918414ad19b54a41052f5b8417ddbd207ee01d6a3e62fd9b0321b1c13d91d6ce15ea7b2ea0c670a5f5cb290ca8e62c26c6499104ab8e9fafb05170ede246bbf7313625d1fc9576f1609ffd08852a2f4b73c04f1f4eeecefe3f3eeb2185a618b6dd3e87d9d3fdcb349cc83c21f26b6c662bbb857aa95378e991640a160a23cce76153c134508c68ec54a5", "0d471079ad3c3432b6de852ec71692d12d9df4f984554d458a9dd1f28a2697976da8111ae4454c9a23d1c8eae75bbc14f8b00e7c065bc290f8938282b91a1a26c22b40a6708c40945d087e45633a595beb67d8f1c29a81", "f3dac58738ce057d3140d68d2b3e651c00ff9dbb2ca0f913be50219dd36f23c6", "bb2d033de71d570ddf824e85", "238c4e6be84bfb151557327095c88f6dc2889bce2d6f0329e0c42a5cd7554ab16c8b5a4db26eab30f519c24766b1085e11d40823053ca77adfe2af387b4dcde12bc38502229510606ff086265f45b1087375dc4a022eb0b641101c74ad566ab6f230133b7aa61861aa8202b67beddc30dda506691a42032357010d45adc7ee633b536a2fefb3b2143837bb46db04f66a6e2bc628d6041b3d306ff78e96205ab66847036efa1fb6e6a387cf8d5a105738be7163df9da0db48e3d8fd6a786f0f887968e180ad6888e110fb3d7919c42a7f8c92491d795c813f30ea645fafcddf877f5035f133f864fd0ba1415b3d698f2349ebe03d9e76610355e7fc23221c5c72b1b2628a40b14badf93288fc4abeaff5306d274f21938650ab236a39496d3f8a6e9086eac058e365d4335b51eafac813f9175bb7bebb75605909ec3fde6515694e119f7b6e96aa1d6d6454c3a7dddeacc83bf0c1f5f6c2a9dd2f460f3e5b074a33b8d7904e6988ae43a22a87f0933f812e45c4c518bf83e606bad4c3c55422ab2207e9d3cfcbc5819049f55e35b9663273d9d3a6f8a897fa38b0dca77eb6c344290cc007b68d913187f2cd480a40262623a4e95d90d5701ac2b9d858d70a27f0672f919c2ded1fb89134ac9a8ba6ac62931c832372abb70e811dc50cce264ece65e87338231f18ac007c5f68f3b1c5904ffbb2e1dc361d53914917770d66afe28c547d8cd5896d892cbdadc34cd6af348c93bdb8b072f38b085361e62ded7a38b4368824c759ec7d2cf4caddb9191e5deedc8b8388bc4ba2c0672321bcda3a7343c9ea71ef03750912f35624d81da5fa8a6ee676c4efd99d0c7258b844ded7b35d8c8233a316b508d79c7c0b3edabad5db9543615179b1c111bfd78b79327ac5b4155336d670baa592d441c810cb1b7c07f3d35473a45b57e780b7d997782aeecfc0363976fb608d6967844ed00b63ba75996054d090aeb605c195b1ff86f9d9ab5892d27632cbb59c06b3ccd69d33ed5dea9398f00b7c6404fcfe2fcb5924e4cb75cbcae0a1b084ea8b15eaa5847431e9ab70e4afe15b4c82239f6165e243e3b76d6c91d23b16edecad8bcb16898641f8e323671452034a8ec9b42b29cec0db210bad0444f1c5bf3505cc41d514d5a270d556f0a34333bd06cd6509ba253a6ba7a6db8f1a60c99f0c3d566a038a72f1271a178cc3ff890b0df1e7438c0c1a12d9873643e2d7bfeb92379545de50834abe2a345faf7ca49beeab87ee516dd8598b71196b8cdb15e7200cb5bd814338babd74c565faaf33d9a8ed4209b417345a1ae611880ea22ab2e894d5d14a28fe3835d3b2718125f0e6daabd85327455646290ceab89e579ed5e1d72a0172e4a6d8da70290b5022c941f3866f96cc4218de5d2622d13af6dab15760a1ec5d10918267f9585284058aba611ba07b1d5711cef505869831699bedc2b190fe1d578814065c91d87a8c8dc9b0d4dae0c80cd241f0bda3a6d5e714c894b7a48b1e5eed4555f103eb03c9db30efcb855df422d7451a6d70f28174c7ebff536dd2cd2891f6c3f264d632ca924c4e0d84b37cf8e06e6f2e29efac6cf008cc27f062441278dbc9f09cf44987e0e9ca088a48437b0b89efb9cf00d3d0c5fb449fd4b64e21dc48cf300c2d80a502cb583219f1881e78e647783d91dd2f3b389a1594eefd8ea07d4786f983d13e33cf7a34e4c9a0ec4b791f1666a4eef4e63bde7a241f49b5cf615888bd8130743bc8a6d502bfc73ab64d1184ead9a611832b7e24483a1a0fc475d9ff6166b86a18a3dc96910ff182cf326456c4461ce8acb3467f801890eaf1ce0b24791da9c650876e718c0bf43c475174f9712dd4a228695e8f8b2b23fc4a06358b4a6a8e1afa87a0280c3e098f218f7a6d6bd716f8c105a7eb799ba0220837fa5a96c8a22a826a6f7ea9d7216a24acbc7b0133210cc17c8190507badb421bc54997ff9340cdc1ee415126ac46a4fec9fee12d40f06300f7e397b228250f36d6f0d2ddad5fe1898ea690e4c7cc3a116a70bfaf6d2dc996753fffae40ba5280b8356b7ab4ffbc914ec74eaa070581fdd1d9e5aa2", }, { "4d81b652fee892d575bd13dad913d976cf0517c819d5183a72eba995b1f27efe743451721ce34791a15a6b7a6e44f13d4a080563dd1d9d4f0946e5ba3863b9ac970a1fb4ed66458ec1b1092ff5fa6c3f0271a2df8e3f2e97851352be760b6a0e1589c202f00791b1b89ae0ae944ced96bd90754bcfa3e355b735132d407d3b5507fd57f705e8a8bd82886b16d459ac91e921dcb8c5bf0d7cf420a9349ee589a5e2e19ce7c944a54ccc1062a0690f3152300d0bf5cd1871c1391bf6d7007f7ce26018ca2a5c6f76287fd8c8e9e7f93b1806460dd35f7f95989a8b6f9a0aeb7c6b0346955fb50b8735e34f1ecb4859e34ea0f022ff6fb797094206a34cf120b7f4664c531c57da513b296f0671c8e9bf68d9e1674998fe52da04f627f516dee97c2b3c988216e9bd3f58c3b021ac70898651f1cfeaef21c4f417ebe92dcad3aaf50f4277262c356584f816a5a5862f2bd720fac10f1b86033371ed603bc00a30cf4da8f579dd5bfdd571a37af7d2a5cef29f9001bb1605ee87f24ec3b259f381a69b771f78d21c4e43bfc83a916e08830d9885c8ae8ab6367c05f92e5eecaf0488262300f83f4e3bff177590857e149216995bc52311fb9f16f4cd74e07c7868a39b699bdbb7d7dace4c6a53ca7ee6e11741a63a52a1d96995a6dd752356dec6f14761ccfe38a6cd8511204f8f0630a747d6e19a77bb030c61e0828436604a28a7acf4a5e49b7269ac93b93b99e9e2e1c0c47b377f7e44e05ec6659526afbdcd5bb172404ce5a9f8786234114c16f20cda6d4359eb873a4a4d9fdf734e9c40aa4db3ea9a98939210f6c62142dd144eb78191116d194bb766ea96da38321ae27fcdcc196560ac75567297984fabe6072c771899906350f74de6d18518eb6898b934b11e945d94ead02b821fd6682602e03e9c70a1ec67eed33874eb24dc83dd1035fba5928f8f62ba1282907aa8935ae72fcb881b3277ee6bebda8fc75d6cd792677c25f70c87b11e094298b2d5f39904be211ff0980e5b83e8ea4a455622d8be9efdb5aa8466c88ea861407d54d98112faa10293af5e16974861dc9f83b45d21b112cc367894c421f5049e49dd205bd7c15e6a70bc810704e2e3a3659800864912527f8be743acdc474a26246a81fc2bdf669b9be7a2a0c986432e1e44b5675607e7e1ee2a8dcb72d8f1964272926e52f909ede0ac8daa32d1d850158db76b959e4d83c9da4e3bb23fd1f5b26463045d6cf13d187fe74a50c09a654d52d0e2f01d66b9f8b4f4aaf4c69fa62a02aa876f9bc4871aacd26a6c6ccfb9bea09cafbd0268b5b65d60aa23ff504d02fad4719698f8b044ca1bb037ea6af58a06a448080dfdbe6a5d698d5db9da5fb4aed04a46c8fa8b93153bca00a5bf8aab64d2b371d072db2ddb688a9442e948f0b99236828dc115a2fddfa2a29e2d4e02ff0173cf734efd4eb687e3f8712be82abe1fac4be0c1eddda090803fbdce41bccfb58c43038991ba1074b281a09bac5eba58a99a1a9678ba26f8f9e3c63ba095f02cd8f3b56aadc5de60477efbf3dcb54b854f651cc72042bf19268554c61b44f2f338a75de56c3c45b3ba40a697f5f21c4557380c777bcc91a151e5676c2a59606200bd476cf98d20b4cdc64bc3b8670810a014871be018bc32fe239e287cfe8a7cbcd1e8b55e08692ccfb4ef871cf797bc0b1fd7ec37931e35b6bc5d32bbe7ae77b9962c179f96436e4a32f566298d2235acf921e38c3f1942fb7674b65e222d17b95a2e58f072c63aa4bba1ce48c303f4bd24d84963f18c5e670015c52342dcdc9c0b348c7dfac721b568effe2bf2f2e816ca3279bbbed823beede8e12fc5bdccd0f1584deb1f6ea1875e9fb350919b675ccde0178bb83a4aa5232bd5e8e9a1b8daf905c6197367a0d106532297ef89f3bc690b48224592c768bd9c50a63d0881370d475081aef052b444744b33fd3fef674a37898fc950f887ed482d2a51ae615ef5b1dfa3a23257e6a6a319a4e2080b2c4094bb09e4b390d1fcbefc4d6c5dab620f8b05b1bd5d976300b007e2b8120ef8a6c9028b7d925c795058c6bdb6711fc5fc2476b9810d1d81bd24637537716edd3b7068b802c531531df710d3682f9865530e1ed51b3b56d860ba4e972bbc74662cdd1e2ea24f81bf469193afc02b14143a32e9556e3f2ecef97c65", "2538d98b64b6aa9258f9141840a5abef66d6037a10356366a3a294719c10d6c148b04cac66f63ebff052d730f8821f5e5822d869573bcffbdd636c7973433abbf38767597da5186df8ef9df071bc4ecade2633366102313e659db8d8e0f293d379fa2df79f456497", "a5049b0aa153e282457555bf6f82b60fc81aa6fd1c2ea3db031478ffb74b5b5d", "350287a6bed5709dfba3d35c", "849670914f5fe318eb01e8849e536374ec11e813acdbbe6a5e82a506f6aef4f916a3a7fb2e41db3adf990175e21f2386d1805af9bbc32a6ac156b13b1a9505958f68599019c4b7297314229c467114754277b10e9f49a4d12837ef24184629c8902ebe2a23f740dc826b01f8963d47100bf617b314835e436104eb207fa9a1079b8feba06d9369b9aa8222d38d87096b73678bc5db9a1add59394530e678b6ec93a80efc6e8320f2909e3e891306d69b016ade0d30cde64c2c903b401f9d01a29b5cb8619dc68ad6c21900b365a6b657f7d9ca4c145fe598a94eeea741e20a9329996b17aba5d7115c93623f2f5d6927068d0f190b49eb885429d771bbbb3980e9293e4d664a71c3cb629d869dc97e58fc3d328331b11df19a38d61e1705ec4c3d779168abe049e9d675337ff658e00d2d610c8f227d1341d1c41f1c01d8b5d83c4b1b30ae4318da9822f46402ee8cd5cfe9f3f22d90a5ec2d0aaa0baa85e10f5295cc6005c5a0887287b0c867a23da1a4c2196f91fe0bd4f0db1ab324c26fe6088d7583f3cd052b7f6fca38e8b21f98fd07fe78b7657da1f586f1fbd3d2b4079e20f21dccc0d269d53a29deb7c7fb63cc291d1d2c50ff163e08ce612310d3bd622f2416e193078ce4e1463f8a3490578af96ca98e665468281f1af9117a2ed23367df19b570885de9d6594f09aaba4090bdd1079720b08d54311793c97bbe14433b031c865b059cb4f75db74779b82c4f83eb4bd829c62eab995027b548063d7cab7d1a6f9642da6cf7181c0ac71594b97fc2c84b1768f81eb287091f63c76623c61e7ba90c922c74d46b9ae5d8094d9752bc1e8020a82601c356a201e0473d540053c707a88f4baad37826152dd245c4cee6b0019583c61e4327fdf6bdcae53584cdba8a503b835bfb5df9d649705fcc1f09376eec96c3da1e105accc1cbc21d90f527041a9beb85f8cbb1ee8db798838bb45374b741618f83b5d0801a3af2f640abdbe74ec3dc15d6711b4c1480aa8d6084defba82ed221ba359c9744705c4feee0955c27ef468cbb816694516f73fb541e0ad4ccf99ec8b67ef090505d1f7c4c3a8ed7e291c820261f12d92bbc6609da6c275349819848c9112826674f243acb9a29ab73f17c8f8af12c7437c11972c824f00db7ad284e51b9b508a925f0664bb259b4443d56463bffc9e5d845c9b9f79b24c1f457088fadd281f48238866e0b92d6253638eb188bbaa8bf6a81d2b1087904974752697cffb00b4ba05e5b7b842a3d2c0a743e4bd691625788fbe9df14600643b1d161bb2916176b6ee40aee38dbb594ec2735d41369ed3a0c6dd9073f1eb51d1b77eb9a967b53670a8ed755f3b2b73a6cb50a9e1ea7549346646dbe4b801c8aa642779d8761b6c2d2e1a9995e758ab92f07c4eb4a23c042171a4b354f434ced5f6d9ccd26cd6c2506e5023dc076ced15566fdabc7364f4a8594cd6ec404e1a9470f52a83052390e4f7789ade9179b069d9f84ca2c7ac9eea51035db817845aded7405bee90cbe92364c8c7cf8a366cbebd7a972438f2a9881395a8610a2cd0c06c46b60cdae5b1f473f4fd6ec48479cf35101656f05485198a470cd36af22838e7ba3e28863cd8ba7bbba7e3c2625c1106a6be44c9e3d9b9938679b26f0713c62c3757a2dc8b2d9eed5e652220a7711cd220bc91a9afd7c940dd8be71616ebb8b2cb0686dfa161c6ef56994a3cafaec5e79bd0a2531fd1c1a42771acb101a38988bcba51ad85bffcd8c67aebec5b37d526b29f7b9d31388e1e7ad7154f8e65516f0d80a30b88c2b868be2541d19ea1d2bcbadd30e2fbb1b4678bfef7f200e0f8309ac0701000c52ebbcd6fa00cb85c8d3ea9c5aceeb3adcf3773cfb3bfc9ac764d031d7c63ab888e9b03eb9fa74554dab4719d426d0875a508c8c86b22cabfeeb70b0f1461db4e5f639d2a2d28a089dbcc48e3f34394ff1acb887b89f75d3236c8143bb9b06273c3878744340ea1858a9f383f8bbdc259250e23a3c3992bf8b7ca7e1a66913547710402bb538a8866772d11cf4214060ed091d403e1c9ca3af75859259f88656a1cfecfdb49d57c193e60a2223627c681a2fbc7390140aeddc19df035a5207adde4f5736bc542bfdc943ae8b094f4a8701618688fadc2284fb423f602c41ad8ee11e5d9fdfa67fb7dc7d4dce7847d4875b3af667168ebb6082f6911c95", }, { "67f0494a728fbfc84e2f4a043e121ee40f3b12b31616c78e157ed970db28674318b08d8b3f4c538d7b9d91b9b0b09ebfebb07201c6398fdbb8684c9390b3d6a8636333a3b086302b24c2e5d47283935d33065efa3fedd5f755218be5d4618d38c5c1db75470ba06bcd853f3f08d39c3cd9fa3618e70b103c2d9b2101fcaf39c1701436b720d723ed5c622d6535c9a10ec4d727abe237e80fd20911ceb84a90285fc6e07f9d036cfa65995f9b6300a927d7d0d2b907bac9d9c4daa87c2438a583fe85029c886f96ed08f5886bf53292cc0265850a1f4ee3e3288b604dc305d0c28ad35e1242f4ff4ae988b6deba48aabcad2fc6cd7eaab0a63510f3f915c4bb9f9719b1d90db123f639d9d4f3227eafcfad769c2b204dd2555dc54e738909122022c4f92f751d25aef6f9a1187750e825c68450e6d1223c2fe88aa27194b492b6788be6eda80b9b9f053cb77c8d9fa15324f23af5147624fc00c66e947b004bf38b31e1343c7cd341b98abe462a5f994e51d343664968624a2ed0dea9d0299d5c5a7e9097fa63d8b3ed96f917f693654766a9adb01110fa3fe0d8e9b102860d5c049df3fe00ccb2ed62ab05583e6aa0a5134d55245d4f643e274def29d3fc86d79979d599458786a8338b0071f6a01609ee6b2e4bba9289e2df780bb27491890d0b5ea650e62df819b8f98aae99a1b8870ce6d3c7785ca957d5b4094946925751f0fda1d62a9aefe3937a912c1b49b4272f87eea7e397feb84c0702929959e38a568460811e5064b1caf5dee53f920c6e19fb16fc9214b5de1cb770b510533f66d8a0e7f6f04ba8ba41869f8018abee31a6042d3919e217359988eaa9db2a10b3caf7aaba43527484d81304f0bef22165f74e9e1031b545ca3d2f74195984cc237b76ddbec85142a06446902339b1883000264031db85fb19b46f320ef3fe316f750f2d3d6070dec5b66ee8ef20701f20965f5171e44c8a99bcbca7afbbd81e30e74c6d48bc4b0d72baf562da6581fafbe14b6cc597f75e53b305036ede219ec56d0c0d29571a9c110ffeeb747fe56f6030dc26c8d3841b868a1ef56840932dad9f3bd7f75573086571f4d9f0d949510a2577d2f8fbed7e850c73ed4c071bf9a656d09dab43a610b49aeaa57333f67d586d4f50683dceee4942db9549f68eef4c5f8df8a2330857cdf2fc4025f2be7d5f0dcdc74a9cb593de91282787b716d416a3ccb8d6d40fa3c70be4ecfda26a5caf3724fad3d98db16ab6d8f26defc68392923b69664b0c2d56f01a549284b042bbd43c8faec940187f190aec08d06f9a62ab03c9f610f64c0010a0939451d5502511dfd3da1fec5a38f64640c7b6db2961def257eee9a3eff944828e9557deba68bd8e42dc7a9c1570e35537993061fa0f5351fd3cf4ec36386ec4cdc5a2882d5f16703b900c5000efa63888d69982e5ecd3e329c8cf5f003e23ce03c55631246ca15ffcadb0fc9d5634252ccda812ba7bf5e343c44244026512062a68374ed4d8add0855dcc22b30148e0cef0f2886be76bafabadf3ae1205b43c6deb8a41c338114895dd6b49deb329ada31b350e02a1bdad4eb05b61b50f9d22fa2863bd607406f552713e302467ddc78213d584b4933202438d63f99d011b97297f5589f35b7e45ccbd76f02453b7a7668c2b1a1f5d1d63eb805c8881771faaf67433eacfb22f9b6fa58b93f9423a5fcf667aeec39751ae17ad36992556431bca77059a29353598dac12bd3036633d2ccadc18f44123e5bc074f4e5ca380095af062fd83b647015259be929011cfbcdc9bc5d0dcf9b688f0f5d74da95746f447a9e1cb5028ccb2827b45129d04cf6990953a6d8ee0e67fe6bdbd8004f4744cae5607fe7ec4a0f14fe603dcead3367b6870d8e751cf57387d04b881f92cce9772d695f19b36e2db2cf6a807c9ee83225f5c09a11b50e99855921a4eced8e631af7c234aa31615c00ccdd7c6ac5ae8fba6e29cc233765a891864c7d73dae08ed1a3c27cd423d8d4efb550597afee8356c12018f496637daec83575f5e38ed2fdbafabafd38483c239d31cb4d104e93d16eacc6050033a3c86929be4ca8914a538bf540b43d7ce7daaea317bee1ab80504846554879f900d312bf2fbb406a0edc5f4f809cbc68675b0b7f09fd1a8a4d52c0929b3a8b9c1dae4b3d599b976867e6a7e8736450dabf5c49c949544386a71419324ea4ce5c4319899ca510f50d07ace57b013655b0929f79dbf3cd629ad17bdd10109b7c53a4f5f04a16e5471e823c898362df43f57ebdd1627b33fd4cafca6cc065d9140acf0454d5f99be47bc87e0f3b4d4320bbf0f21e7c261bb8d5d615963beeaa46bdbe9b83a8277813ffe6132b23564bef5", "74dfdc364097c39ef91c01b707a522e28edb1c11529d5050ff820234e6c0295aa00591e09d547e9671804d7825705ab44b76c59d1315ed1297ef477db070d85076693013bdafa92e2ff6a654660008b176cd4e8ae23b9c792be3f7db54cf2bca385bddf50a8624397cca8ee3cb96944164e3cb461e68", "b3b5ccd7ef49a27d2c6d13c0ae77a37abec2e27e0b2d3530cdbb7f36792a7d2c", "c0494bb7249f864f69beab46", "ed8d6e964bcde1df68e7f362243073941fd68ac77929c8e480c89f519f748b3dc337b1af6231632c975167a8425b174b42c2c60dfc0ec85a0a212bf5c9aada818a83f9664c8712d96de1036b5e5d8c8298786b753638de3a8da958549f16eb9c723355cdf7b999aac464ec39df7d6c1607e81b88b63043d1c847dab618f1b19336911b4b0145c2a694e61db71e021282006d48e37f10f3b6314dd012a07618228532c28ca84a936e0eff83723d117b2f2db857d14af5bbd5948a0e53018b31e57cc2a81f36aa013a844990753ccb347fe98fab294cbd252a8b8f7246276275d2780511fd3cb7baa2fd1548184f968c422230f7ad73ae9dde91295f79f6b799e7d234dfd6573fee6d6ae748b0a8cd7ed4862ebd957390826f276c2afb01fbb4b64b61a1bfc138508efd630e77580867bdc1e96a48a694cf0db6c2a11f05dd0bc8769e7200bb0749f5798b6f3559de55d0c281eb5df22b731fbbc109da9c68f209b888e61240c4c0ca006d105c0a7f43144021547d3316e5a99f6c429f9ea2f17d77dc68bc9d5125b6260f79bc8b3b8061972e6757d87b6544f21645c0b4debe5224f7c48142c09f35b8e144c0c1e6521f04c170519ff744d61abd59a56d25a26c5ed5972191b25e78e2140f3ce68fe17be9e59a79f6c69619a79b83614c670c7736d19c27fd22515fb5b896a6418cc0b4850e85c07b38b995cffafd9f69763cbbcfa9d1bbea6868244a66a5cc82e815fae09f5775d28437634926d571c2b0d200855e09cbdc67d10f85bd4cc334ded4c83aeea57f8e373a950f135997666b653e8de47a3bc0059525720045996bff500a47baeec97808fe971d7693dfde339e8beca3598fbc053121536c30d0af10f8f5d8e5eeaaaa9586d7abb563fd69e88351f93bcc46520f6d97c1a49ba9f8f6a25cdcfc11b2a722910aabe7435ac8f0dcda9f824fdde80850f21a2d4bcbfd2e9fcbd14dec05c117a9796db49e2f0dc55e74c7f0f615bd049fa7d0bfcf197dcda3ef3de90762e6f6f9f8a8936bd04fcf2a97cf18ecc8f2f118ffbf02b67f252097e4289d02f264161f6f90f79e1e1ef8414b01a9e1a77b88c039ad6eda6df1e28fcfe9370f0d574aa9e857dcebb19eb7ce8af9b19b4481c9fb3e1f0db3b02af483f737ce3ea824b2165e7c0fca8585383d4b0a16eab2c7e3ee5c038f939a97bc8e1c093cc5372ee45d81836c988f3ab3e6ee0e5f9549e4b7bc381a2afac2074cf75ed56b0e757e7966cb253d549fb0902da98294c6dd4de3c2e166b7e45098d2729b1393deb68471d4d3218dea3dfd0183b654ae4092a79357945eea4b28cfd06b40d30d1b4b8f19827895f6f908f0fe511f74ec84cbab2483ca4bdfc6ef50178eabad79b18b58529c9328c13c52c2869858cc20ec36ef7717e1c743d13f9607bbdb0b701d9df6aca7366814e883d23e51ee5b0f20ef70e2c4134ab037d213315fddc89009260981329a1872e541767adbd5ee9501e7df4ef0cdfae9769961f8716ee7dfbab0ec89b3f62e987387d5842e124a69b07245d359052ada50cfd67472d27ce2c4eacb5421b62dd7331da54ebf0989803797f4c8c781d0e2e6477b421c7d5cefc8146aacc0012af3f1f7cd71ce2b1045d86bf48c9a13fe469a1865294e160b4975023d0eb24ed26837afefc250a914f86f8b1f5d67d65e9737e841519148d4dd5dbf2b5a8b073861288ec9793d4b113d71c01727f67d791852fc3946dc912d60fc66bffccf4c45d859eed9f0bfc7f89086df5d5cd830ac919aa7cdb4504018052d67f6a3ca012ed69187cd5fbe91875cfade381bff1e804ba59cd59f0f75cb46dcfba234ab9832c3fb9aa8dde19fc1fb30677ac1793a38d94aefd9ffcd4e777e9e4f6d49e0cdac6c16a36bc2f3ed8e23b80350e3be6d866aaafbc8cbf7c69fe44c2aa80651164803150c23ebe262aa669c77ca94d215895d2ee9c3e325a0bf2c61e419a41e0f7b1ba8ee0508307d49301abccd5b74c054b6c7bd1aa67cffeafee033761d8226d9dbd7214b130a867764062cf4da685deefa23693b8549d5ef5e53df85c19bfb3c43c6bd073e7a836f849587a4747e1a9a3c7194f6d5472d2e3e4c81784a3061fc9bd3b94862c4784974d859134369486f2651f1db94f511c6f59f41da0d75307191602730b88e4e6101fc8d392c87687f3be454dd92fb8ec380715bcd88aadb63717cbce4db91a36821a572c363759d8d0a2ab007e5981b78731dfdea20d900b14f0c5ee6a4a9b532ed2134e6edb4dc267f001cb88dbe43aac4aad453b839d035697df7de98ca7a9ee7601228a79004b89796e9ab971aeb8e62c789bb21f38b77b492c57db402bf6a42ad0cee169e9251d865ea3e5f79b1801ef1e53797aa6c7060d6f9486081", }, { "04cf92a64cbe135f7fc1d7223b95e41d13f04b482018039f4e7ccacba8aa15ac79a752c5666524e527fb076290ec80a3dccbebfce3ee9b316a65fd130f12bf88b9124d1f7772049e6d0c01fef881a1d44c8dd02f7b6b60e6d15df9e06fb86929cab64842284de09659e19451623525aec2f5dd3e603e24319b1d120bd57b34a0317ce25ac9c2f022a4847306b998b57c8d92baeed0de1f6cfb3177d0acab70de275238f1152813b9ac87bf651f74e1ad079b9bd779ba4374ecba459865b5768d08ae7e1dd691d6821895e8380ac9e5116580e8de3a2c5326e698bf4c4d35d955e45772bae8483d01de2539e8ee1ef9539ee132d80d85fff41dbe406af319c0d7703292587bcf5959f49241e2b03a364e1b682729ed261d0ae45d74d77634afe667413ee210983b042a7ce6dbb61c29d18450fa7176177b5a74f032ea24e1d08b220f6d32a7a836d1241cacda39d6acbd26a62f9dbeaaf7329a291dbf0aed4a2cfcb85ea360947585b1215feaf70ba71eb2d6bb7081b2a21bdcbfdae6ad2513a9dd714d3d06c2c2b7e322a1db2d48f9df1fb44fa066f2bb42b196295ebb3c0898ad55d5b317986afaba0bd5e754cec773821613e908ce2bba6454181f9020b73e758df18c255c87df675cc6bb2b8d2eada44196ac10c26674167f94a79f4be515d8d6a1fd3228dc9a85a355b030845dd4c5f481d5b6e74acc66de730629581b022fbcff61e5dcfb6a7f511aafd577849a6b057021ecbaee53986159c1ba74c3e930c34a159f467f1e9799cd6c1151067c56769e43308c96c8edef8aa7634d909310dba9af2128cdb8c29b24d3ec2a4f43a1ed86d1791c9a670b240e6e719f01827aaa319bd3ff53959a776886a1b7c942a54f141e6bae8576d294e44333e6c5ad90f74863f69bf890126016b318e0f6bd2f0adb9bb861118af5f6cd28dc93d56c8a1dd080b8c810ca29267d410673fe367dd9d1353ae2bf2fd88d57b4202c21aa49f12a01b93acbe260492367bc219d3afb6e6f35502f6529bcbcdddce9fe8632efb034a9eaff8b4a48afb105d04e3fcbbcae010ddd6636992213750b12fb3e01ab72aa957136e0bae591bfb5e0fe819cac82a98ae8df230af399160594540640c6b1d537e7b5f1cc47b08127ae02c35b846de56c4c08773fa18d4436e14b76a7fc4bdee301d0af4880306f2f33328ab79f6f24ec779b2b1928704f09bbc5b0b7108e9a115e4959df79c80eacfb98649a0788867e23b2974b22e654ddab0494bc922ecdf17727d0f0efde9dea7601857d890bfbacbd93f7df794bbc254f50e1e17eaed2f5d5a2e6c58083aff68434730d406fb9fd02b0dd7bfb99a04aea812b6830fe5e05a044ca21c77a174bae8b58eefa11ecfcc1c977bc6218064c9931b5c92f13cfd05799f11e130869c293c1b08dd29c899365014fc8195514b286c97cb6dc4b8633e47751f87fbaba137b6aa04d072ae06c2b2f34448449f60b1272c1efbd4722a2be749a3d2e5450aabef1f7c51bd8324607668a8caf8097c2f358b1b09fd3525d47ec9a7640eb20ffdc17c4f7eff63df75dc7830c471ace3a727feb11533d6e9a2a08106af33069cf482ec63724032e81cab18e12cb5c4c3ddc374e2f75bcc99fc5da09b80a738852a14e8ac552b8471c6ad52e35317b730db2c13c277e06c643e0d0fbea43833de4d2c7a9247ff040e9c56f1ff7ea92049c5341c4d1478a14275a10119d934e8165152b89951bca7ee1399dd8232fdcbf831d8354640e698b68799d060ceb877201b2fb96cec514affeb28721e163e1648164b9e5722271db9b0ee1a7f96819fa1b1590e9daa598d9571ffa3882db9d034056e9b2785a8d13686eba61d7d45cf2e9ecdbc391739ce89297211472be18b21401658c5bf29fc3615924382d802a166d05dafe7876e70a0d081e80c63632da379766928a0555eb5e7a238cfa4da267527c66caf34dd40055f2801b29b3f5604a5bf3d46048bfbec2e24abd2fed2481698a4b5cd71f5d2c12dd473b903c9bdb978eaff7d76fb69951005681ed7b0257054eb3dd6d10097fee51ba7e8d565925e4091cbb78d255c9d3ab4ac0264d172c9bcb0908db1288c9634248f198a1167daa323822058decd83936985f83b08b1e7b942756a7af200af168fb8a091107b4443fd649cdc22106f9b9657c69f19be485c23b2c715b3762c332eccc44f380883357d10019f20612ab6b8f155c2af9e2ec340e5d8f45bf5278ac1fbc9f9f44d2f615d21007d822b244b1c7a0dbc182c7f5912485d6e4d74e90f60a2f964e028c63d49c6aadbf1df170e4914ca514139ba538207b1cf7caaceed4db8423dd1086b2adf15f6c0e50dcf2e12898f53c339a745316904ae03c38b417bcd7f5cd5ea77a4f06e65d56c24f37ebe72d271ac79b6ddd2bb8bd67f0727ead49737aa71af4f620da53769ca3ae878adbaea5a249128074ca3ddbbbaf5a68f9cde2a0e8d69708b0ea7f4c8d2dd4180882bdaacccf2a409a681c551776bd10439fb12b7548342532b371c0e045d8e8c895929464bdd4fe25f0533c66104daaaffed52446094978bcbb389c", "001084c8a5175c0ad43108f9215c35886c82321c800740c6118a3fcd45776a4588ee0e2d056a37d99b40d2bd9c0845088a77240b7e65d18fef105d3488c77910b5873dbbf275948db5", "d614d2e671066e387f7eee07bca9f9313d86e6a4d1371360900d670e11ecf1e7", "674a516f8f59f9067e0485e3", "1ee376e9e3c89b2147bcf75480ff0dec1d0e8cd45ba812f34c84124871d484b4ca87bfc8cf99f85ad452c482933801426e2737a97468809fa36caebebe8eed07a626b3bc3614ef1ceb54f9221ecb16f413f0bd9ed4b3010c40632f05223484af7bf5948c2fb8a3d2ce04c53e3f2682494f3969a0f8eb738cf93c0141799c9e6b68924433f0326991e19626bb19e6fbb5dd46baf39f92e830f9b1ff465a007f031891fb1f1799cc122d3ae7a55624356b5297bd5d948d9ff2e414cd8adf00a53524df43f398938d33c93b2c06bcde2679566c0a7b0177b4a873f35874739d550712d5cfe3d25c19292ba97c01d84224738bb25546e5c252fe5e5f260ca881aaf176a271a6fca2edbb2cf23ae6d4c56c20daadadb8205c2e33881867cd67ae6e59132edccc3601f014b744ff8eb6aef5e09b358607695d3af42ab8fa30e9fdf99ce54427ba9da3699de19f7a8f9be368df47ff0607601a91e7a5fa6e72be50bb32b825427cdeda3972a18a23af290986cde14f5fb9cbddad336f5efcd2d7a0cf3d5b23e54b702352fd5ee52d7e3479441497d56e17d5868574c56cfc421ee47bb00e9c75b84262a1b9e2cbfcccfed9c4c386ef0d2c1be9a7b7556909b5d72a38b7258acdd624de2396c75386e077c34f005f92a2203c82d1072c8998f03b1df22de832ac733977705453b1d72336b8d371cf1ed3923f462ecd22075de5df68c83ab1e6648ede7fd5ee5794a744abcb32af73bcb182cf97d36f37c15535c4107b7c8f2321f9fe0e2b6ccbe74204df3d748c05bc1e0e2c55ae1aee2d4aa4a52e98ca7229d6d06576196ac8e4b14a9ce807075cdc876aaf904c9962741efa8c6caf41e6b87b2ecd6636e2e58f3ecf576e5d8b895162545e618960ff6e336ff17eacd5a1eb335001633fa78c41ed05466d904ef9b81b643a043298c0e291a085e4e67da72e329adfccc407f800709865147db49cbdf4232073b7bc7ad89b3dd901d927ee08ae6497e0f2f9d052ca8d7444d2e2ae2197f930a7b1c8af38d8739ad298464169823684612cb628c484f710cf9c552551b6837b575a43275100bf800b7a3d777adc44d07f67cee5000422b9049dcfbedfccded0f2aa4d189621579b01e3fdaedc4d772dcc593316ca85e7aa248d219dac21c561d318a4936ac0d3bd5c75311486c174e0e2182affdf69bdd6a086534e4a602efba2b9363beeb5346539b45336cbaf479da6b15b226a9ac026482216dedb84ae3443b306820d9f05f78dca7090d727c7481d82c6e5df80e189e24e46f5758e453e542bd91a58eb51a89e07c50afb543c6b998704432e863dc4c0d0236e0672835a7b0b64e14f5ced2904e54da4287597f920bb4d542c35d3b0271cf0eec055656d523d7d2cbd667445d3e8634854f8616b7d7a7f3e14fd32651e9df40e1daedfdff1371f16d5549ed5646adf2d417e4b3a4d145bbe0974ab388c2716861a08296b862e4fd035163281457877eff89dadb160eb2b780414435784804bf4fd36602699d8c2f6a8cbcb509198c38e2df2edaae7bd7c93313ca98a9c2d24419a12ce35b0b3d68c18840e3ff8739d70969927c7db9a6569787bdedf5c99948a9e79b2302a83a71159f4c789b3b3f05f1e574f8a24c899ae3457f8e73f9bd86976fbddd83b1af337eb8da4c0dbac3792921597e18a2fd3a0ac89a270794529d370d36bb6dc7452e754e903781cbf57c8646b92d5d02842e7df229b3d721f9b981f9d61a48f00e53948a5dbc4f739849609d94aba3e3f5f8163d40321576cb8eb8e89953b608a01184d41aafc13f40c47b12240e3ad49413473c26b6843f4514be221c2af632d1a54cba230457f23f00b2608485c381ae03b389ad0a1671fb416de4659cc7f7a9c4b6d9807789c307d061fcf613b96a2d79e5e3e20b863c8b1b75f35c982b40ac8dcb7d2712ef7df94901facef783e8015a9a48574aa6f0cfb0bf6c1a3409028f8d62137c347f5a35ad6a3cd60d71aeb29bae56bb4590f69226fb4e08fab7a9f41e58f4d5784540a70e7a97720c549c8440b089eabd0eb3e4d37a2e54b1160572ce568f4256dd244decec31fec555017ebf488e878945383750eff26a8a1cca73e7d6f52d8cb229d5603360a3bffec23029ee34145c4aade82d486758e0aea9e1b7bf0b4bfbd4fcc96aab66a27fb463b48c6a6c5c5a60253e2fbc5716ef55629277a5f3b89c300e21bf1226241ce0d587fe3f5b11e47f35614169dcfaa375ee1aa589be33a4363765368f5666d155cf72e851d426fa67b982aac4dbbc29356d71deb0715b34e00b9fd8876bbb09ca0701b15615f05cc45e128b3864b26003e6ffe801c4e27402f37b8997e0c29ebc273dc03358cd22fdb68d9cd3b56ff8248a727c2d4ac65acda4d0e0f511bc07ab06cefcf444f1002c151b953d7f7b19695668a86683497c2a2d2e69f19a4997148d2e8d158da859c8f44437d9ce9db92f84a88e89cbffc74c0ef4295088e2543a4f7c6ae9c908bd987bcfd7a074f83ffaf3888bd7f430dc5a5bb70d223c21b1bcd8bff2103408460df864dcc168486f6a66d67ded366c6e10f50bcddada93627cda711764a57ec36035ebc", }, { "ce72c93caa49bb9850774149a87fcf8e23a0c53701554468645554553d54190bc6e247712b02097b794bc421ca94afed34742435ca689d2ebef183fb469c060c7f4d7daa508726c9d2eaeb9c7e9a89b30faee8d9168607d4778acfbd27d5caa623475073ce763ca061273cdfc2c692d1747baa8a01b15f783b2e36620400082747599a16cfd6b630fef310c0b9a2912d1d3bb71eec16972745cd8a49cd927014eb0a2abbe0e1ebded4fb9e8d9e2fbabb6a71da5688717ecd3e08160b9a861f86904a41702b2c4fff28ed8cc61d468187b75bde3fcc5c0c0a642215fea83584387fc5a9aaf2f8a91ae535e0027b618a32bd687289c47e9428a1a92649deab825d702b076223b07c08e55c0b60be95937bfd0504c18398e924420f6e20baf07e2b1b858d3e360a461b66517c24e60f9fe314a4a4973c8dbc7e9d2a9f571a1d8235a21073d81ab9f4800b70a5f17f44d593e8792a2507e6a3a41042fb2a5f7e5f028ed2daa88cce28973ecd88bd125d50fad77b1fde61c38272057d9c65fbfc6789ce41315a105af14e277a0c39d75c34aed7538c39160eab1c8c47818743e8111229426c399c5e88c4d894fdaff0315ec885ea019bf9acb785f3380c37201d494a60b583fc130bc0eb9fbe9b90eff95874e35910dc05c761f8006e2f208b786aeb2eeee841f9a82d9966c82956c181caa4dada81dfa2e2d7a25007c2dc7f2dc7ad1bafef14581cadbee4d614a557df4931b9ca105bade8fdfdefc0d96eeda11c08500b1ca827ca670ba07bb0f85af92914c43a6f71226d6e112d487f1ae99b2239a63ee2cd0849d8a9c488a11f82ca334604a2b7260f25373c6db75656527890f9b772c6bfbb9f687f27099ea9d4d1efd874a6ff83cc36c039ed1690408f20394692ff054d9e6eccc6776b6f4b3c5f24b0052334d159f40b470a9b8799bbc0df4dbfe59a5e536624cad193160ef23abef85df2c9b6e6d4fdf16f848a2a446a77044f1162a278866c491982570cbc16041908cdd0efa2cde011526a3c96d4b39a23c5fcc53d8232869cb4dea871f4ac8afc795aeb1b28cb2d7a3669100a1cab2ee1a7f31e2a25a5c6da836e4b771ad57393305faf582adcd26045e26b618d9943358c615fb206258c8993d700adac7440dcd3ef34fdcb065e10e9c9727662b5abee160aa01d2f2ca6c203a76fb01bb08cee9fc1eb6bc7497bb012ed2774a2d263b9dd03d60c307ccf33233ee33eee702c8e3118f9f86174a97462d0e804a24bbd7f4f938c7f105bb23399967288069e1637b60f2f1883d88ce5a874ea4bc0a7ca0f3b568e4bb1407e4bd6f0d3dc8fe91345f8435d7b1be961c45e4b0f1ef2d92d2d30bb78e1fbf72cd2e7ffae76e8c2bce005195c2003bde46108f37ffacdac28fd67a0de62970b347f0ae3f5f3a5b1d3aacb2fcaceecaf2ff4a2aeef6f5a176cc1b74b234f5658ce603bc353e075278a4056540e43033d37a6eb2615453d8206f5cd294423811283bcd5d79c4afe268a547b98977ed5cf24c0f53a0533bc0b2889356cacb67e2f7353060f9e04362859b1c1f02f96bf5457b58e5ce84a6810d39d7c7f53faaec64db5d6ebb90c1412bdd503ec6bc240c277ce1f5f18876feb24eb6a77e5193e33ce141e8720329add079dc9735f0a35d7d85436f1dba6dcff9147777760b5aa2ec9c8b5e9fb4fc602ec8f754c99ab2372ff5963dbff3fda91865108e606b214cf7acab875197e78060eed52a798751998ce7c73cebc4d5f429f6729a5193d7593072d0921ac8127ba6e796107ee7b9fbcf7128ab35fe9f6fe501fa4695c19fd64460685f287acacf5250efc13899bcf80ad5a340d432a0b9449affda5c8fa090f008e01873aae7d5fbc7972451542c5c29cf9cfdf23db736c8a7112536b1b626caa63f3e4117044cdeab612fff8d8c194d19174f56ce761f6587349c48fab30390f231d209461ee7e18007d10d83ea5aacf199f3b00003259747b1d03274d3c3670595604bb4482d345ffe31d3e88c70da16649a2677bfbdbf618de1d651a53d573aada2eee5c01335ce5519a6d18a70f7ff0b1e66bacc162c49f7f29b9d3fe2c7dd85b6b355c9f9141f02baf08d2be87c36f6d2e1b2e90dfcd100886e306b360df0ecb146a6aa5ac5ad05b63a219ea65885894a386248254348ada17908d776f9b438306ad28b208f80d6b9b265500aead945134b9d388ed5d6205edf07c5d8bbfe0916d0943750150e09c76359d24e3317517ea489fd8a501dd93f159f07d19d00e86d952fbdba2db771910143df346b30a30fba908a1abe5349c3f241958f428dece7ad9a91cb42035c43573b87b26c2ab216cb4c21799f6b3d81acd300ff50edd6fe7868b9ba6c160db3418565ada027b46b63e5d4f3411284fde585ed3673b424ec1cdea678e4a43c262991c3c9b988351d6e0a10af1c959cf21b7a288f2e4d7b3b2c11b400b5e036df71fa993b72ce48d0d8598fe4ef1ce70a970f89b55cf4f07906a479bc84a08bf6ab25221de37afebbc47ea0b38b87be128737d7d43cc84d336cc6ffe1677bd802910a2084751f30398dd0ed09589b2befd2f3b40fbc013318c822fa2faec2323fcc52b43161f47aefc557e92df3050dc5f8b1c5a4b2f8bd7b2ba7aaca79dcfa362fbe7781a2e261683a4a862d5f83e34845a8fcf8a1aa73cd521e87cbeb71f20b20698cc34bee3b8628b1a3784596c", "08b3fbd73d157e79ea9f61665d19867dcb8c1598c1d37b793606936d8aecd992a0d46addeae857d488b83be5d1c1639d4d78350e4cb08782b61bef4107c9d3a79d3d85", "a56f38b4bbe83b3d9e562cdf5ef5b30593f08a1a166676c4fb0d5861654e640b", "8726dc5cae9497936658f603", "88420357d1ad70e7c7bfd55b3cfd4bf06cd4e9b4ed5cba681045199a06985956d35fe86b28b9a4599964930d05d230a23c55a6a152f67082a453fc31f68489df05c553f9ae5cdb3f611445db384d79af865e52440a876fc4153d896b7a2318dbc2a4495ecdbb2e9dc68022326d35289e82aa55197aedc266dd91ba3018c7b474ba22b4e773773f3e9890ea84bc16a6b235e4bb69e785c40c1adc15b0e0ef03aa147b0d14e62341e27398b84a53f72c9199cc1c94cbcad2bd31aa69c96b06d01775b8c0f80278a43f526664bdd430164863c9c9140ad87798a5b8f38dfe90d37f54d1137709d5311136b728e6c799da244294daa4c8b44bfb0acc603a16c088a081129a0d2cff55ce1c4ccb486fa0ecc3098ef2196f47c49f9d253112bd5746fd99df5d2be577617dc2519c0ad04ee49ee1d7be3d50492017108fffc9a414ea227af39fe49fb2c895fcf00d927bf4a2d78c466fd44df4768e6775d39fa5c834b60979ca27ee9f00faf37a090838f56275a894ddadd265a8d2de74265e4d8d286639ce8f01eccd4f551cf6b4429eae3f08902b6ce6ef422cf91ce8946d9403fe8064784895b62a7f5df76ea294132c59da6b9f53d4195c1e9000bec499c14cf8bad460aebb024a76ac50616f0dcda71c0f56dd3239b11764f3ed6ed06c049b2ad673e4beea391dbb854fde1f01b1900858b9809259f3906b34f95a1c6ce8d24fdf0cf7c2ab7bde2202a7f1482baa6e51caaccef9f541c377da620bfbc63955cae0e6644ec8ed6878f704f1dea30d6b50d4291892bad19b0234582d50c6cc0b4165322cff24a9dc2ce1be35be0fdb3bb7abb777ff0b2f4cf16277388af5a89220d59f1f45ee9cc2a0fd7af9aa8e9e8d548fd65be4e47e7f8ef58f7701f93a42e7ff78f70e807fb63513157fcba96ad9731b2e8f80da85ef407d5c368ad16f0657620bfc122ba1b10d7ac2bf46d8133a9c6fec1fe04882f3d5765da8f825e1984a4313f72b67d806ed45c000dd3ddedd524d474b9b5788547d0712e8edb4c6c586d0cdf8f2384f1e093a7f6dffea6e79df9cb9398f5d0b9a7cbd63d489430fbfa397a0d03ef916b7702f33a54ebab84a7055b7ec6179b0ab7722f03e126ed343b1cdf2af3763df7e3a070162535514b01ad86c6cb051859aba1cc4766b12c8cd57b73fdd3c65af6961c45395aa7b885dd59e115db885f644e1c94bfa26b3804f767601c86e2c7dcecd4daa59955e6a40991a4b4701e63fc82b46dc0ccf59af40a8583171375551c868436ede535705f2e6380c5899cddfcaf9e94314794bab98846cd5ba9e9afbdbe1ea7fec5e22e7b2aae59fa598f4d6c0cc6f936a616e11bf01a2acc891cbfa2bc53c511a8a3a3da2e3aa5907d123ab2a4a3c0009fdb5235a3c33718fe4c504e1539abac6370e06150c402b5fc2f8c32608db4ce2eca9d1e4b96371ee195f6cd632f5b972385f9d5d357b87c78cb4e2c27aa9851534de14de923543f5fd9d55e34d6e8b7e1f3f2735df80046de01f79d0321066f9bbd76299c7386d285f7bf4ac15e033e89a040710c90f87aacc09fb8159f93c8b4860247eef079e32d05707e88aac734a2eadaa853f528d9986e0af3435b5c5f44ddfdab9b0c9ab3eea97676e920f80d1794740067f9b229fb018c804e595aa997533a5e967cb79ee58eea18995a90ac08333f1c69600b17ef4f454f540dbfa8b502457761bc4daa876d9053ae1f55001b6916ce559dc6268d01841255990e56614e6f4ee4ce04472dff0657360d75da4e83a71c852a2585110e53137e91bd89d64d99b5614ab2a5691c876f15d9931b092fc6729c0732db5cc40f966fe440ff99d7d05b24a872f552c27fb0cf2af443340b153214b407fb9ca3750d9c157aa75763b0b7600959663889d00f392d6ebc12835bd2f03ad802a21d0228f1d2e9731d0f0051eb2d5369ab790d1134c38e28d2bc2d5d57d6d897244742c176559961a1e40c84ee5c8225c8d72b92352a011e3785c262aac115cafccc2fe1b5e81a677a0220f207ebadd786b93f58e40eb6ade68ddda5b66c5f0f6b4b95cdb8241156110ba3303beb79acbd54423315768bb43b4fe8c4a465e50c4e63bce272c4d731ea4c797e14b2de31ce4264e2479179b906f67af4a23c56e817abafedc2c7a65aa45f0c89fcd0baba60561a8d013e2d5e0bdf9fbcc1346d3edb20e6e9f9c410982e1ac43039ad8fd0ebd453a6788376951fc20374b59946a6803498929d9fdf2e0f5e58c441329a79d1232e957b3a9ed17231c663b4819dcb6b4e33d205edaeb7d7ec466930bd84a064b40aa67fd76f6ca005408062b45b5aed6f8161836c7160a8c8313dc9aa1c6d42c2c16972a1065e41aea9c58db7916e1670cb42a8b54d85498561b4401761506860b19b446655f8988101fb4c45067e30edc3f00df8d88ee34111dd6626d605d993ff207be09704fd8dc242ce514bae77cecd20f10d4a38435a3f5e545882fdc224586a04ca6a162e118d23716240fa67892b78faf98a17916471f7f121fb9f85497a0b34bf5aaa4ee1ed8a4681bec55d1b4973d4368600115bea70f20a37c9e942b87f6cd1e2ab70fd401e703e3c8334c75fc338508e06d6370779578fbe737a75954b4701bfd92028ec32d3d7ae606caaf9f049d9774f70efa707c1c1174d9fcb5b0a0ae2a961c6f58e48ba82c2db14ebbbdc24288e42879f547b855c86dea9a3b9877e4b105515bd78cc43465", }, { "bf7884fab52251e202afd7b5b46aa53f85bca5fb80a009d8016e276579e401385d853312a884f4aa33cc5fe7360426bbc0ccb7416cc0196e2e40d3a825d5e0825a1394029789acca550bb28b10d847d0a4fe1111be2b7fec6b5294902775128288a784203031ea853c9c104c75571d19552e2a1359a900c5fc9455230968a5920f2ab23f5b9cc49739d4e4ae2c01c7812ff295899b954e9729a3bb330b60c51a8a7759e5131d7d4cf261fa1e62c29f91b4341a4fc968e7f30ca2261702eb328d628b7275a9efc29b50bcb9b27e5844328d5e8256c76949d30b6fea0d5a1c9abca80d3251fcf4ec4db0a5ff2ffd43618aa2e3e1694c2a3c579a2665f443ffb1eb0ce33c09d7285687cd55b6ca9918553bfb36a44860e09ffa0604ef4904a034108370195a986fe165c598305eb08599abbb3df31b1d93162397056d9ba5a1ac2812c582aa356310fafb4058abc5f157802e4a9b4bddb16e75b6db105b7dbc838f820539b76949b1648909104efa67ce28b16a738f1be104d2bd142d3ad1b1c953b6020a1f4cbb84d5c49424befbf2e6ac5c593b783a3f4af75477312528fa78dffd82fe493d821e011642bf1135a5be91fef909383953308dcb61b2f35c2ad259acd1a2e953c0ea6a03a97b384e39c94c33d3846c26b4f9f116abe572d5b7cb81886d6adc2d544630fdc1684bfb32972e051b9a2bd0931de63e025813b923944290fe1ebd5264ee4f25569a2088314e8d4ce8b91c7bd602b9d85acc917d60d30d5ef1cbb055b9ff7b0f999b98caea2517d2de334eb436078c90d41e0e34f11b93e3e643389f43b3afdc4f47a7396cbe0b4bf159ff27618cb835aac6699be1fc7ec840b767836a165fb95d06f2cac4fe15b65714ddb8a095ed4a5b57e63d536405931b6c168683763fe07c32aa4130bff787d4d440746a2dbfc584a502d809076b257482abf7f8ead7741c82b54c41acd41581148aeb4149b0c6eeb39ef7ba091c2e8bc72583b2fdf8ce7fad1bc05aefd6db0360c644a9760a9729a88ee4b2ab123d7238c12435b9f3b4660e74c0fd4a9b00aa614453d84fea01f779e5a924f8e79630a8bb6561ae19c7bc8d88b9d823b98285fdd65d4cc05e443944ed5d3cd4f46c7cafd1dd5deaa519772dd24f508bd2d588a832d5689119a2d506ff11dbf37d57a24e35ff38da18af07eaff5775d12dfe795fd3e1f0ec83c5f283d6cd76532519a15a18d93431893b1b88929159bf8fd21f62b30f4e37d540baab0e30ff3349a08d627ac19303fcae8b8e3fe44eceb66d30697c7ea051bf5afdcd8bfc00d49c8d36164ec9194a78a4d8b78826863e93b6a810354861f4a35ec12e5ac102f74e390d9c0227e67acbbe3254e5b892786e3a88a383ea9726485854a319569a678fa70392cee90c9aa83eee8df6800565bb8e083e78a064c0f8b863120efd799ea57d3073663c0d0e7bfb9b717ca1d6372fdf75a77fd9677791cb899fc8033d6d806de1e6aaeef525ea909666316d9d604c1207cbeb6f427c3acc1b02cf59704fc65135703f2a9529bb2c8fec992c4de53e54b029c3f2a5fdbec1008d1a70dce0c11251003ce62af712b9e4abe631902485404e4933f346f1b4467fceb65baf776d0078aae6a2a1f95b85a441b635663c75b485a8a7cb9a5c12192ac874d940e2d9b88cc05a2db9b5b35df769925da508112ab0b8f64a1408633fd0d81810baf2c846b222736bd826c8cf905b2c35633d6013f5565e0a5ec1492e99613f53530799052a0d70023339d1c394fdf9f73a590a2faf68390d2a823bc3e47a173782b03dacbdadaef1e67fb47a7cad71b6067ce5b5e41fc20ea1fed28578e9bdfa99faa657a754488ed3fc084faa7a05b0f6eb66da0a28e9ab26bb319fa4ee993de840948f94dc1d68d926b783a0bd3396a89970b2c2595de8148e87b87c21f664618af4f567115d403715c3d7d2f66d7a90de2c5237893a4c18c20494e3faf94485ed39ecfe972c36acef0d7ee57bf8755924c790ad02dcc5c4e15aa7db53eb6040244c3ebb7874676782e54dfdddc256018ae6af8cc37450a4cef77f21e2e061062ca0c2a514290c960f5993ec1ce9eea6d09d3293118237e079b6015b966361c3032368174d74ae5cce4148ea2b3690fbd3c28ee544c5c5bd7bc618122979d52c9d3d44eab1f2467f338e695ec5f95998bbe77dffac42bc2809d43a324e0f5feb4ca3d5fd951b7dc8a9e6276ee080079b68849b14c7573cd02c76027a856165d1043acf99554c62fe32896d120974ae71f84986bfa0c28fcc399246bef3ab90f8e55f913aabf339dd7ca6f0861a9ef712e77dd28740615479f39a37e746c7df2b267066d1649fafe0459f665f3d5e7124db43ab1ba5ff94989acc7fe0935e0bbacf718b33103a1355d97ab416d8263ab369e6cf0ee563a77f2f265fc3856b7d54dc0887ed439a421c14f733ec1d6da086536f9539d23cb8026218c5e783423b5f4ac24c8d5d8faa7186dd5ea34afe299e6dbed73ffa8f415da706442a48808a9342d6209f65ca11eba76f8ef26db890da76671971f65bce9e6112c8aa92523dd5295d748e28857acff408c161c0513b37b855a8afb0764d118815bb1b68f8f09156641f7eea994ddea20f4062607b9919d041c880b71592402a4d5b92464b239caf431a99dc67787e76b8e1d7337af004bcb88473cd16b3f7640e8aaa59ad4609f060a2cdc71a4b3ed22c1506a7050a63bd8ed68aa58a8109980bb3f2b9f9fba9599d7620b8c25e8aee739095789af83529cfbfce5941d7f14c8ae30583deafdc7c25fc34e75bbed6ce4f6b47e9647c12333ce08c7db77dc94161cfc43f7ea0bba39def8bf8ae61c6fdcc0de6308af963c6d9ef43916d0cd2cedb970d5937c9fdd4b888cc66e99363b5a04ae62a4349f01c3933ada64080741b1781754e4a722303faef69e382cd9823177e4d5ac83e76017124a7b1a41bcdbb9c4209e7b42c", "eaae1c53919e2029c137a80f91704d0871be2c1870d0333d8bcf7f94", "4c434cddb399e52457113cc7e16f046c3f8301f5b6c296979f8a091a9ea557ea", "b633c1a0e1ddf4727b149b3d", "f1de487001a580cee6edadb1ef6b700c861a70c6ef16274447b8c61bb10d2d1efbf104d5f7d7172c6a5cf9c06d886165a2919ee9418e2e8f803d47832dae5ef232ee300d1f973a6298c22d777a1b16264353cc731a7a683cfe31e0abc704460788c555c0c24f281b81d7761235a955c736f17f213a896b40a034609ca8456ec3cf5906d01121b7580ce19d89347b6a59c81add318df487b2442a7a8b5e30df78467abbf46bcd5ee5b994a39ca5bd8846caba6f02f4f1335b73d4e20be0b6ad85966f86d1bb857713ebf947ae936782f1f4929498bbd66bdd5ad6fa252364a5a6b46180e93b54cc321b3cf63cf23d55392475c6b8c8c9dc707924b55544151c7c55ae0bf391f793e52bed70829fcd32b2926600f65be0943d6a9a96547675426b0dca9cc7b0f5dbc9d5439d0281014c6c159d055d6bd89d67828ba7fd2a0570ba82996037f7dcce297fe6518331270f6fd5ee63d406cc5081472bc5f2298a9208dba9398ccf807ce9af982885897715b3c5742456f756d79c70434a9baf7b4b6664c9d9f5696c5256b74099e593f97a2d4a469cb3430d0c3eb06083398cabd58af598945a85c9235a3fdd9ba7686e54d0de9afb594b1bb030be8e6bb839f6b45699dbcd2f771db64b0c62bbf6c8672fb412d60c00b3d87f82ffff6512e8308877573323c5a2d6a216ce3e2ce07c9763835ae59d44d7958fd873e3995b62b1b347e489ce86e023ae27a6cb03ddec27a38fb233499a714acd89232a91d38abce30299f38f437f7a46df647f2be862c1e7bcc1e4263c2147b13ee5b345b7fcb973f3ac71db8bc12309f67ddb62659bd73fbd20664eadcd23a79233386aeec1a6fcc8c592053954ee53826cb9b6bba22400648887311cdfa5414c96d5956fe193a3729be1434d923a3f9849f6c419f77ea05fb72f3c4f75ccec03b7f7aef8c8e55c8c5480ee505ae1a7594e6a911dfbc39dbb0ae8656f5972eb644c64203a920fe0078f3d050cc5666ed9747c23df7853d6913005d0156e741a5ead3bb1b22e5bd802c303a73a961f0b60d0fa698041c22577b44eba5d6071de4b545d9f5de24944c151de6a189bfdc223e0507c74ff929f06a2e7497e8c63073294b4aba110a006a6e9510a9617405d9ee711831e085940006761822672549d1d1c70e50002c2227f6f304b9a7f11dc05751be2dfd297087044d2e20ecfa0c091478d62c1bf5f0aacd25bb0384853762a51144b77d30418b633c4c10a6eda7b2eac46905641da0b685f85349749a91cdbaa4027fc50eb97a7dea9e8cbb5b5f386ace0363803ba579cd16ef80dc40ba1044b4ecd0e81e382635d7855e2341b18e0ca705ff46990282fe25093a248ca04a1fff64ebee25065350ea4b9e5990da4dd2e28688ab08b6d6fcb54d70f6d74fd7e5e05d21c12f5b140839aa966aea9ee094a923ee5ec704b5b709ff009c20ed89a75468c48b505d07c7a5ba1ad54ed610886c9d84468eaa598c71b017578404c909dbca431703e0cb1cfb975a696a1677bc015a75db007eccdcb21b9e5e119c48f148c2cffcf29e245e52156ba5ba0a8b0031570e4cbe7b3ac4646353594f0c4a9424c9d97845c5e1a4b4016df9be8df3013e5269484cf32258849afbdd733189ea11783f0f64d3aba9b4f48818011e868cc03ecaa44ff0ab83ed12981a6df445294ff672f3a16d6e0d19b90007d4646e967e0fb1763b3c879f548e1103a75c94f3a7f72be78555eafc086c1c58d1761aac60b843704f234c55b951a1303a12705f2120f784c2bc1494432a94c835d908f0edd5cbb169afd2d38087ca5bc5e5df9c3bd970dd2da4fb2a00933538148ebf669a20b5beef0402e53dbfc3a0f289b33b41ca27eb2f036a22f0d02e0617bd01e8c74be264515c9b46b9ab6fc67403a35837844580794088a9d3c14ad9309435daa0396f48017be524856ab6c191350529962ead64bab33171a01bb3c144b23bed406cb05102c693ce5df36eb541c47e871acf56f2b47de687eb9b3511ae83d06b1f69fbcef3225c3469c304741437fcd0ff4ae3484c117f51d24b6ae1363beb7d85d9b61e01e3dee901b90f2d3272eedb384ddb4d3b9594b9c0926595e500f8ce2e5cd407bd7a4e2c8e6f4315bf693e8c961ba5b8a6c7f5030c68a6b995e9d3f9eaee9eebc9d679eaf72a5f1cb6b2fc66edc7dffa2370dd778ea7ff446121999afba7bb35ceabf626c6269bc466d65f7f812c663bcb2fd87d3e09ab7d71e727f66d20ec48a5d2bf0aaf0aca05d1546d6e974f90df85c1393e3d45731f71ec7b5cb6cfb4e5c29976ead6944a99df2045056e198b19905362d4e9b765adb65eb089233a8b3777352665489c9456cceed593c6590d9f3cc4024d0bb92e1a0dc619bf8ae65be77456c18f8171e4d2d846073cf5c57ba93adbc0db9799e3d98934aa6899372acfa4d7d2ea32e20164b79c71d7bd33c94f9a781a25cbcafe563462eeacaec0e8d9d6c0199de85558a3a05d1ee3483351915d8a4e65ca0ab129a2386a9e26aff9b912c588babbcf25f8c467145061b9b8fbbff19d8c6ded8527d457be7c926c8f490bbcd627b3002044b7729a52e94147f95772591616f6074047e758597f410b3100f9efafaa4137dedfd0edfa85b0927804f0b4fcea1a174622116222004d42b36c2c73d04781f2f49d080f351e57154a3980005bcfb0ea34288e2fafec5bfd01e1f7901b3efc71ae58bf8df4cd7c045856103b77bd78073f0174aaaef4a3c0e8b5b46dc92db55478f012dc1b7d513e215e735573257f105d2390b5366f49b61809033c13ed4e1ebe19ab89313c947f2585f0788a0c5de90b41ad0dbbfc604a0d414d0e5390a0f3c9616cfce4097e38e05888b8bc6e55e40368bacdba7e5b76f4bd8fe619746155c30b38807a1ad325b00ecc3dbcf23014e79f1c39af7cdd0dc7ea58ce733e6611b7eae069deb047aeadfc21960e614db19d2e7e0905a9873268b9a24f856c28059321a742cd6cb3d1527", }, { "c89c3cadc094bffd5ba06c600dabe30ea19ad037316fc13b895fe0e14ac8841264c1bf25557e22b01f8e102c3af43adb8e0a12bf79d3fa0232dae37ca3688e07294e2c7ecc4e2eebdd3f17173351f2c15b0480d4d77bd70955ba86f82214004b622cc92f7bf81a5837326f6a83612bdf65abb33c268a457c45cb7467e074b342a17c711c748c74abbee31541444020a9ecd4e5125e2a8ea3f6030bd677be18183a8a34af16a85ad48b7015cfb036789c0a5daf68883d0c7e401754b8d56cd00ff605be0cad19e03989f608392c81d636de859e66c2aae403c138bb96a58ba69b9064a83e7d8877067e7f40aa0016e0df9b7f455d292a60eb621b8107a727a3378c4b7509d3ec10526c50fc6c66dd4b015c915e85bbbf701ddaf2258119c8b9a5132eafe61bbf38870f35f375123f766ed0d4f38b9364a86e56cdef6f95a815a8d7c48ff283c77992fc6c070eab7d7c7b517006e5d4af532a7c429912ebaebac27249b4f5112d870d998e1c450b98c05d08c742dc769506f2d7a004c24ebf84c10838b619653e27ffcc4344d8db0435e4cb77c0410cc734e36738a6b5f72a7600632d19c86b40c737830b0f5f104443dbbb031dc7ca51ab318951e7817b5d81de8a9aa7f5db6e2d5e7a3cbd8a8100653c048204ced3af005d00e7de7b445f5acff901c4d46ff133e92ef073aff1d9ebf55befc32f9ec38c9eaa6a1aefc974bec2758297e474cacea2ba4151ab1a3ca0762c64a5ca273169d29b83c164f77f266c01bd5075871e17426068ed7aa58ef0d1f2959b19c604eb6187acc57e2becea2da93ba23159ba73b9226034c7ee2498e0ba34fa8038e5e2c092a73ebd9329ea3d648d6ebd47e1776941ab3130cfc91089fd0a0a36f0ecf68293343f275d2a64c1b7d27ffeb3f667f4a19824706235fa5f3f04952ff08bb183c0f1aa1d1b0edfd2e05ed093543788f5d0ac6532e15f912163275053b202d772f381900e906fe070cdb00421e78c16b7387be91adb7b3b3ea28b92548d69c780ea578e7ac66eeb931eefb4067bcabdb345a7cd2022085fc494f118215adfa2443630bffc9faa8fbd9943c3140d81c7532895734a9dd20e31c326531d06f5623c252139c4cbc882640c457819c63f6ceed4e03872b246a3766df69373ebf5af1116e8d5e1b15745bd9dbdd663fd4352d1238a43d5d1e74b3edddfb1c9d460daeb49afccfa0712b7a4cf8d07ccd0599ef3e4e1c9b5c814f3a6f3a46fc80449b34df87f47ff91fea3618cab2d5c04cb50e8ad199d752d901b21348ae939d39c86cc1bcecbadcc6f0e581a3bb51e070507b41ea4294b35456c69cf55a2a3f1296f0df73abac3a9c81cc303d1e20ad6e9bef48de83fc22dac2cfc01ce9ff3f70e00ee49bab2f282ceb6859f989075814e690e36a8d16354fd6056cbff49c30e49b1570363498531ff0ad0979a4518e9ae271f57f883abf5e301c0e24a83f09335479698911bca90269a28c0e040a98e67c9e55f4c91542f921511dd980270cd490766da22306b48ca9309aad3b2393b7b1e9ac7afeff64204081f9c0a8f6a5396d02eb9009901ca2c0a75ffbdae3a38ccd5007cc4f6bec8fedd64086cce5c039e8abc9e23bd694fc8de4e858c89bd585ebdd422b492eab26f4ebbdc1d17dfbba19b5ac458c31320a161a52dea638548205a6ad4ec54875ca34238c059177bfab2d5be0a98d12b3932d0661d33ec655446d0283224af8ec7f1c6874add03448fd8029a71d3c5aa06951123c9fd881d435845757df50444e6cacc31a8cf7537a778d1184b96c3512cd474f5d1fd1214555789d24c8d173358e36400b2d937595109729d9f35eecb0963c0da60d2eeb52a778876059fa95d820d5d34e7948d389dffd53d34c4083d27c917879b053cc57dc43c8263e5dfe5f33c19dad0a7126ea6e8abdbacb318d37c305a183596ddb25b1934beff13a4f24fbdcc2064de8e0bc639e672ecfe45692e9f8164365e1691784b4f775ef369aeb135ce15135c20da95064c810592ea33316b9767caaef842f948b9573b2205ec57d3026a2f2244c42991462e233061549cf9bc66a7b4a8a0fc61f73883fd24dad02644004989c4721a0aa03d3b0191d7fa4d3da102e541fe463936c9365ba30681e706ca70cb3c8ad5dcc710de59e7d8a6247aa809bba74ff4dd182a38bb31baa337841302c19ed89d65e87bbed05465f4ce0dfe89b44d7e9266a8ca21d984c41109d813ca76eb67dbd4e39aa437ff98050c968ec1e40c534ab51d6b8ea2309fab08b3757e9edc5972bff316f6f2affbff458ac0299613734b30dfdad20f797d172cf295cbcfee3d8ee25485d40380d3480a9372a1a6e5ecd7c4c6a9d34027ea6c197f37e86e757750c9fc24cc7cf814878b8628326c140930dbb2041bd9ee87f36ebfdbdc34522cfd4e50c9cb48dd52d4647a06d08e0f0069c104849bf30c8e61cb693dffbc69fc0ab9c5d502a227d606a1dcd630ebd799acdb1e47ce2ad52ff53f6cf4fbd5f0058fb5db915702675ea44334d42e0b6ddae78b22b5b5f7e5aa36519e31278e37b64312479b14aef9b8f12d8c1f39faf920851bd53b13bae5490c847b3312b2e956c430f1d8deea91cf171dee5017e7709d0346d81600bd5f0c41da3f548c28aa50589b293685ba059cd7f3edefdb5d8cdea364f4a42153b0632ef0b7ba18610b71fc34a781eead1dc5a00ab47b6840590ba44dafc6a16029cf50e089684194d93dc881beb62edb7ccee6304a4e71a35915f109db92690461b9e4ea21257ffb62477c20feaafc7a78e2aac2301b66893157920ce9fb114ab4f534d61bb3d17dfb4d9ef9f79a736f7c1d32ac3998356aefc876d8c38722787d564e980a1f15056cb3fe634d71d2c98e0475c79cab318b73a863362f85aeacdcfc44e61b5aeb870de9ea5b5abd24e8c19ab05e45e1e9b8894deeb9d29d65ae99aa94b5047f3c1168276cc2e491aba52b5b03703ced28c63a167f0cb3e4bb4d8e4f0292cf3ea4376510fa49a1a5efcc00f23c3cdf6402197b81262e66e17bf4307d87ffbc2b37213b316bddd65aa9d64ce6122c4a1545c5966bf4fc4c6ff17ded787ca9a3b3cadee435bbba8f6590dc4ba30895b84d5b4eb94f4b05be3c", "82abb4ff5457b21f359754f151e456e2c0a185c8363d15918bcee0d6d49f12564ac655", "b63b577e719494032062e3f63682098dcdcfe26cedea2a40893c847a331e4ce9", "9f1d08be539f1244f0f69ad2", "88dcdb0309f8c4a96ad5560f8210eda1f5afb31b85b7a8b15525777748967d4ed77c063f65d64ef19b31044f2adc690f5e457faa1abe2e127b38c626eaa94053c9ae1b6b4d0db1f02c8404b50f58210cc9fcc6fa4ecc615631da631031cd6253b4a13a3e88295ffdc775fd4bdf29655d9780dbe02b0a82aad4c4088e90b51f170909c0f98ff93ca3926067ec94be05841603db4f913b7025a9ee34b8d8bc629ed827a2a9857e0814d36b83cba21e670f8f94ceb4be5757e0b8782895b5d8605868e4f584b5bb6a5f3a94edd9b23fc2b6fa06914aec970c260fc370aa245ca68888c90c43eecb68474c9e45c53a7da055f5bfe39b56769fa56264dc8bf4c1616e30262bd501ff9fc5cd78f73ad89e093feba0393a11c6b2cbca765ba025c40dd0417dfa644fce96db5a0362235ad37a317145e7b5f3c7213c7fb3c393be57a1cb55035f06da1f0bf665653c5fe8a0f3ca67dbcbfc59852694d34819d0978cd09b508d103017168f6848258493be737cc24c2112f2afeabf41038bea1f74bc8656d9910b77d33cc691a0d9b12f7c518ecef93423cb4871949a518d2f06e5427823324275b97110f8f88b0d14788741e617f4b194e679a1627da50376a08d4f23b005c0446b46d4f534ed85e4692e7946ec818437089425ee30e47de995e8774b61003801de67939d9fed7bf0cdaf625798d0d0d04a61a2482217b890168e36f20cf1d6b81f9daf1a49a781567c4363ac2f3ebf0252d5adfbed17f98cc264ed2765aa279b7437410ee8b4cf42932e5055f4884deefd2a979ab1328f97cb750b3b7e4615b9c1c61659c90a5ff6d1c736e785587ec85040fb2c6decf789c2707974bfcbd0c7f699627b31e0762321d55bcc6acf1aabbd44abd7766d397bfbb68c424b311611d9eeb6598ca3126f569f688455da8d5ab86eb01f9c96186858c4b5e447aa2b9ca11aa5453f731beed4e09f95bb7376e200212e2f03551b8b09a19d6910f25898d692bc20bf6ed3ac9a0276db560de5c9e264f4db8fec6577042fbbd4510bb7070086508ac451a1fda26582c259412fbf1bd60cd5e921160c2604fde559b5ed4df52b805010b225f999450adadc6e108b70f169a3d8da6efbe1cce1c4908b004e928e3cdfdd0b4c5f742fd72a11c9585aa3517486201b6d9a98739b77970a88072750d29d005a291546f13b576b4249d71f04a9abf8f653ca206d98f738af2a1203bf0975f0a40138df054ee834ab73a3b1d7036567369a7ae15f808904e08adfc84b34a0e1356009d8a82e51c3e8f2170908179bfe47be8ad819cb12e85b6b76bba7c9b9398dfc00f550e32c171b4d5f2d9676063efee0b0b49660c10260ce052dd00addc3359e35c25dc33066d4b05bec7d93f71e0ad7d5ab83d844c7f33137894327f464260688ea4ce9847046e7dd0bfa48d4e15277a9586b4742daf0c5ecc59aceea6867068b03c20aad38d04a814472287d809a9285cd4dcdbf68f3f4ffb794701f4c265b2dff4aee55c9815938689162e08309df150538e60dccc03d495adcc560fb831444b922a6375845cef5dec56eff2910b5bde5f25f0e550ab5a13205de91d20896fe04a8ecc2c83d1371cf381424f8c43d2a5ced374878405f52bb92f4fa3c15d29ec151508488f9b4e42527921e245a8ee4b5d6ee95797f6ec4374d79acd7b467454a1d7eda05a8ae104534b23c46b27581abed6afc3ca555202dda94fc2b93501fe78867730a84f6f726dfd7364bc240b65d6c3022a04e09c89e36a809fbf244cc5522315110e9e33c8a4e1f1396e3e51fcdd53d9ae94fe7bf6c6ccef0ce02048a11441de3c25aa9787c577501977e486f8dfaa4c81e3183e648311148ce5cf3de56878847a9d14c0645777022c158670377dd9553eb63eb17e19ebb06202be8fd9bc2b24878cc86f9938e5996751ad9ca04b636497199f7f27dfa0f5ba2a01c3a491bec6dc5113d127f6aae38fa07ce7539a0c1817f7f0de0da538f4d85ffa394784a42eb50994e28530e3997e3345db28bafbb836fa463d34146d9f46d8d2b28b3954b9bc7f84046828e9b55e2fd663e562aa95caa97873f48f0a003d2251fb3ddbce0b6072fc17e0d3f99b655b8f41e8e6986ef7526544222e2d402489eabed4c219540605b9f5dd321ad902708601e85bc874c11efedd072aab7e10272c87b08b9457223de9fbc3abc2d1346656a524e9c67d79d4053c4257e886d6b430f5b7f57b2e5e92ae69273c1705a3074d5066def69fadea1af8fa9b3bf4890f9cda4b1833e5ed27f22bc4fe4cf452880c7b53320bc7cb748c0af6e7550ffa84e4714ec18d208131ae9e3edc6cd6fa2c60ab8ebc1ee56eafc01fbfba061e55014b9711eb58fdd01f8936d29dd081565de0b175b02989c5ff374e6f58c3383e9bc00d8a93903e6a221c7475e15aaef77594849af877f3807a76e03bdd54ff0b192bf34385d24d858d6f454810ee48141d73e3acf1aa3d19cd4c723a634cd8e25b4fb604c744e408dfd82961e46e8444f001d0991af24b3b6ec57ba41fb45122afc73ec6b25f501f1abd46181247945729337bf5083e5821968502a5a696043ee696c290095feac000957f968ac61ccb572ab2f37008830ab9a81d02456190af99873450b52df1888c3d8b6b13df65a9bb36a4b6d0538a0f179daebca2bed6f94b4670560fc5471c3770f2d004b6a138b8243068d754fd246e9881242638c6675f1611f237146f6e0f72ff2fba96f479fe0a662a81f40928f5400a0bbfb5ed07a87f457d5febdbdd6f323e2a59f749e6fc8a51d08b023734c762a91cc517401be57ffdf6a52b9174ea153abf2190ae2642955c3c02b4a15d72456c9d2f323de6fabbf56dfa3b566f1aa688c86b662bd34cf2511cc4a30621b6f1f1ac382bc1c4fa4c0d4d5a30ae90a5e54a9fb4afc1475e7c612eeb7f0e09e894c2004cd04126df9359d525d7f090e4b531916207c38c3512341c84218c86fc50061043ba1b89ddfb21cd756b391cb53e8c1cd55352be05efe562669e3986c022e30c79a97bdf087889a392e6da0d72cc7ea208aaf23408df23f3a9ea9bf9a935e49c9994a37a5dd0faf1267d5f7db47cf64ae1d3ec166466b2f882eb21698aa375cb50146c0e660e9bbb38d7bbc1c1c6d8333f7031d6a", }, { "68ca38fccd585eb14f953358220027046c14ef965478d3d8f206f63fef4fe3571a1b53e774b298c347cc1b69cc426d39575ccfabd5a284c7a87a0698cae9efe40543cb79f5643c3c3057a5fc991235f06f059c44a7200b509a12e864fbd748001a14790f78b54ba80cf0a4a603da9672df32b68652c1d6edd3be51cf969acfb0ae49c026fe0bce0bfc72b1ff4c47712b7a27b2cce888b9bc470b8bdda55a8d53a34d79a25947ad55b95e5406a5c5311fece3ecd46ca590b3b01b9055761da8196b21bbc468681922c66d286c32598b1e3d77f2a91d835ccd9eec231409cb2e74ede9385552517718be9f84f0f9100e368701dfa4843b7222279537306065a54d4edda3a02f1ab9edba3ddeb34dece9d5edc8797103eb942a80cb5ae130ff2e7eddd11f0cecd8f9a615d75963c44238b10ab1230d9db7371d8291feb2912d306efe4f7aea2773903d4be9a00f2bd8c03589e342269a79441c0b42ce9c6fff0a6e4e845876f7e9b342d25351fe2b1233b4f576db90ef1facfa617b96d17aa03fc824973e1c80f15e5344b0516fc28424b7faff47ea1ef4e47f6f7b50e91b8fb14027f05ca7e1bafa266a4b952cd0b9e4cab82bb4d61f99568e14a6772f36296f5d19cb04fa86ff20f04ab61d1a6f01e5282c99fe4c3254da46fb5276317be58e94b1928e3791af27dc6544f6d445dbfc7275fbbea74f98ee4aea647b654909f9fa9c88312d3759099c9d0070e3db6d55506813f8b7abe602964a7dfb9387f58e237dbf50b4185a50b65ac099352dee8695017e4dac644f42aecc3e415333cf76b08fc764a721b45d7b74f6b0a2e43637e5b4849218d3d4c6a01208f345d76af56631590e520d6bcd82627d2446b45b2c68e0be81b3924753a54f47ea27b1e08de2399b34470701c9697eedaf3248db9b28991cdc2c632fd1b376bbda279b6709d5033d1c0a3ee573bdd222ef1afe8a4397a61fc30a4e94bdc55097ecebfef6c00133dc0b72c17e2f93a11eae9fa9f1364f10fa595e8e1623dead10caac068aad3967b9ab2837dabcd8f96a77a25baef16ba84bc93661ed150ffddfbb0369683cd021e8f959c2b531bb1fa95d7a574fe5ff9aae35fb9b4a0a9829c59b932ed8634fc05ca88211da3e30839baadaea8fd9843e0e80d9598a7282500d157ee579cda5d57628e7506617d301c2adec5186708f94f069ed7bdb70cbe88549cefe1673d48c9bbbdc01d2af03945cefe6e25f757750de64cbb9d496a25adf7058f5e32c827fe75e80ba0e834e6a72344dd2aac4228828ed42fd83e4576254af5737dcd9b6c338377d46baccb02d00fdffaac12133ea0e75e791593ef3aded4ae4c9249b8d5cd20aa28cd652b9d750b88111d9b4fbe729e27882206b2f0eb614d7daaf6436816fd80d452ac71c7a7f9e8c595287407c6ab9fe8a242e98da4270b4f1d4ea7243c27f89ed46a567c643f31f967b5f12e518106f3d3e08178078cc714cb6e39079631966a9becd6f02c18e983ceeaa2106ba9043f9985b791027eb5dddceed563106bcdbc48a4ac64bd95e87c708a8cdc33811bcd16c35e193203e70ef2bc7203183fbf60d46bc581f1bdfe62387b3e6c0c4a29130d872c3f8b134e7dcfb080e7e03048c49c0e468dbc44eff4b02e50bc6889cf7600fba58c0ee409ce948aa684baef4956fd8fd4a9c4c49e84e2ff314b7900b179fc66f5fb4affb9ef7a6064354fad8c3d2d50e6f2157576f864a843dda8f547955c4d80a73d4a86b7aaeaecea886927a5ba0e97df740ec7e8b70bb650010df55d4b75f478b07b205b560d45de666d84206c1bffd02ab7b8d1c37f21c47d1711b89d16214d8151a8e75eeeb5c54c39e5a855d578708d314240a064051d8b26c6183ce755be38fe9597dd5b5d198532b1db083a4b856b8dd60bf1db197cf1df852eb6daecffd97287a6cdd4c05307722e0fac798507f75b03e9361d5627ecdb56a3b633938fa61b2673efe6c6e768e4e7055e6c1d55c7113efd3e95151b606bbf169f4296455dccb93da370150c54fc11b3682f092f30381c6ecd218a3d9d39442c8bea61d9a71b174a8b2c56e028689380879cafb7c4bc2691dda0cf6ada039755edf93f851446df9f63267f8b8f030c069fabbe6457d4f63575b5905fb927a5a720d52c351bfbc48f12440a91471697e6b2564b1a2b314fa0e6dff090079637287b635d875f120671561102ad27aa83d9f0cee41bf023bcd703ad670b43ae23bf01713650834cc1e95dd486757f0a4f6fc9337bb95738805ad5e756198579c886eb0ee77e4ba957997dde0eecd84e4c9171c84ad8f0cb23c6a289e037f3a8beeea7965ce34fa47cbd727baa4ac9e6dc3baf17049fd2386674b246aca5ef6b8496f1d17a3175f6fee86299232c7fff682f066cbed895155d475bf9fd4b5571d257534c88c93377b1a600d4c280d42aafda975eb32c740073cffa610b5fd2dda7262a2fff5da7a0f3a875c62949e0c9247827d7a49bd8185bc27967124c34b9725ee961bc8102a029786652c2571be6cf33be63cf867c2b48e5826b31b714a415fe05c27f0862a870d8fb33200719ef4ac8530a4ecf2597b4a7f2e66f078a7505803774889a1cf963083c831f46725a1ec5545d8489e53921d81f80ef99f5e51a2d5992c7769c2a7ec8bd8e0f2fd81de53c7b69b650a2d838b269185c5efd668c470943bd956e3c5e1bba5d3b927b10cee68a75372d4d6fdfa6782c05659281bc9bc56a2123967f4f50cc7ae3379ba21e1617553354b5030b3d3f0092c1824f5d47b97e6b4fedaa90aa2573e1b115ffc72d44fa8209fd8d372c8dc9ee00193b47c2a9a302875da331731713243d02eb5a57d5dc51c35988ffd742ddd75c191f1eb2c2214a1fc47b82db8ea708818262d9583f2b1b98a40b6ff6e94742f25661a51882ef28475aab12d9422b6ac48e341cbd6f38460333b5fa1cfd4d0f43aeb46c21938468fe3f7bc771972246156652d2c58b18c8cecec2dbbc0feb0fae9f6bc022e029111f94e8913c0ad741612a1426b53cff73fbb24fb7b22ab750ba1310ecf339fe12ced6a3fae17b4c429550794a8d68be891b0e30cd28e81de2fb2ecfee58bdf11794951276005eb8a5af21e03c8aaeb595ace652c5ce60a8b98f6897d82698ffbb2e02213e50d9d3f00bb42c8652d22bffb87ec576ef6e206ed6c846fd5136a87f38c9ad899371799f35a6258878418830b04da79fabd80e7290456fe17c0850a4c20e2e657f97f4a53e1a3db65bb5e71bf38eab9f56aa11e6ef71c85b8a28f04c271", "ea196b6a64be4b0799b1c2f72281300c3a2577db44e5d3606b8b02fa8fc46c7aded7e442", "7c86a2c06b7520d60023d18fe73d09c514ed07a91d50d8fd5bff00e7550faed1", "952f492fe00b26028c560fc6", "b3f3294815ce461c8843172efe93f73a8254e58a0e71953e35c15aa89a7bd9dfee967853dcbfba73d3b87fa60449cbcabf13b1206d0cb27d2c3fedcfa695b6d41efda37bb6db35449bd470a23787619ee48f981d3f0b1c8e121725b2289b6d67858a4f9ab41683bdaec8a913ca2cc292a9640efe50fb85a1d1f7b286f45d4448f85b3242f45ab44e3281d759db24dfabbae4259f127d6546ecb914d7e93e2c19230c67fba8a6cba6069023ff7ea3d8a170289c2b4391bb97a7b899228d032b36186dfbb29ae8f0e6c06d753f4c6b21982d49ee682bef50a5c2c8434510c5fa2b9c0349592f33f8d7ad6f7243d42b292aee6d210c61e3f898875b91a17a89148275031b74cb34e628d7b701775dbfcf87c79ab279a73dad14d8eed365eb9f29a007b7d2ccc07ceb8cdcdaece67fa0166e135c9a4b939426882eeca98ab887ed2e4888bbebd5afc9f2da3e9162527262b0fa85903246bc8b80df3060c890ebaa516781a2b2a138b98001287e12a9c68471912dd297bc0beadccdc31a27b7c726baf31510cd355a28e4ef786b30084af66ef135909795aa73814cbbc6552270d5e11d46e9497ba30d6d8cecf343d16e7e3357bc9bbfbc7c1dcaa5fafd8a9b07056129da02e6228886463474c5af1d670bc14cf2868b816cc71578ad807a37477341c8192bfc2e8b1f7bfd58827e041f70384f92bb4c6acc415dde5099a1c2b27b709f9e53d1dab07c87a042ca4af7a2a6ee57b37bf2bb42259d372ecfeaf1dc55ac3a9f211f16fef3b2d5f11dc19fd1f425c14779580b2501ec6e0a84220e7e12baf9e0fee3e8cf499a7fba6721a746f598f04ee8ab4df31fb8fa5ce2d2419d5551155c009f2780cdd225ec2c19f94fb9c8b785ad4574b4da766eabfa696a1994e64a2518d1bcade6390cc683a6e80cf8b163c3e58cfa1134ee743079347f08a89c81478668df32ce9cdd7b853db5cf7af13436f3bbb11bcfa8f6b6d727a1df84f99fb3a5c248b8fd5baf669b68fd9af45298030f3251bf0351fa9b58b0b9fba53ecfd838300790ebd689744c1b7b333fbed76c8fb96fc669ecc6695ff5bf8379dd2a3c270af858cc60894be8922d69fb9707bd2a7825f2eec4a5056e5e91714f4dcfa86974259fcbfd5f20d55923a0a9936fb20e5ae9670e2019336e15f530c0be449fe355a7a02c0938d60720d5b8f4f59d2e4213ad5251c6058312b43d47c44ffc8946a98797f5ace279d3e126da63633c0eff1c412febdd47817aaee466c639e43637c1e179f606780ab490d3f0b3c2d79709f1262305fc87c02f68da2dc32f8c544e7b358c3a5d2c27986a19d13fe736c60a3524e94caa55e853eedeece985d16bfa6c487bed6583436cf82077fcdcf90a05f49db50588f46550f7a0c3a1cfca902d66d25dba8d2c53bb5557cc1d87c8a407898b3c30c4f0852df92d839859c191228d0a47324ea9ec2e0ae84513cbe4ff4aff85e77b8587f1044bcb9775099ebc2f28fbcd1cad58a8ce1f072f2228f559fbfdd8405d86f8262c27c3d95e01016b343c6a4e59dec81b59bb6e3c6109a4cffffa85e9752ed2149b5624417c0dfd1a27bd2630bf59814f15820c43bfa317be59ef6f433c95e8be154a8ae94765bcedadebb717f0d8c24e01e1952bd104ba9620f067554ae0faeb78f13c622c45d97b2b5774a3e30cb07f2cf0e8b19d1266d8a8861f3772305e24ec5c9cb714806c7d705a3bed6385f8be4e12562e17ec3df01afb4ef6f7427c48a1bc0e64fc65eb1c3d3ff2d6687e4c275a019f5ab5c63bbe47e3680fb1802d5835c4d494f0f394de1ae47f81eef005127d0971c4589c456ae6a69855f35635c28b590c1b93f155fabcab59b6c7cd8ea1c4ed1f67093aa782c54329cdcf9bf84a40400de707b894587d6e08cf7fd72fa45b6709a26e97ff5ec1269b8042358f872a79e8c2db1c7ebffac014d6b6f71b0c1c1945ddedaf5b6911668059b61b55eea4737aa307c829309c9ea548fba2bede023849bd61b5a467cd1ab1c61205ce64301e2531e5d58d03c74ecdafe1f5b74627be8716cad0d0a0be60984c9f9dfeae24a6c4949170ce2f589326e0a76c447a578ea3a5e4bd9f18884f18843eb1a78aa2fae06a7569a97551b227c34d429c8e1c8c5417ced93c30dcc607cb32a365d87328aaecb4ce57ab8e74f0d9099e267cfb747a3bca9f76b5f6dfb543bc4b5c06c3646062ec14f511058eb2939601913f8a0f1785249cb72b0bb1c12a9508b23caf490537eec53f614f3e06592eb61f75c1cecfa514cf7b500b0375095d5db74556220131390b77d0db72711c0c7229a5769b1d2b3f5105f3a4370beb1cacbd93ce32f89f1fc833c7949211dd204616c013a3399a22f5325f1a00008f4c8ee7dc5bd7476848721fef843123a6213cb0c0b6ae84233ed01a77a115d06e08990b8e60cfa4f41dbc9505cfae76463278b6c6b5ac7c3b83284caaba4a6a1d739c392528ff5b06bc3b82e98060e3001279a44aabaacc661fb14e7581d1235940cbe067c6b386da09454e0467c785ed0b65d41ff4cf36ba5f63d3ff2b45c11c6c22d3ea8ebbf1d52d770e0ebf2ba0c67c7d3641c145cab474a88119335990137fa82a340c2cc8c453752a3aa801127a47aeefe66d1af1a26ee1cd0e6d935bd548f6ce33a9c204be02ba08f9fa03c685665375db7c0c656ddf3e441ddd96b0d2018beff5086cc63339f26bc8332a5e6a1422bfedb69187a3443c23b630a28b02f8075faf3ff2fbeef6cdf02ba4af47a765003de2254b69f487bb5d038759a33ce6885611198b81b0b6fc5d7a531a7a90dbc3556aa758db1657698cb3698b8207b1c1b589efe5d52790667ac483dde9543953c6392d5eb8afdafa205d325e314f810e9c7722cbf5bb76fd6502733149bf21c60717ff5bc366b85ee9f206bb1f330ea72f61a9766090eabde747b1eb9c046cc8713d5a4f8d4b7dcd7c61f2496c5b467608cd9260382b8f11b04c318a5ebb6411a4c7fa060e08c295c6062ac644bd3d10bcbfcfe2e3748eba66f65d904ff21147faa8475f508f21238d42f62b697249b9fceb905127f7684c8130cb8663f09cd25ea038078e1980237389337d1446c3a77bce41b37b50b9c3a020526e7b7b3bef370cd7af71b225700627060eb65693899d277ed130ec5ed9eee75d4886f31aa93bbf302e0c69c9c4499396b43dceb67c02fafaff8b56698308393a03f60babde883f00de2c66831f024fafaf98b2fcf37a9ce01d4f34e95c9408395716dcf83fe86c7a0f5e3e6741c3b63b6ebe9964f1d5005eeb732ce66402007beb3e6a087053", }, { "9100c5b2d7c5d5a854bce55e82f94b89a268da7b66357a661dcf75cba10a1b320ae0e4e1a5b989f9766e57f867a3810a0b5b857191ffd7aece4c796f5694a2617486421940cc12b63a6aaea20d2fac188b318a1c3061cafeae436e04d710654b96a864d674768caee03a50ed6afc06f52d90115df1db5c9f1ecaa4f5da094070b1a447251ad3d4fb0e24e87821ee6d4e7e7eac7059080f77d2b36cacbdac1c6e5063946a376865458c4ebdad3c2afcbba8a82b01b03a7882eee42eab904a19e0aead4ae515b02aa2fee74f3a114bf5b9f320baa35b3225491653f4a69e0d864cbbd031d0805b727e42c2b9530dae0c01cfc6a42af8ca730e1d67b4bb743a072f0a38008b937209d534c2284271344340fae76af2b1dd00cf44b48ab8ee92e8f9cae8845e5a8d338f505cd1c19014018bfb6b7dad487e7c8c32064421982c1a63149ec16f2bf4fe7b50cf3ce1e33d6cdea8e98bf067077c9a0ec1bba6edd5090273ca719ebf6f1a0f3e56f021945cff3c468b2dad92a947a06a024758d7505a4a1bcbe9da3a03e97859da99ed36982a7c23572ab60071566b749dc34bee1d9609e87fe32282cc9adba633c9ddcbf359ef4a83a54af5fbb5699978b487954a907dc9739f4b3f3927e66cf0c338e31c272da0cc7795c72dfe60a5b2e73bfd77b8c6ea58122a913910fe29d3360cef5d398f29b024f0dd225183d538bed2b076989aceaac460e3d45e0ca7941897f151261a024b0adf6d5b62429420144497adde6557a3c53b7723471fb760b6a8b1dcc2b327cd939528f5d7bc16ec00ad99df12f082d82bf9fb7318b3d3ce5b84ab1e38d2ebcb6713c03fd0d62bd083c4af96b4316ee02b6953431c261278aabd96e28f81adf7946e3664446135c825e45ed916ccb941350c84523296cadd5360bfe3e16dda75db10da1f710fe796f3456f0911294a4735cf9968656345b9c3049ca47176194c86f36cf702538df699fcffaa254af15b198ac37eed0837b00cd3547e496ecacf6136c6648a535a235059cd75a3bfd0bc49933b379b72e7a8463c268faaf05f0b27256fb179c9d4c923a13ec6600f83aaa2bee13e30c8e676040c06aefc65ba238a29d403f3a8cc164a0bdcaa1a5f54bc1d35fa4efee0c402eccab1e92f6b0cba94e1bd87898a9dd3957a7eafd9d26bf70866450646090833d4b91c032428bdb9097b409305de669a58e44931b7b428bf1a6dc56177cd944b87b04eabd80c64e287a5758c83db26dbc06f0c772335363ea2fb9f19c833644fe3b3fbbbbf5f9d460412d287eef862ae676f258aa45bc8465667601e9ac46e7d77693936c8d67ccde94e54d746b785ad26aa38ca0500105b6870790235e780ac50b9e3198f5fe678ae3a4ff4f1d4a2177edae183daf2de42625845973fc544907e27a90d868f8634c9d529bbaacbd228a5b4ac7fa68ac208e207a022cce4b24a0b5b5791eaddc6b3b3ef6e5dba41855ff531de9bbca0a39ea743c0732772bd32cd15c4b7f28a6ba579d902331a88920fb970aa75114e14b891d42cb947e9eb14feafccf1393796b21099e52b21773adae8e550f93364b1c438dd7d7fc76994c51860b652974d04a7e6ead207610de149f231422595f4e9ced1674d98d0e15ee841143ad8613f804729524e8a5f30d451611676f70a60c5dcc7127497f4d27f35e7ba0e48f98e9022e0deac400e809170970867a1682c7d2f3ef2c632c44568abff76f4f804841ae462c7247147b6e1debe48802674fd55b2ef1be5b4604d5f60c35358c7d773ab3a3ad0ab81868c6044d4e06a48ddbffacddadf813a2ce09aef34f3b60b666245a032f021b87c81fc506166983f25930cff728d399f6dd48ea1c745ad2da7f2cdd9e3ee915f708db0d1f3481018db1c174ea950ed17247bb8ebc065186758e5403bd4d19a445e4a15519326696e4280bcecd1a903f525bbe1e521f94d79df8db4b35f4ef7bd990c0f2c32789a75f95761ca0064bf251fa00b409a58b979e56d2c44bc2302552f118162891bd78272384c739c0c98bbaca3fc46fbb5bfe123eb25df0e27343e38b5a0c2d0774443af91b64b9d4e0649f20290edb84fcedb3bf4ba491bee8754a32716739e5ab64deb6c9888bb9fd2ada1629a59b16934ec5dee3678dcbdcc7fe5e2f3833da9d1281669b1d108837eaae5180396813883de26b957037623825b0675df431fb06b35191c06229f84cc849ccf1b1e079efc2e575331cd77b3297d2908c048b82b7dd14883f3e707bf6ca38f87c19625bec47c11f54988a97205d27ac51a32f19704391af72021b78cc4461386dc3844a1b45596fede3f70e311eba92b1d9ac221d3dc19f3fdd080c2169348f2cc8c9380e12a7ebf69efa37bda4ca6f7e66919b94532ac43022c0518c04d0a8cd99e0cbac88b7a317a1dac5469534b4fbc64080196b44498e149b0a196bb2d6f59392a21c4a4523ec1ff922a52de790e42810fd9355471169d22b734dde4a3361ecd57e271a92132a8b35cfa91d508d45618ad8c6c1ea209405a3d1d3ee1535caeaa3f20546052fc13aff7a584ff79db1726678344098d8563caa2a2abf6fe5aa03d7af49dccf1b17be85600e7cfdbfff54282394b0fbeafda615185574fdff78d59ec2a26dddba1c531a1ac007cabf5be2e2f0a3dedb9174e0a9da5597c9de6d68911fc66ec9d2b1e3fd71ebb83147ab14384ee303d067f47a324a01fc187f54a98f1b0848fdba2ceb3c18936d503e71887d548c4dbc70b7eecac9ead3393f8cb85a84f1484f2e237b36b6d886f54a0f629e8bb05b0c6839c722149a5b541703aeac04e6eb230a5659b12ed0a668d018f75bc94258218c1f5390b9aee4c0b2836cb76a47da649e2425bcf4cc15c4d51d109e5f78cfdb88137c31b2510264e46f1c4eb6e6b3450ad901ff9517b47a24d508844dc85fc5dbcc079e2d09f301691f401ff5f36500cc66f0617eb4dba389d427c7ac778d78438506608f0961f818a2080ea56d0f61c40fc342b49ee63e730df61f757387b9089e1987977b7fa02d87aec2e4be24b8bdf7fb6286d190f9df870944fa910df32f178ab692fa56b071f57366a3981f51800ab416dc4500abcc19e0c6aaeeb9ca063470993ec749a0bcbd07604516b1d51175ebedbaec8986f67a4d9158f75b5f3bcbe86a83220b4fdf12a0242951f94ac7d52882b1b209b82c4749753ea4d46a60bcc4f3eed033bde2d3d20c25cb46fd907f7052217a0a4db143b2efe8875a59441f4d22ef70d0c244b2de6a7e15581e84c860a6326ae3e3aea6d3972e2de0623d2d852c9e65eed318bd3d86d29595575df60d9050e1740f884796b6657718a294adcf2303adf61c6b23933db93885172e82a78f741b8efc6315a2c88ccb6b11692a346cd82a79334e0c610734e61e6378b5e2ecc161d924778bfcf4475805a0823a0d5a54768d9272ee99b7c4a81b3d5dfe1a2f5ff34", "3c77f30bbb698b1571aeb54653fcae2c23dc16be58603f0c361eedd813ec0c4f63005a1e69e533da93e820e6e4ce1308aa29c60289060ebf24fc9738e8a4874ca4e26a0dc79ee75b8607416bd554737f", "0223c0a6052bb3cdc99a284fa169ba76be2df53b677642a606090a9267a60769", "7d3981073f90c6648c5e9c74", "61ec5230306b70113f67b340575b77ef76d521ff75b754d551e4177591a02351ad382b2a4067f2b3af7e8e15431c7133e98be9d8293d17ef40161dbad9a4f1a4f30cdd557bb9a8b03b5f1b277c850e23ecfa0fc2ab1102e4b1d5e836a606883c3d43527fc3aa26955964b144a9a56cafa7b174d72a0635b80e7b4f871ead3838a955a14c4b8c5c3c66fd86a5e4ff10dfaa92105378bbc5f76ad29727e5bc4779ba3e6dc19bf45020f6ce4dfb3400df05cac51577d58eec21b22839b8f055226b204e641783bb3305b4461172f1c1d48eec56fe6f82aae564ac6688d7b0994747d9b23a24418e69f8a4fc548f854f86baacbdec78b7597b138c453349034c8cad2ff272781e0e6799ef2f8addaf18528736aef21ef8c2d213161e36b2c7815fcfc40747626e0165684e46a9a2275c533d548e52a9952a556168195d602ead86f6bd699e97ca59f4cb2050ff148f5bdfec358dc4542ff2f700db9861dfe5ba377ec7fdc0fcb2501e72fe6873c7cc76b95b4f300857f76e6e6e370119f403b556115b19fee7009f4f6675ad2d174f44002e35ddc360f309f20a3a1dbf39d90d7e5fa2106c53afb0bf445e4cede59cb50b8a7a2c0961d00b2c251f2d815309f74a46a424838ee87f1229273ff3b66dfb79e3b1ce11bd60e061e60e3f37bd7ac896b618cd78388590f44b1a276b965a4b95f2e3a7a175b30fb45dc7a71d4b3a1a33e98af30dbb46a217c50046ac21b8bbe9537c02f05a5780c8a5d796bd6424fd9e9f3ed5932069bc050bf4a1898a0ef0ca756aa2e2269b709cc92e0c5192ab49d692143388ede2bde4923c85eae8f59db5c7711dabeb33743c692be6dfebd815456958b5e1384a109f891f433e7b4a1031d4f30478b05766dd97eb964a28f2f7b55aa6c27c7f4ebf4d47ee8709bf99915426b3896412a855798e392e111789213af537cff7a976b4509e0eb6ffbb8e886a3596a242d16d95109b0ff562c624e06636a3611f804f9b2e252afe8a4e5e868b48e9e734f688f2da2012d7fdfe2d3aca75fd74730a85aae90353417fd52b92d28a5098b6af358a096b859859916bcd5a8f779676c6e04ea461fe62872050af92d08cdf1124bde1e889ace3c923457ecfe0a635ec757907a131ad7c2ca3f60e1317880f843c5e63f4ba59ab2882a492dd1e070b070af6f60e18cca29541206a7b267c3f75a5327fd9b8ffc9b36b57b73b36e586541d15c85253e17a2581e8f8a1518f275cc79afcf2b5c88a16e9bf553e757df089b5db90a9dcdc1867b788fe75abb5161dd7ee1cf37d3f0faa793ddb1bbf1eca13f4220ea63af8ef7c0e7144d999ba1c5a983e74d48cef708c1d28d3c0a168ab87d0ef70f381693f0d438ce013ffa2cba65a8cf6b498a7120209564535b7372690329cdbd74eaa76765962720f06aae58338a10064ad80f5a67395db2c31d36b1f5eb777306395f192599d2f737327afdcd9f14b3f24155a3f974915d3302427494fad756703b13afcd1764ef9735e7dbff920f1253cb668e9f40632aea1e0b4620db162138e4a97e6f0729b14be4a7c3256250d5e7423ba1238c704503c51cfc9cb68db7001b2f597a15e77138beea02e11e0bb98a72f2a77b7260e9172fe7e60483114ddd836addd966b69570db5eb26a0cfc4f8a8b80d26357ed51a70165bc0dd11ad7467688025bdb532e7222ea12f23c44d08d111b0ad4acb2f5b3d6b45c387d541ffc84466ed57acacefb1436ef00bcb5b6211dfd0650113ac369b9f3e4891acb2693c377467b1e9c949cc0ea6c4a72ef9292964275ed397cd2b1ed25fe1aa8f47e90cde362392da5e53893eef6e4f61decae1a75e3b726f0596f09c3cba62aa08bea89984b484d5768296a5afa8b0759dceba530a169d22b81979212b3343db35ce4e4766dd251ea6a47f5033cc090d6577efbed441bb4f8944937e812f12ef17ede76df621bd4cfa31567ade18b74583a2b783279150d584ca13c0d4784b70156afdf9be8ae96666b82def888465cd3df349de427d5f5b3572e4f963d33f968e6780e381ca196bc04a6664fe93fdc8558b21b84130dfa2a646950eb2e927885925af46d7a28d1507bcc3c02ba98318bfebe5b9eea1bd47935ad869eb701cbc35a9aef5efad88ff54eb350a34ccef2e159de8e16135b81105bf799fbd86aa11653b5ef93a1ab1c367231d61b42b8bdb4f04d8d05396d53247d51890be9b56c51cb19eec0fd1e6b8cdc98376b6c6b30963ac7ab02656ff94dec0e3a0eb3f3ffb8bebd99d5889df98e6c77093c370373dd5f17871fb334c7eb12c6ca22deb75bdac9eaf24281c965dffe03da9c940e13fb382fb6be332797813710a7cd2e7720f5b9e53fc0d98fcceeea4a8e9f787e670d60bfc4a849f34571e5d09b9e9c28cdf2b2d888eca9bb31ea8b9239bd19dca86880ad3e12b1583acc3a6d1f0a438ce3b5a337487279dc4ead1b214272d455e6a2c8cce4ae3bb29abfdbe77a67ababeaff5dd9c96b17f589cd4615c0209eba5e4b1c7167b4b739ca4b9957185961529d1082226f85068890c94aa1f1c244259ef7b120e40114926a49c4412b67b4caef1ff3ce6f3aea3c6107b830cd34df9f4d73d7d978b6b9d5c481e9d76e83d649e742b098334838fe50d80975fb567642d3b72c461ef3072ebb1d03c0099e97575bae6a12cd2352d9d296351df6965d736d7568c2911394a73d199743526ba54dd62c56c598f4e78495c0172739274c0b8c96755e489765723a24a8704093a94544f6c8764dcd1ce6b4bf2917cfad27d85e4442b4e5bd577ea1a88c2b79d61cc1be01ee9028235b36444483b4e45da1087bf6d45ca540620de5aacc644a0d5c4b807b582c7b058e140eebca539947502bf73c9abc81a0e3a618b39d3a38c4ff7f94767fd7e6b9eb61e629806bc3d183bdade7e369d180dd2f57fef677e22ce41be7224f11723a85a3f1d14d7b72dc98ccb2816b77e625ce3db3e2c5753af8b079e0d63939079a01910ee4699cb405d4d9c60e4ac86a7fda3a4c9c290662afbdb7678c3a84c87ff83470fa8a416511a06d3216a1445699d7ad7e6980491fd596d39762d576b08fcbf0825243c1fc01ec8300780857c429c607113160a8354f6699b368a87983464472a5754fd58943fca6f6779764fbe6cbb510d5280292df02c4a7ed9acec8c95ad67ebcda71d0f519ac18db9b43b28244cd34fe02c5d694df57410eb54c5e1ca0f8501e7776a811d7ee81eb9d8c80b2ca50a012b5eecd5428af965b217e7fdac80be88a01f76d473105b027eb557a523f13c55e1670ff34627667649573e0f19dda41c525a8c96c2866a88bd73e66c786767e1657960f6676d8a22be1c6024158a0f0e4ec761148b5a3d8ea481d8fed94855be82479ba23213190054f937838f0e35e00aa74c89b294c29ea25ad7e96b4b6fa952ea8f1cbe5397b7c86d0b74ccc25e22c88736b045fe86110bffa0679f28a1f27162b51410498cb7", }, { "0fcff2c29cbb5cc40bfd2ec573ecf368275ade6a00e5730b77dab17e437b46524b3814e7f470acff6ddac4e0c6b748ed112657120bca1d83a4ce01e74a473995804d7c74bd28732a02370ac8ef52b600790d1284d82f077cfe096448509dddd0eb5944a882b7d384efdd4dde3003dea910f12de82035651e3ec9668e66435f519da3fa1f5bcda34aaaf028daf3068304f7b1ec18e65136241a9db281e011d27db5cc9c1099405a4430821e2488a228805314983966ce5d806b0f014c21d4c9d6a066e63aa6407ed6c29cfa4a3e22ca913762ca9d31271d9c371fe858f3b22e931814cdbe544b9416e88f6026b12bb8e88d8285beaaa35be1c24339b5f567480d7b16cbcf6160e549ef4570a0702889feaa0ebc54b11735735b6e2850d5715e5087291fe8890432784aa219bacaa2b874b075c9628cfed5e76dfe38426f9693f6bfb2de49b710c101b2dabb7c7c74f12de9ba8f75b8645d25629568d12bfbc7eaada63364b6f56569cf21e54c95d6797e9008f3496c506ecfe5d6a010d168fb7f0e2ee3c423492df36a133fffe9b87d7ac070c32cc131fba6089cb7d904b25812e03cd6048504f7ef1736ee00ee6b7aaedb3dda9c6fd6437772fa5076aca9888ce55e906a62875979bd477aabb2f4598d32342aa10a6d187c6768f213117a9ff6d830603bb7b9b475002e20b2237a4055ae6af6b8d70e343e76265188a0f07e7820dfb3d898684d99966d4bb9e78b0e95f5044dcc12810a89a75b11474c8fc06c6e734407db91a072ffeb2be6773a7c6c3ec939514b43daf29feb3aeb7afa57e96d9cf0492d90bb2c7be613f2208f5f5f5898b0a3db8a967a75d065efcabdd83759c88086583bb3d422c6c6425525a1adbd515199dbe71350b77940813618b88fe139153974c80d968ed4d9e3f97a91b7cce250a7c963f880dc38011250b9a131f2b76b677f78fd0e4cd6f1465182fd1d644dc42db0bcad8df4ae9f456841765af8e1c1775abf85a69577ece6f9e9035e36c88be784397479e713be4f5434aa4c166bc4702a4916c0c003a6baecaa182372a30af6dc7e6fc4912d13e662bd327829f6e85340fe130001babaee64d211d6761bcc52993c162a692a10cbe7434310392b64792a777a2b31341995072a6b7d4538cfde74e609dd1019a9f75cec0896186c0f42e3896d15be87aac5b11642f74e11d5c2f7de9f07f848ff543507ea4d73fa8f5683fc6b41831606352c482c7a5a013c51e0db59d824582c595f17a6d2113528943194d6b5aadcead62516507f178cd0f76729cf8b81fce4e0138ab224bfdbb8f16f8ea6196b90ef90a63f0fbdcbdfb5320984be8a80a26b932d1db7ecf870dd67fe838069136ff9b9ae087779e82cacf1b06a7b310ce6c439047c26fcec0364ea87e4549a544d540256cb7c3ef7282fa792aad89e919dd89519fe910501f5ef88da43232e917730e742ac2539d454e066feb9058f56dd246fdbb674dcab636585a788b338ffe41f4190447a65985acb9613d02669ad4ad888004c65acb0ca315752e58f51c9ae9259f20cbe8a668a207a5a46e30891bc909108f53db8bf6f0f11549e621d4cf4763e0035c867bfe9e1192fc421c080b25289a78f4167fe517852efdb6f3ccfe67ad01b4337da2c18f35bdc151c5dc76ee66efd27d5fc784e4e6829bea4f8a41ec8bf61ff998d178ce9f4a10551687337d7705eac6cd7fabb3f2379e31c1d01e4dc63e475f0fb01d9efa3de400b5177e2c2d68f2ead89e9ecad62cfc97fd0ad5b3391d0248dd2fd7c75dcbd802d3463ef0af21eb77b07a3286a72f1e9439f457630159abde7983a5c74f7dda12b40913632afedadb691d62003c70a46664fbd976457544cef8ea863858505b1c596e7f745d4a5fb657b1c694226afa9756c40d9c49425b323ce17a8531c5919b24010f715b5f27a300ee37334931ca9ff5c83c3f0a87713768ebccaaa15e35c56f3536ba945e5d954c94c885c68325bc4b51fb55d96c8d424849ece9a812af0747d5b1dc240f71609439f65acd1c17086e025e376eeb79a7255680cd692fc4b0f5768d1985fe8a1a387074f58c8bfdea8e5c11ed379b845ce2052a5b24ef0c1a658923eb87adf5b01e6aa59ae6937564ef97421722c67404cb9e5fe07d5bfad2e52ebe6cccb41ceb1eb2760545fb6a3582bc4ca572b0aa4e4f0a2ecc56299f3b485d980501a4e010576615ad518fd2d43c1f79aed013ed1f1e1bdb74357aaf7dc84772c9ec62da43c8ffe11a7fb3eeabc3584a936c37b28a438dfe78f89de6b0d5597ac1bc55057544e68fb49a6e505db69af122c2a3ad06219b7f2a2955db0ebf55c06baac5e0efac609436dee484857f75a8421945484ad0c7650a1d3008cc85c938208f19002b7994524878d6ddf85c763a65cb72a09c3a059657459f13cb584bfbd754fbf2de904517092be4f1786b2bde26ae8eb2d884592fc9e84395408f8117e47d1ab30d5fca167bbf07e41a33c230d240e3aac53cda9f251e24659da57d721288252fe7ff3653ae3e47b86209e9344accef0009b99f2ec7b3845558f1d77b89fc9b61ebc1b589fffd3261f71b9631e87541e22ed100e694854bed771358f10fe452fba61875a605b8080cc39e3eac13708e32518f28e60464c38b782c7c7800df63b6e7e95ced9154ea54e32900f6998f38eb1e51c112b6949e2eb11a96b1ea0a68c1e3b5af750a99c9fdb2cae44c5a1d37686ef87b158d19343e23daf00dd558cfb91e6f2e18f8e806abb2faf80d082f657717d08ca4e9c0d30d9bc30b612bcb1a3a3a3843231059dec344c6c04ce625b3fe064092e00175fd9d38f8fe54c4088efe30d211412be01460a6d4ad8d0a618b00a21de0a383de30ccd72f119b27a08958729a999e8aadff21829cbe8cfe398d90476e33db4c64981383a9aeab4a27f3bcb29d4b3d3b3a6ebdd71d3ac546b8658e269959630de176819b153cd53d2091efbddd2cf9178ba6ee98e1a3df9a095db0a2b713a0988a22239f5f08cc8f9abc3d67d9267f54dd5dedbf01bd490b0b09adb21d4e5aa7707e36cf77034f01bf8c7988a2e8dd7046bb2f486878436371f1258f3f7026afee6d7f6560be67103ad098edc9665e00118d4879f58bdd677cf2e6bc631d5c517acbb6db8a1debb4fe7492b7daf0b7ec7df056637c23caf926a1a589bef1db29cd81f547afd0fc9e459f46108ffdfcfdee43515a771c439dbde9177ceaf296a8749be0146cdca2b26be8c2ebd6cfd9b5032b1f7a375307f54c2f622711f8cf8684afaaf17c4da3e83666c40d26adc239c8d1a40024bbf560db5787ed404763d4e70ec6635c6a4b82c10f8ff7ad42217613c57648716ba94cb33129f3789dc86f9c8ec2e8e90e6bba0dfba1bb3dc3215188979a09f33346a6647099ed0e624c9ae10f83da0def840bdb25b718e8d86a616ff46b5327b1f99c22937920f5b5bbd6b53fa0b32f24befa4a7603234e6d94be51f00189a20b15c49e8ee58434a15ae9d10b9cf0204bfa7ab1fd9e006b22bebd22b036c4bb4c9949cb7ecdf01028d9f12466e144b2dbbf64d95d65347013e192d428678f64f0d9306f97208fb00a70d4615229143dd8890725ee3ba6021d38d6359055aa812edaf", "0c5fb7075f5e15a6733737b614bf46871e29417e4b140bae6e10081623f5c52f557c36b4da4b5a4e82920497514b1e6f745fedbf73f86ee10976f82c6cbd5bc13a917514ddd062", "e70954c812cac03e367e99f7b82a6dcc073d2f679f965d524872756ee58654cc", "5f6267f6b3b21423267310e6", "c53868c0fdc14e891ae1bc257fbb13be210a5d9cdbd9d18fe1b474f9a1929dbba3f25222d8fe8c1be3eef22352100064b922fd9642ad128a202b6382ae0a67c8affb0c5bfa1a80e55c1084cc372485243df872d677a80a3ef1ca3589908bca621f6f50133eb762cb9c05775d13db7dd3eb65ffd3eef96e8dd42928facc68390f6bbc50b17e1ef5ea6310d8756dd177be2cceb63a97bcceaa046794915589ca022d90756b02c22e8634c0ed44192abc3b8b1e2814c855ab27aaae3bdd801a73e6209fdd559ceb59a94fd98a66d12a31a643ca2f4b07ed910bc390f77ab89395d5cd1d783d8940dad4447f0452991b209cfcd998b0c814cebd08f9ff15052818bab0bf51c3b72ac1020d3b0974fbdf4ff941b1ab9c01f284fe82f2fd89c0aeb4b9fbb0a74ece08b3debc7b65e7263e2922fd4aba15ae3cba7885d04127c8e06a67f244e7aa4556f8694a5db6653f6e48d6de54f9e4024d25d3236d4f933205b6a358aa1506f832ef7d556c6a1bfe4aabfce51f3b5ac64bf6ab1e665bddb12fe13db9f07a55db3da3886df36ddb89f3a4939b1e9e5b701301570e3d01c0b947f498dcc6af438cc15e6038cb78a78986da0316cab67bca3e28c95e6b7e6b36cae9202cf4a77a0e15d3c3291d267aeee172dd587a944719b9fbe077603b4d39d4302b9a6415aa07af309a5e1cf7a9379552becdb4bc6a0b5c85d2e63bb141c405afc58a8b2b4188b3883a24eedf98dd50fc54725c440ccdb03514a6f37cab49296b6826b6bc7d7ad8cac0a3425eeb6866d94119acdad468cefe162a29e8831c77aa83321e8ae3e20e968cfe51dbf2b63f4e26c61536e6be4f63d61bbd06af38023b15f4fccb8ae0356d924dbf646bff69d1ac0d6e1c7f40b12d6d16e52d1c15958add5708bd38c514e47fe623a67c9ec211cd625b398fa7fd67a23e6e9f65d42dda2bae94524372fbc1a7e0ab3f1c451c126135536e73c573749aa60177dfb68843752b010e2cb9c1afaf51c94a48cf8ac7aab3fb200aaebcedefc6cccb581848da0121af92d9f4be002f0c2beffdfa65c36bec80e7f62d7009b1eb719d24b96e97059e6b50a52662c2c833738849f342391514349305228b29bfa9c7cf2a931558ca8e704c600148a28bd871465b23af499c11784aa45acd051f276d82789c58b14f12619372be4bc3a285f6cee21d65648d18e61752d6e7957736d3385f8ad36702c451c61ed475997d6d9f11c8be5257d8febce329aa701028aa2b5644b8515a95b5e866780e32754ac2e6f2e31b2c04a4ad35cbcbc25b23e9bf49cb1a5d877ca30880741757c29303af8676546760016f1538991b37cf0cd24ad3b1d877e5e1bd083e4b990af6ff5c0b28e530db3f463d21e76c928c8e1ffaa6c045937ea171a9071827a173e231f50e95430ae4895932c88ce048058ce6d0a50ca5c1842506158e98bb2912a61c7991a2256c97cb9050a4bb3ca32594622756291340561e9e584dd2e096263b6ff8eb898ae86f5f24500320d2d0ebb30d84cb4ef876a877dad23a611b39bf0cba5e22f2850e11c298fa23fed40691b83acc87136f8fa540b1dc40d1b0d0bd489ee9dad785c121955a094a2c6bd3353e142c04f7b88b2eb3305fd00d5eddb391b73fa2b16a6357aaa2abf2059ec979bd3ce06d5fff1c325bbe5c833a101615750613047d8155ac0c3a0734cc6aaeae7cb65d7501cb95f9d6d1161d09c961c0681547faf7983ed2efaf4e0fbb87a06169ecff1d0ee540a9223a73f75584441d4669cac09c2dbdb8aa2aed74eb9a2870f2021eb16e5f5c3e79a24d7110af4bece22a1086d27642550cadfa4f0e03f2c032a2745e1c9277a4f67fa4dc74ba056110fed3a63f643567d079c9430b8d5b3bf57a9b3f02d486d870229fee5462043b6bda8d265c745ddc1b8952bf91828d6db2edcfca7051e74df9dd456dca5e04ba469b9ff6a8130aab3903c05659b8f31cf4ba4c22511493a36541ff9d88c708dfb714d52a3c0356543e6efad37530b598bb63c3724772907abe4cad39c896c62daf5b30cd7d37eb36a7be2494353028c76e8d148b018c7bb755c45d2a33f61944071bae8316881e9aa37e4ec2374aac4f8436ed3c7db2092326538f07fc6644e0239899e3335f73c1e3c4602b12d19d7b639d4968974b6b2703ec1add8cd930cbafff4158f68f06aaac83bb4a2e31466e2ddc247ad71c5f4c49af7defd1394e21819cc24c78380caefb2ce87c0d1050680313037def12ca21cf67bb6692d6e4a9e90a9c9a0b7118ac300c6c6f636337aa25bc59cf1d9749dc183803cc0ccd1ff53210352795c6edb49ff1e5e8ebaee7b3eda6e3c0c340fa60594115e37fab60133b8a3b39d2e63db0bc6a03973e236fca801553912f93feafd8b96766049dd2066f3c5ac9222121ee9d36cbcd8f713adc8779949941f8a8dcc92ade62e46e9f1b292d5f7eced14c3bff50a811cb762ced1f103652773ef946e18569eb5892626627e085d4ffb3102c1586ddf88acbaeed903b22d3e7ccd8b8ddcdfddb872403240bc8e0e46a068f55bbddaf90fffb9a914187aac2ceedf21fefa1fe32fc7bdbb9fd76dcda1fca7b39107d308d11a118e47499dc4092ef0cd28d0d9af84440f095b4feb7adcba198894cd89a324c60ed0b996c520d4b33391bbbef1997256af7ba7ec1069244359066af81543ca23105742fee3480f890373d3205236bed566cd22a62bf69f8c0f27b714f84a203bca1605865e2cc2f9211389e0df7a4b3aab9d10826639357efe1f5fe64a1bd6d06d0b5605658c4d2d12e1bec77e70ea393b0a09043dd7d6684bd53f4c883f2f6928d99ba91873d063d43600f9105d503b11d8dc2b05e34b4fcf18e78b2b6c97d3b2c9249a2f6566ddab2a8a67fed6c9f8af2f4ef98dd579f2d4fb572e178489c503df5d5f03bee9920db347a6e734ed72ec7233387f1579c13725599a33a90915ddf03725dce20fd3806abc1029a20732380596057830ed63b6edcaa4d4418871bbfd58de1d1f2800588ed207f2016e11abd1baf1895f6096e2c75cc5916836a9ddc09cab4c28e53fadbd7d3080088131cc270095315b61011b0cea5b4d64b647bbcea54d20be1eec0992c72fc9c9771cae19191cf6a6f1840acec1deff605626d0a0d79ea8fe0af63ea75e80f8141fa8d7ca6f4c99dc7e78aeacc67762ed0134f1a0b053debfb9ccb145800b9818c2deb46f7124e8655f37c3291af107ed75384afcedb44518ca14cdea341c9657ec638531011cb957ed6b3434b736ae8c8199684cc58862638c5f6c07e1cbe8ae68c5582b1697ca9dbdd01e97023138a9173d6b1294cd99514a28102e6912b1c87ef22cdc611133bcc111e95c355a26b20a3d6f0ead66e932c5e1229b0fc17a7d6f78134c69beb362ca75017b1bf1105ac8970fad48acb8313cb3ff10e9d72c4ff11f95c2dab59575525c98653a9c7d31585a3742267c062d6ffc7a4303a3e81a45bf39e1ce2097623bba70f216aa612c64ba06ed6d596ad6abbdde69d56ab45e25ebcd4e485824449550232be26f987c14008f67c9db9d0f709f567fa44502b9e0839457e5f0aadec0395bf5c38ed8de7529708e58c0a895198fc8b2570fb6e68547630ca7f313526d392ac4776be973205f971854c300454d5", }, { "95a17355dfa9d378a18ba20e58aa4b8711ea1d6e3c65e0b2d3c6382892c7d02768437d47ed50bf8edc619c340be7bb1cd1d88b0d3d6bbf1031f738c4be09eb264c686d39b92cc7958e63c9994a84b61b5c412999ace8a9dee0e2a29eeb8dc537f63271af5f3844ed9c0d86e6913c02ed7d2b862a132f08f311aa92fc3757342d89a5dce8dd20d5792d5c60be9862ab168d3140a061489472f2266f297da357064833ef2554c49f8120ff40b961ebcfee1d0f8e7e5722f049485f72c502c9cc4afdbb70517f0fd2a00e12596ffe285d1b37eb998e0e89d756e9491ceb13e83610a3a66122b533c2c3461b3244438f5f7a7af8088881dfdf6a29fb563ce38c4c8632ada8e7e06baa2686dc6aca6bc944e5c14d6e432c4dad554803912b8fddb1c18a59a86bc452914b2efc1599c5597f87a6edcad33a7728827bbaad0a975ecc22b7748d7cc71ec7f51adc8fe0350e67dcfb31af35a8d7b72391642e29c2fa4b796ed8f535f6bc2b1198baf1cec858aac38959f83130af55c21383ebd57d364eeb0e442104004c1599060667ce5e1191e76a89199a386e5c4bf147206e7d6e598bb27a90b3c6a54cccacb39a0ac42bf22eb40bc8ec7925376a6c57d8eac6317578ac052b72ab773f572ad961ee05531cb95ee5a6d70add4176351960fb4bd673f7db9f698616a8dd41823f2f87924c40f131e6c83bc40ab1f92312f46ee86765c306cf4a1d77275ef9668d80f9d9c1ea0aa7b2456bbcf764e009584ef1c0b4b4c683fee3fa2641f48ccf7485a8356fb3dd22f848deefadbef8050de9c5c19e8c449c6f3ec2b1324f80a7d428dc44dbb966d40244c3af03bcb410a57ad1430615e07553a22686f1a62dc6cf090aaac3707ec5b44274b7fe28c7a3a298e7a8adc71e016944875bebb421babd2b64809be3454f25b90723e2cec68467ad2d14744b15de8f9c397a505a340e85998e207cd46fa18d76c46f458af4ac3821c0ac6cd68afb72c376c31daad1a2435fc2bf333260c1a82430edaf2499e7455a93b1301eada2e12365ffcd36a1119664d0c996318a3e55bb2c04dfc5eb251f7fd64f9d83f27ea6577d748e1f85248355ed19867857dc3383e01249cc37684b0eb8e891aa663801e4ac8f0331b38686a19f0d19f6e94c7ac95ec395962be0a4e3c8358d2f6d8f13191e164ad29cd1733bde8c31c7d8ab90366e26cc9a06707dcfa60bfe139a112db827778ac348fdfe26892fed61db7e9849a464e3aad561797b6c778e0688bbbeaf3349727b4670a2d0a08f317b0dc9c4b12ea85c0309d57e754d0c7bd5c83985fb82f776c968189908a8ca83b5944767c2efc3c5f898436de54fe8bb17224012a437896d9fa106a749d12aff657266276129ec5ac12fc7a77eb06296d2a2a876d931e479d3ea201cbb4b1b20bd81471eaa33786c624013e1f07577c2171f38f0511c6924078a40c2d55ce392dd2ab0885e29f4c06907a1597c181b933853838970edad7777ed394c491cde27478eafa5b7a36520aa0779261f94b957e83ce058298dcfa07b08ecc425caeb6c599a11103d7631e77daa0d9d3fc6f42703d57f2c624ecddd56b9a27b848de7dd28f8ed656f1e4decc95a8908217e2f2453ae50b5fc1d9352d735ce5bc2b538eaae25501d449d090df793151811443c64f28d19eeaaac4081e10edca4c4148e723ade8f7e7b988b732ba08b3ce4c8a0d655bac4ff66048148135decd7727a49ac59d82ad470b5479c55d3d8399b790ff033d3ef99d770e1eacecdc140480aeca1e2167553cbbdef2090c7592b40681b733b0a0d127beefd49bcbe8904c975a5ab8b1afe56d7ed7667b5cf92f537ad6972b876843364817c20400524097ac9b405e4b35bbba0d12355a0b54bd763b4491b2acd4e8e4fcaaf8fcfd398499d4c4e81ffa93ca07a5ff51a1540f178f43a931e07e1ad56ab5ce57a2f7dc3ccca114dc9ba8a6934e95f4efe9f3f76947909b280ea5fd795bbbc0feb3ad2b704e305cd9d8f37d178961f77355eedc9d7f77c58e1db2f7797eb8682255939293c3ef7dacd2eab46c4cbbdf929aac301a13f59831a88fab173803399d96dc216abb9f079e79bbfab667ca590266891c8a7ea4bc1724573e5c5a67e9f1341b5bffaa538e240f78da7733237999ac86141b2ac0324f17609b71c885630c90befc3b027a5f01e33979165ce2a00968c414838446c2aba76e1d7fe3707c742f68af21d30e23b637accc848f6c8df820a27bb4e94e5090ac6e008fde7cf3fdd5931fa891335ec8d01b5d6f77db57a87dc35d6701adf7ae0bf82dda6511c83ab4d7d3460b221eeb3d6c4aa537924db5559b1c6739040534fc330f5144c78bf99f5f4faa715e85aebac043e2529197a82ca40f65a8149a9447a9e58c61618600b0c5ab221420c0cee114a133a648dbc2eceb2894ffc329376d1eb3ce7039cf30ff6a53038b23c26c38739fdebc7b919956ca2e468d577dea6621a8d66b78075ad26a6e6d8e20c9b694698540d516ea2bd108625e5fd038b5f1e19c5d5993b82bfe16897c375322dbbca81c81cef6ad900f0ffe5ed02714c208a12f5234d78e32ee07af155ad1e1077a0d8938f426d8f326c751f6ee66c8f707e8493cbfc76f9ddf1ea329e094315a91ba9385e16c890823db0f0231c7f939a042665009d5edd8e48102c515341fa6eea33cc00fb5d82380d735b29f2eec3f61428f7b186d43fcee46b2037ad1aa6974d729848cf1a80dc8ddb0580c9c876def06d8f7642cf45263a655ee77f047fcd76171546319622bf71283f3bf0b519e123a85765779c8bb201e99981ed184e642f63aa61f9cc206bf45fa6e514bfc637671d9cdfba2891bb112a3cff438a6372ee0dd3e7d9f352ce52f8b367b7799e1f963bfe50638f0c74b94873fcd3d66fc1e342a8bd36fb8b88f33eefabb78eca4dc9c89e2c57aaa010f2140dc5ea7c86cebe2f8bf42a167d1d546cc80bfa9258c35af6efb1a090c293a4cf588e4bdf5c090ee7fe38fd7b5551e71e5ce2b0b5a50bab95bc4c257edfc94d37579816b4a2249ba05c991bb2ea02d047e480fc8a8ba71f48f344c6d20d140a64ac20184e45b4eea14d0953370c237ef0a47a7a2f22997715dd3ee8ea52f24ffe12674d571b3bf968454ca051701e411499bc43bb55bbd033f9b81d4baa6c49bdd49614efd20d58175af868ca16a9deaf65216abbdc3beed5f30b209e786a5b4c006f3bd27d93e9d78b51a1a2fb7f5160a0bc1b7df70952ea1573888ddde3d9dd5314b0d0a899a733eb48d5e6c7274667e362e4da6b37c480aa4d0d8730e66483fb1453a3aefad69942ac7f09d3c571b6275590938c541336a121bdd20722550236a9a5e4a37c7de628fceffbc260b1e9b6417c4295907937b13609b8585ebb8f076073abdcf19104ed80ffafe1b09997f115d987a552be5689c70fe125ca702d2ae4d807d5690bc2e90b72cabb0b61ad203b34c68df21c16b92bf8def5680b204ce327214c32e4363d5600f96162a6819dda472acc6441858f396385a16fa5ee52cc0f9ffef3d53c49d535aa37db2cd4b573ff81d74006677969ec1ad891082b5d18ca5b0b9f975574ccffaca72b805c9f7fdd76bfe3dd384dc953255a5b50b7731a137fb9aad42e77d3da1eff5a7b9eda5814993cf2d289bb25ae1680ffcdf419e073d38b4701021adb2019359bb70ff4cca930be7bb979a0678f20665d14803d8753c8ce54cae92feb026486ba747a861daa449863bd38cb4d5831aa6db1e7f404b0c3587aac8765aeecec686066ee7d11321574f04d3f3da571e71222ce07277eca7ff97607", "5e24f34a8d53b17bd0c2aee5369e3276dbd7e7c2ea0990f1300fbbb00831b76655aab1e2fd625ecd", "c1d796f1e651a1ee825855d80206baff6818cc8c247ee6ce62b7531e6e9ac32f", "240cb25aaae4d085bbb747a5", "319e968ad291ea5d4a057c38f7afa4ddb9c9565962fa1a7b231e397a268ad8e0c5030a2df09dc4f99402ddf2e0d06e753bf55e1b318b3e5ff0108de2328d3b8d53e23e08bf7d84d59fededd60d47bbb52736b0491f82c616eb5f779c496abd6499555035e4513c8613e7204e6bff8d06dfecd9ce38c6b83efd8d0e41f84f7cfc9ae07113237987a4b2eaa87f7e0a310155e282e57858244e9071712fa026cb781e5a4bfe6fa1bc480e534096394459a3d1354e2d9a54aac6926a60b388410fd0b53f7a3a9116292f37406369c22ea674418c4deeead171e00f74f5cabae5d24a0686a4bcd8ba99aea613a23edd0a019a319daa3779c212fbdca9d772fc3fe612cf178c2aca2aeaf6bce2433494027a474eff699bba95fc7dcf79ca1d77b1e097439a9050a5cc78e0b78bf2e7f50f959ea2986a59be3880519cd84d0a673acb0432feb1945c603e70748445c74600ccfec60efcf9e4d02a7df5f967de4b473f63b0b0499ff4ba350ec1182f3a0ac17ef9ae28945fc9bc714c49909a7c1e2f311aa6ad7652e22e1f48bb51cf53814a2125152813752d86c7f9468a991d0ac84b1a2f3969b8081c228b7f5760718036e26a10e211ff04ea323acdaaddf9b06a08c92ed663d0fdf13fa601cda45c416c2d3803dd9b5ca29cba57e59cf4ad93176c65c64507b1995d638541c90b381ff758833a2ad67b0de44c280fdfd82b3c6d4353ae30b33768863cd3169a2032f26e37ddd57e7da1673cfc7375bf6e6792495a2b434155d684f2a6f2b919f944469d47be5aa7da74eed69d871e6f65c3ae08904a9ad042ba39905188f0b9158fd14094bd6a408fba6ef57566d69eccda86bb54cd3ca7381f51bffeaf8bcc1ae8df91d22c359888e21b70f640d6f3726a34e6100ee269124747f0ca05110f63deee07e3628bd6aacf926036ccec02c0b6bd7259db52ea8b7a686b36ba1d0296c85e43e25d72ce46c66a1e646301dafd2f4c502281e6f949011cea69459c026c65bd130d6ef06be17b23a9c9a84746e39d017b144135025ac527c1e653f233770cd68e9f232c3b623ceda836843b3e9ea313cc6a57d28ce71ccfb7265ce73b06bce1447220645e6f66caeb06b55129b97c8dd8db54c94d771504d24cedc86a8ec706a9f7dcbbcd7fc7cf38005b2913b1cfb77370bd23183ac7b5ca5135a2738cc91d05b2b22640469e3daeb6a7b0f14fc6652563663520f7754aba624a35e5d24529a6ee9f5ef0d019d83c04f5a93a38b68cbce0cecd42a11aae305475806326aebb4f673791f50c9f90894add51a0fd7c02807efd8c1bd21fa717a860e224bc9fa3f40975fd8d558e4844a09f8920256528450d77e546604e2ce2d38efadaf39a0ea3ea12156174aa8a20481e6c1190e448564675f9ca60bcef37cacec5aa218122e7bd25b571ff10f54979d62018b779a2a3d5d7d6cd56ae31efef2c844ba50ff9da88eba7a8e0d9fc5388a805ba4ad35eaa4798e395d2fe112083cce2f11cc850d25ca5c6e60a9996cee4789ca99d519daedb62f4fb1e535b742a35d71d7390117e93821ff18948a78c1fcdcb90a5f1211327d7ee0663ef16ff446e0e22d8cb7b2d3d05469b1c02864f4a87e2d9715f60c9e7be841e308d0a5f6c50161a4a0464aebafb88e0d2df8cefcead93c9623106d5518a9852f320235594be10c45bc0cf06c9daa007100ff97959357f9be8e49c870d0a11c884213e266c35e9131439fb3654fd5f1abd1e778ccb02b8c262753a22653a09272a0c33b6b2683c9045e8f967af756b98dc1797ff605c64ac5bda8252e9ebfe0e4d8d7ca754fcca5e3de3c4b63678da095281d76d60fa12ff4ca818825f346b9c4e426cee16db5818d78a527a901cd088bc2983f9b83430b50683018996996717a1738439680b68e3f61cbdcd0f0e1a6b436af8fa05d3ce2228054e319bad1dc6ac970c75313c552fc1136fabc302fcd1d09ef1b9138d18133a772cbd9cb197ff58c6e898f9e83e4e27206f3b15b6bf2778aaf9fb38e0d50152f8dbf5763816132a04b4b2e9639584b3dc8ea6d95ade024f9497944200ab0aeab206ef099859b9240aaa15f737c1e0fe6d015d04f47261ade4928e3c2ca21d1f5ab4a3f571f2ed92ebeeebf2493e6e39f0063ba931e165384ee1b5081f5f8d26ec24716757037f5158d35effbe67009080ad7b0381292a513f312eb28328cf5ff47a6599e36c14277c3eb5053c5aca530ff5954c21c03fb3fd5fc0facdac36dd819b0495fde421411e0440991da0cc4a20d294446115c0b79045037fbfacfeac574da3bf192fec4bf38c27cef71d03787430223b6069ba6d9273ec8679736a832277c657862ca791b559a5054ee8c7c07618083f75480c8aa01cb086c7317315911802e6cefb15bbe20494b14d97e3a885806db775c216dc15949e3b724f7cbb30bd2c46bd5a2fd6132352c2b21cc2b47891dd9794975f70a6fa7a0791ee761ccf4c263f27f64790826c1aa656c39483e029baef0855935e7e6c133a4035a3699925fbde131ca62948879373346af35bd7fa52b8d6c3338f213bbd9c79977c0d710028d1d386df614c5faf4a1f8fe5506a9af7059370893ff6d07d91383baba67a617b5d829e0e2eb20e541ed5c34be7ef0eaf6c6f6f52d7ca01933a2a4e8de46e422dc95161ba8ad354f6bc7c8e4cf8ab5e08607530147fcd7c9481afc621c5a3230a05e2c4db79db9e1e73f43556a8e8f0dff7ffe420282212f23d4c5f6f8d2febe129b9fe5ba7ddf27f72ae898a4eba270b5d2bb3b6b06e38c546ba80a9b2bc46097d0b47db5ae72485ef2c6419e856c33c2d66a861b9d474699e730eb8a8992e3ea9c1ed74316687d5d9fc611189eba2aa31af5ba8e81179866dc016bda977c59c595e40001c8ab3a4a44cec00ff84c6dbd9ad4be30bcc080e69b9398089d6ea464a70f536ace3b447693301c94850606d0de1299770b5f45e6d28f8ab83e3ffe52178522eb91fdaa9e4a696674ba0f52ee18e960b04415782f018d67479081b1bf9b4c9b90de026cbb66bf7d9d12cddccdd9b2c8ee2f010892571c6f0c0feac9555c71bf61f9cd69553cf7fc2be8d058e0c3430e134adb1ba28985fdc4f0cf71bd3cd09f5f82f303cded0de62f98404477bdd0a846c6c51e3e82ebf72f475afc8e6388aec57206018ba2528ede194345cc1ee95cb2023793f692f708aac3c9e8a682af36b078f5d6c7a3ed07475e9fe73b95d1eee048ab898edfee3fac4beda45f03eeb64b2128f6df9453ed77c6010e13c0270c068f704f49e62fb7410be90ffee47584ca2efc5287dae1f63bcc1819e7548eb9f0d8a3182f9ed00da3817255a2ff735876b75cd21cb25e86aa4b2893f9e5089dfac76194563f9a14335dd37ef06a501c89623caaf6feb4afb792092dfed515ba7518e278c341834a9dd17b50a0fc860b62ec621b69408cb3fbf7d4ab88a3e367fda84c82357376fa9b1161b739361c313b99dcbf4122f3870c8175093298cf432174217398928983ab6cea4759f18e7a21d71fe1b0f3cda05d241e12db0818b8763bd23d958d6e52981ce8d84cd6d82640d2000874a53c0bd14949ec99e48ce6c954ef0d08e6e319de5ebf7e142f25c0f50ff13f6acecde6a270c8d8de05ef4c310ce9e92f40f6f2b77d6e7aa3f056d4a20f7faa7cd0b93d82e3972343a50a26ff462caada10621bc953b73913944246d2a4da25fa52cc6ee1293c436ab9031ee2dc79cce39f139f44d473c236731257c6f65ca4d383e39cf8d33923afea3c80244021d36e0ed43230c44e7d1a1297d35464861f9149d869f26cc51879027169803e43c898d1b4a2a2480197500", }, { "2158abc2472e1b9c061da2c01d0ad9e996fd687cccca331fe8a2baacd12c06f284b1b5cbdfd067e5ed09a60a137ff4a97c5c26482659680ffb22bbcd4ec1bfd272749e52440537320fdd3c225c30ccd98cf221b34b89c247ab7d14f93ed3ccb0486a028c6f3abe7e17fba1742b6d4db85f6e6baaf82df1a3aa059de8d9699821d39bad42d56cc1ec67626092cfad4a2e1cb5d814e2cab78ccf5474a8bd0dc990a877d37de394694af6cadcc57727f393dccba7bf955f4b65b3c00d71cdd701754ed4f231685b7b5e2557239d7e16305be2d81a773765dcea25ea5bf2c15d670f3159409ab5bbf8da121c779132a8ec1480068cb76b68a19152fd83135aeb228b446225f91d1ed4303a4bc16cf3ad8173b30d2a1e75ccafc8c933db231efeae6260d45c7ef230ae2c7b6f986f1c19e2cf260ded9cd99d64a2d03fc5ee3d73509e47ac1c39dcca655839fec75517a9243eb611da8fae3e317e7df66cbb6abd59b16975eb463f509e784e65cd660ef1a4c5027e54b1bc862f397c9cf4e6594d98c2c2830801d3a679220b46881a372cdf3aaa33eb66b91a9f36b6941c0fe1b4d2a437daa50b811f2d8c65b5a69de185d78bb9c2f172dc90a89324c5a2067974aab14f4fbcd06ee95cd49e03717f88480a410afbb4e68b5c79b0211cb69b90604cdfaf08af1ef10cf28f0f630e97ab18d9b5138d9b9ee9154e0b3104a6c164f2a114fa5032eb5c247a6b87880332a0dce7b36982515297a05dc8a4038a09f52b1def7b4fdad8735443fadc462c7c22132f8b9581de2d213bf5c53f7fce34aaeb24263afefead5341a72f88d3acaae6db367c5c14a97d4f9e438e1e11c3c8fde7ee37e5ece5382e8c68b660146046ef96c24caa6bc9fa0a0c88281e4bf01b32df5218cb3750f9c4b8af24cc106abca62d085198d14ba2ded3cafc1fbb17519a696965a1ba5f65720e893f1ef3fbc5200316b9d4615bb23426ae53e1c5a57b2f0ee0d0c83f353b4ebe7a6cb17531d278478b4ca8e6ffdd0cad30ed73d568a2e44972ac88a7e7d665614316d674e84ebc739b645a9a4166477254ba47bc5c2b05ced88e75bf64da21a7f1f71cd946d84de13ca77b7e0dc2f0617d371ed96323a83bb11dfa16f81bbde913d9c259b10f3aeeb6b56cc4775c25f49343cef667763118932c2e8b47ec745ac537b37746ed65fda2d1c11a2de60ec02adcb79152e8a9e614d8715cc4e6b6891d6a0063576560fa3621146308222432ffdbc351c36c37d844a934088fea92ac54920facf870a62e91ba9299dcb6cbdb918e2d54fb642c3f0d60489c4bda489f6c584b64c8f19359ab25f388dbbe636c4d90c048f5ed87024dcf9f98a9e738163f837a07750d61203254a80d120c795f9c3aa791272f9474fe330da81a45be5ac838613d46c25e781606862912ff88af393040605fd4d55d07e2052227c37ceffcdd2d42a08bbab69140dfa4406853799893daf768af546f915a91b81d0da719ebd45b8b5f1641f15621959689e810217bea18e3996c532ac6e4e2e4f289fddd5e5968bd6fa9aec5ca435c532b6c74a7568c8aeff9dd19bfc2fba3b484a191e2faf9a069a24e2e6d928ac0bdf635644cc1ef3bbacc547a8e4f1d42d4bed3b6b8cc56216fa550dc37da9cf4d1d1591d9348594d14adc7a3fde5e5d1a3b9875c85de7df483cdd0baa86dae793e0796d14fef1f649de6079acbec6b6fa5f2cb2bd0481f5316f00dbe5dbc379bc3cd6d13bd8c775a727ef43e6a5fad1051783b22c05a75d64a8394a73fcb430299b015563c8cb0ae0aa4ec750399855411c076d21aeca8656f3d0cae084fb0a1ffc6f73b52a7ea5d4bd6d24e7057a3811719533105fc967439a32241f2d3e3f299da2deb821748cdee1a1c5e71bfdf88d833bade2f505268f375a9e6488cd8e16705cce91d15b60b2fd269a19148296a7be348aa349a12270fbc0d5748e538afeb0598081a4f1349217ceab3c4141d40f765ea2bfffd530fb9606601469fb131a44939be984c07bac8f26d8c068accfdefb729eeb47cfd6ddc646e22031f53a7698c6501d86cbba05e282d64b2f962a1b08b9064078dd1e3f14006f45f599bc8e600cabe6d855fcbae8c3060859202361d929a241f6c0711ac0d050b67a1d44da19e0b0e236adad1f60a327c9c34b2b9c64cdde5b8e4f664f2fc70599d44a63ee2b14d051c27d71231098ecd3d4086038d63e84547dfaa39db1a92785e38b640ea0345062a1c185b25a72862e7ae6574114eba592d6492087e2580dc5d361c473a614d647e66c0a30de806f4976b69a8b92301e68794ee05b96ee116a5fd5edf5eab43dc1103801eec861383f17c2bab9f2d9126c1802b7aee0c909309ee72679ab644abb9c4caa54add283b5954e6f881781e42f849bce6554c7a5e3becc5d5a209805ccd4a0117272a53807e3978ffb19641a9dffd9034490a9284f658599961daf52f24f6464c2099cc9ed3459d84dbde2ebbdbbeef25c882a9beda03573bdd4c6a0143b14d634a1a021d5f9fa23a7ed0f5598ee57e56672814412b6c7c08b8e709fb98575fe2716100d000a20a7e7200d800e556564c7e6a8da9d609b18ff0bb8a8812e96b834a6b534b0d5dc97f5da17f42f8d58e763f1b201625d1a5158c2f9e9e190921637474ae81d278002f197f7211540088931ca8a941794e56067ef4a497fdc6fa713aa9f20c21f23c3a71ae4cc5aed459ca7c020bf55162fbcf56a066546660c5a009b8ad2aaae9651c97b1e145853a10013d1bf68e7df25dd492c328f823ed982da54557502ebc6cc56d4d0bf2881bf3c536ea53b4dcb0886e73b066969dfec343441b9372d7ff38454c4337d45e2b999415ec48f19cd05f0f80c5a61ec369610784f47a5cf3b2a13ff5d8145303ade7189a300936006846812dec9ff15500f8daf47236e724d72619af3a6cb3e854cb8284d5b8843dfe056beaa45c40a4541a98c7507feb27a605d6e07189c8c5554a492a03ce6701d3d2ec782e2c1c8346b54a963435bdda3a93bbac1d837172cebb9cd18903d25cd6bed404eaf18730a6d1c6da0783b5411770ed34f35fa6c11a4292a34565ff1b23d4200ec5a73e6b7905458088fac19f6aafd35e0e791f28bbb2cb0117ca1c3a9e3c4863e487ce5d8c14dd140e9eb4794d87d75b01f683bca84ebdbf19dafab716421bfac9e95755fd346a0cd31e8520a55c7ca652ff63fb4e20ba67fab41e11f7390bc02363162097802c6a9eb18b430d07ea60064d5b546d15bb68cada79c113848136e797577f1783e9b53574f9427be3a28230fdd69d139205dd6c7e9e7f031fb6eab70d69ce905384c5c77d084360aac590a89b2dbb2d339899b13619b455cf9f0cdc08db6c5b5f3223dc3a663ce42bcc8cc6f947f42cdf8dde15a6926b753177513a52be95b1f0b88d2a1ec90e49959b108fe204bbc29199d7382c42ad5dbaff970cbd2dbeade54bd70415e54daa805d396361f525f38efc2bba3fd818f9d7af0594dcc341c20f18c624fe13ce7e7108e1d2fd06c58b03f04642c95e3ba00d4035ea0476ac138f72378d85050bf60dedc90af38e96f67fdc38483a73e847b41d31b894ddcb234f02b0d507bbcb15a8941f9c23b592a291cbeacb3ed213f2f044aa842275a7717757467f121294bba6b357c969e96bfab455c6f328d9e5181d909c3f0543b17d9af7fcac099067b043be79aca8e5a75c3a6d4f6246357a63c516a3ca595447f34b43a055d3070517c67ec36e636aca9ed71a001d4f7b81149124deeb7826dec3697e183d861d544c9c17baff82849d599e9e77ed19f801aa1ce095940674576ff270ac788d00c429187e299a03c6f3a1646a8f7d6290287e70bd1276316ae624da929c67936191abdfba45e2803884e5a3136205a38a841448968a7900709dda033a42969bd3417a8d865d0dbee1f261f4556797dfebab278136a182a63e5ca9789e3f1371808efe06eb0cc5ccfe26c0538d573378035afa39fb7cdf3ad889b277c8c6e84954e74f3ff3140bf13bcb45c822784125d23b5eceb73e", "088fc7ba068f80efd8d4d62813c93c1eba77e9ff400c7781314abc901873ce200295da09245bf8fd2fce254397616151d94b511957c89a881256182ac9e64acb7b25d4a080cc9daf9ac2f231235483fc9fd415f69caf7eaf0597", "78d5f86b071bbf8a185e5e2d54faddd2a9e26983b1e7a74be0f0b979b9f4af31", "d9ce7d249af9496e99c93b36", "ad542824b49fc520f0b7ff8ce2bff8b3d47baacb4a1c95ed56a306483aac551fffba48e8a8f5e4cc536e9266182f6811d070fb9282f5c542cefb4993ccc7044b42cfd6fc71793dc8dd2de23c630f9ceaeddba45efed9d7fca25fcb07d193c000822478b19c2ee9fb31760cfe01475ba8a003db469d1130318a79345a29d054a9f9412dca1edf6d8f1498af5bb6fdbbd3d5f9a244ff176f62742c53779291ef6294df6540d841f4ee8c7c58fc8497ba74d9cf7947add5373427d81ae928305b93dd26cfc65e63b0ed0812ce759511bfbb10aca98f2abdbc9055c4e5ab82637f6a965bb74f592bdf11118b8eb79d50331e76cb4d10c6b4428cd4ec2ef4cb727bdba2b5375f5184d77772d0f9fd3a3c579a4a548b9c2dadc22c805ae959617af49a514b43f47af834313ed2e4d1fcec2c4b9ea87f328fa3d23129a36e6c54bcd08f7e30645de86e98ebb11bcaf99543503eb1e024bc9fd51fe6bd5e6d749033f2452cdf28b3d0f8a304111bdd26dbde641c02fcb15dc21b1a9baac5e86d35b4126ed1cc8a2c3c2a5b94c99fb9b2008daf1a0c090633bf9e31326428c75a50e821b1e72a6504c9d7bcfcaabecd929163d365832e8971f5efebff99ee3f5b95f957e8904d05b410936d8a81c60b4947f8605c58e5b727d491995c76fbe06e556c8ab5cc661a0c09ebc98d61010050f68b31fbe1f9de8f6481b2704204b0164d8433ba4dc1076908c782826e9b555e8d608463581099a466f92bfd6ac9796eacc0ab771a3f11d03806b0f33ec04c69cef6b87d58c11acb5d1374450ce61ba159456b915043c5c17cb03f0ba66d027105bb6fff41e6422f13e2a466f073358bf68149a3b577cfba7ea08b42f83fbc5a2aff17c5ee7dbdac3ff97389f5b8d1f3750e5c9be651209eeb9574127ea81bd7619da16d1cfab85754883543f6474c8c0cc9d5b80e34bf8262d2b4798f9917bcab4b880339397907a5bafe7d149247fd735523df3cbb17ae5e298846ad3bfb7d4f902aa549b7667d3ea945b002e7b209bc83842a7b120d6d27ce80631404371f31d1f61efc5423e1822032a1cbf4fa1a6b6fe79934a202d5add8c6e3595e49be3dd9553a569521c50e9653bc684ef2b73c3526ff7a0843fcac9cc9ecf46e63df5b9328a54c576bd299a366bbdc0f83a9de67b03f1da16244bd6d52e7e4b52c4ed693827735554b05b3a260cd01a41d7c944d0b7b58ae4b0eb052da34bc22b779d7ad46f90f3d4049c097e0adeaf71bbb30ed24b32ff5c7a65177db77492c2571e9cd99f15e613797e319ea7377038d53b28a4cd66a697e5e8f84cf16bd0f0430b34826114b4e1d1ebaaf2939dff7f9f4ce7c0861e51701c42d9cc9e871018b447ccaf4e402e3d63be164dcdf6799314a389ada8bf5e51a35148acf627e51481b9b0e4bec09c9e6d59229721b151fa9adf8323001fcf33afbc9a949643172f39b0d10ef57b37973683fdd9b9eb46e63054fd05ffbef889ff8fc8f251b0ab41fb00757ec1964ef373fceb8f6d148a7f7c89944b3cfc240d091601b23046188ba70a7cdf7b6f96eb93dcd3d24d4aebdc4a29a749bfe3cf5f6e1a025b62982ce188e6b57245d829c9fc1dcaaa5309a8b9557b8824a78eceef6e977721de4065b474ae008642b974001a5565ef5fe4250194e8b861cc45a8691c461817f10b646fb526bf0fe7790bb0db29d1356e8c7a197ec78df8310431d632a032b5490c2a458eb8d4327a9679d7e8ef8739797b0e820e2c567ce3562592e862a1dfcecd50bf77fcfcd00518db65ee0effb9eb3655d5d401a4a47808faa596d17b316f828cbbc14a7e018a0593da9320140a752f3824b5fcb66aa4c3cb94366ee8b821b09e7bea2c04ece15e8a7be1f58463b525e8cfcfc3fdd395ec5b0575094313557e632d0a65e3099e3c653111a5fb4f0eb2aa710229fc055a2bfd8a7147cbecc10823f1244fbb6894af1408ff9047d6483ef83573b5421b9798ee387dc38f166b11de6c33e9785e9b3d9d28bc24c37890e4f8f8ff24cca298b44d6fb1c6aad28cc634a67dd427205285521a172c2a4884ac5b038e261e38faf0086a02aa29195713cea335c47d03d67fa0dec7a8cb21db741519f5f0ba0143f14d71e33d82c75d6a19b3f7a42e6c16d762354daa2670ffa55bd400637de9cddf9e7964a03b4c8956f36bf54d89cf16de23e8c52957b52eb4572a11d1398be72bdb129e2c1abb58c65cc291bb7b0d2dc326c6125a441863a6c92de0f47a355222d58bf10af0d297a86a98b4e933a8f844fc7f1bbc8ba77919dfc50c41219e3db309b92ba056349faa758daf360b8ac05e43fc2069cd46e63fec399cd7764b111467fc65407ac06f5f84a3179930f6215ac5ec906146c19e0d3e162e77a2bca3582128284282b251cdcac03ecc204266ac3a9cfe8d8854008baf89c0ea0096a400d6a0d2f7c681c99462cf0105f7a3dde690ece0438fbb820b9c73c6cdf6208c336831101b904526cf8ac331d879d71615d8b1f750ac7f0ec692d97a5e21e17e194a98c10172b5c4bc1049a8743188ae7c4d70384a7e68c1353aab7882bb91aa383821046ed0ebabb4b2dd126ccb935f48646b299095cdb71ecd5cc402e4635a3f7a3c8a6f54f4076ba028dedb402bcc92f5668dec3d91dda7319f58382017e306237e42480ee2c1f5930564cf16fdf37a3434585336b8e4535bba87311cd47722b9da727250560624a5dde48a2090ee44592d2fc06edda634b600fad9f843c6b2eaa0697b42858afee8191dd2a31e5685bd104188e2ccb057dd0a8d4d1205d7c846f5b8ec0f06bff61c7f47ac4da30e1bc80a4e95af79b14a83e9af2e0f195cb92d14f752a5f12ff90a05765be453075d799694848fcddb07859336ec101c8052bdc273d4abc313cfb351b543fa340dcd01bf32fea59881ddb8f33c6023ccea70532814ce4a2d0c66c846347b86c29dfc34f6fa4db298911d4367c59939020a3d078194e6a3a3c5126c24ed182398468e77fd61a5b1271f5cb2a97868876954c3f7179d6a045f4bd770f681cd82216cd2b1ceeb4e724b3fddeb74481e662fbd7f5dd45bed6d4f89d21b8dd9c1009ad2b0b16954e97993ab8f3fdd9d61f8db102a945591b4552f419971a9e46a792dd8392c8d9502767c82d9b4f69e66071eb579859e9ca070cad5fe3b7fcb77b8474926ea991ce7ad201421f8a79c051b762a066027ab2b9595a1c97ad57f3149f5872ed4d8e99195d47bd3c03bbee590a50a99d8048e912aaeed797977b52f0240a6cf2c865b108456881adbfda60cf701454da17bae879cf098df808f34e50bccaada2d3edeb1aa73cfe3c512d814eb33897b6ff9d67d3d682517cc333c3c2552adc99860b1f0d1076390de9f84fcc9e802581f77e14f5254da01831c70cb8581630dadb44209377d90447a1a21cc8a2d6d897db62d8420afbcc6ed85ce42f3281255bd43e0afd3e86b27d3b957104ef54959282b0e1b381a26f16057246704c7888126055af5a1f494540f01897e8781e1a5c0193b7bef4b5588d0e9b9c8de74dcdb63f03f7b15cf48fbb71c7c3bbe9329e3d326988bad7d0cb85537c1e0b3cd88f37a3c7765f548f99e495ddc29daed8c7f15dadf2e5b79def91dbbea277c51a5da250e66c305604bcce4789ca2df9a10614d72824ba8e4f179f35ccae7119fd962cce13b282f0f970ca6c4776374c4bc438f0de98aa04fb3cf23d2c6800a4a666c15bd20c486e88e688ff9e5fce906b4ae96ec7c3388d7567ce6c8bc61f6d2373b93f9ddbb02b384084b3f28f54c9ddda232d3084daa5fac5ca356ac0059f2fd3fde5d6a9516d0954653b699aa986f70733538e19721daa41329abb95058450e602eb5726ad5a8b81aa474650659c6f7f6f53f8a6e635bf35f4b1191e0dbefad3be756c6141c7d55f007f4fd131e5d5eaa120ba31cc32b8d4c69d4fa784fe0af7dc272898789c774e7995cb252eb6c8e8053c9e7adb59c27f675952d161dba78bdfb15859fdfe4fe4a44c01efd394bf51d43c600aa9a527d9c490971e188e28b980e77a9c6ea0a4ef6bd38d11b47f5745ecdb", }, { "9cd1c25b5bdab9b9080db3e5e05dc749e0783087c310777d89307138613bdffe0ca259677c13208420d4690031314a11a97a986d8b0fea143f5b4da0972c9ea3cef80b4b0b2bcf2bff392c306a764113f0d9807be86a9027c6ddc85d096600d85e0b236937f295362bc1679537a8a9278229a36a9433925a105ab719c0b7f11fc31488fa071d3032de97c81540713dc29ae02c2e13be8823183f3cd9f72ef8ba4280b4499ee47c7c7c4492bcb5cf7e4fafaa7ec26906e58146215a3d4f52f792d3abdb718f57ed0b9b7fc7504e45a0fdf01ebf5924a4da6ac635a715879ea75a4983cbd9dab9e47638acc687f16684e184443aa9e81513ae4abbc4d1596b2ca3eef77cc9b0603fe90c0570fe6cf4dff0381a99212fadcf7968934ac1ff7664ed6ee0b61e41f5074dfb774b676c2b57a445f1c5749e95ed062837c727ae2c151c0ccb3a4dc1429bbcb9e62325117aca566b8fca0924b70f4defd7749d0389b90f55f35d1635f8d2efdef514f06fde46db6e11e492c8f4dfb7cb5454cedd0ddd32013a4836321a25110f3a017f18475a86583e192132f8d8fd4c2dcb2a3aa95c3be3a57216bf9727cfd1284eea6fa870c8e689e91982c116ceeee2f8298b55646efad684b96eab883fd3d629437e9a0b6523f47ea5b59474a4766ccd01c13170bb08f47576a0fdb573d4dfb65279c1b79cb535426bcab60f4022dc42e40db29f15a6148b461241bae62070389932f035e7257752ef2d6130503d72344b24d360cae8ec11fa2dcbe04d3b18e66d081b552e93a71dc0094d1046bf4491e318f2ae00debffa0b8ada58c5f23e33fb598829ec2f46ad3894bd7f530210371a02e51ae0a414eb2eee43f3e08126dbdbae04c7de4b7416df32953234a6694ea84e6889f27c74206ab8144a393a2614e92adcc77550dd54827387b619f004c13f6c4a31e8bf525277669db0a0c3c589eda15063f12eb774a13e2aba2f2f7b6e9bc69f8485f1d6fc5773acf83671812412d28704003e78a17da25bacd1d61a6d9cb9f121abc71d023bcafa713b7c954e4e1c524e5bcaefd86c4a843e209eabbd579cde0263fc059ec6ff10017ba54fc9c2a1171d6b06f5d85079167117c12e6e5d0c71c008765fce756fd0f1141fbad6c1d2f32cd8e80429611a9a78dbc8e738d458f9ddce58ab43c77b34db9befb25cc1a588998e8dc2efa75c6883244fbbf9a7b4d6750c81b8d3fdedaf98dc61f49d067c369409f984b155ec347a3bef73e2a44957b0ca0f84c7fc335fd89453759ad0ac2fd9a5b38afa9fbe74daaee7bc52301302fb2286c21fb922f74d756de84519171fbecaa9b869682d431614ff6845126a4034f10253aa244bf89ab8e0dfd1f7fe8fc1a8472a10746d26896c8ece7ef80eb2e910069435518ccf096caeda63ad692455b04e6525bb8bae27197ca5118a57fb9a5d8fcfae1b9eb7874d91eafafa0e4fab5cb4d0173f7e3e58fae369843a641e98f3ee460e8cfe95d98f7fd38a8d2235e9d6050015833e6d7d21d7015c3b1ff42f0d3a3d9a38d373c8524752e06987c9408cca550f08c38c2a9a8d86d5ac7a04bab44254ed15c7b5670e0747788e11b81adb0d29e3d0b50d6a429340ee0d44a8c286fcaf9bc46403d26b4a4af95b021336103c1ae0f1274b33bb8b21c8cfca8a56c639f18a9df45d083fa7019aaa14d1ba50eb9a4112e574cd70969640602096265a87b1f77c0e00bbb501555f1626196611b4a824991cf10ab2874a12a8e0390267eaf9e3f8f99eadfbf40d111a26772cda1f50743c417eeec9c80171a83a730f246cf31c6691c96185d672a0fde9ccd7091c4b455dc93326913497396e0a4992773caeddcd783e534eb0f34b99bf23a2db6ee738381b5fc94ff603be014c507888ff55557793a8c5439b11dc5a347f35a2666eda81cda4d1c3a78fc4f3df3c7bde91d05524791b67142c446f60c3a4022912ddabdf817ca3280b671beaa496c935661e5adf39c1f4650563c5c807c8f21aa59df926199c4e2404690ea8ffd7dd65f637452ff93995fe9c5ac7a322b9bdc756b7ed6f533b9357a4a1ffa379dd096f144e9e0d87330c238ed3c6b08c8478e23b65518ea1e4e64585e5e9fec2f26dd7400ce4c73ff0eacdc3b07e4f34f6316f5b82fefc66e442ecc92bea8c1d58635d644724a3380e71fbbeef4bf3e57c6240ff603d65447f510eaa3c9ac794fd24f844489b7c560c7814fbc307e03f6a213eca5ea40fddf51d8731b74ec5b472bdf8ba59751065ed2461b02c41ef96622e60c0d26f9dc78c24f94372bef7e47cf09ed565ae3a52d39b02ffddf1953f1ff500f1659db9f1c2b23534702c19ec1cb7c18166fcd33997d53874c7cdb4e6c2b4d82751911913434e48b37a61a0971861187e5decb7f5c1ef6988bc1d6f7fd147a623d8bf361b0d7ece88df6e1ff8d037762d232e22e51d8c6ddaa9dc597b23ff9efbbfd416cc53e5543253732a23aba151cecf73b3ecff21c6a9fd1f24211fc21cde9633aae918ff1c6b72468f1de7e0ecb6539fa353c069fcbe8920dfa8e2fb86782e3062462f7eb2a2c441bfac21ab62744b05c70b6fc3c9f8e3a8a0c5a4263ed256a019861ecb28e20ce78e2d93f1a1def669e9652cb35d105bfdd5ff2313d27ab3eb00d1b628b4c20f42efa23390802af96a8f261ded3678ea0b780e1f4a88d23588a4ebb058adbf9a9c62ce2ce2f8264c874c697482e25f8d5a6daca4f57fd97d23c42d7b71ec150d4ee33931db5f7d63abe7d72dc936bb23a367c798e6a01509644284d52f9ae27d7d1bae597b2cbc26139354dcca0fff6d76c6065d661b66ca5eeb9f8d85810a029cb95b17e5173ef8ab92d475a1d3e21799e874ff04dbc962c668ef4be9f94d85b2a99d97c0db8f6b6d63e00e36c325cfab9aceaf7597113bff0086e8fad36eac7c0b443de6d3a8533789616d4c863df7200ba795a3b8d0a2b9568bb32af95fa604a3e3ea778c3dae159e1b612458584564ffda07b8aba9710134242b2d83d23127b51b9e41584c56f667b71bc01060240f3a2bc7e5d438e7095c1236e0e468079a83a5dbdcf132d258e9ed18f94d3c098867d06d3c09544565677b454be34ce567f1c143e2f3153bdc0353d65090dfd8f7af4633b89a781e01f4634dd7b0323ea1f38184e697bfc39a1299eaa278c39a2709cde0a346fea53a61f211112450b318d137fe68f6c102085aedabd2b045fab912da5c58d8019239f3a44b18f4fe30c5352e2e2bf030334a1dde1dcd23178636f1e38ec9e42102d8c54df0b94b207e804eacab3edddf89fabda6c8e1bd4e17ae31a57716c679ee8bc7de4412fec3934c6f3e8b4c1d1447dbba0fbc775dd3258f789ca53f1593cadc710fef6fd282bb41c0468ede5ad5b914e4758b4148b0d0c04c75ff6208ca3e79d92de8abafa4ec70ea7a4e454f0759337ce575c4954584e2bb8444c34e823d27b025d25fc9becfb4391df9882452bca0373164cd76e9af316df3f5bb7532e22557b485217254d5ab72ce349620f03758219b259784d4c9f1c7beac3cf08e624742e768b53b3d60ad0b94442c847b84a516a93d9b7d068c44c43980b4c7e2fb0ac964bf05a11fb2adb4f6d938715dde88061b238321afc7e5e84799b02a94baf3f879f89a98ab474ca12085137d639b837ebe069f6dcd8456141d063eb1c032aa392a44d1d58b1e77aba38a280625ab84e3b123507ea7a692c4acd1756c031fa52d637703ee957a993804c13e296cc20c1de55c9b8c032e50afffc51c02e5c12f48383237cdacd005b09243d9fe05e51cea42b77645e5c6f4e48c10e671d216b90a48f0d8f5c1dda553217f5126646d11a62587eb0a4ee0efdaf0d54bc2eb04cd34f5a529b682ce09a34d5acab2c8db58ed6244f7b024e68a14bcd5d7a7daa4dbcf490485cbd38e6f20e839d2b0142b9d766f9527937bb1a737877edf6122ba306bbfb5379243a6b22bdf85dcf3b079691f0e90b28a4259c1c9d8a02afa5b5a661a0f9dac52435e7d22e3591593d37eb2e10f646b51be2d1a96cd4490289ef642ad93eeffd64d7cf830d60dc4a98c768a9bdbf6ec9923062ff04abf19e8b65b95494a9420971018c7e6268b8fb2021a4ddd103976333fa52389643c711a980664e29a8479aa9c4091c2cc2074ce3ac1ab4afa217d39c6a1", "c22add33457539a957d32dd07ec9110f8cdd2f00ab6ac256b4bc7732f63dd3b867b0ecac262555", "e71f9a3dd457b4064df1d9055889f105af175a2d10dd7b8729da0d0116c2d9fd", "7df9824e774c5f86d83cb5d8", "689683c9e7aa9c48b9fda0cfffea0458ea0c3dedccd21efeb06126f1194780917c9f4f2f44b1daceec3f6b1f75506f4169bdacf12c1f65958784851056fe0b4b42a22aeb043ab35ca73747346ac58c550324c4b849a404c94b8860967b6fc58aff25dad0556f1952c045b91f56ec8eebf6f552c18b2a0641c037e6c6538b289601e1fd5a7bbe7b6e0b224124fec341bf77615183abafb52b3e30082a0abfc2cf224324338c132426011d9f800b382e6b834896ea48a8247f149d92ded7e69c7800096076cd2a729a1fe41c70dafb1f855ffa2ffc27b93e2f5f6827ade7118af60730033675d84de9cde6c260d3d615a945dfe0ed25f33b6cbd2c0e204ee919219d85c7536f4700f06fa61937f8dbbe9bda88db1f4ba8a8d195cd385eec62edd9ce673880800be9aa4430e5c10a5908f6dd349af70f32b32d8db38a7d73821af47b993b622bf168565082d07e88fc48231a440469adeca59263302438ece96d89de11cf8057454d1bfe8e4e36965a4d82618834a0847af39dd8776866d9558a5cff79a1cc9d1e3c22e050677e54ead68b3cf0094daa01330d41bb66708a8bbb8a196fae5c77dc6774629d38905e81d97c5b16d755182f687a8046e55d148419cf9c12139fee50c0533b0f04a805723ce1ea5595fca5b668e58f6b3b396f438308372489b640317cfa3a79392cf6d1afdd8c3359557a83790021a4eb418fa189ad15ba9be0f74182ac76076f102ec171117a3d16ca20b4d200e03e54f1f0ee6308e463a148c0c85aac3ccbe5781cf45b53a313f7c9975a45d1853ed9104a860c08634a8211b87500b5ffa3d8d9d56f22256d485b9b45b24d3873159adb8ae25966cc40f164f342519e88d1ead1e711e1b2bbd4be64c7e83f056f797c2d3a5cf7c5025f92be5637fa7738a1bbba55f761dcd1451ce4b1e85a6628b629a2f7917a86363b01516472c0f8614abe2ad1c9d5501b2a44a68e3eeeb34a64541125bf49138bcd15b7c82dfd40708414b85107d8b982c4f99783a03c707a37787a91a7198063f0e8a2d52dca61755105faaa09c063c7a0849570cba1aa7ddb3600eeba602c7e7c9b90ed00ec731d4d1d8e4bb42f9e9db21616c4aca48dc27b939428834404331288f03c2b5e887103c51748d0257519c3988f6492eb70cabbc2dd8a8a910d737a678d0970ec48bef3b81673bd10b687b37e11d49e7cf90c03c54826ecd833bfd9dbb8174274dd45b139d08371d5d248ee33298193194734c5863adf4bca92bc282bae2f47da5201fc240dd0710a22a8d922faf92c2071a7eede7ee17232d3b6ee5f3ebb1a8b230600b243c860968ab427a5f540912e5e7bfa0271201f288727f2bd5173539d5318e5c1c0a71cba4d9501b91c3bffa7bb61b3713f1751efe94a66e17d2b42da51d13c3df40f4db988dace42a6a1b9d138c4f590b7227990711afbf8f56fa63f2800cc019bbd4a7b3a0983c9b9e5f77562dcad6de96e3b2eb85cd99d28a021a10d6734400a91369236b48ed68528afc68f247d45c79318fc5d634ecb0f3ef8536d8ec2e877adc3308be906c5b96777d0e05970023e5c5dffed12310cc97249e4b95e32451c9acca8394fde699deda57e938bed7167e62e2cb62357f82fbe821ee73b4e09c6e2f512515412c2f27805762a8493e74a3d30bb409e499002a97354381318af28311ce484bdf7c39db53f08f73ca5793945e13fc8c66d503fa95506b37ce134ce2945d75b424ca6367ef4ed47b9cb8ba7de80e773279bf23ac888eb105385ea958b1b49b27c8db6b1e14a5c8ed5d28808a7d0b6bff1a58f24f9c57fd8b8f477a9d1365f89c698b8ba923896181299d474b93e05d3c915b10a69e61910761a6d8644933c593661b0828afeca590ca18e702322d9140d98fcf836c2f7a4f72b59eb529823a52ab05d919c3eee4db2cae1067213c5070450a160fd52fa44bc9bacc5c136701cd7adb1faf484da376477da08f6a4dcaa37af47c7b026c2da9d5fd0b30741357104cb2bc0d3cebd132b5fc7c873ebeceec5492aecab95ab393f35b93b923d2ca071e6bd8522c3ad8598a05e96646504f1620c045aa5734d665acbdda0ef73612be4ca4d95ba069041e042497f7b10445869989ce30f55206a1feb4e64890b7d1f7e9df2e88a352674a52ae4267c06592d425ed1d88101cf94588135892218ac11f3976ab2b47a27f02eb887696c94b13d48b4370eb11222274b5513a0fef905c66d0c1893832ffdb9b333178b65338fd8b81094d8f86f2e4e96a47e72032cd6fd47af87eec295c6e980f595b57f79abeb4654c4039fa03ade732b1e579551898b801ecd6e0fb1c5fd198335834b51673d074a8222640d2a969998f5b878bf897fdcf3426c4e24a7c599e5567643fa79ea5d20e7de581a873ee0181e3632a4e304f9dae09a81f882d4061ec17e588793b160c93a926874d5a8b78727f88de9bc125589a9562db5bb1c01012bbea1b2eeab68877871ce83455db43cc48455effbc71c436aebe362af22c6a319d134f65681c4d0d51f9aa42fb20f48ae3f7065664aeff5d8349624a5d79eb0bef3cbb2a1244ee445f560a6bf7a796b2c950a37dfb85ed5be11e8e305e835c9e077e676aa5ce23edb1f74806278548e3fa35059abc2f032289f9bd76043c8dd1352b6131cf34f66bcd0e7f1d13081f5b08ed0c69136f3b7ad8e05e9fe99a9b73624095f96740c1f40074e5d92ffeccdc0f15502082fdfcfc97a800be511c22b875f2832b2b891cb1aad2a17c7bd0be4427a4549404172f7c14d5e425e14498237c26a7813cd8612d048703cb180f1a6194f688b4644304950b078692faec7a2a5c5bbc482f3a7e8ef2825c4c19032a7a79a2908ca9774c6403e6b15625c485f2dd078902aff769dfee2dca9373704bf63ad981b51f61253910fd48c49ef10e3938f35ca8dd491a8e569baef675df30367b093f1088ebe8f876191dc32055481d074e5e47a4bd728efaea9fee3e83d8556255ffb2fa08194bdc66897d97d1557186d5f873169461494a83368ed8065b9a033fa4c2f07f7c60f945b60479e3c89233d58f674c0c6fa5918150bae0c6de2b65a09ccd490e2ad8571745bc37e70982411af667f3e8e9b9f7f75d863e5fef05c1f0d2acc7c86585a83ee32e0a64a9e67e75b80def5bfeb7cffe6e6822efa7a9cf049689b58336b081c039696e0fd3b2a2a6b0d177c9b3f8fe5cbb1c69ea93c1235b2c5b6934f603127eeafc4ed0728161612acdb2ba894a5ac376c4ef1fa8d49b4722379e5cb39752837395c413dd29a2a88c03849b6fb2221fd85ba6d5a50ba7ee9c09ecc5e6dc66afdaa1b021282cadc68f19529eadab809341187d57cfdfe01d0798ab8a94277b9b868612e575bd98f70de80ebe5f57637c511800373262eb5ac3836b03808ca5d5f732f286a5f18a7b7fb8cd8f60e4debe54731c9c524b84694c5469975443964ed28ccff2f4e8e0cf4c60c1c8a092e986cf12fa90a994e4f26ac89fabe8a0d1e27fdc00f1d3d3fdb73bb76809f93ea113e336cb0a5438147e454e262fbb7d656aa1be1288839bc342b48ba7d0e72c85a2e24be1a97dfb2db85b5d850481e62f3b11a28c6407686e73d550b9f1d0f010602e82af26813d2484a8db2da0814782c8404b2865abfbe3c98a07ffb37eea6de7992cad73a9b81ae96a9acb13ba213eb4111d868cc73b0432d2b6c2d7e0e0ca7ccbdce86d01576e1136871a07c76498eae53fb7ebf2e85fb8561d10dfba740400ef4495ece7eb33ce3bce26344eddd88cf1ed8028ec5fe8e71edda54dbdae08f50f8df6295f6d7ef1163f62262a200456a7777d0565d7f5832fcc7ac144b5c3e0ce3e5c9b7f880a54ed5e80662e96b356ff58f2e372b1dc0d73cb8b96c72caa9e5dd312841a8be23f838bc706d893e1a8a48b2c069874c293c41d00226f73f987aec8686046ac4c0c972c991c38b98cabce30e7255dbf16039b95dc7d103fde630b03441b15bd2c214763fece9d6778d1c6354d2c9478c226175c02cb006006715fffc879a6a2b4111f6234ee330d6c84d453c9ffac08efda1f380110a8ef8c2fe44e2ed644cc3e0146b4d02f76586fbb6d69b827be38b9add444e2bac4d7165007cdbf2ea8c4b967fc1bb70c68b229f19bc3f79cb13ee6265264885f04c09a96583f331ed46de3e5dcaf08313ba6053f3d0c1916a0f", }, { "3ab6cbeebc18df951d371e0f3cce2697fb367476bd9d50ca9e668c77636eeb9d24b68be0ce6a75eca194fbde6221755d57e9d3148623de24896a9becd98789fd3d14de0c7e53f81fe7f3fd491472a66b5b797fe19c5d0525c7a111a0289a9e65ae7c712ccf694cb75c490070bca7db17205af9bdb7fee27f9ff41fc78ebd2d3d399e690908b5c064ffc0d5bb67b0d2880bcb45c2ca2741691b6131aa1e5ee758fc50610406216905e13ec049ee92d1f95e16bc283dfd91595ec2037d20ead51d3a362140578a4538c80581b79852b0f6686c1ea66aafffc872024592ec1aaf2650d167a75bace024b261db4ab48b401cf85ec2620dc12a7fc37012af8ac1d6db923d82eee962129bc4ede578782594708357d29118fd10dc6d228bf7e461d2769e556488b776237b6309f3dc2e884cb2df1f43f71c53d389765f805ac053d05fa835e75fab0adb0f13ceeb425637f43556372d728a00fb005f7c5a20cf2b7f776066d60b70b11a848005c6d63dba0c93f139067b39017c997dd6b94c0138c3619e9a6d0e4b8792cb8d58a2ca12ae5d03e7637f2065fbb9e2d1722fd3aaf234488ca157d829e9a3b642458054f3dd58da41d7fba6d2b488a327b776d1aaab1a364c710e755ab22b9cf7abf1eb8949c5ca20c070f275f8959cb00c6d5ab7879003f89f795351a4ef4850e033d929f9a349b9133b2e0bd1cabbdd381594bfa697b845100b96b5fade05db12de040b814ec49489f39f5abd5b37f570cbb516636d5b7378f12872d02d4de20b52ed8ca0b12029a4c084621bbb578b870ca2ea79fd5df1ef8664bfb3b1a1bf038e4ba33f6ccde42c5146470c9dd293aa747d2372db1561617920142ac1d32e4f1fd18e8b9e72b7efb8fefc56d08f00450d23b7e8381849b1385ddcf9310a4850dbd6db7a4992690190655760f557a5027b5ceab3743365ac9041a5c14bed1126c4eca00d7e0a0e0e6f666f64bd1466387150ece5835192149237d5dd25e703e9d3a4f652ae04601d6acf8228e4e86055394c3abc9dccd02f04a60c298d101260b408b2620c137f77e2019fc6eaff1b234c56dfe922b0192656254fe3356143e969f64b7609cbedebcc8cb2b68bcdd9d723b9c14669da6cbfffbca2351de51e87db6afde435ead0017682b8014f91d9734a9ab9b374257273e114a8fffac786d53183ba666d8a67e30c1fe45bb1bdcefb5787afcbad213f8e36e78d30ae1305df96bf450349ade655cccbb17d887f79e00728abb449ea427fd2d0af80e3b5607a74a57dbe5264131f2fc49cb74415974b3d43ff872d4106ff11b680f56be06fdf85ec9dd850b1f77f759337b9a9ce04e611036d3f45743e562abe4b959eba7424a712fcf7c3f3773886aef22f7cf6168efa83cd3ff70b9521cae1b6689b2b8c423d883a007bb138025f2a31db2147691bcb365ac242efe40cd09a746cc501ae0289e80205993b07f86538d486803da14b74fb0db6ebf1c2bb8c36275137d654c1be56c65891cd50f705247d85621fd0d61ade8c05cf4ec15b84e8adbcbe017d7d5743d5e91025e0154a5d9bac7c6b8297490e9c195c5d74e046219c042219817a5c56636c7c4382c6a01d721d88f4b4d20250eb5eae5f3ef481dbf8a3f47a1d51d080bd4cc33f12645c8481e57835b77a85a2d83301172782f22026e69a43376ac4f5b78734c9eb914e6c76c6a12d4127cf195ad030825322a279093cbc40a680355d086a27f3fb7560713b019e7c286d96833dc60590e9a709f2e3c632894668e74ed20e42cd83a23ebea3dc3bcc49d14f8697541780fb2072dee6a5672d0d4e7bdf5cbdacdf5fea9e03c6d9cf0faa1e954172acc26dcd344bb3d9b2e0e6015cc55d19713d795bdb7c21b44b305e69c69fdb7261483f9693f36f45d356462f1ba4498de1c2e8bc3e0a70893acef2006dcd73cf15b265a8a5d4ed792a34a846d8f1d3b9b3bb75f1c5e57a00b36c00203973ef4e2654f6cb29e4445318ed99f0de6ca992281e83ed03feedb66aeed6a461c6f2871ae95343cd9797e58430d5639d7ef5c59c78b29f76a055e18e2b85eff177770c60ca4f2d61e612e617e749b4653e7901b62ba02dcbf50e59219349120ac01e6b8a6e98eb54abd16b921a1ff85898f90fc49a3c8f8f4ae9b0dd32c3e7f2e1527c4feb67a496390f28532f20acc71abb8bb4f71b434104f41e36b705289858a4e8430b8cd9449b0198ca2244923cff1df0f63833373c275572de5a9a77b23e5ff54aebce8e86d02651f26ae32e69001e5f3951967579ebe8574682cef8c12dee0b18bc999f8cc0f07e2ad3ac94d3caf30c1c8a8295756aecbbecbbb4ade8a2b8015e52a0eb1290693c6316d036e0c443fc4ec591c32f7e7f1b3933c921d5812233d3c21ee5528822b59ef2ec7eb62f7b04f40cc8238a473ec37a07e54f8907825ccaa1421c2964d2c756be450dedc011e1cdd9045720421b9a4a00e9d3076c2fd10d71ee36d5c0fd2c7e42396b034a4cd0245027449242dfdc42c8af4a34df1b4150097726c9745247b78bb2bad5fe8af94eb13ee1f41dbd36e56d801a4c9c5b9ca5d3c26f4714b6fe9f69b87567426eb6f4ac97e8c9541eafc19fc90d3b24aae0f76c4f3f81063d206ff695d638048c2cb023147a78332939d2f2470d16f1ed0e5d3d4dde438affb2809488b99815e54938fac3b02deceaffde310cf422f9027f364f5e79da5d2b5af1b4138ac9f9d301f396b220829c1f60cd2b54ef24576e5ba6ccd4802900db1bb4eea57de7787eda0e30fa90cc19f099444488699bf7c442c398c2ed989d084c8cadc97325484e337848c34562b3dea6f7670f935ed3d5216c970e04351651c1c31a34e862821bdbcbde202d91fed38965e31cc3b6f1e52288f327bd0a787ecd92b3b6f535d1d000b0f02d41ee01ca54e4e6179ad7fcbd60f0e41dfa5c9cc7ee4f7de3844fb385ffa3b24092b30be697f1fd32c9faef29ead346e42fe2ab1d312901b678b43b7758edb7eaa1c2d038b4cd6a7dc759a6b12cec955bcf4179006a7ab6e22ef15986df107080d340b8870e2304d57caa87a9961c04655d7d66c7f71ca9260e02aced131d6de65d256d6b487141c51bc86eb1e4721742f07d09e799b30da7b5ba94c8d701ae34271ba06f8ce134a7a9a2598d1570cf05edd9ec868cfa2e41b4c20a8bc4b8bfebd45f5a60408f08e931617746d1464bbe1f3844ab3272ede635f771f9af30e483903ee4d0cdecbaff4d31451e7791dc97c92042fb932fe1c82652c1d682a55912e33de3b1299db076cef594458670dc4f911f4a244e2bec757dad4b0052a41235e2f5e60b929682608c16a61287826218a1ac3cf0d8286555d5b0552754685c365d4342f0d9c45065daf6786179da791a86b50a5edd6fb4b21f09d9747136aacf79ecbf52b00fb88b0630ec7f0a6699901ba4eff913a3ab33ac85a71ebb51ed343eac86eebb3e79c16e664078ccda09e77ef8e0919b8cc447116b65ccbd5200fbfe86e9bac5637b33c9bcac9596b57c14ad5da548e96a8ffad5f5c69247c68d464c770011da7b45a337f138cda6b4e15311879bfaf12af4c61fba596780e6adcd5dadde372823da6014122dbac70f0dd896a8d387d3c74df282a659028d06cfeab3ae22dcd1fc3ce60f69a0d678aeae0e5681952949e31ccb8975cd167c9d012f4b230b1c1f47022eb1a3042951b338a734cdd17db0ed483a621650deb3510efe74191a94611dc212c0c73b117a73b8ae41892cf176742bd98a7cb73dcdc53b42df56d640739852335f8d44d901fc884286b433fc285fd5b3db8df0a8522cea3182c071f559c328b8516c9252681a94eecec7ebf626c0a9014d9aaaa0c694d14855433dae06656657d1f8a939123d28e00513d72bd3802d211ad7c1e06b9228c0d5656edccad5339bcdddd5e01afdc01f10974be3187804324fc513ba583b7b2da1e9096bbe3d078c1adc6c34d92c54e9c49fccdc17d10e66962120ee5d9b1cfe852569436270cf7c4c3bb12568050e2ca4db08bbac16214238413195dd4d936272fca5d56d7551b9b002df1807ed44abc84c66746387b79bc9e830a635c308a7bfad7c2c22cee6d3d0c5ebd8b230837b7ceaefdf71a67a3a8eaae0c36de86b2d96e759b8b53f8b8604775eb7a7e13223cb21033dc87d775628581a954085c2d66c1c8f225b1aa86091061738e7495cb36a5ff032dc678904bfa39a00285cd6947865b6d4805e3411644b4a4c94a6fffe05ef31e156bae6165d801685dcec195552d029d22e5de393a82ddf3cd3de3ad8cd6bba2325a03982204f07fc3c21518ef17a601fd743b27f7191bb446ff61d3c61d7608777990997e911932532e5b3235f13423756f5b6c786720cf6682932c90092", "50772c5a0e156ba13a9d86edc0e600021d56f7d31e7e452a74ad53a6775339c7ca6521d87a8c79b42900a1e9e6a1ec03f7e3d615611c3fd5c9927c40e5b508af1a298794b60148df01e9c9e78ab5ea8198c097fadcd6cfa6694be64e00eefe1a1885aece86f6ad87df766e692b58ebc41982bef5", "93a2561a9904a1787a10e2a668cd6a814f2877a7b512698e94796805875c8d1a", "588d9bc1d98210d9700ef488", "165d8c9eabcd5e93e6eff7be122c8c242e1a7f284790c93324f924efabcec4a4ce48262011b7360c2833143d645ff295453853c92f0c48c6dfc2af7ec58d9bec0d13239c7e5593cdb39d49376c6341263df80c0ed2ed79fe9899d0c07de93f6ea95a5dfd307e49bdb5672b158a4df623ee86d54cd1a0fa9a60ce39d1f5f4b6b0ce9daf2a61a907cff3bdd3f29156ac439638e0910d728843ae17ea7368814ad7734732e7c023d4954e1cd5fd19fc9b76e9bb84b61dd4371478917757b14b366b4bfab4eab0d9de746088ad43d8742e2b9e58faff15c2eff084df5f4316111d5dd7d23cc0b1ee1000253f26cd260aa636f03f64a8342e531ca1515b3beecc3ee07a29184988325322d5c09754c278231f92c0d980adc919d4fccf4a1da1d37f1ddb58ca997d6d700946199fa007c43853b6caf5f8049233584087fb23c3952414ac487e452f0c3898486d04e5b008b843122501f9c8a294da9159a04119ad5c8e9f5c211411e34559d3a7bcf2ac10e0174f94f3f2968c80ebdf4498de172884dbdad0acc3a887f9bfe896a6004d54cc424567d53f1198ba33c56aa460edc6af0e437b34322c1144854bafb2434f00703c1992dbad0ceaa0616aec60a380676ca11558cece57a936959d6c2ffe0647eeffd37524fbafa9691f31499701b202d9dc9980e79ea517089eced779aa45b522c9ad193e63ea8b64e8a942f630d44370f23b7e9acfedac51dd9f139f8806b09a8fbbabc76fec3c3721fad5087a6d41f93973af8d787d8bc74a3122d99ea14e2f30a3c90be4b695c8b269784eefafa52d6a79e785eb47a23d72f037ca572b7029d2f37baabce57658119fb02c5b659e3aadfe0052f1cc3c0afc6fe4624533d9700388713945c20c1d175da53738fc73f48fe57fef8305e796b474b6f8d3fc5040042373a13384237d95bb045ce0c20934a964a8372acedfd6e559aa84180a86311a3996cc17bf7f73e5d85d4db2529989e5836edad490aaa5f56d17326825aa20608fd209903335de4b36b79f68b6a52194f6ea8ce42570533df650e65b50c367f69b9f08c32b3ce3e75318106b8b2c6b6d09369c781fbf2aaa35053af215b621f833814ec4778ac683de0dc22c418b077a917a6e405ccbde9f72ed523aa696be1a6f247b096b9235217bcf19b88d43178cce5a7d82335fccb4c079e00280bfd272b9f16ffefa7fea38d09dfb2e4874553b135052595812aed3fa15096abf1eebf9abd598289e0d156974de4c2654c60825d42b662ca7439816d9d3a0255f40a4965504f643f029da535d4b109e8658ec570e99859382ca0ede0b0495d508c63c7f1eff3f648c60e9b773590cc663a751178ba7603a11985ff519056661b9460c1aabc30e83bb0073a927682a06d1b8050c345f7920c1a37546d79587fae2a92c803a986248f90547f0b6c0ad0552d8260d2a0dc3cc76d092ab76b8c12f05dcf141167a6ea300bc23227933396ef6fe9d51a1ba5a754485950f06cfa6964db2d0fd1d4393cc36f0592fca25ac1a6aacda2a32f548ed20287e3d291661848a62d41504e4fcb1cd1785617fa5786712b3005f1a1041733df6cf838ea3ea0b93685889bc6b2857d80a9bc0e7a66f7fb3d805770402f049889311fc112dccc72a25bd127777fd87bf5ab56d39bfe6be2b45a8301c2f324dcc50b27540200d522c24941701f7293b8877ac84cf35638507c7d912a3a94e4384b68c507412df65d0c4ca8ec2da704bd4483eb2e0d13b68c0c2b68c106a55b9710ad0a1436d655a3cf3c419d5e6f027ddf5dcfc896a5b316a7dae9290a7bf81aed539a647c8c98e24e7ed6a4f7f00a11134ca715e5826625c250500f8f16b40de048b095b5dd08268407f58a91c86c36ca5a2bf4f8fc682adf1bf601da24414c74956e1a8fd2888b5260e980c32f6678a4dc4ff73220c22593d23144b84c2ff56920342248876d15ea54fc100c09a81b802dd15f030bda9aa08727ea49e34f0ca8693e0a06d0af06ea7ceddbf0584adfdebeb20510bbac683451d9f84cf0f4e85c34d979e550e07e7f414d6f1011cb3dc28d0df6d4aac113f2d5b04e4486ee2cdcd4157dafcbbd55e8330a7176d1b231d9f47a63da9ee30fec6cc2c5aba3a8c6154f79997af89d972743255355647235ee939f4f305ec655271e0cd562ff6f401b86dd5826c769298445108ad0d9e13c504551f74c507436911331db60ef0ea99dc259b13cfcb0596fa9b3c95cd7fc3b1611e3b012b6719afbcee7548939676dffc372276aecd08e6a14251407cf995266545427d49ae5ab245cd5d534c52542fc71b3973f0b766f3d234c8baaec8b74eaa8ba90abe160b4504769d02e08d7af4e7ecc167780c619cefa58865169b674b2b1e10d82f6560ba0be41a781f4afa46bd722566d941a8e6f87e4a5c03d89685a22a3470354f2922e2915f9d46288a5e8896ed13617dce694a595e379f25fe621dde8ba73d865976950954e5bd07db147a0fb74f87cb06aba49b073942b82fab33a878651df73df2721ef800b658bdc6c359d396f684598e93f38e79639b8736b02dfcc124fb9fc199c35f2fa1d0dc39939c57286e58a7deed7b6c76e02b99a14d9bbf11f65d8eb7fa096fe4baf0f78cb34736499a0ca550f10d7edc8909dc34b039e3abdf1aa67a51d37a2eaf4c07022897d4d8355d3325bcf392d91d02d462488ead90b366e9645b956c3802e4249d34b5b2b2484a1dec15a9477821df6bef5e1626ec5ee9832fc3bd0b63a3c4100d32fac3e9085f0b5ba43123f54beaa7ccbe6ba68231649f35a28acfcbbf97dea2d6cfd96025032b3950ec8437108d0f07baf1bc89e3afbc2cdbb5031d3cd9e20b19018adda466382059229e4c8c54b455eda4280bde43b36afa96e146e408c7104523d5f565d22ef86d4c7cbf9c6e0d0b30e37b37feb9332939c642eacfe19d0dae1259d3267635051ea5f9b518dd74786e45fb8bdf72cbe3753bd50bea2a961b49cc0e2d589e77fd25ebd962463fc728b1d288c38a79a182b124d345872afbcfe792d259e7e5334311244edc75d05f9a12eadb61fd3ff79fe8c097eb01a4ac1f0c339d3be74be3d96b0b6a15e8868d043a0f2007ee8aa51756d78b7a78ad90fd9a26afbcb51fdc20ed7a3947f715c833e363bb87504d8efc9f8b93a993e2e26430f79f3cce203b09093c9b456b1967212eb0db4f7688d4dccd4a523866f75c9d9e7ce07825ae34399c5607a60b771866a647b6d5e1e20795ca906e451f367d8c40ffe79a2cecfe7aa47a402f8d49be9084661c96ebb11f1b48e7e8abd2978ee626f962e98f99db4eb3c6a52aa2bb2e62194120ce1e773b9db784e8c9b5adcfb70e3bd5717293eebf014e9872c5c1bdf3fb296cb88eab5e97a5ac320092033b49f37d840dac23021c19ab2a89190f3c8dde927f6e6b41874bf71ba7747a616682bd5b3f17a1dad40f4993a1b186ce4f44afb4e36af7715450bac62cb1527eb8db1d87bbc4d9c99415d16660e48efd911e02f5777a77e72733af3c3f5315dd0c785d5212b79c46c3bccd74582c57cfac0d50fc0c85370476913f9d8e8e10d0f6602f2271994972de49ab1a91728713c3cfcedb0e61c270b5fb331a980965bcfe10b41251a0f7915d5943f49fb139626f1c424524f2fba3a407e77dd7513669894fd09fff4185fbb997b4e4677f6ea0b52892f013f1691bdb38eee9307a565e396bab484d91cea9268f49aed29e319b0add900b6a75f7461db5486aaf5366f98df05674361308931de753c70777de73337a996f6d4b0e06d63a69849ba7533bb0e446f062edbd6250e61a49f4120f84efc1cf74c1bd30cc61a2d719fa76991dab119fc814a7c56f48bd584c7935679c53bb0ac78905b5d961fcd89a4b567d17a5182651cb07146aa9a94972ce613e8ff9c878a8433c0244052f09980a52d800e97ba65e8ac186862def58c72b9feec91266e26aa5075b3337c7bb8716b3acafe666ffe2df32b78f9995661d3ba28f8a8780436aae1da2a3e6a0a16dc562b8d5df6f68391aab73a10508e0f55208f974a0505f0fc0d8a55049a7b631fc94fab91459ae1f199527362695b41972e50faee34c5cca9e35e8682099f5e9652f88cfe9fa990ff2154c89c1c2a4ed6bb8a889fecfdf048ee0aae7798c55d6cdfd062cbca97ca289578c832d658ceaf26faba54c9c3ee9eb5bac80698c1441b9cba287f749a5e30d5cc715a01c89353ceab0974ae77fecc1d2dfb31a5101783cbc002c73cd155dfd14685c2f9acc170dc437c649b6b4720b676848a7f9b56cc4787eabe72f6e3f2aed776f9bb1432fba93a63bfa44fbcfcb6eaa9ef4b79b32bdbd68cddbb9897cf5a02c6f99fc765790092edf0d5bca7c55cf232a03fbb6f3eae09b12e09a9b49a538e0589394700d16ebd3", }, { "3497e8d61062e6f2084ebf72d00e9a47b550591edeee9746f31ea28039a1646d384c4348af293ab778f92a4807c48fbd14e8dbf3d67339c991dc4aca7dae38b5fb7bfeaaa538611d328b653950f4f664dcd257b345917cd66dc6a1ea75d99f70549d1af9d67b1608077b41576f38bb4c0a13ff4fa47b251142c6fbb79f9a27f43841ed0ebc0416c37f571aef8fd63b99e93ae88db50e9ef7d499ae7433d5686b165579d3598f96d9e7b1c876870310703df8fdf2069beadb34984f676eb7d3840c4c5766dcee3fc39f0739260a499647429339482e232362bc72c92a299cae36e9069cc5f4db8893e2c1b9ec0b4f334de26c951090b9724c2b3b7655d8248bc12a27861e020eb1e4cf6ad0dab903279b6fbdabff761d4ba159c1f631e681f210a8782faa86e08e554b5e30046157a0d1144bd08a691c2cc2dd22f3c3a4e5d44c5d03f7e3e385382ee4683345c0d316d41ee75f87038b49e0ad3ca45121789e7e7b95615e1a9a8dfe02c044c2935a97b141f639448182252ebfc980e0411e5fbcb3c01acd5aa7cc5d67101ffa6ab6acacace5f02d67155c26dedc071ffa66dbad26f67a819d46de0556fdffc1b4ab6d60905d8ef873ea1e51c62571c08b4c6db242e733e02e11e5840ee445c290b2232010b118839b37d4615c4521e8928e9ad475cdb4a3de9928ec7e6daf0e20d22e308347b31e7e877fdacda0c25f2e5c33a329e84707816ff4ffdca30dfc753c2cf883df16016795db34359e9363fac60624ae4d2b30bc1f2f99c23d953779c22ffca145fd08dad83c0f76cf727196799544c6c07483e0a41ca2e1b1da5a730956154f531d292b5a39a229ab13bf24a804eb68786e481c8aebfd3bc557afceadc41d00e1472c3b80ce652be1245089283bf1a1a93abd3325bb6eea121db8c0e1d6c0c31decfe9dba63c89b881824b0531651fc500f2f75ca9e5fdcbb179c9ded5d600a495ea704c2709f4a88c4fadcda4cd82a5b089f25a6fe0161159efe03fb5e0d44bdb5487f25e8c9adacc389860f62b06a6a4f8f104d9171622f70652ace736e8b28b70a4d9fd3fa4b9784d1a6e6811150d0a0601d31d17f6041e58a1058f99b80b0a6cd4f79c79a104b6bb731ecc881bc68e1d99ab358faf43d8504957ea0152e46e27dbfaa17d0f58287276e4fa82ab78a03513d5b4c3199d1362e4fd6447d1c26fadbd011abc69332ed0181952b391f2e8a5c89d68e22a7c451f69a9573b6bb6d918c7e3d52116f3f12f1d43d2af46bb450f58bde1732a268293cfd9cf2b90a844588c1979a30d6ac21aaea4b9e5500ef4a8bcd62bd70cae6acc8839f818d23c615e45daf14335c36dd46817c9b816be60c3848caa812b055da33f45bc01721d6fb7e850fb1e1458f27c70bc34876a955aef11f5703cfacde03a039c3b75b99b2d91fc18b00071a28ce25eb169b946b49858aa0885a4c665deca020a3fbba55d4d9175fd91e7901ec9eec0239806e8305f8238e5270f4af5c94d0008f8a5564636cc33c8a3d3e76db2a7915abe798b0dfbb3e322b33e188c7b188573bddbb9e4a7edbd4bb194b9743c4aceeab449f8affddbc2b109eb3d84f3b2f8b18ea2962680437241d82bb6146674ff1abee7baacc38d5dcd688b425c3e3b0dccdda3e36de755afcf7155d3d7cac2e279baad167e2a743b82ff8ddf3db8ecfa9680ddf468339427a4e9fb8ca4ce6f1e790c24e7269912a9989088c65965b0efe68ed44eb26876674261e3e72042f5995f1a7075b3932f4c23a8027d0db35ce4322122f489995bcc0b3fa32b7298c4c1b3354766c866a2fc0ea5690c58c5e08ae7037f70accb3ca7faefc37d78883f2bcd768285dd2571dbcaead813a0b8ae87cc1df868e93500d414c4418d5c80b919f73b9fd46111a02bfc884f9d30ee14fcfc1d55d54256b9572afad4777b8d8172c911472a22e7461f6f85aca063c19d6fdef3351149ee6864e93cdc54ca5dc7837f0ead91f5e3b155795df5dd1f933cee8671ffc05058353995019e5f6f55d2de6470605a5411afcd7fa5aa8f38d77dbf496d7fa9c5a4d35ab661aa15c77ce42bed44763166160ed5bba954e470c293ca301363f5b837406ea8ea746057588c34acf266030864d8c40e2da88ef04c49205fad1607d456767d30eadd884359bce04c12e35487bc1885d9b104c9fd4dea4ceaf054cf46cb3c77a619ffe963acc9bfcfad0447591ccd32cdd1fccb1fe7080ad75cca2e17f695ce0095a774327123f21e2839773506a9f2d896bde87dc5e35512ad733aa408f8a49e9018d1013cc32f550c968a03308cdbc73ab444f0a79a13450d4de906369da4c6a675d7e338f738358dc238be4f047579c8ba7a60448da541cb9e57f22bfcb8c26280a59b77edd0f5a009a3ef1e2958d6d3c3372840dc6a0c6ab1fe86aeb7590137feacbfdc7da57c77595b8572b45c4677836ec86fd8c4ca8ac351397aaa3aa298d752754507e1cc514d41c3f1ae0a692179218141f65bccb9acf6244730c6d00829455d21371972745b3665f930cf2aa9f0abebe6f7b89094aeb4dbdf7bbbe794f134b6284e289c995ef2929fc1bd39b259259950de29e57cdec15c4a7d33ef6e689596a6ce23301d25c2ace77fe699d90c2329da4d0f471bc093563dc735ac2fdb32c6995606a67bc953534939ed1236003c004d3b47590beabf39a1e4d5d1b00898496e9effda68433da17d1ab3a32aefa3681aeac116c5705077552649153ed15e9d704e67d8819579feb02d91db0d3533182ff43ee5648f5cc9a595ded4772d61e77bd9bffd6f29fc1f478dea44c32d5ce3118bc8860b254fb0bb1e85223bf709a7c0b9a52fd3914f1b1f295fd246bcb568388dee43a32df45e3c798068608a102143b5511746903255b98238003eed68776b46bb0e64af6c9118ecf9896709aaaabefbc1f58bf45b45768345b560ae2cdbe4d7da497736da8013c4098addb4258cafe7823bdbdd715250b707b155248d39fc6773639e4de3b201fd3cdfa1526c4149ee7d15bbee680c956fbdea844b1470a287d430c5c7e2d7b51fa756720397bbe214c19df3399a989958732d93979e361f7266e53a59bcef695435db67cd8749d258e7d582726e1bcad1395e68d7848849fb6d74451a53ae6e8989c64701102959f7fedc6a5cf8352e218396f9181f33037ca74886fae6e57460bbcb71cbe4cbb3d3a81e2090434eb1d6d5baeee4ede251952ad88001ce047279cfe435a4afe97847f798d84ad79a11bd44f09222d2f3b7fdcc47ff8a4c61f40c4629a0f603193e0aa2164579a05726e547c9081abcc0087907f8034469f740a020e19623fad42e9cea64068abb3d6ff2f6680da328061c200e1f646816a5083786ae5b71728a0e5cee14d7a942379c389fa9dbc7afe7e7ae075c061df11e4587bc90f92f1b077c091c43a25e7b3e870ad852c2883aba2632063c4ff74a857ef7267816317f823a8bc5dcda311b513be3a40e6bdeb89210bece50a608e624f00c9d063e0c8878884e45527f50a3ab4447a9a01652322700f087b6f96ddbe96a68ef98656800eda6563015a6d3c0eb1b6a9b21cccd58cdcdd074b73e40a098a980210ef831ec9e881cb42ee07519fbdfa52d9c62766a2046dee7752f880dc9082ed7f050b49ed8d14307b1b811bd87b6db2419418e49885d20fd7ca8fb45a11a1da17ac2304393734b552b5d02a303ddc72d1f456697a287851f207054c18a6262f5349348c806841d21e11fd4e4ed9c01fce1688483e009930079f7d2045a34f98ed83256dec66400a783d58c61619e6e42f6e2c6e6fc69e76651b96aabfe643ac69681955ce595f4696b80dadd1f3910061be6ed0840d47e928dd93e7c3d6932d3ead820d06e2539d9a604a6b53db6bb599da851de7cc060faa9af76d708a9aaf371dbc3eff0fdb99702504c3006f789a49feb730cabe40745837e2c8c17c77f999333798431231b337357637a5efd1eeed891fb7475f2c9f960e67578adf50241287bc5599ee08d0237f08c86ed9b75b62d612a9353e48cb4cb022d78f73fba1fab7f794a5ff64c97e6c91ec464847a81e5a5253989a1ee54a41bcd9b4b77bae6e72421471a7ddf0136edc59b72402d57e542916ee47fb3988b7123c6e8debddff2df171d4ce61e83c3d41f36143c9df97f2f68639f1bfc2a9d1fe175fe9f45e17e5cfebb330d3f06e15e3cf58acaff09ea576d896359a3f06985765824bc499319384e4c458d4326db801c564b0b503552bdbec60752b670d82cc8fce9028ff24ade3e805b81a72701b37d4ccedd72118b20d792739e035bbacc4893ded88619a6c499f246311947e48684a35406c4ef279c71ab2a74f6e5313f7900080f19aec3a39109d4aa41c930c66c84cd2163f4cdd59fe84a86cd8bb6468bce45a56d09490e032da844e6d90b436dd874c1cd32a75d1ae1d3e86d8a2ef948649eb56dd7b360f55ba5dc34a12f9279945436c6fb83d1ed57ba4ae1d9342a3dc2df9baa82fc9fee927c13439ba5bd2ff9f3e6f577b8d2df731db14c51db8a14bb15bf3e125f1ca4cb2fe856c5a576cf995db5010687d0799581c5e76d400c1855bb46680a631cc582f51c589a831", "823d0cd34e7450550da9716c1f456ce0cbc79431483a6214939266581b0e899e4c95719a09c1ef166a618289a6ee6971b6fea3fe380512cb977823b387ac51d341c26d4a835c61eebde37764d2e1d588df7886177e98e3151106c898b3196bf4dbd83f5f", "a4639c22fc7f370d8500a53819102df5e86c541c0ca10e8f6564e50b90c28f34", "34a04df283c45655a52bdd84", "cd8d1b2e5f65ddb3c0da8f12096134da22ad4d541444964077610aafc1f77f8da5ffc75bee807541cb6eb0526e78d57fd88fa9d9608914cf391ae7ccb8eedb0aa711889f9b6192601163b271c90df5d69fef487b6c05a24fc667469cf16cbd5afd58fc830119fc9f61b26dd50a96ed84c96825a615a3aee84ea4c950152323b20884346b25c9e2a6be3a93505ba059fbb114c224bed8f05f54eab76b2c9c23a0fd942eef9696ff67484b542c8347f1b1fd7df7242872b3528c9e45030447b2bc85eaf191963291e4223b75778335e5f1256618ff87bbd68b5a9e5cbd2ca1dc8aff4625c834edf8fb0d879b1f75ba9b85895a6bb4d7569a41bb3be6cdd020065bcc69b44a8fa335d9418ea2d090d8061e042e8e1a6ac03a6d5525079f14274079734ed42c5c9ab9986f0fee6bc9ee6c485e233e9b4d6de70664902529a135a5675ae129353eb2c00b73f226e84fe8c594272d6eceaca28b6da30492c92074250ec80beddb7208f9b5418944305b0864009b3bbb3dfbfb4cc2bba3313f8f7c6c19860f1dc0f5d7aa06e3b551adfc63dddac980a79d72bd2225d54a87a93717291c7b78bdfc5521f7f3239d5564fe9c9559dfefe76b77efc2e75991f31a0134529a6611ab9ef076491f2d2d81ffc5774ba8f8009dd7e5881e09ddf5116fcb5a44e576aef6cea91ebf52c56c742049639392cfb8b280dc2229252e04d8d394ffafa539290acdd8118656e7e1a4f7bfc0bb689448379e8cedff7590a09a3f5a29bf819fd87297b96ca07431a29a07ae126eb9d65e21824c16707db89868e127f17614a536de6ed268b1600a8b02aac2bca54a09b7cccf8e184448df334f95b9f0221187d56da7bd422f09b4d94228098b563df53414a5a86728962a2ea63023d8c3f03847b36db7cd189ccfef3e623b14842b8cccb18b4f80f01b32a4cec48f3009b98ffa25dbad76089c8700e90848da74aeca81d01f4dab2b7e844a3e48bef21f33c92734b821ab382bdf6d0b1048a9866e676b78ac9398678ff626d5c173a15a0a7514b2544405dd54eccaa2791605c87d7117bc9f8c0ad84623a9d3a2b1733304b492d4dec38f7981db9361b03a2837a95fe937976c7f4341a802dbf583366fbe368a3af3f92618046bb55696cf7af1f465a5a57ec5908621f431ffc762f35abe892f772a60a3f75ad8401321f67981e90083fdd1cce40903ce56a629120d6e13c8871523c4d848664331966298c8b31a5bc8174a8c14f61cbe98ae7ee3e90bc832b04318864d19a9b8b6d49a260f42bb120cef9afbe704faecf0f428d917ead9f020f5e9d772bc8f29600f8a7623d8971c1e3c5f1a3b094191e497bd70f85de124137cc4b9fe0617cb73cd44b89aada072625e25976e7aaa5a8fe9d9e3f32db47d1565aaef0e84d256bfce6aedfa1a2dce5a94976a2bb9a0da95941fb7ed444990b0e0e87627e35f3235a998019650a5e5cae804ecab8cf729a5c712f1e7d17486082dd50cbeb2ee1b0be6a7bf08a66ab3cf1fe9f49c7083f5b8ad183f32fb35fb8a41230e4041bcf0e5ef54bc3d21ecc1fceb08d95d745a997e8f2fc3c0f6b1b6c1c02e03ff02ae0d879d13eedd42d9f9949ca7ebb785764162ceb6c6f9944dcb3927b2f4eab23ab566b2b2bcc0c7d77b82579e88203602264064ce98b5b1ed992c1bb13edce579ae7f5e11697b493749f308b33e47512533350df5c07c3dadff656197884f359cdfcb736d29231aea1524b56e06c92f5a98ea663543f67e44003f5b41907a951dd792468c84c5e0e1b46149a5c9751295e153990b78c0cc712889a21b299b0315150dc50aa3b4f7fb0079ddd39d263a754b1dcc595c76ea9fea6c120384afb38d4bd40491c4689b1afc9dd096dd0327c84802bda6bb6b7a8830bc6c06b308ae9665a8666a5551ec954eb72adb827ef38f036c51698a28c92dc1c9e25c267532da2c04c1bf27f5b683ac750c3ef53a8460dc186331549bf82868f9327422c09afe1cd15e161bc41a70cab2f973efcfc8f01a380b86a432e1ae540e09d404d93d22a20dd5f685a52f0acb863dadea236288b1714700f23d1c19e40e219e8ed21f6a393e541abba850ffbbd4030e5f6567b7202fb66d86cc2a0beabd495814f6a50690e8d74cb8b093e4d43261fff80e7a67ca06dfe808899cbef84c09ece01414baac740cbe4c656b17991868e2a136f4785a0de311aeb18cc95ed33fbece22aaed8cc1e47f58cf6c09a6f92c96f37d2d2485b369093506f5e9f8534f8569655277d0399ddd3d33861bd40c71ac53a44d1981cd744d79202322d47a0228356c0e27efa2ff1009cf2a416fb6e8844eb76b8077a4a3961ff193e1c95b222e72688ba48be82ec5da498e58861ea613782ed1ab50a95b5cc236834af98e61528ab18453c20ff978551b81e1bcc0ff4b7092bdd9ab0b946b7324b7361ef05e1f7d7f6a336281b4bb2c671a95a6ab84be6bef1b9c8c3d2536edb8d79b40637e16d7281ec5243016232d7c9fc07ed9dfcf555055d8ae65f12ad150da81f62f2e1e82b3adacf6d623ee4759ad61a09038905bcf1dbbab671dd28fc1d10a0b7eaaef73a5862ab449bd84c8698d061e79fbe52a86739ba945a01353e0f3916667bd7b4356cc65451c7003927f2aa738d98245760550156dda529be741ce3ae1afdea0de35ada26ac241fcb5d518e6ee7f9930baf88bacf8bdaccbecfdb920f3b26285439912a8902ae029b07f28c1dbcfde780cd2bee6c6e5f4520c5c7ff3ab5448ec86cfb270c39586f80041f3764b5dc77dc5ced0695c89671cf90ed34c4067b4bd938b1493c7902dd94be824810a00bbde4915d138fcc7584790bb0b6682fc0799cd415441ac90c1caa008c7fde3ab4a3aae478c64991ebe07e6c4587d3046c9ebb8e125e795f0be9266bcee5a4e4355a2830c5b34e583b0355b34b89c08011db6f6b8371de003074704e8cdda37ce42c7e395b6a37bae3dfbe67bcfd1f125c9a262d56883ddc028773988270aa30c6dd326cbffee589f38286533e1d5c9486011170be591beab5e0ce98837cf91f0a58d69d872e364aa88daf9cfa71bad167129420282d99ed5884a1276dfffb2c4100c74a8b863b063c07937f2e9c12523deac4ea16178863d975e3a5be5efb5ffbea994d07f7ddc5326bed1f5c9415c1d4ee1667e3a581499bb573595158636ad94d84f7c6e4b8efc2b141f2bfab7932a050fd88a8c7b21877cddd488543db5b11138cc808e1248b6e2ef492faa8a32f9d93e3c060b5cec10f03794248f9662ed8c283a8e0eb493824e2750ec75b3b1292d80ce002083a3c64cc487afc31b20f84a778f386b012ef7bef46e638d0f1cd75487ea46e05621d608482637b3e642a9a2c5371bead4386eff968b3e007fc263086d8a930dc76a8431a4e6907ae35c7b3291075d1c723f02e4895714803c0e97d65b04c0f27d01d5d68001bdb3bbd44dfee1eff1754fe8c182cd9bc6ee273beb2a444ca1766f747d86f36cd8cef6eb1dafe0c38b9327a8cac6e83e076099188f02721cc4de3d940c3ef19d9b067be07b890c798a79ee8c44d96c5e05ee5d5202d941a674378386233a83bc85134dc8c46a7531b2b952fb277d8089cfb13e882bcf7545f0605271fe38bf4754f98dfa13fe6b635a62bcf962553882a8f28a9a5fc0b3f85509b702d4a7555d40c4f7d10fbe80d48b4826995fda7d15f14aa9b95fc6526101cf09c97fd74baca6bd26b4fce8a57b0726e0f68118969ec067e9ca39b2ba59fb0d78eb5cec5b872613b1b76763b3217d859bd6d991bbb5448bd4e49dd6597ddec9e46afb3f71d254aba828c91de51904139ab19138e36e6996a207da80323d96077c97a3e8994296376d4dcb602f1e77371efe8b020b7b6f6f7bd2bd733ad9c06c45b77a2893d73b4a8a57707969af74ba06b2fe7d4079bcad1cfeb3689ab95c8b1215fe0a855eb431f67df4ea589dadbf055086924e42cb142c9031e25b81e8e1167a54008ba1ad7fec6794f203b27f3092dd72bb766c9653a72b2e25c965f53487cf3baf74eb7742702380303af8c0a61cca3eec78d4b709e35e2cc5bd586263d9f56fc12454547bc6165e3f070ce7b2bcace5c8cbf52f987568dd90237cf190dabd4ee7a80494692a5379b013611f4eebeef8e1ab9a9c5ba61926095545e19c3dd61b7b404230729aff7d82b6bbbed6b4a926f6e49189e3bccb578fcb3537951fe9c78ac842350ddd80133275ac0bce3a669183776fee8288f874d29190b452d65bb7d8edfedc6fa0ae147102b92041af6dd8a566932e016763b60a5b9b1e3667f228cab075f966d1c525ac19d12046c6409345799adfd7154b6d8b51eeb1eab3a132ac6a2e08acd1a34bbbbdd019195af9f8a93c6ed5463765173e669cb0d42b6cffee1a4b45987853d43c02f920819f45a4fe0905d8c65aca182b4bf56fa0dc51cb53c642fef003d92c13ef4bc1bac571cbe2ba3673a49694f6311b7dfc17a4069759177930b179748d4403c7259e10a5d221cd0a6b745966e598f894e607b779dd5289fbdae0b4348141ad373a62c76aa454b35b39a7be875598bb30007fc300606ee2537cfcd7c22b6149880fb3cd8eb53054d698a0d20f26a5c3ce468255737a68706784", }, { "5622aa8d2f308dd468a7e4959ccc01f0e80d91f79df65b8201eb44911f6abc758c6703bb97908fff377395d33f96c328a4541f414b7ac34c6607dd85729afbfe01feba988e4997c6bd2c99fcc35d2467b143a8fcbe6b49247226a9e4c0a4e3c1a29d5931e6f1f7a31d90a0e0edc4479f08ef9bc65ae4eacd0b93b1cb38948dda31e60b18d702bbf5935bd580201d1f280cbbee679fd834aa6be576a37a037eabe989c3c18c7fb61fda8b9ffaa8bf22b57a101c19e850c454353af7af3d755b26ff1ee78b9d9daa78294972d108958682a5a29c8ef260e2289ad9d7d74f32fd4e51e5d9ee828366abccd97dd56e035713a6f3a1985383c0ed5d98c4accac2fa1ba7d30a295670d5224952f7b7554fcbfb426c9496f054834dec48f9b70af3d2b1c6dcda1c4daf3e9601364e57851952c785e65d753be1c22729bbde33aeb1e4748dbe90da6ecf716f05bfc68ad819515dffafd33a909562b95140ecfff1d0747f8e0459fcd3ca6cd8893262614bb4bf4b639285f327e7ac782898781968ec98f6f0f2f3c4bc5f9c4691ffa7ddb3662816f8ad092095b598bd4d10d6b5fc6fabed619eb11dfd4d638f4c0b6cff7194156a411e8ad6d3229320336ad52fd9811c3a1fcd571d1bbbac67c6186737ac7ca1ed9b2bc46e4e578f81c164b09ae5cdd4059a2c22b5e7ce1dade684e49200867f9bb1430aff9b99805cfd31f7e3fecbe898f70a4eded86b8bbeef7050eff6cf8ba71395a7ae2e270a2b58010e56cdf6efc4003da3d8a82e96979ee68694b6113cc9a6e377d40a810063830eb95005a81405e5b7de8de67424845bab1911bc55da6338513742d237a555465fa54b07ba50ed712e7a57a39fdcfe4af50f064ae969823aa1c40cd86a621ec90769d0c1babd33e8388a8bd76689215b9827a5819127bb32ecc80a562a291f3192eff34cad2635e5b0c0bc174add72e2041864953f1fc72be7d28111fba0438d9036da3d5c0f220ccfde2319bb96fcbfae6055ed7f1c1967ee9a78e93bbb77cbf151084d602a5a2f087d49c3134582c1a5d7af24f4c88be26204cc9dbf4368b19470fef49a5823a2d66c65e9b1e8ab56bf5a7bb3220696840a6222caa58a7b39fb792d95d25038a8bd9d916e853cc5459640f8b8468e3d51f05f1b95e996cee40ffb7ae14cb289094f1b77d5573c1aee7c12a6c3a1e31491422f272cc5f510d4f18ab63d3c3f468c5abd61b2fa7ba0768d46392e2a4dc06c7ce79841dca916cd33cc0a700b50fc660e5d1808d8b87e65feb89428055495823b2dc317d6d9e50aa5ef7ab14076174ed32f56abe7d410e58ca40e92f8a31433d0d74ba7b130b1561f2b075fa11ead744d031f34d82f1a64d428f6cccb0a009be24b42937bf3e99a1ef1fabf0fa7335dab52918382abe756d3de229ee8223aca6d7c5de87047838e387d4e472481a4cfd4365256e13aacb518ce5300f18dcb5e0a28477a6fca08a74756ef6bd8933bacc98d02abc7ae60df7cb3e06d41abcc4bd313c543ddcdea2424d98ffc6dcaa83658aae11f5841ffd4f5df42368a0e815d2146a0fe138b223764b133d17cdb08d485e9f3dd2bf2b220d1f4565b02d7b9231d592130e4436849f49b1a70772244fc0c38da372a8c57fc80ad57828410a5a16ac6d14e093997fdd5b26e4cd4b248e0ea221715ae6e112e1b68b09f795540e31b1231244bc922207b906c4f42b5302dd7474286b653b4d1bb657134bab117d6c349fa0f121c2f8dac9cdcef510c1c28545eae0ab163db6cc84ca182feb858c10153d0136f00a01c9c7d0bed892715dd85c4e73627c3a2ef0f43710dfccacffd1d9f118c9fb1a83b2eb328b8da3e955f027d95294038184f7b895d77532c7570cb86fd6b37a5a66659cf1e330db3930f302838706050c0dcd91d532d49c89d144e9a7f864026ec99f50acc02bd5f11ee88495ee8991ec4723b189f84e03d992fd718b5173ea1b033ab7d3568dc4656648fb54d28d3119b0f293a930a772c394f45ee66838f17b73a94eca27033f9d5c2ae22eb813386905dc024673850a087958eed191d04d05798bcf909eff2deb2a0009d223323b290e3d6f71b2797a2bc2590d54294a5992d629336518514032614a04847c3fad8a7d1cfc2f86765b48cf58acf892f68b691fbece38100e6a71487ef5c4ae934f1ba03b4b26a1967f70ef1c697202e4eb22a3a95ab3b7b524f0241ab4d2adf3ee5e3f2974d0bfe4419ef0ab11039ffc26339570e74d260c4d5a16f22cb4f60b03253487f5e46c47836ce29460728086a615f78d631d89a06790928455889f58adc3d0a3a84ceb2ba9cdb00a403080e6567873b985fd59fd9dec71e375013c12c51cb67d599198f36f58fdaf897e85dfe6f9896cf6d35a84cfdc6834dd9447a2a10e1ffa9fa8edfef1db9e8b4a245b211de49e04b7e88977b4e1ac9285f43526f2452181ee0f80efeb1f6b2533b656519ae45652ccefca81c17714476b497e5d8e9fdf6c9f504c7a7fa7afa36df5f4f8da5b4b973b1618fc8d2d43e866b235e5420551d1659e5bd545fb78a3e17d9cbbc8e842f3fe6be07b892453ffd689d5188f26f9e4c545ba0b3132af12a03bce6914015d026d3d7df661c1e6384bbb50dae24abfa78079a2b1ac41c44c7d82a59183f293f12011e781d3cdca2f791afa5b55a9f2d6139587bfd74bfc54ce91e642847a33b48c1b366fd8f08f520b79ad5113a0273735aee71ceae361a97547fc09b22fbe4e4ae4ae13e52d65e0971341aab368d1e917c8f5f2ac57ac119f981b51b7c99ff2be3e16935b7c73e28fb58d332e6f2c36281228c479c4d6095cf15b14baeb0769191dfc649a70471a25d45d4433797a5b8ba31ff567e60ec4d759d99244d0fb5dfef7c2896809938ddde0d2015a4c5ce5ef6cdb5752da1c2a33e5bc78b6b7c6a5af892f0792c28560a357720da3cee3833bbeda8e98e6a8cccc6535831cfc28bc8557b4181a3978bd90eabb34b99eb7e55d9263e6790ca34561d8c87ec4e12b4a38df524318db00a9b5bbde6f5a8644a818a88e91b521d716fa9f95bf70b109b9905bfca926fd42ecb9114c039790abb0392a41ee4c190536a89ae6194befc2dc4bcf7562bcb84f65c99b69612c0511552f53436b6c489204d3881e1f67e0fba3a061165d2955c2e2e12c440d31556250a8a5cc04ee5e09b1d627c14e08bce1a92df7f6475db92a3ee57e4c16c3ae677c44237122818ad457a29595ab528744707f3ab7ccf3d20bd94047e013e647802a7af14cfc7c11441ea6e9b9f960fe69d03911ad2cf3a8f633e0d647c71dc7e188c92e75353fc953d6a30dd0040c39d4355b71524f1a4872fb1ecab22c8293b54bb22a80e1e3d4c886d2988adec26f041dd0565cfa9edfe5ad9aa7da1d3b8f68fda9e9df9dbe98148120af6ff30e6400deca6dc9593dbf06c856d0d582503e7ffa185f87c6e7ac58184bb80b4a1c0c18d669e23f9791365fe807356a5763ea418c39d94311759b29b14324fb6f3104359ae66532779b825f92b7c9ea2ba43ba7de04eaef7a86192bc93e17286f1b6e0a01c33c796ebed8f17692eb9237173a051c14e4869afda2643bb98c9ac4ea94c6bdc1401c80190df6abe988d2f0b2d80cc7bc8362ba25c6e5df4370a43e156aebd6aaf856b3f64d5fefc622d078faed40b760a361966a4765adb809dbcd74b7a41faffad3a64823860e5656874133c7f8a46b5a3ac591906359aa4f171ef6bb2ea6b5f24cfe25c2fc7c1973bd5d3bb5f197002c5ca1bccffb570f0265f5cd949c7386d961ac9c5e18b5d1d6030d8bf4a48c10f12dcdb11924b02b8ab5e91f425ca62bbe42b80c6b6dde3160ebbd55803966716734327058e29bd39874f2eac199067fdbbe8c372c5a688d3615e2b65f4937b67d6a26c64cc2a9e5379cc00925c678f174f538915f912e85b7014c064a73bcc7ddd38e1a9627ffddb4bfd6da764fdbfb45048c9495ab1a4cac5642f6c9ffbe97d33cb26964a23719620df3d85dcfc392c4502759fb31a6a797e99e51e94cf9bc79ac15de4e5cf7a05aeb88a8ab4c3b6f9c52b99794503f2c49cd7e230a67df7403e552523249f29d257b35c0c7712053c3d9eb583a1a7473d7f296d25a66566e4ba8b08de2a31b082e40c8e5b1e93985b324dded3f52511744e7e99f4e3ffd99d8ae17bb5122b37f637c5525558eab18a378f5e2cb56fa003ed3af8d139d16ec4b2ea79c415b0ba4d750ca2cdf653582ee3b65a9825fb9b123593e36e645232163cabda515b959ed0a1419e9894f6c677ac200fd11babe3503ec7bfa319f1b9559d94a6f82945c9ca8667621a5d28920949a1da644cbdb58b84742e9d65e7f2027b99fba4dec46f642bd17e88fa109143b26ba7fe285c89add0b74a369f3d381ad633bfb4f72e1822ff96aaf9a73b3c59a6e457cf40e17c1198c64737037f52d9b3118daa3fa5cd3e3c7738e3b3743c595893289974a4aa0d6bf1446e70964823a7d5cee67b9b25b7125d9ac5d1d61f2a6947c3deec6deb575e2fc5cec60df26de3c0545e5b79156dd6af33a78552d1ee9994cc8501b7dc5fe7a22eadaf201a92e06ef03be705a8bdb4db65392d3628c7cbf44cccac292c93cb5a407a7a5a0d5ac9fd95b0033d6eb719d3f14609190dd40d5aa1b983cd4c4e278cc8a1e7d5fbb0d39060d6cdce8de6a17e2dab973a7fa594205e17edab6514372eb51e03b0ced6402fac0efd3af49fb8214a505cc9f5f0ea5308d7fe6dec369ba154", "9f522375925222a04f5c95ee14b6386412025903ecad0bc3ab78afe1145136b3a3592835ab4ad6faa66be9", "d1ba82b3ced3e9817642aaacedf482e79bedd0560ef2754215ee792514bbf8e6", "bb21211f342379370f2642d3", "1a6683805d3f478ca1c1512b9846468378f83be27393db63956e151ec408368b47334afe610249182f54c4d0a01b704db2aa90a9755b8feb67ef9301f0715d7d6bdfa5cc4497cef1142a43eeb42f7c413e8f489af30d742a706d05a40a0c4a5991f9e2cc5d9fbca6ad3767682e20c146ac35aef38dfb2a77388b738fa022158d5c802e5f0761096bb45b50815ebf09172759521b5c5d459703ebe9ff669ee4d14a86e5d0650b597f4a082ba0aef366a924ea378b91c3262d99f48189eea19c76c0f644079f8415c11033cf24d30d6c149ab13ca5c29deafdc816e457257361c1af4b915da312d2e6c7fc712faa27be3e67c893f9005a0e2c28369991c1dab22d38961d1abd6d94c4d549cf491aa1f8d522be3ffa6d214825a5fde3c94c4e35c29b8d05b2627eb12c9d94f450a85eec6bc963a279a37c2344ca36eb604c4bd11c2bf2ecc0dc16c2c365bbbcad3541bd54f8d0bdbb3ca4a087b62fc19fcc1c13984eab807d2a6a1386643d90d412d027bcd0a638765498cdbb1f4cc1b91b69bd241eab3645f225ece85a56e5008d6094041f8cca6b9a0ae3b15585de6fe0695d79d348f8619431ece40e736957a7627224fe92bbe30df5124f476d97e36b5b08b3787e8e00f0c10013068eb156f82f3494a35d6edd5f7048d1e91954f1013ede22eca8b4ba41699ee08decedde87139180a567c6d169b672af0f12aa09ce20e9cac4e78b8067d31ba4f63606c00d1d787b868cf7643fbb170f8074667c9f7584d36af80b4e6557724013618c28d0dd40bfe9d4b25761b3c99558af528c2d290d04b09821bd7f992c044dd61dde9395bd0c9ddec6d0bf6e044ddf0b4b2d6753f5acf2e9c904caa4e9f310578527b85e6738803758da646919989f735b09c9a5744e63fed2c3982e59fd29d2baeb9771316bf8d29213a4956b66c78d5654436ffdd82d0d572530fd09507b988d13fd743f35333237681f8abbb301a8ea870159f802a57760659094d0e4902036c5a62c563f1fc86c4238e1ce89f5176ecaea194ca112fbdeefbef4fa7c203678cafd34486fe58b2af04f84a1cb620c6e123bfd96301e0a5e5e5abcc95d28b852d0cee2f51faa73e42f22fc335f50de4c3812ee14038633a195083f3944284c1086c34995832c3cceb7d385b4ce86af10685c16005495121105272d1d739c584a07ec7801c3667bb280987a8aa41f9537e9d1812a5dba5b385a0b71d2e9573c6f3e9ebf0bf7267528946a6aa6f43efce908d32525cdc3b825bb11c7239f1de412704d24c17455b9382fd6a873180f0d5d44dc449320973d5cd0d4e67e83946b6ef47e5fc3dabadd80751f1421404e56b1bce748b7bde63c6975ca81f3eaf52586a55242c9745dee3f7c796d4508e818eaa4fa50490c1a79624561b98d2e1139a328806414c905372356a22393ea0da51c83957029edd8c2dfcf46d9564264d74c1c0497034ec018b1dd4c14acebc34b6d2c1a616937c37b8b4a0ee5dcdf787a0de1173798ab929b72e0fa83a6c9b9a99d8024328d9c236a8f57550a4f83e8071eac76adb55939f85f5b5f514174b670a3e8dc2b54656f6201940a81fe4953d2680ae4ec58635ba74d15efab3e06dca6ac269711ef2d4dd49f731e24a92a3b935ebbb3fe8d001cd4062669ae4baa62c2947033afcfaca227d88a11769f87456d5cd1bb6606891e71d63aff9cd5a7d23263a78768ac2ac54ece1441fd37d096cd27e916e68891137fc3cca427febd1947cfb4d7ccfad75b2ec5e809c132111eadf25a73043d68333139bd2435de9941bbc61c5c509897cfc19a21645019eaaccb6d06371e3d0570c09c7556e41a727e44d9bd672fccd1f89cc7d58761c16df8fb75fb8a1dde2caaf088f02dad91b6489114398740e6798f3ea8c7b0cfd974e160a0106d703d9589ab09aae79108e3212f19cb950ea9c0798a1532bc2a065d5900a12054395c0545b0878ac0b1d461f553dccfc2a22bf254ced88dcb538e3889549960b77ba6237ab1458e158f4f46606372e797ec9d9ecc6534acaa1218e7540eef11030bb9c3e5a7816f3b33a590d970619bdd2dc04d5c6f4ec38b7cb4d525234b836eab57f65dd045e02367eede9049e219b8712b8d6fe178080c5f77b821f1a475259ae571a5578eb3b48863162d45486f71a28ecbcedb35b320e5b6401f9e7870aa5418449bf47502626e1f42abf481b48d5a6819c640bfdb64f873d583fc4e40187940a6c3373ea7b47195270a8657898f55568985018abcea9bce1c155d95b426f91a734b2a14ec2c7ca2011a4d30019fd9b3ef63a804e9c30c3de2651c4213e90285a4ba100b31ee402e8a7f23cf9d4dba003bbf982526bc63be5af102dca34e7d362d6fbf6f56046160d7af33b364f2a86074d1c0fdd54aae89b19480efde2a9caef9de7c0f9491e1cf43a48752cef405a0ff16b0fc67bbe433a3c1b9661406c3726092efdc076febd60c436476f24dab1b0b8f8893986d951ed72282990e8b1526f4dcf539b22c01c6a7eb5577cd540a16a81296ebeeb7ddda72e60fcf2840c5b42c5cba30eaea5402f267d1d04bc80da5ef0dd2bf3c7a2be986507617c9bdbc96c6273a0c9e586a0c48c98b4552113149c6f79557fc8ace0b1a512fec3aa09ef191f95c2163113ac5cdd940f0c2120509bc53c3ea493c54703effb902ef752c830c61e85636ca95429bf16937bf6786b3eae1b277bf08dcd69f521a0078d633beb33c9aa0cb33b238e1021ca67df122a403a3698452740bdcac81d22ccfe4ab5f835d1961708d1faf6d40f115f16c6094ea37a7ff15e0534f62c19a6f4ded0967be337cdbdd2a7c58ba16ba2e4c3686e9d075c6fa7d29b2a0335ab4940d2a95c4500295f4db84ae65e46c54b7300909cc5411c725a31fd962d239aa0e2007c285586b4c778e2ac7afec42cd8409a63d7cd9c677031f43f4aaf04258dcf1270c02a4764177aa66db2d8f860eeb1fd06d0b27587537410bcb641f90aaa7bfc6f12bd143f66e7c933a0f3ce6b5048913e1b2d79eaa6c19e7255d5eabd24d5f12426339541a22d600cdfd1781a1a3894740887840aa82e5a461fc324285b0223ac9b95c3eb88160353f168b3d4ae8a2e87b7715b5fd2671f66e6eaaf9365b3d9e3acd9a749faefba6009783771177aa4dc91f72fed7a5bf6b1b7738b84ac0a07b4a5a3f0a9134a39e1e7e3e2f9a92d5644295f31c5a356092bf07c709b4c34305ebf50e857a4f593dd1cce0439d3fd125c1ede1a48f583bbbe0eec7058345129ef78868a96f8a76ba7fbfd1c5eebf75f3e0eeeb9db87474b96f321b87fffc02433513fb467fb74e2fc8feb498d51530c753e9a173e95e0edc5ba9802641a45db281b2e2d87d409057b4fb1925e834e90fa5619ae3a9237d5b104e7ac67c2bdc31001eedb4ec7064b2f72e0379bf8780f67ec4b195db014a2d130e77b1778efe3dc703f1310a566a6d3b5c9b12b1d4e25815493ed1510a516a31ced3b64ca49a783ad63ea71a57290727fa31386d2fbfe41f12d36a618c6c28d8f10405eb3e0a33e8ac2e4133ba75c688c8c9a2bb33c8fa032eaf3ea0d2c27bf89269c4aec55f8232b292e7fa9fc24527184f19187d9d8a3f52335e2feb5dc6d997b9b773a79a31db832b752e5738963ee5d61a1b426414975693f986e165e52d46cb059fdd4f48f008e96d4c1a48306b7c002fd0c861721656074cf11173ca65cbdb694c79f58a3f3365e872b24670b691682c10261eb1ffb2b65da031d070e31542f49704b77970a78bcfb4c4ca517b4c966a4e8e27664704f633e90cb7d7917dc1d3a8b8b7fcf59ea3a8a81305761923cb182cebdd59255803a14ca8a75fd007670d79a25eacda1138d67a0fd1da981529dbf182fc4d7a700ba498e4476a1d415381c9e2ffa3bd46201cf2e454c4aaedbbe3893bb4121a6de02cbecc1f319155eb8c99d1030103bb6194bee51e74fa01f28dbe16092955b9599d5c1f1c3f356e26d48fcad7c4cdf0eef25c25273dd62171785c9d2c5a01b1f3da9b4786b1b399d890e2049b73c12de2fb7177f2bc3d9c645398111ebcfd83b73119897bb994f998f4a6fae1b3d6361e171059dba0bf9de9af7a5a1b21641790baf82a36278945d649cf5d310f3792fdefe8c58986a48118fd94647b786e47733ae703701e18992bc1b143b1da6110a98030bb9895c14d7b8eae1a155a550e219a5b6301b6d26d7956ecfe4c7023eec1ff62538b3606ebc7906a1243bf8357f593b6cfff32e3fc6b51f6a0ffaecb658d526f7a5e9faa6294e4808b779f4832318cc184e49e8957b72bea0d67366e040cf76a85889fc6b04e84afab0d02947d0d83e0de19f12966fa8372f6e82ff402bd7a69195eb1a7864a3375aa9e23736fa4d4b0224647e416474c01f72b7d4af240d7f43395b5b04c8fdef1165ce1d56ee8ba0e350e6ada893e0594facbfb5f0d8829ae203929525951584c21371b86deb0f76ef5daad5e847135a6488b35ea33e3a165fea502975d6421d4567a229bf3ce94605885453610eb9c82f9ea743bee9e14776bc3076a29af268cc72d9092a492d9ff08c345dc2eb2f8003b561d9912ae1198c58107f8b37a08b35075af9863110e6770425e9d59c2dfff9d9942c8bc3bf7904c2a952bcd573706caf1ee14420564ffc433c0f5871c4bda916f2530ac75819ade49fa1de21edacbbf6b7075dba21a84989411c566b7c356b81803c7215ab0f326a6b8910dbc62c1bee3af51f105fcdebc0dbc56a50b22cf81eda563bf8c2eff98b476e8", }, { "99444e82c6c4c47070b164f298ffdf6955ee5bcb3070b9aa95ce658db4db084d2056cfe61a93568b44ba7ddcba5d450f4ba0da7b119425a6628b3416663c638692326cacc5c237097db5e537122b465dcb21d8dcb5fe831789b72deff3907685c2e23187a56990221e755930a09f8d6cc065487563cb8cec82b9dc754952fa0b342c92d99522fbb39854e338f470a4b4d5ed2a39b8b6253b7001b0b953abc588d757616c7a5d1f12b1024aa572ef5a47dc8480943aa6cfaaa78064fb2b29830280e46efa418d0cf38f57980146f2482276c9b6b16f865b1606bf1131e894336979a163ba2e70adbdc746be0d38062fafcfe5603e6bbb55717b66a263fbd5cc7476302ea4a0dc6167221f745a26a309f5886934f4258965a0ef0803eaddd05e54008df8a0695a078b797be59f1eef95a658c99a7d52001d4108212ce5f18a39f1173291808c980b0513f1a531e03ad7380372b65572d3967af4c25fe54d99d664cb67e557fff05c12e10143c13b1bfa3e8db093ff832a7978ecd85d3971349e3c9b83939b73f0ad55f1f1162d0c106b99c0ff98442911bc15e9194f5b4ded97e9702b84e31b31380c224f392e5fa5c720a45f64cd7020e25a3931b5871e4c708e77f4729225aa9f48f9d876597d3e79219dddee0efdd16836021dbd21692dafe121217347cc128fc5eb051e6843978ae17478ef714957a84c74656ddd931cbeb43e32fb0a448acf2f90ee98d38522b4fa9aa36be4fa13306e799d4c0cb90ac0f73cbc018146d1b0d6bf48aa446a5e3e0502aae9fcbd196b36b6b7426fc10367febf687f05392fdcf878863de2e47be7e625d0e3e3e94e199f055c0fc65f76c41ede43231873ff10eb854dcd6ac9b550ee8533d16f81eb0e86471d4da69311c47255e78ac8e79ab36ce880d6b135279fbb5a712adc5c3862a356af49e9c10d5b16f4e5dedb80914868111e194745b802a0292c7c8564de28ba8e71a44f7eff6573e5434e65d496cde5b5e62cfa9e2e9ac85a164dbff5767983e71dd2661d37d9027a27674ebe3433731a606db88e0880e91ecea8134421962b3f68915c9f6a5e1992c56750f99bc313fb30cb89384c72571a1a6a5e3c01897b691bd70985352217fa8a67f3252a06205bd1a9931d1cea3736559572561fedbf3ac4c8bff9ebd7f3753ee69a69ecbac4be6357db7f4213b697a828edc716ac01da75c1d46098c7d5d6ae6f3f9a2903588c5b340c9d47c234efea21b700cdb8db4279afa2117677e824e627bf0f2b179c864ba823926a57825478395545f130886bdf2a7c55a2647a888c3998b750343d9cdc602e46b7b09a2fe9ef74db1ffc46fe27c254c927ce51b307e96a571da7f3f907223fbed2daedbcc96197e95edde7859f3b4ec6099f791089e368a68a5ba0917ddf4f50b93c0c839ea36cfc8053811f8fcfe6986e5fa9f743119ecd6c3e5fea1dae3ad7eb465a89e9c68569190688a8d56e4143ceea3b11fbd9de67173d5134ec8b0bd7d16560ba2be52345ebacedc01a2e03e8183ef91317d87b2e15cc6301586ed829d438e4ff1d074408b332c8ce60ccb6790ab08c228807509dd4b39f2c227755f6b039f5cd413ad6f46c9ec2cc6a79457529d297b1d9e74ead9bedd9bd652fb31568a8e2a9e2b89e4e57601bc1d960360232cdb30cb502b950ef930d54c2c0692a684cd44b0472995bd2b41dac1553ae47216253d6640d2653a033a862f3118c5b5d60a662d240bda5f4da51092eff514f61a425c5b14b19517ec1b371d240cc30a0739273b34f18a72a69b1586802a7caa6cc8f5817a8a995695d063c9dd26c3d45feb0f84dc8a0773151cf9a537664f942f351599cfbee0558f441f5c7ad320cabe305f9aba570ddf6407749b6db42f9ce94526a8f4170e735b1dcfc5f0e090af10e039db3747aa9b4f1f26acc34639ac8b60557f7753e2c261a29852932901a4093b7f307319cbb228e26eec289898b3f8ee236032163293b8caf64be3f7ffed236f1da688d958a1bbb79dd45026884904bbb936c1ebca7aa6b0c68aa8b667dc1575729e4ecb4ffa82ddced2f4571bf902c52fc4a0ea3f47aaf5c243ac2a1fc19f825fde5d9fc8d06d97a351eebf4ae1846aa62554d57cffdb3f3377695338f8d598d723289ff3962796e8065632e7da9d8dffe2636cd23eac15a60568eefe3e77c561906555268cfc1e9342417b1cdf090cc16c79939b15a9311b0210094087dea22833f74eb0e35d44259ecf327dc84f3f24b8c2bfce7be0d97e00d2be88a150a0d557ff963b4cda60eb99935951d288768b4b2649b717133517f5e3909744417c9c3102c77ddd285976cba2c89e2b4f297665632d7c8652847c4625038a6670169772de0550066ec6c2018f503cce79a333ecc0a0632334df6959d2e3b052fa47c5c84d15ceabdc80bd6be0ea2a5a8d5e374e0e9a613369ca8d4cae3d9f98755560b27b2f6e47b01ba390f5ddeb732c22b12abd225e26ecdb639b08f3237e488430b3b39f0b63aaaef4907cd003a8f2b4c3bfd721d6c3fd3a5f062d72746606a529ba34251ddec4026f40d262e9d527ad84fecf5bb2cc8601c2a38437098aec2335104842ff1c455e5d17c136ece8d461d7a3bd9a60339c22d71059e09b3603c0565c0345684893b56054ec4d3db0bf15546cafb4a03bd7775c3157e7676bb7bdb7baf3100396c563eba1a12952503eb6ccde6b6d0a42d456743c4ddb97f5994fa08c5fa41315080eb6b928090956bfc6252b232f6e0785d233c3adcbb9370b59c35b0dd66005d516befd1fc843df8e68fab19858b91e2aecd1c8a88b0fa3d4c2fed2995ee87e65976b755fbf44ee183f9fa08848bea325807bce0b7b61e03e50b2c7af9b360532a17a8250cf6068fef0198738c82a5e58961c54017e343fcef7076e823d63b4deee472fada7989ca7a213d06a4e3eb2d44b16e5c94b1588321cf6c45a5a792938b058d667e1730f8386dfedc50ea0a959b78f12f2949b34b181f90bec622515227dfb8a5f6e89d2e559c0ba686153b218d2c50b67503018e22914ce9b49d3bdb7cf38172db1ea130baacd640c111614e3db204b3b50641d8978dc14b2afc27a7efa819cac6bafa8166d1c127e2237520d57ad38a80146217a12363cb1f8a720e328cd8f846d379ada43bd4865e4aa633c479bd448d205b2e43befa63486c717af84a733f1dececc127c047850aeeb8ce677612f5966e23d92c1d3c758aaeef82f862c1154fadd6766e1dfc780bb447732a5968c0c78b9af4a9d669338458b57cbb77910a24678092857c0b903152035bab6b1c73f7b667a08cd0d31128888de3ff1fed24866eb60beac19c1b139f77bf0b9332024999a2d56975e691fd7475fd93622119d0d725bb99c1d6ac604d6b6be09d6d29360fff9f84e5318259a67fec08a006d9772b9410ec6abd4cb828b898c625c2fc35c19cb9a6cd3b0073baec7b5af254d21de8e209539f560bc80ea38e33658a68262622cdf35dcd6618b9e272ac3644c91f27d372c6297d8e37201c6a86a7d3accdf579c15246276a0009ddac4021755f4848d10f714e9da86eba13f461e6a12edb1aef2d6117986120750d609682bfdfcb90ee3cde8be54d45f841a6dee2d5b9fdc4e65edb7ebffcf3cc5c8a4e1c6919ac57568be23bd8283319ce11fca3caf968b057432f163f22e29cac30b8154a646ca0ef4fdbc7770ee1451fdde9e9d651992d94c843d4eb2570975528ad9f8c193f7c681a43df28242547010e30d75fca04f39247c77d6c3715c25fc261ecdba16844bbab23e4d0482bd1565ca9b526ada9b8f5703661a84b23070d85f3e8265b2ce10750c5d798f1a8ef4d51a473ff4d2bf4be615566ac796db9fe61a224bcce05c31ecb9ab7bc43a609944a7c9398a7875609ddbcb556296f548a117847df7d0afe48a5b504e85b0d7ca589103d3197933a744fefca795e1e036f964a4f14554d5cfa0261e25d6e5e02f86e402906d3637a2352459cb1639f20faea6f0e3fbc6a39becb1b1b3a791e32e85e5bee31be685410adf0c11190e20b7a5119b90e83f2cc4f0de8898606bb6e64165c95d4c5eae472daa6836a888ee4d9a79de72b8fb47a9c9c0323a2be9106d4ee9ba8b3858c256032a9caba37af94df4c7b0adc2f8478cb879b6d452d73191b0fc1ce944df3f4809cbf3ad46eceb3ba4abd9679410f45c8aab20dd72626f235e7c0c934b4beb4507def24ebbdd7a507943c81d54bc69df578aacd9ed0bfd3b7809dec345ba084d88fa9c34d80685415a4d5eaef9b88e51432b2b2037186baf123a6257e47aa56d6531923d38178e8264dd315e95bfafd8dacaf901e354b0f58f135d638df2c0f32453205c7aaeeedf8c102e11cfddea9a98d3ac7c385d71b760cf2afeb1ebe1d64f0222b9b101893d11a74ed175297c1dfd188a2565fbecc6bb07b56ce3973322a965dc5a675587890cc65a71efc68fdcdf1a023505ef0bc0e6b12dca5860fcf1c6c94c2e2ec3a72b8a019d69c82d36a73738dc3d17d7fdfe992bc8e18cb5d3437f1f619dd318b95d1a56b6d273ed79ab2655d83e2dd63cb6f1f5987eab6bb21a7b13b84e2c619b36b842192c3f82c755d8af840675b0bd67a655d641b1886c3c9c147ac87615ff3e58085a879b21dd63c1616a3712279ec87d650a2eed665b797ad631f0ec312f343979cbc49b99385cfa92841cba12d52777df565545a1deb07800a15431c0987b4a543fd5ed6832e80ab6f4b4d9c9ec419932a6ded4759f5c7630a0b80139234b8d53117acb4452c60b477ad50157169a89bd796e2308baa9395b513a94747611c7978c82dbdf48d716c3ac181ac2b2a4702c02a324bd4c5e089d989d020ebec9963b5c721a95492158f54973b7fc1828181acb3cc8078ac095136d97221c60b847bd2a52427383ab68cd1f10b92738c13203fdfa0b78baa09c1837be2498667c459", "0ce980442336d0f427db869a6799baa6785b5e030567c588e2a7d2680e96c11b7f415fa27730969e0b1c3973b5f3192d4e773153def6dcc09dae29ac44eac7c42c2666a356fd4262197bd5cf6eeefcbd662d104423ec05c19a2e6ddf1834a3445a09e8b1062a1320a5e8ef13d6ebd03c19e1813ccd86fd68b46a", "1ac8a509db7bf4acb80d8d394a5abf47c273b2093f50f35049e749f3e16cb0fb", "47cc9eea11f9f3f9aafa23bd", "088888333340b3a057b05491fb2402301c8654948aa6d5ee1ec75eb045858c22056fef0873d6675f897126052923a47a30675b266ffb6181cbd29ce2da3720e36a227e4c6e53328d789913c0d9cd149a6e49293996b1be7d6c513b24d876445a950e723ade3efc36907c840b9b8cfdb1503811b4044d931a0009b381fd60a5bf1e73d16348cb57eea672709875fb9d56908dbc729d5d7d322a17a41d0f62c9af9a013ab1e19fb7b6c6e7fa0c0b18bec5e3d3e92546c77e3753193389e5fcdb6a6a1896cba461343e71ef7a156b136b27ae6f45be9368301cfade203e9b53824d70f07de9abfea1968b8ff8489b9804422ba05ac3c3adf23ba0848817fa51febab5e9b5500100310479e710b663f064c1ef101c9a5320367cd8bc6e52081a32f070e7d3fd6f4210cdffdb9fcab1de4af5b06a7c6d191dcc12b25b3053e58952bfd1f723afbf570796946c1df9579ad14ea9c8c30389c1de4d1e845c764fec5eb8faaf4c558c5eb5113018c6a21ef653ac7d7f5b6c7e1a8fd48c6f423e9913436202da176a86731287db7331db055508acc94168888040ee37b3c119c8a0d88360241d68745825fe480324a944d56e7cd0375d4d33a5fe7a3863c2aaa899b2d24f65b70bd804039116fe959c32442c9f0b5470463523eb4336985b71125fe5235cbca0c88a6f92416d038e144de5ff8ef6ca749a9e239f02db505bff8e16fad1cba8b1500445f067a674142b6413e9dc0f432242d8301879bfc11fa86d1ac9992ab12319fea8b703e10a13bfd4b017496222be26b56af3ef67610f904f0ca8a3e7cc249ca8122735a542b289f13922904ff23dd197f8883c7ac77150d7331316ef94e0cf13b6ad95070420513599100b0a6d117640b781c622ed7ef7ead29476b3c835bd9dbda2203930bcee7ac01c3b9c89da405ee436ee652ddcc3e96c7f1a94e200eec9a4a226f3cf7ae5725068916e73b61149497d11dd85157f895669f51978d1bea8fd2afabb18d082365daba2682ef623109988b7d0e27ae57bc14d86603f93b5ac040ae52d8db404ee27e6c34cd4246f40eccf9d3f8637a4615a4006918b01d34709bcbebd02ea72958d54db3e87d69e6d783de2f1841029d6975eb11f9b076c247108797d5368c656f888092b82aa81aa26e164e038b359bd68801c22fc107e4083a9d85fc254b002ece9d4545310b0cb22ec1af04a7ee31d210ede4b605dbdbcb70e4301989422ef46edf63f9c96de9cb3f70638b51df5c0abe79b7af8cd97148f2b7bf394bea0f7bbbf6925f83b901b87a6079f2c3b38a98fe1a86dc7f48bf97553701834f557451df4b41e7db984a34432823585380b45c1b84813d6aa21107cae252923fb4673cf660a541e65610ac0127d238285f53bf329b62169f3e42d5efe268dea62578e97da59a58a1314a1bd46cf7a7cae772814130b51411082e30062fdbda1c9e14d6b2bfff89d0379d32461f3b8e833b105f6a89532ae748b5fb43f283fc86450404e8befb8442b65e338aa0408303a70e9c27a1d923d9f2a06e7c6159c50bf2e3ba5b035420ecbd9d0b5fae478eb1ab72fa714f99d00188bb10e60380fa3a3a318c2d359ea3805c2fa0dde17ee52a504f70d6b466bd38d1dd4196be336a9ab4a9e573d1bc6404018a119f688c1dc2a8ed1433e8a8ebf455ce3808c245f0220f0c12d28c771757763bd111ab829294e2429a6f7a59858dfa1fe0b806e986d40aaff934589fefd75ab91097a979f26bc9352267efb2d82c4738e4e6c451b0d5adc398f546c646b9e6b8fc84e91651a1252d5b805a857c7798d102d1e6f90749252bc53588348ecec0897c79f514442fe3b27608c95d0cba999a7e0fbd7f601689b4dc63ecb9ff553ff12eca3e9b26e3eccbde28770bb6aff7c864ad6be77fc09f81f90df6efd0c4025d0916ab5197ab846dfe6121c462761d9cc87112ebbca197b0a222fd34a15b824b7eda06a56a6ffda760fae5f0b527e2798f01e205a3f47947a4bd190f6abfb1dab2e3a53131af95d593bb57e4f4af506440cf20636d9fccc449d9565bf43dec8b6877337ca5a43900c1dc600c877b290342914e909aad8c5f0755bc25652781535c057ed5ab2ff8ad4322a8edf3fc1b5311dae6361a7395919725f4cd87ce0ccba37c64eb3618f9c5a53644ada569b90cd07184fc048f1b589eb29852909e75e7116ef96a268ea85c2bd257cefdde9222d7eda875a2a3abcd3a02a1fb470ba967b20beb54914b8b0c6ed464ba978088d7f8b30d098966b0bde82a8f1210f5d0c3405c9bc73f703134d0b6ee13326f65fa0b8154f4e30808997d4afbd060285942ca1dededc3410a099881492b5730ab7bdc2a4cfd0068f67766d60b5d4945f121459d2083334ac878d067bef644b9ee427bbbd6c9351d7b019bfc051c05ac301ff3792a1c687546dbf6a07a0cf56717374bfa1191c22b7753f6ae02392f8aac9207d1ad0fcd57c5c8b35817574b7dd90a00cab75f508f8a234eabce6618305f94746cb6a8573389d336bb67e1b0d2b6e9bd3959ef344e1eb245b522c35222813b8c6e82df48987436b5592025e9786ca63b6d1a064223bfacf59ada713c2a3116611393aa8446ea79b3cb21e96d13b659ada2d6524686fd46ec66c1b4d8f5ae7831840c9e3db64d528f83a1cef1e0a586a783f8306cb261ed9c2905493e74d35883fcb39cfc5745c282104cc3ce804999231d13e1bc6f2c022f05999fb57575bbdaf00d7a990e17dd2f8b9dfe66a637b42f58ee49ba60f2dd9718d09d7025b6061b2087bc35f0a8c884f5b67a5e18c2b4e857d3b48b79dc7cab6b72f572d22987566238a7153ed6264578424f1ce091fd05b7f14563fe12c76104d3373367af3ed3aca694a21127b5912c0b7eb1ddf9d4a9f03f660d49f7a7f0fb42797fd112414c3eba2b75a04282dcb9645191fd3dbe376e7f60ab40bb7ca1e991053a1912854a68d7dcf854201d1f2c26c6cfaea32e29d80847e6288274713d2ca973b91dab97884326b280c6f06c65b8fd25d314be29139961051a1d8699467d02b67991baabc9b05629660c243ca3b0477362d5e6bf9eaa33beeb52cf399846c77fcae11a89cbfdb2058e443ddd44fe202a3ba5c2efce937d78b9639781b8b2b99077b433189cf3b0733ed73b59bb194c9a98c5aa0cba6e71d1c5522f193defb9e31fd2cd60f22bedaf7008c2fb0b55a8dd52731dfa2bc69b40f835ae95db040cda6a4a1588a5ba4769edfeb7369c1e9a3b1cda293255b4942881d94d771b7b82460004875e71be64c582f2830c5e80dd6de421a311c5852f4912bea1451b0328d01c7029867cf9af99284cdfc1e1f0aa0d8c19ba9bc035dc270b45724247137da5d3fc4daa09e7014fe1439889968eb23fe124f067825d5f7b304f17a983580e009e0e51630ea0006dbc74a30b512cd9eb4d0b315a0ffdbfb581609ea9661b0007cd234ce43c17c92269a7519bfe99c2ca94b5cd3e7654946e67b37d4270a369266db6804336a446022677a024d44cc02cb04108292dc12f790578a0d61cb6fada738902eed3afdf1850bafcb279f18b5798d7466752c6368a594533baff5dbd17974638ecc41753b184845206c79bbab84dfef148eb7f1390f8cb7346a14c88caf540c241cad11ce8869be3bec85d029ef490fc5edacf94fa962be39a33c8efefcbb6b43960d5bc35f8fb72038af3801466aed141b50e9ac7dcf1921f7a6abaf320ff02ac34bbfac265e05e27495e6e027e673a48a874e6f0c33827a050fa21c2efa789c1e3df2ecda95fc52ca7be35dbf17ff6c73f37cb236e5131542e002913d177ffb21ac450e2542e24b894650007c36c52d90f83731009a7c3239ccf11829cf0fb6510d9924e927f14d6a06f8dc772fc9b028a8bbd2d3388985f3e2609abbd08434c46642b97240c9380a831bbafdc5db77be63a1400cc9a4f7362a689b07a77162022c6ba7a1bb9f0446a0b6b460ebdd9111132694fa5f1b29da39be66c5179849ae9720b2da0a012d4bdfd1b18b8fbef0d5c32b92c351dcf2c599f069c3b53f622fc8e904f27584b2d97d43f779abcde6dc1413c0a677dd187b28cfbcf7fa6316f0967b53977432d45944ce8ebd2e265c0bf6b2870c75ae808fed52aa35421ef55667ecd6f9d279c9b91c9314bd9411bce267d6ad52b1d910b3e65147c3eb6021a0af98707408e66bb11ca5abf5e34b2bc85b144fd06ea56f5d7f8939fe0cfa4862e7f306de069cf85f4aa7aa97c6848594f5a6dbcc718d2af77497f4b9d5ffa217fc301127071e9bc9c2c9222ba90e286506e384f321e622f05d81c114953d0f7e9626b74f4a6bea8cfb86ceb4575e5cf4fb84e9efac8291d1f4153ad3cd9a34ce0ffcfbe30b6829c0f986a4f85d63b602ab99ff3934b1e0c46e55d56eb479b79ca0729beb59aed783e9a3ccd55db8d884733dbd93f9fd7a7209fb92fcc49826b2d4356ca676f01b0981637897b3d2f90f37bfd73b214a398a8e4e2f9e5abec01d8192ca690191255dd8304a2d95a69331288bce00385f462e942f4d694dc3560a263c8ac2b5cd1d2c63b90ec67c32eaf5bd947bd8ac730da9c09ebc6888b0b4f3bead157aa9d31c2802df8ff0e4d69b7abfed6f184bf35a16ffb5677ddfc4682322128932d57fe4c32f21e190e1147d8e673ae407b1dbbca31331310b299e9f3db08ebfd2dad3158562c2e47addcbcc831cef0194ac8ba9778d0103c2955c886d439967bf788eae688f2a7459b0ef3bd16808e8d768b8962a24588d918ceb2cd1cd611b504019f65216beca212f44600cb7fac77216b7645c49f18064a3acdc01399315084dc9ea151ee28534fb31628d190bc540ac6b6aba572ba51aee89544015e6fbca2b3c2330f2ac1f68849e99e1a1f7f523599eaee22720392ea52259e26f1101614d4edae481b3783af4e99082d75dcca549049290731bbadd1ec0a93789ad5c9afe8bae44e35b3e59e562362964", }, { "0410d1f8bc890649c250a3819766f4496f339a6384e34acdd72b3a87266edd2a7eae223a372883f978277a108d6e59fca1f35f25d7a9f3aed42d35fa9b12241ac04754f76fd8f0e8ff6af88cd851887a45e89f1c9192ca66bfff605b128575d2ccc9ca3ba1ba23a0251b2cfd6db577b29d17ce2ea998946997f5c4a97a397c46024681a400a54425c071232d269adfc3b1adf15b4586c4dd7b8886f5c1023bc348bc674961ac6e221d914f432c2f06dddcf738227dfcfff88485ed45882809d0e57019461c88683919b87c45e78223c37a5be5f758e4f0dc6add22f2062bc2eb9bdc31b8649af17d526ec339f0e6fc6a41e26299c65276302f982235c3e5205ec1521625ec08a23e766577664b73d18d5533261c859c4cb4346feaf7540a56155c6c3a4874dc86ea42fd518d71221ac65541e2dadd2f8e129e7809f2835f07dfcc4128401dae2b5fac7ced1d9e07e3f348c6cd26f55b3893d4418557a18c366dcd5eadea0dd84ab95437d6f23eb9e5877fb2ad740ee507e2268c39c7186f34e5cee2d0dbba1a940f516a018f23e716a399c317a7a81f89cfabc296c432cba900ad79db67936f76e4d97874fc5f8a9ff84eb7a0f6d629c581ec5c451e27ef1ed468f93bfc68b2e0412a543d89dfdd812d9421236a4be9eb374531556c207340886c7b84d42d651557b952e0982f62c5c383e92dced21905174a5a836acdc3f2393e770d6cdc22c39575a42ea406f36889dc9558aeae5dc5f8b84862850b55bf4accccb6a8ef793d641d6b08235f70ad3b0605eab462afad1af80fa003645f4d302b03d81a7d167e9a8187bee0f76b1cfd7006b2d2b55fedad6e8db1d3ecfe031702dc327ff2b0197337d7542f42702cb276de852b3d72d9acff8a7feb8882028a5e340950e523c41cfa184b3d8878effe56742994e60240e58cbfd01541d39fa007a9f0ecccb409c6cc540354ccf35223677cb74e7ef7330bb60420f7d7bf97de6888cb343cd4fb0928fe5df5f1b018592ccfa7aac6dab57cded573b5950b94fd935f32cf332dd85b2b36501de6687612371dbcfdf77279d647ed8bdcf81fda8b7e0c5ab139330d64695d814fc6f761fd141dfb0c8f74e2d7616db3598d8de40b993fbdd272ca37db27b82aedb08bebc4a8e6d0385ab20fbc20c215ad50fab8e93975bcab3ff38667abb0545b3b3f20e325f01b80a32a3cc3ed51703d4b2826849ee22fddd5b544816599dca0d8fc84feed9f7e90caba53b70bc3f457eb1adb89fd0b67d2c0ab53264430c61d2c4a1b19ea99a9b453fc6b5ebf5fb5ab799134769c9b495c479c828bcc49a8f993c3127d5cbc31afb89c0e78fbc323755457ebf0f3344d3ad1cfc59d186e96ac31a9298e655b3d1df74b95f30fb868631053540388a13d597002f689708d35a2365e309bb96db8b1b94ea4c8060c2b165f7f19e72056409159371ac9c44f6bfaad9b9567094d18c29bbc8aa2c8b5b82735d20f55284fe68186004b4a4fb644fd52d9645b277c1dc238a764005c1d2791ef36e71786cd990ccee4571d9a9b1aec757e479cfa645e320bc33268e05af9cf90e0e616ae7f237c637a99fe15b4ea8a3232262d96855fa248920a28ec03f77ce4dd93925db60ec030a7be455ba9d08edbf6bb717b1a13c3ac1deb9821e21505c0a8971d5ea5dd8e4c9cd3a845a336209af191150ba5d9b8c2c450e3a765e8670d7f846b2461f971fdcd1942704f620a40f4204b99f9035bbd543f64b927cbc7a74f32cbb12c3caef955f169a45374e4479430e08d333c4a877baf41a27a0849ca3a157b6651295fa71ac94b6e3d30b5d160965e93d2a81b4d575cefd264399c9e4e17059f4064465b2d92c96ac27e3b221499b5e642d033992c236b905c072faa1e34495f9890bac6228330e4016c061605bbfc478c30e1b8534c49af54785972aca2d144328b0a540e3b3810a73e26acfa22f48652d53ea521875475ffade8ab50b9f08245fad753350f63dc4e898948ac7dcefe520ca47394f8e993a6d13ff68a2f78cf294f235f5f863bad10c4f5bc41c3ba93cf5e076357f0f7fdc136f34b656b1b8ebb3eed1ac429c7d4edbc902f7f4bc24ea9c9b200b9a9fd7adff0c6445ce1d2171fc031e3e9f8b8d6b448053393c8813d91333d4bdc3bc5bb2b8bff876cd29e8b92cf6f7bc727517b6f57ae031f3040b0637dfb40b8c1fbe44cfb6bb9cd0a445fd9b3daa1da2b1c4a82cb4da1fb8d525e0a4d9ec30e9aa75b951214621c58c1f60c9b97e6c6b330497e7dea790a3cd8158a76d898107ff3a5910707ae60c8a46c633b522aee83736d005de60b9abe202435f8bc4577b0eb08b7f2b617bb5a831e95d6488459bbf15919d764b39684d7cb7c9310f343fbfcfbeeb212a90d96c7a26c1026c5cb171ee4ef839785076e5084026077455c73404a2653f333e9bad555cafc1a9613387a02bb1287c380d7478238bec8943208de585bd18b448b6099565cb3ec70ec6672a778fa6af9d1b17b0970439da24c7bfaa74c85ecd8e5852e42391ab2258024ccf91e37f2f0e86df958b197fafd12f4a45f7990375f1665a14f7f5374ff7740f89677ea8660587fb80916b30629a7aa88213bbf80512421a0a37414a2eb549b81cc85072cdd87e4e69d97ecc63f974e60d20de0233101c3d475d777602b12e2f797e9237570085b0e9f48d4dedf233eb1301ed4621f9736946eadf599bfd79157c0b4cc31bc273f5c6f133a4e3679ff6797d3c9b76aff4bd8ad40726c1703c3d8b78f0974b748d0265b0a75928374f91b48c2d2b2c11d8b6e5efddb75009e4db72e562be59efb0bfa06808c89f585a43d4776ef08947a77f277526777f0b52f1e0b5a03aa560fa45c8f30e584b58ac1fc00b104942b7b86a3cdee1abea349dcaea4e058faeffc567e2c3b03e1c5c4ddc675e25aa15de1442bcf5ee972a8c5204ca5794694759c13a2d716839dda61635043bdf1a09e35cb6d93b4df3b7a00871f79cdb4ee69c79041dd14deb7754107b8fef8589d2d240ac1d8eafc52ea847263512651bbede2fccaf6da816b1b892319817bb6af9fc17078ab6cca95f03cf8426249fd4f2bf91921d39b8cee24af07a52bbe54ca7fc4422a310dbf2149b763ac0060fb2c59154d2cb0da1ad4892279b4e0ce7f5f92c189c3ce48e518ff48c4ffa9bf2b02d4792f84534958dc6bd2914ba010aa32d133f6a07bdbb87a237c7acc3ba5cf101efe947147ed4eb3bfdffe5fefa991c0dc8760586218d286944c52d0f221e0101f74826761d01a20af187f9ec1115e9e98bff6fbd7c8816c15d33c07f51c171490997bf269951218ae92b66fa3150d3bd40336abccb717e18b53e8806fff94009910f202a5041b5396d1c339e6d075bad4ab66a0637d81eed1696e4068024001123204b8371f0bcdf0ce07d79f7c917327f7138a75947846fde68665e9c767fbf96bb3308abffe7a8d05512c81e39fa8dab2334f46ab9543921ca97be31076dc7b2a0d05e90b7f7610d1a391b442398ef56cde3b18737faa8f282572389b4fb3c55cb8ae6737257708c808bc0a414bffae293bc69cba702ce2959e1a30edcdf64985a4b0bcc927c5912f819c71cc9b1ff5d6e5929055be72ea5c8c1a4a591093deb5449b7e6b60109be1ac0cae472ba31e1035ae65f3214f50ad699a077a2de52f7180addde0bd78c2698470b1af13cfbf497d243c9e738c4cdc265356543885c5b933a299f01a5b5a9ecb0b4ddfda0c28573064f6a3f142801795d66bcd5c31868fd3207fee7bd98c47e4da26bee64e1617b20cbaa34e3abbe31126b06d5737fc2b577b19d255a519397f3ff8668d0e7d401a37e368729e4b83c5fbf01c32ec478967605cbc0675f685b5eeeb42fc688216a0667e1204c995c9c485e6f7712d80d88edc9594528b1907790549756dcc8b0d32091f36d2b4009639e68daa130e83a1ea18353ca34f431c548d91c1591ccf8b25eec1f7a3c18ddca71b87bb290a5c13229250c5e193e1352072f6798ec504b3b4c6aa578737332f52baea7bc4468fe6d8dfabb9728cee93fee50c8caa113f5ed7e9b55e21e98d73a377ef68be7e4e965dfa50cf863e6285236f11ce80512c573ae2b55bcb43cf6ebabed6783c250f991f5f68a59dcb2ac13a3c8fba8dbb11c79dc6236809f2d7c4b0ad3cecd24b85f1aaed9748b8c109f2fd98ac8a53bd52f18475598d67305117de8e03b0d988a2847539cc2efad520f86dcd82c08ad4b10e490b9cb03bedc7197bcaca55526cd9c8a5a5f69f7a1697e7e31aa76eee597c386418e89f06b0b9817a83d6cdefaf9594548b33cea1cbb585e55df3d3b66f0b1a88f4b98ea4720f1ef5e6ebe4958078ea0bacb8ad776e325ccb252f81943b9b1c2f54aad3c7baf1bca0dda1355d191f69c5d8163c464898116dc89201032d1e3281c8054882f60522d3a65831bf779a854fb0c195f85aa66522386625658457e74d5c2fcf5234f226da4a579ac1f11f11a1e0a6993a4dfe5c856481ebe9d8d2363401058736f7ad104104aa03f5c91496aaba2fe4072d418d91c2787a9b4ab0cf4bb65681ad0392ef073cf2fc060692b0c0c194c8eed5558098cdfa3317ab02626159e40e5c76fd64b2ef60b8f5f368b6b4fd7ea3d2d3236aa01d9db7c8a01929f9fd38557335b926251ade1a0d47d0c1444e6416218781c1a51e786dbe9297b78fcf0d0304c62929e00744ed4e14af926313a9849b2a464048bead075044bee013cbe318920c4172138560629a0ff4fd229d81bdc7c7fd1086ab17d6efd5b603a1991b33a55ca5b9e2051b7c140f7937adfaf474c2f284489d9b1e8c71d58f126eaa451407eacde9f0e86504f7de3ba4d830199a229de2bf39014baad6dbbc448501588ceb2575db0ddae005b81ba9914bc22b6d600e2c990f7843e553ff29d8008265eba7dac7b5b5a7ba6dc263fe0e262a7b8638a81f4720622c7361554b61d7b04c7f8b133440baeead7d51ac8b77d606fd0eae1c55ce7e8141dfd68d40ae3d8d2dc8a061085b4fb6d8a06263183869154618329be6b01c2890f2b5d0a0f25dcdbbfe2ec3597d79311edb943613fd4b59157df4fc2e1024be03d98ea3cbec7186ea9f4a431dc3743b9f0871b205bc0c1b3a001768", "113b261414b4b7dfa028668ac8b0cde5734120124991c54f4dd16a87d181efe2bc15f6d0caaeaf6ad615f59ec5c2833904a34b4d34109c82e10609b387f995430e8c13d83ac34310d838af9efa32d7fed6224c0a33", "cd762390b93369f1e207eb15deeaeb0036f5331e82480d180f84a76c3e44550b", "e88c14ef96c7768f5dba9de9", "8d6aaa27892a76fb05a2e96cef9a9b4b7ae0670a12cff95f7b076372456889fbd3b9b4fb5fd98b3bd85b247f15009be2f4e7a0329dd118b6872199b314e159618ede0381dd97db28743461ace1a694c0383d8458150a501d6c45f4b50d5b1bd47e61a51f9ed4929bf2e564f201ed0e6825170027d93e482c1ce268459d2f81cab41f0e7ff281430c16b34a29b5c76630dba72ab9e751bae41122b26121d91f2af271a23e818263f46e05fdd52f319d58330bcabf66637a368c0a8aeeb20cad1916d966e5e0b0de74cc67ebe57e3d1fe01e9743d42a931cb4b98bb762ea43ab937d1e5c42eb08fd56e70e911bdcc1ca4ca0604a329c5364b262ce2de282b4732ea657b89300cc7b7127ba4a2d08c13f581f024fd093ac09c2bc245be60c80e102405597fa8082f4d28cc954a93217edffaba3d2a397bb59ee89c8cc0f33eded78f21183bd1acdce64a923dd609a0620d2911f61e81fb2c8ccad8ad9d81157223253a121ea2bc60d6a3670c563fe06bd75688572b3be83cd31dfeac6b17cf8455267b481219c42034b2252977f32b8e6588fb05166498fa37d17c2b002a655b5711bbc21175348225fdcca041b1f97fae48fb1e222c5bb46b5202191c00666b7e1b2d84aca3edbee7a97dc0f6d1330e929226f8a76c155e973c1ab62c867e1f87be37788754e51825ba31af9f4722b5782ef782fbb70c391a664f252d14e49a805e94790135ff6bd881a687f98b42da96fd34bf240eae4914488af739ec15f13f048a7eb5fa94af14e8b6ac5fae714cbef6268b114813ca2a3920a7a9d5eb506a2ca211758de292047eefdb5a97e18530dcd8410495fc42abed91b1204d9b8ba9d6aed11d2d0fa0d931d46f93f2c1a560ef9f5f7cee1497be770d3cb07c534215cec12c1458bb57aab4d95cf4a15a5e3a3bf8e650206d5cac4af3193d169f1a57638d9a50f6b7c6985d42f7138b9226451670d7359351c2affbca65680557693d03458341198b8e13d0ea6abb7496edea3cd4dee2eb93695e668c7c0901c6809b8ef434e88b85a8b22cab6508b9560fae62900056b7c5c29a8c899bed45a2b5159a1d4929476ef350101317f77f02d48a039cf4cf01c56319cbba16fe908c49ed6f3face88867c0ad3703452baa7b86fe58a00ab8f740b4e8055164b0385dd3fa44502ffbb99cdd843bc3287ea468aafe4cc298a3fc180f284dbf78aa09e0a2f7d8593356eab016ad8dc505420edd376b66598a3d0aaa848fd68c4e07419b8b50e40febe2b6b17ad07726fae1f87e86abd01490a0ce24fb57b533c765504ee0a9ca154187bcf5e6828e3addc7597532643cfd992558d63b1acd00e7aa41b9765094217480c08c43f4f0b3f0127120699b7f2a5ac07c655b6143e467777cdad4bc21d4b57da4d8f9b9a7e4523d8c6fba3614b7f7281e80ff0f9004577adcff1b79fe443c80ca9655ecc102d5df6aab2ff6c3401f344b77666c59ac7d5b92bf4f1e2322f74b75e6ef2bf43ad9e018f164ae76a91451e5221bdf5b65a4fbbaa8dc31e6063b451edbbf4965307f8e65bfae87b15f2453083bea8484017228a9cdc6edab1a28834eed8ce07430f776b916b3bdd2340798955ce9ffcf114c3f6a88bcc4c7b6f2e3842426488c340d00f2c4d2d6fd3b6263dcf7a57f5cea6c77efba7013297bd3320accf033acc0833aaa8e8f95cecba469704214f54a1ed581349878a591f9993371f1daf92e55b2a4faf8f952cf785c687a59b3c258daef1b6d7bf9f904123c7384a859933c3ac31e33edf648a1be4d6264ffade860915bd118f0b9aaec2eb8e16b2015fc25e68caac77a3accea53b9b178f6cf48d15029fac12963b4277df037b7a494cb29b1d9e6d2148531a1f7360519cba5657c080254f130a1cc3ccaadb4298d7ea0223897e63d798b4f4909577cf9b491a82de0275a246bb1211bc4144574c8ef176b382262c0e087975cbef33cc616d32e0131a9efdbe8ad3d9cb5f935d3f4f409852acca22ae2a6e7450e9a426ec3b9183f93b4b7f89d850e1c7053c661936e0cde23e831a261b319b430da45772f0fc0113679d06f025983bbf37ecfba35eeca28de5ff4815a490570491266e92faaf8d0ad4ac8df106faff8fe3c8d050ae9dfc03a01ad177c21d7b653509a80369a668a97eaa532dc9867c32aebaf89ed36586e1ebbe1045347766a354a86ec1e8b2f30c8fdfbb6c5d549e7a84db81b73fb828499c5c4be0d4b2b7ffb197133a0ee18abb5a4e371be0ec0a6535507029316f8decde30833ca47493ffcab781d028edfb91c138609baf1054ad52a5d8ccb98b3ca5b138f253d99bd556afd80f71b39f36e0d96fba4e0cbdb18926894968aa825392f12d98b6497ff85a0e4a91c97f37ba1dcad30fe688b54008b925805104a61dc22b712685202ecdb073fad9b10b5b9ee2ff781f23fd41ecdec87f85b369a304b85bd2af126d08f79d8a9e2bff0b18607a95c4efe35941c5493c94e3f2f3902e79f4cfe84c138b83c7f32d7c5a125b28c6107921e8ac92f1af7da015b46a2f9169369cede770292eee8a5f40d080ea1c267c33cb7d4187093d486dc3911bb2d6cae036cb508e81ca783ab5e95cec751e39f3038003081a252eefa7cd913baf136d4e27076251da9cbf0c7d2586fe02b62ec786790ef08fb3ff3d79bd06868eb1abd9875920e14fccf6dc144e898f578b7295fb5f4e84cbf683722ce3597aafe3195e194736fc317ed03ebbb00d956ce89f7a41a334020e1a88da355d3b47d5bd3965a290f6fbf5dfdc8c8e6347b4eb85151e53a960311582235f3b546ca80a670dcb628fef572dfae0c101bc08c80f78d5630a793bdfe402592c316227f2333b386839a67e6ee8d9396fabc9648ea656a407670efaf80966034958f4a70fe7b920c79dea3d5a0ff05f3ed0516537d51a686efcb258520936fdd415345251c9ac1143a41be295cf12da5d4319e78e1c57ce20507490e5213ca7be92afca8ec8b6a07b33571afe6940daa2afb0dd4dcc1c329474ff8e13d740488e5ced552074fff695a04fc1b70755245895a1e9c387fd9514261dbb0f600ae03f4896e795d1e72f421d8572543243d662f6811eb9402b6a3b8dbb0f32de95bb1ac01b1287663d3b6a3f52339a4f6b27789e15519b2b59f2f4fc8fd33ad1a6e4d02cf0ddf8499f45746da424ee78e72847e3cd3833551b6e6fd6b1aa98c688252b57a1d97660ff006ea1b970a0b8fc7d2e313ffd0b0b85299ded47b60cd2fe9bdd7ebace4b0c1072cdf67231a475045990b35ec761e1dc1dfbd0c402296566eb4b9462979d33c9d652a9295ae70943f38adb212b48bd8ebe82722b1712ab6a3be6060297e2aa54e7d0158e4aba6975237e7c7a1e22b29560b8d262125ff2a6e5c1332acd0f6b5ba15b4a82d3631891a01530321830aa8f2e8ab6b41bc5b5356957a4d0c3bc3eab04df7700305a95d0f9cd18d486c675c963876b25b1a0f78e245deb40dedd14dafdaa9d614fb06eb2538c5411e13be116c76fbd3377ff212eb07c5c035612e4cd7a1de2ceafe95832eff88a9bdb3595cc19287fa40b8d244afe9bd24dca40db49893602a59640d7a1b8e7475825b09cb0cee111864deba9d3d1beac03664279910accb9fac534ef099e398d7f6e3235cef7685fd1ae46e47da093135741894273c0c3486197c26057044b10faa57244721328b47e611633d16d3e4776d90309d68ce4a60d3ecda26c9f39c1c6da67ff79fde4977efc5653d79ad86c3b53090003bb72e78aeedcf4c8107185d9aa65221df4e2104640a1a083845c01000370371fea2a6bc8ae43fbe290949da4e559d3867c16df16b143fdc807616f51ebce8d05bb03c2b0bd587b95e3f6a15d907aa9a5b11622ddf4c81ff9fda4bb49d3e9577551bae649cf64ac0cfd646b02f6f16cdefde09a55e77afd16c74e8a3d777d80b7cc42c51f618a3c467968631119f11ca4385f0f5713e37ab1133b692de475db1d44fbfe9d274b9a09e673dac88aea74ba88cde8db3c831e9b5a0f1e40261281e5aea9d4dfd48c5d9e173f4d9cd56fe7fd610909c838bcbe1d6c729e151ecb4caef511a36a14b03cca7ec5d0feacb4647ea5212a11d18cbcbedf78443127680ac0b1bb65120b4197570288226830e2a92b380e32387bbcd3be2c77d6c7722054d849be9de459cc1832ec3ac8e7f60fba9c81cf5fbad37d228eba137a23227d56cd24970340f2b7599aada9d2424cdba8b50c2b97244dc83f7391e2ceba5bc0a11ba547c142126c791265b33a3db6238321a5f3273ffb01e42adee17b898153e41818b91413ec4f6386ab3dd48db875afe659db9eac94d16f850ac179d087d93784d607349e8711f5f96fd514e8d096de8b4a74122ba914520e93a11fa4adf006700e122e2531e1f39340cccbab4862708d69c117d3efbebabc14a0231916ae1ee8285727c9fc980051360346d53dfc76aa5a11fb1fc8f36f95f741e913bd2cd1031e508b320abd2d3a62baa400dc439969eb44e6abf8223b29d4025c3d1ca08d2dbdbbf9927c625270543e8c0cb5ac5bb5d504d224e66a1895719e4f975d819a95e54cecfa59ec8e385aaacbb023772fdddbe093afaf5a75e63a62d51926254e5b47da1e9b05851196644b9180734d05810dcf3502747c4ece652b67674c02aae74f20d07de2ad5993b3a68d10207eab6be5be34e52ada655aa96c1d82df9b24c2acec35e8f0bec9131c20d0ad8936880af87215611b80d07d7a741a12d8145bd05066c6ac171afd8684b92f72237bb0e4ca4aec1ec280e39f36928852d5d8d02fe463acbad8ecefc103083fd4298f399bb254e7bfa166638460b760ccf2b0f5fec0e3875206bdc8ce096274643824acfad71ba06441c74788356caebdd2208f6f077b056fa9d85aa4357e93bf064a776f5f3b0f288d0afdc51558c8f25cbee17247364c2bb24637dd69017f92bbb43024d9c773439626a02bd0cd44136a642c9c5ae593f32eada790c31a6704030f2e07f1173cbc0dabc410bf9864214c298a6283b3631acbf94b8371681ba81eed1aa81ccf258252d7f90fe733ac770b9744d0170cb554b39e6c72e05919cc237f8f4d7f3545f4d2732f4c9473c77401dcba04c0fd33efc73219f31c08dfab26abee9a7cd4ad3584730768fae899fc", }, { "9c73ac05648e0c50a3ea3a8eea70841e8e06669c1e7520c5e25e093769c4b005375c0a9cea16ec8e00261ceb96a00924a66fc0c4e4e089c63e93fea857aead8e0ab82af4ce1682cf3c9fbad23fc3f7e632b7aa169834ddd6c7db7e1e892cac93e4d787b2ed0a812aa93bfce8fef3ce30ab794743ad241974ff989288c43e1ba815a25a03acdc2d5517293e161d0c46c8858d0b32b124a6b0bc3838807753288cf6838fa25fbcf876e6368c0342d3cbc860d6fa12faa1c2b7d9fb37504e60dd44e36ce74229dfb80f1545125718dd1f78b31a8aadbb4d6494489ce596fcc2dbdf2ec22157a1d966b61e780d36552daf084739b602861a96ceb67b65b23d40916c02b2c3a38c2a59aaa266e1f8939000dac9b6dc50d1731e87ee833a2cc3cb98c57e5b680a85c1b428289520bb252096efd7723fa8e55d2fd4e16900a435986ab3f3d2bd799471a1bc07c1772ce10d1bb8805a6065b8903999f9393d2ed1a7e1c57a9e3e0e10dfca17a04143814f5f3acfb99a34712a6e0a24a7485279ef343e69d27c77e25b41f9fb833d7cd29cb6a15551d5c77b43d19feb19f2640926a272f81eeadb792bd474ae11f080ada72103f8f7ca733a9b1325b50589be2b2b3023491afec246d336f4e4277592ce9695c68d5f39c8fa4cedaf51776d7ca29ea0ecb89eaefe71e5f3560c68e8dafe7da08cdcd954d626418677b8f3f45b9194474a32f548a4da3bfae6a3e2c0a25f602e3b3a821160c397d77c8bcbd71c5f1e669213af36eeea30d48e12953071f55eac2fe0bd8fa355671fe032f6fc9214632428125a16fc8aea8a9c7fba0d7518b9a4f876349ccb9bbbabcdb2a85fc60b83ee1ddd041967efa4036e5e10e377c9886f40bc0b0b57c7b724795f843f6a072e87e532a04c21445090a360731a2afb896ab795750e5c2c33d58bb714f5be427ca3751df09661402604a09a1eca95a8344d3daa5b99d68e6e6245825704c5d4a73af197d052d7f75778917542261d77735a21cff3f75d6159a3e4b1a7a9854ee376e6b3c8bdaa1f353b957862b2efd50d10a40007026261a546124cef979ad20d8085d53e30f5736b8aebcd3cdaa349ea474af249ac53eef2653ae1fcd5b3095538de9368d307d45df2a19acd44e3b78c2da9d5d9fcc4cb61feac5dd35f66299845bc0018c3d476b6761083baf33a4621e41cfae0e0c642de729fb2d206db6a4b976a635b3fd911b5e9946fddceb6feb2d2f893b2bed590317442037a1d6dc5b5d72910160221cbecb53bc983f1c736c3bfc9757e9e05af1248b28d651f521af67b2a0d7e4bd86a0013338404fabac7b9833c372142e6338a98c0efb7130aae8e34bb0c80937680a7a904aba3be735d41af9462f17b967b13566bcb697579f8a9340429c77baa6e24ae1ac86d8d25ae3cb9112e34a7a948fd141367898c5f33c0635c87de06f603b510cb229df0d0d9a9e107de88b12686c539ed4fc54c8285afde0c8ee502919a125cbcaf4c8c89f56e90d3f641f97c07326956f7b5d87c65b689f39b8b84359ee0f14d2c7ed621ec67f5e2a8ee5faf21c805187edd95e3941ed62fa95a65473a569566d46b87c0d27ca37b6b022a8cca30a4480d392ba15701d1015b3648958cddfb614983211bffc4966ac6c1f691f19bd9fed405a02c06712d62a775f73353f3949c76b6b7757a4ee0410fd6d20071abfe46b09e72b70f9f19b61410ea67037e037934bbefaf09cff018a5c218176d165d1eb5cfd5c46eee7b82fe65ea02e3ed7b18a86ac7b139b7c9df79e1f6e6f85304ad22d97190c7ec12c651fcc835ea434d92ae1444e7cb0dc644efbc2ae70f2f94310805c1d0f2d49643d05e78baa1c54d4fd99137a49efde88dba1374c94208fb4a0ebc1a0090b043610ebc1bb08168ff5bf936ff9834e825eefb9ab73da2b287b06fa2b0ff52f46061b07c1131e4108cde478c767b749b696f3520acd8d3338842d53941282da289dd1e9a0e02aa9be0f127566c9bf2d50a27f6b6ffc9e9880bbfc14ce7eeee70cb0c0ad90fb474efa69b46123638e8405fdef65fa7e0e7b29fa8fe8696edf661f9003a08b4aff85a4a3e6d817655c1d533b834da981b8c37c38abd5977b3ba71b3f57967a471c2eeaf2f6f258431fbb7e92f91814b1db80ea775681f282290db170942bb7b04aa2a331950b74a4b6e337affb4c51c6cd4c4e13ce3095e73e4767c2731f72bdb225ff572163fbd8573378427fda194d165750d487f6bbb63e1378a132fb6ee5115e3c32b2380b096b735bdb4d651853bc7928346fe3ea9df7534f2a4eae1f5ffc4b82ae738db7df0103ba4e68c2a2153bca499bae2439a57778cfc616df16032aa8a19e26597d275d2775b5ea17cb25d204b18028eb25a053e5666ac47c6def151f7d4b68ea62c601d87bfbe04711c24bc34274be6815024d7b7d01e7dae10cea6e485348ab195a83854663cc5826181b688cc9c091dc1e0d491fe51400e20e6f2a51a7d56af258e038bcbc80e2c4ac4b41661bd33229d07b39b59f3aa79d99c1ef41974a33e02a7cacd6fd8f9b99cadd0fd6a031f070bd3a364c64ddda0e9fb94036f374171de0b3f4ee3380780e6d77d50db9d58e670fb4a364827d631226a3491a27602808141ce657ad6e560ad62b088ff086e6f03b8a64bdf7c7d01e7b19289279509a9d6d80e50aef3b05b5561e4556952c46d0b6ab8eae735eccee77e570e1360b7ea38c53ae6b8eb420e4c2663b57827228392db6e79105a47f7d89e06ecfebdd63783101d3bfb5f494785acfdfed41f8166faefdf0b49260222c4080ec2c6e4f949f41784f076ce37fc7a34fa4e547bb44e6b9359b4b95cd67d64e4402ac83973bd50f8adc7c6e4c34019bd8f6d3843bba3d7155890712e0ed5134e00db877398d86b459f312a6272431f01b057446bfb1b8053acf181bac79408c7708f3a0867a64e06d7786849bb874a6bdf8fd6daaa572d5648ae100f4318d6b3a811bb0fb709168e817ed83c0622a7e5b17ebf5cd5ecb21d9ac32ddddb039083144c93cb55a95ad72732132d54bb120639d1620ebd142b58d75835b35cc6367012c93c6772963e9ac852c71c0dda2246ab845469997fc170d8f62334bc5aa4ce23e036967674303ec6f75bd3d17d197d026de69beda70bc59d2ff95a899d28ac7e5e42f4d37233996a8e6d3b0b86b80df49ea8e145b4a6e3e39f3d6c3c6518bac45baf97cde23037709d737b242b8918ca31f90fe59ff2c83e2f347a954d3559a8e4f075c620ad36be20b1e24b3afa156cf3255192171ad0474e4adc9b7f35436325b92945665f038611e5d14bdfe7b7d20c09642323346a717f460dfe7b5062a0098be66febe9f5fccfc747aeaeff81ba08e5dd2b1a489c998ea9970afaf9aa03859073707a686c492fb3f7ddb27897ba5e75e578bd82114b2ba85525a2002927909c970a04035334b64b1169c3a923211e0999db8baa26b6537cdcf57c051c0ca1b317a5b66ad96cb5ebd57994f99ab202348d8ddeb343312f1f26ab2442b8c5f5cf6bab394418ef2fed68c3e60275e836027515b6b946e5d86d91fdaf49c2a5182d5051726840a156a8653cabda25e1dd9af693533d782caa09295952ebfe6a194fbc8bb7fc2c0da5914a506c6f31490928dc5d6554890f5eb268b09d671bb6b6d7416dd36e7b78ffc5c86b34fab43d22909a87e5239643d5fef373650e291be56b89b9d90431d8c9fa44fdf4f83a1689d59d6ef833b1ce31a44197b36ab298d53b51ae3f8387087dcb0571c340874c1524ba0d576bdb88101c1fc387d25b5c0dad0b4d309255ad5d5b1e209ba56db0c927bd209399a8a3b5c8663c9ac199a76ea4f49e364a4b93a569b3400e20f0d748adf7db46a07efc68e43802a5d1a914759eb2abe8fe3e8d67f2cd7612bd4d5a6a4535b1e5b3ad4d97e54f3db7f8512c9603d87e01160b6908d8df1b952c750071abb1565e5ea3f643f233faeb84278187ff0089150bf21ee4d13979fdae796f592ac5b88869aecc5be1c64665edc8ececc87502d36720b73859313607aaa561d56a195dd3c7292fa8f0750ddd3df9ca056fccd9d6ec900f45c1454c6ceaad4154c69e288dc85735b8cc42950a3c5f0fab2be8811779905c3ad5a9a6bf56e7141d863caa4e93e0065f229b695efb790926618b3eda1b9a15f143bbb09aa3c4b72900617793417df364185cc213d5cc3a375778117212266356e214f085d8a7aed908256c4aa25faebabc70ce913c08c89380da06920069e8e27dd867567f152f883a9bd2dcfb8097b7f065482d6d11c0edebc67feb3068cead403503c04b324885ce1a62c99af9808a5ec8b7cbd978b8c43e37b06e9f7e1ce0b31fa0fe52e8842002e6e99cdf69263d31de080b56c0cf94f77f0397fd1f77b13e17af90ff33b00119999df802c33534a13d3ff7fd0e8cf58e8f8c8bae033cec1aec7d191f2d1a39c7b731c97a67fd1ca43c13a24b9f97d92e2364dc26a1c9408d4659ac7373e53a2a1704a47e01c0223ed4c489735b62a27ec67ea46747e4f48d3da101b0863bda9d3f7f1b413f3e7f130208875e6a29dc30a78198ef658c7ca32d7d53b4b92e51f8ad6d39ecabb800adc0870b2ab0e85b5769f346ce7fc371ad40c561f9f3b2f2a01f2b8ccae48c78a41383cfc36b2a1bd41d61a39c24144965d9aa5ecc5d506c7c7cf9476085bf049942d35caefd77821ad925b7fd3a006213abc1e008114c848d45cbedcb8af264cdc5c07bc338fddd1123940e5d95717040325048439dccd1e298bead22b011ef76d26a390a68161b8bab29e8409a5880cca9c8104694e1282c9fd64f50e73ec6b9a9ffc31115de9cc0088400a2dc806f85487fcbdd60f409ffca584fb197156b40142e512a0dedea1571ebb74d6b26d3b4a59e9105929a055cf3540e8a6a79ca7ea71ba8b40893c9797e81c6e9a7999d4d382e52cac95727bcac354616ae1094552b3d0a33d0d3ac4e547237fc0cd54944039b0eccf335889f6aceb518de496e0986783c564be8a4a05bdc9c67b1e5abb480b98173ef091259d8c772b611e0c09758fceea3e59243406edfa71fc452d4450b55b8fa5ecb543692c6eda3a6ad3bfea929a18ebbe5ce2ac4754989c71dced37286cdd1512107e4e7f4878da1c28b4beb2dd9a712a8d1d61d1a5fe5382db8aab4857b05a783e98e77711c1933a7641fd43dc6e6e597bd03b11ce8e94aa094fe250f03cc92ed5b0a5e7723911e87b0f3c476d9aa0d96adbfb395a8fd353cfb5a4cfe27deeb82e849f90bdb17928b0a5702e4010f7aaece2d43772a78b325d2ff24f9de0f7bc65974d2348c64", "bf96bbc17abcd1f56a9f22ad164d25ca72f8c996f1a7a66d6effe140336da4f20460b47e1c8573872496343be35a055552ceec437692b0e4919224c4ffc8b603286a8245eff5cc148b004f6e5a54c4ac22b0f09842a07cd332a09732694d3591b8b7d6a7ada2bb38a30aa7fd5e6baa811b9a195d3a96306d", "aa2f714d3a184a9883f4199e8e33fbc9c92b36fff2d59f07a9d0d335d7476e81", "36c79f9f14d431cc8c077439", "873d0617c986dc9d83e9cdfc50b1f916626a9d9e1c595dc7ccd99d1e993d25d89b04a893c89e205952eef8f1733054bbb55fa5e1b07135787d4fcfae226737b50cafa2c11276e8708451be9b4d7f662e98ef6b705c5c4fc64588728eab1dfee22a0a92bae61828a7394977b0ae8a3b6d0126a23583fec025becf0a72a28891391ac1495732a7a4a1d43a63ed8eb37b280b6d886096fbc4f77aadbc5e441e996334d0e10cd7f3dbba9bb7efb147297986509a07735385c681e0543186dc166291edc3b4664f5c8ffb0965c85bc30ff5e7769a69609c69ebb68f35d104bafe3dbd3e2a40e13865f19bca3612e48592aa930eaee29440b4ebc1c0a59f1c54519857c929709b086bfddd6d4a30940b592be48e0067976099efe71f45f956182dbb300e8076e1207baa32d59c1afef7f34171bd66099d2d7f07b39d16d0f8b085185bf2554c6ad66bcd656f07979e8f19575a116f5c4fb9700ec3b46a3254f28afa1ed51348c1af6dba26fd398098a76d7bfa2ff195eebab41330ef290bf75205a2ee570a2fa46bbaa74aa6ba68a0e63e2731dc1974eb44794f3c89ba58cf96f7a070fcca678185711d97cd9d7d8202351ed589e0b05a7a190e60ae4aa109254a7bcf7013f8addd07a64145e21226795ff7c7b1c225f40ed7c3552da8eb18b9bc9bc70c2e7ecb10c8b20c54f04b6e27b5044a7a67b558407eb330f2083444375c022565c45fe817dc00c7d24c23db320d15949b0b64fbbaedd310e73e423fcebe6e1e98a5cd232d97e6466642e5e3b23f06525ac1cdf8688650cd366b1b7ba2a9033e62d836b14bb73717757b76b9673671bd3d3b2a56628f5a309f3b86ad32abac0590c50f7c5a22e0a920d88dc9fbcb3add08b900a2a2fae4178aa100a0e645ab428e0e79bd90baf4af2755e48262b64838a6fbc21226e323c0a1ba5703e30738fc7b5a7df9eabec6199df5ff6ad58f9df5a734ccd6509e53ecb3de1c881732e26e52ab848a0335b04b25f2254aaf8c130c78b0c9a40b60d402673ac7ec7311d0b00c45bd176bc73ad81c2478611804f59e3c145110aacce922e473ef346f8acaabdbb9f313dd3f8d0a937d0c048e5af789e2e09a816146f9ea28170909caf2572a2f6e2d0d511242909de2815e9ec586b2d12183ddbeb7dd70f32424097e2ec28b4ba62cf78f547e2057a4c050cccdf6b582172343742ec8c85e2847efb1595bccf89ece3b3ebba824d2f097b1987ec26c6e5710544739d54a714060fa91b7995cff0161415eaf55758078772c0271d9d282354e47a25b673eb11497a6ed8db82267d65ad47412300ed525af96f943c5336b1de88676dc346e7339230032463d305b0442f934018bdf0242768511d20474c6ecc82fd752c0c0ca5cee1f3e06e679fa5835540f97870d47ccc6bab233290be7a3bbd4a73f1dc7682049bf7b3cbfb6687479c18d246e3c07161df5c889ee95d39cccd989625a8c9e80f951f8b1832f6378e05daa8566477d7fe547e49ae6e822a68de4df9fc4d6500d5219c3d3bd8887bd7f695151ba378da17c2e750399f7482973510a386721c59683a86003edb9f0ce1ea89bd7bb8a25c222df7ebedcc1b56c8ce18f367b2cae720e0591b477f6ffb498c3d7ce59cabb1b01d7cba84d7180b4b2a165d4b889a6ac361720e768f2913aa50b0b5c88e55c35bb4df4fbc4460338809605f1fd445a2bcd97ec1d2f269b5e779a18c8f215bbc5555c745424484ee5436119eb8754f5e9e91f51fe715353596baa1fbb0a690e99691636e6027cbd4b7be752bc278661e2677070ddc12dccc262d3dd47160345de51359ee8dcf2f61044f95dfdaf323881b2bbff68af6572348f786f6e52d1309cff871ad58148307d7eaedc93ef037922b6092ac62171433adc4934884efdee3052ebd60ee115f76f9dbd0eab7c4c0a77b4ce8078209d23d81d957335f331965b556ebd54732327b5aacc899f9ed0edacad9eb98cb845867f249efb0e1a5fa2483227f78decbf7f1f32d060ab0c01eb985d83920b2cc24b5f9a0d5d869e980129d3b78277fb87e5cda61e340a729d86b6617b8828dffc7c37d4c38080ef3515c2784935973dd184e0a8160f84bb78bcd8a5e691760be4a4d41ed6512ee436ce24650c0e17e7d74b5e01cc39b21e21514a84db262d673f24a82cfd5dfe2a162976171c538b24af16429bf8ed5fa8e37f89ec6e7d63ea1d83ac1087cf89e8f43161f225108889e922493d973e36b510074533cb1cb22174d21c4076959e4191a5df880a8b868b95a9cb5151a7ad47375fcd87725660cc0b59c88ceb86984941268493c49b8aa2baa8c531ecf497853ffc3d26b926a379e72188e246d42073041fbca453bd558f328881c8f8d9e099e898a912530c4be499f2b32229c359ea10e0befe6d94cba5ddafe51d164898166e890b22fd1eebd5724451511dce1f8f7431d712a3f1e50fa5f609da686253311af255b84b2106b09b803e94b51729cfa0826869945d46b9606547e7e33fd9961cf15b400d0f5e01d8fd4d92a83ae526934059d4514b9e0005317a70466aa0b6086d5fcfed201d958a0de55fd23f0919ea29b8aa02440031a9fc206b9feef362a73430a4204869354ec81b6fff92eca97e7f1bb12d25228eae466b8137b4806895ce34b57dc14bdcd107fe160776b0e5daab150ba06976eb884eaa574da393af4de355381c7caa4f611a2ee70a0c78df93a4276f55e6281997b4aeb36888a6d9638cc95444047e5202f41f8bdd787f1ff44a648cc7d39f05e49e5d6989fedb194c526780709763da81a780db0d1534a466cce57e11dd3a4c0e273d9873af1040d52a90e20101e1f80ef296d45769d204cd5417a84e022b6b336675d36d9cbdb16b0cbb08f5e240012967c8067c92f97f981cd19d449084400d76adfb7c610abb73bf21e161db04debe6665fca79d71c8cc50adc3ecf0e52d07773478ca97b8e9821a5704dc58acc647a5bc618d2b681f17942c46c266c73ec211ca403a7d47e42e12c775b370cd500d70a4aac7124f5f6d2d4ca78e1c17a96426c326bb60379ceb0c84a86200f3b450e5e9aaa11f45440f5260eee7675a8b9c47fbc58cf18a651a1dc7b39a911442504f12c103054bb50f15381e512dc6e3af7b414b3db26fe767d83a2a53d7181fec8f6b196c7874befd6628b31797ee3c9260c7b7853b137893e36696e2a47277add98462ea9a0edeb7d2d3c0f2805fd7db64c2c7eff353ff2b36f4de862a42779ffd4dbe77b6a79bc9f4ea3e909474ead915fa3fa990bc82b83a670b163e79300b627fb91c4502e96bb9dde00f716ae6ad14dac647c9f7c2e5b2e505708b5fee996b8e9113a8f4f2caaf414061ee72e76b8bf47ec4f781bd7c589adebc2c267448247e30d659998d8037783494a1fdadcc819d7ad7ea2674f75e10639c3d3055046a00814ddda0e463185454a4455d60b9780250183d591c3db6f27373cd2ce4f02f206ae10a8c32d71226e7cb8d5b05909445977164983c0073434d6c0f2bb62bda66a16792d6e53a49ccb5ac3e285a6baba935f30e9d1ddb812a018ce04f29e2009ad678ba72b6a7112d6e7cfcd3ee7b058ec954a6fd7fd01018a6eba6209687c3130de58147b07bcfa02ec1caf30b59daf87db4618b4a5fad34cbc8014a7529b9458e05eccb9a77ef1621aa95513c6fa4003b0877ffa6d48805e7867dcf53447caf348228ce926233f65d553146584d6ff3dc3ed3296db9bfe69dec6a07add13037b3aade118b2ac3c52350b9691a6cb32356ad93377059fb8ceab68de38d96876d6d383db01f3cf620e47cbfd471bf6dd1f601210482f7c3bdd4c3bd37dd0a7507e1f0fe515151634813dd4ecefe97b52eda28e7a7129993b0af311abd3a07bc463f3cbbcb4fb0eb265a5835663fdbab0d8b8b5a73837ac98ced6582348fdeb41ac8ea9e36f9818ab9c0a41bac1389a6b518ea17df043dd50550f32471645791bf59855ed695b84919aa5cb688e569122786660f06e3a919ef9cf18c355bb397b86710c367362cddb0239aa1d32d489328e4bf92b3abdc3d0dacd76ef1a1efa28fdb848e708aed6780e2d8efb19a2e26fea56b4440dc3eafd796896d73fd150bbd967871f5e6ee5db58995f2f85cc2a15077d7d472bec2e30430af6891193ef03dfc7761e2b3b3b54a72d4f1084a8fc541526fdeb0633dcba14e9485b43065aee8750397ea88d9ff13417149e0fa145be666e6f4afdabe7ad8e4864e777c20ee7a2842db44dedee22f3ce2f97d72919b9ff6059352083be816a7515c48c5140a99af8e81b9e18b10074dc73dab55fae66261421629c8e323d8134f08beefbda555660a51e4b55a9ba4573bdf0396cc413145a941c4175aa672586f7676027f9fe211db87fe07a23962f5b1ad8f566f0d5b13c5146457276f307a02e1e13d00c5032a06d225248215e4bc4be1b672f1eaff16ca95da42513fc4315c7a6663f9101aba80224acbf0c87fd3a2ee9dedd1808c1247c5bebf3cb8d77377a508ddb484ed91203a438ef5ed3ca14e087102bc5f3828d8c3437ecf5c92eeec0331ed93ae33520740abae9b7bfc45f097da70adbb9b9b879e46a7d655dbf75d89773f737b66fd8a8c13506cff7b44bd85dee279ea7053f3ed8447fe79c400cf23726fae800449d27af5e342ecf776378e2eb449a3af27a40fe4a9806487b81c942bfe1a4b0fc146c971a13f83669e0189e337cc9fa2024864436189a9165ade6b864698ecb797ea05fed0d60f0ab4b92cbae36c72ccb5aa45337cc02dd086afed9e5522ecdb75ccf389fcd63c5a4abbf60908e39cb3268c76a08687588be67a856a841eeaaee8ed016f6640ef0f5acce12ab8bb58dda380696e3fb22d0bae0788c4fb79d00cfa5ae3e479dcf7d08b45f4592c2d2a7f8081d5a9398659613ba4932ebfd7382d516b2648ec4ff4477648069b9b2e4decc89547c16ab82a0ad9cf293fee5adb17cea4c95ab7b8e386dcae6acac63ad0d1d13656dfd97d5623dbe45230de597751321bbe5a03c879c303fd7a0d837d48141decb6df4f0865717628c85dbfda29df9a8a69b2c956c75fc66e45c08960c23bbbc706e48395057f989dfe675305067b3ed8d046db339e504d5b2bc978ab4dc261d8afb325c5e794ec79d63d8db53f9dd24b623fbcc202679fae8f7d39f7f7e0667b142c714b6a723996e5254ad2ebafd63c3577f8909981ce6b3eb1a6ad67a4e93c45ac3b34587d153ec5ab67a2697a9741610d5a176cb9b5856bdccb98f69421061c84811dd6660495d9f30548efaa69e36ead246d997c95bad0ca3fdc1a08b4be31b12daf211d3e29d585cdac48af8f2268ec304bb35d", }, { "ceb1f819497c0d631a9c9616655f419b5e3470fd3b19cd0e4fa556bd26cd9df57e960ec7121b2a2cb7c0421c1f84b77eb8277bf341490190ee574d1424eb09a281176a933394bfea5502077486bef23ee66e3127b732b7a58a04b9aeefc35170dabb030d4fc3f8a4c5ff194bbd0b89a379baca30ec81d576868f25755276e62c31e93a80ac322571313ebcee494592c3ff5cf3ecdec962645887d9aafdbfd62ea910af5542d4c7731283625bc9f41ec85012b42edb1792339e6cdd9c2bb3cad4c4792a064df17a5f74dcbb3dd0d90620ebba4fc6d1e1f9704dd60c798ad64d4e5077549d68cefdddaab81a7a91209b7ddbea43accb3d1c191328929dffdfeb4f5740ecbf0ee99cb9a1b73333d7ceb0b2b8f35f84307b9d44a42fe1a30ecdf2650dde251bc8c1d46978089c50d64c028f40611370ddb0b481df9624ed63165370f4788bbc396026b268c2023e0f04cd4f66e0bf439074c46f0ae85d6dfeb0ddf22868af61c8d5133097156fa61a3cf5801db5c3ad29871d336f7aa06d2a7d5f52e50eb3aee3c7de7bdc4d21f68a1776a7cc3954f5c071282febc89c1545fc672a0a1bd8eee2b769be048ab58ea12b356d658a6225fb8a55e752f1fc97ed64c2f87f9ae661514f1f56d9d4e47b001ae865a44b8a9fd5df8628d183bfbee781b6661c9cc76debe6c3c5bba840bbc228206673aa05498a8c715b0f3019f6b2d05cce6c233b5809ff1dc4a75d7f69859fcff94ad442d460b32f6fe348659518c16385e49fddee9efab2455732aedcd17dd51b5117efb2ca1e21ae6787437f48a7042d46e11be4dbcd2932ffd70fd154e4eca5fcdc57c6fa79746100b8e1485fe575a5c79089a25eb2d55d89e42eddc81b82c4f7da8bf153ff5353b7349b161911bbe0a14483fff6585d7f3c8b5c04a6dfc99db9548f0c53e25f0b16fa212f0bdd10ad2193ac18eb09972795f42b3bd3f4d98c4868989c4af7a760f1c88ffda59faac73256df1d607644f56a70303d6409c9ad716149bb58f01b4ab8ab475e4af1257d47049aa77adf9ce54fcd22b3d6ec60484da903a6991ff052ca37b01428d5916fd92c17530bb3385a805b0d57476e9f9417a23ab1c12a038b61b3a0898831f9615d10b468c3edc24448d09b8f3e3a2355dc5e069e880929eabcc97344fb6ca5587c5ac1404783848f531f1e915941e7359fedd328f7fd12b3c685f8c1f29d1a6ef7dbae3e5e32cdb251eb43aa2d2ae0cc18b3f40fb006c2778cba387e5852ec4f2d9b8e8ccd5b3e1f4781c974aca940c45d35d30d3b9584c750bd45a80f32f73dcd85c99ae107b92888839c342cdcf88911cb974d611b14b1d85a59e88c502559d6eef3b7f5addf7d307bb25c57aae669767db6d798ca887124e159b0317e09076cfdbe61aa9ddeda189036703b1cd9b1998f88325910a37ef1fc2e227a382ae635e847df8625b99eb6ef0ef10ce7a2a5762ad7d03a7a4e2b767c4df0b477d6e9601dc8e6438184f97193ea7d7a8c22f1b6fac1f0740f1beb8b68db40e0b22940cff2261273aa0be43df561b88184a9377e6a27f27942dd04abb9448b6b6ecb3a60f14dd39b58b8d94e1991cf9d3a071ba42e0e1d71eb211ca466a70fd4724a34639707feefbfd73dd9680d76a214924642a063b38b85cf30eb763fbfe889f34b20fa4a10ba214d938a5a092c6e9b73b13bd664c75b34f746aa360593c0f8dee0f328f0ad4a3e40d498490007e573b8204a1ce7a550deecfb15f18ed5ea6cb5dd95a68adfe4cab37c13b383f8273b1971580016a8df02a3f4f431c9de9e7ebb33244512080fc5852278081b9f4434109c3427441329e8071d19d0fbb74fb6ea73fbfc7c0ac1012d3a0948d94d7ceae9b0112ec43a16cb582f9c53e7eb0ad15e05ceda108fdb3dc9e585a332018d1cb19e4a75d86041308fdd8476c88e4826931601a3a5dce06fc16512f4669f10183d5a8d15bace4649abcac07358089aeb1e9b8fc3776f3239d5442d3be33d532097e13651af7c9a5b465ace9e626889800318447b8876b45dbbe1989e1eecbfb5cdf5067c71a0d7b7fba6555d0edede12f7228d7f9841dc532274f24060b1f52da6fbaa179b81ce962723f43601d248f8f4d5778c1653e038c8d27828836d562968004003810e9aa9318edf3260272b54fca2e012f6c04abe92c2e6152f3c3e973c7e9abe8c3467bdc246f0226d1b7669bd577bb317c571aa8758bfb694fe4dd17ce78f091cf6c6de3cb601a9d177128fce8d42e652b490d90c4f8fa04ddc71cac300d3dff699be3250bfdb2136edb0057af3ebcca77ba5b3ca34531810c5e2d4c5b5b3bc4e71ee9e30cac067b7706c326357fe0ad2a4bd9cd811b4e9d696bd9b4b70579ae246381210f879c769e5f9cc3cf8d70e9c94ab74a55f5d7bf61a17418b6edb6db4147fc40cf98c75de85421b7d192919add48e5334ebce2a06e56b915447fe085b7dcd677659dd55de1f705c389975e56e0338a2ef07ccf5ec3786407e8449d9011641786f1ecd4d3d3da975d61f5a442293e6119ab20686ea8cc7681010421226838a95a157e2de948c536aabadafcd4095dfda48e5613272289a8238dc945e5f1ef30075d5de096131740cdf23da1fb8b9fa009e5b321083cd93bba9271909460c09bbe1e8c54319394ff85c291814e21215816d4791f01424abbe4cc4c792d0d04db1b812f4d24b44caa76de2bc50f4d1d1611862512d87fcebd3c0b2659082b2423bc5360d107ad7b8e8ba7438ae4509105d6b618af25e75c51e272aafaaddf1e5a227f2b2a2c96a8a83dec23223cb428136a30b290181ee20a819cf52f6c03798e7294a89f3b5137693d5a8b7a0ea38d78e43008fc4eeaf6d077ebffd3ef7952620e0af1395c38a289832df391d1710ab5b103a1ffeea8c06684c03a74399cd63797c770e3f0136d8331611502d21fb883136a82f2034358880392fc3d2fc274b799e59b89f8f90d2a5a123d3c21e5bf3540323743858fdb8912c7c6329a3aea241075ae097ebb23c8cd50f4ff46b42486e65bda6beba5f4fe6dbb30f7e61b1bf690c9f00f7513c83274cd21bb71563257a20cc38da2b88c1063bd0849c8243058ee205853342085a8edb7545f0d96a6af936a3d4612b95676665eb02e72e0875100dfa444f039eddde1422ceed8d38e6c3dbba25064f8c6cb5786f9ca67712b7840cfbd40f99b1edadd4bb9a61f48124cf3b49d68bd642404eb1dcf428eeabadfba6810a4032f8ed06b38867a7098c7744d54dcfab8f0ff941ecee69da9916d54097e080cad86dd08bf53833fec4aa4399f7124586223ec70e2c31e8c647be06df9e86a976f37901e9b134e775de2a0fd53d545c5f92236dbf5455859c138b7bb1112427049d29ed4f5dd5c43cffd3113c276d9bba910879e55efe817189fc239a204a9ebe738c0dd161d10d60a51e9dcc8c38861d41ff029ffd841086803320a17ebf5ff14b6cc2ac3dcf0ce2eea9af7ae23597233599c2321dd2b99e06d93f84989e75e30a388f47079c2af545d96f270e064a43a00c76bddf2f5be5089a69a138de844216148a1eb0b413f58d831d9b8967df297455e7538442388cdda12d157fb25896c6e2b47696c76b234a88bed4f09dfd64f2e4b77627ef03049030190fe271a5a853591ee9218a0c6b12cb3f02683d665b211dd1480cd44c9c0566ace7d751902babae14cc3821374bec774d54b4b4afd5d1811ede556a7a5ad02642a878d2d32380e7efb9082604f49d51495105f827d77945b5cfaf2f2980566b28ce3dfbf1bee2e077eb067bdfa4cc28f5d2211ca99a615e69118d9391e3feb9b13cb4a2fa9682718189ec612db889228aaa3f3345a091aeb11f41420240fbb47caf567646d9e7c762d3288f8bb2b1165cf049a191db5042fa9185fcd180b04d3007c376e0aa3d427d66d10918821f74736816044366463df7cb3ac94cea167cf1daf2d1842f130295e40bad672a22da9238ded69e241395f04d5e3c3875b8294faafbd3d90ed56ff3e01c5a0a3e349d761273143686aa26d408620c7d1a35ccc430a09e3f750d3256298c6068c0fdded270f308f79d2fcba591d723ac0cef703d8f0e7c051bae5b453abbadfab98bcc297ed4201b03ebc195c2e441cfd3b10c63c08868db36c320707ecd6a37593661d70a81f30e6db4a32f98e4fe6b950ace55923631c8f95138781fa2af78d8104fe39242f1fff6942e8e782dfa0d37c863caff9492f8e5cb70046d207c4630cc29c20e1ac105aef093261d8d335456961e552ab14d107cbe14e9de912f0e5d58d16b729270208204469f917af4e710123c3bc38a4b3f485f2926f058344db105b9239829441a2d8ababf04aea615c0e350846d9bc3b5faecdbeb450f38f615f119ad1b5dc748e88107ec2fae01f0915174feec37b3e7248ed2699d0a5fb2fc785f17d6275fbea867aad815acc8a6fd3ca4ea7357d197e5a30082ad5f35a9d894c0aebb206c6487163c9cc20442c040e6aab33d7b4b221e4ba4cbabd975836e353129559d8ddcb3c97876cdba360da0e0c1dd5b0cff7957a444027db985ebefb6154453a221076c997d3954b347f49308d2ee14d1676b75ab6ef365f3de54aaf398fd96b9040253813ba734829bc78a6db59e3f1c0ab4c878a72d6b8681157919130fd3171126994dcdcdcf68955ad64af8156702c92f7a715ce6f7ddfb70f60e80c92691efbfdebc8cae252108fb6c0010d303d9027d4a5e63413b5fb2316d32fb93c3ea52a2a7df50cc0058c76c58d73f5bb041d9fb9f3c3cda9bee0c0920079ce4f1ef8698ced664ce2e2b3b86027ae2b3bcbbae5bf7ea3693d9429cf94938dd3a2763d3f53937c46763ffee6579d018358bc69182b1c7158a09b18352ea618c11c45f07fe97cb65faca535f43237879ae3e0a31efd14679daf8fd2ce25eb8f32218fa20afc586a98fd908d3fd804cabbf56dcae272328011b252dfd83e5f0a5fdebc6acb04c5540255e1322de5fce9db5aa4cdccd74dde8990ae51cefd6c1edc1879971d3efb1f94dc41b2b23e9c9d89415b46189914a229b2f3e8b05ff78c68711385a00e9534dae6f79d15842aaec575e4ee0f098028bc74016cd3f8e93c6a0cb21a0b574ee63e367343ca9de28003d76e02d0ee2b8d622cfa3615d3628fd02499eb7bd8c1aa1f34edd9c2d059c6a7c7c978a5e4f60801e03e17c3a09793c5217f310a30db1965b8e328893cef20f4a899aa8d9fa28f7fe0a733813ed7466046776a874273ecfb57158483f4a588ad4f232adec5ba4ea651822780596de09fd54b1717bf04130619979a0e3d12ab7c35d64afb8099a1d21bc952653742f50c8e1c244d10374329cedd27fbefd37815a9b3112a4cb2fc587c4ebda381b2b01fced45cdf0b9ff8ca7d10b65ce42e728de183a82e369486a2e3345664e70674a5dac174d6616d90de8e472b62759df057119875483cfbfb103041751747f9cd12bb31e91caf79eb2db1168026a4707dc618f30", "e45eef9561f3acb3672b4f38570256e8cc4d877e2998e72b022e33de8fc20f7320fe0882f2b53559e084923786e8205336a7d15f3fb88a41e7bd20767f2feaa02df2221fa7577988db0bbf61f3dfb429868688c53e130725d0279c505686f083", "475a44cde0cc931edf9a44b0c1e0001766f09ade023dfe6b59a6af800e549b55", "7812a320691ca8442767a51a", "eaa577bd67fe79ce4586f43355c94528e306c1678946e4f7a907d2a8ee7f4281270502522119a8b09b6f05d864921cb515fddf6a1000fc2f67b52d0627998591e2acf5b6faf71c278e5754b2703662ce670dd049da8d6e280c2b84d6a9b29ce28980563c40e03381a49c54608b72faec9b272ef05cfa41957d9eaf3e944b22610c725d8efea90aaac6e782848d368ffc08784d7fe37ea1effbbbb34952def29fc511fb10a1282bb0b6334328e4d00529a44de3259b522553a07d524dc75f431cc9670127c15670c0df419826617cfb5ebdd8788d5f528a9eb1e61324eac5c1746f339aae2e2e2fae598642a389da671482128acf2d69814258d83de98f186468136868b729aa5f0874fef2ff2575a1f87439d64e049e4d0637e9c99ecb7275417af654541306615f30b75a6caaa563e4790dfb28fe9f0e7881ea2d885eefdba99efa7f878925ce7d33e86d888154a1b03189429fe20af8fa3a68d65ced9b690a709031121425cfcd7e1890ed9614f9dc3ecbd0e38c6c84e453e3204978ddc1ef8d7fc6cae28c61a472d8e089e23209f0c36e80c994af771e6505e72ba90e5543f6bad6dcd31fdd468b13533a0254e44797825764ac1f63747d8d6ca019ff16fa732068ee94be382c46b168050ba725379df31a98ab81ec8eb266a3c3f2e1cd95e5f12b3bc79b8b435e4d94098c6184631cec57e9d8913458889223a2a4541f34d2f9df380f34c3e541fc587f0a6cf08c82e99476060eb84709a292f4c7a8551bda3a9eb6735787dbb9d7f1e83937c2e0e49f2cf6e0ab0ad84c40fbafc3c7e61886a8629bea816972fa0afd0f617b6340b1af19e341875e97565c8eb0b25fcf68696ee674d2abdc29396bfd0f282543d2b72a239c6470f76d3b5bff6d1d064e6e2d06f9deef2aae8a259c034373efc820f9a2fdbce36cc27f35dd6386de3b49509d0c305757257f8674d958c580a09e768c0f6ef237416fd53c31511badb2e7cdfee636508482f01899e72052b46b5d844799cf94708520178cfec2b61c8980fa7dfaad8915b0b75ce6eb57ed4a01edcb4a35c1dfcdf8d60f3191bbcdfd522a0e321ea41c2cd87a303522d0f98b82dcbe53232ecbf0e2528de7e1be75569584bf2ec574687fde67ffe9827ebbe78f2e5bc4fb368f3c9b0f588c97f7a139bd82fe86eb605b8e29cee75d07b510da1b24fd62cd2fb366f1621e7dbf268b15937f7f7ea4acf6e615775a32c90733769996dd2c5aebe08ecba73e0bc4781d33971992b2764c1b08aa972859cb61b003406479423254a01ea85a348ef249d408157cc0962d1e24cd9c426e6e6a3784dec6fe935be1f6730b01e8683d97e21d8774b2e2655f85db7149e930a44524d4f86004cd687d8a528b6ceadd890707458cab62809110ee28f61a7277ed79dc41e573fd4a59fabf15393ed4c21bf4d5138ac843e80bbf5e1c39ac2d7f2147f35996eb51a9e835db63faaa196b8aef1823ad72523fbfcb35b5560582a48a25ab770e7528e4b3ef291e6f62f5fac916e2162b3b56304287e46839858daf322b0de083d1691d6bda44d66d085ef0d0ad364eebacdd0a43a4456035e58910d0b2dacce45b1c0beabc784f3620a3e4390c345df6117b86d4fc386523b7ceeaecc21233a2865ec6b63bffba6689fb3323402119db8f0665a4730b2e26ca6411db04f1bcc78ce6272159ed2665a286f1ad7758d6d90090a6fd320e697dafbdfef575077e282b825bd64a4dbcf92d1fc0c6f795154e8466ee4b318f2d44b6f81c52523ab68ff8367e01090c2623e00b4008e784049df873a35c29e0abcfae7acbf27236adba0b913d19a15b4af4996669aba4c656c317084347ca962ac8df15cd2f849f522016eb92de4de62944b917d88200ef9aa2def0d13e5f4ae09d2eb4a2d0800af1d704cb01975f6d59768a2b50e39e78116147fd6dcdfbc08354c1b4033bf6772fa127856a4072556a9f07bd7516d01ef41bcb519005c0a3b2a04400427ec033f1b52fe5fdc1aed8e2521fd0fff663e203defc39d7546281a98a502b8a470af16cc62a6581c9985d7ca516864b799fcc55a803ce80711484f6b81591d2402bb1499c95dfb1dee9846679c22853be87c84b4547138dc4fd46b4e79ad12773a5392540a595954112f0cb1d9be4d4eb3aaa4286b6c01520558d58587d9d7f0df3a0282011ce01c9c17111d10ad61b3675b1826c1ad37fc562bdde951b43f890555d6f74ac4fbdb9abbe8bc1e80bb6d52c13de8960a3ff8f65201265e82981dbe39e0d65cf3f1fb6c56e11f9786210383d0150a5e0cbbdb52ca8b2bc45c12fb572657380df369082685b3de9847d5014beaeef815d63e203cc911061eb53d89a312d187f9f02760bfa71083fb643f5d8c324c410070b7ebde250a185e7359837899bb1568a43fa3418f39c12feb03b148b924bfb98b99352b1fbad3f07ac8e4302f85d1fe9ee4bf7507972670ff8beca105cdeb037f1cc4f944d6ca869d0281653de5ee93a7362420fdba8b01a375ff08fe27873655953ec1c00f53613c6ab8b244e2fc1b6babdca5311428d06f57aa4882dc870165deff75ba877dd2a04d1799f26ebfac97a1be53a83ab77dbc2cd4aa45bd779f61b1283eae1a1866ec8a9c150dd0a4deceb2ddea1bc0f4206cd435600a8f190b999b952337d9eb2bdeb3aba2cb2e7000319056629dc1f00901f0880278509417223a3ea0919fcdcf12bff0771c7cc725bdca292068478ccb2e1f35ae8964e0601789a73e7e7c1769ba53f865910fc3d0085c922d7f7849d27b6e7503d521371351f9d7dfd5afc5df0effdf6ac49617fa228501ad72154a73e07781dc4b07765dbfa721d95cf1dc41e161cbd34fc7883a25e3ba6b03e504b2c3b98c8b12ff629b965c2aefc26d74faff7f784baf09c3fc38c487a9d1f5818261162f97e9dff70cf42eb5dbcd7bebb66d68f26d917ddf2a3efc0db1e3372b170b4cd18da507e44c467943f73648dba74db1053b53f989e481c3054bac22c6342fca2c26d30a859a1312e9c353bf921f68136de2b1589747bc765153927c31ebe749dcdff98b5da84c4b66085451b4c87fe1ba2142f98636bcb268c33f7b8c2b96a6525298814578377aa189dd73d5bb27ec5cd2110d8751c18a3110273df2595d4c3a00809bdeda70d86c4a8169b7010c9cdeabfbc3dd3266518226d0ade9bcc4825f18198c854de329fb8fe456dd3bf35d89bd9d2384f3f3282f6872351a18a2f852bf173ea4426de6d01b3ef4b4685aa82df7dc45b99617a8b8c8a0c65a2237b3eaae8267e1f6c453f485432529d973924a080f6a1cc2cc18f804f53209383ce3601ad9361afc331707be1c88b4370404cb7fe0bc538df04adc5c8d9ced94b4c474b19619a53dca3fddb434cac09ce10c0293fea04e8e1b19fd3ff3d174baa988d91cb604fadc59ac0b61f4f87bfd07eee20f7f3ffd96766dd6f3555cd48da7ecd71d2fef34ab082678bfc4dd007669b3fc7a937a5a46269baa7e4e4e43eff1b2b847ea70b6c6c23905d6fb2fbccd944251087ac00c35c2eedba30641797d36ef9d3cb1afc0e3e8930f5b605a847ee77106995bd44047294d04350194369c5a7bf246d1108e1d18d9a638be0c051f695ce86579db613cd8922e86c683c91800b9a34fe6339e0dd79472daa662f78f04f0151a3acd18f11faa4e1216222843b521fb998c8490ab8bab27fde36395b456501307d07b484b453b189fa339282a634af30fea99c9af8f877e61871fe743238b2cee6cb69dbd17d574b5106ebe4b0fde4ef42fab469a5ba7d62c23b67d857f1af6ac981c320db70cdbb6be41bbca60bb7a159ee1c85cb82e0a220064359c06c660b75de6b49839eea68c80283b75d9d627aa4500c0c0f21edafe4a2cf7ee079d5310479da06ba58b142614fe69cb236c51447d63db31cdff91485b46325c26d40dc6d608d46a5e2fb01df06064a022ddf6d5cce0147d5b2a5aba5f9fadc5e778010a924e00a13e21daeea2cd330f45536ef4f42c2e77be00bb53b3f9a93d3eb327dbf30baccee5d26849cfad654ff3ef2b035b78dd3ef42de3302e5514551a968a205b823dffb040ac9452ae3efb43219b02436d0761ca11470405510e534d56caeaacc40eaf9c47a39475adad266f5ddc813e71223800dd46fa7c02b078353f870049806ed7ba57b40b7c3c6272296667500c4b97dd2d7026698b6bc4985bc01be99e0097013a2632c71740888ffaf902a02bf644b38cf9a42528880d9dd142de967cc2ad3e1f1737f0cb8dc5c59c252496e8cfe4e53c82f4a28d9ba2bfa62b6415ba3e5e09040d7f3e3abfeba53e46575e8817ac5eca806ec8a84c7cf77c9fa86c9dd2940f5b96b25a92d4a8f894d4717c8f80a62a35a51d8511f1e822fd79e6fc27cc3f3097d9e3272447de6f223971657ded9e660ee4f8836359742ce7616fd0ca2de6656c71b212b34b8edc71ff36bc84ac4af58eb1adcba4b2c0cb31468dbd2c2b7ee6752981ee1d152c4e4a9b25b2ce87796820def34b662381806d2e4fc77f0b69d7a87de43d94d62a6a6526a7f8c588392890e96f9c51bb58b4f438eb5d197477ce9b160d1c898c89ab408b3c1d648be93b531a5bb4988592c5a8999ae3acbe586d947fe6dd507cddb92dff4974ae17ab99aad5aec9d07b96bd29489876f51afa67570e86b69321d9e565d86001514638403f86666dbf93f18e0a62bf65db333bb85a3ae12d8411aa3c2a423a29bacbbfeebb8a5bafd90436bfded16f992232360211086a3084d9fd1980dd96631820a2cf25c3ac5c19d164cf5ab9a852399491962100ca4fd640146b7ea5460b4fb9e46bf8d23d508a4eeb8a3e9fad8249ece3648c2ec7705a7414eb8e8d602549204cb437f589161fe40de1447d14efa4d738b775d0333526c845cef5ffcbaf5c957df1d8022176b56eeb198e7ad2dfc3d7ea46b125ed432cd04c77efc011a2dad8573345080d7c3cdf5cc160fbc86c4ee1959ee1b8258056b0f3d9343c22dbb2f7858c5f162f08cffdca1acc866aa68e5f1c00b74f66544e8a61e429335adf6f73e32fa87e48e1adf15bb6c7aeacc93713dbc31cdccc9b0e52f922842679494039c395cc1d95eb97ae4df3bb8aba9a2584d97a236f87cb22f00c0a078b045044a5c456e22b2b94a76a559de2672c880660f9785b76bcc2aaed780e05212415c6e73880ca110654ed155a1004af45d5f15ae8e5bfd4817440c5d3d5589eea2c6c344ca0d85d91460638b37f877ea4cbbed35ea75678ef2335a5922cc8541987cc256c8f58045028d33a1c4899cc32265c619ac782ff998a478996be6a0c5b102a664831b395a884f18e77885d860d6b236c52a8066d2ced25432bce79a31b23117f405ef4ebdf3517de98d288f8c3baf04b63b6817c46c14b646308e9f97170b7dbbf9d1a36480338d8eb7466df56feb6baef42cba75512954fd7e33961d247b7393726e46c6e94e156d5776a89ad3e288554470ca0bc4cf4d2d2b0c01ae4fcafcb65ccd6ead03df1d4d6577bb", }, { "228eabb5ad8b4ff13b10d13b27372bc2152dff149859ba47d9c89b741d4a5340d8fff5858a4576c55547007d7e2b3f94583ea8f0976237712bd2e5481c3988f5387e7ac2c3f18718388795b7b2d44b0a13f3faaa55311b800301c9203a511572cf8f349280bbabb9424070f415bbfe28aef8d20329ee842cef4d4c299e619b6ef1cf00718aab2accec9ac00155be2903b6fb07dfe98b0bd8d8580176b99ce4aa6be51cf59046c17ce1817d363fa63af5a241d48bcce064a438651af102ff9c6de4b86374fe24f1dfa66e16e51550dbb791af425d8fa601c70c1bb90e1a557bfe0dde730b0364eba9d2018ee751699ee219e13fa8874070935b29a1767e1d748bfbe796fe4b81a71e823605d39fa4b5b885f4610c34d1a090fa4106785e7a035a629958ad1b00cb9d36d171d575268efa1bef064fc0a6dfbae8e532466035a0c2cef96fe9f93b872f0cf804811e927b39818189412868fb104e2d56ae62f77031f0df1ae91aa11826991ca7b8af22f130a47a72cce36ddc319b32dffd294f2e192e490249ea1a6f8437173ce6392d16dda888a98bf685bc91b89b8ee1eabdfb1806fd61f018d1744fe8b03521de4bff86d4a811ca2ecd5be668e9c752a6c26aacc0cc9dd89d112785c25ca6a0a7a5267b4e37457c04a0626c8a29be30ec28ddacf47a84918bab164d07bdedae62132ab04a6f2c4e108eba9ab878caa4a1a7509521d427ad7f3dfa86fae8345dfb5e0d46ce3a94dec84f7880c7422468ea74fe0b4825b8c762b34d5d9b82ba96e0c7dcae01718ccac0044a87476ff031e3ee3c2c13f5f375a841d243c38cd9a354b6525527de1fe7e36a6e2ad95e5bbc4c97e85f8cdcd5341da777e03451838807d5dd2eb4fd15976783c140e21cfc2eb3e58e40c16374de0aecbe3e3d41c64417a472cba18762080a2348ec3f441bf229a932ea0ca7c816938655d0c81b14dfbf86aa600d0c68172fb0046ef51f601ec89309d43ad1eacd583f9d205bb1ff1a37a97b44b5e35be4945f52897eb2a74645b01a7f82054cda44e9fa9f9af9bad1a235155718713bacd08d354f3fdd95858db0040fb551e9f93ae399d5dc53a67e88bcd5a02d104dfd9d824cdd5fe262ed9266fc47b7e640f2c9d9c7a62c6d24b429fa55560aa254a824a0858482e771144d6d5b05539cf71d75bec3a22be75655e1ababec4dff9472a019f6220067374dd49252282e4945a407084633ef9c88d14833bd95335107d36afdf56a642cb739bf0a61ed53a6915baed78e9d74166ebc492b517c7c594fe6564550bb7108f43012551e65fbafc0a9874e46fb64b5b7aee0082a5d617a43b8bf9473309c6761aebc7f13b72ed460b522a6b0875b67353c705f99d1d9dc899870fcc90c632aba1fa9ced6d7a2368dc4dd3d4b38a5807415e00de6b9ea70525a6c1b67d04521efeeefc6c591fc5256d990a1123522864a029430bb7ea00dd80d283fdd6d61cc5b509221e28f73386803d97a38fb0182fd95b3b91353c6eb60ef2b3d5c8c0ab8dc9cd9be2b4cf69450d00e88cb0f0bc9a4be82b71148a37237ceaf945ab94c365625f58171eb15c1bb244a87335550d813d28f241a3296520046e65aff3291555786d7c871ec8a2d10d4b44429041c3cd6ab60f0def742de3d28393c5aca92b150697ac15504ee66d8a2aa01a6c63d7c719d6d4f94af2ed1d8670e3231a0e481095e425e6231c43ad36e3b7a3478f6a61563f5aa13237beb8a891dbb29013c325f7f91c1b055fb83c436fdf8aef49ec457946e6ab7e955427373fd9c743acfd4b9609569b591ec79c7ea7276de103a35a4a8a05c91f59e04689ba1ddd570b18ed046f785d7e4ff9fce7115ac814fe126f781828877208ddfbb2ebc919e6d1f6eb417f38bfbf22ac9633f75e58e560b85d88d0e4fad9b2e68c9ebf9675819d50c30c8982bbbc2f41e02690390bf0e16979b24e648bf15b18800aaef58c3c465f38cfd1e47bf1266c17b69523b7868d2138cb95c4bce0dd3ceb7c2267b868b6e12888d5a489fc0091b295b56a1c328b54fe1119aaf1e6d7dd52fa450b52fbfc8b84c2200ebe209060b655cad288562786673121691809366af37b76567762d1fc24f1fad3128b43c8d10e9b6954b2efcbe40124fc0a5b670dd6dd544e30263a551825282aa06be3817a8eeacf31ca8b25cba011d60b78d3d2462810764e4acb566ff371005f5481c9d36c991527143af2c44cc8cfc59c920bb4a281f2ed4d494d30ba4d900edf59e23be2f763072255cb6f1e8b24ab1d305fbfb2429cff8bda303617c034e71a17230d0e860420dbcf9fea4ab48557e4d50797179496936ec6c97686fe6d9115809e14069244d251d4bc9c8931e47e06ec051e709ba1df526b55d959b37a6f3408833aaac80cfc9cb99915eb7d83e26998f0da2492b986fe0f5047b2cab6e6d33a117df21e6a8ec7f394a3712885dab176a4d6095e5cf75dbd3f0077e5e74b1ff8b902072380cf172562884de852ff5f07c55856224fb3df8eb44764ab9284944b86ab6f176a863cdd0e7ab5616a14692f6cbf41bc63113b27689fc2fb145736aaf2a5b26d2bef3a2a59ef8bb3f3e4d360a4251d0736482e9ed7e189fc48c0973b6649988228c2ac72b23826a61cfa06b11f13c8555be6e433d87e20113eb74c94f0e51719a7b38c59eba300089d06b9bc2a72017668e5aa3153ca4282718f1762642e7c1be1f865cd9b65c6387c8fe496f1e60d5acbb78c2f71cea1f35dc955b1e7d1cdc9ca339765995d9e05dd729cdf58aa2a1451b633c374e5b6c2af1c8486ee4250a875e80e1f359c15130eb1e2575c0c7badb2af61378527fa24347ebb12c10bbb36e3c94619556b2c641d0ebb691b2706cdd667f55b8fff8fb46e3ac72f3682661a4bac2391075ff5145eb07d69d77437adec2d096c1c89208ab3e7a9ea6a0ff4a5bc1846b3683bd7c6ec4520c3c95861a5856b0191e4221c9819c67273c66729728f6035e79c0dae8842df4c0c27ada1ad18b34efcd55b94ef120762e87e8c5afdec80d5788e83f0d1533cdd7aea8f27f33266e007b274f6d48c59bcfad607e8b298be2b17322be88558c60033452826778f167f318b660607bfb2f285cadb385399636acb8f5350d819511b5e7931c5f8483529d3ab3fdb5ae2dde0ada918f1327c6c0dfbbf5ed3c8afef171910dd0169022b3cad5b08084dd5e8eb8ef1ecb17e48bf69f80e3db0ae1cc7b73d94b89696e3c3443ecb4c7ca12568201744d1858d90ff759f2d264d49edf47772bd0e0990c14dcf8c8a4c2dafa44dc6e92f4c66b03bdc4f68f28ca2d0811a433e184cced99a8e5614ca83c46ec18b47e0c7ae91037ae06c6d6d0f3dee19711c21cddafb5869416d23c5219296acda7774891877f3f8d46155d39f43ed10500ede3afa26943b83b800b54a9752250ec6ae173e920002f365d692a9b3a2f9b27124ac97b8e81b70e8c0bb7022d07ee97e962810962b03fc019695b5399f77aab414327cfc5dedd51e99453179c42ae85a42f8e06e0cec6f937224dd019c77c5a0ba32ad08107216a9c758138b730bd5b5f4b613f192839514a8621634d9dbd5840e728c1ef4a2c8bbfadc376dd80d13dcb327ce55ab536a43b570789f5c5e135ac0af79b54232613d0e989ae695aeb358c671ae71d508b58a793e19c58c3d204cdc9a021ecc634bcb0bd6a1917554ea3bd688adab8163260a914fc01d7ce05a497a5c5836cf9401cb6aa35cd008470bdecfb97a511c905badd01bbb4d0c05867661debd2162beeccd52399d5a70a929405293916f33ed0d03f8b850f4bdd77b1fb6283118d71de629577383c81cad086f4099ce7476cb787f73c96431a0df4156f7826fce9045f7e7c97bbfd618b845595203cdc8df4638430fac74a07bc5f773486731d8ad29c06695704cbe2882077a85d543551b7ba81b181ccb93d2b3071b1a38f3c762b42df8246aa64cecbdc772830ac79e766fa99e8c65225f28297a32526df9b51227bd368253737f013ae18435a912bc18cc4a95216ce449865e8bd8bc759dce9d4af52f9e789eafa37023e91946952202dfb7243cab7db2f9f98bb66f19750c547a2bf2e2ba92862ab66f33fcf465ffc41d23f0b891a3b28b3f68ea48dde6ad4802902abd22b0d7d9101bd61471c5d88ee9d9477b7cf9f6ac52e0f520c79278da22938745446f1e647ae478ecba416b941aa31f979d0633efe72910bebb8988de1d0013616f31c5da163eb6c07022649ac57422627a5642618f53103adc9918f9992c5b085e10d2744f9934bfbb994a710d6cd387c325e94278f97d5582864f1bb29a1400aaf674ea8fb99a3b42e4ac50418fd804a5b1471eaac4642d4aa338fd3d5d0dd84372b2c32c5cfe7f319acf731a9787b048cedee3833300dde639cb1386c8fbca4bae8d67fb7bd72d1696a0212e27e166e6b04a79e34b47c98502ed0bdbd8d61777537f72df569fe5ed30071b57e8724e98ccb88c07f0458cf32298cefb6ed672b255e581ac756789b57e950d57174bffd3f47bdbe4b168e7e3f1a6df508d4202d327947facfbf9526a9e5fc1a5abb179902d4584deae6cb2900391e080d3f3540b87c3a873ccfaee5b4aaff0e6516a867ea00b4d5e680fee6b91defc65c240614a1409bdd0f49c2c4f3c1d258d77abfc17a749660f49547adb236730e5a7a22fbbabdd8ca079a8efa5b605332db12f455868ab67a1ffd27d1339bdf8d150189cfbf6199c6fc27c05788138a63267eb8ac086e27286b4ef99ee9d92cfedab5ce9916675f128f206a1733f47a597232067aa12da20c7b9cab6575d7634f8c31e9a29948b528681f3f9c13b9f585ebfbff8c28a299a43e4409b31b6c02a79eeb493734fe5f9c1d9e3830572eb54229b5cf525768f695acff48c76b4a6e0936b7406ab69f06d33d3f04946db9d7966ea6e8c50ede5abadda28149edef5223a6938d5c32933070d234043feddbd65c81be218f9d7c497a1ecac30bb9162e60a9bbbcdb4fec4b212050610e2b376aadf58b3c9207860d2650d0310ae6606a8f1b266b6a13b68c3306ed413224abdf19371bac3ea1b964f28996fc70f666ff118c6a7c9f2108d327f5145919c03832f754de35f5979ae72130e39126499037d6fbb3751cbb4843b05d9dc91dd5fc1429da491f72e3069313ea243933b47109af247fcbe0c70f9024ac5a41815655ab309fcaa282d03596ba59cfee0e40f7bd657689453e98d562442fa4c585f970b6983a581b0b8eb1c5e780b3f5c1abb326213c6b5fd440c2187066ddf55f4eabf88804139392c45979440c6f05b7222bd95e963832d7fa4a4760273cc075e8b8feeccb917e8feaf7d3f766d9ae880487e69bc01872ba62b91b8af5dbffdd93fdc95e8f47ed793fc070a5991f2e9ea61439662dab218f643c1959171937aa160008a548f51f87b58f2c4fae5aed556f26bb9cd1dc2b3518458e2f5ec5d974c6e11a0ed639958cc8c1db771cc8cc8bee8727bf6452f47c9782acf548856a0e67841c3dbdb1c98572a4fc8e6cc8195a504019b4930d302a90dc20d8628ae6c90e0206cbb3d05025744db4e115cd3b650e5519a1624acbf226ebca8875b05183b2584e65289f8b9cec3f7d010cb9671a0e80bb70ca8763f1722d79e8decb6b9023baf64b5981e745c06546cc1e", "ade72c2ea29cf829ffe99c2d63840b2eef9b51a9919c02128347d2e88e9f063b86326928cf6252ce4beefbae7206dc61a22d0b33c90d464d551835e3b73c1e3d6e88663deab80c35a607e4180ec079b0ee84e3b7922904e7423acaf976e837", "43348cf32211d7daa300de8a4218543c8e3c7373ad10950765c39760f80b733c", "e4709d225a552e90fb357413", "562050bfb40451f27b1181c389508550a0f46b53d14ca73143da9dae3d3d2b466e9618db39e3219675d2b6eadded7dd9c741d7c9bf3c5619a521189607acbcf6b3964d469d966fa134444aa06d80749c873f0f976e0c5efc5be8d00a2729f03eda6a7b8630575df8b3a19388ff88daf0d00bb3e7c35a525ded90a4511ce815fe6c8904406cf72d7bfa14ca533566f7b54268835285c5402e22a63f98b5d90c86dae0a76d65eacc1ba85b3f5a1499d5f3432dd5455fab9e8bfbd266e99283c2bddf9b556410956b2f061603d1fc91194766f90da841699ba7da3d53ed5abdd8e98034f8fe734446d92b458a731aa4c578552ec1ac5d1baaccc4153a67b48a290602d5f955d61a08436b27cfb0786a80afef76e1266310a42d90feeb3bcc40ae5c4506432dcc92f7e5758ceaf277255401f5c5f4b10df93a249e38edd9effe7bacdf7fecc451d3b2cea77c9bab0403450c41929775b8c0ace46f6928f4d9cf3adf86832d298ea32b236d3201464e2ff506ef01da0e1e389e26e2b3ddc553b369b48d1aa5dd43edd5cab065e276aeff72a4c43206063fc7eea3bcc783ba2221f5b615a7a43a75cecda6bca5aa159e9208bf66af61e2e465c2daee630c4c62077ea6ef0e8b4b4e272d4e93a5f5284f9da463e1a60f815a8a31698ecdc09dff2b62f00e37aea5fd4b07a110cef27e12466c1814d3b10017cb9b8e12f2f38f10cbe31296de2570d5662b16639fcdc05db81e0d48178d055ef873501148d00903ec771400fa4873c5579dc3265028f531538f6dab1e5607a15c8b90cbfa4835107cba6f453bbdc71d08c7e423f58b44be38a9c8a610469f2551ee6177edf639cde35fe8e02f76b7ed106d691a876a4fda3b42d8ace3e0d3d4e026206c5d7d4d56fdda9dcd30fd7b74217fab3c617903f1aeffb8363443ed128af94c391810e327704d6f655e57dece97658d41e074029823850ddf7c5937af41c64465046d8544bba65c691ac69121bd272107f7eef8cfdb6a25da5da16d1033cede09129d51f6abfe63905a6fba9a64d7832fa35825447150595a60163af848eea878fb31a5fb97b1859efbfcc8586eebce8cfe64386461a9b88aa5efc1db43c64dfd5d4a45aa74803fd178f9e16a3f59acfb6e13a564d645cedd73890d0a82fb6dffeef527694a7cf2a89aed9750c3675a67505bff77de8d046087bd39a85c90aedb085e99baf04c7e3bf92e350b332da1b8af85550a00d68904ca426da61add864496d6ff442bb0b848e9aa463bb0c2085cff1a83a47d6f702bd184cfb5c139752754c8978d27b58d364bd88722b9097ee3a6ae28eabb14ca7c31e40461101e92448dbbc63b55cfe56efd078d0058c5e6146c73bcd949c4b3ec9f881b9a5f7b41ca83301261e0c674f2d35d96761baa00ce0675c082bf73dc52dc726a3e605067569a372d2bb47fc8fe1e74f00078ce6f352a6d9d97fd2834670ba3a45aa6751eafc7ed6694e1e07542860c8ea516f296ee901a3ee16b00b40419c74bf6db12c7230325e85a918f412bc2f6469c1a13a5aa77f028e327749efd05b91053f49d9f1edf49aa552c58c68257233a168db60ac55b4086ddaea275b078869cda7b69493c4b371b4e9c8361357a7ac7d3d3bbb464c960addfa8df2b208b21b090d540c440241598212d33273203d484e0930e22469c2a8e866579a4a2b3db8f8344dbf8baa1b97be0c4d976f6aaf14cc09ec52630139b894b2b6f4dad3a205a7b286253f1522b1d6e43bfa37beaf06f831c6f0945cefb2593b9b298da13b0d910582086c5d7e256ed4067bfb476dbe01bcddb437d46ba716d6ace2ff9912c8e460ad33ab3d8f97b7b08dd4ba9e01968d1949ff85b4b9d5b8da291fc0f90ab1eab1d246f67d76092b7a37528ceb388dd76f8a8f0aabb7490f02a2c8bc6498cb26350d859c466dd611bf0ceb81a8b7899c67742c22697ccee21c4963acb003d15c1a2078112bab05595917584e417db3872a0ff0a29138bbca7314449b19827525340370d7e48fdf9f7c6b4a280e78d00775a291081a5e78e7a00ff915015dd5af5f0a45690baba8b1b503bf85f326c23136f4424be4a559aed03fbc81400ac27a33dadb2155d1704950d98043dcd86df1eee78f3f266c4d14deb8126708f74b59aa15e8b497c6a52924a473f999aaf0abd3d148fee8503a1568efec7bfb0bd463402f563e4019cc9c9e1eb498aa54dcb659f43b86df0a34de4e51ec558bbbade3d69511d3fea2baf44f67e85ada7398d7f72ecadcd9e981f82b0743ed74bd33088ba4cbc85b0c99dc5382c599706dd2d51aa9f470c25a98e7e8248dec216a155495630662bf6ba0b7a4baa2cdad30e9ce3e1a65e3c23d69d5f946606ee8504dd70830aa5a8ddd84f10e064695469727d2efeb46186c9d3b7a170057636f05b9ec4c2de7d935fba504a1e7eddf7a5a95226b253b0b9eccec976ca3c57599850db40c27a51ae755c1f30d392467cb74e5c8235861d11d0f8461b0e1d84f5718d64ea92da62f4de184a6499dba473e82b3d197305de0e494f118a263237c7b4c0652327977edb427ccded35552c00a5804b9557ccf2bca2484d9da2c33f6c1bbf2c666ea10b4644a21e3905e5c4eb417ac3572e783428d23dd7222e75c356b99e8183d033034e29e618c90e66ec2f1e9fca47d82c1cffda8ad14c96045159d9437e91ecef41d24cff89009ff57e18c1a422860aa9cd31dd2a85b07422c72a5decc614a9742e62a4988f394421b6918e51c2412d749bb53b1e8fed7b2ef0873ffe14fa77bc366bbd5fa1432be465f5e25266c6c12b55df1f19b1a491acfc5c9019f122c422243d751d8eaa8ff721397915171556e999b34425f7d3ad6f6c3323b8133b4618c65ac16cb5941edc979472734bdccafc73c08939c0b1e306ae3015faa9cfa09ed6560269a1dc54c2c046a12a178144f4381f7b6fd3fd2d28f778d444d9f7a0dae00ea96c6969b78ef326a962d23275f1518f0e6a2469440612f3710b53538fe99a6179471be8c5b2d682ab3e9a5126e41ed6de000cd9e92fec3974e0f4cb2d2245d03d6ee80d6a793b16efa829d75c796f34d4e918250f457703559bb48ff78f0896be1bda403b7f1fd6a319d68478ff70d88238f2b8afc7d20e51757bb9db3bffb35a8040fc0db913c4f03d48619af7fd24cb8986b3e139058be3cc253b3de9b3bb3f8dab7b8818638279b2e6a0c29cfe16fa7250d3c74362ffa07e2977cf562140fe28afba8f61d81f7c73bdd4a2faddb00752bb049d0a57d05c6475c7387e6716ee31974169930c9fd830cef138659cf56f2212de185186c3d683fc6b7fd36e7821f69d0de041a569765066dc4a1934870a7b80f174e8f9e484942e62404a42b21658467873865ef94fc262c231527f39e82dfec91215947b99567daf75c6a28073ee4e67d4307e4b35b46f85433abd9812f35438b34598ff3b6dbd60b60747ad64565391df45ac80b272d0141702ab807fa27c6a6ba2f42c3facfae0c773940cb2943bb1353b41298258bc0d07542b69483e17ab9ce709e4160b80a0968dae9af8fc7c0324c753ca4a11a6df32dfa79a87b445c988154bb3c503e6884cf6d8f5e062a16b4ff230fbda109a6127d35e3bf2b29bfd3b18ba275af773b1981d603300035e046ef023d51874aa105d136bfcc9c7323bd0513a6b2b397ffea71afb7a8d4695411d86164917099eef504f6cff3c5cefb88f23f56c4ae3e2b09a3f353fa55630f45f06c29e8912e8c3c4f493f25eda781680585580595bba43dca9cfd400d9eaf5081d2c6697da59e012dfd0b875336b88fe16609c2e9876737b9afb868ed52417ed0c6b359d582d585ff82d98edd4e63c6b65cf43d4f69eee2af4819157b8a433966953862d1ff2c6d0cba382644a1b0033ddb7be3d1fa9a204042d7b821b293bd659dca980c108ad1db740800b9bd2fc1a163f9b4066f7604f160a7910bd947cb48ce6c81e680fc6571ff0cd12a3ded9c8cd560970ca5cb480a70a8322d5072edcd257604eba8dcf55f9ec97ea2b14fdcc72fbf615131836fb14e42b8d7171d0a06d2fb3caec2e0759e86b0d8f21e312d9211ed7fe0b48669934ffb892baf1db9aa457c07820723e5446420334bf6479f2099e01ef8adf273adfdd9ed0b741931284515d69c211cc2efead8339e450b13be71b35c36c1f00c2b8ed0cfa9792e422912e14b5b1455ef6abdbbec0035480c6cb69d21321d12ee19d528dd48f43b142cf0502eae5304ce52b7fb827552db9ab885b93e83d56a33346135aef11b7e48efca7cd52e2499a7edab0bd0562862187ff4599b2446bff11c37181092fbb05d0e05220ca6bc37f529d6599e8c29acb9f25616c27df291d4fb07430188e6470df7002f73cfe5fe6907dab0b4f90bb58130fe90241c29c6063a22c9f45d032b282eb92c93736692bd5cbde2a17552e942b595b08e6ba0c91a03b9079e9117fbba8f26ce6c5d0500c69bb6e22e3562a50baece49109c2d42b6714250665afd0f0a7e951182012f21aef4b917cd434d9ca22661437608e32666497516be34652500def6c28ef8f56f2273de5416142ce9606faf7df92ab779ed6aa74cb99bb1bfe758ffd344e1d31f479807326d1a7b98f6811e275545d69198707b0fbf027dc6a5e4815d62ef191535569a452c27c4e25ecf139df949d70dd5935bddc04f33b2f0bcf5073c51fc51c15067963a20569b5659f0e7413b347d6d5ee38a92b7e6e656c199149f07ebafe5281db6b1b2ecd9e0384b6f5a8e27ecea9a0249c61b16564964054f5f9621471a98de132e102f518c1419829e2ae2c8c5fffd1270f0a0b33a383437b0034783d50bce8bd7420c059d16364eecbd55b6ac8df8a70382734d8127f4f5895cc9e508b13c000ea053ab59b87ee639745418ffc566ceebad37a17b842d24d3423ac3f086142c622eceaadc4106f8c90c5dae1f52f407fa0bf1e6bf9385cbcbf3b61006ea3b1e66b693ce704577ca9598587f41e05d36d1de424e0e51290a5f2e2f99f1960c0253a046a49b19eef249ca2dda2af1e8dd78411088eff1e9c23c31bd20abd4fc9e7eab19500827d202f76270fe9f90e95309516343e0fca48e5a12182e91c78ebf2cdd4644629afdc90bbccb77546cd765135910ba1cd8a3e3c00fa77e585865e898bfecd06c01a0a4d7be483801099c61941c4967154af5620b171b426cf229df59d2944ba50754140c3f305c16956953be376fe6e7cf31a2e9c276bb09cc24c4b86b2b26f039b0d8511853adcb7feb8502e7641a34e3242bf2c538006bb1983345ec3cacbf219ef10efc1681d52e6e1b1c60bb556b6b8a63d1d1f6869077841d1b816f3165a35833e33d39a8c6e62a2f7c482c395768fc6a0e3cbfc7a1a6d64da53adad66c8016f76eaa73df1b8ef83012ecbe75c92a8e39b48169433f951a539b28a034d5fdd00639a5e3e17ef14dafe869064d130c90c68be4d5ceddabed1bc94e97e2cdf7313f780cd6e175a9e3eba3eaed896fe464073fcf07ae7b5bd41d58c3160f66ac95a76fdaa7a8cbaebb304fe3c8f03cef927a1182ac2281c3b32378813b24bb99e42cb0774331ad78b74d46b8ce48bbf4ef8431a82d4240edfd61b910c38570ba0bfbd4a41665117e6d5f5a97908462e62d0b76160d06aa56cc6e17aaf4607ba8263648f2a0077e306c25486f5f39a75", }, { "2f6210063cb3071b3d49339185c2cef8357b08ca826d8d1acd852540c16540f1c850f70404fe1f414853d3cd15a1c64a1cce149e3ca1b80926de4ae8438ad90bdad010decf2f201782f3e49794aae1b079f54eb59607bebde508a528927e346d4e444b1d736b34f65e198df2c36fa23c64f1f1fbf8b0b8ddb85d054bdb39b8297d0347f16f7be7cd9474c058e36294485386434b36fb28ee582e393367f15ce5f5a3d6641fbd31b331f10b1554a05da726a0f35c9b1b4af3498426b17582966a266cce452900f85af1046f45a4ccedca6ce02607fb70fa45f420f66aa38cd4c9f8a30e21a3067b940aebdaaeb7c77824a79e2ba20f26e70346dd6de96942b261e5c08288c7fe1cd1e9f680a0bdf8c46497f007a616eea95ccc17463559f8973eb919c68017e25100d9d1a196ca65fb615502076bf0b0c8bcc70ef22006895ebfa2243fba0791bae0625b762cc1718d1673948264454a200c58122d5e9b8b1e3eb05df8b7eeb297510e0d7dcf7f0be5f29f6756e4b177f109891e6825a9866359e35b10d20da7231bb5a0ea34abd0264b377d2fe9f420f27d3e5aa2e8e00541c46052966ef9b989ae5974e2054409507b867f647aa057f7deb19ac6929f0856005aec6e53a5f702fe6be403afed532b73d38fed73e6e551987f182a1e20801e7a6c8ccd1184cf0fefb4139fa166ca15395902ac40e7fed8661602853682a3b0ee307dffb44d0ea3012142a2880cb7c166ba6ea6a16c7e0882808db8023068f060e5ef1432fdb8331ffad6a7078d686d47d613e94291f1c4117e7c13aee4030fcaf223fcefdb300ed606b5dd931e4adbf45dc437eeb5fbff337812e15c15f026071423f6ef5305c559baa2ecd8ecc7cd498b043740ff3673774855d45d45fa64591d5b4970600ec91ab1b6f39d7dc0e709c41e49c355bd3b9d120ffb57095fb127bafa971a086135b917285794e83e9dac5ce76fb1a4aa4fb6b94a0dc3a9beea64b8817ec1e2b37af9dbd18ec30f2b6f6c12df1db6896c6c43b67a066038f0c4f17142b254f62c4dd1fedb950d07047919e397d06d033cb0bab6b61aefa6dee01720926b16beb9e8bc947dca9b8143b565da85d2dec182987838b267de9047f5b0d961c7971aaf54ae2c1e4aad61ff123c84e41a4566b2bd9e64247cf46b72a444d36bdced1a309b464ee5f4afe406eb68eb05ae51b76bf01b906c0ffbdeb440b11f1c9e3a4c3a809a1f7449047b356c663a1ab7f286a70d16141d11f2d151a4f06d422ab97cab539c1f9da09ad20c000c27b8fead5f0cc37329d466fa260aea934c154dc9c0a065df3d057a0f117a1c38321ae59226a8054f7d6b49a3753436c249838b0924f0e861f5627106dd8d3f0fa724a1cecda71d4a1267ed889b234ae4a7d5edcbc5d52cba389dc0152aff24d224c6a0f16dbd3b7f242807bf4b51a3f22690bdeb66eaa59e8766b3b265d784899d247a0ae1b58a06dd91c529e3691b09f9d9f55fc39afd4a00b0fc668880ef25a46a30861fba8cfd4b51262eba4138b41a2d13ddc71128c8c1242e49a51d6f49879fcfa7595ba4a4adcad3670b0b1b26382f03ff402bc70150f54bf513ba3e9a590e41b269e55616af297ebb3499e16cc8e46c0810330a602955553c0f93d668a1181a0bfd7021ad9a9f68ce39493b012da70a3dda149d0369f23f788616e0272efa322b6a54d804f340d32c890e2eb7b538f48f4c9293b584d22d0ae80d321607644271b81a76ac5b49d8e457069b0c3e909b8a222e3fa6016cb1e979e300804742f2005c68acb7b1849c088b3714c9c7af54e9de9390df0041c87924c8fa6b0aec6b6754171e059cba0d27f221f0b9d044a3aed8338dd8745651981e4b0329376f908b86ae9022699d495bbe3a148f7eb73d56eacb2e5e2180f63fcbfa680369f88eefa71f1210bc5b6b7b957f0a1437476a2112998033197673e470dbe7d9d476c97b95db8b5136f6cccc75d6e0ac1e4ace30e34e64fcc4d7e135b2c80e863ed701d3b28c25e982f1b5f8c895a4e6df7216c3c07abf8551a0ba0469c88aa7a08c7b5218a03b9b91f0935985373f65aa56286ad0e7ef2288a926f172b098123c136455b3a0f04590839e16bade7b6434a3cf048abe2612684c03dafd9cec39af508e63f07ea881014697bc24122058b5ef5d3fae835216d055f0cdf1dc06a12c95041d13ac9e15f235d11747f16ffce1cc3b8f508da520e395edd471f3759d8879ba9c2558b1188d822fd4739ed0546b0ce3bb9988db7c1dc8518ebbc62c4440e6e0653f917dcc13aca1864b71dbb67dbe7117474c936414e4f3cfab1f13eb05f3504484ce11977ab21ec523f97ba1b7ecb8fe384b634c30561cdb752fc67a2316bfa7e4d03f5f825d24a556a0460d8cfe0cc54a6f117ac52d553a5d1bb48031732716436675c5c3996b1939b127c6b0338bfaa29c7467cac9a127e455a715c9ce2b0c35a0d2f83a3d1273ee39399e6cc4980e610c752bd51652b96bf9cf34c7fa41fc9b13f5d55007483e4082ddac4675baa7822fd257452411b01de0e5e5da26e17539d64a89dd93c71d15a4c95b1a83039cb2d5f3f7fa04a817e48dfcbfb3de34ecb47f7592123caf27e17982fbfc8597af5b8aa6558f4e6c73db69328e47677afbe6ef8df82c3d1f0db6a108b2279f61822908d7b856432c32ac5ec0f3c53befab2a7ca356b9c2636f646b228b0a830d348be4ece2271814d477d4c73c0fb6e83a338b90ec4ef45cb25f7e3d6a014a9e8d2e8a6f55a383291a57f15667a73ea1daca31c7182523ca85a107efa2518d2f7f179ed4ba21fed479ef2be09669817133b2384bd85b155dfc1c4c9e6dd9ceecf06cc1ab8ebf7f07aeaae7441468b5471aed93f248a84f44c59be33274b11f651de010ab9f8fb24d3a99914e0147951c34280e7dd15ec196f9a4c86e55e7d373c7e31e6672d1b3ac6a45fa6c8c9088c0b8963d89f4ff1feea3e85cf9cf2f6c97128afd845bb131c6f62b3282bbba42745080fd457f1d3322058f1bd4be876bd01269546d1a853310b165926c1fd4e07054deb5d3fbe8f6007711d435994005aba95918c3df4cd390b165fcd139dd418ebbf661b6de57b655698a8a02ca8fad73e8c536c7110957c36e5494a831d536eccb97a2a9ef58fe58e2885aad170720ffcc57c7de601ea1cf723577a30aad8fd544317e33897c8b6c04e5191bec391ab990e197f10038c0726d371677e4a54c28d7ca5c6046e7cc4acde565b91f7f72af6109a0614160d3ae97e9257b8f71a4663b00c681e793cbb478306e97b0e04711eae7722b4845dadf2fff5bbe71ff24acffea2ee67df99bf62a098ddae9d4ebd3bc5dff04a2d9e3d1d83e8f493db3f63c9e24231b1dbe1147c79f21b0730c842f6983330c5c17dd34556d7e932074cfbe98f2dab5b0ebfd778a1e28fe2bac2d942f61a08b787ebfcdeb3d600bb130ca4922a4ffd38ffc4a1a1a7218451e45da4da67ad81ef898ece3d54cef877cb9d09f5dcf72eccbbc06e62f1e2b4d64059b0a807329780b155ce1614b68de04387d6108ef4dd3ab54b9da72e528d6eac3e16a360ae3421f3f23808a8b5e8ec3dbefcbca3c9f76905850033d78d9283bba9272c475b4e3b4d7643e62c2cc259ebbf168f890de88e82f8b26a7654ee31fe055e45609c70ae02b4942ee15678cd158f4c9e8d351d102ddf7a942458c6125e1457bea0d86ca38cf0c26e474b2b5cca77eb57ad0867cad7d25efc2b250e79396637ea3e948dbb855029cc9b452955bd04ad5a0d0514d4d773c0f298df7bc235a3ac64383a1fbd8a397a158e936b3ba81895a51daa89f51e4ae7a71a53794ff715a42f4fc3dcc9fd56df7bea4ab782534d3760e7b15605fc4dad16911656983c0ab77bce9445bbeb1537c55fef57a32c8f1404306a0a2ca7b73348cd99d0f9948875531cbb0ef7c036cd201614c33293d746c44140e0e8f82421c5bdf2bf428b249597df949fafdb5ccfe1618323f56a6ab9abab9a84a3beb6696ca918af244d34cc1cd95bbca4a87c860a0fa9ff6a04a905b0338a53f230bd5ee9c60e0e0332ca200c15dca0be5936b858d0a7b2e540b8958432e9767396c55d5cc35b60062580023b5cb2f9a5e9a1feba59a19f9a5a251e9d0e8500955a5df21da95213ced2260a2ed8f3d4b295c36cef750c89cf21985c302d5cc577aab7855409a912dbcf1d0a9800df4aa692a78607a40fd6d5a82305c58fcb3d2a82b27e8c5b91681aae62a2bf31ed55c494dbdc38eba30e83c6044945df76705228eede8470369f2e9941ddcb2f239fb3ff6bfcdb0efb5ec50f981adf0e8b213769ffbbea364b08cf8cd69abbfa2a6fe9865cc48558134a57bb5526b9d047e14a379d246de82d3d64f3c810ede280c768dd8bee25af287d5a8d94045ddbf5981382bc716ad9aedfcd66e0ab496172a24efe80649db8e1e83675fc8451e22c6564d8d6dfb285af7fec802b35f19dd8308c68952a11770247fcfecc4ed0e8a445c17b1573f0b4e3ed350f13269ceb572943fc435563459d5044699f1542335b03be6077af156b8c5a6a9f71078ad820cec4642427a9b187ee1b17036d5a5e6108cee8a7d444342eaec3afa64e77c71d3c2b3153d4e2dbb30df2b66b4d14cc45d3a4eda7e911d697e5763e23ee05311a20626df55549b8533c6ebe79737abf472f9cff08bec590943bdeb819d3f923f45b81f9a0cba1f3f800a261842d10cb4cbdba456c7fe5f0abb4a8b58891d97cfd6b669e2708922f1934809d51a1589e5f12e3bb82c9ac3e7e44e3f6e6cd63d428da624fd2f46eec38ff798a90d228efe50c9b67c63796347c8a2b53478f27605999a03c8e1f18b70e92419f646a7f49670aa12d324751aec17d0208fc296955b3098241189af8172d39a6819415cafb107c1842b369f174d6f37dd31cd728dfd0ab10f93609006342b6e4d6ccbfd1ed2bea2fdf5411442b04b1fe218916f159b20242f80b535b4e0a3024c6eff6a40bd0d3db24e51f5ff9c14e1b4a650ca4170ee70f0a3a5a58349a7d0b7a63af86347351696870b95231f76d8c5c6a20736907726341dcbb76672871d18c2157c094b929fd29d34f5bcaacd82706f89a60000cd341d98eb830b73a12335b69f3e0131ded3ce12c98bbd960d2d0696d40696a13ab43925374498d868cd8f070c9039ea6407fc2d92b9c39fe7c935bbcfcc5c0980952fb7dac79042951f49a1af828b138a87401c4104bc28cdf1e39dbd3fa63dd4d5f5ae9d85f032a43ad353bc5e6746e5a76326ab1f4e79103116ce70bc0b459200f32f85e461291e347dda92e421778b849e37a3ecb0b31ec6818e828dd3148dc74313aba43cc9d8b9a36a9dc4e229488060eb6c109f8ad6201958adec6d3bb3b04e5e558a272d44cb98e18f7a0ad8fa6ac3667a62f150830aa930f6166baac6b9081b44304988fbe1698a5b746255de26bb5988aca90bb6523cad68a7572f615f4aa58f932d8a749615cf0a7724e99de042268ceb31433e6df0a61547d576a6201b36b348c028ded5f7e94d1cd2eafc141088ff42cb3dafbbe4c402b93aa9d955df8d9d9fb57c75ac65c2c837acc44bbd4d4aff1888aed46c73d625ad7fff035e8ca0fe411c73ed8135b6b8e17a039ec74e9de0d64cb442bf8a676c0a666f68f21066332cd921ae0ed766f0516a8e19b82cf98e78add0373737a3419e13aa902310c44feae5fdf8bc64e80dce772686a31f141bcce452041bf545b908ef4a2b000e7beaf378e2afdccbbcaa42e330e5024400cf2852d3444718", "fd5008477b0855f6f2486fd4f74b9fb4f6e19726c6996bc66893183bd76054d5b05c1c2b64722256ba912ab2dcca66d2abfdf972966438fff7513acfb18ea461eac08c4e32aea4ed3fcf9f1c9905ee4402e7b6984bef974340d212f160b6524b76de99a98d3e96cc0d35e8a63ad7ea3cbea1d40a906c4dd03e5fc19e1513e9", "390a5e75c9ff4ad38fb6205ff47f209294337c1f25ff54a3c01eee8e1e220257", "8bf183347ec1ca4bceff3374", "19fa2641519e21293094e9d767ee1237f9e0715dc57172794867c3bbe2cb647f9b28a8d3f85c0ff557b91bad66f5ea16e0107757b0277fdd3ca05bf47c19bcb92a958a57e8c142a51af29bddb20af84377b6db65f77494e0dc4d2634a776b3a5d777319873bc0dacbbd4b9ebccfae849fa7e9769cdf54660ecca0d5cf4fa5190713726d54d02b3a3f21857125b8a808c0ca2f99d11dc430ed5113ee49ff8f00bcc08f0370dd510e8100e1285659a7b2c7457a6049f2af7786c4db1471ce5bd164e11c7a2165e83e03a135ae2b3429f82f677de044a067e99e0bda2d65a7270d629c00e1d528212d3aeb2896e58ee5145a93ed06a9c00705ad5c5988d3a192304c1d17661d45257c5d16799ef70771964435b12e3b2ee9d5b467c3b1992f45b7a59871b40d8daa1c280747ecb3d170257b91df1f549ce6d66455b5b6f60b7c6e95c92a67e20cffe8599ceb183de53f1dedfe19bae836447af8e053ba419660e0912cad064d6125b9e978e8d0d5f28f8a4e43ca3cdf2d4c0e9a11221d8184e9eb6c90761b0beac82d0d22793279aedb1c7db3632adbee323bc3bbde4801152694831abf5676979af26af7dcbadfba1cad1306b635840cbca76c558b37db0803b4c12befa27d16f21506b07ade4a838d6beba1816eb29ed5e3c4f132a752fc747bd9ba879156e87e6c1584e911da9f796e1fa4a055e427272559e4bd6d0f54b8257100f8a55d84c27b702bb1fe2f995425c85fd48b0a0610db5b39f7a5031407a12dae9f508b21b1378f14952d1beb2dea81d016b2d9b7f1a67b814569b69c0e619adea02a8683242d63a11d3317d060e5b4d85df5ad73127541ba5314715d187990735aa81f438f8b94070ec506ba536274d98b766c1694e54367891a602b99e370425b47a70b819277a249fa429c5bbd0530267f987e6022f25030c30f3baeedc0d13c95f3d5e4b2b87465d179a3a23b9f9e76a42ceea55226ce072f9488392f40621289124d786109d2498e74fb37e2ef466fe8bf3016d96e34204c32978775765aa80461cac48518157f86d59f6187bad4ee62fba1ddbe166b29452f4a59af1e057300c353440644a8e40ae8171ea028be2fa315804abf518847c7945e8228b7766cfdb08d3a3116b59aab8e94b6d8c8c9ef442c2dc7f923bc2cd3e5c663baca7dded976bf191fe36da16948c89c385fe71434f4aa5dd15fe0e925d2459e3b068b9d82a9cc8b8f9786bd9f5fef9baaaf2d67027d9bfd58bb2c58ec7c746b747ab62f9242e4b53ed14d6fc75f5280eca0de23717c97a2293826e19cc8eb47f946421516c349dc4ba49225b91e4e868874bdebd373700df1f3792aaa140597e58b88f90e163397dbad3941705b53d754e3e0c9003df836a7fb8d23f40362fcb5f3947a4281b24240be4ee89aa8e917b194f94345eeca224df0adc15f22a617b6427f29410bc48ea3f92216163785723efc36301d23ed52780c6fd7924bcfaa03269b13582b7c7ea9c0e4a451f38a469fbdb585dcb7c81452da77945ebe27eb26ff6e8c7b2decea289aac5af74746dc257c9bea44a0847f02c4f586e1d76f39d5bf952355a0875f177a666d1d354ad86ce5ec0aba2c2b20cab050eaffd31095395132f5af80a2d2d53b77bda49f948bbb37bdf31c8a690476488e14e542ff6841e7fbfc2eb84795696562d079dc1612274b6dff362567084f793f0bc2dd8de23392d05aeeeeac6991c9f74387153a4b7da94790375e336a00c8293bad0fcef2dd1880e7094e2e53f738247c860780ebe308410ca02ae409ae720e841f48c9677acc6e7d4ccd18c219c400f8b7e1257f692e09eaef96802b17a1cb7d93eb81d3bfcbc7af4cdf05b98e22556b3d1a8b56d6d83bb5f5724696f8f329839dbe477483ec3c09fa2e0628faeba1bf285c224bea3f6cdc7bbd768133c6ef1da14f248cc3b819b196588811b073a7291817bd1e89c65760435d8d17cbf9423744a92143e0f956e2977b39c54fdead5a57f3a04a0facca01bbf44d3b1fb9c4fa83ae1046985e3f26aa0a437999004dd8adc04c5111759849f919b93558dbc559173a23b069b59f800096d9fcf077c7640f59170bb9a6fffe64778bac272365d27ea62aa956559e90edd3f6393cc8775597bcf7d91990ab9511973d948324a27261059e93f4b5dd2f70caf12e1a08e0493cb05588618764391f355379578cf94dd33e616136eea997ec11c0d4ff064ff51a767e5558433a2e3a9a74c232d8e187f47b8cca010709eb9fea0dac8f1ea53bf18822e154ecd929c83b0eac366e30fffbd5ba6a46d734f58d26e7f5df538e18b3d827884aa857a680823131bcf30a76f1a555bcabb17b02b53aefad96fe76f7312da69719434c580d3ff1bcdcd594e6375935003d5d732cc577e11ea2abb1d04259f50aed4c3af9866e8c4a52a09809046ee330f05c4403acbc297a9416c5208fadb31ed4eb7a3b01b87bf08c75cf44c2b0df84df30872d021d6567ea649859268e5e1b5b6405e1b41e350a32c1af13722959c17c01b52c42241313b26b25995a1c89a53e248488724d280647226195746901929501df36d1e94815d7fe6c4ca2731f3181293217f71b9d7f59c2474856972013924ae4796db4cbd22d8905a6043c959941ca6b556c53d1688c439036c715d33a47a7dfc2fe40e53424c5093020d2e85e4b04aa4c704ea5bfe5a2384878da38319c59d41d66b6add2a443d9ea11edd8d18fa41004251653857733b388b453943eb33df93dcd5d549757fa2967ef0f9a5105836c48826c47fcccb2d9bc349032b286962136b848632bdcf186a08cbeaa52d195efcfc3a440bac154971d11ff4994f293b14fb8c3214ebe7ab8b3d0f2fe0b03ed7b145fafd7730a173e3cc1847f0cdf2cf629f5ea81a07bef716b1a67dd9e3b7a52fea1aaa7a393f53b5bdb5988df78a57a9dad19a8253316835acab8a6b9a9fb42d97bf29b2443322f46de386fd82bd3453ed68e2370c6eac4497b1bde7b42d569c452f377bd38bd50fa5a6792ef5c9ec6c647001149b86fedb3e2f18d4271e9cc4801aa16ecddb31b6a795fecabc613bfbc8e4f5636d71e74595c841fd11b6a6bc7f169317c1added56b82a71fc36d774bb4d661685363e9da5fd2e1f357006dc5b5bbf8b42ee3f869e75a541586fba558a8f490d641b78c27368b9b4c2db046354e9358ae9140e91cd95ebeffc6c0d2676a3ff4ab10d463bf32bed97023a80a79df191ab9858c43537a03072a17c30b1bd99efbd361590ed6b7d5b0ec4e2326fa35904ab9a48596f44491cbbc0112890f9386ed04dec30126be359a05e99b2b77fa2c8f6b7460a6cd590d71c73b2a1b23312ff89306b6e41c76ddc0a099bfa79498e36ae5cf0c560b8854dff32d2b690ce0ac4aabfa723ac6f2e97ad1083235196b464ad67fdd649aec01695d55c8b4bb198f30630ca635aa5a1915f3718341bcfd8b522f764015fa5479004d28eceea7fe67df7ee24a97a9708d528b89589f1899f13242a0d00f7464c3cdfce213699340e754533b934f4a8410224e111f31cf8e54d7b5e90cd8c68bf96edbc8d183894deefdf4fcc1a83162a3f6341dcd9a9aecf171c0df28257a68b1af1b67c54c43c3cff27fed89cc64bc46e23a49ec74a9efbab7981d9f0a018247441e4f0f5b5f68ba9325582f92de4cca4a5f878a0c5c387581e64324e3246d8f3205c838a29f1abeea24446e496421f0e742d411adb55f70272ae4a992e825a3d327e44b8b3762b25aa451d07eb4eac0322b431fa676462632daba2aba7bdeee1b438f051d21d4b1897e2ac2f95ee7c23f9996a805de8fffb3b30b855cd6c5b84c011accf4bf94d304d944079f04b5cadf8fcd6751c22a0f9165ab98998b2d89e6514641f1f3b91b8c0bf057d69c3d893fc4e041e06a2229e2ee58082ffb58cb920972ede58483287d0ace94c1becef26a410b93e4ff402e61dcc574b790d49679f18f4e2004f8b7cc357faba34a80e56821bb5b883d1a8b49c6605002152f270bbc36bc79095644e29ab08cc988deda765d67e4fff12b726d5de135ff9d0cbd9d5f9d440e548836633b93a38330d638468b59a32642da3375cdf70b062d14b46a78569c24a706e179baa2058dcae5c61fb6cadd9e015b017f26e9dbe3e6366cf5f1ec839aa3bbb21dd6c9b8e910245fa95b09b7d6cbf08a4c6c84bef257a70389be962dad14d97a893c128b73bf6580689e540d004f21edf8403f36b1ad7c9a2e83ffceb141af59700c316c8c1e3347187f24819c2ff0c9f9a2360dce354f3374374eab1643d2d8831310a8e3ca6768200ea7759822b82f7027cd450479fcc7f6d04802b15735a137ad489f1e1ee78434a253a9dd16684ad58fc91960cde6754f82e8b38edd5e798fdbbbf8fc2e2380a4e21dd94f8c1c063b18f29d8cd8d89f65deac5640799d4ca2caa29c1e72ad8bc417490d11e4051d94956fbc74289857e5f8e9e87b9a2d83074a994de0b10bc7782f6650cfbdb8c835c81cd88bdce5f04ca939b3c5cd010d4dc5d51224fcacbca9851694b8bf55b22dead859d023eee5a7ad3436a912c3fc0284456d5d72ea5f1afa8545c856676ac2dd9a057028bd3ca0f50e7070fa74152f13997c95c1834c3e67504f1a4165d2b49a96919b88f72caed60f56ca7ab5a3204fb12ad3592c725fdebb048732fc189c7dfed185c6c184a626e07d7356860d00389862d5b9701eaa4e5f7889e6db0f54633369b8d26805c08471de8fc3f8fa1fb0b0711d9e015add5373f7f8b64abaddbac3399c756244b1b07c579d33e4967e5e0cf16de29cb8a7efad07ff9039ca305772a6e45c76bd9b77e24949556766a8b8425c5e595efb431bde4ee222f9eb3fc2d002a1e2d14db2b23135266c942eea33bffd30eb0218405373240e0cd3040436ca895093bf056fd001c00ba59d90502042e6e6c0167105051628895c8164c9ab959400898309cabafdef12be53604fa57df44e0a90a81bd63c331291a93bffefe809e80db0679568f6e94e0d8e2edec0087c35bcb3c4f4725e6013bcf197156cd9d90612423348123383e45c14d27d8833f56ddb04083c069fd6e282fe69c940840f5f747dfb72ad72fd8cf9f3ded15c9e2f4727fd60b4f40e95dbe77a89b47dde7d5326942600554905d9dade9d145ab6da802643f2081678392609c2fdd1b79dd8caec137cbed315374c6f05c0758070f3bb17e23d81ccc39c6aa89913897e487fde889c5aacd422278f8571641cc4f0a93d9768aef9e45d6bd187d1ba637ce0fbd3c573d6778cf7bf5188c00dcdf13be3fd599143952b376220283e34e014e83b214bd5f64eb0ecb098ae8bef883949907cc36e22ece60b893b963cfa73d120513e285aaf70ce5add34edbdac60b3aa7b385b90e339058fb9b3cf984b06f79788016035c5ce490f2de7995b98a8c1c9c80f29603ae2b7fc41886663163e604275cb085f8453b27f4d795b9bad19ade2f98a1c99b43a7581bd991e5d0e5e1a6e713acc522ba9fe8302658a9782558e35436e714ac6bc85ad1d3cd008f24106901fa954f5fefb61210d6f8dc9ff35c480f1d14e59c0e501917a31ee9d00c6bdb06a00af5a8b08c3928cc5f37476248223627cb77eaf0e96213cb0a13e97d3fe9b9814d462690e8d68d02655a32fc271ee73db4f88a33386ea88a5857e15a28d9b3e3a96f00c7cd85aa53f9282ab8c8ca6d6a8afed43aa87fe7fc1ad59b0f0db2dd25c20af96e8c282c19fc883ef01a4060398926a1c82f07bcd3bc314580d7636b623b7bad8ddba05850291a6344df0f346fa4a321a85ee3e9c", }, { "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b", "0942e506c433afcda3847f2dad", "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", "129039b5572e8a7a8131f76a", "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff4b4086fbbd1b6cec23e45481eac5a25d", }, { "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314", "d3d934f75ea0f210a8f6059401", "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", "129039b5572e8a7a8131f76a", "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f685eb7731024bbf6794c3f4c7c5a1cf925", }, { "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314", "d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9bbce9e525cf08f5e9e25e5360aad2b2d085fa54d835e8d466826498d9a8877565705a8a3f62802944de7ca5894e5759d351adac869580ec17e485f18c0c66f17cc07cbb", "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", "129039b5572e8a7a8131f76a", "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68a12d0f1cc99e132db9014100d9668c91", }, { "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9b", "bc", "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", "129039b5572e8a7a8131f76a", "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68d1f05b5662cd6e04de896d3ef5dae4149485a5a2093ff4ec74b20b5e5bf8e61b5c65515938c202beab3eea5a498d2f32d4d00a24b826b6efb16013ef54cbe170", }, { "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9bbce9e525cf08f5e9e25e5360aad2b2d085fa54d835e8d466826498d9a8877565705a8a3f62802944de7ca5894e5759d351adac869580ec17e485f18c0c66f17cc0", "7cbb22fce466da610b63af62bc83b4692f3affaf271693ac071fb86d11342d", "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", "129039b5572e8a7a8131f76a", "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68d1f05b5662cd6e04de896d3ef5dae4149485a5a2093ff4ec74b20b5e5bf8e61b5c65515938c202beab3eea5a498d2f32c38dbb37d04f8272e741da2802c54a9d9aaf8ecf38b36fc9ad0079523f6a4abd5281a22697a3180bc02662a7c13ee23599d18e5c48300dbb831509df4c172f53e524b3c15124a87ac73e5028cde6c94d8d", }, { "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9bbce9e525", "", "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", "129039b5572e8a7a8131f76a", "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68d1f05b5662cd6e04de896d3ef5dae4149485a5a2093ff4ec74b20b5e5bf8e61b5c65515938c202beab3eea5a498d2f32c38dbb370a9bbc3187cc260ddac991f94ce4f0d5", }, { "0fb826ddb2eb5e708de203d0438be12cf708d635ebdbae56278be09077009586b9bc646ba7c2db35a5de05e86ae71461efea96dac64430edcf117d461113cccacf303576f310ab98efb180599894ba877e50614494923163a3afa9b4c2757f91a6b40799c5b331b464b10dfc45c783c317e408ab76390e19e8b7ceaa2c4d3bd201436bc6f69c7a5a4d8756924ed95665bd5e1034971e4d80d51b2a", "026866d46aa940309fdcabf92a324fbc", "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", "129039b5572e8a7a8131f76a", "30f05cf8189bb7b8b4f560e746e228c4cc7e86e8f2fa66e1afe212d1855db51070acd5eb34ce80b2e223957df50fde4c2531d97fc9e573725e7a5e47f0dfc4da1942620320bb2deaf8b17937bae4218d04db8e76f6efe84a117292159507c9f8a09fb2c17921d7762510dbf1dac7b62b1bd7572e3e2cf008d01c445c7fa78833235034281ae180e051451c6a64f22ca9708634bd0d604e4cfcd971b13742efa5b6363e662a875daccb2b00", }, { "c7d4f8790e4c47d4daecbddf5939973521ddbf3b832e564afc66f03b5583c41c58bd956609dc3ae3c8f7c2213059575236168dba44e3044049f47c9e7840bbd0fd5036062d70e9f567ac1797056ee93c8476f6c959fa09a3ee854166c6fc36c34d6cca7adcb36f435f86db65f4c4a1793b974294914b377fd179e697751c5ac289243c65d8aca93732849c27483da083d4e218652d4fe5fec8cb953ee7f00070143dd6ece97f241b03c0424bfee2cfd2c4e738f2361df0ffe8863dcf763d408a7a167763959b7f985bc1e359a4b22c6899645ad0814bcf69d10c38474978d1c48e482723e3a6bb3f689f980c51c474eb28cfbba91a8a12eb964b32dfc303a3524ccb752f71316ed9d007e521cb5a0cf429c79d4351b02ee7fb60c7be636a10af3586dfa7b74d80875466a820c0b514e97cb12cce615ab55cba7c1b1de72bcd1cb1acc368f944ef4eaa986e6a4d8253c9337f9795d94df193c90cb0b0387dcde929905223d441717ed9dfe826613bf094ba872993d41b269e27d74e5f541b497eac9ba180dc12ffb6f1e7dc5223cce6dd541071282b97c6526e15b2c330fb41dc96e25d72f45c28e543053766d11d44252db54e584c14abbb295d7e5a58bf36eea1936095ef897a338eb1995fcedd85fc92d354dfe7ff9a115c186bb4d7a1a27835030d248c87571a38f17906cefe0261d15740b9", "56", "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", "129039b5572e8a7a8131f76a", "f89c825ca43cae1ce3fbdee85c505edd1aabefe69a0f9efd740f027aa7dee48a91ad24e69ad061648f0a52b4afb19d7ffccdc21f4b4247dfd89f5f9f998cb3c02b226173fedb6f8770aceef9271e7236fefd19fb3b87d08a5c587ac7918e80aa4b477f22602189811e270d686bc4949137a41d11d95ec96ee9d26c6126f6e923ab37638b34d1538d2e46d6df6216da4f193a3cecb731e632e109ced643056a1673059355d2d1314df35ded8364efed7de490201090a6f2d1751748585f64d26041637ba3723cbc4b60e226f10a19699d223075bc1f27d82e7f560c0db630ea670b3f8a70a8950894af4d1c7b3f674a3fa00d19ee4cc2b6174c1d259a297424bf2c3943a29a16a9830ce11abaa79cd2eb77b53a02b365b1838e7bfd5ae1bd044ffc885c61c6b2186a357e8b8f732b7ab96517969aeb70c7b493bbaca9462a61815a3c6135c748bf9c8487ac0631807aa69243fa09cd3b8efb63f8d4e090ad30b6c2f08bf4e82f191cedfa5cbe2b42268d67ecd105918181e44fc9879efd642d20be84e6f74717e03fb94fcbaa6ed3b307431d2a9384b8a2b3e5825ffce8d99af48f177e43bb4272226d8a5edd37d53807f768feb9e0733b437a1d0f84779ab68a1804e92a5eecca56364f0fa6dca152203b249fdc8fbd950fdc37c1887596308a90ba3a5751c7096bfbd1cb177bb17847b33c4379b43938a67674459cd9a06e3017ccac5b", }, { "135a28170fe89066da7bcff3a9ccc1b27dfe942a6f47b23835ef746aaea63dc10066d90f4e697528e5451b8e11dd408fdbd4b94a1c6c82515bf7bc099df9cb9d5fa4acad0d22d5f267f18078cec107a995c1f3b12d7603886dbf910ab85ca7180053c50e759b00dc8c81555a425c03d71df6894a6c8cd2d94b64e303c08a1bc1dee1cf537ccf300850856292e1656aff5bf349c87f1ca1ca8085cd400fe901edcad04146a0714ef0f6b083d715edd670e020385f3cda29bc5ff6fc6edffe5ca9ce9def6e0e3d5f04ede2db02cfb2", "73afd2ab0e0e8537cae42dc6530dc4afb6934ca6", "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", "129039b5572e8a7a8131f76a", "2c125232a59879aee36cacc4aca5085a4688c4f776667a8fbd86862b5cfb1d57c976688fdd652eafa2b88b1b8e358aa2110ff6ef13cdc1ceca9c9f087c35c38d89d6fbd8de89538070f17916ecb19ca3ef4a1c834f0bdaa1df62aaabef2e117106787056c909e61ecd208357dd5c363f11c5d6cf24992cc873cf69f59360a820fcf290bd90b2cab24c47286acb4e1033962b6d41e562a206a94796a8ab1c6b8bade804ff9bdf5ba6062d2c1f8fe0f4dfc05720bd9a612b92c26789f9f6a7ce43f5e8e3aee99a9cd7d6c11eaa611983c36935b0dda57d898a60a0ab7c4b54", }, } ================================================ FILE: go/internal/internal.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package internal provides a coordination point for package keyset, package // insecurecleartextkeyset, and package testkeyset. internal must only be // imported by these three packages. package internal // KeysetHandle is a raw constructor of keyset.Handle. var KeysetHandle any // KeysetMaterial returns the key material contained in a keyset.Handle. var KeysetMaterial any ================================================ FILE: go/internal/internalapi/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") package(default_visibility = ["//:__subpackages__"]) # keep go_library( name = "internalapi", srcs = ["token.go"], importpath = "github.com/google/tink/go/internal/internalapi", ) alias( name = "go_default_library", actual = ":internalapi", visibility = ["//:__subpackages__"], ) ================================================ FILE: go/internal/internalapi/token.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package internalapi provides a token that restricts access to Tink APIs. package internalapi // Token is used to restrict access to APIs that must be exported from their // public packages but shouldn't be accessed by Tink users. type Token struct{} ================================================ FILE: go/internal/internalregistry/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep licenses(["notice"]) # keep go_library( name = "internalregistry", srcs = [ "derivable_key_manager.go", "internal_registry.go", "key_derivation.go", ], importpath = "github.com/google/tink/go/internal/internalregistry", deps = [ "//core/registry", "//monitoring", "//proto/tink_go_proto", "@org_golang_google_protobuf//proto", ], ) go_test( name = "internalregistry_test", srcs = [ "internal_registry_test.go", "key_derivation_test.go", ], deps = [ ":internalregistry", "//aead", "//core/registry", "//internal/testing/stubkeymanager", "//proto/aes_gcm_go_proto", "//proto/tink_go_proto", "//subtle/random", "//testing/fakemonitoring", "@org_golang_google_protobuf//proto", ], ) alias( name = "go_default_library", actual = ":internalregistry", visibility = ["//:__subpackages__"], ) ================================================ FILE: go/internal/internalregistry/derivable_key_manager.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package internalregistry import ( "io" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // DerivableKeyManager is a special type of KeyManager that can derive new keys. type DerivableKeyManager interface { registry.KeyManager // KeyMaterialType returns the key material type of the key manager. KeyMaterialType() tinkpb.KeyData_KeyMaterialType // DeriveKey derives a new key from serializedKeyFormat and pseudorandomness. // // Note: The given parameter pseudorandomness may only produce a finite amount // of randomness. Implementions must obtain the pseudorandom bytes needed // before producing the key. DeriveKey(serializedKeyFormat []byte, pseudorandomness io.Reader) (proto.Message, error) } ================================================ FILE: go/internal/internalregistry/internal_registry.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package internalregistry provides a container for functionality that is required // across Tink similar to the `registry` but isn't part of the public API. package internalregistry import ( "fmt" "sync" "github.com/google/tink/go/monitoring" ) var ( monitoringClientMu sync.RWMutex monitoringClient monitoring.Client = defaultClient ) type doNothingLogger struct{} var _ monitoring.Logger = (*doNothingLogger)(nil) func (l *doNothingLogger) Log(uint32, int) {} func (l *doNothingLogger) LogFailure() {} var defaultLogger = &doNothingLogger{} type doNothingClient struct{} var _ monitoring.Client = (*doNothingClient)(nil) func (c *doNothingClient) NewLogger(*monitoring.Context) (monitoring.Logger, error) { return defaultLogger, nil } var defaultClient = &doNothingClient{} // RegisterMonitoringClient registers a client that can create loggers. func RegisterMonitoringClient(client monitoring.Client) error { monitoringClientMu.Lock() defer monitoringClientMu.Unlock() if monitoringClient != nil && monitoringClient != defaultClient { return fmt.Errorf("monitoring client is already registered") } monitoringClient = client return nil } // ClearMonitoringClient removes the registered monitoring client. func ClearMonitoringClient() { monitoringClientMu.Lock() defer monitoringClientMu.Unlock() monitoringClient = defaultClient } // GetMonitoringClient returns the registered monitoring client. func GetMonitoringClient() monitoring.Client { return monitoringClient } ================================================ FILE: go/internal/internalregistry/internal_registry_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package internalregistry_test import ( "testing" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/testing/fakemonitoring" ) func TestRegisterMonitoringClient(t *testing.T) { defer internalregistry.ClearMonitoringClient() fakeClient := &fakemonitoring.Client{ Name: "fake-monitor-client-1", } if err := internalregistry.RegisterMonitoringClient(fakeClient); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } got := internalregistry.GetMonitoringClient().(*fakemonitoring.Client) if got.Name != "fake-monitor-client-1" { t.Errorf("got = %q, want %q", got.Name, "fake-monitor-client-1") } } func TestRegisterTwiceFailsMonitoringClient(t *testing.T) { defer internalregistry.ClearMonitoringClient() fakeClient := fakemonitoring.Client{} if err := internalregistry.RegisterMonitoringClient(&fakeClient); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } if err := internalregistry.RegisterMonitoringClient(&fakeClient); err == nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = nil, want error") } } func TestDefaultMonitoringLogger(t *testing.T) { defaultClient := internalregistry.GetMonitoringClient() defaultLogger, err := defaultClient.NewLogger(nil) if err != nil { t.Fatalf("defaultClient.NewLogger() err = %v, want nil", err) } defaultLogger.Log(0, 0) defaultLogger.LogFailure() } func TestClearMonitoringClient(t *testing.T) { defer internalregistry.ClearMonitoringClient() fakeClient := &fakemonitoring.Client{ Name: "fake-monitor-client-1", } defaultClient := internalregistry.GetMonitoringClient() if err := internalregistry.RegisterMonitoringClient(fakeClient); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } got := internalregistry.GetMonitoringClient() if got != fakeClient { t.Errorf("internalregistry.GetMonitoringClient() = %v, want %v", got, fakeClient) } internalregistry.ClearMonitoringClient() got = internalregistry.GetMonitoringClient() if got != defaultClient { t.Errorf("internalregistry.GetMonitoringClient() = %v, want %v", got, defaultClient) } } func TestClearReRegisterMonitoringClient(t *testing.T) { defer internalregistry.ClearMonitoringClient() fakeClient := &fakemonitoring.Client{ Name: "fake-monitor-client-1", } if err := internalregistry.RegisterMonitoringClient(fakeClient); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } internalregistry.ClearMonitoringClient() fakeClient2 := &fakemonitoring.Client{ Name: "fake-monitor-client-2", } if err := internalregistry.RegisterMonitoringClient(fakeClient2); err != nil { t.Errorf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } got := internalregistry.GetMonitoringClient() if got != fakeClient2 { t.Errorf("internalregistry.GetMonitoringClient() = %v, want %v", got, fakeClient2) } } ================================================ FILE: go/internal/internalregistry/key_derivation.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package internalregistry import ( "fmt" "io" "sync" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) var ( derivableKeyManagersMu sync.RWMutex // derivableKeyManagers is the set of all key managers allowed to derive keys. // It is keyed by the key manager's type URL, i.e. typeURL -> true. All type // URLs in this map correspond to key managers that are // - in the registry and // - implement key derivation. // // This exists because of Golang's weak type system and the desire to keep key // derivation non-public. If we do not explicitly restrict derivable key // managers, users would be able to register any custom key manager that // implements DeriveKey() and be able to derive keys with it, even without // access to this library, internalregistry. derivableKeyManagers = make(map[string]bool) ) // AllowKeyDerivation adds the type URL to derivableKeyManagers if the // corresponding key manager is in the registry and implements key derivation. func AllowKeyDerivation(typeURL string) error { km, err := registry.GetKeyManager(typeURL) if err != nil { return err } if _, ok := km.(DerivableKeyManager); !ok { return fmt.Errorf("key manager for type %s does not implement key derivation", typeURL) } derivableKeyManagersMu.Lock() derivableKeyManagers[typeURL] = true derivableKeyManagersMu.Unlock() return nil } // CanDeriveKeys returns true if typeURL is in derivableKeyManagers. func CanDeriveKeys(typeURL string) bool { derivableKeyManagersMu.Lock() defer derivableKeyManagersMu.Unlock() return derivableKeyManagers[typeURL] } // DeriveKey derives a new key from template and pseudorandomness. func DeriveKey(keyTemplate *tinkpb.KeyTemplate, pseudorandomness io.Reader) (*tinkpb.KeyData, error) { if !CanDeriveKeys(keyTemplate.GetTypeUrl()) { return nil, fmt.Errorf("key manager for type %s is not allowed to derive keys", keyTemplate.GetTypeUrl()) } km, err := registry.GetKeyManager(keyTemplate.GetTypeUrl()) if err != nil { return nil, err } keyManager, ok := km.(DerivableKeyManager) if !ok { return nil, fmt.Errorf("key manager for type %s does not implement key derivation", keyTemplate.GetTypeUrl()) } key, err := keyManager.DeriveKey(keyTemplate.GetValue(), pseudorandomness) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, fmt.Errorf("failed to serialize derived key: %v", err) } return &tinkpb.KeyData{ TypeUrl: keyTemplate.GetTypeUrl(), Value: serializedKey, KeyMaterialType: keyManager.KeyMaterialType(), }, nil } ================================================ FILE: go/internal/internalregistry/key_derivation_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package internalregistry_test import ( "bytes" "errors" "sync" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/aead" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/internal/testing/stubkeymanager" "github.com/google/tink/go/subtle/random" gcmpb "github.com/google/tink/go/proto/aes_gcm_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( typeURLRoot = "TestDeriveKeyFails" unregisteredKMTypeURL = typeURLRoot + "UnregisteredKeyManager" notDerivableKMTypeURL = typeURLRoot + "NotDerivableKeyManager" failingKMTypeURL = typeURLRoot + "FailingKeyManager" ) var once sync.Once func mustRegisterBadKeyManagers(t *testing.T) { t.Helper() // The registry does not allow a key manager to be registered more than once. once.Do(func() { notDerivableKM := &stubkeymanager.StubKeyManager{URL: notDerivableKMTypeURL} if err := registry.RegisterKeyManager(notDerivableKM); err != nil { t.Fatalf("registry.RegisterKeyManager() err = %v, want nil", err) } failingKM := &stubkeymanager.StubDerivableKeyManager{ StubKeyManager: stubkeymanager.StubKeyManager{ URL: failingKMTypeURL, }, DerErr: errors.New("failing"), } if err := registry.RegisterKeyManager(failingKM); err != nil { t.Fatalf("registry.RegisterKeyManager() err = %v, want nil", err) } }) } func TestDerivableKeyManagers(t *testing.T) { mustRegisterBadKeyManagers(t) for _, typeURL := range []string{ aead.AES128GCMKeyTemplate().GetTypeUrl(), aead.AES256GCMKeyTemplate().GetTypeUrl(), failingKMTypeURL, } { t.Run(typeURL, func(t *testing.T) { if err := internalregistry.AllowKeyDerivation(typeURL); err != nil { t.Fatalf("internalregistry.AllowKeyDerivation() err = %v, want nil", err) } if !internalregistry.CanDeriveKeys(typeURL) { t.Errorf("internalregistry.CanDeriveKeys() = false, want true") } }) } } func TestDerivableKeyManagersRejectsInvalidInputs(t *testing.T) { mustRegisterBadKeyManagers(t) for _, typeURL := range []string{ "", unregisteredKMTypeURL, notDerivableKMTypeURL, } { t.Run(typeURL, func(t *testing.T) { if err := internalregistry.AllowKeyDerivation(typeURL); err == nil { t.Error("internalregistry.AllowKeyDerivation() err = nil, want non-nil") } if internalregistry.CanDeriveKeys(typeURL) { t.Errorf("internalregistry.CanDeriveKeys() = true, want false") } }) } } func TestDeriveKey(t *testing.T) { for _, test := range []struct { name string keyTemplate *tinkpb.KeyTemplate keySize uint32 keyMaterialType tinkpb.KeyData_KeyMaterialType }{ { name: "AES-128-GCM", keyTemplate: aead.AES128GCMKeyTemplate(), keySize: 16, keyMaterialType: tinkpb.KeyData_SYMMETRIC, }, { name: "AES-256-GCM", keyTemplate: aead.AES256GCMKeyTemplate(), keySize: 32, keyMaterialType: tinkpb.KeyData_SYMMETRIC, }, } { t.Run(test.name, func(t *testing.T) { buf := bytes.NewBuffer(random.GetRandomBytes(test.keySize)) keyData, err := internalregistry.DeriveKey(test.keyTemplate, buf) if err != nil { t.Fatalf("internalregistry.DeriveKey() err = %v, want nil", err) } if got, want := keyData.GetTypeUrl(), test.keyTemplate.GetTypeUrl(); got != want { t.Errorf("TypeUrl = %s, want %s", got, want) } key := &gcmpb.AesGcmKey{} if err := proto.Unmarshal(keyData.GetValue(), key); err != nil { t.Errorf("proto.Unmarshal() err = %v, want nil", err) } if got, want := len(key.GetKeyValue()), int(test.keySize); got != want { t.Errorf("len(KeyValue) = %d, want %d", got, want) } if got, want := keyData.GetKeyMaterialType(), test.keyMaterialType; got != want { t.Errorf("KeyMaterialType = %s, want %s", got, want) } }) } } func TestDeriveKeyFails(t *testing.T) { mustRegisterBadKeyManagers(t) rand := random.GetRandomBytes(32) for _, test := range []struct { name string keyTemplate *tinkpb.KeyTemplate randLen uint32 }{ { name: "not enough randomness", keyTemplate: aead.AES128GCMKeyTemplate(), randLen: 15}, { name: "nil key template", randLen: 32}, { name: "derivation-disallowed but registered key manager", keyTemplate: aead.AES128CTRHMACSHA256KeyTemplate(), randLen: 32, }, { name: "derivation-allowed but unregistered key manager", keyTemplate: &tinkpb.KeyTemplate{ TypeUrl: unregisteredKMTypeURL, Value: rand, OutputPrefixType: tinkpb.OutputPrefixType_TINK, }, randLen: 32, }, { "does not implement DerivableKeyManager", &tinkpb.KeyTemplate{ TypeUrl: notDerivableKMTypeURL, Value: rand, OutputPrefixType: tinkpb.OutputPrefixType_TINK, }, 32, }, { "key manager with failing DeriveKey()", &tinkpb.KeyTemplate{ TypeUrl: failingKMTypeURL, Value: rand, OutputPrefixType: tinkpb.OutputPrefixType_TINK, }, 32, }, } { t.Run(test.name, func(t *testing.T) { buf := bytes.NewBuffer(random.GetRandomBytes(test.randLen)) if _, err := internalregistry.DeriveKey(test.keyTemplate, buf); err == nil { t.Error("internalregistry.DeriveKey() err = nil, want non-nil") } }) } } ================================================ FILE: go/internal/monitoringutil/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep go_library( name = "monitoringutil", srcs = ["monitoring_util.go"], importpath = "github.com/google/tink/go/internal/monitoringutil", deps = [ "//core/primitiveset", "//monitoring", "//proto/tink_go_proto", ], ) go_test( name = "monitoringutil_test", srcs = ["monitoring_util_test.go"], deps = [ ":monitoringutil", "//core/primitiveset", "//monitoring", "//proto/tink_go_proto", "@com_github_google_go_cmp//cmp", ], ) alias( name = "go_default_library", actual = ":monitoringutil", visibility = ["//:__subpackages__"], ) ================================================ FILE: go/internal/monitoringutil/monitoring_util.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package monitoringutil implements utility functions for monitoring. package monitoringutil import ( "fmt" "strings" "github.com/google/tink/go/core/primitiveset" "github.com/google/tink/go/monitoring" tpb "github.com/google/tink/go/proto/tink_go_proto" ) const keytypeURLPrefix = "type.googleapis.com/google.crypto." // DoNothingLogger is a Logger that does nothing when invoked. type DoNothingLogger struct{} var _ monitoring.Logger = (*DoNothingLogger)(nil) // Log drops a log call. func (l *DoNothingLogger) Log(uint32, int) {} // LogFailure drops a failure call. func (l *DoNothingLogger) LogFailure() {} func keyStatusFromProto(status tpb.KeyStatusType) (monitoring.KeyStatus, error) { var keyStatus monitoring.KeyStatus = 55 switch status { case tpb.KeyStatusType_ENABLED: keyStatus = monitoring.Enabled case tpb.KeyStatusType_DISABLED: keyStatus = monitoring.Disabled case tpb.KeyStatusType_DESTROYED: keyStatus = monitoring.Destroyed default: return keyStatus, fmt.Errorf("unknown key status: %q", status) } return keyStatus, nil } func parseKeyTypeURL(ktu string) string { return strings.TrimPrefix(ktu, keytypeURLPrefix) } // KeysetInfoFromPrimitiveSet creates a `KeysetInfo` from a `PrimitiveSet`. // This function doesn't guarantee to preserve the ordering of the keys in the keyset. func KeysetInfoFromPrimitiveSet(ps *primitiveset.PrimitiveSet) (*monitoring.KeysetInfo, error) { if ps == nil { return nil, fmt.Errorf("primitive set is nil") } if len(ps.Entries) == 0 { return nil, fmt.Errorf("primitive set is empty") } if ps.Primary == nil { return nil, fmt.Errorf("primary key must not be nil") } entries := []*monitoring.Entry{} for _, pse := range ps.Entries { for _, pe := range pse { keyStatus, err := keyStatusFromProto(pe.Status) if err != nil { return nil, err } e := &monitoring.Entry{ KeyID: pe.KeyID, Status: keyStatus, KeyType: parseKeyTypeURL(pe.TypeURL), KeyPrefix: pe.PrefixType.String(), } entries = append(entries, e) } } return &monitoring.KeysetInfo{ Annotations: ps.Annotations, PrimaryKeyID: ps.Primary.KeyID, Entries: entries, }, nil } ================================================ FILE: go/internal/monitoringutil/monitoring_util_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package monitoringutil_test import ( "testing" "github.com/google/go-cmp/cmp" "github.com/google/tink/go/core/primitiveset" "github.com/google/tink/go/internal/monitoringutil" "github.com/google/tink/go/monitoring" tpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestKeysetInfoFromPrimitiveSetWithNilPrimitiveSetFails(t *testing.T) { if _, err := monitoringutil.KeysetInfoFromPrimitiveSet(nil); err == nil { t.Errorf("KeysetInfoFromPrimitiveSet(nil) err = nil, want error") } } func validPrimitiveSet() *primitiveset.PrimitiveSet { return &primitiveset.PrimitiveSet{ Primary: &primitiveset.Entry{}, Entries: map[string][]*primitiveset.Entry{ "one": []*primitiveset.Entry{ { Status: tpb.KeyStatusType_ENABLED, TypeURL: "type.googleapis.com/google.crypto.tink.AesGcmKey", }, }, }, } } func TestBaselinePrimitiveSet(t *testing.T) { if _, err := monitoringutil.KeysetInfoFromPrimitiveSet(validPrimitiveSet()); err != nil { t.Errorf("KeysetInfoFromPrimitiveSet() err = %v, want nil", err) } } func TestKeysetInfoFromPrimitiveSetWithNoEntryFails(t *testing.T) { ps := validPrimitiveSet() ps.Entries = nil if _, err := monitoringutil.KeysetInfoFromPrimitiveSet(ps); err == nil { t.Errorf("KeysetInfoFromPrimitiveSet() err = nil, want error") } } func TestKeysetInfoFromPrimitiveSetWithNoPrimaryFails(t *testing.T) { ps := validPrimitiveSet() ps.Primary = nil if _, err := monitoringutil.KeysetInfoFromPrimitiveSet(ps); err == nil { t.Errorf("KeysetInfoFromPrimitiveSet() err = nil, want error") } } func TestKeysetInfoFromPrimitiveSetWithInvalidKeyStatusFails(t *testing.T) { ps := validPrimitiveSet() ps.Entries["invalid_key_status"] = []*primitiveset.Entry{ { KeyID: 123, Status: tpb.KeyStatusType_UNKNOWN_STATUS, }, } if _, err := monitoringutil.KeysetInfoFromPrimitiveSet(ps); err == nil { t.Errorf("KeysetInfoFromPrimitiveSet() err = nil, want error") } } func TestKeysetInfoFromPrimitiveSet(t *testing.T) { ps := &primitiveset.PrimitiveSet{ Primary: &primitiveset.Entry{ KeyID: 1, }, Annotations: map[string]string{ "foo": "bar", "zoo": "far", }, Entries: map[string][]*primitiveset.Entry{ // Adding all entries under the same prefix to get deterministic output. "one": []*primitiveset.Entry{ &primitiveset.Entry{ KeyID: 1, Status: tpb.KeyStatusType_ENABLED, TypeURL: "type.googleapis.com/google.crypto.tink.AesSivKey", PrefixType: tpb.OutputPrefixType_TINK, }, &primitiveset.Entry{ KeyID: 2, Status: tpb.KeyStatusType_DISABLED, TypeURL: "type.googleapis.com/google.crypto.tink.AesGcmKey", PrefixType: tpb.OutputPrefixType_TINK, }, &primitiveset.Entry{ KeyID: 3, Status: tpb.KeyStatusType_DESTROYED, TypeURL: "type.googleapis.com/google.crypto.tink.AesCtrHmacKey", PrefixType: tpb.OutputPrefixType_TINK, }, }, }, } want := &monitoring.KeysetInfo{ PrimaryKeyID: 1, Annotations: map[string]string{ "foo": "bar", "zoo": "far", }, Entries: []*monitoring.Entry{ { KeyID: 1, Status: monitoring.Enabled, KeyType: "tink.AesSivKey", KeyPrefix: "TINK", }, { KeyID: 2, Status: monitoring.Disabled, KeyType: "tink.AesGcmKey", KeyPrefix: "TINK", }, { KeyID: 3, Status: monitoring.Destroyed, KeyType: "tink.AesCtrHmacKey", KeyPrefix: "TINK", }, }, } got, err := monitoringutil.KeysetInfoFromPrimitiveSet(ps) if err != nil { t.Fatalf("KeysetInfoFromPrimitiveSet() err = %v, want nil", err) } if !cmp.Equal(got, want) { t.Errorf("got = %v, want = %v, with diff: %v", got, want, cmp.Diff(got, want)) } } ================================================ FILE: go/internal/registryconfig/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "registryconfig", srcs = ["registry_config.go"], importpath = "github.com/google/tink/go/internal/registryconfig", visibility = ["//keyset:__subpackages__"], deps = [ "//core/registry", "//internal/internalapi", "//proto/tink_go_proto", ], ) alias( name = "go_default_library", actual = ":registryconfig", visibility = ["//keyset:__subpackages__"], ) go_test( name = "registryconfig_test", srcs = ["registry_config_test.go"], deps = [ ":registryconfig", "//core/registry", "//internal/internalapi", "//mac/subtle", "//proto/common_go_proto", "//proto/tink_go_proto", "//testutil", "@org_golang_google_protobuf//proto", ], ) ================================================ FILE: go/internal/registryconfig/registry_config.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package registryconfig is a transitioning stepping stone used by the // keyset handle in cases where a configuration is not provided by the user, // so it needs to resort to using the old global registry methods. package registryconfig import ( "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/internalapi" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // RegistryConfig is an internal way for the keyset handle to access the // old global Regsitry through the new Configuration interface. type RegistryConfig struct{} // PrimitiveFromKeyData creates a primitive from KeyData by forwarding the // KeyData straight to the Registry. func (c *RegistryConfig) PrimitiveFromKeyData(keyData *tinkpb.KeyData, _ internalapi.Token) (any, error) { return registry.PrimitiveFromKeyData(keyData) } // RegisterKeyManager registers a provided KeyManager by forwarding it directly // to the Registry. func (c *RegistryConfig) RegisterKeyManager(km registry.KeyManager, _ internalapi.Token) error { return registry.RegisterKeyManager(km) } ================================================ FILE: go/internal/registryconfig/registry_config_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package registryconfig_test import ( "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/internalapi" "github.com/google/tink/go/internal/registryconfig" "github.com/google/tink/go/mac/subtle" "github.com/google/tink/go/testutil" commonpb "github.com/google/tink/go/proto/common_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestPrimitiveFromKeyData(t *testing.T) { keyData := testutil.NewHMACKeyData(commonpb.HashType_SHA256, 16) registryConfig := &registryconfig.RegistryConfig{} p, err := registryConfig.PrimitiveFromKeyData(keyData, internalapi.Token{}) if err != nil { t.Errorf("registryConfig.PrimitiveFromKeyData() err = %v, want nil", err) } if _, ok := p.(*subtle.HMAC); !ok { t.Error("primitive is not of type *subtle.HMAC") } } func TestPrimitiveFromKeyDataErrors(t *testing.T) { registryConfig := &registryconfig.RegistryConfig{} testCases := []struct { name string keyData *tinkpb.KeyData }{ { name: "unregistered url", keyData: func() *tinkpb.KeyData { kd := testutil.NewHMACKeyData(commonpb.HashType_SHA256, 16) kd.TypeUrl = "some url" return kd }(), }, { name: "mismatching url", keyData: func() *tinkpb.KeyData { kd := testutil.NewHMACKeyData(commonpb.HashType_SHA256, 16) kd.TypeUrl = testutil.AESGCMTypeURL return kd }(), }, { name: "nil KeyData", keyData: nil, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { if _, err := registryConfig.PrimitiveFromKeyData(tc.keyData, internalapi.Token{}); err == nil { t.Errorf("registryConfig.Primitive() err = nil, want not-nil") } }) } } type testPrimitive struct{} type testKeyManager struct{} func (km *testKeyManager) Primitive(_ []byte) (any, error) { return &testPrimitive{}, nil } func (km *testKeyManager) NewKey(_ []byte) (proto.Message, error) { return nil, nil } func (km *testKeyManager) DoesSupport(typeURL string) bool { return typeURL == "testKeyManager" } func (km *testKeyManager) TypeURL() string { return "testKeyManager" } func (km *testKeyManager) NewKeyData(_ []byte) (*tinkpb.KeyData, error) { return nil, nil } func TestRegisterKeyManager(t *testing.T) { registryConfig := &registryconfig.RegistryConfig{} if err := registryConfig.RegisterKeyManager(new(testKeyManager), internalapi.Token{}); err != nil { t.Fatalf("registryConfig.RegisterKeyManager() err = %v, want nil", err) } if _, err := registry.GetKeyManager("testKeyManager"); err != nil { t.Fatalf("registry.GetKeyManager(\"testKeyManager\") err = %v, want nil", err) } primitive, err := registry.Primitive(new(testKeyManager).TypeURL(), []byte{0, 1, 2, 3}) if err != nil { t.Fatalf("registry.Primitive() err = %v, want nil", err) } if _, ok := primitive.(*testPrimitive); !ok { t.Error("primitive is not of type *testPrimitive") } } ================================================ FILE: go/internal/signature/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "signature", srcs = [ "rsa.go", "rsassapkcs1_signer.go", "rsassapkcs1_verifier.go", "rsassapss_signer.go", "rsassapss_verifier.go", "signature.go", ], importpath = "github.com/google/tink/go/internal/signature", visibility = ["//:__subpackages__"], deps = [ "//subtle", "//tink", ], ) go_test( name = "signature_test", srcs = [ "rsa_test.go", "rsassapkcs1_signer_verifier_test.go", "rsassapss_signer_verifier_test.go", ], data = [ "//testdata/testvectors:rsa_pss", "//testdata/testvectors:rsa_signature", ], deps = [ ":signature", "//subtle", "//subtle/random", "//testutil", ], ) alias( name = "go_default_library", actual = ":signature", visibility = ["//:__subpackages__"], ) ================================================ FILE: go/internal/signature/rsa.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature import ( "crypto" "crypto/rsa" "fmt" "hash" "github.com/google/tink/go/subtle" "github.com/google/tink/go/tink" ) const ( rsaMinModulusSizeInBits = 2048 rsaDefaultPublicExponent = 65537 ) // RSAValidModulusSizeInBits the size in bits for an RSA key. func RSAValidModulusSizeInBits(m int) error { if m < rsaMinModulusSizeInBits { return fmt.Errorf("modulus size too small, must be >= %d", rsaMinModulusSizeInBits) } return nil } // RSAValidPublicExponent validates a public RSA exponent. func RSAValidPublicExponent(e int) error { // crypto/rsa uses the following hardcoded public exponent value. if e != rsaDefaultPublicExponent { return fmt.Errorf("invalid public exponent") } return nil } // HashSafeForSignature checks whether a hash function is safe to use with digital signatures // that require collision resistance. func HashSafeForSignature(hashAlg string) error { switch hashAlg { case "SHA256", "SHA384", "SHA512": return nil default: return fmt.Errorf("hash function not safe for digital signatures: %q", hashAlg) } } const ( testMsg = "Tink and Wycheproof." signVerifyErrMsg = "signing with private key followed by verifying with public key failed, the key may be corrupted" ) // Validate_RSA_SSA_PKCS1 validates that the corresponding private key is valid by signing and verifying a message. func Validate_RSA_SSA_PKCS1(hashAlg string, privKey *rsa.PrivateKey) error { signer, err := New_RSA_SSA_PKCS1_Signer(hashAlg, privKey) if err != nil { return err } verifier, err := New_RSA_SSA_PKCS1_Verifier(hashAlg, &privKey.PublicKey) if err != nil { return err } if err := validateSignerVerifier(signer, verifier); err != nil { return fmt.Errorf("RSA-SSA-PKCS1: %q", signVerifyErrMsg) } return nil } // Validate_RSA_SSA_PSS validates that the corresponding private key is valid by signing and verifying a message. func Validate_RSA_SSA_PSS(hashAlg string, saltLen int, privKey *rsa.PrivateKey) error { signer, err := New_RSA_SSA_PSS_Signer(hashAlg, saltLen, privKey) if err != nil { return err } verifier, err := New_RSA_SSA_PSS_Verifier(hashAlg, saltLen, &privKey.PublicKey) if err != nil { return err } if err := validateSignerVerifier(signer, verifier); err != nil { return fmt.Errorf("RSA-SSA-PSS: %q", signVerifyErrMsg) } return nil } func validateSignerVerifier(signer tink.Signer, verifier tink.Verifier) error { signature, err := signer.Sign([]byte(testMsg)) if err != nil { return err } if err := verifier.Verify([]byte(signature), []byte(testMsg)); err != nil { return err } return nil } func validRSAPublicKey(publicKey *rsa.PublicKey) error { if err := RSAValidModulusSizeInBits(publicKey.N.BitLen()); err != nil { return err } return RSAValidPublicExponent(publicKey.E) } func hashID(hashAlg string) (crypto.Hash, error) { switch hashAlg { case "SHA256": return crypto.SHA256, nil case "SHA384": return crypto.SHA384, nil case "SHA512": return crypto.SHA512, nil default: return 0, fmt.Errorf("invalid hash function: %q", hashAlg) } } func rsaHashFunc(hashAlg string) (func() hash.Hash, crypto.Hash, error) { if err := HashSafeForSignature(hashAlg); err != nil { return nil, 0, err } hashFunc := subtle.GetHashFunc(hashAlg) if hashFunc == nil { return nil, 0, fmt.Errorf("invalid hash function: %q", hashAlg) } hashID, err := hashID(hashAlg) if err != nil { return nil, 0, err } return hashFunc, hashID, nil } ================================================ FILE: go/internal/signature/rsa_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature_test import ( "crypto/rand" "crypto/rsa" "math/big" "testing" internal "github.com/google/tink/go/internal/signature" ) func TestValidatePublicExponent(t *testing.T) { if err := internal.RSAValidPublicExponent(65537); err != nil { t.Errorf("ValidPublicExponent(65537) err = %v, want nil", err) } } func TestValidateInvalidPublicExponentFails(t *testing.T) { if err := internal.RSAValidPublicExponent(3); err == nil { t.Errorf("ValidPublicExponent(3) err = nil, want error") } } func TestValidateModulusSizeInBits(t *testing.T) { if err := internal.RSAValidModulusSizeInBits(2048); err != nil { t.Errorf("ValidModulusSizeInBits(2048) err = %v, want nil", err) } } func TestValidateInvalidModulusSizeInBitsFails(t *testing.T) { if err := internal.RSAValidModulusSizeInBits(1024); err == nil { t.Errorf("ValidModulusSizeInBits(1024) err = nil, want error") } } func TestHashSafeForSignature(t *testing.T) { for _, h := range []string{ "SHA256", "SHA384", "SHA512", } { t.Run(h, func(t *testing.T) { if err := internal.HashSafeForSignature(h); err != nil { t.Errorf("HashSafeForSignature(%q) err = %v, want nil", h, err) } }) } } func TestHashNotSafeForSignatureFails(t *testing.T) { for _, h := range []string{ "SHA1", "SHA224", "MD5", } { t.Run(h, func(t *testing.T) { if err := internal.HashSafeForSignature(h); err == nil { t.Errorf("HashSafeForSignature(%q) err = nil, want error", h) } }) } } func TestRSAKeySelfTestWithCorruptedKeysFails(t *testing.T) { validPrivKey, err := rsa.GenerateKey(rand.Reader, 3072) if err != nil { t.Fatalf("rsa.GenerateKey(rand.Reader, 3072) err = %v, want nil", err) } if err := internal.Validate_RSA_SSA_PKCS1("SHA256", validPrivKey); err != nil { t.Errorf("internal.Validate_RSA_SSA_PKCS1('SHA256', validPrivKey) err = %v, want nil", err) } saltLen := 0 if err := internal.Validate_RSA_SSA_PSS("SHA256", saltLen, validPrivKey); err != nil { t.Errorf("internal.Validate_RSA_SSA_PSS('SHA256', saltLen, validPrivKey) err = %v, want nil", err) } type testCase struct { tag string key *rsa.PrivateKey hash string } for _, tc := range []testCase{ { tag: "modify public modulus", key: &rsa.PrivateKey{ D: validPrivKey.D, Primes: validPrivKey.Primes, Precomputed: validPrivKey.Precomputed, PublicKey: rsa.PublicKey{ N: validPrivKey.N.Add(validPrivKey.N, big.NewInt(500)), E: validPrivKey.E, }, }, }, { tag: "modify public exponent", key: &rsa.PrivateKey{ D: validPrivKey.D, Primes: validPrivKey.Primes, Precomputed: validPrivKey.Precomputed, PublicKey: rsa.PublicKey{ N: validPrivKey.N, E: validPrivKey.E + 5, }, }, }, { tag: "one byte shift in Q", key: &rsa.PrivateKey{ PublicKey: validPrivKey.PublicKey, D: validPrivKey.D, Precomputed: validPrivKey.Precomputed, Primes: []*big.Int{ func() *big.Int { p := validPrivKey.Primes[0].Bytes() p[4] = byte(uint8(p[4] + 1)) return new(big.Int).SetBytes(p) }(), validPrivKey.Primes[1], }, }, hash: "SHA256", }, { tag: "removing one byte from P", key: &rsa.PrivateKey{ PublicKey: validPrivKey.PublicKey, D: validPrivKey.D, Precomputed: validPrivKey.Precomputed, Primes: []*big.Int{ validPrivKey.Primes[0], func() *big.Int { p := validPrivKey.Primes[1].Bytes() return new(big.Int).SetBytes(p[:len(p)-2]) }(), }, }, hash: "SHA256", }, } { t.Run(tc.tag, func(t *testing.T) { if err := internal.Validate_RSA_SSA_PKCS1(tc.hash, tc.key); err == nil { t.Errorf("internal.Validate_RSA_SSA_PKCS1(hash = %q, key) err = nil, want error", tc.hash) } if err := internal.Validate_RSA_SSA_PSS(tc.hash, saltLen, tc.key); err == nil { t.Errorf("internal.Validate_RSA_SSA_PSS(hash = %d saltLen = %q, key) err = nil, want error", saltLen, tc.hash) } }) } } ================================================ FILE: go/internal/signature/rsassapkcs1_signer.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature import ( "crypto" "crypto/rand" "crypto/rsa" "hash" "github.com/google/tink/go/subtle" "github.com/google/tink/go/tink" ) // RSA_SSA_PKCS1_Signer is an implementation of Signer for RSA-SSA-PKCS1. type RSA_SSA_PKCS1_Signer struct { privateKey *rsa.PrivateKey hashFunc func() hash.Hash hashID crypto.Hash } var _ (tink.Signer) = (*RSA_SSA_PKCS1_Signer)(nil) // New_RSA_SSA_PKCS1_Signer creates a new intance of RSA_SSA_PKCS1_Signer. func New_RSA_SSA_PKCS1_Signer(hashAlg string, privKey *rsa.PrivateKey) (*RSA_SSA_PKCS1_Signer, error) { if err := validRSAPublicKey(privKey.Public().(*rsa.PublicKey)); err != nil { return nil, err } hashFunc, hashID, err := rsaHashFunc(hashAlg) if err != nil { return nil, err } return &RSA_SSA_PKCS1_Signer{ privateKey: privKey, hashFunc: hashFunc, hashID: hashID, }, nil } // Sign computes a signature for the given data. func (s *RSA_SSA_PKCS1_Signer) Sign(data []byte) ([]byte, error) { digest, err := subtle.ComputeHash(s.hashFunc, data) if err != nil { return nil, err } return rsa.SignPKCS1v15(rand.Reader, s.privateKey, s.hashID, digest) } ================================================ FILE: go/internal/signature/rsassapkcs1_signer_verifier_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature_test import ( "crypto/rand" "crypto/rsa" "fmt" "math/big" "testing" internal "github.com/google/tink/go/internal/signature" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/subtle" "github.com/google/tink/go/testutil" ) func TestRSASSAPKCS1SignVerify(t *testing.T) { data := random.GetRandomBytes(20) hash := "SHA256" privKey, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { t.Fatalf("rsa.GenerateKey(rand.Reader, 2048) err = %v, want nil", err) } signer, err := internal.New_RSA_SSA_PKCS1_Signer(hash, privKey) if err != nil { t.Fatalf("New_RSA_SSA_PKCS1_Signer() err = %v, want nil", err) } verifier, err := internal.New_RSA_SSA_PKCS1_Verifier(hash, &privKey.PublicKey) if err != nil { t.Fatalf("New_RSA_SSA_PKCS1_Verifier() err = %v, want nil", err) } signature, err := signer.Sign(data) if err != nil { t.Fatalf("Sign() err = %v, want nil", err) } if err := verifier.Verify(signature, data); err != nil { t.Fatalf("Verify() err = %v, want nil", err) } } func TestRSASSAPKCS1ModifySignatureFails(t *testing.T) { data := random.GetRandomBytes(20) hash := "SHA256" privKey, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { t.Fatalf("rsa.GenerateKey(rand.Reader, 2048) err = %v, want nil", err) } signer, err := internal.New_RSA_SSA_PKCS1_Signer(hash, privKey) if err != nil { t.Fatalf("New_RSA_SSA_PKCS1_Signer() err = %v, want nil", err) } signature, err := signer.Sign(data) if err != nil { t.Fatalf("Sign() err = %v, want nil", err) } verifier, err := internal.New_RSA_SSA_PKCS1_Verifier(hash, &privKey.PublicKey) if err != nil { t.Fatalf("New_RSA_SSA_PKCS1_Verifier() err = %v, want nil", err) } appendSig := append(signature, 0x01) if err := verifier.Verify(appendSig, data); err == nil { t.Fatalf("Verify() err = nil, want error") } truncSig := signature[:len(signature)-2] if err := verifier.Verify(truncSig, data); err == nil { t.Fatalf("Verify() err = nil, want error") } signature[0] = byte(uint8(signature[0] + 1)) if err := verifier.Verify(truncSig, data); err == nil { t.Fatalf("Verify() err = nil, want error") } } func TestNewRSASSAPKCS1SignerVerifierInvalidInput(t *testing.T) { validPrivKey, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { t.Fatalf("rsa.GenerateKey(rand.Reader, 2048) err = %v, want nil", err) } rsaShortModulusKey, err := rsa.GenerateKey(rand.Reader, 1024) if err != nil { t.Fatalf("decoding rsa short modulus: %v", err) } testCases := []struct { name string hash string privKey *rsa.PrivateKey }{ { name: "weak signature hash algorithm", hash: "SHA1", privKey: validPrivKey, }, { name: "invalid public key exponent", hash: "SHA256", privKey: &rsa.PrivateKey{ D: validPrivKey.D, Primes: validPrivKey.Primes, Precomputed: validPrivKey.Precomputed, PublicKey: rsa.PublicKey{ N: validPrivKey.PublicKey.N, E: 3, }, }, }, { name: "small modulus size", hash: "SHA256", privKey: rsaShortModulusKey, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { if _, err := internal.New_RSA_SSA_PKCS1_Signer(tc.hash, tc.privKey); err == nil { t.Errorf("New_RSA_SSA_PKCS1_Signer() err = nil, want error") } if _, err := internal.New_RSA_SSA_PKCS1_Verifier(tc.hash, &tc.privKey.PublicKey); err == nil { t.Errorf("New_RSA_SSA_PKCS1_Verifier() err = nil, want error") } }) } } type rsaSSAPKCS1Suite struct { testutil.WycheproofSuite TestGroups []*rsaSSAPKCS1Group `json:"testGroups"` } type rsaSSAPKCS1Group struct { testutil.WycheproofGroup SHA string `json:"sha"` E testutil.HexBytes `json:"e"` N testutil.HexBytes `json:"n"` Type string `json:"type"` Tests []*rsaSSAPKCS1Case `json:"tests"` } type rsaSSAPKCS1Case struct { testutil.WycheproofCase Message testutil.HexBytes `json:"msg"` Signature testutil.HexBytes `json:"sig"` } func TestRSASSAPKCS1WycheproofCases(t *testing.T) { testutil.SkipTestIfTestSrcDirIsNotSet(t) testsRan := 0 for _, v := range []string{ "rsa_signature_2048_sha256_test.json", "rsa_signature_3072_sha512_test.json", "rsa_signature_4096_sha512_test.json", } { suite := &rsaSSAPKCS1Suite{} if err := testutil.PopulateSuite(suite, v); err != nil { t.Fatalf("testutil.PopulateSuite() err = %v, want nil", err) } for _, group := range suite.TestGroups { hash := subtle.ConvertHashName(group.SHA) if hash == "" { t.Fatalf("invalid hash name") } publicKey := &rsa.PublicKey{ E: int(new(big.Int).SetBytes(group.E).Uint64()), N: new(big.Int).SetBytes(group.N), } if publicKey.E != 65537 { // golang "crypto/rsa" only supports 65537 as an exponent. if _, err := internal.New_RSA_SSA_PKCS1_Verifier(hash, publicKey); err == nil { t.Errorf("NewRSASSAPKCS1Verifier() err = nil, want error") } continue } verifier, err := internal.New_RSA_SSA_PKCS1_Verifier(hash, publicKey) if err != nil { t.Fatalf("NewRSASSAPKCS1Verifier() err = %v, want nil", err) } for _, test := range group.Tests { caseName := fmt.Sprintf("%s: %s-%s:Case-%d", v, group.Type, group.SHA, test.CaseID) t.Run(caseName, func(t *testing.T) { testsRan++ err := verifier.Verify(test.Signature, test.Message) switch test.Result { case "valid": if err != nil { t.Errorf("Verify() err = %v, want nil", err) } case "invalid": if err == nil { t.Errorf("Verify() err = nil, want error") } case "acceptable": // TODO(b/230489047): Inspect flags to appropriately handle acceptable test cases. default: t.Errorf("unsupported test result: %q", test.Result) } }) } } } if testsRan != 716 { t.Errorf("testsRan = %d, want = %d", testsRan, 716) } } ================================================ FILE: go/internal/signature/rsassapkcs1_verifier.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature import ( "crypto" "crypto/rsa" "hash" "github.com/google/tink/go/subtle" "github.com/google/tink/go/tink" ) // RSA_SSA_PKCS1_Verifier is an implementation of Verifier for RSA-SSA-PKCS1. type RSA_SSA_PKCS1_Verifier struct { publicKey *rsa.PublicKey hashFunc func() hash.Hash hashID crypto.Hash } var _ tink.Verifier = (*RSA_SSA_PKCS1_Verifier)(nil) // New_RSA_SSA_PKCS1_Verifier creates a new intance of RSASSAPKCS1Verifier. func New_RSA_SSA_PKCS1_Verifier(hashAlg string, pubKey *rsa.PublicKey) (*RSA_SSA_PKCS1_Verifier, error) { if err := validRSAPublicKey(pubKey); err != nil { return nil, err } hashFunc, hashID, err := rsaHashFunc(hashAlg) if err != nil { return nil, err } return &RSA_SSA_PKCS1_Verifier{ publicKey: pubKey, hashFunc: hashFunc, hashID: hashID, }, nil } // Verify verifies whether the given signaure is valid for the given data. // It returns an error if the signature is not valid; nil otherwise. func (v *RSA_SSA_PKCS1_Verifier) Verify(signature, data []byte) error { hashed, err := subtle.ComputeHash(v.hashFunc, data) if err != nil { return err } return rsa.VerifyPKCS1v15(v.publicKey, v.hashID, hashed, signature) } ================================================ FILE: go/internal/signature/rsassapss_signer.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature import ( "crypto" "crypto/rand" "crypto/rsa" "fmt" "hash" "github.com/google/tink/go/subtle" "github.com/google/tink/go/tink" ) // RSA_SSA_PSS_Signer is an implementation of Signer for RSA-SSA-PSS. type RSA_SSA_PSS_Signer struct { privateKey *rsa.PrivateKey hashFunc func() hash.Hash hashID crypto.Hash saltLength int } var _ tink.Signer = (*RSA_SSA_PSS_Signer)(nil) // New_RSA_SSA_PSS_Signer creates a new instance of RSA_SSA_PSS_Signer. func New_RSA_SSA_PSS_Signer(hashAlg string, saltLength int, privKey *rsa.PrivateKey) (*RSA_SSA_PSS_Signer, error) { if err := validRSAPublicKey(&privKey.PublicKey); err != nil { return nil, err } hashFunc, hashID, err := rsaHashFunc(hashAlg) if err != nil { return nil, err } if saltLength < 0 { return nil, fmt.Errorf("invalid salt length") } return &RSA_SSA_PSS_Signer{ privateKey: privKey, hashFunc: hashFunc, hashID: hashID, saltLength: saltLength, }, nil } // Sign computes a signature for the given data. func (s *RSA_SSA_PSS_Signer) Sign(data []byte) ([]byte, error) { digest, err := subtle.ComputeHash(s.hashFunc, data) if err != nil { return nil, err } return rsa.SignPSS(rand.Reader, s.privateKey, s.hashID, digest, &rsa.PSSOptions{SaltLength: s.saltLength}) } ================================================ FILE: go/internal/signature/rsassapss_signer_verifier_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature_test import ( "crypto/rand" "crypto/rsa" "fmt" "math/big" "testing" "github.com/google/tink/go/internal/signature" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/subtle" "github.com/google/tink/go/testutil" ) func TestRSASSAPSSSignVerify(t *testing.T) { data := random.GetRandomBytes(20) sigHash := "SHA256" saltLength := 10 privKey, err := rsa.GenerateKey(rand.Reader, 3072) if err != nil { t.Fatalf("rsa.GenerateKey(rand.Reader, 3072) err = %v, want nil", err) } signer, err := signature.New_RSA_SSA_PSS_Signer(sigHash, saltLength, privKey) if err != nil { t.Fatalf("New_RSA_SSA_PSS_Signer() error = %v, want nil", err) } verifier, err := signature.New_RSA_SSA_PSS_Verifier(sigHash, saltLength, &privKey.PublicKey) if err != nil { t.Fatalf("New_RSA_SSA_PSS_Verifier() error = %v, want nil", err) } s, err := signer.Sign(data) if err != nil { t.Fatalf("Sign() err = %v, want nil", err) } if err = verifier.Verify(s, data); err != nil { t.Fatalf("Verify() err = %v, want nil", err) } } func TestRSASSAPSSSignVerifyInvalidFails(t *testing.T) { data := random.GetRandomBytes(20) sigHash := "SHA256" saltLength := 10 privKey, err := rsa.GenerateKey(rand.Reader, 3072) if err != nil { t.Fatalf("rsa.GenerateKey(rand.Reader, 3072) err = %v, want nil", err) } signer, err := signature.New_RSA_SSA_PSS_Signer(sigHash, saltLength, privKey) if err != nil { t.Fatalf("New_RSA_SSA_PSS_Signer() error = %v, want nil", err) } verifier, err := signature.New_RSA_SSA_PSS_Verifier(sigHash, saltLength, &privKey.PublicKey) if err != nil { t.Fatalf("New_RSA_SSA_PSS_Verifier() error = %v, want nil", err) } s, err := signer.Sign(data) if err != nil { t.Fatalf("Sign() err = %v, want nil", err) } if err = verifier.Verify(s, data); err != nil { t.Fatalf("Verify() err = %v, want nil", err) } modifiedSig := s[:] // modify first byte in signature modifiedSig[0] = byte(uint8(modifiedSig[0]) + 1) if err := verifier.Verify(modifiedSig, data); err == nil { t.Errorf("Verify(modifiedSig, data) err = nil, want error") } if err := verifier.Verify(s, []byte("invalid_data")); err == nil { t.Errorf("Verify(s, invalid_data) err = nil, want error") } if err := verifier.Verify([]byte("invalid_signature"), data); err == nil { t.Errorf("Verify(invalid_signature, data) err = nil, want error") } diffPrivKey, err := rsa.GenerateKey(rand.Reader, 3072) if err != nil { t.Fatalf("rsa.GenerateKey(rand.Reader, 3072) err = %v, want nil", err) } diffVerifier, err := signature.New_RSA_SSA_PSS_Verifier(sigHash, saltLength, &diffPrivKey.PublicKey) if err != nil { t.Fatalf("New_RSA_SSA_PSS_Verifier() error = %v, want nil", err) } if err := diffVerifier.Verify(s, data); err == nil { t.Errorf("Verify() err = nil, want error") } } func TestNewRSASSAPSSSignerVerifierFailWithInvalidInputs(t *testing.T) { type testCase struct { name string hash string salt int privKey *rsa.PrivateKey } validPrivKey, err := rsa.GenerateKey(rand.Reader, 3072) if err != nil { t.Fatalf("rsa.GenerateKey(rand.Reader, 3072) err = %v, want nil", err) } for _, tc := range []testCase{ { name: "invalid hash function", hash: "SHA1", privKey: validPrivKey, salt: 0, }, { name: "invalid exponent", hash: "SHA256", salt: 0, privKey: &rsa.PrivateKey{ D: validPrivKey.D, PublicKey: rsa.PublicKey{ N: validPrivKey.N, E: 8, }, Primes: validPrivKey.Primes, Precomputed: validPrivKey.Precomputed, }, }, { name: "invalid modulus", hash: "SHA256", salt: 0, privKey: &rsa.PrivateKey{ D: validPrivKey.D, PublicKey: rsa.PublicKey{ N: big.NewInt(5), E: validPrivKey.E, }, Primes: validPrivKey.Primes, Precomputed: validPrivKey.Precomputed, }, }, { name: "invalid salt", hash: "SHA256", salt: -1, privKey: validPrivKey, }, } { t.Run(tc.name, func(t *testing.T) { if _, err := signature.New_RSA_SSA_PSS_Signer(tc.hash, tc.salt, tc.privKey); err == nil { t.Errorf("New_RSA_SSA_PSS_Signer() err = nil, want error") } if _, err := signature.New_RSA_SSA_PSS_Verifier(tc.hash, tc.salt, &tc.privKey.PublicKey); err == nil { t.Errorf("New_RSA_SSA_PSS_Verifier() err = nil, want error") } }) } } type rsaSSAPSSSuite struct { testutil.WycheproofSuite TestGroups []*rsaSSAPSSGroup `json:"testGroups"` } type rsaSSAPSSGroup struct { testutil.WycheproofGroup SHA string `json:"sha"` MGFSHA string `json:"mgfSha"` SaltLength int `json:"sLen"` E testutil.HexBytes `json:"e"` N testutil.HexBytes `json:"N"` Tests []*rsaSSAPSSCase `json:"tests"` } type rsaSSAPSSCase struct { testutil.WycheproofCase Message testutil.HexBytes `json:"msg"` Signature testutil.HexBytes `json:"sig"` } func TestRSASSAPSSWycheproofCases(t *testing.T) { testutil.SkipTestIfTestSrcDirIsNotSet(t) ranTestCount := 0 vectorsFiles := []string{ "rsa_pss_2048_sha512_256_mgf1_28_test.json", "rsa_pss_2048_sha512_256_mgf1_32_test.json", "rsa_pss_2048_sha256_mgf1_0_test.json", "rsa_pss_2048_sha256_mgf1_32_test.json", "rsa_pss_3072_sha256_mgf1_32_test.json", "rsa_pss_4096_sha256_mgf1_32_test.json", "rsa_pss_4096_sha512_mgf1_32_test.json", } for _, v := range vectorsFiles { suite := &rsaSSAPSSSuite{} if err := testutil.PopulateSuite(suite, v); err != nil { t.Fatalf("failed populating suite: %s", err) } for _, group := range suite.TestGroups { sigHash := subtle.ConvertHashName(group.SHA) if sigHash == "" { continue } pubKey := &rsa.PublicKey{ E: int(new(big.Int).SetBytes(group.E).Uint64()), N: new(big.Int).SetBytes(group.N), } verifier, err := signature.New_RSA_SSA_PSS_Verifier(sigHash, group.SaltLength, pubKey) if err != nil { t.Fatalf("New_RSA_SSA_PSS_Verifier() err = %v, want nil", err) } for _, test := range group.Tests { if (test.CaseID == 67 || test.CaseID == 68) && v == "rsa_pss_2048_sha256_mgf1_0_test.json" { // crypto/rsa will interpret zero length salt and parse the salt length from signature. // Since this test cases use a zero salt length as a parameter, even if a different parameter // is provided, Golang will interpret it and parse the salt directly from the signature. continue } ranTestCount++ caseName := fmt.Sprintf("%s: %s-%s-%s-%d:Case-%d", v, group.Type, group.SHA, group.MGFSHA, group.SaltLength, test.CaseID) t.Run(caseName, func(t *testing.T) { err := verifier.Verify(test.Signature, test.Message) switch test.Result { case "valid": if err != nil { t.Errorf("Verify() err = %, want nil", err) } case "invalid": if err == nil { t.Errorf("Verify() err = nil, want error") } case "acceptable": // TODO(b/230489047): Inspect flags to appropriately handle acceptable test cases. default: t.Errorf("unsupported test result: %q", test.Result) } }) } } } if ranTestCount < 578 { t.Errorf("ranTestCount > %d, want > %d", ranTestCount, 578) } } ================================================ FILE: go/internal/signature/rsassapss_verifier.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature import ( "crypto" "crypto/rsa" "fmt" "hash" "github.com/google/tink/go/subtle" "github.com/google/tink/go/tink" ) // RSA_SSA_PSS_Verifier is an implementation of Verifier for RSA-SSA-PSS. type RSA_SSA_PSS_Verifier struct { publicKey *rsa.PublicKey hashFunc func() hash.Hash hashID crypto.Hash saltLength int } var _ tink.Verifier = (*RSA_SSA_PSS_Verifier)(nil) // New_RSA_SSA_PSS_Verifier creates a new instance of RSA_SSA_PSS_Verifier. func New_RSA_SSA_PSS_Verifier(hashAlg string, saltLength int, pubKey *rsa.PublicKey) (*RSA_SSA_PSS_Verifier, error) { if err := validRSAPublicKey(pubKey); err != nil { return nil, err } hashFunc, hashID, err := rsaHashFunc(hashAlg) if err != nil { return nil, err } if saltLength < 0 { return nil, fmt.Errorf("invalid salt length") } return &RSA_SSA_PSS_Verifier{ publicKey: pubKey, hashFunc: hashFunc, hashID: hashID, saltLength: saltLength, }, nil } // Verify verifies whether the given signature is valid for the given data. // It returns an error if the signature is not valid; nil otherwise. func (v *RSA_SSA_PSS_Verifier) Verify(signature, data []byte) error { digest, err := subtle.ComputeHash(v.hashFunc, data) if err != nil { return err } return rsa.VerifyPSS(v.publicKey, v.hashID, digest, signature, &rsa.PSSOptions{SaltLength: v.saltLength}) } ================================================ FILE: go/internal/signature/signature.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package signature provides internal implementations of the Signer and Verifier primitives. package signature ================================================ FILE: go/internal/testing/stubkeymanager/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "stubkeymanager", testonly = 1, srcs = ["stubkeymanager.go"], importpath = "github.com/google/tink/go/internal/testing/stubkeymanager", visibility = ["//:__subpackages__"], deps = [ "//core/registry", "//internal/internalregistry", "//proto/tink_go_proto", "@org_golang_google_protobuf//proto", ], ) go_test( name = "stubkeymanager_test", srcs = ["stubkeymanager_test.go"], deps = [ ":stubkeymanager", "//proto/aes_gcm_go_proto", "//proto/tink_go_proto", "@com_github_google_go_cmp//cmp", "@org_golang_google_protobuf//testing/protocmp", ], ) alias( name = "go_default_library", actual = ":stubkeymanager", visibility = ["//:__subpackages__"], ) ================================================ FILE: go/internal/testing/stubkeymanager/stubkeymanager.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package stubkeymanager defines key managers for testing primitives. package stubkeymanager import ( "io" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/internalregistry" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // StubKeyManager is a key manager for testing. type StubKeyManager struct { URL string Prim any Key proto.Message KeyData *tinkpb.KeyData } var _ (registry.KeyManager) = (*StubKeyManager)(nil) // Primitive returns the stub primitive. func (km *StubKeyManager) Primitive(serializedKey []byte) (any, error) { return km.Prim, nil } // NewKey returns the stub Key. func (km *StubKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { return km.Key, nil } // NewKeyData returns the stub KeyData. func (km *StubKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { return km.KeyData, nil } // DoesSupport returns true if this KeyManager supports key type identified by typeURL. func (km *StubKeyManager) DoesSupport(typeURL string) bool { return typeURL == km.URL } // TypeURL returns the stub type url. func (km *StubKeyManager) TypeURL() string { return km.URL } // StubPrivateKeyManager is a private key manager for testing. type StubPrivateKeyManager struct { StubKeyManager PubKeyData *tinkpb.KeyData } var _ (registry.PrivateKeyManager) = (*StubPrivateKeyManager)(nil) // PublicKeyData returns the stub public key data. func (skm *StubPrivateKeyManager) PublicKeyData(serializedKey []byte) (*tinkpb.KeyData, error) { return skm.PubKeyData, nil } // StubDerivableKeyManager is a derivable key manager for testing. type StubDerivableKeyManager struct { StubKeyManager KeyMatType tinkpb.KeyData_KeyMaterialType DerKey proto.Message DerErr error } var _ (internalregistry.DerivableKeyManager) = (*StubDerivableKeyManager)(nil) // KeyMaterialType returns the stub key material type. func (dkm *StubDerivableKeyManager) KeyMaterialType() tinkpb.KeyData_KeyMaterialType { return dkm.KeyMatType } // DeriveKey returns the stub derived key and error. func (dkm *StubDerivableKeyManager) DeriveKey(serializedKeyFormat []byte, pseudorandomness io.Reader) (proto.Message, error) { return dkm.DerKey, dkm.DerErr } ================================================ FILE: go/internal/testing/stubkeymanager/stubkeymanager_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package stubkeymanager_test import ( "bytes" "errors" "testing" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/testing/protocmp" "github.com/google/tink/go/internal/testing/stubkeymanager" agpb "github.com/google/tink/go/proto/aes_gcm_go_proto" tpb "github.com/google/tink/go/proto/tink_go_proto" ) type fakePrimitive struct { Name string } func TestStubKeyManager(t *testing.T) { keyType := "some.key.type" km := stubkeymanager.StubKeyManager{ URL: keyType, Key: &agpb.AesGcmKey{Version: 1, KeyValue: []byte("key_value")}, Prim: &fakePrimitive{Name: "fake-primitive-name"}, KeyData: &tpb.KeyData{ TypeUrl: keyType, Value: []byte("key_value"), KeyMaterialType: tpb.KeyData_SYMMETRIC, }, } if !km.DoesSupport(keyType) { t.Errorf("DoesSupport(%q) = false , want true", keyType) } if km.DoesSupport("some.other.key.type") { t.Errorf("DoesSupport(%q) = true , want false", keyType) } if km.TypeURL() != km.URL { t.Errorf("TypeURL() = %q, want %q", km.TypeURL(), keyType) } key, err := km.NewKey(nil) if err != nil { t.Errorf("NewKey() err = %v, want nil", err) } if !cmp.Equal(key, km.Key, protocmp.Transform()) { t.Errorf("NewKey() = %v, want %v", key, km.Key) } keyData, err := km.NewKeyData(nil) if err != nil { t.Errorf("NewKeyData() err = %v, want nil", err) } if !cmp.Equal(keyData, km.KeyData, protocmp.Transform()) { t.Errorf("NewKeyData() = %v, want %v", keyData, km.KeyData) } p, err := km.Primitive(nil) if err != nil { t.Errorf("Primitive() err = %v, want nil", err) } if !cmp.Equal(p, km.Prim) { t.Errorf("Primitive() = %v, want %v", p, km.Prim) } } func TestStubPrivateKeyManager(t *testing.T) { km := stubkeymanager.StubPrivateKeyManager{ PubKeyData: &tpb.KeyData{ TypeUrl: "some.key.type", Value: []byte("key_value"), KeyMaterialType: tpb.KeyData_ASYMMETRIC_PUBLIC, }, } pubKeyData, err := km.PublicKeyData(nil) if err != nil { t.Errorf("PublicKeyData() err = %v, want nil", err) } if !cmp.Equal(pubKeyData, km.PubKeyData, protocmp.Transform()) { t.Errorf("PublicKeyData() = %v, want %v", pubKeyData, km.PubKeyData) } } func TestStubDerivableKeyManager(t *testing.T) { km := stubkeymanager.StubDerivableKeyManager{ KeyMatType: tpb.KeyData_SYMMETRIC, DerKey: &agpb.AesGcmKey{Version: 0, KeyValue: []byte("derived_key_value")}, DerErr: errors.New("hiya"), } if km.KeyMaterialType() != km.KeyMatType { t.Errorf("KeyMaterialType() = %d, want %d", km.KeyMaterialType(), tpb.KeyData_SYMMETRIC) } derivedKey, err := km.DeriveKey([]byte{}, &bytes.Buffer{}) if !cmp.Equal(derivedKey, km.DerKey, protocmp.Transform()) { t.Errorf("DeriveKey() = %v, want %v", derivedKey, km.DerKey) } if err != km.DerErr { t.Errorf("DeriveKey() err = %v, want %v", err, km.DerErr) } } ================================================ FILE: go/internal/tinkerror/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) go_library( name = "tinkerror", srcs = [ "doc.go", "tinkerror.go", ], importpath = "github.com/google/tink/go/internal/tinkerror", ) go_test( name = "tinkerror_test", srcs = ["tinkerror_test.go"], deps = [ ":tinkerror", "//internal/tinkerror/tinkerrortest", ], ) alias( name = "go_default_library", actual = ":tinkerror", visibility = ["//:__subpackages__"], ) ================================================ FILE: go/internal/tinkerror/doc.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package tinkerror provides error handling functionality which helps maintain // API backwards compatibility. package tinkerror ================================================ FILE: go/internal/tinkerror/tinkerror.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tinkerror // Fail should be called by functions which do not return an error value but // need to handle an error condition. // // Such functions are strong candidates for replacement by an equivalent // function which returns an explicit error value. Once a replacement has been // introduced, the original should be deprecated and subsequently removed when // performing a major release. func Fail(message string) { panic(message) } ================================================ FILE: go/internal/tinkerror/tinkerror_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tinkerror_test import ( "testing" "github.com/google/tink/go/internal/tinkerror" "github.com/google/tink/go/internal/tinkerror/tinkerrortest" ) func TestFail(t *testing.T) { err := tinkerrortest.RecoverFromFail(func() { tinkerror.Fail("error message") }) if err == nil { t.Errorf("tinkerror.Fail() did not fail") } } ================================================ FILE: go/internal/tinkerror/tinkerrortest/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) go_library( name = "tinkerrortest", testonly = 1, srcs = [ "doc.go", "tinkerrortest.go", ], importpath = "github.com/google/tink/go/internal/tinkerror/tinkerrortest", ) alias( name = "go_default_library", actual = ":tinkerrortest", visibility = ["//:__subpackages__"], ) ================================================ FILE: go/internal/tinkerror/tinkerrortest/doc.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package tinkerrortest provides test functionality for package tinkerror. package tinkerrortest ================================================ FILE: go/internal/tinkerror/tinkerrortest/tinkerrortest.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tinkerrortest import "fmt" // RecoverFromFail facilitates testing a function f in which [tinkerror.Fail] // is called. func RecoverFromFail(f func()) (err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("%v", r) } }() f() return } ================================================ FILE: go/jwt/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") licenses(["notice"]) package(default_visibility = ["//:__subpackages__"]) # keep go_library( name = "jwt", srcs = [ "jwk_converter.go", "jwt.go", "jwt_ecdsa_signer_key_manager.go", "jwt_ecdsa_verifier_key_manager.go", "jwt_encoding.go", "jwt_hmac_key_manager.go", "jwt_key_templates.go", "jwt_mac.go", "jwt_mac_factory.go", "jwt_mac_kid.go", "jwt_rsa_ssa_pkcs1_signer_key_manager.go", "jwt_rsa_ssa_pkcs1_verifier_key_manager.go", "jwt_rsa_ssa_pss_signer_key_manager.go", "jwt_rsa_ssa_pss_verify_key_manager.go", "jwt_signer.go", "jwt_signer_factory.go", "jwt_signer_kid.go", "jwt_validator.go", "jwt_verifier.go", "jwt_verifier_factory.go", "jwt_verifier_kid.go", "raw_jwt.go", "verified_jwt.go", ], importpath = "github.com/google/tink/go/jwt", visibility = ["//visibility:public"], deps = [ "//core/primitiveset", "//core/registry", "//internal/signature", "//internal/tinkerror", "//keyset", "//mac/subtle", "//proto/jwt_ecdsa_go_proto", "//proto/jwt_hmac_go_proto", "//proto/jwt_rsa_ssa_pkcs1_go_proto", "//proto/jwt_rsa_ssa_pss_go_proto", "//proto/tink_go_proto", "//signature/subtle", "//subtle", "//subtle/random", "//tink", "@org_golang_google_protobuf//proto", "@org_golang_google_protobuf//types/known/structpb", ], ) go_test( name = "jwt_test", srcs = [ "jwk_converter_test.go", "jwt_ecdsa_signer_key_manager_test.go", "jwt_ecdsa_verifier_key_manager_test.go", "jwt_encoding_test.go", "jwt_hmac_key_manager_test.go", "jwt_key_templates_test.go", "jwt_mac_factory_test.go", "jwt_mac_kid_test.go", "jwt_rsa_ssa_pkcs1_signer_key_manager_test.go", "jwt_rsa_ssa_pkcs1_verifier_key_manager_test.go", "jwt_rsa_ssa_pss_signer_key_manager_test.go", "jwt_rsa_ssa_pss_verify_key_manager_test.go", "jwt_signer_verifier_factory_test.go", "jwt_signer_verifier_kid_test.go", "jwt_test.go", "jwt_validator_test.go", "raw_jwt_test.go", "verified_jwt_test.go", ], embed = [":jwt"], deps = [ "//core/registry", "//insecurecleartextkeyset", "//keyset", "//mac/subtle", "//proto/ecdsa_go_proto", "//proto/jwt_ecdsa_go_proto", "//proto/jwt_hmac_go_proto", "//proto/jwt_rsa_ssa_pkcs1_go_proto", "//proto/jwt_rsa_ssa_pss_go_proto", "//proto/tink_go_proto", "//signature", "//signature/subtle", "//subtle/random", "//testkeyset", "//testutil", "//tink", "@com_github_google_go_cmp//cmp", "@com_github_google_go_cmp//cmp/cmpopts", "@org_golang_google_protobuf//proto", "@org_golang_google_protobuf//testing/protocmp", "@org_golang_google_protobuf//types/known/structpb", ], ) alias( name = "go_default_library", actual = ":jwt", visibility = ["//visibility:public"], ) ================================================ FILE: go/jwt/jwk_converter.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "bytes" "fmt" "math/big" "math/rand" spb "google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/proto" "github.com/google/tink/go/keyset" jepb "github.com/google/tink/go/proto/jwt_ecdsa_go_proto" jrsppb "github.com/google/tink/go/proto/jwt_rsa_ssa_pkcs1_go_proto" jrpsspb "github.com/google/tink/go/proto/jwt_rsa_ssa_pss_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( jwtECDSAPublicKeyType = "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey" jwtRSPublicKeyType = "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PublicKey" jwtPSPublicKeyType = "type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPublicKey" ) func keysetHasID(ks *tinkpb.Keyset, keyID uint32) bool { for _, k := range ks.GetKey() { if k.GetKeyId() == keyID { return true } } return false } func generateUnusedID(ks *tinkpb.Keyset) uint32 { for { keyID := rand.Uint32() if !keysetHasID(ks, keyID) { return keyID } } } func hasItem(s *spb.Struct, name string) bool { if s.GetFields() == nil { return false } _, ok := s.Fields[name] return ok } func stringItem(s *spb.Struct, name string) (string, error) { fields := s.GetFields() if fields == nil { return "", fmt.Errorf("no fields") } val, ok := fields[name] if !ok { return "", fmt.Errorf("field %q not found", name) } r, ok := val.Kind.(*spb.Value_StringValue) if !ok { return "", fmt.Errorf("field %q is not a string", name) } return r.StringValue, nil } func listValue(s *spb.Struct, name string) (*spb.ListValue, error) { fields := s.GetFields() if fields == nil { return nil, fmt.Errorf("empty set") } vals, ok := fields[name] if !ok { return nil, fmt.Errorf("%q not found", name) } list, ok := vals.Kind.(*spb.Value_ListValue) if !ok { return nil, fmt.Errorf("%q is not a list", name) } if list.ListValue == nil || len(list.ListValue.GetValues()) == 0 { return nil, fmt.Errorf("%q list is empty", name) } return list.ListValue, nil } func expectStringItem(s *spb.Struct, name, value string) error { item, err := stringItem(s, name) if err != nil { return err } if item != value { return fmt.Errorf("unexpected value %q for %q", value, name) } return nil } func decodeItem(s *spb.Struct, name string) ([]byte, error) { e, err := stringItem(s, name) if err != nil { return nil, err } return base64Decode(e) } func validateKeyOPSIsVerify(s *spb.Struct) error { if !hasItem(s, "key_ops") { return nil } keyOPSList, err := listValue(s, "key_ops") if err != nil { return err } if len(keyOPSList.GetValues()) != 1 { return fmt.Errorf("key_ops size is not 1") } value, ok := keyOPSList.GetValues()[0].Kind.(*spb.Value_StringValue) if !ok { return fmt.Errorf("key_ops is not a string") } if value.StringValue != "verify" { return fmt.Errorf("key_ops is not equal to [\"verify\"]") } return nil } func validateUseIsSig(s *spb.Struct) error { if !hasItem(s, "use") { return nil } return expectStringItem(s, "use", "sig") } func algorithmPrefix(s *spb.Struct) (string, error) { alg, err := stringItem(s, "alg") if err != nil { return "", err } if len(alg) < 2 { return "", fmt.Errorf("invalid algorithm") } return alg[0:2], nil } var psNameToAlg = map[string]jrpsspb.JwtRsaSsaPssAlgorithm{ "PS256": jrpsspb.JwtRsaSsaPssAlgorithm_PS256, "PS384": jrpsspb.JwtRsaSsaPssAlgorithm_PS384, "PS512": jrpsspb.JwtRsaSsaPssAlgorithm_PS512, } func psPublicKeyDataFromStruct(keyStruct *spb.Struct) (*tinkpb.KeyData, error) { alg, err := stringItem(keyStruct, "alg") if err != nil { return nil, err } algorithm, ok := psNameToAlg[alg] if !ok { return nil, fmt.Errorf("invalid alg header: %q", alg) } rsaPubKey, err := rsaPubKeyFromStruct(keyStruct) if err != nil { return nil, err } jwtPubKey := &jrpsspb.JwtRsaSsaPssPublicKey{ Version: jwtECDSASignerKeyVersion, Algorithm: algorithm, E: rsaPubKey.exponent, N: rsaPubKey.modulus, } if rsaPubKey.customKID != nil { jwtPubKey.CustomKid = &jrpsspb.JwtRsaSsaPssPublicKey_CustomKid{ Value: *rsaPubKey.customKID, } } serializedPubKey, err := proto.Marshal(jwtPubKey) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: jwtPSPublicKeyType, Value: serializedPubKey, KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC, }, nil } var rsNameToAlg = map[string]jrsppb.JwtRsaSsaPkcs1Algorithm{ "RS256": jrsppb.JwtRsaSsaPkcs1Algorithm_RS256, "RS384": jrsppb.JwtRsaSsaPkcs1Algorithm_RS384, "RS512": jrsppb.JwtRsaSsaPkcs1Algorithm_RS512, } func rsPublicKeyDataFromStruct(keyStruct *spb.Struct) (*tinkpb.KeyData, error) { alg, err := stringItem(keyStruct, "alg") if err != nil { return nil, err } algorithm, ok := rsNameToAlg[alg] if !ok { return nil, fmt.Errorf("invalid alg header: %q", alg) } rsaPubKey, err := rsaPubKeyFromStruct(keyStruct) if err != nil { return nil, err } jwtPubKey := &jrsppb.JwtRsaSsaPkcs1PublicKey{ Version: 0, Algorithm: algorithm, E: rsaPubKey.exponent, N: rsaPubKey.modulus, } if rsaPubKey.customKID != nil { jwtPubKey.CustomKid = &jrsppb.JwtRsaSsaPkcs1PublicKey_CustomKid{ Value: *rsaPubKey.customKID, } } serializedPubKey, err := proto.Marshal(jwtPubKey) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: jwtRSPublicKeyType, Value: serializedPubKey, KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC, }, nil } type rsaPubKey struct { exponent []byte modulus []byte customKID *string } func rsaPubKeyFromStruct(keyStruct *spb.Struct) (*rsaPubKey, error) { if hasItem(keyStruct, "p") || hasItem(keyStruct, "q") || hasItem(keyStruct, "dq") || hasItem(keyStruct, "dp") || hasItem(keyStruct, "d") || hasItem(keyStruct, "qi") { return nil, fmt.Errorf("private key can't be converted") } if err := expectStringItem(keyStruct, "kty", "RSA"); err != nil { return nil, err } if err := validateUseIsSig(keyStruct); err != nil { return nil, err } if err := validateKeyOPSIsVerify(keyStruct); err != nil { return nil, err } e, err := decodeItem(keyStruct, "e") if err != nil { return nil, err } n, err := decodeItem(keyStruct, "n") if err != nil { return nil, err } var customKID *string = nil if hasItem(keyStruct, "kid") { kid, err := stringItem(keyStruct, "kid") if err != nil { return nil, err } customKID = &kid } return &rsaPubKey{ exponent: e, modulus: n, customKID: customKID, }, nil } func esPublicKeyDataFromStruct(keyStruct *spb.Struct) (*tinkpb.KeyData, error) { alg, err := stringItem(keyStruct, "alg") if err != nil { return nil, err } curve, err := stringItem(keyStruct, "crv") if err != nil { return nil, err } var algorithm jepb.JwtEcdsaAlgorithm = jepb.JwtEcdsaAlgorithm_ES_UNKNOWN if alg == "ES256" && curve == "P-256" { algorithm = jepb.JwtEcdsaAlgorithm_ES256 } if alg == "ES384" && curve == "P-384" { algorithm = jepb.JwtEcdsaAlgorithm_ES384 } if alg == "ES512" && curve == "P-521" { algorithm = jepb.JwtEcdsaAlgorithm_ES512 } if algorithm == jepb.JwtEcdsaAlgorithm_ES_UNKNOWN { return nil, fmt.Errorf("invalid algorithm %q and curve %q", alg, curve) } if hasItem(keyStruct, "d") { return nil, fmt.Errorf("private keys cannot be converted") } if err := expectStringItem(keyStruct, "kty", "EC"); err != nil { return nil, err } if err := validateUseIsSig(keyStruct); err != nil { return nil, err } if err := validateKeyOPSIsVerify(keyStruct); err != nil { return nil, err } x, err := decodeItem(keyStruct, "x") if err != nil { return nil, fmt.Errorf("failed to decode x: %v", err) } y, err := decodeItem(keyStruct, "y") if err != nil { return nil, fmt.Errorf("failed to decode y: %v", err) } var customKID *jepb.JwtEcdsaPublicKey_CustomKid = nil if hasItem(keyStruct, "kid") { kid, err := stringItem(keyStruct, "kid") if err != nil { return nil, err } customKID = &jepb.JwtEcdsaPublicKey_CustomKid{Value: kid} } pubKey := &jepb.JwtEcdsaPublicKey{ Version: 0, Algorithm: algorithm, X: x, Y: y, CustomKid: customKID, } serializedPubKey, err := proto.Marshal(pubKey) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: jwtECDSAPublicKeyType, Value: serializedPubKey, KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC, }, nil } func keysetKeyFromStruct(val *spb.Value, keyID uint32) (*tinkpb.Keyset_Key, error) { keyStruct := val.GetStructValue() if keyStruct == nil { return nil, fmt.Errorf("key is not a JSON object") } algPrefix, err := algorithmPrefix(keyStruct) if err != nil { return nil, err } var keyData *tinkpb.KeyData switch algPrefix { case "ES": keyData, err = esPublicKeyDataFromStruct(keyStruct) case "RS": keyData, err = rsPublicKeyDataFromStruct(keyStruct) case "PS": keyData, err = psPublicKeyDataFromStruct(keyStruct) default: return nil, fmt.Errorf("unsupported algorithm prefix: %v", algPrefix) } if err != nil { return nil, err } return &tinkpb.Keyset_Key{ KeyData: keyData, Status: tinkpb.KeyStatusType_ENABLED, OutputPrefixType: tinkpb.OutputPrefixType_RAW, KeyId: keyID, }, nil } // JWKSetToPublicKeysetHandle converts a Json Web Key (JWK) set into a Tink KeysetHandle. // It requires that all keys in the set have the "alg" field set. Currently, only // public keys for algorithms ES256, ES384, ES512, RS256, RS384, and RS512 are supported. // JWK is defined in https://www.rfc-editor.org/rfc/rfc7517.txt. func JWKSetToPublicKeysetHandle(jwkSet []byte) (*keyset.Handle, error) { jwk := &spb.Struct{} if err := jwk.UnmarshalJSON(jwkSet); err != nil { return nil, err } keyList, err := listValue(jwk, "keys") if err != nil { return nil, err } ks := &tinkpb.Keyset{} for _, keyStruct := range keyList.GetValues() { key, err := keysetKeyFromStruct(keyStruct, generateUnusedID(ks)) if err != nil { return nil, err } ks.Key = append(ks.Key, key) } ks.PrimaryKeyId = ks.Key[len(ks.Key)-1].GetKeyId() return keyset.NewHandleWithNoSecrets(ks) } func addKeyOPSVerify(s *spb.Struct) { s.GetFields()["key_ops"] = spb.NewListValue(&spb.ListValue{Values: []*spb.Value{spb.NewStringValue("verify")}}) } func addStringEntry(s *spb.Struct, key, val string) { s.GetFields()[key] = spb.NewStringValue(val) } var psAlgToStr map[jrpsspb.JwtRsaSsaPssAlgorithm]string = map[jrpsspb.JwtRsaSsaPssAlgorithm]string{ jrpsspb.JwtRsaSsaPssAlgorithm_PS256: "PS256", jrpsspb.JwtRsaSsaPssAlgorithm_PS384: "PS384", jrpsspb.JwtRsaSsaPssAlgorithm_PS512: "PS512", } func psPublicKeyToStruct(key *tinkpb.Keyset_Key) (*spb.Struct, error) { pubKey := &jrpsspb.JwtRsaSsaPssPublicKey{} if err := proto.Unmarshal(key.GetKeyData().GetValue(), pubKey); err != nil { return nil, err } alg, ok := psAlgToStr[pubKey.GetAlgorithm()] if !ok { return nil, fmt.Errorf("invalid algorithm") } outKey := &spb.Struct{ Fields: map[string]*spb.Value{}, } addStringEntry(outKey, "alg", alg) addStringEntry(outKey, "kty", "RSA") addStringEntry(outKey, "e", base64Encode(pubKey.GetE())) addStringEntry(outKey, "n", base64Encode(pubKey.GetN())) addStringEntry(outKey, "use", "sig") addKeyOPSVerify(outKey) var customKID *string = nil if pubKey.GetCustomKid() != nil { ck := pubKey.GetCustomKid().GetValue() customKID = &ck } if err := setKeyID(outKey, key, customKID); err != nil { return nil, err } return outKey, nil } var rsAlgToStr map[jrsppb.JwtRsaSsaPkcs1Algorithm]string = map[jrsppb.JwtRsaSsaPkcs1Algorithm]string{ jrsppb.JwtRsaSsaPkcs1Algorithm_RS256: "RS256", jrsppb.JwtRsaSsaPkcs1Algorithm_RS384: "RS384", jrsppb.JwtRsaSsaPkcs1Algorithm_RS512: "RS512", } func rsPublicKeyToStruct(key *tinkpb.Keyset_Key) (*spb.Struct, error) { pubKey := &jrsppb.JwtRsaSsaPkcs1PublicKey{} if err := proto.Unmarshal(key.GetKeyData().GetValue(), pubKey); err != nil { return nil, err } alg, ok := rsAlgToStr[pubKey.GetAlgorithm()] if !ok { return nil, fmt.Errorf("invalid algorithm") } outKey := &spb.Struct{ Fields: map[string]*spb.Value{}, } addStringEntry(outKey, "alg", alg) addStringEntry(outKey, "kty", "RSA") addStringEntry(outKey, "e", base64Encode(pubKey.GetE())) addStringEntry(outKey, "n", base64Encode(pubKey.GetN())) addStringEntry(outKey, "use", "sig") addKeyOPSVerify(outKey) var customKID *string = nil if pubKey.GetCustomKid() != nil { ck := pubKey.GetCustomKid().GetValue() customKID = &ck } if err := setKeyID(outKey, key, customKID); err != nil { return nil, err } return outKey, nil } func esPublicKeyToStruct(key *tinkpb.Keyset_Key) (*spb.Struct, error) { pubKey := &jepb.JwtEcdsaPublicKey{} if err := proto.Unmarshal(key.GetKeyData().GetValue(), pubKey); err != nil { return nil, err } outKey := &spb.Struct{ Fields: map[string]*spb.Value{}, } var algorithm, curve string var encLen int switch pubKey.GetAlgorithm() { case jepb.JwtEcdsaAlgorithm_ES256: curve, algorithm, encLen = "P-256", "ES256", 32 case jepb.JwtEcdsaAlgorithm_ES384: curve, algorithm, encLen = "P-384", "ES384", 48 case jepb.JwtEcdsaAlgorithm_ES512: curve, algorithm, encLen = "P-521", "ES512", 66 default: return nil, fmt.Errorf("invalid algorithm") } // RFC 7518 specifies a fixed sized encoding for the x and y coordinates from SEC 1 // https://datatracker.ietf.org/doc/html/rfc7518#section-6.2.1.2 xi := big.NewInt(0).SetBytes(pubKey.GetX()) if xi.BitLen() > encLen*8 { return nil, fmt.Errorf("invalid x coordinate") } x := xi.FillBytes(make([]byte, encLen)) yi := big.NewInt(0).SetBytes(pubKey.GetY()) if yi.BitLen() > encLen*8 { return nil, fmt.Errorf("invalid y coordinate") } y := yi.FillBytes(make([]byte, encLen)) addStringEntry(outKey, "crv", curve) addStringEntry(outKey, "alg", algorithm) addStringEntry(outKey, "kty", "EC") addStringEntry(outKey, "x", base64Encode(x)) addStringEntry(outKey, "y", base64Encode(y)) addStringEntry(outKey, "use", "sig") addKeyOPSVerify(outKey) var customKID *string = nil if pubKey.GetCustomKid() != nil { ck := pubKey.GetCustomKid().GetValue() customKID = &ck } if err := setKeyID(outKey, key, customKID); err != nil { return nil, err } return outKey, nil } func setKeyID(outKey *spb.Struct, key *tinkpb.Keyset_Key, customKID *string) error { if key.GetOutputPrefixType() == tinkpb.OutputPrefixType_TINK { if customKID != nil { return fmt.Errorf("TINK keys shouldn't have custom KID") } kid := keyID(key.KeyId, key.GetOutputPrefixType()) if kid == nil { return fmt.Errorf("tink KID shouldn't be nil") } addStringEntry(outKey, "kid", *kid) } else if customKID != nil { addStringEntry(outKey, "kid", *customKID) } return nil } // JWKSetFromPublicKeysetHandle converts a Tink KeysetHandle with JWT keys into a Json Web Key (JWK) set. // Currently only public keys for algorithms ES256, ES384, ES512, RS256, RS384, and RS512 are supported. // JWK is defined in https://www.rfc-editor.org/rfc/rfc7517.html. func JWKSetFromPublicKeysetHandle(kh *keyset.Handle) ([]byte, error) { b := &bytes.Buffer{} if err := kh.WriteWithNoSecrets(keyset.NewBinaryWriter(b)); err != nil { return nil, err } ks := &tinkpb.Keyset{} if err := proto.Unmarshal(b.Bytes(), ks); err != nil { return nil, err } keyValList := []*spb.Value{} for _, k := range ks.Key { if k.GetStatus() != tinkpb.KeyStatusType_ENABLED { continue } if k.GetOutputPrefixType() != tinkpb.OutputPrefixType_TINK && k.GetOutputPrefixType() != tinkpb.OutputPrefixType_RAW { return nil, fmt.Errorf("unsupported output prefix type") } keyData := k.GetKeyData() if keyData == nil { return nil, fmt.Errorf("invalid key data") } if keyData.GetKeyMaterialType() != tinkpb.KeyData_ASYMMETRIC_PUBLIC { return nil, fmt.Errorf("only asymmetric public keys are supported") } keyStruct := &spb.Struct{} var err error switch keyData.GetTypeUrl() { case jwtECDSAPublicKeyType: keyStruct, err = esPublicKeyToStruct(k) case jwtRSPublicKeyType: keyStruct, err = rsPublicKeyToStruct(k) case jwtPSPublicKeyType: keyStruct, err = psPublicKeyToStruct(k) default: return nil, fmt.Errorf("unsupported key type url") } if err != nil { return nil, err } keyValList = append(keyValList, spb.NewStructValue(keyStruct)) } output := &spb.Struct{ Fields: map[string]*spb.Value{ "keys": spb.NewListValue(&spb.ListValue{Values: keyValList}), }, } return output.MarshalJSON() } ================================================ FILE: go/jwt/jwk_converter_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt_test import ( "bytes" "encoding/base64" "fmt" "testing" spb "google.golang.org/protobuf/types/known/structpb" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/testing/protocmp" "github.com/google/tink/go/jwt" "github.com/google/tink/go/keyset" "github.com/google/tink/go/testkeyset" epb "github.com/google/tink/go/proto/ecdsa_go_proto" jepb "github.com/google/tink/go/proto/jwt_ecdsa_go_proto" jrsppb "github.com/google/tink/go/proto/jwt_rsa_ssa_pkcs1_go_proto" jrpsspb "github.com/google/tink/go/proto/jwt_rsa_ssa_pss_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) type jwkSetTestCase struct { tag string jwkSet string privateKeyset string publicKeyset string } // synchronized with tests cases from JWK converter for C++ var jwkSetTestCases = []jwkSetTestCase{ { tag: "ES256", jwkSet: `{ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES256","key_ops":["verify"], "kid":"EhuduQ"}] }`, privateKeyset: `{ "primaryKeyId": 303799737, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey", "value": "GiA2S/eedsXqu0DhnOlCJugsHugdpPaAGr/byxXXsZBiVRJGIiDuhGJiGeaQ/qeqt1daC2xZRarm4VEsmSHJUWJY9EHbvxogwO6uIxh8SkKOO8VjZXNRTteRcwCPE4/4JElKyaa0fcQQAQ==", "keyMaterialType": "ASYMMETRIC_PRIVATE" }, "status": "ENABLED", "keyId": 303799737, "outputPrefixType": "TINK" } ] }`, }, { tag: "ES384", jwkSet: `{ "keys":[{"kty":"EC","crv":"P-384", "x":"AEUCTkKhRDEgJ2pTiyPoSsIOERywrB2xjBDgUH8LLg0Ao9xT2SxKadxLdRFIr8Ll", "y":"wQcqkI9pV66PJFmJVyZ7BsqvFaqoWT-jAFvYNjsgdvAIpyB3MHWXkxNhlPYcpEIf", "use":"sig","alg":"ES384","key_ops":["verify"],"kid":"f-fUcw"}] }`, privateKeyset: `{ "primaryKeyId": 2145899635, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey", "value": "GjCfHcFYHsiwTcBCATSyjOyJ64iy4LGa4OuFaR9wZqkYTuYrY1I3ssxO4UK11j/IUe4SZiIwwQcqkI9pV66PJFmJVyZ7BsqvFaqoWT+jAFvYNjsgdvAIpyB3MHWXkxNhlPYcpEIfGjAARQJOQqFEMSAnalOLI+hKwg4RHLCsHbGMEOBQfwsuDQCj3FPZLEpp3Et1EUivwuUQAg==", "keyMaterialType": "ASYMMETRIC_PRIVATE" }, "status": "ENABLED", "keyId": 2145899635, "outputPrefixType": "TINK" } ] }`, }, { tag: "ES512", jwkSet: `{ "keys":[{"kty":"EC","crv":"P-521", "x":"AKRFrHHoTaFAO-d4sCOw78KyUlZijBgqfp2rXtkLZ_QQGLtDM2nScAilkryvw3c_4fM39CEygtSunFLI9xyUyE3m", "y":"ANZK5JjTcNAKtezmXFvDSkrxdxPiuX2uPq6oR3M0pb2wqnfDL-nWeWcKb2nAOxYSyydsrZ98bxBL60lEr20x1Gc_", "use":"sig","alg":"ES512","key_ops":["verify"],"kid":"WDqzeQ"}] }`, privateKeyset: `{ "primaryKeyId": 1480242041, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey", "value": "GkIBnhWq6UrOj8hKwGovjSsLT+dtAGlRqoIkQ2FzMeKxIApx0dT3O4yHrmi6v5sElZHM6BsLz47IopAOajVRYGh48b0SigEiQgDWSuSY03DQCrXs5lxbw0pK8XcT4rl9rj6uqEdzNKW9sKp3wy/p1nlnCm9pwDsWEssnbK2ffG8QS+tJRK9tMdRnPxpCAKRFrHHoTaFAO+d4sCOw78KyUlZijBgqfp2rXtkLZ/QQGLtDM2nScAilkryvw3c/4fM39CEygtSunFLI9xyUyE3mEAM=", "keyMaterialType": "ASYMMETRIC_PRIVATE" }, "status": "ENABLED", "keyId": 1480242041, "outputPrefixType": "TINK" } ] }`, }, { tag: "ES256_NO_KID", jwkSet: `{ "keys":[{ "kty":"EC", "crv":"P-256", "x":"ytH8MlvqTx3X-eL0pdx4ULKUb2YOi2DPnIPpSaIk28M", "y":"AO5TMe5lNcjJpuGjjGtHd4gX9POG9dh_vG-8ptp7HJs", "use":"sig","alg":"ES256","key_ops":["verify"]}] }`, privateKeyset: `{ "primaryKeyId": 765975903, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey", "value": "GiCbUAItoAVleOSwYdPWs563CCFhGHSdX4t/C2xBY2J/ERJGIiAA7lMx7mU1yMmm4aOMa0d3iBf084b12H+8b7ym2nscmxogytH8MlvqTx3X+eL0pdx4ULKUb2YOi2DPnIPpSaIk28MQAQ==", "keyMaterialType": "ASYMMETRIC_PRIVATE" }, "status": "ENABLED", "keyId": 765975903, "outputPrefixType": "RAW" } ] }`, }, { tag: "multiple keys", jwkSet: `{ "keys":[ { "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES256","key_ops":["verify"], "kid":"EhuduQ" }, { "kty":"EC", "crv":"P-384", "x":"AEUCTkKhRDEgJ2pTiyPoSsIOERywrB2xjBDgUH8LLg0Ao9xT2SxKadxLdRFIr8Ll", "y":"wQcqkI9pV66PJFmJVyZ7BsqvFaqoWT-jAFvYNjsgdvAIpyB3MHWXkxNhlPYcpEIf", "use":"sig","alg":"ES384","key_ops":["verify"], "kid":"f-fUcw" } ] }`, privateKeyset: `{ "primaryKeyId": 303799737, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey", "value": "GiA2S/eedsXqu0DhnOlCJugsHugdpPaAGr/byxXXsZBiVRJGIiDuhGJiGeaQ/qeqt1daC2xZRarm4VEsmSHJUWJY9EHbvxogwO6uIxh8SkKOO8VjZXNRTteRcwCPE4/4JElKyaa0fcQQAQ==", "keyMaterialType": "ASYMMETRIC_PRIVATE" }, "status": "ENABLED", "keyId": 303799737, "outputPrefixType": "TINK" }, { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey", "value": "GjCfHcFYHsiwTcBCATSyjOyJ64iy4LGa4OuFaR9wZqkYTuYrY1I3ssxO4UK11j/IUe4SZiIwwQcqkI9pV66PJFmJVyZ7BsqvFaqoWT+jAFvYNjsgdvAIpyB3MHWXkxNhlPYcpEIfGjAARQJOQqFEMSAnalOLI+hKwg4RHLCsHbGMEOBQfwsuDQCj3FPZLEpp3Et1EUivwuUQAg==", "keyMaterialType": "ASYMMETRIC_PRIVATE" }, "status": "ENABLED", "keyId": 2145899635, "outputPrefixType": "TINK" } ] }`, }, { tag: "RS256", jwkSet: `{ "keys":[{ "kty":"RSA", "n": "vmUOa62TYrxj7N8rZVAzoEdSnmsRQaNWBMAdB8adGa8n4ycGiYWoGv0uZWc8vH2jn6l3Pa_72bb2IHf3-KD2UaTwLk1x3yShXybEoS5ZF9bemzrn2ohNixGoN7Ofj7wPb61Z-F1Nv53nq308z-RI1WeyIH-9HjuIcuUxaWY0VevsXzCehMJP5g7kVzyl55bYcRi28didkVazrzVgNG35yNNMEL32oW1Vfvvp7hfQHtxSwkFOPzJgzIPHbJFbxALGrrgXHsoq7UtDQdS9vvoEp4_JzQhCtnCEKahgkTwOWyT96OlRGYiPJSFHWTujy1Qnd6OKc8LGEspAX4oD6Zl-YQ", "e":"AQAB", "use":"sig", "alg":"RS256", "key_ops":["verify"], "kid":"TCGiGw" }] }`, privateKeyset: `{ "primaryKeyId":1277272603, "key":[{ "keyData":{ "typeUrl": "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PrivateKey", "value":"QoABP3S5U0JiFQcqcMFT0Ysqk7FK2NunBCY9o+EAE+svaQi6zWQq2ODFoxB2NU9nqa3ZbhRiCdKNLz6o+jOTIpemKx8Gh/7GufRGLFAjjMchZYs3ripiTNSMaqXgm6ECt8DqrAZbMQ7D3Ha1vArcZG97pbE9t3m4M87zhLs3wPYd/kQ6gAEFPE2GLD5ai8VYd/Q0ePZR0ttLgkJ/2yIig5T8YyJaoZEPjK+v3zVFQuGguJApnl2tC0S7OqOtqsDZ5Dux0H3Cx85FLeyB2STHlXtq9GUGI2VrC/TP3OASc6ap75WMKZRpowEVaip8wWehAOL+VIgTajiFf0yXdSodc4ZjJKreiTKAAd6ahHQiVJapNKY6XANgA+JmluAWq/Fk1LmEnTybWVelcODbppwIvhJ6Xuz6kjuEhhxsUtkPO4vuZJfEF8DWAH5L/FHjJpgP3NnDoNVzGOL5w8SdgIfgCS0UqBLSv2/KhlIEijuL9NYaqydN1cPcjdeadSMcDSIwKjNASRVaPZDJKoABx1/CfOqCbE8eh450YvGwYvII+ro8tR+uusnt2QuQZux3wvl9eto9Dr+5Iq/0bKqpMMgvYHIT+mlkgK6SYLcynZx+SYMAtbixa0nH1lJnnBodOJS6zdMRTcFkpI4g/CbCvzTp5gF5EkfBSbVToVLqICydokKnTvNK6chX3MEUjskigAH0eGwQwn174yJzJTUWH4cRxDredI6LkjADm/ikza76AHT8qRJHJkmwSXL88p3M2bYFN+g9Z/FTL21Ylc0mxn/iII3vabfZWZTWK9QGR7YjAicFyLDeu/ZccCkCXgTFzqqlZ7w4Sv05hWz57xxm81JyxftzapeflfAmjRircFXG2RqAAgub/Z28+SFSf6zSPFMKiYVWx//DI0ubbiuuu65tUse9xYq9JtHEobgYk0dJXNuY9RzPkGblZ8/SD06yRf9l8DMRAbivDfgXY5QZ2PBDk1jn6A2y0S+i80h9MILJ+/sfkljiyvtBFDQwiI9tPOOnxbWmg6bl5xYUdvjbhxBoVB1fgOtAid6gGuLstbf8ycV+DkaWg3mo4054ge9BBT4eWKGC/LHctSaQ/OBs5cbGW+UqZxIjSN9YeOTkbvNKO4l4jGTg0BUBPB3GH8KQPtE4sbBhUDyjYYgAZZcSaRq7AfhLUkiDSfIVcKAIoEOaTS63vf2BQlbW8/HuNlWNUX0M+hkSigIiAwEAARqAAr5lDmutk2K8Y+zfK2VQM6BHUp5rEUGjVgTAHQfGnRmvJ+MnBomFqBr9LmVnPLx9o5+pdz2v+9m29iB39/ig9lGk8C5Ncd8koV8mxKEuWRfW3ps659qITYsRqDezn4+8D2+tWfhdTb+d56t9PM/kSNVnsiB/vR47iHLlMWlmNFXr7F8wnoTCT+YO5Fc8peeW2HEYtvHYnZFWs681YDRt+cjTTBC99qFtVX776e4X0B7cUsJBTj8yYMyDx2yRW8QCxq64Fx7KKu1LQ0HUvb76BKePyc0IQrZwhCmoYJE8Dlsk/ejpURmIjyUhR1k7o8tUJ3ejinPCxhLKQF+KA+mZfmEQAQ==", "keyMaterialType":"ASYMMETRIC_PRIVATE" }, "status":"ENABLED", "keyId":1277272603, "outputPrefixType":"TINK" }] }`, }, { tag: "RS384", jwkSet: `{ "keys":[{ "kty":"RSA", "n":"AI83_8Uy0v4xS6kDZKqcqzSbeyksy2C67ajtI41J2KMDtO9jUaEAQ9uDhMubjZzPYh1wf_gtJgAC5PSiI3fOLUG0AHCbi_yXVfH3_1U_Yl4b_e8yx_NPyuIvwHwXwE5a32hiss9PuY2-qEivH5LK4AXxPiTiUc9x4gh1OwZaSTYWT7SRO-0ROwYwCwpg4Uf0IMLtmHou_NmNw0uOlOgKfx-EFmMzV-5pspEnwsHq_ijFSxmHNAdy5S0n4u1LIKKmgXJIyUu3AKfAJMydn6nTKzrOcpX0yMnxPq9yP8xKuK_mXysFyNvmS0Sq5c-grOETFeMFScweoUpWVnYOCCSyZ93yAhsTUWnDjZd7iuji9Y7zUo4PWlKXyRRz_aSpxrsn70LOZNLLUjILVeyfCRs2JXptfxCNg3wg6FVAH0xTORmPGICgWDmwOFgP1Y6tW-p0cnK8LwVkuRclyKAMvTtYm9xZZHUSjw86rHEnB2VfsPTIn0_WAVnJ2OAKhuVMtwjB7Q", "e":"AQAB", "use":"sig", "alg":"RS384", "key_ops":["verify"], "kid":"FVLRIg" }] }`, privateKeyset: `{ "primaryKeyId":357749026, "key":[{ "keyData":{ "typeUrl": "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PrivateKey", "value":"EosDEAIagQMAjzf/xTLS/jFLqQNkqpyrNJt7KSzLYLrtqO0jjUnYowO072NRoQBD24OEy5uNnM9iHXB/+C0mAALk9KIjd84tQbQAcJuL/JdV8ff/VT9iXhv97zLH80/K4i/AfBfATlrfaGKyz0+5jb6oSK8fksrgBfE+JOJRz3HiCHU7BlpJNhZPtJE77RE7BjALCmDhR/Qgwu2Yei782Y3DS46U6Ap/H4QWYzNX7mmykSfCwer+KMVLGYc0B3LlLSfi7UsgoqaBckjJS7cAp8AkzJ2fqdMrOs5ylfTIyfE+r3I/zEq4r+ZfKwXI2+ZLRKrlz6Cs4RMV4wVJzB6hSlZWdg4IJLJn3fICGxNRacONl3uK6OL1jvNSjg9aUpfJFHP9pKnGuyfvQs5k0stSMgtV7J8JGzYlem1/EI2DfCDoVUAfTFM5GY8YgKBYObA4WA/Vjq1b6nRycrwvBWS5FyXIoAy9O1ib3FlkdRKPDzqscScHZV+w9MifT9YBWcnY4AqG5Uy3CMHtIgMBAAEagAMPPYhMNdJaFmjUvXWy6iUV3g3HHesuifXMah/EYz1Ya4aPiuQe2+Zcr6wr9oulSjRIqbYUdMl8atJubeqUTy5ltX/ue77zzC7rJtbW/X28QgJNt/urGqyeUTKMggKG1Ai+FPKuOO+n88f4pBoaBti8CSXxytul1ZqWB9OWI3ly9gDZWDMmURUU3XvvSMvwWjw6Qgpdxi5GAF3t5mhWIPfSJL41JDuRNVI5PB/vftA5CnWpa8fPmxxkJ8BwO/RnGoy3GgFGFwRuvuLiQgQiHwjCq6czgCKaw1FPq5HaTyJBdCfv+gDG8EjvnsDLzWQqQkq7obvY7uSCxw2lomlXp4cPOo5dbwTSJg2OessyL4rQQJZjw78etOMjOx1M+Q4sVlKbPdd/qxZpnlZ2EG1oUjRM7ZMuJEVfxSy7KRt9GG0P4pqMX7uhMmjF5B/H/re/GujrhISA92cPc8MQX+IA1z9ZHUrHgSMLoSVIf7pwB335sQe9R6pR8xjgoPorFzQ7/kEiwQEAwBOLB9g8uS68ypaUHMixM0RSqaHwaCmhJ8YvJ3z3y7qDYrJWSNmL1zzAjPdbHtvO+u9yssevvuj0/RdjI4U0lAYbT/RsSWMG9M+ojRr/CpK3tcOGE+fJg6EAjOnJXKxkGhxdftM8Nr9ErlyQcei5iNoNbzC5yrytPOM3QvczwiIpbWiygI/+IouMM1gnY7f0OfUFHEyMMOl4hEc8rBKiijJSSbLnuTERLLHDkVlvoCz59D1VUuG+aCUaaRb3vF6ZKsEBAL7h5x4M7K+tBi0prtJy/PCxL70RgGWscummSF7gO8Rw0W0SmA4g8Q9SrEBOI3I/51KFTdxgp6CWQfO2S/L5tbhtDeye7CGqnO8oVeDuB2kD7k4yUkhgyeUFxc7DB/aU1lo8Bc3kClsmecWtwDbJ1pMrCwF7yXifBK6TuVY6iZ/46+HfLnZQ+fWcvvbPAtSbKVZ1YMVYMVipBbvIWf1slWOaHfXIi1YtZlkM+wJHX+a9zheP4HW2TBt4qoTSlm92dTLAAXPv1+2mQhDs+xu1hDVTllIBnXuyua/F4PZnE7NcJR4duIxsZNSYK2aBzx/HdoLL3sVsnuj2y0gKyUWzRi38i14FyZqbSHmLgnlmlrCFaQhywty95kJBmEsRdYmY2+hKTinMkUqqKiBJlyU/zhhThxnptE43NQ4AkPi9lW+gUueNQ0A8//HF+HnVjYy4Wx4/vPT2xlzsf3pOkmYVsbOTk/SipzTA/km0Kk+2BPvI5i3iuAUKuGPMyueF7ckdCe/zkTrAAWDkpP/hCagnSTJVrVNQYUsAdj4gCzAROIeYC7Z1VoFhzzzxqlPJrvPbQGqn/2A4RgDif+J1AcIHY9UFXUoqLW8/lEjfZvez9lOEAwvZZ9OL1kTFUHVDBFkH9B//aiRl6uUFAOFBd2xLfJa2mxJ0pEIyIDURk/Rxq9u+St8VedTFc19Fff07H5boiRsZe9NWK8aicIvcN7hMnAd1LRDyNGbJzZl8whXtl71uVGAUwP6MrHfTZdn6vmlXeB9SEmDkHULAASQW/j0wELpL4tHoIM1q+MpU6x/JB4e+H3oAZv081V9ADroMaweBurQtfa6wH+w/imenWNh+ipFZQe7R9UKsno9fhU2uBZG6gsOLmb2MMpuBMWJNqJMZAQ7jfsubtpyTeL44nkRT8cOxIIGwmjU9jt6CA/CrfKrgH5s5UYcfhIiLqJI+jLIVHn+ygbG0aLoUVoy55mtdW3aCkpdb1GIR8G9ahguwIDzvWKIy8GQpyKA9Rt2tpzMFm7gWK4cz3qrXHg==", "keyMaterialType":"ASYMMETRIC_PRIVATE" }, "status":"ENABLED", "keyId":357749026, "outputPrefixType":"TINK" }] }`, }, { tag: "RS512", jwkSet: `{ "keys":[{ "kty":"RSA", "n":"AKZtuHAGYy-1Mc78sdp1gOV3jMCJtO7NmhyLSproWcBnqSN1g9mB2EdB22-WLWhB_U_JlZRCdHT6CxPHSid0c9JJc-2CmiV9zU2sVTJUkCytOVS0hrcPEz5JK6a6VVy-Skc_1-I0D2YurXd0aRByDALC8heHMok6VQXW8qwHgRyc0Jr1RcbY-CF_SMlRXn88g4e3bnk1AJiPcmHsJOcwkanwlWxq46DxPv5ff0ruXN4gPDYU-6_J6yZJreYjwrl-LhkqzOkz6e-LE4sdI5WFJQR9cGGRMf4ktgF3kqFtcFNFkGtdOvw5MdLe0eaENDzZ8TZyQDgiHYl878x8uPPpmoeif5af_ZUAsrv_bV-h3RpSoTdTP4SlQMmP-3y2R2LxvUs_CiUahoVFwTt_bRHO0Qy-QwpTvAdJX8CzrK2auqycFawYm8xYjj_epTFSwBCJuZjamxpZSa29zTDqP4AXwt2-9LO-70j5muzDQL35czpBgaXSAEJkrM9du91OjkJ2vtYFVLjWougN5uVpEBx1Isk_KgreOgl3lF1vs2EjTuihaxJhM-17alJLmDL06ZEDsht2Uhu_ZExEfPwTKaR_-kfjlamuoLUvTtVhzNZuOHD_XAOrGafMjM9WVq_D5XjqF7WFnb_t4YIOQNmGeOeIFLb4LlR5nHB1HIHUpAWazrvl", "e":"AQAB", "use":"sig", "alg":"RS512", "key_ops":["verify"], "kid":"fVf-Qw" }] }`, privateKeyset: `{ "primaryKeyId":2102918723, "key":[{ "keyData":{ "typeUrl": "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PrivateKey", "value":"EosEEAMagQQApm24cAZjL7Uxzvyx2nWA5XeMwIm07s2aHItKmuhZwGepI3WD2YHYR0Hbb5YtaEH9T8mVlEJ0dPoLE8dKJ3Rz0klz7YKaJX3NTaxVMlSQLK05VLSGtw8TPkkrprpVXL5KRz/X4jQPZi6td3RpEHIMAsLyF4cyiTpVBdbyrAeBHJzQmvVFxtj4IX9IyVFefzyDh7dueTUAmI9yYewk5zCRqfCVbGrjoPE+/l9/Su5c3iA8NhT7r8nrJkmt5iPCuX4uGSrM6TPp74sTix0jlYUlBH1wYZEx/iS2AXeSoW1wU0WQa106/Dkx0t7R5oQ0PNnxNnJAOCIdiXzvzHy48+mah6J/lp/9lQCyu/9tX6HdGlKhN1M/hKVAyY/7fLZHYvG9Sz8KJRqGhUXBO39tEc7RDL5DClO8B0lfwLOsrZq6rJwVrBibzFiOP96lMVLAEIm5mNqbGllJrb3NMOo/gBfC3b70s77vSPma7MNAvflzOkGBpdIAQmSsz1273U6OQna+1gVUuNai6A3m5WkQHHUiyT8qCt46CXeUXW+zYSNO6KFrEmEz7XtqUkuYMvTpkQOyG3ZSG79kTER8/BMppH/6R+OVqa6gtS9O1WHM1m44cP9cA6sZp8yMz1ZWr8PleOoXtYWdv+3hgg5A2YZ454gUtvguVHmccHUcgdSkBZrOu+UiAwEAARqABE1h5sfvsF6WWTpstCVnTS9kjsVXQhFm96kd+upb7p9Pk40xLsULYox/SpBvu10mkalviWUOISfiuxPPLeN6ef/kt0pP12xnOfZLkrF8MC0Vvfpslda347KqQuma6eXddJv8S1yZ6C8StQU90zwaSwtdqULXUeAMh0vXza2/L4EmSLhEItV6PKUWkblJZC607FNGLs+cnVJSIFT3f5EfPBtQCaoHaR+EDE4qCP3GJtgBFP3wc7YgpH2A9KJ1Li0hRj3dcLldsf/3InckbU8wQS39RSuYXy5T02yLNFpqkDenuKazCqIL1ea+Q8py3fcNPuKZ7NIsyp8KwFTMCRMgIwD5dq6l0lsNZ7UMx2/5ex5LEGlTmNdQZCZivav2hQF8/zeEWzq4dH+hDrNWSwIyMF1t70mxChMAQ0RAzH6iteCQQFnLIFFqVTiXIo2FCwwlyg2uQ6ASJvnW4M6ftXw8ktpLlPeP9uDpN2idBW3kO8dLUfQbCjIIr4cQozQvYenVkMBAbXjqORFK0YRp7xtUNeV5i/y0Dd8tKTmVx8QwGaI48RLVZUC6xelFugbP7UKCkVTPw204JbQGj0Bc1o+KM+ekEWd6Z1oyQQEE/tx2pMsQwrC5FrOv6LtVCLTyQrfHmrENpFI3MRyHJsBFSO0UrDFu9CSCsLSvGjM4eAlI+1xhIoECAP9WTkzedYf0VvNI3oMuENt4nG1CLycY9ZoUmebVvaR6jcFFHr8AxT0JGt/ZdnSt5iDK+VC52Z4kjVfiyJaj9O8PKifKiGho9IpXbd57k0lhDVwEZ6jLJ55y3KJRBcXaTtqodO3KsP8Nix2mcInQvKT9y6ZY7w8PT9WOrJuXtClc3CvgK5LyFQLRQ8dsCWclcb2MWD7IKBam1yvdd5mtCylsF0mnSoLfYPFcPAZ/O0zKCQOtyCm1duEfuBlef0mGwYAJsvKvj4N8U10Yk5TNr4oZM4olP2WY4Jf4fucnKscMxwkkbSVOOjms/r8NEBUH6XUpGewUQyaV47LPcFsvw48qgQIAptxTtmGV5XcQqYJJ3bvPAjm03+wr0A32cr4Z0cnByBz/dfNFxacEm6cWKflsu4CB931hDiI0CLveTgElNR0TKdNG5tpM6/17WOowACANRhLjEMH+p5A7zpzAwJrWHEh5qrSpgPm08fJhrUfyWoRZ7kxXm7SoVHWlKvAw4QR1PNPYxcg3Tm1zgZ40/gYn3JSdnDf1KN25XRfxrHgSVbKl3XRL4+6TgzTyu7olONlYEXjpxuuX+UMyTX5oozyxNAC3UUHNXlRPMWhKLy5vbhLDsk5LFwM4j5PL0Edj6pdfuegclsZYqxwWXLdHWu98EKUdZaucFVFoHc77h9OgmSv/SzKAAjhOW+3vkJNuek4j342l9umu6y/czHEeu+pCaL3SnINM0z2vdFxCWzxeaaK7XbfVMU5B9ECs+yQ4g0LCK+GsPjMJcQ5dRz9fBa4MIZpSPeSMllmYTxOV2SLDyYuxukgrIABv7XkSnX1hCzB6p458jV0E6ofATNdRVRWO5Nla1svYQmUahgFdiOyaIQw08s3gH/jgngUaNlzoZcKyj9E/q5pyz5/aWEAL6mDPKh10qSsB0oMRK3anIZP7XqmZgRBBuyH1AZUqyccA/5Ej/kduJCub6xWnqRdKYxygG7v1kyVZ1/pYIgl7+rMFRxfyVX2NxRmk+qZowXYcz516yRgSrFk6gQIAlvfbabTrKTzLv4IZENwelHXfl4WXslsfsnsa4zt273aFD5O2efj961KGdB2u6gqADIrM6Du79nb70Hmqz15p+zqj+LRkSlQCaNUh7ssRF2h5Nq0+mR6fbfVXVCwDMn3ETtW8UuwacZmKFHx24rzCnR9HWKJgdmImuS2uG7ir1ggaJgBbQcM3cXvRmE+7exCfdTsPvhS15GuIhjHw7MaA2VeiXix6HIkoYP8vNDs5Oj26zfZUfvr0JTcMtzxvW4yWT5eIlyMSr7IbBIsv2Fhz5Px/ZefNIeJn0h71YMfqnUpLq4LzsITuGp7cmYL6Lhkl+toEkykfWXDvFNo9gLhU90KBAgDytWdZp7okr10lBmVx+V5mMkmYv7Pa6H2Xp+Ntgr5JxGac771oZs/46EQ4Kl7F6+OSDqyL0d0JVgOYOT3toNnEdYEe+Pv0xfl7PKG2OV2v7+Ud0Ko4PITt9tYUrBHI/LuDJl1D9MsEDwEToQIFhNjgfNlwHsvqWpOWUo1Km2h108cubdC8wv7pkMCJJagOb8XsfnYscT+FCQHOGv+PRIzKTxU1DtZe07i3ZTkvRyYh2e5PLvMRFBNM0RudybikzECPboeWd8EpKY2RUaesNZoXmpPeFh/LsRZQfgnOt9trxQGtKmVUT0b63Jt0sRe3ydYuYldp0PvO0CsClFihj4tv", "keyMaterialType":"ASYMMETRIC_PRIVATE" }, "status":"ENABLED", "keyId":2102918723, "outputPrefixType":"TINK" }] }`, }, { tag: "RS256_NO_KID", jwkSet: `{ "keys":[{ "kty":"RSA", "n":"AImrUP3PDttint7alBxKexY-Oe4nCj0TOZ06yuKgq7UQu-3Gc8KJyQHO5SzPlMBy6FjcWqOzz-kkNm9sej3AsdGhTJCcOCYDoLgArYCaMQoMLOOjMQJTVbHeiPpyVgHzvpG9Xw_IVNPbRJhsT4mzqHuyopUEEexVQcFo6F3U8zE1kppxzoMvIiz5-Zm6dFX8EozolMD2TLDh4NZFAb-6uJs8TYzS8Od6V0BVh1CfHL1CuIpvIirkgki2RGXNE1r57bhJfMZUWtqAUXb5SM2IFhLUcgGLV-PfxP2cxcJ7HHhk5-lFf5794CmqcFa4mliR2tJRnhUR2vmlgxqUjzwK3HE", "e":"AQAB", "use":"sig", "alg":"RS256", "key_ops":["verify"] }] }`, privateKeyset: `{ "primaryKeyId":234505441, "key":[{ "keyData":{ "typeUrl": "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PrivateKey", "value":"EosCEAEagQIAiatQ/c8O22Ke3tqUHEp7Fj457icKPRM5nTrK4qCrtRC77cZzwonJAc7lLM+UwHLoWNxao7PP6SQ2b2x6PcCx0aFMkJw4JgOguACtgJoxCgws46MxAlNVsd6I+nJWAfO+kb1fD8hU09tEmGxPibOoe7KilQQR7FVBwWjoXdTzMTWSmnHOgy8iLPn5mbp0VfwSjOiUwPZMsOHg1kUBv7q4mzxNjNLw53pXQFWHUJ8cvUK4im8iKuSCSLZEZc0TWvntuEl8xlRa2oBRdvlIzYgWEtRyAYtX49/E/ZzFwnsceGTn6UV/nv3gKapwVriaWJHa0lGeFRHa+aWDGpSPPArccSIDAQABGoACOgE5vcbpLpxt7d3Qu97R37xWMja2xKb+BnZIF5a04jRryjJsgdIGJEHlI61Osot3xEEL25+egU/ls6rUEoLHKVk55lA8BCBRLlXyxJWzBdW9cChJNP6hw7DMrCFShb4KVGOi0waIXz8qtsIj/RP6cCwC/qBZYOdHLlOiXC6mTNv0blQ2Cb9yfZZ1Lz855DH0l2/GMdZYXwb6JElM+u/vR7lxTp4Wc6kq/31PULDH7G+Ps+QpXxHMIqghgSWyRsJ9+SHv5yo7JxA58eTQEUXkI6RCJJQ3pSXjdveBzzPyN6ZCmjz91Np3oPh36dZtknW0UspZ6Jnpc5GLphkvG8GblSKBAQC/vcua6r6FGW0VO2yD93nWgX1qepmULYGw7lv+mfOvodPUr+8EqDZXaRzUqCHynhVfb1BDEsoxP9aLoPVFZoJbL1MqBnUx6X0FXoKu2FzqsEJYw2qnl4VLhFn7xebnR+vwv+MMYf+yvnIdcMfmrZhWmCS4hTFQlJDfxji2SPSdByqBAQC3znfJnB2xC7eDUCTSH49h/xW1YWaS6nTqXvk3LJeq4tX2WGBWxfCLh6xpNpzF31xCDdYlt+yGcy6UUBKr4TteePrWf6jY9TWJZO7FvAqIIIxaQv3a/0A4/sgzYcrr2ansWzhNtfCESxOaPFVfLE1wh/PpJBzbcltRbG/mEY3UxzKBAQCfvXhN5Pm6m1c0lCAwxVE88v5QYjlmqI7en4YG062gCbsX+0au45D6O7joNfaqUSdPLcZ5SsMmSp/sDbmpCuDZJNEtNtoWLgaZHYbUMa8fWp67onpNiz9ija4Fwnc/Ab1AAi0fGNnUyTL68gWoWcGLiw80pspR7qPPui1vN9KKqzqAASl2qg8Q6KHHwt4cdjHwbKfuozcHgdwih71XL2EC7jPed+XaieEJRfoz4PDbIQKCII3GEUjw9Kpf0WIjrhKX/IyTPgKlSbGnnywfWL3CbZ3HueGiuyFr81DoKMFujhgmQe7PpSPipx8w0Hs6oQeXNuDryloNi3T1lyQHEjcUPqqBQoABcIm6r6QyTlBactKBKEqyhkXF1tCvw7YR9herJoubM/xklWzU5J8bgSQ1h4dutlANutXFqeOInUufyPChP3inQhcirp3CccJFaMP9uevRMMhUxyOyQkpOfxnAe7hvCjRsDDZZqh5bi5siNzeIEnU1s7sq/0XvzZA7G5fGZgb+dZs=", "keyMaterialType":"ASYMMETRIC_PRIVATE" }, "status":"ENABLED", "keyId":234505441, "outputPrefixType":"RAW" }] }`, }, { tag: "PS256", jwkSet: `{ "keys":[{ "kty":"RSA", "n":"0JqDlgy_KaDpCWhaB95cKdLsyBGCbh865tHHK3LM1Iv5qlt4eqO9n2Bn5R5_ZHrMEGvVoBmwpkfnWmaMxqZg-69k8id0dN4PKeBuIYeO5C2IE3D0uO1UWzsPi4XHtXf3CYmwYOUHJ5DT8q_jgMXYCefys4OvYkRcfSpWVvFtF1PzBSijQaxDQUx0rdJvi0JZTQOXHl4MwgzrFoERTdZswAXh21MK1Uav68Aa_Z8TZU3R_qY-TX78qhBCv8T_1wrooprF_xaJqpywXktUnQxVgu-aG6-yooqrICvobc_LHdF_8R-Qp2pYfsHSmPDSKu-5JqyyIIoxfXpLdUsrDl4HDw", "e":"AQAB", "use":"sig", "alg":"PS256", "key_ops":["verify"], "kid":"a4D_hA" }] }`, privateKeyset: `{ "primaryKeyId": 1803616132, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPrivateKey", "value": "QoABPzsxHq7K5f91YucwaXUDk7ERgE8pqLSc8w34gEnc/wo5vk0BamvQaWRVQQdzEfK+eqVbrHmWi5mhY9QXpOv0dhuhyvo8ZS0ya60cT6DYSu2LBLDHFa68Wp6SWbIwFN4X5uGC8DYvWpJU9PCYg6XUu67T37FhGFekGHTSXDLf9Ko6gAFm7TJOM/v8MbHkCpY5NTtda7fb09XBXFDSC2XFGKvOkfQrGEKdEAvOCffpTBHsyvZAEJag/p2OZ+4W2D3upPNFkrmtS9MSGU39o0kn2fd6Cw90w5S1gjfxgWDbZpzs4AvbpU436Zy2wZYjJSIG6xbjDuYwizrflPX/sq5GUpuCuTKAAW+ovScT/DR/doxZm+xykUTTfEr2W4pd5PpLQiI1gUA2UTnY6p0svW+IbbSaj6vTE8s6+STsTGYAteUgdFBo7Ao501XbAJpJQX4ONI6o66BUvvzy0S6VLs+YQ6MWpArvNnnzRo5NbznO6IESyumWNm+8HQMaJ12sAqpWOoH4bz1xKoAB02eSVf5ZSDiYa4uF85NvvAVvEVPOPAd2gOqXzOWH+AXtTHJ8n/gcvUMnFR3W7cdZdyY2HslV0qphvkL7mCwsoOUBH5dA+F10Ebmk4hU9XEkeQvgFVgffzyqKjG521WOnAXQXudhOkJgXqGoTB/fESyRvSqA7ZKwPL1dvZnpJRv8igAH8m64q3qJFFcHWsnUb3hS58BXm8aTuk8Reju8XDXjBa9DPy5UySS0P/Chyh8HF5PAIwWSXTYDtFvdve3UN28oxTzhZ1xsz86BOeF2lFHpZ1y8/uNzwLRTIYWCXhbAS+bGpQOUR4JJDjSyivJCBqrkMCDUWAXQSqIZzHnyD+wbP8RqAAkukY+fCuoTpXOd06ASnbIsb+ZF4y++LsoulcQ//wmemVEOihJcQDgAfcL0j6HTylFG2EJJMDoLVWv6sZgrYpR1O1g97IB8KsLvyLm1JHxb9rbTDBnKSWL72NSZWPfs/Q5y5SXRxSD1gJoL/pcL5uuOosJjIvQ2olVMryYAgbnsA5UHZP7N8YpX0njZxBl9/PFNrTkWBMr15+A0VqOGh0TGnE/D4iAAduMJn1f4a3ZYVC4FgxKVxLxkB3oOLZz+QXKvs61slwRjotY3BXoKeImedOFmZoOJCA9qD+9rT01mQ113Fi9ylkBD1VGqtvIoB1CZa4tZZkRyoAeIMU7vMUpESigIiAwEAARqAAtCag5YMvymg6QloWgfeXCnS7MgRgm4fOubRxytyzNSL+apbeHqjvZ9gZ+Uef2R6zBBr1aAZsKZH51pmjMamYPuvZPIndHTeDyngbiGHjuQtiBNw9LjtVFs7D4uFx7V39wmJsGDlByeQ0/Kv44DF2Ann8rODr2JEXH0qVlbxbRdT8wUoo0GsQ0FMdK3Sb4tCWU0Dlx5eDMIM6xaBEU3WbMAF4dtTCtVGr+vAGv2fE2VN0f6mPk1+/KoQQr/E/9cK6KKaxf8WiaqcsF5LVJ0MVYLvmhuvsqKKqyAr6G3Pyx3Rf/EfkKdqWH7B0pjw0irvuSassiCKMX16S3VLKw5eBw8QAQ==", "keyMaterialType": "ASYMMETRIC_PRIVATE" }, "status": "ENABLED", "keyId": 1803616132, "outputPrefixType": "TINK" } ] }`, }, { tag: "PS384", jwkSet: `{ "keys":[{ "kty":"RSA", "n":"rMnTRrTk3zWf0ZqukmshN9GH9UsCcD0a2WlmO-0q7x_k31JIe2wtqhlQRwszfuOJmL5M4cpsvkDBT8th5yDqzzHMJRAs61Jq6ACNepj3_0hK8GszxiyxFQL3msxmu8e3F14M-V35n9aLr0meRHk9tzm968-wvp7I_IXlv1hbzHejh_gD14gy-GjdiJYGwg1oWINL6YzSv5DISxIAv9HLu5fmBLtoVyvU9iZLHfUJdq3Rlj5iCBUEFMJVb68PfWiB_xoA7nj3vpgAfGjDzQ62bVrVaOHOg2I4X2OxJBWJ8uFw6RRocpAfD_lEZBet-w6FaMHXh_iVwxPWNuNTbVHlerfdUHTMHO2jCR1JKKkI5px7aVM7fQUVtYSBk754LINhShkMCO9o--k7sZOFL_VohaCHtE9fRxIM5MYOKPyvPTf38EyCrAqreFd4ol0FCPea8n89BwV371GrXgP5C_9BdoG2uY6rxRwTzMNiLxzxWpkvlprNRxAsdRSZPEzKOI_t", "e":"AQAB", "use":"sig", "alg":"PS384", "key_ops":["verify"], "kid":"LFa3bw" }] }`, privateKeyset: `{ "primaryKeyId": 743880559, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPrivateKey", "value": "QsABGgBRiQlPP7T0l7qjag22t5qPSbLa/PkaEnEatcxTqtJ18qo9ncTqNa7Ts851twenilUdELx+HLARFmRtmYcJuanBNMIrJ4ua/I0+rWY2rU/NwxB39x3SglT2T/wvwOx0fZAhXPNqgF6m2aGLMsppgDN6TKrvWZdC8YTC1e+ZoDlq4miBuU+NEOOsrS6Zv0SW/ZI5OxUqvGqQwaaiiy0VCsIzpJjO8GkaPntCYnA6Z1MNZTREOUcncMg2MsPEmYslOsABxBOOesQfs2aiCmt50XjN9bUvTlu/Z9z6/k327kwLpWloxZuzZWz1LMpbchnmrNvl8uj+N8qSvaIk6/Gq2y6w5TtDEdELZuuNcCkUqnnOaUJyVqkZ10PwILL0Ig+tt4GSIGlEFmdt1cL9tdU8Za/IQTkYzDQG11iG6h6llYPmj4aJxeDc/wnon5dT1pMuW93uFygwXpSkYMIvzDBQys6sUGtRbPVjNRsndRVl9w8oiF5wvEeLMtAMpAUgFxmXdC5JMsABHN4zpQrc8qsuYZa57/5gCmi4qGhECQNdsJlu7YjqjScBcRQZEK5F4pUZl2lY4zGQlClRnXUgx/g6F9FGW/ENnHebfYQ63eg2wL/EqvWBujDdYjYvs1oUBXcMFSG66VAkOYkkS8a8JnQpOfEPCkvo4/Hmz32YXjExEZWe450v8KhE4JYsaEolyoH/EoDAfG++NoIfUR6A+slyXqeQlnWK8+GMitoLKaN6EMdc31YeVsioEhn/rFfzd7p5FlLbjqBJKsABzisQA/QhytqNUWQhnhYFSs9QF+Z10ZCuUxwaSZKmD8SV4JTiHcMy7LK7RGt3Btlf76HmTNVOtTTsjXbBftVv4HDNamPmtzg1ggZi05cjPYi3STFZu3lUVAv2tJP5gdjuMe7slW+MqECUfPyz7OkJRBVAPQl0fbH/FSeSb529H6R+/1uXQ9nmXmikUFEt5PvY77li7Qyb6p67B1krBQusW0Lk2SL1Fs8Y8bj/lkjJar86sxGIGl2JNfSwajyK/waJIsAB1o1XIXWE82dw1r/TmkhY+bF4vvApYMYSz7lhsK5shZcY6VeQMXNUY/SCMTTndHzUNmbwdi4NCbnNt/vEOvmZnvQ2Q3YNphd6BLfeZxEmBcPzUMDTKXNaZBLbe8j1HUtaOHoaCfVuLhxxDT8knntNZNIJNuGhAK8YweR96qKQSDyL1zZRXBqnPZlGNnVCDVx0ijMmAmAY43IC5/XCR5h03TwbiJTQ5tG3FImoSXqA7RmwTSr1ynR4EKmRWt34uiVFGoADF4o9gu4FGlXDarpwmxkGQwUESUpJUEI65LDD0Vk71q0ZMMWUg2AXDov5UFx5zQkxx0Hx1ncN/pNy4qyaL3NgGg82OTxtajflwarFm5S4gKp4Ly3jtVWEYJDxa8D6JA4O5xuUl+qSJhEEIcLdUYXU/x/aPISklyupxSF2ze07QG1yNYV3/IadLxOWTtPlos1R0HE+x9g8JAYVC4kt2fQ6ldmZaD6h9fJORqSr6i5mdikzGw1vrJs0XaGmIxuN+C9jAS031tkD15BgK9vd6wrlT9d5C/KDJT7zJShYnNTJ2E9vRXBby7AaiOGjeRx/E67oPzdWH/8qwsLNfkS4eYLT9nbwmIMQ7pWVxcatnWKzuQuYLpCR/O2iJlaSoO76Xuy8RklES38lB2+FNzHuHtN2xAPms74WAUX+dLrIlcA7ceWwUqeF8iyXL9vmCuMmd5kHZGxUJbzVpLOkRUdcDNtc1qXm8qufzWABOUtzVnkn1CuejH/Xv9IpbuCHhQEv8o4REooDIgMBAAEagAOsydNGtOTfNZ/Rmq6SayE30Yf1SwJwPRrZaWY77SrvH+TfUkh7bC2qGVBHCzN+44mYvkzhymy+QMFPy2HnIOrPMcwlECzrUmroAI16mPf/SErwazPGLLEVAveazGa7x7cXXgz5Xfmf1ouvSZ5EeT23Ob3rz7C+nsj8heW/WFvMd6OH+APXiDL4aN2IlgbCDWhYg0vpjNK/kMhLEgC/0cu7l+YEu2hXK9T2Jksd9Ql2rdGWPmIIFQQUwlVvrw99aIH/GgDuePe+mAB8aMPNDrZtWtVo4c6DYjhfY7EkFYny4XDpFGhykB8P+URkF637DoVowdeH+JXDE9Y241NtUeV6t91QdMwc7aMJHUkoqQjmnHtpUzt9BRW1hIGTvngsg2FKGQwI72j76Tuxk4Uv9WiFoIe0T19HEgzkxg4o/K89N/fwTIKsCqt4V3iiXQUI95ryfz0HBXfvUateA/kL/0F2gba5jqvFHBPMw2IvHPFamS+Wms1HECx1FJk8TMo4j+0QAg==", "keyMaterialType": "ASYMMETRIC_PRIVATE" }, "status": "ENABLED", "keyId": 743880559, "outputPrefixType": "TINK" } ] }`, }, { tag: "PS512", jwkSet: `{ "keys":[{ "kty":"RSA", "n":"ubM3lgyGn8IyKO-56q18hvuJkkxPrDXgalRWNmnA3QEseglU_9tp598dlq04eF1G4Xkrmk9OVyVSCuRdvMoko6wP4Jum-3cn42_Gsk8PdTwm3WD-yEBg_Usa_omLGiTfktyqqoZhh1TeOOBtNpD1U_p1wQxP3-bLl4__uR75CqlK9FYdBrIuqLP3nqa3_OAFuPBX77BuD1kcr5pUxPZkXBNAWpnvsW56swyIMZF2GRhfv2n2bZJgT4iybQcmEnvt1wfY3ecO5ZMSX2QNKpnRRejlIEqR9uAQa4wIJMViL8jDbAV-ZvUjMM1G0aAyMHPQzb2Hfkr9OtEi-_xyUCwqF2IUZfUb0-mCjOutpbBlSfkYULOrwd9RQTaLeNe3GhRjYWTJ-gLDS8DUWz8AcpCI7xoQSfuZLmBwxslqsObMYolxQJXej1IDmGX-Rjr4ro80EpMkv67gxYQwjP8p7FMHfK7FSDZMtT-h4mO7AD68vwHd99c9ALDJfPO7tAMG53opzD7YEZU-ySKRcMBIFRe5Kxj-m1fbN9q2ictzoQOvKh8TBlCsPLRbF5WVheUtE9anKiIik5zQInihoZidH5YJksdipMVWLeRs1Qk5J8ddv7n2dlbW7zoC60sh3ubLQ_MDm-eHlXoeKGioCMjDABRdokqal4wugvQUZyQcBBtfWT0", "e":"AQAB", "use":"sig", "alg":"PS512", "key_ops":["verify"], "kid":"L-LcIw" }] }`, privateKeyset: `{ "primaryKeyId": 803396643, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPrivateKey", "value": "QoACUsRKIPRhEtXtTxcFVM0/KMBMyzrafB6NNwb8cHSM0N9XGZEbeUh6EF5JGsbI0PndFyMk2wdhkCdtpdH7Bc/n7hLlW7yVR9fvPQMDoG6mITa0E2XXDkW/iJZ1cZhkiR4ptWMgNKm2xLlxOUTGcVr8+jKQ0Tb1TMsvojs3GeBLJ5jDtzq3HE6kcNY611L/hzft1aOb3+zJGRZpLcN3CuXVbhluTyrccl4V3jWN1KSejvj32zn5l0hRMYES9Ek2h686a+gqK4RYkbeP4QL7ZnT2tkG0rxfi5HlklmLn620YTzrlYpGd9x3ID7NnMjDfTz0mR/910p6JzVBloCbJ6Ai/JTqAApRrAvbP7oGaPN25FupqEWCrTZfpmOZuH2NT4h6KiB6/RxyrbRQWSh6bpRXsS/C8aHlnSj83nFT+G1j7qLINDbqHlrYD8aycRRuiLm5WWNtO6wQzpXmWmrSYutln9Yj6QWtIOIA0Pn4b1u1Aj7DudBpKhd8feihkZa9AHqmsolOi9FKILQ2FwAfmEGDXHtRjP6KrB6bMbg1XuLXrJT6xEBLyfSswsk/UnlHG3+q++jDp5tLPJnmqDgPcZ017PY71JoHE8QyNu2d4+Ng8+wOZxyYWPOvfgC12ZFaGso8do3+vG8C+HEIiHM9+brv4SyWaVZxFt3jn/aezXDlXbIsG4nMygAIJ7xT/Qz6vOVZSAvqRSVMXS20Awi1TnsgxHbUzImi6KMBRrlyFud0ltpQcZw98jlo5qB11d34HFnXTK1TOvNiB61Z2olr2+4Nt2MFPRu26r3uR3mhpacHW+TfkHw5whudHpybXkFc2asiL8auAToS2i2pr1hSOqKUDI0B6qy+qjDjWUCDziJE+IcpWjTEY74UpE5rREBIer5Xci8FPCP4FFjfomAtZZSGgS3DHwnCh9NfqyLZTGdDVJe+MEMlAFFmFUcCAk708H16bqJ8UuJMdGoFqvxU9bJrLGDkAg/CttX0BI6OCs5DR4Rqy+XKHYIkIvy6DVFja3mmhIhAVXXQHKoACvAckkJ1ayoNwbcV11yOBd0qNmPl0+NWdGlkc7+Aft6rLAR25t2tpfEjsFFYEaNCQIlzJNLAXa41Ac7cGdOLx+nRAJI3d/ExRLXhJrbAD95YM6WSM8cXf0dsR+q3hoTE0522T1XwSXICXb1Z2hzfmghL5WigezMdsEolqF/pRpQUcnZug/mpa0P40evFEIsoiPpMJYwS67iETxKeeEJv55z1W5GkT5reEeRwkQIuJm3kZB2r95p2sU82PFyXMVjgnqcqUAKWudi+oRp3jhzd0IUMQg6gcm62kpF7XgQmobMPYloc2c5VIEM1NS52s4arADR7dFxU6R28paLea8LsCByKAAvzUpants7GpQz2rJ7Gl9x0uQjr48yetqeTyzxInjezcKGgO7s85c2GzO3MkeaYcT+68NXHtdUVXrXJYerAiH+PAA2CdouEg8ra/ZOl0t3x9402kkFYcwbzmI1O0TLV4kv6NONapFj7U2WYfj0IdVILYoJWS4PSvvMWrDzP2SlZ7alSZ0zqCUGYa47Mz9d9A7d2teQ6z3UdzrUw3EBWz83szslYXQg6QDtsF+PYUhNx0tBuAdUtF4kVFXPSZoaOzaKdYwxb9TApmRheVsmOVAqb7xtwo9WmqUuJgDADjlfxwA9cam+uggvogd7Ta3i48SbJG6RXboaydht1F0AYeKZsagAQVZNwC5x8yE/nFakDyvtlO5SHR/1qvzhE0ZCepOIEmCmGTubQs5JwMllGJWhwxucVVv/5Rq9CsYjn+fpV8uj6DC2qqMiSIag+SuKjymACBktQuGGOiByYQExwMC8/ry326ehPAy588K9SM8ZuDeCswvp/cWs0aUDOlGsuXtJrKgKXdr8zDnbmZvrTIzA+nDC7R7Kv6NaBTF613XwIPIw0oPSDij0OPHy72+9BLraTRJVQP8GbvSWLb0YraMW2lyYNQN7Djd8rpO2AYKfsJAmmax/HFyPGMuKm2SjlnSxo8bmvH69DGjyK7wkU7bLJQ5Lbp98DpauhGY3EdXispU2fnJkoa9DaDmEzArRGa+T05YCyuzezuYE4eBUlxXJj2QY5ABDH5VkxcnWPSftKUUG5TSRwnIKZQ2Ab2ONNOQDafSOsg2KYDBKmLw4ZxUp2I2izXPeICfCJ2sBW2IOwSK5tRcvno8QoMvkz+9Ci8QNRpNLYTiCgbxXaoW/eLayvKt3qhkj+rKMded7yzWjq2dNv3HfvPUIwtSlAHGSqEhGkuzSijHhp2s2LN5OB6mfQt6d4pzvlh5w+pxaK3sH/wsLoVsdvUg4OBaH+KBFVYRZ9eAQMU8a6fmoFreMpSiNS6B0jY7XPsCL3mgSAuzkojCx2YBh79VB9SjcKrGGdRYLot/RKKBCIDAQABGoAEubM3lgyGn8IyKO+56q18hvuJkkxPrDXgalRWNmnA3QEseglU/9tp598dlq04eF1G4Xkrmk9OVyVSCuRdvMoko6wP4Jum+3cn42/Gsk8PdTwm3WD+yEBg/Usa/omLGiTfktyqqoZhh1TeOOBtNpD1U/p1wQxP3+bLl4//uR75CqlK9FYdBrIuqLP3nqa3/OAFuPBX77BuD1kcr5pUxPZkXBNAWpnvsW56swyIMZF2GRhfv2n2bZJgT4iybQcmEnvt1wfY3ecO5ZMSX2QNKpnRRejlIEqR9uAQa4wIJMViL8jDbAV+ZvUjMM1G0aAyMHPQzb2Hfkr9OtEi+/xyUCwqF2IUZfUb0+mCjOutpbBlSfkYULOrwd9RQTaLeNe3GhRjYWTJ+gLDS8DUWz8AcpCI7xoQSfuZLmBwxslqsObMYolxQJXej1IDmGX+Rjr4ro80EpMkv67gxYQwjP8p7FMHfK7FSDZMtT+h4mO7AD68vwHd99c9ALDJfPO7tAMG53opzD7YEZU+ySKRcMBIFRe5Kxj+m1fbN9q2ictzoQOvKh8TBlCsPLRbF5WVheUtE9anKiIik5zQInihoZidH5YJksdipMVWLeRs1Qk5J8ddv7n2dlbW7zoC60sh3ubLQ/MDm+eHlXoeKGioCMjDABRdokqal4wugvQUZyQcBBtfWT0QAw==", "keyMaterialType": "ASYMMETRIC_PRIVATE" }, "status": "ENABLED", "keyId": 803396643, "outputPrefixType": "TINK" } ] }`, }, { tag: "PS256_NO_KID", jwkSet: `{ "keys":[{ "kty":"RSA", "n":"rzu_DRFtzFpMUy-tXC98YxtyASy-3hVtM1X9KiwAoahSfd7VfzIlIXcbn3VewkZBtKGC98sGQJSQWA-EagOjMDua4rAGVCZ9Cj011Mxy1e2j6w7qRCudtWaMormfMpP6n2ht61HkZkQDZIlbdRvr20Glf2KWgd8KgSoEZKS7AjIHvoGbJCU7A7ajbONyKuicrYq1XYs4b1dYSqQ4VIZaei5NQM7_tddYJl-lSKN3mLEPhdWKHWf1rVfDbJNobAbqN7C70rUKJS3DZkwo-q3-QOoZleJXKTXurdRAhT66nfa-1f7idmIO37LwReX8zrgDWmMZPZ2mpfA86dIlkkk89Q", "e":"AQAB", "use":"sig", "alg":"PS256", "key_ops":["verify"] }] }`, privateKeyset: `{ "primaryKeyId": 1629784556, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPrivateKey", "value": "QoABP9TTJpZ3lfj28Zh9hqHMNydjyJGup+Q8xjYubqsE+E3AlnSIvRDp9r0VVHZzsHBEdKtQQgCW4FT0I7Cy4z4W3ecKskuJWFYYn0PYOXLZoFo2MF3yZ0wI04aWhRS2+Zwl3BSr1eu84jiCm9rTsODyZ0MQORvpeBVaX9Y2IOPclvQ6gAGBpXDhI/1yKJq6vlymUBwKS2FG9Tf3as3YkH2B0b7wtv1Ir+WEa78ub52BwxnOKsf3V57WLnuQppLiw/bvHFxKVDNuWGiGTzEVhJW2qK3RgryXtqzkACm6cjL1FT22B9VmVx/GqWOOOLX4He1pq+UYkboWgXVkAdP0OaPv2hWIMTKAASnEMbcFq+ZbOJIJBwZXsSmrdSnfg8A2kwuatK2U2Of7/YCE5i11CUjWUvi99plk8g/mAinYu0Gfw6YSRgbWsAvK4GsIJ4322WT1yy4g6XuncL8MKC2rCYIkhFWpI1qcsS/PxU3zWMYodV6GjK31HXvqczlJfBYNEBo9HxeYDtchKoAB0vRt2QsYTMSVYw1gIDeKdHnhMDaakaIazjc4o+DCQSk+dU0EStSn8GHON0nIrEA8A5UHqF8/yh1mW+M0mkSaSiBp+7CLAowEu72wgdrymK/e6eIELH+joEDDgWpcF/WMEWSvls2a0q1atiYvC2ERLuSxSFjoJ8IRKVfVmjPi53EigAHUpqb3E/I863RAT2ocS5CnT7A8PBgttZqIyR1H8iC2bocre8H+8z8fVf4SeYsLhqvuBcTPXxZSUT+ZVf+LeELfmcd54savTU/yTQJ27s8WIkuLeTj+80FWCVtengLwP+Bte7nyzqbuXSWHUTUSVTCMK5PiBdWrOElVYlp3JxvTxRqAAgNrTEVGQYjy+xnFbKHHmGr7olwVAi1lqCGQDDZKMQH2fZOQqURH13MhdpPEL8LlKYuLejl5B+hzLaTWOqxx4TmD9Df3nMwAC0ELpDUAfz4e2quvuRD28+cR9u0G560ON53sJPbqPGVlbtaDmpn8nzvCOmczpoGmtzcBeZ/4GeEHThzq1sRE+tBJ6B4oS8R4LUtldg+FBUnZgqJvSC1gYYHO7oySCPC5V0R3EhpWDcVbYf7PyMC7oaxIPmCAu5Wc4DFirh13BAZI2FKW+Np/heZAjYUKa4Gtb0dMxvLwz3OcPPa/AQKSjko6aMRAQvjgd/UgQ+Sr496td45I4JGandESigIiAwEAARqAAq87vw0RbcxaTFMvrVwvfGMbcgEsvt4VbTNV/SosAKGoUn3e1X8yJSF3G591XsJGQbShgvfLBkCUkFgPhGoDozA7muKwBlQmfQo9NdTMctXto+sO6kQrnbVmjKK5nzKT+p9obetR5GZEA2SJW3Ub69tBpX9iloHfCoEqBGSkuwIyB76BmyQlOwO2o2zjcironK2KtV2LOG9XWEqkOFSGWnouTUDO/7XXWCZfpUijd5ixD4XVih1n9a1Xw2yTaGwG6jewu9K1CiUtw2ZMKPqt/kDqGZXiVyk17q3UQIU+up32vtX+4nZiDt+y8EXl/M64A1pjGT2dpqXwPOnSJZJJPPUQAQ==", "keyMaterialType": "ASYMMETRIC_PRIVATE" }, "status": "ENABLED", "keyId": 1629784556, "outputPrefixType": "RAW" } ] }`, }, } func TestToPublicKeysetHandle(t *testing.T) { for _, tc := range jwkSetTestCases { t.Run(tc.tag, func(t *testing.T) { ks, err := jwt.JWKSetToPublicKeysetHandle([]byte(tc.jwkSet)) if err != nil { t.Fatalf("jwt.JWKSetToPublicKeysetHandle() err = %v, want nil", err) } jwkSet, err := jwt.JWKSetFromPublicKeysetHandle(ks) if err != nil { t.Fatalf("jwt.JWKSetFromPublicKeysetHandle() err = %v, want nil", err) } want := &spb.Struct{} if err := want.UnmarshalJSON([]byte(tc.jwkSet)); err != nil { t.Fatalf("want.UnmarshalJSON() err = %v, want nil", err) } got := &spb.Struct{} if err := got.UnmarshalJSON(jwkSet); err != nil { t.Fatalf("got.UnmarshalJSON() err = %v, want nil", err) } if !cmp.Equal(want, got, protocmp.Transform()) { t.Errorf("mismatch in jwk sets: diff (-want,+got): %v", cmp.Diff(want, got, protocmp.Transform())) } }) } } func createKeysetHandle(key string) (*keyset.Handle, error) { ks, err := keyset.NewJSONReader(bytes.NewReader([]byte(key))).Read() if err != nil { return nil, fmt.Errorf("keyset.NewJSONReader().Read() err = %v, want nil", err) } return testkeyset.NewHandle(ks) } func TestJWKSetToPublicKeysetHandleVerifyValidJWT(t *testing.T) { rawJWT, err := jwt.NewRawJWT(&jwt.RawJWTOptions{WithoutExpiration: true}) if err != nil { t.Fatalf("jwt.NewRawJWT() err = %v, want nil", err) } validator, err := jwt.NewValidator(&jwt.ValidatorOpts{AllowMissingExpiration: true}) if err != nil { t.Fatalf("jwt.NewValidator() err = %v, want nil", err) } for _, tc := range jwkSetTestCases { t.Run(tc.tag, func(t *testing.T) { privateHandle, err := createKeysetHandle(tc.privateKeyset) if err != nil { t.Fatalf("createKeysetHandle() err = %v, want nil", err) } signer, err := jwt.NewSigner(privateHandle) if err != nil { t.Fatalf("jwt.NewSigner() err = %v, want nil", err) } compact, err := signer.SignAndEncode(rawJWT) if err != nil { t.Fatalf("signer.SignAndEncode() err = %v, want nil", err) } pubHandle, err := jwt.JWKSetToPublicKeysetHandle([]byte(tc.jwkSet)) if err != nil { t.Fatalf("jwt.JWKSetToPublicKeysetHandle() err = %v, want nil", err) } verifier, err := jwt.NewVerifier(pubHandle) if err != nil { t.Fatalf("jwt.NewVerifier() err = %v, want nil", err) } if _, err := verifier.VerifyAndDecode(compact, validator); err != nil { t.Errorf("verifier.VerifyAndDecode() err = %v, want nil", err) } }) } } func TestJWKSetToPublicKeysetHandleInvalidJSONFails(t *testing.T) { if _, err := jwt.JWKSetToPublicKeysetHandle([]byte(`({[}])`)); err == nil { t.Errorf("jwt.JWKSetToPublicKeysetHandle() err = nil, want error") } } func TestJWKSetToPublicKeysetPrimitivePS256SmallModulusFails(t *testing.T) { jwk := `{"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "use":"sig", "alg":"PS256", "key_ops":["verify"], "kid":"DfpE4Q" }] }` // Keys in the keyset are validated when the primitive is generated. // JWKSetToPublicKeysetHandle doesn't fail, but NewVerifier will fail. pubHandle, err := jwt.JWKSetToPublicKeysetHandle([]byte(jwk)) if err != nil { t.Fatalf("jwt.JWKSetToPublicKeysetHandle() err = %v, want nil", err) } if _, err := jwt.NewVerifier(pubHandle); err == nil { t.Errorf("jwt.NewVerifier() err = nil, want error") } } func TestJWKSetToPublicKeysetPS256CorrectlySetsKID(t *testing.T) { jwkSet := `{"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "use":"sig", "alg":"PS256", "key_ops":["verify"], "kid":"DfpE4Q" }]}` kh, err := jwt.JWKSetToPublicKeysetHandle([]byte(jwkSet)) if err != nil { t.Fatalf("JWKSetToPublicKeysetHandle() err = %v, want nil", err) } ks := testkeyset.KeysetMaterial(kh) key := ks.GetKey()[0] if key.GetOutputPrefixType() != tinkpb.OutputPrefixType_RAW { t.Errorf("key.GetOutputPrefixType() got %q, want %q", key.GetOutputPrefixType(), tinkpb.OutputPrefixType_RAW) } if key.GetKeyData() == nil { t.Fatalf("GetKeyData() got nil, want *tinkpb.KeyData") } pubKey := &jrpsspb.JwtRsaSsaPssPublicKey{} if err := proto.Unmarshal(key.GetKeyData().GetValue(), pubKey); err != nil { t.Fatalf("proto.Unmarshal() err = %v, want nil", err) } if pubKey.GetCustomKid().GetValue() != "DfpE4Q" { t.Errorf("pubKey.GetCustomKid().GetValue() = %q, want %q", pubKey.GetCustomKid().GetValue(), "DfpE4Q") } } func TestJWKSetToPublicKeysetPS256WithoutOptionalFieldsSucceeds(t *testing.T) { jwkSet := `{"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "alg":"PS256" }]}` if _, err := jwt.JWKSetToPublicKeysetHandle([]byte(jwkSet)); err != nil { t.Fatalf("jwt.JWKSetToPublicKeysetHandle() err = %v, want nil", err) } } func TestJWKSetToPublicKeysetInvalidPS256JWKSet(t *testing.T) { for _, tc := range []jwkSetTestCase{ { tag: "PS256 without kty", jwkSet: `{"keys":[ {"n":"AQAB", "e":"AQAB", "use":"sig", "alg":"PS256", "key_ops":["verify"], "kid":"DfpE4Q" }] }`, }, { tag: "PS256 without alg", jwkSet: `{"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "use":"sig", "key_ops":["verify"], "kid":"DfpE4Q" }] }`, }, { tag: "PS256 invalid kty", jwkSet: `{"keys":[ {"kty":"EC", "n":"AQAB", "e":"AQAB", "use":"sig", "alg":"PS256", "key_ops":["verify"], "kid":"DfpE4Q" }] }`, }, { tag: "PS256 invalid key ops", jwkSet: `{"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "use":"sig", "alg":"PS256", "key_ops":["verify "], "kid":"DfpE4Q" }] }`, }, { tag: "PS invalid alg", jwkSet: `{"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "use":"sig", "alg":"PS257", "key_ops":["verify"], "kid":"DfpE4Q" }] }`, }, { tag: "PS256 invalid key ops type", jwkSet: `{"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "use":"sig", "alg":"PS256", "key_ops":"verify", "kid":"DfpE4Q" }] }`, }, { tag: "PS256 invalid use", jwkSet: `{"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "use":"zag", "alg":"PS256", "key_ops":["verify"], "kid":"DfpE4Q" }] } `, }, { tag: "PS256 without modulus", jwkSet: `{"keys":[ {"kty":"RSA", "e":"AQAB", "use":"sig", "alg":"PS256", "key_ops":["verify"], "kid":"DfpE4Q" }] }`, }, { tag: "PSS256 without exponent", jwkSet: `{"keys":[ {"kty":"RSA", "n":"AQAB", "use":"sig", "alg":"PS256", "key_ops":["verify"], "kid":"DfpE4Q" }] }`, }, } { t.Run(tc.tag, func(t *testing.T) { if _, err := jwt.JWKSetToPublicKeysetHandle([]byte(tc.jwkSet)); err == nil { t.Fatalf("jwt.JWKSetToPublicKeysetHandle() err = nil, want error") } }) } } func TestJWKSetToPublicKeysetPrimitiveRS256SmallModulusFails(t *testing.T) { jwk := `{"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "use":"sig", "alg":"RS256", "key_ops":["verify"], "kid":"DfpE4Q" }] }` // Keys in the keyset are validated when the primitive is generated. // JWKSetToPublicKeysetHandle but NewVerifier will fail. pubHandle, err := jwt.JWKSetToPublicKeysetHandle([]byte(jwk)) if err != nil { t.Fatalf("jwt.JWKSetToPublicKeysetHandle() err = %v, want nil", err) } if _, err := jwt.NewVerifier(pubHandle); err == nil { t.Errorf("jwt.NewVerifier() err = nil, want error") } } func TestJWKSetToPublicKeysetRS256CorrectlySetsKID(t *testing.T) { jwkSet := `{"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "use":"sig", "alg":"RS256", "key_ops":["verify"], "kid":"DfpE4Q" }]}` kh, err := jwt.JWKSetToPublicKeysetHandle([]byte(jwkSet)) if err != nil { t.Fatalf("JWKSetToPublicKeysetHandle() err = %v, want nil", err) } ks := testkeyset.KeysetMaterial(kh) key := ks.GetKey()[0] if key.GetOutputPrefixType() != tinkpb.OutputPrefixType_RAW { t.Errorf("key.GetOutputPrefixType() got %q, want %q", key.GetOutputPrefixType(), tinkpb.OutputPrefixType_RAW) } if key.GetKeyData() == nil { t.Fatalf("GetKeyData() got nil, want *tinkpb.KeyData") } pubKey := &jrsppb.JwtRsaSsaPkcs1PublicKey{} if err := proto.Unmarshal(key.GetKeyData().GetValue(), pubKey); err != nil { t.Fatalf("proto.Unmarshal() err = %v, want nil", err) } if pubKey.GetCustomKid().GetValue() != "DfpE4Q" { t.Errorf("pubKey.GetCustomKid().GetValue() = %q, want %q", pubKey.GetCustomKid().GetValue(), "DfpE4Q") } } func TestJWKSetToPublicKeysetRS256WithoutOptionalFieldsSucceeds(t *testing.T) { jwkSet := `{"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "alg":"RS256" }]}` if _, err := jwt.JWKSetToPublicKeysetHandle([]byte(jwkSet)); err != nil { t.Fatalf("jwt.JWKSetToPublicKeysetHandle() err = %v, want nil", err) } } func TestJWKSetToPublicKeysetInvalidRS256JWKSet(t *testing.T) { for _, tc := range []jwkSetTestCase{ { tag: "RS256 without kty", jwkSet: `{"keys":[ {"n":"AQAB", "e":"AQAB", "use":"sig", "alg":"RS256", "key_ops":["verify"], "kid":"DfpE4Q" }] }`, }, { tag: "RS256 without alg", jwkSet: `{"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "use":"sig", "key_ops":["verify"], "kid":"DfpE4Q" }] }`, }, { tag: "RS256 invalid kty", jwkSet: `{"keys":[ {"kty":"EC", "n":"AQAB", "e":"AQAB", "use":"sig", "alg":"RS256", "key_ops":["verify"], "kid":"DfpE4Q" }] }`, }, { tag: "RS256 invalid key ops", jwkSet: `{"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "use":"sig", "alg":"RS256", "key_ops":["verify "], "kid":"DfpE4Q" }] }`, }, { tag: "RS invalid alg", jwkSet: `{"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "use":"sig", "alg":"RS257", "key_ops":["verify"], "kid":"DfpE4Q" }] }`, }, { tag: "RS256 invalid key ops type", jwkSet: `{"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "use":"sig", "alg":"RS256", "key_ops":"verify", "kid":"DfpE4Q" }] }`, }, { tag: "RS256 invalid use", jwkSet: `{"keys":[ {"kty":"RSA", "n":"AQAB", "e":"AQAB", "use":"zag", "alg":"RS256", "key_ops":["verify"], "kid":"DfpE4Q" }] } `, }, { tag: "RS256 without modulus", jwkSet: `{"keys":[ {"kty":"RSA", "e":"AQAB", "use":"sig", "alg":"RS256", "key_ops":["verify"], "kid":"DfpE4Q" }] }`, }, { tag: "RSS256 without exponent", jwkSet: `{"keys":[ {"kty":"RSA", "n":"AQAB", "use":"sig", "alg":"RS256", "key_ops":["verify"], "kid":"DfpE4Q" }] }`, }, } { t.Run(tc.tag, func(t *testing.T) { if _, err := jwt.JWKSetToPublicKeysetHandle([]byte(tc.jwkSet)); err == nil { t.Fatalf("jwt.JWKSetToPublicKeysetHandle() err = nil, want error") } }) } } func TestJWKSetToPublicKeysetES256WithSmallXPrimitiveFails(t *testing.T) { jwk := `{ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8Sk", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES256","key_ops":["verify"]}], "kid":"EhuduQ" }` // Keys in the keyset are validated when the primitive is generated. // JWKSetToPublicKeysetHandle but NewVerifier will fail. pubHandle, err := jwt.JWKSetToPublicKeysetHandle([]byte(jwk)) if err != nil { t.Fatalf("jwt.JWKSetToPublicKeysetHandle() err = %v, want nil", err) } if _, err := jwt.NewVerifier(pubHandle); err == nil { t.Errorf("jwt.NewVerifier() err = nil, want error") } } func TestJWKSetToPublicKeysetES256WithSmallYFails(t *testing.T) { jwk := `{ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB27", "use":"sig","alg":"ES256","key_ops":["verify"]}], "kid":"EhuduQ" }` // Keys in the keyset are validated when the primitive is generated. // JWKSetToPublicKeysetHandle but NewVerifier will fail. pubHandle, err := jwt.JWKSetToPublicKeysetHandle([]byte(jwk)) if err != nil { t.Fatalf("jwt.JWKSetToPublicKeysetHandle() err = %v, want nil", err) } if _, err := jwt.NewVerifier(pubHandle); err == nil { t.Errorf("jwt.NewVerifier() err = nil, want error") } } func TestJWKSetToPublicKeysetES256CorrectlySetsKID(t *testing.T) { jwk := `{ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES256","key_ops":["verify"], "kid":"EhuduQ"}] }` pubHandle, err := jwt.JWKSetToPublicKeysetHandle([]byte(jwk)) if err != nil { t.Fatalf("jwt.JWKSetToPublicKeysetHandle() err = %v, want nil", err) } ks := testkeyset.KeysetMaterial(pubHandle) if len(ks.GetKey()) != 1 { t.Errorf("len(ks.GetKey()) got %d keys, want 1", len(ks.GetKey())) } key := ks.GetKey()[0] if key.GetOutputPrefixType() != tinkpb.OutputPrefixType_RAW { t.Errorf("key.GetOutputPrefixType() got %q, want %q", key.GetOutputPrefixType(), tinkpb.OutputPrefixType_RAW) } if key.GetKeyData() == nil { t.Fatalf("invalid key") } pubKey := &jepb.JwtEcdsaPublicKey{} if err := proto.Unmarshal(key.GetKeyData().GetValue(), pubKey); err != nil { t.Fatalf("proto.Unmarshal(key.GetKeyData(), pubKey) err = %v, want nil", err) } if pubKey.GetCustomKid().GetValue() != "EhuduQ" { t.Errorf("key.GetCustomKid() got %q, want EhuduQ", pubKey.GetCustomKid()) } } func TestJWKSetToPublicKeysetES256WithoutOptionalFieldsSucceeds(t *testing.T) { jwk := `{ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "alg":"ES256"}] }` if _, err := jwt.JWKSetToPublicKeysetHandle([]byte(jwk)); err != nil { t.Fatalf("jwt.JWKSetToPublicKeysetHandle() err = %v, want nil", err) } } func TestJWKSetToPublicKeysetInvalidES256PublicKeys(t *testing.T) { for _, tc := range []jwkSetTestCase{ { tag: "jwk set is not a json", jwkSet: `5`, }, { tag: "empty jwk set", jwkSet: `{}`, }, { tag: "no keys in jwk set", jwkSet: `{"keys": []}`, }, { tag: "keys of wrong type in jwk set", jwkSet: `{"keys": "value"}`, }, { tag: "keys not a json object", jwkSet: `{"keys":[1]}`, }, { tag: "without kty", jwkSet: `{ "keys":[{ "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES256","key_ops":["verify"], "kid":"EhuduQ"}] }`, }, { tag: "without algorithm", jwkSet: `{ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","key_ops":["verify"], "kid":"EhuduQ"}] }`, }, { tag: "empty algorithm", jwkSet: `{ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig", "alg":"", "key_ops":["verify"], "kid":"EhuduQ"}] }`, }, { tag: "invalid algorthm prefix", jwkSet: `{ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig", "alg":"SS256", "key_ops":["verify"], "kid":"EhuduQ"}] }`, }, { tag: "invalid algorithm", jwkSet: `{ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES257","key_ops":["verify"], "kid":"EhuduQ"}] }`, }, { tag: "algorithm not a string", jwkSet: `{ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":256,"key_ops":["verify"], "kid":"EhuduQ"}] }`, }, { tag: "invalid curve and algorithm", jwkSet: `{ "keys":[{ "kty":"EC", "crv":"P-384", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES512","key_ops":["verify"], "kid":"EhuduQ"}] }`, }, { tag: "without curve", jwkSet: `{ "keys":[{ "kty":"EC", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES512","key_ops":["verify"], "kid":"EhuduQ"}] }`, }, { tag: "invalid key ops", jwkSet: `{ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES256","key_ops":["verify "], "kid":"EhuduQ"}] }`, }, { tag: "multiple key ops", jwkSet: `{ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES256","key_ops":["verify", "sign"], "kid":"EhuduQ"}] }`, }, { tag: "invalid key ops type", jwkSet: `{ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES256","key_ops":"verify", "kid":"EhuduQ"}] }`, }, { tag: "invalid key ops type inside list", jwkSet: `{ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES256","key_ops":[1], "kid":"EhuduQ"}] }`, }, { tag: "invalid use", jwkSet: `{ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"zag","alg":"ES256","key_ops":["verify"], "kid":"EhuduQ"}] }`, }, { tag: "without x coordinate", jwkSet: `{ "keys":[{ "kty":"EC", "crv":"P-256", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES256","key_ops":["verify"], "kid":"EhuduQ"}] }`, }, { tag: "without y coordinate", jwkSet: `{ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "use":"sig","alg":"ES256","key_ops":["verify"], "kid":"EhuduQ"}] }`, }, { tag: "kid of invalid type", jwkSet: `{ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig","alg":"ES256","key_ops":["verify"], "kid":5}] }`, }, { tag: "with private key", jwkSet: `{ "keys":[{ "kty":"EC", "crv":"P-256", "alg":"ES256", "x":"SVqB4JcUD6lsfvqMr-OKUNUphdNn64Eay60978ZlL74", "y":"lf0u0pMj4lGAzZix5u4Cm5CMQIgMNpkwy163wtKYVKI", "d":"0g5vAEKzugrXaRbgKG0Tj2qJ5lMP4Bezds1_sTybkfk" }] }`, }, } { t.Run(tc.tag, func(t *testing.T) { if _, err := jwt.JWKSetToPublicKeysetHandle([]byte(tc.jwkSet)); err == nil { t.Fatalf("jwt.JWKSetToPublicKeysetHandle() err = nil, want error") } }) } } func TestJWKSetFromPublicKeysetNonEnabledKeysAreIgnored(t *testing.T) { key := `{ "primaryKeyId": 303799737, "key": [ { "keyId": 303799737, "status": "DISABLED", "outputPrefixType": "TINK", "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey", "keyMaterialType": "ASYMMETRIC_PUBLIC", "value": "IiDuhGJiGeaQ/qeqt1daC2xZRarm4VEsmSHJUWJY9EHbvxogwO6uIxh8SkKOO8VjZXNRTteRcwCPE4/4JElKyaa0fcQQAQ==" } } ] }` handle, err := createKeysetHandle(key) if err != nil { t.Fatalf("createKeysetHandle() err = %v, want nil", err) } jwkSet, err := jwt.JWKSetFromPublicKeysetHandle(handle) if err != nil { t.Fatalf("jwt.JWKSetFromPublicKeysetHandle() err = %v, want nil", err) } want := `{"keys":[]}` if string(jwkSet) != want { t.Fatalf("jwt.JWKSetFromPublicKeysetHandle() = %q, want %q", string(jwkSet), want) } } func TestJWKSetFromPublicKeysetHandleTinkOutputPrefixHasKID(t *testing.T) { for _, tc := range []jwkSetTestCase{ { tag: "JwtEcdsaPublicKey", publicKeyset: `{ "primaryKeyId": 303799737, "key": [ { "keyId": 303799737, "status": "ENABLED", "outputPrefixType": "TINK", "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey", "keyMaterialType": "ASYMMETRIC_PUBLIC", "value": "IiDuhGJiGeaQ/qeqt1daC2xZRarm4VEsmSHJUWJY9EHbvxogwO6uIxh8SkKOO8VjZXNRTteRcwCPE4/4JElKyaa0fcQQAQ==" } } ] }`, jwkSet: `{ "keys":[{ "kty":"EC", "crv":"P-256", "x":"wO6uIxh8SkKOO8VjZXNRTteRcwCPE4_4JElKyaa0fcQ", "y":"7oRiYhnmkP6nqrdXWgtsWUWq5uFRLJkhyVFiWPRB278", "use":"sig", "alg":"ES256", "key_ops":["verify"], "kid":"EhuduQ"}] }`, }, { tag: "JwtRsaSsaPkcs1PublicKey", publicKeyset: `{ "primaryKeyId": 1277272603, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PublicKey", "value": "IgMBAAEagAK+ZQ5rrZNivGPs3ytlUDOgR1KeaxFBo1YEwB0Hxp0ZryfjJwaJhaga/S5lZzy8faOfqXc9r/vZtvYgd/f4oPZRpPAuTXHfJKFfJsShLlkX1t6bOufaiE2LEag3s5+PvA9vrVn4XU2/neerfTzP5EjVZ7Igf70eO4hy5TFpZjRV6+xfMJ6Ewk/mDuRXPKXnlthxGLbx2J2RVrOvNWA0bfnI00wQvfahbVV+++nuF9Ae3FLCQU4/MmDMg8dskVvEAsauuBceyirtS0NB1L2++gSnj8nNCEK2cIQpqGCRPA5bJP3o6VEZiI8lIUdZO6PLVCd3o4pzwsYSykBfigPpmX5hEAE=", "keyMaterialType": "ASYMMETRIC_PUBLIC" }, "status": "ENABLED", "keyId": 1277272603, "outputPrefixType": "TINK" } ] }`, jwkSet: `{ "keys":[{ "kty":"RSA", "n": "vmUOa62TYrxj7N8rZVAzoEdSnmsRQaNWBMAdB8adGa8n4ycGiYWoGv0uZWc8vH2jn6l3Pa_72bb2IHf3-KD2UaTwLk1x3yShXybEoS5ZF9bemzrn2ohNixGoN7Ofj7wPb61Z-F1Nv53nq308z-RI1WeyIH-9HjuIcuUxaWY0VevsXzCehMJP5g7kVzyl55bYcRi28didkVazrzVgNG35yNNMEL32oW1Vfvvp7hfQHtxSwkFOPzJgzIPHbJFbxALGrrgXHsoq7UtDQdS9vvoEp4_JzQhCtnCEKahgkTwOWyT96OlRGYiPJSFHWTujy1Qnd6OKc8LGEspAX4oD6Zl-YQ", "e":"AQAB", "use":"sig", "alg":"RS256", "key_ops":["verify"], "kid":"TCGiGw" }] }`, }, } { t.Run(tc.tag, func(t *testing.T) { handle, err := createKeysetHandle(tc.publicKeyset) if err != nil { t.Fatalf("createKeysetHandle() err = %v, want nil", err) } js, err := jwt.JWKSetFromPublicKeysetHandle(handle) if err != nil { t.Fatalf("jwt.JWKSetFromPublicKeysetHandle() err = %v, want nil", err) } got := &spb.Struct{} if err := got.UnmarshalJSON(js); err != nil { t.Fatalf("got.UnmarshalJSON() err = %v, want nil", err) } want := &spb.Struct{} if err := want.UnmarshalJSON([]byte(tc.jwkSet)); err != nil { t.Fatalf("want.UnmarshalJSON() err = %v, want nil", err) } if !cmp.Equal(want, got, protocmp.Transform()) { t.Errorf("mismatch in jwk sets: diff (-want,+got): %v", cmp.Diff(want, got, protocmp.Transform())) } }) } } func TestJWKSetFromPublicKeysetHandleInvalidKeysetsFails(t *testing.T) { for _, tc := range []jwkSetTestCase{ { tag: "invalid output prefix", publicKeyset: `{ "primaryKeyId": 303799737, "key": [ { "keyId": 303799737, "status": "ENABLED", "outputPrefixType": "LEGACY", "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey", "keyMaterialType": "ASYMMETRIC_PUBLIC", "value": "IiDuhGJiGeaQ/qeqt1daC2xZRarm4VEsmSHJUWJY9EHbvxogwO6uIxh8SkKOO8VjZXNRTteRcwCPE4/4JElKyaa0fcQQAQ==" } } ] }`, }, { tag: "JwtEcdsaPublicKey unknown algorithm", // The algorithm is set in the base64 encoded value of the key data. publicKeyset: `{ "primaryKeyId": 303799737, "key": [ { "keyId": 303799737, "status": "ENABLED", "outputPrefixType": "TINK", "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey", "value": "IiDuhGJiGeaQ/qeqt1daC2xZRarm4VEsmSHJUWJY9EHbvxogwO6uIxh8SkKOO8VjZXNRTteRcwCPE4/4JElKyaa0fcQ=", "keyMaterialType": "ASYMMETRIC_PUBLIC" } } ] }`, }, { tag: "private ecdsa keyset", publicKeyset: `{ "primaryKeyId": 303799737, "key": [ { "keyId": 303799737, "status": "ENABLED", "outputPrefixType": "TINK", "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey", "keyMaterialType": "ASYMMETRIC_PRIVATE", "value": "IiDuhGJiGeaQ/qeqt1daC2xZRarm4VEsmSHJUWJY9EHbvxogwO6uIxh8SkKOO8VjZXNRTteRcwCPE4/4JElKyaa0fcQQAQ==" } } ] }`, }, { tag: "unknown key type", publicKeyset: `{ "primaryKeyId": 303799737, "key": [ { "keyId": 303799737, "status": "ENABLED", "outputPrefixType": "TINK", "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.Unknown", "keyMaterialType": "ASYMMETRIC_PUBLIC", "value": "IiDuhGJiGeaQ/qeqt1daC2xZRarm4VEsmSHJUWJY9EHbvxogwO6uIxh8SkKOO8VjZXNRTteRcwCPE4/4JElKyaa0fcQQAQ==" } } ] }`, }, { tag: "JwtRsaSsaPkcs1 unknown algorithm", // The algorithm is set in the base64 encoded value of the key data. publicKeyset: `{ "primaryKeyId": 1277272603, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PublicKey", "value": "IgMBAAEagAK+ZQ5rrZNivGPs3ytlUDOgR1KeaxFBo1YEwB0Hxp0ZryfjJwaJhaga/S5lZzy8faOfqXc9r/vZtvYgd/f4oPZRpPAuTXHfJKFfJsShLlkX1t6bOufaiE2LEag3s5+PvA9vrVn4XU2/neerfTzP5EjVZ7Igf70eO4hy5TFpZjRV6+xfMJ6Ewk/mDuRXPKXnlthxGLbx2J2RVrOvNWA0bfnI00wQvfahbVV+++nuF9Ae3FLCQU4/MmDMg8dskVvEAsauuBceyirtS0NB1L2++gSnj8nNCEK2cIQpqGCRPA5bJP3o6VEZiI8lIUdZO6PLVCd3o4pzwsYSykBfigPpmX5h", "keyMaterialType": "ASYMMETRIC_PUBLIC" }, "status": "ENABLED", "keyId": 1277272603, "outputPrefixType": "TINK" } ] }`, }, } { t.Run(tc.tag, func(t *testing.T) { handle, err := createKeysetHandle(tc.publicKeyset) if err != nil { t.Fatalf("createKeysetHandle() err = %v, want nil", err) } if _, err := jwt.JWKSetFromPublicKeysetHandle(handle); err == nil { t.Errorf("jwt.JWKSetFromPublicKeysetHandle() err = nil, want error") } }) } } func getCoordinateFromJwk(jwk *spb.Struct, coord string) ([]byte, error) { c := jwk.GetFields()["keys"].GetListValue().GetValues()[0].GetStructValue().GetFields()[coord].GetStringValue() return base64.URLEncoding.WithPadding(base64.NoPadding).DecodeString(c) } func TestJWKSizedSizedECCEncoding(t *testing.T) { type testCase struct { tag string publicKeyset string elementSizeInBytes int } for _, tc := range []testCase{ { tag: "P-256 smaller coordinates", publicKeyset: `{ "primaryKeyId": 2124611562, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey", "value": "EAEaH2lFjtbwLgtzRDh7dV9sYmW4IWl3ZKA+WghvrQPiCNoiIEJ8pQXMyA/JywaGWT+IHmWxuVYWqdxkPsUSHLhSQm51", "keyMaterialType": "ASYMMETRIC_PUBLIC" }, "status": "ENABLED", "keyId": 2124611562, "outputPrefixType": "TINK" } ] }`, elementSizeInBytes: 32, }, { tag: "P-256 larger coordinates", elementSizeInBytes: 32, publicKeyset: `{ "primaryKeyId":858766452, "key":[ { "keyData": { "typeUrl":"type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey", "value":"EAEaIQAocb/rp/rsVlYMqlR2KB18kpSAPURySedsnfswHoqEviIhANrIMzHBtAQvDOKUf3BYVmV+AfwKyA0lq9gHOTY3gVm+", "keyMaterialType":"ASYMMETRIC_PUBLIC" }, "status":"ENABLED", "keyId":858766452, "outputPrefixType":"TINK"}] }`, }, { tag: "P-384 smaller coordinates", publicKeyset: `{ "primaryKeyId": 4159170178, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey", "value": "EAIaL/bm1+e6X7gat+MJK3e65BGlZzKIf6I1q0Ro8zAKeyryUxgvZl8Ww/NlcVN2XJhEIjA3b73hm8eDfSEEUAAaJbrLZFOFGnSdTWng116r+hOvszYiov+WrsTyIgnL/9aRdN8=", "keyMaterialType": "ASYMMETRIC_PUBLIC" }, "status": "ENABLED", "keyId": 4159170178, "outputPrefixType": "TINK" } ] }`, elementSizeInBytes: 48, }, { tag: "P-384 smaller coordinates", publicKeyset: `{ "primaryKeyId": 1286030637, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey", "value": "EAMaQUgdEssWf+tdFT3vSoy/OAotV501af+XQ6JSXDjnOPCzZnFh8fYwrJ8Yu8XYF33IeHBdAIKyicKuW884JkjYR1qJIkH2OWoa4SOmk0FtpeRBZHPbs7U8SMFXVkaV+HZtjmfl11QGiQU9hqUhoW9ock2K0xg6wdcWBe67YTVFdQbThFmtCg==", "keyMaterialType": "ASYMMETRIC_PUBLIC" }, "status": "ENABLED", "keyId": 1286030637, "outputPrefixType": "TINK" } ] }`, elementSizeInBytes: 66, }, } { handle, err := createKeysetHandle(tc.publicKeyset) if err != nil { t.Fatalf("createKeysetHandle() err = %v, want nil", err) } keyset := testkeyset.KeysetMaterial(handle) pubKey := &epb.EcdsaPublicKey{} if err := proto.Unmarshal(keyset.GetKey()[0].GetKeyData().GetValue(), pubKey); err != nil { t.Fatalf("proto.Unmarshal() err = %v, want nil", err) } if len(pubKey.GetX()) == tc.elementSizeInBytes && len(pubKey.GetY()) == tc.elementSizeInBytes { t.Errorf("excepted serialized coordinates to be smaller than element, to test padding logic") } js, err := jwt.JWKSetFromPublicKeysetHandle(handle) if err != nil { t.Fatalf("jwt.JWKSetFromPublicKeysetHandle() err = %v, want nil", err) } jwkSet := &spb.Struct{} if err := jwkSet.UnmarshalJSON(js); err != nil { t.Fatalf("want.UnmarshalJSON() err = %v, want nil", err) } x, err := getCoordinateFromJwk(jwkSet, "x") if err != nil { t.Fatalf("base64.URLEncoding.WithPadding(base64.NoPadding).DecodeString() err = %v, want nil", err) } y, err := getCoordinateFromJwk(jwkSet, "y") if err != nil { t.Fatalf("base64.URLEncoding.WithPadding(base64.NoPadding).DecodeString() err = %v, want nil", err) } if len(x) != tc.elementSizeInBytes { t.Errorf("len(x) = %d, want %d", len(x), tc.elementSizeInBytes) } if len(y) != tc.elementSizeInBytes { t.Errorf("len(x) = %d, want %d", len(y), tc.elementSizeInBytes) } } } ================================================ FILE: go/jwt/jwt.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package jwt implements a subset of JSON Web Token (JWT) as defined by RFC 7519 (https://tools.ietf.org/html/rfc7519) that is considered safe and most often used. package jwt import ( "errors" "fmt" "github.com/google/tink/go/core/registry" ) // A generic error returned when something went wrong before validation var errJwtVerification = errors.New("verification failed") var errJwtExpired = errors.New("token has expired") // IsExpirationErr returns true if err was returned by a JWT verification for a token // with a valid signature that is expired. // // Note that if the corresponding verification key has been removed from the keyset, // verification will not return an expiration error even if the token is expired, because // the expiration is only verified if the signature is valid. func IsExpirationErr(err error) bool { return err == errJwtExpired } func init() { if err := registry.RegisterKeyManager(new(jwtHMACKeyManager)); err != nil { panic(fmt.Sprintf("jwt.init() failed registering JWT HMAC key manager: %v", err)) } if err := registry.RegisterKeyManager(new(jwtECDSAVerifierKeyManager)); err != nil { panic(fmt.Sprintf("jwt.init() failed registering JWT ECDSA verifier key manager: %v", err)) } if err := registry.RegisterKeyManager(new(jwtECDSASignerKeyManager)); err != nil { panic(fmt.Sprintf("jwt.init() failed registering JWT ECDSA signer key manager: %v", err)) } if err := registry.RegisterKeyManager(new(jwtRSSignerKeyManager)); err != nil { panic(fmt.Sprintf("jwt.init() failed registering JWT RSA SSA PKCS1 signer key manager: %v", err)) } if err := registry.RegisterKeyManager(new(jwtRSVerifierKeyManager)); err != nil { panic(fmt.Sprintf("jwt.init() failed registering JWT RSA SSA PKCS1 verifier key manager: %v", err)) } if err := registry.RegisterKeyManager(new(jwtPSSignerKeyManager)); err != nil { panic(fmt.Sprintf("jwt.init() failed registering JWT RSA SSA PSS signer key manager: %v", err)) } if err := registry.RegisterKeyManager(new(jwtPSVerifierKeyManager)); err != nil { panic(fmt.Sprintf("jwt.init() failed registering JWT RSA SSA PSS verifier key manager: %v", err)) } } ================================================ FILE: go/jwt/jwt_ecdsa_signer_key_manager.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "crypto/ecdsa" "crypto/rand" "errors" "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/keyset" subtlesign "github.com/google/tink/go/signature/subtle" "github.com/google/tink/go/subtle" jepb "github.com/google/tink/go/proto/jwt_ecdsa_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( jwtECDSASignerKeyVersion = 0 jwtECDSASignerTypeURL = "type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey" ) var ( errECDSAInvalidKey = errors.New("invalid JwtEcdsaPrivateKey key") errECDSAInvalidKeyFormat = errors.New("invalid key format") ) // jwtECDSASignerKeyManager implements the KeyManager interface // for JWT Signing using the 'ES256', 'ES384', and 'ES512' JWA algorithm. type jwtECDSASignerKeyManager struct{} var _ registry.PrivateKeyManager = (*jwtECDSASignerKeyManager)(nil) func (km *jwtECDSASignerKeyManager) Primitive(serializedKey []byte) (any, error) { if serializedKey == nil { return nil, errECDSAInvalidKey } privKey := &jepb.JwtEcdsaPrivateKey{} if err := proto.Unmarshal(serializedKey, privKey); err != nil { return nil, fmt.Errorf("failed to unmarshal JwtEcdsaPrivateKey: %v", err) } params, err := km.validateKey(privKey) if err != nil { return nil, err } ts, err := subtlesign.NewECDSASigner(params.Hash, params.Curve, jwtECDSAEncoding, privKey.GetKeyValue()) if err != nil { return nil, fmt.Errorf("failed to create ECDSASigner: %v", err) } pubKey := privKey.GetPublicKey() var kid *string = nil if pubKey.GetCustomKid() != nil { k := pubKey.GetCustomKid().GetValue() kid = &k } return newSignerWithKID(ts, pubKey.GetAlgorithm().String(), kid) } func (km *jwtECDSASignerKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { if serializedKeyFormat == nil { return nil, errECDSAInvalidKeyFormat } keyFormat := &jepb.JwtEcdsaKeyFormat{} if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, fmt.Errorf("failed to unmarshal JwtEcdsaKeyFormat: %v", err) } params, ok := esAlgToParams[keyFormat.GetAlgorithm()] if !ok { return nil, errECDSAInvalidAlgorithm } k, err := ecdsa.GenerateKey(subtle.GetCurve(params.Curve), rand.Reader) if err != nil { return nil, fmt.Errorf("failed to generate key: %v", err) } return &jepb.JwtEcdsaPrivateKey{ Version: jwtECDSASignerKeyVersion, PublicKey: &jepb.JwtEcdsaPublicKey{ Version: jwtECDSASignerKeyVersion, Algorithm: keyFormat.GetAlgorithm(), X: k.X.Bytes(), Y: k.Y.Bytes(), }, KeyValue: k.D.Bytes(), }, nil } func (km *jwtECDSASignerKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { if serializedKeyFormat == nil { return nil, errECDSAInvalidKeyFormat } key, err := km.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, fmt.Errorf("failed to marshal JwtEcdsaPrivateKey: %v", err) } return &tinkpb.KeyData{ TypeUrl: jwtECDSASignerTypeURL, Value: serializedKey, KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PRIVATE, }, nil } func (km *jwtECDSASignerKeyManager) PublicKeyData(serializedPrivKey []byte) (*tinkpb.KeyData, error) { if serializedPrivKey == nil { return nil, errECDSAInvalidKey } privKey := &jepb.JwtEcdsaPrivateKey{} if err := proto.Unmarshal(serializedPrivKey, privKey); err != nil { return nil, fmt.Errorf("failed to unmarshal JwtEcdsaPrivateKey: %v", err) } serializedPubKey, err := proto.Marshal(privKey.GetPublicKey()) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: jwtECDSAVerifierTypeURL, Value: serializedPubKey, KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC, }, nil } func (km *jwtECDSASignerKeyManager) DoesSupport(typeURL string) bool { return jwtECDSASignerTypeURL == typeURL } func (km *jwtECDSASignerKeyManager) TypeURL() string { return jwtECDSASignerTypeURL } func (km *jwtECDSASignerKeyManager) validateKey(key *jepb.JwtEcdsaPrivateKey) (ecdsaParams, error) { if err := keyset.ValidateKeyVersion(key.Version, jwtECDSASignerKeyVersion); err != nil { return ecdsaParams{}, fmt.Errorf("invalid key version: %v", err) } if key.GetPublicKey() == nil { return ecdsaParams{}, fmt.Errorf("no public key in JwtEcdsaPrivateKey") } params, ok := esAlgToParams[key.GetPublicKey().GetAlgorithm()] if !ok { return ecdsaParams{}, errECDSAInvalidAlgorithm } return params, nil } ================================================ FILE: go/jwt/jwt_ecdsa_signer_key_manager_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "testing" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" jepb "github.com/google/tink/go/proto/jwt_ecdsa_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( testECDSASignerKeyType = "type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey" testECDSASignerVersion = 0 ) func TestECDSASignerDoesSupport(t *testing.T) { km, err := registry.GetKeyManager(testECDSASignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSASignerKeyType, err) } if !km.DoesSupport(testECDSASignerKeyType) { t.Errorf("km.DoesSupport(%q) = false, want true", testECDSASignerKeyType) } if km.DoesSupport("not.the.actual.key.type") { t.Errorf("km.DoesSupport('not.the.actual.key.type') = true, want false") } } func TestECDSASignerTypeURL(t *testing.T) { km, err := registry.GetKeyManager(testECDSASignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSASignerKeyType, err) } if km.TypeURL() != testECDSASignerKeyType { t.Errorf("km.TypeURL() = %q, want %q", km.TypeURL(), testECDSASignerKeyType) } } func TestECDSASignerNewKeyWithEmptyKeyFormatFails(t *testing.T) { km, err := registry.GetKeyManager(testECDSASignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSASignerKeyType, err) } if _, err := km.NewKey(nil); err == nil { t.Errorf("km.NewKey(nil) err = nil, want error") } } func createECDSASerializedKeyFormat(algorithm jepb.JwtEcdsaAlgorithm, version uint32) ([]byte, error) { kf := &jepb.JwtEcdsaKeyFormat{ Version: version, Algorithm: algorithm, } return proto.Marshal(kf) } func TestECDSASignerNewKeyWithInvalidAlgorithmFails(t *testing.T) { km, err := registry.GetKeyManager(testECDSASignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSASignerKeyType, err) } keyFormat, err := createECDSASerializedKeyFormat(jepb.JwtEcdsaAlgorithm_ES_UNKNOWN, testECDSASignerVersion) if err != nil { t.Fatalf("createECDSASerializedKeyFormat() err = %v, want nil", err) } if _, err := km.NewKey(keyFormat); err == nil { t.Errorf("km.NewKey(keyFormat) err = nil, want error") } } func TestECDSASignerNewKeyGeneratesValidKey(t *testing.T) { type testCase struct { tag string algorithm jepb.JwtEcdsaAlgorithm } for _, tc := range []testCase{ { tag: "ES256", algorithm: jepb.JwtEcdsaAlgorithm_ES256, }, { tag: "ES384", algorithm: jepb.JwtEcdsaAlgorithm_ES384, }, { tag: "ES521", algorithm: jepb.JwtEcdsaAlgorithm_ES512, }, } { t.Run(tc.tag, func(t *testing.T) { km, err := registry.GetKeyManager(testECDSASignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSASignerKeyType, err) } keyFormat, err := createECDSASerializedKeyFormat(tc.algorithm, testECDSASignerVersion) if err != nil { t.Fatalf("createECDSASerializedKeyFormat() err = %v, want nil", err) } k, err := km.NewKey(keyFormat) if err != nil { t.Errorf("km.NewKey(keyFormat) err = %v, want nil", err) } key, ok := k.(*jepb.JwtEcdsaPrivateKey) if !ok { t.Errorf("key is not of type: *jepb.JwtEcdsaPrivateKey") } pubKey := key.GetPublicKey() if pubKey == nil { t.Errorf("pubKey = nil, want *jebp.JwtEcdsaPublicKey{}") } if pubKey.GetAlgorithm() != tc.algorithm { t.Errorf("pubKey.GetAlgorithm() = %q, want %q", pubKey.GetAlgorithm(), tc.algorithm) } if pubKey.GetVersion() != testECDSASignerVersion { t.Errorf("pubKey.GetVersion() = %d, want %d", pubKey.GetVersion(), testECDSASignerVersion) } }) } } func TestECDSASignerNewKeyGeneratesDifferentKeys(t *testing.T) { km, err := registry.GetKeyManager(testECDSASignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSASignerKeyType, err) } keyFormat, err := createECDSASerializedKeyFormat(jepb.JwtEcdsaAlgorithm_ES256, testECDSASignerVersion) if err != nil { t.Fatalf("createECDSASerializedKeyFormat() err = %v, want nil", err) } k1, err := km.NewKey(keyFormat) if err != nil { t.Errorf("km.NewKey(keyFormat) err = %v, want nil", err) } key1, ok := k1.(*jepb.JwtEcdsaPrivateKey) if !ok { t.Errorf("key1 is not of type: *jepb.JwtEcdsaPrivateKey") } k2, err := km.NewKey(keyFormat) if err != nil { t.Errorf("km.NewKey(keyFormat) err = %v, want nil", err) } key2, ok := k2.(*jepb.JwtEcdsaPrivateKey) if !ok { t.Errorf("key2 is not of type: *jepb.JwtEcdsaPrivateKey") } if cmp.Equal(key1.GetKeyValue(), key2.GetKeyValue()) { t.Errorf("keys should have different values") } } func TestECDSASignerNewKeyDataWithEmptyKeyFormatFails(t *testing.T) { km, err := registry.GetKeyManager(testECDSASignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSASignerKeyType, err) } if _, err := km.NewKeyData(nil); err == nil { t.Errorf("km.NewKeyData(nil) err = nil, want error") } } func TestECDSASignerNewKeyDataWithInvalidAlgorithmFails(t *testing.T) { km, err := registry.GetKeyManager(testECDSASignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSASignerKeyType, err) } keyFormat, err := createECDSASerializedKeyFormat(jepb.JwtEcdsaAlgorithm_ES_UNKNOWN, testECDSASignerVersion) if err != nil { t.Fatalf("createECDSASerializedKeyFormat() err = %v, want nil", err) } if _, err := km.NewKeyData(keyFormat); err != errECDSAInvalidAlgorithm { t.Errorf("km.NewKeyData() err = %v, want %v", err, errECDSAInvalidAlgorithm) } } func TestECDSASignerNewKeyDataGeneratesValidKeyData(t *testing.T) { km, err := registry.GetKeyManager(testECDSASignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSASignerKeyType, err) } keyFormat, err := createECDSASerializedKeyFormat(jepb.JwtEcdsaAlgorithm_ES256, testECDSASignerVersion) if err != nil { t.Fatalf("createECDSASerializedKeyFormat() err = %v, want nil", err) } keyData, err := km.NewKeyData(keyFormat) if err != nil { t.Errorf("km.NewKeyData(keyFormat) err = %v, want nil", err) } if keyData.GetTypeUrl() != testECDSASignerKeyType { t.Errorf("keyData.GetTypeUrl() = %q, want %q", keyData.GetTypeUrl(), testECDSASignerKeyType) } if keyData.GetKeyMaterialType() != tinkpb.KeyData_ASYMMETRIC_PRIVATE { t.Errorf("keyData.GetKeyMaterialType() = %q, want %q", keyData.GetKeyMaterialType(), tinkpb.KeyData_ASYMMETRIC_PRIVATE) } } func TestECDSASignerPublicKeyDataWithEmptyKeyFormatFails(t *testing.T) { km, err := registry.GetKeyManager(testECDSASignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSASignerKeyType, err) } pkm, ok := km.(registry.PrivateKeyManager) if !ok { t.Fatalf("key manager is not of type registry.PrivateKeyManager") } if _, err := pkm.PublicKeyData(nil); err == nil { t.Errorf("km.PublicKeyData(nil) err = nil, want error") } } func createECDSAKey() (*jepb.JwtEcdsaPrivateKey, error) { // Private key from: https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.3 k, err := base64Decode("jpsQnnGQmL-YBIffH1136cspYG6-0iY7X1fCE9-E9LI") if err != nil { return nil, err } pubKey, err := createECDSAPublicKey(jepb.JwtEcdsaAlgorithm_ES256, nil /*=kid*/, testECDSASignerVersion) if err != nil { return nil, err } return &jepb.JwtEcdsaPrivateKey{ Version: testECDSASignerVersion, PublicKey: pubKey, KeyValue: k, }, nil } func createSerializedECDSAKey() ([]byte, error) { key, err := createECDSAKey() if err != nil { return nil, err } return proto.Marshal(key) } func TestECDSASignerPublicKeyDataGeneratesValidKeyData(t *testing.T) { km, err := registry.GetKeyManager(testECDSASignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSASignerKeyType, err) } pkm, ok := km.(registry.PrivateKeyManager) if !ok { t.Fatalf("key manager is not of type registry.PrivateKeyManager") } key, err := createSerializedECDSAKey() if err != nil { t.Fatalf("createECDSASerializedKeyFormat() err = %v, want nil", err) } pubKeyData, err := pkm.PublicKeyData(key) if err != nil { t.Fatalf("km.PublicKeyData() err = %v, want nil", err) } if pubKeyData.GetKeyMaterialType() != tinkpb.KeyData_ASYMMETRIC_PUBLIC { t.Fatalf("km.PublicKeyData() = %q, want %q", pubKeyData.GetKeyMaterialType(), tinkpb.KeyData_ASYMMETRIC_PUBLIC) } if pubKeyData.GetTypeUrl() != testECDSAVerifierKeyType { t.Errorf("keyData.GetTypeUrl() = %q, want %q", pubKeyData.GetTypeUrl(), testECDSAVerifierKeyType) } } func TestECDSASignerPrimitiveWithEmptyKeyFails(t *testing.T) { km, err := registry.GetKeyManager(testECDSASignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSASignerKeyType, err) } if _, err := km.Primitive(nil); err == nil { t.Errorf("km.Primitive(nil) err = nil, want error") } } func TestECDSASignerPrimitiveWithInvalidKeyVersionFails(t *testing.T) { km, err := registry.GetKeyManager(testECDSASignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSASignerKeyType, err) } k, err := createECDSAKey() if err != nil { t.Fatalf("createECDSAKey() err = %v, want nil", err) } k.Version = testECDSASignerVersion + 1 serializedKey, err := proto.Marshal(k) if err != nil { t.Fatalf("proto.Marshal(k) err = %v, want nil", err) } if _, err := km.Primitive(serializedKey); err == nil { t.Errorf("km.Primitive() err = nil, want error") } } func TestECDSASignerPrimitiveWithoutPublicKeyFails(t *testing.T) { km, err := registry.GetKeyManager(testECDSASignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSASignerKeyType, err) } k, err := createECDSAKey() if err != nil { t.Fatalf("createECDSAKey() err = %v, want nil", err) } k.PublicKey = nil serializedKey, err := proto.Marshal(k) if err != nil { t.Fatalf("proto.Marshal(k) err = %v, want nil", err) } if _, err := km.Primitive(serializedKey); err == nil { t.Errorf("km.Primitive() err = nil, want error") } } func TestECDSASignerPrimitiveWithInvalidAlgorithmFails(t *testing.T) { km, err := registry.GetKeyManager(testECDSASignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSASignerKeyType, err) } k, err := createECDSAKey() if err != nil { t.Fatalf("createECDSAKey() err = %v, want nil", err) } k.GetPublicKey().Algorithm = jepb.JwtEcdsaAlgorithm_ES_UNKNOWN serializedKey, err := proto.Marshal(k) if err != nil { t.Fatalf("proto.Marshal(k) err = %v, want nil", err) } if _, err := km.Primitive(serializedKey); err == nil { t.Errorf("km.Primitive(nil) err = nil, want error") } } func TestECDSASignerPrimitiveSignAndVerifyToken(t *testing.T) { rawJWT, err := NewRawJWT(&RawJWTOptions{WithoutExpiration: true}) if err != nil { t.Fatalf("NewRawJWT() err = %v, want nil", err) } validator, err := NewValidator(&ValidatorOpts{AllowMissingExpiration: true}) if err != nil { t.Fatalf("NewValidator() err = %v, want nil", err) } km, err := registry.GetKeyManager(testECDSASignerKeyType) if err != nil { t.Errorf("registry.GetKeyManager(%q): %v", jwtECDSASignerTypeURL, err) } k, err := createECDSAKey() if err != nil { t.Fatal(err) } serializedKey, err := proto.Marshal(k) if err != nil { t.Fatalf("proto.Marshal(k) err = %v, want nil", err) } s, err := km.Primitive(serializedKey) if err != nil { t.Fatalf("km.Primitive() err = %v, want error", err) } signer, ok := s.(*signerWithKID) if !ok { t.Fatalf("s.(*signerWithKID) = %T, want *signerWithKID", s) } compact, err := signer.SignAndEncodeWithKID(rawJWT, nil) if err != nil { t.Errorf("signer.SignAndEncodeWithKID() err = %v, want nil", err) } vkm, err := registry.GetKeyManager(testECDSAVerifierKeyType) if err != nil { t.Errorf("registry.GetKeyManager(%q): %v", jwtECDSAVerifierTypeURL, err) } serializedPubKey, err := proto.Marshal(k.GetPublicKey()) if err != nil { t.Fatalf("proto.Marshal(k.GetPublicKey()) err = %v, want nil", err) } v, err := vkm.Primitive(serializedPubKey) if err != nil { t.Fatalf("vkm.Primitive() err = %v, want error", err) } verifier, ok := v.(*verifierWithKID) if !ok { t.Fatalf("v.(*verifierWithKID) = %T, want *verifierWithKID", v) } if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, nil); err != nil { t.Errorf("verifier.VerifyAndDecodeWithKID() err = %v, want nil", err) } // Shouldn't contain KID header at all if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, refString("")); err == nil { t.Errorf("verifier.VerifyAndDecodeWithKID() err = nil, want error") } } func TestECDSASignerPrimitiveSignAndVerifyTokenWithCustomKID(t *testing.T) { rawJWT, err := NewRawJWT(&RawJWTOptions{WithoutExpiration: true}) if err != nil { t.Fatalf("NewRawJWT() err = %v, want nil", err) } validator, err := NewValidator(&ValidatorOpts{AllowMissingExpiration: true}) if err != nil { t.Fatalf("NewValidator() err = %v, want nil", err) } km, err := registry.GetKeyManager(testECDSASignerKeyType) if err != nil { t.Errorf("registry.GetKeyManager(%q): %v", jwtECDSASignerTypeURL, err) } k, err := createECDSAKey() if err != nil { t.Fatal(err) } k.GetPublicKey().CustomKid = &jepb.JwtEcdsaPublicKey_CustomKid{ Value: "1234", } serializedKey, err := proto.Marshal(k) if err != nil { t.Fatalf("proto.Marshal(k) err = %v, want nil", err) } s, err := km.Primitive(serializedKey) if err != nil { t.Fatalf("km.Primitive() err = %v, want error", err) } signer, ok := s.(*signerWithKID) if !ok { t.Fatalf("s.(*signerWithKID) = %T, want *signerWithKID", s) } compact, err := signer.SignAndEncodeWithKID(rawJWT, nil) if err != nil { t.Errorf("signer.SignAndEncodeWithKID(kid = nil) err = %v, want nil", err) } if _, err := signer.SignAndEncodeWithKID(rawJWT, refString("1234")); err == nil { t.Errorf("signer.SignAndEncodeWithKID(kid = 1234) err = nil, want error") } vkm, err := registry.GetKeyManager(testECDSAVerifierKeyType) if err != nil { t.Errorf("registry.GetKeyManager(%q): %v", jwtECDSAVerifierTypeURL, err) } k.GetPublicKey().CustomKid = nil serializedPubKey, err := proto.Marshal(k.GetPublicKey()) if err != nil { t.Fatalf("proto.Marshal(k.GetPublicKey()) err = %v, want nil", err) } v, err := vkm.Primitive(serializedPubKey) if err != nil { t.Fatalf("vkm.Primitive() err = %v, want error", err) } verifier, ok := v.(*verifierWithKID) if !ok { t.Fatalf("v.(*verifierWithKID) = %T, want *verifierWithKID", v) } if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, refString("1234")); err != nil { t.Errorf("verifier.VerifyAndDecodeWithKID(kid = '1234') err = %v, want nil", err) } // wrong KID verification fail if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, refString("1235")); err == nil { t.Errorf("verifier.VerifyAndDecodeWithKID(kid = '1235') err = nil, want error") } } ================================================ FILE: go/jwt/jwt_ecdsa_verifier_key_manager.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "errors" "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/keyset" "github.com/google/tink/go/signature/subtle" jepb "github.com/google/tink/go/proto/jwt_ecdsa_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( jwtECDSAVerifierKeyVersion = 0 jwtECDSAVerifierTypeURL = "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey" jwtECDSAEncoding = "IEEE_P1363" ) var ( errECDSAInvalidAlgorithm = errors.New("invalid algorithm") errECDSAVerifierNotImplemented = errors.New("not supported on verifier key manager") ) // jwtECDSAVerifierKeyManager implements the KeyManager interface // for JWT Verifier using the 'ES256', 'ES384', and 'ES512' JWA algorithm. type jwtECDSAVerifierKeyManager struct{} var _ registry.KeyManager = (*jwtECDSAVerifierKeyManager)(nil) type ecdsaParams struct { Curve string Hash string } var esAlgToParams = map[jepb.JwtEcdsaAlgorithm]ecdsaParams{ jepb.JwtEcdsaAlgorithm_ES256: {Curve: "NIST_P256", Hash: "SHA256"}, jepb.JwtEcdsaAlgorithm_ES384: {Curve: "NIST_P384", Hash: "SHA384"}, jepb.JwtEcdsaAlgorithm_ES512: {Curve: "NIST_P521", Hash: "SHA512"}, } func (km *jwtECDSAVerifierKeyManager) Primitive(serializedKey []byte) (any, error) { if serializedKey == nil || len(serializedKey) == 0 { return nil, fmt.Errorf("invalid key") } pubKey := &jepb.JwtEcdsaPublicKey{} if err := proto.Unmarshal(serializedKey, pubKey); err != nil { return nil, err } if err := keyset.ValidateKeyVersion(pubKey.Version, jwtECDSAVerifierKeyVersion); err != nil { return nil, fmt.Errorf("invalid key: %v", err) } params, ok := esAlgToParams[pubKey.GetAlgorithm()] if !ok { return nil, errECDSAInvalidAlgorithm } tv, err := subtle.NewECDSAVerifier(params.Hash, params.Curve, jwtECDSAEncoding, pubKey.GetX(), pubKey.GetY()) if err != nil { return nil, err } return newVerifierWithKID(tv, pubKey.GetAlgorithm().String(), ecdsaCustomKID(pubKey)) } func (km *jwtECDSAVerifierKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { return nil, errECDSAVerifierNotImplemented } func (km *jwtECDSAVerifierKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { return nil, errECDSAVerifierNotImplemented } func (km *jwtECDSAVerifierKeyManager) DoesSupport(typeURL string) bool { return typeURL == jwtECDSAVerifierTypeURL } func (km *jwtECDSAVerifierKeyManager) TypeURL() string { return jwtECDSAVerifierTypeURL } func ecdsaCustomKID(pk *jepb.JwtEcdsaPublicKey) *string { if pk.GetCustomKid() == nil { return nil } k := pk.GetCustomKid().GetValue() return &k } ================================================ FILE: go/jwt/jwt_ecdsa_verifier_key_manager_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "fmt" "testing" "time" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" jepb "github.com/google/tink/go/proto/jwt_ecdsa_go_proto" ) const testECDSAVerifierKeyType = "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey" func TestECDSAVerifierNotImplemented(t *testing.T) { km, err := registry.GetKeyManager(testECDSAVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSAVerifierKeyType, err) } if _, err := km.NewKey(nil); err != errECDSAVerifierNotImplemented { t.Fatalf("km.NewKey() err = %v, want %v", err, errECDSAVerifierNotImplemented) } if _, err := km.NewKeyData(nil); err != errECDSAVerifierNotImplemented { t.Fatalf("km.NewKeyData() err = %v, want %v", err, errECDSAVerifierNotImplemented) } } func TestECDSAVerifierDoesSupport(t *testing.T) { km, err := registry.GetKeyManager(testECDSAVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSAVerifierKeyType, err) } if !km.DoesSupport(testECDSAVerifierKeyType) { t.Errorf("km.DoesSupport(%q) = false, want true", testECDSAVerifierKeyType) } if km.DoesSupport("not.the.actual.key.type") { t.Errorf("km.DoesSupport('not.the.actual.key.type') = true, want false") } } func TestECDSAVerifierTypeURL(t *testing.T) { km, err := registry.GetKeyManager(testECDSAVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSAVerifierKeyType, err) } if km.TypeURL() != testECDSAVerifierKeyType { t.Errorf("km.TypeURL() = %q, want %q", km.TypeURL(), testECDSAVerifierKeyType) } } func TestECDSAVerifierPrimitiveWithNilKey(t *testing.T) { km, err := registry.GetKeyManager(testECDSAVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSAVerifierKeyType, err) } if _, err := km.Primitive(nil); err == nil { t.Errorf("km.Primitive(nil) err = nil, want error") } } func createECDSAPublicKey(algorithm jepb.JwtEcdsaAlgorithm, kid *string, version uint32) (*jepb.JwtEcdsaPublicKey, error) { // Public key from: https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.3 x, err := base64Decode("f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU") if err != nil { return nil, fmt.Errorf("base64 decoding x coordinate of public key: %v", err) } y, err := base64Decode("x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0") if err != nil { return nil, fmt.Errorf("base64 decoding y coordinate of public key: %v", err) } var customKID *jepb.JwtEcdsaPublicKey_CustomKid = nil if kid != nil { customKID = &jepb.JwtEcdsaPublicKey_CustomKid{Value: *kid} } return &jepb.JwtEcdsaPublicKey{ Version: version, Algorithm: algorithm, X: x, Y: y, CustomKid: customKID, }, nil } func createECDSASerializedPublicKey(algorithm jepb.JwtEcdsaAlgorithm, kid *string, version uint32) ([]byte, error) { pubKey, err := createECDSAPublicKey(algorithm, kid, version) if err != nil { return nil, err } return proto.Marshal(pubKey) } func TestECDSAVerifierPrimitiveInvalidKeyVersion(t *testing.T) { km, err := registry.GetKeyManager(testECDSAVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSAVerifierKeyType, err) } var invalidKeyVersion uint32 = 1 serializedPubKey, err := createECDSASerializedPublicKey(jepb.JwtEcdsaAlgorithm_ES384, nil, invalidKeyVersion) if err != nil { t.Fatal(err) } if _, err := km.Primitive(serializedPubKey); err == nil { t.Errorf("km.Primitive() err = nil, want error") } } func TestECDSAVerifierPrimitiveWithInvalidAlgorithm(t *testing.T) { km, err := registry.GetKeyManager(testECDSAVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSAVerifierKeyType, err) } serializedPubKey, err := createECDSASerializedPublicKey(jepb.JwtEcdsaAlgorithm_ES_UNKNOWN, nil /*=kid*/, 0 /*=version*/) if err != nil { t.Fatal(err) } if _, err := km.Primitive(serializedPubKey); err == nil { t.Errorf("km.Primitive() err = nil, want error") } } func TestECDSAVerifierPrimitiveVerifyFixedToken(t *testing.T) { km, err := registry.GetKeyManager(testECDSAVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSAVerifierKeyType, err) } serializedPubKey, err := createECDSASerializedPublicKey(jepb.JwtEcdsaAlgorithm_ES256, nil /*=kid*/, 0 /*=version*/) if err != nil { t.Fatal(err) } v, err := km.Primitive(serializedPubKey) if err != nil { t.Fatalf("km.Primitive() err = %v, want nil", err) } verifier, ok := v.(*verifierWithKID) if !ok { t.Fatalf("primitive is not a JWT Verifier") } // compact from https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.3 compact := "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q" opts := &ValidatorOpts{ ExpectedIssuer: refString("joe"), FixedNow: time.Unix(12345, 0), } validator, err := NewValidator(opts) if err != nil { t.Fatalf("creating JWTValidator: %v", err) } // verification succeeds because token was valid valid on January 1, 1970 UTC. if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, nil); err != nil { t.Errorf("verifier.VerifyAndDecodeWithKID(kid = nil) err = %v, want nil", err) } // verification with KID fails because token contains no KID. if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, refString("1234")); err == nil { t.Errorf("verifier.VerifyAndDecodeWithKID(kid = '1234') err = nil, want error") } } func TestECDSAVerifierPrimitiveFixedTokenWithKID(t *testing.T) { km, err := registry.GetKeyManager(testECDSAVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSAVerifierKeyType, err) } serializedPubKey, err := createECDSASerializedPublicKey(jepb.JwtEcdsaAlgorithm_ES256, refString("1234"), 0 /*=version*/) if err != nil { t.Fatal(err) } v, err := km.Primitive(serializedPubKey) if err != nil { t.Fatalf("km.Primitive() err = %v, want nil", err) } verifier, ok := v.(*verifierWithKID) if !ok { t.Fatalf("primitive is not a JWT Verifier") } // compact is the claim set '{}' with header '{"alg":"ES256", "kid":"1234"}' // signed with private key as specified in https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.3 compact := "eyJhbGciOiJFUzI1NiIsImtpZCI6IjEyMzQifQ.e30.3jdIhPC4qfXrzE8ds6tyrLoqqmwfXX-CyfP9YG0k_LFeuF5wYPsmgPeUthMFfvPIN63zQ9i-I5BQLJVwaRTTdw" validator, err := NewValidator(&ValidatorOpts{AllowMissingExpiration: true}) if err != nil { t.Fatalf("creating JWTValidator: %v", err) } if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, nil); err != nil { t.Errorf("verifier.VerifyAndDecodeWithKID(kid = nil) err = %v, want nil ", err) } if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, refString("1234")); err == nil { t.Errorf("verifier.VerifyAndDecodeWithKID(kid = 1234) err = nil, want error ") } } ================================================ FILE: go/jwt/jwt_encoding.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "encoding/base64" "encoding/binary" "fmt" "strings" spb "google.golang.org/protobuf/types/known/structpb" tpb "github.com/google/tink/go/proto/tink_go_proto" ) // keyID returns the keyID in big endian format base64 encoded if the key output prefix is of type Tink or nil otherwise. func keyID(keyID uint32, outPrefixType tpb.OutputPrefixType) *string { if outPrefixType != tpb.OutputPrefixType_TINK { return nil } buf := make([]byte, 4) binary.BigEndian.PutUint32(buf, keyID) s := base64Encode(buf) return &s } // createUnsigned creates an unsigned JWT by created the header/payload, encoding them to a websafe base64 encoded string and concatenating. func createUnsigned(rawJWT *RawJWT, algo string, tinkKID *string, customKID *string) (string, error) { if rawJWT == nil { return "", fmt.Errorf("rawJWT is nil") } var typeHeader *string = nil if rawJWT.HasTypeHeader() { th, err := rawJWT.TypeHeader() if err != nil { return "", err } typeHeader = &th } if customKID != nil && tinkKID != nil { return "", fmt.Errorf("TINK Keys are not allowed to have a kid value set") } if tinkKID != nil { customKID = tinkKID } encodedHeader, err := createHeader(algo, typeHeader, customKID) if err != nil { return "", err } payload, err := rawJWT.JSONPayload() if err != nil { return "", err } return dotConcat(encodedHeader, base64Encode(payload)), nil } // combineUnsignedAndSignature combines the token with the raw signature to provide a signed token. func combineUnsignedAndSignature(unsigned string, signature []byte) string { return dotConcat(unsigned, base64Encode(signature)) } // splitSignedCompact extracts the witness and usigned JWT. func splitSignedCompact(compact string) ([]byte, string, error) { i := strings.LastIndex(compact, ".") if i < 0 { return nil, "", fmt.Errorf("invalid token") } witness, err := base64Decode(compact[i+1:]) if err != nil { return nil, "", fmt.Errorf("%q: %v", compact[i+1:], err) } if len(witness) == 0 { return nil, "", fmt.Errorf("empty signature") } unsigned := compact[0:i] if len(unsigned) == 0 { return nil, "", fmt.Errorf("empty content") } if strings.Count(unsigned, ".") != 1 { return nil, "", fmt.Errorf("only tokens in JWS compact serialization formats are supported") } return witness, unsigned, nil } // decodeUnsignedTokenAndValidateHeader verifies the header on an unsigned JWT and decodes the payload into a RawJWT. // Expects the token to be in compact serialization format. The signature should be verified before calling this function. func decodeUnsignedTokenAndValidateHeader(unsigned, algorithm string, tinkKID, customKID *string) (*RawJWT, error) { parts := strings.Split(unsigned, ".") if len(parts) != 2 { return nil, fmt.Errorf("only tokens in JWS compact serialization formats are supported") } jsonHeader, err := base64Decode(parts[0]) if err != nil { return nil, err } header, err := jsonToStruct(jsonHeader) if err != nil { return nil, err } if err := validateHeader(header, algorithm, tinkKID, customKID); err != nil { return nil, err } typeHeader, err := extractTypeHeader(header) if err != nil { return nil, err } jsonPayload, err := base64Decode(parts[1]) if err != nil { return nil, err } return NewRawJWTFromJSON(typeHeader, jsonPayload) } // base64Encode encodes a byte array into a base64 URL safe string with no padding. func base64Encode(content []byte) string { return base64.URLEncoding.WithPadding(base64.NoPadding).EncodeToString(content) } // base64Decode decodes a URL safe base64 encoded string into a byte array ignoring padding. func base64Decode(content string) ([]byte, error) { for _, c := range content { if !isValidURLsafeBase64Char(c) { return nil, fmt.Errorf("invalid encoding") } } return base64.URLEncoding.WithPadding(base64.NoPadding).DecodeString(content) } func isValidURLsafeBase64Char(c rune) bool { return (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || ((c >= '0') && (c <= '9')) || ((c == '-') || (c == '_'))) } func dotConcat(a, b string) string { return fmt.Sprintf("%s.%s", a, b) } func jsonToStruct(jsonPayload []byte) (*spb.Struct, error) { payload := &spb.Struct{} if err := payload.UnmarshalJSON(jsonPayload); err != nil { return nil, err } return payload, nil } func extractTypeHeader(header *spb.Struct) (*string, error) { fields := header.GetFields() if fields == nil { return nil, fmt.Errorf("header contains no fields") } val, ok := fields["typ"] if !ok { return nil, nil } str, ok := val.Kind.(*spb.Value_StringValue) if !ok { return nil, fmt.Errorf("type header isn't a string") } return &str.StringValue, nil } func createHeader(algorithm string, typeHeader, kid *string) (string, error) { header := &spb.Struct{ Fields: map[string]*spb.Value{ "alg": spb.NewStringValue(algorithm), }, } if typeHeader != nil { header.Fields["typ"] = spb.NewStringValue(*typeHeader) } if kid != nil { header.Fields["kid"] = spb.NewStringValue(*kid) } jsonHeader, err := header.MarshalJSON() if err != nil { return "", err } return base64Encode(jsonHeader), nil } func validateHeader(header *spb.Struct, algorithm string, tinkKID, customKID *string) error { fields := header.GetFields() if fields == nil { return fmt.Errorf("header contains no fields") } alg, err := headerStringField(fields, "alg") if err != nil { return err } if alg != algorithm { return fmt.Errorf("invalid alg") } if _, ok := fields["crit"]; ok { return fmt.Errorf("all tokens with crit headers are rejected") } if tinkKID != nil && customKID != nil { return fmt.Errorf("custom_kid can only be set for RAW keys") } _, hasKID := fields["kid"] if tinkKID != nil && !hasKID { return fmt.Errorf("missing kid in header") } if tinkKID != nil { return validateKIDInHeader(fields, tinkKID) } if hasKID && customKID != nil { return validateKIDInHeader(fields, customKID) } return nil } func validateKIDInHeader(fields map[string]*spb.Value, kid *string) error { headerKID, err := headerStringField(fields, "kid") if err != nil { return err } if headerKID != *kid { return fmt.Errorf("invalid kid header") } return nil } func headerStringField(fields map[string]*spb.Value, name string) (string, error) { val, ok := fields[name] if !ok { return "", fmt.Errorf("header is missing %q", name) } str, ok := val.Kind.(*spb.Value_StringValue) if !ok { return "", fmt.Errorf("%q header isn't a string", name) } return str.StringValue, nil } ================================================ FILE: go/jwt/jwt_encoding_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "strings" "testing" "time" "github.com/google/go-cmp/cmp" tpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestKIDForNonTinkKeysIsNil(t *testing.T) { for _, op := range []tpb.OutputPrefixType{ tpb.OutputPrefixType_LEGACY, tpb.OutputPrefixType_RAW, tpb.OutputPrefixType_CRUNCHY} { if kid := keyID(1234, op); kid != nil { t.Errorf("keyID(1234, %q) = %q, want nil", op, *kid) } } } func TestKeyIDForTinkKey(t *testing.T) { want := "GsapRA" kid := keyID(0x1ac6a944, tpb.OutputPrefixType_TINK) if kid == nil { t.Errorf("KeyID(0x1ac6a944, %q) = nil, want %q", tpb.OutputPrefixType_TINK, want) } if kid != nil && !cmp.Equal(*kid, want) { t.Errorf("KeyID(0x1ac6a944, %q) = %q, want %q", tpb.OutputPrefixType_TINK, *kid, want) } } type payloadTestCase struct { tag string rawJWT *RawJWT opts *RawJWTOptions tinkKID *string customKID *string algorithm string } func refString(a string) *string { return &a } func refTime(ts int64) *time.Time { t := time.Unix(ts, 0) return &t } func TestBase64Encode(t *testing.T) { // Examples from: https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.1.1 want := "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" payload := []byte{123, 34, 105, 115, 115, 34, 58, 34, 106, 111, 101, 34, 44, 13, 10, 32, 34, 101, 120, 112, 34, 58, 49, 51, 48, 48, 56, 49, 57, 51, 56, 48, 44, 13, 10, 32, 34, 104, 116, 116, 112, 58, 47, 47, 101, 120, 97, 109, 112, 108, 101, 46, 99, 111, 109, 47, 105, 115, 95, 114, 111, 111, 116, 34, 58, 116, 114, 117, 101, 125} got := base64Encode(payload) if got != want { t.Errorf("base64Encode() got %q want %q", got, want) } } func TestBase64Decode(t *testing.T) { // Examples from: https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.1.1 want := []byte{123, 34, 105, 115, 115, 34, 58, 34, 106, 111, 101, 34, 44, 13, 10, 32, 34, 101, 120, 112, 34, 58, 49, 51, 48, 48, 56, 49, 57, 51, 56, 48, 44, 13, 10, 32, 34, 104, 116, 116, 112, 58, 47, 47, 101, 120, 97, 109, 112, 108, 101, 46, 99, 111, 109, 47, 105, 115, 95, 114, 111, 111, 116, 34, 58, 116, 114, 117, 101, 125} got, err := base64Decode("eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ") if err != nil { t.Errorf("base64Decode() err = %v, want nil", err) } if !cmp.Equal(got, want) { t.Errorf("base64Decode() got %q, want %q", got, want) } } func TestInvalidCharactersFailBase64Decode(t *testing.T) { if _, err := base64Decode("iLA0KIC&hD"); err == nil { t.Errorf("base64Decode() err = nil, want error") } } func TestEncodeStaticHeaderWithPayloadIssuerTokenForSigning(t *testing.T) { opts := &RawJWTOptions{ WithoutExpiration: true, Issuer: refString("tink-issuer"), } // Header 'RS256' alg from: https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.2.1 // Payload: `{"iss":"tink-issuer"}` wantUnsigned := "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJ0aW5rLWlzc3VlciJ9" rawJWT, err := NewRawJWT(opts) if err != nil { t.Fatalf("generating valid RawJWT: %v", err) } unsigned, err := createUnsigned(rawJWT, "RS256", nil, nil) if err != nil { t.Errorf("createUnsigned() err = %v, want nil", err) } if unsigned != wantUnsigned { t.Errorf("got unsigned %q, want %q", unsigned, wantUnsigned) } } func TestEncodeHeaderWithHeaderFieldsAndEmptyPayload(t *testing.T) { type testCase struct { tag string opts *RawJWTOptions wantHeaderSubstring string customKID *string tinkKID *string } for _, tc := range []testCase{ { tag: "type header", opts: &RawJWTOptions{ WithoutExpiration: true, TypeHeader: refString("JWT"), }, wantHeaderSubstring: `"typ":"JWT"`, }, { tag: "custom kid", opts: &RawJWTOptions{ WithoutExpiration: true, }, customKID: refString("custom"), wantHeaderSubstring: `"kid":"custom"`, }, { tag: "tink kid", opts: &RawJWTOptions{ WithoutExpiration: true, }, tinkKID: refString("tink"), wantHeaderSubstring: `"kid":"tink"`, }, } { rawJWT, err := NewRawJWT(tc.opts) if err != nil { t.Fatalf("generating valid RawJWT: %v", err) } unsigned, err := createUnsigned(rawJWT, "RS256", tc.tinkKID, tc.customKID) if err != nil { t.Errorf("createUnsigned() err = %v, want nil", err) } token := strings.Split(unsigned, ".") if len(token) != 2 { t.Errorf("token[0] not encoded in compact serialization format") } header, err := base64Decode(token[0]) if err != nil { t.Errorf("base64Decode(token[0] = %q)", token[0]) } if !strings.Contains(string(header), tc.wantHeaderSubstring) { t.Errorf("header %q, doesn't contain: %q", string(header), tc.wantHeaderSubstring) } wantPayload := "e30" // `{}` if string(token[1]) != wantPayload { t.Errorf("token[1] = %q, want %q", token[1], wantPayload) } } } func TestCreateUnsignedWithNilRawJWTFails(t *testing.T) { if _, err := createUnsigned(nil, "HS256", nil, nil); err == nil { t.Errorf("createUnsigned(rawJWT = nil) err = nil, want error") } } func TestCreateUnsignedCustomAndTinkKIDFail(t *testing.T) { rawJWT, err := NewRawJWT(&RawJWTOptions{WithoutExpiration: true}) if err != nil { t.Fatalf("generating valid RawJWT: %v", err) } if _, err := createUnsigned(rawJWT, "HS256", refString("123"), refString("456")); err == nil { t.Errorf("createUnsigned(tinkKID = 456, customKID = 123) err = nil, want error") } } func TestCombineTokenAndSignature(t *testing.T) { // https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.2.1 payload := "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" signature := []byte{116, 24, 223, 180, 151, 153, 224, 37, 79, 250, 96, 125, 216, 173, 187, 186, 22, 212, 37, 77, 105, 214, 191, 240, 91, 88, 5, 88, 83, 132, 141, 121} token := combineUnsignedAndSignature(payload, signature) want := "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk" if !cmp.Equal(token, want) { t.Errorf("combineUnsignedAndSignature(%q, %q) = %q, want %q", payload, signature, token, want) } } func TestSplitSignedCompactInvalidInputs(t *testing.T) { type testCases struct { tag string token string } for _, tc := range []testCases{ { tag: "empty payload", token: "", }, { tag: "not in compact serialization missing separators", token: "Zm9vYmFyIVRpbms", }, { tag: "not in compact serialization additional separators", token: "Zm9vYmFyIVRpbms.Zm9vYmFyGVRpbms.Zm9vYmFyIVRpbms.Zm9vYmFyINRpbms", }, { tag: "non web safe URL encoding character", token: "Zm9vYmFyIVRpbms.m9vYmFy.Zm&mFyIVRpbms", }, { tag: "no content", token: ".Zm9vYmFyIVRpbms", }, { tag: "no signature", token: "Zm9vYmFyIVRpbms.Zm9vYmFyIVRpbms.", }, { tag: "no signature and no content", token: "..", }, } { t.Run(tc.tag, func(t *testing.T) { if _, _, err := splitSignedCompact(tc.token); err == nil { t.Errorf("splitSignedCompact(%q) err = nil, want error", tc.token) } }) } } func TestSplitSignedCompact(t *testing.T) { // signed token from: https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.1.1 signedToken := "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk" wantSig := []byte{116, 24, 223, 180, 151, 153, 224, 37, 79, 250, 96, 125, 216, 173, 187, 186, 22, 212, 37, 77, 105, 214, 191, 240, 91, 88, 5, 88, 83, 132, 141, 121} wantToken := "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" sig, token, err := splitSignedCompact(signedToken) if err != nil { t.Errorf("splitSignedCompact(%q) err = %v, want nil", signedToken, err) } if !cmp.Equal(sig, wantSig) { t.Errorf("splitSignedCompact() sig = %q, want %q", sig, wantSig) } if token != wantToken { t.Errorf("splitSignedCompact() token = %q, want %q", token, wantToken) } } func TestDecodeValidateInvalidHeaderFailures(t *testing.T) { type testCases struct { tag string header string alg string tinkKID *string customKID *string } for _, tc := range []testCases{ { tag: "invalid JSON header", header: `JiVeQCo`, }, { tag: "contains line feed", header: "eyJ0eXAiOiJKV1Qi\nLA0KICJhbGciOiJIUzI1NiJ9", alg: "HS256", }, { tag: "header contains no fields", header: base64Encode([]byte(`{}`)), }, { tag: "type header not a string", header: base64Encode([]byte(`{"alg":"HS256", "typ":5}`)), alg: "HS256", }, { tag: "wrong algorithm", header: base64Encode([]byte(`{"alg":"HS256"}`)), alg: "HS512", }, { tag: "specyfing custom and tink kid", header: base64Encode([]byte(`{"alg":"HS256", "kid":"tink"}`)), alg: "HS256", tinkKID: refString("tink"), customKID: refString("custom"), }, { tag: "invalid custom kid", header: base64Encode([]byte(`{"alg":"HS256", "kid":"custom"}`)), customKID: refString("notCustom"), alg: "HS256", }, { tag: "invalid tink kid", header: base64Encode([]byte(`{"alg":"HS256", "kid":"tink"}`)), tinkKID: refString("notTink"), alg: "HS256", }, { tag: "specify tink kid and token without kig", header: base64Encode([]byte(`{"alg":"HS256"}`)), tinkKID: refString("notTink"), alg: "HS256", }, { tag: "crit header", header: base64Encode([]byte(`{"alg":"HS256", "crit":"fooBar"}`)), alg: "HS256", }, { tag: "no compact serialization", header: "asd.asd", }, { tag: "invalid UTF16 encoding", header: base64Encode([]byte(`{"alg":"HS256", "typ":"\uD834"}`)), }, } { t.Run(tc.tag, func(t *testing.T) { if _, err := decodeUnsignedTokenAndValidateHeader(dotConcat(tc.header, base64Encode([]byte("{}"))), tc.alg, tc.tinkKID, tc.customKID); err == nil { t.Errorf("decodeUnsignedTokenAndValidateHeader() err = nil, want error") } }) } } func TestDecodeValidateKIDHeader(t *testing.T) { type testCases struct { tag string header string tinkKID *string customKID *string } for _, tc := range []testCases{ { tag: "not kid header field", header: base64Encode([]byte(`{"alg":"HS256"}`)), }, { tag: "validates custom kid", header: base64Encode([]byte(`{"alg":"HS256", "kid":"custom"}`)), customKID: refString("custom"), }, { tag: "validates tink kid", header: base64Encode([]byte(`{"alg":"HS256", "kid":"tink"}`)), tinkKID: refString("tink"), }, { tag: "ignores kid if exists and tink kid isn't specified", header: base64Encode([]byte(`{"alg":"HS256", "kid":"random"}`)), }, { tag: "unkown headers are accepted", header: base64Encode([]byte(`{"alg":"HS256","unknown":"header"}`)), }, } { t.Run(tc.tag, func(t *testing.T) { _, err := decodeUnsignedTokenAndValidateHeader(dotConcat(tc.header, base64Encode([]byte("{}"))), "HS256", tc.tinkKID, tc.customKID) if err != nil { t.Errorf("decodeUnsignedTokenAndValidateHeader() err = %v, want nil", err) } }) } } func TestDecodeVerifyTokenFixedValues(t *testing.T) { header := "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9" // Header example from https://tools.ietf.org/html/rfc7519#section-3.1 payload := "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" // Payload example from https://tools.ietf.org/html/rfc7519#section-3.1 rawJWT, err := decodeUnsignedTokenAndValidateHeader(dotConcat(header, payload), "HS256", nil, nil) if err != nil { t.Errorf("decodeUnsignedTokenAndValidateHeader() err = %v, want nil", err) } iss, err := rawJWT.Issuer() if err != nil { t.Errorf("rawJWT.Issuer() err = %v, want nil", err) } if iss != "joe" { t.Errorf("rawJWT.Issuer() = %q, want joe", iss) } exp, err := rawJWT.ExpiresAt() if err != nil { t.Errorf("rawJWT.ExpiresAt() err = %v, want nil", err) } wantExp := time.Unix(1300819380, 0) if !exp.Equal(wantExp) { t.Errorf("rawJWT.ExpiresAt() = %q, want %q", exp, wantExp) } cc, err := rawJWT.BooleanClaim("http://example.com/is_root") if err != nil { t.Errorf("rawJWT.BooleanClaim('http://example.com/is_root') err = %v want nil", err) } if cc != true { t.Errorf("rawJWT.BooleanClaim('http://example.com/is_root') = %v, want true", cc) } } func TestDecodeVerifyTokenPaylodWithInvalidEndcoding(t *testing.T) { if _, err := decodeUnsignedTokenAndValidateHeader(dotConcat(base64Encode([]byte(`{"alg":"HS256"}`)), "_aSL&%"), "HS256", nil, nil); err == nil { t.Errorf("decodeUnsignedTokenAndValidateHeader() err = nil, want error") } } ================================================ FILE: go/jwt/jwt_hmac_key_manager.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/keyset" macsubtle "github.com/google/tink/go/mac/subtle" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/subtle" jwtmacpb "github.com/google/tink/go/proto/jwt_hmac_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( jwtHMACKeyVersion = 0 jwtHMACTypeURL = "type.googleapis.com/google.crypto.tink.JwtHmacKey" ) // jwtHMACKeyManager is an implementation of the KeyManager interface type jwtHMACKeyManager struct{} // Assert that jwtHMACKeyManager implements the KeyManager interface. var _ registry.KeyManager = (*jwtHMACKeyManager)(nil) var hsAlgToHash = map[jwtmacpb.JwtHmacAlgorithm]string{ jwtmacpb.JwtHmacAlgorithm_HS256: "SHA256", jwtmacpb.JwtHmacAlgorithm_HS384: "SHA384", jwtmacpb.JwtHmacAlgorithm_HS512: "SHA512", } var hsAlgToMinKeySizeBytes = map[jwtmacpb.JwtHmacAlgorithm]int{ jwtmacpb.JwtHmacAlgorithm_HS256: 32, jwtmacpb.JwtHmacAlgorithm_HS384: 48, jwtmacpb.JwtHmacAlgorithm_HS512: 64, } func (km *jwtHMACKeyManager) Primitive(serializedKey []byte) (any, error) { key := &jwtmacpb.JwtHmacKey{} if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, err } if err := km.validateKey(key); err != nil { return nil, err } hashAlg, ok := hsAlgToHash[key.GetAlgorithm()] if !ok { return nil, fmt.Errorf("invalid algorithm: '%v'", key.GetAlgorithm()) } tagSize, err := subtle.GetHashDigestSize(hashAlg) if err != nil { return nil, err } mac, err := macsubtle.NewHMAC(hashAlg, key.GetKeyValue(), tagSize) if err != nil { return nil, err } var kid *string = nil if key.GetCustomKid() != nil { k := key.GetCustomKid().GetValue() kid = &k } return newMACWithKID(mac, key.GetAlgorithm().String(), kid) } func (km *jwtHMACKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { if serializedKeyFormat == nil || len(serializedKeyFormat) == 0 { return nil, fmt.Errorf("no serialized key format") } keyFormat := &jwtmacpb.JwtHmacKeyFormat{} if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, err } if err := km.validateKeyFormat(keyFormat); err != nil { return nil, err } return &jwtmacpb.JwtHmacKey{ Version: jwtHMACKeyVersion, Algorithm: keyFormat.GetAlgorithm(), KeyValue: random.GetRandomBytes(keyFormat.KeySize), }, nil } func (km *jwtHMACKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { key, err := km.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: jwtHMACTypeURL, Value: serializedKey, KeyMaterialType: tinkpb.KeyData_SYMMETRIC, }, nil } // DoesSupport indicates if this key manager supports the given key type. func (km *jwtHMACKeyManager) DoesSupport(keyTypeURL string) bool { return jwtHMACTypeURL == keyTypeURL } // TypeURL returns the key type of keys managed by this key manager. func (km *jwtHMACKeyManager) TypeURL() string { return jwtHMACTypeURL } func (km *jwtHMACKeyManager) validateKey(key *jwtmacpb.JwtHmacKey) error { if key == nil { return fmt.Errorf("key can't be nil") } if err := keyset.ValidateKeyVersion(key.Version, jwtHMACKeyVersion); err != nil { return err } minKeySizeBytes, ok := hsAlgToMinKeySizeBytes[key.GetAlgorithm()] if !ok { return fmt.Errorf("invalid algorithm: '%v'", key.GetAlgorithm()) } if len(key.KeyValue) < minKeySizeBytes { return fmt.Errorf("invalid JwtHmacKey: KeyValue is too short") } return nil } func (km *jwtHMACKeyManager) validateKeyFormat(keyFormat *jwtmacpb.JwtHmacKeyFormat) error { if keyFormat == nil { return fmt.Errorf("key format can't be nil") } minKeySizeBytes, ok := hsAlgToMinKeySizeBytes[keyFormat.GetAlgorithm()] if !ok { return fmt.Errorf("invalid algorithm: '%v'", keyFormat.GetAlgorithm()) } if int(keyFormat.KeySize) < minKeySizeBytes { return fmt.Errorf("invalid JwtHmacKeyFormat: KeySize is too small") } return nil } ================================================ FILE: go/jwt/jwt_hmac_key_manager_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "encoding/base64" "testing" "time" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/subtle/random" jwtmacpb "github.com/google/tink/go/proto/jwt_hmac_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) type jwtKeyManagerTestCase struct { tag string keyFormat *jwtmacpb.JwtHmacKeyFormat key *jwtmacpb.JwtHmacKey } const ( typeURL = "type.googleapis.com/google.crypto.tink.JwtHmacKey" ) func generateKeyFormat(keySize uint32, algorithm jwtmacpb.JwtHmacAlgorithm) *jwtmacpb.JwtHmacKeyFormat { return &jwtmacpb.JwtHmacKeyFormat{ KeySize: keySize, Algorithm: algorithm, } } func TestDoesSupport(t *testing.T) { km, err := registry.GetKeyManager(typeURL) if err != nil { t.Errorf("registry.GetKeyManager(%q) error = %v, want nil", typeURL, err) } if !km.DoesSupport(typeURL) { t.Errorf("km.DoesSupport(%q) = false, want true", typeURL) } } func TestTypeURL(t *testing.T) { km, err := registry.GetKeyManager(typeURL) if err != nil { t.Errorf("registry.GetKeyManager(%q) error = %v, want nil", typeURL, err) } if km.TypeURL() != typeURL { t.Errorf("km.TypeURL() = %q, want %q", km.TypeURL(), typeURL) } } var invalidKeyFormatTestCases = []jwtKeyManagerTestCase{ { tag: "invalid hash algorithm", keyFormat: generateKeyFormat(32, jwtmacpb.JwtHmacAlgorithm_HS_UNKNOWN), }, { tag: "invalid HS256 key size", keyFormat: generateKeyFormat(31, jwtmacpb.JwtHmacAlgorithm_HS256), }, { tag: "invalid HS384 key size", keyFormat: generateKeyFormat(47, jwtmacpb.JwtHmacAlgorithm_HS384), }, { tag: "invalid HS512 key size", keyFormat: generateKeyFormat(63, jwtmacpb.JwtHmacAlgorithm_HS512), }, { tag: "empty key format", keyFormat: &jwtmacpb.JwtHmacKeyFormat{}, }, { tag: "nil key format", keyFormat: nil, }, } func TestNewKeyInvalidFormatFails(t *testing.T) { for _, tc := range invalidKeyFormatTestCases { t.Run(tc.tag, func(t *testing.T) { km, err := registry.GetKeyManager(typeURL) if err != nil { t.Errorf("registry.GetKeyManager(%q): %v", typeURL, err) } serializedKeyFormat, err := proto.Marshal(tc.keyFormat) if err != nil { t.Errorf("serializing key format: %v", err) } if _, err := km.NewKey(serializedKeyFormat); err == nil { t.Errorf("km.NewKey() err = nil, want error") } }) } } func TestNewDataInvalidFormatFails(t *testing.T) { for _, tc := range invalidKeyFormatTestCases { t.Run(tc.tag, func(t *testing.T) { km, err := registry.GetKeyManager(typeURL) if err != nil { t.Errorf("registry.GetKeyManager(%q): %v", typeURL, err) } serializedKeyFormat, err := proto.Marshal(tc.keyFormat) if err != nil { t.Errorf("serializing key format: %v", err) } if _, err := km.NewKeyData(serializedKeyFormat); err == nil { t.Errorf("km.NewKey() err = nil, want error") } }) } } var validKeyFormatTestCases = []jwtKeyManagerTestCase{ { tag: "SHA256 hash algorithm", keyFormat: generateKeyFormat(32, jwtmacpb.JwtHmacAlgorithm_HS256), }, { tag: "SHA384 hash algorithm", keyFormat: generateKeyFormat(48, jwtmacpb.JwtHmacAlgorithm_HS384), }, { tag: "SHA512 hash algorithm", keyFormat: generateKeyFormat(64, jwtmacpb.JwtHmacAlgorithm_HS512), }, } func TestNewKey(t *testing.T) { for _, tc := range validKeyFormatTestCases { t.Run(tc.tag, func(t *testing.T) { km, err := registry.GetKeyManager(typeURL) if err != nil { t.Errorf("registry.GetKeyManager(%q): %v", typeURL, err) } serializedKeyFormat, err := proto.Marshal(tc.keyFormat) if err != nil { t.Errorf("serializing key format: %v", err) } k, err := km.NewKey(serializedKeyFormat) if err != nil { t.Errorf("km.NewKey() err = %v, want nil", err) } key, ok := k.(*jwtmacpb.JwtHmacKey) if !ok { t.Errorf("key isn't of type JwtHmacKey") } if key.Algorithm != tc.keyFormat.Algorithm { t.Errorf("k.Algorithm = %v, want %v", key.Algorithm, tc.keyFormat.Algorithm) } if len(key.KeyValue) != int(tc.keyFormat.KeySize) { t.Errorf("len(key.KeyValue) = %d, want %d", len(key.KeyValue), tc.keyFormat.KeySize) } }) } } func TestNewKeyData(t *testing.T) { for _, tc := range validKeyFormatTestCases { t.Run(tc.tag, func(t *testing.T) { km, err := registry.GetKeyManager(typeURL) if err != nil { t.Errorf("registry.GetKeyManager(%q): %v", typeURL, err) } serializedKeyFormat, err := proto.Marshal(tc.keyFormat) if err != nil { t.Errorf("serializing key format: %v", err) } k, err := km.NewKeyData(serializedKeyFormat) if err != nil { t.Errorf("km.NewKeyData() err = %v, want nil", err) } if k.GetTypeUrl() != typeURL { t.Errorf("k.GetTypeUrl() = %q, want %q", k.GetTypeUrl(), typeURL) } if k.GetKeyMaterialType() != tinkpb.KeyData_SYMMETRIC { t.Errorf("k.GetKeyMaterialType() = %q, want %q", k.GetKeyMaterialType(), tinkpb.KeyData_SYMMETRIC) } }) } } func generateKey(keySize, version uint32, algorithm jwtmacpb.JwtHmacAlgorithm, kid *jwtmacpb.JwtHmacKey_CustomKid) *jwtmacpb.JwtHmacKey { return &jwtmacpb.JwtHmacKey{ KeyValue: random.GetRandomBytes(keySize), Algorithm: algorithm, CustomKid: kid, Version: version, } } func TestGetPrimitiveWithValidKeys(t *testing.T) { rawJWT, err := NewRawJWT(&RawJWTOptions{WithoutExpiration: true, Audiences: []string{"tink-aud"}}) if err != nil { t.Fatalf("NewRawJWT() err = %v, want nil", err) } validator, err := NewValidator(&ValidatorOpts{AllowMissingExpiration: true, ExpectedAudience: refString("tink-aud")}) if err != nil { t.Fatalf("NewValidator() err = %v, want nil", err) } for _, tc := range []jwtKeyManagerTestCase{ { tag: "SHA256 hash algorithm", key: generateKey(32, 0, jwtmacpb.JwtHmacAlgorithm_HS256, nil), }, { tag: "SHA384 hash algorithm", key: generateKey(48, 0, jwtmacpb.JwtHmacAlgorithm_HS384, nil), }, { tag: "SHA512 hash algorithm", key: generateKey(64, 0, jwtmacpb.JwtHmacAlgorithm_HS512, nil), }, { tag: "with custom kid", key: generateKey(64, 0, jwtmacpb.JwtHmacAlgorithm_HS512, &jwtmacpb.JwtHmacKey_CustomKid{Value: "1235"}), }, } { t.Run(tc.tag, func(t *testing.T) { km, err := registry.GetKeyManager(typeURL) if err != nil { t.Errorf("registry.GetKeyManager(%q): %v", typeURL, err) } serializedKey, err := proto.Marshal(tc.key) if err != nil { t.Errorf("serializing key format: %v", err) } p, err := km.Primitive(serializedKey) if err != nil { t.Errorf("km.Primitive() err = %v, want nil", err) } primitive, ok := p.(*macWithKID) if !ok { t.Errorf("primitive isn't of type: macWithKID") } compact, err := primitive.ComputeMACAndEncodeWithKID(rawJWT, nil) if err != nil { t.Errorf("ComputeMACAndEncodeWithKID() err = %v, want nil", err) } verifiedJWT, err := primitive.VerifyMACAndDecodeWithKID(compact, validator, nil) if err != nil { t.Errorf("VerifyMACAndDecodeWithKID() err = %v, want nil", err) } audiences, err := verifiedJWT.Audiences() if err != nil { t.Errorf("verifiedJWT.Audiences() err = %v, want nil", err) } if !cmp.Equal(audiences, []string{"tink-aud"}) { t.Errorf("verifiedJWT.Audiences() = %q, want ['tink-aud']", audiences) } }) } } func TestGetPrimitiveWithInvalidKeys(t *testing.T) { for _, tc := range []jwtKeyManagerTestCase{ { tag: "HS256", key: generateKey(31, 0, jwtmacpb.JwtHmacAlgorithm_HS256, nil), }, { tag: "HS384", key: generateKey(47, 0, jwtmacpb.JwtHmacAlgorithm_HS384, nil), }, { tag: "HS512", key: generateKey(63, 0, jwtmacpb.JwtHmacAlgorithm_HS512, nil), }, } { t.Run(tc.tag, func(t *testing.T) { km, err := registry.GetKeyManager(typeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err=%q, want nil", typeURL, err) } serializedKey, err := proto.Marshal(tc.key) if err != nil { t.Fatalf("proto.Marshal(tc.key) err =%q, want nil", err) } _, err = km.Primitive(serializedKey) if err == nil { t.Error("km.Primitive(serializedKey) err = nil, want error") } }) } } func TestSpecyfingCustomKIDAndTINKKIDFails(t *testing.T) { // key and compact are examples from: https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.1.1 compact := "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk" rawKey, err := base64.URLEncoding.WithPadding(base64.NoPadding).DecodeString("AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow") if err != nil { t.Fatalf("failed decoding test key: %v", err) } key := &jwtmacpb.JwtHmacKey{ KeyValue: rawKey, Algorithm: jwtmacpb.JwtHmacAlgorithm_HS256, CustomKid: &jwtmacpb.JwtHmacKey_CustomKid{Value: "1235"}, Version: 0, } km, err := registry.GetKeyManager(typeURL) if err != nil { t.Errorf("registry.GetKeyManager(%q): %v", typeURL, err) } serializedKey, err := proto.Marshal(key) if err != nil { t.Errorf("serializing key format: %v", err) } p, err := km.Primitive(serializedKey) if err != nil { t.Errorf("km.Primitive() err = %v, want nil", err) } primitive, ok := p.(*macWithKID) if !ok { t.Errorf("primitive isn't of type: macWithKID") } rawJWT, err := NewRawJWT(&RawJWTOptions{WithoutExpiration: true}) if err != nil { t.Errorf("creating new RawJWT: %v", err) } opts := &ValidatorOpts{ ExpectedTypeHeader: refString("JWT"), ExpectedIssuer: refString("joe"), FixedNow: time.Unix(12345, 0), } validator, err := NewValidator(opts) if err != nil { t.Errorf("creating new JWTValidator: %v", err) } if _, err := primitive.ComputeMACAndEncodeWithKID(rawJWT, refString("4566")); err == nil { t.Errorf("primitive.ComputeMACAndEncodeWithKID() err = nil, want error") } if _, err := primitive.VerifyMACAndDecodeWithKID(compact, validator, refString("4566")); err == nil { t.Errorf("primitive.VerifyMACAndDecodeWithKID(kid = 4566) err = nil, want error") } // Verify success without KID if _, err := primitive.VerifyMACAndDecodeWithKID(compact, validator, nil); err != nil { t.Errorf("primitive.VerifyMACAndDecodeWithKID(kid = nil) err = %v, want nil", err) } } func TestGetPrimitiveWithInvalidKeyFails(t *testing.T) { for _, tc := range []jwtKeyManagerTestCase{ { tag: "empty key", key: &jwtmacpb.JwtHmacKey{}, }, { tag: "nil key", key: nil, }, { tag: "unsupported hash algorithm", key: generateKey(32, 0, jwtmacpb.JwtHmacAlgorithm_HS_UNKNOWN, nil), }, { tag: "short key length", key: generateKey(20, 0, jwtmacpb.JwtHmacAlgorithm_HS384, nil), }, { tag: "unsupported version", key: generateKey(48, 1, jwtmacpb.JwtHmacAlgorithm_HS384, nil), }, } { t.Run(tc.tag, func(t *testing.T) { km, err := registry.GetKeyManager(typeURL) if err != nil { t.Errorf("registry.GetKeyManager(%q): %v", typeURL, err) } serializedKey, err := proto.Marshal(tc.key) if err != nil { t.Errorf("serializing key format: %v", err) } if _, err := km.Primitive(serializedKey); err == nil { t.Errorf("km.Primitive() err = nil, want error") } }) } } func TestGeneratesDifferentKeys(t *testing.T) { km, err := registry.GetKeyManager(typeURL) if err != nil { t.Errorf("registry.GetKeyManager(%q): %v", typeURL, err) } serializedKeyFormat, err := proto.Marshal(generateKeyFormat(32, jwtmacpb.JwtHmacAlgorithm_HS256)) if err != nil { t.Errorf("serializing key format: %v", err) } k1, err := km.NewKey(serializedKeyFormat) if err != nil { t.Errorf("km.NewKey() err = %v, want nil", err) } k2, err := km.NewKey(serializedKeyFormat) if err != nil { t.Errorf("km.NewKey() err = %v, want nil", err) } key1, ok := k1.(*jwtmacpb.JwtHmacKey) if !ok { t.Errorf("k1 isn't of type JwtHmacKey") } key2, ok := k2.(*jwtmacpb.JwtHmacKey) if !ok { t.Errorf("k2 isn't of type JwtHmacKey") } if cmp.Equal(key1.GetKeyValue(), key2.GetKeyValue()) { t.Errorf("key material should differ") } } ================================================ FILE: go/jwt/jwt_key_templates.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/internal/tinkerror" jepb "github.com/google/tink/go/proto/jwt_ecdsa_go_proto" jwtmacpb "github.com/google/tink/go/proto/jwt_hmac_go_proto" jrsppb "github.com/google/tink/go/proto/jwt_rsa_ssa_pkcs1_go_proto" jrpsspb "github.com/google/tink/go/proto/jwt_rsa_ssa_pss_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func createJWTHMACKeyTemplate(keySize uint32, algorithm jwtmacpb.JwtHmacAlgorithm, outputPrefixType tinkpb.OutputPrefixType) *tinkpb.KeyTemplate { format := &jwtmacpb.JwtHmacKeyFormat{ KeySize: keySize, Version: jwtHMACKeyVersion, Algorithm: algorithm, } serializedFormat, err := proto.Marshal(format) if err != nil { tinkerror.Fail(fmt.Sprintf("failed to marshal key format: %s", err)) } return &tinkpb.KeyTemplate{ TypeUrl: jwtHMACTypeURL, Value: serializedFormat, OutputPrefixType: outputPrefixType, } } func createJWTECDSAKeyTemplate(algorithm jepb.JwtEcdsaAlgorithm, outputPrefixType tinkpb.OutputPrefixType) *tinkpb.KeyTemplate { format := &jepb.JwtEcdsaKeyFormat{ Version: jwtECDSASignerKeyVersion, Algorithm: algorithm, } serializedFormat, err := proto.Marshal(format) if err != nil { tinkerror.Fail(fmt.Sprintf("failed to marshal key format: %s", err)) } return &tinkpb.KeyTemplate{ TypeUrl: jwtECDSASignerTypeURL, Value: serializedFormat, OutputPrefixType: outputPrefixType, } } func createJWTRSKeyTemplate(algorithm jrsppb.JwtRsaSsaPkcs1Algorithm, modulusSizeInBits uint32, outputPrefixType tinkpb.OutputPrefixType) *tinkpb.KeyTemplate { format := &jrsppb.JwtRsaSsaPkcs1KeyFormat{ Version: jwtRSSignerKeyVersion, Algorithm: algorithm, ModulusSizeInBits: modulusSizeInBits, PublicExponent: []byte{0x01, 0x00, 0x01}, } serializedFormat, err := proto.Marshal(format) if err != nil { tinkerror.Fail(fmt.Sprintf("failed to marshal key format: %s", err)) } return &tinkpb.KeyTemplate{ TypeUrl: jwtRSSignerTypeURL, Value: serializedFormat, OutputPrefixType: outputPrefixType, } } func createJWTPSKeyTemplate(algorithm jrpsspb.JwtRsaSsaPssAlgorithm, modulusSizeInBits uint32, outputPrefixType tinkpb.OutputPrefixType) *tinkpb.KeyTemplate { format := &jrpsspb.JwtRsaSsaPssKeyFormat{ Version: jwtPSSignerKeyVersion, Algorithm: algorithm, PublicExponent: []byte{0x01, 0x00, 0x01}, ModulusSizeInBits: modulusSizeInBits, } serializedFormat, err := proto.Marshal(format) if err != nil { tinkerror.Fail(fmt.Sprintf("failed to marshal key format: %s", err)) } return &tinkpb.KeyTemplate{ TypeUrl: jwtPSSignerTypeURL, Value: serializedFormat, OutputPrefixType: outputPrefixType, } } // HS256Template creates a JWT key template for JWA algorithm "HS256", which is a // HMAC-SHA256 with a 32 byte key. It will set a key ID header "kid" in the token. func HS256Template() *tinkpb.KeyTemplate { return createJWTHMACKeyTemplate(32, jwtmacpb.JwtHmacAlgorithm_HS256, tinkpb.OutputPrefixType_TINK) } // RawHS256Template creates a JWT key template for JWA algorithm "HS256", which is a // HMAC-SHA256 with a 32 byte key. It will not set a key ID header "kid" in the token. func RawHS256Template() *tinkpb.KeyTemplate { return createJWTHMACKeyTemplate(32, jwtmacpb.JwtHmacAlgorithm_HS256, tinkpb.OutputPrefixType_RAW) } // HS384Template creates a JWT key template for JWA algorithm "HS384", which is a // HMAC-SHA384 with a 48 byte key. It will set a key ID header "kid" in the token. func HS384Template() *tinkpb.KeyTemplate { return createJWTHMACKeyTemplate(48, jwtmacpb.JwtHmacAlgorithm_HS384, tinkpb.OutputPrefixType_TINK) } // RawHS384Template creates a JWT key template for JWA algorithm "HS384", which is a // HMAC-SHA384 with a 48 byte key. It will not set a key ID header "kid" in the token. func RawHS384Template() *tinkpb.KeyTemplate { return createJWTHMACKeyTemplate(48, jwtmacpb.JwtHmacAlgorithm_HS384, tinkpb.OutputPrefixType_RAW) } // HS512Template creates a JWT key template for JWA algorithm "HS512", which is a // HMAC-SHA512 with a 64 byte key. It will set a key ID header "kid" in the token. func HS512Template() *tinkpb.KeyTemplate { return createJWTHMACKeyTemplate(64, jwtmacpb.JwtHmacAlgorithm_HS512, tinkpb.OutputPrefixType_TINK) } // RawHS512Template creates a JWT key template for JWA algorithm "HS512", which is a // HMAC-SHA512 with a 64 byte key. It will not set a key ID header "kid" in the token. func RawHS512Template() *tinkpb.KeyTemplate { return createJWTHMACKeyTemplate(64, jwtmacpb.JwtHmacAlgorithm_HS512, tinkpb.OutputPrefixType_RAW) } // ES256Template creates a JWT key template for JWA algorithm "ES256", which is digital // signature with the NIST P-256 curve. It will set a key ID header "kid" in the token. func ES256Template() *tinkpb.KeyTemplate { return createJWTECDSAKeyTemplate(jepb.JwtEcdsaAlgorithm_ES256, tinkpb.OutputPrefixType_TINK) } // RawES256Template creates a JWT key template for JWA algorithm "ES256", which is digital // signature with the NIST P-256 curve. It will not set a key ID header "kid" in the token. func RawES256Template() *tinkpb.KeyTemplate { return createJWTECDSAKeyTemplate(jepb.JwtEcdsaAlgorithm_ES256, tinkpb.OutputPrefixType_RAW) } // ES384Template creates a JWT key template for JWA algorithm "ES384", which is digital // signature with the NIST P-384 curve. It will set a key ID header "kid" in the token. func ES384Template() *tinkpb.KeyTemplate { return createJWTECDSAKeyTemplate(jepb.JwtEcdsaAlgorithm_ES384, tinkpb.OutputPrefixType_TINK) } // RawES384Template creates a JWT key template for JWA algorithm "ES384", which is digital // signature with the NIST P-384 curve. It will not set a key ID header "kid" in the token. func RawES384Template() *tinkpb.KeyTemplate { return createJWTECDSAKeyTemplate(jepb.JwtEcdsaAlgorithm_ES384, tinkpb.OutputPrefixType_RAW) } // ES512Template creates a JWT key template for JWA algorithm "ES512", which is digital // signature with the NIST P-521 curve. It will set a key ID header "kid" in the token. func ES512Template() *tinkpb.KeyTemplate { return createJWTECDSAKeyTemplate(jepb.JwtEcdsaAlgorithm_ES512, tinkpb.OutputPrefixType_TINK) } // RawES512Template creates a JWT key template for JWA algorithm "ES512", which is digital // signature with the NIST P-521 curve. It will not set a key ID header "kid" in the token. func RawES512Template() *tinkpb.KeyTemplate { return createJWTECDSAKeyTemplate(jepb.JwtEcdsaAlgorithm_ES512, tinkpb.OutputPrefixType_RAW) } // RS256_2048_F4_Key_Template creates a JWT key template for JWA algorithm "RS256", which is digital // signature with RSA-SSA-PKCS1 and SHA256. It will set a key ID header "kid" in the token. func RS256_2048_F4_Key_Template() *tinkpb.KeyTemplate { return createJWTRSKeyTemplate(jrsppb.JwtRsaSsaPkcs1Algorithm_RS256, 2048, tinkpb.OutputPrefixType_TINK) } // RawRS256_2048_F4_Key_Template creates a JWT key template for JWA algorithm "RS256", which is digital // signature with RSA-SSA-PKCS1 and SHA256. It will not set a key ID header "kid" in the token. func RawRS256_2048_F4_Key_Template() *tinkpb.KeyTemplate { return createJWTRSKeyTemplate(jrsppb.JwtRsaSsaPkcs1Algorithm_RS256, 2048, tinkpb.OutputPrefixType_RAW) } // RS256_3072_F4_Key_Template creates a JWT key template for JWA algorithm "RS256", which is digital // signature with RSA-SSA-PKCS1 and SHA256. It will set a key ID header "kid" in the token. func RS256_3072_F4_Key_Template() *tinkpb.KeyTemplate { return createJWTRSKeyTemplate(jrsppb.JwtRsaSsaPkcs1Algorithm_RS256, 3072, tinkpb.OutputPrefixType_TINK) } // RawRS256_3072_F4_Key_Template creates a JWT key template for JWA algorithm "RS256", which is digital // signature with RSA-SSA-PKCS1 and SHA256. It will not set a key ID header "kid" in the token. func RawRS256_3072_F4_Key_Template() *tinkpb.KeyTemplate { return createJWTRSKeyTemplate(jrsppb.JwtRsaSsaPkcs1Algorithm_RS256, 3072, tinkpb.OutputPrefixType_RAW) } // RS384_3072_F4_Key_Template creates a JWT key template for JWA algorithm "RS384", which is digital // signature with RSA-SSA-PKCS1 and SHA384. It will set a key ID header "kid" in the token. func RS384_3072_F4_Key_Template() *tinkpb.KeyTemplate { return createJWTRSKeyTemplate(jrsppb.JwtRsaSsaPkcs1Algorithm_RS384, 3072, tinkpb.OutputPrefixType_TINK) } // RawRS384_3072_F4_Key_Template creates a JWT key template for JWA algorithm "RS384", which is digital // signature with RSA-SSA-PKCS1 and SHA384. It will not set a key ID header "kid" in the token. func RawRS384_3072_F4_Key_Template() *tinkpb.KeyTemplate { return createJWTRSKeyTemplate(jrsppb.JwtRsaSsaPkcs1Algorithm_RS384, 3072, tinkpb.OutputPrefixType_RAW) } // RS512_4096_F4_Key_Template creates a JWT key template for JWA algorithm "RS512", which is digital // signature with RSA-SSA-PKCS1 and SHA512. It will set a key ID header "kid" in the token. func RS512_4096_F4_Key_Template() *tinkpb.KeyTemplate { return createJWTRSKeyTemplate(jrsppb.JwtRsaSsaPkcs1Algorithm_RS512, 4096, tinkpb.OutputPrefixType_TINK) } // RawRS512_4096_F4_Key_Template creates a JWT key template for JWA algorithm "RS512", which is digital // signature with RSA-SSA-PKCS1 and SHA512. It will not set a key ID header "kid" in the token. func RawRS512_4096_F4_Key_Template() *tinkpb.KeyTemplate { return createJWTRSKeyTemplate(jrsppb.JwtRsaSsaPkcs1Algorithm_RS512, 4096, tinkpb.OutputPrefixType_RAW) } // PS256_2048_F4_Key_Template creates a JWT key template for JWA algorithm "PS256", which is digital // signature with RSA-SSA-PSS, a 2048 bit modulus, and SHA256. It will set a key ID header "kid" in the token. func PS256_2048_F4_Key_Template() *tinkpb.KeyTemplate { return createJWTPSKeyTemplate(jrpsspb.JwtRsaSsaPssAlgorithm_PS256, 2048, tinkpb.OutputPrefixType_TINK) } // RawPS256_2048_F4_Key_Template creates a JWT key template for JWA algorithm "PS256", which is digital // signature with RSA-SSA-PSS, a 2048 bit modulus, and SHA256. It will not set a key ID header "kid" in the token. func RawPS256_2048_F4_Key_Template() *tinkpb.KeyTemplate { return createJWTPSKeyTemplate(jrpsspb.JwtRsaSsaPssAlgorithm_PS256, 2048, tinkpb.OutputPrefixType_RAW) } // PS256_3072_F4_Key_Template creates a JWT key template for JWA algorithm "PS256", which is digital // signature with RSA-SSA-PSS, a 3072 bit modulus, and SHA256. It will set a key ID header "kid" in the token. func PS256_3072_F4_Key_Template() *tinkpb.KeyTemplate { return createJWTPSKeyTemplate(jrpsspb.JwtRsaSsaPssAlgorithm_PS256, 3072, tinkpb.OutputPrefixType_TINK) } // RawPS256_3072_F4_Key_Template creates a JWT key template for JWA algorithm "PS256", which is digital // signature with RSA-SSA-PSS, a 3072 bit modulus, and SHA256. It will not set a key ID header "kid" in the token. func RawPS256_3072_F4_Key_Template() *tinkpb.KeyTemplate { return createJWTPSKeyTemplate(jrpsspb.JwtRsaSsaPssAlgorithm_PS256, 3072, tinkpb.OutputPrefixType_RAW) } // PS384_3072_F4_Key_Template creates a JWT key template for JWA algorithm "PS384", which is digital // signature with RSA-SSA-PSS, a 3072 bit modulus, and SHA384. It will set a key ID header "kid" in the token. func PS384_3072_F4_Key_Template() *tinkpb.KeyTemplate { return createJWTPSKeyTemplate(jrpsspb.JwtRsaSsaPssAlgorithm_PS384, 3072, tinkpb.OutputPrefixType_TINK) } // RawPS384_3072_F4_Key_Template creates a JWT key template for JWA algorithm "PS384", which is digital // signature with RSA-SSA-PSS, a 3072 bit modulus, and SHA384. It will not set a key ID header "kid" in the token. func RawPS384_3072_F4_Key_Template() *tinkpb.KeyTemplate { return createJWTPSKeyTemplate(jrpsspb.JwtRsaSsaPssAlgorithm_PS384, 3072, tinkpb.OutputPrefixType_RAW) } // PS512_4096_F4_Key_Template creates a JWT key template for JWA algorithm "PS512", which is digital // signature with RSA-SSA-PSS, a 4096 bit modulus, and SHA512. It will set a key ID header "kid" in the token. func PS512_4096_F4_Key_Template() *tinkpb.KeyTemplate { return createJWTPSKeyTemplate(jrpsspb.JwtRsaSsaPssAlgorithm_PS512, 4096, tinkpb.OutputPrefixType_TINK) } // RawPS512_4096_F4_Key_Template creates a JWT key template for JWA algorithm "PS512", which is digital // signature with RSA-SSA-PSS, a 4096 bit modulus, and SHA512. It will not set a key ID header "kid" in the token. func RawPS512_4096_F4_Key_Template() *tinkpb.KeyTemplate { return createJWTPSKeyTemplate(jrpsspb.JwtRsaSsaPssAlgorithm_PS512, 4096, tinkpb.OutputPrefixType_RAW) } ================================================ FILE: go/jwt/jwt_key_templates_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt_test import ( "testing" "time" "github.com/google/tink/go/jwt" "github.com/google/tink/go/keyset" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) type templateTestCase struct { tag string template *tinkpb.KeyTemplate } func TestJWTComputeVerifyMAC(t *testing.T) { expiresAt := time.Now().Add(time.Hour) rawJWT, err := jwt.NewRawJWT(&jwt.RawJWTOptions{ ExpiresAt: &expiresAt, }) if err != nil { t.Errorf("NewRawJWT() err = %v, want nil", err) } for _, tc := range []templateTestCase{ {tag: "JWT_HS256", template: jwt.HS256Template()}, {tag: "JWT_HS384", template: jwt.HS384Template()}, {tag: "JWT_HS512", template: jwt.HS512Template()}, {tag: "JWT_HS256_RAW", template: jwt.RawHS256Template()}, {tag: "JWT_HS384_RAW", template: jwt.RawHS384Template()}, {tag: "JWT_HS512_RAW", template: jwt.RawHS512Template()}, } { t.Run(tc.tag, func(t *testing.T) { handle, err := keyset.NewHandle(tc.template) if err != nil { t.Errorf("keyset.NewHandle() err = %v, want nil", err) } m, err := jwt.NewMAC(handle) if err != nil { t.Errorf("jwt.NewMAC() err = %v, want nil", err) } compact, err := m.ComputeMACAndEncode(rawJWT) if err != nil { t.Errorf("m.ComputeMACAndEncode() err = %v, want nil", err) } validator, err := jwt.NewValidator(&jwt.ValidatorOpts{}) if err != nil { t.Errorf("jwt.NewValidator() err = %v, want nil", err) } if _, err := m.VerifyMACAndDecode(compact, validator); err != nil { t.Errorf("m.VerifyMACAndDecode() err = %v, want nil", err) } // In two hours, VerifyMACAndDecode should fail with an expiration error. inTwoHours := time.Now().Add(time.Hour * 2) futureValidator, err := jwt.NewValidator(&jwt.ValidatorOpts{FixedNow: inTwoHours}) if err != nil { t.Errorf("jwt.NewValidator() err = %v, want nil", err) } _, futureError := m.VerifyMACAndDecode(compact, futureValidator) if futureError == nil { t.Errorf("m.VerifyMACAndDecode(compact, futureValidator) err = nil, want error") } if !jwt.IsExpirationErr(futureError) { t.Errorf("jwt.IsExpirationErr(futureError) = false, want true") } }) } } func TestJWTSignVerify(t *testing.T) { expiresAt := time.Now().Add(time.Hour) rawJWT, err := jwt.NewRawJWT(&jwt.RawJWTOptions{ ExpiresAt: &expiresAt, }) if err != nil { t.Errorf("jwt.NewRawJWT() err = %v, want nil", err) } for _, tc := range []templateTestCase{ {tag: "JWT_ES256", template: jwt.ES256Template()}, {tag: "JWT_ES384", template: jwt.ES384Template()}, {tag: "JWT_ES512", template: jwt.ES512Template()}, {tag: "JWT_ES256_RAW", template: jwt.RawES256Template()}, {tag: "JWT_ES384_RAW", template: jwt.RawES384Template()}, {tag: "JWT_ES512_RAW", template: jwt.RawES512Template()}, {tag: "JWT_RS256_2048_R4", template: jwt.RS256_2048_F4_Key_Template()}, {tag: "JWT_RS256_2048_R4_RAW", template: jwt.RawRS256_2048_F4_Key_Template()}, {tag: "JWT_RS256_3072_R4", template: jwt.RS256_3072_F4_Key_Template()}, {tag: "JWT_RS256_3072_R4_RAW", template: jwt.RawRS256_3072_F4_Key_Template()}, {tag: "JWT_RS384_3072_R4", template: jwt.RS384_3072_F4_Key_Template()}, {tag: "JWT_RS384_3072_R4_RAW", template: jwt.RawRS384_3072_F4_Key_Template()}, {tag: "JWT_RS512_4096_R4", template: jwt.RS512_4096_F4_Key_Template()}, {tag: "JWT_RS512_4096_R4_RAW", template: jwt.RawRS384_3072_F4_Key_Template()}, {tag: "JWT_PS256_2048_R4", template: jwt.PS256_2048_F4_Key_Template()}, {tag: "JWT_PS256_2048_R4_RAW", template: jwt.RawPS256_2048_F4_Key_Template()}, {tag: "JWT_PS256_3072_R4", template: jwt.PS256_3072_F4_Key_Template()}, {tag: "JWT_PS256_3072_R4_RAW", template: jwt.RawPS256_3072_F4_Key_Template()}, {tag: "JWT_PS384_3072_R4", template: jwt.PS384_3072_F4_Key_Template()}, {tag: "JWT_PS384_3072_R4_RAW", template: jwt.RawPS384_3072_F4_Key_Template()}, {tag: "JWT_PS512_4096_R4", template: jwt.PS512_4096_F4_Key_Template()}, {tag: "JWT_PS512_4096_R4_RAW", template: jwt.RawPS384_3072_F4_Key_Template()}, } { t.Run(tc.tag, func(t *testing.T) { kh, err := keyset.NewHandle(tc.template) if err != nil { t.Errorf("keyset.NewHandle() err = %v, want nil", err) } signer, err := jwt.NewSigner(kh) if err != nil { t.Errorf("jwt.NewSigner() err = %v, want nil", err) } compact, err := signer.SignAndEncode(rawJWT) if err != nil { t.Errorf("signer.SignAndEncode() err = %v, want nil", err) } pubkh, err := kh.Public() if err != nil { t.Fatalf("key handle Public() err = %v, want nil", err) } verifier, err := jwt.NewVerifier(pubkh) if err != nil { t.Fatalf("jwt.NewVerifier() err = %v, want nil", err) } validator, err := jwt.NewValidator(&jwt.ValidatorOpts{}) if err != nil { t.Fatalf("jwt.NewValidator() err = %v, want nil", err) } if _, err := verifier.VerifyAndDecode(compact, validator); err != nil { t.Errorf("verifier.VerifyAndDecode() err = %v, want nil", err) } // In two hours, VerifyAndDecode should fail with an expiration error. inTwoHours := time.Now().Add(time.Hour * 2) futureValidator, err := jwt.NewValidator(&jwt.ValidatorOpts{FixedNow: inTwoHours}) if err != nil { t.Errorf("jwt.NewValidator() err = %v, want nil", err) } _, futureError := verifier.VerifyAndDecode(compact, futureValidator) if futureError == nil { t.Errorf("verifier.VerifyAndDecode(compact, futureValidator) err = nil, want error") } if !jwt.IsExpirationErr(futureError) { t.Errorf("jwt.IsExpirationErr(expirationError) = false, want true") } }) } } ================================================ FILE: go/jwt/jwt_mac.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt // MAC is an interface for authenticating and verifying JSON Web Tokens (JWT) with JSON Web Signature (JWS) MAC. // See RFC 7519 and RFC 7515. Security guarantees: similar to Message Authentication Code (MAC). type MAC interface { // Computes a MAC and encodes the raw JWT token and the MAC in the JWS compact serialization format. ComputeMACAndEncode(token *RawJWT) (string, error) // Verifies and decodes a JWT token in the JWS compact serialization format. // // The JWT is validated against the rules in validator. That is, every claim // in validator must also be present in the JWT. For example, if validator // contains an issuer (iss) claim, the JWT must contain an identical claim. // The JWT can contain claims that are NOT in the validator. However, if the // JWT contains a list of audiences, the validator must also contain an // audience in the list. // // If the JWT contains timestamp claims such as expiration (exp), issued_at // (iat) or not_before (nbf), they will also be validated. validator allows to // set a clock skew, to deal with small clock differences among different // machines. VerifyMACAndDecode(compact string, validator *Validator) (*VerifiedJWT, error) } ================================================ FILE: go/jwt/jwt_mac_factory.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "fmt" "github.com/google/tink/go/core/primitiveset" "github.com/google/tink/go/keyset" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // NewMAC generates a new instance of the JWT MAC primitive. func NewMAC(handle *keyset.Handle) (MAC, error) { if handle == nil { return nil, fmt.Errorf("keyset handle can't be nil") } ps, err := handle.PrimitivesWithKeyManager(nil) if err != nil { return nil, fmt.Errorf("jwt_mac_factory: cannot obtain primitive set: %v", err) } return newWrappedJWTMAC(ps) } // wrappedJWTMAC is a JWTMAC implementation that uses the underlying primitive set for JWT MAC. type wrappedJWTMAC struct { ps *primitiveset.PrimitiveSet } var _ MAC = (*wrappedJWTMAC)(nil) func newWrappedJWTMAC(ps *primitiveset.PrimitiveSet) (*wrappedJWTMAC, error) { if _, ok := (ps.Primary.Primitive).(*macWithKID); !ok { return nil, fmt.Errorf("jwt_mac_factory: not a JWT MAC primitive") } for _, primitives := range ps.Entries { for _, p := range primitives { if p.PrefixType != tinkpb.OutputPrefixType_RAW && p.PrefixType != tinkpb.OutputPrefixType_TINK { return nil, fmt.Errorf("jwt_mac_factory: invalid OutputPrefixType: %s", p.PrefixType) } if _, ok := (p.Primitive).(*macWithKID); !ok { return nil, fmt.Errorf("jwt_mac_factory: not a JWT MAC primitive") } } } return &wrappedJWTMAC{ps: ps}, nil } func (w *wrappedJWTMAC) ComputeMACAndEncode(token *RawJWT) (string, error) { primary := w.ps.Primary p, ok := (primary.Primitive).(*macWithKID) if !ok { return "", fmt.Errorf("jwt_mac_factory: not a JWT MAC primitive") } return p.ComputeMACAndEncodeWithKID(token, keyID(primary.KeyID, primary.PrefixType)) } func (w *wrappedJWTMAC) VerifyMACAndDecode(compact string, validator *Validator) (*VerifiedJWT, error) { var interestingErr error for _, s := range w.ps.Entries { for _, e := range s { p, ok := e.Primitive.(*macWithKID) if !ok { return nil, fmt.Errorf("jwt_mac_factory: not a JWT MAC primitive") } verifiedJWT, err := p.VerifyMACAndDecodeWithKID(compact, validator, keyID(e.KeyID, e.PrefixType)) if err == nil { return verifiedJWT, nil } if err != errJwtVerification { // any error that is not the generic errJwtVerification is considered interesting interestingErr = err } } } if interestingErr != nil { return nil, interestingErr } return nil, errJwtVerification } ================================================ FILE: go/jwt/jwt_mac_factory_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt_test import ( "fmt" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/jwt" "github.com/google/tink/go/keyset" "github.com/google/tink/go/signature" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testkeyset" "github.com/google/tink/go/testutil" jwtmacpb "github.com/google/tink/go/proto/jwt_hmac_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func newJWTHMACKey(algorithm jwtmacpb.JwtHmacAlgorithm, kid *jwtmacpb.JwtHmacKey_CustomKid) *jwtmacpb.JwtHmacKey { return &jwtmacpb.JwtHmacKey{ Version: 0, Algorithm: algorithm, KeyValue: random.GetRandomBytes(32), CustomKid: kid, } } func newKeyData(key *jwtmacpb.JwtHmacKey) (*tinkpb.KeyData, error) { serializedKey, err := proto.Marshal(key) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: "type.googleapis.com/google.crypto.tink.JwtHmacKey", Value: serializedKey, KeyMaterialType: tinkpb.KeyData_SYMMETRIC, }, nil } func createJWTMAC(keyData *tinkpb.KeyData, prefixType tinkpb.OutputPrefixType) (jwt.MAC, error) { primaryKey := testutil.NewKey(keyData, tinkpb.KeyStatusType_ENABLED, 42, prefixType) handle, err := testkeyset.NewHandle(testutil.NewKeyset(primaryKey.KeyId, []*tinkpb.Keyset_Key{primaryKey})) if err != nil { return nil, fmt.Errorf("creating keyset handle: %v", err) } return jwt.NewMAC(handle) } func verifyMACCompareSubject(p jwt.MAC, compact string, validator *jwt.Validator, wantSubject string) error { verifiedJWT, err := p.VerifyMACAndDecode(compact, validator) if err != nil { return fmt.Errorf("p.VerifyMACAndDecode() err = %v, want nil", err) } subject, err := verifiedJWT.Subject() if err != nil { return fmt.Errorf("verifiedJWT.Subject() err = %v, want nil", err) } if subject != wantSubject { return fmt.Errorf("verifiedJWT.Subject() = %q, want %q", subject, wantSubject) } return nil } func TestNilKeyHandle(t *testing.T) { if _, err := jwt.NewMAC(nil); err == nil { t.Errorf("TestNilKeyHandle(nil) err = nil, want error") } } func TestFactorySameKeyMaterialWithRawPrefixAndNoKIDShouldIgnoreHeader(t *testing.T) { keyData, err := newKeyData(newJWTHMACKey(jwtmacpb.JwtHmacAlgorithm_HS256, nil)) if err != nil { t.Fatalf("creating NewKeyData: %v", err) } p, err := createJWTMAC(keyData, tinkpb.OutputPrefixType_TINK) if err != nil { t.Fatalf("creating New JWT MAC: %v", err) } rawJWT, err := jwt.NewRawJWT(&jwt.RawJWTOptions{WithoutExpiration: true, Subject: refString("tink-subject")}) if err != nil { t.Errorf("jwt.NewRawJWT() err = %v, want nil", err) } validator, err := jwt.NewValidator(&jwt.ValidatorOpts{AllowMissingExpiration: true}) if err != nil { t.Errorf("jwt.NewValidator() err = %v, want nil", err) } compact, err := p.ComputeMACAndEncode(rawJWT) if err != nil { t.Errorf("p.ComputeMACAndEncode() err = %v, want nil", err) } if err := verifyMACCompareSubject(p, compact, validator, "tink-subject"); err != nil { t.Error(err) } p, err = createJWTMAC(keyData, tinkpb.OutputPrefixType_RAW) if err != nil { t.Fatalf("creating New JWT MAC: %v", err) } if _, err := p.VerifyMACAndDecode(compact, validator); err != nil { t.Errorf("VerifyMACAndDecode() with a RAW key err = %v, want nil", err) } } func TestFactorySameKeyMaterialWithDifferentPrefixAndKIDShouldFailVerification(t *testing.T) { key := newJWTHMACKey(jwtmacpb.JwtHmacAlgorithm_HS256, nil) keyData, err := newKeyData(key) if err != nil { t.Fatalf("creating NewKeyData: %v", err) } p, err := createJWTMAC(keyData, tinkpb.OutputPrefixType_TINK) if err != nil { t.Fatalf("creating New JWT MAC: %v", err) } rawJWT, err := jwt.NewRawJWT(&jwt.RawJWTOptions{WithoutExpiration: true, Subject: refString("tink-subject")}) if err != nil { t.Errorf("jwt.NewRawJWT() err = %v, want nil", err) } validator, err := jwt.NewValidator(&jwt.ValidatorOpts{AllowMissingExpiration: true}) if err != nil { t.Errorf("jwt.NewValidator() err = %v, want nil", err) } compact, err := p.ComputeMACAndEncode(rawJWT) if err != nil { t.Errorf("p.ComputeMACAndEncode() err = %v, want nil", err) } if err := verifyMACCompareSubject(p, compact, validator, "tink-subject"); err != nil { t.Error(err) } key.CustomKid = &jwtmacpb.JwtHmacKey_CustomKid{ Value: "custom-kid", } rawKeyData, err := newKeyData(key) if err != nil { t.Fatalf("creating NewKeyData: %v", err) } p, err = createJWTMAC(rawKeyData, tinkpb.OutputPrefixType_RAW) if err != nil { t.Fatalf("creating New JWT MAC: %v", err) } if _, err := p.VerifyMACAndDecode(compact, validator); err == nil { t.Errorf("VerifyMACAndDecode() with a different KID = nil, want error") } } func TestFactoryDifferentKeyShouldFailValidation(t *testing.T) { keyData, err := newKeyData(newJWTHMACKey(jwtmacpb.JwtHmacAlgorithm_HS256, nil)) if err != nil { t.Fatalf("creating NewKeyData: %v", err) } p, err := createJWTMAC(keyData, tinkpb.OutputPrefixType_TINK) if err != nil { t.Fatalf("creating New JWT MAC: %v", err) } rawJWT, err := jwt.NewRawJWT(&jwt.RawJWTOptions{WithoutExpiration: true, Subject: refString("tink-subject")}) if err != nil { t.Errorf("jwt.NewRawJWT() err = %v, want nil", err) } validator, err := jwt.NewValidator(&jwt.ValidatorOpts{AllowMissingExpiration: true}) if err != nil { t.Errorf("jwt.NewValidator() err = %v, want nil", err) } compact, err := p.ComputeMACAndEncode(rawJWT) if err != nil { t.Errorf("p.ComputeMACAndEncode() err = %v, want nil", err) } if err := verifyMACCompareSubject(p, compact, validator, "tink-subject"); err != nil { t.Error(err) } diffKey := newJWTHMACKey(jwtmacpb.JwtHmacAlgorithm_HS256, nil) diffKeyData, err := newKeyData(diffKey) if err != nil { t.Fatalf("creating NewKeyData: %v", err) } p, err = createJWTMAC(diffKeyData, tinkpb.OutputPrefixType_TINK) if err != nil { t.Fatalf("creating New JWT MAC: %v", err) } if _, err := p.VerifyMACAndDecode(compact, validator); err == nil { t.Errorf("VerifyMACAndDecode() with a different key = nil, want error") } } func TestFactoryWithRAWKeyAndKID(t *testing.T) { key := newJWTHMACKey(jwtmacpb.JwtHmacAlgorithm_HS256, &jwtmacpb.JwtHmacKey_CustomKid{Value: "custom-123"}) keyData, err := newKeyData(key) if err != nil { t.Fatalf("creating NewKeyData: %v", err) } primaryKey := testutil.NewKey(keyData, tinkpb.KeyStatusType_ENABLED, 42, tinkpb.OutputPrefixType_RAW) ks := testutil.NewKeyset(primaryKey.KeyId, []*tinkpb.Keyset_Key{primaryKey}) handle, err := testkeyset.NewHandle(ks) if err != nil { t.Fatalf("creating keyset handle: %v", err) } p, err := jwt.NewMAC(handle) if err != nil { t.Fatalf("creating New JWT MAC: %v", err) } rawJWT, err := jwt.NewRawJWT(&jwt.RawJWTOptions{WithoutExpiration: true, Subject: refString("tink-subject")}) if err != nil { t.Errorf("NewRawJWT() err = %v, want nil", err) } compact, err := p.ComputeMACAndEncode(rawJWT) if err != nil { t.Errorf("p.ComputeMACAndEncode() err = %v, want nil", err) } validator, err := jwt.NewValidator(&jwt.ValidatorOpts{AllowMissingExpiration: true}) if err != nil { t.Errorf("NewValidator() err = %v, want nil", err) } if _, err := p.VerifyMACAndDecode(compact, validator); err != nil { t.Errorf("p.VerifyMACAndDecode() err = %v, want nil", err) } } func TestFactoryWithInvalidPrimitiveSetType(t *testing.T) { kh, err := keyset.NewHandle(signature.ECDSAP256KeyTemplate()) if err != nil { t.Fatalf("failed to build *keyset.Handle: %s", err) } if _, err = jwt.NewMAC(kh); err == nil { t.Fatal("calling NewMAC() err = nil, want error") } } func TestVerifyMACAndDecodeReturnsValidationError(t *testing.T) { keyData, err := newKeyData(newJWTHMACKey(jwtmacpb.JwtHmacAlgorithm_HS256, nil)) if err != nil { t.Fatalf("creating NewKeyData: %v", err) } p, err := createJWTMAC(keyData, tinkpb.OutputPrefixType_TINK) if err != nil { t.Fatalf("creating New JWT MAC: %v", err) } audience := "audience" rawJWT, err := jwt.NewRawJWT(&jwt.RawJWTOptions{Audience: &audience, WithoutExpiration: true}) if err != nil { t.Fatalf("jwt.NewRawJWT() err = %v, want nil", err) } token, err := p.ComputeMACAndEncode(rawJWT) if err != nil { t.Errorf("p.ComputeMACAndEncode() err = %v, want nil", err) } otherAudience := "otherAudience" validator, err := jwt.NewValidator( &jwt.ValidatorOpts{ExpectedAudience: &otherAudience, AllowMissingExpiration: true}) if err != nil { t.Fatalf("jwt.NewValidator() err = %v, want nil", err) } _, err = p.VerifyMACAndDecode(token, validator) wantErr := "validating audience claim: otherAudience not found" if err == nil { t.Errorf("p.VerifyMACAndDecode() err = nil, want %q", wantErr) } if err.Error() != wantErr { t.Errorf("p.VerifyMACAndDecode() err = %q, want %q", err.Error(), wantErr) } } ================================================ FILE: go/jwt/jwt_mac_kid.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "fmt" "github.com/google/tink/go/tink" ) // macWithKID implements the JWTMAC internal interface. type macWithKID struct { tm tink.MAC algorithm string customKID *string } // newMACWithKID creates a new JWTMACwithKID instance. func newMACWithKID(tm tink.MAC, algorithm string, customKID *string) (*macWithKID, error) { if tm == nil { return nil, fmt.Errorf("invalid mac") } return &macWithKID{ tm: tm, algorithm: algorithm, customKID: customKID, }, nil } // ComputeMACAndEncodeWithKID computes a MAC over a jwt token and encodes it using compact serialization. func (jm *macWithKID) ComputeMACAndEncodeWithKID(token *RawJWT, kid *string) (string, error) { unsigned, err := createUnsigned(token, jm.algorithm, kid, jm.customKID) if err != nil { return "", err } tag, err := jm.tm.ComputeMAC([]byte(unsigned)) if err != nil { return "", err } return combineUnsignedAndSignature(unsigned, tag), nil } // VerifyMACAndDecodeWithKID verifies a MAC in a compact serialized JWT and returns a VerifiedJWT or an error. func (jm *macWithKID) VerifyMACAndDecodeWithKID(compact string, verifier *Validator, kid *string) (*VerifiedJWT, error) { tag, content, err := splitSignedCompact(compact) if err != nil { return nil, errJwtVerification } if err := jm.tm.VerifyMAC(tag, []byte(content)); err != nil { return nil, errJwtVerification } rawJWT, err := decodeUnsignedTokenAndValidateHeader(content, jm.algorithm, kid, jm.customKID) if err != nil { return nil, errJwtVerification } if err := verifier.Validate(rawJWT); err != nil { return nil, err } return newVerifiedJWT(rawJWT) } ================================================ FILE: go/jwt/jwt_mac_kid_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "encoding/base64" "fmt" "testing" "time" "github.com/google/tink/go/mac/subtle" ) func TestNewMACwithNilMACFails(t *testing.T) { if _, err := newMACWithKID(nil, "", nil); err == nil { t.Errorf("NewMACWithKID(nil, '', nil) err = nil, want error") } } func createMACwithKID(customKID *string) (*macWithKID, error) { // https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.1.1 key, err := base64.URLEncoding.WithPadding(base64.NoPadding).DecodeString("AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow") if err != nil { return nil, fmt.Errorf("failed parsing test key: %v", err) } mac, err := subtle.NewHMAC("SHA256", key, 32) if err != nil { return nil, err } return newMACWithKID(mac, "HS256", customKID) } func TestCreateAndValidateToken(t *testing.T) { m, err := createMACwithKID(nil) if err != nil { t.Fatalf("creating JWTMACwithKID primitive: %v", err) } rawOpts := &RawJWTOptions{ TypeHeader: refString("typeHeader"), JWTID: refString("123"), WithoutExpiration: true, } rawJWT, err := NewRawJWT(rawOpts) if err != nil { t.Errorf("NewRawJWT() err = %v, want nil", err) } compact, err := m.ComputeMACAndEncodeWithKID(rawJWT, nil) if err != nil { t.Errorf("m.ComputeMACAndEncodeWithKID err = %v, want nil", err) } validatorOps := &ValidatorOpts{ ExpectedTypeHeader: refString("typeHeader"), AllowMissingExpiration: true, } validator, err := NewValidator(validatorOps) if err != nil { t.Errorf("NewValidator err = %v, want nil", err) } verifiedJWT, err := m.VerifyMACAndDecodeWithKID(compact, validator, nil) if err != nil { t.Errorf("m.VerifyMACAndDecodeWithKID() err = %v, want nil", err) } typeHeader, err := verifiedJWT.TypeHeader() if err != nil { t.Errorf("verifiedJWT.TypeHeader() err = %v, want nil", err) } if typeHeader != "typeHeader" { t.Errorf("verifiedJWT.TypeHeader() = %q, want 'typeHeader'", typeHeader) } jwtID, err := verifiedJWT.JWTID() if err != nil { t.Errorf("verifiedJWT.JWTID() err = %v, want nil", err) } if jwtID != "123" { t.Errorf("verifiedJWT.JWTID() = %q, want '123'", jwtID) } validatorOps = &ValidatorOpts{ ExpectedTypeHeader: refString("notTypeHeader"), AllowMissingExpiration: true, } validator, err = NewValidator(validatorOps) if err != nil { t.Errorf("NewValidator err = %v, want nil", err) } if _, err := m.VerifyMACAndDecodeWithKID(compact, validator, nil); err == nil { t.Errorf("m.VerifyMACAndDecodeWithKID() err = nil, want error") } } func TestCreateAndValidateTokenWithKID(t *testing.T) { m, err := createMACwithKID(nil) if err != nil { t.Fatalf("creating JWTMACwithKID primitive: %v", err) } rawOpts := &RawJWTOptions{ TypeHeader: refString("typeHeader"), JWTID: refString("123"), WithoutExpiration: true, } rawJWT, err := NewRawJWT(rawOpts) if err != nil { t.Errorf("NewRawJWT() err = %v, want nil", err) } compact, err := m.ComputeMACAndEncodeWithKID(rawJWT, refString("kid-123")) if err != nil { t.Errorf("m.ComputeMACAndEncodeWithKID err = %v, want nil", err) } opts := &ValidatorOpts{ ExpectedTypeHeader: refString("typeHeader"), AllowMissingExpiration: true, } validator, err := NewValidator(opts) if err != nil { t.Fatalf("creating JWT validator, NewValidator: %v", err) } verifiedJWT, err := m.VerifyMACAndDecodeWithKID(compact, validator, refString("kid-123")) if err != nil { t.Errorf("m.VerifyMACAndDecodeWithKID(kid = kid-123) err = %v, want nil", err) } typeHeader, err := verifiedJWT.TypeHeader() if err != nil { t.Errorf("verifiedJWT.TypeHeader() err = %v, want nil", err) } if typeHeader != *rawOpts.TypeHeader { t.Errorf("verifiedJWT.TypeHeader() = %q, want %q", typeHeader, *rawOpts.TypeHeader) } jwtID, err := verifiedJWT.JWTID() if err != nil { t.Errorf("verifiedJWT.JWTID() err = %v, want nil", err) } if jwtID != *rawOpts.JWTID { t.Errorf("verifiedJWT.JWTID() = %q, want %q", jwtID, *rawOpts.JWTID) } if _, err := m.VerifyMACAndDecodeWithKID(compact, validator, nil); err != nil { t.Errorf("m.VerifyMACAndDecodeWithKID(kid = nil) err = %v, want nil", err) } if _, err := m.VerifyMACAndDecodeWithKID(compact, validator, refString("other-kid")); err == nil { t.Errorf("m.VerifyMACAndDecodeWithKID(kid = 'other-kid') err = nil, want error") } } func TestValidateFixedToken(t *testing.T) { // Key and Token are examples from: https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.1.1 compact := "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk" m, err := createMACwithKID(nil) if err != nil { t.Fatalf("creating JWTMACwithKID primitive: %v", err) } opts := &ValidatorOpts{ ExpectedTypeHeader: refString("JWT"), ExpectedIssuer: refString("joe"), FixedNow: time.Unix(12345, 0), } pastValidator, err := NewValidator(opts) if err != nil { t.Fatalf("creating JWTValidator: %v", err) } // verification succeeds because token was valid valid on January 1, 1970 UTC. verifiedJWT, err := m.VerifyMACAndDecodeWithKID(compact, pastValidator, nil) if err != nil { t.Fatalf("m.VerifyMACAndDecodeWithKID() err = %v, want nil", err) } typeHeader, err := verifiedJWT.TypeHeader() if err != nil { t.Errorf("verifiedJWT.TypeHeader() err = %v, want nil", err) } if typeHeader != *opts.ExpectedTypeHeader { t.Errorf("verifiedJWT.TypeHeader() = %q, want %q", typeHeader, *opts.ExpectedTypeHeader) } issuer, err := verifiedJWT.Issuer() if err != nil { t.Errorf("verifiedJWT.Issuer() err = %v, want nil", err) } if issuer != *opts.ExpectedIssuer { t.Errorf("verifiedJWT.Issuer() = %q, want %q", issuer, *opts.ExpectedIssuer) } boolClaim, err := verifiedJWT.BooleanClaim("http://example.com/is_root") if err != nil { t.Errorf("verifiedJWT.BooleanClaim('http://example.com/is_root') err = %v, want nil", err) } if boolClaim != true { t.Errorf("verifiedJWT.BooleanClaim('http://example.com/is_root') = %q, want true", issuer) } // expired token fails verification opts.FixedNow = time.Now() presentValidator, err := NewValidator(opts) if err != nil { t.Fatalf("creating JWTValidator: %v", err) } _, err = m.VerifyMACAndDecodeWithKID(compact, presentValidator, nil) if err == nil { t.Fatalf("m.VerifyMACAndDecodeWithKID() with expired token err = nil, want error") } if !IsExpirationErr(err) { t.Fatalf("IsExpirationErr(err) for err = %q is false, want true", err) } // tampered token verification fails tamperedCompact := "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXx" if _, err := m.VerifyMACAndDecodeWithKID(tamperedCompact, pastValidator, nil); err == nil { t.Fatalf("m.VerifyMACAndDecodeWithKID() with expired tampered token err = nil, want error") } } func TestInvalidTokens(t *testing.T) { m, err := createMACwithKID(nil) if err != nil { t.Fatalf("creating JWTMACwithKID primitive: %v", err) } validator, err := NewValidator(&ValidatorOpts{}) if err != nil { t.Fatalf("creating JWTValidator: %v", err) } for _, compact := range []string{ "eyJhbGciOiJIUzI1NiJ9.e30.abc.", "eyJhbGciOiJIUzI1NiJ9?.e30.abc", "eyJhbGciOiJIUzI1NiJ9.e30?.abc", "eyJhbGciOiJIUzI1NiJ9.e30.abc?", "eyJhbGciOiJIUzI1NiJ9.e30", "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOi&Jqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk", } { if _, err := m.VerifyMACAndDecodeWithKID(compact, validator, nil); err == nil { t.Errorf("m.VerifyMACAndDecodeWithKID(%q) err = nil, want error", compact) } } } func TestCustomKIDAndTinkPrefixKeyFail(t *testing.T) { m, err := createMACwithKID(refString("custom-kid")) if err != nil { t.Fatalf("creating JWTMACwithKID primitive: %v", err) } rawJWT, err := NewRawJWT(&RawJWTOptions{WithoutExpiration: true}) if err != nil { t.Fatalf("NewRawJWT() err = %v, want nil", err) } if _, err := m.ComputeMACAndEncodeWithKID(rawJWT, refString("tink-kid")); err == nil { t.Errorf("specifying kid when primitive contains kid to ComputeMACAndEncodeWithKID() err = nil, want error") } } ================================================ FILE: go/jwt/jwt_rsa_ssa_pkcs1_signer_key_manager.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "crypto/rand" "crypto/rsa" "errors" "fmt" "math/big" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" internal "github.com/google/tink/go/internal/signature" "github.com/google/tink/go/keyset" jrsppb "github.com/google/tink/go/proto/jwt_rsa_ssa_pkcs1_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( jwtRSSignerKeyVersion = 0 jwtRSSignerTypeURL = "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PrivateKey" ) var ( errRSInvalidPrivateKey = errors.New("invalid JwtRsaSsaPkcs1PrivateKey") errRSInvalidKeyFormat = errors.New("invalid RSA SSA PKCS1 key format") ) // jwtRSSignerKeyManager implements the KeyManager interface // for JWT Signing using the 'RS256', 'RS384', and 'RS512' JWA algorithm. type jwtRSSignerKeyManager struct{} var _ registry.PrivateKeyManager = (*jwtRSSignerKeyManager)(nil) func bytesToBigInt(v []byte) *big.Int { return new(big.Int).SetBytes(v) } func (km *jwtRSSignerKeyManager) Primitive(serializedKey []byte) (any, error) { if serializedKey == nil { return nil, fmt.Errorf("invalid JwtRsaSsaPkcs1PrivateKey") } privKey := &jrsppb.JwtRsaSsaPkcs1PrivateKey{} if err := proto.Unmarshal(serializedKey, privKey); err != nil { return nil, fmt.Errorf("failed to unmarshal RsaSsaPkcs1PrivateKey: %v", err) } if err := validateRSPrivateKey(privKey); err != nil { return nil, err } rsaPrivKey := &rsa.PrivateKey{ PublicKey: rsa.PublicKey{ N: bytesToBigInt(privKey.GetPublicKey().GetN()), E: int(bytesToBigInt(privKey.GetPublicKey().GetE()).Int64()), }, D: bytesToBigInt(privKey.GetD()), Primes: []*big.Int{ bytesToBigInt(privKey.GetP()), bytesToBigInt(privKey.GetQ()), }, } if err := rsaPrivKey.Validate(); err != nil { return nil, err } // Instead of extracting Dp, Dq, and Qinv values from the key proto, // the values must be computed by the Go library. // // See https://pkg.go.dev/crypto/rsa#PrivateKey. rsaPrivKey.Precompute() alg := privKey.GetPublicKey().GetAlgorithm() if err := internal.Validate_RSA_SSA_PKCS1(validRSAlgToHash[alg], rsaPrivKey); err != nil { return nil, err } signer, err := internal.New_RSA_SSA_PKCS1_Signer(validRSAlgToHash[alg], rsaPrivKey) if err != nil { return nil, err } return newSignerWithKID(signer, alg.String(), rsCustomKID(privKey.GetPublicKey())) } func validateRSPrivateKey(privKey *jrsppb.JwtRsaSsaPkcs1PrivateKey) error { if err := keyset.ValidateKeyVersion(privKey.Version, jwtRSSignerKeyVersion); err != nil { return err } if privKey.GetD() == nil || len(privKey.GetPublicKey().GetN()) == 0 || len(privKey.GetPublicKey().GetE()) == 0 || privKey.GetP() == nil || privKey.GetQ() == nil || privKey.GetDp() == nil || privKey.GetDq() == nil || privKey.GetCrt() == nil { return fmt.Errorf("invalid private key") } if err := validateRSPublicKey(privKey.GetPublicKey()); err != nil { return err } return nil } func (km *jwtRSSignerKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errRSInvalidKeyFormat } keyFormat := &jrsppb.JwtRsaSsaPkcs1KeyFormat{} if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, fmt.Errorf("failed to unmarshal JwtRsaSsaPkcs1KeyFormat: %v", err) } if err := keyset.ValidateKeyVersion(keyFormat.GetVersion(), jwtRSSignerKeyVersion); err != nil { return nil, err } if keyFormat.GetVersion() != jwtRSSignerKeyVersion { return nil, fmt.Errorf("invalid key format version: %d", keyFormat.GetVersion()) } rsaKey, err := rsa.GenerateKey(rand.Reader, int(keyFormat.GetModulusSizeInBits())) if err != nil { return nil, err } privKey := &jrsppb.JwtRsaSsaPkcs1PrivateKey{ Version: jwtRSSignerKeyVersion, PublicKey: &jrsppb.JwtRsaSsaPkcs1PublicKey{ Version: jwtRSSignerKeyVersion, Algorithm: keyFormat.GetAlgorithm(), N: rsaKey.PublicKey.N.Bytes(), E: keyFormat.GetPublicExponent(), }, D: rsaKey.D.Bytes(), P: rsaKey.Primes[0].Bytes(), Q: rsaKey.Primes[1].Bytes(), Dp: rsaKey.Precomputed.Dp.Bytes(), Dq: rsaKey.Precomputed.Dq.Bytes(), // In crypto/rsa `Qinv` is the "Chinese Remainder Theorem // coefficient q^(-1) mod p". This corresponds with `Crt` in // the Tink proto. This is unrelated to `CRTValues`, which // contains values specifically for additional primes, which // are not supported by Tink. Crt: rsaKey.Precomputed.Qinv.Bytes(), } if err := validateRSPrivateKey(privKey); err != nil { return nil, err } return privKey, nil } func (km *jwtRSSignerKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { key, err := km.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: jwtRSSignerTypeURL, Value: serializedKey, KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PRIVATE, }, nil } func (km *jwtRSSignerKeyManager) PublicKeyData(serializedPrivKey []byte) (*tinkpb.KeyData, error) { if serializedPrivKey == nil { return nil, errRSInvalidKeyFormat } privKey := &jrsppb.JwtRsaSsaPkcs1PrivateKey{} if err := proto.Unmarshal(serializedPrivKey, privKey); err != nil { return nil, fmt.Errorf("failed to unmarshal JwtRsaSsaPkcs1PrivateKey: %v", err) } if err := validateRSPrivateKey(privKey); err != nil { return nil, err } serializedPubKey, err := proto.Marshal(privKey.GetPublicKey()) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: jwtRSVerifierTypeURL, Value: serializedPubKey, KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC, }, nil } func (km *jwtRSSignerKeyManager) DoesSupport(typeURL string) bool { return jwtRSSignerTypeURL == typeURL } func (km *jwtRSSignerKeyManager) TypeURL() string { return jwtRSSignerTypeURL } ================================================ FILE: go/jwt/jwt_rsa_ssa_pkcs1_signer_key_manager_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "math/big" "testing" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/testing/protocmp" "github.com/google/tink/go/core/registry" jrsppb "github.com/google/tink/go/proto/jwt_rsa_ssa_pkcs1_go_proto" tpb "github.com/google/tink/go/proto/tink_go_proto" ) const testJWTRSSignerKeyType = "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PrivateKey" func makeValidJWTRSPrivateKey() (*jrsppb.JwtRsaSsaPkcs1PrivateKey, error) { // key taken from: https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.2 pubKey, err := makeValidRSPublicKey() if err != nil { return nil, err } d, err := base64Decode( "Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97I" + "jlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0" + "BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn" + "439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYT" + "CBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLh" + "BOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ") if err != nil { return nil, err } p, err := base64Decode( "4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdi" + "YrqBdss1l58BQ3KhooKeQTa9AB0Hw_Py5PJdTJNPY8cQn7ouZ2KKDcmnPG" + "BY5t7yLc1QlQ5xHdwW1VhvKn-nXqhJTBgIPgtldC-KDV5z-y2XDwGUc") if err != nil { return nil, err } q, err := base64Decode( "uQPEfgmVtjL0Uyyx88GZFF1fOunH3-7cepKmtH4pxhtCoHqpWmT8YAmZxa" + "ewHgHAjLYsp1ZSe7zFYHj7C6ul7TjeLQeZD_YwD66t62wDmpe_HlB-TnBA" + "-njbglfIsRLtXlnDzQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdc") if err != nil { return nil, err } dp, err := base64Decode( "BwKfV3Akq5_MFZDFZCnW-wzl-CCo83WoZvnLQwCTeDv8uzluRSnm71I3Q" + "CLdhrqE2e9YkxvuxdBfpT_PI7Yz-FOKnu1R6HsJeDCjn12Sk3vmAktV2zb" + "34MCdy7cpdTh_YVr7tss2u6vneTwrA86rZtu5Mbr1C1XsmvkxHQAdYo0") if err != nil { return nil, err } dq, err := base64Decode( "h_96-mK1R_7glhsum81dZxjTnYynPbZpHziZjeeHcXYsXaaMwkOlODsWa" + "7I9xXDoRwbKgB719rrmI2oKr6N3Do9U0ajaHF-NKJnwgjMd2w9cjz3_-ky" + "NlxAr2v4IKhGNpmM5iIgOS1VZnOZ68m6_pbLBSp3nssTdlqvd0tIiTHU") if err != nil { return nil, err } qi, err := base64Decode( "IYd7DHOhrWvxkwPQsRM2tOgrjbcrfvtQJipd-DlcxyVuuM9sQLdgjVk2o" + "y26F0EmpScGLq2MowX7fhd_QJQ3ydy5cY7YIBi87w93IKLEdfnbJtoOPLU" + "W0ITrJReOgo1cq9SbsxYawBgfp_gh6A5603k2-ZQwVK0JKSHuLFkuQ3U") if err != nil { return nil, err } return &jrsppb.JwtRsaSsaPkcs1PrivateKey{ PublicKey: pubKey, Version: 0, D: d, P: p, Q: q, Dp: dp, Dq: dq, Crt: qi, }, nil } func TestJWTRSSignerKeyManagerDoesSupport(t *testing.T) { km, err := registry.GetKeyManager(testJWTRSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSSignerKeyType, err) } if !km.DoesSupport(testJWTRSSignerKeyType) { t.Errorf("DoesSupport(%q) = false, want true", testJWTRSSignerKeyType) } if km.DoesSupport("invalid.key.type") { t.Errorf("DoesSupport(%q) = true, want false", "invalid.key.type") } } func TestJWTRSSignerKeyManagerTypeURL(t *testing.T) { km, err := registry.GetKeyManager(testJWTRSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSSignerKeyType, err) } if km.TypeURL() != testJWTRSSignerKeyType { t.Errorf("TypeURL() = %v, want = %v", km.TypeURL(), testJWTRSSignerKeyType) } } func TestJWTRSSignerKeyManagerPrimitiveSignAndVerify(t *testing.T) { skm, err := registry.GetKeyManager(testJWTRSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSSignerKeyType, err) } privKey, err := makeValidJWTRSPrivateKey() if err != nil { t.Fatalf("makeValidJWTRSPrivateKey() err = %v, want nil", err) } privKey.PublicKey.CustomKid = nil serializedPrivKey, err := proto.Marshal(privKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } sp, err := skm.Primitive(serializedPrivKey) if err != nil { t.Fatalf("Primitive() err = %v, want nil", err) } signer, ok := sp.(*signerWithKID) if !ok { t.Fatalf("primitive isn't a JWT signer") } unsigned, err := NewRawJWT(&RawJWTOptions{WithoutExpiration: true}) if err != nil { t.Fatalf("NewRawJWT() err = %v, want nil", err) } signed, err := signer.SignAndEncodeWithKID(unsigned, nil) if err != nil { t.Fatalf("SignAndEncodeWithKID(kid = nil) err = %v, want nil", err) } vkm, err := registry.GetKeyManager(testJWTRSVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSVerifierKeyType, err) } serializedPubKey, err := proto.Marshal(privKey.PublicKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } vp, err := vkm.Primitive(serializedPubKey) if err != nil { t.Fatalf("Primitive() err = %v, want nil", err) } verifier, ok := vp.(*verifierWithKID) if !ok { t.Fatalf("primitive isn't a JWT Verifier") } validator, err := NewValidator(&ValidatorOpts{AllowMissingExpiration: true}) if err != nil { t.Fatalf("NewValidator() err = %v, want nil", err) } if _, err := verifier.VerifyAndDecodeWithKID(signed, validator, nil); err != nil { t.Errorf("VerifyAndDecodeWithKID(kid = nil) err = %v, want nil", err) } // Shouldn't contain KID header at all. if _, err := verifier.VerifyAndDecodeWithKID(signed, validator, refString("")); err == nil { t.Errorf("VerifyAndDecodeWithKID(kid = '123') err = nil, want error") } } func TestJWTRSSignerKeyManagerPrimitiveWithInvalidSerializedKeyFails(t *testing.T) { km, err := registry.GetKeyManager(testJWTRSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSSignerKeyType, err) } if _, err := km.Primitive([]byte("invalid_serialization")); err == nil { t.Fatalf("Primitive() err = nil, want error") } } func TestJWTRSSignerKeyManagerPrimitiveSignAndVerifyWithTinkKID(t *testing.T) { skm, err := registry.GetKeyManager(testJWTRSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSSignerKeyType, err) } privKey, err := makeValidJWTRSPrivateKey() if err != nil { t.Fatalf("makeValidJWTRSPrivateKey() err = %v, want nil", err) } privKey.PublicKey.CustomKid = nil serializedPrivKey, err := proto.Marshal(privKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } sp, err := skm.Primitive(serializedPrivKey) if err != nil { t.Fatalf("Primitive() err = %v, want nil", err) } signer, ok := sp.(*signerWithKID) if !ok { t.Fatalf("primitive isn't a JWT signer") } unsigned, err := NewRawJWT(&RawJWTOptions{WithoutExpiration: true}) if err != nil { t.Fatalf("NewRawJWT() err = %v, want nil", err) } signedWithKID, err := signer.SignAndEncodeWithKID(unsigned, refString("555")) if err != nil { t.Fatalf("SignAndEncodeWithKID(kid = '555') err = %v, want nil", err) } vkm, err := registry.GetKeyManager(testJWTRSVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSVerifierKeyType, err) } serializedPubKey, err := proto.Marshal(privKey.PublicKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } vp, err := vkm.Primitive(serializedPubKey) if err != nil { t.Fatalf("Primitive() err = %v, want nil", err) } verifier, ok := vp.(*verifierWithKID) if !ok { t.Fatalf("primitive isn't a JWT Verifier") } validator, err := NewValidator(&ValidatorOpts{AllowMissingExpiration: true}) if err != nil { t.Fatalf("NewValidator() err = %v, want nil", err) } if _, err := verifier.VerifyAndDecodeWithKID(signedWithKID, validator, refString("555")); err != nil { t.Fatalf("VerifyAndDecodeWithKID(kid = '555') err = %v, want nil", err) } if _, err := verifier.VerifyAndDecodeWithKID(signedWithKID, validator, refString("0")); err == nil { t.Fatalf("VerifyAndDecodeWithKID(kid = '0') err = nil, want error") } } func TestJWTRSSignerKeyManagerPrimitiveSignAndVerifyWithCustomKID(t *testing.T) { skm, err := registry.GetKeyManager(testJWTRSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSSignerKeyType, err) } privKey, err := makeValidJWTRSPrivateKey() if err != nil { t.Fatalf("makeValidJWTRSPrivateKey() err = %v, want nil", err) } privKey.PublicKey.CustomKid = &jrsppb.JwtRsaSsaPkcs1PublicKey_CustomKid{ Value: "7843", } serializedPrivKey, err := proto.Marshal(privKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } sp, err := skm.Primitive(serializedPrivKey) if err != nil { t.Fatalf("Primitive() err = %v, want nil", err) } signer, ok := sp.(*signerWithKID) if !ok { t.Fatalf("primitive isn't a JWT signer") } unsigned, err := NewRawJWT(&RawJWTOptions{WithoutExpiration: true}) if err != nil { t.Fatalf("NewRawJWT() err = %v, want nil", err) } signed, err := signer.SignAndEncodeWithKID(unsigned, nil) if err != nil { t.Fatalf("SignAndEncodeWithKID(kid = nil) err = %v, want nil", err) } if _, err := signer.SignAndEncodeWithKID(unsigned, refString("555")); err == nil { t.Fatalf("SignAndEncodeWithKID(kid = '555') err = nil, want error") } vkm, err := registry.GetKeyManager(testJWTRSVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSVerifierKeyType, err) } serializedPubKey, err := proto.Marshal(privKey.PublicKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } vp, err := vkm.Primitive(serializedPubKey) if err != nil { t.Fatalf("Primitive() err = %v, want nil", err) } verifier, ok := vp.(*verifierWithKID) if !ok { t.Fatalf("primitive isn't a JWT Verifier") } validator, err := NewValidator(&ValidatorOpts{AllowMissingExpiration: true}) if err != nil { t.Fatalf("NewValidator() err = %v, want nil", err) } if _, err := verifier.VerifyAndDecodeWithKID(signed, validator, nil); err != nil { t.Fatalf("VerifyAndDecodeWithKID(kid = nil) err = %v, want nil", err) } if _, err := verifier.VerifyAndDecodeWithKID(signed, validator, refString("7843")); err == nil { t.Fatalf("VerifyAndDecodeWithKID(kid = '7843') err = nil, want error") } } func TestJWTRSSignerKeyManagerPrimitiveFailsWithInvalidKey(t *testing.T) { type testCase struct { name string privKey *jrsppb.JwtRsaSsaPkcs1PrivateKey } km, err := registry.GetKeyManager(testJWTRSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSSignerKeyType, err) } validPrivKey, err := makeValidJWTRSPrivateKey() if err != nil { t.Fatalf("makeValidJWTRSPrivateKey() err = %v, want nil", err) } for _, tc := range []testCase{ { name: "nil private key", privKey: nil, }, { name: "empty private key", privKey: &jrsppb.JwtRsaSsaPkcs1PrivateKey{}, }, { name: "invalid private key version", privKey: &jrsppb.JwtRsaSsaPkcs1PrivateKey{ PublicKey: validPrivKey.GetPublicKey(), Version: validPrivKey.GetVersion() + 1, D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid D private key value", privKey: &jrsppb.JwtRsaSsaPkcs1PrivateKey{ PublicKey: validPrivKey.GetPublicKey(), Version: validPrivKey.GetVersion(), D: nil, P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid P private key value", privKey: &jrsppb.JwtRsaSsaPkcs1PrivateKey{ PublicKey: validPrivKey.GetPublicKey(), Version: validPrivKey.GetVersion(), D: validPrivKey.GetD(), P: nil, Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid Q private key value", privKey: &jrsppb.JwtRsaSsaPkcs1PrivateKey{ PublicKey: validPrivKey.GetPublicKey(), Version: validPrivKey.GetVersion(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: nil, Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid pre computed Dp key value", privKey: &jrsppb.JwtRsaSsaPkcs1PrivateKey{ PublicKey: validPrivKey.GetPublicKey(), Version: validPrivKey.GetVersion(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: nil, Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid pre computed Dq key value", privKey: &jrsppb.JwtRsaSsaPkcs1PrivateKey{ PublicKey: validPrivKey.GetPublicKey(), Version: validPrivKey.GetVersion(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: nil, Crt: validPrivKey.GetCrt(), }, }, { name: "invalid pre computed Dq key value", privKey: &jrsppb.JwtRsaSsaPkcs1PrivateKey{ PublicKey: validPrivKey.GetPublicKey(), Version: validPrivKey.GetVersion(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: nil, }, }, { name: "nil public key", privKey: &jrsppb.JwtRsaSsaPkcs1PrivateKey{ PublicKey: nil, Version: validPrivKey.GetVersion(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "empty public key", privKey: &jrsppb.JwtRsaSsaPkcs1PrivateKey{ PublicKey: &jrsppb.JwtRsaSsaPkcs1PublicKey{}, Version: validPrivKey.GetVersion(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid private key version", privKey: &jrsppb.JwtRsaSsaPkcs1PrivateKey{ PublicKey: validPrivKey.GetPublicKey(), Version: validPrivKey.Version + 1, D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid public key version", privKey: &jrsppb.JwtRsaSsaPkcs1PrivateKey{ PublicKey: &jrsppb.JwtRsaSsaPkcs1PublicKey{ Version: validPrivKey.GetPublicKey().GetVersion() + 1, Algorithm: validPrivKey.GetPublicKey().GetAlgorithm(), N: validPrivKey.GetPublicKey().GetN(), E: validPrivKey.GetPublicKey().GetE(), CustomKid: validPrivKey.GetPublicKey().GetCustomKid(), }, Version: validPrivKey.GetVersion(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid algorithm", privKey: &jrsppb.JwtRsaSsaPkcs1PrivateKey{ PublicKey: &jrsppb.JwtRsaSsaPkcs1PublicKey{ Version: validPrivKey.GetPublicKey().GetVersion(), Algorithm: jrsppb.JwtRsaSsaPkcs1Algorithm_RS_UNKNOWN, N: validPrivKey.GetPublicKey().GetN(), E: validPrivKey.GetPublicKey().GetE(), CustomKid: validPrivKey.GetPublicKey().GetCustomKid(), }, Version: validPrivKey.GetVersion(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid modulus", privKey: &jrsppb.JwtRsaSsaPkcs1PrivateKey{ PublicKey: &jrsppb.JwtRsaSsaPkcs1PublicKey{ Version: validPrivKey.GetPublicKey().GetVersion(), Algorithm: validPrivKey.GetPublicKey().GetAlgorithm(), N: []byte{0x00, 0x01}, E: validPrivKey.GetPublicKey().GetE(), CustomKid: validPrivKey.GetPublicKey().GetCustomKid(), }, Version: validPrivKey.GetVersion(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid exponent", privKey: &jrsppb.JwtRsaSsaPkcs1PrivateKey{ PublicKey: &jrsppb.JwtRsaSsaPkcs1PublicKey{ Version: validPrivKey.GetPublicKey().GetVersion(), Algorithm: validPrivKey.GetPublicKey().GetAlgorithm(), N: validPrivKey.GetPublicKey().GetN(), E: []byte{0x07}, CustomKid: validPrivKey.GetPublicKey().GetCustomKid(), }, Version: validPrivKey.GetVersion(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, } { t.Run(tc.name, func(t *testing.T) { serializedPrivKey, err := proto.Marshal(tc.privKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := km.Primitive(serializedPrivKey); err == nil { t.Fatalf("Primitive() err = nil, want error") } if _, err := km.(registry.PrivateKeyManager).PublicKeyData(serializedPrivKey); err == nil { t.Fatalf("PublicKeyData() err = nil, want error") } }) } } func TestJWTRSSignerKeyManagerPrimitiveFailsWithCorruptedKey(t *testing.T) { km, err := registry.GetKeyManager(testJWTRSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSSignerKeyType, err) } validPrivKey, err := makeValidJWTRSPrivateKey() if err != nil { t.Fatalf("makeValidJWTRSPrivateKey() err = %v, want nil", err) } corruptedPrivKey := validPrivKey corruptedPrivKey.P[100] = byte(uint8(corruptedPrivKey.P[100] + 1)) corruptedPrivKey.P[5] = byte(uint8(corruptedPrivKey.P[5] + 1)) serializedPrivKey, err := proto.Marshal(corruptedPrivKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := km.Primitive(serializedPrivKey); err == nil { t.Fatalf("Primitive() err = nil, want error") } } func TestJWTRSSignerKeyManagerPublicKeyData(t *testing.T) { km, err := registry.GetKeyManager(testJWTRSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSSignerKeyType, err) } privKey, err := makeValidJWTRSPrivateKey() if err != nil { t.Fatalf("makeValidJWTRSPrivateKey() err = %v, want nil", err) } serializedPrivKey, err := proto.Marshal(privKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } pubKeyData, err := km.(registry.PrivateKeyManager).PublicKeyData(serializedPrivKey) if err != nil { t.Fatalf("PublicKeyData() err = %v, want nil", err) } if pubKeyData.GetKeyMaterialType() != tpb.KeyData_ASYMMETRIC_PUBLIC { t.Errorf("GetKeyMaterialType() = %v, want %v", pubKeyData.GetKeyMaterialType(), tpb.KeyData_ASYMMETRIC_PUBLIC) } if pubKeyData.GetTypeUrl() != testJWTRSVerifierKeyType { t.Errorf("TypeURL() = %v, want %v", pubKeyData.GetTypeUrl(), testJWTRSVerifierKeyType) } gotPubKey := &jrsppb.JwtRsaSsaPkcs1PublicKey{} if err := proto.Unmarshal(pubKeyData.GetValue(), gotPubKey); err != nil { t.Fatalf("proto.Unmarshal() err = %v, want nil", err) } if !cmp.Equal(gotPubKey, privKey.GetPublicKey(), protocmp.Transform()) { t.Errorf("got = %v, want = %v", gotPubKey, privKey.GetPublicKey()) } } func TestJWTRSSignerKeyManagerPublicKeyDataWithNilKeyFails(t *testing.T) { km, err := registry.GetKeyManager(testJWTRSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSSignerKeyType, err) } if _, err := km.(registry.PrivateKeyManager).PublicKeyData(nil); err == nil { t.Fatalf("PublicKeyData(nil) err = nil, want error") } } func TestJWTRSSignerKeyManagerNewKeyData(t *testing.T) { km, err := registry.GetKeyManager(testJWTRSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSSignerKeyType, err) } type testCase struct { name string keyFormat *jrsppb.JwtRsaSsaPkcs1KeyFormat } for _, tc := range []testCase{ { name: "RS256 with 3072 modulus", keyFormat: &jrsppb.JwtRsaSsaPkcs1KeyFormat{ Version: 0, Algorithm: jrsppb.JwtRsaSsaPkcs1Algorithm_RS256, ModulusSizeInBits: 3072, PublicExponent: []byte{0x01, 0x00, 0x01}, }, }, { name: "RS384 with 3072 modulus", keyFormat: &jrsppb.JwtRsaSsaPkcs1KeyFormat{ Version: 0, Algorithm: jrsppb.JwtRsaSsaPkcs1Algorithm_RS384, ModulusSizeInBits: 3072, PublicExponent: []byte{0x01, 0x00, 0x01}, }, }, { name: "RS512 with 4096 modulus", keyFormat: &jrsppb.JwtRsaSsaPkcs1KeyFormat{ Version: 0, Algorithm: jrsppb.JwtRsaSsaPkcs1Algorithm_RS512, ModulusSizeInBits: 4096, PublicExponent: []byte{0x01, 0x00, 0x01}, }, }, } { t.Run(tc.name, func(t *testing.T) { serializedKeyFormat, err := proto.Marshal(tc.keyFormat) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } keyData, err := km.NewKeyData(serializedKeyFormat) if err != nil { t.Fatalf("NewKeyData() err = %v, want nil", err) } if keyData.GetTypeUrl() != testJWTRSSignerKeyType { t.Errorf("GetTypeURL() = %v, want %v", keyData.GetTypeUrl(), testJWTRSSignerKeyType) } if keyData.GetKeyMaterialType() != tpb.KeyData_ASYMMETRIC_PRIVATE { t.Errorf("GetKeyMaterialType() = %v, want %v", keyData.GetKeyMaterialType(), tpb.KeyData_ASYMMETRIC_PRIVATE) } key := &jrsppb.JwtRsaSsaPkcs1PrivateKey{} if err := proto.Unmarshal(keyData.GetValue(), key); err != nil { t.Fatalf("proto.Unmarshal() err = %v, want nil", err) } pubKey := key.GetPublicKey() got, want := pubKey.GetAlgorithm(), tc.keyFormat.GetAlgorithm() if got != want { t.Errorf("GetAlgorithm() = %v, want %v", got, want) } gotE, wantE := pubKey.GetE(), tc.keyFormat.GetPublicExponent() if !cmp.Equal(gotE, wantE) { t.Errorf("Exponent = %v, want %v", gotE, wantE) } gotMod := new(big.Int).SetBytes(pubKey.GetN()).BitLen() wantMod := int(tc.keyFormat.GetModulusSizeInBits()) if gotMod != wantMod { t.Errorf("Modulus Size in Bits = %d, want %d", gotMod, wantMod) } }) } } func TestJWTRSSignerKeyManagerNewKeyDataFailsWithInvalidFormat(t *testing.T) { type testCase struct { name string keyFormat *jrsppb.JwtRsaSsaPkcs1KeyFormat } km, err := registry.GetKeyManager(testJWTRSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSSignerKeyType, err) } for _, tc := range []testCase{ { name: "nil key format", keyFormat: nil, }, { name: "empty key format", keyFormat: &jrsppb.JwtRsaSsaPkcs1KeyFormat{}, }, { name: "invalid version", keyFormat: &jrsppb.JwtRsaSsaPkcs1KeyFormat{ Algorithm: jrsppb.JwtRsaSsaPkcs1Algorithm_RS256, Version: 1, PublicExponent: []byte{0x01, 0x00, 0x01}, ModulusSizeInBits: 3072, }, }, { name: "invalid algorithm", keyFormat: &jrsppb.JwtRsaSsaPkcs1KeyFormat{ Algorithm: jrsppb.JwtRsaSsaPkcs1Algorithm_RS_UNKNOWN, Version: 0, PublicExponent: []byte{0x01, 0x00, 0x01}, ModulusSizeInBits: 3072, }, }, { name: "invalid public exponent", keyFormat: &jrsppb.JwtRsaSsaPkcs1KeyFormat{ Algorithm: jrsppb.JwtRsaSsaPkcs1Algorithm_RS256, Version: 0, PublicExponent: []byte{0x01}, ModulusSizeInBits: 3072, }, }, { name: "invalid modulus size", keyFormat: &jrsppb.JwtRsaSsaPkcs1KeyFormat{ Algorithm: jrsppb.JwtRsaSsaPkcs1Algorithm_RS256, Version: 0, PublicExponent: []byte{0x01, 0x00, 0x01}, ModulusSizeInBits: 1024, }, }, } { t.Run(tc.name, func(t *testing.T) { serializedKeyFormat, err := proto.Marshal(tc.keyFormat) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := km.NewKeyData(serializedKeyFormat); err == nil { t.Fatalf("NewKeyData() err = nil, want error") } if _, err := km.NewKey(serializedKeyFormat); err == nil { t.Fatalf("NewKey() err = nil, want error") } }) } } func TestJWTRSSignerKeyManagerNewKeyDataFailsWithNilKeyFormat(t *testing.T) { km, err := registry.GetKeyManager(testJWTRSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSSignerKeyType, err) } if _, err := km.NewKeyData(nil); err == nil { t.Fatalf("NewKeyData() err = nil, want error") } if _, err := km.NewKey(nil); err == nil { t.Fatalf("NewKey() err = nil, want error") } } func TestJWTRSSignerKeyManagerNewKeyDataFailsWithInvalidSerializedKeyFormat(t *testing.T) { km, err := registry.GetKeyManager(testJWTRSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSSignerKeyType, err) } if _, err := km.NewKeyData([]byte("invalid_data")); err == nil { t.Fatalf("NewKeyData() err = nil, want error") } if _, err := km.NewKey([]byte("invalid_data")); err == nil { t.Fatalf("NewKey() err = nil, want error") } } ================================================ FILE: go/jwt/jwt_rsa_ssa_pkcs1_verifier_key_manager.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "crypto/rsa" "errors" "fmt" "math/big" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/signature" "github.com/google/tink/go/keyset" jrsppb "github.com/google/tink/go/proto/jwt_rsa_ssa_pkcs1_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( jwtRSVerifierKeyVersion = 0 jwtRSVerifierTypeURL = "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PublicKey" ) var ( errJWTRSVerifierNotImplemented = errors.New("not supported on verifier key manager") ) // jwtRSVerifierKeyManager implements the KeyManager interface // for JWT Verifier using the 'RS256', 'RS384', and 'RS512' JSON Web Algorithms (JWA). type jwtRSVerifierKeyManager struct{} var _ registry.KeyManager = (*jwtRSVerifierKeyManager)(nil) // adding to this map will automatically add to the list of // "accepted" algorithms that will construct valid primitives. var validRSAlgToHash = map[jrsppb.JwtRsaSsaPkcs1Algorithm]string{ jrsppb.JwtRsaSsaPkcs1Algorithm_RS256: "SHA256", jrsppb.JwtRsaSsaPkcs1Algorithm_RS384: "SHA384", jrsppb.JwtRsaSsaPkcs1Algorithm_RS512: "SHA512", } func (km *jwtRSVerifierKeyManager) Primitive(serializedKey []byte) (any, error) { if serializedKey == nil || len(serializedKey) == 0 { return nil, fmt.Errorf("invalid key") } pubKey := &jrsppb.JwtRsaSsaPkcs1PublicKey{} if err := proto.Unmarshal(serializedKey, pubKey); err != nil { return nil, err } if err := validateRSPublicKey(pubKey); err != nil { return nil, err } e := new(big.Int).SetBytes(pubKey.GetE()) if !e.IsInt64() { return nil, fmt.Errorf("public exponent can't fit in a 64 bit integer") } rsaPubKey := &rsa.PublicKey{ N: new(big.Int).SetBytes(pubKey.GetN()), E: int(e.Int64()), } v, err := signature.New_RSA_SSA_PKCS1_Verifier(validRSAlgToHash[pubKey.GetAlgorithm()], rsaPubKey) if err != nil { return nil, err } return newVerifierWithKID(v, pubKey.GetAlgorithm().String(), rsCustomKID(pubKey)) } func (km *jwtRSVerifierKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { return nil, errJWTRSVerifierNotImplemented } func (km *jwtRSVerifierKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { return nil, errJWTRSVerifierNotImplemented } func (km *jwtRSVerifierKeyManager) DoesSupport(typeURL string) bool { return typeURL == jwtRSVerifierTypeURL } func (km *jwtRSVerifierKeyManager) TypeURL() string { return jwtRSVerifierTypeURL } func validateRSPublicKey(pubKey *jrsppb.JwtRsaSsaPkcs1PublicKey) error { if pubKey == nil { return fmt.Errorf("nil public key") } if err := keyset.ValidateKeyVersion(pubKey.Version, jwtRSVerifierKeyVersion); err != nil { return err } if _, ok := validRSAlgToHash[pubKey.GetAlgorithm()]; !ok { return fmt.Errorf("invalid algorithm") } e := new(big.Int).SetBytes(pubKey.GetE()) if !e.IsInt64() { return fmt.Errorf("public exponent can't fit in a 64 bit integer") } if err := signature.RSAValidPublicExponent(int(e.Int64())); err != nil { return err } return signature.RSAValidModulusSizeInBits(new(big.Int).SetBytes(pubKey.GetN()).BitLen()) } func rsCustomKID(pk *jrsppb.JwtRsaSsaPkcs1PublicKey) *string { // nil is an acceptable value for a custom kid. if pk.GetCustomKid() == nil { return nil } k := pk.GetCustomKid().GetValue() return &k } ================================================ FILE: go/jwt/jwt_rsa_ssa_pkcs1_verifier_key_manager_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "fmt" "testing" "time" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/subtle/random" jrsppb "github.com/google/tink/go/proto/jwt_rsa_ssa_pkcs1_go_proto" ) const testJWTRSVerifierKeyType = "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PublicKey" func makeValidRSPublicKey() (*jrsppb.JwtRsaSsaPkcs1PublicKey, error) { // Public key taken from: https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.2 n, err := base64Decode( "ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddx" + "HmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMs" + "D1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSH" + "SXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdV" + "MTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8" + "NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ") if err != nil { return nil, fmt.Errorf("base64 decoding modulus: %v", err) } e, err := base64Decode("AQAB") if err != nil { return nil, fmt.Errorf("base64 decoding public exponent: %v", err) } return &jrsppb.JwtRsaSsaPkcs1PublicKey{ Algorithm: jrsppb.JwtRsaSsaPkcs1Algorithm_RS256, Version: 0, N: n, E: e, CustomKid: nil, }, nil } func TestJWTRSVerifierNotImplemented(t *testing.T) { km, err := registry.GetKeyManager(testJWTRSVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSVerifierKeyType, err) } keyFormat := &jrsppb.JwtRsaSsaPkcs1KeyFormat{ Version: 0, Algorithm: jrsppb.JwtRsaSsaPkcs1Algorithm_RS256, ModulusSizeInBits: 3072, PublicExponent: []byte{0x01, 0x00, 0x01}, // 65537 aka F4 } serializedKeyFormat, err := proto.Marshal(keyFormat) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := km.NewKey(serializedKeyFormat); err == nil { t.Fatalf("km.NewKey() err = nil, want error") } if _, err := km.NewKeyData(serializedKeyFormat); err == nil { t.Fatalf("km.NewKeyData() err = nil, want error") } } func TestJWTRSVerifierDoesSupport(t *testing.T) { km, err := registry.GetKeyManager(testJWTRSVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSVerifierKeyType, err) } if !km.DoesSupport(testJWTRSVerifierKeyType) { t.Errorf("DoesSupport(%q) = false, want true", testJWTRSVerifierKeyType) } if km.DoesSupport("not.the.actual.key.type") { t.Errorf("km.DoesSupport('not.the.actual.key.type') = true, want false") } } func TestJWTRSVerifierTypeURL(t *testing.T) { km, err := registry.GetKeyManager(testJWTRSVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSVerifierKeyType, err) } if km.TypeURL() != testJWTRSVerifierKeyType { t.Errorf("km.TypeURL() = %q, want %q", km.TypeURL(), testJWTRSVerifierKeyType) } } func TestJWTRSVerifierPrimitiveWithInvalidKey(t *testing.T) { type testCase struct { name string pubKey *jrsppb.JwtRsaSsaPkcs1PublicKey } km, err := registry.GetKeyManager(testJWTRSVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSVerifierKeyType, err) } validPubKey, err := makeValidRSPublicKey() if err != nil { t.Fatalf("makeValidRSAPSSPKCS1PrivKey() err = %v, want nil", err) } for _, tc := range []testCase{ { name: "nil public key", pubKey: nil, }, { name: "empty public key", pubKey: &jrsppb.JwtRsaSsaPkcs1PublicKey{}, }, { name: "invalid version", pubKey: &jrsppb.JwtRsaSsaPkcs1PublicKey{ Version: validPubKey.Version + 1, Algorithm: validPubKey.GetAlgorithm(), N: validPubKey.GetN(), E: validPubKey.GetE(), CustomKid: validPubKey.GetCustomKid(), }, }, { name: "invalid algorithm", pubKey: &jrsppb.JwtRsaSsaPkcs1PublicKey{ Algorithm: jrsppb.JwtRsaSsaPkcs1Algorithm_RS_UNKNOWN, Version: validPubKey.Version, N: validPubKey.GetN(), E: validPubKey.GetE(), CustomKid: validPubKey.GetCustomKid(), }, }, { name: "invalid modulus", pubKey: &jrsppb.JwtRsaSsaPkcs1PublicKey{ Version: validPubKey.Version, Algorithm: validPubKey.GetAlgorithm(), N: []byte{0x00}, E: validPubKey.GetE(), CustomKid: validPubKey.GetCustomKid(), }, }, { name: "invalid exponent", pubKey: &jrsppb.JwtRsaSsaPkcs1PublicKey{ Version: validPubKey.Version, Algorithm: validPubKey.GetAlgorithm(), N: validPubKey.GetN(), E: []byte{0x05, 0x04, 0x03}, CustomKid: validPubKey.GetCustomKid(), }, }, { name: "exponent larger than 64 bits", pubKey: &jrsppb.JwtRsaSsaPkcs1PublicKey{ Version: validPubKey.Version, Algorithm: validPubKey.GetAlgorithm(), N: validPubKey.GetN(), E: random.GetRandomBytes(65), CustomKid: validPubKey.GetCustomKid(), }, }, } { t.Run(tc.name, func(t *testing.T) { serializedPubKey, err := proto.Marshal(tc.pubKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := km.Primitive(serializedPubKey); err == nil { t.Errorf("Primitive() err = nil, want error") } }) } } func TestJWTRSVerifierPrimitiveWithInvalidSerializedKey(t *testing.T) { km, err := registry.GetKeyManager(testJWTRSVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSVerifierKeyType, err) } if _, err := km.Primitive([]byte("invalid_serialization")); err == nil { t.Errorf("Primitive() err = nil, want error") } } func TestJWTRSVerifierPrimitiveVerifyFixedToken(t *testing.T) { km, err := registry.GetKeyManager(testJWTRSVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSVerifierKeyType, err) } pubKey, err := makeValidRSPublicKey() if err != nil { t.Fatalf("makeValidRSPublicKey() err = %v, want nil", err) } serializedPubKey, err := proto.Marshal(pubKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } v, err := km.Primitive(serializedPubKey) if err != nil { t.Fatalf("km.Primitive() err = %v, want nil", err) } verifier, ok := v.(*verifierWithKID) if !ok { t.Fatalf("primitive isn't a JWT Verifier") } // compact from https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.2 compact := "eyJhbGciOiJSUzI1NiJ9" + "." + "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt" + "cGxlLmNvbS9pc19yb290Ijp0cnVlfQ" + "." + "cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZmh7" + "AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjbKBYNX4" + "BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHlb1L07Qe7K" + "0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZESc6BfI7noOPqv" + "hJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrB" + "p0igcN_IoypGlUPQGe77Rw" issuer := "joe" validator, err := NewValidator(&ValidatorOpts{ ExpectedIssuer: &issuer, FixedNow: time.Unix(123, 0), }) if err != nil { t.Fatalf("NewValidator() err = %v, want nil", err) } // verification succeeds because token was valid on January 1, 1970 UTC. if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, nil); err != nil { t.Errorf("verifier.VerifyAndDecodeWithKID(kid = nil) err = %v, want nil", err) } // verification with KID fails because token contains no KID. if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, refString("1234")); err == nil { t.Errorf("verifier.VerifyAndDecodeWithKID(kid = '1234') err = nil, want error") } } func TestJWTRSVerifierPrimitiveWithCustomKID(t *testing.T) { km, err := registry.GetKeyManager(testJWTRSVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSVerifierKeyType, err) } pubKey, err := makeValidRSPublicKey() if err != nil { t.Fatalf("makeValidRSPublicKey() err = %v, want nil", err) } pubKey.CustomKid = &jrsppb.JwtRsaSsaPkcs1PublicKey_CustomKid{ Value: "8542", } serializedPubKey, err := proto.Marshal(pubKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } v, err := km.Primitive(serializedPubKey) if err != nil { t.Fatalf("km.Primitive() err = %v, want nil", err) } // similar to https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.2 but with KID 8542 compact := "eyJhbGciOiJSUzI1NiIsImtpZCI6Ijg1NDIifQ" + "." + "eyJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290I" + "jp0cnVlLCJpc3MiOiJqb2UifQ" + "." + "aoQ4f8U_gpIymZM20rbAG2kjw5H5EKruPqPWf_wsEDeKPSjCXzkW016s5UqTz" + "dJ72ZEP05PPZHs4VtZslUXQajLlZNgbK3UJ86QYBrqENq0Pwnhh43TVPi9lrF" + "xOLjSQHAqKXYCy4aflqRdZqP9QqpLqaKtB1mAcDNM25Qx01Ix9FV_ngqI5OLD" + "OYyDp5HoxgMAV-jNR9yq-r31_EBQmmDFHC8K8NJ5XLa4SybbhNlUWi6b1p7sQ" + "NIOcb6RtSGSL73m-FYOo_dOMZ1ZNd7a_JiJe7QZ3-v1Dnw9GBSxvLdtKye2Fu" + "ZHietYMJJczj14KeDbBK6TwmbUM8AacLt-JGg" verifier, ok := v.(*verifierWithKID) if !ok { t.Fatalf("primitive isn't a JWT Verifier") } issuer := "joe" validator, err := NewValidator(&ValidatorOpts{ ExpectedIssuer: &issuer, FixedNow: time.Unix(123, 0), }) if err != nil { t.Fatalf("NewValidator() err = %v, want nil", err) } // verification succeeds because token was valid on January 1, 1970 UTC. if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, nil); err != nil { t.Errorf("verifier.VerifyAndDecodeWithKID(kid = nil) err = %v, want nil", err) } // verification with custom KID and Tink KID fails, there can only be one KID set. if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, refString("8542")); err == nil { t.Errorf("verifier.VerifyAndDecodeWithKID(kid = '8542') err = nil, want error") } pubKey.CustomKid = &jrsppb.JwtRsaSsaPkcs1PublicKey_CustomKid{ Value: "1234", } serializedPubKey, err = proto.Marshal(pubKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } v, err = km.Primitive(serializedPubKey) if err != nil { t.Fatalf("km.Primitive() err = %v, want nil", err) } verifierWrongKID, ok := v.(*verifierWithKID) if !ok { t.Fatalf("primitive isn't a JWT Verifier") } // primitive contains invalid Custom KID which fails verification. if _, err := verifierWrongKID.VerifyAndDecodeWithKID(compact, validator, nil); err == nil { t.Errorf("verifier.VerifyAndDecodeWithKID(kid = nil) err = nil, want error") } } func TestJWTRSVerifierPrimitiveWithTinkKID(t *testing.T) { km, err := registry.GetKeyManager(testJWTRSVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTRSVerifierKeyType, err) } pubKey, err := makeValidRSPublicKey() if err != nil { t.Fatalf("makeValidRSPublicKey() err = %v, want nil", err) } pubKey.CustomKid = nil serializedPubKey, err := proto.Marshal(pubKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } v, err := km.Primitive(serializedPubKey) if err != nil { t.Fatalf("km.Primitive() err = %v, want nil", err) } verifier, ok := v.(*verifierWithKID) if !ok { t.Fatalf("primitive isn't a JWT Verifier") } // similar to https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.2 but with KID 8542 compact := "eyJhbGciOiJSUzI1NiIsImtpZCI6Ijg1NDIifQ" + "." + "eyJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290I" + "jp0cnVlLCJpc3MiOiJqb2UifQ" + "." + "aoQ4f8U_gpIymZM20rbAG2kjw5H5EKruPqPWf_wsEDeKPSjCXzkW016s5UqTz" + "dJ72ZEP05PPZHs4VtZslUXQajLlZNgbK3UJ86QYBrqENq0Pwnhh43TVPi9lrF" + "xOLjSQHAqKXYCy4aflqRdZqP9QqpLqaKtB1mAcDNM25Qx01Ix9FV_ngqI5OLD" + "OYyDp5HoxgMAV-jNR9yq-r31_EBQmmDFHC8K8NJ5XLa4SybbhNlUWi6b1p7sQ" + "NIOcb6RtSGSL73m-FYOo_dOMZ1ZNd7a_JiJe7QZ3-v1Dnw9GBSxvLdtKye2Fu" + "ZHietYMJJczj14KeDbBK6TwmbUM8AacLt-JGg" issuer := "joe" validator, err := NewValidator(&ValidatorOpts{ ExpectedIssuer: &issuer, FixedNow: time.Unix(123, 0), }) if err != nil { t.Fatalf("NewValidator() err = %v, want nil", err) } if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, refString("8542")); err != nil { t.Errorf("verifier.VerifyAndDecodeWithKID(kid = '8542') err = %v, want nil", err) } // verification fails with invalid KID if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, refString("2333")); err == nil { t.Errorf("verifier.VerifyAndDecodeWithKID(kid = '2333') err = nil, want error") } } ================================================ FILE: go/jwt/jwt_rsa_ssa_pss_signer_key_manager.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "crypto/rand" "crypto/rsa" "errors" "fmt" "math/big" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/signature" "github.com/google/tink/go/keyset" jrsppb "github.com/google/tink/go/proto/jwt_rsa_ssa_pss_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( jwtPSSignerKeyVersion = 0 jwtPSSignerTypeURL = "type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPrivateKey" ) var ( errPSInvalidPrivateKey = errors.New("invalid JwtRsaSsaPssPrivateKey") errPSInvalidKeyFormat = errors.New("invalid RSA SSA PSS key format") ) // jwtPSSignerKeyManager implements the KeyManager interface // for JWT Signing using the 'PS256', 'PS384', and 'PS512' JWA algorithm. type jwtPSSignerKeyManager struct{} var _ registry.PrivateKeyManager = (*jwtPSSignerKeyManager)(nil) func (km *jwtPSSignerKeyManager) Primitive(serializedKey []byte) (any, error) { if serializedKey == nil { return nil, fmt.Errorf("invalid JwtRsaSsaPSSPrivateKey") } privKey := &jrsppb.JwtRsaSsaPssPrivateKey{} if err := proto.Unmarshal(serializedKey, privKey); err != nil { return nil, fmt.Errorf("failed to unmarshal JwtRsaSsaPssPrivateKey: %v", err) } if err := validatePSPrivateKey(privKey); err != nil { return nil, err } rsaPrivKey := &rsa.PrivateKey{ PublicKey: rsa.PublicKey{ N: bytesToBigInt(privKey.GetPublicKey().GetN()), E: int(bytesToBigInt(privKey.GetPublicKey().GetE()).Int64()), }, D: bytesToBigInt(privKey.GetD()), Primes: []*big.Int{ bytesToBigInt(privKey.GetP()), bytesToBigInt(privKey.GetQ()), }, } if err := rsaPrivKey.Validate(); err != nil { return nil, err } // Instead of extracting Dp, Dq, and Qinv values from the key proto, // the values must be computed by the Go library. // // See https://pkg.go.dev/crypto/rsa#PrivateKey. rsaPrivKey.Precompute() algorithm := privKey.GetPublicKey().GetAlgorithm() if err := signature.Validate_RSA_SSA_PSS(validPSAlgToHash[algorithm], psAlgToSaltLen[algorithm], rsaPrivKey); err != nil { return nil, err } signer, err := signature.New_RSA_SSA_PSS_Signer(validPSAlgToHash[algorithm], psAlgToSaltLen[algorithm], rsaPrivKey) if err != nil { return nil, err } return newSignerWithKID(signer, algorithm.String(), psCustomKID(privKey.GetPublicKey())) } func validatePSPrivateKey(privKey *jrsppb.JwtRsaSsaPssPrivateKey) error { if err := keyset.ValidateKeyVersion(privKey.Version, jwtPSSignerKeyVersion); err != nil { return err } if privKey.GetD() == nil || len(privKey.GetPublicKey().GetN()) == 0 || len(privKey.GetPublicKey().GetE()) == 0 || privKey.GetP() == nil || privKey.GetQ() == nil || privKey.GetDp() == nil || privKey.GetDq() == nil || privKey.GetCrt() == nil { return fmt.Errorf("invalid private key") } if err := validatePSPublicKey(privKey.GetPublicKey()); err != nil { return err } return nil } func (km *jwtPSSignerKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errPSInvalidKeyFormat } keyFormat := &jrsppb.JwtRsaSsaPssKeyFormat{} if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, fmt.Errorf("failed to unmarshal JwtRsaSsaPssKeyFormat: %v", err) } if err := keyset.ValidateKeyVersion(keyFormat.GetVersion(), jwtPSSignerKeyVersion); err != nil { return nil, err } rsaKey, err := rsa.GenerateKey(rand.Reader, int(keyFormat.GetModulusSizeInBits())) if err != nil { return nil, err } privKey := &jrsppb.JwtRsaSsaPssPrivateKey{ Version: jwtPSSignerKeyVersion, PublicKey: &jrsppb.JwtRsaSsaPssPublicKey{ Version: jwtPSSignerKeyVersion, Algorithm: keyFormat.GetAlgorithm(), N: rsaKey.PublicKey.N.Bytes(), E: keyFormat.GetPublicExponent(), }, D: rsaKey.D.Bytes(), P: rsaKey.Primes[0].Bytes(), Q: rsaKey.Primes[1].Bytes(), Dp: rsaKey.Precomputed.Dp.Bytes(), Dq: rsaKey.Precomputed.Dq.Bytes(), // In crypto/rsa `Qinv` is the "Chinese Remainder Theorem // coefficient q^(-1) mod p". This corresponds with `Crt` in // the Tink proto. This is unrelated to `CRTValues`, which // contains values specifically for additional primes, which // are not supported by Tink. Crt: rsaKey.Precomputed.Qinv.Bytes(), } if err := validatePSPrivateKey(privKey); err != nil { return nil, err } return privKey, nil } func (km *jwtPSSignerKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { key, err := km.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: jwtPSSignerTypeURL, Value: serializedKey, KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PRIVATE, }, nil } func (km *jwtPSSignerKeyManager) PublicKeyData(serializedPrivKey []byte) (*tinkpb.KeyData, error) { if serializedPrivKey == nil { return nil, errPSInvalidKeyFormat } privKey := &jrsppb.JwtRsaSsaPssPrivateKey{} if err := proto.Unmarshal(serializedPrivKey, privKey); err != nil { return nil, fmt.Errorf("failed to unmarshal JwtRsaSsaPssPrivateKey: %v", err) } if err := validatePSPrivateKey(privKey); err != nil { return nil, err } serializedPubKey, err := proto.Marshal(privKey.GetPublicKey()) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: jwtPSVerifierTypeURL, Value: serializedPubKey, KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC, }, nil } func (km *jwtPSSignerKeyManager) DoesSupport(typeURL string) bool { return jwtPSSignerTypeURL == typeURL } func (km *jwtPSSignerKeyManager) TypeURL() string { return jwtPSSignerTypeURL } ================================================ FILE: go/jwt/jwt_rsa_ssa_pss_signer_key_manager_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "math/big" "testing" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/testing/protocmp" "github.com/google/tink/go/core/registry" jrsppb "github.com/google/tink/go/proto/jwt_rsa_ssa_pss_go_proto" tpb "github.com/google/tink/go/proto/tink_go_proto" ) const testJWTPSSignerKeyType = "type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPrivateKey" func makeValidJWTPSPrivateKey() (*jrsppb.JwtRsaSsaPssPrivateKey, error) { // key taken from: https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.2 pubKey, err := makeValidPSPublicKey() if err != nil { return nil, err } d, err := base64Decode( "Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97I" + "jlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0" + "BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn" + "439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYT" + "CBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLh" + "BOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ") if err != nil { return nil, err } p, err := base64Decode( "4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdi" + "YrqBdss1l58BQ3KhooKeQTa9AB0Hw_Py5PJdTJNPY8cQn7ouZ2KKDcmnPG" + "BY5t7yLc1QlQ5xHdwW1VhvKn-nXqhJTBgIPgtldC-KDV5z-y2XDwGUc") if err != nil { return nil, err } q, err := base64Decode( "uQPEfgmVtjL0Uyyx88GZFF1fOunH3-7cepKmtH4pxhtCoHqpWmT8YAmZxa" + "ewHgHAjLYsp1ZSe7zFYHj7C6ul7TjeLQeZD_YwD66t62wDmpe_HlB-TnBA" + "-njbglfIsRLtXlnDzQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdc") if err != nil { return nil, err } dp, err := base64Decode( "BwKfV3Akq5_MFZDFZCnW-wzl-CCo83WoZvnLQwCTeDv8uzluRSnm71I3Q" + "CLdhrqE2e9YkxvuxdBfpT_PI7Yz-FOKnu1R6HsJeDCjn12Sk3vmAktV2zb" + "34MCdy7cpdTh_YVr7tss2u6vneTwrA86rZtu5Mbr1C1XsmvkxHQAdYo0") if err != nil { return nil, err } dq, err := base64Decode( "h_96-mK1R_7glhsum81dZxjTnYynPbZpHziZjeeHcXYsXaaMwkOlODsWa" + "7I9xXDoRwbKgB719rrmI2oKr6N3Do9U0ajaHF-NKJnwgjMd2w9cjz3_-ky" + "NlxAr2v4IKhGNpmM5iIgOS1VZnOZ68m6_pbLBSp3nssTdlqvd0tIiTHU") if err != nil { return nil, err } qi, err := base64Decode( "IYd7DHOhrWvxkwPQsRM2tOgrjbcrfvtQJipd-DlcxyVuuM9sQLdgjVk2o" + "y26F0EmpScGLq2MowX7fhd_QJQ3ydy5cY7YIBi87w93IKLEdfnbJtoOPLU" + "W0ITrJReOgo1cq9SbsxYawBgfp_gh6A5603k2-ZQwVK0JKSHuLFkuQ3U") if err != nil { return nil, err } return &jrsppb.JwtRsaSsaPssPrivateKey{ PublicKey: pubKey, Version: 0, D: d, P: p, Q: q, Dp: dp, Dq: dq, Crt: qi, }, nil } func TestJWTPSSignerKeyManagerDoesSupport(t *testing.T) { km, err := registry.GetKeyManager(testJWTPSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTPSSignerKeyType, err) } if !km.DoesSupport(testJWTPSSignerKeyType) { t.Errorf("DoesSupport(%q) = false, want true", testJWTPSSignerKeyType) } if km.DoesSupport("invalid.key.type") { t.Errorf("DoesSupport(%q) = true, want false", "invalid.key.type") } } func TestJWTPSSignerKeyManagerTypeURL(t *testing.T) { km, err := registry.GetKeyManager(testJWTPSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTPSSignerKeyType, err) } if km.TypeURL() != testJWTPSSignerKeyType { t.Errorf("TypeURL() = %v, want = %v", km.TypeURL(), testJWTPSSignerKeyType) } } func TestJWTPSSignerKeyManagerPritimiveSignVerify(t *testing.T) { skm, err := registry.GetKeyManager(testJWTPSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTPSSignerKeyType, err) } vkm, err := registry.GetKeyManager(testJWTPSVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTPSVerifierKeyType, err) } type testCase struct { tag string customKID *jrsppb.JwtRsaSsaPssPublicKey_CustomKid tinkKID *string } for _, tc := range []testCase{ { tag: "no tink and no custom kid", customKID: nil, tinkKID: nil, }, { tag: "with tink kid and no custom kid", customKID: nil, tinkKID: refString("1234"), }, { tag: "no tink kid and with custom kid", customKID: &jrsppb.JwtRsaSsaPssPublicKey_CustomKid{ Value: "", }, tinkKID: nil, }, } { t.Run(tc.tag, func(t *testing.T) { privKey, err := makeValidJWTPSPrivateKey() if err != nil { t.Fatalf("makeValidJWTPSPrivateKey() err = %v, want nil", err) } privKey.PublicKey.CustomKid = tc.customKID serializedPrivKey, err := proto.Marshal(privKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } sp, err := skm.Primitive(serializedPrivKey) if err != nil { t.Fatalf("Primitive() err = %v, want nil", err) } signer, ok := sp.(*signerWithKID) if !ok { t.Fatalf("primitive isn't a JWT signer") } unsigned, err := NewRawJWT(&RawJWTOptions{WithoutExpiration: true}) if err != nil { t.Fatalf("NewRawJWT() err = %v, want nil", err) } signed, err := signer.SignAndEncodeWithKID(unsigned, tc.tinkKID) if err != nil { t.Fatalf("SignAndEncodeWithKID(kid = nil) err = %v, want nil", err) } serializedPubKey, err := proto.Marshal(privKey.PublicKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } vp, err := vkm.Primitive(serializedPubKey) if err != nil { t.Fatalf("Primitive() err = %v, want nil", err) } verifier, ok := vp.(*verifierWithKID) if !ok { t.Fatalf("primitive isn't a JWT Verifier") } validator, err := NewValidator(&ValidatorOpts{AllowMissingExpiration: true}) if err != nil { t.Fatalf("NewValidator() err = %v, want nil", err) } if _, err := verifier.VerifyAndDecodeWithKID(signed, validator, tc.tinkKID); err != nil { t.Errorf("VerifyAndDecodeWithKID(kid = %v) err = %v, want nil", tc.tinkKID, err) } // wrong KID header should fail. if _, err := verifier.VerifyAndDecodeWithKID(signed, validator, refString("wrong_kid")); err == nil { t.Errorf("VerifyAndDecodeWithKID(kid = 'wrong_kid') err = nil, want error") } // signer/verifier can only have either Tink KID or Custom KID set at a time but not both. if tc.customKID != nil { if _, err := signer.SignAndEncodeWithKID(unsigned, refString("123")); err == nil { t.Fatalf("SignAndEncodeWithKID(kid = '123') err = nil, want error") } if _, err := verifier.VerifyAndDecodeWithKID(signed, validator, refString("123")); err == nil { t.Errorf("VerifyAndDecodeWithKID(kid = '123') err = nil, want error") } } if tc.tinkKID != nil { // The tc.tinkKID value was written into the JWT header in SignAndEncodeWithKID. // It is now ignored if the Tink KID is not set. if _, err := verifier.VerifyAndDecodeWithKID(signed, validator /*=tinkKID*/, nil); err != nil { t.Errorf("VerifyAndDecodeWithKID(kid = nil) err = %v, want nil", err) } } }) } } func TestJWTPSSignerKeyManagerPrimitiveFailsWithCorruptedKey(t *testing.T) { km, err := registry.GetKeyManager(testJWTPSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTPSSignerKeyType, err) } validPrivKey, err := makeValidJWTPSPrivateKey() if err != nil { t.Fatalf("makeValidJWTPSPrivateKey() err = %v, want nil", err) } invalidQ := validPrivKey.GetQ() invalidQ[50] = byte(uint8(invalidQ[50] + 1)) corruptedPrivKey := &jrsppb.JwtRsaSsaPssPrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: validPrivKey.GetPublicKey(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: invalidQ, Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), } serializedPrivKey, err := proto.Marshal(corruptedPrivKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := km.Primitive(serializedPrivKey); err == nil { t.Fatalf("Primitive() err = nil, want error") } } func TestJWTPSSignerKeyManagerPrimitiveFailsWithInvalidKey(t *testing.T) { type testCase struct { name string privKey *jrsppb.JwtRsaSsaPssPrivateKey } km, err := registry.GetKeyManager(testJWTPSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTPSSignerKeyType, err) } validPrivKey, err := makeValidJWTPSPrivateKey() if err != nil { t.Fatalf("makeValidJWTPSPrivateKey() err = %v, want nil", err) } for _, tc := range []testCase{ { name: "nil private key", privKey: nil, }, { name: "empty private key", privKey: &jrsppb.JwtRsaSsaPssPrivateKey{}, }, { name: "invalid private key version", privKey: &jrsppb.JwtRsaSsaPssPrivateKey{ PublicKey: validPrivKey.GetPublicKey(), Version: validPrivKey.GetVersion() + 1, D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid private key D value", privKey: &jrsppb.JwtRsaSsaPssPrivateKey{ PublicKey: validPrivKey.GetPublicKey(), Version: validPrivKey.GetVersion(), D: nil, P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid private key P value", privKey: &jrsppb.JwtRsaSsaPssPrivateKey{ PublicKey: validPrivKey.GetPublicKey(), Version: validPrivKey.GetVersion(), D: validPrivKey.GetD(), P: nil, Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid private key Q value", privKey: &jrsppb.JwtRsaSsaPssPrivateKey{ PublicKey: validPrivKey.GetPublicKey(), Version: validPrivKey.GetVersion(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: nil, Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid pre computed key Dp value", privKey: &jrsppb.JwtRsaSsaPssPrivateKey{ PublicKey: validPrivKey.GetPublicKey(), Version: validPrivKey.GetVersion(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: nil, Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid pre computed key Dq value", privKey: &jrsppb.JwtRsaSsaPssPrivateKey{ PublicKey: validPrivKey.GetPublicKey(), Version: validPrivKey.GetVersion(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: nil, Crt: validPrivKey.GetCrt(), }, }, { name: "invalid pre computed key Crt value", privKey: &jrsppb.JwtRsaSsaPssPrivateKey{ PublicKey: validPrivKey.GetPublicKey(), Version: validPrivKey.GetVersion(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: nil, }, }, { name: "nil public key", privKey: &jrsppb.JwtRsaSsaPssPrivateKey{ PublicKey: nil, Version: validPrivKey.GetVersion(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "empty public key", privKey: &jrsppb.JwtRsaSsaPssPrivateKey{ PublicKey: &jrsppb.JwtRsaSsaPssPublicKey{}, Version: validPrivKey.GetVersion(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid public key version", privKey: &jrsppb.JwtRsaSsaPssPrivateKey{ PublicKey: &jrsppb.JwtRsaSsaPssPublicKey{ Version: validPrivKey.GetPublicKey().GetVersion() + 1, Algorithm: validPrivKey.GetPublicKey().GetAlgorithm(), N: validPrivKey.GetPublicKey().GetN(), E: validPrivKey.GetPublicKey().GetE(), CustomKid: validPrivKey.GetPublicKey().GetCustomKid(), }, Version: validPrivKey.GetVersion(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid algorithm", privKey: &jrsppb.JwtRsaSsaPssPrivateKey{ PublicKey: &jrsppb.JwtRsaSsaPssPublicKey{ Version: validPrivKey.GetPublicKey().GetVersion(), Algorithm: jrsppb.JwtRsaSsaPssAlgorithm_PS_UNKNOWN, N: validPrivKey.GetPublicKey().GetN(), E: validPrivKey.GetPublicKey().GetE(), CustomKid: validPrivKey.GetPublicKey().GetCustomKid(), }, Version: validPrivKey.GetVersion(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid modulus", privKey: &jrsppb.JwtRsaSsaPssPrivateKey{ PublicKey: &jrsppb.JwtRsaSsaPssPublicKey{ Version: validPrivKey.GetPublicKey().GetVersion(), Algorithm: validPrivKey.GetPublicKey().GetAlgorithm(), N: []byte{0x00, 0x01}, E: validPrivKey.GetPublicKey().GetE(), CustomKid: validPrivKey.GetPublicKey().GetCustomKid(), }, Version: validPrivKey.GetVersion(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid exponent", privKey: &jrsppb.JwtRsaSsaPssPrivateKey{ PublicKey: &jrsppb.JwtRsaSsaPssPublicKey{ Version: validPrivKey.GetPublicKey().GetVersion(), Algorithm: validPrivKey.GetPublicKey().GetAlgorithm(), N: validPrivKey.GetPublicKey().GetN(), E: []byte{0x07}, CustomKid: validPrivKey.GetPublicKey().GetCustomKid(), }, Version: validPrivKey.GetVersion(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, } { t.Run(tc.name, func(t *testing.T) { serializedPrivKey, err := proto.Marshal(tc.privKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := km.Primitive(serializedPrivKey); err == nil { t.Fatalf("Primitive() err = nil, want error") } if _, err := km.(registry.PrivateKeyManager).PublicKeyData(serializedPrivKey); err == nil { t.Fatalf("PublicKeyData() err = nil, want error") } }) } } func TestJWTPSSignerKeyManagerPrimitiveFailsWithNilSerializedKey(t *testing.T) { km, err := registry.GetKeyManager(testJWTPSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTPSSignerKeyType, err) } if _, err := km.(registry.PrivateKeyManager).PublicKeyData(nil); err == nil { t.Fatalf("PublicKeyData() err = nil, want error") } } func TestJWTPSSignerKeyManagerPrimitiveFailsWithInvalidSerializedKey(t *testing.T) { km, err := registry.GetKeyManager(testJWTPSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTPSSignerKeyType, err) } if _, err := km.(registry.PrivateKeyManager).PublicKeyData([]byte("invalid_serialization")); err == nil { t.Fatalf("PublicKeyData() err = nil, want error") } } func TestJWTPSSignerKeyManagerPublicKeyData(t *testing.T) { km, err := registry.GetKeyManager(testJWTPSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTPSSignerKeyType, err) } privKey, err := makeValidJWTPSPrivateKey() if err != nil { t.Fatalf("makeValidJWTPSPrivateKey() err = %v, want nil", err) } serializedPrivKey, err := proto.Marshal(privKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } pubKeyData, err := km.(registry.PrivateKeyManager).PublicKeyData(serializedPrivKey) if err != nil { t.Fatalf("PublicKeyData() err = %v, want nil", err) } if pubKeyData.GetKeyMaterialType() != tpb.KeyData_ASYMMETRIC_PUBLIC { t.Errorf("GetKeyMaterialType() = %v, want %v", pubKeyData.GetKeyMaterialType(), tpb.KeyData_ASYMMETRIC_PUBLIC) } if pubKeyData.GetTypeUrl() != testJWTPSVerifierKeyType { t.Errorf("TypeURL() = %v, want %v", pubKeyData.GetTypeUrl(), testJWTPSVerifierKeyType) } gotPubKey := &jrsppb.JwtRsaSsaPssPublicKey{} if err := proto.Unmarshal(pubKeyData.GetValue(), gotPubKey); err != nil { t.Fatalf("proto.Unmarshal() err = %v, want nil", err) } if !cmp.Equal(gotPubKey, privKey.GetPublicKey(), protocmp.Transform()) { t.Errorf("got = %v, want = %v", gotPubKey, privKey.GetPublicKey()) } } func TestJWTPSSignerKeyManagerNewKeyData(t *testing.T) { km, err := registry.GetKeyManager(testJWTPSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTPSSignerKeyType, err) } keyFormat := &jrsppb.JwtRsaSsaPssKeyFormat{ Version: 0, Algorithm: jrsppb.JwtRsaSsaPssAlgorithm_PS256, ModulusSizeInBits: 3072, PublicExponent: []byte{0x01, 0x00, 0x01}, } serializedKeyFormat, err := proto.Marshal(keyFormat) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } keyData, err := km.NewKeyData(serializedKeyFormat) if err != nil { t.Fatalf("NewKeyData() err = %v, want nil", err) } if keyData.GetTypeUrl() != testJWTPSSignerKeyType { t.Errorf("GetTypeURL() = %v, want %v", keyData.GetTypeUrl(), testJWTPSSignerKeyType) } if keyData.GetKeyMaterialType() != tpb.KeyData_ASYMMETRIC_PRIVATE { t.Errorf("GetKeyMaterialType() = %v, want %v", keyData.GetKeyMaterialType(), tpb.KeyData_ASYMMETRIC_PRIVATE) } key := &jrsppb.JwtRsaSsaPssPrivateKey{} if err := proto.Unmarshal(keyData.GetValue(), key); err != nil { t.Fatalf("proto.Unmarshal() err = %v, want nil", err) } pubKey := key.GetPublicKey() if pubKey.GetAlgorithm() != keyFormat.GetAlgorithm() { t.Errorf("GetAlgorithm() = %v, want %v", pubKey.GetAlgorithm(), keyFormat.GetAlgorithm()) } if !cmp.Equal(pubKey.GetE(), keyFormat.GetPublicExponent()) { t.Errorf("Exponent = %v, want %v", pubKey.GetE(), keyFormat.GetPublicExponent()) } modSize := new(big.Int).SetBytes(pubKey.GetN()).BitLen() if modSize != int(keyFormat.GetModulusSizeInBits()) { t.Errorf("Modulus Size in Bits = %d, want %d", modSize, keyFormat.GetModulusSizeInBits()) } } func TestJWTPSSignerKeyManagerNewKeyDataFailsWithInvalidFormat(t *testing.T) { type testCase struct { name string keyFormat *jrsppb.JwtRsaSsaPssKeyFormat } km, err := registry.GetKeyManager(testJWTPSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTPSSignerKeyType, err) } for _, tc := range []testCase{ { name: "nil key format", keyFormat: nil, }, { name: "empty key format", keyFormat: &jrsppb.JwtRsaSsaPssKeyFormat{}, }, { name: "invalid version", keyFormat: &jrsppb.JwtRsaSsaPssKeyFormat{ Algorithm: jrsppb.JwtRsaSsaPssAlgorithm_PS256, Version: 1, PublicExponent: []byte{0x01, 0x00, 0x01}, ModulusSizeInBits: 3072, }, }, { name: "invalid algorithm", keyFormat: &jrsppb.JwtRsaSsaPssKeyFormat{ Algorithm: jrsppb.JwtRsaSsaPssAlgorithm_PS_UNKNOWN, Version: 0, PublicExponent: []byte{0x01, 0x00, 0x01}, ModulusSizeInBits: 3072, }, }, { name: "invalid public exponent", keyFormat: &jrsppb.JwtRsaSsaPssKeyFormat{ Algorithm: jrsppb.JwtRsaSsaPssAlgorithm_PS256, Version: 0, PublicExponent: []byte{0x01}, ModulusSizeInBits: 3072, }, }, { name: "invalid modulus size", keyFormat: &jrsppb.JwtRsaSsaPssKeyFormat{ Algorithm: jrsppb.JwtRsaSsaPssAlgorithm_PS256, Version: 0, PublicExponent: []byte{0x01, 0x00, 0x01}, ModulusSizeInBits: 1024, }, }, } { t.Run(tc.name, func(t *testing.T) { serializedKeyFormat, err := proto.Marshal(tc.keyFormat) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := km.NewKeyData(serializedKeyFormat); err == nil { t.Fatalf("NewKeyData() err = nil, want error") } if _, err := km.NewKey(serializedKeyFormat); err == nil { t.Fatalf("NewKey() err = nil, want error") } }) } } func TestJWTPSSignerKeyManagerNewKeyDataFailsWithNilKeyFormat(t *testing.T) { km, err := registry.GetKeyManager(testJWTPSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTPSSignerKeyType, err) } if _, err := km.NewKeyData(nil); err == nil { t.Fatalf("NewKeyData() err = nil, want error") } if _, err := km.NewKey(nil); err == nil { t.Fatalf("NewKey() err = nil, want error") } } func TestJWTPSSignerKeyManagerNewKeyDataFailsWithInvalidSerializedKeyFormat(t *testing.T) { km, err := registry.GetKeyManager(testJWTPSSignerKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTPSSignerKeyType, err) } if _, err := km.NewKeyData([]byte("invalid_serialization")); err == nil { t.Fatalf("NewKeyData() err = nil, want error") } if _, err := km.NewKey([]byte("invalid_serialization")); err == nil { t.Fatalf("NewKey() err = nil, want error") } } ================================================ FILE: go/jwt/jwt_rsa_ssa_pss_verify_key_manager.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "crypto/rsa" "errors" "fmt" "math/big" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/signature" "github.com/google/tink/go/keyset" jrsppb "github.com/google/tink/go/proto/jwt_rsa_ssa_pss_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( jwtPSVerifierKeyVersion = 0 jwtPSVerifierTypeURL = "type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPublicKey" ) var errJWTPSVerifierNotImplemented = errors.New("not supported on verifier key manager") // jwtPSVerifierKeyManager implements the KeyManager interface // for JWT Verifier using the 'PS256', 'PS384', and 'PS512' JSON Web Algorithms (JWA). type jwtPSVerifierKeyManager struct{} var _ registry.KeyManager = (*jwtPSVerifierKeyManager)(nil) // adding to this map will automatically add to the list of // "accepted" algorithms that will construct valid primitives. var validPSAlgToHash = map[jrsppb.JwtRsaSsaPssAlgorithm]string{ jrsppb.JwtRsaSsaPssAlgorithm_PS256: "SHA256", jrsppb.JwtRsaSsaPssAlgorithm_PS384: "SHA384", jrsppb.JwtRsaSsaPssAlgorithm_PS512: "SHA512", } var psAlgToSaltLen = map[jrsppb.JwtRsaSsaPssAlgorithm]int{ jrsppb.JwtRsaSsaPssAlgorithm_PS256: 32, jrsppb.JwtRsaSsaPssAlgorithm_PS384: 48, jrsppb.JwtRsaSsaPssAlgorithm_PS512: 64, } func (km *jwtPSVerifierKeyManager) Primitive(serializedKey []byte) (any, error) { if serializedKey == nil || len(serializedKey) == 0 { return nil, fmt.Errorf("invalid key") } pubKey := &jrsppb.JwtRsaSsaPssPublicKey{} if err := proto.Unmarshal(serializedKey, pubKey); err != nil { return nil, err } if err := validatePSPublicKey(pubKey); err != nil { return nil, err } e := new(big.Int).SetBytes(pubKey.GetE()) if !e.IsInt64() { return nil, fmt.Errorf("public exponent can't fit in a 64 bit integer") } rsaPubKey := &rsa.PublicKey{ N: new(big.Int).SetBytes(pubKey.GetN()), E: int(e.Int64()), } algorithm := pubKey.GetAlgorithm() v, err := signature.New_RSA_SSA_PSS_Verifier(validPSAlgToHash[algorithm], psAlgToSaltLen[algorithm], rsaPubKey) if err != nil { return nil, err } return newVerifierWithKID(v, algorithm.String(), psCustomKID(pubKey)) } func (km *jwtPSVerifierKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { return nil, errJWTPSVerifierNotImplemented } func (km *jwtPSVerifierKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { return nil, errJWTPSVerifierNotImplemented } func (km *jwtPSVerifierKeyManager) DoesSupport(typeURL string) bool { return typeURL == jwtPSVerifierTypeURL } func (km *jwtPSVerifierKeyManager) TypeURL() string { return jwtPSVerifierTypeURL } func validatePSPublicKey(pubKey *jrsppb.JwtRsaSsaPssPublicKey) error { if pubKey == nil { return fmt.Errorf("nil public key") } if err := keyset.ValidateKeyVersion(pubKey.Version, jwtPSVerifierKeyVersion); err != nil { return err } if _, ok := validPSAlgToHash[pubKey.GetAlgorithm()]; !ok { return fmt.Errorf("invalid algorithm") } e := new(big.Int).SetBytes(pubKey.GetE()) if !e.IsInt64() { return fmt.Errorf("public exponent can't fit in a 64 bit integer") } if err := signature.RSAValidPublicExponent(int(e.Int64())); err != nil { return err } return signature.RSAValidModulusSizeInBits(new(big.Int).SetBytes(pubKey.GetN()).BitLen()) } func psCustomKID(pk *jrsppb.JwtRsaSsaPssPublicKey) *string { // nil is an acceptable value for a custom kid. if pk.GetCustomKid() == nil { return nil } k := pk.GetCustomKid().GetValue() return &k } ================================================ FILE: go/jwt/jwt_rsa_ssa_pss_verify_key_manager_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "fmt" "testing" "time" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/subtle/random" jrsppb "github.com/google/tink/go/proto/jwt_rsa_ssa_pss_go_proto" ) const testJWTPSVerifierKeyType = "type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPublicKey" func makeValidPSPublicKey() (*jrsppb.JwtRsaSsaPssPublicKey, error) { // Public key taken from: https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.2 n, err := base64Decode( "ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddx" + "HmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMs" + "D1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSH" + "SXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdV" + "MTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8" + "NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ") if err != nil { return nil, fmt.Errorf("base64 decoding modulus: %v", err) } e, err := base64Decode("AQAB") if err != nil { return nil, fmt.Errorf("base64 decoding public exponent: %v", err) } return &jrsppb.JwtRsaSsaPssPublicKey{ Algorithm: jrsppb.JwtRsaSsaPssAlgorithm_PS256, Version: 0, N: n, E: e, CustomKid: nil, }, nil } func TestJWTPSVerifierNotImplemented(t *testing.T) { km, err := registry.GetKeyManager(testJWTPSVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTPSVerifierKeyType, err) } keyFormat := &jrsppb.JwtRsaSsaPssKeyFormat{ Version: 0, Algorithm: jrsppb.JwtRsaSsaPssAlgorithm_PS256, ModulusSizeInBits: 3072, PublicExponent: []byte{0x01, 0x00, 0x01}, // 65537 aka F4 } serializedKeyFormat, err := proto.Marshal(keyFormat) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := km.NewKey(serializedKeyFormat); err == nil { t.Fatalf("km.NewKey() err = nil, want error") } if _, err := km.NewKeyData(serializedKeyFormat); err == nil { t.Fatalf("km.NewKeyData() err = nil, want error") } } func TestJWTPSVerifierDoesSupport(t *testing.T) { km, err := registry.GetKeyManager(testJWTPSVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTPSVerifierKeyType, err) } if !km.DoesSupport(testJWTPSVerifierKeyType) { t.Errorf("DoesSupport(%q) = false, want true", testJWTPSVerifierKeyType) } if km.DoesSupport("not.the.actual.key.type") { t.Errorf("km.DoesSupport('not.the.actual.key.type') = true, want false") } } func TestJWTPSVerifierTypeURL(t *testing.T) { km, err := registry.GetKeyManager(testJWTPSVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTPSVerifierKeyType, err) } if km.TypeURL() != testJWTPSVerifierKeyType { t.Errorf("km.TypeURL() = %q, want %q", km.TypeURL(), testJWTPSVerifierKeyType) } } func TestJWTPSVerifierPrimitiveWithInvalidKey(t *testing.T) { type testCase struct { name string pubKey *jrsppb.JwtRsaSsaPssPublicKey } km, err := registry.GetKeyManager(testJWTPSVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTPSVerifierKeyType, err) } validPubKey, err := makeValidPSPublicKey() if err != nil { t.Fatalf("makeValidPSPublicKey() err = %v, want nil", err) } for _, tc := range []testCase{ { name: "nil public key", pubKey: nil, }, { name: "empty public key", pubKey: &jrsppb.JwtRsaSsaPssPublicKey{}, }, { name: "invalid version", pubKey: &jrsppb.JwtRsaSsaPssPublicKey{ Version: validPubKey.Version + 1, Algorithm: validPubKey.GetAlgorithm(), N: validPubKey.GetN(), E: validPubKey.GetE(), CustomKid: validPubKey.GetCustomKid(), }, }, { name: "invalid algorithm", pubKey: &jrsppb.JwtRsaSsaPssPublicKey{ Algorithm: jrsppb.JwtRsaSsaPssAlgorithm_PS_UNKNOWN, Version: validPubKey.Version, N: validPubKey.GetN(), E: validPubKey.GetE(), CustomKid: validPubKey.GetCustomKid(), }, }, { name: "invalid modulus", pubKey: &jrsppb.JwtRsaSsaPssPublicKey{ Version: validPubKey.Version, Algorithm: validPubKey.GetAlgorithm(), N: []byte{0x00}, E: validPubKey.GetE(), CustomKid: validPubKey.GetCustomKid(), }, }, { name: "invalid exponent", pubKey: &jrsppb.JwtRsaSsaPssPublicKey{ Version: validPubKey.Version, Algorithm: validPubKey.GetAlgorithm(), N: validPubKey.GetN(), E: []byte{0x05, 0x04, 0x03}, CustomKid: validPubKey.GetCustomKid(), }, }, { name: "exponent larger than 64 bits", pubKey: &jrsppb.JwtRsaSsaPssPublicKey{ Version: validPubKey.Version, Algorithm: validPubKey.GetAlgorithm(), N: validPubKey.GetN(), E: random.GetRandomBytes(65), CustomKid: validPubKey.GetCustomKid(), }, }, } { t.Run(tc.name, func(t *testing.T) { serializedPubKey, err := proto.Marshal(tc.pubKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := km.Primitive(serializedPubKey); err == nil { t.Errorf("Primitive() err = nil, want error") } }) } } func TestJWTPSVerifierPrimitiveVerifyFixedToken(t *testing.T) { km, err := registry.GetKeyManager(testJWTPSVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTPSVerifierKeyType, err) } pubKey, err := makeValidPSPublicKey() if err != nil { t.Fatalf("makeValidPSPublicKey() err = %v, want nil", err) } serializedPubKey, err := proto.Marshal(pubKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } v, err := km.Primitive(serializedPubKey) if err != nil { t.Fatalf("km.Primitive() err = %v, want nil", err) } verifier, ok := v.(*verifierWithKID) if !ok { t.Fatalf("primitive isn't a JWT Verifier") } // // similar to https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.2 compact := "eyJhbGciOiJQUzI1NiJ9" + "." + "eyJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlLCJpc3MiOiJqb2UifQ" + "." + "PpLcmEZ2zlsOmYygy8SU9Zxwab9deDuibgCg8dCZ8Po1N51kyMU9Mty7wj9fTCOONNqu3QxLe_2Wu_BkVhz41W" + "bxXrP3cci7deSnQmgN2ZkA23egSFfMoDd56CFvY3-eaG22NRxPsDWypECdDgXJXoSPnlRxgtaJDxUUD3Ej9DZ4" + "gmdVcG4ZqmLSxoIAXtmjGi-Da_fqf48DOKaL5AI1uE2SW_byXPXdtaD_oIvNoeL0J5wuU2cSJQutu-UCyfO1rl" + "R3DTOzR_XRx7dEzziqfzP7_YlSxdidkph1Jrh1DIapxsWrnaShYFofS35Vg17SdciALeRMnQHwhClJJqgChg" issuer := "joe" validator, err := NewValidator(&ValidatorOpts{ ExpectedIssuer: &issuer, FixedNow: time.Unix(123, 0), }) if err != nil { t.Fatalf("NewValidator() err = %v, want nil", err) } // verification succeeds because token was valid on January 1, 1970 UTC. if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, nil); err != nil { t.Errorf("verifier.VerifyAndDecodeWithKID(kid = nil) err = %v, want nil", err) } // verification with KID fails because token contains no KID. if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, refString("")); err == nil { t.Errorf("verifier.VerifyAndDecodeWithKID(kid = '1234') err = nil, want error") } } func TestJWTPSVerifierPrimitiveVerifyFixedTokenWithCustomKID(t *testing.T) { km, err := registry.GetKeyManager(testJWTPSVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTPSVerifierKeyType, err) } pubKey, err := makeValidPSPublicKey() if err != nil { t.Fatalf("makeValidPSPublicKey() err = %v, want nil", err) } pubKey.CustomKid = &jrsppb.JwtRsaSsaPssPublicKey_CustomKid{ Value: "oneoh", } serializedPubKey, err := proto.Marshal(pubKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } v, err := km.Primitive(serializedPubKey) if err != nil { t.Fatalf("km.Primitive() err = %v, want nil", err) } verifier, ok := v.(*verifierWithKID) if !ok { t.Fatalf("primitive isn't a JWT Verifier") } // // similar to https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.2 but with KID "oneoh" compact := "eyJhbGciOiJQUzI1NiIsImtpZCI6Im9uZW9oIn0" + "." + "eyJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlLCJpc3MiOiJqb2UifQ" + "." + "hrkeS71m1bg9tDBfEI3P-E6CkLZuNOguG0LlY5Yb-HzjFan9_LmvmemMCYYTsifNJkJkiSZRwkv7BQ0Svd6Rn_" + "TzckQdpr37pez_2mywfpAbYWxi40n35q9Q3W8IWgbpZFIRIru0n1R7v4XIpkVbd90IwahgZG3Yhvlwt3-EWCwz" + "7tb3_EbcFFHsSK0PH-b9mPwrUzb_l-jJR5T2zATc3lTriyGsOhyubBAwcxKuAEg5Ru7_vgLI352jEzjFsz05Fu" + "QVMEtdBGqiLn2iIu8yDQtKMPm-FBhBO_uomHcxjLY4nBziAkba3WPUGkB4HvbIGQz9ZedUjd2ivCQ52GT2uw" issuer := "joe" validator, err := NewValidator(&ValidatorOpts{ ExpectedIssuer: &issuer, FixedNow: time.Unix(123, 0), }) if err != nil { t.Fatalf("NewValidator() err = %v, want nil", err) } // verification succeeds because token was valid on January 1, 1970 UTC. if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, nil); err != nil { t.Errorf("verifier.VerifyAndDecodeWithKID(kid = 'oneoh') err = %v, want nil", err) } // verification fails with Custom KID and Tink KID, only one can be present. if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, refString("oneoh")); err == nil { t.Errorf("verifier.VerifyAndDecodeWithKID(kid = '1234') err = nil, want error") } } func TestJWTPSVerifierPrimitiveVerifyFixedTokenWithTinkKID(t *testing.T) { km, err := registry.GetKeyManager(testJWTPSVerifierKeyType) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testJWTPSVerifierKeyType, err) } pubKey, err := makeValidPSPublicKey() if err != nil { t.Fatalf("makeValidPSPublicKey() err = %v, want nil", err) } pubKey.CustomKid = nil serializedPubKey, err := proto.Marshal(pubKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } v, err := km.Primitive(serializedPubKey) if err != nil { t.Fatalf("km.Primitive() err = %v, want nil", err) } verifier, ok := v.(*verifierWithKID) if !ok { t.Fatalf("primitive isn't a JWT Verifier") } // // similar to https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.2 but with KID "oneoh" compact := "eyJhbGciOiJQUzI1NiIsImtpZCI6Im9uZW9oIn0" + "." + "eyJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlLCJpc3MiOiJqb2UifQ" + "." + "hrkeS71m1bg9tDBfEI3P-E6CkLZuNOguG0LlY5Yb-HzjFan9_LmvmemMCYYTsifNJkJkiSZRwkv7BQ0Svd6Rn_" + "TzckQdpr37pez_2mywfpAbYWxi40n35q9Q3W8IWgbpZFIRIru0n1R7v4XIpkVbd90IwahgZG3Yhvlwt3-EWCwz" + "7tb3_EbcFFHsSK0PH-b9mPwrUzb_l-jJR5T2zATc3lTriyGsOhyubBAwcxKuAEg5Ru7_vgLI352jEzjFsz05Fu" + "QVMEtdBGqiLn2iIu8yDQtKMPm-FBhBO_uomHcxjLY4nBziAkba3WPUGkB4HvbIGQz9ZedUjd2ivCQ52GT2uw" issuer := "joe" validator, err := NewValidator(&ValidatorOpts{ ExpectedIssuer: &issuer, FixedNow: time.Unix(123, 0), }) if err != nil { t.Fatalf("NewValidator() err = %v, want nil", err) } // verification succeeds because token was valid on January 1, 1970 UTC. if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, refString("oneoh")); err != nil { t.Errorf("verifier.VerifyAndDecodeWithKID(kid = 'oneoh') err = %v, want nil", err) } // verification without Tink KID ignores KID header. if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, nil); err != nil { t.Errorf("verifier.VerifyAndDecodeWithKID(kid = nil) err = %v, want nil", err) } // verification with incorrect KID fails because token contains KID header. if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, refString("1234")); err == nil { t.Errorf("verifier.VerifyAndDecodeWithKID(kid = '1234') err = nil, want error") } } ================================================ FILE: go/jwt/jwt_signer.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt // Signer is the interface for signing JWTs. // See RFC 7519 and RFC 7515. Security guarantees: similar to tink.Signer. type Signer interface { // Computes a signature, and encodes the JWT and the signature in the JWS compact serialization format. SignAndEncode(rawJWT *RawJWT) (string, error) } ================================================ FILE: go/jwt/jwt_signer_factory.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "fmt" "github.com/google/tink/go/core/primitiveset" "github.com/google/tink/go/keyset" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // NewSigner generates a new instance of the JWT Signer primitive. func NewSigner(handle *keyset.Handle) (Signer, error) { if handle == nil { return nil, fmt.Errorf("keyset handle can't be nil") } ps, err := handle.PrimitivesWithKeyManager(nil) if err != nil { return nil, fmt.Errorf("jwt_signer_factory: cannot obtain primitive set: %v", err) } return newWrappedSigner(ps) } // wrappedSigner is a JWT Signer implementation that uses the underlying primitive set for JWT Sign. type wrappedSigner struct { ps *primitiveset.PrimitiveSet } var _ Signer = (*wrappedSigner)(nil) func newWrappedSigner(ps *primitiveset.PrimitiveSet) (*wrappedSigner, error) { if _, ok := (ps.Primary.Primitive).(*signerWithKID); !ok { return nil, fmt.Errorf("jwt_signer_factory: not a JWT Signer primitive") } for _, primitives := range ps.Entries { for _, p := range primitives { if p.PrefixType != tinkpb.OutputPrefixType_RAW && p.PrefixType != tinkpb.OutputPrefixType_TINK { return nil, fmt.Errorf("jwt_signer_factory: invalid OutputPrefixType: %s", p.PrefixType) } if _, ok := (p.Primitive).(*signerWithKID); !ok { return nil, fmt.Errorf("jwt_signer_factory: not a JWT Signer primitive") } } } return &wrappedSigner{ps: ps}, nil } func (w *wrappedSigner) SignAndEncode(rawJWT *RawJWT) (string, error) { primary := w.ps.Primary p, ok := (primary.Primitive).(*signerWithKID) if !ok { return "", fmt.Errorf("jwt_signer_factory: not a JWT Signer primitive") } return p.SignAndEncodeWithKID(rawJWT, keyID(primary.KeyID, primary.PrefixType)) } ================================================ FILE: go/jwt/jwt_signer_kid.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "fmt" "github.com/google/tink/go/tink" ) type signerWithKID struct { ts tink.Signer algorithm string customKID *string } func newSignerWithKID(ts tink.Signer, algorithm string, customKID *string) (*signerWithKID, error) { if ts == nil { return nil, fmt.Errorf("tink signer can't be nil") } return &signerWithKID{ ts: ts, algorithm: algorithm, customKID: customKID, }, nil } // SignAndEncodeWithKID creates the header and content from a rawJWT and combines them into a unsigned token. // It then signs it and encodes the output using compact serialization. func (s *signerWithKID) SignAndEncodeWithKID(rawJWT *RawJWT, kid *string) (string, error) { unsigned, err := createUnsigned(rawJWT, s.algorithm, kid, s.customKID) if err != nil { return "", err } signature, err := s.ts.Sign([]byte(unsigned)) if err != nil { return "", err } return combineUnsignedAndSignature(unsigned, signature), nil } ================================================ FILE: go/jwt/jwt_signer_verifier_factory_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt_test import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "fmt" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/jwt" "github.com/google/tink/go/keyset" "github.com/google/tink/go/signature" "github.com/google/tink/go/testkeyset" "github.com/google/tink/go/testutil" jepb "github.com/google/tink/go/proto/jwt_ecdsa_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestSignerVerifierFactoryWithInvalidPrimitiveSetType(t *testing.T) { kh, err := keyset.NewHandle(signature.ECDSAP256KeyTemplate()) if err != nil { t.Fatalf("failed to build *keyset.Handle: %s", err) } if _, err := jwt.NewSigner(kh); err == nil { t.Errorf("jwt.NewSigner() err = nil, want error") } if _, err := jwt.NewVerifier(kh); err == nil { t.Errorf("jwt.NewVerifier() err = nil, want error") } } func TestSignerVerifierFactoryNilKeyset(t *testing.T) { if _, err := jwt.NewSigner(nil); err == nil { t.Errorf("jwt.NewSigner(nil) err = nil, want error") } if _, err := jwt.NewVerifier(nil); err == nil { t.Errorf("jwt.NewVerifier(nil) err = nil, want error") } } func createJWTECDSAKey(kid *string) (*jepb.JwtEcdsaPrivateKey, error) { k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { return nil, fmt.Errorf("ecdsa.GenerateKey(curve=P256): %v", err) } var customKID *jepb.JwtEcdsaPublicKey_CustomKid = nil if kid != nil { customKID = &jepb.JwtEcdsaPublicKey_CustomKid{Value: *kid} } return &jepb.JwtEcdsaPrivateKey{ Version: 0, PublicKey: &jepb.JwtEcdsaPublicKey{ Version: 0, Algorithm: jepb.JwtEcdsaAlgorithm_ES256, X: k.X.Bytes(), Y: k.Y.Bytes(), CustomKid: customKID, }, KeyValue: k.D.Bytes(), }, nil } func createKeyData(privKey *jepb.JwtEcdsaPrivateKey) (*tinkpb.KeyData, error) { serializedPrivKey, err := proto.Marshal(privKey) if err != nil { return nil, fmt.Errorf("serializing private key proto: %v", err) } return &tinkpb.KeyData{ TypeUrl: "type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey", Value: serializedPrivKey, KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PRIVATE, }, nil } func createKeysetHandles(privKey *tinkpb.KeyData, outputPrefixType tinkpb.OutputPrefixType) (*keyset.Handle, *keyset.Handle, error) { k := testutil.NewKey(privKey, tinkpb.KeyStatusType_ENABLED, 1 /*=keyID*/, outputPrefixType) privKeyHandle, err := testkeyset.NewHandle(testutil.NewKeyset(k.KeyId, []*tinkpb.Keyset_Key{k})) if err != nil { return nil, nil, fmt.Errorf("creating keyset handle for private key: %v", err) } pubKeyHandle, err := privKeyHandle.Public() if err != nil { return nil, nil, fmt.Errorf("creating keyset handle for public key: %v", err) } return privKeyHandle, pubKeyHandle, nil } func createKeyHandlesFromKey(t *testing.T, privKey *jepb.JwtEcdsaPrivateKey, outputPrefixType tinkpb.OutputPrefixType) (*keyset.Handle, *keyset.Handle) { privKeyData, err := createKeyData(privKey) if err != nil { t.Fatal(err) } privKeyHandle, pubKeyHandle, err := createKeysetHandles(privKeyData, outputPrefixType) if err != nil { t.Fatal(err) } return privKeyHandle, pubKeyHandle } func createKeyAndKeyHandles(t *testing.T, kid *string, outputPrefixType tinkpb.OutputPrefixType) (*jepb.JwtEcdsaPrivateKey, *keyset.Handle, *keyset.Handle) { privKey, err := createJWTECDSAKey(kid) if err != nil { t.Fatal(err) } privKeyHandle, pubKeyHandle := createKeyHandlesFromKey(t, privKey, outputPrefixType) return privKey, privKeyHandle, pubKeyHandle } func TestFactoryVerifyWithDifferentKeyFails(t *testing.T) { _, privKeyHandle, pubKeyHandle := createKeyAndKeyHandles(t, nil /*=kid*/, tinkpb.OutputPrefixType_TINK) signer, err := jwt.NewSigner(privKeyHandle) if err != nil { t.Fatalf("jwt.NewSigner() err = %v, want nil", err) } verifier, err := jwt.NewVerifier(pubKeyHandle) if err != nil { t.Fatalf("jwt.NewVerifier() err = %v, want nil", err) } rawJWT, err := jwt.NewRawJWT(&jwt.RawJWTOptions{WithoutExpiration: true, Audiences: []string{"tink-audience"}}) if err != nil { t.Fatalf("jwt.NewRawJWT() err = %v, want nil", err) } validator, err := jwt.NewValidator(&jwt.ValidatorOpts{AllowMissingExpiration: true, ExpectedAudience: refString("tink-audience")}) if err != nil { t.Fatalf("jwt.NewValidator() err = %v, want nil", err) } compact, err := signer.SignAndEncode(rawJWT) if err != nil { t.Errorf("signer.SignAndEncode() err = %v, want nil", err) } if _, err := verifier.VerifyAndDecode(compact, validator); err != nil { t.Errorf("verifier.VerifyAndDecode() err = %v, want nil", err) } // verification with different key fails _, _, pubKeyHandle = createKeyAndKeyHandles(t, nil /*=kid*/, tinkpb.OutputPrefixType_TINK) verifier, err = jwt.NewVerifier(pubKeyHandle) if err != nil { t.Fatalf("jwt.NewVerifier() err = %v, want nil", err) } if _, err := verifier.VerifyAndDecode(compact, validator); err == nil { t.Errorf("verifier.VerifyAndDecode() err = nil, want error") } } func TestFactorySignWithTinkAndCustomKIDFails(t *testing.T) { _, privKeyHandle, _ := createKeyAndKeyHandles(t, refString("customKID"), tinkpb.OutputPrefixType_TINK) signer, err := jwt.NewSigner(privKeyHandle) if err != nil { t.Fatalf("jwt.NewSigner() err = %v, want nil", err) } rawJWT, err := jwt.NewRawJWT(&jwt.RawJWTOptions{WithoutExpiration: true}) if err != nil { t.Fatalf("jwt.NewRawJWT() err = %v, want nil", err) } if _, err := signer.SignAndEncode(rawJWT); err == nil { t.Errorf("signer.SignAndEncode() err = nil, want error") } } type signerVerifierFactoryKIDTestCase struct { tag string signerOutputPrefix tinkpb.OutputPrefixType signerKID *string verifierOutputPrefix tinkpb.OutputPrefixType verifierKID *string } func TestFactorySignVerifyWithKIDFailure(t *testing.T) { rawJWT, err := jwt.NewRawJWT(&jwt.RawJWTOptions{WithoutExpiration: true}) if err != nil { t.Fatalf("jwt.NewRawJWT() err = %v, want nil", err) } validator, err := jwt.NewValidator(&jwt.ValidatorOpts{AllowMissingExpiration: true}) if err != nil { t.Fatalf("jwt.NewValidator() err = %v, want nil", err) } for _, tc := range []signerVerifierFactoryKIDTestCase{ { tag: "raw output prefix and different custom kid", signerOutputPrefix: tinkpb.OutputPrefixType_RAW, signerKID: refString("customKID"), verifierOutputPrefix: tinkpb.OutputPrefixType_RAW, verifierKID: refString("OtherCustomKID"), }, { tag: "verifier with tink output prefix and custom kid when token has no kid", signerOutputPrefix: tinkpb.OutputPrefixType_RAW, signerKID: nil, verifierOutputPrefix: tinkpb.OutputPrefixType_TINK, verifierKID: refString("customKID"), }, { tag: "verifier with tink output prefix and custom kid when token has kid", signerOutputPrefix: tinkpb.OutputPrefixType_RAW, signerKID: refString("customKID"), verifierOutputPrefix: tinkpb.OutputPrefixType_TINK, verifierKID: refString("customKid"), }, { tag: "token with fixed kid and verifier with tink output prefix", signerOutputPrefix: tinkpb.OutputPrefixType_RAW, signerKID: refString("customKID"), verifierOutputPrefix: tinkpb.OutputPrefixType_TINK, verifierKID: nil, }, { tag: "token missing kid in header when verifier has tink output prefix", signerOutputPrefix: tinkpb.OutputPrefixType_RAW, signerKID: nil, verifierOutputPrefix: tinkpb.OutputPrefixType_TINK, verifierKID: nil, }, } { t.Run(tc.tag, func(t *testing.T) { key, privKeyHandle, _ := createKeyAndKeyHandles(t, tc.signerKID, tc.signerOutputPrefix) signer, err := jwt.NewSigner(privKeyHandle) if err != nil { t.Fatalf("jwt.NewSigner() err = %v, want nil", err) } compact, err := signer.SignAndEncode(rawJWT) if err != nil { t.Errorf("signer.SignAndEncode() err = %v, want nil", err) } key.PublicKey.CustomKid = nil if tc.verifierKID != nil { key.PublicKey.CustomKid = &jepb.JwtEcdsaPublicKey_CustomKid{Value: *tc.verifierKID} } _, pubKeyHandle := createKeyHandlesFromKey(t, key, tc.verifierOutputPrefix) verifier, err := jwt.NewVerifier(pubKeyHandle) if err != nil { t.Fatalf("jwt.NewVerifier() err = %v, want nil", err) } if _, err := verifier.VerifyAndDecode(compact, validator); err == nil { t.Errorf("verifier.VerifyAndDecode() err = nil, want error") } }) } } func TestVerifyAndDecodeReturnsValidationError(t *testing.T) { _, privateHandle, publicHandle := createKeyAndKeyHandles(t, nil /*=kid*/, tinkpb.OutputPrefixType_TINK) signer, err := jwt.NewSigner(privateHandle) if err != nil { t.Fatalf("jwt.NewSigner() err = %v, want nil", err) } verifier, err := jwt.NewVerifier(publicHandle) if err != nil { t.Fatalf("jwt.NewVerifier() err = %v, want nil", err) } audience := "audience" rawJWT, err := jwt.NewRawJWT(&jwt.RawJWTOptions{Audience: &audience, WithoutExpiration: true}) if err != nil { t.Fatalf("jwt.NewRawJWT() err = %v, want nil", err) } compact, err := signer.SignAndEncode(rawJWT) if err != nil { t.Errorf("signer.SignAndEncode() err = %v, want nil", err) } otherAudience := "otherAudience" validator, err := jwt.NewValidator( &jwt.ValidatorOpts{ExpectedAudience: &otherAudience, AllowMissingExpiration: true}) if err != nil { t.Fatalf("jwt.NewValidator() err = %v, want nil", err) } _, err = verifier.VerifyAndDecode(compact, validator) wantErr := "validating audience claim: otherAudience not found" if err == nil { t.Errorf("verifier.VerifyAndDecode() err = nil, want %q", wantErr) } if err.Error() != wantErr { t.Errorf("verifier.VerifyAndDecode() err = %q, want %q", err.Error(), wantErr) } } func TestFactorySignVerifyWithKIDSuccess(t *testing.T) { rawJWT, err := jwt.NewRawJWT(&jwt.RawJWTOptions{WithoutExpiration: true}) if err != nil { t.Fatalf("jwt.NewRawJWT() err = %v, want nil", err) } validator, err := jwt.NewValidator(&jwt.ValidatorOpts{AllowMissingExpiration: true}) if err != nil { t.Fatalf("jwt.NewValidator() err = %v, want nil", err) } for _, tc := range []signerVerifierFactoryKIDTestCase{ { tag: "signer verifier without custom kid and with raw output prefix", signerOutputPrefix: tinkpb.OutputPrefixType_RAW, signerKID: nil, verifierOutputPrefix: tinkpb.OutputPrefixType_RAW, verifierKID: nil, }, { tag: "signer with custom kid verifier without custom kid and raw output prefixes", signerOutputPrefix: tinkpb.OutputPrefixType_RAW, signerKID: refString("customKID"), verifierOutputPrefix: tinkpb.OutputPrefixType_RAW, verifierKID: nil, }, { tag: "signer and verifier same custom kid and raw output prefix", signerOutputPrefix: tinkpb.OutputPrefixType_RAW, signerKID: refString("customKID"), verifierOutputPrefix: tinkpb.OutputPrefixType_RAW, verifierKID: refString("customKID"), }, { tag: "signer and verifier with tink output prefix and no custom kid", signerOutputPrefix: tinkpb.OutputPrefixType_TINK, signerKID: nil, verifierOutputPrefix: tinkpb.OutputPrefixType_TINK, verifierKID: nil, }, { tag: "signer with tink output prefix verifier with raw output prefix", signerOutputPrefix: tinkpb.OutputPrefixType_TINK, signerKID: nil, verifierOutputPrefix: tinkpb.OutputPrefixType_RAW, verifierKID: nil, }, { tag: "token missing kid in header when verifier has custom kid", signerOutputPrefix: tinkpb.OutputPrefixType_RAW, signerKID: nil, verifierOutputPrefix: tinkpb.OutputPrefixType_RAW, verifierKID: refString("customKID"), }, } { t.Run(tc.tag, func(t *testing.T) { key, privKeyHandle, _ := createKeyAndKeyHandles(t, tc.signerKID, tc.signerOutputPrefix) signer, err := jwt.NewSigner(privKeyHandle) if err != nil { t.Fatalf("jwt.NewSigner() err = %v, want nil", err) } compact, err := signer.SignAndEncode(rawJWT) if err != nil { t.Errorf("signer.SignAndEncode() err = %v, want nil", err) } key.GetPublicKey().CustomKid = nil if tc.verifierKID != nil { key.GetPublicKey().CustomKid = &jepb.JwtEcdsaPublicKey_CustomKid{Value: *tc.verifierKID} } _, pubKeyHandle := createKeyHandlesFromKey(t, key, tc.verifierOutputPrefix) verifier, err := jwt.NewVerifier(pubKeyHandle) if err != nil { t.Fatalf("jwt.NewVerifier() err = %v, want nil", err) } if _, err := verifier.VerifyAndDecode(compact, validator); err != nil { t.Errorf("verifier.VerifyAndDecode() err = %v, want nil", err) } }) } } ================================================ FILE: go/jwt/jwt_signer_verifier_kid_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "fmt" "testing" "time" "github.com/google/tink/go/signature/subtle" "github.com/google/tink/go/tink" ) func createTinkECVerifier() (tink.Verifier, error) { // Public key from: https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.3 x, err := base64Decode("f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU") if err != nil { return nil, fmt.Errorf("base64 decoding x coordinate of public key: %v", err) } y, err := base64Decode("x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0") if err != nil { return nil, fmt.Errorf("base64 decoding y coordinate of public key: %v", err) } tv, err := subtle.NewECDSAVerifier("SHA256", "NIST_P256", "IEEE_P1363", x, y) if err != nil { return nil, fmt.Errorf("subtle.NewECDSAVerifier() err = %v, want nil", err) } return tv, nil } func createTinkECSigner() (tink.Signer, error) { // Private key from: https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.3 k, err := base64Decode("jpsQnnGQmL-YBIffH1136cspYG6-0iY7X1fCE9-E9LI") if err != nil { return nil, fmt.Errorf("base64 decoding private key: %v", err) } ts, err := subtle.NewECDSASigner("SHA256", "NIST_P256", "IEEE_P1363", k) if err != nil { return nil, fmt.Errorf("subtle.NewECDSASigner() err = %v, want nil", err) } return ts, nil } func createESVerifier(kid *string) (*verifierWithKID, error) { tv, err := createTinkECVerifier() if err != nil { return nil, err } v, err := newVerifierWithKID(tv, "ES256", kid) if err != nil { return nil, fmt.Errorf("newVerifierWithKID(algorithm = 'ES256') err = %v, want nil", err) } return v, nil } func createESSigner(kid *string) (*signerWithKID, error) { ts, err := createTinkECSigner() if err != nil { return nil, err } s, err := newSignerWithKID(ts, "ES256", kid) if err != nil { return nil, fmt.Errorf("newSignerWithKID(algorithm = 'ES256') err = %v, want nil", err) } return s, nil } func TestVerifierWithFixedToken(t *testing.T) { // compact from: https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.3 compact := "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q" v, err := createESVerifier(nil) if err != nil { t.Fatal(err) } validator, err := NewValidator(&ValidatorOpts{ExpectedIssuer: refString("joe"), FixedNow: time.Unix(1300819300, 0)}) if err != nil { t.Fatalf("NewValidator() err = %v, want nil", err) } verified, err := v.VerifyAndDecodeWithKID(compact, validator, nil) if err != nil { t.Errorf("VerifyAndDecodeWithKID() err = %v, want nil", err) } issuer, err := verified.Issuer() if err != nil { t.Errorf("verified.Issuer() err = %v, want nil", err) } if issuer != "joe" { t.Errorf("verified.Issuer() = %q, want joe", issuer) } expiration, err := verified.ExpiresAt() if err != nil { t.Errorf("verified.ExpiresAt() err = %v, want nil", err) } wantExp := time.Unix(1300819380, 0) if !expiration.Equal(wantExp) { t.Errorf("verified.ExpiresAt() = %q, want %q", expiration, wantExp) } boolClaim, err := verified.BooleanClaim("http://example.com/is_root") if err != nil { t.Errorf("verified.BooleanClaim('http://example.com/is_root') err = %v, want nil", err) } if boolClaim != true { t.Errorf("verified.BooleanClaim('http://example.com/is_root') = %v, want false", boolClaim) } } func TestCreateSignValidateToken(t *testing.T) { rawJWT, err := NewRawJWT(&RawJWTOptions{TypeHeader: refString("JWT"), WithoutExpiration: true}) if err != nil { t.Fatalf("NewRawJWT() err = %v, want nil", err) } validator, err := NewValidator(&ValidatorOpts{ExpectedTypeHeader: refString("JWT"), AllowMissingExpiration: true}) if err != nil { t.Fatalf("NewValidator() err = %v, want nil", err) } s, err := createESSigner(nil) if err != nil { t.Fatal(err) } v, err := createESVerifier(nil) if err != nil { t.Fatal(err) } compact, err := s.SignAndEncodeWithKID(rawJWT, nil) if err != nil { t.Fatalf("s.SignAndEncodeWithKID() err = %v, want nil", err) } verified, err := v.VerifyAndDecodeWithKID(compact, validator, nil) if err != nil { t.Fatalf("v.VerifyAndDecodeWithKID() err = %v, want nil", err) } typeHeader, err := verified.TypeHeader() if err != nil { t.Errorf("verified.TypeHeader() err = %v, want nil", err) } if typeHeader != "JWT" { t.Errorf("verified.TypeHeader() = %q, want 'JWT'", typeHeader) } } func TestSignerWithTinkAndCustomKIDFails(t *testing.T) { rawJWT, err := NewRawJWT(&RawJWTOptions{TypeHeader: refString("JWT"), WithoutExpiration: true}) if err != nil { t.Fatalf("NewRawJWT() err = %v, want nil", err) } s, err := createESSigner(refString("1234")) if err != nil { t.Fatal(err) } if _, err := s.SignAndEncodeWithKID(rawJWT, refString("123")); err == nil { t.Errorf("s.SignAndEncodeWithKID(kid = 123) err = nil, want error") } } type signerVerifierKIDTestCase struct { tag string signerCustomKID *string verifierCustomKID *string // calculated from the Tink Key ID. signerKID *string // calculated from the Tink Key ID. verifierKID *string } func TestSignVerifyWithKID(t *testing.T) { rawJWT, err := NewRawJWT(&RawJWTOptions{TypeHeader: refString("JWT"), WithoutExpiration: true}) if err != nil { t.Fatalf("NewRawJWT() err = %v, want nil", err) } validator, err := NewValidator(&ValidatorOpts{ExpectedTypeHeader: refString("JWT"), AllowMissingExpiration: true}) if err != nil { t.Fatalf("NewValidator() err = %v, want nil", err) } for _, tc := range []signerVerifierKIDTestCase{ { tag: "verifier with custom kid matches kid in header generated with custom kid", signerCustomKID: refString("1234"), verifierCustomKID: refString("1234"), }, { tag: "verifier with tink kid matches kid in header generated with custom kid", signerCustomKID: refString("1234"), verifierKID: refString("1234"), }, { tag: "verifier with tink kid matches kid in header generated with tink kid", signerKID: refString("1234"), verifierKID: refString("1234"), }, { tag: "no kid in verifier ignores kid when present in header", signerKID: refString("1234"), }, { tag: "verifier with custom kid ignores when no kid present in header", verifierCustomKID: refString("1234"), }, } { t.Run(tc.tag, func(t *testing.T) { s, err := createESSigner(tc.signerCustomKID) if err != nil { t.Fatal(err) } v, err := createESVerifier(tc.verifierCustomKID) if err != nil { t.Fatal(err) } compact, err := s.SignAndEncodeWithKID(rawJWT, tc.signerKID) if err != nil { t.Fatalf("s.SignAndEncodeWithKID(kid = %v) err = %v, want nil", tc.signerKID, err) } verified, err := v.VerifyAndDecodeWithKID(compact, validator, tc.verifierKID) if err != nil { t.Fatalf("s.VerifyAndDecodeWithKID(kid = %v) err = %v, want nil", tc.verifierKID, err) } typeHeader, err := verified.TypeHeader() if err != nil { t.Errorf("verified.TypeHeader() err = %v, want nil", err) } if typeHeader != "JWT" { t.Errorf("verified.TypeHeader() = %q, want 'JWT'", typeHeader) } }) } } func TestSignVerifyWithKIDFailure(t *testing.T) { rawJWT, err := NewRawJWT(&RawJWTOptions{TypeHeader: refString("JWT"), WithoutExpiration: true}) if err != nil { t.Fatalf("NewRawJWT() err = %v, want nil", err) } validator, err := NewValidator(&ValidatorOpts{ExpectedTypeHeader: refString("JWT"), AllowMissingExpiration: true}) if err != nil { t.Fatalf("NewValidator() err = %v, want nil", err) } for _, tc := range []signerVerifierKIDTestCase{ { tag: "verifier with custom kid different from header generated with custom kid", signerCustomKID: refString("1234"), verifierCustomKID: refString("123"), }, { tag: "verifier with custom kid different from header generated with tink kid", signerKID: refString("5678"), verifierCustomKID: refString("1234"), }, { tag: "verifier with both tink and custom kid", verifierCustomKID: refString("1234"), verifierKID: refString("1234"), }, { tag: "verifier with tink kid and token without kid in header", verifierKID: refString("1234"), }, } { t.Run(tc.tag, func(t *testing.T) { s, err := createESSigner(tc.signerCustomKID) if err != nil { t.Fatal(err) } v, err := createESVerifier(tc.verifierCustomKID) if err != nil { t.Fatal(err) } compact, err := s.SignAndEncodeWithKID(rawJWT, tc.signerKID) if err != nil { t.Fatalf("s.SignAndEncodeWithKID(kid = %v) err = %v, want nil", tc.signerKID, err) } if _, err := v.VerifyAndDecodeWithKID(compact, validator, tc.verifierKID); err == nil { t.Fatalf("s.VerifyAndDecodeWithKID(kid = %v) err = nil, want error", tc.verifierKID) } }) } } func TestVerifierModifiedCompact(t *testing.T) { rawJWT, err := NewRawJWT(&RawJWTOptions{TypeHeader: refString("JWT"), WithoutExpiration: true}) if err != nil { t.Fatalf("NewRawJWT() err = %v, want nil", err) } validator, err := NewValidator(&ValidatorOpts{ExpectedTypeHeader: refString("JWT"), AllowMissingExpiration: true}) if err != nil { t.Fatalf("NewValidator() err = %v, want nil", err) } s, err := createESSigner(nil) if err != nil { t.Fatal(err) } v, err := createESVerifier(nil) if err != nil { t.Fatal(err) } compact, err := s.SignAndEncodeWithKID(rawJWT, nil) if err != nil { t.Fatalf("s.SignAndEncodeWithKID() err = %v, want nil", err) } if _, err := v.VerifyAndDecodeWithKID(compact, validator, nil); err != nil { t.Errorf("VerifyAndDecodeWithKID() err = %v, want nil", err) } for _, invalid := range []string{ compact + "x", compact + " ", "x" + compact, " " + compact, } { if _, err := v.VerifyAndDecodeWithKID(invalid, validator, nil); err == nil { t.Errorf("VerifyAndDecodeWithKID() err = nil, want error") } } } func TestVerifierInvalidInputs(t *testing.T) { validator, err := NewValidator(&ValidatorOpts{AllowMissingExpiration: true}) if err != nil { t.Fatalf("NewValidator() err = %v, want nil", err) } v, err := createESVerifier(nil) if err != nil { t.Fatal(err) } for _, invalid := range []string{ "eyJhbGciOiJUzI1NiJ9.e30.YWJj.", "eyJhbGciOiJUzI1NiJ9?.e30.YWJj", "eyJhbGciOiJUzI1NiJ9.e30?.YWJj", "eyJhbGciOiJUzI1NiJ9.e30.YWJj?", "eyJhbGciOiJUzI1NiJ9.YWJj", } { if _, err := v.VerifyAndDecodeWithKID(invalid, validator, nil); err == nil { t.Errorf("v.VerifyAndDecodeWithKID(compact = %q) err = nil, want error", invalid) } } } func TestNewSignerWithNilTinkSignerFails(t *testing.T) { if _, err := newSignerWithKID(nil, "ES256", nil); err == nil { t.Errorf("newSignerWithKID(nil, 'ES256', nil) err = nil, want error") } } func TestNewVerifierWithNilTinkVerifierFails(t *testing.T) { if _, err := newVerifierWithKID(nil, "ES256", nil); err == nil { t.Errorf("newVerifierWithKID(nil, 'ES256', nil) err = nil, want error") } } ================================================ FILE: go/jwt/jwt_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt_test import ( "bytes" "encoding/json" "fmt" "log" "time" "github.com/google/tink/go/insecurecleartextkeyset" "github.com/google/tink/go/jwt" "github.com/google/tink/go/keyset" ) // [START jwt-signature-example] func Example_signAndVerify() { // A private keyset created with // "tinkey create-keyset --key-template=JWT_ES256 --out private_keyset.cfg". // Note that this keyset has the secret key information in cleartext. privateJSONKeyset := `{ "primaryKeyId": 1742360595, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey", "value": "GiBgVYdAPg3Fa2FVFymGDYrI1trHMzVjhVNEMpIxG7t0HRJGIiBeoDMF9LS5BDCh6YgqE3DjHwWwnEKEI3WpPf8izEx1rRogbjQTXrTcw/1HKiiZm2Hqv41w7Vd44M9koyY/+VsP+SAQAQ==", "keyMaterialType": "ASYMMETRIC_PRIVATE" }, "status": "ENABLED", "keyId": 1742360595, "outputPrefixType": "TINK" } ] }` // The corresponding public keyset created with // "tinkey create-public-keyset --in private_keyset.cfg" publicJSONKeyset := `{ "primaryKeyId": 1742360595, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey", "value": "EAEaIG40E1603MP9RyoomZth6r+NcO1XeODPZKMmP/lbD/kgIiBeoDMF9LS5BDCh6YgqE3DjHwWwnEKEI3WpPf8izEx1rQ==", "keyMaterialType": "ASYMMETRIC_PUBLIC" }, "status": "ENABLED", "keyId": 1742360595, "outputPrefixType": "TINK" } ] }` // Create a keyset handle from the cleartext private keyset in the previous // step. The keyset handle provides abstract access to the underlying keyset to // limit the access of the raw key material. WARNING: In practice, // it is unlikely you will want to use a insecurecleartextkeyset, as it implies // that your key material is passed in cleartext, which is a security risk. // Consider encrypting it with a remote key in Cloud KMS, AWS KMS or HashiCorp Vault. // See https://github.com/google/tink/blob/master/docs/GOLANG-HOWTO.md#storing-and-loading-existing-keysets. privateKeysetHandle, err := insecurecleartextkeyset.Read( keyset.NewJSONReader(bytes.NewBufferString(privateJSONKeyset))) if err != nil { log.Fatal(err) } // Retrieve the JWT Signer primitive from privateKeysetHandle. signer, err := jwt.NewSigner(privateKeysetHandle) if err != nil { log.Fatal(err) } // Use the primitive to create and sign a token. In this case, the primary key of the // keyset will be used (which is also the only key in this example). expiresAt := time.Now().Add(time.Hour) audience := "example audience" subject := "example subject" rawJWT, err := jwt.NewRawJWT(&jwt.RawJWTOptions{ Audience: &audience, Subject: &subject, ExpiresAt: &expiresAt, }) if err != nil { log.Fatal(err) } token, err := signer.SignAndEncode(rawJWT) if err != nil { log.Fatal(err) } // Create a keyset handle from the keyset containing the public key. Because the // public keyset does not contain any secrets, we can use [keyset.ReadWithNoSecrets]. publicKeysetHandle, err := keyset.ReadWithNoSecrets( keyset.NewJSONReader(bytes.NewBufferString(publicJSONKeyset))) if err != nil { log.Fatal(err) } // Retrieve the Verifier primitive from publicKeysetHandle. verifier, err := jwt.NewVerifier(publicKeysetHandle) if err != nil { log.Fatal(err) } // Verify the signed token. validator, err := jwt.NewValidator(&jwt.ValidatorOpts{ExpectedAudience: &audience}) if err != nil { log.Fatal(err) } verifiedJWT, err := verifier.VerifyAndDecode(token, validator) if err != nil { log.Fatal(err) } // Extract subject claim from the token. if !verifiedJWT.HasSubject() { log.Fatal(err) } extractedSubject, err := verifiedJWT.Subject() if err != nil { log.Fatal(err) } fmt.Println(extractedSubject) // Output: example subject } // [END jwt-signature-example] // [START jwt-generate-jwks-example] func Example_generateJWKS() { // A Tink keyset in JSON format with one JWT public key. publicJSONKeyset := `{ "primaryKeyId": 1742360595, "key": [ { "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey", "value": "EAEaIG40E1603MP9RyoomZth6r+NcO1XeODPZKMmP/lbD/kgIiBeoDMF9LS5BDCh6YgqE3DjHwWwnEKEI3WpPf8izEx1rQ==", "keyMaterialType": "ASYMMETRIC_PUBLIC" }, "status": "ENABLED", "keyId": 1742360595, "outputPrefixType": "TINK" } ] }` // Create a keyset handle from the keyset containing the public key. Because the // public keyset does not contain any secrets, we can use [keyset.ReadWithNoSecrets]. publicKeysetHandle, err := keyset.ReadWithNoSecrets( keyset.NewJSONReader(bytes.NewBufferString(publicJSONKeyset))) if err != nil { log.Fatal(err) } // Create a publicJWKset from publicKeysetHandle. publicJWKset, err := jwt.JWKSetFromPublicKeysetHandle(publicKeysetHandle) if err != nil { log.Fatal(err) } // Remove whitespace so that we can compare it to the expected string. compactPublicJWKset := &bytes.Buffer{} err = json.Compact(compactPublicJWKset, publicJWKset) if err != nil { log.Fatal(err) } fmt.Println(compactPublicJWKset.String()) // Output: // {"keys":[{"alg":"ES256","crv":"P-256","key_ops":["verify"],"kid":"Z9pQEw","kty":"EC","use":"sig","x":"bjQTXrTcw_1HKiiZm2Hqv41w7Vd44M9koyY_-VsP-SA","y":"XqAzBfS0uQQwoemIKhNw4x8FsJxChCN1qT3_IsxMda0"}]} } // [END jwt-generate-jwks-example] // [START jwt-verify-with-jwks-example] func Example_verifyWithJWKS() { // A signed token with the subject 'example subject', audience 'example audience'. // and expiration on 2023-03-23. token := `eyJhbGciOiJFUzI1NiIsICJraWQiOiJaOXBRRXcifQ.eyJhdWQiOiJleGFtcGxlIGF1ZGllbmNlIiwgImV4cCI6MTY3OTUzMzIwMCwgInN1YiI6ImV4YW1wbGUgc3ViamVjdCJ9.ZvI0T84fJ1aouiB7n62kHOmbm0Hpfiz0JtYs15XVDT8KyoVYZ8hu_DGJUN47BqZIbuOI-rdu9TxJvutj8uF3Ow` // A public keyset in the JWK set format. publicJWKset := `{ "keys":[ { "alg":"ES256", "crv":"P-256", "key_ops":["verify"], "kid":"Z9pQEw", "kty":"EC", "use":"sig", "x":"bjQTXrTcw_1HKiiZm2Hqv41w7Vd44M9koyY_-VsP-SA", "y":"XqAzBfS0uQQwoemIKhNw4x8FsJxChCN1qT3_IsxMda0" } ] }` // Create a keyset handle from publicJWKset. publicKeysetHandle, err := jwt.JWKSetToPublicKeysetHandle([]byte(publicJWKset)) if err != nil { log.Fatal(err) } // Retrieve the Verifier primitive from publicKeysetHandle. verifier, err := jwt.NewVerifier(publicKeysetHandle) if err != nil { log.Fatal(err) } // Verify the signed token. For this example, we use a fixed date. Usually, you would // either not set FixedNow, or set it to the current time. audience := "example audience" validator, err := jwt.NewValidator(&jwt.ValidatorOpts{ ExpectedAudience: &audience, FixedNow: time.Date(2023, 3, 23, 0, 0, 0, 0, time.UTC), }) if err != nil { log.Fatal(err) } verifiedJWT, err := verifier.VerifyAndDecode(token, validator) if err != nil { log.Fatal(err) } // Extract subject claim from the token. if !verifiedJWT.HasSubject() { log.Fatal(err) } extractedSubject, err := verifiedJWT.Subject() if err != nil { log.Fatal(err) } fmt.Println(extractedSubject) // Output: example subject } // [END jwt-verify-with-jwks-example] // [START jwt-mac-example] func Example_computeMACAndVerify() { // Generate a keyset handle. handle, err := keyset.NewHandle(jwt.HS256Template()) if err != nil { log.Fatal(err) } // TODO: Save the keyset to a safe location. DO NOT hardcode it in source // code. Consider encrypting it with a remote key in a KMS. See // https://github.com/google/tink/blob/master/docs/GOLANG-HOWTO.md#storing-and-loading-existing-keysets // Create a token and compute a MAC for it. expiresAt := time.Now().Add(time.Hour) audience := "example audience" customClaims := map[string]any{"custom": "my custom claim"} rawJWT, err := jwt.NewRawJWT(&jwt.RawJWTOptions{ Audience: &audience, CustomClaims: customClaims, ExpiresAt: &expiresAt, }) if err != nil { log.Fatal(err) } mac, err := jwt.NewMAC(handle) if err != nil { log.Fatal(err) } token, err := mac.ComputeMACAndEncode(rawJWT) if err != nil { log.Fatal(err) } // Verify the MAC. validator, err := jwt.NewValidator(&jwt.ValidatorOpts{ExpectedAudience: &audience}) if err != nil { log.Fatal(err) } verifiedJWT, err := mac.VerifyMACAndDecode(token, validator) if err != nil { log.Fatal(err) } // Extract a custom claim from the token. if !verifiedJWT.HasStringClaim("custom") { log.Fatal(err) } extractedCustomClaim, err := verifiedJWT.StringClaim("custom") if err != nil { log.Fatal(err) } fmt.Println(extractedCustomClaim) // Output: my custom claim } // [END jwt-mac-example] ================================================ FILE: go/jwt/jwt_validator.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "fmt" "time" ) const ( jwtMaxClockSkewMinutes = 10 ) // ValidatorOpts define validation options for JWT validators. type ValidatorOpts struct { ExpectedTypeHeader *string ExpectedIssuer *string ExpectedAudience *string IgnoreTypeHeader bool IgnoreAudiences bool IgnoreIssuer bool AllowMissingExpiration bool ExpectIssuedInThePast bool ClockSkew time.Duration FixedNow time.Time // Deprecated: Use ExpectedAudience instead. ExpectedAudiences *string } // Validator defines how JSON Web Tokens (JWT) should be validated. type Validator struct { opts ValidatorOpts } // NewValidator creates a new Validator. func NewValidator(opts *ValidatorOpts) (*Validator, error) { if opts == nil { return nil, fmt.Errorf("ValidatorOpts can't be nil") } if opts.ExpectedAudiences != nil { if opts.ExpectedAudience != nil { return nil, fmt.Errorf("ExpectedAudiences and ExpectedAudience can't be set at the same time") } opts.ExpectedAudience = opts.ExpectedAudiences opts.ExpectedAudiences = nil } if opts.ExpectedTypeHeader != nil && opts.IgnoreTypeHeader { return nil, fmt.Errorf("ExpectedTypeHeader and IgnoreTypeHeader cannot be used together") } if opts.ExpectedIssuer != nil && opts.IgnoreIssuer { return nil, fmt.Errorf("ExpectedIssuer and IgnoreIssuer cannot be used together") } if opts.ExpectedAudience != nil && opts.IgnoreAudiences { return nil, fmt.Errorf("ExpectedAudience and IgnoreAudience cannot be used together") } if opts.ClockSkew.Minutes() > jwtMaxClockSkewMinutes { return nil, fmt.Errorf("clock skew too large, max is %d minutes", jwtMaxClockSkewMinutes) } return &Validator{ opts: *opts, }, nil } // Validate validates a rawJWT according to the options provided. func (v *Validator) Validate(rawJWT *RawJWT) error { if rawJWT == nil { return fmt.Errorf("rawJWT can't be nil") } if err := v.validateTimestamps(rawJWT); err != nil { return err } if err := v.validateTypeHeader(rawJWT); err != nil { return fmt.Errorf("validating type header: %v", err) } if err := v.validateAudiences(rawJWT); err != nil { return fmt.Errorf("validating audience claim: %v", err) } if err := v.validateIssuer(rawJWT); err != nil { return fmt.Errorf("validating issuer claim: %v", err) } return nil } func (v *Validator) validateTimestamps(rawJWT *RawJWT) error { now := time.Now() if !v.opts.FixedNow.IsZero() { now = v.opts.FixedNow } if !rawJWT.HasExpiration() && !v.opts.AllowMissingExpiration { return fmt.Errorf("token doesn't have an expiration set") } if rawJWT.HasExpiration() { exp, err := rawJWT.ExpiresAt() if err != nil { return err } if !exp.After(now.Add(-v.opts.ClockSkew)) { return errJwtExpired } } if rawJWT.HasNotBefore() { nbf, err := rawJWT.NotBefore() if err != nil { return err } if nbf.After(now.Add(v.opts.ClockSkew)) { return fmt.Errorf("token cannot be used yet") } } if v.opts.ExpectIssuedInThePast { iat, err := rawJWT.IssuedAt() if err != nil { return err } if iat.After(now.Add(v.opts.ClockSkew)) { return fmt.Errorf("token has an invalid iat claim in the future") } } return nil } func (v *Validator) validateTypeHeader(rawJWT *RawJWT) error { skip, err := validateFieldPresence(v.opts.IgnoreTypeHeader, rawJWT.HasTypeHeader(), v.opts.ExpectedTypeHeader != nil) if err != nil { return err } if skip { return nil } typeHeader, err := rawJWT.TypeHeader() if err != nil { return err } if typeHeader != *v.opts.ExpectedTypeHeader { return fmt.Errorf("wrong 'type header' type") } return nil } func (v *Validator) validateIssuer(rawJWT *RawJWT) error { skip, err := validateFieldPresence(v.opts.IgnoreIssuer, rawJWT.HasIssuer(), v.opts.ExpectedIssuer != nil) if err != nil { return err } if skip { return nil } issuer, err := rawJWT.Issuer() if err != nil { return err } if issuer != *v.opts.ExpectedIssuer { return fmt.Errorf("got %s, want %s", issuer, *v.opts.ExpectedIssuer) } return nil } func (v *Validator) validateAudiences(rawJWT *RawJWT) error { skip, err := validateFieldPresence(v.opts.IgnoreAudiences, rawJWT.HasAudiences(), v.opts.ExpectedAudience != nil) if err != nil { return err } if skip { return nil } audiences, err := rawJWT.Audiences() if err != nil { return err } for i, aud := range audiences { if aud == *v.opts.ExpectedAudience { break } if i == len(audiences)-1 { return fmt.Errorf("%s not found", *v.opts.ExpectedAudience) } } return nil } func validateFieldPresence(ignore bool, isPresent bool, isExpected bool) (bool, error) { if ignore { return true, nil } if !isExpected && !isPresent { return true, nil } if !isExpected && isPresent { return false, fmt.Errorf("token has claim but validator doesn't expect it") } if isExpected && !isPresent { return false, fmt.Errorf("claim was expected but isn't present") } return false, nil } ================================================ FILE: go/jwt/jwt_validator_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt_test import ( "testing" "time" "github.com/google/tink/go/jwt" ) type validationTestCase struct { tag string tokenOpts *jwt.RawJWTOptions validatorOpts *jwt.ValidatorOpts } func TestNewValidatorFailure(t *testing.T) { for _, tc := range []validationTestCase{ { tag: "combining ExpectedTypeHeader and IgnoreTypeHeader", validatorOpts: &jwt.ValidatorOpts{ ExpectedTypeHeader: refString("should fail"), IgnoreTypeHeader: true, }, }, { tag: "combining ExpectedIssuer and IgnoreIssuer", validatorOpts: &jwt.ValidatorOpts{ ExpectedIssuer: refString("should fail"), IgnoreIssuer: true, }, }, { tag: "combining ExpectedAudience and IgnoreAudiences", validatorOpts: &jwt.ValidatorOpts{ ExpectedAudience: refString("should fail"), IgnoreAudiences: true, }, }, { tag: "combining ExpectedAudiences and IgnoreAudiences", validatorOpts: &jwt.ValidatorOpts{ ExpectedAudiences: refString("should fail"), IgnoreAudiences: true, }, }, { tag: "both ExpectedAudience and ExpectedAudiences are set", validatorOpts: &jwt.ValidatorOpts{ ExpectedAudience: refString("aud"), ExpectedAudiences: refString("aud"), }, }, { tag: "invalid clock skew", validatorOpts: &jwt.ValidatorOpts{ ClockSkew: time.Minute * 11, }, }, { tag: "validator opts can't be nil", }, } { t.Run(tc.tag, func(t *testing.T) { if _, err := jwt.NewValidator(tc.validatorOpts); err == nil { t.Errorf("NewValidator(%v) err = nil, want error", tc.validatorOpts) } }) } } func TestValidationFailures(t *testing.T) { for _, tc := range []validationTestCase{ { tag: "expired token", tokenOpts: &jwt.RawJWTOptions{ ExpiresAt: refTime(100), }, validatorOpts: &jwt.ValidatorOpts{ FixedNow: time.Unix(500, 0), }, }, { tag: "no expiration and AllowMissingExpiration = false", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, }, validatorOpts: &jwt.ValidatorOpts{}, }, { tag: "token expiry equals current time", tokenOpts: &jwt.RawJWTOptions{ ExpiresAt: refTime(123), }, validatorOpts: &jwt.ValidatorOpts{ FixedNow: time.Unix(123, 0), }, }, { tag: "not before in the future", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, NotBefore: refTime(1500), }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, FixedNow: time.Unix(1000, 0), }, }, { tag: "issued in the future with ExpectIssuedInThePast = true", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, IssuedAt: refTime(5000), }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, FixedNow: time.Unix(1000, 0), ExpectIssuedInThePast: true, }, }, { tag: "without issued at with ExpectIssuedInThePast = true", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, ExpectIssuedInThePast: true, }, }, { tag: "no type header and RequiresTypeHeader = true", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, ExpectedTypeHeader: refString("typeHeader"), }, }, { tag: "invalid type header", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, TypeHeader: refString("typeHeader"), }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, ExpectedTypeHeader: refString("different"), }, }, { tag: "type header in token but no type header in validator", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, TypeHeader: refString("typeHeader"), }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, }, }, { tag: "issuer required but not specified", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, ExpectedIssuer: refString("tink-issuer"), }, }, { tag: "invalid issuer", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, Issuer: refString("tink-issuer"), }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, ExpectedIssuer: refString("different"), }, }, { tag: "issuer in token but not in validator", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, Issuer: refString("issuer"), }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, }, }, { tag: "audience required but no specified", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, ExpectedAudience: refString("tink-audience"), }, }, { tag: "audience required but no specified, deprecated", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, ExpectedAudiences: refString("tink-audience"), }, }, { tag: "invalid audience", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, Audience: refString("tink-audience"), }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, ExpectedAudience: refString("audience"), }, }, { tag: "invalid audience, deprecated", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, Audience: refString("tink-audience"), }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, ExpectedAudiences: refString("audience"), }, }, { tag: "audience in token but not in validator", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, Audience: refString("audience"), }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, }, }, } { t.Run(tc.tag, func(t *testing.T) { token, err := jwt.NewRawJWT(tc.tokenOpts) if err != nil { t.Fatalf("jwt.NewRawJWT(%v) err = %v, want nil", tc.tokenOpts, err) } validator, err := jwt.NewValidator(tc.validatorOpts) if err != nil { t.Fatalf("jwt.NewValidator(%v) err = %v, want nil", tc.validatorOpts, err) } if err := validator.Validate(token); err == nil { t.Errorf("validator.Validate(%v) err = nil, want error", token) } }) } } func TestExpiredTokenValidationReturnsExpiredErr(t *testing.T) { tokenOpts := &jwt.RawJWTOptions{ ExpiresAt: refTime(100), } expiredToken, err := jwt.NewRawJWT(tokenOpts) if err != nil { t.Fatalf("jwt.NewRawJWT(tokenOpts) err = %v, want nil", err) } validatorOpts := &jwt.ValidatorOpts{ FixedNow: time.Unix(500, 0), } validator, err := jwt.NewValidator(validatorOpts) if err != nil { t.Fatalf("jwt.NewValidator(validatorOpts) err = %v, want nil", err) } validationErr := validator.Validate(expiredToken) if validationErr == nil { t.Errorf("validator.Validate(expiredToken) err = nil, want error") } if !jwt.IsExpirationErr(validationErr) { t.Errorf("jwt.IsExpirationErr(validationErr) = false, want true") } } func TestExpirationGetsValidatedFirst(t *testing.T) { tokenOpts := &jwt.RawJWTOptions{ ExpiresAt: refTime(100), Audience: refString("invalidAudience"), } expiredTokenWithInvalidAudience, err := jwt.NewRawJWT(tokenOpts) if err != nil { t.Fatalf("jwt.NewRawJWT(tokenOpts) err = %v, want nil", err) } validatorOpts := &jwt.ValidatorOpts{ ExpectedAudiences: refString("audience"), FixedNow: time.Unix(500, 0), } validator, err := jwt.NewValidator(validatorOpts) if err != nil { t.Fatalf("jwt.NewValidator(validatorOpts) err = %v, want nil", err) } validationErr := validator.Validate(expiredTokenWithInvalidAudience) if validationErr == nil { t.Errorf("validator.Validate(expiredTokenWithInvalidAudience) err = nil, want error") } if !jwt.IsExpirationErr(validationErr) { t.Errorf("jwt.IsExpirationErr(validationErr) = false, want true") } } func TestValidationSuccess(t *testing.T) { for _, tc := range []validationTestCase{ { tag: "unexpired token", tokenOpts: &jwt.RawJWTOptions{ ExpiresAt: refTime(1000), }, validatorOpts: &jwt.ValidatorOpts{ FixedNow: time.Unix(100, 0), }, }, { tag: "expired with clock slew", tokenOpts: &jwt.RawJWTOptions{ ExpiresAt: refTime(400), }, validatorOpts: &jwt.ValidatorOpts{ FixedNow: time.Unix(500, 0), ClockSkew: time.Second * 200, }, }, { tag: "not before in the past", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, NotBefore: refTime(500), }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, FixedNow: time.Unix(1000, 0), }, }, { tag: "not before equals now", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, NotBefore: refTime(500), }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, FixedNow: time.Unix(500, 0), }, }, { tag: "not before in near future with clock skew", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, NotBefore: refTime(600), }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, FixedNow: time.Unix(500, 0), ClockSkew: time.Second * 200, }, }, { tag: "issued in the past", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, IssuedAt: refTime(500), }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, FixedNow: time.Unix(1000, 0), }, }, { tag: "issued in the future", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, IssuedAt: refTime(5000), }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, FixedNow: time.Unix(1000, 0), }, }, { tag: "without issued at", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, }, }, { tag: "issued in the past with ExpectIssuedInThePast", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, IssuedAt: refTime(500), }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, ExpectIssuedInThePast: true, FixedNow: time.Unix(1000, 0), }, }, { tag: "issued in the past with ExpectIssuedInThePast and clock skew", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, IssuedAt: refTime(1100), }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, ExpectIssuedInThePast: true, FixedNow: time.Unix(1000, 0), ClockSkew: time.Second * 200, }, }, { tag: "expected type header", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, TypeHeader: refString("typeHeader"), }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, ExpectedTypeHeader: refString("typeHeader"), }, }, { tag: "ignore type header", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, TypeHeader: refString("typeHeader"), }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, IgnoreTypeHeader: true, }, }, { tag: "expected issuer", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, Issuer: refString("issuer"), }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, ExpectedIssuer: refString("issuer"), }, }, { tag: "ignore issuer", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, Issuer: refString("issuer"), }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, IgnoreIssuer: true, }, }, { tag: "expected audience", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, Audience: refString("audience"), }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, ExpectedAudience: refString("audience"), }, }, { tag: "deprecated expected audiences", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, Audience: refString("audience"), }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, ExpectedAudiences: refString("audience"), }, }, { tag: "ignore audience", tokenOpts: &jwt.RawJWTOptions{ WithoutExpiration: true, Audience: refString("audience"), }, validatorOpts: &jwt.ValidatorOpts{ AllowMissingExpiration: true, IgnoreAudiences: true, }, }, } { t.Run(tc.tag, func(t *testing.T) { token, err := jwt.NewRawJWT(tc.tokenOpts) if err != nil { t.Fatalf("NewRawJWT(%v) err = %v, want nil", tc.tokenOpts, err) } validator, err := jwt.NewValidator(tc.validatorOpts) if err != nil { t.Fatalf("NewValidator(%v) err = %v, want nil", tc.validatorOpts, err) } if err := validator.Validate(token); err != nil { t.Errorf("validator.Validate(%v) err = %v, want nil", token, err) } }) } } ================================================ FILE: go/jwt/jwt_verifier.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt // Verifier is the interface for verifying signed JWTs. // See RFC 7519 and RFC 7515. Security guarantees: similar to Verifier. type Verifier interface { // Verifies and decodes a JWT token in the JWS compact serialization format. // // The JWT is validated against the rules in validator. That is, every claim // in validator must also be present in the JWT. For example, if validator // contains an issuer (iss) claim, the JWT must contain an identical claim. // The JWT can contain claims that are NOT in the validator. However, if the // JWT contains a list of audiences, the validator must also contain an // audience in the list. // // If the JWT contains timestamp claims such as expiration (exp), issued_at // (iat) or not_before (nbf), they will also be validated. validator allows to // set a clock skew, to deal with small clock differences among different // machines. VerifyAndDecode(compact string, validator *Validator) (*VerifiedJWT, error) } ================================================ FILE: go/jwt/jwt_verifier_factory.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "fmt" "github.com/google/tink/go/core/primitiveset" "github.com/google/tink/go/keyset" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // NewVerifier generates a new instance of the JWT Verifier primitive. func NewVerifier(handle *keyset.Handle) (Verifier, error) { if handle == nil { return nil, fmt.Errorf("keyset handle can't be nil") } ps, err := handle.PrimitivesWithKeyManager(nil) if err != nil { return nil, fmt.Errorf("jwt_verifier_factory: cannot obtain primitive set: %v", err) } return newWrappedVerifier(ps) } // wrappedVerifier is a JWT Verifier implementation that uses the underlying primitive set for JWT Verifier. type wrappedVerifier struct { ps *primitiveset.PrimitiveSet } var _ Verifier = (*wrappedVerifier)(nil) func newWrappedVerifier(ps *primitiveset.PrimitiveSet) (*wrappedVerifier, error) { if _, ok := (ps.Primary.Primitive).(*verifierWithKID); !ok { return nil, fmt.Errorf("jwt_verifier_factory: not a JWT Verifier primitive") } for _, primitives := range ps.Entries { for _, p := range primitives { if p.PrefixType != tinkpb.OutputPrefixType_RAW && p.PrefixType != tinkpb.OutputPrefixType_TINK { return nil, fmt.Errorf("jwt_verifier_factory: invalid OutputPrefixType: %s", p.PrefixType) } if _, ok := (p.Primitive).(*verifierWithKID); !ok { return nil, fmt.Errorf("jwt_verifier_factory: not a JWT Verifier primitive") } } } return &wrappedVerifier{ps: ps}, nil } func (w *wrappedVerifier) VerifyAndDecode(compact string, validator *Validator) (*VerifiedJWT, error) { var interestingErr error for _, s := range w.ps.Entries { for _, e := range s { p, ok := e.Primitive.(*verifierWithKID) if !ok { return nil, fmt.Errorf("jwt_verifier_factory: not a JWT Verifier primitive") } verifiedJWT, err := p.VerifyAndDecodeWithKID(compact, validator, keyID(e.KeyID, e.PrefixType)) if err == nil { return verifiedJWT, nil } if err != errJwtVerification { // any error that is not the generic errJwtVerification is considered interesting interestingErr = err } } } if interestingErr != nil { return nil, interestingErr } return nil, errJwtVerification } ================================================ FILE: go/jwt/jwt_verifier_kid.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "fmt" "github.com/google/tink/go/tink" ) type verifierWithKID struct { tv tink.Verifier algorithm string customKID *string } func newVerifierWithKID(tv tink.Verifier, algorithm string, customKID *string) (*verifierWithKID, error) { if tv == nil { return nil, fmt.Errorf("tink verifier can't be nil") } return &verifierWithKID{ tv: tv, algorithm: algorithm, customKID: customKID, }, nil } // VerifyAndDecodeWithKID verifies a digital signature in a compact serialized JWT. // It then validates the token, and returns a VerifiedJWT or an error. func (v *verifierWithKID) VerifyAndDecodeWithKID(compact string, validator *Validator, kid *string) (*VerifiedJWT, error) { sig, content, err := splitSignedCompact(compact) if err != nil { return nil, errJwtVerification } if err := v.tv.Verify(sig, []byte(content)); err != nil { return nil, errJwtVerification } rawJWT, err := decodeUnsignedTokenAndValidateHeader(content, v.algorithm, kid, v.customKID) if err != nil { return nil, errJwtVerification } if err := validator.Validate(rawJWT); err != nil { return nil, err } return newVerifiedJWT(rawJWT) } ================================================ FILE: go/jwt/raw_jwt.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "fmt" "time" "unicode/utf8" spb "google.golang.org/protobuf/types/known/structpb" ) const ( claimIssuer = "iss" claimSubject = "sub" claimAudience = "aud" claimExpiration = "exp" claimNotBefore = "nbf" claimIssuedAt = "iat" claimJWTID = "jti" jwtTimestampMax = 253402300799 jwtTimestampMin = 0 ) // RawJWTOptions represent an unsigned JSON Web Token (JWT), https://tools.ietf.org/html/rfc7519. // // It contains all payload claims and a subset of the headers. It does not // contain any headers that depend on the key, such as "alg" or "kid", because // these headers are chosen when the token is signed and encoded, and should not // be chosen by the user. This ensures that the key can be changed without any // changes to the user code. type RawJWTOptions struct { Audiences []string Audience *string Subject *string Issuer *string JWTID *string IssuedAt *time.Time ExpiresAt *time.Time NotBefore *time.Time CustomClaims map[string]any TypeHeader *string WithoutExpiration bool } // RawJWT is an unsigned JSON Web Token (JWT), https://tools.ietf.org/html/rfc7519. type RawJWT struct { jsonpb *spb.Struct typeHeader *string } // NewRawJWT constructs a new RawJWT token based on the RawJwtOptions provided. func NewRawJWT(opts *RawJWTOptions) (*RawJWT, error) { if opts == nil { return nil, fmt.Errorf("jwt options can't be nil") } payload, err := createPayload(opts) if err != nil { return nil, err } if err := validatePayload(payload); err != nil { return nil, err } return &RawJWT{ jsonpb: payload, typeHeader: opts.TypeHeader, }, nil } // NewRawJWTFromJSON builds a RawJWT from a marshaled JSON. // Users shouldn't call this function and instead use NewRawJWT. func NewRawJWTFromJSON(typeHeader *string, jsonPayload []byte) (*RawJWT, error) { payload := &spb.Struct{} if err := payload.UnmarshalJSON(jsonPayload); err != nil { return nil, err } if err := validatePayload(payload); err != nil { return nil, err } return &RawJWT{ jsonpb: payload, typeHeader: typeHeader, }, nil } // JSONPayload marshals a RawJWT payload to JSON. func (r *RawJWT) JSONPayload() ([]byte, error) { return r.jsonpb.MarshalJSON() } // HasTypeHeader returns whether a RawJWT contains a type header. func (r *RawJWT) HasTypeHeader() bool { return r.typeHeader != nil } // TypeHeader returns the JWT type header. func (r *RawJWT) TypeHeader() (string, error) { if !r.HasTypeHeader() { return "", fmt.Errorf("no type header present") } return *r.typeHeader, nil } // HasAudiences checks whether a JWT contains the audience claim ('aud'). func (r *RawJWT) HasAudiences() bool { return r.hasField(claimAudience) } // Audiences returns a list of audiences from the 'aud' claim. If the 'aud' claim is a single string, it is converted into a list with a single entry. func (r *RawJWT) Audiences() ([]string, error) { aud, ok := r.field(claimAudience) if !ok { return nil, fmt.Errorf("no audience claim found") } if err := validateAudienceClaim(aud); err != nil { return nil, err } if val, isString := aud.GetKind().(*spb.Value_StringValue); isString { return []string{val.StringValue}, nil } s := make([]string, 0, len(aud.GetListValue().GetValues())) for _, a := range aud.GetListValue().GetValues() { s = append(s, a.GetStringValue()) } return s, nil } // HasSubject checks whether a JWT contains an issuer claim ('sub'). func (r *RawJWT) HasSubject() bool { return r.hasField(claimSubject) } // Subject returns the subject claim ('sub') or an error if no claim is present. func (r *RawJWT) Subject() (string, error) { return r.stringClaim(claimSubject) } // HasIssuer checks whether a JWT contains an issuer claim ('iss'). func (r *RawJWT) HasIssuer() bool { return r.hasField(claimIssuer) } // Issuer returns the issuer claim ('iss') or an error if no claim is present. func (r *RawJWT) Issuer() (string, error) { return r.stringClaim(claimIssuer) } // HasJWTID checks whether a JWT contains an JWT ID claim ('jti'). func (r *RawJWT) HasJWTID() bool { return r.hasField(claimJWTID) } // JWTID returns the JWT ID claim ('jti') or an error if no claim is present. func (r *RawJWT) JWTID() (string, error) { return r.stringClaim(claimJWTID) } // HasIssuedAt checks whether a JWT contains an issued at claim ('iat'). func (r *RawJWT) HasIssuedAt() bool { return r.hasField(claimIssuedAt) } // IssuedAt returns the issued at claim ('iat') or an error if no claim is present. func (r *RawJWT) IssuedAt() (time.Time, error) { return r.timeClaim(claimIssuedAt) } // HasExpiration checks whether a JWT contains an expiration time claim ('exp'). func (r *RawJWT) HasExpiration() bool { return r.hasField(claimExpiration) } // ExpiresAt returns the expiration claim ('exp') or an error if no claim is present. func (r *RawJWT) ExpiresAt() (time.Time, error) { return r.timeClaim(claimExpiration) } // HasNotBefore checks whether a JWT contains a not before claim ('nbf'). func (r *RawJWT) HasNotBefore() bool { return r.hasField(claimNotBefore) } // NotBefore returns the not before claim ('nbf') or an error if no claim is present. func (r *RawJWT) NotBefore() (time.Time, error) { return r.timeClaim(claimNotBefore) } // HasStringClaim checks whether a claim of type string is present. func (r *RawJWT) HasStringClaim(name string) bool { return !isRegisteredClaim(name) && r.hasClaimOfKind(name, &spb.Value{Kind: &spb.Value_StringValue{}}) } // StringClaim returns a custom string claim or an error if no claim is present. func (r *RawJWT) StringClaim(name string) (string, error) { if isRegisteredClaim(name) { return "", fmt.Errorf("claim '%q' is a registered claim", name) } return r.stringClaim(name) } // HasNumberClaim checks whether a claim of type number is present. func (r *RawJWT) HasNumberClaim(name string) bool { return !isRegisteredClaim(name) && r.hasClaimOfKind(name, &spb.Value{Kind: &spb.Value_NumberValue{}}) } // NumberClaim returns a custom number claim or an error if no claim is present. func (r *RawJWT) NumberClaim(name string) (float64, error) { if isRegisteredClaim(name) { return 0, fmt.Errorf("claim '%q' is a registered claim", name) } return r.numberClaim(name) } // HasBooleanClaim checks whether a claim of type boolean is present. func (r *RawJWT) HasBooleanClaim(name string) bool { return r.hasClaimOfKind(name, &spb.Value{Kind: &spb.Value_BoolValue{}}) } // BooleanClaim returns a custom bool claim or an error if no claim is present. func (r *RawJWT) BooleanClaim(name string) (bool, error) { val, err := r.customClaim(name) if err != nil { return false, err } b, ok := val.Kind.(*spb.Value_BoolValue) if !ok { return false, fmt.Errorf("claim '%q' is not a boolean", name) } return b.BoolValue, nil } // HasNullClaim checks whether a claim of type null is present. func (r *RawJWT) HasNullClaim(name string) bool { return r.hasClaimOfKind(name, &spb.Value{Kind: &spb.Value_NullValue{}}) } // HasArrayClaim checks whether a claim of type list is present. func (r *RawJWT) HasArrayClaim(name string) bool { return !isRegisteredClaim(name) && r.hasClaimOfKind(name, &spb.Value{Kind: &spb.Value_ListValue{}}) } // ArrayClaim returns a slice representing a JSON array for a claim or an error if the claim is empty. func (r *RawJWT) ArrayClaim(name string) ([]any, error) { val, err := r.customClaim(name) if err != nil { return nil, err } if val.GetListValue() == nil { return nil, fmt.Errorf("claim '%q' is not a list", name) } return val.GetListValue().AsSlice(), nil } // HasObjectClaim checks whether a claim of type JSON object is present. func (r *RawJWT) HasObjectClaim(name string) bool { return r.hasClaimOfKind(name, &spb.Value{Kind: &spb.Value_StructValue{}}) } // ObjectClaim returns a map representing a JSON object for a claim or an error if the claim is empty. func (r *RawJWT) ObjectClaim(name string) (map[string]any, error) { val, err := r.customClaim(name) if err != nil { return nil, err } if val.GetStructValue() == nil { return nil, fmt.Errorf("claim '%q' is not a JSON object", name) } return val.GetStructValue().AsMap(), err } // CustomClaimNames returns a list with the name of custom claims in a RawJWT. func (r *RawJWT) CustomClaimNames() []string { names := []string{} for key := range r.jsonpb.GetFields() { if !isRegisteredClaim(key) { names = append(names, key) } } return names } func (r *RawJWT) timeClaim(name string) (time.Time, error) { n, err := r.numberClaim(name) if err != nil { return time.Time{}, err } return time.Unix(int64(n), 0), err } func (r *RawJWT) numberClaim(name string) (float64, error) { val, ok := r.field(name) if !ok { return 0, fmt.Errorf("no '%q' claim found", name) } s, ok := val.Kind.(*spb.Value_NumberValue) if !ok { return 0, fmt.Errorf("claim '%q' is not a number", name) } return s.NumberValue, nil } func (r *RawJWT) stringClaim(name string) (string, error) { val, ok := r.field(name) if !ok { return "", fmt.Errorf("no '%q' claim found", name) } s, ok := val.Kind.(*spb.Value_StringValue) if !ok { return "", fmt.Errorf("claim '%q' is not a string", name) } if !utf8.ValidString(s.StringValue) { return "", fmt.Errorf("claim '%q' is not a valid utf-8 encoded string", name) } return s.StringValue, nil } func (r *RawJWT) hasClaimOfKind(name string, exp *spb.Value) bool { val, exist := r.field(name) if !exist || exp == nil { return false } var isKind bool switch exp.GetKind().(type) { case *spb.Value_StructValue: _, isKind = val.GetKind().(*spb.Value_StructValue) case *spb.Value_NullValue: _, isKind = val.GetKind().(*spb.Value_NullValue) case *spb.Value_BoolValue: _, isKind = val.GetKind().(*spb.Value_BoolValue) case *spb.Value_ListValue: _, isKind = val.GetKind().(*spb.Value_ListValue) case *spb.Value_StringValue: _, isKind = val.GetKind().(*spb.Value_StringValue) case *spb.Value_NumberValue: _, isKind = val.GetKind().(*spb.Value_NumberValue) default: isKind = false } return isKind } func (r *RawJWT) customClaim(name string) (*spb.Value, error) { if isRegisteredClaim(name) { return nil, fmt.Errorf("'%q' is a registered claim", name) } val, ok := r.field(name) if !ok { return nil, fmt.Errorf("claim '%q' not found", name) } return val, nil } func (r *RawJWT) hasField(name string) bool { _, ok := r.field(name) return ok } func (r *RawJWT) field(name string) (*spb.Value, bool) { val, ok := r.jsonpb.GetFields()[name] return val, ok } // createPayload creates a JSON payload from JWT options. func createPayload(opts *RawJWTOptions) (*spb.Struct, error) { if err := validateCustomClaims(opts.CustomClaims); err != nil { return nil, err } if opts.ExpiresAt == nil && !opts.WithoutExpiration { return nil, fmt.Errorf("jwt options must contain an expiration or must be marked WithoutExpiration") } if opts.ExpiresAt != nil && opts.WithoutExpiration { return nil, fmt.Errorf("jwt options can't be marked WithoutExpiration when expiration is specified") } if opts.Audience != nil && opts.Audiences != nil { return nil, fmt.Errorf("jwt options can either contain a single Audience or a list of Audiences but not both") } payload := &spb.Struct{ Fields: map[string]*spb.Value{}, } setStringValue(payload, claimJWTID, opts.JWTID) setStringValue(payload, claimIssuer, opts.Issuer) setStringValue(payload, claimSubject, opts.Subject) setStringValue(payload, claimAudience, opts.Audience) setTimeValue(payload, claimIssuedAt, opts.IssuedAt) setTimeValue(payload, claimNotBefore, opts.NotBefore) setTimeValue(payload, claimExpiration, opts.ExpiresAt) setAudiences(payload, claimAudience, opts.Audiences) for k, v := range opts.CustomClaims { val, err := spb.NewValue(v) if err != nil { return nil, err } setValue(payload, k, val) } return payload, nil } func validatePayload(payload *spb.Struct) error { if payload.Fields == nil || len(payload.Fields) == 0 { return nil } if err := validateAudienceClaim(payload.Fields[claimAudience]); err != nil { return err } for claim, val := range payload.GetFields() { if isRegisteredTimeClaim(claim) { if err := validateTimeClaim(claim, val); err != nil { return err } } if isRegisteredStringClaim(claim) { if err := validateStringClaim(claim, val); err != nil { return err } } } return nil } func validateStringClaim(claim string, val *spb.Value) error { v, ok := val.Kind.(*spb.Value_StringValue) if !ok { return fmt.Errorf("claim: '%q' MUST be a string", claim) } if !utf8.ValidString(v.StringValue) { return fmt.Errorf("claim: '%q' isn't a valid UTF-8 string", claim) } return nil } func validateTimeClaim(claim string, val *spb.Value) error { if _, ok := val.Kind.(*spb.Value_NumberValue); !ok { return fmt.Errorf("claim %q MUST be a numeric value, ", claim) } t := int64(val.GetNumberValue()) if t > jwtTimestampMax || t < jwtTimestampMin { return fmt.Errorf("invalid timestamp: '%d' for claim: %q", t, claim) } return nil } func validateAudienceClaim(val *spb.Value) error { if val == nil { return nil } _, isString := val.Kind.(*spb.Value_StringValue) l, isList := val.Kind.(*spb.Value_ListValue) if !isList && !isString { return fmt.Errorf("audience claim MUST be a list with at least one string or a single string value") } if isString { return validateStringClaim(claimAudience, val) } if l.ListValue != nil && len(l.ListValue.Values) == 0 { return fmt.Errorf("there MUST be at least one value present in the audience claim") } for _, aud := range l.ListValue.Values { v, ok := aud.Kind.(*spb.Value_StringValue) if !ok { return fmt.Errorf("audience value is not a string") } if !utf8.ValidString(v.StringValue) { return fmt.Errorf("audience value is not a valid UTF-8 string") } } return nil } func validateCustomClaims(cc map[string]any) error { if cc == nil { return nil } for key := range cc { if isRegisteredClaim(key) { return fmt.Errorf("claim '%q' is a registered claim, it can't be declared as a custom claim", key) } } return nil } func setTimeValue(p *spb.Struct, claim string, val *time.Time) { if val == nil { return } setValue(p, claim, spb.NewNumberValue(float64(val.Unix()))) } func setStringValue(p *spb.Struct, claim string, val *string) { if val == nil { return } setValue(p, claim, spb.NewStringValue(*val)) } func setAudiences(p *spb.Struct, claim string, vals []string) { if vals == nil { return } audList := &spb.ListValue{ Values: make([]*spb.Value, 0, len(vals)), } for _, aud := range vals { audList.Values = append(audList.Values, spb.NewStringValue(aud)) } setValue(p, claim, spb.NewListValue(audList)) } func setValue(p *spb.Struct, claim string, val *spb.Value) { if p.GetFields() == nil { p.Fields = make(map[string]*spb.Value) } p.GetFields()[claim] = val } func isRegisteredClaim(c string) bool { return isRegisteredStringClaim(c) || isRegisteredTimeClaim(c) || c == claimAudience } func isRegisteredStringClaim(c string) bool { return c == claimIssuer || c == claimSubject || c == claimJWTID } func isRegisteredTimeClaim(c string) bool { return c == claimExpiration || c == claimNotBefore || c == claimIssuedAt } ================================================ FILE: go/jwt/raw_jwt_test.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt_test import ( "testing" "time" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/tink/go/jwt" ) const ( invalidUTF8 = "\xF4\x7F\xBF\xBF" validExpiration = 1640043004 ) type testCase struct { tag string opts *jwt.RawJWTOptions json string token *jwt.RawJWT } func refString(a string) *string { return &a } func refTime(ts int64) *time.Time { t := time.Unix(ts, 0) return &t } func TestCreatingRawJWTWithAllClaims(t *testing.T) { json := `{ "sub": "tink-test-subject", "iss": "tink-test-issuer", "jti": "tink-jwt-id", "aud": ["aud-1", "aud-2"], "exp": 457888, "nbf": 450888, "iat": 400888, "cc-num": 1.67, "cc-bool": true, "cc-null": null, "cc-array": [1,2,3], "cc-string": "cc-val", "cc-object": {"nested-cc-num": 5.5} }` opts := &jwt.RawJWTOptions{ TypeHeader: refString("typeHeader"), Subject: refString("tink-test-subject"), Issuer: refString("tink-test-issuer"), JWTID: refString("tink-jwt-id"), Audiences: []string{"aud-1", "aud-2"}, ExpiresAt: refTime(457888), NotBefore: refTime(450888), IssuedAt: refTime(400888), CustomClaims: map[string]any{ "cc-num": 1.67, "cc-bool": true, "cc-null": nil, "cc-string": "cc-val", "cc-array": []any{1.0, 2.0, 3.0}, "cc-object": map[string]any{"nested-cc-num": 5.5}, }, } fromJSON, err := jwt.NewRawJWTFromJSON(refString("typeHeader"), []byte(json)) if err != nil { t.Fatalf("jwt.NewRawJWTFromJSON(%q): %v", json, err) } fromOpts, err := jwt.NewRawJWT(opts) if err != nil { t.Fatalf("jwt.NewRawJWT(%v): %v", opts, err) } for _, tc := range []testCase{ { tag: "jwt.NewRawJWTFromJSON", token: fromJSON, }, { tag: "NewRawJWT", token: fromOpts, }, } { if !tc.token.HasTypeHeader() { t.Errorf("tc.token.HasTypeHeader() = false, want true") } if !tc.token.HasAudiences() { t.Errorf("tc.token.HasAudiences() = false, want true") } if !tc.token.HasSubject() { t.Errorf("tc.token.HasSubject() = false, want true") } if !tc.token.HasIssuer() { t.Errorf("tc.token.HasIssuer() = false, want true") } if !tc.token.HasJWTID() { t.Errorf("tc.token.HasJWTID() = false, want true") } if !tc.token.HasExpiration() { t.Errorf("tc.token.HasExpiration() = false, want true") } if !tc.token.HasNotBefore() { t.Errorf("tc.token.HasNotBefore() = false, want true") } if !tc.token.HasIssuedAt() { t.Errorf("tc.token.HasIssuedAt() = false, want true") } typeHeader, err := tc.token.TypeHeader() if err != nil { t.Errorf("tc.token.TypeHeader() err = %v, want nil", err) } if !cmp.Equal(typeHeader, *opts.TypeHeader) { t.Errorf("tc.token.TypeHeader() = %q, want %q", typeHeader, *opts.TypeHeader) } audiences, err := tc.token.Audiences() if err != nil { t.Errorf("tc.token.Audiences() err = %v, want nil", err) } if !cmp.Equal(audiences, opts.Audiences) { t.Errorf("tc.token.Audiences() = %q, want %q", audiences, opts.Audiences) } subject, err := tc.token.Subject() if err != nil { t.Errorf("tc.token.Subject() err = %v, want nil", err) } if !cmp.Equal(subject, *opts.Subject) { t.Errorf("tc.token.Subject() = %q, want %q", subject, *opts.Subject) } issuer, err := tc.token.Issuer() if err != nil { t.Errorf("tc.token.Issuer() err = %v, want nil", err) } if !cmp.Equal(issuer, *opts.Issuer) { t.Errorf("tc.token.Issuer() = %q, want %q", issuer, *opts.Issuer) } jwtID, err := tc.token.JWTID() if err != nil { t.Errorf("tc.token.JWTID() err = %v, want nil", err) } if !cmp.Equal(jwtID, *opts.JWTID) { t.Errorf("tc.token.JWTID() = %q, want %q", jwtID, *opts.JWTID) } expiresAt, err := tc.token.ExpiresAt() if err != nil { t.Errorf("tc.token.ExpiresAt() err = %v, want nil", err) } if !cmp.Equal(expiresAt, *opts.ExpiresAt) { t.Errorf("tc.token.ExpiresAt() = %q, want %q", expiresAt, *opts.ExpiresAt) } issuedAt, err := tc.token.IssuedAt() if err != nil { t.Errorf("tc.token.IssuedAt() err = %v, want nil", err) } if !cmp.Equal(issuedAt, *opts.IssuedAt) { t.Errorf("tc.token.IssuedAt() = %q, want %q", issuedAt, *opts.IssuedAt) } notBefore, err := tc.token.NotBefore() if err != nil { t.Errorf("tc.token.NotBefore() err = %v, want nil", err) } if !cmp.Equal(notBefore, *opts.NotBefore) { t.Errorf("tc.token.NotBefore() = %q, want %q", notBefore, *opts.NotBefore) } wantCustomClaims := []string{"cc-num", "cc-bool", "cc-null", "cc-string", "cc-array", "cc-object"} if !cmp.Equal(tc.token.CustomClaimNames(), wantCustomClaims, cmpopts.SortSlices(func(a, b string) bool { return a < b })) { t.Errorf("tc.token.CustomClaimNames() = %q, want %q", tc.token.CustomClaimNames(), wantCustomClaims) } if !tc.token.HasNumberClaim("cc-num") { t.Errorf("tc.token.HasNumberClaim('cc-num') = false, want true") } if !tc.token.HasBooleanClaim("cc-bool") { t.Errorf("tc.token.HasBooleanClaim('cc-bool') = false, want true") } if !tc.token.HasNullClaim("cc-null") { t.Errorf("tc.token.HasNullClaim('cc-null') = false, want true") } if !tc.token.HasStringClaim("cc-string") { t.Errorf("tc.token.HasStringClaim('cc-string') = false, want true") } if !tc.token.HasArrayClaim("cc-array") { t.Errorf("tc.token.HasArrayClaim('cc-array') = false, want true") } if !tc.token.HasObjectClaim("cc-object") { t.Errorf("tc.token.HasObjectClaim('cc-object') = false, want true") } number, err := tc.token.NumberClaim("cc-num") if err != nil { t.Errorf("tc.token.NumberClaim('cc-num') err = %v, want nil", err) } if !cmp.Equal(number, opts.CustomClaims["cc-num"]) { t.Errorf("tc.token.NumberClaim('cc-num') = %f, want %f", number, opts.CustomClaims["cc-num"]) } boolean, err := tc.token.BooleanClaim("cc-bool") if err != nil { t.Errorf("tc.token.BooleanClaim('cc-bool') err = %v, want nil", err) } if !cmp.Equal(boolean, opts.CustomClaims["cc-bool"]) { t.Errorf("tc.token.BooleanClaim('cc-bool') = %v, want %v", boolean, opts.CustomClaims["cc-bool"]) } str, err := tc.token.StringClaim("cc-string") if err != nil { t.Errorf("tc.token.StringClaim('cc-string') err = %v, want nil", err) } if !cmp.Equal(str, opts.CustomClaims["cc-string"]) { t.Errorf("tc.token.StringClaim('cc-string') = %q, want %q", str, opts.CustomClaims["cc-string"]) } array, err := tc.token.ArrayClaim("cc-array") if err != nil { t.Errorf("tc.token.ArrayClaim('cc-array') err = %v, want nil", err) } if !cmp.Equal(array, opts.CustomClaims["cc-array"]) { t.Errorf("tc.token.ArrayClaim('cc-array') = %q, want %q", array, opts.CustomClaims["cc-array"]) } object, err := tc.token.ObjectClaim("cc-object") if err != nil { t.Errorf("tc.token.ObjectClaim('cc-object') err = %v, want nil", err) } if !cmp.Equal(object, opts.CustomClaims["cc-object"]) { t.Errorf("tc.token.ObjectClaim('cc-object') = %q, want %q", object, opts.CustomClaims["cc-object"]) } } } func TestGeneratingRawJWTWithoutClaims(t *testing.T) { jsonToken, err := jwt.NewRawJWTFromJSON(nil, []byte("{}")) if err != nil { t.Fatalf("jwt.NewRawJWTFromJSON({}): %v", err) } optsToken, err := jwt.NewRawJWT(&jwt.RawJWTOptions{WithoutExpiration: true}) if err != nil { t.Fatalf("NewRawJWT with no claims: %v", err) } for _, tc := range []testCase{ { tag: "jwt.NewRawJWTFromJSON", token: jsonToken, }, { tag: "NewRawJWT", token: optsToken, }, } { if tc.token.HasTypeHeader() { t.Errorf("tc.token.HasTypeHeader() = true, want false") } if tc.token.HasAudiences() { t.Errorf("tc.token.HasAudiences() = true, want false") } if tc.token.HasSubject() { t.Errorf("tc.token.HasSubject() = true, want false") } if tc.token.HasIssuer() { t.Errorf("tc.token.HasIssuer() = true, want false") } if tc.token.HasJWTID() { t.Errorf("tc.token.HasJWTID() = true, want false") } if tc.token.HasExpiration() { t.Errorf("tc.token.HasExpiration() = true, want false") } if tc.token.HasNotBefore() { t.Errorf("tc.token.HasNotBefore() = true, want false") } if tc.token.HasIssuedAt() { t.Errorf("tc.token.HasIssuedAt() = true, want false") } if _, err := tc.token.Audiences(); err == nil { t.Errorf("tc.token.Audiences() err = nil, want error") } if _, err := tc.token.Subject(); err == nil { t.Errorf("tc.token.Subject() err = nil, want error") } if _, err := tc.token.Issuer(); err == nil { t.Errorf("tc.token.Issuer() err = nil, want error") } if _, err := tc.token.JWTID(); err == nil { t.Errorf("tc.token.JWTID() err = nil, want error") } if _, err := tc.token.ExpiresAt(); err == nil { t.Errorf("tc.token.ExpiresAt() err = nil, want error") } if _, err := tc.token.IssuedAt(); err == nil { t.Errorf("tc.token.IssuedAt() err = nil, want error") } if _, err := tc.token.NotBefore(); err == nil { t.Errorf("tc.token.NotBefore() err = nil, want error") } if !cmp.Equal(tc.token.CustomClaimNames(), []string{}) { t.Errorf("tc.token.CustomClaimNames() = %q want %q", tc.token.CustomClaimNames(), []string{}) } } } func TestNewRawJWTLargeValidTimestamps(t *testing.T) { opts := &jwt.RawJWTOptions{ TypeHeader: refString("typeHeader"), ExpiresAt: refTime(253402300799), NotBefore: refTime(253402300700), IssuedAt: refTime(253402300000), } token, err := jwt.NewRawJWT(opts) if err != nil { t.Fatalf("generating RawJWT with valid timestamps (%q, %q, %q): %v", opts.ExpiresAt, opts.NotBefore, opts.IssuedAt, err) } expiresAt, err := token.ExpiresAt() if err != nil { t.Errorf("tc.token.ExpiresAt() err = %v, want nil", err) } if !cmp.Equal(expiresAt, *opts.ExpiresAt) { t.Errorf("tc.token.ExpiresAt() = %q want %q", expiresAt, *opts.ExpiresAt) } notBefore, err := token.NotBefore() if err != nil { t.Errorf("tc.token.NotBefore() err = %v, want nil", err) } if !cmp.Equal(notBefore, *opts.NotBefore) { t.Errorf("tc.token.NotBefore() = %q want %q", notBefore, *opts.NotBefore) } issuedAt, err := token.IssuedAt() if err != nil { t.Errorf("tc.token.IssuedAt() err = %v, want nil", err) } if !cmp.Equal(issuedAt, *opts.IssuedAt) { t.Errorf("tc.token.IssuedAt() = %q want %q", issuedAt, *opts.IssuedAt) } } func TestNewRawJWTSingleStringAudience(t *testing.T) { opts := &jwt.RawJWTOptions{ WithoutExpiration: true, Audience: refString("tink-aud"), } rawJWT, err := jwt.NewRawJWT(opts) if err != nil { t.Fatalf("generating RawJWT with a single audience: %v", err) } aud, err := rawJWT.Audiences() if err != nil { t.Errorf("getting audience from token: %v", err) } want := []string{*opts.Audience} if !cmp.Equal(aud, want) { t.Errorf("rawJWT.Audiences() = %q, want %q", aud, want) } } func TestSingleStringAudienceFromJSON(t *testing.T) { rawJWT, err := jwt.NewRawJWTFromJSON(nil, []byte(`{"aud": "tink-aud"}`)) if err != nil { t.Fatalf("parsing valid RawJWT: %v", err) } aud, err := rawJWT.Audiences() if err != nil { t.Errorf("getting audience from token: %v", err) } want := []string{"tink-aud"} if !cmp.Equal(aud, want) { t.Errorf("rawJWT.Audiences() = %q, want %q", aud, want) } } func TestNewRawJWTValidationFailures(t *testing.T) { testCases := []testCase{ { tag: "empty jwt.RawJWTOptions options fails", }, { tag: "no ExpiresAt specified and WithoutExpiration = false fails", opts: &jwt.RawJWTOptions{ Audiences: []string{"tink-foo"}, }, }, { tag: "ExpiresAt and WithoutExpiration = true fails", opts: &jwt.RawJWTOptions{ Audiences: []string{"tink-foo"}, ExpiresAt: refTime(validExpiration), WithoutExpiration: true, }, }, { tag: "specifying Audenience and Audiences fails", opts: &jwt.RawJWTOptions{ Audiences: []string{"tink-foo"}, Audience: refString("tink-bar"), WithoutExpiration: true, }, }, { tag: "empty audiences array fails", opts: &jwt.RawJWTOptions{ ExpiresAt: refTime(validExpiration), Audiences: []string{}, }, }, { tag: "audiences with invalid UTF-8 string fails", opts: &jwt.RawJWTOptions{ WithoutExpiration: true, Audiences: []string{"valid", invalidUTF8}, }, }, { tag: "custom claims containing registered subject claims fails", opts: &jwt.RawJWTOptions{ Audiences: []string{"tink-foo"}, ExpiresAt: refTime(validExpiration), CustomClaims: map[string]any{ "sub": "overwrite", }, }, }, { tag: "custom claims containing registered issuer claims fails", opts: &jwt.RawJWTOptions{ Audiences: []string{"tink-foo"}, ExpiresAt: refTime(validExpiration), CustomClaims: map[string]any{ "iss": "overwrite", }, }, }, { tag: "custom claims containing registered jwt id claims fails", opts: &jwt.RawJWTOptions{ Audiences: []string{"tink-foo"}, ExpiresAt: refTime(validExpiration), CustomClaims: map[string]any{ "jti": "overwrite", }, }, }, { tag: "custom claims containing registered expiration claims fails", opts: &jwt.RawJWTOptions{ Audiences: []string{"tink-foo"}, ExpiresAt: refTime(validExpiration), CustomClaims: map[string]any{ "exp": "overwrite", }, }, }, { tag: "custom claims containing registered audience claims fails", opts: &jwt.RawJWTOptions{ Audiences: []string{"tink-foo"}, WithoutExpiration: true, CustomClaims: map[string]any{ "aud": []any{"overwrite"}, }, }, }, { tag: "custom claims with non standard JSON types fails", opts: &jwt.RawJWTOptions{ Audiences: []string{"tink-foo"}, ExpiresAt: refTime(validExpiration), CustomClaims: map[string]any{ "complex": time.Time{}, }, }, }, { tag: "non UTF-8 string on isser claim fails", opts: &jwt.RawJWTOptions{ Audiences: []string{"tink-foo"}, ExpiresAt: refTime(validExpiration), Issuer: refString(invalidUTF8), }, }, { tag: "non UTF-8 string on subject claim fails", opts: &jwt.RawJWTOptions{ Audiences: []string{"tink-foo"}, WithoutExpiration: true, Subject: refString(invalidUTF8), }, }, { tag: "non UTF-8 string on JWT ID claim fails", opts: &jwt.RawJWTOptions{ Audiences: []string{"tink-foo"}, WithoutExpiration: true, JWTID: refString(invalidUTF8), }, }, { tag: "non UTF-8 string on custom claim fails", opts: &jwt.RawJWTOptions{ Audiences: []string{"tink-foo"}, Issuer: refString("ise-testing"), ExpiresAt: refTime(validExpiration), CustomClaims: map[string]any{ "esoteric": invalidUTF8, }, }, }, { tag: "issued at timestamp greater than valid JWT max time fails", opts: &jwt.RawJWTOptions{ Audiences: []string{"tink-foo"}, ExpiresAt: refTime(validExpiration), IssuedAt: refTime(253402300800), }, }, { tag: "expires at timestamp greater than valid JWT max time fails", opts: &jwt.RawJWTOptions{ Audiences: []string{"tink-foo"}, ExpiresAt: refTime(253402300800), }, }, { tag: "not before timestamp smaller than valid JWT min time fails", opts: &jwt.RawJWTOptions{ Audiences: []string{"tink-foo"}, ExpiresAt: refTime(validExpiration), NotBefore: refTime(-5), }, }, } for _, tc := range testCases { t.Run(tc.tag, func(t *testing.T) { _, err := jwt.NewRawJWT(tc.opts) if err == nil { t.Errorf("expected error instead got nil") } }) } } func TestJSONPayload(t *testing.T) { for _, tc := range []testCase{ { tag: "subject", opts: &jwt.RawJWTOptions{ WithoutExpiration: true, Subject: refString("tink-subject"), }, json: `{"sub":"tink-subject"}`, }, { tag: "audience list", opts: &jwt.RawJWTOptions{ WithoutExpiration: true, Audiences: []string{"one"}, }, json: `{"aud":["one"]}`, }, { tag: "audience string", opts: &jwt.RawJWTOptions{ WithoutExpiration: true, Audience: refString("one"), }, json: `{"aud":"one"}`, }, { tag: "issuer", opts: &jwt.RawJWTOptions{ WithoutExpiration: true, Issuer: refString("tink-test"), }, json: `{"iss":"tink-test"}`, }, { tag: "jwt id", opts: &jwt.RawJWTOptions{ WithoutExpiration: true, JWTID: refString("tink-id"), }, json: `{"jti":"tink-id"}`, }, { tag: "issued at", opts: &jwt.RawJWTOptions{ WithoutExpiration: true, IssuedAt: refTime(78324), }, json: `{"iat":78324}`, }, { tag: "not before", opts: &jwt.RawJWTOptions{ WithoutExpiration: true, NotBefore: refTime(78324), }, json: `{"nbf":78324}`, }, { tag: "expiration", opts: &jwt.RawJWTOptions{ ExpiresAt: refTime(78324), }, json: `{"exp":78324}`, }, { tag: "integer", opts: &jwt.RawJWTOptions{ WithoutExpiration: true, CustomClaims: map[string]any{ "num": 1, }, }, json: `{"num":1}`, }, { tag: "custom-claim", opts: &jwt.RawJWTOptions{ WithoutExpiration: true, CustomClaims: map[string]any{ "cust": []any{map[string]any{"key": "val"}}, }, }, json: `{"cust":[{"key":"val"}]}`, }, { tag: "no claims", opts: &jwt.RawJWTOptions{ WithoutExpiration: true, }, json: `{}`, }, } { t.Run(tc.tag, func(t *testing.T) { token, err := jwt.NewRawJWT(tc.opts) if err != nil { t.Errorf("generating valid RawJWT: %v", err) } j, err := token.JSONPayload() if err != nil { t.Errorf("calling JSONPayload() on rawJWT: %v", err) } if !cmp.Equal(string(j), tc.json) { t.Fatalf("JSONPayload output got %v, expected %v", string(j), tc.json) } }) } } func TestFromJSONValidationFailures(t *testing.T) { testCases := []testCase{ { tag: "json with empty audience", json: `{"sub": "tink", "aud": []}`, }, { tag: "json with audience of wrong type", json: `{"aud": 5}`, }, { tag: "json with audiences of wrong type", json: `{"aud": ["one", null]}`, }, { tag: "json with registered claim with wrong type", json: `{"sub": 1}`, }, { tag: "json with non UTF-8 string on subject claim fails", json: `{"sub": "\xF4\x7F\xBF\xBF"}`, }, { tag: "json with non UTF-8 string on issuer claim fails", json: `{"iss": "\xF4\x7F\xBF\xBF"}`, }, { tag: "json with non UTF-8 string on jwt id claim fails", json: `{"jti": "\xF4\x7F\xBF\xBF"}`, }, { tag: "json with `not before` timestamp claim greater than valid JWT max time fails", json: `{"nbf": 253402301799}`, }, { tag: "json with `issued at` timestamp claim greater than valid JWT max time fails", json: `{"iat": 253402301799}`, }, { tag: "json with `expiration` timestamp claim greater than valid JWT max time fails", json: `{"exp": 253402301799}`, }, { tag: "json with `not before` timestamp claim smaller than valid JWT min time fails", json: `{"nbf": -4}`, }, { tag: "json with `issued at` timestamp claim smaller than valid JWT min time fails", json: `{"iat": -4}`, }, { tag: "json with `expiration` timestamp claim smaller than valid JWT min time fails", json: `{"exp": -4}`, }, { tag: "json with `not before` claim of non numeric type fails", json: `{"nbf": "invalid"}`, }, { tag: "json with `issued at` claim of non numeric type fails", json: `{"iat": "invalid"}`, }, { tag: "json with `expiration` claim of non numeric type fails", json: `{"exp": "invalid"}`, }, } for _, tc := range testCases { t.Run(tc.tag, func(t *testing.T) { if _, err := jwt.NewRawJWTFromJSON(nil, []byte(tc.json)); err == nil { t.Errorf("expected error instead got nil") } }) } } func TestHasCustomClaimsOfKind(t *testing.T) { opts := &jwt.RawJWTOptions{ TypeHeader: refString("typeHeader"), WithoutExpiration: true, CustomClaims: map[string]any{ "cc-num": 1.67, "cc-bool": false, "cc-nil": nil, "cc-list": []any{1.0, 2.0, 3.0}, "cc-string": "cc-val", "cc-object": map[string]any{ "nested-cc-num": 5.5, }, }, } token, err := jwt.NewRawJWT(opts) if err != nil { t.Fatalf("generating valid RawJWT: %v", err) } if token.HasBooleanClaim("cc-num") { t.Errorf("custom number claim 'cc-num' should return false when queried for another type") } if token.HasNullClaim("cc-bool") { t.Errorf("custom boolean claim 'cc-bool' should return false when queried for another type") } if token.HasNumberClaim("cc-bool") { t.Errorf("custom boolean claim 'cc-bool' should return false when queried for another type") } if token.HasStringClaim("cc-bool") { t.Errorf("custom boolean claim 'cc-bool' should return false when queried for another type") } if token.HasArrayClaim("cc-bool") { t.Errorf("custom boolean claim 'cc-bool' should return false when queried for another type") } if token.HasObjectClaim("cc-bool") { t.Errorf("custom boolean claim 'cc-bool' should return false when queried for another type") } } func TestGettingRegisteredClaimsThroughCustomFails(t *testing.T) { opts := &jwt.RawJWTOptions{ TypeHeader: refString("typeHeader"), Subject: refString("tink-test-subject"), Issuer: refString("tink-test-issuer"), JWTID: refString("tink-jwt-id-1"), Audiences: []string{"aud-1", "aud-2"}, ExpiresAt: refTime(validExpiration), IssuedAt: refTime(validExpiration - 100), NotBefore: refTime(validExpiration - 50), } token, err := jwt.NewRawJWT(opts) if err != nil { t.Fatalf("generating valid RawJWT: %v", err) } if !cmp.Equal(token.CustomClaimNames(), []string{}) { t.Errorf("tc.token.CustomClaimNames() = %q want %q", token.CustomClaimNames(), []string{}) } for _, c := range []string{"sub", "iss", "aud", "nbf", "exp", "iat", "jti"} { if token.HasNullClaim(c) { t.Errorf("registered '%q' claim should return false when calling HasNullClaim", c) } if token.HasBooleanClaim(c) { t.Errorf("registered '%q' claim should return false when calling HasBooleanClaim", c) } if _, err := token.BooleanClaim(c); err == nil { t.Errorf("expected error when calling token.BoolClaim(%q) instead got nil", c) } if token.HasNumberClaim(c) { t.Errorf("registered '%q' claim should return false when calling HasNumberClaim", c) } if _, err := token.NumberClaim(c); err == nil { t.Errorf("expected error when calling token.NumberClaim(%q) instead got nil", c) } if token.HasStringClaim(c) { t.Errorf("registered '%q' claim should return false when calling HasStringClaim", c) } if _, err := token.StringClaim(c); err == nil { t.Errorf("expected error when calling token.StringClaim(%q) instead got nil", c) } if token.HasArrayClaim(c) { t.Errorf("registered '%q' claim should return false when calling HasArrayClaim", c) } if _, err := token.ArrayClaim(c); err == nil { t.Errorf("expected error when calling token.ListClaim(%q) instead got nil", c) } if token.HasObjectClaim(c) { t.Errorf("registered '%q' claim should return false when calling HasObjectClaim", c) } if _, err := token.ObjectClaim(c); err == nil { t.Errorf("expected error when calling token.JSONClaim(%q) instead got nil", c) } } } ================================================ FILE: go/jwt/verified_jwt.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt import ( "fmt" "time" ) // VerifiedJWT is a verified JWT token. type VerifiedJWT struct { token *RawJWT } // newVerifiedJWT generates a new VerifiedJWT func newVerifiedJWT(rawJWT *RawJWT) (*VerifiedJWT, error) { if rawJWT == nil { return nil, fmt.Errorf("rawJWT can't be nil") } return &VerifiedJWT{ token: rawJWT, }, nil } // JSONPayload marshals a VerifiedJWT payload to JSON. func (v *VerifiedJWT) JSONPayload() ([]byte, error) { return v.token.JSONPayload() } // HasTypeHeader return whether a RawJWT contains a type header. func (v *VerifiedJWT) HasTypeHeader() bool { return v.token.HasTypeHeader() } // TypeHeader returns the JWT type header. func (v *VerifiedJWT) TypeHeader() (string, error) { return v.token.TypeHeader() } // HasAudiences checks whether a JWT contains the audience claim ('aud'). func (v *VerifiedJWT) HasAudiences() bool { return v.token.HasAudiences() } // Audiences returns a list of audiences from the 'aud' claim. // If the 'aud' claim is a single string, it is converted into a list with a single entry. func (v *VerifiedJWT) Audiences() ([]string, error) { return v.token.Audiences() } // HasSubject checks whether a JWT contains an issuer claim ('sub'). func (v *VerifiedJWT) HasSubject() bool { return v.token.HasSubject() } // Subject returns the subject claim ('sub') or an error if no claim is present. func (v *VerifiedJWT) Subject() (string, error) { return v.token.Subject() } // HasIssuer checks whether a JWT contains an issuer claim ('iss'). func (v *VerifiedJWT) HasIssuer() bool { return v.token.HasIssuer() } // Issuer returns the issuer claim ('iss') or an error if no claim is present. func (v *VerifiedJWT) Issuer() (string, error) { return v.token.Issuer() } // HasJWTID checks whether a JWT contains an JWT ID claim ('jti'). func (v *VerifiedJWT) HasJWTID() bool { return v.token.HasJWTID() } // JWTID returns the JWT ID claim ('jti') or an error if no claim is present. func (v *VerifiedJWT) JWTID() (string, error) { return v.token.JWTID() } // HasIssuedAt checks whether a JWT contains an issued at claim ('iat'). func (v *VerifiedJWT) HasIssuedAt() bool { return v.token.HasIssuedAt() } // IssuedAt returns the issued at claim ('iat') or an error if no claim is present. func (v *VerifiedJWT) IssuedAt() (time.Time, error) { return v.token.IssuedAt() } // HasExpiration checks whether a JWT contains an expiration time claim ('exp'). func (v *VerifiedJWT) HasExpiration() bool { return v.token.HasExpiration() } // ExpiresAt returns the expiration claim ('exp') or an error if no claim is present. func (v *VerifiedJWT) ExpiresAt() (time.Time, error) { return v.token.ExpiresAt() } // HasNotBefore checks whether a JWT contains a not before claim ('nbf'). func (v *VerifiedJWT) HasNotBefore() bool { return v.token.HasNotBefore() } // NotBefore returns the not before claim ('nbf') or an error if no claim is present. func (v *VerifiedJWT) NotBefore() (time.Time, error) { return v.token.NotBefore() } // HasStringClaim checks whether a claim of type string is present. func (v *VerifiedJWT) HasStringClaim(name string) bool { return v.token.HasStringClaim(name) } // StringClaim returns a custom string claim or an error if no claim is present. func (v *VerifiedJWT) StringClaim(name string) (string, error) { return v.token.StringClaim(name) } // HasNumberClaim checks whether a claim of type number is present. func (v *VerifiedJWT) HasNumberClaim(name string) bool { return v.token.HasNumberClaim(name) } // NumberClaim returns a custom number claim or an error if no claim is present. func (v *VerifiedJWT) NumberClaim(name string) (float64, error) { return v.token.NumberClaim(name) } // HasBooleanClaim checks whether a claim of type boolean is present. func (v *VerifiedJWT) HasBooleanClaim(name string) bool { return v.token.HasBooleanClaim(name) } // BooleanClaim returns a custom bool claim or an error if no claim is present. func (v *VerifiedJWT) BooleanClaim(name string) (bool, error) { return v.token.BooleanClaim(name) } // HasNullClaim checks whether a claim of type null is present. func (v *VerifiedJWT) HasNullClaim(name string) bool { return v.token.HasNullClaim(name) } // HasArrayClaim checks whether a claim of type list is present. func (v *VerifiedJWT) HasArrayClaim(name string) bool { return v.token.HasArrayClaim(name) } // ArrayClaim returns a slice representing a JSON array for a claim or an error if the claim is empty. func (v *VerifiedJWT) ArrayClaim(name string) ([]any, error) { return v.token.ArrayClaim(name) } // HasObjectClaim checks whether a claim of type JSON object is present. func (v *VerifiedJWT) HasObjectClaim(name string) bool { return v.token.HasObjectClaim(name) } // ObjectClaim returns a map representing a JSON object for a claim or an error if the claim is empty. func (v *VerifiedJWT) ObjectClaim(name string) (map[string]any, error) { return v.token.ObjectClaim(name) } // CustomClaimNames returns a list with the name of custom claims in a VerifiedJWT. func (v *VerifiedJWT) CustomClaimNames() []string { return v.token.CustomClaimNames() } ================================================ FILE: go/jwt/verified_jwt_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jwt_test import ( "testing" "time" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/tink/go/jwt" "github.com/google/tink/go/keyset" ) func createVerifiedJWT(rawJWT *jwt.RawJWT) (*jwt.VerifiedJWT, error) { kh, err := keyset.NewHandle(jwt.HS256Template()) if err != nil { return nil, err } m, err := jwt.NewMAC(kh) if err != nil { return nil, err } compact, err := m.ComputeMACAndEncode(rawJWT) if err != nil { return nil, err } // This validator is purposely instantiated to always pass. // It isn't really validating much and probably shouldn't // be used like this out side of these tests. opts := &jwt.ValidatorOpts{ AllowMissingExpiration: true, IgnoreTypeHeader: true, IgnoreAudiences: true, IgnoreIssuer: true, } issuedAt, err := rawJWT.IssuedAt() if err == nil { opts.FixedNow = issuedAt } validator, err := jwt.NewValidator(opts) if err != nil { return nil, err } return m.VerifyMACAndDecode(compact, validator) } func TestGetRegisteredStringClaims(t *testing.T) { opts := &jwt.RawJWTOptions{ TypeHeader: refString("typeHeader"), Subject: refString("test-subject"), Issuer: refString("test-issuer"), JWTID: refString("1"), WithoutExpiration: true, } rawJWT, err := jwt.NewRawJWT(opts) if err != nil { t.Fatalf("jwt.NewRawJWT(%v): %v", opts, err) } verifiedJWT, err := createVerifiedJWT(rawJWT) if err != nil { t.Fatalf("creating verifiedJWT: %v", err) } if !verifiedJWT.HasTypeHeader() { t.Errorf("verifiedJWT.HasTypeHeader() = false, want true") } if !verifiedJWT.HasSubject() { t.Errorf("verifiedJWT.HasSubject() = false, want true") } if !verifiedJWT.HasIssuer() { t.Errorf("verifiedJWT.HasIssuer() = false, want true") } if !verifiedJWT.HasJWTID() { t.Errorf("verifiedJWT.HasJWTID() = false, want true") } typeHeader, err := verifiedJWT.TypeHeader() if err != nil { t.Errorf("verifiedJWT.TypeHeader() err = %v, want nil", err) } if !cmp.Equal(typeHeader, *opts.TypeHeader) { t.Errorf("verifiedJWT.TypeHeader() = %q, want %q", typeHeader, *opts.TypeHeader) } subject, err := verifiedJWT.Subject() if err != nil { t.Errorf("verifiedJWT.Subject() err = %v, want nil", err) } if !cmp.Equal(subject, *opts.Subject) { t.Errorf("verifiedJWT.Subject() = %q, want %q", subject, *opts.Subject) } issuer, err := verifiedJWT.Issuer() if err != nil { t.Errorf("verifiedJWT.Issuer() err = %v, want nil", err) } if !cmp.Equal(issuer, *opts.Issuer) { t.Errorf("verifiedJWT.Issuer() = %q, want %q", issuer, *opts.Issuer) } jwtID, err := verifiedJWT.JWTID() if err != nil { t.Errorf("verifiedJWT.JWTID() err = %v, want nil", err) } if !cmp.Equal(jwtID, *opts.JWTID) { t.Errorf("verifiedJWT.JWTID() = %q, want %q", jwtID, *opts.JWTID) } if !cmp.Equal(verifiedJWT.CustomClaimNames(), []string{}) { t.Errorf("verifiedJWT.CustomClaimNames() = %q want %q", verifiedJWT.CustomClaimNames(), []string{}) } } func TestGetRegisteredTimestampClaims(t *testing.T) { now := time.Now() opts := &jwt.RawJWTOptions{ ExpiresAt: refTime(now.Add(time.Hour * 24).Unix()), IssuedAt: refTime(now.Unix()), NotBefore: refTime(now.Add(-time.Hour * 2).Unix()), } rawJWT, err := jwt.NewRawJWT(opts) if err != nil { t.Fatalf("jwt.NewRawJWT(%v): %v", opts, err) } verifiedJWT, err := createVerifiedJWT(rawJWT) if err != nil { t.Fatalf("creating verifiedJWT: %v", err) } if !verifiedJWT.HasExpiration() { t.Errorf("verifiedJWT.HasExpiration() = false, want true") } if !verifiedJWT.HasIssuedAt() { t.Errorf("verifiedJWT.HasIssuedAt() = false, want true") } if !verifiedJWT.HasNotBefore() { t.Errorf("verifiedJWT.HasNotBefore() = false, want true") } expiresAt, err := verifiedJWT.ExpiresAt() if err != nil { t.Errorf("verifiedJWT.ExpiresAt() err = %v, want nil", err) } if !cmp.Equal(expiresAt, *opts.ExpiresAt) { t.Errorf("verifiedJWT.ExpiresAt() = %q, want %q", expiresAt, *opts.ExpiresAt) } issuedAt, err := verifiedJWT.IssuedAt() if err != nil { t.Errorf("verifiedJWT.IssuedAt() err = %v, want nil", err) } if !cmp.Equal(issuedAt, *opts.IssuedAt) { t.Errorf("verifiedJWT.IssuedAt() = %q, want %q", issuedAt, *opts.IssuedAt) } notBefore, err := verifiedJWT.NotBefore() if err != nil { t.Errorf("verifiedJWT.NotBefore() err = %v, want nil", err) } if !cmp.Equal(notBefore, *opts.NotBefore) { t.Errorf("verifiedJWT.NotBefore() = %q, want %q", notBefore, *opts.NotBefore) } } func TestGetAudiencesClaim(t *testing.T) { opts := &jwt.RawJWTOptions{ WithoutExpiration: true, Audiences: []string{"foo", "bar"}, } rawJWT, err := jwt.NewRawJWT(opts) if err != nil { t.Fatalf("jwt.NewRawJWT(%v): %v", opts, err) } verifiedJWT, err := createVerifiedJWT(rawJWT) if err != nil { t.Fatalf("creating verifiedJWT: %v", err) } if !verifiedJWT.HasAudiences() { t.Errorf("verifiedJWT.HasAudiences() = false, want true") } audiences, err := verifiedJWT.Audiences() if err != nil { t.Errorf("verifiedJWT.Audiences() err = %v, want nil", err) } if !cmp.Equal(audiences, opts.Audiences) { t.Errorf("verifiedJWT.Audiences() = %q, want %q", audiences, opts.Audiences) } } func TestGetCustomClaims(t *testing.T) { opts := &jwt.RawJWTOptions{ WithoutExpiration: true, CustomClaims: map[string]any{ "cc-null": nil, "cc-num": 1.67, "cc-bool": true, "cc-string": "goo", "cc-array": []any{"1", "2", "3"}, "cc-object": map[string]any{"cc-nested-num": 5.99}, }, } rawJWT, err := jwt.NewRawJWT(opts) if err != nil { t.Fatalf("jwt.NewRawJWT(%v): %v", opts, err) } verifiedJWT, err := createVerifiedJWT(rawJWT) if err != nil { t.Fatalf("creating verifiedJWT: %v", err) } wantCustomClaims := []string{"cc-num", "cc-bool", "cc-null", "cc-string", "cc-array", "cc-object"} if !cmp.Equal(verifiedJWT.CustomClaimNames(), wantCustomClaims, cmpopts.SortSlices(func(a, b string) bool { return a < b })) { t.Errorf("verifiedJWT.CustomClaimNames() = %q, want %q", verifiedJWT.CustomClaimNames(), wantCustomClaims) } if !verifiedJWT.HasNullClaim("cc-null") { t.Errorf("verifiedJWT.HasNullClaim('cc-null') = false, want true") } if !verifiedJWT.HasNumberClaim("cc-num") { t.Errorf("verifiedJWT.HasNumberClaim('cc-num') = false, want true") } if !verifiedJWT.HasBooleanClaim("cc-bool") { t.Errorf("verifiedJWT.HasBooleanClaim('cc-bool') = false, want true") } if !verifiedJWT.HasStringClaim("cc-string") { t.Errorf("verifiedJWT.HasStringClaim('cc-string') = false, want true") } if !verifiedJWT.HasArrayClaim("cc-array") { t.Errorf("verifiedJWT.HasArrayClaim('cc-array') = false, want true") } if !verifiedJWT.HasObjectClaim("cc-object") { t.Errorf("verifiedJWT.HasObjectClaim('cc-object') = false, want true") } number, err := verifiedJWT.NumberClaim("cc-num") if err != nil { t.Errorf("verifiedJWT.NumberClaim('cc-num') err = %v, want nil", err) } if !cmp.Equal(number, opts.CustomClaims["cc-num"]) { t.Errorf("verifiedJWT.NumberClaim('cc-num') = %f, want %f", number, opts.CustomClaims["cc-num"]) } boolean, err := verifiedJWT.BooleanClaim("cc-bool") if err != nil { t.Errorf("verifiedJWT.BooleanClaim('cc-bool') err = %v, want nil", err) } if !cmp.Equal(boolean, opts.CustomClaims["cc-bool"]) { t.Errorf("verifiedJWT.BooleanClaim('cc-bool') = %v, want %v", boolean, opts.CustomClaims["cc-bool"]) } str, err := verifiedJWT.StringClaim("cc-string") if err != nil { t.Errorf("verifiedJWT.StringClaim('cc-string') err = %v, want nil", err) } if !cmp.Equal(str, opts.CustomClaims["cc-string"]) { t.Errorf("verifiedJWT.StringClaim('cc-string') = %q, want %q", str, opts.CustomClaims["cc-string"]) } array, err := verifiedJWT.ArrayClaim("cc-array") if err != nil { t.Errorf("verifiedJWT.ArrayClaim('cc-array') err = %v, want nil", err) } if !cmp.Equal(array, opts.CustomClaims["cc-array"]) { t.Errorf("verifiedJWT.ArrayClaim('cc-array') = %q, want %q", array, opts.CustomClaims["cc-array"]) } object, err := verifiedJWT.ObjectClaim("cc-object") if err != nil { t.Errorf("verifiedJWT.ObjectClaim('cc-object') err = %v, want nil", err) } if !cmp.Equal(object, opts.CustomClaims["cc-object"]) { t.Errorf("verifiedJWT.ObjectClaim('cc-object') = %q, want %q", object, opts.CustomClaims["cc-object"]) } } func TestCustomClaimIsFalseForWrongType(t *testing.T) { opts := &jwt.RawJWTOptions{ WithoutExpiration: true, CustomClaims: map[string]any{ "cc-null": nil, "cc-num": 1.67, "cc-bool": true, "cc-string": "goo", "cc-array": []any{"1", "2", "3"}, "cc-object": map[string]any{"cc-nested-num": 5.99}, }, } rawJWT, err := jwt.NewRawJWT(opts) if err != nil { t.Fatalf("jwt.NewRawJWT(%v): %v", opts, err) } verifiedJWT, err := createVerifiedJWT(rawJWT) if err != nil { t.Fatalf("creating verifiedJWT: %v", err) } if verifiedJWT.HasNullClaim("cc-object") { t.Errorf("verifiedJWT.HasNullClaim('cc-object') = true, want false") } if verifiedJWT.HasNumberClaim("cc-bool") { t.Errorf("verifiedJWT.HasNumberClaim('cc-bool') = true, want false") } if verifiedJWT.HasStringClaim("cc-array") { t.Errorf("verifiedJWT.HasStringClaim('cc-array') = true, want false") } if verifiedJWT.HasBooleanClaim("cc-string") { t.Errorf("verifiedJWT.HasBooleanClaim('cc-string') = true, want false") } if verifiedJWT.HasArrayClaim("cc-null") { t.Errorf("verifiedJWT.HasArrayClaim('cc-null') = true, want false") } if verifiedJWT.HasObjectClaim("cc-num") { t.Errorf("verifiedJWT.HasObjectClaim('cc-num') = true, want false") } } func TestNoClaimsCallHasAndGet(t *testing.T) { opts := &jwt.RawJWTOptions{ WithoutExpiration: true, } rawJWT, err := jwt.NewRawJWT(opts) if err != nil { t.Fatalf("jwt.NewRawJWT(%v): %v", opts, err) } verifiedJWT, err := createVerifiedJWT(rawJWT) if err != nil { t.Fatalf("creating verifiedJWT: %v", err) } if verifiedJWT.HasAudiences() { t.Errorf("verifiedJWT.HasAudiences() = true, want false") } if verifiedJWT.HasSubject() { t.Errorf("verifiedJWT.HasSubject() = true, want false") } if verifiedJWT.HasIssuer() { t.Errorf("verifiedJWT.HasIssuer() = true, want false") } if verifiedJWT.HasJWTID() { t.Errorf("verifiedJWT.HasJWTID() = true, want false") } if verifiedJWT.HasNotBefore() { t.Errorf("verifiedJWT.HasNotBefore() = true, want false") } if verifiedJWT.HasExpiration() { t.Errorf("verifiedJWT.HasExpiration() = true, want false") } if verifiedJWT.HasIssuedAt() { t.Errorf("verifiedJWT.HasIssuedAt() = true, want false") } if !cmp.Equal(verifiedJWT.CustomClaimNames(), []string{}) { t.Errorf("verifiedJWT.CustomClaimNames() = %q want %q", verifiedJWT.CustomClaimNames(), []string{}) } } func TestCantGetRegisteredClaimsThroughCustomClaims(t *testing.T) { now := time.Now() opts := &jwt.RawJWTOptions{ TypeHeader: refString("typeHeader"), Subject: refString("test-subject"), Issuer: refString("test-issuer"), JWTID: refString("1"), Audiences: []string{"foo", "bar"}, ExpiresAt: refTime(now.Add(time.Hour * 24).Unix()), IssuedAt: refTime(now.Unix()), NotBefore: refTime(now.Add(-time.Hour * 2).Unix()), } rawJWT, err := jwt.NewRawJWT(opts) if err != nil { t.Fatalf("jwt.NewRawJWT(%v): %v", opts, err) } verifiedJWT, err := createVerifiedJWT(rawJWT) if err != nil { t.Fatalf("creating verifiedJWT: %v", err) } for _, c := range []string{"iss", "sub", "aud", "jti", "exp", "nbf", "iat"} { if verifiedJWT.HasStringClaim(c) { t.Errorf("verifiedJWT.HasStringClaim(%q) = true, want false", c) } if verifiedJWT.HasNumberClaim(c) { t.Errorf("verifiedJWT.HasNumberClaim(%q) = true, want false", c) } if verifiedJWT.HasArrayClaim(c) { t.Errorf("verifiedJWT.HasArrayClaim(%q) = true, want false", c) } if _, err := verifiedJWT.StringClaim(c); err == nil { t.Errorf("verifiedJWT.StringClaim(%q) err = nil, want error", c) } if _, err := verifiedJWT.NumberClaim(c); err == nil { t.Errorf("verifiedJWT.NumberClaim(%q) err = nil, want error", c) } if _, err := verifiedJWT.ArrayClaim(c); err == nil { t.Errorf("verifiedJWT.ArrayClaim(%q) err = nil, want error", c) } } } func TestGetJSONPayload(t *testing.T) { opts := &jwt.RawJWTOptions{ Subject: refString("test-subject"), WithoutExpiration: true, } rawJWT, err := jwt.NewRawJWT(opts) if err != nil { t.Fatalf("jwt.NewRawJWT(%v): %v", opts, err) } verifiedJWT, err := createVerifiedJWT(rawJWT) if err != nil { t.Fatalf("creating verifiedJWT: %v", err) } j, err := verifiedJWT.JSONPayload() if err != nil { t.Errorf("verifiedJWT.JSONPayload() err = %v, want nil", err) } expected := `{"sub":"test-subject"}` if !cmp.Equal(string(j), expected) { t.Errorf("verifiedJWT.JSONPayload() = %q, want %q", string(j), expected) } } ================================================ FILE: go/keyderivation/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep licenses(["notice"]) # keep go_library( name = "keyderivation", srcs = [ "keyderivation.go", "keyderivation_key_templates.go", "keyset_deriver.go", "keyset_deriver_factory.go", "prf_based_deriver.go", "prf_based_deriver_key_manager.go", ], importpath = "github.com/google/tink/go/keyderivation", visibility = ["//visibility:public"], deps = [ "//core/primitiveset", "//core/registry", "//insecurecleartextkeyset", "//internal", "//internal/internalregistry", "//keyderivation/internal/streamingprf", "//keyset", "//proto/prf_based_deriver_go_proto", "//proto/tink_go_proto", "@org_golang_google_protobuf//proto", ], ) go_test( name = "keyderivation_test", srcs = [ "keyderivation_key_templates_test.go", "keyderivation_test.go", "keyset_deriver_factory_test.go", "keyset_deriver_factory_x_test.go", "prf_based_deriver_key_manager_test.go", "prf_based_deriver_test.go", ], embed = [":keyderivation"], deps = [ "//aead", "//core/cryptofmt", "//core/primitiveset", "//core/registry", "//daead", "//insecurecleartextkeyset", "//keyset", "//mac", "//prf", "//proto/aes_gcm_go_proto", "//proto/common_go_proto", "//proto/hkdf_prf_go_proto", "//proto/prf_based_deriver_go_proto", "//proto/tink_go_proto", "//signature", "//streamingaead", "//subtle/random", "@com_github_google_go_cmp//cmp", "@org_golang_google_protobuf//proto", "@org_golang_google_protobuf//testing/protocmp", ], ) alias( name = "go_default_library", actual = ":keyderivation", visibility = ["//visibility:public"], ) ================================================ FILE: go/keyderivation/internal/streamingprf/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep licenses(["notice"]) # keep go_library( name = "streamingprf", srcs = [ "hkdf_streaming_prf.go", "hkdf_streaming_prf_key_manager.go", "streaming_prf.go", "streaming_prf_factory.go", ], importpath = "github.com/google/tink/go/keyderivation/internal/streamingprf", deps = [ "//core/primitiveset", "//core/registry", "//keyset", "//proto/common_go_proto", "//proto/hkdf_prf_go_proto", "//proto/tink_go_proto", "//subtle", "@org_golang_google_protobuf//proto", "@org_golang_x_crypto//hkdf", ], ) go_test( name = "streamingprf_test", srcs = [ "hkdf_streaming_prf_key_manager_test.go", "hkdf_streaming_prf_test.go", "streaming_prf_factory_test.go", "streaming_prf_test.go", ], data = ["//testdata/testvectors:kdf"], embed = [":streamingprf"], deps = [ "//aead", "//core/registry", "//keyset", "//prf", "//proto/aes_gcm_go_proto", "//proto/common_go_proto", "//proto/hkdf_prf_go_proto", "//proto/tink_go_proto", "//subtle/random", "//testkeyset", "//testutil", "@org_golang_google_protobuf//proto", ], ) alias( name = "go_default_library", actual = ":streamingprf", visibility = ["//:__subpackages__"], ) ================================================ FILE: go/keyderivation/internal/streamingprf/hkdf_streaming_prf.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package streamingprf import ( "fmt" "hash" "io" "golang.org/x/crypto/hkdf" "github.com/google/tink/go/subtle" ) // minHKDFStreamingPRFKeySize is the minimum allowed key size in bytes. const minHKDFStreamingPRFKeySize = 32 // hkdfStreamingPRF is a HKDF Streaming PRF that implements StreamingPRF. type hkdfStreamingPRF struct { h func() hash.Hash key []byte salt []byte } // Asserts that hkdfStreamingPRF implements the StreamingPRF interface. var _ StreamingPRF = (*hkdfStreamingPRF)(nil) // newHKDFStreamingPRF constructs a new hkdfStreamingPRF using hashName, key, // and salt. Salt can be nil. func newHKDFStreamingPRF(hashName string, key, salt []byte) (*hkdfStreamingPRF, error) { if err := validateHKDFStreamingPRFParams(hashName, len(key)); err != nil { return nil, err } return &hkdfStreamingPRF{ h: subtle.GetHashFunc(hashName), key: key, salt: salt, }, nil } // Compute computes and returns the HKDF as a Reader. func (h *hkdfStreamingPRF) Compute(data []byte) (io.Reader, error) { return hkdf.New(h.h, h.key, h.salt, data), nil } func validateHKDFStreamingPRFParams(hash string, keySize int) error { if hash != "SHA256" && hash != "SHA512" { return fmt.Errorf("only SHA-256, SHA-512 allowed for HKDF") } if keySize < minHKDFStreamingPRFKeySize { return fmt.Errorf("key too short, require %d-bytes: %d", minHKDFStreamingPRFKeySize, keySize) } return nil } ================================================ FILE: go/keyderivation/internal/streamingprf/hkdf_streaming_prf_key_manager.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package streamingprf import ( "errors" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/keyset" commonpb "github.com/google/tink/go/proto/common_go_proto" hkdfpb "github.com/google/tink/go/proto/hkdf_prf_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // TODO(b/260619626): HKDF PRF and HKDF Streaming PRF currently share the same // type URL. This is fine as HKDFStreamingPRFKeyManager is not in the global // registry. HKDF PRF and HKDF Streaming PRF will eventually share the same key // manager, rendering this one obsolete. const ( hkdfStreamingPRFKeyVersion = 0 hkdfPRFTypeURL = "type.googleapis.com/google.crypto.tink.HkdfPrfKey" ) var ( errInvalidHKDFStreamingPRFKey = errors.New("hkdf_streaming_prf_key_manager: invalid key") errInvalidHKDFStreamingPRFKeyFormat = errors.New("hkdf_streaming_prf_key_manager: invalid key format") errHKDFStreamingPRFNotImplemented = errors.New("hkdf_streaming_prf_key_manager: not implemented") ) // HKDFStreamingPRFKeyManager is a KeyManager for HKDF Streaming PRF keys. It is // exported for use in keyderivation.prfBasedDeriver. This is not part of the // public API as this is in internal/. type HKDFStreamingPRFKeyManager struct{} var _ registry.KeyManager = (*HKDFStreamingPRFKeyManager)(nil) // Primitive constructs a primitive instance for the key given in serializedKey. func (km *HKDFStreamingPRFKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidHKDFStreamingPRFKey } key := &hkdfpb.HkdfPrfKey{} if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errInvalidHKDFStreamingPRFKey } if keyset.ValidateKeyVersion(key.GetVersion(), hkdfStreamingPRFKeyVersion) != nil { return nil, errInvalidHKDFStreamingPRFKey } hashName := commonpb.HashType_name[int32(key.GetParams().GetHash())] return newHKDFStreamingPRF(hashName, key.GetKeyValue(), key.GetParams().GetSalt()) } // NewKey generates a new key according to specification in serializedKeyFormat. // It is not implemented for this KeyManager to prevent the generation of keys // of this key type. func (km *HKDFStreamingPRFKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { return nil, errHKDFStreamingPRFNotImplemented } // NewKeyData generates a new KeyData according to specification in // serializedkeyFormat. This should be used solely by the key management API. // It is not implemented for this KeyManager to prevent the generation of keys // of this key type. func (km *HKDFStreamingPRFKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { return nil, errHKDFStreamingPRFNotImplemented } // DoesSupport returns true iff this KeyManager supports key type identified by // typeURL. func (km *HKDFStreamingPRFKeyManager) DoesSupport(typeURL string) bool { return typeURL == hkdfPRFTypeURL } // TypeURL returns the type URL that identifes the key type of keys managed by // this KeyManager. func (km *HKDFStreamingPRFKeyManager) TypeURL() string { return hkdfPRFTypeURL } ================================================ FILE: go/keyderivation/internal/streamingprf/hkdf_streaming_prf_key_manager_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package streamingprf_test import ( "strings" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/keyderivation/internal/streamingprf" "github.com/google/tink/go/subtle/random" aesgcmpb "github.com/google/tink/go/proto/aes_gcm_go_proto" commonpb "github.com/google/tink/go/proto/common_go_proto" hkdfpb "github.com/google/tink/go/proto/hkdf_prf_go_proto" ) func TestHKDFStreamingPRFKeyManagerPrimitive(t *testing.T) { km := streamingprf.HKDFStreamingPRFKeyManager{} for _, test := range []struct { name string hash commonpb.HashType salt []byte }{ { name: "SHA256_nil_salt", hash: commonpb.HashType_SHA256, }, { name: "SHA256_random_salt", hash: commonpb.HashType_SHA256, salt: random.GetRandomBytes(16), }, { name: "SHA512_nil_salt", hash: commonpb.HashType_SHA512, }, { name: "SHA512_random_salt", hash: commonpb.HashType_SHA512, salt: random.GetRandomBytes(16), }, } { t.Run(test.name, func(t *testing.T) { key := &hkdfpb.HkdfPrfKey{ Version: 0, Params: &hkdfpb.HkdfPrfParams{ Hash: test.hash, Salt: test.salt, }, KeyValue: random.GetRandomBytes(32), } serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", key, err) } p, err := km.Primitive(serializedKey) if err != nil { t.Fatalf("Primitive() err = %v, want nil", err) } prf, ok := p.(streamingprf.StreamingPRF) if !ok { t.Fatal("primitive is not StreamingPRF") } r, err := prf.Compute(random.GetRandomBytes(32)) if err != nil { t.Fatalf("Compute() err = %v, want nil", err) } limit := limitFromHash(t, test.hash) out := make([]byte, limit) n, err := r.Read(out) if n != limit || err != nil { t.Errorf("Read() not enough bytes: %d, %v", n, err) } }) } } func TestHKDFStreamingPRFKeyManagerPrimitiveRejectsIncorrectKeys(t *testing.T) { km := streamingprf.HKDFStreamingPRFKeyManager{} missingParamsKey := &hkdfpb.HkdfPrfKey{ Version: 0, KeyValue: random.GetRandomBytes(32), } serializedMissingParamsKey, err := proto.Marshal(missingParamsKey) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", serializedMissingParamsKey, err) } aesGCMKey := &aesgcmpb.AesGcmKey{Version: 0} serializedAESGCMKey, err := proto.Marshal(aesGCMKey) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", aesGCMKey, err) } for _, test := range []struct { name string serializedKey []byte }{ { name: "nil key", }, { name: "zero-length key", serializedKey: []byte{}, }, { name: "missing params", serializedKey: serializedMissingParamsKey, }, { name: "wrong key type", serializedKey: serializedAESGCMKey, }, } { t.Run(test.name, func(t *testing.T) { if _, err := km.Primitive(test.serializedKey); err == nil { t.Error("Primitive() err = nil, want non-nil") } }) } } func TestHKDFStreamingPRFKeyManagerPrimitiveRejectsInvalidKeys(t *testing.T) { km := streamingprf.HKDFStreamingPRFKeyManager{} validKey := &hkdfpb.HkdfPrfKey{ Version: 0, Params: &hkdfpb.HkdfPrfParams{ Hash: commonpb.HashType_SHA256, Salt: random.GetRandomBytes(16), }, KeyValue: random.GetRandomBytes(32), } serializedValidKey, err := proto.Marshal(validKey) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", validKey, err) } if _, err := km.Primitive(serializedValidKey); err != nil { t.Errorf("Primitive() err = %v, want nil", err) } for _, test := range []struct { name string version uint32 hash commonpb.HashType keyValue []byte }{ { "invalid version", 100, validKey.GetParams().GetHash(), validKey.GetKeyValue(), }, { "invalid hash", validKey.GetVersion(), commonpb.HashType_SHA1, validKey.GetKeyValue(), }, { "invalid key size", validKey.GetVersion(), validKey.GetParams().GetHash(), random.GetRandomBytes(12), }, } { t.Run(test.name, func(t *testing.T) { key := &hkdfpb.HkdfPrfKey{ Version: test.version, Params: &hkdfpb.HkdfPrfParams{ Hash: test.hash, // There is no concept of an invalid salt, as it can either be nil or // have a value. Salt: validKey.GetParams().GetSalt(), }, KeyValue: test.keyValue, } serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", key, err) } if _, err := km.Primitive(serializedKey); err == nil { t.Error("Primitive() err = nil, want non-nil") } }) } } func TestHKDFStreamingPRFKeyManagerNewKeyAndNewKeyData(t *testing.T) { km := streamingprf.HKDFStreamingPRFKeyManager{} notImplemented := "not implemented" if _, err := km.NewKey(random.GetRandomBytes(16)); !strings.Contains(err.Error(), notImplemented) { t.Errorf("NewKey() err = %v, want containing %q", err, notImplemented) } if _, err := km.NewKeyData(random.GetRandomBytes(16)); !strings.Contains(err.Error(), notImplemented) { t.Errorf("NewKey() err = %v, want containing %q", err, notImplemented) } } func TestHKDFStreamingPRFKeyManagerDoesSupport(t *testing.T) { km := streamingprf.HKDFStreamingPRFKeyManager{} if !km.DoesSupport(hkdfPRFTypeURL) { t.Errorf("DoesSupport(%q) = false, want true", hkdfPRFTypeURL) } if unsupported := "unsupported.key.type"; km.DoesSupport(unsupported) { t.Errorf("DoesSupport(%q) = true, want false", unsupported) } } func TestHKDFStreamingPRFKeyManagerTypeURL(t *testing.T) { km := streamingprf.HKDFStreamingPRFKeyManager{} if km.TypeURL() != hkdfPRFTypeURL { t.Errorf("TypeURL() = %q, want %q", km.TypeURL(), hkdfPRFTypeURL) } } ================================================ FILE: go/keyderivation/internal/streamingprf/hkdf_streaming_prf_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package streamingprf import ( "bytes" "encoding/hex" "fmt" "io" "strings" "testing" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" ) func TestNewHKDFStreamingPRF(t *testing.T) { for _, test := range []struct { name string hash string salt []byte }{ { name: "SHA256_nil_salt", hash: "SHA256", }, { name: "SHA256_random_salt", hash: "SHA256", salt: random.GetRandomBytes(16), }, { name: "SHA512_nil_salt", hash: "SHA512", }, { name: "SHA512_random_salt", hash: "SHA512", salt: random.GetRandomBytes(16), }, } { t.Run(test.name, func(t *testing.T) { key := random.GetRandomBytes(32) h, err := newHKDFStreamingPRF(test.hash, key, test.salt) if err != nil { t.Fatalf("newHKDFStreamingPRF() err = %v, want nil", err) } if !bytes.Equal(h.key, key) { t.Errorf("key = %v, want %v", h.key, key) } if !bytes.Equal(h.salt, test.salt) { t.Errorf("salt = %v, want %v", h.salt, test.salt) } }) } } func TestNewHKDFStreamingPRFFails(t *testing.T) { for _, test := range []struct { hash string keySize uint32 }{ { hash: "SHA256", keySize: 16, }, { hash: "SHA512", keySize: 16}, { hash: "SHA1", keySize: 20, }, } { t.Run(test.hash, func(t *testing.T) { if _, err := newHKDFStreamingPRF(test.hash, random.GetRandomBytes(test.keySize), nil); err == nil { t.Error("newHKDFStreamingPRF() err = nil, want non-nil") } }) } } func TestHKDFStreamingPRFWithRFCVector(t *testing.T) { // This is the only vector that uses an accepted hash function and has key // size >= minHKDFStreamingPRFKeySize. // https://www.rfc-editor.org/rfc/rfc5869#appendix-A.2 vec := struct { hash string key string salt string info string outLen int okm string }{ hash: "SHA256", key: "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f", salt: "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf", info: "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", outLen: 82, okm: "b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87", } key, err := hex.DecodeString(vec.key) if err != nil { t.Fatalf("hex.DecodeString err = %v, want nil", err) } salt, err := hex.DecodeString(vec.salt) if err != nil { t.Fatalf("hex.DecodeString err = %v, want nil", err) } info, err := hex.DecodeString(vec.info) if err != nil { t.Fatalf("hex.DecodeString err = %v, want nil", err) } h, err := newHKDFStreamingPRF(vec.hash, key, salt) if err != nil { t.Fatalf("newHKDFStreamingPRF() err = %v, want nil", err) } r, err := h.Compute(info) if err != nil { t.Fatalf("Compute() err = %v, want nil", err) } out := make([]byte, vec.outLen) if _, err := io.ReadAtLeast(r, out, len(out)); err != nil { t.Fatalf("io.ReadAtLeast err = %v, want nil", err) } if hex.EncodeToString(out) != vec.okm { t.Errorf("Compute() = %v, want %v", hex.EncodeToString(out), vec.okm) } } func TestHKDFStreamingPRFWithWycheproof(t *testing.T) { testutil.SkipTestIfTestSrcDirIsNotSet(t) type hkdfCase struct { testutil.WycheproofCase IKM testutil.HexBytes `json:"ikm"` Salt testutil.HexBytes `json:"salt"` Info testutil.HexBytes `json:"info"` Size uint32 `json:"size"` OKM testutil.HexBytes `json:"okm"` } type hkdfGroup struct { testutil.WycheproofGroup KeySize uint32 `json:"keySize"` Type string `json:"type"` Tests []*hkdfCase `json:"tests"` } type hkdfSuite struct { testutil.WycheproofSuite TestGroups []*hkdfGroup `json:"testGroups"` } count := 0 for _, hash := range []string{"SHA256", "SHA512"} { filename := fmt.Sprintf("hkdf_%s_test.json", strings.ToLower(hash)) suite := new(hkdfSuite) if err := testutil.PopulateSuite(suite, filename); err != nil { t.Fatalf("testutil.PopulateSuite(%v, %s): %v", suite, filename, err) } for _, group := range suite.TestGroups { for _, test := range group.Tests { caseName := fmt.Sprintf("%s(%d):Case-%d", hash, group.KeySize, test.CaseID) t.Run(caseName, func(t *testing.T) { if got, want := len(test.IKM), int(group.KeySize/8); got != want { t.Fatalf("invalid key length = %d, want %d", got, want) } count++ h, err := newHKDFStreamingPRF(hash, test.IKM, test.Salt) switch test.Result { case "valid": if len(test.IKM) < minHKDFStreamingPRFKeySize { if err == nil { t.Error("newHKDFStreamingPRF err = nil, want non-nil") } return } if err != nil { t.Fatalf("newHKDFStreamingPRF err = %v, want nil", err) } r, err := h.Compute(test.Info) if err != nil { t.Fatalf("Compute() err = %v, want nil", err) } out := make([]byte, test.Size) if _, err := io.ReadAtLeast(r, out, len(out)); err != nil { t.Fatalf("io.ReadAtLeast err = %v, want nil", err) } if !bytes.Equal(out, test.OKM) { t.Errorf("Compute() = %v, want %v", out, test.OKM) } case "invalid": if err != nil { return } r, err := h.Compute(test.Info) if err != nil { t.Fatalf("Compute() err = %v, want nil", err) } out := make([]byte, test.Size) if _, err := io.ReadAtLeast(r, out, len(out)); err == nil { t.Error("io.ReadAtLeast err = nil, want non-nil") } default: t.Errorf("unsupported test result: %s", test.Result) } }) } } } if count < 200 { t.Errorf("number of test cases = %d, want > 200", count) } } ================================================ FILE: go/keyderivation/internal/streamingprf/streaming_prf.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package streamingprf provides implementations of streaming pseudorandom // function families. package streamingprf import ( "io" ) // StreamingPRF is the interface used to represent a streaming pseudorandom // function family for a specified key. // // It has the same properties as the PRF primitive. type StreamingPRF interface { // Compute computes the PRF selected by the specified key on input and returns // the result via a reader. Compute(input []byte) (io.Reader, error) } ================================================ FILE: go/keyderivation/internal/streamingprf/streaming_prf_factory.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package streamingprf import ( "errors" "fmt" "io" "github.com/google/tink/go/core/primitiveset" "github.com/google/tink/go/keyset" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // New generates a new instance of the Streaming PRF primitive. func New(h *keyset.Handle) (StreamingPRF, error) { if h == nil { return nil, errors.New("keyset handle can't be nil") } ps, err := h.PrimitivesWithKeyManager(new(HKDFStreamingPRFKeyManager)) if err != nil { return nil, fmt.Errorf("streaming_prf_factory: cannot obtain primitive set: %v", err) } return newWrappedStreamingPRF(ps) } // wrappedStreamingPRF is a Streaming PRF implementation that uses the underlying primitive set for Streaming PRF. type wrappedStreamingPRF struct { ps *primitiveset.PrimitiveSet } // Asserts that wrappedStreamingPRF implements the StreamingPRF interface. var _ StreamingPRF = (*wrappedStreamingPRF)(nil) func newWrappedStreamingPRF(ps *primitiveset.PrimitiveSet) (*wrappedStreamingPRF, error) { if rawEntries, err := ps.RawEntries(); err != nil || len(rawEntries) != 1 { return nil, errors.New("streaming_prf_factory: only accepts keysets with 1 RAW key") } // ps.Entries is a map of prefix type -> []*Entry. if len(ps.Entries) != 1 { return nil, errors.New("streaming_prf_factory: only accepts keys with prefix type RAW") } if _, ok := (ps.Primary.Primitive).(StreamingPRF); !ok { return nil, errors.New("streaming_prf_factory: not a Streaming PRF primitive") } if ps.Primary.PrefixType != tinkpb.OutputPrefixType_RAW { return nil, errors.New("streaming_prf_factory: primary key prefix type is not RAW") } if ps.Primary.Status != tinkpb.KeyStatusType_ENABLED { return nil, errors.New("streaming_prf_factory: primary key is not ENABLED") } return &wrappedStreamingPRF{ps: ps}, nil } func (w *wrappedStreamingPRF) Compute(input []byte) (io.Reader, error) { primary := w.ps.Primary p, ok := (primary.Primitive).(StreamingPRF) if !ok { return nil, errors.New("streaming_prf_factory: not a Streaming PRF primitive") } return p.Compute(input) } ================================================ FILE: go/keyderivation/internal/streamingprf/streaming_prf_factory_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package streamingprf_test import ( "bytes" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/aead" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/keyderivation/internal/streamingprf" "github.com/google/tink/go/keyset" "github.com/google/tink/go/prf" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testkeyset" commonpb "github.com/google/tink/go/proto/common_go_proto" hkdfpb "github.com/google/tink/go/proto/hkdf_prf_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestNew(t *testing.T) { keyData, err := registry.NewKeyData(prf.HKDFSHA256PRFKeyTemplate()) if err != nil { t.Fatalf("registry.NewKeyData() err = %v", err) } ks := &tinkpb.Keyset{ PrimaryKeyId: 119, Key: []*tinkpb.Keyset_Key{ &tinkpb.Keyset_Key{ KeyData: keyData, Status: tinkpb.KeyStatusType_ENABLED, KeyId: 119, OutputPrefixType: tinkpb.OutputPrefixType_RAW, }, }, } handle, err := testkeyset.NewHandle(ks) if err != nil { t.Fatalf("testkeyset.NewHandle(ks) err = %v, want nil", err) } prf, err := streamingprf.New(handle) if err != nil { t.Fatalf("streamingprf.New() err = %v, want nil", err) } r, err := prf.Compute(random.GetRandomBytes(32)) if err != nil { t.Fatalf("prf.Compute() err = %v, want nil", err) } limit := limitFromHash(t, commonpb.HashType_SHA256) out := make([]byte, limit) n, err := r.Read(out) if n != limit || err != nil { t.Errorf("Read() bytes = %d, want %d: %v", n, limit, err) } } func TestNewEqualToStreamingPRFPrimitive(t *testing.T) { streamingPRFKM := streamingprf.HKDFStreamingPRFKeyManager{} prfKM, err := registry.GetKeyManager(hkdfPRFTypeURL) if err != nil { t.Fatalf("GetKeyManager(%s) err = %v, want nil", hkdfPRFTypeURL, err) } for _, test := range []struct { name string hash commonpb.HashType salt []byte }{ { name: "SHA256_nil_salt", hash: commonpb.HashType_SHA256, }, { name: "SHA256_random_salt", hash: commonpb.HashType_SHA256, salt: random.GetRandomBytes(16), }, { name: "SHA512_nil_salt", hash: commonpb.HashType_SHA512, }, { name: "SHA512_random_salt", hash: commonpb.HashType_SHA512, salt: random.GetRandomBytes(16), }, } { t.Run(test.name, func(t *testing.T) { // Construct shared key data. keyFormat := &hkdfpb.HkdfPrfKeyFormat{ Params: &hkdfpb.HkdfPrfParams{ Hash: test.hash, Salt: test.salt, }, KeySize: 32, Version: 0, } serializedKeyFormat, err := proto.Marshal(keyFormat) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", keyFormat, err) } sharedKeyData, err := prfKM.NewKeyData(serializedKeyFormat) if err != nil { t.Fatalf("NewKeyData() err = %v, want nil", err) } // Use shared key data to create StreamingPRF using New(). var primaryKeyID uint32 = 12 handle, err := testkeyset.NewHandle( &tinkpb.Keyset{ PrimaryKeyId: primaryKeyID, Key: []*tinkpb.Keyset_Key{ &tinkpb.Keyset_Key{ KeyData: sharedKeyData, Status: tinkpb.KeyStatusType_ENABLED, KeyId: primaryKeyID, OutputPrefixType: tinkpb.OutputPrefixType_RAW, }, }, }) if err != nil { t.Fatalf("testkeyset.NewHandle() err = %v, want nil", err) } gotPRF, err := streamingprf.New(handle) if err != nil { t.Fatalf("streamingprf.New() err = %v, want nil", err) } // Use shared key data to create StreamingPRF using Primitive(). p, err := streamingPRFKM.Primitive(sharedKeyData.GetValue()) if err != nil { t.Fatalf("Primitive() err = %v, want nil", err) } wantPRF, ok := p.(streamingprf.StreamingPRF) if !ok { t.Fatal("primitive is not StreamingPRF") } // Verify both PRFs return the same results. limit := limitFromHash(t, test.hash) got, want := make([]byte, limit), make([]byte, limit) data := random.GetRandomBytes(32) { r, err := gotPRF.Compute(data) if err != nil { t.Fatalf("Compute() err = %v, want nil", err) } n, err := r.Read(got) if n != limit || err != nil { t.Fatalf("Read() bytes = %d, want %d: %v", n, limit, err) } } { r, err := wantPRF.Compute(data) if err != nil { t.Fatalf("Compute() err = %v, want nil", err) } n, err := r.Read(want) if n != limit || err != nil { t.Fatalf("Read() bytes = %d, want %d: %v", n, limit, err) } } if !bytes.Equal(got, want) { t.Errorf("Read() = %v, want %v", got, want) } }) } } func TestNewRejectsIncorrectKeysetHandle(t *testing.T) { if _, err := streamingprf.New(nil); err == nil { t.Error("streamingprf.New() err = nil, want non-nil") } aeadHandle, err := keyset.NewHandle(aead.AES128GCMKeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } if _, err := streamingprf.New(aeadHandle); err == nil { t.Error("streamingprf.New() err = nil, want non-nil") } } func TestNewRejectsInvalidKeysetHandle(t *testing.T) { keyData, err := registry.NewKeyData(prf.HKDFSHA256PRFKeyTemplate()) if err != nil { t.Fatalf("registry.NewKeyData() err = %v", err) } for _, test := range []struct { name string keyset *tinkpb.Keyset }{ { "multiple raw keys", &tinkpb.Keyset{ PrimaryKeyId: 119, Key: []*tinkpb.Keyset_Key{ &tinkpb.Keyset_Key{ KeyData: keyData, Status: tinkpb.KeyStatusType_ENABLED, KeyId: 119, OutputPrefixType: tinkpb.OutputPrefixType_RAW, }, &tinkpb.Keyset_Key{ KeyData: keyData, Status: tinkpb.KeyStatusType_ENABLED, KeyId: 200, OutputPrefixType: tinkpb.OutputPrefixType_RAW, }, }, }, }, { "various output prefix keys", &tinkpb.Keyset{ PrimaryKeyId: 119, Key: []*tinkpb.Keyset_Key{ &tinkpb.Keyset_Key{ KeyData: keyData, Status: tinkpb.KeyStatusType_ENABLED, KeyId: 119, OutputPrefixType: tinkpb.OutputPrefixType_RAW, }, &tinkpb.Keyset_Key{ KeyData: keyData, Status: tinkpb.KeyStatusType_ENABLED, KeyId: 200, OutputPrefixType: tinkpb.OutputPrefixType_TINK, }, }, }, }, { "invalid prefix type", &tinkpb.Keyset{ PrimaryKeyId: 119, Key: []*tinkpb.Keyset_Key{ &tinkpb.Keyset_Key{ KeyData: keyData, Status: tinkpb.KeyStatusType_ENABLED, KeyId: 119, OutputPrefixType: tinkpb.OutputPrefixType_TINK, }, }, }}, { "invalid status", &tinkpb.Keyset{ PrimaryKeyId: 119, Key: []*tinkpb.Keyset_Key{ &tinkpb.Keyset_Key{ KeyData: keyData, Status: tinkpb.KeyStatusType_UNKNOWN_STATUS, KeyId: 119, OutputPrefixType: tinkpb.OutputPrefixType_RAW, }, }, }, }, { "no primary key", &tinkpb.Keyset{ PrimaryKeyId: 200, Key: []*tinkpb.Keyset_Key{ &tinkpb.Keyset_Key{ KeyData: keyData, Status: tinkpb.KeyStatusType_UNKNOWN_STATUS, KeyId: 119, OutputPrefixType: tinkpb.OutputPrefixType_RAW, }, }, }, }, } { t.Run(test.name, func(t *testing.T) { handle, err := testkeyset.NewHandle(test.keyset) if err != nil { t.Fatalf("testkeyset.NewHandle(test.keyset) err = %v, want nil", err) } if _, err := streamingprf.New(handle); err == nil { t.Error("streamingprf.New() err = nil, want non-nil") } }) } } ================================================ FILE: go/keyderivation/internal/streamingprf/streaming_prf_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package streamingprf_test import ( "crypto/sha256" "crypto/sha512" "testing" commonpb "github.com/google/tink/go/proto/common_go_proto" ) const hkdfPRFTypeURL = "type.googleapis.com/google.crypto.tink.HkdfPrfKey" // limitFromHash returns the maximum output bytes from a HKDF using hash. func limitFromHash(t *testing.T, hash commonpb.HashType) (limit int) { t.Helper() switch hash { case commonpb.HashType_SHA256: limit = sha256.Size * 255 case commonpb.HashType_SHA512: limit = sha512.Size * 255 default: t.Fatalf("unsupported hash type: %s", hash.String()) } return } ================================================ FILE: go/keyderivation/keyderivation.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package keyderivation provides implementations of the keyset deriver // primitive. package keyderivation import ( "fmt" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal" "github.com/google/tink/go/keyset" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) var ( keysetHandle = internal.KeysetHandle.(func(*tinkpb.Keyset, ...keyset.Option) (*keyset.Handle, error)) ) func init() { if err := registry.RegisterKeyManager(new(prfBasedDeriverKeyManager)); err != nil { panic(fmt.Sprintf("keyderivation.init() failed: %v", err)) } } ================================================ FILE: go/keyderivation/keyderivation_key_templates.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyderivation import ( "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/keyset" prfderpb "github.com/google/tink/go/proto/prf_based_deriver_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // CreatePRFBasedKeyTemplate creates a PRF-Based Deriver key template with the // specified PRF and derived key templates. If either the PRF or derived key // templates are not supported by the registry, an error is returned. func CreatePRFBasedKeyTemplate(prfKeyTemplate, derivedKeyTemplate *tinkpb.KeyTemplate) (*tinkpb.KeyTemplate, error) { keyFormat := &prfderpb.PrfBasedDeriverKeyFormat{ PrfKeyTemplate: prfKeyTemplate, Params: &prfderpb.PrfBasedDeriverParams{ DerivedKeyTemplate: derivedKeyTemplate, }, } serializedFormat, err := proto.Marshal(keyFormat) if err != nil { return nil, fmt.Errorf("failed to marshal key format: %s", err) } template := &tinkpb.KeyTemplate{ TypeUrl: prfBasedDeriverTypeURL, OutputPrefixType: derivedKeyTemplate.GetOutputPrefixType(), Value: serializedFormat, } // Verify `template` is derivable. if _, err := keyset.NewHandle(template); err != nil { return nil, err } return template, nil } ================================================ FILE: go/keyderivation/keyderivation_key_templates_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyderivation_test import ( "bytes" "fmt" "testing" "github.com/google/tink/go/aead" "github.com/google/tink/go/keyderivation" "github.com/google/tink/go/keyset" "github.com/google/tink/go/prf" "github.com/google/tink/go/subtle/random" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestPRFBasedKeyTemplateDerivesAESGCMKeyset(t *testing.T) { plaintext := random.GetRandomBytes(16) associatedData := random.GetRandomBytes(8) prfs := []struct { name string template *tinkpb.KeyTemplate }{ { name: "HKDF-SHA256", template: prf.HKDFSHA256PRFKeyTemplate(), }, } derivations := []struct { name string template *tinkpb.KeyTemplate }{ { name: "AES128GCM", template: aead.AES128GCMKeyTemplate(), }, { name: "AES256GCM", template: aead.AES256GCMKeyTemplate(), }, { name: "AES256GCMNoPrefix", template: aead.AES256GCMNoPrefixKeyTemplate(), }, } for _, prf := range prfs { for _, der := range derivations { for _, salt := range [][]byte{nil, []byte("salt")} { name := fmt.Sprintf("%s_%s", prf.name, der.name) if salt != nil { name += "_with_salt" } t.Run(name, func(t *testing.T) { template, err := keyderivation.CreatePRFBasedKeyTemplate(prf.template, der.template) if err != nil { t.Fatalf("CreatePRFBasedKeyTemplate() err = %v, want nil", err) } handle, err := keyset.NewHandle(template) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } d, err := keyderivation.New(handle) if err != nil { t.Fatalf("keyderivation.New() err = %v, want nil", err) } derivedHandle, err := d.DeriveKeyset(salt) if err != nil { t.Fatalf("DeriveKeyset() err = %v, want nil", err) } a, err := aead.New(derivedHandle) if err != nil { t.Fatalf("aead.New() err = %v, want nil", err) } ciphertext, err := a.Encrypt(plaintext, associatedData) if err != nil { t.Fatalf("Encrypt() err = %v, want nil", err) } gotPlaintext, err := a.Decrypt(ciphertext, associatedData) if err != nil { t.Fatalf("Decrypt() err = %v, want nil", err) } if !bytes.Equal(gotPlaintext, plaintext) { t.Errorf("Decrypt() = %v, want %v", gotPlaintext, plaintext) } }) } } } } func TestInvalidPRFBasedDeriverKeyTemplates(t *testing.T) { for _, test := range []struct { name string prfKeyTemplate *tinkpb.KeyTemplate derivedKeyTemplate *tinkpb.KeyTemplate }{ { name: "nil templates", }, { name: "nil PRF key template", derivedKeyTemplate: aead.AES128GCMKeyTemplate(), }, { name: "nil derived key template", prfKeyTemplate: prf.HKDFSHA256PRFKeyTemplate(), }, { name: "malformed PRF key template", prfKeyTemplate: &tinkpb.KeyTemplate{TypeUrl: "\xff"}, derivedKeyTemplate: aead.AES128GCMKeyTemplate(), }, // AES128CTRHMACSHA256KeyTemplate() is an unsupported derived key template // because DeriveKey() is not implemented in the AES-CTR-HMAC key manager. // TODO(b/227682336): Add mock key manager that doesn't derive keys. { name: "unsupported templates", prfKeyTemplate: aead.AES128GCMKeyTemplate(), derivedKeyTemplate: aead.AES128CTRHMACSHA256KeyTemplate()}, { name: "unsupported PRF key template", prfKeyTemplate: aead.AES128GCMKeyTemplate(), derivedKeyTemplate: aead.AES128GCMKeyTemplate(), }, { name: "unsupported derived key template", prfKeyTemplate: prf.HKDFSHA256PRFKeyTemplate(), derivedKeyTemplate: aead.AES128CTRHMACSHA256KeyTemplate(), }, } { t.Run(test.name, func(t *testing.T) { if _, err := keyderivation.CreatePRFBasedKeyTemplate(test.prfKeyTemplate, test.derivedKeyTemplate); err == nil { t.Error("CreatePRFBasedKeyTemplate() err = nil, want non-nil") } }) } } ================================================ FILE: go/keyderivation/keyderivation_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyderivation_test import ( "fmt" "log" "github.com/google/tink/go/aead" "github.com/google/tink/go/keyderivation" "github.com/google/tink/go/keyset" "github.com/google/tink/go/prf" ) func Example() { template, err := keyderivation.CreatePRFBasedKeyTemplate(prf.HKDFSHA256PRFKeyTemplate(), aead.AES128GCMKeyTemplate()) if err != nil { log.Fatal(err) } handle, err := keyset.NewHandle(template) if err != nil { log.Fatal(err) } deriver, err := keyderivation.New(handle) if err != nil { log.Fatal(err) } derivedHandle, err := deriver.DeriveKeyset([]byte("salt")) if err != nil { log.Fatal(err) } // Use the derived keyset. a, err := aead.New(derivedHandle) if err != nil { log.Fatal(err) } ciphertext, err := a.Encrypt([]byte("a secret message"), nil) if err != nil { log.Fatal(err) } plaintext, err := a.Decrypt(ciphertext, nil) if err != nil { log.Fatal(err) } fmt.Println(string(plaintext)) // Output: a secret message } ================================================ FILE: go/keyderivation/keyset_deriver.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyderivation import ( "github.com/google/tink/go/keyset" ) // KeysetDeriver is the interface used to derive new keysets based on an // additional input, the salt. // // The salt is used to create the keyset using a pseudorandom function. // Implementations must be indistinguishable from ideal KeysetDerivers, which, // for every salt, generates a new random keyset and caches it. type KeysetDeriver interface { DeriveKeyset(salt []byte) (*keyset.Handle, error) } ================================================ FILE: go/keyderivation/keyset_deriver_factory.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyderivation import ( "errors" "fmt" "github.com/google/tink/go/core/primitiveset" "github.com/google/tink/go/insecurecleartextkeyset" "github.com/google/tink/go/keyset" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) var errNotKeysetDeriverPrimitive = errors.New("keyset_deriver_factory: not a Keyset Deriver primitive") // New generates a new instance of the Keyset Deriver primitive. func New(handle *keyset.Handle) (KeysetDeriver, error) { if handle == nil { return nil, errors.New("keyset_deriver_factory: keyset handle can't be nil") } ps, err := handle.PrimitivesWithKeyManager(nil) if err != nil { return nil, fmt.Errorf("keyset_deriver_factory: cannot obtain primitive set: %v", err) } return newWrappedKeysetDeriver(ps) } // wrappedKeysetDeriver is a Keyset Deriver implementation that uses the underlying primitive set to derive keysets. type wrappedKeysetDeriver struct { ps *primitiveset.PrimitiveSet } // Asserts that wrappedKeysetDeriver implements the KeysetDeriver interface. var _ KeysetDeriver = (*wrappedKeysetDeriver)(nil) func newWrappedKeysetDeriver(ps *primitiveset.PrimitiveSet) (*wrappedKeysetDeriver, error) { if _, ok := (ps.Primary.Primitive).(KeysetDeriver); !ok { return nil, errNotKeysetDeriverPrimitive } for _, p := range ps.EntriesInKeysetOrder { if _, ok := (p.Primitive).(KeysetDeriver); !ok { return nil, errNotKeysetDeriverPrimitive } } return &wrappedKeysetDeriver{ps: ps}, nil } func (w *wrappedKeysetDeriver) DeriveKeyset(salt []byte) (*keyset.Handle, error) { keys := make([]*tinkpb.Keyset_Key, 0, len(w.ps.EntriesInKeysetOrder)) for _, e := range w.ps.EntriesInKeysetOrder { p, ok := (e.Primitive).(KeysetDeriver) if !ok { return nil, errNotKeysetDeriverPrimitive } handle, err := p.DeriveKeyset(salt) if err != nil { return nil, errors.New("keyset_deriver_factory: keyset derivation failed") } if len(handle.KeysetInfo().GetKeyInfo()) != 1 { return nil, errors.New("keyset_deriver_factory: primitive must derive keyset handle with exactly one key") } ks := insecurecleartextkeyset.KeysetMaterial(handle) if len(ks.GetKey()) != 1 { return nil, errors.New("keyset_deriver_factory: primitive must derive keyset handle with exactly one key") } // Set all fields, except for KeyData, to match the Entry's in the keyset. key := &tinkpb.Keyset_Key{ KeyData: ks.GetKey()[0].GetKeyData(), Status: e.Status, KeyId: e.KeyID, OutputPrefixType: e.PrefixType, } keys = append(keys, key) } ks := &tinkpb.Keyset{ PrimaryKeyId: w.ps.Primary.KeyID, Key: keys, } return keysetHandle(ks) } ================================================ FILE: go/keyderivation/keyset_deriver_factory_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyderivation import ( "strings" "testing" "github.com/google/tink/go/aead" "github.com/google/tink/go/core/cryptofmt" "github.com/google/tink/go/core/primitiveset" "github.com/google/tink/go/keyset" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // invalidDeriver returns two keys, but wrappedKeysetDeriver accepts only one. type invalidDeriver struct{} var _ KeysetDeriver = (*invalidDeriver)(nil) func (i *invalidDeriver) DeriveKeyset(salt []byte) (*keyset.Handle, error) { manager := keyset.NewManager() keyID, err := manager.Add(aead.AES128GCMKeyTemplate()) if err != nil { return nil, err } manager.SetPrimary(keyID) if _, err = manager.Add(aead.AES256GCMKeyTemplate()); err != nil { return nil, err } return manager.Handle() } func TestDeriveKeysetWithInvalidPrimitiveImplementationFails(t *testing.T) { entry := &primitiveset.Entry{ KeyID: 119, Primitive: &invalidDeriver{}, Prefix: cryptofmt.RawPrefix, Status: tinkpb.KeyStatusType_ENABLED, TypeURL: "type.googleapis.com/google.crypto.tink.PrfBasedDeriverKey", } ps := &primitiveset.PrimitiveSet{ Primary: entry, Entries: map[string][]*primitiveset.Entry{ cryptofmt.RawPrefix: []*primitiveset.Entry{entry}, }, EntriesInKeysetOrder: []*primitiveset.Entry{entry}, } wrappedDeriver, err := newWrappedKeysetDeriver(ps) if err != nil { t.Fatalf("newWrappedKeysetDeriver() err = %v, want nil", err) } _, err = wrappedDeriver.DeriveKeyset([]byte("salt")) if err == nil { t.Fatal("DeriveKeyset() err = nil, want non-nil") } if !strings.Contains(err.Error(), "exactly one key") { t.Errorf("DeriveKeyset() err = %q, doesn't contain %q", err, "exactly one key") } } func TestNewWrappedKeysetDeriverWrongPrimitiveFails(t *testing.T) { handle, err := keyset.NewHandle(aead.AES128GCMKeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } ps, err := handle.Primitives() if err != nil { t.Fatalf("handle.Primitives() err = %v, want nil", err) } if _, err := newWrappedKeysetDeriver(ps); err == nil { t.Errorf("newWrappedKeysetDeriver() err = nil, want non-nil") } } ================================================ FILE: go/keyderivation/keyset_deriver_factory_x_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyderivation_test import ( "bytes" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/aead" "github.com/google/tink/go/keyderivation" "github.com/google/tink/go/keyset" "github.com/google/tink/go/prf" "github.com/google/tink/go/subtle/random" prfderpb "github.com/google/tink/go/proto/prf_based_deriver_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestWrappedKeysetDeriver(t *testing.T) { // Construct deriving keyset handle containing one key. aes128GCMKeyFormat, err := proto.Marshal(&prfderpb.PrfBasedDeriverKeyFormat{ PrfKeyTemplate: prf.HKDFSHA256PRFKeyTemplate(), Params: &prfderpb.PrfBasedDeriverParams{ DerivedKeyTemplate: aead.AES128GCMKeyTemplate(), }, }) if err != nil { t.Fatalf("proto.Marshal(aes128GCMKeyFormat) err = %v, want nil", err) } singleKeyHandle, err := keyset.NewHandle(&tinkpb.KeyTemplate{ TypeUrl: prfBasedDeriverTypeURL, OutputPrefixType: tinkpb.OutputPrefixType_RAW, Value: aes128GCMKeyFormat, }) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } // Construct deriving keyset handle containing three keys. xChaChaKeyFormat, err := proto.Marshal(&prfderpb.PrfBasedDeriverKeyFormat{ PrfKeyTemplate: prf.HKDFSHA256PRFKeyTemplate(), Params: &prfderpb.PrfBasedDeriverParams{ DerivedKeyTemplate: aead.XChaCha20Poly1305KeyTemplate(), }, }) if err != nil { t.Fatalf("proto.Marshal(xChaChaKeyFormat) err = %v, want nil", err) } aes256GCMKeyFormat, err := proto.Marshal(&prfderpb.PrfBasedDeriverKeyFormat{ PrfKeyTemplate: prf.HKDFSHA256PRFKeyTemplate(), Params: &prfderpb.PrfBasedDeriverParams{ DerivedKeyTemplate: aead.AES256GCMKeyTemplate(), }, }) if err != nil { t.Fatalf("proto.Marshal(aes256GCMKeyFormat) err = %v, want nil", err) } manager := keyset.NewManager() aes128GCMKeyID, err := manager.Add(&tinkpb.KeyTemplate{ TypeUrl: prfBasedDeriverTypeURL, OutputPrefixType: tinkpb.OutputPrefixType_RAW, Value: aes128GCMKeyFormat, }) if err != nil { t.Fatalf("manager.Add(aes128GCMTemplate) err = %v, want nil", err) } if err := manager.SetPrimary(aes128GCMKeyID); err != nil { t.Fatalf("manager.SetPrimary() err = %v, want nil", err) } if _, err := manager.Add(&tinkpb.KeyTemplate{ TypeUrl: prfBasedDeriverTypeURL, OutputPrefixType: tinkpb.OutputPrefixType_TINK, Value: xChaChaKeyFormat, }); err != nil { t.Fatalf("manager.Add(xChaChaTemplate) err = %v, want nil", err) } if _, err := manager.Add(&tinkpb.KeyTemplate{ TypeUrl: prfBasedDeriverTypeURL, OutputPrefixType: tinkpb.OutputPrefixType_CRUNCHY, Value: aes256GCMKeyFormat, }); err != nil { t.Fatalf("manager.Add(aes256GCMTemplate) err = %v, want nil", err) } multipleKeysHandle, err := manager.Handle() if err != nil { t.Fatalf("manager.Handle() err = %v, want nil", err) } if got, want := len(multipleKeysHandle.KeysetInfo().GetKeyInfo()), 3; got != want { t.Fatalf("len(multipleKeysHandle) = %d, want %d", got, want) } for _, test := range []struct { name string handle *keyset.Handle wantTypeURLs []string }{ { name: "single key", handle: singleKeyHandle, wantTypeURLs: []string{ "type.googleapis.com/google.crypto.tink.AesGcmKey", }, }, { name: "multiple keys", handle: multipleKeysHandle, wantTypeURLs: []string{ "type.googleapis.com/google.crypto.tink.AesGcmKey", "type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key", "type.googleapis.com/google.crypto.tink.AesGcmKey", }, }, } { t.Run(test.name, func(t *testing.T) { // Derive keyset handle. kd, err := keyderivation.New(test.handle) if err != nil { t.Fatalf("keyderivation.New() err = %v, want nil", err) } derivedHandle, err := kd.DeriveKeyset([]byte("salt")) if err != nil { t.Fatalf("DeriveKeyset() err = %v, want nil", err) } // Verify number of derived keys = number of deriving keys. derivedKeyInfo := derivedHandle.KeysetInfo().GetKeyInfo() keyInfo := test.handle.KeysetInfo().GetKeyInfo() if len(derivedKeyInfo) != len(keyInfo) { t.Errorf("number of derived keys = %d, want %d", len(derivedKeyInfo), len(keyInfo)) } if len(derivedKeyInfo) != len(test.wantTypeURLs) { t.Errorf("number of derived keys = %d, want %d", len(derivedKeyInfo), len(keyInfo)) } // Verify derived keys. hasPrimaryKey := false for i, derivedKey := range derivedKeyInfo { derivingKey := keyInfo[i] if got, want := derivedKey.GetOutputPrefixType(), derivingKey.GetOutputPrefixType(); got != want { t.Errorf("GetOutputPrefixType() = %s, want %s", got, want) } if got, want := derivedKey.GetKeyId(), derivingKey.GetKeyId(); got != want { t.Errorf("GetKeyId() = %d, want %d", got, want) } if got, want := derivedKey.GetTypeUrl(), test.wantTypeURLs[i]; got != want { t.Errorf("GetTypeUrl() = %q, want %q", got, want) } if got, want := derivedKey.GetStatus(), derivingKey.GetStatus(); got != want { t.Errorf("GetStatus() = %s, want %s", got, want) } if derivedKey.GetKeyId() == derivedHandle.KeysetInfo().GetPrimaryKeyId() { hasPrimaryKey = true } } if !hasPrimaryKey { t.Errorf("derived keyset has no primary key") } // Verify derived keyset handle works for AEAD. pt := random.GetRandomBytes(16) ad := random.GetRandomBytes(4) a, err := aead.New(derivedHandle) if err != nil { t.Fatalf("aead.New() err = %v, want nil", err) } ct, err := a.Encrypt(pt, ad) if err != nil { t.Fatalf("Encrypt() err = %v, want nil", err) } gotPT, err := a.Decrypt(ct, ad) if err != nil { t.Fatalf("Decrypt() err = %v, want nil", err) } if !bytes.Equal(gotPT, pt) { t.Errorf("Decrypt() = %v, want %v", gotPT, pt) } }) } } func TestNewRejectsNilKeysetHandle(t *testing.T) { if _, err := keyderivation.New(nil); err == nil { t.Error("keyderivation.New() err = nil, want non-nil") } } func TestNewRejectsIncorrectKey(t *testing.T) { kh, err := keyset.NewHandle(aead.AES128GCMKeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } if _, err := keyderivation.New(kh); err == nil { t.Error("keyderivation.New() err = nil, want non-nil") } } ================================================ FILE: go/keyderivation/prf_based_deriver.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyderivation import ( "errors" "fmt" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/keyderivation/internal/streamingprf" "github.com/google/tink/go/keyset" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const hkdfPRFTypeURL = "type.googleapis.com/google.crypto.tink.HkdfPrfKey" // prfBasedDeriver uses prf and the Tink registry to derive a keyset handle as // described by derivedKeyTemplate. type prfBasedDeriver struct { prf streamingprf.StreamingPRF derivedKeyTemplate *tinkpb.KeyTemplate } // Asserts that prfBasedDeriver implements the KeysetDeriver interface. var _ KeysetDeriver = (*prfBasedDeriver)(nil) func newPRFBasedDeriver(prfKeyData *tinkpb.KeyData, derivedKeyTemplate *tinkpb.KeyTemplate) (*prfBasedDeriver, error) { // Obtain Streaming PRF from PRF key data. if prfKeyData == nil { return nil, errors.New("PRF key data is nil") } if prfKeyData.GetTypeUrl() != hkdfPRFTypeURL { return nil, fmt.Errorf("PRF key data with type URL %q is not supported", prfKeyData.GetTypeUrl()) } // For HKDF PRF keys, create a local instance of the HKDF Streaming PRF key // manager and obtain the Streaming PRF interface through it, instead of // obtaining it through the registry. This allows us to keep the HKDF // Streaming PRF key manager out of the registry for smoother deprecation. // // TODO(b/260619626): Remove this once PRF and Streaming PRF share the same // type URL and registry.Primitive() can return multiple interfaces per // primitive. hkdfStreamingPRFKeyManager := streamingprf.HKDFStreamingPRFKeyManager{} p, err := hkdfStreamingPRFKeyManager.Primitive(prfKeyData.GetValue()) if err != nil { return nil, fmt.Errorf("failed to retrieve StreamingPRF primitive from key manager: %v", err) } prf, ok := p.(streamingprf.StreamingPRF) if !ok { return nil, errors.New("primitive is not StreamingPRF") } // Validate derived key template. if !internalregistry.CanDeriveKeys(derivedKeyTemplate.GetTypeUrl()) { return nil, errors.New("derived key template is not a derivable key type") } return &prfBasedDeriver{ prf: prf, derivedKeyTemplate: derivedKeyTemplate, }, nil } func (p *prfBasedDeriver) DeriveKeyset(salt []byte) (*keyset.Handle, error) { randomness, err := p.prf.Compute(salt) if err != nil { return nil, fmt.Errorf("compute randomness from PRF failed: %v", err) } keyData, err := internalregistry.DeriveKey(p.derivedKeyTemplate, randomness) if err != nil { return nil, fmt.Errorf("derive key failed: %v", err) } // Fill in placeholder values for key ID, status, and output prefix type. // These will be populated with the correct values in the keyset deriver // factory. This is acceptable because the keyset as-is will never leave Tink, // and the user only interacts via the keyset deriver factory. var primaryKeyID uint32 = 0 return keysetHandle(&tinkpb.Keyset{ PrimaryKeyId: primaryKeyID, Key: []*tinkpb.Keyset_Key{ &tinkpb.Keyset_Key{ KeyData: keyData, Status: tinkpb.KeyStatusType_UNKNOWN_STATUS, KeyId: primaryKeyID, OutputPrefixType: tinkpb.OutputPrefixType_UNKNOWN_PREFIX, }, }, }) } ================================================ FILE: go/keyderivation/prf_based_deriver_key_manager.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyderivation import ( "errors" "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/keyset" prfderpb "github.com/google/tink/go/proto/prf_based_deriver_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( prfBasedDeriverKeyVersion = 0 prfBasedDeriverTypeURL = "type.googleapis.com/google.crypto.tink.PrfBasedDeriverKey" ) var ( errInvalidPRFBasedDeriverKey = errors.New("prf_based_deriver_key_manager: invalid key") errInvalidPRFBasedDeriverKeyFormat = errors.New("prf_based_deriver_key_manager: invalid key format") ) type prfBasedDeriverKeyManager struct{} var _ registry.KeyManager = (*prfBasedDeriverKeyManager)(nil) func (km *prfBasedDeriverKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidPRFBasedDeriverKey } key := &prfderpb.PrfBasedDeriverKey{} if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errInvalidPRFBasedDeriverKey } if keyset.ValidateKeyVersion(key.GetVersion(), prfBasedDeriverKeyVersion) != nil { return nil, errInvalidPRFBasedDeriverKey } return newPRFBasedDeriver(key.GetPrfKey(), key.GetParams().GetDerivedKeyTemplate()) } func (km *prfBasedDeriverKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errInvalidPRFBasedDeriverKeyFormat } keyFormat := &prfderpb.PrfBasedDeriverKeyFormat{} if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, errInvalidPRFBasedDeriverKeyFormat } if keyFormat.GetParams() == nil { return nil, errors.New("prf_based_deriver_key_manager: nil PRF-Based Deriver params") } prfKey, err := registry.NewKeyData(keyFormat.GetPrfKeyTemplate()) if err != nil { return nil, errors.New("prf_based_deriver_key_manager: failed to generate key from PRF key template") } // Validate PRF key data and derived key template. if _, err := newPRFBasedDeriver(prfKey, keyFormat.GetParams().GetDerivedKeyTemplate()); err != nil { return nil, fmt.Errorf("prf_based_deriver_key_manager: %v", err) } return &prfderpb.PrfBasedDeriverKey{ Version: prfBasedDeriverKeyVersion, PrfKey: prfKey, Params: keyFormat.GetParams(), }, nil } func (km *prfBasedDeriverKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { key, err := km.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, errInvalidPRFBasedDeriverKeyFormat } return &tinkpb.KeyData{ TypeUrl: prfBasedDeriverTypeURL, Value: serializedKey, KeyMaterialType: tinkpb.KeyData_SYMMETRIC, }, nil } func (km *prfBasedDeriverKeyManager) DoesSupport(typeURL string) bool { return typeURL == prfBasedDeriverTypeURL } func (km *prfBasedDeriverKeyManager) TypeURL() string { return prfBasedDeriverTypeURL } ================================================ FILE: go/keyderivation/prf_based_deriver_key_manager_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyderivation_test import ( "fmt" "testing" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/testing/protocmp" "github.com/google/tink/go/aead" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/keyderivation" "github.com/google/tink/go/prf" "github.com/google/tink/go/subtle/random" aesgcmpb "github.com/google/tink/go/proto/aes_gcm_go_proto" prfderpb "github.com/google/tink/go/proto/prf_based_deriver_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( prfBasedDeriverKeyVersion = 0 prfBasedDeriverTypeURL = "type.googleapis.com/google.crypto.tink.PrfBasedDeriverKey" ) func TestPRFBasedDeriverKeyManagerPrimitive(t *testing.T) { km, err := registry.GetKeyManager(prfBasedDeriverTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", prfBasedDeriverTypeURL, err) } prfs := []struct { name string template *tinkpb.KeyTemplate }{ { name: "HKDF-SHA256", template: prf.HKDFSHA256PRFKeyTemplate(), }, } derivations := []struct { name string template *tinkpb.KeyTemplate }{ { name: "AES128GCM", template: aead.AES128GCMKeyTemplate(), }, { name: "AES256GCM", template: aead.AES256GCMKeyTemplate(), }, { name: "AES256GCMNoPrefix", template: aead.AES256GCMNoPrefixKeyTemplate(), }, } for _, prf := range prfs { for _, der := range derivations { for _, salt := range [][]byte{nil, []byte("salt")} { name := fmt.Sprintf("%s_%s", prf.name, der.name) if salt != nil { name += "_with_salt" } t.Run(name, func(t *testing.T) { prfKey, err := registry.NewKeyData(prf.template) if err != nil { t.Fatalf("registry.NewKeyData() err = %v, want nil", err) } key := &prfderpb.PrfBasedDeriverKey{ Version: 0, PrfKey: prfKey, Params: &prfderpb.PrfBasedDeriverParams{ DerivedKeyTemplate: der.template, }, } serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", key, err) } p, err := km.Primitive(serializedKey) if err != nil { t.Fatalf("Primitive() err = %v, want nil", err) } d, ok := p.(keyderivation.KeysetDeriver) if !ok { t.Fatal("primitive is not KeysetDeriver") } if _, err := d.DeriveKeyset(salt); err != nil { t.Fatalf("DeriveKeyset() err = %v, want nil", err) } // We cannot test the derived keyset handle because, at this point, it // is filled with placeholder values for the key ID, status, and // output prefix type fields. }) } } } } func TestPRFBasedDeriverKeyManagerPrimitiveRejectsIncorrectKeys(t *testing.T) { km, err := registry.GetKeyManager(prfBasedDeriverTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", prfBasedDeriverTypeURL, err) } prfKey, err := registry.NewKeyData(prf.HKDFSHA256PRFKeyTemplate()) if err != nil { t.Fatalf("registry.NewKeyData() err = %v, want nil", err) } missingParamsKey := &prfderpb.PrfBasedDeriverKey{ Version: prfBasedDeriverKeyVersion, PrfKey: prfKey, } serializedMissingParamsKey, err := proto.Marshal(missingParamsKey) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", serializedMissingParamsKey, err) } aesGCMKey := &aesgcmpb.AesGcmKey{Version: 0, KeyValue: random.GetRandomBytes(32)} serializedAESGCMKey, err := proto.Marshal(aesGCMKey) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", aesGCMKey, err) } for _, test := range []struct { name string serializedKey []byte }{ { name: "nil key", }, { name: "zero-length key", serializedKey: []byte{}, }, { name: "missing params", serializedKey: serializedMissingParamsKey, }, { name: "wrong key type", serializedKey: serializedAESGCMKey, }, } { t.Run(test.name, func(t *testing.T) { if _, err := km.Primitive(test.serializedKey); err == nil { t.Error("Primitive() err = nil, want non-nil") } }) } } func TestPRFBasedDeriverKeyManagerPrimitiveRejectsInvalidKeys(t *testing.T) { km, err := registry.GetKeyManager(prfBasedDeriverTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", prfBasedDeriverTypeURL, err) } validPRFKey, err := registry.NewKeyData(prf.HKDFSHA256PRFKeyTemplate()) if err != nil { t.Fatalf("registry.NewKeyData() err = %v, want nil", err) } validKey := &prfderpb.PrfBasedDeriverKey{ Version: 0, PrfKey: validPRFKey, Params: &prfderpb.PrfBasedDeriverParams{ DerivedKeyTemplate: aead.AES128GCMKeyTemplate(), }, } serializedValidKey, err := proto.Marshal(validKey) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", validKey, err) } if _, err := km.Primitive(serializedValidKey); err != nil { t.Errorf("Primitive() err = %v, want nil", err) } invalidPRFKey, err := registry.NewKeyData(aead.AES128GCMKeyTemplate()) if err != nil { t.Fatalf("registry.NewKeyData() err = %v, want nil", err) } for _, test := range []struct { name string version uint32 prfKey *tinkpb.KeyData derKeyTemplate *tinkpb.KeyTemplate }{ { name: "invalid version", version: 100, prfKey: validKey.GetPrfKey(), derKeyTemplate: validKey.GetParams().GetDerivedKeyTemplate(), }, { name: "invalid PRF key", version: validKey.GetVersion(), prfKey: invalidPRFKey, derKeyTemplate: validKey.GetParams().GetDerivedKeyTemplate(), }, { name: "invalid derived key template", version: validKey.GetVersion(), prfKey: validKey.GetPrfKey(), derKeyTemplate: aead.AES128CTRHMACSHA256KeyTemplate(), }, } { t.Run(test.name, func(t *testing.T) { key := &prfderpb.PrfBasedDeriverKey{ Version: test.version, PrfKey: test.prfKey, Params: &prfderpb.PrfBasedDeriverParams{ DerivedKeyTemplate: test.derKeyTemplate, }, } serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", key, err) } if _, err := km.Primitive(serializedKey); err == nil { t.Error("Primitive() err = nil, want non-nil") } }) } } func TestPRFBasedDeriverKeyManagerNewKey(t *testing.T) { km, err := registry.GetKeyManager(prfBasedDeriverTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", prfBasedDeriverTypeURL, err) } prfs := []struct { name string template *tinkpb.KeyTemplate }{ { name: "HKDF-SHA256", template: prf.HKDFSHA256PRFKeyTemplate(), }, } derivations := []struct { name string template *tinkpb.KeyTemplate }{ { name: "AES128GCM", template: aead.AES128GCMKeyTemplate(), }, { name: "AES256GCM", template: aead.AES256GCMKeyTemplate(), }, { name: "AES256GCMNoPrefix", template: aead.AES256GCMNoPrefixKeyTemplate(), }, } for _, prf := range prfs { for _, der := range derivations { for _, salt := range [][]byte{nil, []byte("salt")} { name := fmt.Sprintf("%s_%s", prf.name, der.name) if salt != nil { name += "_with_salt" } t.Run(name, func(t *testing.T) { keyFormat := &prfderpb.PrfBasedDeriverKeyFormat{ PrfKeyTemplate: prf.template, Params: &prfderpb.PrfBasedDeriverParams{ DerivedKeyTemplate: der.template, }, } serializedKeyFormat, err := proto.Marshal(keyFormat) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", keyFormat, err) } k, err := km.NewKey(serializedKeyFormat) if err != nil { t.Errorf("NewKey() err = %v, want nil", err) } key, ok := k.(*prfderpb.PrfBasedDeriverKey) if !ok { t.Fatal("key is not PrfBasedDeriverKey") } if key.GetVersion() != prfBasedDeriverKeyVersion { t.Errorf("GetVersion() = %d, want 0", key.GetVersion()) } prfKeyData := key.GetPrfKey() if got, want := prfKeyData.GetTypeUrl(), prf.template.GetTypeUrl(); got != want { t.Errorf("GetTypeUrl() = %q, want %q", got, want) } if got, want := prfKeyData.GetKeyMaterialType(), tinkpb.KeyData_SYMMETRIC; got != want { t.Errorf("GetKeyMaterialType() = %s, want %s", got, want) } if diff := cmp.Diff(key.GetParams().GetDerivedKeyTemplate(), der.template, protocmp.Transform()); diff != "" { t.Errorf("GetDerivedKeyTemplate() diff = %s", diff) } }) } } } } func TestPRFBasedDeriverKeyManagerNewKeyData(t *testing.T) { km, err := registry.GetKeyManager(prfBasedDeriverTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", prfBasedDeriverTypeURL, err) } prfs := []struct { name string template *tinkpb.KeyTemplate }{ { name: "HKDF-SHA256", template: prf.HKDFSHA256PRFKeyTemplate(), }, } derivations := []struct { name string template *tinkpb.KeyTemplate }{ { name: "AES128GCM", template: aead.AES128GCMKeyTemplate(), }, { name: "AES256GCM", template: aead.AES256GCMKeyTemplate(), }, { name: "AES256GCMNoPrefix", template: aead.AES256GCMNoPrefixKeyTemplate(), }, } for _, prf := range prfs { for _, der := range derivations { for _, salt := range [][]byte{nil, []byte("salt")} { name := fmt.Sprintf("%s_%s", prf.name, der.name) if salt != nil { name += "_with_salt" } t.Run(name, func(t *testing.T) { keyFormat := &prfderpb.PrfBasedDeriverKeyFormat{ PrfKeyTemplate: prf.template, Params: &prfderpb.PrfBasedDeriverParams{ DerivedKeyTemplate: der.template, }, } serializedKeyFormat, err := proto.Marshal(keyFormat) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", keyFormat, err) } keyData, err := km.NewKeyData(serializedKeyFormat) if err != nil { t.Errorf("NewKeyData() err = %v, want nil", err) } if keyData.GetTypeUrl() != prfBasedDeriverTypeURL { t.Errorf("GetTypeUrl() = %s, want %s", keyData.GetTypeUrl(), prfBasedDeriverTypeURL) } if keyData.GetKeyMaterialType() != tinkpb.KeyData_SYMMETRIC { t.Errorf("GetKeyMaterialType() = %s, want %s", keyData.GetKeyMaterialType(), tinkpb.KeyData_SYMMETRIC) } key := &prfderpb.PrfBasedDeriverKey{} if err := proto.Unmarshal(keyData.GetValue(), key); err != nil { t.Fatalf("proto.Unmarshal() err = %v, want nil", err) } if key.GetVersion() != prfBasedDeriverKeyVersion { t.Errorf("GetVersion() = %d, want %d", key.GetVersion(), prfBasedDeriverKeyVersion) } prfKeyData := key.GetPrfKey() if got, want := prfKeyData.GetTypeUrl(), prf.template.GetTypeUrl(); got != want { t.Errorf("GetTypeUrl() = %q, want %q", got, want) } if got, want := prfKeyData.GetKeyMaterialType(), tinkpb.KeyData_SYMMETRIC; got != want { t.Errorf("GetKeyMaterialType() = %s, want %s", got, want) } if diff := cmp.Diff(key.GetParams().GetDerivedKeyTemplate(), der.template, protocmp.Transform()); diff != "" { t.Errorf("GetDerivedKeyTemplate() diff = %s", diff) } }) } } } } func TestPRFBasedDeriverKeyManagerNewKeyAndNewKeyDataRejectsIncorrectKeyFormats(t *testing.T) { km, err := registry.GetKeyManager(prfBasedDeriverTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", prfBasedDeriverTypeURL, err) } missingParamsKeyFormat := &prfderpb.PrfBasedDeriverKeyFormat{ PrfKeyTemplate: prf.HKDFSHA256PRFKeyTemplate(), } serializedMissingParamsKeyFormat, err := proto.Marshal(missingParamsKeyFormat) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", missingParamsKeyFormat, err) } aesGCMKeyFormat := &aesgcmpb.AesGcmKeyFormat{KeySize: 32, Version: 0} serializedAESGCMKeyFormat, err := proto.Marshal(aesGCMKeyFormat) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", aesGCMKeyFormat, err) } for _, test := range []struct { name string serializedKeyFormat []byte }{ { name: "nil key", }, { name: "zero-length key", serializedKeyFormat: []byte{}, }, { name: "missing params", serializedKeyFormat: serializedMissingParamsKeyFormat, }, { name: "wrong key type", serializedKeyFormat: serializedAESGCMKeyFormat, }, } { t.Run(test.name, func(t *testing.T) { if _, err := km.NewKey(test.serializedKeyFormat); err == nil { t.Error("NewKey() err = nil, want non-nil") } if _, err := km.NewKeyData(test.serializedKeyFormat); err == nil { t.Error("NewKeyData() err = nil, want non-nil") } }) } } func TestPRFBasedDeriverKeyManagerNewKeyAndNewKeyDataRejectsInvalidKeyFormats(t *testing.T) { km, err := registry.GetKeyManager(prfBasedDeriverTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", prfBasedDeriverTypeURL, err) } validKeyFormat := &prfderpb.PrfBasedDeriverKeyFormat{ PrfKeyTemplate: prf.HKDFSHA256PRFKeyTemplate(), Params: &prfderpb.PrfBasedDeriverParams{ DerivedKeyTemplate: aead.AES128GCMKeyTemplate(), }, } serializedValidKeyFormat, err := proto.Marshal(validKeyFormat) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", validKeyFormat, err) } if _, err := km.NewKey(serializedValidKeyFormat); err != nil { t.Errorf("Primitive() err = %v, want nil", err) } for _, test := range []struct { name string prfKeyTemplate *tinkpb.KeyTemplate derKeyTemplate *tinkpb.KeyTemplate }{ { "invalid PRF key template", aead.AES128GCMKeyTemplate(), validKeyFormat.GetParams().GetDerivedKeyTemplate(), }, { "invalid derived key template", validKeyFormat.GetPrfKeyTemplate(), aead.AES128CTRHMACSHA256KeyTemplate(), }, } { t.Run(test.name, func(t *testing.T) { keyFormat := &prfderpb.PrfBasedDeriverKeyFormat{ PrfKeyTemplate: test.prfKeyTemplate, Params: &prfderpb.PrfBasedDeriverParams{ DerivedKeyTemplate: test.derKeyTemplate, }, } serializedKeyFormat, err := proto.Marshal(keyFormat) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", keyFormat, err) } if _, err := km.NewKey(serializedKeyFormat); err == nil { t.Error("NewKey() err = nil, want non-nil") } if _, err := km.NewKeyData(serializedKeyFormat); err == nil { t.Error("NewKeyData() err = nil, want non-nil") } }) } } func TestPRFBasedDeriverKeyManagerDoesSupport(t *testing.T) { km, err := registry.GetKeyManager(prfBasedDeriverTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", prfBasedDeriverTypeURL, err) } if !km.DoesSupport(prfBasedDeriverTypeURL) { t.Errorf("DoesSupport(%q) = false, want true", prfBasedDeriverTypeURL) } if unsupported := "unsupported.key.type"; km.DoesSupport(unsupported) { t.Errorf("DoesSupport(%q) = true, want false", unsupported) } } func TestPRFBasedDeriverKeyManagerTypeURL(t *testing.T) { km, err := registry.GetKeyManager(prfBasedDeriverTypeURL) if err != nil { t.Fatalf("GetKeyManager(%q) err = %v, want nil", prfBasedDeriverTypeURL, err) } if km.TypeURL() != prfBasedDeriverTypeURL { t.Errorf("TypeURL() = %q, want %q", km.TypeURL(), prfBasedDeriverTypeURL) } } ================================================ FILE: go/keyderivation/prf_based_deriver_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyderivation import ( "bytes" "encoding/hex" "fmt" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/aead" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/daead" "github.com/google/tink/go/insecurecleartextkeyset" "github.com/google/tink/go/mac" "github.com/google/tink/go/prf" "github.com/google/tink/go/signature" "github.com/google/tink/go/streamingaead" aesgcmpb "github.com/google/tink/go/proto/aes_gcm_go_proto" commonpb "github.com/google/tink/go/proto/common_go_proto" hkdfpb "github.com/google/tink/go/proto/hkdf_prf_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestPRFBasedDeriver(t *testing.T) { prfs := []struct { name string template *tinkpb.KeyTemplate }{ { name: "HKDF_SHA256", template: prf.HKDFSHA256PRFKeyTemplate(), }, } // Derivation names match KEY_TEMPLATE_NAMES in // https://github.com/google/tink/blob/cd96c47ced3f72199832573cdccf18719dc7c73b/testing/cross_language/util/utilities.py. derivations := []struct { name string template *tinkpb.KeyTemplate }{ { name: "AES128_GCM", template: aead.AES128GCMKeyTemplate(), }, { name: "AES256_GCM", template: aead.AES256GCMKeyTemplate(), }, { name: "AES256_GCM_RAW", template: aead.AES256GCMNoPrefixKeyTemplate(), }, { name: "XCHACHA20_POLY1305", template: aead.XChaCha20Poly1305KeyTemplate(), }, { name: "AES256_SIV", template: daead.AESSIVKeyTemplate(), }, { name: "HMAC_SHA256_128BITTAG", template: mac.HMACSHA256Tag128KeyTemplate(), }, { name: "HMAC_SHA256_256BITTAG", template: mac.HMACSHA256Tag256KeyTemplate(), }, { name: "HMAC_SHA512_256BITTAG", template: mac.HMACSHA512Tag256KeyTemplate(), }, { name: "HMAC_SHA512_512BITTAG", template: mac.HMACSHA512Tag512KeyTemplate(), }, { name: "HKDF_SHA256", template: prf.HKDFSHA256PRFKeyTemplate(), }, { name: "HMAC_SHA256_PRF", template: prf.HMACSHA256PRFKeyTemplate(), }, { name: "HMAC_SHA512_PRF", template: prf.HMACSHA512PRFKeyTemplate(), }, { name: "ED25519", template: signature.ED25519KeyTemplate(), }, { name: "AES128_GCM_HKDF_4KB", template: streamingaead.AES128GCMHKDF4KBKeyTemplate(), }, { name: "AES128_GCM_HKDF_1MB", template: streamingaead.AES128GCMHKDF1MBKeyTemplate(), }, { name: "AES256_GCM_HKDF_4KB", template: streamingaead.AES256GCMHKDF4KBKeyTemplate(), }, { name: "AES256_GCM_HKDF_1MB", template: streamingaead.AES256GCMHKDF1MBKeyTemplate(), }, } salts := [][]byte{nil, []byte("salt")} for _, prf := range prfs { for _, der := range derivations { for _, salt := range salts { name := fmt.Sprintf("%s_%s", prf.name, der.name) if salt != nil { name += "_with_salt" } t.Run(name, func(t *testing.T) { prfKeyData, err := registry.NewKeyData(prf.template) if err != nil { t.Fatalf("registry.NewKeyData() err = %v, want nil", err) } d, err := newPRFBasedDeriver(prfKeyData, der.template) if err != nil { t.Fatalf("newPRFBasedDeriver() err = %v, want nil", err) } if _, err := d.DeriveKeyset(salt); err != nil { t.Errorf("DeriveKeyset() err = %v, want nil", err) } // We cannot test the derived keyset handle because, at this point, it // is filled with placeholder values for the key ID, status, and // output prefix type fields. }) } } } } func TestPRFBasedDeriverWithHKDFRFCVectorForAESGCM(t *testing.T) { // This is the only HKDF vector that uses an accepted hash function and has // key size >= 32-bytes. // https://www.rfc-editor.org/rfc/rfc5869#appendix-A.2 vec := struct { hash commonpb.HashType key string salt string info string outLen int okm string }{ hash: commonpb.HashType_SHA256, key: "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f", salt: "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf", info: "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", outLen: 82, okm: "b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87", } prfKeyValue, err := hex.DecodeString(vec.key) if err != nil { t.Fatalf("hex.DecodeString() err = %v, want nil", err) } prfSalt, err := hex.DecodeString(vec.salt) if err != nil { t.Fatalf("hex.DecodeString() err = %v, want nil", err) } derivationSalt, err := hex.DecodeString(vec.info) if err != nil { t.Fatalf("hex.DecodeString() err = %v, want nil", err) } wantKeyValue, err := hex.DecodeString(vec.okm) if err != nil { t.Fatalf("hex.DecodeString() err = %v, want nil", err) } prfKey := &hkdfpb.HkdfPrfKey{ Version: 0, Params: &hkdfpb.HkdfPrfParams{ Hash: vec.hash, Salt: prfSalt, }, KeyValue: prfKeyValue, } serializedPRFKey, err := proto.Marshal(prfKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } prfKeyData := &tinkpb.KeyData{ TypeUrl: prf.HKDFSHA256PRFKeyTemplate().GetTypeUrl(), Value: serializedPRFKey, KeyMaterialType: tinkpb.KeyData_SYMMETRIC, } for _, test := range []struct { name string derivedKeyTemplate *tinkpb.KeyTemplate }{ { name: "AES128_GCM", derivedKeyTemplate: aead.AES128GCMKeyTemplate(), }, { name: "AES256_GCM", derivedKeyTemplate: aead.AES256GCMKeyTemplate(), }, { name: "AES256_GCM_RAW", derivedKeyTemplate: aead.AES256GCMNoPrefixKeyTemplate(), }, } { t.Run(test.name, func(t *testing.T) { // Derive keyset. d, err := newPRFBasedDeriver(prfKeyData, test.derivedKeyTemplate) if err != nil { t.Fatalf("newPRFBasedDeriver() err = %v, want nil", err) } derivedHandle, err := d.DeriveKeyset(derivationSalt) if err != nil { t.Fatalf("DeriveKeyset() err = %v, want nil", err) } derivedKeyset := insecurecleartextkeyset.KeysetMaterial(derivedHandle) // Verify keyset. if len(derivedKeyset.GetKey()) != 1 { t.Fatalf("len(keyset) = %d, want 1", len(derivedKeyset.GetKey())) } key := derivedKeyset.GetKey()[0] if derivedKeyset.GetPrimaryKeyId() != key.GetKeyId() { t.Fatal("keyset has no primary key") } // Verify key attributes set by prfBasedDeriver. if got, want := key.GetStatus(), tinkpb.KeyStatusType_UNKNOWN_STATUS; got != want { t.Errorf("derived key status = %s, want %s", got, want) } if got, want := key.GetOutputPrefixType(), tinkpb.OutputPrefixType_UNKNOWN_PREFIX; got != want { t.Errorf("derived key output prefix type = %s, want %s", got, want) } // Verify key value. derivedKeyFormat := &aesgcmpb.AesGcmKeyFormat{} if err := proto.Unmarshal(test.derivedKeyTemplate.GetValue(), derivedKeyFormat); err != nil { t.Fatalf("proto.Unmarshal() err = %v, want nil", err) } wantKeySize := int(derivedKeyFormat.GetKeySize()) aesGCMKey := &aesgcmpb.AesGcmKey{} if err := proto.Unmarshal(key.GetKeyData().GetValue(), aesGCMKey); err != nil { t.Fatalf("proto.Unmarshal() err = %v, want nil", err) } gotKeyValue := aesGCMKey.GetKeyValue() if len(gotKeyValue) != wantKeySize { t.Errorf("derived key value length = %d, want %d", len(gotKeyValue), wantKeySize) } if !bytes.Equal(gotKeyValue, wantKeyValue[:wantKeySize]) { t.Errorf("derived key value = %q, want %q", gotKeyValue, wantKeyValue[:wantKeySize]) } }) } } func TestNewPRFBasedDeriverRejectsInvalidInputs(t *testing.T) { validPRFKeyData, err := registry.NewKeyData(prf.HKDFSHA256PRFKeyTemplate()) if err != nil { t.Fatalf("registry.NewKeyData() err = %v, want nil", err) } validDerivedKeyTemplate := aead.AES128GCMKeyTemplate() if _, err := newPRFBasedDeriver(validPRFKeyData, validDerivedKeyTemplate); err != nil { t.Fatalf("newPRFBasedDeriver() err = %v, want nil", err) } invalidPRFKeyData, err := registry.NewKeyData(aead.AES128GCMKeyTemplate()) if err != nil { t.Fatalf("registry.NewKeyData() err = %v, want nil", err) } // The derivation of KeysetDeriver keyset handles is not supported, i.e. a // KeysetDeriver key template cannot be used as the derivedKeyTemplate // argument in newPRFBasedDeriver(). invalidDerivedKeyTemplate, err := CreatePRFBasedKeyTemplate(prf.HKDFSHA256PRFKeyTemplate(), aead.AES128GCMKeyTemplate()) if err != nil { t.Fatalf("CreatePRFBasedKeyTemplate() err = %v, want nil", err) } for _, test := range []struct { name string prfKeyData *tinkpb.KeyData derivedKeyTemplate *tinkpb.KeyTemplate }{ { name: "nil inputs", }, { name: "nil PRF key data", derivedKeyTemplate: validDerivedKeyTemplate, }, { name: "nil derived template", prfKeyData: validPRFKeyData, }, { name: "invalid PRF key data", prfKeyData: invalidPRFKeyData, derivedKeyTemplate: validDerivedKeyTemplate, }, { name: "invalid derived template", prfKeyData: validPRFKeyData, derivedKeyTemplate: invalidDerivedKeyTemplate, }, } { t.Run(test.name, func(t *testing.T) { if _, err := newPRFBasedDeriver(test.prfKeyData, test.derivedKeyTemplate); err == nil { t.Errorf("newPRFBasedDeriver() err = nil, want non-nil") } }) } } ================================================ FILE: go/keyset/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) go_library( name = "keyset", srcs = [ "binary_io.go", "handle.go", "json_io.go", "keyset.go", "manager.go", "mem_io.go", "option.go", "reader.go", "validation.go", "writer.go", ], importpath = "github.com/google/tink/go/keyset", visibility = [ "//visibility:public", ], deps = [ "//core/primitiveset", "//core/registry", "//internal", "//internal/internalapi", "//internal/registryconfig", "//proto/tink_go_proto", "//subtle/random", "//tink", "@org_golang_google_protobuf//encoding/protojson", "@org_golang_google_protobuf//encoding/prototext", "@org_golang_google_protobuf//proto", ], ) go_test( name = "keyset_test", srcs = [ "binary_io_test.go", "handle_test.go", "json_io_test.go", "keyset_test.go", "manager_test.go", "mem_io_test.go", "validation_test.go", ], deps = [ ":keyset", "//aead", "//core/registry", "//insecurecleartextkeyset", "//internal/internalapi", "//mac", "//proto/common_go_proto", "//proto/tink_go_proto", "//signature", "//subtle/random", "//testing/fakekms", "//testkeyset", "//testutil", "//tink", "@org_golang_google_protobuf//proto", ], ) alias( name = "go_default_library", actual = ":keyset", visibility = ["//visibility:public"], ) ================================================ FILE: go/keyset/binary_io.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyset import ( "io" "google.golang.org/protobuf/proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // BinaryReader deserializes a keyset from binary proto format. type BinaryReader struct { r io.Reader } // NewBinaryReader returns new BinaryReader that will read from r. func NewBinaryReader(r io.Reader) *BinaryReader { return &BinaryReader{r: r} } // Read parses a (cleartext) keyset from the underlying io.Reader. func (bkr *BinaryReader) Read() (*tinkpb.Keyset, error) { keyset := &tinkpb.Keyset{} if err := read(bkr.r, keyset); err != nil { return nil, err } return keyset, nil } // ReadEncrypted parses an EncryptedKeyset from the underlying io.Reader. func (bkr *BinaryReader) ReadEncrypted() (*tinkpb.EncryptedKeyset, error) { keyset := &tinkpb.EncryptedKeyset{} if err := read(bkr.r, keyset); err != nil { return nil, err } return keyset, nil } func read(r io.Reader, msg proto.Message) error { data, err := io.ReadAll(r) if err != nil { return err } return proto.Unmarshal(data, msg) } // BinaryWriter serializes a keyset into binary proto format. type BinaryWriter struct { w io.Writer } // NewBinaryWriter returns a new BinaryWriter that will write to w. func NewBinaryWriter(w io.Writer) *BinaryWriter { return &BinaryWriter{w: w} } // Write writes the keyset to the underlying io.Writer. func (bkw *BinaryWriter) Write(keyset *tinkpb.Keyset) error { return write(bkw.w, keyset) } // WriteEncrypted writes the encrypted keyset to the underlying io.Writer. func (bkw *BinaryWriter) WriteEncrypted(keyset *tinkpb.EncryptedKeyset) error { encryptedKeysetWithoutInfo := &tinkpb.EncryptedKeyset{ EncryptedKeyset: keyset.GetEncryptedKeyset(), } return write(bkw.w, encryptedKeysetWithoutInfo) } func write(w io.Writer, msg proto.Message) error { data, err := proto.Marshal(msg) if err != nil { return err } _, err = w.Write(data) return err } ================================================ FILE: go/keyset/binary_io_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyset_test import ( "bytes" "strings" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/aead" "github.com/google/tink/go/insecurecleartextkeyset" "github.com/google/tink/go/keyset" "github.com/google/tink/go/testkeyset" "github.com/google/tink/go/testutil" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestBinaryIOUnencrypted(t *testing.T) { buf := new(bytes.Buffer) w := keyset.NewBinaryWriter(buf) r := keyset.NewBinaryReader(buf) manager := testutil.NewHMACKeysetManager() h, err := manager.Handle() if h == nil || err != nil { t.Fatalf("cannot get keyset handle: %v", err) } ks1 := testkeyset.KeysetMaterial(h) if err := w.Write(ks1); err != nil { t.Fatalf("cannot write keyset: %v", err) } ks2, err := r.Read() if err != nil { t.Fatalf("cannot read keyset: %v", err) } if !proto.Equal(ks1, ks2) { t.Errorf("written keyset (%s) doesn't match read keyset (%s)", ks1, ks2) } } func TestBinaryIOEncrypted(t *testing.T) { buf := new(bytes.Buffer) w := keyset.NewBinaryWriter(buf) r := keyset.NewBinaryReader(buf) kse1 := &tinkpb.EncryptedKeyset{EncryptedKeyset: []byte(strings.Repeat("A", 32))} if err := w.WriteEncrypted(kse1); err != nil { t.Fatalf("cannot write encrypted keyset: %v", err) } kse2, err := r.ReadEncrypted() if err != nil { t.Fatalf("cannot read encrypted keyset: %v", err) } if !proto.Equal(kse1, kse2) { t.Errorf("written encrypted keyset (%s) doesn't match read encrypted keyset (%s)", kse1, kse2) } } func TestBinaryWriteEncryptedOverhead(t *testing.T) { keysetEncryptionHandle, err := keyset.NewHandle(aead.AES128GCMKeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle(aead.AES128GCMKeyTemplate()) err = %v, want nil", err) } keysetEncryptionAead, err := aead.New(keysetEncryptionHandle) if err != nil { t.Fatalf("aead.New(keysetEncryptionHandle) err = %v, want nil", err) } handle, err := keyset.NewHandle(aead.AES128GCMKeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle(aead.AES128GCMKeyTemplate()) err = %v, want nil", err) } buf := &bytes.Buffer{} err = insecurecleartextkeyset.Write(handle, keyset.NewBinaryWriter(buf)) if err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } serialized := buf.Bytes() rawEncryptedKeyset, err := keysetEncryptionAead.Encrypt(serialized, nil) if err != nil { t.Fatalf("keysetEncryptionAead.Encrypt() err = %v, want nil", err) } encBuf := &bytes.Buffer{} err = handle.Write(keyset.NewBinaryWriter(encBuf), keysetEncryptionAead) if err != nil { t.Fatalf("handle.Write(keyset.NewBinaryWriter(buff), keysetEncryptionAead) err = %v, want nil", err) } encryptedKeyset := encBuf.Bytes() // encryptedKeyset is a serialized protocol buffer that contains only // rawEncryptedKeyset in a field. So // it should only be slightly larger than rawEncryptedKeyset. if len(encryptedKeyset) >= len(rawEncryptedKeyset)+6 { t.Errorf("len(encryptedKeyset) = %d, want < %d", len(encryptedKeyset), len(rawEncryptedKeyset)+6) } } ================================================ FILE: go/keyset/handle.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyset import ( "errors" "fmt" "google.golang.org/protobuf/encoding/prototext" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/primitiveset" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/internalapi" "github.com/google/tink/go/internal/registryconfig" "github.com/google/tink/go/tink" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) var errInvalidKeyset = fmt.Errorf("keyset.Handle: invalid keyset") // Handle provides access to a Keyset protobuf, to limit the exposure of actual protocol // buffers that hold sensitive key material. type Handle struct { ks *tinkpb.Keyset annotations map[string]string } func newWithOptions(ks *tinkpb.Keyset, opts ...Option) (*Handle, error) { h := &Handle{ks: ks} if err := applyOptions(h, opts...); err != nil { return nil, err } return h, nil } // NewHandle creates a keyset handle that contains a single fresh key generated according // to the given KeyTemplate. func NewHandle(kt *tinkpb.KeyTemplate) (*Handle, error) { manager := NewManager() keyID, err := manager.Add(kt) if err != nil { return nil, fmt.Errorf("keyset.Handle: cannot generate new keyset: %s", err) } err = manager.SetPrimary(keyID) if err != nil { return nil, fmt.Errorf("keyset.Handle: cannot set primary: %s", err) } handle, err := manager.Handle() if err != nil { return nil, fmt.Errorf("keyset.Handle: cannot get keyset handle: %s", err) } return handle, nil } // NewHandleWithNoSecrets creates a new instance of KeysetHandle using the given keyset which does // not contain any secret key material. func NewHandleWithNoSecrets(ks *tinkpb.Keyset) (*Handle, error) { if ks == nil { return nil, errors.New("keyset.Handle: nil keyset") } h := &Handle{ks: ks} if h.hasSecrets() { // If you need to do this, you have to use func insecurecleartextkeyset.Read() instead. return nil, errors.New("importing unencrypted secret key material is forbidden") } return h, nil } // Read tries to create a Handle from an encrypted keyset obtained via reader. func Read(reader Reader, masterKey tink.AEAD) (*Handle, error) { return ReadWithAssociatedData(reader, masterKey, []byte{}) } // ReadWithAssociatedData tries to create a Handle from an encrypted keyset obtained via reader using the provided associated data. func ReadWithAssociatedData(reader Reader, masterKey tink.AEAD, associatedData []byte) (*Handle, error) { encryptedKeyset, err := reader.ReadEncrypted() if err != nil { return nil, err } ks, err := decrypt(encryptedKeyset, masterKey, associatedData) if err != nil { return nil, err } return &Handle{ks: ks}, nil } // ReadWithNoSecrets tries to create a keyset.Handle from a keyset obtained via reader. func ReadWithNoSecrets(reader Reader) (*Handle, error) { ks, err := reader.Read() if err != nil { return nil, err } return NewHandleWithNoSecrets(ks) } // Public returns a Handle of the public keys if the managed keyset contains private keys. func (h *Handle) Public() (*Handle, error) { privKeys := h.ks.Key pubKeys := make([]*tinkpb.Keyset_Key, len(privKeys)) for i := 0; i < len(privKeys); i++ { if privKeys[i] == nil || privKeys[i].KeyData == nil { return nil, errInvalidKeyset } privKeyData := privKeys[i].KeyData pubKeyData, err := publicKeyData(privKeyData) if err != nil { return nil, fmt.Errorf("keyset.Handle: %s", err) } pubKeys[i] = &tinkpb.Keyset_Key{ KeyData: pubKeyData, Status: privKeys[i].Status, KeyId: privKeys[i].KeyId, OutputPrefixType: privKeys[i].OutputPrefixType, } } ks := &tinkpb.Keyset{ PrimaryKeyId: h.ks.PrimaryKeyId, Key: pubKeys, } return &Handle{ks: ks}, nil } // String returns a string representation of the managed keyset. // The result does not contain any sensitive key material. func (h *Handle) String() string { c, err := prototext.MarshalOptions{}.Marshal(getKeysetInfo(h.ks)) if err != nil { return "" } return string(c) } // KeysetInfo returns KeysetInfo representation of the managed keyset. // The result does not contain any sensitive key material. func (h *Handle) KeysetInfo() *tinkpb.KeysetInfo { return getKeysetInfo(h.ks) } // Write encrypts and writes the enclosing keyset. func (h *Handle) Write(writer Writer, masterKey tink.AEAD) error { return h.WriteWithAssociatedData(writer, masterKey, []byte{}) } // WriteWithAssociatedData encrypts and writes the enclosing keyset using the provided associated data. func (h *Handle) WriteWithAssociatedData(writer Writer, masterKey tink.AEAD, associatedData []byte) error { encrypted, err := encrypt(h.ks, masterKey, associatedData) if err != nil { return err } return writer.WriteEncrypted(encrypted) } // WriteWithNoSecrets exports the keyset in h to the given Writer w returning an error if the keyset // contains secret key material. func (h *Handle) WriteWithNoSecrets(w Writer) error { if h.hasSecrets() { return errors.New("exporting unencrypted secret key material is forbidden") } return w.Write(h.ks) } // Config defines methods in the config.Config concrete type that are used by keyset.Handle. // The config.Config concrete type is not used directly due to circular dependencies. type Config interface { PrimitiveFromKeyData(keyData *tinkpb.KeyData, _ internalapi.Token) (any, error) } type primitiveOptions struct { config Config } // PrimitivesOption is used to configure Primitives(...). type PrimitivesOption func(*primitiveOptions) error // WithConfig sets the configuration used to create primitives via Primitives(). // If this option is omitted, default to using the global registry. func WithConfig(c Config) PrimitivesOption { return func(args *primitiveOptions) error { if args.config != nil { return fmt.Errorf("configuration has already been set") } args.config = c return nil } } // Primitives creates a set of primitives corresponding to the keys with // status=ENABLED in the keyset of the given keyset handle. It uses the // key managers that are present in the global Registry or in the Config, // should it be provided. It assumes that all the needed key managers are // present. Keys with status!=ENABLED are skipped. // // An example usage where a custom config is provided: // // ps, err := h.Primitives(WithConfig(config.V0())) // // The returned set is usually later "wrapped" into a class that implements // the corresponding Primitive-interface. func (h *Handle) Primitives(opts ...PrimitivesOption) (*primitiveset.PrimitiveSet, error) { p, err := h.primitives(nil, opts...) if err != nil { return nil, fmt.Errorf("handle.Primitives: %v", err) } return p, nil } // PrimitivesWithKeyManager creates a set of primitives corresponding to // the keys with status=ENABLED in the keyset of the given keysetHandle, using // the given key manager (instead of registered key managers) for keys supported // by it. Keys not supported by the key manager are handled by matching registered // key managers (if present), and keys with status!=ENABLED are skipped. // // This enables custom treatment of keys, for example providing extra context // (e.g. credentials for accessing keys managed by a KMS), or gathering custom // monitoring/profiling information. // // The returned set is usually later "wrapped" into a class that implements // the corresponding Primitive-interface. func (h *Handle) PrimitivesWithKeyManager(km registry.KeyManager) (*primitiveset.PrimitiveSet, error) { p, err := h.primitives(km) if err != nil { return nil, fmt.Errorf("handle.PrimitivesWithKeyManager: %v", err) } return p, nil } func (h *Handle) primitives(km registry.KeyManager, opts ...PrimitivesOption) (*primitiveset.PrimitiveSet, error) { args := new(primitiveOptions) for _, opt := range opts { if err := opt(args); err != nil { return nil, fmt.Errorf("failed to process primitiveOptions: %v", err) } } config := args.config if config == nil { config = &registryconfig.RegistryConfig{} } if err := Validate(h.ks); err != nil { return nil, fmt.Errorf("invalid keyset: %v", err) } primitiveSet := primitiveset.New() primitiveSet.Annotations = h.annotations for _, key := range h.ks.Key { if key.Status != tinkpb.KeyStatusType_ENABLED { continue } var primitive any var err error if km != nil && km.DoesSupport(key.KeyData.TypeUrl) { primitive, err = km.Primitive(key.KeyData.Value) } else { primitive, err = config.PrimitiveFromKeyData(key.KeyData, internalapi.Token{}) } if err != nil { return nil, fmt.Errorf("cannot get primitive from key: %v", err) } entry, err := primitiveSet.Add(primitive, key) if err != nil { return nil, fmt.Errorf("cannot add primitive: %v", err) } if key.KeyId == h.ks.PrimaryKeyId { primitiveSet.Primary = entry } } return primitiveSet, nil } // hasSecrets returns true if the keyset handle contains key material considered secret. This // includes symmetric keys, private keys of asymmetric crypto systems, and keys of an unknown type. func (h *Handle) hasSecrets() bool { for _, k := range h.ks.Key { if k == nil || k.KeyData == nil { continue } if k.KeyData.KeyMaterialType == tinkpb.KeyData_UNKNOWN_KEYMATERIAL { return true } if k.KeyData.KeyMaterialType == tinkpb.KeyData_ASYMMETRIC_PRIVATE { return true } if k.KeyData.KeyMaterialType == tinkpb.KeyData_SYMMETRIC { return true } } return false } func publicKeyData(privKeyData *tinkpb.KeyData) (*tinkpb.KeyData, error) { if privKeyData.KeyMaterialType != tinkpb.KeyData_ASYMMETRIC_PRIVATE { return nil, fmt.Errorf("keyset.Handle: keyset contains a non-private key") } km, err := registry.GetKeyManager(privKeyData.TypeUrl) if err != nil { return nil, err } pkm, ok := km.(registry.PrivateKeyManager) if !ok { return nil, fmt.Errorf("keyset.Handle: %s does not belong to a PrivateKeyManager", privKeyData.TypeUrl) } return pkm.PublicKeyData(privKeyData.Value) } func decrypt(encryptedKeyset *tinkpb.EncryptedKeyset, masterKey tink.AEAD, associatedData []byte) (*tinkpb.Keyset, error) { if encryptedKeyset == nil || masterKey == nil { return nil, fmt.Errorf("keyset.Handle: invalid encrypted keyset") } decrypted, err := masterKey.Decrypt(encryptedKeyset.EncryptedKeyset, associatedData) if err != nil { return nil, fmt.Errorf("keyset.Handle: decryption failed: %s", err) } keyset := new(tinkpb.Keyset) if err := proto.Unmarshal(decrypted, keyset); err != nil { return nil, errInvalidKeyset } return keyset, nil } func encrypt(keyset *tinkpb.Keyset, masterKey tink.AEAD, associatedData []byte) (*tinkpb.EncryptedKeyset, error) { serializedKeyset, err := proto.Marshal(keyset) if err != nil { return nil, errInvalidKeyset } encrypted, err := masterKey.Encrypt(serializedKeyset, associatedData) if err != nil { return nil, fmt.Errorf("keyset.Handle: encrypted failed: %s", err) } // get keyset info encryptedKeyset := &tinkpb.EncryptedKeyset{ EncryptedKeyset: encrypted, KeysetInfo: getKeysetInfo(keyset), } return encryptedKeyset, nil } // getKeysetInfo returns a KeysetInfo from a Keyset protobuf. func getKeysetInfo(keyset *tinkpb.Keyset) *tinkpb.KeysetInfo { if keyset == nil { panic("keyset.Handle: keyset must be non nil") } nKey := len(keyset.Key) keyInfos := make([]*tinkpb.KeysetInfo_KeyInfo, nKey) for i, key := range keyset.Key { keyInfos[i] = getKeyInfo(key) } return &tinkpb.KeysetInfo{ PrimaryKeyId: keyset.PrimaryKeyId, KeyInfo: keyInfos, } } // getKeyInfo returns a KeyInfo from a Key protobuf. func getKeyInfo(key *tinkpb.Keyset_Key) *tinkpb.KeysetInfo_KeyInfo { return &tinkpb.KeysetInfo_KeyInfo{ TypeUrl: key.KeyData.TypeUrl, Status: key.Status, KeyId: key.KeyId, OutputPrefixType: key.OutputPrefixType, } } ================================================ FILE: go/keyset/handle_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyset_test import ( "bytes" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/aead" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/internalapi" "github.com/google/tink/go/keyset" "github.com/google/tink/go/mac" "github.com/google/tink/go/signature" "github.com/google/tink/go/testkeyset" "github.com/google/tink/go/testutil" "github.com/google/tink/go/tink" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestNewHandle(t *testing.T) { template := mac.HMACSHA256Tag128KeyTemplate() handle, err := keyset.NewHandle(template) if err != nil { t.Errorf("keyset.NewHandle(template) = %v, want nil", err) } ks := testkeyset.KeysetMaterial(handle) if len(ks.Key) != 1 { t.Errorf("len(ks.Key) = %d, want 1", len(ks.Key)) } key := ks.Key[0] if ks.PrimaryKeyId != key.KeyId { t.Errorf("ks.PrimaryKeyId = %d, want %d", ks.PrimaryKeyId, key.KeyId) } if key.KeyData.TypeUrl != template.TypeUrl { t.Errorf("key.KeyData.TypeUrl = %v, want %v", key.KeyData.TypeUrl, template.TypeUrl) } if _, err = mac.New(handle); err != nil { t.Errorf("mac.New(handle) err = %v, want nil", err) } } func TestNewHandleWithInvalidTypeURLFails(t *testing.T) { // template with unknown TypeURL invalidTemplate := mac.HMACSHA256Tag128KeyTemplate() invalidTemplate.TypeUrl = "some unknown TypeURL" if _, err := keyset.NewHandle(invalidTemplate); err == nil { t.Errorf("keyset.NewHandle(invalidTemplate) err = nil, want error") } } func TestNewHandleWithNilTemplateFails(t *testing.T) { if _, err := keyset.NewHandle(nil); err == nil { t.Error("keyset.NewHandle(nil) err = nil, want error") } } func TestWriteAndReadInBinary(t *testing.T) { keysetEncryptionHandle, err := keyset.NewHandle(aead.AES128GCMKeyTemplate()) if err != nil { t.Errorf("keyset.NewHandle(aead.AES128GCMKeyTemplate()) err = %v, want nil", err) } keysetEncryptionAead, err := aead.New(keysetEncryptionHandle) if err != nil { t.Errorf("aead.New(keysetEncryptionHandle) err = %v, want nil", err) } handle, err := keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) err = %v, want nil", err) } buff := &bytes.Buffer{} err = handle.Write(keyset.NewBinaryWriter(buff), keysetEncryptionAead) if err != nil { t.Fatalf("handle.Write(keyset.NewBinaryWriter(buff), keysetEncryptionAead) err = %v, want nil", err) } encrypted := buff.Bytes() gotHandle, err := keyset.Read(keyset.NewBinaryReader(bytes.NewBuffer(encrypted)), keysetEncryptionAead) if err != nil { t.Fatalf("keyset.Read() err = %v, want nil", err) } if !proto.Equal(testkeyset.KeysetMaterial(gotHandle), testkeyset.KeysetMaterial(handle)) { t.Fatalf("keyset.Read() = %v, want %v", gotHandle, handle) } } func TestWriteAndReadInJSON(t *testing.T) { keysetEncryptionHandle, err := keyset.NewHandle(aead.AES128GCMKeyTemplate()) if err != nil { t.Errorf("keyset.NewHandle(aead.AES128GCMKeyTemplate()) err = %v, want nil", err) } keysetEncryptionAead, err := aead.New(keysetEncryptionHandle) if err != nil { t.Errorf("aead.New(keysetEncryptionHandle) err = %v, want nil", err) } handle, err := keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) err = %v, want nil", err) } buff := &bytes.Buffer{} err = handle.Write(keyset.NewJSONWriter(buff), keysetEncryptionAead) if err != nil { t.Fatalf("h.Write(keyset.NewJSONWriter(buff), keysetEncryptionAead) err = %v, want nil", err) } encrypted := buff.Bytes() gotHandle, err := keyset.Read(keyset.NewJSONReader(bytes.NewBuffer(encrypted)), keysetEncryptionAead) if err != nil { t.Fatalf("keyset.Read() err = %v, want nil", err) } if !proto.Equal(testkeyset.KeysetMaterial(gotHandle), testkeyset.KeysetMaterial(handle)) { t.Fatalf("keyset.Read() = %v, want %v", gotHandle, handle) } } func TestWriteAndReadWithAssociatedData(t *testing.T) { keysetEncryptionHandle, err := keyset.NewHandle(aead.AES128GCMKeyTemplate()) if err != nil { t.Errorf("keyset.NewHandle(aead.AES128GCMKeyTemplate()) err = %v, want nil", err) } keysetEncryptionAead, err := aead.New(keysetEncryptionHandle) if err != nil { t.Errorf("aead.New(keysetEncryptionHandle) err = %v, want nil", err) } handle, err := keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) err = %v, want nil", err) } associatedData := []byte{0x01, 0x02} buff := &bytes.Buffer{} err = handle.WriteWithAssociatedData(keyset.NewBinaryWriter(buff), keysetEncryptionAead, associatedData) if err != nil { t.Fatalf("handle.WriteWithAssociatedData() err = %v, want nil", err) } encrypted := buff.Bytes() handle2, err := keyset.ReadWithAssociatedData(keyset.NewBinaryReader(bytes.NewBuffer(encrypted)), keysetEncryptionAead, associatedData) if err != nil { t.Fatalf("keyset.ReadWithAssociatedData() err = %v, want nil", err) } if !proto.Equal(testkeyset.KeysetMaterial(handle), testkeyset.KeysetMaterial(handle2)) { t.Errorf("keyset.ReadWithAssociatedData() = %v, want %v", handle2, handle) } } func TestReadWithMismatchedAssociatedData(t *testing.T) { keysetEncryptionHandle, err := keyset.NewHandle(aead.AES128GCMKeyTemplate()) if err != nil { t.Errorf("keyset.NewHandle(aead.AES128GCMKeyTemplate()) err = %v, want nil", err) } keysetEncryptionAead, err := aead.New(keysetEncryptionHandle) if err != nil { t.Errorf("aead.New(keysetEncryptionHandle) err = %v, want nil", err) } handle, err := keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) err = %v, want nil", err) } associatedData := []byte{0x01, 0x02} buff := &bytes.Buffer{} err = handle.WriteWithAssociatedData(keyset.NewBinaryWriter(buff), keysetEncryptionAead, associatedData) if err != nil { t.Fatalf("handle.WriteWithAssociatedData() err = %v, want nil", err) } encrypted := buff.Bytes() invalidAssociatedData := []byte{0x01, 0x03} _, err = keyset.ReadWithAssociatedData(keyset.NewBinaryReader(bytes.NewBuffer(encrypted)), keysetEncryptionAead, invalidAssociatedData) if err == nil { t.Errorf("keyset.ReadWithAssociatedData() err = nil, want err") } } func TestWriteAndReadWithNoSecrets(t *testing.T) { // Create a keyset that contains a public key. privateHandle, err := keyset.NewHandle(signature.ECDSAP256KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle(signature.ECDSAP256KeyTemplate()) err = %v, want nil", err) } handle, err := privateHandle.Public() if err != nil { t.Fatalf("privateHandle.Public() err = %v, want nil", err) } buff := &bytes.Buffer{} err = handle.WriteWithNoSecrets(keyset.NewBinaryWriter(buff)) if err != nil { t.Fatalf("handle.WriteWithAssociatedData(keyset.NewBinaryWriter(buff), masterKey, associatedData) err = %v, want nil", err) } serialized := buff.Bytes() handle2, err := keyset.ReadWithNoSecrets(keyset.NewBinaryReader(bytes.NewBuffer(serialized))) if err != nil { t.Fatalf("keyset.ReadWithNoSecrets() err = %v, want nil", err) } if !proto.Equal(testkeyset.KeysetMaterial(handle), testkeyset.KeysetMaterial(handle2)) { t.Fatalf("keyset.ReadWithNoSecrets() = %v, want %v", handle2, handle) } } func TestWriteWithNoSecretsFailsWithSymmetricSecretKey(t *testing.T) { // Create a keyset that contains a symmetric secret key. handle, err := keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle(aead.AES256GCMKeyTemplate()) err = %v, want nil", err) } buff := &bytes.Buffer{} err = handle.WriteWithNoSecrets(keyset.NewBinaryWriter(buff)) if err == nil { t.Error("handle.WriteWithNoSecrets() = nil, want error") } } func TestReadWithNoSecretsFailsWithSymmetricSecretKey(t *testing.T) { // Create a keyset that contains a symmetric secret key. handle, err := keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle(aead.AES256GCMKeyTemplate()) err = %v, want nil", err) } buff := &bytes.Buffer{} err = testkeyset.Write(handle, keyset.NewBinaryWriter(buff)) if err != nil { t.Fatalf("insecurecleartextkeyset.Write(handle, keyset.NewBinaryWriter(buff)) err = %v, want nil", err) } serialized := buff.Bytes() _, err = keyset.ReadWithNoSecrets(keyset.NewBinaryReader(bytes.NewBuffer(serialized))) if err == nil { t.Error("keyset.ReadWithNoSecrets() = nil, want error") } } func TestWriteWithNoSecretsFailsWithPrivateKey(t *testing.T) { // Create a keyset that contains a private key. handle, err := keyset.NewHandle(signature.ECDSAP256KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle(signature.ECDSAP256KeyTemplate()) err = %v, want nil", err) } buff := &bytes.Buffer{} if err := handle.WriteWithNoSecrets(keyset.NewBinaryWriter(buff)); err == nil { t.Error("handle.WriteWithNoSecrets() = nil, want error") } } func TestReadWithNoSecretsFailsWithPrivateKey(t *testing.T) { // Create a keyset that contains a private key. handle, err := keyset.NewHandle(signature.ECDSAP256KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle(signature.ECDSAP256KeyTemplate()) err = %v, want nil", err) } buff := &bytes.Buffer{} err = testkeyset.Write(handle, keyset.NewBinaryWriter(buff)) if err != nil { t.Fatalf("insecurecleartextkeyset.Write(handle, keyset.NewBinaryWriter(buff)) err = %v, want nil", err) } serialized := buff.Bytes() _, err = keyset.ReadWithNoSecrets(keyset.NewBinaryReader(bytes.NewBuffer(serialized))) if err == nil { t.Error("keyset.ReadWithNoSecrets() = nil, want error") } } func TestWriteAndReadWithNoSecretsFailsWithUnknownKeyMaterial(t *testing.T) { // Create a keyset that contains unknown key material. keyData := testutil.NewKeyData("some type url", []byte{0}, tinkpb.KeyData_UNKNOWN_KEYMATERIAL) key := testutil.NewKey(keyData, tinkpb.KeyStatusType_ENABLED, 1, tinkpb.OutputPrefixType_TINK) ks := testutil.NewKeyset(1, []*tinkpb.Keyset_Key{key}) handle, err := testkeyset.NewHandle(ks) if err != nil { t.Fatal(err) } serialized, err := proto.Marshal(ks) if err != nil { t.Fatal(err) } buff := &bytes.Buffer{} err = handle.WriteWithNoSecrets(keyset.NewBinaryWriter(buff)) if err == nil { t.Error("handle.WriteWithNoSecrets() = nil, want error") } _, err = keyset.ReadWithNoSecrets(keyset.NewBinaryReader(bytes.NewBuffer(serialized))) if err == nil { t.Error("handle.ReadWithNoSecrets() = nil, want error") } } func TestKeysetInfo(t *testing.T) { kt := mac.HMACSHA256Tag128KeyTemplate() kh, err := keyset.NewHandle(kt) if err != nil { t.Errorf("unexpected error: %s", err) } info := kh.KeysetInfo() if info.PrimaryKeyId != info.KeyInfo[0].KeyId { t.Errorf("Expected primary key id: %d, but got: %d", info.KeyInfo[0].KeyId, info.PrimaryKeyId) } } func TestPrimitivesWithRegistry(t *testing.T) { template := mac.HMACSHA256Tag128KeyTemplate() template.OutputPrefixType = tinkpb.OutputPrefixType_RAW handle, err := keyset.NewHandle(template) if err != nil { t.Fatalf("keyset.NewHandle(%v) err = %v, want nil", template, err) } handleMAC, err := mac.New(handle) if err != nil { t.Fatalf("mac.New(%v) err = %v, want nil", handle, err) } ks := testkeyset.KeysetMaterial(handle) if len(ks.Key) != 1 { t.Fatalf("len(ks.Key) = %d, want 1", len(ks.Key)) } keyDataPrimitive, err := registry.PrimitiveFromKeyData(ks.Key[0].KeyData) if err != nil { t.Fatalf("registry.PrimitiveFromKeyData(%v) err = %v, want nil", ks.Key[0].KeyData, err) } keyDataMAC, ok := keyDataPrimitive.(tink.MAC) if !ok { t.Fatal("registry.PrimitiveFromKeyData(keyData) is not of type tink.MAC") } plaintext := []byte("plaintext") handleMACTag, err := handleMAC.ComputeMAC(plaintext) if err != nil { t.Fatalf("handleMAC.ComputeMAC(%v) err = %v, want nil", plaintext, err) } if err = keyDataMAC.VerifyMAC(handleMACTag, plaintext); err != nil { t.Errorf("keyDataMAC.VerifyMAC(%v, %v) err = %v, want nil", handleMACTag, plaintext, err) } keyDataMACTag, err := keyDataMAC.ComputeMAC(plaintext) if err != nil { t.Fatalf("keyDataMAC.ComputeMAC(%v) err = %v, want nil", plaintext, err) } if err = handleMAC.VerifyMAC(keyDataMACTag, plaintext); err != nil { t.Errorf("handleMAC.VerifyMAC(%v, %v) err = %v, want nil", keyDataMACTag, plaintext, err) } } type testConfig struct{} func (c *testConfig) PrimitiveFromKeyData(_ *tinkpb.KeyData, _ internalapi.Token) (any, error) { return testPrimitive{}, nil } func TestPrimitivesWithConfig(t *testing.T) { template := mac.HMACSHA256Tag128KeyTemplate() template.OutputPrefixType = tinkpb.OutputPrefixType_RAW handle, err := keyset.NewHandle(template) if err != nil { t.Fatalf("keyset.NewHandle(%v) = %v, want nil", template, err) } primitives, err := handle.Primitives(keyset.WithConfig(&testConfig{})) if err != nil { t.Fatalf("handle.Primitives(keyset.WithConfig(&testConfig{})) err = %v, want nil", err) } if len(primitives.EntriesInKeysetOrder) != 1 { t.Fatalf("len(handle.Primitives()) = %d, want 1", len(primitives.EntriesInKeysetOrder)) } if _, ok := (primitives.Primary.Primitive).(testPrimitive); !ok { t.Errorf("handle.Primitives().Primary = %v, want instance of `testPrimitive`", primitives.Primary.Primitive) } } func TestPrimitivesWithMultipleConfigs(t *testing.T) { template := mac.HMACSHA256Tag128KeyTemplate() template.OutputPrefixType = tinkpb.OutputPrefixType_RAW handle, err := keyset.NewHandle(template) if err != nil { t.Fatalf("keyset.NewHandle(%v) = %v, want nil", template, err) } _, err = handle.Primitives(keyset.WithConfig(&testConfig{}), keyset.WithConfig(&testConfig{})) if err == nil { // if NO error t.Error("handle.Primitives(keyset.WithConfig(&testConfig{}), keyset.WithConfig(&testConfig{})) err = nil, want error") } } type testKeyManager struct{} type testPrimitive struct{} func (km *testKeyManager) Primitive(_ []byte) (any, error) { return testPrimitive{}, nil } func (km *testKeyManager) NewKey(_ []byte) (proto.Message, error) { return nil, nil } func (km *testKeyManager) TypeURL() string { return mac.HMACSHA256Tag128KeyTemplate().TypeUrl } func (km *testKeyManager) NewKeyData(_ []byte) (*tinkpb.KeyData, error) { return nil, nil } func (km *testKeyManager) DoesSupport(typeURL string) bool { return typeURL == mac.HMACSHA256Tag128KeyTemplate().TypeUrl } func TestPrimitivesWithKeyManager(t *testing.T) { template := mac.HMACSHA256Tag128KeyTemplate() handle, err := keyset.NewHandle(template) if err != nil { t.Fatalf("keyset.NewHandle(%v) = %v, want nil", template, err) } // Verify that without providing a custom key manager we get a usual MAC. if _, err = mac.New(handle); err != nil { t.Fatalf("mac.New(%v) err = %v, want nil", handle, err) } // Verify that with the custom key manager provided we get the custom primitive. primitives, err := handle.PrimitivesWithKeyManager(&testKeyManager{}) if err != nil { t.Fatalf("handle.PrimitivesWithKeyManager(testKeyManager) err = %v, want nil", err) } if len(primitives.EntriesInKeysetOrder) != 1 { t.Fatalf("len(handle.PrimitivesWithKeyManager()) = %d, want 1", len(primitives.EntriesInKeysetOrder)) } if _, ok := (primitives.Primary.Primitive).(testPrimitive); !ok { t.Errorf("handle.PrimitivesWithKeyManager().Primary = %v, want instance of `testPrimitive`", primitives.Primary.Primitive) } } ================================================ FILE: go/keyset/json_io.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyset import ( "io" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // JSONReader deserializes a keyset from json format. type JSONReader struct { r io.Reader j *protojson.UnmarshalOptions } // NewJSONReader returns new JSONReader that will read from r. func NewJSONReader(r io.Reader) *JSONReader { return &JSONReader{ r: r, j: &protojson.UnmarshalOptions{}, } } // Read parses a (cleartext) keyset from the underlying io.Reader. func (bkr *JSONReader) Read() (*tinkpb.Keyset, error) { keyset := &tinkpb.Keyset{} if err := bkr.readJSON(bkr.r, keyset); err != nil { return nil, err } return keyset, nil } // ReadEncrypted parses an EncryptedKeyset from the underlying io.Reader. func (bkr *JSONReader) ReadEncrypted() (*tinkpb.EncryptedKeyset, error) { keyset := &tinkpb.EncryptedKeyset{} if err := bkr.readJSON(bkr.r, keyset); err != nil { return nil, err } return keyset, nil } func (bkr *JSONReader) readJSON(r io.Reader, msg proto.Message) error { b, err := io.ReadAll(r) if err != nil { return err } return bkr.j.Unmarshal(b, msg) } // JSONWriter serializes a keyset into json format. type JSONWriter struct { w io.Writer j *protojson.MarshalOptions } // NewJSONWriter returns a new JSONWriter that will write to w. func NewJSONWriter(w io.Writer) *JSONWriter { return &JSONWriter{ w: w, j: &protojson.MarshalOptions{ EmitUnpopulated: true, Indent: "", }, } } // Write writes the keyset to the underlying io.Writer. func (bkw *JSONWriter) Write(keyset *tinkpb.Keyset) error { return bkw.writeJSON(bkw.w, keyset) } // WriteEncrypted writes the encrypted keyset to the underlying io.Writer. func (bkw *JSONWriter) WriteEncrypted(keyset *tinkpb.EncryptedKeyset) error { return bkw.writeJSON(bkw.w, keyset) } func (bkw *JSONWriter) writeJSON(w io.Writer, msg proto.Message) error { b, err := bkw.j.Marshal(msg) if err != nil { return err } _, err = w.Write(b) return err } ================================================ FILE: go/keyset/json_io_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyset_test import ( "bytes" "encoding/base64" "fmt" "strings" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/keyset" "github.com/google/tink/go/testkeyset" "github.com/google/tink/go/testutil" commonpb "github.com/google/tink/go/proto/common_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestJSONIOUnencrypted(t *testing.T) { buf := new(bytes.Buffer) w := keyset.NewJSONWriter(buf) r := keyset.NewJSONReader(buf) manager := testutil.NewHMACKeysetManager() h, err := manager.Handle() if h == nil || err != nil { t.Fatalf("cannot get keyset handle: %v", err) } ks1 := testkeyset.KeysetMaterial(h) if err := w.Write(ks1); err != nil { t.Fatalf("cannot write keyset: %v", err) } ks2, err := r.Read() if err != nil { t.Fatalf("cannot read keyset: %v", err) } if !proto.Equal(ks1, ks2) { t.Errorf("written keyset (%s) doesn't match read keyset (%s)", ks1, ks2) } } func TestJSONReader(t *testing.T) { gcmkey := []byte(testutil.NewAESGCMKey(0, 16).String()) eaxkey := []byte(testutil.NewHMACKey(commonpb.HashType_SHA512, 32).String()) jsonKeyset := fmt.Sprintf(`{ "primaryKeyId":42, "key":[ { "keyData":{ "typeUrl":"type.googleapis.com/google.crypto.tink.AesGcmKey", "keyMaterialType":"SYMMETRIC", "value": %q }, "outputPrefixType":"TINK", "keyId":42, "status":"ENABLED" }, { "keyData":{ "typeUrl":"type.googleapis.com/google.crypto.tink.AesEaxKey", "keyMaterialType":"SYMMETRIC", "value": %q }, "outputPrefixType":"RAW", "keyId":711, "status":"ENABLED" } ] }`, base64.StdEncoding.EncodeToString([]byte(gcmkey)), base64.StdEncoding.EncodeToString([]byte(eaxkey))) r := keyset.NewJSONReader(bytes.NewBufferString(jsonKeyset)) got, err := r.Read() if err != nil { t.Fatalf("cannot read keyset: %v", err) } want := &tinkpb.Keyset{ PrimaryKeyId: 42, Key: []*tinkpb.Keyset_Key{ { KeyData: &tinkpb.KeyData{ TypeUrl: "type.googleapis.com/google.crypto.tink.AesGcmKey", KeyMaterialType: tinkpb.KeyData_SYMMETRIC, Value: gcmkey, }, OutputPrefixType: tinkpb.OutputPrefixType_TINK, KeyId: 42, Status: tinkpb.KeyStatusType_ENABLED, }, { KeyData: &tinkpb.KeyData{ TypeUrl: "type.googleapis.com/google.crypto.tink.AesEaxKey", KeyMaterialType: tinkpb.KeyData_SYMMETRIC, Value: eaxkey, }, OutputPrefixType: tinkpb.OutputPrefixType_RAW, KeyId: 711, Status: tinkpb.KeyStatusType_ENABLED, }, }, } if !proto.Equal(got, want) { t.Errorf("written keyset %q doesn't match expected keyset %q", got, want) } } func TestJSONReaderLargeIds(t *testing.T) { gcmkey := []byte(testutil.NewAESGCMKey(0, 16).String()) jsonKeyset := fmt.Sprintf(`{ "primaryKeyId":4294967275, "key":[ { "keyData":{ "typeUrl":"type.googleapis.com/google.crypto.tink.AesGcmKey", "keyMaterialType":"SYMMETRIC", "value": %q }, "outputPrefixType":"TINK", "keyId":4294967275, "status":"ENABLED" } ] }`, base64.StdEncoding.EncodeToString([]byte(gcmkey))) r := keyset.NewJSONReader(bytes.NewBufferString(jsonKeyset)) got, err := r.Read() if err != nil { t.Fatalf("cannot read keyset: %v", err) } want := &tinkpb.Keyset{ PrimaryKeyId: 4294967275, Key: []*tinkpb.Keyset_Key{ { KeyData: &tinkpb.KeyData{ TypeUrl: "type.googleapis.com/google.crypto.tink.AesGcmKey", KeyMaterialType: tinkpb.KeyData_SYMMETRIC, Value: gcmkey, }, OutputPrefixType: tinkpb.OutputPrefixType_TINK, KeyId: 4294967275, Status: tinkpb.KeyStatusType_ENABLED, }, }, } if !proto.Equal(got, want) { t.Errorf("written keyset %q doesn't match expected keyset %q", got, want) } } func TestJSONReaderRejectsNegativeKeyIds(t *testing.T) { gcmkey := []byte(testutil.NewAESGCMKey(0, 16).String()) jsonKeyset := fmt.Sprintf(`{ "primaryKeyId": -10, "key":[ { "keyData":{ "typeUrl":"type.googleapis.com/google.crypto.tink.AesGcmKey", "keyMaterialType":"SYMMETRIC", "value": %q }, "outputPrefixType":"TINK", "keyId": -10, "status":"ENABLED" } ] }`, base64.StdEncoding.EncodeToString(gcmkey)) r := keyset.NewJSONReader(bytes.NewBufferString(jsonKeyset)) _, err := r.Read() if err == nil { t.Fatalf("Expected failure due to negative key id") } } func TestJSONReaderRejectsKeyIdLargerThanUint32(t *testing.T) { // 4294967296 = 2^32, which is too large for uint32. gcmkey := []byte(testutil.NewAESGCMKey(0, 16).String()) jsonKeyset := fmt.Sprintf(`{ "primaryKeyId": 4294967296, "key":[ { "keyData":{ "typeUrl":"type.googleapis.com/google.crypto.tink.AesGcmKey", "keyMaterialType":"SYMMETRIC", "value": %q }, "outputPrefixType":"TINK", "keyId": 4294967296, "status":"ENABLED" } ] }`, base64.StdEncoding.EncodeToString(gcmkey)) r := keyset.NewJSONReader(bytes.NewBufferString(jsonKeyset)) _, err := r.Read() if err == nil { t.Fatalf("Expected failure due to negative key id") } } // Tests that large IDs (>2^31) are written correctly. func TestJSONWriterLargeId(t *testing.T) { eaxkey := []byte(testutil.NewHMACKey(commonpb.HashType_SHA512, 32).String()) ks := tinkpb.Keyset{ PrimaryKeyId: 4294967275, Key: []*tinkpb.Keyset_Key{ { KeyData: &tinkpb.KeyData{ TypeUrl: "type.googleapis.com/google.crypto.tink.AesEaxKey", KeyMaterialType: tinkpb.KeyData_SYMMETRIC, Value: eaxkey, }, OutputPrefixType: tinkpb.OutputPrefixType_RAW, KeyId: 4294967275, Status: tinkpb.KeyStatusType_ENABLED, }, }, } buf := new(bytes.Buffer) w := keyset.NewJSONWriter(buf) if err := w.Write(&ks); err != nil { t.Fatalf("cannot write keyset: %v", err) } if !strings.Contains(buf.String(), `"keyId":4294967275`) { t.Errorf("written keyset %q does not contain a key with keyId 4294967275", buf.Bytes()) } if !strings.Contains(buf.String(), "\"primaryKeyId\":4294967275") { t.Errorf("written keyset %q does not contain have primaryKeyId 4294967275", buf.Bytes()) } } func TestJSONIOEncrypted(t *testing.T) { buf := new(bytes.Buffer) w := keyset.NewJSONWriter(buf) r := keyset.NewJSONReader(buf) kse1 := &tinkpb.EncryptedKeyset{EncryptedKeyset: []byte(strings.Repeat("A", 32))} if err := w.WriteEncrypted(kse1); err != nil { t.Fatalf("cannot write encrypted keyset: %v", err) } kse2, err := r.ReadEncrypted() if err != nil { t.Fatalf("cannot read encryped keyset: %v", err) } if !proto.Equal(kse1, kse2) { t.Errorf("written encryped keyset %q doesn't match read encryped keyset %q", kse1, kse2) } } ================================================ FILE: go/keyset/keyset.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package keyset provides methods to generate, read, write or validate // keysets. package keyset import ( "github.com/google/tink/go/internal" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // keysetHandle is used by package insecurecleartextkeyset and package // testkeyset (via package internal) to create a keyset.Handle from cleartext // key material. func keysetHandle(ks *tinkpb.Keyset, opts ...Option) (*Handle, error) { return newWithOptions(ks, opts...) } // keysetMaterial is used by package insecurecleartextkeyset and package // testkeyset (via package internal) to read the key material in a // keyset.Handle. func keysetMaterial(h *Handle) *tinkpb.Keyset { return h.ks } func init() { internal.KeysetHandle = keysetHandle internal.KeysetMaterial = keysetMaterial } ================================================ FILE: go/keyset/keyset_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyset_test // [START encrypted-keyset-example] import ( "bytes" "fmt" "log" "github.com/google/tink/go/aead" "github.com/google/tink/go/keyset" "github.com/google/tink/go/testing/fakekms" ) // The fake KMS should only be used in tests. It is not secure. const keyURI = "fake-kms://CM2b3_MDElQKSAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuQWVzR2NtS2V5EhIaEIK75t5L-adlUwVhWvRuWUwYARABGM2b3_MDIAE" func Example_encryptedKeyset() { // Get a KEK (key encryption key) AEAD. This is usually a remote AEAD to a KMS. In this example, // we use a fake KMS to avoid making RPCs. client, err := fakekms.NewClient(keyURI) if err != nil { log.Fatal(err) } kekAEAD, err := client.GetAEAD(keyURI) if err != nil { log.Fatal(err) } // Generate a new keyset handle for the primitive we want to use. newHandle, err := keyset.NewHandle(aead.AES256GCMKeyTemplate()) if err != nil { log.Fatal(err) } // Choose some associated data. This is the context in which the keyset will be used. keysetAssociatedData := []byte("keyset encryption example") // Encrypt the keyset with the KEK AEAD and the associated data. buf := new(bytes.Buffer) writer := keyset.NewBinaryWriter(buf) err = newHandle.WriteWithAssociatedData(writer, kekAEAD, keysetAssociatedData) if err != nil { log.Fatal(err) } encryptedKeyset := buf.Bytes() // The encrypted keyset can now be stored. // To use the primitive, we first need to decrypt the keyset. We use the same // KEK AEAD and the same associated data that we used to encrypt it. reader := keyset.NewBinaryReader(bytes.NewReader(encryptedKeyset)) handle, err := keyset.ReadWithAssociatedData(reader, kekAEAD, keysetAssociatedData) if err != nil { log.Fatal(err) } // Get the primitive. primitive, err := aead.New(handle) if err != nil { log.Fatal(err) } // Use the primitive. plaintext := []byte("message") associatedData := []byte("example encryption") ciphertext, err := primitive.Encrypt(plaintext, associatedData) if err != nil { log.Fatal(err) } decrypted, err := primitive.Decrypt(ciphertext, associatedData) if err != nil { log.Fatal(err) } fmt.Println(string(decrypted)) // Output: message } // [END encrypted-keyset-example] ================================================ FILE: go/keyset/manager.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyset import ( "errors" "fmt" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/subtle/random" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // Manager manages a Keyset-proto, with convenience methods that rotate, disable, enable or destroy keys. // Note: It is not thread-safe. type Manager struct { ks *tinkpb.Keyset } // NewManager creates a new instance with an empty Keyset. func NewManager() *Manager { ret := new(Manager) ret.ks = new(tinkpb.Keyset) return ret } // NewManagerFromHandle creates a new instance from the given Handle. func NewManagerFromHandle(kh *Handle) *Manager { ret := new(Manager) ret.ks = kh.ks return ret } // Add generates and adds a fresh key using the given key template. // the key is enabled on creation, but not set to primary. // It returns the ID of the new key func (km *Manager) Add(kt *tinkpb.KeyTemplate) (uint32, error) { if kt == nil { return 0, errors.New("keyset_manager: cannot add key, need key template") } if kt.OutputPrefixType == tinkpb.OutputPrefixType_UNKNOWN_PREFIX { return 0, errors.New("keyset_manager: unknown output prefix type") } if km.ks == nil { return 0, errors.New("keyset_manager: cannot add key to nil keyset") } keyData, err := registry.NewKeyData(kt) if err != nil { return 0, fmt.Errorf("keyset_manager: cannot create KeyData: %s", err) } keyID := km.newKeyID() key := &tinkpb.Keyset_Key{ KeyData: keyData, Status: tinkpb.KeyStatusType_ENABLED, KeyId: keyID, OutputPrefixType: kt.OutputPrefixType, } km.ks.Key = append(km.ks.Key, key) return keyID, nil } // SetPrimary sets the key with given keyID as primary. // Returns an error if the key is not found or not enabled. func (km *Manager) SetPrimary(keyID uint32) error { if km.ks == nil { return errors.New("keyset_manager: cannot set primary, no keyset") } for _, key := range km.ks.Key { if key.KeyId != keyID { continue } if key.Status == tinkpb.KeyStatusType_ENABLED { km.ks.PrimaryKeyId = keyID return nil } return errors.New("keyset_manager: cannot set key as primary because it's not enabled") } return fmt.Errorf("keyset_manager: key with id %d not found", keyID) } // Enable will enable the key with given keyID. // Returns an error if the key is not found or is not enabled or disabled already. func (km *Manager) Enable(keyID uint32) error { if km.ks == nil { return errors.New("keyset_manager: cannot enable key, no keyset") } for i, key := range km.ks.Key { if key.KeyId != keyID { continue } if key.Status == tinkpb.KeyStatusType_ENABLED || key.Status == tinkpb.KeyStatusType_DISABLED { km.ks.Key[i].Status = tinkpb.KeyStatusType_ENABLED return nil } return fmt.Errorf("keyset_manager: cannot enable key with id %d with status %s", keyID, key.Status.String()) } return fmt.Errorf("keyset_manager: key with id %d not found", keyID) } // Disable will disable the key with given keyID. // Returns an error if the key is not found or it is the primary key. func (km *Manager) Disable(keyID uint32) error { if km.ks == nil { return errors.New("keyset_manager: cannot disable key, no keyset") } if km.ks.PrimaryKeyId == keyID { return errors.New("keyset_manager: cannot disable the primary key") } for i, key := range km.ks.Key { if key.KeyId != keyID { continue } if key.Status == tinkpb.KeyStatusType_ENABLED || key.Status == tinkpb.KeyStatusType_DISABLED { km.ks.Key[i].Status = tinkpb.KeyStatusType_DISABLED return nil } return fmt.Errorf("keyset_manager: cannot disable key with id %d with status %s", keyID, key.Status.String()) } return fmt.Errorf("keyset_manager: key with id %d not found", keyID) } // Delete will delete the key with given keyID, removing the key from the keyset entirely. // Returns an error if the key is not found or it is the primary key. func (km *Manager) Delete(keyID uint32) error { if km.ks == nil { return errors.New("keyset_manager: cannot delete key, no keyset") } if km.ks.PrimaryKeyId == keyID { return errors.New("keyset_manager: cannot delete the primary key") } deleteIdx, found := 0, false for i, key := range km.ks.Key { if key.KeyId == keyID { found = true deleteIdx = i } } if !found { return fmt.Errorf("keyset_manager: key with id %d not found", keyID) } // swap elements km.ks.Key[deleteIdx] = km.ks.Key[len(km.ks.Key)-1] // trim last element km.ks.Key = km.ks.Key[:len(km.ks.Key)-1] return nil } // Handle creates a new Handle for the managed keyset. func (km *Manager) Handle() (*Handle, error) { return &Handle{ks: km.ks}, nil } // newKeyID generates a key id that has not been used by any key in the keyset. func (km *Manager) newKeyID() uint32 { for { ret := random.GetRandomUint32() ok := true for _, key := range km.ks.Key { if key.KeyId == ret { ok = false break } } if ok { return ret } } } ================================================ FILE: go/keyset/manager_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyset_test import ( "strings" "testing" "github.com/google/tink/go/keyset" "github.com/google/tink/go/mac" "github.com/google/tink/go/testkeyset" "github.com/google/tink/go/testutil" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestKeysetManagerBasic(t *testing.T) { // Create a keyset that contains a single HmacKey. ksm := keyset.NewManager() kt := mac.HMACSHA256Tag128KeyTemplate() keyID, err := ksm.Add(kt) if err != nil { t.Errorf("cannot add key: %s", err) } err = ksm.SetPrimary(keyID) if err != nil { t.Errorf("cannot set primary key: %s", err) } h, err := ksm.Handle() if err != nil { t.Errorf("cannot get keyset handle: %s", err) } ks := testkeyset.KeysetMaterial(h) if len(ks.Key) != 1 { t.Fatal("expect the number of keys in the keyset is 1") } if ks.Key[0].KeyId != ks.PrimaryKeyId || ks.Key[0].KeyData.TypeUrl != testutil.HMACTypeURL || ks.Key[0].Status != tinkpb.KeyStatusType_ENABLED || ks.Key[0].OutputPrefixType != tinkpb.OutputPrefixType_TINK { t.Errorf("incorrect key information: %s", ks.Key[0]) } } func TestExistingKeyset(t *testing.T) { // Create a keyset that contains a single HmacKey. ksm1 := keyset.NewManager() kt := mac.HMACSHA256Tag128KeyTemplate() keyID1, err := ksm1.Add(kt) if err != nil { t.Errorf("cannot add key: %s", err) } err = ksm1.SetPrimary(keyID1) if err != nil { t.Errorf("cannot set primary key: %s", err) } h1, err := ksm1.Handle() if err != nil { t.Errorf("cannot get keyset handle: %s", err) } ks1 := testkeyset.KeysetMaterial(h1) ksm2 := keyset.NewManagerFromHandle(h1) keyID2, err := ksm2.Add(kt) if err != nil { t.Errorf("cannot add key: %s", err) } err = ksm2.SetPrimary(keyID2) if err != nil { t.Errorf("cannot set primary key: %s", err) } h2, err := ksm2.Handle() if err != nil { t.Errorf("cannot get keyset handle: %s", err) } ks2 := testkeyset.KeysetMaterial(h2) if len(ks2.Key) != 2 { t.Errorf("expect the number of keys to be 2, got %d", len(ks2.Key)) } if ks1.Key[0].String() != ks2.Key[0].String() { t.Errorf("expect the first key in two keysets to be the same") } if ks2.Key[1].KeyId != ks2.PrimaryKeyId { t.Errorf("expect the second key to be primary") } } func TestKeysetManagerFull(t *testing.T) { // Test a full keyset manager cycle: add, get info, set primary. ksm := keyset.NewManager() kt := mac.HMACSHA256Tag128KeyTemplate() _, err := ksm.Add(kt) if err != nil { t.Errorf("Expected no error but got %s", err) } h1, err := ksm.Handle() if err != nil { t.Errorf("Expected no error but got %s", err) } info := h1.KeysetInfo() if len(info.KeyInfo) != 1 { t.Errorf("Expected one key but got %d", len(info.KeyInfo)) } newPrimaryKey := info.KeyInfo[0].KeyId err = ksm.SetPrimary(newPrimaryKey) if err != nil { t.Errorf("Expected no error but got %s", err) } // validate this is a valid keyset ks1 := testkeyset.KeysetMaterial(h1) err = keyset.Validate(ks1) if err != nil { t.Errorf("Expected no error but got %s", err) } } func TestKeysetManagerAdd(t *testing.T) { ksm1 := keyset.NewManager() kt := mac.HMACSHA256Tag128KeyTemplate() keyID, err := ksm1.Add(kt) if err != nil { t.Errorf("Expected no error but got %s", err) } h, err := ksm1.Handle() if err != nil { t.Errorf("Cannot get keyset handle: %s", err) } ks := testkeyset.KeysetMaterial(h) if len(ks.Key) != 1 { t.Errorf("Expected one key but got %d", len(ks.Key)) } if ks.Key[0].KeyId != keyID { t.Errorf("Expected added keyID to be %d but got %d", keyID, ks.Key[0].KeyId) } if ks.Key[0].Status != tinkpb.KeyStatusType_ENABLED { t.Errorf("Expected key to be enabled but got %s", ks.Key[0].Status.String()) } // no primary key set if ks.PrimaryKeyId != 0 { t.Errorf("Expected no primary key but got %d", ks.PrimaryKeyId) } } func TestKeysetManagerAddWithNilKeysetTemplateFails(t *testing.T) { // ops with nil template should fail ksm1 := keyset.NewManager() _, err := ksm1.Add(nil) if err == nil { t.Errorf("ksm1.Add succeeded, but want error") } } func TestKeysetManagerAddWithInvalidTypeUrlFails(t *testing.T) { ksm1 := keyset.NewManager() kt := &tinkpb.KeyTemplate{ TypeUrl: "invalid type", OutputPrefixType: tinkpb.OutputPrefixType_TINK, } _, err := ksm1.Add(kt) if err == nil { t.Errorf("ksm1.Add succeeded, want error") } } func TestKeysetManagerAddWithUnknownOutputPrefixTypeFails(t *testing.T) { ksm1 := keyset.NewManager() kt := mac.HMACSHA256Tag128KeyTemplate() kt.OutputPrefixType = tinkpb.OutputPrefixType_UNKNOWN_PREFIX _, err := ksm1.Add(kt) if err == nil { t.Errorf("ksm1.Add(kt) where kt has an unknown prefix succeeded, want error") } } func TestKeysetManagerEnable(t *testing.T) { keyID := uint32(42) keyData := testutil.NewKeyData("some type url", []byte{0}, tinkpb.KeyData_SYMMETRIC) key := testutil.NewKey(keyData, tinkpb.KeyStatusType_DISABLED, keyID, tinkpb.OutputPrefixType_TINK) ks1 := testutil.NewKeyset(keyID, []*tinkpb.Keyset_Key{key}) h1, err := testkeyset.NewHandle(ks1) if err != nil { t.Errorf("Expected no error but got error %s", err) } ksm1 := keyset.NewManagerFromHandle(h1) // enable key err = ksm1.Enable(keyID) if err != nil { t.Errorf("Expected no error but got error %s", err) } h2, err := ksm1.Handle() if err != nil { t.Errorf("ksm1.Handle() err = %q, want nil", err) } ks2 := testkeyset.KeysetMaterial(h2) if len(ks2.Key) != 1 { t.Fatalf("Expected only one key, got %d", len(ks2.Key)) } if ks2.Key[0].KeyId != keyID { t.Errorf("Expected keyID %d, got %d", keyID, ks2.Key[0].KeyId) } if ks2.Key[0].Status != tinkpb.KeyStatusType_ENABLED { t.Errorf("Expected key to be enabled, but got %s", ks2.Key[0].Status.String()) } } func TestKeysetManagerEnableWithUnknownStatus(t *testing.T) { keyID := uint32(42) keyData := testutil.NewKeyData("some type url", []byte{0}, tinkpb.KeyData_SYMMETRIC) key := testutil.NewKey(keyData, tinkpb.KeyStatusType_UNKNOWN_STATUS, keyID, tinkpb.OutputPrefixType_TINK) ks1 := testutil.NewKeyset(keyID, []*tinkpb.Keyset_Key{key}) h1, err := testkeyset.NewHandle(ks1) if err != nil { t.Errorf("Expected no error but got error %s", err) } ksm1 := keyset.NewManagerFromHandle(h1) // enable key err = ksm1.Enable(keyID) if err == nil { t.Errorf("ksm1.Enable where key has unknown status succeeded, want error") } if !strings.Contains(err.Error(), "cannot enable") { t.Errorf("Expected 'cannot enable' message, got %s", err) } } func TestKeysetManagerEnableWithDestroyed(t *testing.T) { keyID := uint32(42) keyData := testutil.NewKeyData("some type url", nil, tinkpb.KeyData_SYMMETRIC) key := testutil.NewKey(keyData, tinkpb.KeyStatusType_DESTROYED, keyID, tinkpb.OutputPrefixType_TINK) ks1 := testutil.NewKeyset(keyID, []*tinkpb.Keyset_Key{key}) h1, err := testkeyset.NewHandle(ks1) if err != nil { t.Errorf("Expected no error but got error %s", err) } ksm1 := keyset.NewManagerFromHandle(h1) // enable key err = ksm1.Enable(keyID) if err == nil { t.Errorf("ksm1.Enable where key was destroyed succeeded, want error") } if !strings.Contains(err.Error(), "cannot enable") { t.Errorf("Expected 'cannot enable' message, got %s", err) } } func TestKeysetManagerEnableWithMissingKey(t *testing.T) { keyID := uint32(42) keyData := testutil.NewKeyData("some type url", []byte{0}, tinkpb.KeyData_SYMMETRIC) key := testutil.NewKey(keyData, tinkpb.KeyStatusType_UNKNOWN_STATUS, keyID, tinkpb.OutputPrefixType_TINK) ks1 := testutil.NewKeyset(keyID, []*tinkpb.Keyset_Key{key}) h1, err := testkeyset.NewHandle(ks1) if err != nil { t.Errorf("Expected no error but got error %s", err) } ksm1 := keyset.NewManagerFromHandle(h1) // enable key err = ksm1.Enable(uint32(43)) if err == nil { t.Errorf("ksm1.Enable where key doesn't exist succeeded, want error") } if !strings.Contains(err.Error(), "not found") { t.Errorf("Expected 'not found' message, got %s", err) } } func TestKeysetManagerSetPrimary(t *testing.T) { keyID := uint32(42) newKeyID := uint32(43) keyData := testutil.NewKeyData("some type url", []byte{0}, tinkpb.KeyData_SYMMETRIC) key := testutil.NewKey(keyData, tinkpb.KeyStatusType_ENABLED, keyID, tinkpb.OutputPrefixType_TINK) key2 := testutil.NewKey(keyData, tinkpb.KeyStatusType_ENABLED, newKeyID, tinkpb.OutputPrefixType_TINK) ks1 := testutil.NewKeyset(keyID, []*tinkpb.Keyset_Key{key, key2}) h1, err := testkeyset.NewHandle(ks1) if err != nil { t.Errorf("Expected no error but got error %s", err) } ksm1 := keyset.NewManagerFromHandle(h1) // set primary key err = ksm1.SetPrimary(newKeyID) if err != nil { t.Errorf("Expected no error but got error %s", err) } h2, err := ksm1.Handle() if err != nil { t.Errorf("Expected no error but got error %s", err) } ks2 := testkeyset.KeysetMaterial(h2) if len(ks2.Key) != 2 { t.Errorf("Expected two keys, got %d", len(ks2.Key)) } if ks2.PrimaryKeyId != newKeyID { t.Errorf("Expected new key to be primary, got %d", ks2.PrimaryKeyId) } } func TestKeysetManagerSetPrimaryWithDisabledKey(t *testing.T) { keyID := uint32(42) newKeyID := uint32(43) keyData := testutil.NewKeyData("some type url", []byte{0}, tinkpb.KeyData_SYMMETRIC) key := testutil.NewKey(keyData, tinkpb.KeyStatusType_ENABLED, keyID, tinkpb.OutputPrefixType_TINK) // create a disabled key key2 := testutil.NewKey(keyData, tinkpb.KeyStatusType_DISABLED, newKeyID, tinkpb.OutputPrefixType_TINK) ks1 := testutil.NewKeyset(keyID, []*tinkpb.Keyset_Key{key, key2}) h1, err := testkeyset.NewHandle(ks1) if err != nil { t.Errorf("Expected no error but got error %s", err) } ksm1 := keyset.NewManagerFromHandle(h1) // set primary key err = ksm1.SetPrimary(newKeyID) if err == nil { t.Errorf("ksm1.SetPrimary on disabled key succeeded, want error") } if !strings.Contains(err.Error(), "not enabled") { t.Errorf("Expected 'not enabled' message, got %s", err) } } func TestKeysetManagerSetPrimaryWithDestroyedKey(t *testing.T) { keyID := uint32(42) newKeyID := uint32(43) keyData := testutil.NewKeyData("some type url", []byte{0}, tinkpb.KeyData_SYMMETRIC) key := testutil.NewKey(keyData, tinkpb.KeyStatusType_ENABLED, keyID, tinkpb.OutputPrefixType_TINK) // create a destroyed key key2 := testutil.NewKey(keyData, tinkpb.KeyStatusType_DESTROYED, newKeyID, tinkpb.OutputPrefixType_TINK) ks1 := testutil.NewKeyset(keyID, []*tinkpb.Keyset_Key{key, key2}) h1, err := testkeyset.NewHandle(ks1) if err != nil { t.Errorf("Expected no error but got error %s", err) } ksm1 := keyset.NewManagerFromHandle(h1) // set primary key err = ksm1.SetPrimary(newKeyID) if err == nil { t.Errorf("ksm1.SetPrimary on destroyed key succeeded, want error") } if !strings.Contains(err.Error(), "not enabled") { t.Errorf("Expected 'not enabled' message, got %s", err) } } func TestKeysetManagerSetPrimaryWithUnknownStatusKey(t *testing.T) { keyID := uint32(42) newKeyID := uint32(43) keyData := testutil.NewKeyData("some type url", []byte{0}, tinkpb.KeyData_SYMMETRIC) key := testutil.NewKey(keyData, tinkpb.KeyStatusType_ENABLED, keyID, tinkpb.OutputPrefixType_TINK) // create an unknown status key key2 := testutil.NewKey(keyData, tinkpb.KeyStatusType_UNKNOWN_STATUS, newKeyID, tinkpb.OutputPrefixType_TINK) ks1 := testutil.NewKeyset(keyID, []*tinkpb.Keyset_Key{key, key2}) h1, err := testkeyset.NewHandle(ks1) if err != nil { t.Errorf("Expected no error but got error %s", err) } ksm1 := keyset.NewManagerFromHandle(h1) // set primary key err = ksm1.SetPrimary(newKeyID) if err == nil { t.Errorf("ksm1.SetPrimary on unknown key succeeded, want error") } if !strings.Contains(err.Error(), "not enabled") { t.Errorf("Expected 'not enabled' message, got %s", err) } } func TestKeysetManagerSetPrimaryWithMissingKey(t *testing.T) { keyID := uint32(42) newKeyID := uint32(43) keyData := testutil.NewKeyData("some type url", []byte{0}, tinkpb.KeyData_SYMMETRIC) key := testutil.NewKey(keyData, tinkpb.KeyStatusType_ENABLED, keyID, tinkpb.OutputPrefixType_TINK) // create an unknown status key key2 := testutil.NewKey(keyData, tinkpb.KeyStatusType_UNKNOWN_STATUS, newKeyID, tinkpb.OutputPrefixType_TINK) ks1 := testutil.NewKeyset(keyID, []*tinkpb.Keyset_Key{key, key2}) h1, err := testkeyset.NewHandle(ks1) if err != nil { t.Errorf("Expected no error but got error %s", err) } ksm1 := keyset.NewManagerFromHandle(h1) // set primary key err = ksm1.SetPrimary(uint32(44)) if err == nil { t.Errorf("ksm1.SetPrimary on missing key succeeded, want error") } if !strings.Contains(err.Error(), "not found") { t.Errorf("Expected 'not found' message, got %s", err) } } func TestKeysetManagerDisable(t *testing.T) { primaryKeyID := uint32(42) otherKeyID := uint32(43) keyData := testutil.NewKeyData("some type url", []byte{0}, tinkpb.KeyData_SYMMETRIC) key := testutil.NewKey(keyData, tinkpb.KeyStatusType_ENABLED, primaryKeyID, tinkpb.OutputPrefixType_TINK) key2 := testutil.NewKey(keyData, tinkpb.KeyStatusType_ENABLED, otherKeyID, tinkpb.OutputPrefixType_TINK) ks1 := testutil.NewKeyset(primaryKeyID, []*tinkpb.Keyset_Key{key, key2}) h1, err := testkeyset.NewHandle(ks1) if err != nil { t.Errorf("Expected no error but got error %s", err) } ksm1 := keyset.NewManagerFromHandle(h1) // disable key err = ksm1.Disable(otherKeyID) if err != nil { t.Errorf("Expected no error but got error %s", err) } h2, err := ksm1.Handle() if err != nil { t.Errorf("Expected no error but got error %s", err) } ks2 := testkeyset.KeysetMaterial(h2) if ks2.PrimaryKeyId != primaryKeyID { t.Errorf("Expected same key to be primary, got %d", ks2.PrimaryKeyId) } if len(ks2.Key) != 2 { t.Errorf("Expected two keys, got %d", len(ks2.Key)) t.FailNow() } if ks2.Key[1].Status != tinkpb.KeyStatusType_DISABLED { t.Errorf("Expected key to be disabled, got %s", ks2.Key[1].Status.String()) } } func TestKeysetManagerDisableWithPrimaryKey(t *testing.T) { primaryKeyID := uint32(42) otherKeyID := uint32(43) keyData := testutil.NewKeyData("some type url", []byte{0}, tinkpb.KeyData_SYMMETRIC) key := testutil.NewKey(keyData, tinkpb.KeyStatusType_ENABLED, primaryKeyID, tinkpb.OutputPrefixType_TINK) key2 := testutil.NewKey(keyData, tinkpb.KeyStatusType_ENABLED, otherKeyID, tinkpb.OutputPrefixType_TINK) ks1 := testutil.NewKeyset(primaryKeyID, []*tinkpb.Keyset_Key{key, key2}) h1, err := testkeyset.NewHandle(ks1) if err != nil { t.Errorf("Expected no error but got error %s", err) } ksm1 := keyset.NewManagerFromHandle(h1) // disable key err = ksm1.Disable(primaryKeyID) if err == nil { t.Errorf("ksm1.Disable on primary key succeeded, want error") } if !strings.Contains(err.Error(), "cannot disable the primary key") { t.Errorf("Expected 'cannot disable the primary key' message, got %s", err) } h2, err := ksm1.Handle() if err != nil { t.Errorf("Expected no error but got error %s", err) } ks2 := testkeyset.KeysetMaterial(h2) if ks2.PrimaryKeyId != primaryKeyID { t.Errorf("Expected same key to be primary, got %d", ks2.PrimaryKeyId) } } func TestKeysetManagerDisableWithDestroyedKey(t *testing.T) { primaryKeyID := uint32(42) otherKeyID := uint32(43) keyData := testutil.NewKeyData("some type url", []byte{0}, tinkpb.KeyData_SYMMETRIC) key := testutil.NewKey(keyData, tinkpb.KeyStatusType_ENABLED, primaryKeyID, tinkpb.OutputPrefixType_TINK) // destroyed key key2 := testutil.NewKey(keyData, tinkpb.KeyStatusType_DESTROYED, otherKeyID, tinkpb.OutputPrefixType_TINK) ks1 := testutil.NewKeyset(primaryKeyID, []*tinkpb.Keyset_Key{key, key2}) h1, err := testkeyset.NewHandle(ks1) if err != nil { t.Errorf("Expected no error but got error %s", err) } ksm1 := keyset.NewManagerFromHandle(h1) // disable key err = ksm1.Disable(otherKeyID) if err == nil { t.Errorf("ksm1.Disable on destroyed key succeeded, want error") } if !strings.Contains(err.Error(), "cannot disable") { t.Errorf("Expected 'cannot disable' message, got %s", err) } } func TestKeysetManagerDisableWithMissingKey(t *testing.T) { primaryKeyID := uint32(42) otherKeyID := uint32(43) keyData := testutil.NewKeyData("some type url", []byte{0}, tinkpb.KeyData_SYMMETRIC) key := testutil.NewKey(keyData, tinkpb.KeyStatusType_ENABLED, primaryKeyID, tinkpb.OutputPrefixType_TINK) key2 := testutil.NewKey(keyData, tinkpb.KeyStatusType_ENABLED, otherKeyID, tinkpb.OutputPrefixType_TINK) ks1 := testutil.NewKeyset(primaryKeyID, []*tinkpb.Keyset_Key{key, key2}) h1, err := testkeyset.NewHandle(ks1) if err != nil { t.Errorf("Expected no error but got error %s", err) } ksm1 := keyset.NewManagerFromHandle(h1) // disable key err = ksm1.Disable(uint32(44)) if err == nil { t.Errorf("ksm1.Disable on missing key succeeded, want error") } if !strings.Contains(err.Error(), "not found") { t.Errorf("Expected 'not found' message, got %s", err) } } func TestKeysetManagerDelete(t *testing.T) { keyID := uint32(42) otherKeyID := uint32(43) keyData := testutil.NewKeyData("some type url", []byte{0}, tinkpb.KeyData_SYMMETRIC) key := testutil.NewKey(keyData, tinkpb.KeyStatusType_ENABLED, keyID, tinkpb.OutputPrefixType_TINK) key2 := testutil.NewKey(keyData, tinkpb.KeyStatusType_ENABLED, otherKeyID, tinkpb.OutputPrefixType_TINK) ks1 := testutil.NewKeyset(keyID, []*tinkpb.Keyset_Key{key, key2}) h1, err := testkeyset.NewHandle(ks1) if err != nil { t.Errorf("Expected no error but got error %s", err) } ksm1 := keyset.NewManagerFromHandle(h1) // delete key err = ksm1.Delete(otherKeyID) if err != nil { t.Errorf("Expected no error but got error %s", err) } h2, err := ksm1.Handle() if err != nil { t.Fatalf("ksm1.Handle() err = %q, want nil", err) } ks2 := testkeyset.KeysetMaterial(h2) if len(ks2.Key) != 1 { t.Fatalf("Expected only one key but got %d", len(ks2.Key)) } if ks2.Key[0].KeyId != ks2.PrimaryKeyId || ks2.Key[0].KeyId != keyID { t.Errorf("Expected keyID %d to be present but got %d", keyID, ks2.Key[0].KeyId) } if ks2.Key[0].Status != tinkpb.KeyStatusType_ENABLED { t.Errorf("Expected key to be enabled but got %s", ks2.Key[0].Status.String()) } } func TestKeysetManagerDeleteWithPrimaryKey(t *testing.T) { keyID := uint32(42) keyData := testutil.NewKeyData("some type url", []byte{0}, tinkpb.KeyData_SYMMETRIC) key := testutil.NewKey(keyData, tinkpb.KeyStatusType_ENABLED, keyID, tinkpb.OutputPrefixType_TINK) ks1 := testutil.NewKeyset(keyID, []*tinkpb.Keyset_Key{key}) h1, err := testkeyset.NewHandle(ks1) if err != nil { t.Errorf("Expected no error but got error %s", err) } ksm1 := keyset.NewManagerFromHandle(h1) // delete key err = ksm1.Delete(keyID) if err == nil { t.Errorf("ksm1.Delete succeeded but expected error") } if !strings.Contains(err.Error(), "primary key") { t.Errorf("Expected 'primary key' message but got %s", err) } } func TestKeysetManagerDeleteWithMissingKey(t *testing.T) { keyID := uint32(42) keyData := testutil.NewKeyData("some type url", []byte{0}, tinkpb.KeyData_SYMMETRIC) key := testutil.NewKey(keyData, tinkpb.KeyStatusType_ENABLED, keyID, tinkpb.OutputPrefixType_TINK) ks1 := testutil.NewKeyset(keyID, []*tinkpb.Keyset_Key{key}) h1, err := testkeyset.NewHandle(ks1) if err != nil { t.Errorf("Expected no error but got error %s", err) } ksm1 := keyset.NewManagerFromHandle(h1) // delete key err = ksm1.Delete(uint32(43)) if err == nil { t.Errorf("ksm1.Delete succeeded but expected error") } if !strings.Contains(err.Error(), "not found") { t.Errorf("Expected 'not found' message but got %s", err) } } func TestKeysetManagerWithEmptyManager(t *testing.T) { // all ops with empty manager should fail ksm1 := &keyset.Manager{} _, err := ksm1.Add(mac.HMACSHA256Tag128KeyTemplate()) if err == nil { t.Errorf("ksm1.Add succeeded on empty manager, want error") } err = ksm1.SetPrimary(0) if err == nil { t.Errorf("ksm1.SetPrimary succeeded on empty manager, want error") } err = ksm1.Enable(0) if err == nil { t.Errorf("ksm1.Enable succeeded on empty manager, want error") } err = ksm1.Delete(0) if err == nil { t.Errorf("ksm1.Delete succeeded on empty manager, want error") } err = ksm1.Disable(0) if err == nil { t.Errorf("ksm1.Disable succeeded on empty manager, want error") } } ================================================ FILE: go/keyset/mem_io.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyset import tinkpb "github.com/google/tink/go/proto/tink_go_proto" // MemReaderWriter implements keyset.Reader and keyset.Writer for *tinkpb.Keyset and *tinkpb.EncryptedKeyset. // // Deprecated: Use [keyset.NewBinaryReader] or [keyset.NewBinaryWriter] instead. See tests in // mem_io_test.go for examples on how to use them instead. type MemReaderWriter struct { Keyset *tinkpb.Keyset EncryptedKeyset *tinkpb.EncryptedKeyset } // MemReaderWriter implements Reader and Writer. var _ Reader = &MemReaderWriter{} var _ Writer = &MemReaderWriter{} // Read returns *tinkpb.Keyset from memory. func (m *MemReaderWriter) Read() (*tinkpb.Keyset, error) { return m.Keyset, nil } // ReadEncrypted returns *tinkpb.EncryptedKeyset from memory. func (m *MemReaderWriter) ReadEncrypted() (*tinkpb.EncryptedKeyset, error) { return m.EncryptedKeyset, nil } // Write keyset to memory. func (m *MemReaderWriter) Write(keyset *tinkpb.Keyset) error { m.Keyset = keyset return nil } // WriteEncrypted keyset to memory. func (m *MemReaderWriter) WriteEncrypted(keyset *tinkpb.EncryptedKeyset) error { m.EncryptedKeyset = keyset return nil } ================================================ FILE: go/keyset/mem_io_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyset_test import ( "bytes" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/aead" "github.com/google/tink/go/insecurecleartextkeyset" "github.com/google/tink/go/keyset" "github.com/google/tink/go/mac" "github.com/google/tink/go/signature" "github.com/google/tink/go/testkeyset" "github.com/google/tink/go/tink" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestConvertProtoKeysetIntoHandleInTests(t *testing.T) { h, err := keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) if err != nil { t.Fatal(err) } protoKeyset := testkeyset.KeysetMaterial(h) // In tests, this: wantHandle, err := insecurecleartextkeyset.Read(&keyset.MemReaderWriter{Keyset: protoKeyset}) if err != nil { t.Fatal(err) } // can be replaced by this: gotHandle, err := testkeyset.NewHandle(protoKeyset) if err != nil { t.Fatal(err) } if got, want := testkeyset.KeysetMaterial(gotHandle), testkeyset.KeysetMaterial(wantHandle); !proto.Equal(got, want) { t.Errorf("gotHandle contains %s, want %s", got, want) } } func TestConvertHandleKeysetIntoProtoKeysetInTests(t *testing.T) { handle, err := keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) if err != nil { t.Fatal(err) } // In tests, this: writer := &keyset.MemReaderWriter{} if err := insecurecleartextkeyset.Write(handle, writer); err != nil { t.Fatal(err) } wantKeyset := writer.Keyset // can be replaced by this: gotKeyset := testkeyset.KeysetMaterial(handle) if !proto.Equal(gotKeyset, wantKeyset) { t.Errorf("testkeyset.KeysetMaterial(handle) = %v, want %v", gotKeyset, wantKeyset) } } func TestConvertProtoKeysetIntoHandle(t *testing.T) { h, err := keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) if err != nil { t.Fatal(err) } protoKeyset := testkeyset.KeysetMaterial(h) // This: wantHandle, err := insecurecleartextkeyset.Read(&keyset.MemReaderWriter{Keyset: protoKeyset}) if err != nil { t.Fatal(err) } // can be replaced by this: serializedKeyset, err := proto.Marshal(protoKeyset) if err != nil { t.Fatal(err) } gotHandle, err := insecurecleartextkeyset.Read( keyset.NewBinaryReader(bytes.NewBuffer(serializedKeyset))) if err != nil { t.Fatal(err) } if got, want := testkeyset.KeysetMaterial(gotHandle), testkeyset.KeysetMaterial(wantHandle); !proto.Equal(got, want) { t.Errorf("gotHandle contains %s, want %s", got, want) } } func TestConvertHandleKeysetIntoProtoKeyset(t *testing.T) { handle, err := keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) if err != nil { t.Fatal(err) } // This: writer := &keyset.MemReaderWriter{} if err := insecurecleartextkeyset.Write(handle, writer); err != nil { t.Fatal(err) } wantKeyset := writer.Keyset // can be replaced by this: gotKeyset := insecurecleartextkeyset.KeysetMaterial(handle) if !proto.Equal(gotKeyset, wantKeyset) { t.Errorf("insecurecleartextkeyset.KeysetMaterial(handle) = %v, want %v", gotKeyset, wantKeyset) } } func TestConvertHandleKeysetIntoSerializedKeyset(t *testing.T) { handle, err := keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) if err != nil { t.Fatal(err) } // This: writer := &keyset.MemReaderWriter{} if err := insecurecleartextkeyset.Write(handle, writer); err != nil { t.Fatal(err) } wantSerializedKeyset, err := proto.Marshal(writer.Keyset) if err != nil { t.Fatal(err) } // can be replaced by this: buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(handle, keyset.NewBinaryWriter(buff)); err != nil { t.Fatal(err) } gotSerializedKeyset := buff.Bytes() // Since serialization may not be deterministic, we parse the keyset and compare the protos. wantKeyset := new(tinkpb.Keyset) err = proto.Unmarshal(wantSerializedKeyset, wantKeyset) if err != nil { t.Fatal(err) } gotKeyset := new(tinkpb.Keyset) err = proto.Unmarshal(gotSerializedKeyset, gotKeyset) if err != nil { t.Fatal(err) } if !proto.Equal(gotKeyset, wantKeyset) { t.Errorf("gotKeyset = %v, want %v", gotKeyset, wantKeyset) } } func TestConvertPublicKeyProtoKeysetIntoHandle(t *testing.T) { privateHandle, err := keyset.NewHandle(signature.ECDSAP256KeyTemplate()) if err != nil { t.Fatal(err) } publicHandle, err := privateHandle.Public() if err != nil { t.Fatal(err) } protoPublicKeyset := testkeyset.KeysetMaterial(publicHandle) // This: wantHandle, err := keyset.ReadWithNoSecrets(&keyset.MemReaderWriter{Keyset: protoPublicKeyset}) if err != nil { t.Fatal(err) } // can be replaced by this: serializedKeyset, err := proto.Marshal(protoPublicKeyset) if err != nil { t.Fatal(err) } gotHandle, err := keyset.ReadWithNoSecrets( keyset.NewBinaryReader(bytes.NewBuffer(serializedKeyset))) if err != nil { t.Fatal(err) } if got, want := testkeyset.KeysetMaterial(gotHandle), testkeyset.KeysetMaterial(wantHandle); !proto.Equal(got, want) { t.Errorf("gotHandle contains %s, want %s", got, want) } } func TestConvertPublicKeysetHandleIntoProtoKeyset(t *testing.T) { privateHandle, err := keyset.NewHandle(signature.ECDSAP256KeyTemplate()) if err != nil { t.Fatal(err) } publicHandle, err := privateHandle.Public() if err != nil { t.Fatal(err) } // This: writer := &keyset.MemReaderWriter{} if err := publicHandle.WriteWithNoSecrets(writer); err != nil { t.Fatal(err) } wantKeyset := writer.Keyset // can be replaced by this: buff := &bytes.Buffer{} if err := publicHandle.WriteWithNoSecrets(keyset.NewBinaryWriter(buff)); err != nil { t.Fatal(err) } serializedKeyset := buff.Bytes() gotKeyset := new(tinkpb.Keyset) err = proto.Unmarshal(serializedKeyset, gotKeyset) if err != nil { t.Fatal(err) } if !proto.Equal(gotKeyset, wantKeyset) { t.Errorf("gotKeyset = %v, want %v", gotKeyset, wantKeyset) } } func decryptKeyset(encrypted *tinkpb.EncryptedKeyset, keysetEncryptionAEAD tink.AEAD) (*tinkpb.Keyset, error) { decrypted, err := keysetEncryptionAEAD.Decrypt(encrypted.GetEncryptedKeyset(), nil) if err != nil { return nil, err } k := new(tinkpb.Keyset) err = proto.Unmarshal(decrypted, k) if err != nil { return nil, err } return k, err } func TestConvertHandleKeysetIntoProtoEncryptedKeyset(t *testing.T) { kekHandle, err := keyset.NewHandle(aead.AES128GCMKeyTemplate()) if err != nil { t.Fatal(err) } keysetEncryptionAEAD, err := aead.New(kekHandle) if err != nil { t.Fatal(err) } handle, err := keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) if err != nil { t.Fatal(err) } // This: memWriter := &keyset.MemReaderWriter{} if err := handle.Write(memWriter, keysetEncryptionAEAD); err != nil { t.Fatal(err) } wantEncryptedKeyset := memWriter.EncryptedKeyset // can be replaced by this: buff := &bytes.Buffer{} if err := handle.Write(keyset.NewBinaryWriter(buff), keysetEncryptionAEAD); err != nil { t.Fatal(err) } serializedKeyset := buff.Bytes() gotEncryptedKeyset := new(tinkpb.EncryptedKeyset) err = proto.Unmarshal(serializedKeyset, gotEncryptedKeyset) if err != nil { t.Fatal(err) } wantKeyset, err := decryptKeyset(wantEncryptedKeyset, keysetEncryptionAEAD) if err != nil { t.Fatal(err) } gotKeyset, err := decryptKeyset(gotEncryptedKeyset, keysetEncryptionAEAD) if err != nil { t.Fatal(err) } if !proto.Equal(gotKeyset, wantKeyset) { t.Errorf("gotKeyset = %v, want %v", gotKeyset, wantKeyset) } } func TestConvertProtoEncryptedKeysetIntoHandle(t *testing.T) { kekHandle, err := keyset.NewHandle(aead.AES128GCMKeyTemplate()) if err != nil { t.Fatal(err) } keysetEncryptionAEAD, err := aead.New(kekHandle) if err != nil { t.Fatal(err) } handle, err := keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) if err != nil { t.Fatal(err) } buff := &bytes.Buffer{} if err := handle.Write(keyset.NewBinaryWriter(buff), keysetEncryptionAEAD); err != nil { t.Fatal(err) } encryptedKeyset := new(tinkpb.EncryptedKeyset) err = proto.Unmarshal(buff.Bytes(), encryptedKeyset) if err != nil { t.Fatal(err) } // This: memReader := &keyset.MemReaderWriter{ EncryptedKeyset: encryptedKeyset, } wantHandle, err := keyset.Read(memReader, keysetEncryptionAEAD) if err != nil { t.Fatal(err) } // can be replaced by this: serializedKeyset, err := proto.Marshal(encryptedKeyset) if err != nil { t.Fatal(err) } gotHandle, err := keyset.Read( keyset.NewBinaryReader(bytes.NewBuffer(serializedKeyset)), keysetEncryptionAEAD) if err != nil { t.Fatal(err) } if got, want := testkeyset.KeysetMaterial(gotHandle), testkeyset.KeysetMaterial(wantHandle); !proto.Equal(got, want) { t.Errorf("gotHandle contains %s, want %s", got, want) } } ================================================ FILE: go/keyset/option.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyset import "fmt" // Option is used to pass options for a keyset handle. type Option interface { set(k *Handle) error } type option func(*Handle) error func (o option) set(h *Handle) error { return o(h) } // WithAnnotations adds monitoring annotations to a keyset handle. func WithAnnotations(annotations map[string]string) Option { return option(func(h *Handle) error { if h.annotations != nil { return fmt.Errorf("keyset already contains annotations") } h.annotations = annotations return nil }) } func applyOptions(h *Handle, opts ...Option) error { for _, opt := range opts { if err := opt.set(h); err != nil { return err } } return nil } ================================================ FILE: go/keyset/reader.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyset import tinkpb "github.com/google/tink/go/proto/tink_go_proto" // Reader knows how to read a Keyset or an EncryptedKeyset from some source. // In order to turn a Reader into a KeysetHandle for use, callers must use // insecure.KeysetHandle or by keyset.Read (with encryption). type Reader interface { // Read returns a (cleartext) Keyset object from the underlying source. Read() (*tinkpb.Keyset, error) // ReadEncrypted returns an EncryptedKeyset object from the underlying source. ReadEncrypted() (*tinkpb.EncryptedKeyset, error) } ================================================ FILE: go/keyset/validation.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyset import ( "fmt" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // ValidateKeyVersion checks whether the given version is valid. The version is valid // only if it is the range [0..maxExpected] func ValidateKeyVersion(version, maxExpected uint32) error { if version > maxExpected { return fmt.Errorf("key has version %v; only keys with version in range [0..%v] are supported", version, maxExpected) } return nil } // Validate validates the given key set. // Returns nil if it is valid; an error otherwise. func Validate(keyset *tinkpb.Keyset) error { if keyset == nil { return fmt.Errorf("Validate() called with nil") } if len(keyset.Key) == 0 { return fmt.Errorf("empty keyset") } primaryKeyID := keyset.PrimaryKeyId hasPrimaryKey := false numEnabledKeys := 0 for _, key := range keyset.Key { if err := validateKey(key); err != nil { return err } if key.Status != tinkpb.KeyStatusType_ENABLED { continue } if key.KeyId == primaryKeyID { if hasPrimaryKey { return fmt.Errorf("keyset contains multiple primary keys") } hasPrimaryKey = true } numEnabledKeys++ } if numEnabledKeys == 0 { return fmt.Errorf("keyset must contain at least one ENABLED key") } if !hasPrimaryKey { return fmt.Errorf("keyset does not contain a valid primary key") } return nil } /* validateKey validates the given key. Returns nil if it is valid; an error otherwise. */ func validateKey(key *tinkpb.Keyset_Key) error { if key == nil { return fmt.Errorf("ValidateKey() called with nil") } if key.KeyData == nil { return fmt.Errorf("key %d has no key data", key.KeyId) } if key.OutputPrefixType != tinkpb.OutputPrefixType_TINK && key.OutputPrefixType != tinkpb.OutputPrefixType_LEGACY && key.OutputPrefixType != tinkpb.OutputPrefixType_RAW && key.OutputPrefixType != tinkpb.OutputPrefixType_CRUNCHY { return fmt.Errorf("key %d has unknown prefix", key.KeyId) } if key.Status != tinkpb.KeyStatusType_ENABLED && key.Status != tinkpb.KeyStatusType_DISABLED && key.Status != tinkpb.KeyStatusType_DESTROYED { return fmt.Errorf("key %d has unknown status", key.KeyId) } return nil } ================================================ FILE: go/keyset/validation_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyset_test import ( "testing" "github.com/google/tink/go/keyset" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestValidateKeyVersion(t *testing.T) { if keyset.ValidateKeyVersion(2, 1) == nil || keyset.ValidateKeyVersion(1, 1) != nil || keyset.ValidateKeyVersion(1, 2) != nil { t.Errorf("incorrect version validation") } } func TestValidate(t *testing.T) { var err error // nil input if err = keyset.Validate(nil); err == nil { t.Errorf("expect an error when keyset is nil") } // empty keyset var emptyKeys []*tinkpb.Keyset_Key if err = keyset.Validate(testutil.NewKeyset(1, emptyKeys)); err == nil { t.Errorf("expect an error when keyset is empty") } // no primary key keys := []*tinkpb.Keyset_Key{ testutil.NewDummyKey(1, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_TINK), } if err = keyset.Validate(testutil.NewKeyset(2, keys)); err == nil { t.Errorf("expect an error when there is no primary key") } // primary key is disabled keys = []*tinkpb.Keyset_Key{ testutil.NewDummyKey(1, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_TINK), testutil.NewDummyKey(2, tinkpb.KeyStatusType_DISABLED, tinkpb.OutputPrefixType_LEGACY), } if err = keyset.Validate(testutil.NewKeyset(2, keys)); err == nil { t.Errorf("expect an error when primary key is disabled") } // multiple primary keys keys = []*tinkpb.Keyset_Key{ testutil.NewDummyKey(1, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_TINK), testutil.NewDummyKey(1, tinkpb.KeyStatusType_ENABLED, tinkpb.OutputPrefixType_LEGACY), } if err = keyset.Validate(testutil.NewKeyset(1, keys)); err == nil { t.Errorf("expect an error when there are multiple primary keys") } // invalid keys invalidKeys := generateInvalidKeys() for i, key := range invalidKeys { err = keyset.Validate(testutil.NewKeyset(1, []*tinkpb.Keyset_Key{key})) if err == nil { t.Errorf("expect an error when validate invalid key %d", i) } } //no primary keys keys = []*tinkpb.Keyset_Key{ testutil.NewDummyKey(1, tinkpb.KeyStatusType_DISABLED, tinkpb.OutputPrefixType_TINK), testutil.NewDummyKey(1, tinkpb.KeyStatusType_DISABLED, tinkpb.OutputPrefixType_LEGACY), } if err = keyset.Validate(testutil.NewKeyset(1, keys)); err == nil { t.Errorf("expect an error when there are no primary keys") } // public key only keys = []*tinkpb.Keyset_Key{ testutil.NewKey(testutil.NewKeyData(testutil.EciesAeadHkdfPublicKeyTypeURL, random.GetRandomBytes(10), tinkpb.KeyData_ASYMMETRIC_PUBLIC), tinkpb.KeyStatusType_ENABLED, 1, tinkpb.OutputPrefixType_TINK), } if err = keyset.Validate(testutil.NewKeyset(1, keys)); err != nil { t.Errorf("valid test failed when using public key only: %v", err) } // private key keys = []*tinkpb.Keyset_Key{ testutil.NewKey(testutil.NewKeyData(testutil.EciesAeadHkdfPublicKeyTypeURL, random.GetRandomBytes(10), tinkpb.KeyData_ASYMMETRIC_PUBLIC), tinkpb.KeyStatusType_ENABLED, 1, tinkpb.OutputPrefixType_TINK), testutil.NewKey(testutil.NewKeyData(testutil.EciesAeadHkdfPrivateKeyTypeURL, random.GetRandomBytes(10), tinkpb.KeyData_ASYMMETRIC_PRIVATE), tinkpb.KeyStatusType_ENABLED, 1, tinkpb.OutputPrefixType_TINK), } if err = keyset.Validate(testutil.NewKeyset(1, keys)); err == nil { t.Errorf("expect an error when there are keydata other than public") } } func generateInvalidKeys() []*tinkpb.Keyset_Key { return []*tinkpb.Keyset_Key{ nil, // nil KeyData testutil.NewKey(nil, tinkpb.KeyStatusType_ENABLED, 1, tinkpb.OutputPrefixType_TINK), // unknown status testutil.NewKey(new(tinkpb.KeyData), tinkpb.KeyStatusType_UNKNOWN_STATUS, 1, tinkpb.OutputPrefixType_TINK), // unknown prefix testutil.NewKey(new(tinkpb.KeyData), tinkpb.KeyStatusType_ENABLED, 1, tinkpb.OutputPrefixType_UNKNOWN_PREFIX), } } ================================================ FILE: go/keyset/writer.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keyset import tinkpb "github.com/google/tink/go/proto/tink_go_proto" // Writer knows how to write a Keyset or an EncryptedKeyset to some source. type Writer interface { // Write keyset to some storage system. Write(Keyset *tinkpb.Keyset) error // Write EncryptedKeyset to some storage system. WriteEncrypted(keyset *tinkpb.EncryptedKeyset) error } ================================================ FILE: go/kwp/subtle/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep go_library( name = "subtle", srcs = ["kwp.go"], importpath = "github.com/google/tink/go/kwp/subtle", visibility = ["//visibility:public"], ) go_test( name = "subtle_test", srcs = ["kwp_test.go"], data = ["//testdata/testvectors:keywrap"], deps = [ ":subtle", "//subtle/random", "//testutil", ], ) alias( name = "go_default_library", actual = ":subtle", visibility = ["//:__subpackages__"], ) ================================================ FILE: go/kwp/subtle/kwp.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package subtle implements the key wrapping primitive KWP defined in // NIST SP 800 38f. // // The same encryption mode is also defined in RFC 5649. The NIST document is // used here as a primary reference, since it contains a security analysis and // further recommendations. In particular, Section 8 of NIST SP 800 38f // suggests that the allowed key sizes may be restricted. The implementation in // this package requires that the key sizes are in the range MinWrapSize and // MaxWrapSize. // // The minimum of 16 bytes has been chosen, because 128 bit keys are the // smallest key sizes used in tink. Additionally, wrapping short keys with KWP // does not use the function W and hence prevents using security arguments // based on the assumption that W is a strong pseudorandom. One consequence of // using a strong pseudorandom permutation as an underlying function is that // leaking partial information about decrypted bytes is not useful for an // attack. // // The upper bound for the key size is somewhat arbitrary. Setting an upper // bound is motivated by the analysis in section A.4 of NIST SP 800 38f: // forgery of long messages is simpler than forgery of short messages. package subtle import ( "crypto/aes" "crypto/cipher" "encoding/binary" "fmt" "math" // Placeholder for internal crypto/cipher allowlist, please ignore. ) const ( // MinWrapSize is the smallest key byte length that may be wrapped. MinWrapSize = 16 // MaxWrapSize is the largest key byte length that may be wrapped. MaxWrapSize = 8192 roundCount = 6 ivPrefix = uint32(0xA65959A6) ) // KWP is an implementation of an AES-KWP key wrapping cipher. type KWP struct { block cipher.Block } // NewKWP returns a KWP instance. // // The key argument should be the AES wrapping key, either 16 or 32 bytes // to select AES-128 or AES-256. func NewKWP(wrappingKey []byte) (*KWP, error) { switch len(wrappingKey) { default: return nil, fmt.Errorf("kwp: invalid AES key size; want 16 or 32, got %d", len(wrappingKey)) case 16, 32: block, err := aes.NewCipher(wrappingKey) if err != nil { return nil, fmt.Errorf("kwp: error building AES cipher: %v", err) } return &KWP{block: block}, nil } } // wrappingSize computes the byte length of the ciphertext output for the // provided plaintext input. func wrappingSize(inputSize int) int { paddingSize := 7 - (inputSize+7)%8 return inputSize + paddingSize + 8 } // computeW computes the pseudorandom permutation W over the IV concatenated // with zero-padded key material. func (kwp *KWP) computeW(iv, key []byte) ([]byte, error) { // Checks the parameter sizes for which W is defined. // Note that the caller ensures stricter limits. if len(key) <= 8 || len(key) > math.MaxInt32-16 || len(iv) != 8 { return nil, fmt.Errorf("kwp: computeW called with invalid parameters") } data := make([]byte, wrappingSize(len(key))) copy(data, iv) copy(data[8:], key) blockCount := len(data)/8 - 1 buf := make([]byte, 16) copy(buf, data[:8]) for i := 0; i < roundCount; i++ { for j := 0; j < blockCount; j++ { copy(buf[8:], data[8*(j+1):]) kwp.block.Encrypt(buf, buf) // xor the round constant in big endian order // to the left half of the buffer roundConst := uint(i*blockCount + j + 1) for b := 0; b < 4; b++ { buf[7-b] ^= byte(roundConst & 0xFF) roundConst >>= 8 } copy(data[8*(j+1):], buf[8:]) } } copy(data[:8], buf) return data, nil } // invertW computes the inverse of the pseudorandom permutation W. Note that // invertW does not perform an integrity check. func (kwp *KWP) invertW(wrapped []byte) ([]byte, error) { // Checks the input size for which invertW is defined. // Note that the caller ensures stricter limits. if len(wrapped) < 24 || len(wrapped)%8 != 0 { return nil, fmt.Errorf("kwp: incorrect data size") } data := make([]byte, len(wrapped)) copy(data, wrapped) blockCount := len(data)/8 - 1 buf := make([]byte, 16) copy(buf, data[:8]) for i := roundCount - 1; i >= 0; i-- { for j := blockCount - 1; j >= 0; j-- { copy(buf[8:], data[8*(j+1):]) // xor the round constant in big endian order // to the left half of the buffer roundConst := uint(i*blockCount + j + 1) for b := 0; b < 4; b++ { buf[7-b] ^= byte(roundConst & 0xFF) roundConst >>= 8 } kwp.block.Decrypt(buf, buf) copy(data[8*(j+1):], buf[8:]) } } copy(data, buf[:8]) return data, nil } // Wrap wraps the provided key material. func (kwp *KWP) Wrap(data []byte) ([]byte, error) { if len(data) < MinWrapSize { return nil, fmt.Errorf("kwp: key size to wrap too small") } if len(data) > MaxWrapSize { return nil, fmt.Errorf("kwp: key size to wrap too large") } iv := make([]byte, 8) binary.BigEndian.PutUint32(iv, ivPrefix) binary.BigEndian.PutUint32(iv[4:], uint32(len(data))) return kwp.computeW(iv, data) } var errIntegrity = fmt.Errorf("kwp: unwrap failed integrity check") // Unwrap unwraps a wrapped key. func (kwp *KWP) Unwrap(data []byte) ([]byte, error) { if len(data) < wrappingSize(MinWrapSize) { return nil, fmt.Errorf("kwp: wrapped key size too small") } if len(data) > wrappingSize(MaxWrapSize) { return nil, fmt.Errorf("kwp: wrapped key size too large") } if len(data)%8 != 0 { return nil, fmt.Errorf("kwp: wrapped key size must be a multiple of 8 bytes") } unwrapped, err := kwp.invertW(data) if err != nil { return nil, err } // Check the IV and padding. // W has been designed to be strong pseudorandom permutation, so // leaking information about improperly padded keys would not be a // vulnerability. This means we don't have to go to extra lengths to // ensure that the integrity checks run in constant time. if binary.BigEndian.Uint32(unwrapped) != ivPrefix { return nil, errIntegrity } encodedSize := int(binary.BigEndian.Uint32(unwrapped[4:])) if encodedSize < 0 || wrappingSize(encodedSize) != len(unwrapped) { return nil, errIntegrity } for i := 8 + encodedSize; i < len(unwrapped); i++ { if unwrapped[i] != 0 { return nil, errIntegrity } } return unwrapped[8 : 8+encodedSize], nil } ================================================ FILE: go/kwp/subtle/kwp_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "bytes" "encoding/hex" "fmt" "testing" "github.com/google/tink/go/kwp/subtle" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" ) func TestWrapUnwrap(t *testing.T) { kek := random.GetRandomBytes(16) cipher, err := subtle.NewKWP(kek) if err != nil { t.Fatalf("failed to make kwp, error: %v", err) } for i := uint32(16); i < 128; i++ { t.Run(fmt.Sprintf("MessageSize%d", i), func(t *testing.T) { toWrap := random.GetRandomBytes(i) wrapped, err := cipher.Wrap(toWrap) if err != nil { t.Fatalf("failed to wrap, error: %v", err) } unwrapped, err := cipher.Unwrap(wrapped) if err != nil { t.Fatalf("failed to unwrap, error: %v", err) } if !bytes.Equal(toWrap, unwrapped) { t.Error("unwrapped doesn't match original key") } }) } } func TestKeySizes(t *testing.T) { for i := 0; i < 255; i++ { expectSuccess := i == 16 || i == 32 t.Run(fmt.Sprintf("KeySize%d", i), func(t *testing.T) { _, err := subtle.NewKWP(make([]byte, i)) if expectSuccess && err != nil { t.Errorf("failed to create KWP: %v", err) } if !expectSuccess && err == nil { t.Error("created KWP with invalid key size") } }) } } func TestInvalidWrappingSizes(t *testing.T) { kek := random.GetRandomBytes(16) cipher, err := subtle.NewKWP(kek) if err != nil { t.Fatalf("failed to make kwp, error: %v", err) } for i := 0; i < 16; i++ { t.Run(fmt.Sprintf("KeySize%d", i), func(t *testing.T) { if _, err := cipher.Wrap(make([]byte, i)); err == nil { t.Error("wrapped a short key") } }) } } type KwpCase struct { testutil.WycheproofCase Key string `json:"key"` Message string `json:"msg"` Ciphertext string `json:"ct"` } type KwpGroup struct { testutil.WycheproofGroup KeySize int `json:"keySize"` Tests []*KwpCase `json:"tests"` } type KwpSuite struct { testutil.WycheproofSuite Groups []*KwpGroup `json:"testGroups"` } func TestWycheproofCases(t *testing.T) { testutil.SkipTestIfTestSrcDirIsNotSet(t) suite := new(KwpSuite) if err := testutil.PopulateSuite(suite, "kwp_test.json"); err != nil { t.Fatalf("testutil.PopulateSuite: %v", err) } for _, group := range suite.Groups { if group.KeySize == 192 { continue } for _, test := range group.Tests { caseName := fmt.Sprintf("%s-%s(%d):Case-%d", suite.Algorithm, group.Type, group.KeySize, test.CaseID) t.Run(caseName, func(t *testing.T) { runWycheproofCase(t, test) }) } } } func runWycheproofCase(t *testing.T, testCase *KwpCase) { kek, err := hex.DecodeString(testCase.Key) if err != nil { t.Fatalf("hex.DecodeString(testCase.Key) => %v", err) } msg, err := hex.DecodeString(testCase.Message) if err != nil { t.Fatalf("hex.DecodeString(testCase.Message) => %v", err) } ct, err := hex.DecodeString(testCase.Ciphertext) if err != nil { t.Fatalf("hex.DecodeString(testCase.Ciphertext) => %v", err) } cipher, err := subtle.NewKWP(kek) if err != nil { switch testCase.Result { case "valid": t.Fatalf("cannot create kwp, error: %v", err) case "invalid", "acceptable": return } } wrapped, err := cipher.Wrap(msg) switch testCase.Result { case "valid": if err != nil { t.Errorf("cannot wrap, error: %v", err) } else if !bytes.Equal(ct, wrapped) { t.Error("wrapped key mismatches test vector") } case "invalid": if err == nil && bytes.Equal(ct, wrapped) { t.Error("no error and wrapped key matches test vector for invalid case") } case "acceptable": if err == nil && !bytes.Equal(ct, wrapped) { t.Error("no error and wrapped key mismatches test vector for acceptable case") } } unwrapped, err := cipher.Unwrap(ct) switch testCase.Result { case "valid": if err != nil { t.Errorf("cannot unwrap, error: %v", err) } else if !bytes.Equal(msg, unwrapped) { t.Error("unwrapped key mismatches test vector") } case "invalid": if err == nil { t.Error("no error unwrapping invalid case") } case "acceptable": if err == nil && !bytes.Equal(msg, unwrapped) { t.Error("no error and unwrapped key mismatches plaintext") } } } ================================================ FILE: go/mac/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep licenses(["notice"]) # keep go_library( name = "mac", srcs = [ "aes_cmac_key_manager.go", "hmac_key_manager.go", "mac.go", "mac_factory.go", "mac_key_templates.go", ], importpath = "github.com/google/tink/go/mac", visibility = ["//visibility:public"], deps = [ "//core/cryptofmt", "//core/primitiveset", "//core/registry", "//internal/internalregistry", "//internal/monitoringutil", "//internal/tinkerror", "//keyset", "//mac/subtle", "//monitoring", "//proto/aes_cmac_go_proto", "//proto/common_go_proto", "//proto/hmac_go_proto", "//proto/tink_go_proto", "//subtle/random", "//tink", "@org_golang_google_protobuf//proto", ], ) go_test( name = "mac_test", srcs = [ "aes_cmac_key_manager_test.go", "hmac_key_manager_test.go", "mac_benchmark_test.go", "mac_factory_test.go", "mac_init_test.go", "mac_key_templates_test.go", "mac_test.go", ], deps = [ ":mac", "//core/cryptofmt", "//core/registry", "//insecurecleartextkeyset", "//internal/internalregistry", "//internal/testing/stubkeymanager", "//keyset", "//mac/internal/mactest", "//mac/subtle", "//monitoring", "//proto/aes_cmac_go_proto", "//proto/common_go_proto", "//proto/hmac_go_proto", "//proto/tink_go_proto", "//signature", "//subtle/random", "//testing/fakemonitoring", "//testkeyset", "//testutil", "//tink", "@com_github_google_go_cmp//cmp", "@com_github_google_go_cmp//cmp/cmpopts", "@org_golang_google_protobuf//proto", ], ) alias( name = "go_default_library", actual = ":mac", visibility = ["//visibility:public"], ) ================================================ FILE: go/mac/aes_cmac_key_manager.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package mac import ( "errors" "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/keyset" "github.com/google/tink/go/mac/subtle" "github.com/google/tink/go/subtle/random" cmacpb "github.com/google/tink/go/proto/aes_cmac_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( cmacKeyVersion = 0 cmacTypeURL = "type.googleapis.com/google.crypto.tink.AesCmacKey" ) var errInvalidCMACKey = errors.New("aes_cmac_key_manager: invalid key") var errInvalidCMACKeyFormat = errors.New("aes_cmac_key_manager: invalid key format") // cmacKeyManager generates new AES-CMAC keys and produces new instances of AES-CMAC. type aescmacKeyManager struct{} // Primitive constructs a AES-CMAC instance for the given serialized CMACKey. func (km *aescmacKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidCMACKey } key := new(cmacpb.AesCmacKey) if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errInvalidCMACKey } if err := km.validateKey(key); err != nil { return nil, err } cmac, err := subtle.NewAESCMAC(key.KeyValue, key.GetParams().GetTagSize()) if err != nil { return nil, err } return cmac, nil } // NewKey generates a new AesCmacKey according to specification in the given AesCmacKeyFormat. func (km *aescmacKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errInvalidCMACKeyFormat } keyFormat := new(cmacpb.AesCmacKeyFormat) if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, errInvalidCMACKeyFormat } if err := km.validateKeyFormat(keyFormat); err != nil { return nil, fmt.Errorf("aes_cmac_key_manager: invalid key format: %s", err) } keyValue := random.GetRandomBytes(keyFormat.KeySize) return &cmacpb.AesCmacKey{ Version: cmacKeyVersion, Params: keyFormat.Params, KeyValue: keyValue, }, nil } // NewKeyData generates a new KeyData according to specification in the given // serialized AesCmacKeyFormat. This should be used solely by the key management API. func (km *aescmacKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { key, err := km.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, errInvalidCMACKeyFormat } return &tinkpb.KeyData{ TypeUrl: cmacTypeURL, Value: serializedKey, KeyMaterialType: tinkpb.KeyData_SYMMETRIC, }, nil } // DoesSupport checks whether this KeyManager supports the given key type. func (km *aescmacKeyManager) DoesSupport(typeURL string) bool { return typeURL == cmacTypeURL } // TypeURL returns the type URL of keys managed by this KeyManager. func (km *aescmacKeyManager) TypeURL() string { return cmacTypeURL } // validateKey validates the given AesCmacKey. It only validates the version of the // key because other parameters will be validated in primitive construction. func (km *aescmacKeyManager) validateKey(key *cmacpb.AesCmacKey) error { err := keyset.ValidateKeyVersion(key.Version, cmacKeyVersion) if err != nil { return fmt.Errorf("aes_cmac_key_manager: invalid version: %s", err) } keySize := uint32(len(key.KeyValue)) return subtle.ValidateCMACParams(keySize, key.GetParams().GetTagSize()) } // validateKeyFormat validates the given AesCmacKeyFormat func (km *aescmacKeyManager) validateKeyFormat(format *cmacpb.AesCmacKeyFormat) error { return subtle.ValidateCMACParams(format.KeySize, format.GetParams().GetTagSize()) } ================================================ FILE: go/mac/aes_cmac_key_manager_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package mac_test import ( "encoding/hex" "fmt" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" subtleMac "github.com/google/tink/go/mac/subtle" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" cmacpb "github.com/google/tink/go/proto/aes_cmac_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestGetPrimitiveCMACBasic(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESCMACTypeURL) if err != nil { t.Errorf("AESCMAC key manager not found: %s", err) } testKeys := genValidCMACKeys() for i := 0; i < len(testKeys); i++ { serializedKey, err := proto.Marshal(testKeys[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } p, err := km.Primitive(serializedKey) if err != nil { t.Errorf("unexpected error in test case %d: %s", i, err) } if err := validateCMACPrimitive(p, testKeys[i]); err != nil { t.Errorf("%s", err) } } } func TestGetPrimitiveCMACWithInvalidInput(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESCMACTypeURL) if err != nil { t.Errorf("cannot obtain AESCMAC key manager: %s", err) } // invalid key testKeys := genInvalidCMACKeys() for i := 0; i < len(testKeys); i++ { serializedKey, err := proto.Marshal(testKeys[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := km.Primitive(serializedKey); err == nil { t.Errorf("expect an error in test case %d", i) } } if _, err := km.Primitive(nil); err == nil { t.Errorf("expect an error when input is nil") } // empty input if _, err := km.Primitive([]byte{}); err == nil { t.Errorf("expect an error when input is empty") } } func TestNewKeyCMACMultipleTimes(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESCMACTypeURL) if err != nil { t.Errorf("cannot obtain AESCMAC key manager: %s", err) } serializedFormat, err := proto.Marshal(testutil.NewAESCMACKeyFormat(16)) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } keys := make(map[string]bool) nTest := 26 for i := 0; i < nTest; i++ { key, err := km.NewKey(serializedFormat) if err != nil { t.Fatalf("km.NewKey() err = %q, want nil", err) } serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } keys[string(serializedKey)] = true keyData, err := km.NewKeyData(serializedFormat) if err != nil { t.Fatalf("km.NewKeyData() err = %q, want nil", err) } serializedKey = keyData.Value keys[string(serializedKey)] = true } if len(keys) != nTest*2 { t.Errorf("key is repeated") } } func TestNewKeyCMACBasic(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESCMACTypeURL) if err != nil { t.Errorf("cannot obtain AESCMAC key manager: %s", err) } testFormats := genValidCMACKeyFormats() for i := 0; i < len(testFormats); i++ { serializedFormat, err := proto.Marshal(testFormats[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } key, err := km.NewKey(serializedFormat) if err != nil { t.Errorf("unexpected error in test case %d: %s", i, err) } if err := validateCMACKey(testFormats[i], key.(*cmacpb.AesCmacKey)); err != nil { t.Errorf("%s", err) } } } func TestNewKeyCMACWithInvalidInput(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESCMACTypeURL) if err != nil { t.Errorf("cannot obtain AESCMAC key manager: %s", err) } // invalid key formats testFormats := genInvalidCMACKeyFormats() for i := 0; i < len(testFormats); i++ { serializedFormat, err := proto.Marshal(testFormats[i]) if err != nil { fmt.Println("Error!") } if _, err := km.NewKey(serializedFormat); err == nil { t.Errorf("expect an error in test case %d: %s", i, err) } } if _, err := km.NewKey(nil); err == nil { t.Errorf("expect an error when input is nil") } // empty input if _, err := km.NewKey([]byte{}); err == nil { t.Errorf("expect an error when input is empty") } } func TestNewKeyDataCMACBasic(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESCMACTypeURL) if err != nil { t.Errorf("cannot obtain AESCMAC key manager: %s", err) } testFormats := genValidCMACKeyFormats() for i := 0; i < len(testFormats); i++ { serializedFormat, err := proto.Marshal(testFormats[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } keyData, err := km.NewKeyData(serializedFormat) if err != nil { t.Errorf("unexpected error in test case %d: %s", i, err) } if keyData.TypeUrl != testutil.AESCMACTypeURL { t.Errorf("incorrect type url in test case %d", i) } if keyData.KeyMaterialType != tinkpb.KeyData_SYMMETRIC { t.Errorf("incorrect key material type in test case %d", i) } key := new(cmacpb.AesCmacKey) if err := proto.Unmarshal(keyData.Value, key); err != nil { t.Errorf("invalid key value") } if err := validateCMACKey(testFormats[i], key); err != nil { t.Errorf("invalid key") } } } func TestNewKeyDataCMACWithInvalidInput(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESCMACTypeURL) if err != nil { t.Errorf("AESCMAC key manager not found: %s", err) } // invalid key formats testFormats := genInvalidCMACKeyFormats() for i := 0; i < len(testFormats); i++ { serializedFormat, err := proto.Marshal(testFormats[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := km.NewKeyData(serializedFormat); err == nil { t.Errorf("expect an error in test case %d", i) } } // nil input if _, err := km.NewKeyData(nil); err == nil { t.Errorf("expect an error when input is nil") } } func TestDoesSupportCMAC(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESCMACTypeURL) if err != nil { t.Errorf("AESCMAC key manager not found: %s", err) } if !km.DoesSupport(testutil.AESCMACTypeURL) { t.Errorf("AESCMACKeyManager must support %s", testutil.AESCMACTypeURL) } if km.DoesSupport("some bad type") { t.Errorf("AESCMACKeyManager must support only %s", testutil.AESCMACTypeURL) } } func TestTypeURLCMAC(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESCMACTypeURL) if err != nil { t.Errorf("AESCMAC key manager not found: %s", err) } if km.TypeURL() != testutil.AESCMACTypeURL { t.Errorf("incorrect GetKeyType()") } } func genInvalidCMACKeys() []proto.Message { badVersionKey := testutil.NewAESCMACKey(16) badVersionKey.Version++ shortKey := testutil.NewAESCMACKey(16) shortKey.KeyValue = []byte{1, 1} nilParams := testutil.NewAESCMACKey(16) nilParams.Params = nil return []proto.Message{ // not a AESCMACKey testutil.NewAESCMACParams(16), // bad version badVersionKey, // tag size too big testutil.NewAESCMACKey(17), // tag size too small testutil.NewAESCMACKey(1), // key too short shortKey, // params field is unset nilParams, } } func genInvalidCMACKeyFormats() []proto.Message { shortKeyFormat := testutil.NewAESCMACKeyFormat(16) shortKeyFormat.KeySize = 1 nilParams := testutil.NewAESCMACKeyFormat(16) nilParams.Params = nil return []proto.Message{ // not a AESCMACKeyFormat testutil.NewAESCMACParams(16), // tag size too big testutil.NewAESCMACKeyFormat(17), // tag size too small testutil.NewAESCMACKeyFormat(1), // key too short shortKeyFormat, // params field is unset nilParams, } } func genValidCMACKeyFormats() []*cmacpb.AesCmacKeyFormat { return []*cmacpb.AesCmacKeyFormat{ testutil.NewAESCMACKeyFormat(10), testutil.NewAESCMACKeyFormat(16), } } func genValidCMACKeys() []*cmacpb.AesCmacKey { return []*cmacpb.AesCmacKey{ testutil.NewAESCMACKey(10), testutil.NewAESCMACKey(16), } } // Checks whether the given AESCMACKey matches the given key AESCMACKeyFormat func validateCMACKey(format *cmacpb.AesCmacKeyFormat, key *cmacpb.AesCmacKey) error { if format.KeySize != uint32(len(key.KeyValue)) || key.Params.TagSize != format.Params.TagSize { return fmt.Errorf("key format and generated key do not match") } p, err := subtleMac.NewAESCMAC(key.KeyValue, key.Params.TagSize) if err != nil { return fmt.Errorf("cannot create primitive from key: %s", err) } return validateCMACPrimitive(p, key) } // validateCMACPrimitive checks whether the given primitive matches the given AESCMACKey func validateCMACPrimitive(p any, key *cmacpb.AesCmacKey) error { cmacPrimitive := p.(*subtleMac.AESCMAC) keyPrimitive, err := subtleMac.NewAESCMAC(key.KeyValue, key.Params.TagSize) if err != nil { return fmt.Errorf("Could not create AES CMAC with key material %q and tag size %d: %s", hex.EncodeToString(key.KeyValue), key.Params.TagSize, err) } data := random.GetRandomBytes(20) mac, err := cmacPrimitive.ComputeMAC(data) if err != nil { return fmt.Errorf("mac computation failed: %s", err) } keyMac, err := keyPrimitive.ComputeMAC(data) if err != nil { return fmt.Errorf("mac computation with provided key failed: %s", err) } if err = cmacPrimitive.VerifyMAC(mac, data); err != nil { return fmt.Errorf("mac self verification failed: %s", err) } if err = cmacPrimitive.VerifyMAC(keyMac, data); err != nil { return fmt.Errorf("mac computed with the provided key could not be verified: %s", err) } if err = keyPrimitive.VerifyMAC(mac, data); err != nil { return fmt.Errorf("mac could not be verified by primitive using the provided key: %s", err) } if err = keyPrimitive.VerifyMAC(keyMac, data); err != nil { return fmt.Errorf("mac self verification of mac created with the provided key failed: %s", err) } return nil } ================================================ FILE: go/mac/hmac_key_manager.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package mac import ( "errors" "fmt" "io" "google.golang.org/protobuf/proto" "github.com/google/tink/go/keyset" "github.com/google/tink/go/mac/subtle" "github.com/google/tink/go/subtle/random" commonpb "github.com/google/tink/go/proto/common_go_proto" hmacpb "github.com/google/tink/go/proto/hmac_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( hmacKeyVersion = 0 hmacTypeURL = "type.googleapis.com/google.crypto.tink.HmacKey" ) var errInvalidHMACKey = errors.New("hmac_key_manager: invalid key") var errInvalidHMACKeyFormat = errors.New("hmac_key_manager: invalid key format") // hmacKeyManager generates new HMAC keys and produces new instances of HMAC. type hmacKeyManager struct{} // Primitive constructs a HMAC instance for the given serialized HMACKey. func (km *hmacKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidHMACKey } key := new(hmacpb.HmacKey) if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errInvalidHMACKey } if err := km.validateKey(key); err != nil { return nil, err } hash := commonpb.HashType_name[int32(key.GetParams().GetHash())] hmac, err := subtle.NewHMAC(hash, key.KeyValue, key.GetParams().GetTagSize()) if err != nil { return nil, err } return hmac, nil } // NewKey generates a new HMACKey according to specification in the given HMACKeyFormat. func (km *hmacKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errInvalidHMACKeyFormat } keyFormat := new(hmacpb.HmacKeyFormat) if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, errInvalidHMACKeyFormat } if err := km.validateKeyFormat(keyFormat); err != nil { return nil, fmt.Errorf("hmac_key_manager: invalid key format: %s", err) } keyValue := random.GetRandomBytes(keyFormat.KeySize) return &hmacpb.HmacKey{ Version: hmacKeyVersion, Params: keyFormat.Params, KeyValue: keyValue, }, nil } // NewKeyData generates a new KeyData according to specification in the given // serialized HMACKeyFormat. This should be used solely by the key management API. func (km *hmacKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { key, err := km.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, errInvalidHMACKeyFormat } return &tinkpb.KeyData{ TypeUrl: hmacTypeURL, Value: serializedKey, KeyMaterialType: km.KeyMaterialType(), }, nil } // DoesSupport checks whether this KeyManager supports the given key type. func (km *hmacKeyManager) DoesSupport(typeURL string) bool { return typeURL == hmacTypeURL } // TypeURL returns the type URL of keys managed by this KeyManager. func (km *hmacKeyManager) TypeURL() string { return hmacTypeURL } // KeyMaterialType returns the key material type of this key manager. func (km *hmacKeyManager) KeyMaterialType() tinkpb.KeyData_KeyMaterialType { return tinkpb.KeyData_SYMMETRIC } // DeriveKey derives a new key from serializedKeyFormat and pseudorandomness. func (km *hmacKeyManager) DeriveKey(serializedKeyFormat []byte, pseudorandomness io.Reader) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errInvalidHMACKeyFormat } keyFormat := new(hmacpb.HmacKeyFormat) if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, errInvalidHMACKeyFormat } if err := km.validateKeyFormat(keyFormat); err != nil { return nil, fmt.Errorf("hmac_key_manager: invalid key format: %v", err) } if err := keyset.ValidateKeyVersion(keyFormat.GetVersion(), hmacKeyVersion); err != nil { return nil, fmt.Errorf("hmac_key_manager: invalid key version: %s", err) } keyValue := make([]byte, keyFormat.GetKeySize()) if _, err := io.ReadFull(pseudorandomness, keyValue); err != nil { return nil, fmt.Errorf("hmac_key_manager: not enough pseudorandomness given") } return &hmacpb.HmacKey{ Version: hmacKeyVersion, Params: keyFormat.Params, KeyValue: keyValue, }, nil } // validateKey validates the given HMACKey. It only validates the version of the // key because other parameters will be validated in primitive construction. func (km *hmacKeyManager) validateKey(key *hmacpb.HmacKey) error { err := keyset.ValidateKeyVersion(key.Version, hmacKeyVersion) if err != nil { return fmt.Errorf("hmac_key_manager: invalid version: %s", err) } keySize := uint32(len(key.KeyValue)) hash := commonpb.HashType_name[int32(key.GetParams().GetHash())] return subtle.ValidateHMACParams(hash, keySize, key.GetParams().GetTagSize()) } // validateKeyFormat validates the given HMACKeyFormat func (km *hmacKeyManager) validateKeyFormat(format *hmacpb.HmacKeyFormat) error { hash := commonpb.HashType_name[int32(format.GetParams().GetHash())] return subtle.ValidateHMACParams(hash, format.KeySize, format.GetParams().GetTagSize()) } ================================================ FILE: go/mac/hmac_key_manager_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package mac_test import ( "bytes" "encoding/hex" "fmt" "testing" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/mac/subtle" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" "github.com/google/tink/go/tink" commonpb "github.com/google/tink/go/proto/common_go_proto" hmacpb "github.com/google/tink/go/proto/hmac_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestGetPrimitiveWorks(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACTypeURL) if err != nil { t.Errorf("HMAC key manager not found: %s", err) } keyValue := random.GetRandomBytes(20) testCases := []struct { name string key *hmacpb.HmacKey hashName string keyValue []byte tagSize uint32 }{ { name: "SHA1", key: &hmacpb.HmacKey{ Params: &hmacpb.HmacParams{ Hash: commonpb.HashType_SHA1, TagSize: 20, }, KeyValue: keyValue, }, hashName: "SHA1", keyValue: keyValue, tagSize: 20, }, { name: "SHA256", key: &hmacpb.HmacKey{ Params: &hmacpb.HmacParams{ Hash: commonpb.HashType_SHA256, TagSize: 32, }, KeyValue: keyValue, }, hashName: "SHA256", keyValue: keyValue, tagSize: 32, }, { name: "SHA512", key: &hmacpb.HmacKey{ Params: &hmacpb.HmacParams{ Hash: commonpb.HashType_SHA512, TagSize: 64, }, KeyValue: keyValue, }, hashName: "SHA512", keyValue: keyValue, tagSize: 64, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { serializedKey, err := proto.Marshal(tc.key) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } p, err := km.Primitive(serializedKey) if err != nil { t.Fatalf("km.Primitive(serializedKey) err = %q, want nil", err) } mac, ok := p.(tink.MAC) if !ok { t.Fatal("mac is not a tink.MAC") } data := random.GetRandomBytes(20) tag, err := mac.ComputeMAC(data) if err != nil { t.Fatalf("mac.ComputeMAC() err = %q, want nil", err) } if err = mac.VerifyMAC(tag, data); err != nil { t.Fatalf("mac.VerifyMAC() err = %q, want nil", err) } wantMAC, err := subtle.NewHMAC(tc.hashName, tc.keyValue, tc.tagSize) if err != nil { t.Fatalf("subtle.NewHMAC() err = %v, want nil", err) } wantTag, err := wantMAC.ComputeMAC(data) if err != nil { t.Fatalf("wantMAC.ComputeMAC() err = %q, want nil", err) } if !bytes.Equal(tag, wantTag) { t.Errorf("tag = %s, want = %s", tag, wantTag) } }) } } func TestGetPrimitiveWithInvalidInput(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACTypeURL) if err != nil { t.Errorf("cannot obtain HMAC key manager: %s", err) } // invalid key testKeys := genInvalidHMACKeys() for i := 0; i < len(testKeys); i++ { serializedKey, err := proto.Marshal(testKeys[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := km.Primitive(serializedKey); err == nil { t.Errorf("expect an error in test case %d", i) } } if _, err := km.Primitive(nil); err == nil { t.Errorf("expect an error when input is nil") } // empty input if _, err := km.Primitive([]byte{}); err == nil { t.Errorf("expect an error when input is empty") } } func TestNewKeyMultipleTimes(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACTypeURL) if err != nil { t.Errorf("cannot obtain HMAC key manager: %s", err) } serializedFormat, err := proto.Marshal(testutil.NewHMACKeyFormat(commonpb.HashType_SHA256, 32)) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } keys := make(map[string]bool) nTest := 26 for i := 0; i < nTest; i++ { key, err := km.NewKey(serializedFormat) if err != nil { t.Fatalf("km.NewKey() err = %q, want nil", err) } serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } keys[string(serializedKey)] = true keyData, err := km.NewKeyData(serializedFormat) if err != nil { t.Fatalf("km.NewKeyData() err = %q, want nil", err) } serializedKey = keyData.Value keys[string(serializedKey)] = true } if len(keys) != nTest*2 { t.Errorf("key is repeated") } } func TestNewKeyBasic(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACTypeURL) if err != nil { t.Errorf("cannot obtain HMAC key manager: %s", err) } testFormats := genValidHMACKeyFormats() for i := 0; i < len(testFormats); i++ { serializedFormat, err := proto.Marshal(testFormats[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } key, err := km.NewKey(serializedFormat) if err != nil { t.Errorf("unexpected error in test case %d: %s", i, err) } hmacKey, ok := key.(*hmacpb.HmacKey) if !ok { t.Errorf("key is not HmacKey") } format := testFormats[i] if format.KeySize != uint32(len(hmacKey.KeyValue)) || hmacKey.Params.TagSize != format.Params.TagSize || hmacKey.Params.Hash != format.Params.Hash { t.Errorf("key format and generated key do not match") } } } func TestNewKeyWithInvalidInput(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACTypeURL) if err != nil { t.Errorf("cannot obtain HMAC key manager: %s", err) } // invalid key formats testFormats := genInvalidHMACKeyFormats() for i := 0; i < len(testFormats); i++ { serializedFormat, err := proto.Marshal(testFormats[i]) if err != nil { fmt.Println("Error!") } if _, err := km.NewKey(serializedFormat); err == nil { t.Errorf("expect an error in test case %d: %s", i, err) } } if _, err := km.NewKey(nil); err == nil { t.Errorf("expect an error when input is nil") } // empty input if _, err := km.NewKey([]byte{}); err == nil { t.Errorf("expect an error when input is empty") } } func TestNewKeyDataWorks(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACTypeURL) if err != nil { t.Errorf("cannot obtain HMAC key manager: %s", err) } testFormats := genValidHMACKeyFormats() for i := 0; i < len(testFormats); i++ { serializedFormat, err := proto.Marshal(testFormats[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } keyData, err := km.NewKeyData(serializedFormat) if err != nil { t.Errorf("unexpected error in test case %d: %s", i, err) } if keyData.TypeUrl != testutil.HMACTypeURL { t.Errorf("incorrect type url in test case %d", i) } if keyData.KeyMaterialType != tinkpb.KeyData_SYMMETRIC { t.Errorf("incorrect key material type in test case %d", i) } key := new(hmacpb.HmacKey) if err := proto.Unmarshal(keyData.Value, key); err != nil { t.Errorf("invalid key value") } format := testFormats[i] if format.KeySize != uint32(len(key.KeyValue)) || key.Params.TagSize != format.Params.TagSize || key.Params.Hash != format.Params.Hash { t.Errorf("key format and generated key do not match") } p, err := registry.PrimitiveFromKeyData(keyData) if err != nil { t.Errorf("registry.PrimitiveFromKeyData(keyData) err = %v, want nil", err) } _, ok := p.(tink.MAC) if !ok { t.Error("registry.PrimitiveFromKeyData(keyData) did not return a tink.MAC") } } } func TestNewKeyDataWithInvalidInput(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACTypeURL) if err != nil { t.Errorf("HMAC key manager not found: %s", err) } // invalid key formats testFormats := genInvalidHMACKeyFormats() for i := 0; i < len(testFormats); i++ { serializedFormat, err := proto.Marshal(testFormats[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := km.NewKeyData(serializedFormat); err == nil { t.Errorf("expect an error in test case %d", i) } } // nil input if _, err := km.NewKeyData(nil); err == nil { t.Errorf("expect an error when input is nil") } } func TestDoesSupport(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACTypeURL) if err != nil { t.Errorf("HMAC key manager not found: %s", err) } if !km.DoesSupport(testutil.HMACTypeURL) { t.Errorf("HMACKeyManager must support %s", testutil.HMACTypeURL) } if km.DoesSupport("some bad type") { t.Errorf("HMACKeyManager must support only %s", testutil.HMACTypeURL) } } func TestTypeURL(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACTypeURL) if err != nil { t.Errorf("HMAC key manager not found: %s", err) } if km.TypeURL() != testutil.HMACTypeURL { t.Errorf("incorrect GetKeyType()") } } func TestHMACKeyMaterialType(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.HMACTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } if got, want := keyManager.KeyMaterialType(), tinkpb.KeyData_SYMMETRIC; got != want { t.Errorf("KeyMaterialType() = %v, want %v", got, want) } } func TestHMACDeriveKey(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.HMACTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } keyFormat, err := proto.Marshal(&hmacpb.HmacKeyFormat{ Version: testutil.HMACKeyVersion, KeySize: 16, Params: &hmacpb.HmacParams{ Hash: commonpb.HashType_SHA256, TagSize: 10, }, }) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } rand := random.GetRandomBytes(16) buf := &bytes.Buffer{} buf.Write(rand) // never returns a non-nil error k, err := keyManager.DeriveKey(keyFormat, buf) if err != nil { t.Fatalf("keyManager.DeriveKey() err = %v, want nil", err) } key := k.(*hmacpb.HmacKey) if got, want := len(key.GetKeyValue()), 16; got != want { t.Errorf("key length = %d, want %d", got, want) } if diff := cmp.Diff(key.GetKeyValue(), rand); diff != "" { t.Errorf("incorrect derived key: diff = %v", diff) } } func TestHMACDeriveKeyFailsWithInvalidKeyFormats(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.HMACTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } validKeyFormat := &hmacpb.HmacKeyFormat{ Version: testutil.HMACKeyVersion, KeySize: 16, Params: &hmacpb.HmacParams{ Hash: commonpb.HashType_SHA256, TagSize: 10, }, } serializedValidKeyFormat, err := proto.Marshal(validKeyFormat) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", validKeyFormat, err) } buf := bytes.NewBuffer(random.GetRandomBytes(validKeyFormat.KeySize)) if _, err := keyManager.DeriveKey(serializedValidKeyFormat, buf); err != nil { t.Fatalf("keyManager.DeriveKey() err = %v, want nil", err) } for _, test := range []struct { name string version uint32 keySize uint32 hash commonpb.HashType tagSize uint32 }{ { name: "invalid version", version: 10, keySize: validKeyFormat.KeySize, hash: validKeyFormat.Params.Hash, tagSize: validKeyFormat.Params.TagSize, }, { name: "invalid key size", version: validKeyFormat.Version, keySize: 10, hash: validKeyFormat.Params.Hash, tagSize: validKeyFormat.Params.TagSize, }, { name: "invalid hash", version: validKeyFormat.Version, keySize: validKeyFormat.KeySize, hash: commonpb.HashType_UNKNOWN_HASH, tagSize: validKeyFormat.Params.TagSize, }, { name: "invalid tag size", version: validKeyFormat.Version, keySize: validKeyFormat.KeySize, hash: validKeyFormat.Params.Hash, tagSize: 9, }, } { t.Run(test.name, func(t *testing.T) { keyFormat, err := proto.Marshal(&hmacpb.HmacKeyFormat{ Version: test.version, KeySize: test.keySize, Params: &hmacpb.HmacParams{ Hash: test.hash, TagSize: test.tagSize, }, }) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } buf := bytes.NewBuffer(random.GetRandomBytes(test.keySize)) if _, err := keyManager.DeriveKey(keyFormat, buf); err == nil { t.Errorf("keyManager.DeriveKey() err = nil, want non-nil") } }) } } func TestHMACDeriveKeyFailsWithMalformedKeyFormats(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.HMACTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } // Proto messages start with a VarInt, which always ends with a byte with the // MSB unset, so 0x80 is invalid. invalidSerialization, err := hex.DecodeString("80") if err != nil { t.Errorf("hex.DecodeString() err = %v, want nil", err) } for _, test := range []struct { name string keyFormat []byte }{ { name: "nil", keyFormat: nil, }, { name: "empty", keyFormat: []byte{}, }, { name: "invalid serialization", keyFormat: invalidSerialization, }, } { t.Run(test.name, func(t *testing.T) { buf := bytes.NewBuffer(random.GetRandomBytes(16)) if _, err := keyManager.DeriveKey(test.keyFormat, buf); err == nil { t.Errorf("keyManager.DeriveKey() err = nil, want non-nil") } }) } } func TestHMACDeriveKeyFailsWithInsufficientRandomness(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.HMACTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } keyFormat, err := proto.Marshal(&hmacpb.HmacKeyFormat{ Version: testutil.HMACKeyVersion, KeySize: 16, Params: &hmacpb.HmacParams{ Hash: commonpb.HashType_SHA256, TagSize: 10, }, }) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", keyFormat, err) } { buf := bytes.NewBuffer(random.GetRandomBytes(16)) if _, err := keyManager.DeriveKey(keyFormat, buf); err != nil { t.Errorf("keyManager.DeriveKey() err = %v, want nil", err) } } { insufficientBuf := bytes.NewBuffer(random.GetRandomBytes(15)) if _, err := keyManager.DeriveKey(keyFormat, insufficientBuf); err == nil { t.Errorf("keyManager.DeriveKey() err = nil, want non-nil") } } } func genInvalidHMACKeys() []proto.Message { badVersionKey := testutil.NewHMACKey(commonpb.HashType_SHA256, 32) badVersionKey.Version++ shortKey := testutil.NewHMACKey(commonpb.HashType_SHA256, 32) shortKey.KeyValue = []byte{1, 1} nilParams := testutil.NewHMACKey(commonpb.HashType_SHA256, 32) nilParams.Params = nil return []proto.Message{ // not a HMACKey testutil.NewHMACParams(commonpb.HashType_SHA256, 32), // bad version badVersionKey, // tag size too big testutil.NewHMACKey(commonpb.HashType_SHA1, 21), testutil.NewHMACKey(commonpb.HashType_SHA256, 33), testutil.NewHMACKey(commonpb.HashType_SHA512, 65), // tag size too small testutil.NewHMACKey(commonpb.HashType_SHA256, 1), // key too short shortKey, // unknown hash type testutil.NewHMACKey(commonpb.HashType_UNKNOWN_HASH, 32), // params field is unset nilParams, } } func genInvalidHMACKeyFormats() []proto.Message { shortKeyFormat := testutil.NewHMACKeyFormat(commonpb.HashType_SHA256, 32) shortKeyFormat.KeySize = 1 nilParams := testutil.NewHMACKeyFormat(commonpb.HashType_SHA256, 32) nilParams.Params = nil return []proto.Message{ // not a HMACKeyFormat testutil.NewHMACParams(commonpb.HashType_SHA256, 32), // tag size too big testutil.NewHMACKeyFormat(commonpb.HashType_SHA1, 21), testutil.NewHMACKeyFormat(commonpb.HashType_SHA256, 33), testutil.NewHMACKeyFormat(commonpb.HashType_SHA512, 65), // tag size too small testutil.NewHMACKeyFormat(commonpb.HashType_SHA256, 1), // key too short shortKeyFormat, // unknown hash type testutil.NewHMACKeyFormat(commonpb.HashType_UNKNOWN_HASH, 32), // params field is unset nilParams, } } func genValidHMACKeyFormats() []*hmacpb.HmacKeyFormat { return []*hmacpb.HmacKeyFormat{ testutil.NewHMACKeyFormat(commonpb.HashType_SHA1, 20), testutil.NewHMACKeyFormat(commonpb.HashType_SHA256, 32), testutil.NewHMACKeyFormat(commonpb.HashType_SHA512, 64), } } ================================================ FILE: go/mac/internal/mactest/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") # TODO(felobato): describe this package. go_library( name = "mactest", srcs = ["mactest.go"], importpath = "github.com/google/tink/go/mac/internal/mactest", visibility = ["//mac:__subpackages__"], deps = ["//tink"], ) alias( name = "go_default_library", actual = ":mactest", visibility = ["//mac:__subpackages__"], ) go_test( name = "mactest_test", srcs = ["mactest_test.go"], deps = [":mactest"], ) ================================================ FILE: go/mac/internal/mactest/mactest.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package mactest has testing utilities for the MAC primitive package mactest import ( "github.com/google/tink/go/tink" ) // AlwaysFailingMAC fails compute and verify operations. type AlwaysFailingMAC struct { Error error } var _ (tink.MAC) = (*AlwaysFailingMAC)(nil) // ComputeMAC returns an error on compute. func (m *AlwaysFailingMAC) ComputeMAC(data []byte) ([]byte, error) { return nil, m.Error } // VerifyMAC returns an error on verify. func (m *AlwaysFailingMAC) VerifyMAC(mac []byte, data []byte) error { return m.Error } ================================================ FILE: go/mac/internal/mactest/mactest_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package mactest_test import ( "errors" "testing" "github.com/google/tink/go/mac/internal/mactest" ) func TestAlwaysFailingMACAlwayFails(t *testing.T) { wantErr := errors.New("panic at the kernel") p := &mactest.AlwaysFailingMAC{Error: wantErr} if _, err := p.ComputeMAC([]byte("valid_data")); !errors.Is(err, wantErr) { t.Errorf("p.ComputeMac() err = %v, want %v", err, wantErr) } if err := p.VerifyMAC([]byte("data"), []byte("tag")); !errors.Is(err, wantErr) { t.Errorf("p.VerifyMac() err = %v, want %v", err, wantErr) } } ================================================ FILE: go/mac/mac.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package mac provides implementations of the MAC primitive. // // MAC computes a tag for a given message that can be used to authenticate a // message. MAC protects data integrity as well as provides for authenticity // of the message. package mac import ( "fmt" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/internalregistry" ) func init() { if err := registry.RegisterKeyManager(new(hmacKeyManager)); err != nil { panic(fmt.Sprintf("mac.init() failed: %v", err)) } if err := internalregistry.AllowKeyDerivation(hmacTypeURL); err != nil { panic(fmt.Sprintf("mac.init() failed: %v", err)) } if err := registry.RegisterKeyManager(new(aescmacKeyManager)); err != nil { panic(fmt.Sprintf("mac.init() failed: %v", err)) } } ================================================ FILE: go/mac/mac_benchmark_test.go ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // ////////////////////////////////////////////////////////////////////////////// package mac_test import ( "testing" "github.com/google/tink/go/keyset" "github.com/google/tink/go/mac" "github.com/google/tink/go/subtle/random" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // Benchmarks for MAC algorithms. var benchmarkTestCases = []struct { name string template *tinkpb.KeyTemplate dataSize uint32 }{ { name: "HMAC_SHA256_16", template: mac.HMACSHA256Tag128KeyTemplate(), dataSize: 16, }, { name: "HMAC_SHA512_16", template: mac.HMACSHA512Tag256KeyTemplate(), dataSize: 16, }, { name: "AES_CMAC_16", template: mac.AESCMACTag128KeyTemplate(), dataSize: 16, }, { name: "HMAC_SHA256_16k", template: mac.HMACSHA256Tag128KeyTemplate(), dataSize: 16 * 1024, }, { name: "HMAC_SHA512_16k", template: mac.HMACSHA512Tag256KeyTemplate(), dataSize: 16 * 1024, }, { name: "AES_CMAC_16k", template: mac.AESCMACTag128KeyTemplate(), dataSize: 16 * 1024, }, } func BenchmarkComputeMac(b *testing.B) { for _, tc := range benchmarkTestCases { b.Run(tc.name, func(b *testing.B) { b.ReportAllocs() handle, err := keyset.NewHandle(tc.template) if err != nil { b.Fatal(err) } primitive, err := mac.New(handle) if err != nil { b.Fatal(err) } data := random.GetRandomBytes(tc.dataSize) b.ResetTimer() for i := 0; i < b.N; i++ { _, err := primitive.ComputeMAC(data) if err != nil { b.Error(err) } } }) } } func BenchmarkVerifyMac(b *testing.B) { for _, tc := range benchmarkTestCases { b.Run(tc.name, func(b *testing.B) { b.ReportAllocs() handle, err := keyset.NewHandle(tc.template) if err != nil { b.Fatal(err) } primitive, err := mac.New(handle) if err != nil { b.Fatal(err) } data := random.GetRandomBytes(tc.dataSize) tag, err := primitive.ComputeMAC(data) if err != nil { b.Fatal(err) } b.ResetTimer() for i := 0; i < b.N; i++ { if err = primitive.VerifyMAC(tag, data); err != nil { b.Error(err) } } }) } } ================================================ FILE: go/mac/mac_factory.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package mac import ( "fmt" "github.com/google/tink/go/core/cryptofmt" "github.com/google/tink/go/core/primitiveset" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/internal/monitoringutil" "github.com/google/tink/go/keyset" "github.com/google/tink/go/monitoring" "github.com/google/tink/go/tink" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( intSize = 32 << (^uint(0) >> 63) // 32 or 64 maxInt = 1<<(intSize-1) - 1 ) // New creates a MAC primitive from the given keyset handle. func New(handle *keyset.Handle) (tink.MAC, error) { ps, err := handle.Primitives() if err != nil { return nil, fmt.Errorf("mac_factory: cannot obtain primitive set: %s", err) } return newWrappedMAC(ps) } // wrappedMAC is a MAC implementation that uses the underlying primitive set to compute and // verify MACs. type wrappedMAC struct { ps *primitiveset.PrimitiveSet computeLogger monitoring.Logger verifyLogger monitoring.Logger } var _ (tink.MAC) = (*wrappedMAC)(nil) func newWrappedMAC(ps *primitiveset.PrimitiveSet) (*wrappedMAC, error) { if _, ok := (ps.Primary.Primitive).(tink.MAC); !ok { return nil, fmt.Errorf("mac_factory: not a MAC primitive") } for _, primitives := range ps.Entries { for _, p := range primitives { if _, ok := (p.Primitive).(tink.MAC); !ok { return nil, fmt.Errorf("mac_factory: not an MAC primitive") } } } computeLogger, verifyLogger, err := createLoggers(ps) if err != nil { return nil, err } return &wrappedMAC{ ps: ps, computeLogger: computeLogger, verifyLogger: verifyLogger, }, nil } func createLoggers(ps *primitiveset.PrimitiveSet) (monitoring.Logger, monitoring.Logger, error) { if len(ps.Annotations) == 0 { return &monitoringutil.DoNothingLogger{}, &monitoringutil.DoNothingLogger{}, nil } client := internalregistry.GetMonitoringClient() keysetInfo, err := monitoringutil.KeysetInfoFromPrimitiveSet(ps) if err != nil { return nil, nil, err } computeLogger, err := client.NewLogger(&monitoring.Context{ Primitive: "mac", APIFunction: "compute", KeysetInfo: keysetInfo, }) if err != nil { return nil, nil, err } verifyLogger, err := client.NewLogger(&monitoring.Context{ Primitive: "mac", APIFunction: "verify", KeysetInfo: keysetInfo, }) if err != nil { return nil, nil, err } return computeLogger, verifyLogger, nil } // ComputeMAC calculates a MAC over the given data using the primary primitive // and returns the concatenation of the primary's identifier and the calculated mac. func (m *wrappedMAC) ComputeMAC(data []byte) ([]byte, error) { primary := m.ps.Primary primitive, ok := (primary.Primitive).(tink.MAC) if !ok { return nil, fmt.Errorf("mac_factory: not a MAC primitive") } if m.ps.Primary.PrefixType == tinkpb.OutputPrefixType_LEGACY { d := data if len(d) >= maxInt { m.computeLogger.LogFailure() return nil, fmt.Errorf("mac_factory: data too long") } data = make([]byte, 0, len(d)+1) data = append(data, d...) data = append(data, byte(0)) } mac, err := primitive.ComputeMAC(data) if err != nil { m.computeLogger.LogFailure() return nil, err } m.computeLogger.Log(primary.KeyID, len(data)) if len(primary.Prefix) == 0 { return mac, nil } output := make([]byte, 0, len(primary.Prefix)+len(mac)) output = append(output, primary.Prefix...) output = append(output, mac...) return output, nil } var errInvalidMAC = fmt.Errorf("mac_factory: invalid mac") // VerifyMAC verifies whether the given mac is a correct authentication code // for the given data. func (m *wrappedMAC) VerifyMAC(mac, data []byte) error { // This also rejects raw MAC with size of 4 bytes or fewer. Those MACs are // clearly insecure, thus should be discouraged. prefixSize := cryptofmt.NonRawPrefixSize if len(mac) <= prefixSize { m.verifyLogger.LogFailure() return errInvalidMAC } // try non raw keys prefix := mac[:prefixSize] macNoPrefix := mac[prefixSize:] entries, err := m.ps.EntriesForPrefix(string(prefix)) if err == nil { for i := 0; i < len(entries); i++ { entry := entries[i] p, ok := (entry.Primitive).(tink.MAC) if !ok { return fmt.Errorf("mac_factory internal error: not a MAC primitive") } if entry.PrefixType == tinkpb.OutputPrefixType_LEGACY { d := data if len(d) >= maxInt { m.verifyLogger.LogFailure() return fmt.Errorf("mac_factory: data too long") } data = make([]byte, 0, len(d)+1) data = append(data, d...) data = append(data, byte(0)) } if err = p.VerifyMAC(macNoPrefix, data); err == nil { m.verifyLogger.Log(entry.KeyID, len(data)) return nil } } } // try raw keys entries, err = m.ps.RawEntries() if err == nil { for i := 0; i < len(entries); i++ { p, ok := (entries[i].Primitive).(tink.MAC) if !ok { return fmt.Errorf("mac_factory internal error: not a MAC primitive") } if err = p.VerifyMAC(mac, data); err == nil { m.verifyLogger.Log(entries[i].KeyID, len(data)) return nil } } } // nothing worked m.verifyLogger.LogFailure() return errInvalidMAC } ================================================ FILE: go/mac/mac_factory_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package mac_test import ( "bytes" "fmt" "strings" "testing" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/cryptofmt" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/insecurecleartextkeyset" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/internal/testing/stubkeymanager" "github.com/google/tink/go/keyset" "github.com/google/tink/go/mac/internal/mactest" "github.com/google/tink/go/mac" "github.com/google/tink/go/monitoring" "github.com/google/tink/go/signature" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testing/fakemonitoring" "github.com/google/tink/go/testkeyset" "github.com/google/tink/go/testutil" "github.com/google/tink/go/tink" commonpb "github.com/google/tink/go/proto/common_go_proto" hmacpb "github.com/google/tink/go/proto/hmac_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestFactoryMultipleKeys(t *testing.T) { tagSize := uint32(16) keyset := testutil.NewTestHMACKeyset(tagSize, tinkpb.OutputPrefixType_TINK) primaryKey := keyset.Key[0] if primaryKey.OutputPrefixType != tinkpb.OutputPrefixType_TINK { t.Errorf("expect a tink key") } keysetHandle, err := testkeyset.NewHandle(keyset) if err != nil { t.Errorf("testkeyset.NewHandle failed: %s", err) } p, err := mac.New(keysetHandle) if err != nil { t.Errorf("mac.New failed: %s", err) } expectedPrefix, err := cryptofmt.OutputPrefix(primaryKey) if err != nil { t.Errorf("cryptofmt.OutputPrefix failed: %s", err) } if err := verifyMacPrimitive(p, p, expectedPrefix, tagSize); err != nil { t.Errorf("invalid primitive: %s", err) } // mac with a primary RAW key, verify with the keyset rawKey := keyset.Key[1] if rawKey.OutputPrefixType != tinkpb.OutputPrefixType_RAW { t.Errorf("expect a raw key") } keyset2 := testutil.NewKeyset(rawKey.KeyId, []*tinkpb.Keyset_Key{rawKey}) keysetHandle2, err := testkeyset.NewHandle(keyset2) if err != nil { t.Errorf("testkeyset.NewHandle failed: %s", err) } p2, err := mac.New(keysetHandle2) if err != nil { t.Errorf("mac.New failed: %s", err) } if err := verifyMacPrimitive(p2, p, cryptofmt.RawPrefix, tagSize); err != nil { t.Errorf("invalid primitive: %s", err) } // mac with a random key not in the keyset, verify with the keyset should fail keyset2 = testutil.NewTestHMACKeyset(tagSize, tinkpb.OutputPrefixType_TINK) primaryKey = keyset2.Key[0] expectedPrefix, err = cryptofmt.OutputPrefix(primaryKey) if err != nil { t.Errorf("cryptofmt.OutputPrefix() err = %q, want nil", err) } keysetHandle2, err = testkeyset.NewHandle(keyset2) if err != nil { t.Errorf("testkeyset.NewHandle failed: %s", err) } p2, err = mac.New(keysetHandle2) if err != nil { t.Errorf("mac.New: cannot get primitive from keyset handle") } err = verifyMacPrimitive(p2, p, expectedPrefix, tagSize) if err == nil || !strings.Contains(err.Error(), "mac verification failed") { t.Errorf("Invalid MAC, shouldn't return valid") } } func TestFactoryRawKey(t *testing.T) { tagSize := uint32(16) keyset := testutil.NewTestHMACKeyset(tagSize, tinkpb.OutputPrefixType_RAW) primaryKey := keyset.Key[0] if primaryKey.OutputPrefixType != tinkpb.OutputPrefixType_RAW { t.Errorf("expect a raw key") } keysetHandle, err := testkeyset.NewHandle(keyset) if err != nil { t.Errorf("testkeyset.NewHandle failed: %s", err) } p, err := mac.New(keysetHandle) if err != nil { t.Errorf("mac.New failed: %s", err) } if err := verifyMacPrimitive(p, p, cryptofmt.RawPrefix, tagSize); err != nil { t.Errorf("invalid primitive: %s", err) } } func TestFactoryLegacyKey(t *testing.T) { tagSize := uint32(16) keyset := testutil.NewTestHMACKeyset(tagSize, tinkpb.OutputPrefixType_LEGACY) primaryKey := keyset.Key[0] if primaryKey.OutputPrefixType != tinkpb.OutputPrefixType_LEGACY { t.Errorf("expect a legacy key") } keysetHandle, err := testkeyset.NewHandle(keyset) if err != nil { t.Errorf("testkeyset.NewHandle failed: %s", err) } p, err := mac.New(keysetHandle) if err != nil { t.Errorf("mac.New failed: %s", err) } data := []byte("some data") tag, err := p.ComputeMAC(data) if err != nil { t.Errorf("mac computation failed: %s", err) } if err = p.VerifyMAC(tag, data); err != nil { t.Errorf("mac verification failed: %s", err) } } func TestFactoryLegacyFixedKeyFixedTag(t *testing.T) { tagSize := uint32(16) params := testutil.NewHMACParams(commonpb.HashType_SHA256, tagSize) keyValue := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19} key := &hmacpb.HmacKey{ Version: 0, Params: params, KeyValue: keyValue, } serializedKey, err := proto.Marshal(key) if err != nil { t.Errorf("failed serializing proto: %v", err) } keyData := &tinkpb.KeyData{ TypeUrl: "type.googleapis.com/google.crypto.tink.HmacKey", Value: serializedKey, KeyMaterialType: tinkpb.KeyData_SYMMETRIC, } keyset := testutil.NewTestKeyset(keyData, tinkpb.OutputPrefixType_LEGACY) primaryKey := keyset.Key[0] if primaryKey.OutputPrefixType != tinkpb.OutputPrefixType_LEGACY { t.Errorf("expect a legacy key") } keysetHandle, err := testkeyset.NewHandle(keyset) if err != nil { t.Errorf("testkeyset.NewHandle failed: %s", err) } p, err := mac.New(keysetHandle) if err != nil { t.Errorf("mac.New failed: %s", err) } data := []byte("hello") tag := []byte{0, 0, 0, 0, 42, 64, 150, 12, 207, 250, 175, 32, 216, 164, 77, 69, 28, 29, 204, 235, 75} if err = p.VerifyMAC(tag, data); err != nil { t.Errorf("compatibleTag verification failed: %s", err) } } func verifyMacPrimitive(computePrimitive, verifyPrimitive tink.MAC, expectedPrefix string, tagSize uint32) error { data := []byte("hello") tag, err := computePrimitive.ComputeMAC(data) if err != nil { return fmt.Errorf("mac computation failed: %s", err) } prefixSize := len(expectedPrefix) if string(tag[:prefixSize]) != expectedPrefix { return fmt.Errorf("incorrect prefix") } if prefixSize+int(tagSize) != len(tag) { return fmt.Errorf("incorrect tag length") } if err = verifyPrimitive.VerifyMAC(tag, data); err != nil { return fmt.Errorf("mac verification failed: %s", err) } // Modify plaintext or tag and make sure VerifyMAC failed. var dataAndTag []byte dataAndTag = append(dataAndTag, data...) dataAndTag = append(dataAndTag, tag...) if err = verifyPrimitive.VerifyMAC(dataAndTag[len(data):], dataAndTag[:len(data)]); err != nil { return fmt.Errorf("mac verification failed: %s", err) } for i := 0; i < len(dataAndTag); i++ { tmp := dataAndTag[i] for j := 0; j < 8; j++ { dataAndTag[i] ^= 1 << uint8(j) if err = verifyPrimitive.VerifyMAC(dataAndTag[len(data):], dataAndTag[:len(data)]); err == nil { return fmt.Errorf("invalid tag or plaintext, mac should be invalid") } dataAndTag[i] = tmp } } return nil } func TestFactoryWithInvalidPrimitiveSetType(t *testing.T) { wrongKH, err := keyset.NewHandle(signature.ECDSAP256KeyTemplate()) if err != nil { t.Fatalf("failed to build *keyset.Handle: %s", err) } _, err = mac.New(wrongKH) if err == nil { t.Fatal("calling New() with wrong *keyset.Handle should fail") } } func TestFactoryWithValidPrimitiveSetType(t *testing.T) { goodKH, err := keyset.NewHandle(mac.HMACSHA256Tag256KeyTemplate()) if err != nil { t.Fatalf("failed to build *keyset.Handle: %s", err) } _, err = mac.New(goodKH) if err != nil { t.Fatalf("calling New() with good *keyset.Handle failed: %s", err) } } func TestPrimitiveFactoryMonitoringWithoutAnnotationsDoesNotLog(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("registry.RegisterMonitoringClient() err = %v, want nil", err) } kh, err := keyset.NewHandle(mac.HMACSHA256Tag256KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle(mac.HMACSHA256Tag256KeyTemplate()) err = %v, want nil", err) } p, err := mac.New(kh) if err != nil { t.Fatalf("mac.New() err = %v, want nil", err) } data := []byte("data") tag, err := p.ComputeMAC(data) if err != nil { t.Fatalf("p.ComputeMAC() err = %v, want nil", err) } if err := p.VerifyMAC(tag, data); err != nil { t.Fatalf("p.Verify() err = %v, want nil", err) } got := client.Events() if len(got) != 0 { t.Errorf("len(client.Events()) = %d, want 0", len(got)) } } func TestFactoryWithMonitoringPrimitiveWithMultipleKeysLogsComputeVerify(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("registry.RegisterMonitoringClient() err = %v, want nil", err) } manager := keyset.NewManager() keyIDs := make([]uint32, 4, 4) var err error for i, tm := range []*tinkpb.KeyTemplate{ mac.HMACSHA256Tag256KeyTemplate(), mac.HMACSHA256Tag128KeyTemplate(), mac.HMACSHA512Tag512KeyTemplate(), mac.AESCMACTag128KeyTemplate(), } { keyIDs[i], err = manager.Add(tm) if err != nil { t.Fatalf("manager.Add() err = %v, want nil", err) } } if err := manager.SetPrimary(keyIDs[1]); err != nil { t.Fatalf("manager.SetPrimary(%d) err = %v, want nil", keyIDs[1], err) } if err := manager.Disable(keyIDs[0]); err != nil { t.Fatalf("manager.Disable(%d) err = %v, want nil", keyIDs[0], err) } kh, err := manager.Handle() if err != nil { t.Fatalf("manager.Handle() err = %v, want nil", err) } // Annotations are only supported throught the `insecurecleartextkeyset` API. buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } p, err := mac.New(mh) if err != nil { t.Fatalf("mac.New() err = %v, want nil", err) } data := random.GetRandomBytes(50) tag, err := p.ComputeMAC(data) if err != nil { t.Fatalf("p.ComputeMAC() err = %v, want nil", err) } if err := p.VerifyMAC(tag, data); err != nil { t.Fatalf("p.VerifyMAC() err = %v, want nil", err) } failures := len(client.Failures()) if failures != 0 { t.Errorf("len(client.Failures()) = %d, want 0", failures) } got := client.Events() wantKeysetInfo := &monitoring.KeysetInfo{ Annotations: annotations, PrimaryKeyID: kh.KeysetInfo().GetPrimaryKeyId(), Entries: []*monitoring.Entry{ { KeyID: kh.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.HmacKey", KeyPrefix: "TINK", }, { KeyID: keyIDs[2], Status: monitoring.Enabled, KeyType: "tink.HmacKey", KeyPrefix: "TINK", }, { KeyID: keyIDs[3], Status: monitoring.Enabled, KeyType: "tink.AesCmacKey", KeyPrefix: "TINK", }, }, } want := []*fakemonitoring.LogEvent{ { KeyID: kh.KeysetInfo().GetPrimaryKeyId(), NumBytes: len(data), Context: monitoring.NewContext( "mac", "compute", wantKeysetInfo, ), }, { KeyID: kh.KeysetInfo().GetPrimaryKeyId(), NumBytes: len(data), Context: monitoring.NewContext( "mac", "verify", wantKeysetInfo, ), }, } // sort by keyID to avoid non deterministic order. entryLessFunc := func(a, b *monitoring.Entry) bool { return a.KeyID < b.KeyID } if !cmp.Equal(got, want, cmpopts.SortSlices(entryLessFunc)) { t.Errorf("got = %v, want = %v, with diff: %v", got, want, cmp.Diff(got, want)) } } func TestPrimitiveFactoryWithMonitoringAnnotationsComputeFailureIsLogged(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("registry.RegisterMonitoringClient() err = %v, want nil", err) } // Since this key type will be registered in the registry, // we create a very unique typeURL to avoid colliding with other tests. typeURL := "TestPrimitiveFactoryWithMonitoringComputeFailureIsLogged" template := &tinkpb.KeyTemplate{ TypeUrl: typeURL, OutputPrefixType: tinkpb.OutputPrefixType_LEGACY, } km := &stubkeymanager.StubKeyManager{ URL: typeURL, Prim: &mactest.AlwaysFailingMAC{Error: fmt.Errorf("system failure")}, Key: &hmacpb.HmacKey{}, KeyData: &tinkpb.KeyData{ TypeUrl: template.TypeUrl, Value: []byte("some_data"), }, } if err := registry.RegisterKeyManager(km); err != nil { t.Fatalf("registry.RegisterKeyManager() err = %v, want nil", err) } kh, err := keyset.NewHandle(template) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } // Annotations are only supported throught the `insecurecleartextkeyset` API. buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } m, err := mac.New(mh) if err != nil { t.Fatalf("mac.New() err = %v, want nil", err) } if _, err := m.ComputeMAC([]byte("some_data")); err == nil { t.Fatalf("m.ComputeMAC() err = nil, want non-nil error") } got := client.Failures() want := []*fakemonitoring.LogFailure{ { Context: monitoring.NewContext( "mac", "compute", monitoring.NewKeysetInfo( annotations, kh.KeysetInfo().GetPrimaryKeyId(), []*monitoring.Entry{ { KeyID: kh.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: typeURL, KeyPrefix: "LEGACY", }, }, ), ), }, } if !cmp.Equal(got, want) { t.Errorf("got = %v, want = %v, with diff: %v", got, want, cmp.Diff(got, want)) } } func TestPrimitiveFactoryWithMonitoringAnnotationsVerifyFailureIsLogged(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("registry.RegisterMonitoringClient() err = %v, want nil", err) } kh, err := keyset.NewHandle(mac.HMACSHA256Tag256KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } // Annotations are only supported throught the `insecurecleartextkeyset` API. buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } m, err := mac.New(mh) if err != nil { t.Fatalf("mac.New() err = %v, want nil", err) } if err := m.VerifyMAC(nil, nil); err == nil { t.Fatalf("m.VerifyMAC() err = nil, want non-nil error") } got := client.Failures() want := []*fakemonitoring.LogFailure{ { Context: monitoring.NewContext( "mac", "verify", monitoring.NewKeysetInfo( annotations, kh.KeysetInfo().GetPrimaryKeyId(), []*monitoring.Entry{ { KeyID: kh.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.HmacKey", KeyPrefix: "TINK", }, }, ), ), }, } if !cmp.Equal(got, want) { t.Errorf("got = %v, want = %v, with diff: %v", got, want, cmp.Diff(got, want)) } } func TestPrimitiveFactoryMonitoringWithAnnotationsMultiplePrimitivesLogOperations(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("registry.RegisterMonitoringClient() err = %v, want nil", err) } templates := []*tinkpb.KeyTemplate{ mac.HMACSHA256Tag256KeyTemplate(), mac.AESCMACTag128KeyTemplate()} handles := make([]*keyset.Handle, len(templates)) var err error annotations := map[string]string{"foo": "bar"} for i, tm := range templates { handles[i], err = keyset.NewHandle(tm) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } // Annotations are only supported throught the `insecurecleartextkeyset` API. buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(handles[i], keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } p, err := mac.New(mh) if err != nil { t.Fatalf("mac.New() err = %v, want nil", err) } if _, err := p.ComputeMAC([]byte(tm.GetTypeUrl())); err != nil { t.Fatalf("p.ComputeMAC() err = %v, want nil", err) } } got := client.Events() want := []*fakemonitoring.LogEvent{ { KeyID: handles[0].KeysetInfo().GetPrimaryKeyId(), NumBytes: len(templates[0].GetTypeUrl()), Context: monitoring.NewContext( "mac", "compute", monitoring.NewKeysetInfo( annotations, handles[0].KeysetInfo().GetPrimaryKeyId(), []*monitoring.Entry{ { KeyID: handles[0].KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.HmacKey", KeyPrefix: "TINK", }, }, ), ), }, { KeyID: handles[1].KeysetInfo().GetPrimaryKeyId(), NumBytes: len(templates[1].GetTypeUrl()), Context: monitoring.NewContext( "mac", "compute", monitoring.NewKeysetInfo( annotations, handles[1].KeysetInfo().GetPrimaryKeyId(), []*monitoring.Entry{ { KeyID: handles[1].KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.AesCmacKey", KeyPrefix: "TINK", }, }, ), ), }, } if !cmp.Equal(got, want) { t.Errorf("got = %v, want = %v, with diff: %v", got, want, cmp.Diff(got, want)) } } func TestPrimitiveFactoryMonitoringWithAnnotationsComputeVerifyLogs(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("registry.RegisterMonitoringClient() err = %v, want nil", err) } kh, err := keyset.NewHandle(mac.HMACSHA256Tag256KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } // Annotations are only supported throught the `insecurecleartextkeyset` API. buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } p, err := mac.New(mh) if err != nil { t.Fatalf("mac.New() err = %v, want nil", err) } data := []byte("data") tag, err := p.ComputeMAC(data) if err != nil { t.Fatalf("p.ComputeMAC() err = %v, want nil", err) } if err := p.VerifyMAC(tag, data); err != nil { t.Fatalf("p.Verify() err = %v, want nil", err) } got := client.Events() wantKeysetInfo := monitoring.NewKeysetInfo( annotations, kh.KeysetInfo().GetPrimaryKeyId(), []*monitoring.Entry{ { KeyID: kh.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.HmacKey", KeyPrefix: "TINK", }, }, ) want := []*fakemonitoring.LogEvent{ &fakemonitoring.LogEvent{ Context: monitoring.NewContext("mac", "compute", wantKeysetInfo), KeyID: kh.KeysetInfo().GetPrimaryKeyId(), NumBytes: len(data), }, &fakemonitoring.LogEvent{ Context: monitoring.NewContext("mac", "verify", wantKeysetInfo), KeyID: kh.KeysetInfo().GetPrimaryKeyId(), NumBytes: len(data), }, } if !cmp.Equal(got, want) { t.Errorf("got = %v, want = %v, with diff: %v", got, want, cmp.Diff(got, want)) } } ================================================ FILE: go/mac/mac_init_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package mac_test import ( "testing" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/testutil" ) func TestMacInit(t *testing.T) { // Check that the HMAC key manager is in the global registry. _, err := registry.GetKeyManager(testutil.HMACTypeURL) if err != nil { t.Errorf("unexpected error: %s", err) } // Check that the AES CMAC key manager is in the global registry. _, err = registry.GetKeyManager(testutil.AESCMACTypeURL) if err != nil { t.Errorf("unexpected error: %s", err) } } ================================================ FILE: go/mac/mac_key_templates.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package mac import ( "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/internal/tinkerror" cmacpb "github.com/google/tink/go/proto/aes_cmac_go_proto" commonpb "github.com/google/tink/go/proto/common_go_proto" hmacpb "github.com/google/tink/go/proto/hmac_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // This file contains pre-generated KeyTemplate for MAC. // HMACSHA256Tag128KeyTemplate is a KeyTemplate that generates a HMAC key with the following parameters: // - Key size: 32 bytes // - Tag size: 16 bytes // - Hash function: SHA256 func HMACSHA256Tag128KeyTemplate() *tinkpb.KeyTemplate { return createHMACKeyTemplate(32, 16, commonpb.HashType_SHA256) } // HMACSHA256Tag256KeyTemplate is a KeyTemplate that generates a HMAC key with the following parameters: // - Key size: 32 bytes // - Tag size: 32 bytes // - Hash function: SHA256 func HMACSHA256Tag256KeyTemplate() *tinkpb.KeyTemplate { return createHMACKeyTemplate(32, 32, commonpb.HashType_SHA256) } // HMACSHA512Tag256KeyTemplate is a KeyTemplate that generates a HMAC key with the following parameters: // - Key size: 64 bytes // - Tag size: 32 bytes // - Hash function: SHA512 func HMACSHA512Tag256KeyTemplate() *tinkpb.KeyTemplate { return createHMACKeyTemplate(64, 32, commonpb.HashType_SHA512) } // HMACSHA512Tag512KeyTemplate is a KeyTemplate that generates a HMAC key with the following parameters: // - Key size: 64 bytes // - Tag size: 64 bytes // - Hash function: SHA512 func HMACSHA512Tag512KeyTemplate() *tinkpb.KeyTemplate { return createHMACKeyTemplate(64, 64, commonpb.HashType_SHA512) } // AESCMACTag128KeyTemplate is a KeyTemplate that generates a AES-CMAC key with the following parameters: // - Key size: 32 bytes // - Tag size: 16 bytes func AESCMACTag128KeyTemplate() *tinkpb.KeyTemplate { return createCMACKeyTemplate(32, 16) } // createHMACKeyTemplate creates a new KeyTemplate for HMAC using the given parameters. func createHMACKeyTemplate(keySize, tagSize uint32, hashType commonpb.HashType) *tinkpb.KeyTemplate { params := hmacpb.HmacParams{ Hash: hashType, TagSize: tagSize, } format := hmacpb.HmacKeyFormat{ Params: &params, KeySize: keySize, } serializedFormat, err := proto.Marshal(&format) if err != nil { tinkerror.Fail(fmt.Sprintf("failed to marshal key format: %s", err)) } return &tinkpb.KeyTemplate{ TypeUrl: hmacTypeURL, Value: serializedFormat, OutputPrefixType: tinkpb.OutputPrefixType_TINK, } } // createCMACKeyTemplate creates a new KeyTemplate for CMAC using the given parameters. func createCMACKeyTemplate(keySize uint32, tagSize uint32) *tinkpb.KeyTemplate { params := cmacpb.AesCmacParams{ TagSize: tagSize, } format := cmacpb.AesCmacKeyFormat{ Params: &params, KeySize: keySize, } serializedFormat, err := proto.Marshal(&format) if err != nil { tinkerror.Fail(fmt.Sprintf("failed to marshal key format: %s", err)) } return &tinkpb.KeyTemplate{ TypeUrl: cmacTypeURL, Value: serializedFormat, OutputPrefixType: tinkpb.OutputPrefixType_TINK, } } ================================================ FILE: go/mac/mac_key_templates_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package mac_test import ( "testing" "github.com/google/tink/go/keyset" "github.com/google/tink/go/mac" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestKeyTemplates(t *testing.T) { var testCases = []struct { name string template *tinkpb.KeyTemplate }{ {name: "HMAC_SHA256_128BITTAG", template: mac.HMACSHA256Tag128KeyTemplate()}, {name: "HMAC_SHA256_256BITTAG", template: mac.HMACSHA256Tag256KeyTemplate()}, {name: "HMAC_SHA512_256BITTAG", template: mac.HMACSHA512Tag256KeyTemplate()}, {name: "HMAC_SHA512_512BITTAG", template: mac.HMACSHA512Tag512KeyTemplate()}, {name: "AES_CMAC", template: mac.AESCMACTag128KeyTemplate()}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { handle, err := keyset.NewHandle(tc.template) if err != nil { t.Fatalf("keyset.NewHandle(tc.template) failed: %v", err) } primitive, err := mac.New(handle) if err != nil { t.Fatalf("mac.New(handle) failed: %v", err) } var testInputs = []struct { message1 []byte message2 []byte }{ { message1: []byte("this data needs to be authenticated"), message2: []byte("this data needs to be authenticated"), }, { message1: []byte(""), message2: []byte(""), }, { message1: []byte(""), message2: nil, }, { message1: nil, message2: []byte(""), }, { message1: nil, message2: nil, }, } for _, ti := range testInputs { tag, err := primitive.ComputeMAC(ti.message1) if err != nil { t.Fatalf("primitive.ComputeMAC(ti.message1) failed: %v", err) } if primitive.VerifyMAC(tag, ti.message2); err != nil { t.Errorf("primitive.VerifyMAC(tag, ti.message2) failed: %v", err) } } }) } } ================================================ FILE: go/mac/mac_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package mac_test // [START mac-example] import ( "bytes" "fmt" "log" "github.com/google/tink/go/insecurecleartextkeyset" "github.com/google/tink/go/keyset" "github.com/google/tink/go/mac" ) func Example() { // A keyset created with "tinkey create-keyset --key-template=HMAC_SHA256_128BITTAG". // Note that this keyset has the secret key information in cleartext. jsonKeyset := `{ "key": [{ "keyData": { "keyMaterialType": "SYMMETRIC", "typeUrl": "type.googleapis.com/google.crypto.tink.HmacKey", "value": "EgQIAxAQGiA0LQjovcydWhVQV3k8W9ZSRkd7Ei4Y/TRWApE8guwV4Q==" }, "keyId": 1892702217, "outputPrefixType": "TINK", "status": "ENABLED" }], "primaryKeyId": 1892702217 }` // Create a keyset handle from the cleartext keyset in the previous // step. The keyset handle provides abstract access to the underlying keyset to // limit the exposure of accessing the raw key material. WARNING: In practice, // it is unlikely you will want to use a insecurecleartextkeyset, as it implies // that your key material is passed in cleartext, which is a security risk. // Consider encrypting it with a remote key in Cloud KMS, AWS KMS or HashiCorp Vault. // See https://github.com/google/tink/blob/master/docs/GOLANG-HOWTO.md#storing-and-loading-existing-keysets. keysetHandle, err := insecurecleartextkeyset.Read( keyset.NewJSONReader(bytes.NewBufferString(jsonKeyset))) if err != nil { log.Fatal(err) } // Retrieve the MAC primitive we want to use from the keyset handle. primitive, err := mac.New(keysetHandle) if err != nil { log.Fatal(err) } // Use the primitive to create a MAC tag for some data. In this case the primary // key of the keyset will be used (which is also the only key in this example). data := []byte("data") tag, err := primitive.ComputeMAC(data) if err != nil { log.Fatal(err) } // Use the primitive to verify the tag. VerifyMAC finds the correct key in // the keyset. If no key is found or verification fails, it returns an error. err = primitive.VerifyMAC(tag, data) if err != nil { log.Fatal(err) } fmt.Printf("tag is valid") // Output: tag is valid } // [END mac-example] ================================================ FILE: go/mac/subtle/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep go_library( name = "subtle", srcs = [ "cmac.go", "hmac.go", ], importpath = "github.com/google/tink/go/mac/subtle", deps = [ "//prf/subtle", "//subtle", ], ) go_test( name = "subtle_test", srcs = [ "cmac_test.go", "hmac_test.go", ], data = ["//testdata/testvectors:aes_cmac"], deps = [ ":subtle", "//subtle/random", "//testutil", ], ) alias( name = "go_default_library", actual = ":subtle", visibility = ["//:__subpackages__"], ) ================================================ FILE: go/mac/subtle/cmac.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "crypto/subtle" "fmt" subtleprf "github.com/google/tink/go/prf/subtle" // Placeholder for internal crypto/subtle allowlist, please ignore. ) const ( minCMACKeySizeInBytes = 16 recommendedCMACKeySizeInBytes = uint32(32) minTagLengthInBytes = uint32(10) maxTagLengthInBytes = uint32(16) ) // AESCMAC represents an AES-CMAC struct that implements the MAC interface. type AESCMAC struct { prf *subtleprf.AESCMACPRF tagLength uint32 } // NewAESCMAC creates a new AESCMAC object that implements the MAC interface. func NewAESCMAC(key []byte, tagLength uint32) (*AESCMAC, error) { if len(key) < minCMACKeySizeInBytes { return nil, fmt.Errorf("Only 256 but keys are allowed with AES-CMAC") } if tagLength < minTagLengthInBytes { return nil, fmt.Errorf("Tag length %d is shorter than minimum tag length %d", tagLength, minTagLengthInBytes) } if tagLength > maxTagLengthInBytes { return nil, fmt.Errorf("Tag length %d is longer than maximum tag length %d", tagLength, minTagLengthInBytes) } ac := &AESCMAC{} var err error ac.prf, err = subtleprf.NewAESCMACPRF(key) if err != nil { return nil, fmt.Errorf("Could not create AES-CMAC prf: %v", err) } ac.tagLength = tagLength return ac, nil } // ComputeMAC computes message authentication code (MAC) for code data. func (a AESCMAC) ComputeMAC(data []byte) ([]byte, error) { return a.prf.ComputePRF(data, a.tagLength) } // VerifyMAC returns nil if mac is a correct authentication code (MAC) for data, // otherwise it returns an error. func (a AESCMAC) VerifyMAC(mac, data []byte) error { computed, err := a.prf.ComputePRF(data, a.tagLength) if err != nil { return fmt.Errorf("Could not compute MAC: %v", err) } if subtle.ConstantTimeCompare(mac, computed) != 1 { return fmt.Errorf("CMAC: Invalid MAC") } return nil } // ValidateCMACParams validates the parameters for an AES-CMAC against the recommended parameters. func ValidateCMACParams(keySize, tagSize uint32) error { if keySize != recommendedCMACKeySizeInBytes { return fmt.Errorf("Only %d sized keys are allowed with Tink's AES-CMAC", recommendedCMACKeySizeInBytes) } if tagSize < minTagLengthInBytes { return fmt.Errorf("Tag size too short") } if tagSize > maxTagLengthInBytes { return fmt.Errorf("Tag size too long") } return nil } ================================================ FILE: go/mac/subtle/cmac_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "encoding/hex" "testing" "github.com/google/tink/go/mac/subtle" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" ) var ( // Test vectors from RFC 4493. keyRFC4493, _ = hex.DecodeString("2b7e151628aed2a6abf7158809cf4f3c") dataRFC4493, _ = hex.DecodeString("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710") expected = map[int]string{ 0: "bb1d6929e95937287fa37d129b756746", 16: "070a16b46b4d4144f79bdd9dd04a287c", 40: "dfa66747de9ae63030ca32611497c827", 64: "51f0bebf7e3b9d92fc49741779363cfe", } ) type AESCMACSuite struct { Algorithm string GeneratorVersion string NumberOfTests uint32 TestGroups []*testgroup } type testgroup struct { KeySize uint32 TagSize uint32 Type string Tests []*testcase } type testcase struct { Comment string Key string Msg string Result string Tag string TcID uint32 } func TestVectorsWycheproof(t *testing.T) { testutil.SkipTestIfTestSrcDirIsNotSet(t) suite := new(AESCMACSuite) if err := testutil.PopulateSuite(suite, "aes_cmac_test.json"); err != nil { t.Fatalf("testutil.PopulateSuite: %v", err) } for _, g := range suite.TestGroups { for _, tc := range g.Tests { key, err := hex.DecodeString(tc.Key) if err != nil || uint32(len(key))*8 != g.KeySize { t.Errorf("Could not decode key for test case %d (%s): %v", tc.TcID, tc.Comment, err) continue } msg, err := hex.DecodeString(tc.Msg) if err != nil { t.Errorf("Could not decode message for test case %d (%s): %v", tc.TcID, tc.Comment, err) continue } tag, err := hex.DecodeString(tc.Tag) if err != nil { t.Errorf("Could not decode expected tag for test case %d (%s): %v", tc.TcID, tc.Comment, err) continue } if g.TagSize%8 != 0 { t.Errorf("Requested tag size for test case %d (%s) is not a multiple of 8, but %d", tc.TcID, tc.Comment, g.TagSize) continue } aes, err := subtle.NewAESCMAC(key, g.TagSize/8) valid := tc.Result == "valid" if valid && err != nil { t.Errorf("Could not create subtle.CMAC for test case %d (%s): %v", tc.TcID, tc.Comment, err) continue } if !valid && err != nil { continue } res, err := aes.ComputeMAC(msg) if valid && err != nil { t.Errorf("Could not compute AES-CMAC for test case %d (%s): %v", tc.TcID, tc.Comment, err) continue } if valid && hex.EncodeToString(res) != tc.Tag { t.Errorf("Compute AES-CMAC and expected for test case %d (%s) do not match:\nComputed: %q\nExpected: %q", tc.TcID, tc.Comment, hex.EncodeToString(res), tc.Tag) } if !valid && hex.EncodeToString(res) == tc.Tag && err == nil { t.Errorf("Compute AES-CMAC and invalid expected for test case %d (%s) match:\nComputed: %q\nExpected: %q", tc.TcID, tc.Comment, hex.EncodeToString(res), tc.Tag) } err = aes.VerifyMAC(tag, msg) if valid && err != nil { t.Errorf("Could not verify MAC for test case %d (%s): %v", tc.TcID, tc.Comment, err) } if !valid && err == nil { t.Errorf("Verified invalid MAC for test case %d (%s)", tc.TcID, tc.Comment) } } } } func TestCMACBasic(t *testing.T) { a, err := subtle.NewAESCMAC(keyRFC4493, 16) if err != nil { t.Errorf("Could not create subtle.CMAC object: %v", err) } for l, e := range expected { output, err := a.ComputeMAC(dataRFC4493[:l]) if err != nil { t.Errorf("Error computing AES-CMAC: %v", err) } if hex.EncodeToString(output) != e { t.Errorf("Computation and test vector differ. Computation: %q, Test Vector %q", hex.EncodeToString(output), e) } exp, err := hex.DecodeString(e) if err != nil { t.Errorf("Could not decode expected string %q: %v", e, err) } err = a.VerifyMAC(exp, dataRFC4493[:l]) if err != nil { t.Errorf("Verification of test vector failed. Test Vector %q, Verification %v", e, err) } } } func TestNewCMACWithInvalidInput(t *testing.T) { // key too short _, err := subtle.NewAESCMAC(random.GetRandomBytes(1), 16) if err == nil { t.Errorf("expect an error when key is too short") } // tag too short _, err = subtle.NewAESCMAC(random.GetRandomBytes(16), 9) if err == nil { t.Errorf("expect an error when tag size is too small") } // tag too big _, err = subtle.NewAESCMAC(random.GetRandomBytes(16), 17) if err == nil { t.Errorf("expect an error when tag size is too big") } } func TestCMACComputeVerifyWithNilInput(t *testing.T) { cipher, err := subtle.NewAESCMAC(random.GetRandomBytes(16), 16) if err != nil { t.Errorf("unexpected error when creating new CMAC") } tag, err := cipher.ComputeMAC(nil) if err != nil { t.Errorf("cipher.ComputeMAC(nil) failed: %v", err) } if err := cipher.VerifyMAC(tag, nil); err != nil { t.Errorf("cipher.VerifyMAC(tag, nil) failed: %v", err) } } func TestCMACVerifyMACWithInvalidInput(t *testing.T) { cipher, err := subtle.NewAESCMAC(random.GetRandomBytes(16), 16) if err != nil { t.Errorf("unexpected error when creating new CMAC") } if err := cipher.VerifyMAC(nil, []byte{1}); err == nil { t.Errorf("expect an error when mac is nil") } if err := cipher.VerifyMAC([]byte{1}, nil); err == nil { t.Errorf("expect an error when data is nil") } if err := cipher.VerifyMAC(nil, nil); err == nil { t.Errorf("cipher.VerifyMAC(nil, nil) succeeded unexpectedly") } } func TestCMACModification(t *testing.T) { a, err := subtle.NewAESCMAC(keyRFC4493, 16) if err != nil { t.Errorf("Could not create subtle.CMAC object: %v", err) } for l, e := range expected { exp, err := hex.DecodeString(e) if err != nil { t.Errorf("Could not decode expected string %q: %v", e, err) } for i := 0; i < len(exp); i++ { for j := 0; j < 8; j++ { notExpected := make([]byte, 16) copy(notExpected, exp) notExpected[i] ^= 1 << uint8(j) err = a.VerifyMAC(notExpected, dataRFC4493[:l]) if err == nil { t.Errorf("Verification of modified test vector did not fail. Test Vector %q, Modified: %q", e, hex.EncodeToString(notExpected)) } } } } } func TestCMACTruncation(t *testing.T) { a, err := subtle.NewAESCMAC(keyRFC4493, 16) if err != nil { t.Errorf("Could not create subtle.CMAC object: %v", err) } for l, e := range expected { exp, err := hex.DecodeString(e) if err != nil { t.Errorf("Could not decode expected string %q: %v", e, err) } for i := 1; i < len(exp); i++ { notExpected := exp[:i] err = a.VerifyMAC(notExpected, dataRFC4493[:l]) if err == nil { t.Errorf("Verification of truncated test vector did not fail. Test Vector %q, Modified: %q", e, hex.EncodeToString(notExpected)) } } } } func TestCMACSmallerTagSize(t *testing.T) { for i := 10; i <= 16; i++ { a, err := subtle.NewAESCMAC(keyRFC4493, uint32(i)) if err != nil { t.Errorf("Could not create subtle.CMAC object: %v", err) } for l, e := range expected { exp, err := hex.DecodeString(e) if err != nil { t.Errorf("Could not decode expected string %q: %v", e, err) } err = a.VerifyMAC(exp[:i], dataRFC4493[:l]) if err != nil { t.Errorf("Verification of smaller tag test vector did fail. Test Vector %q, Verification: %v", hex.EncodeToString(exp[:i]), err) } } } } ================================================ FILE: go/mac/subtle/hmac.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package subtle provides subtle implementations of the MAC primitive. package subtle import ( "crypto/hmac" "errors" "fmt" "hash" "github.com/google/tink/go/subtle" ) const ( // Minimum key size in bytes. minKeySizeInBytes = uint32(16) // Minimum tag size in bytes. This provides minimum 80-bit security strength. minTagSizeInBytes = uint32(10) ) var errHMACInvalidInput = errors.New("HMAC: invalid input") // HMAC implementation of interface tink.MAC type HMAC struct { HashFunc func() hash.Hash key []byte TagSize uint32 } // NewHMAC creates a new instance of HMAC with the specified key and tag size. func NewHMAC(hashAlg string, key []byte, tagSize uint32) (*HMAC, error) { keySize := uint32(len(key)) if err := ValidateHMACParams(hashAlg, keySize, tagSize); err != nil { return nil, fmt.Errorf("hmac: %s", err) } hashFunc := subtle.GetHashFunc(hashAlg) if hashFunc == nil { return nil, fmt.Errorf("hmac: invalid hash algorithm") } return &HMAC{ HashFunc: hashFunc, key: key, TagSize: tagSize, }, nil } // ValidateHMACParams validates parameters of HMAC constructor. func ValidateHMACParams(hash string, keySize uint32, tagSize uint32) error { // validate tag size digestSize, err := subtle.GetHashDigestSize(hash) if err != nil { return err } if tagSize > digestSize { return fmt.Errorf("tag size too big") } if tagSize < minTagSizeInBytes { return fmt.Errorf("tag size too small") } // validate key size if keySize < minKeySizeInBytes { return fmt.Errorf("key too short") } return nil } // ComputeMAC computes message authentication code (MAC) for the given data. func (h *HMAC) ComputeMAC(data []byte) ([]byte, error) { if h.HashFunc == nil { return nil, fmt.Errorf("hmac: invalid hash algorithm") } mac := hmac.New(h.HashFunc, h.key) mac.Write(data) tag := mac.Sum(nil) return tag[:h.TagSize], nil } // VerifyMAC verifies whether the given MAC is a correct message authentication // code (MAC) the given data. func (h *HMAC) VerifyMAC(mac []byte, data []byte) error { expectedMAC, err := h.ComputeMAC(data) if err != nil { return err } if hmac.Equal(expectedMAC, mac) { return nil } return errors.New("HMAC: invalid MAC") } ================================================ FILE: go/mac/subtle/hmac_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "encoding/hex" "strings" "testing" "github.com/google/tink/go/mac/subtle" "github.com/google/tink/go/subtle/random" ) var key, _ = hex.DecodeString("000102030405060708090a0b0c0d0e0f") var data = []byte("Hello") var hmacTests = []struct { desc string hashAlg string tagSize uint32 key []byte data []byte expectedMac string }{ { desc: "with SHA256 and 32 byte tag", hashAlg: "SHA256", tagSize: 32, data: data, key: key, expectedMac: "e0ff02553d9a619661026c7aa1ddf59b7b44eac06a9908ff9e19961d481935d4", }, { desc: "with SHA512 and 64 byte tag", hashAlg: "SHA512", tagSize: 64, data: data, key: key, expectedMac: "481e10d823ba64c15b94537a3de3f253c16642451ac45124dd4dde120bf1e5c15" + "e55487d55ba72b43039f235226e7954cd5854b30abc4b5b53171a4177047c9b", }, // empty data { desc: "empty data", hashAlg: "SHA256", tagSize: 32, data: []byte{}, key: key, expectedMac: "07eff8b326b7798c9ccfcbdbe579489ac785a7995a04618b1a2813c26744777d", }, } func TestHMACBasic(t *testing.T) { for _, test := range hmacTests { t.Run(test.desc, func(t *testing.T) { cipher, err := subtle.NewHMAC(test.hashAlg, test.key, test.tagSize) if err != nil { t.Fatalf("subtle.NewHMAC() err = %q, want nil", err) } mac, err := cipher.ComputeMAC(test.data) if err != nil { t.Fatalf("cipher.ComputeMAC() err = %q, want nil", err) } if hex.EncodeToString(mac) != test.expectedMac { t.Errorf("hex.EncodeToString(mac) = %q, want %q", hex.EncodeToString(mac), test.expectedMac) } if err := cipher.VerifyMAC(mac, test.data); err != nil { t.Errorf("cipher.VerifyMAC() err = %q, want nil", err) } }) } } func TestNewHMACWithInvalidInput(t *testing.T) { // invalid hash algorithm _, err := subtle.NewHMAC("MD5", random.GetRandomBytes(16), 32) if err == nil || !strings.Contains(err.Error(), "invalid hash algorithm") { t.Errorf("expect an error when hash algorithm is invalid") } // key too short _, err = subtle.NewHMAC("SHA256", random.GetRandomBytes(1), 32) if err == nil || !strings.Contains(err.Error(), "key too short") { t.Errorf("expect an error when key is too short") } // tag too short _, err = subtle.NewHMAC("SHA256", random.GetRandomBytes(16), 9) if err == nil || !strings.Contains(err.Error(), "tag size too small") { t.Errorf("expect an error when tag size is too small") } // tag too big _, err = subtle.NewHMAC("SHA1", random.GetRandomBytes(16), 21) if err == nil || !strings.Contains(err.Error(), "tag size too big") { t.Errorf("expect an error when tag size is too big") } _, err = subtle.NewHMAC("SHA256", random.GetRandomBytes(16), 33) if err == nil || !strings.Contains(err.Error(), "tag size too big") { t.Errorf("expect an error when tag size is too big") } _, err = subtle.NewHMAC("SHA512", random.GetRandomBytes(16), 65) if err == nil || !strings.Contains(err.Error(), "tag size too big") { t.Errorf("expect an error when tag size is too big") } } func TestHMACWithNilHashFunc(t *testing.T) { cipher, err := subtle.NewHMAC("SHA256", random.GetRandomBytes(32), 32) if err != nil { t.Fatalf("subtle.NewHMAC() err = %v", err) } // Modify exported field. cipher.HashFunc = nil if _, err := cipher.ComputeMAC([]byte{}); err == nil { t.Errorf("cipher.ComputerMAC() err = nil, want not nil") } } func TestHMAComputeVerifyWithNilInput(t *testing.T) { cipher, err := subtle.NewHMAC("SHA256", random.GetRandomBytes(16), 32) if err != nil { t.Errorf("unexpected error when creating new HMAC") } tag, err := cipher.ComputeMAC(nil) if err != nil { t.Errorf("cipher.ComputeMAC(nil) failed: %v", err) } if err := cipher.VerifyMAC(tag, nil); err != nil { t.Errorf("cipher.VerifyMAC(tag, nil) failed: %v", err) } } func TestVerifyMACWithInvalidInput(t *testing.T) { cipher, err := subtle.NewHMAC("SHA256", random.GetRandomBytes(16), 32) if err != nil { t.Errorf("unexpected error when creating new HMAC") } if err := cipher.VerifyMAC(nil, []byte{1}); err == nil { t.Errorf("expect an error when mac is nil") } if err := cipher.VerifyMAC([]byte{1}, nil); err == nil { t.Errorf("expect an error when data is nil") } if err := cipher.VerifyMAC(nil, nil); err == nil { t.Errorf("cipher.VerifyMAC(nil, nil) succeeded unexpectedly") } } func TestHMACModification(t *testing.T) { for _, test := range hmacTests { t.Run(test.desc, func(t *testing.T) { cipher, err := subtle.NewHMAC(test.hashAlg, test.key, test.tagSize) if err != nil { t.Fatalf("subtle.NewHMAC() err = %q, want nil", err) } mac, err := cipher.ComputeMAC(test.data) if err != nil { t.Fatalf("cipher.ComputeMAC() err = %q, want nil", err) } for i := 0; i < len(mac); i++ { tmp := mac[i] for j := 0; j < 8; j++ { mac[i] ^= 1 << uint8(j) err := cipher.VerifyMAC(mac, test.data) if err == nil { t.Errorf("cipher.VerifyMAC() of valid mac modified at position (%d, %d) is nil, want error", i, j) } mac[i] = tmp } } }) } } func TestHMACTruncation(t *testing.T) { for i, test := range hmacTests { t.Run(test.desc, func(t *testing.T) { cipher, err := subtle.NewHMAC(test.hashAlg, test.key, test.tagSize) if err != nil { t.Fatalf("subtle.NewHMAC() err = %q, want nil", err) } mac, err := cipher.ComputeMAC(test.data) if err != nil { t.Fatalf("cipher.ComputeMAC() err = %q, want nil", err) } for truncatedLen := 1; i < len(mac); i++ { truncatedMAC := mac[:truncatedLen] err := cipher.VerifyMAC(truncatedMAC, test.data) if err == nil { t.Errorf("cipher.VerifyMAC() of a valid mac truncated to %d bytes is nil, want error", truncatedLen) } } }) } } ================================================ FILE: go/monitoring/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") package(default_visibility = ["//:__subpackages__"]) # keep licenses(["notice"]) # keep go_library( name = "monitoring", srcs = ["monitoring.go"], importpath = "github.com/google/tink/go/monitoring", ) alias( name = "go_default_library", actual = ":monitoring", visibility = ["//:__subpackages__"], ) ================================================ FILE: go/monitoring/monitoring.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package monitoring defines the structs and interfaces for monitoring primitives with Tink. // This package isn't yet production ready and might go through various changes. package monitoring // KeyStatus represents KeyStatusType in tink/proto/tink.proto. type KeyStatus int const ( // Enabled keys can be used for cryptographic operations. Enabled KeyStatus = iota // Disabled keys can't be used, but can be re-enabled. Disabled // Destroyed keys don't exist in the keyset anymore. Destroyed // DoNotUse is intended to guard from failures that may be caused by future expansions. DoNotUse KeyStatus = 20 ) func (status KeyStatus) String() string { switch status { case Enabled: return "ENABLED" case Disabled: return "DISABLED" case Destroyed: return "DESTROYED" } return "UNKNOWN" } // Entry represents each entry inside a Keyset. type Entry struct { Status KeyStatus KeyID uint32 KeyType string KeyPrefix string } // KeysetInfo represents a keyset in a certain point in time for the // purpose of monitoring operations involving cryptographic keys. type KeysetInfo struct { Annotations map[string]string PrimaryKeyID uint32 Entries []*Entry } // NewKeysetInfo creates a new KeysetInfo. func NewKeysetInfo(annotations map[string]string, primaryKeyID uint32, entries []*Entry) *KeysetInfo { return &KeysetInfo{ Annotations: annotations, PrimaryKeyID: primaryKeyID, Entries: entries, } } // Context defines a context for monitoring events, wich includes the // primitive and API used, and information on the keyset. type Context struct { Primitive string APIFunction string KeysetInfo *KeysetInfo } // NewContext creates a new monitoring context. func NewContext(primitive string, apiFunction string, keysetInfo *KeysetInfo) *Context { return &Context{ Primitive: primitive, APIFunction: apiFunction, KeysetInfo: keysetInfo, } } // Logger is an interface for logging which can be created through a `Client`. // monitoring clients are invoked by Tink during cryptographic operations to emit // certain events. type Logger interface { // Logs a successful use of `keyID` on an input of `numBytes`. Tink primitive // wrappers call this method when they successfully use a key to carry out a // primitive method, e.g. aead.Encrypt(). As a consequence, implementations of // MonitoringClient should be mindful on the amount of work performed by this // method, as this will be called on each cryptographic operation. Implementations // of MonitoringClient are responsible to add context to identify, e.g., the // primitive and the API function. Log(keyID uint32, numBytes int) // Logs a failure. Tink calls this method when a cryptographic operation // failed, e.g. no key could be found to decrypt a ciphertext. In this // case the failure is not associated with a specific key, therefore this // method has no arguments. The MonitoringClient implementation is responsible // to add context to identify where the failure comes from. LogFailure() } // Client represents an interface to hold monitoring client context to create a `Logger`. // A Client is registered with Tink's registry and used by primitives to obtain a `Logger`. type Client interface { NewLogger(context *Context) (Logger, error) } ================================================ FILE: go/prf/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep licenses(["notice"]) # keep go_library( name = "prf", srcs = [ "aes_cmac_prf_key_manager.go", "hkdf_prf_key_manager.go", "hmac_prf_key_manager.go", "prf_key_templates.go", "prf_set.go", "prf_set_factory.go", ], importpath = "github.com/google/tink/go/prf", visibility = ["//visibility:public"], deps = [ "//core/primitiveset", "//core/registry", "//internal/internalregistry", "//internal/monitoringutil", "//internal/tinkerror", "//keyset", "//monitoring", "//prf/subtle", "//proto/aes_cmac_prf_go_proto", "//proto/common_go_proto", "//proto/hkdf_prf_go_proto", "//proto/hmac_prf_go_proto", "//proto/tink_go_proto", "//subtle/random", "@org_golang_google_protobuf//proto", ], ) go_test( name = "prf_test", srcs = [ "aes_cmac_prf_key_manager_test.go", "hkdf_prf_key_manager_test.go", "hmac_prf_key_manager_test.go", "prf_benchmark_test.go", "prf_key_templates_test.go", "prf_set_factory_test.go", "prf_test.go", ], deps = [ ":prf", "//core/registry", "//insecurecleartextkeyset", "//internal/internalregistry", "//keyset", "//mac", "//monitoring", "//prf/subtle", "//proto/aes_cmac_prf_go_proto", "//proto/common_go_proto", "//proto/hkdf_prf_go_proto", "//proto/hmac_prf_go_proto", "//proto/tink_go_proto", "//subtle/random", "//testing/fakemonitoring", "//testutil", "@com_github_google_go_cmp//cmp", "@com_github_google_go_cmp//cmp/cmpopts", "@org_golang_google_protobuf//proto", ], ) alias( name = "go_default_library", actual = ":prf", visibility = ["//visibility:public"], ) ================================================ FILE: go/prf/aes_cmac_prf_key_manager.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package prf import ( "errors" "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/keyset" "github.com/google/tink/go/prf/subtle" "github.com/google/tink/go/subtle/random" cmacpb "github.com/google/tink/go/proto/aes_cmac_prf_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( aescmacprfKeyVersion = 0 aescmacprfTypeURL = "type.googleapis.com/google.crypto.tink.AesCmacPrfKey" ) var errInvalidAESCMACPRFKey = errors.New("aes_cmac_prf_key_manager: invalid key") var errInvalidAESCMACPRFKeyFormat = errors.New("aes_cmac_prf_key_manager: invalid key format") // aescmacprfKeyManager generates new AES-CMAC keys and produces new instances of AES-CMAC. type aescmacprfKeyManager struct{} // Primitive constructs a AES-CMAC instance for the given serialized AESCMACPRFKey. func (km *aescmacprfKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidAESCMACPRFKey } key := new(cmacpb.AesCmacPrfKey) if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errInvalidAESCMACPRFKey } if err := km.validateKey(key); err != nil { return nil, err } return subtle.NewAESCMACPRF(key.KeyValue) } // NewKey generates a new AESCMACPRFKey according to specification in the given AESCMACPRFKeyFormat. func (km *aescmacprfKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errInvalidAESCMACPRFKeyFormat } keyFormat := new(cmacpb.AesCmacPrfKeyFormat) if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, errInvalidAESCMACPRFKeyFormat } if err := km.validateKeyFormat(keyFormat); err != nil { return nil, fmt.Errorf("aes_cmac_prf_key_manager: invalid key format: %s", err) } keyValue := random.GetRandomBytes(keyFormat.KeySize) return &cmacpb.AesCmacPrfKey{ Version: aescmacprfKeyVersion, KeyValue: keyValue, }, nil } // NewKeyData generates a new KeyData according to specification in the given // serialized AESCMACPRFKeyFormat. This should be used solely by the key management API. func (km *aescmacprfKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { key, err := km.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, errInvalidAESCMACPRFKeyFormat } return &tinkpb.KeyData{ TypeUrl: aescmacprfTypeURL, Value: serializedKey, KeyMaterialType: tinkpb.KeyData_SYMMETRIC, }, nil } // DoesSupport checks whether this KeyManager supports the given key type. func (km *aescmacprfKeyManager) DoesSupport(typeURL string) bool { return typeURL == aescmacprfTypeURL } // TypeURL returns the type URL of keys managed by this KeyManager. func (km *aescmacprfKeyManager) TypeURL() string { return aescmacprfTypeURL } // validateKey validates the given AESCMACPRFKey. It only validates the version of the // key because other parameters will be validated in primitive construction. func (km *aescmacprfKeyManager) validateKey(key *cmacpb.AesCmacPrfKey) error { err := keyset.ValidateKeyVersion(key.Version, aescmacprfKeyVersion) if err != nil { return fmt.Errorf("aes_cmac_prf_key_manager: invalid version: %s", err) } keySize := uint32(len(key.KeyValue)) return subtle.ValidateAESCMACPRFParams(keySize) } // validateKeyFormat validates the given HMACKeyFormat func (km *aescmacprfKeyManager) validateKeyFormat(format *cmacpb.AesCmacPrfKeyFormat) error { return subtle.ValidateAESCMACPRFParams(format.KeySize) } ================================================ FILE: go/prf/aes_cmac_prf_key_manager_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package prf_test import ( "encoding/hex" "fmt" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/prf" "github.com/google/tink/go/prf/subtle" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" cmacpb "github.com/google/tink/go/proto/aes_cmac_prf_go_proto" commonpb "github.com/google/tink/go/proto/common_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestGetPrimitiveCMACBasic(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESCMACPRFTypeURL) if err != nil { t.Errorf("AES CMAC PRF key manager not found: %s", err) } testKeys := genValidCMACKeys() for i := 0; i < len(testKeys); i++ { serializedKey, err := proto.Marshal(testKeys[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } p, err := km.Primitive(serializedKey) if err != nil { t.Errorf("unexpected error in test case %d: %s", i, err) } if err := validateCMACPrimitive(p, testKeys[i]); err != nil { t.Errorf("%s", err) } } } func TestGetPrimitiveCMACWithInvalidInput(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESCMACPRFTypeURL) if err != nil { t.Errorf("cannot obtain AES CMAC PRF key manager: %s", err) } // invalid key testKeys := genInvalidCMACKeys() for i := 0; i < len(testKeys); i++ { serializedKey, err := proto.Marshal(testKeys[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := km.Primitive(serializedKey); err == nil { t.Errorf("expect an error in test case %d", i) } } if _, err := km.Primitive(nil); err == nil { t.Errorf("expect an error when input is nil") } // empty input if _, err := km.Primitive([]byte{}); err == nil { t.Errorf("expect an error when input is empty") } } func TestNewKeyCMACMultipleTimes(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESCMACPRFTypeURL) if err != nil { t.Errorf("cannot obtain AES CMAC PRF key manager: %s", err) } serializedFormat, err := proto.Marshal(testutil.NewAESCMACPRFKeyFormat()) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } keys := make(map[string]bool) nTest := 26 for i := 0; i < nTest; i++ { key, err := km.NewKey(serializedFormat) if err != nil { t.Fatalf("km.NewKey() err = %q, want nil", err) } serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } keys[string(serializedKey)] = true keyData, err := km.NewKeyData(serializedFormat) if err != nil { t.Fatalf("km.NewKeyData() err = %q, want nil", err) } serializedKey = keyData.Value keys[string(serializedKey)] = true } if len(keys) != nTest*2 { t.Errorf("key is repeated") } } func TestNewKeyCMACBasic(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESCMACPRFTypeURL) if err != nil { t.Errorf("cannot obtain AES CMAC PRF key manager: %s", err) } testFormats := genValidCMACKeyFormats() for i := 0; i < len(testFormats); i++ { serializedFormat, err := proto.Marshal(testFormats[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } key, err := km.NewKey(serializedFormat) if err != nil { t.Errorf("unexpected error in test case %d: %s", i, err) } if err := validateCMACKey(testFormats[i], key.(*cmacpb.AesCmacPrfKey)); err != nil { t.Errorf("%s", err) } } } func TestNewKeyCMACWithInvalidInput(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESCMACPRFTypeURL) if err != nil { t.Errorf("cannot obtain AES CMAC PRF key manager: %s", err) } // invalid key formats testFormats := genInvalidCMACKeyFormats() for i := 0; i < len(testFormats); i++ { serializedFormat, err := proto.Marshal(testFormats[i]) if err != nil { fmt.Println("Error!") } if _, err := km.NewKey(serializedFormat); err == nil { t.Errorf("expect an error in test case %d: %s", i, err) } } if _, err := km.NewKey(nil); err == nil { t.Errorf("expect an error when input is nil") } // empty input if _, err := km.NewKey([]byte{}); err == nil { t.Errorf("expect an error when input is empty") } } func TestNewKeyDataCMACBasic(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESCMACPRFTypeURL) if err != nil { t.Errorf("cannot obtain AES CMAC PRF key manager: %s", err) } testFormats := genValidCMACKeyFormats() for i := 0; i < len(testFormats); i++ { serializedFormat, err := proto.Marshal(testFormats[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } keyData, err := km.NewKeyData(serializedFormat) if err != nil { t.Errorf("unexpected error in test case %d: %s", i, err) } if keyData.TypeUrl != testutil.AESCMACPRFTypeURL { t.Errorf("incorrect type url in test case %d", i) } if keyData.KeyMaterialType != tinkpb.KeyData_SYMMETRIC { t.Errorf("incorrect key material type in test case %d", i) } key := new(cmacpb.AesCmacPrfKey) if err := proto.Unmarshal(keyData.Value, key); err != nil { t.Errorf("invalid key value") } if err := validateCMACKey(testFormats[i], key); err != nil { t.Errorf("invalid key") } } } func TestNewKeyDataCMACWithInvalidInput(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESCMACPRFTypeURL) if err != nil { t.Errorf("AES CMAC PRF key manager not found: %s", err) } // invalid key formats testFormats := genInvalidCMACKeyFormats() for i := 0; i < len(testFormats); i++ { serializedFormat, err := proto.Marshal(testFormats[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := km.NewKeyData(serializedFormat); err == nil { t.Errorf("expect an error in test case %d", i) } } // nil input if _, err := km.NewKeyData(nil); err == nil { t.Errorf("expect an error when input is nil") } } func TestCMACDoesSupport(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESCMACPRFTypeURL) if err != nil { t.Errorf("AES CMAC PRF key manager not found: %s", err) } if !km.DoesSupport(testutil.AESCMACPRFTypeURL) { t.Errorf("AESCMACPRFKeyManager must support %s", testutil.AESCMACPRFTypeURL) } if km.DoesSupport("some bad type") { t.Errorf("AESCMACPRFKeyManager must support only %s", testutil.AESCMACPRFTypeURL) } } func TestCMACTypeURL(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESCMACPRFTypeURL) if err != nil { t.Errorf("AES CMAC PRF key manager not found: %s", err) } if km.TypeURL() != testutil.AESCMACPRFTypeURL { t.Errorf("incorrect GetKeyType()") } } func genInvalidCMACKeys() []proto.Message { badVersionKey := testutil.NewAESCMACPRFKey() badVersionKey.Version++ shortKey := testutil.NewAESCMACPRFKey() shortKey.KeyValue = []byte{1, 1} return []proto.Message{ // not a AESCMACPRFKey testutil.NewHMACParams(commonpb.HashType_SHA256, 32), // bad version badVersionKey, // key too short shortKey, } } func genInvalidCMACKeyFormats() []proto.Message { shortKeyFormat := testutil.NewAESCMACPRFKeyFormat() shortKeyFormat.KeySize = 1 return []proto.Message{ // not a AESCMACPRFKeyFormat testutil.NewHMACParams(commonpb.HashType_SHA256, 32), // key too short shortKeyFormat, } } func genValidCMACKeyFormats() []*cmacpb.AesCmacPrfKeyFormat { return []*cmacpb.AesCmacPrfKeyFormat{ testutil.NewAESCMACPRFKeyFormat(), } } func genValidCMACKeys() []*cmacpb.AesCmacPrfKey { return []*cmacpb.AesCmacPrfKey{ testutil.NewAESCMACPRFKey(), } } // Checks whether the given CMACPRFKey matches the given key AESCMACPRFKeyFormat func validateCMACKey(format *cmacpb.AesCmacPrfKeyFormat, key *cmacpb.AesCmacPrfKey) error { if format.KeySize != uint32(len(key.KeyValue)) { return fmt.Errorf("key format and generated key do not match") } p, err := subtle.NewAESCMACPRF(key.KeyValue) if err != nil { return fmt.Errorf("cannot create primitive from key: %s", err) } return validateCMACPrimitive(p, key) } // validateCMACPrimitive checks whether the given primitive matches the given AESCMACPRFKey func validateCMACPrimitive(p any, key *cmacpb.AesCmacPrfKey) error { cmacPrimitive := p.(prf.PRF) prfPrimitive, err := subtle.NewAESCMACPRF(key.KeyValue) if err != nil { return fmt.Errorf("Could not create AES CMAC PRF with key material %q: %s", hex.EncodeToString(key.KeyValue), err) } data := random.GetRandomBytes(20) res, err := cmacPrimitive.ComputePRF(data, 16) if err != nil { return fmt.Errorf("prf computation failed: %s", err) } if len(res) != 16 { return fmt.Errorf("prf computation did not produce 16 byte output") } res2, err := prfPrimitive.ComputePRF(data, 16) if err != nil { return fmt.Errorf("prf computation failed: %s", err) } if len(res2) != 16 { return fmt.Errorf("prf computation did not produce 16 byte output") } if hex.EncodeToString(res) != hex.EncodeToString(res2) { return fmt.Errorf("prf computation did not produce the same output for the same key and input") } return nil } ================================================ FILE: go/prf/hkdf_prf_key_manager.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package prf import ( "errors" "fmt" "io" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/keyset" "github.com/google/tink/go/prf/subtle" "github.com/google/tink/go/subtle/random" commonpb "github.com/google/tink/go/proto/common_go_proto" hkdfpb "github.com/google/tink/go/proto/hkdf_prf_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( hkdfprfKeyVersion = 0 hkdfprfTypeURL = "type.googleapis.com/google.crypto.tink.HkdfPrfKey" ) var errInvalidHKDFPRFKey = errors.New("hkdf_prf_key_manager: invalid key") var errInvalidHKDFPRFKeyFormat = errors.New("hkdf_prf_key_manager: invalid key format") // hkdfprfKeyManager generates new HKDF PRF keys and produces new instances of HKDF. type hkdfprfKeyManager struct{} // Assert that hkdfprfKeyManager implements the KeyManager interface. var _ registry.KeyManager = (*hkdfprfKeyManager)(nil) // Primitive constructs a HKDF instance for the given serialized HKDFKey. func (km *hkdfprfKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidHKDFPRFKey } key := new(hkdfpb.HkdfPrfKey) if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errInvalidHKDFPRFKey } if err := km.validateKey(key); err != nil { return nil, err } hash := commonpb.HashType_name[int32(key.GetParams().GetHash())] hkdf, err := subtle.NewHKDFPRF(hash, key.GetKeyValue(), key.GetParams().GetSalt()) if err != nil { return nil, err } return hkdf, nil } // NewKey generates a new HKDFPRFKey according to specification in the given HKDFPRFKeyFormat. func (km *hkdfprfKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errInvalidHKDFPRFKeyFormat } keyFormat := new(hkdfpb.HkdfPrfKeyFormat) if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, errInvalidHKDFPRFKeyFormat } if err := km.validateKeyFormat(keyFormat); err != nil { return nil, fmt.Errorf("hkdf_prf_key_manager: invalid key format: %s", err) } keyValue := random.GetRandomBytes(keyFormat.GetKeySize()) return &hkdfpb.HkdfPrfKey{ Version: hkdfprfKeyVersion, Params: keyFormat.GetParams(), KeyValue: keyValue, }, nil } // NewKeyData generates a new KeyData according to specification in the given // serialized HKDFPRFKeyFormat. This should be used solely by the key management API. func (km *hkdfprfKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { key, err := km.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, errInvalidHKDFPRFKeyFormat } return &tinkpb.KeyData{ TypeUrl: hkdfprfTypeURL, Value: serializedKey, KeyMaterialType: km.KeyMaterialType(), }, nil } // DoesSupport checks whether this KeyManager supports the given key type. func (km *hkdfprfKeyManager) DoesSupport(typeURL string) bool { return typeURL == hkdfprfTypeURL } // TypeURL returns the type URL of keys managed by this KeyManager. func (km *hkdfprfKeyManager) TypeURL() string { return hkdfprfTypeURL } // KeyMaterialType returns the key material type of this KeyManager. func (km *hkdfprfKeyManager) KeyMaterialType() tinkpb.KeyData_KeyMaterialType { return tinkpb.KeyData_SYMMETRIC } // DeriveKey derives a new key from serializedKeyFormat and pseudorandomness. func (km *hkdfprfKeyManager) DeriveKey(serializedKeyFormat []byte, pseudorandomness io.Reader) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errInvalidHKDFPRFKeyFormat } keyFormat := new(hkdfpb.HkdfPrfKeyFormat) if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, errInvalidHKDFPRFKeyFormat } if err := km.validateKeyFormat(keyFormat); err != nil { return nil, fmt.Errorf("hkdf_prf_key_manager: invalid key format: %s", err) } if err := keyset.ValidateKeyVersion(keyFormat.GetVersion(), hkdfprfKeyVersion); err != nil { return nil, fmt.Errorf("hkdf_prf_key_manager: invalid key version: %s", err) } keyValue := make([]byte, keyFormat.GetKeySize()) if _, err := io.ReadFull(pseudorandomness, keyValue); err != nil { return nil, fmt.Errorf("hkdf_prf_key_manager: not enough pseudorandomness given") } return &hkdfpb.HkdfPrfKey{ Version: hkdfprfKeyVersion, Params: keyFormat.GetParams(), KeyValue: keyValue, }, nil } // validateKey validates the given HKDFPRFKey. It only validates the version of the // key because other parameters will be validated in primitive construction. func (km *hkdfprfKeyManager) validateKey(key *hkdfpb.HkdfPrfKey) error { if err := keyset.ValidateKeyVersion(key.GetVersion(), hkdfprfKeyVersion); err != nil { return fmt.Errorf("hkdf_prf_key_manager: invalid version: %s", err) } keySize := uint32(len(key.GetKeyValue())) hash := commonpb.HashType_name[int32(key.GetParams().GetHash())] return subtle.ValidateHKDFPRFParams(hash, keySize, key.GetParams().GetSalt()) } // validateKeyFormat validates the given HKDFKeyFormat func (km *hkdfprfKeyManager) validateKeyFormat(format *hkdfpb.HkdfPrfKeyFormat) error { hash := commonpb.HashType_name[int32(format.GetParams().GetHash())] return subtle.ValidateHKDFPRFParams(hash, format.GetKeySize(), format.GetParams().GetSalt()) } ================================================ FILE: go/prf/hkdf_prf_key_manager_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package prf_test import ( "bytes" "encoding/hex" "fmt" "testing" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/prf" "github.com/google/tink/go/prf/subtle" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" commonpb "github.com/google/tink/go/proto/common_go_proto" hkdfpb "github.com/google/tink/go/proto/hkdf_prf_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestGetPrimitiveHKDFBasic(t *testing.T) { km, err := registry.GetKeyManager(testutil.HKDFPRFTypeURL) if err != nil { t.Errorf("HKDF PRF key manager not found: %s", err) } testKeys := genValidHKDFKeys() for i := 0; i < len(testKeys); i++ { serializedKey, err := proto.Marshal(testKeys[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } p, err := km.Primitive(serializedKey) if err != nil { t.Errorf("unexpected error in test case %d: %s", i, err) } if err := validateHKDFPrimitive(p, testKeys[i]); err != nil { t.Errorf("%s", err) } } } func TestGetPrimitiveHKDFWithInvalidInput(t *testing.T) { km, err := registry.GetKeyManager(testutil.HKDFPRFTypeURL) if err != nil { t.Errorf("cannot obtain HKDF PRF key manager: %s", err) } // invalid key testKeys := genInvalidHKDFKeys() for i := 0; i < len(testKeys); i++ { serializedKey, err := proto.Marshal(testKeys[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := km.Primitive(serializedKey); err == nil { t.Errorf("expect an error in test case %d", i) } } if _, err := km.Primitive(nil); err == nil { t.Errorf("expect an error when input is nil") } // empty input if _, err := km.Primitive([]byte{}); err == nil { t.Errorf("expect an error when input is empty") } } func TestNewKeyHKDFMultipleTimes(t *testing.T) { km, err := registry.GetKeyManager(testutil.HKDFPRFTypeURL) if err != nil { t.Errorf("cannot obtain HKDF PRF key manager: %s", err) } serializedFormat, err := proto.Marshal(testutil.NewHKDFPRFKeyFormat(commonpb.HashType_SHA256, make([]byte, 0))) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } keys := make(map[string]bool) nTest := 26 for i := 0; i < nTest; i++ { key, err := km.NewKey(serializedFormat) if err != nil { t.Fatalf("km.NewKey() err = %q, want nil", err) } serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } keys[string(serializedKey)] = true keyData, err := km.NewKeyData(serializedFormat) if err != nil { t.Fatalf("km.NewKeyData() err = %q, want nil", err) } serializedKey = keyData.Value keys[string(serializedKey)] = true } if len(keys) != nTest*2 { t.Errorf("key is repeated") } } func TestNewKeyHKDFBasic(t *testing.T) { km, err := registry.GetKeyManager(testutil.HKDFPRFTypeURL) if err != nil { t.Errorf("cannot obtain HKDF PRF key manager: %s", err) } testFormats := genValidHKDFKeyFormats() for i := 0; i < len(testFormats); i++ { serializedFormat, err := proto.Marshal(testFormats[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } key, err := km.NewKey(serializedFormat) if err != nil { t.Errorf("unexpected error in test case %d: %s", i, err) } if err := validateHKDFKey(testFormats[i], key.(*hkdfpb.HkdfPrfKey)); err != nil { t.Errorf("%s", err) } } } func TestNewKeyHKDFWithInvalidInput(t *testing.T) { km, err := registry.GetKeyManager(testutil.HKDFPRFTypeURL) if err != nil { t.Errorf("cannot obtain HKDF PRF key manager: %s", err) } // invalid key formats testFormats := genInvalidHKDFKeyFormats() for i := 0; i < len(testFormats); i++ { serializedFormat, err := proto.Marshal(testFormats[i]) if err != nil { fmt.Println("Error!") } if _, err := km.NewKey(serializedFormat); err == nil { t.Errorf("expect an error in test case %d: %s", i, err) } } if _, err := km.NewKey(nil); err == nil { t.Errorf("expect an error when input is nil") } // empty input if _, err := km.NewKey([]byte{}); err == nil { t.Errorf("expect an error when input is empty") } } func TestNewKeyDataHKDFBasic(t *testing.T) { km, err := registry.GetKeyManager(testutil.HKDFPRFTypeURL) if err != nil { t.Errorf("cannot obtain HKDF PRF key manager: %s", err) } testFormats := genValidHKDFKeyFormats() for i := 0; i < len(testFormats); i++ { serializedFormat, err := proto.Marshal(testFormats[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } keyData, err := km.NewKeyData(serializedFormat) if err != nil { t.Errorf("unexpected error in test case %d: %s", i, err) } if keyData.TypeUrl != testutil.HKDFPRFTypeURL { t.Errorf("incorrect type url in test case %d", i) } if keyData.KeyMaterialType != tinkpb.KeyData_SYMMETRIC { t.Errorf("incorrect key material type in test case %d", i) } key := new(hkdfpb.HkdfPrfKey) if err := proto.Unmarshal(keyData.Value, key); err != nil { t.Errorf("invalid key value") } if err := validateHKDFKey(testFormats[i], key); err != nil { t.Errorf("invalid key") } } } func TestNewKeyDataHKDFWithInvalidInput(t *testing.T) { km, err := registry.GetKeyManager(testutil.HKDFPRFTypeURL) if err != nil { t.Errorf("HKDF PRF key manager not found: %s", err) } // invalid key formats testFormats := genInvalidHKDFKeyFormats() for i := 0; i < len(testFormats); i++ { serializedFormat, err := proto.Marshal(testFormats[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := km.NewKeyData(serializedFormat); err == nil { t.Errorf("expect an error in test case %d", i) } } // nil input if _, err := km.NewKeyData(nil); err == nil { t.Errorf("expect an error when input is nil") } } func TestHKDFDoesSupport(t *testing.T) { km, err := registry.GetKeyManager(testutil.HKDFPRFTypeURL) if err != nil { t.Errorf("HKDF PRF key manager not found: %s", err) } if !km.DoesSupport(testutil.HKDFPRFTypeURL) { t.Errorf("HKDFPRFKeyManager must support %s", testutil.HKDFPRFTypeURL) } if km.DoesSupport("some bad type") { t.Errorf("HKDFPRFKeyManager must support only %s", testutil.HKDFPRFTypeURL) } } func TestHKDFTypeURL(t *testing.T) { km, err := registry.GetKeyManager(testutil.HKDFPRFTypeURL) if err != nil { t.Errorf("HKDF PRF key manager not found: %s", err) } if km.TypeURL() != testutil.HKDFPRFTypeURL { t.Errorf("incorrect GetKeyType()") } } func TestHKDFKeyMaterialType(t *testing.T) { km, err := registry.GetKeyManager(testutil.HKDFPRFTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.HKDFPRFTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } if got, want := keyManager.KeyMaterialType(), tinkpb.KeyData_SYMMETRIC; got != want { t.Errorf("KeyMaterialType() = %v, want %v", got, want) } } func TestHKDFDeriveKey(t *testing.T) { km, err := registry.GetKeyManager(testutil.HKDFPRFTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.HKDFPRFTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } var keySize uint32 = 32 for _, test := range []struct { name string hashType commonpb.HashType salt []byte }{ { name: "SHA256", hashType: commonpb.HashType_SHA256, salt: make([]byte, 0), }, { name: "SHA256/salt", hashType: commonpb.HashType_SHA256, salt: []byte{0x01, 0x03, 0x42}, }, { name: "SHA512", hashType: commonpb.HashType_SHA512, salt: make([]byte, 0), }, { name: "SHA512/salt", hashType: commonpb.HashType_SHA512, salt: []byte{0x01, 0x03, 0x42}, }, } { t.Run(test.name, func(t *testing.T) { keyFormat := testutil.NewHKDFPRFKeyFormat(test.hashType, test.salt) serializedKeyFormat, err := proto.Marshal(keyFormat) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", keyFormat, err) } rand := random.GetRandomBytes(keySize) buf := &bytes.Buffer{} buf.Write(rand) // never returns a non-nil error k, err := keyManager.DeriveKey(serializedKeyFormat, buf) if err != nil { t.Fatalf("keyManager.DeriveKey() err = %v, want nil", err) } key := k.(*hkdfpb.HkdfPrfKey) if got, want := len(key.GetKeyValue()), int(keySize); got != want { t.Errorf("key length = %d, want %d", got, want) } if diff := cmp.Diff(key.GetKeyValue(), rand); diff != "" { t.Errorf("incorrect derived key: diff = %v", diff) } }) } } func TestHKDFDeriveKeyFailsWithInvalidKeyFormats(t *testing.T) { km, err := registry.GetKeyManager(testutil.HKDFPRFTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.HKDFPRFTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } var keySize uint32 = 32 validKeyFormat := &hkdfpb.HkdfPrfKeyFormat{ Params: testutil.NewHKDFPRFParams(commonpb.HashType_SHA256, make([]byte, 0)), KeySize: keySize, Version: 0, } serializedValidKeyFormat, err := proto.Marshal(validKeyFormat) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", validKeyFormat, err) } buf := bytes.NewBuffer(random.GetRandomBytes(keySize)) if _, err := keyManager.DeriveKey(serializedValidKeyFormat, buf); err != nil { t.Fatalf("keyManager.DeriveKey() err = %v, want nil", err) } for _, test := range []struct { name string keyFormat *hkdfpb.HkdfPrfKeyFormat randLen uint32 }{ { name: "invalid key size", keyFormat: &hkdfpb.HkdfPrfKeyFormat{ Params: validKeyFormat.GetParams(), KeySize: 16, Version: validKeyFormat.GetVersion(), }, randLen: keySize, }, { name: "not enough randomness", keyFormat: validKeyFormat, randLen: 16, }, { name: "invalid version", keyFormat: &hkdfpb.HkdfPrfKeyFormat{ Params: validKeyFormat.GetParams(), KeySize: validKeyFormat.GetKeySize(), Version: 100000, }, randLen: keySize, }, { name: "empty key format", keyFormat: &hkdfpb.HkdfPrfKeyFormat{}, randLen: keySize, }, { name: "nil key format", randLen: keySize, }, } { t.Run(test.name, func(t *testing.T) { serializedKeyFormat, err := proto.Marshal(test.keyFormat) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", test.keyFormat, err) } buf := bytes.NewBuffer(random.GetRandomBytes(test.randLen)) if _, err := keyManager.DeriveKey(serializedKeyFormat, buf); err == nil { t.Errorf("keyManager.DeriveKey() err = nil, want non-nil") } }) } } func TestHKDFDeriveKeyFailsWithMalformedSerializedKeyFormat(t *testing.T) { km, err := registry.GetKeyManager(testutil.HKDFPRFTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.HKDFPRFTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } var keySize uint32 = 32 malformedSerializedKeyFormat := random.GetRandomBytes( uint32( proto.Size(&hkdfpb.HkdfPrfKeyFormat{ Params: testutil.NewHKDFPRFParams(commonpb.HashType_SHA256, make([]byte, 0)), KeySize: keySize, Version: 0, }))) buf := bytes.NewBuffer(random.GetRandomBytes(keySize)) if _, err := keyManager.DeriveKey(malformedSerializedKeyFormat, buf); err == nil { t.Errorf("keyManager.DeriveKey() err = nil, want non-nil") } } func TestAESGCMDeriveKeyFailsWithInsufficientRandomness(t *testing.T) { km, err := registry.GetKeyManager(testutil.HKDFPRFTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.HKDFPRFTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } keyFormat, err := proto.Marshal(testutil.NewHKDFPRFKeyFormat(commonpb.HashType_SHA256, []byte("salty"))) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } var keySize uint32 = 32 { buf := bytes.NewBuffer(random.GetRandomBytes(keySize)) if _, err := keyManager.DeriveKey(keyFormat, buf); err != nil { t.Errorf("keyManager.DeriveKey() err = %v, want nil", err) } } { insufficientBuf := bytes.NewBuffer(random.GetRandomBytes(keySize - 1)) if _, err := keyManager.DeriveKey(keyFormat, insufficientBuf); err == nil { t.Errorf("keyManager.DeriveKey() err = nil, want non-nil") } } } func genInvalidHKDFKeys() []proto.Message { badVersionKey := testutil.NewHKDFPRFKey(commonpb.HashType_SHA256, make([]byte, 0)) badVersionKey.Version++ shortKey := testutil.NewHKDFPRFKey(commonpb.HashType_SHA256, make([]byte, 0)) shortKey.KeyValue = []byte{1, 1} nilParams := testutil.NewHKDFPRFKey(commonpb.HashType_SHA256, make([]byte, 0)) nilParams.Params = nil return []proto.Message{ // not a HKDFPRFKey testutil.NewHKDFPRFParams(commonpb.HashType_SHA256, make([]byte, 0)), // bad version badVersionKey, // key too short shortKey, // SHA-1 testutil.NewHKDFPRFKey(commonpb.HashType_SHA1, make([]byte, 0)), // unknown hash type testutil.NewHKDFPRFKey(commonpb.HashType_UNKNOWN_HASH, make([]byte, 0)), // params field is unset nilParams, } } func genInvalidHKDFKeyFormats() []proto.Message { shortKeyFormat := testutil.NewHKDFPRFKeyFormat(commonpb.HashType_SHA256, make([]byte, 0)) shortKeyFormat.KeySize = 1 nilParams := testutil.NewHKDFPRFKeyFormat(commonpb.HashType_SHA256, make([]byte, 0)) nilParams.Params = nil return []proto.Message{ // not a HKDFPRFKeyFormat testutil.NewHMACParams(commonpb.HashType_SHA256, 32), // key too short shortKeyFormat, // SHA-1 testutil.NewHKDFPRFKeyFormat(commonpb.HashType_SHA1, make([]byte, 0)), // unknown hash type testutil.NewHKDFPRFKeyFormat(commonpb.HashType_UNKNOWN_HASH, make([]byte, 0)), // params field is unset nilParams, } } func genValidHKDFKeyFormats() []*hkdfpb.HkdfPrfKeyFormat { return []*hkdfpb.HkdfPrfKeyFormat{ testutil.NewHKDFPRFKeyFormat(commonpb.HashType_SHA256, make([]byte, 0)), testutil.NewHKDFPRFKeyFormat(commonpb.HashType_SHA512, make([]byte, 0)), testutil.NewHKDFPRFKeyFormat(commonpb.HashType_SHA256, []byte{0x01, 0x03, 0x42}), testutil.NewHKDFPRFKeyFormat(commonpb.HashType_SHA512, []byte{0x01, 0x03, 0x42}), } } func genValidHKDFKeys() []*hkdfpb.HkdfPrfKey { return []*hkdfpb.HkdfPrfKey{ testutil.NewHKDFPRFKey(commonpb.HashType_SHA256, make([]byte, 0)), testutil.NewHKDFPRFKey(commonpb.HashType_SHA512, make([]byte, 0)), testutil.NewHKDFPRFKey(commonpb.HashType_SHA256, []byte{0x01, 0x03, 0x42}), testutil.NewHKDFPRFKey(commonpb.HashType_SHA512, []byte{0x01, 0x03, 0x42}), } } // Checks whether the given HKDFPRFKey matches the given key HKDFPRFKeyFormat func validateHKDFKey(format *hkdfpb.HkdfPrfKeyFormat, key *hkdfpb.HkdfPrfKey) error { if format.KeySize != uint32(len(key.KeyValue)) || key.Params.Hash != format.Params.Hash { return fmt.Errorf("key format and generated key do not match") } p, err := subtle.NewHKDFPRF(commonpb.HashType_name[int32(key.Params.Hash)], key.KeyValue, key.Params.Salt) if err != nil { return fmt.Errorf("cannot create primitive from key: %s", err) } return validateHKDFPrimitive(p, key) } // validateHKDFPrimitive checks whether the given primitive matches the given HKDFPRFKey func validateHKDFPrimitive(p any, key *hkdfpb.HkdfPrfKey) error { hkdfPrimitive := p.(prf.PRF) prfPrimitive, err := subtle.NewHKDFPRF(commonpb.HashType_name[int32(key.Params.Hash)], key.KeyValue, key.Params.Salt) if err != nil { return fmt.Errorf("Could not create HKDF PRF with key material %q: %s", hex.EncodeToString(key.KeyValue), err) } data := random.GetRandomBytes(20) res, err := hkdfPrimitive.ComputePRF(data, 16) if err != nil { return fmt.Errorf("prf computation failed: %s", err) } if len(res) != 16 { return fmt.Errorf("prf computation did not produce 16 byte output") } res2, err := prfPrimitive.ComputePRF(data, 16) if err != nil { return fmt.Errorf("prf computation failed: %s", err) } if len(res2) != 16 { return fmt.Errorf("prf computation did not produce 16 byte output") } if hex.EncodeToString(res) != hex.EncodeToString(res2) { return fmt.Errorf("prf computation did not produce the same output for the same key and input") } return nil } ================================================ FILE: go/prf/hmac_prf_key_manager.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package prf import ( "errors" "fmt" "io" "google.golang.org/protobuf/proto" "github.com/google/tink/go/keyset" "github.com/google/tink/go/prf/subtle" "github.com/google/tink/go/subtle/random" commonpb "github.com/google/tink/go/proto/common_go_proto" hmacpb "github.com/google/tink/go/proto/hmac_prf_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( hmacprfKeyVersion = 0 hmacprfTypeURL = "type.googleapis.com/google.crypto.tink.HmacPrfKey" ) var errInvalidHMACPRFKey = errors.New("hmac_prf_key_manager: invalid key") var errInvalidHMACPRFKeyFormat = errors.New("hmac_prf_key_manager: invalid key format") // hmacprfKeyManager generates new HMAC PRF keys and produces new instances of HMAC. type hmacprfKeyManager struct{} // Primitive constructs a HMAC instance for the given serialized HMACKey. func (km *hmacprfKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidHMACPRFKey } key := new(hmacpb.HmacPrfKey) if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errInvalidHMACPRFKey } if err := km.validateKey(key); err != nil { return nil, err } hash := commonpb.HashType_name[int32(key.GetParams().GetHash())] hmac, err := subtle.NewHMACPRF(hash, key.GetKeyValue()) if err != nil { return nil, err } return hmac, nil } // NewKey generates a new HMACPRFKey according to specification in the given HMACPRFKeyFormat. func (km *hmacprfKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errInvalidHMACPRFKeyFormat } keyFormat := new(hmacpb.HmacPrfKeyFormat) if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, errInvalidHMACPRFKeyFormat } if err := km.validateKeyFormat(keyFormat); err != nil { return nil, fmt.Errorf("hmac_prf_key_manager: invalid key format: %s", err) } return &hmacpb.HmacPrfKey{ Version: hmacprfKeyVersion, Params: keyFormat.GetParams(), KeyValue: random.GetRandomBytes(keyFormat.GetKeySize()), }, nil } // NewKeyData generates a new KeyData according to specification in the given // serialized HMACPRFKeyFormat. This should be used solely by the key management API. func (km *hmacprfKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { key, err := km.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, errInvalidHMACPRFKeyFormat } return &tinkpb.KeyData{ TypeUrl: hmacprfTypeURL, Value: serializedKey, KeyMaterialType: km.KeyMaterialType(), }, nil } // DoesSupport checks whether this KeyManager supports the given key type. func (km *hmacprfKeyManager) DoesSupport(typeURL string) bool { return typeURL == hmacprfTypeURL } // TypeURL returns the type URL of keys managed by this KeyManager. func (km *hmacprfKeyManager) TypeURL() string { return hmacprfTypeURL } // validateKey validates the given HMACPRFKey. It only validates the version of the // key because other parameters will be validated in primitive construction. func (km *hmacprfKeyManager) validateKey(key *hmacpb.HmacPrfKey) error { if err := keyset.ValidateKeyVersion(key.GetVersion(), hmacprfKeyVersion); err != nil { return fmt.Errorf("hmac_prf_key_manager: invalid version: %s", err) } keySize := uint32(len(key.GetKeyValue())) hash := commonpb.HashType_name[int32(key.GetParams().GetHash())] return subtle.ValidateHMACPRFParams(hash, keySize) } // KeyMaterialType returns the key material type of this key manager. func (km *hmacprfKeyManager) KeyMaterialType() tinkpb.KeyData_KeyMaterialType { return tinkpb.KeyData_SYMMETRIC } // DeriveKey derives a new key from serializedKeyFormat and pseudorandomness. func (km *hmacprfKeyManager) DeriveKey(serializedKeyFormat []byte, pseudorandomness io.Reader) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errInvalidHMACPRFKeyFormat } keyFormat := new(hmacpb.HmacPrfKeyFormat) if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, errInvalidHMACPRFKeyFormat } if err := km.validateKeyFormat(keyFormat); err != nil { return nil, fmt.Errorf("hmac_key_manager: invalid key format: %v", err) } if err := keyset.ValidateKeyVersion(keyFormat.GetVersion(), hmacprfKeyVersion); err != nil { return nil, fmt.Errorf("hmac_key_manager: invalid key version: %s", err) } keyValue := make([]byte, keyFormat.GetKeySize()) if _, err := io.ReadFull(pseudorandomness, keyValue); err != nil { return nil, fmt.Errorf("hmac_key_manager: not enough pseudorandomness given") } return &hmacpb.HmacPrfKey{ Version: hmacprfKeyVersion, Params: keyFormat.GetParams(), KeyValue: keyValue, }, nil } // validateKeyFormat validates the given HMACKeyFormat func (km *hmacprfKeyManager) validateKeyFormat(format *hmacpb.HmacPrfKeyFormat) error { hash := commonpb.HashType_name[int32(format.GetParams().GetHash())] return subtle.ValidateHMACPRFParams(hash, format.GetKeySize()) } ================================================ FILE: go/prf/hmac_prf_key_manager_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package prf_test import ( "bytes" "encoding/hex" "fmt" "testing" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/prf" "github.com/google/tink/go/prf/subtle" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" commonpb "github.com/google/tink/go/proto/common_go_proto" hmacpb "github.com/google/tink/go/proto/hmac_prf_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestGetPrimitiveHMACBasic(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACPRFTypeURL) if err != nil { t.Errorf("HMAC PRF key manager not found: %s", err) } testKeys := genValidHMACPRFKeys() for i := 0; i < len(testKeys); i++ { serializedKey, err := proto.Marshal(testKeys[i]) if err != nil { t.Errorf("proto.Marshal() err = %q, want nil", err) } p, err := km.Primitive(serializedKey) if err != nil { t.Errorf("unexpected error in test case %d: %s", i, err) } if err := validateHMACPRFPrimitive(p, testKeys[i]); err != nil { t.Errorf("%s", err) } } } func TestGetPrimitiveHMACWithInvalidInput(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACPRFTypeURL) if err != nil { t.Errorf("cannot obtain HMAC PRFkey manager: %s", err) } // invalid key testKeys := genInvalidHMACPRFKeys() for i := 0; i < len(testKeys); i++ { serializedKey, err := proto.Marshal(testKeys[i]) if err != nil { t.Errorf("proto.Marshal() err = %q, want nil", err) } if _, err := km.Primitive(serializedKey); err == nil { t.Errorf("expect an error in test case %d", i) } } if _, err := km.Primitive(nil); err == nil { t.Errorf("expect an error when input is nil") } // empty input if _, err := km.Primitive([]byte{}); err == nil { t.Errorf("expect an error when input is empty") } } func TestNewKeyHMACMultipleTimes(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACPRFTypeURL) if err != nil { t.Errorf("cannot obtain HMAC PRF key manager: %s", err) } serializedFormat, err := proto.Marshal(testutil.NewHMACPRFKeyFormat(commonpb.HashType_SHA256)) if err != nil { t.Errorf("proto.Marshal() err = %q, want nil", err) } keys := make(map[string]bool) nTest := 26 for i := 0; i < nTest; i++ { key, err := km.NewKey(serializedFormat) if err != nil { t.Fatalf("km.NewKey() err = %q, want nil", err) } serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } keys[string(serializedKey)] = true keyData, err := km.NewKeyData(serializedFormat) if err != nil { t.Fatalf("km.NewKeyData() err = %q, want nil", err) } serializedKey = keyData.Value keys[string(serializedKey)] = true } if len(keys) != nTest*2 { t.Errorf("key is repeated") } } func TestNewKeyHMACBasic(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACPRFTypeURL) if err != nil { t.Errorf("cannot obtain HMAC PRF key manager: %s", err) } testFormats := genValidHMACPRFKeyFormats() for i := 0; i < len(testFormats); i++ { serializedFormat, err := proto.Marshal(testFormats[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } key, err := km.NewKey(serializedFormat) if err != nil { t.Errorf("unexpected error in test case %d: %s", i, err) } if err := validateHMACPRFKey(testFormats[i], key.(*hmacpb.HmacPrfKey)); err != nil { t.Errorf("%s", err) } } } func TestNewKeyHMACWithInvalidInput(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACPRFTypeURL) if err != nil { t.Errorf("cannot obtain HMAC PRF key manager: %s", err) } // invalid key formats testFormats := genInvalidHMACPRFKeyFormats() for i := 0; i < len(testFormats); i++ { serializedFormat, err := proto.Marshal(testFormats[i]) if err != nil { fmt.Println("Error!") } if _, err := km.NewKey(serializedFormat); err == nil { t.Errorf("expect an error in test case %d: %s", i, err) } } if _, err := km.NewKey(nil); err == nil { t.Errorf("expect an error when input is nil") } // empty input if _, err := km.NewKey([]byte{}); err == nil { t.Errorf("expect an error when input is empty") } } func TestNewKeyDataHMACBasic(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACPRFTypeURL) if err != nil { t.Errorf("cannot obtain HMAC PRF key manager: %s", err) } testFormats := genValidHMACPRFKeyFormats() for i := 0; i < len(testFormats); i++ { serializedFormat, err := proto.Marshal(testFormats[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } keyData, err := km.NewKeyData(serializedFormat) if err != nil { t.Errorf("unexpected error in test case %d: %s", i, err) } if keyData.TypeUrl != testutil.HMACPRFTypeURL { t.Errorf("incorrect type url in test case %d", i) } if keyData.KeyMaterialType != tinkpb.KeyData_SYMMETRIC { t.Errorf("incorrect key material type in test case %d", i) } key := new(hmacpb.HmacPrfKey) if err := proto.Unmarshal(keyData.Value, key); err != nil { t.Errorf("invalid key value") } if err := validateHMACPRFKey(testFormats[i], key); err != nil { t.Errorf("invalid key") } } } func TestNewKeyDataHMACWithInvalidInput(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACPRFTypeURL) if err != nil { t.Errorf("HMAC PRF key manager not found: %s", err) } // invalid key formats testFormats := genInvalidHMACPRFKeyFormats() for i := 0; i < len(testFormats); i++ { serializedFormat, err := proto.Marshal(testFormats[i]) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := km.NewKeyData(serializedFormat); err == nil { t.Errorf("expect an error in test case %d", i) } } // nil input if _, err := km.NewKeyData(nil); err == nil { t.Errorf("expect an error when input is nil") } } func TestHMACDoesSupport(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACPRFTypeURL) if err != nil { t.Errorf("HMAC PRF key manager not found: %s", err) } if !km.DoesSupport(testutil.HMACPRFTypeURL) { t.Errorf("HMACPRFKeyManager must support %s", testutil.HMACPRFTypeURL) } if km.DoesSupport("some bad type") { t.Errorf("HMACPRFKeyManager must support only %s", testutil.HMACPRFTypeURL) } } func TestHMACTypeURL(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACPRFTypeURL) if err != nil { t.Errorf("HMAC PRF key manager not found: %s", err) } if km.TypeURL() != testutil.HMACPRFTypeURL { t.Errorf("incorrect GetKeyType()") } } func TestHMACKeyMaterialType(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACPRFTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.HMACPRFTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } if got, want := keyManager.KeyMaterialType(), tinkpb.KeyData_SYMMETRIC; got != want { t.Errorf("KeyMaterialType() = %v, want %v", got, want) } } func TestHMACDeriveKey(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACPRFTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.HMACPRFTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } keyFormat, err := proto.Marshal(&hmacpb.HmacPrfKeyFormat{ Version: testutil.HMACPRFKeyVersion, KeySize: 16, Params: &hmacpb.HmacPrfParams{Hash: commonpb.HashType_SHA256}, }) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } rand := random.GetRandomBytes(16) buf := &bytes.Buffer{} buf.Write(rand) // Never returns a non-nil error. k, err := keyManager.DeriveKey(keyFormat, buf) if err != nil { t.Fatalf("keyManager.DeriveKey() err = %v, want nil", err) } key := k.(*hmacpb.HmacPrfKey) if got, want := len(key.GetKeyValue()), 16; got != want { t.Errorf("key length = %d, want %d", got, want) } if diff := cmp.Diff(key.GetKeyValue(), rand); diff != "" { t.Errorf("incorrect derived key: diff = %v", diff) } } func TestHMACDeriveKeyFailsWithInvalidKeyFormats(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACPRFTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.HMACPRFTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } validKeyFormat := &hmacpb.HmacPrfKeyFormat{ Version: testutil.HMACPRFKeyVersion, KeySize: 16, Params: &hmacpb.HmacPrfParams{Hash: commonpb.HashType_SHA256}, } serializedValidKeyFormat, err := proto.Marshal(validKeyFormat) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", validKeyFormat, err) } buf := bytes.NewBuffer(random.GetRandomBytes(validKeyFormat.KeySize)) if _, err := keyManager.DeriveKey(serializedValidKeyFormat, buf); err != nil { t.Fatalf("keyManager.DeriveKey() err = %v, want nil", err) } for _, test := range []struct { name string version uint32 keySize uint32 hash commonpb.HashType }{ { name: "invalid version", version: 10, keySize: validKeyFormat.KeySize, hash: validKeyFormat.Params.Hash, }, { name: "invalid key size", version: validKeyFormat.Version, keySize: 10, hash: validKeyFormat.Params.Hash, }, { name: "invalid hash", version: validKeyFormat.Version, keySize: validKeyFormat.KeySize, hash: commonpb.HashType_UNKNOWN_HASH, }, } { t.Run(test.name, func(t *testing.T) { keyFormat, err := proto.Marshal(&hmacpb.HmacPrfKeyFormat{ Version: test.version, KeySize: test.keySize, Params: &hmacpb.HmacPrfParams{Hash: test.hash}, }) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } buf := bytes.NewBuffer(random.GetRandomBytes(test.keySize)) if _, err := keyManager.DeriveKey(keyFormat, buf); err == nil { t.Errorf("keyManager.DeriveKey() err = nil, want non-nil") } }) } } func TestHMACDeriveKeyFailsWithMalformedKeyFormats(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACPRFTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.HMACPRFTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } // Proto messages start with a VarInt, which always ends with a byte with the // MSB unset, so 0x80 is invalid. invalidSerialization, err := hex.DecodeString("80") if err != nil { t.Errorf("hex.DecodeString() err = %v, want nil", err) } for _, test := range []struct { name string keyFormat []byte }{ { name: "nil", keyFormat: nil, }, { name: "empty", keyFormat: []byte{}, }, { name: "invalid serialization", keyFormat: invalidSerialization, }, } { t.Run(test.name, func(t *testing.T) { buf := bytes.NewBuffer(random.GetRandomBytes(16)) if _, err := keyManager.DeriveKey(test.keyFormat, buf); err == nil { t.Errorf("keyManager.DeriveKey() err = nil, want non-nil") } }) } } func TestHMACDeriveKeyFailsWithInsufficientRandomness(t *testing.T) { km, err := registry.GetKeyManager(testutil.HMACPRFTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.HMACPRFTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } keyFormat, err := proto.Marshal(&hmacpb.HmacPrfKeyFormat{ Version: testutil.HMACPRFKeyVersion, KeySize: 16, Params: &hmacpb.HmacPrfParams{Hash: commonpb.HashType_SHA256}, }) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", keyFormat, err) } { buf := bytes.NewBuffer(random.GetRandomBytes(16)) if _, err := keyManager.DeriveKey(keyFormat, buf); err != nil { t.Errorf("keyManager.DeriveKey() err = %v, want nil", err) } } { insufficientBuf := bytes.NewBuffer(random.GetRandomBytes(15)) if _, err := keyManager.DeriveKey(keyFormat, insufficientBuf); err == nil { t.Errorf("keyManager.DeriveKey() err = nil, want non-nil") } } } func genInvalidHMACPRFKeys() []proto.Message { badVersionKey := testutil.NewHMACPRFKey(commonpb.HashType_SHA256) badVersionKey.Version++ shortKey := testutil.NewHMACPRFKey(commonpb.HashType_SHA256) shortKey.KeyValue = []byte{1, 1} nilParams := testutil.NewHMACPRFKey(commonpb.HashType_SHA256) nilParams.Params = nil return []proto.Message{ // not a HMACPRFKey testutil.NewHMACParams(commonpb.HashType_SHA256, 32), // bad version badVersionKey, // key too short shortKey, // unknown hash type testutil.NewHMACPRFKey(commonpb.HashType_UNKNOWN_HASH), // params field is unset nilParams, } } func genInvalidHMACPRFKeyFormats() []proto.Message { shortKeyFormat := testutil.NewHMACPRFKeyFormat(commonpb.HashType_SHA256) shortKeyFormat.KeySize = 1 nilParams := testutil.NewHMACPRFKey(commonpb.HashType_SHA256) nilParams.Params = nil return []proto.Message{ // not a HMACPRFKeyFormat testutil.NewHMACParams(commonpb.HashType_SHA256, 32), // key too short shortKeyFormat, // unknown hash type testutil.NewHMACPRFKeyFormat(commonpb.HashType_UNKNOWN_HASH), // params field is unset nilParams, } } func genValidHMACPRFKeyFormats() []*hmacpb.HmacPrfKeyFormat { return []*hmacpb.HmacPrfKeyFormat{ testutil.NewHMACPRFKeyFormat(commonpb.HashType_SHA1), testutil.NewHMACPRFKeyFormat(commonpb.HashType_SHA256), testutil.NewHMACPRFKeyFormat(commonpb.HashType_SHA512), } } func genValidHMACPRFKeys() []*hmacpb.HmacPrfKey { return []*hmacpb.HmacPrfKey{ testutil.NewHMACPRFKey(commonpb.HashType_SHA1), testutil.NewHMACPRFKey(commonpb.HashType_SHA256), testutil.NewHMACPRFKey(commonpb.HashType_SHA512), } } // Checks whether the given HMACPRFKey matches the given key HMACPRFKeyFormat func validateHMACPRFKey(format *hmacpb.HmacPrfKeyFormat, key *hmacpb.HmacPrfKey) error { if format.KeySize != uint32(len(key.KeyValue)) || key.Params.Hash != format.Params.Hash { return fmt.Errorf("key format and generated key do not match") } p, err := subtle.NewHMACPRF(commonpb.HashType_name[int32(key.Params.Hash)], key.KeyValue) if err != nil { return fmt.Errorf("cannot create primitive from key: %s", err) } return validateHMACPRFPrimitive(p, key) } // validateHMACPRFPrimitive checks whether the given primitive can compute a PRF of length 16 func validateHMACPRFPrimitive(p any, key *hmacpb.HmacPrfKey) error { hmac := p.(prf.PRF) prfPrimitive, err := subtle.NewHMACPRF(commonpb.HashType_name[int32(key.Params.Hash)], key.KeyValue) if err != nil { return fmt.Errorf("Could not create HMAC PRF with key material %q: %s", hex.EncodeToString(key.KeyValue), err) } data := random.GetRandomBytes(20) res, err := hmac.ComputePRF(data, 16) if err != nil { return fmt.Errorf("prf computation failed: %s", err) } if len(res) != 16 { return fmt.Errorf("prf computation did not produce 16 byte output") } res2, err := prfPrimitive.ComputePRF(data, 16) if err != nil { return fmt.Errorf("prf computation failed: %s", err) } if len(res2) != 16 { return fmt.Errorf("prf computation did not produce 16 byte output") } if hex.EncodeToString(res) != hex.EncodeToString(res2) { return fmt.Errorf("prf computation did not produce the same output for the same key and input") } return nil } ================================================ FILE: go/prf/prf_benchmark_test.go ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package prf_test import ( "testing" "github.com/google/tink/go/keyset" "github.com/google/tink/go/prf" "github.com/google/tink/go/subtle/random" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // Benchmarks for PRF algorithms. func BenchmarkComputePRF(b *testing.B) { const ( outputLength = 16 ) testCases := []struct { name string template *tinkpb.KeyTemplate dataSize uint32 }{ { name: "HMAC_SHA256_PRF_16", template: prf.HMACSHA256PRFKeyTemplate(), dataSize: 16, }, { name: "HMAC_SHA256_PRF_16k", template: prf.HMACSHA256PRFKeyTemplate(), dataSize: 16 * 1024, }, { name: "HMAC_SHA512_PRF_16", template: prf.HMACSHA512PRFKeyTemplate(), dataSize: 16, }, { name: "HMAC_SHA512_PRF_16k", template: prf.HMACSHA512PRFKeyTemplate(), dataSize: 16 * 1024, }, { name: "HKDF_SHA256_16", template: prf.HKDFSHA256PRFKeyTemplate(), dataSize: 16, }, { name: "HKDF_SHA256_16k", template: prf.HKDFSHA256PRFKeyTemplate(), dataSize: 16 * 1024, }, { name: "AES_CMAC_PRF_16", template: prf.AESCMACPRFKeyTemplate(), dataSize: 16, }, { name: "AES_CMAC_PRF_16k", template: prf.AESCMACPRFKeyTemplate(), dataSize: 16 * 1024, }, } for _, tc := range testCases { b.Run(tc.name, func(b *testing.B) { b.ReportAllocs() handle, err := keyset.NewHandle(tc.template) if err != nil { b.Fatal(err) } primitive, err := prf.NewPRFSet(handle) if err != nil { b.Fatal(err) } data := random.GetRandomBytes(tc.dataSize) b.ResetTimer() for i := 0; i < b.N; i++ { _, err := primitive.ComputePrimaryPRF(data, outputLength) if err != nil { b.Fatal(err) } } }) } } ================================================ FILE: go/prf/prf_key_templates.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package prf import ( "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/internal/tinkerror" cmacpb "github.com/google/tink/go/proto/aes_cmac_prf_go_proto" commonpb "github.com/google/tink/go/proto/common_go_proto" hkdfpb "github.com/google/tink/go/proto/hkdf_prf_go_proto" hmacpb "github.com/google/tink/go/proto/hmac_prf_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // This file contains pre-generated KeyTemplate for PRF. // HMACSHA256PRFKeyTemplate is a KeyTemplate that generates an HMAC key with the following parameters: // - Key size: 32 bytes // - Hash function: SHA256 func HMACSHA256PRFKeyTemplate() *tinkpb.KeyTemplate { return createHMACPRFKeyTemplate(32, commonpb.HashType_SHA256) } // HMACSHA512PRFKeyTemplate is a KeyTemplate that generates an HMAC key with the following parameters: // - Key size: 64 bytes // - Hash function: SHA512 func HMACSHA512PRFKeyTemplate() *tinkpb.KeyTemplate { return createHMACPRFKeyTemplate(64, commonpb.HashType_SHA512) } // HKDFSHA256PRFKeyTemplate is a KeyTemplate that generates an HKDF key with the following parameters: // - Key size: 32 bytes // - Salt: empty // - Hash function: SHA256 func HKDFSHA256PRFKeyTemplate() *tinkpb.KeyTemplate { return createHKDFPRFKeyTemplate(32, commonpb.HashType_SHA256, make([]byte, 0)) } // AESCMACPRFKeyTemplate is a KeyTemplate that generates a AES-CMAC key with the following parameters: // - Key size: 32 bytes func AESCMACPRFKeyTemplate() *tinkpb.KeyTemplate { return createAESCMACPRFKeyTemplate(32) } // createHMACPRFKeyTemplate creates a new KeyTemplate for HMAC using the given parameters. func createHMACPRFKeyTemplate(keySize uint32, hashType commonpb.HashType) *tinkpb.KeyTemplate { params := hmacpb.HmacPrfParams{ Hash: hashType, } format := hmacpb.HmacPrfKeyFormat{ Params: &params, KeySize: keySize, } serializedFormat, err := proto.Marshal(&format) if err != nil { tinkerror.Fail(fmt.Sprintf("failed to marshal key format: %s", err)) } return &tinkpb.KeyTemplate{ TypeUrl: hmacprfTypeURL, OutputPrefixType: tinkpb.OutputPrefixType_RAW, Value: serializedFormat, } } // createHKDFPRFKeyTemplate creates a new KeyTemplate for HKDF using the given parameters. func createHKDFPRFKeyTemplate(keySize uint32, hashType commonpb.HashType, salt []byte) *tinkpb.KeyTemplate { params := hkdfpb.HkdfPrfParams{ Hash: hashType, Salt: salt, } format := hkdfpb.HkdfPrfKeyFormat{ Params: &params, KeySize: keySize, } serializedFormat, err := proto.Marshal(&format) if err != nil { tinkerror.Fail(fmt.Sprintf("failed to marshal key format: %s", err)) } return &tinkpb.KeyTemplate{ TypeUrl: hkdfprfTypeURL, OutputPrefixType: tinkpb.OutputPrefixType_RAW, Value: serializedFormat, } } // createAESCMACPRFKeyTemplate creates a new KeyTemplate for AES-CMAC using the given parameters. func createAESCMACPRFKeyTemplate(keySize uint32) *tinkpb.KeyTemplate { format := cmacpb.AesCmacPrfKeyFormat{ KeySize: keySize, } serializedFormat, err := proto.Marshal(&format) if err != nil { tinkerror.Fail(fmt.Sprintf("failed to marshal key format: %s", err)) } return &tinkpb.KeyTemplate{ TypeUrl: aescmacprfTypeURL, OutputPrefixType: tinkpb.OutputPrefixType_RAW, Value: serializedFormat, } } ================================================ FILE: go/prf/prf_key_templates_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package prf_test import ( "bytes" "testing" "github.com/google/tink/go/keyset" "github.com/google/tink/go/prf" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestKeyTemplates(t *testing.T) { var testCases = []struct { name string template *tinkpb.KeyTemplate }{ {name: "HMAC_SHA256_PRF", template: prf.HMACSHA256PRFKeyTemplate()}, {name: "HMAC_SHA512_PRF", template: prf.HMACSHA512PRFKeyTemplate()}, {name: "HKDF_SHA256", template: prf.HKDFSHA256PRFKeyTemplate()}, {name: "AES_CMAC_PRF", template: prf.AESCMACPRFKeyTemplate()}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { handle, err := keyset.NewHandle(tc.template) if err != nil { t.Errorf("keyset.NewHandle(tc.template) failed: %s", err) } prfset, err := prf.NewPRFSet(handle) if err != nil { t.Errorf("prf.NewPRFSet(handle) failed: %s", err) } var testInputs = []struct { message1 []byte message2 []byte }{ { message1: []byte("this data needs to be authenticated"), message2: []byte("this data needs to be authenticated"), }, { message1: []byte(""), message2: []byte(""), }, { message1: []byte(""), message2: nil, }, { message1: nil, message2: []byte(""), }, { message1: nil, message2: nil, }, } for _, ti := range testInputs { output, err := prfset.ComputePrimaryPRF(ti.message1, 16) if err != nil { t.Errorf("prfset.ComputePrimaryPRF(ti.message1, 16) failed: %s", err) } if len(output) != 16 { t.Errorf("len(output) = %d, want 16", len(output)) } output2, err := prfset.ComputePrimaryPRF(ti.message2, 16) if err != nil { t.Errorf("prfset.ComputePrimaryPRF(ti.message2, 16) failed: %s", err) } if !bytes.Equal(output2, output) { t.Errorf("equivalent inputs did not produce equivalent outputs, got: %q, want: %q", output2, output) } } }) } } ================================================ FILE: go/prf/prf_set.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package prf contains utilities to calculate pseudo random function families. package prf import ( "fmt" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/monitoring" ) // The PRF interface is an abstraction for an element of a pseudo-random // function family, selected by a key. // // It has the following properties: // - It is deterministic. ComputePRF(input, length) will always return the // same output if the same key is used. ComputePRF(input, length1) will be a // prefix of ComputePRF(input, length2) if length1 < length2 and the same // key is used. // - It is indistinguishable from a random function. Given the evaluation of // n different inputs, an attacker cannot distinguish between the PRF and // random bytes on an input different from the n that are known. // // Use cases for PRF are deterministic redaction of PII, keyed hash functions, // creating sub IDs that do not allow joining with the original dataset without // knowing the key. // // While PRFs can be used in order to prove authenticity of a message, using // the MAC interface is recommended for that use case, as it has support for // verification, avoiding the security problems that often happen during // verification, and having automatic support for key rotation. It also allows // for non-deterministic MAC algorithms. type PRF interface { // Computes the PRF selected by the underlying key on input and // returns the first outputLength bytes. // // When choosing this parameter keep the birthday paradox in mind. // If you have 2^n different inputs that your system has to handle // set the output length (in bytes) to at least // ceil(n/4 + 4) // // This corresponds to 2*n + 32 bits, meaning a collision will occur // with a probability less than 1:2^32. When in doubt, request a // security review. // // Returns a non-nil error if the algorithm fails or if the output of // the underlying algorithm is less than outputLength. ComputePRF(input []byte, outputLength uint32) ([]byte, error) } type monitoredPRF struct { prf PRF keyID uint32 logger monitoring.Logger } var _ PRF = (*monitoredPRF)(nil) func (w *monitoredPRF) ComputePRF(input []byte, outputLength uint32) ([]byte, error) { p, err := w.prf.ComputePRF(input, outputLength) if err != nil { w.logger.LogFailure() return nil, err } w.logger.Log(w.keyID, len(input)) return p, nil } // Set is a set of PRFs. // // A Tink Keyset can be converted into a set of PRFs using this primitive. // Every key in the keyset corresponds to a PRF in the prf.Set. Every PRF in // the set is given an ID, which is the same ID as the key id in the Keyset. type Set struct { // PrimaryID is the key ID marked as primary in the corresponding Keyset. PrimaryID uint32 // PRFs maps key IDs to their corresponding PRF. PRFs map[uint32]PRF } // ComputePrimaryPRF is equivalent to set.PRFs[set.PrimaryID].ComputePRF(). func (s Set) ComputePrimaryPRF(input []byte, outputLength uint32) ([]byte, error) { prf, ok := s.PRFs[s.PrimaryID] if !ok { return nil, fmt.Errorf("Could not find primary ID %d in prf.Set", s.PrimaryID) } return prf.ComputePRF(input, outputLength) } func init() { if err := registry.RegisterKeyManager(new(hmacprfKeyManager)); err != nil { panic(fmt.Sprintf("prf.init() failed: %v", err)) } if err := internalregistry.AllowKeyDerivation(hmacprfTypeURL); err != nil { panic(fmt.Sprintf("prf.init() failed: %v", err)) } if err := registry.RegisterKeyManager(new(hkdfprfKeyManager)); err != nil { panic(fmt.Sprintf("prf.init() failed: %v", err)) } if err := internalregistry.AllowKeyDerivation(hkdfprfTypeURL); err != nil { panic(fmt.Sprintf("prf.init() failed: %v", err)) } if err := registry.RegisterKeyManager(new(aescmacprfKeyManager)); err != nil { panic(fmt.Sprintf("prf.init() failed: %v", err)) } } ================================================ FILE: go/prf/prf_set_factory.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package prf import ( "fmt" "github.com/google/tink/go/core/primitiveset" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/internal/monitoringutil" "github.com/google/tink/go/keyset" "github.com/google/tink/go/monitoring" ) // NewPRFSet creates a prf.Set primitive from the given keyset handle. func NewPRFSet(handle *keyset.Handle) (*Set, error) { ps, err := handle.Primitives() if err != nil { return nil, fmt.Errorf("prf_set_factory: cannot obtain primitive set: %s", err) } return wrapPRFset(ps) } func wrapPRFset(ps *primitiveset.PrimitiveSet) (*Set, error) { set := &Set{} if _, ok := (ps.Primary.Primitive).(PRF); !ok { return nil, fmt.Errorf("prf_set_factory: not a PRF primitive") } set.PrimaryID = ps.Primary.KeyID set.PRFs = make(map[uint32]PRF) logger, err := createLogger(ps) if err != nil { return nil, err } entries, err := ps.RawEntries() if err != nil { return nil, fmt.Errorf("Could not get raw entries: %v", err) } if len(entries) == 0 { return nil, fmt.Errorf("Did not find any raw entries") } if len(ps.Entries) != 1 { return nil, fmt.Errorf("Only raw entries allowed for prf.Set") } for _, entry := range entries { prf, ok := (entry.Primitive).(PRF) if !ok { return nil, fmt.Errorf("prf_set_factory: not a PRF primitive") } set.PRFs[entry.KeyID] = &monitoredPRF{ prf: prf, keyID: entry.KeyID, logger: logger, } } return set, nil } func createLogger(ps *primitiveset.PrimitiveSet) (monitoring.Logger, error) { if len(ps.Annotations) == 0 { return &monitoringutil.DoNothingLogger{}, nil } keysetInfo, err := monitoringutil.KeysetInfoFromPrimitiveSet(ps) if err != nil { return nil, err } return internalregistry.GetMonitoringClient().NewLogger(&monitoring.Context{ KeysetInfo: keysetInfo, Primitive: "prf", APIFunction: "compute", }) } ================================================ FILE: go/prf/prf_set_factory_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package prf_test import ( "bytes" "encoding/hex" "fmt" "testing" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/tink/go/insecurecleartextkeyset" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/keyset" "github.com/google/tink/go/mac" "github.com/google/tink/go/monitoring" "github.com/google/tink/go/prf" "github.com/google/tink/go/testing/fakemonitoring" "github.com/google/tink/go/testutil" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( maxAutocorrelation = 100 ) func addKeyAndReturnID(m *keyset.Manager, template *tinkpb.KeyTemplate) (uint32, error) { keyID, err := m.Add(template) if err != nil { return 0, fmt.Errorf("Could not add key from the given template: %v", err) } err = m.SetPrimary(keyID) if err != nil { return 0, fmt.Errorf("Could set key as primary: %v", err) } return keyID, nil } func TestFactoryBasic(t *testing.T) { manager := keyset.NewManager() aescmacID, err := addKeyAndReturnID(manager, prf.AESCMACPRFKeyTemplate()) if err != nil { t.Errorf("Could not add AES CMAC PRF key: %v", err) } hmacsha256ID, err := addKeyAndReturnID(manager, prf.HMACSHA256PRFKeyTemplate()) if err != nil { t.Errorf("Could not add HMAC SHA256 PRF key: %v", err) } hkdfsha256ID, err := addKeyAndReturnID(manager, prf.HKDFSHA256PRFKeyTemplate()) if err != nil { t.Errorf("Could not add HKDF SHA256 PRF key: %v", err) } hmacsha512ID, err := addKeyAndReturnID(manager, prf.HMACSHA512PRFKeyTemplate()) if err != nil { t.Errorf("Could not add HMAC SHA512 PRF key: %v", err) } handle, err := manager.Handle() if err != nil { t.Errorf("Could not obtain handle: %v", err) } prfSet, err := prf.NewPRFSet(handle) if err != nil { t.Errorf("Could not create prf.Set with standard key templates: %v", err) } primaryID := prfSet.PrimaryID if primaryID != hmacsha512ID { t.Errorf("Primary ID %d should be the ID %d, which was added last", primaryID, hmacsha512ID) } for _, length := range []uint32{1, 10, 16, 17, 32, 33, 64, 65, 100, 8160, 8161} { results := [][]byte{} for id, prf := range prfSet.PRFs { ok := true switch { case length > 16 && id == aescmacID: ok = false case length > 32 && id == hmacsha256ID: ok = false case length > 64 && id == hmacsha512ID: ok = false case length > 8160 && id == hkdfsha256ID: ok = false } result1, err := prf.ComputePRF([]byte("The input"), length) switch { case err != nil && !ok: continue case err != nil: t.Errorf("Expected to be able to compute %d bytes of PRF output: %v", length, err) continue case !ok: t.Errorf("Expected to be unable to compute %d bytes PRF output", length) continue } result2, err := prf.ComputePRF([]byte("The different input"), length) switch { case err != nil && !ok: continue case err != nil: t.Errorf("Expected to be able to compute %d bytes of PRF output: %v", length, err) continue case !ok: t.Errorf("Expected to be unable to compute %d bytes PRF output", length) continue } result3, err := prf.ComputePRF([]byte("The input"), length) switch { case err != nil && !ok: continue case err != nil: t.Errorf("Expected to be able to compute %d bytes of PRF output: %v", length, err) continue case !ok: t.Errorf("Expected to be unable to compute %d bytes PRF output", length) continue } if id == primaryID { primaryResult, err := prfSet.ComputePrimaryPRF([]byte("The input"), length) switch { case err != nil && !ok: continue case err != nil: t.Errorf("Expected to be able to compute %d bytes of PRF output: %v", length, err) continue case !ok: t.Errorf("Expected to be unable to compute %d bytes PRF output", length) continue } if hex.EncodeToString(result1) != hex.EncodeToString(primaryResult) { t.Errorf("Expected manual call of ComputePRF of primary PRF and ComputePrimaryPRF with the same input to produce the same output, but got %q and %q", result1, primaryResult) } } if hex.EncodeToString(result1) != hex.EncodeToString(result3) { t.Errorf("Expected different calls with the same input to produce the same output, but got %q and %q", result1, result3) } results = append(results, result1) results = append(results, result2) } runZTests(results, t) } } func TestNonRawKeys(t *testing.T) { template := prf.AESCMACPRFKeyTemplate() template.OutputPrefixType = tinkpb.OutputPrefixType_TINK h, err := keyset.NewHandle(template) if err != nil { t.Errorf("Couldn't create keyset: %v", err) } _, err = prf.NewPRFSet(h) if err == nil { t.Errorf("Expected non RAW prefix to fail to create prf.Set") } m := keyset.NewManagerFromHandle(h) _, err = addKeyAndReturnID(m, prf.HMACSHA256PRFKeyTemplate()) if err != nil { t.Errorf("Expected to be able to add keys to the keyset: %v", err) } h, err = m.Handle() if err != nil { t.Errorf("Expected to be able to create keyset handle: %v", err) } _, err = prf.NewPRFSet(h) if err == nil { t.Errorf("Expected mixed prefix keyset to fail to create prf.Set") } } func TestNonPRFPrimitives(t *testing.T) { template := mac.AESCMACTag128KeyTemplate() template.OutputPrefixType = tinkpb.OutputPrefixType_RAW h, err := keyset.NewHandle(template) if err != nil { t.Errorf("Couldn't create keyset: %v", err) } _, err = prf.NewPRFSet(h) if err == nil { t.Errorf("Expected non PRF primitive to fail to create prf.Set") } m := keyset.NewManagerFromHandle(h) _, err = addKeyAndReturnID(m, prf.HMACSHA256PRFKeyTemplate()) if err != nil { t.Errorf("Expected to be able to add keys to the keyset: %v", err) } h, err = m.Handle() if err != nil { t.Errorf("Expected to be able to create keyset handle: %v", err) } _, err = prf.NewPRFSet(h) if err == nil { t.Errorf("Expected mixed primitive keyset to fail to create prf.Set") } } func runZTests(results [][]byte, t *testing.T) { for i, result1 := range results { if err := testutil.ZTestUniformString(result1); err != nil { t.Errorf("Expected PRF output to pass uniformity z test: %v", err) } if len(result1) <= maxAutocorrelation { if err := testutil.ZTestAutocorrelationUniformString(result1); err != nil { t.Errorf("Expected PRF output to pass autocorrelation test: %v", err) } } for j := i + 1; j < len(results); j++ { result2 := results[j] if err := testutil.ZTestCrosscorrelationUniformStrings(result1, result2); err != nil { t.Errorf("Expected different PRF outputs to be uncorrelated: %v", err) } } } } func TestPrimitiveFactoryComputePRFWithoutAnnotationsDoesNothing(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } kh, err := keyset.NewHandle(prf.HMACSHA256PRFKeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } prfSet, err := prf.NewPRFSet(kh) if err != nil { t.Fatalf("prf.NewPRFSet() err = %v, want nil", err) } if _, err := prfSet.ComputePrimaryPRF([]byte("input_data"), 32); err != nil { t.Fatalf("prfSet.ComputePrimaryPRF() err = %v, want nil", err) } failures := len(client.Failures()) if failures != 0 { t.Errorf("len(client.Failures()) = %d, want 0", failures) } got := client.Events() if got != nil { t.Errorf("client.Events() = %v, want nil", got) } } func TestPrimitiveFactoryMonitoringWithAnnotationsComputePRFFailureIsLogged(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } kh, err := keyset.NewHandle(prf.HMACSHA256PRFKeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } prfSet, err := prf.NewPRFSet(mh) if err != nil { t.Fatalf("prf.NewPRFSet() err = %v, want nil", err) } data := []byte("input_data") if _, err := prfSet.ComputePrimaryPRF(data, 64); err == nil { t.Fatalf("prfSet.ComputePrimaryPRF() err = nil, want non-nil errors") } got := client.Failures() want := []*fakemonitoring.LogFailure{ { Context: monitoring.NewContext( "prf", "compute", &monitoring.KeysetInfo{ Annotations: annotations, Entries: []*monitoring.Entry{ { KeyID: kh.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.HmacPrfKey", KeyPrefix: "RAW", }, }, PrimaryKeyID: kh.KeysetInfo().GetPrimaryKeyId(), }, ), }, } if diff := cmp.Diff(want, got); diff != "" { t.Errorf("%v", diff) } } func TestPrimitiveFactoryIndividualPrfWithAnnotatonsLogsCompute(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } kh, err := keyset.NewHandle(prf.HMACSHA256PRFKeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } manager := keyset.NewManagerFromHandle(kh) hmac512KeyID, err := manager.Add(prf.HMACSHA512PRFKeyTemplate()) if err != nil { t.Fatalf("manager.Add() err = %v, want nil", err) } aesKeyID, err := manager.Add(prf.AESCMACPRFKeyTemplate()) if err != nil { t.Fatalf("manager.Add() err = %v, want nil", err) } kh, err = manager.Handle() if err != nil { t.Fatalf("manager.Handle() err = %v, want nil", err) } buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } prfSet, err := prf.NewPRFSet(mh) if err != nil { t.Fatalf("prf.NewPRFSet() err = %v, want nil", err) } for _, p := range prfSet.PRFs { if _, err := p.ComputePRF([]byte("input_data"), 16); err != nil { t.Fatalf("p.ComputePRF() err = %v, want nil", err) } } got := client.Events() wantKeysetInfo := &monitoring.KeysetInfo{ PrimaryKeyID: kh.KeysetInfo().GetPrimaryKeyId(), Entries: []*monitoring.Entry{ { KeyID: kh.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.HmacPrfKey", KeyPrefix: "RAW", }, { KeyID: hmac512KeyID, Status: monitoring.Enabled, KeyType: "tink.HmacPrfKey", KeyPrefix: "RAW", }, { KeyID: aesKeyID, Status: monitoring.Enabled, KeyType: "tink.AesCmacPrfKey", KeyPrefix: "RAW", }, }, Annotations: annotations, } want := []*fakemonitoring.LogEvent{ { Context: monitoring.NewContext("prf", "compute", wantKeysetInfo), KeyID: kh.KeysetInfo().GetKeyInfo()[0].GetKeyId(), NumBytes: len("input_data"), }, { Context: monitoring.NewContext("prf", "compute", wantKeysetInfo), KeyID: kh.KeysetInfo().GetKeyInfo()[1].GetKeyId(), NumBytes: len("input_data"), }, { Context: monitoring.NewContext("prf", "compute", wantKeysetInfo), KeyID: kh.KeysetInfo().GetKeyInfo()[2].GetKeyId(), NumBytes: len("input_data"), }, } eventCmp := func(a, b *fakemonitoring.LogEvent) bool { return a.KeyID < b.KeyID } if !cmp.Equal(got, want, cmpopts.SortSlices(eventCmp)) { t.Errorf("got = %v, want = %v, with diff: %v", got, want, cmp.Diff(got, want)) } } func TestPrimitiveFactoryWithMonitoringAnnotationsLogsComputePRF(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } kh, err := keyset.NewHandle(prf.HMACSHA256PRFKeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} mh, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } prfSet, err := prf.NewPRFSet(mh) if err != nil { t.Fatalf("prf.NewPRFSet() err = %v, want nil", err) } data := []byte("some_data") if _, err := prfSet.ComputePrimaryPRF(data, 20); err != nil { t.Fatalf("prfSet.ComputePrimaryPRF() err = %v, want nil", err) } got := client.Events() wantKeysetInfo := &monitoring.KeysetInfo{ PrimaryKeyID: kh.KeysetInfo().GetPrimaryKeyId(), Entries: []*monitoring.Entry{ { KeyID: kh.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.HmacPrfKey", KeyPrefix: "RAW", }, }, Annotations: annotations, } want := []*fakemonitoring.LogEvent{ { Context: monitoring.NewContext("prf", "compute", wantKeysetInfo), KeyID: kh.KeysetInfo().GetPrimaryKeyId(), NumBytes: len(data), }, } if !cmp.Equal(got, want) { t.Errorf("got = %v, want = %v, with diff: %v", got, want, cmp.Diff(got, want)) } } ================================================ FILE: go/prf/prf_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package prf_test import ( "encoding/base64" "fmt" "log" "github.com/google/tink/go/keyset" "github.com/google/tink/go/prf" ) func Example() { kh, err := keyset.NewHandle(prf.HMACSHA256PRFKeyTemplate()) if err != nil { log.Fatal(err) } // TODO: save the keyset to a safe location. DO NOT hardcode it in source code. // Consider encrypting it with a remote key in Cloud KMS, AWS KMS or HashiCorp Vault. // See https://github.com/google/tink/blob/master/docs/GOLANG-HOWTO.md#storing-and-loading-existing-keysets. ps, err := prf.NewPRFSet(kh) if err != nil { log.Fatal(err) } msg := []byte("This is an ID needs to be redacted") output, err := ps.ComputePrimaryPRF(msg, 16) fmt.Printf("Message: %s\n", msg) fmt.Printf("Redacted: %s\n", base64.StdEncoding.EncodeToString(output)) } ================================================ FILE: go/prf/subtle/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep go_library( name = "subtle", srcs = [ "aes_cmac.go", "hkdf.go", "hmac.go", "subtle.go", ], importpath = "github.com/google/tink/go/prf/subtle", visibility = ["//visibility:public"], deps = [ "//subtle", "@org_golang_x_crypto//hkdf", ], ) go_test( name = "subtle_test", srcs = [ "aes_cmac_test.go", "hkdf_test.go", "hmac_test.go", "subtle_test.go", ], data = [ "//testdata/testvectors:aes_cmac", "//testdata/testvectors:hmac", "//testdata/testvectors:kdf", ], deps = [ ":subtle", "//testutil", ], ) alias( name = "go_default_library", actual = ":subtle", visibility = ["//:__subpackages__"], ) ================================================ FILE: go/prf/subtle/aes_cmac.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "crypto/aes" "crypto/cipher" "crypto/subtle" "fmt" // Placeholder for internal crypto/cipher allowlist, please ignore. // Placeholder for internal crypto/subtle allowlist, please ignore. ) const ( mul = 0x87 pad = byte(0x80) recommendedKeySize = uint32(32) ) // AESCMACPRF is a type that can be used to compute several CMACs with the same key material. type AESCMACPRF struct { bc cipher.Block subkey1, subkey2 []byte } // NewAESCMACPRF creates a new AESCMACPRF object and initializes it with the correct key material. func NewAESCMACPRF(key []byte) (*AESCMACPRF, error) { aesCmac := &AESCMACPRF{} var err error aesCmac.bc, err = aes.NewCipher(key) if err != nil { return nil, fmt.Errorf("Could not obtain cipher: %v", err) } bs := aesCmac.bc.BlockSize() zeroBlock := make([]byte, bs) // Generate Subkeys aesCmac.subkey1 = make([]byte, bs) aesCmac.subkey2 = make([]byte, bs) aesCmac.bc.Encrypt(aesCmac.subkey1, zeroBlock) mulByX(aesCmac.subkey1) copy(aesCmac.subkey2, aesCmac.subkey1) mulByX(aesCmac.subkey2) return aesCmac, nil } // ValidateAESCMACPRFParams checks that the key is the recommended size for AES-CMAC. func ValidateAESCMACPRFParams(keySize uint32) error { if keySize != recommendedKeySize { return fmt.Errorf("Recommended key size for AES-CMAC is %d, but %d given", recommendedKeySize, keySize) } return nil } // ComputePRF computes the AES-CMAC for the given key and data, returning outputLength bytes. // The timing of this function will only depend on len(data), and not leak any additional information about the key or the data. func (a AESCMACPRF) ComputePRF(data []byte, outputLength uint32) ([]byte, error) { // Setup bs := a.bc.BlockSize() if outputLength > uint32(bs) { return nil, fmt.Errorf("outputLength must be between 0 and %d", bs) } // Pad flag := false n := len(data)/bs + 1 // if only depends on len(data). if len(data) > 0 && len(data)%bs == 0 { n-- flag = true } mLast := make([]byte, bs) mLastStart := (n - 1) * bs for i := 0; i < bs; i++ { // if depends on mLastStart and len(data), which depend on len(data) if i+mLastStart < len(data) { mLast[i] = data[i+mLastStart] } else if i+mLastStart == len(data) { mLast[i] = pad } // if only depends on flag, which depends on len(data) if flag { mLast[i] ^= a.subkey1[i] } else { mLast[i] ^= a.subkey2[i] } } input := make([]byte, bs) output := make([]byte, bs) for i := 0; i < n; i++ { // if depends on n, which depends on len(data) if i+1 == n { copy(input, mLast) } else { copy(input, data[i*bs:(i+1)*bs]) } for j := 0; j < bs; j++ { input[j] ^= output[j] } a.bc.Encrypt(output, input) } return output[:outputLength], nil } func mulByX(block []byte) { bs := len(block) v := int(block[0] >> 7) for i := 0; i < bs-1; i++ { block[i] = block[i]<<1 | block[i+1]>>7 } block[bs-1] = (block[bs-1] << 1) ^ byte(subtle.ConstantTimeSelect(v, mul, 0x00)) } ================================================ FILE: go/prf/subtle/aes_cmac_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "bytes" "encoding/hex" "fmt" "testing" "github.com/google/tink/go/prf/subtle" "github.com/google/tink/go/testutil" ) func TestVectorsRFC4493(t *testing.T) { // Test vectors from RFC 4493. key, err := hex.DecodeString("2b7e151628aed2a6abf7158809cf4f3c") if err != nil { t.Errorf("Could not decode key: %v", err) } data, err := hex.DecodeString("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710") if err != nil { t.Errorf("Could not decode data: %v", err) } expected := map[int]string{ 0: "bb1d6929e95937287fa37d129b756746", 16: "070a16b46b4d4144f79bdd9dd04a287c", 40: "dfa66747de9ae63030ca32611497c827", 64: "51f0bebf7e3b9d92fc49741779363cfe", } a, err := subtle.NewAESCMACPRF(key) if err != nil { t.Errorf("Could not create cmac.AES object: %v", err) } for l, e := range expected { output, err := a.ComputePRF(data[:l], 16) if err != nil { t.Errorf("Error computing AES-CMAC: %v", err) } if hex.EncodeToString(output) != e { t.Errorf("Computation and test vector differ. Computation: %q, Test Vector %q", hex.EncodeToString(output), e) } } } func TestAESCMACPRFWycheproofCases(t *testing.T) { testutil.SkipTestIfTestSrcDirIsNotSet(t) suite := new(macSuite) if err := testutil.PopulateSuite(suite, "aes_cmac_test.json"); err != nil { t.Fatalf("Failed populating suite: %s", err) } for _, group := range suite.TestGroups { groupName := fmt.Sprintf("%s-%s(%d)", suite.Algorithm, group.Type, group.KeySize) if group.TagSize%8 != 0 { t.Errorf("For %s, requested tag size is not a multiple of 8, but %d", groupName, group.TagSize) continue } for _, test := range group.Tests { caseName := fmt.Sprintf("%s:Case-%d", groupName, test.CaseID) t.Run(caseName, func(t *testing.T) { if uint32(len(test.Key))*8 != group.KeySize { t.Fatalf("Invalid key length: %s", test.Comment) } aes, err := subtle.NewAESCMACPRF(test.Key) switch test.Result { case "valid": if err != nil { t.Fatalf("NewAESCMACPRF failed (case: %s): %v", test.Comment, err) } res, err := aes.ComputePRF(test.Message, group.TagSize/8) if err != nil { t.Fatalf("ComputePRF() failed: %v", err) } if !bytes.Equal(res, test.Tag) { t.Errorf("ComputePRF() result and expected result do not match:\nComputed: %q\nExpected: %q", hex.EncodeToString(res), test.Tag) } case "invalid": if err != nil { return } res, err := aes.ComputePRF(test.Message, group.TagSize/8) if err != nil { return } if bytes.Equal(res, test.Tag) { t.Errorf("ComputePRF() result and invalid expected result match:\nComputed: %q\nExpected: %q", hex.EncodeToString(res), test.Tag) } default: t.Fatalf("Unsupported test result: %q", test.Result) } }) } } } func TestValidateAESCMACPRFParams(t *testing.T) { if err := subtle.ValidateAESCMACPRFParams(32); err != nil { t.Errorf("Unexpected error validating AES CMAC PRF Params: %v", err) } if err := subtle.ValidateAESCMACPRFParams(2); err == nil { t.Errorf("Unexpected validation of too short key for AES CMAC PRF Params") } } func TestKeyLength(t *testing.T) { if _, err := subtle.NewAESCMACPRF([]byte{0x01, 0x02}); err == nil { t.Errorf("Expected NewAESCMACPRF to fail on short key") } if _, err := subtle.NewAESCMACPRF([]byte{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}); err != nil { t.Errorf("Expected NewAESCMACPRF to work on 16 byte key") } if _, err := subtle.NewAESCMACPRF([]byte{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}); err != nil { t.Errorf("Expected NewAESCMACPRF to work on 32 byte key") } } func TestAESCMACPRFOutputLength(t *testing.T) { prf, err := subtle.NewAESCMACPRF([]byte{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}) if err != nil { t.Errorf("Expected NewAESCMACPRF to work on 32 byte key") } for i := 0; i <= 16; i++ { output, err := prf.ComputePRF([]byte{0x01, 0x02}, uint32(i)) if err != nil { t.Errorf("Expected to be able to compute AES CMAC PRF with %d output length", i) } if len(output) != i { t.Errorf("Expected AES CMAC PRF to compute %d bytes, got %d", i, len(output)) } } for i := 17; i < 32; i++ { _, err := prf.ComputePRF([]byte{0x01, 0x02}, uint32(i)) if err == nil { t.Errorf("Expected to not be able to compute AES CMAC PRF with %d output length", i) } } } ================================================ FILE: go/prf/subtle/hkdf.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "fmt" "hash" "io" "golang.org/x/crypto/hkdf" "github.com/google/tink/go/subtle" ) const ( // We use a somewhat larger minimum key size than usual, because PRFs might be // used by many users, in which case the security can degrade by a factor // depending on the number of users. (Discussed for example in // https://eprint.iacr.org/2012/159) minHKDFKeySizeInBytes = uint32(32) ) // HKDFPRF is a type that can be used to compute several HKDFs with the same key material. type HKDFPRF struct { h func() hash.Hash key []byte salt []byte } // NewHKDFPRF creates a new HKDFPRF object and initializes it with the correct key material. func NewHKDFPRF(hashAlg string, key []byte, salt []byte) (*HKDFPRF, error) { h := &HKDFPRF{} hashFunc := subtle.GetHashFunc(hashAlg) if hashFunc == nil { return nil, fmt.Errorf("hkdf: invalid hash algorithm") } h.h = hashFunc h.key = key h.salt = salt return h, nil } // ValidateHKDFPRFParams validates parameters of HKDF constructor. func ValidateHKDFPRFParams(hash string, keySize uint32, salt []byte) error { // validate key size if keySize < minHKDFKeySizeInBytes { return fmt.Errorf("key too short") } if subtle.GetHashFunc(hash) == nil { return fmt.Errorf("invalid hash function") } if hash != "SHA256" && hash != "SHA512" { return fmt.Errorf("Only SHA-256 and SHA-512 currently allowed for HKDF") } return nil } // ComputePRF computes the HKDF for the given key and data, returning outputLength bytes. func (h HKDFPRF) ComputePRF(data []byte, outputLength uint32) ([]byte, error) { kdf := hkdf.New(h.h, h.key, h.salt, data) output := make([]byte, outputLength) _, err := io.ReadAtLeast(kdf, output, int(outputLength)) if err != nil { return nil, fmt.Errorf("Error computing HKDF: %v", err) } return output[:outputLength], nil } ================================================ FILE: go/prf/subtle/hkdf_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "bytes" "encoding/hex" "fmt" "strings" "testing" "github.com/google/tink/go/prf/subtle" "github.com/google/tink/go/testutil" ) type rfc5869test struct { hash string key string salt string info string outputLength uint32 okm string } func TestVectorsRFC5869(t *testing.T) { // Test vectors from RFC 5869. testvectors := []*rfc5869test{ { hash: "SHA256", key: "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", salt: "000102030405060708090a0b0c", info: "f0f1f2f3f4f5f6f7f8f9", outputLength: 42, okm: "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865", }, { hash: "SHA256", key: "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f", salt: "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf", info: "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", outputLength: 82, okm: "b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87", }, { hash: "SHA256", key: "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", salt: "", info: "", outputLength: 42, okm: "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8", }, { hash: "SHA1", key: "0b0b0b0b0b0b0b0b0b0b0b", salt: "000102030405060708090a0b0c", info: "f0f1f2f3f4f5f6f7f8f9", outputLength: 42, okm: "085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422478d305f3f896", }, { hash: "SHA1", key: "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f", salt: "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf", info: "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", outputLength: 82, okm: "0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e927336d0441f4c4300e2cff0d0900b52d3b4", }, { hash: "SHA1", key: "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", salt: "", info: "", outputLength: 42, okm: "0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0ea00033de03984d34918", }, { hash: "SHA1", key: "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", salt: "", info: "", outputLength: 42, okm: "2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48", }, } for _, v := range testvectors { key, err := hex.DecodeString(v.key) if err != nil { t.Errorf("Could not decode key: %v", err) } salt, err := hex.DecodeString(v.salt) if err != nil { t.Errorf("Could not decode salt: %v", err) } info, err := hex.DecodeString(v.info) if err != nil { t.Errorf("Could not decode info: %v", err) } p, err := subtle.NewHKDFPRF(v.hash, key, salt) if err != nil { t.Errorf("Could not create HKDF object: %v", err) } output, err := p.ComputePRF(info, v.outputLength) if err != nil { t.Errorf("Error computing HKDF: %v", err) } if hex.EncodeToString(output) != v.okm { t.Errorf("Computation and test vector differ. Computation: %q, Test Vector %q", hex.EncodeToString(output), v.okm) } } } func TestHKDFPRFWycheproofCases(t *testing.T) { testutil.SkipTestIfTestSrcDirIsNotSet(t) for _, hash := range []string{"SHA1", "SHA256", "SHA512"} { filename := fmt.Sprintf("hkdf_%s_test.json", strings.ToLower(hash)) suite := new(hkdfSuite) if err := testutil.PopulateSuite(suite, filename); err != nil { t.Fatalf("Failed populating suite: %s", err) } for _, group := range suite.TestGroups { for _, test := range group.Tests { caseName := fmt.Sprintf("%s-%s-%s(%d):Case-%d", suite.Algorithm, group.Type, hash, group.KeySize, test.CaseID) t.Run(caseName, func(t *testing.T) { if uint32(len(test.IKM))*8 != group.KeySize { t.Fatal("Invalid key length") } hkdfPRF, err := subtle.NewHKDFPRF(hash, test.IKM, test.Salt) switch test.Result { case "valid": if err != nil { t.Fatalf("NewHKDFPRF failed: %v", err) } res, err := hkdfPRF.ComputePRF(test.Info, test.Size) if err != nil { t.Fatalf("ComputePRF() failed: %v", err) } if !bytes.Equal(res, test.OKM) { t.Errorf("ComputePRF() result and expected result do not match:\nComputed: %q\nExpected: %q", hex.EncodeToString(res), test.OKM) } case "invalid": if err != nil { return } res, err := hkdfPRF.ComputePRF(test.Info, test.Size) if err != nil { return } if bytes.Equal(res, test.OKM) { t.Errorf("ComputePRF() result and invalid expected result match:\nComputed: %q\nExpected: %q", hex.EncodeToString(res), test.OKM) } default: t.Fatalf("Unsupported test result: %q", test.Result) } }) } } } } func TestHKDFPRFHash(t *testing.T) { if _, err := subtle.NewHKDFPRF("SHA256", []byte{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}, []byte{}); err != nil { t.Errorf("Expected NewHKDFPRF to work with SHA256: %v", err) } if _, err := subtle.NewHKDFPRF("SHA512", []byte{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}, []byte{}); err != nil { t.Errorf("Expected NewHKDFPRF to work with SHA512: %v", err) } if _, err := subtle.NewHKDFPRF("SHA1", []byte{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}, []byte{}); err != nil { t.Errorf("Expected NewHKDFPRF to work with SHA1: %v", err) } if _, err := subtle.NewHKDFPRF("md5", []byte{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}, []byte{}); err == nil { t.Errorf("Expected NewHKDFPRF to fail with md5") } } func TestHKDFPRFSalt(t *testing.T) { if _, err := subtle.NewHKDFPRF("SHA256", []byte{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}, nil); err != nil { t.Errorf("Expected NewHKDFPRF to work nil salt: %v", err) } if _, err := subtle.NewHKDFPRF("SHA256", []byte{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}, []byte{}); err != nil { t.Errorf("Expected NewHKDFPRF to work empty salt: %v", err) } if _, err := subtle.NewHKDFPRF("SHA256", []byte{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}, []byte{0xaf, 0xfe, 0xc0, 0xff, 0xee}); err != nil { t.Errorf("Expected NewHKDFPRF to work with salt: %v", err) } } func TestHKDFPRFOutputLength(t *testing.T) { for hash, length := range map[string]int{"SHA1": 20, "SHA256": 32, "SHA512": 64} { prf, err := subtle.NewHKDFPRF(hash, []byte{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}, []byte{}) if err != nil { t.Errorf("Expected NewHKDFPRF to work on 32 byte key with hash %s", hash) } for i := 0; i <= length*255; i++ { output, err := prf.ComputePRF([]byte{0x01, 0x02}, uint32(i)) if err != nil { t.Errorf("Expected to be able to compute HKDF %s PRF with %d output length", hash, i) } if len(output) != i { t.Errorf("Expected HKDF %s PRF to compute %d bytes, got %d", hash, i, len(output)) } } for i := length*255 + 1; i < length*255+100; i++ { _, err := prf.ComputePRF([]byte{0x01, 0x02}, uint32(i)) if err == nil { t.Errorf("Expected to not be able to compute HKDF %s PRF with %d output length", hash, i) } } } } func TestValidateHKDFPRFParams(t *testing.T) { if err := subtle.ValidateHKDFPRFParams("SHA256", 32, []byte{}); err != nil { t.Errorf("Unexpected error for valid HKDF PRF params: %v", err) } if err := subtle.ValidateHKDFPRFParams("SHA256", 32, nil); err != nil { t.Errorf("Unexpected error for valid HKDF PRF params: %v", err) } if err := subtle.ValidateHKDFPRFParams("SHA256", 32, []byte{0xaf, 0xfe, 0xc0, 0xff, 0xee}); err != nil { t.Errorf("Unexpected error for salted valid HKDF PRF params: %v", err) } if err := subtle.ValidateHKDFPRFParams("SHA256", 4, []byte{}); err == nil { t.Errorf("Short key size not detected for HKDF PRF params") } if err := subtle.ValidateHKDFPRFParams("md5", 32, []byte{}); err == nil { t.Errorf("Weak hash function not detected for HKDF PRF params") } if err := subtle.ValidateHKDFPRFParams("SHA1", 32, []byte{}); err == nil { t.Errorf("Weak hash function not detected for HKDF PRF params") } } ================================================ FILE: go/prf/subtle/hmac.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "crypto/hmac" "fmt" "hash" "github.com/google/tink/go/subtle" ) const ( minHMACKeySizeInBytes = uint32(16) ) // HMACPRF is a type that can be used to compute several HMACs with the same key material. type HMACPRF struct { h func() hash.Hash key []byte } // NewHMACPRF creates a new HMACPRF object and initializes it with the correct key material. func NewHMACPRF(hashAlg string, key []byte) (*HMACPRF, error) { h := &HMACPRF{} hashFunc := subtle.GetHashFunc(hashAlg) if hashFunc == nil { return nil, fmt.Errorf("hmac: invalid hash algorithm") } h.h = hashFunc h.key = key return h, nil } // ValidateHMACPRFParams validates parameters of HMAC constructor. func ValidateHMACPRFParams(hash string, keySize uint32) error { // validate key size if keySize < minHMACKeySizeInBytes { return fmt.Errorf("key too short") } if subtle.GetHashFunc(hash) == nil { return fmt.Errorf("invalid hash function") } return nil } // ComputePRF computes the HMAC for the given key and data, returning outputLength bytes. func (h HMACPRF) ComputePRF(data []byte, outputLength uint32) ([]byte, error) { mac := hmac.New(h.h, h.key) if outputLength > uint32(mac.Size()) { return nil, fmt.Errorf("outputLength must be between 0 and %d", mac.Size()) } mac.Write(data) return mac.Sum(nil)[:outputLength], nil } ================================================ FILE: go/prf/subtle/hmac_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "bytes" "encoding/hex" "fmt" "strings" "testing" "github.com/google/tink/go/prf/subtle" "github.com/google/tink/go/testutil" ) type rfc4868test struct { key string data string prf map[string]string } func TestVectorsRFC4868(t *testing.T) { // Test vectors from RFC 4868. testvectors := []*rfc4868test{ { key: "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", data: "4869205468657265", prf: map[string]string{ "SHA256": "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7", "SHA512": "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854", }, }, { key: "4a656665", data: "7768617420646f2079612077616e7420666f72206e6f7468696e673f", prf: map[string]string{ "SHA256": "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843", "SHA512": "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737", }, }, { key: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", data: "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", prf: map[string]string{ "SHA256": "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe", "SHA512": "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb", }, }, { key: "0102030405060708090a0b0c0d0e0f10111213141516171819", data: "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd", prf: map[string]string{ "SHA256": "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b", "SHA512": "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd", }, }, { key: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", data: "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b6579202d2048617368204b6579204669727374", prf: map[string]string{ "SHA256": "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54", "SHA512": "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598", }, }, { key: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", data: "5468697320697320612074657374207573696e672061206c6172676572207468616e20626c6f636b2d73697a65206b657920616e642061206c6172676572207468616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565647320746f20626520686173686564206265666f7265206265696e6720757365642062792074686520484d414320616c676f726974686d2e", prf: map[string]string{ "SHA256": "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2", "SHA512": "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58", }, }, } for _, v := range testvectors { key, err := hex.DecodeString(v.key) if err != nil { t.Errorf("Could not decode key: %v", err) } data, err := hex.DecodeString(v.data) if err != nil { t.Errorf("Could not decode data: %v", err) } for hash, e := range v.prf { h, err := subtle.NewHMACPRF(hash, key) if err != nil { t.Errorf("Could not create HMAC PRF object: %v", err) } output, err := h.ComputePRF(data, uint32(len(e)/2)) if err != nil { t.Errorf("Error computing HMAC: %v", err) } if hex.EncodeToString(output) != e { t.Errorf("Computation and test vector differ. Computation: %q, Test Vector %q", hex.EncodeToString(output), e) } } } } func TestHMACPRFWycheproofCases(t *testing.T) { testutil.SkipTestIfTestSrcDirIsNotSet(t) for _, hash := range []string{"SHA1", "SHA256", "SHA512"} { filename := fmt.Sprintf("hmac_%s_test.json", strings.ToLower(hash)) suite := new(macSuite) if err := testutil.PopulateSuite(suite, filename); err != nil { t.Fatalf("Failed populating suite: %s", err) } for _, group := range suite.TestGroups { groupName := fmt.Sprintf("%s-%s-%s(%d)", suite.Algorithm, group.Type, hash, group.KeySize) if group.TagSize%8 != 0 { t.Errorf("For %s, requested tag size is not a multiple of 8, but %d", groupName, group.TagSize) } for _, test := range group.Tests { caseName := fmt.Sprintf("%s:Case-%d", groupName, test.CaseID) t.Run(caseName, func(t *testing.T) { h, err := subtle.NewHMACPRF(hash, test.Key) switch test.Result { case "valid": if err != nil { t.Fatalf("NewHMACPRF() failed: %v", err) } res, err := h.ComputePRF(test.Message, group.TagSize/8) if err != nil { t.Fatalf("ComputePRF() failed: %v", err) } if !bytes.Equal(res, test.Tag) { t.Errorf("ComputePRF() result and expected result do not match:\nComputed: %q\nExpected: %q", hex.EncodeToString(res), hex.EncodeToString(test.Tag)) } case "invalid": if err != nil { return } res, err := h.ComputePRF(test.Message, group.TagSize/8) if err != nil { return } if bytes.Equal(res, test.Tag) { t.Errorf("ComputePRF() result and invalid expected result match:\nComputed: %q\nExpected: %q", hex.EncodeToString(res), hex.EncodeToString(test.Tag)) } default: t.Fatalf("Unsupported test result: %q", test.Result) } }) } } } } func TestHMACPRFHash(t *testing.T) { if _, err := subtle.NewHMACPRF("SHA256", []byte{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}); err != nil { t.Errorf("Expected NewHMACPRF to work with SHA256: %v", err) } if _, err := subtle.NewHMACPRF("SHA512", []byte{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}); err != nil { t.Errorf("Expected NewHMACPRF to work with SHA512: %v", err) } if _, err := subtle.NewHMACPRF("SHA1", []byte{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}); err != nil { t.Errorf("Expected NewHMACPRF to work with SHA1: %v", err) } if _, err := subtle.NewHMACPRF("md5", []byte{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}); err == nil { t.Errorf("Expected NewHMACPRF to fail with md5") } } func TestHMACPRFOutputLength(t *testing.T) { for hash, length := range map[string]int{"SHA1": 20, "SHA256": 32, "SHA512": 64} { prf, err := subtle.NewHMACPRF(hash, []byte{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}) if err != nil { t.Errorf("Expected NewHMACPRF to work on 32 byte key with hash %s", hash) } for i := 0; i <= length; i++ { output, err := prf.ComputePRF([]byte{0x01, 0x02}, uint32(i)) if err != nil { t.Errorf("Expected to be able to compute HMAC %s PRF with %d output length", hash, i) } if len(output) != i { t.Errorf("Expected HMAC %s PRF to compute %d bytes, got %d", hash, i, len(output)) } } for i := length + 1; i < 100; i++ { _, err := prf.ComputePRF([]byte{0x01, 0x02}, uint32(i)) if err == nil { t.Errorf("Expected to not be able to compute HMAC %s PRF with %d output length", hash, i) } } } } func TestValidateHMACPRFParams(t *testing.T) { if err := subtle.ValidateHMACPRFParams("SHA256", 32); err != nil { t.Errorf("Unexpected error for valid HMAC PRF params: %v", err) } if err := subtle.ValidateHMACPRFParams("SHA256", 4); err == nil { t.Errorf("Short key size not detected for HMAC PRF params") } if err := subtle.ValidateHMACPRFParams("md5", 32); err == nil { t.Errorf("Weak hash function not detected for HMAC PRF params") } } ================================================ FILE: go/prf/subtle/subtle.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package subtle provides an implementation of PRFs like AES-CMAC. package subtle ================================================ FILE: go/prf/subtle/subtle_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import "github.com/google/tink/go/testutil" type macSuite struct { testutil.WycheproofSuite TestGroups []*macGroup `json:"testGroups"` } type macGroup struct { testutil.WycheproofGroup KeySize uint32 `json:"keySize"` TagSize uint32 `json:"tagSize"` Type string `json:"type"` Tests []*macCase `json:"tests"` } type macCase struct { testutil.WycheproofCase Key testutil.HexBytes `json:"key"` Message testutil.HexBytes `json:"msg"` Tag testutil.HexBytes `json:"tag"` } type hkdfSuite struct { testutil.WycheproofSuite TestGroups []*hkdfGroup `json:"testGroups"` } type hkdfGroup struct { testutil.WycheproofGroup KeySize uint32 `json:"keySize"` Type string `json:"type"` Tests []*hkdfCase `json:"tests"` } type hkdfCase struct { testutil.WycheproofCase IKM testutil.HexBytes `json:"ikm"` Salt testutil.HexBytes `json:"salt"` Info testutil.HexBytes `json:"info"` Size uint32 `json:"size"` OKM testutil.HexBytes `json:"okm"` } ================================================ FILE: go/proto/aes_cmac_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "aes_cmac_go_proto", srcs = ["aes_cmac.pb.go"], importpath = "github.com/google/tink/go/proto/aes_cmac_go_proto", visibility = ["//visibility:public"], deps = [ "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":aes_cmac_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/aes_cmac_go_proto/aes_cmac.pb.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/aes_cmac.proto package aes_cmac_go_proto import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type AesCmacParams struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields TagSize uint32 `protobuf:"varint,1,opt,name=tag_size,json=tagSize,proto3" json:"tag_size,omitempty"` } func (x *AesCmacParams) Reset() { *x = AesCmacParams{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_aes_cmac_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AesCmacParams) String() string { return protoimpl.X.MessageStringOf(x) } func (*AesCmacParams) ProtoMessage() {} func (x *AesCmacParams) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_aes_cmac_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AesCmacParams.ProtoReflect.Descriptor instead. func (*AesCmacParams) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_aes_cmac_proto_rawDescGZIP(), []int{0} } func (x *AesCmacParams) GetTagSize() uint32 { if x != nil { return x.TagSize } return 0 } // key_type: type.googleapis.com/google.crypto.tink.AesCmacKey type AesCmacKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` KeyValue []byte `protobuf:"bytes,2,opt,name=key_value,json=keyValue,proto3" json:"key_value,omitempty"` Params *AesCmacParams `protobuf:"bytes,3,opt,name=params,proto3" json:"params,omitempty"` } func (x *AesCmacKey) Reset() { *x = AesCmacKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_aes_cmac_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AesCmacKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*AesCmacKey) ProtoMessage() {} func (x *AesCmacKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_aes_cmac_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AesCmacKey.ProtoReflect.Descriptor instead. func (*AesCmacKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_aes_cmac_proto_rawDescGZIP(), []int{1} } func (x *AesCmacKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *AesCmacKey) GetKeyValue() []byte { if x != nil { return x.KeyValue } return nil } func (x *AesCmacKey) GetParams() *AesCmacParams { if x != nil { return x.Params } return nil } type AesCmacKeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields KeySize uint32 `protobuf:"varint,1,opt,name=key_size,json=keySize,proto3" json:"key_size,omitempty"` Params *AesCmacParams `protobuf:"bytes,2,opt,name=params,proto3" json:"params,omitempty"` } func (x *AesCmacKeyFormat) Reset() { *x = AesCmacKeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_aes_cmac_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AesCmacKeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*AesCmacKeyFormat) ProtoMessage() {} func (x *AesCmacKeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_aes_cmac_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AesCmacKeyFormat.ProtoReflect.Descriptor instead. func (*AesCmacKeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_aes_cmac_proto_rawDescGZIP(), []int{2} } func (x *AesCmacKeyFormat) GetKeySize() uint32 { if x != nil { return x.KeySize } return 0 } func (x *AesCmacKeyFormat) GetParams() *AesCmacParams { if x != nil { return x.Params } return nil } var File_third_party_tink_proto_aes_cmac_proto protoreflect.FileDescriptor var file_third_party_tink_proto_aes_cmac_proto_rawDesc = []byte{ 0x0a, 0x25, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x65, 0x73, 0x5f, 0x63, 0x6d, 0x61, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x22, 0x2a, 0x0a, 0x0d, 0x41, 0x65, 0x73, 0x43, 0x6d, 0x61, 0x63, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x61, 0x67, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x74, 0x61, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x7e, 0x0a, 0x0a, 0x41, 0x65, 0x73, 0x43, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x41, 0x65, 0x73, 0x43, 0x6d, 0x61, 0x63, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x68, 0x0a, 0x10, 0x41, 0x65, 0x73, 0x43, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x41, 0x65, 0x73, 0x43, 0x6d, 0x61, 0x63, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0x53, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x65, 0x73, 0x5f, 0x63, 0x6d, 0x61, 0x63, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_aes_cmac_proto_rawDescOnce sync.Once file_third_party_tink_proto_aes_cmac_proto_rawDescData = file_third_party_tink_proto_aes_cmac_proto_rawDesc ) func file_third_party_tink_proto_aes_cmac_proto_rawDescGZIP() []byte { file_third_party_tink_proto_aes_cmac_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_aes_cmac_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_aes_cmac_proto_rawDescData) }) return file_third_party_tink_proto_aes_cmac_proto_rawDescData } var file_third_party_tink_proto_aes_cmac_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_third_party_tink_proto_aes_cmac_proto_goTypes = []interface{}{ (*AesCmacParams)(nil), // 0: google.crypto.tink.AesCmacParams (*AesCmacKey)(nil), // 1: google.crypto.tink.AesCmacKey (*AesCmacKeyFormat)(nil), // 2: google.crypto.tink.AesCmacKeyFormat } var file_third_party_tink_proto_aes_cmac_proto_depIdxs = []int32{ 0, // 0: google.crypto.tink.AesCmacKey.params:type_name -> google.crypto.tink.AesCmacParams 0, // 1: google.crypto.tink.AesCmacKeyFormat.params:type_name -> google.crypto.tink.AesCmacParams 2, // [2:2] is the sub-list for method output_type 2, // [2:2] is the sub-list for method input_type 2, // [2:2] is the sub-list for extension type_name 2, // [2:2] is the sub-list for extension extendee 0, // [0:2] is the sub-list for field type_name } func init() { file_third_party_tink_proto_aes_cmac_proto_init() } func file_third_party_tink_proto_aes_cmac_proto_init() { if File_third_party_tink_proto_aes_cmac_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_aes_cmac_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AesCmacParams); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_aes_cmac_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AesCmacKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_aes_cmac_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AesCmacKeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_aes_cmac_proto_rawDesc, NumEnums: 0, NumMessages: 3, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_aes_cmac_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_aes_cmac_proto_depIdxs, MessageInfos: file_third_party_tink_proto_aes_cmac_proto_msgTypes, }.Build() File_third_party_tink_proto_aes_cmac_proto = out.File file_third_party_tink_proto_aes_cmac_proto_rawDesc = nil file_third_party_tink_proto_aes_cmac_proto_goTypes = nil file_third_party_tink_proto_aes_cmac_proto_depIdxs = nil } ================================================ FILE: go/proto/aes_cmac_prf_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "aes_cmac_prf_go_proto", srcs = ["aes_cmac_prf.pb.go"], importpath = "github.com/google/tink/go/proto/aes_cmac_prf_go_proto", visibility = ["//visibility:public"], deps = [ "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":aes_cmac_prf_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/aes_cmac_prf_go_proto/aes_cmac_prf.pb.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/aes_cmac_prf.proto package aes_cmac_prf_go_proto import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) // key_type: type.googleapis.com/google.crypto.tink.AesCmacPrfKey type AesCmacPrfKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` KeyValue []byte `protobuf:"bytes,2,opt,name=key_value,json=keyValue,proto3" json:"key_value,omitempty"` } func (x *AesCmacPrfKey) Reset() { *x = AesCmacPrfKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_aes_cmac_prf_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AesCmacPrfKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*AesCmacPrfKey) ProtoMessage() {} func (x *AesCmacPrfKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_aes_cmac_prf_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AesCmacPrfKey.ProtoReflect.Descriptor instead. func (*AesCmacPrfKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_aes_cmac_prf_proto_rawDescGZIP(), []int{0} } func (x *AesCmacPrfKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *AesCmacPrfKey) GetKeyValue() []byte { if x != nil { return x.KeyValue } return nil } type AesCmacPrfKeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` KeySize uint32 `protobuf:"varint,1,opt,name=key_size,json=keySize,proto3" json:"key_size,omitempty"` } func (x *AesCmacPrfKeyFormat) Reset() { *x = AesCmacPrfKeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_aes_cmac_prf_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AesCmacPrfKeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*AesCmacPrfKeyFormat) ProtoMessage() {} func (x *AesCmacPrfKeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_aes_cmac_prf_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AesCmacPrfKeyFormat.ProtoReflect.Descriptor instead. func (*AesCmacPrfKeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_aes_cmac_prf_proto_rawDescGZIP(), []int{1} } func (x *AesCmacPrfKeyFormat) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *AesCmacPrfKeyFormat) GetKeySize() uint32 { if x != nil { return x.KeySize } return 0 } var File_third_party_tink_proto_aes_cmac_prf_proto protoreflect.FileDescriptor var file_third_party_tink_proto_aes_cmac_prf_proto_rawDesc = []byte{ 0x0a, 0x29, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x65, 0x73, 0x5f, 0x63, 0x6d, 0x61, 0x63, 0x5f, 0x70, 0x72, 0x66, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x22, 0x46, 0x0a, 0x0d, 0x41, 0x65, 0x73, 0x43, 0x6d, 0x61, 0x63, 0x50, 0x72, 0x66, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x4a, 0x0a, 0x13, 0x41, 0x65, 0x73, 0x43, 0x6d, 0x61, 0x63, 0x50, 0x72, 0x66, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x57, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x65, 0x73, 0x5f, 0x63, 0x6d, 0x61, 0x63, 0x5f, 0x70, 0x72, 0x66, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_aes_cmac_prf_proto_rawDescOnce sync.Once file_third_party_tink_proto_aes_cmac_prf_proto_rawDescData = file_third_party_tink_proto_aes_cmac_prf_proto_rawDesc ) func file_third_party_tink_proto_aes_cmac_prf_proto_rawDescGZIP() []byte { file_third_party_tink_proto_aes_cmac_prf_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_aes_cmac_prf_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_aes_cmac_prf_proto_rawDescData) }) return file_third_party_tink_proto_aes_cmac_prf_proto_rawDescData } var file_third_party_tink_proto_aes_cmac_prf_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_third_party_tink_proto_aes_cmac_prf_proto_goTypes = []interface{}{ (*AesCmacPrfKey)(nil), // 0: google.crypto.tink.AesCmacPrfKey (*AesCmacPrfKeyFormat)(nil), // 1: google.crypto.tink.AesCmacPrfKeyFormat } var file_third_party_tink_proto_aes_cmac_prf_proto_depIdxs = []int32{ 0, // [0:0] is the sub-list for method output_type 0, // [0:0] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name } func init() { file_third_party_tink_proto_aes_cmac_prf_proto_init() } func file_third_party_tink_proto_aes_cmac_prf_proto_init() { if File_third_party_tink_proto_aes_cmac_prf_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_aes_cmac_prf_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AesCmacPrfKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_aes_cmac_prf_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AesCmacPrfKeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_aes_cmac_prf_proto_rawDesc, NumEnums: 0, NumMessages: 2, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_aes_cmac_prf_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_aes_cmac_prf_proto_depIdxs, MessageInfos: file_third_party_tink_proto_aes_cmac_prf_proto_msgTypes, }.Build() File_third_party_tink_proto_aes_cmac_prf_proto = out.File file_third_party_tink_proto_aes_cmac_prf_proto_rawDesc = nil file_third_party_tink_proto_aes_cmac_prf_proto_goTypes = nil file_third_party_tink_proto_aes_cmac_prf_proto_depIdxs = nil } ================================================ FILE: go/proto/aes_ctr_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "aes_ctr_go_proto", srcs = ["aes_ctr.pb.go"], importpath = "github.com/google/tink/go/proto/aes_ctr_go_proto", visibility = ["//visibility:public"], deps = [ "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":aes_ctr_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/aes_ctr_go_proto/aes_ctr.pb.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/aes_ctr.proto package aes_ctr_go_proto import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type AesCtrParams struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields IvSize uint32 `protobuf:"varint,1,opt,name=iv_size,json=ivSize,proto3" json:"iv_size,omitempty"` } func (x *AesCtrParams) Reset() { *x = AesCtrParams{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_aes_ctr_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AesCtrParams) String() string { return protoimpl.X.MessageStringOf(x) } func (*AesCtrParams) ProtoMessage() {} func (x *AesCtrParams) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_aes_ctr_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AesCtrParams.ProtoReflect.Descriptor instead. func (*AesCtrParams) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_aes_ctr_proto_rawDescGZIP(), []int{0} } func (x *AesCtrParams) GetIvSize() uint32 { if x != nil { return x.IvSize } return 0 } type AesCtrKeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Params *AesCtrParams `protobuf:"bytes,1,opt,name=params,proto3" json:"params,omitempty"` KeySize uint32 `protobuf:"varint,2,opt,name=key_size,json=keySize,proto3" json:"key_size,omitempty"` } func (x *AesCtrKeyFormat) Reset() { *x = AesCtrKeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_aes_ctr_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AesCtrKeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*AesCtrKeyFormat) ProtoMessage() {} func (x *AesCtrKeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_aes_ctr_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AesCtrKeyFormat.ProtoReflect.Descriptor instead. func (*AesCtrKeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_aes_ctr_proto_rawDescGZIP(), []int{1} } func (x *AesCtrKeyFormat) GetParams() *AesCtrParams { if x != nil { return x.Params } return nil } func (x *AesCtrKeyFormat) GetKeySize() uint32 { if x != nil { return x.KeySize } return 0 } // key_type: type.googleapis.com/google.crypto.tink.AesCtrKey type AesCtrKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` Params *AesCtrParams `protobuf:"bytes,2,opt,name=params,proto3" json:"params,omitempty"` KeyValue []byte `protobuf:"bytes,3,opt,name=key_value,json=keyValue,proto3" json:"key_value,omitempty"` } func (x *AesCtrKey) Reset() { *x = AesCtrKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_aes_ctr_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AesCtrKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*AesCtrKey) ProtoMessage() {} func (x *AesCtrKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_aes_ctr_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AesCtrKey.ProtoReflect.Descriptor instead. func (*AesCtrKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_aes_ctr_proto_rawDescGZIP(), []int{2} } func (x *AesCtrKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *AesCtrKey) GetParams() *AesCtrParams { if x != nil { return x.Params } return nil } func (x *AesCtrKey) GetKeyValue() []byte { if x != nil { return x.KeyValue } return nil } var File_third_party_tink_proto_aes_ctr_proto protoreflect.FileDescriptor var file_third_party_tink_proto_aes_ctr_proto_rawDesc = []byte{ 0x0a, 0x24, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x65, 0x73, 0x5f, 0x63, 0x74, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x22, 0x27, 0x0a, 0x0c, 0x41, 0x65, 0x73, 0x43, 0x74, 0x72, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x76, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x69, 0x76, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x66, 0x0a, 0x0f, 0x41, 0x65, 0x73, 0x43, 0x74, 0x72, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x38, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x41, 0x65, 0x73, 0x43, 0x74, 0x72, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x7c, 0x0a, 0x09, 0x41, 0x65, 0x73, 0x43, 0x74, 0x72, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x41, 0x65, 0x73, 0x43, 0x74, 0x72, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x52, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x65, 0x73, 0x5f, 0x63, 0x74, 0x72, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_aes_ctr_proto_rawDescOnce sync.Once file_third_party_tink_proto_aes_ctr_proto_rawDescData = file_third_party_tink_proto_aes_ctr_proto_rawDesc ) func file_third_party_tink_proto_aes_ctr_proto_rawDescGZIP() []byte { file_third_party_tink_proto_aes_ctr_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_aes_ctr_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_aes_ctr_proto_rawDescData) }) return file_third_party_tink_proto_aes_ctr_proto_rawDescData } var file_third_party_tink_proto_aes_ctr_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_third_party_tink_proto_aes_ctr_proto_goTypes = []interface{}{ (*AesCtrParams)(nil), // 0: google.crypto.tink.AesCtrParams (*AesCtrKeyFormat)(nil), // 1: google.crypto.tink.AesCtrKeyFormat (*AesCtrKey)(nil), // 2: google.crypto.tink.AesCtrKey } var file_third_party_tink_proto_aes_ctr_proto_depIdxs = []int32{ 0, // 0: google.crypto.tink.AesCtrKeyFormat.params:type_name -> google.crypto.tink.AesCtrParams 0, // 1: google.crypto.tink.AesCtrKey.params:type_name -> google.crypto.tink.AesCtrParams 2, // [2:2] is the sub-list for method output_type 2, // [2:2] is the sub-list for method input_type 2, // [2:2] is the sub-list for extension type_name 2, // [2:2] is the sub-list for extension extendee 0, // [0:2] is the sub-list for field type_name } func init() { file_third_party_tink_proto_aes_ctr_proto_init() } func file_third_party_tink_proto_aes_ctr_proto_init() { if File_third_party_tink_proto_aes_ctr_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_aes_ctr_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AesCtrParams); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_aes_ctr_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AesCtrKeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_aes_ctr_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AesCtrKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_aes_ctr_proto_rawDesc, NumEnums: 0, NumMessages: 3, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_aes_ctr_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_aes_ctr_proto_depIdxs, MessageInfos: file_third_party_tink_proto_aes_ctr_proto_msgTypes, }.Build() File_third_party_tink_proto_aes_ctr_proto = out.File file_third_party_tink_proto_aes_ctr_proto_rawDesc = nil file_third_party_tink_proto_aes_ctr_proto_goTypes = nil file_third_party_tink_proto_aes_ctr_proto_depIdxs = nil } ================================================ FILE: go/proto/aes_ctr_hmac_aead_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "aes_ctr_hmac_aead_go_proto", srcs = ["aes_ctr_hmac_aead.pb.go"], importpath = "github.com/google/tink/go/proto/aes_ctr_hmac_aead_go_proto", visibility = ["//visibility:public"], deps = [ "//proto/aes_ctr_go_proto", "//proto/hmac_go_proto", "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":aes_ctr_hmac_aead_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/aes_ctr_hmac_aead_go_proto/aes_ctr_hmac_aead.pb.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/aes_ctr_hmac_aead.proto package aes_ctr_hmac_aead_go_proto import ( aes_ctr_go_proto "github.com/google/tink/go/proto/aes_ctr_go_proto" hmac_go_proto "github.com/google/tink/go/proto/hmac_go_proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type AesCtrHmacAeadKeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields AesCtrKeyFormat *aes_ctr_go_proto.AesCtrKeyFormat `protobuf:"bytes,1,opt,name=aes_ctr_key_format,json=aesCtrKeyFormat,proto3" json:"aes_ctr_key_format,omitempty"` HmacKeyFormat *hmac_go_proto.HmacKeyFormat `protobuf:"bytes,2,opt,name=hmac_key_format,json=hmacKeyFormat,proto3" json:"hmac_key_format,omitempty"` } func (x *AesCtrHmacAeadKeyFormat) Reset() { *x = AesCtrHmacAeadKeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_aes_ctr_hmac_aead_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AesCtrHmacAeadKeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*AesCtrHmacAeadKeyFormat) ProtoMessage() {} func (x *AesCtrHmacAeadKeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_aes_ctr_hmac_aead_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AesCtrHmacAeadKeyFormat.ProtoReflect.Descriptor instead. func (*AesCtrHmacAeadKeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_aes_ctr_hmac_aead_proto_rawDescGZIP(), []int{0} } func (x *AesCtrHmacAeadKeyFormat) GetAesCtrKeyFormat() *aes_ctr_go_proto.AesCtrKeyFormat { if x != nil { return x.AesCtrKeyFormat } return nil } func (x *AesCtrHmacAeadKeyFormat) GetHmacKeyFormat() *hmac_go_proto.HmacKeyFormat { if x != nil { return x.HmacKeyFormat } return nil } // key_type: type.googleapis.com/google.crypto.tink.AesCtrHmacAeadKey type AesCtrHmacAeadKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` AesCtrKey *aes_ctr_go_proto.AesCtrKey `protobuf:"bytes,2,opt,name=aes_ctr_key,json=aesCtrKey,proto3" json:"aes_ctr_key,omitempty"` HmacKey *hmac_go_proto.HmacKey `protobuf:"bytes,3,opt,name=hmac_key,json=hmacKey,proto3" json:"hmac_key,omitempty"` } func (x *AesCtrHmacAeadKey) Reset() { *x = AesCtrHmacAeadKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_aes_ctr_hmac_aead_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AesCtrHmacAeadKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*AesCtrHmacAeadKey) ProtoMessage() {} func (x *AesCtrHmacAeadKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_aes_ctr_hmac_aead_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AesCtrHmacAeadKey.ProtoReflect.Descriptor instead. func (*AesCtrHmacAeadKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_aes_ctr_hmac_aead_proto_rawDescGZIP(), []int{1} } func (x *AesCtrHmacAeadKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *AesCtrHmacAeadKey) GetAesCtrKey() *aes_ctr_go_proto.AesCtrKey { if x != nil { return x.AesCtrKey } return nil } func (x *AesCtrHmacAeadKey) GetHmacKey() *hmac_go_proto.HmacKey { if x != nil { return x.HmacKey } return nil } var File_third_party_tink_proto_aes_ctr_hmac_aead_proto protoreflect.FileDescriptor var file_third_party_tink_proto_aes_ctr_hmac_aead_proto_rawDesc = []byte{ 0x0a, 0x2e, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x65, 0x73, 0x5f, 0x63, 0x74, 0x72, 0x5f, 0x68, 0x6d, 0x61, 0x63, 0x5f, 0x61, 0x65, 0x61, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x1a, 0x24, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x65, 0x73, 0x5f, 0x63, 0x74, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x68, 0x6d, 0x61, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb6, 0x01, 0x0a, 0x17, 0x41, 0x65, 0x73, 0x43, 0x74, 0x72, 0x48, 0x6d, 0x61, 0x63, 0x41, 0x65, 0x61, 0x64, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x50, 0x0a, 0x12, 0x61, 0x65, 0x73, 0x5f, 0x63, 0x74, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x41, 0x65, 0x73, 0x43, 0x74, 0x72, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x0f, 0x61, 0x65, 0x73, 0x43, 0x74, 0x72, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x49, 0x0a, 0x0f, 0x68, 0x6d, 0x61, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x0d, 0x68, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, 0xa4, 0x01, 0x0a, 0x11, 0x41, 0x65, 0x73, 0x43, 0x74, 0x72, 0x48, 0x6d, 0x61, 0x63, 0x41, 0x65, 0x61, 0x64, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3d, 0x0a, 0x0b, 0x61, 0x65, 0x73, 0x5f, 0x63, 0x74, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x41, 0x65, 0x73, 0x43, 0x74, 0x72, 0x4b, 0x65, 0x79, 0x52, 0x09, 0x61, 0x65, 0x73, 0x43, 0x74, 0x72, 0x4b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x08, 0x68, 0x6d, 0x61, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x07, 0x68, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x5c, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x65, 0x73, 0x5f, 0x63, 0x74, 0x72, 0x5f, 0x68, 0x6d, 0x61, 0x63, 0x5f, 0x61, 0x65, 0x61, 0x64, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_aes_ctr_hmac_aead_proto_rawDescOnce sync.Once file_third_party_tink_proto_aes_ctr_hmac_aead_proto_rawDescData = file_third_party_tink_proto_aes_ctr_hmac_aead_proto_rawDesc ) func file_third_party_tink_proto_aes_ctr_hmac_aead_proto_rawDescGZIP() []byte { file_third_party_tink_proto_aes_ctr_hmac_aead_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_aes_ctr_hmac_aead_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_aes_ctr_hmac_aead_proto_rawDescData) }) return file_third_party_tink_proto_aes_ctr_hmac_aead_proto_rawDescData } var file_third_party_tink_proto_aes_ctr_hmac_aead_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_third_party_tink_proto_aes_ctr_hmac_aead_proto_goTypes = []interface{}{ (*AesCtrHmacAeadKeyFormat)(nil), // 0: google.crypto.tink.AesCtrHmacAeadKeyFormat (*AesCtrHmacAeadKey)(nil), // 1: google.crypto.tink.AesCtrHmacAeadKey (*aes_ctr_go_proto.AesCtrKeyFormat)(nil), // 2: google.crypto.tink.AesCtrKeyFormat (*hmac_go_proto.HmacKeyFormat)(nil), // 3: google.crypto.tink.HmacKeyFormat (*aes_ctr_go_proto.AesCtrKey)(nil), // 4: google.crypto.tink.AesCtrKey (*hmac_go_proto.HmacKey)(nil), // 5: google.crypto.tink.HmacKey } var file_third_party_tink_proto_aes_ctr_hmac_aead_proto_depIdxs = []int32{ 2, // 0: google.crypto.tink.AesCtrHmacAeadKeyFormat.aes_ctr_key_format:type_name -> google.crypto.tink.AesCtrKeyFormat 3, // 1: google.crypto.tink.AesCtrHmacAeadKeyFormat.hmac_key_format:type_name -> google.crypto.tink.HmacKeyFormat 4, // 2: google.crypto.tink.AesCtrHmacAeadKey.aes_ctr_key:type_name -> google.crypto.tink.AesCtrKey 5, // 3: google.crypto.tink.AesCtrHmacAeadKey.hmac_key:type_name -> google.crypto.tink.HmacKey 4, // [4:4] is the sub-list for method output_type 4, // [4:4] is the sub-list for method input_type 4, // [4:4] is the sub-list for extension type_name 4, // [4:4] is the sub-list for extension extendee 0, // [0:4] is the sub-list for field type_name } func init() { file_third_party_tink_proto_aes_ctr_hmac_aead_proto_init() } func file_third_party_tink_proto_aes_ctr_hmac_aead_proto_init() { if File_third_party_tink_proto_aes_ctr_hmac_aead_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_aes_ctr_hmac_aead_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AesCtrHmacAeadKeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_aes_ctr_hmac_aead_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AesCtrHmacAeadKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_aes_ctr_hmac_aead_proto_rawDesc, NumEnums: 0, NumMessages: 2, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_aes_ctr_hmac_aead_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_aes_ctr_hmac_aead_proto_depIdxs, MessageInfos: file_third_party_tink_proto_aes_ctr_hmac_aead_proto_msgTypes, }.Build() File_third_party_tink_proto_aes_ctr_hmac_aead_proto = out.File file_third_party_tink_proto_aes_ctr_hmac_aead_proto_rawDesc = nil file_third_party_tink_proto_aes_ctr_hmac_aead_proto_goTypes = nil file_third_party_tink_proto_aes_ctr_hmac_aead_proto_depIdxs = nil } ================================================ FILE: go/proto/aes_ctr_hmac_streaming_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "aes_ctr_hmac_streaming_go_proto", srcs = ["aes_ctr_hmac_streaming.pb.go"], importpath = "github.com/google/tink/go/proto/aes_ctr_hmac_streaming_go_proto", visibility = ["//visibility:public"], deps = [ "//proto/common_go_proto", "//proto/hmac_go_proto", "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":aes_ctr_hmac_streaming_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/aes_ctr_hmac_streaming_go_proto/aes_ctr_hmac_streaming.pb.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/aes_ctr_hmac_streaming.proto package aes_ctr_hmac_streaming_go_proto import ( common_go_proto "github.com/google/tink/go/proto/common_go_proto" hmac_go_proto "github.com/google/tink/go/proto/hmac_go_proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type AesCtrHmacStreamingParams struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields CiphertextSegmentSize uint32 `protobuf:"varint,1,opt,name=ciphertext_segment_size,json=ciphertextSegmentSize,proto3" json:"ciphertext_segment_size,omitempty"` DerivedKeySize uint32 `protobuf:"varint,2,opt,name=derived_key_size,json=derivedKeySize,proto3" json:"derived_key_size,omitempty"` // size of AES-CTR keys derived for each segment HkdfHashType common_go_proto.HashType `protobuf:"varint,3,opt,name=hkdf_hash_type,json=hkdfHashType,proto3,enum=google.crypto.tink.HashType" json:"hkdf_hash_type,omitempty"` // hash function for key derivation via HKDF HmacParams *hmac_go_proto.HmacParams `protobuf:"bytes,4,opt,name=hmac_params,json=hmacParams,proto3" json:"hmac_params,omitempty"` // params for authentication tags } func (x *AesCtrHmacStreamingParams) Reset() { *x = AesCtrHmacStreamingParams{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AesCtrHmacStreamingParams) String() string { return protoimpl.X.MessageStringOf(x) } func (*AesCtrHmacStreamingParams) ProtoMessage() {} func (x *AesCtrHmacStreamingParams) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AesCtrHmacStreamingParams.ProtoReflect.Descriptor instead. func (*AesCtrHmacStreamingParams) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_rawDescGZIP(), []int{0} } func (x *AesCtrHmacStreamingParams) GetCiphertextSegmentSize() uint32 { if x != nil { return x.CiphertextSegmentSize } return 0 } func (x *AesCtrHmacStreamingParams) GetDerivedKeySize() uint32 { if x != nil { return x.DerivedKeySize } return 0 } func (x *AesCtrHmacStreamingParams) GetHkdfHashType() common_go_proto.HashType { if x != nil { return x.HkdfHashType } return common_go_proto.HashType(0) } func (x *AesCtrHmacStreamingParams) GetHmacParams() *hmac_go_proto.HmacParams { if x != nil { return x.HmacParams } return nil } type AesCtrHmacStreamingKeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,3,opt,name=version,proto3" json:"version,omitempty"` Params *AesCtrHmacStreamingParams `protobuf:"bytes,1,opt,name=params,proto3" json:"params,omitempty"` KeySize uint32 `protobuf:"varint,2,opt,name=key_size,json=keySize,proto3" json:"key_size,omitempty"` // size of the main key (aka. "ikm", input key material) } func (x *AesCtrHmacStreamingKeyFormat) Reset() { *x = AesCtrHmacStreamingKeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AesCtrHmacStreamingKeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*AesCtrHmacStreamingKeyFormat) ProtoMessage() {} func (x *AesCtrHmacStreamingKeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AesCtrHmacStreamingKeyFormat.ProtoReflect.Descriptor instead. func (*AesCtrHmacStreamingKeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_rawDescGZIP(), []int{1} } func (x *AesCtrHmacStreamingKeyFormat) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *AesCtrHmacStreamingKeyFormat) GetParams() *AesCtrHmacStreamingParams { if x != nil { return x.Params } return nil } func (x *AesCtrHmacStreamingKeyFormat) GetKeySize() uint32 { if x != nil { return x.KeySize } return 0 } // key_type: type.googleapis.com/google.crypto.tink.AesCtrHmacStreamingKey type AesCtrHmacStreamingKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` Params *AesCtrHmacStreamingParams `protobuf:"bytes,2,opt,name=params,proto3" json:"params,omitempty"` KeyValue []byte `protobuf:"bytes,3,opt,name=key_value,json=keyValue,proto3" json:"key_value,omitempty"` // the main key, aka. "ikm", input key material } func (x *AesCtrHmacStreamingKey) Reset() { *x = AesCtrHmacStreamingKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AesCtrHmacStreamingKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*AesCtrHmacStreamingKey) ProtoMessage() {} func (x *AesCtrHmacStreamingKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AesCtrHmacStreamingKey.ProtoReflect.Descriptor instead. func (*AesCtrHmacStreamingKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_rawDescGZIP(), []int{2} } func (x *AesCtrHmacStreamingKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *AesCtrHmacStreamingKey) GetParams() *AesCtrHmacStreamingParams { if x != nil { return x.Params } return nil } func (x *AesCtrHmacStreamingKey) GetKeyValue() []byte { if x != nil { return x.KeyValue } return nil } var File_third_party_tink_proto_aes_ctr_hmac_streaming_proto protoreflect.FileDescriptor var file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_rawDesc = []byte{ 0x0a, 0x33, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x65, 0x73, 0x5f, 0x63, 0x74, 0x72, 0x5f, 0x68, 0x6d, 0x61, 0x63, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x1a, 0x23, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x68, 0x6d, 0x61, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x82, 0x02, 0x0a, 0x19, 0x41, 0x65, 0x73, 0x43, 0x74, 0x72, 0x48, 0x6d, 0x61, 0x63, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x36, 0x0a, 0x17, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x15, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x64, 0x65, 0x72, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x64, 0x65, 0x72, 0x69, 0x76, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x42, 0x0a, 0x0e, 0x68, 0x6b, 0x64, 0x66, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0c, 0x68, 0x6b, 0x64, 0x66, 0x48, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x3f, 0x0a, 0x0b, 0x68, 0x6d, 0x61, 0x63, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x6d, 0x61, 0x63, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x0a, 0x68, 0x6d, 0x61, 0x63, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x9a, 0x01, 0x0a, 0x1c, 0x41, 0x65, 0x73, 0x43, 0x74, 0x72, 0x48, 0x6d, 0x61, 0x63, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x41, 0x65, 0x73, 0x43, 0x74, 0x72, 0x48, 0x6d, 0x61, 0x63, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x96, 0x01, 0x0a, 0x16, 0x41, 0x65, 0x73, 0x43, 0x74, 0x72, 0x48, 0x6d, 0x61, 0x63, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x41, 0x65, 0x73, 0x43, 0x74, 0x72, 0x48, 0x6d, 0x61, 0x63, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x61, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x65, 0x73, 0x5f, 0x63, 0x74, 0x72, 0x5f, 0x68, 0x6d, 0x61, 0x63, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_rawDescOnce sync.Once file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_rawDescData = file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_rawDesc ) func file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_rawDescGZIP() []byte { file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_rawDescData) }) return file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_rawDescData } var file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_goTypes = []interface{}{ (*AesCtrHmacStreamingParams)(nil), // 0: google.crypto.tink.AesCtrHmacStreamingParams (*AesCtrHmacStreamingKeyFormat)(nil), // 1: google.crypto.tink.AesCtrHmacStreamingKeyFormat (*AesCtrHmacStreamingKey)(nil), // 2: google.crypto.tink.AesCtrHmacStreamingKey (common_go_proto.HashType)(0), // 3: google.crypto.tink.HashType (*hmac_go_proto.HmacParams)(nil), // 4: google.crypto.tink.HmacParams } var file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_depIdxs = []int32{ 3, // 0: google.crypto.tink.AesCtrHmacStreamingParams.hkdf_hash_type:type_name -> google.crypto.tink.HashType 4, // 1: google.crypto.tink.AesCtrHmacStreamingParams.hmac_params:type_name -> google.crypto.tink.HmacParams 0, // 2: google.crypto.tink.AesCtrHmacStreamingKeyFormat.params:type_name -> google.crypto.tink.AesCtrHmacStreamingParams 0, // 3: google.crypto.tink.AesCtrHmacStreamingKey.params:type_name -> google.crypto.tink.AesCtrHmacStreamingParams 4, // [4:4] is the sub-list for method output_type 4, // [4:4] is the sub-list for method input_type 4, // [4:4] is the sub-list for extension type_name 4, // [4:4] is the sub-list for extension extendee 0, // [0:4] is the sub-list for field type_name } func init() { file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_init() } func file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_init() { if File_third_party_tink_proto_aes_ctr_hmac_streaming_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AesCtrHmacStreamingParams); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AesCtrHmacStreamingKeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AesCtrHmacStreamingKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_rawDesc, NumEnums: 0, NumMessages: 3, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_depIdxs, MessageInfos: file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_msgTypes, }.Build() File_third_party_tink_proto_aes_ctr_hmac_streaming_proto = out.File file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_rawDesc = nil file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_goTypes = nil file_third_party_tink_proto_aes_ctr_hmac_streaming_proto_depIdxs = nil } ================================================ FILE: go/proto/aes_gcm_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "aes_gcm_go_proto", srcs = ["aes_gcm.pb.go"], importpath = "github.com/google/tink/go/proto/aes_gcm_go_proto", visibility = ["//visibility:public"], deps = [ "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":aes_gcm_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/aes_gcm_go_proto/aes_gcm.pb.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/aes_gcm.proto package aes_gcm_go_proto import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type AesGcmKeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields KeySize uint32 `protobuf:"varint,2,opt,name=key_size,json=keySize,proto3" json:"key_size,omitempty"` Version uint32 `protobuf:"varint,3,opt,name=version,proto3" json:"version,omitempty"` } func (x *AesGcmKeyFormat) Reset() { *x = AesGcmKeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_aes_gcm_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AesGcmKeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*AesGcmKeyFormat) ProtoMessage() {} func (x *AesGcmKeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_aes_gcm_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AesGcmKeyFormat.ProtoReflect.Descriptor instead. func (*AesGcmKeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_aes_gcm_proto_rawDescGZIP(), []int{0} } func (x *AesGcmKeyFormat) GetKeySize() uint32 { if x != nil { return x.KeySize } return 0 } func (x *AesGcmKeyFormat) GetVersion() uint32 { if x != nil { return x.Version } return 0 } type AesGcmKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` KeyValue []byte `protobuf:"bytes,3,opt,name=key_value,json=keyValue,proto3" json:"key_value,omitempty"` } func (x *AesGcmKey) Reset() { *x = AesGcmKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_aes_gcm_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AesGcmKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*AesGcmKey) ProtoMessage() {} func (x *AesGcmKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_aes_gcm_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AesGcmKey.ProtoReflect.Descriptor instead. func (*AesGcmKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_aes_gcm_proto_rawDescGZIP(), []int{1} } func (x *AesGcmKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *AesGcmKey) GetKeyValue() []byte { if x != nil { return x.KeyValue } return nil } var File_third_party_tink_proto_aes_gcm_proto protoreflect.FileDescriptor var file_third_party_tink_proto_aes_gcm_proto_rawDesc = []byte{ 0x0a, 0x24, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x65, 0x73, 0x5f, 0x67, 0x63, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x22, 0x46, 0x0a, 0x0f, 0x41, 0x65, 0x73, 0x47, 0x63, 0x6d, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x42, 0x0a, 0x09, 0x41, 0x65, 0x73, 0x47, 0x63, 0x6d, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x5b, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x65, 0x73, 0x5f, 0x67, 0x63, 0x6d, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xa2, 0x02, 0x06, 0x54, 0x49, 0x4e, 0x4b, 0x50, 0x42, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_aes_gcm_proto_rawDescOnce sync.Once file_third_party_tink_proto_aes_gcm_proto_rawDescData = file_third_party_tink_proto_aes_gcm_proto_rawDesc ) func file_third_party_tink_proto_aes_gcm_proto_rawDescGZIP() []byte { file_third_party_tink_proto_aes_gcm_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_aes_gcm_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_aes_gcm_proto_rawDescData) }) return file_third_party_tink_proto_aes_gcm_proto_rawDescData } var file_third_party_tink_proto_aes_gcm_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_third_party_tink_proto_aes_gcm_proto_goTypes = []interface{}{ (*AesGcmKeyFormat)(nil), // 0: google.crypto.tink.AesGcmKeyFormat (*AesGcmKey)(nil), // 1: google.crypto.tink.AesGcmKey } var file_third_party_tink_proto_aes_gcm_proto_depIdxs = []int32{ 0, // [0:0] is the sub-list for method output_type 0, // [0:0] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name } func init() { file_third_party_tink_proto_aes_gcm_proto_init() } func file_third_party_tink_proto_aes_gcm_proto_init() { if File_third_party_tink_proto_aes_gcm_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_aes_gcm_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AesGcmKeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_aes_gcm_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AesGcmKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_aes_gcm_proto_rawDesc, NumEnums: 0, NumMessages: 2, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_aes_gcm_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_aes_gcm_proto_depIdxs, MessageInfos: file_third_party_tink_proto_aes_gcm_proto_msgTypes, }.Build() File_third_party_tink_proto_aes_gcm_proto = out.File file_third_party_tink_proto_aes_gcm_proto_rawDesc = nil file_third_party_tink_proto_aes_gcm_proto_goTypes = nil file_third_party_tink_proto_aes_gcm_proto_depIdxs = nil } ================================================ FILE: go/proto/aes_gcm_hkdf_streaming_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "aes_gcm_hkdf_streaming_go_proto", srcs = ["aes_gcm_hkdf_streaming.pb.go"], importpath = "github.com/google/tink/go/proto/aes_gcm_hkdf_streaming_go_proto", visibility = ["//visibility:public"], deps = [ "//proto/common_go_proto", "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":aes_gcm_hkdf_streaming_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/aes_gcm_hkdf_streaming_go_proto/aes_gcm_hkdf_streaming.pb.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Definitions for streaming encryption using AES-GCM // with HKDF as key derivation function. // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/aes_gcm_hkdf_streaming.proto package aes_gcm_hkdf_streaming_go_proto import ( common_go_proto "github.com/google/tink/go/proto/common_go_proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type AesGcmHkdfStreamingParams struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields CiphertextSegmentSize uint32 `protobuf:"varint,1,opt,name=ciphertext_segment_size,json=ciphertextSegmentSize,proto3" json:"ciphertext_segment_size,omitempty"` DerivedKeySize uint32 `protobuf:"varint,2,opt,name=derived_key_size,json=derivedKeySize,proto3" json:"derived_key_size,omitempty"` // size of AES-GCM keys derived for each segment HkdfHashType common_go_proto.HashType `protobuf:"varint,3,opt,name=hkdf_hash_type,json=hkdfHashType,proto3,enum=google.crypto.tink.HashType" json:"hkdf_hash_type,omitempty"` } func (x *AesGcmHkdfStreamingParams) Reset() { *x = AesGcmHkdfStreamingParams{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AesGcmHkdfStreamingParams) String() string { return protoimpl.X.MessageStringOf(x) } func (*AesGcmHkdfStreamingParams) ProtoMessage() {} func (x *AesGcmHkdfStreamingParams) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AesGcmHkdfStreamingParams.ProtoReflect.Descriptor instead. func (*AesGcmHkdfStreamingParams) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_rawDescGZIP(), []int{0} } func (x *AesGcmHkdfStreamingParams) GetCiphertextSegmentSize() uint32 { if x != nil { return x.CiphertextSegmentSize } return 0 } func (x *AesGcmHkdfStreamingParams) GetDerivedKeySize() uint32 { if x != nil { return x.DerivedKeySize } return 0 } func (x *AesGcmHkdfStreamingParams) GetHkdfHashType() common_go_proto.HashType { if x != nil { return x.HkdfHashType } return common_go_proto.HashType(0) } type AesGcmHkdfStreamingKeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,3,opt,name=version,proto3" json:"version,omitempty"` Params *AesGcmHkdfStreamingParams `protobuf:"bytes,1,opt,name=params,proto3" json:"params,omitempty"` KeySize uint32 `protobuf:"varint,2,opt,name=key_size,json=keySize,proto3" json:"key_size,omitempty"` // size of the main key (aka. "ikm", input key material) } func (x *AesGcmHkdfStreamingKeyFormat) Reset() { *x = AesGcmHkdfStreamingKeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AesGcmHkdfStreamingKeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*AesGcmHkdfStreamingKeyFormat) ProtoMessage() {} func (x *AesGcmHkdfStreamingKeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AesGcmHkdfStreamingKeyFormat.ProtoReflect.Descriptor instead. func (*AesGcmHkdfStreamingKeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_rawDescGZIP(), []int{1} } func (x *AesGcmHkdfStreamingKeyFormat) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *AesGcmHkdfStreamingKeyFormat) GetParams() *AesGcmHkdfStreamingParams { if x != nil { return x.Params } return nil } func (x *AesGcmHkdfStreamingKeyFormat) GetKeySize() uint32 { if x != nil { return x.KeySize } return 0 } // key_type: type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey type AesGcmHkdfStreamingKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` Params *AesGcmHkdfStreamingParams `protobuf:"bytes,2,opt,name=params,proto3" json:"params,omitempty"` KeyValue []byte `protobuf:"bytes,3,opt,name=key_value,json=keyValue,proto3" json:"key_value,omitempty"` } func (x *AesGcmHkdfStreamingKey) Reset() { *x = AesGcmHkdfStreamingKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AesGcmHkdfStreamingKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*AesGcmHkdfStreamingKey) ProtoMessage() {} func (x *AesGcmHkdfStreamingKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AesGcmHkdfStreamingKey.ProtoReflect.Descriptor instead. func (*AesGcmHkdfStreamingKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_rawDescGZIP(), []int{2} } func (x *AesGcmHkdfStreamingKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *AesGcmHkdfStreamingKey) GetParams() *AesGcmHkdfStreamingParams { if x != nil { return x.Params } return nil } func (x *AesGcmHkdfStreamingKey) GetKeyValue() []byte { if x != nil { return x.KeyValue } return nil } var File_third_party_tink_proto_aes_gcm_hkdf_streaming_proto protoreflect.FileDescriptor var file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_rawDesc = []byte{ 0x0a, 0x33, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x65, 0x73, 0x5f, 0x67, 0x63, 0x6d, 0x5f, 0x68, 0x6b, 0x64, 0x66, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x1a, 0x23, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc1, 0x01, 0x0a, 0x19, 0x41, 0x65, 0x73, 0x47, 0x63, 0x6d, 0x48, 0x6b, 0x64, 0x66, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x36, 0x0a, 0x17, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x15, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x64, 0x65, 0x72, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x64, 0x65, 0x72, 0x69, 0x76, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x42, 0x0a, 0x0e, 0x68, 0x6b, 0x64, 0x66, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0c, 0x68, 0x6b, 0x64, 0x66, 0x48, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x22, 0x9a, 0x01, 0x0a, 0x1c, 0x41, 0x65, 0x73, 0x47, 0x63, 0x6d, 0x48, 0x6b, 0x64, 0x66, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x41, 0x65, 0x73, 0x47, 0x63, 0x6d, 0x48, 0x6b, 0x64, 0x66, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x96, 0x01, 0x0a, 0x16, 0x41, 0x65, 0x73, 0x47, 0x63, 0x6d, 0x48, 0x6b, 0x64, 0x66, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x41, 0x65, 0x73, 0x47, 0x63, 0x6d, 0x48, 0x6b, 0x64, 0x66, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x61, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x65, 0x73, 0x5f, 0x67, 0x63, 0x6d, 0x5f, 0x68, 0x6b, 0x64, 0x66, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_rawDescOnce sync.Once file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_rawDescData = file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_rawDesc ) func file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_rawDescGZIP() []byte { file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_rawDescData) }) return file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_rawDescData } var file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_goTypes = []interface{}{ (*AesGcmHkdfStreamingParams)(nil), // 0: google.crypto.tink.AesGcmHkdfStreamingParams (*AesGcmHkdfStreamingKeyFormat)(nil), // 1: google.crypto.tink.AesGcmHkdfStreamingKeyFormat (*AesGcmHkdfStreamingKey)(nil), // 2: google.crypto.tink.AesGcmHkdfStreamingKey (common_go_proto.HashType)(0), // 3: google.crypto.tink.HashType } var file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_depIdxs = []int32{ 3, // 0: google.crypto.tink.AesGcmHkdfStreamingParams.hkdf_hash_type:type_name -> google.crypto.tink.HashType 0, // 1: google.crypto.tink.AesGcmHkdfStreamingKeyFormat.params:type_name -> google.crypto.tink.AesGcmHkdfStreamingParams 0, // 2: google.crypto.tink.AesGcmHkdfStreamingKey.params:type_name -> google.crypto.tink.AesGcmHkdfStreamingParams 3, // [3:3] is the sub-list for method output_type 3, // [3:3] is the sub-list for method input_type 3, // [3:3] is the sub-list for extension type_name 3, // [3:3] is the sub-list for extension extendee 0, // [0:3] is the sub-list for field type_name } func init() { file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_init() } func file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_init() { if File_third_party_tink_proto_aes_gcm_hkdf_streaming_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AesGcmHkdfStreamingParams); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AesGcmHkdfStreamingKeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AesGcmHkdfStreamingKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_rawDesc, NumEnums: 0, NumMessages: 3, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_depIdxs, MessageInfos: file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_msgTypes, }.Build() File_third_party_tink_proto_aes_gcm_hkdf_streaming_proto = out.File file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_rawDesc = nil file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_goTypes = nil file_third_party_tink_proto_aes_gcm_hkdf_streaming_proto_depIdxs = nil } ================================================ FILE: go/proto/aes_gcm_siv_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "aes_gcm_siv_go_proto", srcs = ["aes_gcm_siv.pb.go"], importpath = "github.com/google/tink/go/proto/aes_gcm_siv_go_proto", visibility = ["//visibility:public"], deps = [ "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":aes_gcm_siv_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/aes_gcm_siv_go_proto/aes_gcm_siv.pb.go ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/aes_gcm_siv.proto package aes_gcm_siv_go_proto import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) // The only allowed IV size is 12 bytes and tag size is 16 bytes. // Thus, accept no params. type AesGcmSivKeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields KeySize uint32 `protobuf:"varint,2,opt,name=key_size,json=keySize,proto3" json:"key_size,omitempty"` Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` } func (x *AesGcmSivKeyFormat) Reset() { *x = AesGcmSivKeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_aes_gcm_siv_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AesGcmSivKeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*AesGcmSivKeyFormat) ProtoMessage() {} func (x *AesGcmSivKeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_aes_gcm_siv_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AesGcmSivKeyFormat.ProtoReflect.Descriptor instead. func (*AesGcmSivKeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_aes_gcm_siv_proto_rawDescGZIP(), []int{0} } func (x *AesGcmSivKeyFormat) GetKeySize() uint32 { if x != nil { return x.KeySize } return 0 } func (x *AesGcmSivKeyFormat) GetVersion() uint32 { if x != nil { return x.Version } return 0 } // key_type: type.googleapis.com/google.crypto.tink.AesGcmSivKey type AesGcmSivKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` KeyValue []byte `protobuf:"bytes,3,opt,name=key_value,json=keyValue,proto3" json:"key_value,omitempty"` } func (x *AesGcmSivKey) Reset() { *x = AesGcmSivKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_aes_gcm_siv_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AesGcmSivKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*AesGcmSivKey) ProtoMessage() {} func (x *AesGcmSivKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_aes_gcm_siv_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AesGcmSivKey.ProtoReflect.Descriptor instead. func (*AesGcmSivKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_aes_gcm_siv_proto_rawDescGZIP(), []int{1} } func (x *AesGcmSivKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *AesGcmSivKey) GetKeyValue() []byte { if x != nil { return x.KeyValue } return nil } var File_third_party_tink_proto_aes_gcm_siv_proto protoreflect.FileDescriptor var file_third_party_tink_proto_aes_gcm_siv_proto_rawDesc = []byte{ 0x0a, 0x28, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x65, 0x73, 0x5f, 0x67, 0x63, 0x6d, 0x5f, 0x73, 0x69, 0x76, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x22, 0x49, 0x0a, 0x12, 0x41, 0x65, 0x73, 0x47, 0x63, 0x6d, 0x53, 0x69, 0x76, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x45, 0x0a, 0x0c, 0x41, 0x65, 0x73, 0x47, 0x63, 0x6d, 0x53, 0x69, 0x76, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x56, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x65, 0x73, 0x5f, 0x67, 0x63, 0x6d, 0x5f, 0x73, 0x69, 0x76, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_aes_gcm_siv_proto_rawDescOnce sync.Once file_third_party_tink_proto_aes_gcm_siv_proto_rawDescData = file_third_party_tink_proto_aes_gcm_siv_proto_rawDesc ) func file_third_party_tink_proto_aes_gcm_siv_proto_rawDescGZIP() []byte { file_third_party_tink_proto_aes_gcm_siv_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_aes_gcm_siv_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_aes_gcm_siv_proto_rawDescData) }) return file_third_party_tink_proto_aes_gcm_siv_proto_rawDescData } var file_third_party_tink_proto_aes_gcm_siv_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_third_party_tink_proto_aes_gcm_siv_proto_goTypes = []interface{}{ (*AesGcmSivKeyFormat)(nil), // 0: google.crypto.tink.AesGcmSivKeyFormat (*AesGcmSivKey)(nil), // 1: google.crypto.tink.AesGcmSivKey } var file_third_party_tink_proto_aes_gcm_siv_proto_depIdxs = []int32{ 0, // [0:0] is the sub-list for method output_type 0, // [0:0] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name } func init() { file_third_party_tink_proto_aes_gcm_siv_proto_init() } func file_third_party_tink_proto_aes_gcm_siv_proto_init() { if File_third_party_tink_proto_aes_gcm_siv_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_aes_gcm_siv_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AesGcmSivKeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_aes_gcm_siv_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AesGcmSivKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_aes_gcm_siv_proto_rawDesc, NumEnums: 0, NumMessages: 2, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_aes_gcm_siv_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_aes_gcm_siv_proto_depIdxs, MessageInfos: file_third_party_tink_proto_aes_gcm_siv_proto_msgTypes, }.Build() File_third_party_tink_proto_aes_gcm_siv_proto = out.File file_third_party_tink_proto_aes_gcm_siv_proto_rawDesc = nil file_third_party_tink_proto_aes_gcm_siv_proto_goTypes = nil file_third_party_tink_proto_aes_gcm_siv_proto_depIdxs = nil } ================================================ FILE: go/proto/aes_siv_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "aes_siv_go_proto", srcs = ["aes_siv.pb.go"], importpath = "github.com/google/tink/go/proto/aes_siv_go_proto", visibility = ["//visibility:public"], deps = [ "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":aes_siv_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/aes_siv_go_proto/aes_siv.pb.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/aes_siv.proto package aes_siv_go_proto import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type AesSivKeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Only valid value is: 64. KeySize uint32 `protobuf:"varint,1,opt,name=key_size,json=keySize,proto3" json:"key_size,omitempty"` Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` } func (x *AesSivKeyFormat) Reset() { *x = AesSivKeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_aes_siv_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AesSivKeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*AesSivKeyFormat) ProtoMessage() {} func (x *AesSivKeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_aes_siv_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AesSivKeyFormat.ProtoReflect.Descriptor instead. func (*AesSivKeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_aes_siv_proto_rawDescGZIP(), []int{0} } func (x *AesSivKeyFormat) GetKeySize() uint32 { if x != nil { return x.KeySize } return 0 } func (x *AesSivKeyFormat) GetVersion() uint32 { if x != nil { return x.Version } return 0 } // key_type: type.googleapis.com/google.crypto.tink.AesSivKey type AesSivKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` // First half is AES-CTR key, second is AES-SIV. KeyValue []byte `protobuf:"bytes,2,opt,name=key_value,json=keyValue,proto3" json:"key_value,omitempty"` } func (x *AesSivKey) Reset() { *x = AesSivKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_aes_siv_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AesSivKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*AesSivKey) ProtoMessage() {} func (x *AesSivKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_aes_siv_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AesSivKey.ProtoReflect.Descriptor instead. func (*AesSivKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_aes_siv_proto_rawDescGZIP(), []int{1} } func (x *AesSivKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *AesSivKey) GetKeyValue() []byte { if x != nil { return x.KeyValue } return nil } var File_third_party_tink_proto_aes_siv_proto protoreflect.FileDescriptor var file_third_party_tink_proto_aes_siv_proto_rawDesc = []byte{ 0x0a, 0x24, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x65, 0x73, 0x5f, 0x73, 0x69, 0x76, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x22, 0x46, 0x0a, 0x0f, 0x41, 0x65, 0x73, 0x53, 0x69, 0x76, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x42, 0x0a, 0x09, 0x41, 0x65, 0x73, 0x53, 0x69, 0x76, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x52, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x65, 0x73, 0x5f, 0x73, 0x69, 0x76, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_aes_siv_proto_rawDescOnce sync.Once file_third_party_tink_proto_aes_siv_proto_rawDescData = file_third_party_tink_proto_aes_siv_proto_rawDesc ) func file_third_party_tink_proto_aes_siv_proto_rawDescGZIP() []byte { file_third_party_tink_proto_aes_siv_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_aes_siv_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_aes_siv_proto_rawDescData) }) return file_third_party_tink_proto_aes_siv_proto_rawDescData } var file_third_party_tink_proto_aes_siv_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_third_party_tink_proto_aes_siv_proto_goTypes = []interface{}{ (*AesSivKeyFormat)(nil), // 0: google.crypto.tink.AesSivKeyFormat (*AesSivKey)(nil), // 1: google.crypto.tink.AesSivKey } var file_third_party_tink_proto_aes_siv_proto_depIdxs = []int32{ 0, // [0:0] is the sub-list for method output_type 0, // [0:0] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name } func init() { file_third_party_tink_proto_aes_siv_proto_init() } func file_third_party_tink_proto_aes_siv_proto_init() { if File_third_party_tink_proto_aes_siv_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_aes_siv_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AesSivKeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_aes_siv_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AesSivKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_aes_siv_proto_rawDesc, NumEnums: 0, NumMessages: 2, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_aes_siv_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_aes_siv_proto_depIdxs, MessageInfos: file_third_party_tink_proto_aes_siv_proto_msgTypes, }.Build() File_third_party_tink_proto_aes_siv_proto = out.File file_third_party_tink_proto_aes_siv_proto_rawDesc = nil file_third_party_tink_proto_aes_siv_proto_goTypes = nil file_third_party_tink_proto_aes_siv_proto_depIdxs = nil } ================================================ FILE: go/proto/chacha20_poly1305_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "chacha20_poly1305_go_proto", srcs = ["chacha20_poly1305.pb.go"], importpath = "github.com/google/tink/go/proto/chacha20_poly1305_go_proto", visibility = ["//visibility:public"], deps = [ "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":chacha20_poly1305_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/chacha20_poly1305_go_proto/chacha20_poly1305.pb.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/chacha20_poly1305.proto package chacha20_poly1305_go_proto import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type ChaCha20Poly1305KeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields } func (x *ChaCha20Poly1305KeyFormat) Reset() { *x = ChaCha20Poly1305KeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_chacha20_poly1305_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ChaCha20Poly1305KeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*ChaCha20Poly1305KeyFormat) ProtoMessage() {} func (x *ChaCha20Poly1305KeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_chacha20_poly1305_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use ChaCha20Poly1305KeyFormat.ProtoReflect.Descriptor instead. func (*ChaCha20Poly1305KeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_chacha20_poly1305_proto_rawDescGZIP(), []int{0} } // key_type: type.googleapis.com/google.crypto.tink.ChaCha20Poly1305. // This key type actually implements ChaCha20Poly1305 as described // at https://tools.ietf.org/html/rfc7539#section-2.8. type ChaCha20Poly1305Key struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` KeyValue []byte `protobuf:"bytes,2,opt,name=key_value,json=keyValue,proto3" json:"key_value,omitempty"` } func (x *ChaCha20Poly1305Key) Reset() { *x = ChaCha20Poly1305Key{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_chacha20_poly1305_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ChaCha20Poly1305Key) String() string { return protoimpl.X.MessageStringOf(x) } func (*ChaCha20Poly1305Key) ProtoMessage() {} func (x *ChaCha20Poly1305Key) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_chacha20_poly1305_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use ChaCha20Poly1305Key.ProtoReflect.Descriptor instead. func (*ChaCha20Poly1305Key) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_chacha20_poly1305_proto_rawDescGZIP(), []int{1} } func (x *ChaCha20Poly1305Key) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *ChaCha20Poly1305Key) GetKeyValue() []byte { if x != nil { return x.KeyValue } return nil } var File_third_party_tink_proto_chacha20_poly1305_proto protoreflect.FileDescriptor var file_third_party_tink_proto_chacha20_poly1305_proto_rawDesc = []byte{ 0x0a, 0x2e, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x68, 0x61, 0x63, 0x68, 0x61, 0x32, 0x30, 0x5f, 0x70, 0x6f, 0x6c, 0x79, 0x31, 0x33, 0x30, 0x35, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x22, 0x1b, 0x0a, 0x19, 0x43, 0x68, 0x61, 0x43, 0x68, 0x61, 0x32, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x31, 0x33, 0x30, 0x35, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, 0x4c, 0x0a, 0x13, 0x43, 0x68, 0x61, 0x43, 0x68, 0x61, 0x32, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x31, 0x33, 0x30, 0x35, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x5c, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x68, 0x61, 0x63, 0x68, 0x61, 0x32, 0x30, 0x5f, 0x70, 0x6f, 0x6c, 0x79, 0x31, 0x33, 0x30, 0x35, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_chacha20_poly1305_proto_rawDescOnce sync.Once file_third_party_tink_proto_chacha20_poly1305_proto_rawDescData = file_third_party_tink_proto_chacha20_poly1305_proto_rawDesc ) func file_third_party_tink_proto_chacha20_poly1305_proto_rawDescGZIP() []byte { file_third_party_tink_proto_chacha20_poly1305_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_chacha20_poly1305_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_chacha20_poly1305_proto_rawDescData) }) return file_third_party_tink_proto_chacha20_poly1305_proto_rawDescData } var file_third_party_tink_proto_chacha20_poly1305_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_third_party_tink_proto_chacha20_poly1305_proto_goTypes = []interface{}{ (*ChaCha20Poly1305KeyFormat)(nil), // 0: google.crypto.tink.ChaCha20Poly1305KeyFormat (*ChaCha20Poly1305Key)(nil), // 1: google.crypto.tink.ChaCha20Poly1305Key } var file_third_party_tink_proto_chacha20_poly1305_proto_depIdxs = []int32{ 0, // [0:0] is the sub-list for method output_type 0, // [0:0] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name } func init() { file_third_party_tink_proto_chacha20_poly1305_proto_init() } func file_third_party_tink_proto_chacha20_poly1305_proto_init() { if File_third_party_tink_proto_chacha20_poly1305_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_chacha20_poly1305_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ChaCha20Poly1305KeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_chacha20_poly1305_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ChaCha20Poly1305Key); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_chacha20_poly1305_proto_rawDesc, NumEnums: 0, NumMessages: 2, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_chacha20_poly1305_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_chacha20_poly1305_proto_depIdxs, MessageInfos: file_third_party_tink_proto_chacha20_poly1305_proto_msgTypes, }.Build() File_third_party_tink_proto_chacha20_poly1305_proto = out.File file_third_party_tink_proto_chacha20_poly1305_proto_rawDesc = nil file_third_party_tink_proto_chacha20_poly1305_proto_goTypes = nil file_third_party_tink_proto_chacha20_poly1305_proto_depIdxs = nil } ================================================ FILE: go/proto/common_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "common_go_proto", srcs = ["common.pb.go"], importpath = "github.com/google/tink/go/proto/common_go_proto", visibility = ["//visibility:public"], deps = [ "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":common_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/common_go_proto/common.pb.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Definitions for common cryptographic enum types. // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/common.proto package common_go_proto import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type EllipticCurveType int32 const ( EllipticCurveType_UNKNOWN_CURVE EllipticCurveType = 0 EllipticCurveType_NIST_P256 EllipticCurveType = 2 EllipticCurveType_NIST_P384 EllipticCurveType = 3 EllipticCurveType_NIST_P521 EllipticCurveType = 4 EllipticCurveType_CURVE25519 EllipticCurveType = 5 ) // Enum value maps for EllipticCurveType. var ( EllipticCurveType_name = map[int32]string{ 0: "UNKNOWN_CURVE", 2: "NIST_P256", 3: "NIST_P384", 4: "NIST_P521", 5: "CURVE25519", } EllipticCurveType_value = map[string]int32{ "UNKNOWN_CURVE": 0, "NIST_P256": 2, "NIST_P384": 3, "NIST_P521": 4, "CURVE25519": 5, } ) func (x EllipticCurveType) Enum() *EllipticCurveType { p := new(EllipticCurveType) *p = x return p } func (x EllipticCurveType) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (EllipticCurveType) Descriptor() protoreflect.EnumDescriptor { return file_third_party_tink_proto_common_proto_enumTypes[0].Descriptor() } func (EllipticCurveType) Type() protoreflect.EnumType { return &file_third_party_tink_proto_common_proto_enumTypes[0] } func (x EllipticCurveType) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use EllipticCurveType.Descriptor instead. func (EllipticCurveType) EnumDescriptor() ([]byte, []int) { return file_third_party_tink_proto_common_proto_rawDescGZIP(), []int{0} } type EcPointFormat int32 const ( EcPointFormat_UNKNOWN_FORMAT EcPointFormat = 0 EcPointFormat_UNCOMPRESSED EcPointFormat = 1 EcPointFormat_COMPRESSED EcPointFormat = 2 // Like UNCOMPRESSED but without the \x04 prefix. Crunchy uses this format. // DO NOT USE unless you are a Crunchy user moving to Tink. EcPointFormat_DO_NOT_USE_CRUNCHY_UNCOMPRESSED EcPointFormat = 3 ) // Enum value maps for EcPointFormat. var ( EcPointFormat_name = map[int32]string{ 0: "UNKNOWN_FORMAT", 1: "UNCOMPRESSED", 2: "COMPRESSED", 3: "DO_NOT_USE_CRUNCHY_UNCOMPRESSED", } EcPointFormat_value = map[string]int32{ "UNKNOWN_FORMAT": 0, "UNCOMPRESSED": 1, "COMPRESSED": 2, "DO_NOT_USE_CRUNCHY_UNCOMPRESSED": 3, } ) func (x EcPointFormat) Enum() *EcPointFormat { p := new(EcPointFormat) *p = x return p } func (x EcPointFormat) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (EcPointFormat) Descriptor() protoreflect.EnumDescriptor { return file_third_party_tink_proto_common_proto_enumTypes[1].Descriptor() } func (EcPointFormat) Type() protoreflect.EnumType { return &file_third_party_tink_proto_common_proto_enumTypes[1] } func (x EcPointFormat) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use EcPointFormat.Descriptor instead. func (EcPointFormat) EnumDescriptor() ([]byte, []int) { return file_third_party_tink_proto_common_proto_rawDescGZIP(), []int{1} } type HashType int32 const ( HashType_UNKNOWN_HASH HashType = 0 HashType_SHA1 HashType = 1 // Using SHA1 for digital signature is deprecated but HMAC-SHA1 is // fine. HashType_SHA384 HashType = 2 HashType_SHA256 HashType = 3 HashType_SHA512 HashType = 4 HashType_SHA224 HashType = 5 ) // Enum value maps for HashType. var ( HashType_name = map[int32]string{ 0: "UNKNOWN_HASH", 1: "SHA1", 2: "SHA384", 3: "SHA256", 4: "SHA512", 5: "SHA224", } HashType_value = map[string]int32{ "UNKNOWN_HASH": 0, "SHA1": 1, "SHA384": 2, "SHA256": 3, "SHA512": 4, "SHA224": 5, } ) func (x HashType) Enum() *HashType { p := new(HashType) *p = x return p } func (x HashType) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (HashType) Descriptor() protoreflect.EnumDescriptor { return file_third_party_tink_proto_common_proto_enumTypes[2].Descriptor() } func (HashType) Type() protoreflect.EnumType { return &file_third_party_tink_proto_common_proto_enumTypes[2] } func (x HashType) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use HashType.Descriptor instead. func (HashType) EnumDescriptor() ([]byte, []int) { return file_third_party_tink_proto_common_proto_rawDescGZIP(), []int{2} } var File_third_party_tink_proto_common_proto protoreflect.FileDescriptor var file_third_party_tink_proto_common_proto_rawDesc = []byte{ 0x0a, 0x23, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2a, 0x63, 0x0a, 0x11, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x43, 0x75, 0x72, 0x76, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x11, 0x0a, 0x0d, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x43, 0x55, 0x52, 0x56, 0x45, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x49, 0x53, 0x54, 0x5f, 0x50, 0x32, 0x35, 0x36, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x49, 0x53, 0x54, 0x5f, 0x50, 0x33, 0x38, 0x34, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x49, 0x53, 0x54, 0x5f, 0x50, 0x35, 0x32, 0x31, 0x10, 0x04, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x55, 0x52, 0x56, 0x45, 0x32, 0x35, 0x35, 0x31, 0x39, 0x10, 0x05, 0x2a, 0x6a, 0x0a, 0x0d, 0x45, 0x63, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x12, 0x0a, 0x0e, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x55, 0x4e, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x45, 0x44, 0x10, 0x02, 0x12, 0x23, 0x0a, 0x1f, 0x44, 0x4f, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x53, 0x45, 0x5f, 0x43, 0x52, 0x55, 0x4e, 0x43, 0x48, 0x59, 0x5f, 0x55, 0x4e, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x45, 0x44, 0x10, 0x03, 0x2a, 0x56, 0x0a, 0x08, 0x48, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x0c, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x48, 0x41, 0x31, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x48, 0x41, 0x33, 0x38, 0x34, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x48, 0x41, 0x35, 0x31, 0x32, 0x10, 0x04, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x48, 0x41, 0x32, 0x32, 0x34, 0x10, 0x05, 0x42, 0x51, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_common_proto_rawDescOnce sync.Once file_third_party_tink_proto_common_proto_rawDescData = file_third_party_tink_proto_common_proto_rawDesc ) func file_third_party_tink_proto_common_proto_rawDescGZIP() []byte { file_third_party_tink_proto_common_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_common_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_common_proto_rawDescData) }) return file_third_party_tink_proto_common_proto_rawDescData } var file_third_party_tink_proto_common_proto_enumTypes = make([]protoimpl.EnumInfo, 3) var file_third_party_tink_proto_common_proto_goTypes = []interface{}{ (EllipticCurveType)(0), // 0: google.crypto.tink.EllipticCurveType (EcPointFormat)(0), // 1: google.crypto.tink.EcPointFormat (HashType)(0), // 2: google.crypto.tink.HashType } var file_third_party_tink_proto_common_proto_depIdxs = []int32{ 0, // [0:0] is the sub-list for method output_type 0, // [0:0] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name } func init() { file_third_party_tink_proto_common_proto_init() } func file_third_party_tink_proto_common_proto_init() { if File_third_party_tink_proto_common_proto != nil { return } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_common_proto_rawDesc, NumEnums: 3, NumMessages: 0, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_common_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_common_proto_depIdxs, EnumInfos: file_third_party_tink_proto_common_proto_enumTypes, }.Build() File_third_party_tink_proto_common_proto = out.File file_third_party_tink_proto_common_proto_rawDesc = nil file_third_party_tink_proto_common_proto_goTypes = nil file_third_party_tink_proto_common_proto_depIdxs = nil } ================================================ FILE: go/proto/ecdsa_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "ecdsa_go_proto", srcs = ["ecdsa.pb.go"], importpath = "github.com/google/tink/go/proto/ecdsa_go_proto", visibility = ["//visibility:public"], deps = [ "//proto/common_go_proto", "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":ecdsa_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/ecdsa_go_proto/ecdsa.pb.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Definitions for Elliptic Curve Digital Signature Algorithm (ECDSA). // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/ecdsa.proto package ecdsa_go_proto import ( common_go_proto "github.com/google/tink/go/proto/common_go_proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type EcdsaSignatureEncoding int32 const ( EcdsaSignatureEncoding_UNKNOWN_ENCODING EcdsaSignatureEncoding = 0 // The signature's format is r || s, where r and s are zero-padded and have // the same size in bytes as the order of the curve. For example, for NIST // P-256 curve, r and s are zero-padded to 32 bytes. EcdsaSignatureEncoding_IEEE_P1363 EcdsaSignatureEncoding = 1 // The signature is encoded using ASN.1 // (https://tools.ietf.org/html/rfc5480#appendix-A): // // ECDSA-Sig-Value :: = SEQUENCE { // r INTEGER, // s INTEGER // } EcdsaSignatureEncoding_DER EcdsaSignatureEncoding = 2 ) // Enum value maps for EcdsaSignatureEncoding. var ( EcdsaSignatureEncoding_name = map[int32]string{ 0: "UNKNOWN_ENCODING", 1: "IEEE_P1363", 2: "DER", } EcdsaSignatureEncoding_value = map[string]int32{ "UNKNOWN_ENCODING": 0, "IEEE_P1363": 1, "DER": 2, } ) func (x EcdsaSignatureEncoding) Enum() *EcdsaSignatureEncoding { p := new(EcdsaSignatureEncoding) *p = x return p } func (x EcdsaSignatureEncoding) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (EcdsaSignatureEncoding) Descriptor() protoreflect.EnumDescriptor { return file_third_party_tink_proto_ecdsa_proto_enumTypes[0].Descriptor() } func (EcdsaSignatureEncoding) Type() protoreflect.EnumType { return &file_third_party_tink_proto_ecdsa_proto_enumTypes[0] } func (x EcdsaSignatureEncoding) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use EcdsaSignatureEncoding.Descriptor instead. func (EcdsaSignatureEncoding) EnumDescriptor() ([]byte, []int) { return file_third_party_tink_proto_ecdsa_proto_rawDescGZIP(), []int{0} } // Protos for Ecdsa. type EcdsaParams struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required. HashType common_go_proto.HashType `protobuf:"varint,1,opt,name=hash_type,json=hashType,proto3,enum=google.crypto.tink.HashType" json:"hash_type,omitempty"` // Required. Curve common_go_proto.EllipticCurveType `protobuf:"varint,2,opt,name=curve,proto3,enum=google.crypto.tink.EllipticCurveType" json:"curve,omitempty"` // Required. Encoding EcdsaSignatureEncoding `protobuf:"varint,3,opt,name=encoding,proto3,enum=google.crypto.tink.EcdsaSignatureEncoding" json:"encoding,omitempty"` } func (x *EcdsaParams) Reset() { *x = EcdsaParams{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_ecdsa_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EcdsaParams) String() string { return protoimpl.X.MessageStringOf(x) } func (*EcdsaParams) ProtoMessage() {} func (x *EcdsaParams) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_ecdsa_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use EcdsaParams.ProtoReflect.Descriptor instead. func (*EcdsaParams) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_ecdsa_proto_rawDescGZIP(), []int{0} } func (x *EcdsaParams) GetHashType() common_go_proto.HashType { if x != nil { return x.HashType } return common_go_proto.HashType(0) } func (x *EcdsaParams) GetCurve() common_go_proto.EllipticCurveType { if x != nil { return x.Curve } return common_go_proto.EllipticCurveType(0) } func (x *EcdsaParams) GetEncoding() EcdsaSignatureEncoding { if x != nil { return x.Encoding } return EcdsaSignatureEncoding_UNKNOWN_ENCODING } // key_type: type.googleapis.com/google.crypto.tink.EcdsaPublicKey type EcdsaPublicKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required. Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` // Required. Params *EcdsaParams `protobuf:"bytes,2,opt,name=params,proto3" json:"params,omitempty"` // Affine coordinates of the public key in bigendian representation. The // public key is a point (x, y) on the curve defined by params.curve. For // ECDH, it is crucial to verify whether the public key point (x, y) is on the // private's key curve. For ECDSA, such verification is a defense in depth. // Required. X []byte `protobuf:"bytes,3,opt,name=x,proto3" json:"x,omitempty"` // Required. Y []byte `protobuf:"bytes,4,opt,name=y,proto3" json:"y,omitempty"` } func (x *EcdsaPublicKey) Reset() { *x = EcdsaPublicKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_ecdsa_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EcdsaPublicKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*EcdsaPublicKey) ProtoMessage() {} func (x *EcdsaPublicKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_ecdsa_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use EcdsaPublicKey.ProtoReflect.Descriptor instead. func (*EcdsaPublicKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_ecdsa_proto_rawDescGZIP(), []int{1} } func (x *EcdsaPublicKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *EcdsaPublicKey) GetParams() *EcdsaParams { if x != nil { return x.Params } return nil } func (x *EcdsaPublicKey) GetX() []byte { if x != nil { return x.X } return nil } func (x *EcdsaPublicKey) GetY() []byte { if x != nil { return x.Y } return nil } // key_type: type.googleapis.com/google.crypto.tink.EcdsaPrivateKey type EcdsaPrivateKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required. Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` // Required. PublicKey *EcdsaPublicKey `protobuf:"bytes,2,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` // Unsigned big integer in bigendian representation. // Required. KeyValue []byte `protobuf:"bytes,3,opt,name=key_value,json=keyValue,proto3" json:"key_value,omitempty"` } func (x *EcdsaPrivateKey) Reset() { *x = EcdsaPrivateKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_ecdsa_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EcdsaPrivateKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*EcdsaPrivateKey) ProtoMessage() {} func (x *EcdsaPrivateKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_ecdsa_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use EcdsaPrivateKey.ProtoReflect.Descriptor instead. func (*EcdsaPrivateKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_ecdsa_proto_rawDescGZIP(), []int{2} } func (x *EcdsaPrivateKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *EcdsaPrivateKey) GetPublicKey() *EcdsaPublicKey { if x != nil { return x.PublicKey } return nil } func (x *EcdsaPrivateKey) GetKeyValue() []byte { if x != nil { return x.KeyValue } return nil } type EcdsaKeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required. Params *EcdsaParams `protobuf:"bytes,2,opt,name=params,proto3" json:"params,omitempty"` Version uint32 `protobuf:"varint,3,opt,name=version,proto3" json:"version,omitempty"` } func (x *EcdsaKeyFormat) Reset() { *x = EcdsaKeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_ecdsa_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EcdsaKeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*EcdsaKeyFormat) ProtoMessage() {} func (x *EcdsaKeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_ecdsa_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use EcdsaKeyFormat.ProtoReflect.Descriptor instead. func (*EcdsaKeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_ecdsa_proto_rawDescGZIP(), []int{3} } func (x *EcdsaKeyFormat) GetParams() *EcdsaParams { if x != nil { return x.Params } return nil } func (x *EcdsaKeyFormat) GetVersion() uint32 { if x != nil { return x.Version } return 0 } var File_third_party_tink_proto_ecdsa_proto protoreflect.FileDescriptor var file_third_party_tink_proto_ecdsa_proto_rawDesc = []byte{ 0x0a, 0x22, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x63, 0x64, 0x73, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x1a, 0x23, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xcd, 0x01, 0x0a, 0x0b, 0x45, 0x63, 0x64, 0x73, 0x61, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x39, 0x0a, 0x09, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x68, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x3b, 0x0a, 0x05, 0x63, 0x75, 0x72, 0x76, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x43, 0x75, 0x72, 0x76, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x05, 0x63, 0x75, 0x72, 0x76, 0x65, 0x12, 0x46, 0x0a, 0x08, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x45, 0x63, 0x64, 0x73, 0x61, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x22, 0x7f, 0x0a, 0x0e, 0x45, 0x63, 0x64, 0x73, 0x61, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x45, 0x63, 0x64, 0x73, 0x61, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x0c, 0x0a, 0x01, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x78, 0x12, 0x0c, 0x0a, 0x01, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x79, 0x22, 0x8b, 0x01, 0x0a, 0x0f, 0x45, 0x63, 0x64, 0x73, 0x61, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x45, 0x63, 0x64, 0x73, 0x61, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x63, 0x0a, 0x0e, 0x45, 0x63, 0x64, 0x73, 0x61, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x37, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x45, 0x63, 0x64, 0x73, 0x61, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2a, 0x47, 0x0a, 0x16, 0x45, 0x63, 0x64, 0x73, 0x61, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x14, 0x0a, 0x10, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x45, 0x4e, 0x43, 0x4f, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x45, 0x45, 0x45, 0x5f, 0x50, 0x31, 0x33, 0x36, 0x33, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x44, 0x45, 0x52, 0x10, 0x02, 0x42, 0x50, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x63, 0x64, 0x73, 0x61, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_ecdsa_proto_rawDescOnce sync.Once file_third_party_tink_proto_ecdsa_proto_rawDescData = file_third_party_tink_proto_ecdsa_proto_rawDesc ) func file_third_party_tink_proto_ecdsa_proto_rawDescGZIP() []byte { file_third_party_tink_proto_ecdsa_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_ecdsa_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_ecdsa_proto_rawDescData) }) return file_third_party_tink_proto_ecdsa_proto_rawDescData } var file_third_party_tink_proto_ecdsa_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_third_party_tink_proto_ecdsa_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_third_party_tink_proto_ecdsa_proto_goTypes = []interface{}{ (EcdsaSignatureEncoding)(0), // 0: google.crypto.tink.EcdsaSignatureEncoding (*EcdsaParams)(nil), // 1: google.crypto.tink.EcdsaParams (*EcdsaPublicKey)(nil), // 2: google.crypto.tink.EcdsaPublicKey (*EcdsaPrivateKey)(nil), // 3: google.crypto.tink.EcdsaPrivateKey (*EcdsaKeyFormat)(nil), // 4: google.crypto.tink.EcdsaKeyFormat (common_go_proto.HashType)(0), // 5: google.crypto.tink.HashType (common_go_proto.EllipticCurveType)(0), // 6: google.crypto.tink.EllipticCurveType } var file_third_party_tink_proto_ecdsa_proto_depIdxs = []int32{ 5, // 0: google.crypto.tink.EcdsaParams.hash_type:type_name -> google.crypto.tink.HashType 6, // 1: google.crypto.tink.EcdsaParams.curve:type_name -> google.crypto.tink.EllipticCurveType 0, // 2: google.crypto.tink.EcdsaParams.encoding:type_name -> google.crypto.tink.EcdsaSignatureEncoding 1, // 3: google.crypto.tink.EcdsaPublicKey.params:type_name -> google.crypto.tink.EcdsaParams 2, // 4: google.crypto.tink.EcdsaPrivateKey.public_key:type_name -> google.crypto.tink.EcdsaPublicKey 1, // 5: google.crypto.tink.EcdsaKeyFormat.params:type_name -> google.crypto.tink.EcdsaParams 6, // [6:6] is the sub-list for method output_type 6, // [6:6] is the sub-list for method input_type 6, // [6:6] is the sub-list for extension type_name 6, // [6:6] is the sub-list for extension extendee 0, // [0:6] is the sub-list for field type_name } func init() { file_third_party_tink_proto_ecdsa_proto_init() } func file_third_party_tink_proto_ecdsa_proto_init() { if File_third_party_tink_proto_ecdsa_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_ecdsa_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EcdsaParams); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_ecdsa_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EcdsaPublicKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_ecdsa_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EcdsaPrivateKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_ecdsa_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EcdsaKeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_ecdsa_proto_rawDesc, NumEnums: 1, NumMessages: 4, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_ecdsa_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_ecdsa_proto_depIdxs, EnumInfos: file_third_party_tink_proto_ecdsa_proto_enumTypes, MessageInfos: file_third_party_tink_proto_ecdsa_proto_msgTypes, }.Build() File_third_party_tink_proto_ecdsa_proto = out.File file_third_party_tink_proto_ecdsa_proto_rawDesc = nil file_third_party_tink_proto_ecdsa_proto_goTypes = nil file_third_party_tink_proto_ecdsa_proto_depIdxs = nil } ================================================ FILE: go/proto/ecies_aead_hkdf_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "ecies_aead_hkdf_go_proto", srcs = ["ecies_aead_hkdf.pb.go"], importpath = "github.com/google/tink/go/proto/ecies_aead_hkdf_go_proto", visibility = ["//visibility:public"], deps = [ "//proto/common_go_proto", "//proto/tink_go_proto", "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":ecies_aead_hkdf_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/ecies_aead_hkdf_go_proto/ecies_aead_hkdf.pb.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Definitions for Elliptic Curve Digital Signature Algorithm (ECDSA). // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/ecies_aead_hkdf.proto package ecies_aead_hkdf_go_proto import ( common_go_proto "github.com/google/tink/go/proto/common_go_proto" tink_go_proto "github.com/google/tink/go/proto/tink_go_proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) // Parameters of KEM (Key Encapsulation Mechanism) type EciesHkdfKemParams struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required. CurveType common_go_proto.EllipticCurveType `protobuf:"varint,1,opt,name=curve_type,json=curveType,proto3,enum=google.crypto.tink.EllipticCurveType" json:"curve_type,omitempty"` // Required. HkdfHashType common_go_proto.HashType `protobuf:"varint,2,opt,name=hkdf_hash_type,json=hkdfHashType,proto3,enum=google.crypto.tink.HashType" json:"hkdf_hash_type,omitempty"` // Optional. HkdfSalt []byte `protobuf:"bytes,11,opt,name=hkdf_salt,json=hkdfSalt,proto3" json:"hkdf_salt,omitempty"` } func (x *EciesHkdfKemParams) Reset() { *x = EciesHkdfKemParams{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_ecies_aead_hkdf_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EciesHkdfKemParams) String() string { return protoimpl.X.MessageStringOf(x) } func (*EciesHkdfKemParams) ProtoMessage() {} func (x *EciesHkdfKemParams) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_ecies_aead_hkdf_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use EciesHkdfKemParams.ProtoReflect.Descriptor instead. func (*EciesHkdfKemParams) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_ecies_aead_hkdf_proto_rawDescGZIP(), []int{0} } func (x *EciesHkdfKemParams) GetCurveType() common_go_proto.EllipticCurveType { if x != nil { return x.CurveType } return common_go_proto.EllipticCurveType(0) } func (x *EciesHkdfKemParams) GetHkdfHashType() common_go_proto.HashType { if x != nil { return x.HkdfHashType } return common_go_proto.HashType(0) } func (x *EciesHkdfKemParams) GetHkdfSalt() []byte { if x != nil { return x.HkdfSalt } return nil } // Parameters of AEAD DEM (Data Encapsulation Mechanism). type EciesAeadDemParams struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required. // Contains an Aead or DeterministicAead key format (e.g: // AesCtrHmacAeadKeyFormat, AesGcmKeyFormat or AesSivKeyFormat). AeadDem *tink_go_proto.KeyTemplate `protobuf:"bytes,2,opt,name=aead_dem,json=aeadDem,proto3" json:"aead_dem,omitempty"` } func (x *EciesAeadDemParams) Reset() { *x = EciesAeadDemParams{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_ecies_aead_hkdf_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EciesAeadDemParams) String() string { return protoimpl.X.MessageStringOf(x) } func (*EciesAeadDemParams) ProtoMessage() {} func (x *EciesAeadDemParams) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_ecies_aead_hkdf_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use EciesAeadDemParams.ProtoReflect.Descriptor instead. func (*EciesAeadDemParams) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_ecies_aead_hkdf_proto_rawDescGZIP(), []int{1} } func (x *EciesAeadDemParams) GetAeadDem() *tink_go_proto.KeyTemplate { if x != nil { return x.AeadDem } return nil } type EciesAeadHkdfParams struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Key Encapsulation Mechanism. // Required. KemParams *EciesHkdfKemParams `protobuf:"bytes,1,opt,name=kem_params,json=kemParams,proto3" json:"kem_params,omitempty"` // Data Encapsulation Mechanism. // Required. DemParams *EciesAeadDemParams `protobuf:"bytes,2,opt,name=dem_params,json=demParams,proto3" json:"dem_params,omitempty"` // EC point format. // Required. EcPointFormat common_go_proto.EcPointFormat `protobuf:"varint,3,opt,name=ec_point_format,json=ecPointFormat,proto3,enum=google.crypto.tink.EcPointFormat" json:"ec_point_format,omitempty"` } func (x *EciesAeadHkdfParams) Reset() { *x = EciesAeadHkdfParams{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_ecies_aead_hkdf_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EciesAeadHkdfParams) String() string { return protoimpl.X.MessageStringOf(x) } func (*EciesAeadHkdfParams) ProtoMessage() {} func (x *EciesAeadHkdfParams) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_ecies_aead_hkdf_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use EciesAeadHkdfParams.ProtoReflect.Descriptor instead. func (*EciesAeadHkdfParams) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_ecies_aead_hkdf_proto_rawDescGZIP(), []int{2} } func (x *EciesAeadHkdfParams) GetKemParams() *EciesHkdfKemParams { if x != nil { return x.KemParams } return nil } func (x *EciesAeadHkdfParams) GetDemParams() *EciesAeadDemParams { if x != nil { return x.DemParams } return nil } func (x *EciesAeadHkdfParams) GetEcPointFormat() common_go_proto.EcPointFormat { if x != nil { return x.EcPointFormat } return common_go_proto.EcPointFormat(0) } // EciesAeadHkdfPublicKey represents HybridEncryption primitive. // key_type: type.googleapis.com/google.crypto.tink.EciesAeadHkdfPublicKey type EciesAeadHkdfPublicKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required. Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` // Required. Params *EciesAeadHkdfParams `protobuf:"bytes,2,opt,name=params,proto3" json:"params,omitempty"` // Affine coordinates of the public key in bigendian representation. // The public key is a point (x, y) on the curve defined by // params.kem_params.curve. Required. X []byte `protobuf:"bytes,3,opt,name=x,proto3" json:"x,omitempty"` // Required. Y []byte `protobuf:"bytes,4,opt,name=y,proto3" json:"y,omitempty"` } func (x *EciesAeadHkdfPublicKey) Reset() { *x = EciesAeadHkdfPublicKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_ecies_aead_hkdf_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EciesAeadHkdfPublicKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*EciesAeadHkdfPublicKey) ProtoMessage() {} func (x *EciesAeadHkdfPublicKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_ecies_aead_hkdf_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use EciesAeadHkdfPublicKey.ProtoReflect.Descriptor instead. func (*EciesAeadHkdfPublicKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_ecies_aead_hkdf_proto_rawDescGZIP(), []int{3} } func (x *EciesAeadHkdfPublicKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *EciesAeadHkdfPublicKey) GetParams() *EciesAeadHkdfParams { if x != nil { return x.Params } return nil } func (x *EciesAeadHkdfPublicKey) GetX() []byte { if x != nil { return x.X } return nil } func (x *EciesAeadHkdfPublicKey) GetY() []byte { if x != nil { return x.Y } return nil } // EciesKdfAeadPrivateKey represents HybridDecryption primitive. // key_type: type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey type EciesAeadHkdfPrivateKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required. Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` // Required. PublicKey *EciesAeadHkdfPublicKey `protobuf:"bytes,2,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` // Required. KeyValue []byte `protobuf:"bytes,3,opt,name=key_value,json=keyValue,proto3" json:"key_value,omitempty"` // Big integer in bigendian representation. } func (x *EciesAeadHkdfPrivateKey) Reset() { *x = EciesAeadHkdfPrivateKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_ecies_aead_hkdf_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EciesAeadHkdfPrivateKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*EciesAeadHkdfPrivateKey) ProtoMessage() {} func (x *EciesAeadHkdfPrivateKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_ecies_aead_hkdf_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use EciesAeadHkdfPrivateKey.ProtoReflect.Descriptor instead. func (*EciesAeadHkdfPrivateKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_ecies_aead_hkdf_proto_rawDescGZIP(), []int{4} } func (x *EciesAeadHkdfPrivateKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *EciesAeadHkdfPrivateKey) GetPublicKey() *EciesAeadHkdfPublicKey { if x != nil { return x.PublicKey } return nil } func (x *EciesAeadHkdfPrivateKey) GetKeyValue() []byte { if x != nil { return x.KeyValue } return nil } type EciesAeadHkdfKeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required. Params *EciesAeadHkdfParams `protobuf:"bytes,1,opt,name=params,proto3" json:"params,omitempty"` } func (x *EciesAeadHkdfKeyFormat) Reset() { *x = EciesAeadHkdfKeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_ecies_aead_hkdf_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EciesAeadHkdfKeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*EciesAeadHkdfKeyFormat) ProtoMessage() {} func (x *EciesAeadHkdfKeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_ecies_aead_hkdf_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use EciesAeadHkdfKeyFormat.ProtoReflect.Descriptor instead. func (*EciesAeadHkdfKeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_ecies_aead_hkdf_proto_rawDescGZIP(), []int{5} } func (x *EciesAeadHkdfKeyFormat) GetParams() *EciesAeadHkdfParams { if x != nil { return x.Params } return nil } var File_third_party_tink_proto_ecies_aead_hkdf_proto protoreflect.FileDescriptor var file_third_party_tink_proto_ecies_aead_hkdf_proto_rawDesc = []byte{ 0x0a, 0x2c, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x63, 0x69, 0x65, 0x73, 0x5f, 0x61, 0x65, 0x61, 0x64, 0x5f, 0x68, 0x6b, 0x64, 0x66, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x1a, 0x23, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbb, 0x01, 0x0a, 0x12, 0x45, 0x63, 0x69, 0x65, 0x73, 0x48, 0x6b, 0x64, 0x66, 0x4b, 0x65, 0x6d, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x44, 0x0a, 0x0a, 0x63, 0x75, 0x72, 0x76, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x43, 0x75, 0x72, 0x76, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x09, 0x63, 0x75, 0x72, 0x76, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x42, 0x0a, 0x0e, 0x68, 0x6b, 0x64, 0x66, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0c, 0x68, 0x6b, 0x64, 0x66, 0x48, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x68, 0x6b, 0x64, 0x66, 0x5f, 0x73, 0x61, 0x6c, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x68, 0x6b, 0x64, 0x66, 0x53, 0x61, 0x6c, 0x74, 0x22, 0x50, 0x0a, 0x12, 0x45, 0x63, 0x69, 0x65, 0x73, 0x41, 0x65, 0x61, 0x64, 0x44, 0x65, 0x6d, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x3a, 0x0a, 0x08, 0x61, 0x65, 0x61, 0x64, 0x5f, 0x64, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4b, 0x65, 0x79, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x07, 0x61, 0x65, 0x61, 0x64, 0x44, 0x65, 0x6d, 0x22, 0xee, 0x01, 0x0a, 0x13, 0x45, 0x63, 0x69, 0x65, 0x73, 0x41, 0x65, 0x61, 0x64, 0x48, 0x6b, 0x64, 0x66, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x45, 0x0a, 0x0a, 0x6b, 0x65, 0x6d, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x45, 0x63, 0x69, 0x65, 0x73, 0x48, 0x6b, 0x64, 0x66, 0x4b, 0x65, 0x6d, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x09, 0x6b, 0x65, 0x6d, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x45, 0x0a, 0x0a, 0x64, 0x65, 0x6d, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x45, 0x63, 0x69, 0x65, 0x73, 0x41, 0x65, 0x61, 0x64, 0x44, 0x65, 0x6d, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x09, 0x64, 0x65, 0x6d, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x49, 0x0a, 0x0f, 0x65, 0x63, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x45, 0x63, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x0d, 0x65, 0x63, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, 0x8f, 0x01, 0x0a, 0x16, 0x45, 0x63, 0x69, 0x65, 0x73, 0x41, 0x65, 0x61, 0x64, 0x48, 0x6b, 0x64, 0x66, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x45, 0x63, 0x69, 0x65, 0x73, 0x41, 0x65, 0x61, 0x64, 0x48, 0x6b, 0x64, 0x66, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x0c, 0x0a, 0x01, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x78, 0x12, 0x0c, 0x0a, 0x01, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x79, 0x22, 0x9b, 0x01, 0x0a, 0x17, 0x45, 0x63, 0x69, 0x65, 0x73, 0x41, 0x65, 0x61, 0x64, 0x48, 0x6b, 0x64, 0x66, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x49, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x45, 0x63, 0x69, 0x65, 0x73, 0x41, 0x65, 0x61, 0x64, 0x48, 0x6b, 0x64, 0x66, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x59, 0x0a, 0x16, 0x45, 0x63, 0x69, 0x65, 0x73, 0x41, 0x65, 0x61, 0x64, 0x48, 0x6b, 0x64, 0x66, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x3f, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x45, 0x63, 0x69, 0x65, 0x73, 0x41, 0x65, 0x61, 0x64, 0x48, 0x6b, 0x64, 0x66, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0x5a, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x38, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x63, 0x69, 0x65, 0x73, 0x5f, 0x61, 0x65, 0x61, 0x64, 0x5f, 0x68, 0x6b, 0x64, 0x66, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_ecies_aead_hkdf_proto_rawDescOnce sync.Once file_third_party_tink_proto_ecies_aead_hkdf_proto_rawDescData = file_third_party_tink_proto_ecies_aead_hkdf_proto_rawDesc ) func file_third_party_tink_proto_ecies_aead_hkdf_proto_rawDescGZIP() []byte { file_third_party_tink_proto_ecies_aead_hkdf_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_ecies_aead_hkdf_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_ecies_aead_hkdf_proto_rawDescData) }) return file_third_party_tink_proto_ecies_aead_hkdf_proto_rawDescData } var file_third_party_tink_proto_ecies_aead_hkdf_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_third_party_tink_proto_ecies_aead_hkdf_proto_goTypes = []interface{}{ (*EciesHkdfKemParams)(nil), // 0: google.crypto.tink.EciesHkdfKemParams (*EciesAeadDemParams)(nil), // 1: google.crypto.tink.EciesAeadDemParams (*EciesAeadHkdfParams)(nil), // 2: google.crypto.tink.EciesAeadHkdfParams (*EciesAeadHkdfPublicKey)(nil), // 3: google.crypto.tink.EciesAeadHkdfPublicKey (*EciesAeadHkdfPrivateKey)(nil), // 4: google.crypto.tink.EciesAeadHkdfPrivateKey (*EciesAeadHkdfKeyFormat)(nil), // 5: google.crypto.tink.EciesAeadHkdfKeyFormat (common_go_proto.EllipticCurveType)(0), // 6: google.crypto.tink.EllipticCurveType (common_go_proto.HashType)(0), // 7: google.crypto.tink.HashType (*tink_go_proto.KeyTemplate)(nil), // 8: google.crypto.tink.KeyTemplate (common_go_proto.EcPointFormat)(0), // 9: google.crypto.tink.EcPointFormat } var file_third_party_tink_proto_ecies_aead_hkdf_proto_depIdxs = []int32{ 6, // 0: google.crypto.tink.EciesHkdfKemParams.curve_type:type_name -> google.crypto.tink.EllipticCurveType 7, // 1: google.crypto.tink.EciesHkdfKemParams.hkdf_hash_type:type_name -> google.crypto.tink.HashType 8, // 2: google.crypto.tink.EciesAeadDemParams.aead_dem:type_name -> google.crypto.tink.KeyTemplate 0, // 3: google.crypto.tink.EciesAeadHkdfParams.kem_params:type_name -> google.crypto.tink.EciesHkdfKemParams 1, // 4: google.crypto.tink.EciesAeadHkdfParams.dem_params:type_name -> google.crypto.tink.EciesAeadDemParams 9, // 5: google.crypto.tink.EciesAeadHkdfParams.ec_point_format:type_name -> google.crypto.tink.EcPointFormat 2, // 6: google.crypto.tink.EciesAeadHkdfPublicKey.params:type_name -> google.crypto.tink.EciesAeadHkdfParams 3, // 7: google.crypto.tink.EciesAeadHkdfPrivateKey.public_key:type_name -> google.crypto.tink.EciesAeadHkdfPublicKey 2, // 8: google.crypto.tink.EciesAeadHkdfKeyFormat.params:type_name -> google.crypto.tink.EciesAeadHkdfParams 9, // [9:9] is the sub-list for method output_type 9, // [9:9] is the sub-list for method input_type 9, // [9:9] is the sub-list for extension type_name 9, // [9:9] is the sub-list for extension extendee 0, // [0:9] is the sub-list for field type_name } func init() { file_third_party_tink_proto_ecies_aead_hkdf_proto_init() } func file_third_party_tink_proto_ecies_aead_hkdf_proto_init() { if File_third_party_tink_proto_ecies_aead_hkdf_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_ecies_aead_hkdf_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EciesHkdfKemParams); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_ecies_aead_hkdf_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EciesAeadDemParams); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_ecies_aead_hkdf_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EciesAeadHkdfParams); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_ecies_aead_hkdf_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EciesAeadHkdfPublicKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_ecies_aead_hkdf_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EciesAeadHkdfPrivateKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_ecies_aead_hkdf_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EciesAeadHkdfKeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_ecies_aead_hkdf_proto_rawDesc, NumEnums: 0, NumMessages: 6, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_ecies_aead_hkdf_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_ecies_aead_hkdf_proto_depIdxs, MessageInfos: file_third_party_tink_proto_ecies_aead_hkdf_proto_msgTypes, }.Build() File_third_party_tink_proto_ecies_aead_hkdf_proto = out.File file_third_party_tink_proto_ecies_aead_hkdf_proto_rawDesc = nil file_third_party_tink_proto_ecies_aead_hkdf_proto_goTypes = nil file_third_party_tink_proto_ecies_aead_hkdf_proto_depIdxs = nil } ================================================ FILE: go/proto/ed25519_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "ed25519_go_proto", srcs = ["ed25519.pb.go"], importpath = "github.com/google/tink/go/proto/ed25519_go_proto", visibility = ["//visibility:public"], deps = [ "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":ed25519_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/ed25519_go_proto/ed25519.pb.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Definitions for Ed25519 Digital Signature Algorithm. // See https://ed25519.cr.yp.to/ed25519-20110926.pdf and // https://tools.ietf.org/html/rfc8032. // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/ed25519.proto package ed25519_go_proto import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type Ed25519KeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` } func (x *Ed25519KeyFormat) Reset() { *x = Ed25519KeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_ed25519_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Ed25519KeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*Ed25519KeyFormat) ProtoMessage() {} func (x *Ed25519KeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_ed25519_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use Ed25519KeyFormat.ProtoReflect.Descriptor instead. func (*Ed25519KeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_ed25519_proto_rawDescGZIP(), []int{0} } func (x *Ed25519KeyFormat) GetVersion() uint32 { if x != nil { return x.Version } return 0 } // key_type: type.googleapis.com/google.crypto.tink.Ed25519PublicKey type Ed25519PublicKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required. Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` // The public key is 32 bytes, encoded according to // https://tools.ietf.org/html/rfc8032#section-5.1.2. // Required. KeyValue []byte `protobuf:"bytes,2,opt,name=key_value,json=keyValue,proto3" json:"key_value,omitempty"` } func (x *Ed25519PublicKey) Reset() { *x = Ed25519PublicKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_ed25519_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Ed25519PublicKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*Ed25519PublicKey) ProtoMessage() {} func (x *Ed25519PublicKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_ed25519_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use Ed25519PublicKey.ProtoReflect.Descriptor instead. func (*Ed25519PublicKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_ed25519_proto_rawDescGZIP(), []int{1} } func (x *Ed25519PublicKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *Ed25519PublicKey) GetKeyValue() []byte { if x != nil { return x.KeyValue } return nil } // key_type: type.googleapis.com/google.crypto.tink.Ed25519PrivateKey type Ed25519PrivateKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required. Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` // The private key is 32 bytes of cryptographically secure random data. // See https://tools.ietf.org/html/rfc8032#section-5.1.5. // Required. KeyValue []byte `protobuf:"bytes,2,opt,name=key_value,json=keyValue,proto3" json:"key_value,omitempty"` // The corresponding public key. PublicKey *Ed25519PublicKey `protobuf:"bytes,3,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` } func (x *Ed25519PrivateKey) Reset() { *x = Ed25519PrivateKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_ed25519_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Ed25519PrivateKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*Ed25519PrivateKey) ProtoMessage() {} func (x *Ed25519PrivateKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_ed25519_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use Ed25519PrivateKey.ProtoReflect.Descriptor instead. func (*Ed25519PrivateKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_ed25519_proto_rawDescGZIP(), []int{2} } func (x *Ed25519PrivateKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *Ed25519PrivateKey) GetKeyValue() []byte { if x != nil { return x.KeyValue } return nil } func (x *Ed25519PrivateKey) GetPublicKey() *Ed25519PublicKey { if x != nil { return x.PublicKey } return nil } var File_third_party_tink_proto_ed25519_proto protoreflect.FileDescriptor var file_third_party_tink_proto_ed25519_proto_rawDesc = []byte{ 0x0a, 0x24, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x22, 0x2c, 0x0a, 0x10, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x49, 0x0a, 0x10, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x8f, 0x01, 0x0a, 0x11, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x43, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x52, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_ed25519_proto_rawDescOnce sync.Once file_third_party_tink_proto_ed25519_proto_rawDescData = file_third_party_tink_proto_ed25519_proto_rawDesc ) func file_third_party_tink_proto_ed25519_proto_rawDescGZIP() []byte { file_third_party_tink_proto_ed25519_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_ed25519_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_ed25519_proto_rawDescData) }) return file_third_party_tink_proto_ed25519_proto_rawDescData } var file_third_party_tink_proto_ed25519_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_third_party_tink_proto_ed25519_proto_goTypes = []interface{}{ (*Ed25519KeyFormat)(nil), // 0: google.crypto.tink.Ed25519KeyFormat (*Ed25519PublicKey)(nil), // 1: google.crypto.tink.Ed25519PublicKey (*Ed25519PrivateKey)(nil), // 2: google.crypto.tink.Ed25519PrivateKey } var file_third_party_tink_proto_ed25519_proto_depIdxs = []int32{ 1, // 0: google.crypto.tink.Ed25519PrivateKey.public_key:type_name -> google.crypto.tink.Ed25519PublicKey 1, // [1:1] is the sub-list for method output_type 1, // [1:1] is the sub-list for method input_type 1, // [1:1] is the sub-list for extension type_name 1, // [1:1] is the sub-list for extension extendee 0, // [0:1] is the sub-list for field type_name } func init() { file_third_party_tink_proto_ed25519_proto_init() } func file_third_party_tink_proto_ed25519_proto_init() { if File_third_party_tink_proto_ed25519_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_ed25519_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Ed25519KeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_ed25519_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Ed25519PublicKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_ed25519_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Ed25519PrivateKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_ed25519_proto_rawDesc, NumEnums: 0, NumMessages: 3, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_ed25519_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_ed25519_proto_depIdxs, MessageInfos: file_third_party_tink_proto_ed25519_proto_msgTypes, }.Build() File_third_party_tink_proto_ed25519_proto = out.File file_third_party_tink_proto_ed25519_proto_rawDesc = nil file_third_party_tink_proto_ed25519_proto_goTypes = nil file_third_party_tink_proto_ed25519_proto_depIdxs = nil } ================================================ FILE: go/proto/hkdf_prf_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "hkdf_prf_go_proto", srcs = ["hkdf_prf.pb.go"], importpath = "github.com/google/tink/go/proto/hkdf_prf_go_proto", visibility = ["//visibility:public"], deps = [ "//proto/common_go_proto", "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":hkdf_prf_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/hkdf_prf_go_proto/hkdf_prf.pb.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/hkdf_prf.proto package hkdf_prf_proto import ( common_go_proto "github.com/google/tink/go/proto/common_go_proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type HkdfPrfParams struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Hash common_go_proto.HashType `protobuf:"varint,1,opt,name=hash,proto3,enum=google.crypto.tink.HashType" json:"hash,omitempty"` // Optional. // // An unspecified or zero-length value is equivalent to a sequence of zeros // (0x00) with a length equal to the output size of hash. // // See https://rfc-editor.org/rfc/rfc5869. Salt []byte `protobuf:"bytes,2,opt,name=salt,proto3" json:"salt,omitempty"` } func (x *HkdfPrfParams) Reset() { *x = HkdfPrfParams{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_hkdf_prf_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *HkdfPrfParams) String() string { return protoimpl.X.MessageStringOf(x) } func (*HkdfPrfParams) ProtoMessage() {} func (x *HkdfPrfParams) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_hkdf_prf_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use HkdfPrfParams.ProtoReflect.Descriptor instead. func (*HkdfPrfParams) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_hkdf_prf_proto_rawDescGZIP(), []int{0} } func (x *HkdfPrfParams) GetHash() common_go_proto.HashType { if x != nil { return x.Hash } return common_go_proto.HashType(0) } func (x *HkdfPrfParams) GetSalt() []byte { if x != nil { return x.Salt } return nil } type HkdfPrfKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` Params *HkdfPrfParams `protobuf:"bytes,2,opt,name=params,proto3" json:"params,omitempty"` KeyValue []byte `protobuf:"bytes,3,opt,name=key_value,json=keyValue,proto3" json:"key_value,omitempty"` } func (x *HkdfPrfKey) Reset() { *x = HkdfPrfKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_hkdf_prf_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *HkdfPrfKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*HkdfPrfKey) ProtoMessage() {} func (x *HkdfPrfKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_hkdf_prf_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use HkdfPrfKey.ProtoReflect.Descriptor instead. func (*HkdfPrfKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_hkdf_prf_proto_rawDescGZIP(), []int{1} } func (x *HkdfPrfKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *HkdfPrfKey) GetParams() *HkdfPrfParams { if x != nil { return x.Params } return nil } func (x *HkdfPrfKey) GetKeyValue() []byte { if x != nil { return x.KeyValue } return nil } type HkdfPrfKeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Params *HkdfPrfParams `protobuf:"bytes,1,opt,name=params,proto3" json:"params,omitempty"` KeySize uint32 `protobuf:"varint,2,opt,name=key_size,json=keySize,proto3" json:"key_size,omitempty"` Version uint32 `protobuf:"varint,3,opt,name=version,proto3" json:"version,omitempty"` } func (x *HkdfPrfKeyFormat) Reset() { *x = HkdfPrfKeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_hkdf_prf_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *HkdfPrfKeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*HkdfPrfKeyFormat) ProtoMessage() {} func (x *HkdfPrfKeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_hkdf_prf_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use HkdfPrfKeyFormat.ProtoReflect.Descriptor instead. func (*HkdfPrfKeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_hkdf_prf_proto_rawDescGZIP(), []int{2} } func (x *HkdfPrfKeyFormat) GetParams() *HkdfPrfParams { if x != nil { return x.Params } return nil } func (x *HkdfPrfKeyFormat) GetKeySize() uint32 { if x != nil { return x.KeySize } return 0 } func (x *HkdfPrfKeyFormat) GetVersion() uint32 { if x != nil { return x.Version } return 0 } var File_third_party_tink_proto_hkdf_prf_proto protoreflect.FileDescriptor var file_third_party_tink_proto_hkdf_prf_proto_rawDesc = []byte{ 0x0a, 0x25, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x68, 0x6b, 0x64, 0x66, 0x5f, 0x70, 0x72, 0x66, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x1a, 0x23, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x55, 0x0a, 0x0d, 0x48, 0x6b, 0x64, 0x66, 0x50, 0x72, 0x66, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x30, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x61, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x73, 0x61, 0x6c, 0x74, 0x22, 0x7e, 0x0a, 0x0a, 0x48, 0x6b, 0x64, 0x66, 0x50, 0x72, 0x66, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x6b, 0x64, 0x66, 0x50, 0x72, 0x66, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x82, 0x01, 0x0a, 0x10, 0x48, 0x6b, 0x64, 0x66, 0x50, 0x72, 0x66, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x39, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x6b, 0x64, 0x66, 0x50, 0x72, 0x66, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x50, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x68, 0x6b, 0x64, 0x66, 0x5f, 0x70, 0x72, 0x66, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_hkdf_prf_proto_rawDescOnce sync.Once file_third_party_tink_proto_hkdf_prf_proto_rawDescData = file_third_party_tink_proto_hkdf_prf_proto_rawDesc ) func file_third_party_tink_proto_hkdf_prf_proto_rawDescGZIP() []byte { file_third_party_tink_proto_hkdf_prf_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_hkdf_prf_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_hkdf_prf_proto_rawDescData) }) return file_third_party_tink_proto_hkdf_prf_proto_rawDescData } var file_third_party_tink_proto_hkdf_prf_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_third_party_tink_proto_hkdf_prf_proto_goTypes = []interface{}{ (*HkdfPrfParams)(nil), // 0: google.crypto.tink.HkdfPrfParams (*HkdfPrfKey)(nil), // 1: google.crypto.tink.HkdfPrfKey (*HkdfPrfKeyFormat)(nil), // 2: google.crypto.tink.HkdfPrfKeyFormat (common_go_proto.HashType)(0), // 3: google.crypto.tink.HashType } var file_third_party_tink_proto_hkdf_prf_proto_depIdxs = []int32{ 3, // 0: google.crypto.tink.HkdfPrfParams.hash:type_name -> google.crypto.tink.HashType 0, // 1: google.crypto.tink.HkdfPrfKey.params:type_name -> google.crypto.tink.HkdfPrfParams 0, // 2: google.crypto.tink.HkdfPrfKeyFormat.params:type_name -> google.crypto.tink.HkdfPrfParams 3, // [3:3] is the sub-list for method output_type 3, // [3:3] is the sub-list for method input_type 3, // [3:3] is the sub-list for extension type_name 3, // [3:3] is the sub-list for extension extendee 0, // [0:3] is the sub-list for field type_name } func init() { file_third_party_tink_proto_hkdf_prf_proto_init() } func file_third_party_tink_proto_hkdf_prf_proto_init() { if File_third_party_tink_proto_hkdf_prf_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_hkdf_prf_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HkdfPrfParams); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_hkdf_prf_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HkdfPrfKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_hkdf_prf_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HkdfPrfKeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_hkdf_prf_proto_rawDesc, NumEnums: 0, NumMessages: 3, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_hkdf_prf_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_hkdf_prf_proto_depIdxs, MessageInfos: file_third_party_tink_proto_hkdf_prf_proto_msgTypes, }.Build() File_third_party_tink_proto_hkdf_prf_proto = out.File file_third_party_tink_proto_hkdf_prf_proto_rawDesc = nil file_third_party_tink_proto_hkdf_prf_proto_goTypes = nil file_third_party_tink_proto_hkdf_prf_proto_depIdxs = nil } ================================================ FILE: go/proto/hmac_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "hmac_go_proto", srcs = ["hmac.pb.go"], importpath = "github.com/google/tink/go/proto/hmac_go_proto", visibility = ["//visibility:public"], deps = [ "//proto/common_go_proto", "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":hmac_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/hmac_go_proto/hmac.pb.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/hmac.proto package hmac_go_proto import ( common_go_proto "github.com/google/tink/go/proto/common_go_proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type HmacParams struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Hash common_go_proto.HashType `protobuf:"varint,1,opt,name=hash,proto3,enum=google.crypto.tink.HashType" json:"hash,omitempty"` // HashType is an enum. TagSize uint32 `protobuf:"varint,2,opt,name=tag_size,json=tagSize,proto3" json:"tag_size,omitempty"` } func (x *HmacParams) Reset() { *x = HmacParams{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_hmac_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *HmacParams) String() string { return protoimpl.X.MessageStringOf(x) } func (*HmacParams) ProtoMessage() {} func (x *HmacParams) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_hmac_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use HmacParams.ProtoReflect.Descriptor instead. func (*HmacParams) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_hmac_proto_rawDescGZIP(), []int{0} } func (x *HmacParams) GetHash() common_go_proto.HashType { if x != nil { return x.Hash } return common_go_proto.HashType(0) } func (x *HmacParams) GetTagSize() uint32 { if x != nil { return x.TagSize } return 0 } // key_type: type.googleapis.com/google.crypto.tink.HmacKey type HmacKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` Params *HmacParams `protobuf:"bytes,2,opt,name=params,proto3" json:"params,omitempty"` KeyValue []byte `protobuf:"bytes,3,opt,name=key_value,json=keyValue,proto3" json:"key_value,omitempty"` } func (x *HmacKey) Reset() { *x = HmacKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_hmac_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *HmacKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*HmacKey) ProtoMessage() {} func (x *HmacKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_hmac_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use HmacKey.ProtoReflect.Descriptor instead. func (*HmacKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_hmac_proto_rawDescGZIP(), []int{1} } func (x *HmacKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *HmacKey) GetParams() *HmacParams { if x != nil { return x.Params } return nil } func (x *HmacKey) GetKeyValue() []byte { if x != nil { return x.KeyValue } return nil } type HmacKeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Params *HmacParams `protobuf:"bytes,1,opt,name=params,proto3" json:"params,omitempty"` KeySize uint32 `protobuf:"varint,2,opt,name=key_size,json=keySize,proto3" json:"key_size,omitempty"` Version uint32 `protobuf:"varint,3,opt,name=version,proto3" json:"version,omitempty"` } func (x *HmacKeyFormat) Reset() { *x = HmacKeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_hmac_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *HmacKeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*HmacKeyFormat) ProtoMessage() {} func (x *HmacKeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_hmac_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use HmacKeyFormat.ProtoReflect.Descriptor instead. func (*HmacKeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_hmac_proto_rawDescGZIP(), []int{2} } func (x *HmacKeyFormat) GetParams() *HmacParams { if x != nil { return x.Params } return nil } func (x *HmacKeyFormat) GetKeySize() uint32 { if x != nil { return x.KeySize } return 0 } func (x *HmacKeyFormat) GetVersion() uint32 { if x != nil { return x.Version } return 0 } var File_third_party_tink_proto_hmac_proto protoreflect.FileDescriptor var file_third_party_tink_proto_hmac_proto_rawDesc = []byte{ 0x0a, 0x21, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x68, 0x6d, 0x61, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x1a, 0x23, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x59, 0x0a, 0x0a, 0x48, 0x6d, 0x61, 0x63, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x30, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x61, 0x67, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x74, 0x61, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x78, 0x0a, 0x07, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x6d, 0x61, 0x63, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x7c, 0x0a, 0x0d, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x36, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x6d, 0x61, 0x63, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x4f, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x68, 0x6d, 0x61, 0x63, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_hmac_proto_rawDescOnce sync.Once file_third_party_tink_proto_hmac_proto_rawDescData = file_third_party_tink_proto_hmac_proto_rawDesc ) func file_third_party_tink_proto_hmac_proto_rawDescGZIP() []byte { file_third_party_tink_proto_hmac_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_hmac_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_hmac_proto_rawDescData) }) return file_third_party_tink_proto_hmac_proto_rawDescData } var file_third_party_tink_proto_hmac_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_third_party_tink_proto_hmac_proto_goTypes = []interface{}{ (*HmacParams)(nil), // 0: google.crypto.tink.HmacParams (*HmacKey)(nil), // 1: google.crypto.tink.HmacKey (*HmacKeyFormat)(nil), // 2: google.crypto.tink.HmacKeyFormat (common_go_proto.HashType)(0), // 3: google.crypto.tink.HashType } var file_third_party_tink_proto_hmac_proto_depIdxs = []int32{ 3, // 0: google.crypto.tink.HmacParams.hash:type_name -> google.crypto.tink.HashType 0, // 1: google.crypto.tink.HmacKey.params:type_name -> google.crypto.tink.HmacParams 0, // 2: google.crypto.tink.HmacKeyFormat.params:type_name -> google.crypto.tink.HmacParams 3, // [3:3] is the sub-list for method output_type 3, // [3:3] is the sub-list for method input_type 3, // [3:3] is the sub-list for extension type_name 3, // [3:3] is the sub-list for extension extendee 0, // [0:3] is the sub-list for field type_name } func init() { file_third_party_tink_proto_hmac_proto_init() } func file_third_party_tink_proto_hmac_proto_init() { if File_third_party_tink_proto_hmac_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_hmac_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HmacParams); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_hmac_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HmacKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_hmac_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HmacKeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_hmac_proto_rawDesc, NumEnums: 0, NumMessages: 3, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_hmac_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_hmac_proto_depIdxs, MessageInfos: file_third_party_tink_proto_hmac_proto_msgTypes, }.Build() File_third_party_tink_proto_hmac_proto = out.File file_third_party_tink_proto_hmac_proto_rawDesc = nil file_third_party_tink_proto_hmac_proto_goTypes = nil file_third_party_tink_proto_hmac_proto_depIdxs = nil } ================================================ FILE: go/proto/hmac_prf_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "hmac_prf_go_proto", srcs = ["hmac_prf.pb.go"], importpath = "github.com/google/tink/go/proto/hmac_prf_go_proto", visibility = ["//visibility:public"], deps = [ "//proto/common_go_proto", "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":hmac_prf_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/hmac_prf_go_proto/hmac_prf.pb.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/hmac_prf.proto package hmac_prf_go_proto import ( common_go_proto "github.com/google/tink/go/proto/common_go_proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type HmacPrfParams struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Hash common_go_proto.HashType `protobuf:"varint,1,opt,name=hash,proto3,enum=google.crypto.tink.HashType" json:"hash,omitempty"` // HashType is an enum. } func (x *HmacPrfParams) Reset() { *x = HmacPrfParams{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_hmac_prf_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *HmacPrfParams) String() string { return protoimpl.X.MessageStringOf(x) } func (*HmacPrfParams) ProtoMessage() {} func (x *HmacPrfParams) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_hmac_prf_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use HmacPrfParams.ProtoReflect.Descriptor instead. func (*HmacPrfParams) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_hmac_prf_proto_rawDescGZIP(), []int{0} } func (x *HmacPrfParams) GetHash() common_go_proto.HashType { if x != nil { return x.Hash } return common_go_proto.HashType(0) } // key_type: type.googleapis.com/google.crypto.tink.HmacPrfKey type HmacPrfKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` Params *HmacPrfParams `protobuf:"bytes,2,opt,name=params,proto3" json:"params,omitempty"` KeyValue []byte `protobuf:"bytes,3,opt,name=key_value,json=keyValue,proto3" json:"key_value,omitempty"` } func (x *HmacPrfKey) Reset() { *x = HmacPrfKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_hmac_prf_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *HmacPrfKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*HmacPrfKey) ProtoMessage() {} func (x *HmacPrfKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_hmac_prf_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use HmacPrfKey.ProtoReflect.Descriptor instead. func (*HmacPrfKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_hmac_prf_proto_rawDescGZIP(), []int{1} } func (x *HmacPrfKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *HmacPrfKey) GetParams() *HmacPrfParams { if x != nil { return x.Params } return nil } func (x *HmacPrfKey) GetKeyValue() []byte { if x != nil { return x.KeyValue } return nil } type HmacPrfKeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Params *HmacPrfParams `protobuf:"bytes,1,opt,name=params,proto3" json:"params,omitempty"` KeySize uint32 `protobuf:"varint,2,opt,name=key_size,json=keySize,proto3" json:"key_size,omitempty"` Version uint32 `protobuf:"varint,3,opt,name=version,proto3" json:"version,omitempty"` } func (x *HmacPrfKeyFormat) Reset() { *x = HmacPrfKeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_hmac_prf_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *HmacPrfKeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*HmacPrfKeyFormat) ProtoMessage() {} func (x *HmacPrfKeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_hmac_prf_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use HmacPrfKeyFormat.ProtoReflect.Descriptor instead. func (*HmacPrfKeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_hmac_prf_proto_rawDescGZIP(), []int{2} } func (x *HmacPrfKeyFormat) GetParams() *HmacPrfParams { if x != nil { return x.Params } return nil } func (x *HmacPrfKeyFormat) GetKeySize() uint32 { if x != nil { return x.KeySize } return 0 } func (x *HmacPrfKeyFormat) GetVersion() uint32 { if x != nil { return x.Version } return 0 } var File_third_party_tink_proto_hmac_prf_proto protoreflect.FileDescriptor var file_third_party_tink_proto_hmac_prf_proto_rawDesc = []byte{ 0x0a, 0x25, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x68, 0x6d, 0x61, 0x63, 0x5f, 0x70, 0x72, 0x66, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x1a, 0x23, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x41, 0x0a, 0x0d, 0x48, 0x6d, 0x61, 0x63, 0x50, 0x72, 0x66, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x30, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x22, 0x7e, 0x0a, 0x0a, 0x48, 0x6d, 0x61, 0x63, 0x50, 0x72, 0x66, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x6d, 0x61, 0x63, 0x50, 0x72, 0x66, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x82, 0x01, 0x0a, 0x10, 0x48, 0x6d, 0x61, 0x63, 0x50, 0x72, 0x66, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x39, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x6d, 0x61, 0x63, 0x50, 0x72, 0x66, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x53, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x68, 0x6d, 0x61, 0x63, 0x5f, 0x70, 0x72, 0x66, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_hmac_prf_proto_rawDescOnce sync.Once file_third_party_tink_proto_hmac_prf_proto_rawDescData = file_third_party_tink_proto_hmac_prf_proto_rawDesc ) func file_third_party_tink_proto_hmac_prf_proto_rawDescGZIP() []byte { file_third_party_tink_proto_hmac_prf_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_hmac_prf_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_hmac_prf_proto_rawDescData) }) return file_third_party_tink_proto_hmac_prf_proto_rawDescData } var file_third_party_tink_proto_hmac_prf_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_third_party_tink_proto_hmac_prf_proto_goTypes = []interface{}{ (*HmacPrfParams)(nil), // 0: google.crypto.tink.HmacPrfParams (*HmacPrfKey)(nil), // 1: google.crypto.tink.HmacPrfKey (*HmacPrfKeyFormat)(nil), // 2: google.crypto.tink.HmacPrfKeyFormat (common_go_proto.HashType)(0), // 3: google.crypto.tink.HashType } var file_third_party_tink_proto_hmac_prf_proto_depIdxs = []int32{ 3, // 0: google.crypto.tink.HmacPrfParams.hash:type_name -> google.crypto.tink.HashType 0, // 1: google.crypto.tink.HmacPrfKey.params:type_name -> google.crypto.tink.HmacPrfParams 0, // 2: google.crypto.tink.HmacPrfKeyFormat.params:type_name -> google.crypto.tink.HmacPrfParams 3, // [3:3] is the sub-list for method output_type 3, // [3:3] is the sub-list for method input_type 3, // [3:3] is the sub-list for extension type_name 3, // [3:3] is the sub-list for extension extendee 0, // [0:3] is the sub-list for field type_name } func init() { file_third_party_tink_proto_hmac_prf_proto_init() } func file_third_party_tink_proto_hmac_prf_proto_init() { if File_third_party_tink_proto_hmac_prf_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_hmac_prf_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HmacPrfParams); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_hmac_prf_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HmacPrfKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_hmac_prf_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HmacPrfKeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_hmac_prf_proto_rawDesc, NumEnums: 0, NumMessages: 3, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_hmac_prf_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_hmac_prf_proto_depIdxs, MessageInfos: file_third_party_tink_proto_hmac_prf_proto_msgTypes, }.Build() File_third_party_tink_proto_hmac_prf_proto = out.File file_third_party_tink_proto_hmac_prf_proto_rawDesc = nil file_third_party_tink_proto_hmac_prf_proto_goTypes = nil file_third_party_tink_proto_hmac_prf_proto_depIdxs = nil } ================================================ FILE: go/proto/hpke_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "hpke_go_proto", srcs = ["hpke.pb.go"], importpath = "github.com/google/tink/go/proto/hpke_go_proto", visibility = ["//visibility:public"], deps = [ "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":hpke_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/hpke_go_proto/hpke.pb.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/hpke.proto package hpke_proto import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type HpkeKem int32 const ( HpkeKem_KEM_UNKNOWN HpkeKem = 0 HpkeKem_DHKEM_X25519_HKDF_SHA256 HpkeKem = 1 HpkeKem_DHKEM_P256_HKDF_SHA256 HpkeKem = 2 HpkeKem_DHKEM_P384_HKDF_SHA384 HpkeKem = 3 HpkeKem_DHKEM_P521_HKDF_SHA512 HpkeKem = 4 ) // Enum value maps for HpkeKem. var ( HpkeKem_name = map[int32]string{ 0: "KEM_UNKNOWN", 1: "DHKEM_X25519_HKDF_SHA256", 2: "DHKEM_P256_HKDF_SHA256", 3: "DHKEM_P384_HKDF_SHA384", 4: "DHKEM_P521_HKDF_SHA512", } HpkeKem_value = map[string]int32{ "KEM_UNKNOWN": 0, "DHKEM_X25519_HKDF_SHA256": 1, "DHKEM_P256_HKDF_SHA256": 2, "DHKEM_P384_HKDF_SHA384": 3, "DHKEM_P521_HKDF_SHA512": 4, } ) func (x HpkeKem) Enum() *HpkeKem { p := new(HpkeKem) *p = x return p } func (x HpkeKem) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (HpkeKem) Descriptor() protoreflect.EnumDescriptor { return file_third_party_tink_proto_hpke_proto_enumTypes[0].Descriptor() } func (HpkeKem) Type() protoreflect.EnumType { return &file_third_party_tink_proto_hpke_proto_enumTypes[0] } func (x HpkeKem) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use HpkeKem.Descriptor instead. func (HpkeKem) EnumDescriptor() ([]byte, []int) { return file_third_party_tink_proto_hpke_proto_rawDescGZIP(), []int{0} } type HpkeKdf int32 const ( HpkeKdf_KDF_UNKNOWN HpkeKdf = 0 HpkeKdf_HKDF_SHA256 HpkeKdf = 1 HpkeKdf_HKDF_SHA384 HpkeKdf = 2 HpkeKdf_HKDF_SHA512 HpkeKdf = 3 ) // Enum value maps for HpkeKdf. var ( HpkeKdf_name = map[int32]string{ 0: "KDF_UNKNOWN", 1: "HKDF_SHA256", 2: "HKDF_SHA384", 3: "HKDF_SHA512", } HpkeKdf_value = map[string]int32{ "KDF_UNKNOWN": 0, "HKDF_SHA256": 1, "HKDF_SHA384": 2, "HKDF_SHA512": 3, } ) func (x HpkeKdf) Enum() *HpkeKdf { p := new(HpkeKdf) *p = x return p } func (x HpkeKdf) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (HpkeKdf) Descriptor() protoreflect.EnumDescriptor { return file_third_party_tink_proto_hpke_proto_enumTypes[1].Descriptor() } func (HpkeKdf) Type() protoreflect.EnumType { return &file_third_party_tink_proto_hpke_proto_enumTypes[1] } func (x HpkeKdf) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use HpkeKdf.Descriptor instead. func (HpkeKdf) EnumDescriptor() ([]byte, []int) { return file_third_party_tink_proto_hpke_proto_rawDescGZIP(), []int{1} } type HpkeAead int32 const ( HpkeAead_AEAD_UNKNOWN HpkeAead = 0 HpkeAead_AES_128_GCM HpkeAead = 1 HpkeAead_AES_256_GCM HpkeAead = 2 HpkeAead_CHACHA20_POLY1305 HpkeAead = 3 ) // Enum value maps for HpkeAead. var ( HpkeAead_name = map[int32]string{ 0: "AEAD_UNKNOWN", 1: "AES_128_GCM", 2: "AES_256_GCM", 3: "CHACHA20_POLY1305", } HpkeAead_value = map[string]int32{ "AEAD_UNKNOWN": 0, "AES_128_GCM": 1, "AES_256_GCM": 2, "CHACHA20_POLY1305": 3, } ) func (x HpkeAead) Enum() *HpkeAead { p := new(HpkeAead) *p = x return p } func (x HpkeAead) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (HpkeAead) Descriptor() protoreflect.EnumDescriptor { return file_third_party_tink_proto_hpke_proto_enumTypes[2].Descriptor() } func (HpkeAead) Type() protoreflect.EnumType { return &file_third_party_tink_proto_hpke_proto_enumTypes[2] } func (x HpkeAead) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use HpkeAead.Descriptor instead. func (HpkeAead) EnumDescriptor() ([]byte, []int) { return file_third_party_tink_proto_hpke_proto_rawDescGZIP(), []int{2} } type HpkeParams struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Kem HpkeKem `protobuf:"varint,1,opt,name=kem,proto3,enum=google.crypto.tink.HpkeKem" json:"kem,omitempty"` Kdf HpkeKdf `protobuf:"varint,2,opt,name=kdf,proto3,enum=google.crypto.tink.HpkeKdf" json:"kdf,omitempty"` Aead HpkeAead `protobuf:"varint,3,opt,name=aead,proto3,enum=google.crypto.tink.HpkeAead" json:"aead,omitempty"` } func (x *HpkeParams) Reset() { *x = HpkeParams{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_hpke_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *HpkeParams) String() string { return protoimpl.X.MessageStringOf(x) } func (*HpkeParams) ProtoMessage() {} func (x *HpkeParams) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_hpke_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use HpkeParams.ProtoReflect.Descriptor instead. func (*HpkeParams) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_hpke_proto_rawDescGZIP(), []int{0} } func (x *HpkeParams) GetKem() HpkeKem { if x != nil { return x.Kem } return HpkeKem_KEM_UNKNOWN } func (x *HpkeParams) GetKdf() HpkeKdf { if x != nil { return x.Kdf } return HpkeKdf_KDF_UNKNOWN } func (x *HpkeParams) GetAead() HpkeAead { if x != nil { return x.Aead } return HpkeAead_AEAD_UNKNOWN } type HpkePublicKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` Params *HpkeParams `protobuf:"bytes,2,opt,name=params,proto3" json:"params,omitempty"` // KEM-encoding of public key (i.e., SerializePublicKey() ) as described in // https://www.rfc-editor.org/rfc/rfc9180.html#name-cryptographic-dependencies. PublicKey []byte `protobuf:"bytes,3,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` } func (x *HpkePublicKey) Reset() { *x = HpkePublicKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_hpke_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *HpkePublicKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*HpkePublicKey) ProtoMessage() {} func (x *HpkePublicKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_hpke_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use HpkePublicKey.ProtoReflect.Descriptor instead. func (*HpkePublicKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_hpke_proto_rawDescGZIP(), []int{1} } func (x *HpkePublicKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *HpkePublicKey) GetParams() *HpkeParams { if x != nil { return x.Params } return nil } func (x *HpkePublicKey) GetPublicKey() []byte { if x != nil { return x.PublicKey } return nil } type HpkePrivateKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` PublicKey *HpkePublicKey `protobuf:"bytes,2,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` // KEM-encoding of private key (i.e., SerializePrivateKey() ) as described in // https://www.rfc-editor.org/rfc/rfc9180.html#name-cryptographic-dependencies. PrivateKey []byte `protobuf:"bytes,3,opt,name=private_key,json=privateKey,proto3" json:"private_key,omitempty"` } func (x *HpkePrivateKey) Reset() { *x = HpkePrivateKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_hpke_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *HpkePrivateKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*HpkePrivateKey) ProtoMessage() {} func (x *HpkePrivateKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_hpke_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use HpkePrivateKey.ProtoReflect.Descriptor instead. func (*HpkePrivateKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_hpke_proto_rawDescGZIP(), []int{2} } func (x *HpkePrivateKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *HpkePrivateKey) GetPublicKey() *HpkePublicKey { if x != nil { return x.PublicKey } return nil } func (x *HpkePrivateKey) GetPrivateKey() []byte { if x != nil { return x.PrivateKey } return nil } type HpkeKeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Params *HpkeParams `protobuf:"bytes,1,opt,name=params,proto3" json:"params,omitempty"` } func (x *HpkeKeyFormat) Reset() { *x = HpkeKeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_hpke_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *HpkeKeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*HpkeKeyFormat) ProtoMessage() {} func (x *HpkeKeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_hpke_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use HpkeKeyFormat.ProtoReflect.Descriptor instead. func (*HpkeKeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_hpke_proto_rawDescGZIP(), []int{3} } func (x *HpkeKeyFormat) GetParams() *HpkeParams { if x != nil { return x.Params } return nil } var File_third_party_tink_proto_hpke_proto protoreflect.FileDescriptor var file_third_party_tink_proto_hpke_proto_rawDesc = []byte{ 0x0a, 0x21, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x68, 0x70, 0x6b, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x22, 0x9c, 0x01, 0x0a, 0x0a, 0x48, 0x70, 0x6b, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2d, 0x0a, 0x03, 0x6b, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x70, 0x6b, 0x65, 0x4b, 0x65, 0x6d, 0x52, 0x03, 0x6b, 0x65, 0x6d, 0x12, 0x2d, 0x0a, 0x03, 0x6b, 0x64, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x70, 0x6b, 0x65, 0x4b, 0x64, 0x66, 0x52, 0x03, 0x6b, 0x64, 0x66, 0x12, 0x30, 0x0a, 0x04, 0x61, 0x65, 0x61, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x70, 0x6b, 0x65, 0x41, 0x65, 0x61, 0x64, 0x52, 0x04, 0x61, 0x65, 0x61, 0x64, 0x22, 0x80, 0x01, 0x0a, 0x0d, 0x48, 0x70, 0x6b, 0x65, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x70, 0x6b, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x22, 0x8d, 0x01, 0x0a, 0x0e, 0x48, 0x70, 0x6b, 0x65, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x40, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x70, 0x6b, 0x65, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x22, 0x47, 0x0a, 0x0d, 0x48, 0x70, 0x6b, 0x65, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x36, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x70, 0x6b, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2a, 0x8c, 0x01, 0x0a, 0x07, 0x48, 0x70, 0x6b, 0x65, 0x4b, 0x65, 0x6d, 0x12, 0x0f, 0x0a, 0x0b, 0x4b, 0x45, 0x4d, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x44, 0x48, 0x4b, 0x45, 0x4d, 0x5f, 0x58, 0x32, 0x35, 0x35, 0x31, 0x39, 0x5f, 0x48, 0x4b, 0x44, 0x46, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x44, 0x48, 0x4b, 0x45, 0x4d, 0x5f, 0x50, 0x32, 0x35, 0x36, 0x5f, 0x48, 0x4b, 0x44, 0x46, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x44, 0x48, 0x4b, 0x45, 0x4d, 0x5f, 0x50, 0x33, 0x38, 0x34, 0x5f, 0x48, 0x4b, 0x44, 0x46, 0x5f, 0x53, 0x48, 0x41, 0x33, 0x38, 0x34, 0x10, 0x03, 0x12, 0x1a, 0x0a, 0x16, 0x44, 0x48, 0x4b, 0x45, 0x4d, 0x5f, 0x50, 0x35, 0x32, 0x31, 0x5f, 0x48, 0x4b, 0x44, 0x46, 0x5f, 0x53, 0x48, 0x41, 0x35, 0x31, 0x32, 0x10, 0x04, 0x2a, 0x4d, 0x0a, 0x07, 0x48, 0x70, 0x6b, 0x65, 0x4b, 0x64, 0x66, 0x12, 0x0f, 0x0a, 0x0b, 0x4b, 0x44, 0x46, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x48, 0x4b, 0x44, 0x46, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x48, 0x4b, 0x44, 0x46, 0x5f, 0x53, 0x48, 0x41, 0x33, 0x38, 0x34, 0x10, 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x48, 0x4b, 0x44, 0x46, 0x5f, 0x53, 0x48, 0x41, 0x35, 0x31, 0x32, 0x10, 0x03, 0x2a, 0x55, 0x0a, 0x08, 0x48, 0x70, 0x6b, 0x65, 0x41, 0x65, 0x61, 0x64, 0x12, 0x10, 0x0a, 0x0c, 0x41, 0x45, 0x41, 0x44, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x45, 0x53, 0x5f, 0x31, 0x32, 0x38, 0x5f, 0x47, 0x43, 0x4d, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x45, 0x53, 0x5f, 0x32, 0x35, 0x36, 0x5f, 0x47, 0x43, 0x4d, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x48, 0x41, 0x43, 0x48, 0x41, 0x32, 0x30, 0x5f, 0x50, 0x4f, 0x4c, 0x59, 0x31, 0x33, 0x30, 0x35, 0x10, 0x03, 0x42, 0x4c, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x68, 0x70, 0x6b, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_hpke_proto_rawDescOnce sync.Once file_third_party_tink_proto_hpke_proto_rawDescData = file_third_party_tink_proto_hpke_proto_rawDesc ) func file_third_party_tink_proto_hpke_proto_rawDescGZIP() []byte { file_third_party_tink_proto_hpke_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_hpke_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_hpke_proto_rawDescData) }) return file_third_party_tink_proto_hpke_proto_rawDescData } var file_third_party_tink_proto_hpke_proto_enumTypes = make([]protoimpl.EnumInfo, 3) var file_third_party_tink_proto_hpke_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_third_party_tink_proto_hpke_proto_goTypes = []interface{}{ (HpkeKem)(0), // 0: google.crypto.tink.HpkeKem (HpkeKdf)(0), // 1: google.crypto.tink.HpkeKdf (HpkeAead)(0), // 2: google.crypto.tink.HpkeAead (*HpkeParams)(nil), // 3: google.crypto.tink.HpkeParams (*HpkePublicKey)(nil), // 4: google.crypto.tink.HpkePublicKey (*HpkePrivateKey)(nil), // 5: google.crypto.tink.HpkePrivateKey (*HpkeKeyFormat)(nil), // 6: google.crypto.tink.HpkeKeyFormat } var file_third_party_tink_proto_hpke_proto_depIdxs = []int32{ 0, // 0: google.crypto.tink.HpkeParams.kem:type_name -> google.crypto.tink.HpkeKem 1, // 1: google.crypto.tink.HpkeParams.kdf:type_name -> google.crypto.tink.HpkeKdf 2, // 2: google.crypto.tink.HpkeParams.aead:type_name -> google.crypto.tink.HpkeAead 3, // 3: google.crypto.tink.HpkePublicKey.params:type_name -> google.crypto.tink.HpkeParams 4, // 4: google.crypto.tink.HpkePrivateKey.public_key:type_name -> google.crypto.tink.HpkePublicKey 3, // 5: google.crypto.tink.HpkeKeyFormat.params:type_name -> google.crypto.tink.HpkeParams 6, // [6:6] is the sub-list for method output_type 6, // [6:6] is the sub-list for method input_type 6, // [6:6] is the sub-list for extension type_name 6, // [6:6] is the sub-list for extension extendee 0, // [0:6] is the sub-list for field type_name } func init() { file_third_party_tink_proto_hpke_proto_init() } func file_third_party_tink_proto_hpke_proto_init() { if File_third_party_tink_proto_hpke_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_hpke_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HpkeParams); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_hpke_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HpkePublicKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_hpke_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HpkePrivateKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_hpke_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HpkeKeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_hpke_proto_rawDesc, NumEnums: 3, NumMessages: 4, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_hpke_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_hpke_proto_depIdxs, EnumInfos: file_third_party_tink_proto_hpke_proto_enumTypes, MessageInfos: file_third_party_tink_proto_hpke_proto_msgTypes, }.Build() File_third_party_tink_proto_hpke_proto = out.File file_third_party_tink_proto_hpke_proto_rawDesc = nil file_third_party_tink_proto_hpke_proto_goTypes = nil file_third_party_tink_proto_hpke_proto_depIdxs = nil } ================================================ FILE: go/proto/jwt_ecdsa_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "jwt_ecdsa_go_proto", srcs = ["jwt_ecdsa.pb.go"], importpath = "github.com/google/tink/go/proto/jwt_ecdsa_go_proto", visibility = ["//visibility:public"], deps = [ "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":jwt_ecdsa_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/jwt_ecdsa_go_proto/jwt_ecdsa.pb.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/jwt_ecdsa.proto package jwt_ecdsa_go_proto import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) // See https://datatracker.ietf.org/doc/html/rfc7518#section-3.4 type JwtEcdsaAlgorithm int32 const ( JwtEcdsaAlgorithm_ES_UNKNOWN JwtEcdsaAlgorithm = 0 JwtEcdsaAlgorithm_ES256 JwtEcdsaAlgorithm = 1 // ECDSA using P-256 and SHA-256 JwtEcdsaAlgorithm_ES384 JwtEcdsaAlgorithm = 2 // ECDSA using P-384 and SHA-384 JwtEcdsaAlgorithm_ES512 JwtEcdsaAlgorithm = 3 // ECDSA using P-521 and SHA-512 ) // Enum value maps for JwtEcdsaAlgorithm. var ( JwtEcdsaAlgorithm_name = map[int32]string{ 0: "ES_UNKNOWN", 1: "ES256", 2: "ES384", 3: "ES512", } JwtEcdsaAlgorithm_value = map[string]int32{ "ES_UNKNOWN": 0, "ES256": 1, "ES384": 2, "ES512": 3, } ) func (x JwtEcdsaAlgorithm) Enum() *JwtEcdsaAlgorithm { p := new(JwtEcdsaAlgorithm) *p = x return p } func (x JwtEcdsaAlgorithm) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (JwtEcdsaAlgorithm) Descriptor() protoreflect.EnumDescriptor { return file_third_party_tink_proto_jwt_ecdsa_proto_enumTypes[0].Descriptor() } func (JwtEcdsaAlgorithm) Type() protoreflect.EnumType { return &file_third_party_tink_proto_jwt_ecdsa_proto_enumTypes[0] } func (x JwtEcdsaAlgorithm) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use JwtEcdsaAlgorithm.Descriptor instead. func (JwtEcdsaAlgorithm) EnumDescriptor() ([]byte, []int) { return file_third_party_tink_proto_jwt_ecdsa_proto_rawDescGZIP(), []int{0} } // key_type: type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey type JwtEcdsaPublicKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` Algorithm JwtEcdsaAlgorithm `protobuf:"varint,2,opt,name=algorithm,proto3,enum=google.crypto.tink.JwtEcdsaAlgorithm" json:"algorithm,omitempty"` // Affine coordinates of the public key in big-endian representation. The // public key is a point (x, y) on the curve defined by algorithm. X []byte `protobuf:"bytes,3,opt,name=x,proto3" json:"x,omitempty"` Y []byte `protobuf:"bytes,4,opt,name=y,proto3" json:"y,omitempty"` CustomKid *JwtEcdsaPublicKey_CustomKid `protobuf:"bytes,5,opt,name=custom_kid,json=customKid,proto3" json:"custom_kid,omitempty"` } func (x *JwtEcdsaPublicKey) Reset() { *x = JwtEcdsaPublicKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_jwt_ecdsa_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *JwtEcdsaPublicKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*JwtEcdsaPublicKey) ProtoMessage() {} func (x *JwtEcdsaPublicKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_jwt_ecdsa_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use JwtEcdsaPublicKey.ProtoReflect.Descriptor instead. func (*JwtEcdsaPublicKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_jwt_ecdsa_proto_rawDescGZIP(), []int{0} } func (x *JwtEcdsaPublicKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *JwtEcdsaPublicKey) GetAlgorithm() JwtEcdsaAlgorithm { if x != nil { return x.Algorithm } return JwtEcdsaAlgorithm_ES_UNKNOWN } func (x *JwtEcdsaPublicKey) GetX() []byte { if x != nil { return x.X } return nil } func (x *JwtEcdsaPublicKey) GetY() []byte { if x != nil { return x.Y } return nil } func (x *JwtEcdsaPublicKey) GetCustomKid() *JwtEcdsaPublicKey_CustomKid { if x != nil { return x.CustomKid } return nil } // key_type: type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey type JwtEcdsaPrivateKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` PublicKey *JwtEcdsaPublicKey `protobuf:"bytes,2,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` // Unsigned big integer in bigendian representation. KeyValue []byte `protobuf:"bytes,3,opt,name=key_value,json=keyValue,proto3" json:"key_value,omitempty"` } func (x *JwtEcdsaPrivateKey) Reset() { *x = JwtEcdsaPrivateKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_jwt_ecdsa_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *JwtEcdsaPrivateKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*JwtEcdsaPrivateKey) ProtoMessage() {} func (x *JwtEcdsaPrivateKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_jwt_ecdsa_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use JwtEcdsaPrivateKey.ProtoReflect.Descriptor instead. func (*JwtEcdsaPrivateKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_jwt_ecdsa_proto_rawDescGZIP(), []int{1} } func (x *JwtEcdsaPrivateKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *JwtEcdsaPrivateKey) GetPublicKey() *JwtEcdsaPublicKey { if x != nil { return x.PublicKey } return nil } func (x *JwtEcdsaPrivateKey) GetKeyValue() []byte { if x != nil { return x.KeyValue } return nil } type JwtEcdsaKeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` Algorithm JwtEcdsaAlgorithm `protobuf:"varint,2,opt,name=algorithm,proto3,enum=google.crypto.tink.JwtEcdsaAlgorithm" json:"algorithm,omitempty"` } func (x *JwtEcdsaKeyFormat) Reset() { *x = JwtEcdsaKeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_jwt_ecdsa_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *JwtEcdsaKeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*JwtEcdsaKeyFormat) ProtoMessage() {} func (x *JwtEcdsaKeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_jwt_ecdsa_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use JwtEcdsaKeyFormat.ProtoReflect.Descriptor instead. func (*JwtEcdsaKeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_jwt_ecdsa_proto_rawDescGZIP(), []int{2} } func (x *JwtEcdsaKeyFormat) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *JwtEcdsaKeyFormat) GetAlgorithm() JwtEcdsaAlgorithm { if x != nil { return x.Algorithm } return JwtEcdsaAlgorithm_ES_UNKNOWN } // Optional, custom kid header value to be used with "RAW" keys. // "TINK" keys with this value set will be rejected. type JwtEcdsaPublicKey_CustomKid struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` } func (x *JwtEcdsaPublicKey_CustomKid) Reset() { *x = JwtEcdsaPublicKey_CustomKid{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_jwt_ecdsa_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *JwtEcdsaPublicKey_CustomKid) String() string { return protoimpl.X.MessageStringOf(x) } func (*JwtEcdsaPublicKey_CustomKid) ProtoMessage() {} func (x *JwtEcdsaPublicKey_CustomKid) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_jwt_ecdsa_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use JwtEcdsaPublicKey_CustomKid.ProtoReflect.Descriptor instead. func (*JwtEcdsaPublicKey_CustomKid) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_jwt_ecdsa_proto_rawDescGZIP(), []int{0, 0} } func (x *JwtEcdsaPublicKey_CustomKid) GetValue() string { if x != nil { return x.Value } return "" } var File_third_party_tink_proto_jwt_ecdsa_proto protoreflect.FileDescriptor var file_third_party_tink_proto_jwt_ecdsa_proto_rawDesc = []byte{ 0x0a, 0x26, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6a, 0x77, 0x74, 0x5f, 0x65, 0x63, 0x64, 0x73, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x22, 0x81, 0x02, 0x0a, 0x11, 0x4a, 0x77, 0x74, 0x45, 0x63, 0x64, 0x73, 0x61, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x43, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4a, 0x77, 0x74, 0x45, 0x63, 0x64, 0x73, 0x61, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x52, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x0c, 0x0a, 0x01, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x78, 0x12, 0x0c, 0x0a, 0x01, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x79, 0x12, 0x4e, 0x0a, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6b, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4a, 0x77, 0x74, 0x45, 0x63, 0x64, 0x73, 0x61, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4b, 0x69, 0x64, 0x52, 0x09, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4b, 0x69, 0x64, 0x1a, 0x21, 0x0a, 0x09, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4b, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x91, 0x01, 0x0a, 0x12, 0x4a, 0x77, 0x74, 0x45, 0x63, 0x64, 0x73, 0x61, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x44, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4a, 0x77, 0x74, 0x45, 0x63, 0x64, 0x73, 0x61, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x72, 0x0a, 0x11, 0x4a, 0x77, 0x74, 0x45, 0x63, 0x64, 0x73, 0x61, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x43, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4a, 0x77, 0x74, 0x45, 0x63, 0x64, 0x73, 0x61, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x52, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2a, 0x44, 0x0a, 0x11, 0x4a, 0x77, 0x74, 0x45, 0x63, 0x64, 0x73, 0x61, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x0e, 0x0a, 0x0a, 0x45, 0x53, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x53, 0x32, 0x35, 0x36, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x53, 0x33, 0x38, 0x34, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x53, 0x35, 0x31, 0x32, 0x10, 0x03, 0x42, 0x54, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6a, 0x77, 0x74, 0x5f, 0x65, 0x63, 0x64, 0x73, 0x61, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_jwt_ecdsa_proto_rawDescOnce sync.Once file_third_party_tink_proto_jwt_ecdsa_proto_rawDescData = file_third_party_tink_proto_jwt_ecdsa_proto_rawDesc ) func file_third_party_tink_proto_jwt_ecdsa_proto_rawDescGZIP() []byte { file_third_party_tink_proto_jwt_ecdsa_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_jwt_ecdsa_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_jwt_ecdsa_proto_rawDescData) }) return file_third_party_tink_proto_jwt_ecdsa_proto_rawDescData } var file_third_party_tink_proto_jwt_ecdsa_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_third_party_tink_proto_jwt_ecdsa_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_third_party_tink_proto_jwt_ecdsa_proto_goTypes = []interface{}{ (JwtEcdsaAlgorithm)(0), // 0: google.crypto.tink.JwtEcdsaAlgorithm (*JwtEcdsaPublicKey)(nil), // 1: google.crypto.tink.JwtEcdsaPublicKey (*JwtEcdsaPrivateKey)(nil), // 2: google.crypto.tink.JwtEcdsaPrivateKey (*JwtEcdsaKeyFormat)(nil), // 3: google.crypto.tink.JwtEcdsaKeyFormat (*JwtEcdsaPublicKey_CustomKid)(nil), // 4: google.crypto.tink.JwtEcdsaPublicKey.CustomKid } var file_third_party_tink_proto_jwt_ecdsa_proto_depIdxs = []int32{ 0, // 0: google.crypto.tink.JwtEcdsaPublicKey.algorithm:type_name -> google.crypto.tink.JwtEcdsaAlgorithm 4, // 1: google.crypto.tink.JwtEcdsaPublicKey.custom_kid:type_name -> google.crypto.tink.JwtEcdsaPublicKey.CustomKid 1, // 2: google.crypto.tink.JwtEcdsaPrivateKey.public_key:type_name -> google.crypto.tink.JwtEcdsaPublicKey 0, // 3: google.crypto.tink.JwtEcdsaKeyFormat.algorithm:type_name -> google.crypto.tink.JwtEcdsaAlgorithm 4, // [4:4] is the sub-list for method output_type 4, // [4:4] is the sub-list for method input_type 4, // [4:4] is the sub-list for extension type_name 4, // [4:4] is the sub-list for extension extendee 0, // [0:4] is the sub-list for field type_name } func init() { file_third_party_tink_proto_jwt_ecdsa_proto_init() } func file_third_party_tink_proto_jwt_ecdsa_proto_init() { if File_third_party_tink_proto_jwt_ecdsa_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_jwt_ecdsa_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JwtEcdsaPublicKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_jwt_ecdsa_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JwtEcdsaPrivateKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_jwt_ecdsa_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JwtEcdsaKeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_jwt_ecdsa_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JwtEcdsaPublicKey_CustomKid); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_jwt_ecdsa_proto_rawDesc, NumEnums: 1, NumMessages: 4, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_jwt_ecdsa_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_jwt_ecdsa_proto_depIdxs, EnumInfos: file_third_party_tink_proto_jwt_ecdsa_proto_enumTypes, MessageInfos: file_third_party_tink_proto_jwt_ecdsa_proto_msgTypes, }.Build() File_third_party_tink_proto_jwt_ecdsa_proto = out.File file_third_party_tink_proto_jwt_ecdsa_proto_rawDesc = nil file_third_party_tink_proto_jwt_ecdsa_proto_goTypes = nil file_third_party_tink_proto_jwt_ecdsa_proto_depIdxs = nil } ================================================ FILE: go/proto/jwt_hmac_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "jwt_hmac_go_proto", srcs = ["jwt_hmac.pb.go"], importpath = "github.com/google/tink/go/proto/jwt_hmac_go_proto", visibility = ["//visibility:public"], deps = [ "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":jwt_hmac_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/jwt_hmac_go_proto/jwt_hmac.pb.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/jwt_hmac.proto package jwt_hmac_go_proto import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) // See https://datatracker.ietf.org/doc/html/rfc7518#section-3.2 type JwtHmacAlgorithm int32 const ( JwtHmacAlgorithm_HS_UNKNOWN JwtHmacAlgorithm = 0 JwtHmacAlgorithm_HS256 JwtHmacAlgorithm = 1 // HMAC using SHA-256 JwtHmacAlgorithm_HS384 JwtHmacAlgorithm = 2 // HMAC using SHA-384 JwtHmacAlgorithm_HS512 JwtHmacAlgorithm = 3 // HMAC using SHA-512 ) // Enum value maps for JwtHmacAlgorithm. var ( JwtHmacAlgorithm_name = map[int32]string{ 0: "HS_UNKNOWN", 1: "HS256", 2: "HS384", 3: "HS512", } JwtHmacAlgorithm_value = map[string]int32{ "HS_UNKNOWN": 0, "HS256": 1, "HS384": 2, "HS512": 3, } ) func (x JwtHmacAlgorithm) Enum() *JwtHmacAlgorithm { p := new(JwtHmacAlgorithm) *p = x return p } func (x JwtHmacAlgorithm) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (JwtHmacAlgorithm) Descriptor() protoreflect.EnumDescriptor { return file_third_party_tink_proto_jwt_hmac_proto_enumTypes[0].Descriptor() } func (JwtHmacAlgorithm) Type() protoreflect.EnumType { return &file_third_party_tink_proto_jwt_hmac_proto_enumTypes[0] } func (x JwtHmacAlgorithm) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use JwtHmacAlgorithm.Descriptor instead. func (JwtHmacAlgorithm) EnumDescriptor() ([]byte, []int) { return file_third_party_tink_proto_jwt_hmac_proto_rawDescGZIP(), []int{0} } // key_type: type.googleapis.com/google.crypto.tink.JwtHmacKey type JwtHmacKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` Algorithm JwtHmacAlgorithm `protobuf:"varint,2,opt,name=algorithm,proto3,enum=google.crypto.tink.JwtHmacAlgorithm" json:"algorithm,omitempty"` KeyValue []byte `protobuf:"bytes,3,opt,name=key_value,json=keyValue,proto3" json:"key_value,omitempty"` CustomKid *JwtHmacKey_CustomKid `protobuf:"bytes,4,opt,name=custom_kid,json=customKid,proto3" json:"custom_kid,omitempty"` } func (x *JwtHmacKey) Reset() { *x = JwtHmacKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_jwt_hmac_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *JwtHmacKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*JwtHmacKey) ProtoMessage() {} func (x *JwtHmacKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_jwt_hmac_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use JwtHmacKey.ProtoReflect.Descriptor instead. func (*JwtHmacKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_jwt_hmac_proto_rawDescGZIP(), []int{0} } func (x *JwtHmacKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *JwtHmacKey) GetAlgorithm() JwtHmacAlgorithm { if x != nil { return x.Algorithm } return JwtHmacAlgorithm_HS_UNKNOWN } func (x *JwtHmacKey) GetKeyValue() []byte { if x != nil { return x.KeyValue } return nil } func (x *JwtHmacKey) GetCustomKid() *JwtHmacKey_CustomKid { if x != nil { return x.CustomKid } return nil } type JwtHmacKeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` Algorithm JwtHmacAlgorithm `protobuf:"varint,2,opt,name=algorithm,proto3,enum=google.crypto.tink.JwtHmacAlgorithm" json:"algorithm,omitempty"` KeySize uint32 `protobuf:"varint,3,opt,name=key_size,json=keySize,proto3" json:"key_size,omitempty"` } func (x *JwtHmacKeyFormat) Reset() { *x = JwtHmacKeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_jwt_hmac_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *JwtHmacKeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*JwtHmacKeyFormat) ProtoMessage() {} func (x *JwtHmacKeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_jwt_hmac_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use JwtHmacKeyFormat.ProtoReflect.Descriptor instead. func (*JwtHmacKeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_jwt_hmac_proto_rawDescGZIP(), []int{1} } func (x *JwtHmacKeyFormat) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *JwtHmacKeyFormat) GetAlgorithm() JwtHmacAlgorithm { if x != nil { return x.Algorithm } return JwtHmacAlgorithm_HS_UNKNOWN } func (x *JwtHmacKeyFormat) GetKeySize() uint32 { if x != nil { return x.KeySize } return 0 } // Optional, custom kid header value to be used with "RAW" keys. // "TINK" keys with this value set will be rejected. type JwtHmacKey_CustomKid struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` } func (x *JwtHmacKey_CustomKid) Reset() { *x = JwtHmacKey_CustomKid{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_jwt_hmac_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *JwtHmacKey_CustomKid) String() string { return protoimpl.X.MessageStringOf(x) } func (*JwtHmacKey_CustomKid) ProtoMessage() {} func (x *JwtHmacKey_CustomKid) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_jwt_hmac_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use JwtHmacKey_CustomKid.ProtoReflect.Descriptor instead. func (*JwtHmacKey_CustomKid) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_jwt_hmac_proto_rawDescGZIP(), []int{0, 0} } func (x *JwtHmacKey_CustomKid) GetValue() string { if x != nil { return x.Value } return "" } var File_third_party_tink_proto_jwt_hmac_proto protoreflect.FileDescriptor var file_third_party_tink_proto_jwt_hmac_proto_rawDesc = []byte{ 0x0a, 0x25, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6a, 0x77, 0x74, 0x5f, 0x68, 0x6d, 0x61, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x22, 0xf3, 0x01, 0x0a, 0x0a, 0x4a, 0x77, 0x74, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x42, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4a, 0x77, 0x74, 0x48, 0x6d, 0x61, 0x63, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x52, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x47, 0x0a, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6b, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4a, 0x77, 0x74, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4b, 0x69, 0x64, 0x52, 0x09, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4b, 0x69, 0x64, 0x1a, 0x21, 0x0a, 0x09, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4b, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x8b, 0x01, 0x0a, 0x10, 0x4a, 0x77, 0x74, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x42, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4a, 0x77, 0x74, 0x48, 0x6d, 0x61, 0x63, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x52, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x2a, 0x43, 0x0a, 0x10, 0x4a, 0x77, 0x74, 0x48, 0x6d, 0x61, 0x63, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x0e, 0x0a, 0x0a, 0x48, 0x53, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x48, 0x53, 0x32, 0x35, 0x36, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x48, 0x53, 0x33, 0x38, 0x34, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x48, 0x53, 0x35, 0x31, 0x32, 0x10, 0x03, 0x42, 0x53, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6a, 0x77, 0x74, 0x5f, 0x68, 0x6d, 0x61, 0x63, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_jwt_hmac_proto_rawDescOnce sync.Once file_third_party_tink_proto_jwt_hmac_proto_rawDescData = file_third_party_tink_proto_jwt_hmac_proto_rawDesc ) func file_third_party_tink_proto_jwt_hmac_proto_rawDescGZIP() []byte { file_third_party_tink_proto_jwt_hmac_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_jwt_hmac_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_jwt_hmac_proto_rawDescData) }) return file_third_party_tink_proto_jwt_hmac_proto_rawDescData } var file_third_party_tink_proto_jwt_hmac_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_third_party_tink_proto_jwt_hmac_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_third_party_tink_proto_jwt_hmac_proto_goTypes = []interface{}{ (JwtHmacAlgorithm)(0), // 0: google.crypto.tink.JwtHmacAlgorithm (*JwtHmacKey)(nil), // 1: google.crypto.tink.JwtHmacKey (*JwtHmacKeyFormat)(nil), // 2: google.crypto.tink.JwtHmacKeyFormat (*JwtHmacKey_CustomKid)(nil), // 3: google.crypto.tink.JwtHmacKey.CustomKid } var file_third_party_tink_proto_jwt_hmac_proto_depIdxs = []int32{ 0, // 0: google.crypto.tink.JwtHmacKey.algorithm:type_name -> google.crypto.tink.JwtHmacAlgorithm 3, // 1: google.crypto.tink.JwtHmacKey.custom_kid:type_name -> google.crypto.tink.JwtHmacKey.CustomKid 0, // 2: google.crypto.tink.JwtHmacKeyFormat.algorithm:type_name -> google.crypto.tink.JwtHmacAlgorithm 3, // [3:3] is the sub-list for method output_type 3, // [3:3] is the sub-list for method input_type 3, // [3:3] is the sub-list for extension type_name 3, // [3:3] is the sub-list for extension extendee 0, // [0:3] is the sub-list for field type_name } func init() { file_third_party_tink_proto_jwt_hmac_proto_init() } func file_third_party_tink_proto_jwt_hmac_proto_init() { if File_third_party_tink_proto_jwt_hmac_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_jwt_hmac_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JwtHmacKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_jwt_hmac_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JwtHmacKeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_jwt_hmac_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JwtHmacKey_CustomKid); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_jwt_hmac_proto_rawDesc, NumEnums: 1, NumMessages: 3, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_jwt_hmac_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_jwt_hmac_proto_depIdxs, EnumInfos: file_third_party_tink_proto_jwt_hmac_proto_enumTypes, MessageInfos: file_third_party_tink_proto_jwt_hmac_proto_msgTypes, }.Build() File_third_party_tink_proto_jwt_hmac_proto = out.File file_third_party_tink_proto_jwt_hmac_proto_rawDesc = nil file_third_party_tink_proto_jwt_hmac_proto_goTypes = nil file_third_party_tink_proto_jwt_hmac_proto_depIdxs = nil } ================================================ FILE: go/proto/jwt_rsa_ssa_pkcs1_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "jwt_rsa_ssa_pkcs1_go_proto", srcs = ["jwt_rsa_ssa_pkcs1.pb.go"], importpath = "github.com/google/tink/go/proto/jwt_rsa_ssa_pkcs1_go_proto", visibility = ["//visibility:public"], deps = [ "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":jwt_rsa_ssa_pkcs1_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/jwt_rsa_ssa_pkcs1_go_proto/jwt_rsa_ssa_pkcs1.pb.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/jwt_rsa_ssa_pkcs1.proto package rsa_ssa_pkcs1_go_proto import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) // See https://datatracker.ietf.org/doc/html/rfc7518#section-3.3 type JwtRsaSsaPkcs1Algorithm int32 const ( JwtRsaSsaPkcs1Algorithm_RS_UNKNOWN JwtRsaSsaPkcs1Algorithm = 0 JwtRsaSsaPkcs1Algorithm_RS256 JwtRsaSsaPkcs1Algorithm = 1 // RSASSA-PKCS1-v1_5 using SHA-256 JwtRsaSsaPkcs1Algorithm_RS384 JwtRsaSsaPkcs1Algorithm = 2 // RSASSA-PKCS1-v1_5 using SHA-384 JwtRsaSsaPkcs1Algorithm_RS512 JwtRsaSsaPkcs1Algorithm = 3 // RSASSA-PKCS1-v1_5 using SHA-512 ) // Enum value maps for JwtRsaSsaPkcs1Algorithm. var ( JwtRsaSsaPkcs1Algorithm_name = map[int32]string{ 0: "RS_UNKNOWN", 1: "RS256", 2: "RS384", 3: "RS512", } JwtRsaSsaPkcs1Algorithm_value = map[string]int32{ "RS_UNKNOWN": 0, "RS256": 1, "RS384": 2, "RS512": 3, } ) func (x JwtRsaSsaPkcs1Algorithm) Enum() *JwtRsaSsaPkcs1Algorithm { p := new(JwtRsaSsaPkcs1Algorithm) *p = x return p } func (x JwtRsaSsaPkcs1Algorithm) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (JwtRsaSsaPkcs1Algorithm) Descriptor() protoreflect.EnumDescriptor { return file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_enumTypes[0].Descriptor() } func (JwtRsaSsaPkcs1Algorithm) Type() protoreflect.EnumType { return &file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_enumTypes[0] } func (x JwtRsaSsaPkcs1Algorithm) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use JwtRsaSsaPkcs1Algorithm.Descriptor instead. func (JwtRsaSsaPkcs1Algorithm) EnumDescriptor() ([]byte, []int) { return file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_rawDescGZIP(), []int{0} } // key_type: type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PublicKey type JwtRsaSsaPkcs1PublicKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` Algorithm JwtRsaSsaPkcs1Algorithm `protobuf:"varint,2,opt,name=algorithm,proto3,enum=google.crypto.tink.JwtRsaSsaPkcs1Algorithm" json:"algorithm,omitempty"` // Modulus. // Unsigned big integer in big-endian representation. N []byte `protobuf:"bytes,3,opt,name=n,proto3" json:"n,omitempty"` // Public exponent. // Unsigned big integer in big-endian representation. E []byte `protobuf:"bytes,4,opt,name=e,proto3" json:"e,omitempty"` CustomKid *JwtRsaSsaPkcs1PublicKey_CustomKid `protobuf:"bytes,5,opt,name=custom_kid,json=customKid,proto3" json:"custom_kid,omitempty"` } func (x *JwtRsaSsaPkcs1PublicKey) Reset() { *x = JwtRsaSsaPkcs1PublicKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *JwtRsaSsaPkcs1PublicKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*JwtRsaSsaPkcs1PublicKey) ProtoMessage() {} func (x *JwtRsaSsaPkcs1PublicKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use JwtRsaSsaPkcs1PublicKey.ProtoReflect.Descriptor instead. func (*JwtRsaSsaPkcs1PublicKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_rawDescGZIP(), []int{0} } func (x *JwtRsaSsaPkcs1PublicKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *JwtRsaSsaPkcs1PublicKey) GetAlgorithm() JwtRsaSsaPkcs1Algorithm { if x != nil { return x.Algorithm } return JwtRsaSsaPkcs1Algorithm_RS_UNKNOWN } func (x *JwtRsaSsaPkcs1PublicKey) GetN() []byte { if x != nil { return x.N } return nil } func (x *JwtRsaSsaPkcs1PublicKey) GetE() []byte { if x != nil { return x.E } return nil } func (x *JwtRsaSsaPkcs1PublicKey) GetCustomKid() *JwtRsaSsaPkcs1PublicKey_CustomKid { if x != nil { return x.CustomKid } return nil } // key_type: type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PrivateKey type JwtRsaSsaPkcs1PrivateKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` PublicKey *JwtRsaSsaPkcs1PublicKey `protobuf:"bytes,2,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` // Private exponent. // Unsigned big integer in big-endian representation. D []byte `protobuf:"bytes,3,opt,name=d,proto3" json:"d,omitempty"` // The following parameters are used to optimize RSA signature computation. // The prime factor p of n. // Unsigned big integer in big-endian representation. P []byte `protobuf:"bytes,4,opt,name=p,proto3" json:"p,omitempty"` // The prime factor q of n. // Unsigned big integer in big-endian representation. Q []byte `protobuf:"bytes,5,opt,name=q,proto3" json:"q,omitempty"` // d mod (p - 1). // Unsigned big integer in big-endian representation. Dp []byte `protobuf:"bytes,6,opt,name=dp,proto3" json:"dp,omitempty"` // d mod (q - 1). // Unsigned big integer in big-endian representation. Dq []byte `protobuf:"bytes,7,opt,name=dq,proto3" json:"dq,omitempty"` // Chinese Remainder Theorem coefficient q^(-1) mod p. // Unsigned big integer in big-endian representation. Crt []byte `protobuf:"bytes,8,opt,name=crt,proto3" json:"crt,omitempty"` } func (x *JwtRsaSsaPkcs1PrivateKey) Reset() { *x = JwtRsaSsaPkcs1PrivateKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *JwtRsaSsaPkcs1PrivateKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*JwtRsaSsaPkcs1PrivateKey) ProtoMessage() {} func (x *JwtRsaSsaPkcs1PrivateKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use JwtRsaSsaPkcs1PrivateKey.ProtoReflect.Descriptor instead. func (*JwtRsaSsaPkcs1PrivateKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_rawDescGZIP(), []int{1} } func (x *JwtRsaSsaPkcs1PrivateKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *JwtRsaSsaPkcs1PrivateKey) GetPublicKey() *JwtRsaSsaPkcs1PublicKey { if x != nil { return x.PublicKey } return nil } func (x *JwtRsaSsaPkcs1PrivateKey) GetD() []byte { if x != nil { return x.D } return nil } func (x *JwtRsaSsaPkcs1PrivateKey) GetP() []byte { if x != nil { return x.P } return nil } func (x *JwtRsaSsaPkcs1PrivateKey) GetQ() []byte { if x != nil { return x.Q } return nil } func (x *JwtRsaSsaPkcs1PrivateKey) GetDp() []byte { if x != nil { return x.Dp } return nil } func (x *JwtRsaSsaPkcs1PrivateKey) GetDq() []byte { if x != nil { return x.Dq } return nil } func (x *JwtRsaSsaPkcs1PrivateKey) GetCrt() []byte { if x != nil { return x.Crt } return nil } type JwtRsaSsaPkcs1KeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` Algorithm JwtRsaSsaPkcs1Algorithm `protobuf:"varint,2,opt,name=algorithm,proto3,enum=google.crypto.tink.JwtRsaSsaPkcs1Algorithm" json:"algorithm,omitempty"` ModulusSizeInBits uint32 `protobuf:"varint,3,opt,name=modulus_size_in_bits,json=modulusSizeInBits,proto3" json:"modulus_size_in_bits,omitempty"` PublicExponent []byte `protobuf:"bytes,4,opt,name=public_exponent,json=publicExponent,proto3" json:"public_exponent,omitempty"` } func (x *JwtRsaSsaPkcs1KeyFormat) Reset() { *x = JwtRsaSsaPkcs1KeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *JwtRsaSsaPkcs1KeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*JwtRsaSsaPkcs1KeyFormat) ProtoMessage() {} func (x *JwtRsaSsaPkcs1KeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use JwtRsaSsaPkcs1KeyFormat.ProtoReflect.Descriptor instead. func (*JwtRsaSsaPkcs1KeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_rawDescGZIP(), []int{2} } func (x *JwtRsaSsaPkcs1KeyFormat) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *JwtRsaSsaPkcs1KeyFormat) GetAlgorithm() JwtRsaSsaPkcs1Algorithm { if x != nil { return x.Algorithm } return JwtRsaSsaPkcs1Algorithm_RS_UNKNOWN } func (x *JwtRsaSsaPkcs1KeyFormat) GetModulusSizeInBits() uint32 { if x != nil { return x.ModulusSizeInBits } return 0 } func (x *JwtRsaSsaPkcs1KeyFormat) GetPublicExponent() []byte { if x != nil { return x.PublicExponent } return nil } // Optional, custom kid header value to be used with "RAW" keys. // "TINK" keys with this value set will be rejected. type JwtRsaSsaPkcs1PublicKey_CustomKid struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` } func (x *JwtRsaSsaPkcs1PublicKey_CustomKid) Reset() { *x = JwtRsaSsaPkcs1PublicKey_CustomKid{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *JwtRsaSsaPkcs1PublicKey_CustomKid) String() string { return protoimpl.X.MessageStringOf(x) } func (*JwtRsaSsaPkcs1PublicKey_CustomKid) ProtoMessage() {} func (x *JwtRsaSsaPkcs1PublicKey_CustomKid) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use JwtRsaSsaPkcs1PublicKey_CustomKid.ProtoReflect.Descriptor instead. func (*JwtRsaSsaPkcs1PublicKey_CustomKid) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_rawDescGZIP(), []int{0, 0} } func (x *JwtRsaSsaPkcs1PublicKey_CustomKid) GetValue() string { if x != nil { return x.Value } return "" } var File_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto protoreflect.FileDescriptor var file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_rawDesc = []byte{ 0x0a, 0x2e, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6a, 0x77, 0x74, 0x5f, 0x72, 0x73, 0x61, 0x5f, 0x73, 0x73, 0x61, 0x5f, 0x70, 0x6b, 0x63, 0x73, 0x31, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x22, 0x93, 0x02, 0x0a, 0x17, 0x4a, 0x77, 0x74, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x6b, 0x63, 0x73, 0x31, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x49, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4a, 0x77, 0x74, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x6b, 0x63, 0x73, 0x31, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x52, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x0c, 0x0a, 0x01, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x6e, 0x12, 0x0c, 0x0a, 0x01, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x65, 0x12, 0x54, 0x0a, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6b, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4a, 0x77, 0x74, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x6b, 0x63, 0x73, 0x31, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4b, 0x69, 0x64, 0x52, 0x09, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4b, 0x69, 0x64, 0x1a, 0x21, 0x0a, 0x09, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4b, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xdc, 0x01, 0x0a, 0x18, 0x4a, 0x77, 0x74, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x6b, 0x63, 0x73, 0x31, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4a, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4a, 0x77, 0x74, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x6b, 0x63, 0x73, 0x31, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x0c, 0x0a, 0x01, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x64, 0x12, 0x0c, 0x0a, 0x01, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x70, 0x12, 0x0c, 0x0a, 0x01, 0x71, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x71, 0x12, 0x0e, 0x0a, 0x02, 0x64, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x64, 0x70, 0x12, 0x0e, 0x0a, 0x02, 0x64, 0x71, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x64, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x72, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x63, 0x72, 0x74, 0x22, 0xd8, 0x01, 0x0a, 0x17, 0x4a, 0x77, 0x74, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x6b, 0x63, 0x73, 0x31, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x49, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4a, 0x77, 0x74, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x6b, 0x63, 0x73, 0x31, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x52, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x2f, 0x0a, 0x14, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x75, 0x73, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x69, 0x6e, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x75, 0x73, 0x53, 0x69, 0x7a, 0x65, 0x49, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x65, 0x78, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x45, 0x78, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x2a, 0x4a, 0x0a, 0x17, 0x4a, 0x77, 0x74, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x6b, 0x63, 0x73, 0x31, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x0e, 0x0a, 0x0a, 0x52, 0x53, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x53, 0x32, 0x35, 0x36, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x53, 0x33, 0x38, 0x34, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x53, 0x35, 0x31, 0x32, 0x10, 0x03, 0x42, 0x58, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x72, 0x73, 0x61, 0x5f, 0x73, 0x73, 0x61, 0x5f, 0x70, 0x6b, 0x63, 0x73, 0x31, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_rawDescOnce sync.Once file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_rawDescData = file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_rawDesc ) func file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_rawDescGZIP() []byte { file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_rawDescData) }) return file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_rawDescData } var file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_goTypes = []interface{}{ (JwtRsaSsaPkcs1Algorithm)(0), // 0: google.crypto.tink.JwtRsaSsaPkcs1Algorithm (*JwtRsaSsaPkcs1PublicKey)(nil), // 1: google.crypto.tink.JwtRsaSsaPkcs1PublicKey (*JwtRsaSsaPkcs1PrivateKey)(nil), // 2: google.crypto.tink.JwtRsaSsaPkcs1PrivateKey (*JwtRsaSsaPkcs1KeyFormat)(nil), // 3: google.crypto.tink.JwtRsaSsaPkcs1KeyFormat (*JwtRsaSsaPkcs1PublicKey_CustomKid)(nil), // 4: google.crypto.tink.JwtRsaSsaPkcs1PublicKey.CustomKid } var file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_depIdxs = []int32{ 0, // 0: google.crypto.tink.JwtRsaSsaPkcs1PublicKey.algorithm:type_name -> google.crypto.tink.JwtRsaSsaPkcs1Algorithm 4, // 1: google.crypto.tink.JwtRsaSsaPkcs1PublicKey.custom_kid:type_name -> google.crypto.tink.JwtRsaSsaPkcs1PublicKey.CustomKid 1, // 2: google.crypto.tink.JwtRsaSsaPkcs1PrivateKey.public_key:type_name -> google.crypto.tink.JwtRsaSsaPkcs1PublicKey 0, // 3: google.crypto.tink.JwtRsaSsaPkcs1KeyFormat.algorithm:type_name -> google.crypto.tink.JwtRsaSsaPkcs1Algorithm 4, // [4:4] is the sub-list for method output_type 4, // [4:4] is the sub-list for method input_type 4, // [4:4] is the sub-list for extension type_name 4, // [4:4] is the sub-list for extension extendee 0, // [0:4] is the sub-list for field type_name } func init() { file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_init() } func file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_init() { if File_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JwtRsaSsaPkcs1PublicKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JwtRsaSsaPkcs1PrivateKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JwtRsaSsaPkcs1KeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JwtRsaSsaPkcs1PublicKey_CustomKid); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_rawDesc, NumEnums: 1, NumMessages: 4, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_depIdxs, EnumInfos: file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_enumTypes, MessageInfos: file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_msgTypes, }.Build() File_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto = out.File file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_rawDesc = nil file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_goTypes = nil file_third_party_tink_proto_jwt_rsa_ssa_pkcs1_proto_depIdxs = nil } ================================================ FILE: go/proto/jwt_rsa_ssa_pss_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "jwt_rsa_ssa_pss_go_proto", srcs = ["jwt_rsa_ssa_pss.pb.go"], importpath = "github.com/google/tink/go/proto/jwt_rsa_ssa_pss_go_proto", visibility = ["//visibility:public"], deps = [ "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":jwt_rsa_ssa_pss_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/jwt_rsa_ssa_pss_go_proto/jwt_rsa_ssa_pss.pb.go ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/jwt_rsa_ssa_pss.proto package jwt_rsa_ssa_pss_go_proto import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) // See https://datatracker.ietf.org/doc/html/rfc7518#section-3.5 type JwtRsaSsaPssAlgorithm int32 const ( JwtRsaSsaPssAlgorithm_PS_UNKNOWN JwtRsaSsaPssAlgorithm = 0 JwtRsaSsaPssAlgorithm_PS256 JwtRsaSsaPssAlgorithm = 1 // RSASSA-PSS using SHA-256 and MGF1 with SHA-256 JwtRsaSsaPssAlgorithm_PS384 JwtRsaSsaPssAlgorithm = 2 // RSASSA-PSS using SHA-384 and MGF1 with SHA-384 JwtRsaSsaPssAlgorithm_PS512 JwtRsaSsaPssAlgorithm = 3 // RSASSA-PSS using SHA-512 and MGF1 with SHA-512 ) // Enum value maps for JwtRsaSsaPssAlgorithm. var ( JwtRsaSsaPssAlgorithm_name = map[int32]string{ 0: "PS_UNKNOWN", 1: "PS256", 2: "PS384", 3: "PS512", } JwtRsaSsaPssAlgorithm_value = map[string]int32{ "PS_UNKNOWN": 0, "PS256": 1, "PS384": 2, "PS512": 3, } ) func (x JwtRsaSsaPssAlgorithm) Enum() *JwtRsaSsaPssAlgorithm { p := new(JwtRsaSsaPssAlgorithm) *p = x return p } func (x JwtRsaSsaPssAlgorithm) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (JwtRsaSsaPssAlgorithm) Descriptor() protoreflect.EnumDescriptor { return file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_enumTypes[0].Descriptor() } func (JwtRsaSsaPssAlgorithm) Type() protoreflect.EnumType { return &file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_enumTypes[0] } func (x JwtRsaSsaPssAlgorithm) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use JwtRsaSsaPssAlgorithm.Descriptor instead. func (JwtRsaSsaPssAlgorithm) EnumDescriptor() ([]byte, []int) { return file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_rawDescGZIP(), []int{0} } // key_type: type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPublicKey type JwtRsaSsaPssPublicKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` Algorithm JwtRsaSsaPssAlgorithm `protobuf:"varint,2,opt,name=algorithm,proto3,enum=google.crypto.tink.JwtRsaSsaPssAlgorithm" json:"algorithm,omitempty"` // Modulus. // Unsigned big integer in big-endian representation. N []byte `protobuf:"bytes,3,opt,name=n,proto3" json:"n,omitempty"` // Public exponent. // Unsigned big integer in big-endian representation. E []byte `protobuf:"bytes,4,opt,name=e,proto3" json:"e,omitempty"` CustomKid *JwtRsaSsaPssPublicKey_CustomKid `protobuf:"bytes,5,opt,name=custom_kid,json=customKid,proto3" json:"custom_kid,omitempty"` } func (x *JwtRsaSsaPssPublicKey) Reset() { *x = JwtRsaSsaPssPublicKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *JwtRsaSsaPssPublicKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*JwtRsaSsaPssPublicKey) ProtoMessage() {} func (x *JwtRsaSsaPssPublicKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use JwtRsaSsaPssPublicKey.ProtoReflect.Descriptor instead. func (*JwtRsaSsaPssPublicKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_rawDescGZIP(), []int{0} } func (x *JwtRsaSsaPssPublicKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *JwtRsaSsaPssPublicKey) GetAlgorithm() JwtRsaSsaPssAlgorithm { if x != nil { return x.Algorithm } return JwtRsaSsaPssAlgorithm_PS_UNKNOWN } func (x *JwtRsaSsaPssPublicKey) GetN() []byte { if x != nil { return x.N } return nil } func (x *JwtRsaSsaPssPublicKey) GetE() []byte { if x != nil { return x.E } return nil } func (x *JwtRsaSsaPssPublicKey) GetCustomKid() *JwtRsaSsaPssPublicKey_CustomKid { if x != nil { return x.CustomKid } return nil } // key_type: type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPrivateKey type JwtRsaSsaPssPrivateKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` PublicKey *JwtRsaSsaPssPublicKey `protobuf:"bytes,2,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` // Private exponent. // Unsigned big integer in big-endian representation. D []byte `protobuf:"bytes,3,opt,name=d,proto3" json:"d,omitempty"` // The following parameters are used to optimize RSA signature computation. // The prime factor p of n. // Unsigned big integer in big-endian representation. P []byte `protobuf:"bytes,4,opt,name=p,proto3" json:"p,omitempty"` // The prime factor q of n. // Unsigned big integer in big-endian representation. Q []byte `protobuf:"bytes,5,opt,name=q,proto3" json:"q,omitempty"` // d mod (p - 1). // Unsigned big integer in big-endian representation. Dp []byte `protobuf:"bytes,6,opt,name=dp,proto3" json:"dp,omitempty"` // d mod (q - 1). // Unsigned big integer in big-endian representation. Dq []byte `protobuf:"bytes,7,opt,name=dq,proto3" json:"dq,omitempty"` // Chinese Remainder Theorem coefficient q^(-1) mod p. // Unsigned big integer in big-endian representation. Crt []byte `protobuf:"bytes,8,opt,name=crt,proto3" json:"crt,omitempty"` } func (x *JwtRsaSsaPssPrivateKey) Reset() { *x = JwtRsaSsaPssPrivateKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *JwtRsaSsaPssPrivateKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*JwtRsaSsaPssPrivateKey) ProtoMessage() {} func (x *JwtRsaSsaPssPrivateKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use JwtRsaSsaPssPrivateKey.ProtoReflect.Descriptor instead. func (*JwtRsaSsaPssPrivateKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_rawDescGZIP(), []int{1} } func (x *JwtRsaSsaPssPrivateKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *JwtRsaSsaPssPrivateKey) GetPublicKey() *JwtRsaSsaPssPublicKey { if x != nil { return x.PublicKey } return nil } func (x *JwtRsaSsaPssPrivateKey) GetD() []byte { if x != nil { return x.D } return nil } func (x *JwtRsaSsaPssPrivateKey) GetP() []byte { if x != nil { return x.P } return nil } func (x *JwtRsaSsaPssPrivateKey) GetQ() []byte { if x != nil { return x.Q } return nil } func (x *JwtRsaSsaPssPrivateKey) GetDp() []byte { if x != nil { return x.Dp } return nil } func (x *JwtRsaSsaPssPrivateKey) GetDq() []byte { if x != nil { return x.Dq } return nil } func (x *JwtRsaSsaPssPrivateKey) GetCrt() []byte { if x != nil { return x.Crt } return nil } type JwtRsaSsaPssKeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` Algorithm JwtRsaSsaPssAlgorithm `protobuf:"varint,2,opt,name=algorithm,proto3,enum=google.crypto.tink.JwtRsaSsaPssAlgorithm" json:"algorithm,omitempty"` ModulusSizeInBits uint32 `protobuf:"varint,3,opt,name=modulus_size_in_bits,json=modulusSizeInBits,proto3" json:"modulus_size_in_bits,omitempty"` PublicExponent []byte `protobuf:"bytes,4,opt,name=public_exponent,json=publicExponent,proto3" json:"public_exponent,omitempty"` } func (x *JwtRsaSsaPssKeyFormat) Reset() { *x = JwtRsaSsaPssKeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *JwtRsaSsaPssKeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*JwtRsaSsaPssKeyFormat) ProtoMessage() {} func (x *JwtRsaSsaPssKeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use JwtRsaSsaPssKeyFormat.ProtoReflect.Descriptor instead. func (*JwtRsaSsaPssKeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_rawDescGZIP(), []int{2} } func (x *JwtRsaSsaPssKeyFormat) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *JwtRsaSsaPssKeyFormat) GetAlgorithm() JwtRsaSsaPssAlgorithm { if x != nil { return x.Algorithm } return JwtRsaSsaPssAlgorithm_PS_UNKNOWN } func (x *JwtRsaSsaPssKeyFormat) GetModulusSizeInBits() uint32 { if x != nil { return x.ModulusSizeInBits } return 0 } func (x *JwtRsaSsaPssKeyFormat) GetPublicExponent() []byte { if x != nil { return x.PublicExponent } return nil } // Optional, custom kid header value to be used with "RAW" keys. // "TINK" keys with this value set will be rejected. type JwtRsaSsaPssPublicKey_CustomKid struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` } func (x *JwtRsaSsaPssPublicKey_CustomKid) Reset() { *x = JwtRsaSsaPssPublicKey_CustomKid{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *JwtRsaSsaPssPublicKey_CustomKid) String() string { return protoimpl.X.MessageStringOf(x) } func (*JwtRsaSsaPssPublicKey_CustomKid) ProtoMessage() {} func (x *JwtRsaSsaPssPublicKey_CustomKid) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use JwtRsaSsaPssPublicKey_CustomKid.ProtoReflect.Descriptor instead. func (*JwtRsaSsaPssPublicKey_CustomKid) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_rawDescGZIP(), []int{0, 0} } func (x *JwtRsaSsaPssPublicKey_CustomKid) GetValue() string { if x != nil { return x.Value } return "" } var File_third_party_tink_proto_jwt_rsa_ssa_pss_proto protoreflect.FileDescriptor var file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_rawDesc = []byte{ 0x0a, 0x2c, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6a, 0x77, 0x74, 0x5f, 0x72, 0x73, 0x61, 0x5f, 0x73, 0x73, 0x61, 0x5f, 0x70, 0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x22, 0x8d, 0x02, 0x0a, 0x15, 0x4a, 0x77, 0x74, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x73, 0x73, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4a, 0x77, 0x74, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x73, 0x73, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x52, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x0c, 0x0a, 0x01, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x6e, 0x12, 0x0c, 0x0a, 0x01, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x65, 0x12, 0x52, 0x0a, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6b, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4a, 0x77, 0x74, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x73, 0x73, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4b, 0x69, 0x64, 0x52, 0x09, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4b, 0x69, 0x64, 0x1a, 0x21, 0x0a, 0x09, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4b, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xd8, 0x01, 0x0a, 0x16, 0x4a, 0x77, 0x74, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x73, 0x73, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x48, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4a, 0x77, 0x74, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x73, 0x73, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x0c, 0x0a, 0x01, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x64, 0x12, 0x0c, 0x0a, 0x01, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x70, 0x12, 0x0c, 0x0a, 0x01, 0x71, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x71, 0x12, 0x0e, 0x0a, 0x02, 0x64, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x64, 0x70, 0x12, 0x0e, 0x0a, 0x02, 0x64, 0x71, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x64, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x72, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x63, 0x72, 0x74, 0x22, 0xd4, 0x01, 0x0a, 0x15, 0x4a, 0x77, 0x74, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4a, 0x77, 0x74, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x73, 0x73, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x52, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x2f, 0x0a, 0x14, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x75, 0x73, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x69, 0x6e, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x75, 0x73, 0x53, 0x69, 0x7a, 0x65, 0x49, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x65, 0x78, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x45, 0x78, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x2a, 0x48, 0x0a, 0x15, 0x4a, 0x77, 0x74, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x73, 0x73, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x53, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x53, 0x32, 0x35, 0x36, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x53, 0x33, 0x38, 0x34, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x53, 0x35, 0x31, 0x32, 0x10, 0x03, 0x42, 0x5a, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x38, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6a, 0x77, 0x74, 0x5f, 0x72, 0x73, 0x61, 0x5f, 0x73, 0x73, 0x61, 0x5f, 0x70, 0x73, 0x73, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_rawDescOnce sync.Once file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_rawDescData = file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_rawDesc ) func file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_rawDescGZIP() []byte { file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_rawDescData) }) return file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_rawDescData } var file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_goTypes = []interface{}{ (JwtRsaSsaPssAlgorithm)(0), // 0: google.crypto.tink.JwtRsaSsaPssAlgorithm (*JwtRsaSsaPssPublicKey)(nil), // 1: google.crypto.tink.JwtRsaSsaPssPublicKey (*JwtRsaSsaPssPrivateKey)(nil), // 2: google.crypto.tink.JwtRsaSsaPssPrivateKey (*JwtRsaSsaPssKeyFormat)(nil), // 3: google.crypto.tink.JwtRsaSsaPssKeyFormat (*JwtRsaSsaPssPublicKey_CustomKid)(nil), // 4: google.crypto.tink.JwtRsaSsaPssPublicKey.CustomKid } var file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_depIdxs = []int32{ 0, // 0: google.crypto.tink.JwtRsaSsaPssPublicKey.algorithm:type_name -> google.crypto.tink.JwtRsaSsaPssAlgorithm 4, // 1: google.crypto.tink.JwtRsaSsaPssPublicKey.custom_kid:type_name -> google.crypto.tink.JwtRsaSsaPssPublicKey.CustomKid 1, // 2: google.crypto.tink.JwtRsaSsaPssPrivateKey.public_key:type_name -> google.crypto.tink.JwtRsaSsaPssPublicKey 0, // 3: google.crypto.tink.JwtRsaSsaPssKeyFormat.algorithm:type_name -> google.crypto.tink.JwtRsaSsaPssAlgorithm 4, // [4:4] is the sub-list for method output_type 4, // [4:4] is the sub-list for method input_type 4, // [4:4] is the sub-list for extension type_name 4, // [4:4] is the sub-list for extension extendee 0, // [0:4] is the sub-list for field type_name } func init() { file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_init() } func file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_init() { if File_third_party_tink_proto_jwt_rsa_ssa_pss_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JwtRsaSsaPssPublicKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JwtRsaSsaPssPrivateKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JwtRsaSsaPssKeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JwtRsaSsaPssPublicKey_CustomKid); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_rawDesc, NumEnums: 1, NumMessages: 4, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_depIdxs, EnumInfos: file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_enumTypes, MessageInfos: file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_msgTypes, }.Build() File_third_party_tink_proto_jwt_rsa_ssa_pss_proto = out.File file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_rawDesc = nil file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_goTypes = nil file_third_party_tink_proto_jwt_rsa_ssa_pss_proto_depIdxs = nil } ================================================ FILE: go/proto/kms_aead_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "kms_aead_go_proto", srcs = ["kms_aead.pb.go"], importpath = "github.com/google/tink/go/proto/kms_aead_go_proto", visibility = ["//visibility:public"], deps = [ "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":kms_aead_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/kms_aead_go_proto/kms_aead.pb.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/kms_aead.proto package kms_aead_go_proto import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type KmsAeadKeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required. // The location of a KMS key. // With Google Cloud KMS, valid values have this format: // gcp-kms://projects/*/locations/*/keyRings/*/cryptoKeys/*. // With AWS KMS, valid values have this format: // aws-kms://arn:aws:kms:<region>:<account-id>:key/<key-id> KeyUri string `protobuf:"bytes,1,opt,name=key_uri,json=keyUri,proto3" json:"key_uri,omitempty"` } func (x *KmsAeadKeyFormat) Reset() { *x = KmsAeadKeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_kms_aead_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *KmsAeadKeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*KmsAeadKeyFormat) ProtoMessage() {} func (x *KmsAeadKeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_kms_aead_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use KmsAeadKeyFormat.ProtoReflect.Descriptor instead. func (*KmsAeadKeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_kms_aead_proto_rawDescGZIP(), []int{0} } func (x *KmsAeadKeyFormat) GetKeyUri() string { if x != nil { return x.KeyUri } return "" } // There is no actual key material in the key. type KmsAeadKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` // The key format also contains the params. Params *KmsAeadKeyFormat `protobuf:"bytes,2,opt,name=params,proto3" json:"params,omitempty"` } func (x *KmsAeadKey) Reset() { *x = KmsAeadKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_kms_aead_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *KmsAeadKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*KmsAeadKey) ProtoMessage() {} func (x *KmsAeadKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_kms_aead_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use KmsAeadKey.ProtoReflect.Descriptor instead. func (*KmsAeadKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_kms_aead_proto_rawDescGZIP(), []int{1} } func (x *KmsAeadKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *KmsAeadKey) GetParams() *KmsAeadKeyFormat { if x != nil { return x.Params } return nil } var File_third_party_tink_proto_kms_aead_proto protoreflect.FileDescriptor var file_third_party_tink_proto_kms_aead_proto_rawDesc = []byte{ 0x0a, 0x25, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6b, 0x6d, 0x73, 0x5f, 0x61, 0x65, 0x61, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x22, 0x2b, 0x0a, 0x10, 0x4b, 0x6d, 0x73, 0x41, 0x65, 0x61, 0x64, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6b, 0x65, 0x79, 0x55, 0x72, 0x69, 0x22, 0x64, 0x0a, 0x0a, 0x4b, 0x6d, 0x73, 0x41, 0x65, 0x61, 0x64, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3c, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4b, 0x6d, 0x73, 0x41, 0x65, 0x61, 0x64, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0x53, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6b, 0x6d, 0x73, 0x5f, 0x61, 0x65, 0x61, 0x64, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_kms_aead_proto_rawDescOnce sync.Once file_third_party_tink_proto_kms_aead_proto_rawDescData = file_third_party_tink_proto_kms_aead_proto_rawDesc ) func file_third_party_tink_proto_kms_aead_proto_rawDescGZIP() []byte { file_third_party_tink_proto_kms_aead_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_kms_aead_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_kms_aead_proto_rawDescData) }) return file_third_party_tink_proto_kms_aead_proto_rawDescData } var file_third_party_tink_proto_kms_aead_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_third_party_tink_proto_kms_aead_proto_goTypes = []interface{}{ (*KmsAeadKeyFormat)(nil), // 0: google.crypto.tink.KmsAeadKeyFormat (*KmsAeadKey)(nil), // 1: google.crypto.tink.KmsAeadKey } var file_third_party_tink_proto_kms_aead_proto_depIdxs = []int32{ 0, // 0: google.crypto.tink.KmsAeadKey.params:type_name -> google.crypto.tink.KmsAeadKeyFormat 1, // [1:1] is the sub-list for method output_type 1, // [1:1] is the sub-list for method input_type 1, // [1:1] is the sub-list for extension type_name 1, // [1:1] is the sub-list for extension extendee 0, // [0:1] is the sub-list for field type_name } func init() { file_third_party_tink_proto_kms_aead_proto_init() } func file_third_party_tink_proto_kms_aead_proto_init() { if File_third_party_tink_proto_kms_aead_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_kms_aead_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*KmsAeadKeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_kms_aead_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*KmsAeadKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_kms_aead_proto_rawDesc, NumEnums: 0, NumMessages: 2, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_kms_aead_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_kms_aead_proto_depIdxs, MessageInfos: file_third_party_tink_proto_kms_aead_proto_msgTypes, }.Build() File_third_party_tink_proto_kms_aead_proto = out.File file_third_party_tink_proto_kms_aead_proto_rawDesc = nil file_third_party_tink_proto_kms_aead_proto_goTypes = nil file_third_party_tink_proto_kms_aead_proto_depIdxs = nil } ================================================ FILE: go/proto/kms_envelope_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "kms_envelope_go_proto", srcs = ["kms_envelope.pb.go"], importpath = "github.com/google/tink/go/proto/kms_envelope_go_proto", visibility = ["//visibility:public"], deps = [ "//proto/tink_go_proto", "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":kms_envelope_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/kms_envelope_go_proto/kms_envelope.pb.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/kms_envelope.proto package kms_envelope_go_proto import ( tink_go_proto "github.com/google/tink/go/proto/tink_go_proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type KmsEnvelopeAeadKeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required. // The location of the KEK in a remote KMS. // With Google Cloud KMS, valid values have this format: // gcp-kms://projects/*/locations/*/keyRings/*/cryptoKeys/*. // With AWS KMS, valid values have this format: // aws-kms://arn:aws:kms:<region>:<account-id>:key/<key-id> KekUri string `protobuf:"bytes,1,opt,name=kek_uri,json=kekUri,proto3" json:"kek_uri,omitempty"` // Key template of the Data Encryption Key, e.g., AesCtrHmacAeadKeyFormat. // Required. DekTemplate *tink_go_proto.KeyTemplate `protobuf:"bytes,2,opt,name=dek_template,json=dekTemplate,proto3" json:"dek_template,omitempty"` } func (x *KmsEnvelopeAeadKeyFormat) Reset() { *x = KmsEnvelopeAeadKeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_kms_envelope_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *KmsEnvelopeAeadKeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*KmsEnvelopeAeadKeyFormat) ProtoMessage() {} func (x *KmsEnvelopeAeadKeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_kms_envelope_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use KmsEnvelopeAeadKeyFormat.ProtoReflect.Descriptor instead. func (*KmsEnvelopeAeadKeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_kms_envelope_proto_rawDescGZIP(), []int{0} } func (x *KmsEnvelopeAeadKeyFormat) GetKekUri() string { if x != nil { return x.KekUri } return "" } func (x *KmsEnvelopeAeadKeyFormat) GetDekTemplate() *tink_go_proto.KeyTemplate { if x != nil { return x.DekTemplate } return nil } // There is no actual key material in the key. type KmsEnvelopeAeadKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` // The key format also contains the params. Params *KmsEnvelopeAeadKeyFormat `protobuf:"bytes,2,opt,name=params,proto3" json:"params,omitempty"` } func (x *KmsEnvelopeAeadKey) Reset() { *x = KmsEnvelopeAeadKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_kms_envelope_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *KmsEnvelopeAeadKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*KmsEnvelopeAeadKey) ProtoMessage() {} func (x *KmsEnvelopeAeadKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_kms_envelope_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use KmsEnvelopeAeadKey.ProtoReflect.Descriptor instead. func (*KmsEnvelopeAeadKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_kms_envelope_proto_rawDescGZIP(), []int{1} } func (x *KmsEnvelopeAeadKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *KmsEnvelopeAeadKey) GetParams() *KmsEnvelopeAeadKeyFormat { if x != nil { return x.Params } return nil } var File_third_party_tink_proto_kms_envelope_proto protoreflect.FileDescriptor var file_third_party_tink_proto_kms_envelope_proto_rawDesc = []byte{ 0x0a, 0x29, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6b, 0x6d, 0x73, 0x5f, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x1a, 0x21, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x77, 0x0a, 0x18, 0x4b, 0x6d, 0x73, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x41, 0x65, 0x61, 0x64, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x6b, 0x65, 0x6b, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6b, 0x65, 0x6b, 0x55, 0x72, 0x69, 0x12, 0x42, 0x0a, 0x0c, 0x64, 0x65, 0x6b, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4b, 0x65, 0x79, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x64, 0x65, 0x6b, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0x74, 0x0a, 0x12, 0x4b, 0x6d, 0x73, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x41, 0x65, 0x61, 0x64, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x44, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4b, 0x6d, 0x73, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x41, 0x65, 0x61, 0x64, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0x57, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6b, 0x6d, 0x73, 0x5f, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_kms_envelope_proto_rawDescOnce sync.Once file_third_party_tink_proto_kms_envelope_proto_rawDescData = file_third_party_tink_proto_kms_envelope_proto_rawDesc ) func file_third_party_tink_proto_kms_envelope_proto_rawDescGZIP() []byte { file_third_party_tink_proto_kms_envelope_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_kms_envelope_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_kms_envelope_proto_rawDescData) }) return file_third_party_tink_proto_kms_envelope_proto_rawDescData } var file_third_party_tink_proto_kms_envelope_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_third_party_tink_proto_kms_envelope_proto_goTypes = []interface{}{ (*KmsEnvelopeAeadKeyFormat)(nil), // 0: google.crypto.tink.KmsEnvelopeAeadKeyFormat (*KmsEnvelopeAeadKey)(nil), // 1: google.crypto.tink.KmsEnvelopeAeadKey (*tink_go_proto.KeyTemplate)(nil), // 2: google.crypto.tink.KeyTemplate } var file_third_party_tink_proto_kms_envelope_proto_depIdxs = []int32{ 2, // 0: google.crypto.tink.KmsEnvelopeAeadKeyFormat.dek_template:type_name -> google.crypto.tink.KeyTemplate 0, // 1: google.crypto.tink.KmsEnvelopeAeadKey.params:type_name -> google.crypto.tink.KmsEnvelopeAeadKeyFormat 2, // [2:2] is the sub-list for method output_type 2, // [2:2] is the sub-list for method input_type 2, // [2:2] is the sub-list for extension type_name 2, // [2:2] is the sub-list for extension extendee 0, // [0:2] is the sub-list for field type_name } func init() { file_third_party_tink_proto_kms_envelope_proto_init() } func file_third_party_tink_proto_kms_envelope_proto_init() { if File_third_party_tink_proto_kms_envelope_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_kms_envelope_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*KmsEnvelopeAeadKeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_kms_envelope_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*KmsEnvelopeAeadKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_kms_envelope_proto_rawDesc, NumEnums: 0, NumMessages: 2, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_kms_envelope_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_kms_envelope_proto_depIdxs, MessageInfos: file_third_party_tink_proto_kms_envelope_proto_msgTypes, }.Build() File_third_party_tink_proto_kms_envelope_proto = out.File file_third_party_tink_proto_kms_envelope_proto_rawDesc = nil file_third_party_tink_proto_kms_envelope_proto_goTypes = nil file_third_party_tink_proto_kms_envelope_proto_depIdxs = nil } ================================================ FILE: go/proto/prf_based_deriver_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "prf_based_deriver_go_proto", srcs = ["prf_based_deriver.pb.go"], importpath = "github.com/google/tink/go/proto/prf_based_deriver_go_proto", visibility = ["//visibility:public"], deps = [ "//proto/tink_go_proto", "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":prf_based_deriver_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/prf_based_deriver_go_proto/prf_based_deriver.pb.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/prf_based_deriver.proto package prf_based_deriver_go_proto import ( tink_go_proto "github.com/google/tink/go/proto/tink_go_proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type PrfBasedDeriverParams struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields DerivedKeyTemplate *tink_go_proto.KeyTemplate `protobuf:"bytes,1,opt,name=derived_key_template,json=derivedKeyTemplate,proto3" json:"derived_key_template,omitempty"` } func (x *PrfBasedDeriverParams) Reset() { *x = PrfBasedDeriverParams{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_prf_based_deriver_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *PrfBasedDeriverParams) String() string { return protoimpl.X.MessageStringOf(x) } func (*PrfBasedDeriverParams) ProtoMessage() {} func (x *PrfBasedDeriverParams) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_prf_based_deriver_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use PrfBasedDeriverParams.ProtoReflect.Descriptor instead. func (*PrfBasedDeriverParams) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_prf_based_deriver_proto_rawDescGZIP(), []int{0} } func (x *PrfBasedDeriverParams) GetDerivedKeyTemplate() *tink_go_proto.KeyTemplate { if x != nil { return x.DerivedKeyTemplate } return nil } type PrfBasedDeriverKeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields PrfKeyTemplate *tink_go_proto.KeyTemplate `protobuf:"bytes,1,opt,name=prf_key_template,json=prfKeyTemplate,proto3" json:"prf_key_template,omitempty"` Params *PrfBasedDeriverParams `protobuf:"bytes,2,opt,name=params,proto3" json:"params,omitempty"` } func (x *PrfBasedDeriverKeyFormat) Reset() { *x = PrfBasedDeriverKeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_prf_based_deriver_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *PrfBasedDeriverKeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*PrfBasedDeriverKeyFormat) ProtoMessage() {} func (x *PrfBasedDeriverKeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_prf_based_deriver_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use PrfBasedDeriverKeyFormat.ProtoReflect.Descriptor instead. func (*PrfBasedDeriverKeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_prf_based_deriver_proto_rawDescGZIP(), []int{1} } func (x *PrfBasedDeriverKeyFormat) GetPrfKeyTemplate() *tink_go_proto.KeyTemplate { if x != nil { return x.PrfKeyTemplate } return nil } func (x *PrfBasedDeriverKeyFormat) GetParams() *PrfBasedDeriverParams { if x != nil { return x.Params } return nil } // key_type: type.googleapis.com/google.crypto.tink.PrfBasedDeriverKey type PrfBasedDeriverKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` PrfKey *tink_go_proto.KeyData `protobuf:"bytes,2,opt,name=prf_key,json=prfKey,proto3" json:"prf_key,omitempty"` Params *PrfBasedDeriverParams `protobuf:"bytes,3,opt,name=params,proto3" json:"params,omitempty"` } func (x *PrfBasedDeriverKey) Reset() { *x = PrfBasedDeriverKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_prf_based_deriver_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *PrfBasedDeriverKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*PrfBasedDeriverKey) ProtoMessage() {} func (x *PrfBasedDeriverKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_prf_based_deriver_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use PrfBasedDeriverKey.ProtoReflect.Descriptor instead. func (*PrfBasedDeriverKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_prf_based_deriver_proto_rawDescGZIP(), []int{2} } func (x *PrfBasedDeriverKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *PrfBasedDeriverKey) GetPrfKey() *tink_go_proto.KeyData { if x != nil { return x.PrfKey } return nil } func (x *PrfBasedDeriverKey) GetParams() *PrfBasedDeriverParams { if x != nil { return x.Params } return nil } var File_third_party_tink_proto_prf_based_deriver_proto protoreflect.FileDescriptor var file_third_party_tink_proto_prf_based_deriver_proto_rawDesc = []byte{ 0x0a, 0x2e, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x66, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x64, 0x5f, 0x64, 0x65, 0x72, 0x69, 0x76, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x1a, 0x21, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6a, 0x0a, 0x15, 0x50, 0x72, 0x66, 0x42, 0x61, 0x73, 0x65, 0x64, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x72, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x51, 0x0a, 0x14, 0x64, 0x65, 0x72, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4b, 0x65, 0x79, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x12, 0x64, 0x65, 0x72, 0x69, 0x76, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0xa8, 0x01, 0x0a, 0x18, 0x50, 0x72, 0x66, 0x42, 0x61, 0x73, 0x65, 0x64, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x49, 0x0a, 0x10, 0x70, 0x72, 0x66, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4b, 0x65, 0x79, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x0e, 0x70, 0x72, 0x66, 0x4b, 0x65, 0x79, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x41, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x50, 0x72, 0x66, 0x42, 0x61, 0x73, 0x65, 0x64, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x72, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0xa7, 0x01, 0x0a, 0x12, 0x50, 0x72, 0x66, 0x42, 0x61, 0x73, 0x65, 0x64, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, 0x07, 0x70, 0x72, 0x66, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4b, 0x65, 0x79, 0x44, 0x61, 0x74, 0x61, 0x52, 0x06, 0x70, 0x72, 0x66, 0x4b, 0x65, 0x79, 0x12, 0x41, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x50, 0x72, 0x66, 0x42, 0x61, 0x73, 0x65, 0x64, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x72, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0x5c, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x66, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x64, 0x5f, 0x64, 0x65, 0x72, 0x69, 0x76, 0x65, 0x72, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_prf_based_deriver_proto_rawDescOnce sync.Once file_third_party_tink_proto_prf_based_deriver_proto_rawDescData = file_third_party_tink_proto_prf_based_deriver_proto_rawDesc ) func file_third_party_tink_proto_prf_based_deriver_proto_rawDescGZIP() []byte { file_third_party_tink_proto_prf_based_deriver_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_prf_based_deriver_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_prf_based_deriver_proto_rawDescData) }) return file_third_party_tink_proto_prf_based_deriver_proto_rawDescData } var file_third_party_tink_proto_prf_based_deriver_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_third_party_tink_proto_prf_based_deriver_proto_goTypes = []interface{}{ (*PrfBasedDeriverParams)(nil), // 0: google.crypto.tink.PrfBasedDeriverParams (*PrfBasedDeriverKeyFormat)(nil), // 1: google.crypto.tink.PrfBasedDeriverKeyFormat (*PrfBasedDeriverKey)(nil), // 2: google.crypto.tink.PrfBasedDeriverKey (*tink_go_proto.KeyTemplate)(nil), // 3: google.crypto.tink.KeyTemplate (*tink_go_proto.KeyData)(nil), // 4: google.crypto.tink.KeyData } var file_third_party_tink_proto_prf_based_deriver_proto_depIdxs = []int32{ 3, // 0: google.crypto.tink.PrfBasedDeriverParams.derived_key_template:type_name -> google.crypto.tink.KeyTemplate 3, // 1: google.crypto.tink.PrfBasedDeriverKeyFormat.prf_key_template:type_name -> google.crypto.tink.KeyTemplate 0, // 2: google.crypto.tink.PrfBasedDeriverKeyFormat.params:type_name -> google.crypto.tink.PrfBasedDeriverParams 4, // 3: google.crypto.tink.PrfBasedDeriverKey.prf_key:type_name -> google.crypto.tink.KeyData 0, // 4: google.crypto.tink.PrfBasedDeriverKey.params:type_name -> google.crypto.tink.PrfBasedDeriverParams 5, // [5:5] is the sub-list for method output_type 5, // [5:5] is the sub-list for method input_type 5, // [5:5] is the sub-list for extension type_name 5, // [5:5] is the sub-list for extension extendee 0, // [0:5] is the sub-list for field type_name } func init() { file_third_party_tink_proto_prf_based_deriver_proto_init() } func file_third_party_tink_proto_prf_based_deriver_proto_init() { if File_third_party_tink_proto_prf_based_deriver_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_prf_based_deriver_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PrfBasedDeriverParams); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_prf_based_deriver_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PrfBasedDeriverKeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_prf_based_deriver_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PrfBasedDeriverKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_prf_based_deriver_proto_rawDesc, NumEnums: 0, NumMessages: 3, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_prf_based_deriver_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_prf_based_deriver_proto_depIdxs, MessageInfos: file_third_party_tink_proto_prf_based_deriver_proto_msgTypes, }.Build() File_third_party_tink_proto_prf_based_deriver_proto = out.File file_third_party_tink_proto_prf_based_deriver_proto_rawDesc = nil file_third_party_tink_proto_prf_based_deriver_proto_goTypes = nil file_third_party_tink_proto_prf_based_deriver_proto_depIdxs = nil } ================================================ FILE: go/proto/rsa_ssa_pkcs1_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "rsa_ssa_pkcs1_go_proto", srcs = ["rsa_ssa_pkcs1.pb.go"], importpath = "github.com/google/tink/go/proto/rsa_ssa_pkcs1_go_proto", visibility = ["//visibility:public"], deps = [ "//proto/common_go_proto", "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":rsa_ssa_pkcs1_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/rsa_ssa_pkcs1_go_proto/rsa_ssa_pkcs1.pb.go ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Definitions for RSA SSA (Signature Schemes with Appendix) using PKCS1-v1_5 // encoding (https://tools.ietf.org/html/rfc8017#section-8.2). // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/rsa_ssa_pkcs1.proto package rsa_ssa_pkcs1_go_proto import ( common_go_proto "github.com/google/tink/go/proto/common_go_proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type RsaSsaPkcs1Params struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Hash function used in computing hash of the signing message // (see https://tools.ietf.org/html/rfc8017#section-9.2). // Required. HashType common_go_proto.HashType `protobuf:"varint,1,opt,name=hash_type,json=hashType,proto3,enum=google.crypto.tink.HashType" json:"hash_type,omitempty"` } func (x *RsaSsaPkcs1Params) Reset() { *x = RsaSsaPkcs1Params{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_rsa_ssa_pkcs1_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *RsaSsaPkcs1Params) String() string { return protoimpl.X.MessageStringOf(x) } func (*RsaSsaPkcs1Params) ProtoMessage() {} func (x *RsaSsaPkcs1Params) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_rsa_ssa_pkcs1_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use RsaSsaPkcs1Params.ProtoReflect.Descriptor instead. func (*RsaSsaPkcs1Params) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_rsa_ssa_pkcs1_proto_rawDescGZIP(), []int{0} } func (x *RsaSsaPkcs1Params) GetHashType() common_go_proto.HashType { if x != nil { return x.HashType } return common_go_proto.HashType(0) } // key_type: type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PublicKey type RsaSsaPkcs1PublicKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required. Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` // Required. Params *RsaSsaPkcs1Params `protobuf:"bytes,2,opt,name=params,proto3" json:"params,omitempty"` // Modulus. // Unsigned big integer in bigendian representation. N []byte `protobuf:"bytes,3,opt,name=n,proto3" json:"n,omitempty"` // Public exponent. // Unsigned big integer in bigendian representation. E []byte `protobuf:"bytes,4,opt,name=e,proto3" json:"e,omitempty"` } func (x *RsaSsaPkcs1PublicKey) Reset() { *x = RsaSsaPkcs1PublicKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_rsa_ssa_pkcs1_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *RsaSsaPkcs1PublicKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*RsaSsaPkcs1PublicKey) ProtoMessage() {} func (x *RsaSsaPkcs1PublicKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_rsa_ssa_pkcs1_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use RsaSsaPkcs1PublicKey.ProtoReflect.Descriptor instead. func (*RsaSsaPkcs1PublicKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_rsa_ssa_pkcs1_proto_rawDescGZIP(), []int{1} } func (x *RsaSsaPkcs1PublicKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *RsaSsaPkcs1PublicKey) GetParams() *RsaSsaPkcs1Params { if x != nil { return x.Params } return nil } func (x *RsaSsaPkcs1PublicKey) GetN() []byte { if x != nil { return x.N } return nil } func (x *RsaSsaPkcs1PublicKey) GetE() []byte { if x != nil { return x.E } return nil } // key_type: type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PrivateKey type RsaSsaPkcs1PrivateKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required. Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` // Required. PublicKey *RsaSsaPkcs1PublicKey `protobuf:"bytes,2,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` // Private exponent. // Unsigned big integer in bigendian representation. // Required. D []byte `protobuf:"bytes,3,opt,name=d,proto3" json:"d,omitempty"` // The following parameters are used to optimize RSA signature computation. // The prime factor p of n. // Unsigned big integer in bigendian representation. // Required. P []byte `protobuf:"bytes,4,opt,name=p,proto3" json:"p,omitempty"` // The prime factor q of n. // Unsigned big integer in bigendian representation. // Required. Q []byte `protobuf:"bytes,5,opt,name=q,proto3" json:"q,omitempty"` // d mod (p - 1). // Unsigned big integer in bigendian representation. // Required. Dp []byte `protobuf:"bytes,6,opt,name=dp,proto3" json:"dp,omitempty"` // d mod (q - 1). // Unsigned big integer in bigendian representation. // Required. Dq []byte `protobuf:"bytes,7,opt,name=dq,proto3" json:"dq,omitempty"` // Chinese Remainder Theorem coefficient q^(-1) mod p. // Unsigned big integer in bigendian representation. // Required. Crt []byte `protobuf:"bytes,8,opt,name=crt,proto3" json:"crt,omitempty"` } func (x *RsaSsaPkcs1PrivateKey) Reset() { *x = RsaSsaPkcs1PrivateKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_rsa_ssa_pkcs1_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *RsaSsaPkcs1PrivateKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*RsaSsaPkcs1PrivateKey) ProtoMessage() {} func (x *RsaSsaPkcs1PrivateKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_rsa_ssa_pkcs1_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use RsaSsaPkcs1PrivateKey.ProtoReflect.Descriptor instead. func (*RsaSsaPkcs1PrivateKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_rsa_ssa_pkcs1_proto_rawDescGZIP(), []int{2} } func (x *RsaSsaPkcs1PrivateKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *RsaSsaPkcs1PrivateKey) GetPublicKey() *RsaSsaPkcs1PublicKey { if x != nil { return x.PublicKey } return nil } func (x *RsaSsaPkcs1PrivateKey) GetD() []byte { if x != nil { return x.D } return nil } func (x *RsaSsaPkcs1PrivateKey) GetP() []byte { if x != nil { return x.P } return nil } func (x *RsaSsaPkcs1PrivateKey) GetQ() []byte { if x != nil { return x.Q } return nil } func (x *RsaSsaPkcs1PrivateKey) GetDp() []byte { if x != nil { return x.Dp } return nil } func (x *RsaSsaPkcs1PrivateKey) GetDq() []byte { if x != nil { return x.Dq } return nil } func (x *RsaSsaPkcs1PrivateKey) GetCrt() []byte { if x != nil { return x.Crt } return nil } type RsaSsaPkcs1KeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required. Params *RsaSsaPkcs1Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params,omitempty"` // Required. ModulusSizeInBits uint32 `protobuf:"varint,2,opt,name=modulus_size_in_bits,json=modulusSizeInBits,proto3" json:"modulus_size_in_bits,omitempty"` // Required. PublicExponent []byte `protobuf:"bytes,3,opt,name=public_exponent,json=publicExponent,proto3" json:"public_exponent,omitempty"` } func (x *RsaSsaPkcs1KeyFormat) Reset() { *x = RsaSsaPkcs1KeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_rsa_ssa_pkcs1_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *RsaSsaPkcs1KeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*RsaSsaPkcs1KeyFormat) ProtoMessage() {} func (x *RsaSsaPkcs1KeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_rsa_ssa_pkcs1_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use RsaSsaPkcs1KeyFormat.ProtoReflect.Descriptor instead. func (*RsaSsaPkcs1KeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_rsa_ssa_pkcs1_proto_rawDescGZIP(), []int{3} } func (x *RsaSsaPkcs1KeyFormat) GetParams() *RsaSsaPkcs1Params { if x != nil { return x.Params } return nil } func (x *RsaSsaPkcs1KeyFormat) GetModulusSizeInBits() uint32 { if x != nil { return x.ModulusSizeInBits } return 0 } func (x *RsaSsaPkcs1KeyFormat) GetPublicExponent() []byte { if x != nil { return x.PublicExponent } return nil } var File_third_party_tink_proto_rsa_ssa_pkcs1_proto protoreflect.FileDescriptor var file_third_party_tink_proto_rsa_ssa_pkcs1_proto_rawDesc = []byte{ 0x0a, 0x2a, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x72, 0x73, 0x61, 0x5f, 0x73, 0x73, 0x61, 0x5f, 0x70, 0x6b, 0x63, 0x73, 0x31, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x1a, 0x23, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x4e, 0x0a, 0x11, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x6b, 0x63, 0x73, 0x31, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x39, 0x0a, 0x09, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x68, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x22, 0x8b, 0x01, 0x0a, 0x14, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x6b, 0x63, 0x73, 0x31, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3d, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x6b, 0x63, 0x73, 0x31, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x0c, 0x0a, 0x01, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x6e, 0x12, 0x0c, 0x0a, 0x01, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x65, 0x22, 0xd6, 0x01, 0x0a, 0x15, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x6b, 0x63, 0x73, 0x31, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x6b, 0x63, 0x73, 0x31, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x0c, 0x0a, 0x01, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x64, 0x12, 0x0c, 0x0a, 0x01, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x70, 0x12, 0x0c, 0x0a, 0x01, 0x71, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x71, 0x12, 0x0e, 0x0a, 0x02, 0x64, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x64, 0x70, 0x12, 0x0e, 0x0a, 0x02, 0x64, 0x71, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x64, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x72, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x63, 0x72, 0x74, 0x22, 0xaf, 0x01, 0x0a, 0x14, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x6b, 0x63, 0x73, 0x31, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x3d, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x6b, 0x63, 0x73, 0x31, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2f, 0x0a, 0x14, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x75, 0x73, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x69, 0x6e, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x75, 0x73, 0x53, 0x69, 0x7a, 0x65, 0x49, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x65, 0x78, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x45, 0x78, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x42, 0x58, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x72, 0x73, 0x61, 0x5f, 0x73, 0x73, 0x61, 0x5f, 0x70, 0x6b, 0x63, 0x73, 0x31, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_rsa_ssa_pkcs1_proto_rawDescOnce sync.Once file_third_party_tink_proto_rsa_ssa_pkcs1_proto_rawDescData = file_third_party_tink_proto_rsa_ssa_pkcs1_proto_rawDesc ) func file_third_party_tink_proto_rsa_ssa_pkcs1_proto_rawDescGZIP() []byte { file_third_party_tink_proto_rsa_ssa_pkcs1_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_rsa_ssa_pkcs1_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_rsa_ssa_pkcs1_proto_rawDescData) }) return file_third_party_tink_proto_rsa_ssa_pkcs1_proto_rawDescData } var file_third_party_tink_proto_rsa_ssa_pkcs1_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_third_party_tink_proto_rsa_ssa_pkcs1_proto_goTypes = []interface{}{ (*RsaSsaPkcs1Params)(nil), // 0: google.crypto.tink.RsaSsaPkcs1Params (*RsaSsaPkcs1PublicKey)(nil), // 1: google.crypto.tink.RsaSsaPkcs1PublicKey (*RsaSsaPkcs1PrivateKey)(nil), // 2: google.crypto.tink.RsaSsaPkcs1PrivateKey (*RsaSsaPkcs1KeyFormat)(nil), // 3: google.crypto.tink.RsaSsaPkcs1KeyFormat (common_go_proto.HashType)(0), // 4: google.crypto.tink.HashType } var file_third_party_tink_proto_rsa_ssa_pkcs1_proto_depIdxs = []int32{ 4, // 0: google.crypto.tink.RsaSsaPkcs1Params.hash_type:type_name -> google.crypto.tink.HashType 0, // 1: google.crypto.tink.RsaSsaPkcs1PublicKey.params:type_name -> google.crypto.tink.RsaSsaPkcs1Params 1, // 2: google.crypto.tink.RsaSsaPkcs1PrivateKey.public_key:type_name -> google.crypto.tink.RsaSsaPkcs1PublicKey 0, // 3: google.crypto.tink.RsaSsaPkcs1KeyFormat.params:type_name -> google.crypto.tink.RsaSsaPkcs1Params 4, // [4:4] is the sub-list for method output_type 4, // [4:4] is the sub-list for method input_type 4, // [4:4] is the sub-list for extension type_name 4, // [4:4] is the sub-list for extension extendee 0, // [0:4] is the sub-list for field type_name } func init() { file_third_party_tink_proto_rsa_ssa_pkcs1_proto_init() } func file_third_party_tink_proto_rsa_ssa_pkcs1_proto_init() { if File_third_party_tink_proto_rsa_ssa_pkcs1_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_rsa_ssa_pkcs1_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RsaSsaPkcs1Params); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_rsa_ssa_pkcs1_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RsaSsaPkcs1PublicKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_rsa_ssa_pkcs1_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RsaSsaPkcs1PrivateKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_rsa_ssa_pkcs1_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RsaSsaPkcs1KeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_rsa_ssa_pkcs1_proto_rawDesc, NumEnums: 0, NumMessages: 4, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_rsa_ssa_pkcs1_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_rsa_ssa_pkcs1_proto_depIdxs, MessageInfos: file_third_party_tink_proto_rsa_ssa_pkcs1_proto_msgTypes, }.Build() File_third_party_tink_proto_rsa_ssa_pkcs1_proto = out.File file_third_party_tink_proto_rsa_ssa_pkcs1_proto_rawDesc = nil file_third_party_tink_proto_rsa_ssa_pkcs1_proto_goTypes = nil file_third_party_tink_proto_rsa_ssa_pkcs1_proto_depIdxs = nil } ================================================ FILE: go/proto/rsa_ssa_pss_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "rsa_ssa_pss_go_proto", srcs = ["rsa_ssa_pss.pb.go"], importpath = "github.com/google/tink/go/proto/rsa_ssa_pss_go_proto", visibility = ["//visibility:public"], deps = [ "//proto/common_go_proto", "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":rsa_ssa_pss_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/rsa_ssa_pss_go_proto/rsa_ssa_pss.pb.go ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Definitions for RSA SSA (Signature Schemes with Appendix) using PSS // (Probabilistic Signature Scheme ) encoding // (https://tools.ietf.org/html/rfc8017#section-8.1). // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/rsa_ssa_pss.proto package rsa_ssa_pss_go_proto import ( common_go_proto "github.com/google/tink/go/proto/common_go_proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type RsaSsaPssParams struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Hash function used in computing hash of the signing message // (see https://tools.ietf.org/html/rfc8017#section-9.1.1). // Required. SigHash common_go_proto.HashType `protobuf:"varint,1,opt,name=sig_hash,json=sigHash,proto3,enum=google.crypto.tink.HashType" json:"sig_hash,omitempty"` // Hash function used in MGF1 (a mask generation function based on a // hash function) (see https://tools.ietf.org/html/rfc8017#appendix-B.2.1). // Required. Mgf1Hash common_go_proto.HashType `protobuf:"varint,2,opt,name=mgf1_hash,json=mgf1Hash,proto3,enum=google.crypto.tink.HashType" json:"mgf1_hash,omitempty"` // Salt length (see https://tools.ietf.org/html/rfc8017#section-9.1.1) // Required. SaltLength int32 `protobuf:"varint,3,opt,name=salt_length,json=saltLength,proto3" json:"salt_length,omitempty"` } func (x *RsaSsaPssParams) Reset() { *x = RsaSsaPssParams{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_rsa_ssa_pss_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *RsaSsaPssParams) String() string { return protoimpl.X.MessageStringOf(x) } func (*RsaSsaPssParams) ProtoMessage() {} func (x *RsaSsaPssParams) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_rsa_ssa_pss_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use RsaSsaPssParams.ProtoReflect.Descriptor instead. func (*RsaSsaPssParams) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_rsa_ssa_pss_proto_rawDescGZIP(), []int{0} } func (x *RsaSsaPssParams) GetSigHash() common_go_proto.HashType { if x != nil { return x.SigHash } return common_go_proto.HashType(0) } func (x *RsaSsaPssParams) GetMgf1Hash() common_go_proto.HashType { if x != nil { return x.Mgf1Hash } return common_go_proto.HashType(0) } func (x *RsaSsaPssParams) GetSaltLength() int32 { if x != nil { return x.SaltLength } return 0 } // key_type: type.googleapis.com/google.crypto.tink.RsaSsaPssPublicKey type RsaSsaPssPublicKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required. Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` // Required. Params *RsaSsaPssParams `protobuf:"bytes,2,opt,name=params,proto3" json:"params,omitempty"` // Modulus. // Unsigned big integer in bigendian representation. N []byte `protobuf:"bytes,3,opt,name=n,proto3" json:"n,omitempty"` // Public exponent. // Unsigned big integer in bigendian representation. E []byte `protobuf:"bytes,4,opt,name=e,proto3" json:"e,omitempty"` } func (x *RsaSsaPssPublicKey) Reset() { *x = RsaSsaPssPublicKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_rsa_ssa_pss_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *RsaSsaPssPublicKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*RsaSsaPssPublicKey) ProtoMessage() {} func (x *RsaSsaPssPublicKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_rsa_ssa_pss_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use RsaSsaPssPublicKey.ProtoReflect.Descriptor instead. func (*RsaSsaPssPublicKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_rsa_ssa_pss_proto_rawDescGZIP(), []int{1} } func (x *RsaSsaPssPublicKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *RsaSsaPssPublicKey) GetParams() *RsaSsaPssParams { if x != nil { return x.Params } return nil } func (x *RsaSsaPssPublicKey) GetN() []byte { if x != nil { return x.N } return nil } func (x *RsaSsaPssPublicKey) GetE() []byte { if x != nil { return x.E } return nil } // key_type: type.googleapis.com/google.crypto.tink.RsaSsaPssPrivateKey type RsaSsaPssPrivateKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required. Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` // Required. PublicKey *RsaSsaPssPublicKey `protobuf:"bytes,2,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` // Private exponent. // Unsigned big integer in bigendian representation. // Required. D []byte `protobuf:"bytes,3,opt,name=d,proto3" json:"d,omitempty"` // The following parameters are used to optimize RSA signature computation. // The prime factor p of n. // Unsigned big integer in bigendian representation. // Required. P []byte `protobuf:"bytes,4,opt,name=p,proto3" json:"p,omitempty"` // The prime factor q of n. // Unsigned big integer in bigendian representation. // Required. Q []byte `protobuf:"bytes,5,opt,name=q,proto3" json:"q,omitempty"` // d mod (p - 1). // Unsigned big integer in bigendian representation. // Required. Dp []byte `protobuf:"bytes,6,opt,name=dp,proto3" json:"dp,omitempty"` // d mod (q - 1). // Unsigned big integer in bigendian representation. // Required. Dq []byte `protobuf:"bytes,7,opt,name=dq,proto3" json:"dq,omitempty"` // Chinese Remainder Theorem coefficient q^(-1) mod p. // Unsigned big integer in bigendian representation. // Required. Crt []byte `protobuf:"bytes,8,opt,name=crt,proto3" json:"crt,omitempty"` } func (x *RsaSsaPssPrivateKey) Reset() { *x = RsaSsaPssPrivateKey{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_rsa_ssa_pss_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *RsaSsaPssPrivateKey) String() string { return protoimpl.X.MessageStringOf(x) } func (*RsaSsaPssPrivateKey) ProtoMessage() {} func (x *RsaSsaPssPrivateKey) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_rsa_ssa_pss_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use RsaSsaPssPrivateKey.ProtoReflect.Descriptor instead. func (*RsaSsaPssPrivateKey) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_rsa_ssa_pss_proto_rawDescGZIP(), []int{2} } func (x *RsaSsaPssPrivateKey) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *RsaSsaPssPrivateKey) GetPublicKey() *RsaSsaPssPublicKey { if x != nil { return x.PublicKey } return nil } func (x *RsaSsaPssPrivateKey) GetD() []byte { if x != nil { return x.D } return nil } func (x *RsaSsaPssPrivateKey) GetP() []byte { if x != nil { return x.P } return nil } func (x *RsaSsaPssPrivateKey) GetQ() []byte { if x != nil { return x.Q } return nil } func (x *RsaSsaPssPrivateKey) GetDp() []byte { if x != nil { return x.Dp } return nil } func (x *RsaSsaPssPrivateKey) GetDq() []byte { if x != nil { return x.Dq } return nil } func (x *RsaSsaPssPrivateKey) GetCrt() []byte { if x != nil { return x.Crt } return nil } type RsaSsaPssKeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required. Params *RsaSsaPssParams `protobuf:"bytes,1,opt,name=params,proto3" json:"params,omitempty"` // Required. ModulusSizeInBits uint32 `protobuf:"varint,2,opt,name=modulus_size_in_bits,json=modulusSizeInBits,proto3" json:"modulus_size_in_bits,omitempty"` // Required. PublicExponent []byte `protobuf:"bytes,3,opt,name=public_exponent,json=publicExponent,proto3" json:"public_exponent,omitempty"` } func (x *RsaSsaPssKeyFormat) Reset() { *x = RsaSsaPssKeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_rsa_ssa_pss_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *RsaSsaPssKeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*RsaSsaPssKeyFormat) ProtoMessage() {} func (x *RsaSsaPssKeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_rsa_ssa_pss_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use RsaSsaPssKeyFormat.ProtoReflect.Descriptor instead. func (*RsaSsaPssKeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_rsa_ssa_pss_proto_rawDescGZIP(), []int{3} } func (x *RsaSsaPssKeyFormat) GetParams() *RsaSsaPssParams { if x != nil { return x.Params } return nil } func (x *RsaSsaPssKeyFormat) GetModulusSizeInBits() uint32 { if x != nil { return x.ModulusSizeInBits } return 0 } func (x *RsaSsaPssKeyFormat) GetPublicExponent() []byte { if x != nil { return x.PublicExponent } return nil } var File_third_party_tink_proto_rsa_ssa_pss_proto protoreflect.FileDescriptor var file_third_party_tink_proto_rsa_ssa_pss_proto_rawDesc = []byte{ 0x0a, 0x28, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x72, 0x73, 0x61, 0x5f, 0x73, 0x73, 0x61, 0x5f, 0x70, 0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x1a, 0x23, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa6, 0x01, 0x0a, 0x0f, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x73, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x37, 0x0a, 0x08, 0x73, 0x69, 0x67, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x07, 0x73, 0x69, 0x67, 0x48, 0x61, 0x73, 0x68, 0x12, 0x39, 0x0a, 0x09, 0x6d, 0x67, 0x66, 0x31, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x6d, 0x67, 0x66, 0x31, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x61, 0x6c, 0x74, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, 0x61, 0x6c, 0x74, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x87, 0x01, 0x0a, 0x12, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x73, 0x73, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3b, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x73, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x0c, 0x0a, 0x01, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x6e, 0x12, 0x0c, 0x0a, 0x01, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x65, 0x22, 0xd2, 0x01, 0x0a, 0x13, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x73, 0x73, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x73, 0x73, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x0c, 0x0a, 0x01, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x64, 0x12, 0x0c, 0x0a, 0x01, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x70, 0x12, 0x0c, 0x0a, 0x01, 0x71, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x71, 0x12, 0x0e, 0x0a, 0x02, 0x64, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x64, 0x70, 0x12, 0x0e, 0x0a, 0x02, 0x64, 0x71, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x64, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x72, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x63, 0x72, 0x74, 0x22, 0xab, 0x01, 0x0a, 0x12, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x3b, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x52, 0x73, 0x61, 0x53, 0x73, 0x61, 0x50, 0x73, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2f, 0x0a, 0x14, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x75, 0x73, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x69, 0x6e, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x75, 0x73, 0x53, 0x69, 0x7a, 0x65, 0x49, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x65, 0x78, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x45, 0x78, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x42, 0x56, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x72, 0x73, 0x61, 0x5f, 0x73, 0x73, 0x61, 0x5f, 0x70, 0x73, 0x73, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_rsa_ssa_pss_proto_rawDescOnce sync.Once file_third_party_tink_proto_rsa_ssa_pss_proto_rawDescData = file_third_party_tink_proto_rsa_ssa_pss_proto_rawDesc ) func file_third_party_tink_proto_rsa_ssa_pss_proto_rawDescGZIP() []byte { file_third_party_tink_proto_rsa_ssa_pss_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_rsa_ssa_pss_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_rsa_ssa_pss_proto_rawDescData) }) return file_third_party_tink_proto_rsa_ssa_pss_proto_rawDescData } var file_third_party_tink_proto_rsa_ssa_pss_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_third_party_tink_proto_rsa_ssa_pss_proto_goTypes = []interface{}{ (*RsaSsaPssParams)(nil), // 0: google.crypto.tink.RsaSsaPssParams (*RsaSsaPssPublicKey)(nil), // 1: google.crypto.tink.RsaSsaPssPublicKey (*RsaSsaPssPrivateKey)(nil), // 2: google.crypto.tink.RsaSsaPssPrivateKey (*RsaSsaPssKeyFormat)(nil), // 3: google.crypto.tink.RsaSsaPssKeyFormat (common_go_proto.HashType)(0), // 4: google.crypto.tink.HashType } var file_third_party_tink_proto_rsa_ssa_pss_proto_depIdxs = []int32{ 4, // 0: google.crypto.tink.RsaSsaPssParams.sig_hash:type_name -> google.crypto.tink.HashType 4, // 1: google.crypto.tink.RsaSsaPssParams.mgf1_hash:type_name -> google.crypto.tink.HashType 0, // 2: google.crypto.tink.RsaSsaPssPublicKey.params:type_name -> google.crypto.tink.RsaSsaPssParams 1, // 3: google.crypto.tink.RsaSsaPssPrivateKey.public_key:type_name -> google.crypto.tink.RsaSsaPssPublicKey 0, // 4: google.crypto.tink.RsaSsaPssKeyFormat.params:type_name -> google.crypto.tink.RsaSsaPssParams 5, // [5:5] is the sub-list for method output_type 5, // [5:5] is the sub-list for method input_type 5, // [5:5] is the sub-list for extension type_name 5, // [5:5] is the sub-list for extension extendee 0, // [0:5] is the sub-list for field type_name } func init() { file_third_party_tink_proto_rsa_ssa_pss_proto_init() } func file_third_party_tink_proto_rsa_ssa_pss_proto_init() { if File_third_party_tink_proto_rsa_ssa_pss_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_rsa_ssa_pss_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RsaSsaPssParams); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_rsa_ssa_pss_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RsaSsaPssPublicKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_rsa_ssa_pss_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RsaSsaPssPrivateKey); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_rsa_ssa_pss_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RsaSsaPssKeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_rsa_ssa_pss_proto_rawDesc, NumEnums: 0, NumMessages: 4, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_rsa_ssa_pss_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_rsa_ssa_pss_proto_depIdxs, MessageInfos: file_third_party_tink_proto_rsa_ssa_pss_proto_msgTypes, }.Build() File_third_party_tink_proto_rsa_ssa_pss_proto = out.File file_third_party_tink_proto_rsa_ssa_pss_proto_rawDesc = nil file_third_party_tink_proto_rsa_ssa_pss_proto_goTypes = nil file_third_party_tink_proto_rsa_ssa_pss_proto_depIdxs = nil } ================================================ FILE: go/proto/tink_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "tink_go_proto", srcs = ["tink.pb.go"], importpath = "github.com/google/tink/go/proto/tink_go_proto", visibility = ["//visibility:public"], deps = [ "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":tink_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/tink_go_proto/tink.pb.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Definitions for Cloud Crypto SDK (Tink) library. // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/tink.proto package tink_go_proto import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type KeyStatusType int32 const ( KeyStatusType_UNKNOWN_STATUS KeyStatusType = 0 KeyStatusType_ENABLED KeyStatusType = 1 // Can be used for crypto operations. KeyStatusType_DISABLED KeyStatusType = 2 // Cannot be used, but exists and can become ENABLED. KeyStatusType_DESTROYED KeyStatusType = 3 // Key data does not exist in this Keyset any more. ) // Enum value maps for KeyStatusType. var ( KeyStatusType_name = map[int32]string{ 0: "UNKNOWN_STATUS", 1: "ENABLED", 2: "DISABLED", 3: "DESTROYED", } KeyStatusType_value = map[string]int32{ "UNKNOWN_STATUS": 0, "ENABLED": 1, "DISABLED": 2, "DESTROYED": 3, } ) func (x KeyStatusType) Enum() *KeyStatusType { p := new(KeyStatusType) *p = x return p } func (x KeyStatusType) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (KeyStatusType) Descriptor() protoreflect.EnumDescriptor { return file_third_party_tink_proto_tink_proto_enumTypes[0].Descriptor() } func (KeyStatusType) Type() protoreflect.EnumType { return &file_third_party_tink_proto_tink_proto_enumTypes[0] } func (x KeyStatusType) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use KeyStatusType.Descriptor instead. func (KeyStatusType) EnumDescriptor() ([]byte, []int) { return file_third_party_tink_proto_tink_proto_rawDescGZIP(), []int{0} } // Tink produces and accepts ciphertexts or signatures that consist // of a prefix and a payload. The payload and its format is determined // entirely by the primitive, but the prefix has to be one of the following // 4 types: // - Legacy: prefix is 5 bytes, starts with \x00 and followed by a 4-byte // key id that is computed from the key material. In addition to // that, signature schemes and MACs will add a \x00 byte to the // end of the data being signed / MACed when operating on keys // with this OutputPrefixType. // - Crunchy: prefix is 5 bytes, starts with \x00 and followed by a 4-byte // key id that is generated randomly. // - Tink : prefix is 5 bytes, starts with \x01 and followed by 4-byte // key id that is generated randomly. // - Raw : prefix is 0 byte, i.e., empty. type OutputPrefixType int32 const ( OutputPrefixType_UNKNOWN_PREFIX OutputPrefixType = 0 OutputPrefixType_TINK OutputPrefixType = 1 OutputPrefixType_LEGACY OutputPrefixType = 2 OutputPrefixType_RAW OutputPrefixType = 3 OutputPrefixType_CRUNCHY OutputPrefixType = 4 ) // Enum value maps for OutputPrefixType. var ( OutputPrefixType_name = map[int32]string{ 0: "UNKNOWN_PREFIX", 1: "TINK", 2: "LEGACY", 3: "RAW", 4: "CRUNCHY", } OutputPrefixType_value = map[string]int32{ "UNKNOWN_PREFIX": 0, "TINK": 1, "LEGACY": 2, "RAW": 3, "CRUNCHY": 4, } ) func (x OutputPrefixType) Enum() *OutputPrefixType { p := new(OutputPrefixType) *p = x return p } func (x OutputPrefixType) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (OutputPrefixType) Descriptor() protoreflect.EnumDescriptor { return file_third_party_tink_proto_tink_proto_enumTypes[1].Descriptor() } func (OutputPrefixType) Type() protoreflect.EnumType { return &file_third_party_tink_proto_tink_proto_enumTypes[1] } func (x OutputPrefixType) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use OutputPrefixType.Descriptor instead. func (OutputPrefixType) EnumDescriptor() ([]byte, []int) { return file_third_party_tink_proto_tink_proto_rawDescGZIP(), []int{1} } type KeyData_KeyMaterialType int32 const ( KeyData_UNKNOWN_KEYMATERIAL KeyData_KeyMaterialType = 0 KeyData_SYMMETRIC KeyData_KeyMaterialType = 1 KeyData_ASYMMETRIC_PRIVATE KeyData_KeyMaterialType = 2 KeyData_ASYMMETRIC_PUBLIC KeyData_KeyMaterialType = 3 KeyData_REMOTE KeyData_KeyMaterialType = 4 // points to a remote key, i.e., in a KMS. ) // Enum value maps for KeyData_KeyMaterialType. var ( KeyData_KeyMaterialType_name = map[int32]string{ 0: "UNKNOWN_KEYMATERIAL", 1: "SYMMETRIC", 2: "ASYMMETRIC_PRIVATE", 3: "ASYMMETRIC_PUBLIC", 4: "REMOTE", } KeyData_KeyMaterialType_value = map[string]int32{ "UNKNOWN_KEYMATERIAL": 0, "SYMMETRIC": 1, "ASYMMETRIC_PRIVATE": 2, "ASYMMETRIC_PUBLIC": 3, "REMOTE": 4, } ) func (x KeyData_KeyMaterialType) Enum() *KeyData_KeyMaterialType { p := new(KeyData_KeyMaterialType) *p = x return p } func (x KeyData_KeyMaterialType) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (KeyData_KeyMaterialType) Descriptor() protoreflect.EnumDescriptor { return file_third_party_tink_proto_tink_proto_enumTypes[2].Descriptor() } func (KeyData_KeyMaterialType) Type() protoreflect.EnumType { return &file_third_party_tink_proto_tink_proto_enumTypes[2] } func (x KeyData_KeyMaterialType) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use KeyData_KeyMaterialType.Descriptor instead. func (KeyData_KeyMaterialType) EnumDescriptor() ([]byte, []int) { return file_third_party_tink_proto_tink_proto_rawDescGZIP(), []int{1, 0} } type KeyTemplate struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required. The type_url of the key type in format // type.googleapis.com/packagename.messagename -- see above for details. // This is typically the protobuf type URL of the *Key proto. In particular, // this is different of the protobuf type URL of the *KeyFormat proto. TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl,proto3" json:"type_url,omitempty"` // Required. The serialized *KeyFormat proto. Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` // Required. The type of prefix used when computing some primitives to // identify the ciphertext/signature, etc. OutputPrefixType OutputPrefixType `protobuf:"varint,3,opt,name=output_prefix_type,json=outputPrefixType,proto3,enum=google.crypto.tink.OutputPrefixType" json:"output_prefix_type,omitempty"` } func (x *KeyTemplate) Reset() { *x = KeyTemplate{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_tink_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *KeyTemplate) String() string { return protoimpl.X.MessageStringOf(x) } func (*KeyTemplate) ProtoMessage() {} func (x *KeyTemplate) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_tink_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use KeyTemplate.ProtoReflect.Descriptor instead. func (*KeyTemplate) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_tink_proto_rawDescGZIP(), []int{0} } func (x *KeyTemplate) GetTypeUrl() string { if x != nil { return x.TypeUrl } return "" } func (x *KeyTemplate) GetValue() []byte { if x != nil { return x.Value } return nil } func (x *KeyTemplate) GetOutputPrefixType() OutputPrefixType { if x != nil { return x.OutputPrefixType } return OutputPrefixType_UNKNOWN_PREFIX } // The actual *Key-proto is wrapped in a KeyData message, which in addition // to this serialized proto contains also type_url identifying the // definition of *Key-proto (as in KeyFormat-message), and some extra metadata // about the type key material. type KeyData struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required. TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl,proto3" json:"type_url,omitempty"` // In format type.googleapis.com/packagename.messagename // Required. // Contains specific serialized *Key proto Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` // Required. KeyMaterialType KeyData_KeyMaterialType `protobuf:"varint,3,opt,name=key_material_type,json=keyMaterialType,proto3,enum=google.crypto.tink.KeyData_KeyMaterialType" json:"key_material_type,omitempty"` } func (x *KeyData) Reset() { *x = KeyData{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_tink_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *KeyData) String() string { return protoimpl.X.MessageStringOf(x) } func (*KeyData) ProtoMessage() {} func (x *KeyData) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_tink_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use KeyData.ProtoReflect.Descriptor instead. func (*KeyData) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_tink_proto_rawDescGZIP(), []int{1} } func (x *KeyData) GetTypeUrl() string { if x != nil { return x.TypeUrl } return "" } func (x *KeyData) GetValue() []byte { if x != nil { return x.Value } return nil } func (x *KeyData) GetKeyMaterialType() KeyData_KeyMaterialType { if x != nil { return x.KeyMaterialType } return KeyData_UNKNOWN_KEYMATERIAL } // A Tink user works usually not with single keys, but with keysets, // to enable key rotation. The keys in a keyset can belong to different // implementations/key types, but must all implement the same primitive. // Any given keyset (and any given key) can be used for one primitive only. type Keyset struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Identifies key used to generate new crypto data (encrypt, sign). // Required. PrimaryKeyId uint32 `protobuf:"varint,1,opt,name=primary_key_id,json=primaryKeyId,proto3" json:"primary_key_id,omitempty"` // Actual keys in the Keyset. // Required. Key []*Keyset_Key `protobuf:"bytes,2,rep,name=key,proto3" json:"key,omitempty"` } func (x *Keyset) Reset() { *x = Keyset{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_tink_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Keyset) String() string { return protoimpl.X.MessageStringOf(x) } func (*Keyset) ProtoMessage() {} func (x *Keyset) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_tink_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use Keyset.ProtoReflect.Descriptor instead. func (*Keyset) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_tink_proto_rawDescGZIP(), []int{2} } func (x *Keyset) GetPrimaryKeyId() uint32 { if x != nil { return x.PrimaryKeyId } return 0 } func (x *Keyset) GetKey() []*Keyset_Key { if x != nil { return x.Key } return nil } // Represents a "safe" Keyset that doesn't contain any actual key material, // thus can be used for logging or monitoring. Most fields are copied from // Keyset. type KeysetInfo struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // See Keyset.primary_key_id. PrimaryKeyId uint32 `protobuf:"varint,1,opt,name=primary_key_id,json=primaryKeyId,proto3" json:"primary_key_id,omitempty"` // KeyInfos in the KeysetInfo. // Each KeyInfo is corresponding to a Key in the corresponding Keyset. KeyInfo []*KeysetInfo_KeyInfo `protobuf:"bytes,2,rep,name=key_info,json=keyInfo,proto3" json:"key_info,omitempty"` } func (x *KeysetInfo) Reset() { *x = KeysetInfo{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_tink_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *KeysetInfo) String() string { return protoimpl.X.MessageStringOf(x) } func (*KeysetInfo) ProtoMessage() {} func (x *KeysetInfo) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_tink_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use KeysetInfo.ProtoReflect.Descriptor instead. func (*KeysetInfo) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_tink_proto_rawDescGZIP(), []int{3} } func (x *KeysetInfo) GetPrimaryKeyId() uint32 { if x != nil { return x.PrimaryKeyId } return 0 } func (x *KeysetInfo) GetKeyInfo() []*KeysetInfo_KeyInfo { if x != nil { return x.KeyInfo } return nil } // Represents a keyset that is encrypted with a master key. type EncryptedKeyset struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required. EncryptedKeyset []byte `protobuf:"bytes,2,opt,name=encrypted_keyset,json=encryptedKeyset,proto3" json:"encrypted_keyset,omitempty"` // Optional. KeysetInfo *KeysetInfo `protobuf:"bytes,3,opt,name=keyset_info,json=keysetInfo,proto3" json:"keyset_info,omitempty"` } func (x *EncryptedKeyset) Reset() { *x = EncryptedKeyset{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_tink_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EncryptedKeyset) String() string { return protoimpl.X.MessageStringOf(x) } func (*EncryptedKeyset) ProtoMessage() {} func (x *EncryptedKeyset) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_tink_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use EncryptedKeyset.ProtoReflect.Descriptor instead. func (*EncryptedKeyset) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_tink_proto_rawDescGZIP(), []int{4} } func (x *EncryptedKeyset) GetEncryptedKeyset() []byte { if x != nil { return x.EncryptedKeyset } return nil } func (x *EncryptedKeyset) GetKeysetInfo() *KeysetInfo { if x != nil { return x.KeysetInfo } return nil } type Keyset_Key struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Contains the actual, instantiation specific key proto. // By convention, each key proto contains a version field. KeyData *KeyData `protobuf:"bytes,1,opt,name=key_data,json=keyData,proto3" json:"key_data,omitempty"` Status KeyStatusType `protobuf:"varint,2,opt,name=status,proto3,enum=google.crypto.tink.KeyStatusType" json:"status,omitempty"` // Identifies a key within a keyset, is a part of metadata // of a ciphertext/signature. KeyId uint32 `protobuf:"varint,3,opt,name=key_id,json=keyId,proto3" json:"key_id,omitempty"` // Determines the prefix of the ciphertexts/signatures produced by this key. // This value is copied verbatim from the key template. OutputPrefixType OutputPrefixType `protobuf:"varint,4,opt,name=output_prefix_type,json=outputPrefixType,proto3,enum=google.crypto.tink.OutputPrefixType" json:"output_prefix_type,omitempty"` } func (x *Keyset_Key) Reset() { *x = Keyset_Key{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_tink_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Keyset_Key) String() string { return protoimpl.X.MessageStringOf(x) } func (*Keyset_Key) ProtoMessage() {} func (x *Keyset_Key) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_tink_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use Keyset_Key.ProtoReflect.Descriptor instead. func (*Keyset_Key) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_tink_proto_rawDescGZIP(), []int{2, 0} } func (x *Keyset_Key) GetKeyData() *KeyData { if x != nil { return x.KeyData } return nil } func (x *Keyset_Key) GetStatus() KeyStatusType { if x != nil { return x.Status } return KeyStatusType_UNKNOWN_STATUS } func (x *Keyset_Key) GetKeyId() uint32 { if x != nil { return x.KeyId } return 0 } func (x *Keyset_Key) GetOutputPrefixType() OutputPrefixType { if x != nil { return x.OutputPrefixType } return OutputPrefixType_UNKNOWN_PREFIX } type KeysetInfo_KeyInfo struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // the type url of this key, // e.g., type.googleapis.com/google.crypto.tink.HmacKey. TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl,proto3" json:"type_url,omitempty"` // See Keyset.Key.status. Status KeyStatusType `protobuf:"varint,2,opt,name=status,proto3,enum=google.crypto.tink.KeyStatusType" json:"status,omitempty"` // See Keyset.Key.key_id. KeyId uint32 `protobuf:"varint,3,opt,name=key_id,json=keyId,proto3" json:"key_id,omitempty"` // See Keyset.Key.output_prefix_type. OutputPrefixType OutputPrefixType `protobuf:"varint,4,opt,name=output_prefix_type,json=outputPrefixType,proto3,enum=google.crypto.tink.OutputPrefixType" json:"output_prefix_type,omitempty"` } func (x *KeysetInfo_KeyInfo) Reset() { *x = KeysetInfo_KeyInfo{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_tink_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *KeysetInfo_KeyInfo) String() string { return protoimpl.X.MessageStringOf(x) } func (*KeysetInfo_KeyInfo) ProtoMessage() {} func (x *KeysetInfo_KeyInfo) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_tink_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use KeysetInfo_KeyInfo.ProtoReflect.Descriptor instead. func (*KeysetInfo_KeyInfo) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_tink_proto_rawDescGZIP(), []int{3, 0} } func (x *KeysetInfo_KeyInfo) GetTypeUrl() string { if x != nil { return x.TypeUrl } return "" } func (x *KeysetInfo_KeyInfo) GetStatus() KeyStatusType { if x != nil { return x.Status } return KeyStatusType_UNKNOWN_STATUS } func (x *KeysetInfo_KeyInfo) GetKeyId() uint32 { if x != nil { return x.KeyId } return 0 } func (x *KeysetInfo_KeyInfo) GetOutputPrefixType() OutputPrefixType { if x != nil { return x.OutputPrefixType } return OutputPrefixType_UNKNOWN_PREFIX } var File_third_party_tink_proto_tink_proto protoreflect.FileDescriptor var file_third_party_tink_proto_tink_proto_rawDesc = []byte{ 0x0a, 0x21, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x22, 0x92, 0x01, 0x0a, 0x0b, 0x4b, 0x65, 0x79, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x79, 0x70, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x52, 0x0a, 0x12, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x54, 0x79, 0x70, 0x65, 0x52, 0x10, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x8d, 0x02, 0x0a, 0x07, 0x4b, 0x65, 0x79, 0x44, 0x61, 0x74, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x79, 0x70, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x18, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x02, 0x08, 0x02, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x57, 0x0a, 0x11, 0x6b, 0x65, 0x79, 0x5f, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4b, 0x65, 0x79, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0f, 0x6b, 0x65, 0x79, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x22, 0x74, 0x0a, 0x0f, 0x4b, 0x65, 0x79, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x4b, 0x45, 0x59, 0x4d, 0x41, 0x54, 0x45, 0x52, 0x49, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x59, 0x4d, 0x4d, 0x45, 0x54, 0x52, 0x49, 0x43, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x41, 0x53, 0x59, 0x4d, 0x4d, 0x45, 0x54, 0x52, 0x49, 0x43, 0x5f, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x41, 0x53, 0x59, 0x4d, 0x4d, 0x45, 0x54, 0x52, 0x49, 0x43, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x10, 0x04, 0x22, 0xc6, 0x02, 0x0a, 0x06, 0x4b, 0x65, 0x79, 0x73, 0x65, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x65, 0x74, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x1a, 0xe3, 0x01, 0x0a, 0x03, 0x4b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4b, 0x65, 0x79, 0x44, 0x61, 0x74, 0x61, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x44, 0x61, 0x74, 0x61, 0x12, 0x39, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4b, 0x65, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x54, 0x79, 0x70, 0x65, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x15, 0x0a, 0x06, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6b, 0x65, 0x79, 0x49, 0x64, 0x12, 0x52, 0x0a, 0x12, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x54, 0x79, 0x70, 0x65, 0x52, 0x10, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0xc2, 0x02, 0x0a, 0x0a, 0x4b, 0x65, 0x79, 0x73, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x12, 0x41, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4b, 0x65, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0xca, 0x01, 0x0a, 0x07, 0x4b, 0x65, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x79, 0x70, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x39, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4b, 0x65, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x54, 0x79, 0x70, 0x65, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x15, 0x0a, 0x06, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6b, 0x65, 0x79, 0x49, 0x64, 0x12, 0x52, 0x0a, 0x12, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x54, 0x79, 0x70, 0x65, 0x52, 0x10, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x7d, 0x0a, 0x0f, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x65, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x65, 0x74, 0x12, 0x3f, 0x0a, 0x0b, 0x6b, 0x65, 0x79, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x6b, 0x65, 0x79, 0x73, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x2a, 0x4d, 0x0a, 0x0d, 0x4b, 0x65, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x0e, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x45, 0x4e, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x44, 0x45, 0x53, 0x54, 0x52, 0x4f, 0x59, 0x45, 0x44, 0x10, 0x03, 0x2a, 0x52, 0x0a, 0x10, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x0e, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x50, 0x52, 0x45, 0x46, 0x49, 0x58, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x54, 0x49, 0x4e, 0x4b, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x45, 0x47, 0x41, 0x43, 0x59, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x52, 0x41, 0x57, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x52, 0x55, 0x4e, 0x43, 0x48, 0x59, 0x10, 0x04, 0x42, 0x58, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xa2, 0x02, 0x06, 0x54, 0x49, 0x4e, 0x4b, 0x50, 0x42, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_tink_proto_rawDescOnce sync.Once file_third_party_tink_proto_tink_proto_rawDescData = file_third_party_tink_proto_tink_proto_rawDesc ) func file_third_party_tink_proto_tink_proto_rawDescGZIP() []byte { file_third_party_tink_proto_tink_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_tink_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_tink_proto_rawDescData) }) return file_third_party_tink_proto_tink_proto_rawDescData } var file_third_party_tink_proto_tink_proto_enumTypes = make([]protoimpl.EnumInfo, 3) var file_third_party_tink_proto_tink_proto_msgTypes = make([]protoimpl.MessageInfo, 7) var file_third_party_tink_proto_tink_proto_goTypes = []interface{}{ (KeyStatusType)(0), // 0: google.crypto.tink.KeyStatusType (OutputPrefixType)(0), // 1: google.crypto.tink.OutputPrefixType (KeyData_KeyMaterialType)(0), // 2: google.crypto.tink.KeyData.KeyMaterialType (*KeyTemplate)(nil), // 3: google.crypto.tink.KeyTemplate (*KeyData)(nil), // 4: google.crypto.tink.KeyData (*Keyset)(nil), // 5: google.crypto.tink.Keyset (*KeysetInfo)(nil), // 6: google.crypto.tink.KeysetInfo (*EncryptedKeyset)(nil), // 7: google.crypto.tink.EncryptedKeyset (*Keyset_Key)(nil), // 8: google.crypto.tink.Keyset.Key (*KeysetInfo_KeyInfo)(nil), // 9: google.crypto.tink.KeysetInfo.KeyInfo } var file_third_party_tink_proto_tink_proto_depIdxs = []int32{ 1, // 0: google.crypto.tink.KeyTemplate.output_prefix_type:type_name -> google.crypto.tink.OutputPrefixType 2, // 1: google.crypto.tink.KeyData.key_material_type:type_name -> google.crypto.tink.KeyData.KeyMaterialType 8, // 2: google.crypto.tink.Keyset.key:type_name -> google.crypto.tink.Keyset.Key 9, // 3: google.crypto.tink.KeysetInfo.key_info:type_name -> google.crypto.tink.KeysetInfo.KeyInfo 6, // 4: google.crypto.tink.EncryptedKeyset.keyset_info:type_name -> google.crypto.tink.KeysetInfo 4, // 5: google.crypto.tink.Keyset.Key.key_data:type_name -> google.crypto.tink.KeyData 0, // 6: google.crypto.tink.Keyset.Key.status:type_name -> google.crypto.tink.KeyStatusType 1, // 7: google.crypto.tink.Keyset.Key.output_prefix_type:type_name -> google.crypto.tink.OutputPrefixType 0, // 8: google.crypto.tink.KeysetInfo.KeyInfo.status:type_name -> google.crypto.tink.KeyStatusType 1, // 9: google.crypto.tink.KeysetInfo.KeyInfo.output_prefix_type:type_name -> google.crypto.tink.OutputPrefixType 10, // [10:10] is the sub-list for method output_type 10, // [10:10] is the sub-list for method input_type 10, // [10:10] is the sub-list for extension type_name 10, // [10:10] is the sub-list for extension extendee 0, // [0:10] is the sub-list for field type_name } func init() { file_third_party_tink_proto_tink_proto_init() } func file_third_party_tink_proto_tink_proto_init() { if File_third_party_tink_proto_tink_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_tink_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*KeyTemplate); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_tink_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*KeyData); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_tink_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Keyset); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_tink_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*KeysetInfo); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_tink_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EncryptedKeyset); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_tink_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Keyset_Key); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_tink_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*KeysetInfo_KeyInfo); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_tink_proto_rawDesc, NumEnums: 3, NumMessages: 7, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_tink_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_tink_proto_depIdxs, EnumInfos: file_third_party_tink_proto_tink_proto_enumTypes, MessageInfos: file_third_party_tink_proto_tink_proto_msgTypes, }.Build() File_third_party_tink_proto_tink_proto = out.File file_third_party_tink_proto_tink_proto_rawDesc = nil file_third_party_tink_proto_tink_proto_goTypes = nil file_third_party_tink_proto_tink_proto_depIdxs = nil } ================================================ FILE: go/proto/xchacha20_poly1305_go_proto/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "xchacha20_poly1305_go_proto", srcs = ["xchacha20_poly1305.pb.go"], importpath = "github.com/google/tink/go/proto/xchacha20_poly1305_go_proto", visibility = ["//visibility:public"], deps = [ "@org_golang_google_protobuf//reflect/protoreflect", "@org_golang_google_protobuf//runtime/protoimpl", ], ) alias( name = "go_default_library", actual = ":xchacha20_poly1305_go_proto", visibility = ["//visibility:public"], ) ================================================ FILE: go/proto/xchacha20_poly1305_go_proto/xchacha20_poly1305.pb.go ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 // protoc v3.21.12 // source: third_party/tink/proto/xchacha20_poly1305.proto package xchacha20_poly1305_go_proto import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type XChaCha20Poly1305KeyFormat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` } func (x *XChaCha20Poly1305KeyFormat) Reset() { *x = XChaCha20Poly1305KeyFormat{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_xchacha20_poly1305_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *XChaCha20Poly1305KeyFormat) String() string { return protoimpl.X.MessageStringOf(x) } func (*XChaCha20Poly1305KeyFormat) ProtoMessage() {} func (x *XChaCha20Poly1305KeyFormat) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_xchacha20_poly1305_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use XChaCha20Poly1305KeyFormat.ProtoReflect.Descriptor instead. func (*XChaCha20Poly1305KeyFormat) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_xchacha20_poly1305_proto_rawDescGZIP(), []int{0} } func (x *XChaCha20Poly1305KeyFormat) GetVersion() uint32 { if x != nil { return x.Version } return 0 } // key_type: type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key type XChaCha20Poly1305Key struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` KeyValue []byte `protobuf:"bytes,3,opt,name=key_value,json=keyValue,proto3" json:"key_value,omitempty"` } func (x *XChaCha20Poly1305Key) Reset() { *x = XChaCha20Poly1305Key{} if protoimpl.UnsafeEnabled { mi := &file_third_party_tink_proto_xchacha20_poly1305_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *XChaCha20Poly1305Key) String() string { return protoimpl.X.MessageStringOf(x) } func (*XChaCha20Poly1305Key) ProtoMessage() {} func (x *XChaCha20Poly1305Key) ProtoReflect() protoreflect.Message { mi := &file_third_party_tink_proto_xchacha20_poly1305_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use XChaCha20Poly1305Key.ProtoReflect.Descriptor instead. func (*XChaCha20Poly1305Key) Descriptor() ([]byte, []int) { return file_third_party_tink_proto_xchacha20_poly1305_proto_rawDescGZIP(), []int{1} } func (x *XChaCha20Poly1305Key) GetVersion() uint32 { if x != nil { return x.Version } return 0 } func (x *XChaCha20Poly1305Key) GetKeyValue() []byte { if x != nil { return x.KeyValue } return nil } var File_third_party_tink_proto_xchacha20_poly1305_proto protoreflect.FileDescriptor var file_third_party_tink_proto_xchacha20_poly1305_proto_rawDesc = []byte{ 0x0a, 0x2f, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x78, 0x63, 0x68, 0x61, 0x63, 0x68, 0x61, 0x32, 0x30, 0x5f, 0x70, 0x6f, 0x6c, 0x79, 0x31, 0x33, 0x30, 0x35, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x22, 0x36, 0x0a, 0x1a, 0x58, 0x43, 0x68, 0x61, 0x43, 0x68, 0x61, 0x32, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x31, 0x33, 0x30, 0x35, 0x4b, 0x65, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x4d, 0x0a, 0x14, 0x58, 0x43, 0x68, 0x61, 0x43, 0x68, 0x61, 0x32, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x31, 0x33, 0x30, 0x35, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x5d, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x74, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x69, 0x6e, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x78, 0x63, 0x68, 0x61, 0x63, 0x68, 0x61, 0x32, 0x30, 0x5f, 0x70, 0x6f, 0x6c, 0x79, 0x31, 0x33, 0x30, 0x35, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_third_party_tink_proto_xchacha20_poly1305_proto_rawDescOnce sync.Once file_third_party_tink_proto_xchacha20_poly1305_proto_rawDescData = file_third_party_tink_proto_xchacha20_poly1305_proto_rawDesc ) func file_third_party_tink_proto_xchacha20_poly1305_proto_rawDescGZIP() []byte { file_third_party_tink_proto_xchacha20_poly1305_proto_rawDescOnce.Do(func() { file_third_party_tink_proto_xchacha20_poly1305_proto_rawDescData = protoimpl.X.CompressGZIP(file_third_party_tink_proto_xchacha20_poly1305_proto_rawDescData) }) return file_third_party_tink_proto_xchacha20_poly1305_proto_rawDescData } var file_third_party_tink_proto_xchacha20_poly1305_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_third_party_tink_proto_xchacha20_poly1305_proto_goTypes = []interface{}{ (*XChaCha20Poly1305KeyFormat)(nil), // 0: google.crypto.tink.XChaCha20Poly1305KeyFormat (*XChaCha20Poly1305Key)(nil), // 1: google.crypto.tink.XChaCha20Poly1305Key } var file_third_party_tink_proto_xchacha20_poly1305_proto_depIdxs = []int32{ 0, // [0:0] is the sub-list for method output_type 0, // [0:0] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name } func init() { file_third_party_tink_proto_xchacha20_poly1305_proto_init() } func file_third_party_tink_proto_xchacha20_poly1305_proto_init() { if File_third_party_tink_proto_xchacha20_poly1305_proto != nil { return } if !protoimpl.UnsafeEnabled { file_third_party_tink_proto_xchacha20_poly1305_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*XChaCha20Poly1305KeyFormat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_third_party_tink_proto_xchacha20_poly1305_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*XChaCha20Poly1305Key); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_third_party_tink_proto_xchacha20_poly1305_proto_rawDesc, NumEnums: 0, NumMessages: 2, NumExtensions: 0, NumServices: 0, }, GoTypes: file_third_party_tink_proto_xchacha20_poly1305_proto_goTypes, DependencyIndexes: file_third_party_tink_proto_xchacha20_poly1305_proto_depIdxs, MessageInfos: file_third_party_tink_proto_xchacha20_poly1305_proto_msgTypes, }.Build() File_third_party_tink_proto_xchacha20_poly1305_proto = out.File file_third_party_tink_proto_xchacha20_poly1305_proto_rawDesc = nil file_third_party_tink_proto_xchacha20_poly1305_proto_goTypes = nil file_third_party_tink_proto_xchacha20_poly1305_proto_depIdxs = nil } ================================================ FILE: go/signature/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep licenses(["notice"]) # keep go_library( name = "signature", srcs = [ "ecdsa_signer_key_manager.go", "ecdsa_verifier_key_manager.go", "ed25519_signer_key_manager.go", "ed25519_verifier_key_manager.go", "proto.go", "rsa.go", "rsassapkcs1_signer_key_manager.go", "rsassapkcs1_verifier_key_manager.go", "rsassapss_signer_key_manager.go", "rsassapss_verifier_key_manager.go", "signature.go", "signature_key_templates.go", "signer_factory.go", "verifier_factory.go", ], importpath = "github.com/google/tink/go/signature", visibility = ["//visibility:public"], deps = [ "//core/cryptofmt", "//core/primitiveset", "//core/registry", "//internal/internalregistry", "//internal/monitoringutil", "//internal/signature", "//internal/tinkerror", "//keyset", "//monitoring", "//proto/common_go_proto", "//proto/ecdsa_go_proto", "//proto/ed25519_go_proto", "//proto/rsa_ssa_pkcs1_go_proto", "//proto/rsa_ssa_pss_go_proto", "//proto/tink_go_proto", "//signature/subtle", "//subtle", "//tink", "@org_golang_google_protobuf//proto", ], ) go_test( name = "signature_test", srcs = [ "ecdsa_signer_key_manager_test.go", "ecdsa_verifier_key_manager_test.go", "ed25519_signer_key_manager_test.go", "ed25519_verifier_key_manager_test.go", "rsassapkcs1_signer_key_manager_test.go", "rsassapkcs1_verifier_key_manager_test.go", "rsassapss_signer_key_manager_test.go", "rsassapss_verifier_key_manager_test.go", "signature_benchmark_test.go", "signature_factory_test.go", "signature_init_test.go", "signature_key_templates_test.go", "signature_test.go", ], deps = [ ":signature", "//core/registry", "//insecurecleartextkeyset", "//internal/internalregistry", "//internal/signature", "//internal/testing/stubkeymanager", "//keyset", "//mac", "//monitoring", "//proto/common_go_proto", "//proto/ecdsa_go_proto", "//proto/ed25519_go_proto", "//proto/rsa_ssa_pkcs1_go_proto", "//proto/rsa_ssa_pss_go_proto", "//proto/tink_go_proto", "//signature/subtle", "//subtle/random", "//testing/fakemonitoring", "//testkeyset", "//testutil", "//tink", "@com_github_google_go_cmp//cmp", "@org_golang_google_protobuf//proto", "@org_golang_google_protobuf//testing/protocmp", ], ) alias( name = "go_default_library", actual = ":signature", visibility = ["//visibility:public"], ) ================================================ FILE: go/signature/ecdsa_signer_key_manager.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature import ( "crypto/ecdsa" "crypto/rand" "errors" "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/keyset" subtleSignature "github.com/google/tink/go/signature/subtle" "github.com/google/tink/go/subtle" commonpb "github.com/google/tink/go/proto/common_go_proto" ecdsapb "github.com/google/tink/go/proto/ecdsa_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( ecdsaSignerKeyVersion = 0 ecdsaSignerTypeURL = "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey" ) // common errors var errInvalidECDSASignKey = errors.New("ecdsa_signer_key_manager: invalid key") var errInvalidECDSASignKeyFormat = errors.New("ecdsa_signer_key_manager: invalid key format") // ecdsaSignerKeyManager is an implementation of KeyManager interface. // It generates new ECDSAPrivateKeys and produces new instances of ECDSASign subtle. type ecdsaSignerKeyManager struct{} // Primitive creates an ECDSASign subtle for the given serialized ECDSAPrivateKey proto. func (km *ecdsaSignerKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidECDSASignKey } key := new(ecdsapb.EcdsaPrivateKey) if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errInvalidECDSASignKey } if err := km.validateKey(key); err != nil { return nil, err } hash, curve, encoding := getECDSAParamNames(key.GetPublicKey().GetParams()) ret, err := subtleSignature.NewECDSASigner(hash, curve, encoding, key.KeyValue) if err != nil { return nil, fmt.Errorf("ecdsa_signer_key_manager: %s", err) } return ret, nil } // NewKey creates a new ECDSAPrivateKey according to specification the given serialized ECDSAKeyFormat. func (km *ecdsaSignerKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errInvalidECDSASignKeyFormat } keyFormat := new(ecdsapb.EcdsaKeyFormat) if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, fmt.Errorf("ecdsa_signer_key_manager: invalid proto: %s", err) } if err := km.validateKeyFormat(keyFormat); err != nil { return nil, fmt.Errorf("ecdsa_signer_key_manager: invalid key format: %s", err) } // generate key params := keyFormat.GetParams() curve := commonpb.EllipticCurveType_name[int32(params.Curve)] tmpKey, err := ecdsa.GenerateKey(subtle.GetCurve(curve), rand.Reader) if err != nil { return nil, fmt.Errorf("ecdsa_signer_key_manager: cannot generate ECDSA key: %s", err) } keyValue := tmpKey.D.Bytes() pub := newECDSAPublicKey(ecdsaSignerKeyVersion, params, tmpKey.X.Bytes(), tmpKey.Y.Bytes()) priv := newECDSAPrivateKey(ecdsaSignerKeyVersion, pub, keyValue) return priv, nil } // NewKeyData creates a new KeyData according to specification in the given // serialized ECDSAKeyFormat. It should be used solely by the key management API. func (km *ecdsaSignerKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { key, err := km.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, errInvalidECDSASignKeyFormat } return &tinkpb.KeyData{ TypeUrl: ecdsaSignerTypeURL, Value: serializedKey, KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PRIVATE, }, nil } // PublicKeyData extracts the public key data from the private key. func (km *ecdsaSignerKeyManager) PublicKeyData(serializedPrivKey []byte) (*tinkpb.KeyData, error) { privKey := new(ecdsapb.EcdsaPrivateKey) if err := proto.Unmarshal(serializedPrivKey, privKey); err != nil { return nil, errInvalidECDSASignKey } serializedPubKey, err := proto.Marshal(privKey.PublicKey) if err != nil { return nil, errInvalidECDSASignKey } return &tinkpb.KeyData{ TypeUrl: ecdsaVerifierTypeURL, Value: serializedPubKey, KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC, }, nil } // DoesSupport indicates if this key manager supports the given key type. func (km *ecdsaSignerKeyManager) DoesSupport(typeURL string) bool { return typeURL == ecdsaSignerTypeURL } // TypeURL returns the key type of keys managed by this key manager. func (km *ecdsaSignerKeyManager) TypeURL() string { return ecdsaSignerTypeURL } // validateKey validates the given ECDSAPrivateKey. func (km *ecdsaSignerKeyManager) validateKey(key *ecdsapb.EcdsaPrivateKey) error { if err := keyset.ValidateKeyVersion(key.Version, ecdsaSignerKeyVersion); err != nil { return fmt.Errorf("ecdsa_signer_key_manager: invalid key: %s", err) } hash, curve, encoding := getECDSAParamNames(key.GetPublicKey().GetParams()) return subtleSignature.ValidateECDSAParams(hash, curve, encoding) } // validateKeyFormat validates the given ECDSAKeyFormat. func (km *ecdsaSignerKeyManager) validateKeyFormat(format *ecdsapb.EcdsaKeyFormat) error { hash, curve, encoding := getECDSAParamNames(format.GetParams()) return subtleSignature.ValidateECDSAParams(hash, curve, encoding) } ================================================ FILE: go/signature/ecdsa_signer_key_manager_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature_test import ( "fmt" "math/big" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/signature/subtle" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" commonpb "github.com/google/tink/go/proto/common_go_proto" ecdsapb "github.com/google/tink/go/proto/ecdsa_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) type ecdsaParams struct { hashType commonpb.HashType curve commonpb.EllipticCurveType } func TestECDSASignerGetPrimitiveBasic(t *testing.T) { testParams := genValidECDSAParams() km, err := registry.GetKeyManager(testutil.ECDSASignerTypeURL) if err != nil { t.Errorf("cannot obtain ECDSASigner key manager: %s", err) } for i := 0; i < len(testParams); i++ { serializedKey, err := proto.Marshal(testutil.NewRandomECDSAPrivateKey(testParams[i].hashType, testParams[i].curve)) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } _, err = km.Primitive(serializedKey) if err != nil { t.Errorf("unexpect error in test case %d: %s ", i, err) } } } func TestECDSASignGetPrimitiveWithInvalidInput(t *testing.T) { // invalid params testParams := genInvalidECDSAParams() km, err := registry.GetKeyManager(testutil.ECDSASignerTypeURL) if err != nil { t.Errorf("cannot obtain ECDSASigner key manager: %s", err) } for i := 0; i < len(testParams); i++ { serializedKey, err := proto.Marshal(testutil.NewRandomECDSAPrivateKey(testParams[i].hashType, testParams[i].curve)) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := km.Primitive(serializedKey); err == nil { t.Errorf("expect an error in test case %d", i) } } for _, tc := range genUnkownECDSAParams() { k := testutil.NewRandomECDSAPrivateKey(commonpb.HashType_SHA256, commonpb.EllipticCurveType_NIST_P256) k.GetPublicKey().GetParams().Curve = tc.curve k.GetPublicKey().GetParams().HashType = tc.hashType serializedKey, err := proto.Marshal(k) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := km.Primitive(serializedKey); err == nil { t.Errorf("expect an error in test case with params: (curve = %q, hash = %q)", tc.curve, tc.hashType) } } // invalid version key := testutil.NewRandomECDSAPrivateKey(commonpb.HashType_SHA256, commonpb.EllipticCurveType_NIST_P256) key.Version = testutil.ECDSASignerKeyVersion + 1 serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := km.Primitive(serializedKey); err == nil { t.Errorf("expect an error when version is invalid") } // nil input if _, err := km.Primitive(nil); err == nil { t.Errorf("expect an error when input is nil") } if _, err := km.Primitive([]byte{}); err == nil { t.Errorf("expect an error when input is empty slice") } // nil params field keyNilParams := testutil.NewRandomECDSAPrivateKey(commonpb.HashType_SHA256, commonpb.EllipticCurveType_NIST_P256) keyNilParams.GetPublicKey().Params = nil serializedKeyNilParams, err := proto.Marshal(keyNilParams) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := km.Primitive(serializedKeyNilParams); err == nil { t.Errorf("km.Primitive(serializedKeyNilParams) err = nil, want not nil") } } func TestECDSASignNewKeyBasic(t *testing.T) { testParams := genValidECDSAParams() km, err := registry.GetKeyManager(testutil.ECDSASignerTypeURL) if err != nil { t.Errorf("cannot obtain ECDSASigner key manager: %s", err) } for i := 0; i < len(testParams); i++ { params := testutil.NewECDSAParams(testParams[i].hashType, testParams[i].curve, ecdsapb.EcdsaSignatureEncoding_DER) serializedFormat, err := proto.Marshal(testutil.NewECDSAKeyFormat(params)) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } tmp, err := km.NewKey(serializedFormat) if err != nil { t.Errorf("unexpected error: %s", err) } key := tmp.(*ecdsapb.EcdsaPrivateKey) if err := validateECDSAPrivateKey(key, params); err != nil { t.Errorf("invalid private key in test case %d: %s", i, err) } } } func TestECDSASignNewKeyWithInvalidInput(t *testing.T) { km, err := registry.GetKeyManager(testutil.ECDSASignerTypeURL) if err != nil { t.Errorf("cannot obtain ECDSASigner key manager: %s", err) } // invalid hash and curve type testParams := genInvalidECDSAParams() for i := 0; i < len(testParams); i++ { params := testutil.NewECDSAParams(testParams[i].hashType, testParams[i].curve, ecdsapb.EcdsaSignatureEncoding_DER) serializedFormat, err := proto.Marshal(testutil.NewECDSAKeyFormat(params)) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := km.NewKey(serializedFormat); err == nil { t.Errorf("expect an error in test case %d", i) } } // invalid encoding testParams = genValidECDSAParams() for i := 0; i < len(testParams); i++ { params := testutil.NewECDSAParams(testParams[i].hashType, testParams[i].curve, ecdsapb.EcdsaSignatureEncoding_UNKNOWN_ENCODING) serializedFormat, err := proto.Marshal(testutil.NewECDSAKeyFormat(params)) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := km.NewKey(serializedFormat); err == nil { t.Errorf("expect an error in test case %d", i) } } // nil input if _, err := km.NewKey(nil); err == nil { t.Errorf("expect an error when input is nil") } if _, err := km.NewKey([]byte{}); err == nil { t.Errorf("expect an error when input is empty slice") } // nil params field keyFormatNilParams := testutil.NewECDSAKeyFormat(nil) serializedKeyFormatNilParams, err := proto.Marshal(keyFormatNilParams) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := km.NewKey(serializedKeyFormatNilParams); err == nil { t.Errorf("km.newKey(serializedKeyFormatNilParams) err = nil, want not nil") } } func TestECDSASignNewKeyMultipleTimes(t *testing.T) { km, err := registry.GetKeyManager(testutil.ECDSASignerTypeURL) if err != nil { t.Errorf("cannot obtain ECDSASigner key manager: %s", err) } testParams := genValidECDSAParams() nTest := 27 for i := 0; i < len(testParams); i++ { keys := make(map[string]bool) params := testutil.NewECDSAParams(testParams[i].hashType, testParams[i].curve, ecdsapb.EcdsaSignatureEncoding_DER) format := testutil.NewECDSAKeyFormat(params) serializedFormat, err := proto.Marshal(format) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } for j := 0; j < nTest; j++ { key, err := km.NewKey(serializedFormat) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } keys[string(serializedKey)] = true keyData, err := km.NewKeyData(serializedFormat) if err != nil { t.Fatalf("km.NewKeyData() err = %q, want nil", err) } serializedKey = keyData.Value keys[string(serializedKey)] = true } if len(keys) != nTest*2 { t.Errorf("key is repeated with params: %s", params) } } } func TestECDSASignNewKeyDataBasic(t *testing.T) { km, err := registry.GetKeyManager(testutil.ECDSASignerTypeURL) if err != nil { t.Errorf("cannot obtain ECDSASigner key manager: %s", err) } testParams := genValidECDSAParams() for i := 0; i < len(testParams); i++ { params := testutil.NewECDSAParams(testParams[i].hashType, testParams[i].curve, ecdsapb.EcdsaSignatureEncoding_DER) serializedFormat, err := proto.Marshal(testutil.NewECDSAKeyFormat(params)) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } keyData, err := km.NewKeyData(serializedFormat) if err != nil { t.Errorf("unexpected error in test case %d: %s", i, err) } if keyData.TypeUrl != testutil.ECDSASignerTypeURL { t.Errorf("incorrect type url in test case %d: expect %s, got %s", i, testutil.ECDSASignerTypeURL, keyData.TypeUrl) } if keyData.KeyMaterialType != tinkpb.KeyData_ASYMMETRIC_PRIVATE { t.Errorf("incorrect key material type in test case %d: expect %s, got %s", i, tinkpb.KeyData_ASYMMETRIC_PRIVATE, keyData.KeyMaterialType) } key := new(ecdsapb.EcdsaPrivateKey) if err := proto.Unmarshal(keyData.Value, key); err != nil { t.Errorf("unexpect error in test case %d: %s", i, err) } if err := validateECDSAPrivateKey(key, params); err != nil { t.Errorf("invalid private key in test case %d: %s", i, err) } } } func TestECDSASignNewKeyDataWithInvalidInput(t *testing.T) { km, err := registry.GetKeyManager(testutil.ECDSASignerTypeURL) if err != nil { t.Errorf("cannot obtain ECDSASigner key manager: %s", err) } testParams := genInvalidECDSAParams() for i := 0; i < len(testParams); i++ { params := testutil.NewECDSAParams(testParams[i].hashType, testParams[i].curve, ecdsapb.EcdsaSignatureEncoding_DER) format := testutil.NewECDSAKeyFormat(params) serializedFormat, err := proto.Marshal(format) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := km.NewKeyData(serializedFormat); err == nil { t.Errorf("expect an error in test case %d", i) } } // nil input if _, err := km.NewKeyData(nil); err == nil { t.Errorf("expect an error when input is nil") } } func TestPublicKeyDataBasic(t *testing.T) { testParams := genValidECDSAParams() km, err := registry.GetKeyManager(testutil.ECDSASignerTypeURL) if err != nil { t.Errorf("cannot obtain ECDSASigner key manager: %s", err) } pkm, ok := km.(registry.PrivateKeyManager) if !ok { t.Errorf("cannot obtain private key manager") } for i := 0; i < len(testParams); i++ { key := testutil.NewRandomECDSAPrivateKey(testParams[i].hashType, testParams[i].curve) serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } pubKeyData, err := pkm.PublicKeyData(serializedKey) if err != nil { t.Errorf("unexpect error in test case %d: %s ", i, err) } if pubKeyData.TypeUrl != testutil.ECDSAVerifierTypeURL { t.Errorf("incorrect type url: %s", pubKeyData.TypeUrl) } if pubKeyData.KeyMaterialType != tinkpb.KeyData_ASYMMETRIC_PUBLIC { t.Errorf("incorrect key material type: %d", pubKeyData.KeyMaterialType) } pubKey := new(ecdsapb.EcdsaPublicKey) if err = proto.Unmarshal(pubKeyData.Value, pubKey); err != nil { t.Errorf("invalid public key: %s", err) } } } func TestPublicKeyDataWithInvalidInput(t *testing.T) { km, err := registry.GetKeyManager(testutil.ECDSASignerTypeURL) if err != nil { t.Errorf("cannot obtain ECDSASigner key manager: %s", err) } pkm, ok := km.(registry.PrivateKeyManager) if !ok { t.Errorf("cannot obtain private key manager") } // modified key key := testutil.NewRandomECDSAPrivateKey(commonpb.HashType_SHA256, commonpb.EllipticCurveType_NIST_P256) serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } serializedKey[0] = 0 if _, err := pkm.PublicKeyData(serializedKey); err == nil { t.Errorf("expect an error when input is a modified serialized key") } // invalid with a single byte if _, err := pkm.PublicKeyData([]byte{42}); err == nil { t.Errorf("expect an error when input is an empty slice") } } var errSmallKey = fmt.Errorf("private key doesn't have adequate size") func validateECDSAPrivateKey(key *ecdsapb.EcdsaPrivateKey, params *ecdsapb.EcdsaParams) error { if key.Version != testutil.ECDSASignerKeyVersion { return fmt.Errorf("incorrect private key's version: expect %d, got %d", testutil.ECDSASignerKeyVersion, key.Version) } publicKey := key.PublicKey if publicKey.Version != testutil.ECDSASignerKeyVersion { return fmt.Errorf("incorrect public key's version: expect %d, got %d", testutil.ECDSASignerKeyVersion, key.Version) } if params.HashType != publicKey.Params.HashType || params.Curve != publicKey.Params.Curve || params.Encoding != publicKey.Params.Encoding { return fmt.Errorf("incorrect params: expect %s, got %s", params, publicKey.Params) } if len(publicKey.X) == 0 || len(publicKey.Y) == 0 { return fmt.Errorf("public points are not initialized") } // check private key's size d := new(big.Int).SetBytes(key.KeyValue) keySize := len(d.Bytes()) switch params.Curve { case commonpb.EllipticCurveType_NIST_P256: if keySize < 256/8-8 || keySize > 256/8+1 { return errSmallKey } case commonpb.EllipticCurveType_NIST_P384: if keySize < 384/8-8 || keySize > 384/8+1 { return errSmallKey } case commonpb.EllipticCurveType_NIST_P521: if keySize < 521/8-8 || keySize > 521/8+1 { return errSmallKey } } // try to sign and verify with the key hash, curve, encoding := testutil.GetECDSAParamNames(publicKey.Params) signer, err := subtle.NewECDSASigner(hash, curve, encoding, key.KeyValue) if err != nil { return fmt.Errorf("unexpected error when creating ECDSASign: %s", err) } verifier, err := subtle.NewECDSAVerifier(hash, curve, encoding, publicKey.X, publicKey.Y) if err != nil { return fmt.Errorf("unexpected error when creating ECDSAVerify: %s", err) } data := random.GetRandomBytes(1281) signature, err := signer.Sign(data) if err != nil { return fmt.Errorf("unexpected error when signing: %s", err) } if err := verifier.Verify(signature, data); err != nil { return fmt.Errorf("unexpected error when verifying signature: %s", err) } return nil } func genValidECDSAParams() []ecdsaParams { return []ecdsaParams{ ecdsaParams{ hashType: commonpb.HashType_SHA256, curve: commonpb.EllipticCurveType_NIST_P256, }, ecdsaParams{ hashType: commonpb.HashType_SHA384, curve: commonpb.EllipticCurveType_NIST_P384, }, ecdsaParams{ hashType: commonpb.HashType_SHA512, curve: commonpb.EllipticCurveType_NIST_P384, }, ecdsaParams{ hashType: commonpb.HashType_SHA512, curve: commonpb.EllipticCurveType_NIST_P521, }, } } func genUnkownECDSAParams() []ecdsaParams { return []ecdsaParams{ ecdsaParams{ hashType: commonpb.HashType_UNKNOWN_HASH, curve: commonpb.EllipticCurveType_NIST_P256, }, ecdsaParams{ hashType: commonpb.HashType_SHA256, curve: commonpb.EllipticCurveType_UNKNOWN_CURVE, }, } } func genInvalidECDSAParams() []ecdsaParams { return []ecdsaParams{ ecdsaParams{ hashType: commonpb.HashType_SHA1, curve: commonpb.EllipticCurveType_NIST_P256, }, ecdsaParams{ hashType: commonpb.HashType_SHA1, curve: commonpb.EllipticCurveType_NIST_P384, }, ecdsaParams{ hashType: commonpb.HashType_SHA1, curve: commonpb.EllipticCurveType_NIST_P521, }, ecdsaParams{ hashType: commonpb.HashType_SHA256, curve: commonpb.EllipticCurveType_NIST_P384, }, ecdsaParams{ hashType: commonpb.HashType_SHA256, curve: commonpb.EllipticCurveType_NIST_P521, }, ecdsaParams{ hashType: commonpb.HashType_SHA512, curve: commonpb.EllipticCurveType_NIST_P256, }, } } ================================================ FILE: go/signature/ecdsa_verifier_key_manager.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature import ( "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/keyset" "github.com/google/tink/go/signature/subtle" ecdsapb "github.com/google/tink/go/proto/ecdsa_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( ecdsaVerifierKeyVersion = 0 ecdsaVerifierTypeURL = "type.googleapis.com/google.crypto.tink.EcdsaPublicKey" ) // common errors var errInvalidECDSAVerifierKey = fmt.Errorf("ecdsa_verifier_key_manager: invalid key") var errECDSAVerifierNotImplemented = fmt.Errorf("ecdsa_verifier_key_manager: not implemented") // ecdsaVerifierKeyManager is an implementation of KeyManager interface. // It doesn't support key generation. type ecdsaVerifierKeyManager struct{} // Primitive creates an ECDSAVerifier subtle for the given serialized ECDSAPublicKey proto. func (km *ecdsaVerifierKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidECDSAVerifierKey } key := new(ecdsapb.EcdsaPublicKey) if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errInvalidECDSAVerifierKey } if err := km.validateKey(key); err != nil { return nil, fmt.Errorf("ecdsa_verifier_key_manager: %s", err) } hash, curve, encoding := getECDSAParamNames(key.GetParams()) ret, err := subtle.NewECDSAVerifier(hash, curve, encoding, key.X, key.Y) if err != nil { return nil, fmt.Errorf("ecdsa_verifier_key_manager: invalid key: %s", err) } return ret, nil } // NewKey is not implemented. func (km *ecdsaVerifierKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { return nil, errECDSAVerifierNotImplemented } // NewKeyData creates a new KeyData according to specification in the given // serialized ECDSAKeyFormat. It should be used solely by the key management API. func (km *ecdsaVerifierKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { return nil, errECDSAVerifierNotImplemented } // DoesSupport indicates if this key manager supports the given key type. func (km *ecdsaVerifierKeyManager) DoesSupport(typeURL string) bool { return typeURL == ecdsaVerifierTypeURL } // TypeURL returns the key type of keys managed by this key manager. func (km *ecdsaVerifierKeyManager) TypeURL() string { return ecdsaVerifierTypeURL } // validateKey validates the given ECDSAPublicKey. func (km *ecdsaVerifierKeyManager) validateKey(key *ecdsapb.EcdsaPublicKey) error { if err := keyset.ValidateKeyVersion(key.Version, ecdsaVerifierKeyVersion); err != nil { return fmt.Errorf("ecdsa_verifier_key_manager: %s", err) } hash, curve, encoding := getECDSAParamNames(key.GetParams()) return subtle.ValidateECDSAParams(hash, curve, encoding) } ================================================ FILE: go/signature/ecdsa_verifier_key_manager_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature_test import ( "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/testutil" commonpb "github.com/google/tink/go/proto/common_go_proto" ) func TestECDSAVerifyGetPrimitiveBasic(t *testing.T) { testParams := genValidECDSAParams() km, err := registry.GetKeyManager(testutil.ECDSAVerifierTypeURL) if err != nil { t.Errorf("cannot obtain ECDSAVerifier key manager: %s", err) } for i := 0; i < len(testParams); i++ { serializedKey, err := proto.Marshal(testutil.NewRandomECDSAPublicKey(testParams[i].hashType, testParams[i].curve)) if err != nil { t.Errorf("proto.Marshal() err = %v, want nil", err) } _, err = km.Primitive(serializedKey) if err != nil { t.Errorf("unexpect error in test case %d: %s ", i, err) } } } func TestECDSAVerifyWithInvalidPublicKeyFailsCreatingPrimitive(t *testing.T) { km, err := registry.GetKeyManager(testutil.ECDSAVerifierTypeURL) if err != nil { t.Errorf("cannot obtain ECDSAVerifier key manager: %s", err) } pubKey := testutil.NewRandomECDSAPublicKey(commonpb.HashType_SHA256, commonpb.EllipticCurveType_NIST_P256) pubKey.X = []byte{0, 32, 0} pubKey.Y = []byte{0, 32, 0} serializedPubKey, err := proto.Marshal(pubKey) if err != nil { t.Errorf("proto.Marhsal() err = %v, want nil", err) } if _, err := km.Primitive(serializedPubKey); err == nil { t.Errorf("km.Primitive() err = nil, want error") } } func TestECDSAVerifyGetPrimitiveWithInvalidInput(t *testing.T) { testParams := genInvalidECDSAParams() km, err := registry.GetKeyManager(testutil.ECDSAVerifierTypeURL) if err != nil { t.Errorf("cannot obtain ECDSAVerifier key manager: %s", err) } for i := 0; i < len(testParams); i++ { serializedKey, err := proto.Marshal(testutil.NewRandomECDSAPublicKey(testParams[i].hashType, testParams[i].curve)) if err != nil { t.Errorf("proto.Marshal() err = %q, want nil", err) } if _, err := km.Primitive(serializedKey); err == nil { t.Errorf("expect an error in test case %d", i) } } for _, tc := range genUnkownECDSAParams() { k := testutil.NewRandomECDSAPublicKey(commonpb.HashType_SHA256, commonpb.EllipticCurveType_NIST_P256) k.GetParams().Curve = tc.curve k.GetParams().HashType = tc.hashType serializedKey, err := proto.Marshal(k) if err != nil { t.Errorf("proto.Marshal() err = %q, want nil", err) } if _, err := km.Primitive(serializedKey); err == nil { t.Errorf("expect an error in test case with params: (curve = %q, hash = %q)", tc.curve, tc.hashType) } } // invalid version key := testutil.NewRandomECDSAPublicKey(commonpb.HashType_SHA256, commonpb.EllipticCurveType_NIST_P256) key.Version = testutil.ECDSAVerifierKeyVersion + 1 serializedKey, err := proto.Marshal(key) if err != nil { t.Errorf("proto.Marshal() err = %q, want nil", err) } if _, err = km.Primitive(serializedKey); err == nil { t.Errorf("expect an error when version is invalid") } // nil input if _, err := km.Primitive(nil); err == nil { t.Errorf("expect an error when input is nil") } if _, err := km.Primitive([]byte{}); err == nil { t.Errorf("expect an error when input is empty slice") } // params field is nil keyNilParams := testutil.NewRandomECDSAPublicKey(commonpb.HashType_SHA256, commonpb.EllipticCurveType_NIST_P256) keyNilParams.Params = nil serializedKeyNilParams, err := proto.Marshal(keyNilParams) if err != nil { t.Errorf("proto.Marshal() err = %q, want nil", err) } if _, err := km.Primitive(serializedKeyNilParams); err == nil { t.Errorf("km.Primitive(serializedKeyNilParams); err = nil, want non-nil") } } ================================================ FILE: go/signature/ed25519_signer_key_manager.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature import ( "crypto/ed25519" "crypto/rand" "errors" "fmt" "io" "google.golang.org/protobuf/proto" "github.com/google/tink/go/keyset" "github.com/google/tink/go/signature/subtle" ed25519pb "github.com/google/tink/go/proto/ed25519_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( ed25519SignerKeyVersion = 0 ed25519SignerTypeURL = "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey" ) // common errors var errInvalidED25519SignKey = errors.New("ed25519_signer_key_manager: invalid key") var errInvalidED25519SignKeyFormat = errors.New("ed25519_signer_key_manager: invalid key format") // ed25519SignerKeyManager is an implementation of KeyManager interface. // It generates new ED25519PrivateKeys and produces new instances of ED25519Sign subtle. type ed25519SignerKeyManager struct{} // Primitive creates an ED25519Sign subtle for the given serialized ED25519PrivateKey proto. func (km *ed25519SignerKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidED25519SignKey } key := new(ed25519pb.Ed25519PrivateKey) if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errInvalidED25519SignKey } if err := km.validateKey(key); err != nil { return nil, err } ret, err := subtle.NewED25519Signer(key.KeyValue) if err != nil { return nil, fmt.Errorf("ed25519_signer_key_manager: %s", err) } return ret, nil } // NewKey creates a new ED25519PrivateKey according to specification the given serialized ED25519KeyFormat. func (km *ed25519SignerKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { pub, priv, err := ed25519.GenerateKey(rand.Reader) if err != nil { return nil, fmt.Errorf("ed25519_signer_key_manager: cannot generate ED25519 key: %s", err) } return &ed25519pb.Ed25519PrivateKey{ Version: ed25519SignerKeyVersion, KeyValue: priv.Seed(), PublicKey: &ed25519pb.Ed25519PublicKey{ Version: ed25519SignerKeyVersion, KeyValue: pub, }, }, nil } // NewKeyData creates a new KeyData according to specification in the given // serialized ED25519KeyFormat. It should be used solely by the key management API. func (km *ed25519SignerKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { key, err := km.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, errInvalidED25519SignKeyFormat } return &tinkpb.KeyData{ TypeUrl: ed25519SignerTypeURL, Value: serializedKey, KeyMaterialType: km.KeyMaterialType(), }, nil } // PublicKeyData extracts the public key data from the private key. func (km *ed25519SignerKeyManager) PublicKeyData(serializedPrivKey []byte) (*tinkpb.KeyData, error) { privKey := new(ed25519pb.Ed25519PrivateKey) if err := proto.Unmarshal(serializedPrivKey, privKey); err != nil { return nil, errInvalidED25519SignKey } serializedPubKey, err := proto.Marshal(privKey.PublicKey) if err != nil { return nil, errInvalidED25519SignKey } return &tinkpb.KeyData{ TypeUrl: ed25519VerifierTypeURL, Value: serializedPubKey, KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC, }, nil } // DoesSupport indicates if this key manager supports the given key type. func (km *ed25519SignerKeyManager) DoesSupport(typeURL string) bool { return typeURL == ed25519SignerTypeURL } // TypeURL returns the key type of keys managed by this key manager. func (km *ed25519SignerKeyManager) TypeURL() string { return ed25519SignerTypeURL } // KeyMaterialType returns the key material type of this key manager. func (km *ed25519SignerKeyManager) KeyMaterialType() tinkpb.KeyData_KeyMaterialType { return tinkpb.KeyData_ASYMMETRIC_PRIVATE } // DeriveKey derives a new key from serializedKeyFormat and pseudorandomness. // Unlike NewKey, DeriveKey validates serializedKeyFormat's version. func (km *ed25519SignerKeyManager) DeriveKey(serializedKeyFormat []byte, pseudorandomness io.Reader) (proto.Message, error) { keyFormat := new(ed25519pb.Ed25519KeyFormat) if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, fmt.Errorf("ed25519_signer_key_manager: %v", err) } err := keyset.ValidateKeyVersion(keyFormat.Version, ed25519SignerKeyVersion) if err != nil { return nil, fmt.Errorf("ed25519_signer_key_manager: %v", err) } pub, priv, err := ed25519.GenerateKey(pseudorandomness) if err != nil { return nil, fmt.Errorf("ed25519_signer_key_manager: cannot generate ED25519 key: %s", err) } return &ed25519pb.Ed25519PrivateKey{ Version: ed25519SignerKeyVersion, KeyValue: priv.Seed(), PublicKey: &ed25519pb.Ed25519PublicKey{ Version: ed25519SignerKeyVersion, KeyValue: pub, }, }, nil } // validateKey validates the given ED25519PrivateKey. func (km *ed25519SignerKeyManager) validateKey(key *ed25519pb.Ed25519PrivateKey) error { if err := keyset.ValidateKeyVersion(key.Version, ed25519SignerKeyVersion); err != nil { return fmt.Errorf("ed25519_signer_key_manager: invalid key: %s", err) } if len(key.KeyValue) != ed25519.SeedSize { return fmt.Errorf("ed2219_signer_key_manager: invalid key length, got %d", len(key.KeyValue)) } return nil } ================================================ FILE: go/signature/ed25519_signer_key_manager_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature_test import ( "bytes" "crypto/ed25519" "encoding/hex" "fmt" "testing" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/signature/subtle" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" ed25519pb "github.com/google/tink/go/proto/ed25519_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestED25519SignerGetPrimitiveBasic(t *testing.T) { km, err := registry.GetKeyManager(testutil.ED25519SignerTypeURL) if err != nil { t.Errorf("cannot obtain ED25519Signer key manager: %s", err) } pvtKey := testutil.NewED25519PrivateKey() serializedKey, err := proto.Marshal(pvtKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } tmp, err := km.Primitive(serializedKey) if err != nil { t.Errorf("unexpect error in test case: %s ", err) } var s = tmp.(*subtle.ED25519Signer) kmPub, err := registry.GetKeyManager(testutil.ED25519VerifierTypeURL) if err != nil { t.Errorf("cannot obtain ED25519Signer key manager: %s", err) } pubKey := pvtKey.PublicKey serializedKey, err = proto.Marshal(pubKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } tmp, err = kmPub.Primitive(serializedKey) if err != nil { t.Errorf("unexpect error in test case: %s ", err) } var v = tmp.(*subtle.ED25519Verifier) data := random.GetRandomBytes(1281) signature, err := s.Sign(data) if err != nil { t.Errorf("unexpected error when signing: %s", err) } if err := v.Verify(signature, data); err != nil { t.Errorf("unexpected error when verifying signature: %s", err) } } func TestED25519SignGetPrimitiveWithInvalidInput(t *testing.T) { // invalid params km, err := registry.GetKeyManager(testutil.ED25519SignerTypeURL) if err != nil { t.Errorf("cannot obtain ED25519Signer key manager: %s", err) } // invalid version key := testutil.NewED25519PrivateKey() key.Version = testutil.ED25519SignerKeyVersion + 1 serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := km.Primitive(serializedKey); err == nil { t.Errorf("expect an error when version is invalid") } // nil input if _, err := km.Primitive(nil); err == nil { t.Errorf("expect an error when input is nil") } if _, err := km.Primitive([]byte{}); err == nil { t.Errorf("expect an error when input is empty slice") } } func TestED25519SignNewKeyBasic(t *testing.T) { km, err := registry.GetKeyManager(testutil.ED25519SignerTypeURL) if err != nil { t.Errorf("cannot obtain ED25519Signer key manager: %s", err) } serializedFormat, err := proto.Marshal(testutil.NewED25519PrivateKey()) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } tmp, err := km.NewKey(serializedFormat) if err != nil { t.Errorf("unexpected error: %s", err) } key := tmp.(*ed25519pb.Ed25519PrivateKey) if err := validateED25519PrivateKey(key); err != nil { t.Errorf("invalid private key in test case: %s", err) } } func TestED25519PublicKeyDataBasic(t *testing.T) { km, err := registry.GetKeyManager(testutil.ED25519SignerTypeURL) if err != nil { t.Errorf("cannot obtain ED25519Signer key manager: %s", err) } pkm, ok := km.(registry.PrivateKeyManager) if !ok { t.Errorf("cannot obtain private key manager") } key := testutil.NewED25519PrivateKey() serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } pubKeyData, err := pkm.PublicKeyData(serializedKey) if err != nil { t.Errorf("unexpect error in test case: %s ", err) } if pubKeyData.TypeUrl != testutil.ED25519VerifierTypeURL { t.Errorf("incorrect type url: %s", pubKeyData.TypeUrl) } if pubKeyData.KeyMaterialType != tinkpb.KeyData_ASYMMETRIC_PUBLIC { t.Errorf("incorrect key material type: %d", pubKeyData.KeyMaterialType) } pubKey := new(ed25519pb.Ed25519PublicKey) if err = proto.Unmarshal(pubKeyData.Value, pubKey); err != nil { t.Errorf("invalid public key: %s", err) } } func TestED25519PublicKeyDataWithInvalidInput(t *testing.T) { km, err := registry.GetKeyManager(testutil.ED25519SignerTypeURL) if err != nil { t.Errorf("cannot obtain ED25519Signer key manager: %s", err) } pkm, ok := km.(registry.PrivateKeyManager) if !ok { t.Errorf("cannot obtain private key manager") } // modified key key := testutil.NewED25519PrivateKey() serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } serializedKey[0] = 0 if _, err := pkm.PublicKeyData(serializedKey); err == nil { t.Errorf("expect an error when input is a modified serialized key") } // invalid with a single byte if _, err := pkm.PublicKeyData([]byte{42}); err == nil { t.Errorf("expect an error when input is an empty slice") } } func TestED25519KeyMaterialType(t *testing.T) { km, err := registry.GetKeyManager(testutil.ED25519SignerTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.ED25519SignerTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } if got, want := keyManager.KeyMaterialType(), tinkpb.KeyData_ASYMMETRIC_PRIVATE; got != want { t.Errorf("KeyMaterialType() = %v, want %v", got, want) } } func TestED25519DeriveKey(t *testing.T) { km, err := registry.GetKeyManager(testutil.ED25519SignerTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.ED25519SignerTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } keyFormat, err := proto.Marshal(&ed25519pb.Ed25519KeyFormat{Version: testutil.ED25519SignerKeyVersion}) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } for _, test := range []struct { name string keyFormat []byte }{ { // nil unmarshals to an empty proto, which implies version = 0. name: "nil", keyFormat: nil, }, { // An empty proto implies version = 0. name: "empty", keyFormat: []byte{}, }, { name: "specified", keyFormat: keyFormat, }, } { t.Run(test.name, func(t *testing.T) { rand := random.GetRandomBytes(ed25519.SeedSize) buf := &bytes.Buffer{} buf.Write(rand) // never returns a non-nil error k, err := keyManager.DeriveKey(test.keyFormat, buf) if err != nil { t.Fatalf("keyManager.DeriveKey() err = %v, want nil", err) } key := k.(*ed25519pb.Ed25519PrivateKey) if got, want := len(key.KeyValue), ed25519.SeedSize; got != want { t.Errorf("private key length = %d, want %d", got, want) } if diff := cmp.Diff(key.KeyValue, rand[:ed25519.SeedSize]); diff != "" { t.Errorf("incorrect derived private key: diff = %v", diff) } if got, want := len(key.PublicKey.KeyValue), ed25519.PublicKeySize; got != want { t.Errorf("public key length = %d, want %d", got, want) } if diff := cmp.Diff(key.PublicKey.KeyValue, []byte(ed25519.NewKeyFromSeed(rand))[32:]); diff != "" { t.Errorf("incorrect derived public key: diff = %v", diff) } }) } } func TestED25519DeriveKeyFailsWithInvalidKeyFormats(t *testing.T) { km, err := registry.GetKeyManager(testutil.ED25519SignerTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.ED25519SignerTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } invalidVersion, err := proto.Marshal(&ed25519pb.Ed25519KeyFormat{Version: 10}) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } // Proto messages start with a VarInt, which always ends with a byte with the // MSB unset, so 0x80 is invalid. invalidSerialization, err := hex.DecodeString("80") if err != nil { t.Errorf("hex.DecodeString() err = %v, want nil", err) } for _, test := range []struct { name string keyFormat []byte }{ { name: "invalid version", keyFormat: invalidVersion, }, { name: "invalid serialization", keyFormat: invalidSerialization, }, } { t.Run(test.name, func(t *testing.T) { buf := bytes.NewBuffer(random.GetRandomBytes(ed25519.SeedSize)) if _, err := keyManager.DeriveKey(test.keyFormat, buf); err == nil { t.Errorf("keyManager.DeriveKey() err = nil, want non-nil") } }) } } func TestED25519DeriveKeyFailsWithInsufficientRandomness(t *testing.T) { km, err := registry.GetKeyManager(testutil.ED25519SignerTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.ED25519SignerTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } keyFormat, err := proto.Marshal(&ed25519pb.Ed25519KeyFormat{Version: 0}) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } { buf := bytes.NewBuffer(random.GetRandomBytes(ed25519.SeedSize)) if _, err := keyManager.DeriveKey(keyFormat, buf); err != nil { t.Errorf("keyManager.DeriveKey() err = %v, want nil", err) } } { insufficientBuf := bytes.NewBuffer(random.GetRandomBytes(ed25519.SeedSize - 1)) if _, err := keyManager.DeriveKey(keyFormat, insufficientBuf); err == nil { t.Errorf("keyManager.DeriveKey() err = nil, want non-nil") } } } func validateED25519PrivateKey(key *ed25519pb.Ed25519PrivateKey) error { if key.Version != testutil.ED25519SignerKeyVersion { return fmt.Errorf("incorrect private key's version: expect %d, got %d", testutil.ED25519SignerKeyVersion, key.Version) } publicKey := key.PublicKey if publicKey.Version != testutil.ED25519SignerKeyVersion { return fmt.Errorf("incorrect public key's version: expect %d, got %d", testutil.ED25519SignerKeyVersion, key.Version) } signer, err := subtle.NewED25519Signer(key.KeyValue) if err != nil { return fmt.Errorf("unexpected error when creating ED25519Sign: %s", err) } verifier, err := subtle.NewED25519Verifier(publicKey.KeyValue) if err != nil { return fmt.Errorf("unexpected error when creating ED25519Verify: %s", err) } for i := 0; i < 100; i++ { data := random.GetRandomBytes(1281) signature, err := signer.Sign(data) if err != nil { return fmt.Errorf("unexpected error when signing: %s", err) } if err := verifier.Verify(signature, data); err != nil { return fmt.Errorf("unexpected error when verifying signature: %s", err) } } return nil } ================================================ FILE: go/signature/ed25519_verifier_key_manager.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature import ( "crypto/ed25519" "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/keyset" "github.com/google/tink/go/signature/subtle" ed25519pb "github.com/google/tink/go/proto/ed25519_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( ed25519VerifierKeyVersion = 0 ed25519VerifierTypeURL = "type.googleapis.com/google.crypto.tink.Ed25519PublicKey" ) // common errors var errInvalidED25519VerifierKey = fmt.Errorf("ed25519_verifier_key_manager: invalid key") var errED25519VerifierNotImplemented = fmt.Errorf("ed25519_verifier_key_manager: not implemented") // ed25519VerifierKeyManager is an implementation of KeyManager interface. // It doesn't support key generation. type ed25519VerifierKeyManager struct{} // Primitive creates an ED25519Verifier subtle for the given serialized ED25519PublicKey proto. func (km *ed25519VerifierKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidED25519VerifierKey } key := new(ed25519pb.Ed25519PublicKey) if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errInvalidED25519VerifierKey } if err := km.validateKey(key); err != nil { return nil, fmt.Errorf("ed25519_verifier_key_manager: %s", err) } ret, err := subtle.NewED25519Verifier(key.KeyValue) if err != nil { return nil, fmt.Errorf("ed25519_verifier_key_manager: invalid key: %s", err) } return ret, nil } // NewKey is not implemented. func (km *ed25519VerifierKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { return nil, errED25519VerifierNotImplemented } // NewKeyData creates a new KeyData according to specification in the given // serialized ED25519KeyFormat. It should be used solely by the key management API. func (km *ed25519VerifierKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { return nil, errED25519VerifierNotImplemented } // DoesSupport indicates if this key manager supports the given key type. func (km *ed25519VerifierKeyManager) DoesSupport(typeURL string) bool { return typeURL == ed25519VerifierTypeURL } // TypeURL returns the key type of keys managed by this key manager. func (km *ed25519VerifierKeyManager) TypeURL() string { return ed25519VerifierTypeURL } // validateKey validates the given ED25519PublicKey. func (km *ed25519VerifierKeyManager) validateKey(key *ed25519pb.Ed25519PublicKey) error { if err := keyset.ValidateKeyVersion(key.Version, ed25519VerifierKeyVersion); err != nil { return fmt.Errorf("ed25519_verifier_key_manager: %s", err) } if len(key.KeyValue) != ed25519.PublicKeySize { return fmt.Errorf("ed25519_verifier_key_manager: invalid key length, required :%d", ed25519.PublicKeySize) } return nil } ================================================ FILE: go/signature/ed25519_verifier_key_manager_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature_test import ( "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/testutil" ) func TestED25519VerifyGetPrimitiveBasic(t *testing.T) { km, err := registry.GetKeyManager(testutil.ED25519VerifierTypeURL) if err != nil { t.Errorf("cannot obtain ED25519Verifier key manager: %s", err) } serializedKey, err := proto.Marshal(testutil.NewED25519PublicKey()) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } _, err = km.Primitive(serializedKey) if err != nil { t.Errorf("unexpect error in test case: %s ", err) } } func TestED25519VerifyGetPrimitiveWithInvalidInput(t *testing.T) { km, err := registry.GetKeyManager(testutil.ED25519VerifierTypeURL) if err != nil { t.Errorf("cannot obtain ED25519Verifier key manager: %s", err) } // invalid version key := testutil.NewED25519PublicKey() key.Version = testutil.ED25519VerifierKeyVersion + 1 serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } if _, err := km.Primitive(serializedKey); err == nil { t.Errorf("expect an error when version is invalid") } // nil input if _, err := km.Primitive(nil); err == nil { t.Errorf("expect an error when input is nil") } if _, err := km.Primitive([]byte{}); err == nil { t.Errorf("expect an error when input is empty slice") } } ================================================ FILE: go/signature/proto.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature import ( commonpb "github.com/google/tink/go/proto/common_go_proto" ecdsapb "github.com/google/tink/go/proto/ecdsa_go_proto" ) // getECDSAParamNames returns the string representations of each parameter in // the given ECDSAParams. func getECDSAParamNames(params *ecdsapb.EcdsaParams) (string, string, string) { hashName := commonpb.HashType_name[int32(params.GetHashType())] curveName := commonpb.EllipticCurveType_name[int32(params.GetCurve())] encodingName := ecdsapb.EcdsaSignatureEncoding_name[int32(params.GetEncoding())] return hashName, curveName, encodingName } // newECDSAPrivateKey creates a ECDSAPrivateKey with the specified paramaters. func newECDSAPrivateKey(version uint32, publicKey *ecdsapb.EcdsaPublicKey, keyValue []byte) *ecdsapb.EcdsaPrivateKey { return &ecdsapb.EcdsaPrivateKey{ Version: version, PublicKey: publicKey, KeyValue: keyValue, } } // newECDSAPublicKey creates a ECDSAPublicKey with the specified paramaters. func newECDSAPublicKey(version uint32, params *ecdsapb.EcdsaParams, x, y []byte) *ecdsapb.EcdsaPublicKey { return &ecdsapb.EcdsaPublicKey{ Version: version, Params: params, X: x, Y: y, } } ================================================ FILE: go/signature/rsa.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature import ( "fmt" "math/big" internal "github.com/google/tink/go/internal/signature" commonpb "github.com/google/tink/go/proto/common_go_proto" ) func bytesToBigInt(val []byte) *big.Int { return new(big.Int).SetBytes(val) } func validateRSAPubKeyParams(h commonpb.HashType, modSizeBits int, pubExponent []byte) error { if err := internal.HashSafeForSignature(hashName(h)); err != nil { return err } if err := internal.RSAValidModulusSizeInBits(modSizeBits); err != nil { return err } e := bytesToBigInt(pubExponent) if !e.IsInt64() { return fmt.Errorf("public exponent can't fit in a 64 bit integer") } return internal.RSAValidPublicExponent(int(e.Int64())) } func hashName(h commonpb.HashType) string { return commonpb.HashType_name[int32(h)] } ================================================ FILE: go/signature/rsassapkcs1_signer_key_manager.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature import ( "crypto/rand" "crypto/rsa" "errors" "fmt" "math/big" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" internal "github.com/google/tink/go/internal/signature" "github.com/google/tink/go/keyset" rsassapkcs1pb "github.com/google/tink/go/proto/rsa_ssa_pkcs1_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( rsaSSAPKCS1SignerKeyVersion = 0 rsaSSAPKCS1SignerTypeURL = "type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PrivateKey" ) var ( errInvalidRSASSAPKCS1SignKey = errors.New("rsassapkcs1_signer_key_manager: invalid key") errInvalidRSASSAPKCS1SignKeyFormat = errors.New("rsassapkcs1_signer_key_manager: invalid key format") ) type rsaSSAPKCS1SignerKeyManager struct{} var _ registry.PrivateKeyManager = (*rsaSSAPKCS1SignerKeyManager)(nil) func (km *rsaSSAPKCS1SignerKeyManager) Primitive(serializedKey []byte) (any, error) { if false { return nil, errInvalidRSASSAPKCS1SignKey } key := &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{} if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, err } if err := validateRSAPKCS1PrivateKey(key); err != nil { return nil, err } privKey := &rsa.PrivateKey{ D: bytesToBigInt(key.GetD()), PublicKey: rsa.PublicKey{ N: bytesToBigInt(key.GetPublicKey().GetN()), E: int(bytesToBigInt(key.GetPublicKey().GetE()).Int64()), }, Primes: []*big.Int{ bytesToBigInt(key.GetP()), bytesToBigInt(key.GetQ()), }, } if err := privKey.Validate(); err != nil { return nil, err } // Instead of extracting Dp, Dq, and Qinv values from the key proto, // the values must be computed by the Go library. // // See https://pkg.go.dev/crypto/rsa#PrivateKey. privKey.Precompute() h := hashName(key.GetPublicKey().GetParams().GetHashType()) if err := internal.Validate_RSA_SSA_PKCS1(h, privKey); err != nil { return nil, err } return internal.New_RSA_SSA_PKCS1_Signer(h, privKey) } func validateRSAPKCS1PrivateKey(privKey *rsassapkcs1pb.RsaSsaPkcs1PrivateKey) error { if err := keyset.ValidateKeyVersion(privKey.GetVersion(), rsaSSAPKCS1SignerKeyVersion); err != nil { return err } if len(privKey.GetD()) == 0 || len(privKey.GetPublicKey().GetN()) == 0 || len(privKey.GetPublicKey().GetE()) == 0 || len(privKey.GetP()) == 0 || len(privKey.GetQ()) == 0 || len(privKey.GetDp()) == 0 || len(privKey.GetDq()) == 0 || len(privKey.GetCrt()) == 0 { return errInvalidRSASSAPKCS1SignKey } return validateRSAPKCS1PublicKey(privKey.GetPublicKey()) } func (km *rsaSSAPKCS1SignerKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errInvalidRSASSAPKCS1SignKeyFormat } keyFormat := &rsassapkcs1pb.RsaSsaPkcs1KeyFormat{} if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, err } if err := validateRSAPubKeyParams( keyFormat.GetParams().GetHashType(), int(keyFormat.GetModulusSizeInBits()), keyFormat.GetPublicExponent()); err != nil { return nil, err } rsaKey, err := rsa.GenerateKey(rand.Reader, int(keyFormat.GetModulusSizeInBits())) if err != nil { return nil, fmt.Errorf("generating RSA key: %s", err) } pubKey := &rsassapkcs1pb.RsaSsaPkcs1PublicKey{ Version: rsaSSAPKCS1SignerKeyVersion, Params: &rsassapkcs1pb.RsaSsaPkcs1Params{ HashType: keyFormat.GetParams().GetHashType(), }, N: rsaKey.PublicKey.N.Bytes(), E: big.NewInt(int64(rsaKey.PublicKey.E)).Bytes(), } return &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: rsaSSAPKCS1SignerKeyVersion, PublicKey: pubKey, D: rsaKey.D.Bytes(), P: rsaKey.Primes[0].Bytes(), Q: rsaKey.Primes[1].Bytes(), Dp: rsaKey.Precomputed.Dp.Bytes(), Dq: rsaKey.Precomputed.Dq.Bytes(), // In crypto/rsa `Qinv` is the "Chinese Remainder Theorem // coefficient q^(-1) mod p". This corresponds with `Crt` in // the Tink proto. This is unrelated to `CRTValues`, which // contains values specifically for additional primes, which // are not supported by Tink. Crt: rsaKey.Precomputed.Qinv.Bytes(), }, nil } func (km *rsaSSAPKCS1SignerKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { key, err := km.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, errInvalidRSASSAPKCS1SignKeyFormat } return &tinkpb.KeyData{ TypeUrl: rsaSSAPKCS1SignerTypeURL, Value: serializedKey, KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PRIVATE, }, nil } // PublicKeyData extracts the public key data from the private key. func (km *rsaSSAPKCS1SignerKeyManager) PublicKeyData(serializedPrivKey []byte) (*tinkpb.KeyData, error) { privKey := &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{} if err := proto.Unmarshal(serializedPrivKey, privKey); err != nil { return nil, err } if err := validateRSAPKCS1PrivateKey(privKey); err != nil { return nil, err } serializedPubKey, err := proto.Marshal(privKey.GetPublicKey()) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: rsaSSAPKCS1VerifierTypeURL, Value: serializedPubKey, KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC, }, nil } // DoesSupport indicates if this key manager supports the given key type. func (km *rsaSSAPKCS1SignerKeyManager) DoesSupport(typeURL string) bool { return typeURL == rsaSSAPKCS1SignerTypeURL } // TypeURL returns the key type of keys managed by this key manager. func (km *rsaSSAPKCS1SignerKeyManager) TypeURL() string { return rsaSSAPKCS1SignerTypeURL } ================================================ FILE: go/signature/rsassapkcs1_signer_key_manager_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature_test import ( "encoding/hex" "math/big" "testing" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" internal "github.com/google/tink/go/internal/signature" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/tink" cpb "github.com/google/tink/go/proto/common_go_proto" rsassapkcs1pb "github.com/google/tink/go/proto/rsa_ssa_pkcs1_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( rsaPKCS1PrivateKeyTypeURL = "type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PrivateKey" ) func TestRSASSAPKCS1SignerKeyManagerDoesSupport(t *testing.T) { skm, err := registry.GetKeyManager(rsaPKCS1PrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PrivateKeyTypeURL, err) } if !skm.DoesSupport(rsaPKCS1PrivateKeyTypeURL) { t.Errorf("DoesSupport(%q) = false, want true", rsaPKCS1PrivateKeyTypeURL) } if skm.DoesSupport("not.valid.type") { t.Errorf("DoesSupport(%q) = true, want false", "not.valid.type") } } func TestRSASSAPKCS1SignerTypeURL(t *testing.T) { skm, err := registry.GetKeyManager(rsaPKCS1PrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PrivateKeyTypeURL, err) } if skm.TypeURL() != rsaPKCS1PrivateKeyTypeURL { t.Errorf("TypeURL() = %q, want %q", skm.TypeURL(), rsaPKCS1PrivateKeyTypeURL) } } func TestRSASSAPKCS1SignerKeyManagerPublicKeyData(t *testing.T) { skm, err := registry.GetKeyManager(rsaPKCS1PrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PrivateKeyTypeURL, err) } vkm, err := registry.GetKeyManager(rsaPKCS1PublicTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PublicTypeURL, err) } privKey, err := makeValidRSAPKCS1Key() if err != nil { t.Fatalf("makeValidRSAPKCS1Key() err = %v, want nil", err) } serializedPrivate, err := proto.Marshal(privKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } got, err := skm.(registry.PrivateKeyManager).PublicKeyData(serializedPrivate) if err != nil { t.Fatalf("PublicKeyData() err = %v, want nil", err) } if got.GetKeyMaterialType() != tinkpb.KeyData_ASYMMETRIC_PUBLIC { t.Errorf("GetKeyMaterialType() = %q, want %q", got.GetKeyMaterialType(), tinkpb.KeyData_ASYMMETRIC_PUBLIC) } if got.GetTypeUrl() != rsaPKCS1PublicTypeURL { t.Errorf("GetTypeUrl() = %q, want %q", got.GetTypeUrl(), rsaPKCS1PublicTypeURL) } if _, err := vkm.Primitive(got.GetValue()); err != nil { t.Errorf("Primitive() err = %v, want nil", err) } } func TestRSASSAPKCS1SignerKeyManagerPrimitiveSignVerify(t *testing.T) { skm, err := registry.GetKeyManager(rsaPKCS1PrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PrivateKeyTypeURL, err) } privKey, err := makeValidRSAPKCS1Key() if err != nil { t.Fatalf("makeValidRSAPKCS1Key() err = %v, want nil", err) } serializedPrivate, err := proto.Marshal(privKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } p, err := skm.Primitive(serializedPrivate) if err != nil { t.Fatalf("Primitive() err = %v, want nil", err) } signer, ok := p.(*internal.RSA_SSA_PKCS1_Signer) if !ok { t.Fatalf("primitive is not of type RSA_SSA_PKCS1_Signer") } vkm, err := registry.GetKeyManager(rsaPKCS1PublicTypeURL) if err != nil { t.Fatalf("regitry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PublicTypeURL, err) } serializedPublic, err := proto.Marshal(privKey.PublicKey) if err != nil { t.Fatalf("Failed serializing public key proto: %v", err) } p, err = vkm.Primitive(serializedPublic) if err != nil { t.Fatalf("rsaSSAPKCS1VerifierKeyManager.Primitive() failed: %v", err) } v, ok := p.(*internal.RSA_SSA_PKCS1_Verifier) if !ok { t.Fatalf("primitve is not of type RSA_SSA_PKCS1_Verifier") } data := random.GetRandomBytes(1281) signature, err := signer.Sign(data) if err != nil { t.Fatalf("Sign() err = %v, want nil", err) } if err := v.Verify(signature, data); err != nil { t.Fatalf("Verify() err = %v, want nil", err) } } func TestRSASSAPKCS1SignerKeyManagerPrimitiveWithInvalidInputFails(t *testing.T) { km, err := registry.GetKeyManager(rsaPKCS1PrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PrivateKeyTypeURL, err) } validPrivKey, err := makeValidRSAPKCS1Key() if err != nil { t.Fatalf("makeValidRSAPKCS1Key() err = %v, want nil", err) } serializedValidPrivate, err := proto.Marshal(validPrivKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := km.Primitive(serializedValidPrivate); err != nil { t.Fatalf("Primitive(serializedValidPrivate) err = %v, want nil", err) } type testCase struct { name string key *rsassapkcs1pb.RsaSsaPkcs1PrivateKey } for _, tc := range []testCase{ { name: "empty key", key: &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{}, }, { name: "nil key", key: nil, }, { name: "invalid version", key: &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: validPrivKey.GetVersion() + 1, PublicKey: validPrivKey.GetPublicKey(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid hash algorithm ", key: &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: &rsassapkcs1pb.RsaSsaPkcs1PublicKey{ Version: validPrivKey.GetPublicKey().GetVersion(), E: validPrivKey.GetPublicKey().GetE(), N: validPrivKey.GetPublicKey().GetN(), Params: &rsassapkcs1pb.RsaSsaPkcs1Params{ HashType: cpb.HashType_SHA224, }, }, D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "public key params field unset", key: &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: &rsassapkcs1pb.RsaSsaPkcs1PublicKey{ Version: validPrivKey.GetPublicKey().GetVersion(), E: validPrivKey.GetPublicKey().GetE(), N: validPrivKey.GetPublicKey().GetN(), Params: nil, }, D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid modulus", key: &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: &rsassapkcs1pb.RsaSsaPkcs1PublicKey{ Version: validPrivKey.GetPublicKey().GetVersion(), E: validPrivKey.GetPublicKey().GetE(), N: []byte{3, 4, 5}, Params: validPrivKey.GetPublicKey().GetParams(), }, D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid public key exponent", key: &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: &rsassapkcs1pb.RsaSsaPkcs1PublicKey{ Version: validPrivKey.GetPublicKey().GetVersion(), E: []byte{0x06}, N: validPrivKey.GetPublicKey().GetN(), Params: validPrivKey.GetPublicKey().GetParams(), }, D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid private key D value", key: &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: validPrivKey.GetPublicKey(), D: nil, P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid private key P value", key: &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: validPrivKey.GetPublicKey(), D: validPrivKey.GetD(), P: nil, Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid private key Q value", key: &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: validPrivKey.GetPublicKey(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: nil, Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid precomputed Dp values in private key", key: &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: validPrivKey.GetPublicKey(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: nil, Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid precomputed Dq values in private key", key: &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: validPrivKey.GetPublicKey(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: nil, Crt: validPrivKey.GetCrt(), }, }, { name: "invalid precomputed Crt values in private key", key: &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: validPrivKey.GetPublicKey(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: nil, }, }, } { t.Run(tc.name, func(t *testing.T) { serializedKey, err := proto.Marshal(tc.key) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := km.Primitive(serializedKey); err == nil { t.Errorf("Primitive() err = nil, want error") } if _, err := km.(registry.PrivateKeyManager).PublicKeyData(serializedKey); err == nil { t.Errorf("PublicKeyData() err = nil, want error") } }) } } func TestRSASSAPKCS1SignerKeyManagerPrimitiveWithCorruptedKeyFails(t *testing.T) { km, err := registry.GetKeyManager(rsaPKCS1PrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PrivateKeyTypeURL, err) } corruptedPrivKey, err := makeValidRSAPKCS1Key() if err != nil { t.Fatalf("makeValidRSAPKCS1Key() err = %v, want nil", err) } corruptedPrivKey.P[5] = byte(uint8(corruptedPrivKey.P[5] + 1)) corruptedPrivKey.P[10] = byte(uint8(corruptedPrivKey.P[10] + 1)) serializedCorruptedPrivate, err := proto.Marshal(corruptedPrivKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := km.Primitive(serializedCorruptedPrivate); err == nil { t.Errorf("Primitive() err = nil, want error") } } func TestRSASSAPKCS1SignerKeyManagerPrimitiveNewKey(t *testing.T) { km, err := registry.GetKeyManager(rsaPKCS1PrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PrivateKeyTypeURL, err) } validPrivKey, err := makeValidRSAPKCS1Key() if err != nil { t.Fatalf("makeValidRSAPKCS1Key() err = %v, want nil", err) } keyFormat := &rsassapkcs1pb.RsaSsaPkcs1KeyFormat{ Params: &rsassapkcs1pb.RsaSsaPkcs1Params{ HashType: cpb.HashType_SHA256, }, ModulusSizeInBits: 3072, PublicExponent: []byte{0x01, 0x00, 0x01}, } serializedFormat, err := proto.Marshal(keyFormat) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } m, err := km.NewKey(serializedFormat) if err != nil { t.Fatalf("NewKey() err = %v, want nil", err) } privKey, ok := m.(*rsassapkcs1pb.RsaSsaPkcs1PrivateKey) if !ok { t.Fatalf("privateKey is not a RsaSsaPkcs1PrivateKey") } if privKey.GetVersion() != validPrivKey.GetVersion() { t.Errorf("GetVersion() = %d, want %d", privKey.GetVersion(), validPrivKey.GetVersion()) } wantPubKey := validPrivKey.GetPublicKey() gotPubKey := privKey.GetPublicKey() if gotPubKey.GetParams().GetHashType() != wantPubKey.GetParams().GetHashType() { t.Errorf("GetHashType() = %v, want %v", gotPubKey.GetParams().GetHashType(), wantPubKey.GetParams().GetHashType()) } if !cmp.Equal(gotPubKey.GetE(), wantPubKey.GetE()) { t.Errorf("GetE() = %v, want %v", gotPubKey.GetE(), wantPubKey.GetE()) } gotModSize := new(big.Int).SetBytes(gotPubKey.GetN()).BitLen() if gotModSize != 3072 { t.Errorf("Modulus Size = %d, want %d", gotModSize, 3072) } } func TestRSASSAPKCS1SignerKeyManagerPrimitiveNewKeyWithInvalidInputFails(t *testing.T) { type testCase struct { name string format *rsassapkcs1pb.RsaSsaPkcs1KeyFormat } km, err := registry.GetKeyManager(rsaPKCS1PrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PrivateKeyTypeURL, err) } for _, tc := range []testCase{ { name: "empty format", format: &rsassapkcs1pb.RsaSsaPkcs1KeyFormat{}, }, { name: "invalid hash", format: &rsassapkcs1pb.RsaSsaPkcs1KeyFormat{ ModulusSizeInBits: 2048, PublicExponent: []byte{0x01, 0x00, 0x01}, Params: &rsassapkcs1pb.RsaSsaPkcs1Params{ HashType: cpb.HashType_SHA224, }, }, }, { name: "invalid public exponent", format: &rsassapkcs1pb.RsaSsaPkcs1KeyFormat{ ModulusSizeInBits: 2048, PublicExponent: []byte{0x01}, Params: &rsassapkcs1pb.RsaSsaPkcs1Params{ HashType: cpb.HashType_SHA256, }, }, }, { name: "invalid modulus size", format: &rsassapkcs1pb.RsaSsaPkcs1KeyFormat{ ModulusSizeInBits: 1024, PublicExponent: []byte{0x01}, Params: &rsassapkcs1pb.RsaSsaPkcs1Params{ HashType: cpb.HashType_SHA256, }, }, }, } { t.Run(tc.name, func(t *testing.T) { serializedFormat, err := proto.Marshal(tc.format) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := km.NewKey(serializedFormat); err == nil { t.Fatalf("NewKey() err = nil, want error") } }) } } func TestRSASSAPKCS1SignerKeyManagerPrimitiveNewKeyData(t *testing.T) { km, err := registry.GetKeyManager(rsaPKCS1PrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PrivateKeyTypeURL, err) } keyFormat := &rsassapkcs1pb.RsaSsaPkcs1KeyFormat{ ModulusSizeInBits: 2048, PublicExponent: []byte{0x01, 0x00, 0x01}, Params: &rsassapkcs1pb.RsaSsaPkcs1Params{ HashType: cpb.HashType_SHA256, }, } serializedFormat, err := proto.Marshal(keyFormat) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } keyData, err := km.NewKeyData(serializedFormat) if err != nil { t.Fatalf("NewKeyData() err = %v, want nil", err) } if keyData.GetTypeUrl() != rsaPKCS1PrivateKeyTypeURL { t.Errorf("GetTypeUrl() = %v, want %v", keyData.GetTypeUrl(), rsaPKCS1PrivateKeyTypeURL) } if keyData.GetKeyMaterialType() != tinkpb.KeyData_ASYMMETRIC_PRIVATE { t.Errorf("GetKeyMaterialType() = %v, want %v", keyData.GetKeyMaterialType(), tinkpb.KeyData_ASYMMETRIC_PRIVATE) } if _, err := km.Primitive(keyData.GetValue()); err != nil { t.Errorf("Primitive() err = %v, want nil", err) } } func TestRSASSAPKCS1SignerKeyManagerPrimitiveNISTTestVectors(t *testing.T) { km, err := registry.GetKeyManager(rsaPKCS1PrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PrivateKeyTypeURL, err) } for _, tc := range nistPKCS1TestVectors { t.Run(tc.name, func(t *testing.T) { key, err := tc.ToProtoKey() if err != nil { t.Fatalf("tc.ToProtoKey() err = %v, want nil", err) } serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } p, err := km.Primitive(serializedKey) if err != nil { t.Fatalf("km.Primitive() err = %v, want nil", err) } msg, err := hex.DecodeString(tc.msg) if err != nil { t.Fatalf("hex.DecodeString(tc.msg) err = %v, want nil", err) } signer, ok := p.(tink.Signer) if !ok { t.Fatalf("primitive isn't a Tink.Signer") } sig, err := signer.Sign(msg) if err != nil { t.Fatalf("p.(tink.Signer).Sign(msg) err = %v, want nil", err) } gotSig := hex.EncodeToString(sig) if !cmp.Equal(gotSig, tc.sig) { t.Errorf("Sign() = %q, want %q", gotSig, tc.sig) } }) } } ================================================ FILE: go/signature/rsassapkcs1_verifier_key_manager.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature import ( "crypto/rsa" "errors" "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" internal "github.com/google/tink/go/internal/signature" "github.com/google/tink/go/keyset" rsassapkcs1pb "github.com/google/tink/go/proto/rsa_ssa_pkcs1_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( rsaSSAPKCS1VerifierKeyVersion = 0 rsaSSAPKCS1VerifierTypeURL = "type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PublicKey" ) var ( errRSASSAPKCS1NotImplemented = errors.New("rsassapkcs1_verifier_key_manager: not implemented") ) type rsaSSAPKCS1VerifierKeyManager struct{} var _ registry.KeyManager = (*rsaSSAPKCS1VerifierKeyManager)(nil) func (km *rsaSSAPKCS1VerifierKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, fmt.Errorf("rsassapkcs1_verifier_key_manager: invalid serialized public key") } key := &rsassapkcs1pb.RsaSsaPkcs1PublicKey{} if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, err } if err := validateRSAPKCS1PublicKey(key); err != nil { return nil, err } keyData := &rsa.PublicKey{ E: int(bytesToBigInt(key.GetE()).Int64()), N: bytesToBigInt(key.GetN()), } return internal.New_RSA_SSA_PKCS1_Verifier(hashName(key.GetParams().GetHashType()), keyData) } func validateRSAPKCS1PublicKey(pubKey *rsassapkcs1pb.RsaSsaPkcs1PublicKey) error { if err := keyset.ValidateKeyVersion(pubKey.GetVersion(), rsaSSAPKCS1VerifierKeyVersion); err != nil { return err } return validateRSAPubKeyParams( pubKey.GetParams().GetHashType(), bytesToBigInt(pubKey.GetN()).BitLen(), pubKey.GetE()) } func (km *rsaSSAPKCS1VerifierKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { return nil, errRSASSAPKCS1NotImplemented } func (km *rsaSSAPKCS1VerifierKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { return nil, errRSASSAPKCS1NotImplemented } func (km *rsaSSAPKCS1VerifierKeyManager) DoesSupport(typeURL string) bool { return typeURL == rsaSSAPKCS1VerifierTypeURL } func (km *rsaSSAPKCS1VerifierKeyManager) TypeURL() string { return rsaSSAPKCS1VerifierTypeURL } ================================================ FILE: go/signature/rsassapkcs1_verifier_key_manager_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature_test import ( "crypto/rand" "crypto/rsa" "encoding/hex" "math/big" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" internal "github.com/google/tink/go/internal/signature" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/tink" commonpb "github.com/google/tink/go/proto/common_go_proto" rsassapkcs1pb "github.com/google/tink/go/proto/rsa_ssa_pkcs1_go_proto" ) const ( rsaPKCS1PublicTypeURL = "type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PublicKey" ) func makeValidRSAPKCS1Key() (*rsassapkcs1pb.RsaSsaPkcs1PrivateKey, error) { rsaKey, err := rsa.GenerateKey(rand.Reader, 3072) if err != nil { return nil, err } return &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: 0, PublicKey: &rsassapkcs1pb.RsaSsaPkcs1PublicKey{ N: rsaKey.PublicKey.N.Bytes(), E: big.NewInt(int64(rsaKey.PublicKey.E)).Bytes(), Version: 0, Params: &rsassapkcs1pb.RsaSsaPkcs1Params{ HashType: commonpb.HashType_SHA256, }, }, D: rsaKey.D.Bytes(), P: rsaKey.Primes[0].Bytes(), Q: rsaKey.Primes[1].Bytes(), Dp: rsaKey.Precomputed.Dp.Bytes(), Dq: rsaKey.Precomputed.Dq.Bytes(), Crt: rsaKey.Precomputed.Qinv.Bytes(), }, nil } func TestRSASSAPKCS1VerifierDoesSupport(t *testing.T) { vkm, err := registry.GetKeyManager(rsaPKCS1PublicTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PublicTypeURL, err) } if !vkm.DoesSupport(rsaPKCS1PublicTypeURL) { t.Errorf("DoesSupport(%q) = false, want true", rsaPKCS1PublicTypeURL) } if vkm.DoesSupport("invalid.type.url") { t.Error("DoesSupport('invalid.type.url') = true, want false") } } func TestRSASSAPKCS1VerifierTypeURL(t *testing.T) { vkm, err := registry.GetKeyManager(rsaPKCS1PublicTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PublicTypeURL, err) } if vkm.TypeURL() != rsaPKCS1PublicTypeURL { t.Errorf("TypeURL() = %q, want %q", vkm.TypeURL(), rsaPKCS1PublicTypeURL) } } func TestRSASSAPKCS1VerifierNotImplemented(t *testing.T) { vkm, err := registry.GetKeyManager(rsaPKCS1PublicTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PublicTypeURL, err) } serializedFormat, err := proto.Marshal(&rsassapkcs1pb.RsaSsaPkcs1KeyFormat{ Params: &rsassapkcs1pb.RsaSsaPkcs1Params{ HashType: commonpb.HashType_SHA256, }, ModulusSizeInBits: 3072, PublicExponent: []byte{0x01, 0x00, 0x01}, }) if err != nil { t.Fatalf("proto.Marshall() err = %v, want nil", err) } if _, err := vkm.NewKeyData(serializedFormat); err == nil { t.Error("NewKeyData() err = nil, want error") } if _, err := vkm.NewKey(serializedFormat); err == nil { t.Error("NewKeyData() err = nil, want error") } } func TestRSASSAPKCS1VerifierPrimitive(t *testing.T) { vkm, err := registry.GetKeyManager(rsaPKCS1PublicTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PublicTypeURL, err) } privKey, err := makeValidRSAPKCS1Key() if err != nil { t.Fatalf("makeValidRSAPKCS1Key() err = %v, want nil", err) } serializedPubKey, err := proto.Marshal(privKey.GetPublicKey()) if err != nil { t.Fatalf("proto.Marshall() err = %v, want nil", err) } p, err := vkm.Primitive(serializedPubKey) if err != nil { t.Fatalf("Primitive() err = %v, want nil", err) } if _, ok := p.(*internal.RSA_SSA_PKCS1_Verifier); !ok { t.Fatalf("primitive isn't a RSA_SSA_PKCS1_Verifier") } } func TestRSASSAPKCS1VerifierPrimitiveWithInvalidInput(t *testing.T) { type testCase struct { name string pubKey *rsassapkcs1pb.RsaSsaPkcs1PublicKey } privKey, err := makeValidRSAPKCS1Key() if err != nil { t.Fatalf("makeValidRSAPKCS1Key() err = %v, want nil", err) } vkm, err := registry.GetKeyManager(rsaPKCS1PublicTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PublicTypeURL, err) } for _, tc := range []testCase{ { name: "empty key", pubKey: &rsassapkcs1pb.RsaSsaPkcs1PublicKey{}, }, { name: "nil key", pubKey: nil, }, { name: "invalid version", pubKey: &rsassapkcs1pb.RsaSsaPkcs1PublicKey{ Version: privKey.GetPublicKey().GetVersion() + 1, N: privKey.GetPublicKey().GetN(), E: privKey.GetPublicKey().GetE(), Params: privKey.GetPublicKey().GetParams(), }, }, { name: "params field is unset", pubKey: &rsassapkcs1pb.RsaSsaPkcs1PublicKey{ Version: privKey.GetPublicKey().GetVersion(), N: privKey.GetPublicKey().GetN(), E: privKey.GetPublicKey().GetE(), Params: nil, }, }, { name: "exponent larger than 64 bits", pubKey: &rsassapkcs1pb.RsaSsaPkcs1PublicKey{ Version: privKey.GetPublicKey().GetVersion(), N: privKey.GetPublicKey().GetN(), E: random.GetRandomBytes(65), Params: privKey.GetPublicKey().GetParams(), }, }, { name: "invalid modulus", pubKey: &rsassapkcs1pb.RsaSsaPkcs1PublicKey{ Version: privKey.GetPublicKey().GetVersion(), N: []byte{}, E: privKey.GetPublicKey().GetE(), Params: privKey.GetPublicKey().GetParams(), }, }, { name: "invalid exponent", pubKey: &rsassapkcs1pb.RsaSsaPkcs1PublicKey{ Version: privKey.GetPublicKey().GetVersion(), N: privKey.GetPublicKey().GetN(), E: []byte{0x03}, Params: privKey.GetPublicKey().GetParams(), }, }, { name: "invalid hash function", pubKey: &rsassapkcs1pb.RsaSsaPkcs1PublicKey{ Version: privKey.GetPublicKey().GetVersion(), N: privKey.GetPublicKey().GetN(), E: privKey.GetPublicKey().GetE(), Params: &rsassapkcs1pb.RsaSsaPkcs1Params{ HashType: commonpb.HashType_SHA1, }, }, }, } { t.Run(tc.name, func(t *testing.T) { serializedKey, err := proto.Marshal(tc.pubKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := vkm.Primitive(serializedKey); err == nil { t.Fatalf("Primitive() err = nil, want error") } }) } } // The following keys are from: // https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Digital-Signatures // Publication FIPS 186-2 // Signature Verification PKCS1 v1.5 // Only keys with public exponent 65537 (aka: F4, 0x010001) where chosen since golang rsa/crypto // doesn't support other exponent values. // Precomputed values (dp, dq, crt) where calculated from the private key (p, q, d) using rsa/crypto // to avoid recomputing on each test. var ( nist2048PKCS1Key = &nistRSATestKey{ n: "a911245a2cfb33d8ee375df9439f74e669c03a8d9acad25bd27acf3cd8bea7eb9dbe470155c7c72782c94861f7b573cd325639fb070e9ba6e621991aefa45106182e4d264be7068035595d7549052989b3e7fd04cabc94012c1278a0ef8672b1a51dd1a9e276816ba497dea24b4febe3dd8e977707bcd230ca6fb6f8a8bff9e6ba24fbadcd93f00126b19b396a38e6ef86d18fef945b9154c1963fb488c7025953511f86d05638bfe056493730bc6778446e59cd3c5c3acf07a0a3a64943793652f10e3292aa7a6d25a03181cc6f6ba0658d909e59ce2a02bacc9766fd8c4fbd4ed9c23a866844b8a794d49e505f9f944870a71aadbe5338039825c2dff81af3", e: "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001", p: "bf96de108963b5113399b664765efe046e2dafdb70d6e5e29dc6ec89b789b059348d74d89129c7ade9ddb404c6dc3a3437c7fc9f23bc38dadc8ffd0ff757999f5c2d510b993056147ccdf421e03d0be2c74ec333a9677c430cc604f5550d0d86defdde71488e3db889c699a5cacb44dcdae2f3cca38695e783e6f6250827efb1", q: "e1e7e33618d1b64d6862c132e4b1cd5fabad20ce62bd97bce2a3f5ad2da67bb0a7f0b9e48335a33b7b95e77ec4c47e91416881f9f7c23f9bc1918cc644335c74260e90cd7b2e0fed802f19e78c5ed80a431b38630d82f982c74a0381b8ecf943c60810fae90574e216357b2535002316d9529cb56420f3cc82dea37cb624e1e3", d: "290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061", dp: "bce35c3a8789d3098b8b1fa4ba837b03193157f10cb6025dc35a4cf896085ce2060af4c9538d127de7559a571f4c1ee23ea09ff2b203af36304091a9fd1cd3aba6f052b811a6f3272dc8cbc9de4fb1793b30ef08ef1ac50b41fbb505bf7da7f971be6f61d6bbce243349a7502ab8ef42a357203080847f248b09d961b741d071", dq: "629669813d59a03eadf4932e1bc240c7a4cb7c8ab56ada62b3622ca07450b8a042da7ab5f05123389d59b15a9092d44d9e06f6da5936ebbd94bf6979496044d3e79be9b3d33329fe5337bb0d63242d126570e6adcbc2c21341d7da29edc375910f468bea84713e2e40d4fc3623a838a80b15d39011ef939647f2d3d464453a53", crt: "1261dce1e3d5d006948baf609ab5d114780c85c42b7065ddf0ea41d0d9e1bce2b154086551e425f36f46fb0da62ba7e054b95e5207ee08a6e1aa68cc611abe3c57e20a275cef95b4234b2539e1ed48e5a2363c4f2cb84178dbf6d7bf968a722ece1687376703099ccc182a30d5761b5aa8aedd33941997c63f678f4aba1c0d82", } nist3072PKCS1Key = &nistRSATestKey{ n: "f33d3234f13272c3b2b6821ce4805663ff2e8b0d2a47de363d97fc9cc879cc6b40f9e53aea695dc538a0d2b558498829aac327eacbcd889e172b34f90745c5d528b7e82605f1a58fd228ec7fd4b6f476f393864f48dc47097c8a780a2ecc02f748138dbd7df99c52d822a2e5154c6047fb0eeb4f49da38edcae3c32d3fde435f291f96cad1e09e1030ad7efb4944b69e074d0d7964becb3cb86238d8d293bef3030d141d14868bc21fa133e9de1115f749991cf86ef506e663ac162b2c8567ff131a6b467a6f564d6c588860becbd88970354198ecdd4f1f4baee8f8bdaf7255835385f5673625f113550b123628a0be3994d91c3a19a82e5d73448dabf684ee6794fba7a2b1afbee0287e5a11180c29ce0896795d52ac7f408fe28e8e9116fe0b61a1083f95c5227d62d5537b5040b79e21b3a8e83c225bf3efebb2f808541e97d28a2468359fc60f588e74faad611262064628a25d8d61f9d03d8b21cca515595aaf2343a759b74a6a8afeffca139a389aa281995cd18e16a9cf7b7ff0dddb", e: "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001", p: "f3fcc6aae575312778d9e896acfd7c1aa4c5524f20453e8bab255363164afa7124b2425587a077fa0bfaf61b12ef3f0540dc4c9e777122a60610a53d1d75b0a5859c654a8ddfc2ff4860758bf5a6f264bf8bc2baa7551eb7be23bc06978be992fc81d890e07a3abf95d20eee3f6bbbc089985cac96395b473b2741c66bd2ccbef228432f66b906c15b19694dd786c29f06cbc17b2e6400dde4e3db85819382b3d05a4c3009f092d40d05ed5b2e0428a214e15a7aca09b47120b9ea6cb4084fcd", q: "ff36fcdc519fe10c69aa0dde2cf3bc72cf2ce9a54ac063d809b523f4e5d7ddaa5413d500dc21f409ce661bf33018b748fba3966d874bf96f4313eafea9decfba71d540ae0508161a3658c4762d94ebb3a4e228c45661315db30c20fbd9e20e24c044e4f0b49e6ec80949b16e0ab07f3d32b248b39f48332cc3686df05d29c170a7276acdd129259aaf018ae3afb49b6e0ddb9e404a492863daee7be71dfb11279047794e45f399a9665796d32d5e65956a13a6fbe992b36bf4c842f5f519ac47", d: "078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd", dp: "7c2a7fd028c5e325fb52aa1344261c2a5300384b1c5920e3634db38a11a6469d9dd739fadcf2c51bf34cdc421af8b651ae186ec5967374f698cf8fc7f25e1a6fa1f75d74fb8e8c65ee2768aab971249a3100a730e64763428ef9108f2a4081b5d3db20a35a19da1bf5dad8ce5668353c5ec9b32001b35ec8794a1927296835da56d2369ec0e01897fe0c88929cc46ff70e365358a4db2fb5bcee58a130b82923e93c8ad947b5ae834bbd6075ae8d5f405ceff263dabde59e4cd15083d17b0961", dq: "6a6ac44f1dddfb9a10692f35282b4db5d5bb55856dc10120f1134df5ececf0e9f7faf9034dc6fe9a242d21946ac6b38e4417373f5e7e0879235027d99e7d60c2ce7a6c68e38236ad21622c3156da54d9e873c129f516bbdde52db6872d97fbebc91c3116494a12c9684e0924e86225fc1faa85741883a38b13c3f4ab983d3402c4404461a3c8737ca7628e46585a87c1011845496b704bde2f48e7f33be6178616bc26d1c38b4ad47eef20ddd77a18039062b76b2d3ed57fbb66d1bcfb41843b", crt: "9779d59e838e714e0f04fc936d40863b2bf492f446eb90cfe58b27205c2745e59dd7b5becd7de1f01f1d5a5b1d40e4d2281d668d545d4efc0bedaf5e7cdb4fed310661403f5f31e0e8ea23adab382ea09e3610c7548d0ed835bc693206fbee91a66f1ab9c2c80bdda3c26e1bcfd78bbf0f5fc13d646922d395848f27f5316380b196d4ee422e77309c06b9439216d3fff1c762ef662bc3b683e05b5c29af42fd765c7bc1b1356f1618d02ac9f36ca1637bc6651f8478743bd4f83ad37c5fc915", } nist4096PKCS1Key = &nistRSATestKey{ n: "b10935650754c1a27e54f9ee525c77045d1a056baedc8c1ba05a3d66322c8e2e41689ca02b8e6ec55d3331cd714e161b35c774311540c6410cc3b130e65cec325377ccf18a5d77054afaa737e65b68662327627f5d1092df98c08b60a3ba67599b1406986f441528d2f1f5d6fe5ec6b8aa797dbdb3162876b08298237af81c7004863576af572ddd66c487cf32a82d0f9fe260f8f2681613208aec55723622f50d3cb3bd33b1226d5b5b9ea2c97a2c59054e31536849ec2f0f2597c077e621ddea0a22ddfb1df925c9f1941cd431afce0398d28e736cfeab3dd7f062a65a2a4c1ddca1f32afa03b4ddfd8b7ca40cc0ce2ed42229d753f03cc6d8bcdca76ab7c2703c5ddad08aa9bf9a27740a8b23168c6b55917bd3d5c1c057c34d1efb1411da51ab745519bd92b9432fea8fadcb9a70e5dc3adcd3081d3333507b7b998886e988296628dd7265e64eab557712556cc492377f15a078dcb620a6e7f051a1fb8754efdca3de253dd0aad4205b032659e4a4fb307f074fbde340702b5911acb34737d7834600cf2ac77f62f83ccc9ba78ff911021b9f8ad1bf421430ae0d64916944b504542c0f6263c48e5e233ef1869df1efc2ccf6f4a95e4db2de7b4cb1a992bef6573511bab4bf2cd58e72a0c235f56dfc182df4dfffb69433a5677415f35d84f5125f5200eb57868cce6b74c5833417990e318372c9239a36dca1a0b28809", e: "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001", p: "bd4e8bb7fd7ef1e39d71de06b0001bdadcc81b0edf2226e0d056b7eea70b2249000279cc1c04b1ac2919014fc3fb8b62baca3e261601fb0a58a9f67f03cd60085b2d43906d36ad014f321012a9bde9617478a0c10201afd53f2207de3648afd1d737afadf7fd2c0b9824d4f66b2c7dfe93390888ac088c680c27b1b2486659ccfa8986c8c23f78f18b5815a410328e629e7440221bffd8ec4722bba3420da5234f898f8cd7e6d7dcb1349bc4a0b665b41d930e3957cfdc88797aee5b2b27dafb5ba0949e3dd892f490212dfd249f4b1d99fd3b72695ee0652997127f0b9b417fa8365ba9fd103b978309d9baa9d401902cc107cb8d2af7ce04660900e3707ab3", q: "ef67f69838735c055145d21fccb42298642177fe3fadc39070a95e4fc04ff058aeaf9070b4eb2de1cca72d8533bc55206d2ce9f2895b148da67c89e5b6496ba682f76bcaef69306a7fa4fbd41a838bdf0fab3e7b56c27a8c18dc4bf970364dff7427cdcc6f532b49712282370a718b7d5287bfc02c4abc35ccb2eab3777f5e0d8a27ff9ebe13e725aa0a0cd48aee1fa33ea6b4ea965ba42fcce7af3c528a6675cedf4969640f2ca73345dfd322620df9dcf16520195df8232061e2bc89c12de24838f255e7b1c17713ba435d5a351e263350198b3fb881b8ce0acb5aa58b7afaff184489d167c9af21e40e2ba9fa69b44a3854329385c97df0de24dc283a4053", d: "25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919", dp: "0ae4891f962386d19d0e9f42ed3fa45aac978b0f0901d310de8c0edb599b4766c1ec628bbf14fa1038f12a652796c2c7748e0c936e72c0ba30addef42208e03cbada58e7e790dcd5957400fec1eb9e912ffd7cea7e2e10ab098df0bbf58dab283ce50463d3402b17a3b282da87023161c3a0e57fcfbe522dee7d1e396ef70cb5c1b8c61ba929b3d0da3ec04807729144d56f44fd7175004b60307c71816c7d9311918dc401ec53816c64e58da3ddbaee69413bf14abf3826562f1fa5f94ebac7f9d6bc967a628ada2daceb1384d6f1a08b6ac9cfe486440d2e1e763eff30f8ccdaa5fe1242f07b2d55a9ec70543351bfb5038a6a48fe2ef218c8b23dedd85c07", dq: "9bf8c68e8b9094ae1e31f7e0a1d3e60a148a3d8bd65ed5df5f96e88bdac5f9d73d0fc271bb5cd10a9ff376d3a64e17c3c57d1279e20505d1f75a81d8b7b703bc7aecc93c7057bea453bee01662a3bb57baf49d036c15ce13420b1c30496c07cadb192799fe19584543c0f0c6fd35d663f285e0664a34f283b6760634a030c9ccd66a92be1026155cd37832bdb239cb40e68b63a8c606b4643401e987ca5ac2c013e42306d79a8f43eb42a5bcff5494b869ba97609f463a68602b85b5c1a5aac816b78b226e8dbf765dd2e71a85afbf91b1b288c1d0e4db16d49df1b87fcbec766405a2798b852bbfbebbbe83b1fd242ac2840a4edd0fb7a3266f03e2af0eac63", crt: "87f4c4ddef9c241eae1215e92f30e2252519ac18c6cdf8906bca21627fa7288bab9a0efd1ea6fb8562479bec1de7ce7cf2f86cc862df35a3766559a87a4dc2a12d20f30815c68bfdee87beabfb5cce965f5fddb0ad59153df8bce3acfa279aad0202f94f2a9b48049e8a3e5a1af82d63269b5d8ea864b8b1239d2b5a74496a116b23070932f7a7f4b13140e17826bfed5004f7247dfe1a8a0943b9f6fc0a856fb96159c61a2584380aca3fab48b892639b80f089b35b65182a973878b1b16cde5c2c0b0bff46884b8793aa8564d06eab99f6ef407199b7477f8b811ed1434368895cc5ffe2354a04023e9ba0598da9838db89adcb9986c37e805ff0b083da119", } ) type nistRSAPKCS1TestVector struct { name string sig string msg string hashType commonpb.HashType key *nistRSATestKey } func (t *nistRSAPKCS1TestVector) ToProtoKey() (*rsassapkcs1pb.RsaSsaPkcs1PrivateKey, error) { e, err := hex.DecodeString(t.key.e) if err != nil { return nil, err } n, err := hex.DecodeString(t.key.n) if err != nil { return nil, err } d, err := hex.DecodeString(t.key.d) if err != nil { return nil, err } p, err := hex.DecodeString(t.key.p) if err != nil { return nil, err } q, err := hex.DecodeString(t.key.q) if err != nil { return nil, err } dp, err := hex.DecodeString(t.key.dp) if err != nil { return nil, err } dq, err := hex.DecodeString(t.key.dq) if err != nil { return nil, err } crt, err := hex.DecodeString(t.key.crt) if err != nil { return nil, err } return &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: 0, PublicKey: &rsassapkcs1pb.RsaSsaPkcs1PublicKey{ Version: 0, E: e, N: n, Params: &rsassapkcs1pb.RsaSsaPkcs1Params{ HashType: t.hashType, }, }, D: d, P: p, Q: q, Dq: dq, Dp: dp, Crt: crt, }, nil } // The following test vectors are from: // https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Digital-Signatures // Publication FIPS 186-2 // Signature Verification PKCS1 v1.5 var nistPKCS1TestVectors = []nistRSAPKCS1TestVector{ { name: "RSA_SSA_PKCS1_2048_SHA256", sig: "794d0a45bc9fc6febb586e319dfa6924c888594802b9deb9668963fdb309bf02817960a7457106fc474f91601436e8954cbb6815350b2c51b53c968d2c48cc1799550d5d03b41f6e5a8c3c264d2e2fe0b5b8ff53fdcb9dd111c985cb488d7086e6548b4077ec00721c9cb500fe07a031c2030e8ad1dd0112c34ffd9091d77a187aac8661b298eee39eb615f9715c4c48a6762ede55a466ec7f3cdb6a937cfc80188a85d8f8d3a2a80b199ce5e6375af8f02f06d706a34d9cf38318903965db54aaa7d3fa7a7ee58034cd58c8435739c8906366e2ddba293f2fb2c15f07fa4951014471e7f677d3bdacffc4c68a906e08d68b39f9010746cbacd22980cee73e8d", msg: "6918d6328ca0a8b64bbe81d91cdea519911b59fc2dbd53af76006fec4b18a320787135ce883b2b2edb26041bf86aa52c230b9620335b6e7f9ec08c7ed6b70823d819e9ab019e9929249f966fdb2069311a0ddc680ac468f514d4ed873b04a6beb0985b91a0cfd8ed51b09f9e6d06da739eaa939d5a00275901c4f8cf25076339", key: nist2048PKCS1Key, hashType: commonpb.HashType_SHA256, }, { name: "RSA_SSA_PKCS1_2048_SHA384", sig: "80d7286710e5f165eeb63d2936e8e313ac5999bd297d35590c2b6ffaa4b7b7ed30003f0b83c1d1996c8593a37bc5d7b501a3d126ac6124779a23718497002d9dd2ce891b83d185e333af05460c6deb65a509640f775a0d3c70e55112c2e4af19f4ccec7af9ebb34226164f1b47d50b8ecc1dc3e0fc09aa15abfce5aa3998b5c2b1fde261c35eb43220f0d64529f723801d7faff841faba8709f6ea7751f30428dfc58045c84995107ee013ca4a84f65b99adde1abdefb5428f834ac8da04dafb9beaf1813f73a4bff2ec94120e3a702aed1184c387ebda2abf1959970724299b9a05f4ad313d91beb5344fe1fe13b3fc3386c279f031c77d74bdc9bc97e22455", msg: "752fbf49ae63c7853b3ef6f52ed324e53867925bd5d4c49dc42b93f3ba9d7eae579c4169593da98f10e1a61e1214a2aa2fb511a4a75849dc9be89445c29184f85ddc877c6d1cbb45230a047a98ac5bfcbe7b69a397c454cba44fd90fa13f9b546f39ba0a52c8a8ae5c0038932962f8e3cd00c1e00be28c70c8a787d9be6f69c9", key: nist2048PKCS1Key, hashType: commonpb.HashType_SHA384, }, { name: "RSA_SSA_PKCS1_2048_SHA512", sig: "25b408187418c512e7d36eac17edc64999e94011b4d5088ab926d29e433a69e24ebac43146a1371635fc78c3d215a66ea46d0a734b1607fdb9c3848a1404545ff60582abd579d978902ed399eb5dcdfacde0ca02145480246e1a22af5ddca7080aec216895d3528a8756e0c1a2059d392f87576fe896e411ddf02bd6be81ae2a654e0a15542a6b533b776703e2057b01ad02f5430d97c691f80219e46319de527541f0bfcf0b4e1b510059fa20779eb44b1ef293b7a8318447ed25793037ddfd1877cd98514c81575613f36d946670f632779eaf629a593fe99110e781cb38101a3cbd54d7871983dbf868a00cfcb17bd330309d43b8df8d4f05eb4c43649cdf", msg: "5cb7a0a74095a6f284a13d4392aac30a73a9211df0520bf2f7e9831240579fca2f7d8d24fdc8d4161306dcf8b678b13be92804598f7c7308d10c0ab3bfb1092a3adee799113498b76a500c3f64e8f8a4fa16d8012bf3354e576823daed410ff54383b7edc5007a3d5228d200e3221fac6e1ca6fc0adfd92e53a6d96f10303994", key: nist2048PKCS1Key, hashType: commonpb.HashType_SHA512, }, { name: "RSA_SSA_PKCS1_3072_SHA256", sig: "2e4d98c10e126e544d2b74bbcf0a4f03f081d4725a6661c0683d3612b01ddb2dd6f0391ef3679f39dc0785b37ac275f0d6841ed3a44ff7f6a407a085129a164faf63ff2aaed18ec6a5f7d27b48d017a50b24c8c4859ad2bb680ace5f3af57f2eac2d7337c0dd7403ffb2e8bac69dfdc98e62a07354b2fc93d03e499ee2d126647edaba094196b693e98cb98ad2817ba3f7f522c8f786b6ef82632ef5a00d5d4f42db6d26709909ca751aa8174037c924628852ce78e2829493d6c741d3558adcf713734697754e55e7b3bea0d8717da8aba2b2874527a0b3a8d2e1433344dd6bbaee1ebc7fa352539d94c6b45f915c6979b8e18be8934d28d770806c6ff893660dffd0e948a8cce11ac870507f88c1f86caa875ad721326dcb4f0d5ecc2d2538c4fabcc6c756ce4a59bcdafc44568787cf2bd9650486da8c85fd0b87794547e179e498cb6a5b26f71f9987d703f2d53418411c1f9a3a2e6705637b7bbda9660641c0eb037eb432b2d7515d1ffa99175cfdb8a2a4eed013b947faa4bf1c3cbd59", msg: "dbbd09ff7b1c707c2bd52014adbb773ceb146aa72637c8724f5ac39fb5a5acc4e18bfe04be599e3ffe0f6186b870cfd2565527f5ae46a3d06f4bfcc7bf00317222e885959e03c6531da3d59e127b63f25ff9f94377d63b34bfeb6d893b4636df667da49a61427120503885450205bb05d0a9e879c70e1a0409df1dce709e4473", key: nist3072PKCS1Key, hashType: commonpb.HashType_SHA256, }, { name: "RSA_SSA_PKCS1_3072_SHA384", sig: "879c4df9b66227ce30e6403b620a488c72329b400ec67667a600bcfe3d0ea893f3051c8076eee81e0fece30c4153552ae2b2c774888657adb5300bedaf4940d6d6ce9310a476093b3590fca889e8ead464809be4da3370c21784e4740453df999bb9f7c290ea16e4b0e4ca666ddf23c757474fa9b0dbef769b1876e1eb553ee3a1c14c201c101164d5d1e5f628a7ebaf65c0f0f27f239ff67a4fe659d347cf50921b5859d79d86f8bfd2a25eabfcf76eb606b4151516c482c74ca3e54ede03e99086e61c0708e8ad9c94c1fe3640bf811f4e2c0e62d17d593f2e86adfd0798f04616adf9367b0f77f40de77135301debb490bfc76ba710878ddf91651a5fa025c348b6066a49853d6ece7bc79cdcd8ae709a77b96701c1ba9c4a91663e3790bad5c5c48017fcfd005a1b03d47d07dd3c511aefeb4c766dd19e377d2d82329a222b18ee0899e166cfb37c0b1b3226123f80a33c096fa4ba784719c4d9e52e60ccddb6da8575e705a36dbee7d97093f830283c71abbbb85c06daa913f96dede4ce", msg: "88af470625e6b5be3358cf6a8698a5655ef321838f044746df83bc55b05e8529df0b120aeb1c7b3a5a1409705879f887a22a7b78a2f30186db5fb7b888cd4e8c80c6feea5d8ecb57ddf9076b8980188594947bbd0533091a19b87906e2f727fe3589138ec3652d7d86b0d0455fd78cc5fdda283a00ebe76c5e370b25060498e7", key: nist3072PKCS1Key, hashType: commonpb.HashType_SHA384, }, { name: "RSA_SSA_PKCS1_3072_SHA512", sig: "aa3ee99d39ad0332ca48deeb68b5966962018906f1e2e97d0d711df66e600fc875faf8da141212ea9bc49b2934f19bcb26f819b3633381b23f74f0c1d486c8fed6f6c17cacaac222e55c8c534ca2cb3921ca6f0cc19d045fa5456b4ffbc496d0d3079f19d93bba5600048b783a905abc3f30fe4b33b057a203b5f9d01254bdeb02896cc11b713fdca55e3ecc67e243fddf19130e2f3c79bd984558feef0fe877e071b0a13323e700de83244e2bcc09a602eaa06bb39d832d58e30450dcd96b30052778c07d4b209d5929bb6cc80800c95963a24bea449189301b50b5f26a899739dd0a4af6eba05e7e625c96cabda3beb2e4b0d11ccf72252b2d524d76a104a6dcef635517d78f248c78837422ac900557e1671958116500c673e2fc9a08e40d4eff8d44146f43fcc5f4086d276ba026e9953425a11b7be0036ddba0648f12424c3359cd8db8a0490b1bab3b35d3550840b4937ad1986aadedab74fcab27fec7561ae2bbcbb16d28d173efdf049fa8a1daae66db51f4c03fc91d1cda85d2cddc", msg: "112b7aa9fec5c7ac703a49c298c4e29586083296f79b099e6ec422d586840ed486d36e06362d6554f14d4d01fc39a9d2167e5b7350bd18161f66185db0c4127a7b3a67951bcc9e6d5de010439746e4f43b773e65ab1ab4234fcd024be621fea819e6ce1c56aa5841db7cfa4f11f67b411c7a4233b0bbc60f267f4668cfa4baa6", key: nist3072PKCS1Key, hashType: commonpb.HashType_SHA512, }, { name: "RSA_SSA_PKCS1_4096_SHA256", sig: "2df1e58e7491739bb027c6315a70eebbcf37b8e5958df07578a589a47cbaf1edb23ff2e676f2f273a1cc0babd22e0bff874529cfd6479ae5c7250f06579eb212dd3f4058c476abae8e94c89afe05746c3aea93155cf03195ce5f4eced399d2b61aab7f4060b69844cbff6303d264c4755be78af001d125af461fececad8f46a9c4b07420ca63c4212f80a751fcca6a4737684543fcf07b39089baa9995394766f69239479e7c9778c644e022dd4ec7e07a769aa75db2571e58a5e0ba1e4377e9677092bc9dee9d9dbb448441da8f4385b4d4f8ccff4b3dc3c3c3ac8ba11a6ce8caafa930108ba3603c5b0ef65a02a7afebebf605aa88511513a69b3086fdfc25c588c4d61a06219d0d5643410d3ae4d78b2f695efe4e0b82161c53bb9d4b8a83692bb16de8da18b4a6c2abbd0f6b0e24229077fd6c3bca918bc9d9f4518598238df0c925f8587fff0852c44e8107ccbc1ce6a9be3b0941c3b28bb03c87eeb959d719dba9a64a338c7b9931cdf6bb169686de1f8de0e1fa74d03419d164f2c8bd2030562705d1470415e48144181dfd31cdd4219b5d22f9a4c659923cf5c4edbde18e8277dae11264c11423c5481402e80af223f0c4faea0c2c7aefacbf513962c2f16af353ffae1414b408f726eeb946d7c4c8577e72d8f1d49ae2301cf70abee46d286a6fac1b888c334538abb3b830fae595bbb19ea9dce46a343da031117c", msg: "8f937d50d24a1a6ed858d2e3de56e5c23b917d5a936c87b84effc06d48041391caf42207ba6d23030ed7edca864752b99ba3b089b308c3d19668bdcc2578995d4ac9ac502b347de3a37cd685f22f1bddb3cddb0e0f2ca53a311b1d45f9464edbf55a42b48d69d0167d8fb69c89d6e8376b57277211a2d4fa0560075d2d37dc12", key: nist4096PKCS1Key, hashType: commonpb.HashType_SHA256, }, { name: "RSA_SSA_PKCS1_4096_SHA384", sig: "0471456bd38ff2a5adeb19b73c35de60f07d7907479f9e6d5735dca75ebd3ef499194917287ae0c3334a5b97f2be41598917a5d880b3d021c61a7acfe9083441661f56fb984ec6717986c558a10d108fac9e00bbd5adbd817a7684edd424e612c8a7f60ff1c8056067f0eee1c6ce3a4ceb6c27c735f0fdc93cfb521b529e1002659e6fe9cddcc79c218a84ee59b7355a43b47b5c4ece8535e0874cca866e3981dec3d1996d4dd05afab27bb5dae9d6ac9dc39e957329eb273254c4e7784a29db26696bd0ff872eede9fff869c35487643755d9cd5bae01c7858b123e4f9688b1d2607f349d52c828dd6d76ff41514565564d39038814841a0441c232411c8afcb15073739f5d5c537138b9bbda60bfd2cfea2847678ffbab73eb02fcaba9e4cabd7768bc0c3a6009dd78f02a8d791f5e1e30d7358b5a642cf0a1a838b954b76a15386109926595b2862de80ddfea98e6218efb925cf5d6434b93045cad5bfd1af36e63a98c14b8f5c6974f04e5e52243bf7cffdc8cb9c0a35fc3250943d07037b319cafef02a2fd21c39aaa3da9f171f1e9c9613ff97d3a6770e7639ecbfa7e47804d8833e8212064d091e02801869bcb2bbbfc2be5d21b2da790ddd7973b6f5b9d6c763cfa503c6243851461490dfab31cccc6621fd91fc1ae28b4b1d393cb1e41d397852acd98fa35b93b6b4dd92e2d5fac7665d8c0b3f7d03ad3048b6854b", msg: "450171e919ecc10bbf1d05f41eee02eab8eede088a31263433eb1652593d14b7494f7de1dd9fa465a39918283b6726d2010a9f80edaadcbab72afea43e007a782a44d633d006ad8f57e5f93219dd92254c61f187e2aa3a83ad4e7a7fc7142c9631070349bac9e371232a307880f94cc9e11b5b8532d94a78607e0f4bbe2232fb", key: nist4096PKCS1Key, hashType: commonpb.HashType_SHA384, }, { name: "RSA_SSA_PKCS1_4096_SHA512", sig: "6836dff1bea541916b9ccce2695e921ff27a737ac54f4a5c3b2facee80a8dd3bbfe86c93a1af8da5c6b3a92c445dfac7e215fa9f3d67c9589dba858a223f326afeb8f5d0f92f28ac4e3671c22b5b4e0b4266f776aca928bb0309929f2c452b62d462675cef09388e5720cf0cb99351d44059790720db82ce014d7e795826833284bd4205c64e1330e30e09ff6220f62c013c117ace4f4286cd46e52694c4925aba12a5278e47de910dcdd820396febe5179bbc6ccecdac1883bd408530bde92e93c49db2c6fbb42e9705f29703763b21a8172489d2831889bb060505040940e60f7c5cb9f58327c3d3f7cf7e18ad60e877edb65222a699d4acdcb358fbc87e1e461468cfdc82a8cd7fb1f82e05378737f4aa741a63ddf6039b23e1aa19d94e7087915899685add8a8da8f64a93707be0b6354c8e9a8aefc7484bb45cd0beca493a4a0aef0b6aaae801866b905683c582bf39f9cc0768d880c6e4b331da86506b298c180cf95fa45e532483c55544371468088b4e378f37976c397e09f89081f0f0b6f4ba3be6929957f55f14a88f6beb456b70e6fbc6227e98c1e8a4a6f734c9080c13ed58bcfb3456cbbc217653835000f54956d839d4073571d8a42fa2294df1a747e88af53a16df1834203009cccd6d61304739872ab92be79a4462125ebc8bba909ca2b4d91b9e520d6c681c2f92070f156e31a6875122993e1d94fc3568", msg: "42c5ea617a25f019329ee172e4932485518dabd01983249189597473b4a6616cc5ba8ee693e0ad1d76e0f0c85ac8c0fb11ecb24cee2cb7358f7593b9fa8b904aec0573eb6d99af92a899d9d0fabe5cb349256eec9797422dd60d7fd5fe73f2cf5ead7fb72fd85e3f6fd284d2edfc5e77a03ec5f73c4c2f420728220fe9e9efc3", key: nist4096PKCS1Key, hashType: commonpb.HashType_SHA512, }, } func TestRSASSAPKCS1VerifierPrimitiveNISTTestVectors(t *testing.T) { vkm, err := registry.GetKeyManager(rsaPKCS1PublicTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PublicTypeURL, err) } for _, tc := range nistPKCS1TestVectors { t.Run(tc.name, func(t *testing.T) { privKey, err := tc.ToProtoKey() if err != nil { t.Fatalf("tc.ToProtoKey() err = %v, want nil", err) } serializedPubKey, err := proto.Marshal(privKey.GetPublicKey()) if err != nil { t.Fatalf("proto.Marshall() err = %v, want nil", err) } p, err := vkm.Primitive(serializedPubKey) if err != nil { t.Fatalf("Primitive() err = %v, want nil", err) } sig, err := hex.DecodeString(tc.sig) if err != nil { t.Fatalf("hex.DecodeString(tc.sig) err = %v, want nil", err) } msg, err := hex.DecodeString(tc.msg) if err != nil { t.Fatalf("hex.DecodeString(tc.msg) err = %v, want nil", err) } if err := p.(tink.Verifier).Verify(sig, msg); err != nil { t.Fatalf("Verify() err = %v, want nil", err) } }) } } ================================================ FILE: go/signature/rsassapss_signer_key_manager.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature import ( "crypto/rand" "crypto/rsa" "fmt" "errors" "math/big" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" internal "github.com/google/tink/go/internal/signature" "github.com/google/tink/go/keyset" rsassapsspb "github.com/google/tink/go/proto/rsa_ssa_pss_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( rsaSSAPSSSignerKeyVersion = 0 rsaSSAPSSSignerTypeURL = "type.googleapis.com/google.crypto.tink.RsaSsaPssPrivateKey" ) var ( errInvalidRSASSAPSSSignKey = errors.New("rsassapss_signer_key_manager: invalid key") ) type rsaSSAPSSSignerKeyManager struct{} var _ registry.PrivateKeyManager = (*rsaSSAPSSSignerKeyManager)(nil) func (km *rsaSSAPSSSignerKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidRSASSAPSSSignKey } key := &rsassapsspb.RsaSsaPssPrivateKey{} if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, err } if err := validateRSAPSSPrivateKey(key); err != nil { return nil, err } privKey := &rsa.PrivateKey{ PublicKey: rsa.PublicKey{ N: bytesToBigInt(key.GetPublicKey().GetN()), E: int(bytesToBigInt(key.GetPublicKey().GetE()).Uint64()), }, D: bytesToBigInt(key.GetD()), Primes: []*big.Int{ bytesToBigInt(key.GetP()), bytesToBigInt(key.GetQ()), }, } if err := privKey.Validate(); err != nil { return nil, err } // Instead of extracting Dp, Dq, and Qinv values from the key proto, // the values must be computed by the Go library. // // See https://pkg.go.dev/crypto/rsa#PrivateKey. privKey.Precompute() params := key.GetPublicKey().GetParams() if err := internal.Validate_RSA_SSA_PSS(hashName(params.GetSigHash()), int(params.GetSaltLength()), privKey); err != nil { return nil, err } return internal.New_RSA_SSA_PSS_Signer(hashName(params.GetSigHash()), int(params.GetSaltLength()), privKey) } func validateRSAPSSPrivateKey(privKey *rsassapsspb.RsaSsaPssPrivateKey) error { if err := keyset.ValidateKeyVersion(privKey.GetVersion(), rsaSSAPSSSignerKeyVersion); err != nil { return err } if err := validateRSAPSSPublicKey(privKey.GetPublicKey()); err != nil { return err } if len(privKey.GetD()) == 0 || len(privKey.GetPublicKey().GetN()) == 0 || len(privKey.GetPublicKey().GetE()) == 0 || len(privKey.GetP()) == 0 || len(privKey.GetQ()) == 0 || len(privKey.GetDp()) == 0 || len(privKey.GetDq()) == 0 || len(privKey.GetCrt()) == 0 { return errInvalidRSASSAPSSSignKey } return nil } func (km *rsaSSAPSSSignerKeyManager) PublicKeyData(serializedPrivKey []byte) (*tinkpb.KeyData, error) { if serializedPrivKey == nil { return nil, errInvalidRSASSAPSSSignKey } privKey := &rsassapsspb.RsaSsaPssPrivateKey{} if err := proto.Unmarshal(serializedPrivKey, privKey); err != nil { return nil, err } if err := validateRSAPSSPrivateKey(privKey); err != nil { return nil, err } serializedPubKey, err := proto.Marshal(privKey.GetPublicKey()) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: rsaSSAPSSVerifierTypeURL, Value: serializedPubKey, KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC, }, nil } func (km *rsaSSAPSSSignerKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, fmt.Errorf("invalid key format") } keyFormat := &rsassapsspb.RsaSsaPssKeyFormat{} if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, err } params := keyFormat.GetParams() if params.GetSigHash() != params.GetMgf1Hash() { return nil, fmt.Errorf("signature hash and mgf1 hash must be the same") } if params.GetSaltLength() < 0 { return nil, fmt.Errorf("salt length can't be negative") } if err := validateRSAPubKeyParams( params.GetSigHash(), int(keyFormat.GetModulusSizeInBits()), keyFormat.GetPublicExponent()); err != nil { return nil, err } privKey, err := rsa.GenerateKey(rand.Reader, int(keyFormat.GetModulusSizeInBits())) if err != nil { return nil, err } return &rsassapsspb.RsaSsaPssPrivateKey{ Version: rsaSSAPSSSignerKeyVersion, PublicKey: &rsassapsspb.RsaSsaPssPublicKey{ Version: rsaSSAPSSSignerKeyVersion, Params: keyFormat.GetParams(), N: privKey.PublicKey.N.Bytes(), E: big.NewInt(int64(privKey.PublicKey.E)).Bytes(), }, D: privKey.D.Bytes(), P: privKey.Primes[0].Bytes(), Q: privKey.Primes[1].Bytes(), Dp: privKey.Precomputed.Dp.Bytes(), Dq: privKey.Precomputed.Dq.Bytes(), // In crypto/rsa `Qinv` is the "Chinese Remainder Theorem // coefficient q^(-1) mod p". This corresponds with `Crt` in // the Tink proto. This is unrelated to `CRTValues`, which // contains values specifically for additional primes, which // are not supported by Tink. Crt: privKey.Precomputed.Qinv.Bytes(), }, nil } func (km *rsaSSAPSSSignerKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { key, err := km.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: rsaSSAPSSSignerTypeURL, Value: serializedKey, KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PRIVATE, }, nil } func (km *rsaSSAPSSSignerKeyManager) DoesSupport(typeURL string) bool { return typeURL == rsaSSAPSSSignerTypeURL } func (km *rsaSSAPSSSignerKeyManager) TypeURL() string { return rsaSSAPSSSignerTypeURL } ================================================ FILE: go/signature/rsassapss_signer_key_manager_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature_test import ( "math/big" "testing" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/testing/protocmp" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/tink" cpb "github.com/google/tink/go/proto/common_go_proto" rsppb "github.com/google/tink/go/proto/rsa_ssa_pss_go_proto" tpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( rsaPSSTestPrivateKeyTypeURL = "type.googleapis.com/google.crypto.tink.RsaSsaPssPrivateKey" rsaPSSTestPrivateKeyVersion = 0 ) func TestRSASSAPSSSignerKeyManagerDoesSupport(t *testing.T) { skm, err := registry.GetKeyManager(rsaPSSTestPrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", err, rsaPSSTestPrivateKeyTypeURL) } if !skm.DoesSupport(rsaPSSTestPrivateKeyTypeURL) { t.Errorf("DoesSupport(%q) err = false, want true", rsaPSSTestPrivateKeyTypeURL) } if skm.DoesSupport("fake.type.url") { t.Errorf("DoesSupport(%q) err = true, want false", "fake.type.url") } } func TestRSASSAPSSSignerKeyManagerTypeURL(t *testing.T) { skm, err := registry.GetKeyManager(rsaPSSTestPrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", err, rsaPSSTestPrivateKeyTypeURL) } if skm.TypeURL() != rsaPSSTestPrivateKeyTypeURL { t.Errorf("TypeURL() = %q, want %q", skm.TypeURL(), rsaPSSTestPrivateKeyTypeURL) } } func TestRSASSAPSSSignerGetPrimitive(t *testing.T) { skm, err := registry.GetKeyManager(rsaPSSTestPrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", err, rsaPSSTestPrivateKeyTypeURL) } privKey, err := makeValidRSAPSSKey() if err != nil { t.Fatalf("makeValidRSAPSSKey() err = %v, want nil", err) } serializedPrivate, err := proto.Marshal(privKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } p, err := skm.Primitive(serializedPrivate) if err != nil { t.Fatalf("Primitive() err = %v, want nil", err) } signer := p.(tink.Signer) vkm, err := registry.GetKeyManager(rsaPSSTestPublicKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", err, rsaPSSTestPublicKeyTypeURL) } serializedPublic, err := proto.Marshal(privKey.GetPublicKey()) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } p, err = vkm.Primitive(serializedPublic) if err != nil { t.Fatalf("Primitive() err = %v, want nil", err) } verifier := p.(tink.Verifier) data := random.GetRandomBytes(80) signature, err := signer.Sign(data) if err != nil { t.Fatalf("Sign() err = %v, want nil", err) } if err := verifier.Verify(signature, data); err != nil { t.Fatalf("Verify() err = %v, want nil", err) } } func mergePrivPub(priv *rsppb.RsaSsaPssPrivateKey, pub *rsppb.RsaSsaPssPublicKey) *rsppb.RsaSsaPssPrivateKey { return &rsppb.RsaSsaPssPrivateKey{ Version: priv.GetVersion(), PublicKey: pub, D: priv.GetD(), P: priv.GetP(), Q: priv.GetQ(), Dp: priv.GetDp(), Dq: priv.GetDq(), Crt: priv.GetCrt(), } } func TestRSASSAPSSSignerGetPrimitiveWithInvalidInput(t *testing.T) { type testCase struct { tag string privKey *rsppb.RsaSsaPssPrivateKey } skm, err := registry.GetKeyManager(rsaPSSTestPrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", err, rsaPSSTestPrivateKeyTypeURL) } validPrivKey, err := makeValidRSAPSSKey() if err != nil { t.Fatalf("makeValidRSAPSSKey() err = %v, want nil", err) } for _, tc := range []testCase{ { tag: "empty private key", privKey: &rsppb.RsaSsaPssPrivateKey{}, }, { tag: "invalid private key version", privKey: &rsppb.RsaSsaPssPrivateKey{ Version: validPrivKey.GetVersion() + 1, PublicKey: validPrivKey.GetPublicKey(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { tag: "invalid private key D", privKey: &rsppb.RsaSsaPssPrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: validPrivKey.GetPublicKey(), D: nil, P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { tag: "invalid private key P", privKey: &rsppb.RsaSsaPssPrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: validPrivKey.GetPublicKey(), D: validPrivKey.GetD(), P: nil, Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { tag: "invalid private key Q", privKey: &rsppb.RsaSsaPssPrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: validPrivKey.GetPublicKey(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: nil, Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { tag: "invalid private key Dp", privKey: &rsppb.RsaSsaPssPrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: validPrivKey.GetPublicKey(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: nil, Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { tag: "invalid private key Dq", privKey: &rsppb.RsaSsaPssPrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: validPrivKey.GetPublicKey(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: nil, Crt: validPrivKey.GetCrt(), }, }, { tag: "invalid private key Crt", privKey: &rsppb.RsaSsaPssPrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: validPrivKey.GetPublicKey(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: nil, }, }, { tag: "empty public key", privKey: mergePrivPub(validPrivKey, &rsppb.RsaSsaPssPublicKey{}), }, { tag: "nil public key params", privKey: mergePrivPub( validPrivKey, &rsppb.RsaSsaPssPublicKey{ Version: validPrivKey.GetPublicKey().GetVersion(), Params: nil, N: validPrivKey.GetPublicKey().GetN(), E: validPrivKey.GetPublicKey().GetE(), }), }, { tag: "invalid public key version", privKey: mergePrivPub( validPrivKey, &rsppb.RsaSsaPssPublicKey{ Version: validPrivKey.GetPublicKey().GetVersion() + 1, Params: validPrivKey.GetPublicKey().GetParams(), N: validPrivKey.GetPublicKey().GetN(), E: validPrivKey.GetPublicKey().GetE(), }), }, { tag: "different sig and mgf1 hash functions", privKey: mergePrivPub( validPrivKey, &rsppb.RsaSsaPssPublicKey{ Version: validPrivKey.GetPublicKey().GetVersion(), Params: &rsppb.RsaSsaPssParams{ SigHash: cpb.HashType_SHA256, Mgf1Hash: cpb.HashType_SHA384, SaltLength: validPrivKey.GetPublicKey().GetParams().GetSaltLength(), }, N: validPrivKey.GetPublicKey().GetN(), E: validPrivKey.GetPublicKey().GetE(), }), }, { tag: "negative salt length", privKey: mergePrivPub( validPrivKey, &rsppb.RsaSsaPssPublicKey{ Version: validPrivKey.GetPublicKey().GetVersion(), Params: &rsppb.RsaSsaPssParams{ SigHash: validPrivKey.GetPublicKey().GetParams().GetSigHash(), Mgf1Hash: validPrivKey.GetPublicKey().GetParams().GetMgf1Hash(), SaltLength: -1, }, N: validPrivKey.GetPublicKey().GetN(), E: validPrivKey.GetPublicKey().GetE(), }), }, { tag: "invalid hash function", privKey: mergePrivPub( validPrivKey, &rsppb.RsaSsaPssPublicKey{ Version: validPrivKey.GetPublicKey().GetVersion(), Params: &rsppb.RsaSsaPssParams{ SigHash: cpb.HashType_UNKNOWN_HASH, Mgf1Hash: cpb.HashType_UNKNOWN_HASH, SaltLength: validPrivKey.GetPublicKey().GetParams().GetSaltLength(), }, N: validPrivKey.GetPublicKey().GetN(), E: validPrivKey.GetPublicKey().GetE(), }), }, { tag: "unsafe hash function", privKey: mergePrivPub( validPrivKey, &rsppb.RsaSsaPssPublicKey{ Version: validPrivKey.GetPublicKey().GetVersion(), Params: &rsppb.RsaSsaPssParams{ SigHash: cpb.HashType_SHA1, Mgf1Hash: cpb.HashType_SHA1, SaltLength: validPrivKey.GetPublicKey().GetParams().GetSaltLength(), }, N: validPrivKey.GetPublicKey().GetN(), E: validPrivKey.GetPublicKey().GetE(), }), }, { tag: "invalid modulus", privKey: mergePrivPub( validPrivKey, &rsppb.RsaSsaPssPublicKey{ Version: validPrivKey.GetPublicKey().GetVersion(), Params: validPrivKey.GetPublicKey().GetParams(), N: []byte{0x00}, E: validPrivKey.GetPublicKey().GetE(), }), }, { tag: "invalid exponent", privKey: mergePrivPub( validPrivKey, &rsppb.RsaSsaPssPublicKey{ Version: validPrivKey.GetPublicKey().GetVersion(), Params: validPrivKey.GetPublicKey().GetParams(), N: validPrivKey.GetPublicKey().GetN(), E: []byte{0x01}, }), }, { tag: "exponent larger than 64 bits", privKey: mergePrivPub( validPrivKey, &rsppb.RsaSsaPssPublicKey{ Version: validPrivKey.GetPublicKey().GetVersion(), Params: validPrivKey.GetPublicKey().GetParams(), N: validPrivKey.GetPublicKey().GetN(), E: random.GetRandomBytes(32), }), }, } { t.Run(tc.tag, func(t *testing.T) { serializedPrivKey, err := proto.Marshal(tc.privKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := skm.Primitive(serializedPrivKey); err == nil { t.Errorf("Primitive() err = nil, want error") } if _, err := skm.(registry.PrivateKeyManager).PublicKeyData(serializedPrivKey); err == nil { t.Errorf("PublicKeyData() err = nil, want error") } }) } } func TestRSASSAPSSSignerGetPrimitiveWithCorruptedPrivateKey(t *testing.T) { skm, err := registry.GetKeyManager(rsaPSSTestPrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", err, rsaPSSTestPrivateKeyTypeURL) } validPrivKey, err := makeValidRSAPSSKey() if err != nil { t.Fatalf("makeValidRSAPSSKey() err = %v, want nil", err) } corruptedPrivKey := validPrivKey corruptedPrivKey.P[5] <<= 1 corruptedPrivKey.P[20] <<= 1 serializedPrivKey, err := proto.Marshal(corruptedPrivKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := skm.Primitive(serializedPrivKey); err == nil { t.Errorf("Primitive() err = nil, want error") } } func TestRSASSAPSSSignerNewKey(t *testing.T) { keyFormat := &rsppb.RsaSsaPssKeyFormat{ Params: &rsppb.RsaSsaPssParams{ SigHash: cpb.HashType_SHA256, Mgf1Hash: cpb.HashType_SHA256, SaltLength: 32, }, ModulusSizeInBits: 3072, PublicExponent: []byte{0x01, 0x00, 0x01}, } serializedKeyFormat, err := proto.Marshal(keyFormat) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } skm, err := registry.GetKeyManager(rsaPSSTestPrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", err, rsaPSSTestPrivateKeyTypeURL) } key, err := skm.NewKey(serializedKeyFormat) if err != nil { t.Fatalf("NewKey() err = %v, want nil", err) } privKey, ok := key.(*rsppb.RsaSsaPssPrivateKey) if !ok { t.Fatalf("key isn't a *rsppb.RsaSsaPssPrivateKey") } if privKey.GetVersion() != rsaPSSTestPrivateKeyVersion { t.Errorf("privKey.GetVersion() = %d, want %d", privKey.GetVersion(), rsaPSSTestPrivateKeyVersion) } if privKey.GetD() == nil { t.Error("GetD() == nil, want []byte{}") } if privKey.GetP() == nil { t.Error("GetP() == nil, want []byte{}") } if privKey.GetQ() == nil { t.Error("GetQ() == nil, want []byte{}") } if privKey.GetDp() == nil { t.Error("GetDp() == nil, want []byte{}") } if privKey.GetDq() == nil { t.Error("GetDq() == nil, want []byte{}") } if privKey.GetCrt() == nil { t.Error("GetCrt() == nil, want []byte{}") } pubKey := privKey.GetPublicKey() if !cmp.Equal(pubKey.GetE(), keyFormat.GetPublicExponent()) { t.Errorf("GetE() = %v, want %v", pubKey.GetE(), keyFormat.GetPublicExponent()) } n := uint32(new(big.Int).SetBytes(pubKey.GetN()).BitLen()) if !cmp.Equal(n, keyFormat.GetModulusSizeInBits()) { t.Errorf("Modulus size in bits = %q, want %q", n, keyFormat.GetModulusSizeInBits()) } if !cmp.Equal(pubKey.GetParams(), keyFormat.GetParams(), protocmp.Transform()) { t.Errorf("GetParams() = %v, want %v", pubKey.GetParams(), keyFormat.GetParams()) } } func TestRSASSAPSSSignerNewKeyData(t *testing.T) { keyFormat := &rsppb.RsaSsaPssKeyFormat{ Params: &rsppb.RsaSsaPssParams{ SigHash: cpb.HashType_SHA256, Mgf1Hash: cpb.HashType_SHA256, SaltLength: 32, }, ModulusSizeInBits: 3072, PublicExponent: []byte{0x01, 0x00, 0x01}, } serializedKeyFormat, err := proto.Marshal(keyFormat) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } skm, err := registry.GetKeyManager(rsaPSSTestPrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", err, rsaPSSTestPrivateKeyTypeURL) } vkm, err := registry.GetKeyManager(rsaPSSTestPublicKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", err, rsaPSSTestPublicKeyTypeURL) } keyData, err := skm.NewKeyData(serializedKeyFormat) if err != nil { t.Fatalf("skm.NewKeyData() err = %v, want nil", err) } if keyData.GetKeyMaterialType() != tpb.KeyData_ASYMMETRIC_PRIVATE { t.Errorf("keyData.GetKeyMaterialType() = %v, want %v", keyData.GetKeyMaterialType(), tpb.KeyData_ASYMMETRIC_PRIVATE) } if keyData.GetTypeUrl() != rsaPSSTestPrivateKeyTypeURL { t.Errorf("keyData.GetTypeUrl() = %q, want %q", keyData.GetTypeUrl(), rsaPSSTestPrivateKeyTypeURL) } // Creating a primitive does a self key test which signs and verifies data. s, err := skm.Primitive(keyData.GetValue()) if err != nil { t.Fatalf("Primitive() err = %v, want nil", err) } signer, ok := s.(tink.Signer) if !ok { t.Fatal("Primitive() return type isn't a tink.Signer") } data := random.GetRandomBytes(50) sig, err := signer.Sign(data) if err != nil { t.Fatalf("signer.Sign() err = %v, want nil", err) } pubKeyData, err := skm.(registry.PrivateKeyManager).PublicKeyData(keyData.GetValue()) if err != nil { t.Fatalf("PublicKeyData() err = %v, want nil", err) } v, err := vkm.Primitive(pubKeyData.GetValue()) if err != nil { t.Fatalf("Primitive() err = %v, want nil", err) } verifier, ok := v.(tink.Verifier) if !ok { t.Fatal("Primitive() return type isn't a tink.Verifier") } if err := verifier.Verify(sig, data); err != nil { t.Fatalf("verifier.Verify() err = %v, want nil", err) } } func TestRSASSAPSSSignerNewKeyFailsWithInvalidFormat(t *testing.T) { type testCase struct { tag string keyFormat *rsppb.RsaSsaPssKeyFormat } skm, err := registry.GetKeyManager(rsaPSSTestPrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", err, rsaPSSTestPrivateKeyTypeURL) } validKeyFormat := &rsppb.RsaSsaPssKeyFormat{ Params: &rsppb.RsaSsaPssParams{ SigHash: cpb.HashType_SHA256, Mgf1Hash: cpb.HashType_SHA256, SaltLength: 32, }, ModulusSizeInBits: 3072, PublicExponent: []byte{0x01, 0x00, 0x01}, } serializedKeyFormat, err := proto.Marshal(validKeyFormat) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := skm.NewKeyData(serializedKeyFormat); err != nil { t.Fatalf("NewKeyData() err = %v, want nil", err) } for _, tc := range []testCase{ { tag: "nil params", keyFormat: &rsppb.RsaSsaPssKeyFormat{ Params: nil, ModulusSizeInBits: validKeyFormat.GetModulusSizeInBits(), PublicExponent: validKeyFormat.GetPublicExponent(), }, }, { tag: "unsafe hash function", keyFormat: &rsppb.RsaSsaPssKeyFormat{ Params: &rsppb.RsaSsaPssParams{ SigHash: cpb.HashType_SHA224, Mgf1Hash: cpb.HashType_SHA224, SaltLength: validKeyFormat.GetParams().GetSaltLength(), }, ModulusSizeInBits: validKeyFormat.GetModulusSizeInBits(), PublicExponent: validKeyFormat.GetPublicExponent(), }, }, { tag: "different signature and mgf1 hash function", keyFormat: &rsppb.RsaSsaPssKeyFormat{ Params: &rsppb.RsaSsaPssParams{ SigHash: cpb.HashType_SHA384, Mgf1Hash: cpb.HashType_SHA512, SaltLength: validKeyFormat.GetParams().GetSaltLength(), }, ModulusSizeInBits: validKeyFormat.GetModulusSizeInBits(), PublicExponent: validKeyFormat.GetPublicExponent(), }, }, { tag: "negative salt length", keyFormat: &rsppb.RsaSsaPssKeyFormat{ Params: &rsppb.RsaSsaPssParams{ SigHash: validKeyFormat.GetParams().GetSigHash(), Mgf1Hash: validKeyFormat.GetParams().GetMgf1Hash(), SaltLength: -1, }, ModulusSizeInBits: validKeyFormat.GetModulusSizeInBits(), PublicExponent: validKeyFormat.GetPublicExponent(), }, }, { tag: "insecure modulus size", keyFormat: &rsppb.RsaSsaPssKeyFormat{ Params: validKeyFormat.GetParams(), ModulusSizeInBits: 2047, PublicExponent: validKeyFormat.GetPublicExponent(), }, }, { tag: "invalid public exponent", keyFormat: &rsppb.RsaSsaPssKeyFormat{ Params: validKeyFormat.GetParams(), ModulusSizeInBits: validKeyFormat.GetModulusSizeInBits(), PublicExponent: []byte{0x00, 0x00, 0x03}, }, }, } { t.Run(tc.tag, func(t *testing.T) { serializedKeyFormat, err := proto.Marshal(tc.keyFormat) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := skm.NewKey(serializedKeyFormat); err == nil { t.Fatalf("NewKey() err = nil, want error") } if _, err := skm.NewKeyData(serializedKeyFormat); err == nil { t.Fatalf("NewKeyData() err = nil, want error") } }) } } func TestRSASSAPSSSignerPublicKeyData(t *testing.T) { skm, err := registry.GetKeyManager(rsaPSSTestPrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", err, rsaPSSTestPrivateKeyTypeURL) } vkm, err := registry.GetKeyManager(rsaPSSTestPublicKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", err, rsaPSSTestPublicKeyTypeURL) } validPrivKey, err := makeValidRSAPSSKey() if err != nil { t.Fatalf("makeValidRSAPSSKey() err = %v, want nil", err) } serializedPrivKey, err := proto.Marshal(validPrivKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } pubKeyData, err := skm.(registry.PrivateKeyManager).PublicKeyData(serializedPrivKey) if err != nil { t.Fatalf("PublicKeyData() err = %v, want nil", err) } if pubKeyData.GetKeyMaterialType() != tpb.KeyData_ASYMMETRIC_PUBLIC { t.Errorf("GetKeyMaterialType() = %v, want %v", pubKeyData.GetKeyMaterialType(), tpb.KeyData_ASYMMETRIC_PUBLIC) } if pubKeyData.GetTypeUrl() != rsaPSSTestPublicKeyTypeURL { t.Errorf("GetTypeUrl() = %q, want %q", pubKeyData.GetTypeUrl(), rsaPSSTestPublicKeyTypeURL) } if _, err := vkm.Primitive(pubKeyData.GetValue()); err != nil { t.Fatalf("vkm.Primitive() err = %v, want nil", err) } } ================================================ FILE: go/signature/rsassapss_verifier_key_manager.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature import ( "crypto/rsa" "errors" "fmt" "math/big" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" internal "github.com/google/tink/go/internal/signature" "github.com/google/tink/go/keyset" rsassapsspb "github.com/google/tink/go/proto/rsa_ssa_pss_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( rsaSSAPSSVerifierKeyVersion = 0 rsaSSAPSSVerifierTypeURL = "type.googleapis.com/google.crypto.tink.RsaSsaPssPublicKey" ) var ( errInvalidRSASSAPSSVerifierKey = errors.New("rsassapss_verifier_key_manager: invalid key") errRSASSAPSSNotImplemented = errors.New("rsassapss_verifier_key_manager: not implemented") ) type rsaSSAPSSVerifierKeyManager struct{} var _ (registry.KeyManager) = (*rsaSSAPSSVerifierKeyManager)(nil) func (km *rsaSSAPSSVerifierKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidRSASSAPSSVerifierKey } key := &rsassapsspb.RsaSsaPssPublicKey{} if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errInvalidRSASSAPSSVerifierKey } if err := validateRSAPSSPublicKey(key); err != nil { return nil, err } pubKey := &rsa.PublicKey{ E: int(new(big.Int).SetBytes(key.E).Uint64()), N: new(big.Int).SetBytes(key.N), } return internal.New_RSA_SSA_PSS_Verifier(hashName(key.GetParams().GetSigHash()), int(key.GetParams().GetSaltLength()), pubKey) } func validateRSAPSSPublicKey(pubKey *rsassapsspb.RsaSsaPssPublicKey) error { if err := keyset.ValidateKeyVersion(pubKey.GetVersion(), rsaSSAPSSVerifierKeyVersion); err != nil { return err } if pubKey.GetParams().GetSigHash() != pubKey.GetParams().GetMgf1Hash() { return fmt.Errorf("signature hash and MGF1 hash function must match") } if pubKey.GetParams().GetSaltLength() < 0 { return fmt.Errorf("salt length can't be negative") } return validateRSAPubKeyParams( pubKey.GetParams().GetSigHash(), new(big.Int).SetBytes(pubKey.GetN()).BitLen(), pubKey.GetE()) } func (km *rsaSSAPSSVerifierKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { return nil, errRSASSAPSSNotImplemented } func (km *rsaSSAPSSVerifierKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { return nil, errRSASSAPSSNotImplemented } func (km *rsaSSAPSSVerifierKeyManager) DoesSupport(typeURL string) bool { return typeURL == rsaSSAPSSVerifierTypeURL } func (km *rsaSSAPSSVerifierKeyManager) TypeURL() string { return rsaSSAPSSVerifierTypeURL } ================================================ FILE: go/signature/rsassapss_verifier_key_manager_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature_test import ( "crypto/rand" "crypto/rsa" "encoding/hex" "fmt" "math/big" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/tink" commonpb "github.com/google/tink/go/proto/common_go_proto" rsppb "github.com/google/tink/go/proto/rsa_ssa_pss_go_proto" ) const ( rsaPSSTestPublicKeyTypeURL = "type.googleapis.com/google.crypto.tink.RsaSsaPssPublicKey" ) func makeValidRSAPSSKey() (*rsppb.RsaSsaPssPrivateKey, error) { rsaKey, err := rsa.GenerateKey(rand.Reader, 3072) if err != nil { return nil, err } return &rsppb.RsaSsaPssPrivateKey{ Version: 0, PublicKey: &rsppb.RsaSsaPssPublicKey{ N: rsaKey.PublicKey.N.Bytes(), E: big.NewInt(int64(rsaKey.PublicKey.E)).Bytes(), Version: 0, Params: &rsppb.RsaSsaPssParams{ SigHash: commonpb.HashType_SHA256, Mgf1Hash: commonpb.HashType_SHA256, SaltLength: 32, }, }, D: rsaKey.D.Bytes(), P: rsaKey.Primes[0].Bytes(), Q: rsaKey.Primes[1].Bytes(), Dp: rsaKey.Precomputed.Dp.Bytes(), Dq: rsaKey.Precomputed.Dq.Bytes(), Crt: rsaKey.Precomputed.Qinv.Bytes(), }, nil } func TestRSASSAPSSVerifierNewKeyNotSupported(t *testing.T) { vkm, err := registry.GetKeyManager(rsaPSSTestPublicKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", err, rsaPSSTestPublicKeyTypeURL) } keyFormat := &rsppb.RsaSsaPssKeyFormat{ Params: &rsppb.RsaSsaPssParams{ SigHash: commonpb.HashType_SHA256, Mgf1Hash: commonpb.HashType_SHA256, SaltLength: 32, }, ModulusSizeInBits: 3072, PublicExponent: []byte{0x01, 0x00, 0x01}, } serializedKeyFormat, err := proto.Marshal(keyFormat) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := vkm.NewKey(serializedKeyFormat); err == nil { t.Errorf("NewKey() err = nil, want error") } if _, err := vkm.NewKeyData(serializedKeyFormat); err == nil { t.Errorf("NewKeyData() err = nil, want error") } } func TestRSASSAPSSVerifierDoesSupport(t *testing.T) { vkm, err := registry.GetKeyManager(rsaPSSTestPublicKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", err, rsaPSSTestPublicKeyTypeURL) } if !vkm.DoesSupport(rsaPSSTestPublicKeyTypeURL) { t.Errorf("DoesSupport(%q) = %v, want true", rsaPSSTestPublicKeyTypeURL, vkm.DoesSupport(rsaPSSTestPublicKeyTypeURL)) } if vkm.DoesSupport("fake.key.type") { t.Errorf("DoesSupport(%q) = %v, want false", "fake.key.type", vkm.DoesSupport("fake.key.type")) } } func TestRSASSAPSSVerifierTypeURL(t *testing.T) { vkm, err := registry.GetKeyManager(rsaPSSTestPublicKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", err, rsaPSSTestPublicKeyTypeURL) } if vkm.TypeURL() != rsaPSSTestPublicKeyTypeURL { t.Errorf("TypeURL() = %q, want %q", vkm.TypeURL(), rsaPSSTestPublicKeyTypeURL) } } type nistRSATestKey struct { // public keys only require `n` and `e` to be set. n string e string d string p string q string dp string dq string crt string } // The following keys are from: // https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Digital-Signatures // Publication FIPS 186-4 // Signature Verification PSS // Only keys with public exponent 65537 (aka: F4, 0x010001) where chosen since golang rsa/crypto // doesn't support other exponent values. var ( rsaPSS2048NISTKey = &nistRSATestKey{ n: "c6e0ed537a2d85cf1c4effad6419884d824ceabf5200e755691cb7328acd6a755fe85798502ccaec9e55d47afd0cf3258ebe920b50c5fd9d72897462bd0e459bbdf902b63d17195b2ef54908980be12aa7489f8af274b92c0cbc16aed2fa46f782d5517b666edfb2e5e5efeaff7e24965e26472e51980b0cfe457d297e6aa5dacb8e728dc6f58130f925a13275c3cace62f820db1e13cc5274c58ff4d7837671a1bf5f80d6ad8699c568df8d24dd0f152ded36ef4861f59b354bba96a076913a25facf4722737e6deed95b69a00fb2bced0feeedea4ff01a92605cfe26a6b39553d0c74e5650eb3779705e135c4b2fa518a8d4339c53efab4bb0058238def555", e: "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001", } rsaPSS3072NISTKey = &nistRSATestKey{ n: "a5f3da0aaf54b45f99a5d7085f213c3721cbe7e83b3e6c3fe0f5a84c7e387ba513392c28a9010d3b618c03847e6b11bbbbe4d5e47fc97ea696250699e96ecd911404f7b806957038a68bb59a520f2d90182d183e035204a914e6ac03c2bc6d3f9d7856b25f9041b56df310de3feb30aa468a0668a1e5da9cdb185956caa5d75e1cdcac2db823173495619105367231b7f2de7528a8a79ec9fdbbab601178a204a5aa4e19759eb16ea4bab87bf48bb1790f9fc6eb4d5674d3fbc11b922558d4e568e454b26a7178f3e147beb0c8ca6ecff5e52af248ac07d6a189393e17232adff2f7423f56b94b9a7d61fde23a9558ac7a3bc7c06748a5da11759f92baf4e386bb0212565b5beecf31d063cfab71af896b3d734750d9bca07343bfb3c28645226e9dad3070fc247c71c078e974934941000a79d01abab14d21f5e608c4e4d13deec1aef298e1247c50b47bfee6162f352f41cdba8628d1d628848c876cfb102dacce7fa160c04d3aabc8667a142a710b7f495fd350c4862a653d15c33d9266fd", e: "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001", } rsaPSS4096NISTKey = &nistRSATestKey{ n: "d7e8df622c35d46a2b92aa4a4167415178f57aa2b14f996008e41244a2c6e4e39e897579fa4d4fce60199033ee922c0f09fb8fe6572eed3a17a3c7a4ee33c8a715b6185200735c4dab77cab436b30b4d7a75900da2e87c823f233c45cd074db5805e70d582b31e3532f55aa73162302298c1c14dad186aa558c88840b04d8ce503a8a766089b66c1b0b4dcfa609e8376dee4913dfff6c3f8dcf2e962c7b72c867f67ad2b2750e920ea19ea518ee6b9d2149ff730afbeadae29b1cca3b73a61e867a700c12d3fce1b10f56b3611e4c37fe11042cf4230d7d966e5d1cdbc4e53d7049cd7f5066762db27193560f842a234f9d6d018f6bfa92a36d90c4b695e63e1ff8af82933431443a98dfaf17e780038f8cca2672ede3529aafe1d38ef73a5939c8664b3f39b0f45207cfe862f7059a8d36dcaa19588c1294e9720bc72474717e9924d1ab206aa16bf09a3dbf6cd6bdbd093870553bf6a14ea71bc24f892977d0f2adf22673813f923228fefa114c3333a40e86cd97f64bcedcaf0a2516c4a11cbd7ad2898b684f39b15435136c13e0aa1866d10b59c0a5b6338bca491daa62cf22e91edacf26cb6a3e6a9a6ce9671ef4e07612de935a9b0cc0ec437c6f7a23e895aac5708ebd7ef9d222b70370fcdd44cb8a1caf6f9009ae6fe6283e5508d5270b5b052fa7901311724f418e8c65fedfdfb9ac51f2bc98c30c909aaeb3fbe9d", e: "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001", } ) type nistRSAPSSTestVector struct { name string msg string sig string hashFunc commonpb.HashType saltLen int pubKey *nistRSATestKey } // The following test vectors are from: // https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Digital-Signatures // Publication FIPS 186-4 // Signature Verification PSS var nistRSAPSSTestVectors = []nistRSAPSSTestVector{ { name: "RSA_SSA_PSS_2048_SHA256_10", msg: "81eaf473d40896dbf4deac0f35c63bd1e129147c76e7aa8d0ef921631f55a7436411079f1bcc7b98714ac2c13b5e7326e60d918db1f05ffb19da767a95bb141a84c4b73664ccebf844f3601f7c853f009b21becba11af3106f1de5827b14e9fac84b2cbf16d18c045622acb260024768e8acc4c0ae2c0bd5f60a98023828cdec", sig: "40d59ebc6cb7b960cbda0db353f9b85d77e7c03f84447fb8e91b96a5a7377abc329d1f55c85e0dbedbc2886ce191d9e2cf3be05b33d6bbd2ba92b85eee2ff89cd6ee29cd531e42016e6aba1d620fe55e44480c033e8a59c0852dd1caffbc2ce82969e3a9f44ceff79f89993b9ebf3741b2ccab0b9516f2e128656a5b2ad5251e20c6ce0c26a14eef7ee86458942ddbe95ccc1f67b253e43e72117f49595dab5ba423496ece12825435661112666dbae71aaffd5a8f1d58db9dc02e0d70fe3ac36a87b8eeed4f20c00fd4303f9f767d03bca1a619bbe4b08e4e53b5cb69d2ba0235063e04ca392334d9979a41c42a66ca8b9721edcf76989ba89f3a170bb2e485", hashFunc: commonpb.HashType_SHA256, saltLen: 10, pubKey: rsaPSS2048NISTKey, }, { name: "RSA_SSA_PSS_2048_SHA384_10", msg: "32a7b1479acf505db793f3ebed953f4e31c9ecad1a3479df3af31e89ae7e0387f42eaf8efdfdc30f838ee85e9d6d06139197b7b1e93dfb85c9c52dd17f12352a5c05001fc2432d1b7f39098d595ebe45eab8c721afa2a7ea5bccdb7971830d1e11338a42122af64a529e3fbf4af2cface635064893ece7d5991111c8ab5bf12a", sig: "0cb375ecc34a9f36b88bf56ebf1235387ffacfd3dd09c48e872897caca60af9e386496aafd0d4b1fd8fb4714fac925edda6f34633c3bb08f7cca3d9ad8b76472de8c9f91cb7518648d368fbeb31d1a7cb39a40a7b17ee2f7bace9bd99ba08295aadd856cd6902ee6c96d5c1291dc299a7f3528a869f62fb8fbd51817ffe6490ed6e0007d7981ab12b8f4ce0d7432e8c3213fae2b81006f333714b513eba0414c161fab6ea23338567995f273e3269c44a587ad835c320d1e5ff553db4c47126680cd58293231915cf7aefb80690499243eda83f5347a300e070568baee2745b20c68688dad6e3807afcb34c72cdaeb9a571089c7f8c63d1b6ffdbe2fd13330e6", hashFunc: commonpb.HashType_SHA384, saltLen: 10, pubKey: rsaPSS2048NISTKey, }, { name: "RSA_SSA_PSS_2048_SHA512_10", msg: "35a37946e52678ee378f5f176838ef08f3c21392b1ad204645255be5b71fbc185fa5f161056ea65246b204fd393c77ab53c1b5d18870fc3fb3ca9a9b38b4b30ee8cb3f3d25f7527b4643a03c3dec40cd76b7b04303881ab2f731d59f0f882fb798bc6ac18ce904d1ffe93cbeb96ed1d7254d0dd26a1d0205d70114d984c2b77b", sig: "56279ccd2d37e8113625732cd3f3b61b4ef9325160c7f6af7077c25049d32742607ae3f845bd66cd6752813c26067fdc23f08008cf6a531124e9ebc9264f7cfd6d6eeff15daf97dad22565ec36b69125e7b27fc93892f6ff42ce8f265dc2cf2e5758ba0d67968e800e73fd47131008f5adc863919ea0cc153cf7efff134b0bcbd0af5505ab49af7b75d63a8aa7976b8fe77baf5a699a7e38a60eb7ca64e834f3e0f89da5b6a343a01f7657fd842c091a6208503bc75de8f95de0d871a6fc114b594ff99d615825fd3b896933381452536d68d9e034f65abf3412e8e32002689e102a8bb69991e04a7ff681b62e48ee687badf8690b2ccee4bf245cd0a25dcf21", hashFunc: commonpb.HashType_SHA512, saltLen: 10, pubKey: rsaPSS2048NISTKey, }, { name: "RSA_SSA_PSS_3072_SHA256_10", msg: "886f83a22335aee35be0f76ec4c32e644c29467e1ba459fcbea2ebdf8541735829651880b207b84998d02eb529e6d5462a0648b5c1d36ce7936db11c2946946a9831696a61bc573196c0a4813e363241fb4c4a2beab999c5cb4d789262cc71891cfcfec6f6fd93809bd9df3bcc5c503e0526d5485efee77faf69caa9f77b109e", sig: "92ae66dbda65a60a5f70031c3562ece74e615486acde2276c20ea01d82f7bab23af2aba27d62749850d49d2689381f1e875ade766dfe7b7f02fd601f3401dcf319caef080d73caecc08a2b4576d4cc3704bde1b7495bce086846a8a01488d00aecd54d4045f0b9e31262b460a94f0563e3d9eeb86d8f9403e5eef0d223ceb74e058a8095db8efe228d6755715bbaaafe1ab375df1112d740d951db72f6f4d25fae951a26d4c1d99f3b5a7bf311fa9cf580860b8c1b434e03d3ae0500b6457a2582275db531037a781aefc9d4f5820167a2a9cf86595fed5596246fa7fd2c8c2df0042caf9e25c59b289f58474145bf50950ecb05271afd7ce21da967b415f0de136ce5ba01fa7948bff66fea0a8063882cf88469a495ae75bba4ffb539ee5176731ec3778477f643669f94de0e4b7c856bcc511f56ad8aa23edca0c1d84d2c19abbdd191bfc0ca898fdb4b8100c44df99e5afcc93faf227a01a63c15bfd26e5e3f49fb34a98ea8a851703aad68463513d3a2ee6a4a2fe9fee958205dfd2db254", hashFunc: commonpb.HashType_SHA256, saltLen: 10, pubKey: rsaPSS3072NISTKey, }, { name: "RSA_SSA_PSS_3072_SHA384_10", msg: "5e5ca00767fad960921dcbbf16eb8e2ee85ad6db8caa6dbe2c33e17ce7607a8c6bfc6e98c6ac582679bde777ce20d3af6cb3163729c358601fceab49028d7802b131b9f10aee697503b639caf647852d3d678640ff6ec9af4906e014612f57185786eadbdcc6f497578f2b8036668bee82fe90bdb7b5a8f4d262e8a6ab4efe16", sig: "2ad995df3355aafb5dc71f06f10e42ef27d5a755351806961dec23ed08dc9cf0cd8d80a40fffe5ee54bdc71f355f661b59ff7a438a642b96d3e6ef95a54e5fd7d7af188b307914b8b8d05cbc09a046545be5c53908027c7324dd84b42f2a0054768161c6b1bad21de778babfe626f74bc325fed37dbba68648ad0b70881ee765825a215c23f21ae7f4805da65ae14fa8320cfa0cc43396e7a2193317695587bd8b4a3e935607465a0d29aa44f80ffb33e95604d087362a9a297aa8585cfcb4e1781bab34fbe7ea5503fd9a1deeec50caa56d7361d1159de065d2acf667d8bd46026cbca2cf8492e4ab6be427400db381b64e220c1cca709edc2768e80db78920912a929031c9bd0e13ad9fd6560c343904dc1bad633c3cdb7563dd4cf444ef2f7d8df047fe3ded5b277f94d56abf819943303fa6d9f0b55ecc20f98e92e6f1d34761148e7a51c51d5bd012cd6032aa2b3f0646059df34045f837c7eeaca6fa16357aa2c48922e34d4fb48183d11ca049684ae198c053de473bc167531b712516", hashFunc: commonpb.HashType_SHA384, saltLen: 10, pubKey: rsaPSS3072NISTKey, }, { name: "RSA_SSA_PSS_3072_SHA512_10", msg: "be7d5fca06c75896b6bbb0333a625d876b851447bf121975bcc05527b3f6a98baaea82289a06ad66db8f6d51dc88cb9a17d42ede449c2b2bcdf09ec183b1fa158faedd1cab0de8c592edcdc8b449a99e2f1f95d0fbd2777564ce1ff6be6a8f155412992ea1a5b0bcc31cf81e2c6d9f9c9bae70a54a7ea55a69a1fd51ccea0f92", sig: "04625331d8a8a03eb818e027407341feb037706e7421ae3a9c95a4119d98ee4c47c3262562ac6785c0c5fbed288478a1b69b5d51185780f4f3a3e897f453f89e279336ceaded9901d0a696ec0ced21dbca16e31b7996b642b7778e1752365f7a17c95d9e10c750c72d373deb940423fdbe63074be971590dfa9b2f6d629eae702cf715e052eb1631a934994f5bda15eaf2bf032a0059804145b50c8c68401458dd34d972d4747faa894bb830dafae440cd81096756a0897d8656c60ea7665922b0b0c21055fd411e9487e63213cc6c0ce5193fee48b99942685649de2d89f260800e8797bd4d572aa0c92b56466b431e5355c417123303a4fc908d7be8e1528724cd19906fd117a8390b8b9a61399a8284425b15025f34122f2bada19a18e3859d5dc03d6ae30aac2c7145288927aece2b2a5c2769d4de0fe90523362ab416f253a66265cb3b31613e4fb37f23319432a28838fa8adf1c3f807bbffb9d6eea78409ceb985f5d301daede0486e0fa933f81d632d3ac9690a7be4bef961c194132", hashFunc: commonpb.HashType_SHA512, saltLen: 10, pubKey: rsaPSS3072NISTKey, }, { name: "RSA_SSA_PSS_4096_SHA256_10", sig: "40a35351e11b783060d83bcafce26acf0d60e4b65c1aa487d705b9cc46393f7604c7237d168448a74c1acec7cfdedbd16c4c7bb25df9a1d89d3eb6d99e008cb61bcd466f9a30fbb4299eda0d9a327fa4102294ef08205e814bc44ba2a0243429f84a550b9d0b9dc19c823e92608a1b7e35f29d62eb11194ea55dd413ed82f35c25a1ad83f1d8844abf46b841cdbea149bd0a17bd6bd728e55d610de19618686eacab67a84fd6dc03c05deabd13bb83a26a6978d529fa15b468c35eca64c75209fb2a5cf6b624436710765e6507226b4e46686d247c17769c90e1839be25a5725262f82980bb097d7a06695d56426e244e01174dfbe9288611dfc6da3da181287c08a90488e5dc0698f9d5ec9dd0ac9dee0fe2bde7cb2f1c1aa5b61aefa44dc681f3e090b8de0e7e3eb52ca10a9c2d029aa0d8318f26e33e54d591f831a7f368db305da474fed7a7720ad3915cefd59c4c5b35d5066a48c8a9fc2e2bbb1430e7ba125c332c8d450e6d313c992878d80b4667cbfa255b9f79b82cabe2c24752c3da0917a4cbba9280279a7621724b6987e04e39f13bbd1ceec95031eb061142922160fd4c55af93148c36e36fb423ce113035d0d441aef27f7a60de29afda06425f2c51fc73c297ee8151e8a0e05b307db6f9a076271f07099cd902aff495461b7dcdd32cece0949d87e7f630f0ee5052d0e65c4496ae6645efad9e54052797388", msg: "158009419260a400e8eb9d7f65c65c9c3fdc67d3d99aca0c425fbcb7fe2e7f1b0aa788eb1a35e01b2588caf12346a65f16fd1590475d5ec1d2a411526459ea1d443df706907ffdd3ca2f193f93f5a349b50357d26748b767cde6ab5cbfe76b1acb2b9eb97da5c4d2ddc8d18e3a3b1a0326d475c1c2c49ca73c0fd3fc9540cbbb", hashFunc: commonpb.HashType_SHA256, saltLen: 10, pubKey: rsaPSS4096NISTKey, }, { name: "RSA_SSA_PSS_4096_SHA384_10", sig: "a8edbfcefecfc5bd4782ec1701a99fb5c5901e07d4fd004cab64e4331c70595ed7704a5747066d19ec4f70051932d833eedd46b0d21bef7111559d4439fdc859fd538a86088fb19cff2ba3d8a1f907b0eb9ec0a6aecab645cfd05e3f8297288c015b51bc761f4a431cdeeb441155a3f465f13758018803cb724bf062213ce1f6a59b4ad5516465a2064b8920c41af8df2c2d406f776ee0ac66f19ec0ecc0874d19bc1ff5a41a0db246d66d0814c4befc7430f668e94af3a2188c7d8d44a4426ec4801d652519db2badd641382dd7ef567be5458eed7a23429ecfb3d38d96534846dc4d62bfa2106156b714fd380e6f3a31702818c3349e6d7a5aa0a452ec8645936a37767c62b03aaf7f907ce70567dbb915a8c86b1ea1c32786e5c8f160319db7641accdd53bf9d7b8f648e1082c5521c41347dc58d1455c6e72bbea93f4ecf762f980b08ef2c31567190078d7c6b772a9816bdbc1d40b5ccd0d4979b69b78e1a401bec0bb957192dd31046a2dcc2489fae00dc8fa293f89ec8b36b56acac3f87bd92e04ba6ad5df7d46d322d0cf2b930a499a35971e2a1850651a7cf7e59e930f62bba68e436836b5e47490d92e35d3dca827e4448c8c92af7d6796663ab7fabbbcef0bc9f61fc00c822e406ed8fcea1b42286ae054c40c97c1eb2656c59bd3c6b18566e32f27c0e8f5ded3afdb28f175ab90b1980667666c5d06162f975f5", msg: "3874dd769d0426ee7dcbdceb67a9ad770e1781e34b15a45f656328c88ff485c1b2a083056d195afc5b20178c94f94131761cbd50a52defc8502e22cbb6f42aece9d74778d2ae4d0a76fb025a7762c856de607c7417399d463d32b14f9901e4156582f377d5ab484158c267fe1bcd880dce4b85f7ac21f700b5d79cfc3e04fd64", hashFunc: commonpb.HashType_SHA384, saltLen: 10, pubKey: rsaPSS4096NISTKey, }, { name: "RSA_SSA_PSS_4096_SHA384_10", sig: "3e6544351f1d6e4e76e354446b416544b54494831e99ac6adfdf68ca28dc8ea30cda2085d7f8ac0fec27d03c8ab0705835d647822277ec7b7bccd8c6857a9c017a6139cd88f0bf9a4559f1308445ffeafd94e010aff4127773b8ccbcaba0e8184d8ce8c990cea9d3b9f41b889bf5451eb2b6afd89b5bfe1e681e2447c4020ee93369e3bff4bfdebd03ba5b17ff78bb5dff04e4ec440d080ea26ef9aba76e9872ec271d56d678ce63588eaa50da25c005193030e0deb4b842e6aca4c645c094754a41e61263a5056852902b70dafa5381bddfa3dd6d881c5c67c33009d4fc8843c55e8662bec083ead69b1c005ea7aea175c08cf27c838aa9bb2c3eb2e08a7e458efce3f394118d069aa6e0663f7339753c49f14a1209fe8d3e546d0dad553e144939c208a48b4797afc24b9eb1788b65f568b8a815359a78bc92185f59c9532666bff497b56035a98f645d28cf12c1063f83cf736c6f38016a9626a886144cc90ad9dcae6a0d36fbd8377f13cf03342f59fbdd99f3985e17a364f0a2835332f4eb494ef16b63101f05dbc826ced2afb213da2aa368b2895fbe809a92873c6547e9755c35097c32ffc2c62ff395cec8e50a2d7ad50ed99f3daa8bfc0d16c9a63ae9fb150c88b49162d489a2cb8b0dbf260c113a9f9883728fc089e0af3026bf9a4fb3b8ef4ef85ff7f055b13b403bececb9f62bc6922153bed8b2a78b71168cea", msg: "b1a82d51fc2abf919b68f369f3057136f8f2f1204337f0fb66f0a76f7c953d57047f3c68efa84213f7b3f9ac332c48cbe810cbf3a39081718412c587dd7980cafca69cc9443ebcef83ae2aab7f6d10cdd281ec34f8453ea6a76983ff5e3a678e412437bc247595eee6636fad005132055d4e3a2a6ddf8e6275feca1e29625c6a", hashFunc: commonpb.HashType_SHA512, saltLen: 10, pubKey: rsaPSS4096NISTKey, }, } func (t *nistRSAPSSTestVector) ProtoKey() (*rsppb.RsaSsaPssPublicKey, error) { e, err := hex.DecodeString(t.pubKey.e) if err != nil { return nil, fmt.Errorf("hex.DecodeString(t.pubKey.e) err = %v, want nil", err) } n, err := hex.DecodeString(t.pubKey.n) if err != nil { return nil, fmt.Errorf("hex.DecodeString(t.pubKey.n) err = %v, want nil", err) } return &rsppb.RsaSsaPssPublicKey{ Version: 0, Params: &rsppb.RsaSsaPssParams{ SigHash: t.hashFunc, Mgf1Hash: t.hashFunc, SaltLength: int32(t.saltLen), }, E: e, N: n, }, nil } func TestRSASSAPSSVerifierPrimitive(t *testing.T) { vkm, err := registry.GetKeyManager(rsaPSSTestPublicKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", err, rsaPSSTestPublicKeyTypeURL) } for _, tc := range nistRSAPSSTestVectors { t.Run("nist test vector", func(t *testing.T) { k, err := tc.ProtoKey() if err != nil { t.Fatalf("tc.ProtoKey() err = %v, want nil", err) } sig, err := hex.DecodeString(tc.sig) if err != nil { t.Fatalf("hex.DecodeString() err = %v, want nil", err) } msg, err := hex.DecodeString(tc.msg) if err != nil { t.Fatalf("hex.DecodeString() err = %v, want nil", err) } serializedPublic, err := proto.Marshal(k) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } v, err := vkm.Primitive(serializedPublic) if err != nil { t.Fatalf("Primitive() err = %v, want nil", err) } verifier, ok := v.(tink.Verifier) if !ok { t.Fatalf("primitive isn't a tink verifier") } if err := verifier.Verify(sig, msg); err != nil { t.Errorf("verifier.Verify() err = %v, want nil", err) } }) } } func TestRSASSAPSSVerifierPrimitiveFailsWithInvalidKey(t *testing.T) { type testCase struct { tag string pubKey *rsppb.RsaSsaPssPublicKey } vkm, err := registry.GetKeyManager(rsaPSSTestPublicKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", err, rsaPSSTestPublicKeyTypeURL) } privKey, err := makeValidRSAPSSKey() if err != nil { t.Fatalf("makeValidRSAPSSKey() err = %v, want nil", err) } validPubKey := privKey.GetPublicKey() for _, tc := range []testCase{ { tag: "empty public key", pubKey: &rsppb.RsaSsaPssPublicKey{}, }, { tag: "nil params", pubKey: &rsppb.RsaSsaPssPublicKey{ Version: validPubKey.GetVersion(), Params: nil, N: validPubKey.GetN(), E: validPubKey.GetE(), }, }, { tag: "invalid public key version", pubKey: &rsppb.RsaSsaPssPublicKey{ Version: validPubKey.GetVersion() + 1, Params: validPubKey.GetParams(), N: validPubKey.GetN(), E: validPubKey.GetE(), }, }, { tag: "different sig and mgf1 hash functions", pubKey: &rsppb.RsaSsaPssPublicKey{ Version: validPubKey.GetVersion(), Params: &rsppb.RsaSsaPssParams{ SigHash: commonpb.HashType_SHA256, Mgf1Hash: commonpb.HashType_SHA384, SaltLength: validPubKey.GetParams().GetSaltLength(), }, N: validPubKey.GetN(), E: validPubKey.GetE(), }, }, { tag: "negative salt length", pubKey: &rsppb.RsaSsaPssPublicKey{ Version: validPubKey.GetVersion(), Params: &rsppb.RsaSsaPssParams{ SigHash: validPubKey.GetParams().GetSigHash(), Mgf1Hash: validPubKey.GetParams().GetMgf1Hash(), SaltLength: -1, }, N: validPubKey.GetN(), E: validPubKey.GetE(), }, }, { tag: "invalid hash function", pubKey: &rsppb.RsaSsaPssPublicKey{ Version: validPubKey.GetVersion(), Params: &rsppb.RsaSsaPssParams{ SigHash: commonpb.HashType_UNKNOWN_HASH, Mgf1Hash: commonpb.HashType_UNKNOWN_HASH, SaltLength: validPubKey.GetParams().GetSaltLength(), }, N: validPubKey.GetN(), E: validPubKey.GetE(), }, }, { tag: "unsafe hash function", pubKey: &rsppb.RsaSsaPssPublicKey{ Version: validPubKey.GetVersion(), Params: &rsppb.RsaSsaPssParams{ SigHash: commonpb.HashType_SHA1, Mgf1Hash: commonpb.HashType_SHA1, SaltLength: validPubKey.GetParams().GetSaltLength(), }, N: validPubKey.GetN(), E: validPubKey.GetE(), }, }, { tag: "invalid modulus", pubKey: &rsppb.RsaSsaPssPublicKey{ Version: validPubKey.GetVersion(), Params: validPubKey.GetParams(), N: []byte{0x00}, E: validPubKey.GetE(), }, }, { tag: "invalid exponent", pubKey: &rsppb.RsaSsaPssPublicKey{ Version: validPubKey.GetVersion(), Params: validPubKey.GetParams(), N: validPubKey.GetN(), E: []byte{0x01}, }, }, { tag: "exponent larger than 64 bits", pubKey: &rsppb.RsaSsaPssPublicKey{ Version: validPubKey.GetVersion(), Params: validPubKey.GetParams(), N: validPubKey.GetN(), E: random.GetRandomBytes(32), }, }, } { t.Run(tc.tag, func(t *testing.T) { serializedPubKey, err := proto.Marshal(tc.pubKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := vkm.Primitive(serializedPubKey); err == nil { t.Errorf("Primitive() err = nil, want error") } }) } } ================================================ FILE: go/signature/signature.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package signature provides implementations of the Signer and Verifier // primitives. // // To sign data using Tink you can use ECDSA, ED25519 or RSA-SSA-PKCS1 key templates. package signature import ( "fmt" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/internalregistry" ) func init() { // ECDSA if err := registry.RegisterKeyManager(new(ecdsaSignerKeyManager)); err != nil { panic(fmt.Sprintf("signature.init() failed: %v", err)) } if err := registry.RegisterKeyManager(new(ecdsaVerifierKeyManager)); err != nil { panic(fmt.Sprintf("signature.init() failed: %v", err)) } // ED25519 if err := registry.RegisterKeyManager(new(ed25519SignerKeyManager)); err != nil { panic(fmt.Sprintf("signature.init() failed: %v", err)) } if err := internalregistry.AllowKeyDerivation(ed25519SignerTypeURL); err != nil { panic(fmt.Sprintf("signature.init() failed: %v", err)) } if err := registry.RegisterKeyManager(new(ed25519VerifierKeyManager)); err != nil { panic(fmt.Sprintf("signature.init() failed: %v", err)) } // RSA SSA PKCS1 if err := registry.RegisterKeyManager(new(rsaSSAPKCS1SignerKeyManager)); err != nil { panic(fmt.Sprintf("signature.init() failed: %v", err)) } if err := registry.RegisterKeyManager(new(rsaSSAPKCS1VerifierKeyManager)); err != nil { panic(fmt.Sprintf("signature.init() failed: %v", err)) } // RSA SSA PSS if err := registry.RegisterKeyManager(new(rsaSSAPSSSignerKeyManager)); err != nil { panic(fmt.Sprintf("signature.init() failed: %v", err)) } if err := registry.RegisterKeyManager(new(rsaSSAPSSVerifierKeyManager)); err != nil { panic(fmt.Sprintf("signature.init() failed: %v", err)) } } ================================================ FILE: go/signature/signature_benchmark_test.go ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature_test import ( "testing" "github.com/google/tink/go/keyset" "github.com/google/tink/go/signature" "github.com/google/tink/go/subtle/random" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // Benchmarks for Signature algorithms. const benchmarkDataSize = 16 * 1024 var benchmarkTestCases = []struct { name string template *tinkpb.KeyTemplate }{ { name: "RSA_SSA_PKCS1_3072", template: signature.RSA_SSA_PKCS1_3072_SHA256_F4_Key_Template(), }, { name: "RSA_SSA_PSS_3072", template: signature.RSA_SSA_PSS_3072_SHA256_32_F4_Key_Template(), }, { name: "RSA_SSA_PKCS1_4096", template: signature.RSA_SSA_PKCS1_4096_SHA512_F4_Key_Template(), }, { name: "RSA_SSA_PSS_4096", template: signature.RSA_SSA_PSS_4096_SHA512_64_F4_Key_Template(), }, { name: "ECDSA_P256", template: signature.ECDSAP256KeyTemplate(), }, { name: "ECDSA_P384", template: signature.ECDSAP384SHA384KeyTemplate(), }, { name: "ECDSA_P521", template: signature.ECDSAP521KeyTemplate(), }, { name: "ED25519", template: signature.ED25519KeyTemplate(), }, } func BenchmarkSign(b *testing.B) { for _, tc := range benchmarkTestCases { b.Run(tc.name, func(b *testing.B) { b.ReportAllocs() handle, err := keyset.NewHandle(tc.template) if err != nil { b.Fatal(err) } primitive, err := signature.NewSigner(handle) if err != nil { b.Fatal(err) } data := random.GetRandomBytes(benchmarkDataSize) b.ResetTimer() for i := 0; i < b.N; i++ { _, err = primitive.Sign(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkVerify(b *testing.B) { for _, tc := range benchmarkTestCases { b.Run(tc.name, func(b *testing.B) { b.ReportAllocs() handle, err := keyset.NewHandle(tc.template) if err != nil { b.Fatal(err) } signer, err := signature.NewSigner(handle) if err != nil { b.Fatal(err) } data := random.GetRandomBytes(benchmarkDataSize) sig, err := signer.Sign(data) if err != nil { b.Fatal(err) } publicHandle, err := handle.Public() if err != nil { b.Fatal(err) } primitive, err := signature.NewVerifier(publicHandle) if err != nil { b.Fatal(err) } b.ResetTimer() for i := 0; i < b.N; i++ { err = primitive.Verify(sig, data) if err != nil { b.Fatal(err) } } }) } } ================================================ FILE: go/signature/signature_factory_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature_test import ( "bytes" "fmt" "testing" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/insecurecleartextkeyset" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/internal/testing/stubkeymanager" "github.com/google/tink/go/keyset" "github.com/google/tink/go/mac" "github.com/google/tink/go/monitoring" "github.com/google/tink/go/signature" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testing/fakemonitoring" "github.com/google/tink/go/testkeyset" "github.com/google/tink/go/testutil" commonpb "github.com/google/tink/go/proto/common_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestSignerVerifyFactory(t *testing.T) { tinkPriv, tinkPub := newECDSAKeysetKeypair(t, commonpb.HashType_SHA512, commonpb.EllipticCurveType_NIST_P521, tinkpb.OutputPrefixType_TINK, 1) legacyPriv, legacyPub := newECDSAKeysetKeypair(t, commonpb.HashType_SHA256, commonpb.EllipticCurveType_NIST_P256, tinkpb.OutputPrefixType_LEGACY, 2) rawPriv, rawPub := newECDSAKeysetKeypair(t, commonpb.HashType_SHA512, commonpb.EllipticCurveType_NIST_P384, tinkpb.OutputPrefixType_RAW, 3) crunchyPriv, crunchyPub := newECDSAKeysetKeypair(t, commonpb.HashType_SHA512, commonpb.EllipticCurveType_NIST_P384, tinkpb.OutputPrefixType_CRUNCHY, 4) privKeys := []*tinkpb.Keyset_Key{tinkPriv, legacyPriv, rawPriv, crunchyPriv} privKeyset := testutil.NewKeyset(privKeys[0].KeyId, privKeys) privKeysetHandle, err := testkeyset.NewHandle(privKeyset) if err != nil { t.Fatalf("testkeyset.NewHandle() err = %q, want nil", err) } pubKeys := []*tinkpb.Keyset_Key{tinkPub, legacyPub, rawPub, crunchyPub} pubKeyset := testutil.NewKeyset(pubKeys[0].KeyId, pubKeys) pubKeysetHandle, err := testkeyset.NewHandle(pubKeyset) if err != nil { t.Fatalf("testkeyset.NewHandle(pubKeyset) err = %v, want nil", err) } // sign some random data signer, err := signature.NewSigner(privKeysetHandle) if err != nil { t.Fatalf("signature.NewSigner(privKeysetHandle) err = %v, want nil", err) } data := random.GetRandomBytes(1211) sig, err := signer.Sign(data) if err != nil { t.Fatalf("signer.Sign(data) err = %v, want nil", err) } // verify with the same set of public keys should work verifier, err := signature.NewVerifier(pubKeysetHandle) if err != nil { t.Fatalf("signature.NewVerifier(pubKeysetHandle) err = %v, want nil", err) } if err := verifier.Verify(sig, data); err != nil { t.Errorf("verifier.Verify(sig, data) = %v, want nil", err) } // verify with other key should fail _, otherPub := newECDSAKeysetKeypair(t, commonpb.HashType_SHA512, commonpb.EllipticCurveType_NIST_P521, tinkpb.OutputPrefixType_TINK, 1) otherPubKeys := []*tinkpb.Keyset_Key{otherPub} otherPubKeyset := testutil.NewKeyset(otherPubKeys[0].KeyId, otherPubKeys) otherPubKeysetHandle, err := testkeyset.NewHandle(otherPubKeyset) if err != nil { t.Fatalf("testkeyset.NewHandle(otherPubKeyset) err = %v, want nil", err) } otherVerifier, err := signature.NewVerifier(otherPubKeysetHandle) if err != nil { t.Fatalf("signature.NewVerifier(otherPubKeysetHandle) err = %v, want nil", err) } if err = otherVerifier.Verify(sig, data); err == nil { t.Error("otherVerifier.Verify(sig, data) = nil, want not nil") } } func TestPrimitiveFactoryFailsWhenKeysetHasNoPrimary(t *testing.T) { privateKey, _ := newECDSAKeysetKeypair(t, commonpb.HashType_SHA512, commonpb.EllipticCurveType_NIST_P521, tinkpb.OutputPrefixType_TINK, 1) privateKeysetWithoutPrimary := &tinkpb.Keyset{ Key: []*tinkpb.Keyset_Key{privateKey}, } privateHandleWithoutPrimary, err := testkeyset.NewHandle(privateKeysetWithoutPrimary) if err != nil { t.Fatalf("testkeyset.NewHandle(privateKeysetWithoutPrimary) err = %v, want nil", err) } publicHandleWithoutPrimary, err := privateHandleWithoutPrimary.Public() if err != nil { t.Fatalf("privateHandleWithoutPrimary.Public() err = %v, want nil", err) } if _, err = signature.NewSigner(privateHandleWithoutPrimary); err == nil { t.Errorf("signature.NewSigner(privateHandleWithoutPrimary) err = nil, want not nil") } if _, err = signature.NewVerifier(publicHandleWithoutPrimary); err == nil { t.Errorf("signature.NewVerifier(publicHandleWithoutPrimary) err = nil, want not nil") } } func newECDSAKeysetKeypair(t *testing.T, hashType commonpb.HashType, curve commonpb.EllipticCurveType, outputPrefixType tinkpb.OutputPrefixType, keyID uint32) (*tinkpb.Keyset_Key, *tinkpb.Keyset_Key) { t.Helper() key := testutil.NewRandomECDSAPrivateKey(hashType, curve) serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } keyData := testutil.NewKeyData(testutil.ECDSASignerTypeURL, serializedKey, tinkpb.KeyData_ASYMMETRIC_PRIVATE) privKey := testutil.NewKey(keyData, tinkpb.KeyStatusType_ENABLED, keyID, outputPrefixType) serializedKey, err = proto.Marshal(key.PublicKey) if err != nil { t.Fatalf("proto.Marshal() err = %q, want nil", err) } keyData = testutil.NewKeyData(testutil.ECDSAVerifierTypeURL, serializedKey, tinkpb.KeyData_ASYMMETRIC_PUBLIC) pubKey := testutil.NewKey(keyData, tinkpb.KeyStatusType_ENABLED, keyID, outputPrefixType) return privKey, pubKey } func TestFactoryWithInvalidPrimitiveSetType(t *testing.T) { wrongKH, err := keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) err = %v, want nil", err) } _, err = signature.NewSigner(wrongKH) if err == nil { t.Error("signature.NewSigner(wrongKH) err = nil, want not nil") } _, err = signature.NewVerifier(wrongKH) if err == nil { t.Error("signature.NewVerifier(wrongKH) err = nil, want not nil") } } func TestFactoryWithValidPrimitiveSetType(t *testing.T) { goodKH, err := keyset.NewHandle(signature.ECDSAP256KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle(signature.ECDSAP256KeyTemplate()) err = %v, want nil", err) } _, err = signature.NewSigner(goodKH) if err != nil { t.Fatalf("signature.NewSigner(goodKH) err = %v, want nil", err) } goodPublicKH, err := goodKH.Public() if err != nil { t.Fatalf("goodKH.Public() err = %v, want nil", err) } _, err = signature.NewVerifier(goodPublicKH) if err != nil { t.Errorf("signature.NewVerifier(goodPublicKH) err = %v, want nil", err) } } func TestPrimitiveFactorySignVerifyWithoutAnnotationsDoesNothing(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } privHandle, err := keyset.NewHandle(signature.ED25519KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } signer, err := signature.NewSigner(privHandle) if err != nil { t.Fatalf("signature.NewSigner() err = %v, want nil", err) } pubHandle, err := privHandle.Public() if err != nil { t.Fatalf("privHandle.Public() err = %v, want nil", err) } verifier, err := signature.NewVerifier(pubHandle) if err != nil { t.Fatalf("signature.NewVerifier() err = %v, want nil", err) } data := []byte("some_important_data") sig, err := signer.Sign(data) if err != nil { t.Fatalf("signer.Sign() err = %v, want nil", err) } if err := verifier.Verify(sig, data); err != nil { t.Fatalf("verifier.Verify() err = %v, want nil", err) } if len(client.Events()) != 0 { t.Errorf("len(client.Events()) = %d, want 0", len(client.Events())) } if len(client.Failures()) != 0 { t.Errorf("len(client.Failures()) = %d, want 0", len(client.Failures())) } } func TestPrimitiveFactoryMonitoringWithAnnotationsLogSignVerify(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } handle, err := keyset.NewHandle(signature.ED25519KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(handle, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} privHandle, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } signer, err := signature.NewSigner(privHandle) if err != nil { t.Fatalf("signature.NewSigner() err = %v, want nil", err) } pubHandle, err := privHandle.Public() if err != nil { t.Fatalf("privHandle.Public() err = %v, want nil", err) } buff.Reset() if err := insecurecleartextkeyset.Write(pubHandle, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } pubHandle, err = insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } verifier, err := signature.NewVerifier(pubHandle) if err != nil { t.Fatalf("signature.NewVerifier() err = %v, want nil", err) } data := []byte("some_important_data") sig, err := signer.Sign(data) if err != nil { t.Fatalf("signer.Sign() err = %v, want nil", err) } if err := verifier.Verify(sig, data); err != nil { t.Fatalf("verifier.Verify() err = %v, want nil", err) } if len(client.Failures()) != 0 { t.Errorf("len(client.Failures()) = %d, want 0", len(client.Failures())) } got := client.Events() wantVerifyKeysetInfo := &monitoring.KeysetInfo{ Annotations: annotations, PrimaryKeyID: pubHandle.KeysetInfo().GetPrimaryKeyId(), Entries: []*monitoring.Entry{ { KeyID: pubHandle.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.Ed25519PublicKey", KeyPrefix: "TINK", }, }, } wantSignKeysetInfo := &monitoring.KeysetInfo{ Annotations: annotations, PrimaryKeyID: privHandle.KeysetInfo().GetPrimaryKeyId(), Entries: []*monitoring.Entry{ { KeyID: privHandle.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.Ed25519PrivateKey", KeyPrefix: "TINK", }, }, } want := []*fakemonitoring.LogEvent{ { Context: monitoring.NewContext("public_key_sign", "sign", wantSignKeysetInfo), KeyID: privHandle.KeysetInfo().GetPrimaryKeyId(), NumBytes: len(data), }, { Context: monitoring.NewContext("public_key_verify", "verify", wantVerifyKeysetInfo), KeyID: privHandle.KeysetInfo().GetPrimaryKeyId(), NumBytes: len(data), }, } if diff := cmp.Diff(want, got); diff != "" { t.Errorf("%v", diff) } } type alwaysFailingSigner struct{} func (a *alwaysFailingSigner) Sign(data []byte) ([]byte, error) { return nil, fmt.Errorf("failed") } func TestPrimitiveFactoryMonitoringWithAnnotationsSignFailureIsLogged(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } typeURL := "TestPrimitiveFactoryMonitoringWithAnnotationsSignFailureIsLogged" + "PrivateKeyManager" km := &stubkeymanager.StubPrivateKeyManager{ StubKeyManager: stubkeymanager.StubKeyManager{ URL: typeURL, Prim: &alwaysFailingSigner{}, KeyData: &tinkpb.KeyData{ TypeUrl: typeURL, Value: []byte("serialized_key"), KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PRIVATE, }, }, } if err := registry.RegisterKeyManager(km); err != nil { t.Fatalf("registry.RegisterKeyManager() err = %v, want nil", err) } template := &tinkpb.KeyTemplate{ TypeUrl: typeURL, OutputPrefixType: tinkpb.OutputPrefixType_LEGACY, } kh, err := keyset.NewHandle(template) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } buff := &bytes.Buffer{} if err := insecurecleartextkeyset.Write(kh, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } annotations := map[string]string{"foo": "bar"} privHandle, err := insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } signer, err := signature.NewSigner(privHandle) if err != nil { t.Fatalf("signature.NewSigner() err = %v, want nil", err) } if _, err := signer.Sign([]byte("some_data")); err == nil { t.Fatalf("signer.Sign() err = nil, want error") } if len(client.Events()) != 0 { t.Errorf("len(client.Events()) = %d, want 0", len(client.Events())) } got := client.Failures() want := []*fakemonitoring.LogFailure{ { Context: monitoring.NewContext( "public_key_sign", "sign", monitoring.NewKeysetInfo( annotations, kh.KeysetInfo().GetPrimaryKeyId(), []*monitoring.Entry{ { KeyID: kh.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: typeURL, KeyPrefix: "LEGACY", }, }, ), ), }, } if diff := cmp.Diff(want, got); diff != "" { t.Errorf("%v", diff) } } func TestPrimitiveFactoryMonitoringWithAnnotationsVerifyFailureIsLogged(t *testing.T) { defer internalregistry.ClearMonitoringClient() client := fakemonitoring.NewClient("fake-client") if err := internalregistry.RegisterMonitoringClient(client); err != nil { t.Fatalf("internalregistry.RegisterMonitoringClient() err = %v, want nil", err) } privHandle, err := keyset.NewHandle(signature.ED25519KeyTemplate()) if err != nil { t.Fatalf("keyset.NewHandle() err = %v, want nil", err) } pubHandle, err := privHandle.Public() if err != nil { t.Fatalf("privHandle.Public() err = %v, want nil", err) } buff := &bytes.Buffer{} annotations := map[string]string{"foo": "bar"} if err := insecurecleartextkeyset.Write(pubHandle, keyset.NewBinaryWriter(buff)); err != nil { t.Fatalf("insecurecleartextkeyset.Write() err = %v, want nil", err) } pubHandle, err = insecurecleartextkeyset.Read(keyset.NewBinaryReader(buff), keyset.WithAnnotations(annotations)) if err != nil { t.Fatalf("insecurecleartextkeyset.Read() err = %v, want nil", err) } verifier, err := signature.NewVerifier(pubHandle) if err != nil { t.Fatalf("signature.NewVerifier() err = %v, want nil", err) } if err := verifier.Verify([]byte("some_invalid_signature"), []byte("some_invalid_data")); err == nil { t.Fatalf("verifier.Verify() err = nil, want error") } if len(client.Events()) != 0 { t.Errorf("len(client.Events()) = %d, want 0", len(client.Events())) } got := client.Failures() want := []*fakemonitoring.LogFailure{ { Context: monitoring.NewContext( "public_key_verify", "verify", monitoring.NewKeysetInfo( annotations, pubHandle.KeysetInfo().GetPrimaryKeyId(), []*monitoring.Entry{ { KeyID: pubHandle.KeysetInfo().GetPrimaryKeyId(), Status: monitoring.Enabled, KeyType: "tink.Ed25519PublicKey", KeyPrefix: "TINK", }, }, ), ), }, } if diff := cmp.Diff(want, got); diff != "" { t.Errorf("%v", diff) } } func TestVerifyWithLegacyKeyDoesNotHaveSideEffectOnMessage(t *testing.T) { privateKey, publicKey := newECDSAKeysetKeypair(t, commonpb.HashType_SHA256, commonpb.EllipticCurveType_NIST_P256, tinkpb.OutputPrefixType_LEGACY, 2) privateKeyset := testutil.NewKeyset(privateKey.KeyId, []*tinkpb.Keyset_Key{privateKey}) privateHandle, err := testkeyset.NewHandle(privateKeyset) if err != nil { t.Fatalf("testkeyset.NewHandle(privateHandle) err = %v, want nil", err) } publicKeyset := testutil.NewKeyset(publicKey.KeyId, []*tinkpb.Keyset_Key{publicKey}) publicHandle, err := testkeyset.NewHandle(publicKeyset) if err != nil { t.Fatalf("testkeyset.NewHandle(publicKeyset) err = %v, want nil", err) } signer, err := signature.NewSigner(privateHandle) if err != nil { t.Fatalf("signature.NewSigner(privateHandle) err = %v, want nil", err) } verifier, err := signature.NewVerifier(publicHandle) if err != nil { t.Fatalf("signature.NewVerifier(publicHandle) err = %v, want nil", err) } data := []byte("data") message := data[:3] // Let message be a slice of data. sig, err := signer.Sign(message) if err != nil { t.Fatalf("signer.Sign(message) err = %v, want nil", err) } err = verifier.Verify(sig, message) if err != nil { t.Fatalf("verifier.Verify(sig, message) err = %v, want nil", err) } wantData := []byte("data") if !bytes.Equal(data, wantData) { t.Errorf("data = %q, want: %q", data, wantData) } } ================================================ FILE: go/signature/signature_init_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature_test import ( "testing" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/testutil" ) func TestSignatureInit(t *testing.T) { // Check that the ECDSA signer key manager is in the global registry. if _, err := registry.GetKeyManager(testutil.ECDSASignerTypeURL); err != nil { t.Errorf("unexpected error: %s", err) } // Check that the ECDSA verifier key manager is in the global registry. if _, err := registry.GetKeyManager(testutil.ECDSAVerifierTypeURL); err != nil { t.Errorf("unexpected error: %s", err) } } ================================================ FILE: go/signature/signature_key_templates.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature import ( "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/internal/tinkerror" commonpb "github.com/google/tink/go/proto/common_go_proto" ecdsapb "github.com/google/tink/go/proto/ecdsa_go_proto" rsppb "github.com/google/tink/go/proto/rsa_ssa_pkcs1_go_proto" rspsspb "github.com/google/tink/go/proto/rsa_ssa_pss_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // This file contains pre-generated KeyTemplates for Signer and Verifier. // One can use these templates to generate new Keysets. // ECDSAP256KeyTemplate is a KeyTemplate that generates a new ECDSA private key with the following parameters: // - Hash function: SHA256 // - Curve: NIST P-256 // - Signature encoding: DER // - Output prefix type: TINK func ECDSAP256KeyTemplate() *tinkpb.KeyTemplate { return createECDSAKeyTemplate(commonpb.HashType_SHA256, commonpb.EllipticCurveType_NIST_P256, ecdsapb.EcdsaSignatureEncoding_DER, tinkpb.OutputPrefixType_TINK) } // ECDSAP256KeyWithoutPrefixTemplate is a KeyTemplate that generates a new ECDSA private key with the following // parameters: // - Hash function: SHA256 // - Curve: NIST P-256 // - Signature encoding: DER // - Output prefix type: RAW // // Note that this template uses a different encoding than ESDSA_P256_RAW in Tinkey. func ECDSAP256KeyWithoutPrefixTemplate() *tinkpb.KeyTemplate { return createECDSAKeyTemplate(commonpb.HashType_SHA256, commonpb.EllipticCurveType_NIST_P256, ecdsapb.EcdsaSignatureEncoding_DER, tinkpb.OutputPrefixType_RAW) } // ECDSAP256RawKeyTemplate is a KeyTemplate that generates a new ECDSA private key with the following // parameters: // - Hash function: SHA256 // - Curve: NIST P-256 // - Signature encoding: IEEE_P1363 // - Output prefix type: RAW func ECDSAP256RawKeyTemplate() *tinkpb.KeyTemplate { return createECDSAKeyTemplate(commonpb.HashType_SHA256, commonpb.EllipticCurveType_NIST_P256, ecdsapb.EcdsaSignatureEncoding_IEEE_P1363, tinkpb.OutputPrefixType_RAW) } // ECDSAP384SHA384KeyTemplate is a KeyTemplate that generates a new ECDSA private key with the following parameters: // - Hash function: SHA384 // - Curve: NIST P-384 // - Signature encoding: DER // - Output prefix type: TINK func ECDSAP384SHA384KeyTemplate() *tinkpb.KeyTemplate { return createECDSAKeyTemplate(commonpb.HashType_SHA384, commonpb.EllipticCurveType_NIST_P384, ecdsapb.EcdsaSignatureEncoding_DER, tinkpb.OutputPrefixType_TINK) } // ECDSAP384SHA384KeyWithoutPrefixTemplate is a KeyTemplate that generates a new ECDSA private key with the following parameters: // - Hash function: SHA384 // - Curve: NIST P-384 // - Signature encoding: DER // - Output prefix type: RAW func ECDSAP384SHA384KeyWithoutPrefixTemplate() *tinkpb.KeyTemplate { return createECDSAKeyTemplate(commonpb.HashType_SHA384, commonpb.EllipticCurveType_NIST_P384, ecdsapb.EcdsaSignatureEncoding_DER, tinkpb.OutputPrefixType_RAW) } // ECDSAP384SHA512KeyTemplate is a KeyTemplate that generates a new ECDSA private key with the following parameters: // - Hash function: SHA512 // - Curve: NIST P-384 // - Signature encoding: DER // - Output prefix type: TINK func ECDSAP384SHA512KeyTemplate() *tinkpb.KeyTemplate { return createECDSAKeyTemplate(commonpb.HashType_SHA512, commonpb.EllipticCurveType_NIST_P384, ecdsapb.EcdsaSignatureEncoding_DER, tinkpb.OutputPrefixType_TINK) } // ECDSAP384KeyWithoutPrefixTemplate is a KeyTemplate that generates a new ECDSA private key with the following // parameters: // - Hash function: SHA512 // - Curve: NIST P-384 // - Signature encoding: DER // - Output prefix type: RAW func ECDSAP384KeyWithoutPrefixTemplate() *tinkpb.KeyTemplate { return createECDSAKeyTemplate(commonpb.HashType_SHA512, commonpb.EllipticCurveType_NIST_P384, ecdsapb.EcdsaSignatureEncoding_DER, tinkpb.OutputPrefixType_RAW) } // ECDSAP521KeyTemplate is a KeyTemplate that generates a new ECDSA private key with the following parameters: // - Hash function: SHA512 // - Curve: NIST P-521 // - Signature encoding: DER // - Output prefix type: TINK func ECDSAP521KeyTemplate() *tinkpb.KeyTemplate { return createECDSAKeyTemplate(commonpb.HashType_SHA512, commonpb.EllipticCurveType_NIST_P521, ecdsapb.EcdsaSignatureEncoding_DER, tinkpb.OutputPrefixType_TINK) } // ECDSAP521KeyWithoutPrefixTemplate is a KeyTemplate that generates a new ECDSA private key with the following // parameters: // - Hash function: SHA512 // - Curve: NIST P-521 // - Signature encoding: DER // - Output prefix type: RAW func ECDSAP521KeyWithoutPrefixTemplate() *tinkpb.KeyTemplate { return createECDSAKeyTemplate(commonpb.HashType_SHA512, commonpb.EllipticCurveType_NIST_P521, ecdsapb.EcdsaSignatureEncoding_DER, tinkpb.OutputPrefixType_RAW) } // createECDSAKeyTemplate creates a KeyTemplate containing a EcdasKeyFormat // with the given parameters. func createECDSAKeyTemplate(hashType commonpb.HashType, curve commonpb.EllipticCurveType, encoding ecdsapb.EcdsaSignatureEncoding, prefixType tinkpb.OutputPrefixType) *tinkpb.KeyTemplate { params := &ecdsapb.EcdsaParams{ HashType: hashType, Curve: curve, Encoding: encoding, } format := &ecdsapb.EcdsaKeyFormat{Params: params} serializedFormat, err := proto.Marshal(format) if err != nil { tinkerror.Fail(fmt.Sprintf("failed to marshal key format: %s", err)) } return &tinkpb.KeyTemplate{ TypeUrl: ecdsaSignerTypeURL, Value: serializedFormat, OutputPrefixType: prefixType, } } // ED25519KeyTemplate is a KeyTemplate that generates a new ED25519 private key. func ED25519KeyTemplate() *tinkpb.KeyTemplate { return &tinkpb.KeyTemplate{ TypeUrl: ed25519SignerTypeURL, OutputPrefixType: tinkpb.OutputPrefixType_TINK, } } // ED25519KeyWithoutPrefixTemplate is a KeyTemplate that generates a new ED25519 private key. func ED25519KeyWithoutPrefixTemplate() *tinkpb.KeyTemplate { return &tinkpb.KeyTemplate{ TypeUrl: ed25519SignerTypeURL, OutputPrefixType: tinkpb.OutputPrefixType_RAW, } } func create_RSA_SSA_PKCS1_Template(prefixType tinkpb.OutputPrefixType, hashType commonpb.HashType, modulusSizeInBits uint32) *tinkpb.KeyTemplate { keyFormat := &rsppb.RsaSsaPkcs1KeyFormat{ Params: &rsppb.RsaSsaPkcs1Params{ HashType: hashType, }, ModulusSizeInBits: modulusSizeInBits, PublicExponent: []byte{0x01, 0x00, 0x01}, } serializedFormat, err := proto.Marshal(keyFormat) if err != nil { tinkerror.Fail(fmt.Sprintf("failed to marshal key format: %s", err)) } return &tinkpb.KeyTemplate{ TypeUrl: rsaSSAPKCS1SignerTypeURL, OutputPrefixType: prefixType, Value: serializedFormat, } } func create_RSA_SSA_PSS_Template(prefixType tinkpb.OutputPrefixType, hashType commonpb.HashType, saltLength int32, modulusSizeInBits uint32) *tinkpb.KeyTemplate { keyFormat := &rspsspb.RsaSsaPssKeyFormat{ Params: &rspsspb.RsaSsaPssParams{ SigHash: hashType, Mgf1Hash: hashType, SaltLength: saltLength, }, ModulusSizeInBits: modulusSizeInBits, PublicExponent: []byte{0x01, 0x00, 0x01}, } serializedFormat, err := proto.Marshal(keyFormat) if err != nil { tinkerror.Fail(fmt.Sprintf("failed to marshal key format: %s", err)) } return &tinkpb.KeyTemplate{ TypeUrl: rsaSSAPSSSignerTypeURL, OutputPrefixType: prefixType, Value: serializedFormat, } } // RSA_SSA_PKCS1_3072_SHA256_F4_Key_Template is a KeyTemplate that generates a new RSA SSA PKCS1 private key with the following // parameters: // - Modulus size in bits: 3072. // - Hash function: SHA256. // - Public Exponent: 65537 (aka F4). // - OutputPrefixType: TINK func RSA_SSA_PKCS1_3072_SHA256_F4_Key_Template() *tinkpb.KeyTemplate { return create_RSA_SSA_PKCS1_Template(tinkpb.OutputPrefixType_TINK, commonpb.HashType_SHA256, 3072) } // RSA_SSA_PKCS1_3072_SHA256_F4_RAW_Key_Template is a KeyTemplate that generates a new RSA SSA PKCS1 private key with the following // parameters: // - Modulus size in bits: 3072. // - Hash function: SHA256. // - Public Exponent: 65537 (aka F4). // - OutputPrefixType: RAW func RSA_SSA_PKCS1_3072_SHA256_F4_RAW_Key_Template() *tinkpb.KeyTemplate { return create_RSA_SSA_PKCS1_Template(tinkpb.OutputPrefixType_RAW, commonpb.HashType_SHA256, 3072) } // RSA_SSA_PKCS1_4096_SHA512_F4_Key_Template is a KeyTemplate that generates a new RSA SSA PKCS1 private key with the following // parameters: // - Modulus size in bits: 4096. // - Hash function: SHA512. // - Public Exponent: 65537 (aka F4). // - OutputPrefixType: TINK func RSA_SSA_PKCS1_4096_SHA512_F4_Key_Template() *tinkpb.KeyTemplate { return create_RSA_SSA_PKCS1_Template(tinkpb.OutputPrefixType_TINK, commonpb.HashType_SHA512, 4096) } // RSA_SSA_PKCS1_4096_SHA512_F4_RAW_Key_Template is a KeyTemplate that generates a new RSA SSA PKCS1 private key with the following // parameters: // - Modulus size in bits: 4096. // - Hash function: SHA512. // - Public Exponent: 65537 (aka F4). // - OutputPrefixType: RAW func RSA_SSA_PKCS1_4096_SHA512_F4_RAW_Key_Template() *tinkpb.KeyTemplate { return create_RSA_SSA_PKCS1_Template(tinkpb.OutputPrefixType_RAW, commonpb.HashType_SHA512, 4096) } // RSA_SSA_PSS_3072_SHA256_32_F4_Key_Template is a KeyTemplate that generates a new RSA SSA PSS private key with the following // parameters: // - Modulus size in bits: 3072. // - Signature hash: SHA256. // - MGF1 hash: SHA256. // - Salt length: 32 (i.e., SHA256's output length). // - Public Exponent: 65537 (aka F4). // - OutputPrefixType: TINK func RSA_SSA_PSS_3072_SHA256_32_F4_Key_Template() *tinkpb.KeyTemplate { return create_RSA_SSA_PSS_Template(tinkpb.OutputPrefixType_TINK, commonpb.HashType_SHA256, 32, 3072) } // RSA_SSA_PSS_3072_SHA256_32_F4_Raw_Key_Template is a KeyTemplate that generates a new RSA SSA PSS private key with the following // parameters: // - Modulus size in bits: 3072. // - Signature hash: SHA256. // - MGF1 hash: SHA256. // - Salt length: 32 (i.e., SHA256's output length). // - Public Exponent: 65537 (aka F4). // - OutputPrefixType: RAW func RSA_SSA_PSS_3072_SHA256_32_F4_Raw_Key_Template() *tinkpb.KeyTemplate { return create_RSA_SSA_PSS_Template(tinkpb.OutputPrefixType_RAW, commonpb.HashType_SHA256, 32, 3072) } // RSA_SSA_PSS_4096_SHA512_64_F4_Key_Template is a KeyTemplate that generates a new RSA SSA PSS private key with the following // parameters: // - Modulus size in bits: 4096. // - Signature hash: SHA512. // - MGF1 hash: SHA512. // - Salt length: 64 (i.e., SHA512's output length). // - Public Exponent: 65537 (aka F4). // - OutputPrefixType: TINK func RSA_SSA_PSS_4096_SHA512_64_F4_Key_Template() *tinkpb.KeyTemplate { return create_RSA_SSA_PSS_Template(tinkpb.OutputPrefixType_TINK, commonpb.HashType_SHA512, 64, 4096) } // RSA_SSA_PSS_4096_SHA512_64_F4_Raw_Key_Template is a KeyTemplate that generates a new RSA SSA PSS private key with the following // parameters: // - Modulus size in bits: 4096. // - Signature hash: SHA512. // - MGF1 hash: SHA512. // - Salt length: 64 (i.e., SHA512's output length). // - Public Exponent: 65537 (aka F4). // - OutputPrefixType: RAW func RSA_SSA_PSS_4096_SHA512_64_F4_Raw_Key_Template() *tinkpb.KeyTemplate { return create_RSA_SSA_PSS_Template(tinkpb.OutputPrefixType_RAW, commonpb.HashType_SHA512, 64, 4096) } ================================================ FILE: go/signature/signature_key_templates_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature_test import ( "fmt" "testing" "github.com/google/tink/go/keyset" "github.com/google/tink/go/signature" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestKeyTemplates(t *testing.T) { var testCases = []struct { name string template *tinkpb.KeyTemplate }{ {name: "ECDSA_P256", template: signature.ECDSAP256KeyTemplate()}, {name: "ECDSA_P384_SHA384", template: signature.ECDSAP384SHA384KeyTemplate()}, {name: "ECDSA_P384_SHA512", template: signature.ECDSAP384SHA512KeyTemplate()}, {name: "ECDSA_P521", template: signature.ECDSAP521KeyTemplate()}, {name: "ECDSA_P256_RAW", template: signature.ECDSAP256RawKeyTemplate()}, {name: "ECDSA_P256_NO_PREFIX", template: signature.ECDSAP256KeyWithoutPrefixTemplate()}, {name: "ECDSA_P384_NO_PREFIX", template: signature.ECDSAP384KeyWithoutPrefixTemplate()}, {name: "ECDSA_P384_SHA384_NO_PREFIX", template: signature.ECDSAP384SHA384KeyWithoutPrefixTemplate()}, {name: "ECDSA_P521_NO_PREFIX", template: signature.ECDSAP521KeyWithoutPrefixTemplate()}, {name: "RSA_SSA_PKCS1_3072_SHA256_F4", template: signature.RSA_SSA_PKCS1_3072_SHA256_F4_Key_Template()}, {name: "RSA_SSA_PKCS1_3072_SHA256_F4_RAW", template: signature.RSA_SSA_PKCS1_3072_SHA256_F4_RAW_Key_Template()}, {name: "RSA_SSA_PKCS1_4096_SHA512_F4", template: signature.RSA_SSA_PKCS1_4096_SHA512_F4_Key_Template()}, {name: "RSA_SSA_PKCS1_4096_SHA512_F4_RAW", template: signature.RSA_SSA_PKCS1_4096_SHA512_F4_RAW_Key_Template()}, {name: "RSA_SSA_PSS_3072_SHA256_32_F4", template: signature.RSA_SSA_PSS_3072_SHA256_32_F4_Key_Template()}, {name: "RSA_SSA_PSS_3072_SHA256_32_F4_RAW", template: signature.RSA_SSA_PSS_3072_SHA256_32_F4_Raw_Key_Template()}, {name: "RSA_SSA_PSS_4096_SHA512_64_F4", template: signature.RSA_SSA_PSS_4096_SHA512_64_F4_Key_Template()}, {name: "RSA_SSA_PSS_4096_SHA512_64_F4_RAW", template: signature.RSA_SSA_PSS_4096_SHA512_64_F4_Raw_Key_Template()}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { if err := testSignVerify(tc.template); err != nil { t.Error(err) } }) } } func testSignVerify(template *tinkpb.KeyTemplate) error { privateHandle, err := keyset.NewHandle(template) if err != nil { return fmt.Errorf("keyset.NewHandle(tc.template) failed: %s", err) } signer, err := signature.NewSigner(privateHandle) if err != nil { return fmt.Errorf("signature.NewSigner(privateHandle) failed: %s", err) } publicHandle, err := privateHandle.Public() if err != nil { return fmt.Errorf("privateHandle.Public() failed: %s", err) } verifier, err := signature.NewVerifier(publicHandle) if err != nil { return fmt.Errorf("signature.NewVerifier(publicHandle) failed: %s", err) } var testInputs = []struct { message1 []byte message2 []byte }{ { message1: []byte("this data needs to be signed"), message2: []byte("this data needs to be signed"), }, { message1: []byte(""), message2: []byte(""), }, { message1: []byte(""), message2: nil, }, { message1: nil, message2: []byte(""), }, { message1: nil, message2: nil, }, } for _, ti := range testInputs { sig, err := signer.Sign(ti.message1) if err != nil { return fmt.Errorf("signer.Sign(ti.message1) failed: %s", err) } if err := verifier.Verify(sig, ti.message2); err != nil { return fmt.Errorf("verifier.Verify(sig, ti.message2) failed: %s", err) } } return nil } ================================================ FILE: go/signature/signature_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature_test // [START signature-example] import ( "bytes" "fmt" "log" "github.com/google/tink/go/insecurecleartextkeyset" "github.com/google/tink/go/keyset" "github.com/google/tink/go/signature" ) func Example() { // A private keyset created with // "tinkey create-keyset --key-template=ECDSA_P256 --out private_keyset.cfg". // Note that this keyset has the secret key information in cleartext. privateJSONKeyset := `{ "key": [{ "keyData": { "keyMaterialType": "ASYMMETRIC_PRIVATE", "typeUrl": "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey", "value": "EkwSBggDEAIYAhogEiSZ9u2nDtvZuDgWgGsVTIZ5/V08N4ycUspTX0RYRrkiIHpEwHxQd1bImkyMvV2bqtUbgMh5uPSTdnUEGrPXdt56GiEA3iUi+CRN71qy0fOCK66xAW/IvFyjOGtxjppRhSFUneo=" }, "keyId": 611814836, "outputPrefixType": "TINK", "status": "ENABLED" }], "primaryKeyId": 611814836 }` // The corresponding public keyset created with // "tinkey create-public-keyset --in private_keyset.cfg" publicJSONKeyset := `{ "key": [{ "keyData": { "keyMaterialType": "ASYMMETRIC_PUBLIC", "typeUrl": "type.googleapis.com/google.crypto.tink.EcdsaPublicKey", "value": "EgYIAxACGAIaIBIkmfbtpw7b2bg4FoBrFUyGef1dPDeMnFLKU19EWEa5IiB6RMB8UHdWyJpMjL1dm6rVG4DIebj0k3Z1BBqz13beeg==" }, "keyId": 611814836, "outputPrefixType": "TINK", "status": "ENABLED" }], "primaryKeyId": 611814836 }` // Create a keyset handle from the cleartext private keyset in the previous // step. The keyset handle provides abstract access to the underlying keyset to // limit the access of the raw key material. WARNING: In practice, // it is unlikely you will want to use a insecurecleartextkeyset, as it implies // that your key material is passed in cleartext, which is a security risk. // Consider encrypting it with a remote key in Cloud KMS, AWS KMS or HashiCorp Vault. // See https://github.com/google/tink/blob/master/docs/GOLANG-HOWTO.md#storing-and-loading-existing-keysets. privateKeysetHandle, err := insecurecleartextkeyset.Read( keyset.NewJSONReader(bytes.NewBufferString(privateJSONKeyset))) if err != nil { log.Fatal(err) } // Retrieve the Signer primitive from privateKeysetHandle. signer, err := signature.NewSigner(privateKeysetHandle) if err != nil { log.Fatal(err) } // Use the primitive to sign a message. In this case, the primary key of the // keyset will be used (which is also the only key in this example). data := []byte("data") sig, err := signer.Sign(data) if err != nil { log.Fatal(err) } // Create a keyset handle from the keyset containing the public key. Because the // public keyset does not contain any secrets, we can use [keyset.ReadWithNoSecrets]. publicKeysetHandle, err := keyset.ReadWithNoSecrets( keyset.NewJSONReader(bytes.NewBufferString(publicJSONKeyset))) if err != nil { log.Fatal(err) } // Retrieve the Verifier primitive from publicKeysetHandle. verifier, err := signature.NewVerifier(publicKeysetHandle) if err != nil { log.Fatal(err) } if err = verifier.Verify(sig, data); err != nil { log.Fatal(err) } fmt.Printf("sig is valid") // Output: sig is valid } // [END signature-example] ================================================ FILE: go/signature/signer_factory.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature import ( "fmt" "github.com/google/tink/go/core/primitiveset" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/internal/monitoringutil" "github.com/google/tink/go/keyset" "github.com/google/tink/go/monitoring" "github.com/google/tink/go/tink" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // NewSigner returns a Signer primitive from the given keyset handle. func NewSigner(handle *keyset.Handle) (tink.Signer, error) { ps, err := handle.Primitives() if err != nil { return nil, fmt.Errorf("public_key_sign_factory: cannot obtain primitive set: %s", err) } return newWrappedSigner(ps) } // wrappedSigner is an Signer implementation that uses the underlying primitive set for signing. type wrappedSigner struct { ps *primitiveset.PrimitiveSet logger monitoring.Logger } // Asserts that wrappedSigner implements the Signer interface. var _ tink.Signer = (*wrappedSigner)(nil) func newWrappedSigner(ps *primitiveset.PrimitiveSet) (*wrappedSigner, error) { if _, ok := (ps.Primary.Primitive).(tink.Signer); !ok { return nil, fmt.Errorf("public_key_sign_factory: not a Signer primitive") } for _, primitives := range ps.Entries { for _, p := range primitives { if _, ok := (p.Primitive).(tink.Signer); !ok { return nil, fmt.Errorf("public_key_sign_factory: not an Signer primitive") } } } logger, err := createSignerLogger(ps) if err != nil { return nil, err } return &wrappedSigner{ ps: ps, logger: logger, }, nil } func createSignerLogger(ps *primitiveset.PrimitiveSet) (monitoring.Logger, error) { // only keysets which contain annotations are monitored. if len(ps.Annotations) == 0 { return &monitoringutil.DoNothingLogger{}, nil } keysetInfo, err := monitoringutil.KeysetInfoFromPrimitiveSet(ps) if err != nil { return nil, err } return internalregistry.GetMonitoringClient().NewLogger(&monitoring.Context{ KeysetInfo: keysetInfo, Primitive: "public_key_sign", APIFunction: "sign", }) } // Sign signs the given data and returns the signature concatenated with the identifier of the // primary primitive. func (s *wrappedSigner) Sign(data []byte) ([]byte, error) { primary := s.ps.Primary signer, ok := (primary.Primitive).(tink.Signer) if !ok { return nil, fmt.Errorf("public_key_sign_factory: not a Signer primitive") } var signedData []byte if primary.PrefixType == tinkpb.OutputPrefixType_LEGACY { signedData = make([]byte, 0, len(data)+1) signedData = append(signedData, data...) signedData = append(signedData, byte(0)) } else { signedData = data } signature, err := signer.Sign(signedData) if err != nil { s.logger.LogFailure() return nil, err } s.logger.Log(primary.KeyID, len(data)) if len(primary.Prefix) == 0 { return signature, nil } output := make([]byte, 0, len(primary.Prefix)+len(signature)) output = append(output, primary.Prefix...) output = append(output, signature...) return output, nil } ================================================ FILE: go/signature/subtle/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep go_library( name = "subtle", srcs = [ "ecdsa.go", "ecdsa_signer.go", "ecdsa_verifier.go", "ed25519_signer.go", "ed25519_verifier.go", "encoding.go", "subtle.go", ], importpath = "github.com/google/tink/go/signature/subtle", deps = ["//subtle"], ) go_test( name = "subtle_test", srcs = [ "ecdsa_signer_verifier_test.go", "ecdsa_test.go", "ed25519_signer_verifier_test.go", "subtle_test.go", ], data = [ "//testdata/testvectors:ecdsa", "//testdata/testvectors:eddsa", ], deps = [ ":subtle", "//subtle", "//subtle/random", "//testutil", ], ) alias( name = "go_default_library", actual = ":subtle", visibility = ["//:__subpackages__"], ) ================================================ FILE: go/signature/subtle/ecdsa.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "errors" "fmt" "math/big" ) var errUnsupportedEncoding = errors.New("ecdsa: unsupported encoding") // ECDSASignature is a struct holding the r and s values of an ECDSA signature. type ECDSASignature struct { R, S *big.Int } // NewECDSASignature creates a new ECDSASignature instance. func NewECDSASignature(r, s *big.Int) *ECDSASignature { return &ECDSASignature{R: r, S: s} } // EncodeECDSASignature converts the signature to the given encoding format. func (sig *ECDSASignature) EncodeECDSASignature(encoding, curveName string) ([]byte, error) { var enc []byte var err error switch encoding { case "IEEE_P1363": enc, err = ieeeP1363Encode(sig, curveName) case "DER": enc, err = asn1encode(sig) default: err = errUnsupportedEncoding } if err != nil { return nil, fmt.Errorf("ecdsa: can't convert ECDSA signature to %s encoding: %v", encoding, err) } return enc, nil } // DecodeECDSASignature creates a new ECDSA signature using the given byte slice. // The function assumes that the byte slice is the concatenation of the BigEndian // representation of two big integer r and s. func DecodeECDSASignature(encodedBytes []byte, encoding string) (*ECDSASignature, error) { var sig *ECDSASignature var err error switch encoding { case "IEEE_P1363": sig, err = ieeeP1363Decode(encodedBytes) case "DER": sig, err = asn1decode(encodedBytes) default: err = errUnsupportedEncoding } if err != nil { return nil, fmt.Errorf("ecdsa: %s", err) } return sig, nil } // ValidateECDSAParams validates ECDSA parameters. // The hash's strength must not be weaker than the curve's strength. // DER and IEEE_P1363 encodings are supported. func ValidateECDSAParams(hashAlg string, curve string, encoding string) error { switch encoding { case "DER": case "IEEE_P1363": default: return errUnsupportedEncoding } switch curve { case "NIST_P256": if hashAlg != "SHA256" { return errors.New("invalid hash type, expect SHA-256") } case "NIST_P384": if hashAlg != "SHA384" && hashAlg != "SHA512" { return errors.New("invalid hash type, expect SHA-384 or SHA-512") } case "NIST_P521": if hashAlg != "SHA512" { return errors.New("invalid hash type, expect SHA-512") } default: return fmt.Errorf("unsupported curve: %s", curve) } return nil } ================================================ FILE: go/signature/subtle/ecdsa_signer.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "crypto/ecdsa" "crypto/rand" "errors" "fmt" "hash" "math/big" "github.com/google/tink/go/subtle" ) // ECDSASigner is an implementation of Signer for ECDSA. // At the moment, the implementation only accepts DER encoding. type ECDSASigner struct { privateKey *ecdsa.PrivateKey hashFunc func() hash.Hash encoding string } // NewECDSASigner creates a new instance of ECDSASigner. func NewECDSASigner(hashAlg, curve, encoding string, keyValue []byte) (*ECDSASigner, error) { privKey := new(ecdsa.PrivateKey) c := subtle.GetCurve(curve) if c == nil { return nil, errors.New("ecdsa_signer: invalid curve") } privKey.PublicKey.Curve = c privKey.D = new(big.Int).SetBytes(keyValue) privKey.PublicKey.X, privKey.PublicKey.Y = c.ScalarBaseMult(keyValue) return NewECDSASignerFromPrivateKey(hashAlg, encoding, privKey) } // NewECDSASignerFromPrivateKey creates a new instance of ECDSASigner func NewECDSASignerFromPrivateKey(hashAlg, encoding string, privateKey *ecdsa.PrivateKey) (*ECDSASigner, error) { if privateKey.Curve == nil { return nil, errors.New("ecdsa_signer: privateKey.Curve can't be nil") } curve := subtle.ConvertCurveName(privateKey.Curve.Params().Name) if err := ValidateECDSAParams(hashAlg, curve, encoding); err != nil { return nil, fmt.Errorf("ecdsa_signer: %s", err) } hashFunc := subtle.GetHashFunc(hashAlg) return &ECDSASigner{ privateKey: privateKey, hashFunc: hashFunc, encoding: encoding, }, nil } // Sign computes a signature for the given data. func (e *ECDSASigner) Sign(data []byte) ([]byte, error) { hashed, err := subtle.ComputeHash(e.hashFunc, data) if err != nil { return nil, err } r, s, err := ecdsa.Sign(rand.Reader, e.privateKey, hashed) if err != nil { return nil, fmt.Errorf("ecdsa_signer: signing failed: %s", err) } // format the signature sig := NewECDSASignature(r, s) ret, err := sig.EncodeECDSASignature(e.encoding, e.privateKey.PublicKey.Curve.Params().Name) if err != nil { return nil, fmt.Errorf("ecdsa_signer: signing failed: %s", err) } return ret, nil } ================================================ FILE: go/signature/subtle/ecdsa_signer_verifier_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "crypto/ecdsa" "crypto/rand" "fmt" "testing" subtleSignature "github.com/google/tink/go/signature/subtle" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/subtle" "github.com/google/tink/go/testutil" ) func TestSignVerify(t *testing.T) { data := random.GetRandomBytes(20) hash := "SHA256" curve := "NIST_P256" encodings := []string{"DER", "IEEE_P1363"} for _, encoding := range encodings { priv, err := ecdsa.GenerateKey(subtle.GetCurve(curve), rand.Reader) if err != nil { t.Fatalf("ecdsa.GenerateKey() err = %q, want nil", err) } // Use the private key and public key directly to create new instances signer, err := subtleSignature.NewECDSASignerFromPrivateKey(hash, encoding, priv) if err != nil { t.Errorf("unexpected error when creating ECDSASigner: %s", err) } verifier, err := subtleSignature.NewECDSAVerifierFromPublicKey(hash, encoding, &priv.PublicKey) if err != nil { t.Errorf("unexpected error when creating ECDSAVerifier: %s", err) } signature, err := signer.Sign(data) if err != nil { t.Errorf("unexpected error when signing: %s", err) } if err := verifier.Verify(signature, data); err != nil { t.Errorf("unexpected error when verifying: %s", err) } // Use byte slices to create new instances signer, err = subtleSignature.NewECDSASigner(hash, curve, encoding, priv.D.Bytes()) if err != nil { t.Errorf("unexpected error when creating ECDSASigner: %s", err) } verifier, err = subtleSignature.NewECDSAVerifier(hash, curve, encoding, priv.X.Bytes(), priv.Y.Bytes()) if err != nil { t.Errorf("unexpected error when creating ECDSAVerifier: %s", err) } signature, err = signer.Sign(data) if err != nil { t.Errorf("unexpected error when signing: %s", err) } if err = verifier.Verify(signature, data); err != nil { t.Errorf("unexpected error when verifying: %s", err) } } } func TestECDSAInvalidPublicKey(t *testing.T) { if _, err := subtleSignature.NewECDSAVerifier("SHA256", "NIST_P256", "IEEE_P1363", []byte{0, 32, 0}, []byte{0, 32}); err == nil { t.Errorf("subtleSignature.NewECDSAVerifier() err = nil, want error") } } func TestECDSAInvalidCurve(t *testing.T) { priv, err := ecdsa.GenerateKey(subtle.GetCurve("NIST_P256"), rand.Reader) if err != nil { t.Fatalf("ecdsa.GenerateKey() err = %q, want nil", err) } if _, err := subtleSignature.NewECDSAVerifier("SHA256", "INVALID", "IEEE_P1363", priv.X.Bytes(), priv.Y.Bytes()); err == nil { t.Errorf("subtleSignature.NewECDSAVerifier() err = nil, want error") } } func TestECDSAWycheproofCases(t *testing.T) { testutil.SkipTestIfTestSrcDirIsNotSet(t) vectors := []struct { Filename string Encoding string }{ {"ecdsa_test.json", "DER"}, {"ecdsa_secp256r1_sha256_p1363_test.json", "IEEE_P1363"}, {"ecdsa_secp384r1_sha512_p1363_test.json", "IEEE_P1363"}, {"ecdsa_secp521r1_sha512_p1363_test.json", "IEEE_P1363"}, } for _, v := range vectors { suite := new(ecdsaSuite) if err := testutil.PopulateSuite(suite, v.Filename); err != nil { t.Fatalf("failed populating suite: %s", err) } for _, group := range suite.TestGroups { hash := subtle.ConvertHashName(group.SHA) curve := subtle.ConvertCurveName(group.Key.Curve) if hash == "" || curve == "" { continue } x, err := subtle.NewBigIntFromHex(group.Key.Wx) if err != nil { t.Errorf("cannot decode wx: %s", err) continue } y, err := subtle.NewBigIntFromHex(group.Key.Wy) if err != nil { t.Errorf("cannot decode wy: %s", err) continue } verifier, err := subtleSignature.NewECDSAVerifier(hash, curve, v.Encoding, x.Bytes(), y.Bytes()) if err != nil { continue } for _, test := range group.Tests { caseName := fmt.Sprintf("%s-%s:Case-%d", group.Type, group.SHA, test.CaseID) t.Run(caseName, func(t *testing.T) { err := verifier.Verify(test.Signature, test.Message) switch test.Result { case "valid": if err != nil { t.Fatalf("ECDSAVerifier.Verify() failed in a valid test case: %s", err) } case "invalid": if err == nil { t.Fatalf("ECDSAVerifier.Verify() succeeded in an invalid test case") } case "acceptable": // TODO(ckl): Inspect flags to appropriately handle acceptable test cases. default: t.Fatalf("unsupported test result: %q", test.Result) } }) } } } } ================================================ FILE: go/signature/subtle/ecdsa_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "encoding/asn1" "encoding/hex" "math/big" "testing" "github.com/google/tink/go/signature/subtle" "github.com/google/tink/go/subtle/random" ) type paramsTestECDSA struct { hash string curve string encoding string } func TestECDSAEncodeDecodeDER(t *testing.T) { nTest := 1000 for i := 0; i < nTest; i++ { sig := newECDSARandomSignature() encoding := "DER" encoded, err := sig.EncodeECDSASignature(encoding, "P-256") if err != nil { t.Errorf("unexpected error during encoding: %s", err) } // first byte is 0x30 if encoded[0] != byte(0x30) { t.Errorf("first byte is incorrect, expected 48, got %v", encoded[0]) } // tag is 2 if encoded[2] != byte(2) || encoded[4+encoded[3]] != byte(2) { t.Errorf("expect tag to be 2 (integer), got %d and %d", encoded[2], encoded[4+encoded[3]]) } // length if len(encoded) != int(encoded[1])+2 { t.Errorf("incorrect length, expected %d, got %d", len(encoded), encoded[1]+2) } decodedSig, err := subtle.DecodeECDSASignature(encoded, encoding) if err != nil { t.Errorf("unexpected error during decoding: %s", err) } if decodedSig.R.Cmp(sig.R) != 0 || decodedSig.S.Cmp(sig.S) != 0 { t.Errorf("decoded signature doesn't match original value") } } } func TestECDSAEncodeDecodeIEEEP1363(t *testing.T) { nTest := 1000 for i := 0; i < nTest; i++ { sig := newECDSARandomSignature() encoding := "IEEE_P1363" encoded, err := sig.EncodeECDSASignature(encoding, "P-256") if err != nil { t.Errorf("unexpected error during encoding: %s", err) } if len(encoded) != 64 { t.Errorf("incorrect length, expected %d, got %d", 64, len(encoded)) } if len(sig.R.Bytes()) < 32 { expectedZeros := 32 - len(sig.R.Bytes()) for i := 0; i < expectedZeros; i++ { if encoded[i] != 0 { t.Errorf("expect byte %d to be 0, got %d. encoded data = %s", i, encoded[i], hex.Dump(encoded)) } } } if len(sig.S.Bytes()) < 32 { expectedZeros := 32 - len(sig.S.Bytes()) for i := 32; i < (32 + expectedZeros); i++ { if encoded[i] != 0 { t.Errorf("expect byte %d to be 0, got %d. encoded data = %s", i, encoded[i], hex.Dump(encoded)) } } } decodedSig, err := subtle.DecodeECDSASignature(encoded, encoding) if err != nil { t.Errorf("unexpected error during decoding: %s", err) } if decodedSig.R.Cmp(sig.R) != 0 || decodedSig.S.Cmp(sig.S) != 0 { t.Errorf("decoded signature doesn't match original value") } } } func TestECDSAEncodeWithInvalidInput(t *testing.T) { sig := newECDSARandomSignature() _, err := sig.EncodeECDSASignature("UNKNOWN_ENCODING", "P-256") if err == nil { t.Errorf("expect an error when encoding is invalid") } } func TestECDSADecodeWithModifiedFirstByte(t *testing.T) { sig := newECDSARandomSignature() encoded, err := sig.EncodeECDSASignature("DER", "P-256") if err != nil { t.Fatalf("sig.EncodeECDSASignature() err = %q, want nil", err) } encoded[0] = 0x31 if _, err := subtle.DecodeECDSASignature(encoded, "DER"); err == nil { t.Errorf("expect an error when first byte is not 0x30") } } func TestECDSADecodeWithModifiedTag(t *testing.T) { sig := newECDSARandomSignature() encoded, err := sig.EncodeECDSASignature("DER", "P-256") if err != nil { t.Fatalf("sig.EncodeECDSASignature() err = %q, want nil", err) } encoded[2] = encoded[2] + 1 if _, err := subtle.DecodeECDSASignature(encoded, "DER"); err == nil { t.Errorf("expect an error when tag is modified") } } func TestECDSADecodeWithModifiedLength(t *testing.T) { sig := newECDSARandomSignature() encoded, err := sig.EncodeECDSASignature("DER", "P-256") if err != nil { t.Fatalf("sig.EncodeECDSASignature() err = %q, want nil", err) } encoded[1] = encoded[1] + 1 if _, err := subtle.DecodeECDSASignature(encoded, "DER"); err == nil { t.Errorf("expect an error when length is modified") } } func TestECDSADecodeWithUnusedZeros(t *testing.T) { sig := newECDSARandomSignature() encoded, err := sig.EncodeECDSASignature("DER", "P-256") if err != nil { t.Fatalf("sig.EncodeECDSASignature() err = %q, want nil", err) } tmp := make([]byte, len(encoded)+4) copy(tmp, encoded) if _, err := subtle.DecodeECDSASignature(tmp, "DER"); err == nil { t.Errorf("expect an error when unused 0s are appended to signature") } } func TestECDSADecodeWithStructWithThreeNumbers(t *testing.T) { randomStruct := struct{ X, Y, Z *big.Int }{ X: new(big.Int).SetBytes(random.GetRandomBytes(32)), Y: new(big.Int).SetBytes(random.GetRandomBytes(32)), Z: new(big.Int).SetBytes(random.GetRandomBytes(32)), } encoded, err := asn1.Marshal(randomStruct) if err != nil { t.Fatalf("asn1.Marshal() err = %q, want nil", err) } if _, err := subtle.DecodeECDSASignature(encoded, "DER"); err == nil { t.Errorf("expect an error when input is not an ECDSASignature") } } func TestECDSAValidateParams(t *testing.T) { params := genECDSAValidParams() for i := 0; i < len(params); i++ { if err := subtle.ValidateECDSAParams(params[i].hash, params[i].curve, params[i].encoding); err != nil { t.Errorf("unexpected error for valid params: %s, i = %d", err, i) } } params = genECDSAInvalidParams() for i := 0; i < len(params); i++ { if err := subtle.ValidateECDSAParams(params[i].hash, params[i].curve, params[i].encoding); err == nil { t.Errorf("expect an error when params are invalid, i = %d", i) } } } func genECDSAInvalidParams() []paramsTestECDSA { encodings := []string{"DER", "IEEE_P1363"} testCases := []paramsTestECDSA{ // invalid encoding {hash: "SHA256", curve: "NIST_P256", encoding: "UNKNOWN_ENCODING"}, // invalid hash {hash: "SHA1", curve: "NIST_P256", encoding: "IEEE_P1363"}, // invalid curve {hash: "SHA1", curve: "UNKNOWN_CURVE", encoding: "IEEE_P1363"}, } for _, encoding := range encodings { testCases = append(testCases, // invalid curve paramsTestECDSA{hash: "SHA256", curve: "UNKNOWN_CURVE", encoding: encoding}, // invalid hash: P256 and SHA-512 paramsTestECDSA{hash: "SHA512", curve: "NIST_P256", encoding: encoding}, // invalid hash: P521 and SHA-256 paramsTestECDSA{hash: "SHA256", curve: "NIST_P521", encoding: encoding}, // invalid hash: P384 and SHA-256 paramsTestECDSA{hash: "SHA256", curve: "NIST_P384", encoding: encoding}, ) } return testCases } func genECDSAValidParams() []paramsTestECDSA { return []paramsTestECDSA{ {hash: "SHA256", curve: "NIST_P256", encoding: "DER"}, {hash: "SHA256", curve: "NIST_P256", encoding: "IEEE_P1363"}, {hash: "SHA384", curve: "NIST_P384", encoding: "DER"}, {hash: "SHA384", curve: "NIST_P384", encoding: "IEEE_P1363"}, {hash: "SHA512", curve: "NIST_P384", encoding: "DER"}, {hash: "SHA512", curve: "NIST_P384", encoding: "IEEE_P1363"}, {hash: "SHA512", curve: "NIST_P521", encoding: "DER"}, {hash: "SHA512", curve: "NIST_P521", encoding: "IEEE_P1363"}, } } func newECDSARandomSignature() *subtle.ECDSASignature { r := new(big.Int).SetBytes(random.GetRandomBytes(32)) s := new(big.Int).SetBytes(random.GetRandomBytes(32)) return subtle.NewECDSASignature(r, s) } ================================================ FILE: go/signature/subtle/ecdsa_verifier.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "crypto/ecdsa" "errors" "fmt" "hash" "math/big" "github.com/google/tink/go/subtle" ) var errInvalidECDSASignature = errors.New("ecdsa_verifier: invalid signature") // ECDSAVerifier is an implementation of Verifier for ECDSA. // At the moment, the implementation only accepts signatures with strict DER encoding. type ECDSAVerifier struct { publicKey *ecdsa.PublicKey hashFunc func() hash.Hash encoding string } // NewECDSAVerifier creates a new instance of ECDSAVerifier. func NewECDSAVerifier(hashAlg string, curve string, encoding string, x []byte, y []byte) (*ECDSAVerifier, error) { publicKey := &ecdsa.PublicKey{ Curve: subtle.GetCurve(curve), X: new(big.Int).SetBytes(x), Y: new(big.Int).SetBytes(y), } return NewECDSAVerifierFromPublicKey(hashAlg, encoding, publicKey) } // NewECDSAVerifierFromPublicKey creates a new instance of ECDSAVerifier. func NewECDSAVerifierFromPublicKey(hashAlg string, encoding string, publicKey *ecdsa.PublicKey) (*ECDSAVerifier, error) { if publicKey.Curve == nil { return nil, errors.New("ecdsa_verifier: invalid curve") } if !publicKey.Curve.IsOnCurve(publicKey.X, publicKey.Y) { return nil, fmt.Errorf("ecdsa_verifier: invalid public key") } curve := subtle.ConvertCurveName(publicKey.Curve.Params().Name) if err := ValidateECDSAParams(hashAlg, curve, encoding); err != nil { return nil, fmt.Errorf("ecdsa_verifier: %s", err) } hashFunc := subtle.GetHashFunc(hashAlg) return &ECDSAVerifier{ publicKey: publicKey, hashFunc: hashFunc, encoding: encoding, }, nil } // Verify verifies whether the given signature is valid for the given data. // It returns an error if the signature is not valid; nil otherwise. func (e *ECDSAVerifier) Verify(signatureBytes, data []byte) error { signature, err := DecodeECDSASignature(signatureBytes, e.encoding) if err != nil { return fmt.Errorf("ecdsa_verifier: %s", err) } hashed, err := subtle.ComputeHash(e.hashFunc, data) if err != nil { return err } valid := ecdsa.Verify(e.publicKey, hashed, signature.R, signature.S) if !valid { return errInvalidECDSASignature } return nil } ================================================ FILE: go/signature/subtle/ed25519_signer.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "crypto/ed25519" ) // ED25519Signer is an implementation of Signer for ED25519. type ED25519Signer struct { privateKey *ed25519.PrivateKey } // NewED25519Signer creates a new instance of ED25519Signer. func NewED25519Signer(keyValue []byte) (*ED25519Signer, error) { p := ed25519.NewKeyFromSeed(keyValue) return NewED25519SignerFromPrivateKey(&p) } // NewED25519SignerFromPrivateKey creates a new instance of ED25519Signer func NewED25519SignerFromPrivateKey(privateKey *ed25519.PrivateKey) (*ED25519Signer, error) { return &ED25519Signer{ privateKey: privateKey, }, nil } // Sign computes a signature for the given data. func (e *ED25519Signer) Sign(data []byte) ([]byte, error) { r := ed25519.Sign(*e.privateKey, data) if len(r) != ed25519.SignatureSize { return nil, errInvalidED25519Signature } return r, nil } ================================================ FILE: go/signature/subtle/ed25519_signer_verifier_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "bytes" "crypto/ed25519" "crypto/rand" "encoding/hex" "fmt" "testing" subtleSignature "github.com/google/tink/go/signature/subtle" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" ) func TestED25519Deterministic(t *testing.T) { data := random.GetRandomBytes(20) public, priv, err := ed25519.GenerateKey(rand.Reader) if err != nil { t.Errorf("key generation error: %s", err) } // Use the private key and public key directly to create new instances signer, verifier, err := newSignerVerifier(t, &priv, &public) if err != nil { t.Errorf("unexpected error when creating ED25519 Signer and Verifier: %s", err) } sign1, err := signer.Sign(data) if err != nil { t.Errorf("unexpected error when signing: %s", err) } if err := verifier.Verify(sign1, data); err != nil { t.Errorf("unexpected error when verifying: %s", err) } sign2, err := signer.Sign(data) if err != nil { t.Errorf("unexpected error when signing: %s", err) } if err := verifier.Verify(sign2, data); err != nil { t.Errorf("unexpected error when verifying: %s", err) } if !bytes.Equal(sign1, sign2) { t.Error("deterministic signature check failure") } } func TestEd25519VerifyModifiedSignature(t *testing.T) { data := random.GetRandomBytes(20) public, priv, err := ed25519.GenerateKey(rand.Reader) if err != nil { t.Errorf("key generation error: %s", err) } // Use the private key and public key directly to create new instances signer, verifier, err := newSignerVerifier(t, &priv, &public) if err != nil { t.Fatalf("failed to create new signer verifier: %v", err) } sign, err := signer.Sign(data) if err != nil { t.Errorf("unexpected error when signing: %s", err) } for i := 0; i < len(sign); i++ { for j := 0; j < 8; j++ { sign[i] = byte(sign[i] ^ (1 << uint32(j))) if err := verifier.Verify(sign, data); err == nil { t.Errorf("unexpected error when verifying: %s", err) } } } } func TestEd25519VerifyModifiedMessage(t *testing.T) { data := random.GetRandomBytes(20) public, priv, err := ed25519.GenerateKey(rand.Reader) if err != nil { t.Errorf("key generation error: %s", err) } // Use the private key and public key directly to create new instances signer, verifier, err := newSignerVerifier(t, &priv, &public) if err != nil { t.Fatalf("failed to create new signer verifier: %v", err) } sign, err := signer.Sign(data) if err != nil { t.Errorf("unexpected error when signing: %s", err) } for i := 0; i < len(data); i++ { for j := 0; j < 8; j++ { data[i] = byte(data[i] ^ (1 << uint32(j))) if err := verifier.Verify(sign, data); err == nil { t.Errorf("unexpected error when verifying: %s", err) } } } } func TestED25519SignVerify(t *testing.T) { public, priv, err := ed25519.GenerateKey(rand.Reader) if err != nil { t.Errorf("key generation error: %s", err) } // Use the private key and public key directly to create new instances signer, verifier, err := newSignerVerifier(t, &priv, &public) if err != nil { t.Errorf("unexpected error when creating ED25519 Signer and Verifier: %s", err) } for i := 0; i < 100; i++ { data := random.GetRandomBytes(20) signature, err := signer.Sign(data) if err != nil { t.Errorf("unexpected error when signing: %s", err) } if err := verifier.Verify(signature, data); err != nil { t.Errorf("unexpected error when verifying: %s", err) } // Use byte slices to create new instances signer, err = subtleSignature.NewED25519Signer(priv[:ed25519.SeedSize]) if err != nil { t.Errorf("unexpected error when creating ED25519 Signer: %s", err) } signature, err = signer.Sign(data) if err != nil { t.Errorf("unexpected error when signing: %s", err) } if err = verifier.Verify(signature, data); err != nil { t.Errorf("unexpected error when verifying: %s", err) } } } func TestED25519WycheproofCases(t *testing.T) { testutil.SkipTestIfTestSrcDirIsNotSet(t) suite := new(ed25519Suite) if err := testutil.PopulateSuite(suite, "eddsa_test.json"); err != nil { t.Fatalf("failed populating suite: %s", err) } for _, group := range suite.TestGroups { private := ed25519.PrivateKey(group.Key.SK) public := ed25519.PrivateKey(group.Key.PK) signer, err := subtleSignature.NewED25519Signer(private) if err != nil { continue } verifier, err := subtleSignature.NewED25519Verifier(public) if err != nil { continue } for _, test := range group.Tests { caseName := fmt.Sprintf("Sign-%s-%s:Case-%d", suite.Algorithm, group.Type, test.CaseID) t.Run(caseName, func(t *testing.T) { got, err := signer.Sign(test.Message) switch test.Result { case "valid": if err != nil { t.Fatalf("ED25519Signer.Sign() failed in a valid test case: %s", err) } if !bytes.Equal(got, test.Signature) { // Ed25519 is deterministic. // Getting an alternative signature may leak the private key. // This is especially the case if an attacker can also learn the valid signature. t.Fatalf("ED25519Signer.Sign() = %s, want = %s", hex.EncodeToString(got), hex.EncodeToString(test.Signature)) } case "invalid": if err == nil && bytes.Equal(got, test.Signature) { t.Fatalf("ED25519Signer.Sign() produced a matching signature in an invalid test case.") } default: t.Fatalf("unrecognized result: %q", test.Result) } }) caseName = fmt.Sprintf("Verify-%s-%s:Case-%d", suite.Algorithm, group.Type, test.CaseID) t.Run(caseName, func(t *testing.T) { err := verifier.Verify(test.Signature, test.Message) switch test.Result { case "valid": if err != nil { t.Fatalf("ED25519Verifier.Verify() failed in a valid test case: %s", err) } case "invalid": if err == nil { t.Fatal("ED25519Verifier.Verify() succeeded in an invalid test case.") } default: t.Fatalf("unsupported test result: %q", test.Result) } }) } } } func newSignerVerifier(t *testing.T, pvtKey *ed25519.PrivateKey, pubKey *ed25519.PublicKey) (*subtleSignature.ED25519Signer, *subtleSignature.ED25519Verifier, error) { t.Helper() signer, err := subtleSignature.NewED25519SignerFromPrivateKey(pvtKey) if err != nil { return nil, nil, err } verifier, err := subtleSignature.NewED25519VerifierFromPublicKey(pubKey) if err != nil { return nil, nil, err } return signer, verifier, nil } ================================================ FILE: go/signature/subtle/ed25519_verifier.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "crypto/ed25519" "errors" "fmt" ) var errInvalidED25519Signature = errors.New("ed25519: invalid signature") // ED25519Verifier is an implementation of Verifier for ED25519. // At the moment, the implementation only accepts signatures with strict DER encoding. type ED25519Verifier struct { publicKey *ed25519.PublicKey } // NewED25519Verifier creates a new instance of ED25519Verifier. func NewED25519Verifier(pub []byte) (*ED25519Verifier, error) { publicKey := ed25519.PublicKey(pub) return NewED25519VerifierFromPublicKey(&publicKey) } // NewED25519VerifierFromPublicKey creates a new instance of ED25519Verifier. func NewED25519VerifierFromPublicKey(publicKey *ed25519.PublicKey) (*ED25519Verifier, error) { return &ED25519Verifier{ publicKey: publicKey, }, nil } // Verify verifies whether the given signature is valid for the given data. // It returns an error if the signature is not valid; nil otherwise. func (e *ED25519Verifier) Verify(signature, data []byte) error { if len(signature) != ed25519.SignatureSize { return fmt.Errorf("the length of the signature is not %d", ed25519.SignatureSize) } if !ed25519.Verify(*e.publicKey, data, signature) { return errInvalidED25519Signature } return nil } ================================================ FILE: go/signature/subtle/encoding.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "bytes" "crypto/elliptic" "encoding/asn1" "fmt" "math/big" ) // asn1encode encodes the given ECDSA signature using ASN.1 encoding. func asn1encode(sig *ECDSASignature) ([]byte, error) { ret, err := asn1.Marshal(*sig) if err != nil { return nil, fmt.Errorf("asn.1 encoding failed") } return ret, nil } var errAsn1Decoding = fmt.Errorf("asn.1 decoding failed") // asn1decode verifies the given ECDSA signature and decodes it if it is valid. // Since asn1.Unmarshal() doesn't do a strict verification on its input, it will // accept signatures with trailing data. Thus, we add an additional check to make sure // that the input follows strict DER encoding: after unmarshalling the signature bytes, // we marshal the obtained signature object again. Since DER encoding is deterministic, // we expect that the obtained bytes would be equal to the input. func asn1decode(b []byte) (*ECDSASignature, error) { // parse the signature sig := new(ECDSASignature) _, err := asn1.Unmarshal(b, sig) if err != nil { return nil, errAsn1Decoding } // encode the signature again encoded, err := asn1.Marshal(*sig) if err != nil { return nil, errAsn1Decoding } if !bytes.Equal(b, encoded) { return nil, errAsn1Decoding } return sig, nil } func ieeeSignatureSize(curveName string) (int, error) { switch curveName { case elliptic.P256().Params().Name: return 64, nil case elliptic.P384().Params().Name: return 96, nil case elliptic.P521().Params().Name: return 132, nil default: return 0, fmt.Errorf("ieeeP1363 unsupported curve name: %q", curveName) } } func ieeeP1363Encode(sig *ECDSASignature, curveName string) ([]byte, error) { sigSize, err := ieeeSignatureSize(curveName) if err != nil { return nil, err } enc := make([]byte, sigSize) // sigR and sigS must be half the size of the signature. If not, we need to pad them with zeros. offset := 0 if len(sig.R.Bytes()) < (sigSize / 2) { offset += (sigSize / 2) - len(sig.R.Bytes()) } // Copy sigR after any zero-padding. copy(enc[offset:], sig.R.Bytes()) // Skip the bytes of sigR. offset = sigSize / 2 if len(sig.S.Bytes()) < (sigSize / 2) { offset += (sigSize / 2) - len(sig.S.Bytes()) } // Copy sigS after sigR and any zero-padding. copy(enc[offset:], sig.S.Bytes()) return enc, nil } func ieeeP1363Decode(encodedBytes []byte) (*ECDSASignature, error) { if len(encodedBytes) == 0 || len(encodedBytes) > 132 || len(encodedBytes)%2 != 0 { return nil, fmt.Errorf("ecdsa: Invalid IEEE_P1363 encoded bytes") } r := new(big.Int).SetBytes(encodedBytes[:len(encodedBytes)/2]) s := new(big.Int).SetBytes(encodedBytes[len(encodedBytes)/2:]) return &ECDSASignature{R: r, S: s}, nil } ================================================ FILE: go/signature/subtle/subtle.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package subtle provides subtle implementations of the digital signature // primitive. package subtle ================================================ FILE: go/signature/subtle/subtle_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import "github.com/google/tink/go/testutil" type ecdsaSuite struct { testutil.WycheproofSuite TestGroups []*ecdsaGroup `json:"testGroups"` } type ecdsaGroup struct { testutil.WycheproofGroup JWK *ecdsaJWK `json:"jwk,omitempty"` KeyDER string `json:"keyDer"` KeyPEM string `json:"keyPem"` SHA string `json:"sha"` Type string `json:"type"` Key *ecdsaTestKey `json:"key"` Tests []*ecdsaCase `json:"tests"` } type ecdsaCase struct { testutil.WycheproofCase Message testutil.HexBytes `json:"msg"` Signature testutil.HexBytes `json:"sig"` } type ecdsaTestKey struct { Curve string `json:"curve"` Type string `json:"type"` Wx string `json:"wx"` Wy string `json:"wy"` } type ecdsaJWK struct { JWK string `json:"jwk"` Curve string `json:"crv"` Kid string `json:"kid"` Kty string `json:"kty"` X string `json:"x"` Y string `json:"y"` } type ed25519Suite struct { testutil.WycheproofSuite TestGroups []*ed25519Group `json:"testGroups"` } type ed25519Group struct { testutil.WycheproofGroup KeyDER string `json:"keyDer"` KeyPEM string `json:"keyPem"` SHA string `json:"sha"` Type string `json:"type"` Key *ed25519TestKey `json:"key"` Tests []*ed25519Case `json:"tests"` } type ed25519Case struct { testutil.WycheproofCase Message testutil.HexBytes `json:"msg"` Signature testutil.HexBytes `json:"sig"` } type ed25519TestKey struct { SK testutil.HexBytes `json:"sk"` PK testutil.HexBytes `json:"pk"` } ================================================ FILE: go/signature/verifier_factory.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package signature import ( "errors" "fmt" "github.com/google/tink/go/core/cryptofmt" "github.com/google/tink/go/core/primitiveset" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/internal/monitoringutil" "github.com/google/tink/go/keyset" "github.com/google/tink/go/monitoring" "github.com/google/tink/go/tink" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // NewVerifier returns a Verifier primitive from the given keyset handle. func NewVerifier(handle *keyset.Handle) (tink.Verifier, error) { ps, err := handle.Primitives() if err != nil { return nil, fmt.Errorf("verifier_factory: cannot obtain primitive set: %s", err) } return newWrappedVerifier(ps) } // verifierSet is a Verifier implementation that uses the // underlying primitive set for verifying. type wrappedVerifier struct { ps *primitiveset.PrimitiveSet logger monitoring.Logger } // Asserts that verifierSet implements the Verifier interface. var _ tink.Verifier = (*wrappedVerifier)(nil) func newWrappedVerifier(ps *primitiveset.PrimitiveSet) (*wrappedVerifier, error) { if _, ok := (ps.Primary.Primitive).(tink.Verifier); !ok { return nil, fmt.Errorf("verifier_factory: not a Verifier primitive") } for _, primitives := range ps.Entries { for _, p := range primitives { if _, ok := (p.Primitive).(tink.Verifier); !ok { return nil, fmt.Errorf("verifier_factory: not an Verifier primitive") } } } logger, err := createVerifierLogger(ps) if err != nil { return nil, err } return &wrappedVerifier{ ps: ps, logger: logger, }, nil } func createVerifierLogger(ps *primitiveset.PrimitiveSet) (monitoring.Logger, error) { // only keysets which contain annotations are monitored. if len(ps.Annotations) == 0 { return &monitoringutil.DoNothingLogger{}, nil } keysetInfo, err := monitoringutil.KeysetInfoFromPrimitiveSet(ps) if err != nil { return nil, err } return internalregistry.GetMonitoringClient().NewLogger(&monitoring.Context{ KeysetInfo: keysetInfo, Primitive: "public_key_verify", APIFunction: "verify", }) } var errInvalidSignature = errors.New("verifier_factory: invalid signature") // Verify checks whether the given signature is a valid signature of the given data. func (v *wrappedVerifier) Verify(signature, data []byte) error { prefixSize := cryptofmt.NonRawPrefixSize if len(signature) < prefixSize { return errInvalidSignature } // try non-raw keys prefix := signature[:prefixSize] signatureNoPrefix := signature[prefixSize:] entries, err := v.ps.EntriesForPrefix(string(prefix)) if err == nil { for i := 0; i < len(entries); i++ { var signedData []byte if entries[i].PrefixType == tinkpb.OutputPrefixType_LEGACY { signedData = make([]byte, 0, len(data)+1) signedData = append(signedData, data...) signedData = append(signedData, byte(0)) } else { signedData = data } verifier, ok := (entries[i].Primitive).(tink.Verifier) if !ok { return fmt.Errorf("verifier_factory: not an Verifier primitive") } if err = verifier.Verify(signatureNoPrefix, signedData); err == nil { v.logger.Log(entries[i].KeyID, len(signedData)) return nil } } } // try raw keys entries, err = v.ps.RawEntries() if err == nil { for i := 0; i < len(entries); i++ { verifier, ok := (entries[i].Primitive).(tink.Verifier) if !ok { return fmt.Errorf("verifier_factory: not an Verifier primitive") } if err = verifier.Verify(signature, data); err == nil { v.logger.Log(entries[i].KeyID, len(data)) return nil } } } v.logger.LogFailure() return errInvalidSignature } ================================================ FILE: go/streamingaead/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep licenses(["notice"]) # keep go_library( name = "streamingaead", srcs = [ "aes_ctr_hmac_key_manager.go", "aes_gcm_hkdf_key_manager.go", "decrypt_reader.go", "streamingaead.go", "streamingaead_factory.go", "streamingaead_key_templates.go", ], importpath = "github.com/google/tink/go/streamingaead", visibility = ["//visibility:public"], deps = [ "//aead/subtle", "//core/primitiveset", "//core/registry", "//internal/internalregistry", "//internal/tinkerror", "//keyset", "//mac/subtle", "//proto/aes_ctr_hmac_streaming_go_proto", "//proto/aes_gcm_hkdf_streaming_go_proto", "//proto/common_go_proto", "//proto/hmac_go_proto", "//proto/tink_go_proto", "//streamingaead/subtle", "//subtle/random", "//tink", "@org_golang_google_protobuf//proto", ], ) go_test( name = "streamingaead_test", srcs = [ "aes_ctr_hmac_key_manager_test.go", "aes_gcm_hkdf_key_manager_test.go", "decrypt_reader_test.go", "streamingaead_factory_test.go", "streamingaead_key_templates_test.go", "streamingaead_test.go", ], embed = [":streamingaead"], deps = [ "//core/registry", "//insecurecleartextkeyset", "//internal/internalregistry", "//keyset", "//mac", "//proto/aes_ctr_hmac_streaming_go_proto", "//proto/aes_gcm_hkdf_streaming_go_proto", "//proto/common_go_proto", "//proto/tink_go_proto", "//streamingaead/subtle", "//subtle/random", "//testkeyset", "//testutil", "//tink", "@com_github_google_go_cmp//cmp", "@org_golang_google_protobuf//proto", ], ) alias( name = "go_default_library", actual = ":streamingaead", visibility = ["//visibility:public"], ) ================================================ FILE: go/streamingaead/aes_ctr_hmac_key_manager.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package streamingaead import ( "errors" "fmt" "google.golang.org/protobuf/proto" subtleaead "github.com/google/tink/go/aead/subtle" "github.com/google/tink/go/keyset" subtlemac "github.com/google/tink/go/mac/subtle" "github.com/google/tink/go/streamingaead/subtle" "github.com/google/tink/go/subtle/random" chpb "github.com/google/tink/go/proto/aes_ctr_hmac_streaming_go_proto" commonpb "github.com/google/tink/go/proto/common_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( aesCTRHMACKeyVersion = 0 aesCTRHMACTypeURL = "type.googleapis.com/google.crypto.tink.AesCtrHmacStreamingKey" ) var ( errInvalidAESCTRHMACKey = errors.New("aes_ctr_hmac_key_manager: invalid key") errInvalidAESCTRHMACKeyFormat = errors.New("aes_ctr_hmac_key_manager: invalid key format") ) // aesCTRHMACKeyManager is an implementation of KeyManager interface. // // It generates new AESCTRHMACKey keys and produces new instances of AESCTRHMAC // subtle. type aesCTRHMACKeyManager struct{} // Primitive creates an AESCTRHMAC subtle for the given serialized // AESCTRHMACKey proto. func (km *aesCTRHMACKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidAESCTRHMACKey } key := &chpb.AesCtrHmacStreamingKey{} if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errInvalidAESCTRHMACKey } if err := km.validateKey(key); err != nil { return nil, err } p, err := subtle.NewAESCTRHMAC( key.GetKeyValue(), key.GetParams().GetHkdfHashType().String(), int(key.GetParams().GetDerivedKeySize()), key.GetParams().GetHmacParams().GetHash().String(), int(key.GetParams().GetHmacParams().GetTagSize()), int(key.GetParams().GetCiphertextSegmentSize()), // No first segment offset. 0) if err != nil { return nil, fmt.Errorf("aes_ctr_hmac_key_manager: cannot create new primitive: %s", err) } return p, nil } // NewKey creates a new key according to specification in the given serialized // AesCtrHmacStreamingKeyFormat. func (km *aesCTRHMACKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errInvalidAESCTRHMACKeyFormat } keyFormat := &chpb.AesCtrHmacStreamingKeyFormat{} if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, errInvalidAESCTRHMACKeyFormat } if err := km.validateKeyFormat(keyFormat); err != nil { return nil, fmt.Errorf("%s: %s", errInvalidAESCTRHMACKeyFormat, err) } return &chpb.AesCtrHmacStreamingKey{ Version: aesCTRHMACKeyVersion, KeyValue: random.GetRandomBytes(keyFormat.GetKeySize()), Params: keyFormat.Params, }, nil } // NewKeyData creates a new KeyData according to specification in the given // serialized AesCtrHmacStreamingKeyFormat. // // It should be used solely by the key management API. func (km *aesCTRHMACKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { key, err := km.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: km.TypeURL(), Value: serializedKey, KeyMaterialType: tinkpb.KeyData_SYMMETRIC, }, nil } // DoesSupport indicates if this key manager supports the given key type. func (km *aesCTRHMACKeyManager) DoesSupport(typeURL string) bool { return typeURL == aesCTRHMACTypeURL } // TypeURL returns the key type of keys managed by this key manager. func (km *aesCTRHMACKeyManager) TypeURL() string { return aesCTRHMACTypeURL } // validateKey validates the given AESCTRHMACKey. func (km *aesCTRHMACKeyManager) validateKey(key *chpb.AesCtrHmacStreamingKey) error { if err := keyset.ValidateKeyVersion(key.GetVersion(), aesCTRHMACKeyVersion); err != nil { return err } keySize := uint32(len(key.GetKeyValue())) if err := subtleaead.ValidateAESKeySize(keySize); err != nil { return err } if err := km.validateParams(key.GetParams()); err != nil { return err } return nil } // validateKeyFormat validates the given AESCTRHMACKeyFormat. func (km *aesCTRHMACKeyManager) validateKeyFormat(format *chpb.AesCtrHmacStreamingKeyFormat) error { if err := subtleaead.ValidateAESKeySize(format.KeySize); err != nil { return err } if err := km.validateParams(format.GetParams()); err != nil { return err } return nil } // validateParams validates the given AESCTRHMACStreamingParams. func (km *aesCTRHMACKeyManager) validateParams(params *chpb.AesCtrHmacStreamingParams) error { if err := subtleaead.ValidateAESKeySize(params.GetDerivedKeySize()); err != nil { return err } if params.GetHkdfHashType() != commonpb.HashType_SHA1 && params.GetHkdfHashType() != commonpb.HashType_SHA256 && params.GetHkdfHashType() != commonpb.HashType_SHA512 { return fmt.Errorf("Invalid HKDF hash type (%s)", params.GetHkdfHashType()) } if params.GetHmacParams().GetHash() != commonpb.HashType_SHA1 && params.GetHmacParams().GetHash() != commonpb.HashType_SHA256 && params.GetHmacParams().GetHash() != commonpb.HashType_SHA512 { return fmt.Errorf("Invalid tag algorithm (%s)", params.GetHmacParams().GetHash()) } hmacHash := commonpb.HashType_name[int32(params.GetHmacParams().GetHash())] if err := subtlemac.ValidateHMACParams(hmacHash, subtle.AESCTRHMACKeySizeInBytes, params.GetHmacParams().GetTagSize()); err != nil { return err } minSegmentSize := params.GetDerivedKeySize() + subtle.AESCTRHMACNoncePrefixSizeInBytes + params.GetHmacParams().GetTagSize() + 2 if params.GetCiphertextSegmentSize() < minSegmentSize { return fmt.Errorf("ciphertext segment size must be at least (derivedKeySize + noncePrefixInBytes + tagSizeInBytes + 2)") } if params.GetCiphertextSegmentSize() > 0x7fffffff { return fmt.Errorf("ciphertext segment size must be at most 2^31 - 1") } return nil } ================================================ FILE: go/streamingaead/aes_ctr_hmac_key_manager_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package streamingaead_test import ( "fmt" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/streamingaead/subtle" "github.com/google/tink/go/testutil" ctrhmacpb "github.com/google/tink/go/proto/aes_ctr_hmac_streaming_go_proto" commonpb "github.com/google/tink/go/proto/common_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) var aesCTRHMACKeySizes = []uint32{16, 32} func TestAESCTRHMACGetPrimitiveBasic(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL) if err != nil { t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err) } for _, keySize := range aesCTRHMACKeySizes { key := testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, keySize, commonpb.HashType_SHA256, keySize, commonpb.HashType_SHA256, 16, 4096) serializedKey, err := proto.Marshal(key) if err != nil { t.Errorf("failed to marshal key: %s", err) } p, err := keyManager.Primitive(serializedKey) if err != nil { t.Errorf("unexpected error: %s", err) } if err := validateAESCTRHMACPrimitive(p, key); err != nil { t.Errorf("%s", err) } } } func TestAESCTRHMACGetPrimitiveWithInvalidInput(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL) if err != nil { t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err) } testKeys := genInvalidAESCTRHMACKeys() for i := 0; i < len(testKeys); i++ { serializedKey, err := proto.Marshal(testKeys[i]) if err != nil { t.Errorf("failed to marshal key: %s", err) } if _, err := keyManager.Primitive(serializedKey); err == nil { t.Errorf("expect an error in test case %d", i) } } if _, err := keyManager.Primitive(nil); err == nil { t.Errorf("expect an error when input is nil") } if _, err := keyManager.Primitive([]byte{}); err == nil { t.Errorf("expect an error when input is empty") } keyNilParams := testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 32, commonpb.HashType_SHA256, 32, commonpb.HashType_SHA256, 16, 4096) keyNilParams.Params = nil serializedKeyNilParams, err := proto.Marshal(keyNilParams) if err != nil { t.Errorf("proto.Marshal(keyNilParams) err = %v, want nil", err) } if _, err := keyManager.Primitive(serializedKeyNilParams); err == nil { t.Errorf("keyManager.Primitive(serializedKeyNilParams) err = nil, want non-nil") } } func TestAESCTRHMACNewKeyMultipleTimes(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL) if err != nil { t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err) } format := testutil.NewAESCTRHMACKeyFormat(32, commonpb.HashType_SHA256, 32, commonpb.HashType_SHA256, 16, 4096) serializedFormat, err := proto.Marshal(format) if err != nil { t.Errorf("failed to marshal key: %s", err) } keys := make(map[string]struct{}) n := 26 for i := 0; i < n; i++ { key, err := keyManager.NewKey(serializedFormat) if err != nil { t.Fatalf("keyManager.NewKey() err = %q, want nil", err) } serializedKey, err := proto.Marshal(key) if err != nil { t.Errorf("failed to marshal key: %s", err) } keys[string(serializedKey)] = struct{}{} keyData, err := keyManager.NewKeyData(serializedFormat) if err != nil { t.Fatalf("keyManager.NewKeyData() err = %q, want nil", err) } serializedKey = keyData.Value keys[string(serializedKey)] = struct{}{} } if len(keys) != n*2 { t.Errorf("key is repeated") } } func TestAESCTRHMACNewKeyBasic(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL) if err != nil { t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err) } for _, keySize := range aesCTRHMACKeySizes { format := testutil.NewAESCTRHMACKeyFormat(keySize, commonpb.HashType_SHA256, keySize, commonpb.HashType_SHA256, 16, 4096) serializedFormat, err := proto.Marshal(format) if err != nil { t.Errorf("failed to marshal key: %s", err) } m, err := keyManager.NewKey(serializedFormat) if err != nil { t.Errorf("unexpected error: %s", err) } key := m.(*ctrhmacpb.AesCtrHmacStreamingKey) if err := validateAESCTRHMACKey(key, format); err != nil { t.Errorf("%s", err) } } } func TestAESCTRHMACNewKeyWithInvalidInput(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL) if err != nil { t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err) } // bad format badFormats := genInvalidAESCTRHMACKeyFormats() for i := 0; i < len(badFormats); i++ { serializedFormat, err := proto.Marshal(badFormats[i]) if err != nil { t.Errorf("failed to marshal key: %s", err) } if _, err := keyManager.NewKey(serializedFormat); err == nil { t.Errorf("expect an error in test case %d", i) } } // nil if _, err := keyManager.NewKey(nil); err == nil { t.Errorf("expect an error when input is nil") } // empty array if _, err := keyManager.NewKey([]byte{}); err == nil { t.Errorf("expect an error when input is empty") } // params field is unset formatNilParams := testutil.NewAESCTRHMACKeyFormat(32, commonpb.HashType_SHA256, 32, commonpb.HashType_SHA256, 16, 4096) formatNilParams.Params = nil serializedFormatNilParams, err := proto.Marshal(formatNilParams) if err != nil { t.Errorf("proto.Marshal(formatNilParams) err = %v, want nil", err) } if _, err := keyManager.NewKey(serializedFormatNilParams); err == nil { t.Errorf("keyManager.NewKey(serializedFormatNilParams) err = nil, want non-nil") } } func TestAESCTRHMACNewKeyDataBasic(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL) if err != nil { t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err) } for _, keySize := range aesCTRHMACKeySizes { format := testutil.NewAESCTRHMACKeyFormat(keySize, commonpb.HashType_SHA256, keySize, commonpb.HashType_SHA256, 16, 4096) serializedFormat, err := proto.Marshal(format) if err != nil { t.Errorf("failed to marshal key: %s", err) } keyData, err := keyManager.NewKeyData(serializedFormat) if err != nil { t.Errorf("unexpected error: %s", err) } if keyData.TypeUrl != testutil.AESCTRHMACTypeURL { t.Errorf("incorrect type url") } if keyData.KeyMaterialType != tinkpb.KeyData_SYMMETRIC { t.Errorf("incorrect key material type") } key := new(ctrhmacpb.AesCtrHmacStreamingKey) if err := proto.Unmarshal(keyData.Value, key); err != nil { t.Errorf("incorrect key value") } if err := validateAESCTRHMACKey(key, format); err != nil { t.Errorf("%s", err) } p, err := registry.PrimitiveFromKeyData(keyData) if err != nil { t.Errorf("registry.PrimitiveFromKeyData(kd) err = %v, want nil", err) } _, ok := p.(*subtle.AESCTRHMAC) if !ok { t.Error("registry.PrimitiveFromKeyData(kd) did not return a AESCTRHMAC primitive") } } } func TestAESCTRHMACNewKeyDataWithInvalidInput(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL) if err != nil { t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err) } badFormats := genInvalidAESCTRHMACKeyFormats() for i := 0; i < len(badFormats); i++ { serializedFormat, err := proto.Marshal(badFormats[i]) if err != nil { t.Errorf("failed to marshal key: %s", err) } if _, err := km.NewKeyData(serializedFormat); err == nil { t.Errorf("expect an error in test case %d", i) } } // nil input if _, err := km.NewKeyData(nil); err == nil { t.Errorf("expect an error when input is nil") } // empty input if _, err := km.NewKeyData([]byte{}); err == nil { t.Errorf("expect an error when input is empty") } } func TestAESCTRHMACDoesSupport(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL) if err != nil { t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err) } if !keyManager.DoesSupport(testutil.AESCTRHMACTypeURL) { t.Errorf("AESCTRHMACKeyManager must support %s", testutil.AESCTRHMACTypeURL) } if keyManager.DoesSupport("some bad type") { t.Errorf("AESCTRHMACKeyManager must support only %s", testutil.AESCTRHMACTypeURL) } } func TestAESCTRHMACTypeURL(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESCTRHMACTypeURL) if err != nil { t.Errorf("cannot obtain AES-CTR-HMAC key manager: %s", err) } if keyManager.TypeURL() != testutil.AESCTRHMACTypeURL { t.Errorf("incorrect key type") } } func genInvalidAESCTRHMACKeys() []proto.Message { return []proto.Message{ // not a AESCTRHMACKey testutil.NewAESCTRHMACKeyFormat(32, commonpb.HashType_SHA256, 32, commonpb.HashType_SHA256, 16, 4096), // bad key size testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 17, commonpb.HashType_SHA256, 16, commonpb.HashType_SHA256, 16, 4096), testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 16, commonpb.HashType_SHA256, 17, commonpb.HashType_SHA256, 16, 4096), testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 33, commonpb.HashType_SHA256, 33, commonpb.HashType_SHA256, 16, 4096), // bad version testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion+1, 16, commonpb.HashType_SHA256, 16, commonpb.HashType_SHA256, 16, 4096), // bad ciphertext_segment_size testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 16, commonpb.HashType_SHA256, 16, commonpb.HashType_SHA256, 16, 2147483648), // bad hmac params hash type testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 16, commonpb.HashType_SHA256, 16, commonpb.HashType_SHA224, 16, 4096), testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 16, commonpb.HashType_SHA256, 16, commonpb.HashType_SHA384, 16, 4096), // bad hkdf hash type testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 16, commonpb.HashType_SHA224, 16, commonpb.HashType_SHA256, 16, 4096), testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 16, commonpb.HashType_SHA384, 16, commonpb.HashType_SHA256, 16, 4096), } } func genInvalidAESCTRHMACKeyFormats() []proto.Message { return []proto.Message{ // not AESCTRHMACKeyFormat testutil.NewAESCTRHMACKey(testutil.AESCTRHMACKeyVersion, 16, commonpb.HashType_SHA256, 16, commonpb.HashType_SHA256, 16, 4096), // invalid key size testutil.NewAESCTRHMACKeyFormat(17, commonpb.HashType_SHA256, 16, commonpb.HashType_SHA256, 16, 4096), testutil.NewAESCTRHMACKeyFormat(16, commonpb.HashType_SHA256, 17, commonpb.HashType_SHA256, 16, 4096), testutil.NewAESCTRHMACKeyFormat(33, commonpb.HashType_SHA256, 33, commonpb.HashType_SHA256, 16, 4096), } } func validateAESCTRHMACKey(key *ctrhmacpb.AesCtrHmacStreamingKey, format *ctrhmacpb.AesCtrHmacStreamingKeyFormat) error { if uint32(len(key.KeyValue)) != format.KeySize { return fmt.Errorf("incorrect key size") } if key.Version != testutil.AESCTRHMACKeyVersion { return fmt.Errorf("incorrect key version") } if key.Params.CiphertextSegmentSize != format.Params.CiphertextSegmentSize { return fmt.Errorf("incorrect ciphertext segment size") } if key.Params.DerivedKeySize != format.Params.DerivedKeySize { return fmt.Errorf("incorrect derived key size") } if key.Params.HkdfHashType != format.Params.HkdfHashType { return fmt.Errorf("incorrect HKDF hash type") } // try to encrypt and decrypt p, err := subtle.NewAESCTRHMAC( key.KeyValue, key.Params.HkdfHashType.String(), int(key.Params.DerivedKeySize), key.Params.HmacParams.Hash.String(), int(key.Params.HmacParams.TagSize), int(key.Params.CiphertextSegmentSize), 0, ) if err != nil { return fmt.Errorf("invalid key") } return validateAESCTRHMACPrimitive(p, key) } func validateAESCTRHMACPrimitive(p any, key *ctrhmacpb.AesCtrHmacStreamingKey) error { cipher := p.(*subtle.AESCTRHMAC) return encryptDecrypt(cipher, cipher, 32, 32) } ================================================ FILE: go/streamingaead/aes_gcm_hkdf_key_manager.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package streamingaead import ( "errors" "fmt" "io" "google.golang.org/protobuf/proto" subtleaead "github.com/google/tink/go/aead/subtle" "github.com/google/tink/go/keyset" "github.com/google/tink/go/streamingaead/subtle" "github.com/google/tink/go/subtle/random" ghpb "github.com/google/tink/go/proto/aes_gcm_hkdf_streaming_go_proto" commonpb "github.com/google/tink/go/proto/common_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( aesGCMHKDFKeyVersion = 0 aesGCMHKDFTypeURL = "type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey" ) var ( errInvalidAESGCMHKDFKey = errors.New("aes_gcm_hkdf_key_manager: invalid key") errInvalidAESGCMHKDFKeyFormat = errors.New("aes_gcm_hkdf_key_manager: invalid key format") ) // aesGCMHKDFKeyManager is an implementation of KeyManager interface. // It generates new AESGCMHKDFKey keys and produces new instances of AESGCMHKDF subtle. type aesGCMHKDFKeyManager struct{} // Primitive creates an AESGCMHKDF subtle for the given serialized AESGCMHKDFKey proto. func (km *aesGCMHKDFKeyManager) Primitive(serializedKey []byte) (any, error) { if len(serializedKey) == 0 { return nil, errInvalidAESGCMHKDFKey } key := &ghpb.AesGcmHkdfStreamingKey{} if err := proto.Unmarshal(serializedKey, key); err != nil { return nil, errInvalidAESGCMHKDFKey } if err := km.validateKey(key); err != nil { return nil, err } ret, err := subtle.NewAESGCMHKDF( key.GetKeyValue(), key.GetParams().GetHkdfHashType().String(), int(key.GetParams().GetDerivedKeySize()), int(key.GetParams().GetCiphertextSegmentSize()), // no first segment offset 0) if err != nil { return nil, fmt.Errorf("aes_gcm_hkdf_key_manager: cannot create new primitive: %s", err) } return ret, nil } // NewKey creates a new key according to specification in the given serialized // AesGcmHkdfStreamingKeyFormat. func (km *aesGCMHKDFKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errInvalidAESGCMHKDFKeyFormat } keyFormat := &ghpb.AesGcmHkdfStreamingKeyFormat{} if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, errInvalidAESGCMHKDFKeyFormat } if err := km.validateKeyFormat(keyFormat); err != nil { return nil, fmt.Errorf("aes_gcm_hkdf_key_manager: invalid key format: %s", err) } return &ghpb.AesGcmHkdfStreamingKey{ Version: aesGCMHKDFKeyVersion, KeyValue: random.GetRandomBytes(keyFormat.GetKeySize()), Params: keyFormat.Params, }, nil } // NewKeyData creates a new KeyData according to specification in the given serialized AesGcmHkdfStreamingKeyFormat. // It should be used solely by the key management API. func (km *aesGCMHKDFKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { key, err := km.NewKey(serializedKeyFormat) if err != nil { return nil, err } serializedKey, err := proto.Marshal(key) if err != nil { return nil, err } return &tinkpb.KeyData{ TypeUrl: km.TypeURL(), Value: serializedKey, KeyMaterialType: km.KeyMaterialType(), }, nil } // DoesSupport indicates if this key manager supports the given key type. func (km *aesGCMHKDFKeyManager) DoesSupport(typeURL string) bool { return typeURL == aesGCMHKDFTypeURL } // TypeURL returns the key type of keys managed by this key manager. func (km *aesGCMHKDFKeyManager) TypeURL() string { return aesGCMHKDFTypeURL } // KeyMaterialType returns the key material type of this key manager. func (km *aesGCMHKDFKeyManager) KeyMaterialType() tinkpb.KeyData_KeyMaterialType { return tinkpb.KeyData_SYMMETRIC } // DeriveKey derives a new key from serializedKeyFormat and pseudorandomness. func (km *aesGCMHKDFKeyManager) DeriveKey(serializedKeyFormat []byte, pseudorandomness io.Reader) (proto.Message, error) { if len(serializedKeyFormat) == 0 { return nil, errInvalidAESGCMHKDFKeyFormat } keyFormat := &ghpb.AesGcmHkdfStreamingKeyFormat{} if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { return nil, errInvalidAESGCMHKDFKeyFormat } if err := km.validateKeyFormat(keyFormat); err != nil { return nil, fmt.Errorf("aes_gcm_hkdf_key_manager: invalid key format: %v", err) } if err := keyset.ValidateKeyVersion(keyFormat.GetVersion(), aesGCMHKDFKeyVersion); err != nil { return nil, fmt.Errorf("aes_gcm_hkdf_key_manager: invalid key version: %s", err) } keyValue := make([]byte, keyFormat.GetKeySize()) if _, err := io.ReadFull(pseudorandomness, keyValue); err != nil { return nil, fmt.Errorf("aes_gcm_hkdf_key_manager: not enough pseudorandomness given") } return &ghpb.AesGcmHkdfStreamingKey{ Version: aesGCMHKDFKeyVersion, KeyValue: keyValue, Params: keyFormat.GetParams(), }, nil } // validateKey validates the given AESGCMHKDFKey. func (km *aesGCMHKDFKeyManager) validateKey(key *ghpb.AesGcmHkdfStreamingKey) error { if err := keyset.ValidateKeyVersion(key.Version, aesGCMHKDFKeyVersion); err != nil { return fmt.Errorf("aes_gcm_hkdf_key_manager: %s", err) } keySize := uint32(len(key.GetKeyValue())) if err := subtleaead.ValidateAESKeySize(keySize); err != nil { return fmt.Errorf("aes_gcm_hkdf_key_manager: %s", err) } if err := km.validateParams(key.GetParams()); err != nil { return fmt.Errorf("aes_gcm_hkdf_key_manager: %s", err) } return nil } // validateKeyFormat validates the given AESGCMHKDFKeyFormat. func (km *aesGCMHKDFKeyManager) validateKeyFormat(format *ghpb.AesGcmHkdfStreamingKeyFormat) error { if err := subtleaead.ValidateAESKeySize(format.KeySize); err != nil { return fmt.Errorf("aes_gcm_hkdf_key_manager: %s", err) } if err := km.validateParams(format.GetParams()); err != nil { return fmt.Errorf("aes_gcm_hkdf_key_manager: %s", err) } return nil } // validateKeyFormat validates the given AESGCMHKDFKeyFormat. func (km *aesGCMHKDFKeyManager) validateParams(params *ghpb.AesGcmHkdfStreamingParams) error { if err := subtleaead.ValidateAESKeySize(params.GetDerivedKeySize()); err != nil { return fmt.Errorf("aes_gcm_hkdf_key_manager: %s", err) } if params.GetHkdfHashType() != commonpb.HashType_SHA1 && params.GetHkdfHashType() != commonpb.HashType_SHA256 && params.GetHkdfHashType() != commonpb.HashType_SHA512 { return errors.New("unknown HKDF hash type") } if params.GetCiphertextSegmentSize() > 0x7fffffff { return errors.New("CiphertextSegmentSize must be at most 2^31 - 1") } minSegmentSize := params.GetDerivedKeySize() + subtle.AESGCMHKDFNoncePrefixSizeInBytes + subtle.AESGCMHKDFTagSizeInBytes + 2 if params.GetCiphertextSegmentSize() < minSegmentSize { return fmt.Errorf("ciphertext segment_size must be at least (derivedKeySize + noncePrefixInBytes + tagSizeInBytes + 2)") } return nil } ================================================ FILE: go/streamingaead/aes_gcm_hkdf_key_manager_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package streamingaead_test import ( "bytes" "encoding/hex" "fmt" "testing" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/internalregistry" "github.com/google/tink/go/streamingaead/subtle" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" gcmhkdfpb "github.com/google/tink/go/proto/aes_gcm_hkdf_streaming_go_proto" commonpb "github.com/google/tink/go/proto/common_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) var aesGCMHKDFKeySizes = []uint32{16, 32} func TestAESGCMHKDFGetPrimitiveBasic(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMHKDFTypeURL) if err != nil { t.Errorf("cannot obtain AES-GCM-HKDF key manager: %s", err) } for _, keySize := range aesGCMHKDFKeySizes { key := testutil.NewAESGCMHKDFKey(testutil.AESGCMHKDFKeyVersion, keySize, keySize, commonpb.HashType_SHA256, 4096) serializedKey, err := proto.Marshal(key) if err != nil { t.Errorf("failed to marshal key: %s", err) } p, err := keyManager.Primitive(serializedKey) if err != nil { t.Errorf("unexpected error: %s", err) } if err := validatePrimitive(p, key); err != nil { t.Errorf("%s", err) } } } func TestAESGCMHKDFGetPrimitiveWithInvalidInput(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMHKDFTypeURL) if err != nil { t.Errorf("cannot obtain AES-GCM-HKDF key manager: %s", err) } testKeys := genInvalidAESGCMHKDFKeys() for i := 0; i < len(testKeys); i++ { serializedKey, err := proto.Marshal(testKeys[i]) if err != nil { t.Errorf("failed to marshal key: %s", err) } if _, err := keyManager.Primitive(serializedKey); err == nil { t.Errorf("expect an error in test case %d", i) } } if _, err := keyManager.Primitive(nil); err == nil { t.Errorf("expect an error when input is nil") } if _, err := keyManager.Primitive([]byte{}); err == nil { t.Errorf("expect an error when input is empty") } keyNilParams := testutil.NewAESGCMHKDFKey(testutil.AESGCMHKDFKeyVersion, 32, 32, commonpb.HashType_SHA256, 4096) keyNilParams.Params = nil serializedKeyNilParams, err := proto.Marshal(keyNilParams) if err != nil { t.Errorf("proto.Marshal(keyNilParams) err = %v, want nil", err) } if _, err := keyManager.Primitive(serializedKeyNilParams); err == nil { t.Errorf("keyManager.Primitive(serializedKeyNilParams) err = nil, want non-nil") } } func TestAESGCMHKDFNewKeyMultipleTimes(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMHKDFTypeURL) if err != nil { t.Errorf("cannot obtain AES-GCM-HKDF key manager: %s", err) } format := testutil.NewAESGCMHKDFKeyFormat(32, 32, commonpb.HashType_SHA256, 4096) serializedFormat, err := proto.Marshal(format) if err != nil { t.Errorf("failed to marshal key: %s", err) } keys := make(map[string]struct{}) n := 26 for i := 0; i < n; i++ { key, err := keyManager.NewKey(serializedFormat) if err != nil { t.Fatalf("keyManager.NewKey() err = %q, want nil", err) } serializedKey, err := proto.Marshal(key) if err != nil { t.Errorf("failed to marshal key: %s", err) } keys[string(serializedKey)] = struct{}{} keyData, err := keyManager.NewKeyData(serializedFormat) if err != nil { t.Fatalf("keyManager.NewKeyData() err = %q, want nil", err) } serializedKey = keyData.Value keys[string(serializedKey)] = struct{}{} } if len(keys) != n*2 { t.Errorf("key is repeated") } } func TestAESGCMHKDFNewKeyBasic(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMHKDFTypeURL) if err != nil { t.Errorf("cannot obtain AES-GCM-HKDF key manager: %s", err) } for _, keySize := range aesGCMHKDFKeySizes { format := testutil.NewAESGCMHKDFKeyFormat( keySize, keySize, commonpb.HashType_SHA256, 4096, ) serializedFormat, err := proto.Marshal(format) if err != nil { t.Errorf("failed to marshal key: %s", err) } m, err := keyManager.NewKey(serializedFormat) if err != nil { t.Errorf("unexpected error: %s", err) } key := m.(*gcmhkdfpb.AesGcmHkdfStreamingKey) if err := validateAESGCMHKDFKey(key, format); err != nil { t.Errorf("%s", err) } } } func TestAESGCMHKDFNewKeyWithInvalidInput(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMHKDFTypeURL) if err != nil { t.Errorf("cannot obtain AES-GCM-HKDF key manager: %s", err) } // bad format badFormats := genInvalidAESGCMHKDFKeyFormats() for i := 0; i < len(badFormats); i++ { serializedFormat, err := proto.Marshal(badFormats[i]) if err != nil { t.Errorf("failed to marshal key: %s", err) } if _, err := keyManager.NewKey(serializedFormat); err == nil { t.Errorf("expect an error in test case %d", i) } } // nil if _, err := keyManager.NewKey(nil); err == nil { t.Errorf("expect an error when input is nil") } // empty array if _, err := keyManager.NewKey([]byte{}); err == nil { t.Errorf("expect an error when input is empty") } // params field is unset formatNilParams := testutil.NewAESGCMHKDFKeyFormat(32, 32, commonpb.HashType_SHA256, 4096) formatNilParams.Params = nil serializedFormatNilParams, err := proto.Marshal(formatNilParams) if err != nil { t.Errorf("proto.Marshal(formatNilParams) err = %v, want nil", err) } if _, err := keyManager.NewKey(serializedFormatNilParams); err == nil { t.Errorf("keyManager.NewKey(serializedFormatNilParams) err = nil, want non-nil") } } func TestAESGCMHKDFNewKeyDataBasic(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMHKDFTypeURL) if err != nil { t.Errorf("cannot obtain AES-GCM-HKDF key manager: %s", err) } for _, keySize := range aesGCMHKDFKeySizes { format := testutil.NewAESGCMHKDFKeyFormat( keySize, keySize, commonpb.HashType_SHA256, 4096, ) serializedFormat, err := proto.Marshal(format) if err != nil { t.Errorf("failed to marshal key: %s", err) } keyData, err := keyManager.NewKeyData(serializedFormat) if err != nil { t.Errorf("unexpected error: %s", err) } if keyData.TypeUrl != testutil.AESGCMHKDFTypeURL { t.Errorf("incorrect type url") } if keyData.KeyMaterialType != tinkpb.KeyData_SYMMETRIC { t.Errorf("incorrect key material type") } key := new(gcmhkdfpb.AesGcmHkdfStreamingKey) if err := proto.Unmarshal(keyData.Value, key); err != nil { t.Errorf("incorrect key value") } if err := validateAESGCMHKDFKey(key, format); err != nil { t.Errorf("%s", err) } p, err := registry.PrimitiveFromKeyData(keyData) if err != nil { t.Errorf("registry.PrimitiveFromKeyData(keyData) err = %v, want nil", err) } _, ok := p.(*subtle.AESGCMHKDF) if !ok { t.Error("registry.PrimitiveFromKeyData(keyData) did not return a AESGCMHKDF primitive") } } } func TestAESGCMHKDFNewKeyDataWithInvalidInput(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESGCMHKDFTypeURL) if err != nil { t.Errorf("cannot obtain AES-GCM-HKDF key manager: %s", err) } badFormats := genInvalidAESGCMHKDFKeyFormats() for i := 0; i < len(badFormats); i++ { serializedFormat, err := proto.Marshal(badFormats[i]) if err != nil { t.Errorf("failed to marshal key: %s", err) } if _, err := km.NewKeyData(serializedFormat); err == nil { t.Errorf("expect an error in test case %d", i) } } // nil input if _, err := km.NewKeyData(nil); err == nil { t.Errorf("expect an error when input is nil") } // empty input if _, err := km.NewKeyData([]byte{}); err == nil { t.Errorf("expect an error when input is empty") } } func TestAESGCMHKDFDoesSupport(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMHKDFTypeURL) if err != nil { t.Errorf("cannot obtain AES-GCM-HKDF key manager: %s", err) } if !keyManager.DoesSupport(testutil.AESGCMHKDFTypeURL) { t.Errorf("AESGCMHKDFKeyManager must support %s", testutil.AESGCMHKDFTypeURL) } if keyManager.DoesSupport("some bad type") { t.Errorf("AESGCMHKDFKeyManager must support only %s", testutil.AESGCMHKDFTypeURL) } } func TestAESGCMHKDFTypeURL(t *testing.T) { keyManager, err := registry.GetKeyManager(testutil.AESGCMHKDFTypeURL) if err != nil { t.Errorf("cannot obtain AES-GCM-HKDF key manager: %s", err) } if keyManager.TypeURL() != testutil.AESGCMHKDFTypeURL { t.Errorf("incorrect key type") } } func TestAESGCMHKDFKeyMaterialType(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESGCMHKDFTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.AESGCMHKDFTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } if got, want := keyManager.KeyMaterialType(), tinkpb.KeyData_SYMMETRIC; got != want { t.Errorf("KeyMaterialType() = %v, want %v", got, want) } } func TestAESGCMHKDFDeriveKey(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESGCMHKDFTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.AESGCMHKDFTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } for _, keySize := range []uint32{16, 32} { for _, derivedKeySize := range []uint32{16, 32} { keyFormat := &gcmhkdfpb.AesGcmHkdfStreamingKeyFormat{ Version: testutil.AESGCMHKDFKeyVersion, Params: &gcmhkdfpb.AesGcmHkdfStreamingParams{ CiphertextSegmentSize: derivedKeySize + subtle.AESGCMHKDFNoncePrefixSizeInBytes + subtle.AESGCMHKDFTagSizeInBytes + 2, DerivedKeySize: derivedKeySize, HkdfHashType: commonpb.HashType_SHA256, }, KeySize: keySize, } serializedKeyFormat, err := proto.Marshal(keyFormat) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", keyFormat, err) } rand := random.GetRandomBytes(keySize) buf := &bytes.Buffer{} buf.Write(rand) // never returns a non-nil error k, err := keyManager.DeriveKey(serializedKeyFormat, buf) if err != nil { t.Fatalf("keyManager.DeriveKey() err = %v, want nil", err) } key := k.(*gcmhkdfpb.AesGcmHkdfStreamingKey) if got, want := len(key.GetKeyValue()), int(keySize); got != want { t.Errorf("key length = %d, want %d", got, want) } if diff := cmp.Diff(key.GetKeyValue(), rand); diff != "" { t.Errorf("incorrect derived key: diff = %v", diff) } } } } func TestAESGCMHKDFDeriveKeyFailsWithInvalidKeyFormats(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESGCMHKDFTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.AESGCMHKDFTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } validKeyFormat := &gcmhkdfpb.AesGcmHkdfStreamingKeyFormat{ Version: testutil.AESGCMHKDFKeyVersion, Params: &gcmhkdfpb.AesGcmHkdfStreamingParams{ CiphertextSegmentSize: 16 + subtle.AESGCMHKDFNoncePrefixSizeInBytes + subtle.AESGCMHKDFTagSizeInBytes + 2, DerivedKeySize: 16, HkdfHashType: commonpb.HashType_SHA256, }, KeySize: 16, } serializedValidKeyFormat, err := proto.Marshal(validKeyFormat) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", validKeyFormat, err) } buf := bytes.NewBuffer(random.GetRandomBytes(validKeyFormat.KeySize)) if _, err := keyManager.DeriveKey(serializedValidKeyFormat, buf); err != nil { t.Fatalf("keyManager.DeriveKey() err = %v, want nil", err) } for _, test := range []struct { name string version uint32 keySize uint32 ciphertextSegmentSize uint32 derivedKeySize uint32 hkdfHashType commonpb.HashType }{ { name: "invalid version", version: 10, keySize: validKeyFormat.KeySize, ciphertextSegmentSize: validKeyFormat.Params.CiphertextSegmentSize, derivedKeySize: validKeyFormat.Params.DerivedKeySize, hkdfHashType: validKeyFormat.Params.HkdfHashType, }, { name: "invalid key size", version: validKeyFormat.Version, keySize: 10, ciphertextSegmentSize: validKeyFormat.Params.CiphertextSegmentSize, derivedKeySize: validKeyFormat.Params.DerivedKeySize, hkdfHashType: validKeyFormat.Params.HkdfHashType, }, { name: "invalid ciphertext segment size", version: validKeyFormat.Version, keySize: validKeyFormat.KeySize, ciphertextSegmentSize: 10, derivedKeySize: validKeyFormat.Params.DerivedKeySize, hkdfHashType: validKeyFormat.Params.HkdfHashType, }, { name: "invalid ciphertext segment size", version: validKeyFormat.Version, keySize: validKeyFormat.KeySize, ciphertextSegmentSize: 2147483648, derivedKeySize: validKeyFormat.Params.DerivedKeySize, hkdfHashType: validKeyFormat.Params.HkdfHashType, }, { name: "invalid derived key size", version: validKeyFormat.Version, keySize: validKeyFormat.KeySize, ciphertextSegmentSize: validKeyFormat.Params.CiphertextSegmentSize, derivedKeySize: 10, hkdfHashType: validKeyFormat.Params.HkdfHashType, }, { name: "invalid HKDF hash type", version: validKeyFormat.Version, keySize: validKeyFormat.KeySize, ciphertextSegmentSize: validKeyFormat.Params.CiphertextSegmentSize, derivedKeySize: validKeyFormat.Params.DerivedKeySize, hkdfHashType: commonpb.HashType_UNKNOWN_HASH, }, { name: "invalid HKDF hash type", version: validKeyFormat.Version, keySize: validKeyFormat.KeySize, ciphertextSegmentSize: validKeyFormat.Params.CiphertextSegmentSize, derivedKeySize: validKeyFormat.Params.DerivedKeySize, hkdfHashType: commonpb.HashType_SHA224, }, { name: "invalid HKDF hash type", version: validKeyFormat.Version, keySize: validKeyFormat.KeySize, ciphertextSegmentSize: validKeyFormat.Params.CiphertextSegmentSize, derivedKeySize: validKeyFormat.Params.DerivedKeySize, hkdfHashType: commonpb.HashType_SHA384, }, } { t.Run(test.name, func(t *testing.T) { keyFormat, err := proto.Marshal(&gcmhkdfpb.AesGcmHkdfStreamingKeyFormat{ Version: test.version, KeySize: test.keySize, Params: &gcmhkdfpb.AesGcmHkdfStreamingParams{ CiphertextSegmentSize: test.ciphertextSegmentSize, DerivedKeySize: test.derivedKeySize, HkdfHashType: test.hkdfHashType, }, }) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } buf := bytes.NewBuffer(random.GetRandomBytes(test.keySize)) if _, err := keyManager.DeriveKey(keyFormat, buf); err == nil { t.Errorf("keyManager.DeriveKey() err = nil, want non-nil") } }) } } func TestAESGCMHKDFDeriveKeyFailsWithMalformedKeyFormats(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESGCMHKDFTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.AESGCMHKDFTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } // Proto messages start with a VarInt, which always ends with a byte with the // MSB unset, so 0x80 is invalid. invalidSerialization, err := hex.DecodeString("80") if err != nil { t.Errorf("hex.DecodeString() err = %v, want nil", err) } for _, test := range []struct { name string keyFormat []byte }{ { name: "nil", keyFormat: nil, }, { name: "empty", keyFormat: []byte{}, }, { name: "invalid serialization", keyFormat: invalidSerialization, }, } { t.Run(test.name, func(t *testing.T) { buf := bytes.NewBuffer(random.GetRandomBytes(32)) if _, err := keyManager.DeriveKey(test.keyFormat, buf); err == nil { t.Errorf("keyManager.DeriveKey() err = nil, want non-nil") } }) } } func TestAESGCMHKDFDeriveKeyFailsWithInsufficientRandomness(t *testing.T) { km, err := registry.GetKeyManager(testutil.AESGCMHKDFTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testutil.AESGCMHKDFTypeURL, err) } keyManager, ok := km.(internalregistry.DerivableKeyManager) if !ok { t.Fatalf("key manager is not DerivableKeyManager") } keyFormat, err := proto.Marshal(&gcmhkdfpb.AesGcmHkdfStreamingKeyFormat{ Version: testutil.AESGCMHKDFKeyVersion, Params: &gcmhkdfpb.AesGcmHkdfStreamingParams{ CiphertextSegmentSize: 16 + subtle.AESGCMHKDFNoncePrefixSizeInBytes + subtle.AESGCMHKDFTagSizeInBytes + 2, DerivedKeySize: 16, HkdfHashType: commonpb.HashType_SHA256, }, KeySize: 16, }) if err != nil { t.Fatalf("proto.Marshal(%v) err = %v, want nil", keyFormat, err) } { buf := bytes.NewBuffer(random.GetRandomBytes(16)) if _, err := keyManager.DeriveKey(keyFormat, buf); err != nil { t.Errorf("keyManager.DeriveKey() err = %v, want nil", err) } } { insufficientBuf := bytes.NewBuffer(random.GetRandomBytes(15)) if _, err := keyManager.DeriveKey(keyFormat, insufficientBuf); err == nil { t.Errorf("keyManager.DeriveKey() err = nil, want non-nil") } } } func genInvalidAESGCMHKDFKeys() []proto.Message { return []proto.Message{ // not a AESGCMHKDFKey testutil.NewAESGCMHKDFKeyFormat(32, 32, commonpb.HashType_SHA256, 4096), // bad key size testutil.NewAESGCMHKDFKey(testutil.AESGCMKeyVersion, 17, 16, commonpb.HashType_SHA256, 4096), testutil.NewAESGCMHKDFKey(testutil.AESGCMKeyVersion, 16, 17, commonpb.HashType_SHA256, 4096), testutil.NewAESGCMHKDFKey(testutil.AESGCMKeyVersion, 33, 33, commonpb.HashType_SHA256, 4096), // bad version testutil.NewAESGCMHKDFKey(testutil.AESGCMKeyVersion+1, 16, 16, commonpb.HashType_SHA256, 4096), } } func genInvalidAESGCMHKDFKeyFormats() []proto.Message { return []proto.Message{ // not AESGCMKeyFormat testutil.NewAESGCMHKDFKey(testutil.AESGCMKeyVersion, 16, 16, commonpb.HashType_SHA256, 16), // invalid key size testutil.NewAESGCMHKDFKeyFormat(17, 16, commonpb.HashType_SHA256, 4096), testutil.NewAESGCMHKDFKeyFormat(16, 17, commonpb.HashType_SHA256, 4096), testutil.NewAESGCMHKDFKeyFormat(33, 33, commonpb.HashType_SHA256, 4096), } } func validateAESGCMHKDFKey(key *gcmhkdfpb.AesGcmHkdfStreamingKey, format *gcmhkdfpb.AesGcmHkdfStreamingKeyFormat) error { if uint32(len(key.KeyValue)) != format.KeySize { return fmt.Errorf("incorrect key size") } if key.Version != testutil.AESGCMKeyVersion { return fmt.Errorf("incorrect key version") } if key.Params.CiphertextSegmentSize != format.Params.CiphertextSegmentSize { return fmt.Errorf("incorrect ciphertext segment size") } if key.Params.DerivedKeySize != format.Params.DerivedKeySize { return fmt.Errorf("incorrect derived key size") } if key.Params.HkdfHashType != format.Params.HkdfHashType { return fmt.Errorf("incorrect HKDF hash type") } // try to encrypt and decrypt p, err := subtle.NewAESGCMHKDF( key.KeyValue, key.Params.HkdfHashType.String(), int(key.Params.DerivedKeySize), int(key.Params.CiphertextSegmentSize), 0, ) if err != nil { return fmt.Errorf("invalid key") } return validatePrimitive(p, key) } func validatePrimitive(p any, key *gcmhkdfpb.AesGcmHkdfStreamingKey) error { cipher := p.(*subtle.AESGCMHKDF) return encryptDecrypt(cipher, cipher, 32, 32) } ================================================ FILE: go/streamingaead/decrypt_reader.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package streamingaead import ( "errors" "io" "github.com/google/tink/go/tink" ) var ( _ io.Reader = &decryptReader{} errKeyNotFound = errors.New("no matching key found for the ciphertext in the stream") ) // decryptReader is a reader that tries to find the right key to decrypt ciphertext from the given primitive set. type decryptReader struct { wrapped *wrappedStreamingAEAD // cr is a source Reader which provides ciphertext to be decrypted. cr io.Reader aad []byte matchAttempted bool // mr is a matched decrypting reader initialized with a proper key to decrypt ciphertext. mr io.Reader } func (dr *decryptReader) Read(p []byte) (n int, err error) { if dr.mr != nil { return dr.mr.Read(p) } if dr.matchAttempted { return 0, errKeyNotFound } dr.matchAttempted = true ur := &unreader{r: dr.cr} // find proper key to decrypt ciphertext // // For legacy reasons (Tink always encrypted with non-RAW keys) we use all // primitives, even those which have output_prefix_type != RAW. for _, e := range dr.wrapped.ps.EntriesInKeysetOrder { sa, ok := e.Primitive.(tink.StreamingAEAD) if !ok { continue } read := func() (io.Reader, int, error) { r, err := sa.NewDecryptingReader(ur, dr.aad) if err != nil { return nil, 0, err } n, err := r.Read(p) if err != nil { return nil, 0, err } return r, n, nil } r, n, err := read() if err == nil { dr.mr = r ur.disable() return n, nil } ur.unread() } return 0, errKeyNotFound } // unreader wraps a reader and keeps a copy of everything that's read so it can // be unread and read again. When no additional unreads are needed, the buffer // can be disabled and the memory released. type unreader struct { r io.Reader buf []byte pos int disabled bool } func (u *unreader) Read(buf []byte) (int, error) { if len(u.buf) != u.pos { n := copy(buf, u.buf[u.pos:]) u.pos += n return n, nil } n, err := u.r.Read(buf) if u.disabled { u.buf = nil u.pos = 0 } else { u.buf = append(u.buf, buf[:n]...) u.pos = len(u.buf) } return n, err } // unread starts the reader over again. A copy of all read data will be returned // by `Read()` before the wrapped reader is read from again. func (u *unreader) unread() { u.pos = 0 } // disable ensures the buffer is released for garbage collection once it's no // longer needed. func (u *unreader) disable() { u.disabled = true } ================================================ FILE: go/streamingaead/decrypt_reader_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package streamingaead import ( "bytes" "crypto/rand" "fmt" "io" "strings" "testing" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testkeyset" "github.com/google/tink/go/testutil" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func BenchmarkDecryptReader(b *testing.B) { b.ReportAllocs() // Create a Streaming AEAD primitive using a full keyset. decKeyset := testutil.NewTestAESGCMHKDFKeyset() decKeysetHandle, err := testkeyset.NewHandle(decKeyset) if err != nil { b.Fatalf("Failed creating keyset handle: %v", err) } decCipher, err := New(decKeysetHandle) if err != nil { b.Errorf("streamingaead.New failed: %v", err) } // Extract the raw key from the keyset and create a Streaming AEAD primitive // using only that key. // // testutil.NewTestAESGCMHKDFKeyset() places a raw key at position 1. rawKey := decKeyset.Key[1] if rawKey.OutputPrefixType != tinkpb.OutputPrefixType_RAW { b.Fatalf("Expected a raw key.") } encKeyset := testutil.NewKeyset(rawKey.KeyId, []*tinkpb.Keyset_Key{rawKey}) encKeysetHandle, err := testkeyset.NewHandle(encKeyset) if err != nil { b.Fatalf("Failed creating keyset handle: %v", err) } encCipher, err := New(encKeysetHandle) if err != nil { b.Fatalf("streamingaead.New failed: %v", err) } plaintext := random.GetRandomBytes(8) associatedData := random.GetRandomBytes(32) b.ResetTimer() for i := 0; i < b.N; i++ { // Create a pipe for communication between the encrypting writer and // decrypting reader. r, w := io.Pipe() defer r.Close() // Repeatedly encrypt the plaintext and write the ciphertext to a pipe. go func() { const writeAtLeast = 1 << 30 // 1 GiB enc, err := encCipher.NewEncryptingWriter(w, associatedData) if err != nil { b.Errorf("Cannot create encrypt writer: %v", err) return } for i := 0; i < writeAtLeast; i += len(plaintext) { if _, err := enc.Write(plaintext); err != nil { b.Errorf("Error encrypting data: %v", err) return } } if err := enc.Close(); err != nil { b.Errorf("Error closing encrypting writer: %v", err) return } if err := w.Close(); err != nil { b.Errorf("Error closing pipe: %v", err) return } }() // Decrypt the ciphertext in small chunks. dec, err := decCipher.NewDecryptingReader(r, associatedData) if err != nil { b.Fatalf("Cannot create decrypt reader: %v", err) } buf := make([]byte, 16384) // 16 KiB for { _, err := dec.Read(buf) if err == io.EOF { break } if err != nil { b.Fatalf("Error decrypting data: %v", err) } } } } func TestUnreaderUnread(t *testing.T) { original := make([]byte, 4096) if _, err := io.ReadFull(rand.Reader, original); err != nil { t.Fatalf("Failed to fill buffer with random bytes: %v", err) } u := &unreader{r: bytes.NewReader(original)} got, err := io.ReadAll(u) if err != nil { t.Errorf("First io.ReadAll(%T) failed unexpectedly: %v", u, err) } if !bytes.Equal(got, original) { t.Errorf("First io.ReadAll(%T) got %d bytes, want %d bytes that match the original random data.\nGot: %X\nWant: %X", u, len(got), len(original), got, original) } u.unread() got, err = io.ReadAll(u) if err != nil { t.Errorf("After %T.unread(), io.ReadAll(%T) failed unexpectedly: %v", u, u, err) } if !bytes.Equal(got, original) { t.Errorf("After %T.unread(), io.ReadAll(%T) got %d bytes, want %d bytes that match the original random data.\nGot: %X\nWant: %X", u, u, len(got), len(original), got, original) } } func TestUnreader(t *testing.T) { // Repeating sequence of characters '0' through '9' makes it easy to see // holes or repeated data. original := make([]byte, 100) for i := range original { original[i] = '0' + byte(i%10) } type step struct { read int // If set, read the given number of bytes exactly. unread bool // If true, call unread(). disable bool // If true, call disable(). } tcs := []struct { name string steps []step }{ {"Read2UnreadRead4Unread", []step{{read: 2}, {unread: true}, {read: 4}, {unread: true}}}, {"Read4UnreadRead2Unread", []step{{read: 4}, {unread: true}, {read: 2}, {unread: true}}}, {"Read3UnreadRead3Unread", []step{{read: 3}, {unread: true}, {read: 3}, {unread: true}}}, {"Read3Disable", []step{{read: 3}, {disable: true}}}, {"Read2UnreadRead4Disable", []step{{read: 2}, {unread: true}, {read: 4}, {disable: true}}}, {"Read4UnreadRead2Disable", []step{{read: 4}, {unread: true}, {read: 2}, {disable: true}}}, {"Read3UnreadRead3Disable", []step{{read: 3}, {unread: true}, {read: 3}, {disable: true}}}, {"Read2UnreadDisable", []step{{read: 2}, {unread: true}, {disable: true}}}, {"Read4UnreadDisable", []step{{read: 4}, {unread: true}, {disable: true}}}, {"ReadAllUnread", []step{{read: len(original)}, {unread: true}}}, {"ReadAllDisable", []step{{read: len(original)}, {disable: true}}}, {"Unread", []step{{unread: true}}}, {"Disable", []step{{disable: true}}}, {"UnreadDisable", []step{{unread: true}, {disable: true}}}, } for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { u := &unreader{r: bytes.NewReader(original)} var ( after []string pos int ) // Explains what happened before the failure. prefix := func() string { if after == nil { return "" } return fmt.Sprintf("After %s, ", strings.Join(after, "+")) } for _, s := range tc.steps { if s.read != 0 { buf := make([]byte, s.read) if _, err := io.ReadFull(u, buf); err != nil { t.Fatalf("%sio.ReadFull(%T, %d byte buffer) failed unexpectedly: %v", prefix(), u, s.read, err) } if want := original[pos : pos+s.read]; !bytes.Equal(buf, want) { t.Fatalf("%sio.ReadFull(%T, %d byte buffer) got %q, want %q", prefix(), u, s.read, buf, want) } after = append(after, fmt.Sprintf("Read(%d bytes)", s.read)) pos += s.read } if s.disable { u.disable() after = append(after, "disable()") } if s.unread { u.unread() after = append(after, "unread()") pos = 0 } } got, err := io.ReadAll(u) if err != nil { t.Fatalf("%sio.ReadAll(%T) failed unexpectedly: %v", prefix(), u, err) } if want := original[pos:]; !bytes.Equal(want, got) { t.Errorf("%sio.ReadAll(%T) got %q, want %q", prefix(), u, got, want) } }) } } ================================================ FILE: go/streamingaead/streamingaead.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package streamingaead provides implementations of the streaming AEAD primitive. // // AEAD encryption assures the confidentiality and authenticity of the data. // This primitive is CPA secure. package streamingaead import ( "fmt" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/internal/internalregistry" ) func init() { if err := registry.RegisterKeyManager(new(aesGCMHKDFKeyManager)); err != nil { panic(fmt.Sprintf("streamingaead.init() failed: %v", err)) } if err := internalregistry.AllowKeyDerivation(aesGCMHKDFTypeURL); err != nil { panic(fmt.Sprintf("streamingaead.init() failed: %v", err)) } if err := registry.RegisterKeyManager(new(aesCTRHMACKeyManager)); err != nil { panic(fmt.Sprintf("streamingaead.init() failed: %v", err)) } } ================================================ FILE: go/streamingaead/streamingaead_factory.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package streamingaead import ( "fmt" "io" "github.com/google/tink/go/core/primitiveset" "github.com/google/tink/go/keyset" "github.com/google/tink/go/tink" ) // New returns a StreamingAEAD primitive from the given keyset handle. func New(handle *keyset.Handle) (tink.StreamingAEAD, error) { ps, err := handle.Primitives() if err != nil { return nil, fmt.Errorf("streamingaead_factory: cannot obtain primitive set: %s", err) } _, ok := (ps.Primary.Primitive).(tink.StreamingAEAD) if !ok { return nil, fmt.Errorf("streamingaead_factory: not a StreamingAEAD primitive") } for _, primitives := range ps.Entries { for _, p := range primitives { if _, ok := (p.Primitive).(tink.StreamingAEAD); !ok { return nil, fmt.Errorf("streamingaead_factory: not a StreamingAEAD primitive") } } } ret := new(wrappedStreamingAEAD) ret.ps = ps return tink.StreamingAEAD(ret), nil } // wrappedStreamingAEAD is a StreamingAEAD implementation that uses the underlying primitive set // for streaming encryption and decryption. type wrappedStreamingAEAD struct { ps *primitiveset.PrimitiveSet } // Asserts that wrappedStreamingAEAD implements the StreamingAEAD interface. var _ tink.StreamingAEAD = (*wrappedStreamingAEAD)(nil) // NewEncryptingWriter returns a wrapper around underlying io.Writer, such that any write-operation // via the wrapper results in AEAD-encryption of the written data, using aad // as associated authenticated data. The associated data is not included in the ciphertext // and has to be passed in as parameter for decryption. func (s *wrappedStreamingAEAD) NewEncryptingWriter(w io.Writer, aad []byte) (io.WriteCloser, error) { primary := s.ps.Primary p, ok := (primary.Primitive).(tink.StreamingAEAD) if !ok { return nil, fmt.Errorf("streamingaead_factory: not a StreamingAEAD primitive") } return p.NewEncryptingWriter(w, aad) } // NewDecryptingReader returns a wrapper around underlying io.Reader, such that any read-operation // via the wrapper results in AEAD-decryption of the underlying ciphertext, // using aad as associated authenticated data. func (s *wrappedStreamingAEAD) NewDecryptingReader(r io.Reader, aad []byte) (io.Reader, error) { return &decryptReader{ wrapped: s, cr: r, aad: aad, }, nil } ================================================ FILE: go/streamingaead/streamingaead_factory_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package streamingaead_test import ( "bytes" "fmt" "io" "strings" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/keyset" "github.com/google/tink/go/mac" "github.com/google/tink/go/streamingaead" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testkeyset" "github.com/google/tink/go/testutil" "github.com/google/tink/go/tink" ghpb "github.com/google/tink/go/proto/aes_gcm_hkdf_streaming_go_proto" commonpb "github.com/google/tink/go/proto/common_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( aesGCMHKDFTypeURL = "type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey" ) func TestFactoryMultipleKeys(t *testing.T) { keyset := testutil.NewTestAESGCMHKDFKeyset() keysetHandle, err := testkeyset.NewHandle(keyset) if err != nil { t.Fatal(err) } a, err := streamingaead.New(keysetHandle) if err != nil { t.Errorf("streamingaead.New failed: %s", err) } t.Run("Encrypt with a primary RAW key and decrypt with the keyset", func(t *testing.T) { if err := validateFactoryCipher(a, a); err != nil { t.Errorf("invalid cipher: %s", err) } }) t.Run("Encrypt with a non-primary RAW key and decrypt with the keyset", func(t *testing.T) { rawKey := keyset.Key[1] if rawKey.OutputPrefixType != tinkpb.OutputPrefixType_RAW { t.Errorf("expect a raw key") } keyset2 := testutil.NewKeyset(rawKey.KeyId, []*tinkpb.Keyset_Key{rawKey}) keysetHandle2, err := testkeyset.NewHandle(keyset2) if err != nil { t.Fatalf("testkeyset.NewHandle(keyset2) err = %q, want nil", err) } a2, err := streamingaead.New(keysetHandle2) if err != nil { t.Errorf("streamingaead.New failed: %s", err) } if err := validateFactoryCipher(a2, a); err != nil { t.Errorf("invalid cipher: %s", err) } }) t.Run("Encrypt with a random key not in the keyset, decrypt with the keyset should fail", func(t *testing.T) { keyset2 := testutil.NewTestAESGCMHKDFKeyset() keysetHandle2, err := testkeyset.NewHandle(keyset2) if err != nil { t.Fatalf("testkeyset.NewHandle(keyset2) err = %q, want nil", err) } a2, err := streamingaead.New(keysetHandle2) if err != nil { t.Errorf("streamingaead.New failed: %s", err) } err = validateFactoryCipher(a2, a) if err == nil || !strings.Contains(err.Error(), "decryption failed") { t.Errorf("expect decryption to fail with random key: %s", err) } }) } func validateFactoryCipher(encryptCipher tink.StreamingAEAD, decryptCipher tink.StreamingAEAD) error { tt := []int{1, 16, 4095, 4096, 4097, 16384} for _, t := range tt { if err := encryptDecrypt(encryptCipher, decryptCipher, t, 32); err != nil { return fmt.Errorf("failed plaintext-size=%d: %s", t, err) } } return nil } func encryptDecrypt(encryptCipher, decryptCipher tink.StreamingAEAD, ptSize, aadSize int) error { pt := random.GetRandomBytes(uint32(ptSize)) aad := random.GetRandomBytes(uint32(aadSize)) buf := &bytes.Buffer{} w, err := encryptCipher.NewEncryptingWriter(buf, aad) if err != nil { return fmt.Errorf("cannot create encrypt writer: %v", err) } if _, err := w.Write(pt); err != nil { return fmt.Errorf("error writing data: %v", err) } if err := w.Close(); err != nil { return fmt.Errorf("error closing writer: %v", err) } r, err := decryptCipher.NewDecryptingReader(buf, aad) if err != nil { return fmt.Errorf("cannot create decrypt reader: %v", err) } ptGot := make([]byte, len(pt)+1) n, err := io.ReadFull(r, ptGot) if err != nil && err != io.ErrUnexpectedEOF { return fmt.Errorf("decryption failed: %v", err) } ptGot = ptGot[:n] if !bytes.Equal(pt, ptGot) { return fmt.Errorf("decryption failed") } return nil } func TestFactoryWithInvalidPrimitiveSetType(t *testing.T) { wrongKH, err := keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate()) if err != nil { t.Fatalf("failed to build *keyset.Handle: %s", err) } _, err = streamingaead.New(wrongKH) if err == nil { t.Fatal("New() should fail with wrong *keyset.Handle") } } func TestFactoryWithValidPrimitiveSetType(t *testing.T) { goodKH, err := keyset.NewHandle(streamingaead.AES128GCMHKDF4KBKeyTemplate()) if err != nil { t.Fatalf("failed to build *keyset.Handle: %s", err) } _, err = streamingaead.New(goodKH) if err != nil { t.Fatalf("New() failed with good *keyset.Handle: %s", err) } } func TestFactoryWithKeysetWithTinkKeys(t *testing.T) { key := &ghpb.AesGcmHkdfStreamingKey{ Version: 0, KeyValue: []byte("0123456789abcdef"), Params: &ghpb.AesGcmHkdfStreamingParams{ CiphertextSegmentSize: 512, DerivedKeySize: 16, HkdfHashType: commonpb.HashType_SHA1, }, } value1, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal(key) err = %q, want nil", err) } key.KeyValue = []byte("ABCDEF0123456789") value2, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal(key) err = %q, want nil", err) } keyset := &tinkpb.Keyset{ PrimaryKeyId: 1, Key: []*tinkpb.Keyset_Key{{ KeyData: &tinkpb.KeyData{ TypeUrl: aesGCMHKDFTypeURL, Value: value1, KeyMaterialType: tinkpb.KeyData_SYMMETRIC, }, OutputPrefixType: tinkpb.OutputPrefixType_TINK, KeyId: 1, Status: tinkpb.KeyStatusType_ENABLED, }, &tinkpb.Keyset_Key{ KeyData: &tinkpb.KeyData{ TypeUrl: aesGCMHKDFTypeURL, Value: value2, KeyMaterialType: tinkpb.KeyData_SYMMETRIC, }, OutputPrefixType: tinkpb.OutputPrefixType_RAW, KeyId: 2, Status: tinkpb.KeyStatusType_ENABLED, }}, } keysetHandle, err := testkeyset.NewHandle(keyset) if err != nil { t.Fatalf("testkeyset.NewHandle(keyset) err = %q, want nil", err) } a, err := streamingaead.New(keysetHandle) if err != nil { t.Errorf("streamingaead.New(keysetHandle) err = %q, want nil", err) } if err := validateFactoryCipher(a, a); err != nil { t.Errorf("Encryption & Decryption with TINK key should succeed") } } ================================================ FILE: go/streamingaead/streamingaead_key_templates.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package streamingaead import ( "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/internal/tinkerror" ctrhmacpb "github.com/google/tink/go/proto/aes_ctr_hmac_streaming_go_proto" gcmhkdfpb "github.com/google/tink/go/proto/aes_gcm_hkdf_streaming_go_proto" commonpb "github.com/google/tink/go/proto/common_go_proto" hmacpb "github.com/google/tink/go/proto/hmac_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // This file contains pre-generated KeyTemplates for streaming AEAD keys. One can use these templates // to generate new Keysets. // AES128GCMHKDF4KBKeyTemplate is a KeyTemplate that generates an AES-GCM key with the following parameters: // - Main key size: 16 bytes // - HKDF algo: HMAC-SHA256 // - Size of AES-GCM derived keys: 16 bytes // - Ciphertext segment size: 4096 bytes func AES128GCMHKDF4KBKeyTemplate() *tinkpb.KeyTemplate { return newAESGCMHKDFKeyTemplate(16, commonpb.HashType_SHA256, 16, 4096) } // AES128GCMHKDF1MBKeyTemplate is a KeyTemplate that generates an AES-GCM key with the following parameters: // - Main key size: 16 bytes // - HKDF algo: HMAC-SHA256 // - Size of AES-GCM derived keys: 16 bytes // - Ciphertext segment size: 1048576 bytes (1 MB) func AES128GCMHKDF1MBKeyTemplate() *tinkpb.KeyTemplate { return newAESGCMHKDFKeyTemplate(16, commonpb.HashType_SHA256, 16, 1048576) } // AES256GCMHKDF4KBKeyTemplate is a KeyTemplate that generates an AES-GCM key with the following parameters: // - Main key size: 32 bytes // - HKDF algo: HMAC-SHA256 // - Size of AES-GCM derived keys: 32 bytes // - Ciphertext segment size: 4096 bytes func AES256GCMHKDF4KBKeyTemplate() *tinkpb.KeyTemplate { return newAESGCMHKDFKeyTemplate(32, commonpb.HashType_SHA256, 32, 4096) } // AES256GCMHKDF1MBKeyTemplate is a KeyTemplate that generates an AES-GCM key with the following parameters: // - Main key size: 32 bytes // - HKDF algo: HMAC-SHA256 // - Size of AES-GCM derived keys: 32 bytes // - Ciphertext segment size: 1048576 bytes (1 MB) func AES256GCMHKDF1MBKeyTemplate() *tinkpb.KeyTemplate { return newAESGCMHKDFKeyTemplate(32, commonpb.HashType_SHA256, 32, 1048576) } // AES128CTRHMACSHA256Segment4KBKeyTemplate is a KeyTemplate that generates an // AES-CTR-HMAC key with the following parameters: // - Main key size: 16 bytes // - HKDF algorthim: HMAC-SHA256 // - AES-CTR derived key size: 16 bytes // - Tag algorithm: HMAC-SHA256 // - Tag size: 32 bytes // - Ciphertext segment size: 4096 bytes (4 KB) func AES128CTRHMACSHA256Segment4KBKeyTemplate() *tinkpb.KeyTemplate { return newAESCTRHMACKeyTemplate(16, commonpb.HashType_SHA256, 16, commonpb.HashType_SHA256, 32, 4096) } // AES128CTRHMACSHA256Segment1MBKeyTemplate is a KeyTemplate that generates an // AES-CTR-HMAC key with the following parameters: // - Main key size: 16 bytes // - HKDF algorthim: HMAC-SHA256 // - AES-CTR derived key size: 16 bytes // - Tag algorithm: HMAC-SHA256 // - Tag size: 32 bytes // - Ciphertext segment size: 1048576 bytes (1 MB) func AES128CTRHMACSHA256Segment1MBKeyTemplate() *tinkpb.KeyTemplate { return newAESCTRHMACKeyTemplate(16, commonpb.HashType_SHA256, 16, commonpb.HashType_SHA256, 32, 1048576) } // AES256CTRHMACSHA256Segment4KBKeyTemplate is a KeyTemplate that generates an // AES-CTR-HMAC key with the following parameters: // - Main key size: 32 bytes // - HKDF algorthim: HMAC-SHA256 // - AES-CTR derived key size: 32 bytes // - Tag algorithm: HMAC-SHA256 // - Tag size: 32 bytes // - Ciphertext segment size: 4096 bytes (4 KB) func AES256CTRHMACSHA256Segment4KBKeyTemplate() *tinkpb.KeyTemplate { return newAESCTRHMACKeyTemplate(32, commonpb.HashType_SHA256, 32, commonpb.HashType_SHA256, 32, 4096) } // AES256CTRHMACSHA256Segment1MBKeyTemplate is a KeyTemplate that generates an // AES-CTR-HMAC key with the following parameters: // - Main key size: 32 bytes // - HKDF algorthim: HMAC-SHA256 // - AES-CTR derived key size: 32 bytes // - Tag algorithm: HMAC-SHA256 // - Tag size: 32 bytes // - Ciphertext segment size: 1048576 bytes (1 MB) func AES256CTRHMACSHA256Segment1MBKeyTemplate() *tinkpb.KeyTemplate { return newAESCTRHMACKeyTemplate(32, commonpb.HashType_SHA256, 32, commonpb.HashType_SHA256, 32, 1048576) } // newAESGCMHKDFKeyTemplate creates a KeyTemplate containing a AesGcmHkdfStreamingKeyFormat with // specified parameters. func newAESGCMHKDFKeyTemplate(mainKeySize uint32, hkdfHashType commonpb.HashType, derivedKeySize, ciphertextSegmentSize uint32) *tinkpb.KeyTemplate { serializedFormat, err := proto.Marshal(&gcmhkdfpb.AesGcmHkdfStreamingKeyFormat{ KeySize: mainKeySize, Params: &gcmhkdfpb.AesGcmHkdfStreamingParams{ CiphertextSegmentSize: ciphertextSegmentSize, DerivedKeySize: derivedKeySize, HkdfHashType: hkdfHashType, }, }) if err != nil { tinkerror.Fail(fmt.Sprintf("failed to marshal key: %s", err)) } return &tinkpb.KeyTemplate{ TypeUrl: aesGCMHKDFTypeURL, Value: serializedFormat, OutputPrefixType: tinkpb.OutputPrefixType_RAW, } } // newAESCTRHMACKeyTemplate creates a KeyTemplate containing a // AesCtrHmacStreamingKeyFormat with the specified parameters. func newAESCTRHMACKeyTemplate(mainKeySize uint32, hkdfHashType commonpb.HashType, derivedKeySize uint32, tagAlg commonpb.HashType, tagSize, ciphertextSegmentSize uint32) *tinkpb.KeyTemplate { serializedFormat, err := proto.Marshal(&ctrhmacpb.AesCtrHmacStreamingKeyFormat{ KeySize: mainKeySize, Params: &ctrhmacpb.AesCtrHmacStreamingParams{ CiphertextSegmentSize: ciphertextSegmentSize, DerivedKeySize: derivedKeySize, HkdfHashType: hkdfHashType, HmacParams: &hmacpb.HmacParams{ Hash: tagAlg, TagSize: tagSize, }, }, }) if err != nil { tinkerror.Fail(fmt.Sprintf("failed to marshal key: %s", err)) } return &tinkpb.KeyTemplate{ TypeUrl: aesCTRHMACTypeURL, Value: serializedFormat, OutputPrefixType: tinkpb.OutputPrefixType_RAW, } } ================================================ FILE: go/streamingaead/streamingaead_key_templates_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package streamingaead_test import ( "bytes" "io" "testing" "github.com/google/tink/go/keyset" "github.com/google/tink/go/streamingaead" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestKeyTemplates(t *testing.T) { var testCases = []struct { name string template *tinkpb.KeyTemplate }{ { name: "AES128_GCM_HKDF_4KB", template: streamingaead.AES128GCMHKDF4KBKeyTemplate(), }, { name: "AES128_GCM_HKDF_1MB", template: streamingaead.AES128GCMHKDF1MBKeyTemplate(), }, { name: "AES256_GCM_HKDF_4KB", template: streamingaead.AES256GCMHKDF4KBKeyTemplate(), }, { name: "AES256_GCM_HKDF_1MB", template: streamingaead.AES256GCMHKDF1MBKeyTemplate(), }, { name: "AES128_CTR_HMAC_SHA256_4KB", template: streamingaead.AES128CTRHMACSHA256Segment4KBKeyTemplate(), }, { name: "AES128_CTR_HMAC_SHA256_1MB", template: streamingaead.AES128CTRHMACSHA256Segment1MBKeyTemplate(), }, { name: "AES256_CTR_HMAC_SHA256_4KB", template: streamingaead.AES256CTRHMACSHA256Segment4KBKeyTemplate(), }, { name: "AES256_CTR_HMAC_SHA256_1MB", template: streamingaead.AES256CTRHMACSHA256Segment1MBKeyTemplate(), }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { handle, err := keyset.NewHandle(tc.template) if err != nil { t.Fatalf("keyset.NewHandle(template) failed: %v", err) } primitive, err := streamingaead.New(handle) if err != nil { t.Fatalf("aead.New(handle) failed: %v", err) } plaintext := []byte("some data to encrypt") aad := []byte("extra data to authenticate") buf := &bytes.Buffer{} w, err := primitive.NewEncryptingWriter(buf, aad) if err != nil { t.Fatalf("primitive.NewEncryptingWriter(buf, aad) failed: %v", err) } if _, err := w.Write(plaintext); err != nil { t.Fatalf("w.Write(plaintext) failed: %v", err) } if err := w.Close(); err != nil { t.Fatalf("w.Close() failed: %v", err) } r, err := primitive.NewDecryptingReader(buf, aad) if err != nil { t.Fatalf("primitive.NewDecryptingReader(buf, aad) failed: %v", err) } decrypted, err := io.ReadAll(r) if err != nil { t.Fatalf("io.ReadAll(r) failed: %v", err) } if !bytes.Equal(decrypted, plaintext) { t.Errorf("decrypted data doesn't match plaintext, got: %q, want: ''", decrypted) } }) } } ================================================ FILE: go/streamingaead/streamingaead_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package streamingaead_test // [START streaming-aead-example] import ( "bytes" "fmt" "io" "log" "os" "path/filepath" "github.com/google/tink/go/insecurecleartextkeyset" "github.com/google/tink/go/keyset" "github.com/google/tink/go/streamingaead" ) func Example() { // A keyset created with "tinkey create-keyset --key-template=AES256_CTR_HMAC_SHA256_1MB". Note // that this keyset has the secret key information in cleartext. jsonKeyset := `{ "primaryKeyId": 1720777699, "key": [{ "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.AesCtrHmacStreamingKey", "keyMaterialType": "SYMMETRIC", "value": "Eg0IgCAQIBgDIgQIAxAgGiDtesd/4gCnQdTrh+AXodwpm2b6BFJkp043n+8mqx0YGw==" }, "outputPrefixType": "RAW", "keyId": 1720777699, "status": "ENABLED" }] }` // Create a keyset handle from the cleartext keyset in the previous // step. The keyset handle provides abstract access to the underlying keyset to // limit the exposure of accessing the raw key material. WARNING: In practice, // it is unlikely you will want to use an insecurecleartextkeyset, as it implies // that your key material is passed in cleartext, which is a security risk. // Consider encrypting it with a remote key in Cloud KMS, AWS KMS or HashiCorp Vault. // See https://github.com/google/tink/blob/master/docs/GOLANG-HOWTO.md#storing-and-loading-existing-keysets. keysetHandle, err := insecurecleartextkeyset.Read( keyset.NewJSONReader(bytes.NewBufferString(jsonKeyset))) if err != nil { log.Fatal(err) } // Retrieve the StreamingAEAD primitive we want to use from the keyset handle. primitive, err := streamingaead.New(keysetHandle) if err != nil { log.Fatal(err) } // Create a file with the plaintext. dir, err := os.MkdirTemp("", "streamingaead") if err != nil { log.Fatal(err) } defer os.RemoveAll(dir) plaintextPath := filepath.Join(dir, "plaintext") if err := os.WriteFile(plaintextPath, []byte("this data needs to be encrypted"), 0666); err != nil { log.Fatal(err) } plaintextFile, err := os.Open(plaintextPath) if err != nil { log.Fatal(err) } // associatedData defines the context of the encryption. Here, we include the path of the // plaintext file. associatedData := []byte("associatedData for " + plaintextPath) // Encrypt the plaintext file and write the output to the ciphertext file. In this case the // primary key of the keyset will be used (which is also the only key in this example). ciphertextPath := filepath.Join(dir, "ciphertext") ciphertextFile, err := os.Create(ciphertextPath) if err != nil { log.Fatal(err) } w, err := primitive.NewEncryptingWriter(ciphertextFile, associatedData) if err != nil { log.Fatal(err) } if _, err := io.Copy(w, plaintextFile); err != nil { log.Fatal(err) } if err := w.Close(); err != nil { log.Fatal(err) } if err := ciphertextFile.Close(); err != nil { log.Fatal(err) } if err := plaintextFile.Close(); err != nil { log.Fatal(err) } // Decrypt the ciphertext file and write the output to the decrypted file. The // decryption finds the correct key in the keyset and decrypts the ciphertext. // If no key is found or decryption fails, it returns an error. ciphertextFile, err = os.Open(ciphertextPath) if err != nil { log.Fatal(err) } decryptedPath := filepath.Join(dir, "decrypted") decryptedFile, err := os.Create(decryptedPath) if err != nil { log.Fatal(err) } r, err := primitive.NewDecryptingReader(ciphertextFile, associatedData) if err != nil { log.Fatal(err) } if _, err := io.Copy(decryptedFile, r); err != nil { log.Fatal(err) } if err := decryptedFile.Close(); err != nil { log.Fatal(err) } if err := ciphertextFile.Close(); err != nil { log.Fatal(err) } // Print the content of the decrypted file. b, err := os.ReadFile(decryptedPath) if err != nil { log.Fatal(err) } fmt.Println(string(b)) // Output: this data needs to be encrypted } // [END streaming-aead-example] ================================================ FILE: go/streamingaead/subtle/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "subtle", srcs = [ "aes_ctr_hmac.go", "aes_gcm_hkdf.go", "subtle.go", ], importpath = "github.com/google/tink/go/streamingaead/subtle", visibility = ["//visibility:public"], deps = [ "//aead/subtle", "//mac/subtle", "//streamingaead/subtle/noncebased", "//subtle", "//subtle/random", ], ) go_test( name = "subtle_test", srcs = [ "aes_ctr_hmac_test.go", "aes_gcm_hkdf_test.go", "subtle_test.go", ], deps = [ ":subtle", "//tink", ], ) alias( name = "go_default_library", actual = ":subtle", visibility = ["//visibility:public"], ) ================================================ FILE: go/streamingaead/subtle/aes_ctr_hmac.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "crypto/aes" "crypto/cipher" "errors" "fmt" "io" // Placeholder for internal crypto/cipher allowlist, please ignore. subtleaead "github.com/google/tink/go/aead/subtle" subtlemac "github.com/google/tink/go/mac/subtle" "github.com/google/tink/go/streamingaead/subtle/noncebased" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/subtle" ) const ( // AESCTRHMACNonceSizeInBytes is the size of the nonces used as IVs for CTR. AESCTRHMACNonceSizeInBytes = 16 // AESCTRHMACNoncePrefixSizeInBytes is the size of the nonce prefix. AESCTRHMACNoncePrefixSizeInBytes = 7 // AESCTRHMACKeySizeInBytes is the size of the HMAC key. AESCTRHMACKeySizeInBytes = 32 ) // AESCTRHMAC implements streaming AEAD encryption using AES-CTR and HMAC. // // Each ciphertext uses new AES-CTR and HMAC keys. These keys are derived using // HKDF and are derived from the key derivation key, a randomly chosen salt of // the same size as the key and a nonce prefix. type AESCTRHMAC struct { mainKey []byte hkdfAlg string keySizeInBytes int tagAlg string tagSizeInBytes int ciphertextSegmentSize int plaintextSegmentSize int firstCiphertextSegmentOffset int } // NewAESCTRHMAC initializes an AESCTRHMAC primitive with a key derivation key // and encryption parameters. // // mainKey is input keying material used to derive sub keys. // // hkdfAlg is a MAC algorithm name, e.g., HmacSha256, used for the HKDF key // derivation. // // keySizeInBytes is the key size of the sub keys. // // tagAlg is the MAC algorithm name, e.g. HmacSha256, used for generating per // segment tags. // // tagSizeInBytes is the size of the per segment tags. // // ciphertextSegmentSize is the size of ciphertext segments. // // firstSegmentOffset is the offset of the first ciphertext segment. func NewAESCTRHMAC(mainKey []byte, hkdfAlg string, keySizeInBytes int, tagAlg string, tagSizeInBytes, ciphertextSegmentSize, firstSegmentOffset int) (*AESCTRHMAC, error) { if len(mainKey) < 16 || len(mainKey) < keySizeInBytes { return nil, errors.New("mainKey too short") } if err := subtleaead.ValidateAESKeySize(uint32(keySizeInBytes)); err != nil { return nil, err } if tagSizeInBytes < 10 { return nil, errors.New("tag size too small") } digestSize, err := subtle.GetHashDigestSize(tagAlg) if err != nil { return nil, err } if uint32(tagSizeInBytes) > digestSize { return nil, errors.New("tag size too big") } headerLen := 1 + keySizeInBytes + AESCTRHMACNoncePrefixSizeInBytes if ciphertextSegmentSize <= firstSegmentOffset+headerLen+tagSizeInBytes { return nil, errors.New("ciphertextSegmentSize too small") } keyClone := make([]byte, len(mainKey)) copy(keyClone, mainKey) return &AESCTRHMAC{ mainKey: keyClone, hkdfAlg: hkdfAlg, keySizeInBytes: keySizeInBytes, tagAlg: tagAlg, tagSizeInBytes: tagSizeInBytes, ciphertextSegmentSize: ciphertextSegmentSize, firstCiphertextSegmentOffset: firstSegmentOffset + headerLen, plaintextSegmentSize: ciphertextSegmentSize - tagSizeInBytes, }, nil } // HeaderLength returns the length of the encryption header. func (a *AESCTRHMAC) HeaderLength() int { return 1 + a.keySizeInBytes + AESCTRHMACNoncePrefixSizeInBytes } // deriveKeys returns an AES of size a.keySizeInBytes and an HMAC key of size AESCTRHMACKeySizeInBytes. // // They are derived from the main key using salt and aad as parameters. func (a *AESCTRHMAC) deriveKeys(salt, aad []byte) ([]byte, []byte, error) { keyMaterialSize := a.keySizeInBytes + AESCTRHMACKeySizeInBytes km, err := subtle.ComputeHKDF(a.hkdfAlg, a.mainKey, salt, aad, uint32(keyMaterialSize)) if err != nil { return nil, nil, err } aesKey := km[:a.keySizeInBytes] hmacKey := km[a.keySizeInBytes:] return aesKey, hmacKey, nil } type aesCTRHMACSegmentEncrypter struct { noncebased.SegmentEncrypter blockCipher cipher.Block hmac *subtlemac.HMAC tagSizeInBytes int } func (e aesCTRHMACSegmentEncrypter) EncryptSegment(segment, nonce []byte) ([]byte, error) { sLen := len(segment) nLen := len(nonce) ctLen := sLen + e.tagSizeInBytes ciphertext := make([]byte, ctLen) stream := cipher.NewCTR(e.blockCipher, nonce) stream.XORKeyStream(ciphertext, segment) macInput := make([]byte, nLen+sLen) copy(macInput, nonce) copy(macInput[nLen:], ciphertext) tag, err := e.hmac.ComputeMAC(macInput) if err != nil { return nil, err } copy(ciphertext[sLen:], tag) return ciphertext, nil } // aesCTRHMACWriter works as a wrapper around underlying io.Writer, which is // responsible for encrypting written data. The data is encrypted and flushed // in segments of a given size. Once all the data is written aesCTRHMACWriter // must be closed. type aesCTRHMACWriter struct { *noncebased.Writer } // NewEncryptingWriter returns a wrapper around underlying io.Writer, such that // any write-operation via the wrapper results in AEAD-encryption of the // written data, using aad as associated authenticated data. The associated // data is not included in the ciphertext and has to be passed in as parameter // for decryption. func (a *AESCTRHMAC) NewEncryptingWriter(w io.Writer, aad []byte) (io.WriteCloser, error) { salt := random.GetRandomBytes(uint32(a.keySizeInBytes)) noncePrefix := random.GetRandomBytes(AESCTRHMACNoncePrefixSizeInBytes) aesKey, hmacKey, err := a.deriveKeys(salt, aad) if err != nil { return nil, err } blockCipher, err := aes.NewCipher(aesKey) if err != nil { return nil, err } hmac, err := subtlemac.NewHMAC(a.tagAlg, hmacKey, uint32(a.tagSizeInBytes)) if err != nil { return nil, err } header := make([]byte, a.HeaderLength()) header[0] = byte(a.HeaderLength()) copy(header[1:], salt) copy(header[1+len(salt):], noncePrefix) if _, err := w.Write(header); err != nil { return nil, err } nw, err := noncebased.NewWriter(noncebased.WriterParams{ W: w, SegmentEncrypter: aesCTRHMACSegmentEncrypter{ blockCipher: blockCipher, hmac: hmac, tagSizeInBytes: a.tagSizeInBytes, }, NonceSize: AESCTRHMACNonceSizeInBytes, NoncePrefix: noncePrefix, PlaintextSegmentSize: a.plaintextSegmentSize, FirstCiphertextSegmentOffset: a.firstCiphertextSegmentOffset, }) if err != nil { return nil, err } return &aesCTRHMACWriter{Writer: nw}, nil } type aesCTRHMACSegmentDecrypter struct { noncebased.SegmentDecrypter blockCipher cipher.Block hmac *subtlemac.HMAC tagSizeInBytes int } func (d aesCTRHMACSegmentDecrypter) DecryptSegment(segment, nonce []byte) ([]byte, error) { sLen := len(segment) nLen := len(nonce) tagStart := sLen - d.tagSizeInBytes if tagStart < 0 { return nil, errors.New("segment too short") } tag := segment[tagStart:] macInput := make([]byte, nLen+tagStart) copy(macInput, nonce) copy(macInput[nLen:], segment[:tagStart]) if err := d.hmac.VerifyMAC(tag, macInput); err != nil { return nil, errors.New("tag mismatch") } result := make([]byte, tagStart) stream := cipher.NewCTR(d.blockCipher, nonce) stream.XORKeyStream(result, segment[:tagStart]) return result, nil } // aesCTRHMACReader works as a wrapper around underlying io.Reader. type aesCTRHMACReader struct { *noncebased.Reader } // NewDecryptingReader returns a wrapper around underlying io.Reader, such that // any read-operation via the wrapper results in AEAD-decryption of the // underlying ciphertext, using aad as associated authenticated data. func (a *AESCTRHMAC) NewDecryptingReader(r io.Reader, aad []byte) (io.Reader, error) { hlen := make([]byte, 1) if _, err := io.ReadFull(r, hlen); err != nil { return nil, err } if hlen[0] != byte(a.HeaderLength()) { return nil, errors.New("invalid header length") } salt := make([]byte, a.keySizeInBytes) if _, err := io.ReadFull(r, salt); err != nil { return nil, fmt.Errorf("cannot read salt: %v", err) } noncePrefix := make([]byte, AESCTRHMACNoncePrefixSizeInBytes) if _, err := io.ReadFull(r, noncePrefix); err != nil { return nil, fmt.Errorf("cannot read noncePrefix: %v", err) } aesKey, hmacKey, err := a.deriveKeys(salt, aad) if err != nil { return nil, err } blockCipher, err := aes.NewCipher(aesKey) if err != nil { return nil, err } hmac, err := subtlemac.NewHMAC(a.tagAlg, hmacKey, uint32(a.tagSizeInBytes)) if err != nil { return nil, err } nr, err := noncebased.NewReader(noncebased.ReaderParams{ R: r, SegmentDecrypter: aesCTRHMACSegmentDecrypter{ blockCipher: blockCipher, hmac: hmac, tagSizeInBytes: a.tagSizeInBytes, }, NonceSize: AESCTRHMACNonceSizeInBytes, NoncePrefix: noncePrefix, CiphertextSegmentSize: a.ciphertextSegmentSize, FirstCiphertextSegmentOffset: a.firstCiphertextSegmentOffset, }) if err != nil { return nil, err } return &aesCTRHMACReader{Reader: nr}, nil } ================================================ FILE: go/streamingaead/subtle/aes_ctr_hmac_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "encoding/hex" "testing" "github.com/google/tink/go/streamingaead/subtle" ) func TestAESCTRHMACEncryptDecrypt(t *testing.T) { testCases := []struct { name string keySizeInBytes int tagSizeInBytes int segmentSize int firstSegmentOffset int plaintextSize int chunkSize int }{ { name: "small-1", keySizeInBytes: 16, tagSizeInBytes: 12, segmentSize: 256, firstSegmentOffset: 0, plaintextSize: 20, chunkSize: 64, }, { name: "small-2", keySizeInBytes: 16, tagSizeInBytes: 12, segmentSize: 512, firstSegmentOffset: 0, plaintextSize: 400, chunkSize: 64, }, { name: "small-offset-1", keySizeInBytes: 16, tagSizeInBytes: 12, segmentSize: 256, firstSegmentOffset: 8, plaintextSize: 20, chunkSize: 64, }, { name: "small-offset-2", keySizeInBytes: 16, tagSizeInBytes: 12, segmentSize: 512, firstSegmentOffset: 8, plaintextSize: 400, chunkSize: 64, }, { name: "empty-1", keySizeInBytes: 16, tagSizeInBytes: 12, segmentSize: 256, firstSegmentOffset: 0, plaintextSize: 0, chunkSize: 128, }, { name: "empty-2", keySizeInBytes: 16, tagSizeInBytes: 12, segmentSize: 256, firstSegmentOffset: 8, plaintextSize: 0, chunkSize: 128, }, { name: "medium-1", keySizeInBytes: 16, tagSizeInBytes: 12, segmentSize: 256, firstSegmentOffset: 0, plaintextSize: 1024, chunkSize: 128, }, { name: "medium-2", keySizeInBytes: 16, tagSizeInBytes: 12, segmentSize: 512, firstSegmentOffset: 0, plaintextSize: 3086, chunkSize: 128, }, { name: "medium-3", keySizeInBytes: 32, tagSizeInBytes: 12, segmentSize: 1024, firstSegmentOffset: 0, plaintextSize: 12345, chunkSize: 128, }, { name: "large-chunks-1", keySizeInBytes: 16, tagSizeInBytes: 12, segmentSize: 256, firstSegmentOffset: 0, plaintextSize: 1024, chunkSize: 4096, }, { name: "large-chunks-2", keySizeInBytes: 16, tagSizeInBytes: 12, segmentSize: 512, firstSegmentOffset: 0, plaintextSize: 5086, chunkSize: 4096, }, { name: "large-chunks-3", keySizeInBytes: 32, tagSizeInBytes: 12, segmentSize: 1024, firstSegmentOffset: 0, plaintextSize: 12345, chunkSize: 5000, }, { name: "medium-offset-1", keySizeInBytes: 16, tagSizeInBytes: 12, segmentSize: 256, firstSegmentOffset: 8, plaintextSize: 1024, chunkSize: 64, }, { name: "medium-offset-2", keySizeInBytes: 16, tagSizeInBytes: 12, segmentSize: 512, firstSegmentOffset: 20, plaintextSize: 3086, chunkSize: 256, }, { name: "medium-offset-3", keySizeInBytes: 32, tagSizeInBytes: 12, segmentSize: 1024, firstSegmentOffset: 10, plaintextSize: 12345, chunkSize: 5000, }, { name: "last-segment-full-1", keySizeInBytes: 16, tagSizeInBytes: 12, segmentSize: 256, firstSegmentOffset: 0, plaintextSize: 216, chunkSize: 64, }, { name: "last-segment-full-2", keySizeInBytes: 16, tagSizeInBytes: 12, segmentSize: 256, firstSegmentOffset: 16, plaintextSize: 200, chunkSize: 256, }, { name: "last-segment-full-3", keySizeInBytes: 16, tagSizeInBytes: 12, segmentSize: 256, firstSegmentOffset: 16, plaintextSize: 440, chunkSize: 1024, }, { name: "single-byte-1", keySizeInBytes: 16, tagSizeInBytes: 12, segmentSize: 256, firstSegmentOffset: 0, plaintextSize: 1024, chunkSize: 1, }, { name: "single-byte-2", keySizeInBytes: 32, tagSizeInBytes: 12, segmentSize: 512, firstSegmentOffset: 0, plaintextSize: 5086, chunkSize: 1, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { cipher, err := subtle.NewAESCTRHMAC(ikm, "SHA256", tc.keySizeInBytes, "SHA256", tc.tagSizeInBytes, tc.segmentSize, tc.firstSegmentOffset) if err != nil { t.Errorf("cannot create cipher: %v", err) } pt, ct, err := encrypt(cipher, aad, tc.plaintextSize) if err != nil { t.Errorf("failure during encryption: %v", err) } if err := decrypt(cipher, aad, pt, ct, tc.chunkSize); err != nil { t.Errorf("failure during decryption: %v", err) } }) } } func TestAESCTRHMACModifiedCiphertext(t *testing.T) { ikm, err := hex.DecodeString("000102030405060708090a0b0c0d0e0f00112233445566778899aabbccddeeff") if err != nil { t.Fatal(err) } aad, err := hex.DecodeString("aabbccddeeff") if err != nil { t.Fatal(err) } const ( keySizeInBytes = 16 tagSizeInBytes = 12 segmentSize = 256 firstSegmentOffset = 8 plaintextSize = 1024 chunkSize = 128 ) cipher, err := subtle.NewAESCTRHMAC(ikm, "SHA256", keySizeInBytes, "SHA256", tagSizeInBytes, segmentSize, firstSegmentOffset) if err != nil { t.Errorf("Cannot create a cipher: %v", err) } pt, ct, err := encrypt(cipher, aad, plaintextSize) if err != nil { t.Error(err) } t.Run("truncate ciphertext", func(t *testing.T) { for i := 0; i < len(ct); i += 8 { if err := decrypt(cipher, aad, pt, ct[:i], chunkSize); err == nil { t.Error("expected error") } } }) t.Run("append to ciphertext", func(t *testing.T) { sizes := []int{1, segmentSize - len(ct)%segmentSize, segmentSize} for _, size := range sizes { ct2 := append(ct, make([]byte, size)...) if err := decrypt(cipher, aad, pt, ct2, chunkSize); err == nil { t.Errorf("expected error") } } }) t.Run("flip bits", func(t *testing.T) { for i := range ct { ct2 := make([]byte, len(ct)) copy(ct2, ct) ct2[i] ^= byte(1) if err := decrypt(cipher, aad, pt, ct2, chunkSize); err == nil { t.Errorf("expected error") } } }) t.Run("delete segments", func(t *testing.T) { for i := 0; i < len(ct)/segmentSize+1; i++ { start, end := segmentPos(segmentSize, firstSegmentOffset, cipher.HeaderLength(), i) if start > len(ct) { break } if end > len(ct) { end = len(ct) } ct2 := append(ct[:start], ct[end:]...) if err := decrypt(cipher, aad, pt, ct2, chunkSize); err == nil { t.Errorf("expected error") } } }) t.Run("duplicate segments", func(t *testing.T) { for i := 0; i < len(ct)/segmentSize+1; i++ { start, end := segmentPos(segmentSize, firstSegmentOffset, cipher.HeaderLength(), i) if start > len(ct) { break } if end > len(ct) { end = len(ct) } ct2 := append(ct[:end], ct[start:]...) if err := decrypt(cipher, aad, pt, ct2, chunkSize); err == nil { t.Errorf("expected error") } } }) t.Run("modify aad", func(t *testing.T) { for i := range aad { aad2 := make([]byte, len(aad)) copy(aad2, aad) aad2[i] ^= byte(1) if err := decrypt(cipher, aad2, pt, ct, chunkSize); err == nil { t.Errorf("expected error") } } }) } ================================================ FILE: go/streamingaead/subtle/aes_gcm_hkdf.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "crypto/aes" "crypto/cipher" "errors" "fmt" "io" // Placeholder for internal crypto/cipher allowlist, please ignore. subtleaead "github.com/google/tink/go/aead/subtle" "github.com/google/tink/go/streamingaead/subtle/noncebased" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/subtle" ) const ( // AESGCMHKDFNonceSizeInBytes is the size of the nonces used for GCM. AESGCMHKDFNonceSizeInBytes = 12 // AESGCMHKDFNoncePrefixSizeInBytes is the size of the randomly generated // nonce prefix. AESGCMHKDFNoncePrefixSizeInBytes = 7 // AESGCMHKDFTagSizeInBytes is the size of the tags of each ciphertext // segment. AESGCMHKDFTagSizeInBytes = 16 ) // AESGCMHKDF implements streaming AEAD encryption using AES-GCM. // // Each ciphertext uses a new AES-GCM key. These keys are derived using HKDF // and are derived from the key derivation key, a randomly chosen salt of the // same size as the key and a nonce prefix. type AESGCMHKDF struct { mainKey []byte hkdfAlg string keySizeInBytes int ciphertextSegmentSize int firstCiphertextSegmentOffset int plaintextSegmentSize int } // NewAESGCMHKDF initializes a streaming primitive with a key derivation key // and encryption parameters. // // mainKey is an input keying material used to derive sub keys. // // hkdfAlg is a MAC algorithm name, e.g., HmacSha256, used for the HKDF key // derivation. // // keySizeInBytes argument is a key size of the sub keys. // // ciphertextSegmentSize argument is the size of ciphertext segments. // // firstSegmentOffset argument is the offset of the first ciphertext segment. func NewAESGCMHKDF(mainKey []byte, hkdfAlg string, keySizeInBytes, ciphertextSegmentSize, firstSegmentOffset int) (*AESGCMHKDF, error) { if len(mainKey) < 16 || len(mainKey) < keySizeInBytes { return nil, errors.New("mainKey too short") } if err := subtleaead.ValidateAESKeySize(uint32(keySizeInBytes)); err != nil { return nil, err } headerLen := 1 + keySizeInBytes + AESGCMHKDFNoncePrefixSizeInBytes if ciphertextSegmentSize <= firstSegmentOffset+headerLen+AESGCMHKDFTagSizeInBytes { return nil, errors.New("ciphertextSegmentSize too small") } keyClone := make([]byte, len(mainKey)) copy(keyClone, mainKey) return &AESGCMHKDF{ mainKey: keyClone, hkdfAlg: hkdfAlg, keySizeInBytes: keySizeInBytes, ciphertextSegmentSize: ciphertextSegmentSize, firstCiphertextSegmentOffset: firstSegmentOffset + headerLen, plaintextSegmentSize: ciphertextSegmentSize - AESGCMHKDFTagSizeInBytes, }, nil } // HeaderLength returns the length of the encryption header. func (a *AESGCMHKDF) HeaderLength() int { return 1 + a.keySizeInBytes + AESGCMHKDFNoncePrefixSizeInBytes } // deriveKey returns a key derived from the given main key using salt and aad // parameters. func (a *AESGCMHKDF) deriveKey(salt, aad []byte) ([]byte, error) { return subtle.ComputeHKDF(a.hkdfAlg, a.mainKey, salt, aad, uint32(a.keySizeInBytes)) } // newCipher creates a new AES-GCM cipher using the given key and the crypto library. func (a *AESGCMHKDF) newCipher(key []byte) (cipher.AEAD, error) { aesCipher, err := aes.NewCipher(key) if err != nil { return nil, err } aesGCMCipher, err := cipher.NewGCMWithTagSize(aesCipher, AESGCMHKDFTagSizeInBytes) if err != nil { return nil, err } return aesGCMCipher, nil } type aesGCMHKDFSegmentEncrypter struct { noncebased.SegmentEncrypter cipher cipher.AEAD } func (e aesGCMHKDFSegmentEncrypter) EncryptSegment(segment, nonce []byte) ([]byte, error) { result := make([]byte, 0, len(segment)) result = e.cipher.Seal(result, nonce, segment, nil) return result, nil } // aesGCMHKDFWriter works as a wrapper around underlying io.Writer, which is // responsible for encrypting written data. The data is encrypted and flushed // in segments of a given size. Once all the data is written aesGCMHKDFWriter // must be closed. type aesGCMHKDFWriter struct { *noncebased.Writer } // NewEncryptingWriter returns a wrapper around underlying io.Writer, such that // any write-operation via the wrapper results in AEAD-encryption of the // written data, using aad as associated authenticated data. The associated // data is not included in the ciphertext and has to be passed in as parameter // for decryption. func (a *AESGCMHKDF) NewEncryptingWriter(w io.Writer, aad []byte) (io.WriteCloser, error) { salt := random.GetRandomBytes(uint32(a.keySizeInBytes)) noncePrefix := random.GetRandomBytes(AESGCMHKDFNoncePrefixSizeInBytes) dkey, err := a.deriveKey(salt, aad) if err != nil { return nil, err } cipher, err := a.newCipher(dkey) if err != nil { return nil, err } header := make([]byte, a.HeaderLength()) header[0] = byte(a.HeaderLength()) copy(header[1:], salt) copy(header[1+len(salt):], noncePrefix) if _, err := w.Write(header); err != nil { return nil, err } nw, err := noncebased.NewWriter(noncebased.WriterParams{ W: w, SegmentEncrypter: aesGCMHKDFSegmentEncrypter{cipher: cipher}, NonceSize: AESGCMHKDFNonceSizeInBytes, NoncePrefix: noncePrefix, PlaintextSegmentSize: a.plaintextSegmentSize, FirstCiphertextSegmentOffset: a.firstCiphertextSegmentOffset, }) if err != nil { return nil, err } return &aesGCMHKDFWriter{Writer: nw}, nil } type aesGCMHKDFSegmentDecrypter struct { noncebased.SegmentDecrypter cipher cipher.AEAD } func (d aesGCMHKDFSegmentDecrypter) DecryptSegment(segment, nonce []byte) ([]byte, error) { result := make([]byte, 0, len(segment)) result, err := d.cipher.Open(result, nonce, segment, nil) if err != nil { return nil, err } return result, nil } // aesGCMHKDFReader works as a wrapper around underlying io.Reader. type aesGCMHKDFReader struct { *noncebased.Reader } // NewDecryptingReader returns a wrapper around underlying io.Reader, such that // any read-operation via the wrapper results in AEAD-decryption of the // underlying ciphertext, using aad as associated authenticated data. func (a *AESGCMHKDF) NewDecryptingReader(r io.Reader, aad []byte) (io.Reader, error) { hlen := make([]byte, 1) if _, err := io.ReadFull(r, hlen); err != nil { return nil, err } if hlen[0] != byte(a.HeaderLength()) { return nil, errors.New("invalid header length") } salt := make([]byte, a.keySizeInBytes) if _, err := io.ReadFull(r, salt); err != nil { return nil, fmt.Errorf("cannot read salt: %v", err) } noncePrefix := make([]byte, AESGCMHKDFNoncePrefixSizeInBytes) if _, err := io.ReadFull(r, noncePrefix); err != nil { return nil, fmt.Errorf("cannot read noncePrefix: %v", err) } dkey, err := a.deriveKey(salt, aad) if err != nil { return nil, err } cipher, err := a.newCipher(dkey) if err != nil { return nil, err } nr, err := noncebased.NewReader(noncebased.ReaderParams{ R: r, SegmentDecrypter: aesGCMHKDFSegmentDecrypter{cipher: cipher}, NonceSize: AESGCMHKDFNonceSizeInBytes, NoncePrefix: noncePrefix, CiphertextSegmentSize: a.ciphertextSegmentSize, FirstCiphertextSegmentOffset: a.firstCiphertextSegmentOffset, }) if err != nil { return nil, err } return &aesGCMHKDFReader{Reader: nr}, nil } ================================================ FILE: go/streamingaead/subtle/aes_gcm_hkdf_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "encoding/hex" "testing" "github.com/google/tink/go/streamingaead/subtle" ) func TestAESGCMHKDFEncryptDecrypt(t *testing.T) { testCases := []struct { name string keySizeInBytes int segmentSize int firstSegmentOffset int plaintextSize int chunkSize int }{ { name: "small-1", keySizeInBytes: 16, segmentSize: 256, firstSegmentOffset: 0, plaintextSize: 20, chunkSize: 64, }, { name: "small-2", keySizeInBytes: 16, segmentSize: 512, firstSegmentOffset: 0, plaintextSize: 400, chunkSize: 64, }, { name: "small-offset-1", keySizeInBytes: 16, segmentSize: 256, firstSegmentOffset: 8, plaintextSize: 20, chunkSize: 64, }, { name: "small-offset-2", keySizeInBytes: 16, segmentSize: 512, firstSegmentOffset: 8, plaintextSize: 400, chunkSize: 64, }, { name: "empty-1", keySizeInBytes: 16, segmentSize: 256, firstSegmentOffset: 0, plaintextSize: 0, chunkSize: 128, }, { name: "empty-2", keySizeInBytes: 16, segmentSize: 256, firstSegmentOffset: 8, plaintextSize: 0, chunkSize: 128, }, { name: "medium-1", keySizeInBytes: 16, segmentSize: 256, firstSegmentOffset: 0, plaintextSize: 1024, chunkSize: 128, }, { name: "medium-2", keySizeInBytes: 16, segmentSize: 512, firstSegmentOffset: 0, plaintextSize: 3086, chunkSize: 128, }, { name: "medium-3", keySizeInBytes: 32, segmentSize: 1024, firstSegmentOffset: 0, plaintextSize: 12345, chunkSize: 128, }, { name: "large-chunks-1", keySizeInBytes: 16, segmentSize: 256, firstSegmentOffset: 0, plaintextSize: 1024, chunkSize: 4096, }, { name: "large-chunks-2", keySizeInBytes: 16, segmentSize: 512, firstSegmentOffset: 0, plaintextSize: 5086, chunkSize: 4096, }, { name: "large-chunks-3", keySizeInBytes: 32, segmentSize: 1024, firstSegmentOffset: 0, plaintextSize: 12345, chunkSize: 5000, }, { name: "medium-offset-1", keySizeInBytes: 16, segmentSize: 256, firstSegmentOffset: 8, plaintextSize: 1024, chunkSize: 64, }, { name: "medium-offset-2", keySizeInBytes: 16, segmentSize: 512, firstSegmentOffset: 20, plaintextSize: 3086, chunkSize: 256, }, { name: "medium-offset-3", keySizeInBytes: 32, segmentSize: 1024, firstSegmentOffset: 10, plaintextSize: 12345, chunkSize: 5000, }, { name: "last-segment-full-1", keySizeInBytes: 16, segmentSize: 256, firstSegmentOffset: 0, plaintextSize: 216, chunkSize: 64, }, { name: "last-segment-full-2", keySizeInBytes: 16, segmentSize: 256, firstSegmentOffset: 16, plaintextSize: 200, chunkSize: 256, }, { name: "last-segment-full-3", keySizeInBytes: 16, segmentSize: 256, firstSegmentOffset: 16, plaintextSize: 440, chunkSize: 1024, }, { name: "single-byte-1", keySizeInBytes: 16, segmentSize: 256, firstSegmentOffset: 0, plaintextSize: 1024, chunkSize: 1, }, { name: "single-byte-2", keySizeInBytes: 32, segmentSize: 512, firstSegmentOffset: 0, plaintextSize: 5086, chunkSize: 1, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { cipher, err := subtle.NewAESGCMHKDF(ikm, "SHA256", tc.keySizeInBytes, tc.segmentSize, tc.firstSegmentOffset) if err != nil { t.Errorf("Cannot create a cipher: %v", err) } pt, ct, err := encrypt(cipher, aad, tc.plaintextSize) if err != nil { t.Error(err) } if err := decrypt(cipher, aad, pt, ct, tc.chunkSize); err != nil { t.Error(err) } }) } } func TestAESGCMHKDFModifiedCiphertext(t *testing.T) { ikm, err := hex.DecodeString("000102030405060708090a0b0c0d0e0f00112233445566778899aabbccddeeff") if err != nil { t.Fatal(err) } aad, err := hex.DecodeString("aabbccddeeff") if err != nil { t.Fatal(err) } const ( keySizeInBytes = 16 segmentSize = 256 firstSegmentOffset = 8 plaintextSize = 1024 chunkSize = 128 ) cipher, err := subtle.NewAESGCMHKDF(ikm, "SHA256", keySizeInBytes, segmentSize, firstSegmentOffset) if err != nil { t.Errorf("Cannot create a cipher: %v", err) } pt, ct, err := encrypt(cipher, aad, plaintextSize) if err != nil { t.Error(err) } t.Run("truncate ciphertext", func(t *testing.T) { for i := 0; i < len(ct); i += 8 { if err := decrypt(cipher, aad, pt, ct[:i], chunkSize); err == nil { t.Errorf("expected error") } } }) t.Run("append to ciphertext", func(t *testing.T) { sizes := []int{1, segmentSize - len(ct)%segmentSize, segmentSize} for _, size := range sizes { ct2 := append(ct, make([]byte, size)...) if err := decrypt(cipher, aad, pt, ct2, chunkSize); err == nil { t.Errorf("expected error") } } }) t.Run("flip bits", func(t *testing.T) { for i := range ct { ct2 := make([]byte, len(ct)) copy(ct2, ct) ct2[i] ^= byte(1) if err := decrypt(cipher, aad, pt, ct2, chunkSize); err == nil { t.Errorf("expected error") } } }) t.Run("delete segments", func(t *testing.T) { for i := 0; i < len(ct)/segmentSize+1; i++ { start, end := segmentPos(segmentSize, firstSegmentOffset, cipher.HeaderLength(), i) if start > len(ct) { break } if end > len(ct) { end = len(ct) } ct2 := append(ct[:start], ct[end:]...) if err := decrypt(cipher, aad, pt, ct2, chunkSize); err == nil { t.Errorf("expected error") } } }) t.Run("duplicate segments", func(t *testing.T) { for i := 0; i < len(ct)/segmentSize+1; i++ { start, end := segmentPos(segmentSize, firstSegmentOffset, cipher.HeaderLength(), i) if start > len(ct) { break } if end > len(ct) { end = len(ct) } ct2 := append(ct[:end], ct[start:]...) if err := decrypt(cipher, aad, pt, ct2, chunkSize); err == nil { t.Errorf("expected error") } } }) t.Run("modify aad", func(t *testing.T) { for i := range aad { aad2 := make([]byte, len(aad)) copy(aad2, aad) aad2[i] ^= byte(1) if err := decrypt(cipher, aad2, pt, ct, chunkSize); err == nil { t.Errorf("expected error") } } }) } ================================================ FILE: go/streamingaead/subtle/noncebased/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "noncebased", srcs = ["noncebased.go"], importpath = "github.com/google/tink/go/streamingaead/subtle/noncebased", visibility = ["//visibility:public"], ) go_test( name = "noncebased_test", srcs = ["noncebased_test.go"], deps = [":noncebased"], ) alias( name = "go_default_library", actual = ":noncebased", visibility = ["//visibility:public"], ) ================================================ FILE: go/streamingaead/subtle/noncebased/noncebased.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package noncebased provides a reusable streaming AEAD framework. // // It tackles the segment handling portions of the nonce based online // encryption scheme proposed in "Online Authenticated-Encryption and its // Nonce-Reuse Misuse-Resistance" by Hoang, Reyhanitabar, Rogaway and Vizár // (https://eprint.iacr.org/2015/189.pdf). // // In this scheme, the format of a ciphertext is: // // header || segment_0 || segment_1 || ... || segment_k. // // The format of header is: // // headerLength || salt || nonce_prefix // // headerLength is 1 byte which documents the size of the header and can be // obtained via HeaderLength(). In principle, headerLength is redundant // information, since the length of the header can be determined from the key // size. // // salt is a salt used in the key derivation. // // nonce_prefix is a prefix for all per-segment nonces. // // segment_i is the i-th segment of the ciphertext. The size of segment_1 .. // segment_{k-1} is ciphertextSegmentSize. segment_0 is shorter, so that // segment_0 plus additional data of size firstCiphertextSegmentOffset (e.g. // the header) aligns with ciphertextSegmentSize. // // The first segment size will be: // // ciphertextSegmentSize - HeaderLength() - firstCiphertextSegmentOffset. package noncebased import ( "encoding/binary" "errors" "io" "math" ) var ( // ErrNonceSizeTooShort indicates that the specified nonce size isn't large // enough to hold the nonce prefix, counter and last segment flag. ErrNonceSizeTooShort = errors.New("nonce size too short") // ErrCiphertextSegmentTooShort indicates the the ciphertext segment being // processed is too short. ErrCiphertextSegmentTooShort = errors.New("ciphertext segment too short") // ErrTooManySegments indicates that the ciphertext has too many segments. ErrTooManySegments = errors.New("too many segments") ) // SegmentEncrypter facilitates implementing various streaming AEAD encryption // modes. type SegmentEncrypter interface { EncryptSegment(segment, nonce []byte) ([]byte, error) } // Writer provides a framework for ingesting plaintext data and // writing encrypted data to the wrapped io.Writer. The scheme used for // encrypting segments is specified by providing a SegmentEncrypter // implementation. type Writer struct { w io.Writer segmentEncrypter SegmentEncrypter encryptedSegmentCnt uint64 firstCiphertextSegmentOffset int nonceSize int noncePrefix []byte plaintext []byte plaintextPos int ciphertext []byte closed bool } // WriterParams contains the options for instantiating a Writer via NewWriter(). type WriterParams struct { // W is the underlying writer being wrapped. W io.Writer // SegmentEncrypter provides a method for encrypting segments. SegmentEncrypter SegmentEncrypter // NonceSize is the length of generated nonces. It must be at least 5 + // len(NoncePrefix). It can be longer, but longer nonces introduce more // overhead in the resultant ciphertext. NonceSize int // NoncePrefix is a constant that all nonces throughout the ciphertext will // start with. It's length must be at least 5 bytes shorter than NonceSize. NoncePrefix []byte // The size of the segments which the plaintext will be split into. PlaintextSegmentSize int // FirstCiphertexSegmentOffset indicates where the ciphertext should begin in // W. This allows for the existence of overhead in the stream unrelated to // this encryption scheme. FirstCiphertextSegmentOffset int } // NewWriter creates a new Writer instance. func NewWriter(params WriterParams) (*Writer, error) { if params.NonceSize-len(params.NoncePrefix) < 5 { return nil, ErrNonceSizeTooShort } return &Writer{ w: params.W, segmentEncrypter: params.SegmentEncrypter, nonceSize: params.NonceSize, noncePrefix: params.NoncePrefix, firstCiphertextSegmentOffset: params.FirstCiphertextSegmentOffset, plaintext: make([]byte, params.PlaintextSegmentSize), }, nil } // Write encrypts passed data and passes the encrypted data to the underlying writer. func (w *Writer) Write(p []byte) (int, error) { if w.closed { return 0, errors.New("write on closed writer") } pos := 0 for { ptLim := len(w.plaintext) if w.encryptedSegmentCnt == 0 { ptLim -= w.firstCiphertextSegmentOffset } n := copy(w.plaintext[w.plaintextPos:ptLim], p[pos:]) w.plaintextPos += n pos += n if pos == len(p) { break } nonce, err := generateSegmentNonce(w.nonceSize, w.noncePrefix, w.encryptedSegmentCnt, false) if err != nil { return pos, err } w.ciphertext, err = w.segmentEncrypter.EncryptSegment(w.plaintext[:ptLim], nonce) if err != nil { return pos, err } if _, err := w.w.Write(w.ciphertext); err != nil { return pos, err } w.plaintextPos = 0 w.encryptedSegmentCnt++ } return pos, nil } // Close encrypts the remaining data, flushes it to the underlying writer and // closes this writer. func (w *Writer) Close() error { if w.closed { return nil } nonce, err := generateSegmentNonce(w.nonceSize, w.noncePrefix, w.encryptedSegmentCnt, true) if err != nil { return err } w.ciphertext, err = w.segmentEncrypter.EncryptSegment(w.plaintext[:w.plaintextPos], nonce) if err != nil { return err } if _, err := w.w.Write(w.ciphertext); err != nil { return err } w.plaintextPos = 0 w.encryptedSegmentCnt++ w.closed = true return nil } // SegmentDecrypter facilitates implementing various streaming AEAD encryption modes. type SegmentDecrypter interface { DecryptSegment(segment, nonce []byte) ([]byte, error) } // Reader facilitates the decryption of ciphertexts created using a Writer. // // The scheme used for decrypting segments is specified by providing a // SegmentDecrypter implementation. The implementation must align // with the SegmentEncrypter used in the Writer. type Reader struct { r io.Reader segmentDecrypter SegmentDecrypter decryptedSegmentCnt uint64 firstCiphertextSegmentOffset int nonceSize int noncePrefix []byte plaintext []byte plaintextPos int ciphertext []byte ciphertextPos int } // ReaderParams contains the options for instantiating a Reader via NewReader(). type ReaderParams struct { // R is the underlying reader being wrapped. R io.Reader // SegmentDecrypter provides a method for decrypting segments. SegmentDecrypter SegmentDecrypter // NonceSize is the length of generated nonces. It must match the NonceSize // of the Writer used to create the ciphertext. NonceSize int // NoncePrefix is a constant that all nocnes throughout the ciphertext start // with. It's extracted from the header of the ciphertext. NoncePrefix []byte // The size of the ciphertext segments. CiphertextSegmentSize int // FirstCiphertexSegmentOffset indicates where the ciphertext actually begins // in R. This allows for the existence of overhead in the stream unrelated to // this encryption scheme. FirstCiphertextSegmentOffset int } // NewReader creates a new Reader instance. func NewReader(params ReaderParams) (*Reader, error) { if params.NonceSize-len(params.NoncePrefix) < 5 { return nil, ErrNonceSizeTooShort } return &Reader{ r: params.R, segmentDecrypter: params.SegmentDecrypter, nonceSize: params.NonceSize, noncePrefix: params.NoncePrefix, firstCiphertextSegmentOffset: params.FirstCiphertextSegmentOffset, // Allocate an extra byte to detect the last segment. ciphertext: make([]byte, params.CiphertextSegmentSize+1), }, nil } // Read decrypts data from underlying reader and passes it to p. func (r *Reader) Read(p []byte) (int, error) { if r.plaintextPos < len(r.plaintext) { n := copy(p, r.plaintext[r.plaintextPos:]) r.plaintextPos += n return n, nil } r.plaintextPos = 0 ctLim := len(r.ciphertext) if r.decryptedSegmentCnt == 0 { ctLim -= r.firstCiphertextSegmentOffset } n, err := io.ReadFull(r.r, r.ciphertext[r.ciphertextPos:ctLim]) if err != nil && err != io.ErrUnexpectedEOF { return 0, err } var ( lastSegment bool segment int ) if err != nil { lastSegment = true segment = r.ciphertextPos + n } else { segment = r.ciphertextPos + n - 1 } if segment < 0 { return 0, ErrCiphertextSegmentTooShort } nonce, err := generateSegmentNonce(r.nonceSize, r.noncePrefix, r.decryptedSegmentCnt, lastSegment) if err != nil { return 0, err } r.plaintext, err = r.segmentDecrypter.DecryptSegment(r.ciphertext[:segment], nonce) if err != nil { return 0, err } // Copy 1 byte remainder to the beginning of ciphertext. if !lastSegment { remainderOffset := segment r.ciphertext[0] = r.ciphertext[remainderOffset] r.ciphertextPos = 1 } r.decryptedSegmentCnt++ n = copy(p, r.plaintext) r.plaintextPos = n return n, nil } // generateSegmentNonce returns a nonce for a segment. // // The format of the nonce is: // // nonce_prefix || ctr || last_block. // // nonce_prefix is a constant prefix used throughout the whole ciphertext. // // The ctr is a 32 bit counter. // // last_block is 1 byte which is set to 1 for the last segment and 0 // otherwise. func generateSegmentNonce(size int, prefix []byte, segmentNum uint64, last bool) ([]byte, error) { if segmentNum >= math.MaxUint32 { return nil, ErrTooManySegments } nonce := make([]byte, size) copy(nonce, prefix) offset := len(prefix) binary.BigEndian.PutUint32(nonce[offset:], uint32(segmentNum)) offset += 4 if last { nonce[offset] = 1 } return nonce, nil } ================================================ FILE: go/streamingaead/subtle/noncebased/noncebased_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package noncebased_test import ( "bufio" "bytes" "crypto/rand" "encoding/hex" "errors" "fmt" "io" "testing" "github.com/google/tink/go/streamingaead/subtle/noncebased" ) func TestNonceBased(t *testing.T) { testcases := []struct { name string plaintextSize int nonceSize int noncePrefixSize int plaintextSegmentSize int firstCiphertextSegmentOffset int chunkSize int }{ { name: "plaintextSizeAlignedWithSegmentSize", plaintextSize: 100, nonceSize: 10, noncePrefixSize: 5, plaintextSegmentSize: 20, firstCiphertextSegmentOffset: 10, chunkSize: 5, }, { name: "plaintextSizeNotAlignedWithSegmentSize", plaintextSize: 110, nonceSize: 10, noncePrefixSize: 5, plaintextSegmentSize: 20, firstCiphertextSegmentOffset: 10, chunkSize: 5, }, { name: "singleSegment", plaintextSize: 100, nonceSize: 10, noncePrefixSize: 5, plaintextSegmentSize: 100, firstCiphertextSegmentOffset: 10, chunkSize: 5, }, { name: "shortPlaintext", plaintextSize: 1, nonceSize: 10, noncePrefixSize: 5, plaintextSegmentSize: 100, firstCiphertextSegmentOffset: 10, chunkSize: 5, }, { name: "shortSegmentSize", plaintextSize: 100, nonceSize: 10, noncePrefixSize: 5, plaintextSegmentSize: 10, firstCiphertextSegmentOffset: 10, chunkSize: 5, }, { name: "largeChunkSize", plaintextSize: 100, nonceSize: 10, noncePrefixSize: 5, plaintextSegmentSize: 10, firstCiphertextSegmentOffset: 10, chunkSize: 500, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { writerParams := noncebased.WriterParams{ NonceSize: tc.nonceSize, PlaintextSegmentSize: tc.plaintextSegmentSize, FirstCiphertextSegmentOffset: tc.firstCiphertextSegmentOffset, } plaintext, ciphertext, noncePrefix, err := testEncrypt(tc.plaintextSize, tc.noncePrefixSize, writerParams) if err != nil { t.Fatalf("encrypting failed: %v\n", err) } readerParams := noncebased.ReaderParams{ NonceSize: tc.nonceSize, NoncePrefix: noncePrefix, CiphertextSegmentSize: tc.plaintextSegmentSize + tc.nonceSize, FirstCiphertextSegmentOffset: tc.firstCiphertextSegmentOffset, } if err := testDecrypt(plaintext, ciphertext, tc.chunkSize, readerParams); err != nil { t.Fatalf("decrypting failed: %v\n", err) } }) } } func TestNonceBased_invalidParameters(t *testing.T) { testcases := []struct { name string plaintextSize int nonceSize int noncePrefixSize int plaintextSegmentSize int firstCiphertextSegmentOffset int chunkSize int expectedError error }{ { name: "nonceTooSmall", plaintextSize: 100, nonceSize: 5, noncePrefixSize: 5, plaintextSegmentSize: 20, firstCiphertextSegmentOffset: 10, chunkSize: 5, expectedError: noncebased.ErrNonceSizeTooShort, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { writerParams := noncebased.WriterParams{ NonceSize: tc.nonceSize, FirstCiphertextSegmentOffset: tc.firstCiphertextSegmentOffset, } _, _, _, err := testEncrypt(tc.plaintextSize, tc.noncePrefixSize, writerParams) if err != tc.expectedError { t.Errorf("did not produce expected error: got: %q, want: %q\n", err, tc.expectedError) } // Prepare empty input for testDecrypt(). ciphertextSegmentSize := tc.plaintextSegmentSize + tc.nonceSize ciphertextSize := tc.firstCiphertextSegmentOffset ciphertextSize += (tc.plaintextSize / tc.plaintextSegmentSize) * ciphertextSegmentSize plaintextRemainder := tc.plaintextSize % tc.plaintextSegmentSize if plaintextRemainder > 0 { ciphertextSize += plaintextRemainder + tc.nonceSize } readerParams := noncebased.ReaderParams{ NonceSize: tc.nonceSize, NoncePrefix: make([]byte, tc.noncePrefixSize), CiphertextSegmentSize: tc.plaintextSegmentSize + tc.nonceSize, FirstCiphertextSegmentOffset: tc.firstCiphertextSegmentOffset, } if err := testDecrypt(make([]byte, tc.plaintextSize), make([]byte, ciphertextSize), tc.chunkSize, readerParams); err != tc.expectedError { t.Errorf("did not produce expected error: got: %q, want: %q\n", err, tc.expectedError) } }) } } // testEncrypter is essentially a no-op cipher. // // It produces ciphertexts which contain the plaintext broken into segments, // with the unmodified per-segment nonce placed at the end of each segment. type testEncrypter struct { noncebased.SegmentEncrypter } func (e testEncrypter) EncryptSegment(segment, nonce []byte) ([]byte, error) { ctLen := len(segment) + len(nonce) ciphertext := make([]byte, ctLen) copy(ciphertext, segment) copy(ciphertext[len(segment):], nonce) return ciphertext, nil } type testDecrypter struct { noncebased.SegmentDecrypter } func (d testDecrypter) DecryptSegment(segment, nonce []byte) ([]byte, error) { tagStart := len(segment) - len(nonce) if tagStart < 0 { return nil, errors.New("segment too short") } tag := segment[tagStart:] if !bytes.Equal(nonce, tag) { return nil, fmt.Errorf("tag mismtach:\nsegment: %s\nnonce: %s\ntag: %s", hex.EncodeToString(segment), hex.EncodeToString(nonce), hex.EncodeToString(tag)) } result := make([]byte, tagStart) copy(result, segment[:tagStart]) return result, nil } // testEncrypt generates a random plaintext and random noncePrefix, then uses // them to instantiate a noncebased.Writer and uses it to produce a ciphertext. // // The plaintext, ciphertext and nonce prefix are returned. func testEncrypt(plaintextSize, noncePrefixSize int, wp noncebased.WriterParams) ([]byte, []byte, []byte, error) { var dst bytes.Buffer dstWriter := bufio.NewWriter(&dst) noncePrefix := make([]byte, noncePrefixSize) if _, err := rand.Read(noncePrefix); err != nil { return nil, nil, nil, err } wp.W = dstWriter wp.SegmentEncrypter = testEncrypter{} wp.NoncePrefix = noncePrefix w, err := noncebased.NewWriter(wp) if err != nil { return nil, nil, nil, err } plaintext := make([]byte, plaintextSize) if _, err := rand.Read(plaintext); err != nil { return nil, nil, nil, err } w.Write(plaintext) w.Close() dstWriter.Flush() ciphertext := dst.Bytes() return plaintext, ciphertext, noncePrefix, nil } // testDecrypt instantiates a noncebased.Reader, uses it to decrypt ciphertext // and verifies it matches plaintext. While decrypting, it reads in chunkSize // increments. func testDecrypt(plaintext, ciphertext []byte, chunkSize int, rp noncebased.ReaderParams) error { rp.R = bytes.NewReader(ciphertext) rp.SegmentDecrypter = testDecrypter{} r, err := noncebased.NewReader(rp) if err != nil { return err } var ( chunk = make([]byte, chunkSize) decrypted = 0 eof = false ) for !eof { n, err := r.Read(chunk) if err != nil && err != io.EOF { return fmt.Errorf("error reading chunk: %v", err) } eof = err == io.EOF got := chunk[:n] want := plaintext[decrypted : decrypted+n] if !bytes.Equal(got, want) { return fmt.Errorf("decrypted data does not match. Got=%s;want=%s", hex.EncodeToString(got), hex.EncodeToString(want)) } decrypted += n } if decrypted != len(plaintext) { return fmt.Errorf("number of decrypted bytes does not match. Got=%d,want=%d", decrypted, len(plaintext)) } return nil } ================================================ FILE: go/streamingaead/subtle/subtle.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package subtle provides subtle implementations of the Streaming AEAD // primitive. package subtle ================================================ FILE: go/streamingaead/subtle/subtle_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "bytes" "encoding/hex" "fmt" "io" "github.com/google/tink/go/tink" ) var ( ikm = []byte{ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, } aad = []byte{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff} ) // encrypt generates a random plaintext of size plaintextSize and encrypts it // using the cipher. Upon success this function returns the actual plaintext // and ciphertext bytes. func encrypt(cipher tink.StreamingAEAD, aad []byte, plaintextSize int) ([]byte, []byte, error) { pt := make([]byte, plaintextSize) for i := range pt { pt[i] = byte(i % 253) } ctBuf := &bytes.Buffer{} w, err := cipher.NewEncryptingWriter(ctBuf, aad) if err != nil { return nil, nil, fmt.Errorf("cannot create an encrypt writer: %v", err) } n, err := w.Write(pt) if err != nil { return nil, nil, fmt.Errorf("error writing to an encrypt writer: %v", err) } if n != len(pt) { return nil, nil, fmt.Errorf("unexpected number of bytes written. Got=%d;want=%d", n, len(pt)) } if err := w.Close(); err != nil { return nil, nil, fmt.Errorf("error closing writer: %v", err) } return pt, ctBuf.Bytes(), err } // decrypt decrypts ciphertext ct using the cipher and validates that it's the // same as the original plaintext pt. func decrypt(cipher tink.StreamingAEAD, aad, pt, ct []byte, chunkSize int) error { r, err := cipher.NewDecryptingReader(bytes.NewBuffer(ct), aad) if err != nil { return fmt.Errorf("cannot create an encrypt reader: %v", err) } var ( chunk = make([]byte, chunkSize) decrypted = 0 eof = false ) for !eof { n, err := r.Read(chunk) if err != nil && err != io.EOF { return fmt.Errorf("error reading chunk: %v", err) } eof = err == io.EOF got := chunk[:n] want := pt[decrypted : decrypted+n] if !bytes.Equal(got, want) { return fmt.Errorf("decrypted data doesn't match. Got=%s;want=%s", hex.EncodeToString(got), hex.EncodeToString(want)) } decrypted += n } if decrypted != len(pt) { return fmt.Errorf("number of decrypted bytes doesn't match. Got=%d;want=%d", decrypted, len(pt)) } return nil } func segmentPos(segmentSize, firstSegmentOffset, headerLen, segmentNr int) (int, int) { start := segmentSize * segmentNr end := start + segmentSize firstSegmentDiff := firstSegmentOffset + headerLen if start > 0 { start -= firstSegmentDiff } end -= firstSegmentDiff return start + headerLen, end + headerLen } ================================================ FILE: go/subtle/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep go_library( name = "subtle", srcs = [ "hkdf.go", "subtle.go", "x25519.go", ], importpath = "github.com/google/tink/go/subtle", deps = [ "@org_golang_x_crypto//curve25519", "@org_golang_x_crypto//hkdf", ], ) go_test( name = "subtle_test", srcs = [ "hkdf_test.go", "subtle_test.go", "x25519_test.go", ], data = ["//testdata/testvectors:xdh"], deps = [ ":subtle", "//testutil", "@org_golang_x_crypto//curve25519", ], ) alias( name = "go_default_library", actual = ":subtle", visibility = ["//:__subpackages__"], ) ================================================ FILE: go/subtle/hkdf.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "errors" "fmt" "io" "golang.org/x/crypto/hkdf" ) const ( // Minimum tag size in bytes. This provides minimum 80-bit security strength. minTagSizeInBytes = uint32(10) ) var errHKDFInvalidInput = errors.New("HKDF: invalid input") // validateHKDFParams validates parameters of HKDF constructor. func validateHKDFParams(hash string, keySize uint32, tagSize uint32) error { // validate tag size digestSize, err := GetHashDigestSize(hash) if err != nil { return err } if tagSize > 255*digestSize { return fmt.Errorf("tag size too big") } if tagSize < minTagSizeInBytes { return fmt.Errorf("tag size too small") } return nil } // ComputeHKDF extracts a pseudorandom key. func ComputeHKDF(hashAlg string, key []byte, salt []byte, info []byte, tagSize uint32) ([]byte, error) { keySize := uint32(len(key)) if err := validateHKDFParams(hashAlg, keySize, tagSize); err != nil { return nil, fmt.Errorf("hkdf: %s", err) } hashFunc := GetHashFunc(hashAlg) if hashFunc == nil { return nil, fmt.Errorf("hkdf: invalid hash algorithm") } if len(salt) == 0 { salt = make([]byte, hashFunc().Size()) } result := make([]byte, tagSize) kdf := hkdf.New(hashFunc, key, salt, info) n, err := io.ReadFull(kdf, result) if n != len(result) || err != nil { return nil, fmt.Errorf("compute of hkdf failed") } return result, nil } ================================================ FILE: go/subtle/hkdf_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "encoding/hex" "testing" "github.com/google/tink/go/subtle" ) func TestHKDFBasic(t *testing.T) { // Test vectors from RFC 5869, Appendix A. // // The name and desc fields align with the content from the RFC for easy // cross referencing. var tests = []struct { name string desc string hashAlg string key string salt string info string tagSize uint32 okm string }{ { name: "TestCase1", desc: "Basic test case with SHA-256", hashAlg: "SHA256", key: "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", salt: "000102030405060708090a0b0c", info: "f0f1f2f3f4f5f6f7f8f9", tagSize: 42, okm: "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865", }, { name: "TestCase2", desc: "Test with SHA-256 and longer inputs/outputs", hashAlg: "SHA256", key: "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f", salt: "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", info: "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeef" + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", tagSize: 82, okm: "b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c" + "59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71" + "cc30c58179ec3e87c14c01d5c1f3434f1d87", }, { name: "TestCase3", desc: "Test with SHA-256 and zero-length salt/info", hashAlg: "SHA256", key: "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", salt: "", info: "", tagSize: 42, okm: "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d" + "9d201395faa4b61a96c8", }, { name: "TestCase4", desc: "Basic test case with SHA-1", hashAlg: "SHA1", key: "0b0b0b0b0b0b0b0b0b0b0b", salt: "000102030405060708090a0b0c", info: "f0f1f2f3f4f5f6f7f8f9", tagSize: 42, okm: "085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422478d305f3f896", }, { name: "TestCase5", desc: "Test with SHA-1 and longer inputs/outputs", hashAlg: "SHA1", key: "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f", salt: "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", info: "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeef" + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", tagSize: 82, okm: "0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe" + "8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e" + "927336d0441f4c4300e2cff0d0900b52d3b4", }, { name: "TestCase6", desc: "Test with SHA-1 and zero-length salt/info", hashAlg: "SHA1", key: "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", salt: "", info: "", tagSize: 42, okm: "0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0" + "ea00033de03984d34918", }, { name: "TestCase7", desc: "Test with SHA-1, salt not provided (defaults to HashLen zero octets), zero-length info", hashAlg: "SHA1", key: "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", salt: "", info: "", tagSize: 42, okm: "2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5" + "673a081d70cce7acfc48", }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { key, err := hex.DecodeString(test.key) if err != nil { t.Fatalf("%s\nhex.DecodeString(key) err = %v", test.desc, err) } salt, err := hex.DecodeString(test.salt) if err != nil { t.Fatalf("%s\nFailed decoding salt: %v", test.desc, err) } info, err := hex.DecodeString(test.info) if err != nil { t.Fatalf("%s\nFailed decoding info: %v", test.desc, err) } okm, err := subtle.ComputeHKDF(test.hashAlg, key, salt, info, test.tagSize) if err != nil { t.Errorf("%s\nsubtle.ComputeHKDF() err = %v, want nil", test.desc, err) } if got, want := hex.EncodeToString(okm), test.okm; got != want { t.Errorf("%s\nsubtle.ComputeHKDF() = %q, want %q", test.desc, got, want) } }) } } func TestNewHMACWithInvalidInput(t *testing.T) { var tests = []struct { name string hashAlg string tagSize uint32 }{ { name: "invalid algorithm", hashAlg: "SHA0", tagSize: 32, }, { name: "tag too short", hashAlg: "SHA256", tagSize: 9, }, { name: "tag too big", hashAlg: "SHA512", tagSize: 16323, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { if _, err := subtle.ComputeHKDF(test.hashAlg, nil, nil, nil, test.tagSize); err == nil { t.Fatalf("subtle.ComputeHKDF(%q, nil, nil, nil, %d) err is nil, want not nil", test.hashAlg, test.tagSize) } }) } } ================================================ FILE: go/subtle/random/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep go_library( name = "random", srcs = ["random.go"], importpath = "github.com/google/tink/go/subtle/random", visibility = ["//visibility:public"], ) go_test( name = "random_test", srcs = ["random_test.go"], deps = [":random"], ) alias( name = "go_default_library", actual = ":random", visibility = ["//visibility:public"], ) ================================================ FILE: go/subtle/random/random.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package random provides functions that generate random numbers or bytes. package random import ( "crypto/rand" "encoding/binary" ) // GetRandomBytes randomly generates n bytes. func GetRandomBytes(n uint32) []byte { buf := make([]byte, n) _, err := rand.Read(buf) if err != nil { panic(err) // out of randomness, should never happen } return buf } // GetRandomUint32 randomly generates an unsigned 32-bit integer. func GetRandomUint32() uint32 { b := GetRandomBytes(4) return binary.BigEndian.Uint32(b) } ================================================ FILE: go/subtle/random/random_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package random_test import ( "testing" "github.com/google/tink/go/subtle/random" ) func TestGetRandomBytes(t *testing.T) { for i := 0; i <= 32; i++ { buf := random.GetRandomBytes(uint32(i)) if len(buf) != i { t.Errorf("length of the output doesn't match the input") } } } ================================================ FILE: go/subtle/subtle.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package subtle provides common methods needed in subtle implementations. package subtle import ( "crypto/elliptic" "crypto/sha1" "crypto/sha256" "crypto/sha512" "encoding/hex" "errors" "hash" "math/big" ) var errNilHashFunc = errors.New("nil hash function") // hashDigestSize maps hash algorithms to their digest size in bytes. var hashDigestSize = map[string]uint32{ "SHA1": uint32(20), "SHA224": uint32(28), "SHA256": uint32(32), "SHA384": uint32(48), "SHA512": uint32(64), } // GetHashDigestSize returns the digest size of the specified hash algorithm. func GetHashDigestSize(hash string) (uint32, error) { digestSize, ok := hashDigestSize[hash] if !ok { return 0, errors.New("invalid hash algorithm") } return digestSize, nil } // TODO(ckl): Perhaps return an explicit error instead of ""/nil for the // following functions. // ConvertHashName converts different forms of a hash name to the // hash name that tink recognizes. func ConvertHashName(name string) string { switch name { case "SHA-224": return "SHA224" case "SHA-256": return "SHA256" case "SHA-384": return "SHA384" case "SHA-512": return "SHA512" case "SHA-1": return "SHA1" default: return "" } } // ConvertCurveName converts different forms of a curve name to the // name that tink recognizes. func ConvertCurveName(name string) string { switch name { case "secp256r1", "P-256": return "NIST_P256" case "secp384r1", "P-384": return "NIST_P384" case "secp521r1", "P-521": return "NIST_P521" default: return "" } } // GetHashFunc returns the corresponding hash function of the given hash name. func GetHashFunc(hash string) func() hash.Hash { switch hash { case "SHA1": return sha1.New case "SHA224": return sha256.New224 case "SHA256": return sha256.New case "SHA384": return sha512.New384 case "SHA512": return sha512.New default: return nil } } // GetCurve returns the curve object that corresponds to the given curve type. // It returns null if the curve type is not supported. func GetCurve(curve string) elliptic.Curve { switch curve { case "NIST_P256": return elliptic.P256() case "NIST_P384": return elliptic.P384() case "NIST_P521": return elliptic.P521() default: return nil } } // ComputeHash calculates a hash of the given data using the given hash function. func ComputeHash(hashFunc func() hash.Hash, data []byte) ([]byte, error) { if hashFunc == nil { return nil, errNilHashFunc } h := hashFunc() h.Write(data) return h.Sum(nil), nil } // NewBigIntFromHex returns a big integer from a hex string. func NewBigIntFromHex(s string) (*big.Int, error) { if len(s)%2 == 1 { s = "0" + s } b, err := hex.DecodeString(s) if err != nil { return nil, err } ret := new(big.Int).SetBytes(b) return ret, nil } ================================================ FILE: go/subtle/subtle_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "encoding/hex" "hash" "testing" "github.com/google/tink/go/subtle" ) func TestConvertHashName(t *testing.T) { if subtle.ConvertHashName("SHA-256") != "SHA256" || subtle.ConvertHashName("SHA-1") != "SHA1" || subtle.ConvertHashName("SHA-512") != "SHA512" || subtle.ConvertHashName("UNKNOWN_HASH") != "" { t.Errorf("incorrect hash name conversion") } } func TestConvertCurveName(t *testing.T) { if subtle.ConvertCurveName("secp256r1") != "NIST_P256" || subtle.ConvertCurveName("secp384r1") != "NIST_P384" || subtle.ConvertCurveName("secp521r1") != "NIST_P521" || subtle.ConvertCurveName("UNKNOWN_CURVE") != "" { t.Errorf("incorrect curve name conversion") } } func TestComputeHash(t *testing.T) { data := []byte("Hello") var tests = []struct { hashFunc func() hash.Hash expectedHash string }{ {subtle.GetHashFunc("SHA1"), "f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0"}, {subtle.GetHashFunc("SHA256"), "185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969"}, {subtle.GetHashFunc("SHA512"), "3615f80c9d293ed7402687f94b22d58e529b8cc7916f8fac7fddf7fbd5af4cf777d3d795a7a00a16bf7e7f3fb9561ee9baae480da9fe7a18769e71886b03f315"}, } for _, tt := range tests { hashFunc := tt.hashFunc if hashFunc == nil { t.Fatal("got nil hash func") } hashed, err := subtle.ComputeHash(hashFunc, data) if err != nil { t.Fatalf("got error: %q", err) } if gotHash := hex.EncodeToString(hashed); gotHash != tt.expectedHash { t.Fatalf("Expected: %s. Got: %s", tt.expectedHash, gotHash) } } // unknown if subtle.GetHashFunc("UNKNOWN_HASH") != nil { t.Errorf("unexpected result for invalid hash types") } } func TestGetCurve(t *testing.T) { if subtle.GetCurve("NIST_P256").Params().Name != "P-256" { t.Errorf("incorrect result for NIST_P256") } if subtle.GetCurve("NIST_P384").Params().Name != "P-384" { t.Errorf("incorrect result for NIST_P384") } if subtle.GetCurve("NIST_P521").Params().Name != "P-521" { t.Errorf("incorrect result for NIST_P521") } if subtle.GetCurve("UNKNOWN_CURVE") != nil { t.Errorf("expect nil when curve is unknown") } } ================================================ FILE: go/subtle/x25519.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle import ( "crypto/rand" "golang.org/x/crypto/curve25519" ) // GeneratePrivateKeyX25519 generates a new 32-byte private key. func GeneratePrivateKeyX25519() ([]byte, error) { privKey := make([]byte, curve25519.ScalarSize) _, err := rand.Read(privKey) return privKey, err } // ComputeSharedSecretX25519 returns the 32-byte shared key, i.e. // privKey * pubValue on the curve. func ComputeSharedSecretX25519(privKey, pubValue []byte) ([]byte, error) { return curve25519.X25519(privKey, pubValue) } // PublicFromPrivateX25519 computes privKey's corresponding public key. func PublicFromPrivateX25519(privKey []byte) ([]byte, error) { return ComputeSharedSecretX25519(privKey, curve25519.Basepoint) } ================================================ FILE: go/subtle/x25519_test.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package subtle_test import ( "crypto/rand" "encoding/hex" "fmt" "testing" "golang.org/x/crypto/curve25519" "github.com/google/tink/go/subtle" "github.com/google/tink/go/testutil" ) func TestComputeSharedSecretX25519WithRFCTestVectors(t *testing.T) { // Test vectors are defined at // https://datatracker.ietf.org/doc/html/rfc7748#section-6.1. tests := []struct { priv string pub string }{ {"5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb", "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a"}, {"77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a", "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f"}, } shared := "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742" for i, test := range tests { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { priv, err := hex.DecodeString(test.priv) if err != nil { t.Fatalf("DecodeString(priv): got err %q, want nil", err) } pub, err := hex.DecodeString(test.pub) if err != nil { t.Fatalf("DecodeString(pub): got err %q, want nil", err) } gotShared, err := subtle.ComputeSharedSecretX25519(priv, pub) if err != nil { t.Fatalf("ComputeSharedSecretX25519(priv, pub): got err %q, want nil", err) } if got, want := hex.EncodeToString(gotShared), shared; got != want { t.Errorf("ComputeSharedSecretX25519(shared): got %v, want %v", got, want) } }) } } type x25519Suite struct { testutil.WycheproofSuite TestGroups []*x25519Group `json:"testGroups"` } type x25519Group struct { testutil.WycheproofGroup Curve string `json:"curve"` Tests []*x25519Case `json:"tests"` } type x25519Case struct { testutil.WycheproofCase Public string `json:"public"` Private string `json:"private"` Shared string `json:"shared"` Result string `json:"result"` Flags []string `json:"flags"` } func TestComputeSharedSecretX25519WithWycheproofVectors(t *testing.T) { testutil.SkipTestIfTestSrcDirIsNotSet(t) suite := new(x25519Suite) if err := testutil.PopulateSuite(suite, "x25519_test.json"); err != nil { t.Fatalf("testutil.PopulateSuite: %v", err) } for _, group := range suite.TestGroups { if group.Curve != "curve25519" { continue } for _, test := range group.Tests { t.Run(fmt.Sprintf("%d", test.CaseID), func(t *testing.T) { pub, err := hex.DecodeString(test.Public) if err != nil { t.Fatalf("DecodeString(pub): got err %q, want nil", err) } priv, err := hex.DecodeString(test.Private) if err != nil { t.Fatalf("DecodeString(priv): got err %q, want nil", err) } gotShared, err := subtle.ComputeSharedSecretX25519(priv, pub) // ComputeSharedSecretX25519 fails on low order public values. wantErr := false for _, flag := range test.Flags { if flag == "LowOrderPublic" { wantErr = true } } if wantErr { if err == nil { t.Error("ComputeSharedSecretX25519(priv, pub): got success, want err") } } else { if err != nil { t.Errorf("ComputeSharedSecretX25519(priv, pub): got err %q, want nil", err) } if got, want := hex.EncodeToString(gotShared), test.Shared; got != want { t.Errorf("ComputeSharedSecretX25519(shared): got %v, want %v", got, want) } } }) } } } func TestComputeSharedSecretX25519Fails(t *testing.T) { pubs := []string{ // Should fail on non-32-byte inputs. "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c", "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a2a", // Should fail on low order points, from Sodium // https://github.com/jedisct1/libsodium/blob/65621a1059a37d/src/libsodium/crypto_scalarmult/curve25519/ref10/x25519_ref10.c#L11-L70. "0000000000000000000000000000000000000000000000000000000000000000", "0100000000000000000000000000000000000000000000000000000000000000", "e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b800", "5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157", "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", } priv := make([]byte, curve25519.ScalarSize) if _, err := rand.Read(priv); err != nil { t.Fatal(err) } for i, pubHex := range pubs { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { pub, err := hex.DecodeString(pubHex) if err != nil { t.Fatalf("DecodeString(pub): got err %q, want nil", err) } if _, err := subtle.ComputeSharedSecretX25519(priv, pub); err == nil { t.Error("ComputeSharedSecretX25519(priv, pub): got success, want err") } }) } } func TestPublicFromPrivateX25519WithRFCTestVectors(t *testing.T) { // Test vectors are defined at // https://datatracker.ietf.org/doc/html/rfc7748#section-6.1. tests := []struct { priv string pub string }{ {"77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a", "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a"}, {"5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb", "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f"}, } for i, test := range tests { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { priv, err := hex.DecodeString(test.priv) if err != nil { t.Fatalf("DecodeString(priv): got err %q, want nil", err) } gotPub, err := subtle.PublicFromPrivateX25519(priv) if err != nil { t.Fatalf("PublicFromPrivateX25519(priv): got err %q, want nil", err) } if got, want := hex.EncodeToString(gotPub), test.pub; got != want { t.Errorf("PublicFromPrivateX25519(priv): got %s, want %s", got, want) } }) } } func TestPublicFromPrivateX25519Fails(t *testing.T) { // PublicFromPrivateX25519 fails on non-32-byte private keys. privs := []string{ "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c", "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb95", } for i, priv := range privs { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { priv, err := hex.DecodeString(priv) if err != nil { t.Fatalf("DecodeString(priv): got err %q, want nil", err) } if _, err := subtle.PublicFromPrivateX25519(priv); err == nil { t.Error("PublicFromPrivateX25519(priv): got success, want err") } }) } } ================================================ FILE: go/testdata/BUILD.bazel ================================================ ================================================ FILE: go/testdata/aws/BUILD.bazel ================================================ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) filegroup( name = "credentials", testonly = 1, srcs = [ "credentials.cred", "credentials.csv", "credentials.ini", "key_arn.txt", ], ) filegroup( name = "bad_credentials", testonly = 1, srcs = [ "access_keys_bad.csv", "credentials_bad.csv", "credentials_bad.ini", "key_arn_bad.txt", ], ) ================================================ FILE: go/testdata/aws/README.md ================================================ This folder contains AWS credentials that are used for testing Tink. For security reasons, all credentials in this folder are invalid. If you want to run tests that depend on them, please create your own [AWS access keys][aws-access-keys]. The credentials are required in several formats expected by different APIs. For example, Java expects the credentials as a [properties file][properties-file]. In order to cover all tests across all languages you have to replace `aws/credentials.cred`, `aws/credentials.csv` and `aws/credentials.ini`. These can be generated in a similar way to this [credential copying script][copy-credentials-script]. [aws-access-keys]: https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html [properties-file]: https://docs.aws.amazon.com/AmazonS3/latest/dev/AuthUsingAcctOrUserCredentials.html [copy-credentials-script]: https://github.com/google/tink/blob/master/kokoro/copy_credentials.sh ================================================ FILE: go/testdata/aws/access_keys_bad.csv ================================================ Access key ID,Secret access key AKIAIOSFODNN7EXAMPLE,wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY ================================================ FILE: go/testdata/aws/credentials.cred ================================================ [default] accessKey = AKIAIIK5X7P3NAHNSNUQ secretKey = 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 ================================================ FILE: go/testdata/aws/credentials.csv ================================================ User name,Password,Access key ID,Secret access key,Console login link tink-user1,,AKIAIIK5X7P3NAHNSNUQ,c7k55Gw83QlN1gYBhVPEEn1pKV909sxbll8JOvHF,https://235739564943.signin.aws.amazon.com/console ================================================ FILE: go/testdata/aws/credentials.ini ================================================ [default] aws_access_key_id = AKIAIIK5X7P3NAHNSNUQ aws_secret_access_key = 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 ================================================ FILE: go/testdata/aws/credentials_bad.csv ================================================ User name,Password,Access key ID,Secret access key ,,AKIAIOSFODNN7EXAMPLE,wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY ================================================ FILE: go/testdata/aws/credentials_bad.ini ================================================ [default] aws_access_key_id = AKIAIOSFODNN7EXAMPLE aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY ================================================ FILE: go/testdata/aws/key_arn.txt ================================================ arn:aws:kms:us-east-2:235739564943:key/3ee50705-5a82-4f5b-9753-05c4f473922f ================================================ FILE: go/testdata/aws/key_arn_bad.txt ================================================ arn:aws:kms:us-east-2:123456789012:key/12345678-1234-1234-1234-123456789012 ================================================ FILE: go/testdata/gcp/BUILD.bazel ================================================ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) exports_files(srcs = ["credential.json"]) filegroup( name = "credentials", testonly = 1, srcs = [ "credential.json", "key_name.txt", ], ) filegroup( name = "bad_credentials", testonly = 1, srcs = [ "credential_bad.json", "key_name_bad.txt", ], ) ================================================ FILE: go/testdata/gcp/README.md ================================================ This folder contains GCP credentials that are used for testing Tink. For security reasons, all credentials in this folder are invalid. If you want to run tests that depend on them, please create your own [Cloud KMS key](https://cloud.google.com/kms/docs/creating-keys), and copy the credentials to `gcp/credential.json` and the key URI to `gcp/key_name.txt`. ================================================ FILE: go/testdata/gcp/credential.json ================================================ { "type": "service_account", "project_id": "tink-test-infrastructure", "private_key_id": "some_bad_private_key_id", "private_key": "-----BEGIN PRIVATE KEY-----\nMIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMtJlaQD79xGIC28\nowTpj7wkdi34piSubtDKttgC3lL00ioyQf/WMqLnyDWySNufCjhavQ7/sxXQAUCL\n5B3WDwM8+mFqQM2wJB18NBWBSfGOFSMwVQyWv7Y/1AFr+PvNKVlw4RZ4G8VuJzXZ\n9v/+5zyKv8py66sGVoHPI+LGfIprAgMBAAECgYEAxcgX8PVrnrITiKwpJxReJbyL\nxnpOmw2i/zza3BseVzOebjNrhw/NQDWl0qhcvmBjvyR5IGiiwiwXq8bu8CBdhRiE\nw3vKf1iuVOKhH07RB2wvCaGbVlB/p15gYau3sTRn5nej0tjYHX7xa/St/DwPk2H/\nxYGTRhyYtNL6wdtMjYECQQD+LVVJf0rLnxyPADTcz7Wdb+FUX79nWtMlzQOEB09+\nJj4ie0kD0cIvTQFjV3pOsg3uW2khFpjg110TXpJJfPjhAkEAzL7RhhfDdL7Dn2zl\n1orUthcGa2pzEAmg1tGBNb1pOg7LbVHKSa3GOOwyPRsActoyrPw18/fXaJdEfByY\ne9kwywJAB7rHMjH9y01uZ+bgtKpYYo5JcvBqeLEpZKfkaHp0b2ioURIguU4Csr+L\nwEKjxIrjo5ECFHCEe6nw+arRlgyH4QJBAIfQmEn733LEzB0n7npXU2yKb363eSYN\nTPzSsoREZdXWVIjqtWYUeKXvwA+apryJEw5+qwdvwxslJI+zpE6bLusCQE6M1lO9\nN6A3PtQv7Z3XwrEE/sPEVv4M4VHj0YHLs/32UuSXq5taMizKILfis1Stry4WjRHp\nQxEqdLrIkb13NH8=\n-----END PRIVATE KEY-----", "client_email": "unit-and-integration-testing@tink-test-infrastructure.iam.gserviceaccount.com", "client_id": "111876397550362269561", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://accounts.google.com/o/oauth2/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/unit-and-integration-testing%40tink-test-infrastructure.iam.gserviceaccount.com" } ================================================ FILE: go/testdata/gcp/credential_bad.json ================================================ { "type": "service_account", "project_id": "tink-test-infrastructure", "private_key_id": "some_bad_private_key_id", "private_key": "-----BEGIN PRIVATE KEY-----\nMIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMtJlaQD79xGIC28\nowTpj7wkdi34piSubtDKttgC3lL00ioyQf/WMqLnyDWySNufCjhavQ7/sxXQAUCL\n5B3WDwM8+mFqQM2wJB18NBWBSfGOFSMwVQyWv7Y/1AFr+PvNKVlw4RZ4G8VuJzXZ\n9v/+5zyKv8py66sGVoHPI+LGfIprAgMBAAECgYEAxcgX8PVrnrITiKwpJxReJbyL\nxnpOmw2i/zza3BseVzOebjNrhw/NQDWl0qhcvmBjvyR5IGiiwiwXq8bu8CBdhRiE\nw3vKf1iuVOKhH07RB2wvCaGbVlB/p15gYau3sTRn5nej0tjYHX7xa/St/DwPk2H/\nxYGTRhyYtNL6wdtMjYECQQD+LVVJf0rLnxyPADTcz7Wdb+FUX79nWtMlzQOEB09+\nJj4ie0kD0cIvTQFjV3pOsg3uW2khFpjg110TXpJJfPjhAkEAzL7RhhfDdL7Dn2zl\n1orUthcGa2pzEAmg1tGBNb1pOg7LbVHKSa3GOOwyPRsActoyrPw18/fXaJdEfByY\ne9kwywJAB7rHMjH9y01uZ+bgtKpYYo5JcvBqeLEpZKfkaHp0b2ioURIguU4Csr+L\nwEKjxIrjo5ECFHCEe6nw+arRlgyH4QJBAIfQmEn733LEzB0n7npXU2yKb363eSYN\nTPzSsoREZdXWVIjqtWYUeKXvwA+apryJEw5+qwdvwxslJI+zpE6bLusCQE6M1lO9\nN6A3PtQv7Z3XwrEE/sPEVv4M4VHj0YHLs/32UuSXq5taMizKILfis1Stry4WjRHp\nQxEqdLrIkb13NH8=\n-----END PRIVATE KEY-----", "client_email": "unit-and-integration-testing@tink-test-infrastructure.iam.gserviceaccount.com", "client_id": "111876397550362269561", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://accounts.google.com/o/oauth2/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/unit-and-integration-testing%40tink-test-infrastructure.iam.gserviceaccount.com" } ================================================ FILE: go/testdata/gcp/key_name.txt ================================================ projects/tink-test-infrastructure/locations/global/keyRings/unit-and-integration-testing/cryptoKeys/aead-key ================================================ FILE: go/testdata/gcp/key_name_bad.txt ================================================ projects/non-existing-project/locations/global/keyRings/some-key-ring/cryptoKeys/aead-key ================================================ FILE: go/testdata/keysets/BUILD.bazel ================================================ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) filegroup( name = "ecies", testonly = 1, srcs = [ # Generated with # tinkey create \ # --key-template ECIES_P256_HKDF_HMAC_SHA256_AES128_CTR_HMAC_SHA256 \ # --out testdata/keysets/ecies_private_keyset2.bin \ # --out-format BINARY "ecies_private_keyset.bin", # Generated with # tinkey create \ # --key-template ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM \ # --out testdata/keysets/ecies_private_keyset2.bin \ # --out-format BINARY "ecies_private_keyset2.bin", # tinkey create-public-keyset \ # --in testdata/keysets/ecies_private_keyset.bin \ # --in-form BINARY \ # --out testdata/keysets/ecies_public_keyset.bin \ # --out-form BINARY "ecies_public_keyset.bin", "ecies_public_keyset2.bin", ], ) ================================================ FILE: go/testdata/testvectors/BUILD.bazel ================================================ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) filegroup( name = "hpke_boringssl", testonly = 1, srcs = ["hpke_boringssl.json"], ) # Below we define a set of genrules to copy test vectors from Wycheproof. # This is needed to assist the transition to using Bazel Modules, in that Bazel # Modules packages use a different folder naming for dependencies compared to # WORKSPACE-based packages. genrule( name = "aes_cmac", testonly = 1, srcs = ["@wycheproof//testvectors:aes_cmac"], outs = ["aes_cmac_test.json"], cmd = "cp $(SRCS) $(@D)/", ) genrule( name = "aes_gcm", testonly = 1, srcs = ["@wycheproof//testvectors:aes_gcm"], outs = ["aes_gcm_test.json"], cmd = "cp $(SRCS) $(@D)/", ) genrule( name = "aes_gcm_siv", testonly = 1, srcs = ["@wycheproof//testvectors:aes_gcm_siv"], outs = ["aes_gcm_siv_test.json"], cmd = "cp $(SRCS) $(@D)/", ) genrule( name = "aes_eax", testonly = 1, srcs = ["@wycheproof//testvectors:aes_eax"], outs = ["aes_eax_test.json"], cmd = "cp $(SRCS) $(@D)/", ) genrule( name = "aes_siv_cmac", testonly = 1, srcs = ["@wycheproof//testvectors:aes_siv_cmac"], outs = [ "aead_aes_siv_cmac_test.json", "aes_siv_cmac_test.json", ], cmd = "cp $(SRCS) $(@D)/", ) genrule( name = "chacha20_poly1305", testonly = 1, srcs = ["@wycheproof//testvectors:chacha20_poly1305"], outs = [ "chacha20_poly1305_test.json", "xchacha20_poly1305_test.json", ], cmd = "cp $(SRCS) $(@D)/", ) genrule( name = "hmac", testonly = 1, srcs = ["@wycheproof//testvectors:hmac"], outs = [ "hmac_sha1_test.json", "hmac_sha224_test.json", "hmac_sha256_test.json", "hmac_sha384_test.json", "hmac_sha3_224_test.json", "hmac_sha3_256_test.json", "hmac_sha3_384_test.json", "hmac_sha3_512_test.json", "hmac_sha512_test.json", ], cmd = "cp $(SRCS) $(@D)/", ) genrule( name = "rsa_pss", testonly = 1, srcs = ["@wycheproof//testvectors:all"], outs = [ "rsa_pss_2048_sha1_mgf1_20_test.json", "rsa_pss_2048_sha256_mgf1_0_test.json", "rsa_pss_2048_sha256_mgf1_32_test.json", "rsa_pss_2048_sha512_256_mgf1_28_test.json", "rsa_pss_2048_sha512_256_mgf1_32_test.json", "rsa_pss_3072_sha256_mgf1_32_test.json", "rsa_pss_4096_sha256_mgf1_32_test.json", "rsa_pss_4096_sha512_mgf1_32_test.json", "rsa_pss_misc_test.json", ], cmd = "cp $(SRCS) $(@D)/", ) genrule( name = "rsa_signature", testonly = 1, srcs = ["@wycheproof//testvectors:rsa_signature"], outs = [ # Signature verification "rsa_signature_2048_sha224_test.json", "rsa_signature_2048_sha256_test.json", "rsa_signature_2048_sha512_test.json", "rsa_signature_3072_sha256_test.json", "rsa_signature_3072_sha384_test.json", "rsa_signature_3072_sha512_test.json", "rsa_signature_4096_sha384_test.json", "rsa_signature_4096_sha512_test.json", "rsa_signature_2048_sha3_224_test.json", "rsa_signature_2048_sha3_256_test.json", "rsa_signature_2048_sha3_384_test.json", "rsa_signature_2048_sha3_512_test.json", "rsa_signature_3072_sha3_256_test.json", "rsa_signature_3072_sha3_384_test.json", "rsa_signature_3072_sha3_512_test.json", "rsa_signature_test.json", # Signature generation "rsa_sig_gen_misc_test.json", ], cmd = "cp $(SRCS) $(@D)/", ) genrule( name = "ecdsa_webcrypto", testonly = 1, srcs = ["@wycheproof//testvectors:ecdsa_webcrypto"], outs = ["ecdsa_webcrypto_test.json"], cmd = "cp $(SRCS) $(@D)/", ) genrule( name = "ecdsa", testonly = 1, srcs = ["@wycheproof//testvectors:all"], outs = [ "ecdsa_brainpoolP224r1_sha224_test.json", "ecdsa_brainpoolP256r1_sha256_test.json", "ecdsa_brainpoolP320r1_sha384_test.json", "ecdsa_brainpoolP384r1_sha384_test.json", "ecdsa_brainpoolP512r1_sha512_test.json", "ecdsa_secp224r1_sha224_test.json", "ecdsa_secp224r1_sha256_test.json", "ecdsa_secp224r1_sha3_224_test.json", "ecdsa_secp224r1_sha3_256_test.json", "ecdsa_secp224r1_sha3_512_test.json", "ecdsa_secp224r1_sha512_test.json", "ecdsa_secp256k1_sha256_test.json", "ecdsa_secp256k1_sha3_256_test.json", "ecdsa_secp256k1_sha3_512_test.json", "ecdsa_secp256k1_sha512_test.json", "ecdsa_secp256r1_sha256_test.json", "ecdsa_secp256r1_sha3_256_test.json", "ecdsa_secp256r1_sha3_512_test.json", "ecdsa_secp256r1_sha512_test.json", "ecdsa_secp384r1_sha384_test.json", "ecdsa_secp384r1_sha3_384_test.json", "ecdsa_secp384r1_sha3_512_test.json", "ecdsa_secp384r1_sha512_test.json", "ecdsa_secp521r1_sha3_512_test.json", "ecdsa_secp521r1_sha512_test.json", "ecdsa_secp256r1_sha256_p1363_test.json", "ecdsa_secp384r1_sha512_p1363_test.json", "ecdsa_secp521r1_sha512_p1363_test.json", "ecdsa_test.json", # deprecated: use the files above ], cmd = "cp $(SRCS) $(@D)/", ) genrule( name = "eddsa", testonly = 1, srcs = ["@wycheproof//testvectors:eddsa"], outs = [ "ed448_test.json", "eddsa_test.json", ], cmd = "cp $(SRCS) $(@D)/", ) genrule( name = "ecdh", testonly = 1, srcs = ["@wycheproof//testvectors:ecdh"], outs = [ "ecdh_brainpoolP224r1_test.json", "ecdh_brainpoolP256r1_test.json", "ecdh_brainpoolP320r1_test.json", "ecdh_brainpoolP384r1_test.json", "ecdh_brainpoolP512r1_test.json", "ecdh_secp224r1_test.json", "ecdh_secp256k1_test.json", "ecdh_secp256r1_test.json", "ecdh_secp384r1_test.json", "ecdh_secp521r1_test.json", "ecdh_test.json", # deprecated use the files above ], cmd = "cp $(SRCS) $(@D)/", ) genrule( name = "ecdh_ecpoint", testonly = 1, srcs = ["@wycheproof//testvectors:ecdh_ecpoint"], outs = [ "ecdh_secp224r1_ecpoint_test.json", "ecdh_secp256r1_ecpoint_test.json", "ecdh_secp384r1_ecpoint_test.json", "ecdh_secp521r1_ecpoint_test.json", ], cmd = "cp $(SRCS) $(@D)/", ) genrule( name = "keywrap", testonly = 1, srcs = ["@wycheproof//testvectors:keywrap"], outs = [ "kw_test.json", "kwp_test.json", ], cmd = "cp $(SRCS) $(@D)/", ) genrule( name = "kdf", testonly = 1, srcs = ["@wycheproof//testvectors:kdf"], outs = [ "hkdf_sha1_test.json", "hkdf_sha256_test.json", "hkdf_sha384_test.json", "hkdf_sha512_test.json", ], cmd = "cp $(SRCS) $(@D)/", ) genrule( name = "xdh", testonly = 1, srcs = ["@wycheproof//testvectors:xdh"], outs = [ "x25519_asn_test.json", "x25519_jwk_test.json", "x25519_pem_test.json", "x25519_test.json", "x448_asn_test.json", "x448_jwk_test.json", "x448_pem_test.json", "x448_test.json", ], cmd = "cp $(SRCS) $(@D)/", ) ================================================ FILE: go/testdata/testvectors/hpke_boringssl.json ================================================ [{"mode":0,"kem_id":32,"kdf_id":1,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"0a3367dadc97e200074936b5adedcd5680f30672d1ec7158fdfcb795040ec909","ikmE":"1dacee520c81ade608f4fa3e5ccae0ecedcc7880e3fc6f3e5afd2e4af8396571","skRm":"c867f27c253f720c7074f9b4a495f2c690060629e249f86991bb55edf804f7bd","skEm":"ee9fcf08d07241b13b93f2cf6dbdd56f94e940d788c3e4c860f757a08974a883","pkRm":"8bd766c487fa9266ce3ac898827439aea2fa9c0099ab62da954b06f979f2141b","pkEm":"890e346283bf75af9d786a526c4a191b84d0110c794b6aa7e9a0b6205fe2c10c","enc":"890e346283bf75af9d786a526c4a191b84d0110c794b6aa7e9a0b6205fe2c10c","shared_secret":"85a44c9238b103cdaa67ec6ffde55d8f2e75e49aefcf1ade3c65900bddd503f2","key_schedule_context":"00725611c9d98c07c03f60095cd32d400d8347d45ed67097bbad50fc56da742d07cb6cffde367bb0565ba28bb02c90744a20f5ef37f30523526106f637abb05449","secret":"aa2c8768a36ce56c54a50a4ef93bdf42c225fa5cdf68a1f65c76b30358cdc478","key":"96d0b503c045e18f6e9f62a52d7f59d2","base_nonce":"aa39425b7270fcaf1c7b69ec","exporter_secret":"304296751e7583846d4ec1d49f78b511dee838a32e18dd1bfa44a30a1c1012e0","encryptions":[{"aad":"436f756e742d30","ciphertext":"1d2ae93bff2fc322a909669c94372cdd2ac0da261face2a706e417a952272f6e5eaa20d0cd15fc28ee52026c4d","nonce":"aa39425b7270fcaf1c7b69ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"db308d0077b75c29fd4ebbf3e3ee57312af210d2d2a795e882e8da0e5ae5a0775684fc8530aa0c31aea69755b7","nonce":"aa39425b7270fcaf1c7b69ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"ae1262b27b76a174a67143392dd384535bb8cd3d3a16ff971baeb81b27847238458e257c024f4fe52e1c2d2512","nonce":"aa39425b7270fcaf1c7b69ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"edd95930e4fe6fbacb8e1855b074124ada872beded292c353fc960564e09c7051f8b7f5ae944696ff4dde2c69e","nonce":"aa39425b7270fcaf1c7b69ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"90abc5e812ab0a5952f2222c12753821ab91e5dbabbf041e7fd21fdb13045648e90ddd152a183dc2881bd67528","nonce":"aa39425b7270fcaf1c7b69e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"36b6c4d62e98a62349015225efa47465704644125e7615c4891196a11884f137256563a8c0b831f51719c61aeb","nonce":"aa39425b7270fcaf1c7b69e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"a14504cb046f2691521cd9de3e5b12276eb5cc50d2817bef3557e08b3703f4b4ba0618127dcd667172e1d4c979","nonce":"aa39425b7270fcaf1c7b69ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"b2a39c3a10cb1d19d12af813d120b43b6ec46bd321a0d5f26677218bed6c34a67f24c93ee904cf69d61f0df4c3","nonce":"aa39425b7270fcaf1c7b69eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"30c6d7d697c8d26aceba2d65fe68001afab0a614ddeee48cc1b82cb8317b97e28e0e4424c189211edb5dcc81d2","nonce":"aa39425b7270fcaf1c7b69e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"8b6c5f1a4c27f89ee3580709229f496a6c61204bd2974d549d656680272edb6dda3b4580fb91147a619f7070c9","nonce":"aa39425b7270fcaf1c7b69e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"d4ed2cfb3cfd57c6d3dc8a6fc11c07ebda94c2eb176a9d4af1bd797f0e9bfbd718a28ef9b0f5568aba01ad4998","nonce":"aa39425b7270fcaf1c7b69e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"f671644f95ec222c6da648202d2a04bf1573d88bd283fdbb732d48cc643a88f08dbe954a7304fd7f65c98d3b53","nonce":"aa39425b7270fcaf1c7b69e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"bb07adf300892a6cb60480a0f678025aa1537472d01bd370f559fd7f804119d7e3fad41003eb618b48d7ffbc2a","nonce":"aa39425b7270fcaf1c7b69e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"b33504371b938457a2d4a0369ef400e7c8cdb3796989a375b485611fda1db61b7df5b2dd11f566e5d89ab1b81f","nonce":"aa39425b7270fcaf1c7b69e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"a224e7abe9c2905911d5053688b33e8695d8c293aaffdf4540f0f6054db656dec90c72b5fcd17daf7065e65657","nonce":"aa39425b7270fcaf1c7b69e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"781b37e555ab7d02c31c6414fbbce500d607290e75c0de637dd0fe1c48575260d1b67799d99c28bbb8f5415545","nonce":"aa39425b7270fcaf1c7b69e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"d1794d5cf67f0fe49a9c5afdc299f71d934064665b58e7cd3935145f5774f50f9da48299eb8119f524458141f5","nonce":"aa39425b7270fcaf1c7b69fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"2766a39f84486aa24c04326aafa7d5c02b19e728d921bd979ba8a9b9095f5b8c8939135a1e8776033ce618b378","nonce":"aa39425b7270fcaf1c7b69fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"c031311ef1a9a302a6a906a0ad70e8d35ee2150dada3333e4cd4d5af20dbb2c5e5cdff75f1e5aaafb2b6b7c5aa","nonce":"aa39425b7270fcaf1c7b69fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"9ded23ea08881341ef7c3c97cd22fc466af2b6afe455afc50f84f2bd3df06550eaa6fcfd7a5dabf05a9ce6d4b1","nonce":"aa39425b7270fcaf1c7b69ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"d9168b9a98ad05c723a404ca6a290eab6ce1a33cdc92ff3031c2d7f6c84599c2a900a5f1293100232b86eef82b","nonce":"aa39425b7270fcaf1c7b69f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"87f732a130360966477b817a1382c0cf5480f7f7621d09e150081e16a83ea74d76369e56a86f5dffa669ae5653","nonce":"aa39425b7270fcaf1c7b69f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"55cb0c7877d3fd62aa0185de229fc9e15b47a7bc876307dda3d541e236bf02cad5823f2b7041f40f6491000e34","nonce":"aa39425b7270fcaf1c7b69fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"120e20c06de63697e495df12abca1621db380b6ef2f9d748aeb208666b757967d9e294df17af9f1825db14ed6f","nonce":"aa39425b7270fcaf1c7b69fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"b81c227124217e51dade09a3bd140f030d9d39a1b2f84473a7afa744c43059dea17f6bd10f798b3becc12537b5","nonce":"aa39425b7270fcaf1c7b69f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"935afc24ee2513998ca37ca1909fbf9f536e52c2f0d425f24aa589ffc3e44d46a70025ba4c85a336dd8cf0c60e","nonce":"aa39425b7270fcaf1c7b69f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"0745f4766085e72e03e9cadbf161d68da530603cc4459917e7a77ca5ee07833b282fbded9d55a329165cdaae9a","nonce":"aa39425b7270fcaf1c7b69f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"532db0ff603a356194134fd69658fe4f584edc296320d5a44812781f34a49596bd1ad94697f17760cb141c1e6c","nonce":"aa39425b7270fcaf1c7b69f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"e7a471153746f4ef2e8c5044e7030c944a32ccc8b516e9c62d101115d080e6cabfa3bf54cc44b0774b02893ab4","nonce":"aa39425b7270fcaf1c7b69f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"6e6e2a6e2e6d9a98b5c726f55755043f5a133e31d8c853cdc74a72dab862a3aa3ba703b6cecf9714b75832f758","nonce":"aa39425b7270fcaf1c7b69f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"3c1ae9df0865a3784c547c811a7544618d0839f316706ad2224329e66d3b409c095e2efcddee6850c90a219209","nonce":"aa39425b7270fcaf1c7b69f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"d51aa34842e127fb8a5a75427609d05acaa6df972b90671294e3a9cd95e158351d4d30e8859bdb4c94632e3151","nonce":"aa39425b7270fcaf1c7b69f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"3e41fe57509a417274ca3b0bb438f8d024f0fa0a20aeb37d334c173a4990e3157a9e7c373056d6c489640f0858","nonce":"aa39425b7270fcaf1c7b69cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"878a220d65f909536b4f5f5fa6bfadedfdb7af717df0aeb07dc27c571884089a8f1d3d270cc45a4ef1d7cd0afe","nonce":"aa39425b7270fcaf1c7b69cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"e4fec60771c10320648b6099e0dc5abbfd008156eb41e1db10fa50a98385a1be325ae21a25e5afe4db9b4b12dd","nonce":"aa39425b7270fcaf1c7b69ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"0cbdcd88d7f67955687963fb477986754acf8d4c78cd1ea5d3c1d2ee0d91828223eeafe772306f063b55f380fb","nonce":"aa39425b7270fcaf1c7b69cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"d2c37ab9f846007512f0b19a884db8ff51c2282e312e2108b03a97c20bb30201a3ec86bb99f3f03741e4c717b5","nonce":"aa39425b7270fcaf1c7b69c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"b4214dbec0ea42951fefce48f3a9a59947eaf57f96fcb694925c5506a542eeb66ed4726e930cedb7126028bcf3","nonce":"aa39425b7270fcaf1c7b69c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"333270c2cbe0aa0b047817a3038a8568a0935a40e066dd328952380908e9ea332a9e66364aed9d2e755480cb3f","nonce":"aa39425b7270fcaf1c7b69ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"24ed2ab293813bf65e260a5ca073241f43ae773820804dd44f228f34de0796d0ca660a50af6c5be5b84183df65","nonce":"aa39425b7270fcaf1c7b69cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"5a1624b384a5997af6eaa9e751fdc222a63a8b48c11a1175a3a7fcf9c766eddd37e182e107d3fc384258d78f31","nonce":"aa39425b7270fcaf1c7b69c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"2c41cf9b02d41be0aab17dc2b18f9890454a4ea3060f0c87ef22f3c313c463829df833bd42e1727fcc345c53de","nonce":"aa39425b7270fcaf1c7b69c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"efe9cfe3dd9f17d61b7ef48960c60a86e51f4292583e8395648e62278fe05a32c8bb40a3524658a823650814f9","nonce":"aa39425b7270fcaf1c7b69c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"d05ad98aeab2170c05b7cf622b2b1ff0252543c845974be88c64afd19b9bf5f8db23d33ccd24e2298da94d5308","nonce":"aa39425b7270fcaf1c7b69c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"a64b0f0a87b37b28f5acb75b825ea71223c83b6c71f2755d269a392bcec696093b1d406b82a5983de804e295fd","nonce":"aa39425b7270fcaf1c7b69c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"e6fd419f4cd84464ebe505d909bb62ef16e5d493c1d19294a800ea91da4e929f4c407d37ac0b7a61099c821560","nonce":"aa39425b7270fcaf1c7b69c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"99b45a2e3a53e6d5fbcc0d4dbfc3408944a9ff84eac764badde05ee0af7b8e7206821219dda0d838f78c2321b4","nonce":"aa39425b7270fcaf1c7b69c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"91d3a11c90e1b250828d2ec5665a5bc0302985798b513b67a84ce455f9fa1438d486fee1987bdf901a16ba5ab0","nonce":"aa39425b7270fcaf1c7b69c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"57e350cbf7afec4a8d75d92d1efb669ed47d49ccdb4b11d3fcb5468a66edf6bdc2568e904d84be91f62fc96b4d","nonce":"aa39425b7270fcaf1c7b69dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"d1202b6cc08a86bbb8e79c6f5c70259f0f95f51eb5a0e3aa25e082fd6bfeb4ace75bce103c051649e22f5598d1","nonce":"aa39425b7270fcaf1c7b69dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"930bb3f53d4f74b16ad9dea7cd15e8325924043bf1988e31f4030cc60586f5b025e71ff24a57755b2752e901b0","nonce":"aa39425b7270fcaf1c7b69de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"68756e5a97758b8a227b8ef2b6ab941f2fde0a6542ceb1419e14db3d0e25ecab3c625caf025048a9980fe17bdb","nonce":"aa39425b7270fcaf1c7b69df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"d48a3f52375b35626c5cb718a713c25bbec8d59d9c3636bbdb502f6ab5de2d12e5924b7786048aa8727cf07ed0","nonce":"aa39425b7270fcaf1c7b69d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"6fa662848e2065f327069382b38f582f32fe642c6e6da0fa4636472b9f45e825417d508a44cde924c45c09d7b9","nonce":"aa39425b7270fcaf1c7b69d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"96a57f2bdd2dfaef059bb3f2b56b86948e7ea2d46b8eb350687c86d757b47667f17640cc9658dc6d6d292900d1","nonce":"aa39425b7270fcaf1c7b69da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"c80a022ee885d9523691c6b08318fd84e4565c87a3b18c26cb57972a4ca22108ed01b4cf65a024b812f9b23eda","nonce":"aa39425b7270fcaf1c7b69db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"bc4d77717c81cf86eb2b67873e5a018164caf8f99ddf02b3a4a40bf9c142da0a9b55b717dd65698a77e2cdbaf7","nonce":"aa39425b7270fcaf1c7b69d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"8686f18253d1703350bf89d8efcdd190d5b15a906c9eec926132fae636c1101cfd9925a591b9bd14cab8cf92c3","nonce":"aa39425b7270fcaf1c7b69d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"7fcc91a68123b193cd7ffcd628558d690439cdb77e7e0f20d1e9eec033a16c3853e65664bfc4a45ed73c593246","nonce":"aa39425b7270fcaf1c7b69d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"9545671024ec1120dc757e24cb64bb3bfe807047faa9d67f045aeda23841c69599583bbef3083dae9833c78e0f","nonce":"aa39425b7270fcaf1c7b69d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"426163356e776435e8e11ffeec243660f4f535272e215a276d3ab925dea7d46d62d371060a422068daf76c6b11","nonce":"aa39425b7270fcaf1c7b69d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"faf2c79412856b6e630cbaa80653e72ffcf8272a48a0be945c5efd1583d11ad09508ada36fdf00e12a4eefc575","nonce":"aa39425b7270fcaf1c7b69d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"8add0990e6b642f507828c6d8d7a334c921607fb014ce3de7e88f2eccaa54c96b3f687d425f7ce4936cdecca96","nonce":"aa39425b7270fcaf1c7b69d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"1712770f74d7203037ba58a604b9b9ab85f7422b964e09030b1abe4e94e3ed87031e39351eb3e7110fd41e09db","nonce":"aa39425b7270fcaf1c7b69d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"eb593aa8d9b07de951232627a78f7e0cc012d50965b91ce10971bc55798561a1212a0270414095ccdd02cbe15b","nonce":"aa39425b7270fcaf1c7b69ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"49e0f25f39dcf0346dfae474d101eaec8f359c8e6fcedf013d4ba2484555e0ef2cea4a4b326df00ebff00b9ae9","nonce":"aa39425b7270fcaf1c7b69ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"4a06727544c172b5a835d39192edca790e0a2743d6da616b0b0e2edbcada0ebb0e38cb823da8fba4ddca09b315","nonce":"aa39425b7270fcaf1c7b69ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"b1e0d07c7cbc6609765648c202e3e625a95a4f362f465b01f8081808be3ed15a3c42ec199332c401223673312c","nonce":"aa39425b7270fcaf1c7b69af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"62d83995435e6f714ff8e8aeebb6ad8370f8025915deb73bbc29d650ae644b75f6c08220a4933247983aa64280","nonce":"aa39425b7270fcaf1c7b69a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"96843cd39037445382b873172316d9b6d5339d4bdc4554b1eaee4b9de74ded846e0495a517959d95a5d2fc922a","nonce":"aa39425b7270fcaf1c7b69a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"5ff47373de13249fdb7a974b6ff02ea359603da5bcb9d21a4ebad27b01aa8446bb6e5e71ce4d99f4a024fefa1a","nonce":"aa39425b7270fcaf1c7b69aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"9b2c19dd01962f3ddf62eb9316d5bcb58238d3081ac2de88ec393198889e4500f21697d21a544764ce5dcef979","nonce":"aa39425b7270fcaf1c7b69ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"c6a626a34298c6731a399d0b8447ade39e6043fe081b9a214477345364cb061efb86574b52d051f186c27b4675","nonce":"aa39425b7270fcaf1c7b69a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"7a852c748d02c768efcb9c2764bd827a7862cf0ecc99216b57e0af12da2400f00c1fcdecf6de177259a4e5fb7e","nonce":"aa39425b7270fcaf1c7b69a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"f784d0a82f0f042adbe0e7131a829227760b31ef28377d967c80d905bbea64464d42c58a7a89b4221b8c4f0e1c","nonce":"aa39425b7270fcaf1c7b69a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"9fdaf9f447996a7b384a6ade7b07f4fbce8c37f54a57cf146cd823cf91258431502422ea9c39fce5cd63a4506a","nonce":"aa39425b7270fcaf1c7b69a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"f94749cf4a852bfbbf8baa0a0a65e1947ee786e29feb0f48cdd4b9f1808800934bb1220e637db7a7e534c66b6a","nonce":"aa39425b7270fcaf1c7b69a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"b67e26377d97c2540099cb6df17bc2d9e5b9e947535be207adc04f8f36b63e14867364ccd1e1dce2aeacc6e38d","nonce":"aa39425b7270fcaf1c7b69a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"5cbefee3fb936665c906b78f47415724240bb94c56cb8d51582834bf9ddaee79eae9dc77458599ca2980f44646","nonce":"aa39425b7270fcaf1c7b69a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"c35c79e7cd9a6bc675db9b87a8f2c1990eb22e1ce04cf4fff338c5331ad132e0cc1d25f1da6d172ece852c98db","nonce":"aa39425b7270fcaf1c7b69a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"cad29b671ecf8cd5bddffe39d09e5824a899f1807bd1e47a2f4ae93bff7acb2c473b64308ed80d54b21cd975d9","nonce":"aa39425b7270fcaf1c7b69bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"0d9b81e4313e0c2334f4b2b5366d8ad2d9e2f060ca3fc2b6e02d2a7cebbd20be4fa1f5ba6f339656f62a1c0aa2","nonce":"aa39425b7270fcaf1c7b69bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"399c03181c698d704da5b294c60bcec70be3423305a53c6b5649c3d3db02710ff2ce6e335a5acb1415184587fc","nonce":"aa39425b7270fcaf1c7b69be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"be351a29901231ad773a517dffd7cefd15b9508ef59b5c148de2acb9c93835899027afe6d754389bfb6ea1c00c","nonce":"aa39425b7270fcaf1c7b69bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"8eb930635a637a8006080c7dd018472ef355a473f5709e99f6ca2d78905aff407050e743e8908ad5c06409715f","nonce":"aa39425b7270fcaf1c7b69b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"e839db48c6b9bc8864116c8467030024faabda7a9e76134c6e76f6d717deea95e98013b8d704684f5d59d0c5f6","nonce":"aa39425b7270fcaf1c7b69b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"cf4a37268d559688135c014caf86181d3706e61ab3588d1b7c445d3bb6261cc3627e84f9d372b095ca6c203d5f","nonce":"aa39425b7270fcaf1c7b69ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"da644855175c6db93864bb9de9ada481e5d59587630e3ece51ba6669b43ad81a3051767c0cea1498836cb358bc","nonce":"aa39425b7270fcaf1c7b69bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"e0dbf28b3e1f70800438ff28ab04d26d607056841341d2dcefc5bbc1731a9e6d55629a937e011543dcfe88513f","nonce":"aa39425b7270fcaf1c7b69b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"c66c6b5f9aaf53be6d5481013de43b6a965137605eab383b8fff0bb31625e7db67028d61fbe575f55027e8b4cf","nonce":"aa39425b7270fcaf1c7b69b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"f56f89d4453899018fac7e0b05bcce03b543e9d898cf7a2dcfbb249654c01d6a6bb99776959ad9af66d1e53dc3","nonce":"aa39425b7270fcaf1c7b69b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"50ecf6094f6f6c7f7a9bd9a1e1f193090e0244fbb63aec35a53138866bb3a1e5545d2b7ed7d30366d57f1fa640","nonce":"aa39425b7270fcaf1c7b69b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"782991370a57776aa6d99980117fc71f5002afef9d313984a200b80fa88f6d75f3e981e7f03c16ca9cf8c20c3c","nonce":"aa39425b7270fcaf1c7b69b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"4bb859faf17952ebfa8a6c7b75b331f4247dac4960ae4bd6cf229cd162543c8631fcb1d4a9c3309aa3d3d867a6","nonce":"aa39425b7270fcaf1c7b69b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"39f2175bd88fbf9e92f50fe3f06f20360db95b8d3ec2fb64bb64880a15d3738eae9a8f07d4538850f1e80a7b62","nonce":"aa39425b7270fcaf1c7b69b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"1e8c83d1bf0dd02a4e837d448e8576dc35055e66cbaaaae31227053b01e45b488923f1b0849c75f19bd5e9abb5","nonce":"aa39425b7270fcaf1c7b69b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"7599ca5023399dee04cf3c1b03f03577fe3b4ca6e8855cbb0662393477342e041303892ea0ad419ddd951100c1","nonce":"aa39425b7270fcaf1c7b698c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"92bff34fdf341cad9501ee635d35beef79f790208bd11c66991b54491d402badf86ddae0fe2b86cacabbf48a84","nonce":"aa39425b7270fcaf1c7b698d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"5608e67b99d473203559d7d926a9f3ea3d4f34e7ca07332928a4f2b3b7ca8699d774e731d4f1d43c11402409b6","nonce":"aa39425b7270fcaf1c7b698e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"1878c54cd9312c70e9f7c14b05c19f25dee49f688e6c6e267a8afc6c88e8ed47207ee0fe54292536326c1aa9fc","nonce":"aa39425b7270fcaf1c7b698f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"932293c1966e81eec76e8b27b1e2c884efd3a757d13e31fc345a5c08c80c1d65521d9aa49e44bdb6e83d1f5868","nonce":"aa39425b7270fcaf1c7b6988","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"68b29e42259b741e3c6e1f6c70a13db1d47815d03b21ec0b0121d64da1fa37d7fbb2013f5377d1d7b4155fd730","nonce":"aa39425b7270fcaf1c7b6989","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"99eb9aaf35c31bffe117ac8cdf2197cea33da3cbdd4ef5f9d5d15f38279b5ef83d7bd79bc5cc985a80f9671fd5","nonce":"aa39425b7270fcaf1c7b698a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"9d6eea97b25dd801f2c7d5fe30eed6a3a7343e92936a4737831c055233fb80db944185c06cec615f0431f787bb","nonce":"aa39425b7270fcaf1c7b698b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"2c9f26f4ec4c1cd2776fbb72ad0bf5e13675dee4c3ba5555a5fcef3536e9fdbb01dc79578f946339918bba5d5c","nonce":"aa39425b7270fcaf1c7b6984","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"75b2a056fc92ccf2a072bae00f1ae657026e37cad22ac2c9d47712e080b34dcc1bad93669ac3ba02a9e47ae619","nonce":"aa39425b7270fcaf1c7b6985","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"4ee66c79ef2b77704bf5666da5e53f6c7aee65383241a1a68c554f0aa5bd7b318036615fd392d22df9acbd5124","nonce":"aa39425b7270fcaf1c7b6986","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"ed2e2841ac0f73165c6f9e84ebdd903d7b7bb93b50b936241a104549a294c3a95c418da78f99f3c15dcd15ecf5","nonce":"aa39425b7270fcaf1c7b6987","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"b88f5d14cc838bd34802a16e1776a316d970ab950c2b45ca4fa25700f92668835dd7ec74a709a1aefd82bf3eca","nonce":"aa39425b7270fcaf1c7b6980","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"f8102c6fdaaa93358f225c3630c5b311aea60f42be35ee35306122250447ebf7359a8fff39888e02233253ed1d","nonce":"aa39425b7270fcaf1c7b6981","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"597a5fb99e9127e10d77bcffe268e87ac82d2be3b65b9d808d9f65f64383a62267c86f3dcf67d111a50a2ced73","nonce":"aa39425b7270fcaf1c7b6982","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"a7e1cc511d6b18d85c3670953bca45c2a451f7acd1029a58bfcbb6d490d0897e9d553e718992f450c218cb1b94","nonce":"aa39425b7270fcaf1c7b6983","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"c761b04701ae13fe1c5e7a96d22eca0f3fdd8b519b979c9d3329f1a553476aa65a92b1291bab821910b9ee8d32","nonce":"aa39425b7270fcaf1c7b699c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"7f0565c789c9230d103a587cd90196d34c471dc9fb7289a61d720167df7ce222b045807aede5fa8e1a6bee97d0","nonce":"aa39425b7270fcaf1c7b699d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"d7c048a61475a9007ad16269b5a2855b6717f4df08995e3a4228d2b69a6114bf37e69e80ae5aeecb7ccfe33fe8","nonce":"aa39425b7270fcaf1c7b699e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"2994f004a3482cd52e10e30f15901b06df52823fc338a1609ec9b513478132cae2d3deb4fa8c9938a3aeb543f4","nonce":"aa39425b7270fcaf1c7b699f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"1251abba4e32b06ff56acb305ff32a0779526262f5442dc23c182873c313be5c45bc12c030ca4a82873c52e3d4","nonce":"aa39425b7270fcaf1c7b6998","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"7051a631663db8e95c04ea4e37bf307253671892f1752efa5aed590dfd518aefdf60aae8ea41fc37074e520b4b","nonce":"aa39425b7270fcaf1c7b6999","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"a2aa79624f07ca6f81b947dff8f5e6dbf654b85e98e5b41b5fd963dc9e3cb99d1198ddb1a28880b923fe8b27c8","nonce":"aa39425b7270fcaf1c7b699a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"ca4b3e7800ef6e3fb1d4bad284f873b7d22f3c2f6bd0b1589f6c3ab489cef2c07549b99551395b656ed84671a4","nonce":"aa39425b7270fcaf1c7b699b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"72cda5a2adb031e3555d8cbaf8ee652fdb51f6febc83c8edd2222aef06456981ebefbb702b2bfe2da29a90ee73","nonce":"aa39425b7270fcaf1c7b6994","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"39e4fe7ff33616fc0163c3aa26d161f168795b98447569ca17413bb9b27f239e5156bee1d9803214f18a30f2b9","nonce":"aa39425b7270fcaf1c7b6995","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"949da93dca6ce1632b8fd27f1ee7bf0c9afdefb7d26ac02c7bd7883f5b96a51a47e8eb53d66098769dcc07f804","nonce":"aa39425b7270fcaf1c7b6996","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"258bd42d7efcc6ba72131e0fdc5040fa4d8e8089fdc20170578aeac3b87c5e71b783f2a46858716d1316acc037","nonce":"aa39425b7270fcaf1c7b6997","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"33e9d4a56a4f2412b1634ad87c75c296e90793e700f5f4a7fddce05a92d7851302b753c3ae403d0e482d1b60ca","nonce":"aa39425b7270fcaf1c7b6990","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"da0a9cf0afc7a363755c583834f04206a101eb1335c041b76dfc0d67ae8fe1cfaabf0a5bdda20f32b975d00c8f","nonce":"aa39425b7270fcaf1c7b6991","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"ced8909d397009e64a59eece25b2e6fdc2b74bdce98b7444e3a54d954fa64915c77796cda618791f07edc266a5","nonce":"aa39425b7270fcaf1c7b6992","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"5999426f1345324bbbb8a261754dd97e0364709cc649d1ad0177898f85fd2933231899f382de30a574199edea6","nonce":"aa39425b7270fcaf1c7b6993","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"3c760df760bcc6cfad8b250d262adcf2b3243ddff6e6b57c5a4a2a50d6d4ddb6f2c31d9e749b03a3328a82f3b6","nonce":"aa39425b7270fcaf1c7b696c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"bf8490f370c92a2360333fc609c49bea7ed46fc743db1a33e641a71dce485c8d4390eb011cccce41df80edad4a","nonce":"aa39425b7270fcaf1c7b696d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"eb51bcf3049c35393538f6e515513ba968cf0c9b7a38741e449d229838e35a8fcd3200d02b2ccd410b2cb76e11","nonce":"aa39425b7270fcaf1c7b696e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"36343b4dcaa594264c59896b8b7b6b97f395a8464991e2659adec3f615a42c19bd471bcf05e9a492e80d9eaee3","nonce":"aa39425b7270fcaf1c7b696f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"27461b4a4137b85d8bb68b52a46f0d943ce6d8fb5d632d84ba60ac440b56ac9b35b9e073cb3559a7e0eb90b6e3","nonce":"aa39425b7270fcaf1c7b6968","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"8d972d984afc35451924c80269e23b23bd8ba372182dd7bec640982bd30be88e7a328777b8e193377d22198880","nonce":"aa39425b7270fcaf1c7b6969","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"b2d7301db171aa5ba49080f5a67019f4e7a403ceb202d3a5e3a458e7d4232c7eeae89fc54a17295609e4710df3","nonce":"aa39425b7270fcaf1c7b696a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"62ac8f7a79da90a6bc97e94a4bb617a2d7896cdcb142472d2807ea8b5e62ac116c5a92d0d10b8cfa4d0b2f73c7","nonce":"aa39425b7270fcaf1c7b696b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"890c6b692424ba3d1844d7ea03b070b3a9c5fe8762ab48c18c3041024d1b94cffba8561e95cd03ce64cabc3926","nonce":"aa39425b7270fcaf1c7b6964","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"d3af8dc528ce9b47fe496681aa8432422ca63b3f61b76d287f48d43460771e4136394ef1074db5f87523546764","nonce":"aa39425b7270fcaf1c7b6965","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"8de2f7ced54e6f9175527fe6ae4d869c2b2cc1bbf4c60a2fbaee84e0be071c38aea4734d3f1548fb50e0e40c45","nonce":"aa39425b7270fcaf1c7b6966","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"a511eda5aa00e40af8394d7dbf54bd773ec5086ddd21d059aa699a215b2af4322de79cfc7f7c1fd945f8b9b1c2","nonce":"aa39425b7270fcaf1c7b6967","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"437ab1b7c2538c67d6dc724da53980bd756f06e1c8f07e41c8a0ae430f2622329c4795894d436150d4437c8cd5","nonce":"aa39425b7270fcaf1c7b6960","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"a4945fd326373a220a87965d343ab5034170fc42a00af2a9a067ac2428800a85c892b908744ce74d39217486c4","nonce":"aa39425b7270fcaf1c7b6961","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"90b6a50bb345fc17cd66ed612a8d24fc9670b3b0c740722e0ab44378ef9912794068eb7921ce97f2f8a9b28f94","nonce":"aa39425b7270fcaf1c7b6962","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"5171785b9022f500628f1fd864168e2806ab2c50ed8b91c88794cdcf5962a19c9cb83089d50b3ca90e0c93d9d6","nonce":"aa39425b7270fcaf1c7b6963","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"2c1597c05052cc6037b038603c246d5d7e8117a95760568ae8828d93d91a6c72418740803406a325520a04c49f","nonce":"aa39425b7270fcaf1c7b697c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"391ce3692f558381f66e12e08703389cb253b5765a2a301df13f34f973eb441ca7c15e909ab3ff4b7c84171c90","nonce":"aa39425b7270fcaf1c7b697d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"c8588682821278b7defd13998fe42f84873d7f1db719e2e0dbe47eef7eedb80619d011c8aa2169b761c3b55ea3","nonce":"aa39425b7270fcaf1c7b697e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"3232f373d0257b35120f659f6dcbcfaaed019eca4b2f59f408b964a3fb39569e22302e8fdd9340a56699f97a45","nonce":"aa39425b7270fcaf1c7b697f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"bcdcfa18d726c38bb496850628806f2e4d7356f032e01472aec01a565b23405142ce3969372ae10e416846f821","nonce":"aa39425b7270fcaf1c7b6978","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"4390558eceebfcd1464dcfc6ed48cc2e4a75e6820f414695c8366cd75de448e10dcd368e1c33e6366a335d631b","nonce":"aa39425b7270fcaf1c7b6979","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"f24c2cbf61c02d130eee783f02c618641a7ce8fe131c541e9c4cb03bf276bf52599c85383f9e597aa3ffdb8e7e","nonce":"aa39425b7270fcaf1c7b697a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"84f36376d9982f5e438fe74654c36657e2ae872db0803e88ce85b2d1296fe68b961a090c907571af3a5039cc1e","nonce":"aa39425b7270fcaf1c7b697b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"46168e0c1498f6b68a854f69ae9f976e862aca642f8b61cbc6f4d7951ad30283d0a4dff10d763920862bd318ad","nonce":"aa39425b7270fcaf1c7b6974","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"48b667ecccbd8ad529db74ea44b99919ae933bb31c9ac48ed3c62270707f4ac0aae8aa79e91da3c6841f1e3a22","nonce":"aa39425b7270fcaf1c7b6975","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"995c3d826bb37d8bff6fa1cf81fdfda7d29429635e8e4b187249395884154cccca060eb7ffca4266c57b5caa3b","nonce":"aa39425b7270fcaf1c7b6976","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"b83a5faaafa75db21b5297d1c0abfed578c130cee3e77f64146ed7f5bdfe2db07065bec4ce7cc24b7b5902d402","nonce":"aa39425b7270fcaf1c7b6977","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"6d99f03d2d79ae06bef1772b0f9966a3c4e0f6de556b9ef943cac06c5e47881909e24027129978c90c62ddd9c8","nonce":"aa39425b7270fcaf1c7b6970","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"fd701cd8a0a292b496344549ef0532ba3ed92b16a0798df83f38531ddc87dc60e8fa1e9fa56f14bddbbdd70945","nonce":"aa39425b7270fcaf1c7b6971","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"788b1d8faa155e07cc6abc63ebf4eaaadfa4fa8f4a1e14e05de209218f98621e002513c4fc134ee7ef1f79ebc0","nonce":"aa39425b7270fcaf1c7b6972","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"e752c6365639f40fe4d8628a87c122da3b70a4f2132b010142c82c09920d25cc9e6c01b7fef131f3abc138ac3a","nonce":"aa39425b7270fcaf1c7b6973","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"140bd64612dff91be580283cb650b24602a72aa4fbda8dfb18e3ed411a06962910bd8a958d5ea9bbc5efeec8c5","nonce":"aa39425b7270fcaf1c7b694c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"61cecebb58880c93dd5eb36f98bce9f249bc43d5ee219a1fb07bcd52c870deddfd2a2773529bbc21410853c883","nonce":"aa39425b7270fcaf1c7b694d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"02b0626964b199dc48e458ae94a64b38c1372f257906bd7e8443e2f5f54fadd6bea40d3e497a5c0fe799a10b85","nonce":"aa39425b7270fcaf1c7b694e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"2071cd77ce0780c88e2e42829a786a7599004cd473e743af6912c14a017215911f7cac0ba2f40a7e6747ff43db","nonce":"aa39425b7270fcaf1c7b694f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"c17fc9824c08a9b38a77a09d453a3d6e2c0241e073fd095feced2192327ac63011ccbe5ce432ff4152fe268abd","nonce":"aa39425b7270fcaf1c7b6948","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"01cf024223b5d340ef4850cc9591766a0e3c0c7374c676cd2f29ca0bfbc0f00b5785f29770ea3f7649f3d48af5","nonce":"aa39425b7270fcaf1c7b6949","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"bb53299e3cf452f98c8d6decd91060825f5ce8d8d29a8e1cea39c0bd4d4fd2c2b724f4e3dc07b86a8df2324b4c","nonce":"aa39425b7270fcaf1c7b694a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"955ba6ae6659a46f07d1d3716969c385f22a02a22a0843ffa24d8b3805f15a655d948387044686e3b45a7c5cb9","nonce":"aa39425b7270fcaf1c7b694b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"7a174c192e4360e669721d2ace9d067596fdf4a118723213b2ec3433c3fce4e5981246b05d2b4375615e57ba7a","nonce":"aa39425b7270fcaf1c7b6944","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"15ab180ebf15b80511efabeb40a279563b3953506d5e97323e78f0715afd02de20be59c123dee680b8a2b58b06","nonce":"aa39425b7270fcaf1c7b6945","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"bce9ee079f51f941f6c5dd0042188a0012ce87ac9b4bd5f220f3e39d2a944d827f90f8212f205d56711cb02c78","nonce":"aa39425b7270fcaf1c7b6946","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"f768c9fa4092e2f9b2a7033b64ef6b1c0fee88fe649e4473149d05eaf803add03032b941179679c69691d65e6b","nonce":"aa39425b7270fcaf1c7b6947","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"09af3cacdf11305c2177ff3e768af6d2791656c64b791c57d50417af71238b1d4e3e8903f04736ba6b0bb72ade","nonce":"aa39425b7270fcaf1c7b6940","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"623b4ad4b196364a59a57a961034dc95efc79ce01ef533f65600d89fbfeb33d11204fe13504388dd0c259fb70a","nonce":"aa39425b7270fcaf1c7b6941","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"983204e6635ebfcaac7a7509fa92b5375ed36fe5562e740c8fc7be5387be3ddf49d76109c51d62dc9e65d171ad","nonce":"aa39425b7270fcaf1c7b6942","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"5e8f62a9caa29f757b267e8cd2693ae11bf362c07ad21a346217917993a118e937c066d02f51f5c8d29a3183cd","nonce":"aa39425b7270fcaf1c7b6943","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"f0b7c013e758428f7a5c7a59403cfdf7ab6799dbdcf226142c61883cc1a4dd3540e913d6ea081d82d532217733","nonce":"aa39425b7270fcaf1c7b695c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"4f8d9635a8d0632113c576642e07c1ec0e4f5233e5193e96a627823fbbe30162fc2459e04c73ac0b3c693dd492","nonce":"aa39425b7270fcaf1c7b695d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"08c79c930796e36390ad95bbe9f38948442f941086e2f87f9c6e3ae4460477fd212499d1a2f5a20129c7af320b","nonce":"aa39425b7270fcaf1c7b695e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"d8d4144b717a753d36095b29df850a4d99fdddb87f1929ccb54b0075274d471458a68faa268d6ce99c5723d2a7","nonce":"aa39425b7270fcaf1c7b695f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"b2aa121df2f13d6da3ac31e95f2d33a5a87a6540fd7dc5e97b977ef7724c8434b01e222f8114e8aa368e1d5d70","nonce":"aa39425b7270fcaf1c7b6958","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"cee61b4209ff9dca85581e4083477ce4adbf7ba0ae01693a437a6ce7ae61f0ac0ef87d04c9098b631efb31b04d","nonce":"aa39425b7270fcaf1c7b6959","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"cb71b47d9ae8c5a9dcd00e99ed5f142b096c3de2534cc32568537680667ca3c6ef18d453d079d5c50bb25c65d9","nonce":"aa39425b7270fcaf1c7b695a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"3ec796ef1a4e650306d48408a7d746c11af427b9eebcaf9ab1989cf62bd502da3a1f8c9cd4b04050b5027a66dd","nonce":"aa39425b7270fcaf1c7b695b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"414bb5d18d0a14c563e16b642c57f2f73b2d0f4334c8d17b8f2549fb3eb8a918d5af74535a52dcb2444eab5423","nonce":"aa39425b7270fcaf1c7b6954","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"fec19cdfb2417b91158e79b6714f29a4e69f46176161036dcb2e6d375fc6f2f0cf3859dfe3ab6ca31831d4b3fb","nonce":"aa39425b7270fcaf1c7b6955","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"dc0154d58ee5fc233bd1dabc885ab4cd20de9b20f005406611f8db7adbc7ba2eb0756b21ef9d45477275512a16","nonce":"aa39425b7270fcaf1c7b6956","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"99c2bef351eee9f71d1147ecb56afb386e63560be4d4354caa130a48e8c37f751a1a6fd77c118097cef357c07f","nonce":"aa39425b7270fcaf1c7b6957","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"e57a70b63e907be903dc3dfa0635ab899baee8b7053546adaae082dd00bb37f0076e6087968618450c1db52ab7","nonce":"aa39425b7270fcaf1c7b6950","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"ca2df6daab65f06f8dd4e910f118a40622745d9fc73db467153a7bc6459acb6d00a8499fab64e195521cba2b1a","nonce":"aa39425b7270fcaf1c7b6951","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"c5eb2bf93c44d452f70423215267ff9a7410381070b33f0f7b67f867c22743580e01b97e407e297747f70eda18","nonce":"aa39425b7270fcaf1c7b6952","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"c6a050a8d9a1c5482f3007683fe3240743d792665d2887b2daf9f39f53b54cd1d3ae72a566e5e1d310e8bbbfa8","nonce":"aa39425b7270fcaf1c7b6953","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"68fc2ce2746b4104e3cd933d40874d42cafdc2b8a322f3132dbf7e0b3a44407ae6565b2741afa5f49be6a6a8f3","nonce":"aa39425b7270fcaf1c7b692c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"d466ba58f57f4423fcc5b205d46ad4fafba81bce4a524eec07dc7626273dfc10823c1dedd9349a90faacba8219","nonce":"aa39425b7270fcaf1c7b692d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"443598894aaf607abf146feecf43f2677bb35ec0759c92c692f1c49a2a550075693f2c5a6d860e907a3f16af43","nonce":"aa39425b7270fcaf1c7b692e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"931646d1cd3155d13152b3d4946814ed95e3d4231f2a73d32d71ee3ffa0b7aba41ea5c1b8c52141aafc690fa9a","nonce":"aa39425b7270fcaf1c7b692f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"60f4356f1f805bc586324a9960f2398d54e0e97bb71cd5f71342ae48aec2a869d7deaf246f40f1d8791451d617","nonce":"aa39425b7270fcaf1c7b6928","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"c23dad3a439bee4c25dc5eb27a546af7e3b125b90d4e244cff7e1031460eb48716a0ef89aea28fa3f07bc9f3d8","nonce":"aa39425b7270fcaf1c7b6929","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"609a043b57bbf1f970a619755115c090782eb4538cdf32b19b8e89a486b684d24f3a76f5eefa626f18d5525ded","nonce":"aa39425b7270fcaf1c7b692a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"75c857fdd58149c70815101a77bcff4aa068362fc2c0554832f0a0e1f3cdc2ca1f9e94bb8e0dcc323e54b357d8","nonce":"aa39425b7270fcaf1c7b692b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"b105c27c8ea822ff9a5a1781ce0d674ac574ed080eacd575938707eb71231ccb39eb9a3bb3edccee584c40ebe5","nonce":"aa39425b7270fcaf1c7b6924","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"bfcd51982fd224426377303da020957445a6f4f511c03e52be881a470486127a4a80d5c34365ffb6d74ae5991c","nonce":"aa39425b7270fcaf1c7b6925","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"e5b8abfed4498b3424415bda6777175dbaf064d6b558cd89e3658fc2efbe847223fa28c26ae8529fc5ca440518","nonce":"aa39425b7270fcaf1c7b6926","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"0919be84c9e11d9915405e9d5eb08f2c8bab4499f5f4bacd93b2c95bf62126f63b142956800a3c4ab70995831c","nonce":"aa39425b7270fcaf1c7b6927","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"255560e183c0b42eac5fd9937f0d3fd425435e0ada5d8d80357cc136db2545fb0018297732b5e42cbaaaafcf53","nonce":"aa39425b7270fcaf1c7b6920","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"2beb89e3a8688caaba2ceb47379841298c72e144ccdcabb8d765186d7c2d5a8167fdb26ee5b9d993f1fca148b4","nonce":"aa39425b7270fcaf1c7b6921","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"3167d242968980e0c47f45fd80d65bfd9d990dd49f5e5eeec5951838022e40ad143ab1f6db3e0ebee4d842540f","nonce":"aa39425b7270fcaf1c7b6922","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"734ba58d0fbacbb5441ea3d67b1bfe4f5aeca7c7a9b9e9812cbfa4d61dbdb918655d564d3da94885a9e9a8bdf2","nonce":"aa39425b7270fcaf1c7b6923","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"d174d71c4df06e1c5bc8f220a7f42eb61d4ca90fc80ea2c6fbcae44949421772c470f6b33ef4271a44a3f019ee","nonce":"aa39425b7270fcaf1c7b693c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"ec9aa3a07394741299c4a1024317290c067cb0b5f4fc283690b671e7a0613e6971b93176c16e28abd9ed63bca7","nonce":"aa39425b7270fcaf1c7b693d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"c8ddf87e2314f611dbaf0a5db4b6cdca1254cc3d8fbd97f26c14e88dfeb46e2bdaf9375eb3b9df5bcc8836b285","nonce":"aa39425b7270fcaf1c7b693e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"fd1adffad2e7552ef9034f69f04de537046998e6413b57de8543d055a1a0d9475ace2ea2c5f3468447b619c6a3","nonce":"aa39425b7270fcaf1c7b693f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"d5b90e8e1d781d7e34845a82d2e64c5ee2f3739342e9e22598f39e6d8b5e80a47d2605e0d2263f53217ac2e488","nonce":"aa39425b7270fcaf1c7b6938","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"461938376a0d050e1bbb7d2acd3dc0179555b002fb9d3e19dabc591990f65e4f626c3ced0d644e1bd1ac695851","nonce":"aa39425b7270fcaf1c7b6939","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"c7870a0f8f213cb645c072093ff94b9145acc4278f31839972d79a133ce51a0d30cf2591aee7e0e15a345f35b6","nonce":"aa39425b7270fcaf1c7b693a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"e8fefd2f70c430888011be0c28ef0ae7fd5394cf76ce8891cb20115703725978ae52c67e3a365642be34d4e301","nonce":"aa39425b7270fcaf1c7b693b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"5c66bcfdf82534388cb201ec49b687f25e980ac51d071f5ffa0dfd19da3af1d570dc9bbbc65ec434290367ee05","nonce":"aa39425b7270fcaf1c7b6934","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"ab7602cda1c90622173abf23839e14a3d39874ba56133ffd6e5033396022bcfcbe45ac09503e8351040657b4fc","nonce":"aa39425b7270fcaf1c7b6935","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"162c54c571129a7665c8ce85bc8a6c26f2734db60d559ea65bd7ae743d8f14f26fc6752aeb03bc1f2444bd4794","nonce":"aa39425b7270fcaf1c7b6936","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"cae91662fd658bacad5c6a2e6a217636ec1c707ce6b1e294011da7af4c8d4c0f5704e1f8c9dd6ee94ef60b0738","nonce":"aa39425b7270fcaf1c7b6937","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"15d36a4f09fb53e993d895a469c915ef640a01b889eabd0682f4fbc3be04749485c0c9b71831362ab6a09bf0c1","nonce":"aa39425b7270fcaf1c7b6930","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"c49ef2516d76b43b986f3c876a3278feeb59fe5f59ab997a136033fb997b5b2df4d39ea495860796e9d812fc0e","nonce":"aa39425b7270fcaf1c7b6931","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"c13df6923c1016c66f0fd815d6a28c3108a815eb617625d123d3dbb3c07b0674fde21b29a62951212c89a29265","nonce":"aa39425b7270fcaf1c7b6932","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"f7276e7089e7d2da66a41d074b82047f47cb4e87845a73cda6c89a78dfdc958d7f3874145290618d32b43e2443","nonce":"aa39425b7270fcaf1c7b6933","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"3f68e699e5d50097a17d15ca9b68e6700359b59c2f74c6779494834214874e626d6c14b6e14582aec30f731585","nonce":"aa39425b7270fcaf1c7b690c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"8f29ee69c4b409e4d3c0ddb35a241333a738f087c4b3a728edb0330c0bd031db7bc7144e31d08274b57ec92169","nonce":"aa39425b7270fcaf1c7b690d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"fe592fce624d67b269c2af999d1a3f8b41b838b2266bba0eff54aae23ba005cb682769ba3302915bce92f97390","nonce":"aa39425b7270fcaf1c7b690e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"5cf0c374297aa76d1c76092267f819e8ce1ff0168e1cbc3b15c855f8f17d9ebe936acff06e2da9b1c8c0c9405d","nonce":"aa39425b7270fcaf1c7b690f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"8349f35b958c733b1d6fd90acc9d2ea06b669e275e2ba1e7539492483e1013cd9ea6e780c4ae050f71e5923d0d","nonce":"aa39425b7270fcaf1c7b6908","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"87ae134a658f95246710cc5ced3e730d16a5b05b0782930a33ed12e5bdd4080c3f2692b1af28849d6a979f5392","nonce":"aa39425b7270fcaf1c7b6909","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"8a143c62e17cbb56a38615e62801c97e9c4ee3d929f52d95ddde0ed53db7435b647019f57476423390c4523a39","nonce":"aa39425b7270fcaf1c7b690a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"14525d9a662752842938445637bedc09c68372af12de6a6b36d804633584b91ecbd2f6647156652dc83ae72cb3","nonce":"aa39425b7270fcaf1c7b690b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"d757ee33650e973c022aafbfa804a64617b60998e459bea3adbecce6597d75db159a2eca5bd89f5d53f2a0c681","nonce":"aa39425b7270fcaf1c7b6904","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"5bb01b15122b2b795ebf5b296bc3ff1b2c6884b13ca24355ba46baf8a5336dbad63d05beeee6b00542247f29a7","nonce":"aa39425b7270fcaf1c7b6905","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"6c90bc11791d17b585460215a3e61a3729e7019d830a5bc50a1cc250bf8da96caf51b1c89f0ca943d3b3f4e6fb","nonce":"aa39425b7270fcaf1c7b6906","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"3d681edd263d259effa8597f7906938d928116520ee4b3e8aa0a299da6f8b1bb6a3a9c1e4549c7767ffc9703e9","nonce":"aa39425b7270fcaf1c7b6907","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"ae37d54c80af7596253724a0616c383073fd1a4c4dca0aa61d10342d3374ab3f6075dba44466bb840c7aabca4f","nonce":"aa39425b7270fcaf1c7b6900","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"69df6679e5119a6473822d89901d7359a229bb63389eab27eb310350640fc812a7eeecca9afc38107ba8145e71","nonce":"aa39425b7270fcaf1c7b6901","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"e290e915b4c651f40db77e21a032eb957f51d3e0a2b846ba7d589ad7c988b67d9762da2afb679085efcbb53ff1","nonce":"aa39425b7270fcaf1c7b6902","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"dd06a26b4af6adf9e0494794fdd9db237a04f7e0beb7012142ec9ca86e6b844db8e957e2e9c5fe7566f914b52a","nonce":"aa39425b7270fcaf1c7b6903","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"6ab67c32a47ded9565ff3d5a77e519d7305fcd7ff4224d3d2d9c80175f81bea5a7a2d2ffe226ed465ccfb404b1","nonce":"aa39425b7270fcaf1c7b691c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"9243a21d972f4e006800aafe3c1ebd7c5b726c760c80896cc0e2ad4efafc06162ee41c3e5d4b7c714065f230ae","nonce":"aa39425b7270fcaf1c7b691d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"a14a8613caeea5245a8f09802db2b7a0d14bb9157893242f14ab7131d615df2584eb5035ae3a9fa4212f9f0f78","nonce":"aa39425b7270fcaf1c7b691e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"4501386b60e6be9433cb60e7db5d44a5ea2712b7e396ce35fe2ec7575a40c018b09de1e2886d937648644f2066","nonce":"aa39425b7270fcaf1c7b691f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"e30e6970fb0062342a3f49427983331482b1efdce6554b8419bf590f4532a0559127c95d2259b35ec78eadd661","nonce":"aa39425b7270fcaf1c7b6918","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"9ad225ec418bdc67000b4ba2d401959daeca9d50b825fda2c9e56de8f2c2d98b562187eeaa66a53d87661923b8","nonce":"aa39425b7270fcaf1c7b6919","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"344d9301105bb45ea0114b180a66e0ef872244cd8ed2bed4665d3eddabbed509ed66ee3989adcc3ecff65a8683","nonce":"aa39425b7270fcaf1c7b691a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"cbc481cacb870ca63393ecc893324a770bdf17752a049c96803fed6d36353482044715ad6e109a3e6d3a5b4049","nonce":"aa39425b7270fcaf1c7b691b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"01c7bd1d7ee20c1fd6425a0d1864b02b191cd1eb06eb01f4868eb437f277c4fe0cb64092213a311a1d5cff1e54","nonce":"aa39425b7270fcaf1c7b6914","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"e94bce7f5fdb6d8935f8e6b708f57c8083c0b46b2a2d7aaf3263cdba3d7340dab5c94f1cd7ba0b36c9b0f4a536","nonce":"aa39425b7270fcaf1c7b6915","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"78ee8ff7bc8f9f5cb57cf167e15b77baca0f7457e2f74063df1c7128a8d7d8732aed63ccc5702e000e8a598ad4","nonce":"aa39425b7270fcaf1c7b6916","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"39785b194a393c999583f4dcee47c129625c00dcda51db9b66f3cd7cbbbf4893d471c242f6908befef3453fa7d","nonce":"aa39425b7270fcaf1c7b6917","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"ffca894a6e1cfb31e647f919cfde069aa849e0545f83e2aba6d4219db33b2d8aedbe475f0b6356d49a53f2497a","nonce":"aa39425b7270fcaf1c7b6910","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"c491803921924efb50866251ba71d4511b1d14498e0c248bb988c443985c6dc92e6525ef2e68bff7625c209257","nonce":"aa39425b7270fcaf1c7b6911","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"8093b0f1ab5136c22a719b7159f1fadc896ce6372aafa3382ac691bae51337ddb192d8b762e78e8fe7f4df2331","nonce":"aa39425b7270fcaf1c7b6912","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"a356913480b5d3017d05deda7dae5a399ad14e54dc44a2452c9d909e48b1383a55fd9ba7a22ceaeb6c27e32540","nonce":"aa39425b7270fcaf1c7b6913","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"22cfb308437ae3abcac038c030b60f825a35d85a3b668253c43811973ace5c60dee014d97bd13c67e8c4eaaf36","nonce":"aa39425b7270fcaf1c7b68ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"d703147bd36b0218fed1af62840ef3a15869d1c64bc68b4df87371ffc9f9ad95"},{"exporter_context":"00","L":32,"exported_value":"8bfcbf37919c5ee14028640b7eace4e6de00fc39acf073e74cbd9712c9da7beb"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"a71f58a7f54e8ef1ed2a6f70f7a0f158246d4c569750420d545f05822d10fa07"}]},{"mode":1,"kem_id":32,"kdf_id":1,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"89a6ce4b7b8eb12eebff3864615a2539e3e64fa2d4ab525c18c7bc451a2b5e40","ikmE":"7f5b697a87fb11d733e31265410c80b72525637e1b872f9ede00d507c0c534d7","skRm":"52a1b190b90aa604eabdb03853dea870a88c2ab78f812f0137af75c11f00451f","skEm":"a1fb4d2bda0df27dd5cf33fd6d67d4b2fcf7b2d3ef89ba95ded5bc513cb529c3","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"2b15f3560e8545473330de96ab3f0df764571141a4ae9d02d32f967b38b0c701","pkEm":"6c869089a41d49afebbef4a046671062cb95f334d333b2796f78b6c56306bf53","enc":"6c869089a41d49afebbef4a046671062cb95f334d333b2796f78b6c56306bf53","shared_secret":"a0028c3a2e4542ec179cc4f706d49911305e7634b9a952fefb58a8e709d5586d","key_schedule_context":"01e78d5cf6190d275863411ff5edd0dece5d39fa48e04eec1ed9b71be34729d18ccb6cffde367bb0565ba28bb02c90744a20f5ef37f30523526106f637abb05449","secret":"42d002638b73763cd5194a327f1f9c0ac6a3561c051db3206b02a37da7359a07","key":"c7295a3618b0d5f60513c1e0c3624b60","base_nonce":"75ac8b35f8d5f59924145c97","exporter_secret":"c7184d43f15a77671045a0f2162963f62c47ab3a933c6861e038a275d7138489","encryptions":[{"aad":"436f756e742d30","ciphertext":"0024748142b413ee22311a16a7b1bf813cee46b8aad06da9eb1ae14156c3d31bd84385f939e4f6554be9fb22e5","nonce":"75ac8b35f8d5f59924145c97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"c901001814df06c9209bb849511875b2c1a531775304417bfe460932de21a4cc77d234a5e4d9144cf092eecc50","nonce":"75ac8b35f8d5f59924145c96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"7954e8125a7c44d2ee29682541b13139563b220c33f81bc38d18b06bd1f2792f087d64c2de1df6a582a4514984","nonce":"75ac8b35f8d5f59924145c95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"510ce8802cbc778d6d5e285255421a7db63092e7e18e0f7c08f9e584fe3e49ebe2838e90d7d2cc064a8eea873a","nonce":"75ac8b35f8d5f59924145c94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"b6f292027b94a950cb081fb3e6cd0f3f62ff31934b84b138cc0502550324f1edff3fe7d46891fde2b13e3f487b","nonce":"75ac8b35f8d5f59924145c93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"15310c4cba1eb940131434f44ad30b99046bfba130a41348b397e00b0cacf2975e99900a606f0023f9715a4981","nonce":"75ac8b35f8d5f59924145c92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"b297de8844409aee273bc4c5e60ff64782d33c047579ebe4b7b6964d61861fdee558aff170cd7fe64f74529131","nonce":"75ac8b35f8d5f59924145c91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"dbc8208385a3d77babd5f7570ce782a45e2e2ef96028b70715d91722e77d3e6df7f57712f7fd92e5fc1b3f1f71","nonce":"75ac8b35f8d5f59924145c90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"330cdb4ec44f289515302fd70a896b0ed1a28199193bce907b5ed07890141f91ded6d94d84c361adf27c852f06","nonce":"75ac8b35f8d5f59924145c9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"033ae5d13f4549596b89c9f053a9839b9d4aecb75cc7259350c1fa4762a56d4e1238b068deb14ed7d7c076df62","nonce":"75ac8b35f8d5f59924145c9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"e1c831e77bd8c2365c9235148dc19a378dda7718147934b6eba43291a93139170e5cc0c61b289802e9f6740cc5","nonce":"75ac8b35f8d5f59924145c9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"0725e9df1296204bfa9c96d0718da937e087f20c03dfe00cf5082e1a1f95c56942ae82633a8c3a04302e88c4c1","nonce":"75ac8b35f8d5f59924145c9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"983c1d38ae378ee56d4e8ca5d3ec1fa46282fbf6c8783eacdfc0b96029629db8fa1c9721bc9676b7c52a9d4701","nonce":"75ac8b35f8d5f59924145c9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"3055ac739638a6cb7bf4bd5f8e11d9d755f72cbfb1b0ea7521d359436e6c4d70e4e2505c37779cc24329e5851f","nonce":"75ac8b35f8d5f59924145c9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"8a58b6969ac2d14b62362d764314d773fe7d17770c77d213e358425908c70b9e578b4dc4ccd6a0713c58181e1e","nonce":"75ac8b35f8d5f59924145c99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"b2d28317a71d344358bb8849b11c3d0a1f4d8a4e4814e32427e2c092360f4152ccbd6f0b7938dfafcadabee864","nonce":"75ac8b35f8d5f59924145c98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"d61a1ea07a5eb0a411ecd87a7ccb50ca47ea61c54f7e0955b80f9a79bc1146426c0d574499b0805a825373ec5b","nonce":"75ac8b35f8d5f59924145c87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"3fef3e64f1cb659a2b77c28d777eb49bf689e486fa3cff36f0a5f816719e7433b11d4e24dea76f7a83ab219636","nonce":"75ac8b35f8d5f59924145c86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"7c75ca989e9daffb49efc88fe1d6216587edb59042595af0a62002cd88091bf17ca0d6a3463d8cc09132fdd22d","nonce":"75ac8b35f8d5f59924145c85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"df20986c78f3d2b43df3640716e317d70cec17562bdf17db20d3368e970af4e2aca765bffede2a2bcaa470099c","nonce":"75ac8b35f8d5f59924145c84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"83707a260effdb961a8871f7533e9816617d350c24cdd4173af39b20a3072cca7bc192d5561825d68f762bdbef","nonce":"75ac8b35f8d5f59924145c83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"b69f8401b2219eed06183d81afdf0bbc0692cdb14a5d3c0ac049fa72cdb3afefeb615187ff202dab12af5d669d","nonce":"75ac8b35f8d5f59924145c82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"126ab042b20aadeea80e2a01df37c40866704f76cfbc1c82dcbd77c4269ab070b8a69b9af4ffe21d721806883d","nonce":"75ac8b35f8d5f59924145c81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"989ee97c09315e0124a794097234b5d97edef48681bd199d785150b034d40e9ed809a76e0b6b740b3d1bd60c18","nonce":"75ac8b35f8d5f59924145c80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"284aaec141fd116ddfa8d77906ca8cb50db4629be526833a8fe5e27dce66fca2b370be15a837c06d2ab387878b","nonce":"75ac8b35f8d5f59924145c8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"de27583caf70cd01ca31e0de5b09c6678707e5b26fcc30f4f695edac0c5031451fbf0588ffa67e9f93c281d724","nonce":"75ac8b35f8d5f59924145c8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"5689871480ce3ce7be4f950b3e5b9bf8ba342d90c7b82abe9cc03a7f5d2701ec651e5fb86b314f7fe0e839357c","nonce":"75ac8b35f8d5f59924145c8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"01397ab812b6f7ba245a016b74afbf3df5e5dea95d06c8b48255a0b477c022eaef0fac64fc521a0a03430e5cc4","nonce":"75ac8b35f8d5f59924145c8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"e4069e17d70c482c31c4913b25322b7ff3173ab7773f69686966646863d33a9c61f09f23dfec951856e7525686","nonce":"75ac8b35f8d5f59924145c8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"32cdbbe917a5bd4876bab0c2f91cff482002a91cc2548527587b35987bb56b159800c7f47396fe2141c856abd9","nonce":"75ac8b35f8d5f59924145c8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"b19c6b008efee2e986c0c3835116d6212b7884c92e43ddba260fb21bb2b215e724282e3e7b66c3367ac4680e20","nonce":"75ac8b35f8d5f59924145c89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"08caa00ea4d5dfd4c6e8bbf5e5b17ab1cca5da22d4ca1a6aad3200c23bfb58e0f5ecace45753673d5b9b0ab789","nonce":"75ac8b35f8d5f59924145c88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"6d288b87154b9a5404fc717cc276328d23d786253083b5fca2f88dc4afc563895c1c21a54ba2d9ee5ae8778646","nonce":"75ac8b35f8d5f59924145cb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"94d002b5b219df9be901fbc3843cd20d6b35507e4b2a45ebdeac2e89b655e30b1ecfa62c1b6b2e71a1cd866995","nonce":"75ac8b35f8d5f59924145cb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"390bb39e5853570833dc176f165bd957fdd1b47a17bf1e8b1c336ad973f03be321e275e8a37801b9f21518424b","nonce":"75ac8b35f8d5f59924145cb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"e29da74f79163ee25912d4cbcd53761c5206df7c218fc3d755d4d38c3d8923719aad138b068b7172070b9060b5","nonce":"75ac8b35f8d5f59924145cb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"018e4d98feed5ae88bf6a3a9e02c6a61f88784b5428eaa1518accec03a353e5353fbefc13e32ecec16c20aaf62","nonce":"75ac8b35f8d5f59924145cb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"1541050bb14beca7f084229442ce26cd3ac6f3b7c5da92f7f7197976f77ba4400df216aa1b1cffa1bd6eff5a4a","nonce":"75ac8b35f8d5f59924145cb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"bd56515f65b60c7f3872561435c3ce0ba55ac4f63d80f445427dcc8ce98c990525c77b98b8b4a9d4d78a7c6189","nonce":"75ac8b35f8d5f59924145cb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"0eac40506bb27b12974f5a343a006afa5621e8d3ed3dbe14d9f8f9aa8f0115aacf8e89f3e8b36b1b9918898a43","nonce":"75ac8b35f8d5f59924145cb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"55c6f5c7042285ca71c7a1a00e845975579ade144e02aa3d392696bbca914e4fab2bec54cb10cbcb7762144285","nonce":"75ac8b35f8d5f59924145cbf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"4c4fbed1f6d9e3ec3085104479ab09e1690663aa7bd5a0988f165d668a26b4ce6f2b47a985a2fae987e1071f2c","nonce":"75ac8b35f8d5f59924145cbe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"9666c1c45a9aeabb41653bf0c54fc8c802d2ef1c09d08e7bed6ad385a2423cd28a19473e823d5c2ea9821619ff","nonce":"75ac8b35f8d5f59924145cbd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"4014847f3c3d8afe44613e16cc272ad40dac202601d2d6d1b562cbd276b5858f6eb3014faa0c644aa981e08b6f","nonce":"75ac8b35f8d5f59924145cbc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"b62f72a39c77950ce207b5463eff24bb5f24f9bc25fe4a51c8a27cfce310a28312814f322b33ad5e3c63c499e7","nonce":"75ac8b35f8d5f59924145cbb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"7a00185d4b0e6068a83b7f0caa8a5cb13716ee35e8b5ad7ecc11c2541804bd7890f63158840fcbe85e43c4599f","nonce":"75ac8b35f8d5f59924145cba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"e706b3defe4745d6a6a8e8c116b8caac2a2ac41108e2ffc7424e03211ce7bbe488da88743f6fb310848bb7c4ab","nonce":"75ac8b35f8d5f59924145cb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"f4ca5d31e71bca421479157a05800473f95d0a3f24bbf7a0ee582f2e295e6759c20289340a4c73ca44eefec3d0","nonce":"75ac8b35f8d5f59924145cb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"4db31dffb2384d0759b3e9f6b556cbc1818285931512514ed9ec308f157e3ab9136291c64cc0e7e99238443f1a","nonce":"75ac8b35f8d5f59924145ca7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"f0091d3de43aab69a40ae7ccc63e43cfa8dd5e453e21cd3280abd44ec96ad697d2e2fba872977c6a54b3c4b7b0","nonce":"75ac8b35f8d5f59924145ca6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"02d4660af67441c01f77ef7a2526bb346ffed841a298c8ed3d8ea228d66afe14681274f03ab6016cd226a716bf","nonce":"75ac8b35f8d5f59924145ca5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"3fb78bd5851f8c63be58e63007f526d18cab4982f835b8c24571b548cdb77ddd4990b5c9777d60724ffe997f7d","nonce":"75ac8b35f8d5f59924145ca4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"2650ae351fa776da87f50a80b4290eb039be12abe335a9369a4116da4defc6d41882aac45e49813a83c6b8d14c","nonce":"75ac8b35f8d5f59924145ca3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"9411e5f32c51cd8dcefdbf078023400c26ee58b2e90bc872a7c678d70ea2fea9165b089f3c6fba9dec1b9560bc","nonce":"75ac8b35f8d5f59924145ca2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"1920edae3124b1c11ae5f8aec6e198f6542a0a22c50b30ccb4a3ce351d78c2ea364486f08fc916f8453fa50c7b","nonce":"75ac8b35f8d5f59924145ca1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"5038c550d45323b9f586d276a04312b275a2482f6818e74211656dcc9dc66959ba73086c93f349c5423dbfc357","nonce":"75ac8b35f8d5f59924145ca0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"a0339cc116ec59a4684479c68d89799319ce36285d1ff1ba9d33505f49bf11567aa4d5982fa17791a206abb42c","nonce":"75ac8b35f8d5f59924145caf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"7f9c1ffc45bcd6d9774677dd16b029b5ae21db37662591dc2c9a2783f0dabc9d9ad690b9c2d1634068ba4ecdae","nonce":"75ac8b35f8d5f59924145cae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"ec8e3d254975c4402a94c8eae0613a0538e2e05f493b55f4b4f758ba3838eb8783fa53f3399d789badad299dea","nonce":"75ac8b35f8d5f59924145cad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"23791c9672d2dc1736eaf3ffef972e4aab12dfc5af419cc4b47051d515168fb190e58ab45ff9d904e55a36adba","nonce":"75ac8b35f8d5f59924145cac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"c320d2da72cd64e6501698d3685567b7a7f66fea15965251b723dcd2992b35d314134e2bda2579098cce36dbd5","nonce":"75ac8b35f8d5f59924145cab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"86bac19cb12b653cdb15cf32d89395ca620619c2ba7227d8e23de634132b58a5dfd92a3cdba0adb0ca5ee5e7f6","nonce":"75ac8b35f8d5f59924145caa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"27a3268049fdd59f319682c8c138e24eddfffa3a26ace3e1ce322a20fd424e2744156be3b5aca58aadce78142a","nonce":"75ac8b35f8d5f59924145ca9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"b8f08f28bd53948dc35f1ac90a95c7e9c45e24e602e32567e573cb88c337d1fb14db8bcd21ad977532e7b503e6","nonce":"75ac8b35f8d5f59924145ca8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"9f60aa27133d21d199eb94e6c85c5a20fc8b735e01de4c6522a581db279bdc47c2060f5bdfff24d9bfb003fab9","nonce":"75ac8b35f8d5f59924145cd7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"5873aa1149e58d8f9f0531a742b9fcb461429071b4aa12437dd557dff12a924f37e19ba16642ad98e13e3cdea5","nonce":"75ac8b35f8d5f59924145cd6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"449b269ba29adb6b663ba23411124f669a87e75c4a15a8d1f02e2912cfd83a50cb5443fd1ce342d8d562386c51","nonce":"75ac8b35f8d5f59924145cd5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"9f6b0f87ada23863b0248d300eae22fae32820c1e3770488f714fc88f5ab0df7b32bc251f14453347fae477703","nonce":"75ac8b35f8d5f59924145cd4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"368180f70826e077baebc9600f04b6a21bb290f77935b37fcec08b4c5181083f8708b9d6606d131e0219899dde","nonce":"75ac8b35f8d5f59924145cd3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"3a90e5f96a8efaad3d69c15786b86fcabe430f29bbf216a6ea6097d977662b233dbde75579541037a46e3c2d31","nonce":"75ac8b35f8d5f59924145cd2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"48172c1e250ecbf4b500928ca094325cc3aa01e3c7af59ea8adf6fccd43191457dfcd49ccfd1c9d7f0dd87ce1b","nonce":"75ac8b35f8d5f59924145cd1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"06673da838b52ad030f31aff219bc3912540476391ed0ad81b7f6143a94891837ab41df0a2bbe94e9777186d58","nonce":"75ac8b35f8d5f59924145cd0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"6a3a06785b8871797173c059cdbd801998eb074d50b15b0c1a42e2f25f7edeb5e47d54ab52ed713d7da0cb7950","nonce":"75ac8b35f8d5f59924145cdf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"d8614e8f250429dd4f20f4007b6f98c5abc470e2a075a612859af9027b9a5b1f88c18ca0ee44e9f021eec6c2e1","nonce":"75ac8b35f8d5f59924145cde","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"c531ea8d567a4bf1b8f74d91be3a22f4346e1319168cffb8e974d774e9ef5ce0fbec92de8349823197230bbae1","nonce":"75ac8b35f8d5f59924145cdd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"04959f7d3b48438b59090e7680759c5613124870eef277b9169b1aaafe5e8a7aa45707554508eecb82418a8574","nonce":"75ac8b35f8d5f59924145cdc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"dc9434cb2558994a0a2956f2bc34d016c51d19a22372ead13e9f2d01361708566d5a6bfb76b2a739bb497bdd56","nonce":"75ac8b35f8d5f59924145cdb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"47cd2fb05ecb83326438bfb42ff7c7be8101a0c82e5f80a979ae6e6294a0eeee86df75ae65b64b19babfbd7fdc","nonce":"75ac8b35f8d5f59924145cda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"a83672d8f3e4d355f0879c493f03e1a44082268ade06f9e5326d18aaa80aa53e7ba848c47dc4c38173cbff07ea","nonce":"75ac8b35f8d5f59924145cd9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"21c99910fcb11d906beb39349dba166ad031d9be5cfdfb1bb86904382d565fb991315f7522a9441b8be8b06c6e","nonce":"75ac8b35f8d5f59924145cd8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"abfdb9ca7e77115b383c6c96c91dda3558618824404ff59bb53ef38e8047976e1b33e1ec577eed27d481dbf740","nonce":"75ac8b35f8d5f59924145cc7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"714b1a8c5d6567f77b4cb0d3170d8792c301e90b3fb4f29aa5391b506a26589a1ff2c5b4eb8ad9c230ffb60cd2","nonce":"75ac8b35f8d5f59924145cc6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"bc119a59f2c90def135ebda77acdc0459df6ac795c24130778e869e1ed350fc7f39aeb724a15df2aea37f3f90f","nonce":"75ac8b35f8d5f59924145cc5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"571b9d49f76f15ea28f12a533301ae03a65ba932aa319eee0ba6dd1de2f6f0275876fc424be2e6a351717e1c52","nonce":"75ac8b35f8d5f59924145cc4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"57e1c6bddbf609927326e03b1e11bf07aad01c2b4b616ea601bf7377e152275c6c056e6c818808704d916d20bf","nonce":"75ac8b35f8d5f59924145cc3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"4e81c5c3f3aada5add35cf34ced22fca9ffbb6cc823aa28c140b8d73ac904ea70cf05c6fdd8a50dd56f8437c84","nonce":"75ac8b35f8d5f59924145cc2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"aacd852518f3894d602ed87c58f0158d10e43b55b874d1092b590ce885256bf085bb40df384f96023b76880eea","nonce":"75ac8b35f8d5f59924145cc1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"1d811c17647cc1eb93a925debfb1ddc5600a46e283971886b66176e8c8cd082beeebc9bd32697cd9d2380416dd","nonce":"75ac8b35f8d5f59924145cc0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"7f606be5a816e6f4a00fe02d9f65d6be91063cf3402ee51d62ec7f83f3c90ee042a95d2721a74e7a88cca57571","nonce":"75ac8b35f8d5f59924145ccf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"a82a6d3229f8d157bfe67e2ab32f000660bbbf7e7a106b2f666760e6e7cdc49fd044f33a7ac39b711b4c15b35c","nonce":"75ac8b35f8d5f59924145cce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"9c876a6d313a8be401da2f500aba3bdae1ae0f046e353f3749c7a8734c94df204ffe5b63d5f51fc6830874e973","nonce":"75ac8b35f8d5f59924145ccd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"88bc85e8474e0ff10d9ea5673ef2832746ef511029d8dafc91ab213775141126dc3fad90694d940d53229f6c19","nonce":"75ac8b35f8d5f59924145ccc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"25692be73cd8f72edde92ed390e7b578c2f9aafc410f30e7bb955ab4bb82b1c007a322952de0769479176c215f","nonce":"75ac8b35f8d5f59924145ccb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"93aa6d0a90812e4772384c3e33075dc467425c3a3c8fc54f61f9993e4c5cc400a48fd54e03d9ff626e02d6a0a4","nonce":"75ac8b35f8d5f59924145cca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"3fc4676740f00be7d6652f7e774f48996b8f61e2fc93cbe19b9c925dd82c5576a63287c2b3338d6fce8f94aaa5","nonce":"75ac8b35f8d5f59924145cc9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"469c8863a2d425da0c45e0fb7f42bf0945d6645894d31698fe784e0a9ef4b3bdd70ea457947d7221e04a6009f3","nonce":"75ac8b35f8d5f59924145cc8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"bab2ca9ad5dd8e6e3c23f91c398739b0e64c5f131264ba5044584e7e27bb46134db78566e7f37c05d00e1a6441","nonce":"75ac8b35f8d5f59924145cf7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"f5d78bdf7a4f17505722bf98ab88f43f583168885b0d685cbcae027da42122acc77401d9a48fd62e89a187cd1f","nonce":"75ac8b35f8d5f59924145cf6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"dbd17138a419c8ffabd3f0255e441ddd7ed636dc4c76ae86b84e727112ad599d34719eaa3f76b01f25e17915b7","nonce":"75ac8b35f8d5f59924145cf5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"ebd6b6c8008f7e4bebc419e07388b5dc803886838a869ba0162c89caa0d1ce6bccfc76ce668887dac65b33f4bc","nonce":"75ac8b35f8d5f59924145cf4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"4f32b59f9f745a533ff928623e8d2658f1b281fafb01be234953bb7064813d4c7b20ef145dcec3c2d5c12665a1","nonce":"75ac8b35f8d5f59924145cf3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"990970e005b003e7c67a4929e01f46845cabd0a622df80f3d07170c643b5cd40b7c0c8b55f4b7edd8fa8517ea5","nonce":"75ac8b35f8d5f59924145cf2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"dada113f3963347c3e2b388ca2d45ba995673a7bf39eead4b7f468ab639a67185ef587ff9bad98aa16be3ffc57","nonce":"75ac8b35f8d5f59924145cf1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"a55cbd80626427b003925dc6a9801f036141e304ab686dae8851e2330a8244d02c7d244032b6c9ecb3075cc33c","nonce":"75ac8b35f8d5f59924145cf0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"d7342913d1a2402fa1873a5128adf2c98d7cfe481d6d4c71374661fc4a21558afa65eb3c4b71228e8a599add54","nonce":"75ac8b35f8d5f59924145cff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"1f1ed7931996938c7e84f0a162f30fb542489f8cb65d6dcd65f221cd6fa82d4c190108345f45f68d0a8a8805f1","nonce":"75ac8b35f8d5f59924145cfe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"b770a556d75a652104e63cc223c5cc46f77b9e89b489686e8432b7778bb74eff34c8dabc95edeca9ed6be34034","nonce":"75ac8b35f8d5f59924145cfd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"455ef4b179022badd33d63c9d865d46f834bf0d900ac97fbdf48dcd219cc17b49cad050e9a5f2dce7a7959777f","nonce":"75ac8b35f8d5f59924145cfc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"29b10c717191867d611f6d76444f57e85061f3a9127120d4d387d3a256e3c505264d1213b508adc8bd0d605ce7","nonce":"75ac8b35f8d5f59924145cfb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"8352bb1def172ec960c23846002814cb0872d6d6ecf145f7c94ca0defd538d33de80b33e97490ddba8870e8ab1","nonce":"75ac8b35f8d5f59924145cfa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"89ff0e6eaa5494961b64bfc2b250c2d064134f70c2746fc798edd935123c6a95fd489f6da0079002453f5497d5","nonce":"75ac8b35f8d5f59924145cf9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"528427b5773c8bac122e1598859f63b1f0b506b284c0df0a58809c48982e395deaf43437c292291ffad488d3f0","nonce":"75ac8b35f8d5f59924145cf8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"a86fa975fc88b0ccdacdb0a2bdb811183e48ea67f3772d5d3a7831e3e76f4e496a19e0c5b84d2286a06565cdb1","nonce":"75ac8b35f8d5f59924145ce7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"654b9e20e7a0e0623a9f41f3b36ae0bc294935d00f0616774dba32037eaeaff2a97954e3fa6fda980de767b992","nonce":"75ac8b35f8d5f59924145ce6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"61f9246bd89494e2d5a0812a96058a8f33877ffe1f13a44963ad10877de47c5a6f3cfac2527a76f55603348b75","nonce":"75ac8b35f8d5f59924145ce5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"8b2047af44d40004fb4f931d0febb7925cf916d36cd417c397afa9c9818cfc28ce4e7677713246db509109b68a","nonce":"75ac8b35f8d5f59924145ce4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"614cb054a70062bc24072491c370b35e9dd186e4d888e194e999e4236d7bd99e6e206298ce072b2b80fab2bd49","nonce":"75ac8b35f8d5f59924145ce3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"ad85acf2366433f083ea5579a684bac250164ddf283481eb2829d04b753947814e28988b35d8b8b5845233e447","nonce":"75ac8b35f8d5f59924145ce2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"5e00271ee1b8cf97d6e3b6cbbc5b1d527771f3d875ff62d5765745e86fd7871b5800d0890ac8b315aa406f92ac","nonce":"75ac8b35f8d5f59924145ce1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"9dad0d4b43622567531e302cd2967f9d3c8ecb2d8b3ef0b898b4e8c05ddb82e78e527be3fb657fdd9dbf05bb04","nonce":"75ac8b35f8d5f59924145ce0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"fbaa616cc9bbc7b0002582ff03583a542dd76f182385a24863bbcac3282a9f2cacab11a5bcad86bde2510d9b1d","nonce":"75ac8b35f8d5f59924145cef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"4990745d8d79c1b33fef23b82619696d5e5da451cbeefbf00c30da700ef0681531a3d920d72e0d1c908304a463","nonce":"75ac8b35f8d5f59924145cee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"1ef62eeb3ca02b25b2fc43538eabea4131cd852b058eaa1f9a600a49af53533c33231e57b0d996090d9d12f6b2","nonce":"75ac8b35f8d5f59924145ced","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"09ac256bfcffd8ae39de0bafaf62e1b92654ba9b6982658db76d473abdc9ffdcdf2ba52b10b69a1879d682353d","nonce":"75ac8b35f8d5f59924145cec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"55b7c985df175c14e88645e8a80501be4c23ad61d8926767625cc9e449e2ff4ffd867594407259ca4a6fb80a29","nonce":"75ac8b35f8d5f59924145ceb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"3fbe94ece8b9c6daa4f9593cccfae2ac03f141fa1dab738d2f50a25e917f6b604575856ec9c5146494497af566","nonce":"75ac8b35f8d5f59924145cea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"1fa4f537937a17976c847e85464c49297ffa5a80f86d4074106cd7172153839467554e5875be8cf57d0d8ef175","nonce":"75ac8b35f8d5f59924145ce9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"8640feddbddd1dccce0aee7d4009937a05a839a678ebe9ae9e74ae99aa4b829e5b3c8203a4c72a7163b765e3e0","nonce":"75ac8b35f8d5f59924145ce8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"228735923710bca4446d085e2eb06b4d1ea0f1121d829fde3ab230e3a174d0c442d2d872221c668a8c426eab18","nonce":"75ac8b35f8d5f59924145c17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"ce93b6d4e808047e1c09b9a5799529353dcaa465e7dd77573593f78809c0aafc0aa0860e824a9c16374057845c","nonce":"75ac8b35f8d5f59924145c16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"6c76b0a1eb42afca7ba3b58327055e36a93dc86571c924878fec81f031061e7517100ecb063a7d11bee3e34bf5","nonce":"75ac8b35f8d5f59924145c15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"0957df2ecbab9d49ed5b02990a13f42c395d962f8a63ddbc0e702be77c58b3a502248e0d0092b8f29d8e8451df","nonce":"75ac8b35f8d5f59924145c14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"7908cd0b19f31fffe10ae3461d5d08368d26769b76c2a464f6d7e824fa5c51cd220cb39903377c6d3b99a0ca50","nonce":"75ac8b35f8d5f59924145c13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"61ac9e0e87edbaf0723866d86d16f842129bb59433f43f91b9132617a6eb4b2d8bb81680d49cba27465b391140","nonce":"75ac8b35f8d5f59924145c12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"d0ffb5178936871a0f69cb470343a7cf1cfeb003768644f9735f98eb313da7af67c63d2b9cfe3b44090a47e948","nonce":"75ac8b35f8d5f59924145c11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"d7872423e22d83b2844bc709c2a8427ad886ac390d768d0ea508b4c4ef4b661c349cfcd5ddfc1a90ede2e6ecc7","nonce":"75ac8b35f8d5f59924145c10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"4f63972a7f47d9cb15d3e0d3b4b4966dd2a0cbb4810997e9728bc2788c10293d6ab6427f8325d2acd6dd0c17c4","nonce":"75ac8b35f8d5f59924145c1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"42c474bf28f4276c599bcb223877e037e92dd1633438300850e54168b726eb3e3326b73b42daeee7f1124788df","nonce":"75ac8b35f8d5f59924145c1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"1fff015e9c3239916c9c58fe39bbef7168c6777b0cb502537128816fb89c180f7596adb3ffbe091bf99d00d92f","nonce":"75ac8b35f8d5f59924145c1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"4f540fcb8ac7666afdcd38c4273b695c9d472445dc13523bd2121475d3d1c4164b781bce14d90ce630c1af4c09","nonce":"75ac8b35f8d5f59924145c1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"806f3f9c254a92c6c36b7b13c5d7c13ad4e71cfed7aaff29d249eaeacb0846d96edbf5cb90ea474ee1308e46b1","nonce":"75ac8b35f8d5f59924145c1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"75f935eaf0af922513f1faa962876e34d25335fc907f32a552f2982bf4f7eca783f01ead78b1fbd64152bccba8","nonce":"75ac8b35f8d5f59924145c1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"3ba04739c6478c727295ad164308a97c0d46d93c6832efd4e5817849b8a2340ef8cc7e94adc9d2438eb86a0efd","nonce":"75ac8b35f8d5f59924145c19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"90c330de54c46c4ef07ed8434e1f2abcaf9fa38fc731597133bc35010d8351f3ddb61297c1f1f2cf211b0e46cb","nonce":"75ac8b35f8d5f59924145c18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"6a66305dc104628afce3b9a83eeab7608e01fd616bcc8766ad984ab8f60e07cd318b76e4acb4b470d45b9107d0","nonce":"75ac8b35f8d5f59924145c07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"36d4bd636e221987f613b165988dbf52e6ee1cb20258f8be9e280ef8df5e789b7fa9e5f1853bbb469918cf0aee","nonce":"75ac8b35f8d5f59924145c06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"cfe57e0694f5560920508b9209832e781a2309f81887a167b71ee0456a38e38f0f93422741fe505ab01fa1b65e","nonce":"75ac8b35f8d5f59924145c05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"5486a04671fd59e353265cfb67a03b800c5243e775d9f8b34cddc8710b21199346dbd974143ea44fa00bc866bf","nonce":"75ac8b35f8d5f59924145c04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"a7b4b2201bbd8a4e7e5b3900786d6e18c50300069b8dbc8dc91e0b33dd0465f5374d83bce9a08e5e4731a480c9","nonce":"75ac8b35f8d5f59924145c03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"7e86246b43d2ffb384fea3df7ecf76807d2c2dee5c599f51a7160d8d9dc458b5503e4abea40907b3ffbe4b37d5","nonce":"75ac8b35f8d5f59924145c02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"39db7204445f2688bf2853a8b19ac7da9faa3c9389e56758847ed0bc19e18e40b5346464058160b9301c4d6f67","nonce":"75ac8b35f8d5f59924145c01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"d6610e55fc707854297e2e38bf4c1e94f5740bcedd66b32ca8b7dbd5e50422ec8dcd552bba2c431a11d19b3226","nonce":"75ac8b35f8d5f59924145c00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"13770add7e34c7cc5bbc9394bcdeb8f981e55c5720ec99c94b34d0d9043364970140efcb3c196433f65a008dea","nonce":"75ac8b35f8d5f59924145c0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"530160b8bd5cb5f1711f179c9522c0c6f2d837e15ecc9eb1d0a110a0300892986cd629be28c04f9b09113b2fb7","nonce":"75ac8b35f8d5f59924145c0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"44b73112f08a67dc9196bc6be2da6172fed430610835b4d8e4472285029b0e4f506fc1f4898b5f97562d5569b5","nonce":"75ac8b35f8d5f59924145c0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"5220ae919e1818debecb5ceaea216a1b5582f28a838be845d70773f843d5e69bf30c6bc6828b7cfaad3ae24c28","nonce":"75ac8b35f8d5f59924145c0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"53cc13f41a1da765be5ab8834eaef551dccc972c175a9edb7ba8544252a1ee2759d835724041ed4032066dc762","nonce":"75ac8b35f8d5f59924145c0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"48aa2e4031978e9b0431a2754e4c237aeac1766ecbfb7eae5fe400a12c7c6b55c78a419b81a68ed497c56a25af","nonce":"75ac8b35f8d5f59924145c0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"f5f78f3fa690dd90481f63e40f32a4e67443f643b58fe655eaa5cae32de84142b4f607354cd3fbb682604f7421","nonce":"75ac8b35f8d5f59924145c09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"ffad523fba30f38e757c705ddac4b75d07deec1a98a81fbe8e180b49f0e8d66532b8b02749e6a9713ec5b6caa9","nonce":"75ac8b35f8d5f59924145c08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"5dd4e71307edfc1e1a42209c7949d4958b15f2856ef78fd3d310f31c10378ce4f26eada924c1257c1fa39f495c","nonce":"75ac8b35f8d5f59924145c37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"c793cd042cf72c7b374fe2af9a4682a943685c7c8caa0894d67f8a63b414cb6ac40a3fc20e45e771022996d695","nonce":"75ac8b35f8d5f59924145c36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"7f6d0f875511122a245196f2b39cef41abf85b0c83a1c41228e949360e3c07360cfb2172848435b7185f3b918e","nonce":"75ac8b35f8d5f59924145c35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"122900aa1e382093fa8d883f0ea0bbedcc4860125933f307eff8b4577a49083a3f5ee8898f37f966e725ef5ccf","nonce":"75ac8b35f8d5f59924145c34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"df281b46a6092c96e007b8c41f5b16c9d50c7eb3c12987979d6646c2a204cc9ece1ccd8c5361108210b79863d1","nonce":"75ac8b35f8d5f59924145c33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"d7bc0f895be189bd0659c87eb5dcfb0c7b7598c6a2a8b1e7ca874049f375f65209ab11187397874d0a4338c4ce","nonce":"75ac8b35f8d5f59924145c32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"bdefc4be4425e1ea9ab1eeca5c3e0d4a9534bc548cdb83921ea08292bcf0b32e4a0f84280bca3ff6379be97345","nonce":"75ac8b35f8d5f59924145c31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"e9fe8e7b0a516433ae7884d0cc7ce13ef369920c256e99cf197764391b7735263acd5da6f242c5e4e7d57280fe","nonce":"75ac8b35f8d5f59924145c30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"f3cd4ac46d4291ef398381bda4508a9fd2a02f592c35517c003a49bd3cb69a3ba361b680f4b333d39e4abc8e29","nonce":"75ac8b35f8d5f59924145c3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"81b6d2ed6881b28a4197e083e4e56688690be9ffb9f6a583533dc832a728d9983dc1cd10069bd50f8cf289903c","nonce":"75ac8b35f8d5f59924145c3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"85febf71ff22f12fea4159fd4456086f641b27d7842c9b79306f01a01f4eecd96887aaf3e24bcd177ff2757c78","nonce":"75ac8b35f8d5f59924145c3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"43a5428400392ba736786add2ddd4a6cec058389ed54c33f0149e1ad351de7a3af8c9b52f863fd5307484c4a05","nonce":"75ac8b35f8d5f59924145c3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"87d33529fad795e16499893f128f5baa65b27180bc20f2eba9ae521132d589a7e71c14965cd149884d25877bb9","nonce":"75ac8b35f8d5f59924145c3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"5e3e36f23c570c7d00adc27c721cd3559f0930fad510f86bcc727b9b183537cd33d31e2df469fb68272920e41b","nonce":"75ac8b35f8d5f59924145c3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"1ffa0215fa0925f99c73a78a129c3521bfa6349b1172e6ee0ce3228ea0b99aa7ef7857c2ff25069a35fecf3869","nonce":"75ac8b35f8d5f59924145c39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"edd131cfd4158ccb0ec3936bf7454a35783337455a3d056beb1ef78d6a483a41465d312c458bb9411c1d0a785a","nonce":"75ac8b35f8d5f59924145c38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"70165c55639b7ada821a647b1d9b36a79ccff0bedcf08dff660b697531d071d217c4146ceec65cc9676f8e3b18","nonce":"75ac8b35f8d5f59924145c27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"0742984321d6728c48aeb64be1d9d87251cd8fabff82c11f88c456cddf8936a42bafffb2bbe21356813bd63eb6","nonce":"75ac8b35f8d5f59924145c26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"047ba9bf439beda992b9466eb9be7c1eb23b7b42742210e6e0f32d64b69273b6bc517ea075aec940e3fdd0026a","nonce":"75ac8b35f8d5f59924145c25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"f5ad7b9d9c869f75e97c2005542f29f377352577989cccaf742c4d1ac6161af0dce7d6cca34893fe45710c25b3","nonce":"75ac8b35f8d5f59924145c24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"9257646f7d384e4707ac55019ef35c055a41456c1c7c788e55307756db90bea8740eb06843ee60ab9b853ae809","nonce":"75ac8b35f8d5f59924145c23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"53d77cf5d2a99d4e19b6657c22dd903395b7786b38868803014c343bbc3457655f6296acbfe7b16a5511a0ff2d","nonce":"75ac8b35f8d5f59924145c22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"9787f7bc2880438cc07f75f8aed5decfb3892c6f2402a226e518364019573cad4a22db91676fa526cd6283d836","nonce":"75ac8b35f8d5f59924145c21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"7f53eeda3599b51e46c09412e4c239df4695d076de98500daaefb9f7354f0db7b67db5538e2491deccca8b01a1","nonce":"75ac8b35f8d5f59924145c20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"c5da57fb776138aa61fc656e7296f6b3baf3730271e825d131b364a5fc7f061edbe9677013059e62b9ca3349ea","nonce":"75ac8b35f8d5f59924145c2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"ad2fc945fa453c97b2c1bdc34e8805761ff47448a8975d6094b4c383d75f0aae04a336f9f895257034651b6308","nonce":"75ac8b35f8d5f59924145c2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"4987ae7bddc812fca172ab53fa15e12b24009d8682fa96982a059b2afe1c5f10930f38000a788dd9b5fcfb761a","nonce":"75ac8b35f8d5f59924145c2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"9304fbb284a3f664b22dfabd9b51a6c3deaeff937e9148aae5618b73318fdd25ae218153c3b243797b217257a7","nonce":"75ac8b35f8d5f59924145c2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"d13bfd0984d30b21c056010f5d496ccda5aa479455e084b6d0d4308a9fd10d06b7b1d060530ae094e4b50a3f7b","nonce":"75ac8b35f8d5f59924145c2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"36368c42ccef882f06d9c411eecae093ed5fb034108da6c465aeb91a6be5f9b51e6eb052133e27f21e0a3a6c18","nonce":"75ac8b35f8d5f59924145c2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"06516e4bbff7e3a24396ea07063f352843be3bed070261cbbff2aef7e815b42791ce53c0d65aff697d1309013c","nonce":"75ac8b35f8d5f59924145c29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"7854caee339744dd7e4204251ecc67fe83494567242d3119dba347c7dc83a38df0989b9295ad21178a155cb554","nonce":"75ac8b35f8d5f59924145c28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"7c39358aeaf962f8399eb79b04c58424cf0dfc351016d736aa4dd24c1a77778489ef42f8d67d06a87ebd39a903","nonce":"75ac8b35f8d5f59924145c57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"1dbd3d8a6b785a306bca857c8d712b78c86c11df5f3a80e12d5031533b496f5fb6ba27f06e620d29ff99ddf3e8","nonce":"75ac8b35f8d5f59924145c56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"51cb77eeaf1b72e6f496f9e0600df8af7a0f728034ab54f04674e48e683e46d11ea0965a9aef60ab6c17f41e7c","nonce":"75ac8b35f8d5f59924145c55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"e7787a65db3706d325f85cd95d843a57415787b891b9675c9a39130b221555896dee56a7d0a4e4d17da8f2ec1e","nonce":"75ac8b35f8d5f59924145c54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"f71851376f17cecf7a2778db35dd77f5cb686b43eb939819345b6fc7c912ab9b5ca307686d044428c13b3134e9","nonce":"75ac8b35f8d5f59924145c53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"17560da89d192f415be79d2525007899d5aca0723ba026fd345ef06eae806e176a3afc5a643f86549149817eb7","nonce":"75ac8b35f8d5f59924145c52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"fab8a555296789ad7014d884fbf620d6edf7f458ad6d2a81dd3830a4ee5258a1d46cc4ade4de2f9f1b0300ccde","nonce":"75ac8b35f8d5f59924145c51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"903c258b7edaaa1716b2fb415c71e8fa7cb15affffb99cb00dab729be36cbecbf187c314ddb04dee150e562677","nonce":"75ac8b35f8d5f59924145c50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"f6c73fe2e6ddc81d5d1711aa1b9719d7e5967c23454ad613a85419865172fbec58f01b069199f2795a2c0d15d8","nonce":"75ac8b35f8d5f59924145c5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"d81ef99116a0db25d6e1797a30114ecdd856ca926f532d9ce718fa781a68ede2cf03db7646e105e0e8e3ece7db","nonce":"75ac8b35f8d5f59924145c5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"539a61ed62db5c59c7adc82e476ca4399bc203e6eb4bf0454f2688922bdf47a3538d28330ed99d6f3334764d3e","nonce":"75ac8b35f8d5f59924145c5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"7487b18dc97818f96516e547b2256c99145b800d553bdb9908a60ce170cf24ff1ada91a96474a90f45cbfbb627","nonce":"75ac8b35f8d5f59924145c5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"ced60defa3a42c4be45c4f8839d16fe4b3ab9e4be935af3f6d72cb176d32fe9307742da0977fcc8452a46277be","nonce":"75ac8b35f8d5f59924145c5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"f3e12adbabda48b7c6ddcfed0d8ca28c1231b61f8e07a180cbd34a98107213a506328e7c8a11acbb0f54f5e3fa","nonce":"75ac8b35f8d5f59924145c5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"c94f1c5977118a1440ba4065fe29b840bf3c653e3761af11755fff137af12534b96d2d5f70b60576791b1a1ceb","nonce":"75ac8b35f8d5f59924145c59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"bf226a7682c9df4bbefba8270b1b38447c1efa37d76f2efadcf0823c04874efd0dc3ff296895bd19b073f62cd7","nonce":"75ac8b35f8d5f59924145c58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"472bc66d9af83e1dd0b4a8ea297636c4171f9874c7ee14a5ebe62692252372439dbaf191743571274e47e41d17","nonce":"75ac8b35f8d5f59924145c47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"fc6d34ffb00ba5c9a2c1d4c253e28abd3ff497c12d28537d9ebf86f27caf5db27b4e30fa139b4820e4364ae1b0","nonce":"75ac8b35f8d5f59924145c46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"b37849c4b4606f95aa4d3b1e067820b88944e9d47d8086f90d6d88380feae993c94b998c6e0286782275bc729e","nonce":"75ac8b35f8d5f59924145c45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"7e58752d9afecdbcbc44090a442d8e60981237754a369f67f2b5c2762a5bb9b0152c882404874cb681fb11c2fd","nonce":"75ac8b35f8d5f59924145c44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"d7b1d7b538ba76176ee870fa0a58e8b8eaf3a9af520e2169bdfd8b8f85bda28e6988c052473fd55f94233a52ad","nonce":"75ac8b35f8d5f59924145c43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"5518c738a37f94e1e099583296f02ba60812cc17216e7eba1bd86f32b88e30138c4db1dcf7e6e8c7e456595cfe","nonce":"75ac8b35f8d5f59924145c42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"6bd5ccbeb72dd26f2397334e45d0775522e7beb86d32a53ded73f4b1db43d2500c0644dac78ac7edb47acde99b","nonce":"75ac8b35f8d5f59924145c41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"3f0927c1ea9f4fd382034bf54d38173e2dc844a282fdcc800d220fd9288635d69b493d64075f9598bc9eaf894e","nonce":"75ac8b35f8d5f59924145c40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"a3a45fbf558b6c43d285f994b116957363069746dba924d678c6652d814857c89f18f6fea61ca9edcc7059a0ab","nonce":"75ac8b35f8d5f59924145c4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"ce4dc8dead87d327e1c416c8f4fe79b26fca6368c8719a811435569a595c1f6d4ed2b8107b149620292f5a0b60","nonce":"75ac8b35f8d5f59924145c4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"d09df2bae972d92a6bdc3957842e27c8b25e6b60acb2591f18f32eaebae3c68a3cb52e3cb40f1b4b64586f4cc5","nonce":"75ac8b35f8d5f59924145c4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"8a29464759d4a34e08b9a5aa8b9a1ac04a7c1133e25eeb37b412cd3bc84be04897ffc88d16f9a788fa95f3c2d2","nonce":"75ac8b35f8d5f59924145c4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"7ad8b2d135801713fc09da25c9145f1ecb4e54b7613c66b62a6676b2b37699736e2e393252b0e2e1907f4d69a6","nonce":"75ac8b35f8d5f59924145c4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"6498b37ef26ceefd6b31f206d6e41d5fefdf1411a50bd920986b508af428fcca1514f44fce14293221032747b0","nonce":"75ac8b35f8d5f59924145c4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"2e9cc8c5bfb104ac5497663b67e3211fd0096042290b98b3d73d25c775014582f78416b1efbaff5824810de55b","nonce":"75ac8b35f8d5f59924145c49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"0be8bca3d153134c761ce501850ec2dbf2cd9f50120e5ee4d7d4c1052b39d899ff22cfd1fdad575317156674da","nonce":"75ac8b35f8d5f59924145c48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"295c6a08940d47fd623c0c33000f5fe6c7c3f8f9b31303c220255bce10a8d80e4240b4ebffa142cb818c7bc308","nonce":"75ac8b35f8d5f59924145c77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"db325c397e8f5d9dbf7bc0aab951855685fbb97de606c88f350f32290c5c6f4f7c995bfcd05e2a7c1bc16a596a","nonce":"75ac8b35f8d5f59924145c76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"f530eba2baeedfe982b0b022450fe80ac3591c41d1f909480ff37a5425599353fc82c4f527d02e846fe12d9c4b","nonce":"75ac8b35f8d5f59924145c75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"c8af8eff97fdb19cac724747f08df64c1383f472d22e93ccde18aa143dee9542aff8091173c0131b3edeed2c39","nonce":"75ac8b35f8d5f59924145c74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"0c8d1c5036ab423e50452b1e61b721775a199a91cd2291e13c96f04df246f44e3afbab4ded8eae1b67ea84242b","nonce":"75ac8b35f8d5f59924145c73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"ab1f95778ad798625944a6689f4a05bbf80267356544f39d831a161e252eecaa71ae49a419756f410b210847ca","nonce":"75ac8b35f8d5f59924145c72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"7e13815dc835aa4f900173aa7eec0ea5e48a75225b6255917d471f013ab9c391eaa1a18223a5c55bcec4ec8881","nonce":"75ac8b35f8d5f59924145c71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"8149e24653999edc9cabdc1ed5f1b438fd32e763fba8b51b7ed7db5633024951f582caf767c8d6916cd15ed6f3","nonce":"75ac8b35f8d5f59924145c70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"008f0857de35c39602d2550fa4918d26bef695a6bab8f84db6f7917e322a0e0620818e29c4720f2fefa38629cf","nonce":"75ac8b35f8d5f59924145c7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"5b5d971d595dce9b9607e1c479040a7e1d6d2a9c6e24028249d51e83cce0c97b7ec137cbec644baa4e50b764e8","nonce":"75ac8b35f8d5f59924145c7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"32eb5403f55ff9056b2ea7022c456698ef1534c1f4c93de1cf63be41e804ecc272188dcb4cf4a4cffeba127f33","nonce":"75ac8b35f8d5f59924145c7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"5e50b02e08ba86d6682194568ed63477f3a25fe0ec21e6bb0743c4d73befd2b50c954bf44eea50f9cf5ff69ad7","nonce":"75ac8b35f8d5f59924145c7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"06ef37c4aa128b3330df71ada637bda39c7f907d86a895a1dd3e981276f1702529b41903c1a59a855089de15b8","nonce":"75ac8b35f8d5f59924145c7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"1e8cbdd91789160baf40bfd8c44e1210aab4a399d7524fa73db321c78a910d8977cac9849e8317f26b1d1f93ee","nonce":"75ac8b35f8d5f59924145c7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"a66badb1355dc4ff8ccb7f4fb7a81539ea43bdd77c4d6844a39af667e4f2301b1a9f33ab58656f4de4e406358a","nonce":"75ac8b35f8d5f59924145c79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"1981b4ff9cf0345d662224336d3d7b53918b472e9b964d81b0ddccf31c236aad2b3518436bd9e399feff929d7b","nonce":"75ac8b35f8d5f59924145c78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"bd851f7f07ca893c1590f2a60f1cd901527e8a9dd316c0892b09710ba4810aeb02f7c38a11d39b13bbc93a2d2a","nonce":"75ac8b35f8d5f59924145c67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"cd395282b78afc416b04a6ef1b42a7ff244a5345eb14dfa6198cd6ed33d5dc67a4c613d0a4972c74c2eac587ae","nonce":"75ac8b35f8d5f59924145c66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"c124d49084e3b6f8434a7bea03ea98ef82ca9cbef6fdd37bd53d4701cc22bb204c928c1bbcbd012a86c438be4d","nonce":"75ac8b35f8d5f59924145c65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"45fdbbbcda0b30d104974a21ed762d0d93fdc198764768e374b1f3f9dbe958cf1a9bcfa6122657a396f72ab28f","nonce":"75ac8b35f8d5f59924145c64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"4baeef9122422dd0f3823b1e591ab87b713390cea0199dc1a1e6afa8c9ce255fa9137f3acc159bf4cedca24ceb","nonce":"75ac8b35f8d5f59924145c63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"8500ca07d5ac6166d481c54df6f6d2d1e9fe83983b7a0823a029ded897ff9c4ac4c18bcbbbba892170174c13dd","nonce":"75ac8b35f8d5f59924145c62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"ab6b7791a171f4860781cc8980bfe792260076bc719e97cfb53f7e3302417b7ad87f04b2935322e1fd24f7d76f","nonce":"75ac8b35f8d5f59924145c61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"028e53e8eca58f58b2cb945331f07eb8771f37d5a9bba8b3c1d126cbcc760dfbed7b39f9f073afe6536438c062","nonce":"75ac8b35f8d5f59924145c60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"c74d665146e8361835c02260ad9c0cf71b2b50defd6673c41ced2c847c2a1ae1851630e96f5119d88269287289","nonce":"75ac8b35f8d5f59924145c6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"b27c8e4aa2aec43657c12564db71c3397017f4920069b5b55451bcc31af1466cb299b9e25d0b93713bf6772726","nonce":"75ac8b35f8d5f59924145c6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"c62d74ecb3effd0449b9fc7e4ec66173130efcd164c8c7928440f3d44f14d38c9cb0312c5d402af48eb2c2095a","nonce":"75ac8b35f8d5f59924145c6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"c44703fb1d7d93ad4b01a45988974d2598d179514c000cd3ed212d9b0d3eb5c8e753bfe27c234efb86b78120c7","nonce":"75ac8b35f8d5f59924145c6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"5b991f1b12f1135fee61253cd7bc4ed58655267c55323e424e698ed9cb3980a20031fe37df14bb9d23bd7584f1","nonce":"75ac8b35f8d5f59924145c6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"a4b264928a4dc5bf10e1c70f56a7071064aa0f9c61d20571a9394ba72958d1e33ca39d229e623752d01010e84b","nonce":"75ac8b35f8d5f59924145c6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"0b647f17fdc037cdea470edc9ef98955df5caa354ea0941180d8095f050f1963f3822a152371abfbe43bc3c7c9","nonce":"75ac8b35f8d5f59924145c69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"bb5bed92d706f18ecad79bae284255719ca717824b91060d0841d088ecaf1c23ba87a80920c2018dd0485748a2","nonce":"75ac8b35f8d5f59924145c68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"da17b7f8ab265f65eba88ed4d8a7c13a7f14cff2fe8703207109db0a0a4e4f9e1b611b794ca0951f1e551eb1f3","nonce":"75ac8b35f8d5f59924145d97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"02e3fec06eb0aa470b793e040746e459c07ca1fdb12fec9c15eb25f9fc40d6ee"},{"exporter_context":"00","L":32,"exported_value":"fa704fa53292124bf443004b0c29573618be834d515f433fed66675250379c5d"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"039bced37cd97c3702e685150baa1c62c003ef3cb3e69cb827d410a44eb1be0b"}]},{"mode":2,"kem_id":32,"kdf_id":1,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"a10d107753f85bf7128768693e53129fb44a281ea4849a86231632db48dbb28c","ikmS":"e1257ce84dd98bca7847d75661b658cd2cc6c4efbf9e989a40f390720b57d409","ikmE":"f7faa81395a22af1071b5273f9f94db0609ab9a7f4eca54834ea408d97294cc2","skRm":"0dd0a94308e5f9fdf00939ab8e97e5e0cdbda0f91475762b75ffda681990c77b","skSm":"c3ce378b34fb922adfbaaeef93244edf2107d114b3d6b5e8372482f280ab5a37","skEm":"fd0bba2abfa07ad77664ae76107020832064db688bbf56aa30b0eb64ebd91870","pkRm":"9ea1cb679d2b306cfdae2360d8e67cf2fd4c1b594d68894508b7e4edc2e74f5a","pkSm":"2cdac014f0d5a65614fc6669e8f55f16d8dba6a92b474640640103b5c26c3a2a","pkEm":"5b1f385b0e4063b06d9c20ed518a5002e7a46d30c8267e222406fab1a9b40561","enc":"5b1f385b0e4063b06d9c20ed518a5002e7a46d30c8267e222406fab1a9b40561","shared_secret":"53e8d00d80ca3c758365537bbf79f97458452e634b43d6e3616f00f2b6aedd17","key_schedule_context":"02725611c9d98c07c03f60095cd32d400d8347d45ed67097bbad50fc56da742d07cb6cffde367bb0565ba28bb02c90744a20f5ef37f30523526106f637abb05449","secret":"7ef00a01dd67a5576581f0002da22db7fe9c48e5ea4e18a153e83c4ace19c475","key":"3e2e73e913faccf13c182d9c3d162c03","base_nonce":"f6fe99886f9e8f9e991e3deb","exporter_secret":"f24ea8a3e650c5f0b9e7c9aa79bde838b41acb1e74a32b105a46c0f9168afac5","encryptions":[{"aad":"436f756e742d30","ciphertext":"f3884f172c31e40cd4b90ca2280e87c49ae0b6a83ceab51ec799053493612adbc03ae0e39e656878c3148199f5","nonce":"f6fe99886f9e8f9e991e3deb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"7bf476821bd718c3fc2982ebd86f81b46a82dba5969fa0ae2aca7af37d838fb9473b5bccdbe975457f88e41687","nonce":"f6fe99886f9e8f9e991e3dea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"ce38a7151f122f2b0575e2a8ed72e2dc5653ba7753438b7c8b980dec44e33e5f0e5b1b29852cb410723e13e1d2","nonce":"f6fe99886f9e8f9e991e3de9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"9163e33038ee66eae915a7f348591cd38cf7cba7383d531af849fd297bb71492add838386b520d0f8f1e00ae9c","nonce":"f6fe99886f9e8f9e991e3de8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"f9d6702904383307af8b888e33b1cfea49d31791358df32be3d9b8d2a25f6d0900f7b84bec17eb2f7915b93742","nonce":"f6fe99886f9e8f9e991e3def","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"10a6e2674e4dd8e2cc0d761409a55bce92bd6c0116d3537a263371578218d7cf10db9dcc17e1c5e64e92fdee41","nonce":"f6fe99886f9e8f9e991e3dee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"b97e9d3f66bf7949efb28acd0f8276dd6c8559b9c6cee546477f002587db7e1ef4cd87bfa9dcb0196c51d570f1","nonce":"f6fe99886f9e8f9e991e3ded","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"0fb9046b36c6edca089d030fc34f34f63b70cc323d5ba9de96785d4d58bf5f2d11e14965eb01e357db846b8297","nonce":"f6fe99886f9e8f9e991e3dec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"47f6276d3f4cbe96889eb68ec134b3d9909301c70f941390cfeadcc4101bbbe27f8d4b0ebb83b7d9759089d65f","nonce":"f6fe99886f9e8f9e991e3de3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"cef01961650963c68cff6aab6b54dab434d75fdff74d3dcf36443cc522eb68b5e6154372eb4df81478f30b8d20","nonce":"f6fe99886f9e8f9e991e3de2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"d08e09a70458fcc278ea8a3e9e95c0785e1a049a414491288bfa5ceff4eea68cac251014adc44f4e5eb7f362a5","nonce":"f6fe99886f9e8f9e991e3de1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"1e0bd3628536262b502b1f9f0a761c5493878d24f7925229f9355ccadc009a7be3ac9c506c944fca0548f3e20d","nonce":"f6fe99886f9e8f9e991e3de0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"a6f5e7923518defc71ff943c7a385318e6134eab05de4358fd7dc08dba7cafd45858cedee587ec56fa26975dc7","nonce":"f6fe99886f9e8f9e991e3de7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"91f11e6a78c35fe1031c40528e9f3ac01d8075700bfd23f0e296d2d33612b58eae871452b79c8ab64912b3f735","nonce":"f6fe99886f9e8f9e991e3de6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"ad6bec355f71f882bbf7f7b3bd89eecf4e4d4929f88084509e8d1644df8aa461f99d12ab1a354af6ea672db80d","nonce":"f6fe99886f9e8f9e991e3de5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"b9ea1c6d555802253ad1f05e037dec7d8e89565bf1187fef2481fae671bfbc735b0173227617dcd46d329b7bd8","nonce":"f6fe99886f9e8f9e991e3de4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"d4b9a690bc24d230b5169550479b249738249bb02d3ce0519efefcec5568db3b93b90a5a75097c322f07b9f426","nonce":"f6fe99886f9e8f9e991e3dfb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"b0c6f01a2dbba51cc697a7a14e67cbe4b58926c823849e61c8703c0b50171dccd4df2d14af63d71a2ce6c90f1c","nonce":"f6fe99886f9e8f9e991e3dfa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"1a55f2290632b01f58d6ed4b47a9255e4a850b309c506d1504409247e23935f38361a91a62ddfca63b935500eb","nonce":"f6fe99886f9e8f9e991e3df9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"bf58429887be5591cc5a66e8cf4447b67382017ff1ee971141130398670add59e05236045cc325bc5d52dbb80d","nonce":"f6fe99886f9e8f9e991e3df8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"4f83ac742ec25b607e990a5ec74b04f52b8dd30c937098d789b46648044f2c6ad8835646f0bbb76bd1f327affa","nonce":"f6fe99886f9e8f9e991e3dff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"e25784d2884419eae2d6bd69d96e65c4af3319eeb17992af6567ce769b4c0e4dcdd898cf706b7252c8fb61f074","nonce":"f6fe99886f9e8f9e991e3dfe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"df73f1f67f1507a241cd190a5df47031794cdb546e7797b91cadbe22b812263149b5330b418431fb18497ccf37","nonce":"f6fe99886f9e8f9e991e3dfd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"33eff43c23a1d0515363a8f3ce1b008c821f02a172bd0addee54be4346c2c6e174f6f7a397b5e883c0006255ae","nonce":"f6fe99886f9e8f9e991e3dfc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"7a8da8917007e70aa0c6306cd7d8fcf4228a5e20c6b06974e6d125159f742b4021c94177654ce081844326c0a7","nonce":"f6fe99886f9e8f9e991e3df3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"9dfa8d64f85803282080972749af9aba5a957e2258ebce1996188b81b8ea67db6be88368c268b4197e227cbc23","nonce":"f6fe99886f9e8f9e991e3df2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"2e04909d897caa456154c7964f4193b772699d264732edc76ee37622215a0a9b37dc2fbb0b036c13f70344d78d","nonce":"f6fe99886f9e8f9e991e3df1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"e37968880c88fc5a3c8d4e8aa5405ea9254ffdb708af78c630efb5a753f31456a9ef07a5762779b079712e6a5b","nonce":"f6fe99886f9e8f9e991e3df0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"5c975c64527b56fb92d8aca088c746e6334929139a34132097166e4dd676443492ec9fc96aa2229fcaae3c6e9c","nonce":"f6fe99886f9e8f9e991e3df7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"bd8659c37f042ad064f63414c278bf75fd4b9750261435c64a4879e02ea8c8f98542c3175827d1b16532442fa3","nonce":"f6fe99886f9e8f9e991e3df6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"4862eccaab8460fcf579ee5787b957f0ad564a4d4d8379a1bc190e3dad21b8c9833b2ee6b5bd6f2051fcebd5f5","nonce":"f6fe99886f9e8f9e991e3df5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"fd98051fb7134b13a1d84b828da231137e3eb8de5816279e43a76dfd1087b55d3acb3b581e902dd3946c499970","nonce":"f6fe99886f9e8f9e991e3df4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"db83c3bf1c5dc001a22f6144fdfa6436eeb2f03270dfcb7c9e559c403c6c8686960e7945ba0b8f09c87551f856","nonce":"f6fe99886f9e8f9e991e3dcb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"ccf10bbf41979aec9a139ec6e28905add0af937397ca2c5c7c74b7ff175a78426a201c22577f4e6f09ee6b3e07","nonce":"f6fe99886f9e8f9e991e3dca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"0c57777bf6c1a989c60f833962866c4bc9929f6b854154222e6cbfc6bacf71f6425a2333383bd61545098fe8f2","nonce":"f6fe99886f9e8f9e991e3dc9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"586034537d9e0416fbe736b34b9f0e5d870f5ea7abbd81c2f282641732501127ccd87a995b96db01e51e7f690f","nonce":"f6fe99886f9e8f9e991e3dc8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"d144c55a2787680c8ad4e0ed384ac073f7f14ab4e4f8dc4abcd422f32d2d8a197209b5cdcd94777ee254eaa5a0","nonce":"f6fe99886f9e8f9e991e3dcf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"0374210c0341910cc01a1af99bcee47c088b9acfc6616e68e0d8eea51bfa73292c69d37d3dc9353609404a207f","nonce":"f6fe99886f9e8f9e991e3dce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"9ec11cc05e77035103f8b544372d0a274686c86aadc06ce3215e718fd3ce0dde7cacadd5d0a1e63ac2ea07aed2","nonce":"f6fe99886f9e8f9e991e3dcd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"cc0d27de250d984ef41225dbe2ac73fbab85d43426a30ec1bfb7fc921fa167a2461e103943b913e5bf7b4aff16","nonce":"f6fe99886f9e8f9e991e3dcc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"c50753ef2217e070be81cadd09b24320946d4d55942a2cd5006280aa3157813802149bec0f56e525b85ee2ed19","nonce":"f6fe99886f9e8f9e991e3dc3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"28cf174f1719f0ac391a19d1bc5644f6f3c08abef37b5dcea3f79a7eedb4f8a6587871051978f68a1eeb0a3271","nonce":"f6fe99886f9e8f9e991e3dc2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"171c25bb64201bbcfe475740ba302bfb0c3804a89546677dfde26d253025089b80136ee8d3120560fc597dcec4","nonce":"f6fe99886f9e8f9e991e3dc1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"bd1fe483fe0f58a45c6e254251cab081e64de981494720d4d20dbf091dc9537ad147309b4bbc9e2d44af1e0029","nonce":"f6fe99886f9e8f9e991e3dc0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"67d1aaa77a9db70ac036ea625143250db0d473fe8e999b1ddefe9857f4bf642d11d3fe4adcb8d9a18c116865f6","nonce":"f6fe99886f9e8f9e991e3dc7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"1dda37b063b55dba32a27e6690df8b6fe3c2f7ad61669d35a63ad4fc3381960382f926f0b2fe116d1870c5d1e8","nonce":"f6fe99886f9e8f9e991e3dc6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"d71515c09ac97c824f8b34b2b9c9252952316df023db4a167745e18b76b97991120b59ab7abfa5e0f3b688cc32","nonce":"f6fe99886f9e8f9e991e3dc5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"14b2872b90c1a478d4af62d86a24f62f970e67c330be4c3d68df0f37c806e893f5c46d75e439d2b9bb638934f1","nonce":"f6fe99886f9e8f9e991e3dc4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"e524484e99a6f2e31cd0c88dced36999f9082f81079a688c9fcfebee145c427833b78b2c420561fd217f8eccba","nonce":"f6fe99886f9e8f9e991e3ddb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"c8b92d94adbfd42192d858a59020ff8ef19d8f509e4742be28f069071946596e76c76f0d09d5c2543510c4e62f","nonce":"f6fe99886f9e8f9e991e3dda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"6ba0376061a09205dcaa98ff7e6a27d793b56fe4032077e41a819838fa8425a073e11782d2dfd4f34049bdc37e","nonce":"f6fe99886f9e8f9e991e3dd9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"65fa8e245b4a7e365f33ab02eeff2f72af19a438fedfca5f17169ab4aa176216e8b302ffc75b4f2a39d8d7d03d","nonce":"f6fe99886f9e8f9e991e3dd8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"2438e9201a1c55a5d2a93e910206124f2c7f177cc344a01776a8be24157cfc978e4209a99bdb0f4640d72ad5ed","nonce":"f6fe99886f9e8f9e991e3ddf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"e871922c9e8a9eda0be22b1bc90ae2c3bb4fe81e3e584f9330cabb151e745ceeca407a4b7f698c95cf784e31d0","nonce":"f6fe99886f9e8f9e991e3dde","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"2a2bbf2e3181c5c79c1543e1cec0ffefaa65037e5b6d4cb2f773ff6d38a0bb27cfefb919465d122204aeb48e46","nonce":"f6fe99886f9e8f9e991e3ddd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"b645e22a28b054b2484b1eef70db496f1c0ddceeab9f14f621611ebec151d58b7fcb414f1798925c7e8c23b326","nonce":"f6fe99886f9e8f9e991e3ddc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"cd5beb508000b6eb408af7aa004a81a016fb7f808f335d8f5ba2887b6c16c568cb22c7bb8cf6b2d3e64e6bcf24","nonce":"f6fe99886f9e8f9e991e3dd3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"cc83e7b488c1daf2af30d8cab1acf7c63515972e211399408fa468e665e5e7b3980b57cbbb4f11f63a2bae2b35","nonce":"f6fe99886f9e8f9e991e3dd2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"93e4f1eabea3f75ca69a422be77413b345a7a8dd22a6e0675d81d18ea50014758c151a626eefaad0f9c6afd1cd","nonce":"f6fe99886f9e8f9e991e3dd1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"e15d214592d62f139d148dcb89e910dd5522689cb921f94f2576d56dcac4ec4e8d1c2dfc6d611c57ab9fb0b23a","nonce":"f6fe99886f9e8f9e991e3dd0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"82088b45f68e4cf2472a19914b02de8936c9848aaf73a7662d4d506a7ad0f14f43e488349e8844c45d6d2257b7","nonce":"f6fe99886f9e8f9e991e3dd7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"ef835b54410e379fc0157054ef332d8b0e6192a4d645d88f0b74a0b31279f6120d1dc5493f110e43ef7941ef40","nonce":"f6fe99886f9e8f9e991e3dd6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"5840a41d6ff4f44d94de7f924a3e70ca249905abcc24f798f7b8b10d24ac9876a6453e990f0fa003e47c7afaa8","nonce":"f6fe99886f9e8f9e991e3dd5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"08173c2c7f0c450c069ae3c707832ed22944728e392b68f77843a61dcda6cd609d5d01c7d098cac7357bc45212","nonce":"f6fe99886f9e8f9e991e3dd4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"9413a43ca0bb9e8444cc7742642cbc8558963bc3b498f654798a84b5d0d07b7938540326f53c8d48a7634807e5","nonce":"f6fe99886f9e8f9e991e3dab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"914df03e2a47012ab281b73a3f90dad73387823f116f67bac461a1a37ef03e217755d1d2585a703bdf89e17c72","nonce":"f6fe99886f9e8f9e991e3daa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"f985300d80163c2558e806116fb05bb4d6a9f13e46b25d20a8c5450bf6bdadf3ce0893742f50b560c1c2ad90b2","nonce":"f6fe99886f9e8f9e991e3da9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"4934955129e7db59ace872bfd645a5de987764d47f3c8c55b0e7f093782b582ed8d95869617190f757f85e92f1","nonce":"f6fe99886f9e8f9e991e3da8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"5b57e82a97c2284f53d23b1b0a94917fa2903808394264087c423ff3f3817d77d4b26729fce7a1d8bec153e062","nonce":"f6fe99886f9e8f9e991e3daf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"296a67e0c302de90aa74fc368e52e1b9e0482c5da894144f651a47859ce20a40d0dcf01f21efb2b0d30cb8abd6","nonce":"f6fe99886f9e8f9e991e3dae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"05a17dbe9305e309341e4ae172f40bd2e269aa3bb64c57cb8627aaadb694e7530b08224fe3ad0e74730e2ff9b2","nonce":"f6fe99886f9e8f9e991e3dad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"28060c26ef7e5342f8dc653f370516766248751204c06473bb6ec6af96872daf0b5e432b6da9b23cec85e6c0de","nonce":"f6fe99886f9e8f9e991e3dac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"d8d92cd40885d4d40b4891de127d3b032dc3bf4ccc33211408cbd457618ffd30e8470b4e746bb0979ee11f10f8","nonce":"f6fe99886f9e8f9e991e3da3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"0eb60e9760fdc1ac4f82ab1a0c2b2352a54192f7d9d65c9fda850ab05a3a6a3fbfaf1fe555f18f090236f2b772","nonce":"f6fe99886f9e8f9e991e3da2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"c5f36a03a876c01ee28ec3a9c09bf5a6ecbf51f7f96dc0878d50386c5aadc0d163bb27358b42aface142a90b81","nonce":"f6fe99886f9e8f9e991e3da1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"f2b08bf22894a60d1ff022f41f0c7fa91841821a2cd500dfd06298b9e00967a3289f15707fe66ff3755394b8fd","nonce":"f6fe99886f9e8f9e991e3da0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"ebd8454e88309cc80b12a378824bb8cf4218a2e45635c8672496baa4d9e992ea0f6dd278f7f93f5908429b8919","nonce":"f6fe99886f9e8f9e991e3da7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"cc31f56e7ce8619c2be8ed85a3d278aa762667a13c071966b96c81d718be2afd137177aa6a6bece50f76d906f5","nonce":"f6fe99886f9e8f9e991e3da6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"6deda2479c90c61c5bde4b45de06db2b95b83753412979213a0fa9d4089aa15b5be5e0a65bbec34dd9a426dbef","nonce":"f6fe99886f9e8f9e991e3da5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"850086e7b65c3c9244c1ae5d9ce000e5c6632ff76bff4a168bd82c4b5baa7b85c63b0c94136bbe3e3b3f8265ff","nonce":"f6fe99886f9e8f9e991e3da4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"1fd9d1fe9b876d1764b1eb7d5b344955f96cb5719cc37fd94c6a95f19ddcfb7a431776b0ecb5dbf0ec2fbea9e7","nonce":"f6fe99886f9e8f9e991e3dbb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"1f58f90b52f3b5a5332ac485de4321634c68e8f99575aead6c4536208d95331b2d64d3fc365422e2e86290f243","nonce":"f6fe99886f9e8f9e991e3dba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"62fe3ff944f79a3481abdb411627a2455d81795e0aab4eb0c78f49d712634345661a7b791349bfdfb49e9bc945","nonce":"f6fe99886f9e8f9e991e3db9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"f6b6c98f05f0ace1fd211ce6bf86a7c63004c211bb41658edfd7abf95310c901c98fbe8571b4f438826e415121","nonce":"f6fe99886f9e8f9e991e3db8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"92feb00d39e65ed27a2645dbce6b6c4d3845d76dcdb4e3782a77fc8ce4abd9296a38bcc600bc558136b9afde55","nonce":"f6fe99886f9e8f9e991e3dbf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"ad76a6a1c040bf3d86d107406517fc93c3393c54c8e3f978c3787f14d2faeb5709f6cd35d0c35c7d83bbb4f76a","nonce":"f6fe99886f9e8f9e991e3dbe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"193f8410984904ae15d0c7f9216bb365a06de0cd951962cc4fdfe9ea8cfa82ed5453150377d1a59cd63c9205a8","nonce":"f6fe99886f9e8f9e991e3dbd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"f1e0b96e26c7365194b1318a6914b0161ccc17cdbc375d5720f2e9569a2f5628282a79e3a87fc60cd154a24442","nonce":"f6fe99886f9e8f9e991e3dbc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"c1bab506decf9d17edf4d89b7e2d66069d045932e1dac376b4c75140741ff06ce533858ca2f22a2bf902350030","nonce":"f6fe99886f9e8f9e991e3db3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"0a3456eed48f1aaecad484a04841d3af1f4c57c7d4ebb60a495054aef0132df898c3457285fef743458f1c1be7","nonce":"f6fe99886f9e8f9e991e3db2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"74d4d1864609c0b6d65e6f9d4cee056fe6492d8b860d9d227af405340da1f7eebc93d0870ed22339de615f13f6","nonce":"f6fe99886f9e8f9e991e3db1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"3abb75cbb8135b6d4734085871451960c3c721072c10a36f048ca74c25c70e60c8287833469c2564d8dba70955","nonce":"f6fe99886f9e8f9e991e3db0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"19188ff257a37a41d59ea20161e6055e82181cfa01840b5f1b28a4d333c02073251ce56fadfafd99a47da25d35","nonce":"f6fe99886f9e8f9e991e3db7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"6e4cc250f1f0cefcb4016d659ccb7bcc8d346b1f44c4c60f13e75150f383d9f8f82a8765181947288e297ab731","nonce":"f6fe99886f9e8f9e991e3db6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"5d9b1c6bacf0d685dff61641967893c42629fa2e491d017571a0a4daa603a0809fb97231d28558cdfbc92628dc","nonce":"f6fe99886f9e8f9e991e3db5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"b459af37b1b162ca22842d655a7bccfee3a50b65fcf642e8ad7ea19c9b37fb20422f115f83f581c90e60891a6a","nonce":"f6fe99886f9e8f9e991e3db4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"a0f0fcfa8c3c74fc91acd21cf09985075783abe095836f768214a5b2a54d661839f03e06327e107a30006bb22a","nonce":"f6fe99886f9e8f9e991e3d8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"ef9c264b17da837e8dc0ab9c7249f5b2834464eba9c644f71d61e644c71f8a31ced5531c1664f9464629676d33","nonce":"f6fe99886f9e8f9e991e3d8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"ee93f1dc4a441829c5fceb9f973c6b603931ac86b87ebf140351e22ae4546cba730df72d17d04b907d4c25ee24","nonce":"f6fe99886f9e8f9e991e3d89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"bcaae7ceaa8b33c5e47c169805f550ce86a1ed0c53c97cf0259e8cecd0c512863ea9dca008ecc2afd66ef785b2","nonce":"f6fe99886f9e8f9e991e3d88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"9d98ec4377f0c90330011ceafe4bab5df2db826e60b794de6b408dcbb30d15ebf46d5a3052f5c50a336eb05613","nonce":"f6fe99886f9e8f9e991e3d8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"23c7cb5d10ccfd46f0b4462dac41f754b174328eec689944ee1f7050b16fda1e23a18055c5cdbf7dfb4fd0c699","nonce":"f6fe99886f9e8f9e991e3d8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"c46d958e4a312a6760d259f9e8f8f2d810468f0ea1baa455d5e691a3735c91422774936f445fa370e40d1be178","nonce":"f6fe99886f9e8f9e991e3d8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"9bb22c9bc8806f77061f5c92dbbff11a25a86bbe6efbbbcf9fdc68f79554cdacac032ae7b675d410eee8e4b913","nonce":"f6fe99886f9e8f9e991e3d8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"aa504c9f6e74e053a1e32145f681ed384ed6b5f375299be98d5e8c3a2c7429966a5a65ceabf2a8bbf02fac627a","nonce":"f6fe99886f9e8f9e991e3d83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"98478948979c31befa38d707014b74426a0aac62435f1a5f2eb82347ca771ef7a5e4a3d198ed09c793685013ee","nonce":"f6fe99886f9e8f9e991e3d82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"df02990620babc40a1639ae902f8aa40edac31ba906e0c3094d1d2bc3996c6d51bbfb8dd64834299f7b30f5cbb","nonce":"f6fe99886f9e8f9e991e3d81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"f783ae6fdbb6be393daeeb1a5801ef77e637d02ff2ea990a51437f3df770114f6c2d919a69334edbec995d88cd","nonce":"f6fe99886f9e8f9e991e3d80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"fe37f8f6238d9faccab4d1ce9d046d615de56f2436d567953367089cf49c48f2d3231b3536fad729d684404c40","nonce":"f6fe99886f9e8f9e991e3d87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"c083d1b5e761e754edf593c417afdc3d0a9971d92c6af1844d063f9b51ea7e1d51f01c5593e4135c6e32d54115","nonce":"f6fe99886f9e8f9e991e3d86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"87672692f04246576e35d019225dc79b64189d977d033ea1868cdd85ca9a7b7603288e9e16da88c3c9cb88574e","nonce":"f6fe99886f9e8f9e991e3d85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"0018907ca1fd07c5a4465d91f0652af882f370f41be6c429b6957680086fd3b9751059df3233cc14ca5f394030","nonce":"f6fe99886f9e8f9e991e3d84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"a2190e89d6d80cb6455c9bed402f0d6b25b047da0c246ed44bd849875ab7775e8b7e89376f7d434dd1d2979592","nonce":"f6fe99886f9e8f9e991e3d9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"27a51d104da76f4c448cca12cb57b7c4526cf33b6372bdd2d4730278c9e464cef81be0768771895f042e1597b6","nonce":"f6fe99886f9e8f9e991e3d9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"8b9934c21242d7a9b2a940f752d3a61af7fdb9acb3f00698ecedacac1dfcf5cec06129d4a0407e45921063f588","nonce":"f6fe99886f9e8f9e991e3d99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"14c2605af7df0fdfb1d8ec72cfb0914fa5c6c6213befcf85cf30ecd9ae1d3b24a482621ad9b26b90615bf227d3","nonce":"f6fe99886f9e8f9e991e3d98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"e9171adedd7610f45cc5e1d8e2c0ead8aebdd02d62502228e8b1cd2e6bf28312b156a8ce2a619f37cfe4ae4740","nonce":"f6fe99886f9e8f9e991e3d9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"90f6737312647fe458b465e82fcf8186aad758b5a93fd4504f79eb931dc19505fcc708ae87f88be03057deec06","nonce":"f6fe99886f9e8f9e991e3d9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"ef694a54e4572d9cb33d375aaa6486905d7e94aaf3631c9de0bd67e86bbd5e2841162c63fcba8ba528d31bf50e","nonce":"f6fe99886f9e8f9e991e3d9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"90296aa93f30224af9573aad0ddf194c35f23a3acc43a0be6149fdca8aebbb2832e5f101a980d8cc1f1aace1ba","nonce":"f6fe99886f9e8f9e991e3d9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"679ab37419218accc15fc8308e4285bd557c7ab47d55866d22714ec9cd600939d98faeac65d6d48294d3b30a05","nonce":"f6fe99886f9e8f9e991e3d93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"4e0924f623d6d3c67d8665d5d1733dbcac6348872bcbff383e4d78f75cc3c4832ac671842da9a39f0eaf5ae8f9","nonce":"f6fe99886f9e8f9e991e3d92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"2ed2aeac1bd68ab2abf11e25fff351e69d680c77ce681b7ffecfe1a78e88b1f0a9a42d86d0122171061d588940","nonce":"f6fe99886f9e8f9e991e3d91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"b3645b027172bbfe88d9f72181063612f1029d77cf3549e9570999b00cac91c7823f3e4cc8a0eba71cc3fead3c","nonce":"f6fe99886f9e8f9e991e3d90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"b3ed26c30cdc43480462cae4eadb722d70df5ec5c3d744303898b659de3bde468c2d63bb50ca572d1dd3193aa4","nonce":"f6fe99886f9e8f9e991e3d97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"b3824bfa1e82ed457b0ce1a0e335e8cd38457c9fac3f6554fc3daf19eb5ec0c9455053bb26cc7ac939218b33fb","nonce":"f6fe99886f9e8f9e991e3d96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"1f6b24e1dc63cdd16d81d256341412c11133d43003e22d4614304774fda52cd0028447eb4d81c888f4e4365b8c","nonce":"f6fe99886f9e8f9e991e3d95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"e4c267f8f1ba48d3bc9f60e48034ba0b76544d91821e780dd86655228b594231c7f1b25b707e59e7092d3ca926","nonce":"f6fe99886f9e8f9e991e3d94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"6db508b844765e3e0f916d2ff916f83bb8d5ccf3197ac1234d8c70187aef89d4ce474b2004ba66e95478bdd42e","nonce":"f6fe99886f9e8f9e991e3d6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"535427e61519d0454418274a85825cbed60d47dfa152411f5776bf5f9f5403ff654ec13fd553fa7318ccb9a55a","nonce":"f6fe99886f9e8f9e991e3d6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"85068ca6b9bdf34dc5e192726f5985f187df640d11b26f318a4e6b5be224d47ec11a709d8b4895be94f71a0e71","nonce":"f6fe99886f9e8f9e991e3d69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"fd489799ee30398eef2535b36c04fafe5dad6e219fb0427d71cabc001ec7628ba254203863c56a91ae0572c924","nonce":"f6fe99886f9e8f9e991e3d68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"cc60a1ab1fa0541bfc78eef553b52c107521a81c1d43ed17ccb962eeaec76388398aeb058eecd4d4626b9c3e06","nonce":"f6fe99886f9e8f9e991e3d6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"1e251fd2e540c5a116b3158a8ad1358b95999050971d7493810d1188d4a55aa91596a728eac8a6f79e6370bf0f","nonce":"f6fe99886f9e8f9e991e3d6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"a725fc6aa128b10e148ca1923189f97a338918b139a989b13df0251b5d1609dae483fe95332ef41873b32e4c56","nonce":"f6fe99886f9e8f9e991e3d6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"dc3d2edcb6458f8e0181ba216430a1e39a59bf02115c59996c838dfdcd3e4aaf4f0d9aad736e8aa6e2a2a2abaa","nonce":"f6fe99886f9e8f9e991e3d6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"089edac4ae4d8df302bd483fb1bc662428a841e62403e255c752f3e428dc5ef4cbd60141dad4637cdc12c49c3e","nonce":"f6fe99886f9e8f9e991e3d63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"3cbd828e8601b49f8e8a6d36561be35caa212f3b66923a82e29a29c90fe67081435750f3fa38d1ea647d665aee","nonce":"f6fe99886f9e8f9e991e3d62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"2a90a346c98bffceacf22ffaa4ccd48c8296d64e23eebf874b3937e9d1a46f028e93ec62a1acd168f8dfa9fd46","nonce":"f6fe99886f9e8f9e991e3d61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"51a09b4558ec868ae2cdfffe9d442609fd9f627def4e9b4f700d22ca5abd3025e92c68382a95b4c082d3c5ada7","nonce":"f6fe99886f9e8f9e991e3d60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"929a6b4ff93d0b845d21a18486bd8ae65b4fc48b0ca7eeb170e72d9bbbe761ec751aa4a75600e2051f9d2fd294","nonce":"f6fe99886f9e8f9e991e3d67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"778886036d2cdd4164410ee4eb18461e785306473528920997a3b513b3a38fdbf0aa1cf33268d3f60ffd4bb68c","nonce":"f6fe99886f9e8f9e991e3d66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"cbaadb6c4ad8d0bb06202041507ce579ab519bcbb5233dec0f5d9bbecf91a1b5e7a50f513f38c424f9eb11fbbe","nonce":"f6fe99886f9e8f9e991e3d65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"c2fd1cf29be50a26644710e271ab6a1591857c5c768ae0c2fc3fd9ee77fd69e87982326d78f6d915cccb40f17b","nonce":"f6fe99886f9e8f9e991e3d64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"96d16dd877527d2d6cc64f4a6b751f32cb4b0977951c805b1f47e0df8266964a4c2d72b73c7430ddd5d74e6b83","nonce":"f6fe99886f9e8f9e991e3d7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"44facb96c98069ae0df0090d1a0e66a6c372c2947797c5d99969852715f89f686f3624bbefe02e9a34446568e7","nonce":"f6fe99886f9e8f9e991e3d7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"fdea32cf9e42bf1def0389726f210117220a27ca601e296f4e968e40c6c6092aff896eafda0fb5e6fc8500e9c8","nonce":"f6fe99886f9e8f9e991e3d79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"4c873c7cd25e936d8c6a5261cd51fdb64e9a1d5be58048707b8344a951807c0e6b2b43c2957d43be6845b2857e","nonce":"f6fe99886f9e8f9e991e3d78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"68b642042a5c7137ff1cc8c7590cc8d8a714b2700f36ba2254fa508ac606f47214a0f04c9d4860c5e1626ed3c1","nonce":"f6fe99886f9e8f9e991e3d7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"6f6df81608790a0ab67ca419571c6b0446d56836ed36cf6cd481d18b1ab5f61e8d76a40bb69a1499c63904ae1f","nonce":"f6fe99886f9e8f9e991e3d7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"a6359337482666f4819f9d1198e3260a1f7a1da43c559cd6c0e01f737241bfb9ec2e5b6345fd01383c494d4e93","nonce":"f6fe99886f9e8f9e991e3d7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"e9bd360b056af71362581e0e0bb5978a01e547f2f923fee24b77482e0c4a8bcb409668fe5b10928fa280ef835c","nonce":"f6fe99886f9e8f9e991e3d7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"68653055313c768f460fa8198c8cf803a54d9c9a4723734fb61e60e56e0811c808abefa440ae41d7526e8ff3aa","nonce":"f6fe99886f9e8f9e991e3d73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"d24f1bfdeddcb46295b090281c0cb7e955144b1c8ae68bfeced37673df291d5dcaec22c58e41b23587fbe1854f","nonce":"f6fe99886f9e8f9e991e3d72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"0808506d88b105b71b1723dd0765fc5926561cff7236258aa778553800a24e92e2ef25eeb5ce47a747fa201f47","nonce":"f6fe99886f9e8f9e991e3d71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"4a3d1a59466209f3720a0f185fb368655569a862d70107d3aab8026993c3ff0f22a8ed4ddc146be9b04dc75537","nonce":"f6fe99886f9e8f9e991e3d70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"fc2423bfdc11c1c4fa6774c41eaceb0c3819a19aa48a333a984fde27a5d705cf791067fe4738ab7d51fd35bec5","nonce":"f6fe99886f9e8f9e991e3d77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"4202c47a539d17a5407f0765c575774ebbbb113805b3b770524f6d230eb52e8fcbbd62441119a945e0a17284f5","nonce":"f6fe99886f9e8f9e991e3d76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"1062701fc07d1bbc6cac38752ece4c2d0c2392b43a9755a2f96db68b349f271f6db82907d66b65346e6a70d23b","nonce":"f6fe99886f9e8f9e991e3d75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"03be12b588ed6e8b69d3ef6ef68151ed9d43b00432ff7fa8d7923817a518133642e95c722ee92f9ab2dc7f851b","nonce":"f6fe99886f9e8f9e991e3d74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"0c07e2acde5afa78a5e8867ce63bfb6d94397ae71764c6307868f3309dbc608abeae4cf25ed59e52740ca65f69","nonce":"f6fe99886f9e8f9e991e3d4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"2e0edf0dec46cbc7a6bb4871572aefbff72d9c0a5fcb4b7ab1e215cbe460d3b03e17902af99af1cac73d0aa1d6","nonce":"f6fe99886f9e8f9e991e3d4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"e3fc763f31db79e4725cc0e1abef77540a63780f56bd32a42dda4630bb85417191747591a331179fe22a35e378","nonce":"f6fe99886f9e8f9e991e3d49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"a749b8791aef908eee04654e0fd9042c65b0eeccf5ad97d606d998071f847d8cf1830224a562cc6e49cd06326a","nonce":"f6fe99886f9e8f9e991e3d48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"c4cc8820e20c63318388a34bbb36eb3e744f41f8abba7e7ccafcae73c2a9a2a8373d504e72ca49a93eb997e358","nonce":"f6fe99886f9e8f9e991e3d4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"2d14ad8a3bee9fbdf9b5acecf5a1db360f7155436f8be8d7acae2708053bd0bdebd410869a5695109d922be413","nonce":"f6fe99886f9e8f9e991e3d4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"ebc298798cd9df4f70fbdf793d68bc02e0101c3858e4bbba41e06f805428fa5676b4022e3fc145cede9bab7745","nonce":"f6fe99886f9e8f9e991e3d4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"d91f8babdb5587a1ea38b70dbea38ee1b61bb99d76fab4578ee69aac4359f9b75b151fff1e3415512f92788501","nonce":"f6fe99886f9e8f9e991e3d4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"1efb3514abad397e3d8825b73efe45dda719fdf69ca5a4f88fbe96b819afd17a802ae008b20842bb22fbfa69f6","nonce":"f6fe99886f9e8f9e991e3d43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"4bd23d6fcc84276b1cf7d3d5a9df44a0374a15a8dc72791f9b1ebce0d3c7c4e25136787467c61f4ecbd4282ad9","nonce":"f6fe99886f9e8f9e991e3d42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"b3987321f467b7831ffc85ba9dfe94accc1cc2d3ef58a99afa9c45fbc28fe9080ea7c82457c03fd3efed0fec90","nonce":"f6fe99886f9e8f9e991e3d41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"5eb27ba6bf1d0045150e2aa7fe09bdfe9bc974627d232c61ab7d241f26f645e602d20b385dfdb34eca8840d3bb","nonce":"f6fe99886f9e8f9e991e3d40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"a6ca750d8c6cd47ecddb6af175b80a7bd12b08db7b1bb798f0b5ae3f87bb4f222c991f62c1891cc4901fe0a8c3","nonce":"f6fe99886f9e8f9e991e3d47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"0e877d417e4a81ab520de330b71b02a60486b25412ffa87758db73901192903cac4547ad50a53d090736576899","nonce":"f6fe99886f9e8f9e991e3d46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"dfe1625bc951ea1a42f88c6da3e8472a69ceb792fab647b32a4f48088123d28b3fe423a80c42d5fe39891fdfaf","nonce":"f6fe99886f9e8f9e991e3d45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"bdbaa8a28b1340827c0c0130e03312872a38fd96f9f05fb980eb577a41f586cfd8458f3ea6db554c65a32cec82","nonce":"f6fe99886f9e8f9e991e3d44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"ef08c0eacfd05384ec8e5addd5896dd34ec9294057bb4b3309fef81b42d22a28363aa5c4e36283b9d7d29e3d8c","nonce":"f6fe99886f9e8f9e991e3d5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"1ffebdcc9cb9c26437f173628397e23a309bf5da4615d2543a5080c8ad6d7c93f786bca421b4ea51c5bcff1622","nonce":"f6fe99886f9e8f9e991e3d5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"c5a99f013651f709caf9fdf75224db027cfdbe465514cf46556325507c6ee268a279bc25b715663ef48f0c87d8","nonce":"f6fe99886f9e8f9e991e3d59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"1ca57724479235f5c7e29180efac4f29e84948e72008ba5978b347b7a1aa0a7d32dd8aef6cdf275c9a9221e327","nonce":"f6fe99886f9e8f9e991e3d58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"5b8bfbfac47b8cffa7a18299a2b7f934ab2ffe4ea2b57006d41784fac3663a1e37863886209dad5848ed49c56a","nonce":"f6fe99886f9e8f9e991e3d5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"88a878997bbc7de3b764e13bd54a4f031198464b571fb65113360616fbbe933a3199110d3fd17adbf1db5ff705","nonce":"f6fe99886f9e8f9e991e3d5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"96e27fced8c55afc22a44934d701abadeaf815e00a8f081f3e86cf61596e600ffdf2a85cd954ccb10c538126ca","nonce":"f6fe99886f9e8f9e991e3d5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"22e903c8705369a00267b790b7d60ffa6751b5d640c7694755c55b30232587848239b42e36ed63bd985e30993f","nonce":"f6fe99886f9e8f9e991e3d5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"20bd3a67778e2849cba6366a19961133ac86c47ec28f7a5fd5a7333d650fbea1972bd66f5de682e28bd425f092","nonce":"f6fe99886f9e8f9e991e3d53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"0453d545f3d6f76663d802b65cbbb2ffbb2cb469e39dd71f4a28c424c9d40e314734b59346309f2ec988e1eadf","nonce":"f6fe99886f9e8f9e991e3d52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"4ee515c10fca0e64623a2b7e126cda2dc813c81577b05027d08976421eca40a8665ecefdd45c69ae22843d5a9f","nonce":"f6fe99886f9e8f9e991e3d51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"5239212d52f013e20d7f1cf8fc9310eb6c848f74ef70bbf330222e2ca37838f2be42b7b9dbe713c4f29534ec0f","nonce":"f6fe99886f9e8f9e991e3d50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"6e7dbe14c68fd7031a3703f0547928b9b99d79f30386c1437138556bb8836a8f96e3195f09cb77afa329995335","nonce":"f6fe99886f9e8f9e991e3d57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"ab0c6083a5e0daa80728e53c1c87fa957437384648fdf520c7cf4f73800b5f204fef2a32919bbeecea04df01ed","nonce":"f6fe99886f9e8f9e991e3d56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"6260750754d775494c2da8647f3b776f99910e87bf0f23a5c20a0d3e76850b3812e234a3fd880b524762fdfd9b","nonce":"f6fe99886f9e8f9e991e3d55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"3d0ef1d76f91ef274037540136671d0d19eaa4282e850cb8ac663e6fb9ac00bc356840995ff91a647fd82724e6","nonce":"f6fe99886f9e8f9e991e3d54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"cfb69ecde29a30c5ce877c367c7050fca010895ff9aa97759d1bb7e21ed79df1d21c57c9b5e5e16005f14752cf","nonce":"f6fe99886f9e8f9e991e3d2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"a0063e22bbec93160c53243ec93d3054611bd5bdb32956961077072c027204a486e7808c72e4029498125e0a0d","nonce":"f6fe99886f9e8f9e991e3d2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"8c1fdfb5c1401db7a90a4928e1a04670fe14d108e84d71d39bab0c747cec147d8023bfec3d48bb5786c2552b58","nonce":"f6fe99886f9e8f9e991e3d29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"348c8c8c547f58d1ff073bd3f69235db205b2c1614a3a4b47bb8376ade4c996d4e04dfd9e6aee10dc16a2e8b4d","nonce":"f6fe99886f9e8f9e991e3d28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"48cba500bc32d1bc421b6d1cac420dbe7f1f2e89f00b6cce9fe2f01ab9bf1939099d4a85c5ae218ad67e145204","nonce":"f6fe99886f9e8f9e991e3d2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"7f1e713432d43feab947c709787ee5805faf2fbbe9e614cbae21bbeb3c2d9307d2de2ed35695d6f07c7a6bcf7f","nonce":"f6fe99886f9e8f9e991e3d2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"3cdabcd04c31e63a9d8d7cc4589d143c273442f131a757d20869be46919a4ffe5f3962a43402d334b6152e0c7e","nonce":"f6fe99886f9e8f9e991e3d2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"684dacf2f1cc146b7260160891e5fa294fda1b3226010329e42e2de3059a0b0c1f39687fcde7f1ba6f7772e05b","nonce":"f6fe99886f9e8f9e991e3d2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"3b64c6efe9747ea7e46c30583e92f0b3a9b438ab1eb65d9ae6f7777e96624afe8b6b649d24d6aef49ac2bf06d8","nonce":"f6fe99886f9e8f9e991e3d23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"2724b41c15d1cf2604925c172c8297f8b15ed1841d773994425c26660b50780e67c906a42cba02054eba244e03","nonce":"f6fe99886f9e8f9e991e3d22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"601ba1c4277e6c28dcb867bb327c5d132b94cd627e4c5c14ada0521eb18ec4f443c88cdd46deec8bee649d34d0","nonce":"f6fe99886f9e8f9e991e3d21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"547542989950135b57b7af1f9d110e165f8e852185551352c7f407a98d071f691867da4f4fdfd0a6137cf3581e","nonce":"f6fe99886f9e8f9e991e3d20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"202d257a866a1c6d2a9f29f71ae2d994751327aaaed2ab362bbf13d4df6edbfffbe220da4a6984d1e80c7f9b67","nonce":"f6fe99886f9e8f9e991e3d27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"b6cf654520439830068ca9c76c3301d199638a0754315d3f4c608f8417c9e6587170c0813d4ef029f223a81a3a","nonce":"f6fe99886f9e8f9e991e3d26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"174dae052b511b16e53dc63fe983e208b25a5d1bc3c1c8c1d730263277be4f2bfe8477fd791312339a00a76edb","nonce":"f6fe99886f9e8f9e991e3d25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"637a72a960ebbcc26ce57cf4196db6245252982649f483313bd28109fb29de3522ccab79750c22dc2b4a590ae4","nonce":"f6fe99886f9e8f9e991e3d24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"936d6ca12261c89cde1002abf848b2936220a8cbb4cde32a1ea35c42c058c3096bd25f7634df1bb66ca3663b25","nonce":"f6fe99886f9e8f9e991e3d3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"c9d3bf5cf7cbcc595019faede7c1c2a60e2c97f406ff8a28c4af73c39b79ac88d70c77269f6d4a0e0553439755","nonce":"f6fe99886f9e8f9e991e3d3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"85e8c2ba5c329aaec5ab87ae8e1ef5b84ad6e7dbc5b909eaf4ffc9b9db342e56d0e87edfd356c762c5b8ba8c70","nonce":"f6fe99886f9e8f9e991e3d39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"b7c82f4e649efb1c6c61d848f196872f63cad23e75b3e6ec84e294ca094cb7dda660e4fdc70e7d86d757d2e0c5","nonce":"f6fe99886f9e8f9e991e3d38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"5665f3a5c0b4383f5e5052ad505031e7b2485089f3da14a60d93bb22ea3016e548774455585636bf36c274599f","nonce":"f6fe99886f9e8f9e991e3d3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"497520385dcdd463890ee227aa1b84b9d4424d6698f3fda62755472e66c814bc3a24c67a08f2c5f71922f2c77c","nonce":"f6fe99886f9e8f9e991e3d3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"ad77904ed43d4d81681f66ba720b5e1c26f0e460868ff991fefe6df739464c9659278dbdb247be61c6743fc5a1","nonce":"f6fe99886f9e8f9e991e3d3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"d01d1e30d5365c831a50aadad54b7af0692422c4b986c1d340c8e9e3723cbf2545d87965066c8f45c7f7af51ee","nonce":"f6fe99886f9e8f9e991e3d3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"a1f5fb418ff073afcce980e41d6f149d8f44365d05bcfd6cf5dfb1797e303c5a88e9399525d2b423cc597d4343","nonce":"f6fe99886f9e8f9e991e3d33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"2e2305a20e1e9e63b34ea54703a666f3d8c3f1c2a2eeb01cab5028938deb8205c0f503aa9f2e1be55ca4d636fc","nonce":"f6fe99886f9e8f9e991e3d32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"9a5b1b2c8f0c8270c90111638ccfb40487851d1031e0a899c32aa9b2abafc46f31bcc22f71567c47cda5f3b813","nonce":"f6fe99886f9e8f9e991e3d31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"e3cfaa2bcc7d2c5fc2959746fd1d81c7042759ef314fe1bec0df46e3823faf5a5274cdefc9345d2d58c7cb4b04","nonce":"f6fe99886f9e8f9e991e3d30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"4286bb4309ddeaaa36f9893f7a3e0b2841c950f4c32995deed9760324e35766f24fcd24b6e8283a903dd747b5f","nonce":"f6fe99886f9e8f9e991e3d37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"620c478146832e101c1d9da40f51ae727fb87fc42caf19b407a915049aff4ad0ca8c0af81efcd6a8f718f643b4","nonce":"f6fe99886f9e8f9e991e3d36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"84c079904e1c050ac6150a5f1d1001be0ba11426ba323344990e4f57b1fc57e7136ae64342da43532aa7dda7ed","nonce":"f6fe99886f9e8f9e991e3d35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"bb8b6dd211b3076243b36821ac66e8f5f05411d00cff83f09961a6088ffa5c9eaf44c8f3139778876264f4939a","nonce":"f6fe99886f9e8f9e991e3d34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"30639c8c3fd77d5d39b3e45dd1bf3a990517b502c2f73ac065f1868c385bf87c2fc6bc4309493864a86988bf42","nonce":"f6fe99886f9e8f9e991e3d0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"0b3a6b65e864c269048b74de1c34a7313bab8644a2fe2519de0cc4eee443a2cd9dde699a5cd989ed30c569b403","nonce":"f6fe99886f9e8f9e991e3d0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"835d57284f9ab28305be5d16e5bae37051c7fdd1418f57d7c89ddda68a6d162d03206fe0027062a688bede6cfa","nonce":"f6fe99886f9e8f9e991e3d09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"f9885d98e4ba7070bad9439ae78016d7826f43192ed6147d2bd19c6c6bb5b0f370230539bff4206f01728074af","nonce":"f6fe99886f9e8f9e991e3d08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"bf7f92daa17d44e592320eb9655088a8362ab2e3aa8b2bf57635e08a19b3b65c6ec2a84ecf3f8e182eb14f74b1","nonce":"f6fe99886f9e8f9e991e3d0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"c81f9db97af6efb10d173112096fa1e965e0855a0ed499bb2a4c07a4ed3f1813d063a644d9a5817ef91c719022","nonce":"f6fe99886f9e8f9e991e3d0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"b0294d9a5c91555a537e05e3fd68fa523e11214ac7cbab5653a3c5f0d374a38d002f5b256576960290c4d544b1","nonce":"f6fe99886f9e8f9e991e3d0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"1610ceb927d734994afb481a26addc727d3c393fc50abc1804900789b10192d10821b9c4807bc9c85bfa959be0","nonce":"f6fe99886f9e8f9e991e3d0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"b271b8fc86e287c66ef9a4a47514096f1e9193faaa8a277bb856ae2f56856b0c48f04c4d93d9c2256d93f5c04e","nonce":"f6fe99886f9e8f9e991e3d03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"40c632be84abfe970f9152998cd4fc85a33459f18907d1ee97868ab57ff58370b9c30aac05d459993ba3ad06dc","nonce":"f6fe99886f9e8f9e991e3d02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"51cb08ae4ec1ba605f123eda979c3ec2334d4fc57e2ea876f2d22f534e55cabceda3439e542877880efceff1bb","nonce":"f6fe99886f9e8f9e991e3d01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"1f948c6af415c07878436de1fd45e68d28c4b1c235ac91b9b9caa97536c0a08a0a06f4e981b0b7ff3d589cd371","nonce":"f6fe99886f9e8f9e991e3d00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"2d71c7276403aa7eb133f272fc620fed07d12484439c6b636a36c907db9a8897cdda97f2e39ddd5950cafce988","nonce":"f6fe99886f9e8f9e991e3d07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"20d2e11f8359030378289bfd11bfeed009a856ffb74f54742754bd3f5fa98633d5ca3c7402721ad765d8849273","nonce":"f6fe99886f9e8f9e991e3d06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"b1e65ae7421d2c7c4d2a0189f967fa5225e08b18905844716b161d10dc3164f91b719be07638d79e28832bec93","nonce":"f6fe99886f9e8f9e991e3d05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"f57435452f5851f444f13311c98369e8c5d5b424c2f4963d327c31d804df386658a4c8143f06485dd1ea5009d7","nonce":"f6fe99886f9e8f9e991e3d04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"b21420629c7ba56bba975aec9c3e5c1016a16c513caf2d90a8a82517681fd82a708e65799504227b9f1005516b","nonce":"f6fe99886f9e8f9e991e3d1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"d000d54823ef65b2d71638e7f7dca7c3a3e65c90c7f65a175b959b20908077d16dcb812f816fc7836be9ca085c","nonce":"f6fe99886f9e8f9e991e3d1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"bce784a0783829799b7990dc73af2c15b87700c9a7d93bd668ec7a9af26543a48728f7c7e5016a926aee604213","nonce":"f6fe99886f9e8f9e991e3d19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"32d89735e7f61f0df5ac3866ed686956a48b70a61738ce442e606f503c0b4f4cda4eb1fb033d3fc1f4fbc98fcb","nonce":"f6fe99886f9e8f9e991e3d18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"0344247642ab3a9a344bd00b4423a62bca589c607b26d761f1f5c671b282f39b382664954cce67ed618c2b9611","nonce":"f6fe99886f9e8f9e991e3d1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"648d32d3f527f160a86c315d816b1a51ac7fb35a4599ca4c8001fcb892adaa84e46c334048a15711f1d2957ae5","nonce":"f6fe99886f9e8f9e991e3d1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"2b67d938d38dba49ec748accb18672c0bbcfc949cf07cb97dd6535362f9ec9a07a23bf9f8b6a03c7f4367ee5ac","nonce":"f6fe99886f9e8f9e991e3d1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"0e52789ee2dec522d505215d92eadcd1d44b1200d81d9c1ad001ae2f6ec9184da025c387ef071ed60bd7263f2b","nonce":"f6fe99886f9e8f9e991e3d1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"64e18a4177a93fd984215a67664b6aa8480b08cdb9211669f9cd505862861f6fbfcae27736c310213b9e971f06","nonce":"f6fe99886f9e8f9e991e3d13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"53a3a9d23b4085ad7f95915c1b1ebf5340505d374a1483a1d1dd7b8b7bb3c9681ae28a3ddbe11b6c769e4f842d","nonce":"f6fe99886f9e8f9e991e3d12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"dd795198935c2b7f174b645fd019feb555dd1f3731e2fe199e1275d866c878e5a52e3a9a18a99a09eb54efb22c","nonce":"f6fe99886f9e8f9e991e3d11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"b284b768b57ac1b3e3bc1d390aab121c17a81b9ee520473ab120043a22f7faeadf0cd05fa2b44dcfc3eea175a2","nonce":"f6fe99886f9e8f9e991e3d10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"e42fb0c14cbdfc54fa39d07521402282ce13317568f717a5e487f74e7174dee4e7381bb30c434a79425ba758fa","nonce":"f6fe99886f9e8f9e991e3d17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"ec3a17f52d1a1627a33f27a26ae10b04880727ba0856ea1ebbd8e803916d326e07dfe0fe9b71a8af015ec1b520","nonce":"f6fe99886f9e8f9e991e3d16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"6d9845a0839375e30e6494ce3be46590661ca3304e0b16e631e302968114e5dfed7892e1e9f47bf46133260653","nonce":"f6fe99886f9e8f9e991e3d15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"15634a665c3a82b89b2b487ac00467d78490463a95f653aa87acef355065fb4590cdacf591c49496cfd5524a86","nonce":"f6fe99886f9e8f9e991e3d14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"87c1df675abb8cddff53be2a8ddb288c2addadc6e7394b37dc54644b91931e1bdd025cc4ca3493a88387f9004f","nonce":"f6fe99886f9e8f9e991e3ceb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"1f0317bb51c2f650bdfd3a1abd221315149522396df345888946d48f7dcc752d"},{"exporter_context":"00","L":32,"exported_value":"594e2a101ccb8e9d7bc09bb5c284cc86156fc4a6484c8341a69e52e7e7e20061"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"f796b4b0581d12ffe09b34867cc38a787bf7c2cd578f72f45c90d82bc538bacf"}]},{"mode":3,"kem_id":32,"kdf_id":1,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"b281654cdb2cd6a9670c3035eaa702736a951585a938381198f7d29085ca7f3a","ikmS":"ea95c4d3c5e7868af29fc0cb0841485dead8d54b57ee1b8ed31a153295454835","ikmE":"e98713f7e24e7025fb7abddfff317d865ad5f4c3b6be22cda48dbcdde6151a68","skRm":"ab88c57171ce7497c26ef70aafbcd902497fe0caf595182d7d3c8770d3642a2f","skSm":"3d8ab8e757693d972c1e205c2af3cc01b03e59d9b17fde438c8611a874b0be35","skEm":"ef9c696d945edba5e29478de9712423a5dc27d6b7a0b23ddb589e20ffcabc5fc","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"f89ba4eeb8c0e7efa3606872d863a53aaf38fe9122e00b956e9cdd973d8ce46b","pkSm":"7bbd011d8cd7724d81b09a65ef49f1faa33890e79086d877fbd0c03e4ff60826","pkEm":"9dbb32f56ac1c7e70a13e63ccf63239797cfa80ee86d6eab0a70fbb1b2023f0f","enc":"9dbb32f56ac1c7e70a13e63ccf63239797cfa80ee86d6eab0a70fbb1b2023f0f","shared_secret":"7d56765a93434310b9571be3bea9919213601f2b7398ee50ff8ba0de79f85986","key_schedule_context":"03e78d5cf6190d275863411ff5edd0dece5d39fa48e04eec1ed9b71be34729d18ccb6cffde367bb0565ba28bb02c90744a20f5ef37f30523526106f637abb05449","secret":"5507a37af3ab150446e76f10b10b77082576aca1866c616c328d6d76c3f9fb3e","key":"99cc5cc5d06d85b67432c4fbb5ccb257","base_nonce":"6eac26e93ca9a6772bc5990d","exporter_secret":"7e210913716d706c05d1a5e35f2af8483d5f719d4af92ee768acd943851e02bf","encryptions":[{"aad":"436f756e742d30","ciphertext":"1db161fce3ddf79245da0a725439cf8793de594fbcc8c4c6c1d140ab4cff3b3881754da1481ca8e152860271c7","nonce":"6eac26e93ca9a6772bc5990d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"9412a31be293a855abdf95ec1bc609dbe594033f7d101ecf2fbb96c825e699405ac0b2543dcc371e4f51f88645","nonce":"6eac26e93ca9a6772bc5990c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"bbb2f82d70abe28dd624c12ddc637f6f10b86bbaa65c685678e49b5dfc5edb1ac2eead5e7a616f37e95a675a03","nonce":"6eac26e93ca9a6772bc5990f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"438fbd1b2e3fea8ac6d7d58a72ad95696b2859bfcf4cc93c50bcd366ad2225575310961f1cbbdd81b74ef73801","nonce":"6eac26e93ca9a6772bc5990e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"050bc824cbc3ba509b3f9fd50aa631523339d2298aacf59c2702f7aff2dca794de6ce53d6acd0fb48f2659c451","nonce":"6eac26e93ca9a6772bc59909","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"93d156474a741cb3e2382c41c848dd895f20062487f04968a88caff77daff79924b1f322d5307e210111dfc520","nonce":"6eac26e93ca9a6772bc59908","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"575977c85c37955847513d2d528185da17d1c0033179d9f6192025162840670654ffa36d833c4e75ce2709bf25","nonce":"6eac26e93ca9a6772bc5990b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"731a7f9812d9fb7ef899085e7bb6a558e37dc92c43822e296b6983c9270c750a5c38db6597c023f67e8954cc8a","nonce":"6eac26e93ca9a6772bc5990a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"21931c75f75b559a1dd953a3b3eb3e17e94c6a936f3cc8f1d93ea81df85f805156db64bed8c91d889f767ce48a","nonce":"6eac26e93ca9a6772bc59905","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"12e06202d41e362e0e44428e31a80cf5adaabcd21563c2a553f529a011f13757161e5198bec2ce6dc6ff86a3b8","nonce":"6eac26e93ca9a6772bc59904","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"62a7f9859379436804efbbb72677627fbabc0a3e9c7ebce9fc65d4235b88200526a7c0e06407987e7dcfcdc164","nonce":"6eac26e93ca9a6772bc59907","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"908d38e5cffdb0504a94504846018472cc9e8e34368ef6c0a05e4189737b567b12660d5c690e0b60e5983ef4fc","nonce":"6eac26e93ca9a6772bc59906","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"287bc4d18fc1d2487ecb92f49be650a36def86f300a36dc34a45bbed8fdd8dd8594c059a41a1a8717b98410cee","nonce":"6eac26e93ca9a6772bc59901","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"c2bd183687be49ed328d7883f61e10026c59a0e6729a832d2f05ff52b4a4b4a883b66ff652fca567e3388f0eeb","nonce":"6eac26e93ca9a6772bc59900","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"ca8a98beaef5e29e3dda31a2058b47d7b5e4b8f0ad6b08316ebe7c5d55d07858b7ab9b14c0e7f9ba2906c7337b","nonce":"6eac26e93ca9a6772bc59903","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"a753e9edded72816c80ff24908a4dc3bba4cbc714535e0c7650dbe43b66864969145a2fa810149cb47a7245a87","nonce":"6eac26e93ca9a6772bc59902","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"f57f2bac7cb8e8ed6ee5e612963638ddbd0495e67c5b083a534a9f0664c162bb87ac6c54e0649c55afb7b537cc","nonce":"6eac26e93ca9a6772bc5991d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"a07f0849e87e35797b8dfbe376af51d4473364cba572ec3eb656d4cee2b18701fa2259b740bfbeb00d5ad0a56c","nonce":"6eac26e93ca9a6772bc5991c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"a45c3a3df042e3339470cf3fa10b42ba78ec63e156eed4080aee9538b8c1627549c818e6c47831e4b9653f3c64","nonce":"6eac26e93ca9a6772bc5991f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"4a98aa301662352ae582eb46e62042c292cdfd271accfc8f777576f803839ccad54253d6b03d0fb48c9801ba6d","nonce":"6eac26e93ca9a6772bc5991e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"a3247fbc6a2593c0bb77b77b6396d074605371d146ba756fb061efad7e525d466d22443542f3271ed1406c227e","nonce":"6eac26e93ca9a6772bc59919","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"67901e9dd71c0b32a78973587b2c0c80fad2b747fd907620c6d28a01e0b8abb06176dd08272e9362f71873cc63","nonce":"6eac26e93ca9a6772bc59918","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"6c23fa70b6787ca40b76e4161d234ab7ad6324fb47d2393d16420a7fab79aebfac3730b58f5c33a015d66472d1","nonce":"6eac26e93ca9a6772bc5991b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"a625bc19b1814f4fe4846f401048a95697bebc85c15fbec185aac1808e4688d85975239770701190fe7699310b","nonce":"6eac26e93ca9a6772bc5991a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"23ec1491da163f3db880581fa75574db672e77eae6cf0a956865c65a6bb648e62b495a01b15133aed7b0cd23e5","nonce":"6eac26e93ca9a6772bc59915","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"ee0c319059c92464599475591e0e8e4fc973268b12d6879924c26c050ef12161491edfb7e61f245ec0a3f56aec","nonce":"6eac26e93ca9a6772bc59914","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"33bd85ea56616bb3078ce541397efb083354b1514e513864dd63f8477c86cde698370ffb0251df6c0193f652b6","nonce":"6eac26e93ca9a6772bc59917","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"182b2b421bd044bf20f33d8fc47bba4bf07785e5ef54de9f8f9f34888905b2bdf66ee651d4d56f0c3b86333c30","nonce":"6eac26e93ca9a6772bc59916","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"fb2b81e3f9d0880c8a1c0e2153415e9bf39d85923761eb6aacdb40d2462043dc65103d621bc5c270a04f1b0873","nonce":"6eac26e93ca9a6772bc59911","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"5be5dde76558a86a0f5f95033208840c54ba050adc0a200ca4d178daacc5e9fc677b37fb100c64191e9b447740","nonce":"6eac26e93ca9a6772bc59910","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"2a09ad7ac0e96e3a6126e9a166d3a26b276d57550222b5f11fc6e99181a1d0913ca2ceacb991aee82a00cbcd17","nonce":"6eac26e93ca9a6772bc59913","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"858afa137d43dd1a7abe8c3bdbaae493e9efaab0c2c5e2441ac11e374d9e98a2d237eed13b5162a0bc0a9eb39f","nonce":"6eac26e93ca9a6772bc59912","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"dc601f3b6d1f87884516af41db71feb62b4a13424a2c25115e419beecc478b4b8362176897939d30a5fda8439c","nonce":"6eac26e93ca9a6772bc5992d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"37107fdba59e8df171f45ae2f2edf4e5abd2595e7cf0a6ee34ff70ae71c086e2797180434dcd5a7d75eef45c99","nonce":"6eac26e93ca9a6772bc5992c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"07b32001864f5aea288017ffb3b6db020e3a9e43bb41823ffd0d5c9d11c67faa7336f6af64cd6eb2544b98f20f","nonce":"6eac26e93ca9a6772bc5992f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"bcbdafbcab19f344f72826bf40d4039ba221de71f089ed2aa4b3cdced8131e9c5925a9d5ca7e973df412029f81","nonce":"6eac26e93ca9a6772bc5992e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"effd4526e31e52a4ffd9725072be3b23cea02cab6283c08a56fda62a83bb02c1385f40dd7d8becb6a7d0569cc8","nonce":"6eac26e93ca9a6772bc59929","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"22e958c77a06dc22aef5d5f3df1b7382e156f2add37fb2acf7e1d5f84cfceef582e2237e86adccb4c2f4509414","nonce":"6eac26e93ca9a6772bc59928","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"5161a52b4923cd9f37a6a3744aebca23e7fae746ce35abb853a0a3b8b37dd276aa7aed037188f3dc5b2e18c638","nonce":"6eac26e93ca9a6772bc5992b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"2e87e35a5420e1fcda591b23efc7d5e66dd0ad51458e9228cb546e3dde29e8fb46fecaff902f391e588069632a","nonce":"6eac26e93ca9a6772bc5992a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"6d322500e80c815ca24faec5bd6ceef9668204109051c092cc6e94866a7310fab452621a7811df55b21723b1b5","nonce":"6eac26e93ca9a6772bc59925","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"8845a0e108a926c94c93ceb95cf5af74152708bb8cf4e0c18106cccc13a3c041223cef813eaf257b825f1e39bf","nonce":"6eac26e93ca9a6772bc59924","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"7f27173e65e02cfefc4482c93cb98d5810ec9bbbe40065e7394393bb11f9acc4886daff1cec3fb37b8a8b49ab5","nonce":"6eac26e93ca9a6772bc59927","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"233dc3bf8c0a6a1ec9084d366853be9bab2742ee03caa90108167bba5da38177fa373f156988b06258b3228a6b","nonce":"6eac26e93ca9a6772bc59926","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"ad14afa3fbc5c1fb825fe938dbf702f917a3edd2bbb013df1be334e623c248e6bc1fa4425433080ff0ccad85b9","nonce":"6eac26e93ca9a6772bc59921","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"8b714e3f70c5094f4147059a9dcbd961d903392193929829c6f27b470725414dd16e27dab64c3bf0d6c89af316","nonce":"6eac26e93ca9a6772bc59920","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"325826b3612ad35e25cc5b53bce881542d66a3e50a721769c57ad3f6445e138b5a0e80a9cf1176c7b72afed2f2","nonce":"6eac26e93ca9a6772bc59923","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"6a486b48d2396fb00c31ea4d90f58f84f747c7ac7c6a2861aae7a4ed654fb781246207e92691ed1d194b030657","nonce":"6eac26e93ca9a6772bc59922","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"f54388911892889b41f49d36d68933f52fbb2b8b4037b26a99a3e3901aa88bc554e1e3b7173822e56760171399","nonce":"6eac26e93ca9a6772bc5993d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"69a47b0e2d536f9c5926f4e95580fe52f3b957a51a3c6cec72863ee42aa9c5badb091c0861406bccd50264b9e8","nonce":"6eac26e93ca9a6772bc5993c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"53ec05c7e7fe4b6e8d09f3d286927fe198cdaf49e88716f7ac7e6af773fa05b78fb914505cd4ce1669330f0dea","nonce":"6eac26e93ca9a6772bc5993f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"34a21cf6a8acf748a338e1b3e9f9b6517569ccfc580543912f08d0e1c9350994226626593e32df7db7b5daea04","nonce":"6eac26e93ca9a6772bc5993e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"3dd2c62a3364fe46cd5a7d7329baef0fc88e26abe1081f4e01280edf87ca5723f0af104dd3ec37b832be54c571","nonce":"6eac26e93ca9a6772bc59939","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"2582eae1b1c5447c549eeaf03ba0715a895ff8e550f46342c7005f1afdc71321336288cfb72775411092eaad8f","nonce":"6eac26e93ca9a6772bc59938","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"3445860eba31f893d483bbc469f7d0a89d45bd2f559e48f89561e8ea25cc55c32c02a606edd29dc3b85cd602ed","nonce":"6eac26e93ca9a6772bc5993b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"9f060447fae960b1cd58dabd66fb7d5746c9c55532baedffa243d325643ae93fa2a3920c77a0fd3ea9d1795622","nonce":"6eac26e93ca9a6772bc5993a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"8d04f20d458f59539062f617056feb6860187d3f17b66123fcdc7a28b51e5effb61f465705a4704d5e54a5f082","nonce":"6eac26e93ca9a6772bc59935","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"ed881121080fd77ddee4bf4439a25e0194de76c7923c2e31c8d86312220574f0889d3f0850aa80e382a5c66f10","nonce":"6eac26e93ca9a6772bc59934","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"79928c88d010460101c7e66ee50de1ad96858034db4b0da4e2eab9bcb66edeec59ef69ca94b3af512019356b0d","nonce":"6eac26e93ca9a6772bc59937","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"4dba8fe0611660156b8605aa954d09f3b899884a1efaf9b0b4d84512acac0d4032adc4c2ea7e3690cb58b6c397","nonce":"6eac26e93ca9a6772bc59936","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"6d09ecf4593d1d12187b01734a69938e0b6a0f11f9db10710f01be1ff139f4ccf2c58a032a7dfab67256bc9650","nonce":"6eac26e93ca9a6772bc59931","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"897225a60703e839a9812ae0d9779d8d6dd3f455cccea5ecb911b653d01ddd16f1e26eff528394dd9b4ac5766f","nonce":"6eac26e93ca9a6772bc59930","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"4503af1d58c6f373bf7899e034c181d01a971a4dfb7fc4ddcb8b5593437dc28df9f08fff79ac0e05bb6e795c68","nonce":"6eac26e93ca9a6772bc59933","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"d3d4612e71cd5f1f4ac0b27e8f1975d7e89a6ca38df8d02f33adc55138fa5eecbacb7982aebd8d679cc63e1cd7","nonce":"6eac26e93ca9a6772bc59932","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"27470fb3aed45ad2f5c66243ee7e47a7f90b160a34937d263838c360fefc2a6995c7e3263adb3868a5e04d2d4a","nonce":"6eac26e93ca9a6772bc5994d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"e683be63921395d8a126ff794ca9673b2b2a1bb260e47fa383805117a96cf03779565aa2ae9bcf3537807e9396","nonce":"6eac26e93ca9a6772bc5994c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"98c56cbd83b601f443e75b106b4b17363281c420464188033267f3d9ad385bd3f25f42bc1bf1a945820d02bdde","nonce":"6eac26e93ca9a6772bc5994f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"5e7a7baa039c4747d55529d4be211cd8bf2253b43728be84d3df4b864fd9875c36d24ba2e73c5e20df96351cfd","nonce":"6eac26e93ca9a6772bc5994e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"71aa479824ff3ef2fd440dbcef224c9c635f6d96b5f6d6299a3c3329ef668ca9e81acf65045211c6c1a00fcc85","nonce":"6eac26e93ca9a6772bc59949","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"1affd1b7fbea5f20e6eb58b1dab7e7018676e3ef23f41cded42fb083255af096263555ad67a7b6e633f7c1ff19","nonce":"6eac26e93ca9a6772bc59948","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"625abb78f58ebc8d94dd684b166983422cbbe2189f6ac401e625e6a518b8d93c7978482f4237f5eb92656f818c","nonce":"6eac26e93ca9a6772bc5994b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"e63bdac372937ad24a6ccccd41d0a1dbd730079ab0cd910b089ebaeb91c4884e8eb6f4a94e75e1c74b6d53f1f3","nonce":"6eac26e93ca9a6772bc5994a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"c4b7427ee35e48e61689ae9fd4204ef6b1b2e2c5a8470e5b3d8baf88582268f08304db6cc391429e5fbf86c47b","nonce":"6eac26e93ca9a6772bc59945","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"e2f2ba16a4218e1b8bd535def1338187f0b032d40973c5e96268eb9a01c3b346aa076bbd30f4c10a9b5f0ef310","nonce":"6eac26e93ca9a6772bc59944","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"862d43a25613b27591574d3c4a9fa3a4babeca986990a50cb503a859ca52b0f19d7cf73dbbdbac4a17810bd380","nonce":"6eac26e93ca9a6772bc59947","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"46d5b2be999da6733850541d6df0bdee23d17b4977de88f8589285e97d2659de3432f35d7784054eb6e42dae10","nonce":"6eac26e93ca9a6772bc59946","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"46d8176e6fa3130704763998ab9b76e4a69f12c16fa76d49d34a3d006c0b1fe5159bc67bd455bf2b7b92d578dc","nonce":"6eac26e93ca9a6772bc59941","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"c2db17b1094a44f82091a9816f0978c370aa26eb035f56281507e0a8e34a2a592710f66178829953c5efb284e1","nonce":"6eac26e93ca9a6772bc59940","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"e9d4830b3148ded80828e2b8acbcd6c7160e1094e7d7eff434584fac42149f4d2d6860643175b5f19d3ca784e3","nonce":"6eac26e93ca9a6772bc59943","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"6ee63dfdbe9d9f7070ff61ae7bec29b2e9e1280c9feaa31c9b861ba4ac9a4f1de99b705dd974100029653d45fd","nonce":"6eac26e93ca9a6772bc59942","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"bd439117d6bc5d4f2fa3ac7a027860ec4888b0dc1c6aa7344036dc2d1a47648760c016b20537444a1c680042df","nonce":"6eac26e93ca9a6772bc5995d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"2c637c836b4c9e8a8a2d5846054cf0d1bc40ec3432b7aeafa047af2a24e9d438a281f33cf40be7aa6c4fe68ced","nonce":"6eac26e93ca9a6772bc5995c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"35899bcd3afee56caef0fda9cbbcbbe1396ead0e1a1ee66ef5214d215e7b98f93f45292719ee4578aa4d8ed2b3","nonce":"6eac26e93ca9a6772bc5995f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"7210aa6ef653779baa282c59ae823c0eea16330f8d966be747717bd334f26e89cf77f9e4f0e0b63b2e52169532","nonce":"6eac26e93ca9a6772bc5995e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"8d9cfc9e5e502409af81dc688f2c1de5066cd09db46e339b76292821e6bac91922e891de3d9e4024a59e348b64","nonce":"6eac26e93ca9a6772bc59959","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"dc8487f7337095624137507d1caf37089c862581aa0f7b157a1e9cefccd6783d469400f83157ac4384f89fbdf5","nonce":"6eac26e93ca9a6772bc59958","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"cbd5da1fb09a587548330ea43a36c3bfa94d32a795aef23feb88f42b7e794765c6dcb5cbc8f8ac2759f3e41e98","nonce":"6eac26e93ca9a6772bc5995b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"0d7b7b6c4f1904a730d6923380bda9e65c61a9c080c18be1dccfbb832873d696b8ac26138d64510d21d246bdfc","nonce":"6eac26e93ca9a6772bc5995a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"4b6711c79bd402c0ebf18dfcd6b25715366e9856ffd1c40cfdf52a358a90292b1fec7dae1cfea94b0625422c96","nonce":"6eac26e93ca9a6772bc59955","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"1023112942a1b5a364ef0abb234b35c9ce4f0ad141867bab8e0fe5018ad14309b84207c3f932d7f8f1d2c57960","nonce":"6eac26e93ca9a6772bc59954","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"3bac9d1268fd13fccab3d4d4b45eff6326ca9925afa8c43c0600545b59e972124f36abda76fbb4e88d568323e1","nonce":"6eac26e93ca9a6772bc59957","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"9ae1272940c24f4789b9fca6b387b85cb38584c86b3f04089bde473c2649b929ea8f1059266bfbb1cfa71ca875","nonce":"6eac26e93ca9a6772bc59956","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"827bd45a6b18ab93d48da7ed0bea502dc10e5eb897c92367e43eb92975eec1609c6d93fc2eba88d15b7995a340","nonce":"6eac26e93ca9a6772bc59951","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"02a0d22934748975638f634c178ec18b4337505345605d12ac5842911ccb8af5ee2e8c5f2879ad08e220cc5a16","nonce":"6eac26e93ca9a6772bc59950","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"de0cdecd61b562fda6ca5765bd82fcefbf0311f2d76f742ec694bd27a04c8b2cf159e2448ff4ccbab9a9c09db7","nonce":"6eac26e93ca9a6772bc59953","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"d9488580fdc53694f766da979e18fe08c6a176e1a2a956d861d3bd4c218a3ef4403a7f206a1fa89ee444cf8ccc","nonce":"6eac26e93ca9a6772bc59952","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"1e8c03b5f7af4ba0676ac1692c2a241196a1864fe91f7ba13b340d4aa8c3243688f0b098051c2eaca5641c0226","nonce":"6eac26e93ca9a6772bc5996d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"1a2ffcec1a0ad7283b142ef1e1627d8bacc27bc83ed37c2e52f1fc526186fccafdb926543f50087b75b7cdf91e","nonce":"6eac26e93ca9a6772bc5996c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"917cf3eea925eb4afadb4974d8d9808087c9a7ba92faf4b2761de7ab1c8ddd28b14c88e5d362645e3f245100e5","nonce":"6eac26e93ca9a6772bc5996f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"b30c854a34811a46b910ba3c4fa874b4b861ecd020077956101cb724bb6f3c343a984eb067e321e3c4f74079db","nonce":"6eac26e93ca9a6772bc5996e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"794e54f28055812f00e8b3ee3c1fe675728bd75bbfd6168b182ee61aeeb2681d63372e1f8236c4d6864ce1edb7","nonce":"6eac26e93ca9a6772bc59969","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"f953f9b5b0ce28d41cd00fdca6c84e2264ddd6a09f3e8d650c9153c6b2633b88a9d22c34c0ad7c535ee83a39a1","nonce":"6eac26e93ca9a6772bc59968","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"6560907c91164fd58b8c773634263fd9e74b4b1665f116b85b4d452d2547853ee66826daf2d4ca0d0517c34611","nonce":"6eac26e93ca9a6772bc5996b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"ce18e91caa90dd8ffad7d6ab478294ff978ab94d8ce28744882654e79babbcc1387099f39441d06569e9ca1f5a","nonce":"6eac26e93ca9a6772bc5996a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"47af00ef4103fe0e86b2a6b048f58e01c60c4752749494b8bd8097151fb26c3ef31e35b54871e73ee02157cb0b","nonce":"6eac26e93ca9a6772bc59965","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"9d98605f2fa3512111aa11347f242ef31ecee13d2b8ac7636238103eb2a6e16ae033f9a06255fa067b8512e6ae","nonce":"6eac26e93ca9a6772bc59964","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"8d2fb4c7f715127fb0e689e08f54f9f5761e3dbec8e28f36dca3a170bea407f7b56a869ae0dd738057f4fc212d","nonce":"6eac26e93ca9a6772bc59967","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"9485359058e4279537b90f27192708870201a6d9ef4aa45c59a0e9102db89b51687c54d0033c345063452a5ba4","nonce":"6eac26e93ca9a6772bc59966","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"74440c15038ba8829040e79d5ce87d9fff064ff59ec5c7ee321aefefa2a206372dd38743d4c13e86a77b1d3483","nonce":"6eac26e93ca9a6772bc59961","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"9dfb12d6e3d9a4a040a59aae4b79e1dadcd6438b0120325964845c8a1d41bd88df383eec0bd5033ea886081a74","nonce":"6eac26e93ca9a6772bc59960","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"8b80af9ac8224a48092b0a98c544e5a66ab0dd4d1a4f99b2f66480506de039d5e4a6408e8ecd98c423eb49de62","nonce":"6eac26e93ca9a6772bc59963","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"fde62a8e170236caf4bde3a1e34ed61ff9c222c7e146febc3690c85572c41ec4d56af7652d2d8bf8c0df1eec6b","nonce":"6eac26e93ca9a6772bc59962","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"251725f6e4a01097b3debd1a06c039b9a597314d0c3b4df12e4ae726490032e6a64bd82415115849a28a20edf0","nonce":"6eac26e93ca9a6772bc5997d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"d6a3440b8bdc519a48c58f9be6a97a2eb3fb26ac7ccf4d8d22fed4cb0bf38d786f9c10f704b154871f7d9bbb20","nonce":"6eac26e93ca9a6772bc5997c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"5a1861773073242868e98bd0aff8b5c67eae844891a164ea736c150fad565700eb5d15ca915b71fe6eeabaa752","nonce":"6eac26e93ca9a6772bc5997f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"c6391592b93ab58ae5df179833cd859627b5c1ab222b20d72b5d945668de077b290707dbc3dea935af952e02e8","nonce":"6eac26e93ca9a6772bc5997e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"aed7283432dc9b6c3c70ce4b0f6f8e625b4f16ed2e7589ca5df8ebc676a287a312b8c096dd56a94167a52d32eb","nonce":"6eac26e93ca9a6772bc59979","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"08b57458b74cd02dc8f9d370ccec3891a2fec5fce1054ead4eeb6f6f87478385fe6bd1eedb8d82fbd741ee68ea","nonce":"6eac26e93ca9a6772bc59978","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"2d42ddc4328afcf81f15c38dc85d99e3bb5166a8937ee9c72ea81c29ea2ffee631c13dd2a1029effc005112cca","nonce":"6eac26e93ca9a6772bc5997b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"ea22ecfd6d60cd846ed383b2065239958131851e3ba4670ec1a43b4eda4dcb4af9a3982db546fcaa12637c1f84","nonce":"6eac26e93ca9a6772bc5997a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"9ea6f70ae44959dd03b1b7956510aed1cf57ab1bc8c3e6b575525b5d8cfac62ec3929420b754560268dc0a6043","nonce":"6eac26e93ca9a6772bc59975","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"2e70307c6320e6384990549aac846d233d984beb0d78dac68febf24fac2b8c29f1ae0b57fcc7b3058bf44207ce","nonce":"6eac26e93ca9a6772bc59974","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"132c53a5a209e625dd260acbd818a712a7f89475b3cd00dc807872d8c2651a345446091571c86b5f45f372c979","nonce":"6eac26e93ca9a6772bc59977","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"4cdde9f3c92c0fd4a4b48f464e91d8f6eeaee85d83f557aeaf72978b5348f582927a05f20d1765f3c2844235da","nonce":"6eac26e93ca9a6772bc59976","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"4efeda7dfbdad3dfb9a52521163642bcafaba993f6a8daf59db269b7d7e570b280b3d2e95832936ea0b7755682","nonce":"6eac26e93ca9a6772bc59971","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"831edc10c18e384213bf8a84ba974d2175928c14da4f1bc15141e9b61789608085827a44052236e143bcb4c3ba","nonce":"6eac26e93ca9a6772bc59970","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"dd947a5d54547c01dadd49dcbbe52e6b6d42975e3c22f80fdb4591b6471dabe5e90a391fca4ed09cc0612ee1f0","nonce":"6eac26e93ca9a6772bc59973","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"e5dbe719b9a05112e50805f1cd417d5b55e8081cab3dcc7f25666002db1c0b56e27ba3f9991572865400aae1af","nonce":"6eac26e93ca9a6772bc59972","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"275846d125d0487126c0c49bb66771f4a70ecdb423fe4990377ac1d1522df37eeda7b61ef33cf5579ab854ec33","nonce":"6eac26e93ca9a6772bc5998d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"93178ce29f853da590fc1cf23ca9cf95f9b20779fc80323857ca9f856bbb9d4568583fb290610638ef3baea16e","nonce":"6eac26e93ca9a6772bc5998c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"8bdc4ee69052f67af8f5cd552570da304c0b0d95ff12a322adb6d8a1a6e77fcba7c27958dd66cf4ea5b8f0b299","nonce":"6eac26e93ca9a6772bc5998f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"96e68b1544c62f502accd763fc7320328031aa084fd169a97e3aa7e1b8e24faf894928bf7859611455ee21d762","nonce":"6eac26e93ca9a6772bc5998e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"6f585457feebc666e9afc61aebb4b1f7f312f05d2569ba650916abe310d2d5c358a586832b790f8cc6d4082246","nonce":"6eac26e93ca9a6772bc59989","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"3ddcb2488e46ae0a9fde3c1176dfb30b58d2e8aab491e5dfd234bbc99d528916688c94b518bc2c7bd8dd228fd1","nonce":"6eac26e93ca9a6772bc59988","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"9f6c7595d3c3d9454788344dce97ae8de0a24bd468db7d40078581d847152161307f7dbaabb33d54df4b6da8eb","nonce":"6eac26e93ca9a6772bc5998b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"2e7749d2cbc69aa38dc1c09269c40b6c5d6247ecb6a90fd2e84c70cba03a07cb566a894abab531558919f3142c","nonce":"6eac26e93ca9a6772bc5998a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"129916c1698305cb6f04b9de6328e9d3f4934bd14d103e897bfa8cd76855e7a42d109e100ce0f617e9df8e9411","nonce":"6eac26e93ca9a6772bc59985","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"3609a07895979e6fe672d4cd4efe79f898cfaf1b44a4bd9d18ff3e06aa24259de4972ddd94ff080e5f36830e21","nonce":"6eac26e93ca9a6772bc59984","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"bb4e7a36dca8fc22b507b17d081622a8c930e8c748f10213127d1fd28d294391ab9fc5c3c158cf169c5a50d7f4","nonce":"6eac26e93ca9a6772bc59987","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"1319078b7a41f3e6b5a6d3e2448849cf3e67aee8f8fe08ede592bef00f6fcf483bc2dca1ceecca2fbdf4f71459","nonce":"6eac26e93ca9a6772bc59986","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"65d2bcd56bf0c5f338bed27ea47eb5a945b748c980811910c485f6f4d28c5bf4e61bd72ed0e46cd5d7db15d922","nonce":"6eac26e93ca9a6772bc59981","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"0d73c577ad06403d265f7bec5988ab989ad1a04d6d71ebbfccf393728181663cb1267866e417da6279b19341e7","nonce":"6eac26e93ca9a6772bc59980","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"c9fa1985870772f4809257433077dcf2280d760dd0a75531981845502f07bdb6e7eb6b0daa657f136682b86f0b","nonce":"6eac26e93ca9a6772bc59983","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"42b58b467ba46f05992e82093dbad55495ba2ec31442cefbf3fe3a97a7d2d68390f4a81665cda125f69d75a759","nonce":"6eac26e93ca9a6772bc59982","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"ef18bc013d8117bc69cbf2a899fc9802e36b49ff460a95b3ad2bd3238c82ab8f3a0a6e1f6041bb7848055b4c12","nonce":"6eac26e93ca9a6772bc5999d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"fab9850907b225d4d6abcb9f9342234ca19ce0fd710b77eca72cdb9f658fb3137d49591df13b18708042550693","nonce":"6eac26e93ca9a6772bc5999c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"a41bd27b1347d405ca1df8a8bde2cf6b210a45869a74e5ab5523d5cf6bcdbabf1abe8d3fc4b9874a2f36ab343a","nonce":"6eac26e93ca9a6772bc5999f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"1e79ee75c85e6ae2d74110f108f8a27a206aaeddf49a67c4eb771613a9b895e9b51150e4d5d566e60613f043f4","nonce":"6eac26e93ca9a6772bc5999e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"b137e8e62a8a6cf538a4e79c30b5d2f10ff0b67abf0cd6872991b7d507e0be7bcd01f0dda47469395767738b30","nonce":"6eac26e93ca9a6772bc59999","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"92a2b661d3123046d53a23f9b5c845f767b4877b47025ec7959bd0b3c4540a66617b8d39ab4774e67a6a8c544c","nonce":"6eac26e93ca9a6772bc59998","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"eafbb608ca0531537e0869642564c8710b4598a4c4eca252b4f649fc764b466492ac3e66f0e02ae7cfcde6a529","nonce":"6eac26e93ca9a6772bc5999b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"6a0b59b36bce9b2bdeb91a30e74ccb9fb1a5a4d4c74a197a6f55feec1e65ce934192a114fc3b33aae8d4c11d87","nonce":"6eac26e93ca9a6772bc5999a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"8e291c4e9991de7f596db8b1f4ed8fb8f4734311ef23b18e7b58b7e5af2459999823d3de816966071d4ed27da1","nonce":"6eac26e93ca9a6772bc59995","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"52c145ba225f7782dbc3402ec7b492254588a5c0e6bcf95f62f3cf3970aeaf7049116ef82b36bebc518c574252","nonce":"6eac26e93ca9a6772bc59994","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"636f02aff124bba6bc2b527da4f9ce223651490458e8d1e53ff5219a3fbacf80cf26a91625a129b982a585ade1","nonce":"6eac26e93ca9a6772bc59997","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"ff2e4e5de0d6f1c96dc859fcd28f5dd4a1119c3d2525e10ac4de2124c48517b3163bde14e1430b2c2a5c5cd045","nonce":"6eac26e93ca9a6772bc59996","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"6360a5b2e2872234ddb23c6b44cd67436a1ff720a53fccab0ba090ccadbae0a3fe0078c7d8c7bdcb6c684e7354","nonce":"6eac26e93ca9a6772bc59991","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"70e63ba2b5ed481b861a27d6199a4d8faacdcaf8764985d63fbb58a58ae79922482efcdc00234090853babafa3","nonce":"6eac26e93ca9a6772bc59990","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"83ecff250e682fcc3b270b5ec86ab1674345322d499c2bd38a866ff646ea6d30a0df8b0b0fb9745e5057437d5d","nonce":"6eac26e93ca9a6772bc59993","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"8c65b0f9f363787c22716a80cc2768fff0cf2f7004975ec88a14fb2f02ddef20d8ea73af0ccccf32b7bc810b3f","nonce":"6eac26e93ca9a6772bc59992","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"2eaa5666aafe2206e090fe74cec2d5cdaf28a27673c3ddd4c9627800e09bf47978b01f1126bdc56ee83c2a7c9c","nonce":"6eac26e93ca9a6772bc599ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"4ae078539c1dafdd07fcda5cded2007c4fe077db03943d892e5bc9b5aedd154531b0aae678374382f086c5f2b6","nonce":"6eac26e93ca9a6772bc599ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"cd00b2f994e9b43cece95f1a3c623af34db586265a7dd90296e7029648f3381b47d191bd938213e7fd9cba82d9","nonce":"6eac26e93ca9a6772bc599af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"1c2ab2b246a09b7d1babcf39b89b178375c68f6e6ab307e244bf460499e342cd1451352efee14a7df66277b8a9","nonce":"6eac26e93ca9a6772bc599ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"6eda7222abed6a4ec7fe7e6c8462553599888792546cfb60afe114a6733325ab63f35a4fc55c9ece99018364a6","nonce":"6eac26e93ca9a6772bc599a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"0ea679d206ac2a3d8489664001d2dd9497a70f7a1c609996d2130d169d438738283b0080cc70e5698111ee717d","nonce":"6eac26e93ca9a6772bc599a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"ceb96406c690c7bb46d4d52269e5506f264508676d1602938d65a73e5fff2466ebd243dcae12d8f9f9ca73e80c","nonce":"6eac26e93ca9a6772bc599ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"69f8ea62254aaf2f0fd6e32bd061ffdc5cedbd26e3549bd8489fca1dec0a0658245be60da366a50da4c90f40b8","nonce":"6eac26e93ca9a6772bc599aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"1170d86e0a40e898a5c21121d891ec9959c5d7908e8e945a30f6d005f85da845aa6c0da7db7e08a51647c706be","nonce":"6eac26e93ca9a6772bc599a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"ca981b934d0c188d70a3b1d44bc642880a01efc59ce8700e2ce1cc8eca8b6caef6351962022470252d64986711","nonce":"6eac26e93ca9a6772bc599a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"7f56100e043d3d7f1200ffb3826c9bfe1e4757740f95f6ccbac1739148abdcf34bec65102652119767a3387b7a","nonce":"6eac26e93ca9a6772bc599a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"cf01f8dc2b10bca6a337b5fa49c3265e45f71b4cc08caa22f7f4e7c580f512c242f054200524ccef509a3e8c5d","nonce":"6eac26e93ca9a6772bc599a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"a3e532ac84833ecc7307202ab02b4604d8368f23b943c664300a8b7d821065204f64cd6b2cbc371ed884dfed5a","nonce":"6eac26e93ca9a6772bc599a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"09cc0f87505497f63bac68634eef3d6c68ba081025ce066eb5f7513ee8234588792e0bd777e5e76bf75dd0f26c","nonce":"6eac26e93ca9a6772bc599a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"9e09c5f09e54fb5129f737f36626f537c851e24041be5883d01e09e7a0a864007c69907e89633256ece1f3e4f6","nonce":"6eac26e93ca9a6772bc599a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"a8eebd3c9272bf3e39a742df32dc64792f210a5b1b2a46235de48e7be275c6aa156f701dfa429d390a88a0e72c","nonce":"6eac26e93ca9a6772bc599a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"af6a2e90a762c58de2bd5fc1320f49e6f5e2732620e15ce2b5188d5aa3e41d38ba610682bbb25b8eb0fd18afda","nonce":"6eac26e93ca9a6772bc599bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"fe5d18dcaaa96985e439656e20207d232e73618e264cb29fe46c51a5f1d10091953bdd1973a3db196212175b36","nonce":"6eac26e93ca9a6772bc599bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"f143215291f20176dc3bb987dc0ded5b600cda381b9d6346622dd95c98dec7c42244c5142453b7c8340dac45a4","nonce":"6eac26e93ca9a6772bc599bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"5e63f87d506ecae25e2a5dbaf1a83ed2eadd68f2d120587cef712408e0b7f5158cfe3a130531a615641f33827a","nonce":"6eac26e93ca9a6772bc599be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"d932023f8d12f2375e26ba671c52870640dc91fd5d5872ee7d6fa26b06fc9fe439527b7b984f1eadc5b8375ed8","nonce":"6eac26e93ca9a6772bc599b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"af491eafb89598bf1d9e05936f1f8e355c2c6efe57157a69c029576724635ed6724ed436060379c90b22e3702e","nonce":"6eac26e93ca9a6772bc599b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"789f91d56e414b46bc50778de026f2a4983fed1d994aba540131f30b6e40ac9fe38d61be1d78093959f2afe7c9","nonce":"6eac26e93ca9a6772bc599bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"d19f40d3c8c3a939feda4f3432847415f4d102f9c2966b7b9202895657748591e570fbad29b24d3434fa6e34f3","nonce":"6eac26e93ca9a6772bc599ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"590cc735ecd37e4b491fd70e05b92440f73099259e6c7b52c9aaa399f63a99283670210d7f7fa0dbabd606c3c3","nonce":"6eac26e93ca9a6772bc599b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"024738e4d2c2396479d243f85d3f475c423ea7d2d99493a1095f994a5940fccb4c06e1c5a4d7673118b62a5642","nonce":"6eac26e93ca9a6772bc599b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"512c56845976f51724e612d5c3fe084d6c2004432c940a841e15efa09446f047c4965bb133c2614fc3756fbaa7","nonce":"6eac26e93ca9a6772bc599b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"938e0092317c561db12dc8705421a444da0268c648ce75a84d159f4a5f0c6fe1c0af27209906b51ba8272ddb21","nonce":"6eac26e93ca9a6772bc599b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"33b55e591ef224999665595020e5cd65490780c52005a201c3ecec31833a8ee089c64285c0be8f351a2af04057","nonce":"6eac26e93ca9a6772bc599b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"e4c37382b555add6aa306c480ddc16a1baace74a016da6b696288d6c3a390c62b44e19b84de70527f38e61c79f","nonce":"6eac26e93ca9a6772bc599b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"e0e2dcbb05028e98ffbd19469c5995e9eca5ffeac5b25c0d982e2fc0ca411d51b25f98d65a6a4b5afa5ba798ba","nonce":"6eac26e93ca9a6772bc599b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"a9f6da4533f0ac5e1a9fe127c904005949acc9cda98c5343cc9a60171f8dcbf453e46dcda774e9e3618dd43e35","nonce":"6eac26e93ca9a6772bc599b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"260c5837b834e5d489d5e30cd138bcd09839466e3fbd296563d59e6dd4a8d0fb2d84edcd47fdf0fc11caaf5f6a","nonce":"6eac26e93ca9a6772bc599cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"5fb79aa249ef46aad8bfbfa8da811953938038aecbffec95069ea31f87ea47b062b8cf395a6b3765ae57f52b52","nonce":"6eac26e93ca9a6772bc599cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"b40c1fb4be3c8864a4a950d67487c83b4fe1744d295f2a226fb15ca495dc2cb3db333fe986393fcb17a09fe916","nonce":"6eac26e93ca9a6772bc599cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"eba944981486905ec1c6fda8cdb98b7329fc5d0f3cf1ecb4eb5e68510e86b1313b31453a10c082d2026ec165cb","nonce":"6eac26e93ca9a6772bc599ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"b644d94c671291e7bdaaeac9c8f1767d85cc2bc42082d770000bcbcbb46e37cd57ca771c2c0e561faa8dc3b8cc","nonce":"6eac26e93ca9a6772bc599c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"6d2bbcf30229c1268cf91b434d40cfa74b30adcec148c27cc1f8af2099e956c33fd125e683ff6ff4f83c1902fb","nonce":"6eac26e93ca9a6772bc599c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"9c61a9f985cbca7d9b7e9a491d0f51af9cd1effa066b69e619533aca6fc546c04ae8b6ad7440ff045ec434e93f","nonce":"6eac26e93ca9a6772bc599cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"5e9f77d02f6378a9504c5a8675b09a226d4de54cf24cabd6d19517dc905503811fe9d65f82d40ebc759a4b68ff","nonce":"6eac26e93ca9a6772bc599ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"87287f95d272c86983a6523ceb2c61648e223a68f87a4f0bec71994354695621bd45b35ba7d1529cdaeffcaa97","nonce":"6eac26e93ca9a6772bc599c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"d1bf7b3a1b9e7f55d474f0d8168efbe12ee1ea29dc16ebbad2c4790b4722922fa75e6b16475f2257833a6adcde","nonce":"6eac26e93ca9a6772bc599c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"95e8470acb1e3a2a0d174fdb89f3ee7f97d55fd7aeafd0628836f6b18f09782a869bc50395446c4f3d091a5b20","nonce":"6eac26e93ca9a6772bc599c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"42d0b2810f9fa66e3a68e4e55394db859e8eba52fee88270a93841e16299ede143bf46c3f2fede522019b9c3dc","nonce":"6eac26e93ca9a6772bc599c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"982b77f1bb739a1f5466c0c570dfd1da64fbebab240428b1e019894158ea5462715a7167cd269a145c2aec9a73","nonce":"6eac26e93ca9a6772bc599c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"b9656067a0e16977acbdb3948ac4dd2e96d9376e69aa13184279448f640cbbd9878ac1fecb22ab49dec5616f97","nonce":"6eac26e93ca9a6772bc599c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"2ba2fac1de832b3bc48e8e0b25deba1876b6a687705455c66d152e32b6d8e7c811c88eed17d24dcaa49758d6bd","nonce":"6eac26e93ca9a6772bc599c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"002bb0953ec6763600a544a6ca0cea760bb6aa0364f76e30b2175afdb8eea30f27368a3f0036eb1d3f1ccaf691","nonce":"6eac26e93ca9a6772bc599c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"360939b6a415f028ee007e78ce6c5ca209b7592a632f936fd1b1c02467882dcd7fb4419010d0b02f7190501480","nonce":"6eac26e93ca9a6772bc599dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"23ddcebfd41321cfcd02a8753afee1671281dd0b8f92555a0a5d087d903ea522fcaa3de985fb2d28eaa8425f19","nonce":"6eac26e93ca9a6772bc599dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"1767e9a604e4e1af2908e36325c4122dd233ed3e8492d811b61aa1bfe0ec0d58a63631c4cfb389691b451b1982","nonce":"6eac26e93ca9a6772bc599df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"4262ceb2f4be72597b9fb255b1319f8b8ed1b45f483fa7e801e097d61e9125f9a62da350ffb6d09e3e010c9404","nonce":"6eac26e93ca9a6772bc599de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"09e94741816e40e46349638b0d35c8b6b495b6a38694a674c0e0808aaf66496b0820942fbe8319354f00584eb3","nonce":"6eac26e93ca9a6772bc599d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"1a5d13d4a31e160298c46f3b6bf28f149f11d11c8d04ab3d6b2764be292f005208b04c42e92c0f894048ac2f0f","nonce":"6eac26e93ca9a6772bc599d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"bfb98f5b8628b18fb6dbbb3ad81bf800b6abb5400aba52ef3fc6a63ed8e9112f5313900850cd301369402ac53a","nonce":"6eac26e93ca9a6772bc599db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"31efe8346fcafea981889cd5adb98d9fae8cc90a7be80e11f926a235acb5c227eac3983ea7acc0bcf09245db46","nonce":"6eac26e93ca9a6772bc599da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"a9c58d9ce815830a9fd2e880e1c891eb3df5a247900891ba3a4e683a9529b5cb3e904411b9d1ff99315458eaba","nonce":"6eac26e93ca9a6772bc599d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"150a8bb6f5d887a7230d9d3c5de43cdae87dad1aa77c2f4d4f1c33a45d732c81940410c1f7608557c9189399ed","nonce":"6eac26e93ca9a6772bc599d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"62e607ec8b6dd920a5ba83b301ff4f4bd71c6f97a32ce8977d9ec68ed1ba520d1bdd4870ab23e7c1f91021f885","nonce":"6eac26e93ca9a6772bc599d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"2453c22d79d50789fa0b81d34c7810d58a2297d7f4e025cb9fdbd8047c87018a11e124e5b11793f77f5006fd1a","nonce":"6eac26e93ca9a6772bc599d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"19db76bed25dda0be0bb9407768c838eaa81b401289de59cdedeafa9ef3282f8c834c18b92e9986c438f826029","nonce":"6eac26e93ca9a6772bc599d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"13ee87f5de946e282f7dfee46b903dd5410c58d842bd14563a29e4c64c53f439075ae3286a3628d3634264f86b","nonce":"6eac26e93ca9a6772bc599d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"30fc97b6e78c5461747ced4949c33a93a8678de83891befd34f89a15e5bb3527a0889b4aa2c058d0c96e514216","nonce":"6eac26e93ca9a6772bc599d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"9f292115d873606e2c9a1261cc35525c262a69e9dcdd37c5704b08f55c3cc0af9ab6a8e31e3f0e7ec56306bcd4","nonce":"6eac26e93ca9a6772bc599d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"5dd0b39c253b3657bb568b42065126db5963530bbe98c9140183688dfd2b3fd62c7101f83fd3a605f73b75fae0","nonce":"6eac26e93ca9a6772bc599ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"10be6b9b17289fa2adecdf1ff564747d0d18a8f86c2b857e1cfa814d15e5218e5584e57a8b4c0d9bc36de94417","nonce":"6eac26e93ca9a6772bc599ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"a08f031f19cee81e4bc28e1d404dbae0a1bc7fd36cdf6a5fdc2f9ec07fae660569653eff8f9e233df2b5a51618","nonce":"6eac26e93ca9a6772bc599ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"50c9fe3fc6ed6d2e18589963e74dd79e602943d0a203ea5d739ac7bbcda7b3767029a4a20f527b88005fd82cc4","nonce":"6eac26e93ca9a6772bc599ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"80543d159ada0382cdf2ba83ffa2079be9ecaf2d7bd182a567e11f55b3c80e98b00e4415be7620d79fadd4715c","nonce":"6eac26e93ca9a6772bc599e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"e6b2c2933a087107ed92b196768171d2cc1c3e1f979d0ba5290bee5eef63708ffb0a198931f32c351060aafeb8","nonce":"6eac26e93ca9a6772bc599e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"79ccb0d5d6aeaa7619e0e2dc7444104f1d436c92b9fc01441fc3f1a414f9bc08af60da91778b94cb05381c404a","nonce":"6eac26e93ca9a6772bc599eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"d860e1e338a8efb62ec58f144a33fd3e1049fb761d1508deff81fc69d29788e8fae9a7199adbdc9850c6e79cb2","nonce":"6eac26e93ca9a6772bc599ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"82cb47cd690032e451ef673a44963c4f9c6cd44b3cd01c6588de1ad5a16d30f0c4d2af73868568578862c0aa9d","nonce":"6eac26e93ca9a6772bc599e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"52fcda89cf60e796fbc68a992187d9f6496a5a932e313ac3e946510d540dd417651b0b13112c85d81b08bf4099","nonce":"6eac26e93ca9a6772bc599e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"1004fb188c9cdb41305adee25aab22febbda8149ab57874cdfd7393232dc2a155df0d6402463e29e0fb3574cb2","nonce":"6eac26e93ca9a6772bc599e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"9cdc1cedf2681950033a9cb5806a9e9bea06e58a586c9a4a1d37c105455d3e7e58ffdfb3bca58f1a074ac0a79c","nonce":"6eac26e93ca9a6772bc599e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"ade0dc1a0f15d4888083584b22f877aacd2d06886268b06344de4728e08509a1bb9aa402ac173fd3a6356c224d","nonce":"6eac26e93ca9a6772bc599e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"24e2fee8fd830a21e53f28b903065b9c5ff906d3b359629eb95143a610f824d1da899b3e1d1631b90bf0f021cd","nonce":"6eac26e93ca9a6772bc599e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"6b42f5b3668b1ea0f5ba1f79cf39adffa62508c77ccfbbdc17792ac2e267851f39aede5db9b4e50c22b640f852","nonce":"6eac26e93ca9a6772bc599e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"cbfb7eca2de7d763dbdf04dcc70dd7d8f9d726affbb7cad6fb09fd49206ea937314ce8951906b6b8a670782145","nonce":"6eac26e93ca9a6772bc599e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"f3609830a7da9ffff516f39b8e4210c0442b186b5d552ef7dee58200e053d9fd1593f571818d4fb233fc8b4b98","nonce":"6eac26e93ca9a6772bc599fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"a60773f54ea18b148e935b7cb5493c729b0eef3ba5c4fbae2736ac70dd7090736b27f773b9e68b9170da83f4ff","nonce":"6eac26e93ca9a6772bc599fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"a7ec2dadaad00612d121bb158e8bf8467ed85fe70c645c9d6fa956ce635ce6a1391b69f5268755b1ba58bfd388","nonce":"6eac26e93ca9a6772bc599ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"4edaada7b324e505862e2a6a4fd64fdc71c8c007c2142a0f02e38c1c0a4422e93670287b3ff739013b1f316193","nonce":"6eac26e93ca9a6772bc599fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"e9abc2309da5096de3f6100ea4955b79bd90580aefc063bceabc2521de3ac04daf33c4b10f9be3d2db309d0663","nonce":"6eac26e93ca9a6772bc599f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"f50ce3ebc22ed1012f8dec8be832552f4c37591d480c9fae16da39facd941f480e8bb04564703838b982333386","nonce":"6eac26e93ca9a6772bc599f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"66cc8ecaf7e931b80193502567254d4a2a34115a8430c243fce15ca49eabf7fd7531e34c5ffd35bcedb9e1a53d","nonce":"6eac26e93ca9a6772bc599fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"ca8283b2cee304dcc542e295cd365615e2a2d283e591492cabdde6e1c1c5f4b379fa978cbd0fb3767d9a027033","nonce":"6eac26e93ca9a6772bc599fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"800172f60212753bf23952dc16750e368f8ceb2d2b87ada37779d57796d316e3e535e88ca9dd96d6cc46db0ad6","nonce":"6eac26e93ca9a6772bc599f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"3094d38c2909a286d22ebbfb16a45b095702cb37d3661190c457ce8639a422224f5ea739fe97820fa9b31e2dfb","nonce":"6eac26e93ca9a6772bc599f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"b0d714aacd8aa21f720d74d355f1154257e81bc23502004eca87d0319e06cbc12d7e7767c26b5326889152dbd4","nonce":"6eac26e93ca9a6772bc599f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"9f6586e6c17550e3ee1af4bc7d7fdb50a1f1872a3a770d4f3b5f2a85aec1dacb4f11af5cbf0ee97b61fd053c91","nonce":"6eac26e93ca9a6772bc599f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"fac4121f366c87509fec56a80b5ae374ed2122b528e99853ca60225312bf8d26f100338333fbd823870dab0bf3","nonce":"6eac26e93ca9a6772bc599f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"ec068bcb6a2c1181cd4e96e1c6a71057a93fc33e251b1e413027c502c3807447d8ef1816b42ca42b6b3474027a","nonce":"6eac26e93ca9a6772bc599f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"368e888966e3bdda0c00c08074bccd00c450cd0e3ab033a46b73011d5beddb9666b2eed8505c68d91ef5e3ca33","nonce":"6eac26e93ca9a6772bc599f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"352276dc7ad4fcae86aed2c55a543519701d85c11c49f053f35b68b84c9e37534a030740b976ed621861f0dd2d","nonce":"6eac26e93ca9a6772bc599f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"2914fcb5cb68397ed18cd139a2f65eb3c4695760e22a54b8fee2e7cdf62505f19171c00e48ed8e1b46a05d6b61","nonce":"6eac26e93ca9a6772bc5980d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"e14cb7319666c34d6bacd5b7f2f7d45b877f77d27f74279f728b7442fe939257"},{"exporter_context":"00","L":32,"exported_value":"3f1f049e80d67fa30235490ea2f1f384992a3eeccbbda9393290805f3a791b98"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"197afaa956bb7d00cb2a7c5177ddcd0a8f61ab0bf772f459c7338eba49774bed"}]},{"mode":0,"kem_id":32,"kdf_id":1,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"d5b09b6a5e44852d7d5de180b6cd07a1cda48cdc561015134458ea3fbea35ec5","ikmE":"dfd175121e21c253a93df7fab2b69fb20112320188532abb11f2ff74efc5c724","skRm":"4f8282f1b30e39a5d7f3fcccf73d8044a09d89ac168c1929f179e2e93e20b8ae","skEm":"28e212563a8b6f068af7ff17400ff1baf23612b7a738bbaf5dfb321b2b5b431a","pkRm":"ac66bae9ffa270cf4a89ed9f274e30c0456babae2572aaaf002ff0d8884ab018","pkEm":"8e806d41aecfcece96a6b47f1e488a3ac6e48090d9b634355c705dd34311d900","enc":"8e806d41aecfcece96a6b47f1e488a3ac6e48090d9b634355c705dd34311d900","shared_secret":"80d96bdd3f508642a68fb2830e2ef4ce03eb527cc07dfc594d930b08fb573f9c","key_schedule_context":"004ce5472ecdd5093ba0aecb8f871ff13f1fbc90ee76f0e18ace1a1b7e565bafa306f6ef962c9ee7cea40407b5d60f0f26990472faae3ac44c78366f1cac1ecde1","secret":"56eb422dd511b0d0daed680be72cace6d3420efe71012e42e6311ede851f100f","key":"d7c0d49221e08f1a9270fed5ace0e600e570c766c83e19643d520670299a97d1","base_nonce":"a243fc1ebc972a48eaf28ea9","exporter_secret":"645487c1f4008c3ef3341576aa1011fc9c69cdccf7f9f4f3e0fc8c2307d58a5f","encryptions":[{"aad":"436f756e742d30","ciphertext":"23ded2d5d90ea89d975dac4792b297240f194952d7421aacbff0474100052b6bb8aa58d18ef6c42b6960e2e28f","nonce":"a243fc1ebc972a48eaf28ea9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"ced7f6e355712d722a7354968e5e83f1c77814fd2816a8fa4a6aed2dfd3297815d7dcd21ef905230cfbadd1cde","nonce":"a243fc1ebc972a48eaf28ea8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"842cf2d63d152ebbbe7a1ecc39671d0efb328e0b05c592ea7be59819f0567662783587fcb1deb96f2cad51e56c","nonce":"a243fc1ebc972a48eaf28eab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"e87dd08563e2df517d7fd46ceaf54cd1b60e664f5e14cb0c8d292528c558ee36131ab36e79d9fcb4b23a22ba6f","nonce":"a243fc1ebc972a48eaf28eaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"e772130cdbaf62e2aa8ff78078f84c7dce3b16ebd970d4997b6117d736843d7fc3b712108c4912086e510099e7","nonce":"a243fc1ebc972a48eaf28ead","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"eb2776c69528944280c469c34fb26c7b865506c14c5429ae02a7fb7a8e8f611292a74a4c0f0eaba91f4f0adceb","nonce":"a243fc1ebc972a48eaf28eac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"85d88b678ff907967f189cd6f4fb4b3d2ec9ac77f4ddf8ed0f49b646acf9aa2b56d89052ec33b78e88f4430eb3","nonce":"a243fc1ebc972a48eaf28eaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"a9e091e5541c5dae452739233d1966da69e86678ff735108386d1202ac92b3e8765c489016042ccd50c34c55ec","nonce":"a243fc1ebc972a48eaf28eae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"f6379b49f4cf8be756bb51cba9f89c35b384fdfcab8af2f5691a2de635d8eaf36b9d06808336288bff50f716fb","nonce":"a243fc1ebc972a48eaf28ea1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"90fa74418a15c91ebe4c94ae37fe930bbad9489be610b76b894923fd5c8bf4251d6ca88353e3485e4dc3cb9371","nonce":"a243fc1ebc972a48eaf28ea0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"43c3ab517dd7f203bab193badd47fd49eea7e3545a37bbdfaabb4b0d9658d9522b2131a4341ee57f0d6e581bb1","nonce":"a243fc1ebc972a48eaf28ea3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"9d1225d95bbeb52fe6ab99c3ef404f71d4e05c4e3c56eadfff2a017166a41e11dc0e83f864020eac85ce52ca52","nonce":"a243fc1ebc972a48eaf28ea2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"6de80fbcb0249d747c86b668def1d2edcce118ed50ac57f2c90bcd40a4aee3459a58f9c086af09080731d3978c","nonce":"a243fc1ebc972a48eaf28ea5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"b952f5513f8a3e2407fb7f2af5b21ea49629d5888fb78ca0830d64f504269f76a61d515da4697d793bd6afbf70","nonce":"a243fc1ebc972a48eaf28ea4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"89ae533b9a4a609fb42dadda1409fd9aaa3b96a8fb1c8f40de18bafbad1efa31b50145f694fe7889540ccec73c","nonce":"a243fc1ebc972a48eaf28ea7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"283ca163e1cde53b5baf5bd17b031cf84f0c95852cc1291ba85b3f0b2e7be5c2a7519d09c99ac81f35bac7b93c","nonce":"a243fc1ebc972a48eaf28ea6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"ad7750f3aa0bc09314073f43effa81abc1779cc4ee157786d0c7e2a47bfb0ac4803be3caf223bf3da83c6967cb","nonce":"a243fc1ebc972a48eaf28eb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"c2ca31ef04ab31f07dbaf492c5bdf7b29b1114abca5f8ea0619a505f5f3b9ff888038412a1933de261e0ba1263","nonce":"a243fc1ebc972a48eaf28eb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"0575e17db7cf48470437838eca3bce5b7f9493ab4ba663b9390ed900405a3140c57dff1b1d4fd6e48046882978","nonce":"a243fc1ebc972a48eaf28ebb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"fb10f07ed4a994455e341893dfa490068419721fb85baae002f6937b01ae72ba4baed2f6a0e5a92c9a8bbbd473","nonce":"a243fc1ebc972a48eaf28eba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"d0b621b0b932504bef646623f676bd9d54ce1ca86cee9fae522217918531ce98757658a0ad73e5d5faf3d47291","nonce":"a243fc1ebc972a48eaf28ebd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"b52badfb0ba127ac2eec345e13876b13ee44643cddc32f76dddaff7a55131bf39fed5b0a4477d4c01ea6351d0b","nonce":"a243fc1ebc972a48eaf28ebc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"46f0ff9f1d2d15be5e698ee8cbefd68cb602b99c3b81d68b4bd32a07e03c016b2ba97b90fbf3ddb2c13aa981d3","nonce":"a243fc1ebc972a48eaf28ebf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"5a44c9299ebf87e9acfd41f4a2d8070c2b05e6ed3c81565b17b9b7bcd871c28be5825f1b315ce137331bfdbc68","nonce":"a243fc1ebc972a48eaf28ebe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"245b39f8b39882a3e3274a4e8e50b8ceced97cf83707955af76046fd4b5c68a7e6ebb1a86749c7322276756cd7","nonce":"a243fc1ebc972a48eaf28eb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"74dbf7a8d6ed014e7d60600f99db5dd8d6b89579964589d9f9d80312c79e3b957d2a6b84e99b57c15b6f282673","nonce":"a243fc1ebc972a48eaf28eb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"9b592893a02831169656b1a18aa63d1d888b879a7177eed20effd120145b94fa5816c792b910fa351f67aa83e4","nonce":"a243fc1ebc972a48eaf28eb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"8f28a8992a4df78ba36aa8f9fe06b98f9252e4893f412ad74623631a1894802821bafd0de63075b250a5cc5469","nonce":"a243fc1ebc972a48eaf28eb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"8a693666aef0d4e456b98052b4ee94a2e3fc19be65cf1bdd821621e1ffbbae9be7303a908a299bab9113758f2b","nonce":"a243fc1ebc972a48eaf28eb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"d85dca2482c369df79f2e7db1bae4c0f4156b7069250a90373dcf4e98b463dc590ca9cce0880a7e58ef8a5c6d1","nonce":"a243fc1ebc972a48eaf28eb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"18638d637433a6ce39ddca186af8abf85b74e87c16e4e1cd0b7531387e7c2e6b8bf19537df844c98d8e1c6d532","nonce":"a243fc1ebc972a48eaf28eb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"0e83dd1006a4f8a0f405a210082d61cdb486a99ecd4778990e21d5f28500c35ce74fe0e30a2177083b0ec0a446","nonce":"a243fc1ebc972a48eaf28eb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"ea2cb7fd56c892692295b39f56af8d1535601f7d2d617e0eeeb023b42ed17ce885c4e2ffc2965fc928ffc54d7e","nonce":"a243fc1ebc972a48eaf28e89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"06ddd33b2df8e547c063fd2ae00ba9463ef9a231d2ed440ec3a44f77fe34ff28b3ddbd11c565c8233a17dd007f","nonce":"a243fc1ebc972a48eaf28e88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"9cb2108dfcc1902a4ee57a72d97141f4f1e844193cf1aebd4e86db4dab15575a89a73fa93abe5098563e82ccb3","nonce":"a243fc1ebc972a48eaf28e8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"07b13c1f1053ddf141361f29ae628be6de57545f07672f9261114bc83ebdb05ffc058f821f204cc3f172c5e081","nonce":"a243fc1ebc972a48eaf28e8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"607ac6369eaaac716d82024d7638df8a711fe961b00598be497cab2a76dbe603d86c2ca97a8e3bd687abe45da1","nonce":"a243fc1ebc972a48eaf28e8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"36c0a105599a8e228232ea044e135dcc8a6780acde1c4b70de6c83a0332bcbf19edcd760898e31d394dd58b817","nonce":"a243fc1ebc972a48eaf28e8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"2105e3a8edf979d4600dcfe724e0c774bbbcb3c130bad977c6ba63c17ec33edb105da45bffee9fb1a2e923988d","nonce":"a243fc1ebc972a48eaf28e8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"3d2909960783c633f40f1573412d161e7e30099485d36fdb2f5cf0539bf620bbf5af4355f37e76fd27462b036c","nonce":"a243fc1ebc972a48eaf28e8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"ed28f9bf126ae456bf00d030c51c003882fd79bd0352c690c54ec862a0e6f31274302ff3f8dcef90f9be993fce","nonce":"a243fc1ebc972a48eaf28e81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"1582f8312e48b25770f370511f8330eff2698c863216f3c77710bbf4b234a2363adacd4676581cd29576b1af6d","nonce":"a243fc1ebc972a48eaf28e80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"3c276dbe05f783d4df6207da28922eeb4ee11c01b995267a71b514be40691909731f78c9208b43a543e2f96b4b","nonce":"a243fc1ebc972a48eaf28e83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"e6ed2cb97e69156a05368b14515a9a0dfe18ca3729411db0983b63269cacf5dbedb7778adf67082cbad29e5a13","nonce":"a243fc1ebc972a48eaf28e82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"715874922609748d64c1c34f492740a7e161f2fb67221b1d3c4f34ee12a682132668f62ccf1e14ca112c23b5a6","nonce":"a243fc1ebc972a48eaf28e85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"e769212990ee3ed63d729687cdad6a64f91c05dad039275e6cf27722bbfb40a777d3efea2da9a959a299a10ec5","nonce":"a243fc1ebc972a48eaf28e84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"94cef99a452a4a6f67112a41b0d90032cd89e77c9422e8873ddb92a9412c031219cdd309d659ab7e189337040b","nonce":"a243fc1ebc972a48eaf28e87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"163f983534bb70c192fcbd41a1ee355dc85030ef3b5a0861594b95e122d2d3aff804bd080e92ac4a0f0a530c6d","nonce":"a243fc1ebc972a48eaf28e86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"88c7b712f09c6fa040b192144c8a64217cdbe208a9efdc01934978c27a87d495625bd58948daa3c56df0929683","nonce":"a243fc1ebc972a48eaf28e99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"e720cd2d2177d2907158b116badb07361a01e1fef8d3a9654cc4ee2237a9805aa2ccc6370bae68588466fa367d","nonce":"a243fc1ebc972a48eaf28e98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"197f976656d32639790750f46d3a54b617f977003045d7811f46fb4b3dbb0e74c1aa2658b8c1f53623b0e6a9ef","nonce":"a243fc1ebc972a48eaf28e9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"70ae88d589159953d7b95f34b7444a7a94d392349c7fb5847f587e5dd32ddacb7dba0bb031fbcbbc12e43101fe","nonce":"a243fc1ebc972a48eaf28e9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"3a5b2577e7a298f6df5da23ef8fe12fd9700a917a9dde4fabbec6c11055e45183ed7ddc617247e66071701b357","nonce":"a243fc1ebc972a48eaf28e9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"0267d58725763676db456cc088fd32dce997e0198e3bbb32956c71104d2135c577fdafd01c29000b877791f624","nonce":"a243fc1ebc972a48eaf28e9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"df0f00ddcf37c1d48495709f2d4554ac1263da35e4789d30fe82d2475d80723f8c5d169c2300b0c06872b0c92e","nonce":"a243fc1ebc972a48eaf28e9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"abba75e8efce9e8ddc7509aa1699b52ebfcdec85f29857412614e3eababb5a5fa35ca38356e1144ee286697fcb","nonce":"a243fc1ebc972a48eaf28e9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"67fb1d3d57003076e498f5bcb7d64ccd46b6612fbdcaaefeb212e636f4d03763b79ac4f36f3ffccbe0e3e9bc3f","nonce":"a243fc1ebc972a48eaf28e91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"8dd52b9e1dc06c96ddd110ed7b99176aefc0e58b457a667d0bdf35c6b2522ecfaa85042467222caacaba6d35e7","nonce":"a243fc1ebc972a48eaf28e90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"de3b28713a5566e5990c3ab544aadc3b9802ba03c1dc5a2143dfdabeedf7cb44131e86c4458ef78d37c1b9e42e","nonce":"a243fc1ebc972a48eaf28e93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"05a1211c9933bbb004062dd6d7d2cbfa6018094fd5ff2dcf8c7eed58c5bd6385617054fdb78a11a7efc3b58f3b","nonce":"a243fc1ebc972a48eaf28e92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"4d4b228f18c80c103d865847e2ce5f4038d0ad7bf87f37108b0d352759a08735f05e42849d68777f207ee0b114","nonce":"a243fc1ebc972a48eaf28e95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"f0544ad9cbbdc3b432af0f175b4cdb258f18c266562ec4f0443a23b9ec068456343c434056d6f8dfc6d9319e0b","nonce":"a243fc1ebc972a48eaf28e94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"565b02a8bcacb15e7aac8f18310b64ee9231453177352d7a26b0caa4c56c89dfbb0759b927e92abcb01883ab41","nonce":"a243fc1ebc972a48eaf28e97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"1d21c224abc222521b2392c3ca599637dd032204977e0bcc8b4df243f5af80e6cb2b982af75c46ac9574291089","nonce":"a243fc1ebc972a48eaf28e96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"fba6f2eeb0206bbc5aa462ad20fa97967db3b448fba89a7fc530ee0d3dab5f26180f5630bf0068635f2324dbd1","nonce":"a243fc1ebc972a48eaf28ee9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"a6d89e1a87f059b228c5df94c49c170c5a22173e4f69ce503375061163e83bdf6dcba895a20c117dc297153e96","nonce":"a243fc1ebc972a48eaf28ee8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"2fc1754b0dd272448c432b9cc1340452dc57368c242486f032c2422184f0b05ed39adb360badf2fd6335d2a55a","nonce":"a243fc1ebc972a48eaf28eeb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"8d0037fc6fa4fa489747a69f40191e41f9cfedafa883f093b0c3021cdfcd4658fea0c947bce69744ba71d8643f","nonce":"a243fc1ebc972a48eaf28eea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"e1a10e29f987c8c4eb8744a40c7d3567bcd376a20aa5209d49198657caec87b53c547437bfd7baa32ab8db7c2e","nonce":"a243fc1ebc972a48eaf28eed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"5beeea632e795fa425122324b20286248a111c0003cb5b16189817541714f9850f80e10d38ee636cd11cc92c38","nonce":"a243fc1ebc972a48eaf28eec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"661da48efc06d90cb468c189b8347743a13971800f43ec1bf51f16a9a4e8509db12efea51e3b04922327fbc149","nonce":"a243fc1ebc972a48eaf28eef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"26629a94619aaa9db1f1afc6927519356072a1da6a924e5d053eb4ff7730f3931f41730eb612e9831025ca6e0e","nonce":"a243fc1ebc972a48eaf28eee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"55c59647a2a98c65cda4d9075caec37a5712a0f20f8040956f63b4d723cbcbb35807c12622e84deba9f4141982","nonce":"a243fc1ebc972a48eaf28ee1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"80025cff1038f0729ee0f28e19648822a3b60eee18578c30288ce17a3a7cb9fd378540035d5bc723f8170d8fae","nonce":"a243fc1ebc972a48eaf28ee0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"2dd11de94b12b707f07195f28493d54d21495a3878ccf2a7cf0c8e71c60598affa1a5c0af720ec8bc7093cc53f","nonce":"a243fc1ebc972a48eaf28ee3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"0d9fd3c7b1ef7c4905b8d66944c2257d0ed550fdc46fe83813a7c1ed0cfcd7e413afd96afee9f5676677e762ad","nonce":"a243fc1ebc972a48eaf28ee2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"95287f89f51f7df460df160cd236ac981edda1f128017dbb4916446232e23ba06b4a99f9e3fc89561e13348cd0","nonce":"a243fc1ebc972a48eaf28ee5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"8dfe4304019b4cb27eadbbcad74f26e1566daa62a2cf6e492e5d11586d350b898102cadebc67a63d62b73bf461","nonce":"a243fc1ebc972a48eaf28ee4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"03237d347da6979ca0d5c1bc8bf3ab9e553ef60ca18059d6a59ffd9525cd33beff001ca2d9fbcccad2b3273182","nonce":"a243fc1ebc972a48eaf28ee7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"1acd3c98544653048b2293d1dbda0b3847964daf218c1586fb15150695aee7e9ccfcc51893172a1f7aaf763f7f","nonce":"a243fc1ebc972a48eaf28ee6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"9f8431aee69a4bdcc7b1ba8c867dddee7032cf6e04632dbb6d896f7de9d6d23f4941df8ff3c8f2a05744b99513","nonce":"a243fc1ebc972a48eaf28ef9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"f024a7ca3d5b5661577014b24c75c3d78fc2e91c088c4b88b4ba78cca7d7ebf92c909a09925f5316d67068dddc","nonce":"a243fc1ebc972a48eaf28ef8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"b2fc0a1a173157db857cd4dce0a8604ca1dec1ce9d094d6ea05f3da0f894e8e84676cf5627bdf7dec368e0dc36","nonce":"a243fc1ebc972a48eaf28efb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"45e5945c3fa0e27e331fc6d72f5d45a4685dd05864df233d08825ceb190a3e18fd6256732dab484cb3ac11db43","nonce":"a243fc1ebc972a48eaf28efa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"f47c3949d279d114a3a4c5b9c87a3a087266f2f57b917914c012d9d48c058d278d9508b65d2e7f9dac11798005","nonce":"a243fc1ebc972a48eaf28efd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"f061c1b0c1362ab1a877822b351cb353ff6164e0a1106cbfba29cb4015caaaaff6f24311e732e6b5588a1307ed","nonce":"a243fc1ebc972a48eaf28efc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"c8a3448634a86a344ac4a16b83877a4add81ee994d81cab08cf9f19b1b3474f066f1b6cc96ad6d406f464e5d6a","nonce":"a243fc1ebc972a48eaf28eff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"7dfca2af63cc2c7d0801372a703c7d6b9a57b9d09ae434440a6099ec8b9be54e92ad9a2fff7282d091da9027b4","nonce":"a243fc1ebc972a48eaf28efe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"f6c6f47f8f9e224a44a8c0e7f81a62371cefb611aa3907dba734538fa3e62d94734d5196b7ebd702126dc155f0","nonce":"a243fc1ebc972a48eaf28ef1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"09c92df2fbaa8b5c3e3134cfec9ef91ff1dd23adb755194cd10fbb61ed42fe6d305c1835607f431499dce5c6ca","nonce":"a243fc1ebc972a48eaf28ef0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"b8d71aaff92e6bcfb7426801d73f3abc5fd1b309f99ddec7302cb9dd2823f6d8be0bae81b6e406e56681159a18","nonce":"a243fc1ebc972a48eaf28ef3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"3475aef56332532e12e152d4b789cce2ac386fd20003a45dc3daeada5fd4a72ce2181cd214f3391fcf8e113201","nonce":"a243fc1ebc972a48eaf28ef2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"af39ffa86830d658df421342acfab4cd52216a3ccf414b1c6f5e09e2da0c450c229d7ec7776b9d676570e49ea0","nonce":"a243fc1ebc972a48eaf28ef5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"2b76c6e3b7236881ca755f311acf01ce07e4034fc57bb43085bc64724e1cc7d82e53e27a58691038b7eda017ca","nonce":"a243fc1ebc972a48eaf28ef4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"300119c10d8bfcca4942dd79bd69adbaf99bd5dd65bf51c277e17e386581574193631cd4cf8eb12bc72de70e52","nonce":"a243fc1ebc972a48eaf28ef7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"0c6b3d83e1d209b718495b0ce3811b758647842b068f5e1282984c25642e42064061812b1117d1aed3d8fa93dc","nonce":"a243fc1ebc972a48eaf28ef6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"5514c8b6874207cae7658a6bf8543c11f14ea04c714eb3e378e19a2d420517d4cec6ea0dcb0df462d11b911ed4","nonce":"a243fc1ebc972a48eaf28ec9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"70a495dab73e94a4fe0adf5ecd95ac091a6c289e02a32f1b8f595a0fa04d9f1c41e574933f7ea2fd3dcc9ceedd","nonce":"a243fc1ebc972a48eaf28ec8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"693839cf5be96d89b783901147a318226962e2d6e7ef09fbef525185569996de1db9a420b29b4fa60d11e538a5","nonce":"a243fc1ebc972a48eaf28ecb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"f270f49ba19fc52ac4edead28f2a8b85d2cec3ef1c9cfa1702a50fbc40fc4f1f85c3c9c8e23207d056b3002c9e","nonce":"a243fc1ebc972a48eaf28eca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"38f1372fe8996c5e05ebe5b771128b97b489ab6af0af7988a1b4baaa90fcdad9098b0a865e2d0f8c8c5bfd5f0b","nonce":"a243fc1ebc972a48eaf28ecd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"bc0af42bcc394b36e190394dc8a5645d5f2edac7f6b44d12399d0ed79e9c917240dde5765f480604c6b481a685","nonce":"a243fc1ebc972a48eaf28ecc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"01ab9010123a912e1c546f95d6f8d38538c09d0a31e959e57781b03f450c0905e7f1ca0eccb04d276ad0722271","nonce":"a243fc1ebc972a48eaf28ecf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"dd7d768c67a19b2ecd85f6a692c5ec15877265d72efcd0c91cc59dd350265dce5e0fa74c38cbbbfb6e1f6d486c","nonce":"a243fc1ebc972a48eaf28ece","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"ef485a03d81ccea53dc511b94a5cc1453036025f8f9a452194a2f4ca282ab731df324ef0455c03ded9f6b3126b","nonce":"a243fc1ebc972a48eaf28ec1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"f2806de93d8903f0fd3eeef17d12a3ff10fdae6234dbda7ce3745f71749b8f83e00248f1f194c81d2f273da262","nonce":"a243fc1ebc972a48eaf28ec0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"283fa85e636343807ec0c30a2b7e6e77f90ce52731667c8d90f65e6cdbd03d870a74d84f572e2fe1dd54539c9b","nonce":"a243fc1ebc972a48eaf28ec3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"66411e70a365683085a12f95f93a2b6f2d4c98b30f1e5401b8b5a06e2b0a2f88188bfadd8591d9d5daea43df1f","nonce":"a243fc1ebc972a48eaf28ec2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"c304aab5a0bd5e2d9164715edd3b6fdca3242c1e92a3cc7633d0c6969d2440c44d3cc321046fc10c59bfb69ae3","nonce":"a243fc1ebc972a48eaf28ec5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"ffd9ef2f5b1e97bc2bfafbca4864594748ec4f1a39d38ed4c36d5a53795e755baafad364c693b1b21ed5287f8d","nonce":"a243fc1ebc972a48eaf28ec4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"3e0914d58cd7c65d8860b239b9f8f27da4bb0d13fb857b1d67b507ab7d64dd94a8b34e29c4ef11563034b329cd","nonce":"a243fc1ebc972a48eaf28ec7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"95a354852fd1b844b0eade0c4169e41ef75953837c29be8e52f38f0320f60f122e26713509e8f692d3d3cd8b54","nonce":"a243fc1ebc972a48eaf28ec6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"97acd33b572c95f378f6d0e3cb34de3871ca495ac42ad583a30cedc24918e37b985cf3884b6af83a34858ffa85","nonce":"a243fc1ebc972a48eaf28ed9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"fa169a62ff4c643575b47c8b7603931ade72bc36b9939e4396495d0c4d32d2a6443a77cf9caaf58dc2530f1e62","nonce":"a243fc1ebc972a48eaf28ed8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"be3dba7e5351f121ecb0ecd0fb4b0b43348797648b7cb08c35e60d9b891358d1c2286f2587bb12d444e1a5f1e9","nonce":"a243fc1ebc972a48eaf28edb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"d32d44cf512e14de994c7655bfc652d5c76781040514e89e8d9fcc21e83255e41af22834483b552564eb5a2c49","nonce":"a243fc1ebc972a48eaf28eda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"2808ee331cc52d955f95174cae69108eef879af18b0ac4e477c11520559ff2eb46fad007ea4a7fed1dc947f5dc","nonce":"a243fc1ebc972a48eaf28edd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"2ffd408418a63278c476055784327d718ad857f3ebd568f2500e37cae9c5058c3b15eb4184b8158bf0342b4508","nonce":"a243fc1ebc972a48eaf28edc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"ab25cd5275bdeb5e9e65250c020e09946b0462e81cc714fc4c08ef1647e262161f9bc35c52e2f498444371da08","nonce":"a243fc1ebc972a48eaf28edf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"d3d93b39b63322fd14acd2fbfb41b75abf6b7ca6aa8bea342b4be9ff5f87804a36690d71451e7b9ce30c0e35f3","nonce":"a243fc1ebc972a48eaf28ede","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"86e300dafbfe250ff3a1f4e5bc21b643693693ef8eb6b34e8164d602a6afc8391bc526eac95ef147f5e1567e90","nonce":"a243fc1ebc972a48eaf28ed1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"b6f132836705e7ef4a7ac698397575a6d2ddcec7accd7b626add5b706242fabf07c399645de3b2691f57a191cb","nonce":"a243fc1ebc972a48eaf28ed0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"93e767315281fdaa930be29e489ea33a1c13c496b9795eed47bb900feb702d13cc2d62c0d164c0cd3f24b2646b","nonce":"a243fc1ebc972a48eaf28ed3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"f27c250f8cc44f51afcb6b648be27818ba614e99ba91d39084510628c990daead06e5ea71393fe026e43445266","nonce":"a243fc1ebc972a48eaf28ed2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"ef7e382ed5a186fc78a2a6e61e2529e1459d4672d399895aad9e9eb62bc1ec4103363794ba2cbe95683bca9d94","nonce":"a243fc1ebc972a48eaf28ed5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"7538d83638e6d209aa537cdf63609ec2b2096b2913734a676ee9acf2fde992531e8b8074500b9b7f0f915fda52","nonce":"a243fc1ebc972a48eaf28ed4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"0e59382d5dbb1b64029292e7452f20ce9a66ea4b5f62c7e9bea8f6afcdaa6809a932bf19fa3d635088f8a7b801","nonce":"a243fc1ebc972a48eaf28ed7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"ac9fbb39431333ae77d9201129e249f1621bfe8da9c720aaca07be8b3b7195bff318a3827316c5ff8835f25061","nonce":"a243fc1ebc972a48eaf28ed6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"ac54c0fec21bda4939d3ceae1244ef7c8a7e75dc4deeec5a7bee2b442a7cf1c11ab27de2ab12ce9dd2d8b61a28","nonce":"a243fc1ebc972a48eaf28e29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"ecff7dd1abb4be53e3230bc5db998cc63261ef655211a9d9ae13171bb2754c4d661442f1a3a1bbfe3634a1fc0e","nonce":"a243fc1ebc972a48eaf28e28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"8bad94d815af2b15c224c80e90b65bc737c8e0190c364de99c8ec3d1045c29dec85092e5baff32141572796484","nonce":"a243fc1ebc972a48eaf28e2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"e23b220069d2b36a8142ed9895010eda034fa9745560b6a41fe128b01b3b09ee7ac59b5267a28e25eb9b5e9055","nonce":"a243fc1ebc972a48eaf28e2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"4fe6efb3dfa6d932815d5ad3bcd821df7d1dd211bb6c8cdf9b68a6cbfd291d3f937c33d5c7cced480a7bf145b0","nonce":"a243fc1ebc972a48eaf28e2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"7e32f4ee551f30bb43c55e7a9b29ad21b0715c8add443dbba2d5c466302e7a03aabc9f39c12c5911c438544f0d","nonce":"a243fc1ebc972a48eaf28e2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"c6444dafad2138dbdaf67fb985119da29c94eb1264afb0e148c26f9b680f0e8faf4e0ddcc699d43e40c1b73931","nonce":"a243fc1ebc972a48eaf28e2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"9aba43059033ba851482d45b2acc03ad5f0a92be5daa75876caad24ba5543de669c82820ccca5c690dc023b4b5","nonce":"a243fc1ebc972a48eaf28e2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"d0bcb00c3c2d7553d9c115eff662a16e8d986c146796765a0219a4c316710d78c24454419858b0e64ee5352e22","nonce":"a243fc1ebc972a48eaf28e21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"3f25ba542bfdee36371aa07f9dcebecc89e14ece4ff31417bba494d21423a5f5cd1fe1e837619fcfc616756c87","nonce":"a243fc1ebc972a48eaf28e20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"e2e0c237c3bae392a82b149827d4d2d23599b46e051c405dd37c9f4c1c74197f60c7994edd66f3dc06de918983","nonce":"a243fc1ebc972a48eaf28e23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"3931e17e51df65d6e70621efb27aefcdf464a018433932f244b4b40d2c984efe38767073aa07dc6924fc8771c3","nonce":"a243fc1ebc972a48eaf28e22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"5dc29a4f0efd9e7b57ac67d4ed2393395e92f4d0ade8685dc6d7fb8fe42e4ced97eaf7bc02d1c43d236b0f631a","nonce":"a243fc1ebc972a48eaf28e25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"d79b9549c00855f12bc43921cd2098afbe9db5761378384d353432e8577b7b3434b6d8a1fb1a4e81d4b5bef3fc","nonce":"a243fc1ebc972a48eaf28e24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"796c303b9327fa6ad76aa2d360364d0e226113c092f1bb84bea0bd01b152b550d2f5ddd625d35e1ef50807edf1","nonce":"a243fc1ebc972a48eaf28e27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"20229d5b122b8b7c019d414badcf89f41653fccd56dcf56eed54d73bb090d7699ed0b3ed73f2222f53fa845e47","nonce":"a243fc1ebc972a48eaf28e26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"cd0bb9c459fb54e08ef79cccdb2cfa2c5bca5c5c1ae3f78d1f30e51b4cf698ec289eb31805c5b2c24e2a674dcc","nonce":"a243fc1ebc972a48eaf28e39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"1c6b86709942271fdec3fca2ca7ea303ba008248317a3fcd2f429dca807773f20b880d392290bb014e620aea59","nonce":"a243fc1ebc972a48eaf28e38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"ab0442d31887b9c0eddf31269eb3a9eb144fb5b8fe8e9fb1c976aa43496ddf659231463e3ccaf29af77f0b5853","nonce":"a243fc1ebc972a48eaf28e3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"2f6af75dc132f8e62b70d1b8b2775ce698d02f68e2380dd3387f504b53b4cd4d5f7b3f31e7a62e81cd2f486c15","nonce":"a243fc1ebc972a48eaf28e3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"e2edc83a2fa67a2f76de1b8be0b1fe011c15ac0ea0a1f13a19b56ba36264887a4136c886f0b1182ddd216e0f80","nonce":"a243fc1ebc972a48eaf28e3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"a7f2caa8cab402fdbc403880a92403d59e896f49fb0d17d6b3b88818c8aeee5cf8f1882d66fca16683d3614a15","nonce":"a243fc1ebc972a48eaf28e3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"95a7d550db716dd21d2c4104255b5f485aa571ce222ebed536e2c94a0023e65400b4ac86fada4088f36c5573a5","nonce":"a243fc1ebc972a48eaf28e3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"e05415c07412b26b6262d64e4b9cb9c53a30408872ff01b0d91b7f695a6cfa07d22e966da7fb5399c32810cddf","nonce":"a243fc1ebc972a48eaf28e3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"5c28db83cc4c08dfeba2fd09e95ba72c61c8e2343fd8b77928f07aa3b1c16f44e87cf273dd58c7c7012eed2171","nonce":"a243fc1ebc972a48eaf28e31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"96a3aa9b1f6ec1935d2199ddf1624d1d551326f13c92d224ee0baaec4fb42671ddcf6d60821f6e7b23e800aa69","nonce":"a243fc1ebc972a48eaf28e30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"8834889db5b9d771ced9be08775cef9725fd6aae87de093119798901403fcbb7f277c721d61ff3c81476901a3f","nonce":"a243fc1ebc972a48eaf28e33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"eb17227bcc0d511cc8d2d58069c3915cddd860560e1d9a8065808790840c0721ee722a8f8589e6dd415c15fa12","nonce":"a243fc1ebc972a48eaf28e32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"c7d25e2fc15d7e852cbdf69dbb7ff218132957cf3bd8c4bac20d4200dc409d6857291b11d67aaed6173fb2d930","nonce":"a243fc1ebc972a48eaf28e35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"caddc6208516074a159b473fd1637a6197c685452e1a65b28018486218371cf87adf87e526d172f590fc198ca7","nonce":"a243fc1ebc972a48eaf28e34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"2b241cf8a1eea9550f0f9eb0b470923da84e5da63a1c43e64e472da6a32af8480abdf56cd718ab0708d9c575b2","nonce":"a243fc1ebc972a48eaf28e37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"761605a94e63628c17d930e638c7242866939d46841194c80fab8924f4e005aa89d83378239e45d71b2c58a633","nonce":"a243fc1ebc972a48eaf28e36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"57e912b3e62400fd0447030762a63a86cc424bc103ac16b1f0b059fd665371441c7f75b974641402f454f23b80","nonce":"a243fc1ebc972a48eaf28e09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"ed64afcd3aa1001e4d73387962024f3c406342be0faa6e409eb44860ced71c736aaa7b7f2e9e172e9e99571f10","nonce":"a243fc1ebc972a48eaf28e08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"72b3ee002046d968fc5ea945c7e001528bb01c899fc79241b3c9b5a2fb526c8ccadfa7eff66f39f9682df6e02a","nonce":"a243fc1ebc972a48eaf28e0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"f73a793a46f58982f1b32fab1276bb0069697e8aa67c923f335d553a272a022d907206e0a9c195239f0dce7bbd","nonce":"a243fc1ebc972a48eaf28e0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"38fbcd9f99baeb6ee2c949001a4e9aa032e1e3ac7294de90db260e368a4369b6b29c460da1998b2bc3ee7c92b0","nonce":"a243fc1ebc972a48eaf28e0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"92489b0d704efb3d6a93b33ad636f3a240af860c2db65d749a6bde6b7a87337273426d29ff72828b815aa5422e","nonce":"a243fc1ebc972a48eaf28e0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"1fe30901bd982fb766473cb5c08c6dd8307d23fe8b716b3fcbfe2a83ba926322534518de1c6344c3cc5467ba49","nonce":"a243fc1ebc972a48eaf28e0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"4808bdf5940e6ae8fa0442dd618d63d9d69d24600fe3e18679b1f9d69449f9c35034723cca3a625b93d3e3b1f1","nonce":"a243fc1ebc972a48eaf28e0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"1c61c6887472cd2cf6d16137f889dde7554a5cf9ae07ce6de43b78543ca24d23458c4dce43ad9b54863e1bc15d","nonce":"a243fc1ebc972a48eaf28e01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"15cc79957676852e8a15c93917442bf881f1a12f90988f9202cd0d402145ae193231c2924f1885e2d699609117","nonce":"a243fc1ebc972a48eaf28e00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"cfbf10394f5e401f058f43913e58f63421da63a563c9e495b447d78d758e4f0c059837d52c02908627ed55a83c","nonce":"a243fc1ebc972a48eaf28e03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"ec916a4215649d657c25d1e3c3093b25b1da8e80a239f2694b80ed884a1fd4e84c4e906191daf6958a14fe6b9d","nonce":"a243fc1ebc972a48eaf28e02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"66a762daa201c304682241cbe576122faaf648bab5f6f0e2e1f408495a2a4449416f03dcd18ff1d51a39c2007b","nonce":"a243fc1ebc972a48eaf28e05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"ee69d4432e614bcaf3a8071b458b73ca96ac67538e1c3adbd219d4b8a1e2fd46f8bcca435d567cdb04c3647216","nonce":"a243fc1ebc972a48eaf28e04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"4acd9bac8ca762c031a008742e7b97b23320577e395a8e89a1f333a33520003c63a072dc93c39ecff9e72de1df","nonce":"a243fc1ebc972a48eaf28e07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"3f1bc8d8587356ffa7e8a0e13add830f11e907e66621163aa3239f5f1f9ebeee280f824863724e3fda80acbfd1","nonce":"a243fc1ebc972a48eaf28e06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"25c5e5d31fb549db373e2b454423b3072211b0177de15c81d8641c826b8e88256d9f1db8a96a0acd5dc0fd24dd","nonce":"a243fc1ebc972a48eaf28e19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"d38bbe1aff0f2dcf9b8f37c8edfe07232c0f74067efc38b204e9770bc5007d2fce573067feaf013dc138e0f400","nonce":"a243fc1ebc972a48eaf28e18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"9e5292090ea554851a1b86f8b3f6c7c777df3441c1eca9e1e7c3e78ca286dfc88b2098f552c8aedd8e19d7bee6","nonce":"a243fc1ebc972a48eaf28e1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"7db34f669ae604f55ade02e2bb69abeffede5a80f61874549b2a90de8c0c81abfe1c42c0e1898905f3b77cc6aa","nonce":"a243fc1ebc972a48eaf28e1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"f3bec066222f9f1ad447949979e95b59de3338ad5cb8dac7514b8fe939f805a44ca488e77bf5ada4860a9bd76f","nonce":"a243fc1ebc972a48eaf28e1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"ca579358427194021634f2b859a05f9cad15aa53cc548021bda3fb9d2d46923b31b77d734266aab9f9a060ff6d","nonce":"a243fc1ebc972a48eaf28e1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"d60ed8754f21cd2f76be8ba68f439b40b0fe9399a93d3715f3ef421a7b8e113220fb1c9daa22258858e2a23166","nonce":"a243fc1ebc972a48eaf28e1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"7f7c6aa68f9343a36b90ff565be19212cdf49e428301c216f41b94f622ea86f9a67d53e4749a417ea0bcd85feb","nonce":"a243fc1ebc972a48eaf28e1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"ccbeae345606837e1777bab6d76fc7583602d0bce83893d9afc7dc6bbbe12246cb67dc53c4abbf19cae33aadca","nonce":"a243fc1ebc972a48eaf28e11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"b82ae42ad42826c3656d4f1710d7defc6b082aeb3c04c5e6c60d08fbab693351b569370a363888f8733fca662e","nonce":"a243fc1ebc972a48eaf28e10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"9a178ee7b98fc2a41795906783ed7de72f6de9821a5eb4306e653950f5d3e79fc6b3b625a485b2cf25d988df35","nonce":"a243fc1ebc972a48eaf28e13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"815f736b050b418e1d14bab5f893bab02df9c0ab8353f362799f13d380b776af3e6bb22c9f23db905c4f502f2c","nonce":"a243fc1ebc972a48eaf28e12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"c710550592dab20f0e3c7f1c8f87f7f209f81e0047d8f1f1ab1936da875819a69a228618933ef6de3c767e298a","nonce":"a243fc1ebc972a48eaf28e15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"466908e1814981af77790d397cde835b2e3b9476d25d82f4cc6f303a59a534a9c602b31f2b8872571e4ed7eb63","nonce":"a243fc1ebc972a48eaf28e14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"79fbb563a56bcaa74902d4d9c6bc9d5871521a893accfcb22c44477390cea59f25f4ffe07c7fdfdcb05c843d36","nonce":"a243fc1ebc972a48eaf28e17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"5ef5eb9060cb23ff539142786dda191a3177e62572e509bd2bf0738c727e2001123b6d97f06e82906d54414e73","nonce":"a243fc1ebc972a48eaf28e16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"ee2485e7dd26ffee2253e56816ba410de3a5e5b17e142a7f9c1afd98c8928f96c615cb15909d752a9c05f50a88","nonce":"a243fc1ebc972a48eaf28e69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"fbee3015e44378afdc1961b1a25a728a9442b8845c9b94c120ca4697cc2f1c3dc6425e492e21c1fb01661e0cc5","nonce":"a243fc1ebc972a48eaf28e68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"377dd7f52e463d2ae0fb7f8cd887ce28a9bbd18b09807a18037164f7b8fe43f7f9e964aaaf813e1ab0ab58445d","nonce":"a243fc1ebc972a48eaf28e6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"6c60d23f7bcf97cf3fa9fb04d0bb995eb9a809cfda932245d03b7d2eaaa801614650c09a96172c48f8efa8ac89","nonce":"a243fc1ebc972a48eaf28e6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"4bb127f2e847825794a2b107f61c52cf79678c9f0b91d2ebf21861649e17ccfd7c66201b83d3a3d5a36fedd9c3","nonce":"a243fc1ebc972a48eaf28e6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"1b9d31f048f53212503549b0c0158e7c61a5f3e5fb8c1389ca2d25e9f1b78d04b9edb0a86e61dbdbbd41aedc54","nonce":"a243fc1ebc972a48eaf28e6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"34101c2d46e3c43700093d5609f519faf099ad0667821e6caac571626ab8dbf2609effe4c296256a0d184914fb","nonce":"a243fc1ebc972a48eaf28e6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"f779694f4fdb4adf3bd1ed58dd843d3bb6b6e7417b03a9649f115269bfde023cc1c52a7739ed89685a35206cd6","nonce":"a243fc1ebc972a48eaf28e6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"b2aeaf5540420e9d5feda827292aab02e64387765eae1fe965833ba2d787f7ece8d6e8a13dc77f62d24f3eeb8b","nonce":"a243fc1ebc972a48eaf28e61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"5ad7f504ef16b95948822632fdd464614d53f0c114ecf2eded405162d2b9a6e6e7ebcd96c095436eae2fe239ed","nonce":"a243fc1ebc972a48eaf28e60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"a4b80be10aa7306d30eff4ced26d689259c3bc9cf1ef6c6359fc0a7e7af105222ae916d49a75fa99ffb039308f","nonce":"a243fc1ebc972a48eaf28e63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"d18f9fad9e1831b677de7904890157aa75ebc1998561198df09c058a62c95e02279b93ea934f6b43f5e4f627b4","nonce":"a243fc1ebc972a48eaf28e62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"9c3ce2fd2184977509f1b1f48310ad25c1f4d790ee12d029a969d2110056d5744ed87d9cb675e2ba96109e9769","nonce":"a243fc1ebc972a48eaf28e65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"d21bb1039dbec277edec5c9bc2270f0bb185cbc902fbe8714c340877cbdd620642cc934d56890861a7c87fa696","nonce":"a243fc1ebc972a48eaf28e64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"6deddff97f67b958b6927105246a6536560e9ade22086c9d0c3a17668247f164ac3f66ca9edf8ffa0ec039f0b9","nonce":"a243fc1ebc972a48eaf28e67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"4ce98a88690322e1785aa9bd8a17fd87800c37f264f1c4dfb8d114476aceb416b149f5534cddc40df9ca69805f","nonce":"a243fc1ebc972a48eaf28e66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"ff98e6a6b15e81fd02148c8091a68028f1c797abf983cb9c97b285c92e5cd911294c38c837a7078ef27c495d91","nonce":"a243fc1ebc972a48eaf28e79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"1c924c4a543d524346db4eea7d2218e91246a0ecc83a8e4bea4bc05bb6ddcc48b4c8a1366c9735def796c1d4bc","nonce":"a243fc1ebc972a48eaf28e78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"9babd9af9487daec9444a868ce843a3d6bb8e53e2399e5916ec101f43fc3ba7faf062e3c0a7b8e32b5fe42b346","nonce":"a243fc1ebc972a48eaf28e7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"74b58e5367508e79f8c9cace795a73c974438c763bc1bb4292da54ea1fab6ac94570d404b1faee61b12b0dfab9","nonce":"a243fc1ebc972a48eaf28e7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"614bff8d76e834295bde948e3e5bc47f83807c70478c7e7421d5e1125cca511c742cc5c12aac7c4453aec57998","nonce":"a243fc1ebc972a48eaf28e7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"f29e076d78ba557ad4866bee610adecc6b284330ba126f4656835c9cabf5a1ca55b55d95d2b0f64ae3c90a37d2","nonce":"a243fc1ebc972a48eaf28e7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"f925da74b88a9b47d884c3deacda52cab85e6d62053a2846c819f1a481039c6aae4f5b84ded6b68f68c0cb5a8e","nonce":"a243fc1ebc972a48eaf28e7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"2b6d9a9dffd68dc9f0eefc8f242890d11a531a1803cdda9d10c19df3456f3e0857087ee17dd24f13f7a33be356","nonce":"a243fc1ebc972a48eaf28e7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"470ebcfc7f0ca313e9092f49944f664d5355f71ac783897a2540c1d4d4a706ebe49ce95879754a99c17aca0823","nonce":"a243fc1ebc972a48eaf28e71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"0468e8499909a8401e1df3622ab6cef9c5d18154c0645bd2e93f69180fbc71acc04134cfb6af626203124f7414","nonce":"a243fc1ebc972a48eaf28e70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"aad18b1642789b9b7db8d355dadf880780ed2011ed04eab871a40a3401e70a9f1ebb755a9942c8dc53c3245499","nonce":"a243fc1ebc972a48eaf28e73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"5f0825daa56cd62eabe39d6c3bacf24ef3245142a12705a66fc0d2500f7a3b5e03a85c561cc3f1c50385442ea6","nonce":"a243fc1ebc972a48eaf28e72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"11abfd47c57919dddcdd33019ea457156f63f9212aa12c2fc8234ae0bd26883cde9e657ae5dc2841cd69daab29","nonce":"a243fc1ebc972a48eaf28e75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"438dccf9489916b11f47519a323a4f14dbdd0cbf655feaabd5664bff0b26f8e889fa3913376e26d53f40a5ce71","nonce":"a243fc1ebc972a48eaf28e74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"db1bf18c8a9d1f38c0d0e1038eed44a354d65f4b36eb0d882015e2bc64a56cf74740fc531f5c67de1d85054a95","nonce":"a243fc1ebc972a48eaf28e77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"6eea4364f51a9f9bfce60895680071e14e79adac6da05ece84c6ead6bf6f37cede28335ef00db9e07f4aa57c02","nonce":"a243fc1ebc972a48eaf28e76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"df036dde1433ad3b6b8c80490ac1faa6d8770fc49dc2acf3e029dfdb62ef9f3d198884123b55abe8665fcbb946","nonce":"a243fc1ebc972a48eaf28e49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"3924fada71f7b16dd5c92ac2bc40c88d3a113162c01f66cefa4b3d7fbc985c21027739022867ef8cf2efef52c5","nonce":"a243fc1ebc972a48eaf28e48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"c40fc1256a03b52634e1e6bd940f1b6e0727fe83b5802d27eeb4367bc0cf9275c7fdb786a48298a2a44d61bf4b","nonce":"a243fc1ebc972a48eaf28e4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"e05fd7846a9d385d8541f2f9eab051146d82874c1aa9603eb7c5149bef2c30f1799412bf18bd0b098126076c75","nonce":"a243fc1ebc972a48eaf28e4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"35a4a025e3440cbb98ae273e2bfb68ebcf31dcfd0424a5990533c0ae627dd5cae808f1b0d256e02b1ce1b30b9d","nonce":"a243fc1ebc972a48eaf28e4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"451b183efd850a90b3a4ce97543604abfac822c547ee885f49054859900d3045c85eff5e09d7f326b56665353e","nonce":"a243fc1ebc972a48eaf28e4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"959772b27b01dd9fd63888a63a1775bb3ab5c215d317d50c40ba5ea628536fa6837a9ab24a72a068c74369e796","nonce":"a243fc1ebc972a48eaf28e4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"638c63185a25659b4715211147d701c661e3b3bb392031f84d7cb79d9f603b6e218dde9e59d08a858f2f80f412","nonce":"a243fc1ebc972a48eaf28e4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"fd5444a067241796e0055a9869f72e8a2e54869aef7c83b3e7058f18297dd09e262dd282d6fb7ebab4ca0dcfdb","nonce":"a243fc1ebc972a48eaf28e41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"ffeb180478db6ecf7fed0b314662bab02dd49abb8d28289d972b6be47fb0332a371b25ef04d88e0cb0a9775b38","nonce":"a243fc1ebc972a48eaf28e40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"e9896d60058afbcf0c28fd162b75b78d454e4c5e796b9961e45c1c0cf36b581335db3e5452c3d70848b35b9008","nonce":"a243fc1ebc972a48eaf28e43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"ca647d366075b41d66ca930394285f13f986903313933b83fa737a3d1d3c15998ce7c437c3d0b8006681a73e9e","nonce":"a243fc1ebc972a48eaf28e42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"539eb8556908774274e2c4bd5053fc968bd747cb3ecb7eea9dd9ffa98f78aa6c1e60fa22d60a6c4849fc0bfcc8","nonce":"a243fc1ebc972a48eaf28e45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"f113ede7fcdc4fcce6b6106b55d540e578f80576e771df50c248c1dc43bb61beedd94b963bb772ab36a7eafc64","nonce":"a243fc1ebc972a48eaf28e44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"b505150b2d5efc06b6bf76ac43c2df6066a7e7d8a139bb80fa600222f2b3bc417ef3bad3f5fcff8b4bab4602b8","nonce":"a243fc1ebc972a48eaf28e47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"23c7f4e1eea7d1af16df60fb97782a1f8637baa46fc6c72d6955ffabac765360f8b0e2d57eae06a7155dddc967","nonce":"a243fc1ebc972a48eaf28e46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"de05dac315a9a2a4537cba358a5c8c7a75b5c1b945ea5b8002aca0f17c2afdaec9ef0e4475d6be268d94a07301","nonce":"a243fc1ebc972a48eaf28e59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"3cdcd3d1bf4c26be26a1157cffb4981b3884c101c7849c32cec73efa3ed9132e2933c96bad5f8cf34510614bcd","nonce":"a243fc1ebc972a48eaf28e58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"3276473b4041bbc23f64ae6906452fac1688b321b6ee14a0691481ce419737d41a6c8419195686418494186e13","nonce":"a243fc1ebc972a48eaf28e5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"344e225da9b54789269de6d0913ec2529c2c6df549796094ce03648fd8c8d55cf2b7a4954106f87a37eacbc379","nonce":"a243fc1ebc972a48eaf28e5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"b5f291b8db01ea43495b6c3a65d33e5ca0694dc1612e6304d3730529f5589aafa10f16d1d7ddba82df659e2c52","nonce":"a243fc1ebc972a48eaf28e5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"76cb8c9ba4518a77035b57b189d3f448a51b0d20114120f6f2cb9e3d3988b6939fa351d6ae6df6ddd7cd659a38","nonce":"a243fc1ebc972a48eaf28e5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"720f1711b3ac677afade9a513f6d304a70fa32ddfcd1c6f40ff9cfbb421583b605807070d4230048326b23ea75","nonce":"a243fc1ebc972a48eaf28e5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"9f51153d7983feba9e98339fc2e0e93380bb44db4670df4bcd0552ec311f0cc5a9ffc5bd6a23061ce9f78b735a","nonce":"a243fc1ebc972a48eaf28e5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"3a236f02d9a002191bfe65092bc6f19acb0753feb4141c52a1e1aa51cf052b257208ecd74f0ade01c44b5c1dee","nonce":"a243fc1ebc972a48eaf28e51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"d54c0415f190124ffb21595a15b07942efbd6ba544994a1fa3ec36d5ff0ad08d98c481dbc8b25ea6e94597dffd","nonce":"a243fc1ebc972a48eaf28e50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"3f0cb945b002b4c1b6d769f001027b309bbd2460e033a8a3aa434b0e4eb6a1667b687f206d24be763eaddf3728","nonce":"a243fc1ebc972a48eaf28e53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"664f6b425cc4e2a53d92db32d74aa3c5894dd2a20fd2f08e3e3f0f2b0ab5e308cf954fd7e86b836a7e3e0e0271","nonce":"a243fc1ebc972a48eaf28e52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"3e63f961f9f408175e45d97a8ae1f1af38b7f25159afae2d8819d91eee5c82995999da1aca87fb676ab73b0f32","nonce":"a243fc1ebc972a48eaf28e55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"650932605959705eb10627625783a73853002e9c084e8f9ab0fe5a7fda57e5635addddbcc3669b67703ea25984","nonce":"a243fc1ebc972a48eaf28e54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"2f186e257a8add7bf54870709c12af75d6c9330053b3a0fdb002fe4df1bd4a3d4c4f2730ae03c93f9f8eeb602d","nonce":"a243fc1ebc972a48eaf28e57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"e8d90dd741c27619573d34a4e7da36368120dfe420cee7313af5d774ed9be68289518ed0d30427e8a1c1ce222d","nonce":"a243fc1ebc972a48eaf28e56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"fc6b9d1ddfe63c9818507d7aef6ad30013966471dc8a84481d08b1fe61d442eabb40f84a92a480ac22e93b8b4e","nonce":"a243fc1ebc972a48eaf28fa9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"4b4f5f25bcb113003e18472ffd5902f93b8b4848801319a525147b47e03f6aff"},{"exporter_context":"00","L":32,"exported_value":"d95abb928a78415ff0a2c985d54feb17b03f4259190eb90f43d166c7b147ee3f"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"b7cacb2b2e923ad7840d4900dcec3f5d1fbb2f3768f137ab539a3259e7a6cb04"}]},{"mode":1,"kem_id":32,"kdf_id":1,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"37a83d2ad4589e7d11006909076ed80aef29ba124408165c24796c43b5f4e2c0","ikmE":"a1ef032207d2333c0b3c58408514a0d3db1472b276214075c51b69aea103384d","skRm":"15d932c7aa252020bc0a4ecbca4c9a07492fbb8610c5c55592bcdd859a0fd30d","skEm":"634385e7a0bf4b575e547dc006200de82e38ff359c4a7fbe3f1d0235dca6462f","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"d6084ad878887746e6bae9552562f95a15680a0b1a50b901ffce1649247b3224","pkEm":"5645a74dfeed158c20555d62f9a9d9296a1d4ff3fa58ee9e36d99f8569f04054","enc":"5645a74dfeed158c20555d62f9a9d9296a1d4ff3fa58ee9e36d99f8569f04054","shared_secret":"98658e750caeaefef23776de485d2d05a6c9d0af6c358e4ff404b23a3f8ae3fe","key_schedule_context":"01a35894e1dbdc20fa21488d654d8f53f5aff5052690a045752fc170019f0d314e06f6ef962c9ee7cea40407b5d60f0f26990472faae3ac44c78366f1cac1ecde1","secret":"5ce8379bed4569c5e488475fb366d36ae2823226af2748e01846838adaf4782d","key":"6264879d3bb47c01d1211976607e12c5497fe9c0f4a0d5d8b6a20c3bfd001751","base_nonce":"f5370fe795f77fec9098deb0","exporter_secret":"35c3ad4142b7263570e2e4045ad3ec274db32dc8b1b1105449633158e11e8376","encryptions":[{"aad":"436f756e742d30","ciphertext":"0ff9cf5ee8b66df1e99cf1c86b4f6b9193c68c98396f7104962bb3e0ca4ec5e2420efd9238e0736f08a39af200","nonce":"f5370fe795f77fec9098deb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"aa58399e3b6dce19a4b90a266997f008513f483db1d5262e1153792d836c77e2c0c4069912d1caed705c3e6dbc","nonce":"f5370fe795f77fec9098deb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"5339bf642fd381015b95eb83d4ae9123b34e7f00d07d6f365ae4a8eeb2a495a1c5b761d5a3111da4ca6c75728b","nonce":"f5370fe795f77fec9098deb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"0a74d2b71c74e5634edf4e33f841adeb86f3faf2732c9140550a7cb71300b471ed8d5b23eeadcb7dc199700141","nonce":"f5370fe795f77fec9098deb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"6dc49b9490e12f4c58404e9f26b0bf85ccaaa82a01719a09239fc2cba65d347909c9300ec6e426c907315d4749","nonce":"f5370fe795f77fec9098deb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"5b7f60623c8c5f2907419862dccbdfd1c9ae9b97f0149ccb0cd8c2cb34c8b744a4676adc0b343eb192e48b31ca","nonce":"f5370fe795f77fec9098deb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"d5dc6308c4f5b82c01d962b12d5e2ea76c579060033b1341c5e6d1870645428b499cda6a2a6540709627f4c487","nonce":"f5370fe795f77fec9098deb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"ff6558ba2d116dd4aa4a4bee8c0acecc50e2bd6610013d30cf586a0a8077a4823235ec6e1b8edfecbfd6ef59a5","nonce":"f5370fe795f77fec9098deb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"ce3c8c9b0870c1e12651692a1c89869e2eed1253004037dba5af98bb3b03862ae92ba2e0cab6bc41b2ac2a8b16","nonce":"f5370fe795f77fec9098deb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"b2d9ec7f26bcd4c96e48c0b0557df989da86e818824c3962c58106662573ab7e2e98b1240ab8d7b09618a996d3","nonce":"f5370fe795f77fec9098deb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"5ff18d69c370bcfbfaececb5f30a5fedafa8fcbf57820c9e22b130cc4bb26334030ef560cedd9b6ef072f7b046","nonce":"f5370fe795f77fec9098deba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"37a8254f7e723e3c249b71c17b0cafc4f9b9de91879d9f18908a84b5f9487bbb1b9f64a3bb1a61b7f817483bf5","nonce":"f5370fe795f77fec9098debb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"527a37d41945f4eae9d826099117416031bde51327530e41f683181b8d18b7264035c84acf4a994c016477a00f","nonce":"f5370fe795f77fec9098debc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"b4410c3b6dbb6e532d8f8adfbf8e963e83d4eae9d047638a3aefbc16fd2704b3d55188b931bbcdef717507a51b","nonce":"f5370fe795f77fec9098debd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"7904fb83f9542e1d7efe602a7941417363ad5b1a752364c6b0850cd29fbcb8ef9ed87160f3ef246b0cfe87b3b9","nonce":"f5370fe795f77fec9098debe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"e8349d6a492d0b7d23f3d403ef69a094d7969767968755129053da5d246f9758300ce8762e2d1f5b521e691acd","nonce":"f5370fe795f77fec9098debf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"fbaa0b90d8a5fa97f12bf6490384b1b1590f25e4a159af4c6bd47d81694aeae1f0a54f5d43104ee7a86d89f5b1","nonce":"f5370fe795f77fec9098dea0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"bf6eb7182af59796d2ac636265e06fb875ca0f7889d7b482e12f88936c606626f40f52913b5be92e48f744efec","nonce":"f5370fe795f77fec9098dea1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"bc1372a6c6dc5cb7bfd8e2e402ddbea7bb1604db6a8a89cfbb51b79922b9b5594da4f02e942f571cf831a06b7e","nonce":"f5370fe795f77fec9098dea2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"74da66a9cf97baa7f2f755a1ca89190a08f2cd046ec79bd7bb6074731912aaaee7906b52e4247bd1b73ffa9c37","nonce":"f5370fe795f77fec9098dea3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"37c8da9279ce59cdbaf1dce48c079f4e347b633134045c1c70caa18fc42c64ff80ececb69c8091609e6666c65a","nonce":"f5370fe795f77fec9098dea4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"ea33db5ed32138e8bb990c2e8d94e14f177c79fd3498d1c5e5f52fb1bfec42d9c4265030ce18d4981d7e14599a","nonce":"f5370fe795f77fec9098dea5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"c36288efa3a7e763c702f6f67d735334a01684d132ff8f763e27118981b3149a5215c7bc0a3c8fcd59c894699e","nonce":"f5370fe795f77fec9098dea6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"1998e0e5e73a136fa67588f2000f0cf23bf87ebd64aa8cd5abaa7c870b741604c1b1f99fcb5c935f279f155db4","nonce":"f5370fe795f77fec9098dea7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"883c34bc264119613784930f0ecec5ee46cd39d9880a145f8915a0874dc83ade9d490b86a42860e0ed7c27fb43","nonce":"f5370fe795f77fec9098dea8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"7cd875aa2075feebf8fc1e1d37c48e785163d3a9248cddd848fe4163d404019901b43361ea513586b7a6299868","nonce":"f5370fe795f77fec9098dea9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"7d5a214a8110bc897538fc08200973e84751c7bceabae081d3f8527583ff025d71f1104db379773c2075ebad79","nonce":"f5370fe795f77fec9098deaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"6bcf49fa2cc1ccefe6764c8801dcf3e702af3497b0cd8a13ce749bec8bf5d522d4dc8811adbd55c089a89fc9be","nonce":"f5370fe795f77fec9098deab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"27d20663e55726fc38209416aae80d69c02ea8e63e6e0c34124bd77262d36eb835d1fb54b2036a2de2908b58d6","nonce":"f5370fe795f77fec9098deac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"2fa10067bf5c5ed10bf742f45256cc41fef52d65be10a8880c0a94dd833a41205c471b7194a4791933c1abd28b","nonce":"f5370fe795f77fec9098dead","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"6d323f46b3191b910708efaf0bdfcc7869902953e8e7e2b16b23785396bd5535914e3b0735e82d81b66ca59386","nonce":"f5370fe795f77fec9098deae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"682ec3fde6061be0ddf3267e191abb711bf1f7547c14a5f32273b81551bc37f02784daec010e50816124364ee6","nonce":"f5370fe795f77fec9098deaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"5ee3e9ae4c80ceed91935261f9c36c7b1045641ff08169191591faad2d76092902deca5a3f8c77321a4215119c","nonce":"f5370fe795f77fec9098de90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"e206535e1c875ad9fd16477da83d6dff53c7cd70dba67fd65fe04c8b92fa321403d77f9b290ca575785bdf1c2d","nonce":"f5370fe795f77fec9098de91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"37a75f3127cce5a8dac843596360c70cfa60ba51af685df0faec65629a644ab53de47829aee84f65f9bb7b61ce","nonce":"f5370fe795f77fec9098de92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"f5c78fe599e5c4a8846adccb6f0d38124cc8a3902bcef460e1121144d31829b2904dfcca90964a78e04b540429","nonce":"f5370fe795f77fec9098de93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"a1538a51c597bb5006536ea3f2b1eea9d95a021e92ac8e7ede38715309f277f7eb191a29976f8b826a2af8edb6","nonce":"f5370fe795f77fec9098de94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"3ec5327e4b37dd6e344a0d70f2b1c5445e22276a54f664c070f6c44c7a47f3dfbfff78518596d4de2fbc62e948","nonce":"f5370fe795f77fec9098de95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"0fbf527d54155db2076c1772171dcb0870342da311637448a448acc186c41e0d504d2c292e3fa18918eb96e52e","nonce":"f5370fe795f77fec9098de96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"37c2f9745b17ce245bb7eb587d7d13d9d4e3f83be7f4448a13a17886f2bba3d2e6ed7193f0759f84c1e37c1d8f","nonce":"f5370fe795f77fec9098de97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"17f935ce9664e5e2d9221a8af5860b7fa0984f40d64bd33b9927af5832be5314b73d57aaac4e8b8a67adbc08a0","nonce":"f5370fe795f77fec9098de98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"f01badf324307ec43297d41a6cf910c1f0253d887c8d50942859f8eab26e58e502017923870071008302f21400","nonce":"f5370fe795f77fec9098de99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"6ab45bc25375a1202fc35bb61d425565a57bfb8598f4c4bf3695dff4656959c007af68a987179bebcc745e304e","nonce":"f5370fe795f77fec9098de9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"13c2e33c7e7464a24fe37589875d8a0fa8fd227c9a46fb1e928a9446366d5179f4e6ee0b203d50dfee8928bee6","nonce":"f5370fe795f77fec9098de9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"1d668d43d41a9de115aba66e72cb42564a0adf9a35b0dd2816d5435ca80f56b2ff1c310a4c0f41d9e274b29ba8","nonce":"f5370fe795f77fec9098de9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"a83f38f4f8b3c832e6f118e1a0d6248a18404da70daa644b1a4d50d4655902c9f6fba3f6266b6afbf3468e1789","nonce":"f5370fe795f77fec9098de9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"0735639a092c3ca97cd6826bef2c24f5db103979f886958754c674fc75349fa7bb1cd2cf33f567af1e3eade2bb","nonce":"f5370fe795f77fec9098de9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"339fe8b28df80591d1dce2bb92b71f65eba1bae8e069923d3a7ae3132154cb5b567d1d42c530259a3e36418509","nonce":"f5370fe795f77fec9098de9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"4d2b2cef619d2402f02794c3393c216319bfb4e8dbe7735c52295aa9b04ebe33250a0bf48f207281465b023b38","nonce":"f5370fe795f77fec9098de80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"b93bc11d4cfe1ea05939835c6a8d769feb06a95519d26fe8fd98b529c95ff5e8d23b5e20e0d8e1d59a63a38caf","nonce":"f5370fe795f77fec9098de81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"f0e09cfd849e510b731e3f6b45a507e346d1b8d646a8c1d4299e611fa037a74ea6edb32780d3cafba5dd987a14","nonce":"f5370fe795f77fec9098de82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"8752cce22d1af5dcb09e4077b0c8905beea7777324d9f4432b17698e61712ed3e42dcfc83b104a28048ec09208","nonce":"f5370fe795f77fec9098de83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"03f04893d3bdbb2fee35012b41c6fc92764a91284bc5d255840e3108211c81e4e0d5662dea8375b49625af77ef","nonce":"f5370fe795f77fec9098de84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"d7e0c54f404fb24a853ec16a2a1d6acfd857c727039a5b9ce563fd5b1b8f2b62dba03dac2b9b09ade0502dadf6","nonce":"f5370fe795f77fec9098de85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"52e1c58de7f19d89607e49f21a3af2bb0a6bad5524ac6431d67755021f768b2cfafc06b172c4d365ea3391a40a","nonce":"f5370fe795f77fec9098de86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"fb5ee9073519b43c26d308f65406831627e63056efcc6283be402d2084aad947e4483fdc9a7864d4ae6fbfc0d5","nonce":"f5370fe795f77fec9098de87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"27f8b29fff28fbb41fdb31af12cec7c04089f18d13fd69fefaaa17f09067818e0f4925670a991c2bded48c5c6f","nonce":"f5370fe795f77fec9098de88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"0ee45950bcd2be0c80659e9f43bc73650f8b04db16fdf04bc94f808753d380ca1f6fcfde6b2957696b9a5e6fc1","nonce":"f5370fe795f77fec9098de89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"4a71ad48720d0d0b415996374079e79820320b685edc0bed3873bffdc3c41ce9eb1dd1d80a6404a861e5721535","nonce":"f5370fe795f77fec9098de8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"886a69724a56b9aa77f93bb2434d9d06c0e0dfc21131dd1f2ee049ee6da9bab84b518a329bd9d06dd2ce85999c","nonce":"f5370fe795f77fec9098de8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"691802ca83e92fd85034f701142c97709f1cd9b7a386332d164caea53741fea19b7a1a84a65b46fe441d56acbf","nonce":"f5370fe795f77fec9098de8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"0cfa7c4fe969bcb4b74e86c063d7ce23d4596fe065210b65190228040b8cea998e856b39a7dde3a2f2a3fbd18a","nonce":"f5370fe795f77fec9098de8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"c4a621cb1855ab1d8ff07c9637645bf0f8f394abd1e989419c0c5d66b7b6522f4658f77504a280ed737618edd8","nonce":"f5370fe795f77fec9098de8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"d473f8f19b8acef0229a3f9b51816764f19dfdfd60a922bbe8e6fc31f9f74f6e6ad4a70869573c97a9c51b6866","nonce":"f5370fe795f77fec9098de8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"c925b0d3d9d5edfe47b99fa0c6027b1b95a3baf55cb02e9b32e4563bd8a964b24614526ee2b44bb8a9050af983","nonce":"f5370fe795f77fec9098def0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"d699a322bd3e20ecfca05445ef247d12c05f77cc16b481e8892e5e7911939ef3f3acbf913b39ee2570461fd62b","nonce":"f5370fe795f77fec9098def1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"8e157fb1ee4ff80667c5e054ef53a5fa2c82530c91ca2546ad5be4d1e5c32b78e58292d9b154befc96c26fe077","nonce":"f5370fe795f77fec9098def2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"fa9b8802525b682cb3b8aaac477526eee2cd36987a958f5b392ad7f6a053023c9532085fdcbc82773b7d378e73","nonce":"f5370fe795f77fec9098def3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"25803756f41f053447eb0ad2b6dc01aefa114a62e5baca684a8276236962a4a71407dbf31036f98c15b7c2e139","nonce":"f5370fe795f77fec9098def4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"345ed957f5d9e0dc85fb6ff567f2eaee32b6b5f8d1bcfef1d866585eb8c6c1ec8c87beee1f82f6ee5ba727922a","nonce":"f5370fe795f77fec9098def5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"daa40d8e3dacc73edfe83d10efeddec165ef0d859e94c3e83371a867a4397398c4b344e3a21812bd6257e0307f","nonce":"f5370fe795f77fec9098def6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"30d64ea0505aa2127e43a2a03fb88e7990e13248d1a22b2f033f43c895bc57b37512d903d2bef1b73551f42efd","nonce":"f5370fe795f77fec9098def7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"61c1c8ed633f74921fdce8606f9ccefc1af7bd734a891105bf517e4935b2030cc982b0268f427af18ce804c7e7","nonce":"f5370fe795f77fec9098def8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"417b0d336595abb0d04f6f5a50519bd39e6caf424a0d6cbcb2808a6f7a805fa08191a1cabc7f7f659334452db1","nonce":"f5370fe795f77fec9098def9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"20ec43c1c910a2c848503d7a4a3aafbb3a20b5f600cca186a41699857a47739b7b7faaafb3b7ca3a0d43708ae8","nonce":"f5370fe795f77fec9098defa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"e959bf7a27c9fc499a8ceea9122b5536d56b8098329e33c6134a8074f485e3cea39a1e76d41c4b95081e8cfd9e","nonce":"f5370fe795f77fec9098defb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"df95a1a6b5d51ef3a5cd2e2f41379f646e289280b4aa08deecf59ad7b83486653761242a5f58563b8c6db0d60c","nonce":"f5370fe795f77fec9098defc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"1941585732e96a9a7f188b382928a5a1938f1a378b2f186d3be656836552becff9dfea1d0d6a224e205d70d09f","nonce":"f5370fe795f77fec9098defd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"cbc00b99501aa10aeb2b5a0eb98eea69a2485148a136226eb14f6ae9402258f01e5f3f3deafcd91bbcf29224b1","nonce":"f5370fe795f77fec9098defe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"6388a9780b7eba5869a411143d92ffa2a719bb19360f1e8a96f9ae2f93bed595b904d5151308edd23fca991235","nonce":"f5370fe795f77fec9098deff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"f0f644d5950edf7d2b99bfcdbeec5140bd60e14f27126b3d0674554ed9555f986f734e3201fbf340b918e46434","nonce":"f5370fe795f77fec9098dee0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"de17ff9f6e9238079f927243c1ae037aa7003b3e0f7e08cbccd7a0c323a76419c7d2eb54b47c15f2cab0a1cd0e","nonce":"f5370fe795f77fec9098dee1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"aa5eb90f7dacd2a25145103e04c27381f572e0c33b18923b0b7d0a954aec3a4e6c4aaf2a1332f17fe53379cd13","nonce":"f5370fe795f77fec9098dee2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"fa482e474476cb8309dcd6bef793622b0b53b1a6769a7997594f0734d7fc29999c945248228327ded35c0dccf7","nonce":"f5370fe795f77fec9098dee3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"e8a68e639862f02164bcc99c1d37e58db592da53ddb2ca245e6073259891fa69b55aa2d81db900829717ae83a7","nonce":"f5370fe795f77fec9098dee4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"e7aefa5108e31cbb4937fe28bf1cbd6e2bde3b60fc0a8803eabc10205f653a62c3a870d0d56ee9832f0fde65da","nonce":"f5370fe795f77fec9098dee5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"2176b0250742258661b3ee522628ae6a66afc39cbca7841b3ba0b9d4661713695561226a5564a302af777fa822","nonce":"f5370fe795f77fec9098dee6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"3bac96dfb007af1fca52e235cf075950e693178d320617d55eb63be6121a982c32a4f93e560543ac550759d3e9","nonce":"f5370fe795f77fec9098dee7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"8cf90054815ecd0aaa10d85a11b942d9470fafc2b0f9a3b1b5d56975db10844d71ecd5650323f059dcbcbeb00b","nonce":"f5370fe795f77fec9098dee8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"97cf91067d813e05a7fc5cb932cdfa5628b6a7c3d2195c299e4ce18ddf5bd2873e8956ae12755d8bd4fb7912ec","nonce":"f5370fe795f77fec9098dee9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"66734c72a193fcfd82f8b5a775c7792bc63f092b1feacdb5c21c1ac489e29e6e61a265968c177c90d3d30ab7fc","nonce":"f5370fe795f77fec9098deea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"b3623656013675eec924735cd595f51a8040cba8b59d5456385baee13929b50d54c0128864270da806290e1fd2","nonce":"f5370fe795f77fec9098deeb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"dc8b33f7cde1caf39546ed3cf45ca461f5dc4f4ea7ba1833d02268aa2f8fd5eb9af51218518aad98ae47f962a6","nonce":"f5370fe795f77fec9098deec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"2fae2741fea465674f0d3c35e84b8ed7e81d49962e1ea448ee34b445ede85a39c302e5e947f4c5fe53e79fcf29","nonce":"f5370fe795f77fec9098deed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"1a5d702cba38045d1704331017a179ca2f3654d7f77e41f59daad15f60e49cf7db9cb98633707c977463996d15","nonce":"f5370fe795f77fec9098deee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"0ea36c2bda098ebdc472b5db76410975f4fbe203f2cd55a610d4f798465a415d9a9805367d1c6f8c39767df056","nonce":"f5370fe795f77fec9098deef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"b36b35abd67e4f6cd0b25a10f6d6a02290023812616994617606527bb5100cce1d4626d7cad31fd6ad29baaabc","nonce":"f5370fe795f77fec9098ded0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"4fbf549ffda68200e1d8b695565744fcd76a0290f580dd5f189f505174264bdbe7e37d9909fba61044fa33fbcb","nonce":"f5370fe795f77fec9098ded1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"b5df674e3ad9191140d4459f6356d96a104d1da4d1a92c64f6129b3b953aa402a77ebf6d4c65da19d7461cb373","nonce":"f5370fe795f77fec9098ded2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"a1155aea6fddbeedd54b265d8b128bc396c8baf92ec3d80711566303a508867ff615d2ccb2bc0d593bd12db9c6","nonce":"f5370fe795f77fec9098ded3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"f7aa27352ee47a78feac234197b2319ab552ad2575861daa4748316a64b6641d86b06805d815ed91b6d175b192","nonce":"f5370fe795f77fec9098ded4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"81a8ed0d7b22d96706dc76c6736c64ae3f5245d2db3ed2a77ba668a1a8a0cb21429e76d2b161c02b3958455032","nonce":"f5370fe795f77fec9098ded5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"83c1eaf4515f5e75ba7610a46cd31d8bd9d224ab6bb913d2d05e665f049e7d4b0f08b797bd0390af03e9e4a615","nonce":"f5370fe795f77fec9098ded6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"1c5ed192ccdb4167c9b3b38aee334ea3b789d10dcf563dd5b56385b519547472ea5deea986d32677d527997ec8","nonce":"f5370fe795f77fec9098ded7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"8144defc8de8ae2ae3f830d2b200ee9295466d8ddf34032247a2986ee76305f1235beaacc41b5c0cb89fde79f5","nonce":"f5370fe795f77fec9098ded8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"58e76dfd079539fe0a222cce52542178a091e5f079f30446d25aac0d12f6c6d89f6aad3564692951a6f80d1973","nonce":"f5370fe795f77fec9098ded9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"d3900b785927c6089a43c0510be0ab8722ea06e491078b9e45b26b728f29516596d46e3b7f83cc19228c19ddcc","nonce":"f5370fe795f77fec9098deda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"be4e70b9456a8369c787e93d28d4fbfbaef8e507b9eb88b968e934f6f60a87109960e2c4a34a3c4cad8dc4868b","nonce":"f5370fe795f77fec9098dedb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"3268542360685d378a03a277c383c6b11443dfa3f187de2aaddef346c86edf99811e5813155ced5f33813fce8e","nonce":"f5370fe795f77fec9098dedc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"5752de3a266db2e831e092ef8b089f8b6ffd5ae984615159555d848d5398c3abe5333f23e5dc7ded02ab8b1dcd","nonce":"f5370fe795f77fec9098dedd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"296a5ecd7cf8b1dd29fc05af5908da0302945b87bfa69d50a888384c8fedfd6d3d6ec620100b0946337ec2f5a5","nonce":"f5370fe795f77fec9098dede","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"db0ef2b82082bf93f321aead1cefab8a2f7e8c7759dddce0196a8c2c2a74edaafc30a507b9a2ec6c269708f6d3","nonce":"f5370fe795f77fec9098dedf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"074060cf74245ca0693a15451455e8f5282e22cf0f5669c60585d8df7c78b42a43224b0e5b0019a726cd905cbc","nonce":"f5370fe795f77fec9098dec0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"e340cc1551ea0d3a2fe830f64c5f427eab0b227d0f02eac10e3449ea7f9341d95e20272839adcc886f896688bf","nonce":"f5370fe795f77fec9098dec1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"e3178a6b09dbc436fdea6c43975965ee72527462ed6ab215b5660d0f3857dd4d3866aa0e0c511b28a3e4e10362","nonce":"f5370fe795f77fec9098dec2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"03614e29c02e54efc54a6804182852134f08f8c5c6868891641cf33054bbda660356b4fda7133e6719d854e9a3","nonce":"f5370fe795f77fec9098dec3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"c40b31ba7c68f4b0ee1259af579b257025d6cc8cb50efe9a75463ce3bd43f70e12c36d9a3228809755d506d674","nonce":"f5370fe795f77fec9098dec4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"67b6c202fb7a85a90e1d10f7b5c139f3a9558c4430980a30d185bc22c2c09ab1d79733957444411e76f8ad978d","nonce":"f5370fe795f77fec9098dec5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"19fb8ba90a7a6bc02b5ebc9a5cef57944660b59de4c24e06f0742553ee00af03880a461f2a231ab090572e5ed3","nonce":"f5370fe795f77fec9098dec6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"b10b350da0a47ce25ec2f4ce407d5da681abe84e742b76e101a54505c8b4ed4a4471215be255e65adaa1648ded","nonce":"f5370fe795f77fec9098dec7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"06970cabff199ae473e5fcea9f35f2efb28050d9e77f895bccda741ebc0093514618e63a40ad595f3eed15a64f","nonce":"f5370fe795f77fec9098dec8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"446e94f9b21e29029a47fa16d3db7ee7894302ee43ef2c8fb661c6211f57db98e32e90988fc1e2acb8c79e9334","nonce":"f5370fe795f77fec9098dec9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"6c1e5b28c4b0c7d3d07f76600e81e08e3c371a8ae453bb9d62914e1eecf1e169d7abee4bcd2c455b05b9f82eeb","nonce":"f5370fe795f77fec9098deca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"59d359115f5b653c17fac051242a2f529c5dc2ef4caa3873ef847598dd290640f9cb4fa394361c84eee136d6cc","nonce":"f5370fe795f77fec9098decb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"0a5bfaa22e232471c7ffd46b066c2fb8bc43b21bcf2b6e3b9632103171a1fcaf87049a670ac6803bdc011a0ddb","nonce":"f5370fe795f77fec9098decc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"361a2a1cd57bd04bd70eecc0c679e4c6f9bd23a30c7a4d04dfc558078d677d1a5a11b43bdec0f609b55d8c7ce8","nonce":"f5370fe795f77fec9098decd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"c9e3bc96295adf3425113ed42ae373d53cdb4cfcbdd110a336acf124816b90ac4a047ca0d433497e21099cf83e","nonce":"f5370fe795f77fec9098dece","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"5a454436247534dd9ed728da89782ec7cafb39b5c9ca2f18656c6614e0a9158e99fd68768b4880ecb44eb0503d","nonce":"f5370fe795f77fec9098decf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"ecdaf75ab80eedbd323a0bb2c52913c0cf2e9d4fcd93321ed5133179f067748d88620c309c67534e21e44e6d23","nonce":"f5370fe795f77fec9098de30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"968ccea2ae1b13b01e3779c2798926d8613fc153b583826be75fbbf01383c7656be995bf5a7a73e7df46c19d22","nonce":"f5370fe795f77fec9098de31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"e8fc1154160d1d996a6074c5059050651db43a2932b2aac207891f4b62d2c84d1999f1ce835a4923be0096ae01","nonce":"f5370fe795f77fec9098de32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"02d8469771c3b55533ecd16618e34a3492982155d74df3bec904e6bd6c40fff8f1e76fdfb069af8b4c46654a05","nonce":"f5370fe795f77fec9098de33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"f7c1474f2906f5b2f5f15c517a59544f4d2cf77aaf45d3ed5918b2508309754002f1f338edc153dd6ec38cc9aa","nonce":"f5370fe795f77fec9098de34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"9435114dad040c205a079501a3bc215ee5c2f1acb36fd84be074ff1197177fff22141440469f8418f70c1f76df","nonce":"f5370fe795f77fec9098de35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"55be3eda408226eb3899c08063a89f3c9925a6042c4a139c71c88d407ccc27fddc537322d85a0ea61ebe154527","nonce":"f5370fe795f77fec9098de36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"e370021fd6a345a604baa8ad1f20dc1f5e38bb8161abd9049754b0a2cbc3de769fd6e23bcc3609259e37fee173","nonce":"f5370fe795f77fec9098de37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"291e62ef85b7459955739d00b0d1d436006881d3383f2a85533a8d634fd76553a68bee28bad6e7e3775d0a91bf","nonce":"f5370fe795f77fec9098de38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"5d3afe26b2c48e146ec4def5e8dc0cd086ac8126856d6df994d43ca7231ad0536ff6c86a6b0b0388ea980b0c01","nonce":"f5370fe795f77fec9098de39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"f5572e6de1eb549800df1aeeefe9cdd2925b6423519adde46e55aef36ebea488a82e66f0ad07dcc5fd814ccf99","nonce":"f5370fe795f77fec9098de3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"9a536343436b2194ab4da3265d8f7a5d98d683880c81bbdbb92683acbcc1206880cb73f7747d390bb35765b240","nonce":"f5370fe795f77fec9098de3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"a602dc26629795f96047f7d55cd77ad9e355ee5d2887b441837e487c7e582e40b2b5b0d640b4faaf6d70ec032b","nonce":"f5370fe795f77fec9098de3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"4fbb13f59309700dac1a91bea50bfd2e00692160ab9a59c59481ebc10a14b3283310d378a6f6499fadfc881217","nonce":"f5370fe795f77fec9098de3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"180ab59226506826bfae3d9ad5dac908a90a9d53070ec22338991d2622930c643e2750943c0fb92001499b4b19","nonce":"f5370fe795f77fec9098de3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"555359a7c2f6cd13a4551fdc486bbe1a4e89e648af58fba6b34595369e9ece10168a36df623744c3935185bbbe","nonce":"f5370fe795f77fec9098de3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"9d70b16fce7506f959ee4933299f2fb785b54e3e960a2f1ff94e8a53837666b2dc00fccaebe92873287d9613c1","nonce":"f5370fe795f77fec9098de20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"1a44f2b7e1c8b0b59ee9343f8960b9f8fb7d882d6ac33905e8fd90013711ad71510ecfa4c574fa6c9809d99708","nonce":"f5370fe795f77fec9098de21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"1f609e2a1c59ebd3f32354637076630559a6cdba119e4a8b862b7002209ad4dc11bb1f40451635fc29492b6d69","nonce":"f5370fe795f77fec9098de22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"901dd2f0b54ad7b741736e65eec1bd89381824ece71eee464f4c7966490b9c42c1fda6b763ef489c76c3a9d565","nonce":"f5370fe795f77fec9098de23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"b25a4a80817172f3ce8eb385f2edeb7f458bdd79ff7fc89ba8c890f884cb522a483602b1e0833c2011f0aab589","nonce":"f5370fe795f77fec9098de24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"af97821f8c98d2381f390c3dc7c0042d8f61435d36af866e5aebd949ed4421c3ef70f00304b391b53179dcf84b","nonce":"f5370fe795f77fec9098de25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"54785bfaa6131c599648ccbe5548a18e248cd4e14be600d44972cb76ad1710226a7d585a470d47c06e116eb2f3","nonce":"f5370fe795f77fec9098de26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"ad4499ed61406e7be26b862df5a4014e43e5e3e2e4212039e5c6ebddd945bd188b3aba6d74b91cc708f9612820","nonce":"f5370fe795f77fec9098de27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"0c56c0ab5b05f3f571de326070c1ee420eaf9b8971d0a7580dcc58db13c7edea55039677e64090aa4d78e08679","nonce":"f5370fe795f77fec9098de28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"2c0d8138989d7e504269cea19487ac6971d7ed195add0a6f067ac2b3ac48e8ca1801b2fc077d69a7218eff2b6a","nonce":"f5370fe795f77fec9098de29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"2cbe2842c6c765c7d834355caca2d2d5cbd9fe01937accde9d94f3fe1f6296a4447b10f3c5b0644d18d3e903b1","nonce":"f5370fe795f77fec9098de2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"7c3deb57aa3c6ae49ea5aa28dcf3da28ad9ddd61eaeb4b04e4b4fc05574fa0b62b2d12cac7935601144bf58f50","nonce":"f5370fe795f77fec9098de2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"fc078f6e35ba48ed40c594d7524172fd420d7894f15489446a42af1b8ec94d769a3a3a27d058492f1b732bc622","nonce":"f5370fe795f77fec9098de2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"0241b98114f4b7b6b5cb7865d55b788dbed8e07d350eb05214f89b870a1ca6b74614dea4624dca97628753e84d","nonce":"f5370fe795f77fec9098de2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"c262a1833396e6e18df3032d24edd97c9bf00bc8e028bcd1e6ca8776faaae2f15852521fc2c2ba388b0d577b38","nonce":"f5370fe795f77fec9098de2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"40d71c599365750505d8e5e05c66c92cc6bb79ee5408348f383de60a1d8178ce9bfe7484ef9896dc2ac60be576","nonce":"f5370fe795f77fec9098de2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"5b448e60ab4dcd3e98ec92c607b17a0fc62d3c75237befdb51504e1bad89b112b0f100f7d1f52a689fbad38b2f","nonce":"f5370fe795f77fec9098de10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"11ebdbcb6a4026b1b790ad32388d7c77b35fd20260999130e07e77179f621541557e66e1efcd4e0fe17afb38a8","nonce":"f5370fe795f77fec9098de11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"2fa9e2e16e2a81f2b6f023f7af24dcc5e67776bf5d8a9aacfa2fd0d6e48ab0fce8f577bb3a2c1ffa6b8b25b335","nonce":"f5370fe795f77fec9098de12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"68e631a85c31b2c54d45178f6b0b68cbe237134eed743a4fc58ad6885cb2207a9de49301d34f37ae81656fa04d","nonce":"f5370fe795f77fec9098de13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"85477a633222ce36b767117ff9bc3ecdd8693be5969cdfa67d04f63c8d63cef4e28465777a87fd75b3212b0b2a","nonce":"f5370fe795f77fec9098de14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"bfae6a5c41b62d4cd778c53437cb9e33295965c9c51b65de0737204fe5197e5a57bddddb936fb1d479091d58e1","nonce":"f5370fe795f77fec9098de15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"b527409241add8ff68e21c9384db6e8ab5634a47a8abdc9ffa5f122f34e1cfaeed3e20c92dd57caa17ea11c08b","nonce":"f5370fe795f77fec9098de16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"05a4a2b47e9874499d201d4e46b758451f16506a20bff8c91f404c4b2617420424288a3872e066ad90a7bbf9dd","nonce":"f5370fe795f77fec9098de17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"7fc094522bf77873e22b23812ebf3146fa339df0e561d74af265837b3f7c35e13115c87694aba40fd4b7f131e0","nonce":"f5370fe795f77fec9098de18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"d6897d89ca1e873b19c8038841965a85a665a68145c8ba82068f642e7fdc3b80058ecdb6a5c547fb835527e23c","nonce":"f5370fe795f77fec9098de19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"9ea43c5834f3d78b0923d12b2f94ab4722490cd2d125c232e1f2a6fc1ef0f6cda627054ceabff85d98089e8bc6","nonce":"f5370fe795f77fec9098de1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"c49664bf039b36f89e6507ffd615e2fd7db811f4e7fd609858fd45185cf4406a0343b37317fe2240e6cae9a064","nonce":"f5370fe795f77fec9098de1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"ce32b71dc4f1ca7262d13f8716b2017bd9fdb58d566d4656426a49283666a916afde308c0d1de39c3de1df11c6","nonce":"f5370fe795f77fec9098de1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"8dda7a5ff5b74a75652911e3528b7baf78c092d2eb4b6e4e102e0ade6af926b01dc8e46563a9b3bac02a2bbf8a","nonce":"f5370fe795f77fec9098de1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"bb291a188eccfb76fa103e70f374e9d356e42255314967805510129d036ddc5af184460e9a5670612e82c27811","nonce":"f5370fe795f77fec9098de1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"08a0ac3821a58fcaeacb59a0a128c90e528e8774f0b20ffbb9212d5036829bc76a563e6d0cfd23250abb847531","nonce":"f5370fe795f77fec9098de1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"326394c5ccaa42dcfcab1dad95e54f9fc34219193b016f9d48ec74338a0b11f289e05fa9cb28aaf2aa36cf5c01","nonce":"f5370fe795f77fec9098de00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"196af0a7b512a08b0baad2042492fa2c9bfdd7b489cbdc9b335f18547f8fd448b04abaa0e5a263ac6f7e644289","nonce":"f5370fe795f77fec9098de01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"a6001e4c32f373fba95a7390d9cc5b1f33c8e913792c7a08c67e6b60c8f8ba29e20a7867f24373bc85c7e4793b","nonce":"f5370fe795f77fec9098de02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"1641928bd433bf2328303103df6492e151759824e8f197fc09df802a22d5eca6694d45fed940ae7f88c024dac9","nonce":"f5370fe795f77fec9098de03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"f266b6e01949ede09e8ee3362d703c67907afb49dcf75a26ca206d7201056c788782b2c930163603b70b541c1f","nonce":"f5370fe795f77fec9098de04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"4c1ffc1aef048c8966637a820cb61f62afe920232f8342a35148c9f0519c7e93b9c8a5c8e31e2a6a56b5f4616a","nonce":"f5370fe795f77fec9098de05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"2e4e7d25c8a45f5d0e777543245b3318d9e17c75379abdb2a470c63f7255a3f8a2f26db6161930f16b292b7970","nonce":"f5370fe795f77fec9098de06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"d0e58ca3007d4f320c4f2a27fc2ad4ca852f6d491334cd2c01e76f890622542d4444dccbb91e16469bc70af944","nonce":"f5370fe795f77fec9098de07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"78d6e1f26f30360c966ebbac30f6b3f49094670563540d715351d31d6a678da856d1c303589c366c43a97c9260","nonce":"f5370fe795f77fec9098de08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"b55c07bfb67c88cb8f073331c8b401d72181dcd0a13a7bd509957bd467f6f93afa4f93d8a465cce745ee1cc69f","nonce":"f5370fe795f77fec9098de09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"a95f6a56c414d5844a16e4bc48e4b3b6f4945b1c7f1917b3885cc4f30bf63a3c7a9fc4767ba03e5e5a544c3bff","nonce":"f5370fe795f77fec9098de0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"9feb0b9bbb23d25482059a4e75b2c0b8fe073839757eb64c3473489e28ad4bad3e9bd5609bf24a7d5c3c4b5c4e","nonce":"f5370fe795f77fec9098de0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"fd009bb7e86029a92ecf460f7be895b07c8949897a4b35645865d90fec22fa586764ab7a2b74004340b3c81052","nonce":"f5370fe795f77fec9098de0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"346b3e1f3db68c31fe87ab7777d77ef8c3155082f4994683ca180e712a48a0daad3efcb42a9d5a4c3352390055","nonce":"f5370fe795f77fec9098de0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"235fa73e74cc383b80ee4060c4ebc3dda2522864398b551cb02c38c60015f6ba4b3b61e151f43d26ce602ad6a2","nonce":"f5370fe795f77fec9098de0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"ab506fbdbe194100b42dff04d836228ab8f66484997afa4bb3608838baeea3efc9450a6f6858fa66f65c8307bc","nonce":"f5370fe795f77fec9098de0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"e2a4cd05f652f81c5ada6c791d9b7b55b8ea9100ba7f3374001f99350d83a1c6caf104e0737f277f44838975a3","nonce":"f5370fe795f77fec9098de70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"23b21baafadf0d88750989eafc64a2652a8b1858d38b459ff2e16c3f3c9e2ddc9ff9af2a35cb62f405f1fd2995","nonce":"f5370fe795f77fec9098de71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"4a5492591da8c7ea3123f337f192178fcbde2361f4d0e5785bf44c46468d154aed3ef736173cd48544503a5463","nonce":"f5370fe795f77fec9098de72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"7db63bde6206d2398b8fde82be815bbb74f187e997e70b98cef96efe2209affe749f90d00f24dc5c3df9bbf4a7","nonce":"f5370fe795f77fec9098de73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"f7226c4e35b9da70b56eea0194fb4ca48af717a1f8025be8d2e198314984c3e4c7a7d1bfb320c89a3a47657385","nonce":"f5370fe795f77fec9098de74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"88375700488629b1762d1262a515eca22de116e0c0a40783f53a1ab44892386e5ce6879d92314ad8865e6c06b4","nonce":"f5370fe795f77fec9098de75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"f30ac89116c0a94558be8555c8e1dc2bfedd0077b3cb29c460055a03220906dfed2e46aad234cd0e2458513735","nonce":"f5370fe795f77fec9098de76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"a833b7ff2273b073083db9dc2e8f54bae4e54273871f940657be52f18cacbd605cf244d5c4c7fc99c0e11a52dd","nonce":"f5370fe795f77fec9098de77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"bcc52707472f27fc6948f851a5782b6b3ae7dbcae6a0ef7ad479b63a4e6f2174c2bccd5949c84ae8b3323aa5e1","nonce":"f5370fe795f77fec9098de78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"61fb76504c1150833532a122abfe618f24512b479e2a4a29b4b4c643881056e57685224b96c397b2fa834bedf3","nonce":"f5370fe795f77fec9098de79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"b492076d3c62222eafc2a10a9d2e2ece6b972030020dc1a97ea217ba21f1805e3ee2e6e0057624e05474b1d93e","nonce":"f5370fe795f77fec9098de7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"3e0c2458f6232bdd093132ab283b4631bb7613b4dea43a95e6debca90699bd5d311afbe570708fee8289798bc3","nonce":"f5370fe795f77fec9098de7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"e40717934c66bb795a690ad2fb32b7f8eb30a5dfd424ee3b6fccfc6fc0addd4ff010df54db7eb28fed5b052dc9","nonce":"f5370fe795f77fec9098de7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"2ab8f5fe7a7529945f9b6a6b83c4c6629663e8d228d4717736cf361b403dd202587603438306b933a81f8fb1ac","nonce":"f5370fe795f77fec9098de7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"239fa24cba338ab335fd83461501adb6174fecb3f7c0e7889d1fe973bca74ecc176c69a8a1de4440672308f781","nonce":"f5370fe795f77fec9098de7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"ec4c5d8dd8b1b1ee62e0359826602b629af105b0d36c9f9575384795bf9e0f9afe32f9aad3c75ef025f56b08e9","nonce":"f5370fe795f77fec9098de7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"7aa9a01d3606e189a7ea43eae66555a45735624d64b35edce554842267e0722402948a184db94f14a407b6d056","nonce":"f5370fe795f77fec9098de60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"fe1d8afa5e96e90c053653141e19af80b98adc27151918d8e821b40d55c854b45f4b1dc1fac6b0864ccb2fb751","nonce":"f5370fe795f77fec9098de61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"b7058404ae72ac5d09209d6d3c82add101aedb7048d85a13ee007dade1417797285090942ba8f4b3d822890f15","nonce":"f5370fe795f77fec9098de62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"98417157207eaa0fb4378aa56e77fc7adc5d062da454a39922745657482d9af6828641c08f19e41012735c489f","nonce":"f5370fe795f77fec9098de63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"477affdf22cd20a14a4e05b6917b61434ace7ce07b994a96e8678ae39fe606f5d1ce1ad7e9f90071e46b721d88","nonce":"f5370fe795f77fec9098de64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"058766c1c8d65f67f221210ce9af2ea2ad8d599b95a230a7fd4223147c1ebfb551f6b402005419e3316f2d9fda","nonce":"f5370fe795f77fec9098de65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"1b499e8384ff57680935c6af41f621a61ba584a339dddb403d678525219439dac95cc2f71e9256bb8632daf1db","nonce":"f5370fe795f77fec9098de66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"3ea5ea43918e35ea069cc3aca219f7fb5693f321921e26c196c0929f9ff85318e70e2d5c28b7ab088c5f49c94b","nonce":"f5370fe795f77fec9098de67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"58170587d070f12a941ad5c504705352030d849c684efda2dac725c30a80d8ca5fbd5376b1434c41db4764bd01","nonce":"f5370fe795f77fec9098de68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"b7d11bb82044ff7e6d4c2b9e01a4c6bb327d4ddd9b03c477227569cc6b5a43024f029b7ce7a0e3974e9edf6c1a","nonce":"f5370fe795f77fec9098de69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"27041f7dfa9ce0e477d2427fae6e5845e89bbc1add27874ff926d2390162c4f1518ab65cca28e6e4d74a8d88c0","nonce":"f5370fe795f77fec9098de6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"2ce59009669e8bd20c16acb6d1a8b1e691ee70f02e09ff1f2b42de68ae0307d9d7e1053db1025ab8691efbc3f5","nonce":"f5370fe795f77fec9098de6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"163acbab8208358e7f840685c0a8198d12211ccf857d49966c516f72541191595d78d8c2b38b3ce4e63f97fe1e","nonce":"f5370fe795f77fec9098de6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"90fcc621ffdcb849ac2559feb0ac15e053018d8da5e1c933c71a3ed87d6a6c52b73dd2faae9a5aca0fdc341c89","nonce":"f5370fe795f77fec9098de6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"beb93d976d29f66e8ed24803860a29691f55aacb49d82992be7489432dd0dcc402ec05a86e426b3e4d724de950","nonce":"f5370fe795f77fec9098de6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"f41303998d21688d42e9ee06e361b943c9fb2b4901c97c9eaa6a428d706c1b5b124816c172eb555a1ff957fb07","nonce":"f5370fe795f77fec9098de6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"a8e45b63e2c4d9a2e6ea7cf90d8237e250487f667d28f3faa90ce5668f9a5e36acf9063e3b735acdf2bd64b458","nonce":"f5370fe795f77fec9098de50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"4bba0db46f8dd1fe7992a794f8cbc3522f5be1cbb68b8d3b362f07ad5d5496545ad6ec69dd69246db5744d7673","nonce":"f5370fe795f77fec9098de51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"3a05205af769203c83293c80cc166af7314b5404635031b69a5a87bb7f7c799cace241e5df2b33aaf1408b2b52","nonce":"f5370fe795f77fec9098de52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"e3bf141bc208921fe65289cbe035cc6a8f04402b9c3bddd280a8342090f30cde949f7dcf1b63c29990f69fb654","nonce":"f5370fe795f77fec9098de53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"a8019c279b92073300f482f0e83fa6c74f38647c1649738823615e9df21296ef29a81c4d43376a87366b88f378","nonce":"f5370fe795f77fec9098de54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"feb9b988bf5a0bad323cdcce3813923054886dacbd4bc5cbe895c3faac60746b119fc1cd7b33dc1cb6f0cfdc82","nonce":"f5370fe795f77fec9098de55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"51b26388800da6a7a242471b54140a8e9d160d9037dde0054f2a885bd6141fc11ea7b7183a36fca2a05c561354","nonce":"f5370fe795f77fec9098de56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"8a0ae671bfe33cf95b32408a2beb25984bf8a695f0aea1d217ebd0ffcd59a52a8151a31b34bf786db02ca02fc7","nonce":"f5370fe795f77fec9098de57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"a6d39a73bcb65fdfe78aeba1f93edd581674561b47fdf862b93bb538c1ec1696b8a149a5fca0324de97144bedb","nonce":"f5370fe795f77fec9098de58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"6a56a25a3d42cf0f0f44b35888040b3e88819d4bce0dfc0d348b2f7f98b46982753b8fadb272d1dab6d4d26cdf","nonce":"f5370fe795f77fec9098de59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"ed519590b865c64c477914fc0df8bbe76f6cc4e2f2393f4ead9fb70af9eb788bd2c9295bfd4e74ea4b576cc904","nonce":"f5370fe795f77fec9098de5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"2b3d7ab857a87c4625e87349658078eb6beb2d05fadc4925f5986cb1a5851e83017633eb22beb78ba7cbc4afde","nonce":"f5370fe795f77fec9098de5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"6d91347d66d5eed03b4bad5b5f86a01a49aad63a35fa76aebe6cd7138cf4fac769f797a80c70b36f7d72190a28","nonce":"f5370fe795f77fec9098de5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"7d24e6446882d449f3196ff786749f31d649242d09651778b5ae7b128fe393ba8e546f3ba64f4594418f9eac04","nonce":"f5370fe795f77fec9098de5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"038cc18f421a160d787e0ec44f06261a223ecb18571b43fb1b5e74af903e6a02f66cd68aa4dd46f0f5c7f41869","nonce":"f5370fe795f77fec9098de5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"f1f85c1f635d129f54b39f0876febf4f344cc890e5012c4a2b0dd7c34e1ab9d98a7a9866e3bd7884db16e9fab8","nonce":"f5370fe795f77fec9098de5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"f4aaf18957d1f83bbd8cd529fdae0e039804055dff97e7469006115e18708caed9d44b0a5ec80769e4839a20d7","nonce":"f5370fe795f77fec9098de40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"34ae4c39faf1c9ea2eea1b544f3f5662c32110e5990081411e6d8f76abe75ddaed06e29e21000cddcf919cc853","nonce":"f5370fe795f77fec9098de41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"c5848fec48746310f2d42417248a71119701efdd7c7e2315ae27a41f4d2b0fc6e325c2ffb2e70138438567585b","nonce":"f5370fe795f77fec9098de42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"aa8975bee927c4a16084d49eca6bfc6a9b47d2cc887700b254db2f529a1f0b7e8b6573cf712aa301bb33b42e50","nonce":"f5370fe795f77fec9098de43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"40ad52655a622c4551dded35ba86fabc5c692b37b86696ea5ef60ddf79e0a5f574a93d6b83a12c99087ac26f26","nonce":"f5370fe795f77fec9098de44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"c0c7da4310260b850b603169d063686be4b84b484bcec43f5fa8d1eeb8b7a09665181419cad4212a928563c764","nonce":"f5370fe795f77fec9098de45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"7490abb3f3a75f138f3bd927eb27b128961cb8d8e1c1e7c20550ed647dbc8893e81e4c3aa0781f588bcfc36e7d","nonce":"f5370fe795f77fec9098de46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"d452c6d3b42b1012dd0a77ae9c476b5c8f67ba98a4ccab02c6dfbd8e5756b161b71dca50d25a5f622867233dce","nonce":"f5370fe795f77fec9098de47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"1da67ab17a9fc80344e8be5e42ed381137c245cb004119030f2a55a975e3d9241029da6813ecd4ede44b79475d","nonce":"f5370fe795f77fec9098de48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"d93156a8bfbb8c2ae5cfb7771bd30e16a0d779cc7217513343f6e253a1cde70f3cdfc62cdcb8b00dca2f546169","nonce":"f5370fe795f77fec9098de49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"77be25425c469676cca91c3dc8a57c4ae6399110459e6cfa226d06163469462f77273672aefdd0b50a24573a58","nonce":"f5370fe795f77fec9098de4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"ac6970a86ba71b25552b7057bf24a29dbfdf08fb6dd15e484e16069e21a4ae1671a18aa241db9548fa4e47a78e","nonce":"f5370fe795f77fec9098de4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"e14a8d1a4785c0f1b3494cd1cdff31bfd014842ebb2fa07dedaee97e491a27259c91c164dfd0fd11febb360342","nonce":"f5370fe795f77fec9098de4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"d3947c93119be0a274a28f24fa95f39d143bcbf079c3bcbecf27b85fc8f52bd9c61e961d707d84d77b6b3bc488","nonce":"f5370fe795f77fec9098de4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"cedddf41d3325dc4caaf738b73b960e7704e880112b2e8eb4f5e4a588fbc9d0dd8689dab5fa3c0059f75325159","nonce":"f5370fe795f77fec9098de4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"d54024347dd385c9bb79d3ce4fe3838f6e043124aa9e62195a275ade41704b9772e03999b1de98b9cc523d9d0e","nonce":"f5370fe795f77fec9098de4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"1011f39318f868a14e3c254ab69817223faaf60da7cd96417dfb99af9ce86c76c01218cb4d790afcfa8915f53a","nonce":"f5370fe795f77fec9098dfb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"c791c1120399fca95bc48f2b99b65b37e6f619257b6b70dafcd6bd4e99a7e6fd"},{"exporter_context":"00","L":32,"exported_value":"a3ecfab9e08d8ecbb10293f76309d41c05c93902d13d7b3ac04903bace208b58"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"b7787231dcfd42de256284e9ef270b1664aced65d09b870477a6527352fd3d95"}]},{"mode":2,"kem_id":32,"kdf_id":1,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"6959b1b4b5e4eaff5d92a809de59a0bf24b90e8268ada3018d5486bb227efa7a","ikmS":"ac374ded332d25589be26199a77a0589ac8d887ff0a3e7fd0d51d7854e973b8c","ikmE":"96c8b7275859a50cca6d9d38c0634bc04b47630bdc2981c89d5922fae77ad391","skRm":"de1b7aec456fc43d6f5c5a83cca23fe1cf6037ca7dcb8f331016272cf752ba75","skSm":"fe3184b8589464f694322961a6660307dca66485c53d1b9f3f71362b16e85eb2","skEm":"a8c0423973fca3ed136c2b8f8ef9368c3703c431474f098b56a48438a86a7843","pkRm":"915cf185d937cf5fe261ddb6237682bddaf41423ddbbf9709de7c994b1a62e71","pkSm":"8420f244a6d9f2ed5951912f66310d8b078932b511953272a6986904a08ea51c","pkEm":"b2522dca3e0f209dd6c28d654605c308a79829effa5fe608e5820d149a85eb1c","enc":"b2522dca3e0f209dd6c28d654605c308a79829effa5fe608e5820d149a85eb1c","shared_secret":"4bb6e0ab9a2989bb624f5537b528bcac180d362cbdce8e59d904f880664d7452","key_schedule_context":"024ce5472ecdd5093ba0aecb8f871ff13f1fbc90ee76f0e18ace1a1b7e565bafa306f6ef962c9ee7cea40407b5d60f0f26990472faae3ac44c78366f1cac1ecde1","secret":"933c423b50aa01eb81af16298ead28e37709c95006e0266a23dac6231eec26b8","key":"c1d8b066b79bf7a042c74b202cef24f5b78d164dd56be35f4fc51a02d6bfe82c","base_nonce":"652a2286ff3a04e51582357c","exporter_secret":"7364a483d97058079a79e184618b60b89c7530ff070aa6cd52a7e27d99cc7acc","encryptions":[{"aad":"436f756e742d30","ciphertext":"3d83a89c1ddc05f73d4762be65e38ade112af135e3a01d30e52674be7361e95f5ff679af7095a799a0d5582912","nonce":"652a2286ff3a04e51582357c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"759cf0e977241745d8e4d965e27105ad4b084a5d24af1b212ef56df1e6d4629897fddedb6fd6f19a500037f65a","nonce":"652a2286ff3a04e51582357d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"27d3bca60de8d9816dfe771519fe5ed125dcfc5b8104f46da203e791b8d8a384a644900881905f6ed2b9eeaa7c","nonce":"652a2286ff3a04e51582357e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"b7bd90cb932972656b92596739ae31d05002d4697a9d68cedcc46af9da0e8546f59cc222cdffc9e7d945d091f1","nonce":"652a2286ff3a04e51582357f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"20456b66489ab9d76e21c8addce3bd1f4c7fe7d222b301c81095231e9a318b40f595d80317202bd13e10944ad8","nonce":"652a2286ff3a04e515823578","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"1eabd094ddc4463e0a85460bb8dd37a6311c51f9e6843369b0f9153f41f72b8bcd939308415e7353a1828d32c5","nonce":"652a2286ff3a04e515823579","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"48eb1d842c1386efbdef158bfdf730d969215b7df7559d4da6f22530eeaaa76648bed3c28354fbdfdabe8cf2ec","nonce":"652a2286ff3a04e51582357a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"7a2f2606867fe00e2bae3733f6f18c1c2d6c571fe5365950073ad1cfe5dcc8284de68dc7544124e99da1612caf","nonce":"652a2286ff3a04e51582357b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"b3ffa08abffdc32f4e64ac26ee6f07d46a7b157dd2790c071e53387d897db9a0f745a5c1f2be9e0dec94480ca2","nonce":"652a2286ff3a04e515823574","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"ddc4f86bbad8b658a76a08635f4d8b283146f7fa95d43e903de1a348fd4ac038f548f3a31b4b8eda3c3da38996","nonce":"652a2286ff3a04e515823575","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"dc16bac4c7d01d1309fbc492e57af7496e1907897802051d929ab9e2df151bb700730f708e4df668b7d4563205","nonce":"652a2286ff3a04e515823576","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"b48b0b8db90facaf9a8bdcd8931d2eff52f92b74cc9f3d0d0b02ba824b5d744b8bd236f7136b96d0ece7475cf9","nonce":"652a2286ff3a04e515823577","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"dce49329d2ebe9ba8de49f113c501d5e0beb5757556c1716b80a441b570f837f0275ea44ed02657634086154a8","nonce":"652a2286ff3a04e515823570","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"5fbf0e59b2e61c112d85d5931184df1d5ba9fe67e332ce78b6f1faa27356482e4173398dd578447a9f807ab68b","nonce":"652a2286ff3a04e515823571","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"b1b9ecbd01c2ec0b93604d5437f667f9b3c9f365d5de1cc517ccce958a55cf94b802e5cd7b5e8b68445c387140","nonce":"652a2286ff3a04e515823572","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"c061a873a04232306e8f8e6f01d94824fc99daddb527415eaebf06cba882adaf1aeb7e55960dd048d216c22ea2","nonce":"652a2286ff3a04e515823573","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"4f2b638011f20e4b57e9b7820df1a7f5d0f16ab1276adaf253079ac250eee1bb6d444924a4eb8fce7934289165","nonce":"652a2286ff3a04e51582356c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"2bd2bbbe8d7c91d19ad06f253086b2b7277b03528e8b9760db60a1657336125d2f018c4218578ce46c80a75fce","nonce":"652a2286ff3a04e51582356d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"3b24cc0bcca4e7acf36bd68c6c6e233f6c229277593837d404ea49d130b56488bdb3b5f51088920a0141ec8efd","nonce":"652a2286ff3a04e51582356e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"8ebed8c805881912d793cc246bc04ab4ffcaa6d13dc120ac81a8350e1e4a59b54766af79d13526108feeb66c62","nonce":"652a2286ff3a04e51582356f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"e42b544f650eb6869d2c1d8b242a57f38654b72271b092c286493c7428cbb55a477e590b89d93d4b20c3ca0686","nonce":"652a2286ff3a04e515823568","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"6cab088dce51a0fa486dc2cc48df5afc668ead7ad4054ad5f56f5b783baadfafb900a259cbbef6f23b3d48e951","nonce":"652a2286ff3a04e515823569","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"5ce4a7dd3c86e93912a9ca6c617af5b47b4521cd8c2a11ce1e6f616a62620a59f87caea13217eb778b23fe3bed","nonce":"652a2286ff3a04e51582356a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"3163af42852b5cbe69e00eea7b357f8b305283ba7be3ab13f332462e87568975d72d90e7d689c04bd40ff65230","nonce":"652a2286ff3a04e51582356b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"4ad633806ed22aabebaa5715990daee30fdf723507a7363a28a360d8d0a6899b9c6a57a29fe49cf8917c23dfcb","nonce":"652a2286ff3a04e515823564","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"abfb74348bee5320a835644ff572220cd16a9425e59bdf74d5f741cb55d11014b11e6a0b63313e7c3c25c2f66d","nonce":"652a2286ff3a04e515823565","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"72ef2c5c07b43b4cba51ce372a578904005bb639d1c0c0282420c653092b41216e5a0a1aadf0408f2627365536","nonce":"652a2286ff3a04e515823566","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"28804db5a695902af9bee9c33d7e58bf7ec2f98aaa92e42d345ddc2f534eb3aaf833f6af772c38114bc8d1a19c","nonce":"652a2286ff3a04e515823567","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"4d61252a539da3a83def69fb9eea8b7b0e1f84e7c686b82a19cbe4c6056167825e7218a8376106a4d50e22e4a3","nonce":"652a2286ff3a04e515823560","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"984cee53f627a7e34d8ba32f93586eb8f2785ab6b7ce907dd56a68c61ba856aa6cdd5a3a7fff95fd19092ac4da","nonce":"652a2286ff3a04e515823561","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"38be20f3013c38b464606748a6224e6c0936464f41ac082093e62419391e8b270c41cd5278bb978d967962c30e","nonce":"652a2286ff3a04e515823562","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"6831454308ab20c86b3c8cbaf69ad8451c96d03bb39b94e0238ed3812c8ff2ebfac6dbed539bcfb0dd2373aabb","nonce":"652a2286ff3a04e515823563","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"1c79a991fe11547d6df6cc0b2713127559cf238d0752fc644e48edb8a2a9ed7d8f8d85097acf06e0d205c0f0a8","nonce":"652a2286ff3a04e51582355c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"2870bc93daeaf8ac16ff5da8532b683846d78e7c72852b0b9c5196a9f1ded7556017ba7b96d774201b11b52a1a","nonce":"652a2286ff3a04e51582355d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"78744b0729934ebc24f8ce4320e0bf7737abe1b3dc344fe4c25eaf6e0ff34d1866194ece992f4b3d09f6684ec6","nonce":"652a2286ff3a04e51582355e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"13c19e648d72ccd40303cf3b08d73b676d83355064232b0ce4550e9b3449b05b290e9bd4d2748f40036ced4199","nonce":"652a2286ff3a04e51582355f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"ab253553841363a73d2302e11ab2de2a59b66730af53bcdc81993b7d6f69ad7482d5fc65565f962491104c4a43","nonce":"652a2286ff3a04e515823558","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"463521b5193ba54b6d65f61e14a83653393a4608c8c21a7b64df3580cb057c472a06d3a1a8185cee932cb8635e","nonce":"652a2286ff3a04e515823559","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"79a5867a89f79cc96b7f548b1fb043d4dc6b2c8191228a0af4ed7f107fd72b51c528a0b74126adec6285ebda5a","nonce":"652a2286ff3a04e51582355a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"a99f9afe7c968fef03e756d50231c1d17bd17e076eb8d61d501bcc1edb08ba4ac314ba66cd9646eab83589aaf8","nonce":"652a2286ff3a04e51582355b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"57d2cf336c15b71308c7e3766e12ee48c33cb072513f3f377c2423af775fa99195a3898364779195a00c27b740","nonce":"652a2286ff3a04e515823554","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"61e501a4c1f36feccae390c57a413bcc3c465e83321c4f629dda5728d5472a889d2e9e39d38e6a277add027cab","nonce":"652a2286ff3a04e515823555","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"1e988cfd5ec7e197d3ae0ec458bf81dc2546493678e8cc1d842533dc456a472f7da3332a62687a4f08f59043cf","nonce":"652a2286ff3a04e515823556","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"6489fa68547d123de7627c334d2063c047a7f0dec5e51a95b23b330d7b7680e31d7d8e12bb4bdf0bd93b11e6cd","nonce":"652a2286ff3a04e515823557","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"7b02525cb4a8a43e213493674356da3e6a2f35ef4904d8aa963849474e835b0d6782965c478437b2d8fe576822","nonce":"652a2286ff3a04e515823550","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"8ed712389fac7e1fa6f6296bb79f91f4d2cc96a58618fd401b8717b377dd147e9486c1ed537951a7cac16caa61","nonce":"652a2286ff3a04e515823551","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"c748b034bc7e0eec00b8f2943e18e34970a6fb1ec85c5d0c56a225bcd8df88cfd3222c24895494b32d3c26c3cc","nonce":"652a2286ff3a04e515823552","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"442bc7333a56f24f2a470ac6720617db21f04b28d7adbdc0e7554a7e77c2b27c7882469d47aa5443bf45840e1e","nonce":"652a2286ff3a04e515823553","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"0b2f967b591ef87b3aa719628795aa790f4b0d03c1555da117587b33a26c2dcc0f27420ce4e5c6cfc0bec19b70","nonce":"652a2286ff3a04e51582354c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"dc02da0f11bf6e80191fc5161db461522aea8a9230afaa67d118ac3081f9fc9d89d5f92ca2bb3e7a47e7859e47","nonce":"652a2286ff3a04e51582354d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"d6c6cebcef671fa57497e11542ac39027a52a9c219ab163006285f083d0cebcf65eaf0168ff028240ab8ab6459","nonce":"652a2286ff3a04e51582354e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"5f43692728dbabeaadbd0cdda08cc48b7461320b26ee157b040440f5f66e2a74dba425d64037f59a47f6237010","nonce":"652a2286ff3a04e51582354f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"6723a1f8f0a42fc5c60fa927573c5eecdfbc4208ea2858e865d68ecc2bcf5141eb2f648b4861f8b6ab50c3758e","nonce":"652a2286ff3a04e515823548","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"dcacf8fa27d6c1ff19b041a3ef303caa4327045c0e46e21cba644ba387ffd0a3566b25a082b982c1554d1f1a2d","nonce":"652a2286ff3a04e515823549","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"6f4df42468a210171b9ce0d1a7477694d01b76bf1ac4e2639b930f0a8b55d6c22771d03538c65a9c27f7569fd9","nonce":"652a2286ff3a04e51582354a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"74476a5e1b6f54420c36f771615ebb0a6182e91501e79555f77ac1b139886372652cddd39501f420d1c072e50d","nonce":"652a2286ff3a04e51582354b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"e3aedecf942bda1aed5836d5d92e7a96f1a4a2c335381134649eb5a50449acddf23d5a98ffcbbc9384bcf5efb3","nonce":"652a2286ff3a04e515823544","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"36863dbe384712b8b0f30172a3aadade6f11fbc2d1bd5e392cbf9b0865a9aee4913a1099db5b09e7d3ed9279b2","nonce":"652a2286ff3a04e515823545","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"f05f0de8fe453479d1bb7602e6c1e04d5a7a8babcee2fe3bec8eadce813dde49e6c33d99ca2d3fe14a9421e685","nonce":"652a2286ff3a04e515823546","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"b639944389399999923b764774bb86698b049e3e50c9d2cfb529056696e32f3fce04f5f02554a4f21240ec1c6e","nonce":"652a2286ff3a04e515823547","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"0ad57c390ca39869f4883e14cc30f61430b6c35d2c98231b76e413c7574bb2b248c4a9129f83ecadcbdc7b9c62","nonce":"652a2286ff3a04e515823540","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"88b105ebe4d9f009fbc84d91a0fd6f936ca97b8732a6cb293128780fcbe2a9cc07b751bc028708e6505105982e","nonce":"652a2286ff3a04e515823541","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"a37c7a34d7b9f8b5e74706001a0c1550735305850fe9380f1edd492c1079ab879fb753eabb818309f97c10d768","nonce":"652a2286ff3a04e515823542","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"b1cccebbbc38a8239cd48f0225470b7e98634b2e6abe94845f3399c88d2c17847c81d57298dccd81800f60d8cf","nonce":"652a2286ff3a04e515823543","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"7b930d385301ab3eae681c9499adf509713d2fd3c975de7a0cd2910f276d1d7bad15340f8fe2d4c537e95a68db","nonce":"652a2286ff3a04e51582353c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"d157e9f9d80959ccf388af998fd4c4a746ac102ddcbd7816786872076e372323e287de7cf47bc52e5aa8362f66","nonce":"652a2286ff3a04e51582353d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"000c65ad0931b1ced3d6b127bf2b14bb7226349f664cc481ea161c439ca1d2df268497d21f6b5f346e01690fb7","nonce":"652a2286ff3a04e51582353e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"f373ce39d80b0e4e3d90c14f89bd356954708fd7e7cfa0743df5e298428bc3a65787e740c8caf8cceeee7658d6","nonce":"652a2286ff3a04e51582353f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"5f3bf2c812cca0c4219171dabb1ed6298f738df6d52c4d8c9e4fa9f7c1e1fdda340225528eaf40b68816e17e88","nonce":"652a2286ff3a04e515823538","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"873b1ce5113a7915cd2ff5fd4c78efb882575234ffbdb27910fc0e4cdf5afab98099bea6ddf108a0a94a7e4f12","nonce":"652a2286ff3a04e515823539","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"df45465740df2c602cfe99272ebcb888ccee7fc6c53b68f16aa27ffaebc6cf0de4f151582a617fb92d7749038a","nonce":"652a2286ff3a04e51582353a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"f725fa2c5773150a3cc47273c5bf705d8c7afd2d401aa5c0a4a1607c366fcfd0a107bbdac677a1564ff5dc5539","nonce":"652a2286ff3a04e51582353b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"d1e54a7045632411488be6d796b03d1383be353913f84319f71bce2c1f2b614049fcce55ab23df632fbe5fb9a0","nonce":"652a2286ff3a04e515823534","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"9462c1660b0559e88888102451969e79a786726af0c15de9487d3eeea7b59fdf985125b333d9d653a5096be973","nonce":"652a2286ff3a04e515823535","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"3acfa296bf4dc32bb422c3fe0f6c2716c03f656eb5d79749c2c02f0b57597614ddd702fb79ba2e0b84e430ad68","nonce":"652a2286ff3a04e515823536","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"96a2d01a7333f018663e3ded232604a59639cf0402088f4baa1f3764056fa97a8ff65e9131ae2422ef6bcac7df","nonce":"652a2286ff3a04e515823537","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"e19f3d9b12e0debb32856cec3a3638f5a2f617d015f0fd796c005489b768c554587af0d5a0262528f650463055","nonce":"652a2286ff3a04e515823530","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"d8b8799f0d7635993cdae52fb288b9af9e985c816350a294698ceee91c25b76cb0fbad6c2e1ebd65e08c18ba6b","nonce":"652a2286ff3a04e515823531","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"09e6efe58cb96053a255a0a6463e43165d75ae1873fee82febffe8cbe6656dc842ad995c624e36b963fd2f6271","nonce":"652a2286ff3a04e515823532","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"9c456253fd8d439ea40e29a8fe4e143241cddf5305c2b60533d08592c4980c338293c40879ae81476e1bbea180","nonce":"652a2286ff3a04e515823533","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"db0327cdbbf6a16ff62cc072b7fed1ccd4d4e28514f3dd9a803903608f6768c328648674c9af8d373d8bf85bfe","nonce":"652a2286ff3a04e51582352c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"877af5a635e3f1a1d61a9c2364d3fedc43648784e7e446e275f273e37dd56bc83f2140e32ef86ecbd06e23d359","nonce":"652a2286ff3a04e51582352d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"d7fb6374b4d56bc7adb3106c7eb205c2a95b9afc79176928bde7549b5c41e82422e5144516523d7381d395203f","nonce":"652a2286ff3a04e51582352e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"8195b7e62cb74e7fef62f0b7baa22891d2d7b2a7f2b685eb5cdf14c15aec5a585cef92252e83ecc152a0eabcdc","nonce":"652a2286ff3a04e51582352f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"a4844cb8db77b6517d59001cb536856c4fc571eeb030656a1268c201085448234205c123adb5d87d3bfd13fd9e","nonce":"652a2286ff3a04e515823528","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"2ec032d051852d0d04e952cbfc835a733db5c371e65390ff9033480eb9501d816585d12ab1f8071f56072539ce","nonce":"652a2286ff3a04e515823529","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"9f19410ae20116e7ea97e1aec3e3d84f249303ef87d5e1fb1c98ac7f81d4ba1a9c5811027ba68526cb551ba469","nonce":"652a2286ff3a04e51582352a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"6857a9f4a2eb49c3e48c97a3a8df9b2f0fbcde83bd3ee044f791fde68185c1cb52123ba1d2d755d470f2cd6b9e","nonce":"652a2286ff3a04e51582352b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"509251f7e2b9a8382571126200ac31e604c04360f434d77973b0fb130f9b455d2ba21ae57a0706ba94e4040c96","nonce":"652a2286ff3a04e515823524","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"b58d57def2cf35efbb2fae22bfda86471bd5a317571ed6b1530af718abb0724995e65fa45b08536d9d8dabdcb2","nonce":"652a2286ff3a04e515823525","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"6ec4a7818ebf9009b26a6136438b9a0c34351e79c2d9c149debac4645ddcd78a64172711ee5482f2aceed477b8","nonce":"652a2286ff3a04e515823526","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"a61a1c9847f5c16ddfea27f9512e84889bc3a9105b3e565d17a03167de76867eb92fa9d664a3be1f2fae16e397","nonce":"652a2286ff3a04e515823527","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"2374aad1eae4915f04d7df894d575d2745916d5496d55ed914f3389322b0447394af7e5bea86c454b8540b7760","nonce":"652a2286ff3a04e515823520","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"49f4ba77fa2b9ceb9321c878c7760a37efec08bf3ce1db599b1df38a6093468bd0a4c8b0f81024eb8c43b5ff40","nonce":"652a2286ff3a04e515823521","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"df6f5067dcead2069fa0541eb714a50fe269da3f1f4f69684cf02f7e645f917f71d906c48fc0317346c613614b","nonce":"652a2286ff3a04e515823522","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"b578c93e40e7b2415726daf69b865dd44f3644ba426e53ce2bf06df9dffe1891bbacd688627313667582ad3adb","nonce":"652a2286ff3a04e515823523","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"180e08e20d413c07c5aa4ac9c26a20221a5530f9af31472966d89f137de5ad804e77523cfb2db2f41693eec18b","nonce":"652a2286ff3a04e51582351c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"152ea4eefc2d116107542629204b3f16ad2fc55c4121b084855d284098f3bd2a0246fed58eabeea3529c656612","nonce":"652a2286ff3a04e51582351d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"cb7aab6fa74bb87cb671eb5a43e4c7638c7973e00cdfa7af515fe135ee31b08436d30969d06ba934d7db4aa01b","nonce":"652a2286ff3a04e51582351e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"c4f901531f65a92a898096d0746442374f7c683963bd946d7c754a609991cfc7841e1a5d589229bc227812df35","nonce":"652a2286ff3a04e51582351f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"3461ad7e4d882db9066ebce17f941c70176a849835548ba61edec1aede6e8f3eb71a92bcf686e65623ff0b95f7","nonce":"652a2286ff3a04e515823518","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"7209240ee181f2ce699529a897f9e2061a10feb519f70b3c7c7adb7e3ab1ec919e32d0c1f9cb0b106600e365b0","nonce":"652a2286ff3a04e515823519","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"add3eabe7e72102900e18af3629e3d0d2431ef542ef0a293431e77d35112832054ac114309d2893ac34fb0a941","nonce":"652a2286ff3a04e51582351a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"ca781c61a2929273cc321a82cf074c9a4ae6f62c14c4f75980b4d35f7ee4bd8bc43553f4dc52cd185fe9457813","nonce":"652a2286ff3a04e51582351b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"58b703b1530f2e9e71031b717b853e715840f1b9f2c155c5615b001c3c4f65b77bff0eed4c64cbdb7273468498","nonce":"652a2286ff3a04e515823514","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"db26260a31f8e059e74572a7233f4a1b34cab30198d77e60497c384742b7fa43efb724bc7977b4d40107e5ae99","nonce":"652a2286ff3a04e515823515","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"764febc7045bd5305d41022eb2e1553769381a4c13969ce91cd271fb5489bd9c027bb5e6d262c5196f04ec587c","nonce":"652a2286ff3a04e515823516","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"8e4ac0730d5ed415e57df9fe81cb37cb8ea84d871b0f2f7d44ecf82f6db06f72072be86a965505f0732b4ef210","nonce":"652a2286ff3a04e515823517","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"009455cefb28424be4da2dc94243802298592a2e55e15082b931b51cbddc0f265d7da29b5c2fded180821b0c29","nonce":"652a2286ff3a04e515823510","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"1034e931390b97d02d0dbb03c946b59119096747050b3769e06ebebfc06af9efdce049f5cd3a281708502749b5","nonce":"652a2286ff3a04e515823511","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"06e9817f187b0ffa81f8d41766bff695073ca7738fac36f51bae9365785f8289ae90ad2ab41a84540ecee1c680","nonce":"652a2286ff3a04e515823512","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"cd174f88050c9dd0e1c4bc3ddfe0f16597ccb8be6892beffac731ce0f31641f117f52b51f53c776cc6e4b1a541","nonce":"652a2286ff3a04e515823513","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"ef470b58446823f1b546ebbbc65c05d3ac51bef437a36b5353aa4668d327217de891ff4d83c0b12a00344f473b","nonce":"652a2286ff3a04e51582350c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"d7c36e2bd2f62a5e8715360f9ada9ec06969635e8b3ef5f0c6a4065f6b78ac7437b6fa11a8566f7d9e045e1326","nonce":"652a2286ff3a04e51582350d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"78f2d8942c9ee4261d62c96dbdbee2e7dd32a3649c9256312b823fa860c2e2547a3eb353620b6a253c67cf5f61","nonce":"652a2286ff3a04e51582350e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"711eebb295c02902dbd29982b5bc38ac65b8f38ffee9a2a74fc6f72fc1a0f90072ca6c9941506bdeefaca679b7","nonce":"652a2286ff3a04e51582350f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"feb493c24a5e27fd098f819dc4b440144054974c47b460d79225119360e6dd126ec1160ecbf05ed0f36218ad67","nonce":"652a2286ff3a04e515823508","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"5a0e8368d82c2a0ab913b8e58c97a30079181436498bbb5031e89370a271ec71e0a709785151848fbbd681c273","nonce":"652a2286ff3a04e515823509","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"239736f7a59760a720291bad88c4d204662ad55a7b40d45eda977bfa84d986ba33be23cf3d9ca2e1ff424da282","nonce":"652a2286ff3a04e51582350a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"54ae78fbe37c02874191118fd140172ce3c6d4a2c3f8bcbbf263048b7a41aa588e4ecbe833ab4c7680b57d5542","nonce":"652a2286ff3a04e51582350b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"f9776e2a02566e4bb525b512685f20f6cab5512f067076bea8b30fca452936e90e1274270744abce1b1b3e7fc9","nonce":"652a2286ff3a04e515823504","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"50a04167127fb981adeb785ff70357cf7c6ff78089e74fb00badf9e04bd100422c90c10ff6c5b3027cc079ffc5","nonce":"652a2286ff3a04e515823505","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"bb3c93fb9ddbaf1449c63a3c789b0ce6f8c08b951aded3b302f398136d8039d89aa055f8a9733af42238b9744d","nonce":"652a2286ff3a04e515823506","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"a66fb2a494590a9b01905f84c946e8385110f01986d2842eac48cd7e24e1cb23f898cb2d5676e1988ee00b990f","nonce":"652a2286ff3a04e515823507","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"f41e2a6b188acbda9829e31a5f340d06cac29d09d049b63aa13e9f53d3e52fe09635fcd76defe1bc0a7ab74217","nonce":"652a2286ff3a04e515823500","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"236f115d65492bfbe28fc749e2fbf2aef3ccac7afd18ffa71a3b1da02f3d5503b5560d2668cb904952813bbaf9","nonce":"652a2286ff3a04e515823501","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"75b37f1b1ce3ed02ee909701c7f7b79a35247c7bcf8c53e2f91cc97eea83aee2ff8af55d388e6ec8e5ac8fb917","nonce":"652a2286ff3a04e515823502","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"ba7bbb57ca5886e9a2d1a4b9c91b901e30b1f38ca7e45d6286e8358d7b792e9254fc11b36cd177749e5c0409a8","nonce":"652a2286ff3a04e515823503","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"8323e6bdde49d56539b3361a7da51826c39ab5f26238f514f8a2bc17b97a61d27292cdb6b1f9582554e77e0b88","nonce":"652a2286ff3a04e5158235fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"e651dc65d0ed40f3a6759a598144b11f5a2a2687f396933cb982f1d43973620f349ed77a83c456d46631ceb805","nonce":"652a2286ff3a04e5158235fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"d34ac9e82fe9d9ab1ef1a2dbd486bcb1f952cc7a31135e7582b6f14c1da7dff6a300a2166fd11981726768b875","nonce":"652a2286ff3a04e5158235fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"87efae3af22e3332a66ee9b8a9edf6b0f6db7036ac0ec98ebd45ee9db7a004855c0cb726ce69ec0028528beaaa","nonce":"652a2286ff3a04e5158235ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"3d89508c57eb7bb9c4c5518622612f297b45807ff98c5c95da4525c4ecf107a125672276c4977aaa8052966301","nonce":"652a2286ff3a04e5158235f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"199900d92722a5e05147955e0a3bd438c099e7cc48d0057e6289ac320ad5cb1d18e7a6de0b3516b4aea7ddec7d","nonce":"652a2286ff3a04e5158235f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"3e05defbd54599cd22b47eda20bed5c57a4dd1e4ebe357ab7f24e003cf1e5c309b769ea250f0c62a58507a2e82","nonce":"652a2286ff3a04e5158235fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"c77a13f60bcbe9362ecdbef58ac479c299506e1624e8cd336e0265fe4f093c34f6c23ac41b1e2a47defbf14f12","nonce":"652a2286ff3a04e5158235fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"8230b30fb420ddc41cdd542e9e6ae42dcc40552efd1f52e17f79404f5992ec52c0995c0ed4f68ef0b57c955fd8","nonce":"652a2286ff3a04e5158235f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"b46910c2e56ad8e92e51fa4990cffddda373931cc87e4ed49223f7c31d4d5963298028ae5cd706af4d4bbdd67c","nonce":"652a2286ff3a04e5158235f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"108a77ddd7cbe716f8608671a300abe75df6cd448c077c8e365e46d79fafb3ae2cc75e77db5188195e0e771f09","nonce":"652a2286ff3a04e5158235f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"c6eb574902c2ef4653d723ce9873eae3e40b321b9e53568da8967099e57ec9104cb2278d4e32cd3f188b3d8265","nonce":"652a2286ff3a04e5158235f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"7e1a70eecf874372cd6100a4306fe578c8386cad2bdfc61678a89fe07d59397707d7da321f40c3cc187d60968d","nonce":"652a2286ff3a04e5158235f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"265eab86ebfecfaba6e7840e2ff49eaa2008c377f9c6423f5d44c11e36dadbe4ee20dde2c3a534d09fec3417f2","nonce":"652a2286ff3a04e5158235f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"37db55a102dbfd744f848927de46c50a56052c0317a4c34934b7be89b0f8f3494f7d0dd42a3f629fc48d2cccda","nonce":"652a2286ff3a04e5158235f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"233a67894bbcdbf8514358cfd65fca1e2a9db2d98971cd19d5628bf0aa91d86d03c82531a54ce361d59de04f27","nonce":"652a2286ff3a04e5158235f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"d7e14930c313df998c71421eee6cfb0ddea267b00c629437fb8b1079c68d651b7a672926032ecd58ab3efdf907","nonce":"652a2286ff3a04e5158235ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"5c58d3799d066384de78772d26341c8254a8630cebdd4a0a7079438fb4a908c8a39088979ba6f0e7dfa1dca8c8","nonce":"652a2286ff3a04e5158235ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"f9d61619bbe29638b5e3b8817f6bf2ff245398e444cf817096b4b2166def2c4f0b9047972a822dc2b150855b34","nonce":"652a2286ff3a04e5158235ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"3ee6f5cd118b140665fbd8b7d8c216f8634520bb6e45ce994833b3f45143af0a29077e9d2c9b362c5f21c57e59","nonce":"652a2286ff3a04e5158235ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"7220974d6440bce8b858c582dddf85784bd9fe6bc9390e1f86167d5d79102e26a79d75411de4a3c6122c7fe311","nonce":"652a2286ff3a04e5158235e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"0d281d92589085c427561b7e55e45d8b254406ff90b959cc03133750a957b807b1219c5362bf2ef6807de3251f","nonce":"652a2286ff3a04e5158235e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"1568333323ede505b1edb056825be4156860994ac21520fc2819d5d7effea03b2c48bc55db89b1252dc79f36e8","nonce":"652a2286ff3a04e5158235ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"cfc2cefae00bfc919ca3445f94a06fbdefd9c11b6874cff21fb5a277a875907b37f52311c0cae9d917eeb002a2","nonce":"652a2286ff3a04e5158235eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"57586838010dca44420914e3191f335b8196ba1ba50d7575338afffd8ea3271403bb7a69f21e7a532d4322f46b","nonce":"652a2286ff3a04e5158235e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"00cd63e77aa9d15739607d8c2a23b05096c94ac9e4122bf044245fca2258b536392582c20232302e922f111c8f","nonce":"652a2286ff3a04e5158235e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"e516fd9ccff15a014e1733c5b400d08d7c73e6a2a88fbe6791e4ec259a347a73e0182f1c14cab7844e215c70c3","nonce":"652a2286ff3a04e5158235e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"c6659c5eef878e4c3d033a130a61900f2829032370e2b714e27059aa75d4c347048e0fac897feffb73a88f2fcb","nonce":"652a2286ff3a04e5158235e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"05c22a6694ccd4f1b7fe134199e19528c0aba004caadf886f3d6fedae8c9e40ba6e6adbf2b7311eb3d688d5228","nonce":"652a2286ff3a04e5158235e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"4eecaa47020954f746a6fc587503e61a26493d8a043f7730cead6e9f0a0886927bd8f5f1973b74dc0484eca600","nonce":"652a2286ff3a04e5158235e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"e4e1c6ff03d3c2b8c79a0bec65ffa003a6f590b8e7d8f007d47f4dca60057249a336503a15e8486662c32cfe68","nonce":"652a2286ff3a04e5158235e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"33d3f64631171d163e2918cc96eb148e67095270e18c7da9e9f9a5bd43d3d3654090789a9773f8db9f5b525f7b","nonce":"652a2286ff3a04e5158235e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"20a310dfbd5ca7ddeef51f5c2489c4fd6bcfe9e16f622eb1b3be9a662016d74d6b7cf5eb97c5f2bbdc39f517cf","nonce":"652a2286ff3a04e5158235dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"46d22348f324a53d2347b43dfa022ed5cf2358736bb794475ac3c888908d41fa199ab8814ce4207a9120d14231","nonce":"652a2286ff3a04e5158235dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"6cbdf7d9779f3ac675aee953f8938b86aecb9c2a6bfe72444fd8372e6d882cf65ce85a496d7f11d01f7796aa7d","nonce":"652a2286ff3a04e5158235de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"c71b6e429db06098fa4f8ec604f0f0f7da5c467a38a7590744f6e9d8ffbe29fa77de5d3e7654ad478269196282","nonce":"652a2286ff3a04e5158235df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"6e421e34ebea77475c5bb4e5168bdeaeb803ea4662a23f389d3cc9fdea643366b5f77bf135accd0c05a2e1c1ee","nonce":"652a2286ff3a04e5158235d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"564702cd6bdefc7aec4c670a11ac023c238cbe67f291d5ea52f20b684e22738b8d6a7fe1217d2a10ad6c6ef2ea","nonce":"652a2286ff3a04e5158235d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"6da2e3eddf0715e50fd01e949703170d58e0483a1aa838c84c0ebc88edcf93520404f3a90020826f1bcad7cdf6","nonce":"652a2286ff3a04e5158235da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"c8b936227a718e3ced5df5189ef6505dbfaa7c9b4a1a91fae2e9e69a9905bf02c6cd43326164d8f7178607fbfc","nonce":"652a2286ff3a04e5158235db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"48c004f45cb16565221a03e9e6e30c32aa35eb49193526b860392e8a967c18f64ca4ecdb3738ca22840f7f1aad","nonce":"652a2286ff3a04e5158235d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"ab259a5f0a3b34abda52abf61021f97c333fa33bedb58b9cbd65837df4277f73005ae785164a0ef314644de315","nonce":"652a2286ff3a04e5158235d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"53602743ac9888262d5fc830ad76c6e4f7129ad9ee46676ab4bfa33bdba68982f6b9ec6097dec00a3837d13339","nonce":"652a2286ff3a04e5158235d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"4fea6e9eb03973608c8ce28228b9e7e76a6443ac6fe1838bd48f0c059711699c1128f0eaea30228d433a5a3d1c","nonce":"652a2286ff3a04e5158235d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"3fbc71a7f5fbfbb90e22949f6d37524399cab428bb43186dab7d15c218657fb74357220d821bfdc014eff1c9d7","nonce":"652a2286ff3a04e5158235d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"ce10edbf2bcc9d464dd163a655b10e0e34202ac54b15fe6a3de3febb03ae3adf9771ccd9316d524bc4c7723dab","nonce":"652a2286ff3a04e5158235d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"0d8fa33b58655460fb17b1f6e6e36101808b4186b058bb80f98f3df5fbd4aeca7987c2ec9448e7aebc71e87460","nonce":"652a2286ff3a04e5158235d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"c371bbd994e44112740f9214b3c527d7e422ff00dac4e94cb126e5547eb7e303268d5887015922ed9121017946","nonce":"652a2286ff3a04e5158235d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"b3cad7e4c28b24c2df387884d05e0bea601e7dcb6c05f6809b99bf28d1ece31a7f62f65d09493590d17d02f778","nonce":"652a2286ff3a04e5158235cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"ed8745c92e7fc067e4bd603cab9ad763694aa6700394012995d37004f29064835f527158f6d93b341594ae393a","nonce":"652a2286ff3a04e5158235cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"0aaab5bda8f615602ae369853ed61a9f698acf4c4399b6270b4038833c257ba3d65e12e2d35e11b0e762842d4a","nonce":"652a2286ff3a04e5158235ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"a11b345772171fa3dd503038723b024f0cd2fba2f5ca92ef703d68751f16947cff96a68222dbdd38d49efa9b34","nonce":"652a2286ff3a04e5158235cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"b562dc2ee4e1cbf80afebf802916b3e141f4918b8b5ca89f4917e9fe798509c6e99cf28cde0be14880d6d9a6f3","nonce":"652a2286ff3a04e5158235c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"ed4540da7edca1c146a16804da1522d66fa82971f04045664a7275280220ffad42d0b61555f84de9459ed4ee87","nonce":"652a2286ff3a04e5158235c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"4fcde4ca692df6f4238d6fa086fa54ff15378a7168ef525c478156202e2d125adb20f88d796ce23badc04dc9ed","nonce":"652a2286ff3a04e5158235ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"ac58fa86baff9895cce7aab4ec189b8ff043bc44d5b410fae73fb77c887d59979748132e86606d7a1cd25e461d","nonce":"652a2286ff3a04e5158235cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"df88873246c65090e4d315ee991efd62191753c1af95200da6397fba5b36cb8bba70e9aca0cce37b93be71b329","nonce":"652a2286ff3a04e5158235c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"d3175c5b4ed3592caa6564b5643eae73c32b814a77b0f5915aba50d6566ee635056503efa4e213c26b7c757650","nonce":"652a2286ff3a04e5158235c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"4129b15e08531a754c394b827259c282c212f2f6b1840911c984edc343586b93fe9da35788afceff88cdaa1ab9","nonce":"652a2286ff3a04e5158235c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"a2e25f062c9a368314a2a0bd1ec343b4bc0d37d50befa41a1c41bc49116c12aebc6dd36985df4d94f90706eb9a","nonce":"652a2286ff3a04e5158235c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"2e9aa3e6deaa71888e36740b2a9efd24c813c62bdd231335443261f60a5e1fab9f293876964ea304183cacebe2","nonce":"652a2286ff3a04e5158235c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"fad5b77f498049cf5bf853c66179639eda3406af282a907a5b1487402704e58cd198ce4bc619e0ec113b9b0af2","nonce":"652a2286ff3a04e5158235c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"a9f586d9fca221e39ef73b1fff97f3def860907813c61ed5b948ad8ed1b1a30a041b538fd95b427812f6d59fa2","nonce":"652a2286ff3a04e5158235c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"595676ce78d1179eb608e45022260aeceeccdcedaa5695b977c23f3895e33cd32b481139262015ea309eea72fe","nonce":"652a2286ff3a04e5158235c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"aebcb4952cf12305362399f2842b1d250da65156bc2f6db541de78dd4b3c43771ad7d0bcb4de90d7127c469ec2","nonce":"652a2286ff3a04e5158235bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"0e633ee911bc18a356ca6f8bd4162b17394a8ca6942dc4b4463d131c6af40df4f981cc319cc6c7e3fb0812cc1f","nonce":"652a2286ff3a04e5158235bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"f5d00f7079c2a941443846f37201c261e92f0aa1c3caf7e6959ee419e7bbb89ccc7a9ead1bc8656b2a45e87256","nonce":"652a2286ff3a04e5158235be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"c851fc506db16e8695033a1b8564f6167a2faa430b5052cc618f173a8b0c97f3be3d957fc6c7d254488f60b0b4","nonce":"652a2286ff3a04e5158235bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"0d18b73e6faf98052e3bc38a68d482405843c97fd1bb68ef5fd385bc8fc2dd64ee10cdf7238360d7f41e44b7d5","nonce":"652a2286ff3a04e5158235b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"f6acbace4540f149147f309a7e110451c4bd2249863832924ee535c5495677626db577b2ccc3cea4f6e638addc","nonce":"652a2286ff3a04e5158235b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"c25ab1296819db2644a7cb95ab4b4b2953251349484a033490601e0aa7b79322943a5d61b9dc1b43a54c3d8e75","nonce":"652a2286ff3a04e5158235ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"3f2cccf3114130059559875339947c8d686c9b50841b42eaddf6b2381d0167ec2e5e18f7a23cbf7eb22069e8f1","nonce":"652a2286ff3a04e5158235bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"0d64cd06273d246ce492ae5c8eebfcb6a59f8c9e2b6023258cdd5ec4ce4f6c9992a3830fdc882fe69c735f535d","nonce":"652a2286ff3a04e5158235b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"f509ef647c6e7d57b2cd5291b42114e47ea329b9f855177920898f628a7749943a6565ed547b603ead8ea4b28f","nonce":"652a2286ff3a04e5158235b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"3b295145730cd886ab507f07b98a541decd5a2b25f686c1d93115976426529f22ac2fa00d7c7d9e0f98d5b23eb","nonce":"652a2286ff3a04e5158235b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"f86481d06d6343906df1257ee6257cf51a66a443225dc4d99bf3f29cdca3b1bb321fd0b9270ce6f9d64234c5ab","nonce":"652a2286ff3a04e5158235b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"790ccdc55ab27766ecb6367e7f4681864c6ae492bf0df12bd97a3fd26d6384e258988d768619bc4f79a069885d","nonce":"652a2286ff3a04e5158235b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"9375aad75887ee7cfd8d3c7ec6fb926aef10ae2ccf22a90ef08c3f367c93aa0d1e4d854d57d96de8fa3bd3992d","nonce":"652a2286ff3a04e5158235b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"987e9f171899e56acdf90c8dee941c14d9cf0fd43308cfa77c80c2854385ae20730e75beb8e20bc35b5a0b25ee","nonce":"652a2286ff3a04e5158235b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"db00eadcc99ff1c78eb3d4c8033da2d17e1f2802f47ca9d7236acc2265811e916e8023a3180fb820991e71dde3","nonce":"652a2286ff3a04e5158235b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"0c9c955b626ca30557301438fc990278542b63f7e124069a10a73b122bf41a95b2240d21153b820a95fa477c76","nonce":"652a2286ff3a04e5158235ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"a0f3f14b2b87b7fe945b618671f6c77fb160086c0170f8f98d87abe307358c1b1c434b84a76244fef7307871d3","nonce":"652a2286ff3a04e5158235ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"f8bd118b6c9ac7d3f8401d77b83ef5477bb789356b6a50fcda661c68abb1946258359e4b269b88fedd7307831c","nonce":"652a2286ff3a04e5158235ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"d2e5d4c48e548ac9992ea52b6b0092d7df5b7f252bbd62b0c42ce905c9a7cd22fde341fc5ef370ca63d669da5c","nonce":"652a2286ff3a04e5158235af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"ae1a688d910cf3e97a42a693cb24c54195f7bb0092b3c20a6cb581eff7d496ad7a79138f3bb6fba7869fe40010","nonce":"652a2286ff3a04e5158235a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"f8f24dc652416904ae01512e50f24037bff21ca8cdb3f122e28b09b69d36d08c140b89bd07f8418d6e6fe8efef","nonce":"652a2286ff3a04e5158235a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"e5d477f48732903539e78189173bdfe8b03fb27e9d321cf82357b75a38c438c7afb6a4e40290b70b3e3aa5ff33","nonce":"652a2286ff3a04e5158235aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"92c85903c8180943b48af5a6458f5d72fbdefad6ac3fe0d639d7221243e1186621c4ef7131a618f38483785314","nonce":"652a2286ff3a04e5158235ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"0704d20e3ddc6c62e56cd1b80abd585f3ba1d6c3ed99c8f83aa64f4eb7a08bcdab7256a7825ad93bcb1e041e4b","nonce":"652a2286ff3a04e5158235a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"bb85ce9e4f199f88bfc05dd685c021a90372345c8b7b6b17b6d63ed992ba7172185af4c05fc1f9896b852202d9","nonce":"652a2286ff3a04e5158235a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"b56b9ac815ad4f72d38ad5b3563eb16357f79012c9610e7a286b9e14b561d841899a0303d694c839ce67d6e02e","nonce":"652a2286ff3a04e5158235a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"f3282b6d900ef3aa444ed2950764f092e23993f4cae30245c7d4ae9276624a15656af900c4f2b6aef6b9d28667","nonce":"652a2286ff3a04e5158235a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"f888c656b81bcc0548f847228dfcf5956948011dee04be03000ee63cf1a551c5c3ca397069ad2e00397e4c0833","nonce":"652a2286ff3a04e5158235a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"9827edff59e979db083721062d63779389a4d573f9ee751a997e0b445c4d16c4932b2811102356e4fd1d45afaa","nonce":"652a2286ff3a04e5158235a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"03ee95ac78664d5b3507040a7aecd89ce97b0ad7ea4f3bc251619e089123c54a1468c551144fe3036ba44ee507","nonce":"652a2286ff3a04e5158235a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"36566f5f5e4e46f1b3b3bc1da5bf71fb94496fd7772258c76d6af878d152c4c4cf5aada1c189c8b5759b52bec5","nonce":"652a2286ff3a04e5158235a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"f6c7c52b80aa685c7c1fea1deb32d252c3c746be7c5b60d8069d6292ba0022d57928308c70780b26b0c309862c","nonce":"652a2286ff3a04e51582359c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"af2824016146adb8f8d85c61258e0672f239e0fff76e8ee68cd229ed19d0c0be021c2931b045aa7a8d1da91129","nonce":"652a2286ff3a04e51582359d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"7ba3bb3437106c79184e5cd3f89d4c0bd4c57225883b625876173c64b46484047df54e0e385c9406328e7b25da","nonce":"652a2286ff3a04e51582359e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"fdeb7352efe5f73caca0c6aaf7d1c4ff567144956184c2daf48ab10739a05d1c4f8a6dea03c9d6c96945a1d61e","nonce":"652a2286ff3a04e51582359f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"4ad4d19d781da974ec3fb5e3e445ed881308ea445cb5f8eef963577b79d617cbda3a50deb0f9abc284249e63f2","nonce":"652a2286ff3a04e515823598","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"b66237b909c9fb815959bc2e671a4a6a5338a7324e5dacb6bb7a7d21e91f47835c4df93b308663ec8396e97c77","nonce":"652a2286ff3a04e515823599","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"4df319a8739644a87a341787d932b01d73dfcac547c3a5b41b65819263ad621fda05cd6ebce0bb9ea14e719bb0","nonce":"652a2286ff3a04e51582359a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"fd0794d5f5c91910813fae7a3c9a360e815453e45c346aafb91d1a8578db3e69a266f9cb6bdac44db3195063e7","nonce":"652a2286ff3a04e51582359b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"4cef00caf4e343152a57445f93b85e6013e2fbdd54fa6f95d40ad975f57dee171249dd74ead53f943b8983fb8c","nonce":"652a2286ff3a04e515823594","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"a6b567bcad8deffb8ce725149b0bf1cf3cd184406017b4335bee3aac44de90bcee39a519fb2d82ef54d7687cd8","nonce":"652a2286ff3a04e515823595","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"3b86b6dcdf3b34fb6e2da5f70bafd328ea073c34a65564e9e48bbd3af3f4648bed40c341e1c6aa156034b9874b","nonce":"652a2286ff3a04e515823596","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"01eb1720f72bd6cd442fe87e84766bf272021288df98b20e2ea204a30248ab5c99626ca6d2abbe3ddb313fd0f4","nonce":"652a2286ff3a04e515823597","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"201250dfb2d6c6a2d47677e94b5d9b5497fdf4bbfdb149a72f800d075d40e5d178e3a1d888209f06f726e035a6","nonce":"652a2286ff3a04e515823590","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"badaf69be94202cba8491d907f8e35cde5bf2fb1f32aeda0692dc79f0ce6a2c19863d838cc0538449067bd32da","nonce":"652a2286ff3a04e515823591","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"5320a635895480dc6ff0c9eada8b9aff86707af0685b09da0123cb2e9b9da24f179811fa85dc0a2bb93aafc3a0","nonce":"652a2286ff3a04e515823592","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"a0d8c34f3f6064d6e102f196a5daedd2a7abcb86d3e74a5a2ac9410eb4f1c8922dd6c44993a2d3d67a29832c49","nonce":"652a2286ff3a04e515823593","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"c4a8f59ffb7d233741c2bb6492810d5fd40281965ae0d6e1972c6d30fc519763b54cb78f7eccd58815d3220b89","nonce":"652a2286ff3a04e51582358c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"77d637bd5d442d6c8be2ecc67d0fd59bc7f9880cb33a13e97519ac083087f4f9290d23358e8cac5450f1f62609","nonce":"652a2286ff3a04e51582358d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"cdeaf8e76658ccccc7510a2ff974615ead3b8f30cf1af124b2dff86a2f55ceb982397a74d09c80b0cd0eb54124","nonce":"652a2286ff3a04e51582358e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"0cc33e5ebb5b1f5556e2cf8d7dfc868430e15c566e67e9f253424586981c7784e6b315592a1dced5d9df485e29","nonce":"652a2286ff3a04e51582358f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"c87eed26a8130a67857b333eed5fac1833bff4c9892f9fed4be49487c6c566116065a1e96d67d5e896f5bf6cb2","nonce":"652a2286ff3a04e515823588","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"4888a5f1953e5bfa99bf5b066697d70e0a1b96198c1675ff847403048e6d379d2a8ea67866afae24b21f0c6318","nonce":"652a2286ff3a04e515823589","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"0668e1ec2505363d1b2305add29bf57560b3a274e70af814e9935b26e45dfd0cbf676fb1e866a3d72e076f9069","nonce":"652a2286ff3a04e51582358a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"1d28f4bb3678bec8c249c040a69359b2cf383463d13f2e70d8f328d8be219862f365aa9a315c58273c299453cd","nonce":"652a2286ff3a04e51582358b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"f389f9ccf3320a3cd395440dc22c10b6ca4ec3780df2e4f91a9edc883d3aadeb8c4c6cea3e04d87831ba729505","nonce":"652a2286ff3a04e515823584","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"8ce9387092eff75328017a6c08786ac2fb49f82858b51dff9d9789efd1c8abea4cda7fa6f0f26778cc23334698","nonce":"652a2286ff3a04e515823585","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"94f40c4185965da06958a464205972ca4582a77d596c561d4fba3f5d4c6589824f7a65de2ad0560df2f00043bf","nonce":"652a2286ff3a04e515823586","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"c06ef7fc3a4f84ea1f786e6fce56aa10d0aca056a36b96fc64aed08135f5dc384e97e65ea8fb47b1b5654809d9","nonce":"652a2286ff3a04e515823587","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"61c95c76cedceaebc5fe67863710e25cedf4862f0da8dc38ba03175760f69b45be8c8d3954a2b57147f74a97c9","nonce":"652a2286ff3a04e515823580","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"d8eb9e948d9a4885a64cf5d369fb679fc2b22f01e2afe8b26fca89d7e0f0cecccbda475bd43c55d746eab6a0d3","nonce":"652a2286ff3a04e515823581","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"9e188e9af6910760c82075fbab678c4bfd5fe107c65ba0f2e149140989d00692947e000f1cf5863491d77e836a","nonce":"652a2286ff3a04e515823582","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"aac54aebf6fee67b3097aadfa56cf6c6da2ba992aa18ca92a059f9b0f8e04ad056b5a559a1d8590ac25f76d6c9","nonce":"652a2286ff3a04e515823583","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"66f2b806a935de0dfb2bb27bd674c08a34a0900d809312075ac7710007743788ae45015ad119ea1db1dcb6dc5e","nonce":"652a2286ff3a04e51582347c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"40dc895a6133b5a837523536e6e34a4cafc43c03fb36d96f000119ea3ce1d0e8"},{"exporter_context":"00","L":32,"exported_value":"a04a439d8ce67363add99f436d7e49dcbeb35205aa2d15ec000097db9803cbb1"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"8b24465ff4b9d52e782c5528eb3fe8d5b937f0579d82db8632b01e359ddc6f99"}]},{"mode":3,"kem_id":32,"kdf_id":1,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"3007789cee6b2990f5d0defa25add261c13b57dc9d4658f7114d712a113f9ee1","ikmS":"534e49da9d563c52d61cb70bbda68264b1ec93c2419eff04a84c7070e49e2b7e","ikmE":"6fd443728b4f805621e0245d19e0bc81d7adbbcd37dadd208181449e96254011","skRm":"f76c38c7f239eb4d1ccd2b42bdf50115d9f376741618bb96a0401597de7887b9","skSm":"bc8114c67eccf37d0f8bb1f80cbb20fa2b5ef050a410eaeef9d0a753dc457bc1","skEm":"3a401928386496b9726c985e8a78dab44882e4757f58cde2098b8dea4319202e","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"277f13a5cbf5e2fb5ec373fc3bd51495900b1f87742b989fb89027abf6fbe870","pkSm":"bafa54764bb96b07831709e4c72d808858ee689dc61ecb31c25994b8433a836e","pkEm":"51f89d11e0d612525b8431c32a4b537a5030cb541d455e76fe38338c2e069368","enc":"51f89d11e0d612525b8431c32a4b537a5030cb541d455e76fe38338c2e069368","shared_secret":"6aff4435bcc9b19a3fb5ae9671f1a9dd8f3d723bf9ec546a4dde49b5ea176d1d","key_schedule_context":"03a35894e1dbdc20fa21488d654d8f53f5aff5052690a045752fc170019f0d314e06f6ef962c9ee7cea40407b5d60f0f26990472faae3ac44c78366f1cac1ecde1","secret":"78eed9042ca839e6f386a7b5b8cffaedc86256347c302f2c4d511ed4c13ce518","key":"6d4ac60d03ea3916f37812db2fba926444d47a4143025ec8b79f5571be2b91b0","base_nonce":"111eba065e5ad8107a1754b8","exporter_secret":"afb763da316324c488e268f330dbfbea5e98ebd1ed23ce4a553b8b032ef5c3b8","encryptions":[{"aad":"436f756e742d30","ciphertext":"41f8d206da234a258f4a6ad0d82fbbf84a0d119bb1de2317c69fb661389eb016cf0af7b5a80ee51762c0d58612","nonce":"111eba065e5ad8107a1754b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"f2a3a013cb766d56605e8136b86210863b540660f3ec2edcbc3414fa95df7d26762fa9a1d90299ae808421a2e5","nonce":"111eba065e5ad8107a1754b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"b83b0fca1c255ca2a414437e91d397c2c25fd424da5a5182703f5cf11c7d3f3142d3d9833698970feb37302410","nonce":"111eba065e5ad8107a1754ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"9761664f3dbec575368cd3688de3de271e5fc310487b7ab8b0a517261481684035622340a883d1cfdde3948f58","nonce":"111eba065e5ad8107a1754bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"80a166f5a391248e7ebc80d6023b71e2e93ff3555d1a0dc8994e649608db5dbc8fe5776949aeb423b819a845cb","nonce":"111eba065e5ad8107a1754bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"212246489895088170b2c14d7a75d42419ba917ef177781f0b6408184c98ccd2e5069142a79196a367404f7a64","nonce":"111eba065e5ad8107a1754bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"175555e8cf82dc9de4ea0f66855b0be096b055a78c46cc9577cf003028b46c0848e2e277db699903e8974f1348","nonce":"111eba065e5ad8107a1754be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"4a1a2f02749a27cb2bb4fa30d5e46dc301381426711110bbe28f703287750e2cf284a6aa5d01dc58251b5c81da","nonce":"111eba065e5ad8107a1754bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"808c565d861f0165ab977eaa60e4d6318b2db9aafaa20dde3263ad7f5a6f1370ee4c8c3752e851acdd108649a1","nonce":"111eba065e5ad8107a1754b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"9d5cd6934c0672c1badc51012a3e6757361856b32383f7c77078300b487a1f5cc792636a16794895710bcd31bf","nonce":"111eba065e5ad8107a1754b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"8fec181103fbcef3c4ab7f782c699214a3e2e50e7c281a4b4274dcbf5c8c2d497a7198088060775f7687e94667","nonce":"111eba065e5ad8107a1754b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"28990df45be6688dbe22ee747bb135300812502d8018daebb4f7ae3d9b37f626e9e0e4a4b01349a3250879edbd","nonce":"111eba065e5ad8107a1754b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"fed309bdde5498681810252b023b7a4c9a4f0d8024d245c4a75b10d8030635fbdeea94285a10b0dde306e8687c","nonce":"111eba065e5ad8107a1754b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"0403e4d1a1ad4116a8be7221e12a1926adcf9e6618b8aaf2d30db263a45a1094e8a415b10bc388ed7b8e4b37ff","nonce":"111eba065e5ad8107a1754b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"49bc42e8aee926e36b87a3557798fd77b25085d2927bfce842aa72bdcd9f96ac7c4d490ef1b71eef58f7b237e9","nonce":"111eba065e5ad8107a1754b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"04781bee71dbc66417dbb8c325fdcb848f8dc0a0bab38c88e03635d4f72750189cf227f3e1214e23830b750ac5","nonce":"111eba065e5ad8107a1754b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"7223692949082cc133d020226adc696b1996b123ffa0197564369383f3651a78f7252e40df1381e3463527841b","nonce":"111eba065e5ad8107a1754a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"e1435e30ed25969a2e2cc50e32a9aa7a42d0f64b369c82df374c50b76f657486b717a54bee2f9e84e0fbbb7caf","nonce":"111eba065e5ad8107a1754a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"3d48437a8ba18eb6765ac32fb0a9d8ff2c305b06e1ed73a59fe79a677d58c183d116e8a4638a701adc67f368ce","nonce":"111eba065e5ad8107a1754aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"2bb577b3ac00005c9a543dfa87fe5814fcdebf03352e3080396dc4bf3c8a9219406494188694715ca26fb65f9e","nonce":"111eba065e5ad8107a1754ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"d1d91bb241edf98fce8a7a38e61a994c2bc6685e85a48957583d773cad2391bd2da407c63fb93cfe1ae4d468ab","nonce":"111eba065e5ad8107a1754ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"d7cab41a75af3e6cc84515959e7eb2d370a99146bcbfc57c3c09047f3c840e06f2bbb02e5d08e3e7f7e9c19958","nonce":"111eba065e5ad8107a1754ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"b4b52866c712370cdfae984d36f78972ca72e2aff0e62c8cd415617141bc46beec3524463d14413e4833449c8e","nonce":"111eba065e5ad8107a1754ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"00935485e937e9acecbafb2717ccbc15df4528d54fd91ba182b7b73afd5695711ff2920cecc55f6a89da1a2152","nonce":"111eba065e5ad8107a1754af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"ab988d328900afed07679b555d09477d22eadf85ed59fd708bc4ae411dc9bbcd1990dba3f9e767f6da7a074b14","nonce":"111eba065e5ad8107a1754a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"bdfd8edccb3433b6bc034fbbbd6b8c3cf29eaa6f60e2b0ce2f27f0192c7f4b23485d9994d2b85b9ac642f9142f","nonce":"111eba065e5ad8107a1754a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"3612221f6b29727c03ac44988961253c47b6f8d3cd87eaf87d73849d366f3cebb31da07c2c934b322d0a4c89cc","nonce":"111eba065e5ad8107a1754a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"b6e2b2c1f626836849fcdde010c964d5b5c7f72f9c61167c9b3a6ee34cf1458a2be473c6bac1013f8887436d44","nonce":"111eba065e5ad8107a1754a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"aa47db63eafddc84c5989704c57c687381ccbb5a876ca66b90e2e15f50d01ed213d1cd359925b2e59a767261ac","nonce":"111eba065e5ad8107a1754a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"ad601a16f70b89d34ceaf1cd48803a5f939815b8583d9dea9389d1e9e8eaaf66d28def4bdd107b251f24195ceb","nonce":"111eba065e5ad8107a1754a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"6953f857f386e0067f94c0de92ec7279056dbccdd0bd802bd251a094276bcb89c62d48e393263be7c04947b94b","nonce":"111eba065e5ad8107a1754a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"54ce02c433d43b325b9818486911b41ee733dbb732eaa0fcdc419ba8db3553d17cf570e79fd7476df1be90a693","nonce":"111eba065e5ad8107a1754a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"e44428f74c25f37a6f86b311a0c7936acc444692def571872d3636faf63268da1ce255fd4a7f218faa20d8e92e","nonce":"111eba065e5ad8107a175498","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"9f479d687f932063ad76288788fc68158e895d997fadc71fd596c8d2960d4b3e2f1a05d37ca936845f581146d5","nonce":"111eba065e5ad8107a175499","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"d3d6b63a2e9e81b873e04876b49333cf0fbf8432e117e868b081c281edf4b7445cd9d716e5bb4109e06a23c48f","nonce":"111eba065e5ad8107a17549a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"2b647755329aedfebc27c88d0b3d5d2837c4802ba6a7633e4d7329cfaad1f6618fbc4496baca01401a07df710e","nonce":"111eba065e5ad8107a17549b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"68da1eaf8c73e73d400f0408f0bd6b958a9a07e021384399e3abc2ca8696afec3a18235a2ddfce5966ed684779","nonce":"111eba065e5ad8107a17549c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"10b9f534b40661cb38c2650af407aa6f2be01c7882748bfbc3aabf0c5cea4f5b1233173ff52c7017199f57145e","nonce":"111eba065e5ad8107a17549d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"e142538f510125f061c10cc7df8d9e4fbceee44172024f5b3a69398109a90603a1f047a50c35635a55d15a51ab","nonce":"111eba065e5ad8107a17549e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"3dc80dc5d31459edc919d1518656b69ffaf05f042f56b69ce757458e9d1bd9db6caef5e78be89583097b2dc6e3","nonce":"111eba065e5ad8107a17549f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"03eebf70f822538f4f19e62fb3f51dedee2bf753fcd20451604de9d6029f3985e1683d18597c6dce99a4a17f2d","nonce":"111eba065e5ad8107a175490","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"97f736ebae4fdf412d8301d27824bbf798bf505e4fec6b90038b64ca88c8c4e1eaa73cc90bc1e278e82e599fab","nonce":"111eba065e5ad8107a175491","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"88c3cd025791fa11623c8707edac5c73f14224217bf120518e771e292b7330b7422e17bf76f895e033325b53e7","nonce":"111eba065e5ad8107a175492","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"4f84c29fe50e5e427b9cb8114761ccb85e1faa2c17334f45ab0672634df388bdbeb4dace1dccfe83415dee4b5b","nonce":"111eba065e5ad8107a175493","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"a72e56875c9a355fc3838a329f333954cc3ae82ba5b8adb92490abb3f4ab80f8427c74d780070ec4d65a9eeee6","nonce":"111eba065e5ad8107a175494","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"af8bf5d8503e7ea57d8c5172ae13f7100cea76b321e92db09e9f1c82596c093347a92fd8a09e3701db6efd7daa","nonce":"111eba065e5ad8107a175495","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"437137bf990d5e8e28685e3fddeb2cd8145e6c9abea66576aa2eb5537bb4894fecb3672d68338d9c49facb5e5b","nonce":"111eba065e5ad8107a175496","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"5e20d2a17a5a7c1a24d01966499476a31f3a71a70774c104d50f20e9c804c63d9445214b847c660439843289b1","nonce":"111eba065e5ad8107a175497","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"98897700238cd458cdf8a45b090a4677b065803d46d2fc739614796fd6f6ca843415961b89bb7bcf57aa396404","nonce":"111eba065e5ad8107a175488","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"4a50da9d2d44fd3ebfed0e86742602ba3686455f8e4694d4d0ad35deffe38306de46982260a5b0c93b31dbf101","nonce":"111eba065e5ad8107a175489","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"180d1aed7f19030ed3c94c559636a74b578fa39ee8e8b3934e152a7039ccab8240e34a25a422b9832f7e16db3d","nonce":"111eba065e5ad8107a17548a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"9009417d5fa9b59c68785d45c391607290b9e5560be44ab4d76d7c3df81627b085a5c639a355f5c3d1e15bec28","nonce":"111eba065e5ad8107a17548b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"1baaec23c4a522218a4c02e71558e121e2d8edda92d1e01db3f3c2997e5c9a485fdc4be11a5aa21f5ee6ba2f63","nonce":"111eba065e5ad8107a17548c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"953ccf79971f512803e40c98e5010261191d92312d879607df4177043845a5b81df81e300df74f5ddd8b5be5cd","nonce":"111eba065e5ad8107a17548d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"b7d34c13581742bf39bf1265c94cc49e94e457f40f7ed9d5085962837d99eb1c79c623d4334356625a02e78cc2","nonce":"111eba065e5ad8107a17548e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"a99b42722980fb55b94ce2cec8017c866b7d5701df3f2ca9a424c0869e5b81d6126e1bcb9e6f705b855c12cbbd","nonce":"111eba065e5ad8107a17548f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"6f27c17d4743813eb9d88ef40e20ee35573a67044cf697e63f906da0584dbcde3cece2bab3bb11289aad98c9e2","nonce":"111eba065e5ad8107a175480","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"9c67c96096d3f5bcfaac84a16d30bc27e075f8391a8159f2ab411aa5c7056b02cd68384a099b2e4138aee18b3a","nonce":"111eba065e5ad8107a175481","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"50e844efe55e3522986bb6d77fb62d986ffa2e21b0805d59ed995f010e09f4e0e14561aa5e3ee3e695cdc38ae7","nonce":"111eba065e5ad8107a175482","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"039d3f797981c0cdfa2649f477f65a734f6f3bade8c6f7e794db6d843a2c8ce8da9c0b9c325d2f5d58197ee40f","nonce":"111eba065e5ad8107a175483","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"24ab04714be678bd95cfdd0d720299709953d341d998393b86ee443ab2970bd35f6c06c0ecafd7433d59333d3d","nonce":"111eba065e5ad8107a175484","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"9d160c294df912d0b3240b6c3fa8a71a49a1a879c60c78e4c1e0c41d943245bdda9af2b55f24485289c9b451a6","nonce":"111eba065e5ad8107a175485","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"480ab418f399d2a427a333441efc5e69834f5d15056408ff65c1f5531f2e8ae7a0057085315fa0622b5280bb4e","nonce":"111eba065e5ad8107a175486","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"e187d2b8ae439cda3790e446a524107ce21bf442784a7051ad4a23daeb664eef229fbe85896e4caad667f7de2b","nonce":"111eba065e5ad8107a175487","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"8a00350e7e0e1014b84fd295ba853952b67b7539c11b12a34167dfe63895d9729cff9460b24b927ecefd398275","nonce":"111eba065e5ad8107a1754f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"d663133a56c038c8b8514c883c8f15bc6f62fd73e30b10e0ac7cf2a9769ca1f894216e1bd378c58306565542fb","nonce":"111eba065e5ad8107a1754f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"8206fc0b043f09c4ccf23300c36f2ec9dc96db11994c29ac034b76593fa5066f1064511f7147b4688ac27db5ff","nonce":"111eba065e5ad8107a1754fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"acdb716b0c59e7fa695ea826f9c1e89b35b510b41634c4377e1c7bc150426a1d8f768479fe8697dbb3974e985d","nonce":"111eba065e5ad8107a1754fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"e0f53384c67d6a649c26d179980f60ff224d761544c6f41b625e6e739cdd439d7977e29e2cd4351da5b6205c3f","nonce":"111eba065e5ad8107a1754fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"6c5d4a28e751c045ad174b34ea67784f00df5ffd935176adca9643be4753f711eaf2b159d95f641d65c6fd5642","nonce":"111eba065e5ad8107a1754fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"06a852178337c407f448e492b622db58e0a031ab7f0286da7945fe02ea5f98e4f6a6eb3eb3290842d6b4173d9f","nonce":"111eba065e5ad8107a1754fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"c50cdcc65f515732ef1da6c6831ffc982426c4bb2b9cc825aa875ba6ad1211c2fb39487e8752a5cbade0f67db6","nonce":"111eba065e5ad8107a1754ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"477e9be7fcd9a97be061266d067424c1433aa133ee62682fb18d9365c523d5d09edec0b2b58ea983c72d34bcf4","nonce":"111eba065e5ad8107a1754f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"6c38ffe16ff825541717ba91afc93a0b81bea7cb23c0406dc1e5f663af96a4155fbf2a5ceddb7e02fb96f719ab","nonce":"111eba065e5ad8107a1754f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"8e3b1188e9d2b3e629e8a43bff3a5efe2ecb423eb8f6577c9384de3166e6da5aca882b062e7f9955fd1d20cfaf","nonce":"111eba065e5ad8107a1754f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"3743aab91a5567d852b710387fc7b9a0a1be5d317ce5f87b2d6fa8afecc11d83f608d1e4b892addf78ea7c412b","nonce":"111eba065e5ad8107a1754f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"5a075dc2fdbfec0c54a8e911c0f64694de4c8d3b5aa5c8ae4cf3bf03a56a3b39115a6ae5428d67e5da26e91971","nonce":"111eba065e5ad8107a1754f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"27f94b2d432c66519b51e3df81df7a8586435f5e0fbfa12c2a1387baadb984ec58c63ffcb7d7a0d73748cc4f47","nonce":"111eba065e5ad8107a1754f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"478804543a6aad5f2cb1f33d96bc1267c8e6a1c42e6763b6df7bacccef85cab737b08158339dfb4e521f408631","nonce":"111eba065e5ad8107a1754f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"54fe7d91e080b84d3ffa83780c119fce88cf48aa574dcf11cbba67743d4f64cfa28073004f5b73ab6a3f6ddd34","nonce":"111eba065e5ad8107a1754f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"9dad19aef9458dd1be88070773a8091b6ae6b4d94d66547da5443c77cc07ca2e59d68f0573a1af09511f65bff8","nonce":"111eba065e5ad8107a1754e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"e054775b641451129cca36aeb45088bc20999ef1e5da4a5f8fde454f628aaab096ddf778956075324d0fc7ca02","nonce":"111eba065e5ad8107a1754e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"31922cbb0fc842ded9a2c60d8552b035d086c85531cb9d29a85107a387b1210d3029b8e6426d9d356c7ca67fa0","nonce":"111eba065e5ad8107a1754ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"269b3db30187f88850b8d93d7a9a333b0f2c2e238a01cc2b0a85256307b1d53ca3ccd93b1aa9639ba3e6971b22","nonce":"111eba065e5ad8107a1754eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"d4d78ee512d4cb33cf9c1a751a184bb10757068e652db7ade854c58198f5b9816f6e8ec7ff19415f6dbcfcab40","nonce":"111eba065e5ad8107a1754ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"62eb504f1eba90045c7c4c0da3cd9a758ba264b16c033f18668e4645e8c8a4c713dbd27559fd8f24c2e5f65cf5","nonce":"111eba065e5ad8107a1754ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"642e5965ac08338cdb6e5604b6959065b9efdfba5f4bafd649e531c4617d6f590c095ceda50ca6bfde2a776bce","nonce":"111eba065e5ad8107a1754ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"cc8ec7cc7754fa894992e378f7d67f6dc5c829ac280f38bb9dd7daab1ae20cb862d3dab35ee518a222657357d5","nonce":"111eba065e5ad8107a1754ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"8a727b8173eca4ef78d2237c6bf2ab5bec2b6aeb06399039a90f9530528f815a04ed51b1801ccc27f07cc0d6ce","nonce":"111eba065e5ad8107a1754e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"a8d750ab5abf6f82a02e1ea8000b502e9c900a160540b65fd448c155da09392f00cff6f08e1db31b198a996ccf","nonce":"111eba065e5ad8107a1754e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"fdb6af2e31a2dff2a8fe77c664b7916d1d1cb1f9dbba429cabd99b32195b2b40745040e68e09646a9aff8ad83a","nonce":"111eba065e5ad8107a1754e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"6b760b5f008a15e7dfbb3b99a674535129b556b227f6661b0fd56df8aedaf131d9cf22931363abd0f886eecb78","nonce":"111eba065e5ad8107a1754e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"aacf189f86dcacd3b8d8a7d8bf7b039b174f87a3c21b6d1a8a6b25b420c08df24833256e028e4da42394c5c4a8","nonce":"111eba065e5ad8107a1754e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"86f96dde41a6f68d4aec4dd1118a310153e307c4415ac8a2f9c4037d0848d78aec0da96850814dbb33fe172094","nonce":"111eba065e5ad8107a1754e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"8a362dd361dc95c99ecda56578d1b8c3fb0e585eaa74c394ddbd657bbe28f1ce565f1e370817c7a1df0017982a","nonce":"111eba065e5ad8107a1754e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"bd13c582dea2343b7581eeebdccde54df0c3ce660392f0a39e1409ead5a6d65506631e653c9ecde8dd756e35cc","nonce":"111eba065e5ad8107a1754e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"cdad3501172c6e61ff80372829be6d5ea28bfd35318b77c423918941e66178f7eeaf09bd9c2e80e20875d11333","nonce":"111eba065e5ad8107a1754d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"5943be6d0612a285d6ba8411ccc4ab03c3d9b526aae922aef4f394a2e5b59c8c9f54cecf12bb2baccf340301cb","nonce":"111eba065e5ad8107a1754d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"3209ccb2d84338d01e574f374066f942a3ff12a5d12a944b96cf1590d38919c02698fc4c9d66117cc08e673ff1","nonce":"111eba065e5ad8107a1754da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"aef8244140c572ce0aef4ae1288456fe3b9b7711597d62173986d217bc8a3123156e68af050c1850059eceeb4a","nonce":"111eba065e5ad8107a1754db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"1469be67729e813b8e6f0751986122eaab322d1c1acec8546250b3a579bd350dc52ec64e8d4e8176bd8a4089d2","nonce":"111eba065e5ad8107a1754dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"a0e543afe3175e28451661ba734b49f2c83b293971eead606d0371d0b11aa96a16c49e1170ddb336bf6c212839","nonce":"111eba065e5ad8107a1754dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"576565c24a169f5fbf283fc60d82556f33f8a9cc8435828ee0981d4e6b93cc339740f2e8a78c200f9eec5d88ef","nonce":"111eba065e5ad8107a1754de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"b22160cbeef693bae5ad56f0ad74665d6ba4404f4c62697cc124a66bed73fa522fe38a8b8f8874a46dbff71ffe","nonce":"111eba065e5ad8107a1754df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"4691c4cefbe000b6779c79beb460953d3090cb8f9d84f19ddb17f71e4c583cbf90efc44f5b133c1ada408fbd5b","nonce":"111eba065e5ad8107a1754d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"7aeed34fd8e1cf7ea6f1e132147d7cb4067a2aee03235716a02cf03c86a64745559550a624aca27945ab79ceea","nonce":"111eba065e5ad8107a1754d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"da8ca63ecde3599127c90bb8d17de6aa88554bdc085b76453144d63b629a7837f6865484e8510e04b93cd797a9","nonce":"111eba065e5ad8107a1754d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"112d427ff2aa1aa8fd46f8fcb287a7ef0008e3f2cddd3c01203f878e4d29048f432c215821784b2a0f0de721af","nonce":"111eba065e5ad8107a1754d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"f722910a9f1006d1e21f490f5370fc334d035a91a800a1cfa3e1a06844b291ca939670864a93a5e4505771d783","nonce":"111eba065e5ad8107a1754d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"7e47830cf4e40a8dc70a647a5010789562d3802ecdf2a07bdb2688ce43bcc462203768fa1e2d0c04ffaf79074b","nonce":"111eba065e5ad8107a1754d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"8853bd023b481b9b8896a46682239fbb70dbabae6a5f4003665475c7b97315bb33578eb3f2538889b117c29b6e","nonce":"111eba065e5ad8107a1754d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"163ba6c274066dde9a344165b526b10eb21eb467c6ba1ca5f87cc518dd5d983f325a7d5ec601e9f96b8236be9a","nonce":"111eba065e5ad8107a1754d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"97f0ff3b85cd64f5659049c76171ea14f817119216a191808728d5b79fea45eb66dd5345c89a6fffe9cff58cda","nonce":"111eba065e5ad8107a1754c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"acee3218a3083e2b3364e8a6f0d07985e4586cfd1d781eb7e50817a6f09074cfccf604ead2c1d675f991810917","nonce":"111eba065e5ad8107a1754c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"5173aa8484d7a7e4bd76c1b858ec78e88346c5c10a31d05c6b3ea9b54e1aa21c23940818fff439f19ef72d1fce","nonce":"111eba065e5ad8107a1754ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"610b4313fba33a4bf9ba3b84442b73acb578ed42716f8c9572a03cc3c339ef86317613bb5b8822d267d55ddbf0","nonce":"111eba065e5ad8107a1754cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"6c67f102762d4ab896e835655cb1db38c2a00eb40d42fba6f1268cfa4cddaa4af59847f683c8fad147a754f69f","nonce":"111eba065e5ad8107a1754cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"dddda3fc1922ce2f02a1a0af2aba5f2c9cc8dacd5806c141d1289e986b875dc203f47b4d4fc32325245e40190b","nonce":"111eba065e5ad8107a1754cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"13cc13cfb4ad0bf16491d0e899dc273ab136dbe5b9a9f5f467d31ca4b4a1012018ca8792c0d467941ec464414a","nonce":"111eba065e5ad8107a1754ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"3ab55494750e9fbe148d658bc6bd9ad0459ab83d896f75b28bdeb9b7d92b9e578a5d1241fbe4a73b52279ad7ba","nonce":"111eba065e5ad8107a1754cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"dce6aedaf44768c0da7ca5b9dc235a2741313d6087864cccc0c8d4611f8910d1ea6828946dcea926889e79b44d","nonce":"111eba065e5ad8107a1754c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"b9c78c12686207ef672f53ff069a073d3c7c05949ba9bada3a148382d348bde554f2c0d1e4db2378d8289711d4","nonce":"111eba065e5ad8107a1754c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"63cdfc009598d75b4bf6a6d639ca48be57d465116a71f6ccac8de5e95dee33ff12e70ba19cdd76f57de6535461","nonce":"111eba065e5ad8107a1754c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"ba1933e76059445a88220fb7310bdfdebaa93233afd648025f4ee4fcba40c55a203fd19477c2834e638f0244c3","nonce":"111eba065e5ad8107a1754c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"bc77dec197612784cd4f1f3b3b1f166430c032e9c0f683608d28fc45b480eeab3fcc0177fb5e323ba53cf3a1db","nonce":"111eba065e5ad8107a1754c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"c4f204692da110f4c99cffb785f52dcb5825ae1a76098c230144c6e4bf6c53c9bd1d6933adea71955c01004a60","nonce":"111eba065e5ad8107a1754c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"6fcfa404036d40a42255d993271353a9f3a0c827098fb63c6d835e1466909a71f8e63ac63ff02f43cb70941b50","nonce":"111eba065e5ad8107a1754c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"5e964cd592437351d87d7be852e2bd890a33bc068e245e24db18a446c961fac9cc5b5a8e33c599e79dbd11bd73","nonce":"111eba065e5ad8107a1754c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"40431bd0fbab85a3fa173e555b13de526d5cc08fab6f1ccef67dca9683b3a9bd976a76057d381ca219fd662816","nonce":"111eba065e5ad8107a175438","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"fb837db1f83050bc79761a65632dc9204d2c43b314b2f0095384ee76a2e7d05a042e450f580634c96868d8dbfa","nonce":"111eba065e5ad8107a175439","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"1b9cd6cce08ef53f2a4ff3c826687d82e955cc2b0e27d3fa78122ba3eac33aeb6fc930e90a983a13ed258cec1b","nonce":"111eba065e5ad8107a17543a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"dfb4438c057c8f237b1fa13a7c59be80e41ebf3a17459c27f685adf2ae71f5afe704764ae386ac2067cbeaee7d","nonce":"111eba065e5ad8107a17543b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"5a4128901073ea3ed0330f4e8103d27156992d0b67f376cf9ab10ef5c11dcb3736572dc7a91e91a27e747caa49","nonce":"111eba065e5ad8107a17543c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"8ce76a912a0c99ee0169d84d474bbca7b6bd448a159e7c36e4b81da2dca58a4bc7de28e50cc235338e1dcb8f99","nonce":"111eba065e5ad8107a17543d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"ded2437f2d6d247a54a7cbcccccabccd1f77143c9f474416c2478a5fc6f933f1157082253d040b054db8b0834d","nonce":"111eba065e5ad8107a17543e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"b5b535f11cff61b7b1e1e6df53987742440e4a01bb1a8eeca493a79af84509ded8d347ed3c06c5404941e52151","nonce":"111eba065e5ad8107a17543f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"1eaa9f2a38c8df57ad1338aa5301191c25cde0f851edcfe29c3dab547bda8c817ddd6351b2a8fbb0d13914758a","nonce":"111eba065e5ad8107a175430","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"f0926cac70b4ed19cf31f7f16d4d9ade633a294703ed2ccbef4419aa28fa1109d1d08e0911bfa27959e6e0c02c","nonce":"111eba065e5ad8107a175431","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"42b42fe3ada2c90f164edff2b1a20b5b4c7690bfffd70946e98f83d99fcc2c2092e03d503dd18829d3b2272e36","nonce":"111eba065e5ad8107a175432","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"07443e65d0c84e529479b8dd9e340eee2681b8bd1bf7a0fa20b7040eec055c687756fc3da81f7fe5c93113af20","nonce":"111eba065e5ad8107a175433","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"a561c4a42d1e32c4f5a047fccf24066d8345b8f0756c5951cceea4c6150a77f345fb1488c2379bcd0d59a9918c","nonce":"111eba065e5ad8107a175434","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"16474f54e08e5a4377ea40096ad52b04fab3ff028a2aea7821ae30994efc04dfcf46343c65e3e0777daad06017","nonce":"111eba065e5ad8107a175435","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"c1fd6c445f899af2269e06892942783372afdc4b6c4d1a2b44ba7d95fa5da8cbc8d9106777f139f8eb40c6a134","nonce":"111eba065e5ad8107a175436","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"e3b139a87c1672976ecf6ccd6a9414a7c12a1bade210dcb9db7808353ab6406952acf34ae9335093f268b30129","nonce":"111eba065e5ad8107a175437","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"29b1f7d90dd15f576f054a7229f47f3f7e9ace83a600be90d8cddeb23223db7b7f6fd362930c4ae6f357a3e9ac","nonce":"111eba065e5ad8107a175428","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"202b7af8ebde5a29f858425e8f9ab5b9130981fc4cd2d571b5a7580622912684231b8460b65668ec05d65783db","nonce":"111eba065e5ad8107a175429","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"7ff5e32db66104af691d9d22e54489a501e0e41b562eb9ec792ca20efa929ba90fcf3d594b25af6b8f206d5413","nonce":"111eba065e5ad8107a17542a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"fe8c817e360073bc596ffeb40703ebf0ad2eeb21f241e6675dd1f81e4677b2764c58220b1fca5dcc6a89fb5de0","nonce":"111eba065e5ad8107a17542b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"a825d68402890f874258f429c905c814407126509f8f74f384919d59f99496079532e8b960318c845b48433eb9","nonce":"111eba065e5ad8107a17542c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"bd7227fc166a815bf5a4146e559cb784b8c75c23220a6eee78ae8e591d57b348f28be3a9608c22f61e6a87e21b","nonce":"111eba065e5ad8107a17542d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"2ab6371941dae5ed197e5f67f954e6048df3f52524d02eeab5f8a4b77e606154e19c3d3f73428ffaa1a92f817b","nonce":"111eba065e5ad8107a17542e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"9dc72ab5eac3238da486b9977a2678c770dfd28b95c9685057ec6ae9a40cca46f109047ec3dc4f60b1cd16417d","nonce":"111eba065e5ad8107a17542f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"f1b21b11b645f9274dc4f264533470c0aa8f02a50454ec4379ee41d319c1d501e0873071e83ade4b5cbca4f526","nonce":"111eba065e5ad8107a175420","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"efb8bb77a141b5c80d8d22c00adb1165bf767e8402417904bf87f96b668ce040797703d5a9912178cc11e873cb","nonce":"111eba065e5ad8107a175421","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"7e49ceb0d0ea860215dcfe32498ec69b1b11aa538f02a9001d1f046deb54a6bd3360655ed21dbd90866339c57c","nonce":"111eba065e5ad8107a175422","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"d8ae009ca238dd3c441a07a538b139c146d82a5e8181a518f3e38bb4da9d8381a6e9f8daa0b0f86d2d29ae6d25","nonce":"111eba065e5ad8107a175423","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"798ceac33b43d5209974135666441fef7e01b6311877f0d4dfb4cb50493f72a4ad90121a6a87fe034a215a80f1","nonce":"111eba065e5ad8107a175424","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"badee4566059fdff54f1f593830afd93ebb54b55b2026b51e7a7c9184569c38c06a200e0be284b8e5bab265d50","nonce":"111eba065e5ad8107a175425","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"0c1aa4a48a5109b8bedbb578c5d440778b6406cce7aa231eb789db9f051cabece3f29d22d3b0db4d709c7866b1","nonce":"111eba065e5ad8107a175426","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"0a7d824ac270ffffc7cb336541a1b883f62e8a8b6bc50e207ff7432f632a9a326f9f88ba26dc70e40d0c97bb8e","nonce":"111eba065e5ad8107a175427","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"0e4f114884a9e96f6f3cf48d6547e8f0a6668bb0042a0591cd793f783e2496dd79b8cb23ccd4193de314e92365","nonce":"111eba065e5ad8107a175418","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"2629a53055cf4e5000fd4082972c7e4fddb20c06c2a49aaf8d11254036cb36e56a6368d981cf44b90bb8c1fdae","nonce":"111eba065e5ad8107a175419","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"4a30a719106ca645f457dbf7dd52e6bbab5eacead2cf4687c016f6b8007264aaf04c366458b4f0617fcb3f60cb","nonce":"111eba065e5ad8107a17541a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"26ac9edb0daa11a3a31880d9ae6980e35bde5c02c5d55681416c1cb1d7996638c103ef9f62a301a8d9614e68d9","nonce":"111eba065e5ad8107a17541b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"78407043febad2da6b411453ca1f4c5df7433731c2249be5b59f1ee06d4f207118a10c7c63d884c12c22147484","nonce":"111eba065e5ad8107a17541c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"296437046bb1e7e23eb8c74756e2377e807e456d11ec1f7f6b55eee85312d735cdcf29fa5acb39b5b80449822b","nonce":"111eba065e5ad8107a17541d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"ef274710f1fbe25760a9f3b6a4a753553468bddc69690c930fdaa4f1f1cea7455a0ced6f6263e84b439cfdce86","nonce":"111eba065e5ad8107a17541e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"44db605914407b14b7a3217401c392559a4eea5c27df5d07aebf205750f95f1abf999252785e949744cdf887cd","nonce":"111eba065e5ad8107a17541f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"5104d01aa48f805c030ca129c9fe7235fbae3c3ab991ce0ca91db1d001c6bd3f7d7a5264708cb0c43a284bab29","nonce":"111eba065e5ad8107a175410","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"365b4b8ebf923dbdd676341daafa2e7712e6fddbba09d82d6b941c4b6883604a4876407d607082bb906e307670","nonce":"111eba065e5ad8107a175411","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"05ece37be7a8d08b342cb7b58974b081854a190dd53fad9ed7ade6262c181fc44dbad320fb9b71bb026e4e136a","nonce":"111eba065e5ad8107a175412","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"847573d32114daee6955cf35bb801c9035ac16c0b935adfcaf2edf9ec358f8283bbafca7f54eb12fbc5554b284","nonce":"111eba065e5ad8107a175413","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"f493a5fa3e9f73a38e014088978e48917bdafe351026b6feb556e16201c9fba28de8b898ea0ee6bc7fc8905f5f","nonce":"111eba065e5ad8107a175414","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"596b53b150214a1cb0083351f76065bdf63994a39b4cb3d639d420e08dd197f833bb5853f71e5d49efa45b6949","nonce":"111eba065e5ad8107a175415","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"8b84453673c2970e7fdf12c97fba3e0dbb8ae4abd04d84c1531da7085f7446c11059e3e789b76bb4a8d8f2e6f9","nonce":"111eba065e5ad8107a175416","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"2d4be3154b4742cb9a4d5da8ab8a71499be78f94ca9a95bf72dc1499908f73d1aa415dfeb5a16b2e8d4bd40677","nonce":"111eba065e5ad8107a175417","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"6a1911377ff2e74225755f717628885b944ef061cba24258915815265adec9a1028a34894676d82a0f0f90ea2f","nonce":"111eba065e5ad8107a175408","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"bb6edb9c66ea51d29fc12d56c3cc0985ff4a647fe0c8b31ed529400357cd3f228339810992cf4b41cd19b44332","nonce":"111eba065e5ad8107a175409","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"dc6e6a6128241c930f4589b5b3ef6df953fc0734bb34d460d0e61ca733e4180b5804ab5a4d2e18a643fc53007f","nonce":"111eba065e5ad8107a17540a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"b819565cca20c4b9d4cbbbee445d3d680bf2d16f1aaac7506d0e04211176812f238a559bfa538a348cec2a2f38","nonce":"111eba065e5ad8107a17540b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"5364d20c2ed0b733b30fccc18806a9f30f0cdf99ce5714b81511ba4d4259389dcd1918f12d9eed1c22bb58e829","nonce":"111eba065e5ad8107a17540c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"31ef905877be9d0c4225a0af92fcab97ae2552fbe5810f075dfbd1ad9734fc61bf5e826c46b35fe715cae449ac","nonce":"111eba065e5ad8107a17540d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"d806798082a55fdaf0c48815cf04b571955ecd78e58dc021f075c8337968d69ebfc3c3d6fa5f0152fccb0250ee","nonce":"111eba065e5ad8107a17540e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"93dae126fdd6e44104a1eef56db23f5a69c61e124f966dbda47472c5b76b967f061309bfd527dba8481bb2a069","nonce":"111eba065e5ad8107a17540f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"162028de3ea6f0e225a4b6d60edcb458cf41e423b40aec69acd1d108f223d9f80603cf06285b0057f8d42f7078","nonce":"111eba065e5ad8107a175400","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"d6883236f3c2d5646ec96377cabebb11a85dc20ccb05c812c58f9696132ac522e7a551b2768a556aff1a411119","nonce":"111eba065e5ad8107a175401","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"8f5cc69a2458973d7fb9daf582534b4cdf367f842cdcda8dc584aae1a6e294733c2b864926f3977677464ad9a3","nonce":"111eba065e5ad8107a175402","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"d7df742cde3d7e9850b853801077efc37cc6eb3de0f4c720faeb72e293d34f2f3f1b180cc18355e0f2c7d8c24f","nonce":"111eba065e5ad8107a175403","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"61a7a5ee0459028292af91d19e677d3f52564b0284e1b4b6abb41c16d74e952fa096edbde12f1c64f0c36c1793","nonce":"111eba065e5ad8107a175404","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"531ef79ea363b0bcb303010caf4122178e5f7010c73add668fd03768ba80c8f3a672e014facfad6cbaa0ddd5fe","nonce":"111eba065e5ad8107a175405","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"24b72f2995d11c01dfdcd28f5bb3e32c1dd2daa963883a28f2d2e86bb11fb7250c22be12112193ea8a312f425b","nonce":"111eba065e5ad8107a175406","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"46340b1604849c371060642439f24b2a0dfa43fd76d8e6f1d3740b8e5f9ff0cb54491bb47fe8960b799e4151a0","nonce":"111eba065e5ad8107a175407","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"c579320fd812369fe1f0b507e5a3401e536e20d01c4d80c178e88e2672a6c917bd9c0ecf7f94af349923bc5517","nonce":"111eba065e5ad8107a175478","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"85c0ceed661f81787484c9071249b7a733f27a6ca5c6eaf766482fb0d055718cf88f51ec602903f9d3049614be","nonce":"111eba065e5ad8107a175479","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"f7037d8bff0cc07e58957d877356137eb84865e12adb4f74a13e8ea2855649db99730ce689aa4172b125b3600a","nonce":"111eba065e5ad8107a17547a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"70d948d711ceb1a2b6598f5f7f9166abf0ab49ecba30651a7af39e30591935dd7c5d25014e741626c2dee3ae79","nonce":"111eba065e5ad8107a17547b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"3cbfb892ea7d9abc0e1f81f98203af17f51e0b317a67f2b8e75bb4539289ead6fb54ee2e107919cf5f6b32ef3e","nonce":"111eba065e5ad8107a17547c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"a8d23618da72c63f045f2206cb9fc29c5df7bcd354dc798559d9ad5a5d8447dc22b59ae6834d3bfeedc7cddb74","nonce":"111eba065e5ad8107a17547d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"649b201cc8cfaffcc417b9820c9abbe44ef3084bd970d0328aa1976c9b28858e0aef85e4360e58bc249c8624a9","nonce":"111eba065e5ad8107a17547e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"262b4f61af53db80e31156f878b173fb53363cf84531c574040993ed81c73aca78e4b9d0938ab4bccd6bc9e36b","nonce":"111eba065e5ad8107a17547f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"4d8486c75ca53af75fd20c8c715c4de78a158e18f21087d87be521d0b98d1b0bdbb4524aaca6ed2ab84c4dba5b","nonce":"111eba065e5ad8107a175470","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"014619080bea7311627294052a1b43b03467b44a5c54c298df92867c8f569339f9ed0470b64d85fea7984781bb","nonce":"111eba065e5ad8107a175471","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"3d34742b2efb20fc30960756ede2e64b49cf0406e2dced5ecf47ac5a82f48432836a3b60a10a5cb15c1d5f5b33","nonce":"111eba065e5ad8107a175472","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"4e33f0cfca3cd05d3c92ef9f8950237d3f601cdcd199a9c7245fa2a828f66add820b981bba1920a177e072b9ec","nonce":"111eba065e5ad8107a175473","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"98ebbca9e1d0c31a470a60b1f0601cff350e2027ef0787b9ed496c565b6427aa846177458eab690b042af265d4","nonce":"111eba065e5ad8107a175474","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"5dcca962971ec2d6b6be5470e3447f1071c44b961b1af86a3d9b3695b6723075674a3d0e39971dc04b312db1eb","nonce":"111eba065e5ad8107a175475","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"92824d3d6c2593afb8d97f49b20bd9bc497b1717889c7faa9d51e81a20b5649a660c4d3fb623f2b82f8267b36f","nonce":"111eba065e5ad8107a175476","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"de16245363fce16b19f13a74fe926adefea2d2a9af19ad130a9234639972542aba2111b69cb53675c61c32ef0f","nonce":"111eba065e5ad8107a175477","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"39b4abeacd5613bd95b133db8c9ae588e17c85fa2dd6af1f99d749d0049a304c911ffd6125350b7fc8bda2ff33","nonce":"111eba065e5ad8107a175468","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"11878ec03b113cf9993b00c4905464e9d17adee858e965a74fe2effe0af546c1915bab0ec12dc8990165513fff","nonce":"111eba065e5ad8107a175469","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"489a90b7266bd96f085a2d071e99152d0a24f36f6f1fe9e3964e37fa37274e909b86f972909d89bd1702d16d63","nonce":"111eba065e5ad8107a17546a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"4d987d8856e1f70d592759c3a62b8c636032569dd54629f5cfc515de3c1d82e3540f01f9fb75e06d54edb54569","nonce":"111eba065e5ad8107a17546b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"6cc65aebb9b3129e5eaf445b1c88cf378f56cff913f6ce086433e84aeabe0b6e9240f146acc37cb57577fed57d","nonce":"111eba065e5ad8107a17546c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"9e0f5560aa8bdb6e6557d1b243e897f900ac0a4f4995b51022475fa2385d8dfe8d776f6867b03bbb33e8cd559c","nonce":"111eba065e5ad8107a17546d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"5ff32beea315c2d87da0064f55779f905b9cd45c02a4d610c6ce4dcdde33b55cf1f02f932e7ccae3c446b86a07","nonce":"111eba065e5ad8107a17546e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"afe0114d669a8501872907952a881e05601e562fd893891b0c6fbd5e2227180f22c86f8ddcc3e7cd38ccd3a69b","nonce":"111eba065e5ad8107a17546f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"2fd82182f1d08238718247980d6eb54c2379e94aaf1dabb57187913300bfbf17877bafbe794c308b51ab32a698","nonce":"111eba065e5ad8107a175460","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"1e78ce0c5d82427c9e22235f8ff2d361e3330ff6ac23ef5c4e12b10474283f7ecb8fffbc8bbb3e977791417559","nonce":"111eba065e5ad8107a175461","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"6d543e08218f6cb3a3a1e3e5e1bf9c28902edc3f1caa5f112c64672d907fcb8760a844b02e6713b1cc316cf115","nonce":"111eba065e5ad8107a175462","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"343dae6d87e2174260e9ef2bd81e84b9305c8e8396c993db1287035265d50c5630a6e4392882dee5e8c4cd7ebd","nonce":"111eba065e5ad8107a175463","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"8a9be32e7be24bcf875b60df98402708d4fdd81918b781b69aacd54eeec88e5426da43f6294ad5a1ff517ca5d2","nonce":"111eba065e5ad8107a175464","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"14aa775902fa6d7aeb044fa6bb3175c01d39db465c9050c6350540d67509f3eeb19c7004470b32023ae6829261","nonce":"111eba065e5ad8107a175465","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"2744db616c31c13154a86cbb04c224f031ebbbbad1f618f025e3311eae166fe8415ea26e73aba4eeb0e0e71fbc","nonce":"111eba065e5ad8107a175466","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"d59ac240bc0830a1a96d294716580cd294a588425aa752d1b64157f832c4e9af24225e4ca1901a074b64d7d7d3","nonce":"111eba065e5ad8107a175467","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"6e865e7d33723d4cc0a3809bf356ee0408ec899a636f4fba86fd4801d458399b3d7fb94663b11d7d01dd3c5f23","nonce":"111eba065e5ad8107a175458","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"96b672b67d372858282d92c6da5d9a34dd15a41a712879ceea852b3fb2a2dc85ef5a4fd09b1ad1209b52a85859","nonce":"111eba065e5ad8107a175459","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"57da949a2da7592a1426c63d490c2c65719b97b049c8568c12d5082f577b9066091be6f4f082ed0c4e5ed75cae","nonce":"111eba065e5ad8107a17545a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"48b953b204464976341f72acc3f145db354ed3ed7c072263d32664c7d8704d7d8653a2563d40a09e08f417a22e","nonce":"111eba065e5ad8107a17545b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"c09b3d7236b8bf933d27743d362f4f8b422188f62edddf6312dd4e2b7380606f384f5a8723198a2359d6e243db","nonce":"111eba065e5ad8107a17545c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"97b88cd1839dd6a5d80a500b5808a71cf258569aa9162e0cec27c238d4e389879fb1a55cc461da8de6cb9de9b0","nonce":"111eba065e5ad8107a17545d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"e2168703935a22f5aaa88a2156e0d6382295aec564a81f37c1cee150f96eebed89edcdc5ba886bd4669a09c37d","nonce":"111eba065e5ad8107a17545e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"ca3cd04079691896a8a7926a6947a06bdebeb4115cf36ce507c8ef545778d4a5a3bb14752c84c2be786e28e40b","nonce":"111eba065e5ad8107a17545f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"3e719facea45de985baf672672bfb1e32ad7fc935f0b92b57c7000572a8985042b05a954d852ba48a3ddc0c810","nonce":"111eba065e5ad8107a175450","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"a976df8bec762cf32908148d707dcd403e5a67c900d7909a7048fc7d6e4e6a3c86efb2ebe1cc63eed4e471abfc","nonce":"111eba065e5ad8107a175451","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"45b0877482e1d06d900b1269464c91e5ce8001dfdb456d9eca1086195ebffadcf30760c51a8af84bfbac31ea23","nonce":"111eba065e5ad8107a175452","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"9a7c98d2a56232d962940ffaf6fb8b776567dca8b7f57b9bae48219a870afa24b940f7c61ad10c5f2f8e997b7d","nonce":"111eba065e5ad8107a175453","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"2b60aff99525df235fe463ac5d4226d346de7742c6a8eddc1409785e62ab01b61ebd2ef1a807f0350c74fd5d89","nonce":"111eba065e5ad8107a175454","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"f74aefd9131589fd9645cdee64aa86dea51174dd152ffba9f3a59abcd6af40ab5c5e85a097535f51b6c9d75dd6","nonce":"111eba065e5ad8107a175455","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"3b72386bace70446ccc74f1fbef7a91a3282143612856970d9b2d86e8c17d02a3f6ec6ce6ce89bce3375536cc9","nonce":"111eba065e5ad8107a175456","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"d6ae9bfa3cebd1344e8ac2de5a0568ce3b0ef361e43047ad4ca80d76644d97c57a87b2b3253fdf46e96c651f06","nonce":"111eba065e5ad8107a175457","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"735af280fdf3d47cf2741429680b731e7f59133473d09189feaea912de92d116aafc364b78eaa06dcde345495c","nonce":"111eba065e5ad8107a175448","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"6ede7031a963aea585ef6d9e765e42e4accc4fb7e138ae9240a0057dda03106bb3e53ce0ced2e38223c00a1625","nonce":"111eba065e5ad8107a175449","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"a18416c8e2489c6b482b849c5a05c3ef5b6746f7f4133ef5201bbcf998ea1535411f83156d48121636cbbb0c48","nonce":"111eba065e5ad8107a17544a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"519c31abae8839d61edc520043120a78b21b6d1f1c570629a6556902d15482c0b5f773f02470acadf5a0aa7947","nonce":"111eba065e5ad8107a17544b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"1b7245d3fb41c992985f7f5f34a67d96c4e9660d5544020223e930504de5a19417085ffe6fa46f829a559707fa","nonce":"111eba065e5ad8107a17544c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"425b52d6ea85969d37082d5a5431f6288b2a52f770a28f10dd052cb90282f9beeec07bd05d1033143664d2007b","nonce":"111eba065e5ad8107a17544d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"b44a95705a3db5610a46f85a57eaef42fc60a4b1c940e5c21665511f23b907aae8d696e91ecb5b87335fcd6eb9","nonce":"111eba065e5ad8107a17544e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"57cedbba6c1cd6f507152700fefe81cf0c332f94da8eeec9ffeaf96ad03a4ad6f282d194e4afd68a5763cb46ae","nonce":"111eba065e5ad8107a17544f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"ec0bdac3dbc180ae4a337c387c71ac722e2deb70ab7b2a432ed32e2c4e9ecc26efe785395c80be48753dfa5b06","nonce":"111eba065e5ad8107a175440","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"dee4493582dff2027bf4db28ab11ecb82a068dc4ad7eb0462e574097c2eeedf6b1446b7b09015b3ad26f63c078","nonce":"111eba065e5ad8107a175441","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"6a13e3b449e981acf9f2015cb21d16a1f650e8814f136a42a51879c6cdaa198939f7eed77e8170e47bb04dcd3c","nonce":"111eba065e5ad8107a175442","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"6651c3193b183a3a145f731028b98ef3b06d8c260b67d07da58daf2c0f116d7c65a1b97c2f7c95c3a0b7255d60","nonce":"111eba065e5ad8107a175443","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"90046bc7100585d493d412293ad2fe7095b157daa1fd8b1270d81be1e71a608d5007bc048c548083fa5b1a9f24","nonce":"111eba065e5ad8107a175444","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"6f16336f5f9113f085f1076ed207f9967a6042b2ef1004cd059eb2ce82a30dfd39c187095730e4d189a5e9f1cc","nonce":"111eba065e5ad8107a175445","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"35d0dd3f45f18efa5cbd4751a83ab82b18926584ad818dbc933725524d1ef948edcf42916f3da9b50bf351903a","nonce":"111eba065e5ad8107a175446","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"a2d718314003a6bd9736ced739e669b27d7531990b9faadada5088c39b836cd5f66260f2ad5d38532bd8ce6b7e","nonce":"111eba065e5ad8107a175447","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"859103f7bbb57e69c8466d9fb4771c7db5b38d98582c8d5af22a8617e0f6cab69f9ccd5cd62471436672a23d8a","nonce":"111eba065e5ad8107a1755b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"3abb5ebece70726875c4bb94a1370afeaa9a7b16754c7cac7ea78b455c550201"},{"exporter_context":"00","L":32,"exported_value":"b2eeb874b1e6470cd830d27f10dc5889851af0bc7d596cedd14be3e7976d132e"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"dc987ec90889c7c0152d7f78c512f1471a95d039d45e30275d3a408b12e72673"}]},{"mode":0,"kem_id":32,"kdf_id":1,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"be6e6cf70ed8d40b199fccc9d824ba84a02f0dccc409de3643ffd68962a92ef3","ikmE":"8284a224fe2689b97c5fb598889d5af5268ef22efc656ac8359a1c6007910f30","skRm":"47be98cd1ac849d09e95fb64dbebb4861457a864f98becbe5c399d636025a7d7","skEm":"4f15c72b234d390ced29f2d6b07c2930254bb2101425a1cbe709e23375c2ff05","pkRm":"e77bad5e13ac74dc341385a0454a0ff48cbc1faed1f56656b6f5ea9ad7d1220e","pkEm":"d862803cbbc56f94f7ffd62bdb7f96954e4fa1e2b2c3a8e4251858ab57b79e0b","enc":"d862803cbbc56f94f7ffd62bdb7f96954e4fa1e2b2c3a8e4251858ab57b79e0b","shared_secret":"554871607763734d0809e4e8776af6086bee6efcbe98d054e5a1d8f86edeab82","key_schedule_context":"00431df6cd95e11ff49d7013563baf7f11588c75a6611ee2a4404a49306ae4cfc5b69c5718a60cc5876c358d3f7fc31ddb598503f67be58ea1e798c0bb19eb9796","secret":"6797a9ad52fa35dfb5bfa3c597dcaf2bfd395fc6bdd34dc5c4620c6ce6d960f1","key":"84473361e8d74ac69b220fc02f66f4c5d54c4d32ebf0f5b73dda23a7fead9930","base_nonce":"f7fb1c2c9a13c5fd8e5c7ab6","exporter_secret":"7f843b1431520f8c2a5e329e75496e96be470b86d25e85ffa20113765f68166e","encryptions":[{"aad":"436f756e742d30","ciphertext":"11be91e6a7f80d2f341e3baa06470aa60401dc953d6933234c81bafffc4476cecff9b427359e00084c5e02d13a","nonce":"f7fb1c2c9a13c5fd8e5c7ab6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"752f4c9d907602a3fefcf9e0b8defad1c87082762b533c83da780b3c78bab6ede23fff3de660a2e5c4e4ed406e","nonce":"f7fb1c2c9a13c5fd8e5c7ab7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"025350759f0ce9e3dbc8358473163894a5da3d785eec934e6801a4ff072d99024fc81f60b6d6a839a0f2c8fab4","nonce":"f7fb1c2c9a13c5fd8e5c7ab4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"f136377c7ae84ac01c53e0c77056ea6c2138e9b38800044f1e91c8838384e27856a8d380f8acef0c1719939771","nonce":"f7fb1c2c9a13c5fd8e5c7ab5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"28ce79827dbaf7c07b8270170e6851c1e9bb3a98d8d0538ff551c25b4d1d1e176982d4377cc021510e609ab66b","nonce":"f7fb1c2c9a13c5fd8e5c7ab2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"e2786c8e2e20014e589441ca3d0382f3c76e31ed04dcfa2d571d03fe19eb81c0abc2e711b2f8b45f33a4a7666a","nonce":"f7fb1c2c9a13c5fd8e5c7ab3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"a83eeba76dfa34f8fad7235a46a42b1cbcf03507f068768412f6184c748c31b1f872d00a8a7f859c37423ee169","nonce":"f7fb1c2c9a13c5fd8e5c7ab0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"96223d7841f3dc5d747df6e2b0a6cb5ed0ca2ac3c63dac7fb7beeac4555b4b024c448539e2751611be319795a8","nonce":"f7fb1c2c9a13c5fd8e5c7ab1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"759d0488acffb427ae0532c1c51622fb31e4c44f0f48dfea46b979a05a218f2a7d501dffd432f93ca441f0b8f1","nonce":"f7fb1c2c9a13c5fd8e5c7abe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"cfc4e93b5ecaed9a5975fc082ecb360179bba9292f86bb9b0e4b1b3a8d1d89b4b070262b3feaff65349266cfaa","nonce":"f7fb1c2c9a13c5fd8e5c7abf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"ca4a7943e4ec60f7c279ebd17d2f62e42c1e47c37addd2a183c7dc7562dbd988d3a194e5e1621465fbe964c32f","nonce":"f7fb1c2c9a13c5fd8e5c7abc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"33cfb52a5f8990e7f206e81da4610bc513484815262be462c30a5fd8120b4a48a01f0ab263f51a6bdf632901a1","nonce":"f7fb1c2c9a13c5fd8e5c7abd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"a9eb03e9bb81c31b7d8181219ded5c28ec2b816c7d0f47ecf88d5aee3addc0473279d5363bce365ce6279069f1","nonce":"f7fb1c2c9a13c5fd8e5c7aba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"de9e326f13d99bbdfacc5b84643bffc5ea0b921d1729043198f8f67f45f88e14a36ad16a4623851af8b0234d5a","nonce":"f7fb1c2c9a13c5fd8e5c7abb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"41670de15276ac593d1a9ac7d0ead010642a4771a30501727ac1d2a05bb24133ab00fad4856e0fc08612e0b18c","nonce":"f7fb1c2c9a13c5fd8e5c7ab8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"fc08cd03f0045ed815baf4d7932eda174c8fe33c631fd9e233fbe9fa51389efd46b97ab4182d7075665b385bd4","nonce":"f7fb1c2c9a13c5fd8e5c7ab9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"428371feee92674ab18b93b1d023716d404b641f0d7604c2443ed4936500163ed3ae2d180fdc2026c8d96a0559","nonce":"f7fb1c2c9a13c5fd8e5c7aa6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"f853217b23110afe0d4de4e805b7d1c94b736d49edd04ee736ed3c83c0b00d81e6932e79a0bb72591058abd781","nonce":"f7fb1c2c9a13c5fd8e5c7aa7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"17d16569a80994241e1bd749a9072ca1d142ae846843a13e516331ab77e11514f7280814388e07fbc12d5fa7b5","nonce":"f7fb1c2c9a13c5fd8e5c7aa4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"c33f7ac01b1d33f8937d7baae4f40bc28dd6caae0cf2e92df06ae85e37db36e27ca788fffd98826c276fa7dd22","nonce":"f7fb1c2c9a13c5fd8e5c7aa5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"720d65b93331701667ba7345294d4193386341628f63e4af7c163b088e6ae35a4f122b1f331cf89f090435df40","nonce":"f7fb1c2c9a13c5fd8e5c7aa2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"9579a2cfffc52e1a0542cf65046083de51ce60ece850c83e1e3d98bd09c00a79d0dd1c39e94344c800083be710","nonce":"f7fb1c2c9a13c5fd8e5c7aa3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"1c68905f35c296d6366a9efd0cb334d9a8b63670794f99943e0d199de20a581ec5a091b6f344b990deb5ee3977","nonce":"f7fb1c2c9a13c5fd8e5c7aa0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"0dfc4cb465f6f052f780c5ca6a08f7500645b63888f6c7aa102770354b2063f0c7602a425feec9541c1ba1654d","nonce":"f7fb1c2c9a13c5fd8e5c7aa1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"a6afb3d65c419aba639f78b86c781f749766dc2eb7add90872371c7e0e1408c50692f609ddd097fc6dec00e65f","nonce":"f7fb1c2c9a13c5fd8e5c7aae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"5103917951d5d0e9ba18854c3da687ca884c24180ce0d94aa6e0a7a4733bc2753f4c53dc4403235c6a814dcf15","nonce":"f7fb1c2c9a13c5fd8e5c7aaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"2f2a29933797c8b14bfb154ac3c17c6441894df987e64f0939b435e2ac12527cd8fcd509d6f3c0ec010e3159b7","nonce":"f7fb1c2c9a13c5fd8e5c7aac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"e5792f0e4d4cfcb57b90c2de2d3bb3b9c073bee6bb00ff31b0efe73cb8f3d70bcf60faaf81b8dc46ca824c236f","nonce":"f7fb1c2c9a13c5fd8e5c7aad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"063e0998779be19a278d85fdfc0c110c3ca8a6576485f1c8f3979e2875e6047599d95d3fd42a02a9fbff639f02","nonce":"f7fb1c2c9a13c5fd8e5c7aaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"9c1b307ed8dedd676125efd0d88bf10ebdc9f3716e36f60ae1fe6a0ce4d600a219e42d350b0651c045dedf040f","nonce":"f7fb1c2c9a13c5fd8e5c7aab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"57857419ac000fda86130df4f35508f36e89b8a03ab62d035967941502a2c93e860637b025d181266c6e96ae8d","nonce":"f7fb1c2c9a13c5fd8e5c7aa8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"f61f3b4b66c76f65d35ed676c66b01d5a67fabd2321ca70774b5465a31983b5facd0f097ff9e9a786e1f97f433","nonce":"f7fb1c2c9a13c5fd8e5c7aa9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"8034adccb31ffda54fa3f27813c3d6a1593b004b6d3657a6a2ecf2557cd298e41296b48828c48e43140dc60055","nonce":"f7fb1c2c9a13c5fd8e5c7a96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"f86ffc7369272e20b4a1cc67ea3a5d77a689d4256e9a1484075ce9ff44bb15d121dc7b7ae10146d93dce251f5c","nonce":"f7fb1c2c9a13c5fd8e5c7a97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"f01d65112654df58ea8fe6e1be53f73a3a8ab9567d34746682c67ea1851e5bde3c0c29f31eaa551bd6f5264497","nonce":"f7fb1c2c9a13c5fd8e5c7a94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"721a3e2eb997cb2bc265e8e23c9ffa6de9ae88fecdabd6bea46beffeddd1a6455c9dd7169ed934b0283d93a7d2","nonce":"f7fb1c2c9a13c5fd8e5c7a95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"4dae1c33afa6adafd18e62f9b6313144f1ae6003e5e29a9095069fcd6064fb179920c7604198f0e25509abbb6f","nonce":"f7fb1c2c9a13c5fd8e5c7a92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"7f85e5128dee63e731f1d0aea5b2259cd7561444a9acb56d4a19b7e5e01dde1040945135cfa0a974fd13393c15","nonce":"f7fb1c2c9a13c5fd8e5c7a93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"fe658ec34f33c04ba6e5cc8773ddf1a29d8d4f2f876513c27c16b3abaaf5ddf0d87699502c6d89593e1e80b897","nonce":"f7fb1c2c9a13c5fd8e5c7a90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"39e45cba99d062cbadf0afb307c3faff251075fbe73a161babf5f4b2a19de35fef4d8b6dd92a4f24d8901f3e7b","nonce":"f7fb1c2c9a13c5fd8e5c7a91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"462248a0ac3ece7a38a3d6924c5bc0a16c887c74cf10738473b0956d3af669c3636325578c7a8f1332fd6c2870","nonce":"f7fb1c2c9a13c5fd8e5c7a9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"ecf50cf19bf229077dcdc1c75f00d333a202bbc4e220c3ec77f84cc3a3babde611a0dae74b3e4ff4b5eb20128e","nonce":"f7fb1c2c9a13c5fd8e5c7a9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"5149408855139b9cae8fbbe98a213c302960141b70527bbc9ec07222c8b1be5b40a2799ade84395aa48b1c16b7","nonce":"f7fb1c2c9a13c5fd8e5c7a9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"8fdfeed19dae0bfddfd919644b9a56ff013dc1ca2b3e92187601fed81c6f68b40dcd2e210c1dc9f03f3e2ba0f5","nonce":"f7fb1c2c9a13c5fd8e5c7a9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"a4912236225169c797a9c420c166100d751e7acbc721b08c341bb202996249faf04edad4898f684b819c84b445","nonce":"f7fb1c2c9a13c5fd8e5c7a9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"44a14d8c01b28e7134cadec29a13c833e79f370904eb1f10ae556b34df49e90be6b1b0ec6246d84d2e7e42d81b","nonce":"f7fb1c2c9a13c5fd8e5c7a9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"5bc0466eb0137c5de38fb9fc5a03f1d555112f6e1be2a3dec6ab9c3313f73f7417e19e85b42a962a5084a3048b","nonce":"f7fb1c2c9a13c5fd8e5c7a98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"bb8d102a26e002fead3b795e2cf54e5931e7efac0cd48e23a6bb94b60b89de44341622308d6b1581e79c1b217f","nonce":"f7fb1c2c9a13c5fd8e5c7a99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"c20b78f669cef539d91b82c19496936fae52ef39c8ddd11e7e5c3e8482a96ed5c21d0f110696c4b6973ff2d8c6","nonce":"f7fb1c2c9a13c5fd8e5c7a86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"b406b4c1d3660cf6bb4a2f6471b8c6bdbbc27862d9673804fb9d03cd6c1da8fec8eda3e77a658da23f060861d2","nonce":"f7fb1c2c9a13c5fd8e5c7a87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"9d4226c99c6bdcea9865c72c69bf7de196dc9fd64509a29eca7aba02b56c2045bf251cfb9db32fcfde08eaa9b3","nonce":"f7fb1c2c9a13c5fd8e5c7a84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"06a3691d5bc0f8d43f45ea734a87e8020304ae5300bea9ca2a3afc71e255b88014be7e8945ebd0ac59e36ee5e3","nonce":"f7fb1c2c9a13c5fd8e5c7a85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"bf7671b60bce7f274dd4cfcefc5f7ea619ede25629545c1c974ab0ed180dff5423adfce13b2705e8a04c78ed72","nonce":"f7fb1c2c9a13c5fd8e5c7a82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"b6fcb975332a9ad88e860d2e662a5c8d048d90a2467c954ff70c61e67336ad87945bfe2a0640169e2a2862dd23","nonce":"f7fb1c2c9a13c5fd8e5c7a83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"d7909ea378b2d48cb7f68418223d1d795ce28089ef690df03c63ba788730047c73410090e3546960a5f87894ef","nonce":"f7fb1c2c9a13c5fd8e5c7a80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"dc20e2258e73e02dcd414265b2d888b21abd4336846cbf3a73436c46729a8b610e0b8af702fd0fc2eabe5bd8ca","nonce":"f7fb1c2c9a13c5fd8e5c7a81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"2ef646f84e30c220a75ba5b079e9997a2e069a477c7c90ff8db7b2ce74624b8eebb4472dca356be5b74d037500","nonce":"f7fb1c2c9a13c5fd8e5c7a8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"1d9387d2daadcb26cbda820d0564c38db527d0e70fbeb56790a8092ff331f14cf7094ac2068382adf0e581b561","nonce":"f7fb1c2c9a13c5fd8e5c7a8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"ca29ac844fc2767d5fa4703ad1731d1103837ca72ab220c7cba0e5519f5db727177caee1b7214d0337f9bacaef","nonce":"f7fb1c2c9a13c5fd8e5c7a8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"ee3b9235f3c3580e88c2f0827e545916c3817cc250540b864cad4c46c69671f3e7bc0d17c72f243923c85e68ff","nonce":"f7fb1c2c9a13c5fd8e5c7a8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"8625f86ea0af8cfa318431eadb3bc4a218e2ae36afa19912a64f9a2f94315ada01f51f246eef110306e87ec107","nonce":"f7fb1c2c9a13c5fd8e5c7a8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"ffa971b92263954274df4dcdc9a85ad5ace727307289fd04167033a50ce1754247298ed55c690078ef4d96dcc2","nonce":"f7fb1c2c9a13c5fd8e5c7a8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"301cdcd78536c3552e02b9d241422f0614cfbfb5f93f67bccf75b12a6aa6f86e27914d4aad83ae78a03344d9bf","nonce":"f7fb1c2c9a13c5fd8e5c7a88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"fba04958519c226fad5ec23765c8755c649676f21d059b7849a7739a3dfb6bdcd245eacc37a6e1edf15f641c47","nonce":"f7fb1c2c9a13c5fd8e5c7a89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"c9d3eb0c640fec82e58b8e5699fc66566463798b33fd0be3d84be80efcf1bc25d4c2f3b854b50e06cec657b3e9","nonce":"f7fb1c2c9a13c5fd8e5c7af6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"c45e5d6be31bafcd415cc0f23729b9387908bf1fe411b65b4470e71b7a3a2b8e34ddafa120ffd698dee1e93571","nonce":"f7fb1c2c9a13c5fd8e5c7af7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"edf4b98d738296fee63dd021fac520d6c97a4f03ba76bff8d18730a718e1df618c428ceddc6f8beb4de27d6996","nonce":"f7fb1c2c9a13c5fd8e5c7af4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"f1aa0c28b1adc6614179156dc2f6a033c9c45993d56e0f512a52bba5860048869754ab717a6174503abcdc3dd6","nonce":"f7fb1c2c9a13c5fd8e5c7af5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"035c3e3abc6a4eaa3339edb053840891e80ef48918150438da1407d3d9993e9a84dac165bd11e018f1b3d340e8","nonce":"f7fb1c2c9a13c5fd8e5c7af2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"ac46260d7098cc1a65998dcdcd246be93e3aa9f39df5f68584bb59adc4fa2e4f00eb6f709fffc7ba6ac2d1fc5a","nonce":"f7fb1c2c9a13c5fd8e5c7af3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"ffb8d5862b98ecd289be6ba749e4755ea556a8dd47e41b082daaf19a378fb913714dfe1c47838b74d0b96f83b6","nonce":"f7fb1c2c9a13c5fd8e5c7af0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"cf7573ada1527de47e5dc51d154edb698a8a293373635186a4bae13bf0f9a54b3439bed7cc613f3a0c3fc40015","nonce":"f7fb1c2c9a13c5fd8e5c7af1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"a454a60fc3f609a5a196d01831b0b644f47605f2313be28aa3b0e2839438a294dfb13592c09d8f2e9856f2864e","nonce":"f7fb1c2c9a13c5fd8e5c7afe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"45dc05493da820e74ea58e3df5c228298a22953963b83a2d1fb3dc08bee3c88d28bd2f2f4d8d66955031e8e778","nonce":"f7fb1c2c9a13c5fd8e5c7aff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"7cb429f1b97aa56f1cca2548a04026e6e9a597330912cdc92c0624f87c96470e0819e5d9ef549a0fe8f6de7aa6","nonce":"f7fb1c2c9a13c5fd8e5c7afc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"caf0076559e19b473a9dd7dccab8dc6415cc176a6cf6e5c1b0b23cf9c412d5bdd4c3ac2e36c6449b51debee356","nonce":"f7fb1c2c9a13c5fd8e5c7afd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"ff3e1ab667eba56e4409a78cc5680ca9518e8b7696ef7dbc258a3167dce48b3c3632fd8ff3e5786c3deeb6e477","nonce":"f7fb1c2c9a13c5fd8e5c7afa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"0253079dd013b826e429ece4cd649806969cf6cd2c42fad15898287aa0f7b91adffd6b7fa4c43cca0d4bbd2519","nonce":"f7fb1c2c9a13c5fd8e5c7afb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"4224a832c5c7ee3697d48080cd322aed84b43ff501d1f8b702f208aa387e58f5bb8d136c1ae795585b70827e0b","nonce":"f7fb1c2c9a13c5fd8e5c7af8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"f7de3441ce327a00436c2e8a0100c527b10ab7cc1f187a20777616f9b8e7ef21ad21be03119d3740803e5daeda","nonce":"f7fb1c2c9a13c5fd8e5c7af9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"4c0c01eba1059e94bfadfa67958d7f828f60aa78c155ec88f79c2b7d1c6d13a5bf667ad0c9327aa54fd4916bc1","nonce":"f7fb1c2c9a13c5fd8e5c7ae6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"45c19412ee150570b70a5205fdf3e43a0b3c54edfbf6137d931d18a5c5b8f289901b8bb6b663834d22c7f105c5","nonce":"f7fb1c2c9a13c5fd8e5c7ae7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"3cf1047319c9836aa313cfe10496a9abf549b2f791e69c6a564c7357a5c887225f4e1fdbbe5d5c9a26311a1a31","nonce":"f7fb1c2c9a13c5fd8e5c7ae4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"300cf354090f996d7777e01032adedcc7a4d8f6b9bf7270521848c789e2bb755fffd23720b8f0ee6331b1b44cb","nonce":"f7fb1c2c9a13c5fd8e5c7ae5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"2e48c2bebbf757888e7e3c6637c98a45eb471dcd91df4594d0e92c21423a6ab29ebb3482ddfde10d2d127fbc8c","nonce":"f7fb1c2c9a13c5fd8e5c7ae2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"ed3064d3ea9c8633caed88dc5c43b1d1cecae128e94cedf8d94f26148fdbe345562218fb279ec77b6eba072347","nonce":"f7fb1c2c9a13c5fd8e5c7ae3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"e8596e5656fedca55d330c699cd3e747f2150767bd151d92eb931ce957f745925aa8bf774f0813bb06fccdfc11","nonce":"f7fb1c2c9a13c5fd8e5c7ae0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"530625e4b0dbe1be903ccde45f168b1029d3b66a7b3230d5a08abafc300583d94198689b3ed1cae9d70d5ad269","nonce":"f7fb1c2c9a13c5fd8e5c7ae1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"1f819d2011be0c854b1b8dc3c2c70c231b6187669695de052d4c5b62368f372e7326919cfdbd6516bb1aedec67","nonce":"f7fb1c2c9a13c5fd8e5c7aee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"b2d8f260ea663c88a1345ddd5afe23a0b60ca046f1c456da3a0ed6ebadde359dd3de1e59c66c3d0999a113dd9f","nonce":"f7fb1c2c9a13c5fd8e5c7aef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"bce38643203a86631928bd9ff7d582724660838b87e84b077cdb0c01f0004d9cc013190abfeb3803c5d0e0c54f","nonce":"f7fb1c2c9a13c5fd8e5c7aec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"bfe392ba8777b5a3c275839c145ecfdcb307339905c0fd166a91399b322ab151d0dd47d038e9e95f79545def8e","nonce":"f7fb1c2c9a13c5fd8e5c7aed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"a7e72fc696c0400066a0677d2b732784847c6d928fc8efd08402db8184cbe7e98f77bd0e2adb92015734593c1a","nonce":"f7fb1c2c9a13c5fd8e5c7aea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"595da6a633e77c0a7e853e207d591643c577681355943389176cbe9d8ce878eba898e1af72b7f1f3de24e2d60a","nonce":"f7fb1c2c9a13c5fd8e5c7aeb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"5d665e63d8309c84f9fea92b2e9f78810af9bf1830a0b12f6a42b920bf4bd87ad9d49fe42d0aefa1c8494b36c3","nonce":"f7fb1c2c9a13c5fd8e5c7ae8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"aceb5be69978bb80ca0b6d78bb55d8f2048b4832adc4854a8d6c14c861eaf6cde60d3f9d94a8304583a5a65087","nonce":"f7fb1c2c9a13c5fd8e5c7ae9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"9eab5efef06406ebdb546998d722c3348c3b527a67427a17570d3b374e4bf995086079ce7d2b19b21924aca856","nonce":"f7fb1c2c9a13c5fd8e5c7ad6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"5b7e5072a96c033086c476203308cd61566f5a2289f32fe3223b06c0ee3ca1c6a70585b0f09fdeecdb8a3afab7","nonce":"f7fb1c2c9a13c5fd8e5c7ad7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"4ffdebb0a750c3d34ddd3724666a37616ee4ae04f598f74bf3ebea3573e8d313f1bd3f94790328526908f6c1ef","nonce":"f7fb1c2c9a13c5fd8e5c7ad4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"2ae27b8d702263e626d866c74db236bbf3b63a115bbab00f5c92995a59ad6e9029f60962710ff2e799917c4bd0","nonce":"f7fb1c2c9a13c5fd8e5c7ad5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"4f5b4334a3896cc0900a24b37cc23a141ecf60ee07c140c4a6c782db838cbef490fe766e3457a00ce01fcf5f4e","nonce":"f7fb1c2c9a13c5fd8e5c7ad2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"e11288746358ff568486c50efdf70bd7ebda86ddb86d1b0c06d63dcbaa097792135bbaa23bed6865766fd63303","nonce":"f7fb1c2c9a13c5fd8e5c7ad3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"b015b335750e754a03cd1bef95353e534806c6ea47ed8a47eb9619d4fcf9b0c0f13c8314067923260f7130601c","nonce":"f7fb1c2c9a13c5fd8e5c7ad0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"6f133012e3cdeb157ae6104a89099ace0fbb4d2950216eff43fde7d8424024ec557513cceacfd22209f2ed93ed","nonce":"f7fb1c2c9a13c5fd8e5c7ad1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"7a6c407811f719c7d20aa05f78e8e99429a7b0c8cf8b980f9220d580d62903e00b91240fb712a99fbaaac0eb8a","nonce":"f7fb1c2c9a13c5fd8e5c7ade","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"4e599cf812b7cbb02f994396b1ea3a416655e6113e2f07ec0c576c390d8c25582cdf17060a228e0188b78a97e4","nonce":"f7fb1c2c9a13c5fd8e5c7adf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"d79e47784c4660eb0bb02ffd4ad033d6e00830207146f5804a6e004dbd148e19160a58e19c4047c0914c25a523","nonce":"f7fb1c2c9a13c5fd8e5c7adc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"9b089ccf6c1ac15cf5722501d1673a0ee14135a9c85d9bfa07814b379695120f68032d2f8b1515336c5f65e84f","nonce":"f7fb1c2c9a13c5fd8e5c7add","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"23ec4da16407f8be5cda19cd280dc89ec767bc39d09ccdab58e352f12c753c9fd06dd213e2448e159690bca5e2","nonce":"f7fb1c2c9a13c5fd8e5c7ada","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"5432d8a316f2b251b32adf4f84514269cfc19114e6b908bb1d2cbd5d5194e3d93254c3c10a2bb419bef4ca3920","nonce":"f7fb1c2c9a13c5fd8e5c7adb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"71531a8c0052a7139a56dd89c9aa831c35bcccc6285bd698a87ae2017cb2eca6a308cf5ee8e6325c9b766e3bd3","nonce":"f7fb1c2c9a13c5fd8e5c7ad8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"01e4cd8dc138caeef99632b722e2dae11b6ff80ebe00278130485f59d8f81c3983205c8d145ec20e8f7432f00b","nonce":"f7fb1c2c9a13c5fd8e5c7ad9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"5148b4091e0ebe2c2762fea9ddbfbfc1ac1e3eb635f32b23226c6335cb79e893744741ac4a48bf43559f0abe03","nonce":"f7fb1c2c9a13c5fd8e5c7ac6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"b3fe2f0862a5388ad9ee39c891edbf41259c96c44711bf2383218cbc0a882892c4a22b34af4e013facbf1bbf5d","nonce":"f7fb1c2c9a13c5fd8e5c7ac7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"ebd720afac1de25e5f3bb9156462e471394b83bc7b77a959adc996043d6d85e1c4c770e42cb88ab4f45a08b63e","nonce":"f7fb1c2c9a13c5fd8e5c7ac4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"2813c491f7fea85a4ab3e62126d851291eff950f322ea492a028303718802fb4e7cdcacb2cecc6dfda4d4f4fe7","nonce":"f7fb1c2c9a13c5fd8e5c7ac5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"808190553ec142c0600261e2018ff59b1fb4a5a3b79ed1c7ccb79c8c800c5c57b029bdcfd274d91396e724c939","nonce":"f7fb1c2c9a13c5fd8e5c7ac2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"744b1b84634182d3d629a7a8c63541249269b409c8236c0c506fdb0e642211b36d3d65db395e60f2b1e16e5985","nonce":"f7fb1c2c9a13c5fd8e5c7ac3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"9655599ece880e5590cbcca9e15fb51e6ed6f63f053a161afb17da346983d6e13c49b6bb52642831f82b31ba6e","nonce":"f7fb1c2c9a13c5fd8e5c7ac0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"aacdceab396d7347fc9e71f94dc3fb504f4b814f8a25d3f5372023a25dee8252503cc52344b6d776a25ba61823","nonce":"f7fb1c2c9a13c5fd8e5c7ac1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"6824478fd564cf16063a30639f711299be881536a5e8e43b2412c68afde90097c7ce4c70a15ab0ccd3ca4bdead","nonce":"f7fb1c2c9a13c5fd8e5c7ace","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"3570f4d56299e6c8e09c50b3433fc837f95709f294a77f267eb4c1d34881f2ef8453a5bc24be65aa202618c3b9","nonce":"f7fb1c2c9a13c5fd8e5c7acf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"ce07215fd3120647f89413a08a716e31319ebb6f0ceeef8ea296bc1fd5cd8d8c2211490ea4f3f0dfae11097fcf","nonce":"f7fb1c2c9a13c5fd8e5c7acc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"1dc507a6d3f99317d795111c3d14c8893a7b545b48d399407fc121ce9064d9d903c7575d6c8598792e655355e1","nonce":"f7fb1c2c9a13c5fd8e5c7acd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"9944b9e54b7a6e73ca35601c2088801d5e4896da7356994cc17f6d004aac363483a23158a73363926663f1c18e","nonce":"f7fb1c2c9a13c5fd8e5c7aca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"7f8209f4a1f4a8fb642b8e717831ac82a3a99b19445d0f58f5b35447cea428066a242767ce7af6dd4ab72e87f7","nonce":"f7fb1c2c9a13c5fd8e5c7acb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"e3b2862937f3af2f068ccbbf870d225066ea6deca5791c302063f1e1c357f3a44928c403aebc3771271b74bf7c","nonce":"f7fb1c2c9a13c5fd8e5c7ac8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"5a205f8122607dbd95e5b14199e45d52457124c0821e202d7603786ad4d645feb96a855dc54fd278e404a38b86","nonce":"f7fb1c2c9a13c5fd8e5c7ac9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"77627bbdb39c3521a04862c79004d27189b37ec5dba0a7a959ec94d2b819224635056a870781e37454b86db157","nonce":"f7fb1c2c9a13c5fd8e5c7a36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"56203e1fc0578e9e9cd7bf79c69e111114d9f8f7d2c026347c6a6834d22a5e7e07e4cd6832a02747350fbdfc7e","nonce":"f7fb1c2c9a13c5fd8e5c7a37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"0c6fe72e187004ac21bc98a542428b9ff706ad06b6c46bbac2c636c1ab41fe5491eef137ff618341c84048be6a","nonce":"f7fb1c2c9a13c5fd8e5c7a34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"87dfd27388e096b9d713d19729a999290a1d0d96c8cdc5b74ab7ea0a461b96984ee5739ad6eb30c10f022660fe","nonce":"f7fb1c2c9a13c5fd8e5c7a35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"edba309f282ef03b39ca29b97e2cae2b2de4c1a0e1b0801e89208835963fe1d64c0940cb6d5a3040c6fd372de5","nonce":"f7fb1c2c9a13c5fd8e5c7a32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"eed0a6f1fd8b0d41b7a178efbea96778e8774b277fddcdd7ed79dd7fa1c1d35ee092b5b961fd666744261b9b30","nonce":"f7fb1c2c9a13c5fd8e5c7a33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"2e69d4c0fd043b0f19f4ed9a6301ccd97236d8b305db83b49dedcd92648a08f9e8e41247e0b806578861184278","nonce":"f7fb1c2c9a13c5fd8e5c7a30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"2d86c18291cdfccaba8d4d37d577df4691228d49d2fbbfa3b790249115a99fa4d6473dd372458a72c9b1ce5fc0","nonce":"f7fb1c2c9a13c5fd8e5c7a31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"031cdbf578471cc7bd33ff7a15c230ed7a62df2d5aa615e2bf42adb5c5890e714f2210226619c3949e4de057d0","nonce":"f7fb1c2c9a13c5fd8e5c7a3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"7fc4e60c4b7f3eeb1e1c014f08b0ce7d97251c91d25c269d60b1ef51c8873950cde64260dc39f9de5588a3935e","nonce":"f7fb1c2c9a13c5fd8e5c7a3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"a0ecf4bf435f45047088325e82ca1033692fa378476763ad32c39784d9e874f53853e1f081f56b71a7f1e5d6c9","nonce":"f7fb1c2c9a13c5fd8e5c7a3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"ca736f0334688c7a508ce7feee8dbe2487233572f26a84077ae342c605f532c262d99982bfe0d48aee1578dd23","nonce":"f7fb1c2c9a13c5fd8e5c7a3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"91295f1600758fe3b565e9ec67a6c2695266b7ce8478febcc1830dacd2de571d2ec6c2d9358afbf28661cb1edd","nonce":"f7fb1c2c9a13c5fd8e5c7a3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"8e5dae0cd4a465c0be3fb3d20a8cd71f38dcff167ab6a0c245d2ae1c532495f1610dc80d9317b47106a59dacde","nonce":"f7fb1c2c9a13c5fd8e5c7a3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"35d74d8a48579d4a5b2ba24fc656a6639fe66d18435c0cb9bb4e35e54d3f69ce64f3244d203b43660cb59c0dd7","nonce":"f7fb1c2c9a13c5fd8e5c7a38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"73691289adf1bc0bbeb75ab013953ec165aeafc378058b56cf630f910145a332624c187bd267147907f674e0e6","nonce":"f7fb1c2c9a13c5fd8e5c7a39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"16b1a9191940938038af6dd02af82184e48b778410e23ed7ea12d005c3b80ac861acbb445b65e93eac262ee4ea","nonce":"f7fb1c2c9a13c5fd8e5c7a26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"1a399fa7ea110e2e083edbe06a3e7e95e3d6c440330f5a2e8f222993a9b4289138a72131fd21579fbd39a72830","nonce":"f7fb1c2c9a13c5fd8e5c7a27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"46b3e11ce1c601fd5b4f6d5d071e31e889b7cec5c35197587eabf64d1efb0ac74932444cd3942c0b54de55e8c8","nonce":"f7fb1c2c9a13c5fd8e5c7a24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"3d010f3ddb34571f0b47fb98ead0299f30453a076d192c5cad868db2a6045f0488b0befacf1942a4a5037d3485","nonce":"f7fb1c2c9a13c5fd8e5c7a25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"882c8d0b487fc6c7819ae9e54418489dca62b65e36cca05ac160356f7b0a593636218f709431fd6e745a963817","nonce":"f7fb1c2c9a13c5fd8e5c7a22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"de6473d03eec0e09c15091cdef9fa5b9b7ee16098e23bb0c7575d5b94a75ea6c6ac253d36bbf5879dac5a78bb6","nonce":"f7fb1c2c9a13c5fd8e5c7a23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"69e6a4fcfc321a706d64d7e0f8da8fc4fecdbf2ecab1fe6eb1be41f71f1e7bf6571bc351f7aaa507485ed0e1e6","nonce":"f7fb1c2c9a13c5fd8e5c7a20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"25b779df19624e281bfe60467b02becd752b1b75c16e70bd9e1459ce1d1149934cba9db79b110289a2c03e1b9b","nonce":"f7fb1c2c9a13c5fd8e5c7a21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"b7288db07d4bea551bb797eefcbdc53a7c39da754ea36ed29c7f8341ee4b02580537b5e052d397bc7a3a0c55f7","nonce":"f7fb1c2c9a13c5fd8e5c7a2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"40a4f765d62fb4b807809120236ab819c4c69a880a139dc7210fed81e33068dc7d80d69e13510c1c3d96e862cd","nonce":"f7fb1c2c9a13c5fd8e5c7a2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"cc9c979863c855f0ad2c23bca734ea1f20c740c5b455f8e3f3b3f122fcda81aa128178ae7f88a10ec2c1266c8f","nonce":"f7fb1c2c9a13c5fd8e5c7a2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"a3c423e3462901b40f051a2fa9d3e5595d003f623f56c754da58d3ca11c494fe22d045e8e501ff8744f78861c0","nonce":"f7fb1c2c9a13c5fd8e5c7a2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"deb41c997a4cf5c31d4fffeb711e0be48c1aa91365ac55fb62e1fbe83f2dc326963ea607e71e00ebba3de68d89","nonce":"f7fb1c2c9a13c5fd8e5c7a2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"c6822697fe100c5cde5d06563e9c2680b37c88f6f1bdfb556fb85d62cdf6b99fe0cc20ed9d0ed8619258fd94e3","nonce":"f7fb1c2c9a13c5fd8e5c7a2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"81b455d03e11fc7399ae2f28475bd4688e6a8811219bf0b14b728658828fabe8a232189892a9947614ff16c82b","nonce":"f7fb1c2c9a13c5fd8e5c7a28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"4bb1474f6ee9dd990f3d155d858c9e79372ff1dcd51649c3faadd1f8cdd649e99e9073e6f7bc296baefec83049","nonce":"f7fb1c2c9a13c5fd8e5c7a29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"7291a3def6deb0f38f2d3589f96c2bf859558b1b926965c95621e78694b10495f2289b12c57fbae8bf0c7561bc","nonce":"f7fb1c2c9a13c5fd8e5c7a16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"3120edc4c856f652b2c49500e9d5b709fbf49663895bdee2fd1d2ab5116a3b98018a97fa0283d8bea3efe27344","nonce":"f7fb1c2c9a13c5fd8e5c7a17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"d0378269f7dc53155176e1c64c8d5723ea2096989b319d45fdeedd769ae0a034032cb33669c4fe528aba45263f","nonce":"f7fb1c2c9a13c5fd8e5c7a14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"9503a8b80b946bf82f5be9e533108f918a73d7c565c82c1ef19dfbdc88e6eeff2a2bd2872199fd8d940ed025c5","nonce":"f7fb1c2c9a13c5fd8e5c7a15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"a0cad660696b4349c2382f02248ccf2a9f410e32b7a177b1803bc92dbb2008f8c436d47f437ddc0c14f03cc6e1","nonce":"f7fb1c2c9a13c5fd8e5c7a12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"c096f00caac8e0288ed5c1452db02d79822718558e578ffe255098adbb262f58e8d47c05478bef0a6910b6aa93","nonce":"f7fb1c2c9a13c5fd8e5c7a13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"329b2a4d1639b09a6a9ae37ccab09b92aeebc7e6b326e640d5593d080adeb6ce6f8002bfccadb98814c1e13c57","nonce":"f7fb1c2c9a13c5fd8e5c7a10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"4b30880d843fe305fcec2c28a8f4d6c39c73e6e3bc06ec6210a53b053ac701fd78285c788b0fbe1047ab18c5c3","nonce":"f7fb1c2c9a13c5fd8e5c7a11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"02f3746b2680154c6866759afa507d3c6ec6a8452a2c54843e7f3995841f4fc781e951212e02ee5ede5159d88f","nonce":"f7fb1c2c9a13c5fd8e5c7a1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"19120c5fda163701c1fc869eb3415afae83abd4b1dfb197696978a330e6136f390a24a1a84097291ea8b270ff6","nonce":"f7fb1c2c9a13c5fd8e5c7a1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"98d51a1b4bb863c89331dc3402bce26a0cb9ade19e67ce5b75c714977339eee0fe048b39165863573c5312d0cb","nonce":"f7fb1c2c9a13c5fd8e5c7a1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"f3292a0742f0656bc0dda4157ff0ec54fc0453172f275046e69676b5434d1656e7e7594035fef056487c576555","nonce":"f7fb1c2c9a13c5fd8e5c7a1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"24c6b8d33973e9804160dc1624a5d373ee501ad7574bcec4c3e5a1c3ac2327c100111d34357320be765be753e8","nonce":"f7fb1c2c9a13c5fd8e5c7a1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"64ca9484ea6aa9e883d97050583f505c576ec385a451069e762051ca2d324f1c7eb86251a195a69dc70db35b5c","nonce":"f7fb1c2c9a13c5fd8e5c7a1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"229a6a8eedb5db3c3a641b82b727a0d78fa8ff8db94f622b1073a849938ca4dbe2cd2d7d8bf6001922ace549fd","nonce":"f7fb1c2c9a13c5fd8e5c7a18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"7cdfcad2a02e2ec8eddc9609c22f910d93686607ae8778e72c8f74a826d7db0a327bfe0afd3d70a6d0ef165de5","nonce":"f7fb1c2c9a13c5fd8e5c7a19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"e8c1fe53284901d16080199f253e4fdf07db1125568a048ba855316d265796fedfd03ab43acd347382130a4560","nonce":"f7fb1c2c9a13c5fd8e5c7a06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"82b2c06f457514f54ec16ddaf7b0613a2ddd4b80695a99d3a10820c8c22f4559e5ef36b087809b4c8c7b13af82","nonce":"f7fb1c2c9a13c5fd8e5c7a07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"34dee4036b41c434da8f88f2729ed7b9dcc54f9720b679856a86d28cddc392cbead7072705f744449e984f1f31","nonce":"f7fb1c2c9a13c5fd8e5c7a04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"aba1c3a56538cb4817461154604c0295fe43668a40c471e3e961a81813b9b43d876b48d02b81e1876ece49102e","nonce":"f7fb1c2c9a13c5fd8e5c7a05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"8a896b54049d45bbf4bbdde88615fcaf54dbaee6c8b354e428a936c39b12cf275364ddcbb7fca4ee151a330291","nonce":"f7fb1c2c9a13c5fd8e5c7a02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"b6af90855767b772032a265c1f62104ca662a2252e1978665ece8b88f16e7a069a9ee121c1b1ec0dd88db56321","nonce":"f7fb1c2c9a13c5fd8e5c7a03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"f68252f264189420b898fb8692d2d2d1c5a2cb9761277790bd2f5fb4cd1deba827a9e4db43104862094809d27a","nonce":"f7fb1c2c9a13c5fd8e5c7a00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"e83bb896ba44cff8af199b523d535327f5ed4e7786877bd12044b4b61a1e2d87a471962dfe4ff25bf014ed5ad5","nonce":"f7fb1c2c9a13c5fd8e5c7a01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"e2f1aa3c217d4503e11ba39c05ec624ea117bebf2286e0ce1b68fdd79adbfbb853c2e7d5dcad3c3547cbc76542","nonce":"f7fb1c2c9a13c5fd8e5c7a0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"f68081b39e296feb94af0e4876f4762e0d251758aea0e292cca99c31608c7ca40d1f73df4c5e38a1a6ff671347","nonce":"f7fb1c2c9a13c5fd8e5c7a0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"f7f1e4e04d08415370a5756c6adf62abb54732d0920df216d22d8522737b0d3ffb57eabe901d2a5f7621b0352a","nonce":"f7fb1c2c9a13c5fd8e5c7a0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"99fd95a5f841e19389886ef9fc9f183561e40c75f24822d975dd0ca06774bbe239e56d962bca08defea65c6bd5","nonce":"f7fb1c2c9a13c5fd8e5c7a0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"4cedc9bfb4e39c3c59509b7ad465cc572a0cac6cfbe4a7fad036f8495a44bb21ecfd2753893f29141c34578e71","nonce":"f7fb1c2c9a13c5fd8e5c7a0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"3b02e170b4e27c1f8733db553940192a1f45ab982a9a0f9aa3bfc16dae75c0c744619886098412e88a0421d7a0","nonce":"f7fb1c2c9a13c5fd8e5c7a0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"2453453120a5f87d204ff6dcc05cc639e55bd1d79ffc2af195b0a0735cd36554ae19d0b09cc1d5ab389d3f0130","nonce":"f7fb1c2c9a13c5fd8e5c7a08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"f2b93e4aa6f82c9f5938a4bed647e9825fed5b651f14aac4eac28e03a2c2e65a07f1a598c988df21ea79a74c42","nonce":"f7fb1c2c9a13c5fd8e5c7a09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"0c69e75b78071a7e68d19b8ca64adc53543b8e96587215823976c68b8b4287a003c13e584a1ff3d175ba9fd435","nonce":"f7fb1c2c9a13c5fd8e5c7a76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"c7cf7ee78c85561f11a2f0b0d334fa49151f8163b30eba7df57461fb97d1c20184c6ccd6518c1ff37b56818f7d","nonce":"f7fb1c2c9a13c5fd8e5c7a77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"fee46cd65d4fca0322eff9074259b4c8c84b7803d72958a1392171b118a9ced936b6473ed0ddf3ea4263c00129","nonce":"f7fb1c2c9a13c5fd8e5c7a74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"0f3132c1f0462c0da347a3a12e87ca08ac568d18f820b07f9218346eeee61ab2932d422afa1cac22b5812d74c7","nonce":"f7fb1c2c9a13c5fd8e5c7a75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"9674d7d425a211b798697898889b0daa6abd81b60d7447b353b628f72cada35cc33ec861f92d213c7371315186","nonce":"f7fb1c2c9a13c5fd8e5c7a72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"14ed8dee0e4f63fc801bea325c05aea591fa9e0490319576b87ee0f3896b4d1cfb3938e3b4bbe5e5de3274191c","nonce":"f7fb1c2c9a13c5fd8e5c7a73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"25a45341e40e2a33ff5fc304c34c4c58cd706c45f10233d045aff736a8a76821bb39d2a339d17fcba6522b1cb3","nonce":"f7fb1c2c9a13c5fd8e5c7a70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"53d994b5d1d41d24ccdfaaba5a29c62c0cbb89d045e51848fedbf5bc29078cd1613562837a46d7c5c914168ab1","nonce":"f7fb1c2c9a13c5fd8e5c7a71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"c32e89973637abef27f0d98658c43faac58c4e48e6b9a592f3830f79d1d9ed8403a47bb60f6de02dc64936f646","nonce":"f7fb1c2c9a13c5fd8e5c7a7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"227a07cc9846ee66cb5a07d2cacd71edc059caef22e2b31f0c9bc76a2e83a7dc4babf63bb29f8bfbea483a17f9","nonce":"f7fb1c2c9a13c5fd8e5c7a7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"23cfe901a331ec7e40ba3c0795572f14feee8955ce50a2fcf271e90fb67d7aa9b82749472570257ef86de5ca71","nonce":"f7fb1c2c9a13c5fd8e5c7a7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"af7fb8a88d7254297e9c466d9f70a59c88f13853e3671ed8c4815b04f65be191955fde4c9a27cc7ed00f089987","nonce":"f7fb1c2c9a13c5fd8e5c7a7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"143f9a1c5c976557c0d526f4381928f7871ae24d5cb127f29253037579ca5c40cd992c4d90d47652ded61ebee5","nonce":"f7fb1c2c9a13c5fd8e5c7a7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"22034b89df3c28415cfc0d3d12880666d67998f64727ab943e021d02c85396c1108c3c4f6cf10086b023d215eb","nonce":"f7fb1c2c9a13c5fd8e5c7a7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"b2af7413b826e6868bb8a8fcdacae02fd9ebd4cf686264428a6628dc4737c629a90cead4e31588e8974d3394c8","nonce":"f7fb1c2c9a13c5fd8e5c7a78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"0817abddfbd6f1eb9db262ae7d132b5e5d313d083465d18efc2a69a697338be649e113a876ee06ab6985d825ef","nonce":"f7fb1c2c9a13c5fd8e5c7a79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"54a6ae9104180f211780561e4d342a5cd87dd847338605460249e9b8fca90aff933b051b8cd0fd07e80eac4b69","nonce":"f7fb1c2c9a13c5fd8e5c7a66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"72ac378039bd0b8f14f5862db023f6cd32bdceaa7ffb6e57f0a48d3cc1c54b2b27622d89ec9bf38e21006002ee","nonce":"f7fb1c2c9a13c5fd8e5c7a67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"e08e091ada8f8ba1e7272b7f0d62c5b482f06a5e798db4310abff1ae763fda8dac01b80d69506d67c26e9e1a10","nonce":"f7fb1c2c9a13c5fd8e5c7a64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"8881656cb60ed8fc509d731b29352f31741382485bb974c1d5a6a51ac978caff9762ab981b4acb1a20e6d29020","nonce":"f7fb1c2c9a13c5fd8e5c7a65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"252a38dd699b4fc8c7711b4341f108bce268ce67c49c6a9c552dc91f9d5ce52d1af7f5ca47c7cc03d2436b4752","nonce":"f7fb1c2c9a13c5fd8e5c7a62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"238cb4614b76467d53976b3169d85ffb4d7a3c440d7f41b0fe8d3aea992dd9bc4f02bffdc794edca1eb7fb1f6f","nonce":"f7fb1c2c9a13c5fd8e5c7a63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"50e62a20b64ba697d50799737ae9d85c7b8e830ba2b2ca877d66b8e6b1ff26406c720c156b529ab1d5da41f859","nonce":"f7fb1c2c9a13c5fd8e5c7a60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"4f18737d0a0de52aacc69f6f6fb82c7ca5f3a8ad4094d108434541e59e5c7f02876459cf0162f5f725381cbaec","nonce":"f7fb1c2c9a13c5fd8e5c7a61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"746fdc5e410136f1e12409db5b6bbbd91448d40c977da5c2f073cadf7850529319db321924057d98bcd4770aa8","nonce":"f7fb1c2c9a13c5fd8e5c7a6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"52f90a1e09e4bcd0478a60fedaecb379d0348f44d49594f0fa50303b08be7256eb548b5d7bcead1e6101ffa50e","nonce":"f7fb1c2c9a13c5fd8e5c7a6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"51b35f98acacc29b10dca4a377014f4bafe38004a6697cde7091e106e2e057787b82a7ecd46651eac743db1b9f","nonce":"f7fb1c2c9a13c5fd8e5c7a6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"02e1e8e982796dbb38910cd821d90c55f5aa29970b0a78c0099e0de2b4bedfca288b4ad46c5f212c20eb5445bc","nonce":"f7fb1c2c9a13c5fd8e5c7a6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"ab848c3b85bcda3f3a2a6cd1d5062942c43abb2d78d796b1ecf1ad0a44e1cecb786fc76ede6fc01adc9a8ffc44","nonce":"f7fb1c2c9a13c5fd8e5c7a6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"c7be201ccafa7f18b48544d9fb2d90c2182335a618f475168dd6d59a33c620a33d27dd29ead93cfabf93abeb0e","nonce":"f7fb1c2c9a13c5fd8e5c7a6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"46427200d057f4eac8cffd2b0ba308e6b0c3f544f1f3e7877ffe07be669302d05b3e072754c6c6fc70a717f77b","nonce":"f7fb1c2c9a13c5fd8e5c7a68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"60211b3525d844d9d80c52f61eeee677284d9b09995b1f86bbf1b65232fd53ad17c038edb9c93cd46ab2ea834b","nonce":"f7fb1c2c9a13c5fd8e5c7a69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"55a7b13b2fe590f8a336c1a81ea09bea7d8ab62a1dff1587dd87c5f69e029acdd037ea1dee845191d09b1b464a","nonce":"f7fb1c2c9a13c5fd8e5c7a56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"1979d5695b6542167565dcd40baef1f8178ddc511e45388e1359745be952caf98440d9d3026d7bb15a95ae3107","nonce":"f7fb1c2c9a13c5fd8e5c7a57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"fb3bc8c4f1a4582a3972ef5026213303fd2d73e26208e461ae8b5eebe824fe1f6c4f7a4f587033aa0726492216","nonce":"f7fb1c2c9a13c5fd8e5c7a54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"b13817346020c94f9c5a6face3748e8873d89f66feb926d9d2cea8f705239af6b206278b277669bf836261edd8","nonce":"f7fb1c2c9a13c5fd8e5c7a55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"07f08cd7b0411ebfebb5f5d08dc5e0a03f4787771ba3aaddc28175c835b9615f955945c05b089317e7d2aceb87","nonce":"f7fb1c2c9a13c5fd8e5c7a52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"5965ce755d4f85f8d5b5230619758dcb0d283105b5fc0cae0cac5aff8959790fd218004f97d7b833dbda5914d8","nonce":"f7fb1c2c9a13c5fd8e5c7a53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"0a20f3865b41ebfad1f6d8929710390603182e7ce3bb2b0be25b712cc745fc012432f112c0782b2a5c168dfac1","nonce":"f7fb1c2c9a13c5fd8e5c7a50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"2e5f88fff245e1e5c9a9f2444edc6519ff8b0de825e853503f21a14097e0f069f42cced53df0baea9b83d85067","nonce":"f7fb1c2c9a13c5fd8e5c7a51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"089f3433aabc9395ba2d45a62e313c9f00d6416ec5e0b0a0d59f1396c789767095a29533befd82152e161d1a72","nonce":"f7fb1c2c9a13c5fd8e5c7a5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"bb9a9b5c2a74e0f2391a7c08680e9856afc91d30d216be7a9b90e5903a057b4b88993693eeb26d47a1c4e6f384","nonce":"f7fb1c2c9a13c5fd8e5c7a5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"0c49ef3b17980fcb6810c02fa2c5f59faf0eb733db0735df99a4e68859d0a6cbfb7568217cd2208736f63e19d7","nonce":"f7fb1c2c9a13c5fd8e5c7a5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"5d7af4615634f454299cd48e858e463d316ee1afcf9ce342acc27f7ee235ef54093ffa1794a4fc3e7d790a3484","nonce":"f7fb1c2c9a13c5fd8e5c7a5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"33b1e1f4f7bd9f1a84a6387ffb511da4857378fa55e89b7b65e59c1d62abbe2daaf99fd25b36b390db5abb7c3e","nonce":"f7fb1c2c9a13c5fd8e5c7a5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"945d9b88bf37200eb7f0ec94fd927d05d7cb2fe3cb30d13bd6eb24b287a7fb9d7b1bddb61f7515e6b2b0cbf3f7","nonce":"f7fb1c2c9a13c5fd8e5c7a5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"a06241b553666c836106543429e6d37d6312ad5215d25ca689b4d84763a9e94ccadbce18f0a466feeede9cc368","nonce":"f7fb1c2c9a13c5fd8e5c7a58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"b47ec75cfeef1d3c0560fbaeab9734f441c443f25981a23d22221aa3b54936e5c1a5fd1d60acb7ef555981ece2","nonce":"f7fb1c2c9a13c5fd8e5c7a59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"c49d0e92f077d5dc40f1ee0557c85fcf0741bc0061de3f15cf7e4867c5ff1e9381f366c9a6d5694605d6718004","nonce":"f7fb1c2c9a13c5fd8e5c7a46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"2a67843fd4936d2ec31d1f1d0dc0df13206ab334d48f4362ec9c16bedda0a4327672c34666ae3ca81c3940a599","nonce":"f7fb1c2c9a13c5fd8e5c7a47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"bf3244e616daeccf9cac8ed79d07456b24a3a041964baf39815b50ae7e5d23d5244f2c14d84e371957e059c619","nonce":"f7fb1c2c9a13c5fd8e5c7a44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"38fb39828ecbe6f1231d61f07f0cae727e5566a0c1b519f38dbf5878640ba20f2069952f4fd912d97f49c83475","nonce":"f7fb1c2c9a13c5fd8e5c7a45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"68f79debbbb549a1dbedee266346427082d54315344e8a55f2f111d24a0604ae73bac6b5ed21805ad737ab7eae","nonce":"f7fb1c2c9a13c5fd8e5c7a42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"808af4bfc90fdbdcaab1b1921403f1e301afb46c5c8b66388674f800727260c13bbb7b65766948173fd94e80fa","nonce":"f7fb1c2c9a13c5fd8e5c7a43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"abfc30c1d3b3a40bee0d84ddeca4122f7658780ec4f7262a161bb6abe3fa0a16d9b61724cbfa24ee1f077344fd","nonce":"f7fb1c2c9a13c5fd8e5c7a40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"23ec490fa4eac723b512adbee2f3a1bc80c6eecbad19c47eae605a80701e5a2343e7b0d6093b0077a4c8d87ce1","nonce":"f7fb1c2c9a13c5fd8e5c7a41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"ae14177d61bdfaae4b38884aa159df8af45894d7b6b8308aa82e8ab04f32886986f7cf32cc8de92b0b1e056e38","nonce":"f7fb1c2c9a13c5fd8e5c7a4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"d14036d73867f19ce5d276c312e1c9736cf93d6b05a96e2eccb633bf27dfdc45ab0a59683e1a236e4c588f31df","nonce":"f7fb1c2c9a13c5fd8e5c7a4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"ca72e2928eda321484c84c87659439e025f785ca3af41c600586eb10e12713efdbd1a8a7460ac6f778173feff6","nonce":"f7fb1c2c9a13c5fd8e5c7a4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"02cc485905fbad796d441a1bc07bd440d301e0393a34a4d28d23dcd1cf70c3e116b603600e203ffae88be44dcf","nonce":"f7fb1c2c9a13c5fd8e5c7a4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"0943fd2bd5f14028d06875228b1b215d46413e1ac5c0654b8401b7c71525220e9978bf71f1f95adab3d74d03a4","nonce":"f7fb1c2c9a13c5fd8e5c7a4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"8a30c185a8251c5de04a5c3eaaea65517026d6ac07cd30700dfeec2ebf7f007232d26536638a70d3d90ae211b1","nonce":"f7fb1c2c9a13c5fd8e5c7a4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"e4f21df33b678d92913e719f7748ddeb01d505de57bee87c060543bc76e749d72d07d1fb04ece74f0431bc0598","nonce":"f7fb1c2c9a13c5fd8e5c7a48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"0c3d124ab6785da819846e32fc27b7554d1fea1d26ce2dc26e1a693dd7e016d51495d08817797258d3cba5e9cd","nonce":"f7fb1c2c9a13c5fd8e5c7a49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"4333ea695ea28b188f44060bbe8358a0c00b953a16911cf430843511eeeafbcac7537a6405be9b8b40e76fba65","nonce":"f7fb1c2c9a13c5fd8e5c7bb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"f22324dcf072e206156be29e76820fefac943468e1e1a511d99b967cf1994b01"},{"exporter_context":"00","L":32,"exported_value":"785f3dd5cb3a99bbc76502a0f36856e1f5e88afe22853154333f6bf28672f9b8"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"30d788b5e977debf0b8b51c34bd9514116ac7e1b494f6efd44080c02add02809"}]},{"mode":1,"kem_id":32,"kdf_id":1,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"8eef790fad795e48041b5abc031e785418cc736a0f2ffe49744a1257e3ee3c11","ikmE":"a898eec077b574f86a1bb52899ac760912b39e552076d41067e5f30650da0cbf","skRm":"25fa61380093b84d96b13d6e2d6b5d0dd9d182bc0b54c8770581287014370052","skEm":"58378b622e94053c3c0e3f4b416365ccb7bfe06b144b599ce23386d13bad3168","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"74a556a4fda89ff0db891cb66775d6c9d9b4e3e23bd9714db2124c5d23f0b155","pkEm":"d9ded3e1e50f70c474b4ebb64b4b9c3d711b5000918c88a1b01ea0bfc611ef25","enc":"d9ded3e1e50f70c474b4ebb64b4b9c3d711b5000918c88a1b01ea0bfc611ef25","shared_secret":"907709a95470c19f1338ad5f6483e3bc5d6f77a4efb94bf1965e4cb0d26652c8","key_schedule_context":"016870c4c76ca38ae43efbec0f2377d109499d7ce73f4a9e1ec37f21d3d063b97cb69c5718a60cc5876c358d3f7fc31ddb598503f67be58ea1e798c0bb19eb9796","secret":"fd51da955e44c844126ed9e67aabed4c03530e702c94d9bef0236a0832415326","key":"6db9b0f5e6b99a4f3b2379d0aa26b7557b2d60f6565382222e34fbd807b882a2","base_nonce":"811bc3b560eddafde5ad6ed4","exporter_secret":"afa67deee5056ed230df6dabb629bf5c9535b1bbf4eaff3b9532f00b2c89a15f","encryptions":[{"aad":"436f756e742d30","ciphertext":"baeb454095d2218f4cfdc59df314ac4df92edd8e66b16a4d5913bfdf3eeaf305380c0368bf719ef31745f5b84e","nonce":"811bc3b560eddafde5ad6ed4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"f798b121acecfe88fd3ed454e70b0a6386ebc735e9cc702d1e9367278278c259dbaab86ec70083c08806f42cb7","nonce":"811bc3b560eddafde5ad6ed5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"4543b32f9d2ecb0e983551cf3ef53c3f93c779553f1451ef09731edfb466f7046a189e585177520ca488c86a28","nonce":"811bc3b560eddafde5ad6ed6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"cdd792b02b6a46993663bf804fd3ab7846c71446607a55f4b3e5e0d5b3a0d1230207eb79be7576696802de7ca5","nonce":"811bc3b560eddafde5ad6ed7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"0af1c28bb8d92d7b520db655518c74a3b32cd86aeb484274ddbf82c70134604a9da5b6e52352a498ec1cae961d","nonce":"811bc3b560eddafde5ad6ed0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"9ed0586b1284d09cf8388c881ba017bd89b44561eaed1fb1a9825fee67adffb3e0f172aa814b65e10205803b37","nonce":"811bc3b560eddafde5ad6ed1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"53a4edf69b22ee9c48d4806a51b4469ed6878e5fde13672fad0015649f0c6519afd88e7e10f1ef6b38d5bd0e32","nonce":"811bc3b560eddafde5ad6ed2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"c527d08c1032dac10b5796902b2e7524f8314e57b2a7b04c003bcda135e36e4749844a901d7f242a521571872d","nonce":"811bc3b560eddafde5ad6ed3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"c8b4be55e735241a35431e06454ac03829d9147c3871991e70d22f9ab92b4d2796638c38940beba00270550a91","nonce":"811bc3b560eddafde5ad6edc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"fad48fd19db92c967ad51624ec078c1e4554e328f479309edb513e2cf4e02e27c3874caaacf729aefaa9fd4c31","nonce":"811bc3b560eddafde5ad6edd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"6b2c8502f3e4550279d9ee4356fd0af321095baef6d8fce9f3fc77d4c38cfebbc19e73602d2a2a1c4b6bff769a","nonce":"811bc3b560eddafde5ad6ede","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"e31f974b47deed1808f914ebb1312973654d18dcb12a00e2423e6b19c7519be7276aec90183aaa9f799cd9090c","nonce":"811bc3b560eddafde5ad6edf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"d1862c3a3d7620e684a91d5467c7ffde1877e4616c0f62bafe95fc3b32a61ce94987acc1ba0c0808d5481ca7b6","nonce":"811bc3b560eddafde5ad6ed8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"1de2b2cd760b428e935b6bcfadf81790d71931902773e23fde1f5b13e8557e6541ff4334549ed69bb662547e1f","nonce":"811bc3b560eddafde5ad6ed9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"23862b6af839ddf42027b1e66b9ce06562b7e3bd13a6ce8d4d9b64c2e88c8c96a90b37524d786dc92911c08525","nonce":"811bc3b560eddafde5ad6eda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"ff65249fc39891e2b6041856285d48f3801f9f178ea18baa633a77d238104107236f65d4bc7b4c9f3c577f4bb0","nonce":"811bc3b560eddafde5ad6edb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"028463c6529caedf23c49d46d35781a0537bbbaa76311449c8f0a468e7a2277be1ebe1c3344130e1d41fb0c6fa","nonce":"811bc3b560eddafde5ad6ec4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"b90a7bd434109191250496b6f924355f7c53744ae4ce18bddf2a58e87abaab65d3b63c0a871b095bef00ace121","nonce":"811bc3b560eddafde5ad6ec5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"15244600573712b501b883f16bc69c676090343f2b509db628acc7852358f4aacff8e234563da3f1e4f5f16dad","nonce":"811bc3b560eddafde5ad6ec6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"37ad6490dbfb6ca40fe93ce2205b92916e91d36fbd1f988682a8f8cbe57c7bf480302261f8d10167a57c0a38a4","nonce":"811bc3b560eddafde5ad6ec7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"f5398a68521e8580dfee04ade612c725a44907b4b40f069bb05f3ab312e541438a6221689f56dc91e127c5f265","nonce":"811bc3b560eddafde5ad6ec0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"add73c37ae873541fa6930ab010b84b8cb3a721757115ef7c42e5853782f346549915f0d90e307dfe27cc11c23","nonce":"811bc3b560eddafde5ad6ec1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"61aadf97a85fef26ef6ba435dc709c44e795339422fa7ae14f48366267c9c872dbfe19aaf04e3a7166ce448c49","nonce":"811bc3b560eddafde5ad6ec2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"3d56e5a9cff2315f418d85e565eab143c31f1a988aea6af88428b15f38ca18db3c728765fb3e9329ff23f898c6","nonce":"811bc3b560eddafde5ad6ec3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"9759a1d17268fb1d0389f03b94c1b3fd311cf207ec25b101054ca46030721ea4d6689546f61e586822b08a1f7d","nonce":"811bc3b560eddafde5ad6ecc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"ca7e0beadad60f20b9f7c201ab811e2586a39bb3d63d7735deb360e9bd901d45811b345cf47c1bf20d0e5e86b1","nonce":"811bc3b560eddafde5ad6ecd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"7c039dc21fb3ea6c58c56dbb0e34622a3d12dfbe990869dc1a619b29b97c2e79a2a5fea7d0311a7a4608ca6968","nonce":"811bc3b560eddafde5ad6ece","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"2a23265ee9ed9b4b9dce142b362fbffd7792cb2f2cb1a253b203388881ba2373ef8715aad9b1a040264d0c0f98","nonce":"811bc3b560eddafde5ad6ecf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"ac28910c1bc60739b6a0481537ffd04598afd0ca4798d1053da45e0ed11690b8b623df26d3508d543aa2807f94","nonce":"811bc3b560eddafde5ad6ec8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"9955e7b6e9d8c0ab59182114def1b19e2903e80d7dba8068d9f67a66626934c9e5761fb3c10fb89cc184e723e8","nonce":"811bc3b560eddafde5ad6ec9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"729d6555dcad2622f6c1ff73fd243b64c3ad173e1769f9daa4f72b48a3cc523ef5853ccac7774d48874af8555d","nonce":"811bc3b560eddafde5ad6eca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"979833eb13477d919c800f7332b6fe0117f3fa0baf896524e98d3b2c3dfde9968b721abc710e727a6150c31283","nonce":"811bc3b560eddafde5ad6ecb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"b7d05f7025ac4889ed53b93064881401801e7a7279e81f1524906493703f7bad99a65e6ce5ce99a859373be965","nonce":"811bc3b560eddafde5ad6ef4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"5363b166f75e196eca3ebe0797b543a8d41d8cc19fc20b5d6c9ad0ef6d6d32e0b36e8108dd2a3590c739a468c5","nonce":"811bc3b560eddafde5ad6ef5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"b214b6dda138fed2f6fb86745d8bc389e5b6af67127e237f681804e9359a0893609b5c3564c344485acbe9688a","nonce":"811bc3b560eddafde5ad6ef6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"3f93cc54872bfd8f3c51b6c462a7cf5aca5ee38731a7809696ad9571dc92858ec31aee9ac0824df33a92858870","nonce":"811bc3b560eddafde5ad6ef7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"53e90b01c09e8f9a9f0840c324b779e3362f83906770caf8b999b9d4f2cb83b8d180c10377f9f8e39a39bfbe24","nonce":"811bc3b560eddafde5ad6ef0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"d3eec04ed6f0353283f1a25a2aa8cef01caf1a47bc1f9e59d9f4ee36d649021237da72825c5adb6b64c443b3d8","nonce":"811bc3b560eddafde5ad6ef1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"1e00f7217421a151bb9702926d69cce0296d7e70fe2f4c587439ef98cefa618d8705bf83192b4770f7a279f2de","nonce":"811bc3b560eddafde5ad6ef2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"14bcaa22735b68faa34c84a479aaa7d5e62596805944a22f1e558a5d16e3dac700fc6111d0f735b7244791223e","nonce":"811bc3b560eddafde5ad6ef3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"e9c60abdc09dd36ca3c444c5d5ae7c62a8860b804bed325b39c35b2c575455d8658d80f8f76dde68fe216835c7","nonce":"811bc3b560eddafde5ad6efc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"1651de0d5842f5a63218062b3b6199e17f650417021497d5459ee799d724f5b7cd6071a4375f3da6fa3b9ca8fa","nonce":"811bc3b560eddafde5ad6efd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"5c2f01555818fbb9ed119ebd3d9a99af04c64fc1abe80f52412330d8544144ce78ccc51225c18ccec311de142a","nonce":"811bc3b560eddafde5ad6efe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"a495ebeceb15d9f78e9b5a7f369c427f9799df4b764a40afa35db445b3c74d17d6ef546ce2705bda0a16d18764","nonce":"811bc3b560eddafde5ad6eff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"ad8ebe164691ea64cbc254c510750c3dad5e9aa80b70b75cd1d29cd063bb07620f85268c93396434d4fcc3aacd","nonce":"811bc3b560eddafde5ad6ef8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"0b2750686921f08b7c7f8c5abc8f19545e38aa4fee2067075fc917b96dcdfdab6442f445e96952ca9d21871de2","nonce":"811bc3b560eddafde5ad6ef9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"b94dc8eafaf1d1d24ec570eaba89070debcda25f88b4e7a03ebba8d12bb1c9632a3be048579b1d316ac55b40f6","nonce":"811bc3b560eddafde5ad6efa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"760c8ffadc8dbdaeee4b7cda0e7322ccc2a8e1d320e8ecc71a4d30f1e61ddb375b662ffe79227e0782321e0f01","nonce":"811bc3b560eddafde5ad6efb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"3ceddb84bd732f5630fc1618227ee24bd7d73f2463e6bb1dd96fedf3a6dec619d285069355d686c505a58303a2","nonce":"811bc3b560eddafde5ad6ee4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"9184c0a47d2e8a49d587da2deca3474e13b1898d98ffe969d17b39c779427245ab63d9c8d99136bbc5a07788f7","nonce":"811bc3b560eddafde5ad6ee5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"1eb619379fcd8fcf62a58a21043d3d3d190b768cd3373eb9da2fce8f4b7c501eb08e6e04e20637f17650cc1d08","nonce":"811bc3b560eddafde5ad6ee6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"1f039322ab635573cc47029b52e699e7e63a375379f8e64aaa4f26fc89e7a844647cd7d605296b41930cc86d32","nonce":"811bc3b560eddafde5ad6ee7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"d7f573dd6deb3fa3ae52318d3251b6155ec859978e5271f97f33e1b4d26c6e64aa9939672e0c58e31256950532","nonce":"811bc3b560eddafde5ad6ee0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"324a2bb6cbba2cb021bd5e7827730255369dc81afafc93f9524030e4679e578e3701ddf7bdc06a1bd2a44351ca","nonce":"811bc3b560eddafde5ad6ee1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"133f4b6a90c95f948708a574dcd5855a4e3e2fd0d8992d22ddcf96750870c8556d072f897b2aa2b3a6c0ec1963","nonce":"811bc3b560eddafde5ad6ee2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"45a137c15bbd78fcc35da4274ea5c55a9d030251776ceec535a9b7776e8b9d247cbe74050766141fcbe2778b75","nonce":"811bc3b560eddafde5ad6ee3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"5451cfb7a99f5f4e74288803be38480a08ff185dc2d00ef7a1d204c0f696af790519ca2c38a15690f0a00182ae","nonce":"811bc3b560eddafde5ad6eec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"180b8b8f6882982db8023421363f68394082ee931426b5fe759c8ff208bdbc20c9e1c3f5d1ed67db021bb80981","nonce":"811bc3b560eddafde5ad6eed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"f84fe8960be715ecef8efe54235f6c1cff4d77e66d8e423035f5e115acc8a9f74a40cf7536e482f36a1a4dd0aa","nonce":"811bc3b560eddafde5ad6eee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"6d91bbc2477bff0862aa3a22714cdc7efebb64afa4f25b8ac7fbaefc55bdab832abadbd1bb989c81c775da5b53","nonce":"811bc3b560eddafde5ad6eef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"439f8d2b0ae764d958bb073bf577b20ad1429874e43f66bd807f4e24546b69501e16567a588f6ce1104d7f7851","nonce":"811bc3b560eddafde5ad6ee8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"912c3f6029de1722d3d98405615c1e39752224dd1d5d3ff836fb09e7228d0490d7547cfeb10ffb1df69cf1c4a0","nonce":"811bc3b560eddafde5ad6ee9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"57d8caccac28e4de2ca9d5db75b48240b84edf44b15064f3d5dc8219cfbe67c736a1758ce147ec17242d9e0e21","nonce":"811bc3b560eddafde5ad6eea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"b235390ced4a283338af8b09f0d6aa0fb8fcc6b76bbdf42bac8a0153c0200fa381d0a0cea8d45b853280799d4a","nonce":"811bc3b560eddafde5ad6eeb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"68c41f37873951a853cdd8e3808c85231a695c82e7c8681d1e18e6096b98f19db7f28a4b11cd2850e6ad883de8","nonce":"811bc3b560eddafde5ad6e94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"52b9a5390cfad86ddd1ff4be1f4418d5ca514b06924177ef8c16a8fc0751ef2ff42677900faf6a19172fe33309","nonce":"811bc3b560eddafde5ad6e95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"9c75ebaafc3f35486e260bee27de1afc42997d35fbec89df16396c41ebd0596f848f0f9d270ddc840ee7c132fc","nonce":"811bc3b560eddafde5ad6e96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"59ce95ac01c358985452805a8884c139773384b4e5c9ade86d51f662e217305a69a54f7f9d1d39b2ed6e6b8145","nonce":"811bc3b560eddafde5ad6e97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"185fec29af76fc1aa0f971f6e1dc374716d51f48ebbad6a390bcf6714748f148b394dd35c26690426c811a8e7f","nonce":"811bc3b560eddafde5ad6e90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"c03c8ee124e0391dde008d12a84128414ba18da65de8e047c30628791a19a7ae3b5c38ca17e33253c595382dd9","nonce":"811bc3b560eddafde5ad6e91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"d48a6ec0b10e8d13a848c4cf82c895ea66ae3a953a0aa89988991387790db10a4c9703437c39ff1c896fb2bc9d","nonce":"811bc3b560eddafde5ad6e92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"d1d071c074e1fd92d12decd4da29423d8b90053219c5b20f97b11c26f995f7d870094c9a38acc2e35f8717ca2f","nonce":"811bc3b560eddafde5ad6e93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"1d4d2dff695f22145e55cfe1663a4eac25a3bb3bd081e65d2c35458c4dfbef362374480f5afe12a7b56d5ce6a8","nonce":"811bc3b560eddafde5ad6e9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"3b12a1ee79d7de8134f32544f34412961c99cb0a3f8bd0b077202409ce963d62c39f77377591371803411e4ece","nonce":"811bc3b560eddafde5ad6e9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"e557afdf156d6155f2a8a40e2b83b0b2e1596a7331615be49dd599d9a3fdcb74aa3c185bfbd82823413e910e84","nonce":"811bc3b560eddafde5ad6e9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"d765a715670f184e53d5753d692fb40356d164b649f6579c649e16ca89eec0c851d87cfefd8f27f71507f644e3","nonce":"811bc3b560eddafde5ad6e9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"c9654a3c16312b678f04e10d572432cfaaa789320ae729e074e2a13faf95026526a47ef9bcd51514cd3a0517c4","nonce":"811bc3b560eddafde5ad6e98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"15aed62d48803e7b0e345f997f6bd21561858ad25df61227e7355728396659f57f8ac828ac0d30fb3c2dfc98a1","nonce":"811bc3b560eddafde5ad6e99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"1ae5a194abbd2e7ab53664f117e0ad5ad81d1f32de38f3edf387918094ce7de1074ce181dc55e960df90a5a404","nonce":"811bc3b560eddafde5ad6e9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"2448c613d115d68579a4b0c43fdb5f86fc1ebf8bd372362439e3b2b5573e2d632fe8ad4b306eb860c46e8bc260","nonce":"811bc3b560eddafde5ad6e9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"4621a1e8bc63871acae360733ca4b0a303a0f3887be488b282d3ab87f596aa88ff20ff0b3360443a0e2f142098","nonce":"811bc3b560eddafde5ad6e84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"4641e2e7c8dfcbf4a7d34d8c50a3be6c5cae7a72b01ffdeb6f3645468fbd9018a59c675354a686509395caa3b4","nonce":"811bc3b560eddafde5ad6e85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"6386a84728c9d1aa476a8115e59fe702138bc9eff01ecb427997915d7e93a3a5c1b2944caf9db8e124f80b6605","nonce":"811bc3b560eddafde5ad6e86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"804878d22489f63db3826a9cf997269a90f73b8b606c75feee636ad96bbb5b84a18b6a4733005dfa42a7710591","nonce":"811bc3b560eddafde5ad6e87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"031d8e3318cf02b408a0da3b8f9f83f8577068a1f10db3e29cda42fe8a903eb0dd9c7af159547b780740953dbb","nonce":"811bc3b560eddafde5ad6e80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"ee932efee078f44345b9f311cb4e9203f9807cfa4766a3f2e75af103a117e8d80cce3253e48e8b549f1e39d2b7","nonce":"811bc3b560eddafde5ad6e81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"733d719b3343793fb3870ac7cb0bd306f7d52740ae29e7933022956295c1f14c3fb71a84a336babae0edc5e846","nonce":"811bc3b560eddafde5ad6e82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"b1bd4c91005d151c7f29c4bd56ea4896ecc197e8615fb992ec16c277b940653b6f62bdad2a5198f45e0cf58cea","nonce":"811bc3b560eddafde5ad6e83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"3c5c1f5f374b803fa5b5be57ef8f4cb7fb12bbafedb773434479b8fa44dfbd7d9c7c4f5ba089b1e82c3fa76975","nonce":"811bc3b560eddafde5ad6e8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"d05b959bc290dd57f17409d96871dafecadddd97f88a54525f1e85182e1f21825e2148725a4ececbc25d451477","nonce":"811bc3b560eddafde5ad6e8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"40164da22c47f26af5f49db7333318d11481a7fcf930a3259815dc13b1401a694520eafe05d59a0cf8e2b6167f","nonce":"811bc3b560eddafde5ad6e8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"1bf44544d60141de525b98d358417a0cd33b6ebebf7476c535ebf9680f0b165be46b3163af86677a473f77f746","nonce":"811bc3b560eddafde5ad6e8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"58b78e980d2735df2ada2f36193cb4eed18a139ce7adb4c8e6bf6e1a664eabb4163e8f7af5855345e68c058df0","nonce":"811bc3b560eddafde5ad6e88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"847f111ac5ff71b674ef037eaa371fb5330551f87ddaaeeece909a2327fd666bcd997eccdfe83da13e660bbdb9","nonce":"811bc3b560eddafde5ad6e89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"2c6e0122e80aeb4c7b7f341a10847412ab6422c5084cf0efb5de6b2a12614f2ae2fe16957d731df1ba148a26f3","nonce":"811bc3b560eddafde5ad6e8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"c04068e525d338a00a2aae17006deee28d7ecfce707de44a6f14f9adac37648503c7809ade9f5e9b1b7e5cb233","nonce":"811bc3b560eddafde5ad6e8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"99be17f99f03169ba1a938e3d3b3b7e491e4d41b73e204f9904e349ad1ac568cc7890f4825836f3f3f13f65e1d","nonce":"811bc3b560eddafde5ad6eb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"8baf5876715da7cf567e643bf3732886cf30762f379c9da0630c0874b19b7b1e8cff573322cff2234f2163dbf5","nonce":"811bc3b560eddafde5ad6eb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"57c11d262b8e32e4165540ea427a94b03c3db615bacc6b283334d140ded59e6ce2a8168c4c4464b14196f7db99","nonce":"811bc3b560eddafde5ad6eb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"fd721c5032a0b13c0da3b88568449143fe2b0b2cdb71465457709548d41b6fc641803acd283ca6c678e08060e2","nonce":"811bc3b560eddafde5ad6eb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"daa51799dbb8f1d47c79f8c78a958c5167f6cb778ef6e91072066fe7a477b93f103528dd6bf67bba4edad52e28","nonce":"811bc3b560eddafde5ad6eb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"b4ff663a00b9aa5e052844cd7345fefef37f829c9053094a560e99e7e28e05592a041ba3507da31390183c7484","nonce":"811bc3b560eddafde5ad6eb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"1201a48bc16db482584e8eb566ea3f5de8d919e1956b87de9eaab280f35cf1b016f15fe8a9df5253b7a33f51b0","nonce":"811bc3b560eddafde5ad6eb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"ba26ce741d114cdd41a169c10f8fb7925e87b4f7f50cb847ba9769096df908e4c66faf4e5298aea8ffca72880c","nonce":"811bc3b560eddafde5ad6eb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"d7a407d8956c565d6bd777def0783df9ce378ff0cd80eee2c80242627951de1641632d7b66bc32196eeb04edcc","nonce":"811bc3b560eddafde5ad6ebc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"30e1b2199df7be043a2724cd0cc584cb3fc03dad2a0fa038dd35194176169fe68ffcb50dec8268b7aab9f3082f","nonce":"811bc3b560eddafde5ad6ebd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"ba4d1875b9984df81ebe3846452d0193629f8173560ca3b1f349d6447e29c27cb2ce61a1d50022cc91ccee3fe4","nonce":"811bc3b560eddafde5ad6ebe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"a30530ec135d936b21c81bb82c3c211aaa56649e9a2d57b851ad402fd7f43bfb65ebc89dfdcad04a8dc1de44e6","nonce":"811bc3b560eddafde5ad6ebf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"955ee469db027890026eedeed995db6662d1b1ba16f4fad3553289462f46c4ffe4a7878814afefbad6551e8235","nonce":"811bc3b560eddafde5ad6eb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"0e3419a02a038e39e9faf281be3d206d6e18991fabc5155a8478e63b7c6389da8dbd8dece20c39a5497ebbb04c","nonce":"811bc3b560eddafde5ad6eb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"29f54e53603f0e9d31172b70ede26a1cd72d2290e33f5f7919c62b4d7978a6a191b219c2021200b7bdbcdf91d4","nonce":"811bc3b560eddafde5ad6eba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"d3eb705bb367dd35e993ff6f753af2dd98c24288b6eb8eb17bc2f8a3ee4b37caf089ddadea2dc742bd46d4928e","nonce":"811bc3b560eddafde5ad6ebb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"d7ae9b7f17e5e3aa8cdd9a0be8823d28089306b4ca3bdd4ea3c13c0187e6cfd0247eca17603f4fdbc38f93fb2e","nonce":"811bc3b560eddafde5ad6ea4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"275ce6e7853c0a10840ccedbe4b70e391dcc29f96958f29906dbbb3b96954365a31dde8893a31887cf5f1a184f","nonce":"811bc3b560eddafde5ad6ea5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"7672c72d09939248f62a504a2d048e1161f7f9bd0b692ff314be562ffafe6fc4c43e2d5afa7b029be7dd60cd5d","nonce":"811bc3b560eddafde5ad6ea6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"677c8e29156efbb31fa66bd121320d575079b0b79a76e1b0c538a1e4532dfb845560cf517e5b931da7a7b0ca09","nonce":"811bc3b560eddafde5ad6ea7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"e27612ca42338cdbbbb86af09d70cd675eef9da96f15f4ef2d33d77ebd3674e70665fe30702507f01f3c1177f5","nonce":"811bc3b560eddafde5ad6ea0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"0fcd949b0f9a01cb11072d19aa5d6fc6820bcb1812ba15f35b4f8b7052f774773e5426f5742ef856de2e47fce0","nonce":"811bc3b560eddafde5ad6ea1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"c862f8e10d928b0ac781766529459c532d65b60d162d69f6b5b732c054030e4694c243a42df701a187366c1d94","nonce":"811bc3b560eddafde5ad6ea2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"e4a41b0f395c993242a13ec66d9fc51fc1a6e4ad2b4131f148b984ca847b256677b2f9abd825f1629381d5f54a","nonce":"811bc3b560eddafde5ad6ea3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"629246d7f63ae7e0998667f4bd6435ebb678cacd8245f89fca72dd860122ac8db67ad430a5ea71f260bdf7cf68","nonce":"811bc3b560eddafde5ad6eac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"67e94376f1e110d27c09ed6907c268d817cefcd941afa7762af8c9c2b4f59173fd394db3c3c7d69900ce1c69e0","nonce":"811bc3b560eddafde5ad6ead","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"fa29e0a6af3c58bde5edb899ee0fae24b79108342f63ce5c91e19a0ef86cc151d0ebc2771cbbabf9c696f0c897","nonce":"811bc3b560eddafde5ad6eae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"ce52eba11a52e9b0830a4e340b5883ee1cd45edef563275f338d97585188ae18eb8383d7535dc804a8f48f80ac","nonce":"811bc3b560eddafde5ad6eaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"f10ca2c3dcb4dadb2bdf096bac0abfb3657869a946f4a59f3e10ae98b2301c36f6d5a12837bd39947a3d056fc4","nonce":"811bc3b560eddafde5ad6ea8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"f74ea6f3654b1772ba6e1b63f00af103243f3acb9aeef9f3ba899015ddb9e4229945d3bae479c4ce79bd362e06","nonce":"811bc3b560eddafde5ad6ea9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"2522c0d1b9b6877b651a50f3e245a28bea34d9a67f14295bae6f4bda1f882d4ed86daedabea6936d88a3a96e36","nonce":"811bc3b560eddafde5ad6eaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"cf0bc7b9545c0c30d54164e30b52a3bc0ef712adb7f2eb047014ab4eab89c7a548c6be9fe6e7a6e50a310ce684","nonce":"811bc3b560eddafde5ad6eab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"7e746ca75784dd5ffacb65ad499b283979229b57a0b56c52495f0c71fe50f00ce0b9696342e9a3bd8f7c946600","nonce":"811bc3b560eddafde5ad6e54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"b713971ce473f54d2c6b5e56e13161e08d5d67cdea6ccbb9999ebb2648c062cd06e6f5c7534a88006c2bdf648b","nonce":"811bc3b560eddafde5ad6e55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"8bc7b4533a632dcf1527c7dc3a8d2074614e1b4cf400d68beee454a127ae6787245c65b5b8b8fbd67331e28582","nonce":"811bc3b560eddafde5ad6e56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"bd8cf18188249181315962bdfc79b7c23b2a53574a797e665c090eac866c7655a9324e4667d9bcc31245f963db","nonce":"811bc3b560eddafde5ad6e57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"00abf3227a4a0785a2a800f96934bcf6a2190dfde2b89506c42efee005106441aacb5a6a3521ab6d7b5eb883b3","nonce":"811bc3b560eddafde5ad6e50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"5792d052ce7bb10d549b0ba95ea36c428ada3b1bf1d69a00f044ede1e1b1dc8cc80f1c31682f880e06b5e1d694","nonce":"811bc3b560eddafde5ad6e51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"85f179f055828216d1e3e51b25fdb51d18e4224d033463ea2faff0da1cf7ef630a19b8db5e216d3d4f72bb4e95","nonce":"811bc3b560eddafde5ad6e52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"c0c6b195bcd308985dc4fede0725a6f206f65d76190dbd4fd378bd5e861f83e5f026ae5a95cb6acb74b189714a","nonce":"811bc3b560eddafde5ad6e53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"6716c20f707275e4aa7a860361d7ef53c8c29394e585df7a4d114073b45a3358965449ec82f24ba0b8181a74d5","nonce":"811bc3b560eddafde5ad6e5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"4c57569ce1e3fe17ebf9d67391ea9a7b16e242adfb8aadd38027a6ec3473715d1d32e44a4202b98fd7b66bd069","nonce":"811bc3b560eddafde5ad6e5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"523406c6b02903f7e9d611bdd6f01caf1a80b1ca4dbeea27e009896fa8b010f7ff6e08cf4a92133e433ca69ba0","nonce":"811bc3b560eddafde5ad6e5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"dcad2cb71a852750280dd65aaf64b561d7fd540d3f295951c1be86a7d0cf6023e1c474d28b977b2997a31fea81","nonce":"811bc3b560eddafde5ad6e5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"8102fae2e47e551f62c4e4dec48db7e87715fa9f3444f360194cd48dbf50a2bd97c50063753784d3e18fc48d13","nonce":"811bc3b560eddafde5ad6e58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"69cccfbba3d250096ff3ea070c781611adc9a95c47f594f1084dd5d1f1e380353857b4ca2fb472ecaa2e45de73","nonce":"811bc3b560eddafde5ad6e59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"69b440d60a9740fef17bf6090dc520e6188c2c49f957dc7469df699b21ceec9b1e676de627f434a82271ca93c5","nonce":"811bc3b560eddafde5ad6e5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"003fbb213823d0d7fabefc29cde4b94e049ab7bb6d51fe825f9a5799f086164fca51561d5c55b41c212d34c2cf","nonce":"811bc3b560eddafde5ad6e5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"19c5633084cac118de5ac3a8a43c2ddadfee903bebcc7b6185096c86e3664f52e487b5a0fc5f8b698ec11fc64f","nonce":"811bc3b560eddafde5ad6e44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"882bfcda0360e88a300906d880356d5d7fe35727758aad0040e223d13565ed3a4b50fb99b74be7ba4f2d8ad585","nonce":"811bc3b560eddafde5ad6e45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"6cbb6c19825f6a78abe8974f57706428ca6dcf95695dd02bc441b198e2d16770dcdad34da86e1a5af2977680cc","nonce":"811bc3b560eddafde5ad6e46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"e5361f02e13b9fd3c2c5febe05cbd0def3a49c55c355a5e27644028f674c7b0ed98352768b3255950ade25e295","nonce":"811bc3b560eddafde5ad6e47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"acc7e24d90e1232c9f36729c3c0dd8659e1525df777d6cb222cfc8cfa61ce4193361985059b01ca4741b35dbc7","nonce":"811bc3b560eddafde5ad6e40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"6595a7e9b4198502924c61ace6d277263a5ba997ed10e07bdaff17eadfb53641c56e4e063da093800f58add8de","nonce":"811bc3b560eddafde5ad6e41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"d68617c45b886f518236265387673b2ae421d5dd608a67526a2d3c87c37804ff2a2a62f3265cc51866a0cb95a3","nonce":"811bc3b560eddafde5ad6e42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"949d202d4979a554a5e5e578157ea7f585212c61f5d2c790bba9287d552fa3827adde530ceb2f1a5172fa01588","nonce":"811bc3b560eddafde5ad6e43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"34fa65ed40e7324b6b82b9171830bd8263e50ab6bb99cbe4cc184ced39575c2408ed357c047c8290026750a873","nonce":"811bc3b560eddafde5ad6e4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"9c0a45bca81f93e76a589a9f974b831a0dbce0edda1f9042833ca10e84dd5f2351b099802030b53ef0655c58d4","nonce":"811bc3b560eddafde5ad6e4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"ab01795a4d52a6cac7bca2ba4fa945630b5adc46b5c40611bee31159a02622236eae0b02178790941ad63b58cb","nonce":"811bc3b560eddafde5ad6e4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"9176a77482081656224daa28c961ec35976fe062e02f097f549f447b3b5f73c9f4b735d1b4fbfa76c969e9a42d","nonce":"811bc3b560eddafde5ad6e4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"3ac8dfad224d0df0869b1f3e844325514e31d43c12b65caf210f5d9a5cfb6e8feb2f3839a2ab074be92caba5bb","nonce":"811bc3b560eddafde5ad6e48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"211b4d59f6050b0a0e1fb5280fce73318963c890b056719f1f5ece428d8b1a51fdca0b233d83d1c10cb2516d58","nonce":"811bc3b560eddafde5ad6e49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"da74be0f39e179109b9b8686347d94fd8d7a0dd8b6196a050af372b970e33067c22c29af8bc5e388d13e261bac","nonce":"811bc3b560eddafde5ad6e4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"f7721ec56029ab0f566b0ac39b0355b313366ec2006290319485883b786e28a4e2db1e08c6a2532fedd5887fa8","nonce":"811bc3b560eddafde5ad6e4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"f3747a7ca83853cce328a82a711bf46ca7b3f8c77c9bdbd558a09e649fbced96aa0f80c8044684d6ba8e9aea33","nonce":"811bc3b560eddafde5ad6e74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"98b470c5c00073eceba706db766ac97810253fced343ed99dfbfb29208733689298d4d2e53275b0f36a840626a","nonce":"811bc3b560eddafde5ad6e75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"55cf5a96d27f1fbc4c0a3dda6fa3a15e5198b014a50ca069ce3a713839380fa59225492a6b63d34d3f9191e7b8","nonce":"811bc3b560eddafde5ad6e76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"55f048e1a3353acd207d248f6e12489ef4c36e5038fb90bdddce208b8137e7378b09eb1d50282a499c63cb6ce9","nonce":"811bc3b560eddafde5ad6e77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"f606c82388645fc106730099d7d3281865e580c843fa1957d0d528c31b1bccfb1b97b0244ddef8106a22a3d04a","nonce":"811bc3b560eddafde5ad6e70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"7a0546e04826ea036bfad17a5504ff6c7dc1aa01f0e9c48b24f566c38d299056da65e489cd54bc225721241f13","nonce":"811bc3b560eddafde5ad6e71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"2db2ab83f648f37c6ce28105d2bded8bc0f0d7f785ec7738c80036a57a2715383970ae18fbea2a671c34e90541","nonce":"811bc3b560eddafde5ad6e72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"308765695a68dd605289688775091148b6347778f2729f50c07f939ee44b1904fa5081b1d42c17d53a73af1f6f","nonce":"811bc3b560eddafde5ad6e73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"51796873d0d153b57d72291970cd37d5de9df4b72d8ad1dfbac3ea9ab6892f0d9e40c604917692a90f4e815847","nonce":"811bc3b560eddafde5ad6e7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"f5de541fe4d1eb8b8babb07b5708ed32c273de955bf6b98d8502ebe671df5fa337ab3247d4c7a156154cf02be3","nonce":"811bc3b560eddafde5ad6e7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"9cdec6422124c32d162d8c40df54fef1feda766c6efe7be9ca3f2f466b37d19fc92ef362aa7bc1cb7db33ea5c9","nonce":"811bc3b560eddafde5ad6e7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"1d58666b75cddd1e671044222d2ecaa626ca0c53517af470274510d398099b8644193fb01c8684982d1601b50c","nonce":"811bc3b560eddafde5ad6e7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"affb85e3d8897788ea05d4e413036ec551b120af04232176d91e8fdcbf71db4455d108b55ce28075baddf5e63f","nonce":"811bc3b560eddafde5ad6e78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"cd4acf379de011dc2c0f4f141e871992344bfb0702816fb1ce6454ca54df96ce47ba03360595fbf6021d193b00","nonce":"811bc3b560eddafde5ad6e79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"b2f1878432524f0b5148a62979b2acb694353498a0ba7c33c6049fe6391f599d10a150f51656676967f2efea6a","nonce":"811bc3b560eddafde5ad6e7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"ed96872c1ee580d0748135897b2f49b668e2acf0f360f3ca273ec3145575a04345e9022937f525886da326de57","nonce":"811bc3b560eddafde5ad6e7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"525da2a99649be88e00410d9a6363c2d8bb0ec16ee306015225a96f16b383e65c32abaf21a5350bd2ddef7b4fc","nonce":"811bc3b560eddafde5ad6e64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"5545fcf104f1e5fe1a4a698d7165a7ad4ee87e45755da831fdb34243c629ef59b3137ce57407d0d807a6411fa5","nonce":"811bc3b560eddafde5ad6e65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"70754d28fc937f8f81a1088b6e10630cb69e65173f39025a10ca1affb21b45ca064b7b62c75d07a971413c4256","nonce":"811bc3b560eddafde5ad6e66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"3b1a77d22d7ecb53055e3ad0c061cba8407fc918ddc44d604e1456dd6561ce2cf57780d8e563392d5c9f65032d","nonce":"811bc3b560eddafde5ad6e67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"493b0fc0d026ddafc2b34ae4985e92df03ce00323e4391df966cc80686f6f5957a992953ba99343c8cce4a07b1","nonce":"811bc3b560eddafde5ad6e60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"58109fde964c040132c50c8e405eebee37ab84af54c8dbf58937f8da959d8e27dc6588d8501a7e65c2c8d9190e","nonce":"811bc3b560eddafde5ad6e61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"bdf29784985612d4f61854f975a568d93a5fa436f14bdd9e2a84242edbd2afaa39e1216a520634cb8eff255f93","nonce":"811bc3b560eddafde5ad6e62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"2795f5032ecdd49caf620a9e01d0f2ceb9b21d631cdc9de99acc2559589b1673722df92af2de5d76c64bb7077b","nonce":"811bc3b560eddafde5ad6e63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"f79a529bc2a976b19f9016a5ec2524a4ee1719ddb667dd28b126aabcaf9040ebc009f0b71f7b9abe7d9b0a0edd","nonce":"811bc3b560eddafde5ad6e6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"6923dd196554259e350420f4eed9e25c08d64e0d5aee13e2cc99d1d5a2b9c6d6954060d7af2d48747a609e9a8b","nonce":"811bc3b560eddafde5ad6e6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"b33849d9e0a2b0403b638a8ef951fd921322061b7432b9e32944a236d917a32342b9982799df583a3010b306e9","nonce":"811bc3b560eddafde5ad6e6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"7054473cfd2b4fde0071abcf873891d048078a954d658ecab7aea8c3e8d6790d4059ee6a6ef37f59dfef0dc98a","nonce":"811bc3b560eddafde5ad6e6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"4f48707d190f314c2c1e82068706248d1146989fa7e22a7151ef63f487da2921b22a92bd54eeaef580cbbc6003","nonce":"811bc3b560eddafde5ad6e68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"7ce275dc2f092862bbcbebc4602153463c7c8a71fadd2f6a3dabf4acb91764e7b6e211997bb3da8f99ae5e6731","nonce":"811bc3b560eddafde5ad6e69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"9766e9bc17658d83883431bd46c654d9fe48601f2e5e9f22317914be08c8a7335b07ed3fa8768b55e678f59cea","nonce":"811bc3b560eddafde5ad6e6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"e8cffb539f25df69ed4ef571354d4ed20ad878dfa40b21534646d7853f3f97413f12df648e065e0201af9b5763","nonce":"811bc3b560eddafde5ad6e6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"b95de85417bf3092def76da179b5261f49a8051f803faae58a43df0d48dc96ad667f42d7dea9d3ef9f48608b8e","nonce":"811bc3b560eddafde5ad6e14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"036069864599832168787fb8ac1ab0d2a9fad6208e863321201e085c126911b5c9cedd1704e05b751d0b1955d4","nonce":"811bc3b560eddafde5ad6e15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"d77debf07671791c3c875ceccf34d270f226300d563f813e43c86e6b4b1e6c118a2efc1cdf5686bf72530cbe5e","nonce":"811bc3b560eddafde5ad6e16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"40a049b3b171386dee976fcf940fd4e68edf1a2f1d93198dc108c3e20b1409c40d76ffe4e901bba421508425fc","nonce":"811bc3b560eddafde5ad6e17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"ac7f03d5f8f87dd4fb413c7df35b67b9185c2d60052d0a68563d0e480a8bd60fb88a0b5f54b5a7bfe9eab634d1","nonce":"811bc3b560eddafde5ad6e10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"d6cd1923e15547571a341cc9ad804172eb2cfe1d638dea81223429d9d6320675d83ff52300f5ffa9fff0914825","nonce":"811bc3b560eddafde5ad6e11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"384e8a06606fe168a48ddf2ef1a5c3ae4debd335758d268c4426a7eed68d4e91ac4ea557304240d2adadecbe42","nonce":"811bc3b560eddafde5ad6e12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"5a29cdeba8dd93c543a28d53309e2944393e5e505df303c35a12cd240422b167fb299a8661f0297be18d8972d0","nonce":"811bc3b560eddafde5ad6e13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"c35f2364244410d04e25493f2545a7cc54a0f1f0505dddcebb757275ac874a35bfeac2cfea5b722a2aeb842047","nonce":"811bc3b560eddafde5ad6e1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"94b9df34d2bda51953c19e82a14e9db8f1f25fc389096b3924c30296c693701166f2f6566d9f114e3566a98094","nonce":"811bc3b560eddafde5ad6e1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"30fc32dca816a8a43c346a670043275dc2346cd8f123aafc36b14552fef443cc80a59439f34aeea125f317aa7a","nonce":"811bc3b560eddafde5ad6e1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"1be62598bbe1669f6e05c2b5e1b8651194d99d475f1aefb79682a1fc73c8243e65445f06b826ca448b5303043d","nonce":"811bc3b560eddafde5ad6e1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"bce5f65a5f8e9227674897e30b1fba82fce2d0bba1d26c9386b1b1e6ed779a09c9887f27737d612194601f9b44","nonce":"811bc3b560eddafde5ad6e18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"f684d0170928061463eda81693ab441bc6c7c07d942c68c5cc0e602cbc77219e4197f94ad081f478186aab5824","nonce":"811bc3b560eddafde5ad6e19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"d77a786775f272ab8670be13025920d363719d42466f20d58619baecc9782e03f065e9883587060b7d50419c9b","nonce":"811bc3b560eddafde5ad6e1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"e649becb19c9058bcb548e0051711991192902354ad4409d27db0f28dd8b9bee968ab38adb128d6cff6d9015b9","nonce":"811bc3b560eddafde5ad6e1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"f85520fbdd82d69ca864399f5aba878af039fe3df7d27e805c76110da2a740220d13e99ed011e2d1de7e4f9826","nonce":"811bc3b560eddafde5ad6e04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"2830300b0785892393683a4826725650506ed47a8e7637a919643c422f9f1a680d1876fe8b40cd1115093c4a21","nonce":"811bc3b560eddafde5ad6e05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"0e84349dc6b52020c80545b6444d10e288bc8eeeaab8ec72f17df6ecc0c1f0efdb8e3a35060e0314bda40c396c","nonce":"811bc3b560eddafde5ad6e06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"ac351809fc577dfbe5b15eb63f7b0e2bff983afcaa33f3222e09a2136540c522f14734762173979466f4f85bee","nonce":"811bc3b560eddafde5ad6e07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"8a5434cc49826c5ec21302b5d0e2814bc2a3cc88bf937f1e00ffcd8d40e19066f9cc50f063469dfe8eb369ad11","nonce":"811bc3b560eddafde5ad6e00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"e8d69996b13b2f9ada714d965ca794253a146ac012e239fe0949e32dc9dd9990014832fac404be25dad07cf46d","nonce":"811bc3b560eddafde5ad6e01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"05d5eaa2b7cd0972461022a954843b6ace9278d828c1fb1920f417b2b5de9e21793c7ea0ffdb348fe69d1bcb48","nonce":"811bc3b560eddafde5ad6e02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"56d6fb63765380dc354c2b1524e15b1977e5fb0f6b266cd5224f6f18c5f4b58245c79f19e725e9d4d812b35d79","nonce":"811bc3b560eddafde5ad6e03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"48d17af136d84ac2519d5d46801584e6c6d1c2f9a5a9584b17b10c9265301cd90505a85a539035ea3ad3eda69e","nonce":"811bc3b560eddafde5ad6e0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"36e5ddbcb48a47c19000bf809ea204833c87f87ad3f7eea79f93ba8c48b78adfecd9175cc621a1f9295c85cd5c","nonce":"811bc3b560eddafde5ad6e0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"9dfbb7c4b70a793b76b6505c5334045cb503ee456bc3b63e06cd119cdc44f409bc2935aff135586a5a33e5d46c","nonce":"811bc3b560eddafde5ad6e0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"46f06b510435982e58613515fea0ccdc8834235d66180a49199aefd9aa055141621eb193ba3ae25a5d21371ad8","nonce":"811bc3b560eddafde5ad6e0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"b5a9c94d729c4033e35beebc8a63faf49bf447279965fbffd04ba0a01b967fb1db6ff85d5bf85a8e30dfb30c20","nonce":"811bc3b560eddafde5ad6e08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"6fef1799124bcb8893c814d7ead9fea96beaa47cc10c29e551b28c96959c69f49c5ab073a0f30d71b02e489141","nonce":"811bc3b560eddafde5ad6e09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"71b79bed74108debbb630c4ff5c3783ed08b67afb574d35e0fc733f4dddf1bbbe3a2c55daa5fc2d09b4f8a2803","nonce":"811bc3b560eddafde5ad6e0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"86edcfded4c39babb25296dc5b3da17caf87a8fef78b0329ba6d9f2c6b4295c1e01d6e5904b1b1d86eaa10db1e","nonce":"811bc3b560eddafde5ad6e0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"e5822662ab780f247bfa235322ca0f51201ce909006e49e7f1299c0a69c9dfc7a5097ec0622adb3abf76ebcac7","nonce":"811bc3b560eddafde5ad6e34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"d543db0d810f473290af3cbe1eac73625d577da046b033f7d90044c16650e202c395f1c1e0729e2a465ffc04ea","nonce":"811bc3b560eddafde5ad6e35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"76b551cb95942fbe88cd9ed9256e8412ea4e30e2de84945672f3def1190c75056554e364d7eccb11e6d97e274a","nonce":"811bc3b560eddafde5ad6e36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"2e66cfc3a2cfa8dd6dcc6fb308444ae655a79564735b5c0298b97d210f2a7f9758ac0de560bf4f83974e7d5ecc","nonce":"811bc3b560eddafde5ad6e37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"3d707efa5d465968e1dedf66b540bf2a01f53f820164dc0ee9a287b93259853b5a2fd3e2b9b7bd6d677b58b51e","nonce":"811bc3b560eddafde5ad6e30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"4baec3c1c9df80f8de450f3a49e694619e49ce9470b5dec6f7ecbdfa7c3d38de79ec7bfcdc7d66ba5f25fe753a","nonce":"811bc3b560eddafde5ad6e31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"efbcd6cf72c604fa5e2497cf23772abcaef4998e7622402a0ca73f008755eeaa20299f7dae7f56fef1308e1d63","nonce":"811bc3b560eddafde5ad6e32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"cdbb0c1a1a19856a400e3882c6ff4945edbf7fd22152d5cd14712287a8ccb2871f05365fad04272c1905233d19","nonce":"811bc3b560eddafde5ad6e33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"17b5f81908e7a09326b2d29b637213d92edd72d10d26c61bd927a6360f7df6781f6776bc137cf659a9969e825b","nonce":"811bc3b560eddafde5ad6e3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"1b76877d6be42d71efc59777c0fdc18f29b562640ceed86015c7e6420077d7840d61e00cccbedb85e658520a23","nonce":"811bc3b560eddafde5ad6e3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"9a1026a89f2746b22528fb09a910bf0eba824c741fff5ddfbbe06f13b297ad580b695e68411b9f371a4c6eeb0f","nonce":"811bc3b560eddafde5ad6e3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"c36565eb988d2ab8bdd937483b4fa800b8e33a7da81011e67ae5f3b1b0277fe8f5332547ab930069e906e69df6","nonce":"811bc3b560eddafde5ad6e3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"f638c8292cf8a67c1792c2d37ae6fd54d2950fd9d92cd2eb1461a07c78b838ba25d69c37bde442545370b40e56","nonce":"811bc3b560eddafde5ad6e38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"49f2fac9f7b98c0b9a54be5a284f5eb31f1893c071d2f0c2d2deeba79b967d8f62ada6b9aaf3bd250593035f7c","nonce":"811bc3b560eddafde5ad6e39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"edc45189aa6acf4ccf7f85e16f25ab3bd7eaf2ad5a5230b81b730dbbf450a27b72570447c0113cbeb7937c4e1a","nonce":"811bc3b560eddafde5ad6e3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"e3b9defeb10de51ad8220307d8a991c00a2e7b0d81c27f322af8d92bd8a3d14fdf2b6e884ad6e7562216ba34a2","nonce":"811bc3b560eddafde5ad6e3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"d781b38284824bfe00722a251b4ac4148cef8104b4a442d859ab629579230c6fa917218d175fad0aefb4024d9b","nonce":"811bc3b560eddafde5ad6e24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"0837300644a33d81c6aee0f1fe1462a002209f191a949b6434e7c2d33796c06c43fed5d538fa12ec03074a9406","nonce":"811bc3b560eddafde5ad6e25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"1c0287604c78f7a2b1fd694df4ef80375185aedd57d79e6108c2747d5ba76426de520f30c733cc4fdd29375a64","nonce":"811bc3b560eddafde5ad6e26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"c155c2daf9b169c77af98e63c0fc9e710d12e2e25b241a0aadc3a164ae6b656b1c8280ce43c4e875b12583f478","nonce":"811bc3b560eddafde5ad6e27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"f90984f7bed7e8287a6358b4cbdda6fff756b278897a5866d16b5a411ee3a8990a666e265860c5bee2ce3e30e1","nonce":"811bc3b560eddafde5ad6e20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"3cd68555cb154f2606e467ccca3eb1e1f4aacd9e0a1fe39a956bf7a45ae52d54932fc1c5eda1f292f99c676f13","nonce":"811bc3b560eddafde5ad6e21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"f790c0b4b4ff32a68b9194841673d7c945ea58155c391e192c557f9702783e10dafc5f895ae5da34460a3a87f4","nonce":"811bc3b560eddafde5ad6e22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"08234b7682679ea277e5fb53ac41c5b4544f2bbb643af2656a1fc9608853d22d8084793dad37b82d7e1a48abb3","nonce":"811bc3b560eddafde5ad6e23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"5ee52f6946cd4212ac97bdb9dbe01492c7af01ce561551cddfc1b638d11074473897555afd5bb729a46add8d2a","nonce":"811bc3b560eddafde5ad6e2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"e654899f3e44eeb0bbcfd73e85629fa82e22e73c8f7242f6850dae234ed69d02d40025ba4d94151cf3131f0076","nonce":"811bc3b560eddafde5ad6e2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"140d213907a92753ac73932c9cb82867143745ed4bbe1a5f33a6403052206d5214ee6ee4d6b577ecd174be7800","nonce":"811bc3b560eddafde5ad6e2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"d6dc439ed626f567595db353b65ff77025755725305279e4b79f894c030d1d3d34f6d3f86712da36d125752e6d","nonce":"811bc3b560eddafde5ad6e2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"6fec06a28b817cb65bbfa5d68aa45bd2b34e8a9d5278efbe1c485bfa3676d664a331381391028a028452baf2a7","nonce":"811bc3b560eddafde5ad6e28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"32a57d0a1aac5584f3f523e455f4e7c54b5379c524de5d0e083e98678cd188047500babab95888bc1c4e9de04a","nonce":"811bc3b560eddafde5ad6e29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"b358a0bb2ebe2224931445f81a66d1df0edf5ff2e256fb5538571210e8ab2a4cb9254ea94159006cf677e90550","nonce":"811bc3b560eddafde5ad6e2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"11e42eea033e9c9ea4b94a6b0c4f210bab002b101e4b06a4544477cb8aad98ac74132d521454f5676456203527","nonce":"811bc3b560eddafde5ad6e2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"267fce55d3263f581ea42a2cf528b0d67bf6d1dc9220718fb5ed19f1a38e0c5bdaf6dde2805a915ec039d44006","nonce":"811bc3b560eddafde5ad6fd4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"03983379c266a6b09287be5743290ad19b8773fa87693091cd72a6aa215c2e93"},{"exporter_context":"00","L":32,"exported_value":"5110008bcefc255f1d0feef8fcbcbe0665c42a30355d7bf430fb3ee02a5507b8"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"b6da48879ce5a1e1cbe3338800b061a46d1d87ef526a6fa44a159836f3f148e2"}]},{"mode":2,"kem_id":32,"kdf_id":1,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"f6ed2384937da2327cedac13c34e93960627860926993a60d031fa6f46fb659a","ikmS":"02ac3d858a4b089c86f5b6fe5513e7e49c8e0603b008ae4a4019e308bb0ac484","ikmE":"1de23785c74ab0765d900a39cfa60ce81d2484b23224255d003ab9009951c8b4","skRm":"5066f0736ff5f36f6901c2a142f0ee8a49a3bc73170078cd2797cda565fa3e32","skSm":"57078781148b731cf3eff2f7c4a15aedeee5d5f743d5c2a9af67f8bab52aeb4e","skEm":"9f9c631189d1f386cbdca0331e5ee38b3d1e6b98842a5fa29de7a17bb5320488","pkRm":"d16548e3896b89d61746ef931e343ee60c90a6f84b02de99e665c2c7f11cf463","pkSm":"5c7091fa039a955d152e60a3d8dccd8e4c0d8aff2082163c05a0e00590c12d79","pkEm":"f2fe00d5fce2307765db727702cfe2f9278594d1186425afb7868be2d1087639","enc":"f2fe00d5fce2307765db727702cfe2f9278594d1186425afb7868be2d1087639","shared_secret":"9590bceff3d360d7ca200d0daddb81817889079dd110af273838a0aa226e6354","key_schedule_context":"02431df6cd95e11ff49d7013563baf7f11588c75a6611ee2a4404a49306ae4cfc5b69c5718a60cc5876c358d3f7fc31ddb598503f67be58ea1e798c0bb19eb9796","secret":"2496f7812d4f719ed83d17dac1647e5d1dd8e42dd815af8d262389052e4799a0","key":"8c46e9b58caea9becf0a0d3f694d99dcdb58f957d8cb07be09fad142ab2cef0d","base_nonce":"161f276aa6d7bd3029764151","exporter_secret":"5505620ecc591c690b3c397b1f784d6a30048b5324fbe1dd60d79b4508b3944a","encryptions":[{"aad":"436f756e742d30","ciphertext":"7cfb5a4f4cafced25dd42143a5dfb9aa9121ed9695cb70a14aeef805fa70bcc73724c36dac1377251e8fc1d0c6","nonce":"161f276aa6d7bd3029764151","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"7a18b8f1a7b470b518a548e359f307277f8c2560f56b6955a38f3d66f4234b5c4b719b5c0445ae2407f5bc2e41","nonce":"161f276aa6d7bd3029764150","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"149dd1361a871703ed5edc5ea1a74e6973ed4c56cb67982ae6445e3497f2c6b3f99d3acac56145f4e2e2150bf6","nonce":"161f276aa6d7bd3029764153","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"c7bd33139be69ab29541af80527218a6d2008ded67e60def71a3af2745dcf3e3eb78203a431859eda7239083e0","nonce":"161f276aa6d7bd3029764152","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"dcaa6179a1d1bc2a810be84afdaa4ff73c1b04e3bd1a6d797030853b312c2355f28b85b5e88b1ae764bde61ec7","nonce":"161f276aa6d7bd3029764155","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"0a6908510b9e3af8834a65b7c83532bab13149fea4d7a24133fbff625e9605e836fd8f86b29d99c471a821678b","nonce":"161f276aa6d7bd3029764154","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"014a3992f9b7cffddc7e7b966e3da6075c9b0b1e0515890c151d99bf38e0a66d55aa88be1244d07442f6bcc1b3","nonce":"161f276aa6d7bd3029764157","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"e11dafc77ad9651dfeda6a7607bc5d88ecd61cd50feb0cded1eeb8bd00fe1dfd4456b0f9c250a7be0fc068bdd3","nonce":"161f276aa6d7bd3029764156","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"cd4cd996777406c90369b446854fa8de60766bf0ed0f9904222fb5dc973f8ad85df8d1006e31548a8b39bab472","nonce":"161f276aa6d7bd3029764159","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"2c186bd50e0bc34a562b08944993419e682e574c35087bdcaab76436913a4c4ca124d7a8c8094e45b673a836be","nonce":"161f276aa6d7bd3029764158","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"f3f9755429add649b0d40f7ea4d120dbaf1a763c7d4994304e6dcaf242a406a1f2450cede5b426045224355a9d","nonce":"161f276aa6d7bd302976415b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"2ccac6f2bb73ef89097290a94bd20804bb43a1e76e11b8c81df5a3c7f2229a35e6f43720c24a5ff2229fc6cac0","nonce":"161f276aa6d7bd302976415a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"db3a4c6c1804d7eba30b886a63f15e4e064d9f33a49b548278912685a2d8e0ad11c39b169d29036333b153cba7","nonce":"161f276aa6d7bd302976415d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"72b7bda313b222d41eb225c188de100da766cff7d47c34042c88a3e1029201a9e86891c4e07e3aeadfcbc4b923","nonce":"161f276aa6d7bd302976415c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"0aa6a0386c2efc8ef4d76c43b3fb1e38f311091fb6768d84ec4c7448cb91460e0bc073f12b8ee8e0cbc6a8e2e0","nonce":"161f276aa6d7bd302976415f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"d9fe2aceedc019b3bd35e0b2d4ce36aae26c88b9e4689ae9c2068b8dc0b7470856ca4637ca42e78656b3667eb3","nonce":"161f276aa6d7bd302976415e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"e588669dfb81d91f5e1147c3266d8d9c0adb0afa8e6478033ad14f6cbc0025e4e6884c8124ff03945e6761f1c9","nonce":"161f276aa6d7bd3029764141","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"a2dc0119c06b03a2ce98997ef27295699e89680fd5539115cc3f17b592b30be018e3d750a4697b312215590d54","nonce":"161f276aa6d7bd3029764140","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"dac703fc811f95d01a0cf696bbd8e7102a7962f1cb37af202b11f9835709d9954e72ec2057397f300aa3f1a246","nonce":"161f276aa6d7bd3029764143","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"38804c2d5901eca3d94c74f3ddaf67aa70d44e55d43457fd218bff0810fb18777853279d5c68cfec27697f3043","nonce":"161f276aa6d7bd3029764142","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"6eb236cd3f4cce6f94885aa775196f08d192fd39f62fb2e20c22d7c6c46db0890195dfa6b3255456bb105ebb4b","nonce":"161f276aa6d7bd3029764145","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"33f15aa284bce0100ad185e471adc803c2dfd4f2c22668a0a8561a31a1cb1b8071714e8f21a01c9050d44c3d68","nonce":"161f276aa6d7bd3029764144","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"ec1827dd223bb08f33cc1d560714d286abf63c5b615d220fe5c001b3b70e5b102bf994ceb5db964187d22105cd","nonce":"161f276aa6d7bd3029764147","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"43abebff72717ba73bdf440af91d79a0994af8fd61cd7b252a5dac7c590b599a507be4a726a9162b0650c88b9d","nonce":"161f276aa6d7bd3029764146","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"3c99ffefbe5dc130fef0ffd859a98dcbc03d55765fa83c6d485c70264a569d6e1844b96995faf2a02f598938b4","nonce":"161f276aa6d7bd3029764149","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"eebd1b7e87c1da4d609dba903cfe02e9ff84c6a6a659d193b26b744dd10d2bcd24f68b931b7e4eb56b57c65b91","nonce":"161f276aa6d7bd3029764148","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"acd9b33ab07d8915fc12f3b3da1f6b374855f6d41ba6c71fa6ceb787ad8c7c5135717e45d1a09a922c6dd6d138","nonce":"161f276aa6d7bd302976414b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"276284d364c0f7703ebe9a48cef610534d5243b592fb3273f64a106c3f03b9eafc1366d094848525ebd0c3e338","nonce":"161f276aa6d7bd302976414a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"20dd4939dda0899da875a2f2593ca22cbb5c01c0a031c7372e15f5195046490a95a7882039c14496b1c43d7a4c","nonce":"161f276aa6d7bd302976414d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"bbd0b4f0a251dbdba18890fc6df0b518b3897bee4d9c16961735eeb405ed960f38c91087c86f8faf3940cacdaa","nonce":"161f276aa6d7bd302976414c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"48b507deee0a050c91829a90465c191241a5025d6a2ae2b96d8d9a60b136b44a0337b8b40c88b5165dc068cdd8","nonce":"161f276aa6d7bd302976414f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"ebc08c3c6381f59454966b01223f90a4ba27b40331499f7f66202a8db6845a27e7f92607db96bd547b8108baea","nonce":"161f276aa6d7bd302976414e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"bedb5f8f039ddb8605926501c0ff3f7f905ca79cff67e65f6fbf86cdd0e07a27f511b1b97087733794eebcd6c9","nonce":"161f276aa6d7bd3029764171","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"99c0eb66c80285d087b888cbabbc2d186e5f8bea7f38ff69a984e6e8ef8ecd703ffd7e5504b0bac2a9790f3a54","nonce":"161f276aa6d7bd3029764170","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"2604e64a92b4d3817a762ea707da9e2b7add0740b138698b384f0b610e4395dd0f515c454d0184e0825b1b23f8","nonce":"161f276aa6d7bd3029764173","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"6da1cfddf1c2f50bb03e0d51928abb3b41cfca61f62868fc9772cd852d7ae1508a2843d043e140845e23f70e35","nonce":"161f276aa6d7bd3029764172","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"00afd082fff10302ba772a98def2a2bdf1b5abc1c22160e130b60164b435a14c9d615212847e64eb49928b309d","nonce":"161f276aa6d7bd3029764175","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"44768f9ff5d8d843b374a3d54e8633ca37b3136b3d146b7c2d9d3d15f922654a520bd137eea589771a3dff269c","nonce":"161f276aa6d7bd3029764174","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"7489dc8999599749dd66088e918e1a61d20e5ea721aedf3cb0054516bef505ca61bb6b0b3bee4453214be023af","nonce":"161f276aa6d7bd3029764177","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"06d89aa8a3800ba9eca14b61ed17161c1702af58147cdab3fde28e751363f0c4c590727a037490ac4a9abc6747","nonce":"161f276aa6d7bd3029764176","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"6d6167c4a4cf14de3a20ca760cc0fb73071a2b59ea8048caaeb4d683708ffb049f14c6e94e4b90494935053219","nonce":"161f276aa6d7bd3029764179","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"65c2222f0792bf3bff57bda96a2adb2c4bbb69f35fb5a71f159047a92402f1bf345de968b915cca32cb2d1fa92","nonce":"161f276aa6d7bd3029764178","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"155e17a7cb14525dd60627173d9780a6390c0bf312954cf3e689cc2e7b6a73dca1b73b04805eea691f7e58ca5e","nonce":"161f276aa6d7bd302976417b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"863480a57c358cdf9a422041814eeffc5b762676ac95804fe6f6da8dbb8f62911b0084ff63d95749c12f732eb5","nonce":"161f276aa6d7bd302976417a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"b605142e4d829ffbcaa20011016a4be90a41b898fdcb5ba22022ecd9a9ff232c17cc708976e07327ec708d2c65","nonce":"161f276aa6d7bd302976417d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"82572ff6c88f58e1f93707385f32b75491f0d5e8925d1c83daf9c56b5933c0eae12702790d8e6f70d17af470c3","nonce":"161f276aa6d7bd302976417c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"92e306ab48b1ae5c7afa00c9df893141d56e202f0b4c8fc84f3eddca05b9e6e74fdf38c689f20bbb0cc57ee06e","nonce":"161f276aa6d7bd302976417f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"f7da60e2052f069553466ee70fbfbee1df53043045176739168a6240a22da1025205a3ddfa059b09e762fcbdbc","nonce":"161f276aa6d7bd302976417e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"3d1bae0ac1d07d028c3f4f600de69a9a1d1c41f672cf0e5f29353797a9586cbaee380ac75df80d43d25d7316aa","nonce":"161f276aa6d7bd3029764161","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"ee7fd439c868f93a25233cbcc19ecd9eace3e5e81e117fdfb7e17e8a5a1289d75a31ddb0d1c1b6cb8e4b3cf54c","nonce":"161f276aa6d7bd3029764160","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"be9dd1b1bc3f35162c4c7c6da2bfd938700aadcab1fa629c762ddc24b172de4b7335413b8983c7c7cfcbf7c580","nonce":"161f276aa6d7bd3029764163","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"a31beffaf7645da6e22bae91ba243407fd870a813552f8f551c67ec018b9b0e60b373d0ced829ab0be59b7c2ba","nonce":"161f276aa6d7bd3029764162","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"ff0bca0130e035f0b79b0861e86be23551c96272109be6a54978a0a81d1e2192dfbcb1e38915bff2332153f129","nonce":"161f276aa6d7bd3029764165","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"e257a1217989bb2f99e1a3279c026f59c4f73ed6cd20f2f15e4d40370c3019239f499f2e5356ac836a0507ca60","nonce":"161f276aa6d7bd3029764164","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"6c19ef7fa1143c633800af622b06939ee95ccad745f950b9a4977c8610f58ca0a4a9b5218c37cb905af089f592","nonce":"161f276aa6d7bd3029764167","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"ef97a91b8a733be0ee56a7b8001d528c59bca1f600fc7635dffd8a0f4dd55ec078cea3d1a2793b53c06c0cf9ca","nonce":"161f276aa6d7bd3029764166","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"c053602da48b8260e61f349f992f33f4799532d4d5cdd05737d2b4f1ed41c96e4e7d2e489faff38a435c7f6f0a","nonce":"161f276aa6d7bd3029764169","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"abe07bdfa9eec0dc2c2ada8150afa4612549ce95d801d7b5a52dc54339310e33b6c555fe0e748f5e933895f876","nonce":"161f276aa6d7bd3029764168","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"734cae32f4d740dcff4a4a20f5801c4422cf626c05e115e2412690bf7406e3ff2aa9b585fe6d4091666a01f846","nonce":"161f276aa6d7bd302976416b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"5f2c86d36461eb6dfdcc506b7e43b6dc0dcefc82e8a8246c9eb6da333714981946dfdc326e44d200e7896376b7","nonce":"161f276aa6d7bd302976416a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"feb3c5f13b4ef3f18201d7419a211a55b66e67f7ff9a93e41ae014843df01f70e73429a30297687c18588646f3","nonce":"161f276aa6d7bd302976416d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"2621167732c348b9e81e082f26543b65e832bfdf302ec447f35975cb1c72bbdf7ebefd1c12e2fe8e52abf4a94d","nonce":"161f276aa6d7bd302976416c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"6c4d80a760ebec63c485899271c75737022e584b887d040b034345b230472d5a8ffe04de5a40adae9b0ab33fdf","nonce":"161f276aa6d7bd302976416f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"e1641e76c13a0102463a9059a47e54791f818c803325b1f00114a37f13965a40d9ccbfe149a3072742236668fa","nonce":"161f276aa6d7bd302976416e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"b924045b91e94737959f95c01d81593990ad25e2b6c8bd39bd7f593b74942a677a08ce51407b2b50ec68033a58","nonce":"161f276aa6d7bd3029764111","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"7b3196edfd45a5c13e5d4cc10b96f7c9dcce37ae53844c4c08117c256e37ae87524b53378141ee2870db79a760","nonce":"161f276aa6d7bd3029764110","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"b3fa125ad8ac1cd850bda770b7f11b7426b9c6f5f5feb12894244f5b1ff7215d0b5429d5c92c3f6b1964290e1d","nonce":"161f276aa6d7bd3029764113","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"1e589c8f1064c4165131dba91e9eb77da4ec02478d62f7e13ee5c4ec1fe5978ba7fe36c42661c16a6fbd605c59","nonce":"161f276aa6d7bd3029764112","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"56df5f3a29df1041f5793c1dbeff2cd2e8ede61853089af6bcd1d7612a5437d3b511311b378897b489f1abdc65","nonce":"161f276aa6d7bd3029764115","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"4467ec7a900e291c86e1216d32afbbfb78f48d87289d1e66078eb4ebb74bf85ade1bd2b4198294e9ef0879311a","nonce":"161f276aa6d7bd3029764114","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"370b43c93ff63abe54ab3506f8e07466fe26dca890a6df2847de006f55b58c0d7531a707609e0f32b7aad2ff2b","nonce":"161f276aa6d7bd3029764117","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"345a1b9eb0d709b9913ceff93f7df1a72bea18ff52caf97d4a8b157a1a3130218ab8a4431d34a28d0449fb7ed4","nonce":"161f276aa6d7bd3029764116","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"2bbeaf130cb51e7bf0cf56a6a62f63196043c96d3f6c4965c5c14d95f336629e8a45ff1dcee482368fe27cca8a","nonce":"161f276aa6d7bd3029764119","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"34b982275602aa2cc735525cbefee0b40099559b8258036e84602866fdd88bb8d45fde2d53111588a91bd86fb7","nonce":"161f276aa6d7bd3029764118","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"acccda750ec9c51a957cca485ae18f9d41956afdbc93572320db210244595e5472e4657afb87138ef3e44bd749","nonce":"161f276aa6d7bd302976411b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"aa5713de16fc3f5dc224841f0c60335f4e46ccc0b6be4b75bcc16cfe512f5cc145fdfad6523371267424629e60","nonce":"161f276aa6d7bd302976411a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"70dbb68a14f68092859d13da803eefddd9b22e570ae44f6802e2a2d507ad98aa43cd999ba466068de2083cd6ed","nonce":"161f276aa6d7bd302976411d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"4be18218b98ee299295086ed8960dd2a075811ca7b80399416fd5fe6781c77069d7e53824a38600577cfc4d870","nonce":"161f276aa6d7bd302976411c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"21630d01ac42b848dd38e81efa7b74611873de9a9fb0228faa6eacb94acfdee4784eafb47f6f9699e881b37fbb","nonce":"161f276aa6d7bd302976411f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"e6e264676f1f912bcf338740e2640338c4081369f294b3547d35d1995922d274b74225e3af7384aedaae220114","nonce":"161f276aa6d7bd302976411e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"9c7f9a64dc645441535fa7070cd9d6ad80d05e325e2cf080f439a74de69e478f31a9fd77bf4f3fbe061274eafb","nonce":"161f276aa6d7bd3029764101","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"a9500b624153fa563b0ca35a38915b8f0b256cac233f05a8b58acd45219409cd696f83fa993c75ad3cd4601993","nonce":"161f276aa6d7bd3029764100","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"95fa85c5dee89809628c1361e4c7d0fb7c66698d05d5ae8a74ed0bf8e65a3b7a297b433e0fae8d8099264846aa","nonce":"161f276aa6d7bd3029764103","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"c821578f45342ccc09050c1188ae495b21bfdc52eef786ebb753541b6535366cfb6966bb0085798d77b6c818a3","nonce":"161f276aa6d7bd3029764102","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"12cecadf5e1d135723b76c356b52cb11371e3866a7600ab5734caf2514a0d9266ed161db3c57532543a68f8164","nonce":"161f276aa6d7bd3029764105","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"293892f3d3fd2ec25ba2c873e8bc7ba5271ddd6044229ff697e630a04e9ef1b34be171a6ead2dea8f2c9df0904","nonce":"161f276aa6d7bd3029764104","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"7f6e60b536787a289efa54a9a5ea92e956b4836b157afec4794193119ff4016ca44f39a9df51eba7d2a9f1532c","nonce":"161f276aa6d7bd3029764107","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"9dcae2db9744b899819efa382f1df3f3d3f3a36f035146e8c919009d31952ba11a8987fbf3864887037a85bff2","nonce":"161f276aa6d7bd3029764106","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"a2f19722bdf604ae19d0487db38dbfb8c1a8400d17da9f898d5ee13a54b4fb58755f42941ef6c71243acf0c295","nonce":"161f276aa6d7bd3029764109","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"8999a65ca78b2aa2715e5dce12f26df89eeb9f2ebd26990de059d62b41f5b9dc02d8d4d807fb530ee2d26128a5","nonce":"161f276aa6d7bd3029764108","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"7265a5829e75df031fa5d007386f6f3eeca227016c1712e17cab869d045d0266cd2cfb9594a29c1b44741d9ef7","nonce":"161f276aa6d7bd302976410b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"1c6baf2efd354c8f95ded72f92cba1138a6840478908d7ef2b7b6ab612cac9db7517380c1dd65971f71bbd05dc","nonce":"161f276aa6d7bd302976410a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"a37c708bc28fe2862f5cdc25221af08b129a93a92d3a3211b048282e52b60e7d1058357c184c4668df4371f901","nonce":"161f276aa6d7bd302976410d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"acbf21ea710ecf64804c2eb1781f7178bdf3c9e5e630def52a422f11071aa6f0fb0a5131972d4c16d30d14ac47","nonce":"161f276aa6d7bd302976410c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"203e3f2e8293e9ee78761a6f8d62dc5a2898aaa2aa1a0acccafda65f36c7a6172d77fe660b38dc6f40e1fdfbc2","nonce":"161f276aa6d7bd302976410f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"61021785bb260c6d8e59f59c546297802d0e9b366e3ed96935b0ab1e503e97ff3a1006684862a3953dcf92b463","nonce":"161f276aa6d7bd302976410e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"a558d6eaa70957d0e781789a62864423362e293af0c67cb21499267f9533a69053de44290d9c466423823c9657","nonce":"161f276aa6d7bd3029764131","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"6d2958c8ffc6504baa4cbcde540f72fc159465e3d0704cd71fc8cbc101ea04be04842b362fe10b5bb3fceb501a","nonce":"161f276aa6d7bd3029764130","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"687a3895d87ac13499f24a8a364bf37734b74aa78a4c785533e8751ce8f8196c353160c5b4f9f4d7cb0a77d070","nonce":"161f276aa6d7bd3029764133","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"85f1f23613748fe86fb08ed4152f920f0023ec033a346134a484288e8e7f95af8d6f652bc8b016164ef452b292","nonce":"161f276aa6d7bd3029764132","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"beeb2ed75b5324bc7c0dd84e771f69a36585d8912d3e80b73ebc7b33b7fba56eebda73c57d22eb9f9a5e15e903","nonce":"161f276aa6d7bd3029764135","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"11af728e92473c668f31049b5ca1e131e26a3f59ed5a09675be6c1d33c728857918db0faceba2e2ff11c663192","nonce":"161f276aa6d7bd3029764134","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"d98a99f90b597506e78ac17edfcefa325321c49c14e69e0b7f273586e2df15a006ed8531f54158f6c7f0251413","nonce":"161f276aa6d7bd3029764137","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"437b6b1947e0fdd9f183717b280449e38106d1e595c54c77c08624daec8ebc68a0e123ef847a30c78bddd40cc5","nonce":"161f276aa6d7bd3029764136","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"43309a8cdfb371aac07afbce54232355f04e62a3eb4791a0453f122b37d5d1a64fa8abbee12078a4110f7ccb91","nonce":"161f276aa6d7bd3029764139","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"5893bfb72818d334c2088133ca6eff5428766f51055c61f66021c82cbb565144c950bf265ca329705d70b9e690","nonce":"161f276aa6d7bd3029764138","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"49f4e8a1054785472afb53def28c191be26f3a4ba1c36670a2cdecc6c5956abd01b855dcedb7b27fa327b59ebe","nonce":"161f276aa6d7bd302976413b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"67c40e4c1fc435c17c2aba99928f81ea0ec9ebd6770759be018aa67e47df429798e05f2640d8fe27a889cb0747","nonce":"161f276aa6d7bd302976413a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"0632676dc080c7b0eac50d19da0622b99b0147691780800bac11acac16de0f1dc478aeb3044c2ab820980c7bbd","nonce":"161f276aa6d7bd302976413d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"1d9187a32708b4e5f4dd9a2be1da7e5335d0ad32acaf1ce303040115a35253efa4c6a9869156122e7bb1cce949","nonce":"161f276aa6d7bd302976413c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"751da07afcf8eea6983d9cb9a5f14877b76ff0729dbac04ce738d064080292d0555f244f3b76016bee4ef8ef8d","nonce":"161f276aa6d7bd302976413f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"b558d9a60232cf287786af661ea3483f18c5e6b5937e220cd2cb5950c2c7ae7a0ff3b648e1af87cf16c674c573","nonce":"161f276aa6d7bd302976413e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"0d96eaf0ed0e9a59f86393313eec44b43ec448edc3e878ec32d285a47063298072c2dacb594ca572c286959eab","nonce":"161f276aa6d7bd3029764121","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"5b0ae69e8ad804c1e1ad1670b2f280aa419751762d670e8518e494918e639a209dc3bed43a1bb083df3c71eefd","nonce":"161f276aa6d7bd3029764120","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"432e4f635f1ae6e8903be2f346eb96a15f28ef48b6c000ea26c83c879be609ff3abb8e5530961f7aa5d775ae5e","nonce":"161f276aa6d7bd3029764123","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"fdd2c9e3d85c543da10d1e988277fa7b83187942effb46b7b7904de5f73538c88a2825e5f106435424235b1f58","nonce":"161f276aa6d7bd3029764122","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"550fd4c7405f8b55102a7a68e47037d234b38268475ca7927f776c2e68df7a9bb00781372378446b2c47014ca1","nonce":"161f276aa6d7bd3029764125","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"59a4a7280cfac040d1b3c52470322c56a7013a3b5d5d28ec630dc000826cbd311c379b569836261915f0de2d7e","nonce":"161f276aa6d7bd3029764124","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"72ec3d17677c5321f442270ab2dfb54242b7ef02714d3d0f9444e9e03af56441e4487d1bbabe47e469973dc0c3","nonce":"161f276aa6d7bd3029764127","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"b9f1ab9ab6f07f7a44f9cab0414140360d838c6b077c6ec09c56b6064567513cdb7127f72ca5409864ffa271e9","nonce":"161f276aa6d7bd3029764126","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"8370f84a8ba12219900feda8f3b17e1b71ae090908e2033e002cfd45320474d18825a01d77d82dd0af5aba08a5","nonce":"161f276aa6d7bd3029764129","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"208c9f883a357bea5df2644581f6c97733c084d8b7b760c5c9b9d1928ce006c2d305812bddb280044fe36511c9","nonce":"161f276aa6d7bd3029764128","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"597903dc82a3820370255b960827eb4d3674bf6e15f2e84194377f9a2d691c85409f6a47594b97ac970027a3e7","nonce":"161f276aa6d7bd302976412b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"bcacc48c667d2fd1ebbeed7db7c5ae7fd913e9f84b1cdbb7e9f190e08dccc04b6dfb1ea3cb714343b4954da8fe","nonce":"161f276aa6d7bd302976412a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"4e27d749bab8a062a0a3d43ad17af97797a4f007e3eb3100fc0a30717463178f63247efd1841a7a3d55a99fd27","nonce":"161f276aa6d7bd302976412d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"1443abfc017f7d084e7fbfe02421e1c4a0ee536c2b7dea7f44b782422fbc8fb58d949231c7d19445d9202c933b","nonce":"161f276aa6d7bd302976412c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"c3a128cad86521c554dd5cd9bcdd2db80082bde0f638c9478cb5ceca48aac9466c1a334a208d790855a0aa41a4","nonce":"161f276aa6d7bd302976412f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"60b192c85befbcdf6e9fef9bc8ed12f7f8b3f02dd12ab4ea61d12f0feba4371546982c04c1adaf547ed17cb9c7","nonce":"161f276aa6d7bd302976412e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"7d22322c9f99ee97fcabf91d8e54cc8089c30f954782dc9b7fb4d8312f3db31d43d9c47eef82af13a072ba0c68","nonce":"161f276aa6d7bd30297641d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"977a662ab513d51e3727b8755fe6d93eac15217791ca225ad75c53f23ea1b80b7e73a83671adb8f28ff7affe71","nonce":"161f276aa6d7bd30297641d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"7dae74b277624944d3d451a8e710d01582374d4693ba1e5d2fcd1c7f63bd61fc281c61644fd9a569ad203cd7df","nonce":"161f276aa6d7bd30297641d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"66c241a9553dbb9874075796b943f895191cde7a8bf77296141505cdf21d3a823b96f4f4f6a78546acca003481","nonce":"161f276aa6d7bd30297641d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"64266d81594539d642f92a605745c77580c252385c114090a79e337a4d7b1c5880c7c5513f88d68452175c93aa","nonce":"161f276aa6d7bd30297641d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"cba38b858b47f754438d04d54df0fba1a20d7fc81f03676d5e715bef55a813d2ef3aec97120cf292651dbdd871","nonce":"161f276aa6d7bd30297641d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"448040443877365916d1c1c0b22c719aad1b266f979a4cda75fd425d44d2c22cc2c9fa83fb17c78e8b729c321d","nonce":"161f276aa6d7bd30297641d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"28074b30ad560b2f154ab13d64a6fc79c66bb95db1638f6086918b8e6b2729a0a2ca7ee8182205f66c11c5c335","nonce":"161f276aa6d7bd30297641d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"0120f8f9ff8bd99f722651002cf4dd732faf962fedb165839bcab8fe00be8de45181a5a258392485f8cd3d8c25","nonce":"161f276aa6d7bd30297641d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"9a5c790a39db6f864d4d926d4d221f369df83a9a65d948477273895f83d4f35e55e5fd039c6f4a6fa05af58c8f","nonce":"161f276aa6d7bd30297641d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"da1a4040fa7fbeaa67d1df525198df5650b5d2059b6b2ef53c71ec074486ae3f376bd1bc778d16f2d646f6b9c0","nonce":"161f276aa6d7bd30297641db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"71bbf192898beb827d928d830eb9455be50b36846d3a6291f36e281d9545a14d1b27c745700eb0d68f4539f5a6","nonce":"161f276aa6d7bd30297641da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"a7971350dfbe1a1b274af5513e675775a230eabee400f268eaa567d04964822a3d3da5467c7d4dff39505cc021","nonce":"161f276aa6d7bd30297641dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"ac8dbc8af6134035c92d2769ce47c1d3f7648a38a524b03c0ffc209e99e7d5c75efd4633451b5408c52dd49d64","nonce":"161f276aa6d7bd30297641dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"307503de609b60360f4fd91439f0b199241ebb62676638acca53839574238aa7c05da2b192bc4b22ddf9d178b9","nonce":"161f276aa6d7bd30297641df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"a751d3231fb9c92d9a6c2c5c8a56547780e4e756251bfa1633c0c6bd1c7b422ddeb3ea6503240291190cd131c2","nonce":"161f276aa6d7bd30297641de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"79e9588be583d99cc3405ef0c51d83a83cc8b9eb1b4d5e765e1336c44e070e68ba62e7bb1a93123864cf1cf508","nonce":"161f276aa6d7bd30297641c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"e947e672a36ff31acdd83ac73362b5eca695f8417aa490014c65c23ca171ababe6716a84ddbf85a98f8c143d32","nonce":"161f276aa6d7bd30297641c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"9ca13e3bc66e3ad063f75ff50310115745668331aad1a86955ed077c310f28d59854c8177942ad600ca9932987","nonce":"161f276aa6d7bd30297641c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"4ef860175d3b6eb579556cacc612917bc42a0afa6718328234a6ecd8bbf148c77076887753c4533f4653450c9f","nonce":"161f276aa6d7bd30297641c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"521e56c9098463477f1c432c800180f1ce52f637f5bc8a9ef0596877509463fad46e47b1a42ff8657464fe0c76","nonce":"161f276aa6d7bd30297641c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"4a5b76d764e59bde50639ef84a665e8fd219ee6f17ad3bba8996945cb637cde008bb576fca2d753659517a640c","nonce":"161f276aa6d7bd30297641c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"2de4eeda0edeaab37f7ddaf04f0292ab4c83eb72a1a54cac98ed4f0d2a56acb20327ff29b7d2d30a1b04dffda5","nonce":"161f276aa6d7bd30297641c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"81a42bb2711237bd9eb62ccbcff77c4ff660175acc5bc128cc36a8bdab013e8cb91d7f7708c676f1c7481c68d1","nonce":"161f276aa6d7bd30297641c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"f48125221e675d025c1e84c58b4ac64002ec787e4a5626ccdaaca1b16374d7fa6d2e20bb09c438030a772d5590","nonce":"161f276aa6d7bd30297641c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"9614432db6b3ac4799bbe0ea3c620b1cc10dff64c6ba9b4d338c4a024f81418649db3240e03bc945e986f4a5a9","nonce":"161f276aa6d7bd30297641c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"6cf77e7496d386a6235c086eadb821a479b8112af5e71bf7fd3a0fa9fc3389b2d0d6c0a7370fab8c77acfdd476","nonce":"161f276aa6d7bd30297641cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"7b2241da2ba1d84ee5645292d277b596f587d4d77c784a641dd8d26dd3796ea53ddc25ec7abf1649277c615da5","nonce":"161f276aa6d7bd30297641ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"f4175542b3b2594b037e2300cdce8735dc13429f35ec83b816456d2d3bae1de9d31f1d5470ee135c067df71f51","nonce":"161f276aa6d7bd30297641cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"8bcaf4571046e79f436b820f9d623a877a0acb31a0794928758208bfec832df032621cff9598ed4ef05c3e56e8","nonce":"161f276aa6d7bd30297641cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"6378b7f2a21c6d38df691d84bf3223a723ef13f958567d0222cc85e27709aadfef41cf7d1d80dc2ba8b592fae0","nonce":"161f276aa6d7bd30297641cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"5b1ed889cbc17aa9eb34a4e4d40bd867cfbb39dd4614a1d841c6f910c12887abc7d0260d83a4e5165c79ab8b84","nonce":"161f276aa6d7bd30297641ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"f0270356ac0164c3a9e8a1a4a5c90edc15882bc4e473975cc49e9f540f034587358302d21a91ce2a48f92841cc","nonce":"161f276aa6d7bd30297641f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"1ad2f7457fd3830323a888ef26b15b57a725a06c62670d50b270a0a26d58557bfa26bc43c242f6319a69422b79","nonce":"161f276aa6d7bd30297641f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"13911ec10d248d0696ef937726c5a318633f5a53ae679ab2c7dd15f52f3f038596e1bf05576aa090b7c5e413f8","nonce":"161f276aa6d7bd30297641f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"10cf62b51cefa6d2acc1a018fc69183d7fa7ac3c43989d418f4f98aea22bfe08632c57bba956e31a46c6171082","nonce":"161f276aa6d7bd30297641f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"aa4a440e91a1775f1a2be9bba428cb579162a0b14dab602411c5bcbe03edd6336235eb15d28403e3bf11f4ed5e","nonce":"161f276aa6d7bd30297641f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"803bc7f52482a3662d4dcb98851e0942ca6ae19c6562e0e982ecc765261ab8f0e1d2ce2425fe80725dbd9d1a7d","nonce":"161f276aa6d7bd30297641f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"32f1d60e4d05e4ffb4d466c4398f4c511705857e02e6ab40156096978c3ef8ecb727a7b02f3a0b6ad2422d8af6","nonce":"161f276aa6d7bd30297641f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"67bdb62ae46ecd3a83e837de908a54aff64c367abc70b18d1139e2660d1dd61036da9563b526c8c22c04bbc6de","nonce":"161f276aa6d7bd30297641f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"cb9e1a594ea0b8039058474db1433c224c22feb2862bd91b922fcc85a4668ed7647f2c5b8506011c4575938079","nonce":"161f276aa6d7bd30297641f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"fb4ccc0d2357b2726578f31eab85c3990aa76a2b93b2d70496503fb990cc8ae5891ac32f779b7f6f19f7140c18","nonce":"161f276aa6d7bd30297641f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"d76c5224107a4472932dbf644390bba77ff84edf7dbdf2627dab5b168060aedd7ffa2f4474bc96e3b950a59965","nonce":"161f276aa6d7bd30297641fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"084322f23c966c1a7d87f77f274f7fc01be9c22f53e416637d8657d48ba59d72927096265755ec118ba5aa0717","nonce":"161f276aa6d7bd30297641fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"bf5e480baec71ee1cf71640d3cf9b9cc78c92940df299a1b0cf32ffbfe97a0f2d21f6384901d9d8ada95e4860a","nonce":"161f276aa6d7bd30297641fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"fa25924840ef7f0ea9a04d59e1c74cb743f35ff3402cdc8658305e52496eaa424f9519a02a2a5debc55c508a44","nonce":"161f276aa6d7bd30297641fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"fc2ac50e88b74a05f6747233a2df53b9eb10a1729044bf7c76695d9a02d23696e6f16f8f6f30082c4071844ac6","nonce":"161f276aa6d7bd30297641ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"07debd0c1bf580e481c2733a5bf4ae4633d0e9100867ede7a081326b9387fbb0117c0db914e1aadda3b045eb18","nonce":"161f276aa6d7bd30297641fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"bcacae3ff060bc48ad1a1d4a2183d7d77243d6649199ccb0b229970ecd9a9e80e6fdee00a5e6626f9d86699efd","nonce":"161f276aa6d7bd30297641e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"0742c05dd36b1c612c8a1a453c55ef07ddc908497c476a49cffc5f19e46fcd90f63e41eb00e72bbdf4f0773864","nonce":"161f276aa6d7bd30297641e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"8b6e60f92a33b3f8c2d4dc0e42eba71d206cbd2041b6eba7c99c5183932757a6b50974f4feb4ea3eaeb25c76ac","nonce":"161f276aa6d7bd30297641e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"be58b4c442a4d9cf4686473ef53dd4629da39e960825256bbb34b4673b80a77fe6ccff05292b01155b9d9ad4e7","nonce":"161f276aa6d7bd30297641e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"8c417005d7bd646ef614c1a26b001d4bfd725716ce27cf005b250195205f7cecd5c0826451289d30519bec35a2","nonce":"161f276aa6d7bd30297641e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"96069a7f02cd88d3f8fe6dd89f1ae306719ff682b0d66d063b0331e56673ce3d2eb1aaedb927d26ff11298c4ca","nonce":"161f276aa6d7bd30297641e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"3f0e664f6c170fd17727820e76856f1acfe930b2fdfe6619eb41ed153833f025c1bcc5c24af6248f174e0c9a84","nonce":"161f276aa6d7bd30297641e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"461ca177d099adc3b819b009437dfdff8c9b8bd5cc049b35989ef587abdeadc4d9450a6340df0e72cfb4e43da5","nonce":"161f276aa6d7bd30297641e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"a53b0223178b1f07152dc14ae390c65c924462c8a857a7341bf0e06183035f2024ace26bb5892ef1a1468725d0","nonce":"161f276aa6d7bd30297641e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"b5b63dca49a29e6f041463bb8a91a841e00925e66650cd5da9c02e8a31e2bfc7e0a9961c9f65513e401397cfaa","nonce":"161f276aa6d7bd30297641e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"6f812d78cda09b83e557974ef010e775e4cfbe1d6c1bae75bceab0b149dcd363a68c03c7da1eaa94e504adce37","nonce":"161f276aa6d7bd30297641eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"b74da83ccb5fe8bb02dfa4ef5179ec77d135405f640bbc9f59b34b748803de75c1091d4c8fc8c9ada4499412cb","nonce":"161f276aa6d7bd30297641ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"a05de36852ca9d0de0f365c06cb278e750bad3f5244b823550de9724cd5a174c94d27fbc6a98fedbb141959570","nonce":"161f276aa6d7bd30297641ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"2e2d660e920056d69f3aa1b4f69df06e38f8ae55579435490791d3b3dd537f37e92f91ec9843b89b8d6502ba60","nonce":"161f276aa6d7bd30297641ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"650be2867cb1eff7186c93a55cfa9793eb8765fc32a5f2fa87f4657090edcc3d035357b38ee7e9016c39312b33","nonce":"161f276aa6d7bd30297641ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"69b62ccc0f1109fb44204cee347455b768b5cb90b138aaca91cdac385e3e5589934cfcf1b388813afda01a4e39","nonce":"161f276aa6d7bd30297641ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"5c3dd67004a370f3b94cbdbb07025d795d93cd085f936dfa9a3d6d22aab996b06610daab80da25f2ff789e5070","nonce":"161f276aa6d7bd3029764191","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"36b7039cd97e46a1fa1791a9e53b67a2c51acba947c0719c1aa3467d8a24ce559d10f85eeca04b6e589f04cf2a","nonce":"161f276aa6d7bd3029764190","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"ed61057f02604eff5c69683af05954c51e2cdc793f5263845263cedd1efaf39c3d13880c640bf39ade7e384730","nonce":"161f276aa6d7bd3029764193","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"d59a24faa778f5fc63b4e2477ab00e505fa4555611bf3966dd33b24920e8295e77e0017b02a205c61eca196a0f","nonce":"161f276aa6d7bd3029764192","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"94670e716b875c5d453ca01eaabb1ff5ec82fb26387889bc8a13803361affaea35f3730b195495d75c05364040","nonce":"161f276aa6d7bd3029764195","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"0a92778e394e720cb943022da8aa43d52cca46319d59cbb8d6c913c4ef7bfe41628a13fcbf08a1c66c3f411c60","nonce":"161f276aa6d7bd3029764194","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"9a516de0c90a270f27c7048af9c1237be83345776b81913d420b319de17b14ed8511f052f8e7188b108a755e0f","nonce":"161f276aa6d7bd3029764197","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"27404d434c956496c4547c3349a3a64b6ffb2b4b56af791ae780bf04f865140246e78b58ccbdbd7a826dba214c","nonce":"161f276aa6d7bd3029764196","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"0257553779145ea6005487cf7e8143ff1ff62572ee3df63bc2b094d70ad5b518e9e83e19418cc4772f9322756d","nonce":"161f276aa6d7bd3029764199","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"6f9078747ad5d4562aaf7f06dcf71a7b807808e7bc521aabc3ea95fd0d339d60ef4ea9ef38bc14f1f6683a2e60","nonce":"161f276aa6d7bd3029764198","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"394b687d24df0a60349e800cf5eecb47aa16f330eb2f9df830bc63c7701f42220246720741d06fa43c8fc5ff7e","nonce":"161f276aa6d7bd302976419b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"aa582d3c90c6fd17b63ef58fb9ad4090f2adb4404bd3b8923259f2f597b217b60ec8c81f24a4e5d882bb761eec","nonce":"161f276aa6d7bd302976419a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"ba0af4c379c83ffd8fb7a7990f82576a7fc6f9aca8ffb1a5712dc02db2be52babaaa8db167687dc3b7f0eae80d","nonce":"161f276aa6d7bd302976419d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"5f450160363024a0a9b3ffb50117657bdc4f10e3821ec34f782dc06c279c7d8bef34fd9f1280db97e4e18486b9","nonce":"161f276aa6d7bd302976419c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"d9418ca615632791955877086b8096281a4f7c3bb27e2c9af2db54b9844315356b02a82c1e81be0c46712173c7","nonce":"161f276aa6d7bd302976419f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"64707c9392b3413ab54207f31e424d79a0c420cb599d584e4525cf7a7fe6d3d4a6511072c6d30dbfb4b096f52c","nonce":"161f276aa6d7bd302976419e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"63ca9bbd1765b4507f0bfa24c16905341497f70b2f4f0426fad451439d6905671e8b3155f16a1dbab085d24dcf","nonce":"161f276aa6d7bd3029764181","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"107048982395ca255fd3b53821cad3aa8c2990198c187146769dddae2f1792893b069a42257218513dad1e25f2","nonce":"161f276aa6d7bd3029764180","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"c06c55ddff6f5531bf3f3bca15573ee43290c170b6e89ebd116417170d6568b0a0806b73b7e55c50020d266015","nonce":"161f276aa6d7bd3029764183","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"caddba5676116e4b4b0eb03e1f8b85b92e5388246853dff4380f048014a8cd561df399eabc331514cb8c4234ba","nonce":"161f276aa6d7bd3029764182","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"1ba606e272f78170b9d1f7ee858b347ea48a52fc8886d501ce502fdfc0c52b6c98160cde6608775ce0c95dc7f2","nonce":"161f276aa6d7bd3029764185","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"fe0392844df639be7b91e518156a0610631779ab9282c8413bb32e4741d65a1146e90a03419befae95135f2e39","nonce":"161f276aa6d7bd3029764184","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"eaa399312738f252947fdeaa65f61dd4174afa0b5f8d9fe7179277d513003d024355c175ccb57b02693aa17f5d","nonce":"161f276aa6d7bd3029764187","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"26c95b001e9a22374da3482e3186140a9cb2b5dc16b8a3637f0682342665cd60abdb2bc4aee9f02733b8a350a9","nonce":"161f276aa6d7bd3029764186","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"67049b87365e437e791725fdac66b6e7b86abeb2f0576e860862af1505b1c964763513edaba8173ac6e57c0a08","nonce":"161f276aa6d7bd3029764189","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"87e4918992b7b90a0a222ee6c76d4651f83ed72c7ac2364bcee2ee8cd54317d615eb058ed16b7d31f61eb0b5f5","nonce":"161f276aa6d7bd3029764188","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"839272cf11d4b4a0209bd9fab36ddf3b22d456dd5ee45c310e25be3e796c71fccbbd19a556883b4a8fb902577b","nonce":"161f276aa6d7bd302976418b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"87c6382b2d93383c299d49809411889ad1555fe605a585fec5c74d08e19ab04e7b13011ce6b1e1f5aaa58399c6","nonce":"161f276aa6d7bd302976418a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"43f4b1eac29edda443cc8879fdc3cd96f67a0bfa99fbcbfcb8af7ce89af4a8e89d80ef6b018f875b06e8988c9c","nonce":"161f276aa6d7bd302976418d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"aed1d9647a25cb9684e4a0209793a3468ca27a91d90a31824e535e36af1415af26894a192d52b710daf7b2fdb2","nonce":"161f276aa6d7bd302976418c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"109eaf85a85014a24667c27d47f88078ae686a8cc28f5ed7509d97c5546e621e5969c8c455603d2ddf6713b783","nonce":"161f276aa6d7bd302976418f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"4eaecc1583dac5af6b5fc8d6a32f47d5b18bc23dcee5f119620e168a2c847e4877d76abef42646dd3fa147246d","nonce":"161f276aa6d7bd302976418e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"0e2b96fa26b7484a5ccd11c378daa27aa1f32e9a51cebcbe351aff1651b08f3fa759821323014b7deb0c93bbab","nonce":"161f276aa6d7bd30297641b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"6ba532fea6198c3d0d77687a676795307bf649296f8b5cd47382491a1b3fbd07fc6294e5cb0260766c6cca5409","nonce":"161f276aa6d7bd30297641b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"7ddfada8f6b66c6bedb9b094d1a00131e37c6216afdd553edc7074d724baf0ec6fa9fa673be7ef2bc552ca2117","nonce":"161f276aa6d7bd30297641b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"ab3435746269a0f8bfca60b523df79e4090e76f4766911a77bff49b03ed42c03aaa37c9f71c8e6f8ab28f80761","nonce":"161f276aa6d7bd30297641b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"629d74271245817300287e76c4551c3c556a6af983c49a06ad24bd60fac43c40fff74f74be093f37c76101ac14","nonce":"161f276aa6d7bd30297641b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"d3c6aca7b2b108e8766a54e9f0524238109ff1df49cf8278e0975f09524ed8c8e5081d61d25e070deb33ed1cd3","nonce":"161f276aa6d7bd30297641b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"198d897b399e013ebd3707d86a5b32ee83003a91c895ca96cf9d7228cb312c54b78d6a168a64faf0ba77bf38d2","nonce":"161f276aa6d7bd30297641b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"53113b371bfb165f34b7eebcf1385c89b59170e1893a26d69588053f0558b6f88b44e5836c256441f6a95b9730","nonce":"161f276aa6d7bd30297641b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"3ece33ad4aa3c94348eba058efbfd1d6dfa2950ce07a6bc925098c548656d3d48ba4971042dd318bec016d611d","nonce":"161f276aa6d7bd30297641b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"1954df1080c0ef81accc78034461958170263c846a73e3024cd895648bb8fb12fc439729e7268b2385722d34f2","nonce":"161f276aa6d7bd30297641b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"36f0fc96d4bba551b1d2ed3439959bf1b1a453ce7704e566e8dfae8e1eccb90f3bac9f6a18727dba904e17133e","nonce":"161f276aa6d7bd30297641bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"fc4ec451b1bbb24969107255bff4ca834789bf84e22cf548cb04fe1f2fedb48c05cde72f04bcad9ea8816f75f6","nonce":"161f276aa6d7bd30297641ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"e0aeb5e18cd7ac4e9c9cf31752c652050a383fc6c82de045e077617a928d9ba383660df2da844ef5cb721e3111","nonce":"161f276aa6d7bd30297641bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"5aaf7bc559fa4c95a4060c0fa4e9250172a9f0da26cafcc1efb39ad4f9205dbae92cd6f5b48ab88d76c7f717da","nonce":"161f276aa6d7bd30297641bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"f63d22194e334f629b7366922b979ffc6f71f3239c08b8409ffbfbaecb8a2359699614a0da06dfbae99d735877","nonce":"161f276aa6d7bd30297641bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"bae8143efba9299eca903ab17dc542d6557d806ee7bbf9e50ffbf56a13e4b16c068df8a4bac24ac1b54baf82b7","nonce":"161f276aa6d7bd30297641be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"8db66fc2691aa4f7623493235b27190e82c2ab31dbe58cd32b35aa075dce71e3b27759f01dc74290bdab4ee95d","nonce":"161f276aa6d7bd30297641a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"927befe83c7d0b839b13c14bbf3ff4b437cbb9593509b0895f6608d5cf19d0306e4fba9f4204791f21edc2445f","nonce":"161f276aa6d7bd30297641a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"7cd3dc1d5d88b3d32fe45ccc2914f4989ec98f1b7eabdac60b5c15733ddf78f7aea70dd325d992697e463738b0","nonce":"161f276aa6d7bd30297641a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"b6efdf3e20bc5d49673925c1ca7c9a22965b899c6dfb5f0755eb70845c9404003be0d70407d287ff875f894704","nonce":"161f276aa6d7bd30297641a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"ad04890e391d63383954d4e2c445c4fc5f71e6cc186fd923da31034a70aa1f1bc05e3a66456559e9c8a56209b4","nonce":"161f276aa6d7bd30297641a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"992272ddc2f3024bcc0abef45dabd50633c4c91f101755d1c96b1c4fa4083bbdd2632e28a73727fcca5523be76","nonce":"161f276aa6d7bd30297641a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"f962993314e9de18cb903ef5c75d9d48e9d67f3cf1b8516ede9a31b9a1f91ac56b9f83f1593d9447403f6a6eb5","nonce":"161f276aa6d7bd30297641a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"670e0720546c002fe3889f3649770a87ea3da375c9e791e302cd3cc9910c0671ea18cb6b65bf01f83361815f46","nonce":"161f276aa6d7bd30297641a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"3d7c3f8ba3a38d9cd2eece13ed40ccba0a0a89a1f88c1878b64dd3dacd8985807c005e7f305c8075490ccbcd02","nonce":"161f276aa6d7bd30297641a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"4b1eade1982b270811f48ccbc59d9396c17af8637c33121b13e531ce82ee44fe81d073fbc68c6fedce9fb3ff7f","nonce":"161f276aa6d7bd30297641a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"982a0cfb6818552627b7279df4626c846f280251713c61f5afa3826daea52aa3e8c2bfa200ef01bb7949984649","nonce":"161f276aa6d7bd30297641ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"2f932db25b6d71dafb9aac52477c3d858d42e8e410cfc4eb5c14c3ca235dc14e12941a5102e63f53e3fe28d66e","nonce":"161f276aa6d7bd30297641aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"1e6a5a8b2b2a26d68ecfee5d4c8e11467a510ff6329b6b3bb4d6321104d9484ccf380b6363de63ca9214e731c5","nonce":"161f276aa6d7bd30297641ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"6810e94410833b730d56e9f7e81790a6289237d436975bd43fa6d8a721fcc4f5c36522dfde7292ee1a90462744","nonce":"161f276aa6d7bd30297641ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"a8c1b3bd7e2b538eb885b38b5d4372975136d552c4c3e8b6bddd40e63df8f4c04e3763fc6cbefa2ff11609d352","nonce":"161f276aa6d7bd30297641af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"2b4fe7ef3b3b7ba1b89a2792cecb4bcf41e4756e4dbb1f3eae7e17dcf2c5b3895908f049af597f0132ed68970e","nonce":"161f276aa6d7bd30297641ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"5dbec668404f0ef7940afc990d8d18ecf310ecbd62192589be7c7120a0a5de49699084834b15b5a2c4d38f6c9a","nonce":"161f276aa6d7bd3029764051","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"0f86d39794a3d37b391e6f813da7df9cea25addb572ab981b56141ae726f89fa"},{"exporter_context":"00","L":32,"exported_value":"4313a336bc617f42dffed04c039724594bdc556b4bf71192b88ad91310afc601"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"107bb4fabef1741a4ae6a0beed5930702e37935de814f328c200780662bf3d8d"}]},{"mode":3,"kem_id":32,"kdf_id":1,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"c7e6f05f146f1d4501f6b30932de38c12b4a70918d5108d1d1d557bfd4c31861","ikmS":"53116291ecfc12dc1628e89828b265507d610190c255c095681e1a14dcbc9685","ikmE":"545fc015fbbe1e6c2aac275e31fc7f22c89d9c9e3c5675c54e1446b49c93c867","skRm":"7e2f75cd08060313583bfef97ee765b7e1298263b7c5459561ea576c1085b77b","skSm":"735a72d574724240f4e942e1b0b24cce6f69ed214429e4f9b9afc0a45fdf889f","skEm":"ad11a49efa147edc038fddafe5e6df7f8b621ad4bca89730154e644db05eeebe","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"e5d43ed47df8bad12d58de7b28c9eda2086f6e63afb7af872fb789384844643c","pkSm":"9478992ba096dfcb7f62540293802901e158db270c06b7c1ff8e51d634ab965e","pkEm":"15280746df632034bb86dde20324ab57fc772d07da1789673921145c8ea74a78","enc":"15280746df632034bb86dde20324ab57fc772d07da1789673921145c8ea74a78","shared_secret":"396d5e9b5d295dc55502082de7f6f9fc1391c4675f690f030862b21882bfc59c","key_schedule_context":"036870c4c76ca38ae43efbec0f2377d109499d7ce73f4a9e1ec37f21d3d063b97cb69c5718a60cc5876c358d3f7fc31ddb598503f67be58ea1e798c0bb19eb9796","secret":"b80690dc0a11402ec637465d8636d75244d11e7d29d3e0d80999a46243d186d1","key":"5f763de36998ad55feb925dbc2509a8d14cee80b59644b85c526f745902f1946","base_nonce":"ac3b6f34d0d5b20a32547494","exporter_secret":"096b72330ea640ba0bbd8a3ca4b75cab2a08c86d05f9f8653ca017923e39ecea","encryptions":[{"aad":"436f756e742d30","ciphertext":"cc9c605ee5b13d090f25b67edf3f7abb48b1dfc6f572f712e48bd67f2a1c20aeb431d65f02dbf7aaaae94cd268","nonce":"ac3b6f34d0d5b20a32547494","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"8b65253309a197cccb939ab2647e99e71978371eda75ea2c01b219abebc9b2b59b57b9d3dd25e9d16aaec00d75","nonce":"ac3b6f34d0d5b20a32547495","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"8eb4abaa0d8b23fcb8178ee69b76e8d7147d15d34e5c6b9488bd1f9b6e40ec8124f10879ce6951b37d4468b63a","nonce":"ac3b6f34d0d5b20a32547496","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"8728fadfbd3be8cb2c2c7893fdaa4d64e5f17fb36d8c78c6673318474ab568e3f3ed177a295cdc8a6bde7cb78b","nonce":"ac3b6f34d0d5b20a32547497","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"87bf28e98f48b097ddedc8633af82f954f48cdf2cbc91bc6422f7ef5749a6e9e79d9713d1667b5d926686d3be9","nonce":"ac3b6f34d0d5b20a32547490","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"040657ae4d568de7c78540eff8e4ed07562b4ddee8693fb3514eba5c23ecf7710d958e18a548cef452d03dcbc9","nonce":"ac3b6f34d0d5b20a32547491","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"67c0fce497e2b3c647d9b552168cf4ce16396eb0ca8c0b6ae5b13cf76876759abe137fd8298502563defd1bf61","nonce":"ac3b6f34d0d5b20a32547492","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"71dbf6fe2cdf160a261f3ed9fc12348e78df913cb5b9d61d158bb3581ef4bbb0fa0b860e3b1e7178162c10ef49","nonce":"ac3b6f34d0d5b20a32547493","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"fbe9ac47d66eef7351d6cde0756c843120f39b84ecef422584beb1680a52bf9f520dbb13b5d5ce6df1e1de75c1","nonce":"ac3b6f34d0d5b20a3254749c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"16f7606919a9fb5d893d4ec5c4f03af84120df1b0d26301a342d655c7e4aceae74f91a30266b2ee5b26a7bbe01","nonce":"ac3b6f34d0d5b20a3254749d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"97cfe0f47ed452519e32493e44921e5826eb139ee39b0e36a85696e4a309a9209be516996e86656ab6a24490a0","nonce":"ac3b6f34d0d5b20a3254749e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"8c1ef92477f8a74b6799cccb0fa81c864844c5c26c9bd8b79fa8e326ddb79f61727b3ea5fb17a568de081318b4","nonce":"ac3b6f34d0d5b20a3254749f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"5e06098c06c025381fb36b6ffd45fb33b05bf46c93946c724812d70222a400dadb40d1e2eea9c37619bbe8f34a","nonce":"ac3b6f34d0d5b20a32547498","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"c210727ce2ae9fdae6c7c8233d1b08cb34b5a717d6e27fc5ccc5a6fc74c12c011aba1afcb9849176b708202dcd","nonce":"ac3b6f34d0d5b20a32547499","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"e864485cb9c18caa5d3ca5c676cac19e944727759e568e507ef9fec54398fd97951e591ad86acf2c6ddbe23a9e","nonce":"ac3b6f34d0d5b20a3254749a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"7444940ac8da770bae93ee72be7d6076e1c79b7c87288807295b806bdd8ee541bd3a28dfde311c9590bdcd7aaa","nonce":"ac3b6f34d0d5b20a3254749b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"0f092cbf12b0370a30e474110fdafb062ab388f4d060312bfe831223800f2367abde4f5e3d49612c38bf6e58d6","nonce":"ac3b6f34d0d5b20a32547484","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"bc47f2edd4bac184158f5d69bafcd099f8cc453a3a846aa46bc92371c198ec340ea9c39cb72059cf1c6680f58f","nonce":"ac3b6f34d0d5b20a32547485","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"e9190c46782ef461128c9c5343e01034ce6e1c611214004e82b4965b3ad95ca670c28181447a0b0a21505df76d","nonce":"ac3b6f34d0d5b20a32547486","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"ae0e40fd32ca74f46842e539fcd8940f85be78e9ce8376ff238e15988f4d8f41a4283a133e528895835b0e4347","nonce":"ac3b6f34d0d5b20a32547487","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"d7594833099b6bce72f4455e0460157c902881f0ad31b31b3f54037a7e8c68774708f33821f33ca0bf1f255d34","nonce":"ac3b6f34d0d5b20a32547480","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"4b406e1acfef8a3ce232eb5ed3a64e0dc920fb8f8e43c32871b64624fa59a45d3f7bea1f28c8d5c612270e369a","nonce":"ac3b6f34d0d5b20a32547481","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"2f66c5f758ae7ff837d7d6cf6695d914ecaf8d9ade0bb5dbf70c719fea9556c0a28330b58f67de4611d10583d4","nonce":"ac3b6f34d0d5b20a32547482","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"051bb6944c36d4fdcb466b50466f84d2a64d01bf1a71d6d842cf946de3b7c4c3e7af490e07d1af0c44d7bd9ecd","nonce":"ac3b6f34d0d5b20a32547483","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"080185af1bb4c1cc82f6d3b9c3fd0ef950100cfe9de4bfd7dbc49479ae6c02fca4ce8c3d38fe941baf7e856fa9","nonce":"ac3b6f34d0d5b20a3254748c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"66e74221aa7018cb61ea3e0edb2bd1dc2db2596adea26025db9e12ed2bddf40c4a837eb31b9e5142b7add29fc5","nonce":"ac3b6f34d0d5b20a3254748d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"be0f7253f53e73ac6d264bbc0b4dff61dcb0ed88f7ac0623accfbfd2c6c6a8266b87194dfbea19736573331e7f","nonce":"ac3b6f34d0d5b20a3254748e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"658029d740a9f264723389008757e39b1ce25efcf46dc328a204d0f9c427bebd8e219bc8f7f44efe8a16cd3fb9","nonce":"ac3b6f34d0d5b20a3254748f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"2f911c3e7279ff47c57df44258723d762610d4d3383e3a8dc6cb0322d58eb8eaa6d72321e69f6148f1d527260b","nonce":"ac3b6f34d0d5b20a32547488","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"ccd033969ff6860993592476d19cb60613c5a10ad2cc54209778a993147bd50f2c6e05ea4fcd04cf3a3ca533be","nonce":"ac3b6f34d0d5b20a32547489","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"c5903bde189777e403eb05bf8da987db91d38b02232f85430d42e364fddb2d31fe17f6a580058861cba3ac6fcb","nonce":"ac3b6f34d0d5b20a3254748a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"2538af0afc2549ff1e8d36d01ac7574d5f06f748a990dbceec2135494eea61ae58ba22e695d6dde92550a6d55a","nonce":"ac3b6f34d0d5b20a3254748b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"166ee0fb3406845a020faee02582d5db527f612e785167c9d236fd581baf911e0c62bf0e2974686e5f5e2e30dd","nonce":"ac3b6f34d0d5b20a325474b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"e9dc9518323c94c5b84d5c5916a944f652c3801bfcfc400f8fe996c4fb16990324bafa0def8124b2fb8b12cdcd","nonce":"ac3b6f34d0d5b20a325474b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"c4eac722d3b631c31f911b74fe396645528d38df11cf11e874de95d2bd01cb90108014b65964facd12d00e1108","nonce":"ac3b6f34d0d5b20a325474b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"9b494bacbdd3b65ca85dabe2e6a146404054dcfee0e35c0a217848f641961c3ddb18ddb9b8bc316f202cf1de1f","nonce":"ac3b6f34d0d5b20a325474b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"da33ae89a442015e9b9e5b9c8c2f25e042391a39015e388f3622727fb34041a5641ebe91ea1daa7881031f5f08","nonce":"ac3b6f34d0d5b20a325474b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"975445bc58817b224d212261a03046ae5052251f27f01721189b19d9e937a13dd56dc7227ca66eecd0f1d6a18c","nonce":"ac3b6f34d0d5b20a325474b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"3139d4e960326b0a7ca3753f5b54d5f50e820df4671599cdd6e51c3eac337903841dea0bdfb860f0ec133b3e0b","nonce":"ac3b6f34d0d5b20a325474b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"5fc6e3588e52f651c9dce05519f94d4e3d702e001a9a285442fa2f72faca016dc203863544889f97b0117c82bd","nonce":"ac3b6f34d0d5b20a325474b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"7aaf7a7cf9e67176d81d86de36553d2baa0e51f081af33b19260038fe1c9a502dd55da000b8550596bf7ab2a56","nonce":"ac3b6f34d0d5b20a325474bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"3fc8cfdb54fde4bef061253b9d4338943a5351ef26d0b30c5ce121ab7b56404103702478e56c02d91edb4054f9","nonce":"ac3b6f34d0d5b20a325474bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"c5185c96005590e4ad0babb5a3c7dc97796d67a2e459773d060f4be4fec371da4c3dcc53fd94cccdb992f6d5b4","nonce":"ac3b6f34d0d5b20a325474be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"303e9b098311e09c1c4849eb6e49d8041d8f47a27cd62bbad15506a76a7d94749054365398d73159b68972dc40","nonce":"ac3b6f34d0d5b20a325474bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"bcda7d995cbc86ddcfd49c5419d28a171c4194daf72e79f6f16385ca5eb40a2401a5a2560e9af1fdfd494fd27c","nonce":"ac3b6f34d0d5b20a325474b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"b333e8118bd738dcecc6e9bcb22ada4bebb9f8492912a0ff3f9a6314dd3ff09aaa956c529e7bd4884250b54c8e","nonce":"ac3b6f34d0d5b20a325474b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"c0a4959356f64b48cfe9d3d247636e8e68be27a888541091e7731f2fd579d278889deaf24f8d07be8a116f11d2","nonce":"ac3b6f34d0d5b20a325474ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"4896e145a8f526e3eff52621f7836d0c24973d4908d10ae2535b420bc6b695a45d01cf2b7ec14703062dbd815c","nonce":"ac3b6f34d0d5b20a325474bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"b597c99e835240edd91447191dab5206adc8c5eccc7aea52ebe29482fa6b66cb0f3be4feb699c51cc180f92bb4","nonce":"ac3b6f34d0d5b20a325474a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"34ab9e9a7c50b7feaf73917a238b91c6815fe0313dc8cbf8b56b9440c92428217337e292cbafe39e87087975c4","nonce":"ac3b6f34d0d5b20a325474a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"3ae2a6fa136de7a58c42eee0f34cf4247158ea4ea412417f12f4c58d9d66ecc48534a9e2ba591c91dc0ff6a0fa","nonce":"ac3b6f34d0d5b20a325474a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"8d7525efafb7012ff867c46c9964c1225f5b606bccec1b76407986ee31c7d4a0f1d05bf6e4c8cf5f37b09e9ba1","nonce":"ac3b6f34d0d5b20a325474a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"9621e04896e266536105a7abbb5df8449367feb70255b74d95d4a21f99da2da2311e589344cb04af8bda8f633d","nonce":"ac3b6f34d0d5b20a325474a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"c64b823e2fea9906521d18d79cb2f5f1c6021cdf709dc566f7455fe215f30a73db9685e63da96d412bbac66807","nonce":"ac3b6f34d0d5b20a325474a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"5273044c2ccb629346c3cdfcac9f6c312961a9e2bcda126ae3cb12b38925548725a5af3ee6d974e18c726d35ee","nonce":"ac3b6f34d0d5b20a325474a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"09484a3de573f8fade54a662e7d05315c41103d4e4a729038c2394859e61ecfcc9b8f21d5ab2016bb3f9cda9dc","nonce":"ac3b6f34d0d5b20a325474a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"0b14d6cb9cfa6ccc9a7fbc2dff225c1addefb7df87025ebaa494cf5231dbfd88f602221aa3929dacc522cddc6d","nonce":"ac3b6f34d0d5b20a325474ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"12cbde2eb9206daab9416f79d5722e0b2649c9da6e27b19c417c6495971c3eac05fba5ca746d27d23825996938","nonce":"ac3b6f34d0d5b20a325474ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"64a0c3a52c5f37f094dc6f9c6bd5fbbe6165940f3ddbb6d5394290aae41dd60aa44ce59f32df7992303db9e9e9","nonce":"ac3b6f34d0d5b20a325474ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"d0f66df2953b2f151ceda74b65368a5e3cfefa0079bee080e8eed87748dcdeb2d5fe14d1a3094a8f0909beb235","nonce":"ac3b6f34d0d5b20a325474af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"0e467710a15b2f19030c0e8b0b59093d7c0095fb37006f40862fd83c1993d0262547243ae571df37fd353af998","nonce":"ac3b6f34d0d5b20a325474a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"29fd56cb8dea558bb62500650f40890fcc59b8a9976c8d917a20d4283cfb098c60e9b57de349598792a24e0a94","nonce":"ac3b6f34d0d5b20a325474a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"41eeb375d6c90be62968e11935ab2d52ae5d33298ed00e8e95475225ce019d7ff36c725f5acca55d64e5a3b1f7","nonce":"ac3b6f34d0d5b20a325474aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"5fee080a49611b0e525eda05ae64d8118138fc2088fa99e3fbce0fd559956fac66ed1a651695cc26b568a6cf14","nonce":"ac3b6f34d0d5b20a325474ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"adffecea5d2e9cf5c62ea601e0c1665467a1f28d01a86e3ba9248c74ba5cc49061970d23b7585f7f499737103e","nonce":"ac3b6f34d0d5b20a325474d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"568e7c539f41d7400bbca1aeb50678aa1909525a06be3b772fec02ae9c62a9feeea6b58ee87e8ac25133c8a06a","nonce":"ac3b6f34d0d5b20a325474d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"a6e827dc9c490e57cd4e7bcd06cda74697e6455f9e090ad096c11da9b84f8a627c3757b8998af59280f3698543","nonce":"ac3b6f34d0d5b20a325474d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"da492b6937a0e3335af0e2cb5ad4c2f6a629dae9a3312d6a1e1a5c59c117512132868999c6c69cd0738d7b449e","nonce":"ac3b6f34d0d5b20a325474d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"1e4d2ba2ff385166051853df8959ecc19432833604654b198b9ba0ed026c1a818776615d91e4d6113deab440ae","nonce":"ac3b6f34d0d5b20a325474d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"19c3f4a53ecf295a8f0d8fda5102706058b648d6cd758f33ccedcc2be7bcbb189d08742a4bd90a5d40a4d46bfb","nonce":"ac3b6f34d0d5b20a325474d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"f2e5e71e539f08ebdfe86a8b1b7b262b653bf4587045e6bfddc8600d9d63145321325c5c81b677c4ee8478be2a","nonce":"ac3b6f34d0d5b20a325474d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"20e7d7f26e77fbc51829d154ebaa8d1a99a756a5ec9c48d18c96ee60fbfa7ee8556f29a07091de0323b8959da7","nonce":"ac3b6f34d0d5b20a325474d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"0bc86e1a6273b366d56dedea9c55fd382c1664330253f71330a5211730d895f83ca36343a642d647d3d0a4cb4f","nonce":"ac3b6f34d0d5b20a325474dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"f998aebe945d3a3a3bd2001092095230a4b5ba3025a5ffb662dd03447975582523d2ea767ae6f394acff55f7a7","nonce":"ac3b6f34d0d5b20a325474dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"7b6e1dbfae922a003daec3208735417cee310d6c566f0aa462e35c824beceae42fe537e7cc8404ea7583317754","nonce":"ac3b6f34d0d5b20a325474de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"4de42d06433efb77444d87f55c2ad58cb79f3583b54f01c8d34de0496131ee99f4ea6ee52cf22d247d5408c30d","nonce":"ac3b6f34d0d5b20a325474df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"523d5c6ac84318c2def10a92b5c7fc4bb7e0b179aac78b74cc3ff22c60c9fb76da7002c679b35790358a9d7a17","nonce":"ac3b6f34d0d5b20a325474d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"4700fc742d4364d9eeca0c78bc31b83a1bf322ebf3db7fa42fb5df25b6bef42765f659c8b591ef200ce5b3f146","nonce":"ac3b6f34d0d5b20a325474d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"ed0f6959b417448758cb27ebc73663f8b44cf95af7de471012a5efed12a5045e5f6056462c814a11df63f6f6ad","nonce":"ac3b6f34d0d5b20a325474da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"82cf31e1af8f06e9ce7212e21af7dbdd80f51dae03932bb60f8d6878c002a77d16c003e82839fec13cd9cb0964","nonce":"ac3b6f34d0d5b20a325474db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"511fec9ff8dac56ab5ef30e1a2f4bb86fbd2ed654ffa5524f6bc4297e5d9bbe12526878fe4bd8c442737ec6b29","nonce":"ac3b6f34d0d5b20a325474c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"b1b4680e8cf994bbfed46679c6e70907a1e421a7b8788e3e53379daf9f46154c73b6636f93105e4d641bc09cfa","nonce":"ac3b6f34d0d5b20a325474c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"fa964e884e9dc7c8a10b26081b9a927ba815ac77ee3eaf5e1653ee61451fb2dbd397c9951086f4eacd7e92bd7b","nonce":"ac3b6f34d0d5b20a325474c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"30451fd6dc30ebc7b136d848be45386de05bfbe1cd557bfdda83f3da3fd40733bf36a8466fecdca3d58af8d08a","nonce":"ac3b6f34d0d5b20a325474c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"8ad7bb09a6a4dcc60add8b2e3e273c179f6430f10b0e3b612d82b123468f236176f7914f58749230a4ceea3e6c","nonce":"ac3b6f34d0d5b20a325474c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"f6bec7fb1dc0527d87d32a80ade8a04adef29ffc82c4ae53b865206d518fa2fe9d8e1f51eb3e039ab659ab9567","nonce":"ac3b6f34d0d5b20a325474c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"fe9f7f836dce9bac10c7def1f19e71640f697fc1bb16dbf95b26b6f61e5d7d9c3aeed70a8ffce2db2b4dc6c566","nonce":"ac3b6f34d0d5b20a325474c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"4fac16bb002b68c77657153779162b66587f27c9bc113bc618c2bbe5516fe9ed85d3f46dc6ee25fbb196d193c5","nonce":"ac3b6f34d0d5b20a325474c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"59e2803ab4b19f8753e7e24825632a30f11d9406e767905840eae93c7297d3b98bcb189d809b1d9e9c1ab0a11d","nonce":"ac3b6f34d0d5b20a325474cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"c06fb9bfd533303ba503e459038e2d93c75a3c0cb32fece253851cec1dcffa8e3b8e2ed2a478879da300b6c5a5","nonce":"ac3b6f34d0d5b20a325474cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"e0b0763d7ef145ce219324bb9397cc2b916239ebd2d06fd534fb14ce548e97a3625bbb9c22fea2357d00f3a46c","nonce":"ac3b6f34d0d5b20a325474ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"e8269e89c24d70dc337ab21e09c9cc6b01973356f023eb4da15e25fc9add487872656941a253fe9525372070f4","nonce":"ac3b6f34d0d5b20a325474cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"ecd530c5114adbac21dabea3a9e07937ff2e0410aecc7ec56f1d7b7153398822add5ebad7832a253a5fee428dc","nonce":"ac3b6f34d0d5b20a325474c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"576e814746e14e642e601f9fec9651c67146e2245e23a54e80c3ccf3aa6c32305590c5ede3fe5f512701832c7d","nonce":"ac3b6f34d0d5b20a325474c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"8883de621627883098a93420d2be7159708257ea0ea4b21ccf191c22b5f0703d2cb694e9ac2c86d9c6fc227229","nonce":"ac3b6f34d0d5b20a325474ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"5012e6f5875952bee7dabbe05fc8832018df9b557acfbf0cba7f693afa7c0cc9fd93f68662a1f8365275469b04","nonce":"ac3b6f34d0d5b20a325474cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"869aa2dbfa8ebab4de7b63b0d0cc6fec7b4b9398f8bd45ed6eee8e381ae1dd546256dd998a257ba1f13276eaa5","nonce":"ac3b6f34d0d5b20a325474f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"02186175368ac0c84acf61a60c658fb22f147e1daac2ac627cadb29d5d8490f93db647ddc5fef2dfe331fb84c4","nonce":"ac3b6f34d0d5b20a325474f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"b8101d668d8dd2f3349afc149236be846d67a47f31f6e8c7fa76427b0bb65a894775021ecac769e7ff296a5fc7","nonce":"ac3b6f34d0d5b20a325474f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"cdd6ebbf2e017c76c3909e0ae5afd750300cbbeacca0ad93551eb7b4e4ef812a2974a1cefc5a7d730f18847be4","nonce":"ac3b6f34d0d5b20a325474f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"6baf545743beaec62c3a7079c3f4b181324b5aa148e700e18997853d94576404ea7ee602456e90424f5e82c63e","nonce":"ac3b6f34d0d5b20a325474f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"671f9bba0e1a5cf243f1093e150d72ce6382ee20c0c73953a69cc30f704cb088dbaa11df02c313ba51c0157eb6","nonce":"ac3b6f34d0d5b20a325474f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"3314155720ad61f4bf6115c209b8e54c7c1bd1dd58306337faa0debee985b812352c004d1d9bdf0e696f02b49d","nonce":"ac3b6f34d0d5b20a325474f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"1ec30086f368b7bc40855d4c16f9d3a9e0d3483e73048a47eab772ba5726b0e04d8682cd5f1c224364914c6e4c","nonce":"ac3b6f34d0d5b20a325474f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"ef9f580749a1dc0b4c7bcde469bdaeb7345633052e5f058619f36ed221efee41b6e05de1f1fe7cc9f122075cc5","nonce":"ac3b6f34d0d5b20a325474fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"ff85df6089ca02e7aece2bbc526d186d178751348dc63d1a79753789d824d411ac3d7bc3282c20204a2c9ebd90","nonce":"ac3b6f34d0d5b20a325474fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"352fd20fcd7cc40b2165f1364818eb8f3c7965136f00470e96054ae9f869674a3c19fad891ed44163a99f56877","nonce":"ac3b6f34d0d5b20a325474fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"a7a97ae5fdcd7d98ea5531702b981fb4b5c41b5fc0b19af99497df2cfd77d806526ab0e1267d7067b1821e162c","nonce":"ac3b6f34d0d5b20a325474ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"c95c35c6261ccda2be8323d8e9c577ee12dfab304a8e986910d47cf61ed68c344fce0eef2610ecf358372d42f5","nonce":"ac3b6f34d0d5b20a325474f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"b2a7c4512943f85e9ddd84b8367d93a706e96af2d956b9c51ce726ff1783803762f9c643cf993a3bc5eafd5af2","nonce":"ac3b6f34d0d5b20a325474f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"e687d1eab06a4c125843ead38dd24dfa4377485fae4053c49bfe4fe154e6ee7b276b431ea252c7df1a725c6822","nonce":"ac3b6f34d0d5b20a325474fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"57e3708400c12c374842d703db654c312ca4e817bb1624733db64f8bc45d285e82b6161b0ac89c90f5282fe500","nonce":"ac3b6f34d0d5b20a325474fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"9f7df3a9d746ab21e234fc329930e27cbf20a20c4bd680182e3292ce8007198e66d44f48e4a66f5d4b174cd7dc","nonce":"ac3b6f34d0d5b20a325474e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"bbee6a91d0773c98d05b0f3bef6dc334279c51d0df5d10c007d264ee535cac89ee0f09e5e8db2cc7077349bf46","nonce":"ac3b6f34d0d5b20a325474e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"ebd471f8b64d35097ff1c525a03a0b885e3774e2891c9dab239deba379204820e686d6c9d0b7c57e17824707f1","nonce":"ac3b6f34d0d5b20a325474e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"e43c15589d6512bd8d1e14573f40978403e6b50fc327edcc8f8e24881246fbb8ec81106b5c753b7a985b5ac283","nonce":"ac3b6f34d0d5b20a325474e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"e3568dddfb07540039ef9fca1a7e4dd88e67d30625285030339e103e7646ae65f11b047114913eea8b3d235d32","nonce":"ac3b6f34d0d5b20a325474e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"525011b74943ce9830964f0e10cf4618463aa1352aa5b0574abb40ba1ccbbea7689f4f1e77b135104d6612dfbc","nonce":"ac3b6f34d0d5b20a325474e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"2361be3f704a3ec29f4135cba2d0fd0efdd84229e5ed844be921e017e44f70fc8992fa3e2517df3293295389fb","nonce":"ac3b6f34d0d5b20a325474e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"caf264e2828755350890fe568c0df530d645f54c6b6794e3efc210cee85f040a31bd27bae2214a66f7ba778c9f","nonce":"ac3b6f34d0d5b20a325474e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"1300c430700711439fca521a3f63a3cc1c8222ba75c14585706a22397be64104aafea1f74ec6df519357bcd0a5","nonce":"ac3b6f34d0d5b20a325474ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"fd9fdc6d07be56a29d67c22e16092fbf712a25465204dedb62eba4b214488924699f2e6b4e105b046986991b65","nonce":"ac3b6f34d0d5b20a325474ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"12d6faac31760fb99a38a462be669ff5094cb7bb995c4e1b1eaaf4868d05f04625bf8cecd7cde0dfa1915ed32e","nonce":"ac3b6f34d0d5b20a325474ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"882697dc0788d85f0b322f15d09d74355793887d75ff0ea8ecf22495dd19ddbb319b9b7d6a76f6af7f7de840eb","nonce":"ac3b6f34d0d5b20a325474ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"1e7e7e49bb2eb0fa1318702282d0bcde3cef16c576c3b105267bdf7cba927000018d7ab20b0b9225647852b6c8","nonce":"ac3b6f34d0d5b20a325474e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"a48f67c0c22686b08b47185c6b681f80993076ea298d067ab48b59aa7786ab6af27a13252497a7d94868f824c2","nonce":"ac3b6f34d0d5b20a325474e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"dd85783c1dd0de0e8e11d78813f87785b9c3159528bfc908491512ce768d15321f6e404c8b97f32f56a7b90214","nonce":"ac3b6f34d0d5b20a325474ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"f58d18d992c045542d487f52aa08a7ba6b244c65e54541d6862a2aa1292eb2760ce8242b7894b9ff7e59eac400","nonce":"ac3b6f34d0d5b20a325474eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"8974690971a649ce0f7ab93220773938acf868d1006d1c050f825e2fe68a572ad91aa25eff282f5ed5b2ecb9b4","nonce":"ac3b6f34d0d5b20a32547414","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"7fe02c0d2c85ec30e3be433050a0f18c2a9e5200bf9ee2bb5e7b1099a553fa7a7c8178aca5e0e62592de45dd53","nonce":"ac3b6f34d0d5b20a32547415","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"c17d78b18c0d45c44c21d7fad5234bbee7ed14fc60210319e1d7597aa73498fe939ef99371c1a32a688ddd1968","nonce":"ac3b6f34d0d5b20a32547416","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"9cf399e03571c4d107aac6c19e1bc39141701936337430b307a4f12efde012547913e52d0a7dced5cdca71e225","nonce":"ac3b6f34d0d5b20a32547417","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"55854acad5593e7046ab0c055bbacdae5e1e97a9050f45ed0c61e3140f5193a98cfc63a10f8e6ad0fcc78850c1","nonce":"ac3b6f34d0d5b20a32547410","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"19b1b54c5fa2e281cb031a964c54858ce72210ef301a13ea4ae45bbc52579e9e1ba772b8bd871feff619f72337","nonce":"ac3b6f34d0d5b20a32547411","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"675ae4d89c1be10e7750bba9eeb2ef34717cafde5c9ab395af145bfde52bcbcd85e1cb565b179bd02bcd425366","nonce":"ac3b6f34d0d5b20a32547412","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"a20ad69faa3e617765b0fb64ccd0996640b1b42f7e0a3ca0108e45dbf9801b01decfad291021a8243f4b0cbdfd","nonce":"ac3b6f34d0d5b20a32547413","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"aec65014c948de2c1ab51962175ad4c48ade40f7ba3ec96715013e2cde6740484cf4f278a152dbb69dcfc435eb","nonce":"ac3b6f34d0d5b20a3254741c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"5c66e7ca0cfb6eff5a27eab62be47a90982c4f82eef04a598ccbf27e9da01a20740ea65aa543e8ada5eb2bafcb","nonce":"ac3b6f34d0d5b20a3254741d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"7df60e31169651ceeb344dddbf8d84d5eb1e41133f4c0cd6cf7adc3577e1d295d14a49ea6a121795a97383fd5f","nonce":"ac3b6f34d0d5b20a3254741e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"1ad537a14e172c544b47da26db891afea06842f20b2564b685a1228186fb830ce6d1a00ec09f23c63d8871d276","nonce":"ac3b6f34d0d5b20a3254741f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"3bfc52bb2f6b5a73a1ac456bc94d995aa4890499442661e5ef1b862d7230cc87517fdb62e4a06ef430f6fdb6fd","nonce":"ac3b6f34d0d5b20a32547418","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"f2ccf78bac640719c1eb42857725d44298538f6cfa62c9dcb356d3fa6503b90aa9a63630cebf0cce3995bb675a","nonce":"ac3b6f34d0d5b20a32547419","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"abf28e12b14dfe3caf36b4949d543805b89b5fee5f5d125bc7994e43cb818160d0e92b704a560d1d735bddde49","nonce":"ac3b6f34d0d5b20a3254741a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"502790d3ef859f9b632a372e21e855a5d2c84bb5cbd0e3e9f6ff0b04301718847d0874ffe40ca513175027f7ef","nonce":"ac3b6f34d0d5b20a3254741b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"9e66b21548df5a73c12e7932390c1768de80129bda6583850c4983a532e84c49ac9c113b891bf72dcc9ccd1464","nonce":"ac3b6f34d0d5b20a32547404","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"7b732fc8575fb453e45de08507bb52c93d4a54c16dae13cdb8268469221053ae4c0451e7dca24689e2c108826d","nonce":"ac3b6f34d0d5b20a32547405","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"f8f561b24322a75842345a7dcb4bb01d66a2080498e39e2db730830efbc8c8f81530f8ef5c6565b90365d1c2e9","nonce":"ac3b6f34d0d5b20a32547406","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"7d5bfdba5555d5d05cc3bbe80cf5c8db2a1baee5db9bb56fc119528d5121c364adaf626d4660fda3acc36af8f4","nonce":"ac3b6f34d0d5b20a32547407","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"aa89e9275aab60b8947621efef4341cdb89ef191e4100885677f1002e5c330afebe89a9cd8e10d27e499d78c31","nonce":"ac3b6f34d0d5b20a32547400","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"f0277a3e23d168b188ac1d81d6c6aca193b0536c0c624c20839fd8be525d0f56bd3c84c43ef2556e8d4c316044","nonce":"ac3b6f34d0d5b20a32547401","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"a97938d5e3ce8dbce5c5d81426241a32f6061fe9deeb6b00363374c2651ee344030b2832bb9a1d1b98b5413c23","nonce":"ac3b6f34d0d5b20a32547402","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"e55b9a3a89adc44c8fc245e0d752b0271cb90fdd53ebc08033fec687cfffdb98738caec6377f857718019c781a","nonce":"ac3b6f34d0d5b20a32547403","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"87d0cfa6edca79cf7785a3c568176a82157165977dc0bef7041e3de2efd76e66c891442d36adc0a966fd9d0e9b","nonce":"ac3b6f34d0d5b20a3254740c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"d91e42c508e2940044df91189a9b3c7704eb5f1e48d78b321d514bff2cc6d1b8e5e624f8dc204d8e3728e80c1c","nonce":"ac3b6f34d0d5b20a3254740d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"373f29e518ff2f41a97e1ceda4a89aa30e8069cf77de62c35462798128e6e890dbbb12b6234a6fb8fbd9dbb809","nonce":"ac3b6f34d0d5b20a3254740e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"d6231767c6fdf2c90c6d90831431e30c7e4e821744ff1a77d5f2182b147fc79f12378a97b55610438d0d6df445","nonce":"ac3b6f34d0d5b20a3254740f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"c040f3d41bbaf86f9931c84392c36280b02c2ad4177c3a19df0045e5ec030936ede505fad5a669631ef1b1ec77","nonce":"ac3b6f34d0d5b20a32547408","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"039f2996eb6bb4cc39f6393342f7597bdd63678728c71f4ca401c525fab2e9d7b1c924d6ac6d0c0fb882456025","nonce":"ac3b6f34d0d5b20a32547409","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"d9a1e967faa72048b8e7df445ef7bbc06b30d913d5d765adf52c6a0a600eb7c198309610765d280c0081554e61","nonce":"ac3b6f34d0d5b20a3254740a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"d13be939851ccc0700ad8f5bf8dfc858bf79743650c7def1a2ca8ee0436278e7755cc1d5f4f416e44e0498c365","nonce":"ac3b6f34d0d5b20a3254740b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"6d0520cd8c4732bdc1a0566745aee91c4486fc1560b4fd67857d7a8d1dad4ac3ad7582154eb5a312ba33e6c6dd","nonce":"ac3b6f34d0d5b20a32547434","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"615eabdd0c50c4a3c4506d5073624e8fa57aacf6be2587fa26ef21dd0fbf72f232346ea17ff3ddb0176575ab6d","nonce":"ac3b6f34d0d5b20a32547435","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"91273709b02bad9685c311f3b4987db0642405ff3eabd8419f2825cbfb6b927ef2fb1b488aebb9adb3be8f8f10","nonce":"ac3b6f34d0d5b20a32547436","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"a46410fbe3fe94b6216d61cdce632a1df8c70bfb126ad1f19a39b648b32f2bdd1f69e776366e64578960cd0740","nonce":"ac3b6f34d0d5b20a32547437","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"5d55acc4c06446dee3f5ef46d615df9b05aa098e7dbf808678829e071a3e91e0460ab96bc1eb9255836cfe6a6c","nonce":"ac3b6f34d0d5b20a32547430","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"459f773fb2296d0f669a339dce4cf60a6008dede8493e21c79bcd6259bca58015d9827b8ba887d00ce2c866bbf","nonce":"ac3b6f34d0d5b20a32547431","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"05af68c8374af7519f9b8a21ee8c519afb331c8ccceb8a1ac0ce94b4548cf1566bb397ea4622ee732c5a63e4df","nonce":"ac3b6f34d0d5b20a32547432","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"327f6f1c6ec9e67faf4dd2a590df878c003cc1ecf271e7590076fff8a545372e3f36ec86c6b035c2c1967c4961","nonce":"ac3b6f34d0d5b20a32547433","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"bd2e2e68e8a264a6c3570fc961b3123aaf2510949cae81e8c4c32377382902feeb4ff6496ac1d4f311a09edfb5","nonce":"ac3b6f34d0d5b20a3254743c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"6c790802a73ea0310b51a88dbd982d2d12afb3e0132f8616a06c7998533b74b16cf40561bb53ad10835cf62532","nonce":"ac3b6f34d0d5b20a3254743d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"1c308fc7993d0668beeb71bb6187485247e0ad53e53d5d8bc4b1489613201abb7530b3ac2fe0d92f94cb6fd7b8","nonce":"ac3b6f34d0d5b20a3254743e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"ebe91dcc5a884612ab5e5273512bbd5739a67e2a640c55e0881019a618cf3fc7420ac7b52987397813d4f90c6b","nonce":"ac3b6f34d0d5b20a3254743f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"baf431f17dcedd18cbe6d3f321749042b2397f2ca50ae326e8c8d7e8f0a6c0217aa4c8460648e783e0fdbc207d","nonce":"ac3b6f34d0d5b20a32547438","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"d65a91bdded770c4a40e9ebc52ef5c444738b252ec69c055c6d7526ccd2a519b4e9704c503d62c826acd66093d","nonce":"ac3b6f34d0d5b20a32547439","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"296cdcfb582d4b577c7ed41b14875e75e87d2686d83572680c9d4fe23c9966e66cdf9eb38ea957002d8e905279","nonce":"ac3b6f34d0d5b20a3254743a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"42aad65a91a9b66268c0126d810134304f0f782b9d518079e945867a2f4922e55e5ee3dbf0abe8e4c216cf25c0","nonce":"ac3b6f34d0d5b20a3254743b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"73f0690ddd2347bf221224da3841e6dbe6d9af7f9f9d1ff2375cda5a77eda152603099a932fce5b6d519e8c725","nonce":"ac3b6f34d0d5b20a32547424","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"11ea49de9310b0d4a8ba44f2f0dab0df70531e18403acecccb6c11d0efb3b4d60cc4f3fe092bb93483c0e811ba","nonce":"ac3b6f34d0d5b20a32547425","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"424dd7c534e0ff504331a070af840d4c8fb0c40c7c367ef6157b318ec4c5737256d92625141745cda33ba6a21b","nonce":"ac3b6f34d0d5b20a32547426","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"bf844e076b62063ea40a189bd10970518e75d5cec9d453b3220aa49310441266e58c9107c6a24bd6497ad43459","nonce":"ac3b6f34d0d5b20a32547427","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"769d9ad0bc96b20ed884aa9c1cb1a5c614f9529ace388c154659ea8f2d61ec85c84fb57bff30c1154ae2622268","nonce":"ac3b6f34d0d5b20a32547420","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"78eaecd0e1134098e7e1164e8d075ca456357295b3cbe7f7ccec19908e268c565643e201550ea981af848141d8","nonce":"ac3b6f34d0d5b20a32547421","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"bdba7b8536c4b36d64662f0d7a6dae00cc58c0b4b63637e8381bad36d64b72e8125fb47d55c1ce5cbcb34bd67b","nonce":"ac3b6f34d0d5b20a32547422","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"6a1d9a3735096823cfee4030fa96582f96b00ca59b0eb08e9584cc52b8d32aa4051d0667bca173235ec23949ad","nonce":"ac3b6f34d0d5b20a32547423","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"57e9a6ebec25c71b8333d301c280bc27f562f208f1236f4800914ac3fb41d4011c2ce1c0eef70e05274b3fbca8","nonce":"ac3b6f34d0d5b20a3254742c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"196d72f46fb95b72c70435e443fa4e66b68c7391034463118658267e1fa06d875bef5d0440ee857bfb2e0eb1d2","nonce":"ac3b6f34d0d5b20a3254742d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"906d14b1d5329acf9559fdd7d58901ae3ad834d94fe9afa28938d48dd6f9b7854cf9e35df4d21a0481c768cbf6","nonce":"ac3b6f34d0d5b20a3254742e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"aa6732360d83ba7196f569356534ddf959f278b06b2ca4d99cd79c8939f02ede8086393d516cad3d87a641efc7","nonce":"ac3b6f34d0d5b20a3254742f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"607a4de960c3af329ee5407cab07efefa2da869bf39e6c903e9942c7a36eeee77e1e7de84ad7c8165484a22a5d","nonce":"ac3b6f34d0d5b20a32547428","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"bfbff97a0be44e654b492d4ee037872cbde6c372c914b6015100f243b4c7c0f8e2fe43a8ec6a7282849bc58b78","nonce":"ac3b6f34d0d5b20a32547429","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"56b0b48543d92f163adb31ad05c0863553d2e0416125ecacce4c1820c9b0f1625428ebbcd99062d31f26aad80e","nonce":"ac3b6f34d0d5b20a3254742a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"228e082451c1f9ade8ea13aa5ab0afb4daf1cbdf9d183ebed894547c04e18ae866ffc4adcc8736536d71174661","nonce":"ac3b6f34d0d5b20a3254742b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"4aff0f8a71327366e863e09087e1bf6e1c96796e6d56c98c98ad617d817c653b3464284a5b507ee13a4cfc94fc","nonce":"ac3b6f34d0d5b20a32547454","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"8dad92b979aa85498bdd3f55834ce93bc8a451705f373b3e866bc80fbcdc42688445d048b11f6a7f233fd07bc1","nonce":"ac3b6f34d0d5b20a32547455","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"017caea31bb24f4be24d7619e358fd5e0c3587065502d1a089fbdf31fa7bba1189d02c9d597ca68a8b5a05cf62","nonce":"ac3b6f34d0d5b20a32547456","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"215d1bd302e93b98b056f31d8030dcd34cd888a0a10a5d7e2cd5f7585db054fbbd50b5e83c3c6234b06289a2cc","nonce":"ac3b6f34d0d5b20a32547457","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"51fd38f70f20a7be8b7649faa597a2d3d09a22d787781c156c350eed48953263b7dc6bd2baad598edc7e3bea91","nonce":"ac3b6f34d0d5b20a32547450","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"e4ece2dc093e1e54a6ebc71eb56e28a3f997fa83fe130a56a74c0a79a5daa2736a04f95a8b38c8451d4d4eb4d6","nonce":"ac3b6f34d0d5b20a32547451","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"08a81505b3139df8820c08380e202bfb3657f1fb8c40a1c101cd87e323c949f56a7d2f439e6361d073dca0d035","nonce":"ac3b6f34d0d5b20a32547452","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"fcb98d992c3792d0ad5cc98a3a8bd15e194eeb13dd35d94771d3b2a615ca200c64d85d318d8fdce8686e5a6163","nonce":"ac3b6f34d0d5b20a32547453","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"1f423d7a0ec943e7aab7486a5e96fe0b83c984cfd0407a84cac4bea1edd3101d0f93b97144d0cf8538ff9a831c","nonce":"ac3b6f34d0d5b20a3254745c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"b36471252f7a620646ef5e22c30cb23182dcdf3377e9d1d3db0687a8c7f9e51c28e5ddce61e0882decd1f31fc6","nonce":"ac3b6f34d0d5b20a3254745d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"fae1701623273f48d5aa116f881b9fca7ed1c0852ef2cb95ebc3d4f6c44c36dab05f21e54429bed432b2abe5c9","nonce":"ac3b6f34d0d5b20a3254745e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"52a1aa6d47c8ec574a4a75a113b1d298915a125eb56db353d128743d0a054a6bdb20d14475c89f3cd4913b0253","nonce":"ac3b6f34d0d5b20a3254745f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"54ec136d6281fb233103b2b3abcdeccf860fabcbecf2a2b57e432924b0526e159ed316f0141bd07eed7c71342e","nonce":"ac3b6f34d0d5b20a32547458","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"e75d86b34d357832b660a184de654aead25388b0791f167ab830d7eba518972da6223788090437b5fc5b9a6bb7","nonce":"ac3b6f34d0d5b20a32547459","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"90cfe56852dc7c372be828702ca7eceb41ce4d3945af6bf40c06b05e5a55bc72d16d13dbd52a01edde3672b275","nonce":"ac3b6f34d0d5b20a3254745a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"16ac14305720d6cdbcc6c2c6b17b4ed74bb3a768236c1e968a6f3143b33da89209bc601dbe31238a5ccd26979c","nonce":"ac3b6f34d0d5b20a3254745b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"3623fa970fe4d3266b5bcea0420a6d8cc8cc05bd3d30510546dbd7ec70ffcdb0b83d9ce132861ef54a5c4fb8bb","nonce":"ac3b6f34d0d5b20a32547444","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"412998c706bfcabd62b1c42dffde5b2505c6ee4b44a2cfb6aa8cc8d88866a941bb194bdb2cc091f3aff6ad36c6","nonce":"ac3b6f34d0d5b20a32547445","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"6092de6db4cb690a00ea741f6609c73cfe91b72cd989ebf819dc7a76e0c0f7d9eaa2beeab1ebce090932dbecd9","nonce":"ac3b6f34d0d5b20a32547446","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"fcc7d847de4afe480b787d5ef58abbbbd3945873e2b910696057a4d3979f7df3ece33aeb2655a75e80153824c5","nonce":"ac3b6f34d0d5b20a32547447","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"4e2eb3853212fec17d96f048fbdd2ed7a8f2cac73d7b4f3481b9866ab5ef5f0b8268278be7508efaf8903493a1","nonce":"ac3b6f34d0d5b20a32547440","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"6f781b2e51b5900ac7826179e1908b167dabe3b7366ff117bc20fdeb4b6c9019e42017c13e40122d0f15d92070","nonce":"ac3b6f34d0d5b20a32547441","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"c8e16cf0433607e8cea086d63d564316b4a893fb12a03b4220aabf78b7aadfa38287bcc8077f9632dd9dd6baac","nonce":"ac3b6f34d0d5b20a32547442","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"527fd5f2857739d9ca152e1b622cb5065025d72bd22f7902145b5fe262df56aef8eda92f2a615865d9220b7d8c","nonce":"ac3b6f34d0d5b20a32547443","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"4f78cbea14b3e7bfa89fd916b5564781a9a335ec396f0f18335d2fe38692d02df43dd81df99c24c910de94709f","nonce":"ac3b6f34d0d5b20a3254744c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"4570305d7b4763955f1b5167d311be523024f1306690c8b989c54799d6cb716abf4bb0720c084d5e6990c55a82","nonce":"ac3b6f34d0d5b20a3254744d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"ab618b44eb4798e042ec17d5ef32f9b874e87ef3320c3eb9f5b6945d125d056f9843248d9faa550440acd06133","nonce":"ac3b6f34d0d5b20a3254744e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"5b55f1920448fbdad39a264f065808c624a92c998a654fe3dd36d70b4b23ca7595699ca2180cb28f1ca178bb42","nonce":"ac3b6f34d0d5b20a3254744f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"dd32a86c8e49fe157147def2c55b592b583ab303877d8985d0788168e62fddfd4494de97ca0039784d14be899d","nonce":"ac3b6f34d0d5b20a32547448","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"e3379b5e4326ebb9c3e1d9ce2ceae5cce49561641230312818495e0b3ee26703c27139730ea9ec211dc14e123c","nonce":"ac3b6f34d0d5b20a32547449","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"d826320e7ebdbcc3078e8e5195bbab9fd7e7223f1929e37b9060348119cb1021d6665f096c38d18997c7d1444e","nonce":"ac3b6f34d0d5b20a3254744a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"28e878558d274baf6fde260bbfb8ff9079ed257dc9cdf4939376caf0e11134cd56666004c45859877e732f716b","nonce":"ac3b6f34d0d5b20a3254744b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"171aedffc644ef5b1fa62462935a84a7b829834b6b715290e9990d12a902086c02029e6b959a3533547ff7a884","nonce":"ac3b6f34d0d5b20a32547474","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"5fa2b08b13b47d313bd225684526e7c6cf2f1dd953293064a009b7d1bafe8b3c13879dac87de20f23e5f7e7a43","nonce":"ac3b6f34d0d5b20a32547475","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"96e8ec8c4a55592f16e768495d4106bdade3c319ad8b069ae7b0de195bef0513be9ea9badffbfc366539237dfc","nonce":"ac3b6f34d0d5b20a32547476","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"579b7d911c10f79a8a3c73a61b3343506dea3c53a5b9cb1b320b02bc8f0c821157d07f356346b5da471582b63d","nonce":"ac3b6f34d0d5b20a32547477","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"524e8ffaeb3d556e91c8e346caf57ad1e5dd83c37c84a0b483cf350170bf824598bd44a228b31e307702b00712","nonce":"ac3b6f34d0d5b20a32547470","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"d608405b9d541665df98487f78e84db9e165c66e8ef4b7fee76f26e8d4aa531a0a8a05b6807df10f283fc8862d","nonce":"ac3b6f34d0d5b20a32547471","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"4b9c60fc5c4096ccfb9d01f8e7109b35e0ed619b530e73a37166e9a671874f84cd75ba30925fd2de56eb3953c2","nonce":"ac3b6f34d0d5b20a32547472","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"76ef6a792927440af8e718ed635a1e5167436f2a04a4ce2f061900a5e4cea3df9265d4813866c5f4fbdf2386ef","nonce":"ac3b6f34d0d5b20a32547473","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"33d8446a83869f3cf7a75cbf2239dd9e566a8e1e483040a254ef2365d67734e6a438353d79e58b6ab6527c2599","nonce":"ac3b6f34d0d5b20a3254747c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"815cb62db75396146c7e13aa19e0849368f091410105450cc912e374208b0e9cdf713c561e9b1d0f23d7dd35d0","nonce":"ac3b6f34d0d5b20a3254747d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"8a461ae159c58d7ef6079ea4142b23f4ba35085195f050e698f04cc3558b0f8b94f52a3339a71783e21c7f6604","nonce":"ac3b6f34d0d5b20a3254747e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"2ca95698aae76582cf48c1db9289ff1f28f1a0a778d6d813e0fe112ee699cdc0193f172136f5f376cc2ee156e7","nonce":"ac3b6f34d0d5b20a3254747f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"eaf5f49053a1c6436fe9d0e18010d9724c708e3736214670da07a8b8e88067bdf4310384fc4a6a128dbaeec2bb","nonce":"ac3b6f34d0d5b20a32547478","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"cb6fd43dc56d44813694309a1a58d12e2d333826cbfc2b23ecbccde1665dc359b7575b9f39b5760f657c765078","nonce":"ac3b6f34d0d5b20a32547479","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"c490df94224e2631427749645ca4ef3952b75f2907572df550c6e0d457c1f929427c66707da2aa7098708a6558","nonce":"ac3b6f34d0d5b20a3254747a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"7acb169e6da10e14723324b43585b5a9fe7d8725848e8eb068c067e8a10ef1c560d8f58245377e575f34dbe638","nonce":"ac3b6f34d0d5b20a3254747b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"8946d01f9e4397cc1e79d3dbe9af572932fb6313717aebdc1f2d891057873537d558e9714f53483e7b404b5f37","nonce":"ac3b6f34d0d5b20a32547464","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"ea6aa1a5822b876a1743f15994ccc86feb17e8350fc45bddc10c9451b8196e39598e4a0b30e87da286a6c09f7f","nonce":"ac3b6f34d0d5b20a32547465","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"0bec005d3ad54d50d06c5350e7b74d1d226338b4d03b8c935bc61617650f123b32ec44208e6c7ee3eb41ad37cb","nonce":"ac3b6f34d0d5b20a32547466","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"2aaa0c4b622c2f51a66e897ebaa376604a2cbdce1402d5092a70f4f79d51ac630efe206f020d9e6602e8a08ef8","nonce":"ac3b6f34d0d5b20a32547467","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"d385c999f0bcf948fc48748609f8bc16d513a3856b67ab9734f4e922734b2e67dbb86dbf1a47da7a967823551b","nonce":"ac3b6f34d0d5b20a32547460","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"f7ea53d0f3c8118fb404f316b05a3dd52b1d81ddc4bba0349efb4c30ef819bea7091e5bf3bbc53638fd11a395b","nonce":"ac3b6f34d0d5b20a32547461","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"f5b259eec0b22d6cff4db95a8ff2ed59a6593122b3bccaf3fa92596d4f58a292e80b09fd7a154961200f10ec05","nonce":"ac3b6f34d0d5b20a32547462","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"09ff52a39699b54f606bc6c56a06081966ea112ff29d840fa88acefe68a4c44b4c33a910020f3d39aa79fabf64","nonce":"ac3b6f34d0d5b20a32547463","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"15973c3be30922f0c69c273f389467ae1626c84ea44808d436d04688c07dec2424067f4800e2fde64614e57722","nonce":"ac3b6f34d0d5b20a3254746c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"8ba094a14f6c925b3dbd76532a24e34b9f7bb3f6cc75e2990e6f0d5c4bffcbad005befdb7837540a04c71a350c","nonce":"ac3b6f34d0d5b20a3254746d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"835e9ad6c50ba12245a0d30e7ab8b57ab01e7ac3d79d2378eb30392741e89aa80276bf0bcbdec2d3f8f6be7ffb","nonce":"ac3b6f34d0d5b20a3254746e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"8ddb6393c42ed43d4f35c2b4f09f56bd611d66b8a9eacb3a705c4464f8f3a311cb726e7bcd944deac5d1ce0125","nonce":"ac3b6f34d0d5b20a3254746f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"0f2a6065575d1f414649ef410423b7f2ef8eea728f1cf0ea1a32501365a905984f0365fe522d48a9e4f95e71eb","nonce":"ac3b6f34d0d5b20a32547468","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"e8167745d7fcadacabdefa330dfc58bd774a37c147fa0a4ff98abab65a8bb47df4759364cc4306fbbc0162cd75","nonce":"ac3b6f34d0d5b20a32547469","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"0bb2e25bdb88f2bcdd9e60a44176e3f450e7fc77bd28538274e593932a00fc70e600422fa86a2898f36d4c6e60","nonce":"ac3b6f34d0d5b20a3254746a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"6d22dda2882fa98abe99fca0ce66d6058b37064f2aeb883cdbea539f5a8c89e26a1fe3db2587dd79b20349896b","nonce":"ac3b6f34d0d5b20a3254746b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"c9ba6a14b5177cd7be0559892259c5f7a7ce5b1084d85cdeb61940300d4a3d386113130b186d15193e2ee22b03","nonce":"ac3b6f34d0d5b20a32547594","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"ecd4e3b963014dc620459d9981da9a9c9dcd445ac941cf37cbd4dbec66d3c4ee"},{"exporter_context":"00","L":32,"exported_value":"b23a4a0119f979bd5011b8207f1d5eae71cb8d35560a3b5ad498c64e81cd3d92"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"97c2faad2e5fba0efcae91e6b7fcb8b59126f0c3ed2fe559cb4537d9bf0f0f4c"}]},{"mode":0,"kem_id":32,"kdf_id":1,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"2224a63fdbf32767205865d3450ce4ecea88a761bc53acb8c1e6510f4d37a205","ikmE":"4badd64fa6444ca54f5e4fdd0228b1e79eb6c51272db080c79f7befdc4d101b6","skRm":"212524ce7d428c8acbf38b7104cd0831a057374591a1117b61585106edb32420","skEm":"395deaaa3990242a5451cf3e2e5e3102c4fa7608e5d5d9df4e84a1320438af2e","pkRm":"c0cd6b271a1c7db71ba8e90005708c053177983bd998eccbe6eed9d8cad81d32","pkEm":"6606dea00a41c3e1568e13de1144941c3054040b18afd2ba843ea80d702d9b1a","enc":"6606dea00a41c3e1568e13de1144941c3054040b18afd2ba843ea80d702d9b1a","shared_secret":"7875513d8a11a18d5355ff559dc8d89a14476ed35b8e667f3d4ce2da0ec30066","key_schedule_context":"009bd09219212a8cf27c6bb5d54998c5240793a70ca0a892234bd5e082bc619b6a3f4c22aa6d9a0424c2b4292fdf43b8257df93c2f6adbf6ddc9c64fee26bdd292","secret":"98219284a6ba8877d9094ddf8c7dad9780fab937433cee3d6fff84834219d354","key":"","base_nonce":"","exporter_secret":"3a194afc96f98ad98a3ac18f1f542d74fb7ddd102f744cdf77597df164ebac39","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"05a913ac0d4719899ecf620233911ac6be165b79629cb88612fa16d66fdffd50"},{"exporter_context":"00","L":32,"exported_value":"982cb3624cb067a3a475e75d959c0f60f060ca15a3a6325a5e3f9b687e50e1da"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"4eaca1950d8229abe7f767b337794876419ab50b78d8f16620f87c00df77db25"}]},{"mode":1,"kem_id":32,"kdf_id":1,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"d3d715efdf0a22f84803cf245f4313d856b460fb595ce531622a361b1c591536","ikmE":"6693402e7157cceeee0885dc88d8ec08392bea50c465daceb236b13119644ad1","skRm":"b5c60a69ac2e0914c83f35fa01ef6a4e067aca7b7e33d31f03002a1a9da8b000","skEm":"cb55b62fb17e2be38338ca52a3c69a6b03365379f2d9ec1ea2f2ef02c2cc92ed","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"09522a141e2fdb82d2edef1f3b75e0246dc7c6c54e85bda45ca5916561e91861","pkEm":"07be5897241debd4785fc3dd99846181160786900fa5d358c4ea2f9cf9b58f67","enc":"07be5897241debd4785fc3dd99846181160786900fa5d358c4ea2f9cf9b58f67","shared_secret":"df2701f03faaab5bdeae2997171cd638507f40a90266c007392eb012a796d0f8","key_schedule_context":"01446fb1fe2632a0a338f0a85ed1f3a0ac475bdea2cd72f8c713b3a46ee737379a3f4c22aa6d9a0424c2b4292fdf43b8257df93c2f6adbf6ddc9c64fee26bdd292","secret":"31baab353fea75e4118f1e97b07820f8885c180295a4a45df858bc971141f2f3","key":"","base_nonce":"","exporter_secret":"c484b62c5e206626dfcb3e807f1dbeee624aaac63c835019795a6654786e499b","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"8ca2bed1f829faaea4c3bd8b1046445e5fa16c0b061079892eefddb78842fdb0"},{"exporter_context":"00","L":32,"exported_value":"ee258342b703e4c17ded97898f81adca8b650a2dfba42730949652edbe5a5000"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"5e76237d3039230d00986209d3c897f00083fc569a03bb850464b432d1cc9f65"}]},{"mode":2,"kem_id":32,"kdf_id":1,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"0be0028ac1bf53a747414edbba45869f029f2745afa95226f9a7e90e4b0faa26","ikmS":"6c3407c148fbbdfe178227b12b19f89fd367736b018032f9b18874a9bf33fe85","ikmE":"68d3d6f62651149fdd8074e05d9d3cd213ba31783924746f1b222cfdd2c8ac8f","skRm":"c0c40f716ee2def28e804a1d530597cb165051ffcc875c6d87d22d6aaa96c7b8","skSm":"85b89c57d5bcd435cdd12fac2f62ecb1b1f0eed9ca970edc4e53839eb22fb0eb","skEm":"3dde154c0925ea12eb0c7ca926dcecb1eccedc36333596d3129ec3ec26686132","pkRm":"dd247b4daf1e884bdf7968c75c47382b415d12a4087d46f8c98b22db36abd316","pkSm":"c992207c059e4926c94ead3c0626bd207d7ea33f6dc8faa764656b679b3b7b1f","pkEm":"0a6fd8963b85dc0313470376b2cf13cb435a4b64a16089c22dc881f631d87338","enc":"0a6fd8963b85dc0313470376b2cf13cb435a4b64a16089c22dc881f631d87338","shared_secret":"6cd3370e74a573117c2600b29626715a5699c8f63058eb28d24ffe47f27d7d6f","key_schedule_context":"029bd09219212a8cf27c6bb5d54998c5240793a70ca0a892234bd5e082bc619b6a3f4c22aa6d9a0424c2b4292fdf43b8257df93c2f6adbf6ddc9c64fee26bdd292","secret":"bd85c287f80123425fc8027f005add28a02ad261c08e2767e3469ddc13b0dfb2","key":"","base_nonce":"","exporter_secret":"d4d6380c40c217ba10040f66f14f6008cf3f542e087a1ac8fac500e0becd4ebc","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"6f6d2d736c909732f8bd83cd7de30ee52d1882650861e3747aee2ea8a4da18e5"},{"exporter_context":"00","L":32,"exported_value":"571c3957f45f75a76b78c8a21132a138b7e6c1f73d86e88247cfd981fe3da981"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"d9de87a7c1641b8da0f2c06a05ed651c797b5c2c0c43c81a16318782a5e0bff9"}]},{"mode":3,"kem_id":32,"kdf_id":1,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"d14b6e1073edce2b3691a24c3bea74c79d91aec20677e1bf1f6d08cf312e11d8","ikmS":"0af7837a79149ad70dee6cd959e8d0410cdee80898eee54863ce349db6c3885c","ikmE":"cca2b6e24aef16cc966b370d43816dbcbd658a41f57b37e004bb06b67eb7b09d","skRm":"f70439b9a37877e235ae9401a3e5e29df66f6d0bef0695335fa833e018ca46d0","skSm":"a5cf8d3b9920c1110f2ed7f40f1d33e25943c341db44b242db55f5a21639f565","skEm":"a1e558078c8cad670f26804c1b8bfcae4fc53d09782f214d9bef29115664c54e","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"f67127ee61c836e3e69ad3a36a07d950df7c0aa0bf0094856a4223126535aa64","pkSm":"fec16220ff024951bed80fd0ad775b64e8238d548abfd8ec4e00d4841f8f2d1b","pkEm":"006972416dd84e5166e93417680406e0fa51d58aa83809192c5da3ced5e7f63a","enc":"006972416dd84e5166e93417680406e0fa51d58aa83809192c5da3ced5e7f63a","shared_secret":"2a07de6b76201e3944a053529660699b1f1e14fdd0e2184e4bd6d0357e41e083","key_schedule_context":"03446fb1fe2632a0a338f0a85ed1f3a0ac475bdea2cd72f8c713b3a46ee737379a3f4c22aa6d9a0424c2b4292fdf43b8257df93c2f6adbf6ddc9c64fee26bdd292","secret":"116e9c5d9d1be4e9003007cb1cca3b9d54a4f757de88148a1de2fb027575401d","key":"","base_nonce":"","exporter_secret":"9153dafda84187ead5d0c8d05a3aea9e7aa53e548424604fcbdb69fd70561b13","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"4b644b9638557fa11a0a7219048407f4aa76f875518e0d275ccb75e099906dbc"},{"exporter_context":"00","L":32,"exported_value":"2ac0e6dc2b74c4f964ec8760fbab357a85cda30d859878721cb7f7ba0398c40d"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"4de53bb53c95c4f1c7e60aaf42d9154e2d9e8cf33f494993838950a47329babd"}]},{"mode":2,"kem_id":32,"kdf_id":3,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"88c125a56a8f33926ccc2743daabde37777b28f06f96b74be614272833b2b123","ikmS":"841bf6f9fbc43539d6de839eaabd5418aefc5e888295a1c28ac22154bd85b8ef","ikmE":"852be2c63b08389158b0f248f42117060e2c85f8d3dea5af9b15537a0f12a806","skRm":"6c28b59331663809bbcebde9be2559f787cf8a6e3e05f97067b405c760dd93f4","skSm":"7d3dbd26950beb4181ecdec41a17a44472bace32b5707099a370ef1598b5a035","skEm":"4720b46acb8a20b779bda6ce89310ad1b1d6aad4b25e284ffd3dd7a45c855bed","pkRm":"af949de42f3cab2b322c412c4dd1e0b41d9074f95f43b48ecde1d763d2e87f79","pkSm":"434cef63719eae6762eeb991e3bac0dc68d0a6cc3934b80a30a2ab9fca427537","pkEm":"2245f678075ed17923f5fa8d0144eabc8aa2e605b1450c2c7bc20da0e194f230","enc":"2245f678075ed17923f5fa8d0144eabc8aa2e605b1450c2c7bc20da0e194f230","shared_secret":"26b9681cfe3853bc58fb9a82e4deae62311865d61e347309468c4df77da1b7f0","key_schedule_context":"02018d129f34a145043cba6146e7e397593164fb1e78e512e6f36be621c56f9f7023a14f35e95577ec3f6714ee332f48e829fc2ec336e71b204f5958b7067f47756f17ad5b0cda65d91049ff137dc5111687e0d4d44123d94cf2ad7b71ecb5fab6cdf8e044519fe1ecf7cffb6a3f3bfbaf6babfebe5d30a92e166f52849e8d35a3","secret":"03f70902aa9b76e2226573000abdb601e937b5f7e35d2466caec04bf2d78d6e6c462055c98f36296433dd69062170a74dc986ceff4e991a29c241e6aee7d5f74","key":"c348835ed2dd1e56f57c1d9a88d940d4","base_nonce":"9d3fd552711925e8f3dce566","exporter_secret":"1b82991d07220b6d95630d03a1b2351115dea27138ff07178408912e2c8ee6e12e43fcdf553b178a2d413e1ce24ddb8884cbc2eb03a21d5cb7dc3859c1264e60","encryptions":[{"aad":"436f756e742d30","ciphertext":"2f652c4c88385f41cf454408987da61e903316fdae77f3533cb8c1119ded06991cd150eac9fafe1dc4a7bb0c29","nonce":"9d3fd552711925e8f3dce566","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"91eae9f4f386ddc931fd9fc358c433e9dcd550e41b2007948c777145362b97a81780cfe51c0a92f186ab455fda","nonce":"9d3fd552711925e8f3dce567","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"af1ad5458d9180bfcfb75f1d2f1ee8d9bc55fa789dc76ba7ff68ea5b859d5e06f656d1f8aff8bcaca388a86da3","nonce":"9d3fd552711925e8f3dce564","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"f20dbddee36063f6abafd6d6d203d75a5e0fa0c6e187f574ddd53965840c5a76e4792190bd7c87dc47700da404","nonce":"9d3fd552711925e8f3dce565","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"044e74b63460ccb7190930123c3faa305fef85c688412335b85ea6e9d8a6efb3dc78301a5e0724bd0e2be91ad4","nonce":"9d3fd552711925e8f3dce562","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"7c41154b0c54a66a066cde40216adcebc2a138966f8d64fb8c6815ca235769367a9f66e70cc084626b93f3500f","nonce":"9d3fd552711925e8f3dce563","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"2b1c8bf4ae9e226430fcad282b842028779b8a101aeff940e30b9cc980a25ec009194844727bb60af7edeff20e","nonce":"9d3fd552711925e8f3dce560","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"da52dd12f788ce8ebf589c9b10465bbf67dbf0ad9da6486e078dae542ff6a7048ef804b1bd25255c9cb3d6a98c","nonce":"9d3fd552711925e8f3dce561","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"2e82267b01276d290f066a542eb5fbdbdbfb24ae89e86f79b06cdb621cbe70af99473527f4661959fd7779f32e","nonce":"9d3fd552711925e8f3dce56e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"bc431d92d380395dbcd276b0daf9a4d29f1d69579bfcecbee2894ca4dacab4ab5d354d507fed1207305a3ccfe7","nonce":"9d3fd552711925e8f3dce56f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"3af90d0c283d7f0416be5a38d6dc3efe19b0e5a1d687f6e033b171be410a4b274a75bf0b19efb9ef7086016f2f","nonce":"9d3fd552711925e8f3dce56c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"4839fcda6ce4b75562282dd5e068a9d3db811eafbf727b6d0893644bfeb42e1793bccd8cf9dad8b35704e254e4","nonce":"9d3fd552711925e8f3dce56d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"3543a4014fe0074455e03e8de9b53f2d8c25574818eb73661061d7896b3f60414be26e7c171eadb2a00d0505a7","nonce":"9d3fd552711925e8f3dce56a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"84214b044d3aeab14742e0bed234d4e33b7b21cf902c04748c9894079e32e9db5edd9f82061866121a9e78bf5d","nonce":"9d3fd552711925e8f3dce56b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"233350a2a8c292addf8a891bd97021a0216bc4da245b993d0c9bc4aafc559761a6432094b2b6213e721ec0351d","nonce":"9d3fd552711925e8f3dce568","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"4d312d74a1434063e8374a6924f1eb55439ec3aca1ec476b3a20487a188d5701e33a45f78b06f435bb42c51cfb","nonce":"9d3fd552711925e8f3dce569","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"76913990dda8cfe837ccc1abd8b182f35e5ea1004f699179539b3c80a441f31b08237c383493dd476520eb3f04","nonce":"9d3fd552711925e8f3dce576","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"2243a9fec8461cc6babf6c9f21b68fe14f8426c4cfab39c2de044b4b383d0d1e29ab8d7aa73ab67818b1846361","nonce":"9d3fd552711925e8f3dce577","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"927e100bf283f5dc6756ac4d8e2d0fc647c93f3ccab2382080aeae04980bad4a2672c278411ae5ac7affe36193","nonce":"9d3fd552711925e8f3dce574","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"4388eb8990d61c1bb2191bc29950a79cd8c7f2e69a960a037923b59732acd4fbea790e1aae3f5d2767b343781f","nonce":"9d3fd552711925e8f3dce575","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"047242efc798dd80f384852113fbf9eaa86d7dee6845fa9aca32094cf3d8769305876849849e5267e0d739951f","nonce":"9d3fd552711925e8f3dce572","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"15869dde5bcadac1ecc26fc405d1c537f59cb37a46faff5a4736ad9da7259a3eff557eaf0de3dfde71f11114c5","nonce":"9d3fd552711925e8f3dce573","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"ed98a5f360c50e339d47a34e9db77cae16e7bc6a29ca3072ac09149a587e9b872c4a405ad6b9342c04bab684eb","nonce":"9d3fd552711925e8f3dce570","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"2fef92cadc57899c76ad3de346bded9adfb0fa6294fd2da71610b43d884699df277092c562738d1c9582bed4ad","nonce":"9d3fd552711925e8f3dce571","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"d81a614ed572b1128e4b509c7a831daa1f5771fdbb19293f4a82fa5a17149344fb3a88b7961bab87687443bc3e","nonce":"9d3fd552711925e8f3dce57e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"90a6f5bfb42749dd7851e84286f1fcb2bd107d9a6cf531724fcfc908eaa58c1d99a750bbae87c1ca841dfb3834","nonce":"9d3fd552711925e8f3dce57f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"3808425fdb98a796694a64eeb598953fc1923f9327681397045bcfde3b984a3a4945dae19cc6fb6fb6af590d40","nonce":"9d3fd552711925e8f3dce57c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"d55e83c8cfe7ff17aa962d603d724b0fd529260d8d51d38580373e2b5daed3ca49c24b8835a6db8bef875b95ad","nonce":"9d3fd552711925e8f3dce57d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"1dcb451ffe73cc3c16ded47c4ebbbb0c7e88d69f5d5e8b1eb29623d3b6a23f99174831dcfe8528aa57b684deae","nonce":"9d3fd552711925e8f3dce57a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"bf4724ba2f10d19e80072d309655aef2a994406b43aaaaa242e3dd1d9db2546791f5a323d9f37522fa61c50fe3","nonce":"9d3fd552711925e8f3dce57b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"fe133cb73594a085a1556e1dab0bcd7b20384610ed5e1e96c681b76d29b06133d7fc324e065049893c0eb78550","nonce":"9d3fd552711925e8f3dce578","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"050152fa2114eb011c961eb54c5261f9315212866acbcc762188e1883a1b3c7acdeb6103a8edbd503b44e80aeb","nonce":"9d3fd552711925e8f3dce579","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"820334ab64e38677bfe1f74eec004fb081163205f6bf93164da0215e886a7d504a797c17d72e7506e08544aa6d","nonce":"9d3fd552711925e8f3dce546","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"bde109d4d25620e2b4cfc1cf07c0fac5c0d7f05f33a6b0831aec4520e947af9adb42ffd8d5635313e74ce4ef01","nonce":"9d3fd552711925e8f3dce547","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"285579866bbbedae3b89bf038eb2d1a3f36b5144ec40a7cbec5d4102e9889e7cc94956e7a72fff89db1ffacccc","nonce":"9d3fd552711925e8f3dce544","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"a35e3de3c3ed5b33bbeec536e291c846e90b3c173cd1d585dd6208f097d0252ae1d0f5ed971aca2948f5a78485","nonce":"9d3fd552711925e8f3dce545","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"59b9fb2e64c91129e0b22eb06505a7b60c56baa91966f779543e435a5a800d585bff22b9feba8c51600b5b3df1","nonce":"9d3fd552711925e8f3dce542","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"1dafc5e008006a1eb1fee90791ba85f9e5a14667c5c92444a3dab8951d571e375dc5670d088817f4c4a47d4c64","nonce":"9d3fd552711925e8f3dce543","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"c2cd48eb549131d5e16ecd45ea0ba9c310ebf1c18224c656817f385009196a97441c651a3ca4dde96ecd2c6683","nonce":"9d3fd552711925e8f3dce540","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"c5db4b0a131ddce9b1599657cc70243eeece2049f110973891bfa7eeb02f548bdedbfbbcd9bc4bf1a28475a297","nonce":"9d3fd552711925e8f3dce541","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"700caaf12440901c0162db519721ca6532e79db066ed25937aa7b7e7a303ebc1253596e8a3d54ad3f4b41c2ce5","nonce":"9d3fd552711925e8f3dce54e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"5a9d764d14aa815f8bd42c85fe6dc3af903735c8d6582be85d4d123522e0768f7e786a4231982fc166a5a8d13f","nonce":"9d3fd552711925e8f3dce54f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"09f4151fdc6ae826f40285d523985d51d5d58aa5410fe856be37a4fe1c6b8da1ff89f2f2ce63a1e3ef4c5c4c0a","nonce":"9d3fd552711925e8f3dce54c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"f23f4e94678baf2ccb69cf89d4237965cffd7f4d24a8ca6b143b02ebe0bb2bf3bdf4cbd5b0fadf838a3002c069","nonce":"9d3fd552711925e8f3dce54d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"5a921977c0d6f5513861844d0661a2bfeb3ce2607e170596d5240956044c2ec4771f3c9503db05078f65c3f729","nonce":"9d3fd552711925e8f3dce54a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"47b702621ec8f828ab6917bcc5434bfc355b9f3fc8a9b1e964a0eebc4da8b9c180019f676ee93421a15dc2da00","nonce":"9d3fd552711925e8f3dce54b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"db32fdcb9148419d4439a77600b5f90a625fa79c43a78f7f43b8c9de4b1e2d71115bec35fc563b3c8bbed6085c","nonce":"9d3fd552711925e8f3dce548","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"b89461f661685da97a62e17dd198dfc971296fc6b17f9bad675a4db2e0109014bea4e204aeb9eb2cd431f56ba9","nonce":"9d3fd552711925e8f3dce549","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"2ca425833fe880a669cc15f0550f9c9121e204954544c2129410140b895a35e1aff1fa0f18be2eddb1ce3f2671","nonce":"9d3fd552711925e8f3dce556","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"7939aa8ad7e604d6336b58d6a715d4cb089729cee20087ff1a104d1e71c98a58560a2e30a53ee3ca2769ebe4fd","nonce":"9d3fd552711925e8f3dce557","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"21ba6d4c7c5530af09a36c43d091a033fd3eae54ed11001450609da028b9d8fecce6f4159c151c086398185e6e","nonce":"9d3fd552711925e8f3dce554","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"6442b5cb8b6daf36a3df663d3492e964681177b4a4baa4085cf668fd60bdb001354ab8bb701aab17ab13ca9f3c","nonce":"9d3fd552711925e8f3dce555","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"1166237e9fd5c748cc9da2aa20d541d7521fd33c4ea33890389fdeb253874ab335288abce8db95849bbbf99d4a","nonce":"9d3fd552711925e8f3dce552","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"720bbd24e3ab5033d22bbc51c9c01555e895cf8b440c7b2baddcfecc158cff55aa150d43015ba872f7b55a43f4","nonce":"9d3fd552711925e8f3dce553","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"9a73ec4f33dd1b8991ba48b5c7e7d7972bb7f77a240e7859ad7c6c050018bf8930329a0b365fc9d21ef834ec3d","nonce":"9d3fd552711925e8f3dce550","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"1eee8bcbb32f5bf48abbe31cf8c3eb92b4216b5867eca83ffba8123ed123925b22cf553226b5937c219a7840d2","nonce":"9d3fd552711925e8f3dce551","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"40584c20cb67893b6ed3ee03f0f521611d72e7c05794cb2563d99b042bd992d4af4d4704a2f48568f7c68edd05","nonce":"9d3fd552711925e8f3dce55e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"04d1cca56c94a9b2020f0f84167cfd1c253b24f45b2e65ba574877564faf284b6b0d2d470d8c3e3c65d5bccf17","nonce":"9d3fd552711925e8f3dce55f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"a0c14f2f27e25b780c4e2847d1ad715c819fc3958bb769badd13d42397c84ed1bac83a2c12472d4b337ae4dddb","nonce":"9d3fd552711925e8f3dce55c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"48c66fc79968136391bc6137b966c6a1fe5cd24a877ba3f2db2c58af28cd7268520c3d753510a8e19f2e4311b4","nonce":"9d3fd552711925e8f3dce55d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"3c4fa52363db0279bbcc826c10a0b6042158e348c3daa59f2abd49fcaa1ee21c1f53571e1888b6fad3df9816ce","nonce":"9d3fd552711925e8f3dce55a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"233ff2105b0b3fc68834da3871bccc0c14a71533e4a7ce4cfbc1f5e68570674ce510e853144cba6853316a6cb8","nonce":"9d3fd552711925e8f3dce55b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"8d933751f35b2ed6f0193ee4f2ffe928185d3a59198e11ea236ccf2cc21acf885a268fb8e0bcfdd7af5f892729","nonce":"9d3fd552711925e8f3dce558","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"d61779200d9553a9baded9ec6c552d8565b200e4244057dbc9ef8a6f83cf4215bc58d7b076071210ea963900f7","nonce":"9d3fd552711925e8f3dce559","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"15338e71c1b2f0d35aa1140bec17561a3320fe4be8aa4384af60377bd3b58fbc87be201b4697e975c0ad327a55","nonce":"9d3fd552711925e8f3dce526","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"71f76e09c5073a00ef2424318a8025d78b6d840a373bd0535930edd5a35576906eb5274540eab9a379d4a32560","nonce":"9d3fd552711925e8f3dce527","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"ac15433dbd52056236c6a742a2f6026c36c72a46509b9a267ff5530b5cc774ef7b157ab9e728401cce08b71491","nonce":"9d3fd552711925e8f3dce524","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"4b0d50502241d6b91218b9fea209c07562fd7481895e8440e7030087e3cb5768b04817d5996d545b88afbe4277","nonce":"9d3fd552711925e8f3dce525","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"7aa6aef2dfd52c4914fd490531acef1964fcd3da7dc28362bd793fba8c19fb42c35905b060e16ac72bde5f470c","nonce":"9d3fd552711925e8f3dce522","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"ce25de79ea4dc4f6862b4eeca35a70da3677db5737e6c55a657983581f2e982fb387be136af42e1f31db8a363b","nonce":"9d3fd552711925e8f3dce523","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"3316f86d30bf52ae72d85e35ba5150915fadd5f6e96044531e1dbdb6c5e8c2e94a0ed10f589ad32130efc14771","nonce":"9d3fd552711925e8f3dce520","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"ffeafd45b1f8be151061569be8185e53ed0e55bbf094f51c5179c712216cfaadd4385d11588713d674f7ec13e2","nonce":"9d3fd552711925e8f3dce521","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"fc651016c9fa68f24ad77673e4b8d4653c50b4684e6002854891a7a1954656b93aadc4bf36ad9cdf159a713bfd","nonce":"9d3fd552711925e8f3dce52e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"f56d561596b6c9b338c1c3fdee73ad9f84f8e855f26dbaddc264143ad369eb3eba48ea18d588381f7c31e891ab","nonce":"9d3fd552711925e8f3dce52f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"fec3cfe443060dbadfbbada08624e5a327125a6ab63415639d816239cb311db048e8b923e0a694e014fe7928cc","nonce":"9d3fd552711925e8f3dce52c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"c5e01f5bea603b942b4985c4c0490f89f85e2e43585202d8cdfd538259d6e0a8b590147ff652cf8a11ff0ff71a","nonce":"9d3fd552711925e8f3dce52d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"83e30c783b3ebdcba117100412b4c5b422d4cf46542203294dcf1032c7dea236fcdb9d2d7e3d3e6b87bd7b9f78","nonce":"9d3fd552711925e8f3dce52a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"6005f3536a85865a426c050d2f886774f2aadbee0ee59d4dfb0130dee597aa5bc3728844e729629bf48f6b739b","nonce":"9d3fd552711925e8f3dce52b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"b910a3d045b81a6ee1d40a77189940611dd761aec392a6733558161f5d8154c53f2922b5837afec6f86859c81e","nonce":"9d3fd552711925e8f3dce528","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"5d0200476b0c149aa2b60e93c4e42a9ab5c73dc9c85a465e0704ecd5c9f9588b4a51e47cc26d04eec2cf8618c7","nonce":"9d3fd552711925e8f3dce529","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"3a98f53cd115e082237914b094467f2823320b0fe5ebd50c1581b7867f1e08308930013641895a3c053f9102d6","nonce":"9d3fd552711925e8f3dce536","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"81c771b4db2b931fed676f9314b74cf689fe158c9f50af69f9a497258e9422df7c8a70752befd15608d1dc845f","nonce":"9d3fd552711925e8f3dce537","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"0da98df91e6f279587b1936d17767d91ec127fb06abb022918cfe1c7141588d7e271e54a9f5f15f0680d3f0521","nonce":"9d3fd552711925e8f3dce534","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"08156182f4f72245cf81f6316fa5343e4a89bf724b867536ee2d4540cfb1246d8090e3bb07b5f4bbef46a16d19","nonce":"9d3fd552711925e8f3dce535","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"9c6038754bf4d90f1ef53d4d6f94b1bae0b62d97377d3d5d8c5f6943f9d41bd6febc665c4c3164017b8fe0e142","nonce":"9d3fd552711925e8f3dce532","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"df7367c7d1705006819a9e7f3e31feb60813b6706d59535c520c1e8bf665ce63bba643078ca679fc50ed21d187","nonce":"9d3fd552711925e8f3dce533","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"902e0147fac88c1729a940bf2bb6f595c99adffd00955738030c3ce58d273011d89864ae5a04c874850eedcd86","nonce":"9d3fd552711925e8f3dce530","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"940380e8d8c2f0a6761191f0725087f5b13a97da9ebdb00795a17a57689871e943cda90ba32b23a8f81fef54e1","nonce":"9d3fd552711925e8f3dce531","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"7c1ff4bcbd09ac27d39fa13fa63dba1d38812124732f9db479a2650c4b404abf572f66e1f64de50e41f20db6e8","nonce":"9d3fd552711925e8f3dce53e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"218eae54f80225ac3252e8d041639bf7f246535e5ff12ba84166185ebce4f5aec30aa68591ca37ef64db514197","nonce":"9d3fd552711925e8f3dce53f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"a8e289fd90fb981f8aeeddae47c317669b4084382eb24a7ba36b7feee729b6088b0325839a5a3adfe9d0c8029c","nonce":"9d3fd552711925e8f3dce53c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"d8f8d98b9cd3ad5923c9ae6cd61ee307c87d6dcf3618f6b40d1296d4d65a65c1883c8167e0a73b33d163fae17f","nonce":"9d3fd552711925e8f3dce53d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"af84307980d039ab80da8c08d9b802a9faec1c02976b9e7ba222025351bd6bed5b16c260e14d4fea915c6a1899","nonce":"9d3fd552711925e8f3dce53a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"679ce7d59c7185623e945588b9540b3d7c1e97cd61df672561aac0c398a1945c16e753b047e65bc96c7b4f93ce","nonce":"9d3fd552711925e8f3dce53b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"c6744c343a2d8896b6966276bd450712803b54396b2e145821ab52427fe84664ad4f7a813a9bdb3c0fddf3cdca","nonce":"9d3fd552711925e8f3dce538","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"256122208752e24b6f87dc2b81f9733ef39ef2732bf5e4d5291dcb59aaaf3c464ad2180ab61fb9282d32c8e8c0","nonce":"9d3fd552711925e8f3dce539","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"3e4979dcadf96530fe48fb512f175b850371aaa3340e847c5030a9aecc85c9320e8a3aba4db5a870200b07bef6","nonce":"9d3fd552711925e8f3dce506","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"a30ee700b19b92c060a0c5bc293d85f805f0abc840a99e31c21433f687a617fa4368b56410e0193eb8aa19574f","nonce":"9d3fd552711925e8f3dce507","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"11a86b3af8497b02f7ff51ae069b724081ebb597251bef53a0e668511766d81ba5a399046e91235a0ac23eb782","nonce":"9d3fd552711925e8f3dce504","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"31253442e95cff12491b9db68694a5452cd111059cb22975a1353d4564531275c20dc16d2f7b29350db82efe75","nonce":"9d3fd552711925e8f3dce505","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"1758578a0050fddb16bee15d0b2c113c8523129ea30a625e4c8945042a32ce3c3c7edc658f07d952e9e94f6361","nonce":"9d3fd552711925e8f3dce502","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"0fcfc47bbdf887f5be9734ccd00131e0d3e803b640b1922a57d9e0364903654a4c02bc46bcc3e036dea56797a5","nonce":"9d3fd552711925e8f3dce503","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"84b50d27e58a9b233b526669f32ba9cd4d08d58ce8a32b638f6dc4a7081fbc0ae17b2d4a4106dd7e48922910be","nonce":"9d3fd552711925e8f3dce500","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"115a94b74d46393d470e2457cfc02ce2f0ac9f304f6b222c169de2bf96b061a83ce3725c2ed8ff889c68426a33","nonce":"9d3fd552711925e8f3dce501","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"ed3a604c6cec39339e2288647647a4e74aad90f55450d02c0ce1a27f156bf73903caaa347c58336fd6daf54ffe","nonce":"9d3fd552711925e8f3dce50e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"436525a3d31030618607480f6bc51d9e19df4d6aaf2c344b83b52ab408adb3de43a6547dd68ef9af6395dc82ca","nonce":"9d3fd552711925e8f3dce50f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"fd76373a86b877561609432df5ba40edbc0362b19bd9122ed1b1dd98d7db7c96a4936c7852b8f119ce472d5ad7","nonce":"9d3fd552711925e8f3dce50c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"83f28834549846799cbdfa5ee39f7e3e46a907ddefd05cfee7b34b1171290c7b5bd33d0d76a23dd391fed846c7","nonce":"9d3fd552711925e8f3dce50d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"824c6ad21690083b49172207ae70669c52630fd24a0aa31a3d44078ffbec5fc788f7cbd5fdaa3d708734e541ed","nonce":"9d3fd552711925e8f3dce50a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"9929a8c69bfb85a07695181c3a30d1d3c6270a002028b3172c6246f115cd8013b4f33cd2f9a2635ff522931ed9","nonce":"9d3fd552711925e8f3dce50b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"b8522136b8e7f57f3839268981298f4040956d2650a7565c7a668339ba0fd62975aa84bb59ec482304c39ba93e","nonce":"9d3fd552711925e8f3dce508","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"34e23ac75f8fe435e5732f7a6bd1a7fdc5cddc263b2f991ed6fc719cd1b9ba9bc8c07872b4be8f43f84ff82caa","nonce":"9d3fd552711925e8f3dce509","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"8a3b03e73f0a469f68d35100bbf784aaf9518afdfc44bcfbfaa82b4b7de70f4733b1ea267d5a5aa9e8d77795ac","nonce":"9d3fd552711925e8f3dce516","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"c30f9f5b5e583f1654ae69dfa351c3e6973cc0ca920111c1b96c97259b4bab3a576585527d93feda4d2155f7a5","nonce":"9d3fd552711925e8f3dce517","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"0bc9391b7a5caa5ee5d7cffa4989e28a7e5f2dda43197b1efc0a5a6f46d0eef45bf24e877cb1b22aeb22175455","nonce":"9d3fd552711925e8f3dce514","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"b06e06579c67af8e36f1f755b47133cc675059d952e00a5599c6b4951a6abd4b5f888f18eb82558a392f37d20a","nonce":"9d3fd552711925e8f3dce515","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"c7ab07766b63a4ef03187bc1f704e65d7fdc55e0adc12e1ee1ae04deba5cdfd4aa06dc4b1dce61dbd58aebccbe","nonce":"9d3fd552711925e8f3dce512","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"43747d306a73fb8f8c90bdeeac7b07688bc1a83cc3ca44d2cd279dad34e0e4fa7755d50961b38633af40cf7e8d","nonce":"9d3fd552711925e8f3dce513","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"43ccc39f99f6ab427a7d769f27750a22abfbb1225d6d37cc87e2d4f5890cc0396787dbf472c81599fdd20df265","nonce":"9d3fd552711925e8f3dce510","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"e237df1c7da48b238d8ceff36a7fa65d24ff024c129bfbb4d16d1c081c1226f1d80f875a6430175cb35aaea8a3","nonce":"9d3fd552711925e8f3dce511","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"333e5dc0e98bca6409909f9ad93829f2e174f40121ddd380f3353a12fd7dc48cfc5b3708160f7d7a50e683e417","nonce":"9d3fd552711925e8f3dce51e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"bdb0838610665a47d35fe82e66739a60f44dff831577930f93d577469c6ac48bb5ec6b3e54e392ec6b36ace11a","nonce":"9d3fd552711925e8f3dce51f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"22350b9936a36e4aaaf6021369092f3539cdcbf7cd93167925534cb33a705fc0c258c3b392e82f67e31f157e5e","nonce":"9d3fd552711925e8f3dce51c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"3fdbfb93ff9b996123975e309e73820e9a52b6786208797b8d4e780e0d50f3afd7016eddbd964d83add7da7e36","nonce":"9d3fd552711925e8f3dce51d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"3220f544884eb9e2b10cbdb77c39831077010687cb51b96fa069cf1d6d9e72a2c51ba844780725e25e35405ed1","nonce":"9d3fd552711925e8f3dce51a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"a3dca205d28fe007a5e824f8d9d47de16174fbf4a89f79e49845c5a163d734dd2137adbd7017fd28da15d32ad8","nonce":"9d3fd552711925e8f3dce51b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"234e19f44199d943117569d8929644bccd679be99bcb6fef67d4691263343c3491cfa3d998134fef1cc3e512ba","nonce":"9d3fd552711925e8f3dce518","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"b8d3479f067faf2ac68c3b2f6bc251cfc3f703cfbbd3d3d37537949bfffa9ef3d454d00e471cc6266296d0b5e8","nonce":"9d3fd552711925e8f3dce519","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"be6f4448dc6a5ff7809e6e41042352c4397424079faf85884968f326ef3d05d5861bf47540f1189d17a431c4d9","nonce":"9d3fd552711925e8f3dce5e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"f6d222ee1d3a50fd27fcb2913efeaac74c49cbfd77e672dcdea6bb3cc4842483b3a978a17714a356a907c8c809","nonce":"9d3fd552711925e8f3dce5e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"824bb57020c1c0cf80c5ea3a6c89e1c267307322e6e961b56c7e28c1695d566555ab4a2ee4a490b4257e32f017","nonce":"9d3fd552711925e8f3dce5e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"c986bbdc1a57a5bce4e0a1b837ca56eda81d67d02a061bf51ffe24eebeb6cbd8a0912c17c527362352d74e3a6b","nonce":"9d3fd552711925e8f3dce5e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"8d189725b9b1152455e5a7889c4295293f4f42af7deeb1ea31552102e1a4ff370f53486117f66929a5bcc348bc","nonce":"9d3fd552711925e8f3dce5e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"516363b70524a96703e689c290728b28a48e0f7258f9501470395666f2fae57e092c596785a267436daaa6c86f","nonce":"9d3fd552711925e8f3dce5e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"c12ac1c956510c1f435a83ce32a6fe9521dbbd1b8a326bcb666849708cb609d8902834fd275bb31b2a9fe1d2d6","nonce":"9d3fd552711925e8f3dce5e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"5572cf92b946c443e5e41b5f5d38b6ad8a866491341dfc732334467f4318482fcefb051596b3b2ce98fcf0f869","nonce":"9d3fd552711925e8f3dce5e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"5a81fbe2d04e104ce7b20fa3ba241945742cf0ad823f5b083565b5e56342ac777d6a08b0e51b8b53466b4c826e","nonce":"9d3fd552711925e8f3dce5ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"ee12f49bd9ac645c40aa421642e5d2c40b1e4b7ff18af0ef3f173655d054e68f2e15b4c53fb173436ff9cd726f","nonce":"9d3fd552711925e8f3dce5ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"d5cbd98bc9bc40a7605c52068f378f9068426e87d7c3ba9fc4237f6cac05b037fdf04417755fadba76d6fe9f7d","nonce":"9d3fd552711925e8f3dce5ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"a5df8f52fb231fb2f657e17519073a730b55a47fed52105a6f91b8f1eca9f83574a7fbd64e2a30f81e0e45252d","nonce":"9d3fd552711925e8f3dce5ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"3c6e3a289d260995a5825dd089725043bdc65e60ba86d1380f10ff118dde41d47e54a9dcc53b59d7daa82316f5","nonce":"9d3fd552711925e8f3dce5ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"60de779cd28310335b7725a4ee53b4612cdba820046ff9bad40562f63cb47e8c4577da62d492d1d80d01c3226b","nonce":"9d3fd552711925e8f3dce5eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"edb385e86077583a22864b7c53d66a1ad33f3550b6092aeb1962aee7ffb9589794e7d8ff663db98ff520df9529","nonce":"9d3fd552711925e8f3dce5e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"955590f291a53087b48c6c8002de217a87f4497a57f2496b42f56e4cfd2b0dd0a9a0f62659365f46b2988cb39c","nonce":"9d3fd552711925e8f3dce5e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"b2c23dd7f4a8765dc9d8598a481dba6057748c6b881293656aeae61bf1f485d650d5c7a64a56537bb9407bcbb7","nonce":"9d3fd552711925e8f3dce5f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"122f81056ae7df61e721aaeb17966f027f1b234edb397cad1791c11d341ef255b94f67a6a2f0d1a8387648d2e8","nonce":"9d3fd552711925e8f3dce5f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"0ec24649b79dd49f2f5e8d38644ac32b4889b546754fc7cc02984b7cbc928fa8ac7aa76d420a329cb321ba0101","nonce":"9d3fd552711925e8f3dce5f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"165312ddeabce43c4f1065d123a0eafebf61e2e81daa8226ecda53aa3776169fb0c2c6500837b33a9a40ce3a00","nonce":"9d3fd552711925e8f3dce5f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"089105ec3366428bce8c02117493d26aaa4c0ec126f066613ebfd24361560ddb580d38d806d5c933cee32a0054","nonce":"9d3fd552711925e8f3dce5f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"9a71f148a66ae5c6b7c0c052698dcdaeac9c025b5036df215a2778df2954418fd59395a12de266192e7d3ffaa6","nonce":"9d3fd552711925e8f3dce5f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"cafcbc296e357144e1be19fb7f6c5f1154f95dea6be8af88445cbec2351e4d37cf49c73a1ae578c808abec03ac","nonce":"9d3fd552711925e8f3dce5f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"e80420a43fb31d0187bdb3c5012ba201d96c85fc3fd9098e460a8b123cea10d76ae7c7da148f8c1383f0872ebe","nonce":"9d3fd552711925e8f3dce5f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"3e97f6bdeff3f0c47265ab2d407486812e7023e0413e2b768b173f0bb8c17bcef46876b4dd12961359df8a977c","nonce":"9d3fd552711925e8f3dce5fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"9934a12d59d7b2ebc5a273e95b3cb2ad457eb662f04711b56bf094d85cbf71ab9d09353309163cdf89579cc2ae","nonce":"9d3fd552711925e8f3dce5ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"cdab8e6b27c47a3e8cb688a4f4463d18b5020e414d4a1b7b7a86ca8f686744872e499b0ae97e26b2e17e41eefb","nonce":"9d3fd552711925e8f3dce5fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"773993075fab10a6ff4faea26a5332af552344d86c295d6ad2f305e2742492d1cefaca09a187cc93389e3c88d3","nonce":"9d3fd552711925e8f3dce5fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"67e885910a1b16e55337eeb84700c433f2c401e4878932cbd717a67563c5a3ce7a04bad51fc907dcee1fefb86a","nonce":"9d3fd552711925e8f3dce5fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"3b54917b7cb8f4ee855aacc0d60451a52349e0d1967ab8545846009949e1433adbc57d8683645f16e9e5735d6d","nonce":"9d3fd552711925e8f3dce5fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"7d92ca062f4d519cfd2be4f1fe00477d45008f7fa97382ec6704ddea1fc9a745799515ddf04913b73683401a97","nonce":"9d3fd552711925e8f3dce5f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"4bedda54ef2f78ca1de711821b6e87d21fd867a0863b31451b007f3996e30aeeee96a2703e546086dea654ea7a","nonce":"9d3fd552711925e8f3dce5f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"2489331db2d37d442c1f2fba0c373c865703304bee0ca8869ac1212d105106292d435b96571556b0b185313ac5","nonce":"9d3fd552711925e8f3dce5c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"51bfe5d9c2735149f7b031981e8d90c65f45d3090b717a2e5df96dbb29bf7fba42f5f6cc3d64245a8feb82efb6","nonce":"9d3fd552711925e8f3dce5c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"79b4c77d439479640ce791c1aa54ae3ace4da6885e26d9949dbb2aea3c132bf45676b4600b31f41e67f7dffba9","nonce":"9d3fd552711925e8f3dce5c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"afd6d34b4d507df8cedd6cff823de75345012ee440d76531794344ba50c5ed549275278233f3147b4d26a53c7d","nonce":"9d3fd552711925e8f3dce5c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"ea5f2082859bba384852dd5cc9a91e8d8453e180b31f080097373bb34aec00a1a1fab6f0ed40c3a69fa20723d7","nonce":"9d3fd552711925e8f3dce5c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"39227a40e252083048eb7b8b36d3037ae10a014b0ed2fe191ce64fc507b0ce1229c24b3a248651bb152c611000","nonce":"9d3fd552711925e8f3dce5c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"1751e63aff29cd2929c1d8ba67e47d49745ee8563acbc7ef92df945dc5ab655f06d3d02e3d0c75600b099b7582","nonce":"9d3fd552711925e8f3dce5c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"1f8a86f1cf1f8121c97297e38f205af6e033a04ce72f654473d7fdc4eeba5f47671e973e68818f8f4e09da4f54","nonce":"9d3fd552711925e8f3dce5c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"4128c24303fe5acd0328da64b55e2e5f073f5ddc466c37020c9be8768727f2635fe39b981435f6891444addc9e","nonce":"9d3fd552711925e8f3dce5ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"bfe772a8990e74c48c969cef1a1996e88725f48855a83a04c80036744b9ace3029548d5679946d1e84d28df405","nonce":"9d3fd552711925e8f3dce5cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"e84390b18966d64ff75615ad0761ce3722ba782dda38a8b30f31418cbe116707af2c352514c798f45a881897c1","nonce":"9d3fd552711925e8f3dce5cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"227923346cbc035a9871d39bca21df14e8ab772220fe84f891182ef8f53970286ebbfa0367ad6f8ec848ffd6ba","nonce":"9d3fd552711925e8f3dce5cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"ba2bb7ada063ad449d7631242f6e3619d8822626a2165b91faff3bfc2fec32d8071f279f898a2b590dc219e996","nonce":"9d3fd552711925e8f3dce5ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"8dea7becea8e6adcd8622853aa8ebfac5e0ed2db69a002b0686e6e593ca1c44eddd25c850e6f22db1338ab98fa","nonce":"9d3fd552711925e8f3dce5cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"774ef2dd12487530f730dddc55c352975bab22bd44057d696e69e74deb19e7f63c9ce713c6d747ff23fcf263b2","nonce":"9d3fd552711925e8f3dce5c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"1411596b266eebfde02219c1ef7e550c4e60acfc692e31d4a4ec558a5d4ff28388f5461e445024739580c87c3b","nonce":"9d3fd552711925e8f3dce5c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"963c0e8170aa8afb7bf489a1b0333a378aa842b15e16f48c7619f0450e52818f4523e0c20bf2f3d9084c22a119","nonce":"9d3fd552711925e8f3dce5d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"fc16b3f084fbe0c49b0b889d5736544e9f21ef3e66053ed8601da63f91dc72939127d5b5d94d036d7932014a7c","nonce":"9d3fd552711925e8f3dce5d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"4422dd9cd7a64e147be0ae9e84aea636d8f0c2e2e7b1182b52957183430ec64f4c6580ab1d14a26b1515a76eae","nonce":"9d3fd552711925e8f3dce5d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"85b5d6ba8b0252569682243a45aed85128ff93e2b431665bd2cac2e598552d7862fc7061be0bc399be1e9015d4","nonce":"9d3fd552711925e8f3dce5d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"c2fbe4fc89d6ae8ff018a868894b0ae3c25dea97f530b382bedc24a5de67d9a59ef234342e78f69dda53ff9b26","nonce":"9d3fd552711925e8f3dce5d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"854190a1044a36c8a872d05a9b048ebe042e0c896261a023ff55159fb0cd9d7bc633a355218b64655439ec300c","nonce":"9d3fd552711925e8f3dce5d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"0c15dc0f41d6dc40a29f1d89ef5f301be2254afbedb5eb865e552776fc2ee8bbbe6391c861d512871ef57f8085","nonce":"9d3fd552711925e8f3dce5d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"ba16915d3f574a50d78ed041234a0a6ca64c843be4daec9cccc8f68901bba828f84dbf6f391a2edcf1400242dd","nonce":"9d3fd552711925e8f3dce5d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"3993674713af687d6e8e44c04bbeeec45860207a115faba4578135c7f14740d14551bc8581fbc399bc4936a024","nonce":"9d3fd552711925e8f3dce5de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"02444a47414d2dc259095614d4be68e0fadbba58dd9f0820b0885dd67667f0e778d11d7f1650b914eaf7604a4a","nonce":"9d3fd552711925e8f3dce5df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"6eabdfc1810582ccfabbd02e8cc60ddd01f421f9395bfd71e3b1053860e09c33f8bf90f8c95b8c641ec03e5ce2","nonce":"9d3fd552711925e8f3dce5dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"7b2f4f60ca31a1c1e914a95d57d9dad89625814c1c1da1daeaa956002277a655dbebe9cc584b0e60cfcab15e36","nonce":"9d3fd552711925e8f3dce5dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"b3a69ec6b2fcb6c247ba04a91f9ca0d92fe80c06c78a049a6f48bd2289dc599f4da8be70f72bb8123d55e72ccf","nonce":"9d3fd552711925e8f3dce5da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"a4ea11ba1877b8ada9f4b82b0edbe18198dbab95729dc5342216d522f399122a3b9a337138fb889a4a61d69ec9","nonce":"9d3fd552711925e8f3dce5db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"4f4ad53776e9e6622ddcb069df29a7f0f055bd5068e6c9a3cb0a9b2af9e07f18df11349f77f0b0ced02700de7f","nonce":"9d3fd552711925e8f3dce5d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"c29de4456b54d0accbd022f54be8c86330cc0124dc6a84088eead14ea7a3ff1ed164fe0a6d7e2be2c459cdee55","nonce":"9d3fd552711925e8f3dce5d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"90fee50f0e677022f79aec2a14e531b2c17da0afe0ab754648bf494b296a26e31f4cb02cd935828ac3aa472fd5","nonce":"9d3fd552711925e8f3dce5a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"928c8e08f969e65bd4b538f30451b4eb0ee74b47022daef5c48ecbcc3085a63c5c146d70240b94d6361f6e1a2a","nonce":"9d3fd552711925e8f3dce5a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"b030b07110e14bf9ef6fa343f0277542a7934b971a730ca0e61308c978da7b153761048c306eadf9a5ff47cf70","nonce":"9d3fd552711925e8f3dce5a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"432e6a5a77897ebd17f59a75d879c3b8b04509337e335e42b97063715913537534a203a0bcf8146eca98e3f1e9","nonce":"9d3fd552711925e8f3dce5a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"caca1ee7398238fe364f1db8e09e1493410441c9a3425b8f6cd3457c4dd9b5af8e1885831f567adc8fdbb42987","nonce":"9d3fd552711925e8f3dce5a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"5c71a0e1198a246328acf86e064010bd3b05558961ce8839256b8ae918aa6198f3f4cd5f2b8db6f3751e37477d","nonce":"9d3fd552711925e8f3dce5a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"a6a61f6b70a8fdd068dfa217fbc40780b7770a96e7471223fb3407143445ce0db4e98718fafb77e20fa23a47a6","nonce":"9d3fd552711925e8f3dce5a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"5a1257aa397d87c2fc9382870bdaf16ce924b5e0806ee342d003f20d707b539f0359afbfac4c639384ae93b23c","nonce":"9d3fd552711925e8f3dce5a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"0bc585c1f1fde34763e30f3dbd12f0b0186f409a9284a53a24e8e925f4221b83ec7db4d7736280a367ed8afe3d","nonce":"9d3fd552711925e8f3dce5ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"920dfae2ca228e38ce5a7a09bdc6fac32b5c30b67d6c5899046af773d1f8e89c3e8a6c201fa04fdf821d291373","nonce":"9d3fd552711925e8f3dce5af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"0b164c2e543fcd81d7a1b5a7d22985c5422845c7ed247929312ddec75063104f409f2a04944204db46ee972db4","nonce":"9d3fd552711925e8f3dce5ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"d3e7b9221f9f1051e8aad72a18a8bcabd6f73001369fe3c87b849a2e819478ba9ba07e04bc6b8faf13059beb08","nonce":"9d3fd552711925e8f3dce5ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"33b6362f3fc2c9fb7def312eb7e71b77394cf5f8bf1bf0b46edf29ad37dd6554cdab1fc3ff5b0dc48405a52fdc","nonce":"9d3fd552711925e8f3dce5aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"3c9e5be2088020ca563702176cb9a37778cf6f5d0410239e7ba629464f0fed7eb04a16fc9734fc67bf4f7e0863","nonce":"9d3fd552711925e8f3dce5ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"c4c7148545265638b4763614de64616ee581e8ac0edcdc9b812d581e3a1364bc6c8858d28d4de9a7ad23b46d52","nonce":"9d3fd552711925e8f3dce5a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"5083dbf3b3661c6cc1077f8f858f73fd81f3cb4ab53fe83717613e5e0c2ad6c920ae1b2372909db17450a7118f","nonce":"9d3fd552711925e8f3dce5a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"c5c6f8d7d7f784eca1c2b35cd7de374238ae8029809ba1e0804331204d81ff675521e59f6c17c84e50cf7ed734","nonce":"9d3fd552711925e8f3dce5b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"70fe1378e2d90e0f2f602c2574ca4ced29a0679a35eb29fd1cb8ba755c7847e54a4892c69af3d877e48b0dc1d8","nonce":"9d3fd552711925e8f3dce5b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"c92c6211ae972387bd0069b3d311520675e90e9b17358aa47a3ef5674586a3f33b00d8792c3ac8a3f011b1d8f1","nonce":"9d3fd552711925e8f3dce5b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"0c7a7c1368f2d464c8a1908877afd2da494a06a5fd319c4fcbf5f241407c66c0cbf06007d0238dbfdab24e8691","nonce":"9d3fd552711925e8f3dce5b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"acbc7f65ceda48fce6cc21725514158ee0e294a138f63a73eec4821763c45d4f5f799462dc6b0e98e083bc866c","nonce":"9d3fd552711925e8f3dce5b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"29d3ac5b31f88ffa79743b1d30aa04f67929d31f7bd0e06f2e6ba283302823dec82115e1731b78a066ef29393f","nonce":"9d3fd552711925e8f3dce5b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"7a6c8b4afb29ce32ff0bd68cfa0cbf93f671e64c869b790df2d794f4ee921767e21e95e4cd45bdd2f526aef07a","nonce":"9d3fd552711925e8f3dce5b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"fd185bd546b3a316613ed0ca3ce4a4e42cee9a73703fbe2c1f143c6863ea74b9c0db205f080a78f89dbeed9dcc","nonce":"9d3fd552711925e8f3dce5b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"99542fd4ddab1a4c0f2830e39e60fd39a4858ceb76c8b132827102d1a43540c8807550ae5dd96dd7e84b13cac8","nonce":"9d3fd552711925e8f3dce5be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"a38709ec1476021f02ec28e10ce6a4130ecd3f2b44e7ec0736c007a8d3888af62d4ca59097d221e6e6a27ebf7c","nonce":"9d3fd552711925e8f3dce5bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"9c586a08dbfc8085dc6c573b0af7fe74655faf3312dd0c4bd84ecdd756ac71cafdcca9f1b3f212b94a6854525c","nonce":"9d3fd552711925e8f3dce5bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"1686c781042379c6ece35b7c927e5e4e6760ca25576258e186fe08f2e1d37e61afd4088d59fa2cec539515ce85","nonce":"9d3fd552711925e8f3dce5bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"8e5c70a90970d720d0cdba2ad3d1341128806a74ab3bf5aa9f199b733210a5c66531de70dde0db2df93c2b3d40","nonce":"9d3fd552711925e8f3dce5ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"d4a086f56471a2e71642909fdcedf718b9edfc61df48df45874f7442610e7264868b45e26874ab1b9f46ed69f9","nonce":"9d3fd552711925e8f3dce5bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"74f9572a74c424a7b91f563e9a30576d317efdce5d128873364206d26b7b88fd899a477a4f29b11b219536b2b8","nonce":"9d3fd552711925e8f3dce5b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"7901460bc6e3ba033e3ead54fb382a233b78bac951fcb80346698bfd75f438fe668ce6e1602c3c3d1a08076b56","nonce":"9d3fd552711925e8f3dce5b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"4e917033de286658a7d34a5fe546daf3cf338e04a8a1e443e0c055006e8d74df78aa61091a63cfeba5a70e2a40","nonce":"9d3fd552711925e8f3dce586","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"9d72229f8284f3a45055a2ede0a0d672e9932d1306eb1c1f8650fdfc7cab8b70a7150ef0f0f8421c19e53605cf","nonce":"9d3fd552711925e8f3dce587","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"1af31980b196b8eae1d96f977513adb1c2c9b64a38d8e4ba230c80e795c527346c6dbbf8826c85897e09d41d5b","nonce":"9d3fd552711925e8f3dce584","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"98c309f8e082c605f6af833c2faa5e8dd3a1be5280c1c67bea2119a713db2ea2bc88eb5d587d021a639339fd7f","nonce":"9d3fd552711925e8f3dce585","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"c58e106199c5986f865e355c0b306000c48b8f9d5b3a549b23429de392d2b52a26f9afa325353a0209781c8795","nonce":"9d3fd552711925e8f3dce582","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"4a86ba9977f3fa314b0d4eca5753f0c779f2193ee114df849a77be3b7c1c0497c2607e69e345dbc2c4dea4be17","nonce":"9d3fd552711925e8f3dce583","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"b372ffc2eb4e58ceabcc69153503d01c6f11f789837319cb8be0cc3ed1d7de67168fa4bb44cd0abdacfe52d87a","nonce":"9d3fd552711925e8f3dce580","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"ed32f1590ac0f7fa37750934d34ce11851422b737728b08764f91c45f2e230f8485a6c813dfed8414abbec438c","nonce":"9d3fd552711925e8f3dce581","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"326bad4f8a34cfcc4935bd54353dff0e2b9e56a804491ca1b1f8f1f1480b4dee10d9fd675207af84dabb342db1","nonce":"9d3fd552711925e8f3dce58e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"f4c312536d9dc852ca463fd3cbbc20f002be269d73e071c261f1d25afbcb06f68396435c5d9534333e789f1c65","nonce":"9d3fd552711925e8f3dce58f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"467c0033e038f5956fbe42200b649db275969beca4a62ca8948034a93a2170b90735d8abae4a3c380837bfe006","nonce":"9d3fd552711925e8f3dce58c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"2807e96d11d2f945c6a3c651128a3cd5bf1af2e157a20c7c1dbf56f9852a3aabb39bed0e80b30351223eb5784b","nonce":"9d3fd552711925e8f3dce58d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"3c5df256857851cfede418fbc5715a26ebd845e6c77f8f771f52fb8a0d0fdb2c4f3116b66a105ed120813d8dd7","nonce":"9d3fd552711925e8f3dce58a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"e84cfceeb4d83f0abdee9a718bc5680f374d26bd4da41383fa249fb786d696e1934b480ff3cc8f7424513dfa5b","nonce":"9d3fd552711925e8f3dce58b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"46cb1c40367cc93671e5740af009f9ce5b3c04758317bd854fa5f190b1a12c1f9662b1dbe6a45cb4f8dbc09ab1","nonce":"9d3fd552711925e8f3dce588","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"0c13abc6bbc5a9e25e0598e33667e0d0ce2ed66b495d2e699c63de41fac4109f16ff56ba10121fdfdcf502323e","nonce":"9d3fd552711925e8f3dce589","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"e8e79986b3d8172b883868a6771940aa64f5bac9fab4f0432ae6d61e641ddb68c60dbf0941755a8d71efc68f01","nonce":"9d3fd552711925e8f3dce596","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"842b82beb58d4b95394a98bff3225ef92abd49c230bb622c0d7093508adc4c64b061b3604beb2bb00b4edc128d","nonce":"9d3fd552711925e8f3dce597","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"33560d3ea1af6c3b982eabe7b4f3eff9a35b57a4e5c98cec6b145c3a019458cdb6398c2e3a3ca64234d3121886","nonce":"9d3fd552711925e8f3dce594","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"8262184a69cbfc7e5ce7a21dc3ac9f92614682d9e8891b2c13bef54210bed166c192806277d5c347f3d45543cc","nonce":"9d3fd552711925e8f3dce595","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"56246597beaa6dae0d16b794cad8deaef1876caaff5e3e721cc300bff7a0cb8099ee6916546ab386355ef4b5e7","nonce":"9d3fd552711925e8f3dce592","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"254b7b8c2cdcdd1fbf75cae44a55fb98575e9832606ee0da7047d89657180712ce13f5c89e87fe2244065abd60","nonce":"9d3fd552711925e8f3dce593","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"8a8a44f8a9e0a29a34ae77abeef78391917bec396d2179e8727b2fecc0aa82b6c6868433a8fcfe21d9c82943c8","nonce":"9d3fd552711925e8f3dce590","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"aaf094ea70073dda350d42fa4e7e0249b861cfac88da2079abb6437fa925ed90d7389a6c07c1faf6d171f74620","nonce":"9d3fd552711925e8f3dce591","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"f266b4dea15be666afee38961d059f2b887504cd32a61631e6a89f212f02dbd69a2ca2e76f978eb5062646b0aa","nonce":"9d3fd552711925e8f3dce59e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"39266fa6c99491ec344402001e4cb74b2eb3d061ef78d9f21ad599fd291f73594db586cc11dad11573bb6863ee","nonce":"9d3fd552711925e8f3dce59f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"c7ec4bfc5b794612ed93422ba0aa6b3c910d5ed976555e99b9dd08664ee74eb4ef8081b977ac63d6be92aa1061","nonce":"9d3fd552711925e8f3dce59c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"fc32e4caee516149d7a96df2e7528af13bd21fae4e4bda0066f993829bed492afb9dcdc2f9f410f22aa9e3bcae","nonce":"9d3fd552711925e8f3dce59d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"10ddfe64b27511fe807fb5e7fc5fd6f35d47cccf0dca56558be4e1c4254b62c275971a971c0c8313460d3fe1a4","nonce":"9d3fd552711925e8f3dce59a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"30bb092b80b37b17789079fe1a44e7b6e83fa7c8444435dbadca00877608f10a14e8d2a60373955618157f243a","nonce":"9d3fd552711925e8f3dce59b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"1819229a1a3ca75f2d627f06666c887b53218165f270d184b489446a6ff95b6c006a830895231dbd8a2f9645bc","nonce":"9d3fd552711925e8f3dce598","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"881afed124ab6d2f26649ad48e8e1662a34cc04515ce9037159c8d562527a10fe56c8706b708683d9c8c2a6668","nonce":"9d3fd552711925e8f3dce599","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"1dbbb3d234992cdea565d0de8a5e20cac14b531165389eb8b181d814bb156b27936f95f165583e69ee655403b2","nonce":"9d3fd552711925e8f3dce466","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"ac7eabd4dcee3b6a4bfd5a9edde1e6a38172b1e5ffa716f9b658183f50a3a54d"},{"exporter_context":"00","L":32,"exported_value":"dea0b1476572e93eff49cda654d80ef2626ab27e8d1308f3302340483771be8b"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"c3a6c3f9bff8aac4c9a5c2a6ffe59765ae574d74fab9b3b73fd4efc0a18023c3"}]},{"mode":3,"kem_id":32,"kdf_id":3,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"017296a9743280e7654e5853c145960c2c539b0948385ea3e80fd60aab2f813b","ikmS":"4488b7c8118905bb29534961a8d59bf077064578d0846e8f7cdd87ce7a9c5fec","ikmE":"932a077460d845a28d324314fdacb47abdbbff77b07660d7241e16f43639a7b1","skRm":"adb977f799429da0ae426b35f91a05a0f9d6640611da904d3875782d3d07f944","skSm":"8567163669c4ca5aba7d862ab325c13398bdcfbaf475a43ac91cd31986792d83","skEm":"15bc7d736ffe72f753a8f23f8b9c082ef2d72d88dde6514ef7aa06be1fe696f7","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"b6554c9c3ccbdb23231e1a582b01fd8e1918588cb5779e616a70bc36a4bc6064","pkSm":"12d1f298e9b32510d45ea33700038d0f98c621b3e3f7b40a65f96f9e7cec6559","pkEm":"ef577690a6b83cbb8a53d3ddb094ad309c0797ff81abeefc7a3ff0bb54b4ef67","enc":"ef577690a6b83cbb8a53d3ddb094ad309c0797ff81abeefc7a3ff0bb54b4ef67","shared_secret":"ef2bccadcf9b1d46a280b88792ef58a0becdb212ba82d49f166c22e577628ab7","key_schedule_context":"031b6b08c282945123288e49bf5ff79e6dcda0afb9b4391857b06a196397b19c21e12683685046440266553074efce3b8b1d9d6f5e0c0a2544c426f62db07d748c6f17ad5b0cda65d91049ff137dc5111687e0d4d44123d94cf2ad7b71ecb5fab6cdf8e044519fe1ecf7cffb6a3f3bfbaf6babfebe5d30a92e166f52849e8d35a3","secret":"c438fa0eb09bdfcbebc01c2179ae6c7f8b4d58799098e3195ae264140b85428fe52f95120dbb27618cd2b59fddf469e9de70c025b1a4003e609ab85996fe0ab6","key":"1b38f93ef7d02e4717cffae6dbf1b39c","base_nonce":"6a53e3f0f466698a5cd7f022","exporter_secret":"d9924e5ef71ad6c510e513bf97b13e321796c0cee4909c537f830d567adacde5b6d9694ba1722ba0a5cc8d151c6dff66c13b8aba4484b91941230c561016f34d","encryptions":[{"aad":"436f756e742d30","ciphertext":"ece4c064670f533816f171b02730030cfc282747e276ca6a67751473b5d32fb21a273aafd06aa13fc59f8d0483","nonce":"6a53e3f0f466698a5cd7f022","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"617b5e6c6749b2d8b6c04785b367eae2c0754958bcd96f9ab4ca1db09a170e04a71d71ed4a6e1c4c3e74b94cdc","nonce":"6a53e3f0f466698a5cd7f023","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"e8f31a9757bf2e189d2d3a72a6ae2987d9f9297a7af682d1f9d32aa1a31f4c4a29510bb472ee23ab6056258115","nonce":"6a53e3f0f466698a5cd7f020","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"996abfad890c25cf8b91098465b60a88c2dba429f6d2c5b0b5b6fef885777b96bc1bfd1487d4108beae365471f","nonce":"6a53e3f0f466698a5cd7f021","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"e5ef6c2e4188ca69d770dfae0b83f7a25a359c5468f165835d7495d003c46304d6cc398620229a8ee13b80f1d7","nonce":"6a53e3f0f466698a5cd7f026","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"490014083060d2ec8f49a03014b84ecbe954c3336368a0bb9ef9e6ee885c061c243bfc50569783eeb8bf47648c","nonce":"6a53e3f0f466698a5cd7f027","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"d0f43d633e7d9e4255fc5a7fe3ce593580725c926c3e58f7a30751f2f14e35392ccdbd6c1a702088d1e5b6ba69","nonce":"6a53e3f0f466698a5cd7f024","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"2e4b187a264150aff2e579cba9d4107a2ade0305d9fc875477dfe600bcad3f64de99ccf9fa86ececb57994af7f","nonce":"6a53e3f0f466698a5cd7f025","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"0f00cdcf4c12c0033e74e0c9d5f65668e20766d1493c0dce53522817b576d857ac2e566b4e0a59baa68148b57d","nonce":"6a53e3f0f466698a5cd7f02a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"d902c3bb566a203efc7080372a8acad48893d9cf6c68510a293341aca5e0db4182d287bbeee14b87885365d505","nonce":"6a53e3f0f466698a5cd7f02b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"fc17047c5084d5411b2fa144ad007fc1c8ef57fe58cd80b0dae658f10af66bee7a4203ce3b3aebcf457781782a","nonce":"6a53e3f0f466698a5cd7f028","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"29f32e4637275106e1d3ccd894f0e6034c9599600df6beaf1021d1b3e359f314246c9137ff63e64a061a926289","nonce":"6a53e3f0f466698a5cd7f029","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"79892156e2a0f85dc339fbe635cb2fcea026202b990828676b54af6c2c316027d2fd4265b60b97cbb96dbb0c73","nonce":"6a53e3f0f466698a5cd7f02e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"5fbd1781bba9d44668f22262f58c5a88d0fc83799546cf29b7ff3058e8fd985e2035fb48749dd052f83ace6f46","nonce":"6a53e3f0f466698a5cd7f02f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"da261e2ee10b678ec76de376d2407c9b4bf21332f5d455375e9b1633b67d9178582ee3f618f6b21ffc8d1f69b7","nonce":"6a53e3f0f466698a5cd7f02c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"7e677ac577fd15375ccd85a9003698c11f036f4e0051265cf98b0a60689544ff2d849ff09c8816c1ad87ee8b26","nonce":"6a53e3f0f466698a5cd7f02d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"adac2016348821a03650deae22a799d2a6358ab0cd086c50a12d39a01af9de1c3b74351c47238add075b43f56c","nonce":"6a53e3f0f466698a5cd7f032","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"a9f01caaa2e61173973a8bc6bd91b6958b113a42d177da7f36192988798e581fa57505c819202f3fe18998c646","nonce":"6a53e3f0f466698a5cd7f033","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"20d34b1b4f68da04b01b4fe77a1dc1d78877aa202f95ad0f024ef3665105313258abc40a5060a9f0d57473b73a","nonce":"6a53e3f0f466698a5cd7f030","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"4ac2cd32b828c65e499ae7ff7ee5fe9e7ceb3c8e6f5b839c555a8969865747080abf6b684211e2898da6f62032","nonce":"6a53e3f0f466698a5cd7f031","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"fee2802357597febc3dbe39cf23dff9cd4a531163fc049df88241ceb054d0d27d13562863f7e1806ea89cf3bd1","nonce":"6a53e3f0f466698a5cd7f036","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"2a990514bd66ba2e0178ad1595156eb97d7b8c142a8d81599030a5b7c9ea810ebb911b2c34ecb2efc41e34ed03","nonce":"6a53e3f0f466698a5cd7f037","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"7cec9be433525c0ede2e6ab3abfccfd2dac983b187db1ef4217fee0bab4297efe8c523c98fafdeec24f6044dd2","nonce":"6a53e3f0f466698a5cd7f034","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"c5135408964fa85a1e89755753699e7394386719187225943de5ef095fd88ba3a616f09aea8fac3a16b894eef1","nonce":"6a53e3f0f466698a5cd7f035","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"6eeb35bf7e7221b3e96a9d522618317e94c7f33d55f9394aa6cd99c5227e9f414644f186d532b2b732d2fcdc9c","nonce":"6a53e3f0f466698a5cd7f03a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"3fea23d16c9f1afe428ffea916142f65ee2b4eb234757dff37e17782d965c1b3866d53698a1c29ad288291b957","nonce":"6a53e3f0f466698a5cd7f03b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"1a586ae1fe97508654b77c83224ff80352e89f423bfa9677e8b1daf3ab82041950b617a616d54c8a6b3ae2b806","nonce":"6a53e3f0f466698a5cd7f038","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"175e08d03821c8c1da58846aa5efd88d910cc5942aecf33e7a23263b549d0b59519f01d3110d2cadd3e4be1ba2","nonce":"6a53e3f0f466698a5cd7f039","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"bb2a043815078cebd3f6f801120d3ba24b4b6276ba4e8775a07a3c00bc84cf069e46702e83fdf493045ff83a82","nonce":"6a53e3f0f466698a5cd7f03e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"3de301cac151cbea1ca106ee8bf7a3fbdd75fc652bd9f3d08be146dff0396b202ecc42ffcbf0aec2124f71bb61","nonce":"6a53e3f0f466698a5cd7f03f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"b7d2eaa2a8991cfbaecd0a4fa519b982b85e136c123fe85895d2a24eba3f4c159fdc39b10c24a025a84faa7163","nonce":"6a53e3f0f466698a5cd7f03c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"c6ad3c8089c3ab83da79961b3afc1ce965375c92be4e0f58627809c611f7d6dc40d5e5fa6388e71f209a402498","nonce":"6a53e3f0f466698a5cd7f03d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"dd08f006683ded79682ac9c73d86506c98f470ccd8f040aa4ad11366cac105e826dd1d0ea7b0ef8a45792cd7e6","nonce":"6a53e3f0f466698a5cd7f002","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"4f497182641ac1e6a1c05c0007bcc2a74a1eb3d2aa58a7fb923e3b3e74ea1ad31624cbdf6486454c4f2e4c1a15","nonce":"6a53e3f0f466698a5cd7f003","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"1d0ee55837cca7e2a4fa46d0e391501ae9916d45d75724c038a978db9ee1e2ba0d8639b62fbce94ed05e584e03","nonce":"6a53e3f0f466698a5cd7f000","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"bb308d75c258559be2eba8920371c94b282da1a107d6ee690ee132dd2683df8bc03f713ef86f5cf9533349c08d","nonce":"6a53e3f0f466698a5cd7f001","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"3550b230c202edd89086d1be9527f8e566aab3894ea9c5de3e3150d3632cc6910a08d1ff4e611c9135a85ff4ed","nonce":"6a53e3f0f466698a5cd7f006","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"d35ba8c776991e6323db2d1b0490eb2afdf379173ca30fe8cd59f9cebb0fa4643c0118ba17b2648101bbdbe210","nonce":"6a53e3f0f466698a5cd7f007","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"32f8b7179b24118cf50d76ea7e6709d59d214edb728376843effc1b0edc1b2fad098dffa31f190035bf234d694","nonce":"6a53e3f0f466698a5cd7f004","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"9e8f6bf19c5387a4c7f562d6a8f3cff515156b8c1022046721eeb64f169045251f03549c6960604afbd1ba742a","nonce":"6a53e3f0f466698a5cd7f005","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"95e64e27038d983871cc1d95148188fed4942a3989f7fab754d8f972195cce5aad0f681ebb67774e22c9b5e49b","nonce":"6a53e3f0f466698a5cd7f00a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"6770003d5bb1feced11bddeb86f8417bbdc755a2e3f485b52f517fe859e020da0693e413414740475d66e041dc","nonce":"6a53e3f0f466698a5cd7f00b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"be58f03a5947611bd2d1a33e321c85c4e3939ec5e71b84430071a7fb853c25e934d98c8686a73f69b8b8c155ab","nonce":"6a53e3f0f466698a5cd7f008","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"916f69060bed2360a976a39e73105e1f5e94b823b165346e0779404a8895311276a4765a6d9c7b98d91a31d86a","nonce":"6a53e3f0f466698a5cd7f009","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"39345b37975c8efb028f84d77b923a81a39d3c9af9ff6bc08b3a839aa36767392877d387cc8d1aacd74b2d07ae","nonce":"6a53e3f0f466698a5cd7f00e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"483f3f87a23d582b88518319d65037a7f860869427b678d78c40833edd3f045e34ea98e1f31d57d45e2b5cec5a","nonce":"6a53e3f0f466698a5cd7f00f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"03032314fdd3b8ba27e2b578ed0151291db021513bca35a817a29dcfc9e26a9e6e9e647f0a7845e74d54b686b1","nonce":"6a53e3f0f466698a5cd7f00c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"27aa8c06766b9de557e6e7c5a3bcd2f4d57779aaf9a329a76bbde19d64fc6ef37871fb077faf811535b9d4a0b0","nonce":"6a53e3f0f466698a5cd7f00d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"0d7bc82a56baa3a3669c2e95a77a94b3190adcee3b6c301428c1a1247903ab28bda0f85d9427699450e0e9fe75","nonce":"6a53e3f0f466698a5cd7f012","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"8887e627d215dc53619264c8f0f22fe11f616f9aed2468d57cea4146bf6983e14bd104ac1ba83df6913977db12","nonce":"6a53e3f0f466698a5cd7f013","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"2724398db5d4a8154f2cb5f22e6707b8771170ca52422dadb18f8e9a6fc168527cb96d61dfc23c475c8eb7ae59","nonce":"6a53e3f0f466698a5cd7f010","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"4d7bcb981036bb1a835a4e4a5339b608ffe2f4bd70f20e8a322fbcfd035579cfe7a0282d89639ae102c7b82391","nonce":"6a53e3f0f466698a5cd7f011","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"2cbb5ccc9af3e30d2e2f3a691390e64f850e9cba2470bc9c86e52d0aba53271c99ac838d554ee928297955255a","nonce":"6a53e3f0f466698a5cd7f016","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"37a04cb249cab22c5bae296ae2f9715d0fd45e7a6f945402ced5cd33f71d52b1e5187babdb089672c70e0f3479","nonce":"6a53e3f0f466698a5cd7f017","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"35fe5996c81edbe1fe16c95b4d5fd5c7208f0e6e92814fc4404683521a561167f44453a7589a40f7ff8a410c1e","nonce":"6a53e3f0f466698a5cd7f014","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"d7be8bef0049d75a0e5c30ceb2d7a603b46984b2690a59a4dc3ae504d437b5f55223d7ffec03132d901c11cff2","nonce":"6a53e3f0f466698a5cd7f015","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"fc14aa00de6cebc8e9e00b90903af2929bb0a402b47230df913c72e30ba5d12644139fcbb5c6068c5f278b58ae","nonce":"6a53e3f0f466698a5cd7f01a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"c3dfcac8d2d23866e9621c2a256d497ea35e28a64f4d20c9b55ec64b923deb10027335728d218260b6f7dd5fb2","nonce":"6a53e3f0f466698a5cd7f01b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"bf900b18bdcb834dd1835c1570604c64cb16c9534a7fa6ef69349f99330054b649971653e6406cae0e94e78759","nonce":"6a53e3f0f466698a5cd7f018","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"4a3e8353677d66d0d47d46dbccbce165396784b333b3e14531fa24150af9dda48dcbdb0792722e51ee4134190f","nonce":"6a53e3f0f466698a5cd7f019","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"0e0ee7c2d81969d27cb30d9954e7ec138697cfbd08b92c7a4a69dbc28c7f3e1f54528c59ddd70ac0024726ba6b","nonce":"6a53e3f0f466698a5cd7f01e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"6c890be27975be5d558a685401b3ab2d66a9076767c0ad9eeddfdfe976be35dbfcaabc8419a241595d373fdcd8","nonce":"6a53e3f0f466698a5cd7f01f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"5a8583c6020b5a847249c2537c518dfa9b161c697d023cc00a48529166162414af0a33f3bace875edf41141071","nonce":"6a53e3f0f466698a5cd7f01c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"88fec8ddd6552ab284c4e51d3a6fa2164d255f0addcd62ec916f934b81d57bf3f06337b66779875822fb42cfa1","nonce":"6a53e3f0f466698a5cd7f01d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"1c87e6fcf58f60de1b4dee5d0d8c9ef9e1341eb5159455cf1b3e7c8668a452a4386ae836b16cd78fc7b7aafe86","nonce":"6a53e3f0f466698a5cd7f062","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"0b069729c9032f5db429e432cb3ebecbfbc77c5b6cbfdc56f9072370533a4da58464b46ae25fda4397a2a5f417","nonce":"6a53e3f0f466698a5cd7f063","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"1c3b28c424ee5f53aa93578f3114959b22a4aa04322012ea34d791bcaea7f5b5ce710a68d831552f50ae66cc12","nonce":"6a53e3f0f466698a5cd7f060","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"84b013d827e535b18b1cdf5a8af42f56c1bc1eddaf6c5c98401d7c48a20fba063534460b8a922f9c6deb510ce0","nonce":"6a53e3f0f466698a5cd7f061","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"cfb2b14fdf60111d725ebd0bc54c0b3a306bb5eefe17bfa176b2cd3f8e5ad449206f8512e08b8ac3a6fbc3421c","nonce":"6a53e3f0f466698a5cd7f066","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"0bcdc00a8c5db066122ddf5003c56f18915910d2efb4c93c5632d601713d2e9b1f92fb372a69736e4bade5ff8a","nonce":"6a53e3f0f466698a5cd7f067","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"03bf8902317a96f71bd2af74c38c9240f4385f21f6ace8ac3ff2aa63feab6917005c5f08a0ac8fd0b03a261ccd","nonce":"6a53e3f0f466698a5cd7f064","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"beba44a9ba432e157501d209d3530b8716b3fbd69bb3b3e110c66cb1e467a04b4816fb31faaecb01b885eec3b2","nonce":"6a53e3f0f466698a5cd7f065","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"1bba27bbf9796e8becc412f13790c4371984d05748a17d392ecefc18ac38df37d76146c84cbd8d59d5230e575f","nonce":"6a53e3f0f466698a5cd7f06a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"71d6fdfa395a6a044238482dc3e8a044a8104c59070f500afff673bb902f8d7ce188ac198339aeb2f2f0725575","nonce":"6a53e3f0f466698a5cd7f06b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"4d4ee69e4636fc37d595509d23eb21c7f89e507cb4b45667f63ce5dd335fef425ef6d0a695afe86991e2b9bdd1","nonce":"6a53e3f0f466698a5cd7f068","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"6fbc173347db5b49825f41db6a7feea2bfd12d96495b46f9c8fe68f43b22bad26ff5eb1bed1596c513c7697bda","nonce":"6a53e3f0f466698a5cd7f069","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"2490b8947ce4005436bce1bb3d06705a1891bb4d09449d1cf64621c1941f2ac6db6a00bc2abaf6a4e4967c1ad7","nonce":"6a53e3f0f466698a5cd7f06e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"20abbfcefb3df3067e290960d5bd5c0aa06d545440152cac9c559f124de9a15d853581ca98bd36632f0700c441","nonce":"6a53e3f0f466698a5cd7f06f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"bfba5659c628147c7e72ae11f53bec7a9edaee86362ec32c8b653c384fb6f78ea753275d4d8525f9be411c64bd","nonce":"6a53e3f0f466698a5cd7f06c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"d5596c9c6532cbaf8a703fa040a5ce6b4c2dd99abf62ee9f92af929197cc9a6485e504b71d1deb60cebab87df8","nonce":"6a53e3f0f466698a5cd7f06d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"e90b2279b3f2231777acce11d25195c9d82bb02ededa02537dea2d170bf0b691839d257c7b4b6b1ec91f902dca","nonce":"6a53e3f0f466698a5cd7f072","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"9594e9d436c1c30c2ec01254d2c2ce0744fbe2544b60e6368904a70b5e77140895e614ce288cde78aea2975c76","nonce":"6a53e3f0f466698a5cd7f073","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"e2dd21cfefcd7dc4e49d1e474a41976f4485b5584a3359df3c35d1a1a09c0d6e24e780de61e805109312886f10","nonce":"6a53e3f0f466698a5cd7f070","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"feb6529bf2f742f41d2b2bdef3bc47c24907b121d173078c46ad44c48b2517c9cf36deaf3ab5d8c949f39eb9bd","nonce":"6a53e3f0f466698a5cd7f071","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"f335a7a7d0cfee3c2751b25340a1a3cc0c692c04e264155a55d28fb4bddceb6da8d7df990ee2c0b82764a7f124","nonce":"6a53e3f0f466698a5cd7f076","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"31b3c0bb4ece5a16b435a8c44348026dbcdb61a422fb7b654986393231697188569ee7fc7129710d8e7972f7f7","nonce":"6a53e3f0f466698a5cd7f077","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"5dbaebd7ab22d72efa87d0df6b7b5f61527f371cb6cc796306b5ec7977c9d54fc1f29eae422b040a5fec3e383d","nonce":"6a53e3f0f466698a5cd7f074","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"d68837496e47fb60c0fd490a960658bc94859fb28674fa930aef5e781e986909eb86635b7fbf25169adf88a883","nonce":"6a53e3f0f466698a5cd7f075","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"fd1074c5747f9b0ca04f44031525ea524c972cb26223af3f64742e4af4edb4ed46c307dc30e772399d973d16e6","nonce":"6a53e3f0f466698a5cd7f07a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"754c7b688bbf08be7821098fdfb2b6851dd960f3ea82840c98d781e550553c27405c3e040fcccf74cd975b90d0","nonce":"6a53e3f0f466698a5cd7f07b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"2b80290a606dc04f37bbd5d4f55416bd6aa279936b3c8a30ec3fd4693e47f69546aed3075fbd1071118dc18621","nonce":"6a53e3f0f466698a5cd7f078","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"46ffdbd28d8b7f27cc419cdc65d2e89719c837d271e79a6f9169b2b5cb84c6f41ae8acaef44703b77ef9c140ed","nonce":"6a53e3f0f466698a5cd7f079","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"74055ac513b3dddc8e1b87269073dcb93375ce878e7357756220bfc1d61cdc3cddcabbb25f4ff93644fe4608f1","nonce":"6a53e3f0f466698a5cd7f07e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"984b4893e66f22faa160dae426bce97478a2b67777ac2b8b204b44c56ee3e8f8c547d05b2246b0e7620d714ed9","nonce":"6a53e3f0f466698a5cd7f07f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"118101e991d5018a1dccbcd2a0030ef9f34333c44f90fd27483dc06b434a89f69977f170c378062edb6e776dd2","nonce":"6a53e3f0f466698a5cd7f07c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"1fd3c82bde1a8b83f84b2a6b453ba495cf0b351168f351ffe221462dc956bb895c81992e53e51947ddfff1ba67","nonce":"6a53e3f0f466698a5cd7f07d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"8f70c814a71b8dee567f23885d42ac70718888f9ff942c2279aaad5bc3bbb07b268633fe819fc1a508dee74147","nonce":"6a53e3f0f466698a5cd7f042","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"bfa288b19696a64226080cca2e8396c6e29bb4e848c44b7b237c30f8e057f22843105d4272f4637d3b01e5708e","nonce":"6a53e3f0f466698a5cd7f043","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"bacf171e9d5cc82e71884b98ca112215910d9ae4b228b5f0dffb380e4608f50a6a72bb7df52f4560cd5b73f72d","nonce":"6a53e3f0f466698a5cd7f040","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"1fd4cde7c2c311550c4f7284663c4e5f72cef32f6896bc1120024924d45fba19d5a75c014edd01b11c6f9a19a5","nonce":"6a53e3f0f466698a5cd7f041","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"55c8f8d51a9393f9e94e7a65f6844bafb7779b8ce6e3a8fca5676c8e95169f338ba6fc50a3cdb9e377a95d8cf0","nonce":"6a53e3f0f466698a5cd7f046","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"b521fa0f452e0131b1bb6c50f546275417d6fbb89fe0842fc81d4aece0d44e3e1ccabbf22c15c899a11d1fad22","nonce":"6a53e3f0f466698a5cd7f047","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"3720bf8ca1328ee7a4bc8d4cbeabea17ab28990cb743822b91a95fcb036dcfaa3f5d28c3ba834bc2817e3921fc","nonce":"6a53e3f0f466698a5cd7f044","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"88fb2051636faf8bf458895fe225ad1f4dc0da205c38426b31110463229c18cf41d62c1cb6fa20816d7d3fc298","nonce":"6a53e3f0f466698a5cd7f045","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"d0e9c4c9a4fcdfc531c79aad6c467d3ca0c3aec3e63ef726bf677899a03395f0c637b1660f9c4a899931fc0ab5","nonce":"6a53e3f0f466698a5cd7f04a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"545becef8bb5023f50e5ff3295b84756c33691cc337906515a9675fec7902c3f1d393552bdddb6373b44dafaee","nonce":"6a53e3f0f466698a5cd7f04b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"8a13f6a266894c1744c61095750999aededdf0d595cffcecd0dc0f75083292b3f3348b8c5ea4594365a064018c","nonce":"6a53e3f0f466698a5cd7f048","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"e558f56058279327cb166dd9a2d0b3c196b52ad8a1cf2fe0e7201e0375af54daf45286c634bc7381c74e96bf9b","nonce":"6a53e3f0f466698a5cd7f049","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"1d83b3632e086488370a1768bdb6b63bb8ce2416bf9e94add2eb6611e25b3ec65bb58f16afab60e982c6a11fe4","nonce":"6a53e3f0f466698a5cd7f04e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"e1ab63e3d19aa057b3658426298f198329ebdc2b51beb13eef3843abcee9a2d8f604b5c507f39e50d9e94db4e9","nonce":"6a53e3f0f466698a5cd7f04f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"a77ddaa51bd95a44a83608c58f6ab350fba720329be117916b0e8343cc2846bf010a6f531c9849d13dcfdbe7fd","nonce":"6a53e3f0f466698a5cd7f04c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"8dea9d927608eba71798860258f6c5331600928b59056e2c06915b11e2b1bcce2bb4ce16154cd1a426d79a1343","nonce":"6a53e3f0f466698a5cd7f04d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"024e579777a372c906cdf419829361ab45e6e9716f5725d50fc7a3a8c8c6478eb7b4398e1a21810233f186d53f","nonce":"6a53e3f0f466698a5cd7f052","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"639ccafff1e90c272704903a44e73f5f8c57eb8d467e16c805cf6a10c75ffbb8399e5cca0ba41751e6619a8009","nonce":"6a53e3f0f466698a5cd7f053","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"3fd9a96e58e2d3e60cf848921e34ed97b50d1b2339b99a55b1fe7e40b504c56a2fdcdbd555ae65900b6b4c9ff3","nonce":"6a53e3f0f466698a5cd7f050","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"a146b6bcd6640ccbe832f962d027997fa01bd42e9ca56b5ebaa3c7c204dd788585fd6babd1056e392b387ffeca","nonce":"6a53e3f0f466698a5cd7f051","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"86e7e7a519ac80169441db99931dbd4161e3086be0253a30d0b5868981dccf3c5c02b38ef4746191a82aafc2aa","nonce":"6a53e3f0f466698a5cd7f056","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"a0dfafbb4eecd6aa69d4c85a0f4b2a4f4fe2ad2c035f4283f275ae58fee55af47e4798d53883661c9fc7bdfa4f","nonce":"6a53e3f0f466698a5cd7f057","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"55652cb40f90479e13e0bcaca96e0d56b7d592ea1feaac834e02425f77ca67d5f091118822be8491f1a87c46f3","nonce":"6a53e3f0f466698a5cd7f054","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"34af06b9dae8349a9210958744723bd145c9044b5f5cf43772913eba95f78adee4bbb7a6f57b3ccd4de1bde905","nonce":"6a53e3f0f466698a5cd7f055","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"25696168cf052d1969138e2e2fb2e76c1725b7108bf7064679deb599efb55400998f75b446f203cc440a5123a5","nonce":"6a53e3f0f466698a5cd7f05a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"68ab6bd08758c6deac1a2460518d74daec673461fddde06efe3429b07ae47b7ae4aa2e35c51b0c9c87ec81da92","nonce":"6a53e3f0f466698a5cd7f05b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"1131821b14398013390c36e0a7706dae1e3f8930aa07cdd7a01a75661f7b12b2b72570701df4011279f6d8b5e4","nonce":"6a53e3f0f466698a5cd7f058","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"8a9c8906c9c07bda0b969ffba64762fe573fb06bf4b437dda899fe724eaf1b1707ea33122693b361a85a72ccc4","nonce":"6a53e3f0f466698a5cd7f059","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"3679f0acbd088079c6a7424fd198c0c7bb607154443d30246dce279014d9ebdbbb49b2d8222a5f75ca9a3e0d5f","nonce":"6a53e3f0f466698a5cd7f05e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"aafa159c9d81417b1c83d5c5cca07fe0bb5999c5d6e653ffad7f678f5f8842db5e3e3c07a6c7d1ccf2848259c8","nonce":"6a53e3f0f466698a5cd7f05f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"c00f29ee53af666d3f51b335b44e3048dea0890ab253c4c3b1b6bd154fa659b6177f0432447ca9df4151c38488","nonce":"6a53e3f0f466698a5cd7f05c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"10eacc7a58d4593ff697c43ceab76c81dbb173079973a4e0a28553d2dc5b4f2b68f2d3596b38436159e516bd17","nonce":"6a53e3f0f466698a5cd7f05d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"7fb27fbead6ff36123a89145dbe9f184513edba07cde15d231a3d691aac8633f8bc945c08be460ff3fba70cf96","nonce":"6a53e3f0f466698a5cd7f0a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"342c3e1cb69bb4302d98076d4308e87905c1f9994723a9b1f0f2432d0e45e6bd6d2c073d70461beea321da08a1","nonce":"6a53e3f0f466698a5cd7f0a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"8948b7055196bbb5d3c722eeae3eec5498a7b2f3de26885e5e90bdae4e59421bab152a637d2d9a5e13a33b7f3a","nonce":"6a53e3f0f466698a5cd7f0a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"e5c32254b187e3a59573ee30397d951d889b706bdbce3b20fcc334a611a3d1e14a9ebb9f435cedbc26228f9abb","nonce":"6a53e3f0f466698a5cd7f0a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"83376acf65017441dd013d1bfaa17cc718f310ccf3b7d04534dddea9a6afb3e34d2da2ee06275a26d623aba9b4","nonce":"6a53e3f0f466698a5cd7f0a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"9baeb564ff65f19f2f0be68f27308eafac36fe4982daa0cb2e8cef93bc5aee07d9ee8c54c6824ea247618e9ef0","nonce":"6a53e3f0f466698a5cd7f0a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"78b7530f7d8846235067608c7bf5a0dadbdfea3a1ac132826babda30e6ef581e19c3b1abc7152cfea0a2ec4cfd","nonce":"6a53e3f0f466698a5cd7f0a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"73cb54931f4f1e2edccb0921e70f2a985e6e29bb86336e389c5ceb8836c635907156a3157792c5feb8881b02f9","nonce":"6a53e3f0f466698a5cd7f0a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"554c6dd4a4c0650e807ce5ea27c04cfb1093a8594e101194d84a7a308a207dbf70d2e4ed335e31205f2282e6c7","nonce":"6a53e3f0f466698a5cd7f0aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"7265e4b072e70b6f64bb5cad575c008803ea80f6ddc81b627b30582da65d34e772fc463f1b769943e7104ec974","nonce":"6a53e3f0f466698a5cd7f0ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"e1ef83c5ccf9d1cb88222366e9a797fee478f8ff19656784a38090c30fea9fc85f4e8631f5091e30aae296591c","nonce":"6a53e3f0f466698a5cd7f0a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"a5f11aac4ceafd8957a57faac8941574bb7da5a42c42b083d6d206866fe32b5debf658a778c29dd98353af589b","nonce":"6a53e3f0f466698a5cd7f0a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"5f08d494fe2a56413a43ee57ec7593c81f0927b5a5c88719570c1e6b07da3f2a0970411c18fba545e6464beccf","nonce":"6a53e3f0f466698a5cd7f0ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"58288823e3c69be68afc729d633ce34779a145897540759bac99b81db6dafe63e608786bab593348f07248a485","nonce":"6a53e3f0f466698a5cd7f0af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"2a05dfbffba4b8bcbfaddbd79c0aa3a27af5cba01752b94dec27b86d64272381f6d44f10c43fed4e6c076f5759","nonce":"6a53e3f0f466698a5cd7f0ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"7e35d921454fa747738f9fd2bced7d6cb8a913b22532f700cff0e87d75833a6ae53892d57377d3100977a9511f","nonce":"6a53e3f0f466698a5cd7f0ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"8bcfa91b837457b49ba87803cd93577fdf6fdc266fe9cddf227d48873dbb020ac02abc046e79f023ea919ab475","nonce":"6a53e3f0f466698a5cd7f0b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"2d111906fef86a528732e520e53c5a2b00e1fc662b276dfcdcf1e2e365fb72794d95dc2afed7f392266eef4cdf","nonce":"6a53e3f0f466698a5cd7f0b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"3bf6508985c4e6bd7cf4f467da8e8313b4ed0b640b3f2536cf8c6624ea82f5e7f1a38bf2a418c1a608dc056e98","nonce":"6a53e3f0f466698a5cd7f0b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"31652518a74ef69cbb96351f0ef0b197801608592f96d9bb00038cb925ad59d40bb626e55fd2cb4b99d234105b","nonce":"6a53e3f0f466698a5cd7f0b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"34c44d7e832be8f5548c6f63bba3097192e03ccf565194b5ef2fc7cbe9dda75015d37b1169723ebee15f912fea","nonce":"6a53e3f0f466698a5cd7f0b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"7ed135114efa2f744355a56fa2339a1914fbe88a2a33d28fb13eb1faf7775a95199fbe75aad01de2a8e5b91c5d","nonce":"6a53e3f0f466698a5cd7f0b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"d20c5f18fabf963db5da7344e33bbb969b20da2c1bdedfe4c0806ddf032c6164e3ab5081957d9a8cda72694c32","nonce":"6a53e3f0f466698a5cd7f0b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"bd3e7fd25e756d5aed05daa6260831c56e60b1bc4ef6db2cbf291d0082411bfd2dd39e7c912bc042d6d9e2209b","nonce":"6a53e3f0f466698a5cd7f0b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"7b3f148a8c4fdbbec17941eec72b338fa1aefc8259238a492a9c259552e3135be9316773d9dbe9faeafb412af3","nonce":"6a53e3f0f466698a5cd7f0ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"456bd3449704b86388fbbe29685b79ba3d4892fa630e30c8dbfc095b075f8e7e6571246ae2e42cb03861b51b3e","nonce":"6a53e3f0f466698a5cd7f0bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"18aff0558dd855b07c2b778a3547ed41c3502a0f06abf384e53f4400d6deeff5552686232cd7408b34cf24e7cc","nonce":"6a53e3f0f466698a5cd7f0b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"fe85936009e808f7efa873a3fba8f8575ea3591d72feb12b51faf2af079317b26f75f32ff1117aeb07b96779f6","nonce":"6a53e3f0f466698a5cd7f0b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"a3876c676e89c13b33fcf2d0c708f897e52a7b25722004dda8d67f67093030348913d3cdd5bc58f02fb32d24d1","nonce":"6a53e3f0f466698a5cd7f0be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"c01c519514093e672bb799dbc5f20541a387cef572cad5dbef8d6de29df7409713aec4594fa1fa01bae15c0ef5","nonce":"6a53e3f0f466698a5cd7f0bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"0ee438debdd35b5487b95c9fc3c3b9f167f9fa9f4849a5b95b1d4d00ff94bcf1a3b31b6484142370e6172f2cf3","nonce":"6a53e3f0f466698a5cd7f0bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"8142447f83b95bd0f741e86bf17716f034322886870145dbe2ab71a92e1d1182c7be0a26a54b9d14bcc7b305d7","nonce":"6a53e3f0f466698a5cd7f0bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"adff8e7d58260cf79c37f16d7e6e0987531d864ce5578f2dd7fa16263786deebd457e767015cec7955636e5775","nonce":"6a53e3f0f466698a5cd7f082","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"ea2ec307a49120e5e45bc480485dfe656a2baf75f904ca5b1f3991c88c1aeac2d2e9118e7688e92770b9bb2453","nonce":"6a53e3f0f466698a5cd7f083","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"d9b4ab798d948fe0d535e72e769398f094ea2fb2da4118ee48e92baa7cd10c8b73c28100f7928a7f69ab0d48bc","nonce":"6a53e3f0f466698a5cd7f080","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"b84c66816f68294376ad221d3df351ed73d5085df4130b01ae53d46593ce0a8514648412cc36d14226fa560fa9","nonce":"6a53e3f0f466698a5cd7f081","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"82accebc012e0e103291edd09cf6291de9e12b9aa08f3cf795458118874c8974f1ff4e3a17f31a9e856ac12662","nonce":"6a53e3f0f466698a5cd7f086","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"1623e083cbeb5781825402ca1e6c5065a2a5711769d9476bbb651672f5e039537ad19c919f84dcd4dee9f5bcaa","nonce":"6a53e3f0f466698a5cd7f087","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"cb2f2c6a94dfdd83e7f5a54d921936d19f5cbd849d634dd50abeaa68ba1c2308721afdc2515477a9458a113df5","nonce":"6a53e3f0f466698a5cd7f084","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"6cf2d0358c298ad79ba892afd9a9704d1cc83490ad8e7862c959274eac7a4ad766963cc46482d6b9aa3e5faf8f","nonce":"6a53e3f0f466698a5cd7f085","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"ce09f4d2985f3a8fe9bed163011cb02e03f4aa610c358c407402e2570e5965d4eb7599c14b3eb8f3e8af3634f0","nonce":"6a53e3f0f466698a5cd7f08a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"dc62d5bddfc557597fa0c09858650d34073518f39059076f5014b6bad0a7b40ad95735626c6c2e15eb78337294","nonce":"6a53e3f0f466698a5cd7f08b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"002f3700410af466754c3888005bd503a385a5decbaa43eade12f820991fdb6eda57dfe0ae6ad63073cf13d40a","nonce":"6a53e3f0f466698a5cd7f088","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"952125876b57bd7534c73487d6450e98037df024beaa30e18d0f1f1a77715689039639c31dc318f8e2d1b2e00f","nonce":"6a53e3f0f466698a5cd7f089","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"575883d3c56bc14e0f1d4e399e9af5e0378a23454f2c89fc736407ace01f7fdab8e3d9731858eca1a3640305b6","nonce":"6a53e3f0f466698a5cd7f08e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"ea5488c6079e0bc1e675a1516bacb54430f3a66b570c74d4c9778a7ce615492dda89f28516f79da8706c5dc16f","nonce":"6a53e3f0f466698a5cd7f08f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"6ff70dae0cffbe36fa4d2d278b92129abd8797104976cbc3cee68caf77636ec8504a8c60f1f6e0d5dcb8beebf7","nonce":"6a53e3f0f466698a5cd7f08c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"ab36aac7b49787fb447fe0d553acfbc91ba24ee9122be583253145f494ce90afeae07df7cd969c63d50758bca9","nonce":"6a53e3f0f466698a5cd7f08d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"d9a5f27e48d0d158ee3219a5f2fe57221262efad4ca8e778d392a5f1f08810855f1eebf1465230210a596bfbb7","nonce":"6a53e3f0f466698a5cd7f092","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"cfbe30d73214b6867658dfad16a13abe5bf561838bcb46714e81c395d7a38bb5d368af48a55d5e7ac57170adbb","nonce":"6a53e3f0f466698a5cd7f093","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"16aa8b4f7414c31be0ecff8fd6866af88a201887e8cde6d70dd0c0f9c95d52e6a27230d4b4f2b542ede944bc96","nonce":"6a53e3f0f466698a5cd7f090","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"61886f7598d1c935a5048581ec2a99dbd18b11ce4c395eae57725a5e0700f8bbc0f0058609cb141c59aaa78d66","nonce":"6a53e3f0f466698a5cd7f091","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"edf327d2127ea7cdad1baea018e6c5e93f730f4a8227a2d8ce96cab8bc79b6a757ba0e45acd0e93db2b9f8130a","nonce":"6a53e3f0f466698a5cd7f096","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"f865ed43c7112e2b94771eeb9a91fea10e7c7aeabe0154008a53f24a3e40c3606351efc46ac348b5c08b3947a0","nonce":"6a53e3f0f466698a5cd7f097","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"1f9e0691a25138620a8319a50291fbc63ecf8d89336a8b59cd5323198d525a3f6cb865eb4d71934cca919d0113","nonce":"6a53e3f0f466698a5cd7f094","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"c68018e16f8925780612516892180d7d4f69bd91957326de436db0cf2bb237fa9e2b0ce6a59d1bba50e9b6cb47","nonce":"6a53e3f0f466698a5cd7f095","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"42c2b037e518294bc31856d75fd497afce8a669df65cef1600693e9f104c06071904482c447e016adff0f1ab24","nonce":"6a53e3f0f466698a5cd7f09a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"dd9b184f701184b4e9ed50973625d50247c1346264cfb1a91eb3ecac15242bb5491a7ed8e6bcdedede2fcf86ce","nonce":"6a53e3f0f466698a5cd7f09b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"beb1870c213cdef12e80eaf9c116efc4a61bc90667af4a125f9949ba1107258760c62249b565e5b1edfbf348c6","nonce":"6a53e3f0f466698a5cd7f098","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"1d16ce7a715a3136695c20d56c415647b4a96515ffab60fe75a0e4c47f3a99f7b308235a777813120d88565e85","nonce":"6a53e3f0f466698a5cd7f099","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"7cb27c5c8a344422dc8345c7d6c59bba0d791bd37fd5dd03d74e933596f7ab52f774c28feebd2f3430c68d1633","nonce":"6a53e3f0f466698a5cd7f09e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"5da19ed365de614b8bcaffc298df2b90995b4f9db3ba05d729a36a419ec7b902cbeeb3b48b3e8a6b925bdf85f9","nonce":"6a53e3f0f466698a5cd7f09f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"735817587f1025126d524d048320643e9c0af5b190af3d755be367bc9981f17218b3eff4d0a9b9aa0dd02424cf","nonce":"6a53e3f0f466698a5cd7f09c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"9b51026d1f9d70631dbbae981d7df660782aba2987461d0c458ea1ebf538c8dedbf4aed96c6424d038e2ab01a6","nonce":"6a53e3f0f466698a5cd7f09d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"2fae25477691cac1ec218ae5d628a338f1839765e4a0cef26155b1c26fb2e64b5c8df40d9c59b1cef764418e74","nonce":"6a53e3f0f466698a5cd7f0e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"89b360d0d3f8e7fc9c46864c3fb0c346db6819b665a1d5b6d7dbddcf7b142651323abcdc0ad1bb7a0e62a873c2","nonce":"6a53e3f0f466698a5cd7f0e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"42a0e8d6b3c7b89670cbc33afa42c2a916fe808c25eb9fa8b75ef2249a92199ea6ebea3a121a6d70ee9e2772b7","nonce":"6a53e3f0f466698a5cd7f0e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"3a648b900780f160a4c3bd3fbee2e436070fe6b05309f15f9cd6713eeaf5702a9b193c307aa7e16ff10b94ee16","nonce":"6a53e3f0f466698a5cd7f0e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"97702eefad45d83f6f8cf4c21a28c65e2877e7b2f46350cb426d877dae8c56330314ef71920ad7469b8ee8c340","nonce":"6a53e3f0f466698a5cd7f0e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"645c08289c594d75859ac71a324d1e3ccc311928884ea18dca3627fbdeaa2c3825de3f85bd59d211a495e6253e","nonce":"6a53e3f0f466698a5cd7f0e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"85f2d3ed19d9d4580fc9bf537d2ea8606a8ef51cc7f7d1d09b888743b2c18125c67571953736445018ca1f5993","nonce":"6a53e3f0f466698a5cd7f0e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"3f6727708b3a37b8eb9e59c30e3bc22b86a883843beaa9a0f4aa9f21b05540b01c26847342be769fdda42b0b2a","nonce":"6a53e3f0f466698a5cd7f0e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"032d8ed9ab25f574a6be952b07a1b92e7dd2ec86719f1f7bdc96df4db7b1aa0d2fa79c0c3dc13f29eb20e2dc43","nonce":"6a53e3f0f466698a5cd7f0ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"b82afa7ffad9c52575b2e5a89ea19c5e4b42730a8b4007af0a78e20fa57586336b2f4cfbd3322084e26569c12c","nonce":"6a53e3f0f466698a5cd7f0eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"ee669f66fb2ea60ae2687801401a882fee5548f7e1cca7e295b64954d19f75e1a78cdab48e0fc76a7e8418c3a0","nonce":"6a53e3f0f466698a5cd7f0e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"8aec2f7de40050d08b70ab3d2821e17d7c90bd7433b2607f5dc9621aa082333b1d2be23fefc7271624d9eb73d8","nonce":"6a53e3f0f466698a5cd7f0e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"405bd2c06b3fe4d31b09e905c0a1cfedda974f77f73a365f431a7f6359b49648c48de76c6c597a47c7c5467dc8","nonce":"6a53e3f0f466698a5cd7f0ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"4224857983b13e48ab519d3930eb6589e5528ff3fa174bebe1a5c5fc497b5b7347c41b3a8d12416307d755f382","nonce":"6a53e3f0f466698a5cd7f0ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"a0bdf8b5da71f22167d1ea686b69ef87e365671e61e68e8d709ef3a665a9a784ed7a8dc235bdbbaccc7868ea93","nonce":"6a53e3f0f466698a5cd7f0ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"214e285f7da886540458113222032138547f50e91bdb867da3b3990589340e7c39c3d39173fa13efd4c5b732bd","nonce":"6a53e3f0f466698a5cd7f0ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"d39c2cdb2ae4a39c065662ea8d605bf6ad4628dae5726f1f6c2d33e8f1d87d0ccf865994a6ddaf295bdbdb9f68","nonce":"6a53e3f0f466698a5cd7f0f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"40b4cb15d584eb4d742f07242d861ed8569c8d35dd75d81362097d76fe131da3bf494c952ba27e94e7caa8d7b6","nonce":"6a53e3f0f466698a5cd7f0f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"341a015d57926488e7be4563cc4c3fddd678e4d2cac0c2dce013ba5654346820d90acdc16488682e63c2f06537","nonce":"6a53e3f0f466698a5cd7f0f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"6efe3ca311668360cc17f96dc6e88008266ec73039d5c7ef1b6850e2ae0437d88cf98236c35eaf3f1977d03851","nonce":"6a53e3f0f466698a5cd7f0f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"21b32deec98d3b6e7ade323def6bd010280ff883211be4f0edeed18700a9b0af264d45ddf430ade8c142ab7b8e","nonce":"6a53e3f0f466698a5cd7f0f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"45e72400362d9bf76c9b179d0d7f397f39c9b7a95ed5b0d62606e273e722fee2a3d85966211f2ece22789eca33","nonce":"6a53e3f0f466698a5cd7f0f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"eafd93ecc1eeef78d203b7113c037ba47904083ce6e724c00bc3ba5389aa1b0d7639808f7cf607791318bf029c","nonce":"6a53e3f0f466698a5cd7f0f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"7f91f813aa251d67e3262398638078a3ad039d7228ec0daaa5fb52bd3279f284599e4f3d2d85d63c8b870e18bd","nonce":"6a53e3f0f466698a5cd7f0f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"091ddb9a0a0df51242ae98866d0aee7d4260641c987f3d6118d965200c92ff1b4f2dda8e4f682cc44eb3f292f8","nonce":"6a53e3f0f466698a5cd7f0fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"3720d09f389511d95f781652b03da7aaf28e8c9d09503ac841ae4d5785cd332aeb61eadedb5811a739e3edafff","nonce":"6a53e3f0f466698a5cd7f0fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"c309c748e7009a0202ad1d7c63285af6190329b514e415cae1d5d2aaa631de1f1ea9e9f8fd56c010a2353fa66f","nonce":"6a53e3f0f466698a5cd7f0f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"3502ce0099b697b18cdfb62324e81ac02d287a3fb60b79641bbb37c559601ca43578505615358ba4dd83bbd826","nonce":"6a53e3f0f466698a5cd7f0f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"eb4b8743e714778a05a36dfbd00be3856b940ca07438d565b8d62bc952e93853be407bbf26ab2ffdd268472cc5","nonce":"6a53e3f0f466698a5cd7f0fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"53c336297b9e1d716a4e45fbbf4e79db2da504486701ace7c14151a33a433fd30ef51e867340fced6178fae396","nonce":"6a53e3f0f466698a5cd7f0ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"3e2ae045287cb2aebd8389b4d8006b5d34f72ae8168db9fd1617465bffab196ccacd8101ed18043b93c5f007d9","nonce":"6a53e3f0f466698a5cd7f0fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"b798d03f7b01b0e92e3a6df41581dfb3c9710ed8f1d47cecfe1865729beed0d8cad919950f4f14beef0ed00da9","nonce":"6a53e3f0f466698a5cd7f0fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"dbc2179479f3e0893207b74b333f3fa7f8e71fb388448335625a418cbb3e4062009763fd23fcd6aedc924de608","nonce":"6a53e3f0f466698a5cd7f0c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"b22945e1fc29ac9d3098b8369619b3746b72195d1cf17e8aadd6a814cfc214e950fd01cf543bbfcd30345ca27c","nonce":"6a53e3f0f466698a5cd7f0c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"8420485cb868665e8a89ca0c7ce4336cc901223e77ba29bca6f542d3b6b38c10e698a0b393418d5dcf489f4754","nonce":"6a53e3f0f466698a5cd7f0c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"02fc366d79004776ac99e8f4bdf44cc2b967fd84eaba6de970643ee380eb5a967a18a1a431e70ccae93cf8574e","nonce":"6a53e3f0f466698a5cd7f0c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"9a086f1aa09ac6bf33a894febd0c783a88b6ac5585fc2b11e792fcfac59661493a69a39ecd50b14244f1cee096","nonce":"6a53e3f0f466698a5cd7f0c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"7c60ae0a5310b64c8ce79b3d86c9a73103c6018b0a70d0b602973f26c5dfad82176025e4eb3427da575fb64703","nonce":"6a53e3f0f466698a5cd7f0c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"27081fea22a9901930a2b93a537d170d134f65aa950a2d4352e050adf85422dfc2277172fbd5807e599e34850f","nonce":"6a53e3f0f466698a5cd7f0c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"6e8d354429009bcb98da5a024f63d717820c5533557f8f753aae899c297d86e925b2fb83a5634ff4eacc6dcb3d","nonce":"6a53e3f0f466698a5cd7f0c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"55b51c8b6e5be51be0afb8207bfb923d1daec14e73d89a79e1be2bcea63c5477333e5bf643a601e4a4b775bd96","nonce":"6a53e3f0f466698a5cd7f0ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"6e8a687203647480d2afbf2ae3d6dd9dbab4e95ee8eb54236c5e7f5d2b719d08b922d380383f946cd03d08d4db","nonce":"6a53e3f0f466698a5cd7f0cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"f3cc4d5c7ea4737c88cd0b62b80044b094a480265251f84ff0c40a075bbac874b58d4ff58eaf3e216b88e7bc9b","nonce":"6a53e3f0f466698a5cd7f0c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"f4d43d385d3c0c761afb056415a67c855982dea6e152cf2f304e3c28dfbc3931b3904a8d9b6b7f5b0f378e0f9f","nonce":"6a53e3f0f466698a5cd7f0c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"bf3ce5194daed80a780c3bfe41e7abedc8698a0d4c702eff91644227d9f1f892e69720aaa7ee0fdb246347f6c8","nonce":"6a53e3f0f466698a5cd7f0ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"e0eb7d3d34eff1ac992a47cf0dd46f9d8f512617118d876d7acf321d31f1e43fa34c139397f38ad1342defd286","nonce":"6a53e3f0f466698a5cd7f0cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"7a9d6a678cb8ec06ba66d28d1084d0c3b5e095e0423a0999548bcbb25f3d7365178e33ae3bdabf3f51a20d0835","nonce":"6a53e3f0f466698a5cd7f0cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"af89561f817621a589ee12867b2a4b36254f3ba5878b57a8c5e2c50b1fa7272959e24193087442d17442c7ab82","nonce":"6a53e3f0f466698a5cd7f0cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"9e2c0f0cbbc290652256d3235401e0820e06745398bae30b77f42b4bcd547425336779b0e24db42821da84eef8","nonce":"6a53e3f0f466698a5cd7f0d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"dd898456134e5de957997d03db13e292a6865a103520e233e298c093553f8d55a13df785202659728ee39eed67","nonce":"6a53e3f0f466698a5cd7f0d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"d174c686a8973d0109364690f970aee4d8c1925f9cc7a98fe07d8b7d3d868bd35d7d9fa9605a9241d2a62e40fd","nonce":"6a53e3f0f466698a5cd7f0d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"1fded3bc4b650d9d9d65edf46350283de6b40f650b95d9d0ec45426ef23f6dfb2c6be2bd4f536bbea13c9c630a","nonce":"6a53e3f0f466698a5cd7f0d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"c7d4b17e2a81e062a8001c2be2b514de343e341541a2977e838d11c6d0440655c4d7d67f995aaf87d523a8a170","nonce":"6a53e3f0f466698a5cd7f0d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"01aad46a179cc40e95ef09ecb03ac064e349d46b7f84cca8a82a863cd05fbd3a1ecac5e8184d7e1760983b1aa9","nonce":"6a53e3f0f466698a5cd7f0d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"c87491ed8b16279cab94ae18c82f080320f2fab6206b195035591d9e08c76e726c97ab9b36abb5c88591ab6b6a","nonce":"6a53e3f0f466698a5cd7f0d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"f638c2d173bff021426c053558a3f09df7b14315412470761e3f094e8a2be7d8ffec29b17577230dd60f6c23c4","nonce":"6a53e3f0f466698a5cd7f0d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"3904c75f2180b39611589067637c9c31bbe5bd566874100ccedea7b135f55986bcf590dc8ae33e8fe06bc542bf","nonce":"6a53e3f0f466698a5cd7f0da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"1364cb50e3412b09f975d1aaa645c864fb2ae5ed295e013351bc5c4898ff9f7979c9958d1cf93dc3f790855ad2","nonce":"6a53e3f0f466698a5cd7f0db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"73b9840a788a0997919851bfdf8e7755da03b3af4dd3745fcd699d314122e8162e9ca07e367c22604153885cf9","nonce":"6a53e3f0f466698a5cd7f0d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"5b1d29c6dd7557248d1f7e3801345c271b9c28eb9961dee46671152e324ea00292bbd423a1c6f39ddd5b7cecff","nonce":"6a53e3f0f466698a5cd7f0d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"65da75769a61a66dd86d059104e41163bf014fb8f39fe3b889c4fedc8b64b1fccdce5f6da25a57b660e700f1ad","nonce":"6a53e3f0f466698a5cd7f0de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"a04c919a59c92cc202db4ce846b644ecf2c979e241262309bd2d457a33927ada4c5a316968291b2f8ba17d9b49","nonce":"6a53e3f0f466698a5cd7f0df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"860d38abe6b97d5c7b1a02a91851da5b5eef22e63d1a9f3878b965835077bd1e1fe9af0ec60710b80955e3a3e4","nonce":"6a53e3f0f466698a5cd7f0dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"8350e267149ef97b60389daf476c06818b1691b434a1f02ac5e2fb3d3328e1791875e3472c2976909c4874d1bc","nonce":"6a53e3f0f466698a5cd7f0dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"bfcf9b0f30c3fc9d8fb1a44e3be5342280c1a6d0853eb8665a407635863c01cef4a7888e6088238a78b9894ebf","nonce":"6a53e3f0f466698a5cd7f122","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"9aeb03e31d400170d13f5c55bfd5be884e4fe7d42e3a47b3a79cb9624e0c1992"},{"exporter_context":"00","L":32,"exported_value":"336d90ed950b618de0f878aa0c0609b0d842b23b2258d6eaebcad0f1780d2174"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"11f4e59e9112daa35c72db1c6d8e19334e479b102109b25c8c73bd7a4b113c6d"}]},{"mode":0,"kem_id":32,"kdf_id":3,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"fba4464f214b0b5763184f968126de470801c5585bc6ace73f582213d2141617","ikmE":"0943d46a99dc52d52ecaa852041a90cff9584f2c68f1aa950ae06534982c86b3","skRm":"08d639c8779d7c27f5fc942b6e0325527349f412649ad2ba304267e2911a713d","skEm":"15fa8d44bec5c59192cb9df3abd9240d2494c864953d8db8465b6d58abeb5ac2","pkRm":"bc91b4c9e6243eeda359b30e0e216894cfb588ac16d07c45a0f58208f7678f7c","pkEm":"ddea6a6ee697b5ca6f0354fa8d7c1410dc74cbd49b26d80fa9bfff8a274b3872","enc":"ddea6a6ee697b5ca6f0354fa8d7c1410dc74cbd49b26d80fa9bfff8a274b3872","shared_secret":"0970b362d2cc9c00ff1bfe6786bd3e6a92f6b30586cd3587627d91e8252cdac2","key_schedule_context":"00018d129f34a145043cba6146e7e397593164fb1e78e512e6f36be621c56f9f7023a14f35e95577ec3f6714ee332f48e829fc2ec336e71b204f5958b7067f47756f17ad5b0cda65d91049ff137dc5111687e0d4d44123d94cf2ad7b71ecb5fab6cdf8e044519fe1ecf7cffb6a3f3bfbaf6babfebe5d30a92e166f52849e8d35a3","secret":"a2507452b304e94e6c70a9b077d5bf41c732ea1d55a9934f2deb63280b1654d323478b97ad4d2be5231d3341aaea436343c6f484f74edd94374079dac47d58d5","key":"7eb78183c95522778320a704f670f425","base_nonce":"f28f1595dd021db843d5437e","exporter_secret":"3e20633d316f111c1e6a00b2e2a47948b93679d100c745cee74b9b33ec607245a56e7d5a4155ecefa7fb82c534ce60a7ab28483fa178eee8a7ecbe654b0f63a8","encryptions":[{"aad":"436f756e742d30","ciphertext":"5554d7be09317703ecf2bb2879c6fa8ef6050c47fff8c1435ac9cc382425e79c5fb56a7eecc324b96ed01e1219","nonce":"f28f1595dd021db843d5437e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"f856b6038e0f5e57711636e85a52cacdca51194b156f682a9b57369fd8e8ac9ed1c4860492ec01f756ec41fd9b","nonce":"f28f1595dd021db843d5437f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"f45f1e6ab50228f600fd59f27f7278aad38c9c0582438d0efd05d8fce15103436d0f263943aaee189228ac285e","nonce":"f28f1595dd021db843d5437c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"d62955630d201d44b5ef6f1bc571ba94c1ee12e0c0b91aba9b3c629cf3924164d943c0fec778d55d497e1045de","nonce":"f28f1595dd021db843d5437d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"8094f394b8f08a446e7284b1ac389a50233ca274e6518acf9a1158d19011ef5fe0f3b6c4f79a051002ae7d5fae","nonce":"f28f1595dd021db843d5437a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"6611082e8bc4881a4d2be309fd828ac48c3b1a6f416eb4dffbf0e2f7a06b76dc6c3066a2e622db924bea42b0af","nonce":"f28f1595dd021db843d5437b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"26890a33798621c896abce418e27ccca6bbcde6f941e84b80b5d525d05f633b763d53ede6c5481289c52a86ef9","nonce":"f28f1595dd021db843d54378","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"6c1fc1ffec38c47902dfc08365e212a0c9e01f3cdc36ef950674e537b889da6c9ac39c1d67f62ea2598845d23c","nonce":"f28f1595dd021db843d54379","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"8c3648fdce001df2e0440044920dec321145be6630643892b971ba1854ad6b2671d74be3307e9033b73ddf119d","nonce":"f28f1595dd021db843d54376","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"09097a76741bd8fc4dcee4b4575213a98061344c1f9d40e011e0076fa85ad8e1b7947e12f051e50dd0987ca78c","nonce":"f28f1595dd021db843d54377","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"336591a47610a280c3c1a96e7de1b602a4e251c586a1a2f445704e519c839693280bc1391a81b744232d5da76b","nonce":"f28f1595dd021db843d54374","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"d00c1b96825a95db7bd1339d3030c0723b75ea631e6d0741cbe2f02f521b263ea277321a38941ac0f9fa8edc55","nonce":"f28f1595dd021db843d54375","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"2ff5fc8662a5b6b23dfefa90a7769cb5971f20cfecca2e3098a4ef160b313b6fe5193278dc710e48bc1c7cf39e","nonce":"f28f1595dd021db843d54372","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"2c06b04b109e4b08136aeba0c60e51d3aba3d79d6f252784830f8b2e7d16abdf07299f7b8096fe1a9198679c15","nonce":"f28f1595dd021db843d54373","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"0c31a9f85cd34815627461fc7536cf51cb5e53eac05b58210214d3c7f5d3f7bd9c7ba8a10f1e3f1f8a7c90e1c2","nonce":"f28f1595dd021db843d54370","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"c46814866bc612bef3edd7f3974e95958e2a7da89802d11e30367e200fbdf150d8f15394f9cb9769e2961a45f7","nonce":"f28f1595dd021db843d54371","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"a6cd61ecfe99a76655cb97b024691b712fa0946e936bab4989e81d70ed6f0d339a52c038561a0f0e9859a8945a","nonce":"f28f1595dd021db843d5436e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"02ce86b7ddc3aab0dda8bc966705a9f9add1b26170df82d7c421750dc1d8738cc560f0ab24ec9bcbcd68c3c9c9","nonce":"f28f1595dd021db843d5436f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"ebfe7f907bcaef4aedafefe8c03861213653f5063c6f8d96b1a270f08ca8b815e3ad8ec4b04416261a053b667c","nonce":"f28f1595dd021db843d5436c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"5a2d942ad53fde7a5bbf5d76c51197ff210f7357ecbb5532e3471d0f7ab954300920cd78af3d1e1cdf1fbcd51b","nonce":"f28f1595dd021db843d5436d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"a9763d8b10e25dbe542e9b4c295e1bef6527373f174923b8770188261c552d98c8655854594c18ef424f91d8b1","nonce":"f28f1595dd021db843d5436a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"5d0ff88b5500f073e0e590cc5eec958436c06dd25d7985afcfc66e2a8067c851e30e5a775637bf35c1d1f3db72","nonce":"f28f1595dd021db843d5436b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"34d841a4e8f3de57b0c719258b8f7fddce78fe74597f77d9e251f463110b3c24845f9a11a7a9bb43537a952d74","nonce":"f28f1595dd021db843d54368","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"5787768e5e54f84ce9b828389dcdac8c17874fbaf93152ebfdec9018e4b2935743604e2b76ba18f5c97f2f0db5","nonce":"f28f1595dd021db843d54369","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"7ae1a711d4ad3ba4e3f3a15a71d4dcdfb88e6651e2294c13e4e60bc732fc5a90a705beedc511a6ea87b352c95b","nonce":"f28f1595dd021db843d54366","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"e9a17d7027f0913c4eaab3b69c4b391188a200cb47fa7ee504e04ba6f56d9b3dc08ece0ee40fc814317535f49e","nonce":"f28f1595dd021db843d54367","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"e4ffb052809004ef5182eaba6e04dced7031bbea923dda26461902778964f6ad55938eefe575690f4f0d391cb0","nonce":"f28f1595dd021db843d54364","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"00004471a71d60ca5d793592825c6fedda583a2302d5039b7568ec98ffc99ee751b666a30edca030cff5ebf6d0","nonce":"f28f1595dd021db843d54365","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"ef84677286fbdf664561497697394a517ac216a30324f76a51392bcd5e692a68e6b7361491b4c03ca5d06d17c4","nonce":"f28f1595dd021db843d54362","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"4a29fc85c6d8e05c31c7279e3b65b4a117d45a9a6089ffeb21c75b8fbbcdf72ee83bc158a7d36275593203f0ac","nonce":"f28f1595dd021db843d54363","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"cb2a5ae00b588f9573dab6a6c0ee3418cd7f485ba1a8747e162e2aac6df8936b900e78fcedb347e900f1a075cd","nonce":"f28f1595dd021db843d54360","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"4cec3ce1ef454fc35697cf2fe6883ff084150fbaa4fc41d27cc4e50d367ecdab35dbd408f97c413975e894cfe9","nonce":"f28f1595dd021db843d54361","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"9ce90f01d099382e9995e5561cf3914bf61b90edf38eac8445900fc6c711809d1530ce1fe22c10411f427c122a","nonce":"f28f1595dd021db843d5435e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"23e2a8194a0d2924bb97b21f76fc913167ef3c6534541886c21b38b4c5809341144cf6252688d540168d44b891","nonce":"f28f1595dd021db843d5435f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"9584a3c5f9711fe1026cbac3ef482649b6bdecdf720142f5bac30ce9396ec1d7211c1295e3b7908580b8563e6c","nonce":"f28f1595dd021db843d5435c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"e9f16900ee34142c3457e3cb429c0d5d80ebc8b62d9fa6bcdc8271022d920d004e0dd4770f66681bdfe4b6461a","nonce":"f28f1595dd021db843d5435d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"52aef8fc2b8771faa4bb79e87c614ace5e07ff67ae71f5983dd548d5b56a9004d72283a3ecd54f6ae1b37beb11","nonce":"f28f1595dd021db843d5435a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"35a112112cfee70867e9ef61881ca15a400178edb3af5858a026da1d3df10bc015b38b780aec28c7933219f0c2","nonce":"f28f1595dd021db843d5435b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"d111738391b680fd7c2333f4d6865481d853203168c2a7776491901345825ac8d4a68a602f885f031efbf92165","nonce":"f28f1595dd021db843d54358","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"5438f5ff71d218a8ee2b730b242ea2d97d932a29116848a0d60c9e29277e93ae441066794f562a7fd93bf71139","nonce":"f28f1595dd021db843d54359","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"59d5272d9e958db9c28dc454a764be255d10d2e46c702726707d53646ef1fa242dba54ee7c17eda81a3a64b2c7","nonce":"f28f1595dd021db843d54356","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"24e89927c6166158733aa87f6990d2add4bf7467d7cac0c44462b25289915c1a93446ae073fdd69032e256be8c","nonce":"f28f1595dd021db843d54357","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"536d5ee43cf9616b08ea885218ed51513c5e411337750f8b456e7e76bd1b60162a1b91d8b091423bac7415429c","nonce":"f28f1595dd021db843d54354","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"e8bfe1c386bbd568bdaf9a93fd04a0bd68183984b1ae383d9a1014bd8ef13cbb92fc2fcf452f9474db4bb50d8d","nonce":"f28f1595dd021db843d54355","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"2bfbb426648c1ed63ecf0b5f9be42b7ad134022e9fefe32ebdebf6fb17f3225eabe486a19063b63cb43a19056c","nonce":"f28f1595dd021db843d54352","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"09591ebc7acecff90947116c7c4b5682e9f02676e0e7f5421e5c0ae8b172ffc28f7f76a59f030b677b9cd383e7","nonce":"f28f1595dd021db843d54353","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"8467270b38bf93f087d57d83777e76ee117469676aec7455386887c962bc769a36ebd74ec76c642bda4aa76c70","nonce":"f28f1595dd021db843d54350","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"9a5d20cb196cecfade98806589c8601442969515001eb25bb0b95efb062195247440d2479bc9043947c8dbcfd7","nonce":"f28f1595dd021db843d54351","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"c948dc2104dc5294108f59333be059ffff56962c74976f1bc4155b0720dd925850f25fd4a3df1e14a0e6ebfe4d","nonce":"f28f1595dd021db843d5434e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"8efe2b85cdf848df31fdc24ce3f839746858b69bb1367fd018c8aeec6a1859ce297d34cd0ac2f083579e68da64","nonce":"f28f1595dd021db843d5434f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"2ee8387c5347e863adf920639c8b719d08ad48f00534cad8167eb7c924671e95add991c5cae52ebe1e849590cb","nonce":"f28f1595dd021db843d5434c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"6848289f01310b26e1db9ab2a8bff409ccc689e812b0441f0e1df01842f43b51f1b95b22bd3736575f301f28c8","nonce":"f28f1595dd021db843d5434d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"af45493fa737608c8716ac40c6a132a98efb517808a5f88659796e96a5f5994bc56a298c30ed6d318821c7de23","nonce":"f28f1595dd021db843d5434a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"0c01e2a2947c6164cf9691631dd1c9a338d3b6945841ee22eb42b72861ee18f706fd174b336dbbbf4571ebdb82","nonce":"f28f1595dd021db843d5434b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"116aae15ff44e6643d3f0c0ccfed3b4bfd3c49c4be1de0dd1160fd638a629db3b417ce4d7612d427a0fad3407e","nonce":"f28f1595dd021db843d54348","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"9c499e4a7c13783eb1e59c7bf13a4017da3f73591d475196c872c1ba02168c2432fa5bad3103ce736096f8d8e3","nonce":"f28f1595dd021db843d54349","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"120733f6dc9e530ab4692fcd685df87c39654d0dab7dcd8864d0e6958c1d588d8fb15b97a6af7b64516b525330","nonce":"f28f1595dd021db843d54346","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"5ff0b3f886b63e540667232aafc3d69499832e85ddc136c72decd37f441abd184e681afd0085febe7dfc41a497","nonce":"f28f1595dd021db843d54347","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"b3a583e16db0be1428d1a5deaa83ead617d8011a40c475b136e22c4929416cf5a0dd61ad643c533eaec05f2534","nonce":"f28f1595dd021db843d54344","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"e4f51cf948b0adfc1d57684333d6bf81546f1dc573444a38ee18c5049c567b7fc3a392a3c9867c06576da3adc9","nonce":"f28f1595dd021db843d54345","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"0ff8a71d935a96469161cbf8f50349d79b88efee39890f09426f0aa9b72f79bc24a38d66d1dfddbd0557ebc998","nonce":"f28f1595dd021db843d54342","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"f1bb4200fe49d5831f750fbcb76dc494a464265c0bd781f950c286bd3ec1330baf5adffc406272323892969fe8","nonce":"f28f1595dd021db843d54343","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"71e348ef3b65d88a1cccaadfe6d976967c60d941557ffea3d190f691ef365270df07a0f78916d8c8d4e17fc5e7","nonce":"f28f1595dd021db843d54340","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"cd3a45865f7c97c29bae2d7903dd52ff1b0474029944a46f345b9063772f30c558725c241b14baf079cb6d024d","nonce":"f28f1595dd021db843d54341","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"1979db976fe00be12ad5e220e158637d78049d057df9bfbdac3112d51e689136eae3f9a2cfbcec95026183da76","nonce":"f28f1595dd021db843d5433e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"850e39945a643878026e52ef719f67a45c79899cf15c62db7e4fd47ef2cd1cf021c816b9caef10e3624e2bd76a","nonce":"f28f1595dd021db843d5433f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"7d76d0f7243c4af3aa96fe36f41a2d8b0067a8a54b2dff126db6e784e5f284e7cb95123f83a05d6c60289bb362","nonce":"f28f1595dd021db843d5433c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"e6bc8230843bd00f843c4dedb913efc006f1de67ddb17d8bdb2d27304252c97c273d4b200876e3bddb8a30c362","nonce":"f28f1595dd021db843d5433d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"e0bf777bb8e8ba7a450f7a4d2cc34abe68e5f5931d6a9fdb5eec3e1e7838e3ef8fca5408d236a80161b10542f4","nonce":"f28f1595dd021db843d5433a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"c666f17a43ce5fb2d9cd5ecad109a4c1169c5a1676d5867f46a048cefaeeeb7a86bff0d091cfd199b8c14461d0","nonce":"f28f1595dd021db843d5433b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"da62498ef5784a4015885f5dd472b65c57be68fb165deaa1b688e6a3e8414c8e759c7f2fc8d6f92a99f97e8455","nonce":"f28f1595dd021db843d54338","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"03e03919cf9831e91408f3148c3df24a8e7d08d1de419190c1313be59f3401231761d73827d464cf532e673906","nonce":"f28f1595dd021db843d54339","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"cd70d9c0a076bd32cbf6e569f1b49a6c0c0bfc9d25714e3c19c4d93cff2b58be1c1a3350432621377e88bb163a","nonce":"f28f1595dd021db843d54336","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"3e7e7b943a4cd6501aba6740b0dcdd49d19fcb31eccc2439a7b1236df1ea331b23dadc3664b5eef12b03c26871","nonce":"f28f1595dd021db843d54337","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"5460d6abb980807a6ee0dbf547021023f866c5a71eccdf3696793bf72750d6ae17ed8195bdf2764b6779e01029","nonce":"f28f1595dd021db843d54334","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"be47426dbc614d31b12bf02971f66fc188252714d43914ee8f69eb28ecedeff0befd672c0d84e8473dcc958855","nonce":"f28f1595dd021db843d54335","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"33ed9938436333a227bd64a8968c2bcbf83eb196b065a8fe53e5e2454c6fd3a638f68ea1f866a47625f1496970","nonce":"f28f1595dd021db843d54332","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"f047c21bbc397a7d8060db0e4c530d5647afeaaee803760c71f7355bf34015a1171fbaae372aca10b78cf5e500","nonce":"f28f1595dd021db843d54333","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"5082a3959a2bcca7d0e17285de7261dddc24131e43ff8195683c9c2e8b1a1b521cc7e586e90f26493831d0f35d","nonce":"f28f1595dd021db843d54330","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"6f003f0466631807d4c3e351d2b93f52989dc42c02e51d0390e514579f120c7fdda833d8fcba386437c7cdadd0","nonce":"f28f1595dd021db843d54331","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"f3335c89d6d0fc5806dda9c8e6e29dd278bc7e5c96cb481ab0a294f0c351c72cd7772cc18215aca6f97eab35aa","nonce":"f28f1595dd021db843d5432e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"7a3dfd73d6ea875196e1c93ed1e7f088efc0f9785ca5f9e34c00aa1e62b352d3bfdc16f86da6295ca6eb48b45d","nonce":"f28f1595dd021db843d5432f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"57e3feebf7f0eb2ae57a61f8a1c709bd1a78e9d16f62618cb09c884771dc1d01f9487a617f6e38fe175a2b6e13","nonce":"f28f1595dd021db843d5432c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"2945c608b06f6fd1ef913d0f8e3e97ace844b74aa79aec1df9615324460bc379e915cd61ab46d3b64b1cb439c7","nonce":"f28f1595dd021db843d5432d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"570039db61876412e9ef525c72fb478ad699daa796fff4db70009ee80992a7c9f05b0414db515aace9ed1ae4d6","nonce":"f28f1595dd021db843d5432a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"a49f6b378eb796699ff613efeb438cc3779c32be494923f8330e0786fea67a3505035cf9c0a6939adbe7baefca","nonce":"f28f1595dd021db843d5432b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"5ccb27181f2a5853b5e195b481dab89582a4fb80450d20d77bf339bf74ca20bd0f65d7bcad6cacdf1a01c00847","nonce":"f28f1595dd021db843d54328","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"1d59f960d2ef157f8c4a46ae4a0c621782270e80c2fbde05914d94b62140affa4bc4a0018b9fe83b97a75c774e","nonce":"f28f1595dd021db843d54329","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"d4c8ccc3135a9c75e73b5e46295c8c696487f66d3ccd8001d810bdbd8b50d333c2fa0bf893f82ea47e0fb51e45","nonce":"f28f1595dd021db843d54326","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"bc0f5d1a09dcd3eaaa5de3bf1188bd36fb13d72dd79acf01ac807ee2478bfce3dec38fcde019faf9464c276ce5","nonce":"f28f1595dd021db843d54327","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"0121735a4c633c7226acec10c13ce302f0e1a0e37b9e91ef3bf24e9938c952d7af370f8efe3f203dc724468fb5","nonce":"f28f1595dd021db843d54324","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"27a0264df0559bade7641db7023b45dd9df08ad9cec4c54defe572559bee4cb0bf671eed01eab18572349138b4","nonce":"f28f1595dd021db843d54325","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"072cfcf0f38c7cab08d0df9d0a47eb24ae28826c3e33c70dae0699dcf93e94e5b4137df28b9724194ceb6de077","nonce":"f28f1595dd021db843d54322","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"87c2e75fdb46ee3757bde7c6af24dcf0b6cd651d6ba3c89895098995394ee41f4ab39266c59ff68f03dc39a7ed","nonce":"f28f1595dd021db843d54323","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"f45bfd1ce3d2aacc175dcc0018662e7699439001dfa1be562bdc5e553269850d4bf679018a81c374872a93530e","nonce":"f28f1595dd021db843d54320","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"426cbc59e858a1291828cfcee738fca8d24fa649b0f0043d0b6ca613802a4ff2f74d4981e1bb2e2e14e3ccbd67","nonce":"f28f1595dd021db843d54321","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"d10753d667695ae73ffa9306a82f18cf6adb5506793d36688e44c1aa5fcc2de2689911654182fea62d227bb524","nonce":"f28f1595dd021db843d5431e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"59ef3df893ae4afbc08ea2bc21ee57964a82d7304ef6ade4f609bf14bc4257c8aaa453a26f6bd5e5900ad939d3","nonce":"f28f1595dd021db843d5431f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"8ec2f1a281fa2c0856de9644a2c87b9f3b12de3b85fd988158ea4762637384ea9fe654c4ab32c4e1b79afc0d4c","nonce":"f28f1595dd021db843d5431c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"9fad30d5936538027fb39d856bb353ab02f575522407eda08c7bf351cf7e67fa2464ddcb78a48406b675ff5c36","nonce":"f28f1595dd021db843d5431d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"62a217ffb3ee39891ee3e659230150a4e332603c46980ba2454684402dbbe46a424aefa5a4cb5779df40cee3ca","nonce":"f28f1595dd021db843d5431a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"6f40dfeebb56221548300c197e4f4d88587c2d219bee6463bf19299d4115cc104615ca4b8d13984429ad0fef98","nonce":"f28f1595dd021db843d5431b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"d0fabe00de026d071fb804ad64bb360511603904198b0e2ecb72a886dd265197ba0520fb61487b1177b5812aeb","nonce":"f28f1595dd021db843d54318","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"e2426d7421de2a6da887b475d9c1aa64a92c78bfdab9d369c92bfd15049cf71abd794940af778dd5aed187fce5","nonce":"f28f1595dd021db843d54319","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"1d5ea8ce6b44b37e7defd939bf394e1e38f1451244960e530e7579301b2c33b1d0d6663df0868076baf4ff6e25","nonce":"f28f1595dd021db843d54316","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"f6544710facd58c042b6fc0002d56af0877a243c4e5c1ba600821b8adc9cda77902e37d09759bc69323fc7184b","nonce":"f28f1595dd021db843d54317","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"97523d754ad605c65e3d92f68fe1bb426e4ba087d1e3b84ee5a7361b03f31c24600c2d32d2f2d1d6afaafb14a9","nonce":"f28f1595dd021db843d54314","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"29d0659d10b2319331e515b90ef9a880ea3c294730fdf7fabfbad927115e09025daf0fceded8c9087fcad1eac0","nonce":"f28f1595dd021db843d54315","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"39569bdf7635edc9f8d9b46f9320574e2d9d73097326bca6becc1bf5354ecc8a67ad69c3d67fb773bfa6897435","nonce":"f28f1595dd021db843d54312","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"e45ed1fc7ac733c09ba23ece624672e1928da6db8848ebaa3bde3651c0f54365f4569b871da8f4048b4d246486","nonce":"f28f1595dd021db843d54313","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"89608ddc87de90faf1a563874ee2d6b6f95896d050ccf7b40ef78149604350f45d8e1f0f1adacf5da8b676c307","nonce":"f28f1595dd021db843d54310","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"6478a7fdf2a45a1aa3f3cd1008dfec0ee8a9a201e8e5250ed150399217644b359ea711239a2a5065240d5145c6","nonce":"f28f1595dd021db843d54311","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"4b7dce2f495410fe528a1437b1ef0dc8acbd1e8a8170d7cdf19f0be2fc2d649a66fc3b0424cba2618a6204f80f","nonce":"f28f1595dd021db843d5430e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"0fc1c83292b0d7961a3c8fa2d0e21db4f1a5e04ec3e01b6917b93d3317e6e23bd010c938182606fa6e2ee0755e","nonce":"f28f1595dd021db843d5430f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"561470fb32cba3cf01c7aa51ce7178de65886b0355e719d008be5e8eec1ba07508fc6c679dd38a76d18d93e693","nonce":"f28f1595dd021db843d5430c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"64801a743d041cd19f07e4bc1b4bbfa71d3fcd56b9527b58e75eaa5c519a37f115520914fee65c35769267063f","nonce":"f28f1595dd021db843d5430d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"197d3e2acbe36f4fac35ea736a5103d6d713f4b0f068658001c9f24ae736e64d0013a67fe9c2f5924dd4c00806","nonce":"f28f1595dd021db843d5430a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"c508bf9f816295433489c011cbdc1cb39ef61914ae49bbae7e36adb31dd1430383fa46b0bef185519282976e87","nonce":"f28f1595dd021db843d5430b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"32e981ba108cea834a99e7107b6853c9e2adb75e2b9ab5dbfc76a225415535feb17d2a3c73c7b6fbfb5b0ee0f4","nonce":"f28f1595dd021db843d54308","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"a97b3b2452d61a77096c110f72f977ab91059673bc10e03df0750f6a37c61a83f21cb172a113e188ec30a2e9c9","nonce":"f28f1595dd021db843d54309","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"2da31b404dc0f500d486f82dff4b33168aa8fa59985ea1954b1adfeae0d73a57797313c339d782ad5f79c82ce2","nonce":"f28f1595dd021db843d54306","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"945517ead607cc82f5ccce9115a25248e207779b2d0aa8fc6982be3d6642ad2de963319dade520539d3ee3f75d","nonce":"f28f1595dd021db843d54307","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"a12f5b280335f2e94425a145599f75812e1a91e7e1102d6326dc428ae1f272ec3a2dbf5d439ddb74b25ef072ed","nonce":"f28f1595dd021db843d54304","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"57ffd66e1dd46e08c88961718432fdb2485f8f6446aa765abe37eebd0f319a1b058cae5262a7b6f60fc7091f5f","nonce":"f28f1595dd021db843d54305","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"0ba134cb2a143dc4e06bf47adeaa1c50506ec3d2b70157707f0322a20f5e1d19045921593f349aa49455c80dee","nonce":"f28f1595dd021db843d54302","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"7a96c6259f157052228137db41ac3bcb7b0058a4bf2f8d0d6bbf1d8bd841768a3b27c1e0bff3d1f3252d39e05f","nonce":"f28f1595dd021db843d54303","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"7be1b77807224563c78515218631179cfb688587f1b09b75bf1e1e8c5407c6daf5ad1f265801c4ef99ee3af410","nonce":"f28f1595dd021db843d54300","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"9853bde15192781a0ea74a660529daebc0f6d7522e9f7a197e6504b074b94bbdf2dc0a5f958a8b21fe73667b69","nonce":"f28f1595dd021db843d54301","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"019fa7a86c0e68d8a8ab790402c24eb53620c349fb7bb53baa051f30ace4ea967443ffd643a70ab64c7f1940fd","nonce":"f28f1595dd021db843d543fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"ef04246a225e61976321afcb1aec88ec87616b2b0c1f00923dadd5753259c5d598eb8a7a12e05971035ab22d4a","nonce":"f28f1595dd021db843d543ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"202e1e47822d27f6e99af610659f24164d3dab57cceeb88e98eb9568e4294610b5204f01bbd7f66b38e03724e8","nonce":"f28f1595dd021db843d543fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"5385c042723e43f8c26d64075494e1518ea07aa715a0c0f8ec68163dad3c4d320ed2c5c736a971a2014c8276c4","nonce":"f28f1595dd021db843d543fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"92886065cb32cc4653a85fe962a6d282c2e741caa6c0269ade0c3b13ef6753a97e2a8998d106f837c509e7675e","nonce":"f28f1595dd021db843d543fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"2115ab3a338c4fb3cccbdfa9c999c7b141d13586947860976c86b8bf9c7100bef4913160b423d1b9ed1d707500","nonce":"f28f1595dd021db843d543fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"08d6ce05121c84665a7eb2a00e9b05aa65bf1a8f18ac75c5365f97271d8d22e49d255db73f447cdb819078b6ad","nonce":"f28f1595dd021db843d543f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"67e06ac23e857b636b72f81bb9faa9ee65ce8e120f6f03dcae0026766f53883d2bd8520747ad708cbeae8a3769","nonce":"f28f1595dd021db843d543f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"127bd8d1795a17854b440e6c344f4e4b28d55349b36b2110fb3132303f462a039d6fd2201d39fce6db5263c2ca","nonce":"f28f1595dd021db843d543f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"303ca8aaf9ff216bdf08fa8ac9af0ccdd5b166010c1fcd64cb93fa366063197df8e56c4945f7f382f4af04a9e4","nonce":"f28f1595dd021db843d543f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"169da0068fc01a2dcc40cb3c6dc6c1a4fb777be8b988e08080a293e68a1b005a652c51e3b594708cbb5651fa02","nonce":"f28f1595dd021db843d543f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"018ff1ebb6abc5fad80fee254e05eb7f775da410cfc836e0691e55c355fe82bbd3d36b367d7f863d696af8742b","nonce":"f28f1595dd021db843d543f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"7d6206d46ed7779d7c7895581713f27996ddc5cb554d29ec9e1dc3e0c97ac66ff59a2537959cda8de3b9d35b86","nonce":"f28f1595dd021db843d543f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"97f6496828a9c7598b63916791da5d79ae2d4f358ba1a92eb9e6a2258acf10e9c87e0b485d0bcb075d62d07cc7","nonce":"f28f1595dd021db843d543f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"b484445f7986d2ceb017169871fb16197521a7c789ec2bd7462d5822360b30593615208f84d6b00e78c8c4ea50","nonce":"f28f1595dd021db843d543f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"c714dac370be2e5aac6ca91884844c4c3ca0122fa51807f4489880762c3c2e5d695d5dfd7eb2801f3cf2bc690a","nonce":"f28f1595dd021db843d543f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"5fc939ebea4f36a67e586a60ef85898409109f85b40c726780e43e9e6af86df2e1fb80be6fe2baec40a90d036c","nonce":"f28f1595dd021db843d543ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"a5d30e0c1a997f2bd70dd7e1607822568491dea800f4551fffa9039ea5edf181c5e85831ffc51eab118ecde434","nonce":"f28f1595dd021db843d543ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"1d29ca3e01d1452d7c082e30bd8d49911d775cc02e53508769e2128a91d0a0c692a3cef431d8c6bc88b5276329","nonce":"f28f1595dd021db843d543ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"bca55e701b7245fa425540e070418e8e4c11c3bc6da3c2050d9a5c1bda69356fb413b3f8217d2cead7e975e1d9","nonce":"f28f1595dd021db843d543ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"4a79081eb491433f0399324e8dacaabb268f155b4c4ce574ab7d369ba4fb1a67cf768ecf85482a96b6da1e4e4b","nonce":"f28f1595dd021db843d543ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"b0af8a8c4df33b0557a1b7d049afcdadbc7c475633bb13006a6b42fa46bd00e46dd8eb6ffd74ef8193ed1de6bb","nonce":"f28f1595dd021db843d543eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"28be09295a1f7da0e8a65c0dc3e34985a664459dd62a6c6c0e3125bca8c197775dd394c78f13234ff90c70a743","nonce":"f28f1595dd021db843d543e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"6c3129a6da1a364dc0528e8087a1d69ced0411efa112bf645f86f4d1d073929b0f062ac64a0ecbcfa51833e0f4","nonce":"f28f1595dd021db843d543e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"37a0d8d958c777aa711f526893f8065af3ea8c465bcb016f8606633933ed6c85121b908122a34920eaca0ecf88","nonce":"f28f1595dd021db843d543e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"fc6a78a3ad4e69cf04d92eb84fe2af693cb1615e8eae996180ba2f88063f9a0877fbcd6def5bba4f5d23ec5763","nonce":"f28f1595dd021db843d543e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"ce258a91b864149bf3aa9d2fa830b8dbb4b281e01763e4cff397c1c8f16d9b9232e6ccb7ee3a12da0fc80814c8","nonce":"f28f1595dd021db843d543e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"86bde841424015ed8083a3f16a78204127741537f0672f4c251b8d98f77bd1860ab94b3f629b55a6d5352e90c8","nonce":"f28f1595dd021db843d543e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"50fb736fce93053464f356e7cbc5d21008ffe309630e42511355d3e49d8022d958810bacf9facb25259ed9a201","nonce":"f28f1595dd021db843d543e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"d9562af83f91e84773c4a7e81f8e8aecf08d09f26c29dc61c269d55e4e0c6faf7ea1b2399645328bcdac98cf68","nonce":"f28f1595dd021db843d543e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"80e0631793f3da9d1a7b43dccc18975434e3140a235decb011e022d29767839252c329b3a5d86bda410f3d8d87","nonce":"f28f1595dd021db843d543e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"a60277dc349866aead42affe3ffc16d0cba8f8506e9409f0e7c9cbf3bb190b8eedd8643c246cc778c800040770","nonce":"f28f1595dd021db843d543e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"ceae766d4803c0e00f7308288184314b7fe60b1a133332c00457a0cc26e412cf3c8196b1d56d9619355e9a3611","nonce":"f28f1595dd021db843d543de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"1f210b0b2e8e912498cf793f498436a7850a5242779fcce9a3a8824b6f6ea9b9860e2060765db6e0dfe7a748b3","nonce":"f28f1595dd021db843d543df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"28e832088327d84d0c2e74a82e2b2eda272e5c9ddbc3bd18427cc06de8068e66157a53a9588c7911525ec55d16","nonce":"f28f1595dd021db843d543dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"3c8df199a94282a2f74abadf40898471a27a68ed8f796c270ffac7c4c0ae9ab3ed79d82a5633bbf31b2d110ead","nonce":"f28f1595dd021db843d543dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"4ef9ad640678b164abc18a3421b3800f0faad2ce79f041e057e7a56f86cf59d3a0322c8d09e90491a6536172da","nonce":"f28f1595dd021db843d543da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"c6a026559e7a9431e50a93b1a77384ac53405efb74e1328cb0761ec3a6f45261d37b3ab1e0fdf2742845bc098a","nonce":"f28f1595dd021db843d543db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"de72a8637aa8dce2dc1b99a8aa51cd71a2a90d6e953bb1371ef8ea09ff6838dedd35b02f578c256c81eba34a18","nonce":"f28f1595dd021db843d543d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"ef051390ce2c5c8247b7b9bf2824859692ec14e7ab1ca5ab6a61323180aaf3e88f117658fddfdda4f3b52cda34","nonce":"f28f1595dd021db843d543d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"93e01f0bbf2fa4f098a9062eebbcf19400ed1b180403a9db37eb8155d15445e92409aa9844ae80278e21b933f0","nonce":"f28f1595dd021db843d543d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"64c56e3bb8c6b0feb5ec2c8e99606b88488f55247a44dbe381638c215bdff9fa01bcb308ae90104a7abec9ca63","nonce":"f28f1595dd021db843d543d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"95bc68140721f4b8902ea82689b285cb42cb89ca20bc44ac39c4d2e59492d86c2b26ad48f6c52d4c05ac5339fe","nonce":"f28f1595dd021db843d543d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"ad54967b8008a2c229038e33bfea2c16c78bca8f9afd8278e02e1f2cca4e993e1027ef98ba8a58f37328cb7778","nonce":"f28f1595dd021db843d543d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"183a06419b3f783b5d8ba4548d11632ba9adb21e035fbe5f98afb463893d24eae88e75442e97e54923e72d70b4","nonce":"f28f1595dd021db843d543d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"26b7aeb5bba2937aeda06f9c162fafab4dce0fff07485e814b7fef1e6b3507c420d7b1dc579078e276f0aff832","nonce":"f28f1595dd021db843d543d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"cdca96768a933141f40f54ed7b8b2b6689a865791de408295bd7cc8327fe89bd9af6b2ed0b8ca3cb058953ef9d","nonce":"f28f1595dd021db843d543d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"f95802e85c86bb515429473a86d9959ce34a307d778ff1035bdc4f24f6c14e1f251cbdcd994eae24a4de26dfa6","nonce":"f28f1595dd021db843d543d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"d923df899bf685c54e8f45ed970a100499b976189b9121a2c91b7a82b2dce57b3dd675459de53a59a7d4645c50","nonce":"f28f1595dd021db843d543ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"df0f1d0c188a5f15c6e68ad575b1535cec7cec6139350e11d38e71e9946845bf913a448c0c1425fad729a00d8d","nonce":"f28f1595dd021db843d543cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"9613c6f47f5cb5126cdc9cab07740aa617fafa8adb98f8b6bad33448ef253336c0fe799fa429efc11c9c9237c2","nonce":"f28f1595dd021db843d543cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"825acab2bea0c907f115b1dcf8d3b67bfc99ec94e14079f1ac376b3534f3888907be199004b11f68beddd2a31a","nonce":"f28f1595dd021db843d543cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"052a27ac2e043044236e5b77b82d6b1dac9b0a60a79667ccfa449a5635364d26fb9d561acac6e52587dfff33fd","nonce":"f28f1595dd021db843d543ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"822f8427ee32cc7bfc3a330347a44e46ebe777be3180027946d5359e314a414e55a904ab9f8cf09983ad4f79f9","nonce":"f28f1595dd021db843d543cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"61356c5913344fb6b100cf9f6710b7759d7bf4d02a27a49a914d0f6fc10ded0a1b15cda20adef3c8c82646e785","nonce":"f28f1595dd021db843d543c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"62253ebc1ee04f9ff0a56143b01515ba7af0d2ed9ccd0cf0201d341127af86bb58866e5a89928a19bb01f15c0b","nonce":"f28f1595dd021db843d543c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"4929e522d742f2de7848545b751229c20a42b087081a1d3c466cbb104ab634aa9d10a665658738932a9c5ed16a","nonce":"f28f1595dd021db843d543c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"335e3960cb0ec3def20c69f00c3af83c0764c26761ce89f87ec5d228a3eea0d2f1f4124d73d3afddabd5822793","nonce":"f28f1595dd021db843d543c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"b4aae8c6700dfbc806f5fb496654c9decd632ef29523c295e39416e1318aea7cb109f82c8abeb7acadc9445144","nonce":"f28f1595dd021db843d543c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"dcd1c6c6f0376211d758531159316f3fa2bedcc8390f02d04ece4afba0f887947b0801a43fa66a31ca0a97245d","nonce":"f28f1595dd021db843d543c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"e6b547dc058cc3b3725c97b8cec047df259ebfc5897cfe0d559854f7f452c277e788f52a038951dfd70f82cf66","nonce":"f28f1595dd021db843d543c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"8fe262b2340fedd8166924d9c4083759c18475f1c195b9a19257016f3ae8741d5ab17d954a764b006987184e2f","nonce":"f28f1595dd021db843d543c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"6eee9ae4a1687f30e54bb28c672d6fcefd6ad95ceb76330c3eb9738f4a8fa7d1a667cb345fd95640850ac05019","nonce":"f28f1595dd021db843d543c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"fbbde8eec7b17b37f6ee4798823efdc45cbc0097a3315fb598d9f90ae55271ed91060cd552e2ad16f2a2d12113","nonce":"f28f1595dd021db843d543c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"dcfb21893ac544e13c25acd741f4cf57111918061a19f4c635e7c85f1c90e845f306b0b23e0c44a1e7abd37b7b","nonce":"f28f1595dd021db843d543be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"d71a0565960f7745dcf2afe28934487d59785c192480e7a0323cad4fce24cee244627b9b22a59659073ce6fcf0","nonce":"f28f1595dd021db843d543bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"68a78b99eb78c72420194fc39264cee180fac6d28569dd8b7b445ca982a22fcf470ee880eebf82a5ef0105831b","nonce":"f28f1595dd021db843d543bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"3180cbb7f530e05cfb427c0869ab81ed3e9f6b66237be23a7ea2e3fded06ca64f5fe7e092dd6adaba92c7e4814","nonce":"f28f1595dd021db843d543bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"26bd4c6dd9d4b40414bce7a22561e8be2540f05df4d8bb4cd81386055548087278ff81cd631eea879df52235f2","nonce":"f28f1595dd021db843d543ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"eee828eb63e2eb36fd750bda2c24291b193100c6ac0a7dcbc0cdde1678461c05d2ec9637083e630c343b5ef5c3","nonce":"f28f1595dd021db843d543bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"2245f283db411faab50d5035289e04e284426766c5a93034343b13aa91542d28c85c8d2d358aa20f39e99e8ceb","nonce":"f28f1595dd021db843d543b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"f4579ae0009042253aa17648aef6badbad212933fa4f0f28706c2205da66b79e6abd94faeb50d30ce28db30f59","nonce":"f28f1595dd021db843d543b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"9c1b8cfcbe72322239e031476fba123bbc3ed18f9f8f68cd30b3d96c895e7222995857f082da0bb22f1e4c446e","nonce":"f28f1595dd021db843d543b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"82622380a891f41815ca328893a08fa28c670562cac74858847b216004bf7fefbae167b204933642783b6cb3ae","nonce":"f28f1595dd021db843d543b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"645d44acd57e0942fcabcacd35f0bf8c4b51e58a5f267d83a7f2a495cadebf6bb036a751cbcb7d4ef078129902","nonce":"f28f1595dd021db843d543b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"0b2867d211383acba6063be22d1073c317723910a040485b512d583f091d46231e507211c0a2970a3f185f1aa6","nonce":"f28f1595dd021db843d543b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"8d0719d2600497de8814909367f8771aa54e16d556e301c11743c5995f770260f33cc06985f2714a839ee45b07","nonce":"f28f1595dd021db843d543b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"aef8605acfb034b315339edaeaa92df6f54d28668b70fccee8d6ffb5781f372fc63fc6b341b5c89868b4fefa35","nonce":"f28f1595dd021db843d543b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"6595f3436ffd8aa9bbd57c70ee92618e2acd816b9a41543f3db042b56a6f070b946458ef1e3cce3912129cbb8f","nonce":"f28f1595dd021db843d543b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"c6ff4328bb7ad18192662d81ffd3fe2c0cd75a26eb44b9d2880980f1b2fe13c7cf49d8409507bf3130dff6a7e0","nonce":"f28f1595dd021db843d543b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"345b5f1e44d2f39a78e52d61c5cf7a8395b95b09f02cc14c34502fa983b04c89ab9bc970f04314f3ccd2a5acbf","nonce":"f28f1595dd021db843d543ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"805a18f8e3f464b08a1dc049fe0805bbd12cab4f00f5c5ea9e5e401a610bc39c19f11f34f470bba9edaf88f1c0","nonce":"f28f1595dd021db843d543af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"aa9db1746025008dc195e1a9df42129f284c4eeab831fc2d8abd473713bbf955c13873537a72be6477700e8589","nonce":"f28f1595dd021db843d543ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"9189268fff233f2d8a3fe572527c122e63ce53d5cefa0f6e1204c9e1d2caff39bf94ae1babfab456cf415b75df","nonce":"f28f1595dd021db843d543ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"b22f1b11d5edd6909ed3a9a1e8d53d2e492c492453ec8f8c3d9fbe22c66a49a19bc9884612477717defbed212e","nonce":"f28f1595dd021db843d543aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"8fe265c6c7b06d5f576d14872eafa26c9042f45fcc191c11b1a4ca418a7d3a75e3f5fcbfb98e4705a4449405cf","nonce":"f28f1595dd021db843d543ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"7419f98ac99c060ad0cb631092e03ed3c16ff8bf8bf65e95cdd56daac1a474e49f0aca69f93acb692a540a8e2d","nonce":"f28f1595dd021db843d543a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"6347965c2a039862996b49b761ef0bb49cc58541a8ba72bcd15714f0813e256be396cd2443131f268328a3ced6","nonce":"f28f1595dd021db843d543a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"69a939b21e369311883d1a2cba0063a4e3cdcc51b037b7f05d76fa4ac2dd1ef1df3ab1a80f4dbebbf92a757b57","nonce":"f28f1595dd021db843d543a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"6ce7dbe5cd835241bef265468b7a6f2f04ccd17af337ef4c82e51302634924e0040093708c32afc9c173248aa0","nonce":"f28f1595dd021db843d543a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"bf4f90b86b633ea8fe4aa4e32fd407a68f901c00d9d88add4ba8fd99825eb70872b2a01677422c7543a84eb16b","nonce":"f28f1595dd021db843d543a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"46aa6b4b74f884d254f6238cf99c8985c55e4aa24f9774278c913abd398730cec45283341106738d2dae007b92","nonce":"f28f1595dd021db843d543a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"b6bb88db79e8593de5fbc4efc943aaddc81326f8d3163e5ff4db89da70076ddca68dfd2240f459cb37ef02a467","nonce":"f28f1595dd021db843d543a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"05ce8dd6acd34b6d3de2bdb29ca9b7048fa2f9bba8521c38d4dbcbebded487638aa83f879afe67565149a7f2a2","nonce":"f28f1595dd021db843d543a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"00ea738080926de853d58a28803bb9bfcfd60d2295c18686f1216ddbf8f0e52415cf8ee6892518a10f8853e6ff","nonce":"f28f1595dd021db843d543a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"effc6d25bd89ebf56af1fabc33daa0d1c6d29b743fab77559f7044b659376ddc98888080aff0968695bcc87098","nonce":"f28f1595dd021db843d543a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"34b67c1955e9c61695a9fec0dc8338f2dd1e229af99a82e3b2ee048a947f5d6ccb6f8807650b727379f061c1f6","nonce":"f28f1595dd021db843d5439e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"51937661bcc87a475c44bbca85a987a35cc6f8b2170f1827db541c503c0f1ea5cec4c34a6602c10def35f3ea2a","nonce":"f28f1595dd021db843d5439f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"e5e071a0ce27d2a1876e36d2d258b41b36a0c718b3a40756b7c4865cc00db94a011272e106d13d8691390ddfdf","nonce":"f28f1595dd021db843d5439c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"a8c3ff71ae97ee6daa8c6b8bebfe276c5a52f9997a4bc385b94742ff9d0350dc9ba704d5c0dfc8241fec668c89","nonce":"f28f1595dd021db843d5439d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"4db699cf1f556601e1d5324500ec9b69a63d1ed70e691e5829d8ea0cd31333a58b11bef74fb2873b36d31a2065","nonce":"f28f1595dd021db843d5439a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"143f0dfb47062dce0b1062e9a02f748dbacec5853371f1ce0c7ab8f44ddb907addfe6373a483623bafb56eb633","nonce":"f28f1595dd021db843d5439b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"911a1b12ca83f5b58c78c1e099f2a8cd79a66ca343ac938a7268089e3cf517672c11b560a35a7e9d0b73297838","nonce":"f28f1595dd021db843d54398","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"fb0be34e26e284fb10766cb4b89eefb1b23058962bedf8d13b4ba9e2fc5869c5d11096d721bbbe150a64708391","nonce":"f28f1595dd021db843d54399","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"42b41128ebb96732632d5c03f6f9a6fed7e8139d5695959ce6ee8e5a29eb57c72219529947dbbb4d11f1ff8d9a","nonce":"f28f1595dd021db843d54396","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"63c6bd14b53e4652b0dfcc2bd13db32136cac8da4abf42e516e998ed3a7f9e2233a725c4911b58fc9bf6d2b754","nonce":"f28f1595dd021db843d54397","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"cb0b60f9ca45fb110c448165132c1e42e5058b8071ecb11bac9b522dd320f6540a66f3149dcaf83b9f07eb0c27","nonce":"f28f1595dd021db843d54394","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"e006b279fe41db03c0675c425141a5244656f7961501e0e9b678f5a1eeb780673c8ee00f5ba69c2b3c111b02b4","nonce":"f28f1595dd021db843d54395","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"a8a19012dc9871d10b44b0ff8b7ff66c0c8bb2ae182085371c0f7062426a257c9b6f341ddc84b66b8fdf5ae257","nonce":"f28f1595dd021db843d54392","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"8136e0691c833bb411a549a04a15bd3029cdf33239e14075440fe75f4cff4f7d6f1ade731332564318bfa6ccb5","nonce":"f28f1595dd021db843d54393","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"7597324e0fb5705ea9a129c5c61fa34bb8aaea9d098022ae7cf037badafa452c40fb064a328245f26f90f9bc12","nonce":"f28f1595dd021db843d54390","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"c581e3ef8eae32c16357f6d7e2c4732f14f78b2e0d43f2a7c3aa2942b69dfe0e0ed7e87133fb1f1e43b02203f3","nonce":"f28f1595dd021db843d54391","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"f327b85b71b3bf718c95c161de205915f89bfceec5b847220c2f5a6619bbf305cab9f562abd1a7c4351dfce610","nonce":"f28f1595dd021db843d5438e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"0ab568ac7988bb74c8a45032b7c1a2ce3cffddffa5dbd05c7bb2cbeb67708a93998e2e5750714ab982dd7a4a9e","nonce":"f28f1595dd021db843d5438f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"1fd6e4da140aa54f28fb7d638def7533c77ee9e3c2ee9424b33c27f879ec9b491d4a158f4b9f0f0bf23c319cd6","nonce":"f28f1595dd021db843d5438c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"1df03c41dcda714e13680215586dd1bb2a45ed4930bda233ad4ff9c69c52ae564f2c6ae34a78eb311d5301d856","nonce":"f28f1595dd021db843d5438d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"46c2a2ec85b0234fff1612c860f0f295a9352efe0ed9c1c9086b659988bf9bbe0db41cc0d9158d95c850892359","nonce":"f28f1595dd021db843d5438a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"22497e5ff440ffbdda860b1a7c3129e5cbd23d0945f860f6a1254853c06a0c1f12adc130e3967243abc19bafec","nonce":"f28f1595dd021db843d5438b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"3694f1ec51eb2bc7544f98da3e778c78fe286232501b929c07298e65036bed65b4886689a1fb18632c8a601e11","nonce":"f28f1595dd021db843d54388","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"2d7dd160f2561f1a14c67012ea42b5e17f7f1e22e8de65b60b11fe3fc8d0ee2be59bc222aedb089b0b8a577041","nonce":"f28f1595dd021db843d54389","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"b59b5dc707b89d12d2787a47e205010f5d307979f776cc246e5c4b8b624e34d89f0451ff7aa44338ae29f0f316","nonce":"f28f1595dd021db843d54386","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"44f07a6ca5269a12f5653e4277b252427ae35f3601884cb6e93555153be555eb525da864a1cc58e92ca1151dfe","nonce":"f28f1595dd021db843d54387","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"c52753d96ac866b84c281bba1f2b1d8416e18de6662dd804fa269ffb0163de9720565324025dc6b661fdd15e21","nonce":"f28f1595dd021db843d54384","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"8424bd6a99757c60a5f7f805e22e48b7cda64b00f65c5435f3548ca2bb816e5b6aa3ecac07f7023be03930321b","nonce":"f28f1595dd021db843d54385","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"ba83633634d0f7cabd2e36e6a59d5047b44d0f4a6b4c25c098dd8ccb2849b4e6077747092564ff6f33087394cc","nonce":"f28f1595dd021db843d54382","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"aa839037d89797fc904d3d7ef6e81245d4d504222a0045f1a381051a02201eaf4954e4dd939ec1d9c198bd7e3b","nonce":"f28f1595dd021db843d54383","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"2fa0c4f94aae3d2a28d58746dba832500c27d94ea6dd7994c2ff165cea7261d483ba91b9838ddc9ce6f11c500a","nonce":"f28f1595dd021db843d54380","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"b331aefb6bf8b00597f41e923edc913b3329c796d5517933d1531249dc54c31b4e94158a4ca85dd521879f12e6","nonce":"f28f1595dd021db843d54381","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"40546ba8323f375f5f60e4c9f4f7cf23db85feb8e6b6d5a3d731afd20e9f43af4c2945423914151eff213b0f74","nonce":"f28f1595dd021db843d5427e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"b69c3b2b00725c2822a379c0adcb9d7b5619610cf51f22a6a250ef4e68912a03"},{"exporter_context":"00","L":32,"exported_value":"2395f4573e42de33aacf2e89c5298f64193c2575fd692a5728fc22ed2a71470f"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"d8c5eb33e262f150de0d714df071095f2a166684fb8c8401e317fce7ad725dcf"}]},{"mode":1,"kem_id":32,"kdf_id":3,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"f5069eb018e47273a602f6da12866c40b895244af944f2691587597bf8b216ef","ikmE":"23161c70100c0ee30c6fffb7ce5adbbaba45aacfa69a6e377cd165d8e67efacb","skRm":"40cffcce7a245f8356fcfb9eadc69828207282326699c4247c64ed505eb2f263","skEm":"7a2480b0c7c466f4ec155756e87937746264c0881b631f405f1987941cd53bb8","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"a08a0dd37d79572cd4fc49e25c621d7bc718b842f2d0e5d5b61f84e28872b21d","pkEm":"e96f747702b41c838185c0c1d582aeed5701cf729cb951757ec8db541b980414","enc":"e96f747702b41c838185c0c1d582aeed5701cf729cb951757ec8db541b980414","shared_secret":"ae4852bbfce886659f1567ebfecf96ef77780fe0feeb4524c8ea99d6f72bf751","key_schedule_context":"011b6b08c282945123288e49bf5ff79e6dcda0afb9b4391857b06a196397b19c21e12683685046440266553074efce3b8b1d9d6f5e0c0a2544c426f62db07d748c6f17ad5b0cda65d91049ff137dc5111687e0d4d44123d94cf2ad7b71ecb5fab6cdf8e044519fe1ecf7cffb6a3f3bfbaf6babfebe5d30a92e166f52849e8d35a3","secret":"d90aa920f1afeff7c10e0b1ddcfced29edd52ee5f2c8bfd457a19ae2c39e92968cc122f2e5089c250953baa1a44c48d9767fbbad2fa13a5a66422600f34a1223","key":"8de4e223572bdb8f2bf107777fed02c2","base_nonce":"9b3fe8025091827f38d76e92","exporter_secret":"1ee358ef77dfa98cb909bd864c857efbb6edc4c4c79487352d1783deb0c8e733e92657a44b20ae81d0b88fb6119295116f00ff65d83e38e276e786d75610705a","encryptions":[{"aad":"436f756e742d30","ciphertext":"589aea5a0d8870ca8cf9c4dca4a51c5dab1c2d33d29314da30407fb5fccc6bf3cff2abbf2d1397b1d5f61104fd","nonce":"9b3fe8025091827f38d76e92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"841c0d34fc5609215b78479bee622898cb54b4a2c469c174ddab5c0aec5774e58caeeb722454bf430ba4775d9e","nonce":"9b3fe8025091827f38d76e93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"58a94e60d537ec7364060f66cf0025cb53922ea9673d5ed1575c7e55548a766b8798c588a76180a1733982995b","nonce":"9b3fe8025091827f38d76e90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"0481b38e2b7d1da0a9b455a248ff9e09c285349e4c26b0e7d4617ad57379a5a6da55c2a20e8da1ac9c1df5877d","nonce":"9b3fe8025091827f38d76e91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"10d47bb21cd176219f85b4121ad7710ed033c82f0ecb050210698d5170ac83196e90f23479e0fcdf7f135556cc","nonce":"9b3fe8025091827f38d76e96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"ca0e9c2f0704fa47d9c4b6eeda034dfc8edbd49790a9e820753d1634431225b05ffdedb80e622c4536e3b93f93","nonce":"9b3fe8025091827f38d76e97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"52a26206a794ae053ed441cc29257c859254e559783824c117ce5f5798bbce0fd8b5f43afa21087c6a06a44c6f","nonce":"9b3fe8025091827f38d76e94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"d2c135143c5d1aaf0108b01a4b6d8f01b30ce0b4ebbd3b83300a3f78338acb8c367103901a5899b5e20c84bec8","nonce":"9b3fe8025091827f38d76e95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"73cd268cfbf2cebdd6b79cb3cda8d32634b511b5ba4302e60f08425c8b0742b0fc13b0abd1a598ee210dfa6df4","nonce":"9b3fe8025091827f38d76e9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"984724c6230dee281cf1cf627f06985f8ad98b16daebb1414aa82f2e9057e273d709d96461483a3ffca7d5c72a","nonce":"9b3fe8025091827f38d76e9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"7e73379033f32fe3ed715f4aca798162db1e18e49bf596a02f012c6147fc46ad25f41ab1faa346c8d501690361","nonce":"9b3fe8025091827f38d76e98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"da4b267a3988e4f367ebe84b8e42331e90a742530eb6001037520acf6b08840b32c61f5abc08b907e393327338","nonce":"9b3fe8025091827f38d76e99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"b718a384b69bbc5175e378f4d7d0a1548cd004d5532169ec606a5704e80f9db63d41073c20463c9892e2e89c28","nonce":"9b3fe8025091827f38d76e9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"5aa474d14977a2427ef09f508615e74f781ce0dff762a4f5c104d85ad45d558770bffbf1a30fc900055e97398f","nonce":"9b3fe8025091827f38d76e9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"bd74bc7f50493b0389155517f4bbfc9e245c4032e4a4588f931c2cd41b9ec9c35c770b90a3c73595366a4d23a6","nonce":"9b3fe8025091827f38d76e9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"74a00650d496fdf838afbd2984239e73144fe126b8e5ff458be0b0f43bf24fb3094eeec4efe1279577dc4ed4de","nonce":"9b3fe8025091827f38d76e9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"8598abd7d5f5d4f990559dc1437da187b068f684715e0dcec0dbecda2f2bdefd8300cacfa0bade1be6845d842c","nonce":"9b3fe8025091827f38d76e82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"121a1ba602a5855bade505135bf9e613db41619310140ad32b89a47011ac5e3a23d5ff3c4db9362962da413db6","nonce":"9b3fe8025091827f38d76e83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"d98888733221b5f775bf93c54a4505d7eb48e47456827c164ab009975d439c856e3c0238e913ca5f48c879f81c","nonce":"9b3fe8025091827f38d76e80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"ab3dab7327467e5407dc454e4a779f72a6af15f562ddd41ac88356eaf30f1ebcb5aa6d999f24577a343bfbeb93","nonce":"9b3fe8025091827f38d76e81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"3c2cdd17346d89b306de3faaf8395bf0d12c675a4585eb1e9c32cc95a727bfe979e4d5edb29a057b147d05d716","nonce":"9b3fe8025091827f38d76e86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"5bd9aeae4abac02c0fecd0db6aab79595a4e1a392beec8e16d230694ff891c7990978ba2d7660c13cd06a80033","nonce":"9b3fe8025091827f38d76e87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"54a96a3b72d1876d790bf1a1402aa3856885a8044fcf32d27fb2052b1850e80e81217dbda1050685a49c5f0035","nonce":"9b3fe8025091827f38d76e84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"78be8bb40b0632f80834d3a0702084b565b8aa59b0c8da9906201e4f58fc0aede88cff589eefa0213b254a0294","nonce":"9b3fe8025091827f38d76e85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"0dacef191d9acbe73b0200e62e7031859543548e67030ec4c7ccc9d7727b62ed3ae1e04ccec9c6eaff398f5851","nonce":"9b3fe8025091827f38d76e8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"1154c55231763e5c9ef18f15eb145d06edb7344c9259a83f5a33707ff29d9d76d728899ef6fbddebc4ba85be61","nonce":"9b3fe8025091827f38d76e8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"5939a0e29d85511eaf949c362a934b9b941fcd53b00c834074111d0a0410064baf6d25097a9fb1f55b5dcbda6a","nonce":"9b3fe8025091827f38d76e88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"427fbae490870cc207aa4bae1c81758e449113ef10a4ac668334bc114cf1cd8c8de45643df801eed79f7ea378f","nonce":"9b3fe8025091827f38d76e89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"d7ba3a1b855cbcc0eac1f4a37c704832924c91044d871877f5daccbca18d2abd0ad1aca8329068d905b2dba150","nonce":"9b3fe8025091827f38d76e8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"8863583e9122c3f45f3b87ea44d1298afa8a51977589767c6afd5eee6eb971708197f98c473500cf4559f50067","nonce":"9b3fe8025091827f38d76e8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"8571e53c3241124630d68ee3ac456f258dea1a4cf903646d0fc3f2e3f49ca07d83ee48201109e752287106539f","nonce":"9b3fe8025091827f38d76e8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"868022c9571208ff77d4d59d827efa351f777f0d1b7320026aa27d2fe87dbdf77c808c36a46908692697e59d8e","nonce":"9b3fe8025091827f38d76e8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"139d849ce79202359472595f2cf68886ac3790b88e81b2b1108efd2d136ffa202c7e766c8481714f1f4597bb50","nonce":"9b3fe8025091827f38d76eb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"c44bd49868fba1de71f90e58cbce4cec7e6c4ae8828f64a43011ef84beccef854cd62c4a7a658ca333e4dd0403","nonce":"9b3fe8025091827f38d76eb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"66c7ca985176bb6db9f835050431d281546e34efc527f073c8d714f3b12831d523e080d24d0a9666b0b5defdee","nonce":"9b3fe8025091827f38d76eb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"1545bea77102b470f6883c51b8b98ed91399e2408a0e0516c305a1412278372cf049f4818e856546d6be760ae8","nonce":"9b3fe8025091827f38d76eb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"8a88345929b14359d58e3e215c19c77ace825f3edc6197339f16b0f968f9dda575a9f5912b30cd4f2d706ff0e0","nonce":"9b3fe8025091827f38d76eb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"50d2dfaf91b1739feeb9cfff79c823ca55f1a749f5e94fa104735dc2ac4c97ad0c29ac8ac661b982a5c3279191","nonce":"9b3fe8025091827f38d76eb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"110c4528dae44cbd1528544fab9ca4c77340e1f58520a60b2a0ca8e1565728a9790a1c5605c24a825cec866c9e","nonce":"9b3fe8025091827f38d76eb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"41d8b843550fcf738e91405b971e8aa7730191c584d654e8e11f61ee52e464cd4fa002487aab8bd0450bf11404","nonce":"9b3fe8025091827f38d76eb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"ac23c1bef707d1028e7643658b9b4dc37c98a282e529652abc43a85c1d5f32495aa41c56c115c555215472af06","nonce":"9b3fe8025091827f38d76eba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"c3aff17100931a5dc905a9c194e7655043e215de9c0bfb6de79779473723926d104580a53d0e47a0e86b870847","nonce":"9b3fe8025091827f38d76ebb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"28a7672a66cb06da760ba736284713e2e80ce8fbe114d818da55817006fe0e1beca859e186c02b30e5467295be","nonce":"9b3fe8025091827f38d76eb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"a3b17a237e4d0b020daabdc288f87d330510865ffe6019351d3ff9754009e3a48790f8a4050b985835fd3216e8","nonce":"9b3fe8025091827f38d76eb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"68ac482fd53fa545ce91648b2c717de25983cf5d404e5e37480ce56583397dcaf73353139ef450d61aed25b3d7","nonce":"9b3fe8025091827f38d76ebe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"49efedcfca913560fb1d960a23ec49103b0f60fb55a6890eea559e7101b00f44974015c128ebcf2405d75742f9","nonce":"9b3fe8025091827f38d76ebf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"b8c242d62694354c866400c627b14c95213c0f519f2d1728cbe8fcbc67320adae12ec11f33fb1d3c0f0c10e3b6","nonce":"9b3fe8025091827f38d76ebc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"d292f84a1c555ebe4f36b744accd9a17f41c4de0c2f294c67d1a0d725a01d378380a288d9f2ed27abcb48c093a","nonce":"9b3fe8025091827f38d76ebd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"773d0ae303db8f69997e03c9df5b57ca8df1ca4fc00ece39b056b34d96539c6d507c930a6da36f996760810836","nonce":"9b3fe8025091827f38d76ea2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"ee6b81c8fdc823f2918901d99b9cd16d5b2ae2bdc8b187cea689fec53b6d3a546e25830ac435f86770bde978ca","nonce":"9b3fe8025091827f38d76ea3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"79d4bba55260ebdbc7f6bcbcced3e0318e145245456443916229289938938c5a089877d4c043d6f7652f3359d3","nonce":"9b3fe8025091827f38d76ea0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"ba539cd59ad015bf8ad46e95d6142c9961ef3696196db6182a842df7f50a0441a521ce1ecacd4dc6ff0040516c","nonce":"9b3fe8025091827f38d76ea1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"809e1a4d19f13fc99a7edb0a7fa23ee92affad48e9199a7c36e431a2f583d10184ef718c865020cbf610334f13","nonce":"9b3fe8025091827f38d76ea6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"f3036a9922c0a591cdbdf29334a439378121a2f8d9c83960829c0fd242531a1339caafee2bcd3544787569a9d5","nonce":"9b3fe8025091827f38d76ea7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"3bf66f9404ce3b3591b9fb30a884e096e131274313a56319696f4db74081d1564aab78ddf45798064f3c363bf2","nonce":"9b3fe8025091827f38d76ea4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"d99ee06294e96735934fbec9fdaca89f58b451e34ceb13c520e23398bb7e6881f7bcb246de1c86df37b73da4cd","nonce":"9b3fe8025091827f38d76ea5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"e47cf5dde95d91bcd3ef74844eb5d799c2e1fc649f526419d65e87e3e8594c716570aa654d515cf4698ec10fb6","nonce":"9b3fe8025091827f38d76eaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"4c3633396139e62490f24c8758d17a9ba9ea497b3dd2ff3017d12900d862746b630d7148795910762e1585f294","nonce":"9b3fe8025091827f38d76eab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"630557c7248978f1217d3f6bee9b5907dc66730c44204b4a7acffad3dac8527396d2c1e9b54440e759f5c92516","nonce":"9b3fe8025091827f38d76ea8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"1abda45bc6ca317eccc7f2c10331a2208d41fda09800a667b0b4b926e4ff06e73aef6cb634e12373c30c7e3e42","nonce":"9b3fe8025091827f38d76ea9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"f4e38ae4fa9368b50c0c58edcd7c74ee2e3dfc58705906a620d8402cbaca47415ee23e1de8c6257b5908376a6d","nonce":"9b3fe8025091827f38d76eae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"437e9b5cb72b4c47476299419e7df22cb9ef9e2e688f5ee68d1f45c49f0f6250306f3240bcd376b680265ac772","nonce":"9b3fe8025091827f38d76eaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"103fb42247d96e70f2aca368945907aa83cf43a851422f12e977d16f8440f7647dd00d699cb07e37b6a3368a0a","nonce":"9b3fe8025091827f38d76eac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"c880796479768ed285cafa912daaa04e763ab048c196d70f2be9e915e1b1c84dc9e4bc13e9f51a53c1dfeea0c7","nonce":"9b3fe8025091827f38d76ead","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"a9c8c5aac8686509e0532e970f0fb7be8f8f50a33628e300c8a329fadae2567917de3b600b0172a24d1863ed06","nonce":"9b3fe8025091827f38d76ed2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"51f03f5e62b4feddb276fad8e942a64ab9c52a38127ef8cc38dd5afd617a819803af787d8112259a66f1fec4af","nonce":"9b3fe8025091827f38d76ed3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"1f55b6c4f50cb007b8f0a74dcb5dfd2221953a03b3f82f9cbd9428e9f43a15be97008a11bfb020324abb61ec4d","nonce":"9b3fe8025091827f38d76ed0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"4a39cc9b292dad2b04bc44c3d0812f37dc8d442b6dfb0cf8c248a2221a2efd61023edea0b3ace0ce3e601f7316","nonce":"9b3fe8025091827f38d76ed1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"f15f485d5de8f6849c1bd8f1748fc7c01d32665de2424a7a2a17d91171837b73ad7921e9ec1a22c78dcec1e611","nonce":"9b3fe8025091827f38d76ed6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"02698d2e681d96e1797e143b56e760a7f9686915684b23b21c0cf190c322f957b89bd855219f359def29f84ef8","nonce":"9b3fe8025091827f38d76ed7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"3c96607b7a2b74f5c2660999145e0064cb58c4da3105711720157a0bbd1ef3af795c7e04292adae93f32178580","nonce":"9b3fe8025091827f38d76ed4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"b657f8d3e0b165a408f7c53a02cf1da830de1408bec7bdae5d6cb31ee9e984851121102726ddd1cb8bcfd45bb0","nonce":"9b3fe8025091827f38d76ed5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"29c7fab46ceaff2a576ab70099c7115631ec9d206edf6f6fe9601427548c71873093f7bebcd0118b1d170e5de9","nonce":"9b3fe8025091827f38d76eda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"d63fca78f9706975a014360c5b42a7c59e4fdd4bb8e0e400133b3c63ddcd0129f140d95ec53a829dea57c9ad6d","nonce":"9b3fe8025091827f38d76edb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"d71e48a15ed7d255644960e3cee186b7e66c8c0aca1d010b4a762a14b863450866ddefa924d0c71f2aec0f0469","nonce":"9b3fe8025091827f38d76ed8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"65e91162df900035c97c8b6a5b8b44b8c1aa01309223fbc318a5b27136be39cef31148ef8e8bafce40f760921f","nonce":"9b3fe8025091827f38d76ed9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"4443738173c014cac502d065fe5bf478e90d9ef8cfdbbc1cef79165b2bf93dd051be90bb4fd793421faf5b6a7f","nonce":"9b3fe8025091827f38d76ede","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"831f80ea91cc3d8aeb88808171563106f71d7a94464c9677f6f1ca308abe53c579bf7b07dad859edde2c197e89","nonce":"9b3fe8025091827f38d76edf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"93505bb17589c418ebb458bd07e5e8d0690fd0e1eb1ba24c64bd72cafbfcc88bb8b5a9046bdfd246069f4abeed","nonce":"9b3fe8025091827f38d76edc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"d6f33b801718dd0c6a7a3043e20642b0a5adad560b40ecf4dc7b1abaa60797a63bda6b4cf7c30fcbb68fddaea3","nonce":"9b3fe8025091827f38d76edd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"0809a4ec1374c9fd2e2a2cbcfb82550e152154b7ca3228d1abd4b51ee3199f65032acc7297304a4c01a5677488","nonce":"9b3fe8025091827f38d76ec2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"7d6e39ef7dc0e5ffeadd03e2ff439eb01d845793b7d3ea500f8276c900890bb954614a1ce025ac0b1fcfe3e787","nonce":"9b3fe8025091827f38d76ec3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"392651627b486da0c12c297b5f753b2fa4cb058b303601fbdb2c731c2fca23c103997537446e84814040da583f","nonce":"9b3fe8025091827f38d76ec0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"f9f42078dab8fbcd6ecbad76cf6b1438c68ce2b0e8411fafd365bb6618d4df2da56db8f73f19a88d4b819c61d8","nonce":"9b3fe8025091827f38d76ec1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"f5e396748b43af6e2e233e6ac5bf8e6174492532bd2d13561920ddd7d1d4ae096d70fa0929178cdbec8010423e","nonce":"9b3fe8025091827f38d76ec6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"b323bbe5b6e43029ac63e3d26aa06eb269fc548a59a6d6d5661212f392a148cd609260ac8451d4784f77cc5a03","nonce":"9b3fe8025091827f38d76ec7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"99861cfdd3ee81e8cd3cee282101bf1a3c8f7b4fb7864fa97f3c0e3513deae67beceeb734a3beafb84ce488aa2","nonce":"9b3fe8025091827f38d76ec4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"e268e076475161e3fd4b878dff91dedb1c4b63de9f7ae1a80ba8c22019d20f1380971f42b19503e07f6a8c47ce","nonce":"9b3fe8025091827f38d76ec5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"d4e28032ab8f57f2d0ef677699ef2b2f6f637e3839749453f9a6223712f5661b6aa6b6238f3084d73ef27fd0b8","nonce":"9b3fe8025091827f38d76eca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"09dd642bf739093bfa4c7ac90da3b41358c9ef865493b388cff817ccd2465188878b75c3cd805b8cff9b565015","nonce":"9b3fe8025091827f38d76ecb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"7f659bacdb8540fbc2f24e5771f307e4a908e35b1189224880e78e1461845a2c7f139bc7bdd8b16a1b50a9ad17","nonce":"9b3fe8025091827f38d76ec8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"6c85b85ba8cf2f7a8f9654143ffe5385d2c355fc51ca5e93b4b7f84af1a85e1c84ae3fad81c3dde34153e87ed3","nonce":"9b3fe8025091827f38d76ec9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"df8157ef8785221603e843da60cd6ff20aedcb83196160ffb86ad81de90fc2c390e32e0b9acb6f6928255b68ae","nonce":"9b3fe8025091827f38d76ece","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"8cd10a666da7482c2659ee3bbcd503e0f2ed75a22d5e8985f11a8bbd449909dc8987532125376805b2ef1d195e","nonce":"9b3fe8025091827f38d76ecf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"76a58b77fc487d6a16a6a20ea89068cf864cb1c21c35022dee8c444f2a26d673bfd62e6cb2eefc3e5adb610bcd","nonce":"9b3fe8025091827f38d76ecc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"deaa4b35c41714b56048f20e7825e417ea3ac870fb23f60676e65f14c85c82aa0a321372b41bf21225f1716c6f","nonce":"9b3fe8025091827f38d76ecd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"ffbe390bfd3cbbcc2d4e2bf37ca84daa1337d99b69b8663640e54edff38140112869b069304ea56995c83afc68","nonce":"9b3fe8025091827f38d76ef2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"236d5a6f2ad9c061c0ef899459fb0b32390f3d9ca4ad698d1babde42aea6799b547c1b30dba9433e3fd089fed4","nonce":"9b3fe8025091827f38d76ef3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"b60c3bec4226a2f5a1c616454138db5500613f666f6df2d39e283140a6bb6eee76a9efe65cf10001c824191686","nonce":"9b3fe8025091827f38d76ef0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"50e292c3e09a8b7a8753934c0cacb128453f49f4b5d90c312f874f577c120111d707eeed8c786968af7d82e867","nonce":"9b3fe8025091827f38d76ef1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"d8f05b6b3027283dda3e016a689559045f53117b0679192c8433110bf6eec2eaabcc3009d91cfb842a4f645ab4","nonce":"9b3fe8025091827f38d76ef6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"24a23aba1df367e7da8e8cbb2cb0f47ba0bedf26201f6e8f74de2ad828897afdaf9a03211b8d56243c43143f0e","nonce":"9b3fe8025091827f38d76ef7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"d68b5287636dfc28e7a3c15f56948942d00b99e8878b9615a5aabac4ed0192fc4be2cfe3bbf05f00753f8665d1","nonce":"9b3fe8025091827f38d76ef4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"d0faf073dfcc5152a68139f9313a2fd58d6487690b062386f23671dd221bcb7e431d0adab1df8f7d8e5e4de1ea","nonce":"9b3fe8025091827f38d76ef5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"1042c149e04157fc2057612aed17bb4672c847bd2c6bb91d63bc7db2ffad5a3943550795a618a4596ed897eb4d","nonce":"9b3fe8025091827f38d76efa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"e58b512e163d0be58f52943b0a468234bd6e3ca4717b12aaac86f5fdaa75218286485a3ffbfff2f7ee60f264b1","nonce":"9b3fe8025091827f38d76efb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"b7a93e3b86b1c9c368536cc28aa78ca928de553fac986e1c59dcbf9368667e7cb177fd6cf9c85016cee23beeb6","nonce":"9b3fe8025091827f38d76ef8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"cd1a67c9cd42e87dd6b3369ede5a17db58e5892d8f93cf8624c3170d77867c5c51197acd5bfec9d63e226b708b","nonce":"9b3fe8025091827f38d76ef9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"f00e7c25a0e0c530b5366b698e7dcb50a3dd6777564c0a1c70c2beadf8c21efb284169ffb7556da22b9b4e5a1b","nonce":"9b3fe8025091827f38d76efe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"384c6c9ec256f75a4c601cb58748fb1424bd6cd0206301ec1c4b69640857c1f955c23d31c68b6738bb90813e9b","nonce":"9b3fe8025091827f38d76eff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"1ac13bac6a79641de609fd3a5d9e4303ba45a01d5765b6c07f1629a14f4cfe453a2a4d7017a3020ecda423fd4a","nonce":"9b3fe8025091827f38d76efc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"5197b3faa1ac0161e922ab884e7f6f0605e430194e491daebe7a0d2cf079416ef56e38459f5238697b4532a61d","nonce":"9b3fe8025091827f38d76efd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"47278fa91532b5b460a2ab7585172328bc2a716c4f996bd619919a0d8abbc64717980e7f3990cbeb745e36ada8","nonce":"9b3fe8025091827f38d76ee2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"907557e95a1f4f648bec70826a45880ff0a74befd98fbad39e7fafff6385f0b7071c599239748c481d15528429","nonce":"9b3fe8025091827f38d76ee3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"96f9109b1cedf10c8ac6afbd3311d6619d076915e987256991b292b0dd08eabd48cacdcccbec4038c802a35dca","nonce":"9b3fe8025091827f38d76ee0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"9efea62b2632767aadc669650471328ad1ac8a8c2bf2238a944ec9e520f2df21bb16845c22897ac57503c5897a","nonce":"9b3fe8025091827f38d76ee1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"a1c9946bc452c16552989e60d6a67a8138ddf780dcee3002c2d61318146576b0eba142909e74099ff149496611","nonce":"9b3fe8025091827f38d76ee6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"2b2c53d480b7a3af82a492eff16042235c13be8e24a09a7654be89ca51b07950fb6dfb2eb1a8a04c60a34fd5ba","nonce":"9b3fe8025091827f38d76ee7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"ccb1cb24ff24b286ac71c2be26d6ba9b273f1a645547d664bb2801515b33e496c94243772af942e459043576e2","nonce":"9b3fe8025091827f38d76ee4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"f813fb6364ea8ed6976af4a4d162c66a211411b0059e684c926f9b4401649c539c4f3a0360746c8d1012967408","nonce":"9b3fe8025091827f38d76ee5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"92ea4258428d3ad3fd90462af26a8effe409bda40a09a050becbb3093d8dbfeb57650aebf384e22f0572a433de","nonce":"9b3fe8025091827f38d76eea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"4735f3b7736dc653a22d5f0b684990c4d24fa996b446be32e24b8a4f5f70421d75ac59dda0d8cb70375c8e6dee","nonce":"9b3fe8025091827f38d76eeb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"073f6e9bf589f965aa988eabe18ba0ca5d500714400ba05290ce32f32d9cdf58f3039b55b0e27f039cab499ac5","nonce":"9b3fe8025091827f38d76ee8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"e0c6673610e1027d1b1c1ca30858dad3b713300719eba7293a351c5e440c479f9ecde3a6b7a2fc6a749ddc434f","nonce":"9b3fe8025091827f38d76ee9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"9feea90d3d66dc38b8d8307d044f23b115184b21e40bce1cd26a05191aa8baf4076b408716a22243b0a4d47a20","nonce":"9b3fe8025091827f38d76eee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"06943c002dd01988ff238a6370c7cbb4a9627c073070bc04f7b6688b0913829c4d417e0ce298d7146f43de5a17","nonce":"9b3fe8025091827f38d76eef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"60282451a06fb8e5ed1728c1a3c58e5c473d59dedfac1e6fb8323c21316e6dc4b4f901d4d73c1a61acc42f3e3f","nonce":"9b3fe8025091827f38d76eec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"6b6b27430eab33a6d8b131693238d38d0411d58d0843daf552a907db0749199bcca34ec3b10c3721d6b8a44a40","nonce":"9b3fe8025091827f38d76eed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"01c1724d03cb9cbddfecb227e3ac5f3f8cb3e44f80e68dfcbdd0d9dd6a7f8ee905e4ce3eeb2af292379f84d07c","nonce":"9b3fe8025091827f38d76e12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"12e824c15e94a2dac3c8b7fdf5e563366a796d5f9ce251c4473dfe5921c078bcddbdbe4246f77ed66272edad18","nonce":"9b3fe8025091827f38d76e13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"70953f7e5e9ee3bb80151bc80f77bc71b36cc335e3e75842b0577159a13374d969a5fec0a18df94887cddc0b62","nonce":"9b3fe8025091827f38d76e10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"123804b0837fb838535b1f318a38d53a7155c10edf369d6eaaafeeacffef9f2b068790c6e8987fe40c3d50878a","nonce":"9b3fe8025091827f38d76e11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"2756f450407eb224e3047224a530647438bdb473b0bce017906f8ca79e660d78e1a1e080d977c3cbb64f3c96fb","nonce":"9b3fe8025091827f38d76e16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"73cd5d4c1359d3e24bac752fce74a168764bd9d097075eecf0a5921927c773f8b1864c82158341d391f7ffc5ec","nonce":"9b3fe8025091827f38d76e17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"5b8ad2cbecd15a15d39ebff548626e022615edc2c8d6ec504587345cfe6ea483ec8d8e4c5bc8a66ceefab6013f","nonce":"9b3fe8025091827f38d76e14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"2930e798f46e01c2137a5b0627626c42b55370ef215b7b98d12ebfe67ecc67a3e70d93a39a9e66c1ef59340574","nonce":"9b3fe8025091827f38d76e15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"bdb46672099fff624d82cd63dcf7bb73ab7216e222a943976cadf8f160053669661eccb1af8c83249432bda98c","nonce":"9b3fe8025091827f38d76e1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"66384413f34d81c6a996d57ed36a76d0e2c44b83b4e7a5db7201f1f829a2d64c7338790961a8129431fdb25dfb","nonce":"9b3fe8025091827f38d76e1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"2493e1c749bf0c412c91d2842c3e4dba0281a348456205740218b8461e79a3ab91d4abbe8fa5c734f039120174","nonce":"9b3fe8025091827f38d76e18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"7aca5a85f2962d1693a05a5eae9d7a6da43b6ea50d0bf2728311a72b418bbe57ba2032faf0908a2f6884f1e8da","nonce":"9b3fe8025091827f38d76e19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"b28f5230475235b2188aa68e06368fba0f2068c671bb874c7b463eb4225eaa3d9627cacdead910cf8db5e5f93e","nonce":"9b3fe8025091827f38d76e1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"b1548a072372bd9513c68527da4321af566bacadc0dad912d547ef8cb6abad6bd1d615650571f1d59999eb3235","nonce":"9b3fe8025091827f38d76e1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"c3c159cb74aff290c47beea56c072516c7b4bb39ff35eb0398435ca1d0cc8a3328e39b2d4abee65fbabe97b244","nonce":"9b3fe8025091827f38d76e1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"cf9288dc9475e74906734f8fa226e3faa2468f0d3475c691fbb81a579d5c13b43639cb3c6041c8275c39deee5c","nonce":"9b3fe8025091827f38d76e1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"d04724a0632edda49811253b17e2661337bae04c498a7c4587f109fa592ccdbe635ab9187c2b339da0acbb6094","nonce":"9b3fe8025091827f38d76e02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"f67890066e4558a036a62b4bd9213ccf0f4315eb13b92c82740a074ade2af08b6d9ddde643292776b57a14e1fc","nonce":"9b3fe8025091827f38d76e03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"96facf441703e408e0865faf355a02758c10775ee2b7d149b0267e9daf58bef2e2c7274de2d958c15b7004be2e","nonce":"9b3fe8025091827f38d76e00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"cf33a1516e83abefd466d59f0a5ec6d8872535daff4504566ce2c2ace594eb987a3a9eddeb98a2f2fc974ba785","nonce":"9b3fe8025091827f38d76e01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"2fd8a978b63d73f8645fac2379487187fbae62e38518b27e838eec5259a18d2b031155e60b4d6c481a8d0c80be","nonce":"9b3fe8025091827f38d76e06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"ed1d129f802c3c633393acf251ffb6dba441c2733e1df334534aba99421ec125d79ca1ada0e734e533e9744fb9","nonce":"9b3fe8025091827f38d76e07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"c674bc14e82b7907896a3796452bcc303a64c385fba50957e1c3cb80e51fccc76c6724737070dad1b8e70f9940","nonce":"9b3fe8025091827f38d76e04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"1fa01ecbf0ec32e636c1885a006a64aa3cb027537cd81c66bc104a1645c02537bd675bdb8ce3c881c5a4af50b8","nonce":"9b3fe8025091827f38d76e05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"518ab81f918a28ff43ececef9b1ca226ec17ed4d864556276a19403e17641e866b2915c7a8073ba935229c54db","nonce":"9b3fe8025091827f38d76e0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"8ed0d21e34c840c8573a8bbe373444d9f4c7de6d986d2b7f660345ac7dc724813d292207be9ce30ab405ea7188","nonce":"9b3fe8025091827f38d76e0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"089a23761bae6e6c5bff00578a08fdda141788cb648b2390341d0dd3d4b958cd211b5d573e145b119afd29c920","nonce":"9b3fe8025091827f38d76e08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"b253dcc377dc56b26d0774a1ed6b20b5c1562a266944f1b65c5073b12c75686ceaf3822c0408a1d42ee365deca","nonce":"9b3fe8025091827f38d76e09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"ff82b678611e86502da003373d4b19c774c7a68b76fdeb517243226a3879e18ac0d6755d84c04fbb84840c5c4c","nonce":"9b3fe8025091827f38d76e0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"04b23baa5637dad5038a310115c6aea3f6d61f80cc6ba0f10962ad6194ded3c11183d5dedfccc65b2c76babe79","nonce":"9b3fe8025091827f38d76e0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"02777d684c5ac5422ba14d734c32b86e034a262b200b3f37a34260e9f1791b873b847efd0c6b17db85bbbcb2a8","nonce":"9b3fe8025091827f38d76e0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"20486ed6e30110ce155c20d469688b0d03017d1dec8cf04a97af54dc653b928393899a468ffe2e8c42b7975414","nonce":"9b3fe8025091827f38d76e0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"5e802a20b4093a1b8d896ff77341aa91bb3450c471cb97d39392ddba495086c238f8597640ff11a2c4f38dff68","nonce":"9b3fe8025091827f38d76e32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"26a2c19decfb847b1e96b13801cad812d69771668793cfe564840d477c329677d63dc9c6a98faa2341632783e8","nonce":"9b3fe8025091827f38d76e33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"4d50a4e389448228b0649b8ff0bfbb166255bc2045dc84e3388738e8baac67daf648f2b227ec8566e7f75c625c","nonce":"9b3fe8025091827f38d76e30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"30ddaa3ac88cc9489423ca5251db6f78ffef8626fb371f9019021f55a34cd164f4011db0c828d4d17efa2e59af","nonce":"9b3fe8025091827f38d76e31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"835446b5096a38dfe60fd071fd19e75d071c552900a04c074c84eb5e8b1595ddbfdb80cc4127ea55c726fbe23c","nonce":"9b3fe8025091827f38d76e36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"752026713bd450eba27f0bbb2c4b6ccb193f298ca6e0d1f1d32990478e1e19d49b6a3659500c30ce735a689440","nonce":"9b3fe8025091827f38d76e37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"bf289cf3a2235d2caaf2479f113dbdeabf661ead873536bb1cb8deb9408599d380557a4c96914eed8408b82403","nonce":"9b3fe8025091827f38d76e34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"b3e3e352157f0cc90527bfd974f34d2f6ebe089bd1c869d8db436148fe70d45eb5285bb2985d35e07be07e0732","nonce":"9b3fe8025091827f38d76e35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"b332684375fd7b9aea4ffac0826cd41bcf17dfa89d0377b11add38e9cad257d67cc0f0b8528fb85463a1d838ee","nonce":"9b3fe8025091827f38d76e3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"97cde9b479486dd1b6e7a86d23ee499774b38100d824b45db0c4a0ae54a6700cbb8f604cd2c0b74ac286b544fe","nonce":"9b3fe8025091827f38d76e3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"297816af036666d9dfa11a4f8808703ef07e5b8ea520ea8bef230cf615e2bf77a386cac7d872b84747784f868e","nonce":"9b3fe8025091827f38d76e38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"d1bbc8d12434125fdaec83a44aa17e6124797b7c6a2d7030e7c11e9270ee7fdda8e0d8849466e1ccc503581f4a","nonce":"9b3fe8025091827f38d76e39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"e06cc8838cba727916a896ac0121a8dbbb354d0b1f6a6d5d81ccbf2ceaaba0bafe069c79e41b98a24f06c20c9d","nonce":"9b3fe8025091827f38d76e3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"d8a93aaa6caab02af7ab1feaa36b27b2b578fb8b6ceaad928ab63b0721a14dfc562af8b4890dd76ce937eabd3c","nonce":"9b3fe8025091827f38d76e3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"4d71695ef8efa5d3a93b4cb7d1fa5fc54f0179c318cde9c292e05be7ccb09770b5ebfb06a399f42f857ec6b242","nonce":"9b3fe8025091827f38d76e3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"046118385f70a1a161d0661de8039e53584a7dd25796a8108d47309b3f45813a9ba24c230d650288d88a6287f7","nonce":"9b3fe8025091827f38d76e3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"b3d252319dbdd860c21db552b35ec3260b13ccdad04f4e8f8dd45863ec6ab78d925adf9663021d1a129430bf76","nonce":"9b3fe8025091827f38d76e22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"3877d6b1094deb27a222c9b1628096431be3694272cb2b00ba996394839972d9e263f7e7d1f24c02b1a524c32d","nonce":"9b3fe8025091827f38d76e23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"cbdb1061b9239f95442db62b26b217b2a18a5825f7a2667e0f10e286ecdac9b830d5d14b23fc1de10c813ed096","nonce":"9b3fe8025091827f38d76e20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"eabb5cac3c2613492603109a0deffe93078b5c294f45dfbd8e477db7efdda8c830f9a9cd97a07021626919e4e0","nonce":"9b3fe8025091827f38d76e21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"f8c59af3fe958302bd1b488489b71889ee04432b71dcdc632d378a96081eb55ec029426956a059dfbfbb19b110","nonce":"9b3fe8025091827f38d76e26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"8366aeb9c3535184d543422498b71806048027fa2040057a860b47abc6ae6384f26d474342b62e45a3deb34576","nonce":"9b3fe8025091827f38d76e27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"9038203c808d060dc818d072792946ceb3b3f152edc2cf8df3610fd9cb1531151443a3f33964fa1f28bb33c770","nonce":"9b3fe8025091827f38d76e24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"4ab919ca9dc6e770ab5d56e6388bebd6d260ae2fa80056ec34945ecbdcac4806912d18cdcebe20ff4524a943aa","nonce":"9b3fe8025091827f38d76e25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"70b7ce62c89f2d5d6ead02f7db796a43dcbd42517915e0110654c7986b5c02e1ca18e8e40ddbd9913b1d8083fc","nonce":"9b3fe8025091827f38d76e2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"4218c329d942b0b4eaf4493c7617eb692aa109ca1e540a58c0a4830878a95a96d249e50dcefe8ac75b63430b65","nonce":"9b3fe8025091827f38d76e2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"f6cc28a72a984295d925e964f20f4983d5842283f783bced46bdcadc175ecb4212bbc9f641e13e652c7b9d63da","nonce":"9b3fe8025091827f38d76e28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"784ca41a0e89fc2471074fdb753d41289cd0018384681eeab54502f54dca818045b90b9723bb8709c4539fbdda","nonce":"9b3fe8025091827f38d76e29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"a09c23c6b3314d7ea44b77c6d2ea009b04edfe561048becf915147a50fc9870fd5c3bb9afe1cb3e7dfbf23cc85","nonce":"9b3fe8025091827f38d76e2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"e16db283521589708dec9cb82256f21f7facf49903764c22b5fc0b22884923ea04dfe2ffbaa4a68a5008b01b19","nonce":"9b3fe8025091827f38d76e2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"6bd0f0ccb082320a81b89813f7c0a89c210ffca963bcccbd9d747483d193eccca6074f6e31aa2a1fbbd1894e3a","nonce":"9b3fe8025091827f38d76e2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"e517c7c188e9e3e7a1f96eec5fa51998d10cf65d7846a4c3ea2a301bc9b4339e8ff2e38b3bec6815aa3f9f0d16","nonce":"9b3fe8025091827f38d76e2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"0f91e094684af7cd3daf57569c6558180fb169d8aa32d0bf3f8dab0f902371c88304eb5ca5f61d7f86c4e987b5","nonce":"9b3fe8025091827f38d76e52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"727213d9d8da27ffddcfe71b4b6362f9796b929e96cabf2a023b6f3f005a4b58011517b4f6ab36b9664cf5efd7","nonce":"9b3fe8025091827f38d76e53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"5af63508aa2bbb35e3b0952a7dc4c8a32ff6ef87cdc5e53b3d17e7f021d0975254fe32b356b354f53bc1413e98","nonce":"9b3fe8025091827f38d76e50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"400985c7f9fa615342e96a7c1a17ee3b2951a4cdb0de92ab0a5ab731e53b3214fb5700fa3d1c9c65276ffce212","nonce":"9b3fe8025091827f38d76e51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"aadf05696ee9a6c489e53f5db1ec98ae417a5f53c15ffbc0d4cd58aa4e7cc8d06af64fb5ec55fde0b11a4b54df","nonce":"9b3fe8025091827f38d76e56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"b6e2cb77f755b12a3663767f00175b013af445282d6b0558795bb3b5568dbd9c9d1b6b0662fd1df65cbb3ab188","nonce":"9b3fe8025091827f38d76e57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"91018fcd3c4387c308969b2f0d9b77f113c6d55bc35770f23eedbe97d6747566c4b79a56dcdbfd218ed52d3911","nonce":"9b3fe8025091827f38d76e54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"877ba807a1ac7349fa959d58ad7750649340e64069fdfc8008915a013bb6a743c25a67198303c70b033d314add","nonce":"9b3fe8025091827f38d76e55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"6d5ad06e97b06d43e0ac25bfbcad384f008adfc0d36d24e477dea3f271d3720b398dded9aae9681fa951dfcf73","nonce":"9b3fe8025091827f38d76e5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"03dacb73f03ebb216097ead65daecd5d8f0fa98fe0b144f2b190c758d49a55e5d8cc44d639bde16a55ce3d1f3d","nonce":"9b3fe8025091827f38d76e5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"12472c66ee3712640f796af4c860f1260a900fa46f8417c73ab5ad9695cf71b5bca93fc8bbc7944a3a17c734a7","nonce":"9b3fe8025091827f38d76e58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"d9ddcde2aaf45ec01b5e08c96be1ee678ffc66a70b825d4f8c90a042dcd753af59d5596346c8e13fd2516f2421","nonce":"9b3fe8025091827f38d76e59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"396c69b426a4c459c5295386cc00444bf52e64a2366029ff8b3747fd0691292e00c95d4e0dbcb97bd96348dfbc","nonce":"9b3fe8025091827f38d76e5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"96e9b1892fcef4cbbd12356508c0e7ef1d5a90796b2b54f97ca99b4634904be0859d89d14b476fcac60ffdaba6","nonce":"9b3fe8025091827f38d76e5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"b5f2ca68d59379f323f4b78addf93bc688cfcbf43474316482af549dab4e5a312b55c61d05e65fe890a62cec8d","nonce":"9b3fe8025091827f38d76e5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"5b32efbb52d2088181d26d3213f76de142ce62a8d389a0758e7280e4c2b00808ef76adeaeae4299bafcaf599df","nonce":"9b3fe8025091827f38d76e5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"e58420b2e001772c00c1436ff2104393aa94997457d198534cf4c32809190e0bc545553df60d10105916da7569","nonce":"9b3fe8025091827f38d76e42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"574cd0bf342f9c3a402e660dc053e2e6e3fc5b0465b44496794bb4da06c9e27155c45db8a53c51a59a32912f37","nonce":"9b3fe8025091827f38d76e43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"88b92f35a19a37098d33bbacbd595f325d1acca7ea4d9f7788e1035fba7c032fd566f14d207b6b164d94453f02","nonce":"9b3fe8025091827f38d76e40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"02303989b19fcc36f63f1f469a78a620d2435dbe6839d0a5446b6007a76963f3d009a9e4bbac89c2fb32b8baef","nonce":"9b3fe8025091827f38d76e41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"37d07f2cefa2570bde6f2a0a7c9ecd1d0bff64a391a88937e934cba124d53626512e0b8fcee53a32bdf702736d","nonce":"9b3fe8025091827f38d76e46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"0c644183f62016b216a08f6bec95408b8c894bd5e8a87673235507db69c53654e5a6a3ece38f0a85ffc5c3f3ec","nonce":"9b3fe8025091827f38d76e47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"ed0d5870b9fd53f61f0ea32f4d98fba9f52d2bb10f2014412977a9ce5d87b7540e76267f2bc5ae0aa5d28da857","nonce":"9b3fe8025091827f38d76e44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"e36f8581b6c97ce6e6f44f0518690d79e78bf61376af07e149c21e04bc6ef38c916a3c30ecb755b015551a38af","nonce":"9b3fe8025091827f38d76e45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"c2c38b150ee75bf8228b564f3b1f268bc6acbcbf6ff7c4f33c1da65553f0af50b48a23c0fbe7dd59f12e8857cc","nonce":"9b3fe8025091827f38d76e4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"dad54630194d4bcd36065ef282a924905f41b4a30184658daed133915cb9d34540ca4fd4ac385887a3e1b8f805","nonce":"9b3fe8025091827f38d76e4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"e5894f1ee49116a3ce999929dc94f872a288b9c4193d026d7aff3ac0fb6e947cf2ddf324c43fbaef03cfc50fbb","nonce":"9b3fe8025091827f38d76e48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"012688f065aff7f49e4338b04c1082c3136ccead79dd8e75f1080fdc205b19d06509628f038e02ef6debcea502","nonce":"9b3fe8025091827f38d76e49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"275ed11f9cc532681a5d74af6eca61955407f1ddfeee28ebd514e702f83bd550bbd2ac637532a8b356855a0a2d","nonce":"9b3fe8025091827f38d76e4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"627eb9fb869faaf6854c3e5aa0db1856a185bc78d1a52f22f9b80843694bafff927bf7d69d390a3d8beacda77c","nonce":"9b3fe8025091827f38d76e4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"4391381b674cbae4dbbfb1d67a3742a48605b9300ea42cc6e235b6c3e74244aa2b97e5cfdf38637c99b6aafb56","nonce":"9b3fe8025091827f38d76e4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"ae783ade2051173699bb220d79389567ef3b3af0ca0ec8d8738ceb2bde88bc2bcb9af2789e82a82e72c057b3b7","nonce":"9b3fe8025091827f38d76e4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"b2641576e4c7895e0bd457559a41cac4c86838985950cc0b72afbba076570df6bffe81bcc1246d32934de3c3a6","nonce":"9b3fe8025091827f38d76e72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"550095036456ce238b2111e1901a57445fb0446f5ca13b3b6ce65bd0dbd47b68932b77cd77f5aa4187d2ab27ca","nonce":"9b3fe8025091827f38d76e73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"951339ba87b3bd1ff5210c4417205062bb83049cc989e3cdd311976be212adc417a0eb4752694c5bf9aa016d7f","nonce":"9b3fe8025091827f38d76e70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"59e209d55c81491a16dfe2d94204f14bb5b2093dc5ce87902d382b358f56dda002c5d628fa287b3466dd91aaef","nonce":"9b3fe8025091827f38d76e71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"aa94980387c5fbecbd3bd8750c7c6161ce727d5d7c7b70ceb51cdd437c9ef7e1de3cb3a22364a6c58397f0ba27","nonce":"9b3fe8025091827f38d76e76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"e9165e2ba4af77b8a32b5ebf838a52240fc0186316f83c5b9f0d60538ea78e4bbc46aa47259369394f5cb4d869","nonce":"9b3fe8025091827f38d76e77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"da573ffc18e6cbf3ef244a4dca22e74519c22ee5dc9652e2b698472cde8a268c20a631bf746280708f6340e290","nonce":"9b3fe8025091827f38d76e74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"78ac473b85e2a5fbbcf5107456ac0411aaee5c6b91f12b454ed785c32e834e3b6fbb53735d192db7431f75979f","nonce":"9b3fe8025091827f38d76e75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"41b06d462a0e4a58f569e6f7083d0fd5f14c3ba558e2a69d1687dff812503462a8c3f592f81f7a9c8bfbe0ff97","nonce":"9b3fe8025091827f38d76e7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"fec5a49c5cb350df79236fe5fffa53e240215d0717815f5ebc9fe8911187c719ed3e7bf2a9e8442392d5d2c969","nonce":"9b3fe8025091827f38d76e7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"511dd758601b804bee151e05375b7bd14f8170158e0a088d7da09ce3ddcedb56be13a218ee2f0e6c68697eafce","nonce":"9b3fe8025091827f38d76e78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"4ddfd4a80d903cc8d61fd3457a70ad099ce479104cd3c159f1ef54b906ac1d507d7d3a63dfabcb27047bb26158","nonce":"9b3fe8025091827f38d76e79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"ef650ecd120030fc93068b93f24855e872ebcd62016a9bcd9d26789ac720ec67b15dfd17a689adeb681a8f8cee","nonce":"9b3fe8025091827f38d76e7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"09dc5c3f7b4fe644510433f0f7587008c10f79377313fcbc8fc7a438f216756e2b249079de2c99a648d9a91293","nonce":"9b3fe8025091827f38d76e7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"a47a5dd5dc50babbd80008dd8d9a0780ad6a6dd1c7cc1b9e233351ab2ee359cfedd5a0be715d1ca1f267fafb02","nonce":"9b3fe8025091827f38d76e7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"2edbc27b48234a84145e80e4144c722ca20c280b036f45d21ee349d89b4e5b585c5fb8eabee5c54eab3d118df9","nonce":"9b3fe8025091827f38d76e7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"eb1d7e8646edc46a16812fc3c6420a8de23179ddfda7964c58c0f5095dda1f110307b0631f9886650451b91cb1","nonce":"9b3fe8025091827f38d76e62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"3ddd7cb5c115e151c24fcb5677b1671950a28a6dd2624d76da5a0859007d1d45c82350a4dc0c27c6aab1ff8906","nonce":"9b3fe8025091827f38d76e63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"18a404bfea3c965b3ff3d5ebf30791c6ddc5a128443e343c355779a9e969b372bcb5322fb8e3e3b73875e3716f","nonce":"9b3fe8025091827f38d76e60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"36515dd7224d0ee5144672436e7a6123e703a1bec1de9b0f643ab1004eefd89652fa17e36102d3b3a69a1dc8fd","nonce":"9b3fe8025091827f38d76e61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"d4c351b541bdced30ba140ffb5e720e3ee1196f2dcaaf7c6a65b2a67f88bb2d3740f024209db1308a66ac4c2c0","nonce":"9b3fe8025091827f38d76e66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"0f95714cc8de03edc0e5a11bddcb8eecaa7be5fd5915ec3669f1a0e4ddf978bd9626f80ef771607663d2d98fbd","nonce":"9b3fe8025091827f38d76e67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"36ebefd76e34953e006df893765b4664527fb317a00e1a016a1fa9a70e2a7e2ae30c2a67d9a4394484dd63a5c3","nonce":"9b3fe8025091827f38d76e64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"90642aa6c9c033c3059ae12c4b89113f2093e239471cc02cccdba21c7a0f2a50d5153a81c4c1d5fe06ac618835","nonce":"9b3fe8025091827f38d76e65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"071e084e1151945682766de3112355f16e5b88a4f6ad379cf53a19ef8176d37c87d95531e6316f7331968effb4","nonce":"9b3fe8025091827f38d76e6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"27b078bc6119854e088262cc59bff01ba85a332658d925accf382803384a262d8339ecb5f1a366c4bebf3fe73c","nonce":"9b3fe8025091827f38d76e6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"34926315b7d922c130bc585ff02083df116a0698fde26a224606e6dd8778b53b3a8aca1a00d85ac3b646e30788","nonce":"9b3fe8025091827f38d76e68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"69050b4c7a1ebc34313dac74e70a0ff44a6480fcbb1a93f367598d4514dc6cae575c1ed49bd111432edc047733","nonce":"9b3fe8025091827f38d76e69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"39167e3ed8a92da4fd389aceb59699f402262f4ee5299110303f125adb668035593632029807ae151540099da7","nonce":"9b3fe8025091827f38d76e6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"b08964d89c56b6ecfe7e75ccb5ddea592d6c8bd1edbebd2f26ca1caf0c3c723ff02fe4c111a9b49ce319033939","nonce":"9b3fe8025091827f38d76e6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"39c6e35ad5c7ad3e0d5971bbe6a5d305abdf672cac6265e3ec8d4f4a844bd0e7f8f14a1cedb0d4941f6ac2ae52","nonce":"9b3fe8025091827f38d76e6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"1f26b0232973db7616099d0067cad1b3e93b5b1273c9df792aaf254013b5e3deffdfcf0f4c33df5292636b819e","nonce":"9b3fe8025091827f38d76e6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"817b3b3c07dd8fbe7a72992aea320a1ff01422e93852a3617a47d5271f46b04c249aa813ddf097747a566235df","nonce":"9b3fe8025091827f38d76f92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"847432a2d508c7de5ed7d347611239eee4de34926754b5ae75db760517e0a48f"},{"exporter_context":"00","L":32,"exported_value":"e7f90ecaedaeb1bc3df4f1a365863206785f2c0358280bd8112dfb7574803474"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"82422ac492bdeb4fd4eaf7872865c553cbc0aa3d184f8611d3bd25d7d21b9d04"}]},{"mode":1,"kem_id":32,"kdf_id":3,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"79c8b6c8960ccd6c3e52bff62b38e6d2b37ca01be391fd01d3858d4caabc17cd","ikmE":"d7b36188f6134eb54dbd05d1aa6459facba37c12a8e492e5d835e9cb029524be","skRm":"ecb2a337f56cf116f01524d3ab2a1c970f614a97b731176afafa29e8f88da58e","skEm":"544bdb78a645a86a30e322b6c2778d0399e5eeac383f2fcad020389de38f59ca","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"020f94384faff781ca7aa6a9af690a6fd87aab48ec3ca4f37e2dcddfed5b3a6e","pkEm":"0a90e9401c144b93db691299e3c8b308225d4df532d47de07907065ca3d69c1a","enc":"0a90e9401c144b93db691299e3c8b308225d4df532d47de07907065ca3d69c1a","shared_secret":"b41d340c134963a007baaa72b7d901fee818849949cda22b3c3da11a90bf6c8d","key_schedule_context":"014c00167e070c0803ca14469cf4fa24410a5c52e941fe6042d618ec513da1d7689535366ec6bd0534307b1d59b0a605325c437890fe56676a1c507b6cf5e46e9e238f3e66e519a887ea3a0d096475a5defe5bfd1d22ec386b880d050dbfb6995fe8f7d1d0c661c4e10698687f757b1e981cbf025920074204ff660b9f490d7594","secret":"3faacc67dd8a84492ad96b8391feb77f37f8eb0cfff66967d3a06a736435bd823992ebc54950d475d637ac79d7e9a86b7dd14176033438ee87ccedf5d684ad93","key":"4fa99d3ddf919af9349866a12a9aa4d1cad6a1b9cdeda2fb1feafaffdd374fa5","base_nonce":"8a0244cf0f000b92a539a7ab","exporter_secret":"60c08b4cdceee038a6b4aad58dbb55165d54b0993ed443d8dee83b6055d08943f75380b8eba70bde4dd3bb108bcf37cdff686852eb8e240fd035d44eb3f7cfee","encryptions":[{"aad":"436f756e742d30","ciphertext":"e047eb35ce40e00d40784871c3f91a584f3370ce5ff8cb645e66b9476c46355996568f73a87f9fbb329f394d37","nonce":"8a0244cf0f000b92a539a7ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"e4918bcd83e6220008cbf08da9095ddd95be0378b4b9808872f845a4c051f34158e8268c7f0700ba4d174a2df3","nonce":"8a0244cf0f000b92a539a7aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"afaddefe60c53238146d758c47fb6174fa0468f678a2147018b44cbc74f916f30a5e94953a0c5daab8656f4996","nonce":"8a0244cf0f000b92a539a7a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"287728d1de26158883e27224a8869d8a0dae825b0780bbeb54bc0ef3a9dc3000e0623f19eb8259e8dae3e18f25","nonce":"8a0244cf0f000b92a539a7a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"2c36580e20f3a7e2f4383c5b836df2668cb455c1d39485abebb6719fc869d4a748f101724f6903a92417df566d","nonce":"8a0244cf0f000b92a539a7af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"5e0b8f68f08b1b6fb3f1f19b6e660a2d351b3416eb6eaa655085e85a1dba95c53f3a67c08e71345038a54057ba","nonce":"8a0244cf0f000b92a539a7ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"710f4c884bde6ae3d17c6eae6547a91ec47fd902d13b499c35599486e0a02c0e21ae7579a957fac32e8001a5b7","nonce":"8a0244cf0f000b92a539a7ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"31aa8fdadea696d9878160bd2af5978350ce9e574afc7024029763432e22bda1322c4ea1aa97c425a5fc7717a0","nonce":"8a0244cf0f000b92a539a7ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"fcdc89154e17cdd45463d25d3110644142fa31d3bf8db5959779aed97d01037ce45928589e55ede0b47cec574c","nonce":"8a0244cf0f000b92a539a7a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"25913d45720e81a1e3d42fbd293ab1f506558cecb072ecb0a33e166fca3194bd7f52827de9778271d84eff38bb","nonce":"8a0244cf0f000b92a539a7a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"207b24c24787481a50f702a48734a9cf006080ee2fa54d31799ce4550777c1b9aa53b1f9c6c0a4d22cb3c1afd2","nonce":"8a0244cf0f000b92a539a7a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"9885802fe818acad2541f8939cc6ef92e0b82ac96529b6c701a5f8ab196fc3baf877b77c7c86bdf3ab8f4a9121","nonce":"8a0244cf0f000b92a539a7a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"56759ce2cae90023d23c96910ded636340bbc6317886d243a6708f9a0cda56b9310cf620d459ef50e761992b38","nonce":"8a0244cf0f000b92a539a7a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"3bb0724a8011570cea3286b69b19b4b842c40c37ac0585244748de72e473d0b58220648c2d388400218c97dbf5","nonce":"8a0244cf0f000b92a539a7a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"534f7dc59c780521c2e62973fd0447dad9686145c96b2db99229dd8e645212e08f55ae10494791a8e369f43bfe","nonce":"8a0244cf0f000b92a539a7a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"f40408e56a5d30057c5746557a6ef125a533c748ea9d6084d39072b98c74b0668cb22f441b8a1f249f2e80ce53","nonce":"8a0244cf0f000b92a539a7a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"aa871cbc58971c1ca675c3f1c98b9ec7de83c1df7ed09ace75d6b910a4e3c516812d58d572e9ae893270400d90","nonce":"8a0244cf0f000b92a539a7bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"ac9062aca921dfbd1e80dfaab5eda32d2b1b2cbca77528cfcd972c6364540c8c6c739c679b6ad36e4312ca3acf","nonce":"8a0244cf0f000b92a539a7ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"445c5e4323a522f84f5a9f79d9100c527e57d8960d3805cdd85d78b5f80cea1e4119e54521672a557406b613d4","nonce":"8a0244cf0f000b92a539a7b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"f098f11b7cd697ae5618ce0e83261a57f3bee0e912eaf9a545f2ca4d314096de0eac5bae1fe65ee11df4667132","nonce":"8a0244cf0f000b92a539a7b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"4b9dd2797f562fc77b1823ccdec2e54fea281a7546ff6f33515274beb664136a0ba9be99d76fef728b7648ea83","nonce":"8a0244cf0f000b92a539a7bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"7e4b94ac4f8f253ec39e2c0db605378137c712cc0112da7c863b50b44a4a02d8663aa74ded1ed6f2f9a8131db9","nonce":"8a0244cf0f000b92a539a7be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"1ab6d79c9dc831b2c20fdca92bb566a4a5a68bd2e0952c9d57fbac7a84703a4f2797bbd729895d1d4e89fc472f","nonce":"8a0244cf0f000b92a539a7bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"7709f701d69036fe5dbf3c237fae9c871a71f3fe714032056cbe2a884f9698c5bb3708e603a65a1588e250146c","nonce":"8a0244cf0f000b92a539a7bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"5577db783dc20cf6a6464fade4b445e3597cae4cd9c21ee0f6f7407b1ead68e6de254d63fd2d0ebd371b5361e4","nonce":"8a0244cf0f000b92a539a7b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"2a61b3fd7db45bc374f2d0dc3d76a47c0f174a83316c484350409e1c37dbf3b01fc7b480c3fde9b3daacf8b2d6","nonce":"8a0244cf0f000b92a539a7b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"5ccc1528a28f543010e4e0a49da0a9e85fe91e4190063af5f8122ceb1e6402477841f75faeb57ce881081b8c0d","nonce":"8a0244cf0f000b92a539a7b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"1ebb2e3aa5183eb6e1b5cb56f6c00f577dfac1953c9915b13c639854e38c799c399eb9a9d4505075952d40fdc9","nonce":"8a0244cf0f000b92a539a7b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"5eff8a39a9a9c1a63168b881a8a7c91167a9a0b05f249ad11bb60faea258220c71db7db53f1fff8f18568fd5e0","nonce":"8a0244cf0f000b92a539a7b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"4749bd7ef7a0369d2989aeb7b6fdf2fc1cb87f2407684e16a696be8c5740414565fddec3fa61a1a33856a09e91","nonce":"8a0244cf0f000b92a539a7b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"14f4dbc8b1abbafc8f06015c819f1b9a8aef1f71f297a19038cf8acccc66c13492faef70c3bde039f6ee2c309b","nonce":"8a0244cf0f000b92a539a7b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"b73d249dc86553d45aa4f2aa9fe27990031ccb2ff2336109755b43ec692df8ced3e4bf92a5625c91178fef37db","nonce":"8a0244cf0f000b92a539a7b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"041aedcfe640b7b67a1a5bd5075fdaa0d8d697911c4907c0bdfe04adef80da491bfe036d749a802ef230784c56","nonce":"8a0244cf0f000b92a539a78b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"05c9a704dae5abb5704ca37e0c9597880af6f00ed9c62ae2472e452ba5be185ecb56c9da8a7492926d48aa73d0","nonce":"8a0244cf0f000b92a539a78a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"29c73ad3ca2d109d9ffb7ca764da0275d4fa419f9d1cbf8cb58dc231865543ef00a7015665cf591fd47403a328","nonce":"8a0244cf0f000b92a539a789","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"5fbbcf3a4d67c448c4d32eb64866360e33c0bef640fceb35823f10b957293643c5359c400c05865304aad66f84","nonce":"8a0244cf0f000b92a539a788","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"147d4cf95da77e2229563fdfa6b9bc7204d63bfc0a14b27ec367846ee9704a80f7698e8d22c9437f3f492f7d13","nonce":"8a0244cf0f000b92a539a78f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"a6d5b326df4e8d6e8eaaedb55a73cb675f3be4a2563d9e20890db30b012cdb929d824cdf0407ab3d9dbfb62d39","nonce":"8a0244cf0f000b92a539a78e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"23d47abb1e7dfd86d9494b1880ddeb2f8ea4a023012e29dd8ecf1cd5688e6e9180f0b68b275c72e6bb9d8e7108","nonce":"8a0244cf0f000b92a539a78d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"f9b52f97a209ee0c082b908e20e970c68c4fb199988992d353faf56ec2ce7fd728396fcdc07f80a1eb857c410f","nonce":"8a0244cf0f000b92a539a78c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"3c4e750b0e2faeeee1535bb737bbaa225d749fd00b23a2e3f8bcf266752e5a5e498f1723f80c2557e0303687a7","nonce":"8a0244cf0f000b92a539a783","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"2b3e239d748b3087635b21a8005616b400553bb99697340ec1b2e505242ddd5e1c94096803edafcf97a2c79e68","nonce":"8a0244cf0f000b92a539a782","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"5441b827835c397578b17cc4a022d920a52c5ead9ba77ffe1683814a60f819fd3a0d2c413835f826f532850239","nonce":"8a0244cf0f000b92a539a781","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"93bbdacd86736b83ea807e4c6067b081d91dae092cb8de91e11832ceee0b90b7c9c6f370b3901730fa9fbd0bdf","nonce":"8a0244cf0f000b92a539a780","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"4b0c46285d894f5ab500f41ef0c193dbe86f99f25f13a555b71d7bd8f1fe1ae83f8e4b6d4228859fa0b0c85bd8","nonce":"8a0244cf0f000b92a539a787","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"e012e1eb07ef0a4a379db62fac2a68ab2c4ce7630b24cbe6c806fe19f1f906135db6b7e800a58815086adc1759","nonce":"8a0244cf0f000b92a539a786","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"69a5b1f5fae40bda59c0cb3665fe0b2ecfd2059a733495ef8cada47770d25e0cc3e79ea0957933bbde80393593","nonce":"8a0244cf0f000b92a539a785","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"c503a20504f7ab111cf361b378d4b63d5e0b4960010f9d6c4a332958d046a90f634ba2a1943d7f6715695fe77c","nonce":"8a0244cf0f000b92a539a784","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"c936ab64af6f7f0dc4ac199b67173faca2184af255f0a32ddb822fb592c61cd489f23aa8131f143a87e7daed3e","nonce":"8a0244cf0f000b92a539a79b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"269747b90eb39eeb3a765a7f6692871f715d8b7619a58337f38287653955101e153d5e5b0e5cfc5fd4360af79e","nonce":"8a0244cf0f000b92a539a79a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"ca7a5856017ae1ea7674f84d768e5f212853ed68b1274aea034f47772c06846f15e614eaf8cc6594c8b4e749f4","nonce":"8a0244cf0f000b92a539a799","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"f79b74bdc7b3714fe210b235e83fcb9ff980406ae696c9d66bf54a71ae9b16f4cedd68059a2bb770d40255452b","nonce":"8a0244cf0f000b92a539a798","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"ca6b56328fd3fae7d990ad77d8cd5786d7f93d2c54f85ed68eda694899fb17d141717320a8e1c0dd97e8a6b373","nonce":"8a0244cf0f000b92a539a79f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"ca12f838f3e203e9bbca3d9a22a1cb698cb61f407612a9be181a869f37c9ef2a6b5f7405afa9acdadfe94c36ee","nonce":"8a0244cf0f000b92a539a79e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"f07157f038fd85f97356564253480eff52513deacb1e0f0b20d74caa24de48f6ea89abc14f22aa726554ac2cc4","nonce":"8a0244cf0f000b92a539a79d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"4d08674c7f6a9d63a15139ba2e6950523835beec59c42d408e226b3423996021984d0a61d794bbf59194743db7","nonce":"8a0244cf0f000b92a539a79c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"d1ad338db5f955bfeb4b0b4b0e5b84393c2662c203b137d55cc2c640a47dc36a754cf6efe2a585f3b62f5e5f4f","nonce":"8a0244cf0f000b92a539a793","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"d3d3190aae47d05c743130725bffc57d7673fc3b8cadb5e38f35f8d7691c6df9b7d43da742c7d359572f026d62","nonce":"8a0244cf0f000b92a539a792","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"7aacd5184fbd4101bc84cdb8f32de67a6684192e4805d9271cce5ee98d9b5ecd4aee294399166acdc2d130e0b1","nonce":"8a0244cf0f000b92a539a791","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"3a2d0f9b1b405c76d365f733970426375e0c375c7ca36dd434be95a9efa51cae1cc5d21011ab9c35e746f039cd","nonce":"8a0244cf0f000b92a539a790","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"4f1f320b00971d294b29412fdb0b5c94352e98a5f947ec05f7ff9e589d3c68314b5d5d743f779911a3615a76ad","nonce":"8a0244cf0f000b92a539a797","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"97c04ea6ca36abf66bd1e5e824099f4b0e14ae8d8d1bd517b8239f622e80e3eefd86f67b74d0a468f18028ad1f","nonce":"8a0244cf0f000b92a539a796","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"3bbf67f18e738d1b64e382a2f46a23252732ff274c890d239493268b0be2df908b53b589610a0aa00a0c633f44","nonce":"8a0244cf0f000b92a539a795","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"6da00831a53067e3d5890adab5c8ee9a9e4a7ee0c29e02fe148d928ad2ebdaa0bf05641b4244a9956b296453ef","nonce":"8a0244cf0f000b92a539a794","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"f852dcf49cd1e27704d3a132fa8b027409ccfb06ffd8d23b7fa0bc4f03ac55a995ec581c6d144c86306f388cbb","nonce":"8a0244cf0f000b92a539a7eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"c5ce38c62291f648d51fa27e3fe8a7aa3d351a2bbc4076882a9c262d2e81d94f6d4f2b7b3d8f27ebd77b090090","nonce":"8a0244cf0f000b92a539a7ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"fb6ee1880e1c7f5090a16be6834267d2f464b1460cbab7794ab341e68f9941951b4b116a9846ed63bce6f77867","nonce":"8a0244cf0f000b92a539a7e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"1a6807bbf7c61fa52ad8277006ee88a43e52509ddbcb6029e04b421623fa2a4c92f097c54f7edf683e13e64854","nonce":"8a0244cf0f000b92a539a7e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"d7934dfb89ef9f5e8776c349d97fba1a0f86938efbc1cd76357e4eadb23300ebd369e708e19cea455568812a43","nonce":"8a0244cf0f000b92a539a7ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"c4ef37163faf584b6ffb093773c23433fb954e5d253595490446043988bc9f7deb8d1f020b4390efdc5e33beaf","nonce":"8a0244cf0f000b92a539a7ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"e5ef6fb7bcc3af9bbd8865f02d5b7bb8e1a19bcac1a33bba159d3f9d101a9e9d1236d2e055a562cea9daf73780","nonce":"8a0244cf0f000b92a539a7ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"8f50239df1a48a7f90b867220d030c07e765345d9bf6fd3bfa65007b10381d691bdfb229fc9f9c2ad0b026328f","nonce":"8a0244cf0f000b92a539a7ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"5d3e47a3a8e5b6eeeae6cf6161826f96fc177b14c213b99127a1f22cbc011bf3776da2fdff51f0f4a27661647b","nonce":"8a0244cf0f000b92a539a7e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"3373974fd6873a037b5dd08fb226efbe1549a0ef309a68feebc385501d16e10f9cbf9be6a46ea6b767f2e9907d","nonce":"8a0244cf0f000b92a539a7e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"7a18905cdd9ad1f04dad462c310bc02b7fe68d56a7283160711d06de3ea41e502eaf3ccd57b7aa6045eda2871f","nonce":"8a0244cf0f000b92a539a7e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"1de097701852566629bf4e0f9927ba2e229fac815aa5932a103ad4d64f83c5433c5f5b699bdee7cce8d1fef6f4","nonce":"8a0244cf0f000b92a539a7e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"011bbbf1df9745eb28d8e095600ddab2cc44dc80b2a35752586497017b9697a14c6beca949163fa01b1ee5f745","nonce":"8a0244cf0f000b92a539a7e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"fd022902bcd1fb3eebbee41a97375a9a074cab905e012308f49773ae02f751c90e572b490aa27cba1809acfd45","nonce":"8a0244cf0f000b92a539a7e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"3e793b3585c0124aeeb4781d7cb03c83d910996c311e15fc7b10f1488276ebf46c62ebe07b7ac9f31c33a94614","nonce":"8a0244cf0f000b92a539a7e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"94141cc1e6dea96aa222327f59d4004a7a8f94ecfa2ac8c5603352a437985c2377d7777ed0023ae5668495db08","nonce":"8a0244cf0f000b92a539a7e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"176b9ced0aab0c11fffeae10dfaf15ff073ceb573adb7d2f7d99efcd48c060243b4165dcb6c629d459c34faec5","nonce":"8a0244cf0f000b92a539a7fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"12ad1fc3c1d0f0f32a7a02479a064b502e5b27726b5007048d6f9b2e9815b774200207c204999fb2d79833d2a4","nonce":"8a0244cf0f000b92a539a7fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"2cff33729fc770f319c432e1b121eb40bb6787e9147bf8dda29976cdd562ff246759e62b73123d7d19b46d1ff7","nonce":"8a0244cf0f000b92a539a7f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"6288630ffd73cca19d289ec6f0263d56c84f515bea6a4c4ac1c75c4e763d15181a81e3f98926923dde60346103","nonce":"8a0244cf0f000b92a539a7f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"47b156a2d26b07951f68f0eff1d9dcc35c628041c186edd969ccac46f9ed441e960aaa87816e6052ec8ec1580c","nonce":"8a0244cf0f000b92a539a7ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"34cfc6a438e799e058b7831b032e7299114738b62c006c405e9922575a3ec06b58b6a46003f17ca86d9fa709a6","nonce":"8a0244cf0f000b92a539a7fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"7adb4d7b73dba903bb6f8c5eaf52d5e0fe5786515d0c4095a6237438be494dc1a14069db2296ac7a1dffd1d7af","nonce":"8a0244cf0f000b92a539a7fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"8e3db56ac97d7f8ee5550d9df1b972f5aeacc64aecf298208600bcd82a3bd8d7e49f2950e644526c5bbd48e2a0","nonce":"8a0244cf0f000b92a539a7fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"5f2503aaf21ab57c1a7e18d8a2a946550e9b427f1fb26b9ebbdb8c4ceb1b8cf7efa557356b16d9e7ded6d1639b","nonce":"8a0244cf0f000b92a539a7f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"5cb300b57c7094b4eaef3212a7bce6aa08cc8276d86374388571b60b5d1fa0eb0955ca6b4a089378c5aaaf7191","nonce":"8a0244cf0f000b92a539a7f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"3b94c66aa1486b6cec8b651f151e59e0476bca9d0501adb9e9f71467ce9c3f2dc7bdfb83fe02064c34e0536492","nonce":"8a0244cf0f000b92a539a7f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"5f48b4354de5e1abc234965ef0feacb473922e25e1e98eeec3482104599f6d8ad4e8e9d66c0a2850f89ee6cfd3","nonce":"8a0244cf0f000b92a539a7f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"94d3d0c3b6f3414f8a81b439a1d5dac580b3e2f438d34129761c620c7407158e3883b706edbdf1e7803964bdc3","nonce":"8a0244cf0f000b92a539a7f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"05ea9eb5f3987e952b059c42d5c9f5d382a7a54bba175f19955754a67dffd8edc2296070e5e06f78f3cecc33d0","nonce":"8a0244cf0f000b92a539a7f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"9a07f59c48d26d011462656b954fcfc13f4f67534d275820cd90df4c750d23668b1ea89cf76013b5d01e31db74","nonce":"8a0244cf0f000b92a539a7f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"b0dda1055e31539eccccc3229908f11eb0b45f20af9d7c818bed71a246210a7a07943631c345ddee6dd5ecb90c","nonce":"8a0244cf0f000b92a539a7f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"a122d1bd43579191f629a85929833f2d98ffb9a7fe9c82612ea1e7d3f4985cadde1df20420ccc6e46a3993b5d9","nonce":"8a0244cf0f000b92a539a7cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"1b3e8a7398e0b7f7e95bc4525e29c8e48289c5c27b293d2af251e60347d518b6a7791ab5ed80c69e118bbc9c39","nonce":"8a0244cf0f000b92a539a7ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"ff3569fb79bb31f7f59f1c723f7ec1cbb7a9bafa0571c7a686d3d658c526fc39d55d6ed3c8e77c7ae4540c8b57","nonce":"8a0244cf0f000b92a539a7c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"907af7b10ef1c2b97c2f7ff93bbf79c7b20e8c2579cebcce9d4175800bc6f6049268eeca1621faa320e61a70c5","nonce":"8a0244cf0f000b92a539a7c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"5dcb8ba12ec68688679a84bf95d17cad393126e11c36f8a6c9669b4a69d4a428505e74c4c741685ac521707f45","nonce":"8a0244cf0f000b92a539a7cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"22918cc5b0bd00b39b73bf46385e2fe872d9a93ff796dd0f42f3316540f59883e13ac0e80e3323e61ea91e0cb7","nonce":"8a0244cf0f000b92a539a7ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"1e3cbfdef301514ab8a05a5bdae2f867d843b776831d7734de00acc0ab33c24bd61f23f8333196941819a6a5dc","nonce":"8a0244cf0f000b92a539a7cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"48362843d037b2c44622d9b35c41d404c280d03c5601f8c13c87fe079d1b52f910c93180ca3d5bf4d538f1d34d","nonce":"8a0244cf0f000b92a539a7cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"b7c7e0e3177e30a4860e8ff0d833aac9103ec3b99b47cdbd70533cdb4f36b8e01e0cdb39370f7254292b60864e","nonce":"8a0244cf0f000b92a539a7c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"61fa7310333795a3701a8953255275cacdc9c66245c90ee1fc86ae53d338b0a84976a29bfbddc849ca39bd3411","nonce":"8a0244cf0f000b92a539a7c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"e5dd56c80e93e9ebe923fab16b882d8aa0249a97278de2bcc454e1a3efc5afe9969a910b2efb6de30971064216","nonce":"8a0244cf0f000b92a539a7c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"30c2c99ebd3118b2ca892f05984280e95184369eeaeeadd0a8ce808ecbb3946f75f3fec2171d2e736b2caa1bad","nonce":"8a0244cf0f000b92a539a7c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"3b06144c7f61f64d904948f2246fc498f4f083f267b7fcfb7571b94c772d4a55a151c59587338a5682eddc2bfe","nonce":"8a0244cf0f000b92a539a7c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"b32d5e859e83a353fdd1b0ca385d8cfd45a75f6a9168c96b6b53eead037dea00f67271b210558fad52a104b882","nonce":"8a0244cf0f000b92a539a7c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"b2a2dd370690cda9b1ab75012f09e822dee622e12e0990d2d93342eca798cc3081d1ea68c95b7031f5d0b68b29","nonce":"8a0244cf0f000b92a539a7c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"2087fc80af522ae4b9c7409f35c6748e7d8d63e558cded354b9965ae4bddcbc22bd922fcb9cd6223126950b94d","nonce":"8a0244cf0f000b92a539a7c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"34fc07388ed1f849cd3fb343b4d69ba34cee3ba5165e11e90f5782e43ebd81baf0e3eb6d7aaf96d32e47195026","nonce":"8a0244cf0f000b92a539a7db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"c9558fc34d9cc35232fa12ff2d915a93edd947261d75ca04594e19c8946511b3678443e5df45df9ab3381438e9","nonce":"8a0244cf0f000b92a539a7da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"7dc51986286ddeb5e1efaa4b0bd8673b00acb10ce2eb95de6819417cf4a87d0b9c2cf9c821fdfb351ac7d05d9c","nonce":"8a0244cf0f000b92a539a7d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"d195d5eaa17b6cd02c8049f1de434a11268f3d9d9d890c3fd2038ad2db5f43bd5a6d7d5bbbe8109e4b132ce0b1","nonce":"8a0244cf0f000b92a539a7d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"5f6ce66519cae44cbd3e0e934e9aeaaf5ac81b21e2313534f49961e8978ec4416c0647bcbe7a5d04899b86cde0","nonce":"8a0244cf0f000b92a539a7df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"3ea4a11a86130a33d1c601ad5f3d6f5e1dafe97602bbe5a8fd3e139b7c67368ee26a9daf9b6c3c352df1ebc49b","nonce":"8a0244cf0f000b92a539a7de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"c81f34c779509c7c8555e34f3e447c7a079007a463af605a9d2cdd8e02319721dbe7778d91472df675460a9423","nonce":"8a0244cf0f000b92a539a7dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"82c972221ab4185e20f2a2a8038cc5c69885c61291a91082d4a5987cb9665ff416d31d078e9853c01064c49afc","nonce":"8a0244cf0f000b92a539a7dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"c5baeaa3fa3bb04d007d9c17f43f3acea3295e570e7c3413bfe313233a0e341db13713061680f59fe7dcb2027b","nonce":"8a0244cf0f000b92a539a7d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"468b4d8f3524a2356dbe432dc3652972d7f2c4485f12fea3277bb9ce4f502933ad63c8c9b165100012d62ab765","nonce":"8a0244cf0f000b92a539a7d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"dc0b4ae9f6f96479cb8abd65812932c194e77ef21ea0bc77806e8bbc49473f273ee9dc2318c56dfc27256b4b86","nonce":"8a0244cf0f000b92a539a7d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"76134744c3517bda223cd6e82528fca6b5ccd315c100c519a93a3510722bf4b0cdd61382d721e01f8489627d31","nonce":"8a0244cf0f000b92a539a7d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"5bff51268f15797c85ab43bb9f83bc36fc184a8d4b48b6ca3ce298f83e74a6b3810c3ec47a8a77e9714474ef4a","nonce":"8a0244cf0f000b92a539a7d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"d62fa612af3a158f964f413606150b71665a0638639f312e115e62f36143865ad9f4e026fe5b6a4fbdb33453d1","nonce":"8a0244cf0f000b92a539a7d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"c296fd3296e7db112d589799f789799e4c6a49bd4c82d169d7ff56bab4e1632d5e72a3d6a227360e28bffc42b5","nonce":"8a0244cf0f000b92a539a7d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"201fab094368d805c4742f0931ff235180e4b1c01c89f50bfd871f320bb5648d8bcd29b098942b9c3b9e23b609","nonce":"8a0244cf0f000b92a539a7d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"aecdc78f4f795bd01dfa23e5f2b4c3ea10fdbdf75cbcd4436b18c276fea6f0908cab8545d29c7b767ad6239451","nonce":"8a0244cf0f000b92a539a72b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"05c8dcc6e98213c3357c9b9388c0426f461bee450973af780bf43244823dd2a3b93d894f2c5bd77ca88f5dcfb6","nonce":"8a0244cf0f000b92a539a72a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"dac0f149541aeee971dec3d801cbc66de857b4dc2f9870e6ae899613f291254b25b838cd271cee602ba5601461","nonce":"8a0244cf0f000b92a539a729","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"87c4b514a4255f76e656c3a65067c009f3ed9e7091b2716ca777c71ebf9845329546973a92673ab2127e0dad0e","nonce":"8a0244cf0f000b92a539a728","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"7bf6b1fb6c2ab0669a2597ddff66119c2c81a492f037dd1c4a57a5052de209e20c37a313c3c7fcbf946dbd5141","nonce":"8a0244cf0f000b92a539a72f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"837b3a3454b9d11f32114562dd38be1eb580ebcf3ec858de16d0079ad1ff055b940b91d4d760c5523a6911e2a7","nonce":"8a0244cf0f000b92a539a72e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"06afe604c172fa1aa14ab92c171d619cde7678892c50809b2ebfdf45507801880223c8e1fe17c28c9c94e021fe","nonce":"8a0244cf0f000b92a539a72d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"eb4af1981a408bc3e2a00f599b4a62b047b74a9e524a2ab6b4e78350ff51265c55188600807f58372ac55218ab","nonce":"8a0244cf0f000b92a539a72c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"f43aefb22788ee3846bb8eca2b25ba2ad9c171bdbc56eadcc834022fa4ddf40108b491d099bfa44d1a2a3ef7c8","nonce":"8a0244cf0f000b92a539a723","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"f2cbd40fb454821f959fe6d9a874cb03113713ba76fe03fd3cc94ae668f82f050927d40677da60e34e76e0cfee","nonce":"8a0244cf0f000b92a539a722","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"8988418cba7ca876f951c5583cab4024f4c51ebb96d46fde42771c4c9ea24dfbc052545a036f837dab22201ab3","nonce":"8a0244cf0f000b92a539a721","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"65e965d1dc8de572565d04602c7e2105d714e1c03b1b2a515aab64f5e0a2d2b28236417fc0e517bbf44dd63402","nonce":"8a0244cf0f000b92a539a720","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"3c30ef5d0fc3a0d81db44257fddb450b0e78e03564ba3286dacd620d505331553b46281f3baaac21fd5e7133f4","nonce":"8a0244cf0f000b92a539a727","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"605701d7eca097247efc3e5062bc2d095b14c4277eb275490d646ef789b2b6edeb0a08cd4c97cf4f94c52808f4","nonce":"8a0244cf0f000b92a539a726","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"f0a5c285d916fd90cd13fbae6942eec6bef9b4c4922e14681809c9438b76304e5f174c0612b37e83c334253f09","nonce":"8a0244cf0f000b92a539a725","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"c4cd830095555da48ae0a1483ee55c42e13fc5093d2f632a30c449a865733bb5040901a8ca317029aeffe0817d","nonce":"8a0244cf0f000b92a539a724","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"01ddbbbc1d43d5526953c88be724d603f2e4c50240d7cb89fd50c5b6fc0f81a1f6d68cd43cfccae8796a5d8576","nonce":"8a0244cf0f000b92a539a73b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"c7b97444c614e3f46b6ab4291b8a8e6c0b812945cd7e8ccc2210fe20b43e97f63a4d1e38899949321fcb74694a","nonce":"8a0244cf0f000b92a539a73a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"bcb26ca93235eaa439d55b378248c01d123aa704a687ddab1cb7240061ea96142d9422f767ce7cc009398f7764","nonce":"8a0244cf0f000b92a539a739","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"f07660158da9608ab79a5927251c25de76963f48e8af440dff527267d44582593a75741759d779c91860394576","nonce":"8a0244cf0f000b92a539a738","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"8f52e476f030e164cece1c471ed07694293d7586d601f99536b2c020186a19c7792a56950585e3bfd0056ceda0","nonce":"8a0244cf0f000b92a539a73f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"e6908dae14f7f60a815a63ccf473bed0e02c927f4df1e47ec0722fe4d2cf78215adba3e34047744d3f9b01f77b","nonce":"8a0244cf0f000b92a539a73e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"92186344cc15da4673ce35e1ac25a1af09b6eb3a8da4f70f5409a11f2c6c7ea8983279b840a51c98a64841852c","nonce":"8a0244cf0f000b92a539a73d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"2a24bc62b7cc5fc1d5b10653ccba69a59b28767e90366af498c2cdb90bcefc53e38cac84779e0474c15affdc79","nonce":"8a0244cf0f000b92a539a73c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"74292bb872954df8fbc5bc67210c5aa37c87b1a868ad8dd07d43336e49adee402eb4ab3c7fb82e690330aaa90d","nonce":"8a0244cf0f000b92a539a733","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"851bae7384e97f189273a1596c97a780ea0dc44884545ce87a2a2e465c12581086d5503d93c45d7b0ed92538de","nonce":"8a0244cf0f000b92a539a732","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"39888982c1ec5c3bd69975537d32c44f41ca3dfdc1fbcf47d158375459c030415050a13b277e662ccad8873da4","nonce":"8a0244cf0f000b92a539a731","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"969bb7a9e1d15661c92527785280bd48ad48dce0ad2509b65c2814f2753ded783da59dd658ff9a9ce236f62e21","nonce":"8a0244cf0f000b92a539a730","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"c2813cfa31cfbd7c74227755b60513abd4cd33e59977a1e48ac185e70e22781c284fbdb3abb80a73365dc6450c","nonce":"8a0244cf0f000b92a539a737","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"0373dce8622c184d1c34ba1ab433bb30860b7a56975b8837d993ebf3133b2d26a31ec7a7711cb3d7d334dca144","nonce":"8a0244cf0f000b92a539a736","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"e3b992f2e7eb20c184010429ad9b54fce863d428a7da07fa79c6e37d32833919248e2d5ac744d2bbc56dea0a44","nonce":"8a0244cf0f000b92a539a735","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"6b76412a18b5fe5dbe49d000c46a59a5e4777779a58f89c97582663da5e9547dd33274a6e9be5c6fd841546e82","nonce":"8a0244cf0f000b92a539a734","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"a17846da5a7b16044bc8bb938bb93d023d966c3b100d29986f492f6560459e1e68a0c28b41e34586501e540d52","nonce":"8a0244cf0f000b92a539a70b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"4729d3ef3dcb935de5cbace353f9179078a914b7bc4486d53f6c4efb76282315dfcdbb7fbc8bc1f45de8e18db5","nonce":"8a0244cf0f000b92a539a70a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"260316a508e42abf057d1cf014829425dcc2ba721e63d1fb74b690687948fdf402c9ad2af52e037e7e8bae925f","nonce":"8a0244cf0f000b92a539a709","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"59baf80474b29fa8b2c6429bb4ea68b9d273f139c9ca9b04a04f939258a92c3429beb8d28d52c3fe11b87f4981","nonce":"8a0244cf0f000b92a539a708","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"f4b436637fc4aa57db2ee81a0914ba9c027408253a72c5d7a12129cb6a3fc3cb592f856d1ebe215475aa85f5fd","nonce":"8a0244cf0f000b92a539a70f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"49bddea7337c01f5d2ceb20d7cf7c7c707699c68f68b15f56890971361a4ae80324f9130cb1cc7cadc414bc24c","nonce":"8a0244cf0f000b92a539a70e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"9d831cd29d97ba945d690112544c56cf0a186c37d241de464bf7f4399db3636e3f2e23b76b279c7da217fd124e","nonce":"8a0244cf0f000b92a539a70d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"d929e821a69d5970d387a395e4234ac92317cc86cdfd00998d7ae4a0bd83a9b0bd1799a9099bb837ee6cfc0daf","nonce":"8a0244cf0f000b92a539a70c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"5cab8501c36e179424472c9ffa05f10bd3f7682bf3cb5cac914b49abc7ad79230b57a21f45c9b32f762600e317","nonce":"8a0244cf0f000b92a539a703","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"b960c40e975f87ba191c6e0c094196868ba40184c32430021ab92606982189cce165e81f47e4902a9df52a967b","nonce":"8a0244cf0f000b92a539a702","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"d0baf77ced22fa09904087b98c2b7d909d93641b638fbaff2ccfb598ada89f08c721b6120b5d4b77e99f4ed5db","nonce":"8a0244cf0f000b92a539a701","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"48e4b77ac5303b64b7aad17320c7bf84df88cffc27c53e87b701647f287a17be29960dc972f28093351fa90ea7","nonce":"8a0244cf0f000b92a539a700","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"57ea9e3c024c58b97f914118bc8d366afece8042ea4042181b725eaed6a86542fd70526fe0c6c3b8c98f21dca7","nonce":"8a0244cf0f000b92a539a707","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"d37cbc6e1ca2bab21d61355acaae85dc6b759e1808b4cae5df839f2a01994345c119ab496f5b3382f3eeb7f5fd","nonce":"8a0244cf0f000b92a539a706","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"14ee5f90f013b18e4c49e86bce8fe64159d0b11abd078f0089e22a24d0f0ed87c20523ac8ffb4addfb6f1e5036","nonce":"8a0244cf0f000b92a539a705","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"0398ae19385581d886ebe2d7612b3540cbd06133c39f47e2479d14d8e848eb38d1edeb3329591882036308c69f","nonce":"8a0244cf0f000b92a539a704","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"6de53a88f52d563c8adc8281f80112242f612cd8d0bceec90af5351d7948a5717b57b39ef240c4677adaefa75b","nonce":"8a0244cf0f000b92a539a71b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"9bef2754c9c02b038d6af3e3dd3391af27f05f4e8e13312d6c8ba4eeba2e021af3f61ebcc715c923b8c1ea6e88","nonce":"8a0244cf0f000b92a539a71a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"5a733ce779d4e5234ff723f13eb8f5ee39247259306968bb5b3324de3af8c9c38c4fe991f0f9c87a1487b72987","nonce":"8a0244cf0f000b92a539a719","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"0df38b93cb878f774d72240cd6e5ce5820d6a80c76dd212b95b3273edf8ef90c87a56dc73400fd761058786230","nonce":"8a0244cf0f000b92a539a718","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"139a4933252395db8a1a68a4f074cd6b2d179ccc6f7151150fe4b7419fd0530186d8b34f4ab2d839189e995d85","nonce":"8a0244cf0f000b92a539a71f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"cc9bc5fae37455b84ecfb154e398c528cd4ec8468a1735fb1725d2dcd673176de78f1351fc31a6e1a92ecd2818","nonce":"8a0244cf0f000b92a539a71e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"a8e7866ef0cd80e492d667d37ed4e4079e9b3eb91f6cae400024f6ad7b214acd1883789467bdae9f8ce6be3f1a","nonce":"8a0244cf0f000b92a539a71d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"22e9c5c1e1727bc684b8006a0573342e51664214fd388b2ae956fdcd26451b9593b93aaa830fdc0906b2e23f0d","nonce":"8a0244cf0f000b92a539a71c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"3845d678f145917f9f50d6d935181b1349fadde04428f72415269e776f34e3ef0d80fc4b68d5bf0b0a3a18df9a","nonce":"8a0244cf0f000b92a539a713","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"de091683a3cfdb9b04079b55adfc4084c9255bdbc271c7a70438995ded1b4daa23312fe70e3eacb72545953a52","nonce":"8a0244cf0f000b92a539a712","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"f32808a055af2df47cfef88f75f02d62098b65d69862df857bbd30d7d6557fab449b63cbd459735f7fb86873c7","nonce":"8a0244cf0f000b92a539a711","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"ad0e99bf0c15523fbef6c25886d65fc7d91b0e3995fd4d5d448ee5af04c17fc1c5352e37d2db3ad4515ee858ef","nonce":"8a0244cf0f000b92a539a710","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"1d99c341558512e2a21a5afe59c425c9ebfeb8ad11b1793c2c1ab904d7a87860aa96aa13e61869eb9d5eed93d0","nonce":"8a0244cf0f000b92a539a717","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"8fba8e393263158b33916270e292db616594d355361e27ea0026ac33632687fb65a1aa87c4e3b33c69d9bae10d","nonce":"8a0244cf0f000b92a539a716","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"56037ecb19be8159706d995727e381e4d727ffe723326a4556bbd92deb8b990d258b26c6920a8ff71169b2f903","nonce":"8a0244cf0f000b92a539a715","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"fc8d363f82ed1f1569aa4ad95de4b35f8686055d7929948c54c842fa38c27c3fdda7c161a6d203a78bdbee20c7","nonce":"8a0244cf0f000b92a539a714","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"7ccf4f4e799f93b977204d67e1057a25ee34c51e7552ded39249ea37853ff4f191a07850e62528d44697c0494e","nonce":"8a0244cf0f000b92a539a76b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"2ffad6b16ecad80339f19855b4e1bce2e67c1c4301ff4585c70e538e38b967f0a6e0148ab9a1f8098a62ffc88f","nonce":"8a0244cf0f000b92a539a76a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"859c57c4779c18f49577c29974bd7674475557b1ece9c28c5903e5ee42ecbb03df4c301ddc21e99067c874e989","nonce":"8a0244cf0f000b92a539a769","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"106bda00093934e9ea0405b1175a7dc0a0437d6437005936f6e63d031c1b3e31709ac40400a92506a92da7da04","nonce":"8a0244cf0f000b92a539a768","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"728f81e22592691a12950354167d41c04eb825098521f8df9a389f490564c61d95c7011d5aa63120c0b60ec3b1","nonce":"8a0244cf0f000b92a539a76f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"a4d44fa9b42209eb8fde6d81ae159aef0aad9aa2abd09c9a065f217ad55247b51e9abe581e773e9f60f8fcca5a","nonce":"8a0244cf0f000b92a539a76e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"044c1a7b5af06547b3e9ddebb892ecb1314d2b9bbc63b6c14a8e12e591161dbb63b243f6ed868611a10921d8f4","nonce":"8a0244cf0f000b92a539a76d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"a6a41799ad1fd6fc295677b35c8eb3236114dcc1733d059ddf8ae5e3a0c55cac4f1bdb08e57079f970dd8fc7a3","nonce":"8a0244cf0f000b92a539a76c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"43eac3047f7b14ecc7b0b860a3d406e0517b81c4a3b36155c283697da0b28817ab3f7e18787b5b6ed439225454","nonce":"8a0244cf0f000b92a539a763","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"553b64e92ca2d8ead188de92fa331aa6ac717e70c44e1fe0c6b514aeac02e0fa0a325729a0bf92f518340111df","nonce":"8a0244cf0f000b92a539a762","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"a7612de299f9f8b61cad9828ca5b97739724db4da23608e9763b727fd4015f648b9418a696954b6bc5fab68379","nonce":"8a0244cf0f000b92a539a761","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"8080c64d08a16fdb2420617fda908c5a8d737a03d1a97344312a2aebe27895e656a167d7e1bdc470f77a0e0e0d","nonce":"8a0244cf0f000b92a539a760","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"99654ed3fe8f4c42f9619ef241992089bb8516aae307289f2ded713663af0f64fcfb64aee7f03e519169bf7f01","nonce":"8a0244cf0f000b92a539a767","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"975b4fad9bbf9e56373f6317d55a2d74a94d4309b3526032f39189158dd3711f53f676158f61b4a46a27c5b778","nonce":"8a0244cf0f000b92a539a766","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"c685c30d1edbbf26518ef4561243b02c708d9586e9b5636eeeac5554fa116e792a8180986f4ec6078231ea0b93","nonce":"8a0244cf0f000b92a539a765","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"bcfce8797fac8d62289641f16c1ae6f58094ea9252f517bfce5e42054dc2100663178ad12cf013307077c8019d","nonce":"8a0244cf0f000b92a539a764","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"a40f33036fa36e4fb733d8e92fb61157c7aeb2e8f2a27776f7fc761549c675a1eea3fde0f58fa5b7acbe90fe1e","nonce":"8a0244cf0f000b92a539a77b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"44dbff7a26754be05aa3a4d6dba59ac98971f61a88c729113bc06029c51f79ad0f9d26102988e31516f7995828","nonce":"8a0244cf0f000b92a539a77a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"fb415a2974ac319e4e53bbbc245e74cf681b333798ebee65f2e202d4c632c838031f5971b018fe7550424fd1bc","nonce":"8a0244cf0f000b92a539a779","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"7207188d388c73a436fce38438ea894b372ad9016e82dfe66b6e049dda1c40560104df749aa7b81f5879686bdc","nonce":"8a0244cf0f000b92a539a778","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"c56193ccad97e365f3490c080db8b42d33a4c8916b958295b4cd4bb635d75cdbea66ad1a305e794c58bbc9f9de","nonce":"8a0244cf0f000b92a539a77f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"186df6fe4b691d77690c7ff1dc65b2eb609391f330242a81b31dfec821054034d308d56f708239c48bc4ee729a","nonce":"8a0244cf0f000b92a539a77e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"22ec69762c410849c0cf1fdb49a15d3c4b548ceeb38f7aac7b187b153a259b24ee5626059ed3dd55f70ef2f513","nonce":"8a0244cf0f000b92a539a77d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"2d1e4315e3267bf10df1bb1242ba4f1e78209c15cf77a7bc8055101fe16087a84a291bf77a3af5dd1e56e0d47c","nonce":"8a0244cf0f000b92a539a77c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"3c16f850fada66d9fa6a111218fd29823d9ae8cfe8c5e993ce0c4888c200900d72eee578faa7ad7785edc49d48","nonce":"8a0244cf0f000b92a539a773","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"e7d25460e4baa2f56c72486369c054409cb92c5f48c14b84053f06e141a5f63acfe0c90b6227b346db1b8987e7","nonce":"8a0244cf0f000b92a539a772","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"371c6d3bf62815bd602993dd51f4be2c91265470baa3572b8e66ac4d7a431c9281bf72e47693dc8cf404cdb0bb","nonce":"8a0244cf0f000b92a539a771","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"c8d9df32e316bd4785e1564ff4d5396e41d3e763bccbf7f7bd2e535f42dc44bef0bab69624ef8977896122c2d1","nonce":"8a0244cf0f000b92a539a770","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"9f57371f56090bc8be1b2358d4385cc6795a78959b6eab22fb82abf287c69df55645ed69a34f6e2709beb629da","nonce":"8a0244cf0f000b92a539a777","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"a70a1a5bca257842586d5bf7e81a57a9d8a797ab8af200c259d1cc7e045b4f1386d59027ac9bdfa97666122261","nonce":"8a0244cf0f000b92a539a776","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"61499b617e0df9b9ba22093f4dd857dc509f5f629290956d02a21123b54de3a1cb654e5bbc610cb2c41689bd50","nonce":"8a0244cf0f000b92a539a775","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"c3461c8ab4018401c36a2a8c0d859b5128a5cb21af908f139294095eaf1e62a9ac22788ea106caaa25567015c0","nonce":"8a0244cf0f000b92a539a774","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"dbdddecae19120ab1906cba6df98161a67e24e0a925e14503d26ced582edfea22711e1ae2e8f91427914eedf36","nonce":"8a0244cf0f000b92a539a74b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"5419426be655b01b4af112b2a9b2d7b8eab1adc6dd89b2bd720e67f484ae321f3b9d19b19cff87fbf0d6acfe41","nonce":"8a0244cf0f000b92a539a74a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"413e96286fb63a35043d07712244ca04874d642c1630769327023f8e644e077209d704502a93d13f3160b072d0","nonce":"8a0244cf0f000b92a539a749","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"1cc1f0603239e3da80f43f83477d582208b611aa0a985328c4dc2f22293732b842c5cce794cd511e2e9cdc58d3","nonce":"8a0244cf0f000b92a539a748","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"6d3596f56fd33b41f9275f47925711c30550d5542b0e3d7367ba28c304b3ba8570a8a29e987112bd5c01ecf3b3","nonce":"8a0244cf0f000b92a539a74f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"dbab1ce3fbf6f60335a835e6e2aa4bc02b27afada1f8a3a295f8f271882f66bddf1901e165a0421e988a35cae5","nonce":"8a0244cf0f000b92a539a74e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"c11cbd3c1a69c89e626c298a4c20e36e8bba742431cb5d10f373f3c5f3c98755284f6523acb24cd4f6f54f453f","nonce":"8a0244cf0f000b92a539a74d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"93a291d06fa7099416cd7b0c6321c2b1e9e41bacb23830d9e563853b2c99b8f426c2f6a75c1d41e45029931c59","nonce":"8a0244cf0f000b92a539a74c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"9b2377fad7c774c9f04a9566c9c159d1b93a763232fe268a043bb1b6e6c445832be248746553ad0c99a3844465","nonce":"8a0244cf0f000b92a539a743","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"094377e0775ac86c4305fb8879d33c2402e02a1edc83bda6b6f0960f5887f992803f737ae6e6efdcd8fde8e51f","nonce":"8a0244cf0f000b92a539a742","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"eea66258618dbce32c9257b38212df4c68ef6775ca997524ff2f5a7c0ea8e5071a7d45ed5e20c9dde6683aeeff","nonce":"8a0244cf0f000b92a539a741","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"febf16488bb221e9baa3a952936d8e40d3f297234a473e5cab2b409d42acee1cb2f57e7c3aa61a5c5a3b7df852","nonce":"8a0244cf0f000b92a539a740","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"7024bd79b052b34153163225c57bb3eb1725fa2df9201c784199f084c88c53122f70c7955712321e6359f932d7","nonce":"8a0244cf0f000b92a539a747","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"7398ccc10db12612d3c482a3de22b31d377da74808bc36e9cf8a43aeeec97d61c86eea1432612508deab0db1ff","nonce":"8a0244cf0f000b92a539a746","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"99d93b94f79e01976516ea1db59ac10987036439dcafd9d758290c2f5c16cb266f84177affcf35fe1f6c6a5330","nonce":"8a0244cf0f000b92a539a745","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"261c46349c399fd15833fc7fe5097105687bf6be18155263dbb56a2210228a8218acd48bb24488656d94600f55","nonce":"8a0244cf0f000b92a539a744","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"aaa9c28982c0c7d547d6d9a4a8110cf878fc1952e6cd35edbeadfc276394a19439f36406a2740651be84f4a4df","nonce":"8a0244cf0f000b92a539a75b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"13b782c42c7e5d028bf475866c17f3bfb4b97df544daa1fbb2823e4e0b40a92eaf33336b074d2245d85fe584af","nonce":"8a0244cf0f000b92a539a75a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"f962ec7cd195d42047eb59a0f7ee614dada4b906ff80a62e8d460824ddd2420b9477cf4ea996ea00ff055af902","nonce":"8a0244cf0f000b92a539a759","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"9512cdd2555c6478a36d85b9a0b92f6411506f2222e569a533cc06e154505a3b4a62ad220cbf9c2a15456ec8d8","nonce":"8a0244cf0f000b92a539a758","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"dbfb04049faa5b86a1973ecdc1e7a187e0d0b7927d99cd24aebd19c7ba4da0685194b9f8b81fb942c636dfb19a","nonce":"8a0244cf0f000b92a539a75f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"d51912f237cac4b418d14d738c91355fd3f46b0ef405ebedb89fe8a93bcf59fd8da18385cb2e2c36ac64902964","nonce":"8a0244cf0f000b92a539a75e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"f14d9fd9780703bc80ed179dbd59c4d328ffea5b1e530387ff8d0169d22a8bd91de140bcf0a16405dd7a6a28b4","nonce":"8a0244cf0f000b92a539a75d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"16ec1ee98f72a551c3d2808a52c17a55275b84bacb313250d2bf5e2d18e4251cbd2daf916dba18b6a903ffa309","nonce":"8a0244cf0f000b92a539a75c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"a87729d5757338895362b78c6e6a01658bda31892334384c5bdc704af4a204410028f107935211d06394096891","nonce":"8a0244cf0f000b92a539a753","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"7c04611751fede611a0a4f95e1f5f67d579981d8acbcd5c2a1b6858f4974ce21151221c343822233718417eb6a","nonce":"8a0244cf0f000b92a539a752","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"a7620180df046498241204ed2ceec7724b1be8d235ddc525686f203b954fe4761fb2072d5fc162c6427493927b","nonce":"8a0244cf0f000b92a539a751","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"eb4725aafcb098e0def92f63b6536f686858a9944f5718a8a9f0c74744131d1524d511f4c6354e214da6ed33c6","nonce":"8a0244cf0f000b92a539a750","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"ce612d73494a0962c2b8c0cc7da1db6b1412064e8fadc6899648e9f75576f106a75fb542b163bd774b0ca30116","nonce":"8a0244cf0f000b92a539a757","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"e55727a289a0d488cbf4c9756898c5e1e727ee4335ea57d571a5b44af548f8c4f4050c53873ce21334f91f7b5e","nonce":"8a0244cf0f000b92a539a756","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"e9b31037ab220c83960e5b6e7d5af0b03feb921941e2bd4d292290a09b8b9b9733028c4acc0343b362736ea642","nonce":"8a0244cf0f000b92a539a755","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"a00fd8bbb012425e3b88056e43ba863702ee9bb55bf5e0d9ecb499566ba63fb581237a183f6743a360eb3af0ee","nonce":"8a0244cf0f000b92a539a754","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"a734502b17d8fedf9f662ce084898d6dd43b381c144546bb7eeddc2618fed4d87079e1dc9f5ccbfef9caf4f574","nonce":"8a0244cf0f000b92a539a6ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"4b8d26d4e3501f121378c4ac2926678a7ecf17f991a6c9be37d79b92f33c04cc"},{"exporter_context":"00","L":32,"exported_value":"44b10a9991d5c1feaf8b73422d85d5cf23d853b4b21924702603bce46e3a8668"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"15d4242391fde1e4ae271a89aa2d3227671f3736d17155e98fe4638002cdf720"}]},{"mode":2,"kem_id":32,"kdf_id":3,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"fcf24ab525fb0aa3b3482185e7d12cb0696594a66150e2b7d898abc2e69689f2","ikmS":"321f9675e150a87baabbf0fb777c1ac57d1c4102c21f54a00f34731fe4f72f5a","ikmE":"86df33ca982a0b3c1c6cb55740ef9a2b3cdaa226485922a935db0041b9f76822","skRm":"2614d6d99bdf2740694b6df04d9e4c92a92cbfcebed01bc98880bc39c5669e2e","skSm":"4290399e5522a824943621f474942811f7eb8ab9efa80d880a9a402c0b4b6eb9","skEm":"32b91b6f584b9438fcdf07c460dd7458ddbac4f7f1a5730100f3091b5b7321df","pkRm":"cb235cf3525d7ccf739a00245adaf04a9a595be15fe5fd861a3f82cc4af67b47","pkSm":"1f3105d3dc148ae12ce9bf470f446129c60f6f08fd672070772d9b739aab9432","pkEm":"0cacfa40d29d19e242c5ab330fde7c2dc49a948afae4def25341d6747053b57d","enc":"0cacfa40d29d19e242c5ab330fde7c2dc49a948afae4def25341d6747053b57d","shared_secret":"c46129d2b9f9b5131f9bfb7c61fd3b1d877240c4ad56e7414b664fc49c8fc46e","key_schedule_context":"0288e94c0aacbd6d63a08e547dbda944bc1146d7483cba3d5ca0b0cdb26d2fbecd0d6d8d55178b4dfb4a648a4e3e54adc05dfd4cb2a845712a74539ccee8b4f781238f3e66e519a887ea3a0d096475a5defe5bfd1d22ec386b880d050dbfb6995fe8f7d1d0c661c4e10698687f757b1e981cbf025920074204ff660b9f490d7594","secret":"4c94cd10d2d580f4187daf178ab13fdc104e504921ddae26de6bef4f3315379a2b0b3dc581094617b8a5a43d9c957e08403c370e0d1ab5caec272979bbfe6e5e","key":"c04c5f17ef50675d3d4d9a36739a8d67af923c78b3e59e8458b004e6a75c50f0","base_nonce":"333b15353526478c0f77ffbc","exporter_secret":"520303d90e5495952fe352baaaa6577cee34c7161534517ecf03a89a57db7352e4e41b695bd361692a7ef634ac29626be3793133e287332ea3514dc973e0da79","encryptions":[{"aad":"436f756e742d30","ciphertext":"b328436fd7fc91c43a89d79a1b92fd693c697f64c98b2853326db3f22a728163a7f24151f90104b10aa9eb4cdb","nonce":"333b15353526478c0f77ffbc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"c105d0ff7e54900a2b323ad093b10fd4bc53f111c84c60423d3a7b0cff228576d0dae0a5561504ae9f7a69990f","nonce":"333b15353526478c0f77ffbd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"f5f52ade990962cecb0c0aa5e8251e720bc654c2739165a33a7f0a55b4c6933cca778f6bcd82c5afe088ebc979","nonce":"333b15353526478c0f77ffbe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"973811185c756a050ca72acd7ed066572b2cd1d1eb77f32bf27e5bf0d443617b08623c321248228b46f6967a40","nonce":"333b15353526478c0f77ffbf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"313e4d739c1d5ae26cdca86070bba0bb3e4001588ac2a350eba85a7602b82bb6683d5ecfb0dadd09e190e4dda2","nonce":"333b15353526478c0f77ffb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"86cea39b764f22cfad1fadb093ffedf0afa0293e26b97a785f1e0e5226ec02e78409d9dfe6765e42d8701b5b3b","nonce":"333b15353526478c0f77ffb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"d62209bf46aa24c2a4e99dc56b9c5a421fcb0b1469eab2594a27a7c2df72d624fec8729b60f701b4f78a0a1155","nonce":"333b15353526478c0f77ffba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"5009611dde851ac4234a0487a5cae4fbae74d448786a9c608aa5101c3b386c986d50838abac12916844516bc51","nonce":"333b15353526478c0f77ffbb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"69d78e83d74b0d900943320dff9561666d79a78abef8fd4a795d28d28aa7ff6f0ff315d9b71641af4fef795427","nonce":"333b15353526478c0f77ffb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"1d1aa604eb05085983bc3353025cfadea850437d21aca811eaa9cfc1f010b66cd9866ddf612f393d182264a05a","nonce":"333b15353526478c0f77ffb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"6313234dda6ca5c1e4ba9db194b1192ce5cc84f1e192fd7adc8fe7282822c8705f4c46ad3969aa340f9f03af26","nonce":"333b15353526478c0f77ffb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"c4effa795f87b64477a8f5b3fe32b9381a89509d695e5f051c8fb5a975d627209dd3d9b2313f14d102a6b434dd","nonce":"333b15353526478c0f77ffb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"59feb391346d6eb9517d205ab938e48025667b5c51c7f5e71043138ddfcb5270c7b24af19740ea6004aa99a42d","nonce":"333b15353526478c0f77ffb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"74eef33413f12674196fcce363acd52371f4c7b8a3e8b1df6e97c0e20985a1ae5c16207d5d16417e72abc33593","nonce":"333b15353526478c0f77ffb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"d23b06053766a33fab0b61be4faebe72cded6c9c8183314c4ee809ba8df78c09da6e9bd2bf4efe245cea39adc6","nonce":"333b15353526478c0f77ffb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"d915af1b998ab290ff73a3b7f1982bd9464640cba6f69c291ae7594b0845296836992221b5cd3a02cdcbda6756","nonce":"333b15353526478c0f77ffb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"cab49070c2d1373dfecc8bbd2a0608e2168f52057d9930e6b987fe07d1b82c510b4825a554c49855bc071dd9f8","nonce":"333b15353526478c0f77ffac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"c64962ee98245e89b35f7edee9ba8893d0f0ec2a726dc8bac2a42cfbac4c3fb86282b5785a67b1420801fda0f9","nonce":"333b15353526478c0f77ffad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"e00d9d855c8f712a95ff8e0b43c2354690768b411917b0cc6ff9bf3de405f32479ecbd8473880b7d31cd337c94","nonce":"333b15353526478c0f77ffae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"4eebcf9a87411ff5cc6dac5fc13e7978b6e5a89e647b8b236fff54dbcad322836828721b7f9d349c1c2a619b56","nonce":"333b15353526478c0f77ffaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"9d50ef6af0ec39f39c7fe5258ceb49c569fc71d93bd4fc8f2ec7efda56ea90aeb0e7282b9609087054a9bf73a3","nonce":"333b15353526478c0f77ffa8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"6ab6966d8d21f50166f829413007df79ddcfcb03ea58b667ac424369a3ec88391d003d6e57e58ec0acad236f48","nonce":"333b15353526478c0f77ffa9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"2e2d069c1fb994e6f93561c043d889f0f28371a3bc2ad9c6614444840b2432cf9ccb4d7501186540ce06358c39","nonce":"333b15353526478c0f77ffaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"d7f812fb4ecccafa49bbfaed2def4079c163b92bd5983203965c5334574e2712e4a76cdf54da3e5716415f87c6","nonce":"333b15353526478c0f77ffab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"fc7d03d07f43fe915bb1e102a2e974fa1a1da9ef6a03d0b855ff2c05dd55f2a2aac386696f49966c44b1ab8e76","nonce":"333b15353526478c0f77ffa4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"de26458e104349884a43b8b4961e8d2fe9c528a3b875da1dbcae0d963be16421c75540a4f33b5cc0fafae20ba9","nonce":"333b15353526478c0f77ffa5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"1e18a41b95b83bd2e998298053a37a8961c3b0f2457d189a82a32b24c89be2d73d5dcd614359ea729b66d141f3","nonce":"333b15353526478c0f77ffa6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"c26aef5bd8582a3025e9c89993e57ae2d8b91615814aa3627e1730017c5ef476b26867c2cdda5e9fe5282c09a2","nonce":"333b15353526478c0f77ffa7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"6b59756d9609ba013bdfec3ab3f7246202fbe504cb1088c1881c4c29d22a27fb5c89aa77719621965fa9d6a311","nonce":"333b15353526478c0f77ffa0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"d32f197d62df36d1677b67c48f499a82b955db4bd1f51ad919418c26aac02ce4d7225cfcb6c4a6b9f98ac3c9a5","nonce":"333b15353526478c0f77ffa1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"66d5ec7ed2dafdf0f5c4c00b40ee920c0dcfb72cf3e3fd6d71ab9938ae330345e4ae865990050c7f505752d894","nonce":"333b15353526478c0f77ffa2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"a8d003e14ea736aa1a60bb04c126138b67f5809765bd4528dd7f9024f8b123a091183c15022fc764b4257e22c5","nonce":"333b15353526478c0f77ffa3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"6ff4b0b939fe11e00e66aeec0c00e283597dd2b81cb4ad3771940a9b51b18149de3f4b63c7ce3db3e24f43f4b3","nonce":"333b15353526478c0f77ff9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"affd214083d5ece9eea37b6381597d2b15aeef61aa7adf21153ce7780c44314c1e07eaa250d599e41177693380","nonce":"333b15353526478c0f77ff9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"2d03907adfaccc94a7a0d902bff541251f6eac93416dc438d57ec0f03f8f93ffb44254b4dd2975445f28878d75","nonce":"333b15353526478c0f77ff9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"430a29a931fd03d65acdc233ed02dacd129ee8e37a91c4afc2a23ec1067a4319c0893749f18a3cbad7afb7bb2f","nonce":"333b15353526478c0f77ff9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"290bd9d1eea328ef9abaf5a47a4913882d1a821f40db08bf362f5c9b49721a6e4181e7b2931be51e4b85e97dca","nonce":"333b15353526478c0f77ff98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"bf11267994597611b033f65af608b954d24bac9a7b12bb80d2e32c3d26e95c59d631691d6103a8a9e348d11679","nonce":"333b15353526478c0f77ff99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"d2685bf1b934a6b09a1c0f3eff817b7137d164df9c88f900853795d99d0b640139e6dd8952d5cf3c9ebb7697cb","nonce":"333b15353526478c0f77ff9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"99b1b717ce9e7032c6cc5a053c3f0034bfb33289ba1fe5a6af8f7d0907ab55e2c6f20643bc4f556573223aa479","nonce":"333b15353526478c0f77ff9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"6fea53f8437abb812af60ec9a4c68cf4d1f90f7061e8b2aa1b1e1786b49e3796d9f93e0aa1ae03f57730c89113","nonce":"333b15353526478c0f77ff94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"3d789f16baefcdb4dce7bd91309c74362e5594d519c0d19f388585fe61f3f9a2f02ca84433eda68672a3d22b48","nonce":"333b15353526478c0f77ff95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"b09ea9434bf0b21716436c6de16d6a7dbe2e8ed2f329273aeb2621f3bb943ffdf71ed441f28f0aee1a1a360a48","nonce":"333b15353526478c0f77ff96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"d2bc09937840a09604b4656289a37eadfc7d75bf838679bc7432822e1408595d913296c043ba00de3d7f5cd6fd","nonce":"333b15353526478c0f77ff97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"7bea7c22fff9e2e2c805a14795eb57d36f5e283d3cd586d7864304b17fac713c8c40457fbe691891c5efc710c9","nonce":"333b15353526478c0f77ff90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"ef8487b3c7fb57e1a69c3f97329f93e0e1c3d78edde646a13ae030462c178f9138338d15fe60b7f4af253bf349","nonce":"333b15353526478c0f77ff91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"373bf4964f21a61e8c3ced662645e0833a2d1f26b75f80ffb78cb66b4785e10ec924872ff5432f879088ba4349","nonce":"333b15353526478c0f77ff92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"60b0ab7cbcd07efd921b9d5ad0d06bcfd12ae31e2b992c3b945e7f63cdc1c1c45f79182188df288d634e6696f0","nonce":"333b15353526478c0f77ff93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"d8016d6de8315c8b67fc4fc7827bafa95a032f10ae41b3b1b54a2d17fc415b6f042aa3f80bf3ddd6d3a4d3dfce","nonce":"333b15353526478c0f77ff8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"017844c5c62248542f62223c2eb5dc676bf302e93b73b2fc9a6c64bf2b399b19a6972761086e474f2354b4b6d3","nonce":"333b15353526478c0f77ff8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"771760aa059235e9752a7808ebcd55b2f4f7ff100dbe2f88c39559fde95ac0d8cbcfacc17db5a2a7c8883bf342","nonce":"333b15353526478c0f77ff8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"d12e5b80b48db4058212851588044f4a5d39d5f42945cbd0ecf0b445ef8a8c2211bcd1c56a434948bbc013f501","nonce":"333b15353526478c0f77ff8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"6f1af8fa1a7a86ec83ab5ae1ceff6cac6b944a1a59d57689585ac039130a7755da163603ce9e2961ecb888bbe9","nonce":"333b15353526478c0f77ff88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"bb65f5d8531a07dd3afa9057f28b3b50b7c31b5be9367df50f913c3ff41c04bee462c6afbcbd215e7d2e8d3d1b","nonce":"333b15353526478c0f77ff89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"ed36a96af806dd7305ed36c1378bd81597bbdf6c6033f0e619f6f968ab7b4153ac27590d9a68baf0002ded0214","nonce":"333b15353526478c0f77ff8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"151434601a0510e9f75d4057af901d65c5dec8c70f0f0a8b9074dbc1d0f1d66abafdb5f70418a8a80ec1adbe59","nonce":"333b15353526478c0f77ff8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"3c0dcee11caa2d1c0ab26cd524554641436f59bff424cb74694962f4b6eac4266783467c7359725c6dacd1aead","nonce":"333b15353526478c0f77ff84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"944cf3a45986d1c9a4ff6bc83a775048fc1f2e314be93b6d50861e14ee572b7a902ae63556d171ff4e24256a9d","nonce":"333b15353526478c0f77ff85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"826347bdf24557549a7db6f9f6f4f168ebbb5fe9d449f449224c8e85b75784b71d6300fe4631372348104d8ca6","nonce":"333b15353526478c0f77ff86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"d9d3e0d66dfbf7daef9754fb6b24d4bc69f095b01ecc49c80423a45fc617f117448c3bd75b40191591453a84c0","nonce":"333b15353526478c0f77ff87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"b8c14e1478d334122d31af0ac0b33ea7469902e496df46c811b7e91743b2aecfd637abea1a5906076c98c8097a","nonce":"333b15353526478c0f77ff80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"d0b5909143a67c549e0b86d67a3d3c94ddd404e87e49938c94077d399a58f3000f6e708d517d72ab15892253a5","nonce":"333b15353526478c0f77ff81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"52b330d98d9089560f9a35a51d2be0522f215450aa3e9c7ae16b7bd15de9435ce1cec57d226735a0014b501ac4","nonce":"333b15353526478c0f77ff82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"6fcc07d2a5f9dea36ebdb394dfcfee92cec5a840b5a8e50eada35375ef238542653ae9d64bb495e416adf77a56","nonce":"333b15353526478c0f77ff83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"aa3fff55a4da5623bcd12a469297851d375c29ce508a77ade3bafd51afc782dbdb51d8b9b96ad4d4900aa4048c","nonce":"333b15353526478c0f77fffc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"e0ca613452cf6f782c6836e0f5dc55bff5ef9e836d7468212bb4bcce778bccc50d75124ee5808c8b157a96e0b7","nonce":"333b15353526478c0f77fffd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"8859f0b2daff4d4b1908a8d7fea07c873c822624f24cd9983f1bce6a44d36251386bbbdf2ee9d7d205d04e997c","nonce":"333b15353526478c0f77fffe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"d98b41b48f383271fa44343eb2bd1cb6640fa88bc38f695a8e883af01c39cac6cb9866f4b10e3c8c9e889db091","nonce":"333b15353526478c0f77ffff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"7ef7331754b6cd23ae3e9847748edd7e6b81d340d6b98db40117bef68b959896b59d0644562f09d338fe28718b","nonce":"333b15353526478c0f77fff8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"6201877fd63fe35274e8a0439d4a1b32c62a50c7daaef1d1a1efe06842a2aabeac8e4c9375c7588003a162c019","nonce":"333b15353526478c0f77fff9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"092e3cce89efe8fca65782bf0c608d2cb2bcc1f7303391cd4b9b96324e6733ce392affd42e20436bfcc9dbced6","nonce":"333b15353526478c0f77fffa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"e55c6c5bec7a2360837ca63d3a7697b80028a000174801fe041109afabb480af0da2c27fac40d0179bf3024276","nonce":"333b15353526478c0f77fffb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"98fb402ffcc36367b1af6786c242684380141a33ba87bfc64e05caaebeba35e4d5ebf1177d5c944085530f552e","nonce":"333b15353526478c0f77fff4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"858bbeb0f154f8dfcbc065e3bb7bea72373a4c0a67ad7ab3b09910b7e8f4f448a53c828714bb6f3b102401bf76","nonce":"333b15353526478c0f77fff5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"05efc3d74e3f6e04123d6666cb0af11c2bbf8be6bd55a443f8a44ee50c16f26d12da480cbad963567e0ea24a37","nonce":"333b15353526478c0f77fff6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"19752a2c0e48ec008b0c581f1fdce07aed017a58478d1fbe714dfb2d3eb28ec10b4b2dddf94aafd92f0b552221","nonce":"333b15353526478c0f77fff7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"4c544659d77a5ceaa2290a538d4f0aa80037cceb0a443ac66326545bad367efefbe361b6e483f11d8832157185","nonce":"333b15353526478c0f77fff0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"b29113ff022f68ec9535108e581abbb55ff4db04c0f74593a5fced4c9cdae3706cdd29bb5ec0fb583f7407ddc4","nonce":"333b15353526478c0f77fff1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"4fdf51b367aef8f0cf64ed4c97be1ec0d1f62d3f738e68c50d0fb9f89a46bf3a78dce3f6be76918614f0d17276","nonce":"333b15353526478c0f77fff2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"7d7db5125692fcbd2acd0429573e857a936465d410c3c256f05f0c7b4e60e6a8856646c4755b888a78a8c8f3c6","nonce":"333b15353526478c0f77fff3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"42e36c1245ea76794a1bc4b05405f759b75729c1085c5917549645260f9d27897e98a3e55a74801d14205bd6d7","nonce":"333b15353526478c0f77ffec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"d9eb077863fba5f464c5b3c4344da588e758437ec26b4421cf9837c97e79aa880eceebd55ff23671976604f356","nonce":"333b15353526478c0f77ffed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"4dc30c9d5af1973554dc780126a646ad747e91fce00c94cdbc7ab96c0cf2bf1d2f3dc8d16267b2d0717d99204b","nonce":"333b15353526478c0f77ffee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"8867c5ed3b563132f1d99d6b818749a5fa22dda90829d4d8b00f130b8460c6be96b0498215b2be10b7f7aa02f0","nonce":"333b15353526478c0f77ffef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"dff5dd44244e1fb4989a20cf2b7560b3e5ae9ca6acbf52970cb1714d3d0bb859ad0165707c7d068baf17cf914b","nonce":"333b15353526478c0f77ffe8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"2e958ea85c004f3bf55269dee56c18ad6f6fe6c7dccd2b1079af730869fc60796a209e4674c66dc9b5ea42578a","nonce":"333b15353526478c0f77ffe9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"0bd7a5361408c907aabbcea1e2bdc86e431283cdf9f629ea33614ffbb29434a757233ef7189b56683e306ce88a","nonce":"333b15353526478c0f77ffea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"357562c421fc57098ea64fbbbc2c1648144c8c371b1e7838869979d8f8b2a085a93352cd1a8fee4bd243fbee40","nonce":"333b15353526478c0f77ffeb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"f2d911d586764ff4fe695a2e06b3f05d9c6714af25b0007e86ad1d80031b92fa398575d0cc60b0fec328ec57a0","nonce":"333b15353526478c0f77ffe4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"ec2496ba8e0b9b919704490520cc46e52ed72d520083844629cb206410cd55617c29dba6425024944bfd1839e8","nonce":"333b15353526478c0f77ffe5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"4c88ee320c163008c9d2341096bedcd40d4c553c64ac1f40ab377669af890346f849524150634f5d3f54b2a448","nonce":"333b15353526478c0f77ffe6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"1d2838411dd46f675ffa0f3d340db6c434f5ed8ca17ad5f76a8a9fdf1413cce36b9060d7da98f360ac5f0a3bbf","nonce":"333b15353526478c0f77ffe7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"747ee554e82311f1b0827903f6284c0eda362e4de4ea64e42b1c82699ea7c49bf464359c47a81f0cd84ee02bfe","nonce":"333b15353526478c0f77ffe0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"a39638a78947c9abe3afe1cbb84bae8f6dab2b2cc79cec0081f26cb1d8bac4035e04f6daed0698440391cc2ff6","nonce":"333b15353526478c0f77ffe1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"0879c0e9b076cf478973fbbb6b9f2cb4eb244a82586b789baf1e9ac1f17b8c1c1837eb97b776e7fe520c9e0fd0","nonce":"333b15353526478c0f77ffe2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"5bf2c711ab4236fb9f923ff15cf7a0b103b39cfb6be62260badf2bfd22ef6616c7216e4970b792dd91db140388","nonce":"333b15353526478c0f77ffe3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"2179b83d60a98d11998ad8950597eb7399e4397696f0c4114b30cf1f02ae667f5581aa1fbc881c83ed05830e4e","nonce":"333b15353526478c0f77ffdc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"1a2cec34a260364bc4b44ab9403602a9939f9cdc97e49c2dcf0adfbfd836cc14f1849e36e22322f4fcdb82e5c1","nonce":"333b15353526478c0f77ffdd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"aacafae286fe574c1ce8ca367b0a876bf5f31ac7d05fef49ac9074962010906dd2a8a347e2dce5368341965cff","nonce":"333b15353526478c0f77ffde","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"4faa66bedbb0093cdebc1ababbc7568ceeec81ae64c5b95af0c915ca7998702a1c9ea947a2e59bd5468985b532","nonce":"333b15353526478c0f77ffdf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"50b4154303aa255ab50b114ff14f64b25bc48baacea2b654e257271eece37c847c5a29255bc132f683a39ca5cf","nonce":"333b15353526478c0f77ffd8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"b8bf004ef6e692c669da19124446a60808566644fafc5562e9cbe2afb8a17a534bf4a814c77859e652b2ed08b3","nonce":"333b15353526478c0f77ffd9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"874f38b634387ed38c4a78301a0b9b18e0ec2884f19233a291fdd3d25e69c1218ded9a680eedd226e065c31400","nonce":"333b15353526478c0f77ffda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"45ab60f7b4122a1a7bdcdf5d43927a345bd127a9a626e77215c1c33db56bcd0383cfd2b7316f25d1e025666461","nonce":"333b15353526478c0f77ffdb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"c36d0227c173188b154ee9ce06a216f96889f36d1bb75eb19af74dfac121668715b2d693eb519be7d5ae744c29","nonce":"333b15353526478c0f77ffd4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"f0b3aeababe03ec8b6134a4f10ffa9a60c7222deddb540dd27a2133ab67a8622ae97a154a84162cab7ade83948","nonce":"333b15353526478c0f77ffd5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"9d2af3d6335de6c5943b62eb0d14e898431ca2e4914971446baa6136c7f49244a4b0f9fe9beeca9890d7941d40","nonce":"333b15353526478c0f77ffd6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"a8627b9e6a2d7ed8ae7bc89e1e17fc89f82a56a8bfc99b1c5092a2e150ecab1034d0c60ac6cf536a2a49428945","nonce":"333b15353526478c0f77ffd7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"58fcab382745572f48c421c9271aa78e84a878e419c0fcf44677bb96d5c831381c5adc78914ccc4ce77e6e0758","nonce":"333b15353526478c0f77ffd0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"fc5ca68a438bfe63ba524a1fc15a908767f6db3839a9bf87daa493d78f4f0e1a19bb139a8a3e751a3ae2ecfd4e","nonce":"333b15353526478c0f77ffd1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"956d3175773259e7f9e0486ccb49153d4b5d4e8e9eb95f911fb4f935cb9a407469860fddf2e9fb024db98dbb51","nonce":"333b15353526478c0f77ffd2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"4062f28d3f0a4028700cc46855f20e1f360cbff65eadad45b891114ca68532a009cc2ec4499adc91dc94cb9b54","nonce":"333b15353526478c0f77ffd3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"6e2058c65451292ea2bb9eaa76c24f6924b9729fc6803b14eee54808a0c1ff5e5b4d8e4cfb7d06ea5d94299e89","nonce":"333b15353526478c0f77ffcc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"bc9febc22967302a2d5d3b2413840da7e9d557843379959136c8feafcff731fd965989eb2ef3475d9947e02b66","nonce":"333b15353526478c0f77ffcd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"aa8d8e16b00cea27c1b8b1eb16b4961e425aee1784b9b7a9ce978e78e347f26b23e1ee1b03e710e7b19993810b","nonce":"333b15353526478c0f77ffce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"038248c93deae1feceaa376d6acc868df85df73834ad0d7fc692cdd921f1c65c466b64a6aba7215e92d640bd46","nonce":"333b15353526478c0f77ffcf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"3b8080e26c2c7c727dbd6e3d9f68de6ee339d6cdf99b70e082ce01c0b54882fd4325e91abf4129aef22de23930","nonce":"333b15353526478c0f77ffc8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"0ff4ff52878ba25643f59f4a8faad36b7afa94b5f6d558c2edb62097ed0a2b8b2f0744c2a80a387d48438378fc","nonce":"333b15353526478c0f77ffc9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"01fd61b9768cfc1dfd04d18aa0d532d000f340541d33e9703d81eebd6b48d67282964395f1ab55c5291eb21ffd","nonce":"333b15353526478c0f77ffca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"31c32b8248c1a5691aa92b792249554543953d106a3f5135127e9c2c231bffc359d6a30e44fa2ffdb02ae94d55","nonce":"333b15353526478c0f77ffcb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"2f6487f312ea9160c458d14548e7548739d57bd91b5da1d151ed5fcca6041581c862c6b453bec86140c9dce1aa","nonce":"333b15353526478c0f77ffc4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"06bbc06707d200b32eda29ebdaf42b5c8afe54967bf14306e16e5bd5dd9cb3026dfc3c14ba5e43d662ba90db3f","nonce":"333b15353526478c0f77ffc5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"8011b11b19489702a90026c90858224cf5a41da421d450b0b8212a67d04dc3960fac30f1065bbdd52d1119c620","nonce":"333b15353526478c0f77ffc6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"1182f335d07fe74e915fcb9ca34ab60c0166f5ce3da3d3bd6cb5f9a3fe46f8faad452e2bb527232451d8031307","nonce":"333b15353526478c0f77ffc7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"93cdd05e966d7e5115b29fb0685001c39609f4658e70c2a6b9425662516c0a5e75bc6567dde2d5bf43f6423b71","nonce":"333b15353526478c0f77ffc0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"923462f782ab6060d2b57590363ec8cfbf27a2305c4413259620315e244d7c1405fc5f75245a9f64daab98bda0","nonce":"333b15353526478c0f77ffc1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"f249604026d02d93708aa6db9b4c726a0b7f7551430f2785e7b55bf7d4ff4cc8949d9629830375a2b564a3a7ea","nonce":"333b15353526478c0f77ffc2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"1f0744abf755b620e216356882eb522aa942e46570f781b272320901bc5aec217a67367468540121ce43b9f905","nonce":"333b15353526478c0f77ffc3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"9b4e86cc60bc4ebe3bf8198a68571edb02d90067f0a1e0544292d851bb982ad62073a846e81480beb3d3c6cc7b","nonce":"333b15353526478c0f77ff3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"ee45580c77687557c01effd4b7c746307157a165ab8bd3759e673cfd7147173cff2af15e3ba4a5c0de2f798b2c","nonce":"333b15353526478c0f77ff3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"39d21e39c2ff4cc764e9e03bef55c736b698a3e792ec3ef9630fde5f6118b863f451f185826be7f277303cad7d","nonce":"333b15353526478c0f77ff3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"ab845e6253d09651b6938b456a93963d1132d9eecb11a4256302f03bfd42c86a687d585b0704739bcbd99edae6","nonce":"333b15353526478c0f77ff3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"4e3fe44fcb4c939e8c6f6864966d832829ee76dd1671b32361880563ba850dee552ed0c836489b332a6d8b4d07","nonce":"333b15353526478c0f77ff38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"9f05808ece3cc18161e38941b25cde1f79e6829587557b805a967a0bd68f920ecd533d337cc82804186a692414","nonce":"333b15353526478c0f77ff39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"e6f4670dca2c951fac4b2af28c6d09c86ead48f070ad0db49da0c63758368728d94282364a9cf753dd500dd1bf","nonce":"333b15353526478c0f77ff3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"d1cf924060db46ba1fc62776d1f2c682867ac6cb15513eae8af36ad2babd2fed2196ac3c78a0e09e2db6cfd0f2","nonce":"333b15353526478c0f77ff3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"288a517d5c7e94d4c1ab90892cc1dc4db661523300aee81aa592dc0f29afb5d9fd1473419f4e9fc16545af5ad0","nonce":"333b15353526478c0f77ff34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"08b3e6817dfbc71eadb43f59c671e2c951da1b4b369b331bb61d45f4177d4480ba01c933e9abf75162cf3aa2eb","nonce":"333b15353526478c0f77ff35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"1882b5be93cbc132e56eda769629acce4368e4c2bf84de0bedef90dd62ee4c5cef51cbcc93ad9badf748e80cdf","nonce":"333b15353526478c0f77ff36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"60ad75942d71879580aa92962877d6bd1fc5cace1bab4136c53bbd56d8d07274f2a41e16725e43b9f135e28e87","nonce":"333b15353526478c0f77ff37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"0b763d349c279485838c27046d4f324a10215f407a77603fbd6a328e598dd415b393463bb358843c63b5f0947b","nonce":"333b15353526478c0f77ff30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"9a567a23a432580c32387bfc7d769cfb44801f3c6e5e5ac71458f1795f280f2bc225c65b2197edc0628d7664dd","nonce":"333b15353526478c0f77ff31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"c3f7bce3bed7ea492af036b24cabd35a00dead7dbdc9fdaca1146b81f4fe1f9d8b835ccfada98affee1640ef51","nonce":"333b15353526478c0f77ff32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"4f7c428176366ec3cb442390d564447a6b5d3a94d2835b3216c53971a2c16c9b8b014baa81d5f8910ec21c7011","nonce":"333b15353526478c0f77ff33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"dc0661bdc14f92c4bcd0657c446d58f98ed07dec754dede7c6ecbc348fcd2bd1b1c016ddd788ea563609584d61","nonce":"333b15353526478c0f77ff2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"611da938708ff62a26d576834335c8fda4c631917105dbdfd44ef54e5c311f9621212e303aca4a55893a908517","nonce":"333b15353526478c0f77ff2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"af3bccedde249f37c0d6f2c326d62f728890293fe621c4185668a2c01c59c1113929c7e10bb794f59341607eb5","nonce":"333b15353526478c0f77ff2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"469d4d521417f20da3caab3e34ab6c99a789ab6c6a62542a00d83cdeff24706e2da3e4e27353dc61c4a3af4e2d","nonce":"333b15353526478c0f77ff2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"014dcdd3ca475bcc4721d0e79c8c0b18560c71ea7b2cfd21f589a08fc2755864115859b4a8e9844a613dd0cb3a","nonce":"333b15353526478c0f77ff28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"db21bbe9a2f4cd83d2f118ebe118d3252b831bebe070abec2e778035540db98d545347fc79fc8a3c54f13c56dd","nonce":"333b15353526478c0f77ff29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"b47ffb0a4fa5a6e6e83645aed79e1ed7240b17ab3a5ea17dfba87b6c57d66775fe253e6b38d944a95c4127b9ca","nonce":"333b15353526478c0f77ff2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"df2b606c85878516c89631daf10967ef78b9daa94082d1527e089b8e9d2a15facc976de55a13f2dd0c1cc8eb2d","nonce":"333b15353526478c0f77ff2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"f32505df312114bea55f8e67ddd83761707c2ad48c0a0a4e4e24eaff6decb252ebe50e538113f47a111952447a","nonce":"333b15353526478c0f77ff24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"4eb78ce844b48ff4620c4d909b2732ba0519c17b3c7836b7d3f74b601bede7b903b184bb8efe0cf0b9526c6a31","nonce":"333b15353526478c0f77ff25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"437fb037bd37e24533dbd0c7cd8dde513ed2c0190ab901af4083cb0342980c4afaddd52de730e42fad80fc42bb","nonce":"333b15353526478c0f77ff26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"98fb5b555314b1c66d1b1504430ab269afe3173313643c11bdd2ed058f61eee5c1cca4dcb0c1001d116284e236","nonce":"333b15353526478c0f77ff27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"5e7a21109c3594b057f932edbacc5bb5134d0f6eba2bc30b50187c33fd617a6f1059862550dac711e96699fbc3","nonce":"333b15353526478c0f77ff20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"4c2cf0b8f1d91afc1e96826ed163e592d32074f73ba320adc72929ee8725a20ffaf7fe050b592274823049dd9f","nonce":"333b15353526478c0f77ff21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"594cf8d0d4b82b1a9c0c045e60c713b53e96dba016e9813dad20f8abcf00e717bacaa29706a0a5a16ae8af26ed","nonce":"333b15353526478c0f77ff22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"f422d277123788d1479d3267ad20e84bd2114bf21ad96e56582c3a871fc64443e7f202548a23fafcdf66649d99","nonce":"333b15353526478c0f77ff23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"b1df3134424fe31ed24ca2bf5ebcca45a7bc295a481b0ec5e806114f04233878ff0fd4a5d12e7c30ccc9c4eddf","nonce":"333b15353526478c0f77ff1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"fd678bc2648d545564a1a9afda8663717a9bcd36f37f8fe9c9c624a2d81e13cc5bf5833f9eaa93daffa1cd5fa0","nonce":"333b15353526478c0f77ff1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"6feda2bd0cf1382c2d0893b2afb20bdce8131218c945cce076ceb6733925a9db83f5b59a99b95278908bd4d7a8","nonce":"333b15353526478c0f77ff1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"670c10af4b07336e6408ad7e3a8baeda63ca779627f6e186e74636c00c529ee5d820da49246e1bfd189f171598","nonce":"333b15353526478c0f77ff1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"0a8ed94f12b9cae651d3d2c5d44343ee4acf7a82ded5e4326d2041051289b6c5924ae1d5bb6c14392498bc5e94","nonce":"333b15353526478c0f77ff18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"980d97208fa72ecd8cdcf3043916f8e555aee957ea5f63315f30e086efe97971ec6a7f2ce2ed0a3fade45ada57","nonce":"333b15353526478c0f77ff19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"77f5da59757ad950b2cfeb79c8f518874362b7573e476be9e7a812aac4a719106a01ac70dcf9d6f8ccca8f3e7d","nonce":"333b15353526478c0f77ff1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"07445434c9ce848feb226726edad9e8c39b39688b5d7be61108c2615c5b2a81cdf1442a1f9b5dafca8308ebe2f","nonce":"333b15353526478c0f77ff1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"9fd9297442465532521f1ff09f348112e17fd342f468c20addf7046af3dabbfb5ead352d9d08f59f918459764d","nonce":"333b15353526478c0f77ff14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"76ab19b668778d54ec0059f4808250da4fd5348d877f13e9cba63e35edcc5011d0a3e17032900865daabdff01b","nonce":"333b15353526478c0f77ff15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"93c4f9a15e7e2a4d9e2b65184400ba36f7b3ef46e87818456e035a5d473183cb59ba405333a825548cc3251a8a","nonce":"333b15353526478c0f77ff16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"5c61e49c9616f5adbf35b04121053a3c0040a477d3024a901840a2bdf7d26dd93c0103360c3ad94995a8fc0553","nonce":"333b15353526478c0f77ff17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"18fc80ee6c4967ed96372419f679b6a060260adc823d409bbb19c1db661b35067cebeaa1659a9ac3c127b86067","nonce":"333b15353526478c0f77ff10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"7fb58f546a960ae9312fafb803e806980ebac41365b09c87b2733ae1a825712b49f04cb8b8ee00662390f5d0eb","nonce":"333b15353526478c0f77ff11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"818e7465fa323c574c9fd9287471f97f1ce29b7615ee59bf1f1a82dd76f1b363aeb04cf7cd94f56afd108b126f","nonce":"333b15353526478c0f77ff12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"e56f7c6f2431f6f9371c1b412ce1b2f8c08dc29cd9eea8633f93acb67fea55507e1c2071b08c6187158797a4d0","nonce":"333b15353526478c0f77ff13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"c9e52aa656286a1b7d817a949edc68be2e63d9f38fd6cd4ca722501f953931b217db0d26b6d191662f4976c63c","nonce":"333b15353526478c0f77ff0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"808d3f5c5b4f3f4b47d3ac828093657c620a400e92977fa3b73acb899012e8488139e333270c91b2628c5209ac","nonce":"333b15353526478c0f77ff0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"7145db4093dc8c48832a87bc019eef5249b96ebbf1e194168698209b5a6643f409956d2b5f963fac0bb136bf9e","nonce":"333b15353526478c0f77ff0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"184d8aa1f6a4430ebb6f8534a13fd0c66d95a84bb96f1ef398fa8603c374b16ad7debfcdcccb97caddb92badac","nonce":"333b15353526478c0f77ff0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"4e162404ae72474a0d1d2ec0670e7afd1b49c176aa00c400916dcce38789155cc653e2ca905875a6f4cdf3ba64","nonce":"333b15353526478c0f77ff08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"b5997823e81ede8ba65939a83b8c8a5e961887784f7cb5406ccb1ae4a1a1de3718f8216177faf0bdcba5f5b9a4","nonce":"333b15353526478c0f77ff09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"66e53913f4b60f115b092f172704846599072549d6d0db9a6c5d8daea8e02ed69a531088bb3506d19887ab22bb","nonce":"333b15353526478c0f77ff0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"86692ac7350518aa0f6b8d232fac9a16b704f704580040a63b4c815a05bdf105eeafd421e44661c23317d154b2","nonce":"333b15353526478c0f77ff0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"e1749efbbe5eb3755eb8fe278e5d89982adc920cd8af4b05e403cc553e7a72e9b714088377ad96140be572f29e","nonce":"333b15353526478c0f77ff04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"d37803719d8902df1c5313a56a0ab9847e680fbc21a3b290b332103ca539ff5fd3ff68bf3e26fdcb894617cd91","nonce":"333b15353526478c0f77ff05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"c691b94ece7db5351d0a2be5f1907cc2b0a923672986fc761ebb9928bd271b18a273fcc7a5f6cffdd30596c15b","nonce":"333b15353526478c0f77ff06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"93cda8c95165e0bbaa9a91e11d49615f32dbfbb31ffa4d1fb54c2b32cb34b1ef56d895d12973bf49ccc9fbe831","nonce":"333b15353526478c0f77ff07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"31af7900ae48a028d50ef823bc21bdd064a567971966e64a1fb17bcfbf42d50746513bf450a789ff7db585a30c","nonce":"333b15353526478c0f77ff00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"3b9cba2862b471a782949866a99d40bafd72db25632c2bb811b5f1b2eeddb63f32ded79bb3d4e4c511c5b87063","nonce":"333b15353526478c0f77ff01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"3596e05753ed93f22f3c80483256590b92333fe0c56ae1d93d6e79c3702ff431b501b1cf2dda9e9e3650a03c6c","nonce":"333b15353526478c0f77ff02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"6fcacb83c49ff6217c21e22af90df3a6ad4ef9913327d78f74a5e6624e71db7a9d4b842a573ab43dc55f918258","nonce":"333b15353526478c0f77ff03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"d4c6ca51c2d984bce33f427dde26d5534390c36bf311a276ce76509870765f566ce2dd6267b92fce693c0d26fa","nonce":"333b15353526478c0f77ff7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"bf5d7b516fc77ff2ebd89cd1a86bc32bd23a575ea5493aad1fe251399931e486c78fd07b4db80c12757c667c3c","nonce":"333b15353526478c0f77ff7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"edb72c6b0e0fda2168a5271ceb33def99e47780a1b4e2372b7df0ecf6429f3a6bcc3e21d80efcbe9d83af38e33","nonce":"333b15353526478c0f77ff7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"e91bab1ed434951fc054dcd4bdd4916d1323675ebe05f35b0b52b886fbad13b9bd49eea25bce875e53b33faff0","nonce":"333b15353526478c0f77ff7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"38c4465347455198f4fd30584ba8be32b1d8b0fa7661e2123d61e2dbf99f68ae35b084def66778330e772ae76f","nonce":"333b15353526478c0f77ff78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"18d0e59eea513c4e73ab0f0c5e14bd74c2f3f70e86f6b714346ae19e1b1ae7834b290968e0ed03968f452f3c40","nonce":"333b15353526478c0f77ff79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"9c204db5faa35931295e7042c4d4fad0b24df7cce3073c94b76003e85fc80195c6d573a17ca0bd2eda6e32c7c6","nonce":"333b15353526478c0f77ff7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"2b8d159adf182a1accc19dd0cc12079e921134ebb16f09f1eaf8c736bad2b4e817c62255956e6c519fce8b61e5","nonce":"333b15353526478c0f77ff7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"4702f21278f5c95a262c88f6e5fdb12005c4381c296924f5721fda1af368c192eba8d90c7e0aab648c2279768d","nonce":"333b15353526478c0f77ff74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"f599b70e2692ff67134176e9de75fe0f0ccac06d2d3ca4d1c044cf92375114768929d28c9922589047b19b3aae","nonce":"333b15353526478c0f77ff75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"4651e0606afd662f5478359a1f7c5dfd68c0cfe909a7121edea361d049c7196e33bd550bf41ae47585cb214835","nonce":"333b15353526478c0f77ff76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"3ce00762445a06482fa43db30d957604db252047e046d67c860d5541fb1f08f9ff1b230f0a96ee78219ff3a6d2","nonce":"333b15353526478c0f77ff77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"58f329c1f57bd941ef602b40176cf17f74420385a45a7d194e8d1a2100e6959507b83b5ac03adaec6ed11f0752","nonce":"333b15353526478c0f77ff70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"7e6ea2ade00312aed8af9909aa1c4058aaae65d5c895792854e4f3e43ee2e1412e6f8bda83025a448a7601a3f5","nonce":"333b15353526478c0f77ff71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"d64e97a6ab32a90fa80d2916bfef6ad0fd588edcff96ac88e12dca8a4fdd73470c83f687c1462e19f59bb9d6c3","nonce":"333b15353526478c0f77ff72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"48f6e28181b7215b70b2a794e7ba88e28186a28f365364b78cb1a65e3b37e287690b448d56da257eaa0276300d","nonce":"333b15353526478c0f77ff73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"3f53611a6447dc011755bfbcda1d3fb1885e3ac52b65b23f6e430d1ff098586c4ea7055597be4342447ad0fa19","nonce":"333b15353526478c0f77ff6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"37409fbfdfa635c7db21ebf9eacee7df002754a7396d3b4ad68ce1fb0699dbbfb09ed70c82dc41b962eb158284","nonce":"333b15353526478c0f77ff6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"18caec3e7f33db0ec6394d53d18c6604fc9a28de4c023e2c1b08573d08d26a99b6171ce750c46f8e5b5c13636a","nonce":"333b15353526478c0f77ff6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"1daeb0bbdbf6690cf575012f578dca3fcac54a0158c14d4a739c47b3f9fbc3aa0cb0c41fd5f10458a9760b4f62","nonce":"333b15353526478c0f77ff6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"e37b1544c399bb07ca1be90694335522b0af7d0e9b7da63a85487ba7680939179b328569bc6b71f7deb1511f2c","nonce":"333b15353526478c0f77ff68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"bf115c163f8ff92c8c47be92e64683015c79f81b774420659d661531bb869360152e0a412179a4e560cd9a8b57","nonce":"333b15353526478c0f77ff69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"de043c8afb74dfcfc9a090094a959ac4d1c979b90e9ab9168653a4a85bfcdb0a0bceb4c4de256ebf7a737cb1ff","nonce":"333b15353526478c0f77ff6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"36ad5ed0b73f620c81b486cf1d7170a05fbe5b91efef17f142da0f5bbbd0c858afa8036155de64a71e5c521ba1","nonce":"333b15353526478c0f77ff6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"e19e25399081aa38cf2aa1000f8f8b73a18421a7b61017bd95121fd547bcb2d3b1baf6f7fa5bf0e03e6335f112","nonce":"333b15353526478c0f77ff64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"07c2cc1b7504fb823059f255e4075e0f8b42c815e8cc094ba6f15719787f308e363e381983b3f72cfa3e3a7e5c","nonce":"333b15353526478c0f77ff65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"c1fa55e28b65cfa237c3d2db53a704ced1e6da7c7691bf030a6c2ec68cf079914e8f38eeb8be05a076b5470413","nonce":"333b15353526478c0f77ff66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"359349e16e2558531cec607d17373e99f6ef81c8b0c8adda56b2f32e2d35a2b331ad5248830f8bb1cb38c040ef","nonce":"333b15353526478c0f77ff67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"681aac65bbfd31dfa8d190d77c0b49fce4964d292d2d06f1d96ff949c2db0f9b2e359a289c5e86f7e188114cd3","nonce":"333b15353526478c0f77ff60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"e65dac78f7dc13058b9e758339da967a29723563eada44ef1200118af1f07d911fa3f3f1589b671dc04e52c672","nonce":"333b15353526478c0f77ff61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"b3cf29fb27bf1e9fde9127b24c18d14f4d87e458eaebe4aed2fa3bfb4a7402ebfef55ec2480f690a7fb510e834","nonce":"333b15353526478c0f77ff62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"aea482ebb273e239e99d103306020bf58f26306dda1294835940d344d009e9ffe6be74922ee3183cadcd15b532","nonce":"333b15353526478c0f77ff63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"aebca4f6a8b641045353f73df4ea5479951753f6092d883229f50e8ec3a6147b16c743e10e689c90ce3b4276ac","nonce":"333b15353526478c0f77ff5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"b9995d673d29dcf0b828a0dfa5f440b4f2fe5b9ae5fd984428b2cd46fed136dda693a50440b3d3b19cfc9495ef","nonce":"333b15353526478c0f77ff5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"9b5149c8b52fb0134c7cf8a0d689d5ac2637d19d9bc7e1bb2be0f036e29e69a2dfcbc3223da8e7d608ceb35c4f","nonce":"333b15353526478c0f77ff5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"c3b1c80be5c93768776d5f07da133b391fc0bebef25f987de601c374aacbe3847b035a1ebe8c460598951149a2","nonce":"333b15353526478c0f77ff5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"1232d0517575a7f95521878dab94bddf8dc167b30af355463a4a79b4ffc14c8523b9873451a5a9b2acd30f3014","nonce":"333b15353526478c0f77ff58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"30d6c227dfe9980e23f5ffb413f3db60ceb76159cc4ed61624b6d01cd4f39b12fb373180ab4743027589abed3c","nonce":"333b15353526478c0f77ff59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"0eedf2b7b3a00dbf2ae077f19d2b58f70708c02423dc0af5ee1edf570d4383b4819e3ff1db309f33f9a4e46441","nonce":"333b15353526478c0f77ff5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"e952e2f1f4daeef7f10b1409deb550272ff6d8262eb5381365f852a3500c26a81de7b88d87be940112213d7c69","nonce":"333b15353526478c0f77ff5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"5710387de880649d0f89ffee212c6ba229f2446dfdbce247f75fc6006a53d0140988f3e4ea92d5addf5aeeb2c7","nonce":"333b15353526478c0f77ff54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"aeaa8bc783f7045b9739fe7d2959a1ae7021d588e929e358c0514af131bdbf936733222b3c879d337f913afea5","nonce":"333b15353526478c0f77ff55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"9f4f2ac304bac6720b10b0e10fd22108da6afb8c874ef5bb5a9d2dac7f3e32799795cb034567dc24d339cb6cd4","nonce":"333b15353526478c0f77ff56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"8ca434eb780648e0d3859cca4aaa386b37ce0f96f648371b4f226a74db021f388fc8f29ef12d30ecb925d8b5b2","nonce":"333b15353526478c0f77ff57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"0ec6e79768d1f38142b093a9bb4b07139fd38abbf9f2d539b3b736e074f21ef6b2cbd66329d080f000c0a5fdf0","nonce":"333b15353526478c0f77ff50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"9576cccef877a328f6898ad313f949dde3d91d51c12b6fdf4cc4dcda86a2fb238c9f006707bad6e1b8b25f055a","nonce":"333b15353526478c0f77ff51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"8aa7b649d4b90420f0f0b81ebd7fcb238b5bbb2b55a2ee4c9a66fa4773c14d8e171e786866663ad8c20a99850d","nonce":"333b15353526478c0f77ff52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"039377a5a7662fb06d4a347a90ffc84437038907ee16535e531d18464aa495588230fcbde965fa1a7168b93dad","nonce":"333b15353526478c0f77ff53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"09b5818f33d7895daa90d0b3a8c9f096d7b8a1076dff6052cbd5689f1cdcf173fe3c384a71a9b88a674e172bb9","nonce":"333b15353526478c0f77ff4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"2c54db79ddb430493f975a5f3741de60471c6438b4db8adb3da0244dc7556fc617b3e2c0b787ed044097d2c52a","nonce":"333b15353526478c0f77ff4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"e1f3373a1f98cd68b573eedc9f13ee8130c1d9470d85f992a5038f87420af3ab4e18454b43c95ac9c4313e5936","nonce":"333b15353526478c0f77ff4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"84bba2611c670926a07d1cb0ba9ba71cb161324bae417336454ee990533697b1657fcaeabe0480a3675785f291","nonce":"333b15353526478c0f77ff4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"808092353af5b013b11d7acd2c8703c60b58f0bb006d064b0370645b59dbc8b19736440a27f6c02a6fc336b9d4","nonce":"333b15353526478c0f77ff48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"78deba4d2b9ae445a54a156589c635d3017319bf614f7d02368359eb87e984eaa9e5b69be947c065887b476ec6","nonce":"333b15353526478c0f77ff49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"7ba0a0e4a1a816573857fa00efa79576cc8e1b734fa0ea57ffd834a5937ec082d91212d26a646c1952aec9f17f","nonce":"333b15353526478c0f77ff4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"8cf0bc366506452ad8d16a2042fcafd39999764cf89ae9adf98d6e83b864b405b1744db1318edb2da1d749f2e8","nonce":"333b15353526478c0f77ff4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"3e4b41078650d217abcf94cb7afca76e61d6625e12d8b7bf6ba6d6258fc0fbd2e81efa8887ee9f3d1bd9cd16e3","nonce":"333b15353526478c0f77ff44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"d9a5988536bca3b50a189a7e830ae96c04bc2120c9ae299bc6d33b7332ee78ad10860e0c4389b9db1ed0cc87b6","nonce":"333b15353526478c0f77ff45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"9e7c867d777d22a014c1f0945e10ec91fc0d9ad60949a2dfdbf1b0b2739445480e8ceece4e3debe2ef4035f53d","nonce":"333b15353526478c0f77ff46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"634d14aefaaa66d438da5610036db8e88662afe09fe8698faea6397082afff243302262d63d941a5db5fb74475","nonce":"333b15353526478c0f77ff47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"f986b8a115871c1d8212932595d660a0177264fd465ebc131a0b1ba88b938236b1deef1e9ac31749984cd05500","nonce":"333b15353526478c0f77ff40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"aa02392e9fa401ed2df6898e7a9ad33e8ebd96b7ec1b13e1bba4d5198288f54d01426f21e10b32a191b61b255c","nonce":"333b15353526478c0f77ff41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"def75d07f28b7a75857b5e1cc6b01e1e4c150cae8d37a2fef8746b03f2acbd5ea218555ebe0c9e6ed77c8bffe8","nonce":"333b15353526478c0f77ff42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"6c46e0ed46a5147d999f2354533e0976721d1c3b93480d80225acf2d59158d088519185e925c92f2a5b1de8109","nonce":"333b15353526478c0f77ff43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"63a7324ff92ca62570d4b7686f1c8a149fb5e366bbcbcc766aed0567d006b32b624c3c4fc99ea971df79955668","nonce":"333b15353526478c0f77febc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"30105e03fae2e57b00c11ca3251b3d406403cc22e00cb18fe2fb19c67cf3a41c"},{"exporter_context":"00","L":32,"exported_value":"d56112325240d302949056b6704456c0cb4ff369b56e6d73b155907c4ccf22e6"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"e5869c4d97bdf31e404f59ad97dafcbdb055899a93bc5be025596806df5ff35c"}]},{"mode":3,"kem_id":32,"kdf_id":3,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"c0299139a3f545fab8e8c76f6166c3589ba8955fd54f1f0475f1cf0117b25daf","ikmS":"ee57447531b66d118aef5b023a767e44ecab4f33bd0f5c86de0d67bbaffb0b0f","ikmE":"b90cce16fc2816b5f74c0b2c2fba6563520c267b1d83c6574909b679e23560a7","skRm":"cbfe2dc2865ddf512f120e3c10e25541d38d9e52548caa30e2c6c7e403078ab0","skSm":"9f1ab951c96e85a9a646eec01dde4b772763c2f96516a43a07a73a6d8f7c21c7","skEm":"c6b5951ca2b011c0d7c504dd63b80621f6818ccbd63eeb41a186216f42bc11c8","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"8713daee1029f66e3070b827f6f6ae5b44fc32230f58fdf1054e4cac28394b01","pkSm":"d5f26c5861ee947fbc5f28f7f219da862664c2e0d11bcd0adfc3d8e61ea8dc0c","pkEm":"380028a0e8ada593b90883ea56c56e3e30411fe5f529e61928113d9b90376a44","enc":"380028a0e8ada593b90883ea56c56e3e30411fe5f529e61928113d9b90376a44","shared_secret":"8e83226f29f5dce2f4b71b10665e0cfbae16b23f28beed6800ceb10bbe49bc96","key_schedule_context":"034c00167e070c0803ca14469cf4fa24410a5c52e941fe6042d618ec513da1d7689535366ec6bd0534307b1d59b0a605325c437890fe56676a1c507b6cf5e46e9e238f3e66e519a887ea3a0d096475a5defe5bfd1d22ec386b880d050dbfb6995fe8f7d1d0c661c4e10698687f757b1e981cbf025920074204ff660b9f490d7594","secret":"6e3ab1f924c374083cce3db407b09eea0bb49210fa4dbd608d003008b67c1592519242314bb19a42700abea6c2f5a99a633b20170043fa7e9cee6567db632e55","key":"8044493907975b9fb099ee8be45c480dc1cdbe5262733b5728a2cea8cc11b0b5","base_nonce":"5f01ccb22daffc21ced480f4","exporter_secret":"ed3454bcee71bfca04fb29a2af634599d3aa5758ff45bbf1422c6ca0373590156730796f527edb4f4406ca645d2b3832f39af973141a2f5120bead76c175dc1f","encryptions":[{"aad":"436f756e742d30","ciphertext":"4a119ef3e29b494075a6488bba11673b09adf60ae21ffe0a9531e91833bdfc9f9e6e3396d943c8d749daaae3b9","nonce":"5f01ccb22daffc21ced480f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"2a95375a1bf6f8a363e41029e8dd90cd2f51b9fec06a93f740701f68ca3aa375f72d46190b5b1a12224abdc215","nonce":"5f01ccb22daffc21ced480f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"872f8baef3f651655bda34a8897a9bb079a64c6cfebc16abb787f67a08bffc1de5591fedf0ffc3dafed6a75064","nonce":"5f01ccb22daffc21ced480f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"46f64a09ea41c2eec311b414a4ded7d5d0e6a507ec550ec912d705e1482399cf1b389b27d270a2adaf70a2829b","nonce":"5f01ccb22daffc21ced480f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"bfc38a90da635331aab462b001a8964311abbc4785e5a62acc82c2ac3e09f88fc59231ab48848f4eee60a725ec","nonce":"5f01ccb22daffc21ced480f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"8e0356daf2482ec15733ffb34d990673ddf97e108e07a5c3a988022490287eda3e3c985358b98d26d482fa61c7","nonce":"5f01ccb22daffc21ced480f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"7ee761f52b683de38532c3d58ec4e68a822fc1ed5e7e04b2f7e95b70aa86e589518d1b4228884ee06d0ea06adc","nonce":"5f01ccb22daffc21ced480f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"4be2f85443df48825bc3285e99f5982945195193ca57312ea40ccf60dc7db91a42447e20723b63b3020dc15a02","nonce":"5f01ccb22daffc21ced480f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"9fc0328978bf716677118c06e1f7e215485a09e584ec766427f424b4650f41104f3e797621ab7bed3359ddd294","nonce":"5f01ccb22daffc21ced480fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"91fc190d8792cf262c8115a9609c0ee4e7b21a76d3698af2ca0bd65d2cbd605d2f3b9fd0db157ab394e5f74a06","nonce":"5f01ccb22daffc21ced480fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"9fe7846d06afd210a3c54d489c033874581ed749e9725a5119c6f341711b80ae4ca5a4a53debb9119ebc8e7aa0","nonce":"5f01ccb22daffc21ced480fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"54569bc652ae34b9c64889f821ac5fede30032d42280a43f950d0f0e218315f0615f3fc61d6b29bd14b2c5980f","nonce":"5f01ccb22daffc21ced480ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"6aab2acb7d622b9b745252db25ff6038a14561827453b3ba3bc1e0313a76b9b8577bd07e74dc474b663608e212","nonce":"5f01ccb22daffc21ced480f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"edc6f6fe6bbb2d1dabcccc849a3245c4867f88f9c1b5c943342b55611b5f0ac55e76e46acb2237b7d1c65128bb","nonce":"5f01ccb22daffc21ced480f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"037013ada6cd079395322216489eca2727ce83324d7d0fadbb04ae346017c56121dc7cdbdcf710cc1001862760","nonce":"5f01ccb22daffc21ced480fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"3f1994acc7097adf2b7d5b9fe6e6dc5efef24dbdeed6bd95ced36c3029cfd7e230b6604ffa6b299ec264dc2d44","nonce":"5f01ccb22daffc21ced480fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"1bc9665a60d1732d8195b74c4270e81747d878e50906b2385c50f2c4b86df4ac837837ce6ba4d9796e898780a0","nonce":"5f01ccb22daffc21ced480e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"06343a73a54ec49e90e691bd22b1089555c1ff4b4a6026facf19556e2ba7cdce494c2a6200d506381a399fea1d","nonce":"5f01ccb22daffc21ced480e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"f587b86a8260ea10981b9f5c4591694d4338bddd52ac3ab63101eff2ecab86bd3f322f05540da23f65df5779bc","nonce":"5f01ccb22daffc21ced480e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"e03bf85ee11c30d0e42b3416902c13b6cca7449733d9d78c33a224390d39cb8943db28ec6a9dc65848782117f1","nonce":"5f01ccb22daffc21ced480e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"d581eb4d049a249a16d9495bf150d00ee4924837184eb50942d9a01be4547e80210ba404a66eccfd5a1d1264b9","nonce":"5f01ccb22daffc21ced480e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"cbcb8339da0b825e5ed53428ae7b1f5a5bfffabccc02a415ef3dd7d7b8b7fab5d684f4f53ed73a9d9a947aad1b","nonce":"5f01ccb22daffc21ced480e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"1b13acfabadb329147dd059a573cdb28952583305fb5be0977318ddc3fd4bb8eed37a31d73e934b87a0cdd0158","nonce":"5f01ccb22daffc21ced480e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"2d40903f8854a7065ba3689faa0972723f903a1773da723050fea14abf6758437d7e1739d7a288e2ce8c65e42d","nonce":"5f01ccb22daffc21ced480e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"046e0f7d50baccadc6b2504b7b667924f148db755659ea55bd8f448998eaf28425f505643831bd8036ef94405e","nonce":"5f01ccb22daffc21ced480ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"dcbdab1ff1af052fe64c59a102e659b9596f5117d06bdf74cb11c3e7534195e5eff89ae4c2a884a49ff7869325","nonce":"5f01ccb22daffc21ced480ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"bb6f13bc17431df03a666d597e2394896ea2fecc9065b015493e08ee832fd8a30a2497193c0541ef923823f593","nonce":"5f01ccb22daffc21ced480ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"87e079bb01a77c87b38ac7bd2d06f37ca0852df30d8ebb71f3c3e8114567a21c0575a383148ad9d621060f030d","nonce":"5f01ccb22daffc21ced480ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"ebbeab6187c012062adadb2c97c33597a1cb5657556254e0382c87e5e64080f68f78454c2253d98b6176dfa9d9","nonce":"5f01ccb22daffc21ced480e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"1033ea2ce03ef5a2b463d73b092e9f85ad16a748072d4d0adc6e7d2c209296975109fbbe69238eb8b9d46d8762","nonce":"5f01ccb22daffc21ced480e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"7936cd8cb005852c9e4d6c1dbfb3ca91eb82076baa312bc963ce4328960cac1d3da31506789173744a97c3d834","nonce":"5f01ccb22daffc21ced480ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"7af23f0a5642f30328378b5397439e0bd0d27ecbdae8ad0bdde3faa2505ed9e97b084064e87bb5ca7c990fd824","nonce":"5f01ccb22daffc21ced480eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"af69e939729776290521ce0ce1f6025a0b805edc36720a9d9d731b9a3b423e8e6fa9d0cff52ee845378ddc90e3","nonce":"5f01ccb22daffc21ced480d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"a91d1454db2699f697e510ae00d0f953b5db95c75f39f9a9198e21cf3c2f0ce975e1be0b83132d0866398045ce","nonce":"5f01ccb22daffc21ced480d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"4e77dd2eb50288f80c313dde541edf9d1fbff3fdb199845930df54932443d9fe70e85b1916c90a4ef35d9b05fc","nonce":"5f01ccb22daffc21ced480d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"8f5999e5d92481c4323c2004d43cd99342138fa37b24d50a7b61f2cae1120565deb33c36d3e50b6bad289ce5de","nonce":"5f01ccb22daffc21ced480d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"d8d6c43f70e755b3f2958e09038d1741401cfcabe26280eba25a3e54210d5688cf23d2dd6fc777dce5e25da7e0","nonce":"5f01ccb22daffc21ced480d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"2371a05440feda1d86118c1f4066a728c1a012dbeccd8417c5c67e2b62e1ae4124d4a71ee61b24338438fe4d23","nonce":"5f01ccb22daffc21ced480d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"70054a52f68e5cfa78bc1944d9abe465f94c8711f739df978c8f02a18eb1a61fa578eec51f5f0ea5776aceb512","nonce":"5f01ccb22daffc21ced480d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"e885feef37e46bd56a995b670170e39cf1f2e16347f2f1b9402d8d69300684bd9916d05fc6db40591116225a67","nonce":"5f01ccb22daffc21ced480d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"38d97cd4c6f83c083e4221ea80f39b7aaedab81d5ecbd62d6d77d195a539058035618f2490765bc41c1587e04e","nonce":"5f01ccb22daffc21ced480dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"860faad2a2bf3ddc6f2ac8cadde60e8125357bc223dfd2409c475a9c1ebf71bb61978b40d562eed7d925f773d3","nonce":"5f01ccb22daffc21ced480dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"344eff886660f48b8511f956715f307821811698906a1e7aa57ef2fc0ab64668b9cca4c750f1384e7a7181465b","nonce":"5f01ccb22daffc21ced480de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"489e789f8ad42e454ecafe61609774691e6f7c3106d6dc7970678b26e7c4f24204851b8799227a2da5060bed25","nonce":"5f01ccb22daffc21ced480df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"11f2e3cc1e1df3e4beba2b119834ae93073233032515462482e7b3ab1c2535ca83d483eb15f315c661693e3b31","nonce":"5f01ccb22daffc21ced480d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"738e8f8fd4622e48ef05122730b908fae3e0fb0bd842f4e6fcccc8bd20326deec8b653b5c7e1a5686e93919c31","nonce":"5f01ccb22daffc21ced480d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"3b930d69b0af5c4b5576c66430fe22230adc8df70fcd8373f3a61d627da47d6dd49de0b81133c407fce8ee1295","nonce":"5f01ccb22daffc21ced480da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"c2ef044fcfe6aad05fbb67ec367f03549bc4a667ce54a7b3aba4ec4165717a13d87ce2193849ce8e4bfcc4bae9","nonce":"5f01ccb22daffc21ced480db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"733e08a7b3dc222fd10a4507f7427cad4fe5d5a3d2f4f52e274cbf5864873d43b92807f06e5b38267329712632","nonce":"5f01ccb22daffc21ced480c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"b6985e4c8839ec99e7eb3d4c87411c22a261a55d07beb29923a67744ad9c1460022f12401a4e8732cf3ff1d57c","nonce":"5f01ccb22daffc21ced480c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"14d3ef88259545106f7753322225b8401f7d2ada0f604b431687214ad2f8f01154a712938914bd90c169425ca3","nonce":"5f01ccb22daffc21ced480c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"fcd31e25ffba047077803ec410a87e0c4d5e16acadd3ce250595ed092c4db4de5be414bedd2143680f2ab5ded1","nonce":"5f01ccb22daffc21ced480c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"b0be214e2645cc01250e5ac889e9d42b198ac1c5f6ea2034d397d6cbc2220eeea8e298f19f4dc962f171abd983","nonce":"5f01ccb22daffc21ced480c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"318fdcf6aab4299c11e11866289cadb53a7f235a1e9e058dec0ea736d64da8ac03b402acc13a6ca7263b0ac300","nonce":"5f01ccb22daffc21ced480c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"38b6c0c522e14d0ba8391e50b1fe08fd9eb72b33d2e6b93556ca5836032b45b719c875ccbc3ea0f088bf7f7796","nonce":"5f01ccb22daffc21ced480c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"764dce19ab6d602300858a3368ae72007285ab2c201055eed51d733049bf80077257657873c37c84f388bea983","nonce":"5f01ccb22daffc21ced480c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"fc288eedeb9a4e1d665a1243cf488a8d4e97cd3d36405e7c08591ff53c8de87effb06bf1734a03c80ccc7f4872","nonce":"5f01ccb22daffc21ced480cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"bed4c01d20370f971447b4458cac5af8b5d7d42142604f803993e3355dedfbdb6715470b8e18b69ac893ff6047","nonce":"5f01ccb22daffc21ced480cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"2b62029f3b808e75eb06cfcc697a3d8ff51f67af8efb50c6469367b540f2a80a9329e0720c9e8166ff156b2c8b","nonce":"5f01ccb22daffc21ced480ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"f07555243afed27078c02d8adae4ee325d1e6b62bfcb6b721eb91d33877a3044b0a1b48dc6286800c685d5aa47","nonce":"5f01ccb22daffc21ced480cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"a710a7aabe07fb04dae865212acaa5728d8130ef1ba7254bf79b86b14ae03086f5fc3a6a823f50ff0e3a452164","nonce":"5f01ccb22daffc21ced480c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"7ab6c87b0bfcdea115235b6632311f866712bc18b2030553e5c4a61826acb7d23f1ed263a5d8ca34f5e4ad5d06","nonce":"5f01ccb22daffc21ced480c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"c19f1a836b47e0909d6bdb1619baec28fcd73e7e2f48a40bd290cf466a0976328f04c219c83778524c1f8573d9","nonce":"5f01ccb22daffc21ced480ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"27dfd74e2e52bfb6a46e4608957a19e3cacc6a8c27832a357fa671a0676f01a6cd17b44fb1b7caf754e0311246","nonce":"5f01ccb22daffc21ced480cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"6b3b3c27d97907dfb676317f2179dd518f113dc605d717d63e249a62cf3c7914c6c315eb5d43409ff9653a432d","nonce":"5f01ccb22daffc21ced480b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"e2ef278193a7b0b9d01dc968951eef85501101837eeb5968d3e83d52ded4b9863fb9295e6dedbc5f48958199ee","nonce":"5f01ccb22daffc21ced480b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"23c4480e6074958e990b8ce2f4c61e9d34f90e86fa2ed43d39f252b92e25a65eef486a62a07fc5078be652fcad","nonce":"5f01ccb22daffc21ced480b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"c453fe9eca130d530dde0caded4c9613e70040c37ee9c6aaec191ea516bd40c1a936644f6277fdde0c3fd4ce05","nonce":"5f01ccb22daffc21ced480b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"2ca5982be45ad969ce09d2ede41b7fb85837e0483f7bcf9cf7a7bae0de2db023513992c88991e8bc0675f1e5ab","nonce":"5f01ccb22daffc21ced480b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"dd0f75c48421829ff8787f66f721546987b57bfb1b1485d132c4226bd1c4e29bc072e314c79421d589ccfc3c01","nonce":"5f01ccb22daffc21ced480b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"56145eea8bf127c0806c1d3b3ff3c8246ad7641aed08e46504fe4640bf376a17b39515889c8c8dfa7aa1df6db7","nonce":"5f01ccb22daffc21ced480b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"4696e7ce3e4005ed58c7f93cc608fc01cf0033794336a9d6704a93facdf487e54f92fec6b36f6a394c9bfa1cf3","nonce":"5f01ccb22daffc21ced480b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"95c89966d16686c26bced029d367758c6da8272dbe4b1ac821e57f5d7f1d1d12678e559167e8dd2c0bfa497da1","nonce":"5f01ccb22daffc21ced480bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"d07a2ca5e857cfa6989d193d2242f312a8a130dc73c60d469eac2d65a4500fab1ea940080ed6fe9c452e8ae39b","nonce":"5f01ccb22daffc21ced480bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"43510133ab5727d5ac219f9504b3fbc2cbad8cedea8dc2a3555dda771cc1897693b773b1cd4ed47531fc57f269","nonce":"5f01ccb22daffc21ced480be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"7defafd6efb6ed62a007687a30bc08186a0d5b9a5b72de8aada024de467d9c7527e85692133c99d0f035898d97","nonce":"5f01ccb22daffc21ced480bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"b6f527e4238b5d49b415c0e1cd16c04e69d9c7719769683f35617be1bd0f869a63f6f24d9c1a31c27bca5bfab2","nonce":"5f01ccb22daffc21ced480b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"3b0b2957a25b6be7318015e79ec510c42a01b4014b3cc36282ae99526cc8a3b84a001a736de9ab5b9ae8ecb189","nonce":"5f01ccb22daffc21ced480b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"8646a321b5cda20c0b56f42bcda341c21e74940e4d0c80f8a79d357236e20e1852259ddf57af14b01e96688067","nonce":"5f01ccb22daffc21ced480ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"7429b613f9eadb2bdbbe698e5d0cdca14cd76fbf979f68a9e2ee0c91a5f25a8bf175be415a8837f78c4147ec30","nonce":"5f01ccb22daffc21ced480bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"47208d84cb93e98d84d554045fe337e7fa6b2cfcbeb871716c22ef50f54d7cf15120fa13aa095e5340d9df1ed4","nonce":"5f01ccb22daffc21ced480a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"c701d43b35c4595fef4ad25e9917fe2b766a3fdca3aa2386e55bc068102da75043b77d2e2cd8e1741b9aa4c0eb","nonce":"5f01ccb22daffc21ced480a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"cf8b5867aa3ede88f9494994c80c1283d1b5436a2da9aa069ae68372188f38ee636fc313c8f0fc9c05d2a5fe19","nonce":"5f01ccb22daffc21ced480a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"565e4872c5eae9fdd5f94de14f9ce0cc14d7d80fb7800dcf5e238dd36cd815797baad50f93f9ac007c8db2ab90","nonce":"5f01ccb22daffc21ced480a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"50c063c894e23b19d0e1a49feb75f5caa5a48d82f3f5b55a0f93eac443d335a85c047304d5624e8d0b7290d309","nonce":"5f01ccb22daffc21ced480a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"27dbdb31f90952d7b6d5a9702c176861d68b7e0b86bf51c56dd2ab70236b051763d5eb60597b6f350af4c8b419","nonce":"5f01ccb22daffc21ced480a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"f07878674ccf836b7bd8b08854c2e8abfd3de53a570c776900d522bebb33dc775665f2bf38732b3e3e97618eef","nonce":"5f01ccb22daffc21ced480a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"d4f0ad170f261c7c15537c3c4f3bd05358941fed92e98a4336d24053155bd4e06c21258270469f42f5559cf94d","nonce":"5f01ccb22daffc21ced480a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"9a633127beb1b5c69ee2a88154f20a2b00818c82320354c776a00f494adfa5a9043629fb02dd3b104a0f7913f0","nonce":"5f01ccb22daffc21ced480ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"871ec1044cb11b49db2f02c439070a369a3d4da841b46e3993a9e0352a2d25b8695cfddafc375c1c904364a1c4","nonce":"5f01ccb22daffc21ced480ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"a44f197f7479defe3c54a1ec6599acb36b2809ff167395ea2e45ebcbe6cbfcabb92c11e6d15be94d7e3c168c64","nonce":"5f01ccb22daffc21ced480ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"520a486971b9a1627e01692774fda0458f635778f9e7db5e993bfae8c56db5b18477a6d07d4b8b7aac336583c1","nonce":"5f01ccb22daffc21ced480af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"15d74d21ea13fba10fbe8103d3817543b75ceaf625cdfcc8d0d24f4c6f527840c49a2d144f2ed8fda837291431","nonce":"5f01ccb22daffc21ced480a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"6f76afad99124a44f356c7eb8473ccb9907879c1d9d518223e0e9b591426d0e080a3fd35db80f68239c7eefc64","nonce":"5f01ccb22daffc21ced480a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"dbe7ed3898aa741328d0c0cd22cbc1483931660b90555d253fd994160cf2216f1e0a9c03f8aadac286d161c357","nonce":"5f01ccb22daffc21ced480aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"7397c9a2c8c4980d42d916e98a2fbdab158073610406896eb3e773f1e42a9007620ddbcad12ff74298128c33f7","nonce":"5f01ccb22daffc21ced480ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"bacbe93876c1e8c5f65fb6052f3752d725387a0afb486eeeb9332bbbc5d0a59e7460f3f0e6ded3e8c205721c9f","nonce":"5f01ccb22daffc21ced48094","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"c1587f934f3987d70301e8356ce422f81fa9496a4fb0a97672eb30da5434f0a5ef7ab70cdfffb5f28699cc28b1","nonce":"5f01ccb22daffc21ced48095","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"7dd6decee51f0b85134b0c7ba3a5c2c6b22d88c9ec201ab8e4345ebfacfe699e310e724ab033e318a817e00e8f","nonce":"5f01ccb22daffc21ced48096","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"ae38e3e6050bd51e08950f023835e11b7cd124db8ca8c43c6154872ccdf83826b74101abe52b6aecaa19c9722a","nonce":"5f01ccb22daffc21ced48097","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"410880f448ade4e1a24dc579dab82f9ca43ecb995874e6fd9bb949196571d4ec2c37561eff80561e9df41b2633","nonce":"5f01ccb22daffc21ced48090","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"0ffd2aae1c1126832eab912d5e0129f2ea11fb6942eaefb3b1ac577756b45e6fd5ae0534eaf308b475b90f4429","nonce":"5f01ccb22daffc21ced48091","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"9326459eb5a9aa0ad22e085b155ad1ac9e9d5443a0ad9bd79da437e1f81a27ce2cf48dd1ed18af635bfd8c4f34","nonce":"5f01ccb22daffc21ced48092","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"70b2022158a7193ef757835ecc2355f4a4b2e0a9cd2192581954d3fabd78fd5ba085c90a55c0e99aa6a32f9192","nonce":"5f01ccb22daffc21ced48093","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"fe5289d7c46575c26aa3c994f56a81484e6a32bdf143c66cdc4a26837e6fea47b9c3bfb8469f2715e02544bfc0","nonce":"5f01ccb22daffc21ced4809c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"8b8c7e3669bdb2a2f4f3faa08668778ed00749a134fe15e40d6327cbf35ae49a0be01943642f3ea09d60b889ed","nonce":"5f01ccb22daffc21ced4809d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"c6ee549beac35a5532ba75c6a7955d35884c02f0104583ff3d7d67a4102b894df79cc05ffe8dfac4876b57f7b2","nonce":"5f01ccb22daffc21ced4809e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"d09d5cd14a2d5786d648dac82d3e669620c4b6c4719263e57f2f517176a363b7c81502513e895692f29f9ec30d","nonce":"5f01ccb22daffc21ced4809f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"4743ac168524c4e19be5525cfdc8ca42d7783bde33e40225237cd7a0171bf2b0cbc2610a86c8b8d0a321b3d846","nonce":"5f01ccb22daffc21ced48098","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"d6acb54de32eeb20f6ea713e10cc30913fdc3611cca1ed2675ec4b0c23e2e78f85adc9464b4973a1f74c2f2d3d","nonce":"5f01ccb22daffc21ced48099","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"1da751271500337b538593bf5bade8ac62ac0d3c8638c2c507c642776890be2fdffe25fa804d54c976ae40e7ed","nonce":"5f01ccb22daffc21ced4809a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"31ad9a6455a6900d6f7befd923a2bd34bce47ab9fef4cf27f33e7e5ef4793c6ff735710510a6ac0ec871732f86","nonce":"5f01ccb22daffc21ced4809b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"8d2d12e59b38930c5eb9944fba54ec7c2ad73b6cc1ae3bbc26434840c7bd44252adea220733a86294399db0cea","nonce":"5f01ccb22daffc21ced48084","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"4e5f73aa30bba09f7ed57c6131f2168b9a872047a8ae31fd14d1c556a6edbdc892c598157b67d5364711dcde17","nonce":"5f01ccb22daffc21ced48085","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"266c575c1894a51c6e9531a797d68ba5979e317429a9b7c899002e0d0bc12874b90275a493d7244105d0ff4789","nonce":"5f01ccb22daffc21ced48086","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"6d94929cf338233832f61b0ecf82b21c4aa7165ebb5a8659d747743235cebe40a9c6f42cdfaea2ffa44dc9fcd0","nonce":"5f01ccb22daffc21ced48087","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"d9d87f1bdc8dab6dd34c7374e24e5cf65e050c08d97dd03269fcc6dcec899c35ec751bb134397cebeb3e2a9b69","nonce":"5f01ccb22daffc21ced48080","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"832d07cabb686a5175bb79115089317c4bd514c7f9140264b8181115815b34c17d2836651e57c9a0261ff6a8a0","nonce":"5f01ccb22daffc21ced48081","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"79960e9460086f4967a79b8d3aa5ccd9cac9b42afb1c4eead0b6013b746a7524937749d355271019af7da8313c","nonce":"5f01ccb22daffc21ced48082","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"0ec3d2045981e8cf25b922785fed3130828e058af4ae5e36cfd0b1a47f3689a79215ba44dc2e749143bff2976e","nonce":"5f01ccb22daffc21ced48083","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"cf3d7135d2bd1e4aca3d02eaf62c47ece2887b6f3af22e4bece66917b0aa7e9ef904ee7bb917c5c00cb19436c8","nonce":"5f01ccb22daffc21ced4808c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"6cac2c56dd79e75210b840574982996af2a41e3b46de19dcb748eb6285841f2a61d20e976525d9741d68c1f9f7","nonce":"5f01ccb22daffc21ced4808d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"7e90ac579410d803c9493b4bb5144d0b5317a0bc87b9736d7aad5b3295aa4fdda7a9484bb248d3f29074c4dba9","nonce":"5f01ccb22daffc21ced4808e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"6150563522c9df170717ec481d7ba7ce0894cf6a504a4410e35dfbea134c435b0236c7538be4166af596f76ab7","nonce":"5f01ccb22daffc21ced4808f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"720575e7ab279a42cd0419c210118ddd161c292e19353a2108e2c56c628fddb224f8a5bc017c57c46b7f812eaa","nonce":"5f01ccb22daffc21ced48088","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"55955fa359a45ff0b14a4e36862bb7a1bdfff5635f3388b0eccb4afb06ea4bbcdeefbfac893ac80062c250401c","nonce":"5f01ccb22daffc21ced48089","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"d64de875b8620de013246f7b71211f8ab2c6d19aefe39c1d8e0c0a315f49cc8fbbf057ceea922dd4e55aeba6ed","nonce":"5f01ccb22daffc21ced4808a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"2352e62a5882397e8159519d737e064e2fc99e8676e2378f152ddab7b1624983ddadcc3633a2d014603f627f17","nonce":"5f01ccb22daffc21ced4808b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"4510fb9b1ae449c50daf8eda725a79db42a1eaab671618c5f0cfc31c1f3d0b5ef785a853b546417d4a690832c8","nonce":"5f01ccb22daffc21ced48074","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"419476c568c8b2ff1d64b96eb32741bf30882fe0284715ad40e3f1fafbc87c1b938b2a8da55be2bbb49a4f369f","nonce":"5f01ccb22daffc21ced48075","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"93981aec23c2acd82cedd17b32067da3cc9e881b040a4aadaa554885fca1fe33cfdd5207a00b1b8e269c3484e8","nonce":"5f01ccb22daffc21ced48076","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"de40c87816b7097fc36454eab9dd0701a2b02898d3a35861d74d185786ee9231269e87e4eb9d85e40afc622bb4","nonce":"5f01ccb22daffc21ced48077","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"fcabe16925c6ade06f76ab8ce2f0707e01f6862581b321725a39a88840b0c941a9e0c341352605b57f81a389b5","nonce":"5f01ccb22daffc21ced48070","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"251c34b4be499ada7a4082f552203bcb04a93948c9b331bf8cfe211b987a0254b47bfeee8d2489d7d8dd738c39","nonce":"5f01ccb22daffc21ced48071","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"5729368e0f6ed5bf1e90be9290dbbe9a1cac6164918dd70544d9f7babb65df6419ee64b4243d385e07768150e5","nonce":"5f01ccb22daffc21ced48072","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"e4eefe846e849db9f425993264f8977e19e1df2dc52297be4f134b9cb6ab2246c7be8c490b960b2379a67968fd","nonce":"5f01ccb22daffc21ced48073","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"f2b3c34f7a1a3d61e792e99e184ff6843a0c133178ad6c5efea15705d72730d68cfd73bae814336d92371e0378","nonce":"5f01ccb22daffc21ced4807c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"476ca18ff061258816d682e3eef9a160be5c561da3418e1946ed8ef66ff1ae1f43b70e9b5cfafb335e9abcbea4","nonce":"5f01ccb22daffc21ced4807d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"bbb89927c9d6ac1c622b0a272c70c7c8c6be592b8a93d2993fdda973eb759c5954098a2c96b32b3752238e416f","nonce":"5f01ccb22daffc21ced4807e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"19ef510a8e97581d055c32ca40537195d941381955e0801f3a6bc29da08b27827bc15b15ec28d3edaf0f50ed86","nonce":"5f01ccb22daffc21ced4807f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"db37ea6dc87fcbe9ea46d9b26711f5bb1743aad84c4ef7ef654e729a1d8cfd0a96e38715b7a2e91543de145202","nonce":"5f01ccb22daffc21ced48078","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"671b4c6d2f70884a790105058d3b9a1a16d6442632097046c5fb8a860202eac9a5d0d60009fc9dcf1a8d6cf3e6","nonce":"5f01ccb22daffc21ced48079","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"a926fb21f2553bf03d61a92e237912b8eac22f6d389028117510cbc8587064b759720c744dd58ac4de547dd7aa","nonce":"5f01ccb22daffc21ced4807a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"f4e3b8b7e96b1a388f65dd21b1f8ae3c1a9edc719181bcc44834fdf4f2cbb23bd3827621d4d882e046efbc5b38","nonce":"5f01ccb22daffc21ced4807b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"fc7240e28ad1e6edc1711a92e95d4672fdce4557946620e6a5325e42390e6ba5d777d7e317e3c849374d4940ae","nonce":"5f01ccb22daffc21ced48064","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"1ba534513aec955ae7f7e869278918660d4e293b0a06f8e0b77e6f26577f9891b1ecb671138a915dcccb8438bb","nonce":"5f01ccb22daffc21ced48065","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"137e7cd18e379c2350c30e3db75ee91da52f5449897076e1de63c3a62cfad3942d4c00dacda32c5b34f56d7a64","nonce":"5f01ccb22daffc21ced48066","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"ae24fc4f30a7db223594d076c5e84add4b8c8dfb0aba81253a0be27c12a0b930d0cea89660c7ba67fe41e7e4f7","nonce":"5f01ccb22daffc21ced48067","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"53d9e7f0ed14ac8b343b141ff7aa63b757a4bcab1f689781cd32073412baabbf84336671a93884068ade0e61db","nonce":"5f01ccb22daffc21ced48060","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"343726509ec902bcbb159dd33e1b70e79a6946e5b02511b25a1c9833f8dd26426ae57673c65160da78d6ad73ce","nonce":"5f01ccb22daffc21ced48061","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"f9d2a045fb0be73af52a51660fac009d402a7c5be95874088dc377b9d64774e8ef02724c177b9cb1f85721b1ba","nonce":"5f01ccb22daffc21ced48062","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"b65340a00696a44820829db57aef74b2851413518fc53825b04d84ef117f434cd572b1beefd83bc7abb3459f3f","nonce":"5f01ccb22daffc21ced48063","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"96d3ced3a721d2131aa1bded05d7b2fb4dead7eb1c5e0d489675a938b73f83cdfba5ac3b159a692c31158bf4ad","nonce":"5f01ccb22daffc21ced4806c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"1a22c0281005bde4d6820e937435feb5b2cbf67de683216a48f8a450e1a1b9cf11b5c90d4dcf05264ed17c751f","nonce":"5f01ccb22daffc21ced4806d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"139119c2a294aa32683ca0057afaff06182d123b485737f3dfd8e781d1f90a8984fd11af4dc6fab43b8a3f83ef","nonce":"5f01ccb22daffc21ced4806e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"b3c976ac9be15b80cd6eb629b391a0f400c7eae93e652d7b870fc729759a7518a75f58951ca5003abc02f64054","nonce":"5f01ccb22daffc21ced4806f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"ca5327607035d628bca681a0ad07bc8f2c39ef5401c01a5e59d23aebc0e735bf9a5d849975ec70950d2e91ffb3","nonce":"5f01ccb22daffc21ced48068","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"83b622395eb70cd39388c4e0d2405546f09086ac55f99d24d012337a4d52d7ffc97a6d4649dcf2037dad82cbdc","nonce":"5f01ccb22daffc21ced48069","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"1e7dccc344195620c435278fd1e88c55084ef106a082873fd6aba79aeff460e1ec81ab6390ef260aaf2bd561fd","nonce":"5f01ccb22daffc21ced4806a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"62f807e497634ccad66bac4d37c971ee8d460a10fcfe20aca3a8ddb03985927f63a217f9d8e50085368bc18fcd","nonce":"5f01ccb22daffc21ced4806b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"7a56f8665e782933aa93bf8507afc865a824f1e300d74fd171907743d6b02b468594b3dff27ab8f141e334d7fd","nonce":"5f01ccb22daffc21ced48054","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"cacb221fe6010aec2ee9bc70f50efd382f9a6d4d0de75c2cb898241126257b4b04b193acdffdc01de9fc614c70","nonce":"5f01ccb22daffc21ced48055","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"f5d3b1feb5d5fd5edddb7b0a713d07a5c809191ba23e6672131b68132237a30c145b4caed5822fd20a5c127057","nonce":"5f01ccb22daffc21ced48056","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"fb8a4efcd301004be45593ef5e2937f96b00806e08936034113dd2171af9f59d8ad0a084387ef2ceb1a3edc8fb","nonce":"5f01ccb22daffc21ced48057","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"6bce8b11a444c03ea3fe527c7a6e798b8d986d6a2b9fb442209a195a32f159d60546cc1e3216291bacdeefb450","nonce":"5f01ccb22daffc21ced48050","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"c26d7f3f948bcc23ea5000be5367bb64f38ba81ce080135d06b29d228314988361ec808aa949d60c0bbffa9b77","nonce":"5f01ccb22daffc21ced48051","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"dadf7ed19e41bcd56f1b2ae18c5f5626d128812e9bfdb2e3142dcb0d2d9c73b70fbf5c3f5481ba585b5b317eca","nonce":"5f01ccb22daffc21ced48052","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"5cdfc912976c6b74f2954f0c1bb196f044952f23a60505add639c3d38864e7758e646a67b706edca09747416b7","nonce":"5f01ccb22daffc21ced48053","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"b528946e286cf0419f57f1b7ce0aeeb74bc9ec3a6f13515bef43300fe16a1ed56648350af6e0ed6884afe18d7d","nonce":"5f01ccb22daffc21ced4805c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"505bc6de590f843721d328a59658464f1c1caac7a9463511f5c3c8306438e24fb2cbf1f6aefe31bfe13f0b755d","nonce":"5f01ccb22daffc21ced4805d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"e34926f545fef9faca2b57cc438bd3bb7a14880e4555e11f7bc0404462df337c3c5656b0ff282051317db096f3","nonce":"5f01ccb22daffc21ced4805e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"1119ee0e8bea015293e0a55608d5c1afdccbc93cb5cdfd020dbaebdb57f4b2d0f4e8335fd3f07fa365f80fe93d","nonce":"5f01ccb22daffc21ced4805f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"a5bedefac573072e519d0c93fa0d427a86c916d06e895e6ff44ab538b806c637844b5d778235852b47b45065d2","nonce":"5f01ccb22daffc21ced48058","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"2102da0eaa1b7b4175464ad1f3af45a47e78f79071824ba6c5b8a812bdd0bc6f137cb29e0172bf59d8cd20f675","nonce":"5f01ccb22daffc21ced48059","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"86a76d986aec0afc34e90cff1486eda38045e09ea832ddc0b0b6d7753fdcfc2517c3ef5b4d30e9e2b94b2e4190","nonce":"5f01ccb22daffc21ced4805a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"69d0122fb2263f3aa166e3522231a793bb9dc505a0403881a7469e2bbd655f9400045f5b0b201dd493a9d202d2","nonce":"5f01ccb22daffc21ced4805b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"656282ade0ddb1454a9cd52644e7223392037f7286e0df2dbd97e4c98bfd702e4818965aa01d85e477a7214264","nonce":"5f01ccb22daffc21ced48044","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"8987e29f2a3acfd5ddb3abcca177eedf8d1b22a802413c1f7dd1984a89467585d79d306f1225d981de44f4e587","nonce":"5f01ccb22daffc21ced48045","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"ff4982f8d9a88ff6bcf22575d4ca4b6c3a46b531e814857b18f5dcf1256c2359f5a476d075658bd4b0832b72fb","nonce":"5f01ccb22daffc21ced48046","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"1bec0ab2538dd2d8d00298ba1cdd1947ccf8eee1b430f7e8f6c8d1af05514765c44c2ccfe1b9cf32530ce1c065","nonce":"5f01ccb22daffc21ced48047","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"577b98f5dd4c8c44927da48a8b835f976027f9aed1226fe0250f51e729a313974266d3679e992f6f55c301f1ad","nonce":"5f01ccb22daffc21ced48040","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"6fb438a658a0b15111ef038c9401295fa88535a2e6c0bbfc8c03ed398323dfe50d87a5b11d505067a8fff4a3ec","nonce":"5f01ccb22daffc21ced48041","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"018922c0c38f93c42aee5bfb3a81df4599021786836cbd4c867ac745dbdbe8be72aaba89b35fbb49707647d30b","nonce":"5f01ccb22daffc21ced48042","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"7e773510737337db65c8c3f3655197a31c6e17ed730524bfb0128049d8424e234e26a6c3544015aaec713d97e6","nonce":"5f01ccb22daffc21ced48043","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"8c4cde0d4bef5a4dd7d969e572bc79028cab32a8fcd08b0956376ff73b12082651603e2da3b3170204353bbfdc","nonce":"5f01ccb22daffc21ced4804c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"d59cd3d62b75bd7a8a499c8e98eb18343fa9e65c4fa2feb02d4e25f50bdb1e750909a1c3705d9657a7e90380cd","nonce":"5f01ccb22daffc21ced4804d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"8f8861535a618f1f33cba6c9d6b99406596dee2bea69a356e4fc6947045bc890d9db8c93f5ba6cb90fb454cc3e","nonce":"5f01ccb22daffc21ced4804e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"e8decb6c17bbb5fcdad1b0d7ff01a119ce8aba05b844b73a030eac3b343bb842c19bdb82a244dccd672c7733f2","nonce":"5f01ccb22daffc21ced4804f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"610c051fd0e4e5e565d004e2ed86a8629e7364d8b1111adfe0014c1a9825e3a49373973109e0792aff2c2b29b8","nonce":"5f01ccb22daffc21ced48048","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"fa98cd68810e980bb8f6ecedaf9be04f8f6a1f0ed2c9c92d28e255ba32103d60fab1fc8af7cbb0d26085529254","nonce":"5f01ccb22daffc21ced48049","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"75f127e4f7df455543632bd0ea159428e7e36584ab9f78b34b80bde32ecac2523868704d5d7c87a16bdd1f40c1","nonce":"5f01ccb22daffc21ced4804a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"70d1cd58d1fd5851c94973e164903a13d3a1db43c09ca943bb1738f31f16459f05bf22fc3aeb68664267ebea75","nonce":"5f01ccb22daffc21ced4804b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"cb87e1c2e40cf90c4b9f71dbac54e2100bdf4ad19cefd683a871aafca798b3d30a50806c5961e53bd3d72546ef","nonce":"5f01ccb22daffc21ced48034","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"6621651ae2b85c791d036fafe725df4103ea3745ddbab926cbc76112103d5a333a1bb960167dde7b5ee1877f5d","nonce":"5f01ccb22daffc21ced48035","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"8b5128ca0565680dfd114efa381dd6ffd16bfa2cf51346dcf122652e3cdae7f7ea0ab416834d94703b99ff5a0e","nonce":"5f01ccb22daffc21ced48036","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"f55b86b73e1a31e0fda72be7b2a1e3e19ef4aa7f4e4117966025054979770a25ac7b83af817458d57562131abc","nonce":"5f01ccb22daffc21ced48037","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"5b734a9022df54f4a2445434b966088e51225a9672285004d277946d33c22e6bd20958f9e5d410616a3e4897d3","nonce":"5f01ccb22daffc21ced48030","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"3d5d634bc454278a0375d0a30921e102b499c1dc149f03f8b50e3f409fc02daf5b24c5763c7ca84a3d73a03ea4","nonce":"5f01ccb22daffc21ced48031","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"446549e5927d6abe0d498f6d5e9b1412a5a2f002bb4151eceb58a836e77657348e685f0a58b06f5517b0f2e9d3","nonce":"5f01ccb22daffc21ced48032","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"b3a977a31f705549c708c695144037ed139ef5bde8465f7cbb846e8a63a1985bc00559bc6969c880c1ceef4748","nonce":"5f01ccb22daffc21ced48033","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"0ec1187cd4d278e0067a9e4ba29d2a3f231a4cc4df2c164910238071ba0d2ea9a45c2fd0b1f82b8c65ad821d79","nonce":"5f01ccb22daffc21ced4803c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"0a9137bc9758e521e44104e5320bbc36c2424accb8c2f2e1c0155cafa9cf31ce1c93ec7f019d483a2bfa33ca48","nonce":"5f01ccb22daffc21ced4803d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"3c6ed653e429ef4f2e6907d56e26f2df4258d36cb12bd63b6c2dd3e99c9e5ab33adea4272480014d44a9b7e2ca","nonce":"5f01ccb22daffc21ced4803e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"f322d7202d867b4353cec995dd4a6ae9e202252577346c899c0c66ecbecd1581d558a437e12a48ff42ff0e13b1","nonce":"5f01ccb22daffc21ced4803f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"d238c61b23217a483f5d707a3a2dae198b48daf8e383b6ac7fe50fae6380a1005716e413c0d7767b6b57c29585","nonce":"5f01ccb22daffc21ced48038","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"87685a997359c15585970de8989feb7f37604e36bf5d0d3353e0299696a2638784ade39ad8f960947c9d72924c","nonce":"5f01ccb22daffc21ced48039","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"a773d79e47b9d7fda6267fa70cec8bc308ddb262fc888d64d21176620a806fd9c99aca3bf2ed0687dd71f33807","nonce":"5f01ccb22daffc21ced4803a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"98ef6c3971f60dea8f49144a23201fcd06dbfef598bc892000cd76fa04e6a9dae8f02ac1f89ab2de2f159d970c","nonce":"5f01ccb22daffc21ced4803b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"177d0041b0480792e6f9ec5336b24f44cf37e20f51e282e5086e80d792a55692e37276518257c1ef971475e945","nonce":"5f01ccb22daffc21ced48024","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"a61f2c004dfd83f492e92af0b4eaec4252f9c589b0c88aa494b48f4d1744aead5ae57de42b37cdb79d9bd638cc","nonce":"5f01ccb22daffc21ced48025","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"9f18069b175ce2ff87421cf190bf013ed46d71f984729f15ba634d0378653c58e87c617264dfee8363a29605cc","nonce":"5f01ccb22daffc21ced48026","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"9b51ca33e9edc4309c680626f685b3117b0441759f298e2912600ba9495e92d58d4514eb23fb260275d0e914b0","nonce":"5f01ccb22daffc21ced48027","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"e14fce097ab83bbc823a87141c23dd2230fcfd172add8eae14d2a8d3c3f23a0a77234705b8b5120403d664088c","nonce":"5f01ccb22daffc21ced48020","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"71e9edeac77c6d1fce4a432bd917e31e70e4a50c305bbd10e56c39fef4612020ee0b92ab583dea78c6f55b9766","nonce":"5f01ccb22daffc21ced48021","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"8a4cfb4593b70c007cc6675679384b6abffe680bcaba510ec36783d8f8bb5316a2de4cc3dcb00ea736ca04a2bd","nonce":"5f01ccb22daffc21ced48022","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"dfafb4c935cc4b90010e283207d93218b9d55a197c27bac282febc89fa0787a754ee0aa2cdd05034a157a09ac0","nonce":"5f01ccb22daffc21ced48023","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"aa9253417964175c9700e8367bce42cd7d3c5e1182b9f3a26b7957204b96c06d9e11b10c6424bd14da1a580665","nonce":"5f01ccb22daffc21ced4802c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"d89a372183776c6672ad8f007bb184e8eeb69f534c734ef417a1726da73eca8108d97600fd5ff422e75226aa18","nonce":"5f01ccb22daffc21ced4802d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"4c2174beccec2ec63891c0df7a52816bb02097ecbefb39f644bbacb26028dbf7c80c52a5deaf3d28bd52a04ba2","nonce":"5f01ccb22daffc21ced4802e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"7aeddd60f54dcd6f219fc4521cde78234a9a55797d16b9f084de21fca086ba96a413a7624a38b8361079a21c6c","nonce":"5f01ccb22daffc21ced4802f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"aa3dbbe4cf2123e0318ebbafa91d16f39ca5d8081ea97548e91eff1a220ea3cc5623e303cd6bea25368c7a9d0f","nonce":"5f01ccb22daffc21ced48028","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"7bc58c9e476eb6a40f6d60b10bdcad843d130a3f01d9f3b79705622b2098b21950014f44b1034860addbd56a80","nonce":"5f01ccb22daffc21ced48029","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"a92cacd465c3e627524af4767048acea28f6c5b5f75727bc27df7de41feec4f6e1715739c23badc43d1695205a","nonce":"5f01ccb22daffc21ced4802a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"3fbad29e493d3b098ab9e7e4648c4bfd5a561972cde9948392d30d172e07bea63f9e8bcb612914a5266743b715","nonce":"5f01ccb22daffc21ced4802b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"03b34fbe3e37f445ee410bc3f9bde109a6d7e432ce1c258e76d70f4a00680fff76087eef4cbc8a04526f45eec0","nonce":"5f01ccb22daffc21ced48014","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"b1d0a5f1d8af68178cc32f2e1d15a64936fed4f8db192a4a01309e4ec2659d1cedc2ae5dbe3cb9d33bd5f49290","nonce":"5f01ccb22daffc21ced48015","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"34a31f8148be85ddbe694e2041ae9a2710f080a2a09d2ff242f1afdc01a421f5f85eb06cbe07a0d04edbe780fe","nonce":"5f01ccb22daffc21ced48016","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"727ab0050aa6ebe7df1c8ced0e3424205382c1015fe70b577dedbb805c68f588260d950da1d8c6adaee43d2368","nonce":"5f01ccb22daffc21ced48017","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"703dae221d71af99ecce99f417ee798d005657365a187b93f2c6854d849dc661368e2388937a019b9c137502d7","nonce":"5f01ccb22daffc21ced48010","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"d05fb86969379277a4cda6bd08ac1d9b52f59172716675e49a78c62f0cd4d0f548592eb743215518da06e2e824","nonce":"5f01ccb22daffc21ced48011","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"8a8608979b49bb257a9d04872cd55edde53e5b62db9600da2945718662acc1f9701959682bfccc9ed57217996e","nonce":"5f01ccb22daffc21ced48012","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"8ec2997c4c6d1548771cd3da6c6b4216c3543cfa5b6a5395b4b6f1eed74997d7031bf9d076e2a1b594e0bb7d81","nonce":"5f01ccb22daffc21ced48013","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"237bfc9cb607e7762b3723b49d921e8aa6eba92652fc127c9969f7ddd78c6b852f4079fd44b2c8ee6ff857dc2e","nonce":"5f01ccb22daffc21ced4801c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"783aa1e8f1b9f99930f3f24920bfd58e530334d62a8b3a1235f72e79c928d493e4aa8753b93ef4ebf0f9855d72","nonce":"5f01ccb22daffc21ced4801d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"c31e16159f62471e09f71cbe39b68e1ef9874a2eddb09d6293277832c292eb7c0b843d36722824b7a5da96c058","nonce":"5f01ccb22daffc21ced4801e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"3f9068ad8e3b40239d0b72fe79729199d3123d2f7c68536da6d1b598cff4345ae89fd911af9137778487ad93b0","nonce":"5f01ccb22daffc21ced4801f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"79cbd54363c908b0d5a1643ea1463a8ea2ed3442f2d07c77841f022e1e178c546898ea0dcabb86fe7cf36b06e9","nonce":"5f01ccb22daffc21ced48018","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"00b23e9d4caf53a821bc1ebc5093394c4692552115a9806fb227f6f44bd0a7a9dfd444bf09833a37d906c0cd30","nonce":"5f01ccb22daffc21ced48019","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"21a3a92b54e8c50291f8aa080e3b6c8df8c72e8d8e3d385db744f06c8cf49f8b1a7afea3002cd36184078af7dc","nonce":"5f01ccb22daffc21ced4801a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"101341c27817352abbdef67fe6151d7380b6919d45ce9d554710b34e7a69d07da2221599fbe362e1d825ef038e","nonce":"5f01ccb22daffc21ced4801b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"07f834dad19402bebe426b7d3c544921f60b380c8213e635ccff02149eddb1d504aa35a59b7fc73e7608dd3aae","nonce":"5f01ccb22daffc21ced48004","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"b488c80f92e69f68a6b31dbee7cc38e1c26fc9564060a7632fab17459e0de26b9dd4fac95008cfedeec1d03a9e","nonce":"5f01ccb22daffc21ced48005","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"d4dcc99b8a167a2948c79de9ba2ac6aeec7203ac1f8e68454db5e47a8325156cf7bd7dc57dbb56fe1fd220c11e","nonce":"5f01ccb22daffc21ced48006","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"2e73f22ba7bc7a5d8a149b909cc103d0b513efd142ef272618b3a2e58380e180746fa35851ab25241695c104e3","nonce":"5f01ccb22daffc21ced48007","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"8a3b8007a7538dbfa3f9328016cac892e67114382c5bd844751196f78952a2ee34503ad14a553f6d8380adde47","nonce":"5f01ccb22daffc21ced48000","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"2b68d80919f5aa5bd878766c2a5b4d200eee3704372460c5323bd0a7f83db60b3f968b570f2056150e61fb3e20","nonce":"5f01ccb22daffc21ced48001","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"1a2d71714c2fd2f1069fde287c8da8cc7141a02a1f844508a6b548a14a1b147c48e26611c38a546a68ac6adc35","nonce":"5f01ccb22daffc21ced48002","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"75ebf3af0f417a58c7f18689b1a25989f2cec7c1fdf042b72cf74e038309c0b4b6f4d944c67ceaa0a1bf4f9623","nonce":"5f01ccb22daffc21ced48003","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"25e45b5d6bc58bffb54459591f3654f79a6e3ee66664c13aa567e073c7345c24a161ee8c175b57828228e55f6d","nonce":"5f01ccb22daffc21ced4800c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"55174cce69607c8ce76c94cb7a97fefac02e491b57518b5fff7052703061ead2b6fd117997e1b4ae739cc6b9b1","nonce":"5f01ccb22daffc21ced4800d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"6a879a2fc6c35721cc0f8d404d8ab5f8f391e9e63938d540c260abd0116451d0c2000f525cf5e699fa15367f1b","nonce":"5f01ccb22daffc21ced4800e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"1adeadb3ca62e41065837d7d87de6d75480cb7df2b227c65bea057b4391958771ac83b3198d77087b469b895c6","nonce":"5f01ccb22daffc21ced4800f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"f4ff36ec7d8705c6ce05dea1eedd4b5e49aae56b33b6b10f8849beaca9917d39bbb71e9c334be3f0751ed455a5","nonce":"5f01ccb22daffc21ced48008","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"25dcec07ea370f2e00941128232000b5bc7805e1441c1e69f492459c816cfa8a507e7209ededc8c0a62eb7ae1f","nonce":"5f01ccb22daffc21ced48009","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"e46455ef32fdcfbf5f91d434660d0d05a10db146ac0c0c8ba8b4362f20f6284c4dba844f13e401c4269835031a","nonce":"5f01ccb22daffc21ced4800a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"304c8e9b013d97d0c54b74a9726c81aba70b4c20c1163126fc73b52c4103910e6213d72f130b4ee1f70fba48ca","nonce":"5f01ccb22daffc21ced4800b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"565ebfa94357a7cb5a86354275d6bf684ed87c14c60e3ad1b3ff6ded31417d4f77f41dbf794c22b1e7caea1655","nonce":"5f01ccb22daffc21ced481f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"bd6229784a6d3a3dbd81fb31595eb9731c8ce5f555c5362f5df41baff0768164"},{"exporter_context":"00","L":32,"exported_value":"82cf9d4ffae5694cac6f9b28094e87095d2d4e083dca3cc75b04b057b9ff9c83"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"c01efb41fd11c507c7eee4c9ef994f4de592ea477b4e34c9f032cf8497df87fa"}]},{"mode":0,"kem_id":32,"kdf_id":3,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"97e758503d1c8f9a243a3e2c9090340bdebd9f8b18c4fc439048b3f6dfa57e72","ikmE":"b3912acd33b34659ce6195bc9759b7d19953bf74c711cbb643cf1eab3bdc6f74","skRm":"45049207b5fac349139e2c89051cf534faa2ed5fe3aae0589a11c69106004ef8","skEm":"1a240fd63bef8f7162b83933d3cc3e49b5bdf9128290bbc0cbf17b5d9e5acaf9","pkRm":"266dd0c2587eaf0a362ddd6f43ff5fa44c5be25877c882d0b173a82db277937d","pkEm":"37b4ad0855a44175b1572830286d5cb67f51571302953826cba2a85d51400574","enc":"37b4ad0855a44175b1572830286d5cb67f51571302953826cba2a85d51400574","shared_secret":"8baf538e667d1b74850eb6bad2eab5d3cef5bd3f8404b7228203e78a1a052c34","key_schedule_context":"0088e94c0aacbd6d63a08e547dbda944bc1146d7483cba3d5ca0b0cdb26d2fbecd0d6d8d55178b4dfb4a648a4e3e54adc05dfd4cb2a845712a74539ccee8b4f781238f3e66e519a887ea3a0d096475a5defe5bfd1d22ec386b880d050dbfb6995fe8f7d1d0c661c4e10698687f757b1e981cbf025920074204ff660b9f490d7594","secret":"7ec6a7ac2b0c18a572d8e52e9dcbe9b7404653cb7395e398cef20e551eb185500196f98a9d08451e770da193f78d88ae57154f5454a271b2aef007de50e0bbf5","key":"6cac949c7245b6fc7c70ffef9683cff11eb645ec46eaf4fcb3eb8005468e4fef","base_nonce":"78e25403764f7e5946b5b3bb","exporter_secret":"1ccd5db2c929f17c3d31c28f74d0966e87b58aeda4b108ab0ddec37fb915e91d3f914b0c1c87a15a11e50371550ded25c9b3b1c04f850414db184fb908c84ed9","encryptions":[{"aad":"436f756e742d30","ciphertext":"52a1f69fa84078069a1912efea99863ddbdec4e23d0ad4554e0a6f6bdacb0d36e81dfd480cd6bc1f0ea56d35d6","nonce":"78e25403764f7e5946b5b3bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"af3167f31d2545b1c8b0e65f6c083bc9a5474f12daa2cd650f9c99c65bbf52d5e5d0ee8a5670ddda6518f47d2a","nonce":"78e25403764f7e5946b5b3ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"81fafb2e7ad476605773af8918b0402ada492792071dd2f375b4a3dca05576abe3bfab78a14b01160f3f371d27","nonce":"78e25403764f7e5946b5b3b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"1eb96705f0c9806a09abb68d67a4ef4cf2bd26d5151d95f88077b6994cfe1397b2213618ff60ba2061b9490451","nonce":"78e25403764f7e5946b5b3b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"6e9222530e35c14002fef77eb606e607efa10e719b661f12db1a4a1136e666b90e31322ff5ed55a2d07d0aba12","nonce":"78e25403764f7e5946b5b3bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"b87b476e6e32ea8622fc6bd57fc9505070540d63d23a78e0069e20e7f876438a3c294041aa9b2e11c21029cde6","nonce":"78e25403764f7e5946b5b3be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"a8c72cd7efa62a810db32aa9ac7c9ab0469d862849b644cd889adc2a97611a9f3d12169d4860a8b2ff508ee289","nonce":"78e25403764f7e5946b5b3bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"1bc8dc66eb45962a4d0fc91d697e77fb85cc4661a83b918d6402cdb27d47bb5d86056c42e7c165a7b377a31859","nonce":"78e25403764f7e5946b5b3bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"71733c3b07a257a9d0ae074e5dd0eed3269702f7b96ff2e6b1fc37f06fdbe1dcf716b85557c6043526fbc08f86","nonce":"78e25403764f7e5946b5b3b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"d1336711bd17c9c792808f5efadfe8ba6c28dd361d204425fe21a649a61b5315ac7d56cbf4ae8f3abbf3ec1ace","nonce":"78e25403764f7e5946b5b3b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"7f2ef2ab0c961214344397c98530fd873f2ba8c24eeca35f9760859823882819786070b851015099df8023dfe0","nonce":"78e25403764f7e5946b5b3b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"93efa7ab0e46066ac42125b1fa72eeaf05565d08c8e149bf062315d34eb12b2bd0fd9c189a317e576444d23c8e","nonce":"78e25403764f7e5946b5b3b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"54084d8be6dad10e3f3ad9af337535c54583489dda5919c607b218d100236afc397589c5041187820fe00b4216","nonce":"78e25403764f7e5946b5b3b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"bfa3086b7a845968e8cff42eb9c24c1d6d10c96dae12e14b1969b6b82607fe434306f265ab939e412dc42bdf97","nonce":"78e25403764f7e5946b5b3b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"019c0594d3a99a5bcea2fa88a7a17f9cf3930a88a018328b3e5181478d0735d2d68a8e2eddfdbd0bd2965c5b3d","nonce":"78e25403764f7e5946b5b3b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"93a8e1fc6eedb4ff1dfde34a18ebe0b869566d2f22ddb13d120a5bfe1bb30a5ef870fa89f0cd9133d840e1da93","nonce":"78e25403764f7e5946b5b3b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"39fec9394eaace3d5f70a2164b7df2eada5a3a607a414936e78ed5d3d0f3dada05bfb7ec1d329e6d86e92c22b3","nonce":"78e25403764f7e5946b5b3ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"5e1039abdf4566a53b65a7d915b133421810cde1474547d1ec5496207667fb44fc0affe98e444544afd17992b6","nonce":"78e25403764f7e5946b5b3aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"b183498b022f46ef6a872506c60928997126a6cd39399417d5ab2fbd897bf332df909f48edc623879c159f7088","nonce":"78e25403764f7e5946b5b3a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"710b9ee05c797ce96aa6780682c514927880c7e4368a5f82082cdd9c716980a025dda5c95bc95fad67705d479a","nonce":"78e25403764f7e5946b5b3a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"f9d8faec697b77db6b2d986607dbc2f7b91c07c45e75c59c128f10a5f8e3c6083bea4e8a2f327c7772da5a7a60","nonce":"78e25403764f7e5946b5b3af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"8a25227609ede7d42faaf3a086efd33f69c47404248df87094f21de7ad71eee8f15b7b36459c62f0ddfabc79b9","nonce":"78e25403764f7e5946b5b3ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"78cd95d20b1aff974f70514fcff8f1dd4a5a66b49611809204a847224d9d0aad98e400798c595a578e0290223b","nonce":"78e25403764f7e5946b5b3ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"9070a17d6567969caa03ea6598c294fe9efe880fdbc5b886580a7dc578228ef4c582a710e3d25aab255aa2cbcb","nonce":"78e25403764f7e5946b5b3ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"f7f8f341b64453a941fd8f8295774b641835f7706ca9a4afb9a51d6b304113e7579f95ec222361d70b38a69029","nonce":"78e25403764f7e5946b5b3a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"034d82ec5f1778f7529c6cf057766518154f3f4b1bbe4259ca7441da4d3705b79f9f8d10ea14643d305904f276","nonce":"78e25403764f7e5946b5b3a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"87b526bdf13821129a9b7655c3e2a3cd9ccb5569bfd3472339492f97974815a2957f63dece6766ec410b4d5d9e","nonce":"78e25403764f7e5946b5b3a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"9ee5b7be750ca2f76d705eeddccb6f92c4282e3dd9b1a0c28664eb82b325e4fa53f965e5c523fbc206b2ba6b44","nonce":"78e25403764f7e5946b5b3a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"35039e5a43993328d8343c23acf837bece7950680a1fa84c7bd24c44d637f39b19ed6791e16a8d49daec9cffd9","nonce":"78e25403764f7e5946b5b3a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"aa1d3a0cb08c0583a3a270b9c4c5b007a70d0f1262fb946c478022c668ac6fecbb6d17a2f4afbe1c47c679cc93","nonce":"78e25403764f7e5946b5b3a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"fb4c0976c659a895ea326faa3f106d92acc6213898328c1e4bca9c9ef4f0443607aa376c05f04e2e9d0e589a1c","nonce":"78e25403764f7e5946b5b3a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"675fbd6fd65264607a30d998ce41d11da3be168ce27f60d0d849caeaf9082288059cf7e2ea5a7e4ca09e0afeb6","nonce":"78e25403764f7e5946b5b3a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"800c451433fc949d468aa4002107b4942c893a162bdb2c878b228b1cf6f7d9cb7a0258c3ccb3b73847d0f363f7","nonce":"78e25403764f7e5946b5b39b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"c703700ab2d6f1204d9ecaaceb1de20e3d24b895bd7b325ab9758cd6b6e3fb914dbccb84193b1cced4cc71e844","nonce":"78e25403764f7e5946b5b39a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"9c377b794753cb48a97215ebc440d502283f5af048bf661153a60b867edfe9cedd25d5d8eab30a5a23baccfa1c","nonce":"78e25403764f7e5946b5b399","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"29168286cd91800414814f63e62c2eca80697ff57e43ad29b2645d18d38762d940e5185eeea8a1f0a87b97ddf3","nonce":"78e25403764f7e5946b5b398","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"4992188f1f237ae7102cd7f9764a9d85725a8770efcbdda0919debe0c47945e748f1077714ba6699f0aaaf8430","nonce":"78e25403764f7e5946b5b39f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"1af4c45ce62c53fa0721286cd170b22d4a3fc8e79a1ed4397078596fa6a1e7726190776068eea6edc8a8c8a13c","nonce":"78e25403764f7e5946b5b39e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"b26f373bc600eea79015a61ebcbcc9214641e5ea8214c246490402a1d36312bb0ca83f03091b43841fa9a7fa47","nonce":"78e25403764f7e5946b5b39d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"49c083e86ffc57dc007d5639e14bea5ed65d5b58d0854154f3a244a8db10b7ef607355eb1d61b0903ee2971ab8","nonce":"78e25403764f7e5946b5b39c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"0e3d2744cbec45ce78d85a6a22519f5a9eba0a7113cf0151c6c3bd358f1170e6b8704ba7eb52d132e09e94b2a7","nonce":"78e25403764f7e5946b5b393","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"e913de28e361c39f2b63ac4f6e03ccc190bb830860523b7315c0d6a6f43d2bccda88459968211c31ec7de54c60","nonce":"78e25403764f7e5946b5b392","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"ce6e6f50ab66af33d0c165ccb274cb64d4a9d03116c8ab51b3e52131204d3c9cd7a3522d54b7e0a44e3a202dbf","nonce":"78e25403764f7e5946b5b391","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"15beafb1d93203ded991592f1fe13383e2ef727a2f41e3b985c1039a0d76e24c1927a566ba3aa93f8be98c5f58","nonce":"78e25403764f7e5946b5b390","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"a888d08bed9b873d2c816bc76fbbd3c1f1319ef4ee155b92223a3b43fbf3056e3e3401c9d09b6854f69907ab01","nonce":"78e25403764f7e5946b5b397","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"cc09c1d8379bf11718eb15e0e2e8684a571bb6351c4d2681bd15b7822f49b5f48bce900478f01615f9200cd55c","nonce":"78e25403764f7e5946b5b396","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"f363cc2ec5dfe90a84a2c3a2fe7976546671d7cd8cd9e97833d8d36161b7a3170f0df0d2f101b4008e5edaf260","nonce":"78e25403764f7e5946b5b395","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"b86a9c15f77a4d3b8329714940e2a6a551accac382b4cdd6df27be52233a6c446bf3c23e36dfdcddf969602ad5","nonce":"78e25403764f7e5946b5b394","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"165737169b9ba3536604add737899fc7580bb0a3abf3e050d624c18c11d3cc5ca67797ede0f2b7e6289249ceef","nonce":"78e25403764f7e5946b5b38b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"8dbb3e1265d913a7b240813140b610e3eed26b390d05259502ab2c2e7f106de3d04441a372c21da47a473d9166","nonce":"78e25403764f7e5946b5b38a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"6443200c15f134ce335b67022d1f9b77e3fa193a47026195ff1d9bfdb96586816b6fdb7276ff24bc763b51a8ed","nonce":"78e25403764f7e5946b5b389","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"f9b5723dfeb9a4c531fc69f8d77f6583c8e01fc19f53d10a4dae6f681c42105fdb20cb517bede77d86cdeaf2e1","nonce":"78e25403764f7e5946b5b388","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"cd5dfe95040b6f815d1bec478aefdf5ae2b31380472281d4d2b2505a64f2a2cd4e811a55020dd246683ea189c0","nonce":"78e25403764f7e5946b5b38f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"75fb9026143b9c2eff6ff0a5e68d90821e1c41f38fc6798458a610db3cee5fc0950fbd4baf07f6ce83bb5bf24c","nonce":"78e25403764f7e5946b5b38e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"17b91a2949a7407bb4718db6fc4ac5f3518ab7e1e7f16821135fc76f55fdd875935d2a35fbbf7db8e5ea569b3f","nonce":"78e25403764f7e5946b5b38d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"77f41554c23cd78f3a92f0dca3238168362c1e96ccad5f6ae3035372b4ba564e373c1c8242475d04f0dce036e5","nonce":"78e25403764f7e5946b5b38c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"f3a90b7c48382887c5267937ca1c688ccf349481143e14c79eb1778e42dba509a4e87fdf22ebbccaf10549840c","nonce":"78e25403764f7e5946b5b383","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"33194a96c994059fcf697affc4228279d3c5d5a430efca55b2edb7495518f279ceda084014fe8d81493639911f","nonce":"78e25403764f7e5946b5b382","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"e628bde2d1357450734ae402b3fb61e3943268e8ec9736e7601b1907b058fa35b3d61465e8a1c9fb286a226731","nonce":"78e25403764f7e5946b5b381","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"c3099ca547f806d3b54f58d59169e00b7c75edee145b8ab150b440132a73b29f90a13c756501f999443fc1adad","nonce":"78e25403764f7e5946b5b380","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"c62291e9bffa49ea1893a675cefc9d44dbc631820ef5abfd8d9bd15586675a1840562aad041ee741209ff350c4","nonce":"78e25403764f7e5946b5b387","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"af79becfffb85df16d4f61c2cbd1aa154875b20c557c10de5d3bd1f07da297ce6d627f9a570037192e360bf8fe","nonce":"78e25403764f7e5946b5b386","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"c63c82352c47e576096bfa6ccd1127151e196b39bb73e11ae5bb899ce86d9b8dfe558c47ae1b8219ed9d14cfc4","nonce":"78e25403764f7e5946b5b385","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"23e9bc2153c14be243ea6edec28c5a039e95e08fd38bbcecf9e12a38e09c3921362dc668edfc3b7c2e6cea6162","nonce":"78e25403764f7e5946b5b384","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"ffce37f5874f3ff06e749270d767abcca8c7a9cfcc1858cef86595809ad8453805c11277194464e61a869ec24a","nonce":"78e25403764f7e5946b5b3fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"7d933f71a3df11b4676d81accec36696fafeef800f58880b5d26467e84711fa06cbea98c49d4e4f53976577328","nonce":"78e25403764f7e5946b5b3fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"c0f4f01e7c48d9f8851f959d11a73a4035fc6206d5dd0bf5414ccd4cc89d4e05ece18fe340405749229a146944","nonce":"78e25403764f7e5946b5b3f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"b7975dcfb883899bb10250c44b16aa6161ee25191ca263af662076809856bb4dd0465ead263c7a4abbabe4d5b6","nonce":"78e25403764f7e5946b5b3f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"9df9c903e205e3b5cd725d373e3f2a64fa5d7ab7c4177094f54fecce66b7cac408098baa8edec4e23e489e0b50","nonce":"78e25403764f7e5946b5b3ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"5c956ca0533cc3a928b800b36c6bc538ae2dcbff81365eef8e0613017e4bc157758022b412a7882432a4364a70","nonce":"78e25403764f7e5946b5b3fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"5460439b87e232e1421796fde90744ec94854c7edf5dc44cc3a2b3c06e70741799bee7bc204eca0e46e7b749d1","nonce":"78e25403764f7e5946b5b3fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"7110a931c4b92510dac109faa0087d84318402b09008cf31d8c7efc764e90d508edfac5c97c3559ce34cbf755f","nonce":"78e25403764f7e5946b5b3fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"e05ae45cdba59d75da959cf8ec3e455a23c3b927940e8b7099c09eb73859be0d85581d0d54bf189cf37334877b","nonce":"78e25403764f7e5946b5b3f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"93c831c6e15b11028c330115cbd6609b45eab21f89e2ec7a805e22d2f7eaf583b5bd9c9c9ac596ccd5fda96c65","nonce":"78e25403764f7e5946b5b3f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"4cbfce9070d7d6b106f9510762bb35b1763330cdf335747f4604924f671f71d9aacd717eb666cabce5a88cc735","nonce":"78e25403764f7e5946b5b3f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"5d8e61f7291abd14ce4e23b98ee13130568cb326d19cf46c96f6a568b26dbd69436243afb084f435f8a842877b","nonce":"78e25403764f7e5946b5b3f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"4a7eb780ebdc48f3b767eff8aa9e7a6c50d201d63ff83919024219147ccac34d5b92167452fb3c2e8969e9f7e9","nonce":"78e25403764f7e5946b5b3f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"6e0c9ac9f192bb6d9122afe2822905070c2b2821560335d606199089900206f5b785c51c978c22ea519ada8b68","nonce":"78e25403764f7e5946b5b3f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"d88695f49af19ac2a0fa3e9d6995211338b2909eb186d956eb606dff1a77fe216333c574f377bf90b6babfdda5","nonce":"78e25403764f7e5946b5b3f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"0981efb5d5637a33f1202144817633df518594f7856d3a605e501abd2327f00cdd919dd331ebbcb7425b2e5aa8","nonce":"78e25403764f7e5946b5b3f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"99e645ecb40c16151926ee0ce1721eb0d26ad931c9b7e1d891fe7db1da6e2ea6d9d1b126683ca74f512bd593f1","nonce":"78e25403764f7e5946b5b3eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"fbc7ca2112efc845897dd1a9f46463fe3c36b06e262b7c7d52afc8c9c340baab8571b8de52246e0b348941527a","nonce":"78e25403764f7e5946b5b3ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"b1c2d62b6241b23dbe795ace393138b22e95d8219133b605b6e2908f0e47e9be17fe16211d9d8746500af4025f","nonce":"78e25403764f7e5946b5b3e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"dce6bd2e4e63712dd7f98e95c66008b7f0cc0762b8e46a33000d1e2253ee700a02d2c6b87a84a88ec2f6e647ef","nonce":"78e25403764f7e5946b5b3e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"9b72d90b7fc8c9421b4d2ae991f668f87128b11297d957a2c8e517805e3312023c7490d4dc260e23fd7298c4ba","nonce":"78e25403764f7e5946b5b3ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"8b86b33f0070b92e3e72d82555d440c2fa5faf364e2376e8a013ead6a64e5de7f88fe30db30634610de6bcbd3b","nonce":"78e25403764f7e5946b5b3ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"c0a59f935f432a237b90f84434261d4abc4e20e159da93c4740b3dd3113fc76aab30292d25a70dfde1bf502086","nonce":"78e25403764f7e5946b5b3ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"cb80f803c8b1f434abfaf714cca2965be245ac60f3e8b81ae142d3fc74e08f08e45afe7cee1ba518bb755bccdf","nonce":"78e25403764f7e5946b5b3ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"bcdcddbe0f03dd480288822a23958b690db9d8850e42561914e1492a978845f9ba5091e404c4194d1d6fbe18f0","nonce":"78e25403764f7e5946b5b3e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"9688fc37b087571f726ae6c4bfe068c5f31f9e65c0c339f0fb0df34feee0c137ca49fe78cedd57f624889e2c60","nonce":"78e25403764f7e5946b5b3e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"01222593b82f051ed6f9767a7991216a93d3d55d26f97e7825fe2554cb19653e4f006b5a6f0832d933e08f64bf","nonce":"78e25403764f7e5946b5b3e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"0d0d0a36a960965877a6a90a21f088b47c9970fe81109aa564740c791782ba5964fcabc168aedb3d6b6199b9e4","nonce":"78e25403764f7e5946b5b3e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"06b71090da48655bf144393ecebc0cedeef7fabc4485158848aa54b09b7ce813555bdf2811033bab60145f2552","nonce":"78e25403764f7e5946b5b3e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"865abb068920210d840ce0b85ad65c245b4b2075ca4a6240ae8024de17bfe828ea7986a01158fb4e6148594b06","nonce":"78e25403764f7e5946b5b3e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"e6645ce597da134f298818f9f9f32e37b7dadc485dfcbed87002801f36d1497cedbe46879ae0965f457ef2a705","nonce":"78e25403764f7e5946b5b3e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"2e3199a16113c0b6bb694e74ad99085def07b3bf9681425bc671c725e34a8102de0b4b6f10985f71c9439e42aa","nonce":"78e25403764f7e5946b5b3e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"28f4df22a8ca0d04f45988e1854ecf0ea0d6b3793c1a9d7f9cad565d837ad334661727d6a3e9925f95c7dddd34","nonce":"78e25403764f7e5946b5b3db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"1ac589e1e8656cd5bb8034be8ec52a37a38df7722424d29c1d8b2273402b25e39666e74f60c025ec0ae0859244","nonce":"78e25403764f7e5946b5b3da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"b36c1942c5fbe1534674a6b795abba29c8d9ce64e5fa74ddec062bbb2397f5d35ffabc617f4b6f0e4d5223aa23","nonce":"78e25403764f7e5946b5b3d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"e63ec166525258996fd4c354325f4c5a1f72327572d6ebf3a9bbd0150dec28000069246d86259a4b8526af4e66","nonce":"78e25403764f7e5946b5b3d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"92a152f69a46a7aef9ee8d2dffb312fd3f2a377b1dd1135a1687c512017dd2945f3bd7fcad3450b345cd19cd6f","nonce":"78e25403764f7e5946b5b3df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"437cbb2b0d6631cf19b9c81cd7272fa67fca9a37c0ee422950cc005cad5c2de6a0fd1b964e3a43860a63370079","nonce":"78e25403764f7e5946b5b3de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"7e54363f36c351804b5f264702b8634477b6051f145a07ad80bc4803d12667136a1d8d84d39775d13bbd0899ec","nonce":"78e25403764f7e5946b5b3dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"6a5a621b3994925642b2f0f37c2fc58fbfcef40a277c48a3f7496ed0c5fc0130016643b4fcef7e1a8627cf1ee6","nonce":"78e25403764f7e5946b5b3dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"0d72bd55176d20cf654d256c61a4c861748db848e3b9a88f06168545d44467c4cbdfe674cc224034a01f085861","nonce":"78e25403764f7e5946b5b3d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"756ffe317e3b243b0e347f938a18f827021811a404c0a8cffe67db9cf3814b7159ae0db0e59a497188b5a72f8d","nonce":"78e25403764f7e5946b5b3d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"be696b5bed200815594bc208a20ba5a91f4683acfbe828f25c4a781d8c9137d2de6829023d647ecb72e7319a71","nonce":"78e25403764f7e5946b5b3d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"31d3be3d4e04e2beb9a10435f9b2a898a90a8adcd6214a80ee9b329655690592c62d64b3ed18437a5fc65e612a","nonce":"78e25403764f7e5946b5b3d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"bf15704d108fa4b51ad12c6d5d319dcd837134b37abaa9b90d7e314eb2e683c1e755dd57e5a84fab02fc924032","nonce":"78e25403764f7e5946b5b3d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"89e6943db123be1c093c608833a08bbf468d8a8896ee496508e397bbc0c0f76320a6484738d63770820fffbb0c","nonce":"78e25403764f7e5946b5b3d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"d67544dcf3cc2a724d88c51d24b472bfb05ab0576b607b4df81e066d4d61af74f5b57f45a1b587a4c4d3e3232f","nonce":"78e25403764f7e5946b5b3d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"c5c74bc3b22c85ec72c50086161bc94834f9d303c04099959ff474b8f07f9fe7025d19b8457883a667b5f070c1","nonce":"78e25403764f7e5946b5b3d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"f5daecef43c5328219d7e9b290889761a5bafbd99365ed778e5701f33433d177f913b51d719298fe834213c485","nonce":"78e25403764f7e5946b5b3cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"5c17bcc93c2258f423a8362d164777ccb4c57b15bf84196ed98c69e21017b3914ade8a011ecb41a1e461ad89a7","nonce":"78e25403764f7e5946b5b3ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"8ac7825b6ff39c0b23beaef39151d607499956740578ffe95eda85d11cf6671a6f762eb9fe900003e4aed8ea62","nonce":"78e25403764f7e5946b5b3c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"64604fc3352e7400208b3b9469f63e9fbaf296187a7c9f23638a81b7c28729618c8cd34b3b9011efb29fe190ed","nonce":"78e25403764f7e5946b5b3c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"92b6a53da597a11c126d00c665faf3ba09e4f1be3509174eb568f1e0761cf8838f2cf33fa8a238b15c803da468","nonce":"78e25403764f7e5946b5b3cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"4c79e597c059f731c89a8694c57cf6402ecff3985f51988265cb084f6b2712f979e0f1c15e30ad3b51987260fe","nonce":"78e25403764f7e5946b5b3ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"3771b34a2f2227976914640ffa517fe8fbcb8e0361a606acbf3d7f10b623acab6aee0fe8da46a93248c5b99475","nonce":"78e25403764f7e5946b5b3cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"542fc742f465b8cb14902cb1d24bf0bc0ca77627d52456897773f26c3ff5d2809d5e8ae2a0b3c766c4595d184f","nonce":"78e25403764f7e5946b5b3cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"ff018461f21d2188acb66cf89a5c0492df884d28299f68dab3864cdfd16e241685f1ec188f3965a07083affee4","nonce":"78e25403764f7e5946b5b3c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"f33660d835ceb51c7170cf587fbcc9bcca9639f35b099ad73e04bbb95aa56b3f902c109005ff82f8ee8e4e44ae","nonce":"78e25403764f7e5946b5b3c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"4085fb136355a6882c12c1ac3bb3387dc0d75c2230b20cacfbe91da3e395bcf86df0b630f6361972448dc14820","nonce":"78e25403764f7e5946b5b3c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"08d9f2db83a3d86380e8f0bc6f5a77c202267936c0857d3dd39b51f14497379c0f6e16bbb7a8b11e613dfa07f5","nonce":"78e25403764f7e5946b5b3c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"61eb7b772bd47f1dc06523d1890eab0fcc5060e6fc7443174d5db381eceac08d2b886f20d5aedf58db3477249e","nonce":"78e25403764f7e5946b5b3c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"a9ad500a4dde4d1db6feb03ed14afb93288f14a4b55addd97ed7af531eb402b0055b832b9ed4da5746fc17a1cd","nonce":"78e25403764f7e5946b5b3c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"09684b5d34dde828a67cebfcc0fb62dbb9f6764d053ac9fbc4169f979a9573fb5596ec6cce1f980f1d4af343a4","nonce":"78e25403764f7e5946b5b3c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"f3f215042944b74e375d46e917db1be967b3cffb62bf49b32c49020f523b142d353efd608a470bcfe702fbea59","nonce":"78e25403764f7e5946b5b3c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"69f5073547b4327e8519478cce3384d1f976965a8a7717fb75bc70a8409aca397a707d64210f3584df4b145d77","nonce":"78e25403764f7e5946b5b33b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"017f379935bef81089c7297fce99807ab6ff8a33ac28cf66a7883325c0ae328b38f3d2158e6e5aa92578da396b","nonce":"78e25403764f7e5946b5b33a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"0ef9878ebb3fd28897d97bf6cf2e871b6bf1ba1cf2e680a3b1fc7cb3fd252be1d2df212f2f2790ea4b9dd50f02","nonce":"78e25403764f7e5946b5b339","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"7516260b558e4b16f4219884e5335671f8ae15a322a923e86dce5e95779ccb2a75b011142ec358c5b1a6e55a7b","nonce":"78e25403764f7e5946b5b338","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"68c473c020b1328afa7b5e5cd84da7704f6ae63fa71446bc2449b2a552ad44c3e1fbee79748991a1277a8cd595","nonce":"78e25403764f7e5946b5b33f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"87a3a8e7dcd6389cabf7af6d4eb0f186ab4150c91ef066be9470142a2a907be49e502cb3eebc20d95c50be9439","nonce":"78e25403764f7e5946b5b33e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"3ff0b8175158d56c1eadd267041c8e38e1f00e991f8c84f15ec17c8ce6106a8fb15a2ae68f3a74eca56c37e437","nonce":"78e25403764f7e5946b5b33d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"9574bd047d692d63474202df8ad1932d1b471568b60bebf36671382fd4e591ed9cb1862351da23a0b7f128ce0c","nonce":"78e25403764f7e5946b5b33c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"eb205350266289b8f0eddb2d4f9c0a394ce3a991b1bd738bfb8e96117714168fc3b0e1548f0059397ab6266faf","nonce":"78e25403764f7e5946b5b333","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"ddcbd555d7a80accd4bd16e7e2003f510e7eb64d157abc5248514d8411cf4df3950f8ae04acf2a9ef7bf8508ff","nonce":"78e25403764f7e5946b5b332","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"f0b773d3d91ee9e045c7063a6675dfcf753005a8c93e6fa185a35c69ab0831b40e580732176587597a30679b38","nonce":"78e25403764f7e5946b5b331","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"56eec403d4a023293d6dd0adce32b332a45109debe39ded2765e4d35c84fd2746c51310d04e9b95c4d0b32fb79","nonce":"78e25403764f7e5946b5b330","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"21bb079b2d9e7a52c3ab5c0dfd8730ad8cc39fe84703472a29675ea5600a565def0cb54a2176bb2b834b87aa04","nonce":"78e25403764f7e5946b5b337","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"069ba3a854ee050bb454e0e48adb1d434dcc0f6f9701a239eab62e83d9fe99c405599d9e48c08732ba85f02c8f","nonce":"78e25403764f7e5946b5b336","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"5601b2ccc6ebb076ec17a0fd50c922b5b96044c9c721b26efec7c9cf4402f9883729f33414979ea3d7e6fef6b8","nonce":"78e25403764f7e5946b5b335","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"0b62e07e1bd7f9a593337240ef092ed3cc2ba642279f80bed01e06b1fd7040356725463075f01e0b1e9da54045","nonce":"78e25403764f7e5946b5b334","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"5b65ece08f36f8dee994600c1f6ff056f96065a63c9b3c72c178da95d5b88181711236033836d8e7685dae6f42","nonce":"78e25403764f7e5946b5b32b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"8a619034fbe85895aa42c76273f67ba44ab05a615b6cd6cf727b3ddfbe05651b72f59c53a311620618ed882a6e","nonce":"78e25403764f7e5946b5b32a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"845ba991a338118fed4417e294368a3f348047a0ea697fb04e78835c3beb9cff359962ca6f6107bb9221b40a2c","nonce":"78e25403764f7e5946b5b329","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"8df0f9a6b536dc7d2ec903b7460c99426c5681f834590d5afdabc0a9c1382cee90d5945c7eac9b551a4763a138","nonce":"78e25403764f7e5946b5b328","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"b767cde8ebbac3657bbba9dc7e3676cd1c7b00b6dd198fe2a09476bdbe75fc30bba1db3643b41dddf3482769fb","nonce":"78e25403764f7e5946b5b32f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"40a91d0dd0d9845f4e0c0a21f8a4a212926a1f03c482a17405a548899e2cab4b448b37102374400250e91b144c","nonce":"78e25403764f7e5946b5b32e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"29986a8a390419c1416caecc9e965030d0be5c458b81a84b31c0108dac8bfd967519b339fdc6a7a4600fe1f395","nonce":"78e25403764f7e5946b5b32d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"4534b6264141c31d5e422afa3fb9e653f33361ba7b6fb5314ae1632bb33d2e711569d3ef6d7aae82b605313a38","nonce":"78e25403764f7e5946b5b32c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"2b9bd0d96324df1d73a16e48dc73b374cb87f5116a3826195fc9d628dd5ecac38d7b8a99998d67c19bbb97f762","nonce":"78e25403764f7e5946b5b323","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"bfa949e683b5c7554bfe1d329894f17737ca81ca68e031474abfbc76edc5c3f649ac9560d5a980022357f8a0c7","nonce":"78e25403764f7e5946b5b322","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"13df06e0847f9015fcb1da0e44c0a4289306fb359da5dca306d5e4254d364dd57043d8a00d7f0dbbf39c6d2c4a","nonce":"78e25403764f7e5946b5b321","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"c33855496ca2a2657292cb90ff5a2ab940ae84dbf446a6c3bda49284c3062cce7c8d345de620854930bfc1ce47","nonce":"78e25403764f7e5946b5b320","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"9a8127500e5d42ca195414463f63ca3a69921a961cb5f91f5cfb185007187b5888fed08d6ed7df85f55cd21578","nonce":"78e25403764f7e5946b5b327","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"2ac2ef27f14bd4c73aac2c272258498ab153c24fa928bd3187f743c5159e4c08a0d14853a3003dc24a440933a4","nonce":"78e25403764f7e5946b5b326","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"3db8bce2f5f667c6f0f976a7adafaa1af7cced423066a487b721e66f72b42a8b80ee86b6579127038f67f9939e","nonce":"78e25403764f7e5946b5b325","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"ba6985858ad9121242349fa6af622741baa40a7b109b7ff2da8351fbc3ab8a3e7ce8207624f9085c0cd2b1b40e","nonce":"78e25403764f7e5946b5b324","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"f10e6b499661de645c5557ebcc73fbd16f7552f2e07099f3e3b11a1e1477e8a7217f8007b058a288ec777f9c6a","nonce":"78e25403764f7e5946b5b31b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"b4c084b72554b0b7bd9cbabcdf349318732397c1e1f9ed1c9d20cb1e643dcf8129cdc59cd05dfdeb0571e41be7","nonce":"78e25403764f7e5946b5b31a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"06dc54b8a5ddad3e6b7357c9b7deeaa73a764934c3b81e36e9a2e0ea76361e34645a11e888658a8b64c25092ad","nonce":"78e25403764f7e5946b5b319","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"53139a78bde37bb536acb4e7f3764d4cd8bd25f561e20da8a6e64786b408d80170de4a0968d9d567ef4d37b197","nonce":"78e25403764f7e5946b5b318","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"61ac1206930e1caff80bcd90dc22b79cb82c5d5aa278988091add07700c833bb3e360c0df5307673e1c113dfa4","nonce":"78e25403764f7e5946b5b31f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"8f35cca8a11c61bafd668f8e5eef60ede7c2121dee1671be7a088185d28572cf1d06d59d523ad9fbb77df9f4b6","nonce":"78e25403764f7e5946b5b31e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"c19c93dae1075e136fd9688a1ebb4e2d97efb3ae3899d135179c7c91c5a818b31c9b94950df1bb5c3bf045331a","nonce":"78e25403764f7e5946b5b31d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"c09cc62d7fbf118d88cce7ee8d3c3302b24868c3fefae5f3593730b60d7c122bbb21f60f739b1ccfcefe7041e5","nonce":"78e25403764f7e5946b5b31c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"4ece23c4bf4f42356794a2f434e0fc2cc3e71439639f18dded52b38f266794fc8119cfa8a49845e734fd3e62f3","nonce":"78e25403764f7e5946b5b313","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"5267c9d149b15fb2da134cb68b03b047856ac3711397b3638ba663680b59b3cd7a6d1cfd11f0c385f23e454bdd","nonce":"78e25403764f7e5946b5b312","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"7aec21e47dad28661607d25bb2963ffe4f798b4329398c50099dc74e93f662aa7d3cd4f6d4055de8e3689d146b","nonce":"78e25403764f7e5946b5b311","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"3e0d99ffb12c7834247e471549be3757943d6dbca0f79be16aa962e78c5e87fe6147a9005878c48a6f1eecab1e","nonce":"78e25403764f7e5946b5b310","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"cb368a14532f006e1a291ef5e19ef4256fda7718c419d4bfb239e0b6255f1d45dab0b69df0dc8d5017f92b5c57","nonce":"78e25403764f7e5946b5b317","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"2751344e4e818a06159ef5b00e9a780b6aea54f3eea4f5bb90b66a0b276dbdd55938d6f283bbfab12a21a67238","nonce":"78e25403764f7e5946b5b316","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"aa84bc7d95a45ae7eed60b599f4d1f114bfdbc3818690e2a14ad9844d09cd6cb9bfd113c27c0f542363b979f27","nonce":"78e25403764f7e5946b5b315","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"018309fa26d48f980753629ffd796464f4b9c27ebab60396f2fc2ffcd8d2be6a60fdfa4e4f925a42144f1f16df","nonce":"78e25403764f7e5946b5b314","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"0925d8a8a6792ed9992fc120b3334ce575cbfece436740695cbd8618771ab0a3416e85930f771d7262858fe7ec","nonce":"78e25403764f7e5946b5b30b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"ead2e8aa81d8e85e0cffa6f16a9b5ff6bd6801b71a8b84718d29adf817ff9e795a399af8d137515fd27b69968f","nonce":"78e25403764f7e5946b5b30a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"0bacc546567574ffa94485d70eea8c90eeb8a788f956d7a7c935aeaed8533daeb76f5fc3543f484a7ffbc81bd8","nonce":"78e25403764f7e5946b5b309","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"9194bdfed719a1495b4a2ebc97e520078288810f173d5a25683204567fbddb1b0acb7aaf3ef0c2a66503b862cf","nonce":"78e25403764f7e5946b5b308","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"f0af665200bd80d7867797869f6dcdf01b5962e0722d308b30a004641feee3eddd53c073922f6fc7a412fdeefc","nonce":"78e25403764f7e5946b5b30f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"ecd10331b577190dc0f8a127a635382c5dc235f804a8738e7428c03c1432f705b3ca062e278eb46ad144cf661e","nonce":"78e25403764f7e5946b5b30e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"3ae60f821615541458ad5873b50b2d199eb18663c655e35968b960238dbf943f51ac76945d8575fe44aac5f9e6","nonce":"78e25403764f7e5946b5b30d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"af469724ce780854f0a0974931a9f5e489ffd508c844704663e97eaa00ec7ea2d8c2789fde7d0451c0d40524d3","nonce":"78e25403764f7e5946b5b30c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"4387afee89977aad5fd90d16842d05723f1a07d4d3e665bd2799ebb4d0044c1d98257a4d59a65efe8e95fb2277","nonce":"78e25403764f7e5946b5b303","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"181b472899f42a90007f94592d660f0bcbfdd33caebe00c72c6d162e044f1cfc2211c675f857ca1675b1a2c54b","nonce":"78e25403764f7e5946b5b302","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"86530c96a60ca904be7a65933bb0fca55bd8086ababb97ee59b06b2a5d2afd09aa32837c9c7ccfb1029b77b5bc","nonce":"78e25403764f7e5946b5b301","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"a57a7ddc39e5e259cbc198f00b6406463588ac352e6b2aa90466f606f9237656a5f5a1c8b86396d8bf74b4adea","nonce":"78e25403764f7e5946b5b300","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"220ad1ab0f1ed6450b4fa7f11ddf495d86b7dc443a076695afcd082a714e8d12ebd9477530e437d73f652fa7fb","nonce":"78e25403764f7e5946b5b307","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"26fb7a282124638573b5afd855d4bc47e62abee662de740f0b5fd2d9fbeeb8a9b3edda2fe153bbb30d0dae072f","nonce":"78e25403764f7e5946b5b306","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"4a9b990a55c8cf4a939640494a47235ec90c36acca1f55bcfc1b354dba1749a7933332d8cb56d3db6d60d2cadd","nonce":"78e25403764f7e5946b5b305","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"e94978b66ec43add7aa505b8354d8315ba9fb1237ddf00e160dbfc054359cc29f1bc409f097f43871b4dbd1f4e","nonce":"78e25403764f7e5946b5b304","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"79d8e4aa4b1026a83b4564ebe3219548e84a3c9c4d9ac5db2ba8e6f9306f75bf769faf97f7b49116f1ac0c903d","nonce":"78e25403764f7e5946b5b37b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"8b0451e22f0ab1b58e6daeb62c4a6dd684bc84273048837c0eb7325357faf08f71d662fe39b302ab482ed73584","nonce":"78e25403764f7e5946b5b37a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"970829c2bc024cc9d3185ece83a10ea4cd325a8569fede499bb20d1e420e5c79da39ae9520ca880ba8521e5a30","nonce":"78e25403764f7e5946b5b379","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"568fde9265bbb7b1251966fa8e99a99bde699d26b50c89a0aa0ef4d02f648bb5471cddc89954412ec950f4ebf6","nonce":"78e25403764f7e5946b5b378","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"99a024260fb85386076d726e790ce2e7f45a1e87c34997cbd07e866fa594289281674138a5bca7a0bbb9eb9a1d","nonce":"78e25403764f7e5946b5b37f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"da06d95bf1f17c902c24a0fa210963abf0d51888c29a90b8beda33a4dbb8eb41323a003cb016b5dddbefe0c5da","nonce":"78e25403764f7e5946b5b37e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"e1e4c55dd92b4a3f1570da9b25dabf1090a827cd9a62cc2345ef9ef2606332fcdf686c17593cf341235845811d","nonce":"78e25403764f7e5946b5b37d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"8c4c51855b42327353203d00351864316144154a255c7cd8b9340b0adc0001f9fb3212f082351c2f050991259e","nonce":"78e25403764f7e5946b5b37c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"6a44a78875ab34bf5e4eb21771c1c8d12ceca07c0e265ec5a9887dec298925f5b84e0d370bcbcfd321692bce75","nonce":"78e25403764f7e5946b5b373","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"f123a4d9189335554bfdc9fdf2b009464cc6b9d3867639301004e2a6fe433ca1c7ce6788bfe1f9c538547082ea","nonce":"78e25403764f7e5946b5b372","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"8c385415c1ef4dfc8e7344edfdb62e447a08ec048369264f56e230326490b1299fee4a235ef6667167b0403c65","nonce":"78e25403764f7e5946b5b371","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"cae7e25c80114596dd59e0122b0266abe5b7a0120e32e97a3dbfe6f53a47780651124145531eb15c8f59974a9a","nonce":"78e25403764f7e5946b5b370","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"b90136e58d39282806207ef37fa6a48bad7172e1a6050d229739ad7eeaaec5dd0564ba68d1a0b290bb0460526f","nonce":"78e25403764f7e5946b5b377","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"a06250a1240e6db8e32a2bae50c39948556c99a82a7c1c9c8606d7cf280e9ccd6a370bd3593fb25ffc78e63f60","nonce":"78e25403764f7e5946b5b376","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"7a26b7d413c2a44cdd711a3b93342838ef6af5f82d9b426ccf24893be7b4dd4b9afff8fed3043a56dec6e997b4","nonce":"78e25403764f7e5946b5b375","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"9ff893d3a9049b6ba59cc5af4d0cc7e57fb9abd383d430e35965a7251df35d40394f3ff3c3f815d60eba661e28","nonce":"78e25403764f7e5946b5b374","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"f775bbb950bc3d3f04c2e3941a07d84f89ab34e1b3f4c962fc5983a348a5a6bef14f840bf2c63150886c0939ac","nonce":"78e25403764f7e5946b5b36b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"f32474434a007a3a464bc4c0192c6ff6caf2fdca06be3c816f43fb54fdf5c24ec1c06e9926efdda6e79f400930","nonce":"78e25403764f7e5946b5b36a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"a90c2461cc4bdedbc69ada594481147079dfc2409142c484e4ad0277822d0c9ed1a757d16ce5ee885554e3d9d9","nonce":"78e25403764f7e5946b5b369","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"1b75ce4e9ac8ae59977f1ec0c380db6126700cd5caf5d3896defec2e82cb105bd0afbc3ed48207851409b9903b","nonce":"78e25403764f7e5946b5b368","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"634dcaf6c1e9b42e1ec5fa7d7b1d166588960bd0dc11df708ed3b25001333501c6f3a446d0fc82a0d80480628f","nonce":"78e25403764f7e5946b5b36f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"ebf071508e764b0d3f7c730f71de111eb66428c2c8445313c06553af72598c452eb03bb13f4ef8792dc2fe6149","nonce":"78e25403764f7e5946b5b36e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"02b10e0721863a893527731f57fd5839ab469064aeabb22b1d55525597b85dc3efbdb1a82c3707da45729653f0","nonce":"78e25403764f7e5946b5b36d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"b8ea9cfaa7832cdde03b62e8b10f913b5176bb4c356885895273eb3fbc507171e600e3e4a62fe2213dde358edd","nonce":"78e25403764f7e5946b5b36c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"76c4f371b096d17aa8176fde1d8dd41df6e0947b9d29c110b44f7781a04dbea1b86c44bf29d0346a28ebfea586","nonce":"78e25403764f7e5946b5b363","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"1dc9673f3db7fb0ce447c51da167a65e13d0a85fa4213be2ac72fde4d4bfb357a3bb169277802dd39d3c4cf671","nonce":"78e25403764f7e5946b5b362","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"d54d880dd5b68daa1c3a316afd90e6a189a375696135a9d2f1b930b2e332c34550194b65dfda184f1f1048aae1","nonce":"78e25403764f7e5946b5b361","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"39da792eb65996c2d36bd76e4ba9cb4a8bfc6ef910f702accf71f870f76b3de2aeeb473b909ee63e75e638fe7b","nonce":"78e25403764f7e5946b5b360","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"ac9ba660b0ce63e1ea5b80720bca83a45f408bab508f5651cc9939ff01b238e64e24798e6c42b224248d48319f","nonce":"78e25403764f7e5946b5b367","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"12b40c9a1f277c553f6a94a3730dc9171c63ec11da2aede08e9b303a3272624d2bb6d12cede395060f54c2a7b2","nonce":"78e25403764f7e5946b5b366","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"851e403348b533bfec847bf925dc885be35f9947fd6bd77b40c14ae0399daff0a2f8cb1b62e7d39a084359de85","nonce":"78e25403764f7e5946b5b365","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"ee87fef1ce52fe416b1abd1be6ebd6f6055bdcc53a013cf50efd67c7a41b6ca7433243c51946b80224c98526e6","nonce":"78e25403764f7e5946b5b364","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"033e6a1279fd862920f609bb281d64e55623fc9274afba1e35bd67eabde839523c6f7686fba505bdf456059748","nonce":"78e25403764f7e5946b5b35b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"7f4e756004c39ca27ebbcb1b932ee8ad5548c63e43e58f5dc01887deff2123009395988e1bfc3749a21131aae5","nonce":"78e25403764f7e5946b5b35a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"b9cf9739de66b41145ce8c75c15555909c180907b0b849e7a563469162351fb8cd135f1e44ca628aaa7d90074d","nonce":"78e25403764f7e5946b5b359","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"11e0f1cabe7c5ce46830d2025394fa5b90cb56e08ed85a4c43a6cdd7c2157b5a4490710f189d0c8e2202acac5b","nonce":"78e25403764f7e5946b5b358","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"c373c359d080b49c8fa9db976cdc081291a5043808982f61c3f25a1605f2e424112ba84323a729e19661ae6994","nonce":"78e25403764f7e5946b5b35f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"c5e9ea00cc15df164c8457dd4763e72ff9d78b57e41047265df05e1b60e365daee005dcf27bec40c0d71c54a59","nonce":"78e25403764f7e5946b5b35e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"fa6f5c5d43fa94bbd83fa18cc46a8b777a7ffeca14f723ddef190cbd5edc493d9ffbaecc5f974c9374b7324049","nonce":"78e25403764f7e5946b5b35d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"57e36e4f2fbd074c914cacf9bdd3657b51707eed0034f66b34e1c204951b9b965b44ffe86f895a3f412e10258a","nonce":"78e25403764f7e5946b5b35c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"c241ee71e0083beb5ade4ec1c50cf6e24f6114aa7cfb54227b4c29b8c2bef30798814490ef6f7597c024fb8ea6","nonce":"78e25403764f7e5946b5b353","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"6b486cd31a4dbd4ab25ee6523a0f87496fbde31a765848022cb8fb5e963f4db976988fe5309026a7f564430358","nonce":"78e25403764f7e5946b5b352","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"65e01c058591e693321be49a3d7b10e59b3accb1313540842f2d331746862d18287296f1192962f24d9399a27d","nonce":"78e25403764f7e5946b5b351","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"1a27825e59a133ea94e6e229df2f60b5223c0c1df85cf3898a72c36852be07e573e8d51908705925c51d9aba89","nonce":"78e25403764f7e5946b5b350","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"76e1a907e6f7824c6b80c90de82543f55ef4c9e69057ea56293b9fab04e389e5293dbd26c0d6ff63ba6bfaa300","nonce":"78e25403764f7e5946b5b357","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"805e08e6d74131daf1f8b85866ad61f0975f0794f2a0786e3d0834e1a80cba818dc002e4d08629a541802da4f6","nonce":"78e25403764f7e5946b5b356","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"9b4e3c2dc944a140a1731e9855463dca5ff2afcc1455d3f1386be2c776aee1efdffe1d876c02855cd27bc0ad64","nonce":"78e25403764f7e5946b5b355","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"ce41ab05d872c7f93b1d8a2c9e9d6264dbc78a23bf1a1e6da4b2d8af6805f276d055d2aceacfe9a3cc842e8540","nonce":"78e25403764f7e5946b5b354","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"784b47e9df592da5ada0c381c3f25937aca95f86926322483ed90d611ebee64463f1429b169e546d1931f4eadc","nonce":"78e25403764f7e5946b5b34b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"c75fcb8000dccb23456d6b69400e42ef78b928ecea5d9bfe3ac7a55c61e6ee756d4e87fad40de7e87e86fa14be","nonce":"78e25403764f7e5946b5b34a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"08cc0ecb74c64a6e8acb990bfcf933389675ec630a4fcbddfc2eb3d82d15188073f6b05109794d4e2d42fea24d","nonce":"78e25403764f7e5946b5b349","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"8b532a65e1a45ee5f75d4d2d414333aac9df2dfc3ed9c6718371d468f3b708892f25793c3f2235e13007612781","nonce":"78e25403764f7e5946b5b348","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"603d09a52ab02de3cfa71831d39bb6d99263a03158af0b70924c5652f0e04ea23c70439f10c5f6d90bbbb77295","nonce":"78e25403764f7e5946b5b34f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"5535a3db0464d652064d7d669b9117be4644e64b03bbe30fd5e194a972259364554a238bc1c39c185968bd879c","nonce":"78e25403764f7e5946b5b34e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"f4b3e58adc45c316b325fade53a5862a70c15991b1e51ff78ffae3610b0c4ad7a6c09216082c9e15fae5722cf6","nonce":"78e25403764f7e5946b5b34d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"204b355d67cfa273829845461c7fb4a5bf68a9998c273419775d60d95b64238217e8ba39c60f7a7e75b96f4f8a","nonce":"78e25403764f7e5946b5b34c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"bc316eeaef0b25e3a443bf15a5031c22db49091eb0350f80ebccf3074a105fb0813261c0393b62ab0036cd3934","nonce":"78e25403764f7e5946b5b343","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"2ca6c8b75d4b0b755b5d208ff1ed33b35bf253685443d5bf442e71ac9c411ed971463950c85936c2b46004efd4","nonce":"78e25403764f7e5946b5b342","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"34735978d3dbe00a0fb86884df44bdf634b07ed51cb0885c65dfad7f855ebca940dbf05668bd06c2b9d4171fae","nonce":"78e25403764f7e5946b5b341","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"8e13050421e5dd8f31e60241e5826d1d4cdea5d35730cf5eb155ed67bcba7c766e9ed3ad1a76c1bbf8609256f9","nonce":"78e25403764f7e5946b5b340","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"6f59fce26415754107c8fe64ca5a7d65dfe5a2f6a6a00e506b4e8ec8e0c1a91ae6fdf69bfc99a51b26484727cb","nonce":"78e25403764f7e5946b5b347","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"fc4081d2108af3b4feaa472f5923633b9086dc8b166dbe879437bfe86a510563745536d60ff0c5d60f0926fcdf","nonce":"78e25403764f7e5946b5b346","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"00dd92d18a4bc3538de58f3df65d3192b4c7a3968f0b44756707c8f48ee6b67c3446e9ccb8d5dd14a0214a13f0","nonce":"78e25403764f7e5946b5b345","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"36eb4c896602ca953d8c4562a2b8c35e039b28f13fdbd41566c4403446207b6420020cc1d46ae1cbac4841181c","nonce":"78e25403764f7e5946b5b344","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"1fd293547f593e7a82a50b2f2104c0a44ca53ccf767b21a6278d7f24dfe4ade3b079173c111fdbc535664e1be7","nonce":"78e25403764f7e5946b5b2bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"a4e20580802ca2be8e11d8c41ca0d844d476e76378a0a90f0fa19e1d9c44bfe5"},{"exporter_context":"00","L":32,"exported_value":"74964f2ca8c822f81eb9335856b3a714b05222bf59fb6a84f763da71e4f7003e"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"e17b2947c5c3f5bdc6b222f2c9c4e853c411fe820546a764544108fdf2831562"}]},{"mode":0,"kem_id":32,"kdf_id":3,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"5b0f058e8199fa09113acc7b3ec9516405430e6eccf4bf7f3a4ae8c807261e97","ikmE":"1d1203218cd922fe6818373541aa90bd31d18019c7490fafff930a9ae99de2da","skRm":"e79c716f6d7a003f6e19035ddbf2423cf8ad869f5143832a3b72ea46868f8e2a","skEm":"4b0b79433dda55d8afcfc47c25023b8f24f6c80ba7a7eec7fe55fed0f8155b45","pkRm":"9f9795beb7496e89d334bc0849094f1ffed0b02dcee4f18d5efad72e3fcb1065","pkEm":"951f4e859719174b6de112830c258a9f8b2980f76b3a0157f47b064992f36b18","enc":"951f4e859719174b6de112830c258a9f8b2980f76b3a0157f47b064992f36b18","shared_secret":"e10a366a6235982d071c992b876681dfe2b1ed15eea45c7db0b02d8c3c5ffd97","key_schedule_context":"0083803015629a22448332cff137aea9ef69ae21d9319186694096d72c7f14d7e493d3883e171235c9b358f9907d0398275a86ec17f0c3e2e74311c05ccf329d94f18df7d7fbda3c938157f486a23f47621b8c7bc4ab9d89fd902c1d406709ca1b281ef1b7bc4736dc044ee497d5dab805fd38a9f4890398ab2569653a0a7ff73b","secret":"4d105efc5a3daec19dc3cd5531b7d69c29840604b92c7496c84271a125752ec40e30d361bf3ab70ca9445452da17c64406e09a48a1963ac5e57e64eb76a179ea","key":"d79227273dae9c60d14b224ed53ec480ef6b43d00b4420b8fdf05afcc5859d46","base_nonce":"ab5e19699a79a656383dd4eb","exporter_secret":"bc36dbd38f0c79192ddb890c48612c173b065d803f6676fe665d94bb033786b3e9d45fe5d0d14db6a7ee6f6725511577f20d1a72dd64bc3b60026c0a1863a5e0","encryptions":[{"aad":"436f756e742d30","ciphertext":"c5e6fa69d0da73aa0d23b34dd638d5d2d2ec1397f16794b94646027ba9d02d821c59874db1c8ab05c554b44064","nonce":"ab5e19699a79a656383dd4eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"08e8f0ab48a4f1022a5dadd3efd9e497368392d64f9699641635d4dea17bdf678ea18345c27865f09ea03f703f","nonce":"ab5e19699a79a656383dd4ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"c0a7b2a907063ce5566495e7d41c11bc1c036808adee944b0b56f1fbdc90a25ca5f8cbda5d4beeb033c34f6942","nonce":"ab5e19699a79a656383dd4e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"8443f401bc37d193bb9734996f1d662dfebbb731a729d88118fdc81c2d4bc5d0d469125a6a6b48a7b9d068206b","nonce":"ab5e19699a79a656383dd4e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"97d48c403c0ccaedff5655bc59683bd6fbe3bc94ab29a25876b0af651c80ecaafe6f5eec7d0b6394b2b9a05d38","nonce":"ab5e19699a79a656383dd4ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"97a354ff547597ccfec76ab7f229d227e1dafcec0687950fe4ec8f224f9dce5d25fc89e5cbda232fe186b475cd","nonce":"ab5e19699a79a656383dd4ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"fd81d9c715264085f50c472a9aae5fc61a50a41a595e79e720fd1096118af2a49d3311ea8aa0c71d12027d13aa","nonce":"ab5e19699a79a656383dd4ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"291cf76b428eb8adc90eb1aed0ddcb4465854300014bacecf75cedd418e33ce23e6927b423f2ecbb63ea271090","nonce":"ab5e19699a79a656383dd4ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"140dd8e65fe3fd4fdbc529a6469627125cd64c08e054d5967051a93beed9a7aa88f96a6f4bcb749212740f6f54","nonce":"ab5e19699a79a656383dd4e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"667ffc5696fc3eafe601b911aea8aadf1309790d50c5c49210128462a7c0dccc6f6c6eb67918b5d08987a55454","nonce":"ab5e19699a79a656383dd4e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"1102b4a1955dde2451dc2fecb6ec91ce6502075d74ce4df94f762a9b34c39ac9b2f3fe28f39c24f653869c1361","nonce":"ab5e19699a79a656383dd4e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"d21a9ed022c1205d29090cbe29c4230d3a6d0a7d6f22aff8af760a8b43ddae56d795a1398086e3ca87c4332685","nonce":"ab5e19699a79a656383dd4e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"3b5637a2e94df2fb6dc95c76eecab703c9ac3645ca2d9c4bd2edb4c177f77b47bbce6d30bbef5c469cdd1e2554","nonce":"ab5e19699a79a656383dd4e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"2af798fa4390449e6090a450688a5021818dec017bae1d17797f7643a3cad2df67d52a9239c629b6ede85f1be2","nonce":"ab5e19699a79a656383dd4e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"382b0478a10bab68ef5709d83599c92cee442597b0d9fb14276b2139bbe6309fccea2d2bbaf88e95a830e2520b","nonce":"ab5e19699a79a656383dd4e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"beca243613364142edfe2c17a29a82029e003824229dba6d589f6820f22a308fd794763ef26f5b5acf5f97948f","nonce":"ab5e19699a79a656383dd4e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"f8205a0b83c23b279de7255be9d3fce13cffa3414325e12bd2e192531afaafa64e0a806c575860101af0ef8521","nonce":"ab5e19699a79a656383dd4fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"887240940cd8579813c63ebc8800d9523e7f483d02b3e03f8ff757cc9049d8e8b27922c3cde8806f354b4dbcf8","nonce":"ab5e19699a79a656383dd4fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"af7ebb81bdb291003baa46fba8bfd6ceb8f41ff8c17be626b5b4dfc11090a1285843fc753c9b7d3e4e9b179389","nonce":"ab5e19699a79a656383dd4f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"beec729724586a4710285a7c4686cb25cb0c4b87ec8a56f4ed555e333183244dfb77106be692e004e39e6cf865","nonce":"ab5e19699a79a656383dd4f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"015bdd4d86f55aa54bbadd51c243ae8c3e4d89f610d2a0d86f872614fb1a63dabac0f59ec4f1e4363574feff72","nonce":"ab5e19699a79a656383dd4ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"27982d6a0026eafdc87864023c2c86b142ab0b1f6477f3d6497c898da9a475532b19d425200338202db6da0c29","nonce":"ab5e19699a79a656383dd4fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"e0aa991dd0362417a21a304f09419f356c8952bee0f5638ba01fad429998bdb3edabce4adafb05b5e74009a783","nonce":"ab5e19699a79a656383dd4fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"05020d0db747cb3f2c8bf402f7c48b5dd8648bc994c450c17b79240b2ea4a971e799ce42b3d7eefafcfbd9ed94","nonce":"ab5e19699a79a656383dd4fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"7adc7dc8ce597c4b4b29167a3c1844fb86a1f9a1a05bbd74b64bc08882dacf472e8b6e5cfb92438dbbe6b771f1","nonce":"ab5e19699a79a656383dd4f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"60c258e293c074e3af7db85828aa23132c04b58a2ff812cf9d5e5282c881181ab5ca2789017fbbacde1a0bb371","nonce":"ab5e19699a79a656383dd4f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"0c66c049dc316e03d59c5c5bd20c89e54dc88c9fbb2c3a5c80a915ad480e4014547eb1350913c81ad19b37299f","nonce":"ab5e19699a79a656383dd4f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"23543d77ea562883dc52e99dc0945e7754c21303707c984f5c7182bfcbf3d6a7a2a639840b879cd8f2e77b70fa","nonce":"ab5e19699a79a656383dd4f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"2d1f227cc60ee7534d40ac161a9e9c958e8924c972a56da3c8fe514716c8bb96f46a4347141910877fedd071ae","nonce":"ab5e19699a79a656383dd4f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"da88df7223e07e99a9e9738e47ca03b008d593148545d7ff7640137b905e4328b57a12099df8c0f84f6443fd89","nonce":"ab5e19699a79a656383dd4f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"c70de3ab9a1da55efc8ea7e352483f87e974695b85bf9c16f72f18c39d214b62eb0ab7072a82d0cb94ecf0e369","nonce":"ab5e19699a79a656383dd4f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"a03b307850ea80e23b4bcb5f5c735e069b4c75b47dd34f0165257a8c05ea78e268a9f810e4b5131f5e4eea7110","nonce":"ab5e19699a79a656383dd4f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"46a604e4c3b862ddb868e5ae17445b0dd01f20a4c3116f87ce4528f17fb50bdcddfc9e7fcc324e3192d4e98bad","nonce":"ab5e19699a79a656383dd4cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"5235e26a761327dd0eb048b55861b171a4b2a3906d1d62174148ae25c7fa73f7290dd7d8f7b939537be8e81028","nonce":"ab5e19699a79a656383dd4ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"33854bface705319a801724d2572a864e0190380ecfee10009c9d42fc5144f2c7b0d0b5e9e2ce151ef9c7b6016","nonce":"ab5e19699a79a656383dd4c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"f17c86b913ab016ecbf0321ebd2ea18a281ccb2074123027411730a60c26e84f57b27f8fd833bfa0b902c32be1","nonce":"ab5e19699a79a656383dd4c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"e2ca72418df78c38a361aa97858ce32760d9bc65aa6287dffa75a4d36def4609b9ba32fb414ef2638cfd94d297","nonce":"ab5e19699a79a656383dd4cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"d7223e8a124b7ad4bfb777ea7faab4349ade26e1937f94b16200925ad599869a96980e9798d312958b78191e09","nonce":"ab5e19699a79a656383dd4ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"2c2cf6db73e46a212f1e3523fc08a8739587ef788822568f2973e1cf699f04652daf7dd1bf71000dec5c3aa987","nonce":"ab5e19699a79a656383dd4cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"25af9a04a07f1bcef56f4468b307965cee86c2cbe62abca88055658be1b1fb3274d37b6797d5bb165a9163606b","nonce":"ab5e19699a79a656383dd4cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"417b2d8165f636945b0e95dff32de663bf420e7ff4891d52d2f4e1997097be21cab4fcdccb0908d9417bdfdbfb","nonce":"ab5e19699a79a656383dd4c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"d4ce57f70093afbf8f68a654da640d18532d051f7c9cdad3e8328e833c603dc0b4ff96673d78bf19f481a58667","nonce":"ab5e19699a79a656383dd4c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"e33ca672f1055281e906d2a5e0273664a0d7b7f00b4d0eec76e236ca124de5cbacfe1b4f18b96be1eb50409479","nonce":"ab5e19699a79a656383dd4c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"d7925c2921b3a66fc5c3b454a441399afaf669a04f5c6594a9785791bcac33a4eeddecb957ec1875a28ab5da4b","nonce":"ab5e19699a79a656383dd4c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"7d5d9cb03eee63f477307660ab2f90a0ba0f32ca7af23ff36d6d21621fd497e3e3a1f3f5a607b7c13beba2f5cd","nonce":"ab5e19699a79a656383dd4c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"fd029e0731196584625d6ca32a566dbb4f590597e5cd01ce425fe6be4d6df51e613abb5b8daf26220466deca86","nonce":"ab5e19699a79a656383dd4c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"52b67f4d2b95a5aa06a816f2eb4d501d4df62d69c2234cea1e2da9aff6bcba8516f2d83c8918f8d92bf4e525df","nonce":"ab5e19699a79a656383dd4c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"d6790735bb8d16cfa80d8d4dcb9f3ad2090e8b6750a25ceb98af71ee4c6ffbf75b4e9aa150f2620b2cb5988f09","nonce":"ab5e19699a79a656383dd4c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"dbf89de4f1b7f595186ff7ccab9d5b0cb2c1d4f144637728e629a14addd37ad9aa677b984030e8265c85efd5ac","nonce":"ab5e19699a79a656383dd4db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"77ccd8c463ac94fd0c1747a9eb84ac78acc9f238ed47c1bef9d37ce1c88c8b7eba37f80480d6194dd601a78bdd","nonce":"ab5e19699a79a656383dd4da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"0da528fdbd404e3b79de4cc82770b79ca6b9747c1f7f52bd93ab93fbdf55ee8b322654418f94f4c238570c53bd","nonce":"ab5e19699a79a656383dd4d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"3e5f0d40b7a49065ae14e504ee0e9c7477fef79e14a23a6d169a0b6518ed7ebe49527c02bbd2bac7238f9d8214","nonce":"ab5e19699a79a656383dd4d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"5cc4be2bbad8240d55562ffc357cf35b760a18d5ea31718d20f4bc97fa2abd07143aee87b1dad12f282aa0c682","nonce":"ab5e19699a79a656383dd4df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"e18ed6f365da1585ed9a3075e633d69974a36f4020f4a0fb61af288d3c491b045dc746f7e381084a278bad1b98","nonce":"ab5e19699a79a656383dd4de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"0bbfbdd83daf56e6d38356c5588fe0bfed1e1ff2ddb27698367e2720596b2cac1b04df32d468e0f28486e280f3","nonce":"ab5e19699a79a656383dd4dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"c24d82d3944b8de342a7e5d636027256d87dcc104dad296862fc4ce0c327136769a42d9e0c6d48536084f672c1","nonce":"ab5e19699a79a656383dd4dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"136b12ea69d9c2ce073c23a3ba511c46336ceef2802cf081ec46a029132eb41a850af46f4c1d918765fa915447","nonce":"ab5e19699a79a656383dd4d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"950930da9a4331ba5286d678ff96351fb81909f3bba7fb95f60fda804c56de7e0d50e47d82268dfd77412416d3","nonce":"ab5e19699a79a656383dd4d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"b50666453dd4414819a8b66dd9522ed2a8a1919bb3067e3fd9d7e132710ff4f75a09d3897d0a1d0f62d759e20a","nonce":"ab5e19699a79a656383dd4d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"d48ac4189a3dc702452dc3e69cbf012f32af9a6970dc58b4fd7b14b5c92d956d5c3593612d5660fc0ff95749ae","nonce":"ab5e19699a79a656383dd4d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"8b06591670793f428c42c0fa523f601065b7ec48ddeb1e00a1afec3ddb01666ba9d2fb1d30ac0c0217ae836696","nonce":"ab5e19699a79a656383dd4d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"45ca2e5afab4d54adac5e51f5fdb9b693b11bc3244c73922e089f882278ab16763ba86ed546249b9efc595d356","nonce":"ab5e19699a79a656383dd4d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"afa43bad889140ead157a33e245c041d25b608eb44c32b033462bf01a06d8e1ab20237f78c4004bdf39957d0cc","nonce":"ab5e19699a79a656383dd4d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"22c71bec72d2d1df02ddef0c59c1a2a8d6cf4ad2fc27451ae3d06ad373a1d4f72c7c47d57718b3a596a1308a48","nonce":"ab5e19699a79a656383dd4d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"e13487b6cc5b14601aa76e5a73593c4c1cea6f45e26ceaa9b24640b25bedd1ea76ae74e6a549c9055b9a81f10a","nonce":"ab5e19699a79a656383dd4ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"5162049cdc975979c705cd2d6151c5c29bcd0c5b78a85a0c4d8280d53674b09e30f978c506a0f5d7cec6ac322a","nonce":"ab5e19699a79a656383dd4aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"568d779a1138ae468053f4c4337c26a92fc39ec4d3234612bf183ae149675ef2fd4ad7af0254b7ef2c776dd9e4","nonce":"ab5e19699a79a656383dd4a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"dd224362ed4016123b7b2e93265ff482f358d329a2890a8adea845fcb604c44bdb97e08f54b3742da996d1b682","nonce":"ab5e19699a79a656383dd4a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"c8f2e8f788ff4d40716f19be521475bd2d9fd2347cd8489419c78b2e2ef9f3494b7779619897202eeae726546c","nonce":"ab5e19699a79a656383dd4af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"32c5fce68415d15a5f80f749e74027e8d94d68e0413eb88d2c0f8d6fa991f885cb40b7ca90a14f45d02fad8524","nonce":"ab5e19699a79a656383dd4ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"dff28031fc19a899b1b7ebba51869936edca81f772693844149adb3b83b7a0e0dcaac9a2c4d46cd6c66b4f5f7d","nonce":"ab5e19699a79a656383dd4ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"10ff66e1811429dcb6bdb72ed737e57b111f6a3d262e00b152082f38e8954afccb881303e37549c3581cc5ab45","nonce":"ab5e19699a79a656383dd4ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"50489f0462e8c78dab779c27b2b23a7ac8434b02efd36e62beaec7fd016b51b23f697e303eede020d7fd038f70","nonce":"ab5e19699a79a656383dd4a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"fe608d46cd4148508cd50b1021b99d778b9b69469f8e7ce2865f5099f065a37565978e15615dbe53f07475cce4","nonce":"ab5e19699a79a656383dd4a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"22e4e5bf3405671d1f87c9a1606f0da70518e26d66c48d45f969a8a09b7544011b343f14de2c3693a35c441d94","nonce":"ab5e19699a79a656383dd4a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"3fa52f71c5882387a981d3096d151d1206be655b40ea7e4a1334775fbfac65d1dd6408b2a4a5341d364c15ec98","nonce":"ab5e19699a79a656383dd4a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"514c511a9badd39d06616e4a0e249baffe631bffdd8c46956cb9627b26b88bf49bf836545f0ce9447544550019","nonce":"ab5e19699a79a656383dd4a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"871914261e747cc23d81036043242ccdef98a8fbdad35424ae9414d7cb651310db2e3649688f6440fda4597461","nonce":"ab5e19699a79a656383dd4a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"5914daa88d59a086c90817e5496adc2e7c4da0fdb7ec6fccc80ce5228dea6aab3a2e9342803d96c4dd21935902","nonce":"ab5e19699a79a656383dd4a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"a92b466db806e4716b8d95d9c936cd66377b4a75294567fd4b9eb5849753eba2375f36883f48e253920669d981","nonce":"ab5e19699a79a656383dd4a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"bd839700c765881373df61ab2bd3d5b3b230e6729b09e2c7fd058f8eb9850f709eab34bd079803f1f67c605039","nonce":"ab5e19699a79a656383dd4bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"85db9e24929695f22d0009b6f0f613edc106b037edfbcfb9d3f7585fbda06678f2ecd2a036d8edb479ce234a5b","nonce":"ab5e19699a79a656383dd4ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"886064d269cf5c853c63445fd5108009848e725929b163302003a44d5dd382a74707b808c38e0767d00dc9e5ab","nonce":"ab5e19699a79a656383dd4b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"a2a091ad7356a87af05049e1f2bd30567e545bd072a0152714e112b2c3ae799dc108aae424d6fc91d339398fe1","nonce":"ab5e19699a79a656383dd4b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"bd000bd293183d2ddf5c32530586f063e0d2041014430c3032bd223772b6fc81bd6edcecb3f4ab65383cb00499","nonce":"ab5e19699a79a656383dd4bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"a23b0441261754d11e6a9dcab5ff8399504c8f7e064471ca9cb8e178474d1ab65a38ff9c822924e406fb0ae99f","nonce":"ab5e19699a79a656383dd4be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"fb3a81d0f3a721417644e9b4e4fbe5f436f1ba2247349508cb96aeb366dcf2a3d25ee5e99ae84ff4245f30a21b","nonce":"ab5e19699a79a656383dd4bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"0fe2fbf77b849e8b61944ee449940e5e6aabcf161df31c9a1f62999b298b4a7edd2756eda4b91976bea548c897","nonce":"ab5e19699a79a656383dd4bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"9b39b84452f74bc3a03090076e65307c5749398e3542cdea3907314ddd42e94aa7ddf1923affe1a07681cd5083","nonce":"ab5e19699a79a656383dd4b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"438328dc43b4970f09c8618b673cd3749886deb7b4d3eeae1e9e8fdb5361d21aa7bce49a9bc67158a6ce8e553d","nonce":"ab5e19699a79a656383dd4b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"123d99100a7616cb33060bdbfafd881ccfa4c8e596d737fcea4f209e2f6f67e16f58edd5f2c12491b36274c6f1","nonce":"ab5e19699a79a656383dd4b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"1b47d87de23cfd9a687947ca0d56c32929cacea6bb4c9ceddfb91c66b7c8cf36be9fc53a47350fe8011004c4aa","nonce":"ab5e19699a79a656383dd4b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"9132b99f54221cc8c19adbf2cd0ba606f58b0a289f551b93abc52ec79fc3b6e8f8000e6c76bfd8cd5cad03e8b4","nonce":"ab5e19699a79a656383dd4b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"e120f2b56d47e4a4fbc865a9d191776991f06420a2c7778da67a20400349875bfcdb0cd3f08ba83252e7d42fb3","nonce":"ab5e19699a79a656383dd4b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"1deb59524390feaff45af411f24c0a1069ea46acb3b7fc022b2262a61287a1daa4224f1cd57c6a36a983721c30","nonce":"ab5e19699a79a656383dd4b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"e95d67a4937c0057707fc4e20fbf6e23cd9003e311ac0b8d6d7b04fcfa7a266521c66ecf9114797e821554f9f2","nonce":"ab5e19699a79a656383dd4b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"3fc53852c77be4e1960b5935d1b8c10c70fbd9c0ad41261ccde6ecab06386a35e0a5ca86f21086896ef22df83a","nonce":"ab5e19699a79a656383dd48b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"161af4d462597b4260f201926f5e488f7217344cf55a276b08b2d551140ee612b12babe33c525eb4a45eb10c44","nonce":"ab5e19699a79a656383dd48a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"80d91117c0bb9918a986ffc000890b721d9ce20da98f52a2bc21c2a4403c0850d53e1a5b645a35a4978a480c33","nonce":"ab5e19699a79a656383dd489","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"f65d01548e2678f8137f106e61a27b671d29d03022113952b8c8d08f6c84be72d01c7602693c39d12c93e0911d","nonce":"ab5e19699a79a656383dd488","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"50bc1a9b10180e41ec99c8b97e21069d89599c78a4ff966a244638f666d05484f0cb95fdd0b481eb4951c9d736","nonce":"ab5e19699a79a656383dd48f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"ce0d4611df5f9d9007ee7ce81875c28165163c927de87752286fa822f0ab6a511976db2902cf4bf8c84f4cd868","nonce":"ab5e19699a79a656383dd48e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"2b341f8182e3fe1f35aa2355f809a526f2403599dfdf0008591f416416d40aee609e28dd73f9c0773fcce68ee6","nonce":"ab5e19699a79a656383dd48d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"c3b3ce9d3813af8d99be17b9aaf97cac87884833e8e24bed7b16948dbff89b5d188eebefee964fd87984542e9d","nonce":"ab5e19699a79a656383dd48c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"32c2d066e14655ad6c35f60e1b914472cca0e803edc6d4495c866cb709cefdd6f8e2ba6ae476fa1f7c59a94f5c","nonce":"ab5e19699a79a656383dd483","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"a45041afbd83664d5247f35ba0677973c732600666408af3fe0f2c1457805c6f6cec0cd4c2328639d53658d55c","nonce":"ab5e19699a79a656383dd482","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"dee2d4fd744c903ccd66dd01780637919fa7ff1a4a12227216d84665dcd4f3a178c48be49f683fbce2ca3907ce","nonce":"ab5e19699a79a656383dd481","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"4c604980bafa001393e8cfe5ac6730390f8cfcb23770920bc58ee893010ea041908e21113d257c9f049df96346","nonce":"ab5e19699a79a656383dd480","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"7527ee716edd0afc4f37d6bc3206bd3c47e1a39de98ac193de9654bd1a18d78cb40416a88da3ee204fb3c3a047","nonce":"ab5e19699a79a656383dd487","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"3e5de744a4c82e873226487c9b91e1a129b2fb82b78b216a1e7a1afd787a069d932017a33d90667fe5006b5457","nonce":"ab5e19699a79a656383dd486","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"f124eb32f2928d3b5483c7a05b884005d2efac21cca91b53ac2bbfc7e56f78780c894d99e72e56355be579a83f","nonce":"ab5e19699a79a656383dd485","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"41754dbb9f6f4e68b6ce6204fd4554dffceeb5f33b2ebcb6fe623f7090860eefbc2020b45d7161faf0fde76d98","nonce":"ab5e19699a79a656383dd484","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"3d11eb6f8e51c79138d59c3d56bfe279bbb17f302fcdff05307675c5878013639de7e8c084ed23be1f2d0ff615","nonce":"ab5e19699a79a656383dd49b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"cbc5bf23c157eb65822b732b5cc7da486c9fcd08754a6e40713ecf571e541caec73b5d7877970051440ff5a61b","nonce":"ab5e19699a79a656383dd49a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"62cedb677ad1c8b1a891f64980d8a5a0a770a667c6525dd03916a1693190daf84fe00ab6b494d153a278fef242","nonce":"ab5e19699a79a656383dd499","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"779f36c1b26181c2b5b1c10b02adfe55123228892deb068e4b16fcc3c599e785d7f4de669af2029ca85e999b4b","nonce":"ab5e19699a79a656383dd498","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"1d49a3a2e4b666c1c1c13da4f5606edd281f887145d43f31cc751481ddd1bd1254b5c330963adb6e746c9479d5","nonce":"ab5e19699a79a656383dd49f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"70c171cb803caa589ecf65397461310dab8147eabda7fa968547534165389daec98c8853494dd54f6e728a7d5d","nonce":"ab5e19699a79a656383dd49e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"cb06472238c11f893ac04570f7e36995f2722a31b72bac5beeb41509a52fe19d8befe1d863f561549f515e1eae","nonce":"ab5e19699a79a656383dd49d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"7f7b7dc34800806e619c3da801544c54756b7e61ec23eaf1e9fce7ad56e41f39b1221ccf43825bf7bf6d4b3f66","nonce":"ab5e19699a79a656383dd49c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"163ee09ccf8597a6f4acff8a6301f0ee0f0136e942a995befa14ddf1dde4818102609446bd9a74c95de42ae247","nonce":"ab5e19699a79a656383dd493","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"d39e7979b90390a5ef2d166b4e29cdc05e1f80ab4a868a77eb50e10effc5277e7c9d2c9110716c1231350c97fd","nonce":"ab5e19699a79a656383dd492","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"1c030fa308a0133a8c6752c9b5048d5a2eed4b3488d6d3381122e03f904af79d1c655961bfb69dfd53a0bfbff1","nonce":"ab5e19699a79a656383dd491","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"5a16439806df607a0e96f8fc2b4e79c70296d48ab3fa7543416103da3fc8c3a0df379084c9d06faee312ef30d4","nonce":"ab5e19699a79a656383dd490","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"7939228ed15d5bab611df627bc028122f8e14f015807895b0910de75af6a3bf33df6b512450028c3347b5d9e03","nonce":"ab5e19699a79a656383dd497","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"935ab87f6ee283e7c04da8af92c81af6e8cc8d995c699a4dfd3e50b4eec3f0de73650ef46ef93230152f9a4098","nonce":"ab5e19699a79a656383dd496","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"ac104ca7b2d44defdcd4ab3cb0adc65c3e006b212b5463c6a4a44aeec2be40421e799d8e526abc5b44bc01c86c","nonce":"ab5e19699a79a656383dd495","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"e945e9b3d1b42308f037b04a743f8b181932d1a65c66f72a42608cddad98a2ec5e8a739e16304f31d4dbe19730","nonce":"ab5e19699a79a656383dd494","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"2969e1a23d448adc51c2605aebeca7b0cffb28dba6f24fb284b850525cda48768457cef8eba5714125ffe19f27","nonce":"ab5e19699a79a656383dd46b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"8820dc541234bd9b85af095fe4b8e9d6e65894a8cae5ec2971cc95eb0521e70a1379dab89ab663b5fd72bc8332","nonce":"ab5e19699a79a656383dd46a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"47cf7c8e835353f93e95b13743b27f09f59b4344877650ce231a0b696ef03269202534fa2bd637b3dc8f18a02a","nonce":"ab5e19699a79a656383dd469","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"ddca7ecec48075e25ab7d27ef04abb0bfefc955716111fa3f03319564cdc7af1113eacbff09473ade2efbf0f70","nonce":"ab5e19699a79a656383dd468","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"ef5dd6536ad9ecd848a22e62072e07d55d186e59284e2454a952ec988914185147a1a23244965c55ad748432db","nonce":"ab5e19699a79a656383dd46f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"f6fbcf2dc4a5bdea20262e3db0022ee9019b5ef05c560f403c7916974a5c2688598a08aa590848e47b7b5a4339","nonce":"ab5e19699a79a656383dd46e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"ed5a86e03146cff96d6d80dba59f5a373ab02dc6896b790803715cf04ff7ef4796a371b26eb97043a9324706d1","nonce":"ab5e19699a79a656383dd46d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"47530f1ef6743489a2defa04aab70c1e1c57ed514d3e035858a51cdb49baba675a2c723efe463445a17cf35d99","nonce":"ab5e19699a79a656383dd46c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"383dfeebf7eb824f5e2f44f2676077a997f9419698ad537a4175daab98d9600dafab712243c3d22e34b242cd24","nonce":"ab5e19699a79a656383dd463","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"99dcbf1fb04cc8758dec7896f3bec0c744c5672254563739213794f4e48afca407aac2719d9632c36612e0e1f0","nonce":"ab5e19699a79a656383dd462","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"6990f60e36c68e7f2d9837e7d33c6c4430b0b8b41ab257ebc925e46ae0ff503fbce2642ab1057763947cb38abf","nonce":"ab5e19699a79a656383dd461","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"922b1b6bc0b8abf9bee2c85620726d8ec4be7c8d5b81d52972dcd29054b214192110eda1f5e280952396d8ad6a","nonce":"ab5e19699a79a656383dd460","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"0ee1c7d61cca96c7b8d26963053155dd9a1d88cec7bf0bc58192c57a9ec6df6f0298b44be67759dd12efb4808f","nonce":"ab5e19699a79a656383dd467","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"8edd4085d1b7e8ac19728c6c0a88283d75e2c7002d3a9049f82c0b207fe22c3b4e052bcb3498d887a04172c0f3","nonce":"ab5e19699a79a656383dd466","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"adb022bdb44849dac29decea99f6b2284032685591aaaa0a1f6bf9f155b222a9972e6172c60a4c07e9f55bdcc9","nonce":"ab5e19699a79a656383dd465","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"26fd4759daa2e9c6ef2fa8d3832255033c4ae85dec27573f12fd85ab70fd3e3fad7bbf47bf662a3e84d30d5bd3","nonce":"ab5e19699a79a656383dd464","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"6510f1a1909a05744fc6fbb4bd4baf70bcbd5fa9e311e5c714e02b848651d976b4668e2bc3606b8033a62ca264","nonce":"ab5e19699a79a656383dd47b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"1405c964156549f3093aada03f87a283a7e4028787e9ea02de767947fb37bd1fe072c003e573592d86221dc674","nonce":"ab5e19699a79a656383dd47a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"7a1372e657a7d7da5d7f618f4cfbc2f42a7b6ff51e6ec375ac01dd02c3ed0388ddbacddf7c778c6a26d6a5fa5e","nonce":"ab5e19699a79a656383dd479","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"04431e99d79c615a5e0db5b9bfa02bcdc1668901672a831a6f6b157466fe8bc9dbe5e3390d8bf4b47342f6a5bd","nonce":"ab5e19699a79a656383dd478","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"6e3c799c848f1cbe4658d4692efc7a2d138aa9e7b556be19bb73aca2c2bee56bb94268d5d0fa03d1981c4d486b","nonce":"ab5e19699a79a656383dd47f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"ecb349fdc277b73a7852c18386e3ec605ed1560febbc7ad7d7d5ebb51632ef080a058b810348d06be2f4b6c329","nonce":"ab5e19699a79a656383dd47e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"94e96f4a8f30cb12923d51daf07c96fb56a330e1355587c6c9f4dce12102707b34fc60c6e44bc3a66d60762a9d","nonce":"ab5e19699a79a656383dd47d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"1a004d296b8a348bbe14c94ec39e1035c2ce5b8366652b8e46e4043ac14b7ef16a298319dfffe87adaadde223a","nonce":"ab5e19699a79a656383dd47c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"7a08cc8c5efec183fcfc28e40c03c22fa3e06a7f346e16848c6e7d74184a1d12a1da6f110b574c375083ddba0f","nonce":"ab5e19699a79a656383dd473","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"f018cee13e7d7f3b961a3d3c5be28a2048ab0f7cb80351682b5b8cc9ce6646c9f9b8b4fe899e9f04e078fc777f","nonce":"ab5e19699a79a656383dd472","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"62690117fb28d3b3d8e41950be321997a08a467cf0105dd181ca7c4a6da3c61fb4e0f244210b1cea54e9629f53","nonce":"ab5e19699a79a656383dd471","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"a56b1c6e57303913e48f0ab9070085d1e010ca952fd7056ae15580f7634f134f6ee3067853e8b665eb1856a0b0","nonce":"ab5e19699a79a656383dd470","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"e62e434d2bb80e4f332adf394ee5f869a55dbd6e05206e247db2af7c1f429e17f85831e8b932c14fa101399051","nonce":"ab5e19699a79a656383dd477","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"f52bdba01fe9057000daca402943d460e7fdc977ed857fd557ae452ea2796e5fc8de8f497a2754ca4c1549bdb0","nonce":"ab5e19699a79a656383dd476","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"9d3a171dab9ed5611fc63740413914dfeced6aa7ae8907e7d6dab0194431f53f8b603aca04348fdb10a7c79b0f","nonce":"ab5e19699a79a656383dd475","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"12fe93cacf7079d6fb13acb47e8f02ad25ac9e02f75c14932f2081fcb23a0a4f7925d6111834c2c9c4100af5e4","nonce":"ab5e19699a79a656383dd474","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"7a8b464761ab44f553809f70fd779eeea21d84a8b2a8799786ae1e6a4e79ff480c904d474b9c6bab2e07b5f637","nonce":"ab5e19699a79a656383dd44b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"021087a2125eeac2dc3fb84e748559da5628f37a7c564b2fdb775191952065665fcfdb448eb02d42959efbfc71","nonce":"ab5e19699a79a656383dd44a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"a2d76772807141489df06bc28c581fa2fbcbf2f2658f75f08c72ffce4a3e70add77857c8583b225a3443dbbbec","nonce":"ab5e19699a79a656383dd449","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"9f43212f5f5a574ee810b43458cc34151eddc24cf44f765cd67f10c76d567d734e89041da3cd5a6a725f14a4e6","nonce":"ab5e19699a79a656383dd448","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"f9ad55c56179d466772be3d7519d30e1b92f8f53a7f6ce36171ab76242034eae8ffaf98bfee639f64cdd943cf8","nonce":"ab5e19699a79a656383dd44f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"48ae2865e61d0b9eb9e398dbd0e0532d996a5271b91d805d5fedfbfedc09b9e36852edc3ef6de6d1755819f34e","nonce":"ab5e19699a79a656383dd44e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"51abda424bb5434c642f90550776dc57b0d9f8791011e60cb1269dd50edbeba4b9ade9093cf23998b7510a27c3","nonce":"ab5e19699a79a656383dd44d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"a7b7f20fccf381e48078ba774ecd15490b5aa31efe492887135f5af43cbf0378f2cf95e9ea3bf76aebcec1f05e","nonce":"ab5e19699a79a656383dd44c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"cc5dc4799e383b1f61c974b8ff4cf12870c2ffcc94613e35e42df0eeb64776a2033dbcf1c6a3ebf2103bd2e0e7","nonce":"ab5e19699a79a656383dd443","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"ac527450b1a359b2cb9f1d33b81c4be3ca3327eb09ffeb07df38858c24e70aa70df5b898c64b4c986f2ac919e9","nonce":"ab5e19699a79a656383dd442","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"93beb8cf859e63538e65729944486a47709527b80eb9d9edb85585b70c450d58c3bcfb9d13d4eee61285f03013","nonce":"ab5e19699a79a656383dd441","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"550b852939bf20ed506ff99d773bd11ea0f535dc7a825d10039bb548b7eb360d5768409b347331ce670bcd3f90","nonce":"ab5e19699a79a656383dd440","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"f08ee89c430f1b298697c69b110d20b66bdf785c7aa102b231adb4cb78fd0ced0eac34fabf28a38646e3d76453","nonce":"ab5e19699a79a656383dd447","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"1baf10a9e6a22c8876e5ef87f3fbcd268cea035eae63197b4731078a99e71750786950fa67b6d64e980364d7b4","nonce":"ab5e19699a79a656383dd446","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"813ace0167ac90157628649aeaeb003e7f538318c9361d25b6d9e1acc7f2a00a23c97f60cbe2bf83847243af74","nonce":"ab5e19699a79a656383dd445","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"8951ab1544934bbbdabf35793dc0f02f3ffaf9a87e05f20dac0c21fda04cce7b3cdf492e081045ebaacefc37bf","nonce":"ab5e19699a79a656383dd444","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"834334228dc106e83ef437710b530ce3ac79e0aa3c623ae6bc6fd12dede55cdbb4a693740ae54a7c0399c83a29","nonce":"ab5e19699a79a656383dd45b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"51e970d7af486a4ceb2988fb69b04123cd8043a26f4ceceee51c596b7dc46fb3b05a3ca376607c4751294436e7","nonce":"ab5e19699a79a656383dd45a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"68792a278390bdce91517ea774cbdabfdfbd1c950f15e556d4a69659af0b4f8399f0df67f55e9b5fe9422ac197","nonce":"ab5e19699a79a656383dd459","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"e5a168863f2aa6fcdc0627e29f01ddd276019297b76171a9ec93ce9e2d83bb409d1fbc0a13ffe6ebbff26da074","nonce":"ab5e19699a79a656383dd458","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"69073a98e65555ac823f1f0d67b7a5ff0460e29eadf3d0feb740e1b6aa55d7119d4623d1c580ba22a1a6408ac1","nonce":"ab5e19699a79a656383dd45f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"73d37126b3d4fade642ac0c91f97ad60cf23a5c456ad3b0a9fda9389f3ce978f3ddeb082ac549490b3326597cb","nonce":"ab5e19699a79a656383dd45e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"f182d6004bdd032839d7fd6061f1fb3f18b30169e08205275b84dad1467bdf1c7d5d243684d1c2b1d70b39c191","nonce":"ab5e19699a79a656383dd45d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"7a0f02fccbed0eedde68e47a67d52df4db4ba989f8cbc451a4a904770387c3f82a0f07e62378eb7998eb572325","nonce":"ab5e19699a79a656383dd45c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"83563101af4e5824ef7d014fc189ca1bf7e447b899fc6844b7104be84e6572364e16d5b38580477fae315cb3a6","nonce":"ab5e19699a79a656383dd453","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"9ac4f04b152b0ae8b775f2729bf8b2608ea296fe8e0bc67ee2ab4ee52b4529c5cba705aae8a6361ad94ce63727","nonce":"ab5e19699a79a656383dd452","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"7c1a8064f75959e6ab4083efbb7dc5fd5e6829449f255398cab248e9df7880c54a48aa2330d53d545c3acbceb5","nonce":"ab5e19699a79a656383dd451","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"f9c8d03ebfd3a3eb24861ee67af79c4df80c6d00f5bc2ab58f1952db8dae240bde7fd4fe9a06f522fd59aa711b","nonce":"ab5e19699a79a656383dd450","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"f93ead26311d358d72f851c985ffbf467708400e2b33a41145431dc0ca55395ca2c5ca5991905697c9253838e9","nonce":"ab5e19699a79a656383dd457","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"8f2862793a83134347e0ededf429be1ce9a754598a0d8b6d673e36e6e619885a39a055999c1a5c697b67aec248","nonce":"ab5e19699a79a656383dd456","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"95ef0cd417df06cb3f375223d219d78e1b40b310bb7be6f5aa903729ee8b80eb1b3d7ba2de4bf187f0ba6c4828","nonce":"ab5e19699a79a656383dd455","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"a8c5865f23c3a0884a4614e2713241598441201ca3042613f0362f1707bbc658308b7f1371dc06382c7c0deaf8","nonce":"ab5e19699a79a656383dd454","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"c2e8d660689cfcc13c6f05240c35d43e6c374ed45a31da9e7ff7a0d455e7cbe5e8976cfaace97f5c2fc13598f4","nonce":"ab5e19699a79a656383dd42b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"ac170a6ea5b2cc1b0c76b80a71e6a676b212748384b2cec877ce522d5200dbeaeb4be84cba96eb2a70431c383c","nonce":"ab5e19699a79a656383dd42a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"ecfd01c685d81b39154516e832b054c0675ae9999067640aca6f61a7bb9d9808f47ef7903a45bc5c4930df4a2a","nonce":"ab5e19699a79a656383dd429","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"7bd4e0926aecf8df63ad8f2ecc43c829c642a2507839e430a9bd489e0b2c671dc5a13f602f4680e0e47bf1fa60","nonce":"ab5e19699a79a656383dd428","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"2ad2a1212cdaa8fa2aa1e9ece62397b917f8d43dbe23bb1307a7b7312e6859ad30fc056690c46a84fed663c07c","nonce":"ab5e19699a79a656383dd42f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"60fff5cfe34b2c0b9a58bc87317680c013ff64163a2566e689c8b025d1269547e870153234998367b5b0bbf2ff","nonce":"ab5e19699a79a656383dd42e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"9f1fd73b1465a12e2d2690a62dace1f6014bf1ca0b164b147f48879eb3258c8b8c90124cf0ae16886872036675","nonce":"ab5e19699a79a656383dd42d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"c8dd3c9561bfff68ec2ad892f86f9e908370a3b63c0ff555cadd125d9b699840d471bf86b09d340deaac9c4fbf","nonce":"ab5e19699a79a656383dd42c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"703e62d58f34135c362eb4442872483c5d7f0cd2c6be603fef3869bff0902b586aa4329ddd0f15938b794f2e35","nonce":"ab5e19699a79a656383dd423","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"e8ed2fe07b6912ae3553571a6ed13d4cf252774ff9f52f66f04c7d7c019bb3e8715631b14300133ec99ce65d07","nonce":"ab5e19699a79a656383dd422","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"68c88d569446f222dabfd5bf8035415581d28c3cec223ef842bcbe50ef445b0ca3137c3e55a4a37389c34b013a","nonce":"ab5e19699a79a656383dd421","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"4a783e794d459a89c5b74c90120801892b2665a44893e37228c30acde327c79e49504423f8a1c13e1ca5a33a15","nonce":"ab5e19699a79a656383dd420","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"d51246cb64529d63f1e41222a5f9d1c0e046e4cca4050b2542f744d03ac1f0aa5675541d7800d7911c7e57e775","nonce":"ab5e19699a79a656383dd427","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"aca87a770b01062fb212103f6beb82121e171817ee154529a9721febfb2e47c0c1ea9fec622d06b896eb4b58b9","nonce":"ab5e19699a79a656383dd426","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"f8582b5285d787ae917c324f6fdd0109b27a1e38ae4461d5ea43c45db5a5d2ac8fae1eb52011da38185bfa73f4","nonce":"ab5e19699a79a656383dd425","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"bf567f3b4a4376fbd3e5f877e04465bb844ce1b25485864db4e98b1c1b47e292024ead2b5e2707209c2aa093b3","nonce":"ab5e19699a79a656383dd424","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"f06b23c175709ce15def628a5c38629e4c5f9d1995bc26c28fcedf4d9fde2a8419553d3c7e56186961b0953ea4","nonce":"ab5e19699a79a656383dd43b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"b7157cc3ddcdaf535c5a71280e7834502ef340451d79b0b0913c44929aff75dacc3e52146d36366a152faab383","nonce":"ab5e19699a79a656383dd43a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"832234a2618e44fa3a2d7ce2ee2fec4e624aa9ee184ecc7fe6d3fcddc5ef0fa9bb02e413e7e066c31592cc1634","nonce":"ab5e19699a79a656383dd439","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"33cacfb6f84fc4764c4ce82f7b951314bf159bcd06913b147c50aeff049ef86373031d3bd36c52b821da79270b","nonce":"ab5e19699a79a656383dd438","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"9020f8637148044a5c4f8d816adcc7942d65953c870399bbe05a54f184780383a40acd7e221937c9a6f7506b9a","nonce":"ab5e19699a79a656383dd43f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"229ac6e6aee349d03435ce3ad7a3a6f6a5b867d4e81ac842eeae359233bc7dc565a581e1e2d330def7d6332283","nonce":"ab5e19699a79a656383dd43e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"8bbef33fb9773317a1a8f66b6215eb7d64922f763cb688c45690bc3fd673333d25e6f173f0082c263bab714b5b","nonce":"ab5e19699a79a656383dd43d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"3499e810c2a121bafa960aa030fca5aa7a42f59b1b7b9dde674018a8bbe2f4846247129e843a1b962cc169859a","nonce":"ab5e19699a79a656383dd43c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"a0bbb318cbfe0e4a7feca79a15c7dae7b2293e7e820ac109a5e1f7d96639648319b7c0d6da64e18f01705b7af6","nonce":"ab5e19699a79a656383dd433","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"19cd9fb63a33bcc6266a725850c9755fdfa5761e112f5251cbd214215d746b117f7f4d9e56b93659f7a8f0a32c","nonce":"ab5e19699a79a656383dd432","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"2521d804a6fc3054698ff5ac8de7ad573d2eb98ce29cae55353b1a73ef5674bb882a8160a5d77272913628dafa","nonce":"ab5e19699a79a656383dd431","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"d810a4f8177490b42abe11f9e0c9b8486fd6eed52dbdef5379d7bcd92c06bfab384c0e62b06efd436e5cce7a64","nonce":"ab5e19699a79a656383dd430","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"34b8af3dd101ed9f280794eb1050d740d43f5fc26e00a42eb01183a8c06b250329c2285df11bfd0a731d6df9d0","nonce":"ab5e19699a79a656383dd437","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"01441744e8d348ec6c37423a4f6686e447b4a12253912169966e6abf2ee4c9f88206e6b549156518dab149306c","nonce":"ab5e19699a79a656383dd436","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"4afd4950ae24d47dbabe047211ff1a97a790c49498183c623d13ad6374385d3a119eef5a4c19c9cbf9a6992065","nonce":"ab5e19699a79a656383dd435","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"1e98398921ff98e52cef1d796c32a6b9c6ca183d77ca74fce439bba9bdff9412b3a7724f50f04075bdd22f0745","nonce":"ab5e19699a79a656383dd434","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"e3f22f703cd77dba18257f2727cd4a85cb2ff47e7e5c4c80d6c9776f940156baf8b184942ebcbe92adbb37633c","nonce":"ab5e19699a79a656383dd40b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"8cf8af259d7380d35870437c4e5ab1a2d2be1f2cb8d466dd681ca3536836cbc08c0798480b09bf24524a6ef8c9","nonce":"ab5e19699a79a656383dd40a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"dd9789e7ad6aa57aa1cbbfefbb11f2bffb18bb549bc5ff13bc56fb0e7b30d872f60837ffd2654849979e9e50c6","nonce":"ab5e19699a79a656383dd409","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"fd7b3b0ab3e6039bb88074fb8a5c074f593ad709591dfb3191a2a5a65fe35accaf18c383c078a959cfff37bc62","nonce":"ab5e19699a79a656383dd408","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"f0459d730e596ddae3df9bd2c789eaf0a3a667ee71e10c14328b4e42f035ecd2fd7fb4876144154b536164c825","nonce":"ab5e19699a79a656383dd40f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"4e3748e7bdacfabc83943d4ca97269ece77cb5dd0f4e2db6e82016707f34bec2484f6376f1d96ca9ebab56d9e0","nonce":"ab5e19699a79a656383dd40e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"43b4da7770cbfa67ec2471fb378da88a568ec89ced3f2ba0ec3ad8b5f5e023078ef5b6e59cb72533c01e43c4a5","nonce":"ab5e19699a79a656383dd40d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"3b87ebc3b3b6d5d793fafaa8f5a0fa0c735f05437c6862cff89e44404730a905f70dbcc95db8ca57b8978317bd","nonce":"ab5e19699a79a656383dd40c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"025ab79de52c159f83546a02a37401801b9c990347a617c79becc008db6e86311f8001389b49c6743f7b35d7b9","nonce":"ab5e19699a79a656383dd403","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"18fac8b9930bbf71ab553f9715d4a8bd793098610a81e62e4500e5b0fb1db87f14d417e1be69d3e3f9280f91e4","nonce":"ab5e19699a79a656383dd402","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"2284ef4be8ace02d763cfee688ea04a329acd220f83d4f138c5653f45fdc03f3f24fc285eed4044a45d5551279","nonce":"ab5e19699a79a656383dd401","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"9d68e2240ade9f02f4c9ac2635d89c2138fa747573f5ae3577693ce6884ed971f56c5f74cf53e2339136cb48d7","nonce":"ab5e19699a79a656383dd400","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"499095c91ab1b1ca0a6bd6aaf1d821abd508a6dcc219cb402c937002675be6eebd7ac111e9c64802a0ea3226d3","nonce":"ab5e19699a79a656383dd407","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"9ef3c2fedacbb28faba4165ffe7939b8f7acac852362d93707b57c4f77567682655c71cc055d5e753e226afb9e","nonce":"ab5e19699a79a656383dd406","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"3bb2d3d993d440ef601ba78abc18738b6f322a56ddef5c9f13a0c75d9a6a1799f9c7e8abcdbad18eb0c54eb80f","nonce":"ab5e19699a79a656383dd405","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"631778b7cf18bad85976144a223f97f948397287145f3a123b61a43c862cdfabebbb679e0f68ade02e809505a3","nonce":"ab5e19699a79a656383dd404","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"f347c4a19f954c1cccced840dc8bc3715e9f804cab700971642bc852e8128b8b97b5e921ec7ade2804739cdeac","nonce":"ab5e19699a79a656383dd41b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"51939ad35884f76598e6c347a5e08335a7b33cd9cb0d4f6ddb96b5c19f53d15d34d0545c5d334ea58a79ed3b5f","nonce":"ab5e19699a79a656383dd41a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"a4e70a15612fcc467dce5ddfbd1c7355678937e668fda251afd54bfa0c2ad639cec6cdcb83a156e247280f3b10","nonce":"ab5e19699a79a656383dd419","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"9b5b47e66c9caf9782629fc66c2a290967205cb63151f1d92e5b585274d11123b614aefca1a7d9cc0e0bd221fe","nonce":"ab5e19699a79a656383dd418","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"9bdbaf38f0f3bd65f71f4c67745c99e54abe160ba07494a2433c77e83bdd3f7b03ca43a75bc5a0a2d005f05682","nonce":"ab5e19699a79a656383dd41f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"c49db04090fb73f54924107a0d4b73232b8d5b687c4b384a2375da8cca3b5c9bc31c69fa69fc20d033de7c8d9d","nonce":"ab5e19699a79a656383dd41e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"31c4eb490ddc68d1d155edb7ba00f0cbb030ad9f201b75b6310d807bcb676b8c2af4c4bedd81842117f272c4c1","nonce":"ab5e19699a79a656383dd41d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"484eb5c830cf9206653c876b2d9be57fadd37232fba12195707f0ddb2ad4cccd9251dafb82046c2cf53a96e941","nonce":"ab5e19699a79a656383dd41c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"bc1dab1ffe5ba76247073452e7c2c1ad381ddca3c4656ea3adf191b5ec1a366bca8167c33c938df14afac8591f","nonce":"ab5e19699a79a656383dd413","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"dc54b5a3a2d93be9c7376111d88f575856110998adac4cd37312496d35cc32f80225b2b9adb8fd6ad9ae096b04","nonce":"ab5e19699a79a656383dd412","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"7de351f57b41c028621ecb9a308665454375059927d1c46fbe9462c0c17bcd14c85f499789f78488ebd89ecbc8","nonce":"ab5e19699a79a656383dd411","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"9a28cf9ec0085b81cba9597a6c308be417c2d542f1a65af9b650ae8cd3eec19071fc1f8828337585d1a8e7df10","nonce":"ab5e19699a79a656383dd410","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"9c87e92fb8220ef728311f47a17ba080896d00cee33f6b43d063c29ca404ff298ee9c4d867e09c6de49d0d4d68","nonce":"ab5e19699a79a656383dd417","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"6787a45f17b7e9ce62e32cf7346639b5ffe4016e7e0db1d980d50aa36d2ad633de675c58ff4f329b36a2ca407b","nonce":"ab5e19699a79a656383dd416","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"cca7c2bfcfdfe286573e6e66aa16b469a26037c16de403dae873faf744c3402e90992a60d0bacb2ccc5845a290","nonce":"ab5e19699a79a656383dd415","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"b1c90c5e70319ffbe2cf9c6574fc03b92b87af63f336f41cf8fdaaaf91bb9a43f452eba916382df5b0c3ae36d1","nonce":"ab5e19699a79a656383dd414","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"f20899bbb7f82e272a7abefe7179da363e112d3ce4f4e9d040b59908736350f2a81f68769f13839dfb435df937","nonce":"ab5e19699a79a656383dd5eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"96f75b1cad456c2257f0df2f038874c100b925d01d3d55bbec416f897c65ffbe"},{"exporter_context":"00","L":32,"exported_value":"30300911650b451fc1faf2e845e9c63d54a8a96ab376a696cabc57450f6bf5eb"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"ca4f9e5bea692da07140d49299eb1aaeec60ebb4a6f929e1f0a4bbecf023937e"}]},{"mode":1,"kem_id":32,"kdf_id":3,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"7614f4c85a4305c41df4116a8e260f69bd3a6e0b14d1af44177a00a1adb9655d","ikmE":"741f7b1d43f3413d630525b85c2e6a73a458f1832f91dbeacfdec37f8584a642","skRm":"13106adead212c4f5cba95591d1d980d8cfd8dcb0b88f24d2d9c014efc79cd83","skEm":"b03adb30c75160cfbef5c772cdef19384c8c79757049b7579d53a546528caf59","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"ef512ad154def3e313a47aa2f995e6d0ec644955a2eecf83ebd4c2275e9a690e","pkEm":"e515291ceb2beacf082401cf25e67359df4e37d05afbe6ddf79905c6c187cd1d","enc":"e515291ceb2beacf082401cf25e67359df4e37d05afbe6ddf79905c6c187cd1d","shared_secret":"cb7542168841d001059aeacfff789b5e8de21617de2fb281e93ac3a94c0dd46c","key_schedule_context":"012bf29bba14d4c88e22c7637cf6fa2c279836a13308286be2fbcae87dad2dec2c47252d8fa4e8b173b715aae0af06bae18683a6c022c2b1c6e28a096f930585b8f18df7d7fbda3c938157f486a23f47621b8c7bc4ab9d89fd902c1d406709ca1b281ef1b7bc4736dc044ee497d5dab805fd38a9f4890398ab2569653a0a7ff73b","secret":"e474bc7a90702f4913fd61249638a0dcb781a9a80fe91293c09f6f96b64ebede80977c51db5f8dc6a7482a885a9ad354aceafe574c82a3aaee5c4fd3994ac469","key":"d14e66f0ad30af54907dc5bca40217a473806067680e84d39dd5c398d72d9e66","base_nonce":"3f7fdeecb824e5041e4d3738","exporter_secret":"7930b170ab9f28fbd318e964621655444120c9b612e6fafc43f314b6c33a522db5bcb44752c575ed07268b2fe3c12ebc8019064dd45d53bf3d63356ff13849cf","encryptions":[{"aad":"436f756e742d30","ciphertext":"24d923f80772845e960ea5c55f621e563af9543165b4690a9a915e342f4b69eab158ff3181f150591b48b4398e","nonce":"3f7fdeecb824e5041e4d3738","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"95ba9c4532b00ec7612aa71432461d1a48d94c1277920630f69b121d377cdd07abc4ff52193b684cab7ce9ded8","nonce":"3f7fdeecb824e5041e4d3739","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"20a6886f6d460a98edcf3dc395925bef792de5c72d95e4d1757ab8cf9e6fceaf9883d0d1639be1ccd99bff13e1","nonce":"3f7fdeecb824e5041e4d373a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"3d1345e02f015aff0d513f507fd0a1e90d5e590c43d1e2007c9a62491902f959771b318675a6d3fdcf548def58","nonce":"3f7fdeecb824e5041e4d373b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"d2b7be8ea9be241d52f0941ea01c15b352d9a4978796b765115283fbe88bb78a5cfb712e9c581f3fef3fd5dcf2","nonce":"3f7fdeecb824e5041e4d373c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"80f107c2fdf8791fc978d6ed6ad30240843afc1233f544782b28e20d653963a275c1263da3c19a61b9ffdb1251","nonce":"3f7fdeecb824e5041e4d373d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"3179a799349b9482899515bbac730f3e979ffa419030c9256825ff4c7079d8cf311a9eab6afe0372cb58695067","nonce":"3f7fdeecb824e5041e4d373e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"c0aa2d7e05fcea96fd310a9879ddbb6e221e268bd38af49be7978f73e34a5aa391690d891fd97b2efb36669b7e","nonce":"3f7fdeecb824e5041e4d373f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"08f75744d81a9045016d0a2f7c9bc37756dc11bb8e1be8d5096ae437ed0eb07207e99d1c87cb9d1d52bb4a5153","nonce":"3f7fdeecb824e5041e4d3730","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"962e9d4679328f9aabe8ad7ffea872cb56301455c5fcdf05ca8200c6262302b58e7343e29262103bf6b304676e","nonce":"3f7fdeecb824e5041e4d3731","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"286952790131cd5cef81d04eb75546d04703d4e1184d7e53cc0081eddf12fe301b85575939e64fc85faf1e52d8","nonce":"3f7fdeecb824e5041e4d3732","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"e64ced9d940a135bc51b9bd3f6be08fcaec9111a23f3be89c661d14fabdc67707b912ad9b6f4dd7b836b8194a7","nonce":"3f7fdeecb824e5041e4d3733","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"dffd1f1e10288c0d3aabac17105bb48d62fb7965c6ed5dd19a0e941cc09397bf0853ac39965b03e5cf8a488bd1","nonce":"3f7fdeecb824e5041e4d3734","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"97aef0ff0d4e8648f768b47f7dd157d1be0ea3ccce31abb670cdcffce3654ea3042da346d5cfb8855c3381f403","nonce":"3f7fdeecb824e5041e4d3735","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"8870c1a8dc0234d2c9d17d1063494416476fc2996dbebe87cef37cff97349e6cd93eaa892ab898ea470f2b9472","nonce":"3f7fdeecb824e5041e4d3736","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"d60de3c7dd8917d2e7f5034e007f48b79b8a8aad906947623696f22801c80a95c99a563fa2d1bba69d32b83cb7","nonce":"3f7fdeecb824e5041e4d3737","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"cf489651eab1b7a370ec757587ab47729d8cb94e98f6351d91c4ba340a7f2f002f6ac123c63573a8a0539431a8","nonce":"3f7fdeecb824e5041e4d3728","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"0fbc716e054eaf50917644f08b48e9c8e8f6f69665a39177f74c7683b2873f563536a535dd327773bcd3432572","nonce":"3f7fdeecb824e5041e4d3729","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"89520f0fc398670a19e450bf588f3d3a090feb78477a06714a6133f525c246cb9da240f62a2f97a44624241cc7","nonce":"3f7fdeecb824e5041e4d372a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"6406e84d9cf64e4123a73fe241968aa1b3d868eb5659f6574ff925598fda48429c4b7bbb466aceae49d4884e67","nonce":"3f7fdeecb824e5041e4d372b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"900a321929926f9bea44f3cdb504244ea167f01ff60949d6c4eabfc60bc6880c5dee52234ef0bf3e21bf548016","nonce":"3f7fdeecb824e5041e4d372c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"8ecbb631c00939b38daaaeb85947a754dd18e03846889d957a40f5ef490a6bb356c4362836ae0e490e46548816","nonce":"3f7fdeecb824e5041e4d372d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"90afe73624d659a01a787473bc508c1e0a052c2cca03d7ccb025111b0632e6132e3dde5cd2cf56bd3ab809fb42","nonce":"3f7fdeecb824e5041e4d372e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"d0294e1b933d6bd503f72cde4eb04e208b6982900742eb982145ccfb8ce813c0fe944c00fb330dfa65f918bc8e","nonce":"3f7fdeecb824e5041e4d372f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"a657979443c01c4b7a30d266bce2276c9c09cdf84ab60ff35332831b81fa33ad8504c3b639fd10849010738573","nonce":"3f7fdeecb824e5041e4d3720","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"ad640b75e21b51fd2b1477567f1158c8f52163dc2ae8ad0f795f7c4e53f5c994f377b6960a0bbdb992b62b52aa","nonce":"3f7fdeecb824e5041e4d3721","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"2fa0081b31a58c348b824d9e8269a76d9c4ec05052789f1f0d1e921e364f9b21869cd62032ecbbbc028933f78d","nonce":"3f7fdeecb824e5041e4d3722","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"c8fff620a90f66a7d7163716e6e4909ba502f03ad6de3a74b3b0d223e617f8c63d9ee06632515ac97f97cd6729","nonce":"3f7fdeecb824e5041e4d3723","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"2a34e0ace2d12e7718f6780f0529ba309395f27bc64d28abfef5d113d6c447874115755868faf747957175602f","nonce":"3f7fdeecb824e5041e4d3724","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"015bd86436348ba5a970c8d47a03f35e8b2fbc9a571a28ef2714a1f48fec7fbbb7c77676da301d881fd26145d2","nonce":"3f7fdeecb824e5041e4d3725","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"8fff172ae515b29323effd7abe842db9ccddecb0e38702f65f7447f81631210837cb048bb5d7a207f09ed0bd36","nonce":"3f7fdeecb824e5041e4d3726","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"1dba19b8c6dec367a0ae6bae2eee7af50b95a24701c1208239be62d1d0625f3d873b54fb768e5b45c70579f57a","nonce":"3f7fdeecb824e5041e4d3727","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"2b91b676b4f804751d44cbf56f37a1040842f1b028f679b08e14021b01c7a2e8822acb917d97ef1c14ee3b876e","nonce":"3f7fdeecb824e5041e4d3718","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"ff0044febb2630e9196d1bb55c189b5eea1e4a4d174d24c8c99c2ec873b9b562d9a5ff670263745ae91cf0da41","nonce":"3f7fdeecb824e5041e4d3719","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"a37c255db3f1476a4a4b5f5d3847f52dd7d17e9ea3c1032821c178250bf877fc707282b81aa842390684d474d0","nonce":"3f7fdeecb824e5041e4d371a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"43c851c0ee15fa9d48931f8ed4a77be340967467bcb5214dda4d308a0a71042963dda78947ac22cd89b80c4170","nonce":"3f7fdeecb824e5041e4d371b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"f3507378e380e13094bfab7cdc263d7bafc80058e562f7f6ea0693d66adbb6343cf4678d0c6655c4f86c14ed58","nonce":"3f7fdeecb824e5041e4d371c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"033794ff6db1fcd719c123998216d878cdea835a1a8160ded5b5c32f5f3c806cdc566af0d4b79dc2ca608e11ce","nonce":"3f7fdeecb824e5041e4d371d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"99f000713a718084996d026c59bec340f17ab858867da7705e66af713aca41b2d1e73d3b51cdb3aad9f8dbc239","nonce":"3f7fdeecb824e5041e4d371e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"c5f1403664dea638d89c69d3303f7899dcaca9be6c04f95ca40a5585c515c59929d5099977ee23536ac7c37b1f","nonce":"3f7fdeecb824e5041e4d371f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"1d4f1d6bc069f6d1344e1adfb5334d3b8b7a3311018527413445554e44cf7e43badd3615d1eb6fa7897e315703","nonce":"3f7fdeecb824e5041e4d3710","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"08ded6806f890f510efb9d7d4b3efa42779a91b37efe75ce512182d93d4e2a5f141d79ef1e1ecd5398f2582b67","nonce":"3f7fdeecb824e5041e4d3711","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"dd5d3d54abf0202bfd07c58aa1e25ae204a8ee2e004cd83c053e438f1284e25c3118430635a80dc9ba1bd2037b","nonce":"3f7fdeecb824e5041e4d3712","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"0b5e8447d7bf0513f2d3990151d0325c80c9687b615ea5612130156569a343b1a2683b412e4c7d19a420af25a1","nonce":"3f7fdeecb824e5041e4d3713","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"8b6afb058e160718b5b2decce86be38d9d13eefb1d0e755c1de9df800c38b568f12587c5673b7ad23130f49259","nonce":"3f7fdeecb824e5041e4d3714","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"d3988e48d27b186c63b0eba86974e2d562bc269ae585621c3dcd9098f269566f360cc8e2be2a4522bb7f57d4a9","nonce":"3f7fdeecb824e5041e4d3715","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"67cb94a1354f2c630807dc7fee3a13c893b6d8698894beff3ff039ac86f080a01f5c9ebd21c3cd619548691932","nonce":"3f7fdeecb824e5041e4d3716","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"a307e87abbf3c7198b8b2e3410005b8060d31fd17b26cb7492cbac8d6d1deef81d5b0af95831efc542c18ef02c","nonce":"3f7fdeecb824e5041e4d3717","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"3ddbb8560afce53deaea4f76fe18d4968866a37b59086099d8fdf694a2d54f3b2c74388bd475ffe0161593de2e","nonce":"3f7fdeecb824e5041e4d3708","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"0fcdac64c8698d963eb09491502c5d204aaf44bb11417bbae4e1dbd6e56f28c9b13f41355ba12872e96df2d623","nonce":"3f7fdeecb824e5041e4d3709","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"d6864201fb56f5d3f64ddc7cdf7a17c70677d6e233d0f91362a540c2e9690b9e1717ff9cfc7c4f185f2f6647cf","nonce":"3f7fdeecb824e5041e4d370a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"51432c3b1114b688db23a195cdccbf8cc1e83b65965aca7479840cdf90219024953f743da1f4cd0fc19d98e2af","nonce":"3f7fdeecb824e5041e4d370b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"709052a99e4303ac610be710618aff18ea6dc4c3fbb14476daba7c12905642d002471d08661371400883d3fea4","nonce":"3f7fdeecb824e5041e4d370c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"9ff31d4e51742f45f35168770f34ba7da908cea7412a5d1453980d95d297be5de483245f69beff591141de1b32","nonce":"3f7fdeecb824e5041e4d370d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"67005f7577a812372dd5b9da97307f02d9cad4494fcbabe17e97765793b54a3813001b3103a4c8e9246b7042ec","nonce":"3f7fdeecb824e5041e4d370e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"06f0728967602e94f67ddca96f1f5df01586272549d723b29f35fd70ceca3008ca91ac8847a487a90d0b848519","nonce":"3f7fdeecb824e5041e4d370f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"fad8dbeb6de13a403712188f292035d1e29774571c84f59e74f9f577f39b6623214e7bdbab45b0e7cefaf84294","nonce":"3f7fdeecb824e5041e4d3700","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"c8d31b9247066ac289af8d7f01f1b49a6d9e5e94a42307a2c479b1510aaf6556f0bc5bf92830962478bdcb7ae3","nonce":"3f7fdeecb824e5041e4d3701","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"cec4b1d57cf4cb2d1c33f4970de25766f6bf383f340a4569f0874153b47932f2c6011123054eda1d1dfced9b54","nonce":"3f7fdeecb824e5041e4d3702","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"ea202d6b1c8b97e785d87d1756c2f2b815923100ce53e48cf2314792f2667efd11ef01a61ca3494848e1fedea3","nonce":"3f7fdeecb824e5041e4d3703","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"1b1647526e153005bbc62972c5ef88e69b6dbebd567b5ab1868e30991b972027e56beeedcbcc47201160dc2fb6","nonce":"3f7fdeecb824e5041e4d3704","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"15af199ceeea75d901516313251631faecf914ff3b2869b55a4e3b68c349c22b7c5d129732391b9096358d7a04","nonce":"3f7fdeecb824e5041e4d3705","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"494663720b53c28e3e7d14f4e0e5d0465c79ca56eed58c94d20ccefd3b6ffcac96959e6627ea2f0496cbb8e7bd","nonce":"3f7fdeecb824e5041e4d3706","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"d5ea0c952304b8625b6e683e6c79823706e0f8433a21dfe79f30cbe43b3675702e05c1eb8f1b70878f878c911f","nonce":"3f7fdeecb824e5041e4d3707","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"cf149aaa10d91762d8b354d7ec82380895c5d6b53e207ffa93dc3f2c735f349fee591815379834e0967656756b","nonce":"3f7fdeecb824e5041e4d3778","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"374ab8f3e834c1108008499ba35fa1c8f876b5e4814d9136c36de2bb8965a3162519a031434528321667802dec","nonce":"3f7fdeecb824e5041e4d3779","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"c63e43cdc534ad1d4c7d665917a236b1c76b77d0ebe09cfaa33f32b9fae7cbec0069e335c0e8fb994b75a9cff7","nonce":"3f7fdeecb824e5041e4d377a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"e03654a9fa8bbc8550f61ad977a18495a0677a187f74ba4fbc92ccdc53f678b6395d5cae830012b6d56835d854","nonce":"3f7fdeecb824e5041e4d377b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"d1e4d9e7bd47b549b3bf5b5736153c79ae837d05dbbc7f529ff68651802aba427a9a01ec2f388059da04fa00c3","nonce":"3f7fdeecb824e5041e4d377c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"e004c93f83645343899783377afb4eff575a0a25c73dcca101b7674d10aae4e74cc4e6638606817144e497da18","nonce":"3f7fdeecb824e5041e4d377d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"967c4ff35bc87438349270b912b497369513cca31eb76b48657dac46bd56b55859900c8c8d11effe823f6d0943","nonce":"3f7fdeecb824e5041e4d377e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"8701d262837d6fb7705a928ae6e96a328342cd849fa073c5a7c17c8abf4b8025a3838bf709f0d35c67544b2c1d","nonce":"3f7fdeecb824e5041e4d377f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"855aefe394c4073ec3c3532d3d1c4022a3d12bf22e16c6614488a1bb62f0b9199e0662d2b2a4f9d1456aca5674","nonce":"3f7fdeecb824e5041e4d3770","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"c929bb55b5a714094eefac99061745881f1c19c3d0f9657f6583d6f74b983764ea5b48320bcce55ac71cea2f83","nonce":"3f7fdeecb824e5041e4d3771","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"1d52099be83ac899f94e88d57ff3e7d66c7c9a805cb77d78eb43abf0a8c34358a9ddb5eab9740155a5680ba9a3","nonce":"3f7fdeecb824e5041e4d3772","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"7699899c4f6e6df210d9ef059fa2dcb09960dd062cb43814995a85f9be64d2522e6161e19a3159cb521c4551e6","nonce":"3f7fdeecb824e5041e4d3773","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"0c7ae873925d5cc64ad40ef5f7cc34f46e66b112a38b82516167fa4db16acbe16883a15991a29d27906b8cee5b","nonce":"3f7fdeecb824e5041e4d3774","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"7f2dc6a2f13ef2e4ffacd580ba7c7420deb6f65252a6c448bb4067ff8a421fafe4ac327f3981d86ffcb814a03a","nonce":"3f7fdeecb824e5041e4d3775","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"2939d4d2b923399c92280abfcf750f4e074b7f15000e92572e5c74fe93f26a03c1c0be98e75d1f85cde5db03c1","nonce":"3f7fdeecb824e5041e4d3776","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"b93335c6a1e06c573b5a6180e389140e0e1f1686f5bdb77211e905affe616e0c08db80298ff475dc51db860adc","nonce":"3f7fdeecb824e5041e4d3777","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"58aabe016386648ab988400fce5c9de4d6208beb69bedd9ab805f9ecf9a3d89eeaecc0cce59b8c4ef3a44ff6c9","nonce":"3f7fdeecb824e5041e4d3768","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"e6336917416a7a4d3dc20acc719adf261449121fa46a3b8cbd71535bf87e685e374585abbcc7a9809f4bfa5181","nonce":"3f7fdeecb824e5041e4d3769","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"91eeac7d581721413b47d72eede750ad6d7633e4348a6e9c52602518647cf3d69c95f1664c70674615f9dbaee6","nonce":"3f7fdeecb824e5041e4d376a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"49a52847c922e1eedaf2d4df692d225c95b6fd9f20deaf58774119344c8447aa52cd3442d3155ea8c2c6bb4f8b","nonce":"3f7fdeecb824e5041e4d376b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"7f35b2b95805adaa0ba3270c0d20e69889f353265cbfd9c85a50ca12f0bb9299b588a88f76003e2fa2374f124b","nonce":"3f7fdeecb824e5041e4d376c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"9f4b1d81885305961e37c1b7a8a7d5d743b172f3a932ecf3a2b70c2020bc207922f5a8ce03431ca9d19d9ec459","nonce":"3f7fdeecb824e5041e4d376d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"db5d79097815a32a691266c4ce9f276377101860a315c345b37f37ceacd869ea67e3cec7b26baa81ab313f2581","nonce":"3f7fdeecb824e5041e4d376e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"c127be2518fcb0b0e6be04c270051414222b2727233abc6a1794d9d4ca45283951bd87afb52ece60579bdc758f","nonce":"3f7fdeecb824e5041e4d376f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"6d21be1893fb7a20fc93752d743a9c4bc83ab5200b795dd76915c6af4223d99ef9dcb85ebf5cf1b31186a5a6e4","nonce":"3f7fdeecb824e5041e4d3760","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"5558ff4f7b4bb88764d9f905b9eb0b60fe9d253ec002ce8850f64db95448d025eb1110a565950d2acba42a74b9","nonce":"3f7fdeecb824e5041e4d3761","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"36fd6ed40fb2722c6e10048267d7028d975e2889d7bc5567bd478e09d58f68183b97e2e42cc19f215e6da044a6","nonce":"3f7fdeecb824e5041e4d3762","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"d8ce0b1e6d834ffe252cf08c08baa2b80af2a278d73d825217076befb71d85b6f0c22c327ba3f1096d44058981","nonce":"3f7fdeecb824e5041e4d3763","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"3d23d088ab2200694e908a2c544689595fb664c630121be16fca84470633db11dca0121cfe42d8512af94633ff","nonce":"3f7fdeecb824e5041e4d3764","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"47a1391e576d755eafcc54b018543fcfc43fe0c506ebbfdb94ec9e65b0fe795fac665bd076d34b8f541d2f1be6","nonce":"3f7fdeecb824e5041e4d3765","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"4496d62f3db6d465b5c68734ee41d963de387e19bc1b0c5a31b4516eeda9406ae1771910183bc59e5e25757134","nonce":"3f7fdeecb824e5041e4d3766","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"7d683b7b8e56ca2ef6daaa464bb5d2726329135a756502c252d673d227af0916935841e39a4a50c04b75f6deda","nonce":"3f7fdeecb824e5041e4d3767","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"e2c9a318f44da261285d51c4318a58897b59f041babde8ab0b2fb0d0a6b915e721f4cbb3920b669cb7e6e7cbee","nonce":"3f7fdeecb824e5041e4d3758","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"89a38570005127c2f5d48c749854c87946a97474d0bb66cdaa37190b6b9b1ac20b6c5c4762efd0234bba4fc067","nonce":"3f7fdeecb824e5041e4d3759","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"3ab0b2963be94ee1221381356766ca3f6d358c41dbb7dc1f1585a966a09fc9224a5c83c53ebf497e606e028334","nonce":"3f7fdeecb824e5041e4d375a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"acef4431545717e08f8a2cef0ffe7616237f662fe1887a02498cd55a0e3af36e0bc1126b8c3441004cf48b4366","nonce":"3f7fdeecb824e5041e4d375b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"4b5d639ba4e0b66eb3825600c8f7cb61054597baf41d1a74bae0f515c56ab074d4dbd24e504d73715e1b1c08ca","nonce":"3f7fdeecb824e5041e4d375c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"29e5cabdee9a2c46540df2f6a965d67d26dea185cd636831e74f09084236b50c3221a5fee69e8ddfccc169ead3","nonce":"3f7fdeecb824e5041e4d375d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"e4129ceea402fe547274edeb2fcb23da6cdf22978aabebbdc332f440678ef56907a644df46a83622b8474e4a26","nonce":"3f7fdeecb824e5041e4d375e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"efe4eb9cfe9d97ba5d2b9ad043f37e5633add3a6710817af9e8a863a5c6b54e461e3fb270551605d02ba8ecafc","nonce":"3f7fdeecb824e5041e4d375f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"e682cf1fbe582a5b29fa0b8859e78435b85f098eee40df0f2335d3bbbcf1f2003b6826a42b72294a6de8922326","nonce":"3f7fdeecb824e5041e4d3750","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"f656f92a0b378c4c969d9c0e8184ddc35658bd040f350aafe0b21254ed1fa22bb368daff0b22352834287c0f28","nonce":"3f7fdeecb824e5041e4d3751","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"039a1efdbd2f6240f221a14e4e459f8d6a12f44e02f31dd1ff4eee1aeaee5822975ac6931696e5e854c666980d","nonce":"3f7fdeecb824e5041e4d3752","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"7bb1c567ac25d8559e104ddb17ba92ca710bc7a08c805541df9f4931a11914985c29de2fa1db6361f5be7b54fb","nonce":"3f7fdeecb824e5041e4d3753","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"1f7ca20c54053af52af37190b011acbfd2eda37bb09688d56b4fe70c2eb059ac9a1c93bc04d04291cb799c3af7","nonce":"3f7fdeecb824e5041e4d3754","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"3065c57b53413932b3771f13b9c4949e2bf793cf81ba128351db5317dffc5edd1d89c08b9fb0357b42db0ee0d2","nonce":"3f7fdeecb824e5041e4d3755","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"6745b4168e74c6e86da2ea281e17602485826ac80c40cfd848b53c854c88b1d42eafe5ce03c54fe4b14f6a0824","nonce":"3f7fdeecb824e5041e4d3756","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"f8e66d38cef584ac434ce7fa92b0aacf312b84fbdff7d9cca1f8acabfca31afa1acb449cb3fec7b227966a7ac6","nonce":"3f7fdeecb824e5041e4d3757","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"3ba022c3523ae972262000088929f198aa8a1a7b43fe2a18a4831eaf56fd3e6eddac3e4df7ed29993446a1c712","nonce":"3f7fdeecb824e5041e4d3748","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"6dde05bfc733766645d79e41115b24d10fe094f227e0137c1491d618a817071767d86c7d9cc20a7df7fc634958","nonce":"3f7fdeecb824e5041e4d3749","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"502e7a83e8ed698d99ff671413de61c5f0016b879a61a75edde1f70ee633c5d78b2ba6fa7db610cf25fc0228e8","nonce":"3f7fdeecb824e5041e4d374a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"48136d4f4283e3807ad6c478b8d5f009e580c95eda5b504e26e847c1020b66aeb05ea356f1e074cc683bbc45db","nonce":"3f7fdeecb824e5041e4d374b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"47f26bbee266bc59341e912dcc64d5797ae1a4484a015cccc10cdf4e19538663d5966e87e6c06b93d94f23ee45","nonce":"3f7fdeecb824e5041e4d374c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"cda4bcd5fc609d251e143e44b5d2d4a0dad26086ef1b672ed069865ee4e68a7f122b29541002454313c3269a91","nonce":"3f7fdeecb824e5041e4d374d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"c8c2589112824d4fbfd7540f5225278f3ddc3d99de8576f049f01fc732ccd8d80ecaa3196efcc0e77aeb956e9a","nonce":"3f7fdeecb824e5041e4d374e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"2ace9d12a393972aabddeb0bfe7af7c74338a437b0ec29e7a5718e2d633bb3e48316bdb5da398700488c80efca","nonce":"3f7fdeecb824e5041e4d374f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"f83c0662fd8763d1d447b2703f41c7f0adf62ae98516658cce98640fd9db484631b6e63619e5a83e047c8e36c6","nonce":"3f7fdeecb824e5041e4d3740","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"b034ed878dc02408c784a2313945aae52d21375f2ae3e0da9b841705898100d1ecb971e6c70889fd6c6726dabb","nonce":"3f7fdeecb824e5041e4d3741","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"e8f736c47432e21cf9883643e56df77cfe541b269d092980f343ef1d57a240fa809a7eb6c5de391a50f9c1aeb4","nonce":"3f7fdeecb824e5041e4d3742","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"c75413cdd22e30d12127e4c81e273c310be0f017ff258881be80635262ee64617eadc93ca45d149fa8b2945951","nonce":"3f7fdeecb824e5041e4d3743","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"811d66b15a152701d5519a6511da460049571b2a0f2b917ced022ac33db79054761846b199465545f3970023e3","nonce":"3f7fdeecb824e5041e4d3744","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"cc098bcd832745e76ebeccffc8c0b76be028e6fdd7b7754f8c4f902456ac239a848dc100fd35043989d2907fef","nonce":"3f7fdeecb824e5041e4d3745","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"2296eeed210b643cc37d8f1d556ad875190b01cc465bff9433d0e3522fe9055d1b3f4946a5f197d893d5aea771","nonce":"3f7fdeecb824e5041e4d3746","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"ef5cb8a310e016381e77d64c0edd5b14459a9f948d4ed44a975bb372cf33ce4cf966d6d12e3ea5e32cb72eb4f1","nonce":"3f7fdeecb824e5041e4d3747","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"12c034a88626f3092ef8c0f1c4b3e434927aff64cf9e5142c4c9caca26a42c8f086297ebcf4cd4058276c03ed2","nonce":"3f7fdeecb824e5041e4d37b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"80a4bf81f4154ab1a26c2debe3042ce54489242a019189a4dfc906d877c4183f85a012c3e28d0e27e2bcf62bf1","nonce":"3f7fdeecb824e5041e4d37b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"2896a0d2132bb3cac76d7ad48edc4fabff5a6fd6cdb9fbc1639bc172c52bb3cb125b28851faac9782ea1733aac","nonce":"3f7fdeecb824e5041e4d37ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"5084f562ef0558683cc766eb7d6a1c4f6b83a14e48d67a0ccf14838fe876a6e68d1e62e1b1c6f71a0c3644fcf9","nonce":"3f7fdeecb824e5041e4d37bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"489c1a1bbd62c1c9cced0e84a9be1ac011ae6f6280382618aafe27038a22a9c9abcdce8bc19070454d939f86e5","nonce":"3f7fdeecb824e5041e4d37bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"e8c760133d056c882667520c8d59c02c0ef48b10c6a4e0a77049902022b068207944bdf9b979f5384447284a42","nonce":"3f7fdeecb824e5041e4d37bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"362f25ee01fd7dcde4efb342d54183df225ee85d6b12a7207c8b4509da6873e0ac6e28cebd8a3473d3ce56a61b","nonce":"3f7fdeecb824e5041e4d37be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"59c20cf3cb1caa97188edd20d5f546474045405a43429c226399a8468eafc82b676afc7b8098aca37c405211a5","nonce":"3f7fdeecb824e5041e4d37bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"9d17a1357c19edbf5c12fd33b6246d9951d6af81d15b24525de2dd3c5d7152c6cd62d69fe673081cd3eff67527","nonce":"3f7fdeecb824e5041e4d37b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"069887e331cfd4bade8ef77d4a713ee666e98e9e7f5c67979b8e887148a1aa696359771837d45062e5612c28b8","nonce":"3f7fdeecb824e5041e4d37b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"f03e059f79de9e3530b1a48ee0100965b7fafec7f57e22383d95ce7ef27362791c6823fa7097827dde777f6de6","nonce":"3f7fdeecb824e5041e4d37b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"099f8d2028e9b7fee740aed475dc1f034f8f0e39ace2c09297410415e74c8fee649c5d153adf1ad5e18d3b3e3b","nonce":"3f7fdeecb824e5041e4d37b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"579058e4ac21ed48d56b791b81b6a857cd85a6f94f41f3d125cffcc19a5df2211fb2c32dda836a19ae6f85b908","nonce":"3f7fdeecb824e5041e4d37b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"269203ccaabc66fd9d0dffad60b7d6b69f290b49506cf034991f3560ff030a21840405338d262ffc3ebb0c02f4","nonce":"3f7fdeecb824e5041e4d37b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"79870df88f50ade5ae02b22582c40a75ea86ce4a96dc3d9376534b5b1e73bde262685faec6350d73b634b428cf","nonce":"3f7fdeecb824e5041e4d37b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"3dcf68b7ec400ae39393f84a5b59e627316ba03646201e9643c5aa63ed074f9fd1c40a08bb262a6138832f44a3","nonce":"3f7fdeecb824e5041e4d37b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"a1e9f854c42271b82830212aae67eed73275bc6893d6210039894623f1a493e94f23ee7326bd4813283acab610","nonce":"3f7fdeecb824e5041e4d37a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"5ad4d1578232603fee4fcf9846de37965dd09200c4153722c035b5511b6d485f08344a126faf74a51881abbfa4","nonce":"3f7fdeecb824e5041e4d37a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"32b3e3831c84a1e38ec1d030622c128d9a94e81ffebcda369eff664372c567884411a22a57a99041e38c63a627","nonce":"3f7fdeecb824e5041e4d37aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"79f9dc6d78853c2b3885e2ce6b7a793cfcfbe27b651e363853127915f7549e010496433054f0fcf7213986e059","nonce":"3f7fdeecb824e5041e4d37ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"70cb86630a6b007cd22b897d97962a9e573c39eb24e44e56d06ea34d5492d4febf5bc618f5b86d64937a83efdf","nonce":"3f7fdeecb824e5041e4d37ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"243e7acc5b3c7f82dad9825f34967f18165d11aabf05305e5ed2bd7730cbda014902e001bd75f4de78dda9a665","nonce":"3f7fdeecb824e5041e4d37ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"170364c1b62c7e093d0b4d3862c8af8bc722eb4af624b6f5c8ae11079364f5d6950eae9139fcbad09dfa8f5471","nonce":"3f7fdeecb824e5041e4d37ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"5bbdd49a8df3682eae4974c5c5e8532f50c7149649838e2b5b1c67c88aed12f17c7ed687bec4addeed210ed81a","nonce":"3f7fdeecb824e5041e4d37af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"3e2c4c311220f391f168e0a7112ab17d61158450c14c0e9073d7d9831c2687c4e7bc8e44948269e06e11c79bc9","nonce":"3f7fdeecb824e5041e4d37a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"160c1aa7e7bf21bae3959ea916c78c04bef8a4b36d22ba806b5c7f279f921bdd3af43c690be9b967e9bb9dd91e","nonce":"3f7fdeecb824e5041e4d37a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"368d3d06ef31a9e6c2ef47d35d553b810cd5586f59106c97813c6cae876d1d978776e31a53d0f493c346a3cb60","nonce":"3f7fdeecb824e5041e4d37a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"ac66cb2935463b4cecd550ea41343dcb113c12ef3dd0e5668103a591ef14c9bba875a9291359523ceee0d972e4","nonce":"3f7fdeecb824e5041e4d37a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"fa2d99f756a96b5cc86f1cc3a381379c46e87dfbfe43ee1be47b1ee3291ea5ba7297870d41b8d79734e11cb069","nonce":"3f7fdeecb824e5041e4d37a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"b2522d0f2f7ef0e3812dd40272b26c2d9324cbe0e3556b2812e16f79c974fc416464dff81d4d118009504bb273","nonce":"3f7fdeecb824e5041e4d37a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"be9aaeda7fc482a4e7d2c992464bd0c61dd3ef9dd0d8ade403a2528991cef3f74ea3cf134107fb9d656c554410","nonce":"3f7fdeecb824e5041e4d37a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"1a0e211be41bf66c7e89eb842928bb3d7ef91fecd7e6d0eee7ecec4aee5d10ae5b237044eb19248d80ce28e613","nonce":"3f7fdeecb824e5041e4d37a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"0808cf04a4a5d8dcd53f8a890671db0663b89cf9e9a6c8afb52ef8611eb5aa110f3b339a2cf7e067d42037b007","nonce":"3f7fdeecb824e5041e4d3798","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"17e56c4bd9fb9a5b04579a33edd810e092fa0e39a093efd052060d02ab1d91859f9de393698f9f8577531924dd","nonce":"3f7fdeecb824e5041e4d3799","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"197b4918734fab1d650980e6b076944f8fa0acf6ba605530efdc0dbcbf64d1373c95a3e82baaab463541df5980","nonce":"3f7fdeecb824e5041e4d379a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"bc6e81ba170e360c591d56e067e10c3cced7358ad0930eaee4f27232f8de6c956f6889f8a8996f082b6471563d","nonce":"3f7fdeecb824e5041e4d379b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"930213ec53e22f555f33af6beae9f37e666647d6fa0a33fb4cc1881a67db935fcfe0b721d046ad5ae197efa5d5","nonce":"3f7fdeecb824e5041e4d379c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"1c99a893a5f3b95f0b808b0b24b3be86b29555adaf2f01db3af81cb6d1bed990c1e063093a79500c06b614f961","nonce":"3f7fdeecb824e5041e4d379d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"eac6e300a7267d4cbd89530beda834c4f2bcfeec31f8ed8d919e02f157d320690d78fc8eac7bade436899f9e50","nonce":"3f7fdeecb824e5041e4d379e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"56bb5f609415a1411ad01e56e179bf64f9ec9cad204bc33776577fc6b517666702e232e579e98068dce109106c","nonce":"3f7fdeecb824e5041e4d379f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"6e1fccaff72da3c5c514dbb364f48d4f74e732f8a1e03ea9ce46775802f2d889a71010cc6734218002dbb944bc","nonce":"3f7fdeecb824e5041e4d3790","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"5489c724ceb7b3962a0c076848b7442d8f95cc117d17b5ad1a0f795b6d956282a5213b5998b33e7d9eda474d6a","nonce":"3f7fdeecb824e5041e4d3791","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"9697434c2d7191bc35af84e3d20a413b46bd3285b68cf073e17543f4baf100f275abd0f20adfced19f81b4e284","nonce":"3f7fdeecb824e5041e4d3792","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"05b10f8ebcb809bbf5d7dd98071a85e633461655c5b9aeee10e97f0e9c78f27a0e1feff774f10856288398e982","nonce":"3f7fdeecb824e5041e4d3793","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"1258e2c990964dfee315f79752578a37c1fbee50f812bd5cd7d7fa9bea0c1e2f0ea981bc435547438374185c2d","nonce":"3f7fdeecb824e5041e4d3794","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"cd6ec335eaf91ac9e60c1ec17b88232d491534d87a40043935feb22c63a945c61edcf89a64dac8ea22073be9dc","nonce":"3f7fdeecb824e5041e4d3795","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"4ac1779421612f8503b702882fde55a9229bb87a317575c178ffc8c6faf5dfb85bb510317891ef8edd2ce6502c","nonce":"3f7fdeecb824e5041e4d3796","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"8c14c53de4db0a1bf64652d7c4c95855936b47d3c31eb7059defa733895a94500fb779ed439bafe41e78dba7a6","nonce":"3f7fdeecb824e5041e4d3797","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"bbd4b7c6198a22ef74f0aa0739917870e087a4c74482268fc41d4582bbc2005fd5d2929c4268687f8569bd6f5d","nonce":"3f7fdeecb824e5041e4d3788","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"d71cf204069dce7f18992ede14f3aa60f438d2ff2679cd292e1869d75d36f6d34c9c94347e51ee780c775903f7","nonce":"3f7fdeecb824e5041e4d3789","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"ff4d0a5615fc5f945cf926a15d247a5498b96ca06c5fa84dbf0d681626e9b2541442b62fbd50a64f6ef549b220","nonce":"3f7fdeecb824e5041e4d378a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"769543e82c7a3f7c1d244621e137bbef5580d184c1cdeca7281a7ccf363d7310592cf0c0cdc6df233386b1072e","nonce":"3f7fdeecb824e5041e4d378b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"2b5d4da0efa93fec28f9b277ece8cf93445522b8d58993f097aecc6466d0d0f51da56e844a037df444c5fa8194","nonce":"3f7fdeecb824e5041e4d378c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"1235ab59d229290b14e5d90e0dd88323a862ba0899d72345e3a5e4b102c9c267f8cf4e89bce69dc36dafa856e7","nonce":"3f7fdeecb824e5041e4d378d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"2933d185f3acdb3d8c77d601962dbd407afda85c65f0c6cdcf10afc8f387d6c087cf1e143c10e2e795cf1010f5","nonce":"3f7fdeecb824e5041e4d378e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"325c2be28555777f2c511c8c4a785d1a74701dc2cb206e231333a72ea8160ae68e7c7b69e05851d21ca100c9ec","nonce":"3f7fdeecb824e5041e4d378f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"3b779758513b45ca870b6fcf74301e33a07e25c8d675391617b69f08f9297445129d64444a79f9fda16ddf0fc9","nonce":"3f7fdeecb824e5041e4d3780","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"595e72b641b54d0a7d3f5ff89b94f5f4f25fb080e799303ac8d70c461699da5109bc55603074fb2ff67857cc4b","nonce":"3f7fdeecb824e5041e4d3781","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"c255a3693da29a1cf9600b5d1c628e8bc955220275c9d0ef3dc431745ccf9b62e155e7a0b896ed4d06375664e7","nonce":"3f7fdeecb824e5041e4d3782","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"13cd4da90275f7a483182077b0b2a3d019b0febda87fd26b1dbdfe48c12096c089ff19ded273356b0e55f9aa48","nonce":"3f7fdeecb824e5041e4d3783","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"3398bd8ffbf46cabfc80e4b8655c5872faceaffa8cb0ac86cd77bf15bcab804bba6f04c793ed58bf13f7d70a92","nonce":"3f7fdeecb824e5041e4d3784","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"98f46399af9ef00e0994dff01de6bc44a252f6662daf1bf1e25c1c49aa89f07316962107a9ad298eedda1cf8e9","nonce":"3f7fdeecb824e5041e4d3785","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"fcdcc514269f1f75fbd314c6f6250649bee8423b8b03c76282bf1ca96b1a036413fadb0d30acd0eca3f4b15f23","nonce":"3f7fdeecb824e5041e4d3786","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"55406b35ac1bb2e99216555ffc102c56cbf7a3a7711809758e1f1f4a99e767df97c68285f0d5833f28ee39824c","nonce":"3f7fdeecb824e5041e4d3787","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"a7915a2dc5a8c2f8375fa4ab8be764567e611e5c4ff630aa57f4fe6ea1d27405eff4a2b7e9948ac3888abb189a","nonce":"3f7fdeecb824e5041e4d37f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"d6594fe60f5c3dc77a96106ba55d6a95db0164c962a76496d3724b386a2e174d2b2d22653ae2132443207599ea","nonce":"3f7fdeecb824e5041e4d37f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"d701e7b0b0855cd9897dfc7853bef605a6dc7b02bf47b276c9a6099ed4a997f1169f1a2528a6cb90131ecb29b9","nonce":"3f7fdeecb824e5041e4d37fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"e83730acb16ccbd93418313517c71249de529a6821584dca8591b38f684f684dbcc5d796c8d91321da3d4ceebc","nonce":"3f7fdeecb824e5041e4d37fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"c8a9a8ab97da8fcfe5c4ccbb0875cf7a2d332cb776ac9b4c966368d42b055eab5448348644c4cb5363c9f7a513","nonce":"3f7fdeecb824e5041e4d37fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"a0998dc3a1b98d2012f2680fb23858fd359beee75af0a6a8074689ed268a8432ab7eaec43e3cb2d31c15aee87d","nonce":"3f7fdeecb824e5041e4d37fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"eb069df71bcfa468c53b366d7983ad3e623a960905c8d5dd44d544bea9a59ea837c265fac3f2389714bca40ab2","nonce":"3f7fdeecb824e5041e4d37fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"aea620c02f3877c280f483f11d1565d0132ebd820f9165fbba8d33fc88bbd825cf9b780fb1bd108a16e7d57b97","nonce":"3f7fdeecb824e5041e4d37ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"c32cba7c711594056bd2d4458fa7805f4b76886bcaafe7acf254ba14d9a66e0e792d7653e60839932203ddad50","nonce":"3f7fdeecb824e5041e4d37f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"c3f013cf20d5d0772e6ea048d486a058356f7902c561d4ac48b1eade2f43d9335eadbae2c9707212dabcbf2dc5","nonce":"3f7fdeecb824e5041e4d37f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"fc8d37c970bbb0b40080d3be5941faa7ccabc38429ba27a544c5b9ad102cc5284ade6f25a05cacae6bf6a0099f","nonce":"3f7fdeecb824e5041e4d37f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"fcbd2758e1315c447d4b3ee8c282b6ab9100cab28a7dfe9492b5e094b2243cbca54f82264f23c55019942b0fa6","nonce":"3f7fdeecb824e5041e4d37f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"efa6ab5e3e627e692e10c4acf08c484f704269ca66e97241662c6388afe6b7f962fde87f3d0252173f7328c95d","nonce":"3f7fdeecb824e5041e4d37f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"bede989e8b22322fc7350f7a6affade0d9c2141afca93c72ba36200799368ede27ac46e08b1d3e19d4ce3b22a8","nonce":"3f7fdeecb824e5041e4d37f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"388213b95a1c86576722f651b5f8e2f25f7cc89ad797ead901e59a32ffe27970b1f79877f15e8fecedb15dd7d9","nonce":"3f7fdeecb824e5041e4d37f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"92f98bb914c09dfebb1d7b56607ff2feef2666c800a63df8de87192fb67b73632d9f6a2df718ea49fff780b545","nonce":"3f7fdeecb824e5041e4d37f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"21eacea0e65600e3eddbcd2ddfa324279c929d0b93f020f8f4aa81a8ef8354cc1a78707c5f6472fb8d0e41e8a2","nonce":"3f7fdeecb824e5041e4d37e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"90cdd2bfc5ea1f2fab61ea1ca8ea055f62d57d719ab8c2da699275a79ddd6711b63a7a55c4603f2318fedf9999","nonce":"3f7fdeecb824e5041e4d37e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"43b1df33e2f471dae629428634ef7ea17dc17d2eaae5510749170ca316a72021e4d8c1377bde168ce9bfdc3c75","nonce":"3f7fdeecb824e5041e4d37ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"4d71eaff432120ee0c966ade066a30f38306010a921852fa06aa86f9ce72b027972772e8f8d6ac0a3412c3fe39","nonce":"3f7fdeecb824e5041e4d37eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"cea8dbd6aa090039e88ecd160901f95173b8ccd65ffcb5c65083a88b902cd027fd10771fbdd1b58d800e9ac1b2","nonce":"3f7fdeecb824e5041e4d37ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"00972f77eae55ac88d8aa754b9567a732ae9210d75541a8add22659964eff4e073438cd41c8e9c6e5366e6de18","nonce":"3f7fdeecb824e5041e4d37ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"1f2122097ce138c3085f740e0f1b1028aea3eb650057ba0b7753ae9441bde1c5ad2b254958cc90140fc99fbb45","nonce":"3f7fdeecb824e5041e4d37ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"5342f67f400ec6a736974efdaf726289342c5818cb9cddef8f5dc5ca9574c6aa2b28ce9516b1919f569aabb816","nonce":"3f7fdeecb824e5041e4d37ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"a5c1bc79769821ab41f697752d95be7365d8ff2b3f1af3da42696845d384b4eaf6fcc95d9af9e620cca9c59c22","nonce":"3f7fdeecb824e5041e4d37e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"9f12346fbdac3bbcd784931350c858119ee4eb0dd6d15f363147602e40bbb868c0d7fb616e7a3b8365349f5794","nonce":"3f7fdeecb824e5041e4d37e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"3643cfd54fbed03cc10086c53fbda6d3151801bca5618df4fc5b2058a3dd627cec1f7db22ee350c4f280768f73","nonce":"3f7fdeecb824e5041e4d37e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"6c7abd51baf676c9d884ccd8d764786302b8b474db700faa443a3958c213ba84897eef373be9ae32c96ad96c11","nonce":"3f7fdeecb824e5041e4d37e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"724ea86712f988da178ff8969423af10928ca914a2c03e2dfeb7e8cb9fb0e1467a9b8ec55538d4847c62b44ab4","nonce":"3f7fdeecb824e5041e4d37e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"5b4c3f9c3dea32cddd1323022ff14a69dbd5238d77c77b7c40771484d7102f4d47f11456c2da6cfa2b92ff881f","nonce":"3f7fdeecb824e5041e4d37e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"977d07aa0a21c0d4d94f1000db126d641c9f1ee10d9c3fa559a8c631ce3d1eeb3b54ab57c92f4a21a25cafd70c","nonce":"3f7fdeecb824e5041e4d37e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"7433dfaac093510c443e0ef77f1bdfefbd6499ec2656b93b1089c79e2100553cbaca0d7b142b2207a14d73de8e","nonce":"3f7fdeecb824e5041e4d37e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"1bca8c9d1803bdcfb8a0fa69fefb3db444743de7e6aed1629a063c2065f42c7862e10f6ac2fde87d2679a037b0","nonce":"3f7fdeecb824e5041e4d37d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"e6dca8c67189e727c2cb96e5afa1defefc38013f7d12316fe15f866fc0b90465c388c0909343894c9c18733a7c","nonce":"3f7fdeecb824e5041e4d37d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"ba3350eb450dbce8e490e3eca1044b345ae005816185629f17b6f628938d6971df864f4be930b13a78c52278b3","nonce":"3f7fdeecb824e5041e4d37da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"ccdfce3b45b11433d61f5d3f8733886e82557eb0e8785edc524d3936df26444a135b3317317f7d8e4ae2618930","nonce":"3f7fdeecb824e5041e4d37db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"0bcf74ec65cbd23772a0145a2ac8eabdad6ce94821654a6cc9c9f5a4ad36de3924369aedf17590f81a27bb74bc","nonce":"3f7fdeecb824e5041e4d37dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"92ce2f00e38ddc6d738fb0ab16c5fc727ce0cff15873de8338ada62d2741bcf51171ebb4a7864e7c09718ee8dd","nonce":"3f7fdeecb824e5041e4d37dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"c89daa5d5a3e3a8a080ece803fb781e0bff6514031e48c3023938dd695d146917331728954ea6400ac45733b82","nonce":"3f7fdeecb824e5041e4d37de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"33ea9257466917c65e76e8516c585c1bf2d45cb00fbc27dc2bb3e92d7b4a1b54eda25e8eae0e70294f7f7527a4","nonce":"3f7fdeecb824e5041e4d37df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"dd43b6171e785faf6dde249b3684b1c9af660fda09d7f149a9d986b82260a756c393c577e2d4d91d53b6f344b2","nonce":"3f7fdeecb824e5041e4d37d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"503143a76b97ecfecef9cf64a0d2ada87ee5026242ea262af69e0190ed46b4c55327605b4a5b6913170033f06b","nonce":"3f7fdeecb824e5041e4d37d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"49d955ba2497020b948db783d88e7323407e064b378771569411251f22ead73b44bf592b9a2f733089b6dd94e1","nonce":"3f7fdeecb824e5041e4d37d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"1bc6c8a50bfa673caa6e3283962dd629c004682f4cb23e38405c70f99026df00ff2815dff3d73763c1563bfdff","nonce":"3f7fdeecb824e5041e4d37d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"673a272d3ed86eea47448b838b4ff9388551fbc7fcb7579ec771e49ba41bb2807972135ffed6974091c61649fe","nonce":"3f7fdeecb824e5041e4d37d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"2c05b90d6e9d69599f2ef05105043202d81f0c90624c1a176325941c475e258a003e48574c4664d3ca4c8a8854","nonce":"3f7fdeecb824e5041e4d37d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"b63a054306891bc5dc8fc3c07c43300fe4e7ef9c72d74a016db03049f510d6458b6d1fcee8d29d01e1d4d63137","nonce":"3f7fdeecb824e5041e4d37d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"22704bb7a6f0454418c1d8e403622ed4496747e7a4f682af89c3ce516f3f6f13408205d5c74f9c3ff126821f1e","nonce":"3f7fdeecb824e5041e4d37d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"223dba3b9a6507cd92745cf97ba9535288c4ac47de36c9b84780e88b5a2aed531fe5bcf969790a06931f97df56","nonce":"3f7fdeecb824e5041e4d37c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"b543278e81c61f727fb815fdd9d1583cf9ee104fa577909545e8ac16332d312f09fcf9c473488a32b87a748801","nonce":"3f7fdeecb824e5041e4d37c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"de99cb5d7432ef739161ab2706adf97b6955b30e53971cf5eb42b0e3d70884941c34fa94a5138bc9d06946e080","nonce":"3f7fdeecb824e5041e4d37ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"2742f0f6dce163bef876a6bfbe7987d88a12fb71b3d3782f7a6432bbed6f8f7c3b7d30fb4c88bb27cc72033f51","nonce":"3f7fdeecb824e5041e4d37cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"0f09a60a0d07051fb0417ea959b2b3bf7419eed90932f8d150ba49abbd7c4e1dea1829125cc24733c2042dd69c","nonce":"3f7fdeecb824e5041e4d37cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"26143b80ff7426bc5e7ada8bb49db4decbb27bc49014d4ab0407439109018194a42d39c35015cf789892d17879","nonce":"3f7fdeecb824e5041e4d37cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"b7ee648cf4833fe07cc294484f1375d4c0bb26215d9fbff3abfbc0c1ab17c62aa607b37ffd947deda207a20bd6","nonce":"3f7fdeecb824e5041e4d37ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"560c1ac2d61e35e31b155f5eba743bd894335d855c4f01de4e6c7f3591956f7b44b6540e3ce119014f9cf71d26","nonce":"3f7fdeecb824e5041e4d37cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"ca5973954eb07f058ccd456c49d8423b8022b037e8ff2f921b027a6fcf8fe68f7f1e84f1ea181650526f8d7d23","nonce":"3f7fdeecb824e5041e4d37c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"eff3d9a466846995ca2d86caacaeb014472bccb545db6f10db5e0a78dacdf52a68783c6266dd984798000765b3","nonce":"3f7fdeecb824e5041e4d37c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"38073790583a411bac5f0c04b3dcacdcbcc56f4803c299f289d7410110282170cc068f7b115969d79388978e5e","nonce":"3f7fdeecb824e5041e4d37c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"bc646dc3e70eac67b3e42e45e4e25903e4a07e184a7874289be239057dd6473db4275c2157e6291013b83ccc67","nonce":"3f7fdeecb824e5041e4d37c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"3200f1e35e51e4f789201f4c7e0570aa0034860880049d6a11246a02132b031b68995281c1ba37b5e001e58a47","nonce":"3f7fdeecb824e5041e4d37c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"2a71d1f6559eb73a8bfb05dbcc27b43839c913ab1992bef7899ed597c9b3471b409b7ea6cf1854259c65e7db4e","nonce":"3f7fdeecb824e5041e4d37c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"36a477de99259ece0fd3e0b6c81a58ef6e0a441f1f6a885abd8171418ea4b8afbe66c0a38b5ae815fc4fa63657","nonce":"3f7fdeecb824e5041e4d37c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"cc6cc8d99cfb4d655f87c33194341aa4725f7dd52c8a218d980e29002523cf7636146d488595175b040c15a6ec","nonce":"3f7fdeecb824e5041e4d37c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"c8f365e98587584b81303c79d273e87f62709ab9e06968c1e86fc9a501a4af9827502f90193f88abdc46c8c07b","nonce":"3f7fdeecb824e5041e4d3638","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"b1330a7ad5d5cfe8c3675c693f1f62d2290e61e63a1c07a7ea742d41779de8bd"},{"exporter_context":"00","L":32,"exported_value":"0bf59c0d22578588b3191a4e1e72176929ef640174f0e5a8f3d0404ed2f0c29b"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"661679489ad8c0c5bc64240bd660edb344d378388f04fcea674f15a018ae164e"}]},{"mode":2,"kem_id":32,"kdf_id":3,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"d9ffea696e1a325db752274a00001d42a326c99d23989ebc5aa8fa58d151de29","ikmS":"6e6f4ca12f27c5a55b22206c20f71f1ef04717a8a91a06798754a177f27f40b6","ikmE":"fba5aef14937b0211fd1bec2890a9baaaca835227a103301d5cfb61c7f738df4","skRm":"077c4e60d5edea74570f54d236efdeaa146a77f1cc7747325467326648a501a5","skSm":"f5d97be848a3c76eff8cf17472bc50b034cb9a3fa7dbffe8bf2df6b668bc77b9","skEm":"11b419e02cad18d0dda34e2f775a0711628f20b7ae19a7e924c2c8174d426db7","pkRm":"7538a65bb17efc5762fd09d3c110f0419618f3f821663e0c49821c6beb3b766d","pkSm":"36ddfb4e21dce8e05f45e9e875c48a6b84cb7430bdc7906ac1838d3627a6e410","pkEm":"6d78f7c9be931bb071cfda8b8c4f2ccf13064b22152da261977b948733263a36","enc":"6d78f7c9be931bb071cfda8b8c4f2ccf13064b22152da261977b948733263a36","shared_secret":"6be6b0ffc829f20fe0a211c560ac42482ea4a5aa0496360489bbe58674cd9e5b","key_schedule_context":"0283803015629a22448332cff137aea9ef69ae21d9319186694096d72c7f14d7e493d3883e171235c9b358f9907d0398275a86ec17f0c3e2e74311c05ccf329d94f18df7d7fbda3c938157f486a23f47621b8c7bc4ab9d89fd902c1d406709ca1b281ef1b7bc4736dc044ee497d5dab805fd38a9f4890398ab2569653a0a7ff73b","secret":"4e6e9be323b665e141bf5f64dbae8e66404677a51e0674832b09d63fa746aedca3cc8754f9916e68149829b8c3b0f636ccb111fdbefcfcfaee5f75bb026fde0d","key":"bf3bb5c283120be59eeb9bb86e463b20cd813a9a7dbcf018679c34191205065d","base_nonce":"1fe228841b560c8839c39d70","exporter_secret":"1ff8efd0fe16f59f0c745bd0a804558e0f89e8690e6a7973ddc1bb3349eb6774495a3a995c72e133f0700451440ba6fad370ae3385f1e9cd0543693f6c0eb089","encryptions":[{"aad":"436f756e742d30","ciphertext":"0549482adbfabc4042c8c51a6013dc58d60a7c289d8799a780bdc8259e0e1ff8900ce390317f9bcd820b997bd6","nonce":"1fe228841b560c8839c39d70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"e8043a1da1c6658f522da6ad0e720e80eac37e73e7d93823a362882c18f45ecf3c317b2f1c15c077202f29dfe0","nonce":"1fe228841b560c8839c39d71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"604e3b0b47f42b6257eb73b923a6b678806788876fe1c1f112e464f3f174b6ba298719542219d4639612faba55","nonce":"1fe228841b560c8839c39d72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"8a3fcd71344bac25cdc0d2d3ff9b3c126074309cc7a4927d74111c4a63dc379141d23a51649da683b7eeebb7df","nonce":"1fe228841b560c8839c39d73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"c5d6fb0b0d0f544af2d590c84da7e553657823c022448e39042428a22265fd94da5d6ffdde96465cda677d14b0","nonce":"1fe228841b560c8839c39d74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"4ac4dad4df62c2887b21d265548339baff6acb9243957d7df7f9f73a5e40a750c9bb6c5abd47bcefdb79994540","nonce":"1fe228841b560c8839c39d75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"cf96c720522de191945488bf0a940a19849b382a7b9f451fec84eed07649aa18cb1f48366b67be53ae7d1362a6","nonce":"1fe228841b560c8839c39d76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"0aeafbb3de7e0b70dbba7ede4781026301fcc1d3b6e4088f8e03ed33a80c8085ff558328cebfa5fed94b120af9","nonce":"1fe228841b560c8839c39d77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"c9082118ab192c2fa1cb8a562b6c3cb10415342b1f92dcdafc7ebad2baf3fdd3d34096e4f083b1be2f447ca365","nonce":"1fe228841b560c8839c39d78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"b09a2386ed6f1fe9054625b718e4f7e72e534ef22c2b8ce3e3f56e3d45409aba16c676f281fead1f8f12dfbbc6","nonce":"1fe228841b560c8839c39d79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"582fdbe6cec21ee8ce513c7460cf658aec90936181e3d6910aa746a28ce131dd13287b7e62082028a4d5e75e77","nonce":"1fe228841b560c8839c39d7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"cb5d2854ec7c4bd186c3095d6935f10125dfb0a349d7b13c9ff71f967651ba66d9f3418cfbedcbd664019c6e41","nonce":"1fe228841b560c8839c39d7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"c6a4db364012ab848a424a55909f3415614b93b81df3e020e8b5a60d57d376d63b638543543d54789e0075079c","nonce":"1fe228841b560c8839c39d7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"f26cedd04e79aaa13fd51341f06db65b50b93f6b8338af09e29814cc1372e08eb3f5205056f44c346df2ec3e4c","nonce":"1fe228841b560c8839c39d7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"73e3582835c012b4545a6a00baf2fd8acd2696ef2a628f9c4974bd5c32794128942d1c49294e8de0e573add248","nonce":"1fe228841b560c8839c39d7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"9b07e6cda924da1d2680e65cbf5d93b8a0accb4b2bb12577de2f63133a47eaf7c44776c60e6ee8ffe150e1bc30","nonce":"1fe228841b560c8839c39d7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"9f276f332c1749fab7e814980c3a4bf9b6bcbbfe9b2ed6b177dc4662f369dcac7d1637143f7778bf01f74bceb8","nonce":"1fe228841b560c8839c39d60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"cc88ef64fa4150cbfcd0f503aee72dfa0576e79d32f9ef5647808200fe14500bd4b1baa7b1f631ef05cf51c4e5","nonce":"1fe228841b560c8839c39d61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"1650493238741adb2434b7b05069148a6d1f41f2bc5604aa0d27cf207670556294428d227af266c1932f82c48e","nonce":"1fe228841b560c8839c39d62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"d21fb4e1f75e71a9ac01e8a17bd55ad2bfd038a36ac9d12e372fd4119295e2dc96899d665e220bdb0311146037","nonce":"1fe228841b560c8839c39d63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"fc3866d90b5558991970c5056105dd27e39b2edae5dd8166af21c6ba415eb5f1e1de7e5b00f90b7f08088b6c3c","nonce":"1fe228841b560c8839c39d64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"156ac95bb9a2a2b574215e98036c767b1332e375aafb8961324a63b6e7ea7cc94138548c337e54c451a879ba9c","nonce":"1fe228841b560c8839c39d65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"3d14cb0a8b01645c5d0083020c5c2a95d8e41dac52fca4d7e574c9c720756fed7934a37bbd005428c47941a956","nonce":"1fe228841b560c8839c39d66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"ae8f1c790df933aa67f7dbcc1e7e52a63c46df286b3ac07c20d7ff38c175041a825d33a6b380836c88beb98a0d","nonce":"1fe228841b560c8839c39d67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"bb760fe857bd9eceb906e1fbd4bf4160e7d2e708393ebac0d17e98fc2515b4f52e252d003a8186b28ebaf6de99","nonce":"1fe228841b560c8839c39d68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"3d7dd13cb789199f97c1cefb8c6615492cb1402499653259ff053b2c48de2f7704aa44b7190b0284033638a947","nonce":"1fe228841b560c8839c39d69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"4c545a63012c5cb89abc68315b78235766ab10ff8883d43c4f3df109d94c65bc42884c9e6e9aa5b778d4aca3ca","nonce":"1fe228841b560c8839c39d6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"f853aa6e181374fcd152ae98b2b552e8babd64472fae333d134ba04f69922d57ac75f31a0dcb33e5b3b227ee7b","nonce":"1fe228841b560c8839c39d6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"2d6520becd8572638b803467ea0602fff2e48fae388b52ac87d16626446b57bb2d7e9943b7837da41d8d747fc3","nonce":"1fe228841b560c8839c39d6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"53bbc707115a49a85cdd9a48e310ab5c969023df2fca59ee043a67bca193404620dfcfba37fceaaa78a93e972b","nonce":"1fe228841b560c8839c39d6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"74c3366a510693097c7e415e8636111dc61d86e8624fc4244520d782ac48eccef3ea6363411189734e4c2c5954","nonce":"1fe228841b560c8839c39d6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"63fd9f6e2f8e262aee2f42d81fa818b16a67b81b6fb0172f08f5114ecb29a896a804ec8788a7e7dc3f1812df3a","nonce":"1fe228841b560c8839c39d6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"d262d2ca9038e701a3042b61f66f2d53aca500a2edafb3d1adcced8e938eea3e7ecfcd534c2bc413e1380eff38","nonce":"1fe228841b560c8839c39d50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"b8393155486d4fd6156dd2b64c353570263f0e2c65a5fefb4553800268de467e61540162f3e4aa55ca503c3452","nonce":"1fe228841b560c8839c39d51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"f4e76e7275f7638bd1164cd540b089369ab2cb8a02eac079cb30521395f21aaa7a6a92dffcaf9099d162f0eb2c","nonce":"1fe228841b560c8839c39d52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"0ec73ca36eff1812fdf148e16e22eeacc74b9016e1fbd6b53262afb9d451a9730db167da246360818fc14cc2df","nonce":"1fe228841b560c8839c39d53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"257d9572703afb6da853b7a16cfb1500399b1e4138a3cac97cc10702244e9ed087815d17d9d27887dbc8a383ae","nonce":"1fe228841b560c8839c39d54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"1095e2837baef88f810c739247e4d7c00ce3b250d1bff9d99b38f9cccbd2b4cb18e62de9f6039104da0b2848d1","nonce":"1fe228841b560c8839c39d55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"69fad28f332b2d74d8204f3182e01c310d2241e4bc293010b66e9cfe10b48d9a8dc4e21a6de2dea5e00179a76d","nonce":"1fe228841b560c8839c39d56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"d173e02180a5c837e5a33537e4e15baefa1600717a99a778556d85f2dae1ce89c992f91523831db8fc8e016d22","nonce":"1fe228841b560c8839c39d57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"57c19602c84fc8d9ccae30733089e496c0b40fad7d583c877bd3183e46929ea410d27922adb9e98e0927d13995","nonce":"1fe228841b560c8839c39d58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"315dadfa0820cab0bf4875cb05288c50cbae2c53bbf584ad4cd880aecd89a69e3ce30ba6b84ab07490da16278e","nonce":"1fe228841b560c8839c39d59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"87e48b5156d11de7bfeb5d04fd0712b5c3eb64f15d42d8945488b7458d721ae379c1176746a0470edd3f60150e","nonce":"1fe228841b560c8839c39d5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"e2747fdc5cb29d23327e9cbe4d9e62198b7ef0252dc197b44f42ed97bc3ed5d073a85d38179dde4886aac11557","nonce":"1fe228841b560c8839c39d5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"667b0b8919adcfc215003a84eb26bfb8187d2d6e8e8d92cdafc883a4f45370c2f130d7f6f43c6314bebf7a38de","nonce":"1fe228841b560c8839c39d5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"ad98d67d06939f842478677fe5713f6930c26fecbb5f6aacaf7635f3f7c521393254fd02c55d9c178bdc4320e3","nonce":"1fe228841b560c8839c39d5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"f3bd8b93a0465d15b108393ebe1b8e8e8c95794c2b0bc0d3104871d1d22d2844c3ca1198d0ae3f610fa910e463","nonce":"1fe228841b560c8839c39d5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"da1ee382abb8536ba44d5e418d6c828b2f5392b8b1fc1935bbf4586af2ee42d1ae5ad9813e0537427712a2757e","nonce":"1fe228841b560c8839c39d5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"2f3773dc030d8c0240adbdc8d89ccbe6bd2653543e3d4a4a50b41ac357396c32c0e34ec36ed716404e5dda49ec","nonce":"1fe228841b560c8839c39d40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"b84c3f524658ab43b4ac6fd25e04a1b4c6f16f78b8ba54fdd43ba771f8edc77eb36b680fd67d2a6e15de20bd47","nonce":"1fe228841b560c8839c39d41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"7b5ee8faa120bdee2a73baba71c80f516dede99a5c3ef7f17fd8ad949953d5cda26e3fd47c9b9283a8aef514d2","nonce":"1fe228841b560c8839c39d42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"1182b7ca3f0f2cb79ae4abc3cb4e4e529c084f4dbfb10586e2ceed2d91da9b5141eb1763432d0a57b921b7a1f2","nonce":"1fe228841b560c8839c39d43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"33e726223601c95870c278ccb7c28204ca776c077e2f543e0b38a89d2528284b2d222f173ac48f232d96b0d8fd","nonce":"1fe228841b560c8839c39d44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"0da0ce680f0859bd85879e5d6f669d6a377d7619900501f0336d6247142b9a05b685713e01227f645722a5fc9e","nonce":"1fe228841b560c8839c39d45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"71635396cc1a4355a4d4b8507aeb7b0922e5743a362e72eb9fe58270537179c27e55926bb1314e91e425691a34","nonce":"1fe228841b560c8839c39d46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"a53cdc20061afe8eaf6cfdf615f3a7b14a9e13fe7cf25e9e9f0fe6c7b4be9639c43f8700f1521e509870b56130","nonce":"1fe228841b560c8839c39d47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"f91997cb7df380a342a3364fae4c30d4d54d00878c7648231aa2a742c16f66da27babd6a3ec705e2fdef54d7df","nonce":"1fe228841b560c8839c39d48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"1e7c49da647ec5e78474398cf9dfce3c09d699f923573548a71a6679627ff9630ae63b9f6564284d5246f59ce8","nonce":"1fe228841b560c8839c39d49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"34475ea407ac3ccbb23a60b06ed61c3e5db67cfad6a44eae4bb92b937a6dea844729d189a964e9763fb1ed0ac0","nonce":"1fe228841b560c8839c39d4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"8c37246ea00c6ffda3be28c562c28d70a67b4cbe88e26776fcb0c85261114da39c289d898413e11169f8a58e27","nonce":"1fe228841b560c8839c39d4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"5b33279c92033cda8a7bc4775af39560ce75c288bb209280f2bf6684c91ad341b26b4288a542ab725d150c920e","nonce":"1fe228841b560c8839c39d4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"0b1af20719fdedd5f84373d3af81c5b0efcac26e60d4c74a824e1cdd88997d338065308f9b2d9988d44e3bfcde","nonce":"1fe228841b560c8839c39d4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"ac726d5812bfb2ba79f39aba4b05108e9e347e784e38793ea7a7c1dd7e5369ee13a69392caa8c542d60e62fd22","nonce":"1fe228841b560c8839c39d4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"4142acd0d90350aaaafdcbbf7f2b7b3c08ebeba6e28c334673083999e47bdc7e5768edc13369d7df1de7c85e95","nonce":"1fe228841b560c8839c39d4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"5cd8a28fba07ff2eb4508661ec6e0f85b432a96352f59644401ecb4c271756ab4d32d7b258e20373c0d18c5ed2","nonce":"1fe228841b560c8839c39d30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"52b3471ca9e74418036b3d00d34f297e63f02b0c0b6ffeeb13f2f6d551dab5067599386035eca59a6532102a57","nonce":"1fe228841b560c8839c39d31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"1e771a567d5a300e41e5ac9ae03e1712bafdd2d0f714c08c94354a4d0b2b7b2051bd687a336a1c458a4431920d","nonce":"1fe228841b560c8839c39d32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"268cce590b12daadd3ac9a6d5d7eb7588a84848fea7209ba10f53b153dfb0ffe4d224f5e248a87353fbde41419","nonce":"1fe228841b560c8839c39d33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"3b756ed328831376119cf3170e24498c9068dbe4034d1915b66a2a65cbda33b4e9b52d201d4779d6442578c26a","nonce":"1fe228841b560c8839c39d34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"81da64c9cb66a9ce0f04b31bb77bc7d665114f3a1e111d4be76065bbea241aa5c79a0cdb597bbb5e9b38e7299a","nonce":"1fe228841b560c8839c39d35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"1959d5080b9fdf31bf30ae8655b124f2557ad8bf2cea6885ed1b5364feedfaadd903e0eb7be6497c7fb469a31f","nonce":"1fe228841b560c8839c39d36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"837e5b036ffbe4862fd09771a250bc96ec5f3f64fe0d3d456db24be1e5ed32a29ac50566d10e8ce95858a3f47a","nonce":"1fe228841b560c8839c39d37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"ef67972729967a44e2c330b67b9fe88fba31d6d2ef20a18d93fe02b2a7972d7c2518114fbf4a3247fe329c6468","nonce":"1fe228841b560c8839c39d38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"a2e0f07043043c4fc91a6075a4469c9a0f162ed2edfe455225c498c0b1a63157813b14d815ca4bd93b752e6a0f","nonce":"1fe228841b560c8839c39d39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"8f8ac2df5436d46ea39537a9cf2e128c450182d0c3436ef454edf6bdf9b3435d88625f30ca87aa413dd1d52a76","nonce":"1fe228841b560c8839c39d3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"0478cb2434702dbef44f15e0094043357172dd452abc2578dbd39cb1cd6b16c9d1e2207072c81a0fa40022c0b6","nonce":"1fe228841b560c8839c39d3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"688c564e4a749f9457826a5116de49f661469e2df70b78d3383acb283889e88e845a45039e7ee8773bfe6f3194","nonce":"1fe228841b560c8839c39d3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"b171db6149a307d2e96e860c2be1563a78e8a2cb447e2ef0f57b14cd05bb1884076138847fc8d9f0eb5b626ec0","nonce":"1fe228841b560c8839c39d3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"19f261eb27aa5927cfeed97e945e52bf35232c259b4b44cc6dbda2253b52b3ef2fcb43d5278d4bde4ce9ba0419","nonce":"1fe228841b560c8839c39d3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"0c5483bf74d5e8a1b667a0f1cc6617a881fe8c54b2a8c31913e1b6724a97d91c8f771fbba4a10db0d780a37ffd","nonce":"1fe228841b560c8839c39d3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"7d6cfd3549f1d37f722a0d392177c3451db1e4f5246a5ec7e9353cd7c94a5e0c94e67dbe6d977875d881664655","nonce":"1fe228841b560c8839c39d20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"a17a78edec4f43662f36493cf6f63d05076964fc0ef399a2ebae118fe821a9bafa91a38f25da288714a7c3948b","nonce":"1fe228841b560c8839c39d21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"430806e0457b27649da676b972f2aa6c43bb41c574cb4e95e4d96cdc3296e2ca94799516e0d3d25f84a262e228","nonce":"1fe228841b560c8839c39d22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"1d359ac20528e207ab4f67d6edb8f6d7d3bbc2343a7bd28f40bf1ec86c3ed8474a535204e520f437afc49598c7","nonce":"1fe228841b560c8839c39d23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"a5278d201189633ac5c9575c722be28c18322542c9914425dd8e54cf774a3614fba7de03f0ef77d02f813a96cc","nonce":"1fe228841b560c8839c39d24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"c690085a20c9500b1137f24aadbcad8be6d153ed30f81b9dd06c133e58bc7d10d99f16d18e00397991d7bbfd35","nonce":"1fe228841b560c8839c39d25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"01528b332a7264b69f5da1c24ae06b3de5f57ebd47eb282b914b1040747bef5bd31688d2f6c7637229d3668384","nonce":"1fe228841b560c8839c39d26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"8554784e8dd2e06e550e688fdcb10e696ddd0eef80430ef1d6de372322d6514e6d76b3e80ddd45028b7ea4ae05","nonce":"1fe228841b560c8839c39d27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"ff5fb428574dd39f2affb6fccd8e8c5f233516e9b172e3a32b8bd522c5b01d1cabb883f5df2d009e996c151ddb","nonce":"1fe228841b560c8839c39d28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"a9ebb82eada476fc431923932e1d480bbc2ff36ff753288f87cdefeff6fd4e9ee0a7fc0dce1c86ad1d83c22e7e","nonce":"1fe228841b560c8839c39d29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"a045b9cce07e9d23e883ffe9a16544996fd9fd6e12c6a008a8d0600a28a399def0532deb11c3559935fa5cc637","nonce":"1fe228841b560c8839c39d2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"1f5eefe21224c05ce3a2b8fb1f1516f2b466f1f5f2b11b476743dac34e0a338a8f9a1ae907e9863a2fa009c431","nonce":"1fe228841b560c8839c39d2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"f7217b71b1a6732d253e4709ee0f8d60594c1017c9941a215936b7a674e055224353e80f3f1f96de511f769a15","nonce":"1fe228841b560c8839c39d2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"c0ab01d5fc7e617f368b97307efd9628bd337500a77240b390e62e160f886bd6dd1d85a50dbda3305172c22386","nonce":"1fe228841b560c8839c39d2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"ec0617a7ee6c38da6a9e2e47e5c25bcfd1f61bb2e25b6acc0bdad14fd9c4c520c931ab989f44886408a5988a5b","nonce":"1fe228841b560c8839c39d2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"ea8ef5cd6153d891d3dc074dcac018a898e451c87c7a0ea56fe8a442b56fbf7310e1c639973f70bdf248a4a516","nonce":"1fe228841b560c8839c39d2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"d932fb2d37e8e19f28d56678e0b6547f0a6c4df189dd9088f0dbe3abee34d3b2c88e23e0325c35efb6742ea8d6","nonce":"1fe228841b560c8839c39d10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"ccb2cccb66a2c5101e6e557234fe66197277eafd889dc195ccff02314c2c2d3812d0939c35662800a673e54403","nonce":"1fe228841b560c8839c39d11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"3ece0e13c77b9b99759227cfbdbae67ca13a31c9ae111af5adf899d325d443e625ae662e0baaff23de99582a67","nonce":"1fe228841b560c8839c39d12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"d88e4944b8738a610dc9d3c57d90b3fd22e16e4ad7626bcd351b21020a8712046a1430931e68d61937b1256027","nonce":"1fe228841b560c8839c39d13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"da8e9691dde5ac55e135e6a3466b8eff5b0940f5bbecf05dcbdf18a5ad15bcc16e78da37d192cc9adf8d7ab792","nonce":"1fe228841b560c8839c39d14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"a55c8e76a4ec6e2bdd2b8d06599b555ea68669ef05921a583a5471624427865eee63a118dba3f282bfab1015fb","nonce":"1fe228841b560c8839c39d15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"4ca12f53b919df24341fede9fcc0da8aa325b6ad9ad1d7d572020d7e1d6bb3af8939bac6732fc1f6d52211062e","nonce":"1fe228841b560c8839c39d16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"d9290bfa125c0009d3945e941d65f5e46d766286df8951b7f4bdf3afc9bac5f3c0ceb57c23056a8c5404078838","nonce":"1fe228841b560c8839c39d17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"cee3191e5fe38c22c4b4b07f0d92337e8c8f0ce210856617d9e20d2a6dcf1257e7db5d69610b768cd95a822f3f","nonce":"1fe228841b560c8839c39d18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"fe4376abaf096c00637796c2e1aa39374f8ba23a7a8b0f1781b1d203f36e4e9ec25c31b1b4cb68c68c5c7fe862","nonce":"1fe228841b560c8839c39d19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"32109ae8b30e2759a9821734b8b42f2912780a69e45a7edbe6419a8686c825c734467aa8ee570fb1bbcc5a426e","nonce":"1fe228841b560c8839c39d1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"f327ea64110ac2695ca3f3d1752370dcb1e995148ae03c89679f599b30da5b3d373a5d0ff617d7c6cbca32a91b","nonce":"1fe228841b560c8839c39d1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"40949c36570bdf70d7aab728ffa1576dca0960069e99e4f7e1355db3efc3f076a1ef9c579020eebdc28a8b5aa3","nonce":"1fe228841b560c8839c39d1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"625febc52fd9f44786bd666180c7df40654a4661e7bc8c0c4b060003f69ba309e1038253048a54d01dff87ce30","nonce":"1fe228841b560c8839c39d1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"d348003934f870526c28cf4fe039afef3da1e4de8f13a48b7ac5ee1c1b90911671441751dc29b0e098947244c9","nonce":"1fe228841b560c8839c39d1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"ca0af9b9ba7fa58b6c154d8e63247336a25a2f80c496a8d030f96dfcba484e1f5de30eba06d6804ac4f8d7c0d3","nonce":"1fe228841b560c8839c39d1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"e6cda1069ccfff6241993288ad3bebb87bb44dfc7b54753057482d2d884d3162208094fda54447352ef5fb7312","nonce":"1fe228841b560c8839c39d00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"55c3216a647b1c9597417378d62dab09d190c6b7d57cce1bda7e80fab0409dd21ed3fa595fb386230afee180c2","nonce":"1fe228841b560c8839c39d01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"eabcd7ca03009ff7fdcd85bd83b93514a22e24af26ce68d33b54697b48124b792df291b4a1b08b7417a2dc9f26","nonce":"1fe228841b560c8839c39d02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"cb79f5ba85c98c532903b6626bd4cbee4a4affb029f1019c4f7fa07dcdae92d97a1e826b45cec1f0721154acc7","nonce":"1fe228841b560c8839c39d03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"559f58002e9795a442a948244673e78f8b647dda92e82392304e0eeb3c30fbfbb89c493b18c2e8d8fa5d8cb985","nonce":"1fe228841b560c8839c39d04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"7324acd5f3d7bcf34aa77a4e0494cb00061b63ec9bcf6e3fe2d007b5a84b0b3da2655a7292d053ba87e4ff3e91","nonce":"1fe228841b560c8839c39d05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"b357923e5c870287c3b9a5cd391c0d580849823211d951488f3326dadf604fdd3eae68613f8f5b24e82068885e","nonce":"1fe228841b560c8839c39d06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"e831872750c5babeab3bb583b7d71c0a8470af38077e436467b637621ae5986de6e43a51e5a15f958c93b559bf","nonce":"1fe228841b560c8839c39d07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"1d5038abdfbfda60691b1d3e575d1e4b48329c2e9e11136c819b411b8b4d9e921e47d7d1e7d45101ad477d52f6","nonce":"1fe228841b560c8839c39d08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"cb709ba9dd9e6f64e08f46f3246f50c6115162e7727173357dfd87d0b2f275883bd637c56371aa9fd47724ed80","nonce":"1fe228841b560c8839c39d09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"2b42ab206c2188a666f5503fd84cb0ea6fabc73f2218e422138347b4b9177e44c00ea2419f7c0b2f7720e87114","nonce":"1fe228841b560c8839c39d0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"6b106f1098e0bd0a59fbae12b588200a6d8d6c9058da031e6cae97d38e76c07f259024f9d56b9a1f69f8732d05","nonce":"1fe228841b560c8839c39d0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"5e45f42898046715ce979ece1bfa41bb09c2154f1a31685a8d8cf4aaa5b2f4bebe951b22151e2d5ad3acf62896","nonce":"1fe228841b560c8839c39d0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"f1f4f5e4caebb6830cfef810377d7411c713f3dd4720189834a811e7f8e8eb59d3695ccf3aaabda1e5b183d4b9","nonce":"1fe228841b560c8839c39d0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"47f33adcce5b230af2183eb660a2ade7085c769008ac3cc3c7dfaa59e278aa05b47529e77c5ea7ffb08777b6cf","nonce":"1fe228841b560c8839c39d0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"b796aab468bb8e304747190ee3956e4b5aa92237eb4bb90ec898d4e5a571529169438a8328815bd53ebd12b2e9","nonce":"1fe228841b560c8839c39d0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"47de8fb5e1f22cf825e3ad275ac6e730d21e8fed5f66bca03957f7777466291e345227493030842a3aa9cd15e8","nonce":"1fe228841b560c8839c39df0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"f71588ba9a837d38c8b4ac0d3d813363e01a125f287b6813b1d27b61a4463a1457417b75ef2ab21e04f19d64be","nonce":"1fe228841b560c8839c39df1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"730022dc6657ea9be871539c0171d679783e85ea355d954b5e721a139973b1145a4385a047042ed020c962aa8d","nonce":"1fe228841b560c8839c39df2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"2b774eb93e9401f34310654f97f1ddaedf27b67bc7fc3c8d7a1d026373ea522d135c2e00462c16e6d57a14ece5","nonce":"1fe228841b560c8839c39df3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"bb6cd1b3c0811975c9ac1c18b2533281d97840b847d3c38f9447116e730c3514bd239b3629cf90b4233392d24b","nonce":"1fe228841b560c8839c39df4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"3d6d1e8e0d17cd0c6d5a8daa1f6085fdba189577a59a0ffc86ec05d4771e158e03de9501043f3f63537ed6fd0b","nonce":"1fe228841b560c8839c39df5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"26492b8d08d3e8cff1a3e7b0655ffda498d04afa7a5a6bc415635730db54423df11eb4f6aa5f62aee2212512bd","nonce":"1fe228841b560c8839c39df6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"736b270433cce17b77e0279fbd31fcfeb0d4c3394b6e5d00089216012b398b60b8ca2d907e385e88eecab37439","nonce":"1fe228841b560c8839c39df7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"66943dc863553b86b7a007bb5a59276d85daecb9966690cce07966e2267bb47edee640af2dc2f3264611a0fffd","nonce":"1fe228841b560c8839c39df8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"a79c3bd2dc4a9119cd359542f93297536e8ca588f21957b34cff52bc95208fc307d31279afcfd47a22a1e7706f","nonce":"1fe228841b560c8839c39df9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"1fe1d2244c24c5f7e897922645250dbb8008d311c4ea9d3baebb8715101b9e49b45258c4f43bce621375c3ff2d","nonce":"1fe228841b560c8839c39dfa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"05497772be53fc4140a6bd16e2c25719bb9083827154a94cf773bcd0a63edb36bbf8956af570adb062ef491579","nonce":"1fe228841b560c8839c39dfb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"56120c7dc49d7c6a5bcaf97045f61b4fead58f8e07c875c7b1446d2e2f847e6d9a231abf49bca660c72a75e127","nonce":"1fe228841b560c8839c39dfc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"39ba3deb34643fcb56617f67e56d1101879e8a55c7a5f1c9d0cd467d0f69a171c2dc22b651839ec921ead7e3f4","nonce":"1fe228841b560c8839c39dfd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"5f2f6e1684703aab1782ae0b34072e924c0bbfb4b175030d97cb00b2b87a35a58132e8bab52d5a8922b2e18a15","nonce":"1fe228841b560c8839c39dfe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"79cbbb9bec59c925f139e04405b87fe3d03d672a46a31b6b8efe9efdf5e7e5ffd24a64dd300e930581e02e2c43","nonce":"1fe228841b560c8839c39dff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"c68a44ff1d7d1c3ce2f432370350ece61f4afd0c8d11373dfa2072997b285144a887385e8cc81b018f74ade2e1","nonce":"1fe228841b560c8839c39de0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"62f721d2e89f2c2f7ff655e515a77cfb0b0dd53a94ef4ab5378549a3dbe7ee084746198d011dbd84a803b5637d","nonce":"1fe228841b560c8839c39de1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"07b9d76f66f3dc0c4f1f6ef1c69e825b24e4002e380331886090d0335876549276b3820ef4b1dc87a77de935c6","nonce":"1fe228841b560c8839c39de2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"d17d7212da006dfe4971f7e103a7a733e5de351cd6e3427843f4cde5190a8286b081f46514d8ac6de7c4c1bf25","nonce":"1fe228841b560c8839c39de3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"d4802ecda881639e1a3c24b12aa846c7efe124a78ee2568e0cd2e1959bc12d901987b51835855371c5b20c1d40","nonce":"1fe228841b560c8839c39de4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"3c03705d9f9e550d6162803c91100cb44fa262aff50b655e8c23420b1e3a4df69f9c015dce43f6d484d52ea9f0","nonce":"1fe228841b560c8839c39de5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"01f9328332465d8cbfbd09c1dfa5f11e303cc9a0d6e69db8e2bb89359ae91dad1a47eb76907941e465b4d2b7a8","nonce":"1fe228841b560c8839c39de6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"c3ed0d39522fc866864e68aaf32c32d5a108d8caed6e45fcfa3eae64626e17e664354f5f9670377e03d5424b43","nonce":"1fe228841b560c8839c39de7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"6f3cde2ddd9ae4fd74492045b0d27596af9455aaafad26614aebd03a339ce7874e36db16d2afb79ede4ac861ef","nonce":"1fe228841b560c8839c39de8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"938ff0c395c02004b6dca9f6bf14f720f1b2994fa2a952a1d97658dc9f3eab489b4ea2b8b17a772dd0e1f844e5","nonce":"1fe228841b560c8839c39de9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"9006a0f0d0b9a39d387f89bda4f72bb84f8fbefcaf4a933be11da0f041c21383dab8a8e6d9aa70f7ba2ba804ce","nonce":"1fe228841b560c8839c39dea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"d7f947b07a4b52a9ea7f361159ac7ae3784964dfee7bf6d058bd0acfb4997f815a41a8781a50aceb8ab4fe79b4","nonce":"1fe228841b560c8839c39deb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"1205738e792b9dc610429238eec46b2318919901e1f5dc5db342160bf1ae26feffe01f14977ab56bec67d79a66","nonce":"1fe228841b560c8839c39dec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"4f5491ca161a6c758d47efa722c4e74d9e053990ef79b20740e0e2d5e7c87b3d9157bbe915ee42ab050524e330","nonce":"1fe228841b560c8839c39ded","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"ef243f4f134b0fd749ab22e59d34f915511eef9da6cc9b10b5299d36629b62dc0eea0418661bc0699d9084c494","nonce":"1fe228841b560c8839c39dee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"7043ad794621b945a32ab30dbdad99a982c0ed2091f4f6c8306b749926a6821672b8ed8c88d3aec6463479bc4f","nonce":"1fe228841b560c8839c39def","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"2cf01051b662b461390db4e1174d13d104d1eaec1bc56cd6c30f9c452fb57700a73c26ce11e373a10871407030","nonce":"1fe228841b560c8839c39dd0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"b7a8ab4d2cf607899ed1dafadcc13d52819c7108425709890f160129760cd33bdd7d94edc6f0f23247a5843505","nonce":"1fe228841b560c8839c39dd1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"59cacd8cf9e1caf6cf2f5d3a7513748a96133a63d110bc80e82af5b2f20168999077ea00ff65ab2b9be254fccb","nonce":"1fe228841b560c8839c39dd2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"5e2129a9f420aeb60e000a1a91e9398a4b09649c4356cb4fad0fd319e32c7847148721f8aa975db45cdd2d68b0","nonce":"1fe228841b560c8839c39dd3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"a10d305b36d9483a950d3d345f5ffbdd7bcb51b873194919a961d20bdbb847b854f5ef084e8b9b33b39feb0ff7","nonce":"1fe228841b560c8839c39dd4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"d21ad93f690808277c18db7b0bfd94e229917850d1b38380d7b6848279e6042cda47c84cab9574f9ff21c9e0cc","nonce":"1fe228841b560c8839c39dd5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"6d800ae885f0c8113f3b0108911f011bce8fd5ee0bd377df6291e33325b136647d63fbf6c1500d2a386ac497a8","nonce":"1fe228841b560c8839c39dd6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"34bf34936d7ea1db143a9450a41faf11e3c9b1d8fe85480b832462da6231bd10f19fc46c25237e9a5f3108916a","nonce":"1fe228841b560c8839c39dd7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"99220223e61f24f5947ace08c1b2ed7989f76c3fa97748e732510d5b8ea50dc247cfe16b5f2c6bb153b3d4989f","nonce":"1fe228841b560c8839c39dd8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"c1cd2ae3cfdeb2b6e8c11f96372373c426939e8ea7c51beed86e4fe869d5588619b3560d50051ef9dfc47c9783","nonce":"1fe228841b560c8839c39dd9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"7d2f8da23ffee63ef83e71c773bd6eb3e6e7c093420e56d887a60a2460977fba2ae78bfaff4e4b61b2bc2e2222","nonce":"1fe228841b560c8839c39dda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"1e490b00ae67fc44288ec1b2b586fb509b9090cb5a7ee4f2ac899c28541070a9e49c0d5225f7698894c0dbe807","nonce":"1fe228841b560c8839c39ddb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"be088ff416c9d799b1b8475c1b999714c8c978afdb64338e54c1f6319c2ce2d0538c2aae9b15e4f7b180bf68af","nonce":"1fe228841b560c8839c39ddc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"050752f045a889403c4877df86a2c5f51bf38e6b9e923fde8eecad00e3e214c9007abcf48742270da5e9be2bf2","nonce":"1fe228841b560c8839c39ddd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"a2b4e347157b6c9f953ace22be075f8f76a818fc0a0321214d2915417f8fafcd17d4403fbbf4071d073ade9a8a","nonce":"1fe228841b560c8839c39dde","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"59037f704dade193e5b1f821e94479ee373582185757a982e9c0c13ff76cc122fc3ece3318ad7d01b451ecee06","nonce":"1fe228841b560c8839c39ddf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"bb62fab1467bb33ee52782d58838ef628bdc8f1c6131ba6c71daad135ac6e5627f7f9604c077ad0ea5ebd90510","nonce":"1fe228841b560c8839c39dc0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"f0651878cc9fc83b044f660c0030c13f7ddfff6c7d41202831e939cc0c57f3837d922d9c915f4deb16e29bbded","nonce":"1fe228841b560c8839c39dc1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"88ffa772d343dd83eb74eff1676cce037277910a0fd23dbb34a174de4ee4acf7b61d40a7a0de2dbda2fefe8e1e","nonce":"1fe228841b560c8839c39dc2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"4592e3b0c2b2d3d654d7494664f091f0f6d4c249f348f46d38931c1fa3274baa3b45e632d5ea6bfc8fadfd17f0","nonce":"1fe228841b560c8839c39dc3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"d1c0e353e31bd49acef6c8d21897f08f59818e21f95877f7af438b7e64b3cd29b4a900e286a57ffe3f41d27797","nonce":"1fe228841b560c8839c39dc4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"5587b7a8ff780df6b292e0a487c8c3120dda38d4df024049fd57c9cb1f231c70fe531b7f9ce8601c75a2f70c55","nonce":"1fe228841b560c8839c39dc5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"cf5564746f76854485e56690c9c26044effbdd3dc8c4edfa27091b1209d38288589450ac0d2f3e52623549dc54","nonce":"1fe228841b560c8839c39dc6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"609ff4134f314445d97c402664965d4201c454d1f4df1553ba2ae8416f8988d4f7747baf0d2495e1048f1dea31","nonce":"1fe228841b560c8839c39dc7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"ff5529e4995109e8a48c3537136ad5b956cb69f6b9aad71dd1a8ba6298ab017894e18e5ce30645fa9258103f8d","nonce":"1fe228841b560c8839c39dc8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"26253610b5ccadff0d6ecc79e2dca05f96ea2deeceeb8b77f5209f57aa357df80fbc5472ed082c34b87fd8034f","nonce":"1fe228841b560c8839c39dc9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"7699f3661b2fe249479250cc2310e9ede915527c2d09aa963dfe3ef73577d7f68a81a517cdd66f25eba38537b0","nonce":"1fe228841b560c8839c39dca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"f25cbf762b1e8025a68000b63315b1cf6d7f8dab2f42c11f99660daefb289927c5792d3a4f32f59c4816251c0a","nonce":"1fe228841b560c8839c39dcb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"c7484e3dbbda376759bc1dffc8eef2f95256c38f6129c795c7c6e10f41a9eca26d05707027898e0adb5fd2895d","nonce":"1fe228841b560c8839c39dcc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"36402c8ba55d95a44c32c40ce82c85bc36829c4a7692749cf3a98d2ce3590d80fafabd3a611a46afc9a44ac243","nonce":"1fe228841b560c8839c39dcd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"65fa73eb861a2181800529f0cbd0b23e8352727521853863526510b85e5dfcb4e4d9500919929433371912fd6b","nonce":"1fe228841b560c8839c39dce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"429bcb15ca9484b0c44148607726728b423457713f99304a763f95b944ac4974b3804f72e1b4adeee3585b3340","nonce":"1fe228841b560c8839c39dcf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"7ee18770c786eddf5953f04d180104e3b7f709708b29c294e7ebec3c2cdbb13f8f20f9c1ac77c40404a245bf4c","nonce":"1fe228841b560c8839c39db0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"d29b97b358753af15a174268ddf91d4cd77b1c3baa842dfb48d8dc77082682cf845a48096bbf4ec9fa9cf4100a","nonce":"1fe228841b560c8839c39db1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"841073bcf116e59b19fecb98aa2ff91d4d3b56707e60df9f2ce3e195c179ea1b2a4d9f7a95d995a5e1d1c64afa","nonce":"1fe228841b560c8839c39db2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"da96df2a072cb930698c938a135e23bfb489e5da1f42d7d58823fa3d0ce8425b78cc3a8c4cc8249f9cb43bafc1","nonce":"1fe228841b560c8839c39db3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"696e4a206ad5fdbc00fb96c3b7886e2e7a876fe61f21b8c649b6f592bfa43b37b4b16f10821f9ee47a031a4059","nonce":"1fe228841b560c8839c39db4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"7a8f4221e8165f3737b4afdeb96a37f6de70cfbbb982639fdaabe604fdbcaf53f695bb78b0358094778086a2a0","nonce":"1fe228841b560c8839c39db5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"f7d2aa3f299367dc2d3a27bc743a5686785fcf56bb8312d04a9a98ae8fa68f22b8442076c2b0765c10728bfb25","nonce":"1fe228841b560c8839c39db6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"9cf1fcd1375abfc09740316d67fd599ae846cc3054f5ce69a0429f0f2caeaa7e50b747f2871dde5e3befafaa37","nonce":"1fe228841b560c8839c39db7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"9a7dead0a157976d72611ade669e5c37af51d42fb32883b3549e8bdff07f72164accce1ee2808095d70c7b71ad","nonce":"1fe228841b560c8839c39db8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"e3ada8515c2a22c9a2ecaf01d0893f09f01734d53507b9f842e7f8674b82a4bf0003f592650b4e364cbd561775","nonce":"1fe228841b560c8839c39db9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"9d0c80b997ba5073bc247e2e79c2bfe20467ed4f81ed4f602684e9b6abcc74a4f70ebc8c43cf180d04342b3d4d","nonce":"1fe228841b560c8839c39dba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"f4467d746b79f0e749c4d73caafa71353eb23f098a663fa5536b3453d4664cea99b994ddac1336eb68293ee0a5","nonce":"1fe228841b560c8839c39dbb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"17b94f45acd084c7d2d12f628f2d99bbe6670e2499d6bfbc695dc11a5568f047b85de365d1a6942ef0d8e17334","nonce":"1fe228841b560c8839c39dbc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"bffd97270752ff25fa76f961ab5a3f31c94da9309d52d417b10cda585e5b41f2a45ba229a5fdfc2b525acebb68","nonce":"1fe228841b560c8839c39dbd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"69c4d0eba2343c9055797e9c4c67ffd07d14806fd11de3994395bada3f50746ac8f50ba7834ccf9c54535d4f4d","nonce":"1fe228841b560c8839c39dbe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"a937dd4d325eb643e88cbe7ee1fe47e7674194b820ede89d1dcb6aeb973bfb753e51634b21bfe99ed71e83be12","nonce":"1fe228841b560c8839c39dbf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"9d8e39e1c23e8524152a6310aa8f4849d5c7f6651a0ab7bec00b1217a11e1c88ee5d4e5d2ccce1f224ec17ba0b","nonce":"1fe228841b560c8839c39da0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"9dafacf592d130b951c0995fb08fbd7fccea8d0629386e20e974db7287b12355e570ce175760d8acc4934c13e5","nonce":"1fe228841b560c8839c39da1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"6fe3bfb696eaac9a9eab3cbdd02424ca1778ef99dfbd0c8b57be703c419f537f161f91e3507f08e4ad2a457c4e","nonce":"1fe228841b560c8839c39da2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"399f5279be6bade0b18b78cb2669db27ebb61fc372355b8a31fd006f628cff6663f016ff993e8a694a13cb2b8d","nonce":"1fe228841b560c8839c39da3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"f6fafee72d47100071ed9e58c8278070405afebf9fad1dea21af73aa94157da62c3acbabc0208875df6a0c0e86","nonce":"1fe228841b560c8839c39da4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"8265395054a6d4c12a0633491cf547fe16d27e0d5b54cf512d2fefdcb1383f4ebe08b1146146267a729cdfb077","nonce":"1fe228841b560c8839c39da5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"586f126f94ecc848d7cbe9bb5f237182a765745d3cff9d19a4d65172a1eaeb32918a52a5d0b149eed86a256e37","nonce":"1fe228841b560c8839c39da6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"272a89ef199fe48ab034aaed86906f9c359ff008a480d9cd673bdad3c6c0d44ca148ecb5ac02217320e2028e97","nonce":"1fe228841b560c8839c39da7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"74799094665113df65306982c684260e90688617330583693f9a99f9a36f11b3edb8005b3c35ab809af8c8657b","nonce":"1fe228841b560c8839c39da8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"e1ea47f46805c1d50b780e826c90b5c1983a1d7299f374a4c9ca8241163d3360fa73c17f62c682673eec6a4a5e","nonce":"1fe228841b560c8839c39da9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"a6ec66b4773c2723e2d1d494b42d98dd4a78bc618517ea926fd58b8a353cb7c0421f52fb92fc492de91f3d99f9","nonce":"1fe228841b560c8839c39daa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"b4c407301949f9c910bdd77bbc28267c589e563e28d8c86550a05df17ea64a960b964c6eb4531da379bbbdbdff","nonce":"1fe228841b560c8839c39dab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"c6ffee754378747f330a2a6d54de6d44799017d6ce11fe40c79ba42bb60db6325e4db98960ba72b5276a5b2bf4","nonce":"1fe228841b560c8839c39dac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"9d1d788e6d8ef16623a54bd097ef70b7ea266f3831d2edbd681a4b99066034f5b17b944b96f76647292b9367cf","nonce":"1fe228841b560c8839c39dad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"bd1581419bea4c1e2556e615036e2a4e6629693fbad9d124be077e9c2bc47699fadf586085cc12115d99ed6f75","nonce":"1fe228841b560c8839c39dae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"a3646f04f66ec45a8a0ae1f06b0181c6d1bed9c213282f8b0c80666fd74423ae287a7cee101c520939a97de9c6","nonce":"1fe228841b560c8839c39daf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"a8df535c9df4ee1a5243f8079702c82280bc6f877a76c98150adf305fa4a73d52d6eea687f1bb0af96226ab31e","nonce":"1fe228841b560c8839c39d90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"c50166da13827d13f6293220184cb9d84c0dc9fcce9ed2f56b8ce4453ef9b0bcc09f3555f6f5f684823958721a","nonce":"1fe228841b560c8839c39d91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"7a195dd776a0d7096bcf2f0f1bb23443632dad1605e098e77fbf1e7b5b24d80fdf3e6d69ae9709bf3d8a2ea5c5","nonce":"1fe228841b560c8839c39d92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"632e0cafe5b16754de41c1849fd049dfde42f0f056095aa9a49c20fec165117d28867f852f6fa71bceb46f92e5","nonce":"1fe228841b560c8839c39d93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"e62d328dc98c1b31177fae9d8412c7ea9f7486be9ac66a8c8ac98590190d5503e6cf87209f82bfe3a52e318452","nonce":"1fe228841b560c8839c39d94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"393c6b7298b2860950d4a2a27ef14af38bfb8ea43e8827f56d80d293c664b07bd5c8d09079e1a0aa41feeaa500","nonce":"1fe228841b560c8839c39d95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"d2dd290db74691a724186890d9ed3dbf21a124423803558d0d5070c1dc1ffc546b46e09c76b5a288420e21c7d2","nonce":"1fe228841b560c8839c39d96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"e96c4f46c921cb2650fb976602be2b7711ef364c389e14be3e304978c5bb82610e48fd21135109b66fa1e6b18c","nonce":"1fe228841b560c8839c39d97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"20ba5df3f49803f2cab6e650700fad5f997a3fd7559e5dcdf3863d89babdb0f84b1f649a088df5540ed29b9a87","nonce":"1fe228841b560c8839c39d98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"605e35219ec2278bc26459d9c2ac6751ec52a9e65ec50ec32c05b7f0631d2ae443816507896b30f4ffae9a96c7","nonce":"1fe228841b560c8839c39d99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"c7e5f305e125911eaf711bff7e6f78bbeaddcfa9787566a0517c88ccdb59c0a67d04ed4f03d7a6d7544af877ec","nonce":"1fe228841b560c8839c39d9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"15a73b7b044b3136c2c0b8e67752fecb114b983c4a34f9a14c03dd4e2145b35216c5162b63a8603246cbb126a2","nonce":"1fe228841b560c8839c39d9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"aedd377e9d27d2ed2f43cdd14000f9f22b6d5f2e976d4bdddcb64b8f4e70de1593b8e60b9e54f788886935b645","nonce":"1fe228841b560c8839c39d9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"95a316bb7024f39a20557c45eaf323e3aa211a2c3dce2c698ad4108836f7bd3b412837920c3e0bb9973fe2363f","nonce":"1fe228841b560c8839c39d9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"21a47343954bd81f8008bbc75ad00edc3e345f63dcf274c512d44afb4e7bd46da24149c806751fcfe12b530f89","nonce":"1fe228841b560c8839c39d9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"c5aae28f96dfa84574bf40597bedf0cd381729fd17c575b3727cbf5816b954885017f52a6e9a4f59f2211406b4","nonce":"1fe228841b560c8839c39d9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"9578b2d207806b3eb35944f682c479b09a9b4cda03c6d07d16b8f207744b037440b39383b8193b25f5a307a048","nonce":"1fe228841b560c8839c39d80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"980f74adc475e75196ad9802843a95e9a94a07cd6ef0b62c8f83f013e637a613c72f6b3429d2768aeca1684fa9","nonce":"1fe228841b560c8839c39d81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"04802d4d807565e3dcb273b400fe8c4661dbbe7a4222808eec4514938dd14cedfb67efb48515cadb0eb606904a","nonce":"1fe228841b560c8839c39d82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"517e2bcc8f8b75768d181e1aabeb1d88d3f07ae5401b3c90abdc05f5b33ef14bbb1235741f0fe7afa65585e85c","nonce":"1fe228841b560c8839c39d83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"4ed65675b235cb60fd126bb587802db76f115807d84b8bc82d73a4671d28d314fa87258396f4af48ddef7750d4","nonce":"1fe228841b560c8839c39d84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"3272dad370673643e853974e5867c601dade392b80faf997671aa904428a59bfe72738e81580015fda8e3dcec8","nonce":"1fe228841b560c8839c39d85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"d8367ffe39ed63fc1d4bc27e3d62170b11cf7a7150f5863f8ee39fc760a92e0ce7172d682e835e0ab529e6fef4","nonce":"1fe228841b560c8839c39d86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"ed87a4b270b09a63543d77fc741c0e66d2497aaac1a02d15e7f90d1357dfe5021f26e04b7561818a258583f34e","nonce":"1fe228841b560c8839c39d87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"c8201bea259a224812977f74ed261a25fd083d297c4ac25fc0dc89da0c39bbe460b29e1feb21538fa8aec16502","nonce":"1fe228841b560c8839c39d88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"daaab0979fe073b4bef35b943361482fb050409dcca22fdf220d5a57a73cd2cac27e2f6c92aa929a5f5003bd73","nonce":"1fe228841b560c8839c39d89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"43be992b690e5b44a2510c5b316149a2ba48361a5383150d702bf3e99b71ac0c7c7b23418c3c74084af86a3f61","nonce":"1fe228841b560c8839c39d8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"c1ed9d19ea909dee0ae89f95be3e5ce71edb189129c3e571294019f292ac6d576bfa672eed7ce79cd3b7f84a0f","nonce":"1fe228841b560c8839c39d8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"4ef34a097f2dfc47431f7fcc18fff2a64e7a38f28657fe6a1fe599f857c3779af8ea37607b420c99780963816b","nonce":"1fe228841b560c8839c39d8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"d0ca44ddafd9d3d2f798cea2b9a6afe2eda14691b91aa60ad3b5988ccf92673b4fc2f51a6ce333af5d2dad51e2","nonce":"1fe228841b560c8839c39d8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"40c0732b0d65b4c0314cb8e546d763becb518d6ed9791414f73c07227814effb4545ef076cad1ea6a7126fb07b","nonce":"1fe228841b560c8839c39d8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"3d6eed809bb4b80fbfacdf1ec49c2ef86d9402fb8a9cce8a0832cff0e05d47224709a4e2240f8b599e22103d7c","nonce":"1fe228841b560c8839c39d8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"c69dffcfa3313e46861041b48e55fa292f61bb02976eba9466ae307a193a251b4cd9556016e82ddbe3790ead39","nonce":"1fe228841b560c8839c39c70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"ebd1422c0516ad65e0037b4dd4d5010ad2e14423ff01749b1bf7c98889bc0559"},{"exporter_context":"00","L":32,"exported_value":"4e3e9002737117953468c7736063f3987ed54b8d64c2a4ab7844fe4529dbf4d6"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"002ff289d5dfd0a066bbb7c215c7ffa2d6890a264d6445efb0742a954caf60fa"}]},{"mode":3,"kem_id":32,"kdf_id":3,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"9253b0e11c4639e083f53536da5f36a5386b58bdfb2030006a5e66765a8fd251","ikmS":"7fc36b20172a915227a300b87dc62e30b8c7a642d5103ca383f9d34d5bd7b944","ikmE":"398a7622842becaa5132d04a0a7a001be4b4a07d8a479ae576262ef24f08491f","skRm":"4c7ec9a485f1aeb64c13ad41b139efe81587a4be665251904a1cadcb0f82729d","skSm":"9ec86b6e711b7085cc0bc561cee47857012ba2d48184dc15f23e3d0cb0ffca64","skEm":"bf8d7b0c7d04700b0fc27cbec6393dd2d2c386fcf9e2775b630422d2dab908cf","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"261e67b288b98a28683c5ca6b319a7f4c9f68f1bd444ebd0521d4fa4b5312c76","pkSm":"c44d5a8032fffc7d31eb5f69e91854c5c343ed2bdf3a35a8e4ac7cc08a3ae41b","pkEm":"2f55e857aa6e15c9105f38e8a75ad6778494be7bb167cae0d1b1402eb011be75","enc":"2f55e857aa6e15c9105f38e8a75ad6778494be7bb167cae0d1b1402eb011be75","shared_secret":"6999639460a821ba9eb20d24997f68d358878e7c2cce560b98eb54d4cbe161b8","key_schedule_context":"032bf29bba14d4c88e22c7637cf6fa2c279836a13308286be2fbcae87dad2dec2c47252d8fa4e8b173b715aae0af06bae18683a6c022c2b1c6e28a096f930585b8f18df7d7fbda3c938157f486a23f47621b8c7bc4ab9d89fd902c1d406709ca1b281ef1b7bc4736dc044ee497d5dab805fd38a9f4890398ab2569653a0a7ff73b","secret":"faa1b12e7dd6784c1cd7290e63378aec85235d481651bc9892a0ba9f94efde58d3acafe66d30b4c1f2692f2e600c5b090f2369f8e77bcf92f6deb5ea106d0599","key":"600542b70f0772738c35ad9cf30d43947ff7219d5cdb6c1e41b8757704ac6dec","base_nonce":"9c0e00ec1a81914c96d65bca","exporter_secret":"0b7f7c35ec09c7db9c00d11903c10d77132f4bcba08accff31f4801ccbc4f03ff085574f4442f3106c80ecff918e87a4236c26f36c5db40ebc5eea7e1681fbe0","encryptions":[{"aad":"436f756e742d30","ciphertext":"5efb2d2c56514c9251d6589b80962900d9b4529bd7bc26586ffe9652aeb1e9f1dc27246a6714884e9b42b1aec5","nonce":"9c0e00ec1a81914c96d65bca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"c478b35ef373deaebc502f97578903a8c54823a665528a171e8f4f505da810f7f7df69cf5efde8e95fa1add656","nonce":"9c0e00ec1a81914c96d65bcb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"2e3d2c3a88908eba22675fb8fa228dba7edb41d6e57004053df31b426bcb955fc4537d00218ead24e03f75010d","nonce":"9c0e00ec1a81914c96d65bc8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"3f3e3a6d39be1933cd4766196f576ada0f1238544de286ffc636b9fea0cebbc8e4f0550c83918315d38ffde580","nonce":"9c0e00ec1a81914c96d65bc9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"143b2a0eb44f87205a490e16892e989e4526d0e0e9831d4ce639ca357c36477f5525c1bfe5691616e1c754a86e","nonce":"9c0e00ec1a81914c96d65bce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"9df70e69a1cb3f542740ca217a435ea799c6e5b5c6ee1e5a06c57e6b10195bfcf82a468dc779a942144786548b","nonce":"9c0e00ec1a81914c96d65bcf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"b839a924a15fe990d065e546d67b6a72254838a23b3ba936eba6a2ead24c2a768fc37da97bf254bca99ec0547d","nonce":"9c0e00ec1a81914c96d65bcc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"5d35c33b67d790a19a9b80345ef9b979c42024b1e868c4b55f1dac0c4357e0ad6db42ff99c232dbdd1f4e81813","nonce":"9c0e00ec1a81914c96d65bcd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"093b9070b7e1801b56c66f1cf44a81c3c0621263f593993aeba50099e10be696b6d0efd5960a74589d20da8830","nonce":"9c0e00ec1a81914c96d65bc2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"7c88010465774647dbfca53a70a6f0f95862eaf9fb3228d1b8169f90fbf05d57e4b4bb9310b3c66b9e591b2d39","nonce":"9c0e00ec1a81914c96d65bc3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"69ed91a3f3db6b44f37d1db00c72ba9bc7d69f331665da2eccdc511115340379148b1f245653d8c479c76399d8","nonce":"9c0e00ec1a81914c96d65bc0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"5c2c543c0dcdfdaa6fc1497bd702c79ece9fca64ef19daee067b3efedef51ca27155f5c07f867864e3ef88e594","nonce":"9c0e00ec1a81914c96d65bc1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"cc747ce5659ca342e5f3485092da8f000f69d1282d61953a186ebac9d3ac970911df15a34998dcc64627bacbdf","nonce":"9c0e00ec1a81914c96d65bc6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"b37324e08e844b0ce25807ffa8089c2b1c067685f6402ee0748ffca37e71cd4fdcedbc3116167f702baad89c9a","nonce":"9c0e00ec1a81914c96d65bc7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"da7e0c5dc4febbea917a008f96ad4de7f84b31fa1221ac282191c4af669a17a7d36422164c2a811392568c0d54","nonce":"9c0e00ec1a81914c96d65bc4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"433f9fd6b3d46358c6b404662886ee1a929cee0d28654f0f7bfab7b3c625cb950a5a0ed2278a078680165e814e","nonce":"9c0e00ec1a81914c96d65bc5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"0aa8c058bc962a5f937fcd46e625dc5a3561dbe14ce6761ae2a9751ac57b8287883348cea9831c912ace36dc16","nonce":"9c0e00ec1a81914c96d65bda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"6b5ea614ae77a0391de853421e88cfe069f629725ccffa9b04027e24d00dea1230c3cba8d31acc11f0a22d77a3","nonce":"9c0e00ec1a81914c96d65bdb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"bfd884107f97e767db403e50acbb2f051099fa9cd97576e4f12a1a23a8b43fc3ca8b390457475497a62c1757b8","nonce":"9c0e00ec1a81914c96d65bd8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"9df75d3e2751c7bfad6a728513b543215fbb908e3fd89ed939bc4e5ccf2009a55acc7db17f2a75a0fbaeadcf9e","nonce":"9c0e00ec1a81914c96d65bd9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"7c9ad6981b8c0f08f3e74b89e9fd25705e1857be1a373f8dfb9d90f4e1700a27e6d80032299442d44002a6c1b7","nonce":"9c0e00ec1a81914c96d65bde","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"069bcba2aac52d6d6b7487c341ad64c929ed1e99981867db5e3688a334c671776a6678964ac4186f69cf861fcd","nonce":"9c0e00ec1a81914c96d65bdf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"8804388a0a6b1aaedda841bd7a984813d1aff87ba8fa97e92a83d8f392ff0205aefde38c437dbb7632acdbaf74","nonce":"9c0e00ec1a81914c96d65bdc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"7bdfdfd44a9afb2665a5f21c0d0032da43dda48e5a3c6c2c109368cab0b7197acab879429529e1ecbcbe02c17e","nonce":"9c0e00ec1a81914c96d65bdd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"4fc78d19708bc7ff02ad566ce748cdf73430ce33f8ddf11a8a835a657b92bf6abee6091d438a4c25f069133c1b","nonce":"9c0e00ec1a81914c96d65bd2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"80f5098f72e734b1cc3ba8d198360b15c43873db3c5cd7ff1ece3c4dfcad46a8cffe813b36f975f06bd2387ef8","nonce":"9c0e00ec1a81914c96d65bd3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"1d30114a440a38514299311c4525eb6a8c36f8bae7afbe946b3d90d999978ae8c169a8a376543ecbbffff8c8be","nonce":"9c0e00ec1a81914c96d65bd0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"5c7c2d29efc8bf58d364542e55457f59312c1bca8e7e67d20e90c9a7683c72c6298fe0f64968009199cdf2b508","nonce":"9c0e00ec1a81914c96d65bd1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"6b3a5e300befd99f4ca2b1d5cad592d0f52b4252d38bf035e7d5f9fc762729ae3eb80deda9bf16b825935e6434","nonce":"9c0e00ec1a81914c96d65bd6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"57afa6c883d3ec270e3c37018a382b8564961ceed6112aa19b7f90103b3d954a87e22b1438ffa4b6609616e42d","nonce":"9c0e00ec1a81914c96d65bd7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"334a4bc944c3adedc1bd70a299139b7bb76cd54000a050bb473e6f772ffdaa144c04e7635dbf7ab6e0b96f8638","nonce":"9c0e00ec1a81914c96d65bd4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"8611bc4f704a3a5642ba987b21651dd7a564149e5f04a05322cf75afbdb6cb6d63e4458577a05b6c59c3d1c104","nonce":"9c0e00ec1a81914c96d65bd5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"de272965c1ecfe8eb399dfa1a93976b70f30b9af3c7dac3ecb38922c582ed2ad884f728c9a2688a498329c0cb6","nonce":"9c0e00ec1a81914c96d65bea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"464013b2a5299192d2aa91c78bbd89fc20d4aff3770ed472c7be766d2c09f5e7607d71abbe5004052774012ba6","nonce":"9c0e00ec1a81914c96d65beb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"aa97e446c2103e3b879e5c471226ea4133007cb4f0c334ded43612727ac28b4e28f9a157d49b86d1bb200468fb","nonce":"9c0e00ec1a81914c96d65be8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"e9b97ad0e4dbefc0b5d6fd19a56753e0e4ac5bbeae29716a2cf849d132324af52b31e717e88411c7d223d85b7d","nonce":"9c0e00ec1a81914c96d65be9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"aa266f5ee54c3191d3b6d2b9aa3ceaff0dd8ff35c721520f59bdaea977d27ddb7f3564e01a6a83cc3b47dfae69","nonce":"9c0e00ec1a81914c96d65bee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"32cf86c6e8ff0a91cddee1e036d935968b0b9e657a550107a155ee5efc1636ae3c8700b6a8c33f5ee971f6a6bd","nonce":"9c0e00ec1a81914c96d65bef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"2b5e83db7490f8937ca82959c899df0801a84f39300f17fa2cf8b35f4ef5d0db5b6cf07961c5105f81a84df15c","nonce":"9c0e00ec1a81914c96d65bec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"faee6aa0c17c6dded7eb45efeb452108e5a044bfd7822778ed542f6a1bbb83a833555144adf6910afab02a5981","nonce":"9c0e00ec1a81914c96d65bed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"03b417d732059fdbb0033b7efca50bfa8eacedd9bbff965405ee10e9059bc9ab31d0c9e664fb962ef342526f4f","nonce":"9c0e00ec1a81914c96d65be2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"e472013489def38745053a0ffbe2d091e9b2e34b00a85fe41242ad041f528fc8bfbd9f410d949d50ec367ff6d8","nonce":"9c0e00ec1a81914c96d65be3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"5a40c7071d228961cd9afa804fafbbcf591f2857ab708145eee767c469f3b0a544b50691f10388e9415620f316","nonce":"9c0e00ec1a81914c96d65be0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"9a42cbe7e58a6fe94d66100f516004a95ab7678b1e006724dfea13c18c890ee13eae64c4796890bb634c40962e","nonce":"9c0e00ec1a81914c96d65be1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"5e59d9c920a72e4e5b4e168092410d93f6fbed0ca48aa766678ce577c6252dae9d7fa01bf84c966d80d9a596cd","nonce":"9c0e00ec1a81914c96d65be6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"39896f7788bdbe03764d41ad597ee8b6fc16a517910e143f9d776771b88658b5812560c17465bc8be7cd8eb891","nonce":"9c0e00ec1a81914c96d65be7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"092ddbf0201c08e4fadc3fb3cad7e181a585b35860872f2904694732043d703d4c6bfe9194e4b08915f424dbac","nonce":"9c0e00ec1a81914c96d65be4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"32f1013be787919009bc382d46134719ab9df3f5fbd9feb6d2fafcb4fff6bca78cb2aac80725857694ca791a9b","nonce":"9c0e00ec1a81914c96d65be5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"729c07a5545dc167f708695dbd2c7b28fe7993a70223e5a0a9cf6c2002f77bc3ce4c92e1cad2ae76ac15cc8320","nonce":"9c0e00ec1a81914c96d65bfa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"3fcfcc309cb3fe804a5f1b5a58c2357021b7aaa3c252f414e4ac8988efbd5666958e29e6e66a96b413c3508e6c","nonce":"9c0e00ec1a81914c96d65bfb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"5be950c9c7d2632b3fcc657cb308f51366e251428e1978b99a3667b029d882f82b583b8f228ef1d0a222e12e1a","nonce":"9c0e00ec1a81914c96d65bf8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"32d303da51b0336c9307839dfff7c6221c67ebd00ac1bf432afc9b32fb587bf6efffdbc9191b5d1dfb5e784dc7","nonce":"9c0e00ec1a81914c96d65bf9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"12e6dbd5388cbfc2e3e671363bb609dd3db8ca6394e240a44bd23e4365775bb525d70af1cf7e685699d95a5f2c","nonce":"9c0e00ec1a81914c96d65bfe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"5442be1fd398d94c7817adea97d716a5443cfdcf2a9c5716f00873cd79067537bae3dd00784e44e3380cdfa8c8","nonce":"9c0e00ec1a81914c96d65bff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"0678dced0776ec95a275e574b198f7e3e44f762070e2844e2390a8636fef0d7b343b3510ceea4308e11e2dbfa1","nonce":"9c0e00ec1a81914c96d65bfc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"d8c1cbe8a4de8d5c376defaccbd1c1b2e0f773f89187d4f3bc2bc73924cd55e98f2a0143d2953567dd22bc3290","nonce":"9c0e00ec1a81914c96d65bfd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"4dd93f72ff6ae340a605f07a4b8e93864737fea96e4c547649a0c17f7c60d43163c648b25d431509085f28f694","nonce":"9c0e00ec1a81914c96d65bf2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"0731ee384dd0da009797078024aa2390bb11cfbb61c2a6b14f2faceaf245a3d680f3b30de06b785f3ba97fff7a","nonce":"9c0e00ec1a81914c96d65bf3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"b623b5a68afeba03dda8e523741989ec3362c0b9c6631471263408084f2bd157a43ba94da1a5103c87318ff133","nonce":"9c0e00ec1a81914c96d65bf0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"b90ba5f75369eac7875dca2a3f3cc6ea4f80d2bda7abaffadc37e1557002f8402349b3e8f7fba344d141f73dee","nonce":"9c0e00ec1a81914c96d65bf1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"e57b815b38aefd3a81559fc2863dde9f48223ba18b2ddee3035ba74ef0a44d50e6258f0860a0a09c2c5987406f","nonce":"9c0e00ec1a81914c96d65bf6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"f19e2bbd5c560a6f2a37ab08054b27c85cfd49ba1ebdafc1a9d8cf9eece93e2858b55d2804b8d209d3f9b5696c","nonce":"9c0e00ec1a81914c96d65bf7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"60ab503e35b6b52e953f9254ebe8e244eae4061c8914523232390c55c8561ed18b43874e2dd463f93ae6a427cb","nonce":"9c0e00ec1a81914c96d65bf4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"02b4cf4c0bd3cc32e34a289319ef71c7605276477d1c878fcc5f76ddf6541d02d092a21d8a5b4b09ad7f8b9f89","nonce":"9c0e00ec1a81914c96d65bf5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"a504c229f32c5fef0d0d21c4de8cdbb724480796e2de84c1b37cb326853841db3ec72e1a366483d081cbe55f1b","nonce":"9c0e00ec1a81914c96d65b8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"481752aca74176d03d3c2f5d2fc0285bec4d40d9cf9a68b9e478824603571b526c376c85f144ab72877051cd42","nonce":"9c0e00ec1a81914c96d65b8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"8b99536a650ebe16a09f8d17df79c728e900ed81146d8fef3c5e09a46bcf52cd1bde05b83d79b03e2e6b861307","nonce":"9c0e00ec1a81914c96d65b88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"3bf2133d671895caeee1c718092f8859710d4e91b0345fed2dbd749a5ed921d8f617fb4176312c0129f47a57ff","nonce":"9c0e00ec1a81914c96d65b89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"a1750eaf4a3852a66c2b75e737fa3155aaaad7f3e5f0b0af7b8300a6b9a5cabf5f046bc7e5b3755aa3c23c6f15","nonce":"9c0e00ec1a81914c96d65b8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"32d4d0f1201c119f6267f074537d403dec0b014e1acaa3ec2dce601bcded76c6627959db0c456013743ea9542d","nonce":"9c0e00ec1a81914c96d65b8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"6cca27867568978faae9007eaa42d87fe186b004540769b717c4c1bfbfe6a284ff2ea6b7e79fab3335ecb44f9a","nonce":"9c0e00ec1a81914c96d65b8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"c45af90fe5f15b9bdc54cfe73552bd89b7533cefe99cc519b5266e0c60de03b147afe7d14160e45ccff5a6c1ab","nonce":"9c0e00ec1a81914c96d65b8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"38a53dc2b976b518f9094e3fc1e4c9fa5216e42253521871f804cddd5f06d7152c49995c06e8fbed5a00f95b02","nonce":"9c0e00ec1a81914c96d65b82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"6cace2fa14b6887e8e6655039d67706d34869a25967c5365c5381e9d7b1fecb5697072714978c7715e35450b81","nonce":"9c0e00ec1a81914c96d65b83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"6123bebaaccefa9526efca7ca968af300633e651f1d9eea067937a7fb158563b4012f4932c54bea31197214863","nonce":"9c0e00ec1a81914c96d65b80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"e6047f2f36531ab53a9722b11f9317add864b6dfb1357c4a1c3a5949e1d5d82f1ec6a64d8c570b571300311d61","nonce":"9c0e00ec1a81914c96d65b81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"1f6280899290c41a58559d4feed2ac28f505c847ec464672f20d38b2ac77aa9f2b41877b1866d366a12defc3d7","nonce":"9c0e00ec1a81914c96d65b86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"64d35c4227c1215f3f50686db2fa759be94a8cec485bfd74c48e125da26d977db01fc1072487e9973c359d6008","nonce":"9c0e00ec1a81914c96d65b87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"518b1064f1b063703d04d2fb11135f7d2e6684492f51c351ca8a7f8fa7a464bf4aacaf6d0f90fa0c4e6a408431","nonce":"9c0e00ec1a81914c96d65b84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"eb0a19af8f1bde494854284a6b3732bda0750ea68ce9b09bd0fc22df2b3ef0bd10f89d77a3a5eb7fef070dad5c","nonce":"9c0e00ec1a81914c96d65b85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"a4a6100082df148bf443a96b907a32ec2d799af1a6cc651e6a441ce98fee86a80a4686ac506acadec67fc71c9f","nonce":"9c0e00ec1a81914c96d65b9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"06272832c3242d6810e654e17765531e4636a7a60d1df261c8d259697b0ccf4d4144ee1b50e5521316a52f9875","nonce":"9c0e00ec1a81914c96d65b9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"7f2bdd8287b2b304d4dbbe011080faa344a08a7de03dd917ed3ac40b0735906627e1ee6475a8b55350ee7d9e88","nonce":"9c0e00ec1a81914c96d65b98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"0432108d27e0253c165ba0ba1a7c47f2b89dad25342c71c3f1b119af6e056473054c7cef3ed71834a51b5e7a02","nonce":"9c0e00ec1a81914c96d65b99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"a503360285cecce5af48deca3475561aed573201e16f1138aaa920a0d1c0ee1eaca0ba2bf0b500281bac56cd48","nonce":"9c0e00ec1a81914c96d65b9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"1f2aef3ec366434c10fcb3fb5b530b221d724962fedb84e9bdf0f599bf35c2fec60a73e3366e76177fc03be95f","nonce":"9c0e00ec1a81914c96d65b9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"2d928c453184fcb676ea08312c7c9b486e1891ca109b5f125e2c97b89cbb1ce1d4b4b3dee9e6a602eddd30a4ae","nonce":"9c0e00ec1a81914c96d65b9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"bc880a70ca2d22612ae4565a399634154a7b135b44bcc260a06246e6c36a148c490d5d869738ad6d91788b5bf3","nonce":"9c0e00ec1a81914c96d65b9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"a026ccdd75724742b6f4880b8312eec45600e29c90623b21d141e2c2d27171e5347fbc68dda70dfd4baf23187c","nonce":"9c0e00ec1a81914c96d65b92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"5d9b2f7df6d884ec2f27c8f2c819310e436107b516d870f915096e911c1068129b9b578f5b9d48596367992cf6","nonce":"9c0e00ec1a81914c96d65b93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"38642770a360b2064806e1cf84cb5e675a3f45a41a09bc3ca88f10e2984e6a88c5b6bbdd18ef23475943ca1def","nonce":"9c0e00ec1a81914c96d65b90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"8804a133f637fe4bb858ef9ce82f06e4f69eddc07ca3de3eb9d863d9c4bc1b74d692ac8f5e4863dc3ce8ef03a7","nonce":"9c0e00ec1a81914c96d65b91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"1a0e662c9c4c7478e3b21cfcb8b4632c5120392e00284f78f924cb9c01fd5a2d5e71c43828f2a52a051ad5f7d3","nonce":"9c0e00ec1a81914c96d65b96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"b41935026b5ef03c566e84436e04436f6cf0ef070e60b66491cbdcd5ecbc87a10bed5d4bc3d176d47bc6058d67","nonce":"9c0e00ec1a81914c96d65b97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"20c4bed2973d1ce06ec00e11e2d378b7eb7c20d7bbba0bfa49c3fa7dedb30e566f74f9d255bc9a4f7e30832a44","nonce":"9c0e00ec1a81914c96d65b94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"fab6b8f76a9541b8e86c12f968df24a57f6d032c65d74afb34a589b481be91221a772665432525542436943005","nonce":"9c0e00ec1a81914c96d65b95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"17c273c1ecfb385e08cb05aab0bbe937760505949535db5464db3c7cf30921317f9c54e8decb724e5991f9ceb2","nonce":"9c0e00ec1a81914c96d65baa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"02ef2b9dcb1fcc9633ba1372965e90007749524791de44e777a0470d3f2ea8d1ff74565f386e695bb7d91c12a5","nonce":"9c0e00ec1a81914c96d65bab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"f2abd016436056bf82a7b727222f0bb801eb93eed06617225b37c0ed36f5551f0e602424d1e0a78ab3b0f9b356","nonce":"9c0e00ec1a81914c96d65ba8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"c52da5fe072a1be4e57ab5d188cfa9093fe4e22da780c4d435ab85ae586489dd8adaada6e7c63afed6b4d7a28c","nonce":"9c0e00ec1a81914c96d65ba9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"1891b7f80c44464ff6648d0c3364042c5982ef91c286ad0c03dd0bfed5069c3c013cccf2f303999a6b96dd735a","nonce":"9c0e00ec1a81914c96d65bae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"8f638a856790f15f689508eab268875c10dd02d3a6e1676037bbeeb53e3cc688e791b2ef3adb5a4eb902591619","nonce":"9c0e00ec1a81914c96d65baf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"13611da8dc2f9cd69d48ad5319c556310e5d0c72f8157ef46af1f930b3aefe2c40ac1bcf357ec3ea35f1026d8d","nonce":"9c0e00ec1a81914c96d65bac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"c91ea91aba0ceb832aecfd5dfd1c683d595524efbb4686f6b97a1f98da493f304a8924408a8729e02153a9147f","nonce":"9c0e00ec1a81914c96d65bad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"9db94a618f4392b73ac1a03710f4e83ea09b0b17b3a24756fedec025bfbb46caa0b38d0fbea1105f4fad070786","nonce":"9c0e00ec1a81914c96d65ba2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"eace331fab15a7c8f4e66982ea534f5c56670338b6df111c58abe0ee74f59963e22d6f59072043e2525aa57fee","nonce":"9c0e00ec1a81914c96d65ba3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"84a073bfddd3e9f067a3f6a4f73a890fc328630ca5ae936a5334bc7c50d0c85e50968ba360eec718261ea11d07","nonce":"9c0e00ec1a81914c96d65ba0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"5229d6562b2aa7a165fe5ab82847fd8f54dc9aaac4b82ed083e5f4fc9fdedc18b588167b71bdbdc8e3488a556a","nonce":"9c0e00ec1a81914c96d65ba1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"1e517eeb42b5383d54270561ea06589e52d73e9828ac9bc6810e39c27358b8e5db347f56b93f3ff3f536ceaa56","nonce":"9c0e00ec1a81914c96d65ba6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"ab5b4d7784ab49669b3432b02910794db7ac12f1908e2fb0ad367be54e29ffc3876a2d00831faaf16cab5291be","nonce":"9c0e00ec1a81914c96d65ba7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"44029869a659f7d6a16ab34a3d89bb7b61088e9383d906d0586ca070adaef4f1893d7efbb1c50174b4bdfeb2e4","nonce":"9c0e00ec1a81914c96d65ba4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"b2311ca22ed66684bd76342768f68e24581914bafabf86b07c3144a8a54a88a27d99a02b859ec9ff09a6f7e57f","nonce":"9c0e00ec1a81914c96d65ba5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"721191ddd078f6874727dd089746c266bb67690c38430a2ec2193041cb172ebab09819db938ecc8dc4a8261f2a","nonce":"9c0e00ec1a81914c96d65bba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"52c922c2d57fdbd48cd96537fe10725296ca66d8830ee6cadbdd3b63e96a1872a9fb52b1c34311dc594d85fa1c","nonce":"9c0e00ec1a81914c96d65bbb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"f7b0cc4bf6e01339e590d9a96e7a371409767e2e858521cf2b99d9da6b057a6ea0dbb36f65837bcb2afc26716a","nonce":"9c0e00ec1a81914c96d65bb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"32ddea57eba81bef8ea129176cada6f6e3a8eac5aea5eea20ca83c71cfe07099f436b13c39647a284889fac4f3","nonce":"9c0e00ec1a81914c96d65bb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"8aaf6f25cc9cdb922dc3ecfddf5149d232b5ccffe6daac5f6ad40024b6a4f058ceb4269830219a2611e2ae004f","nonce":"9c0e00ec1a81914c96d65bbe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"f269a9b9b9977612cb33e5a4aa72f7ad6a75b920154d29dd3f881296eb3a6ae010373e122b12f7831ab9c69fbb","nonce":"9c0e00ec1a81914c96d65bbf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"d525fd1492c30ddd4056415c9c6124e71e5d85f063390fe3d37b67983661776fb937c5ca1ef9d91bd0df729390","nonce":"9c0e00ec1a81914c96d65bbc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"a617084ee632321bc5a6aa6015e11dc196e306d5e7d5ddcbef99f96c76921b54ef96dcec5de77f8f4e81690016","nonce":"9c0e00ec1a81914c96d65bbd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"5caa956d20a28f582e9e4920cbd16f7070b139f92c1f14ea4a545d8e2f571b39d154ba1baf03443ad3efe6e3ff","nonce":"9c0e00ec1a81914c96d65bb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"847dc27c541077c320e1f973df3785c682a11dce1604dbae3c422a9a4dc5fc25decb26799a28b2950e52a0e824","nonce":"9c0e00ec1a81914c96d65bb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"81530765faacd5864df5004177a1dec1fd9a020e46ae35e257bb3f725d97c9ce961116ecbb1843c5de625c045f","nonce":"9c0e00ec1a81914c96d65bb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"64433b916aac3acd4edf62836fd8d7d3569906536f38d800c0b3cdabbb2458f444b79d6c9284baa5de84eb1026","nonce":"9c0e00ec1a81914c96d65bb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"9a1fb18fba207c9f5c941070ae589737b458c1d5f4b676e088ae44aab6c4060b79058c2a8ecc9efa2eb2cd0c71","nonce":"9c0e00ec1a81914c96d65bb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"feea7c34addb8a4ced2785adc8e832a72e3d051cdc6ad8b33034d80b5f8d717ee088008fc71c8ca233f70e48de","nonce":"9c0e00ec1a81914c96d65bb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"e2e6b331b012fd482e32c24239250156e929b76558aa1b61fb73b3344a67879b98cdc4bcd5ad89fa0a58f461cb","nonce":"9c0e00ec1a81914c96d65bb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"f05dd1436c1d5ca8930ec36b389742593d26cfe9e901e3a401d10069680d5dde261b6d5960b7c4ddcf495e6b71","nonce":"9c0e00ec1a81914c96d65bb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"efbafd485c5b14fafbeb6a214ae959adc8561a4ea98374b025e4ac05304e0bd1477a87039c85f4183e984cfcd3","nonce":"9c0e00ec1a81914c96d65b4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"3780cbd0c050a873adece4d2d3a1598c2d62d4137aedefd75f199249cfe3498c86ef5771babfe7c80855b25466","nonce":"9c0e00ec1a81914c96d65b4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"4b3e357c47219f5b1652f136dfc92a24da4176fc62c0214a4a0d12d1a0f6ccaf6974763671b74c090532457325","nonce":"9c0e00ec1a81914c96d65b48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"e6d763c9df90d911f66a9dd4931085a2f554cbdcd772856baf386bcd7651e5bd6c527126e98241bb4f37c48485","nonce":"9c0e00ec1a81914c96d65b49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"44b075db615c25cf74a9cede8423bb27939de7e3888d055b9c13799230a5f523a1c7ae38b5625ed2d6452e6bcd","nonce":"9c0e00ec1a81914c96d65b4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"7a964d88b4538cec2d9a9979a43ffb4e3cfad8ba067802f7ffc030886cd2cd49f04544afdcc57c9241bc95d724","nonce":"9c0e00ec1a81914c96d65b4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"f67427515b8830c8c43330f9f48923f0dbe1056921d3e3239ded83e7939d14be16febc2daf637ec22e9c6e6a15","nonce":"9c0e00ec1a81914c96d65b4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"da0faa3dd14e8e60b51853846c50c63a3a7a3557f38569f813fd5c0068f3d60619a2446b4389f7aacdd100c410","nonce":"9c0e00ec1a81914c96d65b4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"c8ec4110774a2e073e84a0c26dc774844e7776b09fa4d0adbe9de4706d8c7bada40189f786a063e4584cb069e3","nonce":"9c0e00ec1a81914c96d65b42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"2180b202d805728e4d9df6f5d78c3796c3e35d5fd92b27301ab1617c1df5171a44abc930f6273c4ff5fe2d2001","nonce":"9c0e00ec1a81914c96d65b43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"4c92949d449f1b6602a34fc94ef1373f3d5fbbebfa85f6c934d558b62751eccfa341e32e86b97772d36856f270","nonce":"9c0e00ec1a81914c96d65b40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"8ba1e83b9fc7f6dd499a77d6315d6cf94a621d89f03b57f7ca5ad15b21a3b07178d2944e69c154abcb66556341","nonce":"9c0e00ec1a81914c96d65b41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"d75292b944ee55f00577dff52af4798c980399f1fa20983608ef697c509b1ed759a35b037e04c300b9ea1f3dbb","nonce":"9c0e00ec1a81914c96d65b46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"115a8869ef01c5da9ee82af29f608eb10ca1c127f915632d391a3708dee2a02cd7152225d6d146386d84b4beec","nonce":"9c0e00ec1a81914c96d65b47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"7fba617dd90b23fd6a596303cbebc5f5f473fa654d92eed4066ca9a0c3367e24f28e10a4bbd03d6f00b88f1d8f","nonce":"9c0e00ec1a81914c96d65b44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"a6c2b260f409d52c5042caf294815be70835ed3925539374e370399dcbedf19e2d8683e906d64a7aa9d9e1d9eb","nonce":"9c0e00ec1a81914c96d65b45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"0d1913a2dab6b93f4b51efa73aee736ddc03c64b09bb6adf3673b7048d4d9b57ad44127f51c2dbc81024980b28","nonce":"9c0e00ec1a81914c96d65b5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"a3d45aada240219f95f5cd1c66702d5b94ebedff7a8a90357fc09e6365f3e20f0dcd8137fbb66e17cf8462249b","nonce":"9c0e00ec1a81914c96d65b5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"317b0d19991e09a8347a39804cb4991e684b11bf5270acab59ffa65d757d2bddada6f9ffff084c71fdd5473fc9","nonce":"9c0e00ec1a81914c96d65b58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"903a237bed6bd3926cc26961616011df4c44fdbebfb9b231086edccef2a710ef6c4f61814240812bfdff5e4e2a","nonce":"9c0e00ec1a81914c96d65b59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"beaa8ab796894b18a0d3d2256760dad6114960456d9b27a0ed3a24323715d02aea13dbba734e6b88f195aeac47","nonce":"9c0e00ec1a81914c96d65b5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"d0e4b3c8cf08160429a40de30034f348114d4c7b2b22d1456bbae29f99f9a54150ac0370c78c4009beae141457","nonce":"9c0e00ec1a81914c96d65b5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"7645c464e11fb1d2cb11511c20bf6e3a164e0b149acd8ff68ce493ecf27ef321bdfdb79f71c523c39f932d9b3f","nonce":"9c0e00ec1a81914c96d65b5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"96f7b1da03c0cbd3786d65d2501d1d5e5b83acc136d69f2f3ec80af74c9655feda48913e576f875bf694de5bd3","nonce":"9c0e00ec1a81914c96d65b5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"dc26be01dad65ff4db7574c614c0cf62ab727321c583618a8387357af026b723d935b47c381ef0f2f29e09985b","nonce":"9c0e00ec1a81914c96d65b52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"fb840d05579dfeb6397c161ba9431fde9044bd3e2cfe508eb623dd402aa4396874a3183e680142a399f2f4fd65","nonce":"9c0e00ec1a81914c96d65b53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"81aa1c88ec8517608ae5c9d6b3071c3524736c6d5d3cb1cbb683a02964cd3b33cb7f7c24eb241d0b85a89a40cb","nonce":"9c0e00ec1a81914c96d65b50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"a533eb48196050859db66a3d82b32ee42cea9b75cc19b042917053b7e3789c006a3c0c4a1340d91fbc4a287da2","nonce":"9c0e00ec1a81914c96d65b51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"39cc1379949c9525b18cd7e159ae75d0058e185c0c9237cbb638d25d5581d2df53461ce6d51313a50b27ffeaad","nonce":"9c0e00ec1a81914c96d65b56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"4efcd346eac244fd6df8084d904fe6aebd8a04dbc4891201e01cc42e44de954aa39a7a657d2f12e8b273530edb","nonce":"9c0e00ec1a81914c96d65b57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"8d0591e6fc356f4c1aa7d855ce44c585e277cae90bb07e79a5239d7a0d3f0cf6a94b957ba7dcc54b50baffb3b2","nonce":"9c0e00ec1a81914c96d65b54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"223641f3c19c19b87111d7df93693194e8cc58ca712f94a4f5b9e3cc5f97dd662bc6bb34352b915430f0c4b04a","nonce":"9c0e00ec1a81914c96d65b55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"3a1da01f9f9e5446e78871bf609bb157ac9e01b686bce0fc58052a8763fcbdd73097236a2f5e94eb0770995ea7","nonce":"9c0e00ec1a81914c96d65b6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"50b730376c79f7ef4fe6b89253b89683163f38032e9b0dc8c89fe61bfd7404b6aca8ae902ef43004cfcfd3a8cc","nonce":"9c0e00ec1a81914c96d65b6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"66d78c3511720a2a46f5393f24ea4b7c4ade5228e4e4d50187925811281a6372c04135f3a1fe5e73c38d846262","nonce":"9c0e00ec1a81914c96d65b68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"349c683c3824bb91ff586b6987afbee0498e26bc6ae991b4ee5bab137abb4de30558bb8c8ae2c7e1a8b81d7662","nonce":"9c0e00ec1a81914c96d65b69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"0047d698207fbcde13cdd89aa64abd3a3ec9ec72eb4dec65968e5a84f1e9d6bfcd71a4b88c55230e675c239ba5","nonce":"9c0e00ec1a81914c96d65b6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"d5a768cd9d4e05f88d1d4165a1397cf8d84c80ee803b622dce17bc378acc2d65401f021fbcfdb3de56b935b938","nonce":"9c0e00ec1a81914c96d65b6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"64fdf4c31a1285c25073fa80eb1869c680025d49dfd6d48768032e7c92f96bbe6c09580bf3677bca24157bbd6f","nonce":"9c0e00ec1a81914c96d65b6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"ec58d662531afa01c071a0710f6ac3fc23b17e7f8d9c15753987e2b716eff4069cdb06e4cd859744679b3b8112","nonce":"9c0e00ec1a81914c96d65b6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"7ab27b025cb210036d5f75bb2b2595d300ef9be0739fb87d8a31cc97be9f53f15815f98e02f327b51b74c51a74","nonce":"9c0e00ec1a81914c96d65b62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"9ba0cd8749c75094e352872e410c65406fe54f86f04c4c97ed9eb0958ee9fae0d3b88d79cb2e0497e0b39fa50c","nonce":"9c0e00ec1a81914c96d65b63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"f32768f9521ee6fdc1947b77dd98cf2e3bcb6ef448a4c1cb1cc3337dabffdee2bda5d2fe409732c7f098523f9e","nonce":"9c0e00ec1a81914c96d65b60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"e473cc7e3cd46364496dd4da2fa5d7f0db49679a807b9b6ab8efec1a9a40bf20dccf6f81e7e273261a197aa919","nonce":"9c0e00ec1a81914c96d65b61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"92b509d06f997a8896df91134a5d2be4422d1ddb0989e619f94d55aacafcb43e0fb233cc73a52d10bddb12f943","nonce":"9c0e00ec1a81914c96d65b66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"22ef6ba8473fbfac2366eedf2e928ccea0030ffab23aa056773b3f08bb834427a5281a96b5717c0b89a7ceeccb","nonce":"9c0e00ec1a81914c96d65b67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"14b09419db23c08470f968f2168f4d7ce40ab0d4d9b35d8bf46d3ff1acd80b976394ea48e230e36bb233b21d78","nonce":"9c0e00ec1a81914c96d65b64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"7b5ac42bdea7f237d94180241fe7f57887a476bfbbf1b9fdaeca99ae4e9f12381d2c0479ee3164b5f367a37fa0","nonce":"9c0e00ec1a81914c96d65b65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"6cb188617cacd50f98183d6a6d175086ee12f304737148d5361da337f36e32566a2caa99d82de7011d6aacb6ba","nonce":"9c0e00ec1a81914c96d65b7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"17e52a09efe48a6e0c1be5dee05fadf26fb6353a8634d4a8d2eb360eee80edcb913a7c187a67922945d7d55036","nonce":"9c0e00ec1a81914c96d65b7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"eff85562aeb29d6aef06f4dc5a4bd44eb568a8303efea922222052fa23f036849b90399fadc5564e86e85d1c8c","nonce":"9c0e00ec1a81914c96d65b78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"c2d645d08e9c91d0e0f29597fa24f7d9bfffcce27e9ea505836de249c507423f024d6677ff28736b290139556c","nonce":"9c0e00ec1a81914c96d65b79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"cdd31f5ab91622e0fae0e4fb3595edcaf1eddda109f6d73cc9f93d23814ca4669f5449126fbb14a4fdadc87792","nonce":"9c0e00ec1a81914c96d65b7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"353998ee00defa0c487a231ef82dd1858fb40dfb7fae4e280b3aae75947546bcd6bdbb2f42c8b91de8a1a91091","nonce":"9c0e00ec1a81914c96d65b7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"7143277e7d4c3e36297c88ebc25b7b7058dee4f3f1882f347ebae3400d71bf406ed3061f668c2062b0978d8746","nonce":"9c0e00ec1a81914c96d65b7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"bbd438d17ace276445d6e3f6ad68a1652134d70fed7e12d395cefb630fd163f6e5919342cef628de1f3e6c2f94","nonce":"9c0e00ec1a81914c96d65b7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"c9e0031dd49f883f94a155bdeb9aa0c09d57c9a6bacb5c603937b938fcb69fab63229ffa527c823bbe617165f6","nonce":"9c0e00ec1a81914c96d65b72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"a232850915ec32f7439cc191eb449e6b07982f8ca594b60aac9ea1aa37744419bfa4d59029c3782b02afc84b13","nonce":"9c0e00ec1a81914c96d65b73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"71edb5d40bf798d75d29bb8600a8db8826cc2872851bc59652be3accae818c93df2a8f7e4ee02dda5e87536786","nonce":"9c0e00ec1a81914c96d65b70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"320deac3b0402d71ca94f2abafb2785d49fcb15513d9bfafea3b5f2d787bbbdabe05663246d5120cae373dfdbf","nonce":"9c0e00ec1a81914c96d65b71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"c9b1f1d93d89044e49bbe8b948262f9dfd17f597f8ef46043b2459245cee873e2f9ff6121f32e743bcc79c6926","nonce":"9c0e00ec1a81914c96d65b76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"182a5edcd39c52e8ef59e0f9b1143d21342041869618fb3fdb29e939ada2e93020bc0cac71a61c373eba02b8ee","nonce":"9c0e00ec1a81914c96d65b77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"87b133553a935ccbd1d70323afba2ec5a600ea16bb551a9bc76f50a80ea91452c4bb60a6ed67bf8dd4a197b00a","nonce":"9c0e00ec1a81914c96d65b74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"94e246c371d6d01c327ed1aca0d802effc3913124f227175cbadcf826ec2fa5f4f7ca7079b11401b369d9a8610","nonce":"9c0e00ec1a81914c96d65b75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"585101334bfb6874707e68311dc8c7cba3dddbe5ba8e78973b778b18a070c8263ba89a0b0cdfa363aeba9647ea","nonce":"9c0e00ec1a81914c96d65b0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"e86d4dec026b4460d16125541614378e5e61bf29d25707aaf8d586fc83ef5e7f6a8ee75053dc09b5c43ebac2ff","nonce":"9c0e00ec1a81914c96d65b0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"6b52de92f0344ee4fca9c582baf59269edca51756a786b2cd4acdd43ca7b77df89e894e3bf0bcdcf133632efd6","nonce":"9c0e00ec1a81914c96d65b08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"b95df3b7a221b1a643d0acc02c857496ea498564ec3c7152aa35174a6db149250747a9d0b7574a08e371d47228","nonce":"9c0e00ec1a81914c96d65b09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"cd7e2cdabc1de5ec3157b27daf2d76f3c8b01ae078382026b32d9b8e5ff6818287cf7364d18718418676edf77f","nonce":"9c0e00ec1a81914c96d65b0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"d2f56d3f31d17407dd3f11a2265fe3b06883ba3b1152af22008425ba179ddeb8e8c7d3b8d9184e75356f646c86","nonce":"9c0e00ec1a81914c96d65b0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"c1498c59cee3a7a54f7338b8da53aab4eb2f254b0fa4d6b3d17acaba92e075d118fe1735dfd19cb85abf115c6c","nonce":"9c0e00ec1a81914c96d65b0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"50c70de0277fffdb58ceb3a2d8120e76f76ad5fafd0fc999bb663e3b008330f55d258ee7fa51112f3ed91d4c3f","nonce":"9c0e00ec1a81914c96d65b0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"d75feac814b040de017bc6a08089ad119a28bc9556ddefde1f84f1004ed17b4f4869be8580acb04bf03e807ee2","nonce":"9c0e00ec1a81914c96d65b02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"5d50a64e4adbc8888e2e507e96d9120b9204a87a557ebdbb2ed2018fdc0eb09adc3efd419b6a09c07513cb7ee1","nonce":"9c0e00ec1a81914c96d65b03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"03613b4f231d55f64f0a167a5005c4f8c63c5ca652b959e3ca202e6c67a006c99d16c9a1ad4e67da91a3e5f9e0","nonce":"9c0e00ec1a81914c96d65b00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"2e2076c7ab2e535ec5e6fb55742db5b67f1d2520338872cfed0269fdc9b8ff578f90d6de621070722988b7148a","nonce":"9c0e00ec1a81914c96d65b01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"7b3bdb8ed1e34a6f02aa19707efb7d987bb39e2f4e6eefc43c566bfe1f4b4965ab0b58a2a887d81d01659bed13","nonce":"9c0e00ec1a81914c96d65b06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"1d5d3e419bc15ed1a934a5067831ed13b5e6cde2022dfe2c3a31f10ed87722517b0e48a88c3e7868ac4cbcb59e","nonce":"9c0e00ec1a81914c96d65b07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"68119313c2243e4f38bed73e3117dc9ac2a48ae0ad4812a50570d55325d7c2a44da99d0b0ef73769875d8a0fb9","nonce":"9c0e00ec1a81914c96d65b04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"1088083d9cb8155211866d97bdb6f58951b28e4b725204480b14c6607244841a0058279f7fde908c19cbc9e7af","nonce":"9c0e00ec1a81914c96d65b05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"7e7b6d36a7080686768c63e5ffffbef9f77fc18ae636a3e8bf849b8c5672820ec34c9610e370028858af3c3de7","nonce":"9c0e00ec1a81914c96d65b1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"45c111c0319e56d23cf21dd4d4f067c28905c2fcae751a4a3638707137510fa984680905756f2479c018ffd91c","nonce":"9c0e00ec1a81914c96d65b1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"5743648b70ddc9a917a517d007f576617528e93b999c0932e29d9e29caab386786571578a54fe7b319fe4aab6b","nonce":"9c0e00ec1a81914c96d65b18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"b72fc74c2a33eb538aa5bc6123df5b3186c18a0f77d71821f03f70bfd9a0210889f4b80fdf69a841bb63916795","nonce":"9c0e00ec1a81914c96d65b19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"9da026327f07b96c65df819a39aa0601502d9fca27e3d1a2b214558be3547abee74e6deb5bb5e201119f07ffe0","nonce":"9c0e00ec1a81914c96d65b1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"80385d7fa568fb772c89c612ec5cbae1e8721e6877293cfafb9947eb086b83f1fda70c0701b9987ae3da7b4f3f","nonce":"9c0e00ec1a81914c96d65b1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"6566f3e03426aed1ce7d7e2bed23a733dcbe84fb54faae59858e1c7e785cde744f5ec22c33c32ede4ec64c84a5","nonce":"9c0e00ec1a81914c96d65b1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"15dfcde4d8737b6bb6f25674f278e70c30127b0d0c5eb05879bedcc241979d9df89ba00e4f20bbe876dc18489d","nonce":"9c0e00ec1a81914c96d65b1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"8b3fc260ce04e103921d3cb5cc244b974417821f05deaa43aa7aab162d2d279802fede6632af39acdfd437d001","nonce":"9c0e00ec1a81914c96d65b12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"091d8ab4de3424d17f026ca7acbd34d152d95615fafdc2966ca731601ff5c3c289759762519cb5c567089f8f2c","nonce":"9c0e00ec1a81914c96d65b13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"78ba85d533425f9e7d5a9203db1797b09f480674d4ab4ecdc43618fe24ae8dfa5050a397e75a4ad25ba60f2b66","nonce":"9c0e00ec1a81914c96d65b10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"e1a71ef2119128ae5b7ba011942a59af05d240a1dd169aab926131759a7182a5d1792c03648bebb95a866cec5d","nonce":"9c0e00ec1a81914c96d65b11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"4a5638c76a80490d9be88db44f51480b81dd83349763646ee798c918111e1833da874a6bcf1e6ee1227d225ab0","nonce":"9c0e00ec1a81914c96d65b16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"865e610d09773bf7584660e3aa8755831db99debef946d4be54d8f2d7983694fd63ce205456acc0378e84a01ac","nonce":"9c0e00ec1a81914c96d65b17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"25f889b465681ebe2c5bc818580b1844af8e19ad1d3ff9c026ebf52d4862168cbce98f174d0f80cc59d2ef98e5","nonce":"9c0e00ec1a81914c96d65b14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"20c263cea56340158824ba40eea0a18d388597f08e98c4977c71a85468ca529422738922bec8e0d5327632dcf0","nonce":"9c0e00ec1a81914c96d65b15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"ef1840daa86098b05092f3bed151aea975ed072b158b23effc4cba61294e64e01cfab9d8370a217256cb05a968","nonce":"9c0e00ec1a81914c96d65b2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"5b284fe5a50b6ff08841112ded380247bd3d59533c13b24856a8f90b4a9872f92c7b8aeda6cc32243626809c3d","nonce":"9c0e00ec1a81914c96d65b2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"7badf4cefc225c9ffec59af3fffb083255bbeb81dfaaf7395bc837aa0f50b94ab1608e27ceaf237f1aa6c5eba2","nonce":"9c0e00ec1a81914c96d65b28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"244a17f6a5c1f59683d566c8d51ac56fcb9017609c4c93d9c5015fa088fc1bf4f03a94a54798dc265efdf72bed","nonce":"9c0e00ec1a81914c96d65b29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"3026d1f75ce2e458faf2846de30f008c893bf9abdf352a4724039993a16e4f7c7f0a41f1c61b702f64b5b32239","nonce":"9c0e00ec1a81914c96d65b2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"c9bd06caa5b9283ea2b334cec0aec2f600db05cd16245d90b77984a081385f66d557a59b871093c4ebb91c8cbb","nonce":"9c0e00ec1a81914c96d65b2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"f93dd4998f02ac5b0f62010e6b6b8733eb928457342d0fc8106e3364041159f3d627c19faa3d7e9c766752ddc9","nonce":"9c0e00ec1a81914c96d65b2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"9b779ef80afc9b46287b06bbdbb418a78a9ee514720faacd148739b8dc3ce230e8d4e20a5529b2da6015af4319","nonce":"9c0e00ec1a81914c96d65b2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"4216cf9fbd3f733e68f207666a54e44fe0c1e7c60ede25e1a9d1f9e9da4edd178a9f2956bb0921cfb058686e35","nonce":"9c0e00ec1a81914c96d65b22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"12063bc196eaba0d78a2f41e7096101de9cb88b3c864da506e1058a4ca4a8ca547509782e110999477e84cfccb","nonce":"9c0e00ec1a81914c96d65b23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"e727a2bb6ff6ddb43bbf2bcb377fe5d5c05da3ed00341d53ea5846e2a1d657a336f2419e78429f687453c88fda","nonce":"9c0e00ec1a81914c96d65b20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"03738cf22ed1bc9d38140a65da0d871ff7ed29edfe01ecc43e2af50d678d8db6ca3a0870ade4669dd6ce5f22b6","nonce":"9c0e00ec1a81914c96d65b21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"ab1a52829f3b5a30dc8ed71369ae03bed83a35a1b63ac1730a8d3711f2e600dc27a8ddf12e30787dfde4720edd","nonce":"9c0e00ec1a81914c96d65b26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"da628cf5bc4244b756a2d0be7549c81ac870d8298b5ceab4bab110f92a9dc65b0b8b472c1edd92198da6eec7ab","nonce":"9c0e00ec1a81914c96d65b27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"037ff894225214ac1bc9f3d93bcceed02dd7d4256dffecf5f47411a2494eade81192f536d81f6ba8f072238ec5","nonce":"9c0e00ec1a81914c96d65b24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"0e6eebcb5c2a8553c50b7831834572c6d24ebd752f6e12f23ce0c09403e1dcc988b7d44286a065cad19a67d5ba","nonce":"9c0e00ec1a81914c96d65b25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"1c13319df6fb527a5a10f9b59607c0b34d446856260648e72988440a9326fb3c5d316239e217e322bea3f91379","nonce":"9c0e00ec1a81914c96d65b3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"aeb8aa7942626bef6ceb49323ae93819b14f12f8bcac6d6c3bcdfd6d47b6cf4796ca6cc3ba9d6e1eb30bfad801","nonce":"9c0e00ec1a81914c96d65b3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"2762850019145eee9831d8d5ad7f3cc4136ce26e059ba9f450fd970c387a6631f3d4e5551546ea8e36e103bae4","nonce":"9c0e00ec1a81914c96d65b38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"dc721145df98c5804634cc79e7db14c7f8084bd032039811e9dcc2474bbe327169a08e59d25af94f894f99c06e","nonce":"9c0e00ec1a81914c96d65b39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"28a53add0a031773abc920a877e5be54c7ac968a582864a38b6b9f2e696db4947e7c3b8b5b69b86895e2cc2a3f","nonce":"9c0e00ec1a81914c96d65b3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"758f941665bd38b44142487f993568315896e82a7162dd06baafc9acf553d2f5a40afae11a658fc098701396a3","nonce":"9c0e00ec1a81914c96d65b3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"d00fe7eef61d1199cdc79950accaf47840c1f4668903c030793278b5fe8f4ec80723184106f13cfb1a6c554f4c","nonce":"9c0e00ec1a81914c96d65b3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"fce4b45e83c950eefb41653a4e60372c625336e04066326bac138d3023bd34cb1881834d1dd146365dbdfd4fa5","nonce":"9c0e00ec1a81914c96d65b3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"750e8c6d34c0644c77b957aac4708068a12c1f76e6434ee66a02230124cb5fbc120361283398f7c72c329a6389","nonce":"9c0e00ec1a81914c96d65b32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"71f7ff21bfbb1b634b9feb637ed1e38e087ef5c378d1a58157d8667f15c07d612f2d43ce0c4b74b7462655ab68","nonce":"9c0e00ec1a81914c96d65b33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"09a222720c81f4dd34099f83afbd69d0f0bd780d2e3090ae8c440c3dc57a575501fb39678548451ff476cb8b20","nonce":"9c0e00ec1a81914c96d65b30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"984c7e5638fc3a77f4cc374948ff8be08ab08f54782de22b2df14a57203e66c175cb931f59642b730ec2884962","nonce":"9c0e00ec1a81914c96d65b31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"28934ec8d8842ae2383a39f11baf9cb3a36591ed3140ef650f04621d985291c5c582cefa0fdaa5c7affa47f685","nonce":"9c0e00ec1a81914c96d65b36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"91d58e22d1892a98aec4a1be4184aaa2418181a0031795792f473d392a3a14c6fbddad5a210c530d30b7763dbf","nonce":"9c0e00ec1a81914c96d65b37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"3956dd4c801cd5d1814494346a075053494fe7151cc2437f1f126343d1f4fdd8d804b8749061862cc473d49228","nonce":"9c0e00ec1a81914c96d65b34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"f2602b4d50d1395fcbfeb072a34cead7c3f5f3e13484eb2f288972d15a47c447cbdcebf8f6dcc3db0a77712739","nonce":"9c0e00ec1a81914c96d65b35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"3a6864acdf8aa9a113de9dc3614c9a4af97322c9911f104867520a3c40575b28fc0350c6719deb67d106395500","nonce":"9c0e00ec1a81914c96d65aca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"13388e4b9b42f73ec15b303838279379dd75903e6320a453a16425af3a27cb83"},{"exporter_context":"00","L":32,"exported_value":"526e47be0278c6bd02c4b2987cfe4e6127402dacf7177801af7606730cb0eea0"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"07093c5bbb8a0aa07ff552ee0f6fa817a67c4a0e6570ba06a01c3fbc3b433fc2"}]},{"mode":0,"kem_id":32,"kdf_id":3,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"578da16a762ab12137141f6180abcd7f8fc3fc3269d1c85c17a1a1d5dfdd467e","ikmE":"1e645561d245dfa6e8c821da95016518908192740cbc9221a76df439cb3d94b2","skRm":"cf60708f7e8df4b467893c94e681d80954b190ce873540133c68cc2c821f98b9","skEm":"dd1e71eabf36c6007ac31efaee34dad5b092de47384e9241ef62655c3a4ce7e4","pkRm":"ed1ec15bd6664e301a825587596f44ad15738057b952967f34950da347d8594e","pkEm":"affdb3b2c3742d531b363591f2cfe72da7c336651e9ff9b8a1d53124f1f5f551","enc":"affdb3b2c3742d531b363591f2cfe72da7c336651e9ff9b8a1d53124f1f5f551","shared_secret":"33b88b8eb1892cb5ba219992ae90fb00e0b126e2007641f4ba19596e62888f6f","key_schedule_context":"009c1a42b966625d8f49a6891417e3e774785966900714f2eeb46c4a861c46bc3e58d12f70c2229ee80fde4c8659579fb5777cbcbae107b5bf39630df436fca2c5bb9eb0c9438ce51a3d15506a2bb334f7908dd2db2484418f7c6ce086dba4dfde1a676a2c891d7ac11bdcc0c988de16be10c8b8f8cd38ce906bd92140c74124d3","secret":"5eac75f053e30d88634b7451fec8ff1df8182ed23c7be4df19ef206b1c48eb1f4547d5cfd0f18eadc9e538c2115df4e3879c3254d18582172e6a4d987301d742","key":"","base_nonce":"","exporter_secret":"14d860d2eeaedd0e484d66e8097e473d1a32602ddb8702df041c72a5847ce0e0397f144de680963a47749eb04ed2697cef507fb412fbdc09c7e12dc1e227df03","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"b06c9402d35c48076eb3d54d1dd90372c9cc99f913692e7659a667efe22824a1"},{"exporter_context":"00","L":32,"exported_value":"c5ab669d1b3b6fa487a7177031fbf208bd1fda913bebb0f42aebd217519bc8bd"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"5443e450974b1eb8dbfbc920db2aa3b4a187b39e3e4de048d9872cf9d6a80e7b"}]},{"mode":1,"kem_id":32,"kdf_id":3,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"21a4f9d3fe6310f8b2567b29589a1fcbfa6b153957f9ec0338f11c554ce8e59e","ikmE":"6c41d2a18d18abdcade82ed78b09ac6df9a10bbc9ad523b029bec174f36d653e","skRm":"aa858cc9060c241a975e4842df1f69f33bb5e83864a02d3576e780edbb8f3e18","skEm":"c36543c0315158c63f356d86d57428b3d0bba300b6fc81a063f3bb853b1f6503","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"53e696be80d159f82e063b9e59b5cff979641cba38517fe221008f90a4ed4d17","pkEm":"6ab9b8bff15bdf3e20a248ec3c8d5f5eec34e7faefa0d9483c51f66a38e9aa37","enc":"6ab9b8bff15bdf3e20a248ec3c8d5f5eec34e7faefa0d9483c51f66a38e9aa37","shared_secret":"84fbbb4de1f33be993187ff5328dc4911ac1a3bd9152fa7088a2f009abccea64","key_schedule_context":"01ea4d5f2659071c69c80731d91136e9c10cc3e4c5872ce150ce8e117a90f7fda90fffac95ff45e3c3d976ee37219e448533d94c8c956f5a45f3ac6361d27663ecbb9eb0c9438ce51a3d15506a2bb334f7908dd2db2484418f7c6ce086dba4dfde1a676a2c891d7ac11bdcc0c988de16be10c8b8f8cd38ce906bd92140c74124d3","secret":"3f8369c67f320304202e7effd0b58ea5d782a0f8c58a2c887d00bc54efc6a4ead81ebbf66260e76f5d116e0423bc9595aafdcad9f4cc746fe2c76ba0e21c804f","key":"","base_nonce":"","exporter_secret":"5ef52f9fe5007c682122ae67b0818278b8c0097aebf5a339cd21c050067272af5def36939a652263aee0702c9856dd082755ecd3fc8757e98e239212929f7450","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"3f70b7c151c4450406c97a117a1055a74b8469e9e6aa722682ae9fb2981d3457"},{"exporter_context":"00","L":32,"exported_value":"5ca0d17ea2722ff4c2e90854b3e92cac145d1ec915f1e4319720770e8306cd82"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"2bc2387a38974202720c1bed0c0a44f9cb4cccae36ed9677cdd8dd6d87c6ba49"}]},{"mode":2,"kem_id":32,"kdf_id":3,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"d800912a5dfebd5f403b4fad7714282c697eb60f178b67c39f517e0b8b43dd91","ikmS":"67c609cd356aeec412ad055bf610cdff6a3569c2d95009896280287c35829c4a","ikmE":"3bd0ac1420b6647ff3c1d26abe6fda09cb8ff802f9c0e878aaebe205ba4c4e30","skRm":"00db26eade017fb4f9254fef60665f63a781d545de6b4655fe08b642a58bbc8d","skSm":"b7d039a28af6e63bf4b63c382132ac2f8db4404f738d83214c261ea095041c90","skEm":"e0e521738633e191bd63a927ca12113a76c8362a9014206bba67a86fa5be55ba","pkRm":"4ab158d40ed5132a501b3aafe488f4bb2d9347946e57f12c5109f4d1d90ec301","pkSm":"d87b89922fc1196920cf4ca0640c287ebf7488af243ed34be93180ec67d7dc60","pkEm":"e918a6435c0805ace841e61d785592d9f44fb0c27a9c2467aae1706a0e7b5144","enc":"e918a6435c0805ace841e61d785592d9f44fb0c27a9c2467aae1706a0e7b5144","shared_secret":"612d32791ff19f61cdffb8cab7edde9c474e14e16c5ffa7b0ed78512474557df","key_schedule_context":"029c1a42b966625d8f49a6891417e3e774785966900714f2eeb46c4a861c46bc3e58d12f70c2229ee80fde4c8659579fb5777cbcbae107b5bf39630df436fca2c5bb9eb0c9438ce51a3d15506a2bb334f7908dd2db2484418f7c6ce086dba4dfde1a676a2c891d7ac11bdcc0c988de16be10c8b8f8cd38ce906bd92140c74124d3","secret":"1874043a4547dd034cf3c7b440d3c7f3fa1a3157c34bef534bafb29fdeff0ad716c5eda31e769f661c5fa3be821b3cd3e6e38d1e4bf90da23458ddb0723ebe05","key":"","base_nonce":"","exporter_secret":"5db2088514a58e3e28bac49cc76bc1d3d4665084762171cdaace1aa49cea5c64df543e1fba958f6b11052018929f490029286b2dab3367b972da5b0f855ca3a8","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"cd4d494d0af23e8bf88792d2efff3f1538f2578e212bc6b21dc99e9accf98814"},{"exporter_context":"00","L":32,"exported_value":"b1ee34063be5dbe535158310a8a7d9ad01b2e1661d7979de311f6ef104e1d04a"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"62104e826cd8c48a43e23b940954c6a9378105b76dce33573d43d459d83c970d"}]},{"mode":3,"kem_id":32,"kdf_id":3,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"872d8d6d8a4ea0f12c9fd89e7308c00d0f743d0c506018ee1751d910d7e83bbb","ikmS":"5d0e17ba926207b83eb7422966d4d5742d46e26cb4db16052ebc3d483c5a1948","ikmE":"020842efdd14e0214023040d18bcae9ad44e9f2f7de962873f5e78840ff1ec89","skRm":"e8505a85d87fdd0e811fff1724ec0b5a41bb38064d8e97de986b00f78fdff6a4","skSm":"4006f8d66511d213ea33dcccba250915cc6d023d0fef9d01348443661bade738","skEm":"a66e63d8160f8b2896bfba5b208e891780ca0653c824161f7a381fcb26a58379","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"745ee79505c6a67086a27d1c04777eee81fcf025dfda3ec795b9c29fe8d80911","pkSm":"4f0b40cbdec16e24277b65c5ef526113766914196ab779706c16d9938f420b22","pkEm":"331300288b2b369d9fb50ddeaa3609d32cafbe063d3fbbc1d7170178bf434d39","enc":"331300288b2b369d9fb50ddeaa3609d32cafbe063d3fbbc1d7170178bf434d39","shared_secret":"cdef975c7d53fa5cc710eb39d3261c5c14b4d4763cc9f937db2181ad8a67d2de","key_schedule_context":"03ea4d5f2659071c69c80731d91136e9c10cc3e4c5872ce150ce8e117a90f7fda90fffac95ff45e3c3d976ee37219e448533d94c8c956f5a45f3ac6361d27663ecbb9eb0c9438ce51a3d15506a2bb334f7908dd2db2484418f7c6ce086dba4dfde1a676a2c891d7ac11bdcc0c988de16be10c8b8f8cd38ce906bd92140c74124d3","secret":"4727e62729b7e42d53fc631570bf2165720bba4d46a85b3b1dae66197cb2165fa6f39ab3fc96b45144acec107a91376a7c55bb4fd453bba49d57013d11f05002","key":"","base_nonce":"","exporter_secret":"deb01b557032e962fcf395c7fc63cfac656d1df4ef4be62f57a18f3f16fa2da64d15bfabdcaba67267d972471a8dcef4e934b6539c9301e928720d3207bbd362","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"40518b8f9d5820af1768d35d446e8a55c78414677295891c57e6abec712b5342"},{"exporter_context":"00","L":32,"exported_value":"1efebb6bd0422479f89de39a01d3f5b5e8da606f154edf323c6896d35e9814e6"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"d38db26ec3b33946cf06c0d458620942b86534d43799e8d22d9998b203253f86"}]},{"mode":0,"kem_id":33,"kdf_id":1,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"ca5ef06aca5e68de1cf1c0389911e20354ab7c1cd20c36cb222ba1d807e78c0ae59eed96d04fba46c622d2dcedcf28e16e1330a3aeca3fea","ikmE":"1ecbfa27f1dab7bb48dcbad62111aec0a3e0b010c63a81f62295d03817c2876667acd271a00c565f5837d81cf6a0ef01142cdc7572644cf1","skRm":"11c67f7cb5b2a49dd44401a631f79cf6e7ed2c1ff48add94c1c574e241f882bf032ab96e655ed716656d4157057d13053273a8cb87c6ace9","skEm":"cddadbc86deddb92bbc131c8de14e6a85157047f40a55fea4336117f07af12e561d00e5bc0c050ff171887e3623411d35caa406d8c7db527","pkRm":"1781450d0029eb9c09e9afd085446e6ddda86c1f59f9b339d0361d4802f12a514b4362bc94fea3e68f27b2f3a18cb58b78197316aa5819c9","pkEm":"90528432976dbf44dfeab7b2f58bd90eb4a240c604e400a4f53629d0721d92f7ffbe29a9846d6607d768d5e10f9be29fbe3d7a2eb7c2b193","enc":"90528432976dbf44dfeab7b2f58bd90eb4a240c604e400a4f53629d0721d92f7ffbe29a9846d6607d768d5e10f9be29fbe3d7a2eb7c2b193","shared_secret":"8a3d2ec742e9926d9acbedb85c786740d9be58de50c1c166d9d308e84a595e8ea3f4e1becb462306eb599d888f0af6923c394d327aac05c70db073a77a72affb","key_schedule_context":"001106b1a1933067c87d4d746f7db5f197ad5107c4c5c2b8755555b63f50bf121e2030461bab15fdc38b55e526b9f9cbf3342bacd78553d0ce4eb4260c52b61d24","secret":"f3d234dc92a374e1e819940bb1e5d5fccb95a3524069fe584437bb9825325ae7","key":"8c23e0a7a4ab8561e504bab95e6b7477","base_nonce":"8994a6782c66ab1a5746ee8e","exporter_secret":"3fba9ba3d2424d868a816fb94c4343f351271ba5c546ec6fe5bdffea3188fadf","encryptions":[{"aad":"436f756e742d30","ciphertext":"686492a256992df0899928b77474cbe3fe07943816a639ce63fdfd258a2780bc54da99b1bea7d43304bc1b940b","nonce":"8994a6782c66ab1a5746ee8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"30b91165bf257d0434cc948d24798b30a13c2350befda6ef364bdf443da0b3bbbcba654fe2bfd9eed2e128077d","nonce":"8994a6782c66ab1a5746ee8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"8a236b1b40c25d7fa8c984dbd15a18adc8647993cdb370b9e3451675d81445fb237778db2f9727be779d658220","nonce":"8994a6782c66ab1a5746ee8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"de8860945f971bbcfca9e47cb72f845fe5869e2c1d3e8f4a8a52642f33ddc7f24bf2748ac7202c1c26cb187154","nonce":"8994a6782c66ab1a5746ee8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"d9dfb525ab7e76f0e4c0ab22dd918c69913f706e883ad905c9f7d2b13816e8dbba1280773c1c5329291e4ca5f5","nonce":"8994a6782c66ab1a5746ee8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"23cccf7325522a749eede01d4f8c4609addc7f71e80e8ce044ed5eac6fba732555aab3ee940ee1b5b506c0dd9b","nonce":"8994a6782c66ab1a5746ee8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"2aae1e5ae12d37a0f96a5a861c1b9f066501040c714fe2afa0a8d192c4a6625b5c0ddae9394ab18682bdc437db","nonce":"8994a6782c66ab1a5746ee88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"862b7268122e3f0f912b436363e404b49e2f35a9ba42686725082888d7e00f2134c5c8584103dd6d1196608d21","nonce":"8994a6782c66ab1a5746ee89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"fb6507156593f56e97ea615331f159ab4f740f5c9f73ddab218dcd9c8c71dccd069ca57ebb8b1806d0b4dc3d71","nonce":"8994a6782c66ab1a5746ee86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"076b0bbe049c3a686b4ab59eb92259a995b8695bcc2825d3378565145325e8b2ce351473b483020413d50a1963","nonce":"8994a6782c66ab1a5746ee87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"f339224dba2c6e7363df8033814a3d1060e401e76e4561dd01754d48eb3a8b4c9c80bcab7252036550a06238f4","nonce":"8994a6782c66ab1a5746ee84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"3ca2678308f8f2ebf670f5f8f5fe9e4c78c3af2e0a09fa930542fbc643e788242de2a7b2283928079c3c9d45ee","nonce":"8994a6782c66ab1a5746ee85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"1eeca692d5dbc526e3b0144d0d4d9f78efc85d9e044eaa4f2159caf84dc345d73eb5e30425275ca33ebd5e554b","nonce":"8994a6782c66ab1a5746ee82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"43713519333c87586e24a30db8c8450078ac8caab9fee5790158e23ceb864f230e278ece4db938df686242f98f","nonce":"8994a6782c66ab1a5746ee83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"e2d28015a9991d90c4b87035a369b71e3ce5719d55f393f18adc44524f5822b23d3a7bf39890961213450d13f6","nonce":"8994a6782c66ab1a5746ee80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"131d872301463f01ca8aadbfb7ca4c89778684ba140b12dac98da6def97992828bcac7da5fba3a223ec4efce09","nonce":"8994a6782c66ab1a5746ee81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"62f38c476d06f6c4c16b8fd546a102994a4acfa2072281cf316be339cfb876937b2ab7c3cf712cf34cce1a15ca","nonce":"8994a6782c66ab1a5746ee9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"b292ca7e8dd5b6e6fc4471eec7c4669b2f605a886bf74b5f04c0e40af82c3b19bd5347ee155e3ebfc8ab573666","nonce":"8994a6782c66ab1a5746ee9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"f37f6957137d80f14b89e4fdeb819b051fc8059d60df504d64129fdab5cadb913a6e5ab17d022977d2b3ac8460","nonce":"8994a6782c66ab1a5746ee9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"d61b774fad1da9b10cc80b2ab415f992892295ebe3ef2f51ab428253817052817059bdb2e59f179bd32506fda6","nonce":"8994a6782c66ab1a5746ee9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"b76cce77e012f1b5b9dcdd827fa2eaa8226f16fb6c2265f9a61ee0430a47482522b9cd3904c91821d59edceeb5","nonce":"8994a6782c66ab1a5746ee9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"4dfa3f9de5e42d4b4551679bb7c71ac3de9855b0c72f00c5acae0a8510519b72915a38112c72c3aca4a383b743","nonce":"8994a6782c66ab1a5746ee9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"87ce9e422f5aeb413eb94aa6c181538c45b3e123a810531251551bffe55298905d65bdebec06ea62af506ad6ba","nonce":"8994a6782c66ab1a5746ee98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"48108c7ace078f9c5bdd24eddcd9b258cc545ff0d6b36ce9d8008fc91a249446fe404abed320da363e0da6975e","nonce":"8994a6782c66ab1a5746ee99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"70ac0ea508d9bb590233200141decd5cfad3493a3c5f7f8ab4379d99e103ea0cb2d1a6110cfc9c03f100635780","nonce":"8994a6782c66ab1a5746ee96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"530063aede09e772b4a3ba73a286adbd2f64b6fdda528c6cabbe2930b80855dec667b36ebc7b4fdd6077b90e84","nonce":"8994a6782c66ab1a5746ee97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"cf8329a402059ff27b5fcb8772fdca2452758715275604a36884ef1274c35cd8ef71569b236c75a35d6b760e3f","nonce":"8994a6782c66ab1a5746ee94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"25800045446514fbc4fba781fd445f7248bdc0e6fa7285118cae68af5ae357803758a8d04c017a7b792a784c33","nonce":"8994a6782c66ab1a5746ee95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"e2749ba0f1fff9179d3305353f684f5d07c710aba163dc934b6dc7089d34cf63390e50258dc97f86dbe02e44f9","nonce":"8994a6782c66ab1a5746ee92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"d5f0c4cf5591948a5eba06808ec75cf964a7384c21cfcc2ca60cee190e9efe122a4805e057a1a1c8de5b740b0e","nonce":"8994a6782c66ab1a5746ee93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"e9246ad17b7b7ddede8660347aeef5063effafd275d698d6585504826453e676547054393c43be2c401d6f6695","nonce":"8994a6782c66ab1a5746ee90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"8ee3def1bea28cdce4aa78471af457e190869bc1960b6086b61143f588ce7b18155fd5457268ac7aa64819078b","nonce":"8994a6782c66ab1a5746ee91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"3275b8fd561b64830bb4b62070923f8ca660779663157ae382e0e91ebb892ae6ef35b60cb91fb401e67f91d811","nonce":"8994a6782c66ab1a5746eeae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"503747fbecc927514389cbb51dfcbe1d4f7f3197e09751862b37fff208a25a6c021d4a7b0f976c4f0f7ab5bb11","nonce":"8994a6782c66ab1a5746eeaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"a113b5204d8aba04b5f87d51fc5adfb8ec1ef0b9f6db5ea0cb87a57a57efb16466abdb9576cc9e647f0234733d","nonce":"8994a6782c66ab1a5746eeac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"27e1cfc9f172bcfda0515e74d47021807c2d8856c0e6d832cc539e36cb734f408509edbd9a8736b898fa5491fb","nonce":"8994a6782c66ab1a5746eead","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"973655a44acf007515f933937ebe02a3c202be3cda7f71344fb7b723138b7fab3639c31ce6b0105d5a5338c86e","nonce":"8994a6782c66ab1a5746eeaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"1f52571925c13dc04272db9ac166fef88b53275b0febcaca4a0110cb64205209855e260bf5b86b588fd1c48e1a","nonce":"8994a6782c66ab1a5746eeab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"5808b796ff65c0d11f6b7b5941bbeef529a0670389c74ef843e02696b669b82b16c1c96716cf743a3c0f5ff962","nonce":"8994a6782c66ab1a5746eea8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"616dea9d7235a677ca4e102ccb06fb3c98db449399ec03ef004100b8f104db1e961539569065ff6d98a365cb74","nonce":"8994a6782c66ab1a5746eea9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"3fce6666419509cb3fe9373a1ebfbfe58f732ba161191b6b1c57d49cbf7b0a49750d0a0724d654c86e4d38b8ab","nonce":"8994a6782c66ab1a5746eea6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"f4af2dfb59703dd66760cf5e40711c58b1ba7878435a0c5f5fdf2526e9e814ed6faca01766c60c368fc403039d","nonce":"8994a6782c66ab1a5746eea7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"9efb3bc123eec041c8396fbef56195a5cc9326d0836ff8f17d0972b62b6868120aaab2266934b5243870b68237","nonce":"8994a6782c66ab1a5746eea4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"93e6d74f4b4b17fd1a708b7fb72ad8f92472bfa7d13aba3c9e1d1ad1e7e391f18b967af3fa719ce5eede1c2f69","nonce":"8994a6782c66ab1a5746eea5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"c28c2eec1ea3f26dd5694fc4469f2d057e28f1788b59ce05e1b05a3ca6e356fd141ba21f06596ae719cef74727","nonce":"8994a6782c66ab1a5746eea2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"22f1fc86d8f608812d4c7c523339b236cf3dd774f90e462f33ad43f960313d7d5ec18c9a4f22f1527623020ef5","nonce":"8994a6782c66ab1a5746eea3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"807a7bd58cc2ee91c3a45e25f6dce2a32e1509062e4b06c2ae5bf10c995f7d582bd4ce99c0127683303e4ee51c","nonce":"8994a6782c66ab1a5746eea0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"9edacbe415b5365c2d8078103d81a418db257191c75edd25ba2e92a79556a3957bcfc2ffb0e19a4c5203cdc23d","nonce":"8994a6782c66ab1a5746eea1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"c529fcac22ef2b46eff6b95f474c88902e772c8f6215e63a15eb3f4a96ae7858996c24fa37e048565a47092f70","nonce":"8994a6782c66ab1a5746eebe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"bbcab2924671cdf5d6a1dd1d7c1e57e28e82898b0d487dac83abbc912feaa9306100a7fab56cf4cbe993ee11b3","nonce":"8994a6782c66ab1a5746eebf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"ab08e1dd7e030a46eebb423183e9d17e91b80247d77371cd5efd51a102b251edaf8ee49e7cd3b8b29689a06a63","nonce":"8994a6782c66ab1a5746eebc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"f11c71d1bcc9b1d19dee809747a912de11139809e922858b28073b11f65941f79c8070827c0755fbf0d780cc96","nonce":"8994a6782c66ab1a5746eebd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"76e83c0cb5c4a393a461a79495911023b92ee7de3439fb208cccb606c44bb46bb53655eedc361b6edd6715dab6","nonce":"8994a6782c66ab1a5746eeba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"2af8df8e992c16d961f417b54130d11101c0da709d8bf3bdc233b579a7b0f85d19c0ca1b8f69256a18a4cc5dcd","nonce":"8994a6782c66ab1a5746eebb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"2d724263f2ce0e4378f2697d2c650851d0214a2e97c41bebe96b2b333fe18e9702bd3b887fabfabf3741380f9d","nonce":"8994a6782c66ab1a5746eeb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"3c09e8231e715cd4bc2c762f0622f67cc6dbe3cdaa9a1e085f152fdae38cb136425701a1a8b5314f8cb1dd2935","nonce":"8994a6782c66ab1a5746eeb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"57083bf76417b97940ab492e5f1048e0ed7d6d8f904d97b9b71801711e8022b831c78f0f8eaab3019c40b2c885","nonce":"8994a6782c66ab1a5746eeb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"41bab19a8e15c6c9f8abde31ff3dc20f66485093ddb168762c9073108145780ac88272c43cd77ace262a36f9a6","nonce":"8994a6782c66ab1a5746eeb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"dad7e298d161feeec057cf49ba582a826480270afa6457c3b6fcb97cd2136dafa694bcb52496957af1f20d6c31","nonce":"8994a6782c66ab1a5746eeb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"44cadf5ca9d32c1fcf8fe2bf48f66594082fe4ac065323f71731431470d99f0f4203c608bf052a8420649dda07","nonce":"8994a6782c66ab1a5746eeb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"a87b39b0d6f48d913a451f255c203679819f160ff92c98c50ba1b6ea693fbc9c870207542f8990a4d3035579aa","nonce":"8994a6782c66ab1a5746eeb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"b182013a7a315f3c348f1dc6db83fe63515f28093307740f0cbcc35391ce68ac6bc9a32a86aa5599898be48e75","nonce":"8994a6782c66ab1a5746eeb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"cbb044670cd47c0215fe27b8ad6801882231046ed25f3cdaf90dca559a735dc4d9d5da5be13da9bb836a6fe729","nonce":"8994a6782c66ab1a5746eeb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"afcc96d0ba9a593aa04cb8377c359122c5827f8030f694360bf75cc7f505688cfab26cdabee213bbf7b823aee6","nonce":"8994a6782c66ab1a5746eeb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"005df9fcf830a2bd20641d7d18e494db912695d219b3f9b3495904a3dec7f9cde6ad0ee6ba8119a2be95346990","nonce":"8994a6782c66ab1a5746eece","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"48a74131d5632e48d303b17f1a093d0b37518c34af7cabc96e27117f28e8a8b98027e9c12c9e87937a5291231a","nonce":"8994a6782c66ab1a5746eecf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"db5699e80984c45825d101ce66d2acaaa3738d6c418ccd3671c53e5673629f5ff5101b96e9812e98cde9f14277","nonce":"8994a6782c66ab1a5746eecc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"9ca33823daadcf4a75aa1513df08485e32ae809013342e6df4db87b04d815cc9e6cf96594a3c0154e487a78735","nonce":"8994a6782c66ab1a5746eecd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"e55973bd61d0efb4b2135149c046afb15fcbf8cb2bbef4ed2e3f5ddd47238acc8b068f06a3aa6c8af406c8dbba","nonce":"8994a6782c66ab1a5746eeca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"8dc66bcee63f01d6861906ae0ac97cb316de8e003a8afebafe177a6f1d0ecc9f9482f25a427bd46840011c0d1a","nonce":"8994a6782c66ab1a5746eecb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"8b2a3798ed137cadfb9e5ae68485c107137fb715ca3db4c8bc33bc6e5f5eb6c8b1b60f463bd839d861f55946bf","nonce":"8994a6782c66ab1a5746eec8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"4dcaa276dd31aa4950485dde610fe1918d8630a3372dbf86758853c4ca802f1adc0a852378b01a25450d679a6a","nonce":"8994a6782c66ab1a5746eec9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"01f6f4503b60c86f8c8532db825777cf62e54610a08a4709b9df3f59713b081852c5a72db5d510aa692e934ebb","nonce":"8994a6782c66ab1a5746eec6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"7f5e0150ebec3b26fe187ad82a8aaac9df6e6330e50835626333a1c3ad9a7ea6d6bf38ceb4ed61fd8bf2a4bff8","nonce":"8994a6782c66ab1a5746eec7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"d8a8b1f6c0e446577f54edf944ef0f43489247f2bbb866eb6d9f2c414a7fab5da3b7bb8c7df5e1bfaa2319db97","nonce":"8994a6782c66ab1a5746eec4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"4f5dfdbfaacd2a6b7aca699cf4143bd3ea0803a4364f334d17b386cdf7abf2655077f1bf526dc091c719f38c3b","nonce":"8994a6782c66ab1a5746eec5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"277d72c059d9e22e3d67a37574b6e2d97cee84db3157380544d47f7c8600055d39bdcddc677029504964caaecf","nonce":"8994a6782c66ab1a5746eec2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"eb03703987051eabb23ac8f4bb0ac2d2fa3f696c44bb343ddcfadd9a172df02684c5d50293788f5417a5669383","nonce":"8994a6782c66ab1a5746eec3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"293c4fab459bf55624bd7bc5a4c7bd593ae2bd22f2998f0a669686d406bd1ca82c558f9f28e2be18f9fcf55453","nonce":"8994a6782c66ab1a5746eec0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"d37dd2041992e6839905773add20fbb7c6629ccd14edd01d4db28e9eccdf239c2da0ba06578672cade9a13493f","nonce":"8994a6782c66ab1a5746eec1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"1aac1b65463f1b66b067443c54757eb62276b6e9afdf2862451bf8fd86d0e646466967bd1dff098b991fb7b4e2","nonce":"8994a6782c66ab1a5746eede","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"6ff0d5603776bcf330ea182b313983031b260d736ca6e4fac5a0726abf83a1b9bc40cbd69c237eb56e581a9b60","nonce":"8994a6782c66ab1a5746eedf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"66d6673ac16d1388c158d5138eda090da78a11a0247cf57041b74d2dd6209e6104c66d4f5cb4d21f9d7a0b530a","nonce":"8994a6782c66ab1a5746eedc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"d74371ed94843ee161c2b4a86ab1ca66fa0926f64ca405d224281b3d327bd3621fa7a7fbcad71fa78b51d5e940","nonce":"8994a6782c66ab1a5746eedd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"53b8ea8878dc2eebbfbca7727ce1e463144733e428a1749f9a608566a6a583380aff08011bc44023386374b9cb","nonce":"8994a6782c66ab1a5746eeda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"3a11223ce9d586130588ae8fdf1c68e0b7777b249e50e4e9be01f88b42abb3c1191e233cf8dc0240a235250d8f","nonce":"8994a6782c66ab1a5746eedb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"f545249f365a3c0c928e6b8a8b05eef4bc9d37393785c9bb6c1123249474e11f973bd7d7ec44d41f83e3c0f327","nonce":"8994a6782c66ab1a5746eed8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"7a39de5c4169d57c4394b6ca63d34b37824f7c51049733f168556cabe002a28f7adda1d67755bb2aab5802b2ff","nonce":"8994a6782c66ab1a5746eed9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"2d160f1924c629132158d6a123bcae40fcdedff73f31c65154da25b750aeebef5e368bb309444771b6314fe615","nonce":"8994a6782c66ab1a5746eed6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"d4e5206dd38e2b334e915d99c57c08768474a40ec7fb13c90965d3752c22210559f60158e20bf79691b35a508b","nonce":"8994a6782c66ab1a5746eed7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"bda8bd9586715ca20a9744b65cd10eef427e8c62bcc16a3218a8cb04d74afaed1c8d0e81331eb6eda03326a27a","nonce":"8994a6782c66ab1a5746eed4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"725d484271b387325e86def49eda74c12ad7c8db04c5e026b5ff401291d87c28e1c198c8d3c3c9e21eb61e8bd3","nonce":"8994a6782c66ab1a5746eed5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"f7a8323260c7ed4735a89bee3da67bef62a3bffbd7a3f1f4eda2d90fef4e37159541ef962be60774a678dbf480","nonce":"8994a6782c66ab1a5746eed2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"c90687e2ff6e836e9c0568be18d30de11005b6f99671030e06934bc938f6c08260973766598d063982f4ff5da6","nonce":"8994a6782c66ab1a5746eed3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"904cf1c1b0a31501403aaaaffc6dc631735812c0d6ee8c2ef03475f80fe0676fa4c9ef8cc1b4afd09331f0332a","nonce":"8994a6782c66ab1a5746eed0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"2ed8e3d534831b093fddbe5077fa68f2d239699cb48e9b6bf5aec0a383c7824e416f5f592fcf88a4b4968a3049","nonce":"8994a6782c66ab1a5746eed1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"3cb786675834416a271bed43e0699b53e4524e96cc334d019bcfaa5b8ee37eae4a6ec964f96822a1d26e1935dd","nonce":"8994a6782c66ab1a5746eeee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"3428c4c84468b68535cfb68e1a0a5397b52a496d5595b03831fd3df6839e9355647a2155634fbe0f5c52fc6a94","nonce":"8994a6782c66ab1a5746eeef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"36d9de77b4469e415673a3e80400d5766742429661a22d502896c4871d5cf173ef337cfba6b7f870f3952e4075","nonce":"8994a6782c66ab1a5746eeec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"64231374be4f6c0e0e51026abc494a863dd6a0f9e34e3cd3036e8f74932912b24f82b1b0fb8ee2744e4b24bcdf","nonce":"8994a6782c66ab1a5746eeed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"1497e854c1e7a9472c14f56cfc597ec76c98667ee3ba325291f8e8626109d6bd1c7d2a12d811fa176480dff2fb","nonce":"8994a6782c66ab1a5746eeea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"3cf240742ec3b935d9adde1aa616a6b47dd2a9726d7715bf067d0f4d0a4eadce45012764d609286919d1e41e88","nonce":"8994a6782c66ab1a5746eeeb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"cc6167f2c42421bd997c27436dde1dd9932b08f84fead78faa5eb7697688ad27beef80f81ffb0171688a3259af","nonce":"8994a6782c66ab1a5746eee8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"c6904dd6d3517ee4562add6b9f67fdb3013fdba94832d8996a66c8732fa2f108a82dd4f229bb5f50bbd2b950d5","nonce":"8994a6782c66ab1a5746eee9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"3143788a38b8fe6972d4ccf0aa37251dda09469ca74b2679fdd18d1049fa077c455c860179828f6fd05540d8d5","nonce":"8994a6782c66ab1a5746eee6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"98bf689b6cd6511dcde6b89bb7c748955cc57a1784af887f0ec1df1b43d453a791f72d32e51669b5394463d160","nonce":"8994a6782c66ab1a5746eee7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"8ca1c3d18e263d7aa8a3daad09e0051b814f2421b43434e86654c832ba7f2190202097598afb65e2065178ff70","nonce":"8994a6782c66ab1a5746eee4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"fa8741f1833fc96e003173ff9a7c5ebe5ec7abe5d0410724dee38b5d4fff60d3486bfbcd35b41067f7f8b3083a","nonce":"8994a6782c66ab1a5746eee5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"02c6129374234f7b9b2b67635da26fd4bca5a522871ea497801f1a0dfacd1ae51a818e8b58b17ea86d26713835","nonce":"8994a6782c66ab1a5746eee2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"06ad1c4288897d794545e711ab052c76c05b714783e9a3be4879f4613215f3190de0eef3cd1ea462afea2073c5","nonce":"8994a6782c66ab1a5746eee3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"5b83755df9c698b17024493921fca11705e47602e7941fcb8b4ffcee45984d90ba178ed48f07e20309bb4ee2cf","nonce":"8994a6782c66ab1a5746eee0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"479cf5febe0a3173536c7b97c2106e2bd27903d0c0ba087a3ca1670d1aef470072306209bd336843d751c89e86","nonce":"8994a6782c66ab1a5746eee1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"61a7d8deb2bc8d1ce50f76d13c1967b5ac1440b5c4b7c476c7355ec5ba8582cc7c26e81086c85c8c31e2ee6f88","nonce":"8994a6782c66ab1a5746eefe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"a4e704038b5d1fecada995b010c7267278a43d8b2b7a9495d764f8dbdde5998a687ee77e7884d291d74828447d","nonce":"8994a6782c66ab1a5746eeff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"bbb3e06ee7b3d6ae72930edc1bd62692ac4c4572a3e7ae6c8ccfe4894bff100d5219cc5e4c775265501a7f8d9a","nonce":"8994a6782c66ab1a5746eefc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"dba11fa1222a2db740277412ed98376a0e5af4ff897b97a86a48c760a7ea33619013b2bd4aba1ede853c25e3ff","nonce":"8994a6782c66ab1a5746eefd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"59450eb9bdea97315856e658fbc56b8a5c5d86dbefe3b8ee4c529cc57498e8c92dcc1e5bf40920b2dfacfac18a","nonce":"8994a6782c66ab1a5746eefa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"c965d84e69ce96223508aa2ac5f6b8bfabd26b02e4156942d78c124c4029fd50762d0836fe68a61bb33b81c3b1","nonce":"8994a6782c66ab1a5746eefb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"c919dca45aaa5a95c4b68e900532148b23429d871d1aac85e8ae252127003102a1e7295bc9a31a388673b23bfd","nonce":"8994a6782c66ab1a5746eef8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"06f173c92936e66326023eb252b42e504db57ae93008444e72b63a1e79e1c3d14b3330e7c8bb1c242eb7c06d2d","nonce":"8994a6782c66ab1a5746eef9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"33bc663a62e542dec2ea28c84c0ca542b4789d2307f42cc942f95c91e162866d94c39d97310f5f52051e54a98b","nonce":"8994a6782c66ab1a5746eef6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"5bdf228294c34f26f1a5210d0bcd0d64a7aa4c0f51bb5f84d152cd70aa10c5798c1e661850761c76b82442d2d1","nonce":"8994a6782c66ab1a5746eef7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"ea7ba7661248ca94323fad458461c7a1ccc4ee3be054267f8eaf27bacf306688c46ee58f42bb0bd1bbaa92402f","nonce":"8994a6782c66ab1a5746eef4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"b80a07aa9029d7757eaa08f1838c9377016fbfb8447c0277ee91aa3af1a131214a23c26af5a2666b04c5576a6c","nonce":"8994a6782c66ab1a5746eef5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"c86a01e15e76c076304f0af92a821c078e1ac2fbf0740ee8b5f28d220c6e8dd54324cf29f51c08e291a8a59a6e","nonce":"8994a6782c66ab1a5746eef2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"4b7fb53daad16958837aacb5dd5c36db88f97605100d09cc8d6f167b00e9ce120c3f371de12efdebe3c773a10b","nonce":"8994a6782c66ab1a5746eef3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"703e8f456e4ef7ce903cdc1f8b1d4653b56af146900ccfe3ff4b55cf26d2f9376c9c634a7e1aa9a9d207b4ec07","nonce":"8994a6782c66ab1a5746eef0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"20722cce6ab63edb9eebd9670015c8cad1100dc03543d3150c559009c87380d8e2d54d0a09d7612dafaa3170c9","nonce":"8994a6782c66ab1a5746eef1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"d53ecfdef2917c7f1a7faf5693f203a13b20f4a492e368ea78b94d2fece10a8c76f004e0767d93e120dff1068b","nonce":"8994a6782c66ab1a5746ee0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"106abd4e4576e1a23be566b88a8272a5ac3a9665979f6ed319246ad8e60ae51d3b7e3167813871bddb71311e3c","nonce":"8994a6782c66ab1a5746ee0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"c4411f6ffb7b3e0497f5cb9896e7a45398d2c6bc309c35b60289fedb46384c9a6b7f477dd8c06d4931721a7f6e","nonce":"8994a6782c66ab1a5746ee0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"b2b5f605d97b292170e9c259b89bbf5843c5bdcc427023e83cfd46cebb5b8736dd2fff47e16307830d8cbeff20","nonce":"8994a6782c66ab1a5746ee0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"1c13e4974851089ed186769b23b5f89f7a2382703ca1422b9787c1f4fa91d0dfafb9216ba627ed6fa9e7f136b9","nonce":"8994a6782c66ab1a5746ee0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"335ab67d15425d89057fbc3b2d0123f5d3bb2a4a0cd7f02d1d1fcc2e5bda20c8f69b695de5db272e71b3b50cbc","nonce":"8994a6782c66ab1a5746ee0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"def7a05e6bcc92a841d20980ee79bd86f78f7163cac206e5bef122f0b006ee3b702d37a2dcb535496a6040700d","nonce":"8994a6782c66ab1a5746ee08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"8558d26df7f1c0d0edb3d87860c3d26b91dc5c741c739deca8677cdb29167084bd92b79e4a6f1953a90a33f35f","nonce":"8994a6782c66ab1a5746ee09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"e3ebbca7aeaa7d163cab771dffb2e33d1dfa108ff8233604312573ce345501ad8c006cdb12a34518922c7a319f","nonce":"8994a6782c66ab1a5746ee06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"ff28cfec2803502ef887951bacd426621cbf45b72ebe15372a63a8f2673f2825bbfb7ef9821f879c94912821fd","nonce":"8994a6782c66ab1a5746ee07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"3082108b9cc70f92f7d321b8390335a8e54e95bca00507e973c33c3ce902beb8cfc9b493c926f8c4545ee9a196","nonce":"8994a6782c66ab1a5746ee04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"6768db979a0c34bb47c7bd8be8887a240428c6f1b2c5a459a89865efa946e7125c148b4632f3ec3f40087f673d","nonce":"8994a6782c66ab1a5746ee05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"1bc1bf09d06f87ab66fe4b09c4e018b8945561cdb3825d0c7d754b2e8fad9fc6f397948b8ff9ceb1ab62706372","nonce":"8994a6782c66ab1a5746ee02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"bc9a6dc349ae733ee4f788e5bc4cb996993d093f84c85a701987fd9a37989f87b7c6173ecefb46bb3c9fc58db6","nonce":"8994a6782c66ab1a5746ee03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"5a7756c8dd096bd70b314c34c42eeab0d74c27e048ddc433867eba2846b2779d586dc186bf9edb8fb9b3a6927b","nonce":"8994a6782c66ab1a5746ee00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"d6a8be67accf025a313945c377f5915391943f1eb45c000d41396d4e635a9a8fdb40046d882a569429e15de4a4","nonce":"8994a6782c66ab1a5746ee01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"9f13aa4c16f14e6f19551842a33cb8342ce85c1cde78dbc207fc7c5a12b3ffd5bafb6ece7dd7a99a1715feb4a1","nonce":"8994a6782c66ab1a5746ee1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"7817a6614bf362d65452136cd9640daddeaaabca03d0335e44793042f41e309b08b77dcd414ba781a23de8d915","nonce":"8994a6782c66ab1a5746ee1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"acac278e92316088f8b156de85ad168fdc42626c90726db7696e87e994d6a0fa403d90a3367d16006b11f3ce11","nonce":"8994a6782c66ab1a5746ee1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"91d07d1759689449aadabcaeb77dac903d897625572b51ec022673404cb0a64c77e344e632e43bbe024367cf9c","nonce":"8994a6782c66ab1a5746ee1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"0ea20050effdaf1aedca38675a90a97bdf50994a788e1d049148cbfcffcb8831b243991869ccb4659941dac099","nonce":"8994a6782c66ab1a5746ee1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"70b2c1ed156ee6a3456cd3d437552ae1c7e9d48c11d956924f00165619a637f3ed0e88e01a521c6a9be70875eb","nonce":"8994a6782c66ab1a5746ee1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"2d25f642a617c28ef3ac4c151555fa0f29ec4b727358d4f59f8bd66d4df907761d828ab7ec76f3264864b835ef","nonce":"8994a6782c66ab1a5746ee18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"8c3a9288ad4bbb69688b17d405c5de0a0a9953f374e22a815526b39392404cc6d882a5346cb86a77ff00a167b5","nonce":"8994a6782c66ab1a5746ee19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"e0d64f5156ee8fa6aa5a89c4d4932497aabb2d34bee925ddd34a24de9744f08cdb457e8c420672bb1308c04b6d","nonce":"8994a6782c66ab1a5746ee16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"7dbcc391151f526ee2b13a73672367f5f27e4fe980d1562981f750ec28e5acd87b7e1aa4c474aac7b6aaf1b4b4","nonce":"8994a6782c66ab1a5746ee17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"fcdb01513b599b385bc3f9509a7c9233b61f263188a75d6c7b8578961d1c724e5c1903283a4c5baf21ee651d38","nonce":"8994a6782c66ab1a5746ee14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"51bad0e45317e7d45bedec868496fd21a64b95d474acd81b1e3c671fd41e9feaa16ccd9d0209d1a98bac5ae9c9","nonce":"8994a6782c66ab1a5746ee15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"998cabdd0dd32720451673c286be5a78065915cd1e803d8c8a5b79f73ca167fb574fabb06140384e1e80240bc1","nonce":"8994a6782c66ab1a5746ee12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"62a1de3beffd8630048e4f57843a3ca77e7367543eb55677c5cb7e4d7511c1762e7478aa7d26dbb68b700f929a","nonce":"8994a6782c66ab1a5746ee13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"fc0034c8cac79c3e4d5222bb18052b82d09c651ad77823badae256df01010d237111e3a946606609778564f4b8","nonce":"8994a6782c66ab1a5746ee10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"3e2400877685a6e5c45610e836d519a4d405eb5915e1ab604e09270993ec1cf02450fe2a84bc85f67af23cd7f2","nonce":"8994a6782c66ab1a5746ee11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"262222325ab586549a517de95d4abce545b948c5258bf87c15a895f5a057af6e03532f0bd65f1cc45657bd1ea5","nonce":"8994a6782c66ab1a5746ee2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"1dce3a314fc7f4489cec17c66fe8223dba696c83a831b8b3b4f7832f7c7a42792bf72f8152f12d4c88f78bb603","nonce":"8994a6782c66ab1a5746ee2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"fb551d836c6eab4c5b1800d142311607d39ee86d2767f3a55d935c74542badbbc5d6620eca21271b31c7c0f035","nonce":"8994a6782c66ab1a5746ee2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"e1b441476d954fdf3be12ddc27bb322b0b7c43f85d3d8bfcf2f6c82e2be9912361b40622d7a3203954ad9572e2","nonce":"8994a6782c66ab1a5746ee2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"353292564beb2df104810d039e69eb56eda2a3b7857fed0b55f4d00ad8a2ca9141d5985bc5eb542b4971da98c8","nonce":"8994a6782c66ab1a5746ee2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"585b5d2e3c41068db1268a9498923f8a36721c56359888ffeabce42473cfdb2a8c43dd2e725436f1a374997cd7","nonce":"8994a6782c66ab1a5746ee2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"c976a9b083d9687bc0719e4d57d5eb458d5fe8cc1e45ab4227fb9c2ca82ed0486c465f4455680d38158a6cdd76","nonce":"8994a6782c66ab1a5746ee28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"c0f907f15bd6e8d3f02df55c3d3e0bafa428474b6658602b0a76d80ce0d3fdb30b466b7263940f2352837d3640","nonce":"8994a6782c66ab1a5746ee29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"3fd49e0078e696bd9541aa4bb94261b1ca7e6599b6d3cca73983a2a982b206e423ff1d715bd9be8486b0a1f88e","nonce":"8994a6782c66ab1a5746ee26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"f32d2265d722a99992aad212a5c641d5647526d4f5d41d616527129b7997f22ac04beea579676a79b9cd4e1a57","nonce":"8994a6782c66ab1a5746ee27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"0cb14dac274c39cdc613f5703d99261eb15c174f9282e7dcd2dc7dca586b9b9ae192a91090fb64c5c97fada773","nonce":"8994a6782c66ab1a5746ee24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"70079763b3857aad8f24277ce178a1c242cbde42bfc65f8048c2d5e068dcf87925e8642d1ae4bf86d9ef52b3f9","nonce":"8994a6782c66ab1a5746ee25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"226dc4f44005d26fb83096734b9dad2699af94ef86ca606181723b2f4dad816ea237b7746d213bd1c44e8fce21","nonce":"8994a6782c66ab1a5746ee22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"0d6cdf8ffd2a7a2844df5a8eca78c39cdebb4600076d9d89a17d23f90301726ff5f0f8dc80e9b3951c7a8b0aab","nonce":"8994a6782c66ab1a5746ee23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"8828342364cdcb62227b1fdfb7a6441cbfa6586b428bef0fe42d5ecae6943d96b62eab2b12574d9a1d343649c7","nonce":"8994a6782c66ab1a5746ee20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"a538d03247d1d1ecdad1a1787c112cdd684d51ba9610c77f860b36292b8426f588f67a19bfd36df45fd798cf0b","nonce":"8994a6782c66ab1a5746ee21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"15384a1114f2ae285f0e1773b5eb1b2e7f3bed14400aca86cea11ffac4e91a23634651eb95dfe258ca69b9c4fa","nonce":"8994a6782c66ab1a5746ee3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"eca2f4a0338eac321c557f154eaa08309103283cf2779cd5d85f1fb360a51108e5966db46794ac88d0494a02ee","nonce":"8994a6782c66ab1a5746ee3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"84c74375839d260c37a9254b72df6d507ce7359b9446eef0f0d1e3b48a5a524a7516cb20415c9d72fa7fb1bd67","nonce":"8994a6782c66ab1a5746ee3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"8b728dbb556894a6123d76a38cbb71948bd93fe2e731cc8d318ecdbe3ba3a880c333c1147fb7f6ccd168ba314d","nonce":"8994a6782c66ab1a5746ee3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"504bcc41e4280e7a20a4cad369f0b93f643b91555da92e70edbe329575a081f74772906a408fda459035ed2650","nonce":"8994a6782c66ab1a5746ee3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"327e6224dcd46c3629e70dc674b45463e96b9f3a892c69830ae87a08c09abd532fd853849d47891999e2a24c99","nonce":"8994a6782c66ab1a5746ee3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"cf3403d11168859f9cd98c813d1643da4276f96c3e95c8c09e195114f1f27c34b1224f32f98d7689f712aeefce","nonce":"8994a6782c66ab1a5746ee38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"badf1703d92dbc2958dd86340396ec67c509719f9f03d604ea2cb7b5a20b5733b0a0b40bbb0411b44bd3dff1a9","nonce":"8994a6782c66ab1a5746ee39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"48bfc38a593cab695f133acb025bb264b9f2b9f3f45cb7839b7c6f4c3b6e0a5581922eae2daff36e6c0cdb2fc4","nonce":"8994a6782c66ab1a5746ee36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"b5dcfcaffa7f89fd1c260ca2c1631aac33c39f1d6b9d41a773aa833ea6244856eb94f730e519238eea586c60df","nonce":"8994a6782c66ab1a5746ee37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"f0eb028b7a7f15ccbde0ae121244cea5952e1b747d85af8ca6c6db4c1b534bfb52ac20b16b1f193f334d179528","nonce":"8994a6782c66ab1a5746ee34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"66409ce13af6f496461bc5caba5d7202df5e344eeae26c01a5342f99cd208ad256219b0de66142a0d00d20199c","nonce":"8994a6782c66ab1a5746ee35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"f5eb1e8745f2c37e49a11cf4a5008808f2d73ab9ae4626e685d2dedd061ae911eba29e56b6697d4cbbcdd44a63","nonce":"8994a6782c66ab1a5746ee32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"8b1c2148e185062e9018d87226caecacea738bf3b513115bd0af73755f75ac1eb59f9dd5a590ecfde825aef3d3","nonce":"8994a6782c66ab1a5746ee33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"ef45a4eb7939e08c6512bf4a3314bc7e7d2d40027b748700c778a10527f98765a90c0a9604df1dbdb19da073d9","nonce":"8994a6782c66ab1a5746ee30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"28c4e223be2ce48b394fe35ff9de5bf4561c8ce398543649838735fc54fb4e69368c78bf2a1bc745e7192c729a","nonce":"8994a6782c66ab1a5746ee31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"d78acf0a657c8c3d6b5d9925b93e82445308e5a7fc6921684ea024287532421a9e6bda63af5aaf530ce9204900","nonce":"8994a6782c66ab1a5746ee4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"fe0a720a22b74d696e922727e452df281b7eaa1d4df1d239a2425911de0132853882728e0bbbae67195eded8a1","nonce":"8994a6782c66ab1a5746ee4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"c5dff1b7bb6d364a497f0587514c8e87d9b1ed1b8c90a9bc9d1bdc0038ee163d5ae66dbeb0b829773e7b362fbd","nonce":"8994a6782c66ab1a5746ee4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"5d3867159d3c6bb3a44ee67f361e23560b2a1b970a5124455061cde6e9404fd0b7b1d5cd99f62569cbf4ea9a4a","nonce":"8994a6782c66ab1a5746ee4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"e8f968ed12c7edf1779c8aad8ff150c4e534bcf9986a3fcf881a1ad8cdb0284f004090c331c69b23ed37fef89b","nonce":"8994a6782c66ab1a5746ee4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"daf765e3630964aefb60a4cc535d0317cfb0a17c3639aeb7e180d35a4e6d09109e05fd867b0cd8f21239d679c4","nonce":"8994a6782c66ab1a5746ee4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"6a9014074b1372fecf4ebdc8764884999c0ddbbd3532791b0e8f777f35a30c5e261f7c3d1c9357dbc78699533a","nonce":"8994a6782c66ab1a5746ee48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"7c99d053bf57b1e6d2f730b52ec0a45789750f85f059d539363f2a885761ca46300bd71270b207a6317255a3ae","nonce":"8994a6782c66ab1a5746ee49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"63be2c0738e8d3f7fb88640df33f57699138bddb8b3bb1041be7b372029ed6c94c0ea4e7d3b8446887bae1d591","nonce":"8994a6782c66ab1a5746ee46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"d911c7b636900190fd6ddc74601cb52fc25fc27b31f6355570820302a857ea0b2884261375d4745625cb9ec363","nonce":"8994a6782c66ab1a5746ee47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"2b619b093b10377f6fc271fec6004a3d71b27143066a0f1b4b4e13115ad2fa61393e7dcc40c0997901343a78f8","nonce":"8994a6782c66ab1a5746ee44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"314b0dfc0cef3d096263c556ffa05345a640d71ae02fdc73eef57f0640d4c163ffd0c5fe0db1c22ddc7390b060","nonce":"8994a6782c66ab1a5746ee45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"15222da359ac11ff69924147ace410494a2def4847725d93f5333f2e6222c88363b16605718b7223f148540fd1","nonce":"8994a6782c66ab1a5746ee42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"64c95b42a6cc28c791595634d084442c09cb3ef3268a2a6c34cddde739b1ce92db9a6465c41bf94ab40f63bb7b","nonce":"8994a6782c66ab1a5746ee43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"3ef5edd7bf2883c3377daa1bbddc963c671ac84502b93ee9c389c4f13b9b673564f9f82dda03c7e7281ca35b39","nonce":"8994a6782c66ab1a5746ee40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"cf087f4006921e2dee5486c3b81148f68b096dc9fe6008521585708bda49656a1e54957a0703d67c6487bfd75d","nonce":"8994a6782c66ab1a5746ee41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"b6124b2bc4153df3f76dfca37f9e2f8cddf1d93fcf90938cacfab57963b664aa28f2ae1bd00570756be7692b30","nonce":"8994a6782c66ab1a5746ee5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"ef921a6fa4b605ddf6fef03aec6addbb38267752b7f13be670e758bec94eb85b40e02f72d93e96a8899c0b569e","nonce":"8994a6782c66ab1a5746ee5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"364593942d2ac627b34b713087e10392bc94dda017775060698d648c146ee355a3ee545ecd5dc21f556c5d3cdf","nonce":"8994a6782c66ab1a5746ee5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"26109b28a3c6603ebbeae49bd4400535e3b56ed02df735277d40762263d5462afcb4014c7395c2d5785efe014c","nonce":"8994a6782c66ab1a5746ee5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"820437fc0776ddfe305276e37ad2a8b540167bfc0bfab2958c10f0b218f2e5f6afa227939d6f36f4d31409d745","nonce":"8994a6782c66ab1a5746ee5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"eff39fc08740d9fde11d484ee99c283323de44f37391382d432e7df2364f603a75bf977d4553b517ce56a86634","nonce":"8994a6782c66ab1a5746ee5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"8fdbbc430707d17c5545a10797b16d6453b76d4df033e752117a36196652c1d2f6556224e356994bbf2885651e","nonce":"8994a6782c66ab1a5746ee58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"1864dba9215594984cea074a8d818135cd9dfc2c4f4fb3d4e1e46cfce1c55b20dafa08e4dc2243e3850ce6cfbb","nonce":"8994a6782c66ab1a5746ee59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"5a60c9521120bb87301f2a4c19fa568ea7b7e47367fa5587fe5479b4625e23c3ac6987a77e05d14dca31cf8796","nonce":"8994a6782c66ab1a5746ee56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"f0755c92452a2134a66c8e6db055b35de5cb46b51c54c7885e4593b238166623771332556b1cea90be6d239954","nonce":"8994a6782c66ab1a5746ee57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"790232f1e1e746dbac975b97cbd6bf76f0ffa4a6b64b8bada96e427dd0ae83d48ed5214ee89bff3df6e37977df","nonce":"8994a6782c66ab1a5746ee54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"8e8d0179ac54f189577623e7c4a0fbfeec88b189b3db70f9874d87808a58671e79885245411a8dc37fef469999","nonce":"8994a6782c66ab1a5746ee55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"23f147cbec008d8bd544f6f80588c79efa91cab60d676808c1c3fc5b18e91e7e79eb65d30b562f68e55062385d","nonce":"8994a6782c66ab1a5746ee52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"7c5df9aafdda5edc300d2ed6601dae941fa42fa282446feb70913408827b313ee7e83b3df3e350a3c64932318c","nonce":"8994a6782c66ab1a5746ee53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"6034b587784a424809d3604815cda06b8ce34ba299ea9df4298295787ab7cf655a147e1da0ba4ea205ce0386fc","nonce":"8994a6782c66ab1a5746ee50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"1585b5af7a9a809733dcf5553c55573fbc4e0c3bb8ccca3f0dd82689c1465678fbe4964b7b6ab73b23b33da7c8","nonce":"8994a6782c66ab1a5746ee51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"66322099ffa5d4a0564cc204df57543382af88c84bdec621479163b2c9061deb944f3fc5e251d4759557ff0334","nonce":"8994a6782c66ab1a5746ee6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"4220693197a550fd7dd1fbaebebb8243610b01abec7a1a17316fe0ae9faef60a6f163b858f6a52c83a0df3d3d1","nonce":"8994a6782c66ab1a5746ee6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"8640143f1f6eb33067093222eecae38a85964ba1150a99372834eb8f37b899e89897a8877537443b1c5ea5a035","nonce":"8994a6782c66ab1a5746ee6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"ead8b1ec978c9513483cde57b8482e1c0afa22e2fd944f19d8a2cd1af55cc201b4e46892368472e73695149b8a","nonce":"8994a6782c66ab1a5746ee6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"1d06b213384e807f7c9c065e1bf6dc75ab195a14f954d011c83ab7f13f290135e59f31dd682a866a17fe69dda8","nonce":"8994a6782c66ab1a5746ee6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"f864442868f5cdad45b035279b2b1e781d16d487777d086af7ed450d5acf0c342ad9e5fdb046f7b269b6548f78","nonce":"8994a6782c66ab1a5746ee6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"d2573a7fa5ed45406d7cfcdfff6b951fc287443acad148f50b397b53c415a6491ac3431c5a7b2c679ddd78a2b0","nonce":"8994a6782c66ab1a5746ee68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"a5c33433672409c85067ecc47071787a9a583a771bd57fb0fe880ee681598b64e4b51153d249e12cf0a675bc96","nonce":"8994a6782c66ab1a5746ee69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"0f1aced0c82d967daa9d89e0b0e6ae96cacdfcaaf710646deb410b36eacd556303dd0f05f23e7b21644833bb5e","nonce":"8994a6782c66ab1a5746ee66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"58125066aaabdb3a4f73b34a7576af4b040cee08f84cb6431a02700c80bf200e5e53b1443112034a8f45a38d98","nonce":"8994a6782c66ab1a5746ee67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"0392c0d415f64b6c76114a78961a8106081c13e0192933017a218b9bcda1182f259cc56fab6fc5ee25a2e872da","nonce":"8994a6782c66ab1a5746ee64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"aac419b3365d4d6018fed45748f82d859f0d58f18bc56e27f3e29a609207e58229bb8db4c6018661b4a238c20c","nonce":"8994a6782c66ab1a5746ee65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"7fd1f662c5f770b4cc10100e91292942314b9945f17cfa7873e00ef19731462815eddc45d189a668d1d094ecdb","nonce":"8994a6782c66ab1a5746ee62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"426e3266496420b778ee9bdc3b5dc2e33f0a553cb0ab29ccdc2fc2ef47acd5d113004078336535ff407e7f6ccb","nonce":"8994a6782c66ab1a5746ee63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"d045cfdffff6c87bbdd52e092660a846e8bb4de337ccd9eef99c22d85dc6a4b04c3c8db77e2462e29ed7302e03","nonce":"8994a6782c66ab1a5746ee60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"80e813a99009daa1c1fd87951e87a87bf7792d29338d6afb3f633a39cb535515c87d1ed15a015690a39337cee4","nonce":"8994a6782c66ab1a5746ee61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"acadb937bb1dca024bcf8eec0bde5a53e806e37ad3e61f4cc409b5e1982b89f11c6ce2951007175cb5beebd4ca","nonce":"8994a6782c66ab1a5746ee7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"7912dc20c6486e8a079139e6fea3690e392078a4708dd0ecd51640d711007bb1a45f13477df85c4c19326edab1","nonce":"8994a6782c66ab1a5746ee7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"6891f5d813e41d6aba8fb6f28eb404e1613c23287cfb4a1f0532f6d84ec2e5e5848f183685605da73a6824f0ab","nonce":"8994a6782c66ab1a5746ee7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"a04ea7d1e6c0925f5f41498ebdd113262a5f6bab3af673ff958d7a2586fdd68d37cbc0d9be082f218c58700306","nonce":"8994a6782c66ab1a5746ee7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"455a211c915fec9ddabf2762d1eb3e0f16527af4bc0362bb0f2c64bd17dba542d0ebfc57c0ba0166beded5c50c","nonce":"8994a6782c66ab1a5746ee7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"4d3edef691a45f4ceddc5177f4d82bc9fda22a179b666ec418fd4781529bbc5c3b1fb892ff9248b88795965f7a","nonce":"8994a6782c66ab1a5746ee7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"de91d8688b4501267a9b31be5e465b652d584b4f063764536045c6bfb183d4cd4979f3c7b967840e27dfb12490","nonce":"8994a6782c66ab1a5746ee78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"dbf8c7bbe52de9e7cd5baced69ab71c9bca117b1bd5422c3e02286267bf295bca0a71e1613723def33f093fd56","nonce":"8994a6782c66ab1a5746ee79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"7ffcdd2c45de025d2cc4a1bb017daea13cdcec5772aedebfef7a9402f9b84e507392eb439e0fb1642e7278c033","nonce":"8994a6782c66ab1a5746ee76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"d9dc5516e6899a874e9f1e7c2b44116c188949a7826bd3144a5b479389a17e4b52d8f1f0c35b3707a2f34cb52a","nonce":"8994a6782c66ab1a5746ee77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"7cd7ceac5a1124ce701cd344f93602e78dc2149a26e710e57dbc1c64892a81a97d89db29e92449f26809d231a7","nonce":"8994a6782c66ab1a5746ee74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"dc5e88865656d3be727b5b87a888be379d7ec0931a80bc2e2b54dadc48891e7b3bf0c3f2c98fd819fa0375286a","nonce":"8994a6782c66ab1a5746ee75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"66fd47c78e6ab1566ceaba066ecee36f23211389b7b4bb4f7c3222d9672272b2c428e02c0eac03dacd7ee4894d","nonce":"8994a6782c66ab1a5746ee72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"fcd021f547a05709eb1c5f9e8997d0328b389cf66d18d27405d82142f2c245265b000f8a083ad24f5e55ab8500","nonce":"8994a6782c66ab1a5746ee73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"0c27f2ae303bc915488ee9fa37ef389589145d04a75c80844a9dc06389915cf47cebb7e79b3cdee45702b6bef2","nonce":"8994a6782c66ab1a5746ee70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"3eb90abebce82496c4c36e4c0d17ea920852e835f75a280eb41104875469500117557bc5279e69918f61312516","nonce":"8994a6782c66ab1a5746ee71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"51c90cb7de55fd3c8ad9e90bed7708380dd48cc3afa75681f2382042f2c7762c788e701fac1625f246b2122792","nonce":"8994a6782c66ab1a5746ef8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"efa2bd7ca5de26b536fadcd63088a2ad94f09635d763165a73de589ab26ab626"},{"exporter_context":"00","L":32,"exported_value":"b76012181c3428471988d8a39fc315b9d309a9ba724665b47d3b4c25beac23c2"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"6637ac87ef00edf5fadb5efd32271f9be8e03ff9e6cb93cf5072361b6e1f3915"}]},{"mode":1,"kem_id":33,"kdf_id":1,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"8428929f49f0aa978f0ec41c1f83de33356ce7902068c314521f14b53a9bf2d26e3c0d3559ff65227103ee6d2d0fb3774439a6489c331ad3","ikmE":"67ff2080abc00602ead66f25099a51e4e2a558ace3fb59e0c18ea73f0ffc0baf2038e4b6ba228c4a7823d6cfc7c4490319a1b352a578d314","skRm":"084b6e1462a84d627f6b196b16e5ebde9f9889b99ca6086f6f082befd8f494f186e0766475c1d24804c7dee774e6a744b493ce8fcf85723a","skEm":"37fd716e28ef9c581319807c6874f9a3d5f59d6f51370d33ff5ef4aeec85b5ca41c21ebebc6375d33794b4a291bea15dfa4bd9e8cf793a42","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"4f6c84f8f6b96f7922d10d3e0ef56b8e9cbb63c70b8fb1984060d0e9663e171cb5b1a7466b418b378448c9839f6ee2a3d97106d91e8dedc2","pkEm":"0d1cb1cb12daa8ddb8399e2fbcbd3896cd4bc51de8c3db29974fbbe2e74c1804fa233e80624eb48c0e683856cbd1048f2343b6ab907f27fa","enc":"0d1cb1cb12daa8ddb8399e2fbcbd3896cd4bc51de8c3db29974fbbe2e74c1804fa233e80624eb48c0e683856cbd1048f2343b6ab907f27fa","shared_secret":"8105e0ad1d1f5355e97d537d253366204f70830418ec34ad640cce163e5da7ac3d9ec6b7f82504b5559e3597ffc40e11d0dc8900011e2e6b4f253fab5c341e0f","key_schedule_context":"0113d73d3bc6ad29ada571507511d24ddb61ab73810d32ab71079f9daabf4ee3dc2030461bab15fdc38b55e526b9f9cbf3342bacd78553d0ce4eb4260c52b61d24","secret":"f041fae668f6075c6e0588a0faab9ff19c00060e61b323d0709120c403657906","key":"7efe73c203eccf753614e40f4805633a","base_nonce":"d0b20d43649d3a57236e04c1","exporter_secret":"fb1bf7523d586a918bf461d61e1130c14f6ddca389b1980bc2719117f4972be2","encryptions":[{"aad":"436f756e742d30","ciphertext":"be60300a0fd3337817d0939a419c5106001bbbef95aabd697e92c0d416afe294d9df80f256b34f22f1448eca64","nonce":"d0b20d43649d3a57236e04c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"1b4674cbe52456f179b6a590c51b1127287dbeb83217b15e7f206c9b2a9b2444ecfdbfea7bd3783d7a429c3033","nonce":"d0b20d43649d3a57236e04c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"c301b419aa1a48f73fce6ed222bbcc9289e6e6ccf15767ccadeeecc719ae464a489b76c48b87c99b7991d66682","nonce":"d0b20d43649d3a57236e04c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"80a31835c516819f9bc02fe132124bc56fb9848fe0e5fb9533b5742b0bb0fa53e6cd0b59ca18e827a85c12416f","nonce":"d0b20d43649d3a57236e04c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"5a46b2e158093bdc712dfad2a6a93b452940a2f31f70234b17d263d67fdf2b257feb84b72974a531ed8f409446","nonce":"d0b20d43649d3a57236e04c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"41d6b69fc94ff619f5d733d1cfa4373a1f1674b758565d57cd9995b5598397706e2640aa97a8d63645505fd6cd","nonce":"d0b20d43649d3a57236e04c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"1763acf3852cb5fe9ac81ba3a93439aae63cc9e92ba3725e2cf1c986ed8dfb8b670ac61dfeacdd4494de01c9f1","nonce":"d0b20d43649d3a57236e04c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"6ca7e147a4557dae630b1e209b1ca3e32c3d1bcc25431e79ec79c145237bc4455117edc1b3456f9657dec3d0cf","nonce":"d0b20d43649d3a57236e04c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"e0e01e1e145f3157624e5496afd9ff4fbcecdea52f5ec436366a88e1ec1513b07fb04f9df83f1608e472acd982","nonce":"d0b20d43649d3a57236e04c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"46f651ac07e254e31258b2b60099b606a288243b86d9bec78902f6a72122bf3bdcbf7510ea2de4e94f65afa40e","nonce":"d0b20d43649d3a57236e04c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"ff675153280d6b2f7a544e517f8725b6e2b32ac219141f884c3ef1bda0af16fb103c22f2f3a8134952d8b75a69","nonce":"d0b20d43649d3a57236e04cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"b989345e4d5405682184cb0de2b2627886c3dae6b89041eca73d0c7f6a420f358b0dac5ffd81b4bda0b8fdd685","nonce":"d0b20d43649d3a57236e04ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"8e021142773449fded44ea3e5ba7cbfc81f5d7f89e5ae01e793346b87bc484e9c44847ae1ee1d7b37697de647e","nonce":"d0b20d43649d3a57236e04cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"59571c9a87ef82f834b96bbcaef87a5ce06f10c88de9e00f16f8e5a8a0c1aa0d3dcb0fb9b0461f70157db599e9","nonce":"d0b20d43649d3a57236e04cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"265fe6188601cbf6b311a839cdb58444641d62b082e818265672cec84415e4d887ee000c07519a52e44ebdea20","nonce":"d0b20d43649d3a57236e04cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"897274b14756ae9c35bc68c66175b6c8360c449e4578b3737affbe61398dd8bb9bdf8535e1cb4fd497aa759abd","nonce":"d0b20d43649d3a57236e04ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"a0c9ad021bf4b68097d3c606dcdf70bdc6bb7a77206a782b26e9f9cb0b41e2d562a9df89f3e69ba587421f685b","nonce":"d0b20d43649d3a57236e04d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"8718aafbb2bfe0f94e6f3809f2ed39c481315183a3e776b9dd957aa26df8789a57fe54369c6b66745c9d9ea647","nonce":"d0b20d43649d3a57236e04d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"ade3c62a607604906a7448c670622881fbde5b986d8e0dd047260e7003233287646155827aac3aa131f77bdf86","nonce":"d0b20d43649d3a57236e04d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"2c8f9b2546361b4d225de0b47468a0ff865dc1557fe435ae8514db8fee8316aea49e29c1dac813ffb2ba8844b9","nonce":"d0b20d43649d3a57236e04d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"50987ebb586215ff4277a130ba8ded9402281c4f63dd26286fd40564f31e6e6909a19af2cab4ea46b113dc0dda","nonce":"d0b20d43649d3a57236e04d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"b5bc0db4afc3247f943d91abdec34cd11639c647daf05816c5f2edcd223d515b41774bfe094bc458638ab44592","nonce":"d0b20d43649d3a57236e04d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"868eeb92969b44287d3548c7734494055d6d5c07c453500f7d327bfbcaf9697bf31f096db5a5805e08d2c7ea37","nonce":"d0b20d43649d3a57236e04d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"d9078383d194ebe7e825ce8ec996245c3f3ea3b7471716d18fec59de2ef6e061e4bdfaa9572d52c761cd641bbd","nonce":"d0b20d43649d3a57236e04d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"ddb5be3c26d4d13699caf7abf05e3e1ada82d7c6553d31ea1f6aa13b842960a889a55cc1d3ebe1c6dd1bb90d44","nonce":"d0b20d43649d3a57236e04d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"e0eafb815639e0c7296abe57af865338cd2f9506257647c926d3c77d582c86540a41019431402138cc4ca494da","nonce":"d0b20d43649d3a57236e04d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"306f69cea1a1e1efb028e80285a7601029b63fa18ca723899441c246de8ad18b8900b530fb7a59ffdc4b567f33","nonce":"d0b20d43649d3a57236e04db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"9e02e2d81c97791402977fb762bfdc36ceb40855d551761f52256ae48b867b30cbab2aaf8ec9849d1b332af020","nonce":"d0b20d43649d3a57236e04da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"8e3af784c7ea0087d84cb273074a79ead57b9b34c7565938119d73bf0605d7437783340a5d3a414b383febdd32","nonce":"d0b20d43649d3a57236e04dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"4c760db074bcb3e8d4f5937fe14d2d404410ae94958cb1e570bb7bace3820e08c0a2f5c8b379754133f5f2bc24","nonce":"d0b20d43649d3a57236e04dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"61d09ce94c26dc96069d1f785eaa88140ad2a986e5704f78e6d4fd10ee83f6ad255ba111f7c55338181e20889c","nonce":"d0b20d43649d3a57236e04df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"d2a3e5dfa7117752282d176484588ac6a45e07b5c69ad2eecb1efa5643e8566d11a9d46cd04954b6d3caa2fc64","nonce":"d0b20d43649d3a57236e04de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"657858dde5709303df8fe95f74451f2fea0db91495a55add8179fd26befde31856a4304438e8cc4f62c543e56b","nonce":"d0b20d43649d3a57236e04e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"d8f440a488bd730b950dea73af0f0023ac01727fc64d1c06ef85f3601f6244805bf78d91eac6b3872fada19f4a","nonce":"d0b20d43649d3a57236e04e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"df7753e15ff0bd9eb167b566648fca27b6477babc4edd062d644eb82b8652aecbee0601b9f3733814202d75e4d","nonce":"d0b20d43649d3a57236e04e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"c2a4ad87423054041f5e2a40a4c6f7f6929b2b5f5c0bc30ab4ff03a42c5f9f63dfd89eb3b572b321000ab9b0a2","nonce":"d0b20d43649d3a57236e04e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"87e5af86a32b0e3311df0234029728767bc17b03854115c63a9437c4b3c4b3df270bf60e3ddfb0deae3d643817","nonce":"d0b20d43649d3a57236e04e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"f20ebfde0ae08bedb8004b46950def780daee60438a4499d0a3c6852d118fef0d4ee7430073342296cb043a454","nonce":"d0b20d43649d3a57236e04e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"8a5b7a1d87064b6fecc7185834fac9f5988c724b1fe40217c3156876d020a3790d351cb8af4cb977d47c01f1eb","nonce":"d0b20d43649d3a57236e04e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"cfa0825447a9cef05ec6f25021a0a622a8bb269d513f7add93a3048b343bcc9da7787b0b14a5e6daa73972a36d","nonce":"d0b20d43649d3a57236e04e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"c9f8777c40fb757ab9f04a1e356646ba943bf840658597830ca98dbef3c1e5ce8b0cc06294673b718c53e5d7c8","nonce":"d0b20d43649d3a57236e04e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"b5f38850584774ed65a16c11536fe83bb16fb0441473552c97750deaf15dc0b8e204d959b99c1066aeaeaf00b0","nonce":"d0b20d43649d3a57236e04e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"a471e0639979c683d47037a13f082909d178b7f5bf7d91941c0e67a67ca6e72108fc97c4074440c0b6c23a5ce7","nonce":"d0b20d43649d3a57236e04eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"bcd7d18705cd463d0dbd31ebaab1b616947fa126bc38a5e504fd0cea0025f2f3d76ada11420da5ba8da887e2e7","nonce":"d0b20d43649d3a57236e04ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"7037a254fb97ac1c9a50347ccbeb97c046264afd684b336f7d44ecd81c7b5865c84ec5261af8c7a09ac057d2dc","nonce":"d0b20d43649d3a57236e04ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"292a220d3d5af5d85b7c3b21fdb11f95fa56ec8c0f21ec613a2c9c911596bfbd150a6f3122d50061558411d466","nonce":"d0b20d43649d3a57236e04ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"0c2f721b9b542f6cfc7a4a36097fdd06b51e978b9c6c97936b512c7795ee2319144f61e9ac936097897f979cc2","nonce":"d0b20d43649d3a57236e04ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"2c2cd8b47bd0fdccd2489b4d54ef32b4c1af9dfea3ca780d7c85fe090a481912787aecb43fc1a5f5c655c96de5","nonce":"d0b20d43649d3a57236e04ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"88e381c9e50d404cb6603a36835fba980b3fd328313a1b7dad7cd58169244980eb69220168ea70c37810068810","nonce":"d0b20d43649d3a57236e04f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"02dc8d74de7612338eac73843b96e31271a69e4bad0a45176101b0fe9698bc8fea5a292908dbe6796cd066d098","nonce":"d0b20d43649d3a57236e04f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"853bcacad34036f436e202d6f80f376ad43c06b37ed87daa0ea294623620417e7afdcbce4513c04efe9c0eea67","nonce":"d0b20d43649d3a57236e04f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"3168192b2b7a04fdd452eece22d88cf7883a081859ef804fb738e16147063672c74e8eef01b546b25f26b7e470","nonce":"d0b20d43649d3a57236e04f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"851a2acbadc789c262c40b63041d7ed541a252392ce7942025b985948b3b0da41f11d2c561e4690e1c0b361168","nonce":"d0b20d43649d3a57236e04f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"974f7ca6ef3dfcbc45154baa7445d5c58da4f27aa6520152ea2c75f1735aba811e542bc5c9310d59858089ca84","nonce":"d0b20d43649d3a57236e04f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"c653cd98265e7b49d3d01e77e879da64fea072956f8984d495e5f643faa8a0e3cdbd1cabffecf22502e929994a","nonce":"d0b20d43649d3a57236e04f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"0f61275956967917924078b5da6132dbdde65551e13a0fd644d54803f851987bf7b057d325e5121d40c06cc281","nonce":"d0b20d43649d3a57236e04f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"e1b6ab251efb9ff5c3e0f53b9e106235d85ac3158b35da61468d769ab5999573d6623f78bfde7ea3373f304d12","nonce":"d0b20d43649d3a57236e04f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"6a1b4e9e9f141ef29216455ee182ea4e6233476ab81ff935c94a3b2147260a79eac56d8ded3d24208411dc9959","nonce":"d0b20d43649d3a57236e04f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"270dbd14f988560dd5f91b5fdba511c0c81f573f604e4d31db0c101c3b7d3af19c4a2e9add6dc5e98f39d7937b","nonce":"d0b20d43649d3a57236e04fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"6985f5097bab9ffd23e1bdcb19be847a4d94b411bccdbd048252c66dca52037a49dfd28a87dcf1905c021277d9","nonce":"d0b20d43649d3a57236e04fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"458ee4d0be2e47c2159ccdd3ca286a68aba99a22a6f5a4594a9f8e160d6697d13526a149c22071a2517da275f4","nonce":"d0b20d43649d3a57236e04fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"564baff7b1f7648a45c88f419b51dc3b92c0dd67baeaa66644a8b83e57e7db4bbb63995494062f3ca14fe3052b","nonce":"d0b20d43649d3a57236e04fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"e99ce5a6c97dd4f91061130d86fcc4fca16ad8039f8d18e79bbb0f0e42186cc189f8a9d0222806a07875fc4289","nonce":"d0b20d43649d3a57236e04ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"69ed2599320c8eb6f1c91996ae88ddb91ce42e9545ff50e6b31e1b0740c19760b76a91ccf765391d5f731e0ed4","nonce":"d0b20d43649d3a57236e04fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"6f9fd2d76a6fba3f7c238cba9b22b93d1ac3c9d5f05fbb171fdcb3b0a9aca00dac6f9938354200b00ca93576a8","nonce":"d0b20d43649d3a57236e0481","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"60d578fa3b5f60e2e61d829670a510cca331e08df1b0c6f812e784dc6686038fe8e5cec9e088a3507fb959617f","nonce":"d0b20d43649d3a57236e0480","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"856619112b5314206bd38dabe46ba4318f52701065055d421d306e1441d7cb03285369e5ab3ca7ae1884f7d9b1","nonce":"d0b20d43649d3a57236e0483","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"1eb5be9e0ba87e63b48171e6b6e9d1364374ad171e92606e2958910a9b880f0123b868a6f372c0bf6aad03e98a","nonce":"d0b20d43649d3a57236e0482","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"3219a231d2ffe672c469711180d281cf75321b5bfbd753e6106a397e41abbda7491cc3191bc0c706187754972c","nonce":"d0b20d43649d3a57236e0485","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"ffb39f30d5d7aa23a424280c29d0bc884a1a4d1a7a369ee51df1a47ef5d71261e9a35756b8b2434677b749e872","nonce":"d0b20d43649d3a57236e0484","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"3602f44930a9110134b63804d90ca170758a24017acd1c044d7e428d36d92788d19c9f98d52a28a4cd405cfb18","nonce":"d0b20d43649d3a57236e0487","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"a41ac66726b975413d4e7ea50e06b194a34c3bfd3c54877adccfd5e93684f4856dadc9ec70299b8467ca0e45d0","nonce":"d0b20d43649d3a57236e0486","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"ab02b0b5e534e9d4c23b12ff895d24e76ad9835595dff1b81b95f868af61b1fabf9900ec4d55976909f2dc1dd1","nonce":"d0b20d43649d3a57236e0489","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"5c4d07f4e790bb14697b7cc295ca4f6d02f0772a2d0e1e6629f5c8b07443656eae17d5630d9b021929bf6d11a4","nonce":"d0b20d43649d3a57236e0488","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"29748db9464cbf34164987f0d728e4655047f7bdf3be7b2f27a62e5f786a23eb94518a0ecafdc3d4044ade34d0","nonce":"d0b20d43649d3a57236e048b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"d0526927b649883db79d48a74863d6fec84e246cdd55af37f4ac1a600b8d9a0a8f1eb9df95ce03920fb0abe648","nonce":"d0b20d43649d3a57236e048a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"091ce7b341d285b78f45f51c152cd4193c31cc42d34c81c6ecb7f9e66a92c51682ac68d1a933c0b30457b1a1db","nonce":"d0b20d43649d3a57236e048d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"b8a420a48f02af9e7bb554edc9f048f9ccf19c62a1bcf09f9a9dcf55fcf02634218fd08568e17eaf0b5a83999e","nonce":"d0b20d43649d3a57236e048c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"c98d197d4a8de2e88d103dc19bc1194ace9cd9b9a0ffae5f4910e3b9da4e5e8bec44e1937a43c8bcfda28a0b63","nonce":"d0b20d43649d3a57236e048f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"9087d8bd75657e8a55af091cb77a606bfcd931d8bd686fb67292a2989a4bf328b5af7f8aee274c36eda61b1496","nonce":"d0b20d43649d3a57236e048e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"fb9e672c081f7111e2ca2bba640e888f6c3c276fc5a689f05f738d84839552d9df81bb7d6aaf341ba9f0f23605","nonce":"d0b20d43649d3a57236e0491","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"4374c613bee10af2e5e3ce3b56f3ef5b9ce73a39cf7a819491124cecc051f7dbad23d83442a385d35b4a427704","nonce":"d0b20d43649d3a57236e0490","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"3bf9d47353f4c3803899b76a0ee66059d8ce9641e6657166dd522e42a340bbcbecc8d232f5b131777c48c59d1a","nonce":"d0b20d43649d3a57236e0493","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"2a465f069adda7cc94b677d6b6b3e5462660b3a8227e01cd46bb73c43b26c0226549c6b5693123659204566105","nonce":"d0b20d43649d3a57236e0492","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"7c882527f517648d144c16649693d13ab61ebd92a5246d0210374c98f07fc0b14d071a5124b9bbc3b3439e9768","nonce":"d0b20d43649d3a57236e0495","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"db80c0e49ad63e9c2d3025d258e690c6241c92cbd6d1dc37c8182fc53edf7f592e69266b961d9950ca0e00b9ed","nonce":"d0b20d43649d3a57236e0494","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"2172cd92a5be63d82da9d5aca65c4738554d0338c7c71edafaf925feb346afd793ae2d8fc8cfdc6c1eb177ee20","nonce":"d0b20d43649d3a57236e0497","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"a8a96e5d548203bf5efda14fb7480a003966ffb05ccf36e86b4954e00b315caf05234a85785314a29ea333bd8b","nonce":"d0b20d43649d3a57236e0496","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"15d54e07bf15c24cb3b766f52724f04e967526fb1b260caf9fd6c57907a716192eb509401e0363f33bb1d0e938","nonce":"d0b20d43649d3a57236e0499","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"57e6a137c65a06ca69387566bbf4bf2b9dd82dc5a330b79da65e1df5eb9e216b7435bd2b4376d3f11ea6b3f4d6","nonce":"d0b20d43649d3a57236e0498","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"15fcf0b674d714332f947fbc67114b1af7f44f20f07bd6756d75b5c7065a47cccb5fa6f35d352945705f606cab","nonce":"d0b20d43649d3a57236e049b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"8146a2d3d569dfda509c9f582034e08eb116ac99657cbefcf90e9defa47d7bbea8baa468e26a0990cf66c68cd2","nonce":"d0b20d43649d3a57236e049a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"1d7e3addd6b7cb04d1e677baff04b91c10f6bc25b3a2d7a2da37aa35b492eed218dbaa8637f8510151cb9ee29f","nonce":"d0b20d43649d3a57236e049d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"7c090c49debfac76a3487e8ba8c1642097c378eb405aa186c43340797505fee0be8c0eaa71b0df7bb8ba541b30","nonce":"d0b20d43649d3a57236e049c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"3407ed6cc0f671831be85cdcb31dd4fa81e80105eb1c7f131b588bc224c4355ddc5370205f8d2b3042a8a0e6ac","nonce":"d0b20d43649d3a57236e049f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"2e385e7554e11812a0e02c4ab306f6ea7156cabe11255881d5f5c2041ba3d8c632a718dadcd81f2b874f172623","nonce":"d0b20d43649d3a57236e049e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"dbea48241b7b2dae4b94d8111aa4f720608852c4f1dbbb4a2a5ad325131a7d0677acbc5bce7be4a151afb0f829","nonce":"d0b20d43649d3a57236e04a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"6da740ddf5aede1a274e2c63cd46ecd6904e0396c3b442f12367ca59a82b839ef75e932fa7c782ba935658105f","nonce":"d0b20d43649d3a57236e04a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"229b530890d02fd68283dc3135e8680f5189cb71fb4613f0d144db808d9a822426bd6fa1ebd9dc9bd5167cca09","nonce":"d0b20d43649d3a57236e04a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"78489221a9f66dc5564b8bef595654a473b8a699850c27b4edbc138d00ed768ca5169d76d2a039f0c9db1e20aa","nonce":"d0b20d43649d3a57236e04a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"f49aac5519a7a901d028b6b5714d6d8ec7a043d96f5a518022a2e0c2dac44eed1d61cc6ba5bbe22e84cf64ed50","nonce":"d0b20d43649d3a57236e04a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"3cfbf956856e1bc7573786d84d83d67b3f36ef879f1b4881bdf26c77336e84cda3808df2bfd2005f7ac87ebf8d","nonce":"d0b20d43649d3a57236e04a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"d8c1166a5361e69ffe12650f570f7975a011569bf31a5b68425912e4f1777bf013792d4bd0343e6eebc750ed95","nonce":"d0b20d43649d3a57236e04a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"c50a004f9a7720623d1624687c94e8c9fbd8dfb5530fd6b08eb0ac1206eaa047a7ce167a5faeda10019dfd8327","nonce":"d0b20d43649d3a57236e04a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"b8ed6e2da23f0cf110d6c533a3114b6684f5b967d928dcac426a435f545dc5991a7c5468bea69ea6b468a2ffa5","nonce":"d0b20d43649d3a57236e04a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"153bed1366ce08f7c282e9575f2204bc560106be000afdd1e1c8931ebba931e49753bdb695768aaadf1e4b69d9","nonce":"d0b20d43649d3a57236e04a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"29644a6ef5326b15f99ca2bb96c53d24c32850440a280dcab4effa23a1470bef682f35e4c45477e26a5fd9b150","nonce":"d0b20d43649d3a57236e04ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"cdbdf7a78dad0a5964391ef9a8366574a0d9a231c52c085ace48f2f5160737589e3bc2637f477c7cca3ca52015","nonce":"d0b20d43649d3a57236e04aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"46f5a90a30ca84f742478ee024fd6ac188fb0ebf98bc62b15b3a0adebba334e5ed75aeaa8c505f1a8ffdc57f34","nonce":"d0b20d43649d3a57236e04ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"43e0f4aba01f8e8989bbc7d0ca7ec97e7c5131da613536e41ef377d7888c9b4bfddb6925fd5361e1ac7b3e0410","nonce":"d0b20d43649d3a57236e04ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"db16f10d2520325127d46ba8cdfe0c2bf98be70b847963ae06df197dfb9336a9557047f3054d731dde35d314e5","nonce":"d0b20d43649d3a57236e04af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"1ad7d61541181178acc096e3f95dfb6e8a991d33ef4f518aad9930347801f99d147f497aa84381e8f5be3b98df","nonce":"d0b20d43649d3a57236e04ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"e4e4c882c44983de68099d436dd221848b66812c89a25ba3bacc1d49bb1be5a2937617c9eb05b440b1de4743d2","nonce":"d0b20d43649d3a57236e04b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"21f893cd4ca541b60de1a4c8503ff3016da81c3160512580994f756ff37a21993c5846156370dbdfad742805c2","nonce":"d0b20d43649d3a57236e04b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"5a1797b855a6c828265e922f32ff6beafac5c17c360c43e0a2e0ccd1a3187e7e44f8d583969b7e1c146cd56bcc","nonce":"d0b20d43649d3a57236e04b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"ca1d1d1a34b3442f0a8ea6891f73459587f2044c05980c6e239f3870e6c8d4440b5f5ceddba3259a1962be6326","nonce":"d0b20d43649d3a57236e04b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"f06a78da93b74e0dd24f94f2d15a80cb22a7c2119682ff544b7b652a0c03d720039af54446b21af02159cd040a","nonce":"d0b20d43649d3a57236e04b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"9de05a139f143c2beb9b382e36203019a17d6090e7cc3fa8eab94861d7f14fe4f989886e6810e36ae0dd807969","nonce":"d0b20d43649d3a57236e04b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"5632dfc292d2bed75709e6b8150c84cf2875c3e5655e8c936b60690c20f718f335070f6ed87f6b69ec41de1266","nonce":"d0b20d43649d3a57236e04b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"3f0c8b68c678cec79ea3383de4c8ed5d708a889920202643b4f41cbaa9bf1c107a8ec872d5ac0fc4bc7ed60805","nonce":"d0b20d43649d3a57236e04b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"462ffb5b591bc0c73e4ef86fdfaf0631f0d8d2301096cf8fc0f96ebec344d92c812fc498e879b5aab5123ed878","nonce":"d0b20d43649d3a57236e04b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"5b2e515c9c17e916646abcc3c488b912e25f67963c0d5eddd9e1f7db079c2b4c33873eed0f986373502b693130","nonce":"d0b20d43649d3a57236e04b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"fb8ddd37302261ebb5b43f8107b7c3dc6687e2f477c4fac0361e07e7cb249a6809cc339e0e35feec251db2a26f","nonce":"d0b20d43649d3a57236e04bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"b2ab54340bef1ec612f3aed8db14f0d022b97f6b6b80c93f6ebf052ed7eaff08e44d7811837ce349f178f90a29","nonce":"d0b20d43649d3a57236e04ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"edfe432d056ebe4b32fd2453dd79be76eb2922621450ef20b4d8b0f1bec8d5f7b74f669272d827571230f31719","nonce":"d0b20d43649d3a57236e04bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"3d2c21b63a100d32a3fd9d64e0d34c787a69e574ce477fa84a990eb082bf464bb1f94e8998c59be9ecb538a78e","nonce":"d0b20d43649d3a57236e04bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"7402d239b81db6885cc3e4eef62cf4da2cbd5395842c5e76d09fccec689d652c84e48f19ee0797807455dc5e8c","nonce":"d0b20d43649d3a57236e04bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"8ab4ba4f6b15830232850a4e0c3f396e44531658885239abefc6316381c3504e01929bf6aa3f6d9138eec5e3c3","nonce":"d0b20d43649d3a57236e04be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"fc19c6f172433a557ed1147a5761a06077dac39a34d4785957bb3f98c345f4d8dea162f3cedd809503555b0662","nonce":"d0b20d43649d3a57236e0441","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"a68b0dc8ba489b8808a7823af18bcfefc07b0fdda962f41344c980f4f7b093dffad6e4ef80f6becc8692a0965a","nonce":"d0b20d43649d3a57236e0440","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"6bf7da8aae5943de57cc85bc8ff9e38ba897b767610c905047cea9a4c6bad3fefcf6086027a5f4f74753015921","nonce":"d0b20d43649d3a57236e0443","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"4dfa2d16d53be0b1fbba7e1977abc3888beafef6e3e6d888a6d96460c23ed75530e320081481c9f60b72c3bcd1","nonce":"d0b20d43649d3a57236e0442","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"ab71c60fc95c5c2c53a2f4d91046ed995628f8188959f159d3b03fb09e3e9f76e234d91040ebe45ff12ca534bc","nonce":"d0b20d43649d3a57236e0445","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"9b9c7dd9c6c8ff0ade6140ddfa1b5e6af1d9885f3af2d319981f21c2bc2d3a63860e5834743db714dd8947ee84","nonce":"d0b20d43649d3a57236e0444","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"8b190b1d4005106260ec4975aa115d4d278e6d4a55a3f107b631a86ce48d4fad32648ef5f882d09fe8658fb7f4","nonce":"d0b20d43649d3a57236e0447","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"e845c9bf573b5a17783144bd0c7e40638cb539d301222a849425ef7b385ac27b92ead94dcb0ae7f7d4eb87cb9a","nonce":"d0b20d43649d3a57236e0446","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"bff5a5c334ddfdb75649577c8ee523a7c63e35c5788cb27095ab703daa9b31c6a4a19e734e6af590a36bbef9c8","nonce":"d0b20d43649d3a57236e0449","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"982bc5b52e8506b42385753cc0f9f1611806ed338bb0f66d846bdb0fa0ebf4e6d3eaf65d99173b5d7bd393bd9f","nonce":"d0b20d43649d3a57236e0448","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"e570f4eeb0ef9a4d419290eaee202cc0620c40d79c19ec4ec590fbce45d91b01b93f8d049837229f33a526c0e4","nonce":"d0b20d43649d3a57236e044b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"5520e31dd43ecd30c1c6fe70ddeedeac6271823033beee077fb6499775da2e9525d8b244128f72914fba7bac7b","nonce":"d0b20d43649d3a57236e044a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"ff717bbfa7b202aafc1e01819f5826026d4927d95553e77c0e1856ae4eaaf33f5283468cf7d964a603a2355d62","nonce":"d0b20d43649d3a57236e044d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"534b2767d14e0b30671b706281daea65295c2403e850367ff879405b9d342b261ff9d5c5514c27c6c944655057","nonce":"d0b20d43649d3a57236e044c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"4e2b823cd7f3cd4247868b8e037fce7c335e30ea6bdfd30be75c3ffc50714b3d0bd972111f50a896b34d127714","nonce":"d0b20d43649d3a57236e044f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"f216a92c360558e621f07aad0495b64665e16023e5a79d30fdada2b6e06da0676abbbb57cc50ae327cdd496bc2","nonce":"d0b20d43649d3a57236e044e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"a1dd9c517ecb59ba105a7cdd52e8d36d181ec6275ed3ad2e0d3b5f2d501551872f6e8bc1af5d4f0ab3092e1ca8","nonce":"d0b20d43649d3a57236e0451","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"5ef81c51328ccd4dd21c9dcf669d9c3b7818ef4b12036ff5036674740e96357c81be7157e5dd8d5631a64fcd15","nonce":"d0b20d43649d3a57236e0450","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"755bb718f86689ee50a86173db73ac2c4bc0dff2480d8aeef9b0d0448f2ed332a022b4d02a557d7eb338a7d1e6","nonce":"d0b20d43649d3a57236e0453","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"02431facf56fc17b5dc3343aa3417fd735296b973f5b8daf8edd71e2a4391996df3a144c085d630e3092be462e","nonce":"d0b20d43649d3a57236e0452","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"aef5992a02ef44812d2504f27689b09bdab511dc5d9405309d6700d1ae04e4112958e5248085020758df1d21cc","nonce":"d0b20d43649d3a57236e0455","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"3297917d62b721cf97f0bf5725942697048c5723ecedef35880d46c8a8ff341c3b21318af14c38e927f2cff870","nonce":"d0b20d43649d3a57236e0454","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"0313fdb7f162017f2dd8dca2910419dc0d255be8b239f04980b4ae9bace310ff5d5b89cf7b875e74a9bd6fe133","nonce":"d0b20d43649d3a57236e0457","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"bd9699ab4f8d98f8d5523346d0218ca6b3c360a572c478dacaf3b99f7f0abed0f4b0731ca650c588e3544cdd6c","nonce":"d0b20d43649d3a57236e0456","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"36ae2fb39c6ff0192beb9f81b52165ca119b24324f9ddf814db6eff3062844ad3b3ec4d9b7779e17b9c0190786","nonce":"d0b20d43649d3a57236e0459","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"616ea0929993f0b6f9e7376601c927fa59ddcf57d84e71af4e94bb17a09eafbbc686c6740a849aa19822d7735b","nonce":"d0b20d43649d3a57236e0458","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"acadfd32025bf3098b8869cbd3f76f5d71c91ddb9e150fc93475b9fabd81db264303ad74bcdd189063fbdae8f2","nonce":"d0b20d43649d3a57236e045b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"3c51753fb585f85e1bb7d9ae6258631c0cf307ea7bf5a5909bd9b11d59ce1807b2a9663f3dde5c65eb0da26db6","nonce":"d0b20d43649d3a57236e045a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"4eeb2aeea6503d6a421b6e0b7171d894cb3c45f37dc717223b49c4cf1d3df07c973b1cd82a50d32ecdebf7bea2","nonce":"d0b20d43649d3a57236e045d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"e22eab15e4631497cc86a3ba6d2e915fc854d11caf40c63294d03271a039dd3ebdca83540ab7be129db143383a","nonce":"d0b20d43649d3a57236e045c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"be41d30cb67101c92214fe457fa5eebcb83b743d71300f8b34a56682c10f7c3ce7f8c0a60adb798c1abd325115","nonce":"d0b20d43649d3a57236e045f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"5f2d95a094c3070c012e46505669a2291ae88f8e1cf1c37a506748772fcdea66e1f7fcaadcfa26612ee0049457","nonce":"d0b20d43649d3a57236e045e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"c83f50a4157e32a7bba59d1b16ca9010e743817a6f3d0bb0ee4e790e665574adbe0979fe3eb52df95faccc962a","nonce":"d0b20d43649d3a57236e0461","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"472eac86c163a50a5a41808c0b6da6d00195c7320cb905d51bb7453b6559da3e11b4ce06766929dbc82ebb4e3e","nonce":"d0b20d43649d3a57236e0460","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"ceac87626581a546c0a946ae17f05ea81c80949044decdebc5af3f8adcc6c2a7872932c3e06dac2cd4eb70644d","nonce":"d0b20d43649d3a57236e0463","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"344ba9ce037f27e38a670f45aecb0eeb5039c8b6cea6598206417aac4a2aa531a358f6a4f819326c6b85d2d880","nonce":"d0b20d43649d3a57236e0462","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"ebfbcd85c9cd7986d6fce022e3bb2aa1b9016bfea46d66467b4ca18ac587942068e13e7a5acec001c8e6f88aee","nonce":"d0b20d43649d3a57236e0465","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"ec554f24ce8387eb04c45bb2957d9d3ceae00d16b8715bcb9ebadecd22f6d38650ca95c865abf72988eafeb6e5","nonce":"d0b20d43649d3a57236e0464","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"53188193f47e1f8f82113fb83950a55c966feb1ee344b9118e142f0b69e794cc067f777cb9a9655f56f5e7017c","nonce":"d0b20d43649d3a57236e0467","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"2adc2ec273c9c0bd5c2b2997a5a5cfe1bed52fbcb9ad2b1ffa01316e566137fa6be736e94cd758c8e68790bda3","nonce":"d0b20d43649d3a57236e0466","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"dff735001e631780c28fdcb1f710835fec4d860a7f4399f175bb93577daf9ac4dc3723a6ac5c6e76887f414670","nonce":"d0b20d43649d3a57236e0469","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"ebe51333eae029e7cf973913bac8efd329a0825895a391c53e608a089ca61c8c1ef40fd92056d231b50010b10b","nonce":"d0b20d43649d3a57236e0468","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"11860b4aa94274c040a15d97bc1ee41d92adb324097862ce40bd3bcef07da8ffe7c5fa5fca7094a1c339f4e4d6","nonce":"d0b20d43649d3a57236e046b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"5d99090c8a16f7c154c1a12f22ea204c9a13d65ee2ffaaa76b64f5e6d6304acc137ec1738653ba355cc97ea884","nonce":"d0b20d43649d3a57236e046a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"b0e5f5f9340757fe753c7be9ad054494c108f88dd7fe959e7dd91e7d894c3372f52160d61e83e346aa8598b4d0","nonce":"d0b20d43649d3a57236e046d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"c5c3a6d0d6d7f9d567c22ccdac8ed386c893b3bd0a238db62da254c764134f0e3d259519e176c765f02c21f57c","nonce":"d0b20d43649d3a57236e046c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"1357c9ce02a08829ae2e8a375fc891a50b5828d2b7801e0ed4051e9fab7ed700ac627355146c7cccd1ca2914cb","nonce":"d0b20d43649d3a57236e046f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"f58f358445d3b976a996b3e99872f8cec5b0673fd92da6d04cf5128074bba917c55834d9bb498c44c1ef86908e","nonce":"d0b20d43649d3a57236e046e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"c3e0a9b2eba570ea6d666eb97425e4f20cb5c5a1e8ee31416e4adb278e4aed384a3e53524b8fcb846e781ed7b5","nonce":"d0b20d43649d3a57236e0471","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"ead203ad018a2ed1a5b855400b63db017fb1cd1f8e92cb14dc09f92ae81c0e879cc8b4a45038b8880db4c932ec","nonce":"d0b20d43649d3a57236e0470","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"5e2062d9aa8a58a5ebaa597c8766cace5381f726c4bfcb484353f273f0aaadfc9d03ba670ed9c25f25c4ac66a1","nonce":"d0b20d43649d3a57236e0473","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"46b2099d6e62dcfcf7838f03926859e81a4c27d0d8d3ca5985082539aeb4f9a850150a57a5ad4adda5dcf37f8d","nonce":"d0b20d43649d3a57236e0472","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"2a918093d569a31afc1ab40779f283c25bbfd29c2b87d0f9e53b82deaa4ef4aa1367ca76d7561842cbc588ff38","nonce":"d0b20d43649d3a57236e0475","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"8ded2e04f188c9b8ceffd0df9177930fbbbb1109eddd26eda96355b0af884ff22b2915642e5d5e00dbd97dbc44","nonce":"d0b20d43649d3a57236e0474","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"7a5640ce329781c1e25c4159798f2bc159960439a454e26f551df1b204f0150a764eff2c84a63b51dcb6004870","nonce":"d0b20d43649d3a57236e0477","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"d08e354248566eee69a8f6ef841ef7d2e1d92b2e666fb0740365939869deab3181354bdd74ba1f1cf8d3142b13","nonce":"d0b20d43649d3a57236e0476","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"f60d8e2ec91da60f470fcc01776274c3453bad1d0556f74b73b6ff0c21ea27ea9666a330e1c5e554092226855f","nonce":"d0b20d43649d3a57236e0479","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"45a26fc9bf09e4ac70d7004be9455c9a7f678f2cff4927c659b103a153fa42b06de9f86e77287e9ef34135eb14","nonce":"d0b20d43649d3a57236e0478","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"ce9d61213bea0c96d3872b091d44b79a975975ef9f6e09785414e91727e1f121a2dd9547c84957b01be7e1dca7","nonce":"d0b20d43649d3a57236e047b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"84e9c6c2a400c2e1f5347ca551d5a17f2403f1d65331488ee4607bd51e74f221e776e488a1f3ea1eb12186b3a6","nonce":"d0b20d43649d3a57236e047a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"7fd34fc360a489a677c3a00e8a42e693c4b2204278d7a92abc458c7255e81d5778c9b54fde3802cb962a5a97bf","nonce":"d0b20d43649d3a57236e047d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"7eb194c72193cbc017cbe0124a64254cfc4b4d62b18782e141136139ce0d013a7f114519f6d23b09e86f2181f5","nonce":"d0b20d43649d3a57236e047c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"32bf7ef67b70fd280ac40a773741f19409a501a4a188589c96bfd44e33edd076b38411dac33a516befa4617e5f","nonce":"d0b20d43649d3a57236e047f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"cd76c0ab374f5d2b13cb521e4cc01e2691a56bcdd0073219e5552395cbb4ca3f7a3be93ea0821322e219f14c20","nonce":"d0b20d43649d3a57236e047e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"1cf5282995f8854782a4e1baca837cfba2249a27d3727915a4b345a0349b9b8361e3d5747328984f172d8c263f","nonce":"d0b20d43649d3a57236e0401","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"5ead160cfc22a4a7d9eb5b9e6b6324a720ea7fce0ed1c7fa4173725e86ea3ea0f1e4831e60b061600d08643d72","nonce":"d0b20d43649d3a57236e0400","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"52411669d190eb9700b68ae1d9c29414bc26b69e90c358a7d7c966cf670e1c5937f286dc2761163fcb1c245e8d","nonce":"d0b20d43649d3a57236e0403","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"59f3e49f2b85d1e32e173b629e02c2d5738e022fc29011a92dfe5a285cc1d4e8a64ae2050b0f2940dc277ff2dc","nonce":"d0b20d43649d3a57236e0402","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"63e355b1783aa77232ae205e0a4142b840b97125a7e1e3b8f7ba4d9ebf187851c02cc307c892e7b8df2c6e4159","nonce":"d0b20d43649d3a57236e0405","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"b6d67655ad2977f768b95d1f4f247c3a857415502543911cf9eeba90f468aa660129dd438e447ea8ee2a274197","nonce":"d0b20d43649d3a57236e0404","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"e750a93ccea911b80c0778909af4f15087f0ee70ebe555b6d3ef6b2a386f46d00999327bb44a3cc6d15c701550","nonce":"d0b20d43649d3a57236e0407","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"2b131e58f6a85d3854e0e5ef05e786e45a8453af6c10a5a9be5cf3e01fc31c4da4ad909abdd1f98e2bddebd123","nonce":"d0b20d43649d3a57236e0406","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"7244317f42f30bcee0d5b6b343d9b214792f6b79f2bbe8e53d00de311bc9b3ef304deac7f02299e6d328ee6024","nonce":"d0b20d43649d3a57236e0409","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"6d19fe71f406af35aab86940a5011b9dc82a33f6b1af8bfff2973176d37759b773378351401362d58ec002bfd5","nonce":"d0b20d43649d3a57236e0408","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"84111c1a29e45a5315784489be239f47deb41923e4086d27dd7a00eea2953c3a8b3bd28e4b26abb80f884135f2","nonce":"d0b20d43649d3a57236e040b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"bbf473f0c7f16b50661b5f7640678bfe84b2bc2dc986dc2096d8aff6f341bc3eec188c80895fc7027a0f58e81d","nonce":"d0b20d43649d3a57236e040a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"9c1dbf38894e67b42a0d4ba24c94a7cdc3168e385a26d9a50f2039f36cb7c2c527849ea3a22f41d30cc93e4031","nonce":"d0b20d43649d3a57236e040d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"ca1b6e1684b3932f5a7b0bccfae94216e42f2dd8330fe5f7fc8e208253c57b1d13b3f14657bbb9853eefc56ae9","nonce":"d0b20d43649d3a57236e040c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"584efbac177c4b0cb5e5a1d0d2cfeaaf8a87b5f4e2477347171be1c506563fad6101ab657c3d1b3728e2eef2fd","nonce":"d0b20d43649d3a57236e040f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"130687f286d993a40e94fb3c882cd267f759488446d89328bd8b07472e9af4d3320030190365a299eaa40e740e","nonce":"d0b20d43649d3a57236e040e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"e12eca67431a11dbce4c9076f198f0fd727b2ade745f26a9300e97f12cd1ff39cbc22c727581f1a13223aa2350","nonce":"d0b20d43649d3a57236e0411","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"19ef04279c581cc3490e0d0eb3e83262dd9de7943e57875ea16280f57535e07a4719d3188c303b801d2d7989d9","nonce":"d0b20d43649d3a57236e0410","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"c8279d8f5ba7b7d1815cacccecfe7ad78b0f35faf334c5829b5b48d1bebc7da099fac8a2f4ebe704475cea535c","nonce":"d0b20d43649d3a57236e0413","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"da018cc166f943f155ba8902a86a31eb89d37250ae98bbf7e72e6cf305e9c15d0975d9c4ccafda35c644c01f36","nonce":"d0b20d43649d3a57236e0412","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"45a584f30ea3ffa6f5fe0d4fc39464155687a1d855d4b71e7e12a469331c29d2172a920fb0faabec0588df242a","nonce":"d0b20d43649d3a57236e0415","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"3fce5a0cf3e3efd74b55897f6f68823a1b4eaf6a1889ffd3f42162fa04672df9048b8f017c938c2175130f59cd","nonce":"d0b20d43649d3a57236e0414","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"d95b78641234d49357162ee53f7af930ae5ea86f6182c954697b4bc7cf6bfe368fdb28eee8bae4021ee8483a3d","nonce":"d0b20d43649d3a57236e0417","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"1af86274fe715e1fffd15b11f081a7d4efff5531681381836ac5e1f900a60e2f6c6afe3f37b8cd81c5ee405ecc","nonce":"d0b20d43649d3a57236e0416","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"4768a022e9fe85760a51a6ee0d22bed9ac4130170fdc064fa0c72fda5c69d2448deb3ac5e7e2daedd3c97e4379","nonce":"d0b20d43649d3a57236e0419","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"87156ba32bd56a2acb7fdb7f90614ebd89082f6bb7cd03c78324a423b0f9a3e0ff3185ca7bd07c0606aede2d33","nonce":"d0b20d43649d3a57236e0418","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"8d3b8a707724084190e1c458107b5ce4cbd2243a8572c4d80116c7ac266bbe975ae037450be2087367655caa10","nonce":"d0b20d43649d3a57236e041b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"034ffd3d7bd4e851ea2f8aeaf345124543de796169b1ab5525204fd4f2e506386da4da220fd62848eb00039f78","nonce":"d0b20d43649d3a57236e041a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"50f6f9cc620bc0fdf0f5e878c569c83c474dc23e0d3cf7f84cbc86b6bd624e96f5c7a752cbddcaa288a3a4d7c1","nonce":"d0b20d43649d3a57236e041d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"198d2540ec0230c29b040d167e45b6197c8de09a0cf809cb1cffabb38c9ace633e9dda96db268c13cde20599bc","nonce":"d0b20d43649d3a57236e041c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"3dae513def9ae14a87346010ecd2e1e8a09a94e1523d67fc23a77cb8d31cd16d7dfd023adc7158efd452e63117","nonce":"d0b20d43649d3a57236e041f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"661b1c799938943a29ef0e3712f26ff9a135bca05810b085c9872370a7ec158ee1f49134af411b903d70296c6b","nonce":"d0b20d43649d3a57236e041e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"fae48ad47e64c730318a090bd89a1ebce14d621004c0f4e52b3fdb4829e4639fff88a9a83bd93c8adfae93ada6","nonce":"d0b20d43649d3a57236e0421","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"2601a4b31bd2c8b7278c156153712c782cbdfd7d149b6b79fd39d786385d1f95674304c1cc3ce2a4c4e0be979f","nonce":"d0b20d43649d3a57236e0420","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"049e37d764b2a3c0a0a18fd35ddc792084707ff17cf6abd894310e5be8354edab74b68f4bce3c106919d60de0a","nonce":"d0b20d43649d3a57236e0423","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"422830abcb6eb537e6370cced2a6fa696b6bc93ea365e5e2cf4de22ae3de1761fcee50636ef62335254fdb8948","nonce":"d0b20d43649d3a57236e0422","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"d6f6a4dbed524b7f8425dafa6a639755ac71f45938b0a65e614a3253c1ba10aa00580def4587e64f3a169e84ca","nonce":"d0b20d43649d3a57236e0425","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"5e3a0fa2b04e4303041572d84ded6159df64c78b703b48862c735c49ee23c52bf82a8d0056a3618df3a4ccac47","nonce":"d0b20d43649d3a57236e0424","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"25adfeab0a6c3ef7b08b515bee0540c1a06b9afa188ba0e79466ad4c84dd67df79bf064ec78fbf7431279a8ad9","nonce":"d0b20d43649d3a57236e0427","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"8e6152703f78e4c9dca58f4bccca3d71c9951f2847cba3c41a0865325616854cf7efbdb45d7544e3525bf6f06b","nonce":"d0b20d43649d3a57236e0426","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"a8297a0bafcabf0b75c1e01875bea31139e0d6ea7df9517071d7180245306dec0134ca53dd2e22f6874c85da52","nonce":"d0b20d43649d3a57236e0429","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"268b9d04d8d6c0353f83ed5234fdb8a5e8fdf6c6b53ede454b1bfd5d93f989e0d22e48045bc8905d24a39119b1","nonce":"d0b20d43649d3a57236e0428","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"89dd831ffeca06b8f3e24d9a0889c576cb211a467d81b5aa587bb30b3ca257f86fa771e6444189a4ec7a1fbdd0","nonce":"d0b20d43649d3a57236e042b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"32412d911d422e091693dda7875ecf6eecc5ecb301016e6a189c730f7f9035f0b253caeb643bf76c014731c170","nonce":"d0b20d43649d3a57236e042a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"a1d8bd7f762502823f858ce01f75532738c4aaaf32dbdd610ea2eb83e610e736f8d2e2fc6ba6e13994b28ccfbd","nonce":"d0b20d43649d3a57236e042d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"fd2526b4eecccf7040d4ed387ce115e08f7b6829a36a5014b48e7d899971f18ac6ca2a9692b927222c13d2dc27","nonce":"d0b20d43649d3a57236e042c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"6c76268c66d08cc1ee764fc9f0105487b7c79c2bd5a62f9b6ca0b60ba8882e70252aea28764b5dae1a4423d360","nonce":"d0b20d43649d3a57236e042f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"3660f68c19661982d8e8167da62dfca78d03a95db6145f356955c14dca37917b50441b639cb8b34e3e5ed9b5d0","nonce":"d0b20d43649d3a57236e042e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"28917a2840d53c1853b912794d35a7d64d884ec1e693437057b48ab99f59359f1a6dfb0b36cc1a0c4c6c45284a","nonce":"d0b20d43649d3a57236e0431","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"dad7e644918deb7338f9d4762cdce98d6b5f532021028fb489939342e102eda5657248bac0ce7314af848a83fc","nonce":"d0b20d43649d3a57236e0430","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"9d9d06e529652e4bb153518d2875e7d891d2678c6dd6cdf6527d01dfea28e246ce593403470f3d8878dbeaf5ec","nonce":"d0b20d43649d3a57236e0433","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"89ed161643eaca0dfe14788dc4bea5798d1c3abf7867cd53e5d148c3492df845db66d5394e5dddfb5a4ac4f0ef","nonce":"d0b20d43649d3a57236e0432","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"5a7e1f3a5459873c062928b75d64be6f73756f33a5e37f360f697d6986b936ff84a5e98e28af5dbec96ab08e49","nonce":"d0b20d43649d3a57236e0435","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"2e5e717b36effbe367f4f1bbd9e4aa8f263bf816473b57f94adeb38ae1a135ffd208a1ca2fd53c09f1992e5c6f","nonce":"d0b20d43649d3a57236e0434","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"5daa736703bb386b01d7c3906cee8b3718bddbb31bc126cbc45f56f5c6ca8e6a71bf46bb2d727a8241f4ce7d1e","nonce":"d0b20d43649d3a57236e0437","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"145d19edf6743232794fa0ab2001f4d98013b27d113c55eca3bf3718f116676c85ddabb55b8f064b7e80261634","nonce":"d0b20d43649d3a57236e0436","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"edb5fe6c2c99ac63e23f418edcb5bf61587f02c3e8a41c8370e208f53ad07906f7fd2ca508672863b376b9b206","nonce":"d0b20d43649d3a57236e0439","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"fdbb156c982c1792f5d3118f55b6d8c61453db21ab5fb4ddb7cf43056cb6bd05d17bb64b66275c165187f9e828","nonce":"d0b20d43649d3a57236e0438","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"1fe34dba98aac0e41d05abd6c71b0c337441dfac1fe1fa03d044e4f74b9d18826a2507aa41262e44357ceb64a4","nonce":"d0b20d43649d3a57236e043b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"6f7da7cf456c64f87b8513e9151b31bb8b68ac0a95383e1e9b556bbc158da8ae606d41dd85152ab39922b88df8","nonce":"d0b20d43649d3a57236e043a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"0bac274918d27bfb69522b21aad82c90f5e7b35e5a8ea1ea9242e8830d82485c5bf9aec873456e407e51e4f9fe","nonce":"d0b20d43649d3a57236e043d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"b40fb87fdc763fb883150c6bde99fd1524f5366d20cb17657bc2fe1dab6ec4d693d8f9fb172f193fc77f7f47df","nonce":"d0b20d43649d3a57236e043c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"caf8404cff7fd01d76a8d6f49a38c35c36464cdd458f3d800c9d3c1294ff05746ef468914e3c47c688693a3f46","nonce":"d0b20d43649d3a57236e043f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"2a857bfb059efebf1c47f328ba5bf187903050483f940349b5760a82ba2a58c797547b10e9576b553447986bca","nonce":"d0b20d43649d3a57236e043e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"c5358250bcf312ead06957697889665d3b27677ca7fc242ee915e4146af1c3135c1ba0997ddb7039c0b7f759fa","nonce":"d0b20d43649d3a57236e05c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"d4feb7927cb68642955a042a3332ffc69462ecca1940f5575db099e3ddaf3189"},{"exporter_context":"00","L":32,"exported_value":"0dd5cbe1ad88f315cde375691bd439d3d0095c0f54587cd02a6d43919f39c7e7"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"58063a6823603a88d30c564c377dc296499b340309693a3b67c6e624ab19978b"}]},{"mode":2,"kem_id":33,"kdf_id":1,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"9a54b8a6941b3f438ac9ccba97d43efaaec2a0c86eabe2a7f4693e8eade3a318b06e0378dfa1dccd7398341238a2068039bbf2094038a3b3","ikmS":"3cc1c12cdc7360fb6c71b4f1f83f81ec679fc3a17c3bcb8ea60f7694a02ed62417c4391ad231e03420d45876883e36351dab2cd2d99a135d","ikmE":"11c9a83541963c5d20e170bbb9628b4a9a67f7e27a06297e721946f6bf86bfe44ccaf0b14442834922f79e774ad7ca3b33e411de7dfa7758","skRm":"33aa097f36797c7b911a467c029de222caf21cbd678e8cc252eccf98684bda419240ccfac1ecb5bb95dd42433ff6b5b25c8559ebf2db8ea6","skSm":"bbe781992a906d0aa0db68ecc7cd1a987a48fc6bec426225eb9fd820da561a493c167ec80fa0c4ba052e012236049df3ccf89d7d2ce35fe1","skEm":"2ecb08107887ae3120780933bc88298cc27234c620d4765d40e0f3a8173fcf8828d32ecfbaf9e019a0007c65ff205ae428758cbadb597f5c","pkRm":"ac877c2a69ab94892c34758f7ff5cb0d991685450be6b91cf089d129997a1e7999720ad9d563241defa2bf5920f8ac2ebe0f67d15c482030","pkSm":"8e9e09c278100a90bd7578d1903991899c858d71571701761fa6f1fc6a9647d2af3e2fde18d60cacb1faf9e3d72cb644c3689636087f863c","pkEm":"ddefc7989818e143af0c9d6a9449f0db3100ac7ab0d79f0632999e11d7c775efe8cb7a4c8993e27c25dcc4a4a5517c90e1850c69461fec95","enc":"ddefc7989818e143af0c9d6a9449f0db3100ac7ab0d79f0632999e11d7c775efe8cb7a4c8993e27c25dcc4a4a5517c90e1850c69461fec95","shared_secret":"6423c8c2ebf8a27a04ab498f6eebcbbe3fd8f82dcd872c67dc436d370e63dd0c9ed104363587f40d9847c7b868aaf9f21a7ce2652c23ffc7f69e358b102d7ed3","key_schedule_context":"021106b1a1933067c87d4d746f7db5f197ad5107c4c5c2b8755555b63f50bf121e2030461bab15fdc38b55e526b9f9cbf3342bacd78553d0ce4eb4260c52b61d24","secret":"5fd7957135149dee3be92873ff686d3053732c7973c0b4eccf1002c49e40ad56","key":"e14206480fada7409be74fc1f8db3aa1","base_nonce":"5003994c4d02d48a6171678e","exporter_secret":"f101053fd695ba1663aa7bdb23a65dcc60e48a6d7c464cafe0413188f000e61a","encryptions":[{"aad":"436f756e742d30","ciphertext":"5d208625885a9d21d0762fd144f63fa8a4b8093caf330f0d53dc2368cc8dcc922ba7c0bcbb7328d4a5ab34f7e4","nonce":"5003994c4d02d48a6171678e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"a5f5a2804ce4d8c5d4de2adf0b558eeb24165042b0b6e99146863ed9d85d883b86df238a1ea55036ba92361461","nonce":"5003994c4d02d48a6171678f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"aa664d315b281e2ba4fcad73c4c45e4187938f5c1a0f634de4e2008262823429bcb35b217588b1eb4e7f9b1b78","nonce":"5003994c4d02d48a6171678c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"efcca90cf091488fea32d9bd77397549bc066915735b8e0c175d08cee5d4f9000586d782cd6871b92694964c27","nonce":"5003994c4d02d48a6171678d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"268532a3b827b44a924d5611e6692c3fdc2ba77381c5de0c8bfe6f1ff6bf1afac9ff8ee811b5715cda7d4630f6","nonce":"5003994c4d02d48a6171678a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"de5e1d9478629daef287beb5f50e22b532e80c259e91a9a7fc73c7527d6d19bb396d2eb3a93bab3b6cd7f7a385","nonce":"5003994c4d02d48a6171678b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"cb79caed533f9067dab83069278d59bc965cd5d62ebe9de14e42e767db7963e164dab3f024e568a4a82b3b9cd6","nonce":"5003994c4d02d48a61716788","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"455ab7192f37cc500f9baea9718c72676ea30794154a3418404621d7822886897231b14dc03a781316d803f95c","nonce":"5003994c4d02d48a61716789","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"8dbf9b2fcc275637c376befe09c1b497390c200a37d2c016c5f3105078cfebee4a10b5fa5e8e6057ef42c7a75c","nonce":"5003994c4d02d48a61716786","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"3db9b250983c767aed98f9124fc947e2709a424f1cbb53a873e3bad30746463b1a1efbd82dc7dd4aa2855115da","nonce":"5003994c4d02d48a61716787","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"03c50a59b6a269323e7dd04feaefb5212f0b9eb753add32a0c8a0d7f4572dcea889930c4957f2be9d0e5aace64","nonce":"5003994c4d02d48a61716784","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"6e4970ee9357de6be8f1c87f2389f8eeba474901639c615b8f32cb922d6b8e3cd0758998eda5568004f5694e85","nonce":"5003994c4d02d48a61716785","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"d1af8bc76db654b4cf92cdb26656d3fea607f809050da854c054930d1b95c73c261094ef5e9d6bb96d65afd517","nonce":"5003994c4d02d48a61716782","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"c8d355b41894e58412572a1041bec98ac7298f35a90f05a860ca2a99d07470d4a208ffc35a166038dece698801","nonce":"5003994c4d02d48a61716783","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"0779399451813a9dcca459b2f24439b98ccc766795efcf9b81c5281eb3c6b4884711aa29d9717cdb820baeb248","nonce":"5003994c4d02d48a61716780","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"a547c52a936e8e9565c9dbd0648d616adc3b8071793a83c494d62fcf1dd2fd3962effff6e78c3352c4389e6413","nonce":"5003994c4d02d48a61716781","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"8a1442dbb1d3fb2c91c7070a9f1f2a339acc409bb639b3026aee34c9ca7e1b9bea079e416a2eb62111dcc25089","nonce":"5003994c4d02d48a6171679e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"b315236ce950e470b1d9d0e896d037621f9676862060e8d16700828f68b51746ebd2f8221617907549db0418c7","nonce":"5003994c4d02d48a6171679f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"979bd2a8a70f265eac510653e682b97a7ca6c4959e177b342e4e22a4ac5f8dc92565c923b43425065ac017d5c4","nonce":"5003994c4d02d48a6171679c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"e805f038dd6a841ead918053686fc6759485309fa5362f8e8e72c3403a09ccea96c742502dccd8f4ebbdd5f466","nonce":"5003994c4d02d48a6171679d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"478ac13395385abc67e740a1c6852fcd99b0f0035a05c997bbe0e468e7701614a2bf166030c7fcfcfd8d703666","nonce":"5003994c4d02d48a6171679a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"44e614365f106f583b999443fb17a372756bd8bc8feafbb723c04ab6070e9b7b61e4f0cf4c60b0890ecd73c66d","nonce":"5003994c4d02d48a6171679b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"c40eca88a3afdfa73441ec47d63840f7c2a5409cefc83337751a02b52fd054a87149576cb270b53c3b23a2d7d5","nonce":"5003994c4d02d48a61716798","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"9bb96e7214a0fa3146a1ffa58fc7ef918f7d6eb7d5361255420ef1e93f4a3c3cf887b43e844cdf4bc426008a23","nonce":"5003994c4d02d48a61716799","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"46d166b8f1d5c359ef17fb2f1d855c08b19d86a153a287a6dd3c0d33ee330e275c841b1a3d80fd64c7bd942931","nonce":"5003994c4d02d48a61716796","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"950f136969e696059e5dc28c7c30faf87ee9b9c6e0be919eb64d586a27519255ede343d1d178961183cf06904f","nonce":"5003994c4d02d48a61716797","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"eeb3da15c20c34216450ca421c088b976b21f2509f5a2fa098a649e32738e9311ce1e6bb9f0c86b67f7019a51f","nonce":"5003994c4d02d48a61716794","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"170b4a7894d4047276442e636808f55210136c1644dd2a028a3b614a2e279310d7dc73d3b5ac3993f1c4a64b7b","nonce":"5003994c4d02d48a61716795","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"28b8dad536c8059555bb4769a527910bc2a146f8810945beccb484614d12a76ba6145d57dd5c36c1c30b563952","nonce":"5003994c4d02d48a61716792","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"14c8885af71350ef6a5d05d5a6df227286b3522d8a6c12b73b2277b58f806f5d5b252b1e895bd8bde77d721737","nonce":"5003994c4d02d48a61716793","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"e0da379a991f08c8cc06fb7c48ef0dbccdb8a65d46591895e3e82385a3fa01a3d1c8a7817be30261e2bc361702","nonce":"5003994c4d02d48a61716790","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"deb4d45a7acab4974fc08d2464eee5cc757101f2769e6571e03dfebe6adc80e739843f2a77c2b0313ec724cbdd","nonce":"5003994c4d02d48a61716791","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"331c6f2c16bbf6457e106609caa009447ce703cad37fbb5a030ec112a50ef8ba2c6f9916265833898c89867ecb","nonce":"5003994c4d02d48a617167ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"dee5278194976f548d7706afda5e57e80f2540931882367b3aa7ac962e6a3661b58442beba93ed5d771dfd6722","nonce":"5003994c4d02d48a617167af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"2b3d16e8445720fb7eb66b3514c10e95b70e30b5e571995be225668c8832d0d89038a2ef71a6554cb9535ef611","nonce":"5003994c4d02d48a617167ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"35eb75e01a48bc026749037315d5366538ad9cf62bc7a97e219b9e696f1f54c574a12af6fd157e194ac71b24bf","nonce":"5003994c4d02d48a617167ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"2009562866e30176d9fb565472a8b04a23cf695f8c3a555749be73f94190fe45dc5c323766a8e4fb425a2210b1","nonce":"5003994c4d02d48a617167aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"55437b3742841c437b48f15704eee2dc003ee98929c6b3bc363d8f93fac261c045e7d1659d2c65e1f1c905d687","nonce":"5003994c4d02d48a617167ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"de45fee2d6cf6f63fb64eeb2933c999567714aa34aab3ccad5a05c28ca83030f40be6bfab9bee239444f5229d4","nonce":"5003994c4d02d48a617167a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"2889ce6e98ab78b3b41cf1c9bba6b9b44697de72184bc6e2fd7e1d614695bb0e2be67755437ebfea92110d45c0","nonce":"5003994c4d02d48a617167a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"89b00c72bab299feaeafb7527b4fcd7b2a24d39fb33231b5e6e80a78c51259ec3a44bcbe265a8b7eeab3823a1f","nonce":"5003994c4d02d48a617167a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"549e19fd739ae4b4fa7c7dd82de22c5b5fd03ccb1c4a54a38e4a85470bac2aa0075642b967405aed3591c26827","nonce":"5003994c4d02d48a617167a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"71b9237f81ec778d4f592f63ab4113ffc838bbe3f65be21d8bed9f6b4e2f1a8314e73e12b05e8e73903bd521fe","nonce":"5003994c4d02d48a617167a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"5c4c72c416a9f4e3f93124428f3330ba7782108ea36d92ca1a20a406f0bda6a86699445f325017ee5f12f79c9b","nonce":"5003994c4d02d48a617167a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"1eaa8978b7732a5fdd946d23706d2845a96f5cc27b58ca7a821de8c21548b67169069f2a9edabdf762be6afde0","nonce":"5003994c4d02d48a617167a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"24d80ef64f62e24fd934c0cd8566b79e2f87d461520008633f6335e7eaa79a7654e7c63b4891fa0c8a71341526","nonce":"5003994c4d02d48a617167a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"9e46c6f363e17f3f172df288cc48878318b34e66eaf44d6fd89e950f6a8ad30726db5ceb97d7ef98f396921010","nonce":"5003994c4d02d48a617167a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"268f622d661cf50916f3b2350384687d05942d8c3ff0bd7953098195364d9b554bb85f7b98bd2981828b502a9e","nonce":"5003994c4d02d48a617167a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"262e8b6dc938bcc68940f1ac2d2e93a479e18701cf3a76ae3d94b1a368bcfbac449cbe3d01280ace4d921a76c9","nonce":"5003994c4d02d48a617167be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"b6bf01e3d8acedd430b984a875634df9a22bad8699e44433d45cd7ee745bd19ac2614903413aefe2ea37e5b962","nonce":"5003994c4d02d48a617167bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"4693773970b3d0577689f88d96cf7a1f0ebfae260ea446377230ffb78d3281c0f167e2ff8029db0db909d9dc8b","nonce":"5003994c4d02d48a617167bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"6b565978c79d97454d9a2cfcef9df6780429f9f1580dffafe26264649e0be820aa786956bfdeb969d079501613","nonce":"5003994c4d02d48a617167bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"9ca4fc71a35234bfbfe328aa7569e508559e40554c8deb83ede89ca2e93322e56ddc42f3041b0db469367837e4","nonce":"5003994c4d02d48a617167ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"91643f6aa268a56eac53a7a3ac308f75c1230a722d0b6a1c48563534ebd807b386a0eafb955ef3be47d61feaab","nonce":"5003994c4d02d48a617167bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"07c1bf9ebb1af6194bab7bea803453161e0879726c582ca66a4321a51723c467238db46a1cdf1db32fdab8cb0b","nonce":"5003994c4d02d48a617167b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"4472f480510a3976371673fae13ead13aceae4502b354290efeb038758c8bcaf2cff13cf442b1d00f22927c6ef","nonce":"5003994c4d02d48a617167b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"56bf48823d35d45ad9f9da83ad18dd7b3284dd31eeb90f2bb2577eeeda9b4591dcb5fae3c9138613fa079969aa","nonce":"5003994c4d02d48a617167b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"682f9acf0471b47a1f04fd1eada6a5c569cd2e01de0588643d80587d2d958c2f124a33f576af2199af18df77ce","nonce":"5003994c4d02d48a617167b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"fc7c903b6fa1657ef7ccd2ea0e804daa513e8926775baa11c18084988035ffff77c800994fb31d345c5878b632","nonce":"5003994c4d02d48a617167b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"93824f774c1112e5488a3fbcf4c71ce65bc1eef39f49742efaf4cef75b6aa1b43e4148eb300d584f2b70806203","nonce":"5003994c4d02d48a617167b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"db3cff47ee26ed8f68c86ec7da8cd7f981eeb8d0e08a59c91a88b02eedd9c3457e4ce3a17a576dee5cf6bae420","nonce":"5003994c4d02d48a617167b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"560d85718d1f13aff295003fbe994e8be3f121948865e44e9da1899409f1fe698757879a86b8de3d4e76e7dfe9","nonce":"5003994c4d02d48a617167b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"09e4c64abb15cfa4b7b48494a17cdef890b1d3f1a9289817037d14af03a35def45de7a3e8e1190789f2d82b319","nonce":"5003994c4d02d48a617167b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"79ef79f6a63575a6374ba54be8752a7e465246cab55924390a28ef4a70250f3fcbd65c148e2a1fa1bc5662f78c","nonce":"5003994c4d02d48a617167b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"8b700a895c72da82015bc25abe384a1f10c96cb1d46a650253b1a6a81e5b972258fd1933cfe31fc2d0bed2fc57","nonce":"5003994c4d02d48a617167ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"7ea7c12cbc8e2e88fb93b051074f972ec0d80a464715f1a1abaa091550520caa965d9681550d8d8f0fb47a4138","nonce":"5003994c4d02d48a617167cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"5a841128f7fa3da198039109ff8e8f14e1bf6c3572ef8d01d5486b0d62a94f8b9239b3bcddc58335464693799f","nonce":"5003994c4d02d48a617167cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"941ef9efb3dc8431e1efa76b3cc53573c9c754a41e4e582de7e29f60da405e1ae0e4fcfa4a4625a2e6bb366d13","nonce":"5003994c4d02d48a617167cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"433d9f18909b8f46748ea539315de537149bc4c9f986fe57973dcec40cefcc59a69e739c2f306197875c1c42b4","nonce":"5003994c4d02d48a617167ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"656627405473ae2e6ccb7367a4b8c3e74168d9be60e60578d10b04b36fce5e77f631313aba6451ddab0b65cf8f","nonce":"5003994c4d02d48a617167cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"4945ec682b04ba5d77406abe6272f2669b33e840e858ac28c99784ef6e7101c62ca54f89a183c739eb95c38692","nonce":"5003994c4d02d48a617167c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"51ae1fa662809f407f0f1eceb3420cab81e1cb8d762020d3663a68fe5d5f81af6c87540216a6075dccdb97b873","nonce":"5003994c4d02d48a617167c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"4da8e01ba1adb2af7ea4ce778ecf314d947125a0291eaa0b535dfebe1126f2ae2bb6fe3d3a1b3c52ab7670adb2","nonce":"5003994c4d02d48a617167c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"a186152b66d1bf40d094baf341bcfc975b8e4b207901d096816cd979d6c81bf0a8f5bf9fd2433f2ac7a9b57305","nonce":"5003994c4d02d48a617167c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"6589a74337762eeee4b082c5718ad9e763822cd3488263f3ee14f20ff056c9251669720e7481e22ca11b831d27","nonce":"5003994c4d02d48a617167c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"d4c2f138ab2c2e472cc553fda00e6e35ffcac8308ba32f8473748517fd8424de92b30eb8b6a8a8c48de5cc2635","nonce":"5003994c4d02d48a617167c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"526f145f52e2846635c32a5bc46089d24f8924af8c3ba76d251a5e2983cefc747094203d8a63bcfd1c2fd1aa62","nonce":"5003994c4d02d48a617167c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"36211d42b7e284620f1660e487cbb042b2bda565cb84e9219738a9478e81698e2adc9778b2270e9e4b2a0f7b67","nonce":"5003994c4d02d48a617167c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"f62b9f7dd958376ebcc4dff961279c7a291d4a7644b88ffe4d88b1abbe5fb767f0a705a2199df31d4f2d46bdd2","nonce":"5003994c4d02d48a617167c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"4beca58ba45240f97d19477752aa8dbec31e2d9d3bc8fbfed4166ed43f6fdd81ed80214db2f0d04a7befefc517","nonce":"5003994c4d02d48a617167c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"c549ed4000fef1066c36fdab101d8c12e8eae21d22a6d652e13468f97711e9d1b9f40be2ade7190bac629729cb","nonce":"5003994c4d02d48a617167de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"ea6ed9482a2db3bcd854cba790d4c6ef93fa87fd44235a89e9bed009d5b9f45a8a6a90a62e911de9348df71727","nonce":"5003994c4d02d48a617167df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"deb6445090d4712f92edfa9ea3c62fdcb588082ff0a464be152a42121104d8562f7200fdb4b9f0e6ff2f4ac322","nonce":"5003994c4d02d48a617167dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"ad7b12bfba7381ceb57e0a5ec31b84264771796f14500400e31ea8c2e6cefb38f6009a14261c77c96a0053a8fd","nonce":"5003994c4d02d48a617167dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"f7ab334626967ec7cb16acec85859947f6edf9d8be4b244ce4510bf9aae13bf417c8fc4a56da1a543613506623","nonce":"5003994c4d02d48a617167da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"029e305e59ed18441cb35ac8873d26f4f4217b287fd69bea1a2ee06b4e6f0e32aa26ad982b95d6e88014cd315f","nonce":"5003994c4d02d48a617167db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"2d9a4c6d6f8badc95e5ca6a1af0bc247001c5f0922d8bacfea20985f2a434faf2c18bef1def5de9aac12356379","nonce":"5003994c4d02d48a617167d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"7c24f5f9064331f89da37f3aa4cd0cc385cde2a424703e36a0658e7ffd85affcf4f549ad7eaecf67bd3e9e5b39","nonce":"5003994c4d02d48a617167d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"27867b40164b06972304de6a39f8348dbd74cae03d0e3993714b32616256a037dd4ac2288a6a9fb871ed90d484","nonce":"5003994c4d02d48a617167d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"b0ee4facb7e26ac857caefaaac8fdfd8a11194d8891063988faf328fc718b45f3367a9c421cc7e0d9bf00e90fc","nonce":"5003994c4d02d48a617167d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"dc226710ff732d0fafef53fbed49f6771f9a7a432a14b090baa4d69fd215c4e492deba97fc2296b4cc08652763","nonce":"5003994c4d02d48a617167d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"9cd785ab2dba5e1acbaca87296d3f18f29791388b9b02624bb065fa695c1db7b19bfe477e038aacb8b1b31b89a","nonce":"5003994c4d02d48a617167d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"5ff8f71be5a5e43ef4f8b550d90e3e0cd0301eba383d41c85448ecb6bc9658bf02b5fe43c962126d725b29e46d","nonce":"5003994c4d02d48a617167d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"515f711fb957986d651177590b93b9c82c904c91012de80b89d4a6eb4de1f096e4c5d22c1bd9554ecd3c51ec25","nonce":"5003994c4d02d48a617167d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"514668ac4cf4c5af617bec8268032d200ac781f97322947a7d606aab1a5fcd5f98903ec6edd95cde88dfca4f25","nonce":"5003994c4d02d48a617167d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"add87450f454c15ab5e1a08d0abd8b6e12410be50de468c369ff9d584e90e5b1573678bf804b064e41ff5fa3ca","nonce":"5003994c4d02d48a617167d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"19e87153cd33acd532daca3e5c6f53a4c7f54af08e4beb22cdfbb14436e5813e47cd65b8f8c0e356732b9dcf85","nonce":"5003994c4d02d48a617167ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"7818d2da2c83baacfc00fe5a33397c10957570f03df4f9cd9824d8ac77e5cfa6472ba7feb4476827120524a24a","nonce":"5003994c4d02d48a617167ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"f81bdcbaf7c0509693bc5ba52e403f5810caccb8276882fe10cfde16204c6e1761ddf77191d6894ddb20656a5e","nonce":"5003994c4d02d48a617167ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"33949dc014530f1d24b8e66dd66312d23c7f0caa4ea56eb22c9d37f43fd4cabecd35e4bad55c17fcb39ba4a7b9","nonce":"5003994c4d02d48a617167ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"66c4b86a80d7932d08c5ab6a595b01729b2beb1595402e51d34695170b670e2290732b42894efa0df7563cfa38","nonce":"5003994c4d02d48a617167ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"b511e221fb474fc52c0664358c5ed08f733a54ce0bd43769422d106d50a379690d9b19a9f9555e73aff3374223","nonce":"5003994c4d02d48a617167eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"c7a0fac62162f66515a00da00f2c5f570210a6c7eceadb634eb90f869975c20fc9a0585915050fbd8e1871901e","nonce":"5003994c4d02d48a617167e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"3a71652cf3404b75e61ee3db6e2989549637ea5cab491600badf604eaed8309cf8177e91cbd8020c6968adf293","nonce":"5003994c4d02d48a617167e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"3f5b0803cbd855326cca54fbc7755a2597079d7d8ee4acf6c7f3325424239ebc293929d0fc8b2468f2ed9d0a3f","nonce":"5003994c4d02d48a617167e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"aa3c000b9f599c9dcc21456c2d1ce7b1804c3796adef5f963366fc9163579c610aa5c730f5f22cddaec2b0cb26","nonce":"5003994c4d02d48a617167e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"762e5dd5c008b09c7c832cbf45f789a72a4ca01f2c2bfe412935f9632ede757debfa38c514253a5c2a5b86ff45","nonce":"5003994c4d02d48a617167e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"f0bcc5166d8dc0063b75cd525e008136117c6c3b3ceff203671ca523419f7aa4e718b9e57645c7fd017479494b","nonce":"5003994c4d02d48a617167e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"e528f01bab6b2cff4ab182c03bb17efd936cc5cbde5e882f64fa10a58457bd031b9466ef006be8244119748ac9","nonce":"5003994c4d02d48a617167e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"df4aacd3365c2a179078c9f8ad43f98086ee1d4d53c2a2b54dd60ceea0fc05ed966c7fcd6a776410c7818c5703","nonce":"5003994c4d02d48a617167e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"4f96f9dd9683d41e023afc6fd0679403865cbf353addecae0845359153c04cc72b8be319060824e47a6244e20f","nonce":"5003994c4d02d48a617167e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"8a3d8f11bb8811db00997c5d3f4aa799bd5ab653a1d8a05287fe0c91acce46f984f4d476648ae2ab338234f477","nonce":"5003994c4d02d48a617167e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"644e1a8c2f5302945c9f32e0907aaa91f3ba16f92e44a6c1f570f390aad9f376fec362dc73517ef5a381fb09f8","nonce":"5003994c4d02d48a617167fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"afc92f64d566c315a57f7db5a728ef3722329a896ffa5dbda50d3254e0f12728d12df22249bd3a15e697edc879","nonce":"5003994c4d02d48a617167ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"7a027f872ea830a2abeb41f7268b5d22c7152cc35da74997b581637e6eab1efec7597b79b0290a18d3ecc743f9","nonce":"5003994c4d02d48a617167fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"60a5bd95f5405887eaea6fca05b3f1ecf3423e945e5355834c8befd658cb3a5cc37bfcd74e5c0811e56c432e34","nonce":"5003994c4d02d48a617167fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"065e6de70494241e7ec7cfcebb209d6c22e544fc35aec2ff17c4b136e48f42b1f7162df11296df02b1817ec887","nonce":"5003994c4d02d48a617167fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"20361f66518b07471bc48215c82f3f8aae14942dc5b0fc5662ccf8d64efb754c4f17c6060f01256b8b36a98020","nonce":"5003994c4d02d48a617167fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"7684b6971655b5da022240674adf5e5becce9c43eba0b3e6a0b9367e4312c9b8005c7bed75c74b69f6d6084850","nonce":"5003994c4d02d48a617167f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"44db3bbbfedb7343159c392cc902af7e2546bcc3667ae8aecd9c2b929dcfa5454114435d4a7a32636e6c6aa3f8","nonce":"5003994c4d02d48a617167f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"e48d639c29ead9bc11ae8b56389e53314f9d097c65360f6fd1a202966347f9885d15b2e82bc10d04690974b788","nonce":"5003994c4d02d48a617167f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"275d3d9f21cf63e99e2e609e81913af70735bac2e357c1c4e0fb8304770eef4adbc3f154896801487dadf0fb1b","nonce":"5003994c4d02d48a617167f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"9793379c1f55a75a92ff6538b13ce459a37181c981978d783aef1dff90f275d5a48493411e0a15eeaf5647e7ba","nonce":"5003994c4d02d48a617167f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"ddb790563d1cb71bdea3aca25f7e157a97c331c2fe4e4f5578b0b9470fe44c7207744f247d29f3ee21be2fb07b","nonce":"5003994c4d02d48a617167f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"93f8ecad84b836b1739f78313ba73003f37c486a3d7726414daad734bfccb38e018ef6eb3c59a17dbf0fecb7f4","nonce":"5003994c4d02d48a617167f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"f991af544e5eb0c7444051ff7ffdb0c212cd01a19744cc665a027d99b91217193cd3003513812d4ee6dfe1afb4","nonce":"5003994c4d02d48a617167f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"faaec4acf1fed3c60b00f98aabf50d3d2cd0a9f2fdfa08dae31872a0d07311c0ff6a9f7ee86e9acc59714def6c","nonce":"5003994c4d02d48a617167f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"d4dd86e2ee3febeca128873f521d85bddcf5d08fe6bd6291313ac14244ebba84da4d236e2c612c7823af8446d7","nonce":"5003994c4d02d48a617167f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"79043da832b89b42e588157e1585b304e2c86ad898651fd82aa14d4d8d9528da49706de080728601ac7ea63d2f","nonce":"5003994c4d02d48a6171670e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"ec95afff59f9b47d1d468489fb1c8a6dbc17fb896599ae76e3895ba8d296fb6020527a3bb70ac907d5c966e320","nonce":"5003994c4d02d48a6171670f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"b17cf6bb78df1f26c7e5bf1554d302e29f87062659cb887c5cf8b4ef2795385626e954c801c65078a41886f2f6","nonce":"5003994c4d02d48a6171670c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"6021344b736612956965bc822698edc1f78c1f968ad8e676637fe87cca13ab0b29a6c29a14b9e63b62779ce2fe","nonce":"5003994c4d02d48a6171670d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"d060347eecc21a445f88d7d8102ecf7c364f5c216388f5b65391da29fc61a187c38e718770b99863ab7af61fe8","nonce":"5003994c4d02d48a6171670a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"c341db5637c3f7aa79363720be2ba109bce6a3164e2df09200f0eb49fbd1885a6f28072a4248895e7586808217","nonce":"5003994c4d02d48a6171670b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"47f52c808ca5eb62c48723393fc3bef57d395a52645a835ea0d132de1139b96002c9017c2e40639f16f9e3fdc9","nonce":"5003994c4d02d48a61716708","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"e5fc05061ce7cc34af939426c9fdd56655dc1948484ef49aa24be8e0fa3ce1142a1b69fb6ea3bedc678af72ac5","nonce":"5003994c4d02d48a61716709","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"a2bc7d93872ce1f9b3ddaf83b5f55ca50e48d7de4ec6e6f38724abe320f87f16d043e05e239c3ab2e894370f30","nonce":"5003994c4d02d48a61716706","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"6354afaa2dcc9b216a24d5d80619689a6babbf495da9261ddc3d9634d1e14da031aeb0fdf41c36663fbf914d4b","nonce":"5003994c4d02d48a61716707","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"7ed32ea65a71b21b87a79f40af7355ba679dddb675c5d774c92003268d59e16d651123579a18d9edb36347ff19","nonce":"5003994c4d02d48a61716704","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"5cedad485ae33f567d012c4632952776cabeca3f6e81658d3571c75aeb964e9b0759f402b46db753114a9f5cce","nonce":"5003994c4d02d48a61716705","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"6d97f5978261c787c32bff7bbad5f3dc3c404ee8723b7cd3b7c149ae8ea854d63619ab78599140a4816e556d15","nonce":"5003994c4d02d48a61716702","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"4997b3ac86022ef4646dc33b9c0500ddf6038ec9cad1dcbd39ccd59ac6942bac6f6381f677ba699cf19f86e089","nonce":"5003994c4d02d48a61716703","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"7f3613d37ce9baec1ec0844e3a36e1363d61df35e7d9c3aa7e5d7fed9f5270a1db7715ef8f4f18202ae5556a8d","nonce":"5003994c4d02d48a61716700","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"4c3df5dadd01cf18d7e86027f71f4018f31355db7da0278ca8250d621c2f1312d29333b39eed29369e07665c1f","nonce":"5003994c4d02d48a61716701","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"5e6863aaf5d18d3591ee73ec0add86367dcfce3379c3fe893849817d196be57f97e79241e3a85837ff2a3550bd","nonce":"5003994c4d02d48a6171671e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"b4eee1540511e66c331eb70325732b8499012e6daafe4d815adc24fbcb179214be70a539788d6e67aba6893bce","nonce":"5003994c4d02d48a6171671f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"24c72bb6f6432cafbdacfc58e633caaf1ab75102f20da68dabffbd84777b1ee3bf6c56a5dff714a67cd58449f6","nonce":"5003994c4d02d48a6171671c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"a7d62857604dad6cf0cd7f06e584866859ee49a9fd5f682ea5b702f2b3ce32a1f91844752c06bc36be4b417f56","nonce":"5003994c4d02d48a6171671d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"f4231a64435a6ff3a1bada551d4eb7987e1f6da524dac5e14098185c63dfd666c3f58889de4bef93fa4d1baa08","nonce":"5003994c4d02d48a6171671a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"2e9c7200cd3059e7ba9ccc252a0c70288121916939abcd5a33b6451ef4498a8414943fdda4571763ff6e751f94","nonce":"5003994c4d02d48a6171671b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"1b9e71f06fdf01e72ab2f115763880fb24970c303e62aadd523a227942cf613727bb712324280563674dbd270c","nonce":"5003994c4d02d48a61716718","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"34ae2504b14bb058d76b50525049319023705a33632c2d88f83299e8ec38e76ccf99dc7bedc29ab85cfb6ee214","nonce":"5003994c4d02d48a61716719","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"33f66a9937d2b62e592c0ccde2f2abfb46bb91777200c235a2c84cb48f2e0821670a77e1311b3410da09ed49f2","nonce":"5003994c4d02d48a61716716","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"ec829c37ca203776d6867619a4f773ddefd7618ac42933a708a1abb42769514e2641068098226213b59c8cd56c","nonce":"5003994c4d02d48a61716717","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"9b319a4123929fa8dabf5f4386943788f6c9c4571b2e6b1481e71c9196bcdea30d60b03e535038842eae65afe6","nonce":"5003994c4d02d48a61716714","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"2083b58b6c29cbc6326690539a3cee89f9dd8dc53ef9234f7e41582915ec85efa260e747a9d13891356ca2f559","nonce":"5003994c4d02d48a61716715","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"f48033bb219b6a146d92086d524229aa2c6c035bb55879af678d5c95d8cf2c27ba376f6134c18eb6b5fa4e3c53","nonce":"5003994c4d02d48a61716712","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"d1b8b518a704567070adefafb4b0b9f58f0dab2b7ed35bfc187982c28f60bf01d0329b8dc7505d44b2060e6a1b","nonce":"5003994c4d02d48a61716713","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"66c602ef2c4633693dee1535db11ffa497a5088d3084c7b9d3a8a35c5625ec89e83ebbe45be2b216d01efa4276","nonce":"5003994c4d02d48a61716710","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"6e9293aad0ba2c9b911ac65db7d212d07e45c56d246dfaae7b876e2db8a641a0e474cbe57c772326a20663ce2f","nonce":"5003994c4d02d48a61716711","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"67b8ee96227ba721188a00a61243368f16f04d7163ba6ca53406b6b8d0f5715dc819cbf35b08b2a697696bb036","nonce":"5003994c4d02d48a6171672e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"502460e53265d6ea692efdfe17a86862ebef069cc5474ccb9bc6e8f4cf03b53b96e1c346411721ec95c94a8336","nonce":"5003994c4d02d48a6171672f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"9fc2b4219aed93897d12bfb38e601d3a74ca423d2fb6fa0474be8ee996224776980ca144be48d18860fa58a053","nonce":"5003994c4d02d48a6171672c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"7b57923ae7e29cc6c86d6d83824d77b638813d37be4e3e0272e6360b627049275f19800e6fd09c871a55dabf38","nonce":"5003994c4d02d48a6171672d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"05958f41ec218d16d72d4b5cf023a73510c0036dee878bcb26a5fbdb0f12e0741b3c627a7cc97f2eaa03c63da5","nonce":"5003994c4d02d48a6171672a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"576887b600991ece999803b3686629c42b45b2bea3944d7131b2280d3358e8521b6130218e97fd6a8459c2c4af","nonce":"5003994c4d02d48a6171672b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"8586206d6a9161dcd1c09936f6f8723e74bf437999986c382d03bae6f12ee82c6a4be44a59a2ca868665493db0","nonce":"5003994c4d02d48a61716728","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"0686b63fc3d073692e61ece7d86cb9609d8d8d76bfb08d2d403bdd929b86196c5a06f38a49f7ff65c716783cfb","nonce":"5003994c4d02d48a61716729","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"f18e274ef7469db167551205d30e6b18918c26d4d85c7fc633a3a49d8a5e8d7c6a60605d356203a937058b851d","nonce":"5003994c4d02d48a61716726","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"7df3be804e5da8c88fdbb998a280b3441985b1179e49365047d48f783ecfec609c3674835d029fcec031a95522","nonce":"5003994c4d02d48a61716727","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"4b8e34f69443aaab6ea53b7c1f1b12af30bed644829acb675b6eb7bfc13356246b0fce81b5a519af400ced83c1","nonce":"5003994c4d02d48a61716724","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"0b0337e28b6703a162c84830e1071bc3daa71de0f9767d31eaf99e282787359d23b3018401563441b5e03d7619","nonce":"5003994c4d02d48a61716725","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"14981ea1a1f9f5a77bb657caa2ea6b65962369efb1e824a669ba03d9c2f2c526225c7bd75ca4c106b333d12acb","nonce":"5003994c4d02d48a61716722","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"bbe5bf8a3cb8a56128dc40dd744958f191fa6b6ccd71f6a9b4c486ead71ccef7698763660c29881d063b60024f","nonce":"5003994c4d02d48a61716723","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"b9e6be3fe65121f180cce8fe798a46d1cc6c6c63b81ca9b13bd18528786dc9aacbb294461e66868c8b26395db5","nonce":"5003994c4d02d48a61716720","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"6dbdd4484ee43e34736757fc838d6d3ba20df75aa41f513dffdaffb835c329144440d0ea9c5eccc0b86a2050ce","nonce":"5003994c4d02d48a61716721","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"e07e96b18a562ae51a2ec5ef4e371d605df229c005252f85e19d009053cc7a277aff68e59f883195065e46ae4e","nonce":"5003994c4d02d48a6171673e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"207f49110950c3887aad071e9464b99281d581bee04b5264e84a0eb735ed2b34d6dc3cddc7a68fc00290045384","nonce":"5003994c4d02d48a6171673f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"2b694aee2cb9b20231d96ecb582df4f79fcf71a4dde6a7f1066d70714c322c79120ddec5dc77922b8377824720","nonce":"5003994c4d02d48a6171673c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"5b715149f78d64678466eb4608eccf3efa3361613ac542d4bd50bc93e9cc42e307aa2e623f0e2ee2b133d081bb","nonce":"5003994c4d02d48a6171673d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"3bf72d882b4d1a7470253fc1f2b1e361a2db5c5b0dd672e38502e09ff917687bb02510487297bb05e0407e985c","nonce":"5003994c4d02d48a6171673a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"c80d87d3d1792effcf29f264af4305a2ea682cbffc0cf6cfe915db1e3e234c2ec80ebfc035a9ddb69bfc2e4e14","nonce":"5003994c4d02d48a6171673b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"8f0930cc1f76d701ecbfd08aeb414e5e0461b57f00226ae8e3f9b28f31a107cd7e41093d37265b8a135413a1fe","nonce":"5003994c4d02d48a61716738","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"3f3d51594cd68ed0bb6e19cec7ba78ed74d716dba0a064bf74f77ac5a9dc86c230a57719f9dd19a7c506719093","nonce":"5003994c4d02d48a61716739","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"ee03b554c724605ebe6d28836532e28490e487f22377fa0799da9003a4d35332cedeb80758ce04bf6aead935f0","nonce":"5003994c4d02d48a61716736","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"ac161ce435575d11be05811b14a5ab558666b636d9f68b6fee27f9a6e26e346abf8a8a9675a238897ebc8e0559","nonce":"5003994c4d02d48a61716737","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"8c8812e05a6fa3932f3692e28a3e88e36de102e80e80290508f3d5e22c9b993e83fbee099446f000efde7f1e76","nonce":"5003994c4d02d48a61716734","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"afc71d029871e7b06a6d7215244b88c71998893c6d91ed2ac64cdcfeced5f806e8de0c4d108a46ccee616b2495","nonce":"5003994c4d02d48a61716735","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"762e4602ef00de9eb193b82fc658175bca50565283447c2cb1ac78d95e2d1a5b7e84850f0465b8972d75776a11","nonce":"5003994c4d02d48a61716732","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"3ffc78148d39ca1a574bbf41118f701471f3b8be08491f44f240c4c420a76a64dbfdccfda9f4fa34748bea75c1","nonce":"5003994c4d02d48a61716733","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"f9adbc93d280ab5aee8ffad87360e69ba82996991884b981f1cb809a77f7e4293293eecb119f7b9fb49881a1f1","nonce":"5003994c4d02d48a61716730","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"c8af6c4c52ca8f253d7d9d8009d27a574161eec405c5a55bee8c00159af2e946cd3a6ee655015a938524540e94","nonce":"5003994c4d02d48a61716731","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"baaff71c126b1306178dbf6761861990864f90d45eecb43370f70c6e6779bfda8686945b22ea007158bcb3fa81","nonce":"5003994c4d02d48a6171674e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"5ea33eb001b2772216a7717a292afe2a49d692103cf02c32c5d96b206914dfbb2000ab186ee20b2769b6fd0937","nonce":"5003994c4d02d48a6171674f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"bd2117cd12e33663d9c09896afa3c38c765419c317592dcc17ea6a8847d6930b85bb9be1d05424682beaf837ce","nonce":"5003994c4d02d48a6171674c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"4ac2629a6864387a7dc3f041cb5699f15ea19d823a1584844a055295c2bb88bfd6851eb5b9f1fc820013acfd2e","nonce":"5003994c4d02d48a6171674d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"d4f0263524217f2b7777cfef539d7063161ce8eed8302dce9a030869f01738776b18ba7f1bcddb92b2a77f1292","nonce":"5003994c4d02d48a6171674a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"1aa178b8fae86059340f538f926a6353a42bef3d7d1f908ec2d156a4396cc144d746de75a5a0317bea44d0a3e2","nonce":"5003994c4d02d48a6171674b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"7eb6a2cfef7694df86440303226a548d3035e08dbf710f9cea24ebf7eb2330b1abbd82c30eebad9b8ddb5cc776","nonce":"5003994c4d02d48a61716748","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"938e0396605fab5a4c4f6fc6fbbea33cad6c7de774cbe9d939a670d58acd39668e47029dc20cc5a7d3c18d5b43","nonce":"5003994c4d02d48a61716749","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"b72b5b22a966dbb55b13e0bc394a8b1366ae8ec3753ab56d85008a34d4fea380f9c7f312b01a73a1591b830261","nonce":"5003994c4d02d48a61716746","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"dd4b214a5054c53acc03a8c533269a16edd2cb52ab3efc86225c46b6434e1452e4886e5537bca80a816b567fa1","nonce":"5003994c4d02d48a61716747","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"56e4ac357849b7cb5a1659fc76b15d4d0a090887a78d6a3d03669bc12a8ba1eea932a807223f284b824fa8d54f","nonce":"5003994c4d02d48a61716744","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"ef398a57d5c5c56abb17c84479ee0c67f112d715fda0e76ba2eddcb1485f0ebb9cf800d7b1ae47d3fd780452d3","nonce":"5003994c4d02d48a61716745","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"c4a725fedcc8dc6b8154997b54704fc4e2072aaeff5a9a9feb9d7f076ccf9654730f8c4e6e28d0dedf2a6f1dbc","nonce":"5003994c4d02d48a61716742","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"a917652a1a716548672f1b02ce0c0fbfc7dc0573d6464da9e9b1d5fc0d4a4c42c02307ce849729871cfa3d5f36","nonce":"5003994c4d02d48a61716743","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"257cd46d0e698a8bf07ebe5a683369d0f4fa652773e03e4d61d8c09a003c178bfa92081fd6c7302535075dd3ff","nonce":"5003994c4d02d48a61716740","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"3f626b79a2f80b7785199be0d8357a1cc2b9144e11506e487a2cd173d5ea79fffbdb04f025f1ec480ebd15943e","nonce":"5003994c4d02d48a61716741","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"dd242bec95758f1607b0850f2a6edfa7247bcd0ecec43b841a7e981e4ffdc8e3b89f34b65989092338dc23a96e","nonce":"5003994c4d02d48a6171675e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"0a47c6851aaa674011cdeb649f70d7b57ad0e778469981f53d87a39fdb9ae6a6757351deea9d6ace01ef713f5b","nonce":"5003994c4d02d48a6171675f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"6532e811ffdb24f0dd0735e32ebb055e156dc1a5efceb4485aa242a21d9de1ff73e6240be6443f308c320a0c93","nonce":"5003994c4d02d48a6171675c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"2c00abc674e2bef0c18e254f9f7cc85fba536e215ea071952eb0c9d5fc039c209f20348e5420d5fc9df61b657a","nonce":"5003994c4d02d48a6171675d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"ffe5edc879ca2c22a7089c96ebdc824b9eeb1867d6f09b2e9be935e913fc1d2b1f22e3058e95287cbb7588d7fb","nonce":"5003994c4d02d48a6171675a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"19d22b46953ecca722a54c37495bd3b49fa57284493c80981349ca022ef8edb3a1565d7a33283d35d6d219cee4","nonce":"5003994c4d02d48a6171675b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"62e86bee51e2dcd09b0e09f1fbcb2b0e89a4c95bf1a4df2c7ede86cf1837c0809938bb2462f31eaf7ef0a42011","nonce":"5003994c4d02d48a61716758","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"743e76789d73a2ad4e2a66de12bf92f6146ace7d8b77b3d83ff5d46fc39f4c4ab4f79d0f4731fd6ec7a4c136dc","nonce":"5003994c4d02d48a61716759","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"ad8bc888c73bdaf13dc0b65bbfd749f8f5f5372cec28bb97e0ca8eef54ca6bbcd0c94cdca7268fdac4e34a4122","nonce":"5003994c4d02d48a61716756","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"92555a49f0191339f5f13921a847636f7cadd1bd4fa665c79dcb07efafb4741f429b3cd92c6f33c32421f693a1","nonce":"5003994c4d02d48a61716757","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"7ac1465ca648f067861c9755b7d3595d7b48b7e42f4a1ba76b8e18f135112a42d695dc2d3dbf4502a160ac4036","nonce":"5003994c4d02d48a61716754","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"7e43ae40cbc03cb0c3f41eba17ff93845b2d71062a9585ca4852963704c135c6ce1c47f8dbae621fd197979909","nonce":"5003994c4d02d48a61716755","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"0d6a799e4675f359ef627f849ba71e82278bac5c5ac2b6fdd219248f1c9934f822d41a7012c508089eb3c59024","nonce":"5003994c4d02d48a61716752","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"d46d565e36413262909511ddb8b1259497f19c4f5b89c8e5f8c53cad756c35bebb3485ece264d9e881f5e5ee3d","nonce":"5003994c4d02d48a61716753","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"767dba00babfaf2cdfe9f39c62193db4dad136de58ed8db597520b85f4c7bf27ab3a7de249f9b5c3140681e8a2","nonce":"5003994c4d02d48a61716750","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"7275eb91babf2b00b3e31f99ed1633eeaddc5b4d0df3e84104fddc532868f6cb38d8841881827f7895a4e345ae","nonce":"5003994c4d02d48a61716751","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"15eaf3297803114c627f20e40ca12a23c012a8f65daa4e969c57824f18e708f7acf2915eee03c5506e707085b0","nonce":"5003994c4d02d48a6171676e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"5d6374a5e078707781a018e0698f3cda2ccaa10b8c94291808da048d88fe20c852edf57980d323129e18aee6e6","nonce":"5003994c4d02d48a6171676f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"094c23a3c54106bc55258b8625f0c3dafcccb084223fade080472b81dc5722eb1544091bdf5ceab295fb337e1c","nonce":"5003994c4d02d48a6171676c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"e7f17a8bcecb8a4bdf0af80bdcc1cc0270f2d9b5af647c0ec12bc814c7ab246b6dcd9b89902cc187e7e6f1308c","nonce":"5003994c4d02d48a6171676d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"1e263377a17b1c0532556ab8cf1bd9aed1ad81d6ccf387ad281038c52358e3c9ed77b5baeb795d2ace84cc4b57","nonce":"5003994c4d02d48a6171676a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"d8b959680790a270e46f98b82f241df4bb5f5c5e2d13b92b3daaba0ab70fab3042dfdce933ec01296b6061abb2","nonce":"5003994c4d02d48a6171676b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"a4aac3af8f51de9c7a1560c9bc15b3e2e58e7b793c6df2f63dc34da00a0b803bd4f202a225d025777566b30e63","nonce":"5003994c4d02d48a61716768","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"fb19769b7acad9511af53855ae3b3dc774dba8b56f3cfece819a6352c6eda397af5282d06e670f3223cbe8fee4","nonce":"5003994c4d02d48a61716769","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"e2b898ba1bec0d600236c310d15f17cdc0aab67f585de066b42561ca819fe411df6f3bdf6a4db23c0247e16675","nonce":"5003994c4d02d48a61716766","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"d936d325e1c9ce6fb99598063d4d973a346eb6cf87a8b010b32e7ae84002bb91796c76a9a4e45cc9247cefab2e","nonce":"5003994c4d02d48a61716767","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"8520098d622e7cc86e6ae97cec6f8c96cc2a4ac3fae4c2fefdef806c16300c824afc5016ab9424d08da5593fa0","nonce":"5003994c4d02d48a61716764","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"d9fcaf6d7a9814624cbd6f2dd3e59ec4dc578f467f4024f9fe9a154763d0fdd1ef44e6123ed1f190f9e748341f","nonce":"5003994c4d02d48a61716765","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"611c90efcfe95fd74d4f99691a7972cacd2a22d6fa1ffbd0508fef10c5333c2214c4a066ecc9bbb893061426e3","nonce":"5003994c4d02d48a61716762","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"ad1c96c9de099c1b9cd711f20d7d68b649755ea61f249f84125bde36359d636db0564675bb11db82e973f1bd9d","nonce":"5003994c4d02d48a61716763","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"36b722afd98350faabca1874597cd809e23b5e990bf0e67d6eb840405928995d6f30ef51da45c3536e62276df0","nonce":"5003994c4d02d48a61716760","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"172a1fe1da3769a6fc03c41555860719412b9e4e475f54818c4486ccf79bc526823db19e3373d69a771d7ae50c","nonce":"5003994c4d02d48a61716761","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"5a1fd76778e1cd121c01d84c84df96d4f3adb45618383e1f5b75e89e14fc2e2d4df7e5cf1b2515951fca6019e5","nonce":"5003994c4d02d48a6171677e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"ea57c82f85a4a2aec208b64c8a5fbe8e38ed6b52c9a2c6d0f640b8d4a8f6c0bfa0ee726062069812a6288a6010","nonce":"5003994c4d02d48a6171677f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"82ed09593544e071ed711f2582ab0106c3784e533630d2a5a65dab7424ef05b6f2d46a9388cfa6c1afb0ce498e","nonce":"5003994c4d02d48a6171677c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"8569e03138267beb84dc3468d83a969e1236354e5986a3d51e4837bf02a165eb155c8ab73d3b29bb3b44f50df0","nonce":"5003994c4d02d48a6171677d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"5e1019a5d434f9bd5006deac9e601a6a8e955f20b5a82baa8a0ecc623f94d413c30b463db5fbe48b15cdcd50dd","nonce":"5003994c4d02d48a6171677a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"6104b843cc38813fe54ede3dcbfc18fc3d84057f7bcc46209d161322c25415fb5ff3cbf817a22819d3b0707206","nonce":"5003994c4d02d48a6171677b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"3a383a58985eb16fa1707848b28dfac74b6cb1c5931ab1ab5af697da1ee3870f7c81ad30739fbf67b72df495f1","nonce":"5003994c4d02d48a61716778","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"7eb065fb800824be62510875155cd29f8f849f2a990db35245391145f4008f1091ba9d640472339641f55d33f9","nonce":"5003994c4d02d48a61716779","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"be22780c238ee3be5cc1d6396acd83e860ff6753a061e264af29001dabfa8ab70729d9b681c0ab33ce48709986","nonce":"5003994c4d02d48a61716776","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"f674ad4b6b4838388c06f7d41635fac8e1a72fbf71ce98f69b5950b2846dad66d85dbe66a638546652199b1896","nonce":"5003994c4d02d48a61716777","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"833acc9bb92d54e8f6a6b39ebd641537ab005265644162887ac5ba72c423b7ded2731a1420cbf904bbae80d3d0","nonce":"5003994c4d02d48a61716774","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"1d25c32faf535b401a4eb464efb9f2686732f8dbce6269281f7cbe4bbdad4ced2871e76385996c40206596729e","nonce":"5003994c4d02d48a61716775","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"fb1642e61a26cb7bcb9afa1a56a94288e1ba0a055e84a7513d5f8e0a57f7738a6308d5ffd80d388c9974041aee","nonce":"5003994c4d02d48a61716772","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"9bda6815ef397f59c41339d7dc57e5f04dd88941f0d6d4e730390bc2617327dfad33ba1064e9e4d4fe57d28d20","nonce":"5003994c4d02d48a61716773","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"f8d7a8bebb6c57dc7044c5128421b4dfbcfbf070c53373cf17d59bef2c76bafdfe42da66fdfdeb9f204d49dd24","nonce":"5003994c4d02d48a61716770","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"3ccc4baf2947f7d6846c3bb2eec3c8bab77666d1e7355219c52db86c7ad3647a638b7cb9a855c38a3428c257c5","nonce":"5003994c4d02d48a61716771","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"9febc0ed1dc32c1dc2d558691650f8a08a7e214cf97424e4164713642e9c33a5ea668aca103d0afe685bfc59b4","nonce":"5003994c4d02d48a6171668e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"41d6c9d3bf55e158830a873d438253d18f2bebfcbb7d613e063592c914dae21b"},{"exporter_context":"00","L":32,"exported_value":"9e4d233e4192d9da819ccf7dc1ec42236263fca1218b3038c130b62364202e92"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"bfcc50133c37c30c4535d936b4a75c80e9c17fd75d5cbfd0d4a785fffc2706ff"}]},{"mode":3,"kem_id":33,"kdf_id":1,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"5afdb8111975020069aa7cb3c5574723010abb93ba70110debf9bc75aa107d5bc7965971a71da20e55de6af02658651833be89e4e2ccf789","ikmS":"702b62c3d4557392da722a8d76f424326108ff3ae9b52037269ec4ea24d811a7a2e16b9a38dedd219b18dda958f30ea2243531af82f80a2c","ikmE":"5321d2a653230de76c11ab1a86f97538a4ce5d2950921b221f78ebc11998ec6e05262c78ae1e2a644d8397fc722075a97a7d9557d1434fd4","skRm":"edfd085deeccfa5218f8f2009037d95237b26878c25a0d52050b2c855d4a5f5296631f1a289105e60fa7fe2ff5afbac92e9bf20b1d12c469","skSm":"8fd5f4a9db537906c9221eb050da14b4f0480d4a5a10bea3120f3c937d673cd2efed676ed33141d6d9aaaaa85de8240f214bdcc281fb4c04","skEm":"d5ef8ef5b2ae0b4e1aade2f920effa721aa597be84c0444170d1fd1cb1f91ab284176c58767b700160d7cabe7fef51d693272fa0d5114437","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"c19c08ebc63ee5c3d036ae440b16ba7ddedc975ec6c7adb86f72f6bade585f458ca5b1510a1be6a61cecfd4dec122e1ff1f44e4f4860c68b","pkSm":"04dbb77b45c4e442d2bf013ab3083268a03d2f2e54528c891516e711a2ce1b8c55199cd52d856222434716f12c17112a17164865e2b1ff2d","pkEm":"77799988cafa5e9319a42d782debcb459fc0ac001fed0c1c4539393e595ca61886fc06f4990fbd0f5b45dd8ec5500741e2c7d606afa28956","enc":"77799988cafa5e9319a42d782debcb459fc0ac001fed0c1c4539393e595ca61886fc06f4990fbd0f5b45dd8ec5500741e2c7d606afa28956","shared_secret":"f92bbd4afb1a76dd32020f82f56243eaab9ea2d6ea94c67eee015f3d28caad8fc9f38e526ea623a527861e1f8ad38a20204532e93b6aa502acffb7ba033670ba","key_schedule_context":"0313d73d3bc6ad29ada571507511d24ddb61ab73810d32ab71079f9daabf4ee3dc2030461bab15fdc38b55e526b9f9cbf3342bacd78553d0ce4eb4260c52b61d24","secret":"4248341482fe1619c6c15a6b68b9ea53030adb1c24016fb2929fd0ed8445515f","key":"85a2dc9dd22f8af5725acce5109cf015","base_nonce":"f24a07f28e0fb6144471cc25","exporter_secret":"019293060f140a25f35f04c1459f0e2d3a69b22ec855bb2767e3cbab60e54990","encryptions":[{"aad":"436f756e742d30","ciphertext":"b70c1f9bd91b8bcfa7242f36a3e20cf12ee23c55033aa4a092c05f08f20c10616d57949d9c496d779e68e9f289","nonce":"f24a07f28e0fb6144471cc25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"6514e42ef8ddba273cace99e9eee9a9897e8623e87bc3f9a583d0cd632ff6fdad6000ce1255678e1d2198277f9","nonce":"f24a07f28e0fb6144471cc24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"e30ec1c3e2934d384badc038ba1b8d13e1075e59b7c8e38c4dcb60fa7ab35cc95ba680fc6fc7c0054b48d8efe8","nonce":"f24a07f28e0fb6144471cc27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"6546b864f0b18a2e9c6874cd2875214a5a0771084d25572840098e68fff6bcd9e52b5191816efef037b6047a3f","nonce":"f24a07f28e0fb6144471cc26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"e814efd13ba497185d53d93d3b7e8150cc08f5c5dc8f97f17d3b263fec17779b6c6ff6f24cd1d7477a857d1575","nonce":"f24a07f28e0fb6144471cc21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"6c7e735c5d3d2f534c2d857477149d783e02e56b4e178b8435b4075fb77e9ab575052299ae549ce3e8b094aeaf","nonce":"f24a07f28e0fb6144471cc20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"3e0a0b05a2c2202e02916199371c4edcfebc945cfdd6c92f840444fb9ca67ff65982675f31ee56a433773ac93b","nonce":"f24a07f28e0fb6144471cc23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"62e2f7360250d42cae21a67222163e6b6ec8bc539018e3fc1935ffd41507e4320e1ea452ce6e683c837a928266","nonce":"f24a07f28e0fb6144471cc22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"9777e09fc9e996310a02c3632d4a4989382a63d688feb9738e79f6efe36ead02c0b640aeec8f8297182ef39d98","nonce":"f24a07f28e0fb6144471cc2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"4a25ecce5b98341b4223024709ca3fbd5d32da43fe1ff5ecce38a3c47d17ed2e1e45577a99dabc55f9bae62948","nonce":"f24a07f28e0fb6144471cc2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"e84dfbfd0a30041da9e700c6b337919f0a92f4238986dbd6d2604cda4e59968bd86e7c7359b930fc76dd0a2703","nonce":"f24a07f28e0fb6144471cc2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"62932efc9b2e739aba0d79fa43213975cecef75161a343f1c2f35606fa52eb494173fb111e7d73b9fa43870c9e","nonce":"f24a07f28e0fb6144471cc2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"37465bebc8e757c6eb2605aa5872d437da3e70edc996db850ea3f2d5464c3d3f6244e3c195a2edc093a65737ad","nonce":"f24a07f28e0fb6144471cc29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"1dccc999a08b2e045460fb24ffe3b137162e50bf2bfde93e09fba2812a9b7b75f247e28f641f641c01defd8970","nonce":"f24a07f28e0fb6144471cc28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"9759cf0c0713a14bf387e9338e4c6aacaeeb59d063a7e14aae7031617a60683d418264a1c0f2f72a3f8af3d155","nonce":"f24a07f28e0fb6144471cc2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"4718822420f8bf2f1a8d99020e8b1dfb49337ea4f92107ff3867ac4b6abf4ba12937defec920669688d27812ed","nonce":"f24a07f28e0fb6144471cc2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"400de43913d07961bea7a3c8454e7b84373462152feafd7bce8097c18cc1bc615d38b31eb85a68bcc0010f77ec","nonce":"f24a07f28e0fb6144471cc35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"ff57ee3511953793a568f127cfb946f89d0a46d75ea55e61f547c1ad8304c977cafdd8f287f45505a038c580eb","nonce":"f24a07f28e0fb6144471cc34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"ab4c09c62ea20457a07f1f26ca17be9dfec113e8e2e2124554f2c47c0f4b258b6d0f11dba2a9e3e30dd012ef1f","nonce":"f24a07f28e0fb6144471cc37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"0734f090433fc242507520fd96471773fe116ce50e985242b81cbafda4efec559d9fc05bb06dab6a7512605048","nonce":"f24a07f28e0fb6144471cc36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"64a4c020b04ad24d8e1c9b5e5046e0886edb95fe90256981465a388f2ea74fef8d29759352d47a1bd7597b55ce","nonce":"f24a07f28e0fb6144471cc31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"5a8102fafcc2b0c8105c7bafa36fbbe16c3f261d33044ed6bb8bd389889fe2742de4253ca05837b4fb0838fac2","nonce":"f24a07f28e0fb6144471cc30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"7a43244a00d5ca08ebe63d4ce0dfb8126e6ffc0cd9830084f8824563aba5042217d9e5e72c727f6c630c3341bf","nonce":"f24a07f28e0fb6144471cc33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"c03e0afa310bb70a097aa91b7f765b1d3f30329730d58c5d5313c1c9c47666ade4efd16805fa6b6d533c21bd2c","nonce":"f24a07f28e0fb6144471cc32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"1e0e8914472af391525f0bce7dbc712dde21cc1eb9ecc4299171191399c850f85257985e549e73a86d9dba6b31","nonce":"f24a07f28e0fb6144471cc3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"43bc5906fc6298e3eeabb1a9257a1cf0aee90a306ff48d5d8d15e4d57de59bef36615a6546e3b29413667b7078","nonce":"f24a07f28e0fb6144471cc3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"4a0fbe5a851cd633f253ba38ff93f5e63fc4f0681f066c3027004088b6492c8b2140bcb167c3202c5a88596b7f","nonce":"f24a07f28e0fb6144471cc3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"14f5c727acaeb51957b16503368777d2873a2698239240c179e17e1ac883927174bba02d0738c9ba9e7dbc26bc","nonce":"f24a07f28e0fb6144471cc3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"43592997ea1f6671db2f578ceb576dd49b5ffd192547e2ef5f93b71eddf51f7c9d567736104616b5b6c7fecc96","nonce":"f24a07f28e0fb6144471cc39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"820bc3726aa339b80e1ee213fb152b35f1a28f50968a0ccef2546aa0e5745b277af04d7e81136615e42c32208f","nonce":"f24a07f28e0fb6144471cc38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"35ef7fdca87a689e566ab524a0135b93ffd9948305c7e7404480fe504b0df6a3418a41626468be3f211354616e","nonce":"f24a07f28e0fb6144471cc3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"4b90deabfa959527694b3a99357f64921335e8c95a74ccdb7f1475df56cc561929d59d3cb5c24027abfd198634","nonce":"f24a07f28e0fb6144471cc3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"7e6390728d308c1dbbf56e6fe2ad89724b3d5b9e0123cf2e2e21a01734ff89bc0e318b193b133f65f81c1df8e0","nonce":"f24a07f28e0fb6144471cc05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"293a3d555ebf4c53a1bb541625679766b9c434ae80f1f1addb408e546ca88a665e9db975949f87a123d9af6995","nonce":"f24a07f28e0fb6144471cc04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"dc5e25cbddab69ff16a8ccd7de7f6a1a36a357c6be54a1149e71235786695b317f8b2049a558114d46bac6ff8f","nonce":"f24a07f28e0fb6144471cc07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"1a4ae46de48a2280250afbfdc9ed2b409000cf18eebe09683f79efbeadc538f6740528e8ba666c338c1b64432c","nonce":"f24a07f28e0fb6144471cc06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"22b997874adca2b64753ceb140441b6fe8952a76c4d7617d1801bb1249bab171c624606f40e42edde8d948b425","nonce":"f24a07f28e0fb6144471cc01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"d9cf2b06e2060d7f486e0cfb83d7cfbdd0fc6aca72135bfa2a5ec97c70eaad333ce8b2ac3ee32a9cd241e78da0","nonce":"f24a07f28e0fb6144471cc00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"e6d57b6a74cb9efbeb91e0c0384fc6c0943d370f2e5a11ac791673feb9de01fb6e1825b9f4649ecf00018c263e","nonce":"f24a07f28e0fb6144471cc03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"06c529eacbacfcebb68092bb9d5e4ae8d103c348e9df499c78f7f27906f497be231797c54c239d1ef32110b3df","nonce":"f24a07f28e0fb6144471cc02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"2b27f6fc8122a56dc55005196d654d4a4d428fb33d1a2e4ba919899b0fe4b8bff475b683ce5756d4d2cd0b9cfc","nonce":"f24a07f28e0fb6144471cc0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"2591b9dd7f4d15468639050ab5a791b4d37a8ab52054801792e4f07ad8b71349eedef7ecdcb8a46411af0c3ebd","nonce":"f24a07f28e0fb6144471cc0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"e882cf4dc796b03b21053929d7b8a80aa00f4e957e1171ca7acad4b1b0172cd54b287a9be35926bce21f827f85","nonce":"f24a07f28e0fb6144471cc0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"c15c6afc2f4231ed6783d49fd81860febaf182becf9d10bb9b61ce8b0e2689cde282f116cff0c23418d0cc99c3","nonce":"f24a07f28e0fb6144471cc0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"1e6345e675b8bcfae642661f01d064e547a73e4ec5ce99e063914c7fdd3090ba1bf0b76006fb0cf62b0b580ca2","nonce":"f24a07f28e0fb6144471cc09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"ce6e1173a333c92dc758611163ca82c8ffbd800f9abf6eabff51c35259e2245196a3a9aa0537b4577c16a82359","nonce":"f24a07f28e0fb6144471cc08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"c6a08c30c0cb35a0bba0c072c07820ea338c5364413069341321fa7f75e686216d1a7707f9094aa5cd11f39740","nonce":"f24a07f28e0fb6144471cc0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"385623e49d1935d5f94912c717081f47be0f882369fce7aa61174df52e3139fef6c850bf978c8732aa48200e2a","nonce":"f24a07f28e0fb6144471cc0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"ee127ee35bc6a7826d845db6634ce371478c69239b120932366d412ff05e21951ee393286a780cda9e3f29e843","nonce":"f24a07f28e0fb6144471cc15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"3462740bd7e29d98381ce10833653858e65d4e7d159b92785c9ebbbfcfd6355a1154a991fc217199bb51e7d1a1","nonce":"f24a07f28e0fb6144471cc14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"1ab8aef388eed748964df3b7e54d2567ab49faea0c53a8042deed04a0212d44b3a60a3b80bcc2273c1bc05b630","nonce":"f24a07f28e0fb6144471cc17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"6b3ea52cfae25c7c452724aaa6c47e373a8f492d474fe66edabb404cbbb2fa48c589769970596336bdd0e6d3bd","nonce":"f24a07f28e0fb6144471cc16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"501385fa93bd98fa10ed724c0d4615c0d5cc099914c1f601966dd3b3426f19f988ae6657ae2b6fb9dd06cf8df4","nonce":"f24a07f28e0fb6144471cc11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"75bfb88b20b4c4c3e6c86f198e09924a00757d42691df2b00cec28dd05e6444975fc7805d402259165408a0969","nonce":"f24a07f28e0fb6144471cc10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"999cc096b9f6080d4b90557c10f67b9a0d6b15e25ee970ee440ceae959de52f5b32c3423c076ec2486f263030b","nonce":"f24a07f28e0fb6144471cc13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"d1c46b605540c23f401de3b14e28891c898c7606c932ce20abc6c6ab3db7ac30ac198241edc5a3f84f032a4238","nonce":"f24a07f28e0fb6144471cc12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"03ad418f98ca7bcda00f511f62f02811530d1280a244e27fd2e0126a14e55395bf0b66bab988dde0951cebe1f3","nonce":"f24a07f28e0fb6144471cc1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"a7a8b05fb7aa947a81b222285cf98f3f9d91a965c2b0689ef777029ef3731bb5f5dca1ed9f2f3b5747d9d97097","nonce":"f24a07f28e0fb6144471cc1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"a634fef4e1094281d445397c2167ba849dd29c9a0bd0a788991658a880b2df2f9f39c0bee6c757ce9577531c3b","nonce":"f24a07f28e0fb6144471cc1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"6c8fc5c24607420f431548195594d2da066c0fcd898c6c8ea6816a4c65606832eb2c4819468af572800341cb03","nonce":"f24a07f28e0fb6144471cc1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"39f11c91635837259401bed773d695d4421602921fcdc1ce04fa6ddfaea2ce70f3a68252900cb48d960b0faf27","nonce":"f24a07f28e0fb6144471cc19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"6f640564be377bce7e0da1a0dcb03e473e73c4eb28775066713680b6f960a8e3531011147a0b9bb7d510301ec5","nonce":"f24a07f28e0fb6144471cc18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"e9223bd34dc7e223744bdef246141001d4188ba77633ee850911abf9d7cf3f1336c71d9045d9384b6e63be4664","nonce":"f24a07f28e0fb6144471cc1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"034d15cdd3b2bfb3d63e6643e1906a284bb17d08c52dabd8618f13cb8a7843bf11f6e983cf839cbcff06d2fbb1","nonce":"f24a07f28e0fb6144471cc1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"376a239074def9e2e1620dd76f19e837ce80a1900eb9651cadaf10593a3a863315a2e2ceb78fb81a10aca0bff4","nonce":"f24a07f28e0fb6144471cc65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"0efb745fbc87de38c10ed23560e4f1d6d239857a24dea5451ecf2ab96d4e052cdd4be8ef69febb5616aba6b906","nonce":"f24a07f28e0fb6144471cc64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"ba79b004d98a7532b97d69d72c69d6583e1856f9a5957c46098f93e574f6591d83dd39d1cad5dcf6b8fa7fc51a","nonce":"f24a07f28e0fb6144471cc67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"0d8ef1e7ab933584ca9d4570c90378c0e05d02d2004cec91ee3440379ee5172cb653f9cc6d212a9b0338f0b38a","nonce":"f24a07f28e0fb6144471cc66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"77cbabd35490d3ded3aa4483df66b0d5d71c694fedc84e74e12e82325796a038ca63e8260781c91cc021d22207","nonce":"f24a07f28e0fb6144471cc61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"9711c41565ca3a7849bdfb09507a46060d85b7b21e81c11d8ab5eba3aa1e761738c253dc8dec6f2b90b7ce8b78","nonce":"f24a07f28e0fb6144471cc60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"7e8b56e1b8b1d7e6d283c4ca2610ded38c6527fe7e6fbce8b4593100cdbc5ae3d6b5e94e8c99a28400e0d3b653","nonce":"f24a07f28e0fb6144471cc63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"cf049c774d1b4450bacbd2db99cbb41efa7911c3a497523b09bd521022133fe120f9b74e95ded83134f3c74e6a","nonce":"f24a07f28e0fb6144471cc62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"4a2eb368a8556db0d9d1272a5e3dad5823569a281dfb9b9c6da5ed11bbd41bb471551eae758999e1d7adcbf2e1","nonce":"f24a07f28e0fb6144471cc6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"aa97ef39aaf59df4bfc0df1eaaea49b2bd5560aa4ede49308d333590b1da21cc10bdb097c1d6b56780ac210b32","nonce":"f24a07f28e0fb6144471cc6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"df1f665b998d907209b96bfed956b13e18187bff08babd11d1f5ad8a95139e20d224c6e4fe491cab2f150a4b97","nonce":"f24a07f28e0fb6144471cc6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"e868ba90bfd26a1ab93d3b0aab5e3e6fe0fab14fa6366d3dd5f47da163f5aeef3a53fbd3367098589ba10e19bb","nonce":"f24a07f28e0fb6144471cc6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"f6a72b84dba936c9bb168b761d33e636b7f1f047cbdb32982bbc2299ee4026d8c09e2d53ab606b7dea84cdbbd5","nonce":"f24a07f28e0fb6144471cc69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"0f2bd3a43f58afbb42cf4ea9265cf09bc0660d73a96c1cb5f4419a27f9db8b6bcdbb14d6a0a6d26bae0a5938b7","nonce":"f24a07f28e0fb6144471cc68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"fdcfdc7f6b099c23400f7d4a25c719f78792f88d55cd921255c8df306799af4c913e348fe3526a9d7361028998","nonce":"f24a07f28e0fb6144471cc6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"15bcc43dd93f09b022f375dd4756dad107266e6dc9aebc143ab44f97d99b2e2739e44a06b7ead9fad0e88ab02f","nonce":"f24a07f28e0fb6144471cc6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"c080e77651420e8db0a2f6439e0a638c5a62400a9de7b259107b8d40a2680609ae1b51225ed3b9be6f0b4aa83d","nonce":"f24a07f28e0fb6144471cc75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"399e0c358558dd2e617ea24cdae2b550f9693e30867451ce6c1dd0aebae1cbd3beea2a99055aee491c6a2b86b9","nonce":"f24a07f28e0fb6144471cc74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"44e8cab0236c6ff7e79a0d446126fabe2858389ea6e9a3bb8da1383cd70234b32515547e9a0caee828431c3946","nonce":"f24a07f28e0fb6144471cc77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"4bd23fdd55421d7f69b49a261de54f6cb7a04051c2c2a7bc640e7b8e5e6803985600003f7a634a4fa7eed33718","nonce":"f24a07f28e0fb6144471cc76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"e7fd2f0c6c2c5af75019369223b5b32b475ea2395f986a6bb87e5c5943ffe181e84bbf509ef5e351e6c75f5e4f","nonce":"f24a07f28e0fb6144471cc71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"3429624e331fda6265cd022f2e3202f329b74fa9ae608e68dc0c7c9fdca9b072d1d298be46d38cca893a8477fa","nonce":"f24a07f28e0fb6144471cc70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"902267fbfe0ce1c7d20b7c262317b667252ad4c88edf6a51e005e20350aa0026c67f6eeaeaad5066020a41298f","nonce":"f24a07f28e0fb6144471cc73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"9afb016da11d8051d443e8c70db32ef056ba08438d6df035f8072fbfacf49ab1f353358299ef876d2dd9649c69","nonce":"f24a07f28e0fb6144471cc72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"3556e7e0bd85dea0783c999f6a42fdcd7a2e27a98947df8a692c73e44cbb09c77f54778ed11475b9706f3765b2","nonce":"f24a07f28e0fb6144471cc7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"5a78940be47687cb4be8c9a26ae028ac53ac7de0b0f9d3137895d404995f9fb28a7ce0891ceba8033eb5258b63","nonce":"f24a07f28e0fb6144471cc7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"5060258c3051888774a8fc6476e840a751e9e051887edd4389ad4a0ee6261c04eae6e955ef1dbfb01817cb4f12","nonce":"f24a07f28e0fb6144471cc7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"3aa711e82d87ac081a5ebdd692e28948c15fff1ff444539da959cbd1effceded3b406eee26ec6e0858108fbd45","nonce":"f24a07f28e0fb6144471cc7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"c34c6bdf78d72d4db46858761046f5a9f0e99867cf83207ed37017ea5c3e213ffd675624b1fcfe438fcd850110","nonce":"f24a07f28e0fb6144471cc79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"8ba6022b81c97cd3ca84a67c0d3025e86e920d2626185d325996d28a703a30e8f0dbbcb872e2c6c0c45b6db828","nonce":"f24a07f28e0fb6144471cc78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"ca483580af04dbe6c6198da0aa62944ecb5e497110749cd91fcccbd5a3f1973825a638cb8012b9487a4a83b434","nonce":"f24a07f28e0fb6144471cc7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"9c881a43affeb3957b70a6f4c2666ce2117ccc15c5bc219f364773ef23bbccc458b8488f6be6329f0fad7b3ff0","nonce":"f24a07f28e0fb6144471cc7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"d5d435daf048acf3eddd65dd765c13ec0a34c27eb9714f8815a2c11d8d71d2fa7a5e8eb524af124c6c3699c8a2","nonce":"f24a07f28e0fb6144471cc45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"f1d2b71b94a28a5c50820ccf5fe0b4e63093488ddaeba6b2630204a3cea8cf2567fefba8b81013061d07a5620d","nonce":"f24a07f28e0fb6144471cc44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"6df4fda7f703cbd75691f7c66e531d0c7543108ea0f49b683414c93fcbef84cf1065fe0bd94e047d9a2ce025ca","nonce":"f24a07f28e0fb6144471cc47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"13685eebf62782ab91c9eff67acd0126999c24e18f490bd2641c171c249458cdb9f126cf2967f7a7a6e0c4787e","nonce":"f24a07f28e0fb6144471cc46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"9de6c5a8a37537b7f5edd3625bdf5a5eac3d7271abed4a5dbfc0e6cc09bab7696a040530ba6eb9a09e7a4730ff","nonce":"f24a07f28e0fb6144471cc41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"64df45bf8e3dbe8b423e0105f1690a47b8327348c3e582902a76cd23c06bf726b7f20667f4af44e9c06758ce6b","nonce":"f24a07f28e0fb6144471cc40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"34f306307adbbbd6d2bd5dde4ba309efcca76f85893459cb5518d682d67b98bad5a1c3a6ce160f0384c1acfea9","nonce":"f24a07f28e0fb6144471cc43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"612f92204d4fd5d3a3bbf0615f045226a5fac22db748fdbda12c084bccd5c8531399e03beaa3a113bc08b36c0d","nonce":"f24a07f28e0fb6144471cc42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"125e395f09d9704f3c7234c41e28d1e512a13dff1455ee8cc99bd0b7c526a542c104f8dc4a7c508ae1e23506b5","nonce":"f24a07f28e0fb6144471cc4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"1c170299463739474fc60dba471db39b37557c29582b78c6d59eb6741ef474ae3ca1956e1da969dcd00d32934c","nonce":"f24a07f28e0fb6144471cc4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"87d95e4af1e8be4a3ab3c104fdd9337b80c84d2e8b17484cf325cb44457c103ad6c31274f8e9d97fc92e362a7e","nonce":"f24a07f28e0fb6144471cc4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"810d2bea8bc7012c3460d15479a31a4a9824cca31c111f23be7cbe119697b3341b9e374b463e674b36eea3f90e","nonce":"f24a07f28e0fb6144471cc4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"578271320769f96a4b33ea3be05b01260b9e396fd44c5092159bffe43e27aedaeb3769efa69247cd0bb6c64cbe","nonce":"f24a07f28e0fb6144471cc49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"0f40acb85b294d528646b13a1d1521ec97d37e73a0b107e2c6d0337e5848c8eae3e7e202a4532c889945542f36","nonce":"f24a07f28e0fb6144471cc48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"003e464a44dcd8641855ca67bf0ff28f5b23e39f0845c793a1d35030c8a6bb514a3fd8468699f5a9e3243bda34","nonce":"f24a07f28e0fb6144471cc4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"320d864bca7dc693a9eabec5738dbfac9fb44ac14a794045c7f69956f587099182f185faba7c015f6a71b4ada1","nonce":"f24a07f28e0fb6144471cc4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"14539b5dbb5c5e7211f324800a620fbc49b9f51d3c7c868ca744d75ef99e6baa6d451cef8bbda6f83841736870","nonce":"f24a07f28e0fb6144471cc55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"a6fb237d4c01e5868fb83b405f01f1b04722a2efc76592355c6aed3228362a4f13d243d65e555363f904176e68","nonce":"f24a07f28e0fb6144471cc54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"a192105f743f7fbd1fca326ef810c94a0bf29228c4942d72597686383178064e4300e10bf53e1b552b661dbf08","nonce":"f24a07f28e0fb6144471cc57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"f635e6947000c551bf2f2a723b686195ae0e5852fa630f23034a10f10d70ca97cc7d6f6d0624b786542a91157e","nonce":"f24a07f28e0fb6144471cc56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"f03517dcb7b8e139a0a0b7132fdf27facab2b4d883c86b56a5aae2e86e499a73b19be0f5ba732c483ea58b1acd","nonce":"f24a07f28e0fb6144471cc51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"b3f32c46d1ba33156aac69f9cef05fd1a3c4a064d644fd83eb91a454cf80e6acf04b1dd7e7013dcb57ca7238a0","nonce":"f24a07f28e0fb6144471cc50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"734b7c8ae9270d7745f4644f1a47f7871b8f32ef3f302170e7f4de4eae971274fa2d7d00474f3282fc8b8aa26a","nonce":"f24a07f28e0fb6144471cc53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"7712404491aa821ed87d80b925a39201596dccbd2c71f5f6f8f0d97a76baf06835030dec02791010f3cf73aa87","nonce":"f24a07f28e0fb6144471cc52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"6e35e9ed8a4ac5a067b0ed531eb7b30e1a38acf87624ba38dcdb3fd3fd84b435a134a41f20d61b0d4e7331a1ed","nonce":"f24a07f28e0fb6144471cc5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"f6f6552ad2160a2837259292d7eaf7fb8ea1a8292c0c926733592321dce3ebc031039597b69445b9d7b41e62aa","nonce":"f24a07f28e0fb6144471cc5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"398cb2da4aca37cc673562cdac6cb58e55773c11c1ede2392e9588d4bfff013f52a2daa40f6364f922a1b5ca5d","nonce":"f24a07f28e0fb6144471cc5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"209b2eb25ae6df4afaab72bdc1237b84f01f1e82be98b7edc9cc73d6fd7a62a224dfb18bf9697d39077f1308b2","nonce":"f24a07f28e0fb6144471cc5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"bfa417333cae0dbea342b345d7e02be1bb19045d4371d5fac5f5cc27fe9eb5d5f018fe0dc3c95141b4245c729c","nonce":"f24a07f28e0fb6144471cc59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"e037e2dddec2029549c1a577be10d450e54eeecf8660027249dd2996bc81087d7159a0a5a600ccac4c97250dea","nonce":"f24a07f28e0fb6144471cc58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"467a22319e9381cdd51e5bfd435b639e40ccf3ee5c069995ea336678c276db28a5037b5c508fe679d07eb53bf4","nonce":"f24a07f28e0fb6144471cc5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"a7ef01c20fe98af9a47aa2ca38498f719e4d93c8202edc9aa8188f5e0dde14a1835a897e7268191282c42f9b5f","nonce":"f24a07f28e0fb6144471cc5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"df9c71543d97e3d94c8b4725bcd5ddada7f7ecb1a9638aaa6a00bbbe9639f5bdd24d0d027ab0251b2cb5761ad4","nonce":"f24a07f28e0fb6144471cca5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"9b9f954b828eae1dbd828e6a2308144f31a948253817e1b55d9727a72111a803f0c1362bdff65ccc42f69ffb3f","nonce":"f24a07f28e0fb6144471cca4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"c6af5ad45e2929510ee520068b4eb86eb2e0e1c96d61607ea9c6fad0f8fcb013131c52411c7260bd0b739721e6","nonce":"f24a07f28e0fb6144471cca7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"44fa46c56d6aa2eff45bca4495933b75ad8b7120baafa6cca7c2831c88fef507f33c847e863dcb1b913f8e783a","nonce":"f24a07f28e0fb6144471cca6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"52c551ac547bc55c206640260d00f0151e96473f6341af1466ec5a90b41d1bed9a84d265704232b5bb6717ef8f","nonce":"f24a07f28e0fb6144471cca1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"e9b68e8b1dd61b31e37a318589b8e12c056cdc085cce3ffafdc747fa296165c0699b21476096f202709d0b30d8","nonce":"f24a07f28e0fb6144471cca0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"82f1f74e24a2573a7148e0ca1af2b0ba055b3f2d242c40cfca578d839af5accfc9fcdb475eca9e2e2567f939cc","nonce":"f24a07f28e0fb6144471cca3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"0549553f913b0519274f76726ab236b9f8bd87590e2e88855d340df2d27ca188d0160d40fcdb614127ba7e27f3","nonce":"f24a07f28e0fb6144471cca2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"ee7640e1f7883a38590e1aba9a423360694c7709859fb52be7c3add26f64e55f35bd50a05781943e5e1ac8c744","nonce":"f24a07f28e0fb6144471ccad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"8cccb084a884a25fb603be4b08d30d30f70ca90e21f7057bc8f90667098294fb7fa72972704f8a90f521b42c69","nonce":"f24a07f28e0fb6144471ccac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"77e66ad07f07c071eda277511b490a182a8d6a890d3c303a77889519bfd81ddbf2f58957790b26ff3ec583dc52","nonce":"f24a07f28e0fb6144471ccaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"a4d28e42c81e5ef0d729e5a8eefd4ed7a439880597e53c8c9aae3eeaf86559b07e4a09b54209c691694df39963","nonce":"f24a07f28e0fb6144471ccae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"a542a4cd5461ba8850316af5a6e8d6de0f62b3267f9bb98aab39ebc69780e5d65918fb00bc4cf88864182c94f1","nonce":"f24a07f28e0fb6144471cca9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"7122549ef2f44583910f97f355b463d8958308154b1eebfdbf715d2682b1cf60a1119386ccb054f2fd5812d2e0","nonce":"f24a07f28e0fb6144471cca8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"5b4225bbbdf749e4cac9e9c74821ab63b78eb27422d4ca28b8c1ffcfae84b43d2385e3c42efad9938d64bfa02f","nonce":"f24a07f28e0fb6144471ccab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"f090b4667d76950e71165c3a14425f322fcf7791b06965ae6361b773d68d490c61499792ed68f916aba1a254cc","nonce":"f24a07f28e0fb6144471ccaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"755c0f2805f44d14a16237af6099b27f4372cbb71ca650aa38d37808b54d600fcc34e7ccf374f1dd4eaae671df","nonce":"f24a07f28e0fb6144471ccb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"6c6322b1d9a63507a4c11268aabe9c032c0aac4b8ba86ef7cbf42f92a43b100df7052438c0741c2e6d3453f767","nonce":"f24a07f28e0fb6144471ccb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"85c0325356d68efbcdbe63fb93ee1db45c784a490ca42ef0f0dc9e7c2012bec39c938140c90212c39e7bcc13c4","nonce":"f24a07f28e0fb6144471ccb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"fb739b2cf829d0bfaf7bf549f46481c1a6000ff3c50928313260263ba30c9f66d42881711391852b2fa7e26820","nonce":"f24a07f28e0fb6144471ccb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"1d0af52a584db01003b6964f214013859c566b955020d2009e87dba42d72b20284aeae22cc3cd732c5fad732d2","nonce":"f24a07f28e0fb6144471ccb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"d47d7dd1784dd2d6bbbd133f4f65a22203b131810387830c940c3540e75dcf9fe7b3e2933260a6a29d5956e499","nonce":"f24a07f28e0fb6144471ccb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"781138f115de785b1b460ae077b971fd7b1c4b6d44d55dca928d5d8b0c2690c485143ed56a4c6f084b211f549c","nonce":"f24a07f28e0fb6144471ccb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"7ff52c47d5b70287ac4ba6c2c804b215867d8a5ddc0f45f660b8dc7868cadceba6fe80a495174e7ebba11fa3fa","nonce":"f24a07f28e0fb6144471ccb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"a38959596766387723639d4aa3a24c79b5505da1d5902ea0f2b0995d5d692fc3d886da13da4d774619dfeeccf6","nonce":"f24a07f28e0fb6144471ccbd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"fa15a6a1cc297803c5b5b4caaac3f520b83637bba4e1b91e19d4fc013fa0c3667d4d463e874889504dd81e7010","nonce":"f24a07f28e0fb6144471ccbc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"5daa8894589a2468c00b6b16af736dd2309c6b1ddb74fb166ac1f954ab69fc29cc2bc6fb5fb44d4966893dc4cc","nonce":"f24a07f28e0fb6144471ccbf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"8352693666bbd104f8db1edf2e1bd3b8e18db779604c52c15d58ac1145568f93697176e2a35cef93510c2ce8bd","nonce":"f24a07f28e0fb6144471ccbe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"a531bc22c06aa068574904a30bc1cc92852ab9e790ed083a80e5840f412cdf475937aa2b1249d7fb7db8e51707","nonce":"f24a07f28e0fb6144471ccb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"cbae8e1b12d638b5a7bb7f3fc3eab7b95cf35832e8e7263570dbc9250769338fe0665afe256c0401fb21efe276","nonce":"f24a07f28e0fb6144471ccb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"f00e2723559369d2c125d210643e764fd7718f756fecdc9e3d8dc184238c3229e613a67b20a5c95346392850a0","nonce":"f24a07f28e0fb6144471ccbb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"b8a5291750281c0416a818661d881c9367e6d234f4fce54c3aa22e386cc001782f3a740b577c35bf8c967e5522","nonce":"f24a07f28e0fb6144471ccba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"9ba707cb99a0fbad42cc59152799bcfc04e56ccbe59d21242d55e0c6a5587883de3b2cd0640022f22ee0ded545","nonce":"f24a07f28e0fb6144471cc85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"40dfce0eda5e1d2b0d98a0e4d6e3183c7a0857c842906e8000e1fc399b441e1ddd5c541b043a04357f621df972","nonce":"f24a07f28e0fb6144471cc84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"0a97961cce5e0510f15ce063f63e56e062e99a22c0cdbe24b0f528b6c29670771e5d549d372427f7092be196eb","nonce":"f24a07f28e0fb6144471cc87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"505dd83727c60327507472d8ed3b66f7d384e8972100b7ee6fc4e06236da006c3f8ea077838a119523c86fbd27","nonce":"f24a07f28e0fb6144471cc86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"86be94f3182cf3cec78c619488f002f858429768080a8018eaab8a745f5bd52c16ec15524d43e293a39185d80d","nonce":"f24a07f28e0fb6144471cc81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"1752aa971e2320412f7f0a19d35294fa8698dd39069a65b72b5f12b8dbacf7177133517294ad35301734999cd0","nonce":"f24a07f28e0fb6144471cc80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"35beeb99959ed1f3b8057029cef3859967cef4a39c497b5e30ccd6d456da04984b4369c32c956fb5c8cb6b9660","nonce":"f24a07f28e0fb6144471cc83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"fd58873b3123ae01e6e4d9624c256f1435c05a795aebce078472dd1adc685b0bd261e68a6be59cca880337a3db","nonce":"f24a07f28e0fb6144471cc82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"e0ed7141974cc1a7e1e2278ecc491a37229a6b6813a7891560ca79bfcc39073f41208d1531aa7c593f2b148752","nonce":"f24a07f28e0fb6144471cc8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"05e2f264d95ae0136be0bd5783e592f2b4342b658ae8f905d198a378c797236f5becc45d86220624a5b282c081","nonce":"f24a07f28e0fb6144471cc8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"2ffa2e31fd9dadc7e17b59c4d75b71ff9ee9d23ed4c2d0608f51884d8a16977955792096b986c825c4015e21de","nonce":"f24a07f28e0fb6144471cc8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"a2e23091ba38bd19f47df3213f279b59ea25e1756bef4b51eb46b3aa1758d3795140510c5f4113cdf198e34df9","nonce":"f24a07f28e0fb6144471cc8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"6cf4f22c121ed7daa4e0c818f4f50f8dd37c259cb4d645fe91916fc6d6c7b9265aa64300290a3e5fa6df7b649b","nonce":"f24a07f28e0fb6144471cc89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"c27b81b7659e8e5adb5190bf2fc199315a60577cad3279c950688472d9fd20cf927bdca85186886e63f283e822","nonce":"f24a07f28e0fb6144471cc88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"a2ed11db477143e692a7f3f2853eb1c0acf0ec4094712229a64bbcb7f6b7aea802b2a42380b66905a917acec2c","nonce":"f24a07f28e0fb6144471cc8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"667f9afe69fb60cc6ba9a52c5ea19e3f42dbfae5554b8557035d819750c46bb0a53f3b279ad7b2a8f2bdd336c2","nonce":"f24a07f28e0fb6144471cc8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"07dd9ee57a49e90f4a7e1a78b1d92847b12952c26d0d6fd15a069ba05d986e7c9b57f3b3ec3ae4c1f6a4c50bcc","nonce":"f24a07f28e0fb6144471cc95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"c249840dfca1ea91626f7875c2401221edea20cb849fb25fc14a9968d4420e5f101640926f27d5bc7955430c24","nonce":"f24a07f28e0fb6144471cc94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"6b62b2ec4ba7d488bdf1c91038bd9ec272009182b01504f0df8cce3b958cb56c19cd0892d2f438085ce9687da2","nonce":"f24a07f28e0fb6144471cc97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"21a521a8257cee5d0bc9918dc76302239e716e0f2055e045670f7f7237cd5c1455df0d3252f35ae2b74888e1e9","nonce":"f24a07f28e0fb6144471cc96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"02fdda0d78ba2405dcd6f07754a26b681063b87e82652a1b4dbd30c43f76d43ca52df66d29920b74c8dd1e65a3","nonce":"f24a07f28e0fb6144471cc91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"e831ccdb0662e8b0c932cf8d1455f77db537454f343aba534d183a2817ee7c4a2c910fa73209cd3bca4061f74d","nonce":"f24a07f28e0fb6144471cc90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"89ac0b015dd74a921c76b45aa3032c629b1a29bb1e1c7448d70b23143a26c6dcee2752e4a608e4b41dc2cd2aff","nonce":"f24a07f28e0fb6144471cc93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"ad8cca98ed5cd2cd1ff778b5fdcf544cfbe228838710b945ddf684f5151e6d150c984f2c8502780f6db9e03275","nonce":"f24a07f28e0fb6144471cc92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"b2de0f9d9a07c7e7d3b26de103b62381a2c9cc0a81906f7fb03471ea4632d0553e409a3b726071026da9e2da38","nonce":"f24a07f28e0fb6144471cc9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"88cee7bbaeb5941974a9df3d4b803c2c89286938500741d2da0c326758dae4f0dc4b22a756639d605184cf835e","nonce":"f24a07f28e0fb6144471cc9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"9fc006cc9bb00e3142807dbab323437eeb5ee94d8f940d244a404e210f1298f46d3e09fed673714edb14245ba3","nonce":"f24a07f28e0fb6144471cc9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"9268d7f03561c69f8eba309558307654a807f3070679f3ea471a94b14c0554b82fd356f1a7c901741cc96739c4","nonce":"f24a07f28e0fb6144471cc9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"c6bde1cc6f8ae9c0008b7fcbafb75155ab7fd4882bf1a43059714782a65d24b81bdbcf11a78a124315a68b43e2","nonce":"f24a07f28e0fb6144471cc99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"0f7765951d4f57b0b91cfb60b5bd7c5171eddbbae86f4604ec2db9714b8de67682abf7f2417e766adc3db25583","nonce":"f24a07f28e0fb6144471cc98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"48242d19e57534fce0becdb8ee6be027ceaf305e183eee255f33c1557929a33039f515bc9b437509ef66249573","nonce":"f24a07f28e0fb6144471cc9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"0c9f5f8a94395c938233b3c7a21708783b7f0e75d3e8edf70b36a66d7614240918064ec844950d973c3a8fecca","nonce":"f24a07f28e0fb6144471cc9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"3e9737a5481b946ef2fed0a7aa9ed63b1e49945bab667300510210f16849e852392340bf9b482300562f738a2a","nonce":"f24a07f28e0fb6144471cce5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"c68d86ffe1f377e0a20ffdee88c5a87156986a33a6fdd33a0c95efc1c96769b46e7e87ff6e8d029e0e4627ae63","nonce":"f24a07f28e0fb6144471cce4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"bfa458e1c9f442214ddefbc8f937e893a6fa33489f6308960a9ebd434fb055686d4814f44a17ecfc3f552efea8","nonce":"f24a07f28e0fb6144471cce7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"53923fe9c93a30d86b331c0fe826d73335f3a43a1dfaeae431f019a42a7370e17be30de5e7e329917c8c949727","nonce":"f24a07f28e0fb6144471cce6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"87a7b472b3673faee0fb26367d330aa0ff2991449911af76a5b3fc6770b77ed980f485953497987bef9948e7ac","nonce":"f24a07f28e0fb6144471cce1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"b6fe61ab5d07119714838c71b9bc97fab34c88d1066fc6dac2dc941d23b87ee5a778bcd8b02955963e422ac899","nonce":"f24a07f28e0fb6144471cce0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"ef9687a5293d44cda1084a425f4ae5f429c82da1801c2a7f8bbdd0eb82a433525620103a16d413d20446dad8c6","nonce":"f24a07f28e0fb6144471cce3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"d5b3f3fd6b96b1aa85cb7dd885669bedcf1f2b6383a71354262a3d0c0ebc550cc12a8587166e746d709ac44241","nonce":"f24a07f28e0fb6144471cce2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"4b14192621e50256688df17f2b8008dc2e978f22a33f915ca9d224ebff7a601f14865c215c76b7f5db4ec4f13e","nonce":"f24a07f28e0fb6144471cced","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"6782ab813f1d5a6ec39f26958f3dd3c727aca91fd7dcf2a3395d80a1d680ad8be68b3950de4f86f38e7cc5602d","nonce":"f24a07f28e0fb6144471ccec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"4d8b707de87385dc032e2964d1988aa9a82d430529b73d9df433a9754dc9919c819ee5d61a3fb56149eb920455","nonce":"f24a07f28e0fb6144471ccef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"baddf15f262c1cfd2eda8849ee9fd7c294ce8e1ca15010be3d450b02aae1f57e41cea8ef1672d824135f517f27","nonce":"f24a07f28e0fb6144471ccee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"41c95bad75d0884ebb7c1acb93b9d71e8b4849a662f7c7a533453202608b52c2550228444f659f3fb0452f1063","nonce":"f24a07f28e0fb6144471cce9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"e39a5ee827ca8efe14053118754242e6744bccc9dab1e08d715a611bce07f131383ec23050ef15a7b4b65c89a6","nonce":"f24a07f28e0fb6144471cce8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"793beff66a24ec717ce5cc0afc721a7e979f612e1c566b3f058bb8da9ed6c9878172a0f758d9532662cc8b894a","nonce":"f24a07f28e0fb6144471cceb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"d65b0ff910a2528491ccfe90b1b3ec1b737bee1dd3b5b81a6990fa8c29da58c5dbea0252c654d2021f343b684a","nonce":"f24a07f28e0fb6144471ccea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"8cea46515f42e017d72d52ea2089a975a85d5aefa1d235fb2d146c3aff8627920981224765d59b82860252156e","nonce":"f24a07f28e0fb6144471ccf5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"5a4641650173f373bdd6636f18539ac1bc44ac2f7eeacb68f11348dd9c1f7ad38d066e728b0989c47148638559","nonce":"f24a07f28e0fb6144471ccf4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"bbee615ed60c1979cc691a97bfd75516b30d8b777b5265614d7c68cf83d9626139a53b40005a97f92c96da4528","nonce":"f24a07f28e0fb6144471ccf7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"b1bd0187b2ed7fee7b636c1364fac16ad7c95cc4fadeb87ca256b90e37e6d25866dfa991283f8c2e885632e229","nonce":"f24a07f28e0fb6144471ccf6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"1d2fe9694cad672ed756edec6324724c3387eee6776e3e347bca3385e67c943cde75c704e1969598bba4df6f38","nonce":"f24a07f28e0fb6144471ccf1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"eeb008cc2c3fe2217e322e7ebdff5545f9a4834a89b8fcb2f413703a8e5e2b491b97f1b4052b63f885d38db361","nonce":"f24a07f28e0fb6144471ccf0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"6b2d003d3383672b3cc6be5aab88e8df41e5d7a29c64c9132462631bbbdb73c4dcaf5221ebaab6ab3a452c3ba3","nonce":"f24a07f28e0fb6144471ccf3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"5d20e5b479826c20f1fe9967c6b66b59f4f35186688a862a0ca16ead4a0c9994bedbda778a4bbe31f0eb7bee5f","nonce":"f24a07f28e0fb6144471ccf2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"e91d53838ea2f27ed7170875eca680cc150b09e19ea2c91d350cc0523f90c57270859e0763bf82c37e2c1a69cf","nonce":"f24a07f28e0fb6144471ccfd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"d58902b497841127d37f918505ec79de22c3c3452ff46be8fbaa6d746cd009924316b01a539e0993ab6817a8c6","nonce":"f24a07f28e0fb6144471ccfc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"2df269d9169d1ece2fa2245df6e42e61c1529bf41687e902d2bd0e57ece2ef3273a18e70b4e53a5010cc5aacf6","nonce":"f24a07f28e0fb6144471ccff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"c28b72b9bdd46df22cf8ef7244d0c367036184b69914d2e7bd35adaa45e0e2c5a13ba6e7632aa29796d40afd2c","nonce":"f24a07f28e0fb6144471ccfe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"792ff6e3e318ea7c53d4867f9d2d0033e0760d72bd75408d454d467860f3a72e8f57feb5a34a172ded5698f237","nonce":"f24a07f28e0fb6144471ccf9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"2a4f32ba157f0fcf85da51baad1bcc6cc4660963a9832bf1abb41d5946a07a7f195389ebbd9f21237551f880d7","nonce":"f24a07f28e0fb6144471ccf8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"ea2f514e9ffd72ecb2913b010a2292681aa19c3989ee0e2a0e8e4f1aa6bc80c19306140c783e8cd0ac29629c86","nonce":"f24a07f28e0fb6144471ccfb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"d7a283452819c671737a7b4fa3967c552427d7990bcf1222d10d05b793aa5621b6d99b5b7812dddec92128b73b","nonce":"f24a07f28e0fb6144471ccfa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"cb3882f9471c38f75807e1d54ee3580c67ec5fba00c4b51161bdaf48374c9ab80c005b072f1aa36d707b19069d","nonce":"f24a07f28e0fb6144471ccc5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"e2975c72958b9490c7f82233bd4986366aa1d9cfad2230ff1bdd6674e80b5a4cad0fc5133213b6ccf78f544716","nonce":"f24a07f28e0fb6144471ccc4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"989b3bb6242a4b0cd3bd71f6d58bc2b944fd34c4d3e094a20a5540a200d75e89671459864c5757768dfb3c2241","nonce":"f24a07f28e0fb6144471ccc7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"28c560f8de2eaedda3bf0218c99e06a0c945f4e5ce8275622f29051d3192413d255ce476b8c702f86a815b8d6b","nonce":"f24a07f28e0fb6144471ccc6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"da7738af8f9f3a22db98798a68b7b1fd25004703d1b361ddc61d1947b5a89f68c38a1836bdfaf045a1a0259377","nonce":"f24a07f28e0fb6144471ccc1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"8b74a641963ada7176849e980d3b77e70f66ef1460d6657cc62957767e552523daab8ed401394ea4955252595e","nonce":"f24a07f28e0fb6144471ccc0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"c44e0a2b08bd1a8dd182a71f57a2089aa5187bf856cae4821b70e08cabe387bddd95aa255e37d35d57648a086c","nonce":"f24a07f28e0fb6144471ccc3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"f11c8c5692380de690e68db9fb238067bef1e508a3f70ce403442378f71dd64c65d15a9e900fce24ab605a4496","nonce":"f24a07f28e0fb6144471ccc2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"f24b7e765d26e1706cbb1ec2ab7d7c16e25a9c086188d0e0f288143e43669e123534a292c7aeb719312dc00f24","nonce":"f24a07f28e0fb6144471cccd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"8e09a3fd2d46f63c71294bbcc606c4caa9dd1383c60b6ff9fad70d58d631ac61ff4a151a5350ab75f92dd56578","nonce":"f24a07f28e0fb6144471cccc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"42ca7ab68b41e04cb8d579e826ddfc256f689368d93a2d726c32915df2eb34a46432d0e6f0cb810c5545e93026","nonce":"f24a07f28e0fb6144471cccf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"aa18f77feec6f027251d13f7b2e7276d9a05273ffcdff74ff4f65ad9f2f53223d33dd55b1ebf8031177edf1636","nonce":"f24a07f28e0fb6144471ccce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"283258f761f654b6a709cd284dccdbe2c94b5e843a6b9544675f597848a4fb81d46a88df743a83dee9b5318818","nonce":"f24a07f28e0fb6144471ccc9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"618fc7e4af70e9c46bfe99d0fe0bb2c4d1115869a8528e748b84ba6fa42dd4ec0ca148a3b7127bf6b1bc34d0c0","nonce":"f24a07f28e0fb6144471ccc8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"bf1f62484e6cac9b1a337a71c42e46982ca7454f702fb38b2dbf11859efff98342a94578d43fc1114660e80e9d","nonce":"f24a07f28e0fb6144471cccb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"323061f7780f82df90490f59a78d0ec411592462195487c1fd10ce4c2047536361b69cb4eb312490e5c511e6dc","nonce":"f24a07f28e0fb6144471ccca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"ae3d3305534d5f71cb4b2fa023b6c3b7fe8c98d625ba9e7008dc5efa25869831c756764861f214d734b0035e51","nonce":"f24a07f28e0fb6144471ccd5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"a94463b4067a82e7ad7956ccaf99be7f1c2b4971f1783815a120c5a0c0efba154f95355fbc8ba256e86d2c595f","nonce":"f24a07f28e0fb6144471ccd4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"12d7062cab8e9e0b125001bbe448dad5277964ac4f70f0752a7e0b5e93a945986294e8e3cdb9bccd0b6bd35b93","nonce":"f24a07f28e0fb6144471ccd7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"d208af249ddeaf98e35a0d7019af08ba1d15147a9b1a3199860696a48635c84a3f126e178a9fa5920e1e5ca276","nonce":"f24a07f28e0fb6144471ccd6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"b2779e38e2de65e939e514b3f240edfa3ecaef0a3021c618072aed5b2cdd191f40650610d5bbead2d60396fbd1","nonce":"f24a07f28e0fb6144471ccd1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"d8a7175d8e29fc3776b4ad34482a572c0c5e8d1d98ec35db69abded49eaa2c057929e2997ac5dad812a7dfe9f4","nonce":"f24a07f28e0fb6144471ccd0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"eba8a3ff29be0ffc6b483c613f20cefac729d5ee8ef92f5da79bda7e67ceef0655ce407b5960f62aace86461cc","nonce":"f24a07f28e0fb6144471ccd3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"9048aa0cef171bf309066a3522ac45138a02fc6b96e1efa0e365942d84f0049c3651bf652ea1a4d0817b6259b7","nonce":"f24a07f28e0fb6144471ccd2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"1af996b8b02d3b148256b3b71baa73ab6ac0f31ef469d5bf07699d055badc5a4f6b179476fa38b8f55f93fee19","nonce":"f24a07f28e0fb6144471ccdd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"8b9edf573862231632f1b39dd92772155acf6f9f07b5e0c14616bf147944998dfe15550fecf8d5f9f271f5815e","nonce":"f24a07f28e0fb6144471ccdc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"3d6b1a4d610cd4641ee64a76d9baa0855afe5b62de538532349527298e7e35d1280ec29a3f5b4606754cacac51","nonce":"f24a07f28e0fb6144471ccdf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"fc0de22eacc5a71d99339c63f176fdec9a88615266fa435feb6dcf86bff75b33ab699e6d006e51a4e1837a68ac","nonce":"f24a07f28e0fb6144471ccde","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"ba7c72fc53f24637b72146410a662345f7c4182d4af69402a332b985ea23f1387f830793cf062212afc4c59e9e","nonce":"f24a07f28e0fb6144471ccd9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"e1e0208288fecb9f73a8ef77559e86330a2fcefa3cb3fee3832c12d237b8077836b1576e57698293ae2b6ae498","nonce":"f24a07f28e0fb6144471ccd8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"9371874ebc2aac7207dd199c2503d5718d93ce144af4c7ba06676987529e7a18c8938f05fa2d54f91690deba87","nonce":"f24a07f28e0fb6144471ccdb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"5a256fad585c28d371bd0728d2522e6086055d6dae3f62f5e0e532fe3bc57230d55f2bfa6a61c94f4135fa2ed9","nonce":"f24a07f28e0fb6144471ccda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"3826c17af10f30ed9d79a9d6683f79943f652d86d46c201657dc2afe7ea6273b4e77b5a2eff2af8bf31a8aab48","nonce":"f24a07f28e0fb6144471cd25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"6940c88be45b79f452699282e9120cc7791c258daaa4b33f8c0b596c47803cc8"},{"exporter_context":"00","L":32,"exported_value":"a4c3facd051c9794316121a1b986c770c483fa1928b85194a382397f75be6b81"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"4e4e4676775bca921f567cbca6ddbe57cd04a59db44a706d5db47e9ef90d207e"}]},{"mode":1,"kem_id":33,"kdf_id":1,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"b623e6fa1145e2a4048a24d0402c147938e4066341d3308e0a5c1787b06df4f3815eb5576dbe3215be024993ff6686a79a8039ef02ab88bf","ikmE":"143804846edafc8804ef1e78d02cb49f4be7ec8fba3f593b83c59333c4e29e3cebe025d7a959ac81028e4722cba6cc227b62af3ca693374e","skRm":"818db1ee302a47cbd311184c3d9385d755cf003e353986605b2ad78b14c1d9de6ddff8e55b0634ed1f5f0e72c4ab77ad1408a272879e6025","skEm":"2b704bf89a9a0d7e3f492fd7738de6f023315ac465d836f20ca102d08da13e61a0804280532be6fbf986d42fe4786f66fd4855e20dd50dac","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"785209aa421e0f675e11d0b9c1a9b0cffb93bfcd2c292d1bb348d93bc1b274d73c071fe247846513423f88070ee9989ef3c79609328e5cff","pkEm":"1f837802220fdbe2b1b17cade2544bb5dd1f287051f3621a947d22b229839ac44e50986b9a8d73cdb02631644545866dedec9eedf659b4e3","enc":"1f837802220fdbe2b1b17cade2544bb5dd1f287051f3621a947d22b229839ac44e50986b9a8d73cdb02631644545866dedec9eedf659b4e3","shared_secret":"e7992cd53d9eb4aff6772b758074d984f610a8704ccd114e43726e51566aafa32b4683f65cc825d2ef0bf5d630544dfe05cb318a0fecb63a8c8fac4a29fce439","key_schedule_context":"017d7450e446db15884bc2ae4ec24768fd9f2ee0af660c339d91d6a4d54834361239b47ef10fef9d74124a76b6079f61957d5b791d37ce9aa2fa2a910a7e47ca58","secret":"f9a1a59c8b974cedcaf641f64d9b112f6bebdc850cf14294a960a5d567bf115e","key":"8c7831f7d01025cad498ad6bfdc6a62f1c39dee037c8da5cd3634eab85e8563f","base_nonce":"9ede94493788a33e3336ecfc","exporter_secret":"4359060a89b5e79788137733253020282921ee67b9b27a708208663592953247","encryptions":[{"aad":"436f756e742d30","ciphertext":"f6e6aa31da540f1fa0c65a93f4298f3e534e4b57fde0a4b94ce6d0b9cee9cc35cb4b4703c16209d66219523cd0","nonce":"9ede94493788a33e3336ecfc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"4cc661b3b9e247ca4b369e3f9a85cb91a489facf681d56a038caaf20123a931fd706adc389b0323710a0890941","nonce":"9ede94493788a33e3336ecfd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"86521821eb0a2b7ba2a727f03996fc1d3a47b44c63ffbbd56db033e0ce81799449bd067548b0d978076547f82a","nonce":"9ede94493788a33e3336ecfe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"b1620bf42c56e3e5addfc4ec2a31242cfedb5376840e1d2b596ed0fbcfc2c66b5f4bac77a90decfe33a930a6c2","nonce":"9ede94493788a33e3336ecff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"0d88110663bf2d18890077b5a291ee84d6cc5ffa1eabd98aae204660196edd512444ebd4c7cf89af2809e8c152","nonce":"9ede94493788a33e3336ecf8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"3901699484c6ea35ab9712405e723b5124633486dbc0efd2f2b852224a4c2a6e11f1fe9600bac9323187446334","nonce":"9ede94493788a33e3336ecf9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"4565191d4127f38a9495b745f4d0b67d99a8d1f72a33d7f26a735d94ae6133d5c3a33aa358f7673daa9f412119","nonce":"9ede94493788a33e3336ecfa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"fab3d67e74582103a41f9994bfe63483c01e72ab75917783b428559883786824bdfade09838f99eb1e78d69ff0","nonce":"9ede94493788a33e3336ecfb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"044921416e976a56d500c65d1ac776b417535cb0f7418d6667a1febb7391a173009528bf3575391bdc894c2824","nonce":"9ede94493788a33e3336ecf4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"491c7ce1a0c27b27d3c810f393f5edf3d178d520e16a8e6061014e5dab85018ddc7b6e141ff25c6e52e1c57ccc","nonce":"9ede94493788a33e3336ecf5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"0e18a0703235eaacc37b7e7febda87f7baadb98037347aff76c21087227effec0eccc5d8df8f14996445045fc8","nonce":"9ede94493788a33e3336ecf6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"0977fee560c09bc1c7e34e7bbddf3a50acce4006881d587a5536f7cc58d6c62f3a426cc6b27c9e895548f3c64f","nonce":"9ede94493788a33e3336ecf7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"adbc653b35866f7d7cff7cd5ccd7d87470882599102ef39ddc5e52450daed3af0c8411405e992355f16a197fd7","nonce":"9ede94493788a33e3336ecf0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"6cf89f736d16c8b5199f8b7863da08eda5f18100310436f22bb0da1e764bffd4d19840f277be3bf3cc37007646","nonce":"9ede94493788a33e3336ecf1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"dfa69adc5e5d57703379a25254926439e89f749bd06bb453cfab20e6951ecd80c24c09d6060b62467efc3c627f","nonce":"9ede94493788a33e3336ecf2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"00a413e8837540203d390a63d078d9671250d6afb67fa79cb964289110f33da637d5c80260495a88a52282afde","nonce":"9ede94493788a33e3336ecf3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"9837b1e13ae4fdc949b1edf2737dc3faef5417e40b264937c52318a70364b71deda25e2a630a7e23a952d6ada2","nonce":"9ede94493788a33e3336ecec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"f44ce6616038884a87c84ea2957ef8b6065db77ed826d832c4f843cb1418afbbc57ccd3a30c7e52ed4a6e13256","nonce":"9ede94493788a33e3336eced","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"b885b65717bb7c55e2511f207ec4370ccc955793622d06f8370d2bf9a4e5efa80d5d011c998ae4837c0c104b57","nonce":"9ede94493788a33e3336ecee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"c2bbb26b69b0f2c2cae3b53c3e086572b7a838c6f85a0f47b48f1c805dff0b6ff36995502f717950b238cc1ec4","nonce":"9ede94493788a33e3336ecef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"e393df75c85d414eef98a287e614b603ea4c1acfbaa4170678aedb8cada89f906863a9f1840090dd565d76b7ec","nonce":"9ede94493788a33e3336ece8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"fb84f35883ff56b5f86a495e35b8dec0c35387f677cff19d19e24a987f7689bfb858f143883937cc794800b486","nonce":"9ede94493788a33e3336ece9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"6eedc8843482a8476b63f9e6e41f601d6f2bd43d1adc4df231ee67ce17da19918e30ed1d75d876c5a3f7574916","nonce":"9ede94493788a33e3336ecea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"ea7990530bf9317cfe59144a2b9fd899b50f177181ef7d0ed084654f20f6fbb6e0a4d0706e2a2f7b1de28522cb","nonce":"9ede94493788a33e3336eceb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"ce841b28ad17ac4aca1a2ddd798b77636a8c0a675d80de3b94a184622adca1128c87a5823283a5439c5859c010","nonce":"9ede94493788a33e3336ece4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"5f402a13fbe02ee7fb8f7dd68c0ae2f56b6e97aa521a2ead39f8eca066c47601dcc725f8e67143da8d1288e841","nonce":"9ede94493788a33e3336ece5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"d5c358d878f403e2a52c0645db588b6098ea37b75df023e5c42efdfd3e9ab6eccf115a5f177a10145aa0d7652f","nonce":"9ede94493788a33e3336ece6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"8eca5dd68e241f9e5cd2e7ae191f4a68e6c47c4d47188296c913a8b2fc7209f63dd1762bd205c3b28700005265","nonce":"9ede94493788a33e3336ece7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"5b87a63628a2e79d73cd27a02658a38a84f03c3408aac7a1393a42bd2c21b22169d19f7f958f6df6257fd70abb","nonce":"9ede94493788a33e3336ece0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"11fed7f74bfd3304625f1ff6f4f9f50d6ae203465ab9477f4ca29faa13553a3df08edf428020f4f56b2f13f325","nonce":"9ede94493788a33e3336ece1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"182ac508b13168b4d94a8af6c282beedf4708703801dca220c90e8635b6437a2112d4400f0e2087bb351ef6be5","nonce":"9ede94493788a33e3336ece2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"b45420b026d65411794407a8e6f829a0c30a8442936ede815fb6b9e6d725f6dc2d32cddaf607fdf9d4b32aa2a8","nonce":"9ede94493788a33e3336ece3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"e73afe6ab0a16720d9db531a81f65a76a1886d794431ec6de1d03a32a65f02c585a68796505a32e452e3ad383b","nonce":"9ede94493788a33e3336ecdc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"aa335950921c7a12ce1f81d13f3f67373908afecc74b40f6a2f1b42f38c80900dc74affa27a9afc0ca34320c97","nonce":"9ede94493788a33e3336ecdd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"f9f5b7411df6c6b216248937c7f021fd0853f85970a721c961d5035920485a0755b8b3a01343d494b7845b949a","nonce":"9ede94493788a33e3336ecde","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"bfeac0913d0e4a2075b8459e93d7ba0f11733f3e880a4afe32eab6053906215ac36252f2ba3653fd62a49f79c0","nonce":"9ede94493788a33e3336ecdf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"902daea551691667629fae16b86a74b8c9817f9b4b152bb1f878acfff8ae8797c459dffde518a41086f554ed91","nonce":"9ede94493788a33e3336ecd8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"9b6ff7563ea1edf75157a74e6dc11ecbb33c067a7d45d89cfedc8114140e8df5b1d2293fbef50bac9c312dea4d","nonce":"9ede94493788a33e3336ecd9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"a2dbda652e3521cabe0c0efc47b10533524fb9f110be8a8858b019a07c13d25d8d013217b08d707799bd7a75aa","nonce":"9ede94493788a33e3336ecda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"016383a4980dac9c8aebc86da7dde51141f6ff35d42e149c066c91e1f48c0e997fc4ee5d08dd4b5f004f8e55b1","nonce":"9ede94493788a33e3336ecdb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"69acd2b11bb1e3a078a854c8fc0675cdc42b51ed38278910a469363f2119e6cbbc41e1d243aef6545db3dd0c09","nonce":"9ede94493788a33e3336ecd4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"eb60a4813c846736afbb683a28e8f67e6b01092003ce8c3afa83d81528e5c0c54b03f3c965dd628c9e7a2a9182","nonce":"9ede94493788a33e3336ecd5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"822fab1e82681b1f50531076dad890326948ff6594ad733bf643a48192c85307bf26b6567558375efde60e405e","nonce":"9ede94493788a33e3336ecd6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"d735948ee4a86786209eb6401982881bd3c84c2c3e3ad6eb13a7634c5e607b5e96599a006f64a7c494ebda3c48","nonce":"9ede94493788a33e3336ecd7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"2fb0902370fd3243f1feb73dd11edcceb96fc0de03ec812de9bbf1fc42bd807ea641ff3d004b7ddd402c5b823c","nonce":"9ede94493788a33e3336ecd0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"44c9feeaa6c86cb207a9d55d212d74106ca11d9f5fafcd334b1de8e6345dfba016fa3a88e00585aeecd39f4368","nonce":"9ede94493788a33e3336ecd1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"36d02f5a2d4b3b8356dcd426f5df054de53496ef77821d39f37a3dc6b9fe18b9b439d8a83f799d3824976e07f1","nonce":"9ede94493788a33e3336ecd2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"b26d52693c31ded4679237ec7fb213d0f59d1092ae73b3cb0c36d953a122a0efed8cd5321319ec3e7082366b13","nonce":"9ede94493788a33e3336ecd3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"b1223026de24d562107b056a2368fdeb5ecab23572719f19efbf2f3d1cc9804935535e0aea1cc04373f960922d","nonce":"9ede94493788a33e3336eccc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"0b7b4e1b3fa2bc040dd1db2adb5d49a66a3e554ab3a2ffef90d3ea8b045e1be019fba5c65967a16c703c3a8124","nonce":"9ede94493788a33e3336eccd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"a813bb1b41ce15384e70070d190153df90385acbeadbf19c575e320caa1fcf136cd31ceb4ec16954a9448899ac","nonce":"9ede94493788a33e3336ecce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"3ab477a1e2b7c834f421bb347b904bcf5cf99716f45560048c89226287497d60fbb2ad4ea054bf7983598d267f","nonce":"9ede94493788a33e3336eccf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"84f9c1f8520aadf6ed7f1f7c3d926deaf095cbe0c547eb47b918dce5a571ca52adfc5f7fe5c13776c28c92253e","nonce":"9ede94493788a33e3336ecc8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"ce57e96868ac07082fe42868ae018e8265625f535253c349a1cec0dfc8bc09a75763481979d1d77c54c3638d26","nonce":"9ede94493788a33e3336ecc9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"ce8de4ff22c91a351cd08ab3a1a23589a5e4264b29d1d17921db747dc8d693af1695c1c5a25520c01f54b42435","nonce":"9ede94493788a33e3336ecca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"0d1b13783375354bc41e61970bab1b4e895f111cc7e91299eb73f9749c13db3cc5d16d250aa688f43cb44574e2","nonce":"9ede94493788a33e3336eccb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"0a418df04601a9a62c0fe2b89211fc0776f5956a28e68db012fc79229afb48ad8c46d909f3b6a32c570b395a8c","nonce":"9ede94493788a33e3336ecc4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"ff9054f043a4396c026d767a44dfc23143fc14fe69d305fa98646dc43d3ce5ae92b18bd3ea8a7f869320106840","nonce":"9ede94493788a33e3336ecc5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"556dd6d0d531d36959bdc2207c274b4202cc59de1db8e7d8f9c42b15b3c20a37bc42561545ac763660f347a6e2","nonce":"9ede94493788a33e3336ecc6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"73115b241e0f5cdf215666d5a21cd4cb9af1e14bdb7cd632311bf7d27d7db4aa9dda05df9d7f47de33cbec034d","nonce":"9ede94493788a33e3336ecc7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"3195b8f23ac47852b28c04ee573cc7129516194ded3e2f2a47cd7df46ac7826b238a108ab982d6dcf086a8f1d0","nonce":"9ede94493788a33e3336ecc0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"9daa671eb597edaa905675325b2e04d3b27ed8d7b00537034c0d9c26b8e201e007c31a7d3eaf1e953f4c07e291","nonce":"9ede94493788a33e3336ecc1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"df21a63157824af9e9c221dfae3669a08fb184bd231f720abd4accdb8df9525e7a40e1061fa0fc587612324dc2","nonce":"9ede94493788a33e3336ecc2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"4ef70ce98c656f6a208bc6ecd5319554911d315413e904c18d45a8dec30cded677748f1f4207736c3ddf76738e","nonce":"9ede94493788a33e3336ecc3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"e0072d264a1daebf20df657dda8c221162b7f0a61ca3a5db7597c70d0a8ec14a4573858d44be4670ffd53790d3","nonce":"9ede94493788a33e3336ecbc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"d31ae31bd3733617a460e2961892f908acea76d1803680ce4f58b387322667c40f1a82c1bbd90c65c5e99967d8","nonce":"9ede94493788a33e3336ecbd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"2b876c4861834eab599da199fdae2bf147b2f092ce425c8f0890efb599efb2e903071881f310112ba3b74d7eaa","nonce":"9ede94493788a33e3336ecbe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"4bd995b2c985fe4da5f6c05e270b82bf5694973b23f41fd5f2dd1625e348684cad154cb65e8b7c30dceb98e42d","nonce":"9ede94493788a33e3336ecbf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"872dc84599df1a10d3ab55f4a990d3b72c3c248e4dd37c960926b45e06762226012d012d35df50bf9235c2a538","nonce":"9ede94493788a33e3336ecb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"073f48d4a7f2ce7d7b76d5fd9db0c1f10fb5ff93b12ebb0ebdd475238a1bf806bcd8f6422c4f24a11b9a33faa6","nonce":"9ede94493788a33e3336ecb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"28588b148ade649fec28068bb43e819b0ee007a1c358d02145412cf6fef7dbbf6f7fe283c8a98090be30ca51c9","nonce":"9ede94493788a33e3336ecba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"a05f37d112a65ba8b2e32641a2e7ffcac17e8a4458cf99204bc65040d4cc51a056551db8a6ac65d5f04fd789cc","nonce":"9ede94493788a33e3336ecbb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"4d7d2f23d76cb7f7a84db1e779d1ee09b1f51e5645d75f4e20e011213b99adc0ac072ce12ef74e8213eb5dbb21","nonce":"9ede94493788a33e3336ecb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"46fa0396870605188c34a823a7d2215135ddb12c2fa35ae3ccd381c1a3f55472658c698d1887d87d28e8c4c1ff","nonce":"9ede94493788a33e3336ecb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"234d7109852c0c90e183f4b782320fe9bb59df6b4a1367b6572c09ed2359c117b26c568878959f9826ad85eeb1","nonce":"9ede94493788a33e3336ecb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"4e509c7a863900a2672c90239cf274581b92b85eb17036326a20fdbe625ca961c2a3c081d7169ee26058fa98a0","nonce":"9ede94493788a33e3336ecb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"1f7ec8860e01f1360f91d30b2f7cc0f203b614e2e064ac6e8ce365eb3396cd8e76d3845d2c7b634abc6ffa6636","nonce":"9ede94493788a33e3336ecb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"b077df3a2f26743417e4e165f5b2ec71e021684265824da8216517f7a4aefb337efbbb0f32a9ab1f5ab5854ab3","nonce":"9ede94493788a33e3336ecb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"ee7b3fe125ed52ff40dabe41f1039d5f2668124405b8f6db9fa9762681f95eb30a577777eecd0c9b5f08f9516a","nonce":"9ede94493788a33e3336ecb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"b271bb442f455f59c40568691a3e563f20db6935938021deb3907d4f31df72272dba6ff78c6426018d51a6e9da","nonce":"9ede94493788a33e3336ecb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"2e17c0fb4dc90d8d8b1ed9aa98586e25a63f014ab5ae7bea75249be525bf162fb55725dfd05089fb9b2bc1665b","nonce":"9ede94493788a33e3336ecac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"fb8b0ba3047bddf1c85d86af18b42d8288d64e8aa06db2f1f84fca59043ee6a17a9dc49d0b7a9074bd944ac17b","nonce":"9ede94493788a33e3336ecad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"5494438d927f03491b2cafe068f4e9cdadc4a349dcbb30a85b6937c51d2ab35114538831eb04c9a2c6a67ea78e","nonce":"9ede94493788a33e3336ecae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"b51216f830cb7d1eca5abf4d63f29b24cd71930e2e104370b61c6771d1c5fc3f28fdf9a9ffe641e7fd9981c58f","nonce":"9ede94493788a33e3336ecaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"b7101571cb4c7f83820d4b264206ecbfb1b81eda30cdcf4fdf6affc7de57e7d5bbc30b71269527b93dfe102c2b","nonce":"9ede94493788a33e3336eca8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"eccb2d60945e8232fe7bd3f7392bbbbb552d39062a7f30824602be84c0e8f227d405ec6ba89ee0afce4f692246","nonce":"9ede94493788a33e3336eca9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"6428d5c3cacfb92b75e2a4571e4786ee4056ea91d2e83810842aca616ca951a509e9cb5ec0161cd1882bac2a9e","nonce":"9ede94493788a33e3336ecaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"f88216f0827742aac15d741662d4b2e0c8118d1bd11d140f7a7b86daed0f130b8a630f73bcb8cfdc51764ba931","nonce":"9ede94493788a33e3336ecab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"5a2978ca03ff040ec4577f845a48ea86ecc32a7d1fceb1efc5bd02acc7b80a8bc364743a453486b74cc4ef038d","nonce":"9ede94493788a33e3336eca4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"a23112a10d0502bc3341f0f7fa01e3d1e7d7c8e8fae7fceb5aef35a0d9cad28ddaf68e7c1532dac4a0e011a2f5","nonce":"9ede94493788a33e3336eca5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"6260bc4a73cfae7bdc7fdb6c565844d6e6ed8ecbfb78d282ec6a732d9f864adbdd5eb89ae20923540cdaa7f6a5","nonce":"9ede94493788a33e3336eca6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"89c8531297281dd617231b18a6b9b07b974368334e255cc1201aa7d9dc4550150a31d491dca986730a12593a57","nonce":"9ede94493788a33e3336eca7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"846c98f8744a90f18b7de6df587b2e3c462f4620c7b0e20fd534779ee17df2975f15426972fb54106f1b8fa478","nonce":"9ede94493788a33e3336eca0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"3f16fbb9bf59a70fdc2850fc7ed6e5c7d7e37f64cb525c5f650ad83f1d08f96eb72b125f8fe658c377fcd07283","nonce":"9ede94493788a33e3336eca1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"4248e6d8b842717187748a3417be23c5e79d93ab2182b21fc7a5e3be6382c256b24c9f6becef1161638c498871","nonce":"9ede94493788a33e3336eca2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"e0adff0404be7a64def998ab10b8a63d8402e9470b19ad86504b09d83a83da617183a90bbb2638098312e44bb6","nonce":"9ede94493788a33e3336eca3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"7eaaca00a74812fc3c1db0ad9dc7ff82380cdb91ae3c3b0a3465500198efb5db1b57ce872ae0ae759da56cc6e9","nonce":"9ede94493788a33e3336ec9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"21232532fe8137f7fd161d73dee43d02bc4d963956d7ad3c49c9151b824912db8cf574c80a605b96b4be3a79ed","nonce":"9ede94493788a33e3336ec9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"9b33c4b4aaaaac1e28d6d16d81db71bbb74ab5784b210a928069ec3a00fee41a966894bb83f6fcdf36ccc3aa32","nonce":"9ede94493788a33e3336ec9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"687a4f5ce87304c15ccf7f317362f50164b2e19f5d2f83584d6e01e437cff3264f792fdc11eab3fcf04ebfd022","nonce":"9ede94493788a33e3336ec9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"5b336ab628fe084685b01f0473df618b80cb9f009154b8b70edacea2f837655755853171bbed770bad9ea49a4a","nonce":"9ede94493788a33e3336ec98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"43302e9a01cf517f46a12844356411ff4e3d546f7804447f19aa495d7e7af4a2734f341b7cffb5a03b5aad6f8c","nonce":"9ede94493788a33e3336ec99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"72d9196adb5bdaff27a693dc6b3dbeebc2cbf1cb62a8b405bbe470f03cc5ce8da791d84c88afd97f37006052d0","nonce":"9ede94493788a33e3336ec9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"42bc2cfc6b798f5e62b7169a572a83a4f28c5cb194bf0203b10ff46b6b763255249112a6d322cac0dbde53a2a5","nonce":"9ede94493788a33e3336ec9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"2d116a62a347512743072f3a548cdd33dd66d57082e0a07268a0cdf5944f20660d7966bc7d552d5880a49b2080","nonce":"9ede94493788a33e3336ec94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"e280dc43e46cbc7eb31dd96039da8d386c9588c13ff6e000b9887cb0ba0e65083201919cc59c0c39a751b64219","nonce":"9ede94493788a33e3336ec95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"8b66bc997e3cf50568724eadfb872d57212fe9a52e0fb3722c147e2532cbf36cf408efa0f05546bdfae71734df","nonce":"9ede94493788a33e3336ec96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"4f5771e9a37d1a2aaf3210d8635559fe97208ad19ac1e804fe1c177719193174fed4258371445a3d8533a7e526","nonce":"9ede94493788a33e3336ec97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"6c8a08de402c9737bd013856f31b6098186790cb3c298fba0cc7f0d530ba442d372a38e9d9b4361de3d8d7a50e","nonce":"9ede94493788a33e3336ec90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"a0e211d3e414b48f13041ac1f34228a49c6c465f08ec74e6470f13b366c0cc8fb5128ba19989beb5d0159aa971","nonce":"9ede94493788a33e3336ec91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"25443c23db649a0507544abf741e1b6d2e3a6708381e31710a4717fd7cef51036f6efb02d7384bacf6d592ac2b","nonce":"9ede94493788a33e3336ec92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"1ac029ff5c3d8674747770a0f0beac89c9b24a57059dd848f540f6ece50d0d5f50929bd0cfffa32dd052ca783c","nonce":"9ede94493788a33e3336ec93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"a2136f78376234445e6ba5e06c016eec735b6153beb184846e61fca8a60821295871b863505112f8fcea2d2ff8","nonce":"9ede94493788a33e3336ec8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"3465ef07cf1d05093bb131f32b7d0e99df5f0af92304f868400eb5845c7945a1ead018055fddd30418a9e986a5","nonce":"9ede94493788a33e3336ec8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"65acfe6d1ce2c2ecd9f47e723c22c490bfb1e1eb533578b73d09abf8744e77bd7984719c73167e2863be1a8780","nonce":"9ede94493788a33e3336ec8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"bee424c5981be06e6e8f7921e71a6d7febd75de72d30fd4c917da67ae1f067d11f0dbb869b14df91aa60323ecd","nonce":"9ede94493788a33e3336ec8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"bd9138d7a16a622a34a4d2fafe136dcdffd587906908fde3a93ebe03a1daa361baf160626a7961f354e7a30884","nonce":"9ede94493788a33e3336ec88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"d33aa9fe5b06e4bb4a1a97074a98e123883188214acc5e26dcd9d11046106b0b2a8b4f0a05781f8d6307e1c59f","nonce":"9ede94493788a33e3336ec89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"3f2089acecbefb3da7ecc029b76afeb79adb834dd25eb0934e299d40949170e3b6ed7efbc63e2247b9bd605297","nonce":"9ede94493788a33e3336ec8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"870ff7e4ab1ff8e0b762fbba2136bbaae060b0d7f28db5f18a8d57c94eefe4e01998f58c69bb48573252cdbba4","nonce":"9ede94493788a33e3336ec8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"136f447cd0ea677c10862bd3d62eeeed75125e55f0e91a91ccbf423531eea74972575e5c53f91d019173294cec","nonce":"9ede94493788a33e3336ec84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"682f7f66f21171b2b551b5252d296e1bf03b3032bb59fea7ddc9a7afd069d8779daaa8eda3098a3d426ef6402d","nonce":"9ede94493788a33e3336ec85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"2d0df80a647efb779457b660e2e46bf2c8b4d2c5782ea7c25e21105f5425cd3aca656a4607c79537fd486e133c","nonce":"9ede94493788a33e3336ec86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"055354322baeabf1fe7d760dc8a8e5ea915dcc475b8219f6dc8eee815383353af72051d96d831c4c9e437cf80f","nonce":"9ede94493788a33e3336ec87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"ce7b2963f5b5eeff3b969f6fb299a2122ce836ebdf9c12af9e487fcf5a2bb602ea097f05e6f443a50e435d17b9","nonce":"9ede94493788a33e3336ec80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"5f4fe4923feeee6f68b06a05ed7eab2d4e471e6e08153901f2b1ec38207eab7204625d648e6c0ffb8363dabdec","nonce":"9ede94493788a33e3336ec81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"27be1458f73373131d293ddb26fd71b42e9508df682bf160593a8d47b465676e8d9c9a7452a573104940c57a7c","nonce":"9ede94493788a33e3336ec82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"49c783ed62c50ba37c104ba9aebd3e3dd341dc111cb6fb2096e4f30a85e122fe4defe11356b715b033fb36dc94","nonce":"9ede94493788a33e3336ec83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"374cabceef4518ed0ed10216b570aa64baf433221e34ac9db4c6f6980372978424be77f472492db41694b52808","nonce":"9ede94493788a33e3336ec7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"6fe9f7c1fce2bd26f574181e58ebf505a1629b02d2037e52f158fd62aefca0ff1b69dd79f95b4a60d35a39cca7","nonce":"9ede94493788a33e3336ec7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"a5aa307d7ff66714e950f15fa89223aca6a0264954b64927e5770d10af2fea2851245bccc50c97bbf029524a0d","nonce":"9ede94493788a33e3336ec7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"27fe3b94259207f070799050eb72bc6cb90f23e8f3dd8213a492298f12daf53f26cc6f63e62afbc030e52275a4","nonce":"9ede94493788a33e3336ec7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"8ed95233c790179f060808a156105e0e98681251efa30290df0a3ae173b55479a0c4c8f688a0ce91feef1965db","nonce":"9ede94493788a33e3336ec78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"0534474d2591c59edf42fd5f57929858bdf6ab1680246665be002b9876cf35aa101911b94c5b9c6af53568cef3","nonce":"9ede94493788a33e3336ec79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"121d91d0a5baee2600be8f227d03e582dbe966c739fcf7243a83270c92fa21bff9e5d9c9dbd070361c89ab396a","nonce":"9ede94493788a33e3336ec7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"20fa45a7275109bfd082dbf758785c44cd54a88d305c2d723a4e4d35ebb3e6cc00ffae35523b67024e85ba0758","nonce":"9ede94493788a33e3336ec7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"537e19abd86c9d12286b9bc92993962e6e0e4b37f2c5460e3e0c35babc45b0c194d9e3b4940169b7880e7c42bc","nonce":"9ede94493788a33e3336ec74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"ba7d1baf774363a41ea8978a7cb42174b196cfbf42f7d2443b64ab6cee0b711ce512753e10cc115ce6f9fc4e42","nonce":"9ede94493788a33e3336ec75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"b5467a93f3a35792059f9b05efd8089a5c77153a627e8d783056360b584e16c7132095c12ac62acb14373a9258","nonce":"9ede94493788a33e3336ec76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"bcfedbb0e4f802e2ec67c4d3b135c4fb1b4b019023656e7314d51bf803d0b361a260e34eb6b0b4f8a8a791d4b7","nonce":"9ede94493788a33e3336ec77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"cbfd4e4613c540ff389c15f0a97872d59c8c95ac5598d352b29bbd526ba0275d5354c8302ea0388dd7ae407b88","nonce":"9ede94493788a33e3336ec70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"cc3cd04f7ae9d07386695ed4b396f668739de507dee7a2dfa76013b83c7bd497353e52b897ea4468a17d05c092","nonce":"9ede94493788a33e3336ec71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"b44620966e6aebb0c089c1f8f9f16d5bb68b097c8c3080dc54572b0d753def75faeaf10b416b0017589f212472","nonce":"9ede94493788a33e3336ec72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"46faac0d114a2ae28de6bfd39050257e935eb5ea95462e8a02a6626cc8c062a914615a2e1e5e7d62808650e572","nonce":"9ede94493788a33e3336ec73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"050c1971c206e9cd8e95eca5b1298df342126b69c10edb5adb4c2828cc28594a592d4dd9938343de7f6091b95a","nonce":"9ede94493788a33e3336ec6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"8f0752d1ae1a821aa8cc611fb185504973cf92619491d43cbb30c002f34cc7bd27dc95afcead64b12c35361ce2","nonce":"9ede94493788a33e3336ec6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"7ab14026934a17e48f03ede0d779a64a09b3ebd8b4b155d27f3a0653ada592c0149696fd93ff124d5a1a665260","nonce":"9ede94493788a33e3336ec6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"a69a4401007d651a236291d5d2e4817384dc446bb0a6fc403c8833444204912a83c72794cb5064b6accb83e8f4","nonce":"9ede94493788a33e3336ec6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"a0cc9c486da14af181dcf3570e9236509304d7527a1073f68a85d9da2ee23d4db3b574527cb1b9ac2b4be566f8","nonce":"9ede94493788a33e3336ec68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"42003f1d72106bde680d6068fc6ce92fff3334964a4d48a9a3a53205f08354b865bee9e55ea33ccd5f31a49700","nonce":"9ede94493788a33e3336ec69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"3398d6aac77caaad09577562b6452547892cb61da886bc0ab106b70ab27ecbf5240ba546385acb7b9a1942dd6f","nonce":"9ede94493788a33e3336ec6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"83b8bb0e3659674c6c914c2ab96659461e83fead2c8b22ba8b5209debd4043fb1185aa099fb7646771afbef1c9","nonce":"9ede94493788a33e3336ec6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"77789433f17dad5f51036daf7b0b8240828ba5ce1948dcff98d1cf5f1caf6d82f3a9919229a69326c36d0ff56c","nonce":"9ede94493788a33e3336ec64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"8efd67ee7aac205fc490d55714e2376080a66b86ad92585d7c001921e2af7e949b774472694da51a776f407da1","nonce":"9ede94493788a33e3336ec65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"b0815a492f2c0817e14237f4750a42b50f364cc5256ec7c3be9d271b24bb556eb1b449ee3904c4b56a3eb8beaf","nonce":"9ede94493788a33e3336ec66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"93d0663d927daf76664acda16ded0d37e733c3151c1a225ec7ca28699d33acc89b895d0ceff00473baa392daaf","nonce":"9ede94493788a33e3336ec67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"e410e36ce4c1e97515cd829834b91f69f6261c0b98ab6f0e321ed424409ef4c755fafad13db1dda7007c60ea2e","nonce":"9ede94493788a33e3336ec60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"22bc7b1bd95e1cf03e6208867f6e4c11255fbe81c28f0ab5e17ba90398e5018e4954ac335f6207b7ece1781395","nonce":"9ede94493788a33e3336ec61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"0a9c21c1ce1326c601ca0f47baddc6e264718da73a387d750303aa6ae68d6f80b560c4361165068f1560c5ea29","nonce":"9ede94493788a33e3336ec62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"e839cfd83087559192c070f95193bf4275b8ff66a724ad447c1fcf97ee73797b46dc8b856bf68855e720f65088","nonce":"9ede94493788a33e3336ec63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"edc795f644e733b0ad338f2eaf1b812ce3c43f4495282da3a586b476a302ae10a20efa0e826ec6b4ec2f7710c9","nonce":"9ede94493788a33e3336ec5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"6f26df2a5c77867e613403029ef44a8028cc6c68f2fbc0fff6218887b2d005b29b59e84d401dad2204f68e218e","nonce":"9ede94493788a33e3336ec5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"efef3455c6f3f5ae305b0a39a0774e63400452724cbc7ecc07379cbfe87681bb3c7ee331b9462bcabefd5f89a1","nonce":"9ede94493788a33e3336ec5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"9c6cf4d66404e437732cfc6431589979085bb414bf23de351d3159ae14ec037a4b3392b9df08a5c09f1ec418d1","nonce":"9ede94493788a33e3336ec5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"be008813c46c1a255e743a8c131feffff89545ad23416e884e721e3b0f13490864161acea1747595df0cc084c4","nonce":"9ede94493788a33e3336ec58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"a81fe4c16009b45ce488d84daf091697c57105b0153fde5d020110db793b6401a162d9bca2aa4daa52f0be4ad6","nonce":"9ede94493788a33e3336ec59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"61426658a18b027e023b8a7ab9579f6d0bedaa8de7b2df7bb9ed41c4d6e76eefb57352b3c90ecd306858b7bce8","nonce":"9ede94493788a33e3336ec5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"3a4a0b4451ee9255147d221a4b9b9e740439136ebe4c9b604f7970a2533d500321418563b5b40183f22ee71c97","nonce":"9ede94493788a33e3336ec5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"40913046b8ca391ba25921166dbfbad8a6a83593a9ae65284cf0275666bb126253bce1942852cd1eb201c10890","nonce":"9ede94493788a33e3336ec54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"271565c6b233876dbcf5620f023896e01716fe76fb6cd03e17c410a47c10e5db251edf9a9322e12116684c1b8f","nonce":"9ede94493788a33e3336ec55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"3d8bb74404519e39869bf798f53190068c32dbce886e5f173baa7e8fdd41c5483fd6e3ac327a08e1b3dc592701","nonce":"9ede94493788a33e3336ec56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"bc45eeee7b301fa8adabdaa57657ae3f35537ac8643cc6a7b90a2ca6d5a45fdfc396eb8d5cdab894ad63fc76ea","nonce":"9ede94493788a33e3336ec57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"a761ed204c3ccbda06fb6b38642d1161e37997d71c0fac98fb1fb04d52e5bbe8badba64103b8e3808ff694e8ce","nonce":"9ede94493788a33e3336ec50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"194834b6ae583dd234ee1bd91dab630bdcadaa7b33231d12f37eee5ce0efd7042ea1161414fdfa39d2a9f9456e","nonce":"9ede94493788a33e3336ec51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"1d893199ce9ee93e08830fb5d5c5f9af3443c550088bd5a0db5e799597bb4a0b011c01785d84ced04e06b24677","nonce":"9ede94493788a33e3336ec52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"4d2e67d2c78b2feb140e2afa21ea1330aea36c48ae9536f0dcf3e4cf900c6dca7d104646f106801ddb5aecbf21","nonce":"9ede94493788a33e3336ec53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"5727cefb5cc888981e4aa0f0ca304d9cce0b51eee0ec4028fb8965f87a0a75651d0827816dda9e9933eed89b61","nonce":"9ede94493788a33e3336ec4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"44253aefb9470e7c8b03bc606d6a1ccd7dcfcd11dfbfd2dd8116e43e645c5c9e6b7b66356485343f847a8349bb","nonce":"9ede94493788a33e3336ec4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"38e98d7a61e7b24898074ef5a054a9c1bc22c2401181936c4d699f4fdd696ffcf06fe12de7ce1589e51eb93bb7","nonce":"9ede94493788a33e3336ec4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"439fd62c36be46cee92b4f3311b2b9637b208c4e607a51716ac4ec650af70d6ab7e31610a0cade5c5dff93e3c7","nonce":"9ede94493788a33e3336ec4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"d64c7bafbef116c9f68e2400f5029b7e240dd12d88d2b832ee99442229fa288080380f6aed7ef0434f5b9e77ed","nonce":"9ede94493788a33e3336ec48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"368cd991e9d3398c1707429edbf18741b0dc3b95002d8146be3e6097195754a3ed20c41666add26dadfda7cf1a","nonce":"9ede94493788a33e3336ec49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"2c4b29d786d8af2696c73ec789edb189f7c2900bace21e13d2d737676d0b85f8b24ceacb7fb5869f5be80f8f61","nonce":"9ede94493788a33e3336ec4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"5c4611bda45ff77f902dd599bf036ffe107907805f57092484a7354f3a33858325e6ae9fe59cab92fe075e5323","nonce":"9ede94493788a33e3336ec4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"89c12bdc0c31a3567b8d53e3bb9437c98b95e8be9beed4180fd7ce83c13987875651e199a82ef0c0527346b067","nonce":"9ede94493788a33e3336ec44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"f1c887a5592f3a68395c4beb8f7953ba7ce81a63c1c17d5ca3864fdbb992fa8af00efdff2fb48ee2b66bdd5b46","nonce":"9ede94493788a33e3336ec45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"f94904415084f98089875c9e4fcf48377c1c8a25fb44ff5764c3d77818e7b6d6bdb04c430276ccefc788b258c6","nonce":"9ede94493788a33e3336ec46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"1fde1ee01b5150ad22d1e553d17ae83482c77a06289efef27d3a78166a64dd13fadec9f963ea6e9f3cf206a814","nonce":"9ede94493788a33e3336ec47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"f4b146ecae4744b3940c46d2713f05fc6b4e6636dff83d12a94db8d90a25aa593c473e63fe8072d655f36a405f","nonce":"9ede94493788a33e3336ec40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"1377911c21ebca7acb728444dfb1698af8af4eb6a8755338e464fbdc9e821cf4b5eafffcac778cb7a63aeff7ff","nonce":"9ede94493788a33e3336ec41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"4652821a981915615a717b2103fdf1fda3a62508077e263bb7c5c49a0bda25dee43b1e7a9a1bcb1535d8f8f980","nonce":"9ede94493788a33e3336ec42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"7ceb703731f8a0162ba64c610fc160ba28e60e02b302e721ff6c106d6e8e765ced4aa55b6d3472f54d6e920728","nonce":"9ede94493788a33e3336ec43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"84b718dfc8a5d2ff65be2c4fceaf3649672dd97d2b9998d4c52956827f761a5c365a4d43ed4bda2aabb9a93e33","nonce":"9ede94493788a33e3336ec3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"5e5fca11c6c142f714eadbaf9ee7cbe21f984309b6f0c909b699c1b67a2051a677982a97ff902ca89971afef2b","nonce":"9ede94493788a33e3336ec3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"32b670fb11b5f5f8d35741ea40112e0c3e60b4d6610c4955d29414fe9b4644327a9ef8eda3dad1db34c155c189","nonce":"9ede94493788a33e3336ec3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"a47f81f24125a1b2563567eccfcda025f13dc3ae1e053826f1104ab61752b8152cdcebd909429333128cc11ad5","nonce":"9ede94493788a33e3336ec3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"a8bc770dfd5ff84820c14706eb85344719e969d9d4ffae48d85cb340095d2b63dc4768ab099b87a80fad30ed7c","nonce":"9ede94493788a33e3336ec38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"ac2a33bbd42cf4038339ec8df0a318e4ab36ddd41f48b69afc6ad9a141cae5abb3925e363688b90ff432b3e868","nonce":"9ede94493788a33e3336ec39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"065478a45c6ecc6263a48b469eecf51c7294c1af507e64cd374b9e9edaf6888e0ea8bf65abb1ceeb67ce49db4d","nonce":"9ede94493788a33e3336ec3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"d8c732487ab2d958f885bad0664f8e9cb0e2556ab91cb60d61854d444cc76b1d7d411b64364244774c8fe704e9","nonce":"9ede94493788a33e3336ec3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"9430bcd510d0f9835eeea7bc25897722a045c378f3bedf226c9b2f2e4cab495efa8f9d34970f0de68cf5d776d2","nonce":"9ede94493788a33e3336ec34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"7d9df46f101c3473a5fb4a3f61c89da8531058973c1775b401f0b9bbe7df7fe986feabe9624e26fbb8633d07ba","nonce":"9ede94493788a33e3336ec35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"cb2acdfaea5ad5bd89f6516171f880b17f7784992cb604265c7457f898cad896d8205f1d54485b78f25766d871","nonce":"9ede94493788a33e3336ec36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"45f7010baa2531b8f4e4633feb32051d39bafa1ea7cd11219f104ad3628cbd7dcfc3a7cf383844f34cfa1cc4fa","nonce":"9ede94493788a33e3336ec37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"cc4a34244a3569f4ba7a74aaa9b7f0229dea9952b914e09b684805eaf23c3f44e7bb4af99ff2fb626edee5dc43","nonce":"9ede94493788a33e3336ec30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"5a5152e4c13a6343224ac4b2bba958ad3c550648146c8f5e1ec477a947c2612632a2009ae98927f23dd3e5a163","nonce":"9ede94493788a33e3336ec31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"576a251a5b206064011a172725aacfe76cd34ac91ca22f3a25b89599d0e665a7754e6f0d154e8174dd8bb153e9","nonce":"9ede94493788a33e3336ec32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"67eaa5cdc0359902ab28144aaacdb0008c30edfa17bb4697728939eece7254c2902f5afbb38fef117678caacf1","nonce":"9ede94493788a33e3336ec33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"face59680b56aa0c7323244734df06ba3992e7240935a6b83e5ad36fc1e2e4bc6838e211674512a8139e07b214","nonce":"9ede94493788a33e3336ec2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"99bb6f7d3a2d3c4e737afaacdf66aa18aa9555c569108ca1b2651a688f5c3929bcb483ff18e64102dc67ddecd8","nonce":"9ede94493788a33e3336ec2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"28a941f902c73ac7ea7265b2cf2ae49272132e3466c6e18088c44583fa06a681af706ac3bad758f7eecd46e322","nonce":"9ede94493788a33e3336ec2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"1ae42e7dd54a5509a9ceea5b6558d14a124397cc4223b1bb07e91746e345cc251bb2bb0ead42c73b597a900a55","nonce":"9ede94493788a33e3336ec2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"621c61d9f7798b78dc890299cffce647ce51e117faa5613e0a82e1ee4483151714c8fe61f6ad2f2c3f67b29ad9","nonce":"9ede94493788a33e3336ec28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"4b3d9d9125851e66189db25a1a6fe43fe7e061c13b41d78cf952809e3b4dbb06c3ca4a4a355aeb984bac069ad9","nonce":"9ede94493788a33e3336ec29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"a2b137a3cee69c5195c9536a1674fa8bac94ec95d27c8add8b9d4c30384aea9eeb7c770f136345536f28f4e5d0","nonce":"9ede94493788a33e3336ec2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"8168ba4e43855267d62f98e501ebce9a29504dc9c885701379ad01602ed42ae98f77cbb3e13d779a5dc4215762","nonce":"9ede94493788a33e3336ec2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"c65faeba682c3705e579c899634deb2e00ba6aa14fa26c19f77baeb77fd4bc289c9ea0354c0db419d3dc89a2c5","nonce":"9ede94493788a33e3336ec24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"38c3affe2a19d380e96f3ed456eb909e0a7024379161e3e16fadf5cb343c74d6ea91ce5ddaf279b1fd50dcd1f9","nonce":"9ede94493788a33e3336ec25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"8517da9a101e4fa6b61ea0993c32f03b77007bdd492b40a97dbee71c8b0ebef859625caadcdd35eea74e0ece8e","nonce":"9ede94493788a33e3336ec26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"8e9304c915709be8cdf9b5d2ebd1e86268792a56355eba37cf6df9390c92432ad02b97c8b87fac8b6f1379ebba","nonce":"9ede94493788a33e3336ec27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"4e023bfbfeba3bb5bd67c8f3ee7fae01d9a1347806fe1d1e66f0db1cb59b01efd570b906d85c72b3f92f53fb34","nonce":"9ede94493788a33e3336ec20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"61ea5969e38bae32913a07c0b7f46678b03af009e26460e0eabb3bdbe9bde4239a2b7e0e623a44cce0cfa672ee","nonce":"9ede94493788a33e3336ec21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"3facc4b30d76bdc154f4aa20f03943284cba0adb23109ebbe377c9f5aec8f5bad597df5162dd00a5973288fdd0","nonce":"9ede94493788a33e3336ec22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"006fe2e7ebd26d8d60928b6b0ac4e477d40ced361d65dd431a5e2e176967e0cac1566b1bbf4ff026f73d0a9f84","nonce":"9ede94493788a33e3336ec23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"5a983fafba3fe1ed60223d7dcba43f9f852a9c96cdda4f06745780b21f154af4938f080db9e5dba02ee3136c47","nonce":"9ede94493788a33e3336ec1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"0183f015fd3a453dbf9de40e5e9e5ff5c7a2f33b9fa2cbac6caf05b24b6b46a0d7c4905ee691eea71331f1c65e","nonce":"9ede94493788a33e3336ec1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"58c752053782b10688064a38ff7f41ebf3318919ad6243a98cec85ac8ae512618e22c7f749395744ef8cd90cf5","nonce":"9ede94493788a33e3336ec1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"5066eaabb7124ea7d7a2d3b42b0dcb73169f7ed9caab0f36f7c45dcbaa5595cd139e7448537f5595d43e2d970b","nonce":"9ede94493788a33e3336ec1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"53383c86a993a53dc335976e2474d74fbc3ec3316db4256602a2905bf63e09757e9373b0aa84c3edf3d94233c5","nonce":"9ede94493788a33e3336ec18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"27d53df9b10aaa528381c39933d4f1ff6e89286fa76f3e6c349e73f0a6aee6b4d29bd5ba0822d8ed5930feefe6","nonce":"9ede94493788a33e3336ec19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"90af5489da3afdc1175a182c200e49301758c8fc88564dd45d65a302b825a5c0d46296e1ca8fcacdd879e5df29","nonce":"9ede94493788a33e3336ec1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"791d5f5fc301edba41a03006fa680e56ec0ae95522556d28d84a2b7c5488b715c34ddc161e5183c82f78632f16","nonce":"9ede94493788a33e3336ec1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"d18d708a5ec49dc794ea665fc3cc42f969f77e3d1f008f33f4de7a0ad668bdcd550a19d4d4dc43cb4eb2d17d54","nonce":"9ede94493788a33e3336ec14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"1c9b988588dea69d94525265acbdd6a0d18bd469bfdf3f230cc43f561b77cf0079c5b679f54ac089a94ca0dc1c","nonce":"9ede94493788a33e3336ec15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"9d6abfb219e8b3204d7c20f30e6694ee4f74779d9c2404b3a4af0f2c1b83d5cedc7aa8bc96c22293bb397511ae","nonce":"9ede94493788a33e3336ec16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"6bd9b61a81f9d1ae9fb7bb414fa68bc2889bd18e8aba4bdf49d86bb368d616a75998a0aaa546557aadffa1340d","nonce":"9ede94493788a33e3336ec17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"8e12f1bd02a0466a1471b137c60e78b8778211fb9dbd4ae260ef7ff0904dcbd91067b859c08cbec2f6bd2db544","nonce":"9ede94493788a33e3336ec10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"7231a0c163b1cc34165459ed491aedc603a987560b303526c6de5ffa471e0a564db4a64a33fee7e664509fda17","nonce":"9ede94493788a33e3336ec11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"c2cd36180847722e1ba1a20104dcb5fbaf475fda8884762d1cae706923a6f3d006c37a56b6c7fee4b3804c8501","nonce":"9ede94493788a33e3336ec12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"84efa282a96d519874e01b959fac559576491f15714da4dd69e0cf5d76c20835ccc97db03a2870f75e8b45acc3","nonce":"9ede94493788a33e3336ec13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"a8c6b7c63dce197dfe66776125dcec1ec1cff7304059bcece3aa96851f3a5979e90dff6ed84656aa02e8add283","nonce":"9ede94493788a33e3336ec0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"513e09e5b6bcfa404b5bdaa370dba50c2837be64075e0776972075fcb8e70b9781f032d14c95320cb1565b7738","nonce":"9ede94493788a33e3336ec0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"2acf3355afe15415603e0c809b981ebfaa403f387baa2bb497478a31356ee091a1f36ff262dc7f3c8fdcc8a458","nonce":"9ede94493788a33e3336ec0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"2f7c711dc39c5a7371449db9eb0da06a2ecb3060fcf62dc1df5dbe64bf27881bc9cf9dbf57faf1bb42b975a905","nonce":"9ede94493788a33e3336ec0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"61d196114838eda0bdef9f931172a40cf798fe56eaab49a26468e3ed459f67fc536b741dec2eb1ad1554bddf2d","nonce":"9ede94493788a33e3336ec08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"1f3f0b504676cbd865f85d571ba24bcd0c5c6c89cb06d7492b5847de860e1521f5dbb27ca9cdbdee5533d13499","nonce":"9ede94493788a33e3336ec09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"b01ae1a8f1bbca7a3ada3f4834a271f9be74f322fa6ff643323c374f4e6ab3dd223b5e7cce13104c5375522c42","nonce":"9ede94493788a33e3336ec0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"97a52d90db5492d62bc8ea4d58dd383cdad5f8a81ff00319e42c80f57770a2e3220d4bb8d831776a37dcd25d03","nonce":"9ede94493788a33e3336ec0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"c28876f5d8a095f9672ced5d17df796642e3da38481ad12f1c671216e6df68d2c3ccb6a2cecc56f1113d7b2f23","nonce":"9ede94493788a33e3336ec04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"9de7e0fd01a94061707088f1dce732461d850104e00d0521cde4748422e35f9f4c840675a0d882205c097669cc","nonce":"9ede94493788a33e3336ec05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"f8ce69d1b2fac01da65c200da2e01ee50fa8f2e9c216ec2ea731c95e4d779bfc97734cc56ea3c8c5c86817edd1","nonce":"9ede94493788a33e3336ec06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"a26714706105e9ab2d7ac6d42cdef54ca74598c61b7b9177a3700b636117015e16e6cb81c7121a376a181fa173","nonce":"9ede94493788a33e3336ec07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"f2d99d4b52a9c760f4ea33dcdc262bf895a30f177a25655709a2e682e7ffed9f9cf77aa12076a75d5d321957cd","nonce":"9ede94493788a33e3336ec00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"9b9c67ca09080999f156823625a4a406be6188d8f01eddd8349f2fee07c2426e095e970b6f0900c2270f313534","nonce":"9ede94493788a33e3336ec01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"d5a4e5469c080be21f01173f7acda457c92f1b777da707770921f347e17c726102d30c2d2f3f9ad53f5cd3fce9","nonce":"9ede94493788a33e3336ec02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"644ceb5c8b1fd95a5c05a401936e0e4ad2b9901a62dbe0486fcf026247aab1dedee0cfdda917729ec7788a40b2","nonce":"9ede94493788a33e3336ec03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"44f7b8c5d50acbc566c074700afbd1eae7ae3050a964b7aac8a363da7c1c3e35fb725a65561211c3bd75def372","nonce":"9ede94493788a33e3336edfc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"1b16096e3c191097fd9fa3fd2e0ea0ae6536a08b405e150a4682f3d143950e59"},{"exporter_context":"00","L":32,"exported_value":"d4b0d1c442fb29ee57b49c97c4be7b5c60a9c119851db9ad55b78d77ca1b5d92"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"7f1deb42524badeb00528cf7b99bbe16391e45acdde6995c2832429cbab87144"}]},{"mode":2,"kem_id":33,"kdf_id":1,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"6de09f5dc406936aa15439b01379fe2410a417b5d7a0aab505f27db22455cb38ab31f6aee5b27039640de4f164a3d3c19ef6ffb3ece3026b","ikmS":"5e5eff2ea2483a22d832847b14a95a7aad3033df819bfdd97131984a0107a9640f6c7c77b2fa2f1e93d0524f3416eaef08159a046845998e","ikmE":"75719a9cd4e03f64de631800221f75e22d0bbb13ff736cf0626b68b09a330299ad4e37bebc2e80d9f4e1354fa0c3d3dcdb56ea70bd3ead8e","skRm":"367827192dfcd0703b46c50b55ae59deba599988884052c4959ec66354825aecdddf678e4ac6ed8d5e755509f703383d465cf4374ca522a4","skSm":"1ef2cce1cd3a11ef48d2602381c7fe4c1a59c176c713758120b60a10859f3887341193ffdf0fa9897e92c9c7dc057d82373db2393efb841b","skEm":"8f78b1f65510aafe5a1d10aa3357187b8eb631608eac4d88d4cf43df5ea46a371bf92f40f4ae71a12e6e67ccad8cbc9eb239e3f661a10317","pkRm":"65445ed83fb66fc6af3ac8e39c282d6792652bf0019bb3e7af4c53947f93bbd782a4129f95d7677b0c94b32d3be6d7b8a38fbece3fcf00f8","pkSm":"463834d61fd3dbe05943d75c0988970979c80cd2660f8891ecfb3779f67ac2776c6d17f3e5a72e02edf2dbbbaa0a7fbdb205f2346946b900","pkEm":"1b6dc907a8ef0b75b5d9363f58c8b0e4bc14c8a72123d9f1d782e15e63a9a02087a2484536741c4541c72503c22866b1a518a9f61544293f","enc":"1b6dc907a8ef0b75b5d9363f58c8b0e4bc14c8a72123d9f1d782e15e63a9a02087a2484536741c4541c72503c22866b1a518a9f61544293f","shared_secret":"dbd353f5c41eb4000698fa7277abd820d60ce3e7055722c8599b5f4313e9acdc31789649c3dd73e3c81714cf92a230e96b5c8e93ad75fc49ad785217bec5cabb","key_schedule_context":"02fcb1dfaeb0f739e1fdef674e3bead6aa703796379f96c738934a64ac77c79a0539b47ef10fef9d74124a76b6079f61957d5b791d37ce9aa2fa2a910a7e47ca58","secret":"7bc4f96d170e121bc232cab154cb51099f15dfa5b6d261f921017184b6e10788","key":"be98e5092e262348b90df3a5b492ec87f9e56e221db4bdba8acf77112d658076","base_nonce":"a876ddf57ff5f054569f2ebc","exporter_secret":"dd91d8c00f88ac3fc816852f1a46468faf9fcb903ef0d9385bbcea8fea1c71a8","encryptions":[{"aad":"436f756e742d30","ciphertext":"0dff9ce2d940f6f452fb8b2e832cd01236dfe94974ff1a3a9eb5c3457bd915ab2044bad38c47a56842050ca705","nonce":"a876ddf57ff5f054569f2ebc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"040623f587324143f924b347d26802dfa4b4b128490b13064c1178f01c6e7af7eca77fd81695f72ce955c79fa2","nonce":"a876ddf57ff5f054569f2ebd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"82f1424a70e78a9908baf12274fcc58d90c0aff9f875b7acdc11d9fcffc313ee5d3efa116c595d65bc0ba028f9","nonce":"a876ddf57ff5f054569f2ebe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"767b68d97c625252c096e97c609cada21ee1a022afb8adb11bd9bacd96a5d1efdc4a3684ef52c16db2a37a9868","nonce":"a876ddf57ff5f054569f2ebf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"fb92e9b0c26eaccd282fa61567ea0fadc4e99d5d2c0ab6ee284640ce2c1fdcb1a8cb8e238a03c7225a000a5c6b","nonce":"a876ddf57ff5f054569f2eb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"b879c6670754753919372c094d5643aeb794f955548f8519500c803bade102d19566e52062d4c7c18a3d578554","nonce":"a876ddf57ff5f054569f2eb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"ecae1822a745c2c44056a56a51a9afc586a8b80204f50726da0d66d9e1f9829aadd917c7c52c166adf6bc8e2d8","nonce":"a876ddf57ff5f054569f2eba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"3cad175f0b47b4f514cc3eff4311667ac8d7e951473d3fbd140c9bddf53adeee0ab19e64a8589b374afbf5ae77","nonce":"a876ddf57ff5f054569f2ebb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"18eac20eae1f6ec8c5a581a135e04dad790318157c79fe98f60ca8bdb5f3d4c468a8e0d11f8f87f5cfac3a008c","nonce":"a876ddf57ff5f054569f2eb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"ee312da4094dddb9e739bf6c39e733325cc2076efe0d3da914535d1d392a9363919b9c96e448c5942f64156212","nonce":"a876ddf57ff5f054569f2eb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"e62942519af69a0e5644a4b55d6bb7a6bc41fcc4a260538117d22d53d66914c7c4e5515468a7862365d1d9a2df","nonce":"a876ddf57ff5f054569f2eb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"0d0259869593fd84f954255bbcda50671c4359c1c0831365fa72d6853d4ffee97b1a160ec3f2c56806720146e8","nonce":"a876ddf57ff5f054569f2eb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"efa7a941892772a28eb5e91372269d3bc454c8ab3dc74b62decdd03042700a62264cee8bd9f6f15ec3a3ea7da0","nonce":"a876ddf57ff5f054569f2eb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"6c1329239e4d5b8f1ea51c0bfbde2e571752635b4eab989cfe1eec937eaaa4f7764bfa7e8be5a9d185d8cd4709","nonce":"a876ddf57ff5f054569f2eb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"1b2b01412c9bdbdb57e58da640179b780219c079a4bf2c7501209b11f3569d5b989960b96f4a912e2dc66254e0","nonce":"a876ddf57ff5f054569f2eb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"ec2abe820695721d978594c85a89551f78bca091b35aab30bab94b8d7b41c245cfb925f99aea0823775cea441e","nonce":"a876ddf57ff5f054569f2eb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"0855ca87d16ed387054a84e670f098bde4f48d047e92cef11c4625d6cd8b88b391f4079ee8fb19cb8a3a7b2ea3","nonce":"a876ddf57ff5f054569f2eac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"26aea3e9858e1252cd1aaa3a8105657d5c38a3070eb7f993cb5906774ab320585b68b4bbc28223a4a4866045b2","nonce":"a876ddf57ff5f054569f2ead","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"ab309d28f99598aaab63b9ece53ea2bfe6ad85aeca157caac2e68251d8d00e117d2b0ca3e38c2c55652b6b6fcd","nonce":"a876ddf57ff5f054569f2eae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"19937f064f43b0a7a070a20f33cbf6c6d340dbbdfb72bda8af99cf0289385e5227436bd5f86f7e7293ab198bdc","nonce":"a876ddf57ff5f054569f2eaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"0f8170359f18b81e8728b8897e28dc244f7ec0a6821db777f180456e588782cd4f8f47672ad5872f6cbfa62868","nonce":"a876ddf57ff5f054569f2ea8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"f893037706775b8903abb7c5de396bda7544a983279de92e4ffbd6f8f809b2f381bc43d057a3d7f93f05af9b69","nonce":"a876ddf57ff5f054569f2ea9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"df641aaed1917f30b3a36ad4f69774bea04d515efd292b4d5f71dbe16b6130b70bed921ea3d2b1eca8aff49301","nonce":"a876ddf57ff5f054569f2eaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"d5a2698e43ac90c29f9cf3d131580d4d26991e39fd02023580a7bf459068322579dc85a4d33424c0f227aff2ab","nonce":"a876ddf57ff5f054569f2eab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"b38b352976806331dbfd57fbb3fd675471dbbdf5cd28ce8239fc8de0cd0dbe314d291e04b8c1ef09279ffe28a2","nonce":"a876ddf57ff5f054569f2ea4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"fb73a3548409087b207510077a3876b806d4facc1c5713ad346ce91e5feb746421ac9fb9dea11968074e38a9ef","nonce":"a876ddf57ff5f054569f2ea5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"7b00dfe5bd48c71fa7fa24e922a5290d8b44e082d70356e162c4034df4484add46d79da38c25c4452b34a51612","nonce":"a876ddf57ff5f054569f2ea6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"388477768fdf2f96ebd90e54788c05a0755b04319ed895e1bbacb28064ccc683748012896928191e2e30b63403","nonce":"a876ddf57ff5f054569f2ea7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"5429dae17aeb6d6b33240558e4ca0d694411130bba99a81520a895b4ad59fbf7bd4b0d2ee599ce6f6155cec2b6","nonce":"a876ddf57ff5f054569f2ea0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"b7e676ebc037e4ae4702b72b712e92eb11b73f1326eae121219ab41889719b01cdf742cbcc8a934fe5df7e3b3b","nonce":"a876ddf57ff5f054569f2ea1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"e565756c2a4cd7595b97900b913cbedbd1fa93f16e534eb4ec44e320465117c86565da8947f196aa7bcd1f4e65","nonce":"a876ddf57ff5f054569f2ea2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"e8eea51a81e40416b82d64d39357e1aeb6419b01ecc20ab791f98adf92ab96fd0616e1f8957a4d93ed6ce89343","nonce":"a876ddf57ff5f054569f2ea3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"efd82a5cb08d4cfc8ffbd4a7a372efa3d5fe2877e6170c45dd0f589a42d678616be610034a947a0c5a9e58a7fa","nonce":"a876ddf57ff5f054569f2e9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"b4d2cd3269f2ac4d6e5fd223744b0a7555c3ae6260b88089a3ddbf357cd4e8b51573e08f5dd33f4b71edca0c6e","nonce":"a876ddf57ff5f054569f2e9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"607291b57ad7717d59cce82a57e4af83ab45550fd0b8977237b08c0ad4b965fafa94738f880989aff593cefeb7","nonce":"a876ddf57ff5f054569f2e9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"43e02455de473efd6abd0d7c0a0d0d9218fa1863b66f589da57aad3ad52c414118deee913e9edb98ba14cfb760","nonce":"a876ddf57ff5f054569f2e9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"8ae0b79d920997c4043371f53e80a6a6266c9775a4f43655f9776b816eb775aa548408562454838a21afd21200","nonce":"a876ddf57ff5f054569f2e98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"ac3cb8492a0496ba3498f0e8e78f17dfddb5fc5cc2d620fe2db95934b3badacf5ba543afad9d99853ce572589b","nonce":"a876ddf57ff5f054569f2e99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"d6bbd5bb7c4d54afb2a7c9fd5a63eec12dd4528f2731122bdcadcb07ca2c0bcba533098c6b19005fa5b475722c","nonce":"a876ddf57ff5f054569f2e9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"0f4c50c46bc131ebb3014f68c00272c599940d136a0687c0c4015225e85d9edfd5a6fe3fc052ded2a4b1f50f2d","nonce":"a876ddf57ff5f054569f2e9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"e535290986bf367ed8edb42abbf3e73d418ec6d4b0deb81d929c75ed676146ac5fa77144a7a94c22e568b2c2da","nonce":"a876ddf57ff5f054569f2e94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"23a18760fbea39a556d1676d65ca5166d9ea82c05b58e8e5d1e623fd2eed3043ed3ee1c4647395172c1c096d62","nonce":"a876ddf57ff5f054569f2e95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"a5a55a6269300bd99c86cc59c15be3d10690e71780ddad9fa3d00c39dc6e672cb78520fe55e04e02333f5612ab","nonce":"a876ddf57ff5f054569f2e96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"fb29632a60467e1b7856ccc850c53c207bb481753201873a203e1e1ef1c47bc765b23335477de3bcdbffdde0c0","nonce":"a876ddf57ff5f054569f2e97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"ae81a0713002a1869c203f04df833824aa874619467ebe1bdc17240a8274965b8d63008ff767c262bbde5456ab","nonce":"a876ddf57ff5f054569f2e90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"97297a9337d6f9d59e29677e097205b7c6a59bb039a82daa29faa50f43ed6bb463fd3c84ec1f9dd6252d2f81d7","nonce":"a876ddf57ff5f054569f2e91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"cc9679e3e4501013c2b855f9bc6e828a77ee26313a401f76a64a7705ee918166f22da9fe4dd03981c4c920cf0b","nonce":"a876ddf57ff5f054569f2e92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"b16289472a82fcb97f9b75ed1817f04b96786b6e19b6b045279cec7bc9c8363a90de2c7f513c9a475684ebcb78","nonce":"a876ddf57ff5f054569f2e93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"36ad76987ec0e6ed48a66de3cbf3577cdf994126a27c6a6be78926d97dbf06b4eca0bf4099193d8f493caac690","nonce":"a876ddf57ff5f054569f2e8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"3ac5a8860d39606bdaa80f14246f2cb1ddfed12cda12bbf97c06f0c745816bd4606bf7f1cbfe9ec6246d0e402d","nonce":"a876ddf57ff5f054569f2e8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"e59c88b1788d5558b0833c6f5ab6cbe00175053cbe1c86379f572baafa6620c4c12187dc60eab956bd06959048","nonce":"a876ddf57ff5f054569f2e8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"e715936e0a3582903f0026e686b9a42bc25f7ab983afc4f064f9700188ac190334366ae0f36b34df0a9369f54f","nonce":"a876ddf57ff5f054569f2e8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"55774c3c0d93aa9b6432ca7c760f29c5c9e93eed57ea2270cfe8c46004378a705acbbd955a9827e295597f3b7e","nonce":"a876ddf57ff5f054569f2e88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"6301098d77971db543bcfb516c421ec61ca5a6649e67e10ebfe35ca83d2a608389bd8897e2eb0d2bdfb8d030ee","nonce":"a876ddf57ff5f054569f2e89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"663936451fc21062760bbaa2a111c3008039f7ace339589b870cfd6321d0cbb07852c2df67fc45a7d12bb7760f","nonce":"a876ddf57ff5f054569f2e8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"9305506ab002f58e8bf4f6aa334db4be838f5cfb28bdae8f4aa5644d48128b56eb273d7cf1129aa699fe8519f7","nonce":"a876ddf57ff5f054569f2e8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"0e827ab544abe9b53262772dde2b766646ea6cb586aef935306745bc8b1e24d5c1c0965d3c9c09fd39709348ef","nonce":"a876ddf57ff5f054569f2e84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"1f0424d03ac0f8466ac1a71bf5b3abefe6d9ad3eea406218f222818b898bbd17b970ba6d2077a318cf53e962c7","nonce":"a876ddf57ff5f054569f2e85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"32222881414fd90645dcff7c2c7439c2e5f64840f122fdb141a10135ec3dfab9a0e69c1bd6cfc95b3a0b1fefde","nonce":"a876ddf57ff5f054569f2e86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"742f141f406b6268e1228eefb9e9ac80e018bd9662861c18256b627e2e88b57ed9312388ccba0afa3b4b1c80fa","nonce":"a876ddf57ff5f054569f2e87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"12c3ff9d61704c10af5366b2357ca3618ae98d110545356da5953e3814c69597264da9c63153829e7dd6e6415f","nonce":"a876ddf57ff5f054569f2e80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"fda9d9575e41e0c81e0042a2235be88a93bea41026211e5564d55ffdb13ca8420220ce8b00ce2846579df46d4a","nonce":"a876ddf57ff5f054569f2e81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"7b5de246a274dae0e73fdfdc81c305e65387a084763b5804dc6f902836fa289f5b2df190b1f7fba7af911e27ef","nonce":"a876ddf57ff5f054569f2e82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"67eea2c7da7f38b345eb71b9d491cacb83eb56eec1e2003abf90489f1b0863b454fada832defcefc0908f790f7","nonce":"a876ddf57ff5f054569f2e83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"715dd5d9a8c1ddc0c835397893b53b639c40f26300082c9655805e0624eda3186436b57288bf6e3af3cba31d74","nonce":"a876ddf57ff5f054569f2efc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"761a5fca032eacb31bc6a8a58f06ba38213e0a19488ccedbb1bcaf3c628c7f0ae14429c7bee817b1a760ee282f","nonce":"a876ddf57ff5f054569f2efd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"0596e829eabfe39b30494190fb2925418de8b7434edb1398c8f7cd839185aee6cce3a608d33590373eda4b1761","nonce":"a876ddf57ff5f054569f2efe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"c8d9fbafcd81738aa25db352d6c64c068af74527c236f914745998bd69bb105388a55d18c21746d95021c4fc64","nonce":"a876ddf57ff5f054569f2eff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"53bd9bc2e09b51749d7e25f3d4732a5db674888fe5d601bc26f01cf8f5266bbb47a8ce72e326ea6b6d7aca9400","nonce":"a876ddf57ff5f054569f2ef8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"8a4f7753e668edcbb8fb19e0c22b4eab51599117844534cdffa1d4c724babe196c20b0174aaafb07f4339e2499","nonce":"a876ddf57ff5f054569f2ef9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"e10075f0941fd470483d29fd54b1ae114082de5dfff3310d62a6277b13445c1feaf586d4debc31b5851fefd8ee","nonce":"a876ddf57ff5f054569f2efa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"59728332b8f8ada94137692d186fb4ebf3b96394c74ad92cc957f61e88851870cdb6d01986a606317571826edf","nonce":"a876ddf57ff5f054569f2efb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"2b5421aa9d9f021e67403d6d12610e9eab74b8e17ee1831e2f1c72a94b1b291fe82db20815ab67a6dfd11b7055","nonce":"a876ddf57ff5f054569f2ef4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"03630cf2d9b6c80ebf5d6ba83a6f3e024388011abf1790d545cb24efb14d9d06cfeba05eebf5f0e65c06214c88","nonce":"a876ddf57ff5f054569f2ef5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"d3b9a2908c035481ebc61cbd99dab46433be8c473f0201418a19d89557e845c5d206c2420aa1543402229e1c0c","nonce":"a876ddf57ff5f054569f2ef6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"73505a511d0f505fabfb3a07bacb92ec05f6ba4b234c0367539680eb20239ae44f502f48711d97dcf9204282b9","nonce":"a876ddf57ff5f054569f2ef7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"3387ab1b58724c2b69d6e1ead50a52ffd1a10fe938dddc96ac56f3bb1718451eb89ec857a648696f8635d88314","nonce":"a876ddf57ff5f054569f2ef0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"a798621485fc92421a1ce9edf803f302025395b885aad374844c06c264acc14c36469a97df6d6a496f2fd55dda","nonce":"a876ddf57ff5f054569f2ef1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"96e594d72edbc5f626b630eda774cfe9d206aeeff086ad5edd78d313a13a25a6b97cb193f6ef3fdc4433c3d708","nonce":"a876ddf57ff5f054569f2ef2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"ddaf5db90aa21621bf94ca48ed1cad4172eb0766f4e7156df7eba42595b4962bd15c339b96d41bb13754d8922f","nonce":"a876ddf57ff5f054569f2ef3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"9e23f085a61a027fbf3a619c4e74ce3e60b6126bd47609d2b32e7727afb84ac96fb7cfc8b2ca9f90471b0cf66e","nonce":"a876ddf57ff5f054569f2eec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"1b1d08833c4536981c56f10a0afb80ec75c4789b909b41467d77bb9ec83825226177425bfa5973bf1572f8449d","nonce":"a876ddf57ff5f054569f2eed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"cc06983bfba4847b9d3b11a8abf124ed9013dfab9c0ae625b04d248376d5281de9ce35c7d8dfd2f7f360c0cdc9","nonce":"a876ddf57ff5f054569f2eee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"4d744cd43a79d72256ee223e482e1952a591b6db13938f69a05670a83777767d1e6f9542815494e036abf1056b","nonce":"a876ddf57ff5f054569f2eef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"fe66de189be9cc84cd131f90d9931a65b029bc1e692b982c72cbe07351a809df96515ebb7879b4c65a94b8728f","nonce":"a876ddf57ff5f054569f2ee8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"9a208abc140b6df2470f156af170f97fa9f0d0cafed24155931cf4c74756a9c6a28ca898dd995cb10c8456ca00","nonce":"a876ddf57ff5f054569f2ee9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"bf6d8807235245ec56e76141d20b86611462392e820d2fe8c9fc487c8809ac86c7ba1201ae37fa370a246797a0","nonce":"a876ddf57ff5f054569f2eea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"f2995a36b384978b9803d6327a203d9f01af90dedaf801bdc5a015f4dfb8ed5b986d6edf2e2dd836eb15da7e81","nonce":"a876ddf57ff5f054569f2eeb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"a5560e022eabc84fa41c0ba86dc4b4591e29affaff2e3d72acf1ffc6cebb9d0bdbc0ea51a6934279086075cee1","nonce":"a876ddf57ff5f054569f2ee4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"aed8f2d25d7c678c3becfbca8149bd48a78d96f1741f0412018577f43039bcace76013207e0eaca08c2f76bd1e","nonce":"a876ddf57ff5f054569f2ee5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"f34e342cca2a242472c6a2c725136d61eb5b70513ef03da9a80acd299ac4063490122762d63ddaf79a2f59bbd9","nonce":"a876ddf57ff5f054569f2ee6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"373da420a873c5482fb97947179ff334fde12c99db4eeaa9e4f0f3d94025a0c6bd8924b45046d724d2df6a9410","nonce":"a876ddf57ff5f054569f2ee7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"e141c8cb7ef2aa2965de6e0f8e15045fb01fa8cde373358b94f707781f7c82cb0a0df96d60e0b4279ab9f2ab04","nonce":"a876ddf57ff5f054569f2ee0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"028488e1957dd2876a90204e9eb16eacbfdc3e7a80d51c8b40f83f9c32a4dfb066939e7036f4d39c70c3de3f56","nonce":"a876ddf57ff5f054569f2ee1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"6f3af5846dea4a789513938a335a44e554459c343474084c2a842bce367ddd4b43181714c34b6d8bd81126a658","nonce":"a876ddf57ff5f054569f2ee2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"89e28d80aa7f724d2a3d989db79ecc8d3acf915e3d8a4f91a540087e352e7c38b9ec5b578e6c32fb5d8a19698b","nonce":"a876ddf57ff5f054569f2ee3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"7c8689a4b71c2d8e7df4bd87e5bf9f99226e5385e11eb6e01f1daba7d6b1d340078a5084ca0e7874f3b2fb17d8","nonce":"a876ddf57ff5f054569f2edc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"010310cf3fa90a478f571bed5ce6bf2b7a0d155229b4f87ae71fe41afd70f64cb8ac2a07ee616fc1335b3da259","nonce":"a876ddf57ff5f054569f2edd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"c78fa9e438a0579eabed29e157ad582027ba96841750960582007e56c2db15e7842515e82af36e7ca15dce695a","nonce":"a876ddf57ff5f054569f2ede","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"eb6c0e441fc95bc269244e583c437decd721a0cc6561b7125772bc80ebfcd791c3a5a53ad02395797a7dd40d83","nonce":"a876ddf57ff5f054569f2edf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"c3831516b1df5e4f3fe3d8fbcfee30f5c803fd5c8180e919e879f722459e10a61a27936adcc15e3726f783f710","nonce":"a876ddf57ff5f054569f2ed8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"c48520da57c0b6989c65df64f6e69a20b42f59cd558f880ddc7a31d76a5057ea8ddfd8131f289eacd06e1001ce","nonce":"a876ddf57ff5f054569f2ed9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"5d125236607fc63082ceee4cce9b9135873d3cca5202508c1b7feae9d295f67e94d3ef92c65dad71ec1c487ad4","nonce":"a876ddf57ff5f054569f2eda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"ba2c89be06ddaad8c9c84f5a8584e8a41b885078e636bb1fe13d9fd5f1359b6207d218ae094df26469de445e93","nonce":"a876ddf57ff5f054569f2edb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"4114c1014490333d472f92bb38f342e2ed8e491700dabacd539bc52afd61b13e4e35275d553575905b1a17e91f","nonce":"a876ddf57ff5f054569f2ed4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"927181747bb821ccd1db24a46eb7cbaf411fe8d156db9cea58fa1425fd5b6e4ae10b84b7b2d43a278f2fb1d8a8","nonce":"a876ddf57ff5f054569f2ed5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"045d31cd3b0117354602ef501e8185127ca43306f3f1d414f7d153e2495d3565118539ed7ce99c42d385c028bb","nonce":"a876ddf57ff5f054569f2ed6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"9fefca682a6bb851361857b6bca11bc6ccc11bcdc876f6150c91fda95f06db0bf95a8f3fcde8fb495fafcbc08c","nonce":"a876ddf57ff5f054569f2ed7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"3695f69927f3414aff72c393280eaf56c08dd8ea7d63544cbf902a0d7b938b2036ebb9d791466eb7b647d1c69f","nonce":"a876ddf57ff5f054569f2ed0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"0783472547c553592ab04415f4ed9e317fd11ef3b3f300d5397d93987e1545b2de2c736d2c0caf174d47a147ce","nonce":"a876ddf57ff5f054569f2ed1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"81166959db17f4df3e27776271c4085538b73dd9bd49d8e46a4e7238d6c642a39e8aa67221b29d063aef781fbe","nonce":"a876ddf57ff5f054569f2ed2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"e66ec276de6386c7dadff340933cb88254cc739adc80b481f30e29df0a8fb047d681d97c725a266e1d87e3b655","nonce":"a876ddf57ff5f054569f2ed3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"a526715d0f540037a7c280e0a26fd51130a86df2e3fd09a76e01c1f3c52febd34feaf0c786216d7ab0961ee06f","nonce":"a876ddf57ff5f054569f2ecc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"e701a0debbcf9b37576f5f8368de5fbfac3fcbc9dbc5eed47c4382a29a5a5bd56ee5bd7f9c0beea0b8246d3e3d","nonce":"a876ddf57ff5f054569f2ecd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"8b89b7104644bf1cb25625a7f509793738ed44da899affb05a8cc03d2e80225d218307628f1087eeeabf3b58f3","nonce":"a876ddf57ff5f054569f2ece","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"a1a6883ebeab73133f9c3a5b37017ea64aa43a368586e0f746c0b971fe6dd62bcecd5c85b35e36940fb0660fce","nonce":"a876ddf57ff5f054569f2ecf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"1894379c4325a76a3628687cbd345ad7989356ad7e3a5f57be45b8a6ed5befb334ec146c4dfff0e68885792e35","nonce":"a876ddf57ff5f054569f2ec8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"98f27fcda30fa035ddd04b58922b470b3d7d19d6d3d0588e63f40b9ab647577ae64862fd698011ca4a801b7163","nonce":"a876ddf57ff5f054569f2ec9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"640e544f6e7418691d0dc68c8e506526f3be72d1b2aed49e6bd53c071f22c6db12d10b1d3ee0d25386ce1c3208","nonce":"a876ddf57ff5f054569f2eca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"7350f560574625a048f3f123c804475fb276f4fc2e38e59a0614f07a87b1a091ebb1b5d461702db85395d4dfa2","nonce":"a876ddf57ff5f054569f2ecb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"5b6e8ee9eb974f7937525c3aac79a02d4f4547a954ef8dad3f116c67d5c9a30c767e92eb1b76a15bdf0e77a6a7","nonce":"a876ddf57ff5f054569f2ec4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"6dd2d8e250a2743a01241e64a26658b85c8d20e225f85153d8d31463e4d20e05fe507089a2aef456477d22ebe9","nonce":"a876ddf57ff5f054569f2ec5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"3dcc9d4ce58d9c43d45146f479f6eb66c2ed1eb610ddd3a4044aa70e631ccea39e5bbdfaed4510bee90c6a9fb9","nonce":"a876ddf57ff5f054569f2ec6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"ea2d7315f9a7ba9f1f05f06088d2cc40ec6bf957ea23d21749cd3c3cde4ba1f609435eb0c1c9c4ae26cd01a67b","nonce":"a876ddf57ff5f054569f2ec7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"d2a77924b86a8556c6e918398ebf50352da7b0595dac6e7a2e22d05e34f5a1b4133478471f922dacb83f8528d3","nonce":"a876ddf57ff5f054569f2ec0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"84c633d9b543aa3509f5ab8726c1dc56bbf78f8f48d01cfae901f6f35c535574e68e6c1226e86d3c68cbf2140b","nonce":"a876ddf57ff5f054569f2ec1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"4d638802bdf7c2804803be1e681221632f6a255c06d543e33f7a46b9e315dac819118748adbdee08a59199e0e6","nonce":"a876ddf57ff5f054569f2ec2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"4e79d44441e92ec55447c4484a5c1d056bd244c2dfa386e52a0e55b4f1e085ccc8229a46a0be1d8d9fa816f5af","nonce":"a876ddf57ff5f054569f2ec3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"fd947bcab0299024e1cbddd144d9d922009b2b5d3557d2ada2e7e9c3c8a265bcbe65c155096f717b7babcfe230","nonce":"a876ddf57ff5f054569f2e3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"0de797333e25005e50c6672bb7af3eb821a8af1c1072d2ec5be9c09459e1f7cb9022e16d2f64c500c5e5581b3d","nonce":"a876ddf57ff5f054569f2e3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"68a88cd5e09676ebbb73150763e1e92df49fc2ac79ff96e82d2cc7db432c00a6d18fd2b18a31be6981fe9acc73","nonce":"a876ddf57ff5f054569f2e3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"e714fcc104a15d71b81fd21df9cc107efa4fcb3c77ea2c37ee5acda42cb7c2d9885fe575e0c2bcd89c4b45d52e","nonce":"a876ddf57ff5f054569f2e3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"037a89cbd4ffc705aa1809ade7e36fb3d3c51e859503c3b0a175779cc13638564410939e1037c5180caaa7f092","nonce":"a876ddf57ff5f054569f2e38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"eb661f872e5aba0cafc5198be9d4a5470c6a0232d4f68ff672636d9b2a375ad9da9558dc682c1820f981a37219","nonce":"a876ddf57ff5f054569f2e39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"748dcc93598e656a33033bc662858f98ad00b919bf8e661e897d2f38e559baa1ed44e27d132680c2ab8d80178a","nonce":"a876ddf57ff5f054569f2e3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"138f4857f62ee37cabc5d306e5b599f4a71e36ce1ea36d750f8448739cc2450188e0715c78746b14751e5574ab","nonce":"a876ddf57ff5f054569f2e3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"65b5001c9775363e02116fd59f49caece16f60e6870416213f3b08be685baeb806e953ad5c3ef8afe3ea3841d9","nonce":"a876ddf57ff5f054569f2e34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"be8453c9a063c0d4b740ea0750f16416439ad1dc429633d3dc6c5d33f2b166e580b83b389e88bc9040be068bb1","nonce":"a876ddf57ff5f054569f2e35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"b88b0bb51f8dc9c57031f4eb35f0a211d15c1434808ced754d7589921ff28b95fcf2fc19b0eebc5eda6802dc18","nonce":"a876ddf57ff5f054569f2e36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"0650ac5ae067f2d09eead396faa3625c08741ec507b71d6970da731ff23dabd18369fe917b61ca8f89a54ad873","nonce":"a876ddf57ff5f054569f2e37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"415cc35fda8837c4274da685095072cfaa351f4fb1e23aa9ccd92411a4eb211931555d29e12dba2192f427da3f","nonce":"a876ddf57ff5f054569f2e30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"404d187ef2a67f8d763239ad0d7ab8b366c6447ba598b413dafcad98fd48c9fd5b99645301bf9490232dcae8cd","nonce":"a876ddf57ff5f054569f2e31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"b5acbdf85f5cc5ba287d9a33c3f34b4884fc0dd37a2f9aced5f8ff91a48414ae4a90b2414e37d12a5cdfcb4c3c","nonce":"a876ddf57ff5f054569f2e32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"79db07fe606a3dcfcbf0081e42f0c2e3a3164811d1f22a9d5c9d4dfe2beb26bad830bd8fb8a25fb4133e1f86c0","nonce":"a876ddf57ff5f054569f2e33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"a79f32447b5e988a1231dffd6952e1c7e4d98f3b60e52c821c2b775d2feec152c64bc18406fe4de86df1e77810","nonce":"a876ddf57ff5f054569f2e2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"d4305c794b82db0ea92d516a1ff31ff2c7e19e23fbbc84b563cfa0985ac7da264ad12a74fb00bceb77ac878543","nonce":"a876ddf57ff5f054569f2e2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"368704286ac6dc4c73a859833357e0db5d1885ff30711802ade1847b5b435044d7f1ee4d4c2afe5c2fcaca4aa4","nonce":"a876ddf57ff5f054569f2e2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"691a26dc2f70eccea1bb08d33dc15169b6d950084bf34c2e253fc11e454d1fac38b9281f8f19fe28e8b1caff7c","nonce":"a876ddf57ff5f054569f2e2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"154b2a1ea9108f590dc1d2d00577e23a135d4c234990ce81c9f19cba6ec19f68c4b0b06a88f73352a30ed56bde","nonce":"a876ddf57ff5f054569f2e28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"8d9a0b9ff3eaa583fb357f24a5b55901f4b7e9abdc419c72271786d3e190dca322f68501210132b2249e0537da","nonce":"a876ddf57ff5f054569f2e29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"30674771effb1d72f2e33b71a14c2329020689b7f25e59aabcc1274bad72fdc7cca5e093182fe78fb119eef711","nonce":"a876ddf57ff5f054569f2e2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"fd6ae7e937a4d68183fc2f5173e32119e6b8ec28dd8f5cda4c8ad8aa787f2f0ca5c11eb5fbdc0627d1030f4c14","nonce":"a876ddf57ff5f054569f2e2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"09c7150719ab978a3f33190df5dc585ce9937257135b14eec1778dbf57408eb149dc2d3d7cd3256650e68a593d","nonce":"a876ddf57ff5f054569f2e24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"e42a79b279c4306b4036beb36a57dce83d92f811128833c9fdfe6af1f82555c9aa343878514c5e886925c838e2","nonce":"a876ddf57ff5f054569f2e25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"1f31b3b9adf78593444a15b0cc1d074d19fb8c059ba6193b20b7d09162608cf6318a60d399b985bb9ea5033199","nonce":"a876ddf57ff5f054569f2e26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"13988fedd727ceaabab5822ded5b1db896d7a88ad8465f48f1662eaf8558185d5020d9130202824ca5e6922b03","nonce":"a876ddf57ff5f054569f2e27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"acb9f29145758c598aebb23117128b4eb8e865b9a7433f815b6d44aaa6117d1f14dcfabf13c985837b9a08c3f3","nonce":"a876ddf57ff5f054569f2e20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"9adfbf497c6cee7c7250c5e63cdf5b98a4b652163d7c73c304a162558ba19cb360ada6eb9f14e5764298a79b33","nonce":"a876ddf57ff5f054569f2e21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"c20707a1b3c9da470a53cb4a8b5555fc22d492316eb411024daa2cd5c6ae0acd3680deef60a149d676a3d975b8","nonce":"a876ddf57ff5f054569f2e22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"7b0df4b598dfd52e8d0ef6b041d736aa6152a03bcc6cf4d7ead30e5a3ccc9dbd6cbc5b505f77573bba23211fab","nonce":"a876ddf57ff5f054569f2e23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"0058c259ac033053cdfeace1f8f89784f8189553a33afeb9ab1326d6e6742f5acb31d1175b242013f7444b4eb0","nonce":"a876ddf57ff5f054569f2e1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"6e767e950362243a62b3e4d0c9b1d890a136463cc137c82f872b4b9eb5f1d4bbc0fabecb0415f7af0b7a0fdcd7","nonce":"a876ddf57ff5f054569f2e1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"cc850377d16f102a33e3bd4cb809ac28ca8e8c223f4ff3870a176b18650abbfe8b045a64c9a902048e13b24c74","nonce":"a876ddf57ff5f054569f2e1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"3d023952f2d4f5ffc1c3912b6f16485e193c140eee08203c48be5b4d0108c34d0a69392b0b4153c5e9e77cb302","nonce":"a876ddf57ff5f054569f2e1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"bfe9dce9ce99ea5ecadb638ab5bd2c03fdb953110f748e13cb51c90c3fea8db4219a501b7cbe36c63c125ce2c3","nonce":"a876ddf57ff5f054569f2e18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"e8e809b270c2bcc514ea6a9c9944383410534ef481e8e6311f1372bcb3dcdcd71a409330fc4e879f3208f0bc3b","nonce":"a876ddf57ff5f054569f2e19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"60235084734614305abe4d99ee5400d7d9ee16ea392a0245683941281fb28f9af1c8ce72712063a106a7fe32a5","nonce":"a876ddf57ff5f054569f2e1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"1227af0a10974ce1aefa3f430d113850b73a3d11e0bb144562102f523e43be9ac0bfe9f20c9302ac7808920c06","nonce":"a876ddf57ff5f054569f2e1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"5776be1c59f284fb4f0f72225a4ad8afc69f8aeee80bb6fd5c342602a7662ce22cae5f01bad3f03b16eb71ed48","nonce":"a876ddf57ff5f054569f2e14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"368ff79cdf9dc5a773e9349eda412f140356199701993b8030fd49c8f1dbb2231c6ae600e1567f857db8a5d1b8","nonce":"a876ddf57ff5f054569f2e15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"7e8e065e5622729092e3499860d4c87bdc2bdc4d735b369497f55d87c84832fb523b5a58808fab2d746612f764","nonce":"a876ddf57ff5f054569f2e16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"14336c8eb60ac1fbe20e2bb5fe16a1286b77f2ccd0fa8829d815feba31f82bbc362f568a22dfc411c8f470b104","nonce":"a876ddf57ff5f054569f2e17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"384238c43e1dd36174a5437c81814688be19426decb58aace494b17998ba202cee6059ce929593c70737bda0b3","nonce":"a876ddf57ff5f054569f2e10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"4a636d4df61b67f6135de31d05c92734e109732485234e8fb6e9666aeaa3e58a09427ab8fa6680a5a522b1ed49","nonce":"a876ddf57ff5f054569f2e11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"01daf499c8746940935cc56135de654f5f5ad045c25d842bee548080bc4baa672b445741c86b9d8e20bac3d1e4","nonce":"a876ddf57ff5f054569f2e12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"a00a3fd2c3b9ee324db01f82e510ab1e7d5e3b50e331804087beb159f5fed8dceaae733daaae88c6914154252f","nonce":"a876ddf57ff5f054569f2e13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"be92fa81670a6d2d9e609dc5a307dda68c183e398381dfbfa3ca2124db49d3e76bcaffa3043ca4f33ecd34fd19","nonce":"a876ddf57ff5f054569f2e0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"8d7617609b270ae4843449fcb44b17986535e98499cd38c09f0c29658bd0cee678741de32dc798d2ce87d750ca","nonce":"a876ddf57ff5f054569f2e0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"2187c32e02253e2b02f088cf98b4961d2c9b95c4fe8534cbec6091d6c7c87f9b939f735c97133528d226607a13","nonce":"a876ddf57ff5f054569f2e0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"c55462c91c07d7cd8264c24cbe4cf6ce1a367635fbc4a2b72e6980e4b113801f6f8a75c41c9ae0ad7d2f188ab5","nonce":"a876ddf57ff5f054569f2e0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"34407617a9c86164956f69fa80a3dbcd054b6307f0c883e98c10882d16fa433cefe4b1c269393b3705764d7db1","nonce":"a876ddf57ff5f054569f2e08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"d74a97f02e0ecae0428691ce5e5a36a77a0d7718e6359de9f23f8302e7af7fced05ac44856dbf7c095c63005bc","nonce":"a876ddf57ff5f054569f2e09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"b9ef1d7e544d587f34a26668954387d5df996ff4ed0ab81881ec5e784e98510696ee0d18c7111a05903650802a","nonce":"a876ddf57ff5f054569f2e0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"110be7b990c032592000f4f9d204bd8ac1e465c3418131c021b238b2fc6ab5ef4a36eef0cd12aa38ca48d0d94c","nonce":"a876ddf57ff5f054569f2e0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"bb1380d11a3b031c56fd8ffcfdd9b64744e37a371f8a81b60d6d67271220c7a1eabb010e6c044cf006c7e271fc","nonce":"a876ddf57ff5f054569f2e04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"7b472bbd3d41faabbe7810a9210a4add650565cd9b6d8d47df6dbd4eb3dc71244f0732570669d0c68912e616a7","nonce":"a876ddf57ff5f054569f2e05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"82a25ec4e667fac3a596f477657236851cf4a230da140a7fa000357fe668eb73943aebb8437d27f68d721fe52d","nonce":"a876ddf57ff5f054569f2e06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"2eef0d300185e8ded98f6b61f94050f41ea603fbea8f83b9c20340b7c34369945215fab21ef0c0b00ef259bd18","nonce":"a876ddf57ff5f054569f2e07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"03a9e32e76534fa0ea2af7910b745e591c3bbea0e5dcf9de62d3330c2ce2d60a085920b011d3b24b2a4e9be6e8","nonce":"a876ddf57ff5f054569f2e00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"fc6997852de475aa65515c10b1619a01ed424be7b6863f4ccd272d8bf3aa043c906f4fea36d7aca05e3412b0e6","nonce":"a876ddf57ff5f054569f2e01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"394caf39bc231d0d1ffdb559b52da603342f798558390192db90e933dad788e246ca54483d712c7f048dbb19ff","nonce":"a876ddf57ff5f054569f2e02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"a318e2bb2259f7d9bdd1283a945eb2c3d62c9878bd61be742abd75ea6c3cb571df05a0d2a26f1f37c8fcf78023","nonce":"a876ddf57ff5f054569f2e03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"0bcf1e5bcd832bdf3f5ecea1d345bca22a4c29bba10b0f1a251da8d695aa9ca1c5a739e120759ea7dd54b1045d","nonce":"a876ddf57ff5f054569f2e7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"3120feb64c73abf75e588eb9ff5d3287367c2caf27a3168d82602311bd45c66a207b72f2c81b889b35b44506a6","nonce":"a876ddf57ff5f054569f2e7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"de43f8a42890ef3fe0de7dffb8869ae667dde19437932c10877869af66cd0287cdc75aa7b0e9fc4abc643239fa","nonce":"a876ddf57ff5f054569f2e7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"eb421b59060e7377725aa995c969e44002e6229f0758c3a24c4c9cd79b417a4e40e4cb482ac715ed6c78ca353e","nonce":"a876ddf57ff5f054569f2e7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"a3e3debbf3c25b0784340dac4c13c32679161707705e891bb4e18ad54ae3505bbcbc937a38d4dba449417d2060","nonce":"a876ddf57ff5f054569f2e78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"1465ea1bec9af6829945a6444c3fd1d36aa7247336048ca747ab9c2c022495d618ba7302acb4c40c8c3fd928a4","nonce":"a876ddf57ff5f054569f2e79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"ac62241d764d861aaa185b82fa64ab1348b24f518c01588fe8e12bbb17e125cc277fb926c76fab15623a6c164e","nonce":"a876ddf57ff5f054569f2e7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"d87f47fa48e0de15c146d734571593eb63a8c3a408f2cad6e369af555c7752bae65ec039b51b6b04ceb4d35677","nonce":"a876ddf57ff5f054569f2e7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"f8752441ec1855202bbf6ba14a4a3692951b08a27b99e472e107302cc71ee2349b8bd6e6c9cd5c52636c24a421","nonce":"a876ddf57ff5f054569f2e74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"245cc496a25ea4aa39f269bcf490eea81aab10bdebc43d3d25c702e02380486713f3cfe4053b42cd50f3ad5119","nonce":"a876ddf57ff5f054569f2e75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"8cf05e0e17d9461e32ac9b267d77f554577fa8a82957cd962cbacf68de9116eec24fab48ae396199bd0ef01696","nonce":"a876ddf57ff5f054569f2e76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"2615c03eb34e29220f8d0ecac35caa25185ea4cd1952c22a784295d3c3017679fdf6f3b241aa2fcf5c2ac01573","nonce":"a876ddf57ff5f054569f2e77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"246aa9665ae56de237bce1e12eba1a193f2e9cccb0342011777ed640276127b421c5f583f4209aae3394007567","nonce":"a876ddf57ff5f054569f2e70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"62502ebf2993bb800220debcb5bf1dfedef5961dd3d69602c58995356fe57abd256a7360e08fb50401357686ac","nonce":"a876ddf57ff5f054569f2e71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"0b1220e234c16718d78b8de841dd593eae2a1e1f998659b87db336d0f0a1df0efbb46384d062efcfa890228da9","nonce":"a876ddf57ff5f054569f2e72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"0f92c5ff74d6fe8dd58ae86e5bf52d2d2812e43d489065cc8229b34a8823bd745109f80384e0a6b0d1e5d33767","nonce":"a876ddf57ff5f054569f2e73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"187f2c78003f2eb4841f950d54fe672d26dfadf8854bb5b344c0e0b24960188e8532bdce74010e820c9490237b","nonce":"a876ddf57ff5f054569f2e6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"3a267f55a65e3bb0e09bdfcb7a5259607da31ba6237864e47e813c34bea9a9ae6fe869ee59877ee64c5e102238","nonce":"a876ddf57ff5f054569f2e6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"82db4057147e36e981a5e0b62fd7c61b0d9de4855d070bb50e93c0adb4d1102d162b918aaeba0fe52ee9973b33","nonce":"a876ddf57ff5f054569f2e6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"3618822b2727a6e916ad533abe293054bfbcf0195866e43d4a872345cfea971f431072672353f875b1a9ecf583","nonce":"a876ddf57ff5f054569f2e6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"2280b7b8198a9b51a3abc80da92d7734d38323b78c710e31913272f0b72f22033037d790e8b985e39fcbac43b2","nonce":"a876ddf57ff5f054569f2e68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"7c6ea1917efbb6e49f13c3ed82cf69d7e2ca567bed7e8aed309186d5e4603668c455ffb485127a1520fb6bfa43","nonce":"a876ddf57ff5f054569f2e69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"01c147777f395bd9227910cbf4481b7b3da338254490095adb990951aa886fc1c5e1553eca9726030738be89c2","nonce":"a876ddf57ff5f054569f2e6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"8a1cc41445dee4ac8ea81ea5d6053a5c26bc5f48b2edfa9c1ccb2a1aaa0ad90bd69613254d87d1063497666e6e","nonce":"a876ddf57ff5f054569f2e6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"df4cf73bc3020d7e1a852ba4d339f06e294227b36194eb5bbcdcc59d101fd00b113b5d01f526ea4ec254acc930","nonce":"a876ddf57ff5f054569f2e64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"14bf09830c073891bd0adac60bfe3867a563ab835fe6881adfd7e7a1b1705a33e6d8ac4189756aa1c347dba756","nonce":"a876ddf57ff5f054569f2e65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"e25b15f0e47da8110886d02d2df5d2c5294b276c5a64251d7d794f275ff96ce10b6ea344c923e1708949bcb41d","nonce":"a876ddf57ff5f054569f2e66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"52557f000ad148677d13392fd7f2c0b1fb5acbf085ae88b87229e01f7289494822ca12bc5350719e22d1df253d","nonce":"a876ddf57ff5f054569f2e67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"1d36ea92f71d2e7c8c06bdc0de108438a6f29789905e3ec439d2b516e0abacfa93c4e58e3028554221aecc94ec","nonce":"a876ddf57ff5f054569f2e60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"ff99c0274eed89aa7012e8f7df0c21b5b531a8dc40a8a6a04ff15520b588d7fd2cc80fe728347e5ebde26d3293","nonce":"a876ddf57ff5f054569f2e61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"ca359fbb4c2ee8ce9e6d6520e8f862853baa3630498acdb845b0d98b4fde4784021656dd5b594bee565e235ef1","nonce":"a876ddf57ff5f054569f2e62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"14864675af2f5fccf4cf8944573e28de0411fdd8e5313b2fedc38d4ff1caa79d61fb42a57c33ccb7ff8710a4f9","nonce":"a876ddf57ff5f054569f2e63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"51fde38b9eec38dfc781db04728ac6446f591527bcf448e8fb041581140ccfda6ee33d755756f09997a15f7d95","nonce":"a876ddf57ff5f054569f2e5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"1b586e9c1a17e6e5f543c9c12af90753e8f7749d6dccbcbf357b87ac4f225c6c9be431c9bcee0444010823ad17","nonce":"a876ddf57ff5f054569f2e5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"b52b2b122b611e9eb8f17158f63ff5005f22726f48cd8ca4c246a07a1c762833100b23adb296f5522bc06bda2e","nonce":"a876ddf57ff5f054569f2e5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"f4a1974be3dcb7d9f94c6428fffdcec38fbc62194df3be20f580f0a3fc592c4ca17755bc65f5b2fd471f9e4419","nonce":"a876ddf57ff5f054569f2e5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"8f3665c4de8293e98d80d335e324ce206632c6a6fa2910ebd9ede7c5b2612c8415736e62407086c966aa38f3fe","nonce":"a876ddf57ff5f054569f2e58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"dfea0579e3122a700074328058733628a7381722351da6412481ac15558938f307bd4578e8ac58989daf543a29","nonce":"a876ddf57ff5f054569f2e59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"1dc77aa0c05a33b5675550554fc6f8ce327945437cc0ad06f6b10d1ebebb79f3faf4220e8032911f46c14226d9","nonce":"a876ddf57ff5f054569f2e5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"e2cccf8c6943357a1ce8bdd6ab777f18cf7e91b8750cff23328b1809466336561a89d3e9e71bc7475a2ec17f21","nonce":"a876ddf57ff5f054569f2e5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"c3f55e73e5a9531c9de715f4ae09b601cbef3dd67df46c004243e8fe45557a409ae1f85a9bcd0dbdb5afcd7887","nonce":"a876ddf57ff5f054569f2e54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"f2eedd0d639a6aa728121294b198bcc308dccae7508e41de7151fe0b4fac797bd16b6b87e47607567a16203581","nonce":"a876ddf57ff5f054569f2e55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"fbe84bb1f146bc4dff0abb4ae6d3638c7a5d9ccb47c97b32766e96f46e4a13f70777523b34c372c315066b0f80","nonce":"a876ddf57ff5f054569f2e56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"33fa9f08e0bc80fae1586b39077f91e95fbfdd815d5ddc764830b52faf76f30c30862d0f683a7e2a9d8e271f27","nonce":"a876ddf57ff5f054569f2e57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"2f0a42f13f3cc67582645c067d352f8981bdd0a1782f425ef9324012af05b758a6d7de7c929b330695b4e351b7","nonce":"a876ddf57ff5f054569f2e50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"213e6b0d3a717008c4c6141f725550cd16acd6300cd8ef8b612dcbdcae56ee525c50b01eebf0075b55403c6bc6","nonce":"a876ddf57ff5f054569f2e51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"20420865d55dfd28a6c651280800961e9ab40052bf823bb8929b78e76e7721800c410750b7fde2f34ba118f27a","nonce":"a876ddf57ff5f054569f2e52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"5f12421b7e49e67554b13c03bd7f610fdcda4d75c715ce3416cc9aac5b54bfec912efaeced93e4d90b1f818af8","nonce":"a876ddf57ff5f054569f2e53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"0b2d92e52aa81b128c07e38a7bb81f8961b28f08a84f464e8c547948b75a742d5497d45c6b98b5c65728f23c42","nonce":"a876ddf57ff5f054569f2e4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"254240b56205963af580a9be3e4cb0ee15d91764a0d902468249a23821263911fae68195f9e4ec506b3b51fc33","nonce":"a876ddf57ff5f054569f2e4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"6596aa7ef992f49fce36cac6c73794f7a7b98499300b7c1702c4b290cb839d6a52162715eac07c1c6c0caf2f0d","nonce":"a876ddf57ff5f054569f2e4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"0396c35198461d0cad82019eead4e566b0e9e1292ccd6b79d0c824f0443575226a38ac9843d325f4267a0bf8ad","nonce":"a876ddf57ff5f054569f2e4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"25c7b74bdef059efe40b032203837471e06979e914e09f6a0f657aa02f171cc8a1f44dd27115e500edb008416a","nonce":"a876ddf57ff5f054569f2e48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"b0aad287c10fe5940d48d9105a3a62c445d3a286c019de038a886fa95a624cd3d8d9a08106a69af7c76f8675db","nonce":"a876ddf57ff5f054569f2e49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"3ee978ed027b9da2dee3a8b32e045acb3dd6c6b9fb51f0b51c3bb3e1498f7db79640d5d0788c267ddac7b96fa2","nonce":"a876ddf57ff5f054569f2e4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"41216a91067de0ca0713e2b973dc65e4a2f76d0dcab21cce0d9a03229dec876e588f363a955f6f6e7e22e7e031","nonce":"a876ddf57ff5f054569f2e4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"24adeb7a9223f6207d1774fcefda6e282cb480b66dc56d91c6400247af25f66450d3d63a4fe7be255344598713","nonce":"a876ddf57ff5f054569f2e44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"7cef3ecca8f919865c5b59ee5904af3e0dd9fdfbdbb7718a9055762fc82b3142215e7864e9e058622bbd5b9b0d","nonce":"a876ddf57ff5f054569f2e45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"3c9a1185f891a2382d540866dfb9af642d9924a7df433b62dc51a09b70c09c7c8cff4a7f9161b95af24ab395c4","nonce":"a876ddf57ff5f054569f2e46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"8c46fcf75b64a2b3a1f0c1cb7a41d49a67ff96c622a93cafd076a8721677fc92ee22d4016a0a92a3a8363dd195","nonce":"a876ddf57ff5f054569f2e47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"4efd6dfacbbf75e66831983e6bccacbb890e5d82dc81a8598973238787f7282bbdc48586db5a5a3ab051129ac4","nonce":"a876ddf57ff5f054569f2e40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"5c9e1aa3529197eb51a58cbc02881acad0973840d5ff7310f601dfff1d40e3d73aef59c36b9603a0a6382fb8af","nonce":"a876ddf57ff5f054569f2e41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"b1fc68bf651ed587627a859049de6291ecb6de7eeaad126be4a6faf4e669ebeb3a2bc973453e6a9d74c62327ed","nonce":"a876ddf57ff5f054569f2e42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"dde11248d1246725e6d8fdf9b001f861b55aef73a33849bc35951e908d8d2c9006c457692add44e3b0cc084aa9","nonce":"a876ddf57ff5f054569f2e43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"7ba4cc7860a83ddb9a3441de1d54cfd8a08cdc80bef568060b47e29f92fcff0119b68fae3c007748362c6fc7e0","nonce":"a876ddf57ff5f054569f2fbc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"bf90f7621282e0fe9c58d86f7760fe1d25a33173588f9c45d326277b59c5071c"},{"exporter_context":"00","L":32,"exported_value":"ee2c21a137eaf77f22c893067249076ed7a85b36af64029d4763b3b80d20e6c6"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"ed239f2e8ce9fa18f4b53d17f1774a49b4e853a8389984f63f430b335ef285b2"}]},{"mode":3,"kem_id":33,"kdf_id":1,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"c1830fa07872158c311a7a62f62084eac204b1b2463759f16c85e58932f56bd8fce3710b4ebb4473e16766ded516431222c44a9a5375e301","ikmS":"f30b85c5cbd83d8443adbb077b946a469766983e9efb2b4cf63c9549e1b24ef2c8de291cdce2b15f8a4a2e62d41a9c458efe459df8169ff6","ikmE":"08875ff247809aa967bb3298f03feb02f275bdd9d71f0b2bd2fa291070b8813d72e79b8364fd73b84868279ea7b504b67f172525c28fbe7b","skRm":"2705f3a440ef2e9ded788a30670324a1b20d3ba547cc2b153586d508bf727f555df1bca663d3d69d7093be74d9a67a764253227e9881b8aa","skSm":"0174f9cca687802ba00ea4a84d64ec0343a1cf156633640fe393665705289b6841f761cc636666ca29348f27123993abdc1fb42e91493d84","skEm":"91ff7d7f7e97d1764640a5b56cc54c872fb5aae57a10430a928be7b4394b1182252a0e2d2c58e5fa7297d9eb36d10919de8e3e4322a9c06b","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"4238e429f17ee8f47abc750a7bc9f6b789e6a657b998477ef79f6e99b7e3c5387d1e78e2d03e4099ef157cc6808657b71f6a845a5d2eed31","pkSm":"d66e5149fb861a3bc9f5410f81e4d71319d8a5ee8f6bddc89d4c170721999ddee76946565c28d7933263ce1380a043195d12efd0c104f665","pkEm":"8d394a1907ac9c09ec8a388cd0806539134ebbb2db222126cfba5bcf1527cd775772af89510218918bb03cd486b8300a00eabe05e59902d9","enc":"8d394a1907ac9c09ec8a388cd0806539134ebbb2db222126cfba5bcf1527cd775772af89510218918bb03cd486b8300a00eabe05e59902d9","shared_secret":"268a61df0b392b04ee89d7c73605d7a218632fca525a09c6bbbcf52ac36d71cb56a2d8f9ba69777bfae538add03df5b34a1580c57179c91ac0243f92b571571e","key_schedule_context":"037d7450e446db15884bc2ae4ec24768fd9f2ee0af660c339d91d6a4d54834361239b47ef10fef9d74124a76b6079f61957d5b791d37ce9aa2fa2a910a7e47ca58","secret":"7d33b789e2d4835ee616f335c5e92b03b21c04b0b5cc20ab3cbc366ef4b84379","key":"bbe134bec693a27ea9052fe6aea80166a7e19c3e1312f66d4816596fcdec35f3","base_nonce":"18f031249c9421037cc7d01d","exporter_secret":"427603b77f29bcadc2b0921ecb6ac9f77face52081751011c20e45266932fdfa","encryptions":[{"aad":"436f756e742d30","ciphertext":"0028118c0c57f79b01f9de5fd32593966bc51a9150d266cc0c945bb5c0f42f9ef28d7f6f751285229f50718fbf","nonce":"18f031249c9421037cc7d01d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"da0a3c2d01e089d9b0a9cc42f9685177751e5b0f894c197c585a00d07456f361b4cda64815ed9c0c6728430fbd","nonce":"18f031249c9421037cc7d01c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"709d8c6abdedc79091f934097cd24893501b5d1658b85604633ed07443ddb75f895a4946a06cec32de9f8b47ad","nonce":"18f031249c9421037cc7d01f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"12afea9dc25e010bb5f49860e1d9c575589cc889a4c0a06a696a3b3b9b0dd89ee12a457089a4c7da92594c9da2","nonce":"18f031249c9421037cc7d01e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"c53b88506dc91a5cecb9c196668f5475ff9a7af0b6d0fb5a1806ff3af549b948a48feb2c10cac05c6911651d45","nonce":"18f031249c9421037cc7d019","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"e3e0295c7c4b4a46d50c0ce7f68a8846b4fa55935b982339ebee2ecbb5bab590fd6cde6aa87f6105d6be1dc9cf","nonce":"18f031249c9421037cc7d018","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"075b4a9f95844595edfe83a8d63d4f246f9d0288e0bd8e991b4315d9aa40b68be786260d1941d1d62fa000de56","nonce":"18f031249c9421037cc7d01b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"6ef1f80ed3ecfeaa8df9f4cbe995f50fafa884c347357166400e91e1edcf953a75b67de7240215d46015ae9d67","nonce":"18f031249c9421037cc7d01a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"f535d4cf463a49b9442a8752d1f22201fdf809626770a7d06e305bf8eadeb71933f6ecad4e5dcd9be3ce089dbb","nonce":"18f031249c9421037cc7d015","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"96b45308fffb2ef3f04a3cb10aef81a935bcac92cc4c0714d628d8e50ce522896746abf8431ea7e75ea9b69d50","nonce":"18f031249c9421037cc7d014","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"a884f2a11f9cc406337652fa86f985badeb296ca08a3c90777f15f1af6d523db27b32a44feff75c408962844a2","nonce":"18f031249c9421037cc7d017","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"17072b2bfac19fdd0e40304c113a8684a654f9724788f1c5cb3145b55816f642e10328f388a4b474b9ff6708b0","nonce":"18f031249c9421037cc7d016","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"b5e0403210da17f54625ba6d66695bf4e16d769a146f0683915467e8777a2970abf8390d4bc9b59111616e9056","nonce":"18f031249c9421037cc7d011","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"b6cfef1d21b2e7d06894c109e128afa6e10ad1ed88c4aeb23b8411187e612412a613a2c9c004ffb89b44ab532e","nonce":"18f031249c9421037cc7d010","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"5f2603e3c2173f340a40717488dd852b5702de9a3bf606d528c53f8adcc532989c459c42575226038fca464f38","nonce":"18f031249c9421037cc7d013","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"3f5027c733117c91cf073444f7ed923462232394cec6543c06872d3a34c1a61a90aecf27e0a3682731eb6eb193","nonce":"18f031249c9421037cc7d012","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"f642ffcab5582d443bebeca6743faac07bd2a7be25fa9e1cba883e368af00561b34328c1d5ff3dd43e6eb40ac4","nonce":"18f031249c9421037cc7d00d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"2d87b87188474b1177b1c65fa0ed761f6a2888f534c960cd8d2e8fe43f349142dedf89c0efadac7321cd9fe57c","nonce":"18f031249c9421037cc7d00c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"baf27f4421b0abf808db409334de71cc7a9cdd08082a3b3edd2f9cf99c1812de775857f7d5b6749f1dcbe92b11","nonce":"18f031249c9421037cc7d00f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"21383acdd0ce760f8a3b9e5910642d6204f0530f3a16146145d9bff6525c41255265f428a8a43c6270a0b6da56","nonce":"18f031249c9421037cc7d00e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"0f71c3e377380a25af0e83040f91e83e38cdc368c749be7bf7d0088c4d339b623842c6462272160aeb7cf46380","nonce":"18f031249c9421037cc7d009","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"d5206274bf0dbdcdb8e81d153f0a34df72981d83a3cd159d01c3b8a695b582417a6843b3757f498b1e406ac722","nonce":"18f031249c9421037cc7d008","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"321696af0ac29c16695123917af54fa66b68b2091c82e65ee170553bacda44ef711796ea431bb9b5982c040e05","nonce":"18f031249c9421037cc7d00b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"00fc037421a3d4bf446e4972c7662c5a711029bed579bcee71314afa925cf401a73f83bcba964f33710ffdde5d","nonce":"18f031249c9421037cc7d00a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"2364040544f8239144c69405629f55f0fe1d938949b9305ee79c63c481774dc6c7c1b0ba114c615e5b8aab6ab4","nonce":"18f031249c9421037cc7d005","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"76cf952dc65f12203b16cd6ca6310bfed0849d38989ff5f09df238ed2a96465011ad1aa32d88808405acd7f0aa","nonce":"18f031249c9421037cc7d004","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"d0e11beff572c42a69d39e4fcd8ec2ee6e800e71e0f237aa5cbb40cfed1cee5fc3bd576b2dbb51f1684e1a43a0","nonce":"18f031249c9421037cc7d007","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"b1b293611d5b2002d5fe950b9f3e34a7b3620760f48d593921666b115aef18ac9f4bd1ffb430d19b3179edf0de","nonce":"18f031249c9421037cc7d006","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"84ccc7eac8869a33e0a66dbcb4ef459b4e5ea8b504f10411a0d7881c5cdb5adf239dfc8def9a00986ee2484e7f","nonce":"18f031249c9421037cc7d001","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"7f8b8225e9adcb8e05670245417ae24ed4195fbf154df13f98fd4cba30fe7012a76ac3a0bc33b032584a44cad7","nonce":"18f031249c9421037cc7d000","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"9cb694d9d03021fa912ff103625ba2dfed625067981a62eb9a58b39f359109f13e327dac8bffeaf78149ecb10f","nonce":"18f031249c9421037cc7d003","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"bbea5004e41dafa4b9f52973f10ffe5429d2cdcf940a0aefd173bc61c99c690aaea0cb30287d0711a467d06b3b","nonce":"18f031249c9421037cc7d002","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"407d521a6266dc7b831a89858fba3d96d8ed781b805443eaa9497aa6bdd0ebef0c8cc83baec456c8be8a2495ff","nonce":"18f031249c9421037cc7d03d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"3847067316675faac586dedb98649b490b35f87c7491021d0ef9aedc8a50a9d019710127ba4d3326403cf80a6c","nonce":"18f031249c9421037cc7d03c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"85bf43560873cbdf6977a7e5c04452aaef198e07a59aabb993af030c29a868786f9bbe6d670da3b11691ddb3ed","nonce":"18f031249c9421037cc7d03f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"d70e34c050c60ea62deb72aa562f9d6c2ba7a74225aff54479cd334d74430ac23fba6af7e9fd5c450f297b1b7f","nonce":"18f031249c9421037cc7d03e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"9229c102fe9b0492f8381f5e89d089f191a9c2d2e0308a581aa74897ac691a1383286bf0ad03007e92c2bfa509","nonce":"18f031249c9421037cc7d039","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"a8719e1ebb0900762055af68ec311f25f52e7df0ab4dc0020689b1aa172d7b59e39e3423ddee02a59c0e54a57f","nonce":"18f031249c9421037cc7d038","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"3c66165af115e9b85d31bae0d83aac3e0916a4bc54905781b839a3955aa2d6ef82266a7c95cb2c29aa400da935","nonce":"18f031249c9421037cc7d03b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"1d750881a6d7c81e063a840c6ae25880b9103011b57d77c9dd7740016a7a4c0a29602e360fc05ecdf658f28c11","nonce":"18f031249c9421037cc7d03a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"11bd1052517a5085b32a0869d396407254110516d078f96c602e53f479fed9bd4fdf197bdf92e06a1c75eaf3e4","nonce":"18f031249c9421037cc7d035","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"8dad3686c3d99f9de32b7022737cb143cfd4e47bba05757e6b020aaaf1acc543cbcdc94621eb9ba6f3267275a6","nonce":"18f031249c9421037cc7d034","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"1dae94f770bbf5f0a0f1a5ee4e933fdf2a757a4f42bf0261360cc191fa984672b80885b27b89c86f33a21aa021","nonce":"18f031249c9421037cc7d037","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"079ed5242e82d9b24301bfd496aa782a3fbe4acf0775e47e4600d594a03592e937de54068c14fb8a498afcf7c7","nonce":"18f031249c9421037cc7d036","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"48c2f66536e5958824565265134cade49df113a35ce3bd578a313b237621e5fecb3e1dfda1b9ac8d50ce0e1ddf","nonce":"18f031249c9421037cc7d031","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"616de87bd36ea6d36c16cba0b362028a85ab18dce12f2f11fe651292f5149419d663e4591ff9ebe347a88ca486","nonce":"18f031249c9421037cc7d030","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"5d88c6c0b5cf300213fbf09932cb736faf71d8273be14a05372e5d9e1363fdfdb350f38f9e0fa7392562baf4ef","nonce":"18f031249c9421037cc7d033","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"fcee3383df2a58f2fdc1483383ef518ab78db524a3c88d393a94e180c1d25170c1b82bc5e1943f64b435034c10","nonce":"18f031249c9421037cc7d032","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"bde3e438733321c0f962794056709a596112ff9bee011bb37ad60ecdad5c52e8bdd68effb08cb700737968c2bb","nonce":"18f031249c9421037cc7d02d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"a4b1fbf05d4b628b3504a07bed404f0dcf748a17a2270c832cee344f65bae5624baa44b793019bfc113afacb5d","nonce":"18f031249c9421037cc7d02c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"d05d2ad8478d7c1079e4065ebafa41bf4d714e5f18f593f086aa3682b4baa0dac3ec9d4dc7cc7d6469cad0fd1a","nonce":"18f031249c9421037cc7d02f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"79340d9610f1465443b92e1152c745951d70b8082c5822aec77ef72cd7baa51ae39c8c51426e8aebebbcbba08f","nonce":"18f031249c9421037cc7d02e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"6e12be57db4ca29534c9579daaa92da2a8e08b9394b3511a4d07137e6d4a93f6d0afe887a6b7e15ead2d9d0328","nonce":"18f031249c9421037cc7d029","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"88ea92e816bf7629c25a623a36d03b1f9f9b5c89a2dc768b3b42d62539b1428c11fe7cd79e42f8c7828a5fe761","nonce":"18f031249c9421037cc7d028","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"ac2e6eb8e7b719eeefd997a131f2eea97384685e773178655e6404cf1315c6b9cdae5f1e16fd37d90f5f3d5e15","nonce":"18f031249c9421037cc7d02b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"6af00a58cdab62af19fbb546cb5b580b87a9696ba4ea9b4cfd27fcb6484a5d1f59f21a41f8aa182960c839957d","nonce":"18f031249c9421037cc7d02a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"5abdbb7d7487fa390871e01eb6002f742c10f7c042529bd41d9f3b68596e356cf0a6e1d7c6f0382f23d1b07897","nonce":"18f031249c9421037cc7d025","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"9ef7dbe6f9d9ebaaf2561aa4dce46408deedd597c7aa98cec578294e15e6fef79fc14489049deffc3071ead024","nonce":"18f031249c9421037cc7d024","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"6468217483ef4b786b539834c180941d9c7cab2a52242a80100d45a7e0108bd4e7efef057c3dd023ca1b5e8988","nonce":"18f031249c9421037cc7d027","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"99766192b66d7bfb646ce48ef783cf3baff4b8d0e1a36500e9fcf8ac3f0de48f64b345e8a7d69f9a926fd44a7c","nonce":"18f031249c9421037cc7d026","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"260287f51fd66786990bb5f8778b0fc9e72b67c05d40d43820b9c056300449cc64a3018af7278df4d8b32b609a","nonce":"18f031249c9421037cc7d021","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"9409f8017347fd3e6553509f2d9038c07372a97ebe5ff98fc71ab25dfc56c6d509557510fbaa4226fb74646c09","nonce":"18f031249c9421037cc7d020","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"2c2369d8ea43003e0d01835a5a49fef912444e307acde6c270ce3491ad849c44876d2fb07ac0d3ef61c6639cff","nonce":"18f031249c9421037cc7d023","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"50eb264418905d94ffeb47f4b078e2bbfdddc14580e1cc4e2524bc6e8bb0a71dc78dc9931c116b93ca5646890f","nonce":"18f031249c9421037cc7d022","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"a0b624cf8d4df0c1f6fef1ae3a5ecbd7faca72d744566cc027636132efd61cca76c1f57e42775017a8b5601178","nonce":"18f031249c9421037cc7d05d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"24075d24ab309861048b035602306c95d16d85861c19f9def90de04f4fa6494a1b7d7e52c5460dffc26c990272","nonce":"18f031249c9421037cc7d05c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"655e6fe6b2a898958244f49c3f46b3f2f83bddb261f655938c8b61bed0bb7af47eb374251c79b9714623014803","nonce":"18f031249c9421037cc7d05f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"d4420ac352dd366809258294a5af2b50bdd9c63940ca844ab1fd5375990f7c799deeeea93fb65e745e85993a20","nonce":"18f031249c9421037cc7d05e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"cd9645419c2ca43cb41a27c4d9d50a7e64e50b8643a1b463dded75872cacc0dbce363441bda42f718efbb0ea21","nonce":"18f031249c9421037cc7d059","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"d021525e0a03add7f6be5387f286db31be319ce7cf191e91bdc4c7feb1a2558bbb7aa8269e2adc0327c4d4b654","nonce":"18f031249c9421037cc7d058","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"ac2a7c2c0ab35c5a894f725815c4061f683e1c242c1b5e54db40e04a7be7417b676d5d0b1c5419874256234fca","nonce":"18f031249c9421037cc7d05b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"e8cf5a5a600e4b1ec9a406e4610b2fb3c62a4a70c4193c4706021b2af1a8172fd3b60d0d82470db82257f9ec5e","nonce":"18f031249c9421037cc7d05a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"e8015979853f93cd436bd9463bceb865cae6a2b46a76daa92a16228aea82d10a352fcb2f8c7630ab2e9d3a61b1","nonce":"18f031249c9421037cc7d055","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"be09080b11982d38ec58b2da9ce3eb5230a4152beeeb448b24330bc9b5b7db2c6ba975441ecb5d12542a9eea9d","nonce":"18f031249c9421037cc7d054","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"378825992e1051e4ff08bcc478ffd33bf6dab86584f422ac35ecab48ddd739c82bad0e222a8eeda48533f03edc","nonce":"18f031249c9421037cc7d057","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"26d3b1a7044d2c25a0eaddc9ea45780f73cf866cb73848d25dea49b75686d85b7a4842c18df4fbcbbff6a03e4c","nonce":"18f031249c9421037cc7d056","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"d36b42dae6253ea8cf90c1badfe31b786e41e75bdb7438a46bd847fd9ba07527023c4beef88e9a45c75b540610","nonce":"18f031249c9421037cc7d051","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"e92ad631f63e8ce56236d45cf08b178f5ac3a5f81cca13512cdd07a2ed49c2e12e6cd0294631a35c51e37e9d1e","nonce":"18f031249c9421037cc7d050","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"337dc0ccf2281d5846a27af0afab07378edfa621432b19e9208831cc99bead7ab529de420818b5dcd53d34f9ea","nonce":"18f031249c9421037cc7d053","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"55e5da9046979bff1123e1833a29a58e7d54398933a454747db085bd56f914a785002447b2b88aaf183ee344cb","nonce":"18f031249c9421037cc7d052","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"dbb3d8a39a762de3b60ecbdb5f13b906685d6d6f8216e07778ab1f2b297bf26e9745de22cc13689a7b20fa20a8","nonce":"18f031249c9421037cc7d04d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"0823820d3de52d9dadd02a163bd1eff985eff1d972ce93cc4c59bfeaa72598cc930046d2769fcea4f1217194da","nonce":"18f031249c9421037cc7d04c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"ca7125ce48da349aa146044caa8437d9c2b5d920f26bd9a1757aa9e117f43d3db71d4fa6ecb7e139890f89fd8f","nonce":"18f031249c9421037cc7d04f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"61937fdc8f2dfec975fd515973d7dd0f6e048fdf7bdb70ad22c3e60a5e7f9e01156dd0bfffee3e892fb196c672","nonce":"18f031249c9421037cc7d04e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"b9e2d85a883cbf9bb2396268c3dbfca9f4c6c047f65b5527a81d6aaf9e5d5d9ebe21718d9ef4b451a8f0a22a82","nonce":"18f031249c9421037cc7d049","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"be852746dfcfbac3edb4813c826b19a0c9d2618e0c7deb677a25e367942d05ef8280c6861a5174bd56dfa6d804","nonce":"18f031249c9421037cc7d048","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"5598bebf8d8bf82abdfe145778f24ff0876a7efa73670c75a098c990cefad558a9fa80a75f5fbd4779b5025010","nonce":"18f031249c9421037cc7d04b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"a8237349f20cb12233b4484d1a1a6cec82bdf13a59a7b356aacde1162b0ecdedb7564fe44fe50aeb758a9740d7","nonce":"18f031249c9421037cc7d04a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"93a56f795b8988e2e34ec25b72507956d4d5c7384bf927bf1ed92c5f32aeac42fb7772a49a121e3bc194183f75","nonce":"18f031249c9421037cc7d045","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"b6abeb238c809786f97c514c9975c1f7886e114f5e973a3744e543cf2a9642ae96a335803b9d2f912edf219ab1","nonce":"18f031249c9421037cc7d044","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"98784d4d6c0ea1a2458ffac01b5d674dd0e0cdda87fa2f9fd00979b64bab7b73407b5197e582e02a441720d265","nonce":"18f031249c9421037cc7d047","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"0553a2202998baf805367e275ae3e8d9095cb7e1902bf4dbf81ddd610e38196683383510e56a6aa28ba8331b91","nonce":"18f031249c9421037cc7d046","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"41acfc01796b0e202ebf718bee46501b4dd0f8bbc7c397377aec343fcb4948b8c15391fc129aa23f56a41cb90f","nonce":"18f031249c9421037cc7d041","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"e27b1eaf4f6fbf3407af034e88476d7bd252bf8e959343c5390458846b3461d9ae1fb98e776fb6ab29345a96d3","nonce":"18f031249c9421037cc7d040","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"46fd670bc904ddace4c15052f41fe01449c1d86d1e231fa0952cbb92026e2afa83440b31f7926e841fc7b0bc85","nonce":"18f031249c9421037cc7d043","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"099363c4b4273d5f12a04a39ad7f887c7f7cabded65e27e04864f54a032200c51f5b81bcc7d7dab4ad5739041a","nonce":"18f031249c9421037cc7d042","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"8131de273616dbfa9f3598c6e4105545fc7f858fde796e54c654154db50dd0ee61b647b6e489fe40303d157426","nonce":"18f031249c9421037cc7d07d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"9d04a58602602a4654a3bb45ad88cd88360e2a1471acd74ec0e1b3a159742dd8cd9cd271d1f4f3df40416bcb87","nonce":"18f031249c9421037cc7d07c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"894182e9ee4c013a049f357ff29577727791e6b166907f2704d714fb10655957068a979ae138b68fc5791ce1a0","nonce":"18f031249c9421037cc7d07f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"68544b5f7435660afae022722618a751fa8fe6e4efb9649e6c5453d1e6321b46881da74f4e197ba90e5eaf4248","nonce":"18f031249c9421037cc7d07e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"ad636200c28ab152883ebdb8cc75e5eb8c0b6d0928a007335e276fa1bfa76ebc1e9fc4b86f61da60cb9395ed5a","nonce":"18f031249c9421037cc7d079","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"16bc5c74f5b85387724a958f80658bb7527048fec9c3858e42a41799e83e78ce7cccce6fff68f9c9317ac3cb31","nonce":"18f031249c9421037cc7d078","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"cdb874b1b9f70f17d3e635023ef0e588ab0fa33bd7d3ef8a05dd2f518e144bfdc2f152026e1abef7dd88b2ae96","nonce":"18f031249c9421037cc7d07b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"8df274ca66dbbaecb1bb669b2ec4d8f8721054a2540f2caf6a03a59e920b9d528b4d7a1683b24e92692013c9c3","nonce":"18f031249c9421037cc7d07a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"91bd44d67d61ff30243726003447512125b855990cdb2b0db5107adf119adba266f86387bd8130fa1af0c083df","nonce":"18f031249c9421037cc7d075","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"d25f50704143bbfe90828a748da62058775a366ba0625f55017b535aed44ec6e44239baa5a78e0d40fd48dcfcf","nonce":"18f031249c9421037cc7d074","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"17cefa5ca586aed15c00136d17a243a3be9d87927c44f9b4b2696c85ba0640d031362ac3de4da2e16e5014cabc","nonce":"18f031249c9421037cc7d077","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"7ed3ab8d59c313ffffda9213477d96585e95731416fef519140d849dfd5e2501aa3f6945e83abf3c7c28a00845","nonce":"18f031249c9421037cc7d076","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"0026038f09e60533b094562c5a529429d1144e0f91f7b93b913d15c744cd705ed808d93c906d66aa7524636a85","nonce":"18f031249c9421037cc7d071","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"22ad3b4e6a435ca232c9eea5188c698c035f1d5c20e399967c8b9b8797414ef537d2811be5e2da6dc6f37bdb96","nonce":"18f031249c9421037cc7d070","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"8a0eea4009750d14cbe3a4e8ab416cd522250b1b207871e8d8ca01f2841d80d2692a34d729a361d0cf2f2edd8b","nonce":"18f031249c9421037cc7d073","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"c31ffd2446afebaa8167be51cf574d94bfbe118edd25bb2c222c32e36f7744e0e8a73c36c2fa5dd5e04a3e850d","nonce":"18f031249c9421037cc7d072","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"3fd2fdc0b112b5cca92863a8f188f9ad134e4084088da35030411125e82a17ef171c39867c0ad7e3ac7b5d6d35","nonce":"18f031249c9421037cc7d06d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"4003acfe657c51457c53fae246a37822eb20ac3376ec0bfd933d6640f05e9f21e83fe392b6733100b3671c104c","nonce":"18f031249c9421037cc7d06c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"6bf45a4f894fb763e6569d49e6bdf794a54d6e68ecb6757ad688ffe30e8d309ae7cb7ff7a157cfac9c56013457","nonce":"18f031249c9421037cc7d06f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"57bf7e70becdce106443764fb2e3362b39501e4379aa6fdd62df21ce8ae5cdfe9db2418ee6f90282c97f806f4f","nonce":"18f031249c9421037cc7d06e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"9045a6642d7c2002cf742f7fe4664d81fc210e3b46689bb3854d77240e1883bcdf0f7385e7fb2275daa33c2c05","nonce":"18f031249c9421037cc7d069","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"9229c60e58fbe3a3ce643c130437cd966daf2d94e697051fd3cf904760e138561f56a063e258227c1d0ff039f4","nonce":"18f031249c9421037cc7d068","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"1c41540230ee708715ff52a67ec3d1bead697f739a785b0406eeaf3985641c02a4fc97c1e6ea00a7696d9faf7e","nonce":"18f031249c9421037cc7d06b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"892d67168f04d08782919575981c3483b42eed52ed7acd61b13508f88d7f0f1a6ba654ac9b9c462c8237327588","nonce":"18f031249c9421037cc7d06a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"fe83d1767ce9a27b4383832b968d5632a77140306413198e0cb82e8b37250741e04dacea5034248d8f0f5132c9","nonce":"18f031249c9421037cc7d065","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"967c1516ced254c4576f283104c1908357f9e316c676e782ed8883bb04e656c5449de4f8f600ea244092752323","nonce":"18f031249c9421037cc7d064","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"b3ab42ca6afe458aeb7703e7622aded92f918bc2c1e9c1190500a0633c860a76953d4516c19e69c348873e20aa","nonce":"18f031249c9421037cc7d067","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"41619d343f4648a4117eff231ec66dd9688d4adce6c0ce87eb11a7074ae57e948322d3a7c8a0f92afc9096f515","nonce":"18f031249c9421037cc7d066","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"49599e4069a731dabfbf26235dda2441633b8f3d3e8b07cebede547dbfdf96e922900f0fd904131878f504efbb","nonce":"18f031249c9421037cc7d061","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"3d12354829c98676c7cb99eefc31fd16c745d560bc33ce7ef0e49d56d00fd5d9b17088f346a5cb9b0f8ff07308","nonce":"18f031249c9421037cc7d060","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"89b354f9f5cfc599cc3adc3e101b40bdc292ae820370a65c0d3d6732d660bb4d8720bfd28ce8e03e0c1d1d7082","nonce":"18f031249c9421037cc7d063","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"1cf4f4f2bd16d73379a7bee50d891b7a0cb6b89adb72491f29f4081d75a3eee83e5a8c5a48f0f595b6f18c93e6","nonce":"18f031249c9421037cc7d062","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"bc21fa5fe4648221b34dcb30348190669829ecbc1a2f99e63cf160eb3d93559b16f03403b5048023f857b6b704","nonce":"18f031249c9421037cc7d09d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"2797f69ceba034f911b1559f5c41b976d123399eadfa073ec8d2bb9d5fc31ecdccee031c64262c72018a48557c","nonce":"18f031249c9421037cc7d09c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"a1bf1281fad9d2edea35c0df812113020b9c8d8b9cd643088fb3c10c3f4d5820f4b544952d0d916096337b45ee","nonce":"18f031249c9421037cc7d09f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"00bc720aa1ae926451363e1e117981e8686ef179cd00eeb786c42184336bfbc3b3aad22467be38f1357d0afc6a","nonce":"18f031249c9421037cc7d09e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"1b1f4af652c71333f20f806fd6cf31777a73a1bb95f1abfc90aeecbd1ef19f77a311b92a4099cffe69f30a0b83","nonce":"18f031249c9421037cc7d099","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"61de320db7517760aecc5a16f7e2016fd4031a482850131fbcf726aa2d8dad93fc588dd83863bcf967ff7d01af","nonce":"18f031249c9421037cc7d098","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"039f290b18c84a946a98aceea8a5db0f00613610a908b73b02036b279fbfebb196e8aa42265ff6e113c61d4c9c","nonce":"18f031249c9421037cc7d09b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"0f66bd25c05c28b5ae9fff7551c1a0110811f200efb33402c9d6a7f01de410702536dc25ff78db52130ea8b84b","nonce":"18f031249c9421037cc7d09a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"fd30863cb31c271debde89a441833c7d6ff83094f8f41c8879299e2916aaf5f1568bfc76e34c2451ca69c820ad","nonce":"18f031249c9421037cc7d095","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"9cb91ac28787352eacf79f005737919172b6eabb0fddbcc962ef247de78d38496c10d87a7fa4e4e55470015255","nonce":"18f031249c9421037cc7d094","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"52869fa909b388c462dfb6a1fea7633c0854f6da7265e10b2a08c3dcd7e1921ffffdc4ce37d9ef62d29fdece9f","nonce":"18f031249c9421037cc7d097","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"edfcb6acf41ddba33d0bdce808123fe0ccd39ba8ffb36e186773297d61ab814b9f9857a37787810503fceebfb7","nonce":"18f031249c9421037cc7d096","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"d06e6a64b6d729b8a1521590a082cfcd84c69b405b3895de0f78a8d6d14a5468d1bb3526c3d2c03d19f38dc423","nonce":"18f031249c9421037cc7d091","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"3f4c5d6bbac30c9183b95f9b1c03b40a3e54b296a4dd3ddb78fbda4d0b2aeca03ceb4ed7068f652f4d3d96a089","nonce":"18f031249c9421037cc7d090","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"e31771820c68f43b5125fc96c8db7d0ef008c9b727e2f90addad9058e1e16f5cdbaaa1917a2ee6526115fb7572","nonce":"18f031249c9421037cc7d093","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"9192f841a7e460c4523c557afbd5c0ce2c4ef89a79ede8f2acf7a2cc548375ba00daf3a6065de19f55b477d771","nonce":"18f031249c9421037cc7d092","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"4e62294c90a648551f42a51943bd59a550d96156819b8542c241f23c0a9511de8471977cf46437ce387e7a5e7e","nonce":"18f031249c9421037cc7d08d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"898a879c0bb1a1a4aa27d7de7353658dd95bbef8f6dceefb89cfa34cb7c94004cbd3a0401c92e01a9ced88fed1","nonce":"18f031249c9421037cc7d08c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"47c24a470c9151a20d703e720c3043fc8d993952dd4827c3329a424ad1c5124f8b19c5bcb73ee01340b316144c","nonce":"18f031249c9421037cc7d08f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"6bf1df8516c906746b940870089def926b212da1cea333048db79e5d3cb7978fb91fdadda3094285bd01bf3449","nonce":"18f031249c9421037cc7d08e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"95bd38ba02ad8f4ce5fc2313e6afb7904ba6af07d765114111a42270c5b4f575c3cc7022f7816d5095cefd4cc9","nonce":"18f031249c9421037cc7d089","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"bc90b3f864fdbe33ab103d09e8af056a374c49d320dec7401a950d619323d0292649870de679b45aeb0102d5e0","nonce":"18f031249c9421037cc7d088","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"e66e74e0e28644f795d9ed5b8907f01cb056c0fa0d94fb229339dbdd886fd3f91c3ee89a7dfefaadff711baa4b","nonce":"18f031249c9421037cc7d08b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"51e6ab5e7349336beeb60fb3a0034a31073b72f092cabb3571f2d024d2918079a08c98134da5e337d6ebd829a1","nonce":"18f031249c9421037cc7d08a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"67f99eea9f63727b2fdecb0061b8b4e96660e6c93b45c8772ad71ada2a234c4db1b181dec83bba3d9e36029ebd","nonce":"18f031249c9421037cc7d085","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"2a0f443a6e44fb856da6ad6a043a4818f45f4ffcd63850614cecf2a68924e122dab46b4db3b8b4dec96cb56de1","nonce":"18f031249c9421037cc7d084","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"6f0d2d12481b99582c4db2b45d57eb835c43444fa59d73a91f74691e2309c30285ba5e3e21a72d33914f1f403e","nonce":"18f031249c9421037cc7d087","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"a2723afbf92f9ea4258774dafeb85767755cf475de913260614618987e7fb24147c8206666c2135d701e8fdbdb","nonce":"18f031249c9421037cc7d086","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"17869e5d0c1754143bc6816c428357f4ac1f25816fe4fce988b245d7bd2c63f1457098426e7999f30c6d72d587","nonce":"18f031249c9421037cc7d081","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"41b8388072099c4ebb021796d0b262184ce523afa10def5111a71488e53cff396261c79751a19919d85b8ed0e5","nonce":"18f031249c9421037cc7d080","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"6cda35ee5b72dc4ad5cf2258a223a6d5be65295f2df0338e7e557affd3e981b3758222826be71a858e4138a960","nonce":"18f031249c9421037cc7d083","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"f025704c0803707c5b183a0caa8f057821dd67465989afb46daf89053e70e7e2271dc68eb73ffd207ec70fbb31","nonce":"18f031249c9421037cc7d082","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"0ef35f50a05b9f4fa76b85fac96f9cfd22bb90d57db98e97b10967bbc9dff2388f694a7b1893d91df5d04bf5b8","nonce":"18f031249c9421037cc7d0bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"abf6e7d0d742c86dd479757813eedc5b63e5d74baae2b20e9362e43c0dcd203cb4b58abd56a3bf3f521c339ec6","nonce":"18f031249c9421037cc7d0bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"5fb62dfcc8430e9f6654d3188c81db068aef41561384422d79ffe0c6b572cebdc8b2d374b3a430a2e289c18275","nonce":"18f031249c9421037cc7d0bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"f091504531be9d00b916323aeea764034b755cefc53abe422a859e8f6488f2bcfd23b1d6a7087f1c21800934d6","nonce":"18f031249c9421037cc7d0be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"bc6147d2c4274b0e506ea53dc1a57ac79f38df686a34b5ac3df4489042c383fac05b403db36e4c34e7bda61d78","nonce":"18f031249c9421037cc7d0b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"9a46f74dc8a60ad008745c6cbf542f5b32665c4bf7b52fe931b95f22dcdf360492303c7723511b572bdfb72a50","nonce":"18f031249c9421037cc7d0b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"b252cd4f1ccf88e9fa47281e84e6d4391754db021b400214469a4312d05e5a16e69435f888d4f273dbf7615387","nonce":"18f031249c9421037cc7d0bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"dedca0e9f93eac2707ac12dde992e9bf1f3a0203568392a5402f73d1bcf0161533d5e9e9a3b9d214934df1bc70","nonce":"18f031249c9421037cc7d0ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"a2544de66a6243f84c4bfdc04fe2a07a8cea46bb6bb4daaa16d301b252f418471c7477d208f0d84dd2d4850fa7","nonce":"18f031249c9421037cc7d0b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"bcf5be5756ef2c39027d8ac7d16aae7a40817a5bdcc73205d4a4545bae07b2a6fd2580d37f8f88d572714e40d7","nonce":"18f031249c9421037cc7d0b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"25dc8b2c86d137cdd470259dd624354454e0799a1f9ff3d28676fa48cf3be8240733170a72a5f90d1c9f9d2ca8","nonce":"18f031249c9421037cc7d0b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"4e8e2da76d3a5b4f8fa41c26d815faa8d0ceedcbff1b3831d492a5466952367fb6a13f9a0625e7cb3431be5521","nonce":"18f031249c9421037cc7d0b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"e63b9a4f9c09a7c331ccaf44490d5508cec736387ce5e7292e7a286153e8e80f18033db33eae6aa0a674a1e064","nonce":"18f031249c9421037cc7d0b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"89e8f2cf2f3cd0eaedd255d8129c5f60f968410af997992a0841a95633a2a1984bf7e068ab9dd178d409a3d496","nonce":"18f031249c9421037cc7d0b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"6dacfd36205a2f0b45af14c93bb3ef9ad07280c18bb62b481794604b0692931e022520d06db8d1c9dc63073dd3","nonce":"18f031249c9421037cc7d0b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"b8cae529f6d574facc3f17e1ba163428e294c57a148fc5d3f74442275629d6b161483a10c8bb661ee2e7da2131","nonce":"18f031249c9421037cc7d0b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"6985ac075bfae6d238eaffd79a6cd7dc2fed5f1ebf120983f79b9e9cf020bdb20f6e03b987217eba123fc9793d","nonce":"18f031249c9421037cc7d0ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"d0963aa0dfad553e72bd453114734f80a5f2b96e525ec9f5997ff4609bfcbb8158f9b5ebd4c4e90beb20d5f6c5","nonce":"18f031249c9421037cc7d0ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"4919a58b009be1cdab782397f8cb831d369394c5c5d451c0b6c4f7c5bc05584aa0041c3aa3fadf81a80b052be0","nonce":"18f031249c9421037cc7d0af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"6794fd68de0366859b652cccc9f1ce0ffdccbcdd20bc1f38617f17de1eee80d8d44449af4cb6f7e0ae4871dae7","nonce":"18f031249c9421037cc7d0ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"f0ca7e5ca8bee8edf9c4b02723bc39adf023d922b20f9958f3528504d3d18c886e8ae4c649da2e4d578b09129a","nonce":"18f031249c9421037cc7d0a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"4b2f55f33bf172739b953bd8bec346e2e2db8723e249f7ebd0ef757ca02d543e28c952cd34c43b8210d1f7540f","nonce":"18f031249c9421037cc7d0a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"4f4f1ddd9d4a40dee49a8d16a9bfed63e3ff01ea6e919fe0629485f9c6895a30601b2e45e672b18c62d20d4b3a","nonce":"18f031249c9421037cc7d0ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"dcd886b9b1c5eaa72ee0706e578e8f685893a29f923e090d397259d3b537cb2c37abf74cef95d5455dd8be7a95","nonce":"18f031249c9421037cc7d0aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"29c463ef0637b062148bad92991ba63ce0776fc23a61101ee4bc359070ff612057182b4879774e3e372951cfa6","nonce":"18f031249c9421037cc7d0a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"0d02ccf03d39ccc60d3a1d38114f9782627b9929eb3f575e991b81fb812fa30f9d9acba80188e2c91c0889f1a5","nonce":"18f031249c9421037cc7d0a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"a351a6b8965e4ffca6da9d12c8ef112d603e5ab6cba86a32351f3e7eeacff361d86ecdc9764d12951a9f843926","nonce":"18f031249c9421037cc7d0a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"e13419898ae8e36e162a727dd2e8bc3e8a49bbbcebd1a2f0b2ba62479068dd0eb29d532024d3a090520e2bd254","nonce":"18f031249c9421037cc7d0a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"c2896dbb3b2357b8f8fc068cde0d4c035b7fb3e1ceb85174bfc89234288529f633a44153b77eee390702b3f4eb","nonce":"18f031249c9421037cc7d0a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"6e225e69eac0c085cc42f4ff108f17161242d5533bc57eef873831a149a8b5d4c24ae260ad79a143b32dc56b89","nonce":"18f031249c9421037cc7d0a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"094cc142898c0d4681cbcbf454bdf8badd3140b79453931d6bd3865fb87c385b77bdfa5f888da7c22a331e4aec","nonce":"18f031249c9421037cc7d0a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"4b2f4cdeb71b17b6a607df2437c0ab2797b9254cefae6f27130afa3a5ec5dbe95c2805062832f2d4014d513fe6","nonce":"18f031249c9421037cc7d0a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"e77aa9ae29eef77167148dbc8915857aa6b78e84e63836c814a9b7c344f68b0d6f3d083eef54fee3405737b596","nonce":"18f031249c9421037cc7d0dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"04cf2721becf61a6da3986499ae055744a979a44c3525368991c013c9cbfcc74dd004b75e5d6881afa42d68c66","nonce":"18f031249c9421037cc7d0dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"31f66da0c1bd07ea4725d58fd3f24d5247c655177cbb4c9a2c9634f222e72d378393ffb3be6b2775efd598a312","nonce":"18f031249c9421037cc7d0df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"3c9dadc55c9c388e0cd9e7c06db625bcf331cc4082db134d4354c965d700f6c5dc7d318adf3e9580c92a3b14dc","nonce":"18f031249c9421037cc7d0de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"728922de111b6e205df970ec44e1f2797a7601964f221607e465829decee4924c6b113550af6c28d3d73d759c3","nonce":"18f031249c9421037cc7d0d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"27fa7c45643617e80b7d5bf60f78b02b25317576db9bf9bebfb6abb0343e1dd6595daf52ea380ea895774c9552","nonce":"18f031249c9421037cc7d0d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"7dc4099dea970b259885867b088bed6034b2d77032b5753d088db0efb94fab6e7a0873edaac72cf71b02b5632d","nonce":"18f031249c9421037cc7d0db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"d1a7318b4667bfb6554d7210b8435d56a9a7e3aa11c2693462ff9c90a3e4a85839a009d4d1ff486c71d90b27d3","nonce":"18f031249c9421037cc7d0da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"2ec23e52c8cf62549fc0f1910b1a4a5b5eca3472763fde17fb44aebe5bb1558ef3024796baad973025365b2146","nonce":"18f031249c9421037cc7d0d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"886834bca456b3c9b64455e3d2d91da174cc38d20f7edb9a26d939c7c851dcaab346b291853bdc71da904cb394","nonce":"18f031249c9421037cc7d0d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"8a70803d42586e8961d3f251f00a97deef1fb6fad429c4a55541e5342178bc9ef9531816c4a86d1669e468aac0","nonce":"18f031249c9421037cc7d0d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"e61f11115201d56afffb5853c56a1bc3cc211d66724b6f5a774feaddf0660b540be980e78d431daa8be7643e72","nonce":"18f031249c9421037cc7d0d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"9a1bb865b2f093336cf4b3ddc5cc6037cf246eb55cfe01662f28aaf2e2a8c0923f0b0da2d63a422eb99de871a0","nonce":"18f031249c9421037cc7d0d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"1991fe3f6e66e6d45c84364ceb1822e971b91c93d6e55e52bb5a5afeed1638ccc383e5e237ecfe9205aa344832","nonce":"18f031249c9421037cc7d0d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"47b7b69aed6ea0855fec7d8c5bf0c003adbcacc6249ed471811ad021910801f482e8e262cdd62d6da20457bb79","nonce":"18f031249c9421037cc7d0d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"c80a67c3f6e3813b1a79c845c6a732a74c7893241da8f1e8683aac3cfbde7a60de7fddcef5d89750a6a9db2494","nonce":"18f031249c9421037cc7d0d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"323e8e10fdea9395206f2406fbb0fcfa6a51f315a82f2e0b1d2dc9778d4750da840051122e67c99216b697ba96","nonce":"18f031249c9421037cc7d0cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"73ef184d8ce6ca2a1c4e4e4b3d6c105246a25482d0bab48f5944551374062a94d27f7d3b7424572ea11c6b23c6","nonce":"18f031249c9421037cc7d0cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"d8e5a5f98fa6b3efe330bb879420080e21574f69b989f54ab6328763037b5d39794a3e0bd2f9624a981e99e3ac","nonce":"18f031249c9421037cc7d0cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"5b098f0c24cf61666033f4a188f2a18b6d5abc303edf5c7fceac1d87d0912676c612e486c99e0002f6ec154b14","nonce":"18f031249c9421037cc7d0ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"000c43211bb1124b1c5bf738d4dbe72d3a9cc5674a324a7bfa44dad382f75a992563d2b3a293dc5f24a1fd9094","nonce":"18f031249c9421037cc7d0c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"65c92257e386d8c8b7b53f0d98a86aa200293bd3ab26557e79b3db89d1b14e26634709478aa1a93db375ab644c","nonce":"18f031249c9421037cc7d0c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"d22b51e48d9c06771eb2918960be42c1e0d5ed2cfb9e5bc45d7c5c2a3fcd6cd2dbcb982aba65f54375cfe18750","nonce":"18f031249c9421037cc7d0cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"2489cc6ac50552c72feacb2cc0e886340523dae10afd63e36518dce62a03d44d96519430ba32bd64d25c55e1ea","nonce":"18f031249c9421037cc7d0ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"2b78d4497f0036ee901d36dd2f87ea01f782815e0fc836f5603cdc692563dc2b161474a6ae2f413ed823384e68","nonce":"18f031249c9421037cc7d0c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"bab4d7ae0e7e999310e2a3f1fde87bf7dab6d53e170c68ca816523e847c38c90873eac2ccaba41e0bb9a399a21","nonce":"18f031249c9421037cc7d0c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"291143230d10a8ba3effa927d505baba3986b24e3f14fbe8d53b00fc06d3ee07d119e3002adca33aed62bd7956","nonce":"18f031249c9421037cc7d0c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"3a70e24c6f62581bde9ae4e02753a55356c80dafceba9801573bdbb0a9efdae65f3f77a232c36170e620997ad5","nonce":"18f031249c9421037cc7d0c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"7e2e6276b2f0b4171443bfe01368b9ec33d926c33803ef55d1c60e232801f9fc5033ade9863f9259e452caa384","nonce":"18f031249c9421037cc7d0c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"2e19d99eee985aa1eacdc15d647cbc90b1e00743209f222cf37d05a462687327512220ae0830b81b01504bbd6c","nonce":"18f031249c9421037cc7d0c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"05c35b7b46fc7cdfef6579ba5089836ef212bfb486bfd48ede9d3b52dc96bd2beba190fde3c663f6863c43f1e6","nonce":"18f031249c9421037cc7d0c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"69db4fa5587be30fb12b891f9fa438775fd5860a61d78d64608dfec8ec75892426157d267727949874da984618","nonce":"18f031249c9421037cc7d0c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"33c190b134c72d5c1f6e9828bdfaee9d3064403d29b16779fe69cde3d896ed946fbd6d117956b53f24d299b3c6","nonce":"18f031249c9421037cc7d0fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"a1ec4654c21f438dfdcdca2979fcb414dc12569b9d7f868be824c2547ee01a78ac4abf6816b2bcb4e2ce15926f","nonce":"18f031249c9421037cc7d0fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"f71ce69f2a81ef76e102051ccb44372313c31d945342e072b85939e1b435b2272d2f1e3d18b6ee0be210ece1f6","nonce":"18f031249c9421037cc7d0ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"65ef598f373d9f4a2ba2954f750b0799202ebd905b48969cccf85b8856d1052070c9d10f964fbcf2056ad0c2e7","nonce":"18f031249c9421037cc7d0fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"7ab6187b565149345b38596cbae662e9a2241f655fa55cbc025fa945690a3159859ba3e50623f378b033066d34","nonce":"18f031249c9421037cc7d0f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"1f16e3582b69fd171eeb8f7b258ff538c2597aeecdf7363229953a1a58a95766fe69931f004fc4a111d529fbe5","nonce":"18f031249c9421037cc7d0f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"3927949df770d3aa405eb1ddea0004f295270082c366c4647075d9c82c4116bd5536067262051169c20e9b8e94","nonce":"18f031249c9421037cc7d0fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"3ebde5300d8308513b2801f18c46ce57f436568ccb3fed0ab8e3ea390c60c47254c3b3bb5db90f52b7d99bd81f","nonce":"18f031249c9421037cc7d0fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"4db24123ade25f6053f81d9addff1217b4510ff6b84084015ff6a472fc0a6fc7bd816eb04759f570823afba31b","nonce":"18f031249c9421037cc7d0f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"9272dc90a8eb2d46e02f4b4c809b4b184d5b156c2b6db8a4e1bbbc4be09d9998f45777e7d14ba1cab7dfac4df1","nonce":"18f031249c9421037cc7d0f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"3aedf021a387ae8ef82f43360887a6f987baffdc0546a889617b0a17beb31dfb2f014cee2282a47dcc2ad6e46f","nonce":"18f031249c9421037cc7d0f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"e5347e7dbbae46f0341a4587e1dc5421ebfd50a9ad086eb5ebea7e9eb758a8895d0e2859ac8b51209fdf92fb22","nonce":"18f031249c9421037cc7d0f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"fd139d128962f6a2753870915ec59f34242ea13396f0bcbbaf499c67f9ff32b102a7ad586dc57f099776899a3f","nonce":"18f031249c9421037cc7d0f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"7d1856e694836dd3a790a09fc9ad416b7b80eac75278aff2506ee39616736e220e39703978ff2c3e9d9d43d675","nonce":"18f031249c9421037cc7d0f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"e022de5b35878fe4ca2bb3ffb24ed54fcf167965ed47122617e35bd617367e22fed4b5aafa54d148a488bec10e","nonce":"18f031249c9421037cc7d0f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"885f837b0d7b0f2602bfb1a9b8a089756806ca06b54c2a1901e0fd9af86032b10da6948670cc0c1f107c65ade6","nonce":"18f031249c9421037cc7d0f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"13111a6e9919c511da2791b0d294a48838b77295db3fe4b8a60b7c15abcfd47a3c6aea313c620cf325e9c82e70","nonce":"18f031249c9421037cc7d0ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"276d7eac7143abe496c21c019da9a493d1c16beddd4d763ebb44af35e6062e9e166d7026049dcac18fd8f8e3a9","nonce":"18f031249c9421037cc7d0ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"7c4676d3d0e7f68ad76bb890b878ac45f77d179a6b42fc2977799dbd467f7e4faf288f3ab4f79ff01185f06467","nonce":"18f031249c9421037cc7d0ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"50a54e4da853b26fa7c29081328ec10ba2f5a333852e5b1a78e106523fd9bd62d16b8530a69a89f47b1f6f1a4f","nonce":"18f031249c9421037cc7d0ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"f85e0e2f7eae0954c51ed41bf3de2c4e3d113c1c324041b64ae5ebd706c3c8391982fa6150f1adeb0227f419e7","nonce":"18f031249c9421037cc7d0e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"30f04d3a1f0e130993d6263609edfc51c870fe734c3c0fa42862f74ed4e7267f6c78ec1176c97497e5b2f1951a","nonce":"18f031249c9421037cc7d0e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"5f8e8c1d3e8a350e52dcd891730a1b2cc3f1d4ec8bb1bd9691abef55f7878790cee45e79e947d8367cd5ee31e3","nonce":"18f031249c9421037cc7d0eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"5a0c8a3d8a041b24544c37c65f1e4758d90117ac3d8d76c137e4528efe7e50267ce400bd0f34cd97be982fe996","nonce":"18f031249c9421037cc7d0ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"eea60d87e588e0513c85c8fbc28d7ea8f58c3b75680131718131e3576333a9c930a0cd48a35f2cb5320142c88b","nonce":"18f031249c9421037cc7d0e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"77f2b755c1c47ab6339b9cc77557613d717dabbeb96571e7fa4776c52463cc0a04f721bb1d53d19037c289ba1e","nonce":"18f031249c9421037cc7d0e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"05016c8b016cc8ddad633fea97aa9be0f30501beb1a5d7df4151223f1b93b2bd9a7a6a5bcbffefa954327b3734","nonce":"18f031249c9421037cc7d0e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"7f4e3e5e74ce57d4d4a8ad7945db769e24e63308f3fa59e4c281d862719a6f861fcdbc9b42bba7a6e1d24d043e","nonce":"18f031249c9421037cc7d0e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"5ddfe66ac99b5d3631968628f6a3f6e726397bbc357b4cffdbd408a55aba2c7be9a977e59a1b5725618dd7f73a","nonce":"18f031249c9421037cc7d0e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"33a8cfad9d5adf296a8c6986ed34e87e8624286e254625b049b2d814fe16ff13b137b3105324d8a6653cb2bd1b","nonce":"18f031249c9421037cc7d0e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"456fac9dec428cc5e2b83da58f3f53206de80f3666b0731784c41684120307c36de27e7e54e75474b1f5697cee","nonce":"18f031249c9421037cc7d0e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"b93454e20db4e20d60134691c6bf2fd7436eb93eb333d378e20d11ec28cb9d8d26f215f2f5331690f2006736b4","nonce":"18f031249c9421037cc7d0e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"d503845d1f7fe13434209bbdd005ccf8f956cd4c1123ccc5f36d12f2eb888bf7a3c16d9c8ac09e2ad2d67791c5","nonce":"18f031249c9421037cc7d11d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"6104c00a5ad91e5655f4b707e461dbed209eea4ee91a746713590598a29efab6"},{"exporter_context":"00","L":32,"exported_value":"02fd9f43c225c4fd76758b025db1ee3c32087b673b99cce8f2dfba24c999ee86"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"5510269d93e0563937ed6d16cfc04cf649b1b1db32e189d06abdcd0f723c88a9"}]},{"mode":0,"kem_id":33,"kdf_id":1,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"0e0840ac09fe5473d33f1edfdf7a7442e62a7d62731ee1ca62d36982059a7e8214ef77fea658699feb40852b5d4698c63d1118597d7c7ec3","ikmE":"a4417dc985649576c142c230d32273550ff25c4f4a0c1bbd504f8eb9f4c56ffff43f1b5227be5d88fd58010b58ac71be80ecdbcbdeafdc1d","skRm":"9467dfbe2113c1f5f5d81eb6fc614a37f2386b60c09248a4e8ecc429e3fce73a46c560f35e75aaae96d82475bc64f81ebb33322f08ee54f1","skEm":"3933b6649c9c2d07d857ef1bd4ac308ba27588a7a007e5e29ecddd238a5335139e3bcc57e4da441c4b0b8b7b9ff8e8e96daf2d70b88e3b9b","pkRm":"a732c4f627e626fea315648767e10dd9dd341f3828a38e140bfb033752204afafe9e94d0b7b0e31be9030e1a6899338e78fa59f9097c49fd","pkEm":"4e4efb73137a9e4019e8536dfcff0fcbfffacb35963099a8624377999cefcd2c6e98c07aaa6906ccf70f95dbed21c03bdaed1017851862e6","enc":"4e4efb73137a9e4019e8536dfcff0fcbfffacb35963099a8624377999cefcd2c6e98c07aaa6906ccf70f95dbed21c03bdaed1017851862e6","shared_secret":"ec072c33f90c81c160e601be4d975c8ad36336c1d15537b4b74133642807dd6d6c76c8e1e0ea10a4cad6858dd9372233c55aeb37c5adc224663de0df731a5358","key_schedule_context":"00fcb1dfaeb0f739e1fdef674e3bead6aa703796379f96c738934a64ac77c79a0539b47ef10fef9d74124a76b6079f61957d5b791d37ce9aa2fa2a910a7e47ca58","secret":"ad321453c256f53b34dd1c943958790a0a4376cf5fdaa22080dde573d8496e66","key":"90977048125aa30662f5223a8475c4d18d4d6f07efc37c0c81a399a433b73b7a","base_nonce":"45bd1eab1339a41c98e8ab6f","exporter_secret":"89dd10c50a45b264b5a5ca6656b975e66d82da2c5c877b006be2f048f203484c","encryptions":[{"aad":"436f756e742d30","ciphertext":"bb1f3d72227c124ca240462b18555d49637282462798bc9972feeadd9595f54a84b4ffae282a0e82271d05221c","nonce":"45bd1eab1339a41c98e8ab6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"44faf8bc56a55818e4b86ba4c6f8d03fa66a70e116ac11b5d770b2554e955de2623c4e36316244d44699765de4","nonce":"45bd1eab1339a41c98e8ab6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"5549adfa1657d24300f7529bfd2275fd566ba785ad654d502a8af02a59b850a2f92e62a722930d3f0d1eee3dad","nonce":"45bd1eab1339a41c98e8ab6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"c07a23963030c423be6f34da1e3334917feec550ff1d7801d4313b50d00b2364a98b9bbaaff25c7a04e8a5eab6","nonce":"45bd1eab1339a41c98e8ab6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"fe6efc0545d0742d03dfd7989f840001f995b4ad268569617fef4fd144a1711ce2737db5cbf371a0351d56c530","nonce":"45bd1eab1339a41c98e8ab6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"d9d89b837cd6aaf506a7f6234bdb0810cd6669ed6841cb2bbfe4b975943c0a0869af50edc40aa71586260e8f03","nonce":"45bd1eab1339a41c98e8ab6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"f81501f259362ad0d18a04dfc2904e7f280db0ac69a12b96fbbd93cfac82385dc33d1b286a75d848ce9975c30f","nonce":"45bd1eab1339a41c98e8ab69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"20e1f5bcac20f432977314d6b991151a21d507f9ba50822d20cd5d9e50d84c40e8d7488eb4cd5072c5f777bafa","nonce":"45bd1eab1339a41c98e8ab68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"efaf8f0e4d7fd4b4b3cfa9f53d152bb6024e355cb9c44ed0a1c23396b810d7ae790248612beefa0bb4840461a4","nonce":"45bd1eab1339a41c98e8ab67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"b847a7dfdb7a3b1640f55e82c01f7d66d0dc0c271c981818fe071ad9da6013f5688e0191bb661ab4629f6c368b","nonce":"45bd1eab1339a41c98e8ab66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"9989ab896865c486732bd403aa6f5a473d28e5a069a5603937fca8ab26b2846b30b4b934e365ab7a523a2d2a66","nonce":"45bd1eab1339a41c98e8ab65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"3a11327f49932ddea9d6642dd3fb1dcc5b41bb7591c72f549f54920ae0a065e6629e1c079ad2ffda9fe5327e28","nonce":"45bd1eab1339a41c98e8ab64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"64df11c6822ea8e8c191ebef4a613d274fe8c15c7805b5f7363684721c3beb116a7c3940d52c87d5b10794b8c4","nonce":"45bd1eab1339a41c98e8ab63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"2d547f5bc97b9120b25e974a6a09aff44c82fc96372f85d1e68f93bb6c0a0e6d178fd54ec831bf14b67ececb6a","nonce":"45bd1eab1339a41c98e8ab62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"ec1cb9354a386f495e2acaf2015b7d73f262572f4761a3092aa979372eba50c1403f7d52d17f3b65f4a538b1ca","nonce":"45bd1eab1339a41c98e8ab61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"a91176fdd1bc6bcfdd0b75b5a487089f1ccf7a16796dfb43f93125ad362f3d98623461c6b6fc41e6f8832b07ab","nonce":"45bd1eab1339a41c98e8ab60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"a962ea4c7b686e55b76cf62a416503acfad96b93f0460e6ecdff05ad586de6fcd0efc2a8aa33aaea5cfa69f9ea","nonce":"45bd1eab1339a41c98e8ab7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"e64c59b50762401b9cfb5d85f38494d4903bcc285a218d7f25d441686d8679cb8d7f832ff20aa08829a4f0a09e","nonce":"45bd1eab1339a41c98e8ab7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"5570a291b6dd2b2e6a5ee6ce4116dcdf1b8f9f487352c473cf80c863328e7de5ab7cd31caf44fbfa94e873d165","nonce":"45bd1eab1339a41c98e8ab7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"c1a18a2832aee1ce184b5623d4f6ef981aa961087e05832bbb824ecc0b1bf37595159c2141dcc39fc358962e3e","nonce":"45bd1eab1339a41c98e8ab7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"d60dc04d95ea953f45e991763200af224b1933af673d2e93ee9b6fb3ec1b64f460dbf1d8c0608ad2694973b1bb","nonce":"45bd1eab1339a41c98e8ab7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"3650409090365ddc6e2f4c9f17c6aee98f25f947cbbc8cf41a9da55c27e658d7f505cb6ad9ec6d7860921e0e24","nonce":"45bd1eab1339a41c98e8ab7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"cf571cb3f4814dd8ee391f9aaeb5b8ac60d74c8ad4b07124ef56063e93c6b9b15c613907440d7a46446ceddd1b","nonce":"45bd1eab1339a41c98e8ab79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"791773527fa3da5c87a05b02e969f144ad05f198db48306270e34721eb95a6151f9b13c4b6f3c27019fbdb1bab","nonce":"45bd1eab1339a41c98e8ab78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"a449516a094bce52601f49b2864806da1d3e0d21a900acd2c1288e629f4c91c0d483973614745b6efa58777eba","nonce":"45bd1eab1339a41c98e8ab77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"2480d1df4d8eda399a44f131a8e43e02b92c4257ab7403014b5b69700a0a3221ee8a66dc64501c9971ce992eb2","nonce":"45bd1eab1339a41c98e8ab76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"8db89613ba0f0c9af3ec3fb2127c97188bea939bce06f964fe962c1447c8ff45bae834a20ecfc9a9b7343f4957","nonce":"45bd1eab1339a41c98e8ab75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"3251d19ff6f8b7cd923d7f5ead3a91818f323849bf625b99fe7b36a93ad22a43c497e3a17980c9ef509da357fe","nonce":"45bd1eab1339a41c98e8ab74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"8361901b2a6cd71a1f73033473deeb3cab4fb54e37e89fd13e3a72adf6f64a0f9efa27b5f446bb1f3fbee34dc9","nonce":"45bd1eab1339a41c98e8ab73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"5dbb8fc0cf150a5eca5048b402cebcd3609894e083b8e53f35a46a5c7d320cca203a8426dc24955f0a9fe80c76","nonce":"45bd1eab1339a41c98e8ab72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"c38ebf01a8f4e72a48117939bdf834c8065f92fb3abcba51b48b5b9b94c57d0df9030cf848c43b3427afbc6306","nonce":"45bd1eab1339a41c98e8ab71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"5cd2afa949520b53c69bbe98d51f66da26e57a32e37716bdf63d728635ea95f3bad2a168d3f8aa94e8cd898239","nonce":"45bd1eab1339a41c98e8ab70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"72f033f2ed995b26190e0fac4d51a08ce92bc764ae98c28650e855af80cf2e27ff46360534ec170a5aa4e4ddba","nonce":"45bd1eab1339a41c98e8ab4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"ea4979d4b0efe5516e31e15599c8c961087c8eb319ed07ddd8fffbaf2bcba142db8aee7e94f4b6973407d9edde","nonce":"45bd1eab1339a41c98e8ab4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"0c205cbcdd7120c9dd76d48cc0866d79520151978cf278a9e321b156654f8f7af12a080175d879180fe2c3cd15","nonce":"45bd1eab1339a41c98e8ab4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"8961026cf4c477582b7ebacb1de482f44a93d89627c58bc1734a2c855e5f1dc0a19968b79387e476119582c4f6","nonce":"45bd1eab1339a41c98e8ab4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"2fe002b0ed2bb459a26581107ea6f77534e3021c8ea4c07ebc313df4038bd45ee20d5fbef5bc71736e3b657420","nonce":"45bd1eab1339a41c98e8ab4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"d3bc81579d5fe0d4d370024fee6305e4000c90a18483bcc75afb6710939fd57d53c7ae8030ba307a75ed92933c","nonce":"45bd1eab1339a41c98e8ab4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"836c951cef84df81cad5ac81d46d591ee27eb92e66712124a7a83082d6e8e8074896a829def9ac54bcc3a8d1df","nonce":"45bd1eab1339a41c98e8ab49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"f9e8b59f4c4777ec31c819e2040424c1b3343965fa9625807be37253a683ac6ec876eaba5d4b741155c9e71b1f","nonce":"45bd1eab1339a41c98e8ab48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"ec36b264ce3baa0ab89715555e489e684f7763cc036aa5d33bedc3a4981e8a7e0fdf8c749ccdd1ddc78816bd4d","nonce":"45bd1eab1339a41c98e8ab47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"6c0a9507e34cdd1deaaad69775c34a2c2130988f54de629db1a614d3373291637278f870d359acd42852024981","nonce":"45bd1eab1339a41c98e8ab46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"4b9025957b25b279a76bb7ec392ce6c279f5ba34d736b663c3a09f84886df61a4f52032644c80b53d3f135195e","nonce":"45bd1eab1339a41c98e8ab45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"9f709d67e935ee26141cf5375805fa7251d0de7d683759c710107edfefc7748bafd0417ac9b4d54bdf2daadd91","nonce":"45bd1eab1339a41c98e8ab44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"cbcc3f7450f12a495ed120174ac1af45a2d8a675bd3788bfeb17bb8ca7c21291e300e818f25aa2aaf2df504709","nonce":"45bd1eab1339a41c98e8ab43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"7d3b5b0b6093be82d7c2c053ae83cb1f2e702dbc4ba9bf74d8b03c995a05882ba924738b41d5a86b3c4c6b1815","nonce":"45bd1eab1339a41c98e8ab42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"15f93165729bd67e4024a59d4d22be964430f44c991abd412887203391786f3abae6fd9577f410ff23905fd8c6","nonce":"45bd1eab1339a41c98e8ab41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"8e1c9c0b931bdea9a7b49adb08d08eb80896a9ece227c5521d495c18b5a3fe766cb46112389f93500e7080f393","nonce":"45bd1eab1339a41c98e8ab40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"8a34f408f1f56b74d2f054166e28a592b9eb1ec9ece3ee62356b829929348df3a4a79e2609062680db0120c9e5","nonce":"45bd1eab1339a41c98e8ab5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"95f34ba4244e0f0d927c09e83f67d07cbec2198c03428b838ff70a794e81c60820f2781fccdbdd17de45ed569e","nonce":"45bd1eab1339a41c98e8ab5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"97bdda356f107d87c98ac5280bb18e9d960d19dc4e4f624f20e1c5d72d207f16ecad56594f7632556cabd6cfec","nonce":"45bd1eab1339a41c98e8ab5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"fa348ea54d70e32ad9103c8c7ce5d9f0902da72570dd22d449cd2b2a517359f69dac8a866c2ff6e4ced0d7164c","nonce":"45bd1eab1339a41c98e8ab5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"beea7ae61a55b3ce08f722ccb6d96f8cf4286ee73fb60aa8cefc055d72df051524ad3617148fe6189035b18c0d","nonce":"45bd1eab1339a41c98e8ab5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"26cf568cd945ed2f574474fe7c7e437bd770f3e3b83c252fd0f1932ef0848022716f94fbd7542b1474ce79ad3a","nonce":"45bd1eab1339a41c98e8ab5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"80e55c9273b86625ab102bc272ee21255efffef40e32b588c05cc2b373d537372c3293aaf769f25a2fffe439b0","nonce":"45bd1eab1339a41c98e8ab59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"9417a8ee47708a808ebdc1448c36d829d9618dd65c8a265bc02b61461f18f61629512419042f57246323079580","nonce":"45bd1eab1339a41c98e8ab58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"09253407de7e2fb5f0a202de26456eec8d2eb5e1c2da8f45a9607f45526ba8df567d5bc1775c62608385d7111d","nonce":"45bd1eab1339a41c98e8ab57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"7b92a348c0cba44b691ca768ab761f6cf54cc08ec60c6d04de14e36e06ae25e40dd79df6b22d09236360533db8","nonce":"45bd1eab1339a41c98e8ab56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"b2651025d6d059c005bf0535712a674e857e61eac0be42b9a607e96badbaaee205dff9f84a062bfa318cf2d0b1","nonce":"45bd1eab1339a41c98e8ab55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"e6414f1fd318f987752e97e74982dd4f40a66b987fe665ed5dd030bf7c0e30bef686105e568ff9891c44bb2000","nonce":"45bd1eab1339a41c98e8ab54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"9e17e4a59b3f91d73ebe864470f5904c835e4bcc3f129caee14a63347aa4c88cffcec71b0cc6bc4d507b546495","nonce":"45bd1eab1339a41c98e8ab53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"99312d0cb7e7ea6ed2888cd48c1ed2641fd71aee2f85f5f01281ce31dd874804e3bc203aa47bfb2dfd2e56ff10","nonce":"45bd1eab1339a41c98e8ab52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"9dc287d7b7380fc21cb34acbcaf14bc85cc68a3bd18b3708bc441efd1c9728b9114d30f1cc121a3cd7c8ba2ef0","nonce":"45bd1eab1339a41c98e8ab51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"b922bdb491532da103be4224e1eea5e66fe81a7ad77ec9ac80464ce75c37756fabb7152c5d1d0f9f8c8aec4177","nonce":"45bd1eab1339a41c98e8ab50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"90a3e541c7c711a0ee0f590c71e800572dfc96c08c59904ee7c4e9c9bac85c2bb4afb59ec7b025a36afb652383","nonce":"45bd1eab1339a41c98e8ab2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"60bdd37f767ee58f3e5d410dc8cbe71ab28a25f06313987511d1321818bbcd1cf24eb14ef11e119b05cc0ebdac","nonce":"45bd1eab1339a41c98e8ab2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"160ddcb831148ca73ce6d48c6e27effa6ee61d302d4f4b702c58aa69cea4bc17dd63a9de865c1534434422ef13","nonce":"45bd1eab1339a41c98e8ab2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"cc45020669245a4bf41019ba0814b884b1c2193f384c87ca69d1da52d2dd4ee9ebbeec70de4d71ed534232161c","nonce":"45bd1eab1339a41c98e8ab2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"0a4b470f0ad031228eb93ffaabaf2ce6e0f3b47ac656eb18c8e406db77f0ebf6583e3570ce2fbc990e91091af4","nonce":"45bd1eab1339a41c98e8ab2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"af6a7fa170b86293e677a88071d57c908426c1fb43998582abe3a71cb44497b095c13aabe1f960d56341abbc99","nonce":"45bd1eab1339a41c98e8ab2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"2f774e4c804b238312cff9dfb0320af88ee44401b9ef98fbc38b030987406a702c1ac04c87e91635b96e0c92bf","nonce":"45bd1eab1339a41c98e8ab29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"610eb2f4ad2296fe444a8de266165e140a0e9f9bd85689c1d98d202764dfd2b2cc0d222324cb92a66c4585dc23","nonce":"45bd1eab1339a41c98e8ab28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"d5847c1c2f5c5ee9c59f7a1464015c0a0cdf2fd5d7d429a745f0f277b61609b7dec07ee4c48a5fea85a58bb409","nonce":"45bd1eab1339a41c98e8ab27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"722311be54de4b38a276f7fcd5da1db34489b86554dbc0e6c281aa52ac2f06c3f885f95535dd0c6fa0377d2321","nonce":"45bd1eab1339a41c98e8ab26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"f37b65a27c2d5e2dfb89d1f178b686a33d0e60d776a39bcf1e62a953d14f9eeaaad736ec1650cd8e6831c25bd5","nonce":"45bd1eab1339a41c98e8ab25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"3070742e7ba22aa52decccecd06aa16d1e141bfa55c10ac2d91c647e3ed84cb8a81a36cfea37203e91c89e67ea","nonce":"45bd1eab1339a41c98e8ab24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"1780c403db4274f2e03d91e49a1d5569efe6c91d94952d66da621e43c8067156178bcef9082737f27ba296c27d","nonce":"45bd1eab1339a41c98e8ab23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"b18529796f8c1df5bcd1f9d40b79f9a9dc1c639c9c8e06f18feae13816d9e5ea45658a25d0343bb99e48428697","nonce":"45bd1eab1339a41c98e8ab22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"e5a52a8a00eaf6ec95348a0ee16a020b427fb53302f1f90db6ea9dc0f8bd36431181af937ab7391c84ec295e67","nonce":"45bd1eab1339a41c98e8ab21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"1303b208eea64f530acd35b10d5a4f324b52a50ee155f445aa4d010d685bea617819def654ed9184b456ba4f40","nonce":"45bd1eab1339a41c98e8ab20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"3b8140cff5cafb9f7452c9152596d94af01a449be7c737a0c5aef4cd9e6b2b5714ad7e2f99b1d95c2f575f3961","nonce":"45bd1eab1339a41c98e8ab3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"8832e13e6562df241ab87de0fb6e71f9e230cc3a559ddfd6d4613a3bea7edf10719eca26aee5ca7611066b7266","nonce":"45bd1eab1339a41c98e8ab3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"baa9579786dd21d7fa53b0159f71a7ac2fa2183dbac8d137a8866341b36126bc9f48d6db803e1a56a1025d3dd1","nonce":"45bd1eab1339a41c98e8ab3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"bc7125e1331f6034e3ea39b92564d6408baa32852dd42c121616c554a667644d112687982133415769d0f5f4c5","nonce":"45bd1eab1339a41c98e8ab3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"e23f9eee2b0a5c7e68e481b3f1d2ec729901a7806dccb948e47f5167309acea30ee98e88ec00424c1215d0311a","nonce":"45bd1eab1339a41c98e8ab3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"444c876fa7e4f747c14592d9341df02907ce4ef85c37e097eef327c94cbfee0f56b6caafb2a3d563f28da6d8e3","nonce":"45bd1eab1339a41c98e8ab3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"2886c64762ea5ad84df163c1648b3803508ee13a3f37592c072431821f817e2df79b1ec474325e94607e86df4c","nonce":"45bd1eab1339a41c98e8ab39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"75004a1d79b83953547c07c0603df2f8702f4f15072b77f09164e54445b980265f5112d86be8c393a3bc32bbb7","nonce":"45bd1eab1339a41c98e8ab38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"f7af36a051837e81a346384312e2172decfc49d88e1518815ffe4b2048b929542e070d3ffefd8a71a00c0e71c3","nonce":"45bd1eab1339a41c98e8ab37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"6b3b06b198b5ce6570647e164e21705db16fbf08cc06b3eaae971ca04a7e76af999522d94ed7e20b3598c4951e","nonce":"45bd1eab1339a41c98e8ab36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"8152f829141a61d06f6f864abf8bb8bd5a2a3e364f96a67d536d1dcdc58513ad95962a170b65dbf4b3ca0c49f8","nonce":"45bd1eab1339a41c98e8ab35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"049b512a640b98c984aba6420c2e16a7b11cff6669a1cf989e09eb606012812ae2de24580c1cc779a90286fe7d","nonce":"45bd1eab1339a41c98e8ab34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"30ab0fc87188211332fb74b440796fbd048bd51906832e7a354bc5bfce12126bcbcc74be3c395cfbba46e68a3d","nonce":"45bd1eab1339a41c98e8ab33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"a5e880b981a5e290c412b1f8c7e874ed95abd726892ff4df1ca84d876ed2a59cf2986c8e0d4d7b45ba71a7d71e","nonce":"45bd1eab1339a41c98e8ab32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"9e3aa5341b2c8d62fdcbd67b2772ca89f18966fdbc6b08977e98fd3395f4bf20a7c07650307e56fc3877e600e3","nonce":"45bd1eab1339a41c98e8ab31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"eaebbb6d12a1def3e4959bbaaad82a2868003c0bcf4403fd069e40c7329cdfe1071d42b9ecdbeb3f321144be56","nonce":"45bd1eab1339a41c98e8ab30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"efd2c81f7af2cc51ec2373b54c8f5c5f288b28a3de749a95d9cf937b50eda582b5a87532fda8c8aa56c8de0617","nonce":"45bd1eab1339a41c98e8ab0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"52fd2a9c18afa044380d8d96e4a54935e42cb5188530e199962af57a43379664959d285cda1fb06aec58379c79","nonce":"45bd1eab1339a41c98e8ab0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"f5bbd2c951d6b0edbcd08af6952c43f0ff514386abe697821270e55de967fccb2ce5cb0b0a4d8ce9a628afa9ff","nonce":"45bd1eab1339a41c98e8ab0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"02360af2b546cac745686698d4298021e57978fcd4838dec2b42ec4daf99a77b7f607e915ae5b154805c50ab68","nonce":"45bd1eab1339a41c98e8ab0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"e9a23d2314600dded0407d7852f3a466409c50c548c494c12285ca6d9446a2e4e0b206c3f21d3881fbc110f722","nonce":"45bd1eab1339a41c98e8ab0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"75df4fa6789298ab7f906444c40d702238c37b47371d6e31721e0a991ac138e7dcd9f230333e0fe8180da7d6ed","nonce":"45bd1eab1339a41c98e8ab0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"3dd252354fc9fb4f00cce6491110e3ef023ba29a83ddc3edf3c42851e7badbce05ad2a6ed2149e2aff1debd241","nonce":"45bd1eab1339a41c98e8ab09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"11ff19ebdfe5315056ee436e1b7888aeb6af05fe438d90f8c07e2856480be269d777d0d550d55a2df417df50b8","nonce":"45bd1eab1339a41c98e8ab08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"9a54b8f0d73fd851b075023010a32376bf4fd40fb013760f2d62947687b48344a349ee99efea105738ea2761a7","nonce":"45bd1eab1339a41c98e8ab07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"de9ef54245bd590a4b6acd126c1fa8eef3261343f6acdb1546920047c58379690a91e66e72b582d869ed51623c","nonce":"45bd1eab1339a41c98e8ab06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"a056d2618cd342430491b9045fc393521dd8859c5cefe4ca5427fe3870e8611dd13947af150550ec16eafdd3f9","nonce":"45bd1eab1339a41c98e8ab05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"a51cf84950c90fbfddd05fa251515e799d60836817f7f51a2d09afc9962a34019c20721cedd23a52855bae4b11","nonce":"45bd1eab1339a41c98e8ab04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"dac4c11e4d8cf2f159d86441a1ee2a8c2827d79ba4c317ec1e6b4e27076365b0ad1c87e13bee621d4135c775c3","nonce":"45bd1eab1339a41c98e8ab03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"e713bcb8bca93c4a5cab3703b77ea875f6212d826c829d3ea604998f3bc8d65cd10007f50099bb6ecc9ec796df","nonce":"45bd1eab1339a41c98e8ab02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"5eb8bc53d79c9454b447286a43edc6961f04096feae012119a1e5280e379ac3510527c09c9ab9a20d9c0bca2f4","nonce":"45bd1eab1339a41c98e8ab01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"325d14572273a6fd49502f84f9649baca9d3145842e0f10a950a455fc9b5179f9a6564aea90071c3e017f0bc0b","nonce":"45bd1eab1339a41c98e8ab00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"694185e566c310fadd4772dcce96f0e44861cf5f4c4bcde4f0c19ca878e750bd0aa3655093ddfb9bac3ef7b6bf","nonce":"45bd1eab1339a41c98e8ab1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"a9709cf7452af8bc69536c6aac4e912b24b06f4900b2f51b7a67212c1db58feac5e033b63bec37759475d1040e","nonce":"45bd1eab1339a41c98e8ab1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"e4eecbd1bd7678583178b6e7ee98b5fe145e91d520e0dcb94acc1a51650dc3d4f87d87846cb97f2bcd2e605510","nonce":"45bd1eab1339a41c98e8ab1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"1d28fb056d88cb606e82c891769e00abc7f64c52bf64ee950c6f5262ce3907ce6da01371f7866217f79e7e37b4","nonce":"45bd1eab1339a41c98e8ab1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"6ace161a0a2e30cb0f0b97666f8017491d069b62b69eca3d72fa615f02e42d03ec4f4775739a9a30b2e401e82d","nonce":"45bd1eab1339a41c98e8ab1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"b4a8f6a4c0bb51e50b033647f927f0032318ce5f49cf7dd79f86409b5bd1175cd21fa6f61347afcab6c5b3c5c6","nonce":"45bd1eab1339a41c98e8ab1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"afb3cf3032aa203bc5fdd0fe9507683d2170b9f1cd637e5de63b4cbd7625144f69f54510e7a1a7d7d86b9eb081","nonce":"45bd1eab1339a41c98e8ab19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"028a9dbe393bcbf72cd548614775bd1afe7f3cb4156698414a71caa718ee420d7ec4e091c8dbd6e121b0491d61","nonce":"45bd1eab1339a41c98e8ab18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"0a405fe9f2e1d2769f5beb8b373db323de4c7be9386874661c3ff56245ed921a2b5c2d832f6fc84c097a15e024","nonce":"45bd1eab1339a41c98e8ab17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"5de556beb36bcc810e55f795ed6ba2e771510dabeff1b9535da5475a7500d37abae6cbf4ee078023510ee73905","nonce":"45bd1eab1339a41c98e8ab16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"818a743ce1ab857aa342c0a1483798cdbfeba45a466d93c8671e1fefc856cccc9c46eb987f7983dec3d9150add","nonce":"45bd1eab1339a41c98e8ab15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"1f41e455d3c48cdb86f7c8851a1328c11f5a08c5048af37197cd4ecb68c7331520619b7295b4cb853e1a815e19","nonce":"45bd1eab1339a41c98e8ab14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"54372be208eaa2d3d991d68b97cba4bf0974fafe29b6ce0d3a88edbbee2433e1e0723c854e8085de1b9f1aca96","nonce":"45bd1eab1339a41c98e8ab13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"e52c44c85e42a7aee884c1efa6d730d1353e66022c9f8bac991185e23821bce494da6da6f1efd7e74cc8d0eda1","nonce":"45bd1eab1339a41c98e8ab12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"0a4f8e002e77f18a212273f9bf9e33fa6c3a237073de8883b3b8edce1850b0c044efb0e6481fecf03faf3127bf","nonce":"45bd1eab1339a41c98e8ab11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"d83fc1ed72de88e658d67790f60cd17edf53790c1164798bce864148af4d6bc0c3c41cdeec73fb63ab3a33f3b0","nonce":"45bd1eab1339a41c98e8ab10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"87c04d7f002fa52c4d891fc603656b3c8452091900903a6496480561450cf08ff027f3b691702abebf87d0ee75","nonce":"45bd1eab1339a41c98e8abef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"13db465ca189fb8eee863db222ec7f5c217985604bd93287dba22ab7a7d4c22f2a512ef4be21a19218294cad30","nonce":"45bd1eab1339a41c98e8abee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"7e91c84e752d1d6123c8afc7c645b2725a069207c7bb21337d80743676be70107524bd99f26d43084825c47e7f","nonce":"45bd1eab1339a41c98e8abed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"44fd643b22915e74639969b0c84ecf16f9f4868a7e9c97c4ac1cc8ad381e6a27fd7560802fe3ce376af754378e","nonce":"45bd1eab1339a41c98e8abec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"be5d1dd27ce7a0ad6298ed3f0aa10122d5ed6715a74210a9e15f2d224838c8d3703ea35d9fa29dba965e7c7524","nonce":"45bd1eab1339a41c98e8abeb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"d1dc82f403508c33da5e14c82a6f7d0da64725f0ee1c9106e3af6629714ebbed9df3b762ae9ee1b977ae258512","nonce":"45bd1eab1339a41c98e8abea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"1fc904253e1c1aa6053de0ebf93308bc1f928e1bd1e46915553cb70ef5678aad03b075e5b2645b6ff0b029c8f7","nonce":"45bd1eab1339a41c98e8abe9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"94dc768441c0bfa60ebbe8b2f8fc282994a20f22e9ec2cae45a0c1ca0652604f00094cba6a2caea11aa8038316","nonce":"45bd1eab1339a41c98e8abe8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"16a07d84afda1b261433527d661cd45e14b6b05debff1231666267aca477357583020538734e9c423213fd988d","nonce":"45bd1eab1339a41c98e8abe7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"a56444d4b8c0c62ba816d26992356ba329c6cb88a30e03d004567c488cb46a67c693fb41939b160b5bffcf277f","nonce":"45bd1eab1339a41c98e8abe6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"9687c2c841e8e577933894abd48d99f04fda9f44079268a1bb67fae763a02ffe5c920dde84b3f1baa332d340e5","nonce":"45bd1eab1339a41c98e8abe5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"6e7cec99115abf530b1d5785e9a06f957591b31a5953be7c08ccdfd829a0e48dc527a534cc53d76d24b4f90bfa","nonce":"45bd1eab1339a41c98e8abe4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"322b0f825564ab6c9aad15ac733a73b1dfc977d419b77982fd1d2ded96347dc77ab1bd8c7306a5ff04508136c5","nonce":"45bd1eab1339a41c98e8abe3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"898158219a3706df0cb22d2e079d44205cb29036747b7cb4746f900ac5712e7b1cc26587e000591dfe15dd6f37","nonce":"45bd1eab1339a41c98e8abe2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"0bab6af7c6ad4f2051f0dcbeeb0999aa95f5d64f7f27bbda926f73237733ce940bb85b4bd00a221904a78a6b7f","nonce":"45bd1eab1339a41c98e8abe1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"4a190ea3d9da96fc774d84223c1098ec20bdbb65e467faed2af893ab42b32ffe556637ffaa1ead3cece8281fa4","nonce":"45bd1eab1339a41c98e8abe0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"c70d0ce2a3a81ee8e6fc7de295c28c789e8daf631df0b6d4fa7a4e44b52bc7c0db32ea2bb25c7ede80d105daba","nonce":"45bd1eab1339a41c98e8abff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"7f62c6778bd61d80b3c83cece6fe7603f63e7a63694bdb2a47076f1bf5394349a65aecfdc631c2b42bb55309e7","nonce":"45bd1eab1339a41c98e8abfe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"56a97c5ffbfdcdbdcbea3aadfca9bbbab8ceff3eafccc53bbd3f2bb060e00bd241fc1e555e93e38be60d1b9117","nonce":"45bd1eab1339a41c98e8abfd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"aa5bef891d4775fa529964d785eeada3884f82b4945c2c7a903bffd058af90fa4cf798f1728a5be9cc24447b7d","nonce":"45bd1eab1339a41c98e8abfc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"bf8d96810ff9c12f7a68e77a5418fab54052a39adc89436e8f2cf06b1ded7633d5b8d0d541abee8eae3a2d0e49","nonce":"45bd1eab1339a41c98e8abfb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"6e723607c273b3202b785eb766279c8136dd8e65a7d4136ce317b820d9ccd9eb6eb6a1e7edcbc721c7a23f535e","nonce":"45bd1eab1339a41c98e8abfa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"6189e601e8d4260d0c846b3028db86d4eb41616089509f519d238d00c89ec3276807849a30902e4fe921778782","nonce":"45bd1eab1339a41c98e8abf9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"f088657113729421681c9befcf76c91697a5919ebefb4f2315535d31e6b9faca79422f616f120df54dc509d052","nonce":"45bd1eab1339a41c98e8abf8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"b1a8ab4b28607079446453ad5a88baaf82fe4ce3f7fa6419c874bea021892ad97350d27b8efb945dd2ba76ce37","nonce":"45bd1eab1339a41c98e8abf7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"447dca39dcc7e314e4f94ccd4fe5465b46c752bb47a3c5ade68819c93582b4bacfe1666a5b9749dcdb2a2643df","nonce":"45bd1eab1339a41c98e8abf6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"41b8796196884901e78cb3fa144c0956632f7c8b429c3a79d24a1c09fdceed445eb970bb890f496161868b31c6","nonce":"45bd1eab1339a41c98e8abf5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"7c6ea6436189c9ff4447eeb929029709076e0b4c65e07e48e6501be106dbd315cb7d8f1645aa55dd91788d518a","nonce":"45bd1eab1339a41c98e8abf4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"94548784227da242c9384402d0a3f529fdb72e941678186a452b2d04c89cd497603d97bf504583ce8f6eb9b69a","nonce":"45bd1eab1339a41c98e8abf3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"2c4da6a8f80d835a1cdbde630a7a5f0cbefc1b9818709318e4fb4177a1eb8b0d9b952f330b1ae38e51557d711b","nonce":"45bd1eab1339a41c98e8abf2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"cacb5275a58c6286b96a864e71c8b085b3775ecc9779b6bce1fc2fb36403931b7b73735d68ce0879633a47d122","nonce":"45bd1eab1339a41c98e8abf1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"7e4e9895363c4505621e8dd863cde893161a9164fa5b5831332617ba2e15c33c328b40cf95f788aaebcc59b61f","nonce":"45bd1eab1339a41c98e8abf0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"1f02b2eca7dbde0a69258bfaa2d153feb399abf85023245a7eed558668685ef5bef07e6788e2ba0694bd7235be","nonce":"45bd1eab1339a41c98e8abcf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"cab31243c7b84d26df2e5bec5802b7601592642fca51ed05b03992683d6c08a1e38363ebc053a7d6d536722d91","nonce":"45bd1eab1339a41c98e8abce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"7133cd031da838d7b57c6e4653ebb457cc7bb256dd7396842185697983c9ca9c3a70a671884f7612965251b3c1","nonce":"45bd1eab1339a41c98e8abcd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"72db3240bf78cd6eff80cffeb4333d7821b0378668ad94c4fb0cf0298fa697358655109d28577457f62d048bfe","nonce":"45bd1eab1339a41c98e8abcc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"604361d8c5fcfdbd61be53363a43332164d50284ffddd47b81b561012ca7be4e8f3814de4e9df946e868a7860f","nonce":"45bd1eab1339a41c98e8abcb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"81602860db652a84a8e3d7b77a60c90bd8e67dbd590639c0f0fecf04818568bffffe647880b2f38e0a57c8beed","nonce":"45bd1eab1339a41c98e8abca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"22830100d1e6232e1d3924f7484de54b1f8fbaeb0ffa9c6459e6d96471065c47354e198778706f377ace612b5d","nonce":"45bd1eab1339a41c98e8abc9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"0ad1ae3638103fa54c2a34c48aa845d00459d0630240831ec8df0e383df934f1f27fe1a2732acdac5db82de46f","nonce":"45bd1eab1339a41c98e8abc8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"f2738714972e35f1c31040ada76edef41a2aaef30425a68475dbbd662b88b8acbd32fd1c2d5aaca70b9762542e","nonce":"45bd1eab1339a41c98e8abc7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"5e9411f82521f23d273d879b681166bbcf4ee8c382730432f6eda868c7b4b737595540801e71b729f102b9a7bb","nonce":"45bd1eab1339a41c98e8abc6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"16274167ac168f1c2229c2fa54733aefcb753554266717be9ba6344c9c6a7078a61d21249d46bdb703fb1f8426","nonce":"45bd1eab1339a41c98e8abc5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"bb4d5b84635b80703632afa7505d9f693d6e1e32deafae82412359b3b60ce10322a88a67653977df73f5ee361c","nonce":"45bd1eab1339a41c98e8abc4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"d405b685812f9633734e48c23343637b81e9d00f67e112eba0485f453362f8fa44ab7632546fabf7c11af53d07","nonce":"45bd1eab1339a41c98e8abc3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"d2cf82b095f62d02d528dd39aa057766dc215ab68652da0bb5ee51f23848c44d2b8f5e696636cd3920cf98239c","nonce":"45bd1eab1339a41c98e8abc2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"61d49e055e5649c84a1f9785ad022531233d2f860ea6df79f824b5d0c10dc6c26dcc78d5efccdcc767f1a23b3a","nonce":"45bd1eab1339a41c98e8abc1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"09f98910d0f2f294b11b499c14806d8cbf43105af551cb20fb66e33cc7dc63fb76081f79e3bde8557389f7875b","nonce":"45bd1eab1339a41c98e8abc0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"112232ef250d3a9b9f682c37aca48ce7351c68b8c3430fd1acaa10f393fa032144dda6293d504c9816cb47a20e","nonce":"45bd1eab1339a41c98e8abdf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"9c31f53e2c2182d09ad499b0fd8ecf487750c8a3f6bc8d4acef9182a92e0567fe63cf79a91ad359ce6eda275ec","nonce":"45bd1eab1339a41c98e8abde","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"c736ea4a11671efdeff180dcc0875b387cb4ee66b2d8498b2cdd05390da7fa8901dbe43ac5630d947ae0d80865","nonce":"45bd1eab1339a41c98e8abdd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"ecbaabc297e8acb9fe2beddbbbce104a1a3c0d05bc5014ddd9cabedb7028ae9c7516e8d5e5564d486463362612","nonce":"45bd1eab1339a41c98e8abdc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"778cf44832320f1e33b24fe8b13d2dfb3f61aad0312dead2cfc035366af8a747908048d0a481a11438d396a7a8","nonce":"45bd1eab1339a41c98e8abdb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"c55a5bef94a28d3cb53059be9ba3adc04de9ebeaa15500ab8eb4b9da10fae811a00d5d657fe59dfd38aeaf8a96","nonce":"45bd1eab1339a41c98e8abda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"20b94b418fb041965db78d1c01fa8d48aa53c3c0520d4476e4a8db4947b81b80a3be15828b2c4c175aab5e3651","nonce":"45bd1eab1339a41c98e8abd9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"49b5c731a9a36aae457ec952a70306647357c1bcd13950f36f5d342b194d699bf1c91466670d08818e79966657","nonce":"45bd1eab1339a41c98e8abd8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"88b63691f7daf0adf3114ae585720af7b1884eee0181b87b015976a89eb1f9b07d3da027fa3299c02fa72b046a","nonce":"45bd1eab1339a41c98e8abd7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"c82ae89f83b292332693776da11557582c8779ee6a79a00cbebc719dac4d29715fe268beb8ec8f3f45850f0f04","nonce":"45bd1eab1339a41c98e8abd6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"b39656acade408d65135ab5fc88256cbffb6506c27520d5167b25388fc1942ac16d885f19e708e8928bfb5e4cc","nonce":"45bd1eab1339a41c98e8abd5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"c128241d26ee6bbc89675046104c9be21f75578022442ac9967324b0a43a5ffd38eee2e34e61b2aa63cb581b21","nonce":"45bd1eab1339a41c98e8abd4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"1d6493c86716b1bb0539abd98e00cfc06cb7fedbe3f2f56e3c31b8df686fcd3a7cc21dc603700dbdc498e2ee10","nonce":"45bd1eab1339a41c98e8abd3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"b1f85fe1e01b0ca5cbf67c91c8b2b838342a9d9cc00bad7e42e0aec6b06e932bde9d2b30f820040588a792d553","nonce":"45bd1eab1339a41c98e8abd2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"c598517f6b8606aa8080345616abe4c87f6fb34d707dac9324a275ee57e0e2f492c8eb685ff6d166a29162ad05","nonce":"45bd1eab1339a41c98e8abd1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"f6dd3e4af0007d731c84216dce8d654c1d4dbf7521e1c390969ec81d237fa8fad3d8fa2e0d7c7ca7e797a5c8a1","nonce":"45bd1eab1339a41c98e8abd0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"58729a897e5370deb1786296650744d8c2bd99b296e88bda107fd152d23c2aab1d5c544f138929c72e2393c8f6","nonce":"45bd1eab1339a41c98e8abaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"f2e01f717c97547ee91f7447f349e3b7187fa3c382a92188c9f55d6e98684a2c16de9cbc39f2cfbc3764176094","nonce":"45bd1eab1339a41c98e8abae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"230ed23b502f792cb332b89e76d73be12cd998640cbb140610e16d40ee9294e2ea82416e9f96b5d430418278d2","nonce":"45bd1eab1339a41c98e8abad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"6e3c3122d6ee6e90027a92ebfb37bd59c5190c36c444ecb23272004f53b1a139e6b4da3680527aef27d00582cd","nonce":"45bd1eab1339a41c98e8abac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"2f4c0fb7a2b159f943b55a6946551f929ea4c7d92c7c6ced98273ce95b07d31f03b4b7eb35e30c91b50d267c60","nonce":"45bd1eab1339a41c98e8abab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"200685fb65ed7aab7261a7d2ff0407bf754e0d4c571051c32c6949f5507a1b4b187927e4dd3623e2fa1a5927ab","nonce":"45bd1eab1339a41c98e8abaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"36bd16ee43ee0d3c72df318864a704aa6ce1dc30f3574cb717160045084d54799de414875a49cebb6dbe316727","nonce":"45bd1eab1339a41c98e8aba9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"b135f5fecdaa01e9f5751b818b195dc7aac459277869cf62b474fa434f081bf475c19b6d8eaaa23ee81cde96df","nonce":"45bd1eab1339a41c98e8aba8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"cf27f85010d80cea73a9668807f08ab38c9f2f1bd06149cbdcad2738429a00fa516d93c89bff1946f0ceaa6780","nonce":"45bd1eab1339a41c98e8aba7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"a0c3bd22dfc1e668b136323baa0d8f4de84b6dcb89f0fb4b0d5da82e72c56b07e5aaee0eab7ad634b170004636","nonce":"45bd1eab1339a41c98e8aba6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"e15649677010d0fa355c65a8ce55b5f62fcb835592e50cf2f51f4764e7f3c11901b394eeeebc167cd238842d7b","nonce":"45bd1eab1339a41c98e8aba5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"f2725db32322edaed34a7f4ebe70eb3c75b74fe884a03c49193cc99e7a48e6c7e3b2e3d4adf9b8888bb90d26d4","nonce":"45bd1eab1339a41c98e8aba4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"f7f77f1e36bb70e0dc772c3636b760345fe4f98217a4ed943fb90a8e4b2f0f39168be361714defbec343200053","nonce":"45bd1eab1339a41c98e8aba3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"faf061f42c339e4892c891dbbc6b4f481923e9d8164655a1cc4d8fa149d1ab0fbb42637453c65daad12277628b","nonce":"45bd1eab1339a41c98e8aba2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"855f7a215191c315c3504ac4aec2cafd5fdd9db106c047c1df2ad7cdb1cff13fb66a5daa19a8058ac2453ea442","nonce":"45bd1eab1339a41c98e8aba1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"ddcec99e9de2346d2a824d7a1a806cefaa874af9a8a0d77904c3782426f37c2a4c3963f2663dff4e9fc3d91dcb","nonce":"45bd1eab1339a41c98e8aba0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"847701813ccae2a3677d248a5dd6a656fe28e0f4dba4d8c6d6fb15fd4110452c81399b30576126d260a8a5972d","nonce":"45bd1eab1339a41c98e8abbf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"c0da22c6a36612479494cfb7abe6605149b186ccf8da9b4a54ef24419071346fe6be3a3b1de3907b322b8599b5","nonce":"45bd1eab1339a41c98e8abbe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"5f38379685dcd0a66d7adfded1ea78fcea34eb1800b2a2284f7437f50e5180e92fd1f7a61809b85af55f8e0028","nonce":"45bd1eab1339a41c98e8abbd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"f949b78bbd7f989d8e9adbc6251b788639a5d6618edf72fe25f4faabd46614743495350fcae502d7a5fa312909","nonce":"45bd1eab1339a41c98e8abbc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"2f6766a77504510e07aa86e4b520c42d179e6b27858ee0f6e58fdacc8e177e916b80234114e3ef385401918841","nonce":"45bd1eab1339a41c98e8abbb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"9781001fac6109ba3c085b82ec1c03a3190417c695e05cd6972eeb04fadb3249a3deee19fd4ccc7129651993b4","nonce":"45bd1eab1339a41c98e8abba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"b91cc8032ebfb2f6ef50fd5300da55110ce3df32573f89cef45c3a0e0ef936fc2f54fe78af8fe78b1ac453d649","nonce":"45bd1eab1339a41c98e8abb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"3e0bcc7d17e44cd953a4cc831c7c924e2f67eaa0621bf4cc1b5d843e369b9f7d7f7493c173767e2dafb1a24a9d","nonce":"45bd1eab1339a41c98e8abb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"5728f2117e4103beb4963a98227c8df4f4d24cbf4a84cf362c58ca26554ffca813702ca3ae939ca76b681fbbb9","nonce":"45bd1eab1339a41c98e8abb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"7c0b12cc007030cbaad9c53ae3c91be6e8122107cd9958bb90d0688d679b240e8d624ff6b245a76dd99af7ccb3","nonce":"45bd1eab1339a41c98e8abb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"cb89e1114657d00782eb782fca46a1dc04c8537bc4e21425dabf85d7fecf2855f0c1ff7e9348ec16f56ff0c08f","nonce":"45bd1eab1339a41c98e8abb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"aeaec6beff49681e12b46ed737d5bde4f78a4308a2a3d638040dbb1a1eb2f8d4cebc16758e694fdbb9c58e7652","nonce":"45bd1eab1339a41c98e8abb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"ea2e67545201f29b0806f35654b56a39778f868df8bbb7ea84278c73d7f24e277249ad427baed84e4b6cb90a2f","nonce":"45bd1eab1339a41c98e8abb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"c4b78f2c351c8972b4665f757680dfdcdf11ac21932c9aedb1ea2b354b9a72532b8f2fb56df78e55bb09fc104a","nonce":"45bd1eab1339a41c98e8abb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"2130df7d61fdc2914c7cbd8cadf1564c15e8a6ba67304a01cc7bb275d0a3af6945be9f7d563c6f613d7c809ac5","nonce":"45bd1eab1339a41c98e8abb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"6133e3cd45fd8525a22314b799c6cbcb8d35b21b5675886e0672b7ba7446779588ee39d7a34a9611e35b456dd9","nonce":"45bd1eab1339a41c98e8abb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"c3425235ff51b5af0a70152462b7a3a528dcdec4ccffc6bbacd8b79b2b989f3d2465050a09253b6938347dbbaa","nonce":"45bd1eab1339a41c98e8ab8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"24fd14486217ee2c543fdd5a8b1e7c2faf2b6fe859af44aabd497411b36cfbe867e595d8069d866cd9dddbb300","nonce":"45bd1eab1339a41c98e8ab8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"c60a4948321fde4a3f10e92f5ee97745e7456ddec8398467cea2954dd39a2d663fcc4202070636956c9c164456","nonce":"45bd1eab1339a41c98e8ab8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"c677a89f39000677777ddd4f61233cd4bf0f79fdd61b02007e5543d6296567cd2f1ca860acf28a8c6edfc5d88e","nonce":"45bd1eab1339a41c98e8ab8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"e43f4682909204d525ead5f17d0a06d6003082dc15ba0c582a5b34b1c5173e868c04cbe936cb886c68cdfb9391","nonce":"45bd1eab1339a41c98e8ab8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"65cfff13bfd3c04522f9ad077b1dc0c45f0779d80982b077c39a4b90c4eb22761322d2f6fa79c7df8a10955e17","nonce":"45bd1eab1339a41c98e8ab8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"fb862c4b6d274850e17cd3766898977c3f3f48631a8c12b08f4d0afe774eeabb75a68875e3438bcbbdc1591530","nonce":"45bd1eab1339a41c98e8ab89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"067d6ebf6354b69eab5cb994e9fcbdca555b69aa51c0dbdbdfcecd241dc581178f99bb11429e78879cf4ffdb05","nonce":"45bd1eab1339a41c98e8ab88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"0d9d8967a0e04ddf7dc689a72e3c20006bb58b9abe5b3b19e712d1fb92cd66be3dc35d20513b5ff8e14040f7af","nonce":"45bd1eab1339a41c98e8ab87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"b201eecfe77fdbc148a192c972a2a4c35cf4320c9c00609dfc10545788ab18845714115672c3a7280ded1b8ebd","nonce":"45bd1eab1339a41c98e8ab86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"a3a49facedaa7531c73e593037fcccb865e43b2afdf6be3df57810488fcb26b960fb40cb7ab21cbfc999c73c9e","nonce":"45bd1eab1339a41c98e8ab85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"758f928c346a8fe00e702541fc4f52c0ff6ff57618713dca9f98459b1def4c61aa6bf9eea7818914e60b823de6","nonce":"45bd1eab1339a41c98e8ab84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"6653a9d4ef4e8cc1ab2adac3679fffdf5b870fe4eab71a40df82705b8101b3c948497874ec4f9a01896e75228a","nonce":"45bd1eab1339a41c98e8ab83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"13293efffa5d7209dbbf3c8e3e32f16d51e4eda2a1afd48aa796b888523d31f10c6747d58405b79ace73d3d0db","nonce":"45bd1eab1339a41c98e8ab82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"d23dfc149cdfbf1fff57e8bf89f0c28881ead26baae2f94b70fa7d26b32cc165ab6a93da0303795b3cb539d7de","nonce":"45bd1eab1339a41c98e8ab81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"228caa21ea355172b77aa05afe18e0803ab530bb755fe088b5e3f8c26f0b0c88473bc1c4da0a7d058a22d1bb54","nonce":"45bd1eab1339a41c98e8ab80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"5381a70f8ae19901821ab07516267aa7bf0b2e0a55303ac4d8a22f539d36608e6bd1f7c7425583b35614470851","nonce":"45bd1eab1339a41c98e8ab9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"745d84229a9595013835d321a0b47bf2b9663c15124af147b4fbeb925944e97d0e62ed08df98463ac590d73602","nonce":"45bd1eab1339a41c98e8ab9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"f85d3cf065d5702e45f4788b9420f0588ee53ac8a1ed9bb98880b4bd6f350cb5907116aa6a06af57d72f3dd170","nonce":"45bd1eab1339a41c98e8ab9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"b4b72aa366546377a02199050334a49784843274e14ef4901ccb2360ac6aa0d31ec6ebeee8671cae4a34c702bd","nonce":"45bd1eab1339a41c98e8ab9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"33ea0204e582824891df330492524267a7e44d820546610fa4c2af760feb1ec7ec9cae880b88acd52f44c8025f","nonce":"45bd1eab1339a41c98e8ab9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"fbc17d2f2ca6fa0fc58d152bdc7adf841947b7e072947fc4f165a2524076923321bb507014c8bb14c383c639ab","nonce":"45bd1eab1339a41c98e8ab9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"f599cdadade3b573472bd57acfeacc7cb147e4a2410642c91356b11c7289bd8928c185a9e911fc83fa5bfb7351","nonce":"45bd1eab1339a41c98e8ab99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"74e08193e6edcae445e9780e3da47b6a619f88e0ef7e58908fddef9acf2c6e06741300ae143861cbcf438fd7c1","nonce":"45bd1eab1339a41c98e8ab98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"d2dab31202c3060789e0a2bd52c9338e00531383d512f536392090be1067f83b89a3b6e5a68033dc15cbc94dd4","nonce":"45bd1eab1339a41c98e8ab97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"7876916a9f27de7f45c33ef25179ed15284c09f584260129a7aea4c1a6e87efe4958fea3586873cc463385a426","nonce":"45bd1eab1339a41c98e8ab96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"457089af13b40f40f9c533ec845e6e5d8fdbb60ee1e12126d5731dbbb4eee957451bcbd45e7e4e0eb1f1fc80dc","nonce":"45bd1eab1339a41c98e8ab95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"e75dd43d1a11b3fd4a16f09c88e69776f06aa42e06fc460a032409ecaa991df658a8ea9d20c585083ed1556b63","nonce":"45bd1eab1339a41c98e8ab94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"e5a12f64e8dc3b2e049edf25da8a545ae37db932b0bae75f0bbf03adc920557a0b70d99d408206e2334e3ae8d2","nonce":"45bd1eab1339a41c98e8ab93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"f020a1e7a4102682d39a2f83d0f253d3a1699368eecfd1cd73d6982248e08a1a7f0cee479f35b18ca9eab17a79","nonce":"45bd1eab1339a41c98e8ab92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"7cb42ecddc4c1f157eff88d0013d2553de8f8510f64ed7d292a95d5aa116cf01b40bbb5c0ade0abdb7c8d0ece4","nonce":"45bd1eab1339a41c98e8ab91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"df65d54f166656a9aa22b297a005b456b4b3d2f8b8ffe03afafff00b610fb5c3d99455bce0dc9ec6b645f51ee6","nonce":"45bd1eab1339a41c98e8ab90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"328f649fa1f293f87f5cf1d0ae910d1fdd76531cb7c0aab11f46bfd7c05713b0e842ad1768806e07b75ef62957","nonce":"45bd1eab1339a41c98e8aa6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"45a84f597675986214c6c7e3f3881c4ff7d98a5c0d7384ff484512db1043be07"},{"exporter_context":"00","L":32,"exported_value":"bd238dc844ddfa27ca8eb729d6f5b9058edbf74d0f1baa822c34603e39539815"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"7f118aff1dcde9bb5a407a724042b96cbfdc240c041a887017af13b7a82df807"}]},{"mode":0,"kem_id":33,"kdf_id":1,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"d4c5729fe4a64bd241e16b9b906f4982aac06b378d65d6066cf8763de9ff386adef5681292b948216e3963843ce2ea55fb2027a962a09b82","ikmE":"fa48c663d8bc31fdc8856fb4e8f20d680c1bd8d15520ad0342b7fc512bb11182ade542cbf270309be617fe2889c1d2a8aed92e8ec27d4a83","skRm":"ef0df1441d2fedaa2e0cb13bcd8966e0d8fe3b68c84a89e29ac40d486646c48fe09c170dfa713e34ff05c39f563f27769ecca9f6bb3b7f0e","skEm":"1c8f9d12e532690f90d630d8db5b330ffb580bc54a5db72882a2f03b16b7fdcc7eb3f423966c67c93b83903cc211bf86071713a4422461a5","pkRm":"d0d68f88870ca1cf6be69964fff53c60b6316c31933c658e378b454d240d4050e39f336e82204df4f38a8eb8aa33e923bc1931a3605a5273","pkEm":"330b51c7a7881d8d663b7ff719717d2720d3a1f821100502058dc5f84ad08c7937f99e113c98a448e60ee057cc22929838e885889a4ea922","enc":"330b51c7a7881d8d663b7ff719717d2720d3a1f821100502058dc5f84ad08c7937f99e113c98a448e60ee057cc22929838e885889a4ea922","shared_secret":"80fe921b0df45ec93d49eb293411289ee75e8bd4e6ac1055d16c7393a823e98dd2f8436aa7d073594098462434668b6ea98098e7c2c07131d4747ebfdcdb2026","key_schedule_context":"00501f6956afc1d37028100b38a48efe15d0352c7da3bfecd089af8d3f55c7171387399003157c2bc488b6f17e65efdb0a55ebff5dd99ed2ce3d97d3473e69c23c","secret":"d582f481fe7f069c6687e4f5b1cfe76b2ec064499d754af2069f95538724fbc3","key":"53b93310f274730b56fddb5bd6a9317f2191f9946b0089b1fcdcf680831d1117","base_nonce":"3cd04c6be752c00570352e1b","exporter_secret":"5cb4ec40cf24e8fc9c18e32c67c89c721619d938a00f770cb83e13ad182a0f11","encryptions":[{"aad":"436f756e742d30","ciphertext":"aaf38491d54def4967dee5c73a0521ca3df437ec7db6493e31b070ed8f07173769f80ea9083a9e05d1bcb6efc2","nonce":"3cd04c6be752c00570352e1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"f0ec5520485703491e7fe5b52ee938edb03f9ce9ea9853caab4f4319cb143f42fb5d681ef98ae7fccafa349fff","nonce":"3cd04c6be752c00570352e1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"54eb8b12381a1897c25ce592d08617b400cca0148b57deca572e63edf226225e1ee096c33d1b56e7d115ce55ea","nonce":"3cd04c6be752c00570352e19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"ae71246aa92e2ec91783c18305d856dc812da7b5b14bc1acb83fd4e4ff9d8ac3a4480bda55e7b57940abbaf857","nonce":"3cd04c6be752c00570352e18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"bc0c783d9251a8ee53c68403a56267a51b9324a2c35fb4332943e8ddb37b4e1850816ef8e05215d2db8648dfaf","nonce":"3cd04c6be752c00570352e1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"fb610d36a717cec4d5d39320d0a7b58596c500aeffb4b3c25a224ca4262848f0c9e63c53e2f2549a4e610750ad","nonce":"3cd04c6be752c00570352e1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"4558aeefbab54139b2f07099ee958e150109231d416cc5d99047aabce494842f89ca625f98490a6df3e2b3b9c3","nonce":"3cd04c6be752c00570352e1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"ebaec5601292fc0c6d7d8246bda8354bc183dd3f6684d57f378354b1d0269c32bf1058716b3a082e7ceb9f3757","nonce":"3cd04c6be752c00570352e1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"dd5dec36d93f5deddf77d852afb7f604ed8dc4251ab6491df277bd104b7c3a166ef0998619d5ab59f805108f98","nonce":"3cd04c6be752c00570352e13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"598a38589c844a9e43581de4af46168f981502a9c290f7fee3210d34b4822e3d8be6846afaf1784c5bf399ae54","nonce":"3cd04c6be752c00570352e12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"cb89582fb54c29f36d734b8404745632dc90ec5a621c3d0f29576b8a2d55a44fb5dfd41388b78f562a10194eeb","nonce":"3cd04c6be752c00570352e11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"0ebbb82140af8c2251b588b4016ada734551102dab7758a2330450bb855692179c3cd4ee6c103e1744285b21cf","nonce":"3cd04c6be752c00570352e10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"6c6c4e898fd119a5bab03f965569cd47b204775e35dda92a8da3a24ab1a7c69ce4c2d88cc2d78dd88b40a6f1c6","nonce":"3cd04c6be752c00570352e17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"0d254beb1c60a2003b674785b13768f78a59fabf63867d9dfa76dfa110d383d024c233d8d8f9baab52aa49eedb","nonce":"3cd04c6be752c00570352e16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"718980ec901996b809ebef36e72955e76ecba6691460419d042235fdf3a7a062a7910905c2e4c9fbfbb04d334f","nonce":"3cd04c6be752c00570352e15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"e4852cce1a8a53d158045b9453ecec091d36184030c917cd2316876409d3f4a84940657abb7c88615bc3dd7aa7","nonce":"3cd04c6be752c00570352e14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"e907fdc8f91847f1ae3f64e88647954e80f505cb5ab06dfeeb6c3d28d5c0b329f0a63fe2a9ef2b697fd1f2815a","nonce":"3cd04c6be752c00570352e0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"7a70682c5a354956d276a5514390c21fc6353045f01e99b2949e1df80a9aa1842fa1b5ee9341705ff538bf21c9","nonce":"3cd04c6be752c00570352e0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"35d540f707e7b86d9e4e37e9e6cd2947b2c116c38f5566c8be14e86c110ba047c536655d25f51ea7664398cdd1","nonce":"3cd04c6be752c00570352e09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"8043581a31773557a3964696f70590b64b0b297147a719ccc3802b74b9311a35c61fd204ade1f832cfa8abf4eb","nonce":"3cd04c6be752c00570352e08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"7253e4078ebce8e678b41fea06fcf708b1fb87f0d08d2c5d47db89e7290b2e872c1ffd7902173834f38d9bf707","nonce":"3cd04c6be752c00570352e0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"90ab1d98af615231358e852a292150bb46eb353e21dd6a7f63e56c5bab47c016dd6445c7c77fa64cd40337adc8","nonce":"3cd04c6be752c00570352e0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"4c7e75ddaa04a8ad0deffa923f7d4620a5325daee58a9e7b1563aa2c618bf5a3deb337b41df26c6ad456b67a48","nonce":"3cd04c6be752c00570352e0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"86efd1cff739af841ba50b095ce0713f52d2b7153317546f3d4af68708e7a4e912023e34c5f4a18aa713e63e94","nonce":"3cd04c6be752c00570352e0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"ad6a038ebca8dee1eab8f7daefcf75456737e14ae238e2aff0e97ff32c6d15bb11fa6b824ba49705d96f42da18","nonce":"3cd04c6be752c00570352e03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"3ccc82c1284f0762120abe5594a18ee64226ebe273976860e6e37270d760b8e88a04052766f18366d68f1cc990","nonce":"3cd04c6be752c00570352e02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"2e95edc1dc16854cb7dd0fbbb49c68308fb995718a2e6e49d57b408ae4d187e786ec547c62abafe9e56f082233","nonce":"3cd04c6be752c00570352e01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"dcc4b5b69c62dea5f58b29e4ef879a121438d10240eef16d05ecd98785901ed7421b22113178b99bc221acfac4","nonce":"3cd04c6be752c00570352e00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"e7ae22c9767b2906c0fab087b93f2d18329c918a96aa204ef2ece9a999f5ac30c80376f2d910ba767409633fc1","nonce":"3cd04c6be752c00570352e07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"2a28c54c568d5f6651e50bffad6c7fa103c64064d14bd792fceba486ddd0fb3e5ba24d5e7cb6059d6de0280877","nonce":"3cd04c6be752c00570352e06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"277b81c8ede239ed60ec1e85a38527b856d220930f269ea52a2264d9c5ead5f5090fe9afedb6bb4f39640f79bb","nonce":"3cd04c6be752c00570352e05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"dd9d8c2abd24fafef14970c35cdf2f91a17e9e36450efb878e40e58907722de80008728a5c21ec6b4617ef3d77","nonce":"3cd04c6be752c00570352e04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"38d6e767f9e13786dfca923a809f1f16e7dcbdbb9a05291345051e7cb763216bc3d0b60b548258f028bebeb57b","nonce":"3cd04c6be752c00570352e3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"9ff809e9b28bbc53642db83d18f2342cf876d9319fb90431d56a1748ae90e2af2e2addb51881919bdc84a8ac59","nonce":"3cd04c6be752c00570352e3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"fbfe958fe81a131b29fdfe74919d9ea11c7f1efd8d4292eeb655f86fe279492b011a478c1e705528c36b377dd7","nonce":"3cd04c6be752c00570352e39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"54333aba1f757bec5f7e949e9f1cd618fb5c3f400cdc82b87fb710bfd26c5a9d151a3f66244ff0ed28da05933d","nonce":"3cd04c6be752c00570352e38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"a65b1b9b1fc263a983164ebc9d550bf57ef0c74618f0ae0ec905677717b810dff0265c128e0b68099383aa5b91","nonce":"3cd04c6be752c00570352e3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"dd58cc87c5b2a89fc998cd7ef1191447e52c3474cfb07669dd0d1c54e4d87933fb6357a94e2989241d830f0981","nonce":"3cd04c6be752c00570352e3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"7f5024302a2c03518a9b35a27e1af4b3c4b9439e16450e994c97b4f52a0d09f6b56375a40250f384439cfe075c","nonce":"3cd04c6be752c00570352e3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"3aef3a7dc27ea3fdbb35a779a6159eac2600e39df1434df6bea92789a32001f99b5da3d9d7f8312132269c600e","nonce":"3cd04c6be752c00570352e3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"77b52aeafb9f548a77137fb1d2e8346e29409b0eb831fdda7ffaba78bcb736d6669276a4d7c9941c04f2cf1358","nonce":"3cd04c6be752c00570352e33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"96a7d9ee72c659f4352d396ddbdf93ed267054611d7d2955c472307f342b3aae726f2f7bdc56fa3657020eb375","nonce":"3cd04c6be752c00570352e32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"43e557376006513388980298bc34d8adce05fd84d6c65bd1c2e58580e5036d7aa1cdedfc284e8eeef837800092","nonce":"3cd04c6be752c00570352e31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"f490b8a0f7e62c28d40ac22c83cae6c89cc0440b0725f8eb8232dc2c8836c571c26a2c79dc779e5b35a75336e1","nonce":"3cd04c6be752c00570352e30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"9f86db1262a26a8d190e6eab71b26e0691737f94d9955d5f83fe2854882f586b6388f555625ef3a36ba1de777d","nonce":"3cd04c6be752c00570352e37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"25d4afbc66a70504470ee951da3406e4b6fe94ea739089b4ddaee8c6fd955899b5482de869b5efda9274318641","nonce":"3cd04c6be752c00570352e36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"765776beff8cb816b2803ab534d491870f3245a49fd2f00acd3c3a58fc4c2ec8d311694fa3c123d6e1eab6a9f5","nonce":"3cd04c6be752c00570352e35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"14db68a5d41d1a628f5b35594250cf72f6e26728b9a0aecbc2ddb4b73d5adc8ab999157f5c1878be8a57b867f9","nonce":"3cd04c6be752c00570352e34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"89c1e7eaf5557352182dfe1d5d29c1fd6a9b4397d7eafc8451c0623117d053bcec2193a8176b2a28328019b016","nonce":"3cd04c6be752c00570352e2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"82135703ed0340c1632613e050699111fdcef56a7a4455d3521877a557e955040f2115856830e26a4a2fe62dd6","nonce":"3cd04c6be752c00570352e2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"d9d706e55606895e9f9ee5a3ea2fb2e48a772dddd3084c13fcc1a446f7c5a937e0bcd1984f1834b71e7b7931f8","nonce":"3cd04c6be752c00570352e29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"f05950d1ade1667b66f9d25da92fb786b3fcdb3d7bfe5b8ca6c0a250bff13655aebe79288d25943db66f1610e0","nonce":"3cd04c6be752c00570352e28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"da0f2f2897d7c203b4ea046ef4cc8ba8b574945b9191b38720576e75546d88624e3f8b16f38002aeacd8d48e93","nonce":"3cd04c6be752c00570352e2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"99da4114c7306757e1fcd5ce4644cb72f40c26fd8c2cd58b34c397483307778d8d4e9dbc6b225a90bb1b8ee142","nonce":"3cd04c6be752c00570352e2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"0454a2bc8923d5bc4efa6f0dfbbc710fae729850659294580a7b48b37a77d35f8a7ec5aaaa1714e1dfd525df2e","nonce":"3cd04c6be752c00570352e2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"81437a69a0ffca3bf87f458b923270295f4ce7095f0eefb6109819855bf288f919f8021bb19ea3d62b86aa3585","nonce":"3cd04c6be752c00570352e2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"dbbc7b97a35841ea5c14cfd0405151f72a8fbe5df67b1fd6b4de1e138b30c861f30d3593836e36220d1e05b51f","nonce":"3cd04c6be752c00570352e23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"7b69e07a571afbbb23cf6e24451021b2d6900b0441c014b17c03d26dbb4b753f213f845e69db85d5c904b79a86","nonce":"3cd04c6be752c00570352e22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"3e0b0e78915ab78f47c307b881601678d431948538d54e7ad0754d94bc00cc1d307acd08274f8a04c24302351b","nonce":"3cd04c6be752c00570352e21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"b19505ac71b6551ce50a5827ffb9cc6f3ef02269c0ae5f4b0bc9409333bbd6329cb9308ffeafd57f3a568105a5","nonce":"3cd04c6be752c00570352e20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"35f89d9614f9dc37410439fbae67558720c8b3dc7c013594ac0438fd19718f74fe3d14ab419dcaf70dbe927f17","nonce":"3cd04c6be752c00570352e27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"386b9ed2cab5181e3c153eedc132fc65d861038426ad30d01c1e77edf34cd72d68e405e5b4b69b94be73ee091e","nonce":"3cd04c6be752c00570352e26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"5d52a87605a153ad9817204c09aa2a4722ee2b6d949efca2aee14c5d54794ab9943f51709e3e3e25fc8249ae0b","nonce":"3cd04c6be752c00570352e25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"d77bb66c15974882cf9d61964e3dd2522be729058a0290f12ca6b8cd2ba49157f1513ec4e6a45167c1a6724abb","nonce":"3cd04c6be752c00570352e24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"f9d5347230f0ed3bcb783838c8961966c3a094025b3d3e93b1b0f3065dd6b2c76b7d16fd8eb989400574037b9d","nonce":"3cd04c6be752c00570352e5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"173f2759991d49aeab6a08a149f214e230c657ffc16dbf62b339609c2504da13b928e1e6adfe6f88a3a97bd537","nonce":"3cd04c6be752c00570352e5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"15e861cf3e27a89eb5bff46b707e29d17449536b2202ef3311248e50514da5e85d042763099877a74b3bfe9b94","nonce":"3cd04c6be752c00570352e59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"58909239dcbb073200544b8a0e8fd2bacda32c553a573f5a12706345fbc68157f3fd5a8f022d9174117537373b","nonce":"3cd04c6be752c00570352e58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"0399bee1aee49013456d1a979c193624bb24288fa19e6fbba24544eb12fed63a02634fdf6fb233f2756dc7ab41","nonce":"3cd04c6be752c00570352e5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"4dfb9ee60de93a491cb196105e16b8330c2e367d8a95c00fde5d82145506667793921c1c5fbb4fd23dacd87e6f","nonce":"3cd04c6be752c00570352e5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"051301dcb24448abdf09b598d5dd9fe371bb2d9595ce22064ca5cff21945d8440dd472eebfe5c470b4f25383c7","nonce":"3cd04c6be752c00570352e5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"394423c83461af3b7a5d85b364986659cb8d38cae90bacf9a4c59453ccfb52f5393f5d3e27a17cf0d0ac27e3ce","nonce":"3cd04c6be752c00570352e5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"b1bc320f648af1dc4d8e99bb693c241c824f7845f0d2a5156eef9901d98dfc76e6379c80796bca4e5b3d4c5f07","nonce":"3cd04c6be752c00570352e53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"04caf2850d17c5f26af0fd1bc2779f57d94ba5e55add8d0134a4ba923b7ffca6ed6e97d7a89b1aa93e278fd57f","nonce":"3cd04c6be752c00570352e52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"203e59146f1a3bc02f49ced185112e2e85603048156e06740a0f315591aa0db55672df80a5025952d0a1392af5","nonce":"3cd04c6be752c00570352e51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"19e40a870e51d0ab1cdf6cb4352a10732a66f57e40a1198053248f7c8e44ef9f24018af91ef313615ef12bbc3c","nonce":"3cd04c6be752c00570352e50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"36a307340d686bc9edc8b84a58beae70375487db1bd6b036d0e65b73d9ff8c273074c0abddb2a6837ad439ebfd","nonce":"3cd04c6be752c00570352e57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"419921e330f127a579137b57fd3024becce745113e46817a48d359b541622ebd38d931ee0c3ca838b87a849d8f","nonce":"3cd04c6be752c00570352e56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"f87fbd27a24791430e9c46943261bc1129eb2e9548b5be859eb69316c330e703627e948db3801d071020458f22","nonce":"3cd04c6be752c00570352e55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"4f8f3dddb57a2bbe9ab4c95c6a16a3f8520756ee8e4615e9b5dd46291e918a8d4ce410ed2a0f50e1c05e3877fb","nonce":"3cd04c6be752c00570352e54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"2359c0d381c15dff08d3e814f8366208009da6f01bc2bda4c9e6109597537c1b3bf71ea9c5e7a46fff94aae9c8","nonce":"3cd04c6be752c00570352e4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"3e040c3f54392285a8533ae1c368fd4766e39f276b3a63e22431f5ac8a5789b78d13dbfb0686aab01fcb151425","nonce":"3cd04c6be752c00570352e4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"801e1ae7c2d9dd38d93ee3cfadf00ef930f1ca583d2d11fd1a9f2918a555df48270235a701a88f7acfb3e9b023","nonce":"3cd04c6be752c00570352e49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"d5b89564b0a741276b2e95d69aefb2571f89c173017de97ddb989fdba43c8aa8afa2ed6853411838a560e1ec59","nonce":"3cd04c6be752c00570352e48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"a82b43a89f2a8a9a493e4754c00209a9cb3a9cc6eb1879f988ae6a1ed1521f132d46299791095a267a716a3211","nonce":"3cd04c6be752c00570352e4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"d8d8aeb58ad9a4bdb272b9df4f15b805d32ef74099555b0f32c4d151820454064871c909e5ebb3d1a5f0481298","nonce":"3cd04c6be752c00570352e4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"4e0d055d4e2e1b52ac955a6e236107eaf718c2f450a825b96778ff59845c734710282b4a3aac21ac4e5473da26","nonce":"3cd04c6be752c00570352e4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"a0080a39fab89a8637ab13498dc7657a07bab0d395fc8a1c035d06e72773168e20b521c4feefc4003cf63bbb58","nonce":"3cd04c6be752c00570352e4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"057d149bc4278c472b2fab5e7abda573ac6454d7e7ae1daf2cb544b8c4d41790b6cf2407fb8387892046c5a99b","nonce":"3cd04c6be752c00570352e43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"c146451aa1799cb4abf31d87e55d74bef449e41a88dc9ad39d53c7240dd028fff03f2126e05fc4a37220bd876c","nonce":"3cd04c6be752c00570352e42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"b1ea32b4e24bf6f790ee4412ad4fa4a16badb748a5c2c8033566b969682ccf00f7972af511f3d44dcbae9261ce","nonce":"3cd04c6be752c00570352e41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"f55adc47eeef7ac8a8c2d0448d6b82411c44fa9ebfe726d22dcefa2aa467a61d8d72fad5c940dedc8bb666e52a","nonce":"3cd04c6be752c00570352e40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"c25f87ff4b5a71acb1c87c28ae75d538486ffbd486b7525134898ee9c90d7ff91ed4aa98f8cf1b5205b1e1567f","nonce":"3cd04c6be752c00570352e47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"0ccc6e06f45e690ecf81a1a8fe1a76462a08cd4582885b620a398c2297f901740bbee137094f8a72e56f913a5d","nonce":"3cd04c6be752c00570352e46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"ce7a3fc6026679efacc79648e4fad3679c605bd3f1c0c2269795e50be00dd1324de5c23b2193e2add97c1275b8","nonce":"3cd04c6be752c00570352e45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"1f91547711b193255bb11c883c230966fded86a57755376404a35fea06e7e5645e0d49c8bbf0b9a6640b8ede14","nonce":"3cd04c6be752c00570352e44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"9d13c1ed6113c94f8b1874631ba86f9c2be2555df501fb084388a3b13e73aa5e71831f1b6d334ad30b24bb95a1","nonce":"3cd04c6be752c00570352e7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"1714706dea4f7d3a33021d0fd1bcafd4fcd3dc6b8c9fea72330639b064759537406cb3882687921f18f7c19619","nonce":"3cd04c6be752c00570352e7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"a7901167b9004161aa7734b39d68e31e76db11aecb523a4289c68c57075ec53d1dff30fadc61afa3853d3d0e64","nonce":"3cd04c6be752c00570352e79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"f74dbf59ed4dd087b8c0dc3111f02eacd1d6c60d6a5ae6ea3031de86a3d99fbebf50d654e3908154b99c87b793","nonce":"3cd04c6be752c00570352e78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"c92bdc4263aa658599171417681c8cf5266252ceddb9710ed40b034343482b7925a1633c7a66856343371fc171","nonce":"3cd04c6be752c00570352e7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"9a23bca3cd8e6c13c09db9bdea985a3f45f9b52027f43b626c21c19ac46420cfd8bf2e8be71d279b53bd31601b","nonce":"3cd04c6be752c00570352e7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"1ca071ae8771e7e419db5e0783efccb5495a99609f692a6098ad6e227ebb0dce9a1fe316d9b71ae5e4fc61f0de","nonce":"3cd04c6be752c00570352e7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"5c23d9f7c0595ab33d08a679711c93fa08481aa57bf0529ad29ec972baed046fbc37833aa55aab123ab1900847","nonce":"3cd04c6be752c00570352e7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"2e2338fd85fe372caf89e0e083d2303e6382e5348e32ec801ba90c1f1735849886403a3c54d36e219779d4034c","nonce":"3cd04c6be752c00570352e73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"b3e3a1f15526fca85cebcfbf65c8755cb8d1c425707baedbab8a70dbc47bfc9b0c410597909f66d295d908d719","nonce":"3cd04c6be752c00570352e72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"bc61345dd618003eb16466b0d4b94dc3e8fdc27a65e5d85d6760b3c6a3f00a6f0beca3ca98373b17bd7d383cce","nonce":"3cd04c6be752c00570352e71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"13307a6337ec4e1a86d1fe13e7ef095ffe29bac5299e7e474a21c28b5bca792eb0a4cf30852f062bff97f7d563","nonce":"3cd04c6be752c00570352e70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"a53c93c4a7a02df3d2233bc2a4be44f97e752f3a55f99b2baaf249f710959d3ab4e6d5d25e2f35a40ed7af4247","nonce":"3cd04c6be752c00570352e77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"bc1f8bec940b68565df4d0a8c369d05f3798d035637177755ff0b6f8bb4bf16cecdd7ca649bb5cf58f04ebb511","nonce":"3cd04c6be752c00570352e76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"4e41b65c771e8ace3b9574c1155f57629a8a1c9610f1d7d3e9b2977c93f68afd3b19958bb7f376c7b45d2be65d","nonce":"3cd04c6be752c00570352e75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"2766a8477beb472a2482d028a0ae446947fcc124d10a5e6f4ad42d0ae5fe75f37afc235658e8fd9d7142ab2fd5","nonce":"3cd04c6be752c00570352e74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"97cf9e5bf94d19a330b6161e01a37180f0cf0cbbd1e81eb4c97505d81e6baff7ac88a77ed86dc11b4536b6765a","nonce":"3cd04c6be752c00570352e6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"7292c9d59555f7498d12894c06f17599b2537b7da705cca39ed1e1b4c0f7f06a0897f846f245c2b7e9e4574932","nonce":"3cd04c6be752c00570352e6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"c7eb4a2ecf9e35f42ecdce1e722c579af1dd35a8fadeddc27ce8580766930b3ee534e4ec73538cb0ac5d30e235","nonce":"3cd04c6be752c00570352e69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"f1c7ff71fa802b5b3f9279a1c51f2e791c4c3743f1f88c1ba4dcb0cc604afb24c5ba12cc1a4dd9aeadcfceff1c","nonce":"3cd04c6be752c00570352e68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"8977cc78ad379d48df9858773073d53d0e05c86591eb53c3ce64e0e32e1915551f89987b0d0fc6e59362fac09e","nonce":"3cd04c6be752c00570352e6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"82e426cbdb81d3e79d558f950a7af55290b45dbc870e42bebf133022c66262e0a69586288573db3137bbba5219","nonce":"3cd04c6be752c00570352e6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"a3d39304adb106659b145a02954fa4a9077b54e812f3c28c562f7a1d7dc44dc88bc07a752068e6265e5bbfa040","nonce":"3cd04c6be752c00570352e6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"604c5e5ca0c84d5af6c6071e9310e2b8db1baf6bd1d9402b7e729d3bd1eae4fd10af34b1b4227a9c1f758d8d46","nonce":"3cd04c6be752c00570352e6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"c7369f08ba95d3410a56beb56e3e7376e4060c4a0cb91e2e11668c8319308ddead26bec9778f1f13c78a26afb9","nonce":"3cd04c6be752c00570352e63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"55b1bc455dc0501d297db75457e58ef07972973883508afd7d711d9b72b26f7e65ee31cb65b20e0b9c7b7e2ba4","nonce":"3cd04c6be752c00570352e62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"b55599b026789de7553851d3eeb3640963460f174b3b2d4c4994671ffd4d867bda65d26b7f2af1b122da5d6a57","nonce":"3cd04c6be752c00570352e61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"6a9a72f87e3561703d7969bd9e48834f0208a670a73d115e149da1f624cea6d7980d0db5e21c3becedd97b7e33","nonce":"3cd04c6be752c00570352e60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"81bb88998e356d46fa34a2f2f1fd4c4a0d4b9437e2cfa896c8c38852bd5b49d3e36edc9ba3362e9dfc7d5b01d4","nonce":"3cd04c6be752c00570352e67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"90ba59723d02924abc0b3e2669c8b8829b95889b5ea35c742a90397517573f04f986673c1432e3f68888a1e9bf","nonce":"3cd04c6be752c00570352e66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"a77f4586cbb39b22e41d998ea459d27ed81dbe76802cf5f6da5ea8378d7025dc3e850ab15ce7379a2b4b310184","nonce":"3cd04c6be752c00570352e65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"4ceb6fbc6b6fb8e61bfee1586d9e101c0a0eea2d949ba408a6c05b227668933b68402074d3d46dc49a1e45e271","nonce":"3cd04c6be752c00570352e64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"e07a1178a7bd8d299b66379a47679beddebf1292416f39a136203adea6a106b6163952e537372d2b2ed99d6dc1","nonce":"3cd04c6be752c00570352e9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"b249265df9fd18cfea5f9c48dcefde49e814d83ceef3121661ae0d02038caf8046123b081110e50ff20ddb569a","nonce":"3cd04c6be752c00570352e9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"741e8a7167a600d10811a667e7e09f76632f4b9f460b0a664622bf269083eddd99885934587290f7e05b6e9f98","nonce":"3cd04c6be752c00570352e99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"0c19c5f6a604b5a80936dfd9db58a8a0621da6ac90efd30b625a09b7dec2bbcccccf06a7a8ecfffab2d2707721","nonce":"3cd04c6be752c00570352e98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"a3262c400afdeaf0b1770d6cdb02e4f44edf1e8f4a14b0792bcfb127a2d5dd8e513c160d4edb0d85dc554f0d33","nonce":"3cd04c6be752c00570352e9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"bf55bb11d1e5ebbe1ded6251af2f3f09e244116464478435780f43bfa046f3449f85be25ae223d76a34c113ff1","nonce":"3cd04c6be752c00570352e9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"05bdedaa4f9e6c169c71c33a87b78bc89644417731d7299a7e9f61047e3930baea2943be15a613f6ae77c984db","nonce":"3cd04c6be752c00570352e9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"91b787ad2cf45a54376dce0985c6cd702efd1312ddf761536de80d5bc0343a2beb3a5f7057c82113cbebf92409","nonce":"3cd04c6be752c00570352e9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"d3350489bd193c92bcc4f5af73da2410dbf9e8a5f2e7394c7886707745fef93f267fc7c8a2aec9c1d68bf20af8","nonce":"3cd04c6be752c00570352e93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"60dcd703175fe98e5114053f651cc11cbcb7f31d108d045bcffeaabc0a4b8b3f86375844740e6f047bd1f10dca","nonce":"3cd04c6be752c00570352e92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"f13d907b4c331fd037eff4be4c27c9a3533483f62c0788e6b4cbf1fe87715f6b936aefffd3bee6535b4b78e80d","nonce":"3cd04c6be752c00570352e91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"28e320673d055843e286600216b5f1c3f74022bca861a593f40fc0862e90dd774898445a690d750ebe8814aadc","nonce":"3cd04c6be752c00570352e90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"7c47aea8bda693da8fdd5dbd8345bc6ffd82326b62f7d058c68dccc6656d6b9523d1725ad51ac6f6506f0973d2","nonce":"3cd04c6be752c00570352e97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"5deaead8969bc24ec26543bd7d3d233385652cd7e39f1c151a94e9035800b69aad39416e45e6276feddd8940bc","nonce":"3cd04c6be752c00570352e96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"249819f979da893b313015063d056dd0550d32ee0f26095787ddfc2537a662831485991a5937f970330b05f548","nonce":"3cd04c6be752c00570352e95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"960e2b582ae985d02a35fce9ac9567e38700a645071d8c19b9772dc9322c51aabf00c97eed3d483ca1c8f07508","nonce":"3cd04c6be752c00570352e94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"49ae7e35ec8f8b20ae183bc38a56db72109645f9c202a36063378c38a84a2075187ff8af3672a620a9bf6452d5","nonce":"3cd04c6be752c00570352e8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"80593671ae9d0c397af4310eed3340fe47b2c7e9c62a5993509530ba8fda09bf70aa92100ac1c7f2bb8efdf976","nonce":"3cd04c6be752c00570352e8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"33d7e1b1b80977e20bab161dc2f9e8b7dda561b6b235faac00f0907c3c86ad80866165e43d051149746ba9dafb","nonce":"3cd04c6be752c00570352e89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"7f25ea65148f008236e57e9c254744cb99899c45d5ea6c27a283208908168dcb440a069b8cc4f943814b805673","nonce":"3cd04c6be752c00570352e88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"4f33ca0f65b5040c8d623b1c383e85a3d6bfbea5732f5899cc9001fcd06db41cf049ad717e84f87b64779ae010","nonce":"3cd04c6be752c00570352e8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"014fa3aabdf6f94a17dc28ac55eb9e3e0c87f7902bea04fa3d9088e7b35a0d2d14ad84ba3acb0eb7950ca36891","nonce":"3cd04c6be752c00570352e8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"8701e675d306d58365a0bf6cbb31299ef91436ab8e44665003e8f006b123a6463bc7f54b2edc85d8c14a4ac5ac","nonce":"3cd04c6be752c00570352e8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"a39bd2e7253f1625abe77d1d8061a80f3a1ffede730b5bcdb52fda8a60e21392f91eb4723063804001807915e8","nonce":"3cd04c6be752c00570352e8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"9835f265a98a25f5403a317c0c9f0569aca28754a7e8dfa940f3e28575ac03178e7ca7bc218680577edca06bd5","nonce":"3cd04c6be752c00570352e83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"b73f9524a4d8e16d328c55637448c0d30299b38932604804b2bda27f6fdf5a7ba2b64aab4b05f7adef6863d98a","nonce":"3cd04c6be752c00570352e82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"c0f2ef9d8480ffb8b93c24bd38b447a6c6d4c9c59c39115a13d92bd22cc6f40d9986358adaef140c5d51386445","nonce":"3cd04c6be752c00570352e81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"5ae063c6148fa7cfb1a17384371c7b57946e6d2eca009fdb8a600e8ab23db80f29a6e4a7ffb555cfc7ef62a3ff","nonce":"3cd04c6be752c00570352e80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"0af061dea6ed56a977e240c6244ac1ead2c6043f205cbbac8b13af1950523a5787ecbe13508aeda593e30f57fc","nonce":"3cd04c6be752c00570352e87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"ab28455661709c0e65862b1b86fb8269e834c6ba88b0e3210310a822050466a60cf26a2af087b810951e5bedeb","nonce":"3cd04c6be752c00570352e86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"4e92027d9a73708efb63ed1748b3f24b040be73b54d2c8f1d39120390936d57dc55aec1555606fede1902478c9","nonce":"3cd04c6be752c00570352e85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"812834702b38bbee0469320bbe449965ad10d11c3cea93ea8f70def6d1c4248a1245fbe329d137ac80865ff2ec","nonce":"3cd04c6be752c00570352e84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"0849ce376963dbda684d8bd4794d717836b9e56ae1a4a10deebc2562f3e3462887830a34251ca034ec398fb114","nonce":"3cd04c6be752c00570352ebb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"71ab892868c6cb3dad6a8af5ee3d04cc981dfd37dbfccfc784b4f9068feed3472a930c4dcfdf1896ce3d13db78","nonce":"3cd04c6be752c00570352eba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"f1ab0e0b016153a3cf5252fe9c44807064b57d8128496f877083d5cbb7dc738f2fe596ee87fbd5d561d41d90ad","nonce":"3cd04c6be752c00570352eb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"8eead4e05f5ac8732c3b0b47e6dec76fed307ed607585a70b83862c9fe661034d63b6367aa54dd58e03e5ad836","nonce":"3cd04c6be752c00570352eb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"e0bb8ac5ad5488926903ac73c8412d2f4b3de292633bb6111f6be1c4669c706929145bbd680c52b0e5cdd1d96d","nonce":"3cd04c6be752c00570352ebf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"b39daf05194e10a065a64d18e262441e5fc6331ebff52cee78294082c9d0a8e0e9fba23605f2d1dc31a3ce1bcc","nonce":"3cd04c6be752c00570352ebe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"eb3967810ebbe7fde4abf49a90a89240e7b628c0f3461057e8659c668715b880f75502b90a7e3c95877c67feef","nonce":"3cd04c6be752c00570352ebd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"5d650fe19a6607c4332944ad846a73b3ca53a87839a6ebf2e416a1ffdb7ae6044f902b7e56cd1f1486228ec107","nonce":"3cd04c6be752c00570352ebc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"effc293848e91300f8db88534644235ccf8aa12abc4446a5d9e6d63cf1dd23def7aeed90ab5c280396db27984b","nonce":"3cd04c6be752c00570352eb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"df0071fc9434da66276bc5c0895e558b5198b151d50995f479d1214059463225bb7d8d6b7b1379dd19dee64628","nonce":"3cd04c6be752c00570352eb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"85fb2a90428da3aef93762aaf5e4edd9be80a058ac6e16f1fe765ecf38633543c6c1f9a732d62e8d64cdf657ea","nonce":"3cd04c6be752c00570352eb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"bdc10aacd433a8be44240105230fb042632114c624da1aad7e83bf2e91c26dab1e85a2fb4fb2d9b212d50d34a3","nonce":"3cd04c6be752c00570352eb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"11192ce6d92b5a14b983bc695ba890c7c7b81d7c3068ae0e5982e6b78815b2e73a2e3b40466228a52ac6bf31db","nonce":"3cd04c6be752c00570352eb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"686585d08400ffa604d0f1aa08ab24b972c3ec41acdd133ea5d8703f05d3f64e8fd67d94a93be20e70993d3c53","nonce":"3cd04c6be752c00570352eb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"954e79a5a942507bc8b8072d16aa18971934ba7fa09dc0c86440532c966ffe1e238d133ee8e57b9fcbe43e921c","nonce":"3cd04c6be752c00570352eb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"a3084a20fcaa42b99aba694ca7a0072b274c70093fca797c03b3ccf0517be469d3d59cdbdea94f2bf62e0a0f7a","nonce":"3cd04c6be752c00570352eb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"e9b367ce0894890439a834ddaaffbd66263e2e6667ec912bd9f66c414f061723013078e20fbef777905cd33b19","nonce":"3cd04c6be752c00570352eab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"c3ca3b25843976e859ff8ad2e40207233925d131b22b8cc8097332e2898a2cd8986828c4104f57db4ba54344b7","nonce":"3cd04c6be752c00570352eaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"949e26ccc71981f7faa522481a9b586dcb7b272247c039623802e917f25e105640b88fe3561ce90d45f440020a","nonce":"3cd04c6be752c00570352ea9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"c9f5eb7e2b40729b7fed027b500cf4d29c1d08bdb742838a39f96bcac0f1b6ef4cf57e48b472e9c9818c1bbb1f","nonce":"3cd04c6be752c00570352ea8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"2598e41f849b1199dbf82699294074365a0c7b589a577b6b6db57b8ddbe2f5aadc526f4dc8fc28f2f3116768b1","nonce":"3cd04c6be752c00570352eaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"9d63a25177e3f12402b5df9e8c01279cf8d369abdf515877326d3fd9cd4d5ef1f64e4fe4a5c8ad64f7fb3b9064","nonce":"3cd04c6be752c00570352eae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"c18d996a0244a304718817ecf91533ca93b768c408aabd57d543d59ad222670c0791c1952165295755988d4e54","nonce":"3cd04c6be752c00570352ead","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"4e75aa562690519f5536b23fd86f7536d1f1604a5a7235028934f318419c9293e07ae03db02b37af188c50ec3c","nonce":"3cd04c6be752c00570352eac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"9bba3c4f3cc76acd5c4faf28c9ffda9c36856f3f89fc451cd18edf7008dbc8559a63b663436d9181ae37c274d5","nonce":"3cd04c6be752c00570352ea3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"31b18b78aac5d982feca15d50be991a1840bfd38c7f555308811904abb782cfdc255f60a7956f637f0b6bd7021","nonce":"3cd04c6be752c00570352ea2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"d8b98a71292434d97e61968507a508ce731d5417ab5a81c7864dd36a135e35c316d942fdfa6a7f5c738f6de93d","nonce":"3cd04c6be752c00570352ea1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"6a5b82843411a360445faad9fda3ce311e028fdbfe189a54c0b032b13a226e347e2e696bd990ac28fd382b4ab1","nonce":"3cd04c6be752c00570352ea0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"4ade1f3fec7571a91479c0cf2ab3ffaef69f379886eb884540200019cf023089ba4fe8cfd8bb4d00d1b8820a4e","nonce":"3cd04c6be752c00570352ea7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"ed6d1e8b7eee2dc9fc716d5d01fb608e6450ae21684a25e5270498df8c6fdff8ae72ff5ab0c08e66a6f791760a","nonce":"3cd04c6be752c00570352ea6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"7aa91a748ff2b42b26dba266836a1fc068e6c0265b52f7fef606aa9dfbe01d4170204852b72d8d6e744d55683d","nonce":"3cd04c6be752c00570352ea5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"a501df9516be9f132021373e08fc189564a7166499a2d5bf484f468839c58b8120327a8d6f112c96987296b17c","nonce":"3cd04c6be752c00570352ea4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"aa5ef5308f39ad0ea16d8d937916a76bddc934cc0a970c5f50b354864c99e4d5ca2ff12f78523b9ccbcf20fed1","nonce":"3cd04c6be752c00570352edb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"81d6f9a0955b52643c14bad1144161722d7623e4ea705be748664979bde4cc620bef44bf68d053cda681741e81","nonce":"3cd04c6be752c00570352eda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"c4ad4d9f3cca4c5e9c2a6e3c57e2fd9211379ef05db6c886ba666883ec00e418c2357c56a3d7aaa12629a9ddbe","nonce":"3cd04c6be752c00570352ed9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"965dadffe1035b88372bb2db9cfae32efe0beef9ba74fee4ff0d9e1b31157378796e6716c9d86e5b1768c4bd18","nonce":"3cd04c6be752c00570352ed8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"02fcce0567c7cccd27babf29218c2e48bbb01a5906eacb4a45b91559c82d7623b1687a949e7a4be2e5ef53e1f1","nonce":"3cd04c6be752c00570352edf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"39e5e1f0168944e49a624a030de76d611dcb70b99e9f8cf8ccbee227a4115554176582becec089e2b90df9b6fc","nonce":"3cd04c6be752c00570352ede","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"0b9596d20a69a23332cb89b808e86d3557f5f5a01b2ed4e02f7fc1df00a15fe210efe5c408a321739944442041","nonce":"3cd04c6be752c00570352edd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"5bcbc7f7c6ef08a6d20655fdc55dc889f834fa083f214abab4298bd771149f42e1b1f4381ec12d1e4e8f93ea10","nonce":"3cd04c6be752c00570352edc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"9d9fdf614b1eebef598a192276913d3f39d8d554ac49ddd11e7a59b4479f7ce2eaa2bf1e2ce705069512419034","nonce":"3cd04c6be752c00570352ed3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"0324d0e1195b535476dfd9e249e180724098a59a560a1d214f9c6c80fccbd5b59bb747b5f7d008fcf30ac12e89","nonce":"3cd04c6be752c00570352ed2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"54045bd3a4335b1b094557d874fbe35c511d1d6c6e622dad57a89eaadb78340d8450df19ae01e2897e631f9753","nonce":"3cd04c6be752c00570352ed1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"0edc435a18f86732493570f09e3d8a4d861d32badb8f1980059a8018e22a9a4df8eaf156dc1caf3e638712d7c5","nonce":"3cd04c6be752c00570352ed0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"0e4ab30ed734d60957fe3f17ecce609c2ff558df90878a4d35aa9ee538c3b55b680e5e4eb560f2bc263fb2b84f","nonce":"3cd04c6be752c00570352ed7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"1fbdce525fcba695d28666b477f43037cf8b172c06dd4688cc7085ca24407dc8874a3a1f4d03a6a8031733129c","nonce":"3cd04c6be752c00570352ed6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"db06d7a585e16e1c79b5477da77f20a696b3ce048c5cea59c4aae50c2d31e5316690f73bc7ab87c317f46fad24","nonce":"3cd04c6be752c00570352ed5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"85b0935365367fdf4e5cf54a0aa1c72120529de59c894d840089f6840a80ddd6bafbdc1b2ecaa53ef4725ccc4d","nonce":"3cd04c6be752c00570352ed4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"1aa89a89929474a13372620de6205447d445396ab5f9ec738a4290a914c3bad59b58b76dbc2858e799aecbe846","nonce":"3cd04c6be752c00570352ecb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"165d3dfd0cec68238d73a95e667a891d06c28f004fe03722e8ecada7696a4c318bebcb72fb4f33e6125c8135b7","nonce":"3cd04c6be752c00570352eca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"b27b73cfc960a912e5cf5767668a63d81d07b554e6fca1a33c9a9558b3abe77ed1287db3bc7a8542a1bd9e8035","nonce":"3cd04c6be752c00570352ec9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"bbbda53817a18aca043601b2eca673dca481bda00ea20b0d5de61aed63e838344909e71f058e10d0432ceda047","nonce":"3cd04c6be752c00570352ec8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"c575ebc924f5915cc24ed44ca0ee95f11b1acc5d6937de42c8412fcb0c7f5d33071882e253e781f847da9758cf","nonce":"3cd04c6be752c00570352ecf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"b906e93cb8a9718f0e4ab6ffe4821324b0aab8ae0a7dec28a0076bc9ef46064a7818e3cd5aaa631407f135854f","nonce":"3cd04c6be752c00570352ece","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"2ffd491ead27b8f74fb5d4ab40a9ca62df46644331a93764219375c615224459e4512ff00a30beb30447b94d58","nonce":"3cd04c6be752c00570352ecd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"15ad1d5bf148e98132bb6a7eea851ba4234ed2588077a84e8334bec88d55714e5947025c64ae59c62320c8de1e","nonce":"3cd04c6be752c00570352ecc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"0242b1009755494d374ea90be1cc6110d3b8400583783d8e5c9862543cc8cb8e9588f63c2c1a8f23d00b4f5917","nonce":"3cd04c6be752c00570352ec3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"e185bcbfb5f3887b9fcec3ffc4cc1f4505506e831af38c12ea61023870b68d42fce1ec1c9c1738f5e7a6267e35","nonce":"3cd04c6be752c00570352ec2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"e92e134f902d1bcbdaf32a8e8c2372eb7906df2076f4181c35931ec7e39de68235905c8e8c622f654b054c7a10","nonce":"3cd04c6be752c00570352ec1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"d6cdae7ca6ebdb6232da6539490a5a2c694f37f5fc15f8ad9f7a86233d347f8304bb5d172fbf7125432366b25b","nonce":"3cd04c6be752c00570352ec0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"19d823a017a3c33f8fe68375ad35aac6c89555e4446fb4459c63923f2ba69726ad9a3dd864309fb66c3316d73a","nonce":"3cd04c6be752c00570352ec7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"2537c70f8418e5bc980303107f852e5e3487b5dd770b289888eb5afadc76279e05d8ba3e025c25a3bbf8be09e9","nonce":"3cd04c6be752c00570352ec6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"2e4af10d155d6dca9a4581534686c5bab3b9621708e9b2b8fceef5d6a4bbf1f469cd06a2c1c4294bb99ce63d81","nonce":"3cd04c6be752c00570352ec5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"9ff0062a0c1aee80ca7cc94e8621a3a69394b30bd523535aef73dd29326aa2221d812ed9c64fcbc955cc966726","nonce":"3cd04c6be752c00570352ec4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"eaac4525b251bf222dc124a0f68ae41cce86124fa05b8a57f7f726b0b5d84a05dd1120fecece925c7773940f48","nonce":"3cd04c6be752c00570352efb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"4fc0e90aafdcc691bdb7bc07e443fddad3ef85c1459cb74162701eb9817826c18c953ac298df800f90f13ee219","nonce":"3cd04c6be752c00570352efa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"ebe0821c872d7218b6c3341df49552ff45308764b62598ac28daedffe00f3e5f3a74b990d804f46112ab4a92f3","nonce":"3cd04c6be752c00570352ef9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"06bf58816a2cdc8933e2b5f4a6b635ecbca1481785ff64a265105eab868cd8e5ad37ff9ce79ca73c2cac9c3a97","nonce":"3cd04c6be752c00570352ef8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"0c6ca3933355ce31f92f08c317e6b1c5d94276dc98202de4ebbeb8bbb406be69c8bfaea76b900e7316954094bd","nonce":"3cd04c6be752c00570352eff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"c1d93162740dcfd765cb0691eab74864c3f8d367dcd5d21eb02912d9640e9bd28d8eb8a062e3d732f708f580a8","nonce":"3cd04c6be752c00570352efe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"1b5bdef7a3b727a1629e42734e2325a09170c57f90dd8443d16b3cb15a52d36baae92f3fe748856967cd606c71","nonce":"3cd04c6be752c00570352efd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"e8208e68f535273fb46c7f52e54474e92b82291f3fc6b7b4700e093a4037ec83b7d64dc7af8ae9c735d670bbee","nonce":"3cd04c6be752c00570352efc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"a471943c99bc4cfd03367ff3182a85973ac313c8be7cab86769bc7c481c9fc56892c7540747903fabe4503f76f","nonce":"3cd04c6be752c00570352ef3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"ca10ec190a8a9fe5377c190731d4d495ff561c7087d89dafd486fe0fc150621b755e1318df6f2bb59bb6821c21","nonce":"3cd04c6be752c00570352ef2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"3bced3842a4e258e44fb4c8544bc651cfa57d5db9cbd7a4063b71690a87c58c4920a73f8612b211e454a36d5b7","nonce":"3cd04c6be752c00570352ef1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"28f9887b92a17765f73fe3ed1fc3561a8a9eea5cb4a84f2f4f2d2cfa6b2933922beda7199acde54cc93005048a","nonce":"3cd04c6be752c00570352ef0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"31c6cd122847c68cc72aa4ea39019d9779dd83d4aa73de47c4bfcdc82c99871e11d7b67d35b9d0f88a6c6c1d22","nonce":"3cd04c6be752c00570352ef7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"21966b0a763ae97c425ffbc948e29b6d3a2797b2e45ee562533e52749713786dc9ab06c01d2840ecef65a47a42","nonce":"3cd04c6be752c00570352ef6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"123912a9cb26e7753ad9be7d569101efcf13f00a952546f047600080c60b89eb0a0124f8c94749e476dd9b86f6","nonce":"3cd04c6be752c00570352ef5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"a695347457f5c1ac92fb83b8e1e1e4acbd9b4ad6017ec0802f5ef17a2e511ee0851cbd32fd45e5b79c4f6a956b","nonce":"3cd04c6be752c00570352ef4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"0e0bcbfbb4d42f3989e459d5485d187f626a302b3371a3d3ccab798f585bac138b86924b3ac5319b323513b2b3","nonce":"3cd04c6be752c00570352eeb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"ab5e209cf46cdb0867999f18aae5317a6b788623eb592597a3999d2cd87364cdc9fa02dfeb8953160e03d2f26d","nonce":"3cd04c6be752c00570352eea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"24b2f1752f079c20872d3c54468da2623544e4cc1507ad5bf1a88c4c3def645bae5ef0180d8f9e2a85b44fd9ba","nonce":"3cd04c6be752c00570352ee9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"2ddf25be000f0ba00c37c03c8cb7929b71ddf0a3d398e9d38abfebee5ec06ccf5c7c8c11a0abf6d1d58d5cc294","nonce":"3cd04c6be752c00570352ee8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"297a54e1cd99ed47c8af47f88090e9f200be791ec9d232d28fd8f8a4b07ddc458ccdb4dabb342b6a89ec6eb55b","nonce":"3cd04c6be752c00570352eef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"5d65fd974579d8fde7d789de2b449d00f9b9378ea310d85a13c67143acab3f80f9eef43639fc454336a90516be","nonce":"3cd04c6be752c00570352eee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"3e340f398368cc707873dd7726ed88c5bd67e67fac1edf9da2f466648072f33f53e52fab00dfb78c1993e1185b","nonce":"3cd04c6be752c00570352eed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"8d859ef19fb396bc5ef1a25ba363cfda53fafdab0bc9d73dd1c0cb4d0d72675900f42043c4da381a71480b8e6f","nonce":"3cd04c6be752c00570352eec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"92a982631c038a9af1930251210d6a5b0a06aa5e8fee7cfcc1a98865b4b665c30ba431c364000a383471473181","nonce":"3cd04c6be752c00570352ee3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"c369f7806f9e30c05d4f47bd78b2ec481b7ea9fee1c62f49b65fe04ad1fb0da4b03fbf23b98a5b8fcaebe7ec63","nonce":"3cd04c6be752c00570352ee2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"bc002166078079543facca4d86de2afab5c06f8c3a8b5a0ce96acfa338c589bb6c8ca08eb0078a07773ac90680","nonce":"3cd04c6be752c00570352ee1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"492203804c1560036963a1863ae73bb071c3b590743f681d72b70bdbfb779cbf985c0665b2d36ec061c0174021","nonce":"3cd04c6be752c00570352ee0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"cd3d104ce42958343762a7c496deba6376a0ed2cf76242d1a9b435fb4af573520e10a977d2dd652bb26dcb42c0","nonce":"3cd04c6be752c00570352ee7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"819c60a8a05298898bc1a52af38bd75e0936efc8dcc2b6845666e3ad1fa0bb6565059e698f3bad826016b74333","nonce":"3cd04c6be752c00570352ee6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"cd364d95d7720f99e1b296b2b7b7e8daceefe33ab3f20bb7745c758474e313bbdc206b8eda0d6032e75830f345","nonce":"3cd04c6be752c00570352ee5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"c58db03bd156baa52283b4728de6289b43803f3b9d824f9b096019cad7664a1a5dae0bde3bdb9996a10aa2cd6d","nonce":"3cd04c6be752c00570352ee4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"d57c561dbbb5bc5a34d5c6464ae353822cbfc83657c5244f34bc175c4ac16d1e18f445ce3c9c70fd9cedebf986","nonce":"3cd04c6be752c00570352f1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"db629a2a12d45c79af45f42d3e69b1c1621a70ee3516ff055aaaacac7c2bc59d"},{"exporter_context":"00","L":32,"exported_value":"629dbf3748f093e30fb22e0eee07033717767518300b3a984e9ab2bb8a90dfa1"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"873c29189d9e27f0f4cc88d0eb4de95ec50cbe796cc59607492c045fb26b1bfd"}]},{"mode":1,"kem_id":33,"kdf_id":1,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"b124dec3d1d1ef7a3fc3ef4d88281c71532f48f724c9bba9ffb4c4633391a32e3190262f07bdd9ff854be304eb974777e3b760713499ef09","ikmE":"7146c648286c35db9ddcda3bc7e7d4075a22d831f48579ddae156e418d2e57ff8d9820372e7974b0493cecc103fa4997efc7672be5ac70d9","skRm":"56a8a8cc165d4ea1e4bc367b93af8e925709e37baa250b197a6b1a88cb2014e944e6b74acfd17cc5b1a384e3ca866529dba5a094adec0866","skEm":"bf084e0298e9ad2e8ad48e09f04f3e02df8783f2d1cf17d10b89a8c8cfad440fa36a9d7742e3dede9cd2ee5a311d093aa392245ee139a680","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"a2bcedaf67f4a5b458ca8761f9046e59b6468435e73df513ef2a76b603d4ccb418950cc1560525c23108b9f3bf3fb408fe94ca1710b8c24e","pkEm":"2efa59c331d9cc089a589573e2933b6368e91d189b15e5b42ef64f2a99a70ff796ce85988fafb74ccd19cba86b935d1eb66fe0eb434d3b05","enc":"2efa59c331d9cc089a589573e2933b6368e91d189b15e5b42ef64f2a99a70ff796ce85988fafb74ccd19cba86b935d1eb66fe0eb434d3b05","shared_secret":"199f5464083566ce40d6bf9b7b9182c6149e0f75d27a4b69830169a0cdc9d4ba0f9baea33d4b7a9dab3dc04da5b9941d5c04122cfcfe56bfb575cadbded4e08e","key_schedule_context":"01f122f8796db694193e9c25a9085e064a650b1dd3739e34bfd9a653ff471adc1b87399003157c2bc488b6f17e65efdb0a55ebff5dd99ed2ce3d97d3473e69c23c","secret":"6d42e07e087b4aa908b11b6e403c79c1b29cd7dec93811edd153dfdbb6689e98","key":"a306f28052475f682164b002018698b146f66913599367a6b386bd2ef23eea74","base_nonce":"84cbba8c17fd4cda7986416c","exporter_secret":"e83d9b7dd40f10c7f2d0b5eab128485f037d44dcdaa2556d839f98872164d41c","encryptions":[{"aad":"436f756e742d30","ciphertext":"d9e89a3b02e996e7e4270980f6019be5ee6b08ceff02b45377d78f045cbf5d439113d0ff1f3a7cf1472a2daa97","nonce":"84cbba8c17fd4cda7986416c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"b9afbad942de72f61bf361cea2d2609b99a26ebcda1b7ef9fa0eacbd6a033d6695cf9f4bb5b8d21d3050c182fd","nonce":"84cbba8c17fd4cda7986416d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"cced02b88b97e61fdd959442dde2b4ec7ddfab14c958bac149f297b3d9b2bdc452c5af6fc642df2106d0fd846c","nonce":"84cbba8c17fd4cda7986416e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"ba606891aef22e5709a5b14935a7d17859b698386201b28640e5604399bc857dd8bc5f7c5e4e491ca81ef3675f","nonce":"84cbba8c17fd4cda7986416f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"cff7578d4ac9f743a4617c316e7499e642090ad0586af9f5531b5eb1231a4820109e1dc72b6b064bbda957c840","nonce":"84cbba8c17fd4cda79864168","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"e44eb8a4020717c1773db1d0e5115a6ca8f179a02681a1ada78af25832abe6d9db255d9d52a32b15e5a4852b12","nonce":"84cbba8c17fd4cda79864169","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"86fcc386f63d10f761e688372250a8f6cea117497ac74527e5aa5dfb269d4c9f34acb2da1d19b6f1dedea1faf1","nonce":"84cbba8c17fd4cda7986416a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"7333183d3c4d8663725f606a499e075e58d6f73b1da1ec78f01ea2f5862a24d34d3775cd02c134bafd9c8fb1ad","nonce":"84cbba8c17fd4cda7986416b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"8d958f9aba6ce98d63b307baad918ed2cf503562a4252bfb49573d7833f1443ca7084bcb6cadea09a88205d45f","nonce":"84cbba8c17fd4cda79864164","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"bd4a200621598dc7ff360a21bf24ce2c2af69651c6f195237926b139e4917e6f8c52ee3d19b321f8bc41588d5a","nonce":"84cbba8c17fd4cda79864165","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"8c9d4b121d4d2c957a38b383db964ab619963f3be64c4ef7d932fd1073ea07eb0d2cd064ab83ff3ed5efbbeed4","nonce":"84cbba8c17fd4cda79864166","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"5e514deb4f9070341f64963a900aafe734d1de420f44bfd30703ed48e6907bd4607cc8350bcca78c1886150757","nonce":"84cbba8c17fd4cda79864167","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"3ee788914381163a83a0dfb638fd237d8c912db6f31d258f06fc370b9d7b6c971b60e88ba1924ed9e99fb6c79a","nonce":"84cbba8c17fd4cda79864160","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"b4efccc853204ce23adfa47c84dc6d64c3813a8f8ce629798cfaa32bd806e76c3445cd4bd0ff45fe967d87c634","nonce":"84cbba8c17fd4cda79864161","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"888e2dcf9412f3dcf21f78e037882b7d2b25155068a871ecc5002392426afee588a1e00131e7ef32df073793d9","nonce":"84cbba8c17fd4cda79864162","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"c25ef2e7d2ecef3b3996ec7a98d9b6d325f09442a6a8000375578ef93c0402f6cca8fbff3690fb145c3e6b8bec","nonce":"84cbba8c17fd4cda79864163","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"9265fcd656f146ad1148fb1467eb865336e3cdf3cf239e5e10b2389167905614445e9577da2cd2a66e2c3044dd","nonce":"84cbba8c17fd4cda7986417c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"94d2203fffd59a9083d6e4185f366633f7d0abe743408ec71bd596c411427431462339341821be657d24751cb0","nonce":"84cbba8c17fd4cda7986417d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"2919875ffbe7b36235ca67d597c80f98267a3d16e428aea25d117bbdcd91d6c334d24545d24260b97bc1815860","nonce":"84cbba8c17fd4cda7986417e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"ab26067ac8f3918fbf96f89a0a1cc15f56c662598a7fe3542fa427f3eff985e4ee435d7efa9e100623e9b79263","nonce":"84cbba8c17fd4cda7986417f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"29b8375e8d6f3d894a063d06e34d08653485187dc804df400f25e06e0783cc2cd380e90804aa0c99d916bc98f5","nonce":"84cbba8c17fd4cda79864178","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"ff70f422ec5d3a924ef4a6903bec34272ac07a5a1aea28fd801ba58d13674da91806f7fb5fe4d127603ce38763","nonce":"84cbba8c17fd4cda79864179","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"0761feb55a337d9f15694d6ce5605b05c4f14bf1d830717cfb8effe93b352f5ac01be5770ca3b544f266e3efab","nonce":"84cbba8c17fd4cda7986417a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"4ae0b1b70db07f523e4d9f4e5cdc84a1421656bab9cab28d7a0b264295ee3b28187d78608cf09c3f40685af909","nonce":"84cbba8c17fd4cda7986417b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"6fd6c01bcbe2f1a94e1cd4e95215755a95cd452a4b9303d86a22e7b7f6423c1f966bd9d105505ebc898bf306ba","nonce":"84cbba8c17fd4cda79864174","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"f0b098d0c05fb5981185577b8971e87106ff887acef27fe50fd28773d1f62a4670b957d367311e06206ab41a6b","nonce":"84cbba8c17fd4cda79864175","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"38f81a81b4fc5d225f95ca64371faa5c5e55f7b3076dd2c453722a25ebed45eef0b071d1bee6649b40d5669591","nonce":"84cbba8c17fd4cda79864176","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"34aaac9f549ebd12ed3444abfdfe98e66dbde761e6c3fd2dd97e10a0f9235151942c152440f852c916c064d94b","nonce":"84cbba8c17fd4cda79864177","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"729219316ddde2cb2b08e20c4098111789353e4975136fc343ce78f045b549d03d9dc97275401837e638e30d8b","nonce":"84cbba8c17fd4cda79864170","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"945c3cc57d30eb06ea518a4ef51b6eaeb0c8cde2dd033f54c12afcd43d1ef7626ddd697f285cb9669db6766b33","nonce":"84cbba8c17fd4cda79864171","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"60684b018a8cbc5a5d29ae268f3aab1e98d5497cb0ef1558cb955ebbbe8165fc996d059c119bfd599222d23e46","nonce":"84cbba8c17fd4cda79864172","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"cda9cb5cbddac664d14e8f12bbd1fa7652dd7f578866d19e8f8ec9ae5203001c65bface8da23408b4cf87266af","nonce":"84cbba8c17fd4cda79864173","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"43d8f8d5cf9603d680775b4fe1f486738d17ca4c31e854cdaf45e47a74e50cd132e8f2192ce33516aeb74b4fe6","nonce":"84cbba8c17fd4cda7986414c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"9696631a1cac7aafe44338f6f356498a5c51407a5386c31317899d45a6e44cd0ed32fe1e3ffdc5419606b15f1c","nonce":"84cbba8c17fd4cda7986414d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"eebc087fb156f7240f4a0109134fec4a02a7b03c51f3e909abc3651d2d2d65e568eeb4829326b1f0d1ef8802d8","nonce":"84cbba8c17fd4cda7986414e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"1caeb34f48347d7f566744a42d0b75fbeb2258afad2e28e0dd1d814cad722ae30ff1ff178c17a695ed7a1194bc","nonce":"84cbba8c17fd4cda7986414f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"7bc173ba904d0f691b1f69a66e663f9e8e9ef3b4e5dd721b2a89b9be456cbb063dc0ffc37aeeeaa85caf0b5def","nonce":"84cbba8c17fd4cda79864148","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"da91b36fae7f46a7e7c84fa6f65e6a5bb08fd3817b7dfc3bbbbdc874a1f9b0e4196edd6e02750cc6b71da4ffc1","nonce":"84cbba8c17fd4cda79864149","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"518f03faa176b0378065ba8bcdbca195ea65b6bb7fdf65216421f4d1ca42b47474563fb406cf15e81d2d2ea021","nonce":"84cbba8c17fd4cda7986414a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"26b80310adba67539e4d818ce07af4d83773505600d7da7c140b8bd21f4f6cc69d9681f0db0a562e1c3b3d9f91","nonce":"84cbba8c17fd4cda7986414b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"0faf89e757615a362aed11c8d563900e55c876f10c8138e10c81b68796e7be72ef52019ca9d683ce1e0e8d3a7b","nonce":"84cbba8c17fd4cda79864144","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"9406ea941c515f74d623a83e1a1471b79912a1eb2ec0697aeb114d2376011d63703c4df364f1e04316cf75366c","nonce":"84cbba8c17fd4cda79864145","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"50b127b5cba8c7bcb664514648ae090dde7742c7b8bea06be9e9bbdf2e5a42bb76f9a06aaba12aac867e4746df","nonce":"84cbba8c17fd4cda79864146","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"7189c861961d79cb76c559f2ac5be5b28269b6709ae64fc14b5384cad16c2e53c0efb9625b08e584cff2543be3","nonce":"84cbba8c17fd4cda79864147","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"5efbd02497cea2ba31d62f33becbebebc425fd29e6ee18682f85744f3b4664959ca6faf717625d204a7c3345ca","nonce":"84cbba8c17fd4cda79864140","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"29ed53f05e9f1120b3bd335df563c8ea29386b7a03e93e8e3d299cbc50fc9eddb7182a87f6ab976166c1cdef04","nonce":"84cbba8c17fd4cda79864141","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"eda870e8ccf9f5155ac70486c74d57463cdfb3459dd1f90bdaa8dafe1ac8f0805209288e00d2bab97b8fbbd296","nonce":"84cbba8c17fd4cda79864142","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"5f1c7533fd8571c54ea9ec5d6ec95af65264b1ccc2d57babbb940bf117d50f424775da056f65dae8cb28afe6b5","nonce":"84cbba8c17fd4cda79864143","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"cc255c82f2a9ce782d22deb2fd94b0ace0d03a001ab0f204fcca913791c694a0dcd94dce5d7cc9b889ad2514bd","nonce":"84cbba8c17fd4cda7986415c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"cc4e66156f5b319a16a642fde19375837103737c2f1dab7e63853527cc8c07e73377c6ee9cc52bcc5146bb3804","nonce":"84cbba8c17fd4cda7986415d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"421397d91fc43facb91cf834e8f5b3f7ff9235a8e84a3a58a6e0cc9ef9ee71e2dfbb15081034d5ecb974024a70","nonce":"84cbba8c17fd4cda7986415e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"0c649a3e3ba05d0d9a99469c4de5f9f4613e6e130b2570a4d72f52414671201a45a8497e7316b86d63f6cbb8f3","nonce":"84cbba8c17fd4cda7986415f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"cb1d4d8ccd1fbf77ffcbfc01855dd4251be736ff51bbada941fb1d81195bf9c25661144ac3582fbe950919beee","nonce":"84cbba8c17fd4cda79864158","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"4eb461614000a35fdd26456fd0fbd452fb44406f515a579d0519f526a5cec3107de59ffcc48ef4dd6b9a235e05","nonce":"84cbba8c17fd4cda79864159","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"e4fae05b857304cbca4a0823d56ef589b6f15ab16c831c5e68cf37a8afa131c3abecb32e8074cccc45ab54ea5b","nonce":"84cbba8c17fd4cda7986415a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"b781ae4c9d606dd687135058e0bd008a99ef5399df6bc1ebb6c2334a0beea7f0b40b0466b096f3a20184b5143e","nonce":"84cbba8c17fd4cda7986415b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"c30436c1ff51ded8226cef4dce1a223be182719bad771c3724edd9d3b5a3390ab9f830bb64ba7cea1f60f623f3","nonce":"84cbba8c17fd4cda79864154","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"4f604f7f62973d194d1faf75f8ed8bffefd0e544481d55b6b7cd8d6a9938165eb2ccc2d6a1cce03b60129d0a53","nonce":"84cbba8c17fd4cda79864155","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"5b2631067d2c5f5ce33a75e07999b7bf4a7f0ab8d1def902d628900d1ec5e6d68e2c68f2c1139b1aff813f2a21","nonce":"84cbba8c17fd4cda79864156","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"28d7ed4cd8d3402856f0a18c2b9b8945c554b02ce605dae9af015c4338e2fe40c2eae48c24d326f9851a4efebb","nonce":"84cbba8c17fd4cda79864157","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"2832541f98546590e40fd934b043b6508f4c69c457ec5e047a156a7901665a954ff89854a16fb15cd2a02e5eda","nonce":"84cbba8c17fd4cda79864150","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"09d85845611077d3545d349cf138f75339a3ddb448971fb87d9442c07f266b5ab9482c2bf3af336fc2cf5ce2c3","nonce":"84cbba8c17fd4cda79864151","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"1f793cd166cd6182dc909150426c0ef7ccb8d77821f23a9ddfca4d2f5ee55d9c552e4c35ec3bf81335191e8aeb","nonce":"84cbba8c17fd4cda79864152","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"a111f2a2d82f91650492621b8850fad3fcfa53b33c8a3b4d58ca06bcbc12c308f2c9db6ee5385ea60077dbbed0","nonce":"84cbba8c17fd4cda79864153","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"e1d74efd9dd876a562befe04fe45ce482da6250f0e85676e55ab63740ef4d6fa0241a0c237f092c530b9cad80c","nonce":"84cbba8c17fd4cda7986412c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"6f6e31129c6b786e946cfe5fc8bdc3382ffbd30f1db95f319724af73c3ec7995d188c728dc2b2dbe3176444191","nonce":"84cbba8c17fd4cda7986412d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"2a1d26a3a579d7380e7391670b8070c89f7cb0ef2538a446acf83f046f97822a942f5a1e9bf4d1b220a637fab2","nonce":"84cbba8c17fd4cda7986412e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"9acee95e80fc018ef6863a33e6a0f0de947424b560d71d9e77f421e972be5520f2e45c328b60808341994ad70d","nonce":"84cbba8c17fd4cda7986412f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"67e95cdbcea40276676dc4bb447523304bf5192ce495c88748ca134eaef6a1a018eace925fd4bbbab9344d2a37","nonce":"84cbba8c17fd4cda79864128","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"008ff079ea04782d058c0d1600a27a8a1c6b668545af0b751d2f2e416dc141f17d0b3560bf5d81769b694eaf5a","nonce":"84cbba8c17fd4cda79864129","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"c28ce2dd3de73d15bafdfafec3bad88e6f8eba7832742657cf921ca2f62840a4fa3906f19f8edbbe55e90db979","nonce":"84cbba8c17fd4cda7986412a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"9ddc265a78e94ac04d511f24ffc75aca37fbf53c567d109b78f9064feabaa7e5464d672f3cfc709598cfe68485","nonce":"84cbba8c17fd4cda7986412b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"fc7e206dd59a145a29261b05007fe6a67429abdf0ff7d1611cb6b2d4a8bd8e0287028c3c6e0b4f4a6f14102b80","nonce":"84cbba8c17fd4cda79864124","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"26129b251469f58e69850b5ec9e909e484c4a541aee1b5db48b26468cf27a689e8a6e4c267a0efb14536382119","nonce":"84cbba8c17fd4cda79864125","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"d60bc223a2a3346e925260e5d92a82be05181ba4da1787e6956036077b40f688fc685082d8bac7e7bdf7acda66","nonce":"84cbba8c17fd4cda79864126","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"2c5cf086378f238d8909d5b293c9b0c1731a48d3af064ca1b54048c9e169607521e3652a7fed1441df89c44192","nonce":"84cbba8c17fd4cda79864127","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"e532d557f2b262e5b67e870fe18dadb61c37490cc5fe6a6f1b869a5d2a9fac034adac5069960a1107d2913be7d","nonce":"84cbba8c17fd4cda79864120","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"dfdb1294ec47f6c5015154a4526a39e60ef5b1bf39d2b561d5cd9dc92b7b5e637b9d663d8e60f5f07450e82b98","nonce":"84cbba8c17fd4cda79864121","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"529c6f0f948500301fa62d88b42b38e2d4d8e29c59cc3ee21775dbce859765c0b2d4fc950d38ff34a537f3279c","nonce":"84cbba8c17fd4cda79864122","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"725a5de841f3e922ad8c978bbad94b432f49be94bd70cf3af65f882618ccfe5a3403772b571005fcb8b9769abe","nonce":"84cbba8c17fd4cda79864123","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"44dd1de4a5e6572bfab61c8ed8387708182d7e32d6b5483d79f13ea21fa9a9d0dc95cd2782f8d2b8d847973486","nonce":"84cbba8c17fd4cda7986413c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"5b34399d3b4fe56fffd78a9f7fd75049a293d2132f56a1c2d3cbf8886c9d3f63e299251a60ce4bd4b5637f6102","nonce":"84cbba8c17fd4cda7986413d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"0bcd65e86be8fd7cd718d125c1c22e46107c0206a43dab06923ba050b9041b4948a720f19aa2610e5e2e00322e","nonce":"84cbba8c17fd4cda7986413e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"fac542c79eb58eaedd4622cf6b0771c234e4a7ca9b9de11e88841ddd3e3ac0aedc3e90df33fdaafc5993586f95","nonce":"84cbba8c17fd4cda7986413f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"da1b9e1bbc28ecc85782c1b410930288ba7b8f3a5de3946938ebfadbffc976f99c52d71c29f4ad505bbf0cbfcd","nonce":"84cbba8c17fd4cda79864138","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"97ee1ef82171df2ea628a295725ae003e4f8b7d6808d95338ccc39a656e2c026a92658d36e469dc83dad4125d8","nonce":"84cbba8c17fd4cda79864139","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"aacd941e81afc94293ad628dc2e0653d806d279b949e02377d84b4c402975d1fdc31224bb96c40621743f4d848","nonce":"84cbba8c17fd4cda7986413a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"9e053d4ae81aebf048f51cc10f32bf99b0d32d5dd278f25186666495bd9dc2015f17f3905c03456df01c362e3d","nonce":"84cbba8c17fd4cda7986413b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"bf4a3e05d5d50db4d10da577a7c5b6325b20e8d74941fe4d33c7955b62911adb5962d5a37ae2e2e23d3e4d7bfb","nonce":"84cbba8c17fd4cda79864134","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"ea6a467908c6de96c474316b2bdaba97a45986a2f40a2b9f4ed64b6d042b43c014cac49be6fe5a2f7e187b3f92","nonce":"84cbba8c17fd4cda79864135","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"fde05f0e22d556aced34cbf586fadaa3ba87bf73e07ffcf524d022619360de048fa063a956b1423d58de5d494e","nonce":"84cbba8c17fd4cda79864136","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"6a2a0e5711320fbc7f827766ef52778cc6b9a518f447d34e4e4b43e98f3331a780648c4406e0f405f2a235b9cd","nonce":"84cbba8c17fd4cda79864137","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"f935c97f9024d57c04113b8f90419a1ac6bfeaca2c397b150e55f82bddbed3013218e126799a6b47b3f3e28cc1","nonce":"84cbba8c17fd4cda79864130","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"a4421cd624117be77deaff8be87a44aa3e2c4774bcb6c433b830bfbada89aec7755ace2afbd4f065357616c4f4","nonce":"84cbba8c17fd4cda79864131","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"833a59c5dc3394707e115ecea4bb64e748f0871d9e69dd57aa6f2b00f58add52d36942d48451fd7b0ed5552977","nonce":"84cbba8c17fd4cda79864132","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"a058b4607938f1fbfb98713a5d1ae52ee94cb8a3d7abeb82cd05fdac78dd9ba2e79a2a2d6b50df68f6f3079b0f","nonce":"84cbba8c17fd4cda79864133","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"7612759024d6443473e09ce39b41eab47121ff8336aefbc320670a14eead6ad2de9999209bd0817fe81a4a3dfe","nonce":"84cbba8c17fd4cda7986410c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"1f55d5e9f113016519c81186328d4a72dec51c049ed592fa39a789914d7e37e7eefd77e7089bb883f526ef2b21","nonce":"84cbba8c17fd4cda7986410d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"9f00b37514466c5135289e8d29eccefee22042748c1ebc53d6078ccd9dc089f673df7f2e08858d315a2f8178ff","nonce":"84cbba8c17fd4cda7986410e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"698ac54d4b5885dba7a44e05686f16455b4cac1eb5c44b3fe484746563102ec67b4e32deee153bf0dbd419a951","nonce":"84cbba8c17fd4cda7986410f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"0612321c3803815ec5e6db002473942225c2d9ebdaeb418fa380678fd5ac5fd9ccba80d0d095a8c418a685ecb6","nonce":"84cbba8c17fd4cda79864108","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"e5c7b13fc13a84f76de3027ab9ddd44a6d263dc900fe4d4543fb9662c77abee5d4aa1b9e0bd4285f8ef57fe84b","nonce":"84cbba8c17fd4cda79864109","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"a567bfb8343c86e1a9d7437cf15bea76cbe55d94e0c053286043a4ef0feabdd45fd141dc8661ce781e60154625","nonce":"84cbba8c17fd4cda7986410a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"4b9a17066eaa110ffc3c1c7cd9aca3bc581d6e58263f9ad0c4df20a428050fec28cb16ed7ee66e738e3135d3cf","nonce":"84cbba8c17fd4cda7986410b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"9ce348b13c5b9a68b445074140e7d8788b80592faf432cd4a4b44a9cfd145746f50bd7ae940a330ce9e5d14a53","nonce":"84cbba8c17fd4cda79864104","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"295abd5bc27aa8c10e44f91023d23d9891b0a3d9358145691a89f76e5568c5e71a7338a3165ebdadd666a9f870","nonce":"84cbba8c17fd4cda79864105","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"f919922a53cd9cef42db23cf3d1e188e17624a602ccdd56cda6b2d98cbc38d17af3c552b962b470a560e03b0ad","nonce":"84cbba8c17fd4cda79864106","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"f79fa94fabfe0167019d8827112f1376c86f3432de06911a6d7827b3a072e2af3a818b8ebaa5b263d2bd29ca90","nonce":"84cbba8c17fd4cda79864107","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"4194ed36935b40d304bd854fb6e84e81914dd9633244d7473f88d52c8fbd66b8c997266e19c43e5d66a802ba73","nonce":"84cbba8c17fd4cda79864100","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"e3181979e84f68cc01b4c5b5bacd57073cf0eb926de4544cb2ef109e1d6a2477c12df5cac865fc358ef55a15f9","nonce":"84cbba8c17fd4cda79864101","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"e6b83138861a667ccf4ee61daf677107fd999cef627a98fd9ada8e69875b7019d67fa8454dccc98a0b98bc82f0","nonce":"84cbba8c17fd4cda79864102","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"eb9ec5d5a1f0c6427d99e97b87acc3fa5d0bc88c894551b4e791d74ff955bea463e1acb930b5964d9b0976e655","nonce":"84cbba8c17fd4cda79864103","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"33a49c55f5811ace746201162dd9f66cc510470cb064b23356306f1008db0e6c8bc70eb31adbd6009862c465c4","nonce":"84cbba8c17fd4cda7986411c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"0d2a65c34b236e0c7baab35a7e4ca4cf5776fd43ae7458483756d1310da22e4fc378073e14bc9a5be003b8a1cc","nonce":"84cbba8c17fd4cda7986411d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"6fd7bfe878a2bd589a91de6b833629b2b2ab15d00e58d2623ffd8378baa2644f4e7b6a1f2d4e2812d66ddacf97","nonce":"84cbba8c17fd4cda7986411e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"97d1263b13127cada969255bfe2a7158814964f606b517afa0359917fe74a7859548cd3cfe289fab4e2459305b","nonce":"84cbba8c17fd4cda7986411f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"ba03a433223451d1a075ee9388c15f27f4ac6885eb6a19549cbc1f833da59a752d49cc451d7c2717026a24b921","nonce":"84cbba8c17fd4cda79864118","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"0e1705949eb199daf91f100ed42f11fd8712590af8ee4d320b0ef986fd3fffbde8afc8cab1587ccf505151ea96","nonce":"84cbba8c17fd4cda79864119","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"cd6263e219841e75a08e21872d682aad6931ceb876eb6998d111c5d06c8ae7c90af0e94bbda90a2e9a8cc2fe44","nonce":"84cbba8c17fd4cda7986411a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"429f918ba085d159205468ada9feb2816b91ece9b7b12146a0d6bf6693f8058490c714167dbde4f1d508e8ba87","nonce":"84cbba8c17fd4cda7986411b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"11b452b62877c0e250a2600a218c2788e93540bd07fd9138a7047930579206524c490dfc586de23d0da4b539c5","nonce":"84cbba8c17fd4cda79864114","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"cd95b2b6ebe7e859c88282270bb104ec20c5f11a218ad64e41b09878f4e6c5608fa259c675b3eebd465844f103","nonce":"84cbba8c17fd4cda79864115","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"9f4db39bfb5f102d2776babaf033ab489c022dc05a2688f3155630f8d36acacc492a32b443633009f4222a7ef8","nonce":"84cbba8c17fd4cda79864116","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"808f06002a68a603026532c13f57c52f5ae6df6488e7cda5bf14c692fa3cbf65d3a4120681ade1b5e3f302b8e9","nonce":"84cbba8c17fd4cda79864117","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"93d2f545b8ffc4076602e8fd289e151ff45838ff2f39a3bd9b5cf0f1fa7c51e92bb7e4b8a91fda31c8a4a65c8d","nonce":"84cbba8c17fd4cda79864110","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"4169587748d75aadd85e0c45f66f55981271aa141553810fa83dc45b99628b4a48db6476c8edbe570e4aa2e5af","nonce":"84cbba8c17fd4cda79864111","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"fa669da6112cd6259fa6834fa896904ca9a32fd78d85865bfeb9a5ded72ab11ec24174433e97a744ba81d85573","nonce":"84cbba8c17fd4cda79864112","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"1bd5c00e1a35e08529abb76b7a6c9450d134406f820d7ff65b26fdfe0ff7bbfb33033fc4682221796e23a14348","nonce":"84cbba8c17fd4cda79864113","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"b4729846710d98022907461c233179c53cc3f7ca83e03100966ca7d338305ca60fa733a36627a570565f0a48c7","nonce":"84cbba8c17fd4cda798641ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"8e0546cdedbe2de512faeef15038cff27f4053f501db9e8bed1bdd5e575e7e227eb273fad4824d539376b39b65","nonce":"84cbba8c17fd4cda798641ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"2901f63071a7c3991bd7cc036a614fc6984ea3b84da57e6d295e97318954c2d3269d610558762b85b63bd6b734","nonce":"84cbba8c17fd4cda798641ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"7eb0d2af268a16e5ac72233946357ea4b487793bcf15a76656acbfce1a4b1d8e7c0401576999973f714b4d8619","nonce":"84cbba8c17fd4cda798641ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"918d55e055c0eb106ca3c2efe06cfc397bd404c7bf45eb43edadba82dc2a5898d133450a9fd20dcfe41971509b","nonce":"84cbba8c17fd4cda798641e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"d5acd56e4196ce18f0bb68c09418f31ae1cc6168038be089625f30d387b973a6c4eaf486c4547574b4713a4bc6","nonce":"84cbba8c17fd4cda798641e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"88c5033e786d53cf722866c7a1cc74ed2a74fcf4c52a4252c176bb73a1d809f2c9dd41a6a73aa365e4f99365d6","nonce":"84cbba8c17fd4cda798641ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"80623603234d82e7c4ff743a9147617ea23f6190edf7b24fd15888618c44b6f2b6522b0531333b6e7032752e2b","nonce":"84cbba8c17fd4cda798641eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"19c8f7127524870718e53aa280510e235453f36c7e17f4e68921f62fd4a0d76f29a48875c950bbe75569fdf641","nonce":"84cbba8c17fd4cda798641e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"d436e7161f5e13ffcd15e816c17447a2413f0aad4fa9d5f05f819a67528b5b97e1ca74d5a4b0eba5d491ac6a80","nonce":"84cbba8c17fd4cda798641e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"6ae1e4428d028a0426babef6d0807942683f92b2edca30c09da353dd433c9fbc017376fc239f43a40c6fc59e1b","nonce":"84cbba8c17fd4cda798641e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"68624b787156702806c831363b071501c2d6ed0a74ae5258df40213555f4a65071425ab944f232dabe146134e2","nonce":"84cbba8c17fd4cda798641e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"05270f074040c12d2fc9968029e80e676e221ff9ed250ba5bd3bc33ffc774e498c9016cdad235831259461ccf7","nonce":"84cbba8c17fd4cda798641e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"dcb6881b8212145f55c23ce49fb9d0af6a33602d15bfe8e5cbfaa5be28f3b02b22528ba44227407f2d7337f32a","nonce":"84cbba8c17fd4cda798641e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"912ac754bee836435f39c0a280d41382494ff7f682138abe79ba826f621ff3cf23acbaa54d359b179633a5c20d","nonce":"84cbba8c17fd4cda798641e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"f27219a9e979bed1bb9a558862ee6a4866dbca5c6d308d38a61e7a379dfc4da0e1880a33c159f076b757fde5ed","nonce":"84cbba8c17fd4cda798641e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"8766b6593462feb738fc7b2037a9fa1634b961f7084d27191d0a6f1a7240df01a99672fc84db57a017d14db270","nonce":"84cbba8c17fd4cda798641fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"2046e0d62356bae271bd80f5d57b69d17e1c19074cf72c520e37e6f13a94ee40b9b1a2f5d7ce7f8fd22d56707c","nonce":"84cbba8c17fd4cda798641fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"3af7ffa96d124754e41c0e1259c7b65dfaaf2e5498252389ac6fef00fd9c89a8b34eaa21853200f15d15f65a45","nonce":"84cbba8c17fd4cda798641fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"ce29067bdf39c9a33517e20d898f3f0096ad27036583bf854414d4f7386435a955dc718e504e8802f4afb26b4d","nonce":"84cbba8c17fd4cda798641ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"4a8647405f8d8700327226ed181d74806810d794f05a69100c2a1c9c3e1128f9a0a47b79eeaad1cf7c19c8ded7","nonce":"84cbba8c17fd4cda798641f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"82c301caaab8610aa10767804ee1f2f40464efb86a5f710d9715bd993f4d8ba2f1565c399a8cbf8b97649149d8","nonce":"84cbba8c17fd4cda798641f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"e40fa5d0f47858c42513cb4e373b6515461c7a582e1b2adb882a768639afc5fbe70d77124776315f24f86ed0b3","nonce":"84cbba8c17fd4cda798641fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"50324d4d9e591707bde2846626a45022f420d35bcfc51fb0dba466d215878d2750cc1e9ea769a68770ce7aa5ce","nonce":"84cbba8c17fd4cda798641fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"cb5d57425af9a585b1ac15aca0c2d4dc9ae438211d70dc163c32e316e2214be1994dba8011a8e7f4fe0bead97d","nonce":"84cbba8c17fd4cda798641f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"3d79b0cfe56ad2f6f1b07ad2e0640888686f666c184023a87319e33a7ab2b8cd97b1ac7e9e81296d943b504da5","nonce":"84cbba8c17fd4cda798641f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"dbead20eefd3289d5841118d6440e005289a9d1c5d434072a8c76d18b94865edb5a820e46e6abc535d3e6eece6","nonce":"84cbba8c17fd4cda798641f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"b8ac0808b83db69fc6ab442c311b70834ecfea4e231afa2f1cca909bac395a43fd582f5e7ececc54331a19318b","nonce":"84cbba8c17fd4cda798641f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"7355393e5436af7636a653f2af1b600e07b24655737fac46677d7a15040a67e1686284f3ae165026b79a393e72","nonce":"84cbba8c17fd4cda798641f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"e96f1077b8234ab9abc0a91bb67e63d062cc8915e648675c2fa502a8723a76ab4f12256f742e05b555bb4abc47","nonce":"84cbba8c17fd4cda798641f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"93cdac60ef0afe29ce9557314b7e76b5f533a400c9cb89877e71bee0b9354d0cc112f62c51472c40e43436bdc6","nonce":"84cbba8c17fd4cda798641f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"a7ddb142d604f058cf0abed443879545e033ab2222dad087b327d89262d3254bdb45e8399e59d5385daa5963be","nonce":"84cbba8c17fd4cda798641f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"871189204c779a9edd09b38be945f3f370155101c49e9c8ee0b1dc491c5254cc1ef4bb75343eee47e7c88139a2","nonce":"84cbba8c17fd4cda798641cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"3ff3e5cb13c54bc9e17cb7d2a2e6d74749ab34fb855b4f7855b022e3eaf63fbac3cf5bca4d7d8db29251cda358","nonce":"84cbba8c17fd4cda798641cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"4fda9393ed2351e9668c18114461606e2055a17849269ae6bac209d4424d2d497e12033d9531b7b5ebb79bbea8","nonce":"84cbba8c17fd4cda798641ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"a9842cd9bdb0ac853f0f2fcf0cce083a274ebac65b74d8425106ddd8c21ba6537b4d4be7190f08606d8255a924","nonce":"84cbba8c17fd4cda798641cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"4867bad4c3902fd6357e493e5dc1a39804ac72a58873fb772249c7bb8e43397ac44af98f79cabca827e6fd0452","nonce":"84cbba8c17fd4cda798641c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"680bebda7c2feb1a3f459011eadd6e580d3315f181db4399f065dac9cf37b13d05b7181f8d9f9aa87e3fbdac79","nonce":"84cbba8c17fd4cda798641c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"bc8619cf282ee5c5b0d04070a0d22d6c730db62ddf14bf79771b31a5256d66c6901eb0e585fceeeae881e03a29","nonce":"84cbba8c17fd4cda798641ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"0128f1263cd038cf1360ab9e9fecf23493fa8ebe1846afb56cbaa0aaf9d00e09dd74ec340cd6602ff69fd017d5","nonce":"84cbba8c17fd4cda798641cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"ef366ddf45211c4fcba79baecaa53c9e8101ef0f46ed4ddab602b3c576662b0f57bd690c0f007d7fb641acb69f","nonce":"84cbba8c17fd4cda798641c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"7a3cd4d0911c00f261aa77b347d1cd2a20b251325912a6e98456650e9643c0b4b6751e5982c3d1e6037124300a","nonce":"84cbba8c17fd4cda798641c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"a4e3f815176e5b40c075f50080ab97d56c089e81f0fee69b0ae9c2941c0b781ec2e27be77225d434cb1cc8280d","nonce":"84cbba8c17fd4cda798641c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"9a2c13821683843fcf6096dabd75843432776aee1f8b207394592292a159f6e0be4c36060ded8b7b3f2df3a9b3","nonce":"84cbba8c17fd4cda798641c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"20d742d6d38c9b8e1e23761a9618f5118668cd356af94266d8bc760efc9b3f6d7730bc98c27842eaa58a36120e","nonce":"84cbba8c17fd4cda798641c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"237075470ba14815ee49a64a614073872dfa053748bc4d832e0b2808cb7326ee607b7360f63afec27fe4f570f7","nonce":"84cbba8c17fd4cda798641c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"3d66e1c07845a5e211e1c4fb39a9df996518ad8048c39900d56da4afb0ceff2a00dc87dc5261ee200c8218d191","nonce":"84cbba8c17fd4cda798641c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"027ae9cdfdf916b2902808b58de8c4546cfa4495a10b5e42569ef38a6d847b30a1b33316c2b6574a73b02aa32d","nonce":"84cbba8c17fd4cda798641c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"f60f1c1d763202c2f1ded31788941c811a0a341aa347422f963167b13a8cd1f27e12eebf66f697d239960272f3","nonce":"84cbba8c17fd4cda798641dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"bb9065a0e980f9962bee13ae58c2da0cdf42ff2ce07e5a51bb39b9b5c8b5a67e690a7c07134fd1ab46aa0884f9","nonce":"84cbba8c17fd4cda798641dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"e5a6d10ee2c4146d04efae0ad2e24d72e939c6c2114f8e16ebc4bd10324827665a2b85f1ff8a5d149d7d57d8cb","nonce":"84cbba8c17fd4cda798641de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"1fb68aa35cb8d27eafddd098a279f2e098987193d813ee7411a01e0b75fcc14d033051f41de773d022bb0889e0","nonce":"84cbba8c17fd4cda798641df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"2a9462372b9bb7337fcfd9e90a620ed2f281183680cf76dce7abc4b6e9fe3ce3cfd81b5b7ec7ea186e95b0330b","nonce":"84cbba8c17fd4cda798641d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"f973ac06801d2924ea3f0711a9493194c2b977f0bd463f178303e473c50698cb3e1ecf78607318c641961b71e2","nonce":"84cbba8c17fd4cda798641d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"91fb557789736971676aee3147cb4c8f131d0f128e575b74f7fbc1278c4607e44d4ff870d8c68ce1e169b1ec3e","nonce":"84cbba8c17fd4cda798641da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"a2d74ea6510a19bfde56a50357f0bc2b23697e883959f8e21b952af67cc1329ce42d40831e49615fe51eb97d40","nonce":"84cbba8c17fd4cda798641db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"2368fa6ac97ddb6426302977f7a1b5cd5af14492f0d8f74e3aebc209aa737e394d89854f8a4317b020437befc0","nonce":"84cbba8c17fd4cda798641d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"92b133da32a8fb8c7b448b69abd0d51bdae08d689cd788d51a7db4b9a02560d5d581b36bb848b6e089c1dd465e","nonce":"84cbba8c17fd4cda798641d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"dbe321e7d409ed3577029fe3fa356eeaa7dc1431cd8ce11f86eee47c98ba3d15300f5635d277eea6824bd1bcc6","nonce":"84cbba8c17fd4cda798641d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"705f9918542bd35f6da63da9187ea5bf53016a34fe1d2c865bc00aff1a6113efa804ed17dfed94c77b735596ad","nonce":"84cbba8c17fd4cda798641d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"2d2f912f89f6d95dfb983370594f2956c89c07a21132570c87712da3bb621135d63880ff6ce86f9841d54d6626","nonce":"84cbba8c17fd4cda798641d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"a1375a6f018e2c30f809365763bbd0ef6679d757278a7681015fa84417ec85f60fff176ffc7950ac06b6426665","nonce":"84cbba8c17fd4cda798641d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"e8cb85143ec46ebe8ac0849825f3261830b5b6b2d74453f58b0bbcbdcc77d6cfb8f23216e0a2b20ef46cd629de","nonce":"84cbba8c17fd4cda798641d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"a2965b736d260a12171a58dd5258e39ed62dfe9de723a6681af8b3a0c568db5a4546677d5505fcdeea54aaba7e","nonce":"84cbba8c17fd4cda798641d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"4e102d4028efb63b49988d1385e1e71848917837579047957bfcb2863b2051298888dc9d7f5804bef6aa6b0b17","nonce":"84cbba8c17fd4cda798641ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"723624490b33cbc59a06db7c7805d42a16611b30fc98428e78af797642a0889223966f8a827c0e2ef2e58fc45d","nonce":"84cbba8c17fd4cda798641ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"ea7996e54c81134211719e9b1a2ac2e2ae867dd3f8e04a941c31abd4895cb6e6ce86a846331891834830057f1e","nonce":"84cbba8c17fd4cda798641ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"21a11c72d1264d4a9f32da6a428218dcbcbf29f326422e947251287d2154162134ae06d9d1a670ed9c9501ad74","nonce":"84cbba8c17fd4cda798641af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"66668bce6b0508de53c32e90c1cd0308c4ea690210a772be66e5363aced8768540fb64ca5339e55662c6f52c51","nonce":"84cbba8c17fd4cda798641a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"5da6176ffbe20d6c5958ce1d0573187b259b102446992a3e0588cef84125547088a5bab98099b7d167d4e147a3","nonce":"84cbba8c17fd4cda798641a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"ccd79d8360fa9f8e3a0cb2baeee884e7421e211f3f3955f78c49c7d7cb443b2d9a5f65a3438cd4bf6ba62c0e08","nonce":"84cbba8c17fd4cda798641aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"69af9ff313bccdea34e3a772410eef372d967d5b265e99f522d40d5e5a3a9166d6e9cad65104584394295cceb1","nonce":"84cbba8c17fd4cda798641ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"b33764b38ba1458699e551dc7f7e057aa7207370746ccac617513837bdcfe1ae2eb89c3038984dcb066e665417","nonce":"84cbba8c17fd4cda798641a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"5f8e2146e73632911edf4e1da1b7db1e2acb5c875e27b1ad99aa744691ad9e648e550aa48bec0b1d1c920241f9","nonce":"84cbba8c17fd4cda798641a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"313f36e639ca3e42b823ddfff031e4d2d9475fbfb3429c9eb7204193f66d2d36c655e047ea493fe72c39fc8925","nonce":"84cbba8c17fd4cda798641a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"2e2240ac4a6b1113dab9cffd17e44bb80251effdd8ab0c1f8aabf13e4ba89106f39e33f2b9e40f084690188e3d","nonce":"84cbba8c17fd4cda798641a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"0c4e40b57b03208969b29bca5cead8272b0f7c6140aac8afca404d5398007ec7d1174d012d3b3a2b95f453d686","nonce":"84cbba8c17fd4cda798641a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"27ae5dc2f8d8a92ef5469c02d10b82a1b8e65b6c6173013e712b38e50e17c6ceaf4eb5f454a0c1ec1328c42748","nonce":"84cbba8c17fd4cda798641a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"23055dd4c8daf3b98c20a63ac1db99b0a86ce73f2c9f8866fd68899479160111953b4addb91ca77426866b1e7f","nonce":"84cbba8c17fd4cda798641a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"b1433497a2a82901d9ddf9ab361d8957fdabd42baa185c11d2857d153fda75bcae3203525f0a8fd43d92af1c12","nonce":"84cbba8c17fd4cda798641a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"ccd5ff81b4253d32ae618d435e435f78169a5c07073f7dcdd9e4a4e6f9fb512fc6cd1ec4b150565cbe26a14f12","nonce":"84cbba8c17fd4cda798641bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"87954d40de52728d279014c815663208fa76fbc910db993b0f4a048edfcd5008e622892459f297c3046ba6d32a","nonce":"84cbba8c17fd4cda798641bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"6e6548663ad304d3cb6018dff0ca970637d614bb246a615eb9c2947dbfefb2aeeee78f29cd5472150284d9677e","nonce":"84cbba8c17fd4cda798641be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"aabcb748eb85fb69756c3138fed741be1a01f40ba0e4b3fce8793b23aeb053ef773d073aae114190637e130b8f","nonce":"84cbba8c17fd4cda798641bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"2d6c78eff581aa555af786b79a0a773a23b9fc100d0a89dae93833213d7ba607c100aaab18554858b0134d57a8","nonce":"84cbba8c17fd4cda798641b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"b6afa32ee57c10f8f22ef8e1de156007aab7d8af0a9156874c5bdc46269a2c1fd50e454b0d751b1cca0ecf5be3","nonce":"84cbba8c17fd4cda798641b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"d94d9c4d88ef3bc222de13b06799e785982427b82ec88af8d6b3ce84c158b5ae4f1c5fc321ba190c3bda5a7567","nonce":"84cbba8c17fd4cda798641ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"1fb8a1eff33274576b2869201223786b26442db89fab1b57aace0909e5c894a2cf6bdf7a07d760417f6e8f966a","nonce":"84cbba8c17fd4cda798641bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"9449e361b5097d383ac96959b1abe15375d6f17a87c6f4db6ed2e9d94dbc31aa4bbebc82a97ca418ebc1f62935","nonce":"84cbba8c17fd4cda798641b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"d685a51980822664a610d14eb9d065499f73d503e1867ec7471b30c8fe5a1e6f55d28b4f50fc8c0bb4ceff5fb0","nonce":"84cbba8c17fd4cda798641b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"2a365fdea804967d953931efd5b29c195b3a0c8fe539d7e60f5744a8a4f508d14586f2cd02b87241497858394c","nonce":"84cbba8c17fd4cda798641b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"f303b80c18e3ad1bda7e124b1686c8fc117d05b6653fc5183b7c68a8fd86a2ff191aac4d67fe4934517d377841","nonce":"84cbba8c17fd4cda798641b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"fc996070bbcfff9612e6570744eeae147319582b689910c724b471085b70e5c0526903fe409935ed21202cd82d","nonce":"84cbba8c17fd4cda798641b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"32e6bd3fefc8ee30f48a0c3af65fdeee7407210a147154962eb8a56a6408291fd9c3913e8d9c0d3926f996eec3","nonce":"84cbba8c17fd4cda798641b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"24666b4989c249f79da0028619f35d447b2e4846a1b949aa65777ca11cd816ea10440cc59c0fb1eef4a21918fa","nonce":"84cbba8c17fd4cda798641b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"d3abdd61f4ac2fb4537b155e487f00fe7b550c535e1dbc6ef0ab512a2712bd3a138f2b7d722af5f3d0812aecbd","nonce":"84cbba8c17fd4cda798641b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"459cdee046f1fba1abcb0e786292006cc64c9c9a527e9a5221799b45ef5999ae4b43b55dc7ea2264d71e3ef8a2","nonce":"84cbba8c17fd4cda7986418c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"de4b8becc5896f83b5d8ecd6dd244a4a9500f411947408144ef368d3417eefba3d394fd0887e24b6724c002c22","nonce":"84cbba8c17fd4cda7986418d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"970dcc0cebc48df6798ec21e82c5357c67e0294c6931f7433b2f5bac70c95884b7c90630c65f5488a7edc3b193","nonce":"84cbba8c17fd4cda7986418e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"438fa493f4bb645a676056f19d824e68df849afd2e93178b44431215fc5641efa0bdccc887cb4d1bf9265b774d","nonce":"84cbba8c17fd4cda7986418f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"d4cf34d57b557304c7cff1e3d6b6f9c49216baa9874b61bb06436778149ba294922df2907a15f1ceea55ab1215","nonce":"84cbba8c17fd4cda79864188","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"b3a10a55cceb2f52afd29e8ab7b35ddf9cfcfbbcdf445761cdb15e79e5ed44c14188907213eac8be0fa965c25a","nonce":"84cbba8c17fd4cda79864189","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"0ba165902318ea864fb2dc5d2ed3c4fd2b8550cd5250434a76f1c7aab9f9468945f7156ac20688253ba66fdfaf","nonce":"84cbba8c17fd4cda7986418a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"7e95cadf3b9836183f36b58765cfe2dd38cf6121a346cef5c543174f721e2f21c7f3dc0549fe0d87810f2ce871","nonce":"84cbba8c17fd4cda7986418b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"bc73fd4f83c4f7a9d526dbd69aa844ea7c68b2b3a485fb94ca41921a0854ed1c079e63d6d0e6ae9750c7c8ce54","nonce":"84cbba8c17fd4cda79864184","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"10b299600761c6daa644c3acc1b2a850c0bed4894ce0e0ad6ea3d1e2aa1979708d73a9c8a73aa132052dbf3686","nonce":"84cbba8c17fd4cda79864185","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"6f2ff05784b3da69b592fc235cda3e9891af38290c71a749865fbb8719b829dacb2bef5a4d8917a63b074ed32e","nonce":"84cbba8c17fd4cda79864186","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"361975f9d6f6bfdde9c9bd98efd2750f9e8b553865732563a8dc62bfb1f32dac4e30d4d7426db56ac154033351","nonce":"84cbba8c17fd4cda79864187","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"01bc367f11a2ebdab26444175dc46cc550f576c624d5f7da159d711f2c52de3d421311e2880e788556f4b350e7","nonce":"84cbba8c17fd4cda79864180","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"af62f3e93cf086b3ecdc83264f90a5b9ea3b46e902fa07700a19266df0b4c90597034d7350028615666d1fa1e7","nonce":"84cbba8c17fd4cda79864181","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"943e08d5846bc6feffc97afb51cf873d9f7bf5a7e76e2721b0333016603c637eefccd72446c3a2f8d731d6ecac","nonce":"84cbba8c17fd4cda79864182","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"8674d548ec38bc2cea4e9fe038eec76f26aff577f61259e12cec4cf676f68b39a6448927c1d926895e2e33ad12","nonce":"84cbba8c17fd4cda79864183","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"da93c6e61c244e4f0b06c37ad827e477be13da26a3c20b598481fb6d22d74fbbf80195d8e56413782062464f38","nonce":"84cbba8c17fd4cda7986419c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"f8b25eff428eb0563712e4eaea6f99dcfbb3f9f5d09df185783a7693246c2c10933bf02a150246031bee1e6d0a","nonce":"84cbba8c17fd4cda7986419d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"24122daab6fdd4ed4a68824384a93d48dd36d4e43d6a59dc92a061c7b04a1db95f17d47aed73a7aa88e0ee2b16","nonce":"84cbba8c17fd4cda7986419e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"73f46434ea539be64d973be65b41af8fa34fdec9078de05817d6b205cdbce4663527e8947eaa3f30d9b65d98e5","nonce":"84cbba8c17fd4cda7986419f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"b8b1669a7d24ec726832b32b0a6083f01751b0ac21413314464905f4bb83d94cbb482286167dd136614b7483a0","nonce":"84cbba8c17fd4cda79864198","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"8ffa9f371981294f7007fb3ec9b51fec72d902c33c827cf19c038cad9d6b6e52447f5b68e731807ec45e8ce802","nonce":"84cbba8c17fd4cda79864199","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"c826b1b8063f270197f1e91eb2b0d606b822cd92eebee2df1d81c35aa3aec9ff3d7c835432188f0a8cb2c84436","nonce":"84cbba8c17fd4cda7986419a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"4d44d5ec51240a2aef538225ac7c0c63f1b84b64719633e4d03e96970f333af3a3304a1b385252ea8b43ec8e18","nonce":"84cbba8c17fd4cda7986419b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"6f51e2118f260e92caf4d5d49d30b96eb430a59f5e875752d3f2863aa32b146aac4b32d5ce309e7dd43e2c4275","nonce":"84cbba8c17fd4cda79864194","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"33f1726b67ae53b71862c406b1dcb46b09de3055d293cffdb0de38d53f9987a0683e9827497501c3b7a9f53557","nonce":"84cbba8c17fd4cda79864195","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"a97cce4bf4ea0986f1d1fe9656b8907caeebd97da5b6c7ed151e87886deb238fb81bc9ca11461b3834f36f9b4b","nonce":"84cbba8c17fd4cda79864196","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"7e485054a596be5af65f65df3c3519540db2c5e70489f37662062d9289aacef3e52edf13529adfc86e06b4fa47","nonce":"84cbba8c17fd4cda79864197","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"95f5cc7120c2696ffadd51f13af7b3b5c3c5e4abcb0a3082c6b1525f8eb3fda64a5370d58a42aa1217ba2b1a06","nonce":"84cbba8c17fd4cda79864190","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"5035ac8fba7a952e31253b5576ff5cc3fa1bc38e9e6df8db02f798bc5ff92630a7438f4fee3070fa4bdd228b07","nonce":"84cbba8c17fd4cda79864191","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"d60410294eacd09b2323d041e79966979d03edba2902dcc75fbb928d9f41ced796b1c4634c2f98119028cc893e","nonce":"84cbba8c17fd4cda79864192","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"879f9cef9944e47963ab6a0e79685f207c96770ca17fa9113d1a900c6662c348cc3c1e4c5e400e91e54b6741aa","nonce":"84cbba8c17fd4cda79864193","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"fd7715cf806a0209cdfd90ca084259bbe68d98b0c456ccbedc468bf035b793b778f914d071f6c3dd61ff4fe339","nonce":"84cbba8c17fd4cda7986406c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"4fc5112bd5fc964ddd4e750e89ecace618a8617718e81c1e9c96afe5189d26e3"},{"exporter_context":"00","L":32,"exported_value":"587f6908f93e4fc92512afb517e9637219af8b411a10d72efc6c26e78cff7c16"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"bd8a02ff2dcf8531ac57a7d467fc87092fb1488bcbbd8239018bb046fe3392a8"}]},{"mode":2,"kem_id":33,"kdf_id":1,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"818a520701d9dce062f0fb594b43b84bdf54277254de0f7cabf7ead47c8f9ace4850a67d1e1a930da364be27006d3a79e244c994aad1f220","ikmS":"feef6b83dcdf709afaf3a6531ab3bafd220d98b48897f560f5117213df86849b8b8ad827ce7d10c60ea4003501efdb6ccb0c5be78b35ac3d","ikmE":"1870d53776988c215792d7217dd95d3cab14f55d960e5cb75d6c6bf4d2b9227cee1e37d6eaa472786037e2f6861b7783fb68b922035745bd","skRm":"76b4119b037bd84a6b205f878d3d057501130976681faad08253cd3de064d7b4da5720f3455de6b26160b36aba57d63e1422d063c7125abd","skSm":"b907e4beaaff697ea5f4d13aacf391b13402350f680cb3edfd4aad93a52cb516cc63828466efba10d8e05a328ed5a621dc39ce078b753437","skEm":"3a15946141709554af773863f09fafd8e8f1cd8c5c9894591722066fb4d2a979461db2d3f9bfd213db87c2b4202471f09c8cd542634b08bd","pkRm":"d8a55dc23dc159b2fb853f67fda6e5a799ab186aadffa0f730e334ae22d191c7c4203a48a4f70962fe3894263eebbf61eceb6ecee8ea0d20","pkSm":"694381edd86cb4f30c77eb1bf7980d1c912036f983a6e76217a072f4fddb6099ebda102eb8bcaa700b31b755f0e522a4ee213b0e77a8c2ad","pkEm":"35520baea14832144cba44b83ad38ca51389477b40ba944b43bbb0b1164c66e772022b12cbe6cbdd853de5cbe0be6c359072b584b63638a7","enc":"35520baea14832144cba44b83ad38ca51389477b40ba944b43bbb0b1164c66e772022b12cbe6cbdd853de5cbe0be6c359072b584b63638a7","shared_secret":"5d5b05be3af8fa558cbfd467698f6facf5e7c84fcc4ce7cd61811771fe22a50d6beb37a60ac582c35dd04d9b3a789d86620a5a0611780fa2359cfd49d4ae665d","key_schedule_context":"02501f6956afc1d37028100b38a48efe15d0352c7da3bfecd089af8d3f55c7171387399003157c2bc488b6f17e65efdb0a55ebff5dd99ed2ce3d97d3473e69c23c","secret":"8c5c5947e2c314469ec5ac3af86444baeb3e05594760c112d77fccc4c9b01ecc","key":"2f867dcafcabf0b9b36bee34be8e26e66a87fe73fff08a042f130d92590a337c","base_nonce":"265413d40ec644cdf9820525","exporter_secret":"3341a6f50656259fd802850ee5fef5930638251415422c162212fd172b394582","encryptions":[{"aad":"436f756e742d30","ciphertext":"4fc32eed6881ee626e758eadbfa45850fcd95369ffc10a8a932143522fd319f46d4d64a399c0c88d9b985c2fc3","nonce":"265413d40ec644cdf9820525","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"7aaf63b6d973d2269953520569d6bb4130b27b02d56cfa80ef97e072a4d6d082e768e519e693a307a2faddc417","nonce":"265413d40ec644cdf9820524","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"3d17c6ccd59d5fc252a3cb25fe25513a18058426f7cdfc7be9a35fefb31900c99663bf52e861cc6a1c20817acf","nonce":"265413d40ec644cdf9820527","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"f0e4b46bed363c20237d0bfdc54a30ff2efc630abc2858a9af2f3195487589a83bb98e78f556babec04c4e23d2","nonce":"265413d40ec644cdf9820526","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"f616883944ed9f5822e25586789ffb8d52828e1a4a818879739c7308d3dfd615d1b2c64ba561d67821b1cbf9b4","nonce":"265413d40ec644cdf9820521","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"73053dd7b8597b103d15801527494d5ad1e0dbe81c6105ce0543a4b017d26ee0f8912c8f26862b820759b364d2","nonce":"265413d40ec644cdf9820520","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"6931d15566c50bb719c050cdbcba58dc74d713e6b83c6a15d02a509dccd8b283a74cd183b23a4f551d93edd736","nonce":"265413d40ec644cdf9820523","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"d36d02166d731a5952e060745bf7f462f05abfd5fdd2052243047bda0904b1c07de4fe5ac7e53b3ae7b01c510d","nonce":"265413d40ec644cdf9820522","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"bca93462eaa841e23c2f541a92e4f51bbf4d7ed7c73787476382cfeb9e7ed90c1acf3123c2ba4cef5c97d87b61","nonce":"265413d40ec644cdf982052d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"e9b976067dfebc273bc9369598444d2cf45d040edef06a0afd02f4dbd03d64a0941427a20f887fa6dd6d790c15","nonce":"265413d40ec644cdf982052c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"1e1ae44016415ad4872ab8c933c6acb20bf6188567a00762d713893b395d3ac72f83ded99f49ff0b4117213428","nonce":"265413d40ec644cdf982052f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"421e387197533236ce735cc94c03a9218ee7551a8ffcdd90e8d887ba0be1358f57459b45d4e424f051b4d5d3e8","nonce":"265413d40ec644cdf982052e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"814ded09af8f1ec779470f6c546cb0c8fe0ea58578f0e7a0a9ff1641f385fb36e6ced4defaf3bc2594e4e7a43b","nonce":"265413d40ec644cdf9820529","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"3655f673b65a17ac4116463dc079f616c757ab6f6881e24eb4150682d5302c66eea255e8410accf1252e134c13","nonce":"265413d40ec644cdf9820528","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"f17283b29d7a833b25dbaa9b1fdb0756afa26866681beb3a4df9a0ca76ea27a5b381c8550d57d0d2373a3ea0ba","nonce":"265413d40ec644cdf982052b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"c4ceadca79979a98f46c279d048d780e3f9ad69346d095357ba83669727bf2aff473f3cbba18b42d23d48bb9ba","nonce":"265413d40ec644cdf982052a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"92452845ea3d5d3ef92611552fb191fd9a00f8cb4c1104acc9caec2bbcddf0378ff29e372a34596d6b6066297d","nonce":"265413d40ec644cdf9820535","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"a0624f97d467e9dab0fceed894afda5d6725dae60bca7d7d718e6d4a974dfcb0a5aab7ff25ef0bd2f75335bfff","nonce":"265413d40ec644cdf9820534","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"c12733cc5483715dfd06ea795de6166abe7ba97efc08a1b2b226cfe0f40e15e9b8c8ad045dd75c4e05fb7c394c","nonce":"265413d40ec644cdf9820537","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"b276c12713aac4cc12f0a5c67ce397e89131b84d8f0d1f281f3e7140985e0820251d449b4b59c6533d4fe1b984","nonce":"265413d40ec644cdf9820536","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"c26a4020cdaf9dedd8705ae88e42ecc550b61d152606bdd9e167635764928829ed977343eb25710c3c6a63e73f","nonce":"265413d40ec644cdf9820531","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"c2bb5f1c7ab22b7ab3f0296c9abeea47844fa310031e91270593d961ecdc09956f0d1f589e3ea49a23ddbfde87","nonce":"265413d40ec644cdf9820530","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"44530de9032434c089ee0c406e90482e767c9661c693d7f4b1987e5cd648f1750c1733902d76847b29c270d7f7","nonce":"265413d40ec644cdf9820533","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"7c0b88d633f00724865c8c183cc59bdd0698090d6c232cb93b9ebf05a17fec2762b405ff57b760ad16c7a57098","nonce":"265413d40ec644cdf9820532","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"35179698ac25995dcec8a7834c50ebc409d9b3988bc82d467fa566715a4ec0a5950a4d2ce40892d83f87fe8e32","nonce":"265413d40ec644cdf982053d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"60b23b1391f45d48e807a3bb3f7b036e6da22dfb9caef6c6055df984b171cdc0760584796f2e84487091351439","nonce":"265413d40ec644cdf982053c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"f51e2d5da4cc5e3c8df6036db2e7590b7ad4c19e05a268ca1e65dc19fe8af696d367d30e91bc82698e66fd71b4","nonce":"265413d40ec644cdf982053f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"0460760496e8883daf9c22c40d04dcca73dbfebd58c24f5f4ed850c37315b2b42001d9ad7f942fb8ef8ca1128f","nonce":"265413d40ec644cdf982053e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"0ca603f60480bceb77699b58ee193d1e2a28435165a395f991f503925461230ca4da0b55a20fb0ab71bc4e8b09","nonce":"265413d40ec644cdf9820539","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"c63f9b2930c37076b2bc17b16f97f1cd3b065fd20d511a4b09ff9bba0cf95e5b05a2332cedf8668fd1e2c70122","nonce":"265413d40ec644cdf9820538","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"3ea8768635fbc4d81c461bb70b0754d8c9e30aa3279a077cd372a97ad60041f60b22d1d030b5de31222c1a3ef0","nonce":"265413d40ec644cdf982053b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"17573da4f12047227bc6b73c092ac3b671408d32b5a6b07d1b0abd8019cc690d65e38ce404442334e0cd20cb49","nonce":"265413d40ec644cdf982053a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"fb346b15454be0797e054ed2866a1f44558ec8138e38e4d3c57882387b2f84ae02b684ee2fd7cdd2d79def94c5","nonce":"265413d40ec644cdf9820505","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"6d7695ba2407d85a7c5c7acc92d51e1af325da34c5c26f2a6d944be470e1a690a6a383e02b09ddc7af7e3de4ae","nonce":"265413d40ec644cdf9820504","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"60c088e1f82a4f6edf1ebe4732dc448e78b8c03db3c26aebaf409e673cccedd8475908c333f6055c4463721e15","nonce":"265413d40ec644cdf9820507","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"5a9dfcaea706c8a306eb48c17a55696bad75037b7431e4103c5f51a351677a59e89dda269e07eb1415b7378d32","nonce":"265413d40ec644cdf9820506","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"780e87c46a08470a2c944ab707e968bd05f0ead37d057b7ab6a8e45a9fa14e4c6ecc6bb927f2c930bec7b02792","nonce":"265413d40ec644cdf9820501","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"c64e9eba7dfa320e49bd4e3bed613462865799d08a3269336792c1680c8060a1a6e6b5f39c1d3400b91da2deca","nonce":"265413d40ec644cdf9820500","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"aa7ef72a20735a369107952dceb2286f29a2dbe02af9bac5c42857ce058aab10e424662d9526d277e02e4cbc88","nonce":"265413d40ec644cdf9820503","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"7ae73b7f9cf1045eb819f02febb1e1449af5d08128ec5b296326a2653eb86033d6deb558f8d814494a1ba40795","nonce":"265413d40ec644cdf9820502","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"bd3786dce7a7a56d50053fceb5293ee0b3783059fd0eb9c2cdc5bc1d5a2d22feb2228695440dff8d0521471e91","nonce":"265413d40ec644cdf982050d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"2c5bba936014c2ec1a15f1d3fa3ca13f72f651d7ce1bfddccb7f94b7de60e78a88dbe700bd53bb92ea25bf9819","nonce":"265413d40ec644cdf982050c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"f035e1dac5e3974ad199d430bca4cd66883d376cc4801f8312139e89bef77cb6d69f507f273556522bc9b2d033","nonce":"265413d40ec644cdf982050f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"850eaa6b2f3f5da87b8d6ebe40db0013236bf27e58b761d8a2cc693003cb342af06b9d96bbb081331989c070f4","nonce":"265413d40ec644cdf982050e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"e390b5146a9d49fcdb181e94a20dd1f1ccb3ee07ba0a05a77a0cfa59966075985782ad825217967562e8e285a1","nonce":"265413d40ec644cdf9820509","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"bd400976aad5b379ca391916c0e705d6f7594e1004d9920e615912dee0f1e0dc1a672cc19bdde93dc842da556c","nonce":"265413d40ec644cdf9820508","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"6905bfd98bc380f76c92de75c54b9228577ccfabce5e6e3bde192720d8482e2358bd647964ce7f9a096d0b7b3e","nonce":"265413d40ec644cdf982050b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"63cd70be5942d1a6cfda5241927d15c7c8db44f626c5f418368a11990a8a03c79bfd006463b89e2bf41cb64e99","nonce":"265413d40ec644cdf982050a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"72287709a0c73885365d274164bd53a66e3b5b84fbb13fe4bf5d7352d15c8e03bcc48496cce28e05136c9386bd","nonce":"265413d40ec644cdf9820515","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"957c30768859f4f848dec0c3a23c9f94449caf04450849e04169206182d82d8f949cf1f29c59e3f9ac3aa024b6","nonce":"265413d40ec644cdf9820514","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"70de2c914108c046af383c4425c1b40cec8099e7608a6b258ccdeded8223b427575254da2e3038d5ea004065f7","nonce":"265413d40ec644cdf9820517","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"2dff0af140acd9b7a3de9cb61ea385e61ee057c57571b99eda351710007f5c8cf178b5b5ec3ea0b7afe766f8b4","nonce":"265413d40ec644cdf9820516","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"f192e9ffc3d683714b99e5bed96b20380ef321d00ae684ff76293befdf554424c6e66d40bf6948d613ddd826c5","nonce":"265413d40ec644cdf9820511","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"fe28c3a962cf3e4317da56bda5c8517a08c33363082452e073c484852e31130e09f5256eb21f615dd72e09c1fe","nonce":"265413d40ec644cdf9820510","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"5a9d9394684ba5a921758072f0ebcb38a5d4d2dbf0830903641049eb08ba9e936a320901adfec0138e51005a32","nonce":"265413d40ec644cdf9820513","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"f94d9d5c1860392492eda7807f4c35542de4ec690aa7a560ff239bb5b3f575457a236af9596ca5badb0b983c78","nonce":"265413d40ec644cdf9820512","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"53c4c3945b3162a41fc6c669413ef9e0923c56ef1d1798949e2149eb34565fcc88a30fe18785e673ebc6ad6313","nonce":"265413d40ec644cdf982051d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"5df0c8d260762518230b442317cbc0f59fc2d6c7b4005f32002ab056777bc3c903ad0ce46b4d89ca48be225d47","nonce":"265413d40ec644cdf982051c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"a1c9921fa86efc2ba5190a33f23ff79e2c42daca12e6096ccf8d9c4b082e9327e60a8046fcb47cb5c185a86090","nonce":"265413d40ec644cdf982051f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"2b3eca08fab1d3cf5adb9e58d1fac75731dfa39d3067ba16ccdd862662dbff1a14d97e49149799ee118493a4b8","nonce":"265413d40ec644cdf982051e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"170c3fa05bb001c09708cbe08481703f4ff48ac3367756f125812fed5a8adcd7ab62bbff0ca989160e74362316","nonce":"265413d40ec644cdf9820519","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"6a64ccd37263151931a561d248c986d6fb13c8cb1773c83c01e2bc5b0dbb9a939c2aeb61854643ee236d7cde06","nonce":"265413d40ec644cdf9820518","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"37ae957418f3a3d004a95fdb21f601a6a368742a1d258a6d0cc6ee382f6e496333cde3d544f67cac757e9fd662","nonce":"265413d40ec644cdf982051b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"d18e3441ee57b5d6c52aa849fcaa8acb8004776f7833dc744278b0cc0b91f72332ee0c2f71c5c825ef1cceb198","nonce":"265413d40ec644cdf982051a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"3d9b3b31d02dcb9c003a88137770adcbc4dfeee9543f010e7ba1081d75fb38ceed11a776a5e44e9141c302f4de","nonce":"265413d40ec644cdf9820565","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"53dce33ce29f1281a5242ae71f4b8500a3b561b4fa326f39aa61559ca2b7636c65560e2d2e17f4c8607ed60c97","nonce":"265413d40ec644cdf9820564","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"443986290855b648367b2c57203e25045a64f79032af623f9982d8590cfa67b780f556b83e637df9f7203df7a2","nonce":"265413d40ec644cdf9820567","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"e7968d00311e4c94373af710dcd492e8a026e748bab50e3e74fbc94d176c005e397dfecf88ffc4dce5de9c9d4e","nonce":"265413d40ec644cdf9820566","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"87f0f6a4fc3d322d186da60e61a68def8271d4f57e89aaf31394cbc91687da5aa6ef547bdbdf1a39d8b56ef1ac","nonce":"265413d40ec644cdf9820561","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"6401d4c382f3cd9b55d27a3d523673d8272d00ededd80bb888a028c5e4408f7169cc4c98c947638dbeb3364f6c","nonce":"265413d40ec644cdf9820560","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"0403fd0e807d768ed7dcc08512079e03d526e45fcda29fef20109a2cffedee34b931c3ee1db9a331e60af69d86","nonce":"265413d40ec644cdf9820563","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"1b323818c1a70c9da65e321ac944cfe863b09370632989c9f72f6d15b124e8fc5a94829a6d70f651582ba1ba8c","nonce":"265413d40ec644cdf9820562","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"37984d861be21343f45fcf3c1cd333d0e93be89142c0396d634cd0c29a8c4d48ed20e29eb47064c15d852d29c7","nonce":"265413d40ec644cdf982056d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"ef3c9c89cca40ed1fea55e21dbd27467ba4fee8a0d33693370de21077c6038904df87b222cf0bdffc24a333bb9","nonce":"265413d40ec644cdf982056c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"323fc7eb48d8ef2146f39d07ec424770f034313565ccf788030400d5f0e2d33409bd00f885a3e0cd5a7c5a5d07","nonce":"265413d40ec644cdf982056f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"0ecbad3989b77a78dfe5a8a975c167b03efaa17e6a83d56b770243a9893756dbda88d77d3d9b1c611502173a0c","nonce":"265413d40ec644cdf982056e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"6c86c2f91545ab9f016c829bae58958e1df7b0ece264b617529d83495211f5f03c00e63ee84e1abb6602775fde","nonce":"265413d40ec644cdf9820569","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"f2f1bb830bda284a3ce17f1c5b4cd5e684529b7672bd0df6a5ab57f646ee03173cbd433a34fc220571fa88f833","nonce":"265413d40ec644cdf9820568","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"2391053746d6578c1d0255f00e1db0d5cbc4bfc7c4cb901d08a7b065cabe31f6e8d0c02fe34603ee74abff06eb","nonce":"265413d40ec644cdf982056b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"caf3902f200eadaf9a6a310e4b14f1e36e8c5acc7707d8bc478f8b81eae7a359b104001ee4aa102f65501d8485","nonce":"265413d40ec644cdf982056a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"5a98b18d8e79745ed6d61ca845cd4ea61a492730891628e551690f6ad5d3b64611348399d465dae7f622cb4d8c","nonce":"265413d40ec644cdf9820575","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"9ac24aa7892b4e5dc0c1a65b770e6dc1a2169ce62142f9525968110ca05616a03b85bfdd396a53c6a7218399e3","nonce":"265413d40ec644cdf9820574","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"90c6be579013567fadac26602a56579f37648ad08b388b0193862ab55eb801daf953bf0b674ae139559c24a8bd","nonce":"265413d40ec644cdf9820577","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"02b1adf06650f6a629bb33ba66b60307618a71fec07516239ab1cfc676c6be2ebb7f1d18f09cdd4308626702d7","nonce":"265413d40ec644cdf9820576","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"51e49536dc7e3c490c78874e12315345edf9a9abac511063a174fd5dbb1b3dae5cd9b851622c71018bf103d1d7","nonce":"265413d40ec644cdf9820571","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"176acde29e2e618a513002e9a71bf66b4620691b0e2c134d543498b36efc83bb735a8d93545f030177bfec94c9","nonce":"265413d40ec644cdf9820570","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"2fa0cd63e8500bb1ad14d6142a44ebf018197b4f3cb2b92db7ee2c8c3e07c600810fb77f9f07679d56e24cc6e1","nonce":"265413d40ec644cdf9820573","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"4199af1b89b667b1e77fe2aaacc3641b55f1581eae2ce3d29836f4990ad420d8cd4f82aa3fa169bbcaa7913a7a","nonce":"265413d40ec644cdf9820572","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"1e2ebcac9408f75a380bf4fe6e739b5d7001780e18c0fd5c9c7028f79b568a654ad27ff68465197c4c9f210cc5","nonce":"265413d40ec644cdf982057d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"d1011ab522d2d5be78ffaf54dff0b9e198ce947c6083e33d54d2c2432883912a67675c6dbafd0627218d82337e","nonce":"265413d40ec644cdf982057c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"efb6d262273527ebcda29d3758ed1805f4de77c3686a053349202f1c8bcfe7ac7506703d6e83eedd134d665cfd","nonce":"265413d40ec644cdf982057f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"1068d38ed082150523e2b13876c2ee2411039edef3192bba0df5589d82bf817625d80ea29efff3c5a1451ccc2d","nonce":"265413d40ec644cdf982057e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"125299c71bd8174b7e30afc3f9292952f68c03302d3f12db48ae181f8cf5fbe2591034356687852c0b1e050783","nonce":"265413d40ec644cdf9820579","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"c2d356782cc4feb04d93303c27feadfda4fed4d8217b4a8e45ed1144ca08422ccf831c2504c8fcdd6c2b2ac274","nonce":"265413d40ec644cdf9820578","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"0370fb4dc7446ba79f7b5383fda622b1694ea7a8ef9f4c6f576df1a5b21cc0a3145a200102a3fa01d89987895a","nonce":"265413d40ec644cdf982057b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"92172b05d72eab8af187c363db2888535cf75a90a1d40702331a6296004c6e9aa0bb6af47af09bfe0fdafaa403","nonce":"265413d40ec644cdf982057a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"63fe7ec83bdfbdce3899812554617fa8177eecb5e12261608527c7d1b6027dc5a50957436d6efdd8889b72e2e8","nonce":"265413d40ec644cdf9820545","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"d2acc06d7f35e86646e17723ef150af7978f7a258bdbc0d3861b3636364fe07fb265ad8a548697c9dda248a759","nonce":"265413d40ec644cdf9820544","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"a1a881f9deab9eb2abffd6eb18723ce387e6075f2cbe08f39b0e93499d4cd776644f56e404a0e7af42f19f112b","nonce":"265413d40ec644cdf9820547","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"8e1ae57254290de28c8c539b1df85cafddc1af4939509162f723ba50686aed9a518f426d04a8625fd433b1dfed","nonce":"265413d40ec644cdf9820546","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"c4c98321d802dff3eb46399558ee9c9f1fc80990d5c4a6c7aaed42c9943b7ad0ed6dc98c9fc9d2982b1a41a753","nonce":"265413d40ec644cdf9820541","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"b8847c014843ae7b9a378859c2380dac2ebbad23373cbe98a80aacf249ec43d1286345c6f1b0f95f2ebc8b9988","nonce":"265413d40ec644cdf9820540","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"5dcbacbaadc76b999070e00e82d77b0de0b0ceb73afd78d90e6c363343989bcde1624e36ab5c51892881af4244","nonce":"265413d40ec644cdf9820543","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"19434d8b1166d783d6b0dc9f64733813722a458030b94d676ceffd7df43f3490478419d774bb06277d5b82a388","nonce":"265413d40ec644cdf9820542","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"ecad6e75f34dcf148878abb26c76d9a4223aa1a6e966182a598c0af30528704a949c0d11d050f4047282e29e0e","nonce":"265413d40ec644cdf982054d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"1c5af1c855106bce52b65761061d429a4349bece95f515ad6a1b5cfb40b1880e6507bb2076d2a8499af12da098","nonce":"265413d40ec644cdf982054c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"a7b0ebab6236d25f7ab41ef6c3ef0635e7eeb7f8ff8559005932a7509880f874b642867dd081baf3a4b63a0a00","nonce":"265413d40ec644cdf982054f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"b6ff2dc34c8da2464da4f4af78806f1b45b24c2ec72a92c29250247d8d063051e1619ae83389f136322e2cf64f","nonce":"265413d40ec644cdf982054e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"a0d9dc58ae04ba9beaf29ec32cde4b64308a5b71e682a5c96d46755efcc271377baee8f9a9b6ad110fc7cc6fed","nonce":"265413d40ec644cdf9820549","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"5e78cbaffc2ad02f80c8425f06554afb5ddd964962d5514b06a15c0a41906738184d86f8c270a007c36fec268d","nonce":"265413d40ec644cdf9820548","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"9a0ed8a84b495a6a4f7833d16785486f045b421c3bcda686e16d9dbbc935e8dd9c7f57a2f300ef66692648272c","nonce":"265413d40ec644cdf982054b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"26aa7011e82fa7bf3100f187ce0d688eb7d255e6e15ec0bb2365d759dcfb8c28938a6b9a6c16372e6025de6af9","nonce":"265413d40ec644cdf982054a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"ee677a1e7bb69ec85f1c22f230e0e28c56f452752ef9099c81ac64771d1b14f569ecd837aa5f2ee44afc2e804f","nonce":"265413d40ec644cdf9820555","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"9fe4fa221138fe0aeea21a2b0b60d8ac4e495b197ddafcb0ae1e920c71c01ad7700e283981ce168b1002dcce09","nonce":"265413d40ec644cdf9820554","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"c76f0ac968cdc307f51f6050fb8da9f0f54118d8011c1e29afeb38c1082df639e0a83592418c6fa53615813c38","nonce":"265413d40ec644cdf9820557","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"a49a243db54e597960e62c532296ca6a89c727d57e794635768d6bfb737f4f28d8951bc36ee381480c257a185f","nonce":"265413d40ec644cdf9820556","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"6d5c128337dddbf82997390670b81a30ff9f9169ab96ee63bb867bbe77c152a8c27e29e078254476db629d1b92","nonce":"265413d40ec644cdf9820551","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"62017641ae27fd0425f21d5dcfdae41bd6a540bf6cb68c71de63d5c296bba4c81a6d4b83c2ef63a29817c70bf8","nonce":"265413d40ec644cdf9820550","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"c0ba240c712b905aaa054d91ad9b83b072163ba53892c9188e2aa5835b8829f8f77c1185a80217d6e93f443421","nonce":"265413d40ec644cdf9820553","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"875cf53b70da49a9dd48dd7433366ed07a6f362b21952764b1448a0fa6ab096453fbf96f54550d4e0b2e459b62","nonce":"265413d40ec644cdf9820552","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"39a935f3b401a57092656056356150b6775e4df9acb3bc0273b375cd319cd4f5cfac8eed9b33545e758a354bc5","nonce":"265413d40ec644cdf982055d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"a5e5dc77ffb8fea70564fdcf6469caa21eeb2b0637988ae2920b2354007f5d743af531067a09aa96193b54dcd0","nonce":"265413d40ec644cdf982055c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"eddb6de17bf60ab8778559b7b684d1ffe8be4bb832362a0dbe1b866d5bd117267618075782a4ba1fc713e71163","nonce":"265413d40ec644cdf982055f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"20a240fa71429b0e87503121b8b33b8a52008e1623f5421d8a82cc4d5fa5bdf84dc43a59ea67ae98e0cdaf0844","nonce":"265413d40ec644cdf982055e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"a1dabb508f2a353c54d0b399ff71790fa18fddc5ad8cbf18a034ed1fde95a060b2b98170b2c1431c7bdf3556bc","nonce":"265413d40ec644cdf9820559","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"38796895bf1a8b5c9e5ee6c2e2fb839ea86187135658988b4f4a5502843463b36aa5d861d6069951984e847b64","nonce":"265413d40ec644cdf9820558","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"9abd995209d59a136cd5f6834d9d49f3b83615287ed2b66d54eedcff4f995ac5b2c07c116f1287495564ffa22a","nonce":"265413d40ec644cdf982055b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"b47036e5afef210944042b1d213a7881a8cc50df8a8614832bc7c4ee9d6ce96364bc1829a1e87865ad43ad9507","nonce":"265413d40ec644cdf982055a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"097156c5e6783c1a45231ecbb4884985ad8ba8a98bc4dbb3ce2d5d095a4b90853d4c15b702a708264e704b5650","nonce":"265413d40ec644cdf98205a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"a9d439441a96b65ecfb1cf3d8373e3e84d35eaf4d8c0dec3c3a0dfe9b04b099834565218e5138de8d6ba7c6a61","nonce":"265413d40ec644cdf98205a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"27d2fb18dc79f54cf81910ce38a589ada69a554b6191cc6f41f12df9a32ffccd84a4fa5b4b318138fb90844909","nonce":"265413d40ec644cdf98205a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"068d37b31afd9b5021d77e9c81283d0ecb3b2cb611df3b018cd493f174443c3b6e712f27c8b6f3bb1096a8e76c","nonce":"265413d40ec644cdf98205a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"fb710d468fb94e0097886a02bf4bfdbc2c9ec2a07db61bf232a8cb357d85e367be257c9a482d79ac76422e2571","nonce":"265413d40ec644cdf98205a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"5427f06f090a3dc66ea10bd06cf0470afd60592b9307b6bc804540ce01aa70ee1fa1ce1de392520113912a2c27","nonce":"265413d40ec644cdf98205a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"ea9731bffc850092d269eb2b0c07e53970b2e741389c4b4737df5660880f293c0b5af07db1affa9e8d4cea4efb","nonce":"265413d40ec644cdf98205a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"20a24642082afd82c46fe2ce4e1a851a5a229c6313a0073ccf85256161c7205e6200ea6c9144cdd24979452696","nonce":"265413d40ec644cdf98205a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"2d01996272a6558b29f80d652a127f0dfb119ff1f634f211eb8c9445dc9f31d680a68052b38e5e3a2aa160cfe2","nonce":"265413d40ec644cdf98205ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"6a22579f20276e231b74e1139c4b95e4c688c3689bd5ff7578f2f01d8dc06b172e0bb8282e5210df3f430038a4","nonce":"265413d40ec644cdf98205ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"6b4862dbb75ea32073fbae2fbe79b8dd3948d6952ef4be940e9bdbb2c50e8ad7491bb206347256e7ca49941a98","nonce":"265413d40ec644cdf98205af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"f6ff7de618813fa4d836802a6b94f4931bd7e29a7f46fc973ab71c2c6606ed051fcd43c746e6f6df5b6aca0fb1","nonce":"265413d40ec644cdf98205ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"353c26fc7a628ca22e9fa87fad84fdc599bde52dcf3c8d339dca5c41a10f1ad2540466883032b27b255d31a59c","nonce":"265413d40ec644cdf98205a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"57fd539c7ccc06091d83beee042661a0dd371494901fef60c6190aab54e43d0438eee9e286ab21d3ccc17ca9ee","nonce":"265413d40ec644cdf98205a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"9d83b5ad279ebb5d236b607531b2cbf18505a3e6c0c876b15d7c44f9bee3e29c177853028ff03c86de5a0bbd41","nonce":"265413d40ec644cdf98205ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"52bb095cd9214bc578d5da243ecc33ab4553d58b8aa821ca72f8c9c94fa9e92df38c24294ef43b489cae7f7cbe","nonce":"265413d40ec644cdf98205aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"3e02e38ea95bf750c988f69dbdc06c183038779ef23b1668f76a170bd5efee91efcf1ef0b8c8e793df27966fc9","nonce":"265413d40ec644cdf98205b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"4d03252d9bd7ad8878306845cf64484f6215973da9e2e86d6dd0975a623cbcabe434c1206cb4240b0b70bff9ca","nonce":"265413d40ec644cdf98205b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"75e083626bd5f869af1e91273360bea3755a4e50cfc2e6f73da07660778edcbebbefaaf3ef05f32f6133660a8e","nonce":"265413d40ec644cdf98205b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"c5675991f8134d0e84968f07b7a7545817137247d6f04bae59d6bcb9c78d17713072833644681a9ca1a6669a26","nonce":"265413d40ec644cdf98205b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"c1fac02cd1acbde40d1edc60ceba5ce4fc6ad0e241394d13960c63b3a51f1080e0965aa05a5cc92608e41d7ab0","nonce":"265413d40ec644cdf98205b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"cfb1c510f0ba635eabcbb8c5b6caef8cd31fc564d693da7c6cb387874e8c1561c43835f310e4b4cbea8de68dbb","nonce":"265413d40ec644cdf98205b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"215b99dbc0f26ee02a344d74d32a70541f241d668e2d940095d185e1b244a51eed209f6329eabc7590e89faccf","nonce":"265413d40ec644cdf98205b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"3da2baaabbce969295f54fb8124289cb3717d581f47fecf9014c6933843433dd5707bdda5c67fcf3f552ba6ed3","nonce":"265413d40ec644cdf98205b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"4d8e474d07b4903b1a73eac36d0ca494750ca1649bf5ee7a172e283d5049fa6d1680ded57b816d997634f0992d","nonce":"265413d40ec644cdf98205bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"8c9c92e501f09ecd1274ebbd7f6f34949de27da4f5f3be2425a59da18a0cbe69b6a93836c12a9774cc7dd452fb","nonce":"265413d40ec644cdf98205bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"0679fde83605908b01579767ba5efa48877b2c0fed9f7c9c9575f7286967fcbd3083154205128a861bd0ea2a29","nonce":"265413d40ec644cdf98205bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"c6eae834b86c41059a06ac6d0b4b0165a6fbc965993270f233363ee08a2e7d6f1ded8c1a4aa7ea50b361520df8","nonce":"265413d40ec644cdf98205be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"e37e46f546476ceef480006d004f049c44be083192a8d1e70c6619dff036626283e45a88c1d8560e3774e8d63d","nonce":"265413d40ec644cdf98205b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"c255636808151c814e0946dc42d9a1ff4ca0b14fe3a82f661f78039403622f1e41a167f1eb6ea04cfdff7b88f8","nonce":"265413d40ec644cdf98205b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"7860281de63ee36bd8a894ce3d407f117ba2c5728d61962be368091927f1c97d9e8b26291c76edef6425ef45f4","nonce":"265413d40ec644cdf98205bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"0cb9194400e78c2b5422302b2ab7a3ae4fc3fc26dba511fb71fb44f26d4e0465d558d59b77767f77f652db4824","nonce":"265413d40ec644cdf98205ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"f10aaa96e1f41a9042d43dafe81fbd0b8d47e67da7d453e0af15414a5fe6c1a206f0f566439fe7a3be8a7dacde","nonce":"265413d40ec644cdf9820585","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"04446d7905250daa1de1802341a6e2046927818292ff3052ff79f2e745b3bd5ffcaaedf2f656d95172b0ada4f7","nonce":"265413d40ec644cdf9820584","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"91a7d1451ad757a1145c54c5e7d9b405798d578890ad443895b19b43bc92f674b827da64af03fa0e8f2f42b77c","nonce":"265413d40ec644cdf9820587","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"f41b3b53df77e0e8c377921291e28d54763c5cd237b4839541cc642eede0122a6ed7cb268e4a47a12ea533a9b3","nonce":"265413d40ec644cdf9820586","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"5866215036dddea604aa668b0a478b726d9ee922b61d6b533b3a9a045f34fda65b1b0a9bef0bf711e2edbb594d","nonce":"265413d40ec644cdf9820581","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"86c8dc470755861fb9e5b7dc44fd1301c6c601a8b276e719a33347a2cc9d0c75a444583888d2e508add8a03541","nonce":"265413d40ec644cdf9820580","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"9a3a2c9a8c0b3602fe7ccab1f5b92f4ca931a6d6e9a0c6c86ac1612bba244e9a836420fb0f4e9dd11974de31b8","nonce":"265413d40ec644cdf9820583","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"112cf113c645db15d4537c85adf84f51cde012261a7791d043c644ddb9708985256a672a733b3591ef351825bb","nonce":"265413d40ec644cdf9820582","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"a291910083b7d4b4629287170a5cab3b268e5413ca32cb91abe97863960cbe3e5c63ad944395446a16f1d379f8","nonce":"265413d40ec644cdf982058d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"cef6953371181adb575ee4990355243b6c3b6eea7a0b6315dda64f6d0113a11829364a43e662305c7e14440662","nonce":"265413d40ec644cdf982058c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"6ab37e3a9c419607bd407cb3425b838af6a28a7366110496f915622f36a33cca451f4ee09438c6343b0d61a4fd","nonce":"265413d40ec644cdf982058f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"43fefcc0aea3840426df7b4deeec354084d751f4fbfa233f929d46093bad492cfe059bcef6a75c3160c164252e","nonce":"265413d40ec644cdf982058e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"8c26589aafb56dc851871877edea04a827092b56acff6e587af98c3ababe7de6c0ce2882a5096ae671ac97980a","nonce":"265413d40ec644cdf9820589","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"b378f6fba4807fbecdc16e1e5e4df7409bea07de6352456a3977fb4d55eb9eb91e50582ef250b44b7893a42bde","nonce":"265413d40ec644cdf9820588","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"0c9ef774ca65d8485b4b1871195c15412aeaa73f50593856db2f18a43ba2cdacbe5d5857ebe861abee051462d2","nonce":"265413d40ec644cdf982058b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"e9e3e29d784d67e8a447eb4fae2eec3d9be56e3c26901d45aa1260a3518b282e3be615850b5b26af7a7b763a16","nonce":"265413d40ec644cdf982058a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"e7a98709fd8fbeb6b3f27afcf86dc745abf712a59afc3a24994b101e2b939574193db83de7416d1befbe9faadd","nonce":"265413d40ec644cdf9820595","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"0448d7e9b84e4c2861f16f4e8bb55880dd63310c81f74a4d297e1d45ad466f80ab4312b7426b50a0fae8a29386","nonce":"265413d40ec644cdf9820594","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"b8e6ff4cecd6b995bf2f250bf09c8b1dfc28eae5c1b88ca096b1fb60245119f4a8bb744b4fbf6f12e2c88a28fc","nonce":"265413d40ec644cdf9820597","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"13a832693a06598ed7cca4525cdbc9c9708c890590f381ff45d1f1f8f8b055ee3468d999b6d31b29d7ac8a861e","nonce":"265413d40ec644cdf9820596","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"771063f506cbc46a67caed4d0278fbdd003cd667d2b7f8004ae0c271e888489dd633a3766cde19f55ef5ac3e42","nonce":"265413d40ec644cdf9820591","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"7e31ae8a70bdf754f479f69eea0841ede12aae7a4941e588ce03c2089eb7660a9469ccf1eb14bfdc230f9be3d2","nonce":"265413d40ec644cdf9820590","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"28fd9293863f727d22e294acc3656337ec085b8dd49b9b9dbf2146bdad1394befc6bd44d7358b60a62670a9daf","nonce":"265413d40ec644cdf9820593","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"17a24cc8d9a122e513dc7c9178eda8934b9f201660ef94c1c14b1406dc3bd1e3bf24e261c2cfc241f3c4d65b20","nonce":"265413d40ec644cdf9820592","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"8454bf8ab65f467bd7ff69dfa3f24e6a22837c8fbea9be59b892e603a92acff8f7fdc8c6da543faffdbd498692","nonce":"265413d40ec644cdf982059d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"92be68294fcaf79b879f9807d14b7805fa4c49cd3043a54763cf01c79da08d8851ef4c8530a93dc72093866ad7","nonce":"265413d40ec644cdf982059c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"ebb68a8e8789740400bf630b9af53716870afcaabfb4704d4a0f7d47a41292be140420f187a45b5ac9c0f7dcab","nonce":"265413d40ec644cdf982059f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"704eaf5aeff9cfc58bdabb3f986e91c01a35e007c3387eb1d4d044ebf5438bae49fb44a97421f781d2a7566741","nonce":"265413d40ec644cdf982059e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"ddaa911402476f43e8e0e6753896b3176b09a423cee90ac595f72a1bb0009b4ab08ea9eeab66daabcc599714f0","nonce":"265413d40ec644cdf9820599","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"22e17e4f52c15e5c2c3a49efdfc5c52a0ca5c2200f6dcf9624c7b9916679ae8d845e4d2bb1083e8fc3e1aae6d0","nonce":"265413d40ec644cdf9820598","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"60486dcedead6fb0bdf4e82b3456211ecde69fd4d310a8453ab6d3625d155a9120292cdf164c4a3a0cb1ac0dbe","nonce":"265413d40ec644cdf982059b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"5a00fcf87daa464072fa3ecce44fd3fa382df79a4094302d14f5a133f6a690e6c36b6bfd97aee7c4526e3abb14","nonce":"265413d40ec644cdf982059a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"f7a64a12c3e68af26f05019d0e9ca40b278ff9f12cf46eede0dd01e8039afaa3ef40654c9c0ddd2337c8b51ad6","nonce":"265413d40ec644cdf98205e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"3c3bf6e3b08fff23cdfe43c0153f6efdbac00b2fe9251c16b1bdeb178d6ca03277c45bcfebf92c9a473457500f","nonce":"265413d40ec644cdf98205e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"7fbf3f1b85b0a8af4fd187fc00024ee56ba7673690d54a13c6404b8cce625d2e2ec727042a2b18540d7b24ffa7","nonce":"265413d40ec644cdf98205e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"f87e773110dfbe0dc2d88b73004ff2406b633023f3acb857e9ad29bbc0b06e0a0131872d9fe8f08b485be321c5","nonce":"265413d40ec644cdf98205e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"54bd69a302551443e177b8470a1762910838dcdf6540e71e0a9614055ab28b0cf9daae8968ac1621769431d45a","nonce":"265413d40ec644cdf98205e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"9b02b68f7e6d322e136949b5fbe4fe8e01452b129980b8458db7553f3e89d98fc72c44769354ebb671e24412e9","nonce":"265413d40ec644cdf98205e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"7efd957d2bda1424e51b3ac8c84c7295b28ddaaff50b5bf72461696a96cb6242923cd3b27982dfe41c891991fe","nonce":"265413d40ec644cdf98205e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"8e2d50e24093b53e2bec707d5c3231401104556f1de948763a175355fa250c7f3f01414cc705fc2b6e7a36a88d","nonce":"265413d40ec644cdf98205e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"df707f9a4f5a466504734a65ca6fba43957c69c85a655e5bed5e9b039dbb2bb7b99e95ce9cd6775589a1b7df11","nonce":"265413d40ec644cdf98205ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"ae9282a2a875fcd6add751b18c2ba46cd61d154849e7c89c3132fbcc61a40c891e64d94a8787dffb6beb262ddf","nonce":"265413d40ec644cdf98205ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"5f188565bbecc7031a099395eeb0d3bf524403efc6d8c711c6f6a95e734cba6030192263a67598ee191317774b","nonce":"265413d40ec644cdf98205ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"21c205dc18a55ec5f8898acaf7c946ca0471bd5e560c555f004f5a9050571fda1e1daf07b088b3abfb8bdf03d3","nonce":"265413d40ec644cdf98205ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"863fcfa15bd103be0bb0236578b41e8f1543e0dec74b23ce31056533b1bb80b3c4f56483d921702243e4a23085","nonce":"265413d40ec644cdf98205e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"dc95cb10b8830f20d61931cb3708f37804f39a939c6cd64617d1e92d768856c1bdb45e13b8fde68a4b8c4a8d13","nonce":"265413d40ec644cdf98205e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"3bdc682cccd6a4051a4d90dd1b9849a352778e3280594ca805131701496d4758ad12a22230e1546653ef6a08e7","nonce":"265413d40ec644cdf98205eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"ee354855b84554ad4fbf519d06af6b6c7173e24a013f0554b3fa6393ead30dff12ca1458897a72449b9fc2a87e","nonce":"265413d40ec644cdf98205ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"983bd79e49433faf1d9573d6d448cd2b14105a5dc3c9a683e5b3bd5954fb0d37e58c49a9de357fa1d7488a04bd","nonce":"265413d40ec644cdf98205f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"ac871676a754ebfa7f63d4601bfa8d264aa965891f0729eceb6e2a9383bdcfbb6896acc1dae8800b66577ef2c3","nonce":"265413d40ec644cdf98205f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"7f62e8a5760904a7d8d33755783b7f92aa546a2e50b416eb3040e061cd0241ab012ec3aaedc1b515789019a8f3","nonce":"265413d40ec644cdf98205f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"e349ec4a4238f7ea5bd76961707585db4efe57f3ad59620cf87ab81486e66f11fcba1e475833551beebc2999a1","nonce":"265413d40ec644cdf98205f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"dec5766e30f1f1ecfe5f40313943c1aa499ab88183d4ae8d451dd449e35e77b1ecf8269b077f74ea9bb2b80e28","nonce":"265413d40ec644cdf98205f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"635548b6b70674e3c714f9d3139469e5aaf98fdc85cf0fe454ebfd54d77e8acb7a34c7db310249e2061f587ba2","nonce":"265413d40ec644cdf98205f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"1c75986abc0e54b94d01aefc677705802583efb2fe1fbb676e5bb0acd41486c43b3b3c269150eb0aa194ecf924","nonce":"265413d40ec644cdf98205f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"da80840e74af07f317f203bf1578e6eb08c00f884d047d05215656680d8b92bd0e23bdab23c73416e57b7448fc","nonce":"265413d40ec644cdf98205f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"70194528d89a7f94806a7be7dda7b2901e041e28eb74225f4bb58dfa07104dc5595387bc328bd3dcaa40a5eff9","nonce":"265413d40ec644cdf98205fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"c21470281248f8402456c17c908e1d200a69fd0129bb6cb667ea47eaf8379b0e09e1354d48261d4031f6484fd5","nonce":"265413d40ec644cdf98205fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"384eaf795a01e93fb92894b8b2099b5039f953efe1099053996136329a9709289356a2a30cef8f499f91db2434","nonce":"265413d40ec644cdf98205ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"b1e75d746d5aed90312cc5cd7522ac4cc198cd830e61e6cb56619202df4b7f8c3af676102a9cc19bafa0ca22e6","nonce":"265413d40ec644cdf98205fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"8c10c49a653294eb75889957ec563a86030bbe7f42529b54e5e585183c3f679feb9c60d355180243ca6717ac89","nonce":"265413d40ec644cdf98205f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"c334d4f262cd1df46a92e6af98f6c9b0d282413415f8c38f86720ae4432a374ebb0bc8a34d1ecec4fa6b8733cc","nonce":"265413d40ec644cdf98205f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"2d30bfbe2e0418a75f3605a9eec4a16ea12e3bd42ee5caf1301fedbac9abab36f55e09785ae394f378bda2bdde","nonce":"265413d40ec644cdf98205fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"b24a7f2d65d9292356c513974fcdfe431a38218b00340e91e4d9adf501b77e8e633599dc9e78754c47c2fdac4b","nonce":"265413d40ec644cdf98205fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"4f26b05144f53bd244711f3fa0123dde11d01a78069ba20050868b6049070e7689cebe5fd869777c3bb5dd81f7","nonce":"265413d40ec644cdf98205c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"358b3a5c8d502faa738d5a15b1ca12dc24d4fec56c1b604ecbbce7afe48839792d4ba0000b333015d46b9d1b82","nonce":"265413d40ec644cdf98205c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"07efbf372c7e7aa7f166ce87a0fba9879ba96a9eb0e06a03e24ba7ce2787176dfec2a1a0a7be7f13b91563fa5d","nonce":"265413d40ec644cdf98205c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"0833297b32f82ccc4f04f6d4634fa17cfaf25f1403fe3e5ea9c6deed97d6aa76dc14bdbd6e675cbef52da7c847","nonce":"265413d40ec644cdf98205c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"7a630b297b2416a1392c0ad1f093b5132771a310c1e0a773cce461ff588b1b0b474b6e04fcc2f89ffc9752316c","nonce":"265413d40ec644cdf98205c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"b3a23709be199155f67d1e0cf21539ec296366d70062c8fc5811530d21a120075fefa991dfc2e6c5503955e086","nonce":"265413d40ec644cdf98205c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"f8892bb90df8e1091771ad1b90df0e74683560ef32fb5cdbfc1489997d60ede01a4d2298d566177e8da39726e9","nonce":"265413d40ec644cdf98205c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"b0a6da48e4bd7b2a0d8e7690c138d06a66f1c4934aab72388981a1ff083f7d37b1dcca6788e8838d2392d0e9bd","nonce":"265413d40ec644cdf98205c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"a37722af125c1df4037d94ae326483ebfc4edf16588157993b294ec234cb9c018f7df004a4847a12b153a8c04b","nonce":"265413d40ec644cdf98205cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"b6229ecf474f685a5704836c1d4bba7993b7b924e747e7b2ee0ed87099e717265fdd9aa6a332b7afd2c11f881b","nonce":"265413d40ec644cdf98205cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"731b334f8173485d8b9c3fbd2708cce22c3068435974f57259290e611cc9bf854a2a74475de6ef9c1fbecff19e","nonce":"265413d40ec644cdf98205cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"9ac58fca47360bbf4ab4d0e16a27b4881240210ee763aecd362e6c586775969639388ec96ab36cd1ad2c4fccfd","nonce":"265413d40ec644cdf98205ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"77f128799ccfe1873941bc66de7ff7bfbae78c9c90bd37e194b29c862751b59c9d7a64a2548087b6d685f23d42","nonce":"265413d40ec644cdf98205c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"b94b762b34c75cd7cb0ed2aff3ea473e5a9d857b19b949f5e4b8cd7d14d388eb0f3f485f5e6f38541ffa1f725e","nonce":"265413d40ec644cdf98205c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"faee1ee7cd6697023c7ecc044c66b6ba4f7c708b9e66fc8f235e24a014d39d0d0ddfc0f24db7796719f1b5d1ec","nonce":"265413d40ec644cdf98205cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"021dd09a2de96a91492c8eba81fc0a2f049cc63740e34eb8f5a98f73c6ee6f127aa0b1dc7afcc1dcff53b7e8a2","nonce":"265413d40ec644cdf98205ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"a38746d4fdafddc001773005300db056fad67ae34995c32b7b52fcad252c6234c42287ab7431b431ef3a42771d","nonce":"265413d40ec644cdf98205d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"2c77378ae7b177a19fc92125775537ab6889715153036ab3ea6892d092d7553a130398c3b79ebaee389d365a19","nonce":"265413d40ec644cdf98205d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"2d86706cec3934a528dd534f198257a722f621eeaf7a51de0f56f4164d5310c9803a89520e598e935f9a46a4cf","nonce":"265413d40ec644cdf98205d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"312b9a4c1d10e1fb02e245a8885d19f050494f2b740572a54085cf9583d6b8b50e59e4be4e147cf6b9a3bab91f","nonce":"265413d40ec644cdf98205d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"1148483073bd5edc98490539891474576def617ddab6cb89c004e69a5c444e768df97f5b4612f29204f19053a7","nonce":"265413d40ec644cdf98205d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"013c347172c2967552aff7f1b204a2fbd6d93148a7bc40807b96f45c7c6e8a86ad1593f505c4c706fa88c9ce43","nonce":"265413d40ec644cdf98205d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"2a877244934d752aa2acffa6e49fd049638ea156bd1b663ad05fec888937658b9a29a7602acd0291676c8a236e","nonce":"265413d40ec644cdf98205d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"67af4d9b6958b8e954c4b8d057659b10c06e78b75c4384a9a0d7b0cac9220fef960d33970c31ff2651bdb33aaa","nonce":"265413d40ec644cdf98205d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"c46094299ed8ea4efbbfcb156deb38f11aab0f01aee8ae1addf5d01377050c685fde257ef5900afeacd5ade758","nonce":"265413d40ec644cdf98205dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"2ecb86d84a1428162dea999a2f6b853d16eb602f459680e3bda03f09e513ed99d26a373ef3618728563aefad34","nonce":"265413d40ec644cdf98205dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"55cc3bd279714a23648eb7cb877e44d88adbd7db53680fc7e72f2871e15f7b1b5d8b3dbe92425c06bebeeba1bd","nonce":"265413d40ec644cdf98205df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"a468a10c8966b76d6526fd4c7b4976547bb465bfad99029794bcd116a5c1768aee709e0e8e4b1ba925d27d516b","nonce":"265413d40ec644cdf98205de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"e8f3c4c07dfd5084eb1ffbea0076a2e69f10e34aeb56d8923975b57217f0e3eb263714370d5aa36ed6271b62fe","nonce":"265413d40ec644cdf98205d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"ce6ef94ac1d95a13dd3cbf614eac1f104365ff6740ea309225987395466c82b4372fb662e9e31e4df2c984070e","nonce":"265413d40ec644cdf98205d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"ff3a951ef7f626c23b9e35f43ef13cbd2717913f064b9522c6c3c65394577e6c48ec2180721ec4445596dc8d83","nonce":"265413d40ec644cdf98205db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"b937bc0928036a6240623749755262b3fc54b45969b5bfa385311f8c7b12e1cd9979fd8fbb12972025f7f36dab","nonce":"265413d40ec644cdf98205da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"4537c5ed75ee43919265be010fb0f5192a8da5d9df7b0e4ae94e956466d1d677906317552296db250b73a8605d","nonce":"265413d40ec644cdf9820425","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"dec56ce715a5ab666d23d2fa58d0c2c94131f2093f52b90ecc95a11b1e2c5576"},{"exporter_context":"00","L":32,"exported_value":"1d480de2b86b94a2359bade239a1d3a3136c4b3e9d9b798d3e0a77de858cdf81"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"5b8f6e372e8f308053911b838781e3db005d1c1c29743da0a2fb569b483111a8"}]},{"mode":3,"kem_id":33,"kdf_id":1,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"93fcee51d56f1383acdc8b0cf725d3d33d7cb80bfb261d320000000000000000000000000000000000000000000000000000000000000000","ikmS":"dc954635e51e023970bcf496d784cd8ae6c470c5c43d2fba38baa39426223cca358844187056e8bd70bee3e41978be18db3971c5bf65873c","ikmE":"0335abb285911d4f2a138834f45e2c89deb62ef5bbac73f6ac68c78e956a844bd030c4da432aae55679459cde8a22ac3e994d8d9e67774ec","skRm":"6139ba1b3bb21d1fb9093d6f35b1a1e883136b58cc31a96b6ab92716686011ac9ecc00646f54291130d7745dad85cb26f2392949a860d6fe","skSm":"ee123d74cd5329adc4a7de54d6261ebbd6b04c295fd5508e97ad11469b830cae871267714e8d0e617c615bede74c2a7512a7d81173ec8e6f","skEm":"628c7c9c90855903967751f590df14006178274d550498c8924537dd1896f402c70f1a0425a372a98610f914dd50a6e8138c9aac9ce7a17b","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"034d016a449c173ff1223394f67c8c36bfa1542db9a83b5feb631eba4d5491765eea96e3f25a623b496564cc0aed3a6f42b84485a682ee4b","pkSm":"1b5c19ffc46ece82e6e7a9f65aacb8992ae1b406314563eda66786ff6264b3dc32aebec20856ebc906538f78a40bd3ffc239cc5ffa7a5421","pkEm":"c74f87ed9ebd9aefe693ae7829cd263fc1479e31c13730bc60016a99aa91aa8c8712736b41eb299d0ab88899be48cfe34f606d46c1851034","enc":"c74f87ed9ebd9aefe693ae7829cd263fc1479e31c13730bc60016a99aa91aa8c8712736b41eb299d0ab88899be48cfe34f606d46c1851034","shared_secret":"969d77045a6206a6574b17d7fe4cecbce4e1e0a17ecd632d827d3a6dd40b7dc42bdf8db94cd4cdfc729e220eb87fbed63f33c8e1b5aa5ff154e9a32cd7e73b18","key_schedule_context":"03f122f8796db694193e9c25a9085e064a650b1dd3739e34bfd9a653ff471adc1b87399003157c2bc488b6f17e65efdb0a55ebff5dd99ed2ce3d97d3473e69c23c","secret":"ec53b334906750caa1cfc05acaf16801647b697253009aec7501f609bf49573d","key":"f8e73b46c563b5fe8572125cdc04e700e0cd927ebcf716de280b563c42c19d3a","base_nonce":"59f4d30ec6d460025222c993","exporter_secret":"1a49a392b17655282b3d00815a9c528f91194d38f42c6760adde81ffff9dfb0f","encryptions":[{"aad":"436f756e742d30","ciphertext":"46be21ede968b8c4f520327402269afdb708dee6448ddba835ef26ea13f8eaefdd70550ee6111c2f6f5b41a1f3","nonce":"59f4d30ec6d460025222c993","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"b594bc8dc622adb9c7825e422bd772d6722b316b7f0ae7e49aabd02df5d192b2fcf55ba8ac6a4eae24da7d0024","nonce":"59f4d30ec6d460025222c992","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"633b32f9c546904d1df8ee9d17183737708dca4d7abf50a698331e91837d4d8f3cdc60407798208e8a190d2b25","nonce":"59f4d30ec6d460025222c991","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"10d8cdb63229c20356dd0f1ddc47c056fe0b00a5e615638eff91444a80603e90fb70d1feef6b278e0a3ee02569","nonce":"59f4d30ec6d460025222c990","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"85599438e517dfffeb582866ace8509cf0737304df9b8a7003d2a14cee001e9e88640d3696a22e05afb0488537","nonce":"59f4d30ec6d460025222c997","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"9c2b14739bdebcb6155e204e35fece04078915e00059144c319eef419d14884ddd5976ec2b1bc4c65e95fb3c32","nonce":"59f4d30ec6d460025222c996","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"747331d2c74f4073c7c2675218d00ffb6046441206deffeef16912c10a161e36ff2e04bc7e672de47a6c0488e5","nonce":"59f4d30ec6d460025222c995","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"30256f27b3e4d449a211b96d230cbb107927387c4be2ba093834eeb2aba38cc8735c8b41743d57b1ad13383018","nonce":"59f4d30ec6d460025222c994","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"0038bf52c31829d25f1a17fd60a56d91a8b6e0d3c3afc3745f2458c32f918735a485d9b556a2b96e86f84e4396","nonce":"59f4d30ec6d460025222c99b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"7b15406eb3bd55976564d2818ef587eaeb6f34a50a88c052d2596f408615a594ed76ba393a5ddc8f3f62f2f926","nonce":"59f4d30ec6d460025222c99a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"8769d1a42295a43f1066b5164d21cde2974a1b24f628b7767d613cb0e276fc63adae60b58d98dcc382f6494124","nonce":"59f4d30ec6d460025222c999","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"9d9b06cdd38bde00d15fbc9285e268fd9cfb8278383c3ed2359fa4f8fb01374d5513ccae2850dd963712d0c850","nonce":"59f4d30ec6d460025222c998","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"142dc1c60cce0fed317f19d4d1ef700cff01061f4464faf9172fd438be1b9c45e5c0202ae807d2acbde301feda","nonce":"59f4d30ec6d460025222c99f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"138f3115c7ef53fc04f6a0c33292f872b88e0c1754f4efaf4f6b4d533f6787116ab695bef56a0134a93f371a35","nonce":"59f4d30ec6d460025222c99e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"6f7423156ad43d59477aa25b00bf79c2cd638a83aaa3936ed737235a9fd8d1bbe80a3288c7c23eb5811a132822","nonce":"59f4d30ec6d460025222c99d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"990d5c8cc1c35116cbc73d76ae1f99f59a1922a7347e6939b715ffc20700f89d133654098231af8a50d0168b71","nonce":"59f4d30ec6d460025222c99c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"c5846fe702e4cd7250115a54420a57cc625bdefc51d15893694da869ff307f7dd7b2447a6f27a53d7df86f587c","nonce":"59f4d30ec6d460025222c983","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"299d16e1dae6b86ef5e5c93801541c078ea4611ad5a470ab5c8ec089f62007fd25cb7d339bc5edbd55a1d117ce","nonce":"59f4d30ec6d460025222c982","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"310b4314bcd214e821df1f4aa9a1534fbb9f51dfde9dd167cb233ee1b551fc3beefa4cb6dc5b478581f5bf8033","nonce":"59f4d30ec6d460025222c981","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"f800849e26a53d35b433838420875b9fec626ca3f4efb9213e1beed2eb145f636ae8a115c4824e735310f86e08","nonce":"59f4d30ec6d460025222c980","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"982d5b4e51f60f42a4b995a89d875211a835fa12093a011fbb245e4b8a75110c7a46a334cd11e88911430c58e0","nonce":"59f4d30ec6d460025222c987","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"5f9e6080dc086c7ec43e692bb6eb2ecb191483678b81267f778965cafd404cb355fee6235d54ced9ccba1b9e9d","nonce":"59f4d30ec6d460025222c986","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"0403bc0d3486bfea61c21d9ec4f4f986c5ba1a40c48f4df73c575e416c19afca1e5a6d44b18009074d9194c480","nonce":"59f4d30ec6d460025222c985","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"77eed0e897c4cb870baa891ca104b63f12e54321d6af9590413ce2ebed2ab7244f9be4fe0277f53a61fab32533","nonce":"59f4d30ec6d460025222c984","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"63731d964b523303baa1cebac6b5476a6054ff698a81684e5dceade12366303b2dc7d9c3d97c38fb4cea5f2489","nonce":"59f4d30ec6d460025222c98b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"39aee865b3c0322d8f405379254c6ea157704e66f969c1e2710975250c83cfa36f48dee18c4dbd7dac9118f4e1","nonce":"59f4d30ec6d460025222c98a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"2e156ec0b6538f69366c8e4187224c6966baeb4c6af05072830beda0c6a19b4fa046f77f60eafbe824046aba65","nonce":"59f4d30ec6d460025222c989","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"4853f996ae3a9db70a0e3827b59841a14c56eb940ae7d7b48251f6039f86330df5bebf1d204758e4da1735c5a4","nonce":"59f4d30ec6d460025222c988","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"e8ddbb4542b42b6ffcb5b704ad2f2ddb574521d88257a7c5e4662696c37f6493e66cc69d5b5448b21df511d25a","nonce":"59f4d30ec6d460025222c98f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"48dbc8ca8653b9493aca5eecb1704b7578a8e72fbf8c3431ac76b4a27fb1ead62a2740463df6dcd3cbeed6929e","nonce":"59f4d30ec6d460025222c98e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"69f7499d828180c4ed45d2b7c1c2179098b33054e6dd5acd7d5454aef95eb22a259fedbc14720452207c363af2","nonce":"59f4d30ec6d460025222c98d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"8eaf3385704c2046b85174bcfb3633e543ef92033bdffcdf615727d98f5720e79bbdd592975d63035ef75077ec","nonce":"59f4d30ec6d460025222c98c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"f99a419bb3d3ab4ec27c3942d46f27a30fdf2821119718959ef34c09d33e2784b328f8efdf415d5137ab14081a","nonce":"59f4d30ec6d460025222c9b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"938da69aaf95a7efd11866c3f474b6d70e17f9078bbac93b3c8524f009f188d6779ab39413cbed59adf9185ef3","nonce":"59f4d30ec6d460025222c9b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"8c47037cc8a5f15be24924de4e338a6fa06d66dfda883b4a0ddf93d6cf18e682a4dab4176f6f9b29f55745d80a","nonce":"59f4d30ec6d460025222c9b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"a918615d356a8cf7f41293a4ff38d4895c9611e4a2f0838d86449f0961fc60162cc15f1c5a125fa0ba6b86cb56","nonce":"59f4d30ec6d460025222c9b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"534a4a801b464a9bf15770b70db10062c63b6be2c97b616c7fa0140331224736991741c6c21e5cf9ce9b6ee856","nonce":"59f4d30ec6d460025222c9b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"9cd74572f8d24d2790e7ab6cca57c3e493a5cf467445b6f0fad968ea307d63f4bd7ee53f9bf6f645c9cc24dc66","nonce":"59f4d30ec6d460025222c9b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"e85d20da022555d68a35a1efa0543fa33d3d7230076e467e9a09e28c7d1a8387d96bfa284765a36443b0d3f3c8","nonce":"59f4d30ec6d460025222c9b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"ad1d635f26294fd2ae8d4223fa05639e47dbc5993ab3e9340fcacd6a30f6a168d1f530fd9c22eeacc4976ff852","nonce":"59f4d30ec6d460025222c9b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"bbe0871cb0d6c2a45e24be66599639e335bb4efb3533ce5fffe1b6831df94923bfc2bdf7b9ea2e3cf82ec936ab","nonce":"59f4d30ec6d460025222c9bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"2745c2a971dc68102fd4bc4c3fc664f83b625801f8ac12a1c46f5961af76f04a11d57e8f1f6ac0955c9b1ddb8f","nonce":"59f4d30ec6d460025222c9ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"6964a4b64a44615901e173fa05a3b9360c3f150ef01810306b8e73aa42333b73e230a7cb0b017d737236a60a24","nonce":"59f4d30ec6d460025222c9b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"e3cdebb0a363dce1f028e6d45c1ef0457e375a327878dd75925780ebdfb8880c3fc0893450aac066a560589115","nonce":"59f4d30ec6d460025222c9b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"5c8842b612945cb9d26079e6be76a75a5be164ea741cd1d584b5d183f3d8ac4f7d929b751475a5361b64cee825","nonce":"59f4d30ec6d460025222c9bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"6d445b8fdc10d1b8b1688c68855e852542ae3615b9ce249663a7f48d97a647516ae317c9e78e54498d7a1a7896","nonce":"59f4d30ec6d460025222c9be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"42b9d4ac783eba2d5fbd8dfd05f92d356bfd95979f27ec3b6b9ddb4f7c78b0506c3562904b61b269ffdf28ce3d","nonce":"59f4d30ec6d460025222c9bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"f8ab928a0cf65db7d8bdbfbbad1e46c1b90f6c374381124b694e95f0f6446143094de7bac4b0b449ec130f0cbf","nonce":"59f4d30ec6d460025222c9bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"5433b32074502bcf1743c2813603076265b9c2b6c47136aa3728a19da8dcc040d2abf529b14af0db4b648034d6","nonce":"59f4d30ec6d460025222c9a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"c9733d0a619993fcc40cc5fb3619de67647c0c563b7b48f1c035f658e86a5d2d640c0781095b756f63ee9324dd","nonce":"59f4d30ec6d460025222c9a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"00a9723e8f7d1423031bc546d33ab375993ac72cd01113123872f00d559fa559616fc5f6611161216bd6f411e1","nonce":"59f4d30ec6d460025222c9a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"c6c7b6939fd2c26ea5985f17dc0bb2ae3f86601e4ae9bf3bee1c6fc123d386ff7dc081d5900fdbb782b2f8bc1d","nonce":"59f4d30ec6d460025222c9a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"e3dbc26c9f21c8e446f71d2da132bee83e0b433e71379a9b541c846d11f61c1f9971df2f0d0a1b0479d8ab8abf","nonce":"59f4d30ec6d460025222c9a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"de07f48e08a61fd169587b6ac2ca6de41c446f22bf7bc73f80862ce4d6ca9741b2a3b11b6cf1a4542b4f5d2a8d","nonce":"59f4d30ec6d460025222c9a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"1e2193263d40ae33061c4cd847e0523327844142bcc6ce92c1f2b5629f4c6cd245d6ecbaa46a074d3ec10218f5","nonce":"59f4d30ec6d460025222c9a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"487766421783f1367ff7eb3f7f4d7b5c100d0668fc0a36224230fdc7c79bb3864ba5512e5b09d9203c716a9bd2","nonce":"59f4d30ec6d460025222c9a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"a7fc1116165a64eada8fd3ec2f24fbc9554fa039ba56bfa22576010faa8dd433eab9ed80eef9caa2cb23d43865","nonce":"59f4d30ec6d460025222c9ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"30835b4930fccfddea92fab3890842cf0e4efcc9832880e292a511bed2583d8963bad0fc2efcbc1dc5af917433","nonce":"59f4d30ec6d460025222c9aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"8587f6d36f571c5907b26e8c5ef8d99c47ebad9eace1a95a1f4fc995ae1949b204c46e3df1238fc15496162f5f","nonce":"59f4d30ec6d460025222c9a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"aeb776a2ac18a109d9468f92f022e672775df888627dfa28f9ef2b9443c0301e7eb836958aacca818c18c3c423","nonce":"59f4d30ec6d460025222c9a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"7bf0516091ac4abb51b0a57c6f8dd3783723cc2c7f608a51880ad5800672aee52897dc81f27bd080b6c50699c5","nonce":"59f4d30ec6d460025222c9af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"0f2d8d287c76bac313c54ba6100461adad6bb7442db52a9d4362af5f32dde8e95b9daf475f17d19b688f93bd72","nonce":"59f4d30ec6d460025222c9ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"c7af23d0aaae0181aefd41291b46f55e4baf11b44b461a0fdc543090043255df10410c3886b4a86a8131cce0ca","nonce":"59f4d30ec6d460025222c9ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"e2282a3b3cbd6541687895a91b866cb188e98c82ae12186d9f26e62810997d90832d8c8ede3d2551d59b3a61fb","nonce":"59f4d30ec6d460025222c9ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"13c3b589d18d718aaa7e57e43461ec5896d9699dee640b231af6f589bc5c1baa30f03ff13f9cdcecbd04e25522","nonce":"59f4d30ec6d460025222c9d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"5181e5607310417e688ef871df773e2376530c1bc1d039908d780c9fe72147bc0257126dfda0598b2bfa61886e","nonce":"59f4d30ec6d460025222c9d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"6299ddcf2e1148758c8450cc16e065f06a6960e2a032fea26fc9109eec82442fddd74ac4a807322d8161173f79","nonce":"59f4d30ec6d460025222c9d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"4ce28e5553a3b2a007e3f1a545da9b071d85ab4a1016c92a5e96defed3ef705d65ae5c013c3e597acf2fc599a8","nonce":"59f4d30ec6d460025222c9d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"6dbdef28ab3531750b11b05b5328863d8043d00b5c444b91f90e2146bacd3cdc5777179b44372df2a0229ce9f5","nonce":"59f4d30ec6d460025222c9d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"2bb14a25169d68f67c31ad31eb858ee00595a966221a922b72afea5fcaa1ad9c4fae5b6a68c0976fcf6ee8fb51","nonce":"59f4d30ec6d460025222c9d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"45a44f32e042b078a0839c4569c7cce243628fd7175f345f1bea16504ca870a8c46c57f9a68a0db8523ba9592a","nonce":"59f4d30ec6d460025222c9d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"1a65e23829056dd7233d0bb9ed0322d6da72aa1ee62bd895bfb86cb17a08bc017eba80b3414610ec052150e49e","nonce":"59f4d30ec6d460025222c9d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"c2afb9cb729ed4d14e4e25cb4fc417ce945e001f5150806fc306a70ced13efaff31b49c8e57b6a1aaf49bcc8f2","nonce":"59f4d30ec6d460025222c9db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"5d3915b3277944518040ba042d78f30d4629da271ebe465dcde5cfcb2b80644e2cca8902ea296204b8e9682496","nonce":"59f4d30ec6d460025222c9da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"053d2d4c284a88f9be29bbf9d263710d142ddfc11aa8551542fc0f379e77ac66eba6ce8bc9b7d655c853f00d5e","nonce":"59f4d30ec6d460025222c9d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"4d8bb777d36b17b8f012e0fbfbd2942129dcdba9e20672afeded5714eb2e9be5d30994bcede94f18afd8c77209","nonce":"59f4d30ec6d460025222c9d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"0d770aa9c22c84b682cb7259401012527203de73c6e11ffff2a4e88584859dfac1294254dee95ef5352fa077e3","nonce":"59f4d30ec6d460025222c9df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"c6774fbc9e4f7981e908bc6db0f258aa0c6366e3768b54431f6b386b6040546b5f9028b7c3b06ffe457033fecd","nonce":"59f4d30ec6d460025222c9de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"3a0a71269728a00f6c75bcb677dba5c84a57e0555d8423a2e293c8db9393d1592e5703a1120ea52bde581799b3","nonce":"59f4d30ec6d460025222c9dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"de33dc0d0de545f291cc54c584cebea207a7fb92a979785a2da0d9e1c64e003fdf37afe2f334a737f2a5439f1c","nonce":"59f4d30ec6d460025222c9dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"577cf869576fcb932f4d6d24ecca05c1fabde86e816e5211b079deb1348ac5ff630e2c48891834066a68206e66","nonce":"59f4d30ec6d460025222c9c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"bb8010ca851e4dd93d0b4f85d234a9d22f5d96b24c266f705c701aeb7091b5124835d73b787c10bb7678c059a3","nonce":"59f4d30ec6d460025222c9c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"462b8016e424c3a12774e8720e51431e433ee6ea73660643643cce9dd840fc7a31ff1b81dde6895d0c75a5dd0f","nonce":"59f4d30ec6d460025222c9c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"7ced53f4cd55278f95e10a6558ef6204fc8ff5f3d1d065d8c3276721300fa7371b9a5859296fc97ee98301bbdb","nonce":"59f4d30ec6d460025222c9c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"184c3f9babb8bffae75b100b27aba48f18f2311cc4ef924d78bb0345a6bbf8120c4764c2b6d09888e8471b0036","nonce":"59f4d30ec6d460025222c9c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"9129ffc97d63acfee923afefea5fcbac33be37788276f15361b03f8e89c55c19843c93e7d68dde92bbee06e84c","nonce":"59f4d30ec6d460025222c9c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"54ea42f27ae2c6f2670b0efaf15a4d15e9fdd6d5dcb001297d3daac772e0fa2d191c158d2ab0f05f2472ace813","nonce":"59f4d30ec6d460025222c9c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"408f46cad5f8eff3aa018913c2346f8c32ffac52cf1a1f8e48b0fa863beb533865cd7d253f72e1b14100d50524","nonce":"59f4d30ec6d460025222c9c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"70b5dd6e8b9f58e9d96460fe39d48873076b9fc010e3e98e3f8dda738460d4351db054a13aec1b405427b5e247","nonce":"59f4d30ec6d460025222c9cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"136a2c92ce73e0fc060bdeb785a86952b3d5ac368934342d6a6e109b7fcbd6175475b446a55fe1b534eb5d38e6","nonce":"59f4d30ec6d460025222c9ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"1d85eae19afeacf56a90fa583fb07bb0b833467a6674487c27b50b23abf7608bd2c77f45cbda33e7ecf9b73884","nonce":"59f4d30ec6d460025222c9c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"09220e3ce28bdce05094d15f69be342165c4ff4dc299f97bb9db917e40c503cacac91679e87837b2909afcaae9","nonce":"59f4d30ec6d460025222c9c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"4edac45585f65a97a5e9bccefe722ed1638f2e83eb90d4f05857251d5e90a127044f3d8d3b681a89049c358952","nonce":"59f4d30ec6d460025222c9cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"76f311410de633196ffde8f657d7f78306e1b78e77504993cf644d5f5173909e4901244f29829e9725fc3c2e0a","nonce":"59f4d30ec6d460025222c9ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"0d6f09b757fed70c4f4abca6f33451f657f12b8c19b7b7c90f32279ac7905cc587f5c3b7e8e19a02aa2c7b081c","nonce":"59f4d30ec6d460025222c9cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"f71ce78da25283e9fe8d415afe372ebd417553a508fdac13b7082ef07ad262bac825d60c79d25edeea7eb72870","nonce":"59f4d30ec6d460025222c9cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"ffd808009e73fe65211327cdae53f46e08ee0d9429d104d1bee63790bc103e89399a17eb42a273890175976c25","nonce":"59f4d30ec6d460025222c9f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"d3a9603cdbe5d46ffcce0220dda5dfcafb36f5830a906c7dc4e3a119cec2ae58546abce522fbc70ae0a4f9892c","nonce":"59f4d30ec6d460025222c9f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"5b6981ce080fb59f453c4ec9a7b3a72fc4929a7c4e9e2a5ca6ee054f8e016dd405554beb102bf9bf5a08d6c8f0","nonce":"59f4d30ec6d460025222c9f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"1a1a254198803f66939cf0301bf3b81473281abdc4bc1de734d8c2ff7927f3ed96c6cdbd8fa629ccbde61ad9a2","nonce":"59f4d30ec6d460025222c9f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"f74393499fcffc67c6fd27cb6463d738310c38ca44a9209144fabb3d2296d40760b0b0933f8ebdfc4066ebb064","nonce":"59f4d30ec6d460025222c9f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"9b01d49f42beb523bbcc02bd3b1ef0b8ba70b109dfda6d9e57031480276ca8de6e7aac28e0d7a957b67ce9c8db","nonce":"59f4d30ec6d460025222c9f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"e9d1a0db15caf349874f9fddcb190095599e16b49761718dcd7ff6700b64372ab3a2e45a42b1a2b662d6f1e71f","nonce":"59f4d30ec6d460025222c9f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"5f12fec9d7bf25b8a5f8ad84c97614ac484b6f08d421b42c506fd5f6811f6d197751b381c35217281e54826afd","nonce":"59f4d30ec6d460025222c9f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"d3de1a634ff69c1d508276dc200d21be5f82e9b0e3deca66c01f04a76fd6f16dc55be2b65280b0f5ccf859f2f3","nonce":"59f4d30ec6d460025222c9fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"ccbf3923ccc3cafeb0f6c7832565667af0b7f2c6ad29ce020494db06ee1da65bcb288daec879cca9cd04880195","nonce":"59f4d30ec6d460025222c9fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"853327a82edac4531265ce77bb4fe88d4659076ef60b212532ea7ad9380bad11a8fd0c9c321059fdc6a3ac9e38","nonce":"59f4d30ec6d460025222c9f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"107a2298592a4ff7eead3e058de3d5016a47e3a31707ce4bbb7711ebc7c0067c17595ad4f50277d33f8cb3c622","nonce":"59f4d30ec6d460025222c9f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"a767aacbadeca5bfe1557656280ef77ab58cfd9a11f0f638d54e6eea20a74e003e47d55bdff70e83030799cc6b","nonce":"59f4d30ec6d460025222c9ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"19ad015bbe1170697539d0d95b8474fd022fc6d67e99e0e35fc3e07484cf52f52a5ef8047c1a0634ee4ba36d83","nonce":"59f4d30ec6d460025222c9fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"a3fb99e8ce3d3e516a6df21f4e97bfaba2e838721a720d50204328c98ce1edc030e0008b52ebc11296a6c602bb","nonce":"59f4d30ec6d460025222c9fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"95cb76bcf5990ee2644bb5af94d072bf6124ef7017a94c71e67fbb8df08458462ba65adad535988da70529ac67","nonce":"59f4d30ec6d460025222c9fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"9eed8c8ae44c6a818bb0aad09e9bf692bd5d09af71250f1888830ed33a139ddaed149b0653ccc39a947483c831","nonce":"59f4d30ec6d460025222c9e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"70bdec96f3399d042c7d773ee3d2405f7ad05e1725a368802bd3c1e36e47267aed9c5c220a7b6dc4fd9b2784cd","nonce":"59f4d30ec6d460025222c9e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"9594d4f19f40a903b6de41af9b9d5694b995e57a596a2b995df0eaf4b7fc9d585371971bea308bba97262c2fc5","nonce":"59f4d30ec6d460025222c9e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"971e6ef0176386a8af0a78a03d5c0060a65c18649731bbce4338d85c0e724cb64ca2c65865bb4b938a55ed2b09","nonce":"59f4d30ec6d460025222c9e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"9140106b30c4d92615169a871e4730e18405959a59c69824a7f22d9af88eb9197c2b87c454e6b0b759d549a82e","nonce":"59f4d30ec6d460025222c9e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"3c6bdd2a19bf8366f50cdce088cfa0d679199f040b6a52c94cb6260df42e2a6b11241dd14f9539501cebceb9d2","nonce":"59f4d30ec6d460025222c9e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"02c1c8c832e78dcbfce081200e521ccf377460aa9d9a2cafc94a6e7988d7703a1f1e52a601b4e6bc65e0e28fea","nonce":"59f4d30ec6d460025222c9e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"d4b36119a7ff3c8dbbf504316d6d6367de6aab481f30c470e49f23ea4f3ad65dc9081580c8f3989a578d1c5d9d","nonce":"59f4d30ec6d460025222c9e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"c86df57fe478bd074350cc7acb4f55161330ca963bd3617a880c64d14b3ffe17a38af19e7eed6f81816c259816","nonce":"59f4d30ec6d460025222c9eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"8dfba1fa03bc5fa95115f81edf70894764e893c961521df89cb4e6cbd2cc32a512666c6cda836551fda787482a","nonce":"59f4d30ec6d460025222c9ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"2185698122b2a69b5dd87a312a6f1f78296b3fb09a59022c63808245cfb81dcbd11ad472214ea470606cd01304","nonce":"59f4d30ec6d460025222c9e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"de9ec7fefefb75a21891b2aee404fc3d6fd962af934630f299ac6e092a3413bc1624b5bd953ec762bea5af9f46","nonce":"59f4d30ec6d460025222c9e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"4cd771323fc3e91f770c45af209495b31b1682449a4370608d3104b8cbf4bd82154a6e53bf0291247723baed47","nonce":"59f4d30ec6d460025222c9ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"7a40d41b953fee9eef0ffc0b5dc087e5c174ab01007c5800b7004cae732bbd75932f072930ad16fae7f288169f","nonce":"59f4d30ec6d460025222c9ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"39af3cf85445c1b8a714c8b5e17a64fec56c2504c07bd18bb971b2a5d5ac08c7ee39fc3a677ce0c3469edc4026","nonce":"59f4d30ec6d460025222c9ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"5d71b4cc1ce5914570f2031dcf86dfefabd9e121d6934f1bf3c3fcf032c116678ea37f4b44d28cde92eb8e39ab","nonce":"59f4d30ec6d460025222c9ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"d1776d68692dbd49fea6ba7e9245d120f0cdfc7388768fda162b1704e4c23d26b99cf1e4321f439754b6e2bd49","nonce":"59f4d30ec6d460025222c913","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"9528912d9bc04b789043ab7852714954e77478de7390e533d6addb272f6720c654cfe407d7f80dc17f230401ab","nonce":"59f4d30ec6d460025222c912","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"1c5ef1e7349c27a4f7ae66e7dd29f5cc717e002431264be8d64c0c73877b135ed2b5877bfb042438fef1edc3cb","nonce":"59f4d30ec6d460025222c911","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"f63911940fd815eec34b3b245c0f1c4597bbdad4d5a00f11c4a1da856f5f72d432c2ece75d5434fae789ed2e80","nonce":"59f4d30ec6d460025222c910","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"00e92ecabf01413eac48419f272daabec5b69dea35bcc568f8ed4fd56da5672b4254c484e9ecc571ef8e35b61d","nonce":"59f4d30ec6d460025222c917","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"62c7285abc81cf4ed5a3358895ddd01e6be55428b9e1de9e53fad9f3bcf0392679b51b1e995e274729f6b8ad17","nonce":"59f4d30ec6d460025222c916","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"322dd7b3563486da7014eb3fc7ab78654c92b59b75249f92a9072cd00ed753447ed1caaad9bfaaec576d68c533","nonce":"59f4d30ec6d460025222c915","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"5dad67a0c1ac6cffe8ddcf7ed21042bb8fa0ab5b4be6136b5d5564b226a4214f10e5734255d2cd03846850a99e","nonce":"59f4d30ec6d460025222c914","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"128485cb9ade62766f1590fce4770fe978f9bab69c5abed8ce69b39de817a98be1f77090d575839d14ffaa27f2","nonce":"59f4d30ec6d460025222c91b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"3fe9b29d1266315bf750a484cd47806e5be3611151ba93874a4a8d08efc3f418423d083902492e16afce3d38cd","nonce":"59f4d30ec6d460025222c91a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"721fe48a068c05bc42d28ea6e838f383bdd88855d59137fb5b0d315f621bd9e6847f4af37044f450a9d273bd56","nonce":"59f4d30ec6d460025222c919","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"0679b16e99d0baa2a36b69f85ce2e570a6870ab6d62efcbda5bea09812201c30928c32f43f035063e72f16ce64","nonce":"59f4d30ec6d460025222c918","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"77e61cb50415bc5545537606ed89903eb43c9d3827da08da499bc5bd0bfa3c5c9f288b11e4c065bbc465bdf7af","nonce":"59f4d30ec6d460025222c91f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"8eeef4de36bbf85831b4fd0cbb976ce9f261155d0e84b5ee2f61121ef23f0fa65e43e44d2eecbc541bfbf406dd","nonce":"59f4d30ec6d460025222c91e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"c729bcaec4fe4c139caee21ca42d8d22645e6d2a0308f2fa066804a27e24750349b038a5bf50c2a960e1c12695","nonce":"59f4d30ec6d460025222c91d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"72d76db8777f76dad2a0fd7738bfbef13656644b5fdd44c1bc8217767a3adac14034a800fa6078463b0c50ac0c","nonce":"59f4d30ec6d460025222c91c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"9a132f01dd1f8288eaf09f2d1f3662516bc5ca6576a8d5ff65e403bc980eca0257606fd582d7a206bbbeda6c3a","nonce":"59f4d30ec6d460025222c903","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"a1db928a630c03d54b30a05c07e380a78767e3e7d0e1e7afc8cfa55640d58951609a96eb5f9cbd60fdbbe701d6","nonce":"59f4d30ec6d460025222c902","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"b7b4e3de183f5979d8f450c913d21f27e5e01938d1e6e22498b31b2550c6b8e0d18c38bf02cdeda52265e915a1","nonce":"59f4d30ec6d460025222c901","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"17bc1d427c358d30b34c6bb2fecefb90acfce98666a6e78d58141d9d8f486e58bc93fd448feabb91af68415838","nonce":"59f4d30ec6d460025222c900","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"947b7b8636e2f5f5208ff24b941711f6b69eab6a517e981bbdb0a7243415ac25c39aabf8d1d632ac2f85871bfc","nonce":"59f4d30ec6d460025222c907","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"1c692322274d5e8f85fb39f2dfd3d0fa098d44da56fed8a8aa0556655c92db216baaf35ed74b7e8f0501944f2c","nonce":"59f4d30ec6d460025222c906","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"5e7cef1bd55766f610a14ea834bb318c79d38e97af7d538f0f972ea7368c805e5ff44699aefed1c947f4a53e3e","nonce":"59f4d30ec6d460025222c905","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"edbd34b799dce13273b177df1c1ae1cc068087cf2b73e77547cc26e636a2e9b9d117fd4e0fb78d3c342a613916","nonce":"59f4d30ec6d460025222c904","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"1b812e42e651afe6fdc8e6a5c9478b9baec544cb66943c417d8ebe8704a9560b2f4b90f3b3b11eae1a3678e77d","nonce":"59f4d30ec6d460025222c90b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"2cf5b1c46f641f8c103fb27bb738beb891376e17a727e2317ca3367ab6f16ff11ffafa524813751769594e1c98","nonce":"59f4d30ec6d460025222c90a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"7b8868ce244c10562e27d738eca24e796b6de0c3f5eeb28ea4cd2d656c7b866b7ac7779e039fa563a9cfdd0956","nonce":"59f4d30ec6d460025222c909","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"cdbb9494f3f1b5df53cbdffa867f9eb2af9c7d638a349b358b93ac9e69329e15fc4f3405695aa93ae3ef460115","nonce":"59f4d30ec6d460025222c908","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"9c96306127eb56a8884526e5005ea2ec5d65870a7a6d7e1e4641bd04408864884b59384c010d2db55fe3001e5c","nonce":"59f4d30ec6d460025222c90f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"f711fcdec1d981e95113a1ed66af4de383e514a2ba5b1c5e710a46d5261c1bdcdb4f8deb7e6cbff053e7933779","nonce":"59f4d30ec6d460025222c90e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"ce366d2acf1b1cb0d3546cdfe78a6d6f7176f415232304c223bebbddc1732e57925bad4869a6523c007f48ea7d","nonce":"59f4d30ec6d460025222c90d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"fc284390bfedb6efc4f18170215173e5e8b0edb50a4df011943f3e72e252376a254a3e252ea1add4de66420857","nonce":"59f4d30ec6d460025222c90c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"d8c038e28e9b76b3a2a092eee74a23fce66edf2952f15f3bba89860c0aba790c3b738eb9169ae52eb96f36930e","nonce":"59f4d30ec6d460025222c933","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"8b98568843b7ac7b7cf0876b50f92a354d171caba328a0dd8e4438e4f21fc5c883f24e3d8faeef0e7825607095","nonce":"59f4d30ec6d460025222c932","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"e09da5f89058213e8639c1347adb9ec1381ef3a68b8fb9217ca5642a9b0cd555d43a275a5d74d1ebcf618229fa","nonce":"59f4d30ec6d460025222c931","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"4b15f4254d0443f8e9286f00d21d6c549655d849323a92acbd1197ba620ced4f13b461679a42181fc027385321","nonce":"59f4d30ec6d460025222c930","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"6a7990aa94062060eaecc70319d8a2a2e7009826eca1ccac5433dff849e89e0a37647e51f8af572996c606ffba","nonce":"59f4d30ec6d460025222c937","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"0f6b6dc7d921931b1c640994748f3d4575096d022cd5cac0d5ae3cbfe0ae98304d1eac246f5f174c7dfe6cfa49","nonce":"59f4d30ec6d460025222c936","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"2ee6960a2c319c796359c60ab65b6f5d4dd2d76054bc10b287badd652248a70852248182a7d1cb9868a4919234","nonce":"59f4d30ec6d460025222c935","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"07637dda19f9516c4457cda60fe57606a5e883538cf05fbc313a55851063c4fd8c7030fbb7eb4c3b79758dc31a","nonce":"59f4d30ec6d460025222c934","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"bd0d9e62dc3d78a76a1ffff0e0d4334becdb4d9313dade47cd9b7a594eac6177984397386a980a1681592931ee","nonce":"59f4d30ec6d460025222c93b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"8f9bceb462480b6e6c1c385ae3d69810858e9b4dc2cf827ce63d910f44a692fd0610dca328c1350cf81422f11b","nonce":"59f4d30ec6d460025222c93a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"cbbcad04ce28ca73784e4f4b29e88af6b618f6bd700e6eafc377b6cff3ad0460d31fcfbe8a8abd0ad672e71071","nonce":"59f4d30ec6d460025222c939","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"5e3f9d671d34306c5f147d4cf7dc040c65c3565ea0e90117ea61826cf204441695b49030d8b3da5d2f0f746dc2","nonce":"59f4d30ec6d460025222c938","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"160f9482039ec56a7617b15ff3773aba8035bfd70d9d32214eac09701e5027991cc003764561bec21bbfcbce36","nonce":"59f4d30ec6d460025222c93f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"685ef8e7ecb16dcc36f8a2a4ed12065f63e9bebe8a28b4b7a7fc637a81a11bd46a92d1079bf24815cdd6c99065","nonce":"59f4d30ec6d460025222c93e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"0ac0dd737ff44a2e782ee2014292d10810474c9b052505e0e2228b751a01be51aa72acd530971be54f7066ba87","nonce":"59f4d30ec6d460025222c93d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"d804a67ebf17704d104663ba1385ec70695f70639c6c54c977750ce656e94c19384ba36b71624a86fea17c3e2e","nonce":"59f4d30ec6d460025222c93c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"9901792fb12528edee6505954fc76627ba87e34b5dd8e23b39a1872eb8893ea228cccdd2e62755bdd23e4f9b2b","nonce":"59f4d30ec6d460025222c923","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"886141d1bc00c84f88ef6a859229478d8aa83a1b1efe181817120359d8ed71006c339765b92eba098617e53bc7","nonce":"59f4d30ec6d460025222c922","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"6c0e39332d83a008425a61a19d6fc6aed47952813d8faab568067eb62d0084d7cbbafeea7df0d053e420687245","nonce":"59f4d30ec6d460025222c921","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"47450792af0c46fda6640728947ca54d2020062123bebde1cecf9c7cfa5a4ff39655c9a96f242939d6914401da","nonce":"59f4d30ec6d460025222c920","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"b3033208b65b36780a48746737bdbaf4edbb76322f46cd2cd0b7a1faac98ef8e3599cb13c4c2d3ca9de474d728","nonce":"59f4d30ec6d460025222c927","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"0406d174207c5c776be999e88202e57bda14e1d72c42785847f195d6e0b5f871702bfca99eaa38fa04e4a247d9","nonce":"59f4d30ec6d460025222c926","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"206df0b8ed48499e44482cf6774142e0920e86d5dc42635402635074849e92a4a669d8bedb74f00e674d2d1443","nonce":"59f4d30ec6d460025222c925","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"8ec3c9cfc88676932ab531f8a5fb15c14e59453a8f20ad0c8a08c6d77b85a57a7eb3f17a0db37888fcacbab8b5","nonce":"59f4d30ec6d460025222c924","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"dbd7c7b36ea019ae5ed955ab70bfd1cb1a9023b08a2f1fda2bb1a73ff3a3517487698a446e5023ba79912acb94","nonce":"59f4d30ec6d460025222c92b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"05c1cd17aee95005b0fb9eda894173c377924823bb1d402983ec5b8ec20f22a0fb1913e5f47a2a284ff98f3a1c","nonce":"59f4d30ec6d460025222c92a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"52c36791e4abcc55e47da08d7ea0e9551bbb13fdbcf992b6361cfb49a0c597bb5ec80575c4014af100c7c4dfe1","nonce":"59f4d30ec6d460025222c929","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"ef798e6e1fb6bc86d2c00d2748dc4f53022fc62e525badcf80799cf0c6d751ac6160c9f8723fe981c8f20f1352","nonce":"59f4d30ec6d460025222c928","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"df896ea23f9fdcf0295fee9e2268eb514fb62bbfb9c35f922977c9076153b1e3d8953786f39d056a6b168af6e8","nonce":"59f4d30ec6d460025222c92f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"288c76a1c3f7599e82d0d7a6f5583584dbb5800cf88421bc9c47ca9820f8699d240a90a22e95e55e37de252c3d","nonce":"59f4d30ec6d460025222c92e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"06e42d2d9365541a8962f655e188f8f1ad54d3780f03177147707ec254dd0cd6ecd3ca6f4326ec6879ffbbd354","nonce":"59f4d30ec6d460025222c92d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"f2566452bf58417087d359d203b191f889a3669080e9adaa296a06a4ecb7c82eb593fecd828d87c8addb75ba7d","nonce":"59f4d30ec6d460025222c92c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"816cbf24ee321871b8aa698e3e8e66a3ba6dc7ad7259b0603f9675a56ed1ba08f971b1e9e829b20ea7d2390920","nonce":"59f4d30ec6d460025222c953","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"42d237b82bb6b2717d713b500e070ad1b514d41d76635d8511373c299568450e69a1f9c7bf4c8db6574e7c8f2a","nonce":"59f4d30ec6d460025222c952","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"d6695247ba52d7c9cd5705cd50370113b7f0e3aa4b0324e5d834289aa3099d5d4e02842c28d99b493a99f39078","nonce":"59f4d30ec6d460025222c951","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"d8fd29d0428620b053f38495c5fa564bb508365a92bb2b4c9c691ec57ac20e7d0b1dce6b73b073e1ba5d7c70e9","nonce":"59f4d30ec6d460025222c950","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"e9ddbea0dfb541080a019e839b8deb78037a9035745c82757ff6b05539b5ef9adeee92f5d83069e1baa710026a","nonce":"59f4d30ec6d460025222c957","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"7a0e56feb2a29c3523f7a5210fd12c6f74c8c2e4cc93fb492fd273ca514aa86802ffb4d5716e0e2e6923b607d0","nonce":"59f4d30ec6d460025222c956","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"6f78001e49831a5cc2c14c993afffe1b1e096fe6ced673d898d37e52d097c066bf2ef3609c008dc41937c888a9","nonce":"59f4d30ec6d460025222c955","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"43c4b8a18224bc8aff8ac4cf269c15219c93137424b985738ca9190a3a3465be2c026c9e1a708b415fa54bcbab","nonce":"59f4d30ec6d460025222c954","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"9b5aa791b6e4ddeac59a5233d635f698a368461f7f05bc65397d5b5ab98aa4898f236bc9d1e2fa140290bd0c9d","nonce":"59f4d30ec6d460025222c95b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"9673213707146e2078806da68722823a4bd41fb976e85953c427728aba2c04ada6c9745f1e5a6e449110d1aa24","nonce":"59f4d30ec6d460025222c95a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"7cd0baeae8e582d78ea11a16e5c18dfd0d9065764fb50965448667d8b5c043d3dc97c5baf38cf81a865d18c16d","nonce":"59f4d30ec6d460025222c959","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"4c43764629117febb238fad9abc20c545701d5a4dead4a153f74d02744b3e91a14fefa7f648fd747628939af74","nonce":"59f4d30ec6d460025222c958","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"09768a672ac997ed353e55a7f1491175cb5264f9fbc98a94bc8dc354d612b1f98974b1a679362d5485cd77e13d","nonce":"59f4d30ec6d460025222c95f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"1fc6b3963fbf34a655ba0a43b3e55050a9c62df19a3e42e99c09d0c5b9fa4e1c65752200aacef480940e1748bd","nonce":"59f4d30ec6d460025222c95e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"d41eb23b3d562a1eae8ae99b4f0d66fcc9a6203293c767d3ee642cdb02265f5be4dd0bdcd0646a3ea0ce1089af","nonce":"59f4d30ec6d460025222c95d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"4e97a615309b53e001017397370efa913be6232b440639ebf870983e2299b72a27d4cb2c5cfcf77e74bc960be6","nonce":"59f4d30ec6d460025222c95c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"530e64dd7667cd26a089731816bf7c5099852e20681c333c3109e58e24fbca2c6a3be039747d9f3caf9f7bd94f","nonce":"59f4d30ec6d460025222c943","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"6c437a8689f5446c4566bf9ef0bd061c47b83d6608743d11d52ce723937b52adb24198f56789b46314856d5a9e","nonce":"59f4d30ec6d460025222c942","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"49c5ddc82579bd8a3ce517f2176fe9c2da078a55ba2049b5717954d63d2c439d0586b1a235e7977342a876e55e","nonce":"59f4d30ec6d460025222c941","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"64bd8c77a9d55ab948f85d2e5a1301a087a3b47f39de670149294a95c02abcaffb97f8a037ef0268487b177d11","nonce":"59f4d30ec6d460025222c940","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"9698592f2280a39f8e0da1d858a5b25d71e1e38b24c5e3c686e183516b1224ceafc08ec06c251d2035a3f5061f","nonce":"59f4d30ec6d460025222c947","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"e531e970f7308887925ace1c259dbb1ff5b96872a8f5b3808cf180835016f9a0b6e781764cd4fe6b7d6cec567e","nonce":"59f4d30ec6d460025222c946","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"1a7eb906568e2cdf96db6cd8f57b5f5e80e5d7f5d06d38b6d75f0825d454ba526ba01a982ff9b8bf5d26d18a63","nonce":"59f4d30ec6d460025222c945","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"7625bf0cf4941f6937671edf3eb516e7603ca05e67703cb18fb2029d114b3a4a588fbade74ffcd60fbdcff9aa5","nonce":"59f4d30ec6d460025222c944","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"e5e0c658b2e09cefe8c64fafeacc7f88480f238309e1eefadf11bfd06fad0b7b873f3175c6ec4aff3cb2829f78","nonce":"59f4d30ec6d460025222c94b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"7936335941bae2092d3d29aeabe7111142108ecbfc715fdc5b973b5993e67ef5ac7b961861e941bbfe46436f58","nonce":"59f4d30ec6d460025222c94a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"b1afe51177180f4c5a0090e1308cb4dcbe25cdba18ebbf9f05142c80965c5e10d996116b0f5afa2f67c72a8324","nonce":"59f4d30ec6d460025222c949","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"ceee5cb76f9d93c5a071e20410ec5843d2922910e90a7e7478b13b4252d3fe40d5aea0f7338176e10518dcd8fa","nonce":"59f4d30ec6d460025222c948","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"928a4514d407f5affbfc1adb13e75df37f2157f79168cd13c42bcdb73eff0c8ec4ec21209f22dcf37a5b88d0b0","nonce":"59f4d30ec6d460025222c94f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"56859a9ea6a2ffe583c3abecb692b945a41cf9b4e564aabb321a179426e9f4a2d450b0c830748170c44dd49338","nonce":"59f4d30ec6d460025222c94e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"f202dff3f7ed0e8283864ae7c12a171e2c25bcd428a46418a9506c7e8e1b1677e88ef9c6306c99e14e7db776a3","nonce":"59f4d30ec6d460025222c94d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"19cbee0664f1446da2180ece944118a7671aa0539aaf7209f952c107a574db3bc8c4b8e752153beec24ad51b55","nonce":"59f4d30ec6d460025222c94c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"07d1d6318ef368b0827d56601b3301dbd7e7df14d59048af76a1832726734740b6c18cb37b5686e88f8e474b65","nonce":"59f4d30ec6d460025222c973","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"2219af51b8cc98da02120087d47b505a401ff9f281ea7eb6c6655770cbb6962a5fd52c9757b6159841e4f3cddf","nonce":"59f4d30ec6d460025222c972","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"3520bfcd5a09ba2c874211e774dd4132c9f931452880f14b883c080ee3ad99c2a8f56e8c852cb17a879342dde9","nonce":"59f4d30ec6d460025222c971","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"1aced63b7bdd7b773664c0b4f3d5043a5b2034722b6da764fabf30e9a48aa9535dc40b345f4b6846459e5a7a92","nonce":"59f4d30ec6d460025222c970","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"5b34e052f1a406c0c2fc544faddfd7d65005922ab52950ce3b77d8c3781d7ffa22b1399a878aa27335ef98f73c","nonce":"59f4d30ec6d460025222c977","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"2ee89f3f078af876ed077e8525ba7a735dec77d8de8490161394ac7dbb943f59641d0d35ffa19d4942ae0f114b","nonce":"59f4d30ec6d460025222c976","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"7cf3cc13e89e64e4c75defbf719d994d04a7fb588c528a8b7351b30e1c96bf99c0edb3180aec9dfff00213db78","nonce":"59f4d30ec6d460025222c975","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"086d75caa4e6bfed8f31b9ed160e66001784314b6c5cbd3b586584db246424a349d2d60728b4e7e1de86b4b93d","nonce":"59f4d30ec6d460025222c974","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"76af3f71d4c2b61330a418af0aa5449e05d0f57516404ef5be2ba20620cf7bbeea25de487b1ec5aea7ea347013","nonce":"59f4d30ec6d460025222c97b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"2da0eaccb27270ce631b53d97b74283428b5f6ddce07ce8842519507f429397cec73c74b2e59fa9ceef5300370","nonce":"59f4d30ec6d460025222c97a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"43fd3ea3583c49917536f15ed9a2426fe3fc74f905fbc3c6a63418e7289a461e87ff2f4c6c62e81e0f05c6d993","nonce":"59f4d30ec6d460025222c979","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"6bba8a515598005dbe0d01a8de2c5ecf2b199a62f6f100a7324d174489b30d6f73ddebc48ac1935c85f3631a74","nonce":"59f4d30ec6d460025222c978","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"61af5f487f4928500e2f213e23540bec944f651979cf23c715653f3b10e27d1f7b57479970c3d9a60faed88c84","nonce":"59f4d30ec6d460025222c97f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"a8a278d209ff6af5e8778adc88a92c84b4256d4dabfe66a27aae1e432af020fd329bd24371b039851319905d8f","nonce":"59f4d30ec6d460025222c97e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"3655a5beabfa5b0af95fdd8635a1beb0f681f77f9add195079ec7d06ade150b9bebe6dd07129d3b32790b2032a","nonce":"59f4d30ec6d460025222c97d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"ae59d8e8769e042281bdd7defb4b0bf30b90e44cedad39dee6269946fd961d404c314afd96a001578a646d7b8d","nonce":"59f4d30ec6d460025222c97c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"eb069737388f870e0a012f4dd6438aa6329695e14f34efb99bc69741d97c0fdbb483038c347d96e9204795b5ba","nonce":"59f4d30ec6d460025222c963","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"1ba1230aafd32966534f64080b4122c43f223c8fcccb675ab53899dd354935f01d6b87f1461e4839063c10323f","nonce":"59f4d30ec6d460025222c962","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"ada93fac437183b4184a00f65c8dc867cb93680ac11c6a1e7334e4bb7772dbb93bec39b708336763f26c348c2d","nonce":"59f4d30ec6d460025222c961","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"5cc357c225537d01d3022bf3dd38b12c5fd2861853a590715f39d4589c1af392ba7fc706957204a4fad37f89c4","nonce":"59f4d30ec6d460025222c960","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"5252ed05fe99ee8be0178e46fcc2c6a1914d0d04b2a6672f2cb816ef0898b817ffeffb9bdb77a62d5f7d262342","nonce":"59f4d30ec6d460025222c967","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"6e0b8f0259f630191df7155a8d7d896cb1b310c641914eec6209ab3ed48f5e411ee8a99d76d3b91f8f57f46be9","nonce":"59f4d30ec6d460025222c966","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"3b62844b4b842cc99739fce04e7d57163f9c8b8650c6840a22b9abd0370eb4dcb8dd3a6f0bbe36b3dd7a7e8d9f","nonce":"59f4d30ec6d460025222c965","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"f1f65e35fcbf646e4d6209ef240c28b40a99c8b4a80948fc483e14df964b4efd659b50c6e6d8c959af1fbb0f1a","nonce":"59f4d30ec6d460025222c964","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"3d1f5d49af7c9938896efe606b30d1e52d2946d9fc586849d06d1d342fb0f2bef94172dd3c8f9b2ae3cceebb3d","nonce":"59f4d30ec6d460025222c96b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"d49b520558f5a7e0b81e8d34fbe9909cae5599a5310bb8f9bab38f35221d4651a42dd738086bda8d13f18a51a4","nonce":"59f4d30ec6d460025222c96a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"0f9c767454772ad5c545589eb65bf9007bac01ec952cf7ff3caccde3f2f8f12be6de5115c7fb8d3e8e341096c6","nonce":"59f4d30ec6d460025222c969","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"539148d71ff87094ef1b19bf61ed1446bbd5759019204675a8623f75e4885d1b1f33acb1172b1d4326aea1fbcb","nonce":"59f4d30ec6d460025222c968","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"065a30de5396e67bcb62d40277d882001c6e9b09425125853797c971b07b7c7321984836399cb6d73c81f3aca0","nonce":"59f4d30ec6d460025222c96f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"93fc3b6ca9ed05f8cd09fa0d45a5e4f9ee84ed3b12446074d36f37483e033a589f9798f65814ad65811b7b051f","nonce":"59f4d30ec6d460025222c96e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"c001c34a7a2f01bd027090feabf8cb721d78dc952223300393c2e6b7dbf0e0516b7602526238519bd3cb9eeec1","nonce":"59f4d30ec6d460025222c96d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"db7c929c1054b79837b0a9e27615780efa90358e331a9ff8b3bf5608ed8f8dd3efe0d155b76af1137095c79321","nonce":"59f4d30ec6d460025222c96c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"1d3fee065516b230402d15422410e2e24c8eea52839d5fee15cc28c31c04c16e6324dc734f28ae36f36798e3d0","nonce":"59f4d30ec6d460025222c893","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"411e18b9e5a41a2e998d7973d7e962837648d95cc831c4d4de2e7025a52ce15f"},{"exporter_context":"00","L":32,"exported_value":"85dc810c333a0a6027108d05028235033f5e8dc5858de38b6b18d9e12ad2ffd4"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"8e95efee2764321318e00b18b906a522cf6655b5af37ddc23b46e040a0e45878"}]},{"mode":0,"kem_id":33,"kdf_id":1,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"1ca33cec4723bfc7cb0a644c898b6b2ce3ccc343987f22a3a73aa2e55352a32e8a6d8d794d7d9fc964e48988a1d5914ccee77d28f1114ec2","ikmE":"1a463f4f902ee550c02da906b9cbe87d32115b6c172e057cbbc0ea4c8c35a46ccac1b9184f31e29fdb8efdffaf453a6119a3a0273b2b09a7","skRm":"8ce647f76dcdf95daff154f9a92c32e932d4665a0d387b94e785f346ee65d88ca95724831cb2da6f02bd8e5b9426e4507b934783d3986498","skEm":"55ab1e319340ae13de80f429a5a280c129f1c76a7a221ad5e53ccb2091555e9cf55943ab7043e9260dbc8c4c3d1e2bc64c929850cee67bef","pkRm":"af29cbe9ff4f0c3734d83dc60d0983eaa0ff26b16d7ba5e1550ab0318dc3b397488b0b69ec6e6f7e79a70d76e9b79b2e33c6f5ebe759b02e","pkEm":"578dbdf78e62ec54fedf1ce81dc3ce11c076920c4ecf81355a95a88f88615710ff68f5791e66f60697b4d14b4ea2af5f79a7f30dbb9b9762","enc":"578dbdf78e62ec54fedf1ce81dc3ce11c076920c4ecf81355a95a88f88615710ff68f5791e66f60697b4d14b4ea2af5f79a7f30dbb9b9762","shared_secret":"634f26833c63075d96428c742b81ae3e7956be43067e6519e233337534a7349668a2a08d20a53a579c5eb45fd5e36215decc8e65c8d93fe7a2ec9c49d7e49f13","key_schedule_context":"00d48cc5df954e70a3d12964fb237eb8af46ca0a5ae5746c4e4db3a4811432ac0102adfc8d4a9a21ce5ac967d155f2cb11fc23851d6fa84717ba59f097b4bde4a5","secret":"f76acd12e8a44abde6d8d564ede5a6a816f7f1aa326c4c19b0374e597d6b26fe","key":"","base_nonce":"","exporter_secret":"01d8b9829da52b6a86dd1665921b550e51f6288c3c74eb7316b2bfae59f31afc","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"2be4993c25462e7bba788a1e9aa791d273368b509c64381388bbc4ab6fbf9952"},{"exporter_context":"00","L":32,"exported_value":"cc6647f9165c88f5f662970049e9913e8fa2caf07bacd929e4fb0642ee4aaab7"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"d5a2777673bd7c1e474cdd33eddac17c37346dbe39588df2a726784597302fe5"}]},{"mode":1,"kem_id":33,"kdf_id":1,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"3d94ee0f2fd140df97b00aed51da20109527d72ae26e5211814b4a6f6ad142596f97831dcec2f500d8076dff867188dcfbaf0c1373c67126","ikmE":"d9bdfc14697fcf97ec4ae0db1f1169a8dd36efb9ddb78546fe2ff60e73f10706d5652322fffa504fd60db044da252a89d0242c7b07e537d9","skRm":"64dcd9ce4699d43ecea693936bb173e8a0bd89b2f6e27b3f1f6828198661c73b6541df5ffb6261387319892fbd87c00e615166927bf5e415","skEm":"85c266ac09090bcc4b0a97464c4d5385f87123c2d8962fc78de0b8e5415703c50ef8ac42e6d2a397cd5c58f3def95f3f2097adf69f9c8eba","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"873650cf858fd887a32711c97a68d658f09d670bbf6dd0367d6493ead5caa63b8d5d1c8e5eda49255a1182b9a9bc69a69748d8776b5e51f3","pkEm":"8489d31e6593bdd53659d8ac9ad7ffe67140f34958b638f0172af9e8ae919819dcaeacf1cb5e4c6c49f1b307e9eb95fcd24300f7e4be5bbd","enc":"8489d31e6593bdd53659d8ac9ad7ffe67140f34958b638f0172af9e8ae919819dcaeacf1cb5e4c6c49f1b307e9eb95fcd24300f7e4be5bbd","shared_secret":"0f07b45382d65b230a5b8b99598bdfe9928f848e3770cac26d3dc23aadf4b517ff799f650e069a3d68fd9b5ae618e26a5204fdbcd749fe986eb3dfc19c7ba81e","key_schedule_context":"010235bb7ae0a1ed819dc1a6b1b2f4a2afcbb2a29c4e4f5ba1ca224b81970c390602adfc8d4a9a21ce5ac967d155f2cb11fc23851d6fa84717ba59f097b4bde4a5","secret":"46f082efd9cb674a9eaccbcda0a1df407f300581bd9e1619e2e13dd0e8a52c1d","key":"","base_nonce":"","exporter_secret":"eba1a625266186ae9db1e402fa4b8475141e88cd5b641223ac95175e5f6937c2","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"cc784ccdb93bdd58ef893948acf5384b4202ba6518bd9ceb271b92a0b39b75ec"},{"exporter_context":"00","L":32,"exported_value":"88179881fef37be1b2f80b9ac2465234ff0228fcfa7c832964a576b579ec2257"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"1c947e04f8faf9e5855ff071149f44519ea3b6ca25ca31ee5d97ef584e3601e4"}]},{"mode":2,"kem_id":33,"kdf_id":1,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"26002e3aec8737c805c7f74adc52b8acfebb15259d19491421abb3f6dcc45bdd9cc22c69655df20e4fc562e2f2c0274a7bc8690f807ea795","ikmS":"f2538d3c913995f2fefcabb02fb5d2f8b084349f174ca091b6a221bb4221090550e22b7adf5769df7d78535c749a92946bc30dfc399f6310","ikmE":"7d402f11198ed81757937465eb1c2359dfc3e22d188ec471fda777a96c560756c8136d0f70e139d5ad14eaeaea9a7985b0ab0d61efeca95d","skRm":"0f1c0a8b2037ada0e64c552b15c05b57ed44e501f37d0e07c99fea6a7d4c0f4e9df43fd54b70f105d180ea45d6360c06d2587e0eba9074c2","skSm":"d0801156ecf56acb8a2b0c7fa180787f685e8c37c199fa6e10578aa758f24da7bfd68b85d98d88ec231280b98133387a585bcc0d0dd5768f","skEm":"7e8fbc259f800663c349c56fe3891c5e52806a2402ad2b8d0ba38b9aea70504f9a77dbc5965529da9fb94138c75b94e6220b8238b580db1f","pkRm":"093a1f4cb1dba2b5f3fe695e46ca4d4a03a6d869a05116cb01c049bc35725c37701a649727ede05dcd92f6fb99667a56b58193b9e90561a9","pkSm":"bae4e391033e3571e9ac433319a0b1f6d32da9663ddd01d2dfafeff59ff965e0f418e920c2e7c5f611b9e801626d929cb9dedbf85eb8d366","pkEm":"f00e0b9a79896b412c3c02ed2e6d9c952918b9a6eef18764b9855a5fbdb0f584880feb803edad4d2c6e5ffa9eaac7183895e958aac586de8","enc":"f00e0b9a79896b412c3c02ed2e6d9c952918b9a6eef18764b9855a5fbdb0f584880feb803edad4d2c6e5ffa9eaac7183895e958aac586de8","shared_secret":"aeea710e7782a9ba7913a90cccbb7b0990e68d4ac5f17b57b01c581386a4d78a85188face5a45bc1d8d335ab202d46369c120a37835875927ec765039403123b","key_schedule_context":"02d48cc5df954e70a3d12964fb237eb8af46ca0a5ae5746c4e4db3a4811432ac0102adfc8d4a9a21ce5ac967d155f2cb11fc23851d6fa84717ba59f097b4bde4a5","secret":"865f9614846e30f65cc71878e84ac71a5008936ab73b52548e177d537413d539","key":"","base_nonce":"","exporter_secret":"e54f2820aa52c08de8093db208861c5df46e7b8e6ef0ff8f025888c7d00532fa","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"1e5fc8d3da99ecec54b2a8e8a307e47df12021843d2ad3b57a13d35c1096262e"},{"exporter_context":"00","L":32,"exported_value":"7161b154ad6c8ebc57a01969a4e68c3c21694863a758316ad9a991bdce084ca1"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"dc00d0261bcd82c32584e7a3b9ca2372f19e5ffbacdfeb4ae20e41d2dbcc4b70"}]},{"mode":3,"kem_id":33,"kdf_id":1,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"4d48e3f4d7599cb7bed09321d3661f6a6d561cfdfc714623756c68dd31fee16fbb33376e2a9cdd3ce23a543368d78f6d7012093912252fc6","ikmS":"a02f5c0bf9e458e5604a296a3c2928062afb22a21a2dc2c7fc50f2ea9dbd8ef8ce044c9b87cefac3cfb264f121b4a9613c1fc8a3c25b4cd6","ikmE":"b8ec0d8c4587c6e8a98d62ffae076ed0c8f14d245bedf722afbd1e1dbd6acb29c163b103ea8fe96e97f649bf8d3a2c4b9a3ef916b5ad30f7","skRm":"95e2471ec745540643b8d3e3e43c044883de882da1f38dc95457c46e050e9567fba17ae6f2bbb36f4ab42c7eebc2083e93054e1332b565cf","skSm":"2e30e7315acfb0e2fe5904b3713bc4af5b1da14658ff0bfa6828da3598c839ab190780952556d8b9de15f343afb6320a3749a08bf0b747a3","skEm":"9e874897439cf5d484ec6e3790f6b6aca9f594cd406ef68c87af624f73038f32d3fec9a75b05deb573820523bc74afff746f4ddd7326772c","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"d5cacba5e2fb88fff38fdbeacd6d87fff69e9fd064d67c125a7baffbad7b329434b1902bc78f5fad1b2a8be63421a89c2e41694d6e9e08dd","pkSm":"d57700335bd3de9ed05ddc304be2b69554d0db95e95cdb7f4d6c89b1c5a917f80e4a7b438934aab2d80fee908d8f276cb5abbe3242eb8ad9","pkEm":"90d7afff9bead1dc458d59546acf7e44e4baa62caf2ef74612efe865d8e53ea77f4742dc8f48432d17693c233c7532ef0d0ade1bd6714706","enc":"90d7afff9bead1dc458d59546acf7e44e4baa62caf2ef74612efe865d8e53ea77f4742dc8f48432d17693c233c7532ef0d0ade1bd6714706","shared_secret":"4497c1ab3106c2a15c7c42c2ed6e17e8716d1a8b4138e95f84dc2627de7b91f0e40671432ea9e6f2537bf08d981af62bd519ed374a34c598c843e33119a0eb63","key_schedule_context":"030235bb7ae0a1ed819dc1a6b1b2f4a2afcbb2a29c4e4f5ba1ca224b81970c390602adfc8d4a9a21ce5ac967d155f2cb11fc23851d6fa84717ba59f097b4bde4a5","secret":"8877752bbcfb117b3e19c38cad450f23b4930c3aa7979fdeed2bd782ecf9822a","key":"","base_nonce":"","exporter_secret":"02f698585677e8807d8d67dbfe4e376e7eeb7ad1e9d628448ad138d4d3877e78","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"a03ca050efe90356dee89790ae1d568011e30e632ddf3a298f83c59c67df5525"},{"exporter_context":"00","L":32,"exported_value":"da843bdbf76efc8466f955e84000e769d5df080131fe6aadc62bb350ae1baf42"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"f58465d8b1e215d78c4da6c1d6a967d74485e6bb44be28336cb7955be102fac8"}]},{"mode":0,"kem_id":33,"kdf_id":3,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"f17f842d3e7711d5efdea961f36948cbbfb747e082f135b8a01aabc7ada156ecb84d395923899e98bfff673c72e42d38d9b5850121736a17","ikmE":"a1345454a6ab3b43f4ceffa962b5f4768585bcde7bb7427a8b0e6135b2d9d7005667a7b354eb76559714a78a870c65ebe2bf08c32ae7baa2","skRm":"6f928133eba58182ae4308e9c23a9bba7f47470ccafdd7144a6c4680ec953451bf52654037946944ead49a04b8df2d28fa84aec0d93ddf5a","skEm":"2a113386522e703540d8e6af10bd87c53866d45bd9e142fa4abd839795f99b4f80f156e297bddd3d21116b5b41782a8fe8559b1b6b36ad0d","pkRm":"0201dde2c49a8bff45a560d380fae5fce41f05d7ba7ddec1ab17dcdb64e6cb8b5d50c92373db71d57aef840528a6e967e567f34e2bdce6e7","pkEm":"64f91133e33b0d6b5fb49977687e2997fe13aaaac3bc9f8e82f4016250037a1510eb9abb90a2ec301e2e64a564a406cf04fe2c55a4ede111","enc":"64f91133e33b0d6b5fb49977687e2997fe13aaaac3bc9f8e82f4016250037a1510eb9abb90a2ec301e2e64a564a406cf04fe2c55a4ede111","shared_secret":"b2be63d2a497f5620736097ebfdfa90dc79e55e467b4d7e69a9f9018dc0bd8d9e010ec4bffaa0f282eaad0d21328bc6c5c3ba9ff235b50152189bdfe4514f9cf","key_schedule_context":"000fd8a8635a1129ed4cee7f5560a60bac8af321092b45499ffe0eda28218c8d1d910e2ee5eedbec01d33683d6f9f923d7ab0a69b4b8fd0d53307f806ed48cde59574a72814c5d8e45c985c4252e66abdfe846113c17cdd7485893b89e0d5cb23d409145ac095bcceb628874b68378897f77c36eaaf45dc932c30eb5841015517b","secret":"f85ae1c7b96116b5df329b5893171ac54d78177121ab7e7751fcd410f5540c36eae6d5174061b2cfd56d84f2fc5482edb952f96b53d5b0ac4da194329411beb1","key":"3d545f0dbd25755b2df4e42115b0fc9c","base_nonce":"b5d12d524c30f9837f0172a8","exporter_secret":"eceda177b1f1b20872d8197b7ddd796330af8f1e08793c5069de3d8b5cbdab5c21a54a986b843390ff2c1577af9a08d6eb3994facbeaae682c5263decd564da7","encryptions":[{"aad":"436f756e742d30","ciphertext":"3226347e84db9c09a0133e59b9f63d55271cd9756b7a0445526abbed865b3e86091cca073afee0d79c39675ce4","nonce":"b5d12d524c30f9837f0172a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"b03fea1231f315cd05fe3bcc99ab219d748e930e19e0275da5ee5af94944a0bf963a6ee369506a31c501af922e","nonce":"b5d12d524c30f9837f0172a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"c01173e4d588365205c512fc9848794ed65115ae089b4e9313b37daa171d1bd6ae4285d3e3a4b9fc1f4957387c","nonce":"b5d12d524c30f9837f0172aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"a404c54ee5c567b812157298ec0848b1eb42f10f632a7121b8bcf83f9d017952b25af56ec71eed58cdff8213c2","nonce":"b5d12d524c30f9837f0172ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"760eba65546b9a51488c3fcce7c24f2a918045a576b710b8c036385e9be524068779d89f362cc466a24c96306b","nonce":"b5d12d524c30f9837f0172ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"99a247891de966236bac912cafa022b3794eb65e42e6100ad3280a474a617b838bbaee916e7a09fb3bb7bd4d51","nonce":"b5d12d524c30f9837f0172ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"73856ec6e305ab00c63fb361d40be4ebf757234cf23f0e79fb32435dd6082aadd3ad9bc6b0a4c8413fbdcc45f0","nonce":"b5d12d524c30f9837f0172ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"b79dd324b95b8d742e2e9c34099306d5f8ac126317fa149e1513c00303d58ba2eb1a3c9a1f44a6bee21f7f0e93","nonce":"b5d12d524c30f9837f0172af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"8782b8602734b85e68a586ca75c2ef3e6bbe1cce6e498d7b89179f62d65d9635bbc008725aae8a83844fa88be8","nonce":"b5d12d524c30f9837f0172a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"88e30d0cfc17a85903b17bcf4c12cc4ab52c8cd0143b26bd2dd8e126ed4ff2a0b75d3695c4bd34417a958ac8b9","nonce":"b5d12d524c30f9837f0172a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"2452f4b7907b0504c0ed915a4832f486fc70e1c5a57aec4a0387b3d67ecab99fda7fb6b8a0c1271b95e8a1b012","nonce":"b5d12d524c30f9837f0172a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"6f21395a0bd39205c30932a0f8ba2a7d70541afe18edec4000a9973c9841a104929e5cef044871dd221f62237d","nonce":"b5d12d524c30f9837f0172a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"f10c6d09a849c5bea2b1f77e50680cf0d3791f8c9a7a785d4f43e67f80ef121b4c63c8aebd6c1cb0c9c2e18605","nonce":"b5d12d524c30f9837f0172a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"1a7b5cc530a31a9a59923b860e376ab3d5b0e356f0682f1e43cd06c3e769271bb2581212fa9ef8b583c76ac780","nonce":"b5d12d524c30f9837f0172a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"7a906ca88d475a597b27cd4c1f762aa42cc4b9363b5bfa9500b5d37579ff0f638b086e52fc00f3d76bbb406b22","nonce":"b5d12d524c30f9837f0172a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"0aeaaffb095ac7f322a35e8fbcb3fb549bd969af201d206894441cdf5b1a385f8bc99dbc0c542fed44a815f8fd","nonce":"b5d12d524c30f9837f0172a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"acece2b0ecf75fdd318168fba5a1992158ee6433544f3d662ce69e5b17f72a8f16e17e741437ce9538c2d6287a","nonce":"b5d12d524c30f9837f0172b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"3c9801ad58a6a77021a4dba6632678a1be2bbd5added0ac0299c9f868ddd6d0c2e7f7073ad6b09d276355ad28d","nonce":"b5d12d524c30f9837f0172b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"07307b1feb33271f22c4983917f5d2dcb8f333df7f9f544107baaf294792ed2c79a176f451c18ade8b1a090548","nonce":"b5d12d524c30f9837f0172ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"a1bd69de109478c32a1b01bd1b872224d19bf47bda998051dde0cc9186849f1c6375539ab4d61654c3e94dc5b1","nonce":"b5d12d524c30f9837f0172bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"f19f4861cbed5689679ef58e1f2e59da9e3428fd3c73c279bc661808fcf990d18732a1b6054b609c31aca163a5","nonce":"b5d12d524c30f9837f0172bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"94501a96d17812d162b4e8794ed796df5c8c549d3bd319f5b181461a38474c13df3667f13b3276a8378ebc306a","nonce":"b5d12d524c30f9837f0172bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"015e6af5c6dbc2ab6695962a8a07963c244caa2ed688acaf6a8ca1be0596dadf24c436b86bda76385601e3dbe4","nonce":"b5d12d524c30f9837f0172be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"771e197af372f7ab921972154bf7048a6acfd6876aecdca7702adbebaeba40c02eeffcc4d1d32adc8a3df0d96d","nonce":"b5d12d524c30f9837f0172bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"d3a21cc77afb6f1b38dcc6887c9c91ce79d5027298c86d0549dc3c9ad1df6d262bc31a1f764b69ff9a43335d66","nonce":"b5d12d524c30f9837f0172b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"ba338c9ebb38df2c2b7a8a0d51bf19398674254e1c31299a82ad50f46f171543478c9d4693cf6671189505aae6","nonce":"b5d12d524c30f9837f0172b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"31dbd72f92f833fb71e9081d269ea46d5a1d06636584b79fa92fe44dc9abe884bb949c7b572bb2ba6d0cca4847","nonce":"b5d12d524c30f9837f0172b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"309be1570452dd53e8dc7cd744cac5780276e4f225b6701c0c7c170198be55ccc5a0750d024bf6ed8d0f8be188","nonce":"b5d12d524c30f9837f0172b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"0df29a224d3533ca243d1f180c502269f1b95320d61c0b8ad29f1ac17e2ea4449824f6fd2388ef1679749ee6a5","nonce":"b5d12d524c30f9837f0172b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"181a4f63462e1d80214e38c9384cd27b58d99acb6f9119d9bad08ec33793e3e4d78ba8450f016129155391ccda","nonce":"b5d12d524c30f9837f0172b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"5d4fec84ed5082bbe2bff698df4bd45bf0506a125c9bf0c0c8221d489846da1db328ef07b753f6538ca31c8715","nonce":"b5d12d524c30f9837f0172b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"6b288e6367d1d00a73e517ad82908d35ec1d19c7bc5d92e6404c58a74b97b72b98716470f567d3035efc8b2fa5","nonce":"b5d12d524c30f9837f0172b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"e31ce68250dcfd258d008e164e29307cf1d25cdccac4d5f7cd26d43d475e24d3adbb4c814d58e1ce068afb8f3f","nonce":"b5d12d524c30f9837f017288","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"bc9e7eb1adeaaaa05441bb59c52516f0d84afee8d17175fbc270e81c0ff67e372623a17f950b771863b74eee35","nonce":"b5d12d524c30f9837f017289","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"fcd57903f344406526aecc80e6ff0315f34f6c3e6695586e355b64a1312581227155e826356f611bbc31d86110","nonce":"b5d12d524c30f9837f01728a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"bf1d72b6492d0bace143ef2bc26d9c97fb4a56ef697d99375d9ff0975b7d343562c8eaff3c636c1e2a50665dcc","nonce":"b5d12d524c30f9837f01728b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"a6dbb7a06f976c63deaa602e0d94ba0e0ac4aec847dc1a132b07abe1d3dc5a85c1aaf5241d6748efc9c155dbc9","nonce":"b5d12d524c30f9837f01728c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"a8468da29c87f70a459492a1fb09e1e0e567f35f819bf100ae35f3daa4fe4cb26de07d64ae6ba25a2dc407694a","nonce":"b5d12d524c30f9837f01728d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"1777d301e75cc4344e47497b0ae1451543a240ec071409576fbefc4fabac29ad1f08aadd291a6eae058e067f1d","nonce":"b5d12d524c30f9837f01728e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"62835d52e1d3fb1f950c014eded86c4854689decdb6bd56c0a857fc38e5e3b5c91123e3a9186e620c4e0cbef1f","nonce":"b5d12d524c30f9837f01728f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"c705e21df96b1c03f23556ad2021d8e1f59d67ddf423aa2e29eeb6c188db8ed8365ca445f3895656e6a0746f24","nonce":"b5d12d524c30f9837f017280","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"8f3b791fb784fd5f69e216864a9ab8d0a9cae5cc21bb577674210c9591caa84cb34e48fba7d679e1d2d7cccc00","nonce":"b5d12d524c30f9837f017281","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"14d331b437228aa4b72218d94cbb1af7a89473a98cbea64393809a3a6a4b855fbbc91d00d4c848dbe96e034acb","nonce":"b5d12d524c30f9837f017282","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"c3297f32227f063a54691d2a5b70b5b3d9a79a1575f3255e85058b10aac5f3137f99e558b99a5dd65b457a5783","nonce":"b5d12d524c30f9837f017283","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"37f99edc27b92573986e2eb3b42969108a3491b68615648d99bde0b4465747d56595f21a4954be1d21aa1563e0","nonce":"b5d12d524c30f9837f017284","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"1ed3bb41c1ba0a8b0cba519b869d83aba0d13fbc01896e7f63a0f81fc8d10738357a37caa610ec64e0bb4fb850","nonce":"b5d12d524c30f9837f017285","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"b8f652a49923a402b02d4a70e0d33b74ae0ef2209698cbba31734620b1b8137fc85f816c9689458d7d26f85e9c","nonce":"b5d12d524c30f9837f017286","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"ba06dc0f4191e7d9803930956b0633e4daa46aa47a49bb8e1d1849cf04dd2faf1db0923b7cb514c2e6fdfb90a3","nonce":"b5d12d524c30f9837f017287","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"b8121635f60e56f275d4f90a6bef39ce31e9773d9aa31f0d1f2a6b59479a54df0849675628514bd3450ee7b386","nonce":"b5d12d524c30f9837f017298","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"d1392d1091360e61903842f2cf7895c38ef1c2b8a235fd2cf4f63de244b4475215b7f50bb16f1b46e1fdb8ce5c","nonce":"b5d12d524c30f9837f017299","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"742feeb1c477752528c72458538b611f55ad2b3a3d56767301dfbdfe08d687a55448c6e4051226c3fd24ce7de9","nonce":"b5d12d524c30f9837f01729a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"dac865e2cfa40e83bfe9c2eaa7a03d78f59391bc7d43579d3c4d2859cc7ef7e7baa185c3f34b4cccdeef41e0b3","nonce":"b5d12d524c30f9837f01729b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"44660aa804d19e2832fa48b0972752ce9b00fa7057c5bcde1dc63d0eb039b0d41ec17065198d4e032c1d4bbd6b","nonce":"b5d12d524c30f9837f01729c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"b4e8c82f5ca1a9a43c4a02e47017485278786b10c3774796c1bb3c6568487fd9c0063a6f43cc58cfc9f5fa5b09","nonce":"b5d12d524c30f9837f01729d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"c649c0d415095f7a86a3c942b9985dbfb9feb05d623b59b902028c0145909e6bdd6d4b2cef63431c0f440b791e","nonce":"b5d12d524c30f9837f01729e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"330390f067c96e711cac0d51d1ae9507fc4fbcf6eaccabe6a8873d6037307713632127ce7d8c2a0e261eddbdbd","nonce":"b5d12d524c30f9837f01729f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"4ff9b5daf24b8c70e2c7040426233e25a068e333a49a78e3ac77d78de221437b77a4af8cd326b66c3f134361f4","nonce":"b5d12d524c30f9837f017290","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"bdc78748704214f6fffba4ecd769dd60583510fc2b095fc9c0eea2f75fd283b55c408fb391193dd8ad233b11b1","nonce":"b5d12d524c30f9837f017291","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"cecebd5322744f30dd988e83e3a13eae76bc9f3e3570e375822695b1766711278ca4452061395375a183a82287","nonce":"b5d12d524c30f9837f017292","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"4e4d46b226feaf3f43797ef3ebed3c5acbbd87cd2e6c17d7d8b99f789365eb16aa746a8ad966e71458c6ec6b34","nonce":"b5d12d524c30f9837f017293","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"021105cc10da7f744e9270bf5b8720207353ba0b45c651df0d8e5c1a2cd9db6fc9d25ef136a539bd5c65b149b9","nonce":"b5d12d524c30f9837f017294","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"ab51b7db2385e63d6b322a14e4da1b81f6f20ddb046ed8cb15e612bb930fc5b2ed834c4569b7736d8236b6ed79","nonce":"b5d12d524c30f9837f017295","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"2d617a6889992c8a9a5c8f756b08321b09f72debeee2fd8fdc7319cdd52118e52caf19246b489676ecf8fe7004","nonce":"b5d12d524c30f9837f017296","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"3becdc2b020f2fd915df1e4eafee737ff226822b23f4cf701d2b9b6261308101ccb7ad30f5d23978dcd0548b6f","nonce":"b5d12d524c30f9837f017297","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"b29f4358703f10178fad2ebf8f1bce440fa0d83755c63b668c768b97fcdf077af1542578c541183aee22df6afd","nonce":"b5d12d524c30f9837f0172e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"d0f09c30191cfbb46cf23cd01e769f5a8f2850e72c7aa3952a260ea8a7b09343272ac09f405e723d7ad317f47b","nonce":"b5d12d524c30f9837f0172e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"ee474fa6ac86dbc066c2073a92e9917c8584d28f5e4510c538a383c6fe430f06ee4522129eff15539039728639","nonce":"b5d12d524c30f9837f0172ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"46e83cc0e4e22ef32c822d7f4c1044a93d2ebbc3e5661d1023a1706838c32b8f3b014f565bb900edf3b8452823","nonce":"b5d12d524c30f9837f0172eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"1449932ef0822fb62ce02e06e4fa32970c2aec93001f0981ce4ce75ab4b4fbc0faf02e752c1d173c94c799784f","nonce":"b5d12d524c30f9837f0172ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"bce4368ce2e2bfe40c730bf90ec5ecfae0c11d591050519bca0a661fe775dc5a039e495e92ef0377e944d2f4a9","nonce":"b5d12d524c30f9837f0172ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"c3ec49f268764e73c2ac94abc081da5a9e0eaea35bd8a2ca28a68e799af23b99530d42336ded2ba411c2b580b9","nonce":"b5d12d524c30f9837f0172ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"0f38a2e18b1d7441d5192bc7063fe572e0499571b2d25c6be54da744474af49e9947ff6c514551ab54662d8ead","nonce":"b5d12d524c30f9837f0172ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"344425b3d4042cc6951b969035472e88583292e2f0ec3bdbd5cfb090a7f781856e8bdc5b4ebb187f4f03cbb840","nonce":"b5d12d524c30f9837f0172e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"75569ccf1340d5cb0c0707bf75fffacdcbd98d2a50ce6926433273101dacb1bab20895d431255bf3a5329da4e3","nonce":"b5d12d524c30f9837f0172e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"d7edfe07a8f2077d1468930f4a9a5de85589afd80d72408fb78cb83100e03517e089cd8db8f71210fd77f7325a","nonce":"b5d12d524c30f9837f0172e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"a9040fef3e6ac2cf02dafcd207c5a7535e38f72b1c30aaf909bfedd3a5535baa6ab26e4c37685a39959dc2cdc5","nonce":"b5d12d524c30f9837f0172e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"5cc6a226b4f1eb35265217208041662c9f083ab9ca78571ce29eae8f9177f398a276fd0335c343129813ccb289","nonce":"b5d12d524c30f9837f0172e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"c70db78a11d3c9b13f91a20d60d3cc636f6edcada202587dcb46479eaf517d257e4f4ffb0f48c2a9964257f827","nonce":"b5d12d524c30f9837f0172e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"a91851b406c25cc7a9c4bbb26371150750fd74eadf46f686779924f88208bb956968c7b09d7c4c952010c3c519","nonce":"b5d12d524c30f9837f0172e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"2839253965219d08e80a375380d315172af56640189d0887606a1765c0bd8c251047111f9ddca3f9032d5e95e6","nonce":"b5d12d524c30f9837f0172e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"8d3b57b9609437f15773a0a5c8ee2d9f3e4f20ffb21862faea4bd80cc2961fe28c073ecc723f2cad7962f53acc","nonce":"b5d12d524c30f9837f0172f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"a520dbc07c1b38c9038cd39f76fe43b0452c3f4975499f511320e649202459eb2b52f1fc4111e0b80b7caab5de","nonce":"b5d12d524c30f9837f0172f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"bf20852eeaaabbff75e8693bbbabba12a080d0b13786f4cd4e4cfabbbc11c61f23d70ee0f56a210b901011bbea","nonce":"b5d12d524c30f9837f0172fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"bca1094a309b9c3debf44b76a075d90fb185245bf6f9f7c521290527c4f094225f9c690e5db4ef922bdfc4b3a3","nonce":"b5d12d524c30f9837f0172fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"8e7511b16a46661eb6b6c489bd2818209a2d3999796d2b27b7f94fae0c237322e14b07d648062c77f03755f326","nonce":"b5d12d524c30f9837f0172fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"3fdf3ab868e1794cd332f83c4f9d2e36b08e4711b58ca291c4fb5233ede2c9580b66e004331bc9e79773a3ff2a","nonce":"b5d12d524c30f9837f0172fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"7089b9f6a91260e18a1c8771090592fba5b2546cec1d8548b539c196d79e8635e653865ecbaad1fb86a618127e","nonce":"b5d12d524c30f9837f0172fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"581934027c7dcccc85c4b1a354ddd20a80c0e5ccabcda899a03cfa4fb3f9ac080bd2462b0219245aeadd5b7382","nonce":"b5d12d524c30f9837f0172ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"f5351e28b25c74d8b89a65e5df0a47667255453720bb103dec6b4d00b291173e4627106402036885f63e05abc1","nonce":"b5d12d524c30f9837f0172f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"68168980b180dbec693ee3f6dc5fa106c968ff81333b2fc4ea614fbb63a18723a4390fad7a83bcc0976450d64e","nonce":"b5d12d524c30f9837f0172f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"08b4741e0aa1ea9734946985f8df24b5affd766b23cb812e7118fa2a97c0cb62ea2639806265f00bc02c36c582","nonce":"b5d12d524c30f9837f0172f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"5a406f7b7dfb2a247e773aec7d44fd30209f44c344d4a938b3c1c33238d2788028f2024cf3ee5db7e5adf7cd10","nonce":"b5d12d524c30f9837f0172f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"ae766a5c0d709f82d6966b3781c708bef9fa9c3c33f26459adfc59e910a274704d2bc2a5b7dbaaada33bbbb6f0","nonce":"b5d12d524c30f9837f0172f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"ce0327e956de249460216f43e84ddb6cfae382cbe1f779c8a5c8cef024bad965163af7add591033ad64d4fc8be","nonce":"b5d12d524c30f9837f0172f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"91b4f5f9b76edec713d50d5de597564a47831c769faceb7826f287ea3d557708373ceaab0c3bddefa114d5fcf7","nonce":"b5d12d524c30f9837f0172f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"41902d9f29c89a20de1a5ce9eea66a232081fede8318f3c06f0450b71fe3dd27706fa9c47802080012ec3337a6","nonce":"b5d12d524c30f9837f0172f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"156e86e75a47c3742c6eb87e9109e6fac0340f0d1da3434c4bd8464862072df6d83c460471e2641bf76508e140","nonce":"b5d12d524c30f9837f0172c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"018b92a77a8d4f8770400530f504614431f754f74d2bf589bdf4f80c85a3d7d4dce91384774baeff7dd96991e6","nonce":"b5d12d524c30f9837f0172c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"ec779ae59e00264f5a3e0097d3a87f84242a959f747d5dee4fd88ff83263bb9b5d25642be9777dda2e97d1fc2e","nonce":"b5d12d524c30f9837f0172ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"20502311d86c05810a059041d17fca0b3602d2f79fa7dbe023d4c82baebc67982cd1c0d0c20ffdbefe9f3bf739","nonce":"b5d12d524c30f9837f0172cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"fc8a96514922f3cdd0483082c2b8aa1ae78dba78031b7b17b2109a0659d6813e389c0d51a345f95e66b3a1786b","nonce":"b5d12d524c30f9837f0172cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"ebc16f6ac6103a30951764cf65ef46f044567783a7ecfe8909bd7517ed0069779104d80cabc81cef654e499a22","nonce":"b5d12d524c30f9837f0172cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"1366d5a3ac0b7d3ca3faba1e1a7de033b7c2f6070a529b1e9c68d52271d905f22273be419a9b76924db9b542eb","nonce":"b5d12d524c30f9837f0172ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"3d4dba2482904024848bc8c402380080dfcc24a11e629e337ba40484367eafd8c28d75794f1f888187e91ad73d","nonce":"b5d12d524c30f9837f0172cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"1e1559f2a283930dd4a9a52cf43c01edb6c300e4306e353dfe653dddcea6516253aa4d219e46d4ac86a2ac43a9","nonce":"b5d12d524c30f9837f0172c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"72415eddf9c256f70efb18fc29c23dda3f5ff7f5db685a69bbfc5344b2bbea102b7241985f7331a6c2c6af7df2","nonce":"b5d12d524c30f9837f0172c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"70a315b315657974dca31bcd1c4f1fec1753e984dcdfe79325dafc6a4f1d715d37a3d53e09b24f7c6a01f90ad4","nonce":"b5d12d524c30f9837f0172c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"9a6b669e14ca82db3d78408738ad0de9e2d12da1672e5ecb98400196eb925c7d227e968bc9fb92651c632a19bf","nonce":"b5d12d524c30f9837f0172c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"d5f8a9e7810dcb661875850700adbea2e9fc52cfcb3761653afd6c06b14642788a3d88e9d1353f3ef5882dc1d1","nonce":"b5d12d524c30f9837f0172c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"b835dd7ce63d50cbab94acb7a054b354f4f4f5921acb6ad8561a03f69254fcda46420c0b5e77c97a0182e15398","nonce":"b5d12d524c30f9837f0172c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"84566006fe40c523f5e56a4bfe73d834c15e6e15fa45252aee72ab5f76bed5b0130f8f5c5d7a170a41ab0c8920","nonce":"b5d12d524c30f9837f0172c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"aae3171ca25fa5d5465320b87871a772e8a19d362848d3314bbac4172142cbb1d2260529be3df342413ddb049c","nonce":"b5d12d524c30f9837f0172c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"c1cbf35b9e48d048a85c26acd614d6fce16932d787c306595736886776c21dff1d8b196cc36aeca3e607c00921","nonce":"b5d12d524c30f9837f0172d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"3f32d488564c3f2e7186502e5576974ab0738d850cab9d07c0c156cf0f3914513ce2a76cefc92460a208a25514","nonce":"b5d12d524c30f9837f0172d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"493c986f4cf7688cf2a61cd0fd3dc9ef63a9837e5c2d9447c42d7d146059cb60a3b4c7cbf6c5ba71179272bd51","nonce":"b5d12d524c30f9837f0172da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"28b53efd31a97ad6ecf231dd5505cebcb0f2d2ff7a96a8f389cb88a9328fea88a63d0487688f4d651a07f41a3f","nonce":"b5d12d524c30f9837f0172db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"46e73d23c3dfba380ee4a012c5df7bfac10cd6563eaec0ee97e47bd014a4a02923718d9c55ab6157c42e9bbe85","nonce":"b5d12d524c30f9837f0172dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"372d0d9496bd2f6ae5a611bd85c0ee6d7736a593d2b2af986674427b653f367f6e1cef2c0129b73e3dcac4a015","nonce":"b5d12d524c30f9837f0172dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"88a26cca94eecc71f0b9c55a00ce68cee7c2933915e31dea231a969e9ea233628fa20000d147237af90754ceaf","nonce":"b5d12d524c30f9837f0172de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"78375413263db745f1858d1da280a2741d5e0c402adfde0add2305ac56038cde3aafcdb039d45315f9c4727622","nonce":"b5d12d524c30f9837f0172df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"d9ea4203d185baa80b6be48f8e0192b6b6d983f1f76086b2a93315e437990aa50d64b13d9113780448ac9fbce8","nonce":"b5d12d524c30f9837f0172d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"2c09f3c0ceb389c7f5deeb90a9724daf3223f263f4651e1d4f01e152dfdf9f313dcd46b9f4c34282e588d92fe8","nonce":"b5d12d524c30f9837f0172d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"a25c9ffe7f337984f11fe47a2f11de53a7cb67335d95073a14e1bdf3e05daab87850d6523cd07ab9c58881c085","nonce":"b5d12d524c30f9837f0172d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"d3884cbd5d7f873b70cf44f9cc729494f2e208761ddfb273ab7b1620bd58617374514828a990824a19c6d1acdf","nonce":"b5d12d524c30f9837f0172d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"0a83be7df35539a32d2c69aa6eb62dc648efadb0bcb9ca983ba7872ee8fb9e0b7d5c9db0f099474a94f0e05d2f","nonce":"b5d12d524c30f9837f0172d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"825a734cc4bb26d64d0cb8384e40c46c05e8870ef75a80fc56294f1299fcfffe75510075ea3143eef871fca693","nonce":"b5d12d524c30f9837f0172d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"3f0c25616f62d1fcec4f8b51475cb1fe94fbe3f8b25fd5c42a06e172b11dbb78af45206bdc374176b58fe46488","nonce":"b5d12d524c30f9837f0172d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"705184f9617543905f6b836ef45da27600297a6d89c93fee60bfab0a8f869402e82fa498a1fde0fcd9677584d1","nonce":"b5d12d524c30f9837f0172d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"9c554127c7fc111195466501c8a57617197398392d0aab94565c0b6db012922c4c7968dabe3a15b5270d9febb0","nonce":"b5d12d524c30f9837f017228","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"bc8335ae4fef41ccfd5b0ba5482de10e2fb855d5961369e0ba390702394c97e107e8bcf2c6a0e7cf14f09721f4","nonce":"b5d12d524c30f9837f017229","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"7a82a8cda5f10ae2b779078fe399b3e76e3c151fb9076615de890002ecac96696706ebd85b604c3c5521ff4176","nonce":"b5d12d524c30f9837f01722a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"ecb46eb4aa2aa58e6cae62ac8f9db4a48ed724a96b0a8482cf548174002783469e05948324f52c2623ea110928","nonce":"b5d12d524c30f9837f01722b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"62c75df98309750b961b496dc9c38243212688a26c18f6016b7da869e1e0c93442052a59771754e564b154a31d","nonce":"b5d12d524c30f9837f01722c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"62e5f450ca86bd6ca769bb74e0b8ffcf74c64e6b57a34cf013341a30610afdde21b90bb5e4dfd1f262cf53885b","nonce":"b5d12d524c30f9837f01722d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"3294c02ccb0e16c3942265d88a7156aa5427b9071c17978dd092c5e28338a33898023fe966bd344bcf2d9b144a","nonce":"b5d12d524c30f9837f01722e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"19b3d6b8b7e0a902ff769564b76a9f6abcb6c29defc87501ef0c0e740b14773132e52b240bc26b2475173c62ea","nonce":"b5d12d524c30f9837f01722f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"a35a424f68cdb4d5e90e14ddf545592c88bb02b181d2461c7fb83ceb036d585c0d4469a73982f252192d93e5db","nonce":"b5d12d524c30f9837f017220","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"6117057fa8cc2d3a46f697fde2f06a5ded01fb944f66e4c9782f52715f57ef930e36f8bdeb9e442dbf9c7ee385","nonce":"b5d12d524c30f9837f017221","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"7cffb6d9ba92e470118c4e50012b04c47314fe590f7447e8ccdf8891cb005e654da97c80eee020b057abd9b718","nonce":"b5d12d524c30f9837f017222","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"0ddf8b61d31075f39eb893434ecf71606ec47a74a686a9bd1f8a320b6b256d7c04b9b464415d6dea2888dcca32","nonce":"b5d12d524c30f9837f017223","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"b38c852dedf3d24ee27e99d52805caee4c36761c09cfc38fe5431875d6a1eaa91b21136d44699000c4a70972a5","nonce":"b5d12d524c30f9837f017224","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"fe3e96a26a06e045c6ed9f28def1b046857e522ba0a54612d9a96ce8361d51c3a0f301efd0a33bbd3895767f14","nonce":"b5d12d524c30f9837f017225","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"4e5e1f09cd0b8d076b46ec8a4494e912a46050c45a77f52d53d2c7025d961222767ab4efaa78b0d65bf4b6c625","nonce":"b5d12d524c30f9837f017226","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"ef4c05c26e134d9ad2616d97c93202d9bb7eeebeeee8c85f67796fc5ac2c92b0e4256ecb4ad81e9cf4c1ebfcf7","nonce":"b5d12d524c30f9837f017227","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"ff69cbd7eedf04c5faf2132db8ded5df345afc75587570753f6c02668d4d016481bda8537df5bb1a1a530d550c","nonce":"b5d12d524c30f9837f017238","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"b407305c5c98d6593a609c6b983284354bd995e984c084c35f1c06dc1a4e0dfc0df0ddd2357ac03881e2e40e38","nonce":"b5d12d524c30f9837f017239","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"bc08279071924dd0b9d3d9f2651fc19ca74a50d9e16fef713a074bf8962d5cb7bad7bf334f634662f66d3b5445","nonce":"b5d12d524c30f9837f01723a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"094ef7c4793c0bcad9980f5e675260ff062ca45b0e2e28ec2bc185b5a246455eb99360202cdac7067782bda562","nonce":"b5d12d524c30f9837f01723b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"565097e5c8d43122ffd306dd853167b4123ae9d9e4dfc19b087548ebdc311836208275fd68f2af8a625a94aa4f","nonce":"b5d12d524c30f9837f01723c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"a76ba489b70f2517a56b3065922dadeeea0f082e21e6f1951ada88d82f3d1aec8311fceb2206a599c23c762ea0","nonce":"b5d12d524c30f9837f01723d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"3211441c0db633bbdc2c2d102a876587cd6632aefa7d590cf12353908bd79a6acb843eee41f215d0da4faa1ec0","nonce":"b5d12d524c30f9837f01723e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"6b9873207ae2206d4e114f6edff4e629c180dd572592323815221cceb5f8f007e1d97b4197e33c9339c9ceedaa","nonce":"b5d12d524c30f9837f01723f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"38085e8376c8648fb90f7e1b17328010d42ea6d6cea7e543371721eec4517af3358f5e035f012be516afe33415","nonce":"b5d12d524c30f9837f017230","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"eec1554f36cda5cbb51d8a50d8a8450e2efabdbb3a13301251cc6dda1e0f3b304a6b236cebf6a7ab6b99f57005","nonce":"b5d12d524c30f9837f017231","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"db3dcfb265b4f00fc88372dae6b2411b36c38c6b5cd7b6eb205e5410c3314c135cd01bef680c48b170854ffaa2","nonce":"b5d12d524c30f9837f017232","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"f26d98007dd027937de6043d7beaf784c7b6a68b58c74307d2c83b4f04ca05383c7bf6a86dd3cb4193b9a8d873","nonce":"b5d12d524c30f9837f017233","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"4eb149081f26c5b45546a6189f1d9f6a15e4bfec0117276e813117cbd527fb6cc84052597269baf0eb8c4f6656","nonce":"b5d12d524c30f9837f017234","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"177712e8706d0fb50ddf238e2e3d795f5dd32bd634565c8c71d8c4797ed6a162b9948636da7603c73835270c8f","nonce":"b5d12d524c30f9837f017235","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"4393d0710440121e66650d28daf5e58958193588a881c21557842cce3e29a934f83d6a8ca43cbb94b9c260c3cd","nonce":"b5d12d524c30f9837f017236","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"4e9a69ce410d7678979252dce4e881f257c162f954516cff87a7f95b2a5d2214eb301bcfa17e78f07e1923626d","nonce":"b5d12d524c30f9837f017237","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"79c2daeac55b83062e200999a5687ea7fb2234fc9cb1d43c7e5fdcf9169bbac180b240cb83b11013bd37cfe469","nonce":"b5d12d524c30f9837f017208","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"667d9940d8b824abbe349b721ab81452c19de3454f4053ad2429d84f263a89545da5f0e5ba3e41b0a3c5dfe7ec","nonce":"b5d12d524c30f9837f017209","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"708ca210b3fc7c665d43c14a9ec56acb21b2ee5d495eddeeb66a967a09e80d2f244093f4266dce817716de0db0","nonce":"b5d12d524c30f9837f01720a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"d29d44d6e132f027d49aadcf7ae1159348e2ee1060e09378565acbe5fd226276dc531952136381132b4d8ff3ae","nonce":"b5d12d524c30f9837f01720b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"44494d164ebd056cb24a1d08b2b6f31653705e2251983ccb75578769f599424ba122955aa6f94fb253ae1b52df","nonce":"b5d12d524c30f9837f01720c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"3cbba5d090bcb17421909dcac06283a63bcb665240d3043740d59b56fcb9b3a87aad0884e204a6e8ae503e1469","nonce":"b5d12d524c30f9837f01720d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"f701cc3653e5de5e5dbf083da10ef157ba1800de60c4fe1a8740c187b8ea062dde97fc0f8358dfb9acdf792630","nonce":"b5d12d524c30f9837f01720e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"fb8e86c71bd2fe27f8f4477905430d776353b8bca0b7546ed685a9df3251082dd957de84a8e8e22d8321833711","nonce":"b5d12d524c30f9837f01720f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"c4f1533f187bb349b931efc21c85cc5bd6939f93690d0406595b364c2c7061493450039338a611c705e32fca9b","nonce":"b5d12d524c30f9837f017200","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"7a5ea69e7d1d0a0091d7a4c18897cd3c41a7312922d20def6780c922d2f669b55de1ed693f56aa6ea37bcb010d","nonce":"b5d12d524c30f9837f017201","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"99a74f34ef9188b7c9416d5c8486d37e1252ca87edac1aa36549edd636ec482162e8b4c7cb41ffdae4038c95fd","nonce":"b5d12d524c30f9837f017202","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"cda27605bd999fdedcffc81257c3c95af82ee37695bc6410fccf8fa90c389f4dbf85840e594e2eef1616d7158b","nonce":"b5d12d524c30f9837f017203","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"0e2525ced3a84c3fc89420e1192880b2dbf8eb45671cdb783fa45acd868061fa8688699ff63d913b862964ea39","nonce":"b5d12d524c30f9837f017204","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"8348999f2cc116ff493783704480b2a545a0f63af6a96b3f4b158c16a8b09f80cc1fcb9e940446dff6beb4d31e","nonce":"b5d12d524c30f9837f017205","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"84225209dfe2c808f872d22a7b745c41648b856565b6cd68b35b1b81c0b8984891d343ca866c38d0dcd9f7a651","nonce":"b5d12d524c30f9837f017206","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"9bf94d9f4a581c073f1420c59117082c7a90f6a6e0aaaf779d4d364e2fc3b6ca8f077e3982ca5078e52dfb2b7a","nonce":"b5d12d524c30f9837f017207","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"eb83efbcc30fe53302a8d6361186bd645b9663c35dd1d87853727c94eda1b1f892b48f07dd2fbf7946e4412c4d","nonce":"b5d12d524c30f9837f017218","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"9f2e6657ff794e904471bd24c5cb69d4c89605ecfcc5be3d8455c8f9aa5adf4aa83bfe798eb589c7c4b20e1da3","nonce":"b5d12d524c30f9837f017219","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"ac5c378670fe3dfc7a29f842b362ac0f42c8b7deedc17317a2fe55bd856a0ba19798c772ac271c0ebd83510e4f","nonce":"b5d12d524c30f9837f01721a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"8fa964e3b26f92a14dfe2d4551438750a718779a8be5e4a76ad23867c2179b07513aaeb33cb83a049c5469527f","nonce":"b5d12d524c30f9837f01721b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"95fdfc03de14d09565d4190e72e600d9952f3f043ac1336cf53de3dd3dea543e60463db8e18b5c973aeea89335","nonce":"b5d12d524c30f9837f01721c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"23cbeaf3b106262ef53aa4ec5a44d945ce14ba1ac70a898dc52b3397832c882159ce1fa04765142f4098ec05eb","nonce":"b5d12d524c30f9837f01721d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"f3e874ba32e3dfb67b17111a018a0e5abe23b6a4873fcf232d390ea17f20ab6364de87edc3eaea6bc6805430f2","nonce":"b5d12d524c30f9837f01721e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"f557fd2a6a40f1a95ddb7d669c7abb2f632386857d356bbc2674dfed1117ba6b477ebc5b018d06c26eeccde7b4","nonce":"b5d12d524c30f9837f01721f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"8c2eb2077cd68ecd4c6527bce88f442eceb40826ea331e2a895bc875fdaecf3ef3ced9b766aa7814ec99105021","nonce":"b5d12d524c30f9837f017210","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"9220e2cb8605df59040d09e866d786ff4b6a0bd663a388a1630f65d6fe69ac14fbc88050182edad990869a7e4d","nonce":"b5d12d524c30f9837f017211","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"86a8e3d102f54bb2c7577f227edae62bf0a1d28459b012a42ee0813cfcb2e8a0c0dde28dd3b617e68cd87263ae","nonce":"b5d12d524c30f9837f017212","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"526009691f66c629bb22304099cc8dd2e6d1ffa69cd986ce487be2806277891a6dd8f2defac9584f2d064ecda7","nonce":"b5d12d524c30f9837f017213","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"a6013b0da866c6b6562882c4f42d4071fd49be3fd4786cff96b5d670e8fae75d02471b6aab7dda1ee0205e6f8e","nonce":"b5d12d524c30f9837f017214","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"0722e3e7b94ef772cc2c3fccb96cdc23895d4b02161c9a0f6174617cf44074639c2189e77d84e7e996d2f2f6c5","nonce":"b5d12d524c30f9837f017215","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"8e88a22fe5ecb1b6723d9796218aee8d535b285378e80c0cbc425b740a8acca85461d8aee6424d904a8247ea61","nonce":"b5d12d524c30f9837f017216","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"b78b62d1a038682eb400ed7974f9a447ee7638071fd4d3abe6a36a8d5af01de4b6b9cd3536cf0f5119f2669260","nonce":"b5d12d524c30f9837f017217","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"1d0147923427e61f99a6692bb87f926ba9ae9bff4d5c799098b2bc4ac6428dfae95ef74722b1aff910d2d9a1b4","nonce":"b5d12d524c30f9837f017268","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"021b19f828d2fd78c508a9a68ebc21e61414b4938fe0ae24297dbc10a3716755433a1680efea5a4ec01093f66f","nonce":"b5d12d524c30f9837f017269","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"e50172901197efed3cac4b23d25cc4fbc361481496bf3954f58941325a25b5af574d167b588ecb00ce5e58d588","nonce":"b5d12d524c30f9837f01726a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"7e3528325f0beb686b3281c5c4e62bd178f2fa096c32ed3cf92145964d3ba31950f512f76a8096e685d22c97f2","nonce":"b5d12d524c30f9837f01726b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"506955a9316ed6a02cb156af75519192b4dbd7d2fdbbba33291da468dd96568d398da168981fd95c5dc97ff8c5","nonce":"b5d12d524c30f9837f01726c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"4096a11a32aafc586a16fe82c306843035ddead9bfa5b10b4d65bad734343538b517966d8b57be7141e6b2d0b6","nonce":"b5d12d524c30f9837f01726d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"4abd39004ee3c69855bbe23f5b3e83e68661cb3afc43a7230696035012537a262100aa485f384ed0afb9b8a2f5","nonce":"b5d12d524c30f9837f01726e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"76405517dff364d49a324e2fc13da790bf1204132ed7645834f829aa0d1c4650dd3a7b1e379d6263b3969d6d7c","nonce":"b5d12d524c30f9837f01726f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"e2c9b7847750429da29a24a67458cf65a5fe7b30b88a7b485f3927ee620af13645aefbf1d79ea4423bb29c7561","nonce":"b5d12d524c30f9837f017260","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"43c8af15c154bef004a24e48cc70f9f88d7b8ef4dcc20dedc6775d21b67bd1e2726de5611137aa65217995be5c","nonce":"b5d12d524c30f9837f017261","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"5594c21cbeffbfa38aab0fabf9a6568beb487adfd1ea0c878d7ac047b61074b2cbc7cf46c8a16a177a65bb7c41","nonce":"b5d12d524c30f9837f017262","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"674c1f4aff83228c536ff953607e3b5565a5dbf2bf667a9bfa4342fdcdca876d9637addef5aa6d17af1f9376bc","nonce":"b5d12d524c30f9837f017263","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"fd5ed50ab9b1be587be774059ff872b7b39e8b5f5b0f2b930585aab73e51c6d896818aaffeafe75e96e3caee2a","nonce":"b5d12d524c30f9837f017264","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"a9ce0070a89ff5afaefbfb76004bf5dfdaa81baab2dde985e1c04b27123bf4b4e9c3fb7bcffbe3a0ec836b0a59","nonce":"b5d12d524c30f9837f017265","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"5a17340623e07c0224ba23930fd4151ac5b524bd99f68ea79a9fdcdcc7bac75608ef91fb82c8b83c2f4151d0ee","nonce":"b5d12d524c30f9837f017266","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"01376aeb8d9a91b4f1d75fec87266abe690ec99e7b1f75a1b5e803727b4ea15a3d0ca74672b1a575c2b844cf50","nonce":"b5d12d524c30f9837f017267","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"799b4557ad425574416637c00831a2b0465595fed79bf82f3737ccb2d877c54da6734bd21c42fba73d73099a83","nonce":"b5d12d524c30f9837f017278","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"c99b9f025019e5ac8c39249fc27c00b4764d9c245903e60ed1814507fa8e995911588bc282807999d752242ad3","nonce":"b5d12d524c30f9837f017279","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"ba3572929c2e49d53df650fb3aba8482e3c89373ef8ed58a84711e49436c9c5a970aaf1cf023e5ab0cbaf06203","nonce":"b5d12d524c30f9837f01727a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"fda9e90542ebe3dadf031b853361a9b4d5e95e4d281c12216eace0790fc7ed6abbb21fda1ebc5bcf43f071c1cf","nonce":"b5d12d524c30f9837f01727b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"90d09e84c7f82a1e047226d40c054884725ab9b042d8d0e796195c7e1a543acc24526fb57c5ed9b6de0555df6a","nonce":"b5d12d524c30f9837f01727c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"0d17a8e7e7ff086d1669db55b45f66a3890fa79d24577d5a224482514bdc01d94d486ae9f7fe9e3541c9fb7c28","nonce":"b5d12d524c30f9837f01727d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"e8d0f18cd7c3bc81c83b72c6423facd5c22f77da889dd65837613b62388cad11cd828e6eda5205828a74cca8b6","nonce":"b5d12d524c30f9837f01727e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"3514ba96cf3419705e5c2288ccfd9218fd28dce638852e681d2d06212b02f8ff38d1ed3203692c2fa2344a5aa6","nonce":"b5d12d524c30f9837f01727f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"e96f5f5913943dca1aabcf6b18ba53ba6c39279dcbdb73f01b3bd7d9855d2b0b0dab7a415be2948992785c4a7f","nonce":"b5d12d524c30f9837f017270","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"b0afb5bfd2af8ab15af33ec3934347aabd80826bfa87df2c751b2910c2d09a0de589cfdf284af4af76a749dbdf","nonce":"b5d12d524c30f9837f017271","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"208a8a612c6a5241bc98e4eef78f3a116b495e0392299d50c5de9774aafcdf2338393a3a8f5cccc32f23e1188d","nonce":"b5d12d524c30f9837f017272","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"d1764a98db4a1c55ce9fca6ed8ccbd1d1193b5597c0920144bb83ca479023da3938ada21c61bf8f010ad41cc44","nonce":"b5d12d524c30f9837f017273","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"0ca6d4957e85105a9d7abdc551c6bf839d164f5f242f7a590b998d1137e73889b8cacef0c3f0dc3031ec3b5931","nonce":"b5d12d524c30f9837f017274","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"eb9da59efbfe7fdddd1061c488446409c402f200a93655b1f74456cbb18c7c5d10eb4435d102ac2f7b42aa2ff3","nonce":"b5d12d524c30f9837f017275","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"5fa31274f7048977f1e4d93209dbbfd834e7de98c92b8a2fde630e954eda917d3f1271bbce360edf98cbf5573f","nonce":"b5d12d524c30f9837f017276","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"27831bfed277dc178548257ddee32b2dd40c48537b39acb7e3f5775d3ba40380da51269483836fa0984b5b8e0d","nonce":"b5d12d524c30f9837f017277","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"5c0ddc1f8c3b9ec3b9bab8375d04eb75a3c55490e13809f6e28b50495b6e6b9b08a16be1110d8026ca63f439ad","nonce":"b5d12d524c30f9837f017248","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"cc5388401f032bffb41996d74a99c696b3e840a1b7e1cc1829c9947fd0d6dfbb1edfde3fce76424a7478027b5e","nonce":"b5d12d524c30f9837f017249","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"244988796f6e4c2f45b46fb7a6c0606c6f1dc6ecc1647e1b1d8ecaa7ff919f87a3bb79aa59a2959d94daa69a22","nonce":"b5d12d524c30f9837f01724a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"c785f962968a47e35b1b2197f5bcf2183ad604f8f0c2257e24e7265bfe268032667924a6fd8ef1198592083fbc","nonce":"b5d12d524c30f9837f01724b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"da414df89e10222edc89f2bcc1ddf3dc90fcb671e9054dd42ad7c3d49d1b2f4635e4395b45cf07086d8c7ab187","nonce":"b5d12d524c30f9837f01724c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"a8ce662409face4f04c1369f3ea154d26c7b128eb6057d6d4f52e904de91af46cdde00748f941d48de85c230fb","nonce":"b5d12d524c30f9837f01724d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"baa2debb4c1215a45a4e87ffaf37562fbab970116d3a4d1b286987f68cec1e72a51684dde92bf172f482f5c210","nonce":"b5d12d524c30f9837f01724e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"5b57309a7853a7870a8517322429369e0bb74dff85d4780d7a2573fb967e48704231d805e907343104c91918f1","nonce":"b5d12d524c30f9837f01724f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"a55540f021de6bf328ba1c55f2f2b8c58c4200ca304e4bba0a3f0db787386c7f3da6ddbc826ef83b0a1686cac0","nonce":"b5d12d524c30f9837f017240","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"9334de8986e71c20c478020accccff1e7c521b4483163f5ffe4877db963d1478456d96021f32c447abf91b48bd","nonce":"b5d12d524c30f9837f017241","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"64185577ba0006b37c832d840768491ac7fdaef0c03c428e7d2487a6d79f3af5cf9d73e066683ca29c980f2753","nonce":"b5d12d524c30f9837f017242","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"9108b23b469697e94067dede1f21fe031754f668457965b779f0b8d78377212279c3b666928bed80614efe700b","nonce":"b5d12d524c30f9837f017243","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"f1e638049cdd68ad433cf99d1a137c940adaef6efc22d484b62dc2597b6cb00f4ea854244a17ded9391fc71739","nonce":"b5d12d524c30f9837f017244","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"87bc5c057c6df0d7153bca52dbd1d286d9e1c4dbacd672c51e6edbb672b3fbca488078a79ac053ef582b4ff180","nonce":"b5d12d524c30f9837f017245","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"8e61439b5f67ec081e68ec6894ac7fbd983011c3e3b9511c86a6d8246ab18dab4a631830c13f2a30ce63618cda","nonce":"b5d12d524c30f9837f017246","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"80683c8ba7dd5516118bb200bcb7b7b66d6b104f3ee4d9091bc5d3bda5a5598464a92e6dfae86e61571f6d9a8b","nonce":"b5d12d524c30f9837f017247","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"ae1e9fc063930e11837d33a46efbffbc1793a8a08750ec52be89d3a48bd91e021ce2a3b3021dc23f3328e7b856","nonce":"b5d12d524c30f9837f017258","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"ef9cca1660420480c9f18d8ac8134e1d1066814bd294d2828d25da1d16b1d9e6e2acf1d1056662351dd5b27712","nonce":"b5d12d524c30f9837f017259","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"55befaacb2c17e70c49523f8d27d4b0b187ea0f146a57969fd688d98dfc32745feffd81f61aac0de604957b916","nonce":"b5d12d524c30f9837f01725a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"b369009eb98ff169d3004923812517039fa30a3078f01364d16b299eee7142ceb95a3d17f87c8c3a57f9197cce","nonce":"b5d12d524c30f9837f01725b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"8f4462def884d85d4fb8a225921eb4a10c506e67081e170468cad6406ec1393406994a4889b335d0a3bd48a166","nonce":"b5d12d524c30f9837f01725c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"3b38019675c45f4a1c72b5128ec2f3ef4ddf2401cec2aaddc3d5de831d6464778db74c927ade44e335f9a6965d","nonce":"b5d12d524c30f9837f01725d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"3c62af9a34ecb8063e1521ef309ee2dbde10ad014aa773447fb687c3442f3cbfb74568e9f5a4e6ee80c1d7dffd","nonce":"b5d12d524c30f9837f01725e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"03e9316be3f7b73c076f65565d2b428adbebc54d16b3f2f7fd380e7a0c8557f1ca8a95a9a7b7165df6e993c1d5","nonce":"b5d12d524c30f9837f01725f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"1cc0dd81b7dc12b604c0db89115a5d1a487bf6c61259fe3bb2ff5f23445194743b2817f1cd59951d1db8428450","nonce":"b5d12d524c30f9837f017250","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"90d57c997561d9d6f2fd89883052875d46b0c7f136ae3283c16f27d6b5b3891f9651c377a6f87690573aeb0d69","nonce":"b5d12d524c30f9837f017251","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"904332e6838c6fdf1d4f662f3c6ad302847dae3bbb74b82aa2ea3d1fb931aaf16d4005b5dfa80ad805de15af59","nonce":"b5d12d524c30f9837f017252","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"ab9a221a4e86d16fe7fddf0bf9c15ea359a22e0fd23baf032af23d2d9d80d5a80c3b317b691f61472264cae2e7","nonce":"b5d12d524c30f9837f017253","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"31730e1ebacb798d10385f28bb25920bce09650e7e3cff3dffa95d3ed37e98e59f054566ccc1485197df6ab217","nonce":"b5d12d524c30f9837f017254","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"44e0b6d4b30ada917911d10038251fb37939f733317aadd8aa93db582345ceca7cc745d90bd8b044f6cf3f48d4","nonce":"b5d12d524c30f9837f017255","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"87477e33e5c880689da4ee467177134557f30cd2eb71df2e7f09d143dd30c2d8da30715f2ac338ece5a0921b5c","nonce":"b5d12d524c30f9837f017256","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"79717fb6bcd72ec225688b556a664c1b030fe0230798087c3e6c93eccc98fc9c25bf759c91d70e40fe3c70f9ea","nonce":"b5d12d524c30f9837f017257","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"d7695ba74d3ee55367084e8412949d0ebe3f437b1d10b78668c3aea80841895325dd49e72df4ee2f3722cf7242","nonce":"b5d12d524c30f9837f0173a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"385f42c6cbb04ac4ed92f9554d57277d3c5b580761b118e1e7859dd7f2064905"},{"exporter_context":"00","L":32,"exported_value":"ac76136277a8a2c9e46079a1c4a3386d82febbad9e730d28543bf13674e334e0"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"f547ce5f1395df9537664e46f9e74ec27faeb00f4ef4ede10d7d2533cec89bb8"}]},{"mode":1,"kem_id":33,"kdf_id":3,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"b3f48b20be389035dbdb343b04350d24bb1ebde321c15cb0668d0e4f4d7fe7954c279355e171bf1fe1dcffa75310a01d8cf9abf248da9966","ikmE":"7411c8c5c48b407310bd737c004c0703981aa3e66f890822d7bdb6a1131f6f4c9a1a52b32e7e75fb653bdaee24df0c5e4290294b08373dc9","skRm":"e7ce231f09d5974df7506e4886f252af2917d912028f74ded4262b125acd247d03fae1fe45e535b5d8f754d3ae548ceb65f7e1ff74240132","skEm":"c390be28d65a47bc2f185625491d8875287c9e3dda2f0055e187ca84116f3dcbc272808815e499e4c24d0115f73e9af62ed2bc3ee4fdaf9e","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"143cb2841354e5352a73493b2548b99e1f3f8a77008bbddf89a7f6e0beba24782f3e0f0662bba8b83d0a9776493f34ac782f34b566461cd8","pkEm":"5e2b14215e64002670c30f14d17f2c5e15ca4df3cdda9409b90d1bdfc72603e38692f64798242637dd9f0d3f2c4ca5100b0c139d710de8b1","enc":"5e2b14215e64002670c30f14d17f2c5e15ca4df3cdda9409b90d1bdfc72603e38692f64798242637dd9f0d3f2c4ca5100b0c139d710de8b1","shared_secret":"5678c93efa606bb225882cf959f509b8cda9518a7cea4bd8d5790dc3cca6119e0dd4282c481a6e35222d2a3036ad80cac31def002dc1262ab0b0dd96965d43de","key_schedule_context":"01b6f77772f75e969afc66fe6df70331fdabcbfa9c5fc9108db02ec7e8ae117f5b28f74e569a9bf3df79c9e5507a5441d7483b9da3d3394b3f168e40554f530893574a72814c5d8e45c985c4252e66abdfe846113c17cdd7485893b89e0d5cb23d409145ac095bcceb628874b68378897f77c36eaaf45dc932c30eb5841015517b","secret":"8b82413fe322374a8d809c6f3c40bb8e906e6f3d07dfc539bfa8d79dea856d55c0758a1c801ea6f71000857f6f7650b8b2e81c00aa05e867548e8ba5837c1589","key":"002dea5d2aa428e69fade44f2557f1b1","base_nonce":"6b9edd7bb5de4671c8f7efc0","exporter_secret":"bd44984ebbafd0667268ddaa387f1d274e05a0d7fb0ec1e82d3374841967bb79b174e7a376ac8078215d4594551d67a85f7a849aaf676801f6d716da9003fd02","encryptions":[{"aad":"436f756e742d30","ciphertext":"c203f32fde4f054a5654a0bc9160f41e8647ac3184cb2f58d1c287afa61222ac77f54c92c63bed8fb56c82138a","nonce":"6b9edd7bb5de4671c8f7efc0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"872f6b48478e09cb824c635d0d1cca6caabfa02529484f51127c28091db6ed56a40675b3cebf9689d91106daed","nonce":"6b9edd7bb5de4671c8f7efc1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"1da1c37375ddbcf23c8d74dbc561d7afc3a4fd4fad0352857d46d45df06b6c60613189aee7a18922c6d0513ccc","nonce":"6b9edd7bb5de4671c8f7efc2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"0b83c42b8137a144159fbf8905ff0150f122bf41263da57b2e3c9d872d4b22507e792c7a16bbf943ab8abba450","nonce":"6b9edd7bb5de4671c8f7efc3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"a42396c5ede9a01fa98e6eedcc1dfeac025e872c689471ffc64fa6f2209b9edf45927c23108dd9c12f6c82097b","nonce":"6b9edd7bb5de4671c8f7efc4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"a4e21ee5432087624fa86523ffd08e7efd34929b558b793092b69f9e8e74da2cfc7350dda953bd7228b987101e","nonce":"6b9edd7bb5de4671c8f7efc5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"2ecfb526c87e324f55a8bff402ae87d12cf22192a3d13241fd62a3c84155fc4f4cdce0a58e4412b18ba0aa1624","nonce":"6b9edd7bb5de4671c8f7efc6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"8e337030432278b93d537d83a1644838d733d04c2c242e6d5ffec033726defe7fa1f614c090830756ed9fb0672","nonce":"6b9edd7bb5de4671c8f7efc7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"9198a27d76ec86485c878e6aa5ad8638a8344e211e410555666c7fe6472b5e3551518fbdf8a86a34a8d355b6df","nonce":"6b9edd7bb5de4671c8f7efc8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"4df077db0fceb4db5f88c2d1b85a57bd4b16b9b156506784aa1b7b227b9e48fb7aad9dec7da9a4b74c11c9cb5f","nonce":"6b9edd7bb5de4671c8f7efc9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"1155ec47a3c5b75072476c000a23e90c795ba5969fb923d9ec8ecc9f5b837fbfdf878908c0fd5544c9915a1eed","nonce":"6b9edd7bb5de4671c8f7efca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"12da6f9f027bbb88f6fec92fdc6738c4e90feee69ac9c49695717e7c43f6c8e1eee0deb1c5dd7541d07acdd94a","nonce":"6b9edd7bb5de4671c8f7efcb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"a60cb26ea5aba5bbeec9fe5f995c07fd1697eb8868878956752834125624e2b3cb425f241aceac51bf63739197","nonce":"6b9edd7bb5de4671c8f7efcc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"2811e458fdbf71b9cf3af21bb066452da807f891e9bd5e830a064e447254c094be9ff310089aff21867b7d7129","nonce":"6b9edd7bb5de4671c8f7efcd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"e5465c6ce8346add5790a4b146840882f6f4999e1f8a5b88764e3f397c538f7b5a1b4626fcfc9a360e7625eb5c","nonce":"6b9edd7bb5de4671c8f7efce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"b4503498b9aa9296042b44b30c893fbbc56554d9b78f688626caa60f3b387d919a29c683c5e9ce8c3946cdc2f0","nonce":"6b9edd7bb5de4671c8f7efcf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"54f10bffbdf75c3b4a58c970cb14991a8411308659048873acedabcfe86f13534d84602342299d2838cfad9ba4","nonce":"6b9edd7bb5de4671c8f7efd0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"5d6fe8452a0fcdc8b7cf8fc17a3d664d4bd1a278c8f1fdf2c9735923c17083305aea531b827e2378e72909d52d","nonce":"6b9edd7bb5de4671c8f7efd1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"04d4cae7cefef299701f7079d46135529817b8b68a43920fe011d8f8b615fd63ac6113ea6ebcb95a9c06fe46de","nonce":"6b9edd7bb5de4671c8f7efd2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"5cd0ea8763d27698e6cc44f69c2daeef32c1fdd00605206f41b3903229af3b90ff2610b06970b2515b6435632c","nonce":"6b9edd7bb5de4671c8f7efd3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"a16778e70e70e1e01e244d4976afc176542dbd31270271ac0c04fc4bc3d749cb85523b31bd252bebb102a464f0","nonce":"6b9edd7bb5de4671c8f7efd4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"a89ba2b542363979434626873936a13960281c084d47794ce9f9390ea16d15ad1ebda98a52b47330383a2428ee","nonce":"6b9edd7bb5de4671c8f7efd5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"9f31b5c0cc1a87126c110376a0fb0657464295be168db8210b8cf25cf0ca0f7429204bae48fc11784a1037257e","nonce":"6b9edd7bb5de4671c8f7efd6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"65e247fabb3c30524d0e176435d4d843b551c268179588622704bdba090ae1fdd5de0fbe11b825d7269275470c","nonce":"6b9edd7bb5de4671c8f7efd7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"27bac912c141cef10cebc7765d6126ff307bb0116ce483ac58b20c12973d91c6e6a6474ba00559b51ce8ef206b","nonce":"6b9edd7bb5de4671c8f7efd8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"7d64ab37fdadcf418800093be1d1d26b563a1fd42d5ba57218a96e0d0fc3892b73d97c11f4a7453472dfab4bd4","nonce":"6b9edd7bb5de4671c8f7efd9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"d6e423d088ef40122a62c0da8e331cc35c75f6d472bf3bb15a68d961234846a288e60e9fbdf7cbf872a8303d19","nonce":"6b9edd7bb5de4671c8f7efda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"b2e2c34504c692a31f50adbbcdc78b23a83a6d353418f84ea621eec40f04f6255838296a3a2008a3e494a1a63d","nonce":"6b9edd7bb5de4671c8f7efdb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"29390036e4f28a33d8329173e2be1f25f7e4dd86a340dde4a129c73fcb421b268b28907fe8375089ed9bd19205","nonce":"6b9edd7bb5de4671c8f7efdc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"a250aab6549feb5f79ff8714f1a9f0c6a0d90a11d5e24c5babab88309b7d6e1ec7d352c6bf0c5dbb0d98b82e96","nonce":"6b9edd7bb5de4671c8f7efdd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"c6817346e2fbcda1ebc0959c4e74f73e6fe19987d8732785a9a568b399e98c790a3083f4665e6ef6c9409be854","nonce":"6b9edd7bb5de4671c8f7efde","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"727be45196fbaf52d5f9be1770174fca85cc72fbf543f69677f729c3e3c7a5973305884cbd4af08d5cc443246a","nonce":"6b9edd7bb5de4671c8f7efdf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"7a7e649ed613ed63c091e10140272fd25533abe8226d6e9b40a4a5a7fe6c6c570906bbf7695408ca17ed70ea21","nonce":"6b9edd7bb5de4671c8f7efe0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"7dcbb87c3b2eea4424d0ff77b828aae8700521f21f1137e756fdc3e530354c1272ebd19b75af053ac9aa40a4f8","nonce":"6b9edd7bb5de4671c8f7efe1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"adfeb79f48ff223a865238d04889212a1100b7d5f1be6fdc1db51986a8c0270e1e1d64752fd311e3c0796f25c3","nonce":"6b9edd7bb5de4671c8f7efe2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"3237bbd90b82b78e3943d08079a61273ca66cb31cbd0602ccdfe6e95cf39acd3906bc7d0e2d1b7f90a73afa20a","nonce":"6b9edd7bb5de4671c8f7efe3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"e5b0f1c1f2a349c10162d0d19918a985bce8601a559b28aac5bf8ffaaf0b733d6844c2696bdefb2908c94f65cb","nonce":"6b9edd7bb5de4671c8f7efe4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"39ee722a82b42a52d3020686256d9e85d3e35e263ecdc876269170d445fb94c45f335337b6067d938a2fe40322","nonce":"6b9edd7bb5de4671c8f7efe5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"9cc0e2c60ed15e97b0d3991f427d2afdef079f0bd62f6c0e16209e239c826f6a2dd7b6c24c7d56a2572a500f09","nonce":"6b9edd7bb5de4671c8f7efe6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"90127cd2dbce786f99f47254962e384b52529bba435027b8d104253ab90656a2e9bbbe6558b86ff5700dddd9e6","nonce":"6b9edd7bb5de4671c8f7efe7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"347e3e3a5a56a2fd111557ba32167dd97ec3eec0340f5a7e493e7a167951f6f5819d0271e36b59ef518cf9ea88","nonce":"6b9edd7bb5de4671c8f7efe8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"29cee9bb0f178cfca12c1c739f653b183ea9dffacd6bfe01871ff37c672cb43557af5d0a7ee19ca1c2d10fdd98","nonce":"6b9edd7bb5de4671c8f7efe9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"d9ddf65d09b7c061d3bbd7f58ad33603862a6f3771f3051233468a89b28683f842da4bbdec4d772516870cfb72","nonce":"6b9edd7bb5de4671c8f7efea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"3bbe59080441d61c119981ef4d4882ab7aeba92724ff234bcca11cf766baaf910c56359650ffef7686ecaf2ffd","nonce":"6b9edd7bb5de4671c8f7efeb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"3497847c8c8dc89a10672d0fe364cbc2add1a9b913c0a5170d3cbdc940c04ea03b847733415050ce4d09df2708","nonce":"6b9edd7bb5de4671c8f7efec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"03d36fe53a79554cc1920b97fc620d7dd7f57fa8ea2c5fe8ef23b2e9b95d0c680d350c3a816f952022edacddf0","nonce":"6b9edd7bb5de4671c8f7efed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"5120f622f7f558b4cb3b45142e994181f95b03323b1874f8d1a563c453568cd2e727fe6bbe9bc52f5d9d0f6580","nonce":"6b9edd7bb5de4671c8f7efee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"22f777aabd7c08a2ab8bfe936203fed6e56cc37590af138c2c3c4ca8f77ca38b7a738071055f01f4b1d627c852","nonce":"6b9edd7bb5de4671c8f7efef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"452beacdbffe65c6f22b245f5349341ce02cec1983ef9d81f43876854f335536c6d22107e0406c5bbf23f2cf35","nonce":"6b9edd7bb5de4671c8f7eff0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"daeea7ac52153c7e66cae9a705e5f1f4909f773875f76fe822ccd000501159c7ae23db4d51dd32bb135469cacb","nonce":"6b9edd7bb5de4671c8f7eff1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"653a7c4d7530b2a3fbb0c3b3ec7382b6db12ef490f153def76e18d0fb874fbc9f294e82940405c17de2364930c","nonce":"6b9edd7bb5de4671c8f7eff2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"1838de5f00fa957aa5e90331d2500856af47d90de66a3c2ea866f2e7980703496629183c6cb6b7d29646e3c101","nonce":"6b9edd7bb5de4671c8f7eff3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"c6da307451037abdd327ac43db13f418a232825ac65b704da44f3f2597190ac50ec1d07e4280a4daabd2754e40","nonce":"6b9edd7bb5de4671c8f7eff4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"a12049aa7ec3900d92d6bf38cc5e31813e00dfed63a521f3da93b1d6d026dc3c50eb9053fe1c2fcdbad1f4e375","nonce":"6b9edd7bb5de4671c8f7eff5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"62aa6d298678d3c98ea5750f6aa16747f0785e78ae630364481739a302e5c23ecc6b681c4e0a03b666cb397420","nonce":"6b9edd7bb5de4671c8f7eff6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"3a17c04459c01d0e0c7c51bfd11f633c794cfa63aabc2d20cb6c2e386e1169071eb422a3106343431020a6b016","nonce":"6b9edd7bb5de4671c8f7eff7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"ea50c7d1997c9b8ab9bcf9aac3bf89148da2b424fa0b87478c46fd3dd9dde5465ea780f330023e573e6d6abe8b","nonce":"6b9edd7bb5de4671c8f7eff8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"a401fa17d6f999c1d4bc6517ef056d0703ace5c9524eb1aea5049a663800fbfe51e076e31dd5d0f5e79f954e44","nonce":"6b9edd7bb5de4671c8f7eff9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"883efd8b467ee832a8657bf54cc8e773cc3dee36bf8e0c9238d3b1829d5ba31217b90b989b1f28cad6e41f95e2","nonce":"6b9edd7bb5de4671c8f7effa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"89e12e81844a75341482b06b6d5ea782b54747e0cabd06e6eaaa8fc0abdf0adced836ffa8865c581fe095e7583","nonce":"6b9edd7bb5de4671c8f7effb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"68e76813791de3aee4aea0915d2b9fa82a0c9e29e5464b96d1755297b82407ab34ef331b52fe58a1296a7ccc23","nonce":"6b9edd7bb5de4671c8f7effc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"2dd73464bd1cafa1188afb372bf47d4518e1111f7b2edfcd42108845f0aa14ee54f2f606c095102e5b5862e64e","nonce":"6b9edd7bb5de4671c8f7effd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"50c0669b4609fc9248507a34023b7be2e183e4bba315cf0a344f896f4e77f108867b8e334a2c28728aa3d5bc5c","nonce":"6b9edd7bb5de4671c8f7effe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"6413c41b3db3921b5f2b38ddb332d7077a59406e3843352e9ddbb454411d03c62075257c3fb37e09b4d0e8f68f","nonce":"6b9edd7bb5de4671c8f7efff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"48bb7fe0d943bee5a546d856818b43741ffd186b9202aceab7fd3dfe219ade08f165724e40b6033344359592b7","nonce":"6b9edd7bb5de4671c8f7ef80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"2647e1caea27bd89ce2895bc8c7a3827dac86d5602c273dcce2e4761f734dd8d20ccd4d67f3842d8d8babfefcf","nonce":"6b9edd7bb5de4671c8f7ef81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"8457f46107bc8c8d026b38e26ea2cb06240d4b17dcc88167149790e9f47409c4ae6c4781ff839e370b7a4251fb","nonce":"6b9edd7bb5de4671c8f7ef82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"9ab6a97247410a11454f0b33390508887778c5e633819b26debc91be7793e617a99a14c45d7782ef18a519bfa8","nonce":"6b9edd7bb5de4671c8f7ef83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"b9157f3b3484f606e08ce2d8bc1f64b6b36c09d7a0e4e2d57e1fe173a619e24c0914ef75a463e10778376a2878","nonce":"6b9edd7bb5de4671c8f7ef84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"bbd9f8524497ba7b690c1ee8a40c466131e735cf9573441fca1c36c9bc485bc1be18199d4514384e4c5a9e86fa","nonce":"6b9edd7bb5de4671c8f7ef85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"755094fe68aee8b9888cd8f7b5a19c6597a0341776cc90f4e41733d29dfdddb6b112ec72554f57e66b0a6d7870","nonce":"6b9edd7bb5de4671c8f7ef86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"0aafd379d107cc43e45152acf830dad9491e4e6a04f060b47f16ba127607bcb4821e298447aacc18031271c29d","nonce":"6b9edd7bb5de4671c8f7ef87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"04e80c02f49f2b75e39c245b884e49c2b0846d8fd06300a9d3e4fe768119cb3ae7337d1eae2bcf3b60759eb658","nonce":"6b9edd7bb5de4671c8f7ef88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"07b45f2d04c30f6a55f81002e0f522c95a16c72429b871e60a659230197d56d830e3eacaa39739c5cd2aa99166","nonce":"6b9edd7bb5de4671c8f7ef89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"e751423baf8f2bd242149a937a3aa7e26807c7f8ec4beb2f8a355a2a2fe534904576eddeecdbad3f7dbc5dce27","nonce":"6b9edd7bb5de4671c8f7ef8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"727117ccb10b3d1f15ab965f12d3eedd48af24213a0dfd56dc340cffe11ba8cb435f1cdd92d3daf313ab1bd5f0","nonce":"6b9edd7bb5de4671c8f7ef8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"449f72e72f86bbe0cbbbf0dd24ed7222428734a43d3e4058e2e5174e0ba1520d9070c5e24d16daf286814ee471","nonce":"6b9edd7bb5de4671c8f7ef8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"40d26810d46c0bb7919c5a8b75fd3d3b2ab6ef1f3ea4314df7bb1fb54942b27326250aba40577dac12b9899167","nonce":"6b9edd7bb5de4671c8f7ef8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"cf110299d8891aac06269f09f99ad691107e410996701c285d9627cdd8ee710f5ea4992126a1f012ef32926178","nonce":"6b9edd7bb5de4671c8f7ef8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"29b35abdb70fc9cd6ce162a2d5201b1f25e3ca586aa748abfe6ab358a2ccc80f6d6969f2aef6ed66344f9a312a","nonce":"6b9edd7bb5de4671c8f7ef8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"751a034f695820cddce9ffb9cc315f6b727c39be7419fc82b87ee0a10ecf9d6a2254c9800447cf053d07f0f7cc","nonce":"6b9edd7bb5de4671c8f7ef90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"c314871577aeafcfc52869b6556f3b3ba0d6a2b613bf77531864dbe76bdafa3ffb154a8b37c87afe16dd82f6d9","nonce":"6b9edd7bb5de4671c8f7ef91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"f7babc288181fc7dc79f9072a7a911499b233d9ebc1693edadd008870c370204f6c531aa8f3b9cbe337bb64ab7","nonce":"6b9edd7bb5de4671c8f7ef92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"80c2c5699b363dcdf6daa2ec75706ba34d7f4b681b2c344c4ebf372592b7d78fec240735afca6df48f2d4ec2cd","nonce":"6b9edd7bb5de4671c8f7ef93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"ae81d07cf42f7b22a069ccd12b66b4978404826e9fbb7a8f011df4d791b1f246baabb2a1b70b84913429ea605e","nonce":"6b9edd7bb5de4671c8f7ef94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"8f668d9b9de697571ec8e88a8362dd087e9e6600ec5ab5a6979730d8d9e42b77e9287c2994b9e3d978d475f43c","nonce":"6b9edd7bb5de4671c8f7ef95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"f48c82544765d8f9255ccc3db7bca4e3115d4f52d977e6bde2a7a8f4107952cb2fba1b5d4be3d2ee5fff10baf5","nonce":"6b9edd7bb5de4671c8f7ef96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"95c89cb92a444774689a7b0b91e7febdfcb543e5152968050b16a86b531781cdbd7cc7f4a9d2737195be6f537f","nonce":"6b9edd7bb5de4671c8f7ef97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"56b2e27f3bd5c5a4a4e262522e2116fb97785436ad0f34648ae303eb5ec48610a4b3500e85738c300dbe45ac39","nonce":"6b9edd7bb5de4671c8f7ef98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"dcbcd6512259eb115fc6aa88feb8c9c053cff1a97ee58be843861f9bd8a69a67e8b27aa87b0256b4f3b3ee0fae","nonce":"6b9edd7bb5de4671c8f7ef99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"8470c83b672bacdb4369bf6e523e22ce8cd7c9e2b3eec502b2e3642b757b738b98ecdb276c6465dbb3733e76c7","nonce":"6b9edd7bb5de4671c8f7ef9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"bf345b979396c87b85d2b46a9243852abb3caa3774aab757c0356e210344f2fee64913fbfa9e5ba106e444a1e5","nonce":"6b9edd7bb5de4671c8f7ef9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"cefc5a1fca3d734cb106ef3f07049931550770feb8789c1243b75b34ab2d3d16b97cdd291688d5af2a2a53b19a","nonce":"6b9edd7bb5de4671c8f7ef9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"0dd28f586f7f5bfeff4322613051428b238880f9c987ec870dff6154eab4a890678af1834957fe092dd5375877","nonce":"6b9edd7bb5de4671c8f7ef9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"e5523cc07dabc48c25d73f77036c4f08c6e834daeb215cdce73aa63732d833ef582ee3999325524f5f5e5ce4c2","nonce":"6b9edd7bb5de4671c8f7ef9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"55bc7f4146b376494c51f1fc72717077fd8bbe522bf4da89da2598d735c13d1e5865a54b1de2c557fad12d2621","nonce":"6b9edd7bb5de4671c8f7ef9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"8563e75028b38494fa650c6817a3eb17b75a5cb5033a70c24e902322b2742afbe483c4fdbcc84771467e3eb889","nonce":"6b9edd7bb5de4671c8f7efa0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"e0c84178a72e913cc04663f7c61470ec19cc9663b1807eb4e4a04206443b31afbd41b99bf8deba9abe0ab562a2","nonce":"6b9edd7bb5de4671c8f7efa1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"37b19a64c8d84e7a7af0e1e46372f2e91c429270a92e2ae49911a3a567c038ae92003f9ffe2b0fe28662648578","nonce":"6b9edd7bb5de4671c8f7efa2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"aa22acade5287949bbbfb38a89bad0a187f822fded9b06465148004e80c78c153761b172a779c67deaf6fd967a","nonce":"6b9edd7bb5de4671c8f7efa3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"fddb924a6a06e5b6a0c67dc2bd0422c668d23d8e7f206637182b610c52b5982181362e4f6e8dc99e44ee77be9e","nonce":"6b9edd7bb5de4671c8f7efa4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"fa8b1fc7d15a02572f92e2edbbe7171801f0fffb7918f25d1898be6b16b7429f475eccf55372659cdac19f8490","nonce":"6b9edd7bb5de4671c8f7efa5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"9cf048f07cb576b6cc27be436200ba90ad58f38ee903edeefe6b569d9c24a36dcd5fe30e5c9f31d93a57e15f3a","nonce":"6b9edd7bb5de4671c8f7efa6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"6cd6e0ffb9be434695e58e402c68f0ecfcbedc1f2a9b07b35f64dbe9e034f556372ced7b5054f8383d7e27109d","nonce":"6b9edd7bb5de4671c8f7efa7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"1746098b591b96457dd6d6131854bbe489aba9cae0e9c03ffa6e0d4289b7f728940ca3d9c6789ba13e0885ebaf","nonce":"6b9edd7bb5de4671c8f7efa8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"0d43f464b931da719ef617ee499c6ec863e84943042736433d9a60b08d3f0b9995d4cddb1b8e68fcfe3b51295e","nonce":"6b9edd7bb5de4671c8f7efa9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"5aed021a38773844d5daa394b87b6a58e71fdaf86183f12d2ae23f4d9a9c6e5bcdc25f2ff8b91a91ae9dda1246","nonce":"6b9edd7bb5de4671c8f7efaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"6b1bc1c6334a5122008305ef1a856826d84a3c092481f01b6ce0adeb9215611b9e68def7dac01860b84ccf1305","nonce":"6b9edd7bb5de4671c8f7efab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"f4515d669505aa72970f46e8f62206335a6b934876854e7b2d5fc05e2ba50f3d7939cb7664073b833c7f81bd88","nonce":"6b9edd7bb5de4671c8f7efac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"1fce708a2095e794fc3322fc42938302c73e16feb9b0ef9129a0e130c10c379d086fa6c9adaff3bd88a2d8e9ab","nonce":"6b9edd7bb5de4671c8f7efad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"617c06151bcc77562f80032afad1d9f4d200a108513d07008e6c42506a538298bd25d97b4d6c0d06fdd08e7951","nonce":"6b9edd7bb5de4671c8f7efae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"85147aa72bfce51bef7928de27d32648f3462216b9c31ab98276dbd898ac839602683a08a95ef055c13810da96","nonce":"6b9edd7bb5de4671c8f7efaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"dd99a60948786c3427c012c29966273b80f653f6531f3ec806008bdabfcc375d8231615bf1a9be2b8522795fb0","nonce":"6b9edd7bb5de4671c8f7efb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"76195d3a2404cffa95fa60ed3550f25fcbf47e530e802dcdf7bf986b538771b54af13256c0ce72966cf3c3a79b","nonce":"6b9edd7bb5de4671c8f7efb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"ceaa15b1f25898dd924529a9ac87e955a367420a57015cc89365b4ac02f818c0fe3a327c5498c7c3e5e4f47600","nonce":"6b9edd7bb5de4671c8f7efb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"f04864f72e041ac202383dafec346c75794c5a564ec4f08a2086c8a73acba67730cfd6c2f8d3d9299c9034df25","nonce":"6b9edd7bb5de4671c8f7efb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"42b25826ded1a30d41bd955e37705c176920cd085708c76d92a9882e9945e48eae80e5c0192692e041b51ab81e","nonce":"6b9edd7bb5de4671c8f7efb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"65f463201b08558299e9ae724763a1dbcae5a149c8edb39e5da901ccf628fc6fc867a4ba1fcf04f466deb02959","nonce":"6b9edd7bb5de4671c8f7efb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"0013f38552fb967467dea80ef2d6df7398c37becb045ec17207a3863a2a1d007c1d322e51200b4ceaa964c8190","nonce":"6b9edd7bb5de4671c8f7efb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"ec27108263c89c4f108b13bf61ca92222f7ceaf60811809e38d17354b17b432661409af16027d2f04230e40a20","nonce":"6b9edd7bb5de4671c8f7efb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"d039f92742edbd814530067eb4f0214a1c70ffa7d96c5d291215cd584ad550babac6b506e7c714036316dbeab1","nonce":"6b9edd7bb5de4671c8f7efb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"e4eda6632f5d13f70c6a2527d5a4d011b956e69ad504f838b84f520b2ab905e9195011789278ee116c6d26a51f","nonce":"6b9edd7bb5de4671c8f7efb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"fdac497e49d56e2d4ef500620df9587bc5eb5e0473f7f32a53d7dd2262a7029d0a8cb4af3e7f261c16365e2a37","nonce":"6b9edd7bb5de4671c8f7efba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"deaa113ec47141d0ea00d2063d98c4d585edcb175916de822fce163f0fc24e311d29e3a479d5b177620772018c","nonce":"6b9edd7bb5de4671c8f7efbb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"13a2125eb00e1b5ec57a51269a9240f470f6a0a249aa2504a872847383a8efe64760257b66bad07d9b3ec7c255","nonce":"6b9edd7bb5de4671c8f7efbc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"3e8a6e47eca65b787ec3640f9f202ee67843e77d85b0a1d4dd1b9eaf34b416f03a68f2b11e661bf0354d3b43d8","nonce":"6b9edd7bb5de4671c8f7efbd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"48c54438246da2ef3c8bcdd52c37e377dfc275ebb0eaaca21805f9c6df1e680b9430f1191b8b93a05923a78302","nonce":"6b9edd7bb5de4671c8f7efbe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"635f032d64ec9218b0e614594715f48d6326f3fcec06ca2b980c06f13b803a8347c43e350daf629110678e40fc","nonce":"6b9edd7bb5de4671c8f7efbf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"47cb97438dc7adb31900a2658ec0802289fd730b70238fb00c7452461c0b5e262f89692cfbdc09f5bb1f6351bf","nonce":"6b9edd7bb5de4671c8f7ef40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"c54aae71f03b7052758ad34ebe5f53d1ac616ab8c55b8ca557f1222affdd5c56df7363977ce35b3ac1563e9d1a","nonce":"6b9edd7bb5de4671c8f7ef41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"9971778b36a828b59c8ca8b8aa3c33673d31faa4fa4f04a4b75780c94d2c0bd71f1f8764319b63dc2d77208a13","nonce":"6b9edd7bb5de4671c8f7ef42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"956695f051aafab313db37a87cd4f2c735def61b0716b0f7eea61cfa1047b335b3e57d7f9edf901f6b984b3df2","nonce":"6b9edd7bb5de4671c8f7ef43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"2c33c7b24cc3534071d3f39cdf8090fbb3514c9c6d3d536df43754d1ef962144864f538605e8cde678e3df7aa5","nonce":"6b9edd7bb5de4671c8f7ef44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"662caa433065d676437b9506d75cf8c75e7ebb3320a979a8c6c0248e44a8a953766da8928c9fdb35f5a849aee4","nonce":"6b9edd7bb5de4671c8f7ef45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"2b61e447a5a601dcf18dc657103a26e2261804053b1956f6afed4a9cffbacb7e19611f2456cec44c133b031439","nonce":"6b9edd7bb5de4671c8f7ef46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"548de321727512c37539056730d750c8691ee12946a42806606c37dd5bd53303530bf1fd69c31b414d7ff02f3f","nonce":"6b9edd7bb5de4671c8f7ef47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"160bc15abb0f6f7cad55d4e3484b3345c3e2e07a2ddd84147f4b70f33418d77bc1f4d1ca24cf977b77a5204c97","nonce":"6b9edd7bb5de4671c8f7ef48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"610ff0412e012f27d0a50112ca4baa2a150c0e6c50c80315b2e2ef6f7b7af63cb52650e91fcaba4c18d50a8cc6","nonce":"6b9edd7bb5de4671c8f7ef49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"25aaa3a25b30f6b0e6508cef022b43e78132066cbf02ce54039661902351c7f8f0724fa29a9ae62239b97f2222","nonce":"6b9edd7bb5de4671c8f7ef4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"9e65a86f7747f7a130fade9a02706eb52afc5c621503c41a5d0ff521bfcc76f3ce2ba13782940c7d34aaa83513","nonce":"6b9edd7bb5de4671c8f7ef4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"dd1e4f0730c3e96b2958a862e316ca05f24ff593874a2107efea482de8b946b7fef1670f8f8c7ea3f1780ebc0e","nonce":"6b9edd7bb5de4671c8f7ef4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"6d03b176f0e7ed3966f37a7793a42b1b6cecae5890f3f70e365e18924c6b4cc5753f48540130d1baeec2d0074f","nonce":"6b9edd7bb5de4671c8f7ef4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"43db0c1c7118fe5ebc0a3dd558db5b6a65e990d1754b9cbf2ce11f7d0572f3477bab8cc4eb897e69cf115d28cd","nonce":"6b9edd7bb5de4671c8f7ef4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"c6bf8821b4814631ac8c6e92d62e025fe3064e6c0bfb5bad91c37c7476d6e81fc0c61affd66b7334cbf8b16a7a","nonce":"6b9edd7bb5de4671c8f7ef4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"c7fc18e2a8a5787baa1a0e2d418aa906c17e98f998f955ccc51cf6ceba81044210f9c1b6a8f2e641834058605b","nonce":"6b9edd7bb5de4671c8f7ef50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"9931ca229dde694bffc8255ba60a9f8eb8ea74132a444e5599e0e7d84e71f1a9b90f80238694f047b36f9e01f7","nonce":"6b9edd7bb5de4671c8f7ef51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"95820bdb8df33412b39eb7911328732a096936f5b531e6047520b97dfda42b10342dba57162052749bac17732e","nonce":"6b9edd7bb5de4671c8f7ef52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"1670339000c5339d009998d9f202f66d794c5c9cc6bced0c936829cfc9cdc19691fbcfa975a5cbe3f9e563eb9b","nonce":"6b9edd7bb5de4671c8f7ef53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"1174790743661bd41da9e1be6a55112db124f76b72436c25402914af8a9f1f26b35c4df06e9d469dced872a686","nonce":"6b9edd7bb5de4671c8f7ef54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"5e585b18a65616e1faa223fd1e57852e2ba843fc3fc736112178b2ede995f129347fcdd3be9ef6a856235e5941","nonce":"6b9edd7bb5de4671c8f7ef55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"ed6173e7f0d71cb121fdf8ab0f412095ca963df00fe01a6be2695b51629f12dae687a7adb853f1fedff1924c03","nonce":"6b9edd7bb5de4671c8f7ef56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"dc0c349cd2f7abdeb23f1db937a46d4910dcea376cfc42cc5d99688543ce0922df5f5069425faa238520a098f6","nonce":"6b9edd7bb5de4671c8f7ef57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"b54935b67c02db70ebe44a8c72dbf1e598674db52f8d00d47d0b56ac31ed590a92082536c2d37d71799349caae","nonce":"6b9edd7bb5de4671c8f7ef58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"721809d9f21ef61bfd1f3c40cb047318ea4a2768aa36bfde2a20e0507d49be983dc5455948b9cec38299d6b6fa","nonce":"6b9edd7bb5de4671c8f7ef59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"6b373e16b20314c5524a1f57d3534ad7f7cd290f37a9ace4ed4422f32bac7abf12794520bec5396c8f71185f45","nonce":"6b9edd7bb5de4671c8f7ef5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"5e53be2efd68ba7ef1739a92f63eb521da0e52da7805f102bd0d0373e63a7637d1d6d1b9b27a8a512420d8aee4","nonce":"6b9edd7bb5de4671c8f7ef5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"bf2773d2a51199658dbd345ba6b365930d3cc349d19833bb9015d0cb8b9cd6f7158765ea6184c627a84d4377b7","nonce":"6b9edd7bb5de4671c8f7ef5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"4d30c60dc718162f0b40627f78ff12df5c97fbe0a6e6db9afd5b749cc5096d359e2856f59921c745ac6e15239d","nonce":"6b9edd7bb5de4671c8f7ef5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"5a40c23681c4f9f344ace011b039a925574dd540dc9ede562fee9c3068fcda09d32efe61a247b1c086fc6afa28","nonce":"6b9edd7bb5de4671c8f7ef5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"43264427f7b3ca9aa4df1a9996d23bea7d77b0a8bc148832b6dda48d546990247b2724bc3dc2b8d8ee92825a7e","nonce":"6b9edd7bb5de4671c8f7ef5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"cfe231de6a4a6068de3250ce4e3c50fbff68b49e0cf8c9d1f578275edbc2bf996c5b3af3818fa80eb9ea2b37f2","nonce":"6b9edd7bb5de4671c8f7ef60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"faabc19712ee2ba53d80ab23405d65fec5d58fbddccb5d5388724350b3dc4a3926b5083f5a83697c9a431efb17","nonce":"6b9edd7bb5de4671c8f7ef61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"c79876da191d3ebb4c1b249cd78026c7e82347f8d17e9e77b5973ce8f2004a17d093cd90ba980bebf89e03750f","nonce":"6b9edd7bb5de4671c8f7ef62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"edc699d20c8da3912f336e615950856b1b99bdec2e80b2c344888ddc4cdc6e542d328b946a746944e128e7a764","nonce":"6b9edd7bb5de4671c8f7ef63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"3b0e5617aab11f6d968319cc7c8b8ff0a5b34a78802c5cd37f530e40a1649334a2d0057db719dcaa7ef50d52a2","nonce":"6b9edd7bb5de4671c8f7ef64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"f95f5205e6cd7c97db479c0958245ef521ffb9b828513e2eeea6b5007c18acb58a2b6790442fe439c74a9ac692","nonce":"6b9edd7bb5de4671c8f7ef65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"df9823ca777af7c84d8b6ab8917f2263f721b85d62ea42a248abde46fd4f12ba1e6c8e2726cb9b2f5d4092c309","nonce":"6b9edd7bb5de4671c8f7ef66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"5bf34c03aeb2c71e193dbef546d4a537727c0f22b3c04caf185d32fa82ca6a61ae7f11ef155187bf24eb2acfa8","nonce":"6b9edd7bb5de4671c8f7ef67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"9049ee88976581e1101c84b1cb91923b050a7227b0cc51d62ac259d4d0716c62d954d24d9897f566b33c279480","nonce":"6b9edd7bb5de4671c8f7ef68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"7388c6b68a06218be384e35c9cd4f0ae45f3ff6ce1b56e6e6b10c19266a9c92d42b96d762b2dba7db3e806bc1a","nonce":"6b9edd7bb5de4671c8f7ef69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"46cce429bb194fab411e38ebd9fc26151fbe5003f2ae38c39d95728f52d947d621d1fd5d412e7c2ff8820c45a5","nonce":"6b9edd7bb5de4671c8f7ef6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"675847b16d7b70971a9e4fef49e5e73a2d63f53f5dfc5da874c8c65f844caa13564b131674dfb8b375ab8c0f1d","nonce":"6b9edd7bb5de4671c8f7ef6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"36b0c1735a56650ed3484408b2dd11629a855810b3bee3ecf847c49c4ecd18771f772128a4396c8e9dc8822253","nonce":"6b9edd7bb5de4671c8f7ef6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"261892aefe5fa41bdc8d344d112b03affc8930d38b1e3ce99edddd2e81ff8ed9159be2fca3f0aa160e03825888","nonce":"6b9edd7bb5de4671c8f7ef6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"5e624d295c6d4cdef417abfeedfe1efd481dd78b27b10e6c57b13d065764b9efaad84442cb33017de80c57e0b3","nonce":"6b9edd7bb5de4671c8f7ef6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"be48e277e92bb987c37e5273f786a24ccdb72965f95a66428441ddb8864e1e5194c95144d47633e8923a8f40f7","nonce":"6b9edd7bb5de4671c8f7ef6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"0e04855d99fcba874a144bc4cfc0118c5e42ef77a10f2a03231b73ce1447c2bd3bf798cdee03b69c1aa8028291","nonce":"6b9edd7bb5de4671c8f7ef70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"62be63b6b4bd6eb1219b598167f274534ac63640a0b94b6d6c337619d883dc2a7628c28cf206bcecf13e60def0","nonce":"6b9edd7bb5de4671c8f7ef71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"84c5cb16a13b7ff25bd1d36bc06c2ad3ea5f1eb66e1eedfe983e419a41744b222d46da4ccfa2982fedf218b5eb","nonce":"6b9edd7bb5de4671c8f7ef72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"f1c52904d50028c465036b2885d7081961ba3e131ebbfcd252f23c1158c11d407712d8d1cca51bfa2e19d2fe0b","nonce":"6b9edd7bb5de4671c8f7ef73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"ad588a114076fc4aa22f0ca8412cd51c84e9d90bbdced1441ea312752b88b3e41ac04e1c3b15fd44a07ff6ce69","nonce":"6b9edd7bb5de4671c8f7ef74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"646c740c3d1fd0ecf456bb7e41acada9b747ed0e3837f51cf816ccf24bddf2ed93db2144fa675b896e94c65457","nonce":"6b9edd7bb5de4671c8f7ef75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"939fe7dba73ba4a0c18f0b41504aecfe4d7b1684ea3d59f2254436bb318907cced5229bb9f98a4f05e168f6599","nonce":"6b9edd7bb5de4671c8f7ef76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"9a4e27658eb2a509a1159e0be3941474bc3163bc1f698a6961adc0bca69feaceead2795569a988fa8956d42327","nonce":"6b9edd7bb5de4671c8f7ef77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"33f46b7d99ffc1aa04d727c2a299a8edfdda8ca8e9136e0a50655d8606ff1fa8640312625dede86d3778da8e17","nonce":"6b9edd7bb5de4671c8f7ef78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"b721b84ca45ad471a0f30562403e4ffe1e6559ba7e13260fdb1cf1e7ce3610e9f73f5c111bdf749ef54427042b","nonce":"6b9edd7bb5de4671c8f7ef79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"234ad5dd32aab327690867d6acbf666da29f4661abcfd007d5b3d04db08d5d824ce3a235bbee7342f521f6ce8a","nonce":"6b9edd7bb5de4671c8f7ef7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"13e6c6a33d7a00afb07a87ebc2f1031f9c84fef80d614ed006b67e8c8694f92a3309852a850967e0d84d78dd72","nonce":"6b9edd7bb5de4671c8f7ef7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"74f152c25f6d06012f25017840450b25170e09f78e8acee7f10588d5ab25e4dfbdddad4507c13d8da8a39619fc","nonce":"6b9edd7bb5de4671c8f7ef7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"c27cfde44c58ad0be07379f8a78d208faa28fe8a60f25ab1a6e64fd2f5cee0361dda694b0fbad5c4d035bd6e9c","nonce":"6b9edd7bb5de4671c8f7ef7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"8e75b65ae191349e30db772a29c73a078a963136b658ba41d6eb58d5fd8b77bebcf547fb1d0de76030b6c896cb","nonce":"6b9edd7bb5de4671c8f7ef7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"e65d14f9528e5d7249318fa08f4e7d1a4d89786b2be326a84e9c66df7e44012584a554e86eae838b737b02e867","nonce":"6b9edd7bb5de4671c8f7ef7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"aa8012573ffbb8787f75d20e95fc886e76561503d8aefdc54738223876f803727bd5b0e1446b99ea23b82c211b","nonce":"6b9edd7bb5de4671c8f7ef00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"4ad16bb8ba4578ab9ee9de263c07a4467e9a918897b0e59f94fe2bc561c1ed1ef93de4e737f3bc64a970255127","nonce":"6b9edd7bb5de4671c8f7ef01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"a41978287da98fed3071907d0853e76e4f6f5c8819626def5b003bc83f3d26afc4092004d7bd443b0ca9662ded","nonce":"6b9edd7bb5de4671c8f7ef02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"9a10ad31f68abc40cd840e4a17b7d3c5dca0312af9a1241d4ca330d4d68f4a28b3731c68760eb9ca267473ce39","nonce":"6b9edd7bb5de4671c8f7ef03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"d7a88bfe6d0226cbb0fead8c3f8139e83eb59169097b824a1a7bf44075bd7d5b428bfc7f207368c20b63f08402","nonce":"6b9edd7bb5de4671c8f7ef04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"79758869977e4112dcb9175aa2775c6f5c3d60d567ab31cd3672b6ff842950a27acfdb4349dc5151942abcf355","nonce":"6b9edd7bb5de4671c8f7ef05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"0853d157b7806c5879a97ce3f7a0f5c4c4054881f30aae22fa48d66016e60b569d90b692e37d50e76f3dd7b3a9","nonce":"6b9edd7bb5de4671c8f7ef06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"e958790868ed9c9caf4d0f269838e3256ac8f619997f1aec2b232efebb7a9f71b93ecec9f943c957339106e1fa","nonce":"6b9edd7bb5de4671c8f7ef07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"9f1c8319abf1fef36288d53f73de7f2f0aba68a3575f6b6f66abd5dbbf55889d872e405e172d80a93149770ccc","nonce":"6b9edd7bb5de4671c8f7ef08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"9863afb4dd6c7060a2a73eb70350b02161cde5a2c53e6f41d22daf9eb0c01fb6f03227699c23374e1b94488c91","nonce":"6b9edd7bb5de4671c8f7ef09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"599f9fdb9b4cff8b11be80bcb219a1ffee4afeefe60fb6a75ed4dd9f0d989631a60660f90e7537d6cea3b6e85a","nonce":"6b9edd7bb5de4671c8f7ef0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"6b4a5bf76bd4a32cb048ab3a4260b5afd17312bb331a17c089e847a1fbdb06d9381e18f9c9029c9ffb09eaa731","nonce":"6b9edd7bb5de4671c8f7ef0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"3733232763389c771bbe8a18c47e8bdebfca9ad32802e6e9978366540960b9f85f8597835f74a9dfe5f4d23444","nonce":"6b9edd7bb5de4671c8f7ef0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"4cea562144a20921015794796ab52481c56a874e4a8facdf678e77fffbd530a9abbbabe35b047dad8186102118","nonce":"6b9edd7bb5de4671c8f7ef0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"37f8a2f6f272a931158fc981c0afb1242f73d3756acc76c5a44fd032c23c3942c93d978b64573b44db8a4aa123","nonce":"6b9edd7bb5de4671c8f7ef0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"37e7cc86465e4b3a0b04350a1dcb5d3e7f987470e7566ef1f0b0306bf5e0ed0486c48d5ca2532f8d7edf06444e","nonce":"6b9edd7bb5de4671c8f7ef0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"7e4ccf8c2b6b6289a546a2ce15e6487fda2ee343446189fca76c64679370d941a4a3e043b19d353cee1644cc32","nonce":"6b9edd7bb5de4671c8f7ef10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"882265f26e3cef5a3fb71ef230237da6c39f1f5b510feaa545cc7de60e9caabb731b1c16f2b330145073e61dae","nonce":"6b9edd7bb5de4671c8f7ef11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"d8ac5f43038b3a8a6d7930c765a130272ca8805317ab4a03c536079e1c42ed1e4c090d233550c7cde50a57300e","nonce":"6b9edd7bb5de4671c8f7ef12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"7a25c05e0803e18404982901d0b5f20dfade7910a640acee996aa44d53747d3bd5fedfb4ec9d59bfb5a4b53896","nonce":"6b9edd7bb5de4671c8f7ef13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"aadfb869718b69cd8621c0cecd0d208b349ccec5ba4ab5741c256d0eb8607e658817239e78ab4bc947621377d1","nonce":"6b9edd7bb5de4671c8f7ef14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"af889dbdb50ed8a0ac3c16d439a2dd18060dde4116991aa286312bfa7d67dc1e945946bc494854df9a33ab740e","nonce":"6b9edd7bb5de4671c8f7ef15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"732eb1cc734d8a06082032f9d9159c176d5db05634da1b4697ebffa4dad0136a5d252dc7ff348b283617a37872","nonce":"6b9edd7bb5de4671c8f7ef16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"f9367d7de84b821122801d34b14587b06969c1db60121ec26f65f4da1de25f6288ac2bac927fe48758e38b4d84","nonce":"6b9edd7bb5de4671c8f7ef17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"b0da30dfe7659411de968a6ddf36a222c1efb71b27decc7e1dd3b8253768a87379a6773ea2aefb708cffb7dd8c","nonce":"6b9edd7bb5de4671c8f7ef18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"208ce51b4e935c9cfae608324771b8002c6001c13d3e270ee06e8fd7f2017bbff395a9d70169c9f8cfe229b152","nonce":"6b9edd7bb5de4671c8f7ef19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"dc95f8c64db9a219efcee544d553f4567c83e50a2290fdb61ca8ea67cc6f27f997ded03488f71394721f90dffe","nonce":"6b9edd7bb5de4671c8f7ef1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"c77e1cd1964c9f7ac412ccd1312029b842def3ac344db8a31ce7d3774d404083081c1671c284304199fb9c2357","nonce":"6b9edd7bb5de4671c8f7ef1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"b587b7b86a8d60d4615e1839d34d1c001f542ad9112c00be257289ed3532c5898f2cca1d7f53bb307361d1ab1c","nonce":"6b9edd7bb5de4671c8f7ef1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"38cd193a7b263395cd884f3c5a40e3c4297741e6a125f28cc67216a9ee50d4895036d7ac43ac050116531cccc1","nonce":"6b9edd7bb5de4671c8f7ef1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"1367dde7197667a7453088122964dc65e6dbd67a6eb9fbdccd38b0a89c45f442fa2eb223b3e341c33901675434","nonce":"6b9edd7bb5de4671c8f7ef1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"de74041a86c1f3a8ee0f4c38459ce87f6851c868750087a8f50f9117543525d500bd5028680d6e607c5c7947e5","nonce":"6b9edd7bb5de4671c8f7ef1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"b0631011646b10048d70157f5ea6766600794af38d667087fafc98888d8c43ac1c3e836c8fab0379f34391da32","nonce":"6b9edd7bb5de4671c8f7ef20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"7a05872d2271f99a7b17a422cb400096295a8cf7c9a53bff002e10643aa6d354a5fbc609503d5f22644bfcd1ce","nonce":"6b9edd7bb5de4671c8f7ef21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"917243913674241d7fb2bfb72878c1390822e900c0f5df4f4d39e4016848aa894e938571c277626e42ec14d0f2","nonce":"6b9edd7bb5de4671c8f7ef22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"eff0a3ddf9a11fc6674499cb6369fa9efeace5d77d7ec86a447f4a01f5cabbd121cf06ee2469fd3fd4523d9a71","nonce":"6b9edd7bb5de4671c8f7ef23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"9b3cffe0c6ba5970e42d40e019ef900fb644250f775b4ddde3b6fbca85a09bd89a384ffa2f4adb428d249569e1","nonce":"6b9edd7bb5de4671c8f7ef24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"a9fab90547efbd05bb07af67e4a79304de1426019c371e133dfb6493e2f256754a82047c93bda113d0f0bdd0a4","nonce":"6b9edd7bb5de4671c8f7ef25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"37ae260e34ec6ef4969b71085e65b838a28836202f7e87d2036d9761601de696e7c52f817adb0ddb4a9a4eb6a9","nonce":"6b9edd7bb5de4671c8f7ef26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"de6e7e76258d7377cdc7741548d99439326c87e52d610fda45c549fd8bd01bfe73aaae37446bb364a93c0f7d70","nonce":"6b9edd7bb5de4671c8f7ef27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"bf4d6be14e7217b627b91d3e4db72134918443be6d1a93bf9df463d11e6b7b2ac437a938740cd360fa7b1ce23b","nonce":"6b9edd7bb5de4671c8f7ef28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"35f2a5abb497b62bb8d15fc30e0bd734f9d6b4de37575f5f186ec1bd88d86a8da29f226b9638d3705493543962","nonce":"6b9edd7bb5de4671c8f7ef29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"1e2cc1ad82411c969cefc5ddb32eba060e92298d8d9c0ba8cb782dd127dd77c53d7c96651e20f1956084d9f9aa","nonce":"6b9edd7bb5de4671c8f7ef2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"2d1041ecb44b172cc70e5b09c297323bab136e6e2d770a025aac4ee951dd150e5696ff1f0de476a4d4250fcf6e","nonce":"6b9edd7bb5de4671c8f7ef2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"11e7dbf3994267150d1665dc75e6750157d806d6cf336da3737da31d039018da034435f08e5d240a5de94060a8","nonce":"6b9edd7bb5de4671c8f7ef2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"82a2cdeb255514c7e3a6160baaff51d3e3cd77853bdf6afcaa3d6b6b758c5a9d572112faef61c3bbb45153e49b","nonce":"6b9edd7bb5de4671c8f7ef2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"330ecf6b4a4a3e17c19eb93ee5553119cd5b3b8b37737af8092356dc05bb3a16c3f02c01506edf4e2f26429722","nonce":"6b9edd7bb5de4671c8f7ef2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"171a7e1e451b4eb6fdef67a04ebc0914c76ca4f6303cc77eab4488ba865ef960cadb6b3085bcba7eae4ba0abdd","nonce":"6b9edd7bb5de4671c8f7ef2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"f587374f8d9999f8ab04cd9f107e3f8512cc3d6d1e557c21f56046e54c929bad28d464c8ea12b7b43526c173d6","nonce":"6b9edd7bb5de4671c8f7ef30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"8a8e186c22bb66a8cbfc1e8425a186d4062488c43399eab79cbe19ae2772f08ba59b28cfdcac5f7247afa8c473","nonce":"6b9edd7bb5de4671c8f7ef31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"acd659743a0617530923e170762cab3f2de8369123bde2d8ae5600bee72d042f9ac7c2f1a9f259238accd2dae6","nonce":"6b9edd7bb5de4671c8f7ef32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"c9436bbcaf41e8674584794735cda8671374c3915665109c62d7b18e3c661b3975abe1e224a66b0123fa9126ea","nonce":"6b9edd7bb5de4671c8f7ef33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"46791b9a09edc33aae46fa1b40d94fdbef9dcccff60b38aff36ca9ad41886f32aa7a219782233ab5d5fb7a6ed8","nonce":"6b9edd7bb5de4671c8f7ef34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"a38939a423577cc6c6edcf65b655e3f8623a98339387c1f282dd3fbab034525e0861702d6035f69911fd092282","nonce":"6b9edd7bb5de4671c8f7ef35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"cd48fc4df62e4356c1c5404fde365ade15699f1ea0c3759f9f2deec5047f1a03eb699399dc368d17582c50a24c","nonce":"6b9edd7bb5de4671c8f7ef36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"b2f74ebc72b7a27e5831b1344c4c041d81d481397ba22097e74f0225d3c8aac793425b60c060f12b6100bbd120","nonce":"6b9edd7bb5de4671c8f7ef37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"2a42805029c95d2e04b3e7fb91cc69a9745f56ddfbd25fc2ae1c6c315ef48f31334fe1f0ea67e6e8b96b3e876b","nonce":"6b9edd7bb5de4671c8f7ef38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"038dd4e0ddd88bdf092f1a6d75229870d3138849f677231acecb0805ace742886822a25065ccc8ea61773d9723","nonce":"6b9edd7bb5de4671c8f7ef39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"78b5df275cc3cf0ca4377566750e8f5fa481f0a1f6b6557f843ebed25111e936ef185b1465145f5b69b3f5ff97","nonce":"6b9edd7bb5de4671c8f7ef3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"15f3be208244a5c36e1297fd8182e4110997c4efc360cf1eabfa1e1cd283a867a30b67708734e898e2c3016496","nonce":"6b9edd7bb5de4671c8f7ef3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"67f1f4dd2f4461a0982dc715419371a29819c2f8576dc693477b1d76a364dbdf7a1eeb0aa75be5c46d19e6536c","nonce":"6b9edd7bb5de4671c8f7ef3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"0a7fc8751acf49fe180ae5c577e4d9bae0325f765f69c607d86c978dd25a3ce22ca17d23f94b005beee13b8497","nonce":"6b9edd7bb5de4671c8f7ef3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"45bf64842edbbc80c59a090fbec8bfbad9e19c4304136e67a035b378a491188d31a2220cfc653622b8b77981f4","nonce":"6b9edd7bb5de4671c8f7ef3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"f85cb8fadec5dc22b4663eebf01a64f103599cd1728b700b2ff5ba7f32738c802f4733436771a080a6375aeb1f","nonce":"6b9edd7bb5de4671c8f7ef3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"97e612cc4ff6a6c02f7db397510f6adcba46c2b752844911c2eab9f6baa166e56d36417e5b2d310d054caf96a7","nonce":"6b9edd7bb5de4671c8f7eec0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"8a22fa1c5f1d0ceaf0e48483192bce87698e28b765453d8afe3f9f809a7111a4"},{"exporter_context":"00","L":32,"exported_value":"0a35677be4d55fdce025118f20f4fd950ab6b868b56b50d2f7ee36a13359f9eb"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"5979455c44bf2f84f89489ce889bfd40fc56a86b680c4b145974cdd80ea7e2e9"}]},{"mode":2,"kem_id":33,"kdf_id":3,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"503b95362b644c7fcfec9987f0e3a64e09005f2147ee975a8a375692ade896015fb6ded2c0eec01744ef09e4aec6e54801b4254a7ff4d8f4","ikmS":"ce7902d546c60771912d175457e6a822a3ca0ebb613eab02df1fdd35dd7af4e89bb35b2806965e43266ef2ae4c11add3b1e403aabdd2fc02","ikmE":"909fd5f9ba50bb9c408e479514b03680ce7f7efb0e64ec7a612f42206e952858f85820f3c70244f324bbbf553d7da72db6c4ee470ed964dd","skRm":"390218cfec9ba040c2621bf5c4222615fc854c438748d2801a0fecc2ccd61d650c5eca41ad11ecdea8458881a67a1c5c53de83c44e97c92d","skSm":"8e51222dd12477743f2adc7c677b61d48f4120771d6771473e9176886d59b3158e2c6828eb4ea10c07a35411cbd4b24d88b366a4daf34776","skEm":"fcda3c747078543baa37f7df924fa3fc7e5f5417852e0586bcdd6db48c63e2ea3722c3e162ce6e43560cf109cdc5a9deb386786baad7c54e","pkRm":"542cdec7e847b0c26ab5cad63a24cde98e6e9934547410300fc00a425b1eba1a975b08311ad5b10e482fd32232c81233fa79d08bedab7539","pkSm":"94821344e572e6d78e1b01685edc46cd253d8764dbcde8fa585c208710c07cfaa6fe19103c02b3ac2a82920f0971765456902ccac04e32cc","pkEm":"57981e8134813295ef60b71fa54779d59dacb17f09a5dd280573fc1bd8d3bfd579e4cffd048095be1c6ec82afd8bf6ab163a0152bc734638","enc":"57981e8134813295ef60b71fa54779d59dacb17f09a5dd280573fc1bd8d3bfd579e4cffd048095be1c6ec82afd8bf6ab163a0152bc734638","shared_secret":"da808f4ab10f3f2a7113d76f79b9b4de48ef50fd0d66267de5490008be105e5d9c2873bd752923fec209ecf8e7fea9dee66567f521b3fed9b0e29ab36f4b7cd2","key_schedule_context":"020fd8a8635a1129ed4cee7f5560a60bac8af321092b45499ffe0eda28218c8d1d910e2ee5eedbec01d33683d6f9f923d7ab0a69b4b8fd0d53307f806ed48cde59574a72814c5d8e45c985c4252e66abdfe846113c17cdd7485893b89e0d5cb23d409145ac095bcceb628874b68378897f77c36eaaf45dc932c30eb5841015517b","secret":"732dd8b3f60969c7521b5c677ea26701449ff386811e66d9d6c23fb68fa5b7e867f23add337b139078462911dbc9b54beeea492f262cd787a08e8e7ba6644487","key":"12bd74b3d1dbb33003dbf5d993d4fe48","base_nonce":"d12236568b4bef52ee4a525b","exporter_secret":"aeaaf20994f1eeefefad57118b7b46cdf5c59f44162bec9743722209621443b1c7fee92b9df4e539845a7cfaa0aac432ee765a0768a2be91f9d669bbb568a746","encryptions":[{"aad":"436f756e742d30","ciphertext":"0517b0c430a33128b515454eb372f7f65bce147a73c3aa72b0d7dece712cc1600c5b723bd6b0dcc8d86cb71f19","nonce":"d12236568b4bef52ee4a525b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"ef0cb09835be00566d2fcaf0a8c85788e6447a78c328ada5c1e46b725da3be4c22f2c617211d1fd07ea1b0c480","nonce":"d12236568b4bef52ee4a525a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"3edc019b96229035d3f5f32f84138875a60f77424dabe61705951e925f34f54db85757da2822a61f57791ec3b1","nonce":"d12236568b4bef52ee4a5259","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"28a5abca8ac49965e49512d7860456fcbaae37e7ed52bfc4787b03418d6a4ac1bd0256565fa421462748316266","nonce":"d12236568b4bef52ee4a5258","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"c478508c146eaa9d5c499d0a6b682e547093796b6ae75e08320b5669791ee2b1cb54e1c7a008eb9de645cfc5f6","nonce":"d12236568b4bef52ee4a525f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"92562f7b61f6889b4fbd1b95c7b862aec98b85a1d6ed953d8f953e37c7532f8da5d8d5520bedba0f2aa6e9842d","nonce":"d12236568b4bef52ee4a525e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"10af89bd5b2c513543d5d11f26f5f23846cd1b5d088d77d18b993790a69b7cf991e41e1743e670294fe0704981","nonce":"d12236568b4bef52ee4a525d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"2925f5a31479e2fb386c1d06fd9554e4356d5e79cf52e48b691ede6be5579f9ea180982b718ceffc481da0bf82","nonce":"d12236568b4bef52ee4a525c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"e068ec301beaaf99a323110ff39fb6504a833d9a378c054b667eae088fd147be8c9c870c8e8753266e5fb0688f","nonce":"d12236568b4bef52ee4a5253","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"e98d115674e90c9eb9288e38ce1718092126e9c87dda311d62935fca41b3427a20689edffc95d12359839e2b0d","nonce":"d12236568b4bef52ee4a5252","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"346a212baccca00f834478ce2fee9c7219824f818cc0b91bc6832744a0d9294fb16497faf3df62467cd11484a6","nonce":"d12236568b4bef52ee4a5251","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"f64ba86a96ca060f3c16e9af61f5cae0892770d474cdda9b65bca75be8640f5bacf84e67b5f8a4595820ef0816","nonce":"d12236568b4bef52ee4a5250","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"14f52f1db6f98413e998f7842402556f0cd96294353de7710c105c06711102d7518c51cae24d1250535e659da4","nonce":"d12236568b4bef52ee4a5257","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"367e1c568124c91eb9d205856df0e9a739c09cd4ae78e01e8d3a09f42ea311e2cefaad2bd3d984a4ee9bf24681","nonce":"d12236568b4bef52ee4a5256","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"1322ee2b72bb77f5062751051a6f02780586162ae9164c5126d1d4049f3ac95d95fe0c12b0a8bcbaaa2993b0b8","nonce":"d12236568b4bef52ee4a5255","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"ed5ee51bd713c5308a9f1029e578c8dc6e614d134b6c914ce0f757311c6bc811106d29f7592264e1f2c3e355fb","nonce":"d12236568b4bef52ee4a5254","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"251dd33ab2473301829f77d8187549fed42381bed990c6ead2b1962bb7bd7658b1bdc8e6ac772b106f9de0a743","nonce":"d12236568b4bef52ee4a524b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"bab9979e8403ab0268c14a29aa4cb77828719e858f6c10633c2cb1ba9968058d70ed8e13c6ea710f8d6831b7fd","nonce":"d12236568b4bef52ee4a524a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"355db90cb1384e6501664e8f972d1a20e478bdc2f9071ecaf7520cdd8ad665936827d6ecfa0c26a801315b48fd","nonce":"d12236568b4bef52ee4a5249","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"dbc0bf77799be71dcd732fd7af8f33c52358412528e491c2d8f756ce6a039612fcd72f999f771027bffde525af","nonce":"d12236568b4bef52ee4a5248","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"d94ed6818a97b8c9bf19232ccd46a0abdcb6696cbfe88f4ae39eddabac0c9bf5e3dcd06eebf0415949abf436e5","nonce":"d12236568b4bef52ee4a524f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"293f4465a9d86810d935dc54236976a498d0880d22673e7484f0794895bc5df59c9e5c2250ab78dd348b07d0b1","nonce":"d12236568b4bef52ee4a524e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"7c67098d812b731bfd20d75dacad32d391e570b958e8d7e9c897cd87b206a6cd4100f4a30e78a091c684b96c00","nonce":"d12236568b4bef52ee4a524d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"e07e7b7a79bcb74d6d0c2cbb20c65481c2c6f80153c8322f2d8796aa89808d997cb1be10d63725c9f43f6faf2e","nonce":"d12236568b4bef52ee4a524c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"f2844effd3af86472d56d8f2d1530259924a3753fc87a29231fa0f9dfdf84432948d14fa9ab48694d9dea44818","nonce":"d12236568b4bef52ee4a5243","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"29414980b1589c69159812624ed80d090e26ae8d9a9c01c9f24784a509e438eceed460b236368f3134680dc1b9","nonce":"d12236568b4bef52ee4a5242","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"a9492322f3b2cebff2177056a13943e75988445e1a37a627a948df782f8d7a508e78f0c02a710d7d959e58f48b","nonce":"d12236568b4bef52ee4a5241","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"b88d99bff0cb423ace91e70615aab1d2a22a62b74458a7444ba8fc16ec8c12ea863c0267e2c4598c9d2b23e353","nonce":"d12236568b4bef52ee4a5240","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"e4929eb2fbfb25e8f72a4e790e1369fbd723f0f02d92a91bc2b964c3d8f97dcc48c786c04008ce4aaac657a2ee","nonce":"d12236568b4bef52ee4a5247","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"eb60f68bb261d3c42166090198d676d279c7578df90c0dc6994b377d4b1aa2e2c7896c925042c0c2fc52034e0c","nonce":"d12236568b4bef52ee4a5246","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"b59a074a65e9a5529e776631ce05cdb930e8c5ddaf93d49ee4af643464ccc2fd2c73f53bde2db6f36520a71470","nonce":"d12236568b4bef52ee4a5245","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"6156272520421393334f5790df795211adcdacc9b68b4c86070bda1947014958070573b45f682a0cc0ddacafab","nonce":"d12236568b4bef52ee4a5244","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"7b2b966153d25d93fc66df2b9a013b2acb1dd611998b8c81088a2b473c98a4c5d02b137f1a9df8ea07a6f25db7","nonce":"d12236568b4bef52ee4a527b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"6f6e30ec46ab2155bf7091bc4344a67150e12066aace90015eeecf9c503a8dc020e30264f7645bd3c6c27af422","nonce":"d12236568b4bef52ee4a527a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"41c824e464f63e27a5367fa08c34f0bc0d8bf6cacf791cb1cd1e4712546bab01c9551832dd5d3ed95273df5405","nonce":"d12236568b4bef52ee4a5279","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"7f9cc2fdd2356ff0700f65f9073c6796d1bbf84993788a6e16d7ce8d3af64295967f8af1f69fbba08cdacf3fa8","nonce":"d12236568b4bef52ee4a5278","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"521cb0cf790bc248094a2bf1b49642da5f7117057797486e519131336180abd88f4c91563be378e00ba561a00e","nonce":"d12236568b4bef52ee4a527f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"af15345dd6d3ee79ca82b77a9ee829f3673682e7d8afb6846a028544977377d0b5d765d32ea6233315db240e5f","nonce":"d12236568b4bef52ee4a527e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"3ce5edb7b02066210d18b6ef41ee4f24fc52f597d138047350f04f0a89c37fe789b7d7d9bfe36929e8f4d33ffb","nonce":"d12236568b4bef52ee4a527d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"6b3848ca9bdac8235e306e92eca745ec43211178417984fda7e1f300252ab2307ebaba8fbbb1db5ccf29ff677f","nonce":"d12236568b4bef52ee4a527c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"ff4fbfee55f5b32ad2af30724e4b25d08dd8abf9d278791217bc2325ca95b48ea860afd74da837b3c2e9b01c5a","nonce":"d12236568b4bef52ee4a5273","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"00acd571648c70ff13b268473cde7a5fdb08f62e36109593d8b1abc7dd50737bd0173165148ae3d0ac7ea07877","nonce":"d12236568b4bef52ee4a5272","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"e2d7b4701747d22f226a29498799ee47c5a19efde09e5c03a58c2bd7d6b07af8fa985d38292e63055fb0331dba","nonce":"d12236568b4bef52ee4a5271","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"101c24c2081c71f404dee4ef9ba091c4a9fb919be9ae31f2131d6e307c825c72f3e0eff8349217c0357e8074c7","nonce":"d12236568b4bef52ee4a5270","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"b459fcae36fe7351dddfe7af69d4f236890429d9fb26063e4c0ffdb28a9f505e81e4ed9cf8f28d48d198113581","nonce":"d12236568b4bef52ee4a5277","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"398e05415e6341bc794608a5b7d050ff938ed25d9236aaf881949361fb2244daa3edf054f496de0af850f2f428","nonce":"d12236568b4bef52ee4a5276","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"348e67c3782dc52cc08d3ec703317558de7427d0724c098f19623997319984b94732f332ccc33d6fc81d791a33","nonce":"d12236568b4bef52ee4a5275","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"9ef1bad339ceb7b4b79cae55ec2b3728b5154473f80523f8212dba1ac6f8dcd323872bb9f322da7ed24d384bb6","nonce":"d12236568b4bef52ee4a5274","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"33c209829a090e3835fa83c985b842f2a9d9e89132089e9f589ca462fb1e47cb5bb1bbdc34ae09c5e18a5392ac","nonce":"d12236568b4bef52ee4a526b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"577f865a10476d717b5c856df6c47a14fa5ca62f7d351818d21bd551565b99e6f6203e57b6704939bb5a93b84d","nonce":"d12236568b4bef52ee4a526a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"d2b3a7f52e67c31e0e082683eab3eb5abf35db65f6716ddf21e68b012db13ca803491def4ed1b2b5a132268d6a","nonce":"d12236568b4bef52ee4a5269","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"32ed828c1060de4f7963d9c151d6d4fa27139d9a16cced7f601f1e01114588192bda43b0e9dc2d9dee23c2bdeb","nonce":"d12236568b4bef52ee4a5268","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"632645097cc410dbfd88cb4a7a846000e4133113e1ca2722fd2e3916a4b912848e3b17fc1727513c6c3df611e9","nonce":"d12236568b4bef52ee4a526f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"b63feb0246417fd181f270e968cbc616c03caf556b847266a3ffa3cd0585030255ed567ab70ff4df73f767badc","nonce":"d12236568b4bef52ee4a526e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"4545a1f90a911013d8db594a5459d21098086a2de88367c4bb93727e21d164b74709767aa9623a8b2c9818a4fe","nonce":"d12236568b4bef52ee4a526d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"dfac48d4be75c6db14f494572cd4731d0e25d9a5c9a30035f11211482af1d6079cf6080848517fe939cfdbec17","nonce":"d12236568b4bef52ee4a526c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"093f208a0d523457680efc30e2a20e5357ab22866298eb155f4767022877fe7f1bd9e8cc15c23fc829f6f16891","nonce":"d12236568b4bef52ee4a5263","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"38c3e1ccc401525e1bd5331e9c39eb2f39b39dbcb37495215f42fa24c5d7d5efe2922c21740374e60dfaf2475e","nonce":"d12236568b4bef52ee4a5262","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"2f3cdf8e16d6c381bff407e500f208e5ad24918c4f487e9007bbe5bc09fc0347151fcd315983bb2ffb1201e702","nonce":"d12236568b4bef52ee4a5261","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"3f3f2909f3821c23100e5f7667efdd116d51b4a12f38a4309e944315fbf4cac3824847fdf44c46db532917c748","nonce":"d12236568b4bef52ee4a5260","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"6d5643bdfaab66f20244e1794440611336c4b08d2a1da133af03d5489854fdbc1af652f4996c6642e69694e04a","nonce":"d12236568b4bef52ee4a5267","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"5e357ca3ef16a85061251b5bac540f7c38809a46b28522e6e5b313ddf97d431d1282261705c658b95ae2bf206c","nonce":"d12236568b4bef52ee4a5266","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"300918a9244d7e12fc9ed28b3a3df17cf2505e7eb41626528c5339e5a6051fbb54c5ffe302a3deabb7f89d4345","nonce":"d12236568b4bef52ee4a5265","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"7ebd59d09d2e5a43e43ba7c3468f385b239ff35522e48f6c460394a4358bf31c1790dbf7e8f64265094c3ac074","nonce":"d12236568b4bef52ee4a5264","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"4a49700c9dd72c76bc19de84b13d5f43482490e1deb4f287c680a190c8d99146d18fbd051855ad3643a39b63ae","nonce":"d12236568b4bef52ee4a521b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"bed489e921f1474cf4fd04c4d0cf7607e0865f398149e48c75fe7da8b2d493165613f56638e2effe1083556aef","nonce":"d12236568b4bef52ee4a521a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"1aaa5e9757ffe92137cf851077951b34c41028dbf796a28ab158c36f8da58555ee2d454046ef85f6b48072c11b","nonce":"d12236568b4bef52ee4a5219","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"73ca296a1c5f244a13e95b9c6cb89dec362b38aff23ba12e0798febf17032ac28551d328e21f6627765018ea29","nonce":"d12236568b4bef52ee4a5218","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"3a8d79e2421f53428a695de161a41eb4c1d3888af77db9513eac0be91a5843d2242e0c60e33f1db1ebfeed7f51","nonce":"d12236568b4bef52ee4a521f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"667c6e0c641ef49f789d94930d60b5dfaa42d8edf505ec11401b90184dcbf2c279beae6d509a4f3712abf18db9","nonce":"d12236568b4bef52ee4a521e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"388a00e60e0b3473d527e94d17750fdcdece2aec4c1c0f988459cd8468dddb324011bc8f69d897519ec15e3bf4","nonce":"d12236568b4bef52ee4a521d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"8d0c2c81bc543aafa3254ef8d00ac20f2c368d68860bf7ac4959386837cbdc3e2fe205afd888d0c32a9ea03ab6","nonce":"d12236568b4bef52ee4a521c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"d244be367cec05c18074f1052d30ffa5c13e3c6635b16ec246ed954893e2912c6d74705c0a74013e407a19e512","nonce":"d12236568b4bef52ee4a5213","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"d86de347ea65a21f2ba82e884e14cc663525d8a5db60994bb36c01fd50d71072eab9d27e764911a34cd4e2b517","nonce":"d12236568b4bef52ee4a5212","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"dd5d2ce5db1e2fb95defecbeb2136ea722e894fec55340522fd364205cd488148f054d037674af292b9c1657ef","nonce":"d12236568b4bef52ee4a5211","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"727ca2e85db159a6f6e9b0076e7ad0dcbd0295fffe8e71d9fb82d97932b43bace22c2129c40fd9ee1601edfb69","nonce":"d12236568b4bef52ee4a5210","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"1fce63a3b2ddf830f40f440e8a035ff1547410cb527e887c640a7e692f635e9a965abf2ef30cbc49144661585d","nonce":"d12236568b4bef52ee4a5217","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"5b79406e77cb7607f5231dd3b849237f9c9d80968da826554a2fb4425ede680189b506d363104118e43d66ade4","nonce":"d12236568b4bef52ee4a5216","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"545c29618953a4d9f5739c65c8489393309a95b635710ac9f2df86deeec8303d7270832c296836557cc6652f29","nonce":"d12236568b4bef52ee4a5215","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"997f14b1ae0aab51236201e43ebf8a87f45b260c02a5ae65a7bcc5a786f4fa5bb0c8df1a156628582192886476","nonce":"d12236568b4bef52ee4a5214","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"7d7514be11ffe3d60f0c75994ed36b5152684376e01e9abe6a6e181408373cd34bb4a30160d4bc52186a578630","nonce":"d12236568b4bef52ee4a520b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"5f9ba8535b105d24442c5165b8122bfea31c749eafa7c23f3e8f5680cfde2245aee1ba5ab7a2af9317dfcf3620","nonce":"d12236568b4bef52ee4a520a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"24bdb19f598fe02536346e7568a684f7a2f7da173e3f143bd0aef027cda1c232440167623e63643a0e6364e9d8","nonce":"d12236568b4bef52ee4a5209","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"a43e2f942884414ce1a2839525cd9f3d4f7493abb2fe94b90c68fea8e50fb1b44533cc62bef45acb288ecc3a48","nonce":"d12236568b4bef52ee4a5208","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"8a032f79d4599b6df2a0d7ca4deb612ea547f6e0600186c1e357f84618319bcd1437f12531771c4a5970ae7134","nonce":"d12236568b4bef52ee4a520f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"86e886e69bb9c26da033a0bc434377c23802d0a1750525fee9ea2a7ba913d3986103c9d03a8daa8f544d73d3a0","nonce":"d12236568b4bef52ee4a520e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"eb734be5a843ea3166995ecf71efcb7d3ee1a2403d06bed7eae15d4434a4f1d995667392fd107286f848e8e0fd","nonce":"d12236568b4bef52ee4a520d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"0be1109f1e81c86703bcc51d52b7f1b85e9e689cd15f1c887a5961045b95ce4833d99a0853ef27051bb1fea4ad","nonce":"d12236568b4bef52ee4a520c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"89ac2a99070bfff587be6f0d198ae17d5399804ddb853d53ff9fc32177455aa0f861fe4c63b500c80829f34d87","nonce":"d12236568b4bef52ee4a5203","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"ddfc4cfedf351bdf35bb27bb76174defaf09f581bb4217ecc9d0d5d945aadd2c87e71fdafee400a3a344b574b6","nonce":"d12236568b4bef52ee4a5202","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"7fdac9987781200b2851d8a1eedd468b15221d4e6162c0b4e189ecd198d9b68fb7213b15c36c3b0a2d3f560528","nonce":"d12236568b4bef52ee4a5201","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"8a82560821442d70608995edca0f4cf807c08d10b97768627d55b5865f9ad6dfc9f5bad3ef3af1171b7e78ae17","nonce":"d12236568b4bef52ee4a5200","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"5a0ef258c9c76dfd6ddc82162808044b2f641926aef9d0c1f752edb7ad0894cd83bdde21c9b09553aae3c77897","nonce":"d12236568b4bef52ee4a5207","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"a75c74a69dee9e73446eab6916ead0bb09c393dd8acfc17891aa978a13da01268a87f1d288c73597003b7273d0","nonce":"d12236568b4bef52ee4a5206","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"f1c53f12cc428dea25bcb3e5b9aba8e519fce073d61d8c009e3fb4171f693217dcc378720312699a0f38c56497","nonce":"d12236568b4bef52ee4a5205","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"9bade9520b715ca363ff2fd19a4e7433c216643f98c4684f170645314483b09dc8fc9534c3ddb07a885595163c","nonce":"d12236568b4bef52ee4a5204","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"33e2fa4e8687ef686fea45accfff8ba10f5b03aa68384bfa9668d8744dcbbc99e66f2b398ed329b4af99bcd0e8","nonce":"d12236568b4bef52ee4a523b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"0811734be1ad8b47ef97314f1bdf80407ce3214866a675a941325183c3dff59afb5c9abfd7213029208a82ad21","nonce":"d12236568b4bef52ee4a523a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"51d2c1d8610dbd33e0b8082545ba35f3ce06db333f68fd31d965036311d36b100309ec8907648c9aa7d5cba532","nonce":"d12236568b4bef52ee4a5239","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"370482c84577257429a5d2bce0a66ec23889b293eff670301b0773fe4a01b5625f8b814673c27ddb1b5275849c","nonce":"d12236568b4bef52ee4a5238","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"c5a7ea1eceda5e360675bf97276c4917f34102260d841e129022210d2ec1179b1363db5609e74b3f8e0d13a31b","nonce":"d12236568b4bef52ee4a523f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"f9e3a5ff8a5197f4b30374a8f142a9a0be210d7f5933c58e66577f2bf717c0c12bbd41389e4274c864684619b4","nonce":"d12236568b4bef52ee4a523e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"407d4cf30e16ced7b01a7370d75bccbb9334b5cac398208d332c8bdc4037df3245a5f03d7fcdc6212789f3f64b","nonce":"d12236568b4bef52ee4a523d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"3253f2b8a187dd1c8b7ea37a738117115677388e056507a94202177396f926620fbd48de338d0f36a8fdc99760","nonce":"d12236568b4bef52ee4a523c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"495849d8ec4ba77b365a1bf2137991affef9f4570d75197ea9dff842aafef2799d3b0248165400cd6b2cb5780e","nonce":"d12236568b4bef52ee4a5233","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"801a2b93bd14d550bd0a2e53fdaf7f99edf65af6a51a1f2e525e2c5c5c99d43b3e0b53381ba8b9e93cb5c51244","nonce":"d12236568b4bef52ee4a5232","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"ec9be8918f2fe0e4647e4936db296e55e635d836474544203afbd0ff7ecdf6f4dddd76860b85bd95d2cbde6b77","nonce":"d12236568b4bef52ee4a5231","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"861f884fc3e81d6fea4a13ae6da2420bb5d4bc56b64c7503318949aeaa9ff9033ce6b207d6f8c87edde4345d9c","nonce":"d12236568b4bef52ee4a5230","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"13cef437846fe1518fc522aa73a35d596704b1d9c2e826d28050762d4f8999bee18f8c0551d88fa39d9ea04ed4","nonce":"d12236568b4bef52ee4a5237","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"941bba0e039db2a86484b51dbdc2268a3023ea5092622ed85f58a2aecee5c092980e78f21789667a08e41acd17","nonce":"d12236568b4bef52ee4a5236","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"b26dc6ead53ccaf98c0efe355f6f4de1f7619eea2ee26050fd18fdabecc5bd621413b44a7e276ea60488e5616d","nonce":"d12236568b4bef52ee4a5235","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"365c78f97af72684d3ec5cd4017769abdb8779c07069b320ae035d6f8bd4928fd712f19e04c42d8bb1b0a93a5c","nonce":"d12236568b4bef52ee4a5234","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"0d82bec446b4268f08a4f4c28808116a12282c7fd464ca0c5d83a5c76bde465c65d0f688770b3601b8f0fb4192","nonce":"d12236568b4bef52ee4a522b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"ab7c33cb28b6ce2ecadb60dd196d592d52f984bee0f094bf3df8da4e43b6ab38a0d3f723f0b9373ad3442dc7e8","nonce":"d12236568b4bef52ee4a522a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"7b20b3c26f4a8b7dd1cb0ba3e944dcab2110a550fbf2e301157e2cd4b4f330b1fdd4d0cc24c611e890fe69b910","nonce":"d12236568b4bef52ee4a5229","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"09357b47161b4cd93a763a35e1c6af63ccc412f50c65e01c92b3748712e4acc8003fa9a6f26487153283189957","nonce":"d12236568b4bef52ee4a5228","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"35c75a0183804bddcc8d39af002d76ef9d750dce13a3c06745be2c3e7a1791f7b0cb25d380da66f8ae7cbb6404","nonce":"d12236568b4bef52ee4a522f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"9e16b7d6b44a2ba3174d2364bb78dd5782b90a1271dce3d93ab5b2d67e321eed1ab505f436c0989917db853673","nonce":"d12236568b4bef52ee4a522e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"74e40c605a68061c0590802dfc5cd24357d4a7387ddb423566fe976e5b6d014c1f5bd21242f0857b93aadaba02","nonce":"d12236568b4bef52ee4a522d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"bd6399f0ce4a11f6ce1fb6f8e1888e2552c7cfd9aae7af364be29f634225dcf79bcd0cf47f421d89063eb8148d","nonce":"d12236568b4bef52ee4a522c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"80434b8e08d9709ac6e78ad16a303a027e1e4c740e8bbaebe3aa1b9983ce50a5e237485936f528434fcf8f789f","nonce":"d12236568b4bef52ee4a5223","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"4b6df6b8c5a9d6885de1d90639e45b8391b3a117ae4962d174b2848efafd4bef764664625363a1decc9ebb1917","nonce":"d12236568b4bef52ee4a5222","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"cd3fc8ca84667aa2fa04cd9e32fba302182a4c29d89486a3bc0de84d82fb815342e7913466149390d7d7a3f322","nonce":"d12236568b4bef52ee4a5221","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"d062225e855e8085a95bc9ab696f4a9d0c55e75e18a0707e99e7294b31e061411e5e8f93982cf4db25a3a20813","nonce":"d12236568b4bef52ee4a5220","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"12979c2677a882d8b3e193b755da13c57cc3c71a7e899e5c7412e49f6900f18934078a544e549df29fc536fb5e","nonce":"d12236568b4bef52ee4a5227","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"77fb87085dc68c2fbc6ccb3b9972206e706aece29c391967cdf2f43297ee79deb99f3ab3d3cc14e7c585b5aa64","nonce":"d12236568b4bef52ee4a5226","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"23a603d6e97b05cf5d0b6045e313bf082588bff17d1b51b5dd066bd40d8685863c148a3468550bf907e0f8fa6a","nonce":"d12236568b4bef52ee4a5225","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"87581ecbc899e96a4878798bd4ad9d7f8f1dc5238f1592bd6e0094fa54b946e1961720aebed51177113516a26d","nonce":"d12236568b4bef52ee4a5224","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"9cccfc5fbfc22dc7984c2f7b93c36cbcc26d51794d91528826f4fd3ad47d6f26eb986e4c7f010f782b0210cd7f","nonce":"d12236568b4bef52ee4a52db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"ddfc9e2575902bb127d54826387bca85dc91773c92724614215128d796739a15795c6379ac9fcac714826ad5e5","nonce":"d12236568b4bef52ee4a52da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"1e5a7015903d746d9e40d6e0683ad38f8184028bb3bd1a74f2443ec4fcd3475835046f2923c6e1cdf013722eb3","nonce":"d12236568b4bef52ee4a52d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"b5a94012f4c14a9a640b2162752eeb0604757c7d99c7f578d7a2a5d5e72674e1e43b72d080ba2f8789d0bb5e92","nonce":"d12236568b4bef52ee4a52d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"d63dc365e6378594155053d25a967d8015fbca5cea2887b79e61be4311296211ce657e0ed8c3e22be6d1c5d870","nonce":"d12236568b4bef52ee4a52df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"155c536049c9c3d61db0373751f276a5d7d8cc6f1cd5f735cf8db54ee95c4079461eff0168614a30250ab76d83","nonce":"d12236568b4bef52ee4a52de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"77f0f0f95779a379bb8f2ce8421a529196af74cc7c889bec8483db6eedb7e78c7bfd5e50dadfb634aadb153c74","nonce":"d12236568b4bef52ee4a52dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"1c09f96a6af356041b476fa05f99c45dd0ee2c57100677b23d4eb30987972233dfb37892135d1a2148e8fb1ea1","nonce":"d12236568b4bef52ee4a52dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"1896f6747edb4710f98b4ac724c15b4192c7dee95d90b4f14982c6cb0ca41b1f80f47bad2bc385852fb73465e0","nonce":"d12236568b4bef52ee4a52d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"287f755a0f5643bd8e388c36372377ce93dca790a1cdc1364a8fc2812fdf5186155d2c29574fe02f2bc63e0ebf","nonce":"d12236568b4bef52ee4a52d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"fd80604c0aa4d8ef16e0640e2ec717f0af9e927a825082992b7f43d3f1731046153cc0aedb80d37273465f9d5d","nonce":"d12236568b4bef52ee4a52d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"77c146ccdfd8af9545a9458ca267efd1463ad67706fc0faffb0facacae5e5a05dc9cac3c253b93aec8ab303032","nonce":"d12236568b4bef52ee4a52d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"da8697af5e5295d39d724783095103f74c54e6ad389ab8aac15ce8d76aa4f5bec579542256ede5b7c480213d10","nonce":"d12236568b4bef52ee4a52d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"7c9988ce0d730eff9a4ddd87a90a1570072eb5a1020fc1b607cd5e66dd8b1b4a279c67ca800c98d2bd359e81b7","nonce":"d12236568b4bef52ee4a52d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"aa480dbfa8324a7408f3e6fb9c31b1b4549b172cc0cf5ca04f57a937b10c34ae1fab41aa219fde4192d0c2f454","nonce":"d12236568b4bef52ee4a52d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"c69ea6d80f1d316c7b6fcff2cc1827a2fc4a4dd5ad6516b7b544ba7185fa000f8f81ebeed49ecc8ca62b024973","nonce":"d12236568b4bef52ee4a52d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"fad8792cc26d9dae055d95351d965a409c2a453407aa8a770d7bfedb7dd022c4799678c72aa753fb0277142af8","nonce":"d12236568b4bef52ee4a52cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"682f98eb4a990055675ac40792cbf8f43ca2df5bfe89d87be23f71b84b9239a2db107f38b8ec5c31dacef525a9","nonce":"d12236568b4bef52ee4a52ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"7bdb7af890c6ae61b6e6e64a1ee503a5287c77a7fda2e824c1a6810d8f03a7adc0d841fa03da974cc70a9a90d2","nonce":"d12236568b4bef52ee4a52c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"d870c9f77da2ee5b6efe439e096d873dfec85c06db7b8e3a3f696279984285d6e8fe44eb4bce416ce46a420ee1","nonce":"d12236568b4bef52ee4a52c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"8b5162d7f260726834c48eff9b200a3688bbd934b47ad334d6abfe23b9daa11968e20a416491a6d7c6e0258197","nonce":"d12236568b4bef52ee4a52cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"a10278a9e6ce244e630d553be3aef3bcca7fb9a9d5ecb4ca0a613f36179356108b4c604d4b6072c1c441f06017","nonce":"d12236568b4bef52ee4a52ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"81de73e3d7f1d863bc7599163031110562f65d9a4dde53f2c1b9d8216b782f2be8ba2580d720318ab3cade4602","nonce":"d12236568b4bef52ee4a52cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"7dbec0dcc6b6b9698ee5879653257eadb3379e14c8f82debc17f3fb5c41456b3ea9e59b9969868c3888892b363","nonce":"d12236568b4bef52ee4a52cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"27199618715dd05cff0c7d5da35f232593eea6fb31821c90d700bf990007045843fed866476d91a83ddbfe359f","nonce":"d12236568b4bef52ee4a52c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"1e0ef15a13fce55489e41b2b178c22cddc53be2e81c8f48d38fb46aec0c0231c73939b982dcd3b603b598096cd","nonce":"d12236568b4bef52ee4a52c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"f4fc273731fedc04d03047a24b50c93a75711b87270be8db7e58388fc9df7e5cb58a7b75bacf43ca0a80f07137","nonce":"d12236568b4bef52ee4a52c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"1e5ac22f787729858b4b2dadcf9655bda34bcf185773f2e57345597356b84f6c56036fe83ee51007bf002ee5d3","nonce":"d12236568b4bef52ee4a52c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"f69db8df8a6697253978671910b94576cf824621fbd66a62c8435cea091344a7be6a5563f3106fc2fab4d73505","nonce":"d12236568b4bef52ee4a52c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"953dae629080a8fc8cc041bf5d2271f04d8d4807dae224fd339087860dac8a7f0d41d60cd04d5e04de6ab8965c","nonce":"d12236568b4bef52ee4a52c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"8c3c41d62eb0918d5a5ae63ae5d581e6e40029bf2cab76ecbe42a7fb4221830de23e638cd8572bc7f3182b6faf","nonce":"d12236568b4bef52ee4a52c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"47124b91c4b0bf532b5b05ae7ebf833cd3b23ccec01dc4944f29c0e53bff4aaae9c72d0feaff2a2e9078e5d3c9","nonce":"d12236568b4bef52ee4a52c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"55c042e912b48a7b2936e9824dfefd6a05cf8b4ef0a5cadeffefcc30b7183961a8296f30e580abaa10cb4e0b1b","nonce":"d12236568b4bef52ee4a52fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"64078fd781906b7dbaf7bdd27cc100434274a99fa11527c66259376499743e25ed756b402392877f0a838d06e2","nonce":"d12236568b4bef52ee4a52fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"be571c4b210f0f594d50c1028ca1197fa72ff9891e4c99f2d44897f69f213b7999adb0459d736ba5f63bc5198b","nonce":"d12236568b4bef52ee4a52f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"7cda16adee3e6af2dd1e3aa8fec91fea672e94360bc2037711dca19cb756a2f96dd9d0994a3e18bb606ff2b4a7","nonce":"d12236568b4bef52ee4a52f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"e020b95cd8697056e995a7f8203a4ff95bf76dbbe87af45cfc6ca6e16762082f029bf32e3560f7dc953f3e0c4b","nonce":"d12236568b4bef52ee4a52ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"3722a49241f79d0f5d34f92a3bbfd6683096b5c0fc48ab7263e5becd3bbcaeb77df3c6a076c1836f8de6fc10ef","nonce":"d12236568b4bef52ee4a52fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"7458418c6db18264a78209760076aad3e1785317769e61e84e8146de31b68c804e56db09d75c5bbf8b840f1b24","nonce":"d12236568b4bef52ee4a52fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"ea9de673fbd678cacd6b538c3d1a89b0cc1a65eb9932871129981b27e315854bb38b3d3e297487065b6d93ecd5","nonce":"d12236568b4bef52ee4a52fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"b8777fca400542e740ee3db8f0356d8885faa6c79f96b0cf14c32557edfb13d9c95841145ec95a2953c9d38c27","nonce":"d12236568b4bef52ee4a52f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"df3d456b1ed4222d6e1b40f87c919108c2f53cad89c460c744f0061d5e6195cc42372d6240fef8996a580a8a32","nonce":"d12236568b4bef52ee4a52f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"2391bbd54a5b3c620eaf3d457536efea5c5e9f34615bd74ad0c04632625afd75846ffe4e2a8dc0eb65f40610f2","nonce":"d12236568b4bef52ee4a52f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"df51a9069f67f8b1172c300b7ffcad4b818f1f3dcc4d1e13c494bda65640a380413344ebf6de15679bb4bd755a","nonce":"d12236568b4bef52ee4a52f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"3e2a85c0497a8f9e8b50cf18d59a5f4eea5cdac1904161839adb3e452a8f04ede94e290dcc875bef8d82d0801a","nonce":"d12236568b4bef52ee4a52f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"88d704203a4407fab20809baa9f0d5e1a267cc1ef30858ba3c1d7d66edc2ecd4919faa8d5c59de9bc2269dc98b","nonce":"d12236568b4bef52ee4a52f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"b9f60161976819e0d488ca7a6dcd5f6e22fab1497eecc4343b12a881a6c37f6f216ec4d7d1e3939a67d01774a9","nonce":"d12236568b4bef52ee4a52f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"79d26e9c1185246cf2f0aed77d28ee11ea5e611e2b814022dc7bbb807f3d4394ed8e6feed62f122d3cc06637c8","nonce":"d12236568b4bef52ee4a52f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"845b803a017206ffe3f9bad218bd691f87b82fd114cd75998fd6bf1c3cd97b82ad021dbec76dd6a6db177e9706","nonce":"d12236568b4bef52ee4a52eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"eb943528fecd86ad56f82c3b2e7e1384de77c94228c79353651175ad081c1f5e10102586ef62e478b2440c91de","nonce":"d12236568b4bef52ee4a52ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"2fe3a33c6bc41e3119269cbf1a2ef232ea7eb16429044e7cdca1bbdd60b2ed58ec69f3ea5405f569a4109499a4","nonce":"d12236568b4bef52ee4a52e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"245dbd7bc7cc56fcbd63e54e12417f3ae788b2e6a0efdac0ad986d560ea61357aae93dae9e97341ec9bb2fc6cc","nonce":"d12236568b4bef52ee4a52e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"79e7746452500587fd97545af2689c3ac116d2c78cc8fd98a856ca677bca8c5def7b63f99970f3d6be35d3c17e","nonce":"d12236568b4bef52ee4a52ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"30a35ee8b0464d7b46c1acaaba5397bdc607878313648ec7357bddba673a6d0f0cf9af706af3df9c3865c299bb","nonce":"d12236568b4bef52ee4a52ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"5a38de165852dd5fd7cac756cbc068cf72af08865fe2bbb76617a3ca1251dfcdbbd4f88b1012f317d7b7a5f499","nonce":"d12236568b4bef52ee4a52ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"7ad16b75f3668a162ab627ca74f6971f061830ec3a4e01a9202b105d7706e68132279e0f654f866573e2e97a01","nonce":"d12236568b4bef52ee4a52ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"186f7a51651ddbd8a4c51fd4ad4d7fe02847072999a0a297fc371e46b0ac6e460560691b76b7511eab0ff5826a","nonce":"d12236568b4bef52ee4a52e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"b87014a2f2fced3590aa1878c8acc246ceda86a06123ad9f59d19d0a9e39c7d424262bd58c7f8d5b93f0693387","nonce":"d12236568b4bef52ee4a52e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"8fef6f2b939620df9f6a13a76b733a7f65b8b26c67c46bea5d38ea3f7a873dc429ef32e999d16006715f9b6cc6","nonce":"d12236568b4bef52ee4a52e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"df7fdf05743fc657e2d0337357ae2c8936409d4c925a363c4dfe9041eaafd39d541de8bfde771ef22c503595a0","nonce":"d12236568b4bef52ee4a52e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"f363b6d56866b286e8c02975648d4f95b67a299bf9a6527bf342dadf3db52cc025da37b7a96d2f78125fa55abf","nonce":"d12236568b4bef52ee4a52e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"2d0db57e455845d66a420be01790a2398df5a0b03be5437150d7a629d6abfff8568bb85fb7baf542458f7739ce","nonce":"d12236568b4bef52ee4a52e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"f91d13822f9e1ecb55646d4e4e966ca790363cae6c246c5565e90a8b2a45376b3aaf452f8c5013042044996283","nonce":"d12236568b4bef52ee4a52e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"233d23a40cd25134e6eef6b2f4bf6631698f522e559ff71cc2e374cf84e81590b31c67e87401bec3f4248b6282","nonce":"d12236568b4bef52ee4a52e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"71803b609bdfd6ab794f1202539f287cc742ba9f0961236acffba1d007404058b7338442c7b875e03b62f3b23a","nonce":"d12236568b4bef52ee4a529b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"7210ed2f3f7961fb7ba510dd9c9fdddc2df513cd8fbcc691492ff0b39b3f0b46edab5676ed58a85a0d3ff36d7f","nonce":"d12236568b4bef52ee4a529a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"9cfd4e51c4832dac6cdd7f83f972ec45773e0eb6113486d8740f14158f6f9e9b313a8a3197bf8f689b265ccb60","nonce":"d12236568b4bef52ee4a5299","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"d86e88ac96dd584fa8d23fb2830bdb09c366b2ac329b59d32d5e83129b2690129c7d7d1e278ebd1a43ff2ef6b8","nonce":"d12236568b4bef52ee4a5298","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"fb256cb2f2cbc652b908bb77aff8a8e09085ab7a55c8acd2d781810ff2336f34c5c8dd8c9f9b58510f0ba3c74f","nonce":"d12236568b4bef52ee4a529f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"ab58227c48a809ae26863cf3698de73b21074824c4ba2e1a2dbef600c854b20c422c87cd2ac74312f4b943249d","nonce":"d12236568b4bef52ee4a529e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"37304209f82d163318681aa57f1e32cc8e60c522d65b76bb39a64cb4fe127fd58c60e8f23b6824c6135597c1e8","nonce":"d12236568b4bef52ee4a529d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"19b2b717a18ff93660d9d9911316d17692742e5d328a1cfdd56a306c539e421a2cb2a9a6d698a7e08952419f11","nonce":"d12236568b4bef52ee4a529c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"e96944883d091f1c23cb7560b62b6a86500cd502d952a973b78977b149dcc70fe363afb060605276815804e51f","nonce":"d12236568b4bef52ee4a5293","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"38daca56384c32848a98b080a28ff41b8486125db8d0a5c266acdbabd6bdf7bc5baa94ce8848b1b436fcc5aa9c","nonce":"d12236568b4bef52ee4a5292","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"1faaab8f0ccead14c2b21d049a2fdf583874e520fe10948eacc33f7191a518611e2e58b68c8be59f25748f5c8c","nonce":"d12236568b4bef52ee4a5291","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"1fd1736c8447a89816f4ce8bf98e525e302814fddd3fb12b03ebecde8ac53d192eab86a9f9f2b5dfdbbbe27bc1","nonce":"d12236568b4bef52ee4a5290","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"f377ffc1514ff88fe0b790ddefe351e83608eb4b68236265d4a6258e7c8b033ac0017d6a61313567d3277db5c7","nonce":"d12236568b4bef52ee4a5297","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"82244110d1693a6a497dc54049f55bec1a188d3e7a5a5c54e3fc6136d2903fab2410c225e8318e9142f64edf2a","nonce":"d12236568b4bef52ee4a5296","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"c2fd3d16db419a7e5dc2768b31ac28666c44e9ef953dda1a9bff3eb78a428fd41ddc3410682793d7bf7deb613f","nonce":"d12236568b4bef52ee4a5295","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"9e9e81ed064e43aeb3f863605d889ba72bf93e0102630e0543592d1fc3d719ae0c2b74e8f1466172be7ce9eef9","nonce":"d12236568b4bef52ee4a5294","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"4b173f1ba546b701f64f0ab2cba24645ca8b11a0ecf15f8421b6c49116dcaa008673f1b7539d3c1ae357507d01","nonce":"d12236568b4bef52ee4a528b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"5b6d32be6b256d655562e8f8a921761417ee53e3ad1386342e2b04b997238ff7c61339029661650ae65ab3bdae","nonce":"d12236568b4bef52ee4a528a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"7d1c8ed65e7e705d87b039da0e534a914597866844054c4ea8fd61139b1b71263398087ab475769bc5d37915f7","nonce":"d12236568b4bef52ee4a5289","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"f314f9342c83a7b7fd8dc7398891b1aff33d2c6b6cfc04d9c362b7ed2ef6362f861c15a6de32d3bb83626282c8","nonce":"d12236568b4bef52ee4a5288","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"a3e9d00279ed6ac6e773a30109d4650160acc2f2219b840169c46ffd4800b3a0c0aa667bf0111e5a42eff14ed8","nonce":"d12236568b4bef52ee4a528f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"8a4910d45c27d712972b6a92ebcac7c5f985e23057958e8c7374b4c7e4ee1108f9c2049d95cbd9996f26ec7afe","nonce":"d12236568b4bef52ee4a528e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"18d3aaa168cbdee5953c8b56f02d604c88cfe11abe7b8a9de500782f2b8ba4a19ec43202435f939d66715ded95","nonce":"d12236568b4bef52ee4a528d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"fa711fad515bdbc31965adc0360fc891029fcf2bd2673ac862ad6bad030f709c0d79ae93cfd5dc3b6db15d3c4c","nonce":"d12236568b4bef52ee4a528c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"ca62380fd6d72ceb0574b277e3055a0c59a2cfb19f2272eb402855182b7f1341361c97d907471edc5956360312","nonce":"d12236568b4bef52ee4a5283","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"620c94bf5eff69d863780aa5a1713cc43be69aba2e6c935cb006fa1f9b5657aebdc9db60d69167412d0eb8a644","nonce":"d12236568b4bef52ee4a5282","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"cf0438645af9d5dff7b34c7c100b66d319336bd1acf76dcd75e2a10749e39f3144c9980b5b79ad2efd490955b2","nonce":"d12236568b4bef52ee4a5281","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"bb331b3ad4729ba0c3fe3a407950ad14244e2fd22fef0c4be659234cde18eba18c88dc5448560a1eb0adfccce2","nonce":"d12236568b4bef52ee4a5280","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"fc95836547b804b97b6335de712a3cab7d0ab691af7c19e5441e3e1b234f529518a47ce2324438a26d4d89e5f3","nonce":"d12236568b4bef52ee4a5287","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"e5b6bb5beddf4e9bd5ec15a49d77ca240747e18dc6df6cedf8ca106f787e6c9fa5256dac1f0b153c4a20273e10","nonce":"d12236568b4bef52ee4a5286","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"6a31a8ce5bc9979f77fd76fe468af540dd08a1fc3cc7b155064caa4783285a778e7204eac3232e181eb47fd0c4","nonce":"d12236568b4bef52ee4a5285","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"df3a82223fa9d66f59ea88507860e62e0eebecc01a43f3c1a15f2c468400f37bbf65dcd5c9329ae45b937cbf8d","nonce":"d12236568b4bef52ee4a5284","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"3c7ede90d85702833918eb71314113b80892acb6d1b4e93ac15cde493411afa22ffb97d8222b49bf943d0cfc23","nonce":"d12236568b4bef52ee4a52bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"24a43113f14b6975d252a6eb767d191a00905bf0436e13380bbdb3d82250b45061975a4c3ecefb1b1591389477","nonce":"d12236568b4bef52ee4a52ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"48fe9a2e20b1cd7b40258ac32f090b9c35e548ea796282203200b81fd92cdbb379ee66ec0a36c4174b457da8cd","nonce":"d12236568b4bef52ee4a52b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"c1b1159f5510cbb113d9b6a90743b6a18e9a1582f2b684cb1b068a85b063ed3dae79fc8287d6e69b754fbea1b1","nonce":"d12236568b4bef52ee4a52b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"f0137a67d2419aef73b80506c450379aa23510bcd0df5ff4fb75cd795dfd547d8115e90ee43f08267ae4f5b36a","nonce":"d12236568b4bef52ee4a52bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"edfa348487756b01f103686d48863fee608413f6045b66882483600cbff64e38e6363a131baaea73f4e23bd8e6","nonce":"d12236568b4bef52ee4a52be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"ca9e65e56d90201f1fadc6e1006be031dfbac4a0877db98cadc7025041d7f8e82feac715809a28a5c53f56ee4a","nonce":"d12236568b4bef52ee4a52bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"906b85b25c107eac9b25cee00725a12c60d7ce0105af249aa3a1ab9c129eeac0429f4ddc033bdc68c868c57c68","nonce":"d12236568b4bef52ee4a52bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"358fa560a12d6260249059b64153782abfed9c3cfd21cb03bf97ee19bb987e2966613d7bf097f649b92e64a815","nonce":"d12236568b4bef52ee4a52b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"18c1c9800974362c2575cdfc504247a19fc0ecc19f087c77e837688fd64df1211f7f3b0156c6fd9436f3704798","nonce":"d12236568b4bef52ee4a52b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"d8366c5e5f273707202d2354ef8cea1a4ea5002a609c3db699905e374412b2d7d7098c9b77b7c8169b035d3419","nonce":"d12236568b4bef52ee4a52b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"36e25781536e4a77eaad9613648b8b18a62922f4afb80b76804d73ef2978293c031f1f36d2ccb8ab581655d8b6","nonce":"d12236568b4bef52ee4a52b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"33fa2840815008608d8be0d39f3c5351d438864a7146874ab2d54776025df1f81af89a0e815485a7c891988e99","nonce":"d12236568b4bef52ee4a52b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"130bd04670aa0811c31a54738c3cbee7879f53e47243b4b0814f8d156e784b1c04df31bc9bec49dde7cbaad9e4","nonce":"d12236568b4bef52ee4a52b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"24b85da76c6d22091e82de4545ba63a44679daade871323d98295fab13de38fbc31c88207357fb46a5f4bab428","nonce":"d12236568b4bef52ee4a52b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"ef2d993f821fcec3d2c65641751cae232ac739962252904b42bf865093182fe2a024133f8dc404b391d1341f13","nonce":"d12236568b4bef52ee4a52b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"299c7a3d62ffa34f3d20866d113733d653f90a522e0d24bc459526d4fcab4a4e5662b922db252442dc59e485cf","nonce":"d12236568b4bef52ee4a52ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"5cb5d54dca8761d8a96b3ef172ef82127245ae3a4c86648cb60723474efbb0f0ff63e00d2f2a27c7434faff6b6","nonce":"d12236568b4bef52ee4a52aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"23517a0291f7d1ec7e495f7acc309373ddf03461cb62ef334b8a47373ef8b332278cb610cc8384db1b4a41b77e","nonce":"d12236568b4bef52ee4a52a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"e47f0c711de0b93efafc4b22717c775e3d1268833192e9613a1212ccbc86cc9229d47d9209a80ea8222c8c28da","nonce":"d12236568b4bef52ee4a52a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"a967e046a3c9bcb8cf071a43cc8d10cd2fecba4d71edb3eed935219bc293ba63a5cba053ecee49c9989a0121e8","nonce":"d12236568b4bef52ee4a52af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"229a0acfdefdd9ee54f5552e8cf5edd987ca70f3c79dd4b102c18493f174e6eae2dec76002bdb3187bf6c9d211","nonce":"d12236568b4bef52ee4a52ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"c3ff9fa1a0dfa63c6e02552bea5c2f06a6f3268a3d453853ac92fc9941e24a14d6a301f748318316f689edfd6b","nonce":"d12236568b4bef52ee4a52ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"0b8be5a7f9dbd462c1fd694dbf67c9298a304e66c47fdd8a04038d38463f67fdd9af6dbb380cbf366b392cc674","nonce":"d12236568b4bef52ee4a52ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"078c6610c1ed470249722a28b3b56a3cb633550cff009490ad33977eaafe647473ccaf33c7f8ab33b0517cded3","nonce":"d12236568b4bef52ee4a52a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"c73c584673badefa1fef3a0ff249fc8f63d84922efad994468a0a9b7102c36c1ceca494d858da9fc61ac4bf797","nonce":"d12236568b4bef52ee4a52a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"49d18c35ee0fe8bf6668eaea632c2bb820196ffacbe513229ee82f847b25cd35d1aeeddb3bb2ee39a78eb26f23","nonce":"d12236568b4bef52ee4a52a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"cd3665a1e550639d4463ab9704c9da9d28a6dbf435532915763611b2ea2ab6206d30351f1423f659f10d538a9c","nonce":"d12236568b4bef52ee4a52a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"5bfccba5353cc5884476c1f0ab19f470db0ae246f666b54488871acd1b466fbd2d7decc04f7ed4198fe6424f02","nonce":"d12236568b4bef52ee4a52a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"39c122008e0c223b40f167e2843178f062e8a5043a73f13dfad54cd714f31fdc3589d43a5a6e4384628bf276ce","nonce":"d12236568b4bef52ee4a52a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"01aa14b20b4c6698cc9f4f5c3189652f05c6eaeaa3004c716e6ae66b0426eb3d22414f1dca90b1dc299af47666","nonce":"d12236568b4bef52ee4a52a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"2412e065c667a75a1eb0a6663a8097a74ba9abfbf57a047b38d6a045b84dee333a602b7d05b554a994c237257f","nonce":"d12236568b4bef52ee4a52a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"4feef8b08c597bba951c2645da8cc07321b2f85f4d94e2f42f91851b704ef12132504ed8387d5282a66fe93e24","nonce":"d12236568b4bef52ee4a535b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"2089a7a538fe492cae78f7c93038e3bf9ef741ffb560c080aad4e50eb1213dbd"},{"exporter_context":"00","L":32,"exported_value":"87c240e67d906ce285f71a3f4838df2ae2049b018355049e797470446607dace"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"83d5fac9416590c80b882d9b139f064ec06453c2e962f44240bb92f0727f3583"}]},{"mode":3,"kem_id":33,"kdf_id":3,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"0c6d6a83151013fa800d6ed94c7a7b7e4d4e562f9517131a5257e4d20ebbe7ba9faad59ad49ec9a2a922cb70252db2c168c89ba303d96e07","ikmS":"9b34392ca511fa70eb6a77a0f1e6b121266e185d92bc28936695488a96aad5a79090df7ff9b32af0e7acb54f1720f306c366c521eeac26e4","ikmE":"41fb9334d1ac715b3bae6e858c46e317d4c64fa01e5db5d675283e997b61869777a8191f3dbf21d5a947e471b92b85f1b138aeec5ec4a0a5","skRm":"7b937b3e2d1ed86f46439a2ceab55ed69fe60a63a0b6b73c2ce3c117f218d05c9ee1521fe87f9830dda6fbc9bc3235b269a886226c8feb81","skSm":"998fa176b9657f4681f09c8366c6ed568ea51b3fdf127f8facb4a2f6f83eec91f4f20c50090cb868e82fb1bcb0d78960da77989d063b525d","skEm":"cda2f455110d47fb6a2f5f0f0b3a290eb169cf7e04fcf6dcf567534a1f6d5aea2b9b9e6bc463e7aba34aeec2b2b9e289c50c9f1f5c1d57c3","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"02bb597633b26a8d1c942a39201be275abdc8734524a73adee4b0cb42f802a38578ee6974a0dfeb68d2e31af648f5512e65b7d58f5bb7026","pkSm":"146ea687241e4f9d33a36fd0d482f6d0c698a895f47adfa0d736a536edfec5ee828f68fe0f2e4ddd0c7cdf2d88d2946689f78d0ed2dc0f49","pkEm":"d40b942d7612b9300d4652c02940b5657b4d5212e8f0648362b368e7a131c4bc592ded86f24b032b5e45edb2f05fc19d835c23c088f55999","enc":"d40b942d7612b9300d4652c02940b5657b4d5212e8f0648362b368e7a131c4bc592ded86f24b032b5e45edb2f05fc19d835c23c088f55999","shared_secret":"5dc9bc8036e1f165e2a6be681870b96c61d8aff7c4d7c1a31ad4eaa4ee923689e24c41b7609f92b1799d806f46fadc2a2bd6f815feb89442d769f8e287c9c00b","key_schedule_context":"03b6f77772f75e969afc66fe6df70331fdabcbfa9c5fc9108db02ec7e8ae117f5b28f74e569a9bf3df79c9e5507a5441d7483b9da3d3394b3f168e40554f530893574a72814c5d8e45c985c4252e66abdfe846113c17cdd7485893b89e0d5cb23d409145ac095bcceb628874b68378897f77c36eaaf45dc932c30eb5841015517b","secret":"13e340d5290c4683c0c64743314dd3682f4f5504fbd2b062c0dbe55e176ea2570eabb8f18433052ebd64a595da21b0362faeb3c0baaa29959106736b71a1e96c","key":"cb1f1f742781f3bc1c4e9bf05eafd751","base_nonce":"521517393173b74bf57f3b49","exporter_secret":"d4b808146d25cb1dd585ce4e895833d233c9e92142706f4ff93913819f9e4b25042b610a560aa572aacecce6c598394dc6e928cc2565e89b0906517c13b9f073","encryptions":[{"aad":"436f756e742d30","ciphertext":"8cc9348cd4dc480365c9be49d466d437e0f50b5cf7d7d9392e551e4dd82e85f222544182ebf6b53091f2a8016e","nonce":"521517393173b74bf57f3b49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"fed416e3a5040c0d251bc2acbe987b6c99034446f3e8cb77d3765319bcf42a9bcc23861fc936f9ac506e790ec1","nonce":"521517393173b74bf57f3b48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"55bad04e067b0b61daa6654abd7d0e70a4b9c02f41f69642659802ad3d5f0c438ab435e9dae47b31bcbba61e2f","nonce":"521517393173b74bf57f3b4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"aba34fcfb657b88b7de5f4f520571c4bfac1496f5d4c48028decb5a9697c2822e8b9111255e2142e1b80fd6eff","nonce":"521517393173b74bf57f3b4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"411b9624935ccaae95e2b52ab337dd8e7fdd43f68fa07167dafa0373e567a8d7f86e90e8123827c340a3b74295","nonce":"521517393173b74bf57f3b4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"6cfe737d53048c9de9312e9bc39dc24577b33c1d5cad5c1f42c9420f8efcdc29c893b5967b20af393bb4a9165c","nonce":"521517393173b74bf57f3b4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"c4c9fdead7287f296e69d99c7c84b417bf38ca0d319da44669b808d274ec2d7cf6f7030a4d9eeb9a8544f9969f","nonce":"521517393173b74bf57f3b4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"926a4405f354ee187730b45a775a2db3479842698857fe1420acd217e9c33167ffaa8d647321623f6bb7c29319","nonce":"521517393173b74bf57f3b4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"3fc86702c344372dfb09837764e094c383968fc3ba71b4ed1842f86a2f070089d2d1156337790be893a57734fa","nonce":"521517393173b74bf57f3b41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"ef45c3dd55b82e1eef5a3756786872a22cef0b40f8ae36cedd273d2976c3a2ecd75b8621be72230f21e0eb6784","nonce":"521517393173b74bf57f3b40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"a77c7cc0a5eef7205964552d121700462a3f5a034bd46be36895c9f21df499bf0bb466931159214ff439f7dd0d","nonce":"521517393173b74bf57f3b43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"7873c6de0871faeeab5ad19774f3b43eda3486c58604948789075d83f324a11c90f71cbead810f66b97610edf6","nonce":"521517393173b74bf57f3b42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"49a5c6ffb30a41e297b09c7a47d753bdb79faed178d56cdfd0ba9bead2997e3e37bd48c15b2042dd05bddfa750","nonce":"521517393173b74bf57f3b45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"2c3f68020be1b3353b97848ba4a1b2ab0a855fabf3effe8af232265fc85917a1e09a248b279ad6d482d71a8f22","nonce":"521517393173b74bf57f3b44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"eb6134e466ef8f46f0fa45b3f7a18d1985b74d0a7f197fffc037d199cfc2ecb0cf67778748bdaa315b41daf083","nonce":"521517393173b74bf57f3b47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"ba3f272148f1769fc5d90ec13dfe7c3c9179f4755aff86e48502db2e1f0d6ac7d61c9b6c92c8bbdc80881ce258","nonce":"521517393173b74bf57f3b46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"78a2a117b16a7bd259191371a417739ba7b9c1157328fb66266506a4ee2d9dc8ce37bb753f6ec8dcfa2cb07469","nonce":"521517393173b74bf57f3b59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"3c7bced4708f288c74092f295c425ba7e04d5ed4146c28254a257b06e245695e9ea111b9ed9f8a6e5a3ec1caea","nonce":"521517393173b74bf57f3b58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"6556ffd88bc9ad90b7248fa6989d7a834b9d8a31eba5cb19eb8c2419fbc628c3f963f94d05c089fc1c242bf6be","nonce":"521517393173b74bf57f3b5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"c9f176229206f71ebb46d2c907768769072e8d1406f91b013b5d50dd2e207a5c71033d893f4763116a51a798d3","nonce":"521517393173b74bf57f3b5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"fbea6d563e27833bb5ac7963458962284a97fcaa5e7203265f21b4b729a7da452aa9d7188d1d22edf393877853","nonce":"521517393173b74bf57f3b5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"bf99c88fe92eb4c2a5218c0ddfddcad79c9568daea7f7d81968974fd033e3d04700c9a792c2124c4554828c2f6","nonce":"521517393173b74bf57f3b5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"3c907209f63ffba5ed5d33fa637b43acfc1b732405d826f832ecda2780147b9654382aa2617b7830f537cfb6f4","nonce":"521517393173b74bf57f3b5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"8d864d70fd90a6d4fd4766d6faa78df3ac968a598d170d3eda78587772014a148352e65b4b37e5e3e1c67542bd","nonce":"521517393173b74bf57f3b5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"b1f6ff05e350df0c96adcf4e28d31124a831918a34e6aec0532ccc4041303fbc195536bf2d98f2686e49f42e37","nonce":"521517393173b74bf57f3b51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"7d2ef9beff2219f255c49c558eb12ed7a5684af5af26e3b080a8e11941fb17ffab72ae556730fb8e1d2c2b65fb","nonce":"521517393173b74bf57f3b50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"c59f4306d9357691b71a3d7b98d164fd7666bfa9ef06c14c68d7d1d34c025cd353fc210ccee8ae4a0b065c6cec","nonce":"521517393173b74bf57f3b53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"d86c985d3f4a7ac5ae91738dc10e6ee89bbdae00f60f46613ffb3d467f2afbb11e773d8fe8c17071af5b13e1d8","nonce":"521517393173b74bf57f3b52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"39997be0c53a3c4b522e3408127040ae635883b842818220666e99c6c7122b30824e06805003a40addb4b4a7c1","nonce":"521517393173b74bf57f3b55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"294b85d40548443ab29792359d9254fc5c17d862279adfe01b96cdb2a44246e9219adc7a8105dc10220dcb7e31","nonce":"521517393173b74bf57f3b54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"1cbedb0e37379dc361f6688e2adf0ac88fad805e68d21ad7e227c07e771c76b1f8d94d322ff47d3122d9ee199d","nonce":"521517393173b74bf57f3b57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"34bd114ba4828e29b2a5ccabdd79fd34d8daa64b42462ff1ec1eb451dddbe25a736048156ca95a9bebf3f49bde","nonce":"521517393173b74bf57f3b56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"1ca61eab9068d9da370b895347f824910e9bdd5596ab84549a95696310fe16561c311d4c3002567a49fa9b6960","nonce":"521517393173b74bf57f3b69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"a810d6ec9abfd714f81ec7d5c6ee51710e07b7fce26ff05e596660066f3d1180f9450f83485a168d2473c6c536","nonce":"521517393173b74bf57f3b68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"d50f28a779ba7b59ed980ee2ad1ece55668d630d570ecdd76f5ac253083f851de89d5723ed2fd10511194e09c7","nonce":"521517393173b74bf57f3b6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"9a7bcf63461e27510d01ddd6a06a73a4cce0647812e495cdf084955853d8f12fb066f208f50c878b1fde148f80","nonce":"521517393173b74bf57f3b6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"59654b7464ad570e3939f96090e2fc737d2df9957cbda6e9195ae9860d1559acfe9a9330e3bc96023ebc572a60","nonce":"521517393173b74bf57f3b6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"9e339e497f0a77a10b8e4ca27ef29dcde792550891da78a66137a864a9b2960603663502807b81658bf26d009d","nonce":"521517393173b74bf57f3b6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"b460ec01d85d6b9338dc2dbeacfe092252ecc17fa9f76deccfc56e016a1f5c3dfd3b61befabb367ade0602fbb5","nonce":"521517393173b74bf57f3b6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"3de3d49d00430ffa17afb32e1c6ba742f228bc343fa84627de2012a499ee4a13a773528d1cf1353ac5d58dda43","nonce":"521517393173b74bf57f3b6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"950aa7328ec98bdae27cd827cae9c54920af065674925b36cc70064441e03885a598e5d4da534dd40f24c3e668","nonce":"521517393173b74bf57f3b61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"ca2caaf014b28c21cd16ebbbece1d4f621db0e033828b24c8462f58ce86d995c3c9254ba288a643997498b5954","nonce":"521517393173b74bf57f3b60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"fc896a52fc576a6f1431354550c93e4661b596a44512c77229fa4d8ec728120cfd9e9682b6a05287932bc50295","nonce":"521517393173b74bf57f3b63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"8fd6387d32742cd6f136174d9021af4a4b37bc38e9fc3a4c225921758145174e74cc01a29ebc33a57458c7d706","nonce":"521517393173b74bf57f3b62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"117d6f3e6dccba98e1f267a15129360913e0312b092e542c2f6c7d5ed7c11029db6053ce82d483fca911f7c8b2","nonce":"521517393173b74bf57f3b65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"90bf7caca2cdc9581e75812a9a47a6e264e3dcc5447c1c363613cab8392d4531d56bbf7cf11cd3aed966fa19bf","nonce":"521517393173b74bf57f3b64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"df8b20520a37058e8ae7c47d7909cb4d93bd4fb19d6b2931dfef0c94272a604de29aec5d23a0cf103d1c324a22","nonce":"521517393173b74bf57f3b67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"c6853ae747644097a3be4fe2076ebad8b31eec9cac096f800c678df6e82c86b796b269726fcfc8b3d82363d0c3","nonce":"521517393173b74bf57f3b66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"8ef7b27256e42e918feb8beaa9b76c13a3500849b6747915fca48b1137271c95432dc2ad346458c71c95324ac4","nonce":"521517393173b74bf57f3b79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"b0c984696f84395af7bb0e6ab0f476c9c0887b6cb6d5e013c76a06f00a1423bda484df5b7d9b2e64c5f38ff049","nonce":"521517393173b74bf57f3b78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"0b1fd4fc13db3cf115dacf371bab0c610d20a36ea993dfe2d7042b4ea3b3e9f0dde7ad7345329079c83858f151","nonce":"521517393173b74bf57f3b7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"05459e9d4c431207bfc18bfa5bb0f0dd8177d1a8eee8cc3415a73a0137ad5561154832b1da8ddb5841ce031f03","nonce":"521517393173b74bf57f3b7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"1b977b3b033d7b39219830d2b7c6601aaa3cf55ad3c08c889abb8b32a9f630555316477863973f7de9af916b16","nonce":"521517393173b74bf57f3b7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"7e0b1c9b5ce3f19d3282733f1afb79bf08efb0d76b5c50f79d51e31a3bf2aeedef4b07a0aa04ae90e11f56f0c6","nonce":"521517393173b74bf57f3b7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"a764be4d0f7ad99dea716e664618f708a85ce23b7e94f38a8e2c784e6d6b43f04fdc7840295cc7984d022ba9a3","nonce":"521517393173b74bf57f3b7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"457ab5cc3360635aec25f150471f12ac7ca5fd4d1781dd7383001e02dd3dd74ee3517f95e2b56642370dfd9bd4","nonce":"521517393173b74bf57f3b7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"7a24f0c609ac40af75ff8085c2d4e3b978ef4db420201bcb407a312f5a85f03af82c5b25ebe865b6432377d664","nonce":"521517393173b74bf57f3b71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"984f8712bc9de4f601f18609ffe41d6729d9111f336844dcb0e321380e3985153775d3fffa9bcd68fc676e3001","nonce":"521517393173b74bf57f3b70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"a622ecb427db6598f7b713925a10ba2b77cc0ef0c6845e8b31e1360f77bbfafb50cb9414b40ba98a791fae810d","nonce":"521517393173b74bf57f3b73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"7fac597589e2fa137f8636b2500df752f57acb10ca32c23b5010df44bf6300428bb0d7ce01a1ef05cbb0951033","nonce":"521517393173b74bf57f3b72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"1e5f159115050ac74f15e28ec566b22acbbda45f687d67784062ffd4461b9d1e0286e66ef854ff532be4c1390f","nonce":"521517393173b74bf57f3b75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"6b4235e97e2a9dc021992ef10c8a476144f6d039aefa8ef53147ff4457dfb78abb687be7223ce28575bcfc8d6d","nonce":"521517393173b74bf57f3b74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"2963bd2e0daa2bf6ba1dfed3d6c5991f66a5b6f46b53b452e91259a4899ab17083b641cc5611797fdd75e2362e","nonce":"521517393173b74bf57f3b77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"34b6967490ea98ee1ddd4dc44af59e4dfec933d9b5fb021bb205f38ea93eec43681679fdc905d90339386e7ebe","nonce":"521517393173b74bf57f3b76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"4b20845b42520ea8b918311bf7dffeba449dc94c91add120d37f6bce22c962a16ef7c41494b48897968210cec2","nonce":"521517393173b74bf57f3b09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"e3090b3aed673232ea2696beb8167fd5ed5aa16af1b080e033326f68a465c2137afc66aaf708fda03937f033e6","nonce":"521517393173b74bf57f3b08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"e944d7f3afcae2cf040c712ec7b4acb63b33c4f270e0f7ee37a72fb6337c93bd9597f679b2159d6bca096a9b39","nonce":"521517393173b74bf57f3b0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"14f96c3369569928d08a57eea701978b3bc73ad866697b100ddf5466f3ced863d03a00cd82956c6504c4fc9a01","nonce":"521517393173b74bf57f3b0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"ded73bacaa95ff1d419f59b65b0cd88550649f43d98ab05dca184aa0ee855f1ab827cc6da99b11de59215e0ae8","nonce":"521517393173b74bf57f3b0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"18146ef916b83aef1c6f50fc666e3d21853a08f47b1109a20b2d7076bff962ea2c6ec3187dc3df12c12e6f6962","nonce":"521517393173b74bf57f3b0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"94fb5cf6b482245da451cce42b203c09d637d7b4a87d70cb13e5d2a535326b9502cd73302a7697ec0eebbabac8","nonce":"521517393173b74bf57f3b0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"014176af506eff850d9a2edf0b3ccc3282b190467635db4efe40e41039bbd63170e59c58056641d760b9fa8a7d","nonce":"521517393173b74bf57f3b0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"24d73d676c2e002092385a0dcfed6c3e5be7f3d89acc692466d1d74bfb0a27e34ef394e18ba2e08e7b98d3dd4e","nonce":"521517393173b74bf57f3b01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"7394038ad5b7f21f58eb2166c049077ad3ca2c2477af5eb5aa21964fedc1d36c67fe3156a7ccb00e9d4c08027b","nonce":"521517393173b74bf57f3b00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"3d43cdcd66d29c6ed749972cadffec40732ef3f7934216acf903eb1eb6cd384fb503e0edead77421f7490f1148","nonce":"521517393173b74bf57f3b03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"9d50c97fb1d942ae31516856b24ad8e575e3b35253a53c32e7012bf4e2e944a9b5d52b13b4f3fb3089e27df81f","nonce":"521517393173b74bf57f3b02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"7defd4f00af93ed89c0d747a73020ff406e70e45a653558f915465d7c21195c07d19ddb177830016ddec1b950d","nonce":"521517393173b74bf57f3b05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"6c0575dcaef4ba7c8c500339b20fdab601635c0366e1797070f064bfaa3ff311e097dff17dfe087b7e93c7b2af","nonce":"521517393173b74bf57f3b04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"c0606ab3ec3db15461b42906fe325dcf66f40b10c453dac7692683a61f90956d4bf06290e031e193ae8c8b2929","nonce":"521517393173b74bf57f3b07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"0367377a137825addc2511d11082f33089e9be9d3573f37544a1373fdc8788329d4107d0092eeb61ad86335228","nonce":"521517393173b74bf57f3b06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"40b17db13b2a754418e23bf386f55cc10d0b640b1b21601fb6e09fe4422641aef8dc8fcf7a92b86d19e7f1987d","nonce":"521517393173b74bf57f3b19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"452d6aa734ab961ae4435f63f04b9e9a365ca10b65b14b72795671b3ee27708736beef071ca9e4dbeb008f3dae","nonce":"521517393173b74bf57f3b18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"31866b0753acb7f8b841045785ebb0739fad647778af9c2125e5fe57699afbb9f658a058757844add60fcc37f8","nonce":"521517393173b74bf57f3b1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"c492f19460063b5f61211d973d789792e37a1e5fe6fbf02f162254c58e5eef3b4a61285b05361f82282cb8e8f9","nonce":"521517393173b74bf57f3b1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"b5a96a3a4290438e51db4301879c80bf07444c06966e54218e5952aa8f569700105037a2563fe5aaa292def887","nonce":"521517393173b74bf57f3b1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"9d0bc3b3e768172b69234103802eeb281d1e0d2e2f019bc94b836a9226d92a100159a5430f2c9b0424ce59bfd2","nonce":"521517393173b74bf57f3b1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"f0ad34b11ca0ee7b38f45f11efac2f3fc59825778a8cb0d5bf4c857fa6d46449502ff3cb4fa19e9f262f16efd6","nonce":"521517393173b74bf57f3b1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"ca2b05b8ecf9eb7ebf93af4021450361d150b49b9a346e2785d459139955db5803a9be58fc87c0a5f4b4fa862f","nonce":"521517393173b74bf57f3b1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"b970de18770d986334694728729a4224b9a82746cd43759772966158081ddd811b97b5463afe4156aa7d7887e3","nonce":"521517393173b74bf57f3b11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"0fe0ca8830761335c5e60ed59fac793be9d66213efa46b4b52fe92d45c43982ae5647b350e05f2b696ae246249","nonce":"521517393173b74bf57f3b10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"ae2dc97873655ccad5932b43edfa086fcde64cd44f27bec96fa383aaf5332c2d1690876297443eac771f7acfda","nonce":"521517393173b74bf57f3b13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"e021b6c4da2db2d139e1224f4290f5507e787f7240dd394167cd5b14afd4ae49a7998974586095c2b0dce2d3a6","nonce":"521517393173b74bf57f3b12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"ad4d39a0b6e07d64f83aa98f6912debdd4c18b300b44bae49e61e154311d7d24e44b329a5357f831dbf1ff5820","nonce":"521517393173b74bf57f3b15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"1ad1b96adff9f40f5ed95ab5aba7da28b7ecfe152875a14e861bc0a42c79c7a6d903f0e448689f6abda7cccd21","nonce":"521517393173b74bf57f3b14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"139c7495d645ec0929a3ed969d403347113031bb7e75aab5d4169e112868befe5bab78c34c0d38ddd54794b235","nonce":"521517393173b74bf57f3b17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"728f978bb8544b6361c7922e4a2ed1ac4ff634ac97ee0cd62f89af33d0a2e163dfe34c6a79766841ec54fbc7ea","nonce":"521517393173b74bf57f3b16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"4fcfed64f73e4f4145c9bfefa776e3f841e0d70a11b4c7184f4a908087d82c962560369a40125535e074bbf277","nonce":"521517393173b74bf57f3b29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"bde9ccea2bff9105d9639895c8b85345e0ec0841aadaaefa0ffe201c5541c59915bac8fbccb6c7d4940eed43c6","nonce":"521517393173b74bf57f3b28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"fc68648dc92c308fbb71e788bb15e1a8b83ddb1700794a3f146523f87367fb341c4d3e5e8df0f73e6af2109022","nonce":"521517393173b74bf57f3b2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"9a6bd3eba8a0aa630c5a3d55a56a28e639612340114137195f9b78bae2dae339705e84ae10495159b5ea4b9ffc","nonce":"521517393173b74bf57f3b2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"eeeedd0ed37b27f2ee4b7bc72be8e29d6ed60754d57560a0b2bc35fe65daf2c83c2bb6e73886621992129ae15b","nonce":"521517393173b74bf57f3b2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"30b1e5321b1769c097f284528ea2325b6a2f29536f2075f1141a4c475b0ee0c8b6b2d0594d0f92f00d348e7764","nonce":"521517393173b74bf57f3b2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"ab7faabe528e65d1ea14e7ad7f5abdd66bc34f839347967aef6cd2d3268a0691b45d73c354be266fff2f61fec0","nonce":"521517393173b74bf57f3b2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"67d60cabd11ef59e991afdd401acb9e1e779b0171d4d33a23936bb066e161cd2f905279f8dda3ea171cb15638d","nonce":"521517393173b74bf57f3b2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"44c3d1b0667a74dc316e0b2b83f2104b4c4d8337da282f458f3bd2ab49634e8fad1f3ee49f2455bbddd5487ec0","nonce":"521517393173b74bf57f3b21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"0ce2bbe428e5ff9c54ea427be8c9314abc5b4d7795f5b44ca891263ccc087c907996aee8e53f9eb901e4799280","nonce":"521517393173b74bf57f3b20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"067f0dfebebaf93025a7bd35c6229e7cfd5336fba907b828696d356a7e20324f089e7d2a0fd940154b28da74b1","nonce":"521517393173b74bf57f3b23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"864fde20b28ca34987b92b6578e61d99a435d6759f696d012f241f6db9e628da3b3b197af11c6f95b71c78abad","nonce":"521517393173b74bf57f3b22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"fc76b7eef52b29ca741c2fb9a34c61c6c47bdd0dc5a2a6ba3e54051b043cf98ead1e9e9b50a9845cef2c9990a4","nonce":"521517393173b74bf57f3b25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"e0428b9b7f8bc3b979d8ba6cc90d566fa6e843f6a5daded527bcd15fd6024f4cae1341d8e57136169616b77440","nonce":"521517393173b74bf57f3b24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"62368aca60b60a1c914689d8117ad1311ac270c80e8a3e618320310f6c5149ea975ac765140ca7bfb69b46a5bb","nonce":"521517393173b74bf57f3b27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"a6ba9724c663aeccdc0bab858bae6d1bdf45c44f97c41f702d89c2e31929ab4b024d499748975a7ba525a19ad9","nonce":"521517393173b74bf57f3b26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"a5d25686380fb1cf5cf486fe709b9528e48ebeac611037d2030b87ce9d2e6dea16d7a6d6f18fece88ee3217ee5","nonce":"521517393173b74bf57f3b39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"c1c564cf10825ff3fdc527ecb517ed0a8668706e3322460a2d3f0406cf5652674b8c20073c93affe81801bf077","nonce":"521517393173b74bf57f3b38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"22781192594c38634fbd8412b51912b015d12533c62d5659e940d6c2e37e528ac268c09c792ceddfc6e2062549","nonce":"521517393173b74bf57f3b3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"41fa67aafb0705d3c72b75c4bf0c153281cbfe5b452e39285b664ab08e7c24726fef51f8bb1d894a7aec1f8ac6","nonce":"521517393173b74bf57f3b3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"3b23340318fbb035fe1ce655328ad27d991505cd8ee56c6d4cde97374befe4fe222c7e55dcb9166e6f36191152","nonce":"521517393173b74bf57f3b3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"bd9492204033c700ca64abae3c51ced2e0363bdda6aefea1eb6d3942dd7231bc68afbe42e1eb7471a727b2f154","nonce":"521517393173b74bf57f3b3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"de41156c647ab129ed598f4d4ef82a01e3c9baa0cb41454dab0444a42ad81270f8572f0c6a83eb4fd9a5efa708","nonce":"521517393173b74bf57f3b3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"1f27370a6c7e98c75a8b7667059069a35037b6d693e45333f12d42b49b682757bb9a409c074a21e2d2e1ab53d1","nonce":"521517393173b74bf57f3b3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"fbbfa481e6bf3689cbfd9df3adecac3aedbcc84a570213681c7bbeb6ebe0662797ae71a7d8d2ac185908128e09","nonce":"521517393173b74bf57f3b31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"b87aa2ca83195af09e83669d66f84e240fc440819c6f2f984036a7a46de83fe5115171531d591c1c5a21a4b4e6","nonce":"521517393173b74bf57f3b30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"a63b45d8dc9473e4607a9b8cbe2ef3777f91e9346bd805f759b67ef2853751e997923ee2cf26c14bc6574be2dd","nonce":"521517393173b74bf57f3b33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"984fc6fc3071b019048e746cedbe717c2d37cf683152040a97b6d6548e7e582bd49a10df6fa16f9ae4a69979f1","nonce":"521517393173b74bf57f3b32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"b360051be1a2ddd2b549470be79144182668447657a1d904b6b236f05b89af9676ead5bbaca9823831b688e0f7","nonce":"521517393173b74bf57f3b35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"bdab95f5cbdcf8f474bc115724519130126e5a24cff6e8ba1f3a562141a1af0573142bdc3e10d995e48754bffc","nonce":"521517393173b74bf57f3b34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"38b24a91cca21adc928e905a430cf579f9520b4443f1a38ae5778c7d5a5b8f1150c1889f350cc97e35b07e9a22","nonce":"521517393173b74bf57f3b37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"5aefa2a7135bd2af5f4421555c9161cfe3111275dd1b5f6f32c59444dd85c05f11c6adc799b3dbd59e1bf3e2e9","nonce":"521517393173b74bf57f3b36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"a62a479ec1a8fd000b9eb297fe8a27b804269bd327a20dd399bf0b9250c45ef5d7381a7b2cec47cec0264e4d8b","nonce":"521517393173b74bf57f3bc9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"017028b22e9e65f6fc337aa99bee44ebf97a8f17861155a450bab16d4948899d811a6d6c35d1d0b656b94e4648","nonce":"521517393173b74bf57f3bc8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"3a91097de703d871522e4139d50a46663d095a8e598bf2ad30956eac9c1870358e45ec0a8662dd3d7bae8d02e8","nonce":"521517393173b74bf57f3bcb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"afa81a9f194fa8d2a1388ee09056ca0ac20d5b0652c78643164f8e770431cf691689f3ac924639081cc62b55d1","nonce":"521517393173b74bf57f3bca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"32df52299ee295beaeb78c74ead25a0d1bd44ae6e085a075c712f3b811ba61ee8c2ab1ebc01d11ea4edd117b86","nonce":"521517393173b74bf57f3bcd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"96bd73296e21c3c4cee25dc1e3ab3b63243e72f4d60207554ef8a20bb14654e54b1c39c75c418901833131cd4e","nonce":"521517393173b74bf57f3bcc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"992afbedde25822fdf858cc99f5a92a249adbdd05989669161f2a473bd441428f6ff922b5a583287908b063950","nonce":"521517393173b74bf57f3bcf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"c2718c8a3113d453df4496fd2a937bd29d0c8c5ec3af2386bcd2a630921c0f5004798646ea361e44a9e74cc18b","nonce":"521517393173b74bf57f3bce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"885bca785df786f31a8f993774ac94f84b6c448ff211c327fc7f839037d83c90d7f0d86712f3c0d5e1d26ef299","nonce":"521517393173b74bf57f3bc1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"cd35f2a246cbeb9a6b6b638be71f19f2992a7f51d7c820fe154034a791aa357e503213f12aecb32630533914d4","nonce":"521517393173b74bf57f3bc0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"adcb92cf38ef077168d98c77f778f607ce8e4be75abc09a01fae670835ed41fa1e6a62a7d409592e3393ecf78b","nonce":"521517393173b74bf57f3bc3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"4a98b3c3c9532bb682c66ed8de5150be50aacb379a31b340e9a64e4f3e7e08be5333da46979403c5fd52bb3a1e","nonce":"521517393173b74bf57f3bc2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"51d1cad2cef9582008bbcdbb4096eefa8d82566fd39108a27ea19920fe2ed6ff1469f328e81f7ab642bfe6c2ce","nonce":"521517393173b74bf57f3bc5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"85e6ba2bad431c9d2da45517747bba7e854c96c03d4fa9b314d838ade718f6944fc59654076c0fca499db6a9b7","nonce":"521517393173b74bf57f3bc4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"3692cd1d89f0a82f53dba9f31a9190e553c19f4dfb269952df4c2abd681a868c117e915a8633a03c0e37483b58","nonce":"521517393173b74bf57f3bc7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"dc2d0e070f7ba4b0de6e92f1d310adc8b0242ef67bfd6e8e26af1414e30f4a939c92cff1387ba5db55ccb87538","nonce":"521517393173b74bf57f3bc6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"e5932147b1ce81bbbb17f852625da0da2562b2b61e7ac0a78c3a3d2c910e0393e475273ea83adf492efa57fa3e","nonce":"521517393173b74bf57f3bd9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"e4b7f13a415d6820911df7c62f2f85a8718049554065c24fafa2eecb9342d423581e9ebc30e6d524afc98a177e","nonce":"521517393173b74bf57f3bd8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"ebbbe9a1e601687a0b45eb0e406c49694d2b8e7556c9b6361f47e836c674449bd264c3590aa84787997aff984f","nonce":"521517393173b74bf57f3bdb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"ae682b9a8288826ba2832c1f8b50d01b62756f1878c7ac2ed3385fba6d7e2384cf7a624089256ad5275f07ba79","nonce":"521517393173b74bf57f3bda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"2521afe99179f96f6f42a4fca3969e1a4928d1a58a5668b338a84f0bf82d5a920f477d58cd8ad6a1703ae77ae4","nonce":"521517393173b74bf57f3bdd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"af9d004b35b62d54ab8b8d011a72a8dcd6b0427d286e65d533b6e4e4308185e4976d6ac565643832d5bf4304f9","nonce":"521517393173b74bf57f3bdc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"32abe48db6ac04011f45e198505beaa099b4adb55eda7c1840d2b43668bd1cd7a435d818011323560ebe21c9ee","nonce":"521517393173b74bf57f3bdf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"1ac3cedeeaedf0253a2103503c3e57273161eef1d688cfd1814d114543dc5625024e9a0cf572a1a423efd6d9a0","nonce":"521517393173b74bf57f3bde","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"120f340a657c6dbb5e9ab0effcde7d639482f345135cd6e0ec7e44d9c50aa6bc0d09b37f76d66d9e85fe6b58e4","nonce":"521517393173b74bf57f3bd1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"7dc7db900cebbb0c33e7d7e6900364945007d5956224b6f7e9d8aa161f5c041a08072b2535d06c4c4432fff93f","nonce":"521517393173b74bf57f3bd0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"a8650a24a799bdbd0f717338d605c30c1d61a31236e16892ef44fa286925daf30d492d80371623329ae37d889d","nonce":"521517393173b74bf57f3bd3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"b97c62902d5df9f4086a00d699cc9c1cd2717ce74131f3727e2dee073ff5549a1db7e6bb21db994262b276f655","nonce":"521517393173b74bf57f3bd2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"007170c3b20214710320ed563d69cf85c9fcd70b070bcb75ba65d8e07dd78c985eef9f6c4bd91d34b704acf1dd","nonce":"521517393173b74bf57f3bd5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"3d64f10ecd6c753f53d7b68f5f65decc29aa1ee6ac3eee07f3b55bf189781312ca19aa97572c8550ac57b23dfe","nonce":"521517393173b74bf57f3bd4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"df7382efe66382ca452c5249f72dfd1ae648b7133d37ccc122fd1c70d841008d15deb97b8af81fc33d625f1eef","nonce":"521517393173b74bf57f3bd7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"b6a279c890489d8f0a98619a41eaac190acff0fa1cc982c6215c3fc72630d6f4252c62e26df07278d57c6fdd70","nonce":"521517393173b74bf57f3bd6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"49cfb877705c8bd422b054105e77cbe119e396f8f2add7a7749277c0cc4fa7b6167ddcd8838fb3ff2ad3391c80","nonce":"521517393173b74bf57f3be9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"0de22134953630f5e66d6a54b4b9571450b5541b26873f866ac30b6895467ece906fabdb2f3dbf3ef6c7f70b3b","nonce":"521517393173b74bf57f3be8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"4aa6603cb1405798809f3e659c204fcd82d55225859983812380abdefc53205ce01944e102a69a3ffe5bc51954","nonce":"521517393173b74bf57f3beb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"e1236ee47f87992ecf49844cfaaba23f1dfa968f1d1b5b855dccd4d8916a6980d301fbecbffbbacde3597a53a6","nonce":"521517393173b74bf57f3bea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"475bc20f626300411aabdb3d81f0a910a51b9e814c4187269eee1814b86e0ee382592bcda0c198990604e9234d","nonce":"521517393173b74bf57f3bed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"607911a1318d1918b6e9c3d8ecfc353ad582e83eda4c0559ecb754458a5c334fc37337c6f29647adfcd6baae3f","nonce":"521517393173b74bf57f3bec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"159ca6327acac519a208d34b0fbb725b56e2cc4a08e8b1d632854de453e7bc4ac4d05ded4b01af81eb0f29326c","nonce":"521517393173b74bf57f3bef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"932b570fe17f0dfd62cb5e109628c92c087762668cf97efa4d4dbea407bb95c3753ab295023220ee25767cb981","nonce":"521517393173b74bf57f3bee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"a2aaa6eb8aa505b3b0b87de4ed778b511e42a62c0454fdff1a81fd58815d687a5d38bdb43410341679dc66f4ed","nonce":"521517393173b74bf57f3be1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"6aa1442ee13446d57a205c49997ec9583e93aee7c4bc7e37e33c2682d31f1ea398d0232bd17b16b6074468a857","nonce":"521517393173b74bf57f3be0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"7fbe881fbe157c981e09993c0cb3329e1bd5a36e1357a2022810e6bbf100a99c6939586fef1f8cb90d14249a82","nonce":"521517393173b74bf57f3be3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"b68878441365ed94c782cc06ea7afa5ec9305fdbedbb177f29fb66922e2b8f502eae42204398f5176f51a42588","nonce":"521517393173b74bf57f3be2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"f256617ac7d70c6190ec2c1562aa074de431ff20b8ebbb2c6806df8b86b3fe4d74e4c18d6c25a534f0bd62a0c4","nonce":"521517393173b74bf57f3be5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"7ff20e337a75801fd5c15e1b953ce64d7d6a9075c928ea6ca8b633c08a6d80cecf192f66871a7f7ea9d4a636c0","nonce":"521517393173b74bf57f3be4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"f7986e8005d1039d69fff083a5008bb3ef84e23fdc2798eab84c0c2654765a2d9b7f4f81743df9b902d6c7ed42","nonce":"521517393173b74bf57f3be7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"8e6033a6b6599ac5530be051ea62500463d079262dc70b4994105563e27eba04fa7ffd3e396bde55645d3eb2fb","nonce":"521517393173b74bf57f3be6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"854e9154707edafa61e8c059aea67c41a98565413f2dd3f12b7da6ba7a488a2960e4b4203001685841dbe59555","nonce":"521517393173b74bf57f3bf9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"ef483e22b3789f647c67bd6d8654b6e6d420f5a29a2f76d53dff7701309b22151086221f2b4b11031ad03df7f6","nonce":"521517393173b74bf57f3bf8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"fbdfb59ebf5a84580b82dc828d2498f19fb2afe228eb63eeaa6613c3ad97570d8838d9c4df8b0d364a5f470f8f","nonce":"521517393173b74bf57f3bfb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"434bb978d583121d630617d3fe7dbeb9d234c008cdbc3fa9bbef856135ce6e41041f334148745ffc9af2f5e078","nonce":"521517393173b74bf57f3bfa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"c5389dc13e3253b203fb07cc69e75ee3e3adc6ac170fb706683f41f7e8c509ffc72230be703b9680477212caf8","nonce":"521517393173b74bf57f3bfd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"2ea6ef529deed7f9b60d04287776518107f8aba237915fca67e2d559abd60cccd1b19ac8f6920e08adbafb3830","nonce":"521517393173b74bf57f3bfc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"c929a4e91b5502ccabfde3ffca7809eb9505cc68e282bf759c60e815fa5098f40d4feda4da4232badc29596432","nonce":"521517393173b74bf57f3bff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"62eb503656f68887e52c422c9dd30850f1bc579ada3fda86345b9ea8e893c2d9dfbe2e30510b9d9f942a098928","nonce":"521517393173b74bf57f3bfe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"fee0d5110d6bbc52b939d4a96273491e14a93ac99d463f3e4485f905a272915e35473df30a3c183997d4beab5e","nonce":"521517393173b74bf57f3bf1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"f21c7e9a932090065080a7f736561599b69ca8b536e51318e18d5160ed94354569dd48827694acc497cb016060","nonce":"521517393173b74bf57f3bf0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"f19ef96677a6d408edee29b04339d612e585353250ebff0114d2bc5624dae7e07cde5b5ac288d7a81c5f0b2ece","nonce":"521517393173b74bf57f3bf3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"a23189981daf8315ac6deefefbda10569bd5c153c0bac56e38339303b561ff0a8d08cc5e7bacd2ae79cd7f4f34","nonce":"521517393173b74bf57f3bf2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"9bc4f6fb19a35ed07142a58b4de5edbfa1636634ffb7176ae6c7f9ddd9ac99a3028ea512b31d9696e687f9695e","nonce":"521517393173b74bf57f3bf5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"a2f1996e8a21dd570ca023385a715f76cc6b8e00ba15472d0f6cf757f840f42af223148833308d91481129dbba","nonce":"521517393173b74bf57f3bf4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"f3aeff1507da7b2ec9dc674dadff02a867c4d9e4d5ff3779f8dcd58fff08b61c59b9f4b8f6921708d24c5d7842","nonce":"521517393173b74bf57f3bf7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"cc80c26305cf7fac6bfab4c107010606481d5bee0e09447cde3f7f9020c2df4511e34efe256d18af907aeeaca3","nonce":"521517393173b74bf57f3bf6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"a5a66233c04095c76b18ddaff4c9897f4ed1f405a02e1d36bedeb6b674b404e4a8b181184accb4b0fad8e675a9","nonce":"521517393173b74bf57f3b89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"eca53a726b8cc267196aac3f92cd947d4410e56fab9eedd39a86e78432052c960c9be48cbf3e3da39ecb59b40d","nonce":"521517393173b74bf57f3b88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"68bc7deb2a5a7f05d9635ce055345f9295cb6a2b6e929d9dcc1467b1fa5815e1004145c07a57402d54323faa80","nonce":"521517393173b74bf57f3b8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"e75cb42274ee8fba01415be255d7ab97180717dd03ca71fffeae8c9921ff96a435812fc83440257fb6d4064241","nonce":"521517393173b74bf57f3b8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"0af97daf6d0c53698d70b26ebb4d8a5f49f2834cca1cef856e043d8d6c06303e40b4046dfeba78c99f9df77088","nonce":"521517393173b74bf57f3b8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"904464c0ff97c1ba09bc2b044c863683c3c996ae783c2722055366ef12f10a9fc4476383ac6a3553deb1101d30","nonce":"521517393173b74bf57f3b8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"25fe5d935d83beb979b768c3ba5701b23982b8e0414b0b0ef8f989effbf9a808e5d1abbbe9ebacc3d953b289a1","nonce":"521517393173b74bf57f3b8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"f93a846f1d2475f28d4e29a4812e56b7caf367c9c4e547576759ae5824b4396cdc49942106571de3332879c952","nonce":"521517393173b74bf57f3b8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"b6236d789145d65ee5046ade91aeb17994078fae30bff02dc826a21e5d0bd2b3a11e1269ce034c667dba50f716","nonce":"521517393173b74bf57f3b81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"dd0bf9844147635c281f15293b54698c057117a1cb18b900e239a83dfd2a6caa9bf970f9254037d9b0c4512df5","nonce":"521517393173b74bf57f3b80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"6bbf8753cea5cb9f802883354130e77b913fc5a67cd564cd1fec80b512bb1a84fdb89bd8c7c745007f8dff9b85","nonce":"521517393173b74bf57f3b83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"359bd79202e1b9942216f1842543379008fa6deb0a2c16a9ef95e0ba10ca6a8530f66a77bcd3ff59275ab2c46c","nonce":"521517393173b74bf57f3b82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"cb8d66f6f44cb6dabe640349e430e64c5d5b821afefbe74805d0b563b6f5da3c1e013e6e712fee502e9f076587","nonce":"521517393173b74bf57f3b85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"fed19a3ec7da18862f85bed610a3f2d1155402d67a52344ac8f1d67539285d57d16bde398eeabedfe373ec4fb2","nonce":"521517393173b74bf57f3b84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"3ce2b683fe4f5463c3854bdb8cb875e50fb57677295a9b4012980f020db6c251624d16e0e61adf98d2c038e84d","nonce":"521517393173b74bf57f3b87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"ec0d22614cfff9ae4391fa82acccb633c3d5ed05cf40e06c0b1b0bacd1ecc54ebdfaf01f452f62d114a265f637","nonce":"521517393173b74bf57f3b86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"e7611503870d5f1518f7404f52b7a3db05682a95dedf928a3bf280a6c08feb755e8af7fac55137e2b04a5d881d","nonce":"521517393173b74bf57f3b99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"cd66ddef25ec33b7f00a7a674dc6cfe2e0b83f48a45e1b4b4e241e4689004be10a4bc0acce4ce3223a65d9bb92","nonce":"521517393173b74bf57f3b98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"6a6198564ad237585d2ffaa2e63442f1568c42be90ea69a69f09298182a8e8d3af82b8859315d5f3b2e674d83e","nonce":"521517393173b74bf57f3b9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"e63b526109abe25166018c05e9d557f49e582fd2b567478f367badc1a203693ae90b43924d5fe43d8a00698903","nonce":"521517393173b74bf57f3b9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"f902cf4832357baee3c4e3aaba220d1f0b79843d4fe51d7525177c4c630e3b8ef6678b238045bbbb90d88336b8","nonce":"521517393173b74bf57f3b9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"17c4e5f29796648446213c145df0c4ad9e6edfb159c651b79c37f1a9e51235f4aff595f2b1feb5c6deb73a9ed7","nonce":"521517393173b74bf57f3b9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"e90f6472599daa9a8e3b850df91bc7365db831dd79b11abd6ba4a02df82fc66a8486d8a6870fc5b4f4475b9621","nonce":"521517393173b74bf57f3b9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"03d31dce2fab59fa707d34adde39edcc43dc842595a66709219741cfd5a56a2135879718b91171eee0bffd78fe","nonce":"521517393173b74bf57f3b9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"38413ffbc283c20d10e53359108f91149f0aa18073f335aea7d1e26eb01263edfdc1ff5c1de1685eb1712e9890","nonce":"521517393173b74bf57f3b91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"801b798de209e3f11373eca6ea3d074ef37107a774b5082498221f673e40a9ca6791f4b4438b71acf2fd56f3c6","nonce":"521517393173b74bf57f3b90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"44770cad2831ce8de991088e343c6387053750dced42283e53afb3e21d9433131185074f73e12cec3792e35fa2","nonce":"521517393173b74bf57f3b93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"050c5e3d9a9933ee7c0af1037365d384017f6fd72322b969b1c61e5a9143836933d3f47b485c07898a241849ca","nonce":"521517393173b74bf57f3b92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"66fc579ccf787c2dc874ede9b594236f5f646192837779dbf0353cbff47143280f325fa29f19bde65f9d304667","nonce":"521517393173b74bf57f3b95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"1454549ffe7ab150af70f567af249824428b9aa144b0d6a18a3e6f04e0f413a5d49a997925cba152c1e1f84391","nonce":"521517393173b74bf57f3b94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"6bdeef27c6dd53354bd59d6d1800341093dbde5dd748551a083f15177b5243069c4226f4ec011088f8a025ee07","nonce":"521517393173b74bf57f3b97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"09009e6fea804c04ce5edf4e70da03b81df238ff1f4c8ae5024cf2202487b9633079c907a1e38f1f6ed0da153c","nonce":"521517393173b74bf57f3b96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"93e8037c442db9f16fb7ee3751b90a22b6f9a7a1556bc4a2b54f243921213a88c6ff7a8a1127d998788281ceff","nonce":"521517393173b74bf57f3ba9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"2331c8603141a059c287b101186be811e79adbdc8caec20ec1a9e7f654dbd940eb6adc604fe123e7ab0cc7d2da","nonce":"521517393173b74bf57f3ba8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"87b06de70fa69db2e511b73d00cf5a81d143398d7e79797f73025726f67a1d57afc7d61db5b4e9ec881c60b9ed","nonce":"521517393173b74bf57f3bab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"f7beb2651e49ba2e9040208b5f34bc4f977a3fdcdfc7055b0b5255e15346655772922b0457fb9112393140d905","nonce":"521517393173b74bf57f3baa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"014e4ed4f335d3601dfc779ceed9c4c6913bcf614d92a5312a30e0362a3cf7de540aca472d2db379696e28685f","nonce":"521517393173b74bf57f3bad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"6fae9217610aba2ec94b44349e6207d0617dad3e008fb495cfc70bc91da5dfe304eb21a8fad728547664321a74","nonce":"521517393173b74bf57f3bac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"ebf06854b08ebf276cae423b7f357d3e23461f35e35be61c50fc4696b4616181360c3a4e32019147c64fe3fc58","nonce":"521517393173b74bf57f3baf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"278c1512b986f38d4ceb73ba22005ee380345c74ebe2741519c47aa895b71728a17744258f77751173d06e833c","nonce":"521517393173b74bf57f3bae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"af479e0aff6f262457205891167c21b66cdccbd8ae89ef2d78948084e92c226b6b70d1caea8fe94b6ef78b96fc","nonce":"521517393173b74bf57f3ba1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"f9252bfc43863c16337957005de6c14c9dbeccabaa75ec477f0eff0ef683a1c41b13bbfe5ff0675e759ee5fa2b","nonce":"521517393173b74bf57f3ba0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"bcefcea98853df16334f1164f19b5f811d274e3d9533eb1f1dc407042e39601001df680361be28f1430a1b772d","nonce":"521517393173b74bf57f3ba3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"094256db7a822b6c786bd09184cc29a0e49b7f6da910cd0f9e4792615390d7ef7d369ed3b7e16813189c1e2b8c","nonce":"521517393173b74bf57f3ba2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"edb9521854aa22cc57cef24cba5f3c5f922a62c18c553939749d6dd67b63016b8dab2542d4210dae4826d7051e","nonce":"521517393173b74bf57f3ba5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"8305fc9f0ac206982d580b3b3ca3c2c3d3f59d0ffa50cbdc1a3c8324e69b69a63b77b432df949c2c2fe7aa3f68","nonce":"521517393173b74bf57f3ba4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"574b243987c3d0c42eabac62cfa820f1fd2dbfde71a9c68c6e9cb3e8a8102f9c117d84239b876a4fc6b24e1cff","nonce":"521517393173b74bf57f3ba7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"cf74c5313435649066fd4769aee978f7cb9324715e75f08a72cf37616a413b5d3f13e43939adc7f80a4209b721","nonce":"521517393173b74bf57f3ba6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"c3549d2b103b075a926ec71f86b23af739ba97c9a6eaae94cd833b24ad6cb3092aecd828dfdc8b5f5ece6c3d67","nonce":"521517393173b74bf57f3bb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"a6303001c556ed11227f235a7f130c781bd91f43270e29d21d30c8b5f1f41e97cb9fff995003b3ba5a1a23e410","nonce":"521517393173b74bf57f3bb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"088f79edc15750203a320e232f83d81d86ead95c593dc45d3bc894563f81ee68dbdad8f31577d28f36c5e1312f","nonce":"521517393173b74bf57f3bbb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"509308368c7b813563aa406b9de6378217423d0f30f08abb509f4aa6384997ccefa20a71eaf0555a91e6773852","nonce":"521517393173b74bf57f3bba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"c3398edc17c2340a3cecaa9cc850d81b19dc1e2913f81f0fbd08a83aeebf7854a2df6c17a9782a28a82e712ac2","nonce":"521517393173b74bf57f3bbd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"c804cc8c222cb65553540362c09cbf3a06d3621f680b79b1b7ee54e7ae266a9d979f47bff6d636fc3eb6025c47","nonce":"521517393173b74bf57f3bbc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"4604daf35a898ba39c3fa81fb72129b7c70dd187df0ed368fa3251c0998a3e81d30f0c87ad818b7f6e3c5eb93d","nonce":"521517393173b74bf57f3bbf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"66d74d7c3b8309c4ae876cc10bd0243a3dab547b6741b6bfc1920500780506cb1e0a86c3836c2241beeed8d31e","nonce":"521517393173b74bf57f3bbe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"795015933b94167f2ca8fe2e9c455f0036db15704f6de1042438de90d5a465c91637627a5d075cfacc0af6c46b","nonce":"521517393173b74bf57f3bb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"db314c7f364ab1c2c7f79435e07f5566e6d8cfaab2a9ceb6cd4920610d34ceb67ee84144446460c789ac0214d1","nonce":"521517393173b74bf57f3bb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"a174e119fdc3c2cba6955b0edf0b52f9c344e8064cbc6804cd2bcc87fa8c5f428fe1c0566217aea53892008403","nonce":"521517393173b74bf57f3bb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"ed891e8abdf5a0c107f50342021b48db4aa28727a49f18ac81fc0c57a5127c2b80ed321de2bef038cfa99ca148","nonce":"521517393173b74bf57f3bb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"225015d7e94e049d65729f0635d2ca6d1d185fdbe096968efb1a57d27a68561a2859f9e66f228fa899e59ca027","nonce":"521517393173b74bf57f3bb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"e75f89bec42e1d3613fb109d65b2a35a0168f0b435b3e3483a536f8c6e24bf010ccf8f79d475394742494e0b68","nonce":"521517393173b74bf57f3bb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"8917522c6dd4e596280c08182dcfdf53b78a3eecb0ed35d30d9e4185bb1687468a3243d82c8368c2338fb8334a","nonce":"521517393173b74bf57f3bb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"cffa649159a73658d227c466ea01632e7296b59861cc487ce5d93bb2ea8b600a1e65ebc8a0863e730b8c86ae99","nonce":"521517393173b74bf57f3bb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"1f8e9b248728f3fd3afcf52448a166ca3c2723389c1e35ba824f0ae0166d9d99b4b40e73fb9c3c8153292238ba","nonce":"521517393173b74bf57f3a49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"f377cbd52a8899a137361ed3424a14fd5a72652d7aee222a3b70913beaa69a1f"},{"exporter_context":"00","L":32,"exported_value":"18d6bc3be96c5107fc6aedd6f66442b9d40499320121eb1f586b0da5c3d9156d"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"2d5dbe0646f491e6c13908bc15c4b800e06ee55bcf6f479cf1462594e5514f26"}]},{"mode":0,"kem_id":33,"kdf_id":3,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"2439ca2d6daafeac88785f0225ce5ea48bf719cb977f09ee391d858d55024f003a1949dfb86aa12adc680e64ba591085b6dc3c54124c5303","ikmE":"12505ddbbfd4a66633b0dcdd9b86959dece103519ad97d8c267569b67f57657cacb6995b073ce090144e1b481c57329d26f16a29dfd70f04","skRm":"63b91f7afe3e908be73e594f723b4dac46e3a6062f1c1e599243df0abe3076779ced608421d826c4dde8d22638f4285342d350017e1c7a6a","skEm":"09d774bc14621206c7cdc8e857dab55d951fe292b948e412796ffe9b340e2fc56301f00d7e1952b3e75528eff946c4d79bbd7880bd070ca5","pkRm":"60f0058bc0eee3e0c235b9149520e4832c1d49a97eed242b87a02ed25a5ed50f964f1472b4b9cc352599e37a5b5348f63cb90aeaa73acc95","pkEm":"f5ae104144bf535440ca82b0bb9427c433ef98cde723f3a0004c3d89a982e03ac52ac7b3fdbe2ba0c0b12c31c298be3d9209124481bd2793","enc":"f5ae104144bf535440ca82b0bb9427c433ef98cde723f3a0004c3d89a982e03ac52ac7b3fdbe2ba0c0b12c31c298be3d9209124481bd2793","shared_secret":"6a828983e54897d3c4ee1c5aba31c64405ee4d28dbe4460b84ce792b5395fabcce254a900e8b7b3aa4f68b5c208c3ce243ba56072c7406b76da47a6b820980d1","key_schedule_context":"009f764d157beae4544a48cc4382cc0eaaee23564072136ce01ebe7b274f54ab4420ed990cd86d7ec33fd88dc1a603491ae460c58931a78178cd8e1af2fec96e7994b5b0e6ed9749cf5a584367aeee9665bfdcc13ea89374b725e4d30a351bbcc95bc70b4c35cc84a53ffd1e1877059f35f9f9c98ae168ad89a3a7087d7e88b855","secret":"ebb38a6d7953a31347654d78e2f830bff38c458634cfe6a8385380f751a114e7c1370481741c2536512b2c641f3de731f0313c97b50214305e51e93cbbeccd6d","key":"3c1aac5c8e51400e4117ffd72dfcc74625a81b294977e99216633401e9ff54af","base_nonce":"0900c77d1f2501fc38bf1877","exporter_secret":"e17fd88cc53ffb89bcdf49d76da8d2d5c319d73e68eaa30f64c02d2cc4c27ac953fa618c48c601b9cbfd026ba450691a380c75afcd2f02975107c36426e8ce80","encryptions":[{"aad":"436f756e742d30","ciphertext":"9f854ec973d5e9cbf35620ca95b875ee56cdf017376da107498fc31e4c7fccf59fb9365825a7ac032899628a5a","nonce":"0900c77d1f2501fc38bf1877","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"ec7be8dbac9786d3e655e531aa0cdcb8e0ff8bac14a9590d4fe83fe2672912eb38c1114f292cbc3031ca2b605a","nonce":"0900c77d1f2501fc38bf1876","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"a449310d573319eb8542290f20c4cd8a23275c50839e750252c951c74e7ef7a3668562fb4687034fc46159b209","nonce":"0900c77d1f2501fc38bf1875","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"9251accd44e6253dd725ae20e1aa98e710c6f189fb9acd380eca4e4ccca3cd00c62a768b474daec6293744d947","nonce":"0900c77d1f2501fc38bf1874","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"050187f3bc28e13d770370cf111a295d5b1a0c08841a7e2a57f62735de2f84236dc35044ace1a0d482bd7a4418","nonce":"0900c77d1f2501fc38bf1873","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"b842c8255904e60307637698864ce863a6e1d40eaa6a07936875ffec03b319b9c42a5268571fd475c179d0eeda","nonce":"0900c77d1f2501fc38bf1872","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"ea7465f2b6ff96fdc1050a1a7f04d4fc16133a38fdbf33d0e793ae8bcdfc3cfd941fe2d5b410139660b078f7e3","nonce":"0900c77d1f2501fc38bf1871","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"0fdb190d23f70bd4ad8f0480fb421ba2472230071fdaae8349b19918667b1257e4dd44b8af2b6237d9561e0346","nonce":"0900c77d1f2501fc38bf1870","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"ead063e953bd5589a5bc0cd14b147276b2ef1bfd41548291d69d7396e0a2571c59d633c8e009b147c993cc7fdc","nonce":"0900c77d1f2501fc38bf187f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"de29495cb892f3d2db910ab50262b7f8882e8c378d89152a8fc2a52177c65df67b056ef9897f67263ba82a2f4c","nonce":"0900c77d1f2501fc38bf187e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"d1163b2b642511277b2b21f22207a3cfe477dcfce289323668c299dfcc288e36beeb34dc6bef9b00afdd109f0a","nonce":"0900c77d1f2501fc38bf187d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"7c6e9d023baf6c090dc4bde3feb451ee2cc45bef3deb5699123bb3d9234d1fcb13185a30b93ba6024c31d9d227","nonce":"0900c77d1f2501fc38bf187c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"52fae3c62d62dad62d7cd925b6610d5d00b762867d72f11ec90430ff09d2513a0b01ae4ede95a69bba19803733","nonce":"0900c77d1f2501fc38bf187b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"39320e91e659e190d6e9baa7262bde446555f1d572b0936f03402db3ef7bdf68324396987669d36412c36cd603","nonce":"0900c77d1f2501fc38bf187a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"9ed936fb08cdf45efb421e5e9a27da4643840c9032e375dc3400ab49bdf3fdd8ea1941c7da69a281f67d5f6d5f","nonce":"0900c77d1f2501fc38bf1879","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"ae6470ca6ec99e4aa7292ec4671f5ffa09a0d70bc6c12291d0bf983c9c2379546a21a8db2dc1cf5561048117ba","nonce":"0900c77d1f2501fc38bf1878","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"36aa0ce556bf3f7a812db48362b24313cea9a32917ee3c712ce5af061298c94c672018de1820954f28fff3ea06","nonce":"0900c77d1f2501fc38bf1867","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"dae577d41090ef3442c9177a864a3f97e008dc4b3a8298446037b5d63fd7f694600e4adccb89ccc766f93e28fe","nonce":"0900c77d1f2501fc38bf1866","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"9e93975968263aceae597d9dad3f12e052aeb032aa465ab43536c602f1ce3b27d603549dc1e1b15a7da769b3c9","nonce":"0900c77d1f2501fc38bf1865","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"8cb0c1c45f69530429078ff816137e881cccab5ae9874ccde56ce7844906affbaf989b0cdbc5d8d2b55d102ded","nonce":"0900c77d1f2501fc38bf1864","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"52e5b982cf0564a0d7c81745d671e4bf5d750987c36529bda790e624c1f939471124178032137ac7eb995e6d62","nonce":"0900c77d1f2501fc38bf1863","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"9428068e5f8f20895c9e21b3afca046b05b9a1c49ca1f64bad548b3727dc91c886bfbd74d67ebcb661b1f47a67","nonce":"0900c77d1f2501fc38bf1862","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"c6c79e0ffac7525139c7c3b0e5a2ac493b9b3df4e3e498ca7c6921e723b0ce4071a8332f3ecebd72945d5d941b","nonce":"0900c77d1f2501fc38bf1861","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"afc53899f8e7002d3166861f28bc1ffc915842e90885cf0feb7b764c59612dc377b68cba0a75fa573c5c3f49e1","nonce":"0900c77d1f2501fc38bf1860","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"5aff9f64623aad877f74da88678e1700aa77f091284d7b116855820d971eac96f368cbe04f01cd1475558493d1","nonce":"0900c77d1f2501fc38bf186f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"eec5c55c0f0316598ba718be78efaecbbd93a7009b20ac076ad794d12241d02d3189efa05d094e0a5338393827","nonce":"0900c77d1f2501fc38bf186e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"ed0970e14b269d11b3a9e2a97157c25503bed830bfea441c884faf05f1677f8108302311d4960a5deb2a619dc5","nonce":"0900c77d1f2501fc38bf186d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"2a8437126f15e283348229579989ff4ae53af4509284bc5020cbc8b93e2c13547d85a8421416963eb4d0925224","nonce":"0900c77d1f2501fc38bf186c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"4a1d2d16a96fc7c1f292e364a43708477660afb20b63ffb3c4dc7ecbb2171439d57e632604d33d1da16a76a821","nonce":"0900c77d1f2501fc38bf186b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"22a118d44e495adc25a7870cd688f321310021aa79f9f90484fc53873eec7ac8821b23112e65552d7f40710833","nonce":"0900c77d1f2501fc38bf186a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"fc8b74a67fb3fde27bf67ea434d23518c9a610cefd6441b617aabe1d208545700b913ab3d45e5c9ae53d119c49","nonce":"0900c77d1f2501fc38bf1869","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"a1930531d2b3b3a6402220af5c7d489a1f0a108554be0aa1886fccc758e2b7ba8dae74a5b0011655029999590f","nonce":"0900c77d1f2501fc38bf1868","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"bd65e9d1b03bd671633537262a3dbe7eb96f9645d50d990b94d81c1a66c7fc6f7e6d2e3fa9931160ebad9aff7d","nonce":"0900c77d1f2501fc38bf1857","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"03fe8493cd8a085a5a26b9a69369788792336c1b3a8a90e9a90b67dc2a18d2eaff94d62c235166455e376ef5a2","nonce":"0900c77d1f2501fc38bf1856","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"8b2a75783d2720bd8451504819a4dc06f347807050202ccb39d1c41be11d8305d3e468d8d161cfe6c9fad63578","nonce":"0900c77d1f2501fc38bf1855","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"c5f6c43fbcaf3f9619f347fc1e379bdb883bda09121202ff1e498e9c5dfa075e02327596085fca2f24516252ed","nonce":"0900c77d1f2501fc38bf1854","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"c640a0c8431edf0c7bd04d20ef7f094fab0f89a1bda8a2f2a8ed8ef794aada89ff0007f40afe061827cd2fc38e","nonce":"0900c77d1f2501fc38bf1853","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"51821c680eb4f30ac0e2ef304e3d4acc4d13771f4d97cd61b473cef3c75b8273c4cac1844e755586c408e94f86","nonce":"0900c77d1f2501fc38bf1852","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"0a581d544c5a9ef9de070d8eb75d9ec599d6dc68557cffe82b2f13af95ce9fb4273cbd7cff1bd621f48477f78c","nonce":"0900c77d1f2501fc38bf1851","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"1fc4655706c4d0c2885c671e13b6835f778d1626f4cebb706735b7c91fe14982afd9739e852d09c43575b8ea08","nonce":"0900c77d1f2501fc38bf1850","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"e059b4929dac5fa269bc4d83058287d5b26d94d8699303a97e387b7f53359a25b2abe2a35fe4fa984288346027","nonce":"0900c77d1f2501fc38bf185f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"e41fa51edfe90ddb25115fd8ffd50bd805b4513902cf9ec3244f54d73015777558f252eb6ce83933d77cbd1a61","nonce":"0900c77d1f2501fc38bf185e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"b97fe766fd7989faedf48450a1f47b3b75d446bfdb4d7925593c96207b3b2285ab9926082e3f9846f40300e898","nonce":"0900c77d1f2501fc38bf185d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"cd3401da940348693af945095e1fad76df5504be1b984aae8af9978cb50eb811ccbe78daf18ad1e92c5d448710","nonce":"0900c77d1f2501fc38bf185c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"9665008985822d536ebb8d8c69d3396d0cc93dda1e9c97f10b36adf9c1de5e1b090ee5932b901f45914bc80560","nonce":"0900c77d1f2501fc38bf185b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"432492a524fb9d62b1e80326965502f28b871f0595f114ccdd556707af3399c4a512aaa76d8f4068079b05e966","nonce":"0900c77d1f2501fc38bf185a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"42a9e03c137558091b60e857c55e462918be4d119dfa1586eba12678cafce8830e0fc276fc13930be2252e8970","nonce":"0900c77d1f2501fc38bf1859","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"0e3e60145ef99aa6b281979e8193b6a95e3aa40ab2eb2680f1de871ffc041569e381631e03e6a8d1851c49f32a","nonce":"0900c77d1f2501fc38bf1858","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"6aeed44c82271b39926e7b851474cfa69d12fdcf2079c20f17235bce19e3a4ef6bf5674a507e998f27e614d46b","nonce":"0900c77d1f2501fc38bf1847","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"2eb6be3633842e29c1f8612aedbb3a4f2f6470dfbdef9c378c8f2c60f1c8799343c0ef2ebd6273baf9a7661b00","nonce":"0900c77d1f2501fc38bf1846","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"a166456b4820580d60bddf60abe01b9f7a8e213ca402e8ca6a84bedaa0f9a66899841a4f3764a134e7f4b62719","nonce":"0900c77d1f2501fc38bf1845","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"5737892c39d78e83771e7d13b8b4e610b5257d179d364c04a37031352eb1c507f04fb98ee569f85a82d2a43480","nonce":"0900c77d1f2501fc38bf1844","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"4acea1f2fabcc5a277247e5f3535406a3da86ebcd0220f72a7e39ff79f59a6423d7c3032716a56730c2e490387","nonce":"0900c77d1f2501fc38bf1843","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"bbbb8e34209288f5230cb121f2969a9699ef7163e421b9b885bb552662a45bdf16d88a09615df11ec131e30d0b","nonce":"0900c77d1f2501fc38bf1842","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"dd456d77573ea3259d3c76d8849001afed7dbf5299537452bc6f0a94631c79a6903f8ea349ce3d43c74e39772c","nonce":"0900c77d1f2501fc38bf1841","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"cd76a6bbcd89a526a3e4d7a76fc69f40de6501264bbcb1e8627aae04ff967c727fd821337992285d277fc54ed7","nonce":"0900c77d1f2501fc38bf1840","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"1513b9cbf5b48384ba591581902065849afe29f497c5b01b61e7ead5f92e62f838979071243df2e7951f592519","nonce":"0900c77d1f2501fc38bf184f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"59a82e6b8b08297253cdf6949db5779dec832630e763e8f09363fdbe1320ce2d165468939d127259f11992b007","nonce":"0900c77d1f2501fc38bf184e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"c33c5b9817ab342050adc92e600e02a629aaf9115814707d957628fa49032fa0bfac0f050f2314da8a41775bd5","nonce":"0900c77d1f2501fc38bf184d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"352c522877251b099e32ba0565c35243366c39d851337a9a8393b7f0ca7202e1720f4f5502cd20667e1fbec0cb","nonce":"0900c77d1f2501fc38bf184c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"94a627ae876b0358169ca37c5a629d8272c9ac8e1892881b13767d8bd2946102f67603915174b84012e58a0943","nonce":"0900c77d1f2501fc38bf184b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"2393b83b865fe83035d3836062b5a1de5da40defdc27590d63c70644ad8717976dc2bc5671a15444bdd5700239","nonce":"0900c77d1f2501fc38bf184a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"571ceb5f30183bded1d2ebbc741268d59ff67a9f7409383c7ba542e28c48c1ef78e68f950495446c9b552ea4f0","nonce":"0900c77d1f2501fc38bf1849","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"617dcf3d78ceaed47a0aa6ee938a7c616d490e8af99878910a9c949e742c6ef926df2d799299b93a35337fe35d","nonce":"0900c77d1f2501fc38bf1848","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"013dedf89ace324849d9d8e7c01f9e3e9063466736d0c9170fd3b40d26401f6d5794428a3d33aa7b2dd31e4a35","nonce":"0900c77d1f2501fc38bf1837","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"5de3996af239bb5c126cca414388a0d3425673773aac4bb3036537851df55e913e9c9acdc74907bbc5f1b55cee","nonce":"0900c77d1f2501fc38bf1836","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"56a4ca829356482b09be9c1f39ca704ab63879c11b4f15a29fb8745b5fb3f35394bc666076c6de2bc4db26d48f","nonce":"0900c77d1f2501fc38bf1835","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"414cf8e6f075dcb53d44fafbddaee491dca691673b0e4f8281eac758263d858e9b0733bbc8b5d4c72065fa2db4","nonce":"0900c77d1f2501fc38bf1834","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"5b078d586a8163805d1515aef4d5ebea094d24443dbc62ad1745c0f4b68621ee9a0d004b1534688cc939c7ad74","nonce":"0900c77d1f2501fc38bf1833","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"407c53928ed8f58fc42fd7849bdde15822742ee1d06738332d741f1a83d2a71bae815fe0f48d657337b2df4b27","nonce":"0900c77d1f2501fc38bf1832","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"1a9f66a6bf143ea9956883e079dc9813cfde5cd4cb25e42b2d8590c9ce15f28b477f439929cb74a5b1cb725930","nonce":"0900c77d1f2501fc38bf1831","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"0223b2b1097bfb1c349c34871dce5db34d90edb50aaac36082173e7687000b93fade85a171615323879e1fb8bb","nonce":"0900c77d1f2501fc38bf1830","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"0dec7b534c2bba024abc07b9496a261e9d31ef1b9f27ac23eb2c7d46f9b5a9150f6f5e60729fd13186eaf3043e","nonce":"0900c77d1f2501fc38bf183f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"ec0d5ea12abb2bfb05abecb330aef6f0b7ebeaf968a326a3f85e240e58463ce9a3e48cd41bad32605cc9276dfc","nonce":"0900c77d1f2501fc38bf183e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"adafbcf81a89d6697fa20a546d6a24263522c50f352bdf089db695e5497682ecb648e7222c7fa8c49659ecd1e1","nonce":"0900c77d1f2501fc38bf183d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"a46bd1455c118ee99d5c83741e1d841ca8c08a2eddce2d1ce9dc49c3b876d775206a2890a18d56ac48f704d4bb","nonce":"0900c77d1f2501fc38bf183c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"a0edc9888b555dc959eb0afc51e4894b42a9a99d70f650c0f6af58f6610d2d8086dc2d0c51bf5c5ec71d7cd05e","nonce":"0900c77d1f2501fc38bf183b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"2cda8e2dcb1e7d79f5fd2e0976737f8c09b94df47a7310e563e5383404c4f7360cd89c58e13e007a90ffa9e799","nonce":"0900c77d1f2501fc38bf183a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"0c1e8ce7ebc554e1958d0b9f455b12bfd48865e953dd6975ca524a0f23634568c6c22ed4b1228b4cd85fe05081","nonce":"0900c77d1f2501fc38bf1839","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"67c15bea8401e73e378bd6934aca48fee7af438a9eea9b0e0c8c77b3d30d1e04ec57255840afdecc796148b556","nonce":"0900c77d1f2501fc38bf1838","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"8edbe136dd33321058f6bccb7ed0719f3147f04380931a69b018f48b978d37946c0ac5f9731c301f7a476cac80","nonce":"0900c77d1f2501fc38bf1827","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"6e8199e02d9339f070f1cfa873c4f475111733da81473891b3fdc323ff0569aab44f4f2b14549142d08c90c3e8","nonce":"0900c77d1f2501fc38bf1826","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"a7d34e2ec0db92e43d65687a4472187735659a7ab17745dee41a3b803c2762014affcb2e0ffdb8600265454a10","nonce":"0900c77d1f2501fc38bf1825","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"3b32e0e33301b491a1d2c9c2ffe9efa1a2ff5bad5414f10c705519c2917f12c30123fa8f2819357a712c79f94e","nonce":"0900c77d1f2501fc38bf1824","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"371afa946d6c206647f9db989fcd6cda8578955236a4854ca4a240f8f4a9f8b508c5849e03350faf720b9a4da2","nonce":"0900c77d1f2501fc38bf1823","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"53e1c64b5a6519066911a4cb1cce6760850f05f09649bf59c56a451bbfefa8215975ecddf191d380609096c14c","nonce":"0900c77d1f2501fc38bf1822","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"1338411dc4c018164a4e73c067f902cc156cbf1171804887e8e4d0e6a11758005fcc912df3b74a014556eea083","nonce":"0900c77d1f2501fc38bf1821","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"459dec557b5ee0b3d8121fbb22518d3c54304ae6643038c3c75d8c75dd45e709d50d5a2a9d4b8f5717feb8b87e","nonce":"0900c77d1f2501fc38bf1820","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"c1180341b19919c5509f5b4d7537b9b0615196bbfe0ea4904500ed78c0abb7a0c5592524a409d4119840867f71","nonce":"0900c77d1f2501fc38bf182f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"5b17fd370f165840898213105f28a9e6f5c2fe4c612f7bfefb74123e16bde1db479dd53f20d9a82ae85c4e66c9","nonce":"0900c77d1f2501fc38bf182e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"53830282f1530a6436684a37b492bf55b23f7afb11767d5d9dcdce1821fd644ab7701a43d40457bd305b6d0f45","nonce":"0900c77d1f2501fc38bf182d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"ea506050f6cd9fe5134ac0c966b249c8710de0951be8fbca1ffb3adaf097c905c3485d3afe02673350d9fb650f","nonce":"0900c77d1f2501fc38bf182c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"27786efe2906bab177d5d078e927960d655970144c30283c2972dc2e64471f0e498ea260a9e7d011e40901ccb5","nonce":"0900c77d1f2501fc38bf182b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"884d838263e8b525a1d75d87944b5f67624a403ac638bc2f21c6e77c0541c62fe0d47caecf143bd82dc36934c1","nonce":"0900c77d1f2501fc38bf182a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"149dde680c7338b1ef06c50c9b37877777fbba534c02b548dff3ffa0f2774674ce7781e9230603ea75ea4341a4","nonce":"0900c77d1f2501fc38bf1829","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"387abba2b83b9cd7c0504976aaafc1492bba62da2c1e31ce13178c2fe06e88764bd48071440b53500054971771","nonce":"0900c77d1f2501fc38bf1828","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"878a2e992536bf9a8e9134c85882ff06db075be0f1456dcdffaff7e6bbd3b2a2215ce66e8493f7e1450b7e9909","nonce":"0900c77d1f2501fc38bf1817","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"e6a820455b64a43c6fcb4da783050b252a241e9d0d5ee765e36997c445a97a0dc7c96e29f8547111900bacfe5a","nonce":"0900c77d1f2501fc38bf1816","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"31f6e43fbb11f054fc363e2e46cb588edab8fc642014e904b7843034e1217b5fcbd406cb4d10ae8aa1610099b7","nonce":"0900c77d1f2501fc38bf1815","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"7edba07c6a71a137f82a7b9fb15b0dc035ad278c073e4b3f39e9741dbdddf3b6924593bd418ea733cd8f308eb0","nonce":"0900c77d1f2501fc38bf1814","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"22d700e62d29ca563d94df8e3b853f94871d2fe10d00e21861b2fb9f412a7ca3488556e6c2e3966c7d03e53d8a","nonce":"0900c77d1f2501fc38bf1813","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"1e7fd58af1ece9b1daa55b9c0ef2de81bb65bbf5884309f6adb5562a297cad854a7e92f67ae7a3875c2c1fe717","nonce":"0900c77d1f2501fc38bf1812","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"b3824f0f4a662083ace73c3a2b724f6415c23aec89e6d2f43000ae6fa4c8a74966d041368e434422c9462243f5","nonce":"0900c77d1f2501fc38bf1811","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"dd1ffb0f2077f6b874783084cca880f42aa6273341063c950931a2aa73dd71324f4ff01c5f3b35a3b40b807fb3","nonce":"0900c77d1f2501fc38bf1810","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"aef6e683939e5e199b37956223f36e4ff10c897194ddcd2c160cf8f54033e292580d304e8d9cea9bc299ff9a48","nonce":"0900c77d1f2501fc38bf181f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"2f6a5ca7bec16067d68708e9d12b271a7f105d6fa3c744dfb2aa1c9e36251294fa9f646fe4738f0c9d0559cba1","nonce":"0900c77d1f2501fc38bf181e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"81534ba8631d9e79d61bf424c3ce4f0a01f6c2e1ff5cda1834cf7905db05327c55952058e61c2afcebd1437a7a","nonce":"0900c77d1f2501fc38bf181d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"e105b293762dc19480c2825a6fce6d36f5cefb2131cb638061771aefc62a2539aec549205d13ba11b124ee39e6","nonce":"0900c77d1f2501fc38bf181c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"c1b3d85ce0a5f1755348a25f42126da107bdfe68e5e1b7aa56567ee0b757c6d94d568423e005bc1fe1eca8cb62","nonce":"0900c77d1f2501fc38bf181b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"e2bebe2a8012fc1fcf92829faab15658393d7859c80cb7cef26729e699921760a8538af5057d060a91d65eeb28","nonce":"0900c77d1f2501fc38bf181a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"aaea1296f4f0d48b779802206e9deff4dbc54386380f5118a04a7a54bcbed030a4de0aa40a5d294cf5fc686a52","nonce":"0900c77d1f2501fc38bf1819","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"ccaf270ee703c63edd3cc5326414bc8d6375672ce3a0d2c914ad1700027a27890762eedc938751e6366c3b51ac","nonce":"0900c77d1f2501fc38bf1818","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"68f2fa3f1b3e6b8715cb304790952d1363220640ec50c677198b0b384ea26d103249fe91a0c447ac174f0fd409","nonce":"0900c77d1f2501fc38bf1807","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"5ae776e8871115fea964f681be9411f087057ab727e9449a7041cb650da7dfe113d224e0927b9e4ed7d4fcb512","nonce":"0900c77d1f2501fc38bf1806","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"676edaf0820639437aa76c39f2d36e510ff36f44d66cf927c09a64e9d8cf4d9bd1bb6f79362714cb0a9836b744","nonce":"0900c77d1f2501fc38bf1805","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"0a012cbaed23e72688addb5753fb534061e8044ace9fac7f2a2c84d0c5634aeafdaf1f7731d11c8035c1ecbab3","nonce":"0900c77d1f2501fc38bf1804","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"6a1826a5daaeba789f9ae4d5f6b354f3d1d4c852cfb9923af051855384428952aa472e88db55149bc26a3b7875","nonce":"0900c77d1f2501fc38bf1803","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"1cfda9cfa0831b3d894f3ca5db0558291983e70d143a8cdd37c32b4212f8f87bced79924f6564c5e86543719fc","nonce":"0900c77d1f2501fc38bf1802","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"8f3cafc32c861ad716d7b1f4c24efe2a712941be402a74fae9b550ba38516a065c806327cad5415e91c1ff3f03","nonce":"0900c77d1f2501fc38bf1801","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"f3c0606c66f985eec6d55e7d46a9982f29c42989daa8238b2ea2a2571d975a91afc953b2f3e7f32901d5ee0eb8","nonce":"0900c77d1f2501fc38bf1800","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"9c242050ddf0d0156f949670e9b9e4a3c23169974f7b4075df34201563c02d93624a01c19dfae4da788972d6df","nonce":"0900c77d1f2501fc38bf180f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"d424bbc65fec49ce8a0a835d3d5b240efd04b089279cab990cca5d976dd240bab2494ddb9c0cdc0ecd30e39d11","nonce":"0900c77d1f2501fc38bf180e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"cf4568ca548247975a63fcbb01dcb22be43972a8c8e011858980bb3d418bd98236389c8454f986c393d90b9e00","nonce":"0900c77d1f2501fc38bf180d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"8310dc36312b740fd38766c52d46b0b9d3f2fd63bfd94c4cf26cd51a3e7cc9be7db08ec5498a928e7f1c51a5bd","nonce":"0900c77d1f2501fc38bf180c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"f6df663b35597f4ef952392ae982d142bafb42a373bfa2350b97d35357cc612bfd38f0d8047c02a883a3bb9612","nonce":"0900c77d1f2501fc38bf180b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"d1d93f57163eccf613b59031ecc986d3c9e2269b7399842aa04fb5ab90f21594d3763e07b98ab81cc7862ea08e","nonce":"0900c77d1f2501fc38bf180a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"ea88aa09fbdc94ad677c891862d9083d136ec7996d70af50e01571fd837bed934b969fd9a9683a03fbde4e34fc","nonce":"0900c77d1f2501fc38bf1809","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"89e9ee5013cab265eb24cc6ad9fc7eda3c42bec2ea409ed6a5e3786b24a4bd867177e13f0ded3ba79763653d85","nonce":"0900c77d1f2501fc38bf1808","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"a4eb0234723af59ba05e55e5ff4c2011038d04b6bff573262e8ee14b4c5628146979c6e318714a11d545e09ca7","nonce":"0900c77d1f2501fc38bf18f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"0f66e64c541373496fad8e2769d057661718a0388b72f7dc3648b23fb704806284559577c49b8f2088faa01699","nonce":"0900c77d1f2501fc38bf18f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"5492e0fa61ab1416c25d1039df7aa405ca037ac9fa4f7d8b4daa16c8846e9ee1131ba52a1a7ca3cc192453b3af","nonce":"0900c77d1f2501fc38bf18f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"ccb897c3a71368b812dea4216c82496aa8611c9bcda2cc31d5fc0ea6a2b922e133465006c05324587c733bd8c7","nonce":"0900c77d1f2501fc38bf18f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"7e1e3207ea6dfbc09cace242de6b8f7fd0eac9b6e6582ffcab6f77ab040a6dda4f89bdd3f12b892a23a1a34161","nonce":"0900c77d1f2501fc38bf18f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"4fe40165003c679b03df34c84f91c4b40f6ad3d39a6e0004b3843d1b1d97824b8dd0ced76674fd46c798be11a8","nonce":"0900c77d1f2501fc38bf18f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"2da65a6b69619df199f41b835e8667250ed600b14c90de679af5660fe80a548955a4d4c170775f91892f8f0c91","nonce":"0900c77d1f2501fc38bf18f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"18c783985ea410d29b07b36c3a780e6f14d2b2fe60f2611964b1b07e0dd07b683a74cfe2c292086cf3d71c300c","nonce":"0900c77d1f2501fc38bf18f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"27b140d508d24a4d39b98b084442dbb757842241680d8ed21fa33235cde8be74fd7ee3f9d37c9d254cc018ecf9","nonce":"0900c77d1f2501fc38bf18ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"c8f3a4303f81f63a5ea9316da7600e3a5f9980685154925210e5b7215bc60439430667e85ec3b1b11d79a2a046","nonce":"0900c77d1f2501fc38bf18fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"98f2b7acd60e1332071ce2e37c1281a124712d8006a71eab8e8e4596d71b80d5c5b9f1275e22f36100acc27fc6","nonce":"0900c77d1f2501fc38bf18fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"9610f4c17afcda357430a86ab0ba4cc5918fe6acb300d74b93f5ed60d3bc22527949bfb540789ad1dde8bf8a61","nonce":"0900c77d1f2501fc38bf18fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"b2e87cb7c5aa59b132c6a0ea0fcc1eb1be9c0e478975860653dbc8633ae9a9fb2315ac73e8c6b081f6d8022462","nonce":"0900c77d1f2501fc38bf18fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"8fbb2c1251358177c1d8138e26ce94dd49b0e6001243348e227d3604a5bcc5f27daa3b174aefc5229c894f0f2b","nonce":"0900c77d1f2501fc38bf18fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"fd8d0b700d6694885187c3223a86de6c3bf4d1a7b12d177ad3c62fe12387453b524acdf54bc9b12200f9f3369c","nonce":"0900c77d1f2501fc38bf18f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"fe3695f79113730c77ff78828f0dd1d04a6a1a6d7d081f89e852bdf2ea5223d734bf58218bcf2e3d116f7f9490","nonce":"0900c77d1f2501fc38bf18f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"226792329f0e6b5415595eccc86806dfa7968e54d6c3c56e821653c5a25377010738cbe8a65365ecb3980b7a86","nonce":"0900c77d1f2501fc38bf18e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"75ed98bec384511b23e7bc7441b23dfa553fe2708738afa95b39a248a9b3642ff89a2df54e8b994992ba6c070e","nonce":"0900c77d1f2501fc38bf18e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"9b97eae6b8beb6601e406375bbcc780a55bd694fd2a6feb3acaa4cb92baeab4def61aa4fe98cbc2d1d978c40b8","nonce":"0900c77d1f2501fc38bf18e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"f60ab239ad1173f60bdddf4c8fa1c1b8fe2f9f59983ce09bcaa54dc4420a57e1c75532e680c488ceb22dcd9681","nonce":"0900c77d1f2501fc38bf18e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"3eee434adece140a7cfcfae114315b3abbe06c46ebee5dd857841d44339e86e83b5780cda0ec912c41eb074c26","nonce":"0900c77d1f2501fc38bf18e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"d4ed2a234cd383f2125e4e50f08869c152e6a4209b69b88b26e611b655c376e4b6c3fc8441ec9d49bd53c0ea6e","nonce":"0900c77d1f2501fc38bf18e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"f0d97f4ee4cd2dce5650c9a618282faa4607864e55d8f339a5fe82e6f46f9e2a235033f12dfcff5b9786aabf8a","nonce":"0900c77d1f2501fc38bf18e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"acdb4b677ede05faa9376ff3f28c21fd32d08023bf7109168fee6db8271a3388f7a8ab63ec6f67a09b31e975c7","nonce":"0900c77d1f2501fc38bf18e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"d81dfd728d58e3aadf5ac5c58464510d07e1fd4f1a3cb46e1ef76b498a3b8a1ef0010bd02570baa7c3a8a4a368","nonce":"0900c77d1f2501fc38bf18ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"29b263830d85b19ecd9f3462b013d09a1644c0a825729a7d05e9d971a5750a470a4cda5b334e0a6153c7135638","nonce":"0900c77d1f2501fc38bf18ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"023addc77927420f02a5fb23fb9783a8b8afa554cb66260baffcd7d74630d633124930f7a445be34fc057062ad","nonce":"0900c77d1f2501fc38bf18ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"7a0a9c6116a885a943f17ad0fd639b1415614d72fb3fbe332ebca569f5b7fd3e8e88e99b11ed49f0c4a014eb9f","nonce":"0900c77d1f2501fc38bf18ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"3c304bce97332d91a902e32e32052bc1ff1010c4c7e08d15a136e3358f73cbef7877928978879b877e09c8a98f","nonce":"0900c77d1f2501fc38bf18eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"5e27300e19b63ca1ee945e8984de373602a8a36ef1bb2ac1b6f1b0d26e75c1704942f9292db9e69e5628845573","nonce":"0900c77d1f2501fc38bf18ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"1c1a1dd01548a37626e14ad00ddfb73be10778ae930d56fe70306b8d0c5627dcdf51ab2cd0f5c9049b7673a083","nonce":"0900c77d1f2501fc38bf18e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"d98b39ba6ebcb5f831fd8dafd602892a0ebb2ef36bee7f32b2e24cf4bb5c11e73dca65c31d9f9bbbf4524a23b7","nonce":"0900c77d1f2501fc38bf18e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"e70a14a09ef5a193acb802ee040b2165506cfcd21cbdcd706d33fa179a8c06919124f41fd075aabdab373a8227","nonce":"0900c77d1f2501fc38bf18d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"20bd322a543aff5d945c78b51ad5e99860116f2d6857814b373250fae9df054970d42d4a32ed8cafa3e91c7556","nonce":"0900c77d1f2501fc38bf18d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"4809b4cfd54ae9676aefa7eea4893c36ef6f651033bd0892a0cc462018e7862e48b6fd878180b0f9a7d4ab2970","nonce":"0900c77d1f2501fc38bf18d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"43c8af6101b1e5bf2ff4733b5d85404e61966c790f42516a1f749f54c45a1e750ffcfa0ab35a75c29a0027e0f3","nonce":"0900c77d1f2501fc38bf18d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"cc5cb0e961cb127666f21a67fc57197c16e4a310c358bc58586fa48f8cb79062f140b5c092780407c5dc5ab532","nonce":"0900c77d1f2501fc38bf18d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"7ff326894cfeaebbba86564125039c7073c0e1419ae6b65e2cbc1ab77fbf93aaca11548c9572cc981b78e5a681","nonce":"0900c77d1f2501fc38bf18d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"ad8bd34a4cfa2a66767a339b0860f500a295713c7928343f80ed020823bfe4397c593ad680ea007307daf5d376","nonce":"0900c77d1f2501fc38bf18d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"c7688331b366241404f3c0421645ba24533f8ade00e8d2321b5baa0f2fc017ebc6915d27f63548cd48840f8927","nonce":"0900c77d1f2501fc38bf18d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"574cdde3ce0aed13ff74b38e6867c6b932b96d42b9518eb140f0a02c2f4a5413ae68c7362247827b9e0eed0f45","nonce":"0900c77d1f2501fc38bf18df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"c8f0e866b7cf63cf78458d740b5633ab4cb9d3af03e3156f09faf4e73a4262195fc272860e391d498ae9fed123","nonce":"0900c77d1f2501fc38bf18de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"98d2644cd671583bc0330491c3cb69855511e9ce7062b3b20f29811d8df413dbf40c21425f9c22898d88cc4b57","nonce":"0900c77d1f2501fc38bf18dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"32b380ac2ed05d3b3fa151fc8a1d420e942b61de5fa5d6f53ff376e2ebb4d1225aa25278acfd21f95b9cbc3b81","nonce":"0900c77d1f2501fc38bf18dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"8d186cd0509e4488c1bf3b76bea395a2af57240a5e8f5782097f55f7dc3b4826215dbab89904b501440af544f2","nonce":"0900c77d1f2501fc38bf18db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"250a10ef4663d9df2595f8cc86e98532890f4ea8bedb39ee108ceb1566cb49d7d163c1ce08d73d8296aa0fe3a4","nonce":"0900c77d1f2501fc38bf18da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"5c0679b7565671a98c2cd3e78f722061609427873ac56f543865573e08d60f76b476726730ca8f47109c43d9b8","nonce":"0900c77d1f2501fc38bf18d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"88ad8bc018b9a73cf6f4569f0091d43659166e2d40437ff324ba0be5071b5ae70196de180add27c9afe64e79d9","nonce":"0900c77d1f2501fc38bf18d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"e1b06463b10716a235305c138262be2c651f6cfeb6db26e0ceeac55aa2e2cd7585c14cc39cd6005aef70275baf","nonce":"0900c77d1f2501fc38bf18c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"076efc2f89cf446c79814daea4c1872cb0d175179be9fe407625356a4b09d344dd50d2e166aa43f6182501cf44","nonce":"0900c77d1f2501fc38bf18c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"0b31d4fd417019f1df75bc11ff35a25db26c17e9c0a6426a8a5a43f556eb52da03d3f89c62409c12c11c8a60e5","nonce":"0900c77d1f2501fc38bf18c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"abd6932b7c51e212079ad63670d6773af823d74a8fe91b38ccc7d07df4cc1d35b4438fce1b08fcf67b957b66fd","nonce":"0900c77d1f2501fc38bf18c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"b9c8e0a57e33e778ac10aa0088ec4f9b71f597a97081c91f4e814c813eb0a0199974393adc314c31ca1a1cddd7","nonce":"0900c77d1f2501fc38bf18c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"baa6987117fd1766cede66b1369b6409851875620ac129c3914bc1c15fc6df5f20eb104d2cd6ece1da791d68fb","nonce":"0900c77d1f2501fc38bf18c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"72d9f71ccf9d2e99758ee29cd5b6728b83473d3e8dce66538636bd8005f9558db8268bb79458e42efbb597afcb","nonce":"0900c77d1f2501fc38bf18c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"091c24ec0a039c60fe4caeb3e09aad6b6fe954c20dd3ca0357c33d9cd7d6eb4c36f418cae524f549955dd3480f","nonce":"0900c77d1f2501fc38bf18c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"edb5349e3654a8bc6c831678c948cd521cd1b9f0a5e032122f0ee432aaa186c71a7d5ace0a7d66574b8579c996","nonce":"0900c77d1f2501fc38bf18cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"eb61ae43c17fadd4ef2c133026a6bdfd66baff53fb1688b47bfa201ffea6ab39a70b87f5817d370a0b22eaa76c","nonce":"0900c77d1f2501fc38bf18ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"c71cb6e7dc4400f73b244c2dceede74eccf2e93f3f5f0f4ea96b856fbc200ab6e4486ee9bb7b3112b5e4cda189","nonce":"0900c77d1f2501fc38bf18cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"2eeb6cad7629f680d78ef34d0b418d112b491a78bf9de73cb85686ee680df359c984d9c9967e1df424957739d7","nonce":"0900c77d1f2501fc38bf18cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"5c1e1959a7e34487f401ea21c703d766cb9bdbaff60cea58df3466fe925659fcb9d10ccf13e437234e9d7465d0","nonce":"0900c77d1f2501fc38bf18cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"15568fb0aca057477a3f91ff096594529f63f5acb1fabb1cd1fc95b341be85b7321dbfde654bed3ba10811ea09","nonce":"0900c77d1f2501fc38bf18ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"cdf2b2188e340c2f617721178ccb93328841d03061664f58308a3b3e50785ca931ac04c49894f7ec777ec3643e","nonce":"0900c77d1f2501fc38bf18c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"da7616a5c365a4e3975f5148646fcd7adcc7478139b4289e088c812b84fdcb4b304d78d672a21d1c1d5a67e2f0","nonce":"0900c77d1f2501fc38bf18c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"f1dc41983e8721c67baa79cae24a9c2d4268e16aba5937db0f15f6824201c5322918b355552212566318577eda","nonce":"0900c77d1f2501fc38bf18b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"9f9c3df2079036215042a4cbee4dff96465bf47e671cd6e5a8e5a2dcfa4d83d9cbe289175e5ec24d6be102c423","nonce":"0900c77d1f2501fc38bf18b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"c88b4e189fc2abf60790dd9546b6432dde0ce28b9b2bcd3d73c19c989dd2366e1a871ba5b5b3b5600944cd0810","nonce":"0900c77d1f2501fc38bf18b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"0979308d49d95344d5256ce11892df7e9656c44b7ec58fc3fd1f086481efff52dfffff05f56d2e15154518bee8","nonce":"0900c77d1f2501fc38bf18b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"088b3777432400b4ea57f442d89300084dea9a3c7c50a25dc176ed5640dc4b7e02adbb282e59b937d8e76e9386","nonce":"0900c77d1f2501fc38bf18b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"3f9cc740fccfc606f25069ad58690cad44041da0872ba4bd5a491a1be35dab31a657528a2dee3b410589c8111a","nonce":"0900c77d1f2501fc38bf18b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"f831accdee92296318f7e3c5c4975f54e4264606a7a64c3de42e2caf9bbce3685f90ef54259b24df5c2b84addc","nonce":"0900c77d1f2501fc38bf18b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"249e5a8bd0d175eef05eb97aeeae6c38fc0fc4fb78e21ff67509849d87077f40903675dd1be3be437bca9b06da","nonce":"0900c77d1f2501fc38bf18b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"6db33d68de8b73149b7ac4d3fc38dd97eefef2fd125193f0f9741e7671543e881a15b12b55d258267018337c69","nonce":"0900c77d1f2501fc38bf18bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"129d30a870c65e8b5464ba9c6ec013b7c3b1a0429142747d7d47021d1a30d01747bc428ccad4cf94533d1bbef0","nonce":"0900c77d1f2501fc38bf18be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"e096c37d293b99443d85f0343b0afae53de178f76f7a1ee50d4a3eb19eb795ea82c172832559168000f1ac8eeb","nonce":"0900c77d1f2501fc38bf18bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"602f0c2fc1876b5d8da20f08fa189845b87237f1e43f24f19d8ebaf76dccea54a5be981043130814c1ef9ddda4","nonce":"0900c77d1f2501fc38bf18bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"0e8bbb7e4c8578212b16e583492c925a6e585ee7d9708c4c269cc836f318438d51b846702f1d0216082eee9137","nonce":"0900c77d1f2501fc38bf18bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"ab7e29a255749f25ee21f894f7e36940f01895ecd48e5f78f854ae15b9ed0006dddf42c7ac7846bba2fdab135e","nonce":"0900c77d1f2501fc38bf18ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"24d8dc5fcc70e5db56e0f4b59426b51b9245d8be7087c02e9145402d6cd1b767f0625128b6960c299cadd6f2e0","nonce":"0900c77d1f2501fc38bf18b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"cd21144f7d2d36507d22d44e81dd1bc62438b3c69bfbd62963bcc3cf718221a5ec80652781ca2f10b2c8ba70ff","nonce":"0900c77d1f2501fc38bf18b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"d6dc3133ba1dbfb3b1d1641a8dc84f2bb0b6986e11097023d8cd78eaae0158fefb82b0594d70936c0e6697bbb1","nonce":"0900c77d1f2501fc38bf18a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"c8783469432e0e7db65cd575b3d6716a9b5b400be85ece74c5b9a79092838f6e331eabad0789c97102e52babcf","nonce":"0900c77d1f2501fc38bf18a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"3eb43dcbf89f2faa4d0eb91df4b3e19a38661d9dcf5a0b0237a3f3952c0c0bcfb0fe79d172d0c5f5d96fc663a8","nonce":"0900c77d1f2501fc38bf18a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"39efca895f1d6379f3123eeb3bc970ce5cd819d73cc370e5ff49473dee8cae136d7ef6de8aaf98b00b9f788da3","nonce":"0900c77d1f2501fc38bf18a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"04406224a5489174e03ed74413b1c011eb1f0f95414561165b9ab20802e2dea874bb6c19cd2bcbdf3abb772e74","nonce":"0900c77d1f2501fc38bf18a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"86e3ac31bd1595472aecb3014e9fb9878fa3805b55bb92ad744a774d88ee9f2a7f361e6001d986cf13c29c19fe","nonce":"0900c77d1f2501fc38bf18a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"33b20fc560d2f775c58a2022fb55f8657594de8ea3b7837db942f65222fda1f356f13a858ff9f076757058f356","nonce":"0900c77d1f2501fc38bf18a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"07caf692f8937e99331696559fa2162a841271f91b4e00a3c981c936472911cbbd28677fb4f5155077914ec0b7","nonce":"0900c77d1f2501fc38bf18a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"765e87ab227e54b80e5c812adad637b0c53d9a16fc8bb0e4bed83c555ff6e6ca2b95c31251439e16cfe68f6f92","nonce":"0900c77d1f2501fc38bf18af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"36d144794800f68f4d1b97761ae73d987e1966726c6787c944e03e65574b655f9e2290beb5629163220b9df735","nonce":"0900c77d1f2501fc38bf18ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"2f3cce2893ca3367813bbf1f1ba08036f8802cedd376269dd1802866637ffc7844e7e459feae13c62bad6ff449","nonce":"0900c77d1f2501fc38bf18ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"484eff8da9109536ac16e1e718c3badebd5fc7c6d3dc9a46db561ead94ba7e4b2ea644add685b0d45ad45484f6","nonce":"0900c77d1f2501fc38bf18ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"c44c41c4c1cb218419a1ce15dc6a61dff99f56664ffc32c1ef591669600a38c73eb750adcb054bb5f732d191b4","nonce":"0900c77d1f2501fc38bf18ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"7084f54536d228e79fe76a2be604c2c29962eef126efb10a21ea39145985205d0532ba47cc5d39161bcd74323d","nonce":"0900c77d1f2501fc38bf18aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"f0548a47f95bbfae27b7a9acd4716966be96b4da26af23e1a6e77738ef3418f6ec83a772092bdbb1f169a6ca0a","nonce":"0900c77d1f2501fc38bf18a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"3b23333757ced1a4106673f10200aef4d4f540dd0f9c3b66b3efdd1c7ffa74fb3a84df7c8ce1828c3cc2375db4","nonce":"0900c77d1f2501fc38bf18a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"57d9b76139d1d93dcd423f4136fdb441dbbfca9e85084d3b166e876891984760eff08246861bba735bbb2a099a","nonce":"0900c77d1f2501fc38bf1897","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"7e02d3ce8e7341af76310b02ae31ac39ee21a8bb0b451459f2a3f748250a0f8f2ad35bee603293f0a2660d9b5f","nonce":"0900c77d1f2501fc38bf1896","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"49f4d20c1e1c0f8bca3defc4dcc9ca38ddc354221fa49fd72b3e31e2c752c51771651f1979e5ce2af20da6c519","nonce":"0900c77d1f2501fc38bf1895","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"9e260fc4e700fa8264779d5006a5f5c90617114744e3cf515a575f1266442d6aa60df6d8a3fb119e7ca34c2cfe","nonce":"0900c77d1f2501fc38bf1894","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"7e3f079a8c1c76bd42c3f1fd5ab90ada3d1337ba72a68acb0b0baf2cd0c0b6db1cc1b24cf266e46b62e2d617f8","nonce":"0900c77d1f2501fc38bf1893","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"b2b562d3994ddaebb33b770b18bc0bed5383ad00ac2d3becc1b5bb013bdd5c93a101a1b7849bdbb95ffd89ae64","nonce":"0900c77d1f2501fc38bf1892","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"ed6339551fa3c9ed419a3ea7f9af5b1b4938b653286e678879006a868f7518d74f65f240fafd9714c9195240b4","nonce":"0900c77d1f2501fc38bf1891","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"2b3ee83886bbb94c81046a36236e17f5a8f9a4eb93d00edce757fb280e5aa3a088c8583359881850355493d75e","nonce":"0900c77d1f2501fc38bf1890","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"70d83c0cb42c086732d8be00275837ebb3907962be93182d5ebd46a35ef99f74b48a99575d6f0794d04071c635","nonce":"0900c77d1f2501fc38bf189f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"abf283f76fc6383e77fee1e7d7ef9a0739414fcad6c202030a1a57383d347328981e21d182a717af418460ff03","nonce":"0900c77d1f2501fc38bf189e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"4d68593b4ce24f144bc75f51eb946e8f5303bc3182efd8c33ef3ed23721bc62f4e2b461ababe7f9555692dfbe1","nonce":"0900c77d1f2501fc38bf189d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"1835766bfa54ff3f917d3b27249223e17b3fa4d0ec4aa2d25b8da4003b6bf37d39266de5d25679785c7eeab8c1","nonce":"0900c77d1f2501fc38bf189c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"f0bd4b948f2017fe7b03f0bdaf3f4e33eca51cc6a2fc3d879f3a9cbc7eaaaf6ace5583e6640df058d9e1cfbbac","nonce":"0900c77d1f2501fc38bf189b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"532c7e0f5675a3caa0a1ddd0019ca4de48dcb4091945483f9bee698ae559d8815ffd76df78b3eab9eb09142fd6","nonce":"0900c77d1f2501fc38bf189a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"6cad2a24438546f3e018cd78564dde8d6d486ad965a73e8e6648ca872b856ef332b9bb4e2044c694990810ef9e","nonce":"0900c77d1f2501fc38bf1899","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"76d1d9987dbf3ed73bcf27a186adafe9441a45c9b4c25ae029aa37630cd96f0d354e371e96d1348a8f3fc59883","nonce":"0900c77d1f2501fc38bf1898","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"33c7fe8eaccbfb5b87f171bf079348836c3fd5e51099b39d4e6b3461eb85fbd7eda5e633dcbeeb115b27340e1a","nonce":"0900c77d1f2501fc38bf1887","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"84ace3f220ebebcaec5437f9170079b53f91c583ac9c953570bb00fe6b31b3b25674ce9de29ef0106ff3579d24","nonce":"0900c77d1f2501fc38bf1886","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"b030484d7436f7f0f7ef8b7c699cea8b6dd9384ca8ed437e006b40183714807045924348c37c5526ff2d276210","nonce":"0900c77d1f2501fc38bf1885","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"2312aa76a1e0744cb27e112ffb4d3343dbaf5a3d29a0e0864e40c3b13b95856744d70075c1c7ee5744d2737c60","nonce":"0900c77d1f2501fc38bf1884","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"a8fbc92da0875aec34a8083daa4226f536f33a2146849a18b8fef0e59ec23e8f32c691d2f77f2f6458cc364e87","nonce":"0900c77d1f2501fc38bf1883","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"cf9c799707f53145129f40e375af102963fba8bfb8221062f8aa8662022d21ffedcc126979e64cb2d47ec1ee84","nonce":"0900c77d1f2501fc38bf1882","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"3d174296f1b2205bd6cffabc061e83b6a7aa86c17dc8d823261ade931f368ab312e364d87fd9c3b87099b66580","nonce":"0900c77d1f2501fc38bf1881","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"5c13c49ca16b0b596990696329671e28d9be4ade593f861d6b470848a5dbf837dd05f32cd0dd8b2b7ed308059b","nonce":"0900c77d1f2501fc38bf1880","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"62dcb659d11412a5bfb6647f55b36eeb652af81d92bbeea3b6d3164582f5f5f8fe49c3879dd2a3b76eb5ae3d6b","nonce":"0900c77d1f2501fc38bf188f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"a8551b26942b12ae8d5d41b97ef074464b2a986bc99be660c6621f48bd0ba616a673d7099818d455ee4d723388","nonce":"0900c77d1f2501fc38bf188e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"fb406937da4513695f5dea5db17afed1559e088b13e70c489ebf97596b41f8ab551d0d4e921fbb67cb4cf6010c","nonce":"0900c77d1f2501fc38bf188d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"c55498719aaa4f8df4d8f0bcb2ccbc9b6f359421e5bb66dc473c0c360dabdc90e0dcd543bf7520cc3001b4ebf6","nonce":"0900c77d1f2501fc38bf188c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"159a8850f2c098ca9f9b1ff7dfcf2bc66fbd63d26688aaadae8c1e698b1b86e6cf2e7a0e2ae1bae0794905e871","nonce":"0900c77d1f2501fc38bf188b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"981cbc4efec9fabe0fe94827ad317bab4a3d7d190557faf41f0fd953e9d3a0040c052c37b3979cd30a929abc95","nonce":"0900c77d1f2501fc38bf188a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"919c79d9107cea7ed820629613710a9684893019164bbd15d55659df633e64ca317d6988f79021942364c59d25","nonce":"0900c77d1f2501fc38bf1889","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"d96e729582e4a9c20947807c3e7f21985c1f81dd6f2ae870f08d72978ed7f4d8cc17bd7f7d41ddb62eb6af9c76","nonce":"0900c77d1f2501fc38bf1888","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"08fd1332b411fc53877f3723ac58678d47ec85ad800cd9d9628954e81983486138f6b2a59d060bcdac397443ee","nonce":"0900c77d1f2501fc38bf1977","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"589a236e883fa685742eb5ae6420a7798afe2148ab7902628d9933bf7ad822bc"},{"exporter_context":"00","L":32,"exported_value":"3e1b4fcf263b7889f72f5bb27037aafef052091611b78b42314f92aaa4a2481e"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"405acc3d31fc8db0234dd4d5e72117ae1c4e3ad5e6cb0267a5061dc12ee83319"}]},{"mode":1,"kem_id":33,"kdf_id":3,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"8bea29dd1bbb6f23a67e4f3f36d056a7286ceb46d8c610aa543ce81fcbe1743ebc9ccf39a916d4a54400a48d84fa78b996202c05a05bcde6","ikmE":"ff73b0109a0ee2e4d0a670606c7241f5fc89e602c9f5a2070ff3c9c302efc20e33c46637b0bcca3cbae7a3dc442698b7705dfe5323a22142","skRm":"d143c59a4e2258cb0497f67cf2c7b0408a364114f75b432c43ea96069ec02f5e9072ce9c9c9a24d713b2276ea944c1430b462053c082c5f0","skEm":"5ac21a9f31bd4481d49217059e0480ea0a087d5a110c187e932cf42974604949f79543969057c1f95253c52463044ee55a3b9a8e43b8db96","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"ed53ccaf667d0247b74c624a8ea8180c6e8376facdf260f0fae359559e4d3daaf63a8d74bc2a41676573cce1fe364746aa07c4f83747e1ce","pkEm":"8386f81f124c73a5df4665a5e937a4358cefbdfd03912c8ff4b14905e108c8227570acb3cdd071bae236c123cd73738a4de76add64efcc47","enc":"8386f81f124c73a5df4665a5e937a4358cefbdfd03912c8ff4b14905e108c8227570acb3cdd071bae236c123cd73738a4de76add64efcc47","shared_secret":"0a8b32efc3a5bb64412cabbea72163002df751d4b221f7151e9f322fcc7b9bc6c86240c3af63a924011d235793754c4a6d6b79edd32302c2fd53b4460b4f0b18","key_schedule_context":"010a7c8b9e324bd689cfa3b72dd78f6b347be3666df100fede193d2d7564373b5859fdea4160c82285f4d0f8e5c644ae33714a93e91c2c82a980a152a8ad127ada94b5b0e6ed9749cf5a584367aeee9665bfdcc13ea89374b725e4d30a351bbcc95bc70b4c35cc84a53ffd1e1877059f35f9f9c98ae168ad89a3a7087d7e88b855","secret":"446d41b4f14dee956cde2f00c1937ef0166d1a98bfdc5ca15ee800e225ff9be6c7a544ee31deabcf4d10fe2e66f149880864d949eb2778a481f15bdbf69f986b","key":"2d19a10813816a214829dacdbd0a2a2e8be2f32dbe1164baee26b0c8b831cd91","base_nonce":"f85eba2eb961d957d424f9b5","exporter_secret":"a2669c13ca5a1a054ed64f7b0c31cc6bd865d0d6ea2f445d55531429b06b2afbd1c4a72a1bee82a4f9fc501ae5a9cceb940037cd1ea7ab13e5a7c46b6dc61781","encryptions":[{"aad":"436f756e742d30","ciphertext":"3ba1afe136e5a5a626995db4bf7dbe8cc231784ff36777770e02a740fda35d69938ed4fbf17f046f58c1af0ecd","nonce":"f85eba2eb961d957d424f9b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"e01c7bbec58110c04f52850b6b622f6c89cd7e905aa65f28ed49721cecb2a41bb2da95f1dfe0ae96aa22740760","nonce":"f85eba2eb961d957d424f9b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"11149bd70de0eebe91fd8a99ca4fb694fc3aa8cf1b518829fc8c13d2e0c6bdeb2217a752df83b50fd1a0e7d6ae","nonce":"f85eba2eb961d957d424f9b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"def9bbf6ecccb6cbc07cc9770593fd2189b011a7259553cffa7e572642ea227ddff7eed9ac2045823387c3ea77","nonce":"f85eba2eb961d957d424f9b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"37a68f6a88e8ab07d7b81ef1b996bec9d71ca651819115e187930b0c2c56849dd81e63e4c8100131ba1ab008bf","nonce":"f85eba2eb961d957d424f9b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"6d2673f40dbaa45856f77fbcb388165553ec51f454d00dcd83320a42f48297d5a4e1838ef93a836085e54680a9","nonce":"f85eba2eb961d957d424f9b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"96825010821c3986bc10e8c1eb7189c5c2b45dafc2e44e3aeb57ba29564206b301426b6a305d19569c1cc689b0","nonce":"f85eba2eb961d957d424f9b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"36dba2ded9f80cc22b835e017921efdda55b5cb7af13f53ecf641bc05f976be28e3db2f2d41daaff0eb1e4a6d8","nonce":"f85eba2eb961d957d424f9b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"2156bd38f26ced36fcddcf70230893e08ef71adddff1b1ef220f3153a4180cee9bdc811d36eb6517f5113bd79c","nonce":"f85eba2eb961d957d424f9bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"b45ea152d209d3d199a17dc7cd8d836afc0f1ca652d0541e9064bba66f82069f0788ea228728ced022f9d5dc6e","nonce":"f85eba2eb961d957d424f9bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"250505aa10799ab498143e4c51ab14b8c345ff8f57c69253cd31f49a74fe90d866c67b9b4ea3782e4afc783b95","nonce":"f85eba2eb961d957d424f9bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"78e83a37efc2c449fed0d0c9060b4dcf81ddbe7b8a2adae639fd4f8bdf590d51ce7f4ec76c462b110f937c6895","nonce":"f85eba2eb961d957d424f9be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"a58392deaa3ca74651258685ef263428c93a00de23f08b18e06ccd9b938945b7f880bc1368b00d07b51ad98378","nonce":"f85eba2eb961d957d424f9b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"90ff8359a47aa67492fc6aeb66b813a0fe519c7cad4f01fc9fd1fdf6dfe10bdbbee066d375411aa6b9f209feae","nonce":"f85eba2eb961d957d424f9b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"5c67119c46c2d335d984cb9395970b9f16340729251866d1fb0cc9dad8be2464a92b3dbe3ea53e5dc90526d0a2","nonce":"f85eba2eb961d957d424f9bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"7bdf51efd2567bc0441cd7366135ac0dfa934ef8f16a2fb059f44bcc104de03c7630c241dff5d058d266200c69","nonce":"f85eba2eb961d957d424f9ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"8cb5298ac338d578ffe50a7600a3bf1645e51c7280b57f1dcde00f5d02a37e25d9a354dd2d344193c1382802f8","nonce":"f85eba2eb961d957d424f9a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"e7b1320473505476bcb15c584a866b0de6b74cf9ba1b23d4138872ae78a649b3ad1896e838858583208cf35081","nonce":"f85eba2eb961d957d424f9a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"6e5ad6bbb8cf5ecfa4d8a4ac2ec439d76cf5a0260dd17dce35afc0a2e2dae15ec144a1ee3ecf68337d7de098f3","nonce":"f85eba2eb961d957d424f9a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"0b904c9360b0d9968f20c36bc85f4526a07f0993ad1dd376e97a3ab3f765400823cc95e362a2f7a63c11f09b2c","nonce":"f85eba2eb961d957d424f9a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"5c10f4b4946ecf801868fc5690279ec48f6f4c74a0b4f784105ea2a2880fb0746b074f1a559685a4665389e99e","nonce":"f85eba2eb961d957d424f9a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"1ad9776dc6bb9d61e3e11c8b8e2056197937d8af3ec51a971b4231f009e004951cd74e1cd23ed1c87515b8b807","nonce":"f85eba2eb961d957d424f9a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"87ab7504f4613ab4ca8d2152752fb76cc726a129504dee4854ec2407e7f23783bf07ef9276859f77fe698de0dd","nonce":"f85eba2eb961d957d424f9a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"8e1a5e2c4d19a4b6ae532063f18d607c30127806525347164608379179ba49039e55b1e93cd2171b0dd6a47c9c","nonce":"f85eba2eb961d957d424f9a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"14f0b3b842db4bd82c511c703a9803f8de107339c2966c16826060bdfed5d66855c940441be751413f072d0d8e","nonce":"f85eba2eb961d957d424f9ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"0f1084a8c2af161cfb4c0ffee5c2834db3efcd1e6f464d7850628602b4e73d75201daa47cf23a76c1b2a2b60bf","nonce":"f85eba2eb961d957d424f9ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"c016d0b6ce28373af08f2e3db913fac098eaefb05a3524366d13b2d3a0958082e3fced5d8974e88027720776ed","nonce":"f85eba2eb961d957d424f9af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"768cfb2757262a805505b5fcb07b05942df696d73cade307aea1cd0d26cbff9a0222dbd3c2d9761e973b9fd933","nonce":"f85eba2eb961d957d424f9ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"e32f3085a1ec951236dea581e7b0bfccd1a470705b85bab97c56880d8684d7cbbe8467d516bebb102e5ec82d64","nonce":"f85eba2eb961d957d424f9a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"0082a0c75d011fa31c636f6bce1727bb09fa46c46afa512771ba1bdcd0281fa6e5d39e9a85b2f037a8ab55903f","nonce":"f85eba2eb961d957d424f9a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"fb443f530d75d2cd270df3e21753aba93221e755a678dddcf0e9cec875cfd5ed5361c1b7f763b32e4e033d750e","nonce":"f85eba2eb961d957d424f9ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"7b1890576a8b5809a86812ce67e562bc75839b58b12683481469ed91488bead0e8df20d8b47a5495140261baac","nonce":"f85eba2eb961d957d424f9aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"5a82d4cf1afcf0fdf062fff07d29bda918f39fd86ca770ce70af941908e017ae3345684b4b47d8eb1a5f408270","nonce":"f85eba2eb961d957d424f995","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"d1367a9e974cc90703186df37f8082c2db86cecd4c14f6f7c1347db8a32fba3daefeed005315b5b96715d08f17","nonce":"f85eba2eb961d957d424f994","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"fc58c3ebf711db3630fc2be9e5be65326044ebb5a8e2246ae2db98fb5e92b51b6a456ce9f624ac76805fe3d6d1","nonce":"f85eba2eb961d957d424f997","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"6c6258ca07e9b684ef5baaf09ab0c4922862db73abd25742cdd0e03f68e3fb0116cb5c30d757d4655ed08b62e4","nonce":"f85eba2eb961d957d424f996","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"facb12f0cb5b3e8b69c71c14854c826ae6051a142a1d90de0103d96f59a80f876633dbfbb14d6bdde08d782b84","nonce":"f85eba2eb961d957d424f991","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"f7e8e03b897d3b3a845e2965b4b65d9ae584607497193b24da8df062a6586708635f630436933a9b290524a3c1","nonce":"f85eba2eb961d957d424f990","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"0831e1f40f0514049b5229da2b832bdd62e318b3cfbf1997066e8b152c015eb4e7fb22981e819da947639e6914","nonce":"f85eba2eb961d957d424f993","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"b3450b58a562f99135e2e0a449a2cad35f957a62205cb000b28469ea7f6741b5b9e6ca004f957e41597ab96267","nonce":"f85eba2eb961d957d424f992","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"78d028dac44866f2d6eb1e6e659e5f76703cece573a1fccce3414770e43284816e4188c3eae0731cbb37d2cada","nonce":"f85eba2eb961d957d424f99d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"31e437d4f805f73362065029b8e64a118c07efe79e140ce69fbc365cb30a92b91fc2cb498f9b159ee4fd24c3ff","nonce":"f85eba2eb961d957d424f99c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"36080852d01ddfa71158288e89580f342d499048c671054ccd3c20d2752d8865198b46571c3e177fb34cba9b32","nonce":"f85eba2eb961d957d424f99f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"ce88aefb4bf3d796b1a39352153404e7cae0fcec13669ffd2f600a655ba69fb0f36b53fda4c699d28b01de04bb","nonce":"f85eba2eb961d957d424f99e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"934942bb056368ee3af4bc5276efa248dfaf98c8abd239e0090b071214c571edc0513e02c598fdd1f3ada5df7e","nonce":"f85eba2eb961d957d424f999","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"288a6acf0a15f9e9b1e1b1eaed6a202fded9f5425c64eeaf91efb9312b8e666004152ff1bf91e6f066cc3f049c","nonce":"f85eba2eb961d957d424f998","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"d5184b03a46f834f55d155f66e1f98067bd8f9dd2d7df71c83fdbaad3502475696b5c9a66ed7e3fb286b371e21","nonce":"f85eba2eb961d957d424f99b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"453c9f5680d06e6e790082586227ed1d95f5c03c5c771138352c3626bd86a9ee7501be3b35c24fa208f10718d7","nonce":"f85eba2eb961d957d424f99a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"4b6e0ee47a5b16f27ad3a25a4a3e1974d75a73fbbea66614d74d0ca7638de620c94dc58c566963762680641cdc","nonce":"f85eba2eb961d957d424f985","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"575dd19bb41d82992931d8df7f04d6b7b9ffbc57f66c624696f073e6a70b7ba6b59b10550833e0e081bfb33d77","nonce":"f85eba2eb961d957d424f984","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"1e8c2bf241d418fa1f5ad4d0ac7bfb799a4a074a06b106b8d1c98133519057a8871c804640f9aa7dc7ce002d27","nonce":"f85eba2eb961d957d424f987","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"f64fd8992010b707c7d19ebe5ca985301f1d876d6507cb7e5cea26acb63c162dfa9445b170698b37977ab05adc","nonce":"f85eba2eb961d957d424f986","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"56c6f46c3d10605a249e4a0303f15817abca5e6032e82d284af095b5f969c27c2f36bee142297332c688f11c85","nonce":"f85eba2eb961d957d424f981","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"e170cd31986302a2584fdb60898863872d63bbd814986ee0927da44f9e22174d4e350af458786d81d9f4bea65a","nonce":"f85eba2eb961d957d424f980","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"6e3882dbf41bfabc9c73683f609e0e05132f03d85deab97769f3d0e61aeb6e9d53fd49a946a2a3ecb280427a27","nonce":"f85eba2eb961d957d424f983","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"0cbe9f63455e87a0abe6687cd0d416c688b8526e9950238bd9d13fc4d54da7f04267bbd62a7fe71388fcae3bf9","nonce":"f85eba2eb961d957d424f982","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"790ee36cedb62d13adb6b399b358cb7c4d4682ce8d05ed09a76c0c9edc1b2df5568f42bc09e3739eb4ac17e5b7","nonce":"f85eba2eb961d957d424f98d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"680fa50caf6e2d3139e74888eb0651b3cba55d8879feaea309337a06d92441435c86b3bd3670700d711c432abd","nonce":"f85eba2eb961d957d424f98c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"08da7f0edaa2cce23726f559dac2e302be73c0bca9446860ca7747b704ae71ef652b458ace48121a078990c0da","nonce":"f85eba2eb961d957d424f98f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"0e9cafecf8f84643685078e404b6973abf4d8547281176f242357209bc42f1a3bf1f08bbfb4d8c1980b23fa82e","nonce":"f85eba2eb961d957d424f98e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"148b7e1eef7e6c7649e8f9924da0e5e04529b8534bc0003884afca4e1428a1b788326d06dc0ad9d442322743cd","nonce":"f85eba2eb961d957d424f989","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"dbaef65f484286c81974b3820eb387a061041792fefe1bb716a57f0560107a6f4d474bb1add24da17c4b043117","nonce":"f85eba2eb961d957d424f988","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"8263ed8f6187149227069096e676405c398157f2417ecfb3b1a6accaf93e68972742aaa006b7c3c52b76ed1e71","nonce":"f85eba2eb961d957d424f98b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"a593708c931e2f076e1d7e91c50114826e9cc8c521c64ebb8470e5c183d6050e32b06fc2fad3708fb0b501133b","nonce":"f85eba2eb961d957d424f98a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"1f929465833713834ff91e8176c00b6aa266fdb20a3786690cad8e4845696abbcf243a0d8118637f79ced0acee","nonce":"f85eba2eb961d957d424f9f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"40fcba4b0b046d894468e131fd572f98e909b3b26ab568b13295ab800cb876ea6aea5d6354fe672341b9fcff26","nonce":"f85eba2eb961d957d424f9f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"a1933ba92b95cbd30277e6928bf00aa6183b9608d869ed3fbfb1ccc388ff8ef184008aaafb361b4012cf667219","nonce":"f85eba2eb961d957d424f9f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"3e89a184ac62ea076895bfbf39f90a37c3ec722696d2328019bad15459ec6027d482b694bd917b8a7338b3eb73","nonce":"f85eba2eb961d957d424f9f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"a3cb3eb659cc61e4ebfeca952aa148e2794c9a45a9e524750ebbde1490956ee8212ee83ec7559f9f6800444a5c","nonce":"f85eba2eb961d957d424f9f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"604944af9b9323f849a403fe647920717fb0cedbcecc91945695607d366ced75476a534a4fa3b318fc4553c181","nonce":"f85eba2eb961d957d424f9f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"2d58db50061ded7e90f190f9cd51ab22e4669033d675c283079129d0a595ecaf5509726669e323adf6d7081720","nonce":"f85eba2eb961d957d424f9f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"381b6251967e15dd8af00e9b25fba02f19e2a56d4ad7e7f1b99a35045864a327ea291168838457d23f4a3d0a4c","nonce":"f85eba2eb961d957d424f9f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"a19f33fcb9571a8e288f733d4dfbbef94153863cd206256c54f4e2b7a21729a88ca562936a2ee01c76a0665082","nonce":"f85eba2eb961d957d424f9fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"212ea19556167c029e43a3533970bcb5dea0e3c51098164759d673da51cf130ecf62d34dd6b2e76103a39d2b8d","nonce":"f85eba2eb961d957d424f9fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"4aed8bba9ca26b94f16f26ce80d72b24889634236b63b244e76c405641c572ff902e68a076c5a2c9d34da059bb","nonce":"f85eba2eb961d957d424f9ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"d0f084c0f6c716ed10cfd93028b8667ba5febd93d8e2a45313e6decc8fb53c10f62d16248f0658470c81e85041","nonce":"f85eba2eb961d957d424f9fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"1ace04b7e8b766078486a473043cccd5c957c0caf379101b5c6172b292e022f40bd2fb54f357d3efb9b136b11f","nonce":"f85eba2eb961d957d424f9f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"e2d64aac7f40e67e26d89477aa07e7ee6a1c6e4140a2e13b6d36d2ce6b498973047062c64d77a468e115f459fe","nonce":"f85eba2eb961d957d424f9f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"10b04881af79820f8a78cd40b1d9913d8af15ba3b00a9a3f21eec44d9adcbf990a175ff7127f0c060ed5b38d95","nonce":"f85eba2eb961d957d424f9fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"2449a376cbe1ead8d34f3f7efd5bc6f81fd6e6af475727798e6501b67b0b2083956bfd427ddb9d7723441424bc","nonce":"f85eba2eb961d957d424f9fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"109ecd88e2b1a07a152995134ac544a9efe7fb01c9877432ff6580374e81ddfb22f91316bd1adbaa225dc0760e","nonce":"f85eba2eb961d957d424f9e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"7edd69e6caff065f1d42c8eb41cd117e7ba4f6ebcc5d16560579a7e71c134671697f144156361eaa82756650ae","nonce":"f85eba2eb961d957d424f9e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"e02cb2e8767cd96d33c54529aba568c10109d9400be56952b725e53cab492d80be2c52608beb301089828db618","nonce":"f85eba2eb961d957d424f9e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"19c56d54ca87df61e030e107964468d6d93e84eb71d0bc11f00957fa86037cd4e9f2591d1f647135748b24d794","nonce":"f85eba2eb961d957d424f9e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"a3194ea9a1e6e294468e73208d9126a75e40822b418860a92354547af439d89a978577724370e66648288c3204","nonce":"f85eba2eb961d957d424f9e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"20a168733e00d53276463937df282499a0674b52883ab43ff669835a68ee35c91d7ab5c60dea198f91139c2593","nonce":"f85eba2eb961d957d424f9e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"0f2208bbc804ce62dc4e53647587dd9a29ff0ba9a10eadfd49a4157557490d1821d77581e8f313a4265d0e5af7","nonce":"f85eba2eb961d957d424f9e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"2b1ac36ffa6ead1f3450c4d687c4199002384e55d60d479d7802584eba7bcdb392515edb99816965657e700fef","nonce":"f85eba2eb961d957d424f9e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"edbb6e45d1fff226074f00135443d7a5c8a36c8c4e2e35a0094fad6cae0324975d1aafa09f01354bf0e55548f2","nonce":"f85eba2eb961d957d424f9ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"ce7203a54d89ac1ce5a3126d41531a8b7960d11738cbc866e06c9787f9836e20484376b5a96493b6094006babb","nonce":"f85eba2eb961d957d424f9ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"e44864c9626e84b7ade33166239adf4ff2bb236a79b9c264735973c322ddd291d3fcf20af7bf991719b63cc6c9","nonce":"f85eba2eb961d957d424f9ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"54c0a41d2b36055802f87ff69d5d21ceabff431eeb82ac6d153d14b3e4a0f6cfd4f4a54583d0c1d4b57528e430","nonce":"f85eba2eb961d957d424f9ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"d9cf5fecadefb92041d951a40db39f086a4a0d0708a77486742a07d7c441f0aaf01436d5e819046b46698b6a7f","nonce":"f85eba2eb961d957d424f9e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"eb5d82832c61b85f01bbcfd7f2d64ac13442f59f9d44772ce1cb34d1b30d7627c90e66fa2665011dd6e7edeb96","nonce":"f85eba2eb961d957d424f9e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"20a0a0ef4a6f400720a7da8c17f49e5bea30122933696552704ce28f889ff5d7a161a6c7a9ca0feb93409f307b","nonce":"f85eba2eb961d957d424f9eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"1909aeb64decb3b6b445416bf39fb21624b3835d722f8bf0943a7a47ffede86895add0fe65c3533e0e3acf80a3","nonce":"f85eba2eb961d957d424f9ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"6678501c2ffae3c44c045bd52f67fce7752e83cbe09344d7c5a5465f3ed04c4cb4c940f01d9c6b5ae0122b85bf","nonce":"f85eba2eb961d957d424f9d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"511cd6c343bda5d39dc76b5aec5404fd139a93678adb4a71dc4f841b100bb5b99ff8e8d11f0f609c9b617bc161","nonce":"f85eba2eb961d957d424f9d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"ecbe9ff65e68f3046ea6b62b6789a82270e14d20b68d6541421c50013f1253084253dda08c5a0f9355f02f9e26","nonce":"f85eba2eb961d957d424f9d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"097ac2d46381072f0c4703a0341ec0b82368f1f19be381691b49e7987820879d3ca8ca65521e87cbdbd81c6cba","nonce":"f85eba2eb961d957d424f9d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"e710b920224f1d24ff1dd034b04077a2f91812650045125804fc409f2bc6afdab00752d498edff1e7cf877f258","nonce":"f85eba2eb961d957d424f9d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"6f3f1b34a5e4f18bf33afb1ce366ad960b005d827fb9c5b959e0785699843078c556aa02834b9a09f72fa7764a","nonce":"f85eba2eb961d957d424f9d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"cb7183dda3c155240aabfae849a2462bd7020c372e88a6800a11993d536394f50b9f3b5247cf95034f97c7fc40","nonce":"f85eba2eb961d957d424f9d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"848c28e0d964c587888f4bfa5893a0f444ab45352c7cf6a7fee6057edcadf92b750625af81857de9f948df0618","nonce":"f85eba2eb961d957d424f9d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"f2d1a8ff92ed42525cfad9a4523ea2879497c772e95dad1f3d85a03f20ff59aef1b752aac995ce2673536a1bb8","nonce":"f85eba2eb961d957d424f9dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"de0a07a6f56cded7e316c9090c9d2a04a9d83fe01e2cf96fe4e847cb4da19eec626a184dafb7ebe0d75beeb770","nonce":"f85eba2eb961d957d424f9dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"5ad20a9ec632d44d3c88a406720c16d5a0fd0db45b6422d7cde9b9dc336e295804e3d89fcdcb0ba003f7115a4c","nonce":"f85eba2eb961d957d424f9df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"b17b040b214b4ab7e151fb3979c4713291db1a77112cb322a3530c32aeb55d8d7c470d6dfb42134872263fad29","nonce":"f85eba2eb961d957d424f9de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"f6db5a0104f0f3307e4905abaa9256f1c48c2d0d21e4d634a3dbb85f7e6d879abccf06b9fbc7acc8e9a7ae878b","nonce":"f85eba2eb961d957d424f9d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"61e456d49cce8cbc33ceae63342868f902f752df9d44f1a5a9a2b79ca6d924e8f1a159cfe940db4a293a6dedd2","nonce":"f85eba2eb961d957d424f9d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"c023140f603745332f6df858c718d8ae8b6d4d8ee536d9c42aa80362cbad0e407eab80aa497527c46697c3ffe7","nonce":"f85eba2eb961d957d424f9db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"62e187232088a5e20e205592ab8c50c8bb344277ced749c237e9a450f80ce4cca3c6bf464ba870871e45352ddf","nonce":"f85eba2eb961d957d424f9da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"3c24e331ee523e8a419b985b5e41ad7b7d7c6ec889e164246a4f0934f042dc88cc7d63fd01ccf12295fab5cb60","nonce":"f85eba2eb961d957d424f9c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"9b2e3a560a3b1d7e6d35e27b9415c58f7f076ea8d10bd468428e5e531d28dc77753e57b1ce0073f0b2d38ae0e8","nonce":"f85eba2eb961d957d424f9c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"8e987c9a8fdd360675bec2bd7d2e3cb993ca51396a9a516877273f76702362c9698f2b2d0a75cf7e9a10ed6240","nonce":"f85eba2eb961d957d424f9c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"18dbe3bda337be395cdf841d6de89fbc5d20ba2401dc14b1287cf04691d341197f7bdd55d480749318ad244ae7","nonce":"f85eba2eb961d957d424f9c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"8527de98e315f94526484c3667e9a9e8c5cd4b4552e9e72409969446c9c712ac4e679921945e7d6c552528763c","nonce":"f85eba2eb961d957d424f9c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"2c09f9dabad51e39bd2a744caa53f0f6ba2bfa976cfa0ed8097bb39e4e7a1451d8fcb9242034a9fc8c6d2343d5","nonce":"f85eba2eb961d957d424f9c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"74d0736deff8634bd6c51fcd61b6b93efc110114ebdc474c252c160bbd064b4893b19ba1627ec175e80cfbeb4d","nonce":"f85eba2eb961d957d424f9c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"54b0dddd7d53029750c32e1b3f10c2697152e0a92c0c1dfba5b95e0ee71e48f6135a624813a28e52ab60420b0b","nonce":"f85eba2eb961d957d424f9c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"8a5364e03f60c537e27094a79554744b775b89047ef45764fbf3989095c5a86ccc028ca4eadf5479ebd7c7c9d0","nonce":"f85eba2eb961d957d424f9cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"6d7fb83b8ccceb9ed50fd9899f473e74dfe92ce90fe456437e5b63d58d67723d9a733c6dce7e4b66ab1e98d6fd","nonce":"f85eba2eb961d957d424f9cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"76e895fced269826a334a787ceefe918daa6183c343c8d4e627417938dfd2461063981f56e67c7230b3d88720f","nonce":"f85eba2eb961d957d424f9cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"7cb48591088130efb3825b527dead7b170dacad282aa34ec498e5564ff7e35b6c8cbc6d1d39638387386c9bbec","nonce":"f85eba2eb961d957d424f9ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"6a5f6e622a79dd8ec5e964cd481e496389f8282893acdc84b0c70a9503f4ef15f4496e2b82afc980876e4b9b25","nonce":"f85eba2eb961d957d424f9c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"784c44e1da654327b71ad85c5a319ea45189ce9acb5519536ef231d951288bedd28f8687807504664504112af8","nonce":"f85eba2eb961d957d424f9c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"00df122715d5e6bb94338d96e780d166ec862001b701095147046f2748b8e41935faf7b5a98794704553cbc164","nonce":"f85eba2eb961d957d424f9cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"d376bf0a75c82d8cc20886ef374c8ca45cdfd2839590e4f04eba994b8100dd3f3ec2b1629421aa066b399a3779","nonce":"f85eba2eb961d957d424f9ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"d076b23d877ccef005d2180770cd7a84188d36ad4bfaa64f0d48e6aad6bf2a358722a1129f352334df87d465a7","nonce":"f85eba2eb961d957d424f935","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"67f9fbab29a2cd84e6e655b7ba9ff59de69c0939a85b0e61a3c812a48e46e4a2774f18c15f13e06b0ff0b95d2a","nonce":"f85eba2eb961d957d424f934","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"1c9eef1f28b53f3d427da56e2fc5616958a518fc17fe3434a1595a589677931ec6918e2b3f5ff28c969752c20a","nonce":"f85eba2eb961d957d424f937","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"adae53e69bd977725168991e9e869c32927b030a2f8f78e25508004e459ab44d24a85fd0e9e4e18ffef702a7f8","nonce":"f85eba2eb961d957d424f936","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"398a95c25da659bb02560564175403ae09c8db00bbfd78365b801c359af9ff576ea67b0506124d3b988367a3cb","nonce":"f85eba2eb961d957d424f931","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"85a1633e74c4d4b89515345186886e5435081be5825ae9e0964f631b41a7a26fc492eabbc95fcc217cfc77662d","nonce":"f85eba2eb961d957d424f930","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"b2fc767164ea6bf92be848b5e4bad241e05834b4e31fb310482441a84fea4c40bfdfcf541751fbf95e648e5021","nonce":"f85eba2eb961d957d424f933","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"16a577be909a66bd8445a2da1239fbef0dfd94c548463fefb8d83747f519b47759b19995d538cb63c117f57850","nonce":"f85eba2eb961d957d424f932","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"d250f15827226c0a72fc0b823ce3d7af9640942b27e7c7cdfc07d1ddffa15e7a18eec97c1a3345caeed1b68747","nonce":"f85eba2eb961d957d424f93d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"edd3df12b575b9074ecb3ab65ca70c87ed6c4de4f01252f62258a4abee328d019bcd6901fea66ba2fdc55beb49","nonce":"f85eba2eb961d957d424f93c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"9c410c872adb81b014803a9ca02804bf7cdf9901c9e441c0c5950a96148789b5bd8616a5d52c0fb55b64e16863","nonce":"f85eba2eb961d957d424f93f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"cea624b3ed83ee93ec9cdd1d9fccf70ffebfcca8e6dede5d12db09bd4bcd16b507c75311e22ddd6f2b6bd75154","nonce":"f85eba2eb961d957d424f93e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"286f594701def752bcb68204ab5c501bb104dc32f5dca1a59a2c948a15bafb690b1f925d678553fd00b0e8b64b","nonce":"f85eba2eb961d957d424f939","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"897ec7a634c6e6d4d6c98e749afb3bbdd48457e21ad9b1892c996a92fb5f02b6ccb4b4fc5ac473cb5b8df75a5d","nonce":"f85eba2eb961d957d424f938","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"ee77dcbb8dc2c014482ae0c54fc726bde5e4660cea07211b5756320a168706416c59a0bfa9dfce6239a94c65a7","nonce":"f85eba2eb961d957d424f93b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"294bad6211b803cf90e8da358970d44852fbb9fbecafb717f4be3c746d487b32c9f3051608a56148826eb39477","nonce":"f85eba2eb961d957d424f93a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"472507e24c4facfec436e2f8931accf1ab4a79154e7ba4c585d71302b1115434f76275c209e87e1ae872c4955e","nonce":"f85eba2eb961d957d424f925","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"365b2f78a3caf4d2d19ef97de165529b0e87bf2c1a3d9f160560ebfe10c258074b6560765007327f6a5d14c695","nonce":"f85eba2eb961d957d424f924","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"687bcce7fb3c0b25b8b16ee2527772eee4048e3bb5549705da656a0b9b879b2bb35058ebfe94949cb79942c122","nonce":"f85eba2eb961d957d424f927","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"27c997dc1748fe2349603df3459eb703b9877536c3fb4c1c9ab77433b56fffbc18dea86beee29088c366edd03e","nonce":"f85eba2eb961d957d424f926","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"0ea31e4d398934296f559504294af9de26d282006d7259fcaca49849a591e52c0c92ebc240df53c63179c4f673","nonce":"f85eba2eb961d957d424f921","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"fc7ba1d029616fa0967bb677d73b042e2758b5343e7f49e023f40111ec2d7cd56c3722536b61dea0842164ef9d","nonce":"f85eba2eb961d957d424f920","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"6ad50385cdfb3e5ce0ab8581be6d8275ff2239f78766a5a3bf4a9d3cc595ee9e571c38ac6fc66de6540614326f","nonce":"f85eba2eb961d957d424f923","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"51bf35fda5ee62b30bff8fbbd2f6c6c27e22de65d938530e17c307970d850a09edbf2295b1f9e3549a6ee34fdd","nonce":"f85eba2eb961d957d424f922","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"68b6032d358e2d4ea838ee14300b1c8998c398f17cd18531fd486677769d1e49bdd21f7f5773901772f2012ab5","nonce":"f85eba2eb961d957d424f92d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"dc20926f1ce5845b3e3a3cef23e48dfb50f6d842d152791d11c7433e59a6af27e138430bf3f9bf7e2529e00de8","nonce":"f85eba2eb961d957d424f92c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"1071aee8c478daf98f3913c9ef1d0635f2a24bab1f8d2a3c579aef2f4f29fc565d41603dd0738b2c9427a1ff10","nonce":"f85eba2eb961d957d424f92f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"ca2c62c8b7ef05d228f565d99782655d6716044c41bbb5f69ac719b123fb57bf0502c653b44b2daa46f7c77342","nonce":"f85eba2eb961d957d424f92e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"5aaf292bd9f059911ba6bcd459bfcd2c5b13a1d9591e2dafa523415e6619171041c3f0b0aaa4e8f9815bda61cc","nonce":"f85eba2eb961d957d424f929","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"4e2928b31b0fe7ecaedd646178b788c542daac9e8987aee32cf4d0bdfc8810a3fffad24603b1a8b9523d7f7fb5","nonce":"f85eba2eb961d957d424f928","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"0df6770bbdcbdf7d2c486601e7341bc63239a33c63d855c5231b4806e6e20b1f4d64d9ddc686a5204185317c52","nonce":"f85eba2eb961d957d424f92b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"37840bc1c574a9cffbd21db51964a053631d4fba94cbf5462d385df8b80a542fad86d785fdcd4ee0d544432e59","nonce":"f85eba2eb961d957d424f92a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"b0cbad0031fd1a4b980db0aa697960272296ee59fd357be99f67ba2925849c45e9f22706a1753cffadb27c808a","nonce":"f85eba2eb961d957d424f915","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"f0a1539082638572dc3827fd8723388f4fe1f93f6b27a22018f60e872d1a412e690fdfd080aff39d4d600cc765","nonce":"f85eba2eb961d957d424f914","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"80a9ec94f48d73be937ad8b58242b220b8b81126dc1c6bee392c8caebf560910ff92caaabe3f32669ff2b722a5","nonce":"f85eba2eb961d957d424f917","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"a9b334284f74d5279343313a719bdcc7fa858efd1a4c9a4955969ca0a7b69a2aec4d1f66ee011a676bf94c7da9","nonce":"f85eba2eb961d957d424f916","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"1ec540cfc324448d9b1f93174e82f1ddd1f8f606a1bfc3ee63ec772937f31179f5da1019ee9a4cd71eb658d480","nonce":"f85eba2eb961d957d424f911","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"a5eac7462137d173eb1f6a62f799a5bb0443149da22042dd7a49ec33e721eed62488edf6cf9b4a419371c150d3","nonce":"f85eba2eb961d957d424f910","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"598cacdefac30cbcd9d1b4c5d18546759a0d936f540bd59fe82f0464f64d77a0b67504ab9b005e9df9b705e3b4","nonce":"f85eba2eb961d957d424f913","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"a84770cdb9cc4b07b59e3d245089b05b3351c64ffcf7b5cf4fb3234aa0fc9ee4ffc7ee450a7b4f3c078375e542","nonce":"f85eba2eb961d957d424f912","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"d86626abc2a82a90a0223c778e3453f4a8e381f33365f263506502f7db8e223d4ef2313f06fbea1099d29445ff","nonce":"f85eba2eb961d957d424f91d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"04f2e525c6506380c66562e87fbae820195017e3c53c64ccd9721a3c19c54ead58b9b548823cd196fd3bb04a71","nonce":"f85eba2eb961d957d424f91c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"356703dc469325f750ebc5fc616ce95948c4304d4ab93b217b60bdc5d65ceb47691ca85dfed9b9ce17458cdaf9","nonce":"f85eba2eb961d957d424f91f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"9639963f4737841c0c1e776ae29a6059a675abff7be010a381c36ef3939d053acd2a9470f6d33df816d9606ff4","nonce":"f85eba2eb961d957d424f91e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"6790ef6ae239154897679fe4b4b949caf02ad0f1be35dd6e4734c8009e4faad5a093b99cfefaf3ab449c2d3df2","nonce":"f85eba2eb961d957d424f919","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"9bdbb731bcb311a0d5e3d9d7e2ee68d8bae6add89e9f59abf55317ff064d11cb78cb57b98f418569251655af6d","nonce":"f85eba2eb961d957d424f918","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"772125d5e538934435bde72971c7f42e32fefc72bcece081e3dcbfa56a1e9441a22e59363dc19885a191cde96d","nonce":"f85eba2eb961d957d424f91b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"4b1f9d288a29cf8fd0c4194f83d03e67438801fd58694243523fba770eff8168b292bb818cf5befbea58bbb6cb","nonce":"f85eba2eb961d957d424f91a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"b0449c0bca7ce14b633a44aad89fd57293bad0647611fad55da416224806406a9f4a56c8b52415750f61c0569b","nonce":"f85eba2eb961d957d424f905","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"9e864abb49acb88371cd4f493c4da5e31dded4d4ec17774024a4ed49bbbc7417ef26baacd335a85877401ef3cd","nonce":"f85eba2eb961d957d424f904","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"96b074630fe49fa42825dd0616a443dfa7926358805534b77075c6f288f9b89d398231666cc4f41602782f9556","nonce":"f85eba2eb961d957d424f907","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"1cdc3a12719c98c914db2f3e36d95647bdfe57b4e69aca4bec31cdf71473be6c4d3f5b4adda200187298cf8188","nonce":"f85eba2eb961d957d424f906","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"0e752462a5e2acad5113efead8a4ec3b8dd3fc45f56dba46230f65e22725f6c9540122d58c2e17d95d15200e3e","nonce":"f85eba2eb961d957d424f901","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"92a683da7c552a6f42294dd21142e392291bd1e7151a38048cead999efc3c448371edd86988e7c64ea99e705c3","nonce":"f85eba2eb961d957d424f900","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"85742ad6f0ecf00b0d82c243d2b43ccec2b7107962dcbec4db8ea78ec2043807d1e0e279ccb983568beebee075","nonce":"f85eba2eb961d957d424f903","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"2ea3feac7b6671a33b3ce5a3ae5b32de60835761a0574b174b32ab8e1714412bffc653707b6171af4b79352344","nonce":"f85eba2eb961d957d424f902","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"48ac28b4ea73dd8f78f96eae94453d4125eaba7e93e85b983444aae0f6e2e9937a649800483adfa3a52b39978f","nonce":"f85eba2eb961d957d424f90d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"5d67c89be6668ccde87c150ebfb2d982f4d1cd35b085029e105fb50e430e7d17f32520f81941806dc863f92618","nonce":"f85eba2eb961d957d424f90c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"0686a0dfa45f43ff7e94b18a3a43a8fad1c4f10f78505f846c27029c1f7a10c557d1f29caeabc9d2bb91ee62e2","nonce":"f85eba2eb961d957d424f90f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"ef54ef67eb04531e4f9e51cbdf2611e1b7c13e8182e08fc87ea9d0f70ee6732b3f3a161be5773e37af688defa3","nonce":"f85eba2eb961d957d424f90e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"84eff0bd34bde5c010640cd911c99a46979c00856595291b98e9fad6147c8d15c9c967a52ebbb45c39b97fd7d6","nonce":"f85eba2eb961d957d424f909","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"635a1e2ef7a7a5f7fc15311b19d19f8d7b132dccb806da322699f54d3f82f7c0136f1f6487e7b6f8bd26337c90","nonce":"f85eba2eb961d957d424f908","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"6dcff57a189e5ddcb76907ba6bb2c29ca3c192789adeb94011d78fab70c091097f49f501a7e60259496f042427","nonce":"f85eba2eb961d957d424f90b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"c8b1efb1a92aa816f99b183db47a7227307989d04cf35009de63f00173c3ecd46cd0f27bd1ca731af4cddcfcf3","nonce":"f85eba2eb961d957d424f90a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"ca7f3a9a4a260db4e5ee5e391b6cfb630fd9e70d359f96cdc10762ba497c5369263a1795780744bb0b09ffe74f","nonce":"f85eba2eb961d957d424f975","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"a4b910118393ac51345bf7c02872a5e0b003d34fc346fc2d64c6f79c2cbdc0bf6cb86f6bbf55ee202dab0e8d4a","nonce":"f85eba2eb961d957d424f974","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"c40e71df541ef1ab7e422ad3cc6d52c244201eb0b2e42411533b8181e4ed27a809d5e5ce4fa7ee80f8e3d51184","nonce":"f85eba2eb961d957d424f977","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"13e332627e5f2b691fa4efa6d25f92eda3fa48c8ff933d44efe5b62f00a8220ae89d9e8bfc1c3bdf003b0e2dbc","nonce":"f85eba2eb961d957d424f976","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"ec399c46591506074a3e49eb5d59d5d8f20c1920d75ae0100456251494e0bcfc8c5dff10dc2a3ed767e8a06179","nonce":"f85eba2eb961d957d424f971","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"c33e48d46428c189ddb88f6de689c77f071e453f7f06a36bef128d892faf19d6eb28c1874c79c3628bd262b11a","nonce":"f85eba2eb961d957d424f970","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"9d96d6613930fbb201c5191887616a6cb8951ef8dafc996620cc633ae38e27a13f90313ec02a9efb02fcd9ad45","nonce":"f85eba2eb961d957d424f973","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"820bf099b8652c7dad811f8233a7c4177b2186a511787d8858a56194be53540e741607e650084d5342c637b3e2","nonce":"f85eba2eb961d957d424f972","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"57f0d6810b01410707b2e71ae213e05b950165529048d1bcbce7b779d0abe53cc6d71706af63e6283adb21a404","nonce":"f85eba2eb961d957d424f97d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"382106a67da83c3b7b1c9c021975b49570bf51492110d12293fa1f420047078429c730b58a948c1cf7082ea5ea","nonce":"f85eba2eb961d957d424f97c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"f501b26ff5ce609441b03569b570fd9767623a88a371f560d35e1f365eec300169b55ce5425f394858c7fd3d54","nonce":"f85eba2eb961d957d424f97f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"c697c6890ec42a04c864c5dedc55e37b316e853347c8202d78d4b7a6b842755980eff4e8f09f6f862b04f9830b","nonce":"f85eba2eb961d957d424f97e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"59510c0df89c42de3dd79964affc18a24c68fa8a78684606db04ac563a583125731ac2ac4581ffe8f0d8df69fc","nonce":"f85eba2eb961d957d424f979","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"bcff5406679a58023fb0fce1cb8211b9c4c36e7ccfb18eee8aa1e1f35d7e4f43913b05d4c7cb55abe24a4ae943","nonce":"f85eba2eb961d957d424f978","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"68b6449656328e6ab60c0fbb0bffe042e55fa0ea5ba25f51b5f30d8e18f859d1678deef327d6de2f553a67c397","nonce":"f85eba2eb961d957d424f97b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"46c4be7d1d51dda0a1beabcec6640f668ea09e803d9f3759ea4483eb79cafc841b0eba329b50676b8c45c5c106","nonce":"f85eba2eb961d957d424f97a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"4fa46b4b0208b8b93ac29d416d5844554bdc38be0442ed85474751633e601229d41bf385b8201b4ec1d5a8765e","nonce":"f85eba2eb961d957d424f965","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"667c5da7f522b4e987c19f750aeb142b912258b2f637cdbe6b97129a099e6e008bdef0f94372973cf09f3d9c55","nonce":"f85eba2eb961d957d424f964","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"e0f4229a2d44abe3500617754fd473000d1d88e8a4f9307bacf9f3245eb7eac7185071a217c1d2f5ec03a6077b","nonce":"f85eba2eb961d957d424f967","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"ff8016f8ae31928aa7ee4af07db20a511571cfb84c7992c6f7df3c316b1c66ffb5f2e98fb19b27df6bb372f31f","nonce":"f85eba2eb961d957d424f966","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"575ac874772a80189ffb85620940049d3abada679af743ccda3e4523f8feaf82a1c67c54ddd4af1dd0a1777d4c","nonce":"f85eba2eb961d957d424f961","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"b9b4bc9679d584862a30724091de119b5e6154683765bac85bec77c9faff6ba6d0e471fb832fd0f0b503d64cdd","nonce":"f85eba2eb961d957d424f960","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"d052ea5d1b8729d3d8af5b629af2cf97bcba893ba20616e0231165e122885cdcf26362d3daa707b3d76dd2d385","nonce":"f85eba2eb961d957d424f963","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"611dae370f46061cc1e428b5b8d9795e17de70d088495e89ff422d006a7be859da2b1edee2c045276d2e64330d","nonce":"f85eba2eb961d957d424f962","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"8d19ff1de49324fa4ede373ff7a07c226de6999f63078a1abad7887a92cfc37b68f1e3fc577882c4cfccf5d4be","nonce":"f85eba2eb961d957d424f96d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"77fa715169a89938714c412b6a06d7f74bb9dfdb8ba360f4fc5479923f4edc2fe5df975df214585e80f3a57037","nonce":"f85eba2eb961d957d424f96c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"12960ced8251b60baac445755677f09d19f8ef8368f2af2ee0aad8e64c15f8510e94a8adc2201932bb30d0f3dc","nonce":"f85eba2eb961d957d424f96f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"e1e773eb41ed3cd5ed570593cb9cc6cff6c30258ca3b71d5d702c57561966e879be87b52298a1f6d9308035f93","nonce":"f85eba2eb961d957d424f96e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"4c3fbd59f4e9c05f12c43b2cee067d5a1c62eee381bc5d3c2b13cc68e6a177b1bf99fa7f9ed0f7197c74b11c2e","nonce":"f85eba2eb961d957d424f969","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"5863f48a85bb2decc6acd5942206aac59dfdc1de658e0781ab540546935a37b386935810fe5cbe9e0370e7757d","nonce":"f85eba2eb961d957d424f968","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"ea990dd13990a66d770e4cb07325912ca55ec646198f97ab9c9f64a9ca324011a43513bffb18478ba7dab90503","nonce":"f85eba2eb961d957d424f96b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"9aed8afbf5e69e295502297243fcb7db61fd58b795c48f5a46f7dba9247994a9038313309fb84c978ad4f76a27","nonce":"f85eba2eb961d957d424f96a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"9f3b4f7416a2cd7a955cb67e064a521e8d20ffffb6b0aa737f97f691aa24626249e0525cfb3612453743fb21f4","nonce":"f85eba2eb961d957d424f955","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"a1d3b438625d85d7cc6c2ee167c33b9551e1a1469378625f0bd1878d35cd593836dcb6bad297b6f8676e564903","nonce":"f85eba2eb961d957d424f954","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"ba91cdbb4d755108cc2dc678d0377482e1c9adbcb3b46f169aefc4bf2c267f053e0c253ceda8fdf0c2390e64d6","nonce":"f85eba2eb961d957d424f957","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"3cc3a5ebf7d5b7fc989a5b72aca7c105f90ef4b8b42a4c3a0a182020b87dd93e43a0c87c5f157319d2cc3ba3da","nonce":"f85eba2eb961d957d424f956","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"eaad23f224bf9e81ca6335c59560eba24c02bde5db1eb3b57bebc69ab7473415a3d9948225523a811705bb54d8","nonce":"f85eba2eb961d957d424f951","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"8b44a2c99b2ec746b5428caac54ef3538f3823718253fda24b3536cc68e6411e552687bc43c151f67a94e765fb","nonce":"f85eba2eb961d957d424f950","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"112eae744b208c98ba82f646077c916d2d23d39063577b21f621493398547a85da4eb2427591fc4d108c26e47f","nonce":"f85eba2eb961d957d424f953","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"44b78d05b99784cd3a15f0d87e4fd6053d73f20b11256b370b6d3d687109724805f0b22a76b10633a8acdcabe2","nonce":"f85eba2eb961d957d424f952","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"2451bc52ac9b6f671b30824754740200b7346fd9f15b696205d9ca30de94d4a252c85096179089186316e762f3","nonce":"f85eba2eb961d957d424f95d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"2cf249bd0378d92b4a34ef89d5f4e51caf44ba1d128f886805a68a84dd4f4de64c8b0fb537ea0e32134b75cf2c","nonce":"f85eba2eb961d957d424f95c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"b7e452d53d8366416a38fa1ed2876c1cf0d20e55a983b5ab704c984a2d8c9edcebc63d2c2540b717544fe2547b","nonce":"f85eba2eb961d957d424f95f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"ff2fd8be29c9b26cb66c476e9a94c9a67211eb78118a3061463cc2560bca8fee3c433fefca0d3bdb7256c14795","nonce":"f85eba2eb961d957d424f95e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"914d613bec12767bbc580ba917d77f2dd0080861979c2e11a4fda837eb330bfe7514ef70d2825f31a28c99bf9b","nonce":"f85eba2eb961d957d424f959","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"d1c73cd946ab02e93f3167f93ac9be26d958d1562b569b07338cf3fb2995067f421300546f2fb31f5dd06d16c0","nonce":"f85eba2eb961d957d424f958","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"39acea6d7e31b7236eb3c6a57c877eb0372a97492ba78d97ccbb82a38980c1aed98ff0edad775e2e04e61473ca","nonce":"f85eba2eb961d957d424f95b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"1ffc4e0c64f69d0d1c1c8fc76e50b45467f99950096538480cb4bd23441321205719249d279b02351fe31a1105","nonce":"f85eba2eb961d957d424f95a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"d34934f187cdba8562c986fa208f7aba0b69ecd85110fb3a7f8418744541c6f96a49be4f40b8c84ae384b5e35d","nonce":"f85eba2eb961d957d424f945","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"0b2a14349d2d098ba147800050aa2a3a6f2b260fdf5161aad7e5b4738ec84a75424edf1e1e3e05188c9aff7407","nonce":"f85eba2eb961d957d424f944","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"23117a7e5bf8814fea13667429b0ad85df5f1aedf2259854b79f1721a53451f85789b5901c9070b44109dc5704","nonce":"f85eba2eb961d957d424f947","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"796eb25c68fe819de2eca9cc3c011cbebd8de0bd5cfd37c48cd64be8d0f6f12c9188821be3c24d95ceddce9f07","nonce":"f85eba2eb961d957d424f946","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"c7cc25a6abc0ae7c0406a3f37e4066fa94a498d0399fea72d7c3aa42d7a7494d6ccb80fbab917c55016710bf7a","nonce":"f85eba2eb961d957d424f941","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"468199ab76c520062ab708bfacf0cbb969a5582d4ef119a2517ef588a0e9a30d7d4aeaeec1a009313c915d7e3b","nonce":"f85eba2eb961d957d424f940","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"9e33ac5f557f76d707c4d4149f318d065a5cc1cb52d05d1518d5e41e27440639f5c6197237b0127566f2879d36","nonce":"f85eba2eb961d957d424f943","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"637de85cdc2456d0b6d4f1284ffb6c1029b730bdee27b7ad02af51968b02538c4570cc4f457743af3c77cef50c","nonce":"f85eba2eb961d957d424f942","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"7e517266b120b48f9ee8d5b1f6b7cc1ed4507da3a8c0a95fbb16b16cb1221fc81dbd79c63c7c7abd6fffcb222b","nonce":"f85eba2eb961d957d424f94d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"7f585e79ee53cd0dd3bb749dd899b888ef6cce5ef4bc31cce0df3880031afad7c2d1c7fee9ed95022e86360c7b","nonce":"f85eba2eb961d957d424f94c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"946e7ca6ec5f37c0f6e1dd3e5bdc91e85e2ef06ad5d870a954d35271b218f1cc2a35eff27f25c64558d4a07da6","nonce":"f85eba2eb961d957d424f94f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"7e7012101a964f05d5ecb1d16208a9e20c8d716e5006b38b5bc71a861a0e085049b6f90e7c81c9e8364fde9c07","nonce":"f85eba2eb961d957d424f94e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"1d733940847fb6b719d9da5ffd4caf329755c09641dd6019fde5d35f87e0160748babbc78955f2a98ddca08d58","nonce":"f85eba2eb961d957d424f949","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"6dca054c63767883749babfcf0724cea4b8330aea25115e9cabce6e1b3b9967742edc3b90260ca72816fd5e4de","nonce":"f85eba2eb961d957d424f948","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"ef87504e3bc113855f7bfbd3e1115029a8b1a486df4b4f852c5a0dcb6f0cfecaf21a3117708a2909a7989f506d","nonce":"f85eba2eb961d957d424f94b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"56cc2b16350cc8d3a546041620ced452953eb8eab68d8acd7c574ba84da7fe26aa74acec4d6bc052fd8bde9d4b","nonce":"f85eba2eb961d957d424f94a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"03356ff04e5b40381c7c9ecf442d92107effe533bbd72fa505408fe8ef0b3101c5fbb1bdb0fb171308c29459d3","nonce":"f85eba2eb961d957d424f8b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"b94a60b253325dc8faede682671fba9b1d7f2c3fb4fde7d6c3227a60862d6701"},{"exporter_context":"00","L":32,"exported_value":"65a8c6261c3c2bf51d631d2bbff8382563e9eaab1b3a99330dc886e275d185e6"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"97cfc188a763536ca29f1cd8bcd97b41e7d6f9c4c37fd4d7fe7ee75dcedd5586"}]},{"mode":2,"kem_id":33,"kdf_id":3,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"33330a4f6b1074c5f75eae0e0072a1f691b1e448f77d07d9e5c0b27aabd897145188eee46df2fa95e94f64961342783b52edd16694f40dbd","ikmS":"f92a84c0a24caed39d99093bd095df31e80dd79094080c116af7dfe50bcf831bb4d58d2cf1cb047a2ac31f36b6207482e16d03aebd7d59df","ikmE":"f7f686dbeaa3b0e590eba0232608e23bac7c74d6a2a8e1305b3c694526a3750df33c0ca672ea10600d7ed1a81a56fdbdfd24d1eae0284462","skRm":"431a9ee4b4789a319d3d483cc241b45b84f8a98b55f706070f75e7c45ffb310d6ba1131926da78ce394494b18b8f9d9af5c74dd09e34e002","skSm":"5a60e53db9e9b7a577d59c2c7accc37d7c4e1481693b9d69cea97ff7289768dd696cdd1fcc67a9e97d19aef205089cc25e561237e4989ed7","skEm":"627fd5457b47752b3f8209559bd6e00e36dce3cd60995bf15eec9a5c28290b043cfe09a10449f4cb0eb3a034aa02a78798d0268024e308b1","pkRm":"af300aecf9a1eb2f075eba3a717ec9ef4715d56838ab45b8985e427ab218ea9cba2f303988dd64e84b385fbbd72117eb6651242f763e3c12","pkSm":"371c20fde5e26013c11f701c5c9ef4c35d0341b2439d44f7e164d37de5e1e14ec24dc7d238dfec408874d3cb3c10fb85250cec70c317c2bc","pkEm":"0c6bb0556ba3d1a6c814c3a4a1b64fbc6a9dd3a25c358d642e5ec942599a06a0b3be1154d98d186bd1b4d332041600aa0da2b7e7f1323805","enc":"0c6bb0556ba3d1a6c814c3a4a1b64fbc6a9dd3a25c358d642e5ec942599a06a0b3be1154d98d186bd1b4d332041600aa0da2b7e7f1323805","shared_secret":"7f06e1a9b85216d1324b5bcc70f67d4f132f61909daf3048d0dff3f1ad2b25f601145120f8ea529fe46ec6b23c2ad25eb9db987484636f55743a77f262011abf","key_schedule_context":"029f764d157beae4544a48cc4382cc0eaaee23564072136ce01ebe7b274f54ab4420ed990cd86d7ec33fd88dc1a603491ae460c58931a78178cd8e1af2fec96e7994b5b0e6ed9749cf5a584367aeee9665bfdcc13ea89374b725e4d30a351bbcc95bc70b4c35cc84a53ffd1e1877059f35f9f9c98ae168ad89a3a7087d7e88b855","secret":"23f2c0c250157ff9e9ec154af81dc7ecfd57539cab91a27c83226f41cfa5c07eced85d997f19f158b67e257695e122df5b685e3db77c192264ed30adabfa9ddc","key":"0f9b8692e8b4470b8efc3bf1908a63cbc3f4cd47c8e0867f4785fb88f23f5ccd","base_nonce":"0a83e3ec68dff6ab367aec76","exporter_secret":"6efcfafe8cfde481b13c16265bd4cac99d935d2e2413624f21f6d19d4015cdf44ef13efe682698c2975159a2519d87094d187616e5f03cbe9eee8658d350e9c5","encryptions":[{"aad":"436f756e742d30","ciphertext":"536cb2f1735e4dfdbf7efd8511f866abaa2651b73bf8b46a0296e401a37bd933969c6a57e52f1f2a7458efde4a","nonce":"0a83e3ec68dff6ab367aec76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"7707fb638b294bf62ab3383c43edea8e84fd1bfa93271c3602ca1a2dde27c74e5c3bcff3d894e4319c32cfb3a9","nonce":"0a83e3ec68dff6ab367aec77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"31d0f8713498843ac43c966d951d8d33f66c1930dc590ebf725eaadf68ded63756298508600f6aca4521818bb8","nonce":"0a83e3ec68dff6ab367aec74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"374f565f584e20cd5570a35027db8efc8927b8703bc5959906bcb7e69badeae9ab3c32a4b9d7e5bb25f2e01bb8","nonce":"0a83e3ec68dff6ab367aec75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"083f4d748cca004290568419e875e17ef0f30f5ae92bffb49a7a0101fafbba2fceae989425cac61f7c79b60cee","nonce":"0a83e3ec68dff6ab367aec72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"834cdc5b98e83e5aed17a2f6d2853a06d58a29f502c32130d77f0fb3a14913a3f2306c45011f24e8590e52f697","nonce":"0a83e3ec68dff6ab367aec73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"3c49bc6d4bcfc4b8ce27d8d300fd1569644fb05d24e8b43f9e893feb748ef73d68f07fff34c38e9d669a87e4e0","nonce":"0a83e3ec68dff6ab367aec70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"1a3bdcaaf85e097bff62ef4f57d35354f9421848bcb65a55128b9c2e46a7cd0b636912fe9ad628bf647f8749e3","nonce":"0a83e3ec68dff6ab367aec71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"b36d6c372ee76838ff564374eb051ad76aac3ca72905230a8022143cabb47f86420f79c7d9832c41d85e5fb95d","nonce":"0a83e3ec68dff6ab367aec7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"abd491ea344a680323454772722a8870a255434575ab4b21dbf4ef699488e4eea5e87d8ae81d8897bc128eb2fc","nonce":"0a83e3ec68dff6ab367aec7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"6940deda0d60163e77ddbec83323155f8fb20d635ce7043c17108b87f6e0e267b6525fffca752d431f0745bc75","nonce":"0a83e3ec68dff6ab367aec7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"752d64cf31022c7fc49d8bc949e1009576639a520c335077107dc8b3471aeef5dde30e42cae1b7424e28c4a3d5","nonce":"0a83e3ec68dff6ab367aec7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"f8ec52dd667728177357ceffc997cd0577df79e263273c7ed83380facd8d71421db1b3869028b28ab785924e4f","nonce":"0a83e3ec68dff6ab367aec7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"1af1abf04064eda7002bb1357461007fc0509859f6d1e8db0a1f7024572a3093e92c9dca136af404a462941d06","nonce":"0a83e3ec68dff6ab367aec7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"a151758060bca1a49ec5f435ffc0165ffd15f3cc55408c871680dd19c8f81d233af13150b201bcd19461da7bd9","nonce":"0a83e3ec68dff6ab367aec78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"ee5a77730fcd87380e3cb85cc63d80ca6fb6033b41508318e68482b8edd9c3deae0aa607af203f9ac574a27723","nonce":"0a83e3ec68dff6ab367aec79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"9bc04e9831690dfd1ade293c14d5911ea5ee18c8e53e6dfbc0302920f5641ba214a23975abf3e6f1861ccb3451","nonce":"0a83e3ec68dff6ab367aec66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"d352c6ce1f36f7ba493a4366ef0d17c6ce71931192e14f412f54c222c156f42ec4e1c9d2b3e6a0309b08a02be2","nonce":"0a83e3ec68dff6ab367aec67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"f4022deb3973b78c59b52d5c1e59b19f63461bac4ed25ddf4c722f77f402fa122547a0b624feaacef07b93303d","nonce":"0a83e3ec68dff6ab367aec64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"21e8515c72919b447639a9836cdf65001b25f76de8b775eb0354b3c4eba80c7346c2dde766f01c8d00de7c27b4","nonce":"0a83e3ec68dff6ab367aec65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"9c11552430f37c4d44e31c800e883ade7eb517e699f856dc77a7e2c41bb11483d2bfa8ac425fb4f7ed36a14483","nonce":"0a83e3ec68dff6ab367aec62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"ea2658329e66ad5eb7abafcab403d3d6e3f3845d41033d0920a102a3fdcd394032b0fbb597e8ac966062d8f31d","nonce":"0a83e3ec68dff6ab367aec63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"28f34c8b856ca2d25d5a154305c165b908a33b94b8661cb5d695dba0841e70c6d1c3799bb590404e7256e727ca","nonce":"0a83e3ec68dff6ab367aec60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"ea2b71bfb7953af7a8dd9aadd5d3c40329c2a7923d95d6da18b39953a77bd2cb983b0ed9f05419ea7d6dbf3455","nonce":"0a83e3ec68dff6ab367aec61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"0335d7cbdbab79e006618c980e3f6d1fa5db7981ff07f37aedfc08c29690b89f0f529da466eaee2957ec2e4dbc","nonce":"0a83e3ec68dff6ab367aec6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"0255b4014574196d6b978d7f815c223ef021f3287b39e1ba5d3d87ba84079297550b379c7114aa637b4c98f63d","nonce":"0a83e3ec68dff6ab367aec6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"d0b9187015b3f324af37c58dd1190c93895b30c56106eaed97720e9bfe8e702ca1bb2fde255869266ff920dbca","nonce":"0a83e3ec68dff6ab367aec6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"cc78bd500f72a6b6ddea22396a6a4c26caed6aad3c7373995af3b445d582806a920042d255e7e6e81863fc3184","nonce":"0a83e3ec68dff6ab367aec6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"6802328bbbe3ed31229a48e2be00584ef65e6fb0e29b7bb6b2854f71557aa23c137a5f1aeaaeb04661e7fbf276","nonce":"0a83e3ec68dff6ab367aec6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"f504251e4c5b6c65f62eeb282034c9affc76d74f0b478a0a65b074afeb79d98d83b5711448bdb7aba836292a5b","nonce":"0a83e3ec68dff6ab367aec6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"912811b7fbaea22e8c445eabdb47717f463986b0809bad9526724d5a1656d0164aefc500b9fadb5ceb7be159a5","nonce":"0a83e3ec68dff6ab367aec68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"c627e5e7b155b3032c3801899bd768424c9484129bc36d8ad6d7130ce7543976eaf1ec3b81728bca622e7744d8","nonce":"0a83e3ec68dff6ab367aec69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"2972f018f727087aaf77f1b8ae00d82bb74b6d77586a7105d1934b5757ced9f47714c2d5537cb23c08b08a45fe","nonce":"0a83e3ec68dff6ab367aec56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"b37fa6a71544f627dbe27e7e31b57cd9f4ef109ff2b93fa83dfcf8be26a86b2518053fcd213fe5307621127539","nonce":"0a83e3ec68dff6ab367aec57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"6c136fe3224ba50648fbad7900fb83938c2f03442f3f9e0cd57878b2a9108592013b4e289cb243973cc8632bb5","nonce":"0a83e3ec68dff6ab367aec54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"9bc0883bd2b56792701e446800fc4dbb2b71011cd9fe7b2d2d7d81867cd25c710646b0d0480e05846378790a6e","nonce":"0a83e3ec68dff6ab367aec55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"439b44603a8d9cedfb962bd5498fd542c0e80d010b84d24e21e2b30a2e8550cd821800211c3c43062b673c735f","nonce":"0a83e3ec68dff6ab367aec52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"a65e3e6bbf3c265e90ffb8b79b72e3224cfda3a712a2be07c29a290e08ce2a574c6fad2a5a4806ea2c68a1783b","nonce":"0a83e3ec68dff6ab367aec53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"2759048fd3f6a39519f377b6d0bc4cba71f959c5b3b307306d413b2a4c9b0e36d5a83e71d6ff136b9e2ce14b7d","nonce":"0a83e3ec68dff6ab367aec50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"86f6eb5b361a139327adfe7c1123511e78635164e3a3467d3abbd58d343d24b1a282c7ac04f74be21c77446c8a","nonce":"0a83e3ec68dff6ab367aec51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"d62e24af16d1ea7bbb30407239143b04c43dc7b70068885e298e08a0de09a53193506e6d503a36e6e3e1917276","nonce":"0a83e3ec68dff6ab367aec5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"ebbe3f0ec53512a8c2989bd0608a9939585c593af3bb9c29bb5597759ae742d53d8386e3c1bfe6f342bcbc3f6d","nonce":"0a83e3ec68dff6ab367aec5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"2f8a321a3c683d34b655b966fd05aa0c3282587edcabf0145d670ebfca2ed79810ab32bc4571ffffc84f24cc80","nonce":"0a83e3ec68dff6ab367aec5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"d5a3f66d90afabf1f71042adbc3988205ceb27484cfa08de743bdef781373cac72c123bc904a24ad0b6ee1aff0","nonce":"0a83e3ec68dff6ab367aec5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"e8f2adfd846228800212510dd3f9ab1f1bc64b8107f8c859cbce6a08fd645fa9b4b3e41485075e8c046f8cf5eb","nonce":"0a83e3ec68dff6ab367aec5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"d47662604e872f0e4dd7e8132bb13ea016a3c31e753d3e52f69d5894c9a83817f7025794bdb7608c251d025de1","nonce":"0a83e3ec68dff6ab367aec5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"6bf2a95547410a0a511ef1e438c82042da0ceb01bf92afd009cc6e01f7f2ba14ede86c158b26ab1085b6e7a693","nonce":"0a83e3ec68dff6ab367aec58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"0f5793f5fc36f7c6afa22565d57aadcb07b126cceb27af7817ebfdc8f19cb2a536188ebb155dfdad7972d167e3","nonce":"0a83e3ec68dff6ab367aec59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"41dbffd972ffc4a711380bf84bbe5fee6b38e98ad17bfe902089d9a0a675ee17ba666f02610558f2f18212ebf7","nonce":"0a83e3ec68dff6ab367aec46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"9345128da4c501e559c42c628d81cc6a6f1e3c96f58ae7628d3ed0ec8d51b812e8bd81c80972916f27002b061f","nonce":"0a83e3ec68dff6ab367aec47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"0d45b3380e84654d5ab13aaeaaf123307741cba622b8dac971ee586f343499e86da8464d6789cea4dc2ee844ba","nonce":"0a83e3ec68dff6ab367aec44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"9c1bd655c5889dcdbe59ed08e43a21de79ba3f654c1f0c364ae7e42cda082787ca3729c4be3be76f3da5509b15","nonce":"0a83e3ec68dff6ab367aec45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"bfde7b20e628213491156616cd9204459ee4faa55194faa697e0f20aafa7137d6595de583e93620a3ae5ce7bd9","nonce":"0a83e3ec68dff6ab367aec42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"9a4f3678dce56d8584b8b25a4b257445a4a4ead16124c43117b966c95b5675f840c1b230440196d715885c963b","nonce":"0a83e3ec68dff6ab367aec43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"acfc35afa619af3237c02471f61c625f0620466993f295435142c8abdda5de8aeac231b328d6d763394fbd4d88","nonce":"0a83e3ec68dff6ab367aec40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"59317017821d29cc34d95cbf486f133f64be48ea82b6d6817d684ebff37a03fd9b3980d675ca6dfa221e6a5cdd","nonce":"0a83e3ec68dff6ab367aec41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"befa1e1dd96956259078c334395fec5fd6cd4b0bbcd18b8cbe71f380f54ad3974d0c916acaa66a885495bb7cd9","nonce":"0a83e3ec68dff6ab367aec4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"a0d3d7d3b337445036a4afdc3a61b2f6fd78e41ae634d07583fa1733e0713a0ec84d9d8482904e98f3380e3bbc","nonce":"0a83e3ec68dff6ab367aec4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"c5b2d18c7472e7920b9a0bc1f125cb4893bf1e3844d8a0758fe06374f6ee555bccab40e0d2454d9da9a4b80cc8","nonce":"0a83e3ec68dff6ab367aec4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"4551ea8610ba72a78c10c43fe2f32c9ab967c8c66acba63a0ec0e7382e1583a61c5dfc9201a9e0ce932b6d2ec5","nonce":"0a83e3ec68dff6ab367aec4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"2de684a0d88095c01799e7f048513007ec1e9e512333f3ae6dbeb90d9e8131178b0af1551366cccc7e7efb8d06","nonce":"0a83e3ec68dff6ab367aec4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"ffbf56b8eac900695f4cf80baf259b715d3cd3ec1da6c5c881ff2d5bf7b6b921539716352344cafe2f17a242c5","nonce":"0a83e3ec68dff6ab367aec4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"16949d6884e3e7af42eaec786f84bf6211209372801224bc35ed7aed3be0ec536432b2eb709cc0c51cb7f301bf","nonce":"0a83e3ec68dff6ab367aec48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"883c1c3c1c49bb7b30ca32d95e3811c159df70864ddfdc10c30a75783db4211f792f71041f08a4ac0ed3e0f5c0","nonce":"0a83e3ec68dff6ab367aec49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"5803f937ab4a4216a667123219c1cb8316a03eec105481d854fffcc0bd0c91585aba17765c47feb6ca79d571fe","nonce":"0a83e3ec68dff6ab367aec36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"a2550772660a5de2cf0b01e739f39b19d27073115706d884f4c2a449b931fbb8313ec8e5ac33dcdeb0e310e113","nonce":"0a83e3ec68dff6ab367aec37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"2860dbe254d13c965f0323721e9e4bd26da828da6198fabf943907e7ef029d970be2f51f0e203f9b3f022ed448","nonce":"0a83e3ec68dff6ab367aec34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"0f3e99d0fa3e999ad198656d48b5743cc8fdbca6aba29c0edd58cb7dfa8288ee4e9d2e92ff5aae6af2252821d3","nonce":"0a83e3ec68dff6ab367aec35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"da29d18b69e8d7607875a5780f9cbb9b0b96fc5c813b2fd955e425eaa6f0f26fc12f92cba5d23cc265a3178000","nonce":"0a83e3ec68dff6ab367aec32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"b1dc08ea8efbbc15337967ed890e6d1f6fc1ab9745cf403260ca4d9aedb6ce87fd5185464fb0967572e1bece89","nonce":"0a83e3ec68dff6ab367aec33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"64a41b82fa8847259ea195f7c4d447046864178f937508266880fba8171f83812380904e2f3ec833bfe1e6d1de","nonce":"0a83e3ec68dff6ab367aec30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"13e38e2aae20a41b6af852aac73de82623f3becd39e783f5a5209c852f31f4bb296a38c44fd99d9046f0fa6f79","nonce":"0a83e3ec68dff6ab367aec31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"6af6fd88307357df336b6484e790eb3eca1713e4bd0a57d5536b14456be2d4e2b7d1012955048a8b7cd332c80d","nonce":"0a83e3ec68dff6ab367aec3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"fbf6992516efbd4dfe6135c33bc8d953ee53f4709b2a4f3176887c11c71127fb0e931edf45ef14e0a92eb2bd7b","nonce":"0a83e3ec68dff6ab367aec3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"f28ebefc4c6471f8b536ec4dda49c41e244f266199bf7e558d36caa9f2e7c3959c66ac3f0fff6d9093dee7b6aa","nonce":"0a83e3ec68dff6ab367aec3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"60ea6deb0ddebee901cdf8ecd9db3b0430f60656facb334370fffb67bfc6b78f7fdef216c95d630d96a4d19994","nonce":"0a83e3ec68dff6ab367aec3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"fedbec2503a5bfb26c717bb2e5b48db4b332fa5811afc72007eb1b563f70281aa22edd5f80087e021911275142","nonce":"0a83e3ec68dff6ab367aec3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"e855955f17c95047d3ce436d668a73bd4f423d9ae0f3518c09a575fdfeda9fb367213a48a54ebc72c8dd1e355a","nonce":"0a83e3ec68dff6ab367aec3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"796d4def34134b5a5ce097fca7ae3d0097a6dded49acb0961b199fb2758d9ac4cbaf478af38fa517d064c98d83","nonce":"0a83e3ec68dff6ab367aec38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"e0ec7a9e01e695cd60d27fc202f27b8b3d8eed564d90ff63ea54d17b1f14eafe642e70646f929406c94ace7e07","nonce":"0a83e3ec68dff6ab367aec39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"215405d6f62f7ba21e63401c5d534340289804ef49d6dd7f5292af3c415b592ac9188a1e30f5b40e0fd1153a99","nonce":"0a83e3ec68dff6ab367aec26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"6e61d77583594e08ce1283259645db8daabebcbdfb691621869b4f0ef0c451ae76ad2111d93af509af9b368a2f","nonce":"0a83e3ec68dff6ab367aec27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"bb725be61c5567317e5572cfc85e14b8b9e2179edaead284b82cd7d14c996e2c4f478164a8e400ac92c3f04e52","nonce":"0a83e3ec68dff6ab367aec24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"330aebf7605d1c6b3c9be26c1f2c413b48d82a0dd705b3771eef27acf03f2d1452499774022fe275a71d9e4f8e","nonce":"0a83e3ec68dff6ab367aec25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"8555da9ac5fdc543fce7a9c4b70098e5aedc5c0c13bf9612ea98776fed4d4c5ef7b601f6abf53480d1f62b8a22","nonce":"0a83e3ec68dff6ab367aec22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"d4b813cfeace6165dbcc36fac3adb5f900908231f4d4c38b1b544306c5861094ead7b0c9c124c1844141604e21","nonce":"0a83e3ec68dff6ab367aec23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"e5076741bb2bc482f829eef6d8bda6fb5e192d3517ceedab964d66440eb743b6045761e00160c42e3e97ea4fbd","nonce":"0a83e3ec68dff6ab367aec20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"3f252a71489d29d4530f5780b73a155a8b6c33449f4b252c5cbfc4f39e8c3048252935337de9d461fd64164377","nonce":"0a83e3ec68dff6ab367aec21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"2330aecc7013fc4f1c3550aebf00d7d48e9bd74df13fda9c8f7c0813bc87f2141c44804bc45b51017373c5c773","nonce":"0a83e3ec68dff6ab367aec2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"7a0f4a8d8701651744cdf3a389e532d3ab123edb6d3ed0a40149c681b00f5a9af44c4d8e0aac76540f4e4cdb50","nonce":"0a83e3ec68dff6ab367aec2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"f74f98035e97f9fbd47c27e7d10fe60bc6777e3f33a3e3a063714b6559936607192393fa04686d86597ec80951","nonce":"0a83e3ec68dff6ab367aec2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"3244abc9d5699809cd248b1183c09cd2ae8479f163fc33b99bb82895397d6cc2e66f610d118f3cc63b995dd8df","nonce":"0a83e3ec68dff6ab367aec2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"e8a74a2834c9522f560d42c2cd1ef313687bcb31b06203f1a760ee7958891aeba6e79283c018060c3adce135a9","nonce":"0a83e3ec68dff6ab367aec2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"2759140ca7baa1362099677688392722c3bd17ec45b8a5dd0b29139c248554a3e5c30a2acf117e79e1b0f902bf","nonce":"0a83e3ec68dff6ab367aec2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"76864bbbcd4db5578a9cada23abc1f4268a32d38f501c19e4416d0c718c8d26e7f559ae6550f4d9b1e0b4473f2","nonce":"0a83e3ec68dff6ab367aec28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"54f241bb518b4711e5a7db23f1c0c1a476354aa28924d0921f0a07182bf22ebf227ca5744c1b7010628164cd0f","nonce":"0a83e3ec68dff6ab367aec29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"02125a3404eebe5c3f6a17c13521a1bfca0e12820ca5b1700200336faddadafcfb15f7ed72387f363e6dadd57c","nonce":"0a83e3ec68dff6ab367aec16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"2bd05b4053a0d5ba0f1218cbaf2a78af3b7fdbdcfbabc9b241928ebf859fcf8a12092af0957a75c2e9f516c253","nonce":"0a83e3ec68dff6ab367aec17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"b00e2df6d2b02a4d0315e83f11cf1335693f2a688484a28cb495d871a15280c8a296b649fca117aeb5942bf8d4","nonce":"0a83e3ec68dff6ab367aec14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"b2bd56c4281882adf43c858112e561f1b42a18364537f9af595857da3f8686922f669c6d1d5d6989cbd98168f3","nonce":"0a83e3ec68dff6ab367aec15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"66e5eba9b8c7f633cc80bfa2a3fefe494257be7b01a62ef0ec9180cb1f6e627305c6baf6350e4493a198b46480","nonce":"0a83e3ec68dff6ab367aec12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"eb81a0e32826be5fb778466f1f3bff0ede9b8ec0658c369eacef359bd3e97e8b4a89a142a54ab26596f3c4333f","nonce":"0a83e3ec68dff6ab367aec13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"bed78002fa94443c734977bfe2336b621ef2c496bb7cbefb59c286ce20d068a464dda4ba95c2f96e0280594aeb","nonce":"0a83e3ec68dff6ab367aec10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"751e5aab909b5d9db3b52d8e303963c58500fecd16597bd87acfa0b6fa843f7a0bce276e063bbacf22f0b02d61","nonce":"0a83e3ec68dff6ab367aec11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"c7e711b8851a50bdfd7ff2cf6a0dd06ab1a1c7cf10a3c953e689670bf7030375afc0ce7ca7f20b03b664876844","nonce":"0a83e3ec68dff6ab367aec1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"e014858b9567ca920558e5dc9958ffbd891bcde1118a8b7d219ad769d2209eca6a8cb96ca9b97005624835e5c4","nonce":"0a83e3ec68dff6ab367aec1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"b77b8283e6b3a377e12a3b6c2fcc33d80a56ca3731b4e7b08fa2220e599107b7fc0fcca148544c39becb6acebc","nonce":"0a83e3ec68dff6ab367aec1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"e0266581de01e16bc012da46ebc5c9201f8e8a583883953e23fbbbcd87caae754dd2b5e38d86513d3f0802a293","nonce":"0a83e3ec68dff6ab367aec1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"7b105b9e6c98588295eaa5c31a47b70066104b6f7bd96a1908dadccd1d1773c28fc3e2383a23c369cd0d58a740","nonce":"0a83e3ec68dff6ab367aec1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"a3dd58de3eaa6ad8a70afdf915a22873316c152f5a95058cdb5d627d1e4d9d035af6020e273a0a0fd9c5edf6a6","nonce":"0a83e3ec68dff6ab367aec1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"2a0f332406334e46353aad9afbe1b3dbc44e51c2a7db1713a9487772c7e87e3156578b26610a618394865216bb","nonce":"0a83e3ec68dff6ab367aec18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"53a35f8e183e53fc3e27950e744d5e09a7f112919b1a6265f7b7a6d87dcd6b6aacc10fc6510cb18461976b9966","nonce":"0a83e3ec68dff6ab367aec19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"2494b9820cef344302254fcae01c5954fd2ba5771373d75abfe0ad9e7461f0241f9b43c515eeef0d734bddba85","nonce":"0a83e3ec68dff6ab367aec06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"5bf8cbf6beb53e2ca4225da2fb75863717cf747400d190084872c292087fed8c15f8bf2a63eda4d8c8e33731ad","nonce":"0a83e3ec68dff6ab367aec07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"fa6b032a22ce4bae99988db14dbdab2861144d1e3fd2d6db6edc92a32ca60474b26f56e811d001dfb725722b9f","nonce":"0a83e3ec68dff6ab367aec04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"2f1195e21588927d6ad3c4e2f5780d689a033defcfdac25bddde69a7e66b90ec95d8f949e23369431d22c131cc","nonce":"0a83e3ec68dff6ab367aec05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"94e69500a241397648c804017bd96dde419d4d37415b6959623c7ee15094a98905393f1051c8abde9b5028dd66","nonce":"0a83e3ec68dff6ab367aec02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"fd6db8b647d50f7cacec8f2535949ca65d38cab573bc4a7e368e760224a7838bd4f2432673f93f93bf364865e0","nonce":"0a83e3ec68dff6ab367aec03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"9d3414f19f96ca5a771130b069207f8cff3a5ad0e7b31bdc1e4bef6810e183cc61d32557f84e3217acb15e3cf7","nonce":"0a83e3ec68dff6ab367aec00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"981bdb002d78b8ac8afb79b31d629e8eb90633742136f0d6a0fd221405be0faff38a583146e2869a8b64c82647","nonce":"0a83e3ec68dff6ab367aec01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"5dbdbed2e4592d949a7715adea7d20a20d28cb991cb8859871ad25624ee7a83417c7f469d59bb8a22b7dc2e39f","nonce":"0a83e3ec68dff6ab367aec0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"054a5a2c258ee2e903feeff8ef7b4006932f09876eb2859a1102827a9b8fd55f77ab0835b2a88e7d6b59a1e5ad","nonce":"0a83e3ec68dff6ab367aec0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"455648098cdc924a802d10cc6035ef8ac74ca7774b28f818e39a71f87830a81ce374d16bc68c8f1ed92ba78a67","nonce":"0a83e3ec68dff6ab367aec0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"f5a592933d02702a2b57be413c66fad6b10ccf0641d097c66f62a687d5e42a7db0c741cd3b3eb9dc9f75b09dfa","nonce":"0a83e3ec68dff6ab367aec0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"645be78193935238a21240835bcdada911fc2cc7a17c0a7ffcccd967831171105a38b5063f4b24181e108ad134","nonce":"0a83e3ec68dff6ab367aec0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"9eaf50c2b389faa85b884dbba39fc961061e0dd1ee58cf9814e0b70577945161d05f4010c3ac5a8a5d51ebe9e0","nonce":"0a83e3ec68dff6ab367aec0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"b9ce21c657f4bb8dc689f6842e0cdfdf998d274a5919d4a800b3fd2930d0494bb7b9e91c82aca6eae0c8b734eb","nonce":"0a83e3ec68dff6ab367aec08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"36a4d632a5130a36232bf491bf9eab04f75f0f2833b3320f43ffa517b8d63bb1ab8ea7467204367e46bb6f3f18","nonce":"0a83e3ec68dff6ab367aec09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"831205eac671217929a558ff342d48c65f1eaf969aeda66db2b47a25de14a51599fd29eb046a1036107f8254c1","nonce":"0a83e3ec68dff6ab367aecf6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"a00dbad5312e57c8be9c51f232581f95df74c6a0d47c3e5f3e9f7c6b8ba78814df7989f793661037ce9d533910","nonce":"0a83e3ec68dff6ab367aecf7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"9b4bc53bf4c8f7c70277c510a9cfa0f9d83633cf788c2c6a618639402e482da7ee2db3bf221df50be1e5c963b2","nonce":"0a83e3ec68dff6ab367aecf4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"4d243542563f7e5c28c75a1daf3a974986583f3c340c4e5d5cc8c5328630cc522ee3f227d7581fd2f1e8058e18","nonce":"0a83e3ec68dff6ab367aecf5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"880f9d9cdbcaca3a97ee14d58a04664dd6f0d06d1fd48b7404a2f7679053df025b6ebaa9d3a93bea2ffbaa91ae","nonce":"0a83e3ec68dff6ab367aecf2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"823de0d4d70d9b225178b5db97b3005dbb6e7ba92e1a68858105c26c8e93366e92288034591fdcc4607c29a687","nonce":"0a83e3ec68dff6ab367aecf3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"68f2d81380fab072f0a9c54068d637085d779cb527697a0652b3c1c970809d2034324b92f368415dd933b891ec","nonce":"0a83e3ec68dff6ab367aecf0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"6bf893cf858cd2b8fcc5cc14c780b0200e356b43e660179d7b13310f046aeeee5fdbfac068f0b3df10d896726e","nonce":"0a83e3ec68dff6ab367aecf1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"e49250f36df7f2932f433860da6338b14d446ad0aecfbc655c99bbce9fca0caa9b30f2651a67cc50bbd72427b7","nonce":"0a83e3ec68dff6ab367aecfe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"db3070fbdb51a2dcad774dc5667fa933dcd4bc341081dd03f92c89b995c1890a83161a6ae2e7975aead6370c11","nonce":"0a83e3ec68dff6ab367aecff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"736f39275a2cd1154ca137733987794b2b0e23b3adc55b628001563141cb4ab03fd54cb560ea8f7f94ccad8055","nonce":"0a83e3ec68dff6ab367aecfc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"ee4446f960a05830f1f464e93bd8eb2434cd0bebd3f7c41538997606bcb9d84ecb0f2e80da5a7091b4b8b39fcc","nonce":"0a83e3ec68dff6ab367aecfd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"ec7b9d39999d8582e39edd92ed607a68b74a0e4ef4063f1321bf5794661ef657674fc25a1f5e5a38dcd5e07b5a","nonce":"0a83e3ec68dff6ab367aecfa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"ba371615e76ec190a0e58043557e6f3c162fc0550c1d3c25152d1efa61d773808c3c883016728f8f3dc507a962","nonce":"0a83e3ec68dff6ab367aecfb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"901b4f2807de6a413a145d74c19fb435bd3b87dfd00492c2a9b5d6cce50f7150a466e1d6493cd153c3c127f3d3","nonce":"0a83e3ec68dff6ab367aecf8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"c4c1161c6f4b3db7126b93d51a17f1b8529299f86958108acc25296924a50a36bbf9e59b3d9d1dce1928d00e9a","nonce":"0a83e3ec68dff6ab367aecf9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"89a210d5c9d17345821fc40fcb41b2b6dece78938d16422d7ccb3e78a82e6b2300c344f72c3a88491b3992af97","nonce":"0a83e3ec68dff6ab367aece6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"401ee572ce6f9756878ed4dddbc54e15a18c3c769460354c71015942c62dd9765605f56cf054e60862320a2d79","nonce":"0a83e3ec68dff6ab367aece7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"bcec2642f807d33839d404634a4695438e29ca4c9cf098ffc6cfb401aa019fe160d7a30c2574e25f217660d46b","nonce":"0a83e3ec68dff6ab367aece4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"587009ac57a95a4778c14d4acd5754a9fa18680f018f56ec5e3641ca4746eef17bdfbfb54d9ad4eac8cc54633d","nonce":"0a83e3ec68dff6ab367aece5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"2245f77a2e1181738f872572f0458d68df457840b3ad78af6fa91843298db350b72d2e17a37fc8e03c72220895","nonce":"0a83e3ec68dff6ab367aece2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"831f36ec2e806fa3c569004594e274a1557f890c091622bf3b494077277123f9eb92b1f5243eabac720da2eeaf","nonce":"0a83e3ec68dff6ab367aece3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"1d661b0a1835b4b762683aa1022120e655fe01c2aad596abccbd6ca3d2f78c0d2eeb82c1285ea64f4084146d80","nonce":"0a83e3ec68dff6ab367aece0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"375700e09c9b331f726422ac8f0c799eba786e9dcffa192c879a200c48fa356894aa792ce9e222e65d88690337","nonce":"0a83e3ec68dff6ab367aece1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"9c8c7f301a663516f7eebcb3d362ce9a5f775ef752777c17b9b8b3569e2ddaa98ae5fdff75294b6912a5711319","nonce":"0a83e3ec68dff6ab367aecee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"dd3b9710fe28023f35f30b85a9316a65b65e01777544e9a81860cbed1fd851cef199853938d25d7c7d4de7b348","nonce":"0a83e3ec68dff6ab367aecef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"7525f7322ba1e058d8a63ef557b11cf1781142fac0978fbd15b9330a6b24466191cb3e1b0a4bbea26f479aa8be","nonce":"0a83e3ec68dff6ab367aecec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"2aec0b18b52d0a951603343b92113fd9811413464744c3a7b81b553ba7f7f389467418c3626985e6fe66c911bd","nonce":"0a83e3ec68dff6ab367aeced","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"2586011b6a8b241cd50fb415776e269bb2003eaba41fb08c143a131abf77dd6700c533d045e60e557fd77cf8f2","nonce":"0a83e3ec68dff6ab367aecea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"7199354a115a642158172d3748b279eb2f43d05612917909062db7d2b46a8a2895b0e20ecbcc1bd48cf408d2a7","nonce":"0a83e3ec68dff6ab367aeceb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"7050783965d95f253b96ac680187278258e20e8faa5017e3b5cdabd6bb3b87437fb054cc73bb7ca8e55f02c06b","nonce":"0a83e3ec68dff6ab367aece8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"a96d983492d147ce576c3f1c93ee1aef3506e059a110a0ff53bd696d05687bb656ccb00ef765caed864843d795","nonce":"0a83e3ec68dff6ab367aece9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"c081060da54283c927567b836d874ac13f2c77c0c20c00f4d6cb73f9686528f3e3e592c8ea0291586293a48645","nonce":"0a83e3ec68dff6ab367aecd6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"fb25da064a1b418c2a9a77577bfb6fee579dd3c400e509f6bb68ad128ff1922956094b605f54e407dc154d726d","nonce":"0a83e3ec68dff6ab367aecd7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"134dc737f7ff6536993298293b8324fda4669c6328e9bc8a8a87d0d681fa0764f1111db935a0446b8a23567af7","nonce":"0a83e3ec68dff6ab367aecd4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"792d405aef9c6b932fdb08dd94099ac55ae05c563eb3174ca3d11e47849323450940a1473435216629bab8c28b","nonce":"0a83e3ec68dff6ab367aecd5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"df1ad49f12ff28fbd13f60949ee1a73deca8f999a35ee199636e73cacdaaac7c36f41c5fdbe646aeb3006aca34","nonce":"0a83e3ec68dff6ab367aecd2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"7f41ccb9984512e22826626b0d968549dd0397d0b58d2570703f7aa6dfa63bd2c880234b2e257285ac2377bff7","nonce":"0a83e3ec68dff6ab367aecd3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"2c743d1914b5f2b4f73f17969f221f0570820fe7c44bee989534d979792d060ae26592e2ca6fc0133b9a94857e","nonce":"0a83e3ec68dff6ab367aecd0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"f1cf14c58b398c755613c7bb7305da65c90e8c2f068d510e51465578a094ec56dc4740ff84e34981fda1150bdb","nonce":"0a83e3ec68dff6ab367aecd1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"88118b1d3fae54fd6c377395b9401248b3ec4302a18de29e5091980f98918017703c12aaf434489ee7dd41a671","nonce":"0a83e3ec68dff6ab367aecde","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"80e8f6edc33d572046f5fe8800dad0fc19d898abebf25540ec3749f853dff3d1e0f04c55d6e7ae5d5b8b290f2b","nonce":"0a83e3ec68dff6ab367aecdf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"f8f7f2e0f54be34f5bb5b34b946d63f4b5b344e332772836188536c361dfea3871ef0712ec9f96998b8bfed13f","nonce":"0a83e3ec68dff6ab367aecdc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"064bf3effcd79a73569834e672cbaa6e5e365a620c6c0e12d9432f6776587f71b17c39a99b2734fca958b6b6a8","nonce":"0a83e3ec68dff6ab367aecdd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"2b461bb9af333eedb94fcb381ec0b4dd0e036f2e11263fbe6be80285153362ea8beb08525580f8807e116315c8","nonce":"0a83e3ec68dff6ab367aecda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"b4a11353a16fd495a508fc1270953f8aa79740f141812a5643097d6207eb27ba9546f5b7b99316444c55eecca6","nonce":"0a83e3ec68dff6ab367aecdb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"1f3dbe76269d3dee728a4cbdb10419ab0488c6edcde69594b1cbdc6e45072c5cce8fae6c50e917755a1d8b3891","nonce":"0a83e3ec68dff6ab367aecd8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"0b5009e9cecfa8687e652835a6068656087a5af65a01395c5e272622b25303f7ac5da2bc70c638a70b6ba74be7","nonce":"0a83e3ec68dff6ab367aecd9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"a86a16cb88ef1a5dcc7c5a22521bcf27ec5d4ae88ef208422eccb466edb8b9d8bab9eb77c1df884ed831b96d4f","nonce":"0a83e3ec68dff6ab367aecc6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"49a32d8f5af0a417d5633d798ebf65337829aff96b52303b7fd122bc80ae2c4c80d4d3483425360201fcda28d9","nonce":"0a83e3ec68dff6ab367aecc7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"5673c36dd312182cf5f0197afbe041ce098b338086d2fb19b78b05d2439274f8ae7e78eadae57750a2288ecaca","nonce":"0a83e3ec68dff6ab367aecc4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"275438375b8fb1fc1663d628d9729a6a2e3a5f141c9dd3372f06a83bae0a7ec51b5500b6c09ab8775c2c48173d","nonce":"0a83e3ec68dff6ab367aecc5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"87204569ca9b6bd3384ee7e7345a7068df9c859c467394cb387e897fa22860979681e64639bb4ca8a2aeb41fc8","nonce":"0a83e3ec68dff6ab367aecc2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"c2866507d71143f6625f31c9a5b80b2c2bbd6fcca9edd0f52764344e0ac3f4361a9d00366616813edbe5b80eec","nonce":"0a83e3ec68dff6ab367aecc3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"b0e4a35449ad16bf9a07cb654d9485e86fd949146f03106fb43a564628ae1985a4ad7d02e44f68756a6f83201d","nonce":"0a83e3ec68dff6ab367aecc0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"b0494ab3008b3ca44c1cd11d5cd223b627535f02c10d24aaa7a92525ca5a66fba9a4d7f6ba3cfacf2ce38673aa","nonce":"0a83e3ec68dff6ab367aecc1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"057515f3d1aa88b87e2c9372454a4e477025906dba20d137c7c1cb39b0fe737a2303a0959ce1b7a27f2115c38d","nonce":"0a83e3ec68dff6ab367aecce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"390385214a5a70f9fcaaf48ebdf2f5e300e69666a5c88f3aabe1d5730b8b9114224b832e6769b92e5ee477ab50","nonce":"0a83e3ec68dff6ab367aeccf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"01c157f42b16efe79a5f684297d153c77e91fb3aef0feec603d5b7db7d375ce69ad6ce0390941c85f2415dd2e5","nonce":"0a83e3ec68dff6ab367aeccc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"5d8e5ed5a474de44ebed7d1ebf8cef5a2b47e7377fa8d8233a7584b550f576b7f8969701afd4f235957b3b156f","nonce":"0a83e3ec68dff6ab367aeccd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"aa7733a97e66f4b521aac69db3ecc52b8998232841c5d443e35697e84e06809d540f8ec97ca92cc06ccdac8eaa","nonce":"0a83e3ec68dff6ab367aecca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"ca1eb93f5fbf6ffe1cd162f0e0fd3161ff62272f482a105c56709adce6b30c9be58cf96d454e8a695394aaccc3","nonce":"0a83e3ec68dff6ab367aeccb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"b744cc62ea6e3657e2dcb7f5a159a107dad20f10c4b1da31ccbf38f1744d58a96e340b0a82df5a6ed35d0b158f","nonce":"0a83e3ec68dff6ab367aecc8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"42cb680d556f404ab78486cb7f7b7174a95b1c05dc87dd90e2818e3a6574c1c833ab4fcfc682106e2d64693741","nonce":"0a83e3ec68dff6ab367aecc9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"5d31fc7fcb261357bd92071350bc7314a437851f873c8cafcbc01b96f3394da5b5ea7087a6586484eb4a99276b","nonce":"0a83e3ec68dff6ab367aecb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"6d7bcbf8b32eae4bdc33d58b00d87a01ca0333a507ff44a3f8c6afc72f58f216b9c4eb546167bbdb930637bd63","nonce":"0a83e3ec68dff6ab367aecb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"ee90794255acd1e8761c936fbe4454ccd5cb01de3b5783157b5438f3b0196303f1761fe7ece04ffba3e63b3262","nonce":"0a83e3ec68dff6ab367aecb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"53859cd49872cbd68cbeef787ef7469e698206fdbb60c664daa4dcc01cd9cdf97bdb73eb6e051f43f211304257","nonce":"0a83e3ec68dff6ab367aecb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"b29845bc5d3f2f2f8c5caaa30abede66e54b58f52e352ba8e2307e5750024dea580a7ad965a1b6b97f787c9e64","nonce":"0a83e3ec68dff6ab367aecb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"0e2b8011c5ae5ffaeaf90412cc9e7ed7bbfdc0082f47d73ab6dc7092116a48e2ec75f92ca4043d158a1d226e82","nonce":"0a83e3ec68dff6ab367aecb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"05ad1a4ad90f05a599ef5d86408b293d7471952c11b7ed0bf729f6d2d778494b226e58c81feb805207938ca868","nonce":"0a83e3ec68dff6ab367aecb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"618dc7a0a0ab90c048996d98686179678288448ab30f5c00b921e9baff9aa55224f0bdde3628a36cfe205f24bd","nonce":"0a83e3ec68dff6ab367aecb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"b1572836c04f4bc96811db56151318c79afa74fc1fd9a2e75a4d93bd7662524b7926a7084b32742666ea80f95f","nonce":"0a83e3ec68dff6ab367aecbe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"cdb4c5017bf7d929e7913a8721801f541e889aed50c4209a249e2cfdf8b0a813454a5677a4fbdd3e240ac00f56","nonce":"0a83e3ec68dff6ab367aecbf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"5429bb7c57ff0ef00b3102b25e1b0aca2d596e3c02ec6c3fd72703a8fb3c8194bcd810c21c6735b5f11bfb264a","nonce":"0a83e3ec68dff6ab367aecbc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"00be197a708cad38ef4b569bd627bec0fc61914a3a1266d0f2e7da717079753e40c971de7aa1f630f0abc3f622","nonce":"0a83e3ec68dff6ab367aecbd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"fcc977fb6393fe0aff7e58887c2eddd7069beb19d85a23e1df687edf778779d3c0ce88e909725f7fd99154eb1d","nonce":"0a83e3ec68dff6ab367aecba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"b9eb22b67fe0f4ac59364c75d5ab46e434c4c1538dc6d5002996c6d16e19054b18335748e9a3076a6afb65f32c","nonce":"0a83e3ec68dff6ab367aecbb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"ccd76f8515019759cffc052b42e01111500a251cf6e4296402764b215ee9efd6be26216bb40e5c044e581ef2a0","nonce":"0a83e3ec68dff6ab367aecb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"0153f258bda09c698325aef65839d251990bfafae6b3f35576da6d9d963acbe0f03d95e3f061941faa0437fda4","nonce":"0a83e3ec68dff6ab367aecb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"827ee58e1123cd372d6826307b072756dc81d0c62fecf8bfa42692c211afabddd3b5f77ac0bb0b0439482affe0","nonce":"0a83e3ec68dff6ab367aeca6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"0b02c49387e26ee645de02a52e7d772c446d6de8ae310d7ed8b55d451e30b08a0f84e893ab48a0dc978d1cdcc1","nonce":"0a83e3ec68dff6ab367aeca7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"faf5df427e096b8f5097d3a878fcba4dd888b1d72de7e50734a581e7a48028a126254e008fb701e5ae6de9844f","nonce":"0a83e3ec68dff6ab367aeca4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"1b5a48038d2fffe6a05482275dfa16e618d64d73d7d64440d169b9f7a2dab0e19b9b6016906e9447a6781d4b10","nonce":"0a83e3ec68dff6ab367aeca5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"8ddb802acf465dde0bf7f3b57f13908837b1c7cb61163b08e2a8a9baf44be8474377218fdd3b6156276c7d4b16","nonce":"0a83e3ec68dff6ab367aeca2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"946e6000fa1348e381a5bc0ac4ec76d0e75955065191ebfc48a8b79d02f38061baa95997d9f15f096913ad5d05","nonce":"0a83e3ec68dff6ab367aeca3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"2361ba25781098fb610ca47ff1907297627e727a945ae8903ea30b29ea1eb2eb4b0f1ba1c2eae169e1a6bbe87d","nonce":"0a83e3ec68dff6ab367aeca0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"c746f700cb73af155f62dc0d3e17d5dd76c39681cd61d39caa292636eaa417aadffd8b4081ce5b8923917db810","nonce":"0a83e3ec68dff6ab367aeca1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"e4585d73566a875ab6de3c118be0da76cab622814d151373cacac58f392ddf72f2098cb64bd8ab4bfbf9f56269","nonce":"0a83e3ec68dff6ab367aecae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"f064aa52be6dc3b0b8308fccb7a036e786cf98cee654819a9f0941b41c54ea21f9ecad404c3bd29f1d6e46a055","nonce":"0a83e3ec68dff6ab367aecaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"52e9e3246f5aa6a5b78ea16d38363ec7294b43f2f32872de6baed821591e90f48798bcb28ccb3a8e703e29b1fd","nonce":"0a83e3ec68dff6ab367aecac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"78aceec79ce3146c50152302970c6017fc371008303257d8cc75fc1bbca00b7142767a1c2a8e46126cef0b5231","nonce":"0a83e3ec68dff6ab367aecad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"4e724b52204f19b790da4136936dbab9c2e92a54ff16408c78b3fc02717d48661683a2650c15ea59066dbf0dc9","nonce":"0a83e3ec68dff6ab367aecaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"7601e3d2c7fa6c5ad6538290aed574d48dc49c2cbf27b8249a155ae919f0e13f69ce2dca0a79020aa7c95a5fc8","nonce":"0a83e3ec68dff6ab367aecab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"91edf630e17c470ae76992153c5a872d8060535cf5bcc853f626806ae31cd422b840e6f61038d99b13663f527c","nonce":"0a83e3ec68dff6ab367aeca8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"cee84acb24cfc3245a08346e369af6370c576fae55cec11efcf9bcc0d68e879d265d83046fcb9e0187a511da67","nonce":"0a83e3ec68dff6ab367aeca9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"bccc1f83d20faae60836f943183cbc5fc38a71b530bcfa4781756e5231111d3dad7e1ea6519507d2fed020ff60","nonce":"0a83e3ec68dff6ab367aec96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"de0f05ae4c25f80d245d8b9df730f3523cc5b6b1a6f7376caf050d8c8fa1408b33b687eaacca4c5bafb395d19e","nonce":"0a83e3ec68dff6ab367aec97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"dfe13e97d7e48691176e1f63cbe50b0bd8b27f01a9fc9d9b981d42b680d0e0389b7f3d5f0e25e4ba228f38ad9e","nonce":"0a83e3ec68dff6ab367aec94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"5543e7d001d23162e95acd6cf5c693389591a452b2e6c746f28a0b6a7c5c214e7c4113fc599a5c3e974db5b4b3","nonce":"0a83e3ec68dff6ab367aec95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"5c38bb4a9e6671cd5d1265225380aca0f0d138e70cb1c394b2d62ffbcf725f050e9d20a971ebbead630d7c8ff4","nonce":"0a83e3ec68dff6ab367aec92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"15e3d812b1e2eac1d8261a16b8a4ef0672ba51124309966f86da8ec96004fb486b97fe68bf421e365d12dbb0a7","nonce":"0a83e3ec68dff6ab367aec93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"7ebd5b7e8fa0b1818ebdaf886b8007ba2b67a1068e929c013e6c03a4dce9fd9ca20a98041e540ad59f59d2a570","nonce":"0a83e3ec68dff6ab367aec90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"ffce4af5472d13ad2b824f3b40c2fa1ba76221f4baa8fc342b19ae2d8546082cbe5d6751e3c9782ade9bc457a7","nonce":"0a83e3ec68dff6ab367aec91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"3e923bda4a58149dc618fc174fa1fa4d3c1aef251d1fab98b61ce8e76601eb1d113e4e90b0c92e3a7a03980737","nonce":"0a83e3ec68dff6ab367aec9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"2ecfa76d7cc599e8ac355d0d8294702cd865879b9261592a49028b1d487197efdd3d243685dab8936c2c6f6e90","nonce":"0a83e3ec68dff6ab367aec9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"373a5bfd447d44ae8c47bb0af5a4322c653a02a3a12fa3a574cc911f1f2e9ccf0357ccc07f360aed8cd0901734","nonce":"0a83e3ec68dff6ab367aec9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"5d048412ddb871a23ac1d30da23d1a828c86769ff75562aafdf8fc3815146595edd0fed78192f0dfb573ec9ee7","nonce":"0a83e3ec68dff6ab367aec9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"8011be39b23a7067e443cbb1121e000423d75ee1e62a5c40bb8393f26fb18355307cf5d3d990d11b6f478ead11","nonce":"0a83e3ec68dff6ab367aec9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"4f9729d396b2c7a9b445b21423107dfe692d4a5439a3477f0760408d45145905f751241fc75181b55f7598beb3","nonce":"0a83e3ec68dff6ab367aec9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"5ff087cd58c7c4ff1ea00f3d29dade007834ddae2488eca107fb5a5d6716b2ad2e5af33738705dbbd8d55802f2","nonce":"0a83e3ec68dff6ab367aec98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"4e667299acfe0b14e315a4637debb146f831c97b6ffbd1492b303eb829645f01823dd0bd0b74e3c0abd1ace28b","nonce":"0a83e3ec68dff6ab367aec99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"b06aa174003cbd1584289a28957ca77af9489fcc204f0af159646b2d86a382d416f6725602609baff76923191a","nonce":"0a83e3ec68dff6ab367aec86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"11e59e86b77658c310acf64bc3df88e3cc6c9378cb412e3fb31aebdcdbbcafbaee76aa694adc0c13ad3e01f837","nonce":"0a83e3ec68dff6ab367aec87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"8cbf0217855faf745b4ed8f45ac7fe9375be71c94f7661d13ede1d16e676a2966bfa59aa46e290f78813df73e8","nonce":"0a83e3ec68dff6ab367aec84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"c738cce33f108b2bc3fbe855a547da23d4f05994c29c5948b2ff01a39aa05387ceb00a5b55662a12f7e40fb38e","nonce":"0a83e3ec68dff6ab367aec85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"d0445c2251dee22df74cf3bf6f86248ffa79d133acdd91038f5ffdc5e68dcc86411667032b28ff3a2899a2813c","nonce":"0a83e3ec68dff6ab367aec82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"33f6cb9100d37aab05cdf44355dc924df9aad4b3ed57f59f33397893b3a2eb5f7eaafc4babd416328107dfcf53","nonce":"0a83e3ec68dff6ab367aec83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"8237dc7e467d8a02bf85e5d2151f88a3e7367b3879bbb084da0518d519724ee82054efcddc929de36c3f469638","nonce":"0a83e3ec68dff6ab367aec80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"5b4e7d23263bc066a637266481601668e928dd146a36699a5c9e8f434dd53750c8f0f771fabb5c0ca501f80cf1","nonce":"0a83e3ec68dff6ab367aec81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"7ebec7d76d0bc90a2acdd9467f3112b488a070a3210644748f990b4d1244687b772371867cc6c96860fd052ce1","nonce":"0a83e3ec68dff6ab367aec8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"19db00c1f550646983ebe9c76b40a8aadafbb6db6891cb613849f7475d06c1ce5f15ec1d1f6d61f67799bf8908","nonce":"0a83e3ec68dff6ab367aec8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"7deda648864a5fe084ab1a4e81b91d41c7bc8a766d5a749bbf8279bf6710051ba403a68a3bfd68464f76bdeafe","nonce":"0a83e3ec68dff6ab367aec8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"8752c84507cc3030e07c6dbeec5891e7d2895f47db1d490a01dc717d1ff1e6d516f906c1ea6c7e93f8a88ccdf3","nonce":"0a83e3ec68dff6ab367aec8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"cdd257c1717ac9583a59b9d2e912dfd84f5ae4cd9362f9eae0fbe16aad401ffc74e0dff4964647dbc2f4d74c00","nonce":"0a83e3ec68dff6ab367aec8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"c2c6ea0962248e4c9e2ac44918e55ef35f0c3229cfc824bc291ae5831e1bfc898ec149b8549b55ef538218300f","nonce":"0a83e3ec68dff6ab367aec8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"294ec2ecb42402f956097cea3884e277da7f31c5330625c8f8bd505ea9edc9391a8a71dea6e5630b720fc319fb","nonce":"0a83e3ec68dff6ab367aec88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"66f49cb936720430c8f743941517da3d5ce2f5b0b3474d9b763b49ae33efe7bc73d34b4b571367d64f7d9acc38","nonce":"0a83e3ec68dff6ab367aec89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"e3d52d402b5f3595de6b36f2eb561aa31b94c5f59579cfb33daff1be7b60fcd723ebecb1fb62a0ccc6a11513eb","nonce":"0a83e3ec68dff6ab367aed76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"500a545719ae476a37e546393640a815b8146adf654a362531991124598d3547"},{"exporter_context":"00","L":32,"exported_value":"542bd7fc364a33818f72de3bad4c9e835bfa23a88bc9450aa8de5186aace9a4e"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"4e28f07c1b97037a1d58406d0cb352dc809d72bef2d39c7659c18eff7220a29b"}]},{"mode":3,"kem_id":33,"kdf_id":3,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"c22292683065ad456ac2094190e03a475dbe3df2e168d491705248efbc604a09d4ee1f4fa227220619d432ca4a4576f985ced130046afb97","ikmS":"b3ee2ce1eca5796fa60b6f35406e1bea927dce7e9d9afd5a2e1fe3a8844e380a9fa4fcf64ea334333b067c84d6f0d57609f6f79a982fa7b5","ikmE":"f8cfb4dffa3c0f9f91f2741f3348d9e4dde67060a3e5bcd72a14aa03a245b9936416ed67437e2d5efdec508ce89abc5af61b30e6310ef103","skRm":"1a3a18501c72594d17f0585d6733ccfff0708017f953fc16847c3302dd59c0fb19f2ee461e37296ab899b375b7381cb51d310091667d1c34","skSm":"2f3ad84bfd0aef192435905b6be851e7af2bd3afcfa9ee3d07a71b5d3c54a177e2d390df67b7f2aeb9e5bbf39473922bdbff828e30ed3bb7","skEm":"18693f75f1552ecd7908a9f0df7a09eaa7a4653f8dee2ae20d95d746e521d11c8b6fb23672788f8ebcf87bd6e2e194133533146e0ce96591","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"3804f263e18bdb35fc46c5c845f17578c165faa53e4721763067f741e64906f898c52ea08ddc9e730bb5fa744120755cdfcb359fe7e87522","pkSm":"ef872d4fedebba01ae901c5dcb846a0cee375b7ea23945685c402be75fb65abe1ff3750441ee15b709f097e99509e67de153030570c078cc","pkEm":"3a0face6e8c9bcf6a37b1dd905061e21bf5796113114f789776df5f744d4b4ff18805969a0c13067ca2717d95ad41daaabeb876fc1775760","enc":"3a0face6e8c9bcf6a37b1dd905061e21bf5796113114f789776df5f744d4b4ff18805969a0c13067ca2717d95ad41daaabeb876fc1775760","shared_secret":"b2592e738abfc5aca386ddf7276f9494652d9834da28dab9df89c2221e0a1a58c75b88c3f75d6bd52826f1728a16f0eb55653659bb3ea031999a999d324128d2","key_schedule_context":"030a7c8b9e324bd689cfa3b72dd78f6b347be3666df100fede193d2d7564373b5859fdea4160c82285f4d0f8e5c644ae33714a93e91c2c82a980a152a8ad127ada94b5b0e6ed9749cf5a584367aeee9665bfdcc13ea89374b725e4d30a351bbcc95bc70b4c35cc84a53ffd1e1877059f35f9f9c98ae168ad89a3a7087d7e88b855","secret":"557950cfeed313ae102bb804a9a0c8ef69251d684a5d1a30b4ba4f62f561d4c9fd5edbafd41660a4b2e89a1f9b9fe21dcc1a9ee55a4b1e232db9260ff119c5a4","key":"7237964cab69643d53b6fd6d8ad0ce733789b9c008ff28de3361456ec04e1d87","base_nonce":"a124c973c73a389d6e99e451","exporter_secret":"9ffed635c432c9afc397203ab16bb7d84c7e057c466653c2754ccd89d6fb4a3384e5ff173965ffc9a75b5d937c7b13a8e86f2c61631b18b4c641c835af14e102","encryptions":[{"aad":"436f756e742d30","ciphertext":"1fd1efa596cd6217a90fffad6d7140cb719cc0ecdd322d6914df4cae312e462b75b5fb3eb84fc7b36730acd9f3","nonce":"a124c973c73a389d6e99e451","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"dd3da43ef5a834bd14b700aeb541fc29067ce619971c54a199bf20bbaa9a55815a943b4eacea818ad9da4874fe","nonce":"a124c973c73a389d6e99e450","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"e6391a98c5e6f0fe942e082c7dff753eca807e4307892838f72664f28cf7596aa4d0a98d3b2600fbdcc47389cd","nonce":"a124c973c73a389d6e99e453","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"fe1cd9405527bb42c2807245203707256cf47b1486d18b8a918f6367fca343f38c9b46f4542da230f716f5e499","nonce":"a124c973c73a389d6e99e452","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"ebd3134278e265df9ed37f6270c7c3f386584c319de0480a40e8813811ca99ef0bf3fb0c382bef398a636e18e9","nonce":"a124c973c73a389d6e99e455","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"3cb54d812d4c496de111b782d837a22bae60070fde8103498c75e5d6609d1105de1ad8896086a583581adbaf28","nonce":"a124c973c73a389d6e99e454","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"d78e02aedc0423ad55b37f05caad64617b33ce332e6d345edeb6b43e94d40e08412fc4c39c4dfaac2ca415d398","nonce":"a124c973c73a389d6e99e457","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"6f57344cbe5c3a648828600e635e7e10a0cda6dbff3426f5387d4ae3c1a3c9ef52a006451fcb5d969a221c2f94","nonce":"a124c973c73a389d6e99e456","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"641fb917324c564ca068c49f818f3df1f27d9b30b2320bfa89d28480b3263544abc556c7e9f1496def0129b541","nonce":"a124c973c73a389d6e99e459","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"d174e2829f61d89707dfbe797bdc02fcecbdeabe6b9c98a9931ff510ca894ee35b12b315fc5bda1d504e007ce2","nonce":"a124c973c73a389d6e99e458","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"29a98df376995dfd6606597912b7f53b2a9ecde88f766077bb9e06d294eef32004860ddd92d3da56c74f4abc28","nonce":"a124c973c73a389d6e99e45b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"685d8e793b7bb590ce22c908ffc42674ae03c8c0905ceb7b26b35618f7d8671cd4d669552361b5975c086b8e1e","nonce":"a124c973c73a389d6e99e45a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"262ab04d6dcd199c5b8d51dfa2d400161a56caa4ee6c313042436dd3146d5d568d57edfd0c7cb72351beb0ea35","nonce":"a124c973c73a389d6e99e45d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"3039a02cac118ff5368fe104704a98426d0a01dcaf6feb538670e8c23ce481384b44589eabc7631611ce940aae","nonce":"a124c973c73a389d6e99e45c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"e2bbe8d6af9e5d4539a6053c5fd13927f9babbd5a1dff943eb7295cc2a17125f0a0f32a1e624b5f33819522ec1","nonce":"a124c973c73a389d6e99e45f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"384cfa75fdc0295c89de9edbf6a43a44847473ee1a3a1389619e05deadb65b57fe9613a6112a48d8c0c0d46dc2","nonce":"a124c973c73a389d6e99e45e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"07fe923754b2ef2217a22a3379b839b70a6d4b5d01ede3b36d1efeaf691a91b714c7a1eb6263276fcb24cb65ce","nonce":"a124c973c73a389d6e99e441","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"f94961295258b515a333d8288e43896a3b87a387deca97ee844643e7efe5b18cea506be0b20cd4793c7ef63498","nonce":"a124c973c73a389d6e99e440","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"799b0de651400afb5e70e5d2b460ad3424ca77da47ffae4131c81f9fdfc81a7e001299cee0ef2a0da0dc026ef0","nonce":"a124c973c73a389d6e99e443","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"05b5ec0c4ab23e75ec4d05d9450cb1b807a836b37120a2392edd205dd7acea0e1f2102f26d5123cd24b383515a","nonce":"a124c973c73a389d6e99e442","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"927b31e85da97bc0be8a7a65b95af9aef6cf0500570da5ef7106d6490ff90279dc9d1bd88e8289b7d1868e886f","nonce":"a124c973c73a389d6e99e445","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"13db5b5b429e2bbbb5c0ad80115087496f29a6620a22e0a0c4fb3a48e2ca67c93fe71420d4ed9942d118661172","nonce":"a124c973c73a389d6e99e444","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"686af21599f5cbb680f08b6732fcc3e220d4aa533ea516d4c2989db9447dfb8f216bb290c2fe18c68bb6b70cda","nonce":"a124c973c73a389d6e99e447","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"7d994eb15f24671dd4c03124b19e8b33ac0c2b9bb266776da68ad006df6d0f7f4b05c570439e58e64f20da73fa","nonce":"a124c973c73a389d6e99e446","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"ac1dd0b251d0c38c3d1f0532d663a5fbad6781272b56bc79197f336dbe5661077c34cf159a4e6873e72c8c81cb","nonce":"a124c973c73a389d6e99e449","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"da7e19d52a71b161483dbfc5d57d1c70c57fbb1afe7c59a511bd2f7ef2ace6ca25b753af81c96628acbb8a188c","nonce":"a124c973c73a389d6e99e448","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"6c650e5fca937f83e8e3eb0362e848f23659e4a8394614adabc55100935c63458d40588070a44cd979b7d52713","nonce":"a124c973c73a389d6e99e44b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"4ce474f69fc337c65654ee65cb4d2296f1e2d6b7b1bd925f9ca6e1d70bfa56ec656a8ab82a64ab71ed51da010d","nonce":"a124c973c73a389d6e99e44a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"cdebdab5588c6fe4cdc7c9e391382eea68551e736c9e946de4873359202215930c0fc537d08257511f8911763f","nonce":"a124c973c73a389d6e99e44d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"a7665e8e35faf5fcc5e799779949f8412655d874b6b5e2f8e50bd61a70a0b275f618f110ba8842bd928b2d538c","nonce":"a124c973c73a389d6e99e44c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"24e112ead96d087515eead14e86aacb52610f0e2a025505fb7adcd47dc195f9d1427dedf4bae00b3071155fa25","nonce":"a124c973c73a389d6e99e44f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"a3cd5ba699c6efe044a8884f6ca561c64ea2ea676144466164f1e17feb6a2817804151cabe76603cf72191609c","nonce":"a124c973c73a389d6e99e44e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"14732c137f2982a3edd83be846ea028048a75e9aca06badc48d820fade670f9f202befbee0a57f23604d817f58","nonce":"a124c973c73a389d6e99e471","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"fe8ba7bded7c763cd4817a66787d40ac3aba4d3269fa829b03075f031b0d3433a632a5393b82044cdbe75e7f95","nonce":"a124c973c73a389d6e99e470","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"7bd54f6ea468036878897b1f3e2e6b237af51ab4d43a108794de9694dd71dc3eef8ca6ea35d8000f6ddb190042","nonce":"a124c973c73a389d6e99e473","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"6cbed76c88a31775ff46c231a0542d482edc72b56d20cb74b89e0cecd6f5db53292f45667aa43b4c7ad4b60eab","nonce":"a124c973c73a389d6e99e472","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"c5d773e67309b9f34ce0495d2d1733437223ac6791cb0e93c49a637f87012e25af5cbe646672f504558b44adda","nonce":"a124c973c73a389d6e99e475","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"f97a692bfd33dea9626ed83bfcda7e8527320905d85921fbf93429f2a088efd19b2e194c623a3c31c15be0d60a","nonce":"a124c973c73a389d6e99e474","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"fa61b90d4418ddd7d8b6715b1525c5b2951e70d663f2b6236ff8e95cacb6bf86beb3aebf4b09646e0f17c5dfb4","nonce":"a124c973c73a389d6e99e477","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"5eed7c79582b1f3803ca26fd8fa34ed28a3a41e8eb528ce6b595bbc437aa777147f43de380ff37e3e996f7595c","nonce":"a124c973c73a389d6e99e476","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"1a825357336988c523f793888987957a5fc4f52b851553eaf2c144f51deefa86d265013e4f9d44eefd4b5810c7","nonce":"a124c973c73a389d6e99e479","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"25ed5b1f4080261097b1608c382788cf2d93fb46a9774ffad840c0e50d72a6883a48b4d92d5c0194cb702332c9","nonce":"a124c973c73a389d6e99e478","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"0683ffcecedbfe4ecb87815f0faa541ff8dad00cd449b55fb5c0f19fd4f63d9c7cae74842c88c9374944c447e4","nonce":"a124c973c73a389d6e99e47b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"a5e96b24dbc670fcfb400993c92a289c8413b817a0e301d9a8ad5379e5ca1ec3fb29ac2d3403823016415092f4","nonce":"a124c973c73a389d6e99e47a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"57e30935a1b29400af2647f1e8fed6ddff018c46c38520fef1d32f454d48cd2b322047c27c12a26fd83db876f8","nonce":"a124c973c73a389d6e99e47d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"2579ca7a2082610cfa9e0bebe5b2d4006ee790557496c5885ac1dfbc2770a24e538ec856b5e743100768cc958f","nonce":"a124c973c73a389d6e99e47c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"9df45f363c41d42266f0c8febacd348c7b1e9670a8bbde4e9f5b746bd8075e1f4024ec0cbf3915bbb06d977936","nonce":"a124c973c73a389d6e99e47f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"4a0d09fdb8dcf2d1581138cd7f0b823b6b669cc7013cc7017cc314c1a5ddae42f13f36a69049917904adde4a40","nonce":"a124c973c73a389d6e99e47e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"4a3d0d41466398899cc2a90d1d88597dfc58057b2bc6c6b95a4aed723e4ef43081c3b93a66cef679b84d2519ad","nonce":"a124c973c73a389d6e99e461","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"5fbc1427263f83edc89adb599649f317112f2246683fe35d5c6c7ec710e691a09f5d9388d48f88a601e45614ca","nonce":"a124c973c73a389d6e99e460","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"0a519654c3abfa96c0f24bff129ecc0e5cbc37522ae2bc84f7163c77ba7b43e90e37bf247bc32df68879bf731d","nonce":"a124c973c73a389d6e99e463","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"b8a0bce14ca384e3a06b102949a78cfbeb76738c1b04a74ceb11ca2f2f9075b0b0a1b88d34bced40e5ed972e31","nonce":"a124c973c73a389d6e99e462","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"a4386e5d1e00ad10c14c2586bb8c45968aec25874fea95d57570da7a0c56c37624f183b0c5923b9303d16c4a05","nonce":"a124c973c73a389d6e99e465","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"632b6c28cc235133d9403c6cc62eb5f34d60d847b5eb532ea201c84d1f805800d20d70cac6544ea8656920c1ad","nonce":"a124c973c73a389d6e99e464","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"739b1d400e78132931416e04dd18480ac4cdeda30ce0f9944135e45cc52257f763e7c8dacf0c350b3791efb345","nonce":"a124c973c73a389d6e99e467","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"3060eae2970f4d25d4781192bce64bf33d92014273de30ee02276c146d7862b2c62ca4a7003445f5a5d8e43495","nonce":"a124c973c73a389d6e99e466","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"3a54c9d97dc96a812889ea746f0f133e86d22ab176e58b99a2ae72f70cc6aa1abddf46a34b2cef4a5a52a3496e","nonce":"a124c973c73a389d6e99e469","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"da41259393e92e763557886475a7671f116ee49778e7a61e1df2d60c972f45b3c6fc0e2f0337c15fa08b5d5e93","nonce":"a124c973c73a389d6e99e468","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"1c658b5db5c4cb53f7ba4db9253dc41b0191f6ad5804d5b21f01bec468f3a72aa421633d26bb4667afdc7edb4b","nonce":"a124c973c73a389d6e99e46b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"e501520ed3785f0dea1caac2e7260042c2e88a4ec37afa8259174990b1adf66785e757d6e56958534b0ca892aa","nonce":"a124c973c73a389d6e99e46a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"cec88f30609b1298864c8a255ee7245cac826179ba4cf1e4363faac00cfa3db64ea894a9d5d8988aa1760848b2","nonce":"a124c973c73a389d6e99e46d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"7fa9e853965455869e446024dce1f672634cbad7481cd8feaae0d4c6520e9b2b7f4b5ba5f6d95f61bc6ef10600","nonce":"a124c973c73a389d6e99e46c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"5533afd47f8bd651fc48762f22069a1121be109fa4c12e0db4e429daa5c13b550ab0ca7a181019651fec53f355","nonce":"a124c973c73a389d6e99e46f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"af24b2a931785a65bd0296ecde035433991e378f120700d3bd50d5e953c1a84999cf5e5c04ff12b7baa302448c","nonce":"a124c973c73a389d6e99e46e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"470b68b6b7a43fb96e87fe01ed90fdeeba19c8817e094d650c94bc7491b01380407e417d59ade705c7dbbf99d9","nonce":"a124c973c73a389d6e99e411","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"10f6fdcb1aa71cfe7d767652331256edcd5363dfafd08070e9464c5f47c88042a8c42f9c708cc79aa28ae2cd88","nonce":"a124c973c73a389d6e99e410","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"239bd1d05bf2fc4468abdcd8e929a84e6906c8fbaa81ca0ea627dfe8733753d78959e9f4e53c5be97efb2ef7ae","nonce":"a124c973c73a389d6e99e413","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"1a304175044f6f8fccba73d83d92ca99f95839951b75ca1cb2badfe00047f3787f0c39f29e37cf7ca0d4e65331","nonce":"a124c973c73a389d6e99e412","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"f5df37fb0bc06b8ce856f98344137cc9610334520e3b0282de8a802853af930941e00f6e224fde4cbeed39e407","nonce":"a124c973c73a389d6e99e415","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"8899481fb8d2f3903d2d13bbb215544bc4c2a92ee5c2faff864f83005bd4a3473e2d508739305ac2ff9700e03d","nonce":"a124c973c73a389d6e99e414","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"e36274d133fc65b884ef06fd04c20e26409ed3329412a2c34ed472acf437ba816c21ddeff3963e62e889bbc46c","nonce":"a124c973c73a389d6e99e417","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"e591cedf62bc28d7300dd04b94286f2408147bb173ab4b2b3f497912aa36c28fe64e9050674e52b0a72278a005","nonce":"a124c973c73a389d6e99e416","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"81d62844cddfeb73184ce4c6f7016ed1e2c2e779e2c9a72f200dd91ba791606a514147988987148d4190f17feb","nonce":"a124c973c73a389d6e99e419","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"e58304a89ffb0f7c94b5ac7e44d4d6d2277b9766042d0e1bbf8d854266468646b3517f5e19b7c64c23e9332da3","nonce":"a124c973c73a389d6e99e418","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"95967d98c888328fa1844f42e34c30af1c098d647f23e5d104d2f949d7bf575aa020cb4896d62510916a0ed475","nonce":"a124c973c73a389d6e99e41b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"23cce7ac2b7260f59caff9ff7c1459371706a4edcc7482e7af34674e53b58dc07c9e8d14afef108458a371bd3f","nonce":"a124c973c73a389d6e99e41a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"8284adb60f8365b8b3604e55edd8e5c97adb9a5e35fd863784f0c08e0f5bc2f9eab6aef11edbe50a98dcab8b44","nonce":"a124c973c73a389d6e99e41d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"bc3212fe2c3c3032c7030edc85e7100b172b363d58b21259b829021c360bffe10a22bd16f8d09a7f8c5fca17e4","nonce":"a124c973c73a389d6e99e41c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"986e9ddb2ebf90a061e09cf6856a7c455cb1d105abe8cb2eb9ac9beae41ab36016bf83ac5be1109cf1aee381d4","nonce":"a124c973c73a389d6e99e41f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"64b90b01181f6efac0431345432ad2b111d3a17ba5bb30cc04340ce88fa7f1453e5de99cb43d8958e64a405d08","nonce":"a124c973c73a389d6e99e41e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"76db3e1f1e63dec009e14d9c0e4bfa48ae0f07981548834ac0c4f75232d6d5d274278f00e3f7006c572e922051","nonce":"a124c973c73a389d6e99e401","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"c455f234fe6f5588d97eda9345e2c8ec06f66d7fd456a79df4077bc1ad6f01b58e116f740607ec6f69e80cd51d","nonce":"a124c973c73a389d6e99e400","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"e529334d7ae4e6889fa1232d927bb514b5fdcf85963ebcbdc72bcc9b7d2dbdecfeb82062d865b9270135f51120","nonce":"a124c973c73a389d6e99e403","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"2537cc25630e3c0bf2894ddf208a91829877a5a4d596f44518199e172ff207756450a68fc296641653f042364e","nonce":"a124c973c73a389d6e99e402","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"8b61f2de816f96bd3f7997ee53d2713262109ba5e9dc3c9add44c8fb35cf317f2b76f1252e1acfd1181c6bc9ba","nonce":"a124c973c73a389d6e99e405","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"d9d12ef804c1db1a02d175bea2ca577756a2c3dbbf827e06e99b3f39e9bb9bd4222e76716e3614514dbad37397","nonce":"a124c973c73a389d6e99e404","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"8dda4470cd66a3a51abc3e82c11afda4ac0245e713b3808b23fc9384091038b8672a98e4585161da7e8a981bfc","nonce":"a124c973c73a389d6e99e407","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"4faff72a74e91ca0ffb87f817d8be3938961e2cd72c0a6abca4f9c164170911726a4afb85e68234747df30a0e3","nonce":"a124c973c73a389d6e99e406","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"00e6a49a953d8349518646cdb09eca7e91769c92dc8bd8bafe7d5eeb767254754d33ff3e7d2c764b529912ec39","nonce":"a124c973c73a389d6e99e409","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"33fb95b5074fd817c38943d3a6f82e22c94456a53f33fab9d19d53812cfe5c43a8f1badfdd733e457b01b79d81","nonce":"a124c973c73a389d6e99e408","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"bef630608380f56f307c6522b751e3d430ec108a016a7dbe0afb6bb0e055c967d8f322589762da7c9fc07a7de0","nonce":"a124c973c73a389d6e99e40b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"6e744e375893f3a1f59a9f8b0a314626e1a4d18b2a9590a7862017b0a326a5b21a78c81885312fa99cb7aada2f","nonce":"a124c973c73a389d6e99e40a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"0dcc341f84f579149b844b473f8e152a22279d07c4a74d1570c189f94fa2ce5e6bf77da37cd0526253e63aaa6d","nonce":"a124c973c73a389d6e99e40d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"8597476c5352075e6def3852da2eca4f0f20487350bedd675d5df18576bb146f81db27d069d17df3bfc4e3e1db","nonce":"a124c973c73a389d6e99e40c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"053645f11a03b5af320ad7665520b4a30d6531b8442a37020f97cd9f6fc311968f81dd238f1f715f1b14fe6631","nonce":"a124c973c73a389d6e99e40f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"6330390f3fb68404ba6f88f15f3c4f0eb4e29723cdd0023d429e083ff64ed1523c062ca6aa2e8a5ef17ba71d1a","nonce":"a124c973c73a389d6e99e40e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"e5d1170a9aed1244da60903f0f9fd537c9314d8c2855678c2f4ffb095ae095619934dcc60f03b51c4cfa0dfd2a","nonce":"a124c973c73a389d6e99e431","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"1a46cf64103d5f24b86435ff018b91005fda696c0fcf827143d85a2bf016c9ac11bd4b7bfdeb739e6a78ef50b1","nonce":"a124c973c73a389d6e99e430","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"c243f1016dd22c0d0e0e9afcb3cb4242abd9b370ca2a2296de71c0716d2b43249cc75aba4200d9263d0c4cf5d9","nonce":"a124c973c73a389d6e99e433","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"4ef69b00f80624c9e4754c0bed23e1ffce0aa20022038bcb7c9f21affc558bfca94fe06296f72be86722eaf0e6","nonce":"a124c973c73a389d6e99e432","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"fdd139df65a86ee845b5b4927a4fd3fb6ceb9a42328de2a65b092d1f3dfc14d79baa4e2b648b78be5513e3c39b","nonce":"a124c973c73a389d6e99e435","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"123b716b5fa1a77ba3b0e3b08065c66ece31386bd18cba1e4f5cca0740719bae38f133ad3b444471d133d4e37f","nonce":"a124c973c73a389d6e99e434","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"3606a695b87fcc0018b47577ee219b16ba184045391ac4137de20f0a92d9338712e73aa47c6ad2df517d5bbc10","nonce":"a124c973c73a389d6e99e437","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"c99c4d4ea410c40e99661dae55f477567b942cb27c9c9f6e17728938efa9afa313dc4ea28c06247cbde098fb9e","nonce":"a124c973c73a389d6e99e436","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"0d2cb1f919864d97dfa1785bf2fe821a140819d001d6361f7bbfa783dab5e4e51a0eb890b2fbd1afa0f316e95c","nonce":"a124c973c73a389d6e99e439","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"5adeece281970d69777e6c7180bc9e8fa807c884ecac3beebbb9dbe221224738b46471e93f5cecc74d64699207","nonce":"a124c973c73a389d6e99e438","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"ef0e041297bbfbe2d90abb588be79bf068a8da243019693bd634ce7d0776c3ea2278e723d30613a22156f92eb9","nonce":"a124c973c73a389d6e99e43b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"f138fe9d9e694c50c4f8915d4c05074345f4d14c7e32409362c98f8967ba9bd4d8f0c8285521784f3ca8f721d1","nonce":"a124c973c73a389d6e99e43a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"0a0ddadbd3abc819b890364c00dd38a80f5188d7dcb34911e59206acef96c9cbe2cb88ea5a6dbfe0fad336f5d4","nonce":"a124c973c73a389d6e99e43d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"f08de28f85f9791fc42ea9ee4c31f40f2c3572cb40e3c77307d7822305fc162c16215e5bfc04dd76aa36581771","nonce":"a124c973c73a389d6e99e43c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"ea67bc43fb3589134aa1dd5b724bd0227bab7ab2de5b7628592e0e227929059f13dd7ea98e40d60659eb03a220","nonce":"a124c973c73a389d6e99e43f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"45a6454fc14df3ddcd3aee7eaa27dbc4f1acc2722f1937f41fd134a002b6ae2c0d7122ba6c25e07db413287ea9","nonce":"a124c973c73a389d6e99e43e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"c4b67aca031a03b1f44cec77f9f8d041dfd15cea8421bc36031ef8696fadd6c164a4451e3b300b8916262a0259","nonce":"a124c973c73a389d6e99e421","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"9e8bd8a5c9a8bbc280800e50c5249243066ab318183690430b1ee3f3bde14cff11149113d546bf00800471456e","nonce":"a124c973c73a389d6e99e420","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"41c9b688841ef3e095a2956161cf783521718bdee0685ed8b1c7fac9fd9074ba6c551b48dc42613166578e4736","nonce":"a124c973c73a389d6e99e423","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"6e2608bdaaf5e68d27d00b6ba975c626aa74765c35c2449b2db034537e95e0bcbe8455f3290beb0d289f977307","nonce":"a124c973c73a389d6e99e422","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"7adb8a449d2cb2373d4f10bd8930738358e4930c74f26d7dc13638e37a19e29e342fad58f611a7cb37951575f9","nonce":"a124c973c73a389d6e99e425","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"0d35c7e7be5755179463a471f7f82ec4de8767ab665c18cc6285f0b5d89bfb22b0bb33b85056e0e8b4f9f79436","nonce":"a124c973c73a389d6e99e424","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"98a1bec7ac8f04763856bc0362d740fff7d6c947f0cb3c692d733d523f399fb84d52717c675cbfcf984f386306","nonce":"a124c973c73a389d6e99e427","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"05966f3eba3ff847afd97b96864e14ac25a4100bbd17b150c97930eb91fdbcf6d2718a1d334938db8a5fac6d0c","nonce":"a124c973c73a389d6e99e426","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"1f9ec284715b07d8d181a9e132a3e7058cd61d31d8ceffd1f63a1b4bfd3e193b6d9d6f1baadc827dc3b4d81306","nonce":"a124c973c73a389d6e99e429","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"12b9149f2f32b191d9f21c84a5c238b2c64d06cd82b963961f909ea1875fc2ea4af37f632d50b56efe8c045323","nonce":"a124c973c73a389d6e99e428","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"0335cd1874271fd62b46e2db8e407f552174de45ccaaf90de07649c949d13b2bf7ea127d05cb6cc03ee913a2c7","nonce":"a124c973c73a389d6e99e42b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"da8674388e4095963eded895dea9a7ffd872ef1e18c33f9d29a98c118492d95df1fb8af9fa7cccad151877eb43","nonce":"a124c973c73a389d6e99e42a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"31c1cf8ee57d55986c39740034bfea4fbb4b6661dc4eccfb68c38a6599b29c3befd75140589ee278c8f83e1d10","nonce":"a124c973c73a389d6e99e42d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"cb2bf683506ec3f510905eff9c6422c931d68dd28f3573249bafa11c6293cb1b615c970963c482284571dfe8d1","nonce":"a124c973c73a389d6e99e42c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"9d1e0ff00d88ca6a024006af3fa5133cd407d4ccfdcf80b9e91dd3a9cfedb0354c8b86005d6f0f744cf744b8f9","nonce":"a124c973c73a389d6e99e42f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"4b9f98b3285f04220a231e9ef414267e6bfb8eaa7f15a279cdc7c0ceaa958eaa8916b7fdf3cdcb401ee2157177","nonce":"a124c973c73a389d6e99e42e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"def6e0505fd920b043115ad6572647a954e9a949156981a9aba38c7d166eb39c53b53e1e5d724fc5b88d5981f2","nonce":"a124c973c73a389d6e99e4d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"91ca92b4740926e4a495f201aee2d0d3a37ad4a1e744bccf4af6873aecdd065d92bbd4ff6d95830296699afdf6","nonce":"a124c973c73a389d6e99e4d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"ee6d409be4eb386c51984302d323ab8660389ef2add6ad4ca532c45523b8e8f7d7700ef62b69dd65cbd32a8959","nonce":"a124c973c73a389d6e99e4d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"a1e3ba1bf06254adc693db8d6aad247bdc24dd2ce9f266a4171c92ca795cb8d442b522196fb88e3390a46001fe","nonce":"a124c973c73a389d6e99e4d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"ed124443e96bac0c53a71dff40e336c2fa61b6366c0012906ce173985922ac34c3032d4510a88ca0d371a32f0f","nonce":"a124c973c73a389d6e99e4d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"9e24cf7ebb6d0526a5d50289078a41350313d64c736fa70f1ef66c346b1fd09a360f0751875bc1c6f7e6dc3205","nonce":"a124c973c73a389d6e99e4d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"216daad165295e3e373a2397c591518331e7fa9cc7948cc1e43f682292bcab3b1d2d2b292ffd691e404bfe054f","nonce":"a124c973c73a389d6e99e4d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"bec9744c49239dbebc94b1048e5dda66252dfac4bcfcd1d2d4e32abe6400aab461d43192ad913162bdb355fcb2","nonce":"a124c973c73a389d6e99e4d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"f879b0e8c25cb91fcda9d8717ef26e6872d0eb8502f7c1d00e482533657a5a994c5313205f643170883d035598","nonce":"a124c973c73a389d6e99e4d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"c9f30babf7cc424b55d65ff427358a3fa7004975f528e303aa7d3b87a0308c2163cb0a47d5b3df0e50326c861e","nonce":"a124c973c73a389d6e99e4d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"5ed08e8937749bb2576a306a04178563119c19d03cbba2304a5941f872afc548bdcfcbc5cf3ae04162c5e4e111","nonce":"a124c973c73a389d6e99e4db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"df0875f9afbb8a0acc16fdcf9a640a7dfa1385939b5127dd7a593f01f5cfd409d412aaca9a70c093b624f2f8b7","nonce":"a124c973c73a389d6e99e4da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"d32f3d2a7fc2c60138af9eeabeee2aed0acdace422f2738d951b3ddb68bf9a55ae39b588f3a014fe060b7b4a2f","nonce":"a124c973c73a389d6e99e4dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"642fd79738e208935654ed18bcb96af53026b3eb2e073a2c04ff142a7394bcbe5d0da6f228e6d85b871c1bdb03","nonce":"a124c973c73a389d6e99e4dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"487c20705713c5ffdd47c546c7c87f2a77963bed0f57bffe45e966328d2b93f9c5c74e621c36fcde19ef245f53","nonce":"a124c973c73a389d6e99e4df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"135c25acad7530625131fb325fa2d0335b6490e578602f0ec795443493e442459e43e8dab3c81435a81eb90dcf","nonce":"a124c973c73a389d6e99e4de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"0731ce995d7ab86f44f1ec19fe2424a8a3ca09820ea1236cb22455ffb3bf7d4d611fbaa8a086e2c5e487f7e7fe","nonce":"a124c973c73a389d6e99e4c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"5ac3aec17c112e004d6084cb670219107c9b776c1623eb5e4f44587dd127f8f6bbd112cec13af1141a8213f302","nonce":"a124c973c73a389d6e99e4c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"622a0caa0cc7ca8765ce3a660ac4183fab979e4354ef11a58b4a1086695f33b1556b5c312e2be42958af837b92","nonce":"a124c973c73a389d6e99e4c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"b699b09847ecc54f70c734860bd548fdbe9e9156ffc317346b261eb715e33bc2c527c1ddf63c95715240d3e4c2","nonce":"a124c973c73a389d6e99e4c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"1cbc0bd9b991e03d93129b88f3f01d4816f820e4ba82f1c8f7afa48c81024e2b08796587f56440ffe7075123dd","nonce":"a124c973c73a389d6e99e4c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"8fca04f82df1cb979a94a99bc3af296de747b1447371c4692b11c681e43ad6f79f323dccaca5b3dcde7bbeec32","nonce":"a124c973c73a389d6e99e4c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"efacdb068589f77f4c321c59cfe38a94f6fb3eb2366b727cb939c079e684172398485f4ede69f4ff1b9eaac0e3","nonce":"a124c973c73a389d6e99e4c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"f30903194d0158a2d63900b542be897d59e0f51a0b17bdff1e0e92f613fd563492867bee09b2064ee6617569b2","nonce":"a124c973c73a389d6e99e4c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"c42725124047d49b77655837877c7b254154fc79a7fbebc629a65917b0165958b32485d4c57c1ed615aaced373","nonce":"a124c973c73a389d6e99e4c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"6094217746f84be0c5271ab1e2f785ffed6989ea28c6d253312f2232154bf28bd27d89e3b9399d83b95fc472bf","nonce":"a124c973c73a389d6e99e4c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"4da9bcb7a90de29a6939869d466167a4b7793c6bec9bca2f0ed40b0951d88f1c509277db9a40797cab97907417","nonce":"a124c973c73a389d6e99e4cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"190a380e1ebe00109945e989649fa87cb4f44f4b12fd741f7467d71ce60e51e406042262a1b7b4471dd42b529b","nonce":"a124c973c73a389d6e99e4ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"8c5356dfcbc27ae6db3f3ca2f48f04bd63b14077a168c5a62fc8c92f1cdd5f6a765700f7496439bd7233db73bc","nonce":"a124c973c73a389d6e99e4cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"295ed0b6a21d5b1ed4d8be67f44d5c0b6e876fb60d2d4e2e59e82dfa953228e5a03b6a5358b9de68fd0265306c","nonce":"a124c973c73a389d6e99e4cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"b719643ad2a215363147e6551400942fa293bda979e81ffb5d1fbb4f21d66dd37ea4e5c0767298764575e2ed4c","nonce":"a124c973c73a389d6e99e4cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"6cc7809a99cbc757fc04c57416372854088354d5bb1e2e3eb1ed9f2f2f55ba00edfcdb9d28d2d101d39afc89d6","nonce":"a124c973c73a389d6e99e4ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"fe8ddf4dc7f6be62be6e241abb41f68ea35cc2b468fcdc647ba7a56c264182801fe94e709abe93710c2fbb65ce","nonce":"a124c973c73a389d6e99e4f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"cb7f543e78e447e0cdfe5e0759eb36a5e0256b25f2a96d3a9a16800f35e8ec1694570e2a50359234bbdf35002f","nonce":"a124c973c73a389d6e99e4f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"497399f273aaf8c72ad6031d6a1de8cb2c65a70777cdf9fcf594e461cc40a82ec8b22d7e9fbe27b4191038ee11","nonce":"a124c973c73a389d6e99e4f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"595fb776b823aa1ef837652e63575f4bcc869442c5a421eacb32a6b92161615853c8ae6f40de8cfd8ca8924dce","nonce":"a124c973c73a389d6e99e4f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"f2d28801bbbf0da8fe9ff1a4a5dd7167caf4d64164251bfea6b5775916444fa5141eaf191f947e8e26a9662f34","nonce":"a124c973c73a389d6e99e4f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"77e92041252fde8008a6e662e0f52c265991c40a4ca7c3dc5d2de29e0e78a65a625a1558ff52686c4fb4621f88","nonce":"a124c973c73a389d6e99e4f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"5632df1c4f7acd4ed0d7ccb7ce9c673958f39486b7b79ddd3a7f8bdee51f7bd3c8568e761ab26386107b9f1f42","nonce":"a124c973c73a389d6e99e4f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"41109f3cca513657f7915885737be3d2319b0c76c6c8684c4d109ef241777300944c31f645608ee5eff0e7a038","nonce":"a124c973c73a389d6e99e4f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"4b44eaaeeeb6a22846b9dd39d8f66307dbbe7493428eba7061ccb2901036f8a1f8f2e466bf23d6d201b9e28a96","nonce":"a124c973c73a389d6e99e4f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"109ca9a890304192dbf1b4e21c2edfd914d8018372ee8604138842e435e08d4b27b7650e2784ea8874a752a6fc","nonce":"a124c973c73a389d6e99e4f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"f1d13f6d4cc906913cb29a07f6b1919f18e31d1a22704919ba154d12635f71367dd22beeb1168af6931f6472c4","nonce":"a124c973c73a389d6e99e4fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"e07bbb733b26ef812b8a8ac045dd3a013f749c14aa9c49a5edec17c3530935216b39c4485f33a71bf4978c94e7","nonce":"a124c973c73a389d6e99e4fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"c3b75e26a94469dfd1891d250ab2d32ef0c286786154dfaa12b7e4cd8db534236f7a011869257cb8e5cac07095","nonce":"a124c973c73a389d6e99e4fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"244868264ee3cdf20594eda8bf41e50a978ba3e7c2f7b64af1119aec217a8abc3961a3c348195a9ab0f0a56f05","nonce":"a124c973c73a389d6e99e4fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"c72172e721a1ba4565a3595cdd80cc7a99a97cfc003d0108408f17e27c889c1cea759338ccc6a97bd8650f9a24","nonce":"a124c973c73a389d6e99e4ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"d4f37fa67a2e04ac32bf9416791912195727e1f02b453d450df7378b54b0ff976da74ad4059cb5afd6b331f5e2","nonce":"a124c973c73a389d6e99e4fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"2e748370b0c60b1812aa8267d6f17218beffc98b47db8fd116bf104a1d9e50baa68b820cdc57dbfa6eaaabde17","nonce":"a124c973c73a389d6e99e4e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"788f18e26f919b1825fb1c23497f6875070a4de55c7c0fd4e6626374ddb1ae20e2ad297841758e182a53f8b030","nonce":"a124c973c73a389d6e99e4e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"416b332e0ba1dd2644110cc233d29a12cd8d13b1cdfe3957d099b443efa34dc78d9feea98f32174fbdf786e15c","nonce":"a124c973c73a389d6e99e4e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"d2a5efeb8d302d0a638ccb790a30c08e267f637340647c9bfab6453da83923f2bb18fb1cb7bd589bcc044acc74","nonce":"a124c973c73a389d6e99e4e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"d5980b7ebca23024e12c81d8fa1649abb770543f1b0aa788fa77b2b0179fdbaed2a1e09825817d102c055cc83d","nonce":"a124c973c73a389d6e99e4e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"037533f30d1d83f0e2e321d22f4b3fbcdb3642a12fd7c189db348ab7a2fa9531f515ab24fcd84a561716b21109","nonce":"a124c973c73a389d6e99e4e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"7405c9abf878502a272d76cba1ebe87ee28a1107545ef78627c30bca013826248399e81dd91da287c6458160a8","nonce":"a124c973c73a389d6e99e4e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"6777bbef3538190ea72ba99e17ca9829fde9e599a8b41a387ba558d6af1fb9b16f7d5b347de79740b5088f98d8","nonce":"a124c973c73a389d6e99e4e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"6b667f4418d99232fd39312f2bd4995410f08fbd5fde6589ca1ac425441377ab8fd4e151e7a855c209bfe3ce7c","nonce":"a124c973c73a389d6e99e4e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"99aa90193fb2a799f92908e63dd4c3cd0232d151d3882df1139f7041dd315abbe5106a781d306d0c7515251d45","nonce":"a124c973c73a389d6e99e4e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"77221e2636f982ecdbddaad5b31e22485d97e61c208eac3889dd0ee7d7f94f6d72e64789b3d688929309a664d4","nonce":"a124c973c73a389d6e99e4eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"ba1b2eafd36b12a4ad119c1b0492274f6aa05e5f1cae9c9497380416be015738c8dc2895f1dd378a103aab898f","nonce":"a124c973c73a389d6e99e4ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"7d29dadcca5b214341d9d71724465e1e775d07d67ce6070683600761687ee9a5af729b5291919ce999a4990ffa","nonce":"a124c973c73a389d6e99e4ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"79a360c28c4edd883e4632a8764ff4ad5ae68f5b1b141eeb45754eaf5f05e6e5b0507f6508f3f12484495c9d84","nonce":"a124c973c73a389d6e99e4ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"188ae9cecd5907f21e7edb35b8e785596c279eed2a9f735d627076ffa42afe59cc53e07b96f0303e76c19f740b","nonce":"a124c973c73a389d6e99e4ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"e0da9b37cbdaca22f46d02949ca85c2dd95f787834b252a63c677dfa72b880d627e7ce52984264328f27107250","nonce":"a124c973c73a389d6e99e4ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"e36cf2a7c118f31f2caa6445f157c5ff8709b8d9a5b59ecdb5d7fa22031a2139a036da5d11e4bd329fa2fca73a","nonce":"a124c973c73a389d6e99e491","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"f3bc0643b4cbf0fa15603fe34029b99430ed86e2c322698e76347205c2df91eba0419413eec6e0f12ebe3b9082","nonce":"a124c973c73a389d6e99e490","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"0b9c99d2dc1e527cb429621871fa8e03ad2106bff4e75bd509d875aae7de8a7281ecf692c4570b086c08838d9d","nonce":"a124c973c73a389d6e99e493","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"683c96ba5d8008ed96ee9daadd89560e78f5c9d83b8d1f89544bd292784854ef39aff8ccc10b4373c1d156367d","nonce":"a124c973c73a389d6e99e492","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"d26881e6c88b5759e7657ccec7a69d759427f8d3b285987ef351f269d46ea46a65813901e874f4fcf4b2389f99","nonce":"a124c973c73a389d6e99e495","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"6939ff165cccac3e2cb25622a2db01726be4537ad246a8ec1144cb49632ebc603b13079faca46aaa0844e2bac8","nonce":"a124c973c73a389d6e99e494","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"187a325beb9d93d86eb5d113a41219eef07f98998210cfeacfd9b4478ea97be64c2715d3c05d7da47c5378b71c","nonce":"a124c973c73a389d6e99e497","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"6d79d7b5c087a0483e70f321cb6ddc01e6f8a16de14403373b139a1ff0730cf51c13529980ae5c93541cec33d3","nonce":"a124c973c73a389d6e99e496","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"a18dbfc1ade0dba1d5ec839b9b94bbaf7615c6ee715d9a712e966f761c34f4e06baea9a2e8d5df6ea5c842af74","nonce":"a124c973c73a389d6e99e499","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"ba85343930075065b5817a17ce3dc4d840bdac4a490d16c43344f228856dcf4b393667fa07f4f170c7de2c21a4","nonce":"a124c973c73a389d6e99e498","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"f24a439d345a8768985aeb1426572efa7b66ce3cc8c1f98023d16c4d970665a9e5c26d6433a73322a4a5bb9dfd","nonce":"a124c973c73a389d6e99e49b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"376b2b1ae7d05e98b41c68b69c63dea82964c3a5c4de3349aacbed7e06ff42223f5f8ed4f6ebe79d3d84245622","nonce":"a124c973c73a389d6e99e49a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"ddcd3801a692a14e6f47baafc7e0740d1083a1095c3f348afe5051a7f9d4977258ec52c6061ab88f1502e8c2a9","nonce":"a124c973c73a389d6e99e49d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"75496498c81eb1ceefa21a401f0da49265f836f7d3379ebadd7cc9d5fa6d3669df3786fb2763c300f4818c9140","nonce":"a124c973c73a389d6e99e49c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"eb1ef449fb871314c8d67ac91198c675e29f6bb1f3a473e807fc0f27ac1927e3cdd32a429edf9e0de52d057791","nonce":"a124c973c73a389d6e99e49f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"f332e487fa824e21556a46aac2327623418837432d0f3a340d67fa345c1a9d7a711c67ea8844a5214df98a1bdd","nonce":"a124c973c73a389d6e99e49e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"f2b85f1915e7abc194211d009dd147f7ba313ca735d62c12919179a02103f44fe422b433428db5df7caf681fd8","nonce":"a124c973c73a389d6e99e481","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"307574a904bd368d00d5232d74385a1064979e4ca240005df1dca19e667d4b369d81f53a910abde9215b3ca7fe","nonce":"a124c973c73a389d6e99e480","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"d688a0294c4283a9d7a9ea4cea0e69e5b381de7a69c7e2933a571304f08723ba7c9156cce5b0295ef7ddf57937","nonce":"a124c973c73a389d6e99e483","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"0f78cffafbdbffaf2b2c240ae6fbf8410e2fd23c7dce6ac63dd5dc3e39539767ded8addddee65e7dbbd34b3461","nonce":"a124c973c73a389d6e99e482","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"0f299760c7e2a732ff8fd6dcd787ad64ca45c0edb7ae46137ea659ae4d0216a80fe916b25ba91c530359f54aaa","nonce":"a124c973c73a389d6e99e485","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"9f5cd4aa313211ed944ea2b78514aafb1454a5ec760ac5c4513bb5ed4798b0cae58aaf1e7af70851ac78c5eeca","nonce":"a124c973c73a389d6e99e484","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"11c434a4f0c3e3a0c9d2df0936336fe204acc843717a436f4f801df644b350892c0c91eb8682aa1b0e783093b8","nonce":"a124c973c73a389d6e99e487","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"82f427252e38b9ae7d3be7adbba43175d4a43ff083c81ad1829fcbda41daf40e9836842478425b904160e018f8","nonce":"a124c973c73a389d6e99e486","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"fd731b17f5dc7884227a63bc349af7bd19f2a13a78db395ea72ba2d6c8b33608fa689592d96a0fc9454d4ba8d0","nonce":"a124c973c73a389d6e99e489","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"3775451889c1856d783d2e05e7db0721152326961116b9146c65127649e471baa004659ef4ad45cbb8c54d84af","nonce":"a124c973c73a389d6e99e488","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"ae1f6d3cc78117c6bc017f340d35f05284b35fdc7061d6e3e897e65b6cb2ad502e3239582ec1ca3f75e29dae3d","nonce":"a124c973c73a389d6e99e48b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"64882c0a850ea6cec7169e1ecb02966b66a2f13bb506674168d6374f64c30f4a900ef97dece584ce178812a83d","nonce":"a124c973c73a389d6e99e48a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"676b609d26bfdb80527853ac21a4976321ed07dcdbdb8bac97aa6b93647a3694dbbbd67a10b4f911df037e96ce","nonce":"a124c973c73a389d6e99e48d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"883840b848c1958f9ee353b03a85fbccd5798af5b315217b00f4dfb64a3f89eb1855efd0ef235582839bfd6c42","nonce":"a124c973c73a389d6e99e48c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"ed1fa2a944a9f3166a360018fbe439f75deac4b3b1c36eb5dc8cdc3b23a98c15f1b346f8b0efbc74eb8584a1c1","nonce":"a124c973c73a389d6e99e48f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"ddb9563d3cc6adadb3559c258778db0058ce536eb952215232d03abbf95baf6e5788041af8101bda7cb3378e42","nonce":"a124c973c73a389d6e99e48e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"82f44de3e3c57205a4387b86a7572b72386aef6a82515b058f5c54e9bd180cbfbe4d224ff05eb065dad309dc6e","nonce":"a124c973c73a389d6e99e4b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"5da303153538ea35710398daf0344f410a19a23af12e669fc6f4693059d50a8f4b9989a92daa56a430138a026e","nonce":"a124c973c73a389d6e99e4b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"9d5df8545cd056ec0423c84ad8ea2656768506eafbafee04792f7cb0177703900a3facbc3b9d64e3f81de3bcf0","nonce":"a124c973c73a389d6e99e4b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"1d70f6e108ee0c84d1124dd768535aa269baa07a7ad0e029f0b791274763d0370394035b687e9a044fcc7724ae","nonce":"a124c973c73a389d6e99e4b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"4994ba6caf4e48fa941dd066681c1186260285dad54e811f3cf449e4717b13751ee26546d560d997ea2b7ae3a5","nonce":"a124c973c73a389d6e99e4b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"6352c3c200e6b0f1234c0c7171a9fc38fd444b40f6975a2a6647869add24f827b6b0667e914904ee93407e4b85","nonce":"a124c973c73a389d6e99e4b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"7fd7da20acd25f678a4252ded514e8c18cb7c22c1ba258e58e801733c9b2e1f050c3b227ffbe1f6a08fdd4299e","nonce":"a124c973c73a389d6e99e4b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"8c526b4aeacc66a0252c4a90cb4a1620e6bba91e538ec434877a6f67e7aa1b80b9236c63cc347e55e0be6ee0a7","nonce":"a124c973c73a389d6e99e4b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"9b6164622e30b2f475080df9149b95766c0b64b803781308d77806050987ca3b640096071c454c77984042ea3d","nonce":"a124c973c73a389d6e99e4b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"46457ce9b3c8adc6dc32f0d8366b6a08297ea018debb300603be0cd032c76128d2d034ec7fe93dd7d848d821bc","nonce":"a124c973c73a389d6e99e4b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"cd733e2eb212165c5c592097574cd07ddf4486e3c2b331c780009afd2b33454e5494cc984d75ffdfcc3760d1e1","nonce":"a124c973c73a389d6e99e4bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"0e16a0faad3ff591dc0bd44608a053f15181fbe888aa374a8384329360be08f0be58ca35573bdc229120cc10f0","nonce":"a124c973c73a389d6e99e4ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"ed7daebf9669d2c4d2667e1f873b36c78fe05ea32717863ade4d797cab75612f58766dbcc5d7279a267c892bbd","nonce":"a124c973c73a389d6e99e4bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"e1fe1946a4f07d2bef388c85cbfad71b096069007ee64fa75c0941c09ca0446b1aaad52ced1ad6f2dc39f94932","nonce":"a124c973c73a389d6e99e4bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"d059bf69f0d42c2954ca1ac6514b9ad3d606c0f0a6c3111a0a55cc9b34a1266ed5bc89a0c10c4ab74e61e432ba","nonce":"a124c973c73a389d6e99e4bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"4274d61cddd3622883311da61cfb761b967db33713345bb75f166b6f4f64c8a98d99473d667488bd50fb528f70","nonce":"a124c973c73a389d6e99e4be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"2d63c68b354e1866e49f67be118c2629f1d36dfaf7c937f1779064a40afa131169354db2ea187096bf6ba1b98b","nonce":"a124c973c73a389d6e99e4a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"a6041d9103594d2b92220f5e3a42719171661d03ab10022b1514af32673d520b5d69a12b15af1a332d902e2963","nonce":"a124c973c73a389d6e99e4a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"af77c91bdcef9160276b73dcde326ff72d1b0631e5d83284253c7b09cd62079c606df6b1458516e2ba56780535","nonce":"a124c973c73a389d6e99e4a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"8977f5a483734cdeb0e9cd975f6207235847a1be58ea0e499bdf9ae3afb1c6d762b9cfc42fcbfaada3fa835658","nonce":"a124c973c73a389d6e99e4a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"9aff5994848aff122b5c153094823e50059e9cc743a6b811e64792aef249219d384f3ca9feb18569570ef961ce","nonce":"a124c973c73a389d6e99e4a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"48d4a22dda58f167efb6e93f9000da4f75c59582b0834b8dd229da077f2da5a0a85990d565f797ad6602c6caac","nonce":"a124c973c73a389d6e99e4a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"7a735eec73bb7b330a101b0202d25b20067c2c5f6320687b3a54ffcbf074b8bfc9637c9afc8356fc696ed917cd","nonce":"a124c973c73a389d6e99e4a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"004d7e7dbaabd26bb4310158363922b71a661df249be71a1f67f61ca510369e39b399c21377dd3cee0fd1f481b","nonce":"a124c973c73a389d6e99e4a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"cdf74098aa0215262966af0a3656f8a5c09d7cfef0ee980c969f2b35ea21bd4e91900fb676e30e940781ac0089","nonce":"a124c973c73a389d6e99e4a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"10576193b33581b330c2e75010100e167d71db046f41bcc050240a8211ab3e0877743d8d2d10fdb81801a6833c","nonce":"a124c973c73a389d6e99e4a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"b618cd0625c9fa7e08e3011ac01618b6b9275307aa37d34079e5e648384dae0253667e8c4857d76c1de169ca13","nonce":"a124c973c73a389d6e99e4ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"90f9ccff9f0cc54891d09e0acbe77544ea8d60f8e7d77adfe660aa9a6b81d2bf31bc8b4beaca6dcbd005025df8","nonce":"a124c973c73a389d6e99e4aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"b593e4fa12f82c3a7c9cc702dd052e160deb55d7449089eefbe3df1e7348ebdb0d9056a949596172ab8aab26b2","nonce":"a124c973c73a389d6e99e4ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"be9e5a7ed72f4b08ab6ac4c2ba97ce5bbef9921046b3adf60a3d68a7bb060c1d0fb120d224ab37f4f09042c8ff","nonce":"a124c973c73a389d6e99e4ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"f3a450af2975dc5576804845bb67b6ef0530374287c545aee394cb39124abc1fa493d65db6b00842326c8ec621","nonce":"a124c973c73a389d6e99e4af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"8472f2560ef8ad6c2d50ab6f8e5760d6af09b38c22dc724e72f78532c342b0d569291e4e7e1d928bbe4d9a4970","nonce":"a124c973c73a389d6e99e4ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"0e4d88f6111626445bb030979502162347d2ae564a1bda69ce7ca0bbbf76b25da0740594b4595a60facc174ece","nonce":"a124c973c73a389d6e99e551","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"a27dce937a4b4aed672887390e4540bcf6ed74185a31140822b3a7ac6fd127df"},{"exporter_context":"00","L":32,"exported_value":"23da835226a2df2da5a65b7c46d3daada4e1d097e8193548f7e9c754b99209c5"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"3f0951dc35e1a7f48b38fee4c5a430a5e544783e12aa6ace8501623187a9ade9"}]},{"mode":0,"kem_id":33,"kdf_id":3,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"256f80644d3b4c027fd23243e12278cc3d5a4527b6153721ad6661500aed7c4743db358c274b33b058f356865a537f3447078bef4cc94bd0","ikmE":"85922c2f5dbab665361b1d4bd15f3e36654c3a0f674d817e37ad58ebd167129a9232330f97c8758380fe654a589c7a40690c99ae31fa9ee5","skRm":"269d252a3a45312b7f7850694adb38e8e712e1251e42bfb9ba617160a529e8934b2c887eacb5a8d4e8a1df81f790267d2ade10b499242775","skEm":"0aa74dbd63c2306003dbb904434129d8e70c45fb023f86a7d66bf50c2f6ad9343c9f37343dc6d62c95eab450c46199526870acbb0e0de65d","pkRm":"382c6bb3947d0378d8b15626d9349ab1a2d5155d3d9a9be4a1a98414939e195a0e659b5d761f341437699568298a5dcdb2f8f91853f92728","pkEm":"de0ed865adcaa56b5f54522fabdce8190585ce39631eda7040c67a11ffa56a67f3df3617fa8c530d51d106144b49542e0fd28f510c45486d","enc":"de0ed865adcaa56b5f54522fabdce8190585ce39631eda7040c67a11ffa56a67f3df3617fa8c530d51d106144b49542e0fd28f510c45486d","shared_secret":"91c7cdde39f1906efadc934d34917fd1bb122409ea572a18227e6c49020e222f6ee2898e11b1c4fab1ba7fdf14ef8f5f922a64f84ef0e6e1d5ed5268a7181052","key_schedule_context":"00c88fa84728b245b308fd6933bb5039e92b2d3dfdfe95d8786fd110e7eef15eeeed01013a4b3649cec0160061020dedf2ff1a5a9579dd7f35f82ce7e4da7034b2817d22761b0e30bbcdab3759c3f6eb30117e5901b4813c6a7f4a98cd855f07b790aea87cfe90b91c465c22904d4128111352d6be737eaa757a0e2a1834173707","secret":"042ef6917be9c54d2acd0a9d806fb037c5c341ebbb39857a0e168ab09a37f025d4616bef7d4d5360c0005f1b7a51d155edbba6236896f7ffb58c30a4011204b5","key":"256c499dd3c0580d31904fdfdbbf2aa963127948567711ded2c44445e3b88fa5","base_nonce":"1a7f49d0550a732e30d19dab","exporter_secret":"c7506ff1183e68f8616bcca498558aacb6493c6847e5f36b9fa9fa49b3e32fef484e51948f46181ada856325fd9d52be1180e856c3a2bdb864ba9521eba9eb12","encryptions":[{"aad":"436f756e742d30","ciphertext":"b72608e00e3c00a8fa68e953de4438a34652283c899a2b7d5d54548f483a85d2a5b33bb7d2438c2caab61ca40e","nonce":"1a7f49d0550a732e30d19dab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"34d9b2b84807cb380d096d7d8d6b45f4b3c6edc62eac715db41ef7abe2ed7ababff6a689d0ab0d05666575d56a","nonce":"1a7f49d0550a732e30d19daa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"927169ab96fdb1dff4780c28169e53fc26cead6227a24c8a8379165a7695fd54c40a3ab804c7754a76150e4486","nonce":"1a7f49d0550a732e30d19da9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"08c75993f0c8a91aa3f8990111c62b2a9fe95afe2ed61ee1b7efc319e977e7743b70c9171b218674c45d351239","nonce":"1a7f49d0550a732e30d19da8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"cb794532a1b02e9d05c626815dd0bcb7e0bb809992a871d65b282fcf7653ba49acc24c1124548b5b1ae3861b2a","nonce":"1a7f49d0550a732e30d19daf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"e8b5d51da524346dfc5b3284a086c6fb3cd7413cdba0ebff08e2720a8f38cdc305cafd8d4de154ee4e6cc418cb","nonce":"1a7f49d0550a732e30d19dae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"79ab9e80cfa56ee5e84a0be2ba200698b174539cf8e94de1acab80a68025ad2e5b61d9eb5308368524b8a5291d","nonce":"1a7f49d0550a732e30d19dad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"e627abafee006c028b299210fde2cf67d35f314d1f997048f0995cf7d18dfa93cf00708eb41c2f6c01bbcf8a79","nonce":"1a7f49d0550a732e30d19dac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"c19eacf35e2effbf51a16f24ccb03a6fc88f4cf2e264c1a51809d61621b85fd5b8d380c69bf205e0f8896e772c","nonce":"1a7f49d0550a732e30d19da3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"a84aa1b71a84901ef9326c99c07e241d069b7287bce111c270140246397c52feaf2e1eeed48f686eaaf2b5b7be","nonce":"1a7f49d0550a732e30d19da2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"a8d442407cdfa6ee7a905512a90c8b4bd4fddaa09d794784c86dbfe805a3c145f30f6e43977032fa7eff39cf7a","nonce":"1a7f49d0550a732e30d19da1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"19c3795b795e4e6fa5a4392a84c4c24a545c8dd918e93143b3f125db417f51c3e787a2f1de87a23a938a1766c7","nonce":"1a7f49d0550a732e30d19da0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"f7e5d109b84eb834c9a0c6b62f88c5cfd6eee0016c56c199becee4b01b918eeca888218a8bf8ae6dd249e7197d","nonce":"1a7f49d0550a732e30d19da7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"24ba8eef06843f8dc487b7fea65241405d68952767b65335f2e8da35714d6574051c525bf983c93f8796e2651a","nonce":"1a7f49d0550a732e30d19da6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"f85682ff69a492c3546de2f3b1ee94ce36824d2fc15040e4de2e7f6735d152e134ce2d4439faabf39184d13fde","nonce":"1a7f49d0550a732e30d19da5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"92ddce0b48545ddd7dfc5acd513ce1fd3dafebee12408ae8113194bad621609304331d3173dbcb9a45852b5fbd","nonce":"1a7f49d0550a732e30d19da4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"1666d45362362d86dabe01e271ed9c1f428bdd0d564e0da95b8bd4b616b9c1c9219472488540d9fe63b039dde2","nonce":"1a7f49d0550a732e30d19dbb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"c85348dfab7cdd3bb72fdc63c40cbf951cbda0ca6f2c6b21ee3808bad3aa69671250abc9f82849cadaafbdc706","nonce":"1a7f49d0550a732e30d19dba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"61b0c5f6153fb48cf4277b7f3f6ed72e72eba373fcfff336fa85168bafc2bd25ada4a60a45eb66cbd4552408c5","nonce":"1a7f49d0550a732e30d19db9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"fcca7b7161bc9f61804d30b055fdd19e44bf1b8d9ad1fc3f21a51fd417f869434c11dd9c9441c9d1cffe19abae","nonce":"1a7f49d0550a732e30d19db8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"ea0c174ed85f886ea7093c41b4cf9cfc9ba7bb9ddcaca6042ba67246056ac9e01d497110be6b66bbb964d608b2","nonce":"1a7f49d0550a732e30d19dbf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"f264cd747e403332bd43107c6e7280cc5e89301bdb902981b591ab3123e48478956dc5ee0a37c4277eb12c3590","nonce":"1a7f49d0550a732e30d19dbe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"870e8975c65cebee70cfc68a6b342929d63b304e53b29877d7fd7116956e2969116d9a0b0e6f5a7bd149cfa8e6","nonce":"1a7f49d0550a732e30d19dbd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"fc1849ae394befeb323999a52ce463046ff2922738eb575452b563deb21b36cfc7ebefec85b88146cab480eb34","nonce":"1a7f49d0550a732e30d19dbc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"0a32c138c65c43d55e0c6a4e509afa7522a259580170a12adf225ecdb2c0e23161e27efffcdf51ef7221e23acd","nonce":"1a7f49d0550a732e30d19db3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"c3cdd1e86116d61a414ab34e2bdfa2ea5f7e6cabf44e269566d498883d1922996310301c429e4f1f14c6e01668","nonce":"1a7f49d0550a732e30d19db2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"9c311153d03dbb0d6f4adb9874582551f658d74ece5421b5025338661c6d01edb539235b4de8140e20949c0f7d","nonce":"1a7f49d0550a732e30d19db1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"b3948d115ca75e018f3e8fda023c72747b137752b72c250ec8c5f983e5743850a34b824810a91dfb3e5c579fb3","nonce":"1a7f49d0550a732e30d19db0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"7b27730e68af1374b659bdb5a3bcf4bedbdbfdedaa38c45586c58d76b9331207c1c7b8bf781c7e74bf578c7e8f","nonce":"1a7f49d0550a732e30d19db7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"64618560409c802e8b7d1c67b1aa5a59a4cfdfd713e093cdec5c2f4e98c52cb21f52d7893ece86843615920692","nonce":"1a7f49d0550a732e30d19db6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"bfef9ed92f295c09b403dae75aa27458ccda0fc6b63dcc3da43ac0bb8d5813f646b6f471fa696cee32f8f89ee4","nonce":"1a7f49d0550a732e30d19db5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"70b5d1cd0f13d0ca4af41bb55e2e80dadfc68e5178e1fefa8653fd72dc31e32d9609e6e79955de1fe02ff0000c","nonce":"1a7f49d0550a732e30d19db4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"c9d3c8e909eecc6529c1942f754e5dcc4b90b722754b8cf652d61b15ce1021f52683b7d87a7bd789de415f82d4","nonce":"1a7f49d0550a732e30d19d8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"aad35f9bd90d71bf0592a31694585a1b660c3a3c277524437ea447cf16ed3c49caf3779f73d327796e93c96aa9","nonce":"1a7f49d0550a732e30d19d8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"4710744d60ee3cf3c9346fdfed60c02c51791734dbec0b88fbf43bfd305b4d258bbe6547d70f6f5652ca139c25","nonce":"1a7f49d0550a732e30d19d89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"0d52919ff2a31463007eff72340576220b1cbc65a970ca862c209dbdf5c0b1a8b795364d75dad1f0afad8c525e","nonce":"1a7f49d0550a732e30d19d88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"c1a52cc27275d74acaa789a9a03eeec689ea9bd3e893f3c5dca0eca753067dd46028a846313091142d17ca17da","nonce":"1a7f49d0550a732e30d19d8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"c23283c7d7cf1098401d8535cfcc1cc53528195de1005d36c1a37a06cb5e051964402b2c06982504790bc88513","nonce":"1a7f49d0550a732e30d19d8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"9d9667555251cd5f59e3f98e61cbc4eb115e9f177f4c3c4be0085e51a082859beb3f8b44bbb9c48c01c01df6a2","nonce":"1a7f49d0550a732e30d19d8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"cc18859fdcf97c74e60a3d31003ed41e57c9dd0d97031490e77548d8c42c64a26c509daffa66b4d6659dace637","nonce":"1a7f49d0550a732e30d19d8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"a3ba0806d8641c37a575d9a74e20d02a6b17507ea6ce0c4e3ed7d0e85c489b054cc2d13d92fb6ed77da581d08d","nonce":"1a7f49d0550a732e30d19d83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"c7f70ab80bf7f6ec0f65ca76fb49190aa9bbe60c3066e6127d78a9ee42c3c02baaa6b2e2772e60e844d0a2ce15","nonce":"1a7f49d0550a732e30d19d82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"b8eace0280bb9c38e2c85f14e141c1299a51cba938f51f96f703acd0ce70dbf705aa6c6d96f192732b74cf6093","nonce":"1a7f49d0550a732e30d19d81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"a3bb23dc1486425cf5669dd4f312eab437247a35cf5fe1a699a24a040bd095f788be5f6c2e765cbc5cea85cede","nonce":"1a7f49d0550a732e30d19d80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"9e7f71c259d8dfda652c2c6ab0ce7d3ccc603fad7a57756dbf2a285f865eaa06783c0e0c62ec869df871cf28ab","nonce":"1a7f49d0550a732e30d19d87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"bf9e2f5113111ceebb338a65f2727a5dfc603dea131884118b09595d5e9aff417218ecc5c8de1f95c867afacdf","nonce":"1a7f49d0550a732e30d19d86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"5b4220ff3cc6223f35e754a7d3973c9de6351f8f909d874882b82d7da15d35c255402d55ad6ac395bc618f1d4e","nonce":"1a7f49d0550a732e30d19d85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"f6136901aa8fd0a64eadbbbe87ac6c4433c1eae986364eb9616bb6651bf84f66cf01704e1a3b56895388b5ff0d","nonce":"1a7f49d0550a732e30d19d84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"84b117cc4a7576f74541a4de2d13dfc8a43265d64c9dc6c6e6a272eca95c16ebf368a6acc4aaae991f27e57190","nonce":"1a7f49d0550a732e30d19d9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"b3d3d9352884f892f0cfccadac4d67175d32976385b73214cd9bdc49d08461f9e251dbd49fe0efd071fe7cfa64","nonce":"1a7f49d0550a732e30d19d9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"b51968dea43f42044c7d497ecc97f0ffe2ceb1442aad082b341c4cec8b5ff6ed8fc3fbfc769eaa987d4c3a8476","nonce":"1a7f49d0550a732e30d19d99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"d07a1182059db662406a471a74212391e0680572745c9e1ae95eed23400a13694aef9ab445572f0d301b661dbe","nonce":"1a7f49d0550a732e30d19d98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"a9075b7d6a6a32aeededc674a99393f48560ec4e2efcd9cced8829c67966d6a0937710fd0530c425d569b07bed","nonce":"1a7f49d0550a732e30d19d9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"fd7b55237f1c1d1048ed7e4de8fb5b3a240874c70bff5cef0ad0b7a42138291e4eec2a637e164be428bcad03aa","nonce":"1a7f49d0550a732e30d19d9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"a488c20336bd38f4609c3a1338abf6317d76b960556a9f0d47155ad731ed4e8d82b56829f5db8a92414791fb31","nonce":"1a7f49d0550a732e30d19d9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"e60af5ddd8abc7e3fade00cecb0984aa39fa0034daffcbe1493fc62aeb883adc0465d869364b8efcbcb67d1f83","nonce":"1a7f49d0550a732e30d19d9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"47b2c53cd4f696872c428d9eddbcfc50f6e521e0f3cb472f5bca9346285c8eb675b10dcb0231b97ae5da3f5312","nonce":"1a7f49d0550a732e30d19d93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"ea60b532b31d93b7da26c161ca1b6921c6c7ad5ab2457aef99a961396ca4466cf9349189d2a8df1c120f2819f0","nonce":"1a7f49d0550a732e30d19d92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"c1b0e9ccbab19749aae1ad368825367e5839752be9433ee87175d8001d89c0d8b60319d619dc73d78a6a2cf1d1","nonce":"1a7f49d0550a732e30d19d91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"a7c3841fedf029f578b694c0b7591463cfe6ed2b1122190559fce8f20ca99eedb2965fc437b7cab1ec0ef7ac46","nonce":"1a7f49d0550a732e30d19d90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"ad3ea11839b7fd3934b2767e1faca452abfc6a3a26d15efa00d384eaf66e0c144ffbefd1614b489308af4af913","nonce":"1a7f49d0550a732e30d19d97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"e9f8d39687dab188d60ca405c37c96138e8623d4a18c43514b3659668f418ed17cf0b2315a9b8597c8e915b93f","nonce":"1a7f49d0550a732e30d19d96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"c1d430dba90bf23fc5b75a37838fe53d4aa8e205a9db54c58b36fd3b6a7f7cda691c9f6e2540419342f35941c3","nonce":"1a7f49d0550a732e30d19d95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"adec32e22c23300e6661a2ebc3602d58df308a4b46c113e2f327dd8b72053d4cf923d104c946bd918262946be5","nonce":"1a7f49d0550a732e30d19d94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"e0b2f41250de51fbe1d2a7f7033db4737f46b6e1fd358024de23c0eded303284db49d659de6cbaa0b34235afc2","nonce":"1a7f49d0550a732e30d19deb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"70a5dea1254e1271223cc08359d19481a7183260d4aec6f063a2fb6902cca9ee6cf5f1ca2016f2eb4f8f760989","nonce":"1a7f49d0550a732e30d19dea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"c615eae358b8944291d88095b58882b1a2478f2129d0aa3e3154ecdcd1a0ab62434154db14f94d16a1daa4d10f","nonce":"1a7f49d0550a732e30d19de9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"6cc727826e53f784db6b1d56bea6f20ddedd00bfee5e53234ca828bd3d0fafae44244ef9882e696075b0e68f8c","nonce":"1a7f49d0550a732e30d19de8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"8c6d58b08dd79e389f2a873b71217bef43478c3847496660dee8bacbf430d80b8cc11d19eae469bf9e665e112e","nonce":"1a7f49d0550a732e30d19def","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"c970436b766652f3475087f3edbf57cab21f9faec7ca09e0b61ab2f3c1bea9fe97cf79e13d61e04872b484bb1e","nonce":"1a7f49d0550a732e30d19dee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"300c1172990f88fa148168c75d8039cf8e175de4d072255b78e68f9d046222f6487ffaf0f9f49afea3e472de26","nonce":"1a7f49d0550a732e30d19ded","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"08a68c673a857908140c21703f16d93b4e001f25f6569838af531fe6dbc6e2dac07fb2e962ac850599ab59a113","nonce":"1a7f49d0550a732e30d19dec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"d281d1d14cd875a5787e81c4ba55f691522921eaff18ac30f9deec4377eaa04f852646511c6e1267b3b98832a6","nonce":"1a7f49d0550a732e30d19de3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"a2019dff12f2454cad687f365aabc17ebf8aeefcad35c21784de3d8c8c150608d794441396ef796d5d89e0bacb","nonce":"1a7f49d0550a732e30d19de2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"730df861ed3a111a14ffe7e818765d728049cc48130e8ffcd4db6acf54d25c234906f985d3f027b55faf047b7d","nonce":"1a7f49d0550a732e30d19de1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"910d5d8ba047080b3e455e2033735b7bd184e95f77a16f6e236553c3b54748dd03f71dee6acc8058e9cbc9f6fe","nonce":"1a7f49d0550a732e30d19de0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"afb10f6e1e863f45474474f0f6f8c7ac17fe09e84d111a9f027c126e004babe7d5e038fcbaa6ccc9e1327b3ec0","nonce":"1a7f49d0550a732e30d19de7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"c21791665bf45327851b38a0f7392b82fa3ea0b319bd20c63ee5866d9ac300b1453175343fd63303479429f22d","nonce":"1a7f49d0550a732e30d19de6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"a45097cae3e6727d8a23c7baefc7cbee240874b589d6383806134a62183b7b61c2a3172946a1aa442a8947072a","nonce":"1a7f49d0550a732e30d19de5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"bac6ace5e450e2395b6145de292842b612c9f201e230cdf40c827110dfd2919dc98c6a5a0e9e30194d2f5b031e","nonce":"1a7f49d0550a732e30d19de4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"c6435165c936b03408268cd4b71966f01aeaf05fb7526b231ef4109eda1dbba1b8d484591009dbf79e897c18e1","nonce":"1a7f49d0550a732e30d19dfb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"e56df709cc07cd7cc3aa9e135f0c56661e8c88c088ac85aec94394d621c3b093b870a61e4e28924f557aeed88a","nonce":"1a7f49d0550a732e30d19dfa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"d197bf84a912a9cb7e48a3359e194d7b63d29299fa0eeca08fb66e6acb58ff3ad2df16c6f50616731c2ad3824c","nonce":"1a7f49d0550a732e30d19df9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"20b27b7f285327e60456ba7b94a0fa709492190e7e6c3c1c3bd234fef7b0cb2d511b650215fac7471a4692c18c","nonce":"1a7f49d0550a732e30d19df8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"e8f29f26ab36caa3e31f101314a5eed35ee66ce3160bef27e3c7a71ecf86c7b64e828360099940ac1d34229517","nonce":"1a7f49d0550a732e30d19dff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"25854f9f3948725bda5b51268066e0b0beb5f38d3c72cf34caffcd825b377976d4364556f9209baa775b4290d7","nonce":"1a7f49d0550a732e30d19dfe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"e0269d0af8b4b641b3f064051948dd06995caf66a2a8d97b4423494cadf197fe0864bab5eb3c5cd9cd1ab6ed07","nonce":"1a7f49d0550a732e30d19dfd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"7647eb766aec09e1a376b826edb326e57d56889092764f5058795f676eee6a87af42320d6dc22193b11de983eb","nonce":"1a7f49d0550a732e30d19dfc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"cd5843dd6b4105ff222e37143b3bf924f2849f02dfe5ce75e9a667b9983beaf637d320b84a4803383e24d15c46","nonce":"1a7f49d0550a732e30d19df3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"7a4838a9e99d5ce16d62ed773138e31d2d4640ec2dc4ac7c8fce3b0e4f4a3edd95e7ea921620e705b23256b078","nonce":"1a7f49d0550a732e30d19df2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"cb0c8903cf7bf7174a61f1fe1c63e0efddbfcb759d0a7ce7649716766525703f6cc892ea1ca3e93826c24045de","nonce":"1a7f49d0550a732e30d19df1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"9a477c8f87a57566cda98de5b3bb5e6bbb4cc6b3c5c0363319de4a051a3ae00cf0646ecf5fe0acbdf23f7124c9","nonce":"1a7f49d0550a732e30d19df0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"41becf286b7aeeb051a33a33622c7608863706a797e204ffb4bfcef3a37f101787591288205f6942a135314bb8","nonce":"1a7f49d0550a732e30d19df7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"42860bb8b4b86af4606b06a2e2c238ad329dd78bfefbc28f55b797b2f037feb569cabd6f4bd482f8b8515fa238","nonce":"1a7f49d0550a732e30d19df6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"e7b115e72dae7e3efc7c501d15f6f710b30e87cdf07e3d9f3edca1343943f2915501f93f30bfb1a1294b6de59b","nonce":"1a7f49d0550a732e30d19df5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"771dc91ff14bb847a5de83dcd8f86568c0de839e3a0faf823eff4a3a3198f85922c81894603a91771215677231","nonce":"1a7f49d0550a732e30d19df4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"79ab849a1ed2bfb481cb75804dc97043b8d339d82ef2ade190102fc61854e09135eb160b65221b5ae1c1312b8e","nonce":"1a7f49d0550a732e30d19dcb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"48d7ae13a98d565a319e5e19d0407f73630cdc61cd9079cf9e0f4bfeb046ed43d82a7d0aaf468300b46245551e","nonce":"1a7f49d0550a732e30d19dca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"5581497e5c3c581d70b2995465c36c03ec4212cb0be8e5d724c31c25e3de7dcab0b02da62105389401d3278a7a","nonce":"1a7f49d0550a732e30d19dc9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"7960612a37db7a17686bc0f9260c2a77ae56dd27a12df9cecb5783e41b773797635fb7730d66b59fc2251dc786","nonce":"1a7f49d0550a732e30d19dc8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"c0180462c855a3443230ee8948a3454218e01261ec14acbeeb8fa8d227dd0e90d62129d776cd30410974862b5c","nonce":"1a7f49d0550a732e30d19dcf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"7e1f63d4d8982997f614d545f0d032400b7dc4ef1c1195d19c9e4fab8d78d1b460078ba56cd000f0d46182b49b","nonce":"1a7f49d0550a732e30d19dce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"fb8cb9aa3fd7a8a5226e68b13c3b68cc50b4f586ee7d66d288ccb584a234d9ead7cf991b95a40bae2bb09823f8","nonce":"1a7f49d0550a732e30d19dcd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"63cce35e11dd2d6ce7ffba35d08adac5e8c7ad621119bb40f6866ef8bfe12f0b2aa4f5e15bf0010b7e5dddf97a","nonce":"1a7f49d0550a732e30d19dcc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"8af11a5c1d40bc651df83a3cba122a98c02b1d1f13f3370ae591f24478c3b68be766e815b9165e229931c4d930","nonce":"1a7f49d0550a732e30d19dc3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"5c23cd51fbb777a5c1318245e7ba47535329fe99a2bac50bdb6985ffa92f2053f279e3b5c1006e02e7025ad95f","nonce":"1a7f49d0550a732e30d19dc2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"055418c1b2b5634b72524a79fb8d6124b77c81980a5b23e96114882795b03ae4e2b22e5de64d8af55473fe1789","nonce":"1a7f49d0550a732e30d19dc1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"70aa80761680f8cbc838a42f136a41ac982bbd9a421c0bba090da56edd384c0ee01eeac6903738ebc10ea5f2c4","nonce":"1a7f49d0550a732e30d19dc0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"fc8f3b9794355fae9bc3643bb4cc6a71a76f04ec8aab36b6fb583c475755ba29a84abcf777930b2efdc549b33c","nonce":"1a7f49d0550a732e30d19dc7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"123c6dfad6d6acb457f628bd3aae710491833a479bd2db0845405abb3aa6943113f7ae4e6117e312b6f582fd21","nonce":"1a7f49d0550a732e30d19dc6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"d5cc01114495a0bc2357c8c19bfadcb935773580d1cde72e468b379a8fb1e20be636a6694cf2262a149db4ac35","nonce":"1a7f49d0550a732e30d19dc5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"f33ac78be9909cd25404a6cab0d834da1955f8a87427412b1aa336f086399c0c3c0b0558206bbf5efa1fa3b5d1","nonce":"1a7f49d0550a732e30d19dc4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"e67410f70dbb278b7956536b0e3e2f585737d8aa150517823f0de77936ef3d14fc2e34cd17f4f67de8b796ae47","nonce":"1a7f49d0550a732e30d19ddb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"673de957beda9b11ddedc253f93bda095be95fa682f82c65164360c5abd7d194ba3cfbe565dc162718e36cec87","nonce":"1a7f49d0550a732e30d19dda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"d57e860e05899ed7a936f231207342279baf7f47acdbbb0dfd82fee94ef99680d585483561bd794d17f740e535","nonce":"1a7f49d0550a732e30d19dd9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"d4026bd979043a047f60ecb19184e519fc5038eeeb9ae8dea89a72b3676e81bb8d385d7e9876c3f43beb4bb5a8","nonce":"1a7f49d0550a732e30d19dd8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"d687f5a305a8d28cb36eefda7c98b0a13c99a7a97b6a486ec13df333ee37f93f3d45ed120571bf6ffd58edbe23","nonce":"1a7f49d0550a732e30d19ddf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"067ac706d70a8e93ead5cd1766705684a68fe95aaed53928631697cf0e0bde0e2cc26fb83a01e77202341cc2f8","nonce":"1a7f49d0550a732e30d19dde","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"9e0e0744c419ed54b1f261d23f157babadbaff1ec7fb83900d64768861d98c012684dd3fde5aba4d2310eaca76","nonce":"1a7f49d0550a732e30d19ddd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"53abe689afd43922bf939d8c9f6b6ff2080172e20b3bbae997ac5a76760d73b222806bf6f177250aff5db8bbb8","nonce":"1a7f49d0550a732e30d19ddc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"ce433f6426091d0fb0f378d022795275b9d6fd9ad1c9e72fe262747f43b90f8c1b80b4f5f83501b738d0ddc33b","nonce":"1a7f49d0550a732e30d19dd3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"4fc5bda1fc05a67c1a4d1f52ac6d0d08de4605b9d749f4ed61fa687c8ce87e924f281b1d8be4c117efbdec4d73","nonce":"1a7f49d0550a732e30d19dd2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"dfe4fd95569cf9e14cfc3f879edbfb56ecfdf78d29143f2a674b6f3cad14b42fbbf1aa017ee5fce1cefc21ee86","nonce":"1a7f49d0550a732e30d19dd1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"acbb1d623ef9db3adfddb00315895967ef9b50ee87ee0cb7e5e9c548aa668083ff273c44b6d8de29340ff510c4","nonce":"1a7f49d0550a732e30d19dd0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"bded2c78faee317c2ef0bf910e8aa85adf3cd9b71b9dd5ee45ea5e4d3de64327f6da76dbdd25e89a366de9093a","nonce":"1a7f49d0550a732e30d19dd7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"1b69ed2a8cf0a5c914eb94e6f350a74e02548cfbac5f931ec484ce04d746689d7ba71aa891ae8ab22d384a4550","nonce":"1a7f49d0550a732e30d19dd6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"90b3c80020582e71128e648332241ea6c8c51064e74490cda00f48016c994bbf2f4e1ff1fce43108090ed830d8","nonce":"1a7f49d0550a732e30d19dd5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"28b8f05a0e38e1c43c5672d2e703e2b4a60827ea0e5749bff8c6cb634b5807ecedabf7a5d37e655a308915ecd1","nonce":"1a7f49d0550a732e30d19dd4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"925d816cc75b591ea25298856e4cac4a139e442af0183d37322160fb4d025ea349eaee38b258a0ceda012fdef9","nonce":"1a7f49d0550a732e30d19d2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"27585f7b66152691e6796a864a972f736abf6bb385684dd18a5c729fc934fbb46531bd6da695c0483650e5ce4a","nonce":"1a7f49d0550a732e30d19d2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"e908cd02cff444a3ab8d6a1277dfffb04f343eabde5e4ac3d9f82e91fdebb82cb72bbd9a6c2c1d30235f3cc33c","nonce":"1a7f49d0550a732e30d19d29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"845cf4cb6859187b22e1676216df993b29f25507ee9d10d7c941c430adc7e2cbf797a9cc2e01707814fc08b114","nonce":"1a7f49d0550a732e30d19d28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"925f35d5b42bbd7328fe19615f65fcb202d7da7a00eb1f9898f31a5a83e38906168422df11080dd110aaa85d88","nonce":"1a7f49d0550a732e30d19d2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"cf2951ba4f87d3355675b339a419bf3fae0c345650286fb9832475ea8de5aa409b4fc7f40e0db7ff8a798b884d","nonce":"1a7f49d0550a732e30d19d2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"f5d775014ab2d36a71a5ef2ce8738b8ff6b43ae83874cd491f04d87fb584175f506c9b132b0a35704eb4ceb381","nonce":"1a7f49d0550a732e30d19d2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"b9de1c13e75e7dbd0a36c91bd90a5314311a646c5eb638b1b942a58fc46576d83975b21914e7082f2888e92241","nonce":"1a7f49d0550a732e30d19d2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"78fc8ab03b6b7eeb70e98ad01e92fbf95eba31ace33dabed3ba9860c51b9ff3eaf72a3949533ce6f4423ba5262","nonce":"1a7f49d0550a732e30d19d23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"1682c4b004e24fb78a159fe6f3b8ece4df055d4eaef18f6c3120811d920e15795a48d32b1aa84cec52a754f8bb","nonce":"1a7f49d0550a732e30d19d22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"15824d9f0e231020b6a7de69d10d22a8a22ed4549436ffcd70774663426484a53d34396f0da4cc48b53ac2a6bf","nonce":"1a7f49d0550a732e30d19d21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"f20bb8321d8cbc5d24984946a31fb82497e29a6368e53c0c92a36045aa2b8d8b834001d6a9c51254371bcda3af","nonce":"1a7f49d0550a732e30d19d20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"9d4e656c9490944d0b74342a9f67b53baa22a3381adf2d27ed5491843f7eff69ef1daa66f9dc707ab5755c3237","nonce":"1a7f49d0550a732e30d19d27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"8fb0029be34025462ef54131a4c203f28af76d6383a5e68eb6922b46e82e7b97b04b307accc3398ffbb2d0c4a0","nonce":"1a7f49d0550a732e30d19d26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"e617129995dc6c6e6d1ff0e10652b36ad4a4cead877169c0c3278be06d7884f592131274eb3c88aae665e68a92","nonce":"1a7f49d0550a732e30d19d25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"99b78e07d97260778d5cc9bf642bdb609f9b0736be00d728442cb00e0187ff5c4328aca752272f3cd3c6dafb85","nonce":"1a7f49d0550a732e30d19d24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"8d9ed5f98ecf120192d49df4f2960d638428c1e88c917721668083c4f2a0d6e69304b5315c7651749fedafc0a8","nonce":"1a7f49d0550a732e30d19d3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"4d7ea12d0db27bd11c02808639b2ea41826eac4265352c0fc7344aab79b65e4af7349dec5a848d0d809b702cb8","nonce":"1a7f49d0550a732e30d19d3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"e8f605cf26523076156c6da2b5aa830c5d6022c806e8733e280c0b8609250e876aa49908e76f9bcfea44049eca","nonce":"1a7f49d0550a732e30d19d39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"da0e64f2dccd88fed1c29cf75f9c9eff2a0afd7c5d4946895bd6724e59af1d0bc211f6bd7375e45c224bf305fb","nonce":"1a7f49d0550a732e30d19d38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"fad6cde8398fe25cccb136010c0879af4ab036671aaadd8b9b9fad04a0493a0b1767a77276420d076bf0d987d0","nonce":"1a7f49d0550a732e30d19d3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"8a9a80157b9e0cc86f346e4a03a4d82ce5bac269446b6c3693bb12c0d5853ffc88d951f5ca1e34a013fbeecd2c","nonce":"1a7f49d0550a732e30d19d3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"ed982510e541e4952d8f784392bc5633fed1173c83ec3d37169624998345013661373735919f423f8c38d9ce23","nonce":"1a7f49d0550a732e30d19d3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"cc493f061af1256c9b6539a721e0adcdf5a0c442e04175bcaeb572bd50dabdfa46fae75ba1205c0776c23a3921","nonce":"1a7f49d0550a732e30d19d3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"9420ae46b9bb9c47134ef1d9d2b0cdf0bdaf7cd59e95ecab9faca8620c705a8184d9f55bffdcfb05f1b414a980","nonce":"1a7f49d0550a732e30d19d33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"75ef43d874a8e54263465a92bb1e242c4e99a21f5b5f5ebd55255fcb942102fe37ee5ea3576d1d4ef40b49f174","nonce":"1a7f49d0550a732e30d19d32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"19236c6fc03168e804553d0502d8c1304a35cefdf0f132a8322ce9ddd747abd0ae0788f9433983c077dd6006bb","nonce":"1a7f49d0550a732e30d19d31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"d914842cb00aa3fa8533517fe44d183960fa4295db365311c37b3216ac2b5d7353bca36e9a3cc07ebb396b91af","nonce":"1a7f49d0550a732e30d19d30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"015f51839319c4691996666fdc7297378e0de3fdef86f5a7303733a68be792672f499b019113f7e7914a00bfb6","nonce":"1a7f49d0550a732e30d19d37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"22f1a379a8ea7536e88776a6779c88b3919c6f63f4626addc72555c5564803c7939ec53b56558efcc7d8877297","nonce":"1a7f49d0550a732e30d19d36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"25182c68ec39a641af8644d910b68f61b52537f3847ce5b28d3602b6550018330e1faaf74fd8f34483e9cb0a11","nonce":"1a7f49d0550a732e30d19d35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"fb54b6f9e9c06a73322152a09495005c92234d5efbfbd9eb8bc3490c618c78b062304326673f7c08a458f995b6","nonce":"1a7f49d0550a732e30d19d34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"a641cd2462c69335a7634728460e25542df5ad2f5d743d93a2f546a71e80659eaa9c9a5ddf1fa1f0e35a4ccf1e","nonce":"1a7f49d0550a732e30d19d0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"fe8bcd7d0679b94de37f9af58f2578e2a731ae1104ee99ff98e0a1c26a75edc6ca2c8868c6b26f2cfa5ce3e49b","nonce":"1a7f49d0550a732e30d19d0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"620b150bd9d132ade15327d8bdb30aacf0d615fa5a13887549223c931269908c22307edd372aed0be486b734c7","nonce":"1a7f49d0550a732e30d19d09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"02f161f19b9e15de89c848b688fae880689bc0237c459e5d122c11643f8728c7e74e03842641617cf28f85b0ef","nonce":"1a7f49d0550a732e30d19d08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"5a13c402a595778ef21ea89177cf4862fb99d10c3adeee1077307f024c3352925514edf8b0b9b001cf52a401ac","nonce":"1a7f49d0550a732e30d19d0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"131e92794e23b4d6c08bd7ca769ed0a8407f072365f9b74a0c1c811658328b3dc6fcad503bb16d28056dd03b71","nonce":"1a7f49d0550a732e30d19d0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"5a146bcbebe4eaddc46e121cd085e00cfbb500117dd2624b5cfa097e6bd9c46516733d566f1bab187be6d3f132","nonce":"1a7f49d0550a732e30d19d0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"b5a98ad2bb8b6679875fcffb99ac233d40f6f7c7cb2e439e275619ca3bcf3d23c20dc2eefe08de028b2c20d06c","nonce":"1a7f49d0550a732e30d19d0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"9a403169f404c8733e3527c4073beac354d60d7e8d2c37e0c50de55be96e90b1afe3769c2c77ee73fb2ff048c6","nonce":"1a7f49d0550a732e30d19d03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"b48bfe3c410e38fce317c01613b232aa8166555cdd5e2736a958ceec3d21bdfede974e4addd4f5d93474897318","nonce":"1a7f49d0550a732e30d19d02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"7ab0e04895bededd077ed6c6e8c351c9e7540c481fd2e1bcf912edc78d2e833ea05aa5aed388dab3b22a93e346","nonce":"1a7f49d0550a732e30d19d01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"f133bc8b70a62e29afa764cde42d894e7b56cda02cde6a3832046ac30d0791707eb3a85e43cc100b37ee2ce82a","nonce":"1a7f49d0550a732e30d19d00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"68534eafad93cc7e253a783e13346d4a36d3a6b816f76e8230976162f843110f5ed6b675c792725c9c4db86e72","nonce":"1a7f49d0550a732e30d19d07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"1cef0b80e0497afec2a3f1ed160827273d39807b0022b219d6cbdf4f8762fa185ecbf396238b0018496d2675a7","nonce":"1a7f49d0550a732e30d19d06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"6ad5fdd709f278c11e237df75ddcb2639ec46a8acd139d20b2b7d3d866328005a99aa36668212cf01edfd24d12","nonce":"1a7f49d0550a732e30d19d05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"f7862d28bac96b5cf75342931d51d7707d209c707901e86b2fabf83d8be0492128ea29db680786933b44e4ba11","nonce":"1a7f49d0550a732e30d19d04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"ebf4253b87219737cea48bd137fcff6d0822b17df3c290c2e6418f9d60ec2b2c5dd0afaa7b6db0ac6bf7893710","nonce":"1a7f49d0550a732e30d19d1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"98326487de1fc56e7b333ba84c7679a41192a2e4e68d11483d5551ed22c299f034b6998f7d0a550021d305c6c7","nonce":"1a7f49d0550a732e30d19d1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"8146fa03b2a1ba78c19a7358d02f0be2acb9039a53f954e86b7fb9f436bbcd733ecef6d5b02953e2d5f5224e60","nonce":"1a7f49d0550a732e30d19d19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"327136346dab4647741b10a1aa49fb1d87698f459b8323caeac296c49f08b2da0f1d62b9a8160a0a58c3654809","nonce":"1a7f49d0550a732e30d19d18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"9c7a80b2147e5b2ad82ee5e8c06accc409267c6b68db92fd898779f8ef12341eae02c1af6ed77fd45374a93117","nonce":"1a7f49d0550a732e30d19d1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"8f293ba4d843e5fa22e07c4e8bb13d955dba95abf1a0726f8b94dccbda3857fa7e25959299664021446b994e87","nonce":"1a7f49d0550a732e30d19d1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"20e75316ae42a0ca068f082586b1f6b5a457c5c9c156d43b844e67a13f66868b7c8871fa6be5f7b0c3fb32167b","nonce":"1a7f49d0550a732e30d19d1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"83771007a66c9917a8fb7661ce62083cd63d31d1c60da8d29a2fe85dff49edafaf09b91d494b30ebd022895212","nonce":"1a7f49d0550a732e30d19d1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"bad021fdce77e1417cc811177016e42c8f0377bd8589b62581eb24b13c5fe757f18d37b948717879cd680a244d","nonce":"1a7f49d0550a732e30d19d13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"3ae36292f6d9b129a0ae307ea6f0e0b51904ed761ef46da25b3c036f55dffada9fa34cf5cee84486cfbf6fade0","nonce":"1a7f49d0550a732e30d19d12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"1f64ff5faf1c3ad938ad648672cc997cd5c27d22ed18192d0d67514c13273d1fb73feff382a99010b953e50dc2","nonce":"1a7f49d0550a732e30d19d11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"38439d744409c42dd5771b551a34d66ea922e0722e438f1d70ccada8439a8daba68ea24f26b889b634f9058534","nonce":"1a7f49d0550a732e30d19d10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"a2b481ce6dde4c72c6265d4d9a734b1ec466e6524fb1371663397c8ed8211a54e4933046d68228149e6170055e","nonce":"1a7f49d0550a732e30d19d17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"936b5c909c86bbcc5f14d7b746b6a382002a017742a03d79cfc38fa468de0509592d7d816f580a8039ec6f69a3","nonce":"1a7f49d0550a732e30d19d16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"d5f8f50e59da53ddf1d2661a4fa6e4829b6f15273d5f2d7788e82a87ce20fae2076c6c6658fe4008c0b4e5a566","nonce":"1a7f49d0550a732e30d19d15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"d4a2c03e3b46a1b70d9b6fff728d66defd344428eadb223c7d06d003da8c8078306c91ac955ab7cf8af1e91370","nonce":"1a7f49d0550a732e30d19d14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"3e74daf3bebcf792f9f1660546e74345ad61506970f9ebe9b00e6c4a4c6d4c35e389088cdbaa894a33fc53b920","nonce":"1a7f49d0550a732e30d19d6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"6273ded47f8cc0e5f31ffdc03205e0fea43b39ea753fefdc38ef42285d6521fd78b0abcb2348f2c085fc1db70b","nonce":"1a7f49d0550a732e30d19d6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"f8087197c283aab514b7c3d7464ebaa32aa4443261d6fffbdb3c770fa03f10106ae06cdf8d79079792a377c087","nonce":"1a7f49d0550a732e30d19d69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"c676d8e13b8d9125466108a5d0389d06f4bd58fb1e2c861f7b50772a04b10dd0715675fd5af1c18501c257b273","nonce":"1a7f49d0550a732e30d19d68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"29bcf7fe6de3dcead9a83f1547bfd18bdf12131310779656551c109e9272dacd43e6fbb0460695ad3385553e35","nonce":"1a7f49d0550a732e30d19d6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"ea48e22a3eb9138b2d3ca1856341e3b71ea11b992426a6175a53e8fa4e8b59f9adbc73306042d7330afee8b4a8","nonce":"1a7f49d0550a732e30d19d6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"a6003e0d55c4361b8a96b703bc60393ce3da230c9486e0f021b6376c2b3a6cb54723dd952e94d81851f9b1ae9e","nonce":"1a7f49d0550a732e30d19d6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"e663dc30e11ea5b476290336ba1dcc38d428971ca552590fa9bc02b87fb705247bd0204938c150ad780f3a2614","nonce":"1a7f49d0550a732e30d19d6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"0942983047f76953fd8af1b5031c4d8321cfc5cdc1325461c2207be42d95e40432c26fb950d989219d662afedd","nonce":"1a7f49d0550a732e30d19d63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"1cb09fa47b03f4e1290c55a869c5eb64b8ee6f557754cc37a6e16fef12fcfadc79b8ea433431915bbb19ec1b29","nonce":"1a7f49d0550a732e30d19d62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"8ab6ebd74f3d5ea3641066dc72035e3a8f056afff583e62f82f08cf2545916ff79a1859111a59c6c5284660ea3","nonce":"1a7f49d0550a732e30d19d61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"a682a5a2ffcfca6cb96512f42fc695a4c2817c5ebbb3c226159c07ac27d9cfe7eb3e6a0694af33fc637aae8456","nonce":"1a7f49d0550a732e30d19d60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"72879f8e1dab078dcbe8da1e03b23eda681b70b0adcbe7941f9327861389ba69cabafb00f1f83d2dc35812c7c8","nonce":"1a7f49d0550a732e30d19d67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"3dbb5baf3d1182037b42846a35436dbf7815746ba045881fda74c647d66a7671989bc58265db380123333afc40","nonce":"1a7f49d0550a732e30d19d66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"9c99be330e538385fec4179492611a6ace63016efb156319bc2630bf4c82138235f898a92059e043d5fd574bd2","nonce":"1a7f49d0550a732e30d19d65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"2da651d5975e470e660165f6b56d664ed8b36ffcd5149861b05652a8c8630b77b82ca66109a7f5bc3f3bc2a419","nonce":"1a7f49d0550a732e30d19d64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"e5c5536391c894ea0616d7cd60334245a842b9d800827a4dda2afe3e7df0eacaa4f02d7e3b1ab73c4a15c43bb7","nonce":"1a7f49d0550a732e30d19d7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"b6764330ada47361437236e5d57da6c617c6498050fe65d02e1510e11fd5ba48e43217cf60a2e93daae85a6568","nonce":"1a7f49d0550a732e30d19d7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"bd4b1cd174fc13e55298540a562429fb1f6b80035bb423046c52201045790941b13de081404ce47a6262924139","nonce":"1a7f49d0550a732e30d19d79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"d9dc80249f14e5d805fc8779ee001159713aa9e998c6b8b0332dfc606821c90a01053d8413df49a6a70d0bbaaf","nonce":"1a7f49d0550a732e30d19d78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"73c572be2c4545923c33e8f7596ac9e872c42e237c45e540c1c2e1d6f2c6dd1cd08c81bcea71f22be46bf2702e","nonce":"1a7f49d0550a732e30d19d7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"e5162e13150d8db396c55bad31f985e81186e3a2f656ddb874210104d06eef242c345abbf65c6a8a906bd53d19","nonce":"1a7f49d0550a732e30d19d7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"31d8d96fc04b93f21e04ac1fc80faa42c1879f52d4e88d23252e5282d0923465c25de13aa54fed1df921dbe472","nonce":"1a7f49d0550a732e30d19d7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"dee23afa6c14e95f7c5daa0d29a4a32228bd8380069ccfd52fec3d2867591b0d689b0a1d67441fa26fc97d3b42","nonce":"1a7f49d0550a732e30d19d7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"ab7d0c203ea0ce58ae8b8832fef750ffbb9288e8689bf4206f34932d1afd2d2503dfcb98ef82223274a0cfe589","nonce":"1a7f49d0550a732e30d19d73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"ea950413fbf26865dbc63c43caab5291731202cd83a3c455c82a603a4a4f2834c742946bc8b3486c8cf3936973","nonce":"1a7f49d0550a732e30d19d72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"7deab9a13989018917d3e74fbc8dcd277181b9946f19beb13dc80a7c8dd26394950724094a6d68aa82baa8eaec","nonce":"1a7f49d0550a732e30d19d71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"a9f1a267acc9fb44a9c695951e3080186df5d2bdf49764586c6ca469881dc99a82a20e0d566bb833d9ef491468","nonce":"1a7f49d0550a732e30d19d70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"ef254e82b5f09110f9fa30cb3d86f0ca7889966f0ba6e385d6c5381b1b5e55142942438d5a919bf2382a751e0a","nonce":"1a7f49d0550a732e30d19d77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"7e1d640301f96d994c8623509b1322ddc6b05687dd97f67c15884d0e68bcc9d0659f95b2cc1f245246a971ab85","nonce":"1a7f49d0550a732e30d19d76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"3ef7f61862c24e1e7e0be43511fea64290553f93af9dec034adb466442d36e46447c9240132cd3e0e537fc0052","nonce":"1a7f49d0550a732e30d19d75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"63e21de93f1d17a03f265f68b304b68c51d3a66b5b8f73d91ed57d26b2c96fe57a0a24b04f03d00124d7ad1b0e","nonce":"1a7f49d0550a732e30d19d74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"49393b8e1c1c405a83d5aa146b17e84deaf0b17554aa044660c16fa558786249207615ff4841024c5499a8eef3","nonce":"1a7f49d0550a732e30d19d4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"ce8efd82881577886bf302d627ccaf3988f6416e9aa25d5646d2ea6e2dba0314e040137a2601facd720ebe3a27","nonce":"1a7f49d0550a732e30d19d4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"70df570f4c2c6d20d1357c16f4615d8fa8515eae839d1ba4a6c44d549b882266aa9234102d6f021b8cc4f42da7","nonce":"1a7f49d0550a732e30d19d49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"f3307bdee548d06249c2004f801f79918421e9e914ee9efbebab75bb956db9c3eda6ee9a2d8f7c0361decafb15","nonce":"1a7f49d0550a732e30d19d48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"cf83257c325b110908f62753d061a8d584f1f989b1930080d04e1ae0c1279ccce30a3c209259017c220eb07345","nonce":"1a7f49d0550a732e30d19d4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"de0f3c643599a6e732e56d86dfe0bb56ee790ab38465613025be97ded4cb263211cc95813e17323ac49f1c1333","nonce":"1a7f49d0550a732e30d19d4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"ae480e15759938a0824b0404435c0b93e8f7ed592203c4491ae8f53081c3a6fdb5380c1b27fdc06bf2253000f1","nonce":"1a7f49d0550a732e30d19d4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"70ecfb3b01342cd2a037b7e06dda48c0518c41cb87768b1fdb2f652f2932c236fa11892f0a7c65e26832bfcaa3","nonce":"1a7f49d0550a732e30d19d4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"69cc886728c3171195134501bdc1aa96fc0405bc04c7e84dd2639e055d320d013c2acf0bc640f0112cf6ffbbe1","nonce":"1a7f49d0550a732e30d19d43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"d5e4e3b521a93b53d6977dc8750c7aab28c27aebef3f7488ac6687a65905c4adecb44855e1b374dc3113e1d0b2","nonce":"1a7f49d0550a732e30d19d42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"a414a6d3ffcd34c8b7328aa4a30678b38887c5465497cc59b09135777c6473f6770a6bd7751ac393bf353758ab","nonce":"1a7f49d0550a732e30d19d41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"a34572f1f58e67debeb30056fd535c1e9ee41d9646e3ae35a343f3d1dae1e3798014cfc0234175a3dbe7667788","nonce":"1a7f49d0550a732e30d19d40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"2304776ea7c62b5b3834597adbe4f3841dcebb7b186d3f4ea38da4d700df2f5100fee0b91702162c31d60426ac","nonce":"1a7f49d0550a732e30d19d47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"ae929745ddbe1e15be2b05dcf2553104bb582a637abd4a596ac3001f8106486d613e41a9490640c5c8035c9948","nonce":"1a7f49d0550a732e30d19d46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"626476441922cb99ca6887be99b0d86d0ebf80cd99a3afe66d888463931d652f638f2f243dd322da5be586c1df","nonce":"1a7f49d0550a732e30d19d45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"c1d04d74ad7e9d37145812647552fbdf91088419a84bbe16ad9d71e7a007fbfb55bba182a1bfe0c75905ec8e55","nonce":"1a7f49d0550a732e30d19d44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"92f6e8d293b9d0df12f837d07fed83578a601fe3566ffcb39fdabd31573a0ef7146384d1cfe0f8892f3ae2046e","nonce":"1a7f49d0550a732e30d19d5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"cd4c1c7b8e59415100b348eb664f3bdac46cf107f5066730e0cd8fc263bda38ebe81fbb2f6802bdd304ef49673","nonce":"1a7f49d0550a732e30d19d5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"afd94324cb8a0760d81702f273278a70946a773b5d75d527b0d5f19a06b3408d525e09539add73ee1e81941bab","nonce":"1a7f49d0550a732e30d19d59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"21cbd1688e9f2c702a43b4a44696d0bfb43aee04576e84253acf7b8e0b01cf8aac42e13298c8cadfae36d02e06","nonce":"1a7f49d0550a732e30d19d58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"137feee5d44dd719577e33cf4a6ce3b773eee12ad07fd69635e7387bb0ddccc68451ae20efefc7abe04050dae4","nonce":"1a7f49d0550a732e30d19d5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"a0b237eb48037a849fd76841af9a4380802725e1a6f622a913261d1ac3289fa0111f9cd3e50b6bae5e2362bdd0","nonce":"1a7f49d0550a732e30d19d5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"f05c031f621e141e4ed5d862c09a904bef1d3e8f78bf5058d6e99a60ed27ed129a7955debdc49d328b29e1039b","nonce":"1a7f49d0550a732e30d19d5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"640d1770503171698c0f77347853adb98a1adc0fb56a909ab4bc2a8a2ff1a76e840a53c849fc2bd33d19acf716","nonce":"1a7f49d0550a732e30d19d5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"b1d4bbc021c5f1a5c25387df39947bb89eee75dee74dd6ce62f261f9759616583022182e0b01e03a671c2ab3bd","nonce":"1a7f49d0550a732e30d19d53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"342a80fb0248e5cface315fd53ad63296d6fa53b1c090995a702551e1a05bcdc083321b39d41ae41a5d30ed04f","nonce":"1a7f49d0550a732e30d19d52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"d06c739cb5d12dd732aebb19fa17e323c95b260ea3305e9dd4e40b19cf8b83bbf471b837d101447d6c890919fa","nonce":"1a7f49d0550a732e30d19d51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"86be0abd6f77826acca1c7d6e73cae33231f8bfaee727e378ca5a0db0464fa3951bebc54edfe87da7d4dded51e","nonce":"1a7f49d0550a732e30d19d50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"b62dbd7003705cae32986bd15139971975bfe4fffa4680629cf34b25a1b11196678fb5b5c142e358dcb5566481","nonce":"1a7f49d0550a732e30d19d57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"a9ba51b719fd7cfdf00cfa5d136a172da97bec6ebd3d35a01f01fe90636208aacaadd47599804a76bad54a980f","nonce":"1a7f49d0550a732e30d19d56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"ca11ca78c7fbe69f24d6e7615bc4e6c0005df4fe30965f1cae39d672352a2ba78261895d370e6887cbdde0431c","nonce":"1a7f49d0550a732e30d19d55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"4bb02a2282f04a0d7c96b548e8be91afe29f296c8040365f53056dd37798cdfc264012632f1103621a37eeeaa1","nonce":"1a7f49d0550a732e30d19d54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"3c7bdff7f524870cdfda3e78bd0938cbf906e56589471ee8eedd66c522bee00ba03b02bb792b501b012b40f623","nonce":"1a7f49d0550a732e30d19cab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"e75fa22abfb966c72d82e92f000e047ed5bd9707b61131c9237b0343ff1055ad"},{"exporter_context":"00","L":32,"exported_value":"97cbc4f0b6d0ba8934d6872d50e15809eeded1fd019007556085e25d0258fdc6"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"6c973319f0c6b91099a8f62dfd9bf67119e983e801c7754e0e3758d225cdb93f"}]},{"mode":1,"kem_id":33,"kdf_id":3,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"503eff5522d5341f092743039bb5c8b56bff2abc62224a3aaba72303e8e09fb5db82d3b83c00206138783aa7ba0a97165678b2f11f671ce7","ikmE":"4015bcb44167231f0a07e4d9801cbd5ae2f7c7ce7a40e806c7b4fc93cc8ca2502a75a191d07d3c5545ef883e32e27aa194a11b67865fde57","skRm":"286977eeb75298053fb00263b054f1f1aca63046e9aecab1eb2c4858c3da6c797abd8f9035519b392e4ed30a24beeb4081e431e3ac09b775","skEm":"849506d2fcc2238091f0fb3bbb47ef278363db1a31446e6623066a82692f03de676a3507410b97f91c32f1c3fb43d9de0819f2c4927dd251","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"dcb810aec355a18f70d86d7585d94b1b8c75e2b46b92877e146bd003cf26875ad0ad81c8aded786406bcd5a5f5395a9236c221a2bea5e5bd","pkEm":"12b2a41304a0302280dd10be9f89584431ba34bb83ce099b25a9df9cde67a93fe1daf8cd0da6e29bebb058bef1b0f22dc6d211532bbed654","enc":"12b2a41304a0302280dd10be9f89584431ba34bb83ce099b25a9df9cde67a93fe1daf8cd0da6e29bebb058bef1b0f22dc6d211532bbed654","shared_secret":"7c3872fe97cb92e0b4d4b776c45d93c4a5c6db1d36a40842d77cc94468bf77c62d226654c92ba0f024e3196f9d3a5e89fbdc3716d395bb9fe6853bb5b0d5c9fe","key_schedule_context":"0125a22652318d3203b17a5dfe9a97fe6ca95fbe1bc17e0b9e19de28ab3294f256dc1c176ee71c44073a5dc3a585f607e7b1950e6924d36128e509650a0bb8ceb2817d22761b0e30bbcdab3759c3f6eb30117e5901b4813c6a7f4a98cd855f07b790aea87cfe90b91c465c22904d4128111352d6be737eaa757a0e2a1834173707","secret":"84e47a76353e3ce9dd48a4f5277579644c3897beed24d2cbfed9439ddc9b2e8283ad1f18fe49cd1912d227119446b77e2e99096c80bce294b34872e6244627d9","key":"b754689d0821ec108eea8f28d9a510c4cb68cf2bb7af0f434faa820e2891341d","base_nonce":"0540932f4103d6eb513b3f25","exporter_secret":"809ebcc06469e14ea3d46b59b6783bbed31b5daf35c3dce7222c3dee2d4ebb58c1f6cafedc0fe03deb34a1e7d2b68153427fad0f78798737df1e881b5e4b11bd","encryptions":[{"aad":"436f756e742d30","ciphertext":"0ff9b9fb023f87af6c708bc97db53727df6580e9c9655589aa5b191ae1603e1efb359370dc15683dde3f7a36db","nonce":"0540932f4103d6eb513b3f25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"30b77a337745fd75cfcabbfeab418e335055474b919ec3081e7bbeec8dd1278490c6fd475be768bdd2c9a681e9","nonce":"0540932f4103d6eb513b3f24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"0088e2cd69a4a65fcb9511e0e84232e4bfb910ea906b5341cb86cb3d03d2000190e1f454525d579eb7adaedb0e","nonce":"0540932f4103d6eb513b3f27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"99ca4129dd634d359fc294a191ddbfff7412cbd19ea210c0c3ce621bd90ed8e2eafeb229d647eed900c4313327","nonce":"0540932f4103d6eb513b3f26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"3c9d48dc9f56060729cad753b49516aa65b4c78758c52412a0f54aa7343f83284c7ece746a1c33bb04e5a55f67","nonce":"0540932f4103d6eb513b3f21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"48bda2cbec565668c6dfd52d93a2281af249ce4633706e5bfcea711ac838c01a33ebffdf1fdcde8cd6d0b5f4cb","nonce":"0540932f4103d6eb513b3f20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"ebcd6dfab4763fc2368cbfa4093b760afeb2e7d0f632659e2f666f716ceac6270ac00ba20b73c858949eddc7b4","nonce":"0540932f4103d6eb513b3f23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"9ba35f7f6c59fd1cb623707370c356983508ea8589fadc6b4d5c90f88684bf0d24f2cc051876a493a378b6235f","nonce":"0540932f4103d6eb513b3f22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"448b0592181bcecf94fde12324d72be76e69d78c9c1f093625bbc9b60d7e26addc94f47e74df92c4168acf209f","nonce":"0540932f4103d6eb513b3f2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"5bfd66f51bb1ccda6e026191b2098d84ef3b76ba62b739f323ad6b89cb5e6733702bd6629802548ee2cfb87ed7","nonce":"0540932f4103d6eb513b3f2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"8085c2169646a8744bcb7c379010e97280fc7e400fe3146e384ed9553fea04b54643fd96a36aec06cafb0c673d","nonce":"0540932f4103d6eb513b3f2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"1b07c304528bfa5f11d8e277a92cc85b7c37658de9e61b3a743a5a619a9cb43597a0f9fa02c86ec246ba062390","nonce":"0540932f4103d6eb513b3f2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"59db0c903938b3a9d5993ae28927285bc6d7cbae94c2732893aafe00330fcf4dd4085d5b6af00c95d5d1341fd5","nonce":"0540932f4103d6eb513b3f29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"85c3325e3fd2368bf793649020c5fb866ec5451a563cfbbd97e8a0f46bf7bab3b21057e7b7bb274b6c98d8e4e7","nonce":"0540932f4103d6eb513b3f28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"bf17009ebaecbf352b984b7489a53f790deebb62c1b76537272006b37581547ea46b85d8e30abe2faab062d4d0","nonce":"0540932f4103d6eb513b3f2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"59bc8f1b235be2cf5c1844b6bf2bec4a9f4edf71d286b234fa92948accd88bf64fcc5bdcf71cb52f23a9500f1d","nonce":"0540932f4103d6eb513b3f2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"f17d4cc254e642293737d6004f49bb75e7201c10bc3e03503badb6071c41d2d5b67b930cdfe02798e3cbb3a349","nonce":"0540932f4103d6eb513b3f35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"280d496dfca2d04bb7030e3b573d49ea769e4b56d3d02c4a60162106250a478dfe0bc8dacb5a4292fdbc289976","nonce":"0540932f4103d6eb513b3f34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"158c343e9fc97ada9d5721e132b3715f4cfd1488d37ba464b73857e876472e2a9fb2bfaff493587622fcaa359c","nonce":"0540932f4103d6eb513b3f37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"e03c9e67a05eb45422b8592d784808565dfb7a348845c1d25afb826e0f037d5f18d05bde0e53c7a856eedeae9a","nonce":"0540932f4103d6eb513b3f36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"eb8f1be3b580401ceea1b2ee2d887de0eafa81f3c9d60b5a9227bdf425312ff8a1c009db7a551c28725409e368","nonce":"0540932f4103d6eb513b3f31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"7ca9fafec0d16ef40dab97c95ac70fcafb9b1bd02111738a7c3295d29516b51ad5d0f3cdd32ea5747dfd83cf76","nonce":"0540932f4103d6eb513b3f30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"bba706e54c20c238d0ce3a7eb7482297307dcc25b604bfd4202e5438cba44888421f20c8985a842832751feab7","nonce":"0540932f4103d6eb513b3f33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"04b31e9e710e651f0e90d64b7d925ff5605f4fee7aefde9b5a3d2d2f56ae5e414e03be52fe9bbe814e7f974942","nonce":"0540932f4103d6eb513b3f32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"cac079b9bac9a84b935f021369049e7660ae5261830c9a9c7eb3a6c50180a5be4df344ec3b73cfc57069fb55d9","nonce":"0540932f4103d6eb513b3f3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"4e7a99e8a25bde99dd78b5533231e0b6976e97711ea68b02e9fd2cca39cf56eacedd7ad85cd69604aab0542241","nonce":"0540932f4103d6eb513b3f3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"bd2043047673773ee56279806cf9fe4029e801f78ad59c54f3587680d489243812d957d70f12ecfeb5010b4a09","nonce":"0540932f4103d6eb513b3f3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"8b95fd7bffb45845e45ad5ee2b9d09a06175a55ef1f5da79dbd49e97c6cfa76aff923b3ee2a7f505a68506a4a1","nonce":"0540932f4103d6eb513b3f3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"2ac2ef77b93a74ab5b99c0f078a8b3b689bff465308c9c1a405f4e1bfa33fc7d8cb8ee4e764856e78e5aa8d06a","nonce":"0540932f4103d6eb513b3f39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"848fd19c8c8a0fd13e5c548a6df421bb0ae58692903fb1e7c2fe918c03910b94af9ea86bb4b8e28158629dec74","nonce":"0540932f4103d6eb513b3f38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"f8d250a76f715b1eb780b292893c1bee2056baba95eef9e7fa403d113be38cd8060094e81b9b0ead6534e07c14","nonce":"0540932f4103d6eb513b3f3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"a28c5aef21c48398a1df99d901e8d656b1e0e58967e0e69a66c3ae2f086cb25caa430a15e46bee3983fac3e298","nonce":"0540932f4103d6eb513b3f3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"7bae38bdc47905a17839750fefb33503dde7c7f2448924d0f0191441f93f5fd5ef962637ca582f0f2961c90a81","nonce":"0540932f4103d6eb513b3f05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"f9cc2b8855de87f3655e9113c51bd61dc13ff84feed4f456f43f5f4f2fccebba77a000b63b4b6cd39e4b0050c3","nonce":"0540932f4103d6eb513b3f04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"f9d03c4525e82e11863eaceb8bf292f79b54dff60927a286fb9615fbca140b58258dfba9d63bffb2d53c900361","nonce":"0540932f4103d6eb513b3f07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"478ef40c7cff7df3e56766cfbc6f020bc1ba517018b25f3996973bf206350234bbdc182a04f45e6a2d17ff1aaf","nonce":"0540932f4103d6eb513b3f06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"6fd09044ab971e47b67e8d46ce0b6ed8993199b72ef432d83912b95205a7e8b0c9123669667a81a8e02818f5a3","nonce":"0540932f4103d6eb513b3f01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"9f7b7f930ab87586c4f0276c6ff16996757601d0635580c8526b6dc6d47095c06dee455970f6fef21477fdcdce","nonce":"0540932f4103d6eb513b3f00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"387d8e397102fc80e90edc3cc3a6b8d05d8538ba286cc84a8bd15cb8c69740939e0d697aacd48bf397dc539a47","nonce":"0540932f4103d6eb513b3f03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"2292fb71e8c5b859362331d497fdf685b5ff10a0e9b8ce2e812078b0b2e82d1488268cc613873ad01a70ab6c34","nonce":"0540932f4103d6eb513b3f02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"c28ded5617b4300d79bf23a00de1ccaac61224adbadc064ce097db3e5e009a354b3c7a8029e2f96346cc626704","nonce":"0540932f4103d6eb513b3f0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"598476ae908e6ea5164276851ae0e6dc55615ddc066bb3a173721f997fc72958575ede92f7c98b2736f49aa510","nonce":"0540932f4103d6eb513b3f0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"e6a8957f0b4a357b9496431f44a2a37816e09bf6d0b894a53f7d6ba6acc1c7d5ca4d8129db2c153356952eb3db","nonce":"0540932f4103d6eb513b3f0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"81ec65ec4cd0be08c3ef3da3f63cecc96c2d062936f9bfa42e4ec4f51b0d2c6b63f1d75d41bbc591f0b60c2d5d","nonce":"0540932f4103d6eb513b3f0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"af5359d9f2a1442dbd0783673908e648039f62d511040ff237fcc3ddbbce33170db8c6f671ab707d92e96a29b8","nonce":"0540932f4103d6eb513b3f09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"3e897dd25df7ad4be11184304e198c3cfa66eba388abd96e66ec4468daada445011acccf02b9a19a28a40d26ee","nonce":"0540932f4103d6eb513b3f08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"92cf40af0302284678405fb8b2b880e49792d474088b64508342f1f7db3dcf3b0b24b0ca3cba780158785d3b76","nonce":"0540932f4103d6eb513b3f0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"25eb026dd4a3494da8939d698599b6c8b5a9b58b133cbfcc81124d1c19eb7a79c7ea58c03bbbef53443191e96b","nonce":"0540932f4103d6eb513b3f0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"e76b577d45403a4b02131d2da230fb8ea3dbe602645f42077156448cbe8dba483a7011cc1b35e5a5b0c6119b72","nonce":"0540932f4103d6eb513b3f15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"8434bc61628a2fd4f1cfe567d4b2f77d582fa6996b63f165b17f81855d73187c55c7f71f82df1d7912c47c6e66","nonce":"0540932f4103d6eb513b3f14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"603cd7a3b528e00206a627732355860c600161bf560242cb6f1fe62e8c1824ae65c78537fd22c0735360f4f859","nonce":"0540932f4103d6eb513b3f17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"7d04381614e04d0c45085509cb6ac0c8a777c50fe4ef04a56fd63cdf72b9ddb56d1552207b5244386491146622","nonce":"0540932f4103d6eb513b3f16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"87b6a134b2390fa96ad9e9b12c4ed7038e807bf71226c18fbf844bd52ddb7a8bec26728a7ed479643c6a2d5ab1","nonce":"0540932f4103d6eb513b3f11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"3aa7677dacbb055cf201f5adcf3ffad072657f76763778cadf5d6fdd2f4ccda3e3a6e3db9683d0de84c9496b06","nonce":"0540932f4103d6eb513b3f10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"cbe5d53acb0166123ce02e2bd11c826dfe8ed13c2c03f87e95a390488eb115da478bdbad002e381b8e9fcd9f9c","nonce":"0540932f4103d6eb513b3f13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"de1d3c8336c59e3200fed225605b14e3c6427d682019289c4df4ec34c4574b70b706f89b176792dc55c10db91e","nonce":"0540932f4103d6eb513b3f12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"222a0fa6a691475e405464ff578b2797af4e796e552af41ea57478ab7f583997490f7d1e7f119091b53744a194","nonce":"0540932f4103d6eb513b3f1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"d0aa7a2ef180ad249dc06d2a28dfbdc857298a1e7c95781862905f7d42e577172b736a1188bc885a6044432e8d","nonce":"0540932f4103d6eb513b3f1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"9fda5c6e33dbc642f2f6615d81d9d102240fe368f524ac761238de4cb5acb04103048e67bb3ab94b30f1ec2e33","nonce":"0540932f4103d6eb513b3f1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"5f3ea046ae5af9f9306449e466f433e3ee70a31314f594ea80118e5d1eb6856903abd215e7e4cafcef27164715","nonce":"0540932f4103d6eb513b3f1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"8e522e5da9fe3bfdb8de1c00d2f501e96cc4ae6433a0b702dbf9721e76630f690d5bc97abe3f3829f4c916c7ea","nonce":"0540932f4103d6eb513b3f19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"b221082c718b7328110942149ac9699bba740f800497066c841f3818c2a2dc36ae06fda80f2437bfc8b7d1e3e6","nonce":"0540932f4103d6eb513b3f18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"6f72a96c37c42875a4ff83454a53dac71f967b24460e9cc1a5cc18d7f155993d558210cbdd4bbe70f07ae3cddf","nonce":"0540932f4103d6eb513b3f1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"55df3e231281cf83495511a9dc828afda07db9143cf0c3b0c59adc12fbebac00eacbb5f9e62900901b539df1ea","nonce":"0540932f4103d6eb513b3f1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"a495578a09140941965c10c221eacc2690286d692cad33c835c2e9ac9406d2695b6112a36eac23f908d06cee3f","nonce":"0540932f4103d6eb513b3f65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"5c1f01419ba684a6dd07ac621f188d36490c63153d6cf8da9bab39b728c5db4fb615cfa0a07bbdfbbb12e34d9e","nonce":"0540932f4103d6eb513b3f64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"fbba26d396a320bb8a28a66fefe86349e4f4e342b173510dba609617a05035693a882a0b89db632efca6a5f4fb","nonce":"0540932f4103d6eb513b3f67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"b0777a40036bb79e47caa4ce70d0d204b2fc5ac45c2ade46f3551a54726051782f87992a7ccfbc39df5cc16f17","nonce":"0540932f4103d6eb513b3f66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"825f0d7cb3b2497c276c5b0485314f838a72e7764326142cdd8afcddc48a8d8c1911809f5b306e03ca38d98448","nonce":"0540932f4103d6eb513b3f61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"0c19cd13f304418c5d2dea22cb5375dd5060fd77659a28e98dbe79a8524aefce8ff0abe43ab90dffa856744643","nonce":"0540932f4103d6eb513b3f60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"ede5d9674688c8242407068083576a48e9f08c16ba2d44a79c89120340b55a04a1c5d0210b76269318e4ff41ca","nonce":"0540932f4103d6eb513b3f63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"8240d8a7d3433197a8a295ca7a60f916df081614792daf6fb73cb00955307d044e3788b198ef5fd20cbdc1415c","nonce":"0540932f4103d6eb513b3f62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"17f36c221ff9f8ef4797ff714d224453bf91c52f36c6444b0ac74a346da77bf8a4a087a34e13460732b05434d8","nonce":"0540932f4103d6eb513b3f6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"fe3d7a3796b6e7d211dc33241218b9e01acb2fb735d07c6fa8a7f3a225f5f7301f05fbca415673fbe5eab9cc80","nonce":"0540932f4103d6eb513b3f6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"870201f15f849e807480c46a87fff3feeaa0eec363840b69135410132600c7030f6b3d60e6230f045d81aa4bac","nonce":"0540932f4103d6eb513b3f6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"4390883ff8d29e9194fea0604a341969c39c55c24debfaad53ac3429817e9169ad8d31c943709b3f6f3ab79fa0","nonce":"0540932f4103d6eb513b3f6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"9055db4312a9dd9cdd90f121f4e30c77f12fc6ddf5a5c8fab93b2f2e4e9e2db8866b893833b2c061ff2c952aa7","nonce":"0540932f4103d6eb513b3f69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"8319f1a0bdf298c6b0115382f6e427af1d8ebab019b373334641f031f46be77c8de1912df079b7277cdedc0f8f","nonce":"0540932f4103d6eb513b3f68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"9bcc52af704b0119231c586c198f3e9d78870e9108c6d9af05593dfa84d22a24fad5e316fc8b6440b06155d49a","nonce":"0540932f4103d6eb513b3f6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"d34aafe25deb7fc045fb19c8331fda6166a370830a105385d50ddef9624b9a83f7963b2ee15e5fad8e6fa3cc8e","nonce":"0540932f4103d6eb513b3f6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"a2688d688eeca89cac2dd37b5d2ea7e5a5b1669b3630b6d473f3744633e0b8baf3baac072de6678645556cd443","nonce":"0540932f4103d6eb513b3f75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"d3d02bf395d792636bac064cc57b67a51e50c67df25db577562cd2d3f7e167d2a7d6742c8feb118fd6a8d164e6","nonce":"0540932f4103d6eb513b3f74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"77540fbae1fa48331a264ab00599771cef8dc4ca026164bea15bc6b0479781548f896b8afc4ddb08b9a1064dc1","nonce":"0540932f4103d6eb513b3f77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"c397a2143654dbed5e20f2d8e3e5fc370b8e39ec322049188a020d7d596c52507075ac0840e25a66b049ef7c6d","nonce":"0540932f4103d6eb513b3f76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"02181ff4b109bd63273fc55412602384f22cb942d6f2ea89e8ccbe403e533e215a5420fc365f5ff2c9ba467716","nonce":"0540932f4103d6eb513b3f71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"4a2b6389798d1f93f69763662a1e181ceec0235872c4b9cf6b3c8898f59f56da984942b366b28c9bfcaf8ed2e6","nonce":"0540932f4103d6eb513b3f70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"2fad4d1ffa27e997c51f569a4c374d78f9dc3825dc70eee39dcd33d458ad72fff3a6728ff398d8cd0b6c6e2a08","nonce":"0540932f4103d6eb513b3f73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"843357c0a6dc00dfcf169a1d68ad73f95867ed5130185b71bb3229f40e64daa7afa140fdedcf809509f61091a4","nonce":"0540932f4103d6eb513b3f72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"be0519aa7ad5c9bb27f5cba644c4c106e12a78e45d050a9d49130acfe56e3dbcc57d472fd0a88b2dc993ab52fc","nonce":"0540932f4103d6eb513b3f7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"35509080039902857aff47893ed0f81939126460848d92efb9e763285a3c321b50bf61ec9ae101372c796568be","nonce":"0540932f4103d6eb513b3f7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"b3c4afbd2b61c17b38b4a150f84e104e0f1428dc89f355784ce9ff052f445b7a9d82ca46d863979dd42a69e80a","nonce":"0540932f4103d6eb513b3f7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"c5b771bf89fb01090151b37b09acf9b93138529bc06edb06c69cda6b7b3800e63672f6b5e0d19059003ec9be0f","nonce":"0540932f4103d6eb513b3f7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"311a76b2a196187ff9eae3cdba45c9e71ef398d351d03bda960579dabd2720f74d7160fcc77e0fe5754fc40368","nonce":"0540932f4103d6eb513b3f79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"a3136b52dfcc5e457cc4382f6db843356fdb50ac8ef60bc78cabac18296186830a5ee0c3e28461ef32112e8f05","nonce":"0540932f4103d6eb513b3f78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"2ce9828ed57cfa0750ee88593f542aa942d43d6542c9d5d2f7f18cc15cd29a112c6f6b8931324012c9aa1f42d1","nonce":"0540932f4103d6eb513b3f7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"ac14ffd8c18bfde9646efd1b4cfb228cd6f85b5eceaf60aa607167743b5f5ba61f3b844618abec94b1040aaccd","nonce":"0540932f4103d6eb513b3f7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"45d2252f9f981b62b5b7eb405d77f2cf61d48779c3b02b8eff0f241fc9e1b4556c35102f53ec937927cbbb48e1","nonce":"0540932f4103d6eb513b3f45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"75d6507b66ba1897eebf49e6dfec6905a4024026685eff92d2c9a3b9eff5316d474b65fbac965b935935f672fe","nonce":"0540932f4103d6eb513b3f44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"29a8fc40476f0ff1c70381a1faa2da779eb33caa2ebc82e58e15a0077c11e312f97931e8131a284db33da63516","nonce":"0540932f4103d6eb513b3f47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"2e81c94728b3476f9679984cf5fb3646a8afbf4fd7970962091a56392c7eb9daf46f64d1d2e3da2ec57e3efed9","nonce":"0540932f4103d6eb513b3f46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"bdc15241e363c45553b6895aed69b321c17c6bac72a9091c29ef71147650d0ee740ad0dc9f752bcc05395c4d45","nonce":"0540932f4103d6eb513b3f41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"794da29ea253eb71e50d0a34f3fe7a7108f8dab4c9e16fc975f4a8bcf775db97acf1d3cd9f51e4a188596be8b4","nonce":"0540932f4103d6eb513b3f40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"aa833c8071188c1bdab453a7b013c7ab7fa22f304e686383928852f6414d59d46841baaa573f68e49ca30287ae","nonce":"0540932f4103d6eb513b3f43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"e6c22186fb80465f22ff2db8820db8dbadcbd7402bb67ff78f4791d16a8ce707c693d4ec986b4e939b91a85524","nonce":"0540932f4103d6eb513b3f42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"3ef5ff7b77e14425db6b495b6f0b9e481d9d58b9638b550cbddd38a29926460a3ff704a379040a7ac53fe62f50","nonce":"0540932f4103d6eb513b3f4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"f2acedb0df373188403fa9db5f1979828482b77e634e694953bd0ce11816f9d107f0f2f6b8732c2394e0b36294","nonce":"0540932f4103d6eb513b3f4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"157293d9d2a2b439a2e8d6d80ceb13b07daaf36b6946014c0ee9da36f74737da857346a37b3339382fc3fb30b8","nonce":"0540932f4103d6eb513b3f4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"56cb9bde904a538192c8d6b25e46ea988c9d7ebc9b41fa5de41b243ded66981279ae771eb76d84ba349b2f384d","nonce":"0540932f4103d6eb513b3f4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"dbeeee6b03c7f8db2aa4b140ced1b01899b76e938ea14d8f6fcd29a9f8f7e070ff7808d23270209a3c4d570f91","nonce":"0540932f4103d6eb513b3f49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"38a37203b87c8a54affebf9e06115f1851a827559db913e1210f9ee8bdbded2e455074b521dbf54cdd99b216de","nonce":"0540932f4103d6eb513b3f48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"09666e59f860e162b4ce7f01a6da421456e2134a36c0f9771f2598d2a1318fc21be755a616b7a321d29a6ffc71","nonce":"0540932f4103d6eb513b3f4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"8ccdc9af98527c9565880184b7d90016be996a20aa83f1bdf82fe3eda5fa3cdf9ebd4b01ed1530544eba264520","nonce":"0540932f4103d6eb513b3f4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"939c3fae7eac97bc822727bc14e866e50f957cfeca05150ca947c534eff91b64cce14bd44021ea1298928ca796","nonce":"0540932f4103d6eb513b3f55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"b0862191d3e34878992aa9b3137eb4c14291014536300aa5950462efa51cde8b1de37e8061f3a5ae22a8f2e74e","nonce":"0540932f4103d6eb513b3f54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"e02909850f555faeb0aa49539317dc54059fb4f751d5a25791d0747d28f5ef4618ff70b68175322da2f62abf4a","nonce":"0540932f4103d6eb513b3f57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"9c150ff34c228b49c31ed0446d4461620e540fbc5d493a9fdddc23fd8f7b3351bd95b3e2e58d932cc8aeed5dac","nonce":"0540932f4103d6eb513b3f56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"ad54e1c2e00a2767e090881ff2dec8d8df19292a2b4bd12e78ecd0e453874fbf3bb1a1298eacd3d68179b8abb6","nonce":"0540932f4103d6eb513b3f51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"4584a7a9395c2917d69dbd9c21e280d2f10ab5fc160a478f15a8b5b0761931444fb51961117a03149a34ba751d","nonce":"0540932f4103d6eb513b3f50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"88546a8a18459b0338aafe14d8006061a2cbedc4890ecfd66dbd1269edd7412fea4325e388790d357a0a404d1e","nonce":"0540932f4103d6eb513b3f53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"2b7e4af032213b66bc462723f5fe9e52f2d2d1a11eadaa8502fcda4a5878db2cc885c2ecf2ebb1b4430346cdb7","nonce":"0540932f4103d6eb513b3f52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"1ae3c9cc110155f9a86657ee519b93b41d4c8a66aec856d24e5e21b31fbea8d1e470e536224f25e90c438bfe78","nonce":"0540932f4103d6eb513b3f5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"70fa694d7ed2f9be2179a40147d664a01938de12fd1c04cdaea34deee948083093ce705d368d98e19baf36404b","nonce":"0540932f4103d6eb513b3f5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"b05a0c3fd382dda7eafb5b840270f3485fc98a4f3ddc8fba5a44fcd17a686cdce38ca2a1e4bf12b22ffa590667","nonce":"0540932f4103d6eb513b3f5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"fa2cc8a64ad9c417bc536c9961a297fe35fdfa7275a68ebead57c0e3884b810976e2b28451778fa4a55240980c","nonce":"0540932f4103d6eb513b3f5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"74a587639fffd74e9f1e2b31da5cb9c88eece2d8242d36d0aaf6fddd3866095fa86a6952e45381a6d55d61fe82","nonce":"0540932f4103d6eb513b3f59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"a5cb172baac862ed2a6711d007085df6cd7fd9dfe33ba6289bdcc7569d03bc79dc8baa9124680094f956a681eb","nonce":"0540932f4103d6eb513b3f58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"1828a026940cc272024f1f368af5e4b8b344575b50a42146176981ddd0e9c07eeaa39d27c72a4a12549a3e8871","nonce":"0540932f4103d6eb513b3f5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"4a7d4acb3cb61aa2ac0ffd99bbaca63256429e363db66d48e01cbfb7c81c09317462289bda6cadc28e76b449db","nonce":"0540932f4103d6eb513b3f5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"0bc4f7289d9401fb727412c02948979222fde04b37b1e0b3381de0f88bb5a126d43cd413aa4a9f116b4e27748d","nonce":"0540932f4103d6eb513b3fa5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"38ad4c3f96007296d0c9e73d75b2ae1e402aa4b56ed8db1b39920015e2413ae248d6ad2cdf0fc296a76135a12e","nonce":"0540932f4103d6eb513b3fa4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"9ba7978c814ba6bba25466a4536bd6d1d1b33bc16bd81e3e0ecc877ed4a55fd5450327e4adfe6b8deaf8e3f82e","nonce":"0540932f4103d6eb513b3fa7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"293ecf6b0b0fb03bdf24ab0d8d9aecbd33750a455c5ec02aaad3f94f28d7d698e7817c86f4e90cdf92ebb50132","nonce":"0540932f4103d6eb513b3fa6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"98b528eba73113d9cb4f2a70acd3e7c643b3fe1871deb282a2732a52b0df3ba76b34a96149f69880c8d0a9f2ee","nonce":"0540932f4103d6eb513b3fa1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"14d17fc8374a4c7749ece5b60e4698bcc57699e3f0286bf517eceb9364baeaaf7da15054f1ec5ac523c74c2813","nonce":"0540932f4103d6eb513b3fa0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"051463c27f609d1292c8e6b3fc0a1e25aff31746469ebb7bc9f1780844948e06d649dcc1ee68dd16c20ea7552b","nonce":"0540932f4103d6eb513b3fa3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"ea7bba95c92348560e06ba89f9c384197d02ec4fee047282029aed7518f837ed9a74cdbdd76857a7e1aeaf9545","nonce":"0540932f4103d6eb513b3fa2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"57dd3a32a48cf519033cf65602e9949f6c3a2bd1f51953e4c3c6e2dbcf8a33767f864944165f9be55e8c741aae","nonce":"0540932f4103d6eb513b3fad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"5a1d4a645e5dcf97c98774a71d8bd3b081d779dcd773699e51118ae90a802c4b46d03604c5d6f2d48e3060e583","nonce":"0540932f4103d6eb513b3fac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"d29d06442c2720d19779c2c0e925e88beceb49fea54b7360b7151cb5d040e0259468813b9280790647f31133d5","nonce":"0540932f4103d6eb513b3faf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"7848bb125770e4bed42df0703c2c004fa9dc13115bf6e40f4b7b31177f5375cf627417fca4e4c512bf976b6c6e","nonce":"0540932f4103d6eb513b3fae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"61360c0519db0aac4a5a8e41c5caeec9fe946a7f593800db478774ea669cc210b633a41fb9260e7d34377c0a71","nonce":"0540932f4103d6eb513b3fa9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"75495adf0870873035d4a1b09dc09a2949d2b55b7e0c521d2a65c6cd5ef979e7fb8ececad7ba1e944ad2e80a50","nonce":"0540932f4103d6eb513b3fa8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"52495d0d9fb7277df0078f253da24dee2cc3eb0d0cd048cdcc11de7a9e9f97214dc87a1f140fc2a5c57bda2946","nonce":"0540932f4103d6eb513b3fab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"028e7d00edb2255265e37de3a7f76fe84b96288f9f0b9372681792e200b7d860907e204051f5a413b18bb4ef3c","nonce":"0540932f4103d6eb513b3faa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"01816fa338ad12813805b74d4df25eb03f275ccd1a6a58020c27f0a1b678001ac6dc55bf00fb1fbb0778adb830","nonce":"0540932f4103d6eb513b3fb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"0b36bd9e4ba775d832ee02a2cdc15fe4899738eebe750df5649060aff40ff4de577591e6039c13854d62dca0be","nonce":"0540932f4103d6eb513b3fb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"897e6926cf88dc4d0a4c193380bcedd9980ca562599bbb02c2cc3902d863bf98fcc09c5e075619f033fe4cabd9","nonce":"0540932f4103d6eb513b3fb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"7f1e4c961913098ec77a8847b4cb7cfc201ed62064f496a1bff63cbba9f1ae90282984b7b62242f217b96d3146","nonce":"0540932f4103d6eb513b3fb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"e2b4848632f16fed32e19407b9119317678a1c8ce05a6954f30fdef527f908bab13e92cd013bde4489ee1c5a49","nonce":"0540932f4103d6eb513b3fb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"b06e0d91ff840bd1e3d7ce787af1af503398ba1fd2ab4bba9ed196803b0c2c64b0dd250606232fcf5baf15696f","nonce":"0540932f4103d6eb513b3fb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"e7e506e02493563a71b662c5e8994463467cbed898cdb31bfa0fa358ca9ab3515d6434d05914f4a3e1371deb86","nonce":"0540932f4103d6eb513b3fb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"644e37dae1d666d415bb5689148cd69165959970130fbfc1d9bfb93549af3a9a0cca1bf6059c1c46c539013b2f","nonce":"0540932f4103d6eb513b3fb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"cd2090b5ca8a9a73dc5f36e79cd3891b231ccb00d42ccc5214cccace1b090a790eb63ecbedd9d49ed8ca304914","nonce":"0540932f4103d6eb513b3fbd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"7f27793b123bdea700fa6f75376e39f260a31fe345d8fca0598cbf045588990e7778e4a91bfec511c86868a1b6","nonce":"0540932f4103d6eb513b3fbc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"f6ae6105164a7bc3a50213dd37cdf7915055bff1f6c3db9daf473333b3b6234d5e5825f073afd5e9f7fd15d851","nonce":"0540932f4103d6eb513b3fbf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"40ccf6b11d5720257819118ee47facab2d1433a704349560b9e4b2c9db8c88f2ef51f50ad78b90c61b2185eef0","nonce":"0540932f4103d6eb513b3fbe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"1601975ccd71a1dd07ca101d47fe242c085231178716235d8a6f14ca8c8d19e39d54a50b2d28e6b78a08d854e5","nonce":"0540932f4103d6eb513b3fb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"1be2da8be6ac7ad074c7e6441cd1ec21b5fe23f3549567471d8dc4b5feabd5e2525804182a1e36ad4aa6f59c4b","nonce":"0540932f4103d6eb513b3fb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"151c6632b5316117fc8c8cc3de73d472ce002b3782c9073f0f51048c509d1c5c2d34e4a19a60928e0cd9952a6c","nonce":"0540932f4103d6eb513b3fbb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"1916cf99c28f9f5b134084e9d722484ab50bc5fc2dc074a1097aabbb9e0c5171ed45e86a283241516e78e5f3a9","nonce":"0540932f4103d6eb513b3fba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"d79cfb30e896e83cf830d4cd515007cebf21c70628ab01298f168d00590383f4a8138ffa9dbb2c3b9ad1cbbee9","nonce":"0540932f4103d6eb513b3f85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"4d51d2cf4e256b4e5db9e74d14de461785296225a932d5c67c2aacf2cf71edb5fc08461b8d73be6dc179cad39b","nonce":"0540932f4103d6eb513b3f84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"bdec94cb2244a9c0222eb456b8b5d208e7f6a2e27c1a74e38463c9b2574ead8d77d47e7859d21c266695c71dd0","nonce":"0540932f4103d6eb513b3f87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"55c42d09b3c5b4b0fe15e02915b544b354b2dbe7a62cfa950e285e49a17dc59e09ec7a2f03b19ab731616c53a7","nonce":"0540932f4103d6eb513b3f86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"42911c6f596d56d35559ce2ad2d970f5ff6b5a800db7437b9b4d21f04a4c6f249fe7e5b5a49d9f02559a267013","nonce":"0540932f4103d6eb513b3f81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"eb9e3525adf9d1dd2343f7ae8ed15804d0e0e61e4719c2ae9508f42a0d6dba0701baad4cd596b5e749ee1b6766","nonce":"0540932f4103d6eb513b3f80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"e4d1b39a63e5567f9de748f4e583cf1902a659820f031e450d89ee5aa039a7787543a2db9e8cf26f2d5ad7b3e9","nonce":"0540932f4103d6eb513b3f83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"3c28e21abfd4c4c9af679fc80753d25c4486de268c4be3fdf6acd37533650289d0ad65b279980ef93a6c260bd4","nonce":"0540932f4103d6eb513b3f82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"bfba3594898d4c1657ca614e636dd626585407a52674491d90ef0693b1cbe425eadad913aa6a0ae8dda4244018","nonce":"0540932f4103d6eb513b3f8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"3c1df9fee440b8f0d7b7f2676a0a7222d845e0c6fb5923d6a1313e55aceb2710910642539966664dceb400c809","nonce":"0540932f4103d6eb513b3f8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"132eeec0ae5eb86b4b94c0138f234674491c2ca6cd94bf208d8bd787e20a085d6c58b9324efaa6f2a9a27f1b78","nonce":"0540932f4103d6eb513b3f8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"b6960766d3f181ba1ebb8b490982ac40446def435d9b43e8ecbca1196cfdd48ece11368e6f77377e694703e37a","nonce":"0540932f4103d6eb513b3f8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"7a11d4bab3055facd346e6192413d00fc857dce8f717ffd4b082160e5e83bb208b08eb79121dacf8b9c6bc463c","nonce":"0540932f4103d6eb513b3f89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"9b617c7857524b5b910310e72b1b9ba84d8fae6049bfd16876a1abd150499326233ebbd12335cbd537205dda9a","nonce":"0540932f4103d6eb513b3f88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"78dc0566cd14c67f313996e70a550a24f82d034d86d76d0c6a222edb86ad3c48f5f531b05ea985f8b5607e0b0f","nonce":"0540932f4103d6eb513b3f8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"68d95c9720f042644a23e05959b4de725825a8be74aafcca02f823fd08c96d4eb5aec1bb12c83c0deafee9755a","nonce":"0540932f4103d6eb513b3f8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"fda10ecab4800d52a828391a35b50190c0d3360f249473890cc628d7137b66f88cdf6a4fd62b67fe3be22003d7","nonce":"0540932f4103d6eb513b3f95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"19ccf5f210d9b2571bba7cf65e05284d62457124cdb4de3d8614adaad8c930ead64df80fe122791514459eba39","nonce":"0540932f4103d6eb513b3f94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"92d4c672a256083e22e2deef4c8d930b4686e988bfc39c063d945d4096ed237ac6cbb93d9e89803f7dd42580d9","nonce":"0540932f4103d6eb513b3f97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"fea0f068c2b99f6b3a1bedb057c1b708bc6bafd3226d420d112dca4b077e76e08cf8fb894b5e0df4e0c276390b","nonce":"0540932f4103d6eb513b3f96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"bb68b921ac7c8f8872b4bb44ec8f4601fe69bec3ac9819401531b757e170a55f2e0f76bd202060aa7c11bea3d4","nonce":"0540932f4103d6eb513b3f91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"e64b6d631991bd4f8ede1148eb9a81956c331ef29326e3c742007643d6a00fe7d4f7a8ca6042e7f952581e1ac4","nonce":"0540932f4103d6eb513b3f90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"69cebc656c56fae05b62bbc2965828b26dbb374e4cc19163c360ccfd5357fc03ea94d94b3700ec9f1179c62d0b","nonce":"0540932f4103d6eb513b3f93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"70d2698471662d84ff6e53b4619fc5fcd8f7ded22ca8b1b409a6410d83ef5585033ad87f6f86f4adb84d91eb96","nonce":"0540932f4103d6eb513b3f92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"2fa5132c7d17d00f3dba93c13c9218a2d2dcb0d74d0f24295067572f1efcb7444341d6102bdd61fc3ebc40766d","nonce":"0540932f4103d6eb513b3f9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"c5e26f0be3b281131a62525ba55cd6b7d5a682710bdfb95127b42f88f02add687e3253222a512eb6e01aad8fae","nonce":"0540932f4103d6eb513b3f9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"07d09beb2aaa23cc3398117e14f666f4d440d682ebc1c6f4421fe9099ec8b2209fd2787fb523c49255b387727e","nonce":"0540932f4103d6eb513b3f9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"717d00d1f00b57de4e40bd9bffca4faace108bea26ba2fb8c61c194bf7389804da77b7dd5cc3eaf58da42d1049","nonce":"0540932f4103d6eb513b3f9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"41cf3570989cabc00df9fe32808eda4d7f98baf5d0ee9211a14a53cb8548543e19001b7e0da8305f68f9b11910","nonce":"0540932f4103d6eb513b3f99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"a3320441717b5f54395c63a06e592bc16ed95e9356b7eb91941ce9c43ae7310a2f4c0676463e84a5d73f2fdb99","nonce":"0540932f4103d6eb513b3f98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"864147971ef7bb8d37d91608570576d779524f8b881d07c26151b7a667655c8a2d8a28c20bad76eab20ff780e4","nonce":"0540932f4103d6eb513b3f9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"6fc28b112edffdefc40aafa34d9b0737b6dae4b6e76801cb1e8d1d266f19cf3bd076ad753e7a9953f2b5510da6","nonce":"0540932f4103d6eb513b3f9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"6d378167dc83aae1175fc78522f40151049d64580fd401b9772f9006d7379bf9aac5e6ff822301270cdec8272a","nonce":"0540932f4103d6eb513b3fe5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"ae80adc46388c9ea50212cbb1a55548671f859d2febe3d44144df50e50905cc5f626948f9615d52d893c1979df","nonce":"0540932f4103d6eb513b3fe4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"db6df7585d633d5aead496341188f34b315a1894acd2960562cda42b9f9acb261f2b4d2fa2c3e8b75539f5442e","nonce":"0540932f4103d6eb513b3fe7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"4e2a723637aa6443ed56bdb45e16e9ac8edbe162b21da3447f825dd693175c50da359cb6aaf5669501e96550d1","nonce":"0540932f4103d6eb513b3fe6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"4cfdcb2f2dc63d9687a1ad7733abd1e5737e3b7d07e273f6eff7a32ea69acfa8a5820372815434682bb63e8f6b","nonce":"0540932f4103d6eb513b3fe1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"8f555672c74b18080622f6658209efc3c9c61d2ded961ac2f671682ad79905e57969a3a27d94fc89851849635a","nonce":"0540932f4103d6eb513b3fe0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"02342a87bd3b643afd29b1cea2f1efce13d915764885d2e8f93837ffcc19c3f3dc38cf111c6cd3937df13712e3","nonce":"0540932f4103d6eb513b3fe3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"b7907ac1f0d1eb36fc4f704cfac64e8461ae8cf4069742c4212b3361686dc907b7b6223676a59e7506f79d5e1b","nonce":"0540932f4103d6eb513b3fe2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"34debdc76afbb1120280dfff31e19708ae337c605b9967eeee3a58eb6ce890f727a5fdb082677c4cc7bbd4c62b","nonce":"0540932f4103d6eb513b3fed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"228e37085e4e93dc0f382338eb70cf9ebf9b8df9bf895b04e84665b84faccd46df95a4d2bdb02249fc7e8a5935","nonce":"0540932f4103d6eb513b3fec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"3d51c3db25676691cb7997040d9e32710142c21076a2171c0f7b129acdc4bc2a206919bf296cd65cc94facc5e7","nonce":"0540932f4103d6eb513b3fef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"b4a66904e92767633f50c82ed789ac090505f633b719917c0a2f56701f88bec067f915ba058aa47e8c227c8175","nonce":"0540932f4103d6eb513b3fee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"6d317ee8b3896e15336aae3b04724d600e7445da0bf90dae3da591435caedaa97221a50a21d7a65e568d607b08","nonce":"0540932f4103d6eb513b3fe9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"6b4db81814ffa2c4997b5ac5e1fc84b289fe76f3959d18a567fe621ff7be0e2907cfb75d0b777c27f4df145cb9","nonce":"0540932f4103d6eb513b3fe8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"79142a52bf9bbcba188e224bf055b72659c596a48ea498fe3fe95176a7bf8c02fd96ca815e700799349cf8c0d1","nonce":"0540932f4103d6eb513b3feb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"7ce69f02b50a5be55d9a8dcce45f31f49e7d9f948ada671a9e18dd163e0015cf25a71af0382940ddadb11a3d71","nonce":"0540932f4103d6eb513b3fea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"1c5de691f07a705ec62c0ca17fc90721528e3438ae1a43c2b11d3f424f2775f18b269d9d50bd74ffaead19a870","nonce":"0540932f4103d6eb513b3ff5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"c6174e4e4e65bc794b8210af29c688e64b8cf1cb05dd1b367b3ebad2694708291d227b23d16e79debc6da78d8a","nonce":"0540932f4103d6eb513b3ff4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"f55aa69b67ed40559278ffa968b155ef83a5b848b6e344a0683f5b9614ce3eb9d5027eed7606f6422948a9277e","nonce":"0540932f4103d6eb513b3ff7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"1b744d7513bb5a6cb7ae36bb279a5f2c16f18dbeb5a44856c51c11a5318d5ce09a6fce95c666a6b2af8fba90b7","nonce":"0540932f4103d6eb513b3ff6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"293ce306b28c7152b0925e32e57105b1960bdccc438db1a70a76fee06b98ed0dbd5dd591700e08fe4b4e29aa75","nonce":"0540932f4103d6eb513b3ff1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"38a3c63f0f67b11a044079440cb81d8ceaf000881ac8b8f9c15acf1bc4c8208885c242b6806d19b4dc3b9a6339","nonce":"0540932f4103d6eb513b3ff0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"8eac1bf856e88ac04c99863c09c7243b161e32db20d7af3950cb9a89bc8d6d0588f60cfea051cd775476b6ff12","nonce":"0540932f4103d6eb513b3ff3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"2303c0e486fe8368e7a690b1f6267c88203d8d65bb93eb624ee737757fa20251bee17fcc788ef087eaad7b1c48","nonce":"0540932f4103d6eb513b3ff2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"ec499c8e15789c78665c689ffbf0e724189b92e81949539c3ec1c5458a45062b0f984ae70b53afe5b2311d8ae6","nonce":"0540932f4103d6eb513b3ffd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"ddc4dd1ee8e74e61db8b6caba6fa81d55c5fe4fbcaf33abc717819fa8c7f6ebd9f35d9e89a75f9b1f15e65d175","nonce":"0540932f4103d6eb513b3ffc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"97bd33b551bfe4d8be5c0f9e6333c25f84cc3c8c057b81d26303eb1abdc35b63633e85ed19d12471095ad9a4c8","nonce":"0540932f4103d6eb513b3fff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"05032f078aac39badf56400b9ce05b044481de5a7009ef594f8f6e91e70f0dfbe97f39cf68e77d32818eb0f621","nonce":"0540932f4103d6eb513b3ffe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"c7ea2cbb5cae1a8320d96e8c7a8d8f48746fb8cdb713f4852cf60eb6fb2e30932a82742448979f2a6e3809c7a4","nonce":"0540932f4103d6eb513b3ff9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"726324a277e2d9cb1ffdcd71609661144159de6c9f5a0cc821747f62291be1488bc1c035d5422c81d786c99969","nonce":"0540932f4103d6eb513b3ff8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"5e0dd99cd3ed202db4f01b528bac3dbe3d57a2c58f337b1f87de96559395148b58030295d9c2bd074657bf20d3","nonce":"0540932f4103d6eb513b3ffb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"61160470759986628cb82b75e0a235980de4516c09527ed502816690fab945ce2b222f7322eacc3fef8cdcd16f","nonce":"0540932f4103d6eb513b3ffa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"8b6003ae69b3276341cfe8e1e2f954e037e8b573ee5c7f987b0a9a3b2263277aa66dd7d13fc14c337556a5d391","nonce":"0540932f4103d6eb513b3fc5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"df813a80a347456bf242b146d8813ae2e2508a8591a7432ea72144655f8c3804ae9b379790be1ca6a52c0bab81","nonce":"0540932f4103d6eb513b3fc4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"157efed10f8431bc0877a442081f674de2569d1c9e03df139bc3af6aad36f279c111d96aec66c2b679f1d713a0","nonce":"0540932f4103d6eb513b3fc7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"0abc0295933557c705dc8465eeb6aeb393b11ddf28e8c3c62b7b834165f027db240eb1f11336e6f3f3805b7922","nonce":"0540932f4103d6eb513b3fc6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"bfadf70a6ae47aa84770b1979d251bcace97a8d50e27da1cb901e0fecd32b4ba5959babd5782947a9a417b3b7e","nonce":"0540932f4103d6eb513b3fc1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"fe6daa96f3a6cface09cbba71711c25a31376073ca9419277a60a2185a19b842132c98b5a7a8793f09ca92388b","nonce":"0540932f4103d6eb513b3fc0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"8823ae66a7214ec3fb5a0aa7d0430fb685f27629868af9e8eea2bb8ead5fab8d9a39ba023a3ad79707655ec37d","nonce":"0540932f4103d6eb513b3fc3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"6eb52e7aaed79a842dbc43c89bf7fcb2374017e57d41024054554cac50a57a2d8e1e26c44a985d25be15217a1d","nonce":"0540932f4103d6eb513b3fc2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"0f90768bf9b20a8c83066af071973f86f24fa5736bf9f36f8ec3faba2e1f2467b34878b7c4080cde100b7505e7","nonce":"0540932f4103d6eb513b3fcd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"26f7a9a5600553f3e78b200ca869e383039b00353f9a566aa4ce162f36be9774f8ff6b51c2bdd8460a454ef76a","nonce":"0540932f4103d6eb513b3fcc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"0fee7168bdb4ef10515b56497095b0f26299a0d45297b02438ef20673a0a76819ea6cd454bbbc7942ec0027a92","nonce":"0540932f4103d6eb513b3fcf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"6fd7a1420a5e440473f84cb48b66db8c3d8c3d31e864a276fb1814d7d793344d4c0d59bef0e9e94bcb379f11cb","nonce":"0540932f4103d6eb513b3fce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"413b9f2e68ab9c9d6b3c96630a535626b697f7e77a7dfbb04a8fa4328796a5bdab04e2834a41f31530143159b7","nonce":"0540932f4103d6eb513b3fc9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"b5af7396da6c5ba1dfcf820206276d53cebc3071f258f03ed06ed923ef868cc8a10fb10196468c73a872af1284","nonce":"0540932f4103d6eb513b3fc8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"3f6df2202ec726260b2453451c980ae232937c10887de9d17256538cb79122dad0b9d709a3e5721560eb4dec70","nonce":"0540932f4103d6eb513b3fcb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"3940bdf3f5d2acf910bacbe866eb47e33ee4a34483682c1a0e4be6e6477aadbbdb6a4ccdaddd1d4b55019f34fe","nonce":"0540932f4103d6eb513b3fca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"d4f0015bace1ef6cc5477dab804a003f349b84868416dd4afcd84f0f542157c7f6d5e128dcd263ffb0c2d0b844","nonce":"0540932f4103d6eb513b3fd5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"400b6fb502280df2bf9e75fd06ac3e80de6e5a56658c19d654cf4199564e4cc55e7fca92af7b67573140eb1a5b","nonce":"0540932f4103d6eb513b3fd4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"5cd0f256537a70633c295555126bc6a449f4647ce45332753cfcecf17c1ba682a6292a7097d05d6eeddb970496","nonce":"0540932f4103d6eb513b3fd7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"3bc7baf9447a3638fdaf74ac9f87559164e2b2b94038e97ed69c52c2001300733e79a484acc89f5eb6239f0d98","nonce":"0540932f4103d6eb513b3fd6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"6f7fceed2be55013767cb37cf6d40716b844fb0f18716e51980056c8fbaf1fd01cb041ad5f50530e149b4c7852","nonce":"0540932f4103d6eb513b3fd1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"706e921d6c4a30450283d43ab8fa915a61bee9f7e00eba54371612c1bcb2a85a55efca59866d0702a49f6019cc","nonce":"0540932f4103d6eb513b3fd0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"b4715ac6136952cf2f326122e649e0bf97ba95d481235d6788c75a467f8394cc0e30be10eeb21bedbfdc718907","nonce":"0540932f4103d6eb513b3fd3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"ece7347c0074d9e345c906438512836b8244d0f7e9287669d74d0b18320aaec3abb268c1394321adda0c4f85f8","nonce":"0540932f4103d6eb513b3fd2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"38d13b59da31ef59b0511bd3a7708d3c66bca6f3260f748fe8bbdaf44a4fe70264267a0a346873e385ba26e32b","nonce":"0540932f4103d6eb513b3fdd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"580c0ae0b8bfa9cc8f00ea6d80d6d0086112a7a5552c85a5d5ecb85986e739bd5bd8d5b02d2eecf282aed10652","nonce":"0540932f4103d6eb513b3fdc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"7900462455929bdbda0b5c5146c2671afb4b511e8e1e9aa8e3c478229c0afb7f90d4ec6521024d3a9ee047080a","nonce":"0540932f4103d6eb513b3fdf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"752ebfae8efa2c3b220ade44848e50b3c847dabeced189971551dff8f2380fe9f5d0f3e79a0fbc967dad0451ad","nonce":"0540932f4103d6eb513b3fde","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"c7f24ca9954ddb1103a35814ba2982e63eea419ba2d296146b70923dedc2b425dfcde2246a5e065dfec22fc92e","nonce":"0540932f4103d6eb513b3fd9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"5ef969049c432f86afc5cbc869af277e881eaea732e9d5eb3ceecdae6d9582954ce5732c0d46be978363badf21","nonce":"0540932f4103d6eb513b3fd8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"12fb0ce5712a39f312048c425092335120b840beac746d04d80aa991fc813a3f18f30ee3b54ed4163a26020d89","nonce":"0540932f4103d6eb513b3fdb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"0d44183080a7bc54bc0446807ae68e14d3f6743524b5cd4c1703674db64bc3e7bb39c4bfcb93098810a8fc52e0","nonce":"0540932f4103d6eb513b3fda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"d1c8d0b860b85b27df4df87917e95811f89a75eb97ff931b375ef5d06d1d3ca0ad2f0c30e477cd1f42508f1324","nonce":"0540932f4103d6eb513b3e25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"9df9ebd1d01f6d52e22f43f512df59bfd3db323d334f934135e7138d446f98cb"},{"exporter_context":"00","L":32,"exported_value":"4530c15a50194242ada24fef46d5a3e8e75fdd37f39e5b7e6b2dce807abfedb9"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"2457a11d58886d7caedc76bc25bfed62fcd82ed35031005846fc79068202162d"}]},{"mode":2,"kem_id":33,"kdf_id":3,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"6fca9dda27034530c5cbf310d5b350d6af4c67565070bd7677df2bacbf094961c148ccb32d31eb9a93198331a5579d77d85d167e36121907","ikmS":"86b31cf3b62b53ef5d439cf740ab554ba34d374b479e984c3d0733f191d4d8ca2eda48499f09af345ddedf613e8c3657e8878c5251e977d3","ikmE":"403831a3076fbcd7980ef063edcced4cc9a712f4dcdb93e9110b9bc214884d426df56d15dc1451a76ec3c76dd69982875c547f2eef268bfd","skRm":"a431ea780a7c0473edf52534deb0c9a59746ba728f65af6b20b8633046b610750144faaf4ecde5572bad15db7b334ce295de2f4e00bdd7e1","skSm":"7632481c53824f88f7495e96cb59c0b33ad47cccb8df33f936f733e1c2ab6e444e4f131cd333b41746914d66521b8d5a5f9b5c7ce454b60d","skEm":"f8e2703d062e94fc4e2e1ee936302ed6cabf2dd07bb429478067543b114564eac367fed61bffad67763cdc649e9004942e3217664c965d64","pkRm":"146e5335f3a25050ea4f811b2d64c3166ad2afe5f4d03fba34ce861735705225cbbb69154e27cfd48fc3373a8ad43b30521c8cd6bd117458","pkSm":"a07cc0aa10885233cfb6bdb572b26646b1442ca07b087463eb857cceb8df18d5ebae561d3350601d1dec95d22ec66877c85d39a7a75d1da2","pkEm":"deff44dadbb774f554d65309f72ec2665dbba45d2c981781c66ad82d114f12520567ffcac95d2751096fb6d5faceac921417c987958e9cd7","enc":"deff44dadbb774f554d65309f72ec2665dbba45d2c981781c66ad82d114f12520567ffcac95d2751096fb6d5faceac921417c987958e9cd7","shared_secret":"5c413ae080cff126302c5a1d862ea3bacf9fd00f02acaf63612bae8e7c88d2abd9d32eab1e64f99b505aacfa62e8580dddf3d4baad906aad9ca9057e383d203f","key_schedule_context":"02c88fa84728b245b308fd6933bb5039e92b2d3dfdfe95d8786fd110e7eef15eeeed01013a4b3649cec0160061020dedf2ff1a5a9579dd7f35f82ce7e4da7034b2817d22761b0e30bbcdab3759c3f6eb30117e5901b4813c6a7f4a98cd855f07b790aea87cfe90b91c465c22904d4128111352d6be737eaa757a0e2a1834173707","secret":"42fc23ac7a7cbddb5414a11e957df27f2fc58856f4b9a08f385ec3acbf96143b8b0c475431983f9b3f2884b30ab81f7a252e48edd7400da0d29fd83faaa0dab8","key":"c77e2de11dab00f98f8e726f3be85fc1afa2beb360e3e0777ee5fae281e4a236","base_nonce":"553ab29fe2ef4a39c7e00d2a","exporter_secret":"17e14346812bc06204ccd086b8c94bd5401b9fcb089c1ff1bdb7e69655c0b89af1b5f7caf975d09e28d3b420e652124b68572ad6f11a9ac1235cdd0e9071cec8","encryptions":[{"aad":"436f756e742d30","ciphertext":"8332249fd30e505bb4d0e607bdaa912e4904f0e7dd7c2b0e9039b431d4ba02bc31ab010cc9d5da2c615599dd07","nonce":"553ab29fe2ef4a39c7e00d2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"c729cec5eda552f37ee6af0b4cb360c3e04ae8454efb6fc51ca0405ea671c9557dc189b0eb9a326cf625216dbe","nonce":"553ab29fe2ef4a39c7e00d2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"247561ec25b72951ac4f70421ede8a5e3b3b9d7349e5d7939fabee941ec617fb985456dc282bbdf8d931c8a6e3","nonce":"553ab29fe2ef4a39c7e00d28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"2a4bb2230c3ee5eff0413511775adcb0a73775a952946f021f771bebcba563d5267924c8a79b054cbe1efe8d47","nonce":"553ab29fe2ef4a39c7e00d29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"702b8e50e9474b49118a184ac61dad91e2627284668bcf194b476fb66b5b1ec245ef349ef7273094c7d3c58d3e","nonce":"553ab29fe2ef4a39c7e00d2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"eb89c1f6231fa93e97dcea6ba75a2444ebee89b5f8e373175ca1fdc8f71d1b1af2eaebe1f28faf021a2bb248cb","nonce":"553ab29fe2ef4a39c7e00d2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"b90fd1eaf1d630c7df4196f326671058be49773f802a7cf14dd2dcf50186f458faeca83dd516903740a3600bde","nonce":"553ab29fe2ef4a39c7e00d2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"f1d0a1cab78b320873e8b2086cb1d17b476cdc722f7911f3384ed9d5cf4fa0c2a9b882e3edbab0f54c4e2e1f1b","nonce":"553ab29fe2ef4a39c7e00d2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"7f1604bfd7b2b8e74c3a943800515c1c326cac07b86d50fbb1e6edb28078336f68032c0826957791d0c8a617ff","nonce":"553ab29fe2ef4a39c7e00d22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"8c01c6efa773629fbd00bc6dcb0e54731ce90b345dda3ebdbb6a815de7c67c1a28f12c39ba9019aeca1a8e53d3","nonce":"553ab29fe2ef4a39c7e00d23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"1a416e455b318d329d30789cef2340b44dc9594c3c062ddfce01c864628e2c4e01b233be4630c25a1d4dd82cee","nonce":"553ab29fe2ef4a39c7e00d20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"1acdaedb08479924bea40d0630e5bd326fc77894c485050a4b56c0e10651b210a15ec2ad6c67d2e9355a09ad1a","nonce":"553ab29fe2ef4a39c7e00d21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"ea131bc167f4bac2f58692b8e2e04d3fb4f6196c5d12c9a490342e428c16cfe8ad88ef3a4746caf529d4be2e75","nonce":"553ab29fe2ef4a39c7e00d26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"90644fc7a77d42d952348a7ca64efc9c5026ffba77081604a131212ceece90e17b866a97d5706c10ff35619b7c","nonce":"553ab29fe2ef4a39c7e00d27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"216e320604c5d6d04600aa38767dc77e2dab9dab3d88a22720416785c94466567caf04490bfc8dbbc56a60d1e9","nonce":"553ab29fe2ef4a39c7e00d24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"621d96b004c5b415b25eeb9a9e9a87a410ff6c7455f95b1caf8f73f0e86d07cedd082bc388a3c646275aa66333","nonce":"553ab29fe2ef4a39c7e00d25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"18e4a70d18717e281483d2553330d83ce1140dc284686f0cdbf3d885bdf4bec64d4a4320ac757096619ec438e9","nonce":"553ab29fe2ef4a39c7e00d3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"99560aeaf0fc284cdb08f29c4c537b488c6ad96534011c919c1caf8771cb080ec5fd35585da05d397ddd5e5949","nonce":"553ab29fe2ef4a39c7e00d3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"48eb13c1e49a89fcb4e23ee6996c50fd0cbca1af5ccc15f49d0d906d039d55212c6a398f85ac8f2995b04cb717","nonce":"553ab29fe2ef4a39c7e00d38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"fd905f32421ae6a551ffc5ef3ec4cae52bbf13698b6960457e87c52a83645808a391a61efa485e6a67a84b6115","nonce":"553ab29fe2ef4a39c7e00d39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"25aa386a650ebda92842618aa2f118813b6600b592a7e9dc8b51edf0ae2684f0d565015443d0745cd07231dd70","nonce":"553ab29fe2ef4a39c7e00d3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"43ee5c2c1d182e4fa9950991f32b0229738ffd1421ee8f195696f8f25cfade533142173091ca1bd1dc4a48f6dd","nonce":"553ab29fe2ef4a39c7e00d3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"8f55376e1e58229b48d5f53e1ce684a1eb5b290588f41f5c1410bf0d8401fb4667d1c1fdcc0079ab008c812639","nonce":"553ab29fe2ef4a39c7e00d3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"4ea5b33a74f84850b526338b912354a6326a7e93e7d1b955a70c87f326b7ff35694b287f7815c218d69632b4d3","nonce":"553ab29fe2ef4a39c7e00d3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"33403f46ff2e12ab8f8065170e3cda1654453878ba9a861207ed2f52022eedea31cf428a0fe32f5d207ecd3807","nonce":"553ab29fe2ef4a39c7e00d32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"b9c35b49949920d9dc5a6ccd80bc5d8b3375d87330ae057e282e665c3ab1b7dfa1d498b14650808a7d4f605de3","nonce":"553ab29fe2ef4a39c7e00d33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"86fa545160a381639df0e774f83781c635e8e81ce1734971d7e01bc9c32976c2db1a3b4140b3aac77aa82870f0","nonce":"553ab29fe2ef4a39c7e00d30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"55ee04ecb54608674d08b3782ab9c8ab92000a05811ea627d35f37ffe7d5089f44d60bce4e7678c79eeb0829b6","nonce":"553ab29fe2ef4a39c7e00d31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"d56362435487ba05d878871423a604e5bacf6d5eb13412269abee63e733256af978f16dc98939a81927b07ce35","nonce":"553ab29fe2ef4a39c7e00d36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"cca0a25d3766e246e9c9c313b01e3e670a869d36111b6da233c4f9a38a8b42c8d7cfb7fb9ddb24cfd077ceb945","nonce":"553ab29fe2ef4a39c7e00d37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"16c8bce41ee5c08060cc7abb1fd6c8c1284a556d642265a5c0c0d3eabc886d60b306215d6e7d19d69deb6eca8b","nonce":"553ab29fe2ef4a39c7e00d34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"830d76a9fc1b68606204d673d4196998c4f3b7b0824cd66124b606c7723727c666dc58fa92f350baff4b1b7456","nonce":"553ab29fe2ef4a39c7e00d35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"66aa9eff8948d905be8e04e04a1e1f1dcac9fe0972c9db14d62f76dda8a66466ec9d134943d673b6fa6d295472","nonce":"553ab29fe2ef4a39c7e00d0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"1ba0eef452aaff2e53ef4d71304e70127cf29f43eea2386bfff972831e768f3934dfc179da6902027b247a8a08","nonce":"553ab29fe2ef4a39c7e00d0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"8601f7c771710d77d4413187787c4e5d6b92971f13ae54f03f30592075c7d52e0eb569aac8e02da515f5ec80b8","nonce":"553ab29fe2ef4a39c7e00d08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"c6613aeaad230bf6d46f42f73ba8394ad9bf878793551dddd210a646de3fb92ebc90fe94d16434591e38531453","nonce":"553ab29fe2ef4a39c7e00d09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"99ff9dcbf424cb75e36f24c92693a2ea308c2b169afe449cc732f8866a5ab222ee924ce6060558bca9186c3e60","nonce":"553ab29fe2ef4a39c7e00d0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"1b267c46fc17e59bf1849dd5800f13b8d7c4c93570de7124518124fe8cd58957d1cc1ccc838bca78111533c497","nonce":"553ab29fe2ef4a39c7e00d0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"86544ed5034af6b9042ff9d36972c3de959c4bd5de5662d48f4353f3604035d29502c8d3b85081fb2268892ff5","nonce":"553ab29fe2ef4a39c7e00d0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"f3256c3d5eef2e1743358d083d4a79652ed17bbb269570b35fae4afa52572f4c8cbe604ef8c9d2b078cf2a7c7e","nonce":"553ab29fe2ef4a39c7e00d0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"03efc142cb64587ea0b5728d4d254c85fe35c38d8e6b1a3676eb6f1e400e7a4479da3b660433f4f72138a58563","nonce":"553ab29fe2ef4a39c7e00d02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"26ec12b76fd9ebdbca60c90b47bf49546622da331eacd640390365d7513f1dec8797c2cd98616a1d08de10510a","nonce":"553ab29fe2ef4a39c7e00d03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"b154983239c10df493e18422230f852db84a67c05ec13999b00e330247b65439d71026f079f912bd92c9375335","nonce":"553ab29fe2ef4a39c7e00d00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"ef45bfe564e2f227827b389c3a4bc3d54ebdc9231d9e00eb83858d02f320053377b0d950fa4004ec8d03e224bc","nonce":"553ab29fe2ef4a39c7e00d01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"217642ebb0c31b69cf732683a7deb04b1dcd3aa6443a3ae470a7c23f96ea0c012e7557fab8ececedb8a00af4f2","nonce":"553ab29fe2ef4a39c7e00d06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"03485952c148d59ba9e7b90d8806a4af83736b55041d7ba3e370ee6a6ed972537645fd5aa0a08422e026ce801e","nonce":"553ab29fe2ef4a39c7e00d07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"f0e322b359ea5d73334a8e14e6f8dae34c8b744c5a87d3c517d4d04fbe804952c4247b4f5564c86879481511a3","nonce":"553ab29fe2ef4a39c7e00d04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"4f17ded7b2d950f2472eb20de16c85ea69a2573d2ba58b6e8f3c837163af5858bdeb2c39aaa7ebe026f7c29840","nonce":"553ab29fe2ef4a39c7e00d05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"434af0e0562ebdb2df20d32387674004e293e5942fc115a91482e8e7b7ff8d68ddedb11d4c8118eb1b38a6573c","nonce":"553ab29fe2ef4a39c7e00d1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"39fcc9c09a16cb54fd1ce9bb0d77d7f47f07cea6cd0ccccb417975e897647c0c336470d4eb76b63af4b9c9ca85","nonce":"553ab29fe2ef4a39c7e00d1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"489da6d9669977f85c0350b352e4315ebcb41759f974e79a0bc632b9ea9a6f1380d731272ac0c2dc7308429a34","nonce":"553ab29fe2ef4a39c7e00d18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"6543ecb3b360607a7e35817a6a55172d848697b161d7283b66c5a1eb43cca293cefc268d09caf3915afd0411eb","nonce":"553ab29fe2ef4a39c7e00d19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"fc6f38b6f89b4fca7305df9f27fb08494344a0f332950b2b093ff45fce8ab8387f14922edff9f5ce0866fe2c71","nonce":"553ab29fe2ef4a39c7e00d1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"e0a1efe4300f9bb67dcdde4093a2f7e3d35fb58bb4ce1b12f2d7c3a4b86ea5e5ad65794146b04fd5687b0be2de","nonce":"553ab29fe2ef4a39c7e00d1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"408f1b0e8cb39b7d496258a6729fe6ce7606ec279b324b64016376cbd90a6fad7c8705fa996371bb064dee1405","nonce":"553ab29fe2ef4a39c7e00d1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"b957856d6173a1d69295391c837a2400700ab7d6d35bbcb069e35757dac6b637339320b4ffa3a6923dd982a797","nonce":"553ab29fe2ef4a39c7e00d1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"240aa06d2d0b2eedd5cac7d6d67987372abc74e1bee77b7c4cdaaca5541fa2bd9c43c201b812d9ef92993ac88f","nonce":"553ab29fe2ef4a39c7e00d12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"4521ad87a6a88ac68cde5bbabd5bb098ae4f26354f7a16d91a5822e4aa9abf082e7b5dc364b35a39a2348228fe","nonce":"553ab29fe2ef4a39c7e00d13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"33b6748f658b53ac5d5a70f7781049f0d6740c05bae2cf396a926c9ef6263817a40ae9dc978a8cf83c1542bc83","nonce":"553ab29fe2ef4a39c7e00d10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"98c688ec535208e56d48b23511b233c7de1bf56b83117c04c3a5a99eb032b6bbd650a7321111eabcb205eeef0a","nonce":"553ab29fe2ef4a39c7e00d11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"4054c332635527396aa588c6f3bbed5b8bc7779b2ca557f4477c2643d37d4effc2f64d7f489cae135c01e571fa","nonce":"553ab29fe2ef4a39c7e00d16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"a26d85eb8a32e49fc1da6b6ec2552cb49696c0ea5a169317cc6e8bcfb9505f4a3f7efc4cf987b1017106041fbe","nonce":"553ab29fe2ef4a39c7e00d17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"130a22edaf8e89d0a0f097718bed152875929fce75b84a33119bd17618a9b28a0778a2d4355abbc96086c61634","nonce":"553ab29fe2ef4a39c7e00d14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"af1956aaf4c2227c782dd2e01bfd0937807a69c56ba7cc05912347ee3578bf4a75c10f84e0987fae0254080d5a","nonce":"553ab29fe2ef4a39c7e00d15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"e1ae9159aeb04b932c0990d603cf6763bfcd15ed3ebaf7713362e00c3344936a2d16033811ca23a5944d8dae0e","nonce":"553ab29fe2ef4a39c7e00d6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"79c9bfa7ae46209ec3180aa11be7b01cc7f4373f6e11867f9514235792325f68ba4f710072ffed4d114a4485e9","nonce":"553ab29fe2ef4a39c7e00d6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"fe90981404e3f02d25ed956dc6b59093f450e00860d8882b6054e791174515fe434ebc4f15d28eea9381ab8f01","nonce":"553ab29fe2ef4a39c7e00d68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"85ca1cf1f76825165b8866fcea1d57f0fd4dcc6bafc2dcbcd6c42eb08b7fcd14a714fe727bf8eeff410591fcf6","nonce":"553ab29fe2ef4a39c7e00d69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"568863b8bdca2392a3c113b07115f7840e098a211c2c7ae1e523948c599c4118ac813915f0eddd6ac0b67d808a","nonce":"553ab29fe2ef4a39c7e00d6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"c1fa88a830ece37c7c8a9b88beee0a0c5e84947265b0643c3b3b2f5a88768407531d0f3217659d3514eacdddb1","nonce":"553ab29fe2ef4a39c7e00d6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"82ad10e6e274b22e4d7b9a67d04c72f8f451d9102d7a4db09138878ece99d2f105f4291b6ea1d9d2d737cebc3c","nonce":"553ab29fe2ef4a39c7e00d6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"8bcd466bd86812bf178ef50b2a586715ae114a980f038a1f4a7bcca3bec6511dd0d22a47cc108830bb2e5cedcd","nonce":"553ab29fe2ef4a39c7e00d6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"e69d4e87242887bc1157ca6a055d08c18e1dadf23165e4fa55ec965b788d4f5bd29768a46420db3a665a87b180","nonce":"553ab29fe2ef4a39c7e00d62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"acb6598dd5561c2e2ba14dd9bc0fbc77f4fd9d52b579d17f17a0a16d570ee6d273b6650efbc2e6df263e249203","nonce":"553ab29fe2ef4a39c7e00d63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"f07e03a251a190609fbf2754929e4d60778178882a0302f732b6a3dcffc61d7503fc27b194c30e45ba9a5b50ac","nonce":"553ab29fe2ef4a39c7e00d60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"d06055e1920fa5465cdf87c998c26509d0478eb0c655107f6081093bfc60fb0e2d41f9e9b7233820ed7caf8d33","nonce":"553ab29fe2ef4a39c7e00d61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"0b3b7bd1e7fd7861d0390b9ac427bc18c7ac32bdbc3fa0275c991e2d1c29a782737be743024b57bdfee8e8853c","nonce":"553ab29fe2ef4a39c7e00d66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"abdda63f857dc77b69cc245f7047a501cce29d7935ffb7627cb5ee8e15d97a4d809a518aba60b6af83408e5656","nonce":"553ab29fe2ef4a39c7e00d67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"92b717c780bf4b74644b578621013bbd74c4cde5de7fc11b7be7bf70ab5962675c24c67d01c3bff1b787d80584","nonce":"553ab29fe2ef4a39c7e00d64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"51768ef11df739bd107cdfd86b3152c007a23c9544442582ed26f6de56672c8831e1c61a78791601bee2ec1d10","nonce":"553ab29fe2ef4a39c7e00d65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"6fb1bbd82bb4e6b7298eff6b22ec3f50f413db2a9c3023e7374e67989509c104bfd231da8c98394ac51d2b93a2","nonce":"553ab29fe2ef4a39c7e00d7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"da3d2a11e7f4521ed6be71006713e6c6dcac3c47267bd95a1deaa8660e70bc055d62934e2ea7bfaba8efc034c3","nonce":"553ab29fe2ef4a39c7e00d7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"fe8f71ff78f36945039f49f0108cac99d7b543b1a483354931f3e1354ae450a7326cb68e670eafc613c60e8d62","nonce":"553ab29fe2ef4a39c7e00d78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"10a34b1e55a1b1fc0100b9c711e17655013017241a2f040d7cdf07d2f32f86ce6f9268ad0b136369324ad447a3","nonce":"553ab29fe2ef4a39c7e00d79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"9030aff3eafd47a9fc9ca5d4967fce84d7290e16e0c4fc4c633fca974951fccc8da11bc907aedb474786fbe3a2","nonce":"553ab29fe2ef4a39c7e00d7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"79d35c13e686253cfe06c57b54b2f7eac235ca137303f014393203e3f8f4264264491bbf77b75f359cae1cfda1","nonce":"553ab29fe2ef4a39c7e00d7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"ca4108a2afbd87d09389bf0ea3e86b504272b926f88d2661e2881308affe2f790ddbe9d156a433fcbb8be8017d","nonce":"553ab29fe2ef4a39c7e00d7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"4fc21fb8879e9354981a9aede2a62ce838b23264085a6b7d8fbd624492db46c2c6c65388167b065ca4c8dc31f5","nonce":"553ab29fe2ef4a39c7e00d7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"d0a111ee67d8c657b2c01c03c89c3a567f48cd4463d80eb6c98549924b6564e129981e0eae9212b59e8a4a60f4","nonce":"553ab29fe2ef4a39c7e00d72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"83b27d587a0d0a399b4126655719f20f254dc08f2076a439af1653494f881738807b40582ef1b9f34ad546440d","nonce":"553ab29fe2ef4a39c7e00d73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"0a5ad795d651c56fe4205279e0debf948097a604802fc3e9a4f03333a1e23fa07c8bbd2212d1cf464e8a0eed62","nonce":"553ab29fe2ef4a39c7e00d70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"243d9f3ef3e93bd3037e5eb4aa11ef8b7e6a6d53a7a9b5fc51893bac0bd44e896f8037f184e7bbc0b4adbfe0f2","nonce":"553ab29fe2ef4a39c7e00d71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"eb4aaf831df4b58fc9dd9668dc1c4693796e658fa1af258a2e224c9036c63692453dd016c0423ac4f963052ade","nonce":"553ab29fe2ef4a39c7e00d76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"5b0b8501494474e1e6aacdcec989f8442542aff44039d2ae534bf6827c89a43d5158082474148d8f9a1e62751b","nonce":"553ab29fe2ef4a39c7e00d77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"c828d3d6cb20d97ae849ef1a185fbd87ab32a8e9393a7d58d06cc5d0112d970e0aaa0363bff8528c005e5994fe","nonce":"553ab29fe2ef4a39c7e00d74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"ae497856ee89107fa056a955647360c4844de3dfdc6fc6c06ec9aab0dcc1054ea213205dc5bfd86f1b69b5800c","nonce":"553ab29fe2ef4a39c7e00d75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"4bd4d1d0bca1d248ffdf6888da45c34655018651e4a4327178aa442a15a34e052a691a8a6fdcd5933b2fefc277","nonce":"553ab29fe2ef4a39c7e00d4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"5eae208925288c9aa84eda57b139e14010301f206f17fc11290021b4739ebdf881625470933e59ccbce0e32e72","nonce":"553ab29fe2ef4a39c7e00d4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"1753d75edfbb830d6bddd00686a6bc16e99d423a308330c468954e2565aebd3a0bfb12b1f5fb038a2202094f53","nonce":"553ab29fe2ef4a39c7e00d48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"1c3b792910f03dc7aabdd025c6ab7262a0ba149dee97634755d4d16b6d9be4a6afdfaca8f3eb0a574c5a64b31d","nonce":"553ab29fe2ef4a39c7e00d49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"2af3334a9124d402c849fca60b37caf5fc2f99691344e9ff7084b77e858361d22faf188f3db1b8a01eef7fff1e","nonce":"553ab29fe2ef4a39c7e00d4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"1819f08ff26a1857d6ef1e9a3e002e0faa2f3f817b2c1d19c62e5d2839c2a16b099dd3bf1508648b41916bb126","nonce":"553ab29fe2ef4a39c7e00d4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"78d6bb7e5b906920e235e0c4f3720cfeccae6c0b25ee50935da3e19d71d206b41ed3d1f7a7bf0ef9c5762b0413","nonce":"553ab29fe2ef4a39c7e00d4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"86b3c01e9916c8ecdd5c6ffb2d5543f23693f915c3e1da75237e77502a41c86acd2f3796b670cf087eaaa03e83","nonce":"553ab29fe2ef4a39c7e00d4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"67eea6a1c9583e6dde4bdae8a215b91e07ea551f3fd9891cde4eb7df654185c46c279d4e34e4238af4cb214a43","nonce":"553ab29fe2ef4a39c7e00d42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"25bb91a5d53735bf17377e7cb338cffaa5b81326357d3f8a6fd0e4b78e16359a2a6fdc9b3e808b613b5e9ca896","nonce":"553ab29fe2ef4a39c7e00d43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"2f4522c82bdcc7e08f752b65e893f0b7d9d4d7ffc5a1134ce8e5de7ab5905279c98a275a23b73968772f1ddd9e","nonce":"553ab29fe2ef4a39c7e00d40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"2ba320eb3c40bb208fc116b268c186c6807a9dd9e2d51992c736a7491cf913fec6c41717e5ffd85bb23191468d","nonce":"553ab29fe2ef4a39c7e00d41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"de6e936bdc985997de4bffe98de2756a8d583c2b0cf39c67e730ac5f038df1ff403405e8dea2ddc32e5b63ff74","nonce":"553ab29fe2ef4a39c7e00d46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"c72d53b27abea1c15623f9dfd3ef3d752c1f0da26d1497fbdcc564a4bd9e2d2ee8b58d3a8178110014ff631ae9","nonce":"553ab29fe2ef4a39c7e00d47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"37bd12f9ba71c1931461581d2088d33d253ff6bbed823c224d24f5cbd75bcee1cce9a1c5b83181a9deb6a35b96","nonce":"553ab29fe2ef4a39c7e00d44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"ab14f1634de73af7173c878f3a52cca4e1132652432c108dc980c5110be56a6465e771f3da4c935f988f426cfc","nonce":"553ab29fe2ef4a39c7e00d45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"425388c6e30bba7675f20dca57d4635fe2871fb8b78b406a31ab455f8b9f2518e18de31f47cba7cea5dfb8132f","nonce":"553ab29fe2ef4a39c7e00d5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"5b9fc3a7cd91ff4cf1087673fc153003e06ac78d5709b378541d4213a704fca6f31a440bf9c260b97820989069","nonce":"553ab29fe2ef4a39c7e00d5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"539e1f980b30736ad19695008f8f456a14a299ce40c06b716e14003eabcd87e7e86b684fcd416970d47168f298","nonce":"553ab29fe2ef4a39c7e00d58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"0b87392e30e494f326d4e3b35e78a1a39dc72be8209808ed9106731807a3c239bd4cae8600186c19ec655e309c","nonce":"553ab29fe2ef4a39c7e00d59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"98b20118f12b155e7503e3099ed50dc9c3fa30e4020347aef57f1247a657f156260ab95346d212dc85a94155e4","nonce":"553ab29fe2ef4a39c7e00d5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"5a88c9c47e1e770396c21223115f2122aba3c230f8d6813c8664af6f7bebaa2fa39d5b97b87631e65baa3d8322","nonce":"553ab29fe2ef4a39c7e00d5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"29deaf099b5683f2b213e8b5b576d84987543f696362b059663c5668fc7519877da086c3736a3966b1e0967220","nonce":"553ab29fe2ef4a39c7e00d5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"1aaae72ad15dd9de45738150ac00c26870a95581c799e26da6dde48e7f9ff2037613bc509e7e10ca9e4822faee","nonce":"553ab29fe2ef4a39c7e00d5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"51a44476365f3ba707097f9de7477c2b8f6ac143e30f687254dd7b4784d948e378b5468c76fdae48e3480cf335","nonce":"553ab29fe2ef4a39c7e00d52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"de635459c285e40719ea467913d5350b6fc850e2e251b1b10a0ef0a2453e4f8c6d52c1d48a972cd20c48bd047b","nonce":"553ab29fe2ef4a39c7e00d53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"de7c927151a9a2c78594781a86e58afce9f147e66ba1878af27cacc396f553bdadcb080d42b0061b3a9435d24e","nonce":"553ab29fe2ef4a39c7e00d50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"ca249e02a32f85ba6ccc2a4650c8048e9fb2655fb44067cb7cb6dcdef2c5a397e1afd1a04e2af46104cf1e7aca","nonce":"553ab29fe2ef4a39c7e00d51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"daa2fe6fa0a2d3bb835b7d075b52dec805247774a903eb1d1f1a7a4b062db7884c596b2a434dfea220c61d0570","nonce":"553ab29fe2ef4a39c7e00d56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"9fd1077c64542f05a4c43e7442c65ab00ae32674bcfd180b6f4179c48898d18a8c74c7371d722a98b3487ac164","nonce":"553ab29fe2ef4a39c7e00d57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"3b5b2d88ca204a3ec24be304ec64b92d4c5e0b61914aa007a5f171cef9b7b18d75114b7685ee4f1cbcfe0c3276","nonce":"553ab29fe2ef4a39c7e00d54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"4a5dcc9f632ea05ce0ac921de68f8617c54898d6bd77ca4a40fc6a7ac2ade4513d7b2cb1cfd93af410c44f3b6c","nonce":"553ab29fe2ef4a39c7e00d55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"8969fcef08f10957a307cde3cfbc222992adfb3afe700f3143290ba993e4e6c9fdc83533aa3932d39289e3c1a6","nonce":"553ab29fe2ef4a39c7e00daa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"a14dbdbaba37a34375a09faa23bddfee9411d77f1d0a778e4d6459be582c7221d446f00438701b77138e420c41","nonce":"553ab29fe2ef4a39c7e00dab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"95f0fa630ca0cf40c64236d2a5c138ae47adab1475d0a96b84cdec315486a4ce8b0ba80d8e7fea410bfda1b25a","nonce":"553ab29fe2ef4a39c7e00da8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"546b1d86fa40bad5b2b2c13774ee28aa20b3d8d0221d3c35700ace1c2981e12b929eb37db69b3c59d2cc60fe41","nonce":"553ab29fe2ef4a39c7e00da9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"bdc31e254eaff9ec651d92e5a53b810182a4ad7e4d91965c098addffe35fc7bdcb3cb7e5f00df0fb167b9565d0","nonce":"553ab29fe2ef4a39c7e00dae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"316819946bfcc225c312807ff8fd01cbf234a520843cb392e7c1a26963817e84875996b859b725a92ea8e53863","nonce":"553ab29fe2ef4a39c7e00daf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"e46f1ae5e3012ebe7af126b12a30f2b0015ff26148c91d51d9bd7a62e60aa9b22d7aaf04b230ecd7cb45ba8eb4","nonce":"553ab29fe2ef4a39c7e00dac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"91f4355ee2fe03bae240487f6fa2a59fa43d88b191b6ef6f08056a5e8e95083c0dd0c3c6372f0e77f8f751557e","nonce":"553ab29fe2ef4a39c7e00dad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"2a9b8f0453827ea5a8c576b0f77e83a53c1513b5e1c9ba7fdf8b2c78dd27948d86ac469fd8b908de175b299c5b","nonce":"553ab29fe2ef4a39c7e00da2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"ee1284377c0c1c77c3f98fd14ca9d7d98a526ddbaaaf19d9cef0bd69bc8fc22ba1c436ab58d95d4de3384de183","nonce":"553ab29fe2ef4a39c7e00da3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"350b30c3452fbbacea29899c1f5615ca44d465ad848ab71781d7796a4f6636f0596916b0d147cd2f5107ddeac9","nonce":"553ab29fe2ef4a39c7e00da0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"0d058405b4189d8ac03f06a06d827d40b58c17e70ed52f00e7f4bb8b1284f7388d680695e5230ea6867bc35bbb","nonce":"553ab29fe2ef4a39c7e00da1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"1bef535a9ebcc02212ab54e391a6393a6b0bfb6bc71e11bb39f11b5b56fb947d65c8d6460170f9df6191958b2a","nonce":"553ab29fe2ef4a39c7e00da6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"d635ad5c88368b4ccefd68a268e20b599e0c9a0e820dfdf33caf8eef73ed3232145a6887c9c6f4ccae3e8b4e7f","nonce":"553ab29fe2ef4a39c7e00da7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"69e3ba7aabbd0fe1a8a9f259340ce7ed1d9ec58a0ed590917d6781d425727c7e48f4d26935857b0555a994a87b","nonce":"553ab29fe2ef4a39c7e00da4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"f46ddaf013ae13c84b8d3a643d8bd4b56ad8589fbd4e9e5c2380c36e40e31e27aa0b16bb947c3350e691f158be","nonce":"553ab29fe2ef4a39c7e00da5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"ef41217c7ca69c6e47f330aeace3d56c5587393231e33690eba77227a7472254fd371a3baf1ed2056118282a0b","nonce":"553ab29fe2ef4a39c7e00dba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"7b3736e193d82660e1019c88d6f09bd6c47efd8829bf19bd5ec4264cf5d5a826db23a832c0d9d8815ee178ae7b","nonce":"553ab29fe2ef4a39c7e00dbb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"b39438982086de86ecd619409db5d437a2f2091e5499951b82950be2c543431fd8f89469d0be95708857059b9f","nonce":"553ab29fe2ef4a39c7e00db8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"f56fd6eb4568d67fd019b8611632e1401f255809c78877cb3da5de2553ee6a01d0c10e8dd3928ff84735b46b5d","nonce":"553ab29fe2ef4a39c7e00db9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"0045b49261ab43ddbc0e5811efe0e06690c75f0b1cd03e90b0c369cf87d412965de1c89e23914258bf2e5ae4c0","nonce":"553ab29fe2ef4a39c7e00dbe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"e0f96d491f8d9c14086ee63f9e556680df293835df7f3e2817349755311cc0a9c62c4be40c4bac181acf59e858","nonce":"553ab29fe2ef4a39c7e00dbf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"28cded33e703f95ff328eadaa4e5285ee00f3a51bd0aed9ccc17982cd52617c166adab3e1f2cb77925762cdcc1","nonce":"553ab29fe2ef4a39c7e00dbc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"2084de6e9fa51e6582abe571cb7b20dd14ba2cd39d60762d574f0ca315fbe32de935218d7a2cad86475d06c673","nonce":"553ab29fe2ef4a39c7e00dbd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"200860cef7ed7e3d009a3efea354de02d4c959123126c051ca7d86301ba655a7db68fdefb4741efd4fae17e597","nonce":"553ab29fe2ef4a39c7e00db2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"dc583b6cc53379aba3f58c35dc775bfd05ff622450d9929073c44cdc113663571df879a9b4be93d5fb7ae6b217","nonce":"553ab29fe2ef4a39c7e00db3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"c425de96b98575319a4880b9c03c9f92ba7359e70f8bd4c8365f6569ff6adedf18a9a7212018f472719f6a07f6","nonce":"553ab29fe2ef4a39c7e00db0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"390e703062a98441ff026991cab108ce3c118beb098048625771a4103da716abad94ab0d1519e65181fc74db22","nonce":"553ab29fe2ef4a39c7e00db1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"66aa422ef243c53dfdb95cffbaeda33750ced1978ed22e8d1a6ec2dbf30c7ad0dd0a144959c43d4194116616da","nonce":"553ab29fe2ef4a39c7e00db6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"b535287c1c78a90b9159084ad0b749cad684c5d54243ff8df05c172382098ca405857b0aa65df22870c7c27978","nonce":"553ab29fe2ef4a39c7e00db7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"d6289ca7fdba61192bf4ee6a68ef9b2923f1888245aa1e9bc98cc914230fc29b3c3e044aeba8350a60b47708f4","nonce":"553ab29fe2ef4a39c7e00db4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"1f217453c6201991d22c3573bb325a76a57083062575ed0f532e92e8a659195569164d9291db76e4ad0cbe5496","nonce":"553ab29fe2ef4a39c7e00db5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"517e07ab9b5e5c5f48302af70fc5f96e396440bd950589c615896a26ea361b41c603aeaa61195d644c39643693","nonce":"553ab29fe2ef4a39c7e00d8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"1d8e6c0d8303d67ba0b83eff91c044074cfc627fe2cdbd757a2b0299ddad311a1c2039b1fb5918bb4090bbac66","nonce":"553ab29fe2ef4a39c7e00d8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"495b7a82f977f9a4b9cc9cf970b9ac658c509a809234cf9291c4592c80f7dac19a527521c3b0b43e08aa4c4561","nonce":"553ab29fe2ef4a39c7e00d88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"35a290f38a99955a9eaad6d7ab8b616fc4bc7defa971e6cfc2434268e930e3ae231579a7a3791e22916e088634","nonce":"553ab29fe2ef4a39c7e00d89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"691e54e0c5090b57869947000e57ecc1c25ad9051421c50d3250fc76320fc9c6cd0fd6843ec2b99c735e8c6b0b","nonce":"553ab29fe2ef4a39c7e00d8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"50081ad85eaaefde944cfe1a01af589e791a4fe463f705df61a7a8d863237183a7d7d6cf0df11c05b7c0288c09","nonce":"553ab29fe2ef4a39c7e00d8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"a436d41b0c2358d237517e6021ab74ed6716acd4073fce745a0eb98def4a701299f8c568f7dabf0a6d39449007","nonce":"553ab29fe2ef4a39c7e00d8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"0ab4fa99044684849c57be8a441bbba4b13c0f79f8cbf05673ab19ba646566d41c54074b0d88972ad91965983f","nonce":"553ab29fe2ef4a39c7e00d8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"80b39fd438a6f7d2f3ede41b8d26fe5a27f5c12bdcc4a9e2aaf9762ac769f9decd84508a295022f76e1ca323e1","nonce":"553ab29fe2ef4a39c7e00d82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"071f3d5822e880d1983471edf8c33d91c4ad2d2b388352011facb86f1380e96285379e29145654ea3cc3ce8d31","nonce":"553ab29fe2ef4a39c7e00d83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"48908d51129984189c420956cd86aba89b3354ae93b0aa5b6f4cfc9e599f56c0a14cbf0925a3056b68ab575900","nonce":"553ab29fe2ef4a39c7e00d80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"b319556a7396c4cf0c04a9192e4a7b285c27502d1097c049eb0814b4511026ea77e9836a170973008708a24e39","nonce":"553ab29fe2ef4a39c7e00d81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"291e1f6b84af03ee047ab83c2ebaface77053529ddd5b3c2a04db4ee752faf3b20c1a336a31dc1d7fed15a3c21","nonce":"553ab29fe2ef4a39c7e00d86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"319190bfd83af13bfcdc563803f397fdc5efbce5b6d643a4abffed50c72819a548e79647826d13ec5d525a7fea","nonce":"553ab29fe2ef4a39c7e00d87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"2290106015c6d81613727138ed2343304b21902eea3240ec338b234b7c4972c527b9f4c2182739b0f36802d0c2","nonce":"553ab29fe2ef4a39c7e00d84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"34c6f6f595c4addb5996ce231f6d245389ec892dd3a3ddc3868d957deea423caffb35cca18f7f32cec578cb77f","nonce":"553ab29fe2ef4a39c7e00d85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"d673dc469138a8343ebef843e70d1eb4d73f0beaef64013a23b90bb0fee857a55174839112da3aa00f323eca4a","nonce":"553ab29fe2ef4a39c7e00d9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"196af506e09a9038d4e6d2375d69121546158c88e02e9fd249428afbf395b888153f04d92f8b10e298562ddd83","nonce":"553ab29fe2ef4a39c7e00d9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"a3f6c0f0c2e64d4555268023de8776da1c1c8a1c5270b80eb7fe15b3735b62e70b2cb85d04251c1c894d496272","nonce":"553ab29fe2ef4a39c7e00d98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"27d4e7fad35152e080bbefbe97349ea5b305cb9d646ac8f8ab0a157f7b2b37879c1d760055021352ee4d8e0fb0","nonce":"553ab29fe2ef4a39c7e00d99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"6825122d96bf5ad3df35ca9b502a1abc78ae792ffa0191ea8b455630c6dd38543d07f5c7c1de2482bde1c66ef0","nonce":"553ab29fe2ef4a39c7e00d9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"c659fd76a1d800562795aaf0363e7cdb1b1364d403a1b20f2949405d4d861cd1b397f946c0b203faed788e0d4f","nonce":"553ab29fe2ef4a39c7e00d9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"023461c7d7038e7207ba4ff6a4fd371ae4c29b9cb2bd6cf61315490408f08ae5686607bfa5c3128ff43f5dd3d1","nonce":"553ab29fe2ef4a39c7e00d9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"2d810bd8f2ad39adcbdd56c0406a4ccc9d73e5986e9b52a90bda5e60ad4997d11803f134022b3c23891f20e62d","nonce":"553ab29fe2ef4a39c7e00d9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"61ac62302e204a2c7676d5c2bada1b9c68ac22596eb5cd0bb4cb130dbcd866dc436739b9396c88d63385c68be8","nonce":"553ab29fe2ef4a39c7e00d92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"0496c12e6f142d3988fed6f687f81c562c2f4802fa7f86b57404baa5cbdfabfcd5cc2647cab214c7e732117733","nonce":"553ab29fe2ef4a39c7e00d93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"f6b2545d8f65fa29b365d3c02b13966b3e136feb40b1a3d34c6902291e8e1aea15db66e6f39095bcfab6838074","nonce":"553ab29fe2ef4a39c7e00d90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"8fb024402464630454becb91fac1d86744e047587998beeb78e16adcb09c23d299ae7542c1daaf381c4aabd61c","nonce":"553ab29fe2ef4a39c7e00d91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"49a9dfa06a72fcc107a84a9a2cffeada6f13c82b47385c82c6e8b955fb455c2e4c0f4e7a5c02f0aba041cf3d32","nonce":"553ab29fe2ef4a39c7e00d96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"f769a7894a2722175e515a30adc811194f41a2b3edc9c73b855a88010dcdb8f545a995dfaa53cd8911a1b5c184","nonce":"553ab29fe2ef4a39c7e00d97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"0f6f487428ec6188d62055733592cfca2f8254d7da9336a24cc02a51a0bffb8aac90bee66118f84dfabe242918","nonce":"553ab29fe2ef4a39c7e00d94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"51a74752b503772cf9d5bec63a185111821811731ba2bf0ed24afb30062bf94a57041293b2579bfff490d1ab41","nonce":"553ab29fe2ef4a39c7e00d95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"e73ed08f01be367f49144938fa532006c63385f620b92ef1a452fdd325609752f5c7789df4ac4ddd697512a601","nonce":"553ab29fe2ef4a39c7e00dea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"f1fedfba6c02c971d20e8e01144ba349fb791fa51b76670a1e35f9a0c1a63391da59949965a687115875f28c0f","nonce":"553ab29fe2ef4a39c7e00deb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"337b6b82b5502446fb1318161d6d80a0a7231730fc9852787650a0f8cb8300f7a230a0181cbe2a72149ff91018","nonce":"553ab29fe2ef4a39c7e00de8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"90dbdac1634963dfabd04db868cab0451741f4f87b2423136ff2f7297df910bb6ae9f6b31cab1b3b2f6eafa181","nonce":"553ab29fe2ef4a39c7e00de9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"a82beb70e0f020cf5cb262ccf023c734943a0298e7bfb82c7aa124b4d1bacdedb7ceb9d9d4e3a9dc1d3a14f065","nonce":"553ab29fe2ef4a39c7e00dee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"2265702541de4a368ab6ba024aa541239295c29c03b73a7c56f6cebdbb3df0f9e8575711064448f60449785cec","nonce":"553ab29fe2ef4a39c7e00def","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"f9a48a98a2fbfe39522c10347f2fa3e1066e90a84ebbb5af18d6d04121ad41701eb039a5b2b2ec8476448092d5","nonce":"553ab29fe2ef4a39c7e00dec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"1378f180c91b5ab14d30ba80e8e204f8cc34c7b87dc9c4494b4c932089652c239a2a8636e0c884bddf590d467c","nonce":"553ab29fe2ef4a39c7e00ded","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"8fb93fcddbd8cb52de149dc1493e8228fa3b8c47cd7a813fb5f70fad28d009b12be34dec3e32e0a4d8aec4271f","nonce":"553ab29fe2ef4a39c7e00de2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"4d8ebbe5d8519d76e15079f1872594d3c36b13100f31c81f0aee0e73889fab27bc456b0163a8c81841e62ac2ad","nonce":"553ab29fe2ef4a39c7e00de3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"6892698a7452e8a1f7b0ecf3dcc78983d69f6379fe952bd1ec3d669db9a42bc2adf07ae914052d7ac029765c48","nonce":"553ab29fe2ef4a39c7e00de0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"617521e724b32af8b3dff0e04d2bbbe1c9ab6d540677cf82f5145488e758a199a60aaf59f001312752304215a4","nonce":"553ab29fe2ef4a39c7e00de1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"1ea09b8c54be0a8d956466b2848b6680ffbf4cf94a5c47184e111ef15b00dbe4a67631d6677ed0c592e17d81de","nonce":"553ab29fe2ef4a39c7e00de6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"c142a29c76e38ff0fe6c3e6992bb45e65bbef052a8337d8993a13fe02b594246359461100ddbdfa5b8a1243f2f","nonce":"553ab29fe2ef4a39c7e00de7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"30ceef15e904707cd9fbc0bc8866f794b0041c750c0dfcbe1045370c314c45d7f1664c65d6bf25981cb37ce631","nonce":"553ab29fe2ef4a39c7e00de4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"a01557de62da3fad544729d8c009cd0f774567b91d57cdb11001928c31ed3e09cd3838738db5a414371dc26167","nonce":"553ab29fe2ef4a39c7e00de5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"0de509162386915cf129f19e3cd4d5a9a93f8744c83aef9810bb96cc740f0056ce164590d442611c1ab95f77d7","nonce":"553ab29fe2ef4a39c7e00dfa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"2e2254509cc893f4af9904ff9aace4e3687af408cc44e850297ba778e035adfea353ff0596bfb1d7c812a6d9ef","nonce":"553ab29fe2ef4a39c7e00dfb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"c17d09337778f1de7b2664c469a73d9de38cf3e528225ce4d0b15f318ad2f1e05396709a88da19fae21b957813","nonce":"553ab29fe2ef4a39c7e00df8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"fc7f5a89e723eca187e10c9b29b3cd3dbbc077d76eff61437a0733802dae552f31111d7baa440b24c6ab348bf7","nonce":"553ab29fe2ef4a39c7e00df9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"16d5020694878ad681ce642f648d70d6947f3a72f8e3df707e45566ab6884cef85bae27e0d1e8accaccf67ee45","nonce":"553ab29fe2ef4a39c7e00dfe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"98df3704cbd3b5bbf986ea344b9196d0d58c17509fc1cb117b17f4aabfbf09b4eeb8cd29bf6617d2713f38e6b5","nonce":"553ab29fe2ef4a39c7e00dff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"e483cdd7f784c0a486e71f742b420256ca96667c39041f28b5add3f8a4f17503ca1ccd9cf37bd92d364ffe2d11","nonce":"553ab29fe2ef4a39c7e00dfc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"9d22d988ce4a3624d46b2c0c34ad76905af41fd87bbfeee57fac9a7b97b3403630d4fb96e62bb7d2428edd10f9","nonce":"553ab29fe2ef4a39c7e00dfd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"e98752d4b1e2f4bdbf66231558d6580c203098e554cec75e2ced80f2309dd2fc2167686d661ba9233094269a31","nonce":"553ab29fe2ef4a39c7e00df2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"b36933890347ca8d155ee4e78118b93df5a8db73d3f437c2c60480e63bf2cf6b3ca5dde0d84f8760e18343afad","nonce":"553ab29fe2ef4a39c7e00df3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"4c90932648534c5b7319101ae87b220c9575d7e33daba06115fe39a557b8a305f68b5e5f02fb2db0a30b2451a2","nonce":"553ab29fe2ef4a39c7e00df0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"f5fa43743828d38be728577e70b25ea9298f3a24bba4a93a00ce06b4479f997b4eaeeeba310a39cc5586829416","nonce":"553ab29fe2ef4a39c7e00df1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"cf5e5542038f7463cbbe1828aec3c570f688abc76230e076feed92d697826f3fce987db2ac8421114bf89670af","nonce":"553ab29fe2ef4a39c7e00df6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"ed97db6cf54208fdc9d95b3258c70684b92562e076d0fb14f1970fb896792fb5341b471a8e8422be9c5c0e348b","nonce":"553ab29fe2ef4a39c7e00df7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"fb6137f181c6e9776a6a33e5f359c75085a7a0a999337cb69db9c329e4b0403e411ede0e212242b6b9ee3bbcad","nonce":"553ab29fe2ef4a39c7e00df4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"053357b6679e042c226a9b2d3c4cd8696b0cfde1eaf8c7355db2c2c6f0a12368953f6dfc76e403e87b8298c513","nonce":"553ab29fe2ef4a39c7e00df5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"4e17fa3e3ea8432758ba1b1f1250ae35e72a5fc165b62e267fe1680618b0798fa3cfe78324d2760eb5c59db016","nonce":"553ab29fe2ef4a39c7e00dca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"4e964f74febea993d65654f3d66555ec56aa5e7e9d5c456ff8cc71bf66e8ef40d9e83ec94734fc1eed36a6a4aa","nonce":"553ab29fe2ef4a39c7e00dcb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"8cb704854f9e40e0d76f3dee906cc4ee1eff3699628da4cf83fc4dd32d50622d77aa7a7c5580f06697bc7e9106","nonce":"553ab29fe2ef4a39c7e00dc8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"b28a52793d7b59698bb3bfb85ab2100b339dc774d409dce0e0191b1c5e2657048b3691d30f55357cdbefea92e0","nonce":"553ab29fe2ef4a39c7e00dc9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"1df5d603503278537630f293bb73a458e27d54577eb8145cc9f34273aceae8053536ce79d8f62d7397410fc9d2","nonce":"553ab29fe2ef4a39c7e00dce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"d52cd87b9215cece3079922ad57ea44f371bea05a4c1f7c01929302f5ea05e8415c00a2adb465a93985fc59132","nonce":"553ab29fe2ef4a39c7e00dcf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"af44bec51050af5c9919b95bda6601d23137245268e9a14dc2e6d27c9d6e22eb8cfaf31c10223dffa45a550ceb","nonce":"553ab29fe2ef4a39c7e00dcc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"243a0bca52b8ecb1ecc8a63af066e8a8b979f654644e08c074dbea0779182ea8441a8cc8dcdb8bba4fca29a6d1","nonce":"553ab29fe2ef4a39c7e00dcd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"8e93f43742e6d06efba8010110747d93c5477df90d437c7ee16315bf285927014e73f3fff2b0f6ad3ec005aec9","nonce":"553ab29fe2ef4a39c7e00dc2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"57370eced099345d764404a9ee80a2d7ef35a01567b110f157b9e9f737165e83678c087808aa09f4bfb32fc883","nonce":"553ab29fe2ef4a39c7e00dc3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"82a6edafe8116275142699a5c3c3be222a644fe11d17e5b56823037a0bbee83d994091c7b7648679caf66e8718","nonce":"553ab29fe2ef4a39c7e00dc0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"17a6f52f030f42dde81838eeae59802b1f230e9ae7c43a0bc88de94524ec9050f272466b58b12ac9a505a56a06","nonce":"553ab29fe2ef4a39c7e00dc1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"3f3ec7bbd9a28a621002c94b770cdcf0c5a5be715b4a34e80743687112e9a518e2485ab4e6e323ef540845653a","nonce":"553ab29fe2ef4a39c7e00dc6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"bfcb3b0c22104eb402d7bbccadb3e23cf13a2ffc7c29c23065d8a1734a485be78900fbf4cbbfe0e61f6bdb9196","nonce":"553ab29fe2ef4a39c7e00dc7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"f25b20f18f7089a41973ed01ca02cd440dc814ab34455e83372a03ad367a127634ded8314b7ab122f98c5074ff","nonce":"553ab29fe2ef4a39c7e00dc4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"8ce2566c3510ffb0523fb278599bd218081cec34da60c177ab76dfae32668b4e404af07276231916fa39586283","nonce":"553ab29fe2ef4a39c7e00dc5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"7e6366e2569cee15ede9a7d4e9a8ff201211e38382ea026f33ceaafe6bafe6607d4fc1f6ffc25b4536fe85ca20","nonce":"553ab29fe2ef4a39c7e00dda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"5268c34ae1e600835e3879621e9b17150b3030fb5a65e3718c4e150144fe3b9e151399c84d87fb492889f181cb","nonce":"553ab29fe2ef4a39c7e00ddb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"d8123d202f73534b80619acdb26a57ef894de634f7e8c6fc411a1047883c7ace49ee80ab299462a88227a574ee","nonce":"553ab29fe2ef4a39c7e00dd8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"328c97f5ebb5772e4230cda0866ca7f2821da6c0d71946f3a1634155fbfc4ed5437790d32679f1d6acd6fb3ac3","nonce":"553ab29fe2ef4a39c7e00dd9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"1dd5062b556f727dd42431834f9143d48fc6b8f85f097da926c86c4e58c2f0077a50647fb5608ad83ea995e349","nonce":"553ab29fe2ef4a39c7e00dde","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"1f818cc08bab9d5676845582c4f7801dd6e95ee1f78af6b6b3c3f33195896ca0a9abaf3340f5fb1d80957c1041","nonce":"553ab29fe2ef4a39c7e00ddf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"58c6fc6eea3d5c5bd785236e1488778fc57c8be9bb7dce80adfa9a2bea46285e284cf00fa4a9e5f355620ec609","nonce":"553ab29fe2ef4a39c7e00ddc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"d8601bf5820bdd1e7808954d343cc563af164f36f36e277f3a4e3f8e1436e3aeeb27ab1005e7009fb00488109a","nonce":"553ab29fe2ef4a39c7e00ddd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"ec2b5564785893a6e7028c1ac44018dc5dc29ad16cda204026c399aa47f242af3adc4c81e6c2bbd027e65f5464","nonce":"553ab29fe2ef4a39c7e00dd2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"746ed417dc07a3f14f7851bdf2d6fdae5fa4d44b417cc53f42ebdbdcb1925d85bd02116fa4f00072e680abf1e2","nonce":"553ab29fe2ef4a39c7e00dd3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"52622b8df3d45425678d7a77940a2a4386125ca9e62c3fbe055658923665b6df1fbe7220cb9500bebf424efd47","nonce":"553ab29fe2ef4a39c7e00dd0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"7c17e942db0d4ef9cc1d359d11cbebbe543d836395ec5250f6d2cf1610fb0a08a09af300a05374b3b02a6ed19f","nonce":"553ab29fe2ef4a39c7e00dd1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"1941d18ca585d41f08239b250448c8a1b1db3984a32fa0cf18803aeae6b4bc598f4f7124a7e6ed10f7ae4bc90e","nonce":"553ab29fe2ef4a39c7e00dd6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"20a18fb379310efb07f728d2b418a87e89ead9af6981718d0c3f9f0fd6726e453743b2c84480e226b40042d3c2","nonce":"553ab29fe2ef4a39c7e00dd7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"f7c061c67cc151de0d9bfb43a4928e0262089247185f4cfe7a4ca47b288ec1b31818b0a0fe646261135ed2cd7f","nonce":"553ab29fe2ef4a39c7e00dd4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"7fab4739432aa4193d4a7951b7dedd06f5e222bb799ce6c7994d627b0d9ddac15c1ba5128bac113f0a5cc09df5","nonce":"553ab29fe2ef4a39c7e00dd5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"19831d2099e62458f69abf2bf45d75a23fe6412ccb2dfef3df482db7f68bc6d862c7794798b8f71114b8da043a","nonce":"553ab29fe2ef4a39c7e00c2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"3faae3a2bb14b7ed123cf8254856b32db8c40aea4d59e85de0160aeb1e7fa5c9"},{"exporter_context":"00","L":32,"exported_value":"d78f30a8f5997692b0ee862fc392ab0d452b93fd1f8a67be68447df91217ae87"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"0f0a3f43cd09b41f63a997a94b1b64dfb318023ea01973ea6113b0c6b85d1ba6"}]},{"mode":3,"kem_id":33,"kdf_id":3,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"3b0c15b9a7e3d84f7092189d6725752c667d477f24309296070673b388cd27e6ce3c8304e184914e05804a3dab3f5904b4b39114c3010a35","ikmS":"bf121d9dee22bdf323412646ebc129ee6c52d32c35638d0386187225babfa1e81881ea37b29b3461853faed26b9fa171eb41d8e1a093e7c6","ikmE":"ec37feab6f634b2770c94c3d765078ff7ef45d08020571d49259bdc53fd4772da7c924c117753d4d5c4f953982204cd9cd391e9071158efc","skRm":"ebd172589aba1372a29a91ace9e8cde2d488e2217b4a2b52a939830bf2b353ed06a8b3a56450c123416ab21cff3cb6af9a3e8e3d14611c93","skSm":"4ee10a7dae0a2a5954641545911d7f5fcc21b7ed5fc8805b98e3fc56aa917b78544a7d17c602c3482911d1918c45089c2985f17674e4dac9","skEm":"40d25a1331fb37e05f46876a0e632011d861a1f7c6da7e59cb76b69cb2127f195c128d279e5e7a56a6a367f911517303cc38c9d3ee35f361","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"1f07c96aabb3efb7e0d6d7e094cef73344e763ceb5b0c6c61f38a092b454b7d36541117063353c037913c4d0abe8cd0bd971f8b7e73049de","pkSm":"e4b07477255293ce28fbb786d9b957c2946654c442b3b488e5cafdc3f3b6b24f9fce3460f432c25f98baebe05687bd2b3b1f88cb871c4d4a","pkEm":"5accffb1075a7d87124e6a5c98bb3985db198b6a49cad1a084f06d44d45cf9d0e58f9dfab6665bb3420434fa1bd2947896e361c141035993","enc":"5accffb1075a7d87124e6a5c98bb3985db198b6a49cad1a084f06d44d45cf9d0e58f9dfab6665bb3420434fa1bd2947896e361c141035993","shared_secret":"8ebb4c5bf98346dd4ebdf6a4a815dbaebd6941314ba590c3b296181f0ffc15534e9e715a2d91a67a92292bf2198b5c984d6edf1b5f4888e750598accfed7dee1","key_schedule_context":"0325a22652318d3203b17a5dfe9a97fe6ca95fbe1bc17e0b9e19de28ab3294f256dc1c176ee71c44073a5dc3a585f607e7b1950e6924d36128e509650a0bb8ceb2817d22761b0e30bbcdab3759c3f6eb30117e5901b4813c6a7f4a98cd855f07b790aea87cfe90b91c465c22904d4128111352d6be737eaa757a0e2a1834173707","secret":"41ee822146e3b8d61f0b8ec585fd768034f8d2a232011390489607371e22f2e0a800be197a78701d6d781c76bf65af29bff5f2c8681e0784d45886180a0b0bc6","key":"56cb3f060ee87f511bee202a318bd127f692ec24cd0d1b312264e01ac218a1da","base_nonce":"b704a02f75480a85a6af9261","exporter_secret":"7bebc049bf45027b4efb3b435aa91c7d50e1a6645f49185760c6c4c764870b5ef9a9320b7ea1957dac29678cedc4209f96bf1da5290c62f59594d280dce1e8c6","encryptions":[{"aad":"436f756e742d30","ciphertext":"5622f837148f021a50facb2e975582e36d9df555887f878e64dbb68c6032decc1b9f1b30926270ec3c44813c3d","nonce":"b704a02f75480a85a6af9261","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"8d25d557b9713da5568d8630787b92705858c6d41b5399811194aebe114bcc853dedbbf425b601f4d1d2d14c66","nonce":"b704a02f75480a85a6af9260","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"970c728d49cb59ea0386c99a06492649a2ef3bbad46d1ec62a06431e4072565efe517cee20f3d0bd782db22780","nonce":"b704a02f75480a85a6af9263","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"5fb5e3f7c32aa0c182ec447caf08a626657e8424cd6bf47a007b387d09ab4d4c7e511306b633b477b5ff86bd79","nonce":"b704a02f75480a85a6af9262","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"4bc0e440547b067a780daa62c5d7c8ca1efa1c62ec538b1c02c08447890110c279f3db4af4897cf65a690c152d","nonce":"b704a02f75480a85a6af9265","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"dfb20b569141cdc5e6f97cd7deb6622fee4c31af13ab73ebabcdb74c312a13ab238a07a78ad0fc0a6dd7eb9b7a","nonce":"b704a02f75480a85a6af9264","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"567f84d96026c6fc5459ae29f2de6ac07846665b24e4b7f3140c462af9453c80091b1092c3c8284c8302ca096f","nonce":"b704a02f75480a85a6af9267","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"c983cf58db2d444a98e4edaa400e09696ef2459b19dc7f05c4abe436be166eafbabb2d97130b6d80ef122a62d5","nonce":"b704a02f75480a85a6af9266","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"8576f4d52a41d269ff1ab9eb18ab3ccb4784f782a639e3ef3dfad10ea7ed9bf922de2a971ffd5826c848946b22","nonce":"b704a02f75480a85a6af9269","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"e30f8098df3cc3550b9422dc6fc5ec0733fc474bfaf96d9509605ea06db0a6c4a17473b19d19a89cb3cd21e98b","nonce":"b704a02f75480a85a6af9268","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"81b9cd05989843ff6a0ce9a7075d031af5d8f36c2c0bfd6070787c1253e926c968b81dbec83c95d485ebfacd02","nonce":"b704a02f75480a85a6af926b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"308b3b194a6bfe71c3109a3522416b5a9cb13d411c49071b1d27d2d3ae0e8b6f34dfbdd042998438176a048343","nonce":"b704a02f75480a85a6af926a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"e9b073ea6a61309e1f1cddf6dd827c20fdeda44ce694f3a7f3580783af8d20269cc51eeafb3ba114a19c429dc7","nonce":"b704a02f75480a85a6af926d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"7919508b2ae8433aab169f0474960157e4165ce2957d3f69cf4f5f48969fd340a6ab2ed279dc2e4440b98e8e72","nonce":"b704a02f75480a85a6af926c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"13d643b783b401f8c724a468b980b2cdf47e725a5d24cb08a2e98d767e85042b9c420845bd65f5501f55ff620b","nonce":"b704a02f75480a85a6af926f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"5c8082af92e2d271fbac5bcf4e0ad94786018e41deeb6556133872f04dcbe2890255d5c7f3e78c147fcfb047d0","nonce":"b704a02f75480a85a6af926e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"0daa2edd6798d9b74f298969152c2ddcc0cf39b948da716119e0d5c2b858f911bab87b69d99cf48e2cabb68dad","nonce":"b704a02f75480a85a6af9271","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"0ea8afdb4cb4b2e026d665a6a25818e2153f9859490e3e7397bc0d0d3f08c68f6567d412d56c18fe530070cf28","nonce":"b704a02f75480a85a6af9270","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"c8b4f579337eee47da969f5f80bf7b20aa86c39ea429c40a37e356fdd6bf9ae8ac14d71c26435ac6f57572af3e","nonce":"b704a02f75480a85a6af9273","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"b1e01572f6b832523c203ecca0a90d0a917a965da786fab93be40e02a140499086dff1b79b2727e237ceba3a19","nonce":"b704a02f75480a85a6af9272","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"4a59ed6f25481fd69034da4c183b8950a41fe5db3708b7a9d7ffb5dd9fff30f31f5dbb4c4f6383fb7c4d1c27e9","nonce":"b704a02f75480a85a6af9275","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"b12e633ebaee69efe3c6abd17acbd1d87d63174e55223c49a2e31f667ef10bc6cacad059e7ed5d88fa88e5c148","nonce":"b704a02f75480a85a6af9274","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"cc0e0b4a6a639bd53a8cf51dd552ab909dc20d11e2ff827be1a1c291b90fb6c06e5ae3d20464d5df0861849fe9","nonce":"b704a02f75480a85a6af9277","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"591cc42abf37de9a53d2b717a79c08e331db8245f5a4fb420c7f1b846fd8020013175834e44fc14069e9347cd0","nonce":"b704a02f75480a85a6af9276","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"d857ae8ea25c0f0313740673c764558e13e3055944771598fa69b60a6334e217eacd15954ec60a6fb8f1978e03","nonce":"b704a02f75480a85a6af9279","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"0b766aef7f1c1ee2b28fd6664a52eace7ed9633b837a940c167df1cb4f9f3c4a707ef22b404c124b5fb7e9d615","nonce":"b704a02f75480a85a6af9278","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"55f901c05a3ef103be245469a928b18e075ef5ab4f0742b2cd649ea00deb2e5d2ecba63868c42be69315ff4600","nonce":"b704a02f75480a85a6af927b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"352e39fdfe3aa531650d3afd0b90abe2a469a8cdc8a8b7452fee3bb71a0f4f0046dcf3b6546538be2be06a4140","nonce":"b704a02f75480a85a6af927a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"2065e6445880f56b67a4e86f49c42fd15314bc1c3b8a6bcf3d520cc531470e9736ac93978bdf60bb19075e0298","nonce":"b704a02f75480a85a6af927d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"af9c65f670d998de764fdf15a601a05e9f0dc9d8a03e2cfb3f3bc206b78d386137e67ed69e66d8e4b4d6c2cc29","nonce":"b704a02f75480a85a6af927c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"325f467e5140f4a5c20fa34e368d6d16ff0bfa2dbea265ae099533d696fc225a9bbec65230347b0dbc9be5f7bc","nonce":"b704a02f75480a85a6af927f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"4379d7ce143097f186abf2bbaaba5f622fe95fb5f6f6f76ee546e056c3caae303846962fc77746a5d73625f4cb","nonce":"b704a02f75480a85a6af927e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"9977f35cd3670e447202e85f59191452b412941a45c2d35062dab0b11e199e9fc790a550b1373be657a77805cc","nonce":"b704a02f75480a85a6af9241","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"3958aef79b7b030fab45b72a1a41fe498106d131fe3499b28dd607a5b096dc6ef1f3b1e4dd7d82dd07990a1a37","nonce":"b704a02f75480a85a6af9240","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"8e902760319fc8f87bb65b8951982aa6e20bbcafec13fb921b674a3879e8acfeabe44246b68c9be36a4b280cac","nonce":"b704a02f75480a85a6af9243","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"58fdedd5f76c32e34e39e3cb6c8e5fabb1c494976651aa25d9b2d841e7acbb9c5fc4f60737f2668c438ccefd7c","nonce":"b704a02f75480a85a6af9242","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"a2046fdad9f7723deb39c8b4af22cf1fd57a590d7ea08e467dfaf7b19ab8e2315fd83c8a16a201792eb6e1a925","nonce":"b704a02f75480a85a6af9245","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"5cd91ddd2931f0b46525c09b96b078cf5fa05841ece4ad76b841e70563b08cead9d71deda466255b099511a8bf","nonce":"b704a02f75480a85a6af9244","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"20d84697662b7bb1ad5a844e12477dfd7ed38d38de40d0af1df7462293489f8e58dfae89cf16ac0d5507e5660e","nonce":"b704a02f75480a85a6af9247","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"f03e554bea2e712b3b32dbcedd34aff6a5719dca4e4a040f7510290c62e993861e157ed867ee015523b9489f11","nonce":"b704a02f75480a85a6af9246","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"de6fde8b74f9bce4aa0bf524019be13f99c9f0526b19876037a595f1d0f91b85d79bba6fb88ec9c925c0c91c3b","nonce":"b704a02f75480a85a6af9249","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"8eeb3e0f7d6f7b43504eebf511e0878a57fd782d982270dc2d3ba6594f874974941e64442a2f7d9c3822ece384","nonce":"b704a02f75480a85a6af9248","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"5a24e08e66eae39dcc371976179580d80acce4bb1c47b9e0b5e332d1699063e23ef15dea64b1a1baf40b057062","nonce":"b704a02f75480a85a6af924b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"6b97243ffa1490ef4b4be7903386c06e371a4b4d854ad3ab16bb7ba8350727523a212a2df26ef541e6f5364456","nonce":"b704a02f75480a85a6af924a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"7f173ec63f0535081114449974529ee3f2833bef99dd44ab46ce12b6196aeb51ce218facd3ae0fe9e4f78404db","nonce":"b704a02f75480a85a6af924d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"de16cffc507f0eb3f0fcbb5d3df9725b1c1ad8a97cd885ad985ae25f22207cf1a1c243158f89045c499612a1af","nonce":"b704a02f75480a85a6af924c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"cfba14c4c21d744c38ac44f9f3a816368a1680229ff20e7b94b2fc4b00baf8a9b66de0def34680fa62abe97789","nonce":"b704a02f75480a85a6af924f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"c5789f6c0706f392cf58793546e03e0d6fd3d291f55684e397f659e5df8115410b424f429fbbf8f4aec70a8066","nonce":"b704a02f75480a85a6af924e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"758f77445a57faa7ef11f157f47bab7aec88284c25471cc3cf2c446362a34277235f78da9eaeebf1c5abc5a284","nonce":"b704a02f75480a85a6af9251","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"0cf3007c6959471d664d09099893552508d7f0841fa269294077d10412b48ca95788c1c6198d8cf70a24185b52","nonce":"b704a02f75480a85a6af9250","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"0e581dfac99f184b4331938aaffed5a8159da90f02938d18ce7097fcb3ddf9eafa3af62a67f47734bb390c14fe","nonce":"b704a02f75480a85a6af9253","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"82e9e7f5516664612415fd79a1f67f6370e2893310584d55d4461ebbd74eef85afa2c1e68151a670615cf46f73","nonce":"b704a02f75480a85a6af9252","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"c715d12e1c674c41de039e5db6ba15423896c2131b428d6576ffee3d03fa774df51ab24f4362eb5223bfbf8acb","nonce":"b704a02f75480a85a6af9255","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"dee39fa706533327dda21301446d23b3b63fba23442a538f8dbc0ba2c621e6318f0e7007e3d668547f550a9ab5","nonce":"b704a02f75480a85a6af9254","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"068ce3f8b9ec260ee36732544b20e2c0993d5024b71f028d27e361e845d303d7accf4654b3cf5f8c19cee1652c","nonce":"b704a02f75480a85a6af9257","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"f3381d225a7823cd0ac94e1f595a132c307d20c0f0218a9d2cc151d66258b121b19ac96e0dda95403bfd2b351b","nonce":"b704a02f75480a85a6af9256","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"faf8f7dc4b1ab4a9385c85f56fe5cd74009b63af67b6c864ffcdb6a420002b0a21a4b90fa4ce48d682994b26dc","nonce":"b704a02f75480a85a6af9259","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"4ebf6e6b2fbd021a2c64c9730a667e575c0f20fbe3def84dfb0ff98fdc1fb72765d7ffff2c36ed3801a1c2b9f7","nonce":"b704a02f75480a85a6af9258","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"a304047c3de8c2f35b800a6fe149787be51092e2a7ac1976b940aae8457639da51adccf98b546d8ebcbb1cd247","nonce":"b704a02f75480a85a6af925b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"e6d1bc4fa08ee02558f78cddea85fb670b351b6716d46ce32fe5492e807934111a632547925eda0c1bdbb88d7a","nonce":"b704a02f75480a85a6af925a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"9ed8cb1e54c6c48b660a0443f8f90d8f6f3d2b99f03911cf61dbf62ecd19c19a19db600e9258e146456357cff2","nonce":"b704a02f75480a85a6af925d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"c1978cdf326e813cebc941948790a67cd4a6b7a9013921806ef4d05a6be6ab43a72ab823587104b5b185a7ff65","nonce":"b704a02f75480a85a6af925c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"200401f5c6c853bf2f7d916b3ee39dfa2450eb43233ea9c12dcb005db9b343c31fedb3e1a66f27c1463e4df120","nonce":"b704a02f75480a85a6af925f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"198104351187194696cc4d540075af8f45c2ebbc0b6ed08896187607c54d8ea9f9228464837d414716633f470a","nonce":"b704a02f75480a85a6af925e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"76af64d17ca2b90b5dea5281fdc3f77f39a5bb7ddf38f7f797785956dc6dc765dee833f4f9839666d3225e8727","nonce":"b704a02f75480a85a6af9221","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"29ce52e470dd372d4616cca38d1a07f8dc0909a588e4ccedae2a11f2e84c74a7e93915a182675ed014ed27411c","nonce":"b704a02f75480a85a6af9220","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"8804aa5fb5eaea9ec471867d2c2640a1994d2397f1003a2537dab32a789fbe612539e32c4124c9e638d6f5d65f","nonce":"b704a02f75480a85a6af9223","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"60cb15cdfe0359e62add90795fa05f128f87de52f92086e2d4b01294a7676d71c23bd80ed526d84a6cc4984403","nonce":"b704a02f75480a85a6af9222","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"07322bd38e00351ab2884de27d4751f8a1bba96b9c3987c4fc069d9a24ffe87736eae2af3dc301527b6899faa3","nonce":"b704a02f75480a85a6af9225","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"577cfe0dbd4547e8cd2ec502cd96d4977e9999bf834f2607f79b0d9a4984a2394a8ec7aafec0a871c8ce8d2d24","nonce":"b704a02f75480a85a6af9224","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"87fc4c94e1a5dd9568c5c3e5b4868b4ffe774d37505f89ebd0c39c2c3a5b3304a69148aa9e349b1cc65a1a60f1","nonce":"b704a02f75480a85a6af9227","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"e31eeb56cf07407ced80c86cee58fe2d37cf493a3ba1a14d0938fbc8f6807c7908aadc4fe61cb38c4880294ae8","nonce":"b704a02f75480a85a6af9226","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"70ff2eb442d11f398a581b38145119a93d4213d7638d13833fa487a3968742119e635077fcba77803999caeb8d","nonce":"b704a02f75480a85a6af9229","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"5f108ebcc67a1545e277f350010efce229456ad4567392dd15bd251bf6573307abfddc20420cc67b2fe8add36a","nonce":"b704a02f75480a85a6af9228","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"f85ad634ebe10536f9fad4af3e51a5854a0e590a57bc236bd157920548f3b4470d269624d937de7434c8502efc","nonce":"b704a02f75480a85a6af922b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"ffda1b713f4ceb7a7e741bc0c0167f0bf5c39eeab251a888f0ac685c77b2450049a262a6b4a6af497c364e89dd","nonce":"b704a02f75480a85a6af922a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"bf673c26526986ebb64290146188f77c846d0f8b90fcb8e7411d31bac97e270e6e499059144cac73c220adac04","nonce":"b704a02f75480a85a6af922d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"af2100273e751120743bf79af395709ed1506aae8b415c4f3db56b72eeba028a8dcfbb132a7b8e2a7b6918c8fd","nonce":"b704a02f75480a85a6af922c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"ea04c9b281e3f84acfbe1f3c47d1e2abb38773be36eaa87dbbc1107a3664bf816ebcbe526ce382f5619d8da80b","nonce":"b704a02f75480a85a6af922f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"100f2799c6e8213f38cb167ee0885e8b8655dd8f5afc40705797c4fb58fc068b18add0de2bc64759f1f55a3a25","nonce":"b704a02f75480a85a6af922e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"902f195812a4b78e53f31285e504a7103ee170508b3bca7fef8a742892a03d29746ca50ffedd5fc12ea720388d","nonce":"b704a02f75480a85a6af9231","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"d96c92ca2af67e1b13113d4186cb6aa4515a1691222019f1cefe980b87f0fa09eae45f72b81c4b463d6c01b1eb","nonce":"b704a02f75480a85a6af9230","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"7d3e6c475741c4e1ef4a2be817554f3168abf7bc2eda6aaee9b35f1eeead0589b871313847f34abe85d208038a","nonce":"b704a02f75480a85a6af9233","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"5de5101a856541680740da51d410fe4335488eba41ccec3913c71727ede8d48a1f249cda2b1eb6f37434f5c1db","nonce":"b704a02f75480a85a6af9232","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"1361059be7121b567954edbac353ade32d9c03866edea99d3200644de5c2b57921b5aeb3907e6df53d6e8f24d9","nonce":"b704a02f75480a85a6af9235","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"1203b5af5129944b24a7cafbe4ff9eea6f58621aa2639cbb058d3297af45548ea4a3e4883e7c92d8ba21db2163","nonce":"b704a02f75480a85a6af9234","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"0dd721271fa76962faf6fcffa3957546913160f806c993819bf68bd7b9bc4e2d6212c9a1a1318ab19506715ee7","nonce":"b704a02f75480a85a6af9237","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"20d9dd87461514e3acbd0f5000b3fcaa1ce3542076ff00885b7e93719e9dcd6b2e29e1cadc9d2af4c04eca638a","nonce":"b704a02f75480a85a6af9236","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"1aa7faf9a2e1ca221a3ee187a65b3cf37b312c221e26a76492be29ecaa77df7da8c2d74c614670c65a46495cfc","nonce":"b704a02f75480a85a6af9239","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"4a51f52b02fb8167e7911d2d899f47b91c6f430f043d08983815c9c845785dc94d64fe3e2c605b126b5b4b6407","nonce":"b704a02f75480a85a6af9238","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"361ef34045df5ba526360ee0edcea66d15c6c198e165f4de95ead05da91f029b488ccdca3a08806a57a6d28070","nonce":"b704a02f75480a85a6af923b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"897e642fab874d930b6085e4a1961ac71264101679a4ed03fcb22856110e9881bd9d1169bf818786c73dc8d455","nonce":"b704a02f75480a85a6af923a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"a7a2ef478198d30dbf166ca1d7341ef7d40a0bb636143d0276b61cc0aab66617888a6fb94d8df682118f6059d7","nonce":"b704a02f75480a85a6af923d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"babdae4f91af59c28f434a36bb7560f2bd08910c1a41751a9e37b5c9f182063f1c6acea13db9100c3e23d51f8c","nonce":"b704a02f75480a85a6af923c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"94331598d6d261daec91673a4b3b5d0e25ff4dc856c935d62ff258e777bbd063458a78d7b5fc65fa6de5de4ace","nonce":"b704a02f75480a85a6af923f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"7ab4b782d391921501d1450552c2b2ddb925be36a9993ad35a71fb6c62e59f351db3b4ca7f5fcab16dcc796ecc","nonce":"b704a02f75480a85a6af923e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"b0174e7b3fa8cb734debf4f3f1743ca30d8913fd7efb74ae11679e73bf7794e9b9dd3a43e01da9667b6e658dcb","nonce":"b704a02f75480a85a6af9201","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"ff19258c3b6f8a5aaac9282d49960ea67512bc1eba5b958186e77b454e83032e67a3fe8a8ce6ab10aecba2f48a","nonce":"b704a02f75480a85a6af9200","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"548d432959f4e413e7142b778a0f675085cb386bc9b1905656ca776137f4847e466ed18f6ab3f14013f399884a","nonce":"b704a02f75480a85a6af9203","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"43ab7a2378e850496a590aa67275148a594ec3d60b759781e5277aa991560b6fb4f483ab9876f4f0cc01e7b476","nonce":"b704a02f75480a85a6af9202","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"909ece564066225fa4211020018417afb7c1f9d3a84ec24ff8f3a0402c17f784cb400f154f890dbf6f701b4344","nonce":"b704a02f75480a85a6af9205","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"e577a070e45ac8e1bf45fee5b14c1c7e928e6d19fcce419f5aab57aecf40a47547faa1a870ff9d144076d29310","nonce":"b704a02f75480a85a6af9204","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"a039ca0579818568714604c5962d9f61c5a31d500001ca6774364e28ecd4611a01e351030d600cdf9626a7fdd3","nonce":"b704a02f75480a85a6af9207","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"12da2f7e7e6e23da201228d0cc9bf588056f4bc9ae5a860180381533756cd9b73f31a55f1c760b6d6ad8de604c","nonce":"b704a02f75480a85a6af9206","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"e7cc91be79d06661cee4baccf23601d4f8eeaaefa4df44151ba277d282b02a901c490e82bbcc7d041ff1eaccc4","nonce":"b704a02f75480a85a6af9209","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"e16b545de1757c58cbececabed8b20764c0f21d07f95304448ac9d2e123a39abbdf1c2e411bb5fc38338c3c0ac","nonce":"b704a02f75480a85a6af9208","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"c25555e26a1d94fa485c8ad5e53963fb41e7b0b17d8fabde378d15e2127d25c62ea8a0f3a12348a28d44ca1ae1","nonce":"b704a02f75480a85a6af920b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"63d5c985be282839a6416f031bcbe8360e8f04950576520d03714c4df4adf687aa8fae238c865a538c609ef239","nonce":"b704a02f75480a85a6af920a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"f2095cf1c1e1918b41b563d37ab39141131c745fcd24ba713d9469324f7d013b96a0c11cc561df2c8bfb318653","nonce":"b704a02f75480a85a6af920d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"30618544e53f35bb2f563e8a3e01273d44e38769f4d84e555806126e2f92f6d5af0cd221adcbe9dbde65f0b597","nonce":"b704a02f75480a85a6af920c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"a6356c6182392c131e51034780b112d81c0979c93894791a22b04db7c984123da798e77bf9c6de6b3c5c3bb200","nonce":"b704a02f75480a85a6af920f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"7f0e3e5278c569ef43234a66362761c47a182dfcf00ae8e18d9c03d182bf4a18224b98c5e7de521dc7b75f3ba4","nonce":"b704a02f75480a85a6af920e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"4286ce4cbfb33751777f134a73209fb0e0b061faa09d3e5fd7ec8d9795af0182841db3f5334d08695d8ebcc382","nonce":"b704a02f75480a85a6af9211","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"ee62ee45fb34c1c5377a714e29ab9c5960cf88c2db1034207857a23bfb1575a3127869c022843e9cd8df2636ad","nonce":"b704a02f75480a85a6af9210","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"12516d2ef49a2d136f5a566193a9093b921bd73385d072c9deec74f87bd14d5dec865fb1945438e996dcaca8fc","nonce":"b704a02f75480a85a6af9213","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"122523eabfa6d7c361e7049d3e6d07a51ca258094d1204e68de356a07f973b66c6f085f09cdb48c62f4b3ee981","nonce":"b704a02f75480a85a6af9212","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"83c4eb2d4f7f9b75d7683db2f1dcd5444a244ad91d2b13712fb7f696384f5539c672389ce3c36b7bed75840bf8","nonce":"b704a02f75480a85a6af9215","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"482362e14fc0804dc2dc720007566ddae384072c2fb43c45df3d1245436737d5024e7c07ff619a4c32a7f40a6c","nonce":"b704a02f75480a85a6af9214","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"c265621ef67ede55ddb3c566f63f7e0c4b6d224dd99d4fec769e2049a1a89566cecb54f98729c0f7c644e419eb","nonce":"b704a02f75480a85a6af9217","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"0738daaf07de6ce6d88654ac24c51525a2fe84e03a86fcc459cf3daf6b3451cbaa66f8de79cb71b60d3dd4b91b","nonce":"b704a02f75480a85a6af9216","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"c4448c7702badc8e78b3bc3292686a344beafae6ae3bd0bcc6f737ca4d8583110c20133eec8a6af0ceb084203e","nonce":"b704a02f75480a85a6af9219","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"ff03740c0c4eae39f2259c9f17a9a23689390335c40c033afd3280a4ddfe88b27ce69a1e6b80dc0708f7371ec9","nonce":"b704a02f75480a85a6af9218","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"c0605c99ea2af852b9d68c0ddb303d07157b8f18257d5db903f50b53acb79b049d804121f1a80ba9da04b128d2","nonce":"b704a02f75480a85a6af921b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"242616d199117efa9eadf5a125a7ef946f6585e6b31c7034f7b4b996ae2a6715ab5a996bf1d929a1244d068c6e","nonce":"b704a02f75480a85a6af921a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"29154ab2709bcb1c776946d8b2ba8ba019153db596f89ed5740f4ccda0d56697b1b90be169af9a16113e0c7e45","nonce":"b704a02f75480a85a6af921d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"7ae8a000c91ce51d179efc90de2e2acae4b8e8f1f394ad97af0d502b00023fba25321a367db4b2559407c10923","nonce":"b704a02f75480a85a6af921c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"f98486aaf1cb9943a8cffe6e608b363af956920a41f7d0dba5c925c3f96db41b0a6c1e24a49b2cce9532e93073","nonce":"b704a02f75480a85a6af921f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"4fcbfea4af5142485e7207ede4b3ce52692d5532aaec3d7de22ee6166fac4ddb83e66b333ecd946408a1db2ba4","nonce":"b704a02f75480a85a6af921e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"a9047df1f1d6bf6fbfe743eecd3c16a4f7f626c079b2015e8659a2d6bc6a7615adb2fc253ec2191224b2dbb166","nonce":"b704a02f75480a85a6af92e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"16bc204d76acccee149985723231d1d6899b70f2e37e062a9b3b251dad75f11059a6e6b89a116978bfd5f82fe9","nonce":"b704a02f75480a85a6af92e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"65bf991a0a46a66ec9562ac60c9c766ace8355e1701c43c1115eb497fedb86e4491a5b282caffaea34a37e6867","nonce":"b704a02f75480a85a6af92e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"360f9ca937d1702053752e4ffdaca5fafd0f8d868cc0d11a37ea629fe34f573ae29bbfc7792436dd62005eeca2","nonce":"b704a02f75480a85a6af92e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"f2097136db48d31e0a516ca215bfd9283b0966b48ef5909776fcbc6bdc79ea3e5e7da4b5f057d2049a9f637405","nonce":"b704a02f75480a85a6af92e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"7feef813ffa390a1129b4159820817bf59187ddd750fa4be2c688eecd6620be00742f456cfcbc2ef9ee71d8d5c","nonce":"b704a02f75480a85a6af92e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"d8f19c2f81b5033d521e9a3d8227aa89aff540dbdff1f93e3e16e76b6a8da22baadb0b158713ce8b7b1b72e6d8","nonce":"b704a02f75480a85a6af92e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"451bd620fd6ed09a24446af631c35292a3d71d94efdc292c4c19e2a58fea49af8670202e6dc0ac6b2c31d8180a","nonce":"b704a02f75480a85a6af92e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"556b2789e24a34187d027aa16af8332d86c1cac6166a193cb70928eafbb161a21eb2c456541c6cab4fffb759a0","nonce":"b704a02f75480a85a6af92e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"c1d82c6246f5f798fb79848e91ef82e321222d2f138715e38e3fca73e7e2a8ce415081bc08a8f4236d61dd3650","nonce":"b704a02f75480a85a6af92e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"1aa7ebdfc71660288e50e5d39da07093a0e16dd069b5d0ec425cc9303c6489b7dbb519bb08454f195700579e9e","nonce":"b704a02f75480a85a6af92eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"5bf0e352a6764fbbf918e801b5f696940cc4d77dafd8c04364d3c97189b4d0a8000183fc6d6f1cdc1f1cfd9384","nonce":"b704a02f75480a85a6af92ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"c0d906bf28689b931e8e8154a33e93b8be4bd00ee6b663849072de371272866963fed7d6917fa8cb15979e62b6","nonce":"b704a02f75480a85a6af92ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"c228e66a99493f0f57838c0abfbe4a31a5add61dcc8417c636575106a88c796c79111b186c30242b1153c8eaa1","nonce":"b704a02f75480a85a6af92ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"be2ef2d57a8eb066988899670328851f24efb65553a385ec2b59c86dd22517717774e5253875e73ae25635507e","nonce":"b704a02f75480a85a6af92ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"646e8234691b544b0a17868ce6543c4be9381fac7726ffd240884f4954890cb1665e1c35e142e4fb6b7040547f","nonce":"b704a02f75480a85a6af92ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"c9abf09fac81f8d6a75f241a90fc7453b9aa2c3ad78cb4659a0d64a2c1139bc1344ea64b72a2448493bdc77283","nonce":"b704a02f75480a85a6af92f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"36768a83960bbe5f2611aa31ded6fe447b03a080f5783763155aa2b665d56af48397b7a22d6e5d4dbadcc53e8b","nonce":"b704a02f75480a85a6af92f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"471d9ec97db2cee5faff84d6a57bc1a6a61c10791106b54b35114bf693db21f5fee95530ef0830bc4277e8ca32","nonce":"b704a02f75480a85a6af92f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"d1a7aefb253b52bf94bb16dcefb5205ed4c589db1b311dfadd167045e76d4b79d19a50c64c9ee3fe576e8e69d2","nonce":"b704a02f75480a85a6af92f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"b9ca212afaeef9f115b74f6c5bf781d7a725e9212b6bcca40d92ae5bb0c90633a4fc5b43a5f2829d6b28fc5887","nonce":"b704a02f75480a85a6af92f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"a5c6b42525fa83b14cc965367a56102cadb3ae0e07760c1b011e9ccd52a3092e77b622d37ee3b6d8a9acbfc963","nonce":"b704a02f75480a85a6af92f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"eb12dbd08bb05754832a32aac808ffb54387f5828dd17e1db7fb5f3cac31827ad317b1dc8e6d2bacf86f7434ab","nonce":"b704a02f75480a85a6af92f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"0da8d09756e4ec439e71f6900f67575b93500d6b8200b528dff026c0a671a985472815e0bc0140fb5d06e2ac46","nonce":"b704a02f75480a85a6af92f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"e096639d9145efc41ade0747d125c08860fd0cb8246ee678a281b0d6e84560f811d2f1e8edb565a7d8f864677b","nonce":"b704a02f75480a85a6af92f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"f6ce7b4789482df20a2ea4d3eff9514f8e365828e0da9b6ab6bbbbc6e550eecfe23fe6954e0bd486e4398d1e68","nonce":"b704a02f75480a85a6af92f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"336e886c7753508bed09dbf9bc18988485ca44adbefe8e619694827fa836b02feb1b2e0b8186d48c116398bd8b","nonce":"b704a02f75480a85a6af92fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"889e3f797695b435e9f4f67eff4bea36daedd68c456a0d3333d22565d1d56ff390d629998fb024b10c3e4f56b0","nonce":"b704a02f75480a85a6af92fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"c6fd8ba2ad8b5971b4b25895be000b6bd5d6de5fc7557c891eecec2ca1114a117225e7066164817b1dee06246b","nonce":"b704a02f75480a85a6af92fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"34142dda2267b8f6cd763d8dd6b3b068cb5401b7bcd575cfbe7508f042a01333896c2d2eefb295e76b2727f550","nonce":"b704a02f75480a85a6af92fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"52bae50729e5e9938f2600a7ac57306ec0bba7f27391ff3baf30cdf809b8911994d9b3530b9b1e780913a8a342","nonce":"b704a02f75480a85a6af92ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"d43997e33cae4e8bfe30532587da3803c9fe46e2c48657c6de0b28ccec10948e6ee3ea0ec5f8226f1450616031","nonce":"b704a02f75480a85a6af92fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"b425cb93a0135f2193766170f3efa51eb304568d308b69a40c733785804148f87f4b56280959ed1c18b7cfefd1","nonce":"b704a02f75480a85a6af92c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"cabef0c3503ef33ef8844049fd2fb31562d2b61d23745306b9c16a951a1dc62b05c83066bea550dda9aaf92786","nonce":"b704a02f75480a85a6af92c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"eb6a9448c1da0147217ed5db4a2079feaa5ff23c3b7c520bd35d68ff67fc2002f3feaa3905c3cccbe2d92dafd6","nonce":"b704a02f75480a85a6af92c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"9f15c5fd18f667d9561e9d7807ee2bb13078c70765dd589765e1c9d8660482e2aa9350b6635289d8e2d6b7fcef","nonce":"b704a02f75480a85a6af92c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"b50a6e438b591382439990e23be50e3d329de0e590b0aba2667e7f627d7bb9582a6e678fec760a060dd9cf2a86","nonce":"b704a02f75480a85a6af92c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"1359997071feb1a6186518ef4d5fea8adc2620019b9f991a1d17c5be59ed4fb064d8b52c6a9f7dbb4750b38ad5","nonce":"b704a02f75480a85a6af92c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"3e569f47f3537639cbb25440551dbc89c91a785980be2c2cee43da399068c33f49d159c4f697cdbc253c6b1cf5","nonce":"b704a02f75480a85a6af92c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"07341ea44d0b70221fa65ae211b02d9e1c4b033e13e3205fc4fdd64dc1252ee899758a56c51dd0c21df8b0f7ea","nonce":"b704a02f75480a85a6af92c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"92537d00b32b6994c53ea2b7876df50bb7c7b251ca150daf56dd02c94ee5ce9f1fe74e43ba8e4c06f2553e44f3","nonce":"b704a02f75480a85a6af92c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"ff3385c46ebd8f1e5c809f9c1f6bb2745e6605aa3baa78d2aa385f4db4180a279db1b0551da9386350b2691f86","nonce":"b704a02f75480a85a6af92c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"4ccc58974633bf4df56af960c2b85810bc22c42103b42fd58771135248774c220454e790db8f4bd39279615d67","nonce":"b704a02f75480a85a6af92cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"44d592c425f5b8af955ce5c093595b0e545f92b6af2552d049b5d421303699d47069af3b40b6fea234ab9d612a","nonce":"b704a02f75480a85a6af92ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"aaf4f97c173e3a172927e1f5ed30633f5cfcc56dae7eee444464509ef08dd0c7a3fbff10b83577013b3d0336c6","nonce":"b704a02f75480a85a6af92cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"e821f21df35325f7e0d09e673f768141ae450d4e0a84978d75ee230ffe8fb8f36b88ef183d5eeb4ca2c8576cb0","nonce":"b704a02f75480a85a6af92cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"a6467f5b370d6479b630fe5ee9f0dee49d27f07f07168d6cea385a32039ba666c6db1f7ef2291a07918c958caf","nonce":"b704a02f75480a85a6af92cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"a86c13d31e3e1b2cb3fef3e8b2fabf2f0e66d21e37f0dd6a00ec9d13872e3ecb0e7726acbd0c496b4a3c67384d","nonce":"b704a02f75480a85a6af92ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"a52420c274026d934b9f0ee302c70c7022aa6c2a638dd4d899b72b41a08de5cfa323090b92008007f0050c6cbf","nonce":"b704a02f75480a85a6af92d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"7bf53b8db35d43dc834d09de82c7a9d6d28de46ed1d04a110b7c62c01b6ea12166085b8a3e6afe4c0b2546eba1","nonce":"b704a02f75480a85a6af92d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"02651cb8315e06b35c03884178d630d1238a67902dfb48c09b3f7f0fba2194f5bb0ac3923c1294186e57f85c2d","nonce":"b704a02f75480a85a6af92d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"8bb3aee25e00d675640f46dc46a43cbbcf9d42500f41f7359653f91e6524cbc6f67a3e26a9c46fe4e92c01e3f5","nonce":"b704a02f75480a85a6af92d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"4e56d48f007cd72c846d8aee957ea4ea31f0c43e20b07f22f7cf39b3f245cdfd84aa093ffe3af87ffd044ab52d","nonce":"b704a02f75480a85a6af92d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"1a1118a64e7c91acdaf3f2c2d7b6bff540a3530fb0d138952be0cb4dcd382117cd9b9166a24fcb21cf2f8be5a9","nonce":"b704a02f75480a85a6af92d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"03cdd531d31e2d6c9d25a760d40c38e04ac154576f731981b2c02631927505e5ee78e6a2bf9407486769e1b068","nonce":"b704a02f75480a85a6af92d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"ef860d0f3c87e1cb3c3221627b1b5c0cea0e6f114c66a3d884fd581b3cd1fac153e96280143a298fcc3adb25b5","nonce":"b704a02f75480a85a6af92d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"8ef59ec62ef53c46d82cfc3fab41517436ecc7800562e4276b8dd17185de8b188d0aa302f06ddc46e10daac744","nonce":"b704a02f75480a85a6af92d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"454e682df8730531e5184398f70a92f4a0f4ed4c7eb27d541cd788dc59eec5ab8317cc89a72b5365591d52815e","nonce":"b704a02f75480a85a6af92d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"757e80552934a8163ce0c7f14c5731e78624fec84587742f6f333e1e4e037581b8793e11708c885ea1c4ca9be2","nonce":"b704a02f75480a85a6af92db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"7779aecdb9407e5c0f5fcf77ac3feb87c38e8cce2dbd3488342fae86cf982643bd22d61728194ec30b674f86dc","nonce":"b704a02f75480a85a6af92da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"b7d6c513b617ce9b89ff4b059ee652220f205441db0100bdfe8dadbe16aab14e75b9edf1a65d2ec9bb20f03628","nonce":"b704a02f75480a85a6af92dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"bb22ca42c1f978c436568ec7d3c56438c06dab97ac57b53ce0659e61311e7893e093ad1eb7182eff04f8e76b51","nonce":"b704a02f75480a85a6af92dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"616dc47ea94318e734de94ff2a97c6658f531fe9225e647638c0b4272eb142259be8bb08c1fba2b2f14ea4967d","nonce":"b704a02f75480a85a6af92df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"a07bfa82e1eae6762bbea0c0d10ba3cebd3c149c9f87d35898ec9bd5bfc765355eaec3b4a6628ec173b2f5f934","nonce":"b704a02f75480a85a6af92de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"3deb384fbe3b2da9ce8b58ab03d7a4608ae849174dcc776efcb492d59154754b3da308777640cc4a062248253e","nonce":"b704a02f75480a85a6af92a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"aba09aee4f10dff393489072555cc2545cc93a96b9c6a03aff61d9506fb28c482823a7e35a0274711eabeb5784","nonce":"b704a02f75480a85a6af92a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"d22e1449073f7ba6465acb9e4964bc37c2148a5296a48a19ce71b878aadc85ae678f96bcbefc7d1612e1244e6e","nonce":"b704a02f75480a85a6af92a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"f16c84ebf6cfb9336840a98b17480a7fc2bcbc325f0d575b5bdfcb6e995964a5c90654da72ff403042de9826ab","nonce":"b704a02f75480a85a6af92a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"97e722fb2cf1f6bc34ffdff7276533162b221a2b9638cac919d5d4abeee683edddf81bfbcc798e5fb39de71845","nonce":"b704a02f75480a85a6af92a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"3992fa104b1fe7495b0a7477b8488aace745ce6ca2aa681798bc664c607d4054c07ee31f52e181e50589707309","nonce":"b704a02f75480a85a6af92a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"20e5b7a703ab52370c4c7393b2e9aabcd9f8274f1d97008db284641450ee63be8048f050cc0f507de5324afb6b","nonce":"b704a02f75480a85a6af92a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"6c675273c32ef1d5de15fbcecbcb8b45a9b1f24a3b91a76e106aad27788472abd323d711b6511eb849bf75b7af","nonce":"b704a02f75480a85a6af92a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"178a0c42c5620891927eaa8f92b202497ce8bad61fae641ef3438e4291437065d774e420c7dbee41b9733235e2","nonce":"b704a02f75480a85a6af92a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"515a2a171b2ab14c9eb06d00d18ee3d6ebc1a91efd4d0b5f8d6caa1df72054992f197c56ffd0d4efef23fddc48","nonce":"b704a02f75480a85a6af92a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"e69932e4804c4093af2bf28b248549b52934c89d5652e95960458c6f5f9c9b20f1d3365ad05fe9156ee318b82a","nonce":"b704a02f75480a85a6af92ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"c2a3e324cbf93273a9af46a240da819f52811b012828607460896c58d0ab36ab13f20ab94342e34b4963a94221","nonce":"b704a02f75480a85a6af92aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"561580e15d8f41d158fe34e79351a6e64d8bec897ca87526c9218cf1065165843a5d7d07101b49801047576013","nonce":"b704a02f75480a85a6af92ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"adb2e6ac9f626fc190241132676bd8b4eb52dc77113d3786865349b12ca6b9096ed9317e8290b4be75af3da53a","nonce":"b704a02f75480a85a6af92ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"39e60d1393f7c186951400a725b6dd063fb114500a384543d620fecca031dc0cab3f47b79d36624520e250b124","nonce":"b704a02f75480a85a6af92af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"1b8a62d241b8fe9776114ec67607736a557a008876296791bd7c457aab4a6521470b9ca4f02d020ec5ecfdfb61","nonce":"b704a02f75480a85a6af92ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"0ae1f6a59326926dbb23b7d7d5567af03d3ca256658ec4ed044556d7d790ed75640d602b924ec521ca54b36b9a","nonce":"b704a02f75480a85a6af92b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"af04fb24486be8a9fbb53b35adf5f71921c7c110845d3f7eed1a41238ef83eec05aea22a4bbef298699cbfc4eb","nonce":"b704a02f75480a85a6af92b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"2e11639ed82340742e448eef7e438ba8726bb6915dd51aceef7bc75ae0c152def688cbdd2ac37713fb31141baf","nonce":"b704a02f75480a85a6af92b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"9cb5f41949dda0c81229ad62fc061fb2f62320b4e6b83aadb215c0c89b43166741e1857288ab0860aa63865757","nonce":"b704a02f75480a85a6af92b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"4f0af7bac63b27273f21569cf95ece59d464797e8a8f427a3b4cdbb87b43aec461b7a30328c86d4f65798fd97c","nonce":"b704a02f75480a85a6af92b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"620d3f12e1815d95acb786663d0cfe9e21c4a4a5212004188c75edfa50789c3497c305ba9db3590d697608d09b","nonce":"b704a02f75480a85a6af92b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"03dfe3adf4a3bcc83bff28a63767a0818e33f54499f84a0beb68093bfe2706886e9facfa9a387ef294fd8338a9","nonce":"b704a02f75480a85a6af92b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"803dad36c0ca5d3ad6762200418987e9f2b98b3c58419e24c50c8a9407116a2f917070f54db65750144d41ff09","nonce":"b704a02f75480a85a6af92b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"ce62916e25e884c883ceafdb852389497b34eae7d581f167c5c28ea1e864ddc6bf782067853b60ec88b5e3a4a6","nonce":"b704a02f75480a85a6af92b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"13dd01c064935e3f9bee09c1d4c786a1bb02e67009e173092b4a4a10b1f3ae6dfece09cc7578599f401ab8bd99","nonce":"b704a02f75480a85a6af92b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"8121109f21d115c689bad3f17ca865520f73d8e833a0bddd842da14143e5cdc9ccaff65c45ef45c3f96829312e","nonce":"b704a02f75480a85a6af92bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"9d743e491770d68776deec7ecc7fdfd43140c25328aea6339bdace0a79e3329b96c18afbd1fccfe09d3b19672c","nonce":"b704a02f75480a85a6af92ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"aabf4ecd2e678035a00c3a8ac956f6f8236fa6c22e13da048def037480d0d40fc91229352883e735b159e5e24a","nonce":"b704a02f75480a85a6af92bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"5e96faaae6cbfa6bb90677f11b136e2b328ef0ee41b289396da68247e31421a826dc3c1011a26929fb35e06ce4","nonce":"b704a02f75480a85a6af92bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"5acf5fd7d6b63a618e1a4c0698b022876d8d9a3347f2a49efb42eac8f20a26907cfb1fa47754145d547d379c51","nonce":"b704a02f75480a85a6af92bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"caef78ab120c8a5669038bfc53f754608838da3e3aba4067a431bee64c1d41a3ab0eacf48f31746e80fdfa4006","nonce":"b704a02f75480a85a6af92be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"448de18ac3c03707072a7e950bec57952d6f32daa8730fd654671bd6818aeeccffa16b05e20e384308a31d2113","nonce":"b704a02f75480a85a6af9281","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"5761970d01941236e7fb12b637a92ed49e26ee804ecf48752e4ba35dd93f16ee1116df10f5b68cfd23fa0bcd5e","nonce":"b704a02f75480a85a6af9280","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"d07e8579b43ac44c0b59eeb1435a9bd1036a98fd47353e8478421d6371036a735f68d1bc4b30c350fc9ae3b2a4","nonce":"b704a02f75480a85a6af9283","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"2d80c722befcca66f8592e93994912ac2900c9ec2c28d1bc5ceec026728b6f7230058f8f6486d9ea9767e32d9a","nonce":"b704a02f75480a85a6af9282","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"d48a96b1c507fb5267bf3d5551d230fba27302fce81a5b275e511765a4c9862a04d87019177116ef3741835539","nonce":"b704a02f75480a85a6af9285","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"5152ebf5c7306993da37128dc7986cce6d0dabd22f00829a52571cc03d7c0937adfa49bf706eef0342b9180d31","nonce":"b704a02f75480a85a6af9284","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"807fcfbf1be754bc0f9ef9730605495cf7ff9205593fbe1bb94976ed4b339bb31849224aaa0661fe536cf3bc51","nonce":"b704a02f75480a85a6af9287","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"a52424f520e72affe6f68f96c94e6be78657c26168cc9772b96d262d491c2e8810a48390fdda97e4012c43e37c","nonce":"b704a02f75480a85a6af9286","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"5a5db425dc4ab10982132c1944e68152085423f433230231899692b275b5b7ce41e2a3bf789c982dd17fe50b82","nonce":"b704a02f75480a85a6af9289","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"94dd1eb1acb5808764f4bccfc129a621ef2b42f92e6c9879316fafefec5083a4d5c7a403feb86ded3e3434bbc7","nonce":"b704a02f75480a85a6af9288","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"7342bf0c8946ee0b1aba0cf9169fc49cafa0f95972cb582324809ff3982ae2761517d2ce58c16a24d2e8cb4630","nonce":"b704a02f75480a85a6af928b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"fae2c54a932c372cb0bd247255708114f2b1d94be4022b42efdc09091086763519e9cbff4f57648f799aae1707","nonce":"b704a02f75480a85a6af928a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"25598071247c69454e0f575fedf24fdb0a02b305712258694491c417972fda00aa7ccb3d8858e195fed8a67546","nonce":"b704a02f75480a85a6af928d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"12f4ec5083a34b84bddff26946a26d8c3d0aef93ccf0cf311654103239879d4cac568f25091fc94a365f702468","nonce":"b704a02f75480a85a6af928c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"0ec5489ea1ade871fa4a6549c8278d56cc786a81072b1d45521143d4acc115bbbaa1500a6b914a469ed2bfab21","nonce":"b704a02f75480a85a6af928f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"b15c8fa6849a872bf4961fea343f8bfca2693dbe8d7b4ee7bffebd6e48248fee7aefe81145532a8ca205bda8c6","nonce":"b704a02f75480a85a6af928e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"5c88746d8e3cfb39e958269709c594f8b3c806bd3e35db848667a82b1f3ec1c2a527477f0154f72076c6cbb202","nonce":"b704a02f75480a85a6af9291","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"3d63518f22744129f7156f5a3ee14f653a22e78dce22cc5a9a8de9883a380151fe2bbb430151667f53f915659d","nonce":"b704a02f75480a85a6af9290","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"a1a3cb6ec3110b5b4b6e7afc15c43dd20da7a8591fe2536c115f37d76ebd4756917ffd179134879324679c9d0b","nonce":"b704a02f75480a85a6af9293","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"e61f05fd52ec3233f4745394dc38398a3cef18c7b685193424365f2217158334d5c5cc6721cb7ecbbd390be09a","nonce":"b704a02f75480a85a6af9292","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"cda5a84e5ebf19f81240dfab36221195e2cc988ecfd5b9d1b8bc43e97facf6830bdc4df865134297374f0e095c","nonce":"b704a02f75480a85a6af9295","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"4bf9d769a84f668573faecb54a661a1dfd3499cc0a3d452468846c0a149bb9a33b5f0e77731abeb3ea4e2a30a2","nonce":"b704a02f75480a85a6af9294","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"5b8ba5d6eec1a72ae181104b12525a2ca0f281e95e85887fd342ebfc9986d5537e10e37af7b2cd0432364c79f3","nonce":"b704a02f75480a85a6af9297","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"0262e4550cbca6513f4fafad201cf95bd137f62849e9198977b2c50db00ce4ae3d0a696dac990396295ab8b8f2","nonce":"b704a02f75480a85a6af9296","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"5d32363705cab32c520441be5252d73fa335d3ff6c2c7ecf631990e3bcb2b35eec207f77fbb58b17722d5df6e2","nonce":"b704a02f75480a85a6af9299","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"b308e5d81d0c61c99b422c3ada8691d603a239e5a9d8b240b956f0f8472902a2706ebd1ba7b179046d49c066b5","nonce":"b704a02f75480a85a6af9298","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"8dea36c18d86f5433605f457b633fc768df5a29029cfc1e827a259f8f5d4d4dafd7573c9494a6cd0942cf40f25","nonce":"b704a02f75480a85a6af929b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"1b52f9450fd6a63afc955400cb510d594462ad6f3afd7a4ed82b66c858fc72610fb92f1533b2f3e1b96e2809c8","nonce":"b704a02f75480a85a6af929a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"22e0ae7bfe8d852c5719d54faad5931d2daddfe22d63f2cc8d2e841f0904c7cca11d6f0ee9550195ca9fb0ac25","nonce":"b704a02f75480a85a6af929d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"72b25199522255954806b65aa325e221806583bbafe97be9314d7f3d7fa47b59cdc50ed2c5e57884aa35f2477f","nonce":"b704a02f75480a85a6af929c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"014732ba586c23b918703ac991319b882748a2048ef3f156a4d8b9e24b0295cbec1c76d7e2cf650496f7ddd23e","nonce":"b704a02f75480a85a6af929f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"4a7c9b5703fd447de692e49a1263328cb7f983257e77fb710ad7d72b3a1f2e8953f526792ad1808e5d3bc0851a","nonce":"b704a02f75480a85a6af929e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"458bd690a3a680cded468408508fba9936e527f625c046b74b9dc8ee50cf61708db6a00f0919e962ecbee14a03","nonce":"b704a02f75480a85a6af9361","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"c583063f010f3260a29621e1df52ca8a1e646e48d29e1826bc3d60ec5165d48b"},{"exporter_context":"00","L":32,"exported_value":"c25b69a48a92165aa31c162d7671d7b08a9e75f9cc819fbf607202bbf8c3c8f5"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"36fec681ee755555a01adcfab08e77e16fceab1e4d5e0ea3dcb50e9f4d53a56b"}]},{"mode":0,"kem_id":33,"kdf_id":3,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"b00dea303b6f238b53958849fa32ec142ed7309f8a0da77ae8aa7326a4b6abab13a7511d28b58f22e544345484221fabbf5930c4fe62fb80","ikmE":"891eec8749d6ffea8175cb7a2450ae63cca1db66017d9378e3d53af813cf172b29f93d9fd7d122a7991d0ff713752cb3236c41b698538d5d","skRm":"743df37e2673b083e31079e7688e141f555c32f6cb1dbf7842e2d12e1929e9671656ae2df4122316567044bf0d4d966e6e716b5a8c5f7011","skEm":"8d61fbcb8af8185d65bb7bda46cbdc76cbda72d852d0c47d729a5524754daeca45117558f89e94f25f12da9e0da8da0c45d5971f1737f10d","pkRm":"7b3381e3fb7a12576bbee20b7b78eeb83a68e6f667f51da4109124a98a50f28c0edd0ba65b45822696b6f090bfb543b6e71460dbc209d9fd","pkEm":"dc663ac316d4133aeaba6bed15eadafee7d8824f9145f782880e4fadeff89d3280c107cac737391c28ccd00b87d0ec68aa144a6ba6e87fc2","enc":"dc663ac316d4133aeaba6bed15eadafee7d8824f9145f782880e4fadeff89d3280c107cac737391c28ccd00b87d0ec68aa144a6ba6e87fc2","shared_secret":"8d7bcf63c1582ffc7af5673fac523c3a06875b718f7bd90ad0f359ee1213fb006bb412bae093737240a98c7f62d396a44b2a62336279bc8caf2fd2573f9a438d","key_schedule_context":"00ee4fca86c518a1057129a790470347c02bd27b4a6e36f17db1186907541583ecca9a8d65aaafed3e87e030dc2227f68cf7ff612167b37f12f245ead4ba4c0afa69461ad54024dd0d2a7440f1cff5f3c5a53e21372d18bf6766592554919ce44969c417418d86d6855c4df20dfc189556f20d520a21ac7fe152ad7899d597fb87","secret":"310b7c5233f46e3951d09288029148aaaa63b2893d9a581b5e1af58bb628a255ffb3f5f5ede0865f810f92a09c9ec4f70d270f2d94ee3a8e627c3cc771f4f393","key":"","base_nonce":"","exporter_secret":"a94028ceb519749f9e3c420eed6dacc4958d645a86039b9b217325fb8dc1fd0043f0fb380de7652a0653a37586d00afebb97705cca6974a4c54932d75963d46a","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"7bce4805badb7ab8931d32a0b3faa2272a1a2f1c879ab0d82442f4621cad6bba"},{"exporter_context":"00","L":32,"exported_value":"6c269c0d4444370e4bfb5d364099db9bc9a97fc25a0dd7cfcc2450bab49b4e7e"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"e59ca3ad4c51ff760a4d02fd582027d5f37f5a2fe7b24453d3f5363220914047"}]},{"mode":1,"kem_id":33,"kdf_id":3,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"d109c128e2dc1d456200070d68cfd6fa301e8f3f033b3b03c962469e6a6b830f05c79402bd3be983c94f80c849a111cc154238ee565edfc4","ikmE":"b624ca118c8d7868f552774e7aaf582c30a225ac63e383e57a9b4beeef91e5fdd7a6c70ce70bd3b1a2269a14c1d15a336fedaecd1c063576","skRm":"1445f950cdc895e05fc8d7b1f6a4d287b185b21820f5596741047894fc5f4edf3ec924872448b292ab1f9d26619c8bea2dfbb35695604f97","skEm":"44bdb381cf5ca8fe59301af7bfafb0856edb46d5e3d8fe4aaa1b808bb276a0f028af0059fb024f7a70803015a53b08465bb289ad29601c12","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"02ca87504211cb6fbfc22e58c1abc573b7d0833a59c855af55948c0d0637de15c9b6e20fa9b45b9c9fb8b7f1478295dc79a6aade2b4fb75e","pkEm":"58ccad66749c37e979576cfd4f1cfd594ec1d28c2ce59fcaddd3ad79e5e46a0de003efed8f9b9c22b966c9a63ca29ced09d61aee5ca024a7","enc":"58ccad66749c37e979576cfd4f1cfd594ec1d28c2ce59fcaddd3ad79e5e46a0de003efed8f9b9c22b966c9a63ca29ced09d61aee5ca024a7","shared_secret":"3de290762048d582301523137116db474b77298d85c6a084b20ed9db8dc40b1efd255bc231a1cffedcd96a5eb06f4da174a9a1f081b8ed38cb404fe6464fb7ff","key_schedule_context":"019d56ead53f8b69840e6dc5a1395be5afee0e65ce75192384fc5b9ee231b1609791732ab7e49c63c751bb1400c6e1fbe3df49a9a352d1f68d790068dc4f0c37aa69461ad54024dd0d2a7440f1cff5f3c5a53e21372d18bf6766592554919ce44969c417418d86d6855c4df20dfc189556f20d520a21ac7fe152ad7899d597fb87","secret":"ed453003875b9467d256310de798823611e1f6a3f404e250c736f6069153965227b8f0161c63bc3b63fe51dd14d54f0ccdfb073fa64abd978f843e9a39e424f2","key":"","base_nonce":"","exporter_secret":"02a845a9f3ddf8a2de90c26b3b69ac28fa7b920b96b44387970c95a5c47a75e0bd4403156e5265fc9381787219c1c7064ea22a4bec08576ab06a35b9d0015c06","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"82cd0f07aad577f2db292ff1d1073b6dfab655140374d9c1db3ce0a3deba65ae"},{"exporter_context":"00","L":32,"exported_value":"8e4d3a3568f1f5de942853792b76e2893777400a0645c694c57a575bd0fa83fd"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"c4c882f1e7ac43c80517e17528d9991efe82fdfa33f6dc4b9c80dc0a8c0d87ee"}]},{"mode":2,"kem_id":33,"kdf_id":3,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"4816034ea7193802ab37f8827982878d8c9fe0c6850e73403b8379b6ef41c95c71f46cdf0a6f1d2e19a14c1d157c4bd3749bcad576e4c5d3","ikmS":"1be526ce23297ea973641e48f2336659a4bdbf70edf76aa44c0d69df795c92f9957c3f0fb8373d7023c97416c8c4b2e01fc40ab91050ae50","ikmE":"d85f5047e512ab8aff0c3d783ce62efbe1e3ad83268717d71b088872070d9e6c24089966e27d7fdf1cb58410257b766f5689041fb7f3b510","skRm":"643dee148f06b1eea412889a2bb64e739f0b41c77bb343041f61b27d8ff7eb054391bcc861440a914c45c19299c17812fa94d871aaeeea18","skSm":"84ec6079cfb99fb8b5ef030c8ccb50f524f49ee93e7028639a7c71d6bfc4c7dcf591bd7b9e80d7b3e9951264f3aa10465594eb3e3d43ab4f","skEm":"77575e62c26de8742552e0a5952f2538d08acc8d2cc9e9b70d271e4dd28833c2d0a509c0d842d4556322186cd40a5e8cf8ac9a58a2964871","pkRm":"a7c161d7bdcaf39f9d00b15cb9e2038cd64e2086c43d87ddb31fda412e59f2401588fcaf641ad3822dd616a7e06f2ef1183d6dbf4f19c358","pkSm":"797f1b388a2e9692c4d6692263fd3a97449f1b1e91b09879aed5749c66bf4255b27c8ca953003ab445c148bf982b90a3f00d6717a27005ed","pkEm":"7afdc030f65c05fc1cc2ccabd830504f96665f173e90d159efc457f33c6cb94a69c24aaeae87016926df2ff9ea2c12fb54be74e94ba704c6","enc":"7afdc030f65c05fc1cc2ccabd830504f96665f173e90d159efc457f33c6cb94a69c24aaeae87016926df2ff9ea2c12fb54be74e94ba704c6","shared_secret":"2df2d5187b22f2cd4ee54d90ccfbfdc1788bbd70a37090de3086e4c97209a0c639d33b6af15efeb7aaa86e72580d1034fd2c1d339b8f7b977f91c4c988c93dc4","key_schedule_context":"02ee4fca86c518a1057129a790470347c02bd27b4a6e36f17db1186907541583ecca9a8d65aaafed3e87e030dc2227f68cf7ff612167b37f12f245ead4ba4c0afa69461ad54024dd0d2a7440f1cff5f3c5a53e21372d18bf6766592554919ce44969c417418d86d6855c4df20dfc189556f20d520a21ac7fe152ad7899d597fb87","secret":"60db1f0036b43a0517c473d0a7462277e734a29160c6b301c5c0e8a534fb4131992b63a3b10e5c64ecc95430d60e67d412cda00147aadac95e399bdd91b03dd6","key":"","base_nonce":"","exporter_secret":"93aad46f4aa4a32823bdc3394214a46d5149597f310b5de95ab28de8c9dbb64614af8284974d5002c545e307675356d902a1c24f227877ba3598232aa3aebb6e","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"a5110ac57dc0ef535a431d933479839df777d07bf8472170935e2103ae2de9b9"},{"exporter_context":"00","L":32,"exported_value":"333a5aecd81a4a58877f6da0d11afa144d59bc96b751252afa59d0d7c642684b"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"0b459c87b0fb74f151b49c246121e9fbd46e8a24a4a81a485d63252f8b07c82b"}]},{"mode":3,"kem_id":33,"kdf_id":3,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"eccae8ffa8123d00489b97f89025c1ffcfe02403a432dc4bf2930c8dab7f4548eef16a0cdb327f5c929f8295b25367ad93baf757de1192bc","ikmS":"22394797542cac795ab07e45516ba74514aaa516373e361bb69a1506df1d8b1786ca155e7a4bc85029e800cf4f8150e0a516700c7da76510","ikmE":"8ab82510f0b5599836a2e0c9feb24b0f32e422f9fe7613f2a3904f15b08aa4ae1817241d5cf14a228ff3e4ae89d0eb8d7e8d7eb137de34ef","skRm":"da829f536cdaf058a59765688a7b6525a8ebfd89600436c36094d4055d5510b47a0a703ee89391a247e67ad2d35b8d9ad8853646da1abd54","skSm":"70d5b7f9a39fc264fc0c4bc57fedca4c9c6d54f8da6de11e27ea34221c7abf7a3cb729ca9cb6c3aefa6b33b95519602f962eafe48a3461cb","skEm":"f627b0a846ee24137f83d70276e341d062c1cbefddad798142ab32a9e099d6f9561e3902f2d601f378c31b5a001e419f9f896ab3dd0dd924","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"231baf1b1255f0c97f94df37229bd2a60f02dc7133cbb0d27c717b26518bd7df008345849e250f59b61aa07a8af118b7aa650f27abe1e72b","pkSm":"2a2ce8004618ef7e65c7b063923407432ec8056db9826492fb4762be401ee967c0476a86a2f1874bab4548a6b4e7d9089112d3d385a41688","pkEm":"2830a0aee7b43f55534df95519126cfb5906e9dc8d9cb8a526176b6f66a18fad40c091ee0085e3f09a1e1e8c5f8675dd543e91088346588e","enc":"2830a0aee7b43f55534df95519126cfb5906e9dc8d9cb8a526176b6f66a18fad40c091ee0085e3f09a1e1e8c5f8675dd543e91088346588e","shared_secret":"4f3a7db20de7d76ceb239004c81b5a49d583574c654978ec65ce4544ac0f4af704510d409535f9a574097fa77aa0f0ea6af3800ba708994efbb8e5def1f9f071","key_schedule_context":"039d56ead53f8b69840e6dc5a1395be5afee0e65ce75192384fc5b9ee231b1609791732ab7e49c63c751bb1400c6e1fbe3df49a9a352d1f68d790068dc4f0c37aa69461ad54024dd0d2a7440f1cff5f3c5a53e21372d18bf6766592554919ce44969c417418d86d6855c4df20dfc189556f20d520a21ac7fe152ad7899d597fb87","secret":"c274471827c174ee8034676114e1fdee46ff0fe17f770822ad5a54bd9a7cc93143c25d19a4707c3d57a9125fb8f1a6a5d5dba2ca7c549814afec27ac9a5c45a2","key":"","base_nonce":"","exporter_secret":"956b75b64cbe8b0d7c2ae88e84f86e600f08eff79d2571a866f0e90929003e2f5327115e8420a8fcb90b5722f95297a374299401e7c15f9e6330a711fe965c9c","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"9614a6ca27d9e781f5a7dbeaa371d07c7d067e54fa4b84c2c647ed518b6d13e6"},{"exporter_context":"00","L":32,"exported_value":"318be0b35212a1ac3b320d37e76813d0316dd819fcec07ec39179b4920d23bff"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"4e15cb421ec39b1023e1a4a119d4fce8f95aa6f8012ca10ba78e76b4ce0d4078"}]},{"mode":0,"kem_id":16,"kdf_id":1,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"6b1ec8ebf259e05ca9596fd0ec634035a649d81582b0e3007f8603c6eb3435ad","ikmE":"5377490d651f4cd3e97ddaaeb50f7337230618522c4e54c1d63587adf8c96cc7","skRm":"fcabb035645cbd80f4e63e8a339c34aae82c7c79c51ddbe04890f277a6a8a249","skEm":"44d89b96fa66ec92dff344aa2df82e99d438da3c602ee705fffc1c7d5949181b","pkRm":"04d4ead4935ada233d184e73611b575e74983c10b82cb16f1fc12904792673fc31cc99035421947969b1785cc169b5f18abea0f18413dceb895b47b6f8b457470a","pkEm":"046c62e9ee75fe5b73c4aed592220c08b100a8dd0bc8ed09bfe3ccdcc2fcb12c84fc09748089abca1a2310ceebbbf3cc14e56bd325f74ba2dc8242b789f503f400","enc":"046c62e9ee75fe5b73c4aed592220c08b100a8dd0bc8ed09bfe3ccdcc2fcb12c84fc09748089abca1a2310ceebbbf3cc14e56bd325f74ba2dc8242b789f503f400","shared_secret":"4c43dd81351c0d19bf5eff313012c080978aaa3b8d14aff42322f1b832cf2610","key_schedule_context":"00b88d4e6d91759e65e87c470e8b9141113e9ad5f0c8ceefc1e088c82e6980500798e486f9c9c09c9b5c753ac72d6005de254c607d1b534ed11d493ae1c1d9ac85","secret":"fad3e982298be3f2b529b8ac142213cef6b48ad4c10d860d561cc8f1b6c5dfec","key":"856ed4d1d5ebfdbb25fd2f3d4bca3f72","base_nonce":"7f16c754a173fcd13d14f878","exporter_secret":"56f0f7619fa9a896d18da2f921597cd299c57985ca0c3c1cd473aa1c88d18377","encryptions":[{"aad":"436f756e742d30","ciphertext":"b7481ce0b49e40d4a71a73b60beda9c5ea5656815608b96eb65ad9932511de4c2354e2444d310db8b9593ffb2c","nonce":"7f16c754a173fcd13d14f878","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"28e5588d7dc7e3a1d602ba5629709d0e27bec782439afe4056105f7ecee42ac7a61740faef8fefa9e7e6dfb520","nonce":"7f16c754a173fcd13d14f879","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"8db0f0f743112e74777ff9290b9a3a2ebf34872a905c514cfd0b3ffc1495c6d5a08c6233edbaee198a3321fe0b","nonce":"7f16c754a173fcd13d14f87a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"a31c851d4fcb9fe3d68bc4c7e57849252e2dbc82a724e7378b8917cdb490fb3cea79ba73be664285fa8da3ba46","nonce":"7f16c754a173fcd13d14f87b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"f7c7ebcd92829dd869d4feed2c794f5a35dc23cda6420f4b601d705f72669b3d1bf470b2f1410ca0f939ef99ca","nonce":"7f16c754a173fcd13d14f87c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"e72f5d363e32847013686c08ecd5c03d2770022476985cf43965ac02b9f67deedf8124f20be93d142c6025f295","nonce":"7f16c754a173fcd13d14f87d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"b274e5124ed40c5a0039c5cabaf131192ddaa6f30d880879b365043b15e0c4059ab86cf5a255d9a2b8ab9db47e","nonce":"7f16c754a173fcd13d14f87e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"36fbcd9cce2de0a9463c407f043e1ba187565e7858b47f2928fa20cbb39f49cc24d5ddc30e35f213e1c2a1bce0","nonce":"7f16c754a173fcd13d14f87f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"69941fa27b53eae127949ef37e7320af68db92c4b42a8c7e441135374664ac7d4789eebca0e17a700025f53cb4","nonce":"7f16c754a173fcd13d14f870","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"bdb5818b937792cdcbf6d95d55e0cbb32dc4100babb3e8285403dfd8359b7439396d213215611d998810a9b963","nonce":"7f16c754a173fcd13d14f871","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"8746c2f602b7b107802bf01c7b7451945a6ed7731e845bdb09db1b18de430cbe7532463b343b2e991174e92fb3","nonce":"7f16c754a173fcd13d14f872","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"e3eddbbfed88ddf17406cab72da0727309e08f85f53928cab4c02e4eb30b78df943d94dc59991f91b3bec5925a","nonce":"7f16c754a173fcd13d14f873","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"a9e55d144efee6d367b5b6d9e771a11e06348ad35feae40e7eef0d162fad97e7706821d10f8b17e19d0169e06c","nonce":"7f16c754a173fcd13d14f874","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"7ac977860fa9609298e912acbd0f0e36078db6351cccefe840fa84707687d3b0a00c149e37126cf6c1f7e4648a","nonce":"7f16c754a173fcd13d14f875","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"3d7b9e52be19f0ea4a546c7dd986ec4d6f7f810c0a9926a3abdb075c93f76c1656c1cc232986b2af1c6033d303","nonce":"7f16c754a173fcd13d14f876","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"1e4ba406668e347d9e14233ce7902227f5ab8701021ab5f744e84ebcdf12c29ca9b8073864fee26e964d0b3ef0","nonce":"7f16c754a173fcd13d14f877","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"5aa9fd17a9e48e0b5e6df6cc1e01cd5ea820c1127bc3eedc57b4ab3eb7f6c720d14c50cecf79b3d06853521ee5","nonce":"7f16c754a173fcd13d14f868","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"9b834caa66565230ee240a10ebb4b884ca7ca5f48ca20846752ac94dba2bffdc9f829e0e50521388f2ed86c8e1","nonce":"7f16c754a173fcd13d14f869","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"49d0a940654d79d63fa9bfbe18d15e4852aef0897b2ef2117ba00cb486b42508d3b7b1524ad6d11abd04a27c16","nonce":"7f16c754a173fcd13d14f86a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"287ef4b565be13eee8777acddf058506485b5da0e02b4b5742aed20ef7af5c37bc64d1b92bf9d4cc7a0c4f71af","nonce":"7f16c754a173fcd13d14f86b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"06e086bf89d5d971cd697fb43ffc2cee6fc04d068f8c1ffe18760d333e1aeba92a1da44d0f789e02834c62ab33","nonce":"7f16c754a173fcd13d14f86c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"fa06763d4c50bf11626b6bb298c8aa9005013e09d98676f0cc566ac8fb37339e6a029f7f42e3759e1649e0e12d","nonce":"7f16c754a173fcd13d14f86d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"bd591caae707dab0ea34c9ce8e1b6be4ef83040a39a5458271a94d01b4897e718205a4a45623d08c0378a3f916","nonce":"7f16c754a173fcd13d14f86e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"5e593383c34f43f2b9cd5f1e5d661506db5fb023e2253f9ef17c4c71006041baacf7d280430a2047bd7a9b3bb5","nonce":"7f16c754a173fcd13d14f86f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"7e715199dfb149e8805c2bbd86b3ba7ffa8c9b85528a587ea81db647074a17d8c089c20ab6900c3380a0bd8c41","nonce":"7f16c754a173fcd13d14f860","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"f6ddda226a32910a083f0ac98773140604ca5bbb7aeaff0fbbd332886b2085a6c9946c7f9d600b38b2bf96b7d8","nonce":"7f16c754a173fcd13d14f861","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"8dd92966ef2ece16577d0dce69a68d9f3992af8d5cc2bbdcf6b92a4f4357afcbec5e14dd2cadf05595b0dad5d4","nonce":"7f16c754a173fcd13d14f862","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"6970a7d8e83af507017bcf946a5ed164e2dc715a1669ef9b15245f4d28412d456a5be74fdc15d4f56ba9f56866","nonce":"7f16c754a173fcd13d14f863","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"469c1b977b67e596a3854234ed3b99f881241dfc6e4dd4f9754678eea4261337c99ed84e77c51fac8bb2785867","nonce":"7f16c754a173fcd13d14f864","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"da2c6fe4ced9eefb87c0adf91bbc24546352446ae73d53600e5dfaa74d7ceb1991addc275bb2f0000bc6cf75ed","nonce":"7f16c754a173fcd13d14f865","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"a148c7f30aba1eb9a774a52fc9f9c579de9adfe0d3c3f1601f71e1d7255733a8aa36e3bbe804fcf23e6636bc01","nonce":"7f16c754a173fcd13d14f866","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"4afca8bde84d85c8c361f0b82888e7e94e3f53e8ec99b06921ef10dc4ed87acf2a1218d9181204880f99973b42","nonce":"7f16c754a173fcd13d14f867","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"1f42f7b800bc86931340f7b5f2de1932dc307e2df7bf6e344d2ef533f4e9b6254a39d42c76fe443450fdec5344","nonce":"7f16c754a173fcd13d14f858","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"9501508b03f6073f8e361fadb9416870342a3f34e4127c28b5ff34d27c8352b57d4438fb417dc4fa599cff04ae","nonce":"7f16c754a173fcd13d14f859","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"4e5f15ec0af07283976ec079c688046b25250711ce73b352ce3aa20531ff3535efdfd68c938824d8bd0f411b84","nonce":"7f16c754a173fcd13d14f85a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"6cfa067aad7d86c05e0b072178efa3f8de8da4e60924d118145e8836e2dd838536860522245c351b67d30fed60","nonce":"7f16c754a173fcd13d14f85b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"3a10a095f8541e5145e21f6f9faff035597a4e3c82d721c65b07584e49d6eaa72d2162beb6df75e197c067cee0","nonce":"7f16c754a173fcd13d14f85c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"1a1ea6d5b401fec78722e0e267f38ab87b9e6b8abc9db937ad921aa575fcb289e625d443af3926b49de26f0e55","nonce":"7f16c754a173fcd13d14f85d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"9bb021cadb50249f80abac568a6618289ff5aac2e043df52a45ef777613bd80b01bf44cdb35a4773bf8d39c58a","nonce":"7f16c754a173fcd13d14f85e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"21bf937fb08d8bb6d206d0eac166849bc89c240ae35d2ef808208f598c9645ce2eeb86719f6be6203d1b22679b","nonce":"7f16c754a173fcd13d14f85f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"5195b779d5231a2798a666dab6dc14b2588b4451dc8faa079426b49d83a80ebdb256e68627c9136ca02f0c68d3","nonce":"7f16c754a173fcd13d14f850","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"89c34c0a38449a4a01b9eb1a68eba338f8832490c1ee6a184ee3795430f1f4b0e5ebf8f0cf14b04ea40f887dd7","nonce":"7f16c754a173fcd13d14f851","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"81adf5376ad698a704c5c009e2490e1ee2d2c0e724ad633a89718d5a20a9e27a851b7b491017ad311d6d862e11","nonce":"7f16c754a173fcd13d14f852","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"18ef6c51b44e0f0711238388358c72dc84bca88d47c813888643d0902c11790e765ac8d5a5037cf4a556d0aa9d","nonce":"7f16c754a173fcd13d14f853","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"e72865f8e5e668a7b335c452ff9c29b97d16f316189e1b8a4156fcc0576946911f51de5030fd6fd004dbce938c","nonce":"7f16c754a173fcd13d14f854","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"9202a96a58c2beaff65c59aa2b138a21278b60079a5cd3c060df49f0d36d2b44d09293754b99a500f15a115af7","nonce":"7f16c754a173fcd13d14f855","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"7b7965a9325622ef0da1a153f6ba1b9178e7ea35bf80607bd0a994be161b49a31081004397a80cd7bf91ae56c9","nonce":"7f16c754a173fcd13d14f856","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"422974b81bcacf0df427327ba0e75147115beafc70a7a3cbc22cd74b4168875d0dbb824551a63738be9adf30ab","nonce":"7f16c754a173fcd13d14f857","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"e158fc97f6da71e464cbceab918b09318a9be9e30328e06a11081c6a43096ce680a240d7ea042825144d40d827","nonce":"7f16c754a173fcd13d14f848","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"61ac64c2093fff764a7857810f40a342bd3740b3e97fff2e1da2bc2f67f29a304e70aaad7cde601e6e3cb54f1e","nonce":"7f16c754a173fcd13d14f849","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"e4a8fcb17e3f236eec4f5beba88a93e5d371435f225e05b416c74dec26aed8ce132d35e50c5712e104671b0369","nonce":"7f16c754a173fcd13d14f84a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"a4cc5c246dda0c152cad51590f58f7a7b82ad4a0850161b64f2fa3f076a8b57dba841b37df8a1ae87e031c4f26","nonce":"7f16c754a173fcd13d14f84b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"29f7d78fc8d1f192933161f4784330d8daf712b5975163b79091693e6376cbc859fb395e0db33233cca9e96c62","nonce":"7f16c754a173fcd13d14f84c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"0353a04fd5e396235d84cff57450e81a9351a62b9d811913cc8080c0bcc25d991115f336857dcc10492d839fdb","nonce":"7f16c754a173fcd13d14f84d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"ce5344ffad904a82da2c6d4b968a63fa409d41cfef9d67f8615ba1f581149a867b4f914bf4affc13e7d9e79fd7","nonce":"7f16c754a173fcd13d14f84e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"6526545379bff995661d7417ceec0bd21521047b4a1208575f4f7cf9e422a0111b305b8de7e36e970b3d49974d","nonce":"7f16c754a173fcd13d14f84f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"552938e575f02421520849cdddaf7f851820d7d8c89362f6f9e9f6af963ef52d04ce603c37acf6dffdc3e7f80b","nonce":"7f16c754a173fcd13d14f840","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"60d0d7d7426c8bc7fd10506ea449b5f946e1cab7f1459a200d30b677fb60b0e9d3c8f559b4c72753587c242fc7","nonce":"7f16c754a173fcd13d14f841","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"472361f737cb5526722bacffa185a1df96fc981cb475c04270cc12c4ae6303a32882af0996934dba36d70ece28","nonce":"7f16c754a173fcd13d14f842","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"27ce6a602e9a074e574c7923a96d324c03c8c59985f1a17c52584957dcf170169c20d7100e31a369644126aca6","nonce":"7f16c754a173fcd13d14f843","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"d5091c6a2e6df6cdf751a5b933f97468c81eb8a36130a11b66ed0c0c406244699eccc08f5f35b4f4b9b0bd804f","nonce":"7f16c754a173fcd13d14f844","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"1ffe57fc18c1a55705cd929b4d2b0c9d229992054aea35b9dbb95e2abcab783f14b42dabf188a4f84f4a6705d2","nonce":"7f16c754a173fcd13d14f845","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"a0ea2fe423b7fcb8aa86c8013a20f2a8d266a6f2afb4914561f04f054471653ca350b86e6c87ff72cebfe74ed5","nonce":"7f16c754a173fcd13d14f846","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"602154ffff1e35845d427dbd6bb6df323b797c82272cded71ec601718dda0ae1a12e7a3552f425b5af0035866e","nonce":"7f16c754a173fcd13d14f847","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"2fa634c5f61221e7b0897ac3229e3813dc938d8987b8726199a6e5511eabc32dde173f68c615adeeb55bff92f7","nonce":"7f16c754a173fcd13d14f838","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"7bb764cbc09fa125a55c2678b784571a026e83fa20560f2617c9a17eea28e78d833d4025a67dd5825514c08d99","nonce":"7f16c754a173fcd13d14f839","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"3f52e67ab3884ee82f3f7db6e2c6fca7355764d562f23cef0884eb325690c6a414b23586fc6f780dd70c8fb3ce","nonce":"7f16c754a173fcd13d14f83a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"9aa24644665ea4ee2a2a33856cfa865b148643da9f1ed180b931018b806a4ae850fd785d1355832cc79bcea095","nonce":"7f16c754a173fcd13d14f83b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"cb4942ec07d66b665984e5475001c6b76914721eb4e524be4907bc2fd57b414b432ec1bb272eec15fc9c573805","nonce":"7f16c754a173fcd13d14f83c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"b9efba791bcf444c87409c0c3a7ce14120ef50a4225a50d7aed173329c8d573608d78c46c8db2c5752c23d80c6","nonce":"7f16c754a173fcd13d14f83d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"8bff31b07ab0bf7d93ff8fac9ff24dd664aeb6de4dd21eade1f8d6a4fde7db90bbb2e49c5cf3d3998dbdf4ea63","nonce":"7f16c754a173fcd13d14f83e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"83e528ece03a3050283ffcc7c50182091c24de589549866a965c707b2f4d8a01f849f72b7976e1e04a9e56888b","nonce":"7f16c754a173fcd13d14f83f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"f00a11934b1ccabd1366e17a433f04520e1ac90eae168e8d7d65dd7590004dee21e10d331eb312f010835f2c26","nonce":"7f16c754a173fcd13d14f830","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"c2fbf0d52d08a1b5d5231f10b4cb9d34a4c3a23f4a6e4691514cb5e153ec03e203cc9e18f6397195375311cc90","nonce":"7f16c754a173fcd13d14f831","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"b8960435ae80710be21ac7fe1db969e755454919e087a80ce35824adadb0dd579204acd7120e3b5beffb9fbd69","nonce":"7f16c754a173fcd13d14f832","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"0a024fb162864e0153cc4a8fa8e08e301ecc196d40286405bd50c0dd49806f6178aea834b4b6227125bcac625b","nonce":"7f16c754a173fcd13d14f833","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"1679c0999d608f873dfbb79a5e0e27bd64ae5d12d9181ad262385d5456bad1a77a33fc9d6cb6d540ac7235a2ae","nonce":"7f16c754a173fcd13d14f834","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"9df098b9db45fe4e7a9f97d4d6a1be62df0bd7d491d579a41e7dfd1af4cf04bc6d38811475992456441f64ffa3","nonce":"7f16c754a173fcd13d14f835","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"fa4930fdf5d873a9f126ef24e8e450751c227f962f255ceb1ea044a2c744c7a805a43e5e1495e6132b62ef18d2","nonce":"7f16c754a173fcd13d14f836","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"08e5ebaa0733a08b8567f25b8c4348fd4f79b8b73f3ad3029709afba1f7d1cc94f5183c30b439b92407a381496","nonce":"7f16c754a173fcd13d14f837","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"d76b9d75842863f1ce3a766afaa71aacd364d3f64048a33af923123c74bdbb709201eacb4bf2b84be1f55f4748","nonce":"7f16c754a173fcd13d14f828","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"b7acdad7daf9013284f760c874f4e71c98e9585f0b5db11602d80cda9f8ad62f6f832eee61b6dfb706b1401811","nonce":"7f16c754a173fcd13d14f829","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"fea8e28c5c2b9a2de21a624f615a45959f97d1ef09489c7061c892e30223ef04c5ca9c56a7f97bb0f883758ec9","nonce":"7f16c754a173fcd13d14f82a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"c5a25b7068282668e7e275f5b7a03772b1d21d269a797fda8ecf1f078ff9f8fd08cbd05503f4dd49a3a54e847c","nonce":"7f16c754a173fcd13d14f82b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"bdcebe0c45d2a054f8255769942f26714f29e6865dd6f2ee12f2bbbb8062178430014308a991043410337704c2","nonce":"7f16c754a173fcd13d14f82c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"f3a9bca4338b6bebded1d6dd2bac1c9cfce769a3a85de9901982897fd3676b131b58b2f137ce9ab95ab6c9a66e","nonce":"7f16c754a173fcd13d14f82d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"03ac32ce36e9322accfbdfefad102edf8060b143735443cd898f62c33f85ea39ee5b3e6a4e2bcc0bf9091442c6","nonce":"7f16c754a173fcd13d14f82e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"b999df114d617df5df2633e06fefeec5b1ce28abcab8cdeaa68a8878d73d9c1fee108c7c7a29a666d5b6c7e4a4","nonce":"7f16c754a173fcd13d14f82f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"5ea3b22b0002240c574161c8dca9dd0fbc23246038d28cdd9fd8032857661bf7a324db8d1ebe162b53225931d3","nonce":"7f16c754a173fcd13d14f820","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"37d788226724741cd7543bac11ed0bdb1ca2f9c1fda475fce41561d949bbea4bbd65bd2a12b5af855f7195a449","nonce":"7f16c754a173fcd13d14f821","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"135a85cfc64078a9dc31ec72956d20e207c63e28f979ee879b771cc48f96be61e176c2c76ed359b7bcc6e329db","nonce":"7f16c754a173fcd13d14f822","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"c5fbe0b8f6d3513213272394844c7e6de1080fe7e5f4fd7c1a5200a02dd19c5560309ad76576ccc5a203992855","nonce":"7f16c754a173fcd13d14f823","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"db1a7be2959692b8e1213168bd70cb00f7592cc6ab523a78b5cae99a22a23aea6621d14dde26cb4a1fb5013975","nonce":"7f16c754a173fcd13d14f824","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"4685f07f2f9b1466e7b8327cb5e36a1e30a08830c90e51f2103ef17ea2dac45f44dabbd86bd1ce94fb556b2a03","nonce":"7f16c754a173fcd13d14f825","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"2da3d10b9a74b79be84e711937cfa30d563e1dbec0a2353016f6266816b5c41d8dec456b09b2442e85c95d0923","nonce":"7f16c754a173fcd13d14f826","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"9718d478d29012b8016613df9e1949e3f6776179ee770343d9c98d895228e6b2cfced7945043d0a093c3f970d2","nonce":"7f16c754a173fcd13d14f827","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"7aa261b7fb566cd348d74d54ef8bd25174233d9105a04ac85b4fb90c5242cc1f33ff259795751613ecbe7fdbbe","nonce":"7f16c754a173fcd13d14f818","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"cdfda850926fd05485719367e3076c026ec89b1afeea71931df75bc2e51f9c0268c9f8a64c1bc9bfc0c15ce698","nonce":"7f16c754a173fcd13d14f819","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"e885781454f036c9e7ff66b950a45b75d67cfdb243e3e614e2c165dc489d34a65fbead623ab45a1eaeff328293","nonce":"7f16c754a173fcd13d14f81a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"58b210b09cfff543ffef460bfad53d98ef047671c880e1f6be59acd1e8a1564af8eec9ab0474584f78f1ccf4e6","nonce":"7f16c754a173fcd13d14f81b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"ca29dfa06ae8a4b3bf5d1c8b643f27f129322b765ea0bc76668c70b2c34e6bc9b6ddd016ab5cfccba0da641255","nonce":"7f16c754a173fcd13d14f81c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"216dea9820ab38fae25f29f02a796e437c67d5d293dd73ba2ad193dd2615aef4a5137d684c6051b634ec1a6509","nonce":"7f16c754a173fcd13d14f81d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"d07df362366f4f86174fc02268981f2a51140fd9747dfb0830624d2b8482e49edc0885a300030344e6ed671b7c","nonce":"7f16c754a173fcd13d14f81e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"cbf41f0eb09f1cdd127b50c09c1fc1613b2026c1877d79ac7c14c4a56efae4fa2404734a38fb665c958a07fd84","nonce":"7f16c754a173fcd13d14f81f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"153cee775e248be87db125a2e160654286a4ee4ac6c05a7f142bffeb16fa00bf72ce63611744c5890864d4308c","nonce":"7f16c754a173fcd13d14f810","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"c70b9b2c583cf2d022171d6fbd0a93af4881b91da4fc04ab24a378a342edcde6c2bafb5976b6eabfdfb7ef50da","nonce":"7f16c754a173fcd13d14f811","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"cf07e2af8d61fd7fe2a28cf6dd52523a79f4f9c850bbdd147e29d2587733854dd29e19078f7905fa1bc86d533a","nonce":"7f16c754a173fcd13d14f812","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"6d070a9819c69b3bceb1cba86fe85fcde4215d61df2e184e718f958b1fcda3c2460f9db9f047184801a882023d","nonce":"7f16c754a173fcd13d14f813","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"79040e2b9f5a134e3ba497cd08ae7f7eb953aded793d96446cc3cb638f9c962701f1d5d8c03d9092c75a3a63bf","nonce":"7f16c754a173fcd13d14f814","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"2442b22f159c70acf9b7eb189c0a18f0a2b3e8e240e625c0896e854cca798635d8be78472220bb8f7bd94892f9","nonce":"7f16c754a173fcd13d14f815","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"b81f747f6ceeb8f15b78f9062cff1e14a4b0d702dc7e73abb436bbf67ee40021e2f84e030a520cdc7cb0815af9","nonce":"7f16c754a173fcd13d14f816","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"a2a540e6ee1886564a80b2e2368f5db2695df7f8577989dba5c6a2a18d14ebee9df8b78422be9b60de192c6788","nonce":"7f16c754a173fcd13d14f817","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"e9d1806b5650a138ad51b275f01dcbb8c9a35780b29da0122b6ee8ba6ca5bea029c9f4394a4d75635bd4c02041","nonce":"7f16c754a173fcd13d14f808","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"b4da6b0e4ca5fa49cd67e7a50b3e33953c97c9f3eba0d31ef16695a56392775072171aa6e9b42d44d3c0a4b0ce","nonce":"7f16c754a173fcd13d14f809","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"78aa6353238a66ac2c5993ffcf742018da8eef46708779bbfc5761baccd6b38e967fff64ad98487cb1b9d138b0","nonce":"7f16c754a173fcd13d14f80a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"76cf4b1e49acf5252f60d55d74c3e102df32983f5433095d7dc7f751c252c2e7e1cc16f80ea584805ab75116c5","nonce":"7f16c754a173fcd13d14f80b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"9b999b0faffd539aafb6ef9b4bd05ff1f21c7443f04c804774935d6694882881e0162b606dcce09b5a2b3d19d5","nonce":"7f16c754a173fcd13d14f80c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"b5127ccf5514394860a2e65ef15fd0eaf635a7463c0817087906d9e7595d0cbfd1a769ab736ccf4e76cd7a5284","nonce":"7f16c754a173fcd13d14f80d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"787bf0d5d268f37e9abfe64ddb75ef63f35283a3bc44458a525a0f43768581c75bb880b3054e7aed16f808b7b2","nonce":"7f16c754a173fcd13d14f80e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"3888259e797d63ec7a0040b762091c2cd9ce91b2f8bdee3125a2e4343ca0b8edfdabf94f3040974d9f376b6250","nonce":"7f16c754a173fcd13d14f80f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"c8220a8c4b42effee696800c6925347556f09b3dac49d4281c332b684ca4b80fc043c33ce3a57ff4c752a009f8","nonce":"7f16c754a173fcd13d14f800","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"416bf14b53cdf67396501a772aa097ee73065a5ef0e129b0de27ce1b975f4f8dff6fbcc26a7679f895f4b17fc8","nonce":"7f16c754a173fcd13d14f801","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"e352b79e6789cae878d23a538d8f3e6e272f38d0486904e45432fcae7a4374a9ea5a2953fd49a0cae30a869733","nonce":"7f16c754a173fcd13d14f802","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"b38b240f16edc948f4cca1ab7945ca33f8b6e8b4ebe8ab2e1dfd9274f5b933bdeeccb26162ab81c84f8267e78a","nonce":"7f16c754a173fcd13d14f803","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"13067bb449c6935dd5a76a95e16a5feffdd20bf66c8ffda93825f0fb019291edf8fce768938997845d11788872","nonce":"7f16c754a173fcd13d14f804","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"ef59432dc4c8bf02e3fd434dc2a45caf5404062c0fe9a7c5403235c43a55d1986e11c46c628e84cc0c9ffca115","nonce":"7f16c754a173fcd13d14f805","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"c10635d990715bedc0df07d7c12a70cad30112a9817ab8d57d21538faeb9ca6dd83cf4827bcaf1922cd683be1b","nonce":"7f16c754a173fcd13d14f806","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"a14a8e417cd33d13a1abeba27adc600fe45f18c88923bb037493339480aac166017407adc700042a13dcdaf5db","nonce":"7f16c754a173fcd13d14f807","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"2471352a7036e075423973b5ba106ba95a7ed94543492045abc3b07e101e39a825c739c63033c19d99319cb447","nonce":"7f16c754a173fcd13d14f8f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"30d3b96ba6b80868b4a836c0bf3186c373491538f85d6cbb75ad761a68d32618d83ce196122aec453e255813f3","nonce":"7f16c754a173fcd13d14f8f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"8b974ec025d5decc4dc7fb7b6c5acab0b0ea2875a23ab3a98fad1f29ce3ad9057b40a34378a837020857289503","nonce":"7f16c754a173fcd13d14f8fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"df858a39c5436b997e13668b3aa94dba2831c6b76dcd96e4937157622f8e6700686fbd21b0bd3d59c8ff159ad1","nonce":"7f16c754a173fcd13d14f8fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"21d3dcd89ec9033589520126697ae76c6dfdff941de5901414915b1c28fe54830d6b526bb1f5fbec433e3e5c81","nonce":"7f16c754a173fcd13d14f8fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"577076353eba566b6fdc02abf233ad1a1f976c34d291e3d14075a263487a5d2b0eca0449cad7b4fd32a9a8b39c","nonce":"7f16c754a173fcd13d14f8fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"adeaa85c61ccd63316a43028a667e39931e0a071b3d7cbfa68b2ab6050472d21da38842b367037809c50f7c43f","nonce":"7f16c754a173fcd13d14f8fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"31750452de147ba00345e0a0e77a34a0ed010ec17aa0a60f3efea7ec767450bbbc1cff4fb101dcdb03da6213b0","nonce":"7f16c754a173fcd13d14f8ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"07afde83c90efb3f61b5fbed43a00aac9b0782ad31c79f43408f4eeb1f44bd04f976bab13a88eaf375e170e904","nonce":"7f16c754a173fcd13d14f8f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"767ef17a9291ebe550318e9d7f6a02dd87dc2cf863e305a18b80363fb5520b330ec06003f9d743e2071f07150f","nonce":"7f16c754a173fcd13d14f8f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"32e54cdf0b36cc7e4a5d6b876cbb26e09d47e895d4c7377f885a0f418f9bdadcada30ff5d5dfa733e443f45a3b","nonce":"7f16c754a173fcd13d14f8f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"c194b13b718ace09f0517d40114171d546cb7c545d7dbe9fec502ecb4c0d48000456816962e66cdccc7d93b2ab","nonce":"7f16c754a173fcd13d14f8f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"f11877749be5aa3deaf909343be9e82913cb972f16f92a5976ad5004dbf6f7b4f5cdc841886a7d218ace34bf39","nonce":"7f16c754a173fcd13d14f8f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"81eb05ba8c03660cd3c557625024a37c1d393b3087c477e6b82f24d2a1f335c88403fb77fe57c4289dcff88115","nonce":"7f16c754a173fcd13d14f8f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"766f539b021b25ef88cfc261db6f96c57fa559e94f630cd075fdcbb9dc5827a83a2aa1b499a9eb25520698db61","nonce":"7f16c754a173fcd13d14f8f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"7860dd545c45348bcd1d9238f81f12d08a068e212ed17dd1fded5b3ed5095f0cb90039710091414fc53ab7d624","nonce":"7f16c754a173fcd13d14f8f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"f1ef20de72d509a17e2b91314a6d885e046415689d5a3c1ab00e0fdbd986c95a3d69d5ba30a323fbebbb2434cc","nonce":"7f16c754a173fcd13d14f8e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"b1292feb4da90dd35e29b73afb3d45d1ae8a116752e02e45025b82a567b0cdcb6d42caeba68fd0ac0bd5ff4936","nonce":"7f16c754a173fcd13d14f8e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"c7a3d543c0b45400c807847f1bebffca70a1c3d2c276069a71910f6a6edb9c99bfacab896ed34c88fdd1777e42","nonce":"7f16c754a173fcd13d14f8ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"c0893396d66903fb216dea35ab11de35d9594b780ac66f57521a041a42a18d34413a36547cd3483d70a1dd2414","nonce":"7f16c754a173fcd13d14f8eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"b34363a13a1a5eb334464fdb9dee7faee389f639096c88d49e74edf9e73c14f8d49042fcd620bafd26bf92946a","nonce":"7f16c754a173fcd13d14f8ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"3f759506fd7ccd97a55f56baa46daa931de76405e39ced1e8213aee2b8d77efcb5272fb020c50bb621bb41ffde","nonce":"7f16c754a173fcd13d14f8ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"535c639fa39fdf1ff661720ed584c5c1e87f26614a840c906fedfae2873aed91bb19b4f3d8825025b17acf213d","nonce":"7f16c754a173fcd13d14f8ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"6fb6538a367a2048192be3d7adb05a577443113116df70c4158c24dc882b7dd72d7596cd497e7a526f61f357b5","nonce":"7f16c754a173fcd13d14f8ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"c9e23fad52ed209c6443674c1effdfc7952e78f74d133c41a6690678a7caa096a3c49b13f508e2937973decf5f","nonce":"7f16c754a173fcd13d14f8e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"06b3fe359d1566146561461fe141484da553e5e85e467ba16d2306364c4540ffeda99d9eb0efca884df27e3e59","nonce":"7f16c754a173fcd13d14f8e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"4479d5a4810adbc926f6a741f3a0d93299b21f609686350c2ca5a68dbd645ed9921930dc5317693788e3b33edb","nonce":"7f16c754a173fcd13d14f8e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"270f0827bd696fdfb2521acf93469bc6357d5ef25fe4abf1438f53cf2222d58d6a5655d48745f8f7b6a208730d","nonce":"7f16c754a173fcd13d14f8e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"4ba2e01c043b1e0309787aa7c35c0b98d2705cbad4c186cac4e54c0ef167c31ab5e3ca5ea1b1558546a0624225","nonce":"7f16c754a173fcd13d14f8e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"bd1d8bf6421daed00dac72c41dcebbd77d0a07d2e0536826a34a12a140ad536991996f338100863a1a103633da","nonce":"7f16c754a173fcd13d14f8e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"02143f3ff3134eec0df03072199b8ac706366a992a23bd70e4db005144947f6933bc0c88a8f22471fe86ec42ed","nonce":"7f16c754a173fcd13d14f8e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"7fde8185568332ebc82958626582eb7700eebc8bc543ce4ff6a7c5812efe88b00cd587516427e568f92faf8804","nonce":"7f16c754a173fcd13d14f8e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"43910acc58de56d6f0d530f909f0c066084f88070afa557effa076d8c0a983e7c2bed1c39b93df10f501710cd5","nonce":"7f16c754a173fcd13d14f8d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"179220a3f016e8819f67a37117e4bd01dccef98fa34508b54824a4938d2f12feb10d8f2b8b123bbd5fcfe2c228","nonce":"7f16c754a173fcd13d14f8d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"c3720c4a80ebdf7b20c816046a647b4a8679a63591dbbbb925cf1e27bbaff23a6d4915971594cdeb7b529943f4","nonce":"7f16c754a173fcd13d14f8da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"11da4233cfe92b726bb8767683846250846af75598164a0b3eb58f51c2bdc341989c94187344f01b3babdafabb","nonce":"7f16c754a173fcd13d14f8db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"f36def571ba32f054821e8505b690922f9d562cf187187b1ce4e1ae16f15d298a0e7806b3b4d30162c0115092a","nonce":"7f16c754a173fcd13d14f8dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"1a963fff463b4b2e17267b66a1ffa10dad528209bd7fb54f8fceec6239e7402b3562e55fb48e03324408966dfc","nonce":"7f16c754a173fcd13d14f8dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"f30a642c7c0f9b4ad04e2ef0a5d39eae4842ecef2eec12dd12974c4986c64f6790aa88e3e65572eea28e8d9e51","nonce":"7f16c754a173fcd13d14f8de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"83ea5b8d1448f57b145a777d27ab2a4a4df72eda6806edff52c345dc15c3f84d554f59891818ead400640476b4","nonce":"7f16c754a173fcd13d14f8df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"dcabc949790a9627e47052ea3bbabfedf0011ea9a1fbec48646b3a2365085861821b929b8234a54c5d91a88440","nonce":"7f16c754a173fcd13d14f8d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"e3585f04c692927ab9183185c1969b3895bc510dcda595d77cbc2627c0c0e606bf751d61db5836a00f416a6e79","nonce":"7f16c754a173fcd13d14f8d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"7086bc4d6d10e696837d4d29b8eb851648f3bd261a9426fbe35d16b636d056bdde366232c3a15d2ce6375a9ccd","nonce":"7f16c754a173fcd13d14f8d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"1292fe4431f2986643b2c9e03b1e9e3c3f484e14d11773ac900e92801b8ca0b39d25ccf84f79e5daac96a14c39","nonce":"7f16c754a173fcd13d14f8d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"66cec460d24e6f87ec103f2fee81d61349e58e38aad422c30617cee0a23517f0ddd9ae495d332b405558faf771","nonce":"7f16c754a173fcd13d14f8d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"7d82398adc12dcfab96f3e1221962ece420404d60667564f0c2b7908661b9c8c89447e8842759691b6d02345c8","nonce":"7f16c754a173fcd13d14f8d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"4d3980de4f15b0ea3b676a0923957e301cc63ce84fdd0fef72b8b58e9f1a7edb809b7cc1b3a2334145f3b6460d","nonce":"7f16c754a173fcd13d14f8d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"94ce841367f61f47f2a97b567e093a27659ca5cb1af9f078bd6fe14f93a8d762ce26d0b6004eeba4e6b05fc1e1","nonce":"7f16c754a173fcd13d14f8d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"cc1e41aaf70dca1beb735a184b9effb12bdd6645906ab993c8b5902ee603fd36638345d627b6401363bcac6e65","nonce":"7f16c754a173fcd13d14f8c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"b0bdc4f2204fef8264c586e69f8675a12bf1c4f98ace5efb77906739fada1aa0af6f43e261dc55f313cf902f70","nonce":"7f16c754a173fcd13d14f8c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"7defa4d3cb15180c1dccf4f8f02492e8b0f126ddb53068794c3b630ff12c456de8b09a9324551f085f70f306eb","nonce":"7f16c754a173fcd13d14f8ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"5b129e5470b0980a8124cb242171cfee7a02d1cd8cbcb8306c0932df3cce4f4b2d70ac65638cefdcfe0ece762f","nonce":"7f16c754a173fcd13d14f8cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"1a8f88154d702b2fdbb194c2fad37b33596521ad035857fdac86f6c27530931f2302382e080f55f49defe83b71","nonce":"7f16c754a173fcd13d14f8cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"fe10a22bb4db28d3d6af06e9942151c9cc509ba4aec939a827e6cba6afa12a0e882d31ef67ad1e78d79a916114","nonce":"7f16c754a173fcd13d14f8cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"55adb5625fbec578aaf751fe846b0ca7ee6ecfa2f4f6402b3d49c0ea9ff2727262cd71d3cdcb66e27268701689","nonce":"7f16c754a173fcd13d14f8ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"c4c94d6a4471fa93cae9fd1d4aad9b73cdfff9e105a1cff4b60560b6149ddd42b7e392c3e38a48a2c05c87a70d","nonce":"7f16c754a173fcd13d14f8cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"41775438b200da8cd482fe20b43f3b0bbf060e2e8f35f2944b1b21d3efa867f4a1c5820d06fb07442afce3f4ba","nonce":"7f16c754a173fcd13d14f8c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"80eb3b98c2a1b7ecac5d87d2b70b8bf62a5e10a6affd4d764483f45ffc4ba007baab69d2e097a0fb33ac2c9c34","nonce":"7f16c754a173fcd13d14f8c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"86b9a4d77c0fd3a754c89779cebac83f77542f96b3dd6003d838c7aadfc6bddac44def46a767a31ce46d2985b9","nonce":"7f16c754a173fcd13d14f8c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"2919c09c2c95ab8e4528512435d81c674774677d217bc151ee39664f1416d5a9bac8477912e4603d0098f80ce8","nonce":"7f16c754a173fcd13d14f8c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"9f57c80a9f5b37eb04e648ccb972cd4cf96711dbd587aed2e6efc33e6d9aa70deec509ca4401864a3347957f53","nonce":"7f16c754a173fcd13d14f8c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"83ef4f34b2adbb9cfd681ddae893873cbe7842bea71e85a69b6d5f409395bb83f97d40ecb79e912b62d75d267b","nonce":"7f16c754a173fcd13d14f8c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"75c1715f7fd9e9b9ff7ebe853c6f8c053f7562030cbb8c7231038bb25531b6c3aa1a896604cd68e2adbf284e3b","nonce":"7f16c754a173fcd13d14f8c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"bce4454306ea59ea4933cbc2706604254dcc84580663d9df166ad613ad8c2f301371e4c4748f48eb1b3134b7f9","nonce":"7f16c754a173fcd13d14f8c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"35592d8a09f35883e3d27ea84437275d6b956c77ac4789485f1848afe1c55f90df3d1c9eaab8688a1073b75cc5","nonce":"7f16c754a173fcd13d14f8b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"210c14d219e5a7089e64116601ed1b5f6cba8ace5babcf11414fe1ef292e0de86f42180c09b91514e5240f7067","nonce":"7f16c754a173fcd13d14f8b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"341372251abaf303d20b0e20723786bc4a30c9a3e1febf30a55fcbc49d7fb5d8c78596765c1bb5a7d557e0aa46","nonce":"7f16c754a173fcd13d14f8ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"39e62116b3eaa4fcd8f2ab3d77363fbc838137c7cd2b586ad7a0102041dd6c0ff05758a305a6b7e84d43b41b10","nonce":"7f16c754a173fcd13d14f8bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"0466f3f35230a2f8a6bee9cd2527e5c64685281670a42d0442882d1e91ce6a8276e34df789bfa4a8f6a678373e","nonce":"7f16c754a173fcd13d14f8bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"c8fec044f836a726c766463b4484d6b07c431e3abe0be79c9732f6bafb0ad15bde708157746af879a3d3ba41ae","nonce":"7f16c754a173fcd13d14f8bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"b60d4b84fd5ba3eaf84b295ce0debfe81a7b66decc69b43e2e5220843ed7a09ba41a335c122a530ba2cd432002","nonce":"7f16c754a173fcd13d14f8be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"ce0c2ad1d7e8b3e56ccdffa8df98b7e99aaecb07559170f9d5d2814185249b876909eafce3f378916bb99428ec","nonce":"7f16c754a173fcd13d14f8bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"41cbbffdca4b457be02c5d79d4d7b8617f04785aa8e0d3145cc1e7d27af7c972d5bb9b72348e78fe6517980590","nonce":"7f16c754a173fcd13d14f8b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"c3b6b12f0f85ad0449bc9d2cd5aab97deaf2374222eaf4b53f094037fcce8ee2c42e87e73c4f2a5b9b0c82f0da","nonce":"7f16c754a173fcd13d14f8b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"ed1ada29893d1d73f31a553f9e67b6404975bf6950d8dfd1344dda83797a34ec5a7c7e8cb763968d2267ae2453","nonce":"7f16c754a173fcd13d14f8b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"0cc009981971b65abad4db22728eb4016599df27780e3df5ca04404558af54f7bb2fc868881caa454612831d20","nonce":"7f16c754a173fcd13d14f8b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"86733f53ed174db4bd1427f1bee70dcc6a517b2db26755be331b105cee691c1ecc2aad7d94cd5cba5dc2071f00","nonce":"7f16c754a173fcd13d14f8b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"d5538dcb0162706b4e481ffc281ed323d0195aff3f14ea1775a5fc7876d74eb1d2b7c102b2c03d4a0dd17a3bc2","nonce":"7f16c754a173fcd13d14f8b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"acb097774789e39151bb64c83d4c8b6538bafb3216a99c01af451d9ed6f122f2f96bd85a825d6c61a6d16adf3f","nonce":"7f16c754a173fcd13d14f8b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"b8b2e65fde9cdf862ba461bc9a43feb5a9b58f8989927837619851a364ce43c95293a138c05aa4a8b860ed9390","nonce":"7f16c754a173fcd13d14f8b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"860e98396975b8102b5de84d634027505efeffd7c580d6e0d235beb1e4b5079c19923a52903f9654002b071097","nonce":"7f16c754a173fcd13d14f8a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"ffb3f5184b74b3e36d3d6c1454b49390f8092cfd39886f4ec99a23bf110b0d82555122a0e9f0189e9eafb7cfec","nonce":"7f16c754a173fcd13d14f8a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"69d130b0b55a59a597d5dcc7c943f19f1e2d6807915517566fe53705b022242f8864a1f7f2643a234c764aa6fb","nonce":"7f16c754a173fcd13d14f8aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"60e32af418930f53cbc602dbe7a41e1689ffb99a30f874f00c761f1e0f1ab410d688625f199ef788230ea38fa2","nonce":"7f16c754a173fcd13d14f8ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"8e2810dda9135153d404d0afc627846a50d7009f254d7a08662dc9edfd7ec606f371e91a23232ab322f6378f52","nonce":"7f16c754a173fcd13d14f8ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"a377f598eb5526fa48d74571360cce6f7b9afb05535ad52e97c9406db987e970f196726972a00226015708fcd9","nonce":"7f16c754a173fcd13d14f8ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"4bb578d708f1ab6f2a623bec5945f3c76b65519a8496466d8d0d8d47549f43a81e3bbbb9f5c7fbf507d12a239b","nonce":"7f16c754a173fcd13d14f8ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"3c486c6f3829484c3c9543ab57034d7f9ccc589f24b888429fe35e53b244a15af809f9f1e04d6c63f4b543edea","nonce":"7f16c754a173fcd13d14f8af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"fc11da2257f0ef7a0f59bb608b64b416574cab8ce12764d7918e904e2efa1989f220ce3e4fe546aa486c0bd76c","nonce":"7f16c754a173fcd13d14f8a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"58eb8b2397532f7d44403220205f486495c72a04181f6753fefeb84d6273978ec732fe87f7a2cad6be7b5ad91a","nonce":"7f16c754a173fcd13d14f8a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"5402f3a3b7426c67732914d7fbcee7ec2ae7d15932c5c79ed6dacbf22e3a91bb46297e59256eb5a370f274bd5f","nonce":"7f16c754a173fcd13d14f8a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"17be9ef7e542479a96823fbcc4f1e6b1d72099494a88e36d2babca2dbe0bd3fe65681d60eccc917fe324b75568","nonce":"7f16c754a173fcd13d14f8a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"8e8015515947c1f1d8698e2f1e8b293e3571bc8342395cf01361061495f1ffa55e885aa5cd9e6bf4c6393761c0","nonce":"7f16c754a173fcd13d14f8a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"eb18ff38c6a5824b602831af31c496081c98cca6520d8798d4997e73e217279a1eb1499c12f2cd5429f2e0b4d0","nonce":"7f16c754a173fcd13d14f8a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"1652d5568fa74898ca70ca452948ab59482c6b7cede375e13ad5bbea9f2edd5e3085c56c68c7108f3da7c970a4","nonce":"7f16c754a173fcd13d14f8a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"cfe171cb528a8d96d33bd19404f2e4210f18b6f047cb2dd0eb06871ff5d2ff171c942e4bd62357e6f73f56b5af","nonce":"7f16c754a173fcd13d14f8a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"a4fdfc3bdafab25d990477101bb76b5d51d4691553c872675f085cc1b5c6f796e61c6f0e6f36ab72dafd3e51ac","nonce":"7f16c754a173fcd13d14f898","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"d36fd7bdb5160eaac46df22a7233ea84d846a81c2f64c4a01dfa58aeee38451f13f1103fa27647ea7ff1204b6f","nonce":"7f16c754a173fcd13d14f899","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"e8283f028bb37169150dda9d30d749031fe25becdc0cf96690052756173537972a10a02b91bdbc66995227ddef","nonce":"7f16c754a173fcd13d14f89a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"f7fe6c724a1d3cbbb84861125a7fa330d4478ddec2d867823e40f95e811981db1193115044cafa76e3427669e7","nonce":"7f16c754a173fcd13d14f89b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"0884dad7bf4496b1504920b081293080c884f6404ac11f5d63022b8f57638fd7d6904075ac9d71b7f21df46ad6","nonce":"7f16c754a173fcd13d14f89c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"e1de8e3604a2998bbdc15c755b1c10ce13b60b5528bfd5820d2470ec249a1b0e9b70f363c1f19387666c7d5955","nonce":"7f16c754a173fcd13d14f89d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"f13cc1e47241afbc1cc64887e2e6d7b2692cc96021751bf846f5f9a5e62c39f3995470ad1733105b310120afdb","nonce":"7f16c754a173fcd13d14f89e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"1d6b89414f038a316c7ea75e37a1239829468d9ec5364278e79ef51e54868e2060d641957169ad79d0ddebb471","nonce":"7f16c754a173fcd13d14f89f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"9ea44ddcd7f3a9649900aa3708af24553e3af72f16ac6fa48cae4a849a63bb7c951ae20cb7d8804fc92a40311a","nonce":"7f16c754a173fcd13d14f890","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"8a29e038ea0da387649aedacd9fc9230d70fc12f5ee911830491b7944d75caca10fa1413df1c8d6611787ce3e1","nonce":"7f16c754a173fcd13d14f891","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"1ef0d307907db7847dbb16b6ec0a44fe6bb021d67b9a3b9dccab1df7292cd967fa76989456acc365b37e29a809","nonce":"7f16c754a173fcd13d14f892","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"430a2bc3a3851d2eb131462715fdd2abdbd76db32cd6150bdc70bbbf2152b1a14b687b467e7b7bf56f9049ed3b","nonce":"7f16c754a173fcd13d14f893","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"649e89f85e1581de9d2bf2aa69d668dd57f58fd3a927c5158f0aa8a87e0505da287b840c0dc84a2ed77a646bcc","nonce":"7f16c754a173fcd13d14f894","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"3d2750102eaca0e972e4fdf6e265b74bb8828119eca46506e899640fd14040e0c25eb981e5d5bfc1d9ee9b8ccf","nonce":"7f16c754a173fcd13d14f895","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"956b39aabd4d88af3238a932005ce49e5735c30ac0c0567b1d44eb6ceb5f712d22daf4906a3d8a861b7b9406ba","nonce":"7f16c754a173fcd13d14f896","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"eee8db45f5f19a927f7e915fd1e3b1eeaf23790734c4355fe8a37087a7007bac4e104f78e6d23337c3e0b8b342","nonce":"7f16c754a173fcd13d14f897","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"a5d5f7ad189969fb89c94acca721299c2ab42daebcf48340d72ad2ce335e611cd208a21553295cc9422d53284b","nonce":"7f16c754a173fcd13d14f888","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"3e18cc3b02eef935641ac50e24e6fba283a5717d03b7ba34dc071bf2b822c8b5e547fa917fa4443a19b7d14ec7","nonce":"7f16c754a173fcd13d14f889","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"ecf0454fb1c2680d089d94f5b4a04f26fad6102cd9a46c41ce71535d8920ddd4471653184e7f43bce05809ba91","nonce":"7f16c754a173fcd13d14f88a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"512814512326a2c1fabcfc81def35b29c32cbcc2b7ac2989ad6d2ff55a6b8b86f16637f1e89feb0bf8996c2301","nonce":"7f16c754a173fcd13d14f88b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"047e2fa5c201f6bd2fb82133bb2142396600202af09a6942747d0f7c22eae8cfc540a30a532ef679e05b2d1968","nonce":"7f16c754a173fcd13d14f88c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"147abf44af69bd177c735a3941cc483662154f765f5a6f4a780fc3784671d7315ef7302a907c6c64e62882e2a3","nonce":"7f16c754a173fcd13d14f88d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"f18632b9211c5fb3be639357a7b813f853e72fd2d222bdfa4ed9bae631ac9971b0ebab3e7bff9115c44983972b","nonce":"7f16c754a173fcd13d14f88e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"5fc19e78caffb9c9ff81a36e739680f29aaf91d7428d6b2a43b0df6f21378075530e5d710b064acbc08798161a","nonce":"7f16c754a173fcd13d14f88f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"93c48f9a341daa3395e095c2a5324b66a48bd4baa9b757bec1737f04636b135b0b427e8541961cd12759797e00","nonce":"7f16c754a173fcd13d14f880","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"8d9b75663c39c9c42c5df458542ffc20a7fee4e57dcf6d971c88c72ec1d57f925d04cde9b57c21531d699443c1","nonce":"7f16c754a173fcd13d14f881","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"560ec137f40072cbb6aaca9d6cef339e1c9356d683314454dead08f8d0c4224d8a4027ed4677632feed98d3f77","nonce":"7f16c754a173fcd13d14f882","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"8ac5dc787f781f34adc0e2c8d75fadb8e020c983e14c384ba2799c3753effe81e898ab20d155f999bf642d6aaf","nonce":"7f16c754a173fcd13d14f883","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"e721faf049d1d0d07a4c393367baba13c8426271abc70392bdb6870fcade4247d39d9d5107ac686726573de813","nonce":"7f16c754a173fcd13d14f884","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"b739db338a5f29e723664e9464533ad4d1771351e3d7bd950aa20c4ecd1a9eabbb6af9448980bac1cadd83988e","nonce":"7f16c754a173fcd13d14f885","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"49d35279dedf6d22be26bde7562d82d91ceb9a6808f9dfd456ff1c92ff77b3e1d64bc1bd3d9580247c4bd61bf6","nonce":"7f16c754a173fcd13d14f886","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"1b720d012a81f2d15443587f2e1c805ef65b60a09dc5776825175aa325e36d38c13b6e5c0c9c24cec3845f64a5","nonce":"7f16c754a173fcd13d14f887","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"b3f206da3ee89d41bcf154666c379267931000f50d172cb5a6b43b0b9021910669403daf4f63f4d9893a06ad01","nonce":"7f16c754a173fcd13d14f978","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"40b45cc28dbb2db11cf9e2ebccecc3b1f84cd7cf0818de77fcbe8c930b302411"},{"exporter_context":"00","L":32,"exported_value":"1879b1b4113fdfc0211b1d03d2cd320987e887dc6815436289083e57e63dc098"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"02438d80efe54328b1a2db44026ebc1869bfb190d8164f91d7457623065666cf"}]},{"mode":1,"kem_id":16,"kdf_id":1,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"9f1b6497ae7d50aa847cc71283d6bf3c3a4f28687fe19cab7a83d7e08206b7ab","ikmE":"6470e9c5f96201e747fac5e53e89a3ec71d7dbf6b4ce89ab30cb60c1a2c1376b","skRm":"fb389576827bcc122407e70f30dd2631e7572527dcc908537def4a78205d032f","skEm":"9dba601a744e55b24275d550fc173f77503332ce61d3c974e2944ccd8d68e445","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"04a459aac3f085c18c74d7db44da258ca513a51af1ceb738e5ada24461ee0ba1466a87f2c072239adb2bc0dc1463a31a5755cc761101b9a3e7d93f8cddb6f56e3b","pkEm":"044580890bca9e5e8cce209f3c9c1731373012c18c4224b99f21bd844789ef9646d97a963d9a2f78ce6d7bfa5a8bf01f48f4b4df184f527b072782f46510c5e9e4","enc":"044580890bca9e5e8cce209f3c9c1731373012c18c4224b99f21bd844789ef9646d97a963d9a2f78ce6d7bfa5a8bf01f48f4b4df184f527b072782f46510c5e9e4","shared_secret":"aca9a7ab75de7d7354d8bcf0028a00f306581a216cb171af7f20295470b656e0","key_schedule_context":"01b873cdf2dff4c1434988053b7a775e980dd2039ea24f950b26b056ccedcb933198e486f9c9c09c9b5c753ac72d6005de254c607d1b534ed11d493ae1c1d9ac85","secret":"46d37126521f0de3bf90be29b5e5ed1b0f57a7aaee7a66b7705c82f6c70f2266","key":"be7eaf974cdf589e8312169a03155b84","base_nonce":"4250c1f06d8a36fb964e5b86","exporter_secret":"e9c69341bcdf8b4b37756ff53a4fd2f6d5c8b1597fbfa1cf78e9af3dfeecb093","encryptions":[{"aad":"436f756e742d30","ciphertext":"b384d901dba02c6052e2ffe957f6332a0e342108e6647d2e7b2bd0b7b69f49e27c8f0f5ec19ca537550618b872","nonce":"4250c1f06d8a36fb964e5b86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"a1c1c47021c2c429cba30e675de4d1181b88c93f02ae4bdb38494c9912a3177b77e21837e64b760361699c10ed","nonce":"4250c1f06d8a36fb964e5b87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"2da27c295fae23648d8f17508e0774ccb739b012a054a598a813767e74c0e944edfede921108f60ab1643094e4","nonce":"4250c1f06d8a36fb964e5b84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"ede82623d61820b5e719fe92e97d255526e214065692404bc401b9b3b7bbcbec8acfbd3f21e6d9d1a88d34b9e1","nonce":"4250c1f06d8a36fb964e5b85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"613613a4dff2f8e92eee91ec7aa7b56f9956bd2aa0faf2be13502aabb56469b53cbfb9edb32be4a06c42a7144a","nonce":"4250c1f06d8a36fb964e5b82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"ef853ae997a83ce29fb185c8ac52f3f280122a60a85a174692083459abc0008d67ff33fe31284fdf3b29d4fb65","nonce":"4250c1f06d8a36fb964e5b83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"a87df97296e8f3362b19f6ded6b939bd5a2914c846e008dfc9138a7d9e7c609798ad7046ab2c4abf590fafaa9a","nonce":"4250c1f06d8a36fb964e5b80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"35a1b0dd4268c6dab1a2fea96f1585d5a12dbc0d00f1b38aef62b7e3f74070d88ddca63b3b409659742b07cba3","nonce":"4250c1f06d8a36fb964e5b81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"5cd9316f0e655bc1bcd3bc1ec9078e15a1be2e1af532ac4b41e2161a347dd31fdc4dab36de2f3615063efc341e","nonce":"4250c1f06d8a36fb964e5b8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"8e9849f8b7f14196cf767363187e3dbb015495810e2bc923557575ba23474a5e7666ba7f1c32b2dc208dfafc7f","nonce":"4250c1f06d8a36fb964e5b8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"cab4bbe6a3b687101d0bca76dc1efa772655476d81610c0153962601f7962e13d70df22b7a17a91e64ab75a156","nonce":"4250c1f06d8a36fb964e5b8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"92003b4c006bbf66e5998007c17f1ebea74a4e439beb47f5a35ae224f43f7f4907a510379dca4a4861fe3540bb","nonce":"4250c1f06d8a36fb964e5b8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"2b069246fedfb86530d36ea72e0d6b49016f43e61c90b87bdb05b7ed46d124e730197a755d64432cfcbe8dedc5","nonce":"4250c1f06d8a36fb964e5b8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"827c6b41c47c848d8ebfd2895831fe17418a531dcd07f74b22e159c6b0d903e49b6ee1e9f41da2f6087b328de3","nonce":"4250c1f06d8a36fb964e5b8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"3f426e641d56521d2029ee50d1340059f83740e5c1959b4dab43d6d265c43e9046eeffae1ed3f265f65cb02451","nonce":"4250c1f06d8a36fb964e5b88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"b1fc565bc6cdf11a748b5e55d26b752f863e264ecb621309c26bde070623e447c465338f3743166c3d501188e3","nonce":"4250c1f06d8a36fb964e5b89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"28d6aeb55c13ae6481c6edafc3f7b29c50eba97bf5a72c99527a3210cd30077d8dc251df8838e9efd31d05d44a","nonce":"4250c1f06d8a36fb964e5b96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"c8de51299a94448090cd79d98a974833dac541aa889554d7aedb1140a01ef3e1280fe00b60e288bdcbef0bfe7e","nonce":"4250c1f06d8a36fb964e5b97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"33869fc33de0d718d64c42512dcb282f114c3c0ca9c611744084edc3483c602cc9465810098f5cf2985479e9f7","nonce":"4250c1f06d8a36fb964e5b94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"5416d15331ab6ef41cda58dc3ff18db4953c92151156aeed678b54bc7c2a6ee684f2141ff751b0f7fcec38d7f9","nonce":"4250c1f06d8a36fb964e5b95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"1a1afa2a01a75fd40a948f1bebb63d3137ad1768066808528e4b89ccb61ae01a9bb30e075f5f41e51e25dc6357","nonce":"4250c1f06d8a36fb964e5b92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"9054c85f12db40f0bcac8fd6e157abf91e2bd0a16ac4737ecfd89249a64f72d7714268460a9abeb404065d0743","nonce":"4250c1f06d8a36fb964e5b93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"8ba54979a9c7c4feaa3352afb0d9c9934b18b3838f27e3aa46cf73a6c35c333029cb914cce4b59f515352005f8","nonce":"4250c1f06d8a36fb964e5b90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"c1901da1c2cd85f7d1839b013fe481d502bce0cf3b1d7f3a3ce86414583e65760d17759f1d93252af4272c401e","nonce":"4250c1f06d8a36fb964e5b91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"343b279b15627a03fee825c6643ce149a3a3bcd42094aedb5121df370a6d9262646059ae062c8d12749f84059e","nonce":"4250c1f06d8a36fb964e5b9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"bb156656137c522d0a1b74e9ea04bc1ef5b53fe2a42ea36a93bb304905f4757c145414c0a9f2c0cbde4435c062","nonce":"4250c1f06d8a36fb964e5b9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"5bc27c12f0e1e125c17bb6981c3685bdd8061ac47e7f9a69236aa783a8c23ba148ea92d57db98aad44f9ca0702","nonce":"4250c1f06d8a36fb964e5b9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"a1f5d52868f1b81bddde0b1f3d281029ff5eadef7623ff74f00d7d65473e75001101a16bc32a7eacf8d72d5508","nonce":"4250c1f06d8a36fb964e5b9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"f6443ded3c14ac86aeda20eeaf263f390ffbb03a5b36160d4c68f2c03c803af8d0dd4c60959f8f2fa4221c872e","nonce":"4250c1f06d8a36fb964e5b9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"467a237d18d526661ff70dd1a376c76486e0f28ac4d6dd9a925037f362af03fad5d2a129fd0fb4d60a0f0d5da5","nonce":"4250c1f06d8a36fb964e5b9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"d90ce6d03644ab1f81e7fd306a476e898ba95082c8e59defe350f73067c40422ade44be6f149757bd39467ed03","nonce":"4250c1f06d8a36fb964e5b98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"0ad83e1dd9f0747f108a5cff3ee456a076f9db6c3b0ddf225d48deee03c0d784b737d7fde483322d488a5b5cf5","nonce":"4250c1f06d8a36fb964e5b99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"11aae302dd68e0e523ceb6d2df0985643b632b866d503e74eaa575928046d15fc4f5333fb7d15626e7b92db534","nonce":"4250c1f06d8a36fb964e5ba6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"7c8017f48a7fdd24923fe159509420feb3056632d5fbcd952b5296ad39c013b79d8a1d0dfe5c35e5fc440bee11","nonce":"4250c1f06d8a36fb964e5ba7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"6031ae20a15857b027793126c2cd501a501312c67f6c4accf1bd73de43a64739acd9793545c2cb50b3bc4283c8","nonce":"4250c1f06d8a36fb964e5ba4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"17575a3a7ce7f2da12dd3ac4f262b8fd15af421c0af786b9a5a7d3cd6d7f607a759f19e3ed46a598eb28a328fc","nonce":"4250c1f06d8a36fb964e5ba5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"fa37f4ee1f28e1a24d4f84268279bc38c3ff1b6b75b2d052cbf7e96607ff1e6faed08250234ad1c7706446326d","nonce":"4250c1f06d8a36fb964e5ba2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"fac9cad2983753603800cdc014f04678b132f27a980869e1647824777e700b6ff4c8dc124e8a6cc132d000e631","nonce":"4250c1f06d8a36fb964e5ba3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"13c7468895db4f85d21778c6609f06250eba807b96e774996e76e569e01e701566f71ba8533956a86fe383df92","nonce":"4250c1f06d8a36fb964e5ba0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"8d4a38f1590fa33cbdfaf939773ec8fdaba619d1ae686c7403fb65807863a8fe1edd6da072c8bb68b396ba0447","nonce":"4250c1f06d8a36fb964e5ba1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"95de996d18816b10eef713a2484397d980ffbb43c609142d11a0c34703840b0d4fabea3b36b9289d2d939a49aa","nonce":"4250c1f06d8a36fb964e5bae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"f7fc4d716e7738be1de331ee8828378611af63593881679e51ab388275274254f77225604c9eada7626f5553f8","nonce":"4250c1f06d8a36fb964e5baf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"1e0e2f63a452e637da6c23feeff55cab1272eae612e6a9688a8f345faeb96c1b775011ec4d05b97e79d73cb2a6","nonce":"4250c1f06d8a36fb964e5bac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"fc5cdd408dac740a2dca642b88f753c60846baaf294c5ee3bcf55114eb17a53afc7f75fa317811c29a5cd43aa2","nonce":"4250c1f06d8a36fb964e5bad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"51b22559df443c8f527023357ed0b0ad4058bd20c7e773fa60e6bc007b8c7305690c414638c83c9d8d0cfcdd5c","nonce":"4250c1f06d8a36fb964e5baa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"d0ae6ee3fca0a1b461f709ce16c137048487b3722cf30f669df4694b22ed340a84bf2388ed892495ab97354ea4","nonce":"4250c1f06d8a36fb964e5bab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"c8c6c8b379770625e171cc0dfbc7ecbd19f756a6d1b869fde9c3ce1c7dd9e4bb844f58a6adda5d8c8916a38f1e","nonce":"4250c1f06d8a36fb964e5ba8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"ce403e1f54631ee73a1f1ddc291fc6057ece2299978b4921350cf24f937f3bacbbeb91e2ee8c28ebb228cdef22","nonce":"4250c1f06d8a36fb964e5ba9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"364d0be28e3bb68d63f2547e2d48685821103e6e5ad00dc948acd4ac927c00332586cea6bd26dc8391109d6f7e","nonce":"4250c1f06d8a36fb964e5bb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"80e93f3367ef450b4df0fc10acbb8c0e040650789d158cd35a06156c9ce47afcfac62699c7c83e4db1c3af7d7f","nonce":"4250c1f06d8a36fb964e5bb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"9557e9b5641851ed860e8bd68e27af72762dbb03adf1c33ef63d7bedeb8f16c795f7062b9939bd7db10ab5e2da","nonce":"4250c1f06d8a36fb964e5bb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"e46f71e16757e51458638c9bd63d0c36e6e7f6c0ffa5668e7022acfa640eaf4695f337be1320d39edff745ab0f","nonce":"4250c1f06d8a36fb964e5bb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"8c5b2d66d9de9137962be10d82f002cb75fc5149190b59f13131b4ab0a719c4c0fa1899d3e7310449f4f5cb88b","nonce":"4250c1f06d8a36fb964e5bb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"dd1ad76a086f42f110f6ffd6f8837eb5b20339e3e5d5bed8b0976ab6630cf4e37a6a4beab6aaf56a52f40b7149","nonce":"4250c1f06d8a36fb964e5bb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"48ff858edceee4eb2dfed4ce805a4e55f939a756f5602a200f54d7cb9d972c6f657c40efabc2354da53ef77db6","nonce":"4250c1f06d8a36fb964e5bb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"babfc13d4e546922867495ad305d7f81c966292edcc84baed5e2a9ac3dc880e3456263b7b20d0f4bb45b7471ba","nonce":"4250c1f06d8a36fb964e5bb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"18cfd596ccb9595bd3cc8e6f24a02518956dd5ec62b6c8381afe3a3a00cb8402281fb47d8c373f66baad227c27","nonce":"4250c1f06d8a36fb964e5bbe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"ea4f78cf3e2027473cbdf0062d64743644b6116fe72dcddd7e462fdce8463fbbdc32b7906b947a170e36ede3fd","nonce":"4250c1f06d8a36fb964e5bbf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"9486c20c2683ab1c61033254a537dc11f3e0d21a9e6fb79a6cc813b783111d8cfc1ee773e55cd8aa9a3b46e7c9","nonce":"4250c1f06d8a36fb964e5bbc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"52a9905272e7b08ccff02048d5e3b4d141a99c022e69a908a37d213b98765566b455e18acd542c19c164a76209","nonce":"4250c1f06d8a36fb964e5bbd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"c2a280ad0fee8214dd2da8f934414383ed86ed59ec82f80d55db824ffe62507a0160eaf2b9bf1c474a3b64f9fc","nonce":"4250c1f06d8a36fb964e5bba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"d25c0cc6e1e521330993518d2b172bbb2915def71042ac242c15392eb888275785386b6307ef6a7893d8c0563f","nonce":"4250c1f06d8a36fb964e5bbb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"908097b5e37a106b9fb74ace7a25a579c3268b7c2335f372792153751d59a81aa73d4d6a794f6319f1bdc67910","nonce":"4250c1f06d8a36fb964e5bb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"2442459c960637dca86a9effd093b644adcfc3704683ee2787f2983758e8b81ee3e6312a723cf8ca899825ddff","nonce":"4250c1f06d8a36fb964e5bb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"df4ee4a8315101c8ec82f12243517b18e8b178e3cac3e641d814dfd27a17b87654c54cced05f831ef8118479fa","nonce":"4250c1f06d8a36fb964e5bc6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"d30fa6ba80df344cfd65d500f979b256fc5a1e159e56e3fc7dac8cc4a80d8beef0832a65343fcfdc5b2f9d3beb","nonce":"4250c1f06d8a36fb964e5bc7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"510657ccd479cc76d47170b9ebdf266c6a5fa939e15db1740204a990cd5371249840b1ddca468b2f93218ba520","nonce":"4250c1f06d8a36fb964e5bc4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"b5ca0dad80c3ab8ac78b7437b9d601e381de96c74f27e191215ab46474f2541ca6523c69b5c09a3a7ea1e414d8","nonce":"4250c1f06d8a36fb964e5bc5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"3852299aff7f86c31877e162b444a1f8298cf9b4bd534997ee2ff5033b11795bd58427a3cc4a745ab88fbc7f3d","nonce":"4250c1f06d8a36fb964e5bc2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"27667031cd060f010e6d3f15a8f128c1b594fa36543fd51219af197510a993267752cf83487f6ce6cec7fa9252","nonce":"4250c1f06d8a36fb964e5bc3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"c040399737abe8e7a8a5c093bb3841dda7cad674cb0c8e2c6e7bd29eb37ad4880a5d702e8096eb81726bb13a58","nonce":"4250c1f06d8a36fb964e5bc0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"8ed67788583858557c784e1776c74e55f9f0c2d1c9a044be2b90ac943fa803745dcab1a552138e8449fafeccfe","nonce":"4250c1f06d8a36fb964e5bc1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"07ce04be09180615a092d80d8724aeb589ea138a3aa016fcaf1229188af5b42dd01c5959b17253e492f4b5f69d","nonce":"4250c1f06d8a36fb964e5bce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"d6095fa9e16d6242f5f5c019314c312260a341b4cb6642db9ed108542e8ffc67c6f37a03529fb32d77f53a31ab","nonce":"4250c1f06d8a36fb964e5bcf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"f7863f5fad7406033b3c24cc6f30ad773eeecb7582e0d729bf063208df128c74a18a1f6302979e53b57d33cb17","nonce":"4250c1f06d8a36fb964e5bcc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"6c43692a406ba64e4edc006dc7918235d954f54c05a3a9b7e66ae6bd079ccebc8bc8c30b05790554af3e7f800d","nonce":"4250c1f06d8a36fb964e5bcd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"be209b8d5e0fe8c8b27f3ebe4ce4c6a71292d467b4ff6bbf56c2994c8bab1f5de5d63c89e9541d141df463ca5a","nonce":"4250c1f06d8a36fb964e5bca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"876d560dcc890b489498b5be9658ace6d9d5401a704114b424474d2e539d0ba4aa5c85a387e040df61b10c3652","nonce":"4250c1f06d8a36fb964e5bcb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"9a18d18f31dd02ee2ffd2c5c64f55e8e028284e8fc88cb2c882b509095dd08444390fee49eec33058ef184317f","nonce":"4250c1f06d8a36fb964e5bc8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"87a06c351000735308cfb5ca8b3fe47b4f04cb9f26c942879d702613a766a085b60a75515693f78235ac2bb016","nonce":"4250c1f06d8a36fb964e5bc9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"cff531369a9cd9b6dac2bc63990a044c3edcae9da131a2f50da11bdc933f49f8a453e27f645f7076c1547b6ad7","nonce":"4250c1f06d8a36fb964e5bd6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"efecfb4ae89f2588dee00e70ea674f990caa03b7ba9cbd150277f28ce2ac8db80048f937b05b7c205695d9be6b","nonce":"4250c1f06d8a36fb964e5bd7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"e30daadb2e86db1729c9a10adfc545d193d1db782e2837da0735e4a83fed9ed396f79b138aa304ca2e25618a70","nonce":"4250c1f06d8a36fb964e5bd4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"cc6daa9ab05711f5599bb147c005f1fcba60dc92ed80a2c5b62bc8fcdea239a8439b2cc7af445df82d8957a29d","nonce":"4250c1f06d8a36fb964e5bd5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"9f76b73dbf178a3947687aae87de42faed927c82d682cc3e7319cf01c9f8d8e6665c8a9e141248d6a9209a802f","nonce":"4250c1f06d8a36fb964e5bd2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"aa86b450bc1e74b066a18945aee12c8ae3d43b96319d77b857ddb28c2f17fccd329f13c163c0b69de8ff884786","nonce":"4250c1f06d8a36fb964e5bd3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"597d2422a9f17fa1f7f25de0f2af6095a5eb574f63f268b30c7796f9b98386c236d6dfe77b342b9cad156e6de9","nonce":"4250c1f06d8a36fb964e5bd0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"7bb6f76e594e4ad7a5f6eb11c533159e612cea71d54115f842605f8cd86c2bec381242cd9f23e60ddf43163e69","nonce":"4250c1f06d8a36fb964e5bd1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"42dc3eaeabd8440f99d7421e7b9b07177fcd280b0cbce0ce7aafd0e342fa581573a6e42c9216fb004477599127","nonce":"4250c1f06d8a36fb964e5bde","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"1c001369360e5d0d2636b560d3794ea0cba71c23b8a0daad1c6c11670c57101590d3db2126bfda530efd8a8ff4","nonce":"4250c1f06d8a36fb964e5bdf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"de0e267ddde2d881f85039eb3fecedbacd0ea8967ba589c84b0bb31d2fafe69bde94fa23f4763cf0bcd6d8dee2","nonce":"4250c1f06d8a36fb964e5bdc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"21cc8ad004e8755534eb5a51c5a8d3a8e6168ce51b4d6b34aa6ef991d825b44a68a97d49354535e1efe1b6b628","nonce":"4250c1f06d8a36fb964e5bdd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"1a459b5eb203d3294f2c30b68fbe89d2e798a97490a90b6e81bed9cd52b6694664453b2cf7a25a07443787ba62","nonce":"4250c1f06d8a36fb964e5bda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"92cfe794ff0faa1fb160a2c85a05ee9d9d27404fd2cc89d433629d5806b40a1bd1ede656ed48a9ac1a42ab1bce","nonce":"4250c1f06d8a36fb964e5bdb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"73c23cf54b4c03aa26a7d67abbc7666b9304fd8daeabb3a9a640a6daca92507da78d5f04754a9978007c1086ef","nonce":"4250c1f06d8a36fb964e5bd8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"f6cd0f54b48c1c9e5ce83bbb40daf5b3e5865606f7c37c023c848a6d6e9710ec3458aaf480cf4c5da63f756dce","nonce":"4250c1f06d8a36fb964e5bd9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"d14bf1c9885c42fdde22ab031314df5b81fa5dbf635a0bea25eb9ce20cdf347e0b772fac01463066c29a67770f","nonce":"4250c1f06d8a36fb964e5be6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"65e46cb2021c7746bbbbac2ee7fcaebb3891bdc379e9b17588eb9bba4d1020acd4742632bad59ec5d2e650a46f","nonce":"4250c1f06d8a36fb964e5be7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"f6f4671738a0ed6e5cdb13e45e1494adb88daa5eac68f70262f2ebbc60c713b9c87e9d6209ce4ba1f41271bdd6","nonce":"4250c1f06d8a36fb964e5be4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"bdb3ecf8c55fb29c360984f9a02db3dea68bfa899482f21ccee4f0d039f0467822d3befa10cd027e4250bda6d1","nonce":"4250c1f06d8a36fb964e5be5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"c90fd337e39b5f4e78a92d40a0512044516a8f7e069944528ac7d4e131574427d54b3f691d8c62cceb53af2ddd","nonce":"4250c1f06d8a36fb964e5be2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"a54d80a6f887be5f864d8f33959c6a33ed868bbd4451cac6e302c7d94a2c1d6bc6e89abe83c91c10049050f5f8","nonce":"4250c1f06d8a36fb964e5be3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"a65825e1c539cddcd7857a2b9f347ddd53b037a8c46b7897c7e8ba003a61c86547e5648c07fe9f9692d1a86d57","nonce":"4250c1f06d8a36fb964e5be0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"862131439b6df8725aaef367ca8a2696eb3ef1f3dc2f226e72b3bcf5095a88af30cf692a660741853d43a10fce","nonce":"4250c1f06d8a36fb964e5be1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"ea3b5ae0feabda8bab8642d0e6631dddd6caaff4e275b7f186a40be5a171e1e0bba1d2c0a53829030e15dc5823","nonce":"4250c1f06d8a36fb964e5bee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"db3ed4cd4b58ee4c1eb67904dd5ae1c29dce0e8e15255eb6aa12e97c22e7a1b5e00d5b52df3958a3eb5c684eb4","nonce":"4250c1f06d8a36fb964e5bef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"fbc18b57a03cf16ee5dff18f43fc9063e858cf806b9095f8f18f4deea93614432fe36506cbfe8b17d68a25c53f","nonce":"4250c1f06d8a36fb964e5bec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"6199cc70b8590f385d767bc0a6ea93aaf2b56318134ad83b928660aa558c32142d26015fce8e2e2b720c225055","nonce":"4250c1f06d8a36fb964e5bed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"cb128bfed34d82d8b3cda16a6ee05b1333753322f45f194352ced8f8e93d3520ffb338687787b8d87c7fd26875","nonce":"4250c1f06d8a36fb964e5bea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"ec3dd9b1c7fec43d3411949931b820ca357fb72de321d9805005aa11ef2fe498f73d8dbecb32df77b31be6d678","nonce":"4250c1f06d8a36fb964e5beb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"e63fb8ffee74f811857531de4e63518e7561753d18e7cc2552e5cbe570f3bb4619cc82b39e8b2838b169b870c7","nonce":"4250c1f06d8a36fb964e5be8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"e423c5907c2b52591ee9763a3d3abe34b7627782db64db2152263ff1b25909d86937ffb5e2e905db5f5487bea7","nonce":"4250c1f06d8a36fb964e5be9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"bf04be4abf61941172b79ea61cfddb63b2031791e7bdee9f4b44ae79a3bbd9910f4c460e5db39df381c4f95b1e","nonce":"4250c1f06d8a36fb964e5bf6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"513086e17d2e44315894e9e000ab6ae3e67ddbb48cb1f110c2472a8088b2a632890506dc16003239d5da245e6c","nonce":"4250c1f06d8a36fb964e5bf7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"c16c081d461499140bc1bb05e8b92dee1884497d5a4a1921913cf30595a576345e14439ea3fa5c064316fb0113","nonce":"4250c1f06d8a36fb964e5bf4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"009839fae96b3693d103c18413a54bbdbd41d62df6b2f7c4d78d517bd55ca7cb43ce0ff66b69a66e3d0ab914a9","nonce":"4250c1f06d8a36fb964e5bf5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"af9d04bc70c45d8e364ee805aabfa44f335e89fd227f5859b3b015e2762cc5df003ef7671f778c55d91f65595b","nonce":"4250c1f06d8a36fb964e5bf2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"9d47ee08af9e013dd751988192ca4a6ca77d0c794d7c7c199560c837aeb2bd7f59b6038394dd2a799382911e16","nonce":"4250c1f06d8a36fb964e5bf3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"cc0871cac5cb88669d2e8454bbeb07ff440666d4c6226bf8fa835739b3a75746623cc4076e854c03e8922cbb03","nonce":"4250c1f06d8a36fb964e5bf0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"c2682283b6d042624cd374c4961cd1f17a65b623c598ed00dfc9df7a4333c98e431d6d8ef15c236652971ee5ad","nonce":"4250c1f06d8a36fb964e5bf1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"23e37363a50d65d5ed52ba8033a1a105cca5df362fc9df8ab38bbc1af5c9ca4b1797523098f09c3ff5dc062f6a","nonce":"4250c1f06d8a36fb964e5bfe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"037c0298fc3568096d32b3a9a027a4f9ba8bf203c5fd3d1791c4539c07d31548713c579b4e69dd8884ce3fd276","nonce":"4250c1f06d8a36fb964e5bff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"9b31540f9ca524cc328ff43af1eaa99744a8751ee003a74b8d265de7d346bce7c9f30587e5ca57ee56d00f39cf","nonce":"4250c1f06d8a36fb964e5bfc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"45d1d1f6162b23ec8c05626edbe9030eef1ede6defc67c20e2e4ad8c5ec8936cf830efa8e2642a4bff5ed62366","nonce":"4250c1f06d8a36fb964e5bfd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"5dbafdaa8cc4aa10e69c80c3cc56931cc12c590f87af3b88fe19054017220c542b2229cfb167d3d6ee9dc792a0","nonce":"4250c1f06d8a36fb964e5bfa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"7931ac54eb4c2e6e018a94419ff4b5610246fee47e0fb65cdd8e42104d2392d6add627a4786b3c75c7f622d62a","nonce":"4250c1f06d8a36fb964e5bfb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"302054157cf120abb18279fbd288da6250ef20d765b447e21eae6542ab2bb16bcf24b7409a725a851fdb1b938a","nonce":"4250c1f06d8a36fb964e5bf8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"368786222b1237ec3e142f0d64b1d1f55089d06d75bb6248a298e9c3599a5288762e848bd9a22d193badabd0ff","nonce":"4250c1f06d8a36fb964e5bf9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"9ed2967e949f284c72bb1ead47da835f1ee7b6582f7badb44cb5ce93ede2d5aaeea759ab53f4df51fb25a1afd6","nonce":"4250c1f06d8a36fb964e5b06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"45a046c39aaf30182d5eb7cbc0b457d931a6b00b19ed4e5e3c5b55172e847eb17a2ae160af8ea508d743124893","nonce":"4250c1f06d8a36fb964e5b07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"d9a1928f904577e91aba22a2ee6199413828a04f2a7aa2e61f11af63a052ac78a8852d93ed8939685f187fe405","nonce":"4250c1f06d8a36fb964e5b04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"f27215fc8df8fcfd99df0b06333289edb70a65150661b467a7ffde31ad43a5c071e1fc3d5ab69d1b3407457e2b","nonce":"4250c1f06d8a36fb964e5b05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"667e598d00cb4b498b8ea23478df54478e2103cd19fc997a98918004c800e41943da52bff73648f305c96d0bed","nonce":"4250c1f06d8a36fb964e5b02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"0a0c6d296fd30901e7dfd2bc5d25b54c21f14a442078d89659eee9bb84b3cbf223bbccad6a7df167ffdb7bb39f","nonce":"4250c1f06d8a36fb964e5b03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"248c5543774029799ce7ea61b55f41a7f59942296a236e3c1e08915894b3f4baf90e88b54e4c9949a520acae64","nonce":"4250c1f06d8a36fb964e5b00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"d8217e2e76452c3f7b7b59b1c6432e59529098866de8ad40fc35a0db91444f269ab430156edb84d0b44fe1a03d","nonce":"4250c1f06d8a36fb964e5b01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"ac7b7f49e02a8ac8074fb7a128000b12b55df6972da965f4c168fa4f1698aa954b8baaa2acb43f4c4258942b99","nonce":"4250c1f06d8a36fb964e5b0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"90064dd49e20093ff12a088e779f6c45a8d0a69fa94cff3e3fdfe499c99b61a1a07479ffb1864de7bea3591c88","nonce":"4250c1f06d8a36fb964e5b0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"5ce5bf5aae770c41851e0c6ab62f99f007511f4fe7bb8a3dd6cd24ef2b688d7f633693b99291dd3d8b6e243ef8","nonce":"4250c1f06d8a36fb964e5b0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"824de53e9bfe4f369cf6a94d0320ea6628da1b8730695f6aa29ee523d8a40b603e0954551f7e10adf30406b39a","nonce":"4250c1f06d8a36fb964e5b0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"50612feca15e491c0cef556dd88c4c6a33791ccc37ab8d939062cf79163996e272685f4f4846c133c36a69cd2c","nonce":"4250c1f06d8a36fb964e5b0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"79a57a5dec338ebac23bde0909a850e2888b54addd3202a6e92b73e6e4d1dce3d662855150f6f154564ff4d337","nonce":"4250c1f06d8a36fb964e5b0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"c099e63ef1f08056b000d25123f5d11d94c6339216421a15974f9af853c3b176658ba30dacdfbad97414ac308e","nonce":"4250c1f06d8a36fb964e5b08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"c153429f18e8726ec26dead05e3f8ae484f08aed29532c3ef78609e82c848c086856cfa72389ed251fbaa6d245","nonce":"4250c1f06d8a36fb964e5b09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"9f1ab15ab09f7dad2aa5d57a22f5f4f6a7466d8d03e7082d2bd1d9b02d2ee4a28bf06408089215e1a9de40d0a6","nonce":"4250c1f06d8a36fb964e5b16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"42a05f09f2c27d786ed8110bfad43aa8d532c353851ffb592b8df530622360445c95703329040919400a9c27c1","nonce":"4250c1f06d8a36fb964e5b17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"046126241e26f463aad96c45fb1b9979e2a5051b089becbeb87f0797e5eb09e6674e3b047be70601c99e5b5f63","nonce":"4250c1f06d8a36fb964e5b14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"d29d5ae9e94b1bce0daebe719af0bcef2e93f5968302fa78f3f6a90dfb21f5ae3104e38ecd952b8fde6b86b93b","nonce":"4250c1f06d8a36fb964e5b15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"289e13ca6646dbe7992a4518c43f8749de7e7b92a4ccb97a9d3fee5c3aea92d0865a94e39c066ff7ea7d06a090","nonce":"4250c1f06d8a36fb964e5b12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"ff705ee6193122cc73093ccbe6b08b997f67b86eb10420d9827fb1945c3c26ba26a01137979899d2ac5f686504","nonce":"4250c1f06d8a36fb964e5b13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"013927e9e021dcff33eb0e9e8fba4800ef3fd03b0e38dbfe8b3dbc3caf2fb472627509266966b55abe1245824a","nonce":"4250c1f06d8a36fb964e5b10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"9f5a78d0729a1af0a53dfe0bea9265b7f3beebc7443cdc99ef9cd84f41d477515a91a58a7f74f25694978f3d5b","nonce":"4250c1f06d8a36fb964e5b11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"fd90477fbc1fdc647c19abbc6df1a4966b59432b438f6d505b3ea5e0d0d42245576af6dd7ca70cdb7e00aa55f4","nonce":"4250c1f06d8a36fb964e5b1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"9bc87f30dad61802ae52f1bd1f76c05bb1243cf069a492bfb3bfd33fd46d0f9b961c7b9d11f516b65a9177327c","nonce":"4250c1f06d8a36fb964e5b1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"199f6a8d1bc8ec0d57eeeb00328b559342d0cba0bf65f375d1e5d504cf9725bdba36a9ac4fdf922297709d0189","nonce":"4250c1f06d8a36fb964e5b1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"af8c53cd0d0db924ec1216afae06e0450db61b5ec4ee919664c5d420c959bebb0db51c2eb4a92b51759e1f7681","nonce":"4250c1f06d8a36fb964e5b1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"7fc074036a5c2e95648f6381821908a0720c7c1d0ac8ae03bf8a9333ef9a8e81981eab77e7749f6312ab5b74cf","nonce":"4250c1f06d8a36fb964e5b1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"11f13c3ef74c87bae151541854e0c3acbba41ae4eaf10d10c167d807ff488459bd9fcb5b0a644d71133472c78e","nonce":"4250c1f06d8a36fb964e5b1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"19f556158c936ee5d250c3439553e0c984e6362280aea920f63dbface01d40ddb0ff616233f46a1943ce9147d2","nonce":"4250c1f06d8a36fb964e5b18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"d3652c471d31516115aa9d62fe6a1dd0c7e4d553572d20ad84e3d1335a21bb2946e0eeed6cba045eb2e7bc7e49","nonce":"4250c1f06d8a36fb964e5b19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"fbe694e7f254c35b184a42a9120e690d33ed811feb6f55bf9ccb44256a1657fcf3d3e69fa4cfcee55bdb3b8e58","nonce":"4250c1f06d8a36fb964e5b26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"79f8e776f8f9748edbd1e156cc921f27359d893041e06ea57e252cd824a9ab78d86024a0298dd3eb52e5107302","nonce":"4250c1f06d8a36fb964e5b27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"f00ac68698bed537974d06ff9d5659160ffae6f94389d1709e992a27509421ae885aed25121c22b5a10b6542d0","nonce":"4250c1f06d8a36fb964e5b24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"79ace26074c9a707405224f5605b6a58f9847502ed65e606f4d751128d850775b25f86fdbb82f9c42d2415c1f1","nonce":"4250c1f06d8a36fb964e5b25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"ce13290086712dabbb435fcaf4823f07f3a04c409d8adace6aaa5da9f47c751267c40b78dd20344237e187c93b","nonce":"4250c1f06d8a36fb964e5b22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"b78a8bbd87d5415518c6be9274ecf925a4e5ae327f6ef94fcabe1904497bf5b9c47c7ced2cdf213560d0d1ea8b","nonce":"4250c1f06d8a36fb964e5b23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"e08ce0fe703cb88a998291fc85733238d3d60fc48946da3c7998fa784a48408a208b42a847d045696fab855d96","nonce":"4250c1f06d8a36fb964e5b20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"0be2c1e20b1715e4e60ca876c9fc585a445cf37a4a2cb6ab14388e55c38fede4ee0e09245fed88d138ca74c57e","nonce":"4250c1f06d8a36fb964e5b21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"f830525bcccfce2de59975fa638ef508bed9edf5dc1f90e13a57c0d20ad99107c1f4eeb1d8e8b05149dc2be97e","nonce":"4250c1f06d8a36fb964e5b2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"b73277345effd019abc1e8153c649fc55d8549f491dba667811306929a9d8b24c6b1d892ff8c79ee22990583f0","nonce":"4250c1f06d8a36fb964e5b2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"0b3fb5180088eec245fb56bbbaa7a65b3bbbe6c5dc7119103bbe715e75602d2b812423779dfbc5c65f9e1e6a6b","nonce":"4250c1f06d8a36fb964e5b2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"e43b4fbf009cf05c5de1e14424cbd9fd22e74cc1e822315efc9b381e47cd8d4af65b8dadb74a54834e96588b9d","nonce":"4250c1f06d8a36fb964e5b2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"1c30dbc57e0df5291b57ec3c48c07cca347a4dd196f9a443066dbe47ad20870410a6c997bd9f57d17e66fa590d","nonce":"4250c1f06d8a36fb964e5b2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"df94a4bd43e85cb922cdd367772be99f11b696021ad355ac850df373f74a00726800ac624f67fe696524feb7cd","nonce":"4250c1f06d8a36fb964e5b2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"61ba7d97c8f708f1ed6dcee97b616153afe9bcedec6b01ff88f77dbbdbef8fbd8aedd248a291657417bad77c7d","nonce":"4250c1f06d8a36fb964e5b28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"74053d1c846df9af36ac69c2e783fc437350fb8f08053078185ee90559fd6c523e637aacbe09c40c132c40da53","nonce":"4250c1f06d8a36fb964e5b29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"37e84aff1d7affc669b83eb4c3a15557b8e44a9e5372f7906b7481790f34c65d57c19db4b54328d5efdca8d615","nonce":"4250c1f06d8a36fb964e5b36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"1d90cde32653856d35d6afe595da2e2df9eda87db4d21cc34042cb1b16c45889d2dd409fb4556b037e9122ddde","nonce":"4250c1f06d8a36fb964e5b37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"3467e1ff740cc545cf8b15aa429ea7d97837bd5bf70d59bcb2fd53ce420acf3569078d2d02286b585fe65108cd","nonce":"4250c1f06d8a36fb964e5b34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"0b63d256c93ebb3f9693a9b2b57b45d835672f773f131848a5ba82a1787d8c77f1e3e021a3d7daf3dfad4f619f","nonce":"4250c1f06d8a36fb964e5b35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"adec45942c6b6f271e0a75434567dc189ccff037c4de3d6c812e1e919bbf15bb2effec4262a5276a9ba7c802b5","nonce":"4250c1f06d8a36fb964e5b32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"c471fe669d166c0216b19495891978d2b71330b375eb0defbef59f4ae171bf9853d92f165034ce14bdc2dac4d8","nonce":"4250c1f06d8a36fb964e5b33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"f6d365e795797b207ed8d443c0cb084490c82a6dd39a7b02dcb8b2dc00a0dec3c7ac23ad14156da49df4b5ed49","nonce":"4250c1f06d8a36fb964e5b30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"5fd1fd7122cfe7fdaa1e6dc1710f78b3eb8a756eab870b35fdfbb0ab1082f4a83b9e69aeaa33d076e6637a383a","nonce":"4250c1f06d8a36fb964e5b31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"7c22ca0e82c8156c5db9db4f0aa4c6c2487a6d0c3d1ea18dc54eafdef32c75df9b41f6ad08289cfa73437e74c9","nonce":"4250c1f06d8a36fb964e5b3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"59b77e83c472c06a69b8c88e43808b9458aa470157a3cb40d66a45248d1ebc18633503d31cb3297750a3e5ccea","nonce":"4250c1f06d8a36fb964e5b3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"aa27765b59dd77acfe25539db611d453e550bc8042f345215d1d0e37331e56e24bc8d79f2cf0c81c2db9f9e1e6","nonce":"4250c1f06d8a36fb964e5b3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"677e6f244b639f35e950ff81aec94fb175e735407937dbbc13c8f942a984a6f3f8299799b60e4f2bd6aba17f02","nonce":"4250c1f06d8a36fb964e5b3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"38bd1961538356a33c4ca9ea53db4d4cf0d8517f2a120a0786dbaedbcfc6f4b50f44cd3d7183625cbbd2faf74e","nonce":"4250c1f06d8a36fb964e5b3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"a5f71e596a1a61c6749c5531781541562621ea35543d069845aa7501110311780756c3e03bdc8a627ebbc0f8e0","nonce":"4250c1f06d8a36fb964e5b3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"baf75088be0778d0797a76222d59d9d930353bb83e6915beb5de8956e1e5bc08db96d4639f4ad9908ffbc599fd","nonce":"4250c1f06d8a36fb964e5b38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"a873d8afe40a7c3b3428817a8ad2eef8e9ee08924d8e9d4710c70c24dde154b729b50f98986c5e5c2f9a540112","nonce":"4250c1f06d8a36fb964e5b39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"a55884038c7bc14109d1c80ea9ece57046c479c84de8ff108fbcaea00e3fe277156d992fa64b6acf2efa045d7c","nonce":"4250c1f06d8a36fb964e5b46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"231aa7bc6342f9b397079c3113461e9795ba9af96812e42abf0fe80a612771217c581c624cc7b1e034cda9cd0f","nonce":"4250c1f06d8a36fb964e5b47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"7c3b1cbc25465f88380ec361508713733ffab50833a3822dc6e9c2f562933f566537d6e44ed112b0cd35e295d4","nonce":"4250c1f06d8a36fb964e5b44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"66f62a60ed7b013ba214b91406ac8b3ed6488205d75e863ad9af921725b1fef2f84be04a38809f3c82929ccaaa","nonce":"4250c1f06d8a36fb964e5b45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"f49e1892804cee054f312c3e5c7ad09d6b15484dcb20070d796d59c129c97ebd54b1fbe4373f469eab54ee658d","nonce":"4250c1f06d8a36fb964e5b42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"713188ea92da88e57b60d8db7fac6ed2ee8fe189be97006fda1572bf8bc688d873ef361a64352a0eb4dbac520e","nonce":"4250c1f06d8a36fb964e5b43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"001ad96ae469bdb816034e4d42184a54f187b9e01cbc5abeaf5e9b0160f1926862af5711e80a754e9da8135487","nonce":"4250c1f06d8a36fb964e5b40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"dfc4475cd513d337016cf1ef46d5aeeb22eb382ea70ead401a70a637737b3fed00b7fa0953f1b88730aa869522","nonce":"4250c1f06d8a36fb964e5b41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"b1af0c675252c8157c709b2e48462d1fbd631f3a23c6e86afcf388ad44fef80911af01ae2df701ac65ae44392c","nonce":"4250c1f06d8a36fb964e5b4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"45e574c3c3d6f3967181c0b32e6f2b43be1b9dde4c201f75d73f3a07384a72695c833c70de165f8f1198b897bb","nonce":"4250c1f06d8a36fb964e5b4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"d99352b7ef0bfc03c6719f99997a66f85b7f9d88d02f5929f2af1944eb641704d7a93c5e1e1aaaee6f06900b47","nonce":"4250c1f06d8a36fb964e5b4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"eecac6f1bca28cd3a155f3f3b4e3432280a6d72bb2747f4edb364eb3aba5db3245c01e3c3770f215565bc89b50","nonce":"4250c1f06d8a36fb964e5b4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"f6f7b83d7a2e910803be6ee5c5900e082a6bb793fff30d13c22e3340f7f241ff0af978914917e98f9a728e9f99","nonce":"4250c1f06d8a36fb964e5b4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"563ad85f75f39f3fa1c290e0a4ed39c7ca050f19bae0b5f8b41c00d0ac484aecbdf2bc628ee64b9c0732d8f3b4","nonce":"4250c1f06d8a36fb964e5b4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"acd079eeca3fc0e556d63f4881110b4db2f6f1c4caa1bb788254c3c3affe1ab56798d87a2f8d7d480d92ac614d","nonce":"4250c1f06d8a36fb964e5b48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"1706f0749f0f4653cf3a9a4277c86bee3d252d9c273cbc3ea18321a5c1e416c59868cb170393ab17264cf2cfb9","nonce":"4250c1f06d8a36fb964e5b49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"6ba68113179517384ada0005263b7f114903c92df0dd5fa7b4331c41a5ef3265260fb259101a6808a4dff578e3","nonce":"4250c1f06d8a36fb964e5b56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"1bec35ff4667461497287d76f13627bc5c66ee63d202328f9f886a146a2f9c5207ea7be55b2b85c8c273f7cd54","nonce":"4250c1f06d8a36fb964e5b57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"dac22a07ae8a45140ae0cfd516d79ea1d9904042b2d1385510a911977946c3615d2ed6539a35dba8ab24aa8125","nonce":"4250c1f06d8a36fb964e5b54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"65b5940d5316548b70154ef8f60777296ce8dc293ced2e76cca6f35c351e5279e235955d7ef3185576bef4cb94","nonce":"4250c1f06d8a36fb964e5b55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"210ed301bb64cc39951d071107abcc564a8fc2639f5d22dd210faa2c8d5ac7dd4b292422d5228ce8417859f25b","nonce":"4250c1f06d8a36fb964e5b52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"7f73cb8ef4cdc0c5c2368098d4aa0e7013c5f6b92e0c40c0bf51fa7eea1ccc5090e7c5a8478d13669f75e0dd5c","nonce":"4250c1f06d8a36fb964e5b53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"68fd691dfad62e93f3638e8f7fba8b369d83150c3fc5944342465e2b55233719f1e36ea911c62e98fdcf0e2d2a","nonce":"4250c1f06d8a36fb964e5b50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"142b7018340a0c4ee42784c830b2608914f61077121375a7abf2acd7d837bcc0f0176c068f391b3e36c1663459","nonce":"4250c1f06d8a36fb964e5b51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"3060ad426c32d262e684dc063837de6d6bbe89afaaeb7daf974e5fcede62706df7391520f5a78a49df51d66fe7","nonce":"4250c1f06d8a36fb964e5b5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"9b9169e2abc92b7b14a3a31456016bb98ac0101fc2f0b0fe2f414da518d3b36fc70e0c3dbe834d68fc1ffbe328","nonce":"4250c1f06d8a36fb964e5b5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"c307267450c1eb96488f3c4d094002f8d26e5c55839811078604b54592bbfb2536d9c24dcc8daa1d7c786d6157","nonce":"4250c1f06d8a36fb964e5b5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"db65fd0b86ef91f7ef5233b1be535e1b87071bcab425a51c893c8a48387a5fae235a771d158b7545ee77c3648c","nonce":"4250c1f06d8a36fb964e5b5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"126f7b7073caa33876bc84e6c893d704b2670a319852cfabcb134a0f06545a02e1276418c19c1843b1540375b1","nonce":"4250c1f06d8a36fb964e5b5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"a688279eea3d6e88934bc5c8a20b7238e0febfb640b1837bf5573ff7d8fadd57992a770080be6632786e6a11b9","nonce":"4250c1f06d8a36fb964e5b5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"79bb0927eec8c596bdf834495f66ed9fba5c63f04f47c30f3fa6db45758816bfe2dd794fb59ff7a45df650f370","nonce":"4250c1f06d8a36fb964e5b58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"9aa9980ee7ff7245bc4d95eeb43522295f2805ef08f12276d102d1f893757aa96b6a3aaf268003fd83db751718","nonce":"4250c1f06d8a36fb964e5b59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"55d3662666ae3a3b75aa79050e98b92598a7047d5a9a8ed80025fdbabf127071289fe65d74b0df2a8772ec2d2f","nonce":"4250c1f06d8a36fb964e5b66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"953c4b32645421814a94d92e04a2383616dcef00820c06674f577ddd6da091dfad3877aaf303d3d3a098e3eb63","nonce":"4250c1f06d8a36fb964e5b67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"f0fea3c8cb5469d3795a70097dbb84997f694535716a97094e8428f9907bd30c857a5cab226dbc73e93e5e2132","nonce":"4250c1f06d8a36fb964e5b64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"ce2a7000394b1040dd11f7957cd7e60c04f7915c07deeef219c54836fe0b242f992b2b30b479be1ff92ef9b199","nonce":"4250c1f06d8a36fb964e5b65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"9ef73c71a4a966867e3db403c5b5728074e2dfc11541c079aac28038952b8ea0ae5974585ba696a58d2d7e6c25","nonce":"4250c1f06d8a36fb964e5b62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"15889eac5f73d18cea4505af71db55b155df5358bffca4d072adf9c055846c0de99f140788d3c2360f7bec83f4","nonce":"4250c1f06d8a36fb964e5b63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"e78ac8664e7bb4b3926709acefa9e3482138c3be7096ecc521255bce776d782720dbed3471e7c329eb2f520bb2","nonce":"4250c1f06d8a36fb964e5b60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"f21fc205f842fc6172d0455b0f1a5b26be69444f3eef10ca5eecabcae7301766e3b018886e9ad927ef3b1a23c4","nonce":"4250c1f06d8a36fb964e5b61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"edc41f7649f8346bdd9ea0fd8290090a620bbf023c2f195d4fee90ab6d5e9a068f30ec45afd1262dc70f4d27d7","nonce":"4250c1f06d8a36fb964e5b6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"9abd8c36bdd91e96517de0fad69789e4e880d555467de39a4e5d95898d7b370f557cde7abbb59fc51df0fef723","nonce":"4250c1f06d8a36fb964e5b6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"79a641b3afe53474b2ddcd90b2ff667339e99e1e2fe913d654f2a0ea5fb769520c139a91a7861ef6a25b1c24d9","nonce":"4250c1f06d8a36fb964e5b6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"e2c5ce0c7719c11fce884a95bacda78c94e6579b37fe2450fd3fd8ee0bc7fc58130385bdfddbcc4ebe81594688","nonce":"4250c1f06d8a36fb964e5b6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"d7a2aaed4eab50d760263a5b9a4f96c3b9782e25ac7b43a08fc891bf0e4c35f8579047be9b97e2cddde0570b89","nonce":"4250c1f06d8a36fb964e5b6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"678b8af47e21060f9e2e1f178eb3bc0329d902cbe1fdc6feb2109557247e3759119eb2df54b1ae2eb39810328c","nonce":"4250c1f06d8a36fb964e5b6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"a33e3db3d56dc399538d526a087fab0d57522d300027677618d1397696af54f3c725063f219794d5b9eca09c25","nonce":"4250c1f06d8a36fb964e5b68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"643d2cff6140fa7d1c041b21174606d2c02cc792870c8b39daafa78b093de5aed3f4d772a2cf85f1cfb205e0d6","nonce":"4250c1f06d8a36fb964e5b69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"73aaed80fbf2d51e0c9f798c2bac7f22766ca8b6a281d6db31b66e0242f1752d22f59aff69bc17a5a46e590aac","nonce":"4250c1f06d8a36fb964e5b76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"8b6a7a70f11b829daa3c9b1645935fd492dac3713b51da6f0b69d1ec4dc191b4b7d7e13feea5f458b3b609336c","nonce":"4250c1f06d8a36fb964e5b77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"c0e4c6784bca57fe7f37f87aef4b2f45c9124c7dbf361acfda4102e6f76c3bc49bb0904e245b21a6ddf375c1c7","nonce":"4250c1f06d8a36fb964e5b74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"824bc4f0cbad53dc8dd54a3a16dc308cc711ae1c6a4d33ed0536cd6be9ed75ec8302ff892977e74456587b4142","nonce":"4250c1f06d8a36fb964e5b75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"d2ccd4c0057e4e243fbb8182ecedf7bdba219fe78c0595e8da4c3c7921306dd973f7a36f82be372f396867475d","nonce":"4250c1f06d8a36fb964e5b72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"3104571b4fd897e72654ae9180f5c80859e24ee406757aafd114d6b321ecf45bee250e52b450f681c4cfd9e982","nonce":"4250c1f06d8a36fb964e5b73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"a4bde0e693fb63915d10c1f5c7ba6f3e610343b114a270e4fc87f546a64b689e0d488e97f7dd4f1079ec115322","nonce":"4250c1f06d8a36fb964e5b70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"c12b9bddae27a324bfac0c2790f4295cdfd06a14752d278fe55ef635dc75ca1d65c826ca543a38115a161d60f2","nonce":"4250c1f06d8a36fb964e5b71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"b3b78a6dc12c499df05169ccc554b9bed63079b4d95e96d86504c33055a3af533447ad8597db43a1f6f1ffa8af","nonce":"4250c1f06d8a36fb964e5b7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"21c530984e896040799af7df7ab5eccfccd0ff3ddf41245960e07a6908b088d7d642aa1b6d9e36e946cb969229","nonce":"4250c1f06d8a36fb964e5b7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"4c7d7de6ac066b9f8513f206ca6b20d0255f52b0283bb6f9d62b8fb74fd8b34ba1683667c146e1870399c608de","nonce":"4250c1f06d8a36fb964e5b7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"bf8c218004e46e4b5e49292041cbf0560a30e89f552ba779bad01300b2a735c6fd734bbfe03ace7bdd0e0d7c5a","nonce":"4250c1f06d8a36fb964e5b7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"52bd8a2bae128875c45765f36b7bd6655b490db17b65d68d113d3c202a4689e9c0b7268d08a60bf3f2b7334df8","nonce":"4250c1f06d8a36fb964e5b7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"51ea7407bba19fd1f4b1b295a18cfb9eaa81ad5eabc112b47d24b7c70254eee0c1ba5b02e09726bb769951914e","nonce":"4250c1f06d8a36fb964e5b7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"88c59b98eb68460fa2ae2246856988f4e2bf024a3b2b08124c1a58581a415c6ae94d4dc38d2f215cc6bfae9598","nonce":"4250c1f06d8a36fb964e5b78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"fefe87557b20f7b330a8d86bb90535017cccd70c6279e55dd25be01284cce75ee52d9af95261c26d864dc24352","nonce":"4250c1f06d8a36fb964e5b79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"ded3ac2a2e552a96e61d43c3e91398f3a5339e2f1ae0cb28ac0a7f99a14d3623f5abba5fcece80bf939ce981ab","nonce":"4250c1f06d8a36fb964e5a86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"10d620103170f0555e7cd04e145cdd1833ee3f6c866ca3b16b92d05d67c72d90"},{"exporter_context":"00","L":32,"exported_value":"ffa41fe8b285ed16d7fb0f5a4867d33cec18030dce739601710063c0bb30a9b9"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"4f878c039d18dfa92bbdaaeb1cae76968e2cfc5bba68fa56ad579123824a6221"}]},{"mode":2,"kem_id":16,"kdf_id":1,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"f89f532928e3f23be9d787efc3368fb825d6b2b5a83c72c412037546ab23dbe6","ikmS":"33886922e11b46947ff1732d2b04aab4b0cc1f2df749a4260f2c5e263484770e","ikmE":"8062d4cde05a279a8ef4cdc8f7ca43f1662bc9ad2fc44a5c246c8f520be9a028","skRm":"ed65e49ac5a613f66e0f28ff2ed5edb553d21a0b822e31f39246ea954ec38e7e","skSm":"38c4e7316db234ab4b43401d86dfa1294fa065e7c857a73f0e2db991b181cb2b","skEm":"5e3bf594e739cfa790dc21dee74094f83a221dbed9e10652757f4a0cf5976ed8","pkRm":"0402d8fa38e12de9421a9056309ea454bbe31c2ce717c55c7d35533ec9133f0c2fb946972b5cee88f6f6318aee678a2a7adc6ad9db7c757e9c7c87c6005a58010c","pkSm":"04377e03caea6fbf6a5be744b6294a4644312864066202957a5bdf63abbcecb52bc3d7232138473af939622f3ecf9ed5b72c915785f55c7118c51fc7bfabf9fd8c","pkEm":"04bc1605647feb6b48252c835c7b47899e513d0ba82b9246c947b3981af64008178522a1965c48e699e1bf5ce22b0939edbcdf1c7bb103a25a6f9fdb9b8cd7fdb3","enc":"04bc1605647feb6b48252c835c7b47899e513d0ba82b9246c947b3981af64008178522a1965c48e699e1bf5ce22b0939edbcdf1c7bb103a25a6f9fdb9b8cd7fdb3","shared_secret":"ea6b93f5344da09ae1f64c4cb29cc69123e552e44ab1fb205bcb5e89eabd55e2","key_schedule_context":"02b88d4e6d91759e65e87c470e8b9141113e9ad5f0c8ceefc1e088c82e6980500798e486f9c9c09c9b5c753ac72d6005de254c607d1b534ed11d493ae1c1d9ac85","secret":"e6d88abf2af8cb7310d0bcb5f6f4da722ea7d22335eb690f6fb688e76057d23d","key":"f77f4763aa41ffe999cfba0d2a8bd769","base_nonce":"124c755a5a9d9445e679181a","exporter_secret":"32449118a68c0db5f63c4fe9db37c2214029bd4db0b137fba08b907ac05ae075","encryptions":[{"aad":"436f756e742d30","ciphertext":"8448ac7c43bcaae17f8e40055aa51a73731797703a4e08ccdbe6c7eb7445278609240d269a8bf553e897045ba9","nonce":"124c755a5a9d9445e679181a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"f387e3ff926ce169cdaffc3ee8d6e0921624516af48a34be1a0157ebbeda9050e9a97e6cb88eda687421ce1b09","nonce":"124c755a5a9d9445e679181b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"a03db189863105001d5bd768d621b0197bbb44fdd83cb3e4937bde2012018bc96f421b442a5bd733e4c777dcd1","nonce":"124c755a5a9d9445e6791818","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"861459c28a7967887742b5c4c7bbc19870accfbfd2f6e56b2829ba8e52547e461c968f77b5a666af3f166ac938","nonce":"124c755a5a9d9445e6791819","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"86e905b62676387f4dddf2c8b033c4d9e8cf389599992523da6a2ed7e836d22ad56741f10a6004ed6b7a9dbc66","nonce":"124c755a5a9d9445e679181e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"9b4eb42837a041694fe7bd11470fc6579771dcfd9ca84a58f79afa4d99170c9bd657bf84acdcc055e81e9b5886","nonce":"124c755a5a9d9445e679181f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"5f153e6f8724e6d9f358fcf9ba832e2b185c5955ff3a6d0c79df0a3806c609410f2976a891b061a29fbfc581d3","nonce":"124c755a5a9d9445e679181c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"76c816f8b0b3449ab6bbed3f5bde86ce0b6157066cdf0210f085bc522f8d322687610badf6af9ded8931bc6ae8","nonce":"124c755a5a9d9445e679181d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"48df287fa3fdccdf07ac0f3ddd068d7f890172edb7dd82b3ed1a2c12524eeb70a3b92c66a10804ce506375480b","nonce":"124c755a5a9d9445e6791812","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"ebeb9ccf9a4e8e8286600c665035d39367772350ba09e9b89ec84f2534cd2ac699910dbfd8a7d9c4f9ea688d2c","nonce":"124c755a5a9d9445e6791813","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"530917e472f245bd5ad463ddf2df1cf52981dc079bc239f0805df5aba174ce52a8e8ca74eaab28f01fb566e817","nonce":"124c755a5a9d9445e6791810","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"54e97c1c06dcbed88ae3ae3c2de649a9b4a778ac2cf9e89fe65a2c8135cfb61a4284b5b76a313d2fb449dd921d","nonce":"124c755a5a9d9445e6791811","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"9d620ea382a8d2f12e1d14b7f9dbcd48d238fa3fd4e1e747b3242ad8c5bd7d16e906fd31095e34d25072d1a032","nonce":"124c755a5a9d9445e6791816","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"3772949c0cafb74e8c13469f442a34d624935aaf239bd1ed8c65b49c294eee36d13581d8e663e70c0bf1d35a5c","nonce":"124c755a5a9d9445e6791817","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"8117dd9efd01f7415fd38303a01e6886b732bb0549f3e96128aca964e5c2b42f42f02ad8f1a8fad661fdf76b71","nonce":"124c755a5a9d9445e6791814","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"ff4d4ceff6cfcadfbb7b20cad7da68647c1b6a3918891322bc34d026dd595cfb9008d210f83340cbf0198e2a56","nonce":"124c755a5a9d9445e6791815","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"bd52a011430eb5baefda52b5d8eb321d9032e64234b462f8029867c6166d0ea5b548212f816a46b8e19b74de52","nonce":"124c755a5a9d9445e679180a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"12a16c36c9c6b7ebf617fdab0a5140ddbbd7bdea161eee45ad900e99c217807f74a9096bee9a84512fbbbe634b","nonce":"124c755a5a9d9445e679180b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"d06ff54f8a4c49a7187efcad7dab596bf6adc81a264d5118973a523bb2c0e461c83b1e999433850f6bc01549c3","nonce":"124c755a5a9d9445e6791808","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"95da65cf41a45a91bb37efe8de1e1969ae03d41c7d7845379778c55aa5a9ce71c8a2ab180ecedf8c7cc28f73e9","nonce":"124c755a5a9d9445e6791809","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"2e0c6f9d4fcc6a24a654b69aa02ac221464dee83301ff712aea4ee793afe958ccdd86ad9f9c1aaaae28e6ee08b","nonce":"124c755a5a9d9445e679180e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"5aef9d0eebe9e49248a5ea86e486afa87d90aaede2a31b893c9019eec24ea13af1badd0f66961e049205a9c20e","nonce":"124c755a5a9d9445e679180f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"4aa69fb9df9d26c4a93b1db5372decb0aab37d63ce950bb229f3cecef2f9cd7fad295bf3136092a0c8ceb41b6f","nonce":"124c755a5a9d9445e679180c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"66ef31254bfa1567193771cdb3e9808b09f7b99a80a478ab6ec68abe5252484f8137f6489b01b8ff1240f4205d","nonce":"124c755a5a9d9445e679180d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"a7376788eefec7cedc8b69ed1fb43105c0d0d2fd74b2db7e32e21b2c15bb3baf1a3dadb111334141d49cced3f6","nonce":"124c755a5a9d9445e6791802","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"dd86e82a124a3767eb0327498dd8480e6f50671397c5b127f780b0297642ab9c47cb134d0d28ec062a1669bf4a","nonce":"124c755a5a9d9445e6791803","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"80f41d540c8e5084ea4bc8e165fcc7a18a79ff629d6e76b7255231b88933f3c2629a28da50d9f6b1883fdda88d","nonce":"124c755a5a9d9445e6791800","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"cec431f0b3d21e6d6a96420712a9dfd1e745269c086995b1da887ad96f367bd54031804473b6d337ad85510c0f","nonce":"124c755a5a9d9445e6791801","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"7a20b7ea3be9384dd320d941821d0d4bf02e7d34bc32792555e4312e7d2b119c138d76c5b9ab975b1d76260508","nonce":"124c755a5a9d9445e6791806","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"345f3b816efd4540951e57a66a74c57160e1e326a133b6013e12c4ee6442d6e6c8c36935e2f24a50ae508a9d1c","nonce":"124c755a5a9d9445e6791807","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"94bfe9b191b370fba564441cdc0b5dabdfe30a5062e09b2abdc0b66bc7bc43130ac01f248336c524a497c8aa71","nonce":"124c755a5a9d9445e6791804","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"59969be91dac998bcacbc7046aeb5dd75f7ccb06c839312d346d235f7060617591900a3ecb6d526540b8d2c175","nonce":"124c755a5a9d9445e6791805","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"892d643fa815a84c3fa34b575055a084425ab9170107504ddc89e26f7f73b5012f8d6cf096953774ac87bc6881","nonce":"124c755a5a9d9445e679183a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"3e87e21760a9e06780456d8d79849ac06377f0ed6b7c468ea0a1c0f83092fa560df7a39447c0beac206b4d4763","nonce":"124c755a5a9d9445e679183b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"197bc53345ddccecdf0eaa3a561e93881e4204f54fd83fab16580d40aae5fa255f167ca062db06cd2de4396f1c","nonce":"124c755a5a9d9445e6791838","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"b096e28962d0d97b0e5b80018b1e1dcbf76957249cde0b8170c6179185686c4d896639a88adee45fcf5435434e","nonce":"124c755a5a9d9445e6791839","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"9e9438cce4d12d29c90a8abf70ec7926f9cb0fcd5ebb7ba3e34156f1d3a2039aad7f37f3c9881aa3da8dae6328","nonce":"124c755a5a9d9445e679183e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"38b1365470cef8ec34534e3bd9e0bf2f069bb8bc881e1fdf8b91c9940157e25347e64181061448ba18da817b5f","nonce":"124c755a5a9d9445e679183f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"575b146bbe807da1c5baa8298f2d33f67bee4fec46bd0aa06e6190bc90e505241efb9a1b6d42b9a48a3151b5f8","nonce":"124c755a5a9d9445e679183c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"7131188387e9c52a0d7c1ad6bbc4ae26b3c73fc1c5133c9356e3cef96469e2e4e2c1372234f0373e4133db91a1","nonce":"124c755a5a9d9445e679183d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"75a7c75e13e7dde126396f63737523e497b9f8c97a1d7eb8bad84f71b7a5228dc3e614359a70ce20d59bd80708","nonce":"124c755a5a9d9445e6791832","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"e9f1a21782b7f3ae33355c1d7b819a1242553212dd439b79afdb020c5838499e7073c48b0d7b1e0f10703bd8bf","nonce":"124c755a5a9d9445e6791833","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"9c35e0710865bf7a5015520383a661359573c9eeafd28b7f400d5463139a5832364119c9f9af182399b17d04ad","nonce":"124c755a5a9d9445e6791830","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"468633ac56e91df1dc2d5bf8be23e2e4b2eed0f43fe268b75ace52d5830c0eac6f1a25dce0a5c383da4fe9b756","nonce":"124c755a5a9d9445e6791831","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"13dda7a977d60abb3679cfa2d733b2f5696b32d49180e1b860161053603c2c46111b205e9a9938476fe0501978","nonce":"124c755a5a9d9445e6791836","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"3bc50d5792da41848e225906245e336b2f15566d45f382051c80c045002616bf2c050e26e65f410c661f886cc7","nonce":"124c755a5a9d9445e6791837","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"390da95e100736e1cd6a0d99966b5d485a8a91b838538e1a6effd86a320214121a896f829f0c5277c5fb94701a","nonce":"124c755a5a9d9445e6791834","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"02fd61ad42993ab5920db61e010e9ff1260902edf8b942f7e3da39cf2ed25b289ecf83806f5969892c4284cee7","nonce":"124c755a5a9d9445e6791835","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"26bbcf9639383175311ffe5f39d874f98a9e9d2e79bea252667a1dc219303024c9b744732878b26e7992ad4ad0","nonce":"124c755a5a9d9445e679182a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"0745f6eb2d42e767bff5103d52e0cb0dfb954077b7c1a571d90046028f1e74409c1ab269321d4baeff19d53aa1","nonce":"124c755a5a9d9445e679182b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"8231328eddb0683022537b9d81c963df98830ef5069dba2444458c767cea3fd5f4c2494e8bb1ffa4beb2a7a32e","nonce":"124c755a5a9d9445e6791828","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"135dc7ca570ec56567a453901b8cc7c58449b3518b18bef96d252ce66f0560e12e57beb59b1e7d7e0e68f76b72","nonce":"124c755a5a9d9445e6791829","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"b9486f3da745566daeb8d31f7c614018b5d9b7d6b59fcb0d3f68880bb0fdfdc78106ccfaa29691c4dd6e3fc8df","nonce":"124c755a5a9d9445e679182e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"cf433bd66bf2bff8299558e0c4e331dfaed39a1fb8978ac56309189e2c972b8d85572a652297edec3058b2364b","nonce":"124c755a5a9d9445e679182f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"9c41c52765a6c540525e821ae671cd0a7ce88535a66497dcff7e95d67ecddf05ef4282501872e119372f6c3f04","nonce":"124c755a5a9d9445e679182c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"152865a4ab4c9a4659409735f1aba6427bd567c27f6ef4ab2b3e4188b354e3133a734e7ad8466d8c7d03fe3111","nonce":"124c755a5a9d9445e679182d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"d5c2664433f219829443c0013f6fdc69fa740f23c68170525dda298c984a06abf6e9886de824f54a12123406b1","nonce":"124c755a5a9d9445e6791822","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"c3170615c3ff26b225f8ae578f3fe50115e18964f9ee7c592007639b167a0f01aff22314700a90d67d785b716d","nonce":"124c755a5a9d9445e6791823","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"a683728919bac49a67ee0bc47a26e2a9c3f69f16ccdf312ae48482ab2b6639a6444f9c7df900523191a0111062","nonce":"124c755a5a9d9445e6791820","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"92857b10c545813f0352c350d9bc1c2b2f3d394c124d6700725dbfe7678a487ce54cba5906f7cc8142260cfee8","nonce":"124c755a5a9d9445e6791821","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"d33447451b73da72ea50a3991492677234c275eec53a7de72e0dbb4fe5f4fd4588e5774058bfcfff53e1189e0d","nonce":"124c755a5a9d9445e6791826","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"31c3ecf86edc252f6a5f8f93a5a81d9e4a400cf69b063885f72e84730bd92c94a979679a7dc5f171f7d619f247","nonce":"124c755a5a9d9445e6791827","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"a01c86e8b77124303a253a4cd9eddcf23e43f9f03011087d58e379e986ceb852db162724d831a90f052aa23bab","nonce":"124c755a5a9d9445e6791824","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"2baa0f534ce5a4ff6062335e2043f9df2722c8be8089a9a1f232bdf011786276c69f5ff607c7f69c9acadca388","nonce":"124c755a5a9d9445e6791825","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"99de97a493603027a668f6d207df6676a101bbe2befc3b531d9b27db8a30f8f77fc7bcfd0aa30db7c8e3955413","nonce":"124c755a5a9d9445e679185a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"2022dafeb87ff0e805b9db4f9ede5f9965a14a5d2549f1e4a83a292d95b4b9624681af355394810369e7be6ddf","nonce":"124c755a5a9d9445e679185b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"c64ecf809f911330ed2b7dc14c24f3e1db815da7ad213a61b0f4fff5a8129f817203e8e9e57881f4957152cc5e","nonce":"124c755a5a9d9445e6791858","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"136b04badb04651dc96f609eee43f7cafea1c474d598d1421b7f044846305d6c4b180aeb6b128f651f017d1279","nonce":"124c755a5a9d9445e6791859","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"f8aa4bd0bc99eb9523cd8a574adff4246153eed558e7cbb0857d429af265335f58e77fb6b64eab747b1f81d923","nonce":"124c755a5a9d9445e679185e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"77ea8724a5e0ed2da7a0f8fe1b6e692ff0fb31b343b266b94054131595e692d40481ac59292c96ec6a740dbe10","nonce":"124c755a5a9d9445e679185f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"c713f3811d5e87def2fdf69626c9021aa20dcbd7f4e93db06dd5ddbac7915e042f626e9dbd2d29b239d82c1f2e","nonce":"124c755a5a9d9445e679185c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"8006f6fb540e6c500c31ba343077800d3bf6d90f04d3263e1bcd21282915ee62ecf54bc51c4a6287196002d3d3","nonce":"124c755a5a9d9445e679185d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"7b5793708ef9bb55a8bc8049798cb023495ef4ce20fdd6fa0e2f55e8d46fa4b746ddeb567d298a6885ffd6d6ed","nonce":"124c755a5a9d9445e6791852","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"3fe0c29b832866db057a7133efe900b0aaa97ec5279de43c49bf03d8f144ac1ff6e78065f3b84eddd4a25bdc38","nonce":"124c755a5a9d9445e6791853","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"45dc4adefa2a931ebe80a659dc745a92decfab07a6bc50b6691c2d533fa28fafa1f94c5781d2228e4f20368139","nonce":"124c755a5a9d9445e6791850","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"e0ec4838c2d24342df7dea391d10e9909a8a6e190d84ca32f15b1c2c4e9abe8a5aebbdd117e32b850ea1c67159","nonce":"124c755a5a9d9445e6791851","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"f522d4400707e747d3e07cb0d1055fdf72b91d0567e20e28acaedee2b196084b167cc8f1bd95f2f5a690b6b4cf","nonce":"124c755a5a9d9445e6791856","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"dda6ec43dd0fdad7b5533a62554764dc919e7cf3a1468664e2aeb8a4fc0c235fd016a0edff79661cbccf47c533","nonce":"124c755a5a9d9445e6791857","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"753c07a4e6b6bbbd646100ed7174de0a04e420b3d4cbf564b53ac354187297425bb5413f6d84de068bb0872aa6","nonce":"124c755a5a9d9445e6791854","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"0e8e0bed068637cd692c6f0ba47902f348079e83d11ca9ba14be58b00266859c83073707033011c2ed2b888037","nonce":"124c755a5a9d9445e6791855","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"f0ee5149dcf2d5a1fec7ccdf49674cf798ef633c19490c8624b7c53122d6ebef71c1fb60660e5040e6c19f4b89","nonce":"124c755a5a9d9445e679184a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"cafc59d1adf893bde75858be6d97d9c17d65175a32cd82e02c2435a6630ca47846e5c3d76c1898ef34217c6b99","nonce":"124c755a5a9d9445e679184b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"bb25fbb060de4821bd79506b68eb6728d896feac59a10427bd55348156e764560039e075f68057f85ff6f8a601","nonce":"124c755a5a9d9445e6791848","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"274c056b37c6bccd57bfd4c2dc67878284d9c1f9bd8da604eec21af1de9c752bb89e081155048a7c61fd95c8e4","nonce":"124c755a5a9d9445e6791849","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"7940f151dd769a14704f76b03e81f28f3fde5f2aad86a61e3fa91897a7598694a7483ea89cc9f85bf393a36c54","nonce":"124c755a5a9d9445e679184e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"a62970932d05fee6845c1c319da35ca52dd2e3245ed3863b489abc9f25f4a825ce4e5cbd73870fb54c304ae1ec","nonce":"124c755a5a9d9445e679184f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"226c03352b71dc5b26ff448da814a836c47ae49a7720a8c6aabcaa281f5b60b1e9851855054cb3de42155b8c1e","nonce":"124c755a5a9d9445e679184c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"1c410638da74cbe4979d8fbf4139341b66d33b431a13cbae7113d844867df737b246228406f8e0a773e4ad8691","nonce":"124c755a5a9d9445e679184d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"6bcb71214653bc10cf567cbda6b1ccfe660cd17442241a3413db0f5d63cb490f19d84cc13f27b8cd1358aa4af1","nonce":"124c755a5a9d9445e6791842","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"9894fdb8721f843d7a572b7208eb2b7d0df74f71d0c88d70f6862011485565595fbf0516dc782df8d3f3539973","nonce":"124c755a5a9d9445e6791843","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"b93c1ed4dc3cb9ac83a0a42e1bbc705add82a2cb5ebbb349711ce35d903cc0857dd856988373ceaee65162dd50","nonce":"124c755a5a9d9445e6791840","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"12536e8a6d9c6084539c0501efd82509391fb701254ab719cfa89c844b025af49ebc20830139c8402ebfab7b6d","nonce":"124c755a5a9d9445e6791841","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"342c4656b2fced17642173c73bdd0af191c2ab5774b3fdbae5700c9042a8564813cdf0b7123c8973ee2803e1ae","nonce":"124c755a5a9d9445e6791846","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"1319f09a5bcdbf66b6a9f97b90f0ce571fd0b8675b5d01ae7ac6d5d5aac859b06c4235a08248698fccc3006247","nonce":"124c755a5a9d9445e6791847","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"ee1f71e75e1037497bb2f860465ba5d611cd5f9836f09e974896e10256e4736f385d31803ea74da6153f531615","nonce":"124c755a5a9d9445e6791844","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"383ff0a5c93fa06fe71ac385c06f7b0aababf32c0d093555033be6e7ae02b527dae7c84a253af783325ce21c07","nonce":"124c755a5a9d9445e6791845","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"d4e44405ae23a26a8c24cd170edb1ff4151957a94ab9fba0284188c7a6b11a20345a17f36d450428217075c0b7","nonce":"124c755a5a9d9445e679187a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"262fced7f41f725abbb046faf87f466fb9b4666a59ef505c00d75b48e0dcfe27eeb5d24f1b564d50a53e227906","nonce":"124c755a5a9d9445e679187b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"2c8acd84f8cc6d8e03c12fec9c820938eceab6c01208c74e2cf7d910afda21918e0757851b06e2e75a293859e1","nonce":"124c755a5a9d9445e6791878","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"abf8dc413a9ce130f3300d05bfe2070c9a747f6a4162dfbfea097670697fce9d29b7093438302417f0d119509e","nonce":"124c755a5a9d9445e6791879","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"bfe279765a944263329246990223b0b1c943701a9fb3971f4d6f2f7d19e85a0a29513e08aa1b7838e1a5a13ce4","nonce":"124c755a5a9d9445e679187e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"979a07c11f4475412d20fc87b65aa5ba26421893d9b09bfacb1b11a4e540baf20dd57024c7b260a0fc1959355e","nonce":"124c755a5a9d9445e679187f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"73b09633eff3254cd30d4aab5809269165aeed4f333097e27dfa07c09a190099d1db51209921a31e634c4b89ad","nonce":"124c755a5a9d9445e679187c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"3ab9c07443e3d589d5213506dee852f383895af22397fdedf7a31476cf14052484c8d2f2c6faeb6ebf8f5d7542","nonce":"124c755a5a9d9445e679187d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"18a231283f34c3b6c07c65024a6e7b7b6594261df0cbd8021d941762abb6222f34087e74456571746c4dc031f4","nonce":"124c755a5a9d9445e6791872","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"eca432b90a9ddb04e87a1533c69066649fbf92e7f55dc07964ab926523535162625e793badbd0cbea806c694fb","nonce":"124c755a5a9d9445e6791873","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"e138ccd6826a13f60e6584ad7292521a160f723514d4799b1d4ff882e20ba7b53e604c7c368d094c02c66169cf","nonce":"124c755a5a9d9445e6791870","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"7252f78f3fce60ebfcc04e31435db0941236f606b7cdf18faf7569ce0f599cbc093144ce76f9bc74168b36b062","nonce":"124c755a5a9d9445e6791871","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"2508503626645d707de0128c45730d91b427b64c7f4277c3171378ca82ce06a4145d95247fde3290848438e055","nonce":"124c755a5a9d9445e6791876","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"1a612faddf48b821b2878448e11718745cf8505365a77dce6b8613fee85ccdbf10bdb9f52b5bfb5392c4b02ce4","nonce":"124c755a5a9d9445e6791877","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"0365feac13227e1d5e1890a2d26fe628297ea6235077cc9510bfdaa76fa62543f3a85f172f92bb60cffc121251","nonce":"124c755a5a9d9445e6791874","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"6662e3654a9682a4fdf503c1d4defe3aa58f3fb88fe9353e9608b6b686affda61f9766bfe203792b7f871f6cb1","nonce":"124c755a5a9d9445e6791875","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"d1525e7d9def8fdeb283318333bcdde2f8c633f5b1e30fcc76f2673a92c4dc0717f6647e96197b8b8556fcab9c","nonce":"124c755a5a9d9445e679186a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"935b5f916757b5fb090ebb9a371920b5badef70d9e7d69c96620f3c18efb5f4e4adfa9dcd83568eae19aaa749b","nonce":"124c755a5a9d9445e679186b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"87ecece438ce61ba31727231d9ff07697ef9d1f5985d703ad348092c7aaa97b305b8aa8c2e43b4e1269d8ca5ec","nonce":"124c755a5a9d9445e6791868","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"33d3951fb4a9c1f65b2d81cac8affb3060ea92ca74bc357de9d49bbddda99624cff83bf90994e10aca8d486254","nonce":"124c755a5a9d9445e6791869","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"15351a1264c1714175b01bc553ede8d0afac46d2d3a8b0f6383825a2c96c12ee1ac68f01fd87e21bbb2c083755","nonce":"124c755a5a9d9445e679186e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"c2884e1d292fabb8046d9786cf79dff056df8eb51094cf22057a135d1e63c505c536939746e320388b4f37276c","nonce":"124c755a5a9d9445e679186f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"a88783abfcc7a5383790040be2be81ad80fc3d6d3a831f670c6ba38c81707ba264d5c284d6a1ffbc9987104452","nonce":"124c755a5a9d9445e679186c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"cd21743888d572c7356e2d771816b67422d7a5b0ee3612837cc9b32131e4991daef034615ecf78676ff9a6ac79","nonce":"124c755a5a9d9445e679186d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"7825df0a19357d7c8d1cf0ccafc6646bc4494b9dc8368e7da5d535d2e4e477c218c97b1499c6ac40ef6680f1ac","nonce":"124c755a5a9d9445e6791862","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"55b57f2cb94a3a981d2f7912800eedf398ddad5c36867f4b0c0ebf16865ec7284a00637a20d58226ff30fca846","nonce":"124c755a5a9d9445e6791863","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"095be640ebf7b28094f64b8598a64cd225a365d8d99ecf944eaf3dbaad57d6f6f362ba47fdbf336ef8a5517daf","nonce":"124c755a5a9d9445e6791860","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"021fc6eab1f4e61e839f008fb1c9562708bddecd0e7be6730f0d6ce8fa125f9167978cfc2dac7629499f624e42","nonce":"124c755a5a9d9445e6791861","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"e0ae3c92561ab92f82975afa63cf983a87178bc7424f3419dfdc17ffcfadd5496f46cb85ac95b43354ab51012a","nonce":"124c755a5a9d9445e6791866","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"742654340346e2f8099763f023740d5570b05d7bbd626fe0e7afac8c89c56305809226c13e2261f4fa2e416938","nonce":"124c755a5a9d9445e6791867","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"a62c4ca30b1d54be48e0ce711318c1c77986bfb3d16d96fdd6de90f51f14021ce1ec3e34feeebf2f15d75cbe5c","nonce":"124c755a5a9d9445e6791864","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"a7343f2c3381df5e00290f813f97948538917d07da84e5d83b00aede156a6c238c388d7f8804ad1346c32fea62","nonce":"124c755a5a9d9445e6791865","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"d4dc13861582b1bb269f638f3e6be764bde8604a92d54f649cda99302d0ea48330909650d9aad83984adee87d9","nonce":"124c755a5a9d9445e679189a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"2272088534b96de9d82b189a5832bd899cf5cc69851b4b664a44fd86eb487f6d844f60dc819fb8c7cca033ee8e","nonce":"124c755a5a9d9445e679189b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"1caa0cfa3fb8b004d056d9e45c0d977cf0967f581276898be0a04e4c4768aa850b1e9e76586c9555ab18845623","nonce":"124c755a5a9d9445e6791898","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"f5637bd98493e851dd57ef41f0630ea30bc12e5668109fa1bb704233fdf4e190337539d70bcf21ee2074e2a4b8","nonce":"124c755a5a9d9445e6791899","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"04de522a4121ade3faaa0078be5840826c0bb16064841a24712ceb21d3720561db30ed60371115f89bf72a5ead","nonce":"124c755a5a9d9445e679189e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"4faf266a75eb1c35df2a7731f2a064fc8b4991fbebfcb7fa5a72e687b8b3c3343431bf56410dddf4607776e3da","nonce":"124c755a5a9d9445e679189f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"701728bcf8ca70b01c7dc126e302f038c42d1bd09df9353f249516cb2b39ed073d705daa4362ad9c9b3e28c2f3","nonce":"124c755a5a9d9445e679189c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"dc426aca25f456bcedc4cbed2e693f1130a8ed69ca6401ec9a583b2380a42ae753370c1d7406b07b68fe5336a1","nonce":"124c755a5a9d9445e679189d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"60982930ad07e65a44a642cc9cc79e35b63230b62644acbf007ee6a0a012c955a81cbb90afd294a6f79cd63b98","nonce":"124c755a5a9d9445e6791892","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"2120e6d7552cbad293c752abb37ba7c5e5aa913d7e4a4d4271a61a4abffe7ed624614b1d90e42f4f3ae64010ec","nonce":"124c755a5a9d9445e6791893","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"6d327c068189efc483c7f7ab34ce4c6110058fd64deb1d9a3ae5b6843725abfc7dc6a06f9362e924b0aac93eda","nonce":"124c755a5a9d9445e6791890","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"8ca28cbf07b6adfe954c7ab6d2d58e265d5df339dfeb2c3b2c37b8797adf1b957a739ef111e1800b28cf40a4ac","nonce":"124c755a5a9d9445e6791891","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"9471cee3e407007172e255cb368fb951226d6741dbbb62d21ac5fac8e85c776a298050d3772ced67a144113496","nonce":"124c755a5a9d9445e6791896","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"475efd83690c00f8101bdff3d38f861968d8e142a80d543140e7475a1f6e0b89365a925b386808617baa5d17ac","nonce":"124c755a5a9d9445e6791897","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"36034f08a1c48a6056c13988e5d27abf8d735f35172f73c94d880d84316b07019b1400c06aaff3bc7a2163c789","nonce":"124c755a5a9d9445e6791894","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"fd30f186de4dc1dffa2c709c034547dca9d37a249b690e7aa2e476bfdd105a41e1b49b2db70a268be6c8366e57","nonce":"124c755a5a9d9445e6791895","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"d3c2393f15919af6135e0de1e18e694e6469e924996fd360e0e8ad4b57af9e8c95a0f5c32ee9e54e2b5d9874d1","nonce":"124c755a5a9d9445e679188a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"ff74325b1769a4d3ae01606f89b35ef7e41fb577e928c36d1f6fd7badd34c1fcf7b2007c649415b704afa97111","nonce":"124c755a5a9d9445e679188b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"f99a9dcf655f587f111221aca7ae5b22583689d8f421260abf6dd480e4d4d751465ab0c91d6828f34c8c70e407","nonce":"124c755a5a9d9445e6791888","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"d45efae7e6d411dbc09a51920e5b508db287e90a6ecdb98ec46f57ec88a9e14fd07c48c38ddcc7287b99eadb5c","nonce":"124c755a5a9d9445e6791889","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"05a249e1949a35d6c4096a08f2b3dce6706b7cd294a6a20b2783ec16621b05c8777cf227a9475711172114b489","nonce":"124c755a5a9d9445e679188e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"bb9cfd9da9b571a5ef3c681fde7833ea12a3e5750f7daa403cb6e7c19c5d47bd5768b7bb443002a1834c910199","nonce":"124c755a5a9d9445e679188f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"05740e2413ab80fe67981c7116fa0dcbbfdfb259f15089265b90a4c8c7e9c524afc6c4f4b0bb2113714e5fd251","nonce":"124c755a5a9d9445e679188c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"574c90e94625aaeab593233d87ccec01c4c9d1e682788d231712bbe1894b1e16dcac41c9861429fb4c4059808d","nonce":"124c755a5a9d9445e679188d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"006e1dd4dfd9902f3aaf40c81cb5aba61438e66d5ace1e86529291973e26b6845333f1293aa8e3666608a23ebd","nonce":"124c755a5a9d9445e6791882","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"3d2cd7cf613189d3cdb55fa9fca60af995d0a7bd8991d8c3b99b4698608b5446ab64de5472e8c82a6b56ae9ddc","nonce":"124c755a5a9d9445e6791883","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"1dfe8d50c53f5c3dd3b85b320912311781c3370be92d4e5f97f6aacbe7f0e821b5ba6a264a6201c65677ee43f9","nonce":"124c755a5a9d9445e6791880","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"4e18842f798504ca7a13e8b2cf1c34a6cb8dbee8d68bdd6cb89ce2999cfb5caa14c1d49862f3289914950f1915","nonce":"124c755a5a9d9445e6791881","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"dda975fd9eb21b072708c46fbd78c482e3955a4d9b9dcd3fd6ac9aef9b2a41b81cb1788cae91b92dd6d638f0a1","nonce":"124c755a5a9d9445e6791886","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"25a5ab7a308406f3e5758f8ad5b50fe4ed63beba962ff87d0dceafe8f03ba64142fb5688513c0909b0aaefe516","nonce":"124c755a5a9d9445e6791887","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"0bd49dc017905e96f7041e22448ae531374ebf0b7d4b0f598dfa59ca86089707120784486a141bef5e35767967","nonce":"124c755a5a9d9445e6791884","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"2ce3b96c118e8aa7d58bc35326d09bc1fc15a6496d84d48bba9c6962a8da1eadd9c88c9a8fbe0f147109bb047f","nonce":"124c755a5a9d9445e6791885","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"1eaf491a7ea8d5df1b485403628b6b655fcb3db88a4b5f4c8d9ef1c00dac45ea9ef4d349131887ffa61fd7f720","nonce":"124c755a5a9d9445e67918ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"adf8e20140e3c5fccedd0a30ee1728738b096981a16fd678b34cd847eccb73e8dc7eecd0c1df1f945511437a18","nonce":"124c755a5a9d9445e67918bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"c769e4ee9fdf2348991f8996ea1cbd432f0f70376e6db5ff55f8fc37f2a69e071aa764869899ffd66511f12f36","nonce":"124c755a5a9d9445e67918b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"1afe68d196ec62d1b4a630b66f52557f5f4e29b67d740d959300a5b908c46f2bca125edf0ad2d5e0417a6a32eb","nonce":"124c755a5a9d9445e67918b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"d8e78f5c9113c1d8bbf34cfe1676d648f5d20532b38683a1c4b1c3cb5f5e2319ae90cf862fea74250df0277a11","nonce":"124c755a5a9d9445e67918be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"bc3d98a888638da237ffb913782c758a935e84c168f28b03bbf8208313b12f45682e4d862854e330ca1312f904","nonce":"124c755a5a9d9445e67918bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"d91d703266323393c30a73181ab429828bee37b8cafb5b5b82656c2c6abb3912e37b287c11adb03f48d3d2c004","nonce":"124c755a5a9d9445e67918bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"32f83dee5cd113dee1dd93a449337e05d7ca0d7576020b2f626b12850fd0eca176d703722697f6cc5517932722","nonce":"124c755a5a9d9445e67918bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"bfcf51ce66c8b43d5eb7c2ed5d25845128bad531a058685980fa098893f0ba20a9dad5b4cea963372ddd6c15a4","nonce":"124c755a5a9d9445e67918b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"61174ae1f9a17b19185613b8696024d3b29cae597f124df4aa20dc17110ab3f14d9869ec48f8894b52fd2a4cc8","nonce":"124c755a5a9d9445e67918b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"9a05afc9435d5df01015fc7bee0b6154f6c5edfc45b0ff33ce2b59e85f6d37dc3ca188b6f869577f3b80d45736","nonce":"124c755a5a9d9445e67918b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"fd74665723fa226c4496c38c90e73aaf9a43d389901b806ca6f3ff322e9f2dea88e4150455a7af0e2a2366a79d","nonce":"124c755a5a9d9445e67918b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"1420dbdf808dd4b6504d2acf1df075eaed45f480551831a03f72e9dc0fbfa345ba33438c618388bc3a019300cc","nonce":"124c755a5a9d9445e67918b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"06e39ed97ebab007f1694c3fdb561528668a51d909d77ad65e367c8603f323aa662e9e0d740f179881a77c2608","nonce":"124c755a5a9d9445e67918b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"abd7a694775704ed9705515972279c28818d3c753a828dc22d93c23b11b4e200d7a21051de317d841f9f4e28c6","nonce":"124c755a5a9d9445e67918b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"d9625787d3a5220122fec73e1a500c3ee023a69fbac6f2a59f4103ad2b714ef43200528c776eaa279285f282dc","nonce":"124c755a5a9d9445e67918b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"68cbb967c084610300d3f9f5dd40505bac00a65c264d131772a8c53dab3c8e0bd0491707bc37fe727cb300f72a","nonce":"124c755a5a9d9445e67918aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"eb032835a505c8dbcc4d4d3daf643f8b7ce84cc2a43a6902ec6bf1eb6ee3503765a29f8c2a07b93526e8f21d21","nonce":"124c755a5a9d9445e67918ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"63feddd5fa9552dbac27dd5b2bce06e2d96ef2d162486dd007e5fe01886958cb9020bcce734b827b92c7e93de0","nonce":"124c755a5a9d9445e67918a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"8302d84ee38410bcc1918246b2839cfc927c4201c2016100ca6342957e3c031a9996271e73378e1223e9846d47","nonce":"124c755a5a9d9445e67918a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"406c6c905ac37b8d545b138b57f1af3ca11d052e8437a0b720bc53ddea8ddd428d7930da4f5ec9fee354afd19c","nonce":"124c755a5a9d9445e67918ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"227e6002593e26f4e8bf0726d094c65da2bbcdfc962d1ad9ffbfd44608885e1fc39dd82b808f0a0477bfadc455","nonce":"124c755a5a9d9445e67918af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"877245db793cb9fd832025d523fa1ae865f0896f5b55954cc2dc314c3d707110eea86bcc63f1aba7dc6d9229b1","nonce":"124c755a5a9d9445e67918ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"1919ddfe074d517f0bb486a7c3e51fe08ce2f1bed404925bd9111c91fabcc7bcddf1a8f552e58043788467ad76","nonce":"124c755a5a9d9445e67918ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"0b832bf4d0171283d2671be38269356d3e06203f54b0518a33f4ef0f27ac0dfaaf64632926a3599cb28c38bbee","nonce":"124c755a5a9d9445e67918a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"e110115be437403a4fdf908dd33396693378bc9cd3f41b456a4a3a6ff65db8907c81678f6cfa9f022cbe1cb516","nonce":"124c755a5a9d9445e67918a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"91cb24b21900500428b4660f2ce469e797f4d9edc7dd9055345fb1aea285c36e43e21b87297f13a11ea7bf1884","nonce":"124c755a5a9d9445e67918a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"b932c96c915c9b589b1fa3a19f80c0caa6d26e70c8d93fe9df2776b33e8a455bd561a460d5042d8d7ed0003d2f","nonce":"124c755a5a9d9445e67918a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"cfce940b7979e676209b3d2cd8bc2c6709e914e91ef03c44639d8177133c1369b8b44c933cd12a01272b0b15cb","nonce":"124c755a5a9d9445e67918a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"43f1db0072192091c8052fd453a93aace6da900b30db434832545742876d29ebbb4f34de4a62bf9452c1516d3a","nonce":"124c755a5a9d9445e67918a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"70e5abc4403c7663f057e95a3cec722398c61dbe387150eef0a6f87014f42417daf4609cf81844b04203822791","nonce":"124c755a5a9d9445e67918a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"ec28b683df3cc89067c319f677167e25236b4ad0e757a4dad325399c095d97cdefe56ee1dfb33228b0d641ba02","nonce":"124c755a5a9d9445e67918a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"08af32795004d9561512c56405ed17ac3d67afa5912b51f5a8303769e250064052eb7f71d80e8d587920e2561f","nonce":"124c755a5a9d9445e67918da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"dce63c601aaf878b9b298236ae0b5b67ba8690e2c1412c207925adb4caa46cbd969cd63ec39eec9a59b56aaed9","nonce":"124c755a5a9d9445e67918db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"1ada6d2061cf3a6bb21522d24c830e9d765f1a292cc59670f9e423806531a0261cefcc71e6e42b833678a09e1b","nonce":"124c755a5a9d9445e67918d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"93f5994f85f9f5a1148f020b688b4813e811f7a1fa92c00c312744794d771548933f1083f540d0d634a892272f","nonce":"124c755a5a9d9445e67918d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"e397c2d992a574e9233c0e3c181b62ef975cc2397a4262e2cc8155c080e7193162a0183642c949d916b3ed34ce","nonce":"124c755a5a9d9445e67918de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"d3a3513661dc1a0dcecee1a8f8ed15166cdff6eba2502a97f81dde00f484b1f1f943316bf5ce2495ff0df47654","nonce":"124c755a5a9d9445e67918df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"79e35172c4bb24686a0db6aeb035702631bb648619ffc208fc960763d4122ea7282df39c8056be541826d5d979","nonce":"124c755a5a9d9445e67918dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"3bb72ef78b1c495fd3ca039ffb11ab86772894bb1fa3668c5d677f4f684d3654afde6277c3398e6a4f7a236785","nonce":"124c755a5a9d9445e67918dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"958935062eab542f55e0d5abc7d370da95bcb753dbcc755f3d0aaee8c1346780aeb54562251a7b4fd436b5982b","nonce":"124c755a5a9d9445e67918d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"00695c27b52971eaced1424d2394fdbbf981792aea120246613d6a1e3b5ca0033cc325429eaeca0664331916c2","nonce":"124c755a5a9d9445e67918d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"26540c1e0ba85c2d7dd1d9fa81dd2ae0c5e172582c6355c739a6d37f0bf77adbe91db2596b3411e528b6e9559d","nonce":"124c755a5a9d9445e67918d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"78225ca717f598cae3cb3f9f0f72c3944480d2e3d73546daddd19ceaa5ffbae9fa79fbb82af18d30e776a6c8a7","nonce":"124c755a5a9d9445e67918d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"68b1cf25cef08ad9456c38d32d999778052a2bfa04925c5d541a6b86c4ce3742e42730c4e435b2cbacee97933f","nonce":"124c755a5a9d9445e67918d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"c9f8c749a750473a09475b7e9587af834295d586cbde17863754792125b79afc6c9dff0a44121f1cb7afdd44f9","nonce":"124c755a5a9d9445e67918d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"9571d7f1bda5cc4f05163a80ffff8a22165512232550f609ea2b59f942116ab07acd6dbb306a4ffbae8b6410ff","nonce":"124c755a5a9d9445e67918d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"73567d876aecb8a1d2fea1cb0fc28ce2d0ac6797156ee8e63b51ec41335d9d820837196747c36ff40dbfdc184c","nonce":"124c755a5a9d9445e67918d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"6992915d12f047f780acc3768520d52ecf6b0e2d11ea261d07c5a2fba69f91c80db3c6d6ac49483240bfbaf0ea","nonce":"124c755a5a9d9445e67918ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"f7e224ea7eeeda7d9cfeaba1c60fd7c01bd6ba927a991430771a069fb70eec8f7bd0a9e0a51496de94804e832e","nonce":"124c755a5a9d9445e67918cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"f36ed26c4977a62afab8f0f61f1edc626ac3b69005f28e5798f42e36ba422af6629baa18f996680102c06d777b","nonce":"124c755a5a9d9445e67918c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"62c7d96ed255b5e3ad70c82f2d0384aa81721c10193595f50333c5e79afdcb7e8fb9b02d0fb2bb16a8d5094744","nonce":"124c755a5a9d9445e67918c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"c73a20a6fdf6d931181008d01e2e48a1a816828687e46d0305194735c4f20524137a78383164d24f904b3069e7","nonce":"124c755a5a9d9445e67918ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"0befa62e096a61ca7cd6e78557b57f8ba3aa2771ccdbb81f77e09f12b1d4eca3bbea999b5433be3dd1312d654b","nonce":"124c755a5a9d9445e67918cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"5860f0036b0a4366db5bc64fc77efcc99ac20ac7170819ae5d459ed6e0e731efa276ef602c27f8dc84a5432ce0","nonce":"124c755a5a9d9445e67918cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"4ba405973138f1cefb1079fe18ac643c6e15c81b88b454261482659906692d6328928b124e2ced4d4951696091","nonce":"124c755a5a9d9445e67918cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"67727cc01a6a8e12747e25e387b92ac8889a22290acb5f22ac00f33abfe402e0f4b424be5231b6afaa342d58d3","nonce":"124c755a5a9d9445e67918c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"cab529faa9571a39fdbb7e7777a8a5d88dfcd02aafb07a2609d2d9a6d7699db5a8ee9d9f2a73b41fb023424c54","nonce":"124c755a5a9d9445e67918c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"6b1768066848e2fea77d698acca2cb475fba702d1d7d8af134757c08de3fc9148d82babb2a52b885e4248f49dc","nonce":"124c755a5a9d9445e67918c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"4a4a1ee0f7e7e440e9af8a94cf4210c31a79b86c94cae7b3dd2f77cb209e4a43aafb2133fe50dc1ff2f8de2e11","nonce":"124c755a5a9d9445e67918c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"7bffb4aee8f851e295cba833a75d6bcc3ca56050f2d1221f328d23243b8c804dc55da1b325444c1230ba69a335","nonce":"124c755a5a9d9445e67918c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"067ea3f26a8c42351eb5a38029a84cbfddc419e92a8508fd70c69d764f1acd5a4a06e62aea235247d639927f44","nonce":"124c755a5a9d9445e67918c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"37ae15377c4941e85427a891f05ed8bf013a353fa9ba7eeccc75ee11666d8b599c1689ba1c7957aa13d9b7ac55","nonce":"124c755a5a9d9445e67918c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"73e20956158eedbc3c4fec098a84302a95a32b881dedd1c3d19250f8b2bb050e0ae8463fc84310f9bede94be0b","nonce":"124c755a5a9d9445e67918c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"fe3f48d60366ede763d736ffa4bae5a5a380922fb1dbcb569250c539b98dabf7ca17601fbe1efbca9ce67b909d","nonce":"124c755a5a9d9445e67918fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"ec069a848f7cf01b190874d2dbbbfec89c3e2cb7ae32b5b5464ba41a42aa48ac66af9ac65cf1ba19139e8ec904","nonce":"124c755a5a9d9445e67918fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"defa6b939223fa162bac4994282bd7e0baed2be53862486f8aa2dd95644c7a5deab48d56495795eb90dfc45c10","nonce":"124c755a5a9d9445e67918f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"0bbd697612e75aba709eb463293a474df790cc3924e6ef947b4d327163dd1df3df6a6f7e2613a757dcb0da9ea5","nonce":"124c755a5a9d9445e67918f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"f572061d8151649fa0118e5a1c815aab104dd98d634f945b6dbd40f241596b76061265b2243fb2dc5335502a01","nonce":"124c755a5a9d9445e67918fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"2905f4e907e7cff99dff8471f3a4b909ef471b526ed03ba1043f43a4887ae4a2fba3221a19107386a033c4ef4c","nonce":"124c755a5a9d9445e67918ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"27189b999d3b340063bf4810564efdcd3e97c25013b675130fcdc8861f9f95eafa0d52d343fdcfdf65e94c4d8b","nonce":"124c755a5a9d9445e67918fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"e94737da6216f404ebd755b1e882b141968419c7b82f0e412b9b14022e56e9e0aee3db3044612af93bd3ccdadc","nonce":"124c755a5a9d9445e67918fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"77652231bab295f7198cf6d851a336557e4149166b3d522c9da069cc50ed52b15a7f88c296566a26f74be66030","nonce":"124c755a5a9d9445e67918f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"2507f11289c6e15e229670b50e467f6123512b734e5e057c2a367c38617bc3ba490bf50e6d762622f3e906e39f","nonce":"124c755a5a9d9445e67918f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"3b2406a6f3aa54d886581ed3f0e69063f1e47456e97b45d83704fdbe79bb4f2b3cc55792b6a6bee2c037ea1484","nonce":"124c755a5a9d9445e67918f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"8a57d9f86204d1910426e5029786614b2795220a085f0421f04027ee6aff6800dcb90e81c07f35705314491974","nonce":"124c755a5a9d9445e67918f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"41210710fe9a63190284b7c7eeb23d67343fd0a99598b60cea696c96f0e6c2433fea1a89e4ed3d565736e742ad","nonce":"124c755a5a9d9445e67918f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"74ceb17e5b0b9b21b4581c06d5aad43d118f1a84b123b958f1a85141408b3d9528b5edab91d2ce2b0732a49334","nonce":"124c755a5a9d9445e67918f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"23a544198dd08ab45348a2d197ab51230064455abff8def5e72908d926fc08c6e5ed200f3d6d39bc30b37bed68","nonce":"124c755a5a9d9445e67918f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"e90a26c2a9b632c812d3bd23e97dcd3334e2c7d63841ef28961add375d3bd0b6e63db8c6331a78b35081f328bc","nonce":"124c755a5a9d9445e67918f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"d84d32580d1d0dc70bc064b1e195f378a3e5bd9cc369e1865546af9e6b8af0b0141ac8bdc92af165787efe6ea4","nonce":"124c755a5a9d9445e67918ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"58b574478202e1414f934f2138f1ec0aded1988366f85bf5520ead5daeee4b9dec73383f307a391a5d7dc85f16","nonce":"124c755a5a9d9445e67918eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"71074b7db01b82bfd971f76a7ce65d481f76654b3a1963d34666f31b0c6e11fa785a86a79735e133ee4fe8f439","nonce":"124c755a5a9d9445e67918e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"e362c7f05e6a60c1a3c66fa1079a6bb74fa343ceaedfe685a2222224faa7edc5ef214b8451610b6f7ce65e3fd9","nonce":"124c755a5a9d9445e67918e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"f4ef5df3f75a8c62dd06ec4b7e90555623b8558a5fa0fc5e63d6e464da928e108d1e13f7816bf02b56125c917c","nonce":"124c755a5a9d9445e67918ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"cde25ff28ac24d77fe8131a5dfbb139f2c8fd0fe5955537407248bb789f572f8d192047ef17317ab117c66b539","nonce":"124c755a5a9d9445e67918ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"d68bb08eaea197e8fe56803276b30d7638bdfda0a62d40b9fe0b058acbcfe738edbe8283769bc1c3ac713bb605","nonce":"124c755a5a9d9445e67918ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"0dd1a4b79e5818ca84c43ef07dee180621bdab6e25de0e7941f9a095ca42d0e2c7df1677f095be9e81ecaabd9f","nonce":"124c755a5a9d9445e67918ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"5b9e2a41fddb408b67bcd1a8328aec54c37d37d26bf86902278cfcfe554c2c9419dbe730e1952d046f12565abc","nonce":"124c755a5a9d9445e67918e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"7c3f8ebc8a6e54edb3c3e3c227ae70094404d40ad5461da27a85448075b2e896af7d26f2f0b68c6b8c3255e150","nonce":"124c755a5a9d9445e67918e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"636b447e16d44c4f40e6c5f2841581dc384e632690f26119ce6a5d01323dc707ad9448d3414b8cf09cd616d1f3","nonce":"124c755a5a9d9445e67918e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"6d384d18383de596f67de5492385d249291431e46daee7ab65e69094248d38545e8359d25bf7cddf636ff14d43","nonce":"124c755a5a9d9445e67918e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"fd73d77f82ddda79d3397cf4e0c1e1f72a2aac5750d71f18d8688d62fcfb16960eece1febad53464fcc294b117","nonce":"124c755a5a9d9445e67918e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"8ee926f2971bff02d69b2d235b83f81342355fbff9daee0d3dffe59e742b345e4c58ade76a4cc08f9bb4166344","nonce":"124c755a5a9d9445e67918e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"93a01f6f5e7f3fda8b866a7f8026dc8001c2949d9e32df18e97079bd4176a21a948c9f956ea4c8de51725af7ed","nonce":"124c755a5a9d9445e67918e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"7eeaebd496d0da1869c41bf247e36d393f7bf922e91002331fcca495fd541418150c179424c3abe8c181dbcf0a","nonce":"124c755a5a9d9445e67918e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"ba50ed518ac3e57303d081f9d4462cb29dc9bb0e0815c9f51dcd175a9c12ec21dae32cee0e1b99a28b920cf69d","nonce":"124c755a5a9d9445e679191a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"9af5e1a89be04b569cba0cc2c62e9770c95f127597b408ca2cf5f08944fbd2f4"},{"exporter_context":"00","L":32,"exported_value":"b0dfce72c3ddfc6671b7efe9d52d7c332b3690dd48ec4ae3550127124c313e8d"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"6be74b9358c5b6169d2c752a03930e72aa2d8b74cc44e36ab096fe2be601a60f"}]},{"mode":3,"kem_id":16,"kdf_id":1,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"86cf426cc60770fe75f02decb23dd126b351475d5f27771751868ce92cf235be","ikmS":"69f8176ac02e8f73193284d46d39824531d57f0e67bf2ae3feac0bb128366f87","ikmE":"741aa0c6fc5ec64372a32cc48662b01c0b75db1fe2d7336e7723610ba5ba2725","skRm":"5dce991791aebaad1819d144b3293b75ced87577ab1a1c1e5e262d04c62fb6c9","skSm":"d9ee3f9e2e73c5b681d143c9b8d1865bcfafc96678099803069b91fd0ab55671","skEm":"30b464ecd2424f30a519d5212b573d6a38088312c575312438b64fd874b9b5d5","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"04aa6664cc7044475c09983c507b6e4972bb6869383a66ab83d7264f977872c8b529b68397d28fc3a6d259fd70f7cbefabfa96b1d3d661a72e983bb8e0dc5ec4ed","pkSm":"049240f92bc7d5faad04d39bc3f1236250ab59918efc3400aa4a463341954a4e1aa95f0daf52e01c45ca77d73917d5650c255921124470a6a3605f29232f8bd473","pkEm":"04cbf5a3a7d785bf8ca6a1de5896009fbf87dfc60704fc0177068239e2200d74a94adb75017898ae49d8884913fc9b4b7719a47832c0861800ddb7b9a596617800","enc":"04cbf5a3a7d785bf8ca6a1de5896009fbf87dfc60704fc0177068239e2200d74a94adb75017898ae49d8884913fc9b4b7719a47832c0861800ddb7b9a596617800","shared_secret":"9c0b65cba2f417717e3213daa085cbb57c5350adf4b27f91b9e2d3f66418a2c2","key_schedule_context":"03b873cdf2dff4c1434988053b7a775e980dd2039ea24f950b26b056ccedcb933198e486f9c9c09c9b5c753ac72d6005de254c607d1b534ed11d493ae1c1d9ac85","secret":"fbfb23542c2769d2c0714261d184b04cb5a63a21b39c656886d317c355c5e790","key":"06100c5921975cc1aab7bc7528427e48","base_nonce":"6839d9a86d5fd8bcefa5a1ad","exporter_secret":"dadd70bee6374dabbdb80a0dbb8c1d5904b5cf1d04a8a84e7368828786af7cfc","encryptions":[{"aad":"436f756e742d30","ciphertext":"6ab348e5a953e00c6de6ec2a801b5dd0fe5f8d22ab7bf53bc7d967b03341ab5a964c54f60fb8bbc2c94a0221c3","nonce":"6839d9a86d5fd8bcefa5a1ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"a1e28e5a3ba3c9e3e3bd824811f7ea2ff8ce7521d317e5da810cc93b0f05a0483c3d35aca0ef6f1299fbe9bf52","nonce":"6839d9a86d5fd8bcefa5a1ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"07eded4415974d873aeddaa770552adfca18447dd7f08032f53e4fd5d0a62d803299921f85e1701c4edfa7cb47","nonce":"6839d9a86d5fd8bcefa5a1af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"420fdf143eddaa1492aa733abee1004f00bd0b16d15576b4846d7a2aab99f465f60aca5777e20694b677aa5b8c","nonce":"6839d9a86d5fd8bcefa5a1ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"a7e7d15c44829efab0c783eb814076aeef9ce7ae8ad789599658387b5bf63d2e097821d42999b03c1f2007ead1","nonce":"6839d9a86d5fd8bcefa5a1a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"7df5f282f9aac2a102abf83c5cdb126e5ff90bc4edc327861cdc5f3e8db45d5116fb3c9e3d323799ca13a1aebc","nonce":"6839d9a86d5fd8bcefa5a1a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"32b21fab5874c4b8a5e207b132dbdc3a4eb93f17ceb1acabbad0148c003f8589ade7e07e2a6d49a4437ba1ebf0","nonce":"6839d9a86d5fd8bcefa5a1ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"0827eda19683b067c7678b4058e7001df8fa8b7401eb4d7dd1468bee65d90093271265048fd3c7deebf8ee485e","nonce":"6839d9a86d5fd8bcefa5a1aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"910e5e99d5b1caa3797f08287f203bfe381e51a2758286c51d031a7a9a88e587e1b44a4b59f5238e699d75a4f9","nonce":"6839d9a86d5fd8bcefa5a1a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"0f0fa17a780e4694b038edfb8e1e69bf274e3562cdca4024579ef6b80e4aa12e90d13f198776139b687c821ba8","nonce":"6839d9a86d5fd8bcefa5a1a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"24c52ab14051398beddc34a67107a50933f9680f5dc26be9f9ce3c2db71fd98f91e787374d1e658b68beb69405","nonce":"6839d9a86d5fd8bcefa5a1a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"0ab60b5f69992037303c65d10a6aeb45c29ee33308ac9c225b7229457df45ae3ac2e1ea837480113f96c30c870","nonce":"6839d9a86d5fd8bcefa5a1a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"0ab38b13b21984fc1360d2b44314b9e6fc32ca06cfd644fbf129410b76664d4c0bb8fbd2a774f08eabe326a894","nonce":"6839d9a86d5fd8bcefa5a1a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"f8de91392d89a341f81a42a14afca49332be56b64d594da2ea9076a9e0024d74fc8346464fe5b88a9564e936cf","nonce":"6839d9a86d5fd8bcefa5a1a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"20b9616716a4bd0d1e226cdfeec39f6fc402017c8f8e32d165568e4065d9b330e00e9c95aefc4e08058aa44e3b","nonce":"6839d9a86d5fd8bcefa5a1a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"71d8a98b198db106610287e228b865af213cc2e5b744869a3c00910797cdc9428b1fb8be401a7ea9fc5e74b4e8","nonce":"6839d9a86d5fd8bcefa5a1a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"297fb5dae2ff41e0abed99cf237d66ae640de477e4e61ae3193b08e0c6b82c8d5175d240b8402b64958aae0a8c","nonce":"6839d9a86d5fd8bcefa5a1bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"05316faa9c5fe5614dfb06aaa2e2f8aab55128d3f76152597abaa254e0d668cc429dfb68f6a4f66dee83c7322f","nonce":"6839d9a86d5fd8bcefa5a1bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"fd9320246a9b7a14c02e19f964b7164036f717a7c14935059e48e9a349c278c788b513a19103adcf62f1720061","nonce":"6839d9a86d5fd8bcefa5a1bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"562fe19e2ac59ff1ff14ad51636d11eb9fc415b66af53e2c5fe3bfab810f207f99363fe82cc135c2b4d3654fc6","nonce":"6839d9a86d5fd8bcefa5a1be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"8deeea2d8baee81de5b76e1a820b878c8f6af75d4235093433c38b27ff2ebff3803474ae01537c5583f61a3a67","nonce":"6839d9a86d5fd8bcefa5a1b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"db131539a51ecf3612f7185077c9322df4f8123f3b9ecd60ac5e1e1ec0860afb68f864990c578d2ce666ce3941","nonce":"6839d9a86d5fd8bcefa5a1b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"6fcbc0006efd7285403d0db19d64fa4d64a2785d4ed72972ef1336b8af95dca94b6c7b7496e028b8afbaeab27a","nonce":"6839d9a86d5fd8bcefa5a1bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"d48ec5daaac6588799b4a2b135cd2a08e864ff9bbc86cf4c491f442a0cf736d1f343692bc9210c880b2725c8dc","nonce":"6839d9a86d5fd8bcefa5a1ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"41aa11c2a9cb4fe5d5e3191601100e96e466433a397d1e6b57dc4917099cce235f21fd1bac702dd995bc1bf840","nonce":"6839d9a86d5fd8bcefa5a1b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"a5218ebbcc99753944b9abed97bc0195adeb15f5603c97896e7911215f5f07cbfd277995a299eb126b26e6bdcb","nonce":"6839d9a86d5fd8bcefa5a1b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"b8fe39edc61bc3a502932fd23aebdd0e9010cf52e16f991e55f38d897d375b6d84afe41ce52093197a07079d37","nonce":"6839d9a86d5fd8bcefa5a1b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"cb92b5a58d54090d0ae31c5d5c5c8c1bcf699f5d6b6c8efe87861aa1db9ed330c0ad5fc4784d0664560dd2b1f2","nonce":"6839d9a86d5fd8bcefa5a1b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"db3d2bf7759c4dbebcdc7e2c1f4d7c1478523b1b9f46fa7c775bfaa3a33378a6053a2e9549e6391ae3d742d9a8","nonce":"6839d9a86d5fd8bcefa5a1b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"f1c620ece1f3e2cf74f50146a93e4b62d3b64869cde3eb7cbb30b2166dcf60671f4832bf88aa8cbec5d199e6d1","nonce":"6839d9a86d5fd8bcefa5a1b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"37ab209f49223e3e952dcaa24aac49d6b5d5119e4b04d3f90e2176f97c0bac0eb1eec181b1d2c98b9984cad757","nonce":"6839d9a86d5fd8bcefa5a1b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"7494f959d570446107f5e628bd3013c3b2ad3f831e59db4d4f4afa3c4cd39c234c1c6a58f36aa23d6e41577b44","nonce":"6839d9a86d5fd8bcefa5a1b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"5a8d5439ff111d976c44c4b60238625be32874cc28ebcffe54519eccb3ac686aa1be79a491a47712b30a38876d","nonce":"6839d9a86d5fd8bcefa5a18d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"7ac998470f2083b2ed34aa977333edfc45bb2130825e829467379844235da4005bbb880284559c198b8b1eff44","nonce":"6839d9a86d5fd8bcefa5a18c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"046afe94b8152e6751871bbc724eb2267c70c24f9b0ae85b93d79a2ed778b5e68c67e2d48bae46f20fc9ea68c2","nonce":"6839d9a86d5fd8bcefa5a18f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"b29e76f930f03593ea9ae7e5f01d09152a2e0239087cfbab677a61b24856f73d9a14625f5ccf6abfc56f38b243","nonce":"6839d9a86d5fd8bcefa5a18e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"44ecf9402a043b2ca78c47ad83068f9753fedabfd443ed75c887a1f757540667cc7cce558673dfec7b1ec9d986","nonce":"6839d9a86d5fd8bcefa5a189","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"e23c0e9b8d3f715c92ec4c8d67a8c9f0635a259422b696d07aff9197cfb95ddd906b5a589094fb1736687f4dfd","nonce":"6839d9a86d5fd8bcefa5a188","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"29614474258a8121710d81b9a4b8abd2ca3ee6553480d066b1312e2a39eda8adc938fe5c5d60a102ebc78affcd","nonce":"6839d9a86d5fd8bcefa5a18b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"0178fac06df1367381319f8789eba9ecb64b369ebc17ffaffbe9142b5a33f9285cdfe0bdae90e02d8416bcf3a5","nonce":"6839d9a86d5fd8bcefa5a18a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"643b205b76b1394556b1bd123d00388a15f13da095f63021358166693dc402420deefbc2f423637e072e22e709","nonce":"6839d9a86d5fd8bcefa5a185","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"8e2ea6ea0c05ac9fdc90044e875aa689df90b2fd6f6141134eb34eb9b213ff05b39814de51ae03b7d588c7a2e8","nonce":"6839d9a86d5fd8bcefa5a184","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"61fdfa23c020dc6d9edf27271bcbc3202173b453a9cc0ee06886a48b8d7ddfd48851fb562145b95746e18fde6a","nonce":"6839d9a86d5fd8bcefa5a187","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"8d7d3c1d78a1ffb03da0c4b61383f62cc1a7313a177693a3e8def5c297c20fe3320af6b5649247a2518dc39677","nonce":"6839d9a86d5fd8bcefa5a186","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"826f6fc1dfffb601b18602686793495669f7596bf38fae9de7bcbc4f7d5e7d9fa613a59a28e1ec74df318c4272","nonce":"6839d9a86d5fd8bcefa5a181","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"a562b4bdf086d967b70126b82663136dc385c04eed4a832ebe8ea217a1a2bb4e1a9ef37c74a9fa3307ce41c756","nonce":"6839d9a86d5fd8bcefa5a180","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"de4df59348538c62b65cac27c98e0f5bc22f7922a185fc344f6c84e95076db7782fe50684906b3eae9ff6b6032","nonce":"6839d9a86d5fd8bcefa5a183","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"175f4dfc871c818e80d37ea3d6d103d1309a804c8ed890bc9e6774474ae64f99976aa7661e2be72d15c51d3934","nonce":"6839d9a86d5fd8bcefa5a182","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"08f5441ebf83871820712a222f0d514bd71d0eef349b0b3987127a14736645bce28dc68dd7f61a73c25a463e2f","nonce":"6839d9a86d5fd8bcefa5a19d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"e410b271d5935b8693e4f0a5b3ed93f05a39c4a12619b6e17bcdcc6eae7e3267d4338c51000d95f768a6a94af7","nonce":"6839d9a86d5fd8bcefa5a19c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"7a82a9d202b09f392a63dea462f852658f4e3e24e5dffd1ae800d336baa4290c5e7926dc3f8ba43d45dd1e4252","nonce":"6839d9a86d5fd8bcefa5a19f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"9116abf982ca7a8e41a326bb3bbc8dde4039ad04581749f0fb16866d4a166c22408dd48b2a1eb42ca814c3535f","nonce":"6839d9a86d5fd8bcefa5a19e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"fa0991a410259d3b786e04ef1c7a7f1576fea36eb1fee137a8eb9d34e48317d6c70976cffab5ff85b81e6c32ec","nonce":"6839d9a86d5fd8bcefa5a199","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"ed8478b7e4383a45e40e756bd79fe8ee1a6aaf7f9dad640f1f60162642fdb6f40bc7497e6bfd6ec287dc5755f2","nonce":"6839d9a86d5fd8bcefa5a198","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"24be5f404904d267feb7398e797b3c403662f4c8db6ecd2c3f3f298b178991c726e3565df3b93cff4a713cb9c1","nonce":"6839d9a86d5fd8bcefa5a19b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"d6cc60f2e3d2e4f46d4e51c7c8cc90107deb11dead45ed60633ae459a5f6e77bf17f44c753bacfdfcbb6aee7d3","nonce":"6839d9a86d5fd8bcefa5a19a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"61a337875802bc48c854e676511383bd133358dfe1a26f22ed0d6f73df64f80b0ad78d25239d845ecddce700be","nonce":"6839d9a86d5fd8bcefa5a195","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"b2d667ddce3a34e86ece4cebab60a415d9abea5b1769c0bd3cfdf357ab51aa63aa1ebe946405a275710f3bc5fe","nonce":"6839d9a86d5fd8bcefa5a194","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"de1b0b9c68775d423f66f1e2298d7773ddcb5ce9ccf992372bbbab0105cef58c1fc863911d38f7863c44bcd93e","nonce":"6839d9a86d5fd8bcefa5a197","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"d6c85180ff52e0408736ee5fef339d090f706453158a7e24952d5903621d4cb0c16f43f8e18535e7de6aeab53c","nonce":"6839d9a86d5fd8bcefa5a196","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"d60f2c04ca52ee9d2d4d1c0fd1c4cd23cb6faaf5eceb0a6e91fc76572fffb019bacb79c762fc87398aa2a0e425","nonce":"6839d9a86d5fd8bcefa5a191","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"5bb24eff08206dcb33791af4de48ed4ff148d9ccfcdc4601763610b2fb5d3540ad490ae8e2a8b3d6596e7ea65b","nonce":"6839d9a86d5fd8bcefa5a190","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"e67a505abda4f24750d646b388299979b3d85fdac4effcb19d5a86fbe0c6771e2e7d8c22c9d37fe3029fb74ec1","nonce":"6839d9a86d5fd8bcefa5a193","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"39d7db9583bda2a60d991d73324c034d1dce984c49e8e264f27d896761e95101da0791008c98f5488ee846fef2","nonce":"6839d9a86d5fd8bcefa5a192","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"2362631094f7fe4b5ac2bd7df6a9a4ae222475acc2216da3fe33208beaf3189f26389c6cb3b2fc826db094290f","nonce":"6839d9a86d5fd8bcefa5a1ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"73d8fc9319689c9aa12e0773d87f487c1b73b357ed9c55ac729846814686d56c39e8ae808bf6233911bebd397c","nonce":"6839d9a86d5fd8bcefa5a1ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"c98311d7155f240ccf059c54c4b9e4378124a52e794015842f2fe4d84d9ac95a0b1dc56a2b2905176c096bf62b","nonce":"6839d9a86d5fd8bcefa5a1ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"c0c7c3892c112c929d1544d8853639424a219d24a462c7337092bce2970b0777b32e39ef3ea75296247135b03f","nonce":"6839d9a86d5fd8bcefa5a1ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"1ed5bbdcbedc13348467b507232577119cb519b52c3cafe636d2b2c364a429208182705d492ab465969c59e235","nonce":"6839d9a86d5fd8bcefa5a1e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"b00ab810e0759cd9d0aa55e4a3a249f08aefaee25b1d9584b380cd20f12db26bd1edeb5d757ec0d5ab1a5aa269","nonce":"6839d9a86d5fd8bcefa5a1e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"9d117aa621ff86b7b0f470e8ee4953408e5c35a976f671a86efd5cf69cbbc601908c6315fddf3e48bab74bbaf7","nonce":"6839d9a86d5fd8bcefa5a1eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"58362648b536cb999045cd7c0c56783e08d64688d5ad3dd30aa93e26399af88538cefb3824007c9731119e6b13","nonce":"6839d9a86d5fd8bcefa5a1ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"eccd18b78b4012c1693ba649faa389c7e049cd76285d464455ae8670a1fceedd812c389b39fe1bd1e154f4e3a8","nonce":"6839d9a86d5fd8bcefa5a1e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"7c7b67317f87b21af3036f3083817120637575c4cab39f4c62ca4e87e074edeaef169ecf8aed6ba412b6da258b","nonce":"6839d9a86d5fd8bcefa5a1e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"abe1a299693807c792b24fb600ca52bdb61ae4e38b0f13ff5e64c9c7b69472c4359f2655252f66b59fd257a9bc","nonce":"6839d9a86d5fd8bcefa5a1e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"62c3801a427d86101a80672e8efec2e6f3fd8cbc6bca4f35f131ec119df73aa8455978de2b83b466562ec777c2","nonce":"6839d9a86d5fd8bcefa5a1e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"60055400bd1262acd01e526d21f3e69b49977b861b4fd8df6965365f60505a4359fed8e8587ac9a95ad111ebdc","nonce":"6839d9a86d5fd8bcefa5a1e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"7a939980277b6dac0a86f99c5f5333c02bc2858c326780600f5ab05e2ec0b274322ee6b91ec01ce864e7beb32f","nonce":"6839d9a86d5fd8bcefa5a1e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"9ef8f0b10788b0bf4fbc789d727fe6ec74f279cc3282a7235481789057d98206aa0138ce4919089906e7fc5526","nonce":"6839d9a86d5fd8bcefa5a1e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"4f218876590d7a68236ab03456842e4052c5f4c1e3d36917fb716051a6f8618eae1a3336d63ea66a21d078dbce","nonce":"6839d9a86d5fd8bcefa5a1e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"0d795ef5c5e02ab79d4c4460ecf4cab6220442aed3ee6681966105f1a4e12d363ff5cf2321ff3377210d62e3b0","nonce":"6839d9a86d5fd8bcefa5a1fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"7684b48080b15f58ee3e9fa43a9be736ade8f3f0fb523561712247bc890b14249c2c457844599340bc0947c992","nonce":"6839d9a86d5fd8bcefa5a1fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"e057ef39dfc37418aab8a040976dc7c3cfd2c4a94547bf20a6b9b980173ed37e8720c9a5b2e86169c802c1bcef","nonce":"6839d9a86d5fd8bcefa5a1ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"017c303deacc8d9237dcd63e6d6a0c840abcd1ca53903bbffb85ef6121fddc0d26325b24ec24651f49f13be35f","nonce":"6839d9a86d5fd8bcefa5a1fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"53f1fb4ccc9bd326892714996c791820e516184149c0c6223d126a4e35bb1673a47d192a2ed9ed005bae5499fd","nonce":"6839d9a86d5fd8bcefa5a1f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"2dc33a82fe98f5f85854153c71f8c46616cb4b44ef7a68e82c90e59a3205d7fd0b5d5640dacb1809289f5f0125","nonce":"6839d9a86d5fd8bcefa5a1f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"0667670c34b7acfe95ec59d8beb9b4d2025933c8a1bcf73e300200eb592cb5df28dca968f51e68f9b4aac3a4b0","nonce":"6839d9a86d5fd8bcefa5a1fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"03cdef8a6f352e66178786e451bbf199b82764b72c1a90cd8b47ef0b486d67f036437666f6830e9647ea6f7102","nonce":"6839d9a86d5fd8bcefa5a1fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"1abd63285ab607860a40a2b12e59d43f50d8d223e365954c86f831715ad2ee3d3504ddc1c2dd6b501d9c514e57","nonce":"6839d9a86d5fd8bcefa5a1f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"f8c61dbd052992ddcc3773b6d755afcc142caa2ca530e50a21fc2a8c610a4d4c6ca0c1b352f543d109f55aee1a","nonce":"6839d9a86d5fd8bcefa5a1f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"7670b94bdbcd1a4153fb28bfdcae1f4a62389bdebf229b801131f886754edd0bafeae65612bf72a16520e0fe62","nonce":"6839d9a86d5fd8bcefa5a1f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"463c3013a0464bc727eded8d3fcada26080605d8f434af5c438e703490a24651038d66e9b833de9e79408bc100","nonce":"6839d9a86d5fd8bcefa5a1f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"62305e36f2012c2efd203101bc4c4e18b3d37d4cc15106c7c6f4055acb0ca0f9b31d2c71f562b9417b9ed1e94e","nonce":"6839d9a86d5fd8bcefa5a1f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"ca1273acd26353285eaa00457bb559d0a73054d2eb6ccaa122a0591f90d8d1c53badaaefce079359b0088d71b8","nonce":"6839d9a86d5fd8bcefa5a1f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"8dcc20784349449c879173cfea851deff1258cdbe25ebbda75d680e8f30c6961a0375fe3b9008f5b57f19b86c5","nonce":"6839d9a86d5fd8bcefa5a1f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"3252b553a251ac280b1822634c44c2b7d377f4a7bde5925ba18541231d6049921392e4dac7dfac2329d44f115f","nonce":"6839d9a86d5fd8bcefa5a1f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"bebedc5c1f823eac6d30d33d88699b2c0247eecf8c0f9008a23f90de371571862ae1f72d8503c8981db7a9f689","nonce":"6839d9a86d5fd8bcefa5a1cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"cdc1af5dc251cb2dc2b1dbd993f0d43cbe60dc79d28e7ebc8e41eb0f4fb3e2a7dabc5180f09c873c5984f3930f","nonce":"6839d9a86d5fd8bcefa5a1cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"050dbe680eaac3423a3c20801338e0aa0e08167c9f671540162784cbdc5de0e0b255d05e2ad26993eef4516eda","nonce":"6839d9a86d5fd8bcefa5a1cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"2e2aecd1af9f94fee39e81c1165477f251968bf2d648a6f3732fd50bb0da76cd1a2786f3a39c594c77b55def67","nonce":"6839d9a86d5fd8bcefa5a1ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"acffb31f6ba797a401102cb680f8c000907afa5662a537ecc329607037eff7c904538c6a17d57dd8a6420a98bb","nonce":"6839d9a86d5fd8bcefa5a1c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"66081ccddde31ffa962ce051ec546feb0ce9117956304105e4233fe1fa1e12c93e0ed348394e20ed967de28e42","nonce":"6839d9a86d5fd8bcefa5a1c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"02b2b14ba91659ef060fa5b9a0fd692bb0bc170b6ce06de67643e76f0bde97f948bd12e0e95d3eed63a79bece6","nonce":"6839d9a86d5fd8bcefa5a1cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"6463ebf304474b1a0b4b23e5d2b4493f67849687fa97166d0acc68e8e0f64e3b6ee3867f1b2a787f285fc0f010","nonce":"6839d9a86d5fd8bcefa5a1ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"d8926bf105a97d5856652e4c9f79e791baead0e99847f770f28ac055ff59d43aad5806833939a3fda3bdf6bbeb","nonce":"6839d9a86d5fd8bcefa5a1c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"0a30172788941c2789ddcefa2b64faba952b17ee2b70e15540313ceaa1eba186828d9e1d5e06c291c2810968cb","nonce":"6839d9a86d5fd8bcefa5a1c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"fe40903275f744de44e616382cc6323e309f168e1bca5016948b230e45585cadd74767724b3ff425580ff99c4a","nonce":"6839d9a86d5fd8bcefa5a1c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"d77c51f1f7485f60e02f03c9818be7f2b9bce88ab7a37446b09070c3e99944fe40bea37eff4e7de29321789785","nonce":"6839d9a86d5fd8bcefa5a1c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"356a67fec079e5a53373b4190a64a67192a33679b4434ab1847b0b141d5a0d2ab019648a354123991c3fb989cc","nonce":"6839d9a86d5fd8bcefa5a1c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"e7c390e8c5a0a4db1e97888c74506c803951801070b02cd5e75911d5790bf7b2309ec70f1bd3c6ba8f8615e008","nonce":"6839d9a86d5fd8bcefa5a1c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"be6e924336ecd4c3e336c655b5fc960616b553415b8bcdd501129758f28e9adff12d796907fe9cec11b86b5e37","nonce":"6839d9a86d5fd8bcefa5a1c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"c51056cf76350c17a2b31aff12b4eb282de2ed96ae69c32f01bc259c2128579aa62a9ea860caa033772ab22425","nonce":"6839d9a86d5fd8bcefa5a1c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"2d83afd9660313f3f221a3212555a2c5ab4e3b4229c5e16219ef3da71a0e2236899ac19f05e4c46c17dde6b727","nonce":"6839d9a86d5fd8bcefa5a1dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"8ad301b904ef7d7bc22403531407a7b161bb7ed1aeaa49de008ce09472019f0667004c61fbae1de486e5961177","nonce":"6839d9a86d5fd8bcefa5a1dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"8451101e339c48f7eebe60876c01caf88e37a69a944f90bd73278503138178efe26379dcc398251387719ac05e","nonce":"6839d9a86d5fd8bcefa5a1df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"d962df54aec5db2b87d934c2501706582dfc4934c5bd1e695dee310e4bf40588c24944cda56aacc9fd106923f9","nonce":"6839d9a86d5fd8bcefa5a1de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"b9219185b08b9ade3671ee6e35baf6305c42e9df2dda3aa6149b55b599cf74ba409c8db1bbd951f36091a85e60","nonce":"6839d9a86d5fd8bcefa5a1d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"c5d2582c175a7ea3ab1e3a7922dfd56f1e64752c958554a76d9bc9346af532e75f06be8c8208389bb39d8a3b58","nonce":"6839d9a86d5fd8bcefa5a1d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"6988efb29f2059fcf43b637c130df14ffb0e92c1fc3e8cfcf823d92c51416783ca561d3b1dd4aefa8f163299c6","nonce":"6839d9a86d5fd8bcefa5a1db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"4d179333c7a1cfd8a0de13555e796f58c5c9b80a33bd4974fed1ad2b37fce0cd64073d85397838d9e827b632ab","nonce":"6839d9a86d5fd8bcefa5a1da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"045ca3f01ae19af716261c8639707ffd321391af643724f8261149678dd8307ca3818904a13758a47aeb289d50","nonce":"6839d9a86d5fd8bcefa5a1d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"b859a07c84a7e703501325ddf167fd5919f3524993af8d2b7f00e5ef4ee9ca8073d6da5270b07f2d9b3a5e97ad","nonce":"6839d9a86d5fd8bcefa5a1d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"298e73b0ad8e7c203bf2d9ba6af06852167d14f0ddb31cbd140d2299b16c9eb8bef2e887fb5e3f6239ffa87588","nonce":"6839d9a86d5fd8bcefa5a1d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"2bd5dd288357c535a57847e478811bc3d9c73af2935d7cebe69fa1d2ca4c3f1cc4a033dfe660ea6aa80c16d72b","nonce":"6839d9a86d5fd8bcefa5a1d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"b3884709c447a260af76262c14cc187ea5bff01991306fd9f74cb4f525d6bb9ef6c6ebe66c90b4affbd1771c35","nonce":"6839d9a86d5fd8bcefa5a1d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"9f8fed62614616bd8d441efa304b7d8cb52c82872c4c90dfa0651e169581c07651d7ad520c33fdd74781f217c9","nonce":"6839d9a86d5fd8bcefa5a1d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"9253484a3af9fc91f211db548a76f6c51667073e133f4c3d94d9c9eb7a3c8d3842da59e8cebd2c1726e4a281e0","nonce":"6839d9a86d5fd8bcefa5a1d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"1c2ef0b8f17170c413d241440eb31da4cd135516b68fcf86ec549a7137fa5af8f22b83fda3b3e6354c984e1262","nonce":"6839d9a86d5fd8bcefa5a1d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"ba071dff0135adb131fec07641eae33b3645fc98d9506448090e92a08b71c0b6345f337b598f36e7f310d4f926","nonce":"6839d9a86d5fd8bcefa5a12d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"0f1475885822bd0b966cc84c01c12c0287973cd44703b35bdb08ce957000d72e41f571cc2109614c27c10c1e05","nonce":"6839d9a86d5fd8bcefa5a12c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"a0d284dfc88151298636c7d70da2208e6c59ec8345f1f95d6fe8adb5d7aaeb745205dd71b17153210addad89b1","nonce":"6839d9a86d5fd8bcefa5a12f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"bdec9d41a0156f46bb9d402e6f3ce8e4711d09881318b6482e800b71bef13468705eabd4b193b5e78a3260837a","nonce":"6839d9a86d5fd8bcefa5a12e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"4de67b6fb3e652a42baec0c85696829ac068520630f17ff5faba5a358151a757f3d196c002be9aa6d85decf3d2","nonce":"6839d9a86d5fd8bcefa5a129","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"f0d3aafedb7d42b635b11c8a30f759edae2dd6e05a133c7a58682aebd9d31d2d7afca0b70a5a8d8a72e0d30bf5","nonce":"6839d9a86d5fd8bcefa5a128","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"2f250d97d4c93092f43539318de5f6e6bc071bb785ea0c4765b60e1259f3b0605e4a941611a916f9e29389e59d","nonce":"6839d9a86d5fd8bcefa5a12b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"edadd6c91c7145fc4e9b7f07a739ba8aab20de5e0cf84e494f2fbfe4a75d12997d223300486cb706e550fea387","nonce":"6839d9a86d5fd8bcefa5a12a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"2cb2863f237fa04fe18d41eb9e73ca5423bc85c2479d8cfecedb3b6cb20c34f451d28bab470a51f96c9a8d8f1f","nonce":"6839d9a86d5fd8bcefa5a125","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"798a1ef08396cecaf391c3b0dafc9b1cce33b86760c55bafcad2ae73a4ed189965390ce4e7731e90250662af48","nonce":"6839d9a86d5fd8bcefa5a124","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"ef14c7d631af682c0ed6ed1c8833a599a99b43a28652a6052bb1ee47715b7198c1c8fdbc1a94f855e04b3d8491","nonce":"6839d9a86d5fd8bcefa5a127","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"764675f6e03d867483e9202cc414ed84603d89907b53d76a886c0ae1e6b1f9f810b38c9a08e0477e63aa2880cf","nonce":"6839d9a86d5fd8bcefa5a126","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"bf45cbbb3d75a11b39d47f02cd002349208a6076c44a4a785b225bcf6f11b4c8aa852a72a65bb6460e9304609d","nonce":"6839d9a86d5fd8bcefa5a121","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"b215522cb388fd08129eefb2af35e8f430e58d9dcf25ea1dd1195c6c074daec7df89ebb483dc5fafa0de953c99","nonce":"6839d9a86d5fd8bcefa5a120","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"3298918947b116be1d45270ab592a6abdc260a0bb87ec46e5802561e44fab77c2821a814cb1de34337faa8696e","nonce":"6839d9a86d5fd8bcefa5a123","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"8e6e755bfa47fbe6cf96fe04d6f65ca447850627046a527e83ee9ef3978c4aa3f30c5a5964e8d58f5713e96cb0","nonce":"6839d9a86d5fd8bcefa5a122","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"4ecf5da3501c5030a33cc446fa6b5eb99db3383883cd2b481c6dcbb2605c31464063f719790cdf7513cabd02fe","nonce":"6839d9a86d5fd8bcefa5a13d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"65bd4eaff875dddd38de74c701fae2dfc9f59c702649c26ba7b012ed1a471b1529b5263dcc1cde7a15118c53c4","nonce":"6839d9a86d5fd8bcefa5a13c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"77b1cbb087205f40fcc8637266604f68c1d865dc31e52b42a4b007210d66e25489db1e8901eb9abc1bf1422e99","nonce":"6839d9a86d5fd8bcefa5a13f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"1af1a9ff91efdc0a424d849faf93b6625bd343ac047b98c91d44a7eaf594adac9fdce3d6668fa8d582d9a6d866","nonce":"6839d9a86d5fd8bcefa5a13e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"882dc5933a3b732ddfcad74dd23ae045f6c1a8e59d7b53999167612408b20b1d0673eda285a67f9b6609cb0ce4","nonce":"6839d9a86d5fd8bcefa5a139","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"cd8c932f49ef90c029b7a87ea94ab213a3e19bef6c00ef3eb4369a4641e3b9ba020ae76189c88dfd391134ae46","nonce":"6839d9a86d5fd8bcefa5a138","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"fa7c30280777b7c6f89856d23e4177dbfb6a22214213afcf865d419f6ed47b1ed933d396901678712b94f2d131","nonce":"6839d9a86d5fd8bcefa5a13b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"ae59249d40da64c1ff31c493a1818de8488500666a7f1a31134ebc4b2e0493257640264407caa33742fc19df56","nonce":"6839d9a86d5fd8bcefa5a13a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"a215f7342b7768cb7d9babf5c514b523ff62fe66635ea6fbdfc3be8353ada691eedc440f93df30bdfdcd9d5761","nonce":"6839d9a86d5fd8bcefa5a135","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"b16c95be7e98e8bd8cb5e6d02e0bf0069ee5d60e43ebd97c1cdc7fc5b2547bc7d88da06ea770b19696112b190e","nonce":"6839d9a86d5fd8bcefa5a134","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"4754a07a184273ce354a93b12cf8006e1a4a4f971db4eaaad484dffe46f85824edfb5c20a23d83a26840cfd875","nonce":"6839d9a86d5fd8bcefa5a137","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"1c0faa095f62e30d4d2e13307bbfcd5e5ec13143ec8d136544bebaa5bdf6792f9e4606d0d79094864fea1a417b","nonce":"6839d9a86d5fd8bcefa5a136","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"3f1ce402bd7fb65d6b5276915a0759b7690697e3ac441b6b346c83bc1707ed98d6bdf55e5769350535ef7a3d46","nonce":"6839d9a86d5fd8bcefa5a131","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"43af8239f7b623f5a26a2b43613e592e80ba558ac2431befd09c78fee783055f95ca75c9b4bf142bbf67773b2a","nonce":"6839d9a86d5fd8bcefa5a130","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"94a405bef3c713b4b066df0827a2e7f2eb9f2fe4096f35d17216fdaf8777d5e45ede3182c8a4e2f7671838fed0","nonce":"6839d9a86d5fd8bcefa5a133","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"746eea007bd9e8c3de4a33ad0cb87f4c28d76046cf7f26c312c3892f2c9f627d04baa7fdd185d1b6c78c538e91","nonce":"6839d9a86d5fd8bcefa5a132","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"9939e64dab9f5adb14c2e9e36393d3a263e07c4bdaf1f786a31d24af98e1f58534ef77e505d95954f7e3f81694","nonce":"6839d9a86d5fd8bcefa5a10d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"2127eb6bfd2a470a178f2b5f227c8ea24715f384e9825111194f8cfc17bca42e457a0d437d0b538159b02908a3","nonce":"6839d9a86d5fd8bcefa5a10c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"03ef975076ed13b26b3695102adcc1697e5e54b24614109806b6aae1b246cb424da4f4a4d5e9121675cf018321","nonce":"6839d9a86d5fd8bcefa5a10f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"b7dc88dfb76eeab61826c98584a520056d1cf8cc7f44e4f26cb5fc7ebe082a75e9b040bb43996cdf3ff366902f","nonce":"6839d9a86d5fd8bcefa5a10e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"324b6e7ac59d634b1d1ec444eadde31d1518ba6354677e3b476d189d6d24fec65aa024c90a51294f4944cabfe6","nonce":"6839d9a86d5fd8bcefa5a109","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"6e6ec1a47b4d4aa50ee018793ec5d67335635ea4b30b91d62b723ceccde4262e1ef952dc392cced16164fc72cb","nonce":"6839d9a86d5fd8bcefa5a108","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"c56dc792656a8ca1b5d4b33e173144cd3e1fbd114fd21c2256e4cdbcc3b5a1850120329362a631f57de24e7829","nonce":"6839d9a86d5fd8bcefa5a10b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"9416bc76df5b06769a965a2ea6f23634d7a98d50e37ee4676621cd3b7f248d177ad9d0cb91941e3974b55a5c4c","nonce":"6839d9a86d5fd8bcefa5a10a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"e2cad5a9230d141cc3d2a6a1861cff25ff14cc1c71cc79c02277542c7dde2baad5bc6240bc2d14d3c73ae2ee12","nonce":"6839d9a86d5fd8bcefa5a105","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"3d5135a517a45579d4db3e4532cc8a50b7cb6f734557f6eb32e9b156b743c520b1286b74808e12eebce81fcd30","nonce":"6839d9a86d5fd8bcefa5a104","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"5ed410b31e99fc24c1cb80c05a5cb65e5e96c5438dc874c1d0b9d80ce9a3aa07a4646d518582efb366fc842a65","nonce":"6839d9a86d5fd8bcefa5a107","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"a4b06fdd9df3051f23ea9d3529eee1f6d1c97a08a3ad499ac4d99cc70ffe8082e0ea377aa1379844fe3890c82c","nonce":"6839d9a86d5fd8bcefa5a106","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"2bf7b78c8fad39ea068bc0aab2a1c0340273dc97f801f26f98ec5a12fafc4ee4f9f722382627ec0892ebe057a8","nonce":"6839d9a86d5fd8bcefa5a101","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"d10f0550f0ccea560d16d033340cbed36d7650d69d43773a651db0a8c8fd57e03842e29d6b7ef48030dfd60c5c","nonce":"6839d9a86d5fd8bcefa5a100","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"a6ef9af40f3dbb3e688970dd249bad057b974c7dac043a47d3af0e1a80c27cab28c15be3428a70100c816acfdb","nonce":"6839d9a86d5fd8bcefa5a103","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"bb0adb5252ddf3e84217606822c55dc9b5ec46cc02a0752852819527a212c7a619d017280a609f761dea314bd7","nonce":"6839d9a86d5fd8bcefa5a102","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"2b3a897c9f62a4dcdf5cf6ac49a01fddfb3c82676cedb55054ea5cd67a417eaa2a23f42803f551f75b2f59959a","nonce":"6839d9a86d5fd8bcefa5a11d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"4624fcb20c42c5e1c601848ced07c48e05857ab83c774dc55bb778e814990f1bfd14dc51ffeeab5075b0492a68","nonce":"6839d9a86d5fd8bcefa5a11c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"3e4f036ae0f5d2ab71e0e8ca5e6ad7b35d24fea1ff2e7815a07a415bdb5a979c11b598cb81006ededd34f6f9dc","nonce":"6839d9a86d5fd8bcefa5a11f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"7cadabd4824b6657780dd8e8ae1815be0b8180ca2bd51efcd82f58798fb0aefdca05ff75fe97ba11b084f03973","nonce":"6839d9a86d5fd8bcefa5a11e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"7230b6577362468e263ebcd3e594fac6f9e3c0e2defc206bdb107913ad26ac1d7e6e5bae4c2de33d2618f97b5d","nonce":"6839d9a86d5fd8bcefa5a119","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"811f9b020812dc160f3a6716f11750177f93d29e498d053ceee9fde759ad4840d9d4b76996ac8f0dcf4a042527","nonce":"6839d9a86d5fd8bcefa5a118","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"4edad464ab5168f603bbadef0aee9e5866c14f9d0cc0647500a55e912dc6c72c6ad1acbfcdbaa7db8c5d7f11b1","nonce":"6839d9a86d5fd8bcefa5a11b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"1855bea5b052a8f387f0e3e8bb9fbab5334bbaa33c902e8d91efe4bd50d262a75892099e63656029b92a0863e2","nonce":"6839d9a86d5fd8bcefa5a11a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"792177ca6cb5aaf65c9e399cb77dbca1fabca54843d4329b914b66f04a6b6327e631336d548dda9524e7d23714","nonce":"6839d9a86d5fd8bcefa5a115","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"99706e9560db62fcbb1eaafdaf26641f1069bceb47e15fe1129045fe71956e74c7926277f1fcba67bd8dc16d48","nonce":"6839d9a86d5fd8bcefa5a114","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"397f456c0ad2dcd9e7a7136115b20e4000d5fb588c38246eb38ab3391349bd82d7f7fa1e4c99faf53c14cb9632","nonce":"6839d9a86d5fd8bcefa5a117","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"10e7564b9b827cd2c21225498de3d301efabac75837af27deb4d41c3226d8a6da0befa598cb9f17144664d36cc","nonce":"6839d9a86d5fd8bcefa5a116","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"5a835644ffe33162ec41dcfd3946c600293f79e81906b8e92eb4d5f8e3f24e77e16322e42152e6f72847423759","nonce":"6839d9a86d5fd8bcefa5a111","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"01cbe29c634ba4da15f0baf264d5f3edef7f98fb0b66f7398f39de9fd61611dcd06f3bde321ac5375a719e7bf0","nonce":"6839d9a86d5fd8bcefa5a110","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"99faae6622034d312c7e7b5a965128eb5b66f7f89a4fba8028600f74908b1efb12ec516d166550b6c6b3b5baf6","nonce":"6839d9a86d5fd8bcefa5a113","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"cd55b5b8a90d0bac6f67ae1d1a1f1ea2b48b3b6a4f385b77f77f7376d7dafd5a0507a8ea019d94b8244095715c","nonce":"6839d9a86d5fd8bcefa5a112","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"d497b6a8fe16d485e007a51c6a9c4c84c5a01e36665a76668a3c09a3f5a6e3ef0833cdea050ee75ed8fd9710e4","nonce":"6839d9a86d5fd8bcefa5a16d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"733dd06c7a49ab567f8f7b2109b17dcd6d40b1a9b545199bbd4ad87034bd18d3ca21ec5960f16ed67fd4e41839","nonce":"6839d9a86d5fd8bcefa5a16c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"f8675ad4c5bed7214c4a9b9c8ec9c48da476476897e0b1f30a3cd94bb1d007cd67f66a9b0e585eca16c6cb1251","nonce":"6839d9a86d5fd8bcefa5a16f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"6ecb8e68bdf69d931dbd69d7c750d32cb5e845a51fe6db2a918459f47e9e7c1a19559f13c0a4a67c6fb7f93957","nonce":"6839d9a86d5fd8bcefa5a16e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"85ca007c48ad232ff3380c7b56836456f480a2a64ae4cbbc7e0d36b1ccfc2a824be6ca3219836f52a85af37c60","nonce":"6839d9a86d5fd8bcefa5a169","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"d576ee4420781cab805fd3bbab32f893e7b85da7868369b82e9bcbbe7b7a552ecbaa1af016d9d41383ac1d82ab","nonce":"6839d9a86d5fd8bcefa5a168","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"c5f065beb2fa75920fc30a7b622835c43ceb1cc951a7f6a36f810d8237a283764c5ae36facdc7e6ae419d2014d","nonce":"6839d9a86d5fd8bcefa5a16b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"2e726ab6294d78734e7ba93027afd9af66085eb07eaf6dff709bc674a3741152fe7c4fcf30710f3ee791446df0","nonce":"6839d9a86d5fd8bcefa5a16a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"e22a80bbd6797c9af811e019e30666402e55f2ab961f69b1bf0360e3a76b1b42627e308b1dc6a36ef057412538","nonce":"6839d9a86d5fd8bcefa5a165","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"45a78ace737e0318d6f7e6a875181a991caa774fad5d34ea1d53ebd49272ff709c3037757c577a0c64bb1c39e5","nonce":"6839d9a86d5fd8bcefa5a164","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"b0022a5f8f2749fa520dfc71e4822045b94129cdffd133851d0824363ca245687b6b06dc7f1507573d06faa8ed","nonce":"6839d9a86d5fd8bcefa5a167","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"fb3b9c349b8c63e96381458d009d8411732843394d612565a80a9c5f3151b1988aaef617853482b419e755c496","nonce":"6839d9a86d5fd8bcefa5a166","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"a4e5b99149f3d3229b2576d6767200b1a58c177a21274069fc96fd5eb16f25f9b97dda4cb9cdd76055be71fab7","nonce":"6839d9a86d5fd8bcefa5a161","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"530ef431f7d28d8c1a48a495fb93bd25c4792995f8a13ba1adccf95c01bc318bb89fe6bd7ef319a42d8d776840","nonce":"6839d9a86d5fd8bcefa5a160","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"d29c464c3559ce1168d112dd0826a884860f3b6d9c8b0b06c9bd70db8cdcaf2aa4a5a3891489299c131e981fe5","nonce":"6839d9a86d5fd8bcefa5a163","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"f527ec95ac7f5c277dd8e4e126ff5e1b2d6eeb69bcc6414b0a30a832a47101511498bb207ab7c361c5a18b1fa2","nonce":"6839d9a86d5fd8bcefa5a162","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"6deefb6d9906c08299e7a2cd0a944b81eebe3b6ebf7dc43d507d73656379eeec406501e1cc56f97652707b6b59","nonce":"6839d9a86d5fd8bcefa5a17d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"02adbd8c2b1eac5bc7e8f4819ec66171d40dca1fa0e47418440d5b4bb9804ff09ec053f1e3f39d80ae6a92c88a","nonce":"6839d9a86d5fd8bcefa5a17c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"ff62b7884aeaf8ec2af72388471da32b301a4cf5e79614f854ebfede9020e7ddf7b5ab27032361dcee07da3d96","nonce":"6839d9a86d5fd8bcefa5a17f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"9f45bcf71fe9c71544138c0a074777e794227d2202ff4825c1fe9ede4af51f4d851a8b1cab10cebea1e627c319","nonce":"6839d9a86d5fd8bcefa5a17e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"37bd10605c79560ddb6a08970ed4cb0591269c29b46f0b91732145e2c3085a2ae86f90fe02af2a97a5ce8e2948","nonce":"6839d9a86d5fd8bcefa5a179","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"56eb4546c38d427673d9e1738bd2679660f3fc55c48fd9e4733e4f43d07bd92f167f4a139007bb5d217f862d8f","nonce":"6839d9a86d5fd8bcefa5a178","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"d48b7dfe47281cb3ed4c686edf857151db107434b02ff7e62749a35b2a4b778376b27100a286cb26234fbffdd0","nonce":"6839d9a86d5fd8bcefa5a17b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"68750f45e6eaca8582ae345dbcb7d4f43b6476938278c2469be7788d15694d725434c8d22a3f4889d213e811cb","nonce":"6839d9a86d5fd8bcefa5a17a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"7ce17def1ccba9333c799990f5dbc3d228121aeadd71122b4367829382b0c2864f762253c4006df2318be26ea0","nonce":"6839d9a86d5fd8bcefa5a175","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"d90b324f435b5bb3f6a70ab8d63911fdfac9f29e1da5a2d2e6813fd7cf75658bc9d8f5247609c57ded5cc7fed5","nonce":"6839d9a86d5fd8bcefa5a174","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"1849489446850daab4b06bbf08fec34327c5bf1064256dd1fb3c571019c4e827151b8afde47f8eb7ddd41148d2","nonce":"6839d9a86d5fd8bcefa5a177","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"969b234a086bdf96a864374fce12581fc6c30f116513cfd6412bbf300e1b291eaf0e2d8731c8ae0fc1d124a914","nonce":"6839d9a86d5fd8bcefa5a176","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"89bd19a3342240032663b59a393c5a6d112135c7fe73e4686cda1f4d2922951bc95474fffd5057894e7d890ccd","nonce":"6839d9a86d5fd8bcefa5a171","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"30e742147e5ad43e388b7cae14db27780affe15a0581c3a2a8a6b9f63ae878be28ec9436edcce01044c515998d","nonce":"6839d9a86d5fd8bcefa5a170","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"06b50d41495a3e3790305fd86ba2b40566e5d6e97e1b336cbc32a7c8dcf1ca3ff722a5409119fc48c7fd1d21e6","nonce":"6839d9a86d5fd8bcefa5a173","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"35783f77bdaefb75774e76b841382e0debbfb56618abfcf9909cc88d4e9dfbb896d0363f3a38cca87d7a0ff800","nonce":"6839d9a86d5fd8bcefa5a172","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"a714bc1f7a9d41d256d3d53f5ea594fba3d62ac66f4cad37f89fb6836208124916bbb11f9f4e9110384cea38a4","nonce":"6839d9a86d5fd8bcefa5a14d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"9a7fb79672402b60185be97119a47f505d518c1acba347a49e50397d47b1d6b180fd30ea5ff3d6393298f6ae07","nonce":"6839d9a86d5fd8bcefa5a14c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"fb15354cd215711d254ee3538a907162a7bf71b82eb1c506d30c81e4915fa2f2b423b38191e23141d2447d091c","nonce":"6839d9a86d5fd8bcefa5a14f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"57056340627d3c54219042d34e67016774696faf0ed65ec939f301ef89de17fdb2d74ab4fc878fbef96bb93d7f","nonce":"6839d9a86d5fd8bcefa5a14e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"3d7c9e7b83d577b9ac17b171d1aae1817dd8f93947c9abf92e456af95a0fbdadeed836862b0e6b1daf5a8bb372","nonce":"6839d9a86d5fd8bcefa5a149","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"6a8b98cfde7f2c7a4e0cd97692a7bc577662d8e3c168560de5527e31e1196262d531abf85f920b2604de4e62fd","nonce":"6839d9a86d5fd8bcefa5a148","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"a58a802715a6e664b549bf8c1ce0c3a06e9c6adfd33cb71156cf79b265e21fc486758a4daf94ccfd6e7334fb1e","nonce":"6839d9a86d5fd8bcefa5a14b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"9033f88acd0837fd557b48a91c698d29730e39a2791dd5ad6ea036f82576a6bb78c9132cf7fb4d31b75e6b14f1","nonce":"6839d9a86d5fd8bcefa5a14a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"a64e2c04de86802e7a2ae273d1169d58c3a894e08d066de28559d4a696e3aacfd192936d9221dce09f2e2ebb13","nonce":"6839d9a86d5fd8bcefa5a145","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"f65e826c62898e3a623e646df7e31efac891d0570d0bf73c006220ee7395528347d75bef38e8ff39b6afa2989c","nonce":"6839d9a86d5fd8bcefa5a144","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"c9e2b88323356dae944b39a3f56bd5c6106f55d0b06d6cd858efb75755e18e793d23a601885180dcb704f50709","nonce":"6839d9a86d5fd8bcefa5a147","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"da923ee82da5c878226792b53c2e4480f41a90979f02f0dfe782e99e2158e931800ca0d69a89a68032e81859be","nonce":"6839d9a86d5fd8bcefa5a146","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"577748a808d0a820dd84a1af9900b029c0d4124aca4796176ada28d5c1297299b8035f429f7b5524208525a272","nonce":"6839d9a86d5fd8bcefa5a141","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"855bf117913321b8926d5ca9181c03745d59df37f5b00e112bfd5226239ff0c72795bb1d92b5b15c697e247a45","nonce":"6839d9a86d5fd8bcefa5a140","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"a790903ede8fd45eb325e1b2b892ac0488143a30896280c0a2132301b8fdc1046290922cd0034192915a2682bf","nonce":"6839d9a86d5fd8bcefa5a143","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"a07952a35ff428f9e30252f59fdf8be69f70fd779b7b33d19ba2d4496b3b92f012c812863d373f433809f37edd","nonce":"6839d9a86d5fd8bcefa5a142","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"ebe4280512f2b94b7295acc30d9db1a5c8ca7dc606e4c4e5a4cfa7ce030b844d2e20ccd4602e2f48c835ed24d0","nonce":"6839d9a86d5fd8bcefa5a15d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"9c13edf8bee21a3342ee07b2d62d785206a5ce9b3a1783b9163fe48a9b3df65f58d4dd991c4cd81c916e10eab5","nonce":"6839d9a86d5fd8bcefa5a15c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"3f910272ca493ff8840830d96cf86320044b9cd3d0aa89c7102f9106c217702c34837b910c93ec17146a7ef418","nonce":"6839d9a86d5fd8bcefa5a15f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"a4b24384bd67bba96b89961f99b67085e06a0270aa142fbda00040f41e04565fcc34b64e77d21fd3f7f0f84471","nonce":"6839d9a86d5fd8bcefa5a15e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"05a305dcf84fcd008367bc1b20f6b006114069a54e6dc3012fa668ed1495be6e4c8968a555e89c8c6a09baae12","nonce":"6839d9a86d5fd8bcefa5a159","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"6a99928f39ff64b8452f71f2017d84fc5504f97a5f191a65a269cc32237c860c34e56dfbb0214f378fbcee1e3e","nonce":"6839d9a86d5fd8bcefa5a158","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"72b367e0525b3223833796103451a6428115c5f674bdb3416a3f9ad0b06843b852230b6b86346ccda8b136243c","nonce":"6839d9a86d5fd8bcefa5a15b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"0d299b32444df933992e42b61d5f15f1a0e4eacfce10b0ddb443b0b58975bd8cdeae00919580cb0702f62e32dd","nonce":"6839d9a86d5fd8bcefa5a15a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"72262d3bdba0838b09467d32d81108115dbc66bb291b8ce65ee25dda1e0d7625642fc96dfbd7b6fe6cd71d15be","nonce":"6839d9a86d5fd8bcefa5a155","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"9d3e71e2235432ad87b5ad65a8ce0ebc788a162a2821f0383d7892b5a88cbbe12d0cb2d5c0dbd46d9862da8ee8","nonce":"6839d9a86d5fd8bcefa5a154","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"d90e4d6a10d9d0f4b8fa9ffbf88b04c0ca1c63fbf4f957c9c38f0496009233480d6fba755ac44870930abcbc0e","nonce":"6839d9a86d5fd8bcefa5a157","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"1561785f61b8cb042dfb64036cae7cc95700e0adad6dc2419b5c7fbd3f74a833977807381c41adb9c226cf3d84","nonce":"6839d9a86d5fd8bcefa5a156","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"f5b4eb0830837e7e0c7f4676ba4d9ae6099d450e7f78a8d1f155e02919c9c404ccef7e137ea1ee0cc7612a04e5","nonce":"6839d9a86d5fd8bcefa5a151","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"b98bf03569f2dc1c4d44cd792f3355d89285e451370d9606dafcb76369d3e6156980872a9d15e418db4eba54b3","nonce":"6839d9a86d5fd8bcefa5a150","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"7c9d9907ae828fd7217b5bff3e09e022439cc444570a128d15441b6a2ede2b5476b91f66b54f7db0aebaaab912","nonce":"6839d9a86d5fd8bcefa5a153","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"6bca7d01856e0dfe9894fe628b9207b9d7e9a9e01e53eb5b6ab8d8bbd8c235226c7c796a121917b90763ab6319","nonce":"6839d9a86d5fd8bcefa5a152","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"cb36ddb362dffa35bba568f33d193f93386a23fbfda0ca84980c10f2bf2400b7a1bf9533bc32c0539c58342d29","nonce":"6839d9a86d5fd8bcefa5a0ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"8a4e49b960a7f20110f3a60f6d3797edec527db1e5ab97ef418642e0b1b47e54"},{"exporter_context":"00","L":32,"exported_value":"afdbc7fae5f454ed5c17c53eeecf8cda213d92cdc48dcb197d5853467e325f7d"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"f2cef5c0adfb4398281eacd00943ca7693789d7769a2098c3026e39ff4912d96"}]},{"mode":0,"kem_id":16,"kdf_id":1,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"03f75a34fe711cbd5a348cd52aca1387c8a69726328b83fa703c4f3e91ce9e7a","ikmE":"8468257215a9b747463886cc35fb1995bf2041325d6984b48e4fb0d872f43fb2","skRm":"01f59b0596c63d30c1956617095a4084dd8a62c754a7395069a56ab8aa9118fc","skEm":"bb0df6228f0055d4f4647cb76f4aee46923aecff163829074eb2210190271352","pkRm":"0421dc6b4cc0d2a73090cf944c9f1b8d0a700a153dcaf34721ec8fbb8baeea19e65fd71d34acdcfe1bceff9bde0f1f5f73a2edb3599f533e703a2f42865a3ea819","pkEm":"0469f24d3b44c6741cce6660b1c72e05d6d9c615b64dca6947c3eeca104be0cda1d4b3e8b1978e1de88aba437155df4fa9008ee3ad02a72f1ab6534cf7fcfadb51","enc":"0469f24d3b44c6741cce6660b1c72e05d6d9c615b64dca6947c3eeca104be0cda1d4b3e8b1978e1de88aba437155df4fa9008ee3ad02a72f1ab6534cf7fcfadb51","shared_secret":"3cda4df6c8490d7ae37eccef737e1dc3aea0e4162f985d58b90e4c3d0a69103c","key_schedule_context":"008fc3aeb832490a4b5ab3e42023287db29a1f4bc7c222c0df228727b70a4021127f1ff3fd1aa97af7e5d473e1cb01ba74831133d9659b6c26b03a038a49a84074","secret":"a739c51cdb0b699811e62929d722721a2972bc4ab3f84c778de0505e1a71d8ee","key":"94a73ec014266333b4663335220cf3ebfe7fe279c5abb52c40b6fcf19a20043d","base_nonce":"d2dacb23cee6e1b7441da406","exporter_secret":"b51679d6e7c6f6cf5850406bb10c554c49692e5f41b5cece113a33b01c7f89d2","encryptions":[{"aad":"436f756e742d30","ciphertext":"59b14653f7a80bd228248c71df9caf21319aa29cc90ef8e51761ef91a1275f46653b1b056482b17e1cbe1cb1de","nonce":"d2dacb23cee6e1b7441da406","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"1c4b78d35035138a224a462ed10dc99302a77e63e46cf99c87e3f32be5e0a67caf698dde91b6176fa410cbba23","nonce":"d2dacb23cee6e1b7441da407","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"d0371760a7091e6b261616494fa815d89a003615560bc57a6016ccd2e2a101de6e5065f3d10f19cbbdc5ee5848","nonce":"d2dacb23cee6e1b7441da404","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"1460e7fc8efd74c5e3d63978c5264ddf4ddff67c34507f87c7d81e6b587c5339d72fb15fa4e62060204cfef050","nonce":"d2dacb23cee6e1b7441da405","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"db0262ba4bad6bcaa7238921f5512b5a9cc24de24633e68b85666baf0f9eeaa4ce34a1a430f6022c3d1967dadf","nonce":"d2dacb23cee6e1b7441da402","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"51a082759f7bb9a80040400d6e28eb1771b835e474db6b69a546aa042ec91da2dbf164fd1fd65acdf5aa06e8de","nonce":"d2dacb23cee6e1b7441da403","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"d5c513e2e5bfb67415241fd8b23026b547730dc624acee3f697a7881a4f14e7cb1b2d376502de16a24f6cc270e","nonce":"d2dacb23cee6e1b7441da400","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"12454c1a65e61c611365152d4bfef6a6842f3a219866abbad8282919346695f7fa6507dced5f174f7b38ad1e07","nonce":"d2dacb23cee6e1b7441da401","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"f19ff33a553617954d34ce0021a14a191afd804352c9ebaf1e1de109abcace08d4bb30166ae878f38a395dbd07","nonce":"d2dacb23cee6e1b7441da40e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"29cd2bbc89639ccdf3f05d0fad1381aa5a6bf2cf61f2c68d0087c2fbdec030f17afda7242f1592bfb57d0ca84a","nonce":"d2dacb23cee6e1b7441da40f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"ac2a6f13d0f1a365433e33ad9fbd3ef833df2bc1f00e9784e46fc025bf511fa703c9bba06291e5addea69d9aa9","nonce":"d2dacb23cee6e1b7441da40c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"328fe4526dfcef3cb5e8bc073696f96d7775ad181e5b6c7f7371aa8dcee5d32c3371d8620218b367c446e0a379","nonce":"d2dacb23cee6e1b7441da40d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"21327b635374ff9db30b2be841bce328904516bee10d87d255934f72cc4163550e2d3f3d8f549d979952ebcd70","nonce":"d2dacb23cee6e1b7441da40a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"aab9dd5c116cd36c211ab61d3553ee87da4bc3cc298fc5b4ca58aed4698ac59725d1afab82c9f6a803172f1717","nonce":"d2dacb23cee6e1b7441da40b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"0765ce2e9e8547c5b699ffba145b30f28d56aa015778126834a221540f96822d73d815fec9177fc18af4d43db0","nonce":"d2dacb23cee6e1b7441da408","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"f3d5ce5280f38966cc41494613c9002fcc6c9b15af99700dffb4952cd9efdc912431ef807ea56285bd5196cd33","nonce":"d2dacb23cee6e1b7441da409","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"3cd3b4a241c6aa65397c664c9657a8edcbca5579ee72b5b46bc74ac17d8290d842eceb2f91911972e447376c7b","nonce":"d2dacb23cee6e1b7441da416","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"e12d859c845dabec355e6bad227de8e5ff4775c2c0d8261acc6a82852d8c898844883246b5e7100f6196a5bbbb","nonce":"d2dacb23cee6e1b7441da417","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"5d7ecd932fe6700fde5dba3ec583d7ea63f4faaae49d348027ef51a0861755d71c8469dfdb3a5b633b5f836913","nonce":"d2dacb23cee6e1b7441da414","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"720fe01fa3c391ddbe86f92e6736c77529983f288c255146cee35606ed51923bf279e353949426bd158b2b8ebc","nonce":"d2dacb23cee6e1b7441da415","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"b92e94c3dc14719353c085997c03d5a0dfdef5a3d8381839093d2b0d409ae925c238593c79172af644dcb47f28","nonce":"d2dacb23cee6e1b7441da412","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"b37b93536f5d8ad092c355265887a9b32ec446ae8363d86275c0fd41c883115f3ba414f72635fecbf43c04eba9","nonce":"d2dacb23cee6e1b7441da413","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"50137dd1d335b2fdee3e1ddd633be657b4c8ebf2680be94fc08fdf94d52cad7440d2de151c8e72c014172e7232","nonce":"d2dacb23cee6e1b7441da410","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"8df0a9a8b0a58d6a2b6d94eaf7dce259bbfd3abdd23835073c35b4f16ccb0fb2263389b6f8e662b0f4856551a6","nonce":"d2dacb23cee6e1b7441da411","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"360165a7f64bed7f33d5f1fe449225e741fb4957a7295eebae2869a9189a505f468be53cb3a1f93b8ea344e505","nonce":"d2dacb23cee6e1b7441da41e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"2a6f4489ebd7b71f12ad54c19df1ca97020283ffd044814749c4544c0b68e3f317c0847176c35c50182f862338","nonce":"d2dacb23cee6e1b7441da41f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"4a0e95bb063b98187cedc1af62f80dcc5db0577e061d2bd27520f931741726d59d7b221a42e15183d943af5872","nonce":"d2dacb23cee6e1b7441da41c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"7fa5a72b71c2d1fff4e996de2954cc7a1e6e3594d6f4bf9fc524a80a68c4ecbd58bf32d9b6456365611257f7e5","nonce":"d2dacb23cee6e1b7441da41d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"c1c4739dbd32b793698cfab67899afbe48e3db167a7d46d7cd11914077bf319f57a116084526732e5415983dc6","nonce":"d2dacb23cee6e1b7441da41a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"6796eb84caa1493b787c528e0857202f0beabf6a7fcb79973bf04343f19c5fd8bdec3a813488c5200163cb1a85","nonce":"d2dacb23cee6e1b7441da41b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"b504ee78ed5c6687d765bc6a3bebef7e2096fad96fbc99b674f7a68da26f176ef40fe34cb97fb2578b12c50512","nonce":"d2dacb23cee6e1b7441da418","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"aa94cc8dba8b0d38e701c72e261aebb2a7f46c62f5ab1940cf8509d66a13fdd50a1b90633f50323f1c195a343f","nonce":"d2dacb23cee6e1b7441da419","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"a817e3f74db625ef3aac41556e695d45939c69d5282341171471c56108c011910a165e726194aaaf2a2e63d823","nonce":"d2dacb23cee6e1b7441da426","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"593a27e45e4d3dd210d621942520771c35f02402a8ec43121c32e01028a77070795545693b13435dba1e61fc2a","nonce":"d2dacb23cee6e1b7441da427","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"6801024788a18f6b71a4efd249994237db9e585a9effc8d3f58d1c4b4fe5c402161be709fffb447930113222ae","nonce":"d2dacb23cee6e1b7441da424","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"b51300479a3fc9503743d680417e4fef11fb052a85e47f6e8b22bf0cffe5ec7e158e847e1cac776337e1f4e733","nonce":"d2dacb23cee6e1b7441da425","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"5cd411486af86ba853ed9eb8f245898a31bc0de184880d42df0fb5284998787ba23cc6e32a90cb98573b895dd9","nonce":"d2dacb23cee6e1b7441da422","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"14d54ec459034e5befabdfcce773fea277f02749b052b8b17a25ce269fa46b777ef0c476080e032f5fc7a4a53b","nonce":"d2dacb23cee6e1b7441da423","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"7a6697269d8db287c5285854a658c1d192fb75ab3dcb74e65b5033a55d1e7bf1381172c21e108d6c34a1e27df2","nonce":"d2dacb23cee6e1b7441da420","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"4371b5cdd5464fabe3f5fd41ca32095eaf8aa2660d4aef197138df6fae0607576d60a45c5939ccdc9824b9a1a2","nonce":"d2dacb23cee6e1b7441da421","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"394ab916e9ebf5ac1ecbbefcdb1a61495c69322306da20fa594c53934dae3a7273a5f4d56aace07f6e50c9f042","nonce":"d2dacb23cee6e1b7441da42e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"4a055bbdb8f4fc0eb982ee1f195893b42b2a628c7af2066fa666cc55bc4cca10d07ace22ff95f1f10ce77b8219","nonce":"d2dacb23cee6e1b7441da42f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"72d477094256d72c812ecdfd51d2f02d63586e3ce5ff02df07a9eeba2035388a3900439c2588ff0bf7802a4877","nonce":"d2dacb23cee6e1b7441da42c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"ac98b4061bbfe9b6b7e44a27d58afd575dc37ba8f46d487571bb05ce09341ecaded4bca6eb4ac4f7b35d8f0441","nonce":"d2dacb23cee6e1b7441da42d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"4b26a57f282bf6b7c8f9f7a83533f0f1cf62773b044cc3cae785692d3a018d4ca8f28fd87d00798d9682c501ee","nonce":"d2dacb23cee6e1b7441da42a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"d30bca0ff559b50ea5fefb38cac8ec7209a923bc3a13952678772038487caed6ce7e0ee3e1ac63a702b18b5d76","nonce":"d2dacb23cee6e1b7441da42b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"2a10e49317596b923539c639693bfc873118260812a42fd4c9b29f9e683b8838cada82ea57d1deebe726ed44a7","nonce":"d2dacb23cee6e1b7441da428","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"e3d860c22332558373e865f4b2f05f72405f2a27265e8c76e677b3ae0836b12185ae7e51b3db822853cad20b17","nonce":"d2dacb23cee6e1b7441da429","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"0c475c3325f516089da5299a3482780d700c8c66c7cc45aca00078bf0bb773988f5112ff03d6eeea17a2a8c43f","nonce":"d2dacb23cee6e1b7441da436","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"443f1888883057f86bb7d8044e48407933e6865065326b871d4e66a9809cca46c2cbc97d67c2c19a7ea67a7aa1","nonce":"d2dacb23cee6e1b7441da437","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"af124080e0f057247a02d534248b24753556ef7cb0736818035c29bafd3b4282ae4f65a13e463cb02b357a9609","nonce":"d2dacb23cee6e1b7441da434","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"e54ff25b9b7dc92c41d37d698d072ad2bc105e39bcf943df31a8acd504d2e297b14cd4d12d117715bea64c1e5d","nonce":"d2dacb23cee6e1b7441da435","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"734f6e62b971a1cb3c13a3ca8409d7dccb6ac4297a4bba2fd7e28422e31a70ab0bbc1f26d1342f37bf7a8c2669","nonce":"d2dacb23cee6e1b7441da432","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"c4a591fec2445a0f0b342ec0ef04a73b8e5492bb99be1b8b9d2616e49cf351db2d304f90c336e59a78bd3fc23c","nonce":"d2dacb23cee6e1b7441da433","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"6ffd8cf23a093885cbf526152364d789cec5fcea8577463e1ca55bf81ba963ad539b7b73043e4ba7a8c385d47b","nonce":"d2dacb23cee6e1b7441da430","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"88b47f8980e7cfe90ea6d240eb85bb37eca7f19fb38f786683db6d0ea963c27838f30b5bbb3b6c01b5189cae26","nonce":"d2dacb23cee6e1b7441da431","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"90d364fea88ac1a2c0910e80e3fcd6c0ca5d81cdefe071fe8329ac140524170b7a62130200ceb427615ee094f2","nonce":"d2dacb23cee6e1b7441da43e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"e6be1130d754038f0248ad3b09b60fa8969c6e377dce1335ec18f8ab7868f441df74e0d835f43404caaaf1e627","nonce":"d2dacb23cee6e1b7441da43f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"657838d0c2d4f50119a8946fa7e07a3bc7587856a80db7d3db3294136bde081a0d01b134e7a26cfe249856fb39","nonce":"d2dacb23cee6e1b7441da43c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"423b60d3e60e8c8f2dd2585fee70deea6ce9203ed6b5e27a47f0c737cd8aa5e3e026e46ee1beee5925c22cc528","nonce":"d2dacb23cee6e1b7441da43d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"1bfcdec32647e18d426194ae56dd090f18deb9b57e538951e44e8e5918365449120085d9bfed211ea14ec26fcd","nonce":"d2dacb23cee6e1b7441da43a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"da87b1f4c913e9741a858f7f59630d106d20fb97b93d0a9d3b80975122ccd6793ed31b9bba245a862e2bd69e65","nonce":"d2dacb23cee6e1b7441da43b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"57e70057fcb01176a68633d80a259b98ba88cf04c0e21d7e729d328f01e6c8edc86e8493ffab577c5b12987cf0","nonce":"d2dacb23cee6e1b7441da438","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"59a3739dc39f649962c723101c8f5a064f070776bffb759e20bfe246b0ec34f0976d7ea5409c9f2238e7a984b2","nonce":"d2dacb23cee6e1b7441da439","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"efb131a16187b72d94547cd338f428d8333d6ca9acfac318c8c7cba2e4a218c3de14b5cc66703a3d625643fddd","nonce":"d2dacb23cee6e1b7441da446","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"610e658fdb446f1914c33cff2044f534cb3a42ec3ccdadf74f038034a032043d69f6ec8271deebd64c3a2f67ec","nonce":"d2dacb23cee6e1b7441da447","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"c98a76a60b9d24c29ddce720e40861f918a6b29de47a03aae5515654ae05790603e2e6e468ef3a80bd94c62e45","nonce":"d2dacb23cee6e1b7441da444","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"863ecf4aae1970756fd25ad19712d219dfa31f1dac5b8ab63d5efa995e75d8ccc91c118aa8320fdb4cdaeed039","nonce":"d2dacb23cee6e1b7441da445","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"c4ce3f4e059cb7dcd0d86d18603a680cb85ec39c8d6582c2b21b841308fa67775f20885a21df4a65eb2d636b8b","nonce":"d2dacb23cee6e1b7441da442","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"8efcbdd0d2c5d9de0638a4dcbdb016837e46075670c7f7d979c2ad04bcd3ba30eb001daba7f7a3888206896caa","nonce":"d2dacb23cee6e1b7441da443","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"5b15ff2d03460d7af4b2fc0c80a6445a847a30e050994cb35462d83ac73935505f93845ff52d9358ed9c4d9a51","nonce":"d2dacb23cee6e1b7441da440","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"607ba98eb622594b5003cae575e42f3c7e83d0c021a832754ea262bec08e60bce990f51eba9f296258115ab571","nonce":"d2dacb23cee6e1b7441da441","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"22eb9f73d0245e0dc469f0da30b50e8a750fe9a385c58be65ea7cc37b4c11eeeba45217d0680be85d8f917669a","nonce":"d2dacb23cee6e1b7441da44e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"176bb16828ae793b515070e2f300954a3151e25d6b3205b8075709fff6634c6b13e17abaa9a061e7685e622923","nonce":"d2dacb23cee6e1b7441da44f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"229617fb36aa2930a31ef9f509a7e0bfbec98226660bb4c8b6b006c076dd549668a7fa0b227a691f5518c41cfa","nonce":"d2dacb23cee6e1b7441da44c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"6d931a4b058bd2c4becddc1dd117d60cacdaa0821fd8260dde0b71d7fedc484af0a229b75e907184ac68d25a32","nonce":"d2dacb23cee6e1b7441da44d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"0131b0a47de8ef0937f3923e8368775b7a3e28bc16f14b836c060f55873b6ba63d4a4b202b6fb187c060d67425","nonce":"d2dacb23cee6e1b7441da44a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"78f3e20f3d01de5016bc78cedb7ebcf91a2186bfa17b41a39a95fe77348ccd5dd1420e3369f2e97e646d306107","nonce":"d2dacb23cee6e1b7441da44b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"c410645197f928050bcfa69428d3a921fe498abcedcb19cd94eed367ecffaa7e3198f08911fb9a6af3438f581d","nonce":"d2dacb23cee6e1b7441da448","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"d101ae6aa4166d9486dcc10ce8d515a69610f5de4ca16af5b6a1a66438fe441e709600bb6d598119ca1765dc8d","nonce":"d2dacb23cee6e1b7441da449","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"f9f8850378483815e8d8e5cc9700f41dfcdab20dda9c64cbc3c126c15f099e910a7b33e5e81d6be948d1c9d92c","nonce":"d2dacb23cee6e1b7441da456","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"0cc431bc15a8eed68a0c4972fba2112e2ab4bcfd7cd75473b9349c78dd269ad4409c4f15c8a2d9a5dd863d6b85","nonce":"d2dacb23cee6e1b7441da457","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"f3d1fa2edfc9412743999c320a4d34a6602aeec037a16b90df044661fa44c64421a88b7306a16fc0d8c6b4fe19","nonce":"d2dacb23cee6e1b7441da454","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"da3ad99165090bbf00f5f873bd196641b7cea4c87f2bd1230474885be2a30d45f6d40cb7a7163d2ab07c724d04","nonce":"d2dacb23cee6e1b7441da455","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"5101a95146e34d5fb0a0d963c1156ee7b0e0561f8ae257d7bb4ac6adcb6f865cf24c0a632913f08d657b863f41","nonce":"d2dacb23cee6e1b7441da452","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"5132cfc6759ef712ff6c6a3ec6607433d31c69acb23f9ea1f15a8b9289d8ac2a50827f1b34c13f59c77d054765","nonce":"d2dacb23cee6e1b7441da453","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"35e4cfa62606c04e57e41a3f376be859edf80bc2feefda9741250d14af3e2d44944be3838c8eec4ab55a3509d8","nonce":"d2dacb23cee6e1b7441da450","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"045b3191a816dff67ebe627bff2702d060c71cc7d1f9824ecdeac8d4c48579791464d3b761c3fbbad9ca5e374e","nonce":"d2dacb23cee6e1b7441da451","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"a8c691385038c0d8a8192f76aef5bbcd77d68ca0456eaa26fa607587790b36b21b7ed24f2d24227b34bf96de69","nonce":"d2dacb23cee6e1b7441da45e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"ff27ec82a2cf2a00dcacaa6dce7492f02d4a941b39221c067d97b20d6c24d5c0b1cb64250ead9f4b2b85d64e02","nonce":"d2dacb23cee6e1b7441da45f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"c20ebd2ffb2700bd80fe5dafd8e79b7571e908a10bbc4a825cb13364879221ba702a550ff9a4861907d27bb087","nonce":"d2dacb23cee6e1b7441da45c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"fbb2be331ea971cfcc1db915b6fc060904c1ac7139988e5800cb6dead1132b58655717738507c18bc52e78c115","nonce":"d2dacb23cee6e1b7441da45d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"786641a51eb7370fa5b1291e5e536ed99a8fa1d5c03c20b29d1ec0a03ac24a500553057f858cb35d9931c99f7d","nonce":"d2dacb23cee6e1b7441da45a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"8902a373f887984061a2a74fbc56607ffd9a143fa074ddf324a5005facfbeea9ad436f1c295cacb773d507abbb","nonce":"d2dacb23cee6e1b7441da45b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"02eb8aecadc3518795eb7cdeaf76a0a91702593500f2ee8a0cace7e3ef2a4c23af323fa4ff4d3df487bc136509","nonce":"d2dacb23cee6e1b7441da458","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"e6182049955f77bd0263bb4ea0c019a88b7856964e8e57ec500251646a7fd7f39348ecfd99f58cc6878f861ab3","nonce":"d2dacb23cee6e1b7441da459","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"a64932897e8fe563bfce452f36051eeb2aba499d47c0ecd859b9a401d9594550f9377d09abdee1ab4da2152062","nonce":"d2dacb23cee6e1b7441da466","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"426e277688e2d531b1ed616d0d1ea89f743bdef4417368e11c0f85ca43db798c2ede31b09bf9e51b02ad58d420","nonce":"d2dacb23cee6e1b7441da467","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"bb1585c5790a034c8d2d9ba2213136ca4bd83c36eb4da9cf0ce3e52aa9888d3748952820aa9a2a4fb4e2d8ad31","nonce":"d2dacb23cee6e1b7441da464","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"73cdbdd047ec48d69c00cb91aab77ef022abf3b2dec8191608d3c1e2c7094cd1d0c4c7703c8e5ed4d041f84d80","nonce":"d2dacb23cee6e1b7441da465","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"5c4fae45ef944aae2d66c49c0b6fdd7bb43cde6fef217b8bc4ec7da074684e5edabf6ea5c4eb2a37e2e3a4025a","nonce":"d2dacb23cee6e1b7441da462","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"c01bfc05443c5c6abd112e0ca8c49471166fffc6b108d51a5aa4793eacc5b1e040b12b929f0bcb7360b4c29c91","nonce":"d2dacb23cee6e1b7441da463","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"1d3254f3a7c2e801efc50110ef96f8e4e71872603787806a5106a8c6d8960aeb6ff979ab33e295ffcd27049505","nonce":"d2dacb23cee6e1b7441da460","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"f782d5d5a4dbb5041d9661bec611a21fac8c6ec6e14f40c20969cbfbeb3dbd6967d355c72ccf26c76a7d2c2406","nonce":"d2dacb23cee6e1b7441da461","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"39d8cd21ca9ed98be22521d7ecfac5342b32849480da6316405a328ed24601f154942af175fc5a78a3554a5d6f","nonce":"d2dacb23cee6e1b7441da46e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"6f11ef9542f5c9d2686023b53408db742c0f60d65261cde0c076575f6c56a6f84ff910fff3e80ba4794083b3d0","nonce":"d2dacb23cee6e1b7441da46f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"f4ab4305331b16092bab7886145f843057361d21f8be20a7acf0c131f2f084184ba34b1afbbd456af594ddf38a","nonce":"d2dacb23cee6e1b7441da46c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"645b450473932fd3c62a1c20943e6922f77c1b303509e65c9c796766998d75359aa94584d734f591bce2386090","nonce":"d2dacb23cee6e1b7441da46d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"39406af9dba04519273e93b856d86a4224df4cdd263bc105c20cfccbe02ce6fed7d9b756e332418f7e05ab0c94","nonce":"d2dacb23cee6e1b7441da46a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"cf7e1da62b8fa775a65a607e91ffc0c6662f96c21e469383ff642d6e049a85dd660a832a7fed4d3928c8e4af1b","nonce":"d2dacb23cee6e1b7441da46b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"75c36cc6c6d9482955570f26b0bc8e083c1c7e2136e167311d42ab5675a1be6f1089b71d429493b2811fe6b889","nonce":"d2dacb23cee6e1b7441da468","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"fd5bb2b9a398d189435f2c2c77f21813c7f16e48877d16c052e6bf79a6b15c0865813bfb7ae08d252a0dec739a","nonce":"d2dacb23cee6e1b7441da469","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"983b15f75702612f622b0d4da1c6d5f2e69fbedb5d599394b8b8ee3c0d833aa86a742abcd10c9c0fb80c1b4ad5","nonce":"d2dacb23cee6e1b7441da476","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"4e437e95ce1d2f425205b5561ebfaae1bf1409c07e209cbc16f93ffd1a95921fb98c5589f3da1985647dc54608","nonce":"d2dacb23cee6e1b7441da477","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"e7ecd86ea9cfb145e83e40983c8c7191167cdc182f9b240bdf88469fc90872477cccbcb068813a3f1839644a92","nonce":"d2dacb23cee6e1b7441da474","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"40caf346833c4f385e540308aa025f09d3d52041b55ff6497900e33aa0b4997f9a3bb361da41a68c42d7fc5802","nonce":"d2dacb23cee6e1b7441da475","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"c537713a7aec65cef3678627978872b8e99ed7e1f4ce9ff7b6cfca78d55e0f2d539dae1a5343ec53618ef76d6b","nonce":"d2dacb23cee6e1b7441da472","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"2cb2f201d424fbf7fdb3efb8443264031e7c3b1d11a4c8eae686961f7cc3dffafd60bca2ad72422344db15f9cf","nonce":"d2dacb23cee6e1b7441da473","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"49d72eba3fc557d6e2185f3af4d4a58f067a9bcd8b9fd9b91ae6c142d7691100757cc3e6a1e9b46851872398ef","nonce":"d2dacb23cee6e1b7441da470","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"ff42c0a11c7d4081c0697b060694bb8fdc712563b043284911107749ccabfd5c8aba8448c0c2a6481bfa42ccf3","nonce":"d2dacb23cee6e1b7441da471","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"4453aa6ef2035c3ea9384d105e36a897a0e106231d6cbefb5c21ff7b4b2778fd90dcb53cf8877c435fc0470022","nonce":"d2dacb23cee6e1b7441da47e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"c75c0bc0e96fc4e799ab4b09a212a50304eda4f64fe97750e28ce75a09f5a71b74bdedf510e23a145dad5c6012","nonce":"d2dacb23cee6e1b7441da47f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"4f83695ca868ba5db6686c2459edeaa9af493b709858fefe716fbfa5270ed6e66f3c5d1483968907c13e36db3f","nonce":"d2dacb23cee6e1b7441da47c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"e74ebdafccb32c0934742cf69d15575e5fca3ce786279d2362d047fcc92737686a6a12aad61bb18a473c19c362","nonce":"d2dacb23cee6e1b7441da47d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"e2ecb8e86d96a93d7c5e1038d6ee1e1d57869f84aa1e7515605634a3611847db023d0ea029b1e6d853b3027b07","nonce":"d2dacb23cee6e1b7441da47a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"4f24776b7c39e3234415e35eeb75a03e93a2f588cd07b8ceb047507bc9245e2d203b18d3ef9a56701a21eeaacf","nonce":"d2dacb23cee6e1b7441da47b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"89488dce9e208f338a4f955915513ac42a9d0459bbf0cf65e9d1ecd7610eb5e03def4e673b5f9f29ce54205b26","nonce":"d2dacb23cee6e1b7441da478","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"e687fe5fea982d2b054f027d8ed092023e6430626869edfc4ab9e87fdb196c0564526e964fb535c5fd54d7b5d0","nonce":"d2dacb23cee6e1b7441da479","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"3ad317be56d62d97b55a992b1331cc96b0d640799db424a5737cb4e083d2b7685b090c08219379129a60e608cc","nonce":"d2dacb23cee6e1b7441da486","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"e6bd83085c1a17f5fd6045ec7fcd80e3f97bfe04d3d85c0b8f10a4a00eb55401bb0f77d0381ad040a6e3d5719c","nonce":"d2dacb23cee6e1b7441da487","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"5afe45f21a8fd8b81584da57a5ec6e043ae6fcd574add7141e931d335367d2588196f0d0e40138a582ecf571c9","nonce":"d2dacb23cee6e1b7441da484","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"e3ae559e5133e444097e98234ef826a504477ed45ae790991dfe9226365307cd2f482f243231e904618018de40","nonce":"d2dacb23cee6e1b7441da485","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"34bf642cb23ed75a635c982f89b043b70bde99a195391b36ad4f2a91c7996590b8c2b26cde7cb2e300092218dd","nonce":"d2dacb23cee6e1b7441da482","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"7977bb1cb6bf379479dcb918af92d4c4bb12a0fa8b119fe9f7cc424726bd745ff664c7517a18379de54c108c82","nonce":"d2dacb23cee6e1b7441da483","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"27d31e820e83929971fdff345a6787b9c1ab8e9fab1ccbfb67a4ce2671eee27a2645df5d970776b36d67f9ce69","nonce":"d2dacb23cee6e1b7441da480","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"b6a6cfe0ef1c762b7d5b58a586fe6d5a31d5a29fcd7c23b9d5a97ab664027bda059eea20590709dc875c693c6c","nonce":"d2dacb23cee6e1b7441da481","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"7d6580066e02bd04464e93865a4a834d1c3b100a43a21107f873993712e9d525ec7c9b83fba6cf082682839bc6","nonce":"d2dacb23cee6e1b7441da48e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"f2c994e5582d258bda8ca54019218e62a0eaf9090719c47be336e53d57ef2c4634f714bdb999b6eb11f1fd2448","nonce":"d2dacb23cee6e1b7441da48f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"25b56d8c646a946f1a3a403b561aaa90a21ef3ef17aed6dc59b441e139d839cb7a779d5142ecfec850386c5fe3","nonce":"d2dacb23cee6e1b7441da48c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"fd4cf24e4e55bdc79e98592775f7d71f0606352632fb95f9cd8d6298f2323db124b1bf35e97a4056e5122b08af","nonce":"d2dacb23cee6e1b7441da48d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"63f640c1dba4757b79264f9a0d8c72929ee300501ebb6fc935514ac67f038abe0aeef09a40149bb5166df34574","nonce":"d2dacb23cee6e1b7441da48a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"e66ef33cd303fe8fcf11e0a525cd06319846d32dc5c28307eb1bc0cb28a78589b7509c93f84aed9ab357792c9c","nonce":"d2dacb23cee6e1b7441da48b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"c3bdd2cc0377a30b47cf1f9bb03b1daca6bda4d3913024ad1ab90a8d3d2bb96916ef8f10ed8c8f6dbfbca35e7a","nonce":"d2dacb23cee6e1b7441da488","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"314750a88fed6048d58b479c83d0b77a4358d2211089dd59cdcea7139ca0ba672e40f7c1aab204a00f0524c35b","nonce":"d2dacb23cee6e1b7441da489","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"259fd16db45c7eaa28a281f7a5bd699b2498407402388fccfbae190390d543499aaa77f7aca7c28f38db0ec1d8","nonce":"d2dacb23cee6e1b7441da496","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"02a4932a1bce0a972b0e865292aabb3e2acf0c2ebae3cdb56c8c263e2a90e70abe60fb89ffb2438183034f54c5","nonce":"d2dacb23cee6e1b7441da497","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"57bd8e7d3dddf3522f906c230df7fedc13ecee7592154bb716171a1029f591b7b61eb23836b50c518a2b69f575","nonce":"d2dacb23cee6e1b7441da494","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"bdaa1b039fd0c950d5767bdcc0140bcdc70566897a37dde6b3fdbc92744144e8f35ca6d91fe20378cea432f734","nonce":"d2dacb23cee6e1b7441da495","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"92988b05b963d3811953cfb9a0ff3a67ec52c289ae683555d8e969301fc44cf821b5f115091ccc514c93d0ddeb","nonce":"d2dacb23cee6e1b7441da492","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"338ff7468f8cee32410d50ef101843b8609c013914f6a521222bcfc1806e5fd63b8963e7f8f51a86d62b5a01b1","nonce":"d2dacb23cee6e1b7441da493","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"c63f960a949bc5ad9751d860802b9b752f0d885f3b85d0d23199823229df88c84e6e467984cacc7609355fd2ed","nonce":"d2dacb23cee6e1b7441da490","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"d3cc68c58a7f04bd9f792b20b65ddb57f94af82f3d17d78e4cbc1c82acfb3e67379e05941df1a5f2cf02d4674a","nonce":"d2dacb23cee6e1b7441da491","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"63e99a06078a7c8440a10471a5631b4eed53e0c01b3f61aacbeb0388c2c762068aba69047020202796c03f32e9","nonce":"d2dacb23cee6e1b7441da49e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"410a68933338e8300c54ade4914f8019ab6c1e9acee362293790da8994f8f453b31c444b71701dc1a854dc2640","nonce":"d2dacb23cee6e1b7441da49f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"0b91147dc199cd326cd66044e5f769114b05efd4e7b9126da2e4bf79167bac1707e9146e8f3cf0d15ac0b3aea6","nonce":"d2dacb23cee6e1b7441da49c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"58abc745d1311230978b9c39fe361b1b656eb4a7c83b614e94396ac81dbcabad29fca7a54d9131dc5bfd131c3a","nonce":"d2dacb23cee6e1b7441da49d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"7cf9652880c43bc9c8498221142c0e72c12ed04da8cf290ec71385ac7faa0429f0ecd30b5c36c7dc4723af13a1","nonce":"d2dacb23cee6e1b7441da49a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"c00cc033a2678a8ce047d50e1452602d0cf5db24136fa80585e7c3ecb6bdcd3e27b46a452e8d64cc169eca7345","nonce":"d2dacb23cee6e1b7441da49b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"246009a02ee2774bf6b7b15239b79f4f4f974f3274c11e849cbde1915abd39c3796ffe5bfe45066f7f633787d7","nonce":"d2dacb23cee6e1b7441da498","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"8d0a3b12b1fb33aa10c85ee7f4ca3dca643c39826604534fe72f8a6cc6b26e7d15a60f93ed1e416dff45957b74","nonce":"d2dacb23cee6e1b7441da499","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"a99f87eab35e1cf722976c318a43d03f1949e4a23a0da638e68d592739e1628035e136dba886d07f8223393c8d","nonce":"d2dacb23cee6e1b7441da4a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"da3236d97d3ab67524b4854700c67be377bd870556b8048cb979b28f41b3a13cad60247ee926a0189946c7b888","nonce":"d2dacb23cee6e1b7441da4a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"7adcaf67403d0b0114faecd30a34db53dfb9290a3afdefe15a6368f4191ef39751dd17aec94e4bcf580c5f92bc","nonce":"d2dacb23cee6e1b7441da4a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"e2e00d64e33c66f6748da44670b63f7c1684c1ef0e20d783b1a0bf0c9ec043512d97c82b94745e9ef078f7e2c4","nonce":"d2dacb23cee6e1b7441da4a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"519a313a1015d1e2fd02b1667b03ba56dd61a33f4066c58ad9a9797794ffeccf2a16b77a4a11398ede52b9ed91","nonce":"d2dacb23cee6e1b7441da4a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"08d4156c90af9af0334231ed8410b922c2de0019158bc9d1a7563114f8e4562d48fa4d65f98187a877f6983b9b","nonce":"d2dacb23cee6e1b7441da4a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"a9dd0f3541af5249ea267f74ae9f08a18e18ee9da257c5117b4bb2f524d56b93da26524a24df563bd0d4b73219","nonce":"d2dacb23cee6e1b7441da4a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"b304179b8cee8f449b3da6b22e2c75dc27b0a33a08600316656b443d8196ab2ed41ab882b1bb8db215434bfb49","nonce":"d2dacb23cee6e1b7441da4a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"809d6b4f63e76892402f2c74661b0d581bd4018d7640a9da11f26c782a96e319e9e19af54211443c3434d2486b","nonce":"d2dacb23cee6e1b7441da4ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"1bf8e115ad9573a23a345db32bf14f4958146f0071ef3613b7e4351738a98ee29b7a14fefd79fb6d6555be0e39","nonce":"d2dacb23cee6e1b7441da4af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"9539031704528a326b346ecbfc882efca4982ddef964c4789f9f00edaaad8afe18933535850778fc2ecddaab08","nonce":"d2dacb23cee6e1b7441da4ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"258123b7e6a84baed61953a0ec54e0cc7f556538559abb9b2c3889b3ce063e04ba6c1db44263d93d0c281212d6","nonce":"d2dacb23cee6e1b7441da4ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"bfed70e5df2ec6541aaaae2fc1de93e0b5967a3ad20341c90bf2c6cb80040948713d84e16c58c6def4825d38af","nonce":"d2dacb23cee6e1b7441da4aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"da5db1f241cb065138b46cfae6435108c2821c51ef5392a647c71ba9f463fdf3035d71ca26926ac2eba2500553","nonce":"d2dacb23cee6e1b7441da4ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"c6c255a4b10aecb846399dc7a26ecc39c0ef2578ab073e528cedd1ea060c1012377e006827c40e18c0625b595a","nonce":"d2dacb23cee6e1b7441da4a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"f76fac7d88d1232169f6e6dded1a88c4c7b731e6d9fd022dba7af4e93cc5b2cd39132b5e8b3a083f77790fd839","nonce":"d2dacb23cee6e1b7441da4a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"7103c59032a953e4aad8222577c3aa1d9c58a19545a63713a6548be1be2aae9762f2c1d5ee1c4612799348ab8d","nonce":"d2dacb23cee6e1b7441da4b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"b0aa9015d36d0ce3ad63d8330bc532680fa122781cf03c183dc78edbc8fc20cd8c12226f3d5b092677371c121a","nonce":"d2dacb23cee6e1b7441da4b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"33ee490324a4ae12760c88752224d14680d1753f1fe11fe9f0f26b420095820fbaf8b8b080aa061cd214679273","nonce":"d2dacb23cee6e1b7441da4b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"31cee6c0f8c9f98642809ff62880f65a85fb95659ac4bf2d590fc5e64e535d570b41c71232872cde54149347ff","nonce":"d2dacb23cee6e1b7441da4b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"13fed7fc7e4504cd7d2f37add03fc9e9472518ac5e3f03ee41bd637f594e7031356bba82103f1b4ff1a2d26712","nonce":"d2dacb23cee6e1b7441da4b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"370561a4c6b9c2efbd4ca0e216d6929e585963be37e48df3011be3b6f013b74790bd877ec551806d58e7a5aea9","nonce":"d2dacb23cee6e1b7441da4b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"d867d2e1e0bb40960ec5bbd3c303eca662a8bfed74bf0ff77f9900ad3d8922fd1d8f1be07750e2a8f6d1db357f","nonce":"d2dacb23cee6e1b7441da4b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"1151224b177bb677da0019afa9c2554a46da0a7d90d3190e35c99a1bdc937df6b1e9125a57bddc25c6e371da57","nonce":"d2dacb23cee6e1b7441da4b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"c32ae4a5814729f5c115760c9bb6fb47d1e2575f699f77e2f521b48f50887ee3cde0341d6bea1fdc7047dffa0c","nonce":"d2dacb23cee6e1b7441da4be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"c940ae8d9ad09b0bd5c3df89bd6afac74be87dfe42d6fd80955f8c9a48ecb9ffad1a18006d342082626b79a1db","nonce":"d2dacb23cee6e1b7441da4bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"369b399fea0e507b8f400b021402fded172293ef83f6f6c3f313ab619a48d9673e9e01b3e756ae72d272630655","nonce":"d2dacb23cee6e1b7441da4bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"48b9373f3ae6e26b715ed9398e3a7461da642d90b0d4d4fbbb65ea75af5982172e1946b19c36b544ee4394f811","nonce":"d2dacb23cee6e1b7441da4bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"3e4bc29644768a81a91b71fcb4cd806cf001a7364207c64721b15e3197ce35bd8109ce3325a91034bccc4b2c95","nonce":"d2dacb23cee6e1b7441da4ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"524f3f38d3d05f4ff769a7828acd8878dc8a630dc903a7c2ef0be5bd229dd0ac368ae23fdc7d7849ec2df091fb","nonce":"d2dacb23cee6e1b7441da4bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"2541fd5a95610d8fa8305364bef7db1e0b06a7a9089fc0064081f60d8a699d2c3a821cee9ec2e4922e7a0f2f54","nonce":"d2dacb23cee6e1b7441da4b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"e52918787fc11102637de97ce3a273b5072325213d569450c19e92d2328cb4c4f24c208769a58819e07e68735b","nonce":"d2dacb23cee6e1b7441da4b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"7655b792093d3878de556bfeb5b4a4885b478064c475d2b5c5e9103942d768e6393f8aab47433c670eb8a39ad0","nonce":"d2dacb23cee6e1b7441da4c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"72952c06539e281c9da1c04823103ca31ea2cdb6d2c27ebbedbc6c23d65614dc303e461de4684483cea7c9509b","nonce":"d2dacb23cee6e1b7441da4c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"0b7e500426d3492ab4d8524fac4d1c8b0b1351a95a77a39d53db699244b3297d79fe7f587349b8b20ed8c2418b","nonce":"d2dacb23cee6e1b7441da4c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"6ef65fcb0355570a73537adb534edc45a6585cb45bf803b1141215f99d8f7120b676962fe2c95b152bb9af5e99","nonce":"d2dacb23cee6e1b7441da4c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"8271ddd43976f69ab0bdc0eae47949594f4b0c8fbb872115395af958c2047089ba7aba088a786f7b07be22f0c8","nonce":"d2dacb23cee6e1b7441da4c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"b0414a13e282766afe6f2ad34dea014c4fd987fe0710b52b847a5489b6f06f38534ee73635fc256d337b6963da","nonce":"d2dacb23cee6e1b7441da4c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"e3ae68ed81eaf30cdfe02d5f3ba2073fbed2beba8c3be1ecd384a8c3056145e1589455e2b7f7df89f55a0a0ba1","nonce":"d2dacb23cee6e1b7441da4c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"8ceb02736ccef5f207c45a999a14bada499c64ef1354d206708f2541664fd54c9e2fe33130460ffe0894260bea","nonce":"d2dacb23cee6e1b7441da4c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"1a3b6ec8df77e7ba870951429bd7e89596344ac60df825bc84f57b71a5b869fd5638afb7474198965eac37e4b4","nonce":"d2dacb23cee6e1b7441da4ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"67e49c0693545e0df5476d429e66860fffe8b9ab3c162d841f063b0943fef4823dd02bf2a5e672aae8bbd8dbd9","nonce":"d2dacb23cee6e1b7441da4cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"e55f575fe849f4b8f44f60d0077209f7e448a9d5ff86195f82abb5db7e7284da1445225b481dba25c688509a69","nonce":"d2dacb23cee6e1b7441da4cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"513650c60f7d4526aadb4cd0c69a2bf271a3f59ec4b7a7f7640bffd49cd85ff35c2264fb9ef083c7aed27f5911","nonce":"d2dacb23cee6e1b7441da4cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"e8958419ce597a465933146edd5ed958d6d27b71d6377c595361394b8cd0bcd30b4e02d4f09ab8890999a90df9","nonce":"d2dacb23cee6e1b7441da4ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"acbba400968c4a0e6cf99f3b3d3f683f8b3c3c4cce8fa7882f957545e9bf0b5d9cf3f84829ef28278667b989bd","nonce":"d2dacb23cee6e1b7441da4cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"bda25376cb9e95e64221950370288f66637f07237583516f7ba86938c02c7b68f6c1cafda364fa5b2025f03eee","nonce":"d2dacb23cee6e1b7441da4c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"cec2e6bb877bdc9864e333a4cb634631bfe6786259a3dde8ad20861ed673bfd5b227101d70751ad00c0489b925","nonce":"d2dacb23cee6e1b7441da4c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"2cc853919113e13596d0b9424677fe08d92850e0697bdb51634df1edcd65c6ef33faa02a31790d256317df86a5","nonce":"d2dacb23cee6e1b7441da4d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"2adc28423b24cf2dd5d87905e2362cb4022f2b89e38a78a68df5f35234ff9988873c59cb703fcb00ddb9a804e8","nonce":"d2dacb23cee6e1b7441da4d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"ee6f4e1fba6f841f75d88bd0f037b614319a4fca376eb794985735783038aee2116cc90c55d40f32f83ce3b8da","nonce":"d2dacb23cee6e1b7441da4d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"ec68ffaf63650cc44051bcb0258ab4df7dc7c5e56758a1f9d3f57c607d04ee3a8df76794348bba8aa9abe0d2c1","nonce":"d2dacb23cee6e1b7441da4d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"82a78a15fb18e763301822c0bfc0bd07da2fc4b21e8662579c3980ef7d871cb22026258caad48866ec193ddd71","nonce":"d2dacb23cee6e1b7441da4d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"03eec1796f91a8e422b423d8cfff9a76ef66eb03ddf8ddfadf90929a8b77fa2868a8a9ef456fad4ef193b05577","nonce":"d2dacb23cee6e1b7441da4d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"91b1835f10d8dbff98a505d8ccf77b1da1705ff6009ac54f36b1a8c07261ef05c7edcd7e4849cbbb69191fac69","nonce":"d2dacb23cee6e1b7441da4d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"69bdfaa6819c717c52e3e8a2b762c4d81fab76c913599ebcfe37bfae3ca866d60fda2bed9507bef21d9705ec14","nonce":"d2dacb23cee6e1b7441da4d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"24ff7bb5a1abfc4b5dd7cc191f26118b437f861a26a4dcdb41f96b71983272bc6397839453cc79feb92cbb67ef","nonce":"d2dacb23cee6e1b7441da4de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"f5a97873674b145d39df2c3e5eb569ab9e9a61c352a14b1a4f6eefccb5f310f49967e6b9941aa47f1e59e49bbc","nonce":"d2dacb23cee6e1b7441da4df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"f74622dd317a1a6af50f775ea2386954c6e9b701bf5f60e321cd6ba07aea49be7cbb89bb98aafe04adfbfa7ce5","nonce":"d2dacb23cee6e1b7441da4dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"c175e608ced9da6c8edb0acf4d85b4d491c7a48c3d9b93b5a557e1746a0d638bcd8e46f67ca846b76c7d6ed831","nonce":"d2dacb23cee6e1b7441da4dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"840ed48906c4934fad780b1ec774b275b7f211aed8c0a17d12c76f52f09fa1e4fa4e20cc7ca40a18b5b894898f","nonce":"d2dacb23cee6e1b7441da4da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"dee9eb98dc0b27100c35e04a32f7b735f7fa7a78cb538e1d884d42645a14f3db8d3882a1afce28461d2fc653f5","nonce":"d2dacb23cee6e1b7441da4db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"165a01aa7fa9ea932ae9dd9c8d7362e5e3d432ec99a62a8b9440d331896fe8a8390817e745751b8e046c71a031","nonce":"d2dacb23cee6e1b7441da4d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"7dbb5cc00e8a9af1d921dd161b54666f16b4922465340c036cbdcc1b8818105bf028b401ce1839a83bf5295d9a","nonce":"d2dacb23cee6e1b7441da4d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"680f6fe6c6154fa683871ad63067bdbab974e1f5a4916e3118d56b7e1984f02cba181ca06aa20867576a4c1fd2","nonce":"d2dacb23cee6e1b7441da4e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"63a6adce44d9728a3bae2bee33d6a16d7ae7efdc9a0f710f90f9b4a344a3951ef62a0e00dae89d408969a7fcb3","nonce":"d2dacb23cee6e1b7441da4e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"39ee0b681a242f44b49a30ae4a186cc77ad0616ae6b90bce4b7942b28ee8d13c08c16fed8ad28722d8e9a0335e","nonce":"d2dacb23cee6e1b7441da4e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"b4f7e59da069298c630e35ebd849ceb529d524932b29aed96bc54e528279ef2b534a505f6928b7927a24b78d5f","nonce":"d2dacb23cee6e1b7441da4e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"f3e5504468838aaf2639acee41a866191e193ecc4fc42e73803400939bdd4b274355cd719d015cd875ee6fd235","nonce":"d2dacb23cee6e1b7441da4e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"7769eac5fc86e531c0526762c45ac6eff21f1dc051c336a01fc40899a49a009dd38ac1a70563069a8a10b7b14f","nonce":"d2dacb23cee6e1b7441da4e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"c35f3cc0646166a1b0dc20f67edcf1f73026b2084c7b6c6e5a34f2f26df1a55635cef4fa0282d85893a1793e9c","nonce":"d2dacb23cee6e1b7441da4e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"01e62a2c5c3db5e07a7d3374e4c997fcb09d110948c4d8fadca784568d696b8b1cd87fedc6a188595cf15ccab5","nonce":"d2dacb23cee6e1b7441da4e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"78fef5edefac38b91c9d9de721ce7753bc5540bc4fb43b4f2eadf6a4bbe592118dd2a98e0f5a47095ac38a2bf7","nonce":"d2dacb23cee6e1b7441da4ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"900a763129278282fc05b763e6ee711ec95464c9d13cfd5561caeafb29af6b45d6ba345a55215185e543ec6c6e","nonce":"d2dacb23cee6e1b7441da4ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"2a326a1517039247786ce4279f481fc0652c43bd47103f1b3f283fa86d5c455d1edf38076501365f8f69b8966c","nonce":"d2dacb23cee6e1b7441da4ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"bc31e489db4f42d0858feb2a038e10abb50f4a475524ec599018a596e94cb61b47d608e38fbd4742a11c6b4b56","nonce":"d2dacb23cee6e1b7441da4ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"fd37d218c3d26b003bb2f9de9f79d95f7a49d2bfad2d79573a80bbdb6ef006524832edf1388353086dd6e71581","nonce":"d2dacb23cee6e1b7441da4ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"d6c90dfa8df988273479f23d17c5411c983f2b5ab1929cb81638ad70ae7f0caf3dd207bb469c1e9afe6359ece0","nonce":"d2dacb23cee6e1b7441da4eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"1f24d2b8eb854b98aa81523cf121af437798dfc33dfe80a23594fd50ce8632c314467e5895d36ef4d5932ac15e","nonce":"d2dacb23cee6e1b7441da4e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"490cbd14e2c091ed2b557ce421c6f6b4ee9222fe95a47e98089c5fbf2a6de3f293efd7c9e60062bcb76bddc4fc","nonce":"d2dacb23cee6e1b7441da4e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"d5b6c8dd898af8d179ae1d0121d7ca2ecbd38fc6c4ecc95a9329354d507178c5e0b65eda90cfbc91722624ca11","nonce":"d2dacb23cee6e1b7441da4f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"ce591f952c42885adbb6dab82482e7e2a5fe1094d04a30f2497805b63254bc92ffea8602ac4895039d86061b75","nonce":"d2dacb23cee6e1b7441da4f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"2ff166591b9cd7fcedd8750d2783c3ad5972bca4106163d54b0f845bc7155778932e1b9c1e4444b824cd80ddb4","nonce":"d2dacb23cee6e1b7441da4f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"ec142b900fd2ef2b1e4406afe09cfa85c885a65adc774338515237aacf3ba4a4392c9befc569fdb8b92f80e621","nonce":"d2dacb23cee6e1b7441da4f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"6c1131f95f43f2afc422739e7f918bcbdf920cc3c9333355e9de4bbbb90b26655d9543ec9723fc104abb4002ca","nonce":"d2dacb23cee6e1b7441da4f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"2b66d06f6f73f8c5813af11502ad97438c1b1175dcc7d07e22d1c2d9fd382a1c7ac9c15f221edf705b9350ca0a","nonce":"d2dacb23cee6e1b7441da4f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"6e6469eb7d4bf89405d1ec5fa143948fed4e10d8920b0435ecacb9524a1fedebb321bfda6728662b2a07734344","nonce":"d2dacb23cee6e1b7441da4f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"cd2b6ff39ee7a7c2b7c610ef3a6513a67aa0f1769b45b8fc6e5f3cd9a9f627e6b66ad4a377a310bf103a34b99a","nonce":"d2dacb23cee6e1b7441da4f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"af9a3fdc5a3e5fb094f333eaf1e5cafdeb5d88d8aba7e615a428d9249a5bd79500e0d670428cc4ddedbf840290","nonce":"d2dacb23cee6e1b7441da4fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"a115f56ced6fa51a1e38c323cc97b55a61c2cbab3464583c9f66e0d554aafc8e3ad6d9fde28111da3b138ddfde","nonce":"d2dacb23cee6e1b7441da4ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"ca1177004b3551f6b54a9967f8d885343c63293eb99f05b33b1dc08f8e1c599110fb0120a2dda740cdbbfad1dc","nonce":"d2dacb23cee6e1b7441da4fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"b831015e5ac7a4286a9368b5d63aeaaf6772b90569cbe3ca2679382a972144809a2d659cebcd084ad302fc3569","nonce":"d2dacb23cee6e1b7441da4fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"ca475310cae28945eb8ca30bd781ebc851ba30e9bf8c7142be0a961b523085ddbc8c9e3b6e5e28e7d81e1b1de8","nonce":"d2dacb23cee6e1b7441da4fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"843a49bc4e102a0849fe20964b33fc7738d4a977ff099d5a0f8099a9a40e44defa1090a0a35347dc7481a81040","nonce":"d2dacb23cee6e1b7441da4fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"69280ea8704672a93b135c1b81da8ec24dfe4d4a0199ab04219c5f67882e9cefc67f1e88cbc3707e5cf2c4d440","nonce":"d2dacb23cee6e1b7441da4f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"11bd3a46dadf19e5d373d4140fe0d177458e968fce03ad69af14b598ce141f74216b23a1e0a978f5bb9692e7ff","nonce":"d2dacb23cee6e1b7441da4f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"b622449394200fb4fe612ffc81e701be97f2eb65ea7b847d75c554dbe992aac5996f8cbee11b98947055d0eaf1","nonce":"d2dacb23cee6e1b7441da506","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"137e5fb8f28525b4c8cd75bbe92021fcca02668dc938f2b1c56df1bd336a93ef"},{"exporter_context":"00","L":32,"exported_value":"661735371c3210220bef5285b271a71c7c4e0c7745134914ccd32e95d601672d"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"ad4ca528e31ced64dab8e7709eb457c8b478f078df09eb300b8990ab2672a1ca"}]},{"mode":1,"kem_id":16,"kdf_id":1,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"93b8de9d9745402f42f992aca9295e34b85df768e4299f39e7395b38b1080cbe","ikmE":"fd7faa79dc6021385eff334707ce2013be43a28ffc3425184b4e128ea9554d2b","skRm":"68b2bff1d98b1f653e525f8d980deaea84fea1b9da281dd4b6978002e9e0a716","skEm":"bec6ac55f646c169f3051cff4d41288f14ae32bb80f4e301aeec662b5b14cbd0","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"04b600aa10c70f615a96bceeee8585759facfdde763927a9f333137ba156e96d1a509ce02b9acee87bd60b5a4c1016b2f328b37ba75de01ef3664ac7f0d98a0e65","pkEm":"04bb7981f5e1ca33ee78259ea8ef498ca19cdab07b53b42ec340191e0f5006fef0963c127334c642461ad64fa81a5e20b51d0d68f802acd85459a58cc0bb5e1c2b","enc":"04bb7981f5e1ca33ee78259ea8ef498ca19cdab07b53b42ec340191e0f5006fef0963c127334c642461ad64fa81a5e20b51d0d68f802acd85459a58cc0bb5e1c2b","shared_secret":"6b65cc90e64f5cd0d2056ae315a2639fbdf89ba77a3867e392efbc0e48dfc62d","key_schedule_context":"014347bda95dee60516b0482433e06221b26075bceb38f3931c30f869f189cdf8f7f1ff3fd1aa97af7e5d473e1cb01ba74831133d9659b6c26b03a038a49a84074","secret":"c35023e8c3407538a66b88559d178edb1e128a69115f826caee5a249512b7d5a","key":"0d35328257dd327017a0c24dea29c9bd0872805d9046ce72f06cea1d30c8bffa","base_nonce":"e77389abf637245b8ffcc0c8","exporter_secret":"be7cb9c6a92c6e91f28b861105a394228c1172d6616eb924d0747ffcca1ffacb","encryptions":[{"aad":"436f756e742d30","ciphertext":"f8fb106bab2a01c4f9ce16ea3e9e20d1c3a8b4f350086ba2dce7eacf14a5647288e1cb3e40f49912b729dd1627","nonce":"e77389abf637245b8ffcc0c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"6924909c007392842932ad05596e1b48dd5d738a93bd8c08c2a8b74fdc96bad7aa49c0233de2b1a2f43164fafc","nonce":"e77389abf637245b8ffcc0c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"4b540671ed3f07051ca2e11d8cdee6822a6e8263dc7317903fc36cd9d8e3721e57c75ab0ea10d7bf22f6d9dd1a","nonce":"e77389abf637245b8ffcc0ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"63e082342a77086f08d9d5984a22b15ef23c605ce2ff9262823fce6973b9503e31d64a449353019e827866263a","nonce":"e77389abf637245b8ffcc0cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"db3436921e809d44852678c80ada602d5d56e46bfb4c44fe2d46f427e774fff127797c9268f92d0d169281c765","nonce":"e77389abf637245b8ffcc0cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"2210f26d32211e539b1982739777451da4378593d113fe5458bc0b65e123ed3454243ab07e4f6e6977b35cebba","nonce":"e77389abf637245b8ffcc0cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"b2b9c8b07c51d2324c29b97bd817388bc48cd15da877b041eedc8622c46f0f030aa0aa804c4deed7039f21fd8b","nonce":"e77389abf637245b8ffcc0ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"edc13c081c0705e7054a37da0145bdadd8131ecf2d80468d746fbc6475f18e7872e23cdb3ed671ea4284a1ae1d","nonce":"e77389abf637245b8ffcc0cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"2c8920a28855a6196216dcfae98e2b8d33d74f3910de17882bfdba0c0d63791174c7cb85e73a15c574da8c355b","nonce":"e77389abf637245b8ffcc0c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"137f4cbf4fc0bef04a2fc077fd0a9f21a9d959ef0140d0f08bf04c43ee405fad87b07d47235be198739db21baa","nonce":"e77389abf637245b8ffcc0c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"102803e5ddfa97f6173253bed7c9925fac63788643dbcf70e39141252633685821ae457674752a229b2adc0aa1","nonce":"e77389abf637245b8ffcc0c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"7d6851ec35dc756859ff9dbf61dadcf0d9235a3f206823fe0375f32365139ed4116b5d154463d3dbe8e4721cc5","nonce":"e77389abf637245b8ffcc0c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"f3d3d010455d8a40bbb020fdb2967c9fa70df99bb72763332cafa04819933b112fc030911d3b16b9c3757833f4","nonce":"e77389abf637245b8ffcc0c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"d584ae13742b7e730c90562d97fd8efab6b47a4e291ffa40b478090f3fad4386043d1068cb4043ca150ae3e7f6","nonce":"e77389abf637245b8ffcc0c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"d6d0852b20f6ebb47d271942367f5a1d2d459e093a550959112ce15e64704ee3cd29337fe7a003f56cb11dec96","nonce":"e77389abf637245b8ffcc0c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"fdac812e1fe9f65482487d1996ba214fae15e36d7577e2ac1e6f23fec8fdd0373cebf158eab965925d1a9990f9","nonce":"e77389abf637245b8ffcc0c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"6963b6bf3888691dc5c3e297fd05d205e3242f68588bddd015fa865ed543a97db7f6970c37a4e596672f6fae06","nonce":"e77389abf637245b8ffcc0d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"b864bb02a51e704e21e708f94fbabe4cc17849b957c76ab3bc89850fe17465e58082323b1d3a9c9fe3a4ae3ddf","nonce":"e77389abf637245b8ffcc0d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"e5a58c45b917669ae4a793927e2fc096ed1c0b14c345e9df61b532436be0e49b6805a70ee7b65721adaa968c24","nonce":"e77389abf637245b8ffcc0da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"588185cf2993df7eed0fd86c0f279f1c3a9b8ebc0be2281e59cce2e6400925035a169e170f91a82f046c62054f","nonce":"e77389abf637245b8ffcc0db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"f7640d2640537616a6ea00ef7c9e3ccca803b63114b6a232ced226d43265dbc775606bdaf431a91c49ab67dfe7","nonce":"e77389abf637245b8ffcc0dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"d2d60a799ae89d1c169a2f77621e95df947ba7d390f537184709e755a19f10ea3c337a48721fc8f37cc5334a19","nonce":"e77389abf637245b8ffcc0dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"f1834c4c71027b664101168e9d917c9a0e72e9563d9b405ba4aeebc8d1eeebaa22c699d890d3242eaa28ca00e2","nonce":"e77389abf637245b8ffcc0de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"8ac725aae6b18fdfd953a9f26c632258823393f390acaa2d987199cca0fd8075c648fa4e3e588469dca68ebb9a","nonce":"e77389abf637245b8ffcc0df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"3d426f4819aa0fd11c7d58fb5398944a08857a55592ddd61b0d048449435049b06303c22d2753082cac09689f0","nonce":"e77389abf637245b8ffcc0d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"90f2c178cb67f91d99a6c79aa7df5084ffa0d21d605767f3a1942188b2e77cf7aa8a708586527f14a3754ce3c7","nonce":"e77389abf637245b8ffcc0d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"4fe28bc61b348a25dc7938ae14e33e5d4dfd004802fe52d5a7f9649d0ed555a23e4026627badd7cfee9ff32999","nonce":"e77389abf637245b8ffcc0d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"cb3277ae3108f3e1a52482b311f8d36e376a2fa371713d09526f0932367dacf98e95cc6c3633f7bc904c26c25b","nonce":"e77389abf637245b8ffcc0d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"2757e9cacb0e6604c9717828085a44ce2f7829953514515d050f4e15903e326ffc9b71fdce29ef7fcfd0061b2b","nonce":"e77389abf637245b8ffcc0d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"56723a4990a4f2c869afb41a65fb18b31ec03be21ea6b51d7c1c8037d6a53f812647fef1bc99128e75a3c19ffa","nonce":"e77389abf637245b8ffcc0d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"86a40c13b6aa00f31ee8362e0668604d7d07274fe7a5d0d7e7c25559256d3cfdf9553512570494be29ee8e60f1","nonce":"e77389abf637245b8ffcc0d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"c8c523e76873fa8bb470cb3e127b8af33db3e6079f2c32602354f6397d1bb70322eef32796cb02e7638a52670f","nonce":"e77389abf637245b8ffcc0d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"6d21eadc14f9aa0d611f7a1132ae1a1f7ee08bc2ec1b78fb873200c05de26743a09e964d1c46248e367df40071","nonce":"e77389abf637245b8ffcc0e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"ca79ceda62b38724d641f3d7e4bea51b2f6aa44566869e9716deec61c5f56d4505f7114ed87de224a4ceddfde7","nonce":"e77389abf637245b8ffcc0e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"6c7c3456e37e9e0506875fbbea57f64d94de98302cdd553b56ca29b36f8dbe4f2a7f64f5f15fa95663134efd33","nonce":"e77389abf637245b8ffcc0ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"c705b0332bcef2432ea04cc8069e961b081dd12b427c4627d2ea81bf0e356eeb1a297ca98c9c21cdbe79361c66","nonce":"e77389abf637245b8ffcc0eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"36ebaf5d56be6656cd6fb63bd4904cb53f69e7fc61fd2a0787b6a2eb062afa5c30c6058907aadb9cf4293966ce","nonce":"e77389abf637245b8ffcc0ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"e2cad74aec7aa42b4aecb8a4fe7aa7c8be74c0573efefadfba42d66d8d9aef4b2da2bb5fffcc9a9f7d57cba8ee","nonce":"e77389abf637245b8ffcc0ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"33a0a11dc06d40c05f3311ed05f9ff6ff331aee4717aa8ec8fe375d86f0055e94376f1814351c38564dd810df0","nonce":"e77389abf637245b8ffcc0ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"f413be040408271fa721ed0939e484a73b9fbb773e4f9d7ad22b23e7f90252e53ed5bb8fa5d968ed676605fa81","nonce":"e77389abf637245b8ffcc0ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"7c99fb8966f2ffdb63a9c329c0e61e64ef0aa9105767dab48b1526ca192818222e3d58326bedec49355ec37c98","nonce":"e77389abf637245b8ffcc0e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"87ee4c7a2cfa09b8f788cf2bb37267fb6adb3264776a0758b81a5de1b7122e7d5e02f111f0fcfb5775ab38f60a","nonce":"e77389abf637245b8ffcc0e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"38956d92bd43d90aad89873a0432849b5cc8c7aacc094f7c5ed98ca481bc4007ff5bb237716ed9d2f3deb27463","nonce":"e77389abf637245b8ffcc0e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"dbee267c2a6201d6eb753d61a79c7a804876fc0bcfc938781ced15daedbf31ef611f87846c42548062d6620739","nonce":"e77389abf637245b8ffcc0e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"8c3e8078fb8e852ec21f08ddc02fa31d60da39a9628c5bb208dbdb7fbffbf3a1ef358b8fee186d577db63cede3","nonce":"e77389abf637245b8ffcc0e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"05fbb698a5ed538c528b5368e69223ea69df5126c8f951ec99f5e1b329150e705c3da91fd43e050bd90aff27e4","nonce":"e77389abf637245b8ffcc0e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"7f8cfc99a8cf35544a380884ff9e911f40243700b638aad7a61d7e3139b322d70fe40ae2fbdd4ab85c15834cbc","nonce":"e77389abf637245b8ffcc0e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"d22c1a671126ae8ad3d7c36157e5021deb322def209fabca618d539122a6b596bd8b3f105ad383330bd3855f13","nonce":"e77389abf637245b8ffcc0e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"a92116e86b9476ade750e90d7814df64c9c42b7ebb65c7ca42d8bb94db1b31487f9d9b9678f540152a6233a7ac","nonce":"e77389abf637245b8ffcc0f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"356307b00471482d843a35e3e5ce5421b0c93bf53fdd242bd7ed558eec1d7eb55159a4f573526c21f926f2faad","nonce":"e77389abf637245b8ffcc0f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"9b84ff437eec69795f57cf481c5fd6175ab1ca2fe047590125528d0cb7fb517065c19909ead151134cab0c3daf","nonce":"e77389abf637245b8ffcc0fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"78444c26f3a4a1bf2f4eaebb432e4222b6266be3f3c621e5b246221005c600e595b299b9e44fe54c632700a896","nonce":"e77389abf637245b8ffcc0fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"1f94d4593e999df2b11770f2c33f3f840c05101794ee09bebe2ce75a1a7a32b96d920f7a7d1206f7cf75fd4b38","nonce":"e77389abf637245b8ffcc0fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"b7799d7e93929d41abbf2f19f89413d46e5c44588a96f8852408451d2117cff59abe31286f911848feaded264d","nonce":"e77389abf637245b8ffcc0fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"c15e77dd8bf53b98e66e57543fc71bb20c6cb0a5fba3f5f3fba45b44baa48b92859846c94c0432a5a53c655c00","nonce":"e77389abf637245b8ffcc0fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"0408a50d3f32a5282d980298b4d1bb69b1596086147ddb9831f68284d2e299c07a50383e8ac462f034bedbdb3e","nonce":"e77389abf637245b8ffcc0ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"2fcba105950eb7a10db907355d3871d33621c9eb1dfa179a4fc1a5246e202e919df455b3b54de99fb747800b33","nonce":"e77389abf637245b8ffcc0f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"55287d0bd4aa87b83144308aa0fe5f1b74282280f471c51f63110d97ef5a21fb6038c8b0f0b86d691c62dbde49","nonce":"e77389abf637245b8ffcc0f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"38bb87659dbaaa23d9506e8b496ad7b8c98ca5fe14eadfbae830ccede6334f41d8b17666ef35685d61a3fe8425","nonce":"e77389abf637245b8ffcc0f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"acbedc6195a439b636ca632e422f226db2eea184a00f1d2c31d726fee47b42095cd569418a8c71492392c39edc","nonce":"e77389abf637245b8ffcc0f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"151eb9a38dd79216b7982e0193e5932181e5a28a8ca4047913bdf0445959ede7621959c424af70593a6cf09447","nonce":"e77389abf637245b8ffcc0f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"6cc9f05ef114ba90f52a1782348738c489a302f4d29ce0499d5164aa9d5b5dd6e0d4373cfd0ba834e6c3d81d48","nonce":"e77389abf637245b8ffcc0f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"03875b3d45add1fb22bb39f5a32d83271e995341778421ceabaa36a580f71314be4b137a10af1309fe74b7c525","nonce":"e77389abf637245b8ffcc0f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"e6bcd12f99226bf6ae183b4a63891e2132c8d5d2560b37b331d3ad1d9f705d6af3907122ae6d6e4ca20c3c0c6b","nonce":"e77389abf637245b8ffcc0f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"92d8187f71e4555c4a1e875a6d1b590c92172c10b580afb7ae21ebed67d8a71debeef7a1882606c5003de86014","nonce":"e77389abf637245b8ffcc088","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"d62f3f8551228b6bd8f82e08d162f62a6082d5c77e17b8593d9b8f57fbdf9cf761350565b26ba6e32283e01970","nonce":"e77389abf637245b8ffcc089","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"b8dc88a73d56d5f59d5dfadc1ff079dd24c7355c7ac038342aaac55b5bf741ac3fe7a262071ed6c6ad27c5e7c5","nonce":"e77389abf637245b8ffcc08a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"7c82c16c6c5f2713893fa085c0203fd30ee04128a16c3c57b7e664e3a5bccfd5d0777e570ce4906d355deb6016","nonce":"e77389abf637245b8ffcc08b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"47274c3cdd432f4f44793bbd019f140419e7911806f47e131a9d72896f813c2fd71158fb8c592e31486f34df06","nonce":"e77389abf637245b8ffcc08c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"e9865cbfc603e1ceb9497ba5c762ca376c4ff9c63166cfcd91faa83cfb4887db4f5faad8ecdab86aa495c67195","nonce":"e77389abf637245b8ffcc08d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"d346301ca953d7a107c0ef87dee87b1a65067310e49e1b141437aa4baded7bb01e053e1aca5ece036666b67451","nonce":"e77389abf637245b8ffcc08e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"3ff424e897d87830d6adc1ae92e725caab2e34c3ba1c217ea89eda4720dc08f2d16e61d9fe42be469878374144","nonce":"e77389abf637245b8ffcc08f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"51feb366cf00860b359b524d6e99bad277434d564ad1c134b63e6004088f01ccbd34e3168634480192883f852f","nonce":"e77389abf637245b8ffcc080","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"77b6f7bc0f6eb44a52e78f90577284f0ffb22ecb618eeeb27bd90e3c3d26b5d809ab810b3dd32181c87a3c3afd","nonce":"e77389abf637245b8ffcc081","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"c8d78f0c3fdc1869194a21890838eae422b6396c5529d345c6ae2e5c29286e738a571b5c8a104416619cd8a294","nonce":"e77389abf637245b8ffcc082","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"14f2aa5fb4079f2829bcce681f554b6c4b78e72cc33a848d9acceb6b848fae845da3c2806e607fce2dde352d4a","nonce":"e77389abf637245b8ffcc083","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"8efe87e7a98bad2c81be6ec3fe4660c1b447f9b30773064ba556c5518f84e31c017cfebcb4eb7c891d356137c5","nonce":"e77389abf637245b8ffcc084","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"8d9464f23eb50368debc340b2f96f32d78f099fead7ed02deab126a2a79872f7bbbf900d0d2313cb768b45b387","nonce":"e77389abf637245b8ffcc085","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"be2db16f1496c747813787b7c86f98a89e4572c047fc2c194faff7b69f12ed7214cb14b57c77c658fd905c97a4","nonce":"e77389abf637245b8ffcc086","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"b1bc98a55ca56ca20d0d0acc8e8c5ae4fc5407ce5bf9c3ff5ffb404da64b78118629ca2baeae0658e4f2f28ca8","nonce":"e77389abf637245b8ffcc087","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"7c6a2dc983892062636449a8db9417d7b2267ecc6d25aa3f122cd1739398941a396e623d4822e8400be58bf62c","nonce":"e77389abf637245b8ffcc098","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"c921a530a35e9372963eab9d3fa58847cfcdc19b0442057af6f777edf28f5fcb394fc48b416173a2791ebff847","nonce":"e77389abf637245b8ffcc099","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"02add2403a5ff21fc6fb1e47f10fc26f2078fb124a9af0a1b1f6d0446823d3f34afde705e5a7578328f40256c0","nonce":"e77389abf637245b8ffcc09a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"0107e57a0878bce0c289055fd1e01980784e4df7903beabe4e00fa4a9991ecc99b4ff3cc06eb12d4c3d6db6ab8","nonce":"e77389abf637245b8ffcc09b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"e24f1213782c00553c4118b018deea521c12486c3b31d5dd40aeb9d21119afef52696ece0db5ddfe6932c0bccb","nonce":"e77389abf637245b8ffcc09c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"9ad0c1d92c4e760e2b51aaa8bddc4e1bc79f8653850d32e5ccb26c665e3cecbcab27a1f2dae1e3696ec724e338","nonce":"e77389abf637245b8ffcc09d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"0907d3eea310d4781f55e1f03c03ed4e8b3db138645c93a2192d7e28f646742620ebf8c55c2ec2a34deeee6cf2","nonce":"e77389abf637245b8ffcc09e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"85dfeefcc2c52a0f0b69aa0c200a16f6941a6459f9d3df42246d1c3dc5bb10d40abea468452da3ee868b9b601b","nonce":"e77389abf637245b8ffcc09f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"0446e56493722412c8e8896e00b13503dba589dc0ed0ba01bf5d16d012f300c8bb09786f7c2b6045550f68f905","nonce":"e77389abf637245b8ffcc090","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"b25814a8e909439fc94ece0b1209ed7328fc5e5296fb3761dd6227daed0d315b3d156573f42aa2e13ecc44c5eb","nonce":"e77389abf637245b8ffcc091","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"aef40d6f19ffd4afa4f87c7d9049d8830ec3c5fc0729130f7d8914ee0f58b8097e3dcf54f1e1bb1b2d7eb08aa6","nonce":"e77389abf637245b8ffcc092","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"9b0904f5a90181e44a05b07720c156c788ad4d3204c1cafd73c6d126155b83a728747ba010f36244554aa4113e","nonce":"e77389abf637245b8ffcc093","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"b7218a3f2a137bc1cbf201662bc9efd8ed47a099fc030b2175613b92728d553eb31b72ce53ba77689fc39a7d98","nonce":"e77389abf637245b8ffcc094","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"81f96fd79c72a00e58845866715fd261c92739a044b224eb87c5de94c12641d76a106f2324f0b303885a3fb5b9","nonce":"e77389abf637245b8ffcc095","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"cc6d81693fe162f9acc7e6a0e5ac50619c99729cc9d6791f406c5bf96b03c95bd54997d5d53d1c5a4918ed9778","nonce":"e77389abf637245b8ffcc096","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"7eb674090a07d87c3795e4668dd6c6598a4e1fced254a1559c28ed4acda31f676e0e63df69c912826e9c55ac2b","nonce":"e77389abf637245b8ffcc097","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"cd4225fa0667a594e91a1ab9d2eb58b0f822cea90da6b451cd7de7f963bf5520a5d653b6acbb2a897820d6f052","nonce":"e77389abf637245b8ffcc0a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"5274c9cd7099d90935a0f729414ff7682c5d49d4d5dd66344cd43c3ac1af899b1fe7469658f0632ff6aeb97196","nonce":"e77389abf637245b8ffcc0a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"e43808e348def9dbfd95ebaed0192ae4a4f8bb67025a343e20d2b87d6e0387965a2186707d74107ee6eb101775","nonce":"e77389abf637245b8ffcc0aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"e72d4a5edc6f5ff777ed5ddbe9596c5cd046bc45ae686751714fd91f096cc3a9ded2fe44896bd048090c3a3859","nonce":"e77389abf637245b8ffcc0ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"ee8245c525a30d03257ca4e356ef7830f10afb785c8da2b01dee02fdef9aed6caba3e65f05991658de6b3ed2fe","nonce":"e77389abf637245b8ffcc0ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"e26dfee44989b0bc247b2e8892aa633562070180b00cac3140f54130cbff7712945366ee87f2938553a3fed98e","nonce":"e77389abf637245b8ffcc0ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"b0e071d45d6f7c9eb36393f8cea5a996e51a7f184b7d0b32c039d4d07d8a312c4d1ff735024699c538bf2a46fe","nonce":"e77389abf637245b8ffcc0ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"632c5e76a5f50bbd85d25c59b58e97786bb19570ddf0fc647cb7c6034b3defeec694f71796674d9dcd81154b18","nonce":"e77389abf637245b8ffcc0af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"742d760360b4d77057830326e4071d45bd06d96ed1cd667e631d5446c7782650394f09a8d202f8b99361ab9cc9","nonce":"e77389abf637245b8ffcc0a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"af2290fe699b0d670b27aa3484b401f958d60225e32caa7d5767296f4a1e13b2865db7ee95232425bb538ced65","nonce":"e77389abf637245b8ffcc0a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"9609596e2faf17eeb1c100904e17ed5222a8466ff71997e0e2957460b1475a58daf3d09c0ce1289bd760196b3f","nonce":"e77389abf637245b8ffcc0a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"8d4b1f58d1c543ab3b4d5cb2d4fc9b7ffec24736a6de8a748e09badde6f087c8cb2e8c98078827194f56b12a69","nonce":"e77389abf637245b8ffcc0a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"cfed95f84d5238af5668e649dfd54ce88ad3c0c16ad98c7ba8d39b484909b3fb0fe240caa153efd8055ff8ab6a","nonce":"e77389abf637245b8ffcc0a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"94ab2f60087f0f4b5f70f88530ddf19e76fba96ff56f42ff2cb8a9740de0eca1e6aa79e58bfc427e5229527243","nonce":"e77389abf637245b8ffcc0a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"8ba26790a9562e0477f46a0075a2221f924f41c9df60b2e0217d6e8ad1902aa191c31c5080546c12b31b3ff813","nonce":"e77389abf637245b8ffcc0a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"3e5ca586b7e2aeda19b0253988d996c13766040d8d138984b3b5ecd17c98e7e5ed4ba1693f956e816e0eb6ac98","nonce":"e77389abf637245b8ffcc0a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"8c1e5d4f05be7ff3129af03f0ea043cd17aaca6c1f5d746716281b1399e9438ae1139bcb17cbca2244ef0d053a","nonce":"e77389abf637245b8ffcc0b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"7f7a10efcfd325a0657c2c7e2adfbeb09f40daa57c763bbf7607ed350a03e576bf536f02655286aa731ea8b604","nonce":"e77389abf637245b8ffcc0b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"ac71496d544c377dabfc9a39904af1e00cb399b174b0276d546d3002a21ef01c698fe2e5b1352a36c5cf3408af","nonce":"e77389abf637245b8ffcc0ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"f8add0ec2d3438e2eece9174740ed9ce6171f16f02b5f28ab8b4b1f2fc15fb05c7e631bd33b4aa117de3da11b1","nonce":"e77389abf637245b8ffcc0bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"a5b40cfd4b68b7fb84cf3836bfa0d368e06f02710ad672ae9a2b6f17c81db0a34abe15092858cc2d6e382107ca","nonce":"e77389abf637245b8ffcc0bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"d5786de8a2ccb1dfebea8559027ac04fd34575878aaf123ecbce49ab3ccc202681ca64f4bd40dc9226716a6840","nonce":"e77389abf637245b8ffcc0bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"4c222dfab6428c9908efbb47d9b6e5dddb75c78eef4b71340cb3efa65e2a6031b3f3eea57f5c26936e1651ebe4","nonce":"e77389abf637245b8ffcc0be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"436f03fb83bd9c02ae24172861b5df5398300e0a6e24ecd3913c8af6a5620913e099d35d211f7ad8e294edb0fe","nonce":"e77389abf637245b8ffcc0bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"727e6c75c92823dd6517f0f260ffd1a8f35a4ea732e64c5978a72bc8dfe4231bfc506be558ef3580c88d2948fa","nonce":"e77389abf637245b8ffcc0b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"1bc2aa33754d472f22ed5da2b50245c51e9242ea0fcfcb52ce0eca062a2e6c81d8375694f95da3af2476814b58","nonce":"e77389abf637245b8ffcc0b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"09572eb5661eebd1834b1c9ab3e3b8b4e357af15e7c76473681c8b6ec89cdbc43199a12890b0d80cfc101e7699","nonce":"e77389abf637245b8ffcc0b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"c056660e6b8a594f8488f2a37154ecc37e6a277fe2b849602af192fde2c71c9fac4b5bbc69bfe01513bb7a1139","nonce":"e77389abf637245b8ffcc0b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"3361ef125d7ff390db0ea60df9228e5218984da687e5e285b81a6b96da9fa69509be64225a3ec2da00ff2717e7","nonce":"e77389abf637245b8ffcc0b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"1ab31ce49fa75858b55c7e05a941fc4d01e2e9fdfe428c0b7ee2b0f52cfc6f353a11e912db727320c6f25d16b8","nonce":"e77389abf637245b8ffcc0b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"35f6e92f92238bfc3a7eb82771ca7cb50ca3e83cd9db515a6da3eb11cf92fc2db8ca425ed630940b6d968ab79c","nonce":"e77389abf637245b8ffcc0b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"0acde9a1cb6d855fcb7d014fb2dc3a2d3178460a2a7bc0c4d9f8ec92859682bcf19b3c2d9131dad405198461b4","nonce":"e77389abf637245b8ffcc0b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"362d5684852641f24d37545305c9626ff30d8b70d4864341f006c12b01629e46ab8752a38f8fc0b8d78fd205f2","nonce":"e77389abf637245b8ffcc048","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"7be30b695611247e9f3c79e98b83c9e224a02e9e7192695adf14825a416197fd4c116d903c83330be8903c6cc3","nonce":"e77389abf637245b8ffcc049","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"9105de25114b34d5885ffc97dffa6fa7d851b5e57aa93e257bd8342055d2a20436f831f0c21c47aede0f65010a","nonce":"e77389abf637245b8ffcc04a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"bd970ad09bc56cd459a916f6b91c5ad8f2991fc8082b1931606f270dc6462a2825df090865a9ec4d82648f80f0","nonce":"e77389abf637245b8ffcc04b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"2cf27e9d49cac4186aa679ca57393d8be6f06169227ea983bcfeb1599a2007d8cdb5df1d4a79c92ecfc776f70d","nonce":"e77389abf637245b8ffcc04c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"afbddb1b2890c6a1994f487452aa69009b3b4c2734bdffb096df3ae87f3f64693ad635de91bb6b0072c7ba7525","nonce":"e77389abf637245b8ffcc04d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"0781d70428a7136fe833990e2bc14b84d0c649ccb5c1f7d5d2580c10c81e22daba806d43c879edf33433b545d8","nonce":"e77389abf637245b8ffcc04e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"b4ca30f7d00bb86ba7230663b0d56fbfbcc121c2ee786784e4f87a7acc78d22888ef8d15c243a7ca2c248574c6","nonce":"e77389abf637245b8ffcc04f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"fb90d6845cbf30dc1f54645b4fc5a08621b6bca5fd1307a1f35e6a032c1008676bf2f395785e06d815e6b25c2a","nonce":"e77389abf637245b8ffcc040","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"13455c69180015922aba4b91fd539f50d0a0ae390f9b0b18d5efd937f0fc36ab32ff1a29a52ddb9833f7a2b4d9","nonce":"e77389abf637245b8ffcc041","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"bf6a1b6488dbc153c6f1acbd1da062b5bf19fa114e0f5778ec0727172afcc628542306ee942d77c5fba54a6feb","nonce":"e77389abf637245b8ffcc042","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"679333bd9d857b55859ed243e785af9c61602a8a5180baa0c5a0c97cbfbc3a7974438f818c696308528e88f76f","nonce":"e77389abf637245b8ffcc043","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"80183b2d58edc436524b8467684d3c439764852adc8cc120ea9912866c15f4e7b0f00185fbf60ed44055b542f0","nonce":"e77389abf637245b8ffcc044","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"b1777cfdf733f5dc9dbf216e7cee3c9fab5057e9d7770299087057a8e0ae9ef82ec27d9ddf0b91095031e324d4","nonce":"e77389abf637245b8ffcc045","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"0e6b0a27584a594a3b6fb4b912613994a8af0872b589602a713d01985405df7af6cb3e7e774d17dc7f2b2b7c0f","nonce":"e77389abf637245b8ffcc046","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"23ac12b46c81b42fad7a6155c0e44ebf947754d1ae1907eada681db6e3943695e90442dd264bc8593eab8e2acd","nonce":"e77389abf637245b8ffcc047","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"583d84aad37bd22ecc74a0e61fa596511191953c7f5710fee22814e7286de5ce1bdaf0d990bdf7999e2f0a1a11","nonce":"e77389abf637245b8ffcc058","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"5597a6cebc9e67d8292d5bc128c56d085a0d6915048bfa5033ce86f12fba84549f5d913608a8d3fe86295a35a5","nonce":"e77389abf637245b8ffcc059","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"b717c071413f9e9a2c231a191f72ea9f34c29372b59734ca78da755f132a8a3c8fc4bc4776588d92849766ee26","nonce":"e77389abf637245b8ffcc05a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"91cd9e1851d0d10182b83bef8f182eb9dc0647775a5101d6a31397e977a4d530d31f149438a0b68a3fe695daf9","nonce":"e77389abf637245b8ffcc05b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"aa1982155cdd87f37d75bfd8cd723ee7d26103fafd6a3789efe5a9c188781c3305044e3496f10f8d1e2725aaf4","nonce":"e77389abf637245b8ffcc05c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"389f6b7bf7c463db7845348881a3b408bfb55d44e67c60804856ff76085bacc39bca39dc1730b4e9f21e4b044c","nonce":"e77389abf637245b8ffcc05d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"502c3c163cb42b41be78283581d3aa2b57c109912436a0c34b1b787ff844c466133f8c29b604d66833758c0303","nonce":"e77389abf637245b8ffcc05e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"1d8f435a0c2cbbf8433d28eba38cf878293631277645bb373aca7cb0c1cb840ced4f6d80e991f9cabb36d0a195","nonce":"e77389abf637245b8ffcc05f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"a628f1ff6463647316b7763b565065a70a45b7010eda905ca67ca44e1e423358e6eeed69b3759b58078fbf1354","nonce":"e77389abf637245b8ffcc050","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"3ee0437ad16665847a67fedf97969de2ffa35fe05e4dbfd8613315f07e03e87bd03031ab86f1d8d45b24e39f16","nonce":"e77389abf637245b8ffcc051","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"343c9b34b100175e675a70131f99f91ccef76240bb402cc58f9bff68148173742a07fcbcd2b7a920e8b4590ded","nonce":"e77389abf637245b8ffcc052","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"9e86e581482bcd0bc79beb22cafd552001f04b56336f8eb1898ab4d2ac4dc7925e3a7190aff842c8d99a4b562e","nonce":"e77389abf637245b8ffcc053","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"a8fe5e428453620e5c6c993ca6854206c5be9d23d222217f110b99b9ef6e3f241eac360c84352d0a61b2b8ca3a","nonce":"e77389abf637245b8ffcc054","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"a6db10d2ec28aa023703622b514c1c667c836c185a99f1282f3f3148c024d947ea7d469a326399485965272046","nonce":"e77389abf637245b8ffcc055","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"801923e5afacd9c79b9e025aff80dda87ef7662d31b76007fd1c592def7f548afefeb1f4404cf713eeb5ddd5bd","nonce":"e77389abf637245b8ffcc056","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"7c2a7e325cd539772bda097d1f87e370c6dddbcb0d969dde5ec919b9b8ef0a65662dea6e74903e364df8f30661","nonce":"e77389abf637245b8ffcc057","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"5d9a00f5d31ad65aa68b0a04c50b487669827846cbeb0e84e4b83807f57250f28f4aacb8309b138b71d8f67e39","nonce":"e77389abf637245b8ffcc068","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"cf73fa4c10d0b4f82dfd029b4da11acf84b8739a55992ec921a00e82c64187e271e66c8763034a69e5a0a55a1b","nonce":"e77389abf637245b8ffcc069","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"e8e33e26603d88aaa627280a9bc2dc5a393aff750349ad3c8edfde9fa938dbaa95ef7aeaecac15417ff07cab31","nonce":"e77389abf637245b8ffcc06a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"af4e4c93cc77c03a6e9cab566ee6b580df495f89bc8d6e59735f0ccd40325d29f3b0cef79438e6fe3dc6b59622","nonce":"e77389abf637245b8ffcc06b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"4be5a36324e616691a527bf38b1af5ed365a7c16f51d7555ebf9236a3eb92b37ac9112fa12a858827b0e427e41","nonce":"e77389abf637245b8ffcc06c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"02fa09ae5535d3029a54bb299555f954b3bc3fa62eae6f1e1dac15ea0ffb0e0e0a75ff3a9ccbfecfa0e30d753a","nonce":"e77389abf637245b8ffcc06d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"4d0e2f2742c9672f789ca91982f25b7b1c549c3c03942c1cf3efcb7936cf3955f8edb63cd859ceba4beaaea37f","nonce":"e77389abf637245b8ffcc06e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"bb9ad1eabfeba3bf445804a2bd982d6ec7ec659e23014882497be3f43eba284097eaa336d40418e819057674cf","nonce":"e77389abf637245b8ffcc06f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"cfef2f2f0122cf2b648bd4b3f055cd5a54ce3ef4e641c7c49a903cd69d7ba36e8609a63f77e4238976c8e8cd73","nonce":"e77389abf637245b8ffcc060","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"d0cb1cbe0a6945cc49413e3c19c171d8d3008242ca619e26fb29c214f531c5df58f3d32091212c46b8ace7fa2d","nonce":"e77389abf637245b8ffcc061","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"eb8d691678db7016f3a6fbf183d0158771e686b7fa000fe50b7ab5f4ba31c9768be89135b233a0bd59f1cfe225","nonce":"e77389abf637245b8ffcc062","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"a8615f0edd79b3675144426ab6dddd370f4eb31b70cb5287fbd7ae7c38fe79ba5f8782753128e1219daa4a55e2","nonce":"e77389abf637245b8ffcc063","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"1dae007a30d8d4eeff3e24c259b5bce358333c79b968efa264c505ecc8f0d9f21b7fe72c1b2bcdedc33f25001e","nonce":"e77389abf637245b8ffcc064","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"5d05caa976b0dde22897670f27fcf79b523b35ceb6b6ff8fc898578a4f23d1048ad0953f98e646d50de1d7b003","nonce":"e77389abf637245b8ffcc065","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"a78b3e8169f0c91290e219a51f99245cf40de5c75ad624d3e8914028239b912f8fdb269a0ecfaf9e2fb5d08441","nonce":"e77389abf637245b8ffcc066","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"285949f3507dc4d785e5f91e8b2eb35fe140fd5999b9a338feee283a911e32ebdc5a4cc2732793a9dc77f633a3","nonce":"e77389abf637245b8ffcc067","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"44bee16a2b970bf534316775915f717db294cd4afb8b3a6800a03ccb762cb38409ae10fa1ef29b8002e74d4652","nonce":"e77389abf637245b8ffcc078","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"a4d15a7134673d44acc04b6fa24ea9d5fe2d0a01888a6d0e7e1f843670a5f16bb54429f2517499741c292a0247","nonce":"e77389abf637245b8ffcc079","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"4115c0ad75e2409f851d4bac23d344702227c7feaae0e384d8f2f0cf775d7e93adadb2841a946536687cf8c1a1","nonce":"e77389abf637245b8ffcc07a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"31b0b31d661ebd211723adf0daca497380389f45eeb75f35ac458d62b5a3bd9d70bcd667a0ba28d06a5dc8016d","nonce":"e77389abf637245b8ffcc07b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"e958a84c824395bdd18c253261ac8a680b65c037ada7ad68c330b2f7ff91bc39efd71f054e03b7a65cb2c8482a","nonce":"e77389abf637245b8ffcc07c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"9ff5214cc636fd7f401e3abd8e4740c3a457291454ea163bf41475b9a14532baee9e50682dc9a676058f78b2ae","nonce":"e77389abf637245b8ffcc07d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"08b55af4bb9f1f1d095bea8cb352b665245c6d68b64a0645b0c18ab0481acf3611c1d7c6494e0c884d1853ef63","nonce":"e77389abf637245b8ffcc07e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"56cebe8ba52e5005d1b701f5c68b9849dc2f994ceb0536621e0d55e8311bff8be356996bf859a34e76e6d6611e","nonce":"e77389abf637245b8ffcc07f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"6b0eeff353b33a44a36df3ecfdff838ee5866b02a21fccb76749f18e1229ae529d022339de695ae938cf3e8fe9","nonce":"e77389abf637245b8ffcc070","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"aa614c9f667780a2c89ddd82e4e448ea30ca2d4c6a18ec9218c72a4d39c6fade83ffede1f4c2d189b9834f8f9d","nonce":"e77389abf637245b8ffcc071","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"56342bea13e2829fb2ca22dc9fe6291ee3432650f0fc8d9f082705a4303c36a3c61052dcbf59fbe26b0d303533","nonce":"e77389abf637245b8ffcc072","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"36cc3f86da22bd50018c51342819f4c3369a54d127fd0ffa8dd32049e33727032dafa85347c5cc8135b6a82e02","nonce":"e77389abf637245b8ffcc073","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"b20dc145461442140d6ba944916c82363163e953b42a34f162e4f63bee13b92e939f6ef82242b3bba726fb60be","nonce":"e77389abf637245b8ffcc074","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"155d47db621d047f53bab153cd9953a227ef1d45835f26cebc0d535561f8e068d4fef8c34ce4c1ac18e7db1f43","nonce":"e77389abf637245b8ffcc075","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"10af750bd67d4de34025be3e75a32e3d864662795be78b61c02b484e93c81eea953a97824798aac7fa992c56ae","nonce":"e77389abf637245b8ffcc076","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"bb70c5d9c742c08cd462a21931de9fadbd7dbde7a879fbd153318ec4f63e5a9693ad679d6e501bf9b66659761e","nonce":"e77389abf637245b8ffcc077","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"955b8c851dfc1d450c44404c35474fbe5fecbf0dabea7ce1f75871de513940b2d65fcc1e1edb6afcffaf1988ca","nonce":"e77389abf637245b8ffcc008","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"73b234c0b37779e8e49614ebd24296adb03fc1cef06fb2181d53546e3dad907dab8c37a849774467717ce3a827","nonce":"e77389abf637245b8ffcc009","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"277848cbd35987d4e42c167eab9754dd717c154ddb1c82d4e68d94c1ba5e9b3eebb3f52ae4f88eb25506b52c52","nonce":"e77389abf637245b8ffcc00a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"eb533e8123dab6f16254fa73852fd64a79d1a1f28abb7d79534eb09625a62789c790d0adc24bb60308b511cbb9","nonce":"e77389abf637245b8ffcc00b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"fd80b280e19b6277dd6220e43c5155703bebf4efa01ade994c0eb403a62dfe1755f407ab58bcf792185a3e8598","nonce":"e77389abf637245b8ffcc00c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"95df244a13c44e17d05a5db016b61381a449d0f60621033191045c90ccace5ddad9b4ec58f5294d5c65089eab5","nonce":"e77389abf637245b8ffcc00d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"adcca2249058e3aa16c3ab00fff2a85b6ce5a072da1e9eed01b5fe970945f1e84c26f25b7f250b0228f9c272ce","nonce":"e77389abf637245b8ffcc00e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"97af7f9913bf976a496b226487d2956adfec34f9404de4bee36f911b35cf3eb0e4c710f0e7aa16dcba79985204","nonce":"e77389abf637245b8ffcc00f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"3a138e6e3f83286cc3c7bc8945423c836d53a815ecb4cec4998970170e83fee85cddd730fb09a6db6086f1ead2","nonce":"e77389abf637245b8ffcc000","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"d296f3acca2968e2e4a131a81cae98c0114529185448ed59b93f1ed1d5a94122d2b99471c256d411557f7dac26","nonce":"e77389abf637245b8ffcc001","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"658c9b5acd610a3af46ce67b5c78fb88b8a0c3cab85f855d7a2b2092df7e8f98857f51e98cddb942314b280451","nonce":"e77389abf637245b8ffcc002","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"84510c0ec5a5c9301b05f5edb45144edeeb6a8edd682866ab5e8789b05cab40f4be3ba751442cddf9129e1dfe1","nonce":"e77389abf637245b8ffcc003","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"d4559cdf51745d3c5cdd9d914c3ad18ea27707b4edb4fe40f57f00c320f5bb9b4aed76845af7e4c51fc1fb03e6","nonce":"e77389abf637245b8ffcc004","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"8c817ee9662c7ddb21fd6c68c2e03c244e6c6b7913800ee72ca38e8f07940cbdfc52cae8a2c77b1b372995b0bf","nonce":"e77389abf637245b8ffcc005","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"4a027e05cc33781e412c41df03c280eeb5d26ca081a254c8ee48bef6c749bba484993cad11567ad26159456eb6","nonce":"e77389abf637245b8ffcc006","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"bebd9f0054fcc6f663ffc325d25c1904abb3ab0ab9568e23b568521992e05aa378402862f1c72caf2b30b8efb2","nonce":"e77389abf637245b8ffcc007","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"f55daddcdca1fa3519d0952cf7c3aee734c1894b23a863924ab57ab901931e6e12a9902d08f5a9e2dcb5dbcb38","nonce":"e77389abf637245b8ffcc018","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"a1b300e4641b683638de87b469d2398b9976f4fd5bffa8e9e654de89b5f2c74e1ba28d71d0d0e2f1c1b902cfd7","nonce":"e77389abf637245b8ffcc019","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"e418a4d0e67f91dca74dfbdb6dd3d13e5c28e65775027a5d9fe730b7dbf31b1eb8b97ca22ec2c4d47529fb2136","nonce":"e77389abf637245b8ffcc01a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"013ee0f5338ae6da9282894ca634d02496d9291c318ed68a223a57eca1b77f94c271fd6591b2caa43fd1e42d51","nonce":"e77389abf637245b8ffcc01b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"5f67b7e5163574c2ca4582ec1ade7147484e86600ed84abb2258e1fe5594ead257b7782017e02346b6778ca8d0","nonce":"e77389abf637245b8ffcc01c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"5699241871d44f92db667cebf7b17a72eeb5ffd49461bc660f20c94a890371b7bdddb6281e50e408b4cf773faa","nonce":"e77389abf637245b8ffcc01d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"d66549bb03d9dbcc8912c4774ce6e653c67ec984608b8665bb34b2420411ef9a8cc7cdce1f8ff7656f1f586ee5","nonce":"e77389abf637245b8ffcc01e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"820d038a9a76749168d9566fd3d0b3522339eb6771869d9f507d3935582e66d66105e7fa4ca637a547847c3d23","nonce":"e77389abf637245b8ffcc01f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"5e36829c8b5867e50bce243c3448c9cbe69177719d912bc5e32abd3b0c57a28854b9f7339ff5c1a8e5387186db","nonce":"e77389abf637245b8ffcc010","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"a8224703b8ad519a5a5ac9392050ad277ff89453c728751398abb248df541b90bfee57bea0e78027f3b5e0a79b","nonce":"e77389abf637245b8ffcc011","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"1a47e312d919345e9656949df8cceda5564e47220c60eede9d53414d0415709d3b5b2197274024f59c75e4b17b","nonce":"e77389abf637245b8ffcc012","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"60899313be2619a7da101543d083cc37976c4016fe0fdff70e63bc2742594ff657dd19f918ea79d5461f425be8","nonce":"e77389abf637245b8ffcc013","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"c932c07311f390e5a2c0079efed5012a7002a23b74a409dbfab0cfcb67144bedf5cc75cbb978fcd185c1f31249","nonce":"e77389abf637245b8ffcc014","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"3ae14ed9cbc4a5f758538dcb720f3353eafedd76f0c8cc0bfece7b46f46b13317f017bc97b411041f099175e7e","nonce":"e77389abf637245b8ffcc015","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"e349ce99bf45443ac645c63bc66039d3311eedf8596e6ca76f11a735d25dcef6741fae71fb98a6b8b968888b3d","nonce":"e77389abf637245b8ffcc016","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"4634fbd24205e6d3ffcfac68e8feb65fbdb425b4279587d2f75ef9e31b2b46c03757df3523858c32043e9d973a","nonce":"e77389abf637245b8ffcc017","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"b4737b997f3682e2f665c8545abe0a09cf2d7dbebe3e9807a06d63ed4288021f5260f99c96b9348c6c640965b1","nonce":"e77389abf637245b8ffcc028","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"96b8c460e28e31bbdd3e1188844ea237cd33776ca09f8cb92945ee83a3eabffd9f883663368be25616024b1a2b","nonce":"e77389abf637245b8ffcc029","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"254cfccbe2445ae3e1b1cdfca8156c5969ebf4be241d03ae7b9435ada8c010732856cbff86852a76f9dd319047","nonce":"e77389abf637245b8ffcc02a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"498f5fbdc7158599f66646f2246400848f965c7d7b96591a8b2192c6b466c0719643b56cc63cfae31e1f524b7c","nonce":"e77389abf637245b8ffcc02b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"960e952863bbb6e2017b09eaa97b3bbdc37cb6a3fe653564f65f21c03f8af48028a009241bf96cc1e847c54a3d","nonce":"e77389abf637245b8ffcc02c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"a846a1e36ea0be37f45939cd21189d8c404f3e1fc75a1ee3bafc60f7c28f263c925f2e0947f39ea0fdf8c1abaa","nonce":"e77389abf637245b8ffcc02d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"2050a573a3a647e334778c361c1501baf402c2a1a50c4a30072bbc5092ac56ceec3ea9e47271dbea5ae4a4fbbb","nonce":"e77389abf637245b8ffcc02e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"9e02e64216647a5777aa768398a035badeb33498be300ee9a739682f3ac1b731a56db1894ecc80cb5a87b50a80","nonce":"e77389abf637245b8ffcc02f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"5e15b6921646e6cad406447eac42a0de169d16d25e14a586891ecaeeeb45b05a7366af5b6197f6e7f7ee725634","nonce":"e77389abf637245b8ffcc020","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"a5f9d61cf1bd2f413badafb6b1b816bafbc4abf2a25dc75c76f720dfa3ea4875dfb8c9df9b91cbbb76fc5920c4","nonce":"e77389abf637245b8ffcc021","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"726bfdbb09d3a6a7a6f1d1e213291b0f492d5b52803fc6659e0e30e139c5e1ee5feda256920504350fd1cd4643","nonce":"e77389abf637245b8ffcc022","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"75a38e72dd013d6434368c2470c52c79bafbb7b621380fbebd05c51733f35e180fa3743d4b7065b24e5e2627b6","nonce":"e77389abf637245b8ffcc023","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"16730a9c33694bb7013de276f145e6eec413fbf8e9d322b804fa720b2422bcdb93f5a3cd63275f30f01ffe8798","nonce":"e77389abf637245b8ffcc024","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"96d62789ffe1c4620a90f724e8f7a13a19e76ba35b34c653becaffaeeaf1ef459315d12b467899be16b0293944","nonce":"e77389abf637245b8ffcc025","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"374f39c3bdda2196efbe0f488f40871e4aed21850b7dfdf640c466fe988938363a08a420e0d1aad30bb6d2fa80","nonce":"e77389abf637245b8ffcc026","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"d69e19fd7cbf47ff7b44f3bd1487b275c45484b50ea82c111fdc19f6c75135e6e413bc19680f87883e01cd1b49","nonce":"e77389abf637245b8ffcc027","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"6dac51b603ed3591b5d01ca669334398c1be7c2fae625f76c12770cb8ef974b4c9576c7976af1874e1c0b7a0c4","nonce":"e77389abf637245b8ffcc038","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"674c170f6bc260e7a0d07843436e0b5b2e64129f56526612550731a4da384370aec23563df934e06fec798ea7f","nonce":"e77389abf637245b8ffcc039","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"096b694cad096da15a23f02c15e0643ee1b0ea62d96831650641e651f2376dfd5868c75541f55014f50c3c08d7","nonce":"e77389abf637245b8ffcc03a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"90608627789bc370cb47ca8ff105e802d52710014b0a1287e2ea7f20cb3e887a7800081aee2fffd3966fcc839d","nonce":"e77389abf637245b8ffcc03b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"31388e0c57507f4d97714b6d131c11371e6a460b089f2ed99d106145e360bcc84db3908cd44e2deb815d58c519","nonce":"e77389abf637245b8ffcc03c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"d9b22938b4daeaff002481b2ce37ffd64003e20d95e5c93fdabca681d445ac95c2d24d37b8684f0e25ca5ebc6f","nonce":"e77389abf637245b8ffcc03d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"218ef85b49545b1806e8370d1578f8d092f3b321f496d302bcde47aaa08b4473ed79f915dfb6932d3be40040ca","nonce":"e77389abf637245b8ffcc03e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"2953cfe06682202fe9b1c4c5f95fe6abc3e32be77b4ee9d733bac4f39686a5e7d80f49abad618a55523c51e992","nonce":"e77389abf637245b8ffcc03f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"b83ee86666f13ad1c5f213adb1a8c7eafb6a1c99c9a3baff599f9bacb88c88d49564780524673c77dfa9039b83","nonce":"e77389abf637245b8ffcc030","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"c16bcfb9a16d149a25e4e52a31dc56c2884bd4a08e8acd594033f36980b0069410ba3f8c4609b7a68af267bc74","nonce":"e77389abf637245b8ffcc031","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"634b477854ecb4b0295e184b63691c35ebc5e2589eb76e0a233e980dbd3c933e6cdef974a0568de01b118aa6ed","nonce":"e77389abf637245b8ffcc032","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"5a34b5b1d2cd65630fadc3baf280191bb436bb6d3418235daba8abe066cf56269cefcbef2066e05a03f6036fac","nonce":"e77389abf637245b8ffcc033","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"93f31341a798cadd7718b987a0ce1a023f8123f247053fd0d44307ae6fac8b864a101d43b28aad87254c708b58","nonce":"e77389abf637245b8ffcc034","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"a5c454ec4d7cf6fe0d2e7a0dc3b6a883c329b8e0e0affad36008bda87b16696b914973163535cf033516f5388f","nonce":"e77389abf637245b8ffcc035","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"42a94bf5a8cc987fd5b976483185e4b48b02d56f44631af334f62e53d703a8083295dc99137eab917f401e9b87","nonce":"e77389abf637245b8ffcc036","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"1a1c734d40fee3a8ec85f419e2b803d6aa9011f88db64296af8f07ae85f2e5b45419c6ac9e9b6989f53069f6c2","nonce":"e77389abf637245b8ffcc037","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"39c051218766238e117fcc071269d0f632e320af2465db395a32be2e32af9679e57238b78c5c043a2224657797","nonce":"e77389abf637245b8ffcc1c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"bfb9b1470c5f7d301f3068d088f707f0f98f95bc3f5d5dfd99540346b8d562f4"},{"exporter_context":"00","L":32,"exported_value":"d7e59fe26c86faf4e8127b4c3e8bd65b92ae8e17c2aa7145f291519b6472ccab"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"05fd21c8c53c84a0f78c7c9cc3733e109874a5404cae5985bd5f72d5e79fb5af"}]},{"mode":2,"kem_id":16,"kdf_id":1,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"acc8d49478d16d7a48335589dc269f625180f30061213404037cdbc4cebf627a","ikmS":"018194bcf92cba5fc316a41d0db26ff1adbd689f0a47acd9c1100474b1cc4432","ikmE":"240e9480c220ada65c3e5c2fad20c8b8c6a4f384ddd1e1862054249544629624","skRm":"6b6581374cb083700efe4b2efcc8d31f8975f815b95daadc4325c0aa21e247f0","skSm":"681e436f3d5408bf91b185e6ce05c3f1c1f424096430eaee3d7127d465490998","skEm":"b3fc4a3e46b090dd0d9c33039781283f15ed25ff10b0350ecc24e0faef10409a","pkRm":"04c63b95a0f0996ec1b676233a8ab8dd353f96610c518c37ed793e099de55ad50fe7fe85dfed9b1b9534676566b02b4205a8f3c7145a76454e82edb3d9d68eb952","pkSm":"047e7d5992ec1d1212cc83c01cfe3c5c86e598b4724cfa36b0c3b890f40392a09149ee03443b92cd16b28ec64157afa1a8358c0a1730ed006aad73d2c7a7c0a24f","pkEm":"043f1e9dc297c547c7baccb789ae7aadafe6cd53abc723c4d455e9328ae43e3c0f62ef4e31682b889c15a5eedee84d9d1327758bae06a40759a1a1f554d17a25a6","enc":"043f1e9dc297c547c7baccb789ae7aadafe6cd53abc723c4d455e9328ae43e3c0f62ef4e31682b889c15a5eedee84d9d1327758bae06a40759a1a1f554d17a25a6","shared_secret":"f75cf763fbe0b94eab3af9522278cb6f028a707dbd72926026258710b1d3ff21","key_schedule_context":"028fc3aeb832490a4b5ab3e42023287db29a1f4bc7c222c0df228727b70a4021127f1ff3fd1aa97af7e5d473e1cb01ba74831133d9659b6c26b03a038a49a84074","secret":"d154e8bf4c470e1a0dbd0e0fd2b8baef4aeb474b60e0ff1ac9c6501b7df1c591","key":"94d7d922c005ce4564ae097bd4b452375d52c13e77c896c5eabf53e6f4b94baf","base_nonce":"6480cc2c4a19201d342753a9","exporter_secret":"75572ab7758d6ee53b59c8eefa397d2b54c87a839eac87f415c9ca9de20445ad","encryptions":[{"aad":"436f756e742d30","ciphertext":"c91cac02de5752374c35cab784ec92264f7eb0537305d57c26c9bbffc6b6d61fb31e03dca2b78cffb7abb491ba","nonce":"6480cc2c4a19201d342753a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"be6e8940fe63c7b81b81afb8b8f3bb5736e3b080df871f2a8d9755c0d94ef1b94d61072bf4a5b0c5bfbebb7f4e","nonce":"6480cc2c4a19201d342753a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"4ea70ddf076a83cf131e14b84da33dbdf9034749c65257b4f485cf124757bf84797c9563187e34043dce504253","nonce":"6480cc2c4a19201d342753ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"4b0f5c525bc94db42004c0ae344777b66201cbaa3c1d928db01df9798e639dac5b8d80a102bac71866af3cd380","nonce":"6480cc2c4a19201d342753aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"aa8beec253e321f2b10a007a4b9f7db9cee10860ae126c34fe0a70808222b2c6c13270a958855b45873e9a3b6a","nonce":"6480cc2c4a19201d342753ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"61c5b0d8bc326231ebe44e927e069a432777dee1548a9fcd96f969481d6e4e325534d2844dc934d5adf5cc209e","nonce":"6480cc2c4a19201d342753ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"2045bfc042adf81ac2307e148b76eeaaafe6a7cfb3afb7ac9c80abfdd542d8f0202e0d3dde6715ef8e1c420f1a","nonce":"6480cc2c4a19201d342753af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"61e980843b999c57691f8367855750b073eb1a35f96786e185775681854bbafd645ade8e6d1956fccdeb10c714","nonce":"6480cc2c4a19201d342753ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"ae0066be3c3abd005fb02b76b1801fbcded215e791e9cd0d89a4c7c7a33a013f1713e96068b88d54b6b61b1692","nonce":"6480cc2c4a19201d342753a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"e14d9e30eb83fce639a2f58638310370fa562b70b8fb102ad1c74d175340d4b66715db4ae51a7e0f65c654b2ed","nonce":"6480cc2c4a19201d342753a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"7fbbd3198b043b76b25bad3ff2fa5b9b1222bec6ac0a96d3f407f82f1b0e64fbae2893669f4f4e6bbbcd35596b","nonce":"6480cc2c4a19201d342753a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"2e7a7be91aa699af399c599126eeb929e6bc512d0212f1158af4798487467d08ab9edc4cc58cfb4f731b4d48c0","nonce":"6480cc2c4a19201d342753a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"a5b1f8eabf81b0769f090e0bd7e5f7c9da66eaa1001026aa436cbcd9c665dd76e2150a911bf5ef2bb39f232e8a","nonce":"6480cc2c4a19201d342753a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"225e684cda5dda1f97ad6bc278184b764d69a653c8073ee273bc997c7c3756bd694d76e53845387e5920785d77","nonce":"6480cc2c4a19201d342753a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"40b031490eddfcd0a54e9e5d23c1809fc6db0811b8474e25ee65627086565b5e793740ece62120693d7648a0d1","nonce":"6480cc2c4a19201d342753a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"a0cc785118cc5423c9026f21b158195bf0e6da8a15347de19cca4033e250c1e3766b612cdff2dae3a694664b1d","nonce":"6480cc2c4a19201d342753a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"be65caed6e51b4d6fca517d69ba90747d1bcd18a5c501e03b64209a0081edf962ec8da4601a93764ff941263f8","nonce":"6480cc2c4a19201d342753b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"f5bc3ca7ce56df9bbe2b2474fc1873f139ba7184d173a39e5b542235161cbae543bf0f770f6dda90c78b36127b","nonce":"6480cc2c4a19201d342753b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"67eb8e064439b0cc6171a5b1a3c73d64d32100fad14d10fce0442cf55ea160699343bfc393780e5c49df564c2c","nonce":"6480cc2c4a19201d342753bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"bfa68881d5ace8fa90030751c34ddb6a4eee589e860564ce7d29897303232dff05ed4831c9a005b2cc92b71187","nonce":"6480cc2c4a19201d342753ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"36470d872f5ccb76b12c329a5e145d2141645a97208a1ea88ced704312905b8bde0f93d238c327ae28a72ff16b","nonce":"6480cc2c4a19201d342753bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"1b57cd70f522901d0f768a55f645100bdd77bdec7556d83818cfa9e5c66b91b6f1475679c8a971e79b9ee6141b","nonce":"6480cc2c4a19201d342753bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"a1a4fa5298ecdf27e50fe6fa62c49c3b409bbfd2786c50971d47257f03381b067ea4bae681ade5280dedefeac2","nonce":"6480cc2c4a19201d342753bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"1b9158f8f6d5d02e149ff573dbf973b405fcbfbbb54413e5a8b5297be631763ea65a5f7d54958a46c88fa0a4de","nonce":"6480cc2c4a19201d342753be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"01bee271d2416ba82b21eec8efdd37288bb2d7afa52dffc035d2dc795ac5855824ff43c5eba7e596c52c0ef42e","nonce":"6480cc2c4a19201d342753b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"eb3d0d79b9bc9280d2ef0d4a980d3620ccc85f23a827342652c0db5514cbdcdec3de7a36bb75e395b7f11a8ba8","nonce":"6480cc2c4a19201d342753b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"f1fd9a9ee4df747561042f89c161052b3f6e9c8030e0f8bfdd5f79e48d3c38f729279da9db19e6ebc08a93d947","nonce":"6480cc2c4a19201d342753b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"8d27ec12958da8f5def0d4ea6f4e81ee58c1acb6b02c3eb8fb1eece2155828ab413d2ab15ea48fca2dba4c8db7","nonce":"6480cc2c4a19201d342753b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"3fd7f1175b56f696b162615347765fc22361ee931ddbb8f57825b38f1ab3307a8dfdbe9422a73306d26527465d","nonce":"6480cc2c4a19201d342753b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"c1e7efa654d5a0a3c144d7adf9467497e0d0d3c692f0a5d445ec92b1881628ea21c8e64121309431764163d5f7","nonce":"6480cc2c4a19201d342753b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"a83cec1b469a3e2f99c1a48a42ab8777d84c6933850bae7491243bb77822997cdfce7ab9d1f6ffea00302a2f75","nonce":"6480cc2c4a19201d342753b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"be315d924b5f72b29610f06c7b6414bc3d445c2571e684b8e074f0911a1376e136d57c12744a3de196d16fe4bd","nonce":"6480cc2c4a19201d342753b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"815df74bc2ac1b5a3a6b230f786bc5e212008f01f666f42ac1e1e875418e22636e79ae3e7421a55f42a960455c","nonce":"6480cc2c4a19201d34275389","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"5398ac4b51ab855d7256d74f46f0b778cea38fe2c6322e22afb38d09a70842618dd47dce5bab1d06540ed93f3a","nonce":"6480cc2c4a19201d34275388","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"82e8e38f1136c6bcb25d5edbc20a3b5a28aa6be9394baafb4927e6f41d62737883573670148b053c2c33c387e0","nonce":"6480cc2c4a19201d3427538b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"d510994974ae8f6e2c157c6dc4e7d2d2e4115cea5fbfbe5925888fe8b4da06177562867cd84de5dae1cebd6996","nonce":"6480cc2c4a19201d3427538a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"9e0f94b99e33e63c0ee5dbfd6dece4bc6f37862e9bddaba12a733a26bbeb02dc9a57c12127a6eb65c169499c7d","nonce":"6480cc2c4a19201d3427538d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"079a1ac785e5ba00ab75c060cf1cc32726564fb7519053e162520950d8b52fdcdc673e6d24ca1c5e78f84d9233","nonce":"6480cc2c4a19201d3427538c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"6518be903c1da355194220ed4ebf23f6af3fb74cf49680e353040992bda61fdf78a05ad4721eca0b09945be758","nonce":"6480cc2c4a19201d3427538f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"26ad2ec5e67ee36f46b4a7f92f70295216931aa796221b4b4bfe535218ccc5e4326fd93226d999069c9dd6fbb4","nonce":"6480cc2c4a19201d3427538e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"52d887a5b0994834bf8ae2d5465c8d6a59cf52d2b02ea21667b3bfccb871ee87d4841566a2574f6adfadf39cbd","nonce":"6480cc2c4a19201d34275381","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"ab12c8ed78e305f8a9bd2b3e8428ca46aba34f73734e50bd193585be63a69f6baad6ddf2412fc2686efe167503","nonce":"6480cc2c4a19201d34275380","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"5da8c5cd36c2aa6ad92f07a33965d96bd54039af780db6120d0a32da5b1d03af91e4105e81c3b0c2f8c1f114fe","nonce":"6480cc2c4a19201d34275383","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"eea94ecbe7773f6d4f00cf7106d81bb097b196a1bcf301fd42dc90b7c46a7f6029fda9157c2786e9d209b1ce10","nonce":"6480cc2c4a19201d34275382","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"f98f43774017bc5ddbdfbc9519ed88119ab686fa06421430c9c3514548f140d0272421dacca308a4ab4ae71105","nonce":"6480cc2c4a19201d34275385","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"668d47762d864aafe904e539842415bae874ad7836b3823384b4abaf459924c9cb88aeffd1ff70bba7bbade01d","nonce":"6480cc2c4a19201d34275384","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"85b8d43808e865b7154e635cbfde06998afe4d00f2354e3c64db4bceee619fe8c1015159554fac40d0bc726378","nonce":"6480cc2c4a19201d34275387","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"6b83bdb46914264fc7c34e5322926dd33b789599dc92b44a1b994b8fafaf5b0a2f745a69130420b1934c63608d","nonce":"6480cc2c4a19201d34275386","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"e7d5a83567b8ef396303085ce42701636615fafe58fcce3b66028ea9c3bcd8f2cd680efa09439fafc87f52095e","nonce":"6480cc2c4a19201d34275399","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"bdf3895f4cb24ed8f9be1d5a9f044ee312bf02ee219bd0571711e69ecdbb7d29ebf63b1a072d3b4a4144a480d8","nonce":"6480cc2c4a19201d34275398","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"03df1941160f87ccdb80c34d0b7ae0d42cbe3e999e1ece90e10c9e02fd7f3894077d68270bfaa29b789a81d1a3","nonce":"6480cc2c4a19201d3427539b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"564ee3549f84d84e98a6ff2211d9b95f416a7a60beed3c74179819cb47dac60f940ea9ffc043ec38eba02673c6","nonce":"6480cc2c4a19201d3427539a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"a74d3692c2a70642c76cc21cc9deacdd3aa6493c86fdfa514a169349b52df9f59bf5e6e8cc468bbd5073cc2f89","nonce":"6480cc2c4a19201d3427539d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"915f8b447afadfc31ff238009669bf45d07d0fc72648a2ba68992eabe83f98cb03e17a7c16df2fa41bd3e62027","nonce":"6480cc2c4a19201d3427539c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"4eb3b328704ee0984f129632e0f7e6d43b86efeeca4b55202492acd1a8c6d0b032b8a62d6bcf9b9a224dbb8883","nonce":"6480cc2c4a19201d3427539f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"dc397eee7a28687bdbca25236b902afdb770c3f2022ce8574cc65da25913cb01899eb604bfd5c645be3c37e3a2","nonce":"6480cc2c4a19201d3427539e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"5a052df7ebc78ed6c33e839ea071e7de8c622ff9e10c66583d0c59b9ffcec951ac04c3a0fc3ab82d31912a0b64","nonce":"6480cc2c4a19201d34275391","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"33f9e43e2187c91f4e575db6125a22b495923ed30185800a7f41ef810a1af9d32934cca623ed79a45d777c716d","nonce":"6480cc2c4a19201d34275390","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"ff86b5f40c470eb038763a54c599d0a019563b4c419a4427402e33cc3157929fa451d3655dcba5f644d52bd7f8","nonce":"6480cc2c4a19201d34275393","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"d9a6bedd5803e8db0ec694207b6248ff4c984bb8650981f3af6028c830ebb8f278e5d6e2f5ed53ae95d42066b3","nonce":"6480cc2c4a19201d34275392","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"6770998d2bb13a970caa84eb7eff29a3591abaefb6245b33a042f5be4df91abe90e16e8aea91232f8bd4f472de","nonce":"6480cc2c4a19201d34275395","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"59b56a14f96ce0651189af2904a76aa7e44467b0cde523bad391a9953b572d5b76653665a54d7c5d1c9a43360c","nonce":"6480cc2c4a19201d34275394","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"9dcbb613fba1958411509fb21baaa62714ddcbf667f98f04ce471d891dc398f9ec6e8d91cbbce13b9ed59634c4","nonce":"6480cc2c4a19201d34275397","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"5cbe821c390f846c224147f12ab5fafe0c86e33b4bc3f849db2297604576cda92d73e58efdfe40a4f61aa8ce35","nonce":"6480cc2c4a19201d34275396","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"799c7e491754eaa10c756bfbe846b70af70e8296a8b1efa3d925016d107c5abd5412546948b0247a5a044af92d","nonce":"6480cc2c4a19201d342753e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"9c0a891f3efca3ce5a02267db205e89b1d79ea63a1e7488067726205d923f1cf56c7c6f118fb1bc015a2017330","nonce":"6480cc2c4a19201d342753e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"a7f0b26a1bc31cdfdced24aa2e80fab4b63ce23df637ed19b80d746613d298bc8e57929f8aff3bf2ea05dc535c","nonce":"6480cc2c4a19201d342753eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"e447b6979bda3b374b6c9c51cb4297a49a88250ec2f07a8ef28c1e5bc8768604bb10694bcf4061dc276f184d57","nonce":"6480cc2c4a19201d342753ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"2e1258e116358081d6f2c8422c279e206003bc31ead914d980f6fd0c15ace74b3318556fc312adb97e307cadd2","nonce":"6480cc2c4a19201d342753ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"8f3a8a5791419b51678b3d66c15f442b38cd5332d286fe15067e7ad56661cd1f16e398c10b3530b088808b2a67","nonce":"6480cc2c4a19201d342753ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"07610efa21558c1f4fcb2211b113686ba5eef32fcbee3481b2502370237777a9ebce43ab0d193f9c40019433fb","nonce":"6480cc2c4a19201d342753ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"659e8844f62c946d3b0f50f3f41f5822dacfe7985e1bfc684dbb658fa6c637cb31d9e053fb31cccc1b4d5af033","nonce":"6480cc2c4a19201d342753ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"4c01258e03f560ca10163c162d7163a8f77e18ea4240b958a36dc703e2ab3fc9beec5f6c4fc3a8ca61259815b4","nonce":"6480cc2c4a19201d342753e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"9d2e3584099e63d0421a4caa68de106129324962d734ac52de783b27b670f13e4e422e77ea0583ba9e39f3f82d","nonce":"6480cc2c4a19201d342753e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"32bd65b142df49fcf99b0c05b1e4a7dacac755464e6d43060be9a73f8e559cd4b3f10da09fea0acf24b278addf","nonce":"6480cc2c4a19201d342753e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"30faf95101834b20970aac11d6f5e025df978c2f40cc3f52ce55b8c7ab88aa4d9676f7de796707742bed5dff38","nonce":"6480cc2c4a19201d342753e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"0c321f081036eb2def9fc82c7fb73af9896e0b27afea36907999ccc2268443d5ee1579d4f6e68a24872adf4cde","nonce":"6480cc2c4a19201d342753e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"fee6f6724cac7f77f4cc055943e3445f1d737b3c643145e2350941dafe4461f47bbe7ed8a2aa504b2350ad5b76","nonce":"6480cc2c4a19201d342753e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"2e913f8737e75984a18b233abd4d06a14afa37a180447e0de56386d3bd85be671f0cb2921f05635221d146ca7a","nonce":"6480cc2c4a19201d342753e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"765ba9b8198d6ac23428d592bde68de1daa41dab080ef9770509022dfae01700854e9648ca98606a7101343f34","nonce":"6480cc2c4a19201d342753e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"ef7f15ef34eea101c063275cde5524a513a87146e6b9de38b1db1226797ff33cc4446057655707ccf151448a6d","nonce":"6480cc2c4a19201d342753f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"6826b0a25ad93c145452ef439dcba5b75f12542147d98f4093014038f1010acdf8f02d93565a7c7484d5f238e9","nonce":"6480cc2c4a19201d342753f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"b9b4f65bc9349929cc1f6917639f5edc8c709355c66518797490ca6b0a6b6dfc1b4cb47b6111e095022aaa6967","nonce":"6480cc2c4a19201d342753fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"2fc5fc2a5eee482f529df16b0601fcd1ba5adec540c1dbd04ea6f27c4b097ada3c76839959b3b7ad52a4ba091a","nonce":"6480cc2c4a19201d342753fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"99722a06fc7e1641d66bfa937c4cf97fd0371a5740ef12c85940e1c52d3eae3f2a42193e0beb03c55ec4fd8477","nonce":"6480cc2c4a19201d342753fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"b2c40884ee1e80ac018cad3c915bee933b0518acc99a7047751a5406d813aeb308427339e8c0b5153b2b660c7c","nonce":"6480cc2c4a19201d342753fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"3ddb1cc5af4fdfe98f977d0df698fcaff1b54972117f7413797401eb6e8de0782677735a537dc62e1aaeacbc1e","nonce":"6480cc2c4a19201d342753ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"ba6ad24df2fea365255bd835c685393e47461a229de6933bda3696c1f4fc4a1db20361ba5dda658e3934329679","nonce":"6480cc2c4a19201d342753fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"992c9be44c073ee54bb1c0b9c197aae5da31eb1c05da43a6abd3a00f4fe90d7358f4317c865d80a945e16ed88b","nonce":"6480cc2c4a19201d342753f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"492c715d9b30f2c9f7b2b15eff00a3710071717abdcbbbd5e6566b21f83b4e52db940b160fa868777d13eaa25e","nonce":"6480cc2c4a19201d342753f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"9495dee00d841ca1a35709e16b42c328ba83a76ef5566e1d54f3b6183f1181cf126fc3cd98d2ccc7caa5af9df9","nonce":"6480cc2c4a19201d342753f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"626a0861695ac115afcb6ce6fbac4c8fef94c3590a767108dce6a16738c04e6b77408e8e0a74d56e715b7743d7","nonce":"6480cc2c4a19201d342753f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"a2b993db4196b3ad127c02b4f5a259aff69330183d1417290426d060c7064f1e256f87c9b9fc039762b55eb389","nonce":"6480cc2c4a19201d342753f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"353fe0814f0247682767d9b13e4f77d1c9c0877cd9bebbbee629b99f4b4cb684c6c8e5ded7452a1dbdf67d336b","nonce":"6480cc2c4a19201d342753f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"360cbcbbc3c149c5964f811aa759006d939469d7bab41efc8ced6397ccd98257fae61bad6728326b86eb6475d1","nonce":"6480cc2c4a19201d342753f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"d7e9a1f19763e96093e84d14ae0b01969f313052a3e2f67280cb3688c338998eff9a3c0c3ed615fd28b3f859c3","nonce":"6480cc2c4a19201d342753f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"80285c6442e81bbc19b0b4ace9d77954787304df03c53c657856d2a55021b819e6a3b5cf8c5ca4ab33e614f615","nonce":"6480cc2c4a19201d342753c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"0ee723686ed77b20f7eb3b8bd9510d25acc191072f4924ef19702525acf3ddb36f9dd6d57a1cba69e265737361","nonce":"6480cc2c4a19201d342753c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"1704dca2d26c72700434e5b7d882bc8df78acb0805ea3d4224ad68ce65080c8291b171915f977d9712c98db2dd","nonce":"6480cc2c4a19201d342753cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"f5771a7ae43c280a9ad061c68e968ff7d2bcedc60ae4bbab6c5492c4ced8e2dc2aaf5e878744ac3a2dc1e6ebca","nonce":"6480cc2c4a19201d342753ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"cdea5ae3366cd0c391ae5a90c30c26285f4fdc3f1cb0e3e6f3ddd3474066c77793b511369221c7f6af159a46c8","nonce":"6480cc2c4a19201d342753cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"9020b9521c49c3b3c39b808c4f3c7be102d1372ca45eec8dd6ac5d47c73c2b8e4805fd62b56ff9532549bc6a98","nonce":"6480cc2c4a19201d342753cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"833ef96bd3c3d723b15f83cd2219957caeeae6fb2fe2fce9d4b37cb6edbb9a7751e94b56410e9654e3912e6f04","nonce":"6480cc2c4a19201d342753cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"018b2e3159cb3bfa319b51aeac9e32be72d1cbf62e03f007d937c5a3bc3fbbbd8d15ea3fb77ca6f63314c0370f","nonce":"6480cc2c4a19201d342753ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"12ee3c3536ffc28ad40bf48547f6c346789b9045df0635e65872ac8aef73ba71730daa2675f863955ba33c54e7","nonce":"6480cc2c4a19201d342753c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"35ef67bb5d3c6f29a4cefa6816c45d303976d21f86784a942c68531e5d1997dd04f9c1e6609957d08238218d42","nonce":"6480cc2c4a19201d342753c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"012b8ae301292ea183123b262a744437484f9b440b56eab4170c22c326fda36c435eb5acb1f8bdd511779a08cf","nonce":"6480cc2c4a19201d342753c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"547f36a0d7963325861457645ac0e3960dee5d02833220564cc8d24c7a067eace48773cf461728bf3385b362a2","nonce":"6480cc2c4a19201d342753c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"977a39e161c8ebc4f3a1e18a6c375aa4cdd86e44afea4b113fd0db05061a43655688f39c53d56d20635b94e7c9","nonce":"6480cc2c4a19201d342753c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"4b60bcd05bbf86883cff4faac04f001f79078d9126111381f0dae7b8ae16468b8c22196b856b6c6e34a550e7ce","nonce":"6480cc2c4a19201d342753c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"358c1d63a7aba715a77dbd71db5f7c7ca3a600de47b9d3c78a0d1ff254942ad7ef194e22d4b70818455490a29c","nonce":"6480cc2c4a19201d342753c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"1d6784f4b8d1a9ba3c122f690d3a26b0bd503746a7d4106ec3a07a6315398129b95c351dc9c61cb8e1fee7f867","nonce":"6480cc2c4a19201d342753c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"03883ac84c2ee00f7c1a1dffb78a166bc9b28f30ce8f6985d29362ce4cc88cf67c66ceae2377c5910ef3c590f0","nonce":"6480cc2c4a19201d342753d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"443efc10d6404f195b729492be7fa3229c2390803a89e5deb39ba643627a6a94897c9811088a2dd58851a761d0","nonce":"6480cc2c4a19201d342753d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"957a8942df14bee11875bb3e6920d55b87edec6c34d66efc63efca5cb721946349968142fdb367ca83a03f026a","nonce":"6480cc2c4a19201d342753db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"e7bd0d80a411e0384ff67380b433ee61cfdc2caeaff42e72cfe70faf54c72d2a301eee2044f481f5d84d8c07c1","nonce":"6480cc2c4a19201d342753da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"821d378e79e853103c3783db4bffcc04e2f2576a83022a9ac7b9177ce190ec4cad1dc8d1664e8444ee4ca5a6dd","nonce":"6480cc2c4a19201d342753dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"2176990d59a16a59e99b3c3066f75a3759b2bac429e4baef7857514fbe772404b7443251f3b7981a54632bae6d","nonce":"6480cc2c4a19201d342753dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"305ee1ff2ddcce885f5dd791299d7e887ba32f1ca1cccb314d6e46e0915be818149644c0244798686b99c6449f","nonce":"6480cc2c4a19201d342753df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"f65198f4d4ac5f22a33b20fa0655828652cfc8ffece382a22294da359b9c2d2d8b725e8b527f0b45b0111f4e66","nonce":"6480cc2c4a19201d342753de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"3b60729f2ef950891d18ba933994ad224a2ee9871a38b9e1759399fb0062f70e7e560de0ad0e582e0abf153a1b","nonce":"6480cc2c4a19201d342753d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"9139647a95fda968188d1a5c4f1ed2bd3d46e6ea9d7996d98d0db1981826f5250a768caee4a6c58fee51212438","nonce":"6480cc2c4a19201d342753d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"403af082dea4dc3df61d5b6fbf0db21daeb9b8e87901747edb5b96f6318a0597507051b350954222b66f32d5ec","nonce":"6480cc2c4a19201d342753d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"45f73c1c5426b63ab64f1bb0351d3dfcd4cacd88a2485b91d11aae2cbf692c15b41092ce79ad53d90135577cc9","nonce":"6480cc2c4a19201d342753d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"27e3f2e3d276dd66233f62147e79b9f22c052d7fddcc3b2e6ceeb260f4235d37c85a080a238bea638bd700658f","nonce":"6480cc2c4a19201d342753d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"000be3483f3278331d06b45e20bbbebb65e1f073f81704ad786dd2fe239c25ae177201edbd40f551c51a7e07f3","nonce":"6480cc2c4a19201d342753d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"7099cacc510357e479f2c3bede549603c8e582f13ab9ca60a61a4f6305e4094e1e27470936d305837677e9639e","nonce":"6480cc2c4a19201d342753d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"bfe0c9412005f2a990f403a49f548d3fc0d7cc5dee58f62b130a1dce8a135bbce6768e210d013b662758e77d11","nonce":"6480cc2c4a19201d342753d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"8d02b125db4b226a7a3ad8640d0d6a176e7376786039103c51a10759fefebbadd97f2fb3928dfcc886a8a0a9a3","nonce":"6480cc2c4a19201d34275329","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"c9ab9d4effcbde6d667cd6b11759b9feca687452cb5d5aec78575487a0c58ebee1be46f92b0affb7a91ebe394f","nonce":"6480cc2c4a19201d34275328","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"6deb23b7fc3a91150a8ef08a26e8822e591d494e9475114a568c8d91df1c920c4b7f0614dbda8a44277a21c400","nonce":"6480cc2c4a19201d3427532b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"6aa9c0ff319a11cf813e53a1ee2678d796c5636b0787c813958e75484a15585d9f2c29e0a2f376a4b110781ff1","nonce":"6480cc2c4a19201d3427532a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"e07bf2f51f9ebdf50521cafcf2e0ae9c9742ec096f475e1150ee06b60cbd57f6e0a8008ae931af3891b541efda","nonce":"6480cc2c4a19201d3427532d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"f1d7a857a0ef4314cfc768aef332e448379fbfbe2efafea8b37137578cef7a6811be70669d81564a0290a2c428","nonce":"6480cc2c4a19201d3427532c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"2c550bc4bc54093645d09fa5e5db073dee12a980a1e26a942a8d0364b70ea9c441ab57d1007c49a779b11bd259","nonce":"6480cc2c4a19201d3427532f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"0bd96ffd3e2e82597a1d72bf9095ff8cecc1730f268947ab79468fc158c0e411c64eee2a10dcd430d74e5c5522","nonce":"6480cc2c4a19201d3427532e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"13eec4c90c9f957e0caf693fa7349be6c08c231094497da50356329360d6c66e689586d10057056dff6d7267a5","nonce":"6480cc2c4a19201d34275321","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"5339986cfa97a5b716b005d05af075d3b85a41a99ecf0ff67b222000b32e88e4d83ea13f0a14880083a44d9b16","nonce":"6480cc2c4a19201d34275320","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"d95cdfcd2468c4f0a7dc7c12bf676edd81ad5d12d32b3d4c1946726470253ae46d7cfe18dbae8cb4be9d554c68","nonce":"6480cc2c4a19201d34275323","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"024758d736f7425cf42db486274b34db2cd0f38b898fb65c7ce3d0bb0c933d1e9b850186f71385bc1a29165551","nonce":"6480cc2c4a19201d34275322","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"776f7e7ca8a38c26e65c39ace02526dfd0138d5a07e812b0f10d479b610d3a5d2db5b35b44a6e220a4f176e947","nonce":"6480cc2c4a19201d34275325","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"9ffdc423ba72fd467ebde01ade061eb7a1ab7397de38fb854224409949e1dd4a36e887e1956dcc7eb5caa6bead","nonce":"6480cc2c4a19201d34275324","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"6a5142f31124b0fd38743da6a94963ddbf109f78417380f5ffc27806438d284ffdf589cbba488fc16758499366","nonce":"6480cc2c4a19201d34275327","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"21ba3f017f9e75b4d98eb2945f8463729f33969c521a6e585842ff492348eb8f6e10d65bfe9cde543b5c135fbc","nonce":"6480cc2c4a19201d34275326","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"19866e2a3b5ed76cdeede136f28bb47febbb93b22701a5781b5e3e33ccd0c78d891b3f2fc993ad19d33472408a","nonce":"6480cc2c4a19201d34275339","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"03c26f235727bb424e3affec8d85d42e345c6293b64bae3056aa17a23f7c84d8d5a193be9cdfed5423a170d778","nonce":"6480cc2c4a19201d34275338","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"086da9c49b09ce5d9f0d086572402aad69b2bf395cf14d32bfd9f35b717903ca8459c0be6a22746ba8e1cdabb9","nonce":"6480cc2c4a19201d3427533b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"fedee845acf1b9e1a47d073ff15f550b3ce51d55869d49a6cd110352baab02dda68aa0e902f4861f9b6fa5c4d1","nonce":"6480cc2c4a19201d3427533a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"b086efb68d64946ba2957cb5d596dfc061f8a10779f6c269d9d0ce8fdfcd95fca5ade60adafe3ea1fc15b6527d","nonce":"6480cc2c4a19201d3427533d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"4b0a54e06ccd162bdff3c6e8f3369e22c5d193b7471ca729a03ce41c67b5257b47be213583fcfb32302c92b6e3","nonce":"6480cc2c4a19201d3427533c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"01152d892b57686f149c9fa48c5ba4d0c966bffd643518a7030fe349d8dfac4fd9ad2d8acb3cc3d45cd2bdc2d7","nonce":"6480cc2c4a19201d3427533f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"52433253ccdf1fc33758215b053bd37c5e69108b437c3bea2922ee1bb04e4e592ccd20dd98e559c3cbe87a4481","nonce":"6480cc2c4a19201d3427533e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"2001ab8b12fe517af978f64524216d556666792bd225e690ca6d900513d218415e0c0c7d1d3b13352fccbf9b38","nonce":"6480cc2c4a19201d34275331","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"eca4635ade3798a321b6ae4e1ea8bf7f043b57949b386f74478c8530d51798ee5848405e548e2e652b85b969db","nonce":"6480cc2c4a19201d34275330","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"0117b702374eed42fdb6b8ddfb55870363a668be55ed8f01d89b470f496f45e71690c41fa4199982c728ff9bfe","nonce":"6480cc2c4a19201d34275333","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"d8b5da889818b64869988e9057f5191dc08afb8ed06ac9e1721ed784a489938d42faa8b9393a88d59f042181cb","nonce":"6480cc2c4a19201d34275332","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"42afe6b2688a54d94a33b047c7336682e0cb99d7937016cb16b7cd253f749729ef00bd2e5326b4a58ba9da9c6c","nonce":"6480cc2c4a19201d34275335","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"fdebd80e1d2b8e56672f310192fd18ca262cc1fd4a08de6f1d388f91057e917af6f01d349c2ea539f50a32d8d1","nonce":"6480cc2c4a19201d34275334","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"97229fe2a7c3b4938052f71e20d9bc2684546283b74eb5a90c1866bfe780259010ba567a280c038604025f8ad1","nonce":"6480cc2c4a19201d34275337","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"44bc18b5e91c564a46e3c5184197c9544db5889c2286be8c9a3862d3797a382059a234413fac4dea95d6c23527","nonce":"6480cc2c4a19201d34275336","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"dc4d7f1878ebb06e8ec1d739662b7d7760f059273fac04006ef82d87962af11593eef8e2b5d624d06ea9a3bf9b","nonce":"6480cc2c4a19201d34275309","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"96d89c16a620cc4bb9535e6f685faf644f30c6677169e102d9cff48a176961a2552e57bb4de4770efb568b14ef","nonce":"6480cc2c4a19201d34275308","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"173a68fecdd6c58900557943929ef5fdf492939e10c18254f5331423681d8b7609fd5b717bd9495b28f307d10d","nonce":"6480cc2c4a19201d3427530b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"f46eff4f9d2e2f9f7d8247b9c7f343079acb9cbe7d81a4166b98dba7a767865d2035834dd532e97f6ca5d5b414","nonce":"6480cc2c4a19201d3427530a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"6e16699ee518daede55fc9c97257866fee9c98fc9e33d77e4a7fc84a8a6da61fbf1a24f3d733c2c173310b3750","nonce":"6480cc2c4a19201d3427530d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"f0d69cf6ffd7577cc2a92d49fc6ad0e0d2e218e7013a41fe1c2e71b622532af02eefa5f726dd093cb97ef000b7","nonce":"6480cc2c4a19201d3427530c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"0d84319a5e9cdfce86780c066a6044043513bd04655c89c238d53cf5428a7fcf16c5cfe7de65905446428c672c","nonce":"6480cc2c4a19201d3427530f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"394f13f4f97ea443dbfbb1742e27b7838a4b65e1c04a5d26edabd41d6393c827fb3b0293d089787e6ba4230827","nonce":"6480cc2c4a19201d3427530e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"3a45739cad01dde159a6e51e2b116522a94da99d606d3f52b742acb66c3cf524ced1c53fbfe27dbe7c17de293b","nonce":"6480cc2c4a19201d34275301","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"8fc03cbf540811a620e53fea9696210ef1f79edd6664c7c40836c9ca3a3319100ea2bb66ec3987607be1513ff3","nonce":"6480cc2c4a19201d34275300","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"122cbc627b1cd1e68e7a8c33e08a301220e48e0e1c2228f647975be4cdd60fb46b9595bef1d39bcd3cbfbb3eef","nonce":"6480cc2c4a19201d34275303","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"7a127ba2b52a1a442c351333184794448b1ea9f760d25ae382bcc5e0683564f798e16cc2188e73bbc834b75d48","nonce":"6480cc2c4a19201d34275302","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"038f78bfea230ab323348836eb26de35fc5562d86a5ef95f230600ce8c56f22fc85eb0e1a4bf41e478c29589e6","nonce":"6480cc2c4a19201d34275305","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"0351c3a534b777e359e149f0805b86a0cc858a789ff077ac087f7e1f32d150a6662f7335f26555a56afaf520eb","nonce":"6480cc2c4a19201d34275304","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"e874830888aaa12b4ce13004804f4f1c21b194027433ece16048b566977d08a64e04f684fbf9df0f15e2352f93","nonce":"6480cc2c4a19201d34275307","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"817cdd71e09ffaa84ae983b266058dc156e64011fab593f9a9e5dd42646371d9d1076ea2c920d1814316183340","nonce":"6480cc2c4a19201d34275306","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"a736a9b26c643b94e558d6e24ed39bbc9e125385dceecc39275a2a584fa3d97ab06d4cb8e7826b1e3227a7eedc","nonce":"6480cc2c4a19201d34275319","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"44f42aeab802f4a0510b762f965e3f2b0d0b801edfa7bf7a9345f22db14c848316dadac3df5749e06b8f0c6a4a","nonce":"6480cc2c4a19201d34275318","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"5323abf6ca02bd431c7934d6e248ead5888336bc375ef124c649a7bceb7d31767e91c011d6d3ef742ead739286","nonce":"6480cc2c4a19201d3427531b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"6ad3906f11024bc8e2a2620c0adf72c1c695c4dcbc4c9429b574049d3d9cce7826736dfe222676e6be964c5b4f","nonce":"6480cc2c4a19201d3427531a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"91a7e67098f5504f847a5a6e4142ba5f6c33b4bd6158972ec9328f2836fc4d7021d8c7810866e1bdf4d819ff20","nonce":"6480cc2c4a19201d3427531d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"c24394be9df5c78fcf58cc8c2b672f414e43cd2bac6cb4dffc854297827b049a7acd5f8f899692acb5c8259df8","nonce":"6480cc2c4a19201d3427531c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"3c54ebe3ac30ce59d96916305e215f7c2a8b0b09ddd1938304c730e75bd8b18956e6321af92777c3095468a5d7","nonce":"6480cc2c4a19201d3427531f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"28d4149054040310ad8ee53e2425df91c2518e30a5303941982d12b49fb05c0eb1b96017debf24c19f00a20615","nonce":"6480cc2c4a19201d3427531e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"31d333ecb410bb71b3a82ea75bfca9955a69fdb25ce50615c42ff3f7303635b08400f08518dbe664aa51c2db10","nonce":"6480cc2c4a19201d34275311","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"039fbfab95840882d397c407a0e4016433aee42616cfa3d2bb5240c9097673e296dffbb1b0174979caf0839717","nonce":"6480cc2c4a19201d34275310","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"2fbc5c23c45e6426c74ba783ac9501dba82766571b567c04343e6b195b0383edcad993a1153ecb2ca7eaf75b5c","nonce":"6480cc2c4a19201d34275313","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"b6e769a11a8698174c646b3f08ca299fe69f7e55cfd527663bb1d602774b5901925c9d49b02a2f616546b9b167","nonce":"6480cc2c4a19201d34275312","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"7fb942854b700738315c33ab6d58ff8ba623da5df91288156c8dc40d8fc5214fc7be43812bff11ddbd2137329d","nonce":"6480cc2c4a19201d34275315","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"4be91a0c795c3e09a642030d3efe913200054966b9b5da759f6849fa7303426080599a3c6aa5edb6e592c36ec4","nonce":"6480cc2c4a19201d34275314","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"9741933da57e1d6660882bca1e8cd4730e2a76e23ccd27dadd0f2c2c06dfc36d7dfee4953124a9b67cf1947c12","nonce":"6480cc2c4a19201d34275317","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"b1bdff084d3c90552ddb16fb61cae1071106f3a73e643f022a40cc4edf5b34fda7267c475d93df584730955d04","nonce":"6480cc2c4a19201d34275316","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"6e580d27fdf20a09b2abfc9751158b695afbc8aa98ec166469160df0444386a17916e253e49b80cd895648c147","nonce":"6480cc2c4a19201d34275369","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"010a3bde90274c25d229c7466c779798a1e77a1ac71de19e92e6822bb695c666ef189c226f4d773708951b951f","nonce":"6480cc2c4a19201d34275368","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"6e06b15afc74fea54b93e273d34e1f91c13d8a6feb498dd35df697d8c8bca44bae964fb449582d4a46d4ce4933","nonce":"6480cc2c4a19201d3427536b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"3ae99fd4bb0a8b5dd91837fb430fa7efd7f0de819fc0036992e61dadebcdf4a16922be3760d05a767e30d37dfc","nonce":"6480cc2c4a19201d3427536a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"b08dfe3e267622ba7be4e1325ea005e3d8c148fe4e761d3bad234d621d9efd7b21a85ba2e7580595c91c57cca5","nonce":"6480cc2c4a19201d3427536d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"53dc3a99e169ff9787e2a803d6870cf16c0ef12481c6de75ee86e5f685401f93470e6004244ea177b37372a537","nonce":"6480cc2c4a19201d3427536c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"d01506510b194de18a680e70f7920c5d1344925514c699968d340da3d7dd90d5c4eff8b36d68fbc7f0617ce861","nonce":"6480cc2c4a19201d3427536f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"1dcd2e82752fad3b60c180cdc663c3721e4a342fedc1ffcdc892c1671e0f5366cc50d763bf4adb1103c267c3f4","nonce":"6480cc2c4a19201d3427536e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"1fb39079a9f1caa8a18907baa26c3e59c04ac709fa7215aea2f5208434c3fb0500ccab4ca52c6ab73e4cb9a4f1","nonce":"6480cc2c4a19201d34275361","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"fd8ceb7f6c680047ddfcd3274bdf5f2c17c572f603efda8bd0021eef310c1d76234a0fa11ada540d32ecf0dfcc","nonce":"6480cc2c4a19201d34275360","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"a4cbf2c4bcfe521e7e254614903809a3674faef10cfffeccd6dac90c54ac9d672db17b75a7f191bc822066e5d7","nonce":"6480cc2c4a19201d34275363","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"2a8f2bf8b0f4cb9caab0a888fb492f173796be92b9bc9383365f9839c81efa976f9f7f4a5f3dc7e8522aa42fc0","nonce":"6480cc2c4a19201d34275362","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"29fbea44e2b418f639af718e9af65957e6d69f88f1ffd5643463081b70ec4dfe28db92d49a102280e892bbcf07","nonce":"6480cc2c4a19201d34275365","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"8a32c5522b5d9fcb54bc494350b194b16df64b348f45fa296bbc700016e2f1a867bb390ce2c0dc9be50f99a6af","nonce":"6480cc2c4a19201d34275364","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"24df7f988f453e2348aaf81aef44982fad8522d04450de96b95be24172dadca4f4cf6c768fec599fb5a7203a6d","nonce":"6480cc2c4a19201d34275367","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"8cdae579f9c2f55d9e65c10bb607e4481e6786d728e54d78226e1d447139608f4e1c7cbaadb66826f5749163b5","nonce":"6480cc2c4a19201d34275366","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"14e5de72875c92cca813aeac11b10aba7d7ddd0263842d81da0f1e23f445b8fd9d7eb7f4c01c27352c9d03c6e6","nonce":"6480cc2c4a19201d34275379","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"70289eb79b0e00d2208f8575083a619d613f041740d7fb32a4e04e7bc6b61a80db18e03ed0be6d1930250b0319","nonce":"6480cc2c4a19201d34275378","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"fa0361f9ac79fdbc9fb3c25aaecf278a24cc60b4e462b9e6cc6600304c1f0ab7e6f1d92b915bdd518cc98a1a00","nonce":"6480cc2c4a19201d3427537b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"4d08574e5e9f2331153454cb6add5ddcecedfbc58485b28e0d90d79a5d1964e05e486b4bc786cebdfdcd6017d6","nonce":"6480cc2c4a19201d3427537a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"93f11d97390c080afcfa91988407daa2aff07daa1649a76b1ca63f4ed4ec3ce654544c86e05e80cfecb753d480","nonce":"6480cc2c4a19201d3427537d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"c801b6f7ad0a49c6d55993aa6cc5c3974e1589078bf7a646514dc97feb4a354b38c7f076cb4afeb6f5d275a24e","nonce":"6480cc2c4a19201d3427537c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"b159003ca9d0d8d967ac9dde07a6bee94d91fdc35f0688bc681eb6147d21b608a19781a7da1fde6697e61237cc","nonce":"6480cc2c4a19201d3427537f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"9a120abb217b4ac4eef3011746a5087536aacb3d637a06c939de6c54e91a60db83d4fb2dfc65fcffbc6732e4bb","nonce":"6480cc2c4a19201d3427537e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"4d63faf806ca5ba638de421abb306b625b415f59ae38c8370313cc07cac12b4c64a7abc286cb93110aa5ee29d3","nonce":"6480cc2c4a19201d34275371","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"42e2766c29f16ca5c26aca95022f176416b0f010cf1a5eec6764b827a275e08903943b6be6b97fb97e9f6a539e","nonce":"6480cc2c4a19201d34275370","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"68dd2b7393dca05b928e32269e095362b1766de3a0c86d775ce4ea473d1062667a823a03888a354af46614503b","nonce":"6480cc2c4a19201d34275373","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"069a742192b09ebd06deb25e71c1fdcb8de2634b44bafb84e024949b99b2661cc20d59ab6ae395c79fcae68b1e","nonce":"6480cc2c4a19201d34275372","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"aef4fe67514707c74132da434cf9362b439f66555b00155488311174322095e316d5c8399005e7b28101844793","nonce":"6480cc2c4a19201d34275375","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"d82e7663ab9a51b653bddeb7ca827c846ba03720aae6aaeefbc6f502d8f06664ed7fb044e9cf485ce5270e220a","nonce":"6480cc2c4a19201d34275374","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"d4a9eb084bff999808041d35a0a23f1c53f9b80a87561e44fc4ef923a99c003e1038173984aaa498301b4643a9","nonce":"6480cc2c4a19201d34275377","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"721896a284ee956c62451fd3b3abb0b668203dbb99807dfbbd71222b8db6844e8172087500238248bcca1be3b8","nonce":"6480cc2c4a19201d34275376","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"0a73d8bdf441b308e1539c1c2388383fefbb9395eda4eb318b6ded6ffe051d97c4117ae28a4ab328412893b2ae","nonce":"6480cc2c4a19201d34275349","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"badaf4e6291357bc08c32e3a08c295478db4699c46e1bd9ad9ad10104b41f812439c0200c2554ecef394f227ed","nonce":"6480cc2c4a19201d34275348","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"0a3d32d7016315733d072774472b1bf3fab34c0384928e8301719bbfc32f8dac4aa74839d22bdf85710cc88c9b","nonce":"6480cc2c4a19201d3427534b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"318eb9b4bd5b36a1a4ea252f7d3ca0338f4850f0322ad3bc19183c5bab48fcc556d77107a087d95f87cfc5de50","nonce":"6480cc2c4a19201d3427534a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"bd22616663081a2e25c3ed984f85c0b72160b82a280db10968ac491e19887955f49da4e7b051791267fc8f0a5d","nonce":"6480cc2c4a19201d3427534d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"b09977092322ae286e74d9023c2d431d2bd462c7e1c2a8a071137559108edc421054c5fc4aeca2f911635a14e9","nonce":"6480cc2c4a19201d3427534c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"0f32d81826345791b0acd3b671d0b26e5115bb8ca011e5afd7f70ab2654cf69fb226c37eba7be9d73fbbab1757","nonce":"6480cc2c4a19201d3427534f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"49121ef33e1c90a8104eddae18d9599507e007535a8a1e7be54c40f0a45f49d956c2d9138298abf0710ed02fcd","nonce":"6480cc2c4a19201d3427534e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"6a9e7d8a394e1136d944e2c700db05ad1a842870813229e2214ca0ae52b365e4436c4938e0178fc6549dd4df80","nonce":"6480cc2c4a19201d34275341","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"cf2fa3036896e4c43f203b7825dc6952b8d32827bb70b6b278ae9d117a61b4a6ba3504f8896cd3e430da54401d","nonce":"6480cc2c4a19201d34275340","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"753bf2b4d70e0ec11c54a68da139d6f465d46de81735f1e7e6a96b04bc557cb5685d191d3edb7e1fe40b5a3161","nonce":"6480cc2c4a19201d34275343","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"b96a9a03295c282db168b6d54b4604ccfcfe3bf01c98c316286016fd4e3955c1f208ec6502d192c4f80701e336","nonce":"6480cc2c4a19201d34275342","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"115d740c0386823494cc93e88bb4da1d7e55beddebf359aa2f2061a36f1af6aed77f619c136203592230259702","nonce":"6480cc2c4a19201d34275345","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"d3711bb918b6bae7c386d6af528c3f6f02b969ea372ca2b7651ad14f1fafb7013253f819e1d7ca7d39068625b3","nonce":"6480cc2c4a19201d34275344","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"16187333afcdcf2b8bccb57d037297df5ad3cb86cb47ab34f8388bf9584b15e7df15f21a537a7945b21822b30c","nonce":"6480cc2c4a19201d34275347","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"7a170bdf4e29ef75f88c269859b85cdad6bcc75fa574bf0d21c22c621d81436245e7819dc8fe6983d044212283","nonce":"6480cc2c4a19201d34275346","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"e4806e89c883ba6be72464ebee2329ec8527d0274a72f99d80f7f97f0c886f5e105f176800ea7b7a5a38e36f58","nonce":"6480cc2c4a19201d34275359","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"ee0295a5b91ace0f93db984885bea9b54f8428a2dda27232608a78689ebf9fb29c574b602a2a396fabce02869a","nonce":"6480cc2c4a19201d34275358","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"1fef0461c467901cf1ccbde17905cd0eae499befd6633d0259fe9d4887c814a04c03b33cbac1513f3aec3ff01e","nonce":"6480cc2c4a19201d3427535b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"e8e99c0bc2c4b07cfe79de7674bc50b7b5bbe2093610a833bacf09cec0686266dbf546c05767cf094dbab66b3b","nonce":"6480cc2c4a19201d3427535a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"c68d8798565908d3912b164a85a9e35b035d37d46260224bda9a192cc1dc2d1e73a92ffffaf29d807cef8aa8ba","nonce":"6480cc2c4a19201d3427535d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"9eba7accef8f09977978de960d0a5ce0be82f3ec34b248d75fa11213247b6589575e72a1dc92ae31b5c5712e5e","nonce":"6480cc2c4a19201d3427535c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"8fde362793c9f8ee54b3a424d4e3d8897de54c2bc91f42454ee715b29720a07433893a79fc78b153391a3c5773","nonce":"6480cc2c4a19201d3427535f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"9ee024d59812ac99f9edf0f64aacdd1bb01276108fe6693f1314fd8513936e81392cd003c6d0c7987de411751b","nonce":"6480cc2c4a19201d3427535e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"f9fc2e59d7d45723ca7cb25d33131455ae940f074f5be3c7b91c46bb80f57df0f00eddd30c3f904d6b84e23dd3","nonce":"6480cc2c4a19201d34275351","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"cd9f65e7bbb66b3375f792c26300638e4c1304c252937d1e00852d1bfa543c2397e0da72fa877b9028074e9a4e","nonce":"6480cc2c4a19201d34275350","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"445817d041cbc9f5731d417827f50c2c0eca60a59134990543f8fa920663fe42849b6a591ef52ad53c180791a2","nonce":"6480cc2c4a19201d34275353","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"555fae6991f10c50e9cf9c906f2c9eecf50290033e210696f5667cdb1bb177c81b00cf3c511247660c96f357b7","nonce":"6480cc2c4a19201d34275352","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"ccb65f5c6ffba5c211fc0aafe499804fcf11117fceac5fc3711f6b7e661b6922b3fdb21394d0c1fd5bd205adc9","nonce":"6480cc2c4a19201d34275355","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"73bb7a671d09cf8bd9772990ada72b72795415fdc0ad66d08a66284a040599b1b19746989a9b678a71be342dc3","nonce":"6480cc2c4a19201d34275354","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"4ff22cefea9dd07b225f6c0e57431a848a22e93a3120ae9efa99f65f2f9c667d42934f6039f5abf0bd083a9989","nonce":"6480cc2c4a19201d34275357","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"7411662ccf1d0b15e774a2ca9823b38a50f036fa88a02a39a22fe708f532f770d2d82e1463165fa5d6577d8940","nonce":"6480cc2c4a19201d34275356","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"c3d35be0295a68b9f9d9e95c59accc769624063a03c7cfeb7f012078ddcfd0294b23bed26a12eef7d36d3f69b2","nonce":"6480cc2c4a19201d342752a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"83a1361d866bdc049addea53f619a67d856f7023bf34661b577fae5b1f0b8352"},{"exporter_context":"00","L":32,"exported_value":"3c96f42cc87200fc4b1d96cbc534d783ebc96ff4ae52a078b706cc6c900635f5"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"8d6e24b1898e0a36de5d667b1dcad9abd2e2cf25dda46e947de423405468b845"}]},{"mode":3,"kem_id":16,"kdf_id":1,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"afc159c07b9cdcdd7d92de6bff784a0a548d39e53f984aa36fbc383b0004e39d","ikmS":"346ff786d45323cb1efa92d0f9fb7f27385297cf9a63f825a4a8c1319fc59009","ikmE":"da933dd85f6329090582baeac614ffa9ea3470ee37433b23b18409abbbc488a5","skRm":"4f85f278fea487695bf3043669e1fdaa88f6f7a866cc94eab40801e55ba6248b","skSm":"289e807f26ef09c316494034823dd9b71c75a01598b1226c6e9e59f0c93f07ba","skEm":"4388d21f40415624a5971483ad9530573d262346d0e5995b4e54c09c4fb1f9a3","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"04f6b40e7606115513ebf5c9edb483920275f1300e57ac49e5682110eb57ed4ab2c1cc3694203343143ca07d6a74ec8aeb13ea47fab747bf110f3af61f3be6e24b","pkSm":"046a147eccb0ca16f6f7b89a341e58f09917bf963b3088b94f1bdf64f9b2b8c78fd91c7f38c325ea75d76eb3f51f58ef55fddf739df8eae66b53870ca0d6c2798c","pkEm":"047e7ff64b310d1079802d277fb9d4022843d7330b1e1157a01557f3f4a80f900b57a8b1ef2f77b7e1c578732da3b40f3798e57830a6e7b2575f5cff5784254fd1","enc":"047e7ff64b310d1079802d277fb9d4022843d7330b1e1157a01557f3f4a80f900b57a8b1ef2f77b7e1c578732da3b40f3798e57830a6e7b2575f5cff5784254fd1","shared_secret":"9f1ca22f8456d9281d3f282f6b76771122e9b6423792b2ec80241ceab32b1fa5","key_schedule_context":"034347bda95dee60516b0482433e06221b26075bceb38f3931c30f869f189cdf8f7f1ff3fd1aa97af7e5d473e1cb01ba74831133d9659b6c26b03a038a49a84074","secret":"b7ac46497aced4b303f94e8135652c10a6b6d7d69c727820f53bb1c6afce185b","key":"b7da736e32c049e2a13e15fcdf0408dd9c260894f21c6899b65e980de3952d65","base_nonce":"585c5e66ed424ec12dff9aac","exporter_secret":"f864fbf03d49020780759cba793169023aea0e26a50f0f7fa46a9630ca81be8c","encryptions":[{"aad":"436f756e742d30","ciphertext":"c82a56851f971bf82c3ef6239c0becff1b23753ce2329f97033f595cb27ee5577651c56175eb48f981416604b7","nonce":"585c5e66ed424ec12dff9aac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"05b0fbbbd5052f424d9e41a165adc867b3ab8ecd58ef84089fee18a75563769714b6f0cd67549d983b2ef992a7","nonce":"585c5e66ed424ec12dff9aad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"522314a37e5eb89f6dc811eceea9a9067bf94b213a76d77a3c11514df149f0b09ae6f962bcd15b8bc7c47793f9","nonce":"585c5e66ed424ec12dff9aae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"a62787d7c736f32efe583198798465ecf246fc748358e2e823a7ecab26c3af58589b8fccbd13ae043e62235096","nonce":"585c5e66ed424ec12dff9aaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"d5c87a1a4f1659512426a45a6ea10fce277db2ca46aa7ee57d97a5cce89def1d42cab83cf181e19e64eb08446b","nonce":"585c5e66ed424ec12dff9aa8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"fa7eec779087d467c10dfdef3331020898f39c945d0e6c6d2f3a4678634248b7dd51b4853fe2da608fe5c8404c","nonce":"585c5e66ed424ec12dff9aa9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"251cced286f7b9342519a9534bf9d8834ff05df2d7056de9113dd73ed7ff94896f6d0f320e3a37e9356b5f9352","nonce":"585c5e66ed424ec12dff9aaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"37e482cbb62d3b545cd794a376587ac71f72ed086668ccb1ee93ffa1fc2832c63494f2383c4a6dcd51fa7c19e6","nonce":"585c5e66ed424ec12dff9aab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"db140c670bf968293537853030591c1f0590ee5f5e669ab134edfa80d167a955c7e83489c60eb7210d64d9234e","nonce":"585c5e66ed424ec12dff9aa4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"b286170d08975ff09ddd2b4d6d9bc602cd64534518ea2a007c2b2ac9fdcd28b21ac3ee5a83506a48ac78dbec94","nonce":"585c5e66ed424ec12dff9aa5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"82906912b8f4512ecd5d69a2d6734e68dc9aeb05b3e5afa28e6c9d93643fb2c54b60b6b9b55c0a8dc2fddb3da5","nonce":"585c5e66ed424ec12dff9aa6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"96658e50fa02e715125bd4eaf3ff0bf94f766fd6548da4f9c28366c7b04c4b6c2fe2fa004db355abb77f4adb62","nonce":"585c5e66ed424ec12dff9aa7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"805f8f5f1292c342fc16e944900c192a3b46189305437fe494047c46ee4e87603d0aad567d462134a949d8b390","nonce":"585c5e66ed424ec12dff9aa0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"ad1138b574f7560b17c916144a6407a1b8ff7a6d4f7028e51e6f37ec9c03ef3bd6e324547b6de96c23275af1b2","nonce":"585c5e66ed424ec12dff9aa1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"efda53830ab264279897562ff9e1454db49d775491d8e34e202a7ffa88d2322798ba0cbc14150ea58ae2553e62","nonce":"585c5e66ed424ec12dff9aa2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"c0d256cfe70e203e42618cccae8922c6c2f7ca6b8527e813c1d8ecec278a80689d55f41829582f1c060aee9183","nonce":"585c5e66ed424ec12dff9aa3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"7e9f89596bb81ad434b950956349041a9a95c1b9f98b55d2603e387ed47707508e56a5a040623a3d1ab2ed1d61","nonce":"585c5e66ed424ec12dff9abc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"e8a24f38cfe1b4c904a779a6865ef4033145ca9c133ae9af5e7d06046ac99c5f59af2736062b5c8cb3e0cbd11b","nonce":"585c5e66ed424ec12dff9abd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"d8fddc9c01c2b179cf7c88208a02ee4f63e7f04de7d3466a0b8fa086de74d14135ed5343786faa7c636ef008bd","nonce":"585c5e66ed424ec12dff9abe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"aa7257dfe74d1d56f0749721e0b315c70abc79a61ae420c27ebc87182867f17ae5a942ad18eb2893c5062b9520","nonce":"585c5e66ed424ec12dff9abf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"62958872f3d59a146910409810b94491a14bd5a538fdd5644ec9b5fcf8b5cfc8439a07ad6d6088ecc957240063","nonce":"585c5e66ed424ec12dff9ab8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"b4e7a6bb2cad3b564bb57ce545dec379eae35482c3248a7a8e9e5e0e16e9f4bc6290f6a30ab96b04f6fe13e0a2","nonce":"585c5e66ed424ec12dff9ab9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"18cf12976115ac8216d2c8912f7ceb14717b6c585b69354422308304d6f3fe6487f156df9f241cdafbe99d1185","nonce":"585c5e66ed424ec12dff9aba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"bbea50b6acfd5c7b2c39979f4f992df17e44fcd00b206ba56b339522a7e91b5c9cee90ebaec1856a1feb738e08","nonce":"585c5e66ed424ec12dff9abb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"16aa805a8db31f9023d77ec6a91acd9aa849ce822a07e16235dc9a2bf719744203af422241447cc4df44a5f209","nonce":"585c5e66ed424ec12dff9ab4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"b0c69c89e2c96c5d4dc4a8fec68836b874c36ea567f2065c7a4dddf0d95dee13429aa799965d700fcd0dd6ac25","nonce":"585c5e66ed424ec12dff9ab5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"136870752616c43e814014da48dbda7a58753e4314889f6e354b36e1be0c903672c4b96644b189529a69b61aa1","nonce":"585c5e66ed424ec12dff9ab6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"14a106840adc9bb8645fe05d37947e7af323e3b3f5ad41919dad18b7609b922cfc9934c19ca11edf6355b3040b","nonce":"585c5e66ed424ec12dff9ab7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"31cadffcba3f1b6fc1ae93a95a1962f86206f4c6759d3129fca4ff32ed6c878447d706e8798d9a676f2925661f","nonce":"585c5e66ed424ec12dff9ab0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"ce941158cbf6aad6811b9f616ea0a43d5b3698951a27b577ff9d3bf23031c10cfa78abdca6d6d34c96694dbd16","nonce":"585c5e66ed424ec12dff9ab1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"d6be493927a332de30d98ba7a3bc129e5b24a138d7f589f4707c9abafc8c00f68afca9ef42f7fbe6b5a7504328","nonce":"585c5e66ed424ec12dff9ab2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"a60f9faa3393b7c036d7d689cf8435c18741157cd34c7433336b51783ee3e094ed781a7ef978c9e8199d3202f3","nonce":"585c5e66ed424ec12dff9ab3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"9281f63af30d851cd4bc6a8ccaa310a85afaaab2bbc22e75d414428664c4116f5c8be43be656862569641df8f2","nonce":"585c5e66ed424ec12dff9a8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"d46b909e46d397c2904a54b70202371cd44bbed75e224f40b496a07c3b1f676e3f1c810bac788206d81def7ff6","nonce":"585c5e66ed424ec12dff9a8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"75e437886766d79df2456c30550f19ffdd81f3a945dbc13a8406f8e51f53ffcbf22024303555ae838d2512fa6a","nonce":"585c5e66ed424ec12dff9a8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"44c7999adfee8446549567c2954e9f8abc42633508e0bad603a27c6b6e7dd49ca27c106ad5eea44deb101db34e","nonce":"585c5e66ed424ec12dff9a8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"89e12bbaee23dcbd452cd1120b339449926a35e1e539d2c154c8c43aa7951709c9bfb88d1ba98117b48eaad0d1","nonce":"585c5e66ed424ec12dff9a88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"0a36d1cf24b1942999077bfc37f27eba3a7bc73b6620e70dfc4218816741ca2d30b237d6f56be1f0d4534a6486","nonce":"585c5e66ed424ec12dff9a89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"c81d20669c55bec2df74701fb509b32e3c159ae84226a619023164c717ac37887ee75d7b31439744e43767d4ae","nonce":"585c5e66ed424ec12dff9a8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"ec817799704b38380a936aa40ab06c87805b879d85c98c24b4a7d01e9a4626b03d427efcb0b672ec6b58d2219f","nonce":"585c5e66ed424ec12dff9a8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"dd1374160286afb6b5876545e4dd5e34912eb0a10166a7ee63c903b10c8f1260ff7f7abbb0de35172745862583","nonce":"585c5e66ed424ec12dff9a84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"e9f54e8313b759ccfc05d1aef012983eb34dbc8c3e5bff6c50df9206262c61b6498482e256d42cd0da24b9ad99","nonce":"585c5e66ed424ec12dff9a85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"f5173dbf18ef703d37cacb0f3fa06074a82cc8b48d71a5986a43e1f67e5d1bf7b0f7270ff5e470d7baed30b22f","nonce":"585c5e66ed424ec12dff9a86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"5bbe87b7d90b88c04ef19ac68048e477f5b0c9e8ec95832d3632a0c487317447f401edd9bb8891752a78100416","nonce":"585c5e66ed424ec12dff9a87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"76ac0adc7aebc7cec82378b1229f3bbc350b851de7eba5c4688fd7bb39edeeff58f9f8b9bb18fa3949a8dd1d6c","nonce":"585c5e66ed424ec12dff9a80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"95876cd383857848b8214213f1e3690930d1c929cabf8503bb2741bcbc64bfdf3b46e46e1bda27541cee1eae59","nonce":"585c5e66ed424ec12dff9a81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"afb5dcedc1ae15870449f37150fd6c32d757476f80bd90d3988586c3f12e6b4ad2f8d0eaff417e06028e1960b7","nonce":"585c5e66ed424ec12dff9a82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"9be00855bfe883ebcdcb5cc3e3714ac25f6de853b91025445281fb6534bab12f491273dedfc9e1741723095e38","nonce":"585c5e66ed424ec12dff9a83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"3a3db38993173f62ee2a5f78b33c8ef39c8660537c13ca2263e069db736c85b3d59d2919200eab83f25c659978","nonce":"585c5e66ed424ec12dff9a9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"978e4210adc8960593b829809463d89776d61dcacc33988c19ca24928be83dfa69f25fddd42bc8f5df77501c58","nonce":"585c5e66ed424ec12dff9a9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"8aab0a8397804bd46de284f853dd069403118abf2cdbd258ede930040956790d48d904b16238291cc61c7f77a3","nonce":"585c5e66ed424ec12dff9a9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"bbf20956dd6c1e2c1a0e1ab4cd96c124dc0533cf6ec214b1fbc183a42982d185d3d5ca59bdc986f5e80124bc8b","nonce":"585c5e66ed424ec12dff9a9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"b40b07a128a95f8708695719074093fed2cf997e589039d485a9cfa6939bb67d1af5b3282fe43eb27f96a0ab20","nonce":"585c5e66ed424ec12dff9a98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"24714b8af2a314f2eefd00067f0f7754b22deca38f2090e511af8d015d3c2fb6a87b3ef9e3a17655462c1352aa","nonce":"585c5e66ed424ec12dff9a99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"cdb8e662963f84645800fe94a34f8bd35387196e6c248cedd015d201ff1b15914dd9ac25b784ca4afec28bfeb6","nonce":"585c5e66ed424ec12dff9a9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"54624b6cb45dba4ec717f71400d2b5f19c331678f23cc14eb330c1099c100f84dd1b8bd739fb2f47a22e1be054","nonce":"585c5e66ed424ec12dff9a9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"257b0670ea833ac3b14908834c007efe72fdd41b87be511dcc2884765cdb0e0061305f98b451f330953577a4f8","nonce":"585c5e66ed424ec12dff9a94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"7d8824b99028cacbe50432351565527c382d70f5b1b39097c873a4a55a3473d73a8bc95eaa3b4273c00a53cdea","nonce":"585c5e66ed424ec12dff9a95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"388ec322e4aa59d53e25b5143b9ebef6ae5ef16de9d4bc58700ec1d277e968189d9c69874bb1db0df82f6e45a9","nonce":"585c5e66ed424ec12dff9a96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"902a9f5327720ce253a5fd39fa0c254ea43c5832eb6373664b9cba13dcb89292c6715c9fbb3780e9dc4bd94ab8","nonce":"585c5e66ed424ec12dff9a97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"b77ca64505efb4e8d6c011cc5d3b758f55a45db3fc0fdeac7138eff7eebf3d132c49fe0a33f1970e646112f67d","nonce":"585c5e66ed424ec12dff9a90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"9fe3bdfb11751379047a3975ecc844f2e1eaf49ba7c23392094ce29bf34192a0538ccb32ace09f4716b1fe927e","nonce":"585c5e66ed424ec12dff9a91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"eea2559f4df068af65b4051e2d1e5624405315ab92540e6fd1f18a6c83179f0acf95a000ffa2a8eb9e2b496215","nonce":"585c5e66ed424ec12dff9a92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"1272759583afb014dfd87f27f07851af3041d2b2675a130596bbd79452a66072d38442fd42ead1bb8afb2e4d12","nonce":"585c5e66ed424ec12dff9a93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"1bd6b51ac9c4c355a3219268a79d272a356f8429ffe82d73693609a1b1d2698f00efb54eb180d90356783291ef","nonce":"585c5e66ed424ec12dff9aec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"10a7b2e5cb0a559269533035d4f75151e24e984ffedba9698946ee12b8a047aac9ff6584f9f7b6193a428d437d","nonce":"585c5e66ed424ec12dff9aed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"dbf90dabddc0110df2a67226ef41aaf4e367d51a772d8e759936dbd03e91f15198e1fe1d707ff3a5c24385e579","nonce":"585c5e66ed424ec12dff9aee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"151f6747346762c1d7cea3ceb11d1c040d6c465c73e65979d377ff7aab947725b5099ee582499a4187d533f57d","nonce":"585c5e66ed424ec12dff9aef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"1f43ecdf325319a717ff2e0de0b1cf0e1255eed52f22ef93c0eb9b15d117fc2e94aa64891ba81df831aff8b7ca","nonce":"585c5e66ed424ec12dff9ae8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"677e9635d0168332de7071ba88cbde49077f1c2a711ca0b012573c2e8b16b24d58f6ad7ef18258e039596f6c49","nonce":"585c5e66ed424ec12dff9ae9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"9828b93c86b669259aae5fd4e1f528e1aa2f248f16b25f9ae6efa5bd5617ebafa5f7735a3cf30e8c28a9fa7f20","nonce":"585c5e66ed424ec12dff9aea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"049a05f11bb7f616fc214f0cdfc2ac6d63093b172500c0a3668787b1bcefc78c839288d8cf26b270f5f5d6ee59","nonce":"585c5e66ed424ec12dff9aeb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"e6a516788a9f8a11df35469876c43d19df0825f5a7c901d826ae63a5423c49a7582d517b5aaeb9c3b75187a074","nonce":"585c5e66ed424ec12dff9ae4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"ca2005e889c141db0ad51d9c08a1ff57413d3452b4ea18916fac780d630dea65c3e8d9607b246d0fd3081ae982","nonce":"585c5e66ed424ec12dff9ae5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"9947a8c761cabd8d3b6ba8ecf4d0c2ba25eaf41f694ba3ae225719621dd84090f0e29e402c8013e51f4dafae4b","nonce":"585c5e66ed424ec12dff9ae6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"d0514dcc90790cb5ec45d3144dc977fa3a3a7b218d77e67b7338e32bfb638ca6bcd2cbb0c93dca5aefa4505395","nonce":"585c5e66ed424ec12dff9ae7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"25867a69557e46b6e2f64f3a908d323589ae817d1e75855575faebd4473888f386391e709b09275bea28938702","nonce":"585c5e66ed424ec12dff9ae0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"cc014e1b5a68d8a9777185066cb4e1717f7dd653f73242e0842f0c9e639a2473e55de14b9c8e6936958ad40056","nonce":"585c5e66ed424ec12dff9ae1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"61da419a804595b8b3fc22e93517ff1899cec1240fecbf4dff589573da04b3356b7ee33b99d4ca43d12d233bcf","nonce":"585c5e66ed424ec12dff9ae2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"60ac607b1d0e30dea744db87ec792aefa026afd54d742ee6c0455c0d24ba4f67d927c9cb9a8b83958c21f315dc","nonce":"585c5e66ed424ec12dff9ae3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"4d2d68d7b94069205d53aff2ef84c63e12694c56aed865417590c3c90d3492e92a6ed497248320c7cdadf0f07e","nonce":"585c5e66ed424ec12dff9afc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"3f964bac3e08896f004636e6ea97efebe6b232298797a3f3930165905b59f94ccbfe7406b9fa3d13873a68ecb5","nonce":"585c5e66ed424ec12dff9afd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"29c16aca09a062a3985546f0f07d16956a8ab16845558ba78e22cf0eea598db7256fee171c493fe0132663b05e","nonce":"585c5e66ed424ec12dff9afe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"8f223f09b2a0eefcd4b89a1ef6b93d082e88489e8f4ff2b45ab8416dc8ddf079af3a5365e9d118e6a0b36a0a58","nonce":"585c5e66ed424ec12dff9aff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"e070bc1f4a1c8d35e29d7f2d816fdd73ed6105dd3c6963544d527642e4b0a58313702d969bbac082a46e1a1dce","nonce":"585c5e66ed424ec12dff9af8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"e92432aac48b177b0a9b4927ef38369a05f892f81cb05f4c5b6cbb46b83d76bcee1ad70d55096caf5891eecac5","nonce":"585c5e66ed424ec12dff9af9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"a9418605f5b7b57e8622416772a48927b28a5d9fcadf9f0eb35443cace3f004cd2b2aad8c132952f6adaf3a69c","nonce":"585c5e66ed424ec12dff9afa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"357d78a3d878121e22969911b52d703f599afd35a5480b83896700b8d804520fbcb22cdf9607fca457ed8d4173","nonce":"585c5e66ed424ec12dff9afb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"2c52c17ef651452744e320a700c6369b10d2f42d7e820dc0c5c915691c275876233f68c82035e98c94a11900a9","nonce":"585c5e66ed424ec12dff9af4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"c47da0a85eb960b84895f6faf458f233dcdb5e619cb5bedec78d21fb4700bc9b37c272528326a358f3930e2472","nonce":"585c5e66ed424ec12dff9af5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"a6cf2c6926dc772bdad2801bf748bd64da33aad576414b7a78e95306af3811094de67e04ec12ee991b282c96b4","nonce":"585c5e66ed424ec12dff9af6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"db8bb8b68be3449086b4c7bcd1f20b2ca6673e48256077e71bae9839527c1c8cc9c7ba47264390006f8392c008","nonce":"585c5e66ed424ec12dff9af7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"ce8e3ed26caf5c25c24548161997c673db5fddd0249078e80c393ecd69938c97360a77dce4d75b2be066f2d009","nonce":"585c5e66ed424ec12dff9af0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"cd52a1d177970053ac1f610ca79c08dfb094b723ffc447445624c766341a303936cb09eae2df47999bab48bef7","nonce":"585c5e66ed424ec12dff9af1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"06709df2d280887d3fc06538d99a139955463f141720944444349c9c38ccac5c8ff3590004d925925eed81971a","nonce":"585c5e66ed424ec12dff9af2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"f6bb6dd774bd49193c016e1cf37374e3acf3dc95de5addfea7776c818aa3790170d086636e2484781e9560bde1","nonce":"585c5e66ed424ec12dff9af3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"12bde9de7d9d286b076c93c1323a65738d700dc6cc340c621e5123d4ed45f3d15fce8256fb6e0d8d49234422cc","nonce":"585c5e66ed424ec12dff9acc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"a9affaae15d84d4e91d95752f8b49d2f82ea15201c7e51c6bde9f482e62e06da86ca18ae2408bb494ca545c42c","nonce":"585c5e66ed424ec12dff9acd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"a41a6828f1b4df16c5d59807dbfc5f16400b1ddf89350542784437e61837cade0f7196c04a7751264bb562a5f0","nonce":"585c5e66ed424ec12dff9ace","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"1fb775661d31e8295e54de0531dcf306c51500f4a7101299b3963e4ffd952e5e6320cf97ec2fc5cfbd5a0b7fbf","nonce":"585c5e66ed424ec12dff9acf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"89089ca22a6a2e43544a07ac5d334b3d374edecf3b2d2c198e4f678cf3664819d51822fe369d63cf25571231b6","nonce":"585c5e66ed424ec12dff9ac8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"05ca4bf89ab936033202043e51b319337ab3683c9d89c4b05e8df5b15c1e0936bac7c75c1fe884b1b312617876","nonce":"585c5e66ed424ec12dff9ac9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"1e6930a55f58d83b054ebdf7c79afe50824da846d8b30e731a80503a507653a9816075dd218abf6cef07a82ad4","nonce":"585c5e66ed424ec12dff9aca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"efa0625e93d4b87996f8e955701ca5cc49e6abed4bfb2498c055ed3ff4a88cc07b40c19828ddeb89e3e1e30571","nonce":"585c5e66ed424ec12dff9acb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"3f6fecc064059a7b8aeb288550d6c23e1c4d431cc6d7cd13162d14a9663244d360cdd003d2a05b349c7d8b3b35","nonce":"585c5e66ed424ec12dff9ac4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"bc1325149b2272d58c2c8307a82710977af48b9759e10b43bb497cad0bab1f02639cae9c610879123ec0153652","nonce":"585c5e66ed424ec12dff9ac5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"7c61d7a0750246b5bab0770885771d1b18ca57d72bd8668ef9b6d2dd8056ceb44ab61a957a409e3ef165a6ed6b","nonce":"585c5e66ed424ec12dff9ac6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"6f0f4965ebc00cc7f380459c2ad67b3503e5fdabcbc0d6ba2f0189348b16e7b2c69304e11124dabd86d2f9d815","nonce":"585c5e66ed424ec12dff9ac7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"46cec3adaefc191613e848c54234d6d8ce6ed6c1ae2877a6b038eeaf7fb2524b082570557baf050344d3acd18e","nonce":"585c5e66ed424ec12dff9ac0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"59cf540b76d3acc059d92de19b2bc9bdbf5c69fb3790dcd4c4209be739f06f75cc9fbad1ba526bbbefc16bb439","nonce":"585c5e66ed424ec12dff9ac1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"4831b4c34c39557ce5826b45205439ab3c6701f344d975f1c5da43751c751ac0e856083daeaf1b57a361fb22df","nonce":"585c5e66ed424ec12dff9ac2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"5809d1d4424a7ad4b55f071aeb4298efda758c66f1b5d73e0faac23cb411c1615c4077429a215336a2369edc62","nonce":"585c5e66ed424ec12dff9ac3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"0dad08198f9acf19b8f11421febe08fa1f024123f18f8ab243d6e314dab09e9d5d95a38c1ff6ce9aeed95045c1","nonce":"585c5e66ed424ec12dff9adc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"ac080ee936d3029920c669ce4120a69506139f6b4b420561f526ce2460d5d913383df710f7bb04c22d16c3f3b0","nonce":"585c5e66ed424ec12dff9add","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"aa12bd4e76a7ea43a8d6e42936351dba3fea4356a999ddd4fe021bf8f659caf7e2b12879c1889c1afa3b70b3bc","nonce":"585c5e66ed424ec12dff9ade","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"beff67259ad2ac6fa81b7b644b09ecbb1d144db1d7d75cdacc700c3b9606ce565f35f1f4e702df28eba02351d5","nonce":"585c5e66ed424ec12dff9adf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"d4d54ab22c477edf2a64dd772914c0921db495774350971ad16b87d60b6430c2718068fb34ee4c2b3c2a06db13","nonce":"585c5e66ed424ec12dff9ad8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"6cbfa05ea2422cea1fe3aa95ca3dd00da0f63d89614f47bbb2ca471097e6572e0cf48bdc21410fb981fe0324dc","nonce":"585c5e66ed424ec12dff9ad9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"c76573bab5097eeb5fbdb2cf4d396c9c924cdcc0ceee2960dbf0eda2957d1e78a4f75de44926399b0a8cdbf207","nonce":"585c5e66ed424ec12dff9ada","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"e691f9a1c4176a9c0109dd133b1136ed1bd2f7aaaf156cb6cd28a83169ff6ffc44de8d4a8832409667433ec1fa","nonce":"585c5e66ed424ec12dff9adb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"80b8edcacebbb3e4fb9ee32eb3f137a9f9ed3c13d6467045c9a809549928b9c574a34f4e58b0dc33c81d72f508","nonce":"585c5e66ed424ec12dff9ad4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"f932788a2107f0efd7d4cdcc90a16cfcec301328b3e232385e99c827fdaad3e1a9fee81b50fad79fd68ccb1dd8","nonce":"585c5e66ed424ec12dff9ad5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"0ab4f6108908cd7aa536d51782bb8a7019016ce75344ce087d12e2318039a69a2f8cc363e568e452859b07d0bf","nonce":"585c5e66ed424ec12dff9ad6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"0bc05c26c3c5c951f086ee4923156bc12f811c3d90537f7e82dfdfbff439c67fe6d0e2ed9efafb1c8d101c35a4","nonce":"585c5e66ed424ec12dff9ad7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"3bc1f9ee697c2800c6267d595704c0e22b00d4cd304a62aed09cf939774468f4659eef378888c90758bbd901b1","nonce":"585c5e66ed424ec12dff9ad0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"ede7b1685c572bd79dc077895131a2c188dafa343aa9ad2b52fc0c6c702a280bf0634dc679919a3ac0224b99d4","nonce":"585c5e66ed424ec12dff9ad1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"f6269b2c974b2acdd7c6249d2f3548fd1b423c8d95b66d91cff522e809c9f607b982b1b36b69beea3db7fafb5b","nonce":"585c5e66ed424ec12dff9ad2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"c824afecaeb576638ebb752b7318cf4f677fd2b6919443b2dc45a8c4ad65a151323592d7342888c396c8ce0cca","nonce":"585c5e66ed424ec12dff9ad3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"418146e08d67259e01c9363664d4cb826b482e6cf815e3c14bb9548dc96806d4d145b649b0c0e17a9820cc5a88","nonce":"585c5e66ed424ec12dff9a2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"781e99c94180923ae21d1cc5932e8c017566ed10e979cd0e4d93cfb019af70c71a92ac45392b01edfc8b8c0acf","nonce":"585c5e66ed424ec12dff9a2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"4e0a3633a2fba5bebb975e256a18d5f983c8f7761feaaabce6dcc6f415541681710f3fb1028d04759c723dd1f1","nonce":"585c5e66ed424ec12dff9a2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"22ea51a864b2fc738fc3b488fe828702b520007fb09618b60a5aab5e29862c05b3fa6e08f8f1fe13faabba492e","nonce":"585c5e66ed424ec12dff9a2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"12cb6799627c0fb1c5f636ee2c71c20f85c7bd4c7697f97e4c178573ff459a7531b3ca5ecc9e4f84b862f3b4c3","nonce":"585c5e66ed424ec12dff9a28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"a95299d0aa288d12be647df78d45f4d7c2a83f73a7e960582eb726fd25de22dc636add27264af9b27fa351e7d4","nonce":"585c5e66ed424ec12dff9a29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"52bdb7ecb185a971f4a68f8480199751214a0b51078de20b0b38dd65d22a308adca246c7d4f631dee62d39a744","nonce":"585c5e66ed424ec12dff9a2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"1c5d648106a7a300cffe0f4c8872f42ee752e42b9c078d467b354dac3a30ee88a1314e88633cb866585a41a8b2","nonce":"585c5e66ed424ec12dff9a2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"45a29813512ead5619ad82867a6ff8ccff18d1a4b1bd55e21ba8bac3c25485e384e5b88f88b2044ae5e1383aa4","nonce":"585c5e66ed424ec12dff9a24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"3769502a88e7f068fd120bd77440106f1df1494c8a8103b94eff95c94913ac983833263276189678b0288eecdb","nonce":"585c5e66ed424ec12dff9a25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"c19eb13c637ce508301b5638b961f87e89f6f4ab625f5e3be68cd494c47f2762b34987fe2e98657247271fd630","nonce":"585c5e66ed424ec12dff9a26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"2b9f013c93ec2240aad0187d99601a91a95c409e6dca9caa89316769e48658321ba401168d4f505c859d47255a","nonce":"585c5e66ed424ec12dff9a27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"b561cffa57dcb1a5a8d072b84a5d0432bc6fbf7d50fd458adb42cb7c0bd7e7e0bc1538ed943585d8f5472f50cf","nonce":"585c5e66ed424ec12dff9a20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"52d1172b0b2db0eff4fc99a48acf51e2a362fe7d06ef8941e8a336c3b711ccde6ca0fb494b24366da2a1742d94","nonce":"585c5e66ed424ec12dff9a21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"2705c90cd8d319d483c54f03dd5c6b46516dd85b58089397ccd0595fe764e025e5ec0f4ef43d2426ef9fae3b6f","nonce":"585c5e66ed424ec12dff9a22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"e38cbce23c02f5f722b16ed3fcd2c0a9e55c4e87742ab39a5d2f8352c3ab2a201bdaf6e05655ddad838240945a","nonce":"585c5e66ed424ec12dff9a23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"2a0103d768c517cbbd327f3320d8235d52cc5bf26b4765c1df30032de96948ab1e85de9f2f81b2b11a09156249","nonce":"585c5e66ed424ec12dff9a3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"6882ad0ba1878a2eea36f69f36cd34b4e8454093472fdd44f88511c70a77f8ca524559643191c65681e6be7451","nonce":"585c5e66ed424ec12dff9a3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"1f58a2f59ad0afc36240df9c929d8abcc6227afe3a7bba9aef9936e55f7bbdf0cb2e339bbe9909e8f70a3a23a4","nonce":"585c5e66ed424ec12dff9a3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"7a67db6a577e8ab7bd7ad7cdb04e053baa513a3784a940ddd98da424da199a2c120e2e5e61af70f9788aca08cf","nonce":"585c5e66ed424ec12dff9a3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"b90247bd2c16829a5663c15051d6cb07aade67a840e37c63dffedf70de0fa76bb87fce0f3b3cf848ce4ddbc97e","nonce":"585c5e66ed424ec12dff9a38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"7965f3083efd4a4128fc8c0368e2f6bd47afbc94f1eb523778a1ae2cc293fd6464a1bdf8c6b3d88ef70e313487","nonce":"585c5e66ed424ec12dff9a39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"e47ac0afa3f7ee61b5f12f730a6ac3882cf899361985fe6583eda323cc6f04f00a96dd236abeea5a8cd75cb22f","nonce":"585c5e66ed424ec12dff9a3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"3b6793e9bd8ecfd20896710106412ea3cb0780fe66731689485106664c13949792812e1b32d69aed575e6681fc","nonce":"585c5e66ed424ec12dff9a3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"dc91d95599b96ee16aad075aae41ab526aeb1473c8fbaae41a79ce88ef8ab35fa28722069d01096beca4f50744","nonce":"585c5e66ed424ec12dff9a34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"61c7f624a59873bad035faa6af15b72a1e61efc1f1dfed657a77ab21f561778c7c78d704729995221f71bfdae7","nonce":"585c5e66ed424ec12dff9a35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"dba7550aef013d965b553c9f1ea61ab21bed1d2bec80e6808da48cf8c10f3af6807dc1a0b80a90a4c14af41b74","nonce":"585c5e66ed424ec12dff9a36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"68352c74146d93f345fa0c8149acc245df934216b5df380dae242d907c3e8eb4f2f62adeb05691455b25164352","nonce":"585c5e66ed424ec12dff9a37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"c82c845e6dca57f9d6a7ea8454567cb16708704e513054e0a6ad58983c171a24eb7f3835078ca5d07e7698f8a9","nonce":"585c5e66ed424ec12dff9a30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"9ddd3b0704f06c58f1807d76aaed05881273dc877662e9a26a1ddcd07f792f0e84d3e41db169dd68d5dabd6040","nonce":"585c5e66ed424ec12dff9a31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"e49a92b819ca57cf951c680c7c94af04e71ccf2f6e610e1ce6228cbd010fd53dc044499b92dc461930d0e91f54","nonce":"585c5e66ed424ec12dff9a32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"37557f32681f61ec5c8247976bf563c7c83d358434e32d6e1944b1b6fbb277a687cb00fc6fed258c5594713f83","nonce":"585c5e66ed424ec12dff9a33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"298aa279c42b51312e1b0a67fab3fd27d9cdbbea0b31893d5fc3aab934d91306a5e6177e1d400c8ea9e5d4206b","nonce":"585c5e66ed424ec12dff9a0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"92ad757d9bb390258687fb8dc6e1673352ebcdc78368d480b057fcb1bbc55be30f8f822643232938e8270361bb","nonce":"585c5e66ed424ec12dff9a0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"dd512dc08bc113225bc022e12d1b0ed4249b90564bd2163ec1ab7d1c2f4a20c4ca9d100c0e7ce081ea7411e8b1","nonce":"585c5e66ed424ec12dff9a0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"abe8c37e4418d09adcbc4bb994a4fdb74e84950e4505caac50daf8a2b4e287083b1ce37327c2737dcb19b20a80","nonce":"585c5e66ed424ec12dff9a0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"0d27b76c02669d680c89aa2e26c74a7601305036c812c5346ded491da02622f3ac982c48bac463032a7f51d319","nonce":"585c5e66ed424ec12dff9a08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"e4e26cff30669ec640ccdc20af9a650399843260b58b976550fcc82dd42f9dbebfdc2a43a00ac61df362d7e7da","nonce":"585c5e66ed424ec12dff9a09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"0e7ef1b1fe151f09fdadda0051fe2e1ec11344d9017d3a0434cb7f0045e34a456c2fddb614c064f79b110b2866","nonce":"585c5e66ed424ec12dff9a0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"182868b1c6d86e9b493b09f23dc75b3aaf30f0fdcdfbc9d29cc25ccabc4e6b4c0aafe45ff7efffa47efa9a4b46","nonce":"585c5e66ed424ec12dff9a0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"19ee8c93b238ece20e17a5b1046982fb71c217ae482a0507999a06bc81f206af9e01c599bd5aa3b61e9bab1c3d","nonce":"585c5e66ed424ec12dff9a04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"bb51a288ddef14d2dac0ec4c7cd17087f94281158658eb2dbb80d66b589a1dcd4bf3b88091e0387a5336503da4","nonce":"585c5e66ed424ec12dff9a05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"dc49f098964498da513cfb2b03fef49e7f34bc0fd56e603fff4d2927f8369b4283c1781aba52f64bdddee159df","nonce":"585c5e66ed424ec12dff9a06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"efee199c2b2f9c6af4e033c12a1410147a92748d1e2088b02f75b0d688bc69ac0179e277afb1b67b77090b77bb","nonce":"585c5e66ed424ec12dff9a07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"46c71636ac43eef5e264f56ca94b458a49689eec2dc4b5dce4178fd83733777861beee5ea52cea01afbfa54dc7","nonce":"585c5e66ed424ec12dff9a00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"cd682b0d8e4a3b7093adb63510c5a9953760297f405a1555d082ad6b2770b34ba6ffec2085b7bb94d296877cd2","nonce":"585c5e66ed424ec12dff9a01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"6a773b741e1cc409ef485e108161fd5cd735d119cef3fc894c3493f9341d3baa97f98403ee209d81b5d94bab96","nonce":"585c5e66ed424ec12dff9a02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"8e592f7910818d04c7c196faf3521340c7201d9b895a00d5214ae86b612dd9b4b253a3520ad266f2d224e2a720","nonce":"585c5e66ed424ec12dff9a03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"c1789eb2b3a0c6b78459491a7741577b3c103a66511e51279c0cc4f1f1ec8fe31e138e62b2cbcbd42ac746c867","nonce":"585c5e66ed424ec12dff9a1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"88ad4cd411f9826f8f0b35f31f81f1f8c548ef1c309a452fda4fc91f6d6e083ce545a4a5229d1e2d917027822a","nonce":"585c5e66ed424ec12dff9a1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"b3e55e4bd190dbe5d0b85faca8f0a49c3f551b0ee2928336dd8c489090bff36a22e5e9c57ccd1d18f5b8a1b1a8","nonce":"585c5e66ed424ec12dff9a1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"d0b23ef3b185a4ff1c9be7b26a4bcfcdd9a72d40ee94c1101868eafb8ef71a33e1a3ae4c3735a0ecf2e5e6dada","nonce":"585c5e66ed424ec12dff9a1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"a294e8e57cc0c958f68a5e7da24bc095972329f2cde2f32f0c09fc24ecb43c47a3e59fcd864d543702ce321a9d","nonce":"585c5e66ed424ec12dff9a18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"54d38e12409e5fe17275825024cf6f0a1748710b79d69d884ccfda0050c8b1986bd9563b21eab2689c3439d30a","nonce":"585c5e66ed424ec12dff9a19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"33591cf34b4fbaaf2730fbab349ceee5708394c6bbcef2820f05e38f015c9b180a88d039e3a042ac1d9d17e914","nonce":"585c5e66ed424ec12dff9a1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"10040432f6db59fd84e6c9c36997624a586740770016489a17ee3948c12f4967f48a6da16b437e1cfd3f022e7c","nonce":"585c5e66ed424ec12dff9a1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"a6bf154288105c942fbba3e407a1639665326fa581f46a8d2a336359cd9f7847ca839bdb88d15d2945879fc144","nonce":"585c5e66ed424ec12dff9a14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"5435444f8a5f3003e7d1ee5a3ac4b6626ba0087e79e304bd9769c81fbfb58efacaa5e33b336fc4839bde521580","nonce":"585c5e66ed424ec12dff9a15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"0e96f28580d3b5158252f4386ce444afe7b36012e1cd07c24e152052a8da100b5a78f06b7d585ca9dc1306594e","nonce":"585c5e66ed424ec12dff9a16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"77c46dbb3a2ae55d60b7d1fc8da4caec6ef311b71df693dfe8aadb8c974b6681c86babc6dda0e4ae0bd82aa432","nonce":"585c5e66ed424ec12dff9a17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"f6d6e3f08c482957793a8105b82212a86fbcd793f2b84c2b98d789bcd3dc35329eecf2de1cc994da10f2c9c47f","nonce":"585c5e66ed424ec12dff9a10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"0d875a8cada0a338044b145806a71229e17f484f130d73d8656136584a150b8011e0335154411813854eaa3c3d","nonce":"585c5e66ed424ec12dff9a11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"b62a051db67e0bd8774e50e2776d563f3588ab110918a90f1a8ca00e2e08e3a6290f19f7eff2be091e1d523365","nonce":"585c5e66ed424ec12dff9a12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"bdc66dc36c55883fdc5fc38ff0ee684325d5798a9ba4f2cf8ebf33e4d97ee6e448070756a400ef4ac4e2b042e8","nonce":"585c5e66ed424ec12dff9a13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"82ad16f7ec277b22552b0e3d935be42aaadfe8b045242b277f3b744367d6ff710c3264b9accec78cca8056da32","nonce":"585c5e66ed424ec12dff9a6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"444f36596b4cdfacbd9e60c6c8be704437d9c386284e7f0dfbfe282d50b91a821f76d8ad4572ab9a22b1a0a8ee","nonce":"585c5e66ed424ec12dff9a6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"13c98cee0b29959e2344c34eac8224fca940ff6703a35b7d7a0ccb8942bb0f3b9468a0ca76f1c6a9c936ad1ff9","nonce":"585c5e66ed424ec12dff9a6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"3249fa2c9d5d31aa65de586584977944f3654d652c7b65f91c9d742b5d2ec963a8d54fbd7a5afaaa796d26c84c","nonce":"585c5e66ed424ec12dff9a6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"5f4f89bc3fbc165509619b7b2d63a74c7f1dd6912a3d1ebd4c95a577103f636a3ad093d308978984310b105782","nonce":"585c5e66ed424ec12dff9a68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"2a3394a3c7ebd6468bcb37e279ae16181cd7a2f44f74999a8e5de3fc5e73766babc1eb0bb6f4afd60e29b24480","nonce":"585c5e66ed424ec12dff9a69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"e5d5cc9c51b19856b6ace7b5d203fad91e0751264401dc487dfb70ffb3f590b902b2dc12a515349da3f3b0a948","nonce":"585c5e66ed424ec12dff9a6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"4b5c5a4e170a397584ad410c70a0e795341f1dd3764ca84456d844994ac4ada426650f2a5e62cd2fea5d03aa86","nonce":"585c5e66ed424ec12dff9a6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"74a7301a2d0f86833b005cf6a9361f13686f7588d9e8c523b6a93f61e5eaca838fd158145899c07257d5aa7e3d","nonce":"585c5e66ed424ec12dff9a64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"5d47bfde559dcde2045133ddbfb455f4783bfe7ba4e66ac136361a2c3b0eccbfb44a88f1940c81b583e53ae3aa","nonce":"585c5e66ed424ec12dff9a65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"fbff2fbf6a8fc773749f8481e96960a1bfdaa5859d0f1be7333e3900402e6cab24b6ea42485c2376132189e88f","nonce":"585c5e66ed424ec12dff9a66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"15d58a92eb9cec64d475f4d1b77cc2c40fed7088f31b6d28f0a64726bad6ea46f05494d894eae33482c2680543","nonce":"585c5e66ed424ec12dff9a67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"d31e3f26adbce17f0fe5efd571f447a37b6459ee6667a3b62b1666dc01e7153a2e7189d57edab11189ad6b2751","nonce":"585c5e66ed424ec12dff9a60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"94d0a01761985e28f377fd287ceb60d0f0d848774a48a91f1c4fa82bab017de8f78d2f14db5b55f8b446ccec75","nonce":"585c5e66ed424ec12dff9a61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"3551cb49afc6a517de2fcc264985644f6e93df139553a1e30d1478864bc784ec5e115a557653cf1f42d38d446c","nonce":"585c5e66ed424ec12dff9a62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"1969ca3068bff329149e7b74a98cb6c3a9eb6bc942c7295c79cf2ce3b8d7a28a6f64c29cad6e4f611f0d545fba","nonce":"585c5e66ed424ec12dff9a63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"fb75c95cf06bbd2f56823ee673473fbaa386e2373a0ffcf9d59cc8b6b1a26a26a809c2027ba3220194c7f19fec","nonce":"585c5e66ed424ec12dff9a7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"b5868362e447458c85ff791ac9e1d1a3d14cd67556e1124dcd58655a244f937da2a2d4418e93e4a4d6af6cb223","nonce":"585c5e66ed424ec12dff9a7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"d8f0898075c6c0eb3ac3da819f0e44c1341a0e115afbee2f895bcdee5c60903aec9265f416def707fe516a0f60","nonce":"585c5e66ed424ec12dff9a7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"bc6c3e9a1705265a12df941cad5de70707d192bae4d34951a109d4732e694962e871d2ebb810bddeb882bdf903","nonce":"585c5e66ed424ec12dff9a7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"e5231ca887cf4ff1e38299abda04108bf58c5a93ca9f72997aca6c03db93c33ba86aab63252f8d90c491136d5b","nonce":"585c5e66ed424ec12dff9a78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"2dcca5343fbd70ac2249200bf61c2290b613af5032bd8432de253fb6c40b0e7f4f9ca2a9a2d91e168d09921e11","nonce":"585c5e66ed424ec12dff9a79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"14374a7b3df6a4e8da74e521a316463c455e104940d3ecf259888e9323152fd0db973b1e230cde0f8efca29a61","nonce":"585c5e66ed424ec12dff9a7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"56854d7e6922b60ce9511ddfa6b8294437f58962f49764cfd2d829cc4f5afcddceb41ed34ca39892d2e183613c","nonce":"585c5e66ed424ec12dff9a7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"f7b743c326999b2b2433975989f0470a5015f760596b28d13acdeef82b2b8cd0c807c9d3f7d90e802858f5d51a","nonce":"585c5e66ed424ec12dff9a74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"3b382f6fadaed5508b1b857d5ddb8b67883a79dbab68957d081e2274913692b4b0a4d2ce5c6b0cbbab17bec936","nonce":"585c5e66ed424ec12dff9a75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"6279473d9af93676ef63c6ac00fb0c325e22bb0b4765f04c59ad34a9adf46cb71ef7a0490c06e8abebfffe29b9","nonce":"585c5e66ed424ec12dff9a76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"45e65f0685e9d17ffd7737e6d4248106ec58f3e3d402e69a22d7cfe9fb3a81e5d5d8509311200c0df28f94c08f","nonce":"585c5e66ed424ec12dff9a77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"2ab8218e9af8d5002ff459f13ee7830c524937bc6ffb65b930b225463788bf8804e5ddafd81b31a779b44f270e","nonce":"585c5e66ed424ec12dff9a70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"44b81125a622f503e0b0dd863cd558cb5744e62836dbf98f366d52a61cde2a43de7ad7e78c0d7f2a3837970b44","nonce":"585c5e66ed424ec12dff9a71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"8f45a7d3e93618a5d047d34277f273f13cab88b308fb1636ae43ee900c1a9cacfe390428461021ad0343c29bef","nonce":"585c5e66ed424ec12dff9a72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"eaf4c1b7c83e0c8439dda90f9b3590b901dfafffcd42f63391392587955be976dd28e35a5a2afb48d8a266a944","nonce":"585c5e66ed424ec12dff9a73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"4f9130c61ef8414a24209a1edec32c985e36b3a0122b540ecae313c58e17acc6afe084341621cfb1276837326c","nonce":"585c5e66ed424ec12dff9a4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"35154e686d9942593c5ab3aa8fecadfc315910a955d742b853de11d202b75873c949de89a0070497a8e2019bf8","nonce":"585c5e66ed424ec12dff9a4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"5c62f129c6c47556058028370b52ccc7471fce0f0440c5dbb1b68ae8098e98f08189a05d3a9b7ef212498435fb","nonce":"585c5e66ed424ec12dff9a4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"93b36eda69fbc08db8514f01c1c8d236f08076db4e7c8e23734b08ee75d4cfc802342433a6e4c426921c499d1a","nonce":"585c5e66ed424ec12dff9a4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"17528bc172515298200781c02e8c9143aa36eac66e384468d509ff5c33954052af2b42c27416fbe2ca32889fc6","nonce":"585c5e66ed424ec12dff9a48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"71ee590d3359b76d4ac8148591d33aa505b5a39192390e8d490685787a4e8fc8098c4f6f83c617199f34174223","nonce":"585c5e66ed424ec12dff9a49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"62df3e6b8466cebcce5ad50c210b85dd4baed720a5af4d92bd2d741b50c7841fb4645a8634506147845e021a76","nonce":"585c5e66ed424ec12dff9a4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"8842e2248eee0b63f61ffa6215231d5adf41c620ede4eaa8d788946133683bb343cc225c5890b8a6de05639d29","nonce":"585c5e66ed424ec12dff9a4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"6dfe0414abdefb3aa1100560b071d6d0de0ca739c9fdadf617c9a1e988834d8b5d7a64402e0625666e2c030751","nonce":"585c5e66ed424ec12dff9a44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"624b1d3bcb3b93be860b5b06a2559497e732f3864236f6f7347afb9c819166d53a8e2f2db96e44fcba33d8a2f0","nonce":"585c5e66ed424ec12dff9a45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"84f8db173a72c7140725ad57971682f34d91de335a92c56e1e44a1d7e11c1a3faab09bd354c50002230a341309","nonce":"585c5e66ed424ec12dff9a46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"1977ceb671b94ee5aaf59b7daf6e751219b9b23539ca8325286f33917f17c4ffe47cdbc299816d47de38eb96e3","nonce":"585c5e66ed424ec12dff9a47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"474c5e4a63931ae681652188219b7ac9c42ccb3e2a7c27375829560a725e2173f2f56befae42cbea51a93ca00a","nonce":"585c5e66ed424ec12dff9a40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"bad1b5105c7232a93b053110eb8bbc20ac8a77b04a0ea10e3c95857e697ce51120a84fde18e287a8a067cf4806","nonce":"585c5e66ed424ec12dff9a41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"695974f3527414744b9be8b5e42b3b521bb162ec31444bf37916440af49491de5f4f1dbf1355c2f8609cc9ead1","nonce":"585c5e66ed424ec12dff9a42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"15c684fcd56b86bf77c79930e42c297905d191f1f22b062f8464f72f845bab5f6e3726952dcb91ffe964f14038","nonce":"585c5e66ed424ec12dff9a43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"ba85b884617f4d3723136a857dccf12af0f8da8fdd1a8c1a629c63f6eb3463352508a895953eae826a0eb2d275","nonce":"585c5e66ed424ec12dff9a5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"ad8a6698a3bdfc4cb23ec88ee052e20fab76ada65e988c66621ec4f60fd1675a134f540dc861a314fab05b7090","nonce":"585c5e66ed424ec12dff9a5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"101ff6603390ce457c364495fc502f0d8fd01f4dfd87975491a9a3206d84c429e7c5f1c9c3dc2df0aff88fa9c8","nonce":"585c5e66ed424ec12dff9a5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"3c5d2e79ec2768c7a0fe6fb01a0b692a195299501bb319aeaf6897a35bc759b004a2a956d6a7074c71977d9198","nonce":"585c5e66ed424ec12dff9a5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"54e344895aad4d02d39124e8939b97aa6936b17a468e6ad39bbdb672187701d8cf97ecb2e286867cd67e1e1d18","nonce":"585c5e66ed424ec12dff9a58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"4fb3927afb089a5ecbb28f64dd5776ecb56f77a4e1d26ec2b41c522728a6c222a6c53ab3754b5688bf54a310a2","nonce":"585c5e66ed424ec12dff9a59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"9853810486bdeee2df6c4f234546c3b83555bbeca4f2299144e931ed224a511e431c33b81322b1e283d8cdb938","nonce":"585c5e66ed424ec12dff9a5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"d4836a486450b846e1e83d22264ef37ab46524e4a0c0bae41e80f9be2238e209b83505006378b45ba6b6d273b3","nonce":"585c5e66ed424ec12dff9a5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"46e0f3fb90ecb12e1328c2ef750d054d84bb05e7b623f64ee5e032954b04d5a96396a1a45fd96ee69b0dc0f4c8","nonce":"585c5e66ed424ec12dff9a54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"2d93aa8f133aed99f898386745dace568669d8fb1f9a8213f6c6806190a378c2a88a7e10a32a4128d049a6199e","nonce":"585c5e66ed424ec12dff9a55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"ef57e2b04860d2f6b8af388b4c61a07f80c3d6957441181a6a004b73d3f39c78a036c06f6be9ae547fee583a94","nonce":"585c5e66ed424ec12dff9a56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"6a370c50356bbb0111a55b5ccdbddf01f3fec9d76f36ce15da6a0441d1a8a810b95ed4952b8d4449a55202197a","nonce":"585c5e66ed424ec12dff9a57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"8877c384e459698cef96880cf48b4520937f5b850f863c24a5774d669d150786150399e9bd824945afd86c10ff","nonce":"585c5e66ed424ec12dff9a50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"c415931fc24b74435907f360b061580336fa9f6ab73c61e912686574919daf0e4e0e405ca717c51fb66ce99c18","nonce":"585c5e66ed424ec12dff9a51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"69536bb8b16fb099735ff5889b6c7af6389d6fac6cb1efc05e16fdbbce3722864cddf3f3ddfe97673471bb72da","nonce":"585c5e66ed424ec12dff9a52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"77dcb56d86c33876bc34d9c421eb937863b2cca72db0697e886baa94579ae7ba4a688997153430e0e53e6bd22f","nonce":"585c5e66ed424ec12dff9a53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"ae271cc808192b410ef7e9bbfc9845e07eebbb49b300186fca6cbb647d39651a53cc6a9698e99d71f5446b2ca8","nonce":"585c5e66ed424ec12dff9bac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"ac0424ff64fbc5487223181c8d6d26685e40df624d802c3d0085bda285041c6c"},{"exporter_context":"00","L":32,"exported_value":"9dfddaac4b85c7e8a0c7481154d58fe6215fb4780f246dc5ebca262372839f5d"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"81105c5836cac49983d5884d4154ced7342be630c7d3ac716a7ee37b3096ef3e"}]},{"mode":0,"kem_id":16,"kdf_id":1,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"565f23469bf1d7dec4429ec38443a45dddf287754324ceb72c664fab7fe343cf","ikmE":"b962b3a828601bef545646ff117408f06b23417df1352c7728663c2834503d12","skRm":"0edded4d3adc8f3bf601579d6e803e9a4bc7eef8beb3fd33e1196ae75413a6f1","skEm":"4bd3b845e64e673a36c52ea2e819b8291f2d381b15d7649c41870c14c3bdcf8a","pkRm":"04c67b9451ed0c36a980b3a20876b9da797e814234177d1c3365c786de5fdabf2c4b19a0f7bcd5567132d59dc08eae061e87c29536e245f95cbb83ab1b2f74164c","pkEm":"049b53cb1aa6004646da50eb6c96bbe3543c5054f1758086d8a5268316dbc423cfe6fe4b0ce9902eaa14ac8ed48449a0597cad62345b2d73bc8b1fbcaa108782ab","enc":"049b53cb1aa6004646da50eb6c96bbe3543c5054f1758086d8a5268316dbc423cfe6fe4b0ce9902eaa14ac8ed48449a0597cad62345b2d73bc8b1fbcaa108782ab","shared_secret":"8493bd3b5eb99e1f93ef3822860e97eaaebc0d02f6a5d3e74b79d29dda9af7f1","key_schedule_context":"00b738cd703db7b4106e93b4621e9a19c89c838e55964240e5d3f331aaf8b0d58b2e986ea1c671b61cf45eec134dac0bae58ec6f63e790b1400b47c33038b0269c","secret":"9a267f765989b3a21dd18b1f1e99acec3b5ddff46c6d1680e6a7807d4b9adc46","key":"70baf5e6f34736265b72b423500bc71b3828e5f78404b355850034f2c1fa921c","base_nonce":"991700c41169507e6ee5600d","exporter_secret":"ca013271612b219874d7d76dedc14296e3bb65885a1016e471c052027d5c76a8","encryptions":[{"aad":"436f756e742d30","ciphertext":"74c9155d64e6ce4f667f8267a326e4014d9b5c0074937b02e1802f75f29eb56471d02c923ac125d9cee9c1a5a4","nonce":"991700c41169507e6ee5600d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"eb002fe214bf4643fb4e70bc8662ef4753b75e2c47b989524aa0eab9e4dea869be1fa28120980addfe75b43f14","nonce":"991700c41169507e6ee5600c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"81ecafe01f618f4acc1a680763a2ec28dbbef8509b1f43691a60ff9aab7e801ac72c6c8c99784c7c4b16287ea7","nonce":"991700c41169507e6ee5600f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"ff2b59d0a2163612c99474345b5c492aaf5bc52157decd4396de2cbc6d0b39f285b6e2434196062e1376466919","nonce":"991700c41169507e6ee5600e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"25d24e72f6dff4e4a6f283a68d990e303d04d44fbddeaab7078aa44e2edff82be34105b94a154fbde7494515af","nonce":"991700c41169507e6ee56009","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"c271f7b275f3cbdb5ec7f3b5f81b1159a43f5b8852342a49cd273982341a5ff4befd64c0870ab61863d28b4a30","nonce":"991700c41169507e6ee56008","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"147355ba9e255371b33390898340e4141391471618cff6b8f8d315d645732c584b391e866c6a3fc52df7e3eb1c","nonce":"991700c41169507e6ee5600b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"bd856e403184c856b7ef557eaadb4183d317c62133dcd33cec26247045a600eccb18fb2298b308b62793ee5361","nonce":"991700c41169507e6ee5600a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"5ff5af167c8c9161fb41e3eb01cedaa079b39b79826cdc060ac4d987aabc0cf9c93ede8b432e775999fac2ee8b","nonce":"991700c41169507e6ee56005","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"692d5b0d80c47c18834a7f4f87fadad715d765f45ef91c894351e9a2f6e1f62ff05e2fb2e68634d795e5f367b5","nonce":"991700c41169507e6ee56004","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"9bca2d53977a2c82a52bd7d46a9750267626ddb2458d1f2bb5e59b1cb6b2517f71d7e1ec4f9c9dcd5d64927271","nonce":"991700c41169507e6ee56007","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"3169c458b73af08b8b83cd1de9f998978a2807611091fabd8daec990625af597228237c9e0f5626eb699688537","nonce":"991700c41169507e6ee56006","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"f8925e7eca2bf1d388a059ac26bb078b1da69a749050f6c681430bc1f1b16c2f245e73991bf15e6d7cad6f8c07","nonce":"991700c41169507e6ee56001","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"60f536fcbaa093156a47bea283beaf4246bb61b3a44373a9122d59dcf9ce761954ce87b278ff0cc5d2fc680b12","nonce":"991700c41169507e6ee56000","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"f615d31683b8e123b3aabc05f9cb32d8dfc02551c1f520fce634ffd79d61ff1434eaf5dd1e7d8df84ad2c62744","nonce":"991700c41169507e6ee56003","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"7fa99c00bd8d268cd5429171d12873e550ade8d832100834c01aa3b93745745ccee6cadff200eddb16553b67f4","nonce":"991700c41169507e6ee56002","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"507f74d25d16a638a1daface897e4d6619b78cb17bda7b4ee53052fb9903e5b9f19c11148538ca517c48385308","nonce":"991700c41169507e6ee5601d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"338f5c617834af07b4e0d7c4453f33411315c91fb921dacc905f91f26609b8c4cf2742a9cc7fb4780d8eac193d","nonce":"991700c41169507e6ee5601c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"3487855fde04438bd55da08a5f503058844c413ea2d1b2b262190ec128264e39231d9eecb8e60528268f21a02c","nonce":"991700c41169507e6ee5601f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"aca65aa8600ed1c9087485a55072487f89d59aa11c855564a9cb9008ffa44ea85443fd9cded2ef568e9d34819e","nonce":"991700c41169507e6ee5601e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"7fb2726e0fb444e3a78ba1e87fb5f65875b65b380e51a5d3052987f57cfa99d4ea8bbf68e99109c9d8c4ab9f1a","nonce":"991700c41169507e6ee56019","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"c5e80aa5b390161ac2bf53495996f1bd0121d5d6e1a5fa36ff16f3a1744eed8e263802f8d5e08e125db20700d5","nonce":"991700c41169507e6ee56018","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"c9718a3e3f7ca217e03234a1e187209dc9cfaec9c73540cb63d582a7d8af823cac442d3054a0227860ad15d87c","nonce":"991700c41169507e6ee5601b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"c44617ae53128e25798a408988abf818a033724946fb0f0ba11962f5df8e3fa2e54fc63e6e06d98d7b3cd2b5da","nonce":"991700c41169507e6ee5601a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"e5fc55fec0bd5523d5e3d5ac11535488c28afa831e6c4289fb138985afff65feeec593f81d781041181b393f1a","nonce":"991700c41169507e6ee56015","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"729c83b82ea79fc3b16b4ad658123c516bbe482717cc8d80579eae261a6eccad6c7086335efdee039f14a213bb","nonce":"991700c41169507e6ee56014","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"ce3e12701f2f763d8234ff3f1393606a8be0ff4f9b84e4de6d90ddf0b6229f279a17d4a9ee4fdfa32209667ea5","nonce":"991700c41169507e6ee56017","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"039f4ec064303d87361457000563e20344ba3718bf1d9e15743ef8209de44bea955306d06465ae6a869b432a4d","nonce":"991700c41169507e6ee56016","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"7664d480a08b377ada01740e82e69c2b0cf364087078191a1ab1321103cac870e4f6c7b2c76c510d1e39a6c7b2","nonce":"991700c41169507e6ee56011","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"d755f8297df69a6e140dc5c08bf2077f2193e0d3a6a49079994d2161f280c78e72828fe8723b823946998e65ea","nonce":"991700c41169507e6ee56010","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"f1b35642999dcc793e6a11232e8223b390146db9037a68961e7967a3207d57a4b83e6288b4367a63f9d750bce7","nonce":"991700c41169507e6ee56013","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"ec41ba5b26abbdc0ac1f051b49611103e8a10e48da05ef00d5f89dba016ce9bdd06950457d4834a7f5ba6daafa","nonce":"991700c41169507e6ee56012","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"426b221aea22b1d7aa37013d44a2d8a72bfd77b445b2081e8d2fd18dc33c5edd31491f6a6df9d981eba779722b","nonce":"991700c41169507e6ee5602d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"55c0497d6cace9337362a0d56b0c507ff737b622b72c1765ecc44e240b0b3b7c40997aca0a8c249195b60b685c","nonce":"991700c41169507e6ee5602c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"d122c63b8dcfa81d5a2134e8c103acaf936941fe3a2708f9a937f1cbd9bded0debdc0fdb1fa7ee9d5af4a7cd3e","nonce":"991700c41169507e6ee5602f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"904d5fa8e327c0df2153e4ad08d8ea03f7d4e5a7aa04b2c0921317cd76afadcb0482c7bf0fd520bac19b3d1ab4","nonce":"991700c41169507e6ee5602e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"6658508f9111b4b2aeec41f8d7ca37fceaa088cbee2290d958c9a98fbc42b97f82af2d28af727fecf362b331b1","nonce":"991700c41169507e6ee56029","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"5f51c13245aef9d8693f433d3b16487238111dfa58276042283c9d61e4e5c3cd3c74543148548b81a1916a483d","nonce":"991700c41169507e6ee56028","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"e42ebfc9a13cc7e48efaee52f14129276fe71f273aa22ab4e9a52c57cf1d957d9a1371a3db7b76723c5d03f2e9","nonce":"991700c41169507e6ee5602b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"77df2b1333d60263c69281a210dc56c760cf95a5cf9749cb96b729dc1051ba105249a31b9a933b1c3012b17cac","nonce":"991700c41169507e6ee5602a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"d45166cc3cf355eb1ebd78430c1cd5114ca9d4715f7287579bdae80dcfdd475566575b4a797611cb84c8a8fd50","nonce":"991700c41169507e6ee56025","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"2c755097cf30e94d9cc26f7a09a1eef85ab409a879876130844edf68571a3596225e6b54e5594ad125d6826580","nonce":"991700c41169507e6ee56024","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"7cec4d9bd87ce17032e95b79c3223ddb820a0d26e06e51f2246883110cf250b29ea64c2f4edabb9da44d4190c6","nonce":"991700c41169507e6ee56027","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"bd9b1fa0a8bdb7476dd49b28250a542faa24e2069ce18609274d7508b64f1ca0cd402e7a568ae169be7f161810","nonce":"991700c41169507e6ee56026","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"be19d79beddd28241f76be9f252b1737c394059ec424fcdb949e13fb1415a5cb3672356e801cbf718d583d4a99","nonce":"991700c41169507e6ee56021","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"31f8b0e1d67dab955011bf19873e8b8c7e8f4827e1bcba41721029cc48caec95b2673ed731453d3dfa72cbfda7","nonce":"991700c41169507e6ee56020","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"91bea8f341d9f3fbfb0b4b29279ad2926b3b559a76608f036444abbe1965ab25525e059423ca384c90b3110dbf","nonce":"991700c41169507e6ee56023","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"d4279f477d925a655ba07cf15069ea38f2f54ebd67261b28c8612a6e8d3c1309695dfd4c0f2479bd55a55182d7","nonce":"991700c41169507e6ee56022","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"ca48253dd97bc546a28fec856bc1af9ae38ce8735c243451c6918c743f9260f3ecee1658491b07c480e185f365","nonce":"991700c41169507e6ee5603d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"77384bb93a95b69a6fc2510883e3a7cb7c935d4773590fbfea1087165d60b1b756b21f167766fc213af38e118d","nonce":"991700c41169507e6ee5603c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"bfa2c76dc0ae6e64a5e83e04542d3e2e557cf14287ecb5aef0586e3642dc64e09dbeb3aceb8be9227c66921866","nonce":"991700c41169507e6ee5603f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"186692ab3134149c01a4f15d570316b423f112d93453fde60bf6eca48b725e14c2b36e832c06be7823dd3d1b7d","nonce":"991700c41169507e6ee5603e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"07ce18d36053bb6de41295243d9ebd8ce08870dc0477e83a9a88b5ec456ff2ef8f734f5756c7942ce553ea71f4","nonce":"991700c41169507e6ee56039","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"4ac67c360e8ba217aef88d8e143b21c5163368facceb61100b518ba1c3d680d539a2518d52d0d9d44b01fd9f0b","nonce":"991700c41169507e6ee56038","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"19db0dfbab64ba3428deafd94e001106580af9ee3723fdde25bdcc0af14d7ee93a0831e22b16f1c32b1492e8e3","nonce":"991700c41169507e6ee5603b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"1911d82031d1dcf6f0dfb2c76663b0375fb119fdb6eb1be37feba7b0c64f3c00377e72418f714398998cf6d51d","nonce":"991700c41169507e6ee5603a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"b19a281318863c9e19d83933e9edce0af1441c7dc66fc3f060d0c5dce2cc0fc849999a9d90968ad0c04ebfbe4c","nonce":"991700c41169507e6ee56035","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"a3a5c7b7262deb39d5b4ecc2c069290a172eaec72f8caed4e8416f2f0e2887d64d6eb5ac81f8cc64d3641a1e1e","nonce":"991700c41169507e6ee56034","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"8d86e6a0356ad50420e6b2a0ed4a35ffd619d168bcbdf93dd8a9c720158486361228b8cc7c78b9863d53c366cd","nonce":"991700c41169507e6ee56037","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"ad7014cf6a10b77be035cb61cc027d76beed06d88d1a1323af98c7abdab609350bd06ae176135f0c9d04b4f380","nonce":"991700c41169507e6ee56036","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"f033aba0af1d0ab3d247cf9f597c10208017bae37fb9688a99ee56d84b9d13af420fef14b3e359b0a9a2f834db","nonce":"991700c41169507e6ee56031","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"ee1baa07f081bea15742d03331f985578e9c878366beefbe8a7cf4dd6b267002e8529af95f900f7ce8ce43b5bf","nonce":"991700c41169507e6ee56030","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"e32337069748b5edbbe5c5df0e90ec385be61274a097b718610d8575519f89ab8dc22242cf15029e7a967d2871","nonce":"991700c41169507e6ee56033","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"5ede87259f1355743365d2ac17ffd02b19e6d7d6db452377ea94d09fce2b691e598854831572db0b31db8b0242","nonce":"991700c41169507e6ee56032","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"f07e469b9449935ecc0e427c7c0bee96623ace615e196add508fc0f0ed314cc15ad1cc6781416cf730ceac66a4","nonce":"991700c41169507e6ee5604d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"3fbbb5338b581cb79237af6e7a5e80dfe87c181b9688ea8d1eb82b18c8e6a54f0fe41f05db79aac9f03cd1a9b0","nonce":"991700c41169507e6ee5604c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"3fc263f2a3daa1b7623179e3b4ae2217e1c73c8b051ba3c54cc5a9153228fbf5b7cecbdac4d2d0105ac8f2972d","nonce":"991700c41169507e6ee5604f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"bb9419ffbb62425348ba1856c5e5375d79601e98699fbf9da007f53bd7e4f68538ff5289d87221cab976ca5255","nonce":"991700c41169507e6ee5604e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"892c8080de800c1c64d714953fbbc92d2aa94a57f41054892d9dd1836240edb1378c40eaaa4166a66afc9f4dbc","nonce":"991700c41169507e6ee56049","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"466431a11d4fc37da27909d69a179056ec76ab9af18ee313e76d95a60a206d207780b4d3f15a43d0ea052217fd","nonce":"991700c41169507e6ee56048","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"dacf9fa9190ebb1dfdf213f1694ac731b89462c855a99eecdf4a690660cb050fe91a0cb4e9ee2b26f1523c0bff","nonce":"991700c41169507e6ee5604b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"322a86b9e34467f0263fe032361ca1789acba9eb6fcf944db384cccfb38e6b98555ea42183f2f8b1d2dbee9277","nonce":"991700c41169507e6ee5604a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"dc82c7e473e07a49c462e950f6f3591faa72422964c7125eeec062a95bc292cb52fcefb5c69abb95359c5ee71c","nonce":"991700c41169507e6ee56045","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"9e275b1dfb2123ce81e3da8b1361ece58e68826182d49b448e33ae2548ab34a4183561f89ef6fe9225e51e12c4","nonce":"991700c41169507e6ee56044","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"91aee99bca931f4693f282704f6248c295df86173994855e55591f47742cf5fcf2c3651d822fbbb2dc4dc0338c","nonce":"991700c41169507e6ee56047","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"55e852a53e9463fefcfada8c21334b49734d9aa19eb5e73a62f004858079e2cd7e456f2abd7d34c765d554712a","nonce":"991700c41169507e6ee56046","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"b30c0c3663209169222894fad1e47d5d9dd0650460e4ac7dadcb223f0c17b45dcbe9ba02b79cc735f3055cc8ba","nonce":"991700c41169507e6ee56041","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"6059be1a258b040ba0256ffd833baafb4a2e8670d8084ce421b2e26f2ba986a2f33fd34a3d05d8ae432820ebc7","nonce":"991700c41169507e6ee56040","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"905122490d32feac7528235e63c3dcd58c4fa5665d5eee09ce6f7f3327ae88a31dd718cdeb33534ee146da041c","nonce":"991700c41169507e6ee56043","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"2ec59c8eea92145cbaaad240adc736def364a781e4e0c6715973e6ea4bb4a573e60d4820385eefed450b072f27","nonce":"991700c41169507e6ee56042","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"1cfcaed7ef432e83aaf44258f2583210295d22dbb50c78fe897d7db93a9d69e7dab735990586eb3720dfd101e6","nonce":"991700c41169507e6ee5605d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"cd9117886dd5cbcfa74b0fe3a1cba8e62df8280cbd1457b6677a75fc5d4fa05f6def24448f04c27acd0e127ee0","nonce":"991700c41169507e6ee5605c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"90a1885011a8b276658d81808fdb8de7c5cb2bc6e7e6c53980219e39fab5cc6129b9283842a4d4b21521d9dc4a","nonce":"991700c41169507e6ee5605f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"137f54335ea261e9ca0abb44c7159f5f1ed44c5f85dbc2b1036ed18d5bd2ca13f84a353059fe3d2bd71bcc4815","nonce":"991700c41169507e6ee5605e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"b4705079a36da08af23d9835ea0cdeb9976f90cbeb03e99940474b56ac9d0a131824f51cf379977e2ae68b189a","nonce":"991700c41169507e6ee56059","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"e5df355c0248816692a9fae2ab88ce7d8d4b322f6b67851d3152e041aac627cc95af7d8cf5d5bf344d50d3004e","nonce":"991700c41169507e6ee56058","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"ac69316d84512388cb2deea5f2771270b03a860083c203b7b9d1a78b051262279e36f5f78bbdbee2f167e97563","nonce":"991700c41169507e6ee5605b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"9996ff15e97f9af14133fc8e9298caa79b86114cccc9f54d90f5d42bc1b4039f443388aebc6445082900f3958e","nonce":"991700c41169507e6ee5605a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"5af13f500a38d44cc5ed9f2e0065e568b868abf867db61fbd9a73163e4fd56f33fd84bde16efc50b21a09b09c8","nonce":"991700c41169507e6ee56055","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"7ad3bf14ea52ec1ca2353448e7192f28be0eef1ddbdb15785d3496c045958e2a2bd39cbee9c6ea92d8dd261c16","nonce":"991700c41169507e6ee56054","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"523d386315dbe428203b63337569bdbc576b7e1cf46332da9dde7583eb8ee96c38a14a818144be9662d66ce581","nonce":"991700c41169507e6ee56057","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"bf83e4f653a7b5a1c1f0d5ba93163c58891d20640be864a8e980bf3a25f067062878143507794663a475c33d9a","nonce":"991700c41169507e6ee56056","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"f7f853fff2e67e6452de147c3bb26d115200073c26e3b73003a10a72590ffc04f66a283ad0995f8e727f1ce890","nonce":"991700c41169507e6ee56051","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"6f5108004a6914fddfc0070e42bc3faf85a38f078451558c4bcd82f404d667129d9626c3120c6cbbf075a0c74b","nonce":"991700c41169507e6ee56050","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"a841b7446b0f112707deaa0baf4242443353c1615f7dd067a0898859ba04d5cd1d7ba84909d69d3ecf92352b1a","nonce":"991700c41169507e6ee56053","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"dd6f087985cf185a12ec49849dc347a4e4bb9b189f287a39cd1f320c36b8ecdb323f180bead76cbb2bc46aa4c9","nonce":"991700c41169507e6ee56052","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"9073618c0c19ebc7a10dea72d5b518309d01b812136ce58a7d3c40dcafc96a0f3dbff65aad9dd90e6b41372f3f","nonce":"991700c41169507e6ee5606d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"acd0f61ea7afec89c0886e35a2f5483e903cc925a31c89abd8fb343641c14bb359202c49f62d5f5dd274434ee2","nonce":"991700c41169507e6ee5606c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"0ce7a72b5944cd081cdf95a77d6c28cbdf173848658c4743d2ce3e4c8a1dfd2e404a0af67b19424c64839ef198","nonce":"991700c41169507e6ee5606f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"6f58163573d96fec1d77788718b231b00579f8ba0c670998f067586ada6014d7e0c0ee657cfccd7fed4e02f1d0","nonce":"991700c41169507e6ee5606e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"544c5dff19d461a5d19948dbc02d83a50576ec6ba6736326ea919aadf3cc028b174c9e2ab26d6f4082d8908049","nonce":"991700c41169507e6ee56069","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"21314bbfb70a877cc8c323f15502c43359211645bccb85b484b75b39f0bb73cbd5cd8c05b7139181eac61e021b","nonce":"991700c41169507e6ee56068","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"11287f849448ee4bb50ab92356e49396c2ad0d0448f10d9395d8c0d6f1b131ac792424474f685bb4b0a151af88","nonce":"991700c41169507e6ee5606b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"1af08e89bbf3e40d91e6e9b169eb00ac497ef5526f08605d640c35b77f297d954b00e806086ab8d5f3a4401f79","nonce":"991700c41169507e6ee5606a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"66994657e0ae344dc6eb9e4475e73a7837434e8d174ee7718693d63fcc1e557c14cc9309a907701056d22ed75f","nonce":"991700c41169507e6ee56065","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"477c33a2a1fe76541098f71b3ed24026b791e0c08ac738e1b68bd03684bf8d7b8aa0d19a3eeb5ec79293d7f59f","nonce":"991700c41169507e6ee56064","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"40ef16e9042ca3381fbc6a323155c768659d6bbbbf95fd51d8c46f995a4fa41abddb069095a55be6f28c815dea","nonce":"991700c41169507e6ee56067","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"86df1d0056081e7c625d32ce8eabd2750a8d94d4bb83b5d5df1986cb9bd3110a30b4df7a6dbc8dbe89f46008bf","nonce":"991700c41169507e6ee56066","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"1adc8a728e410b10855ccf82667726148585dfb24e891e65a7416f9b1776a43c05db8fa495f490e196257e5d14","nonce":"991700c41169507e6ee56061","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"159fd8cbae05490609c43f79321abd13dee227fada9b42aa0e2905258231e743bebcbdffa51adc5f2089fe7e06","nonce":"991700c41169507e6ee56060","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"08d952f10cae93192fa371a79da6c014fb3d77151eee546931992bf2fc13cdebfd5c5424d188032e0d8b2ca71b","nonce":"991700c41169507e6ee56063","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"7e40dba24dc436893f3bab90b831533e32d3ed0c9b5a0162e11e72f46491ec9921a561186d91b6a6c0f244c94b","nonce":"991700c41169507e6ee56062","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"0d36c1f2c678b6ffa81374ee55ea9a12fa1550746a1f248d64442d6ff16a376dac5c60f5658e7653358ee87147","nonce":"991700c41169507e6ee5607d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"1b5db41844ac26d911c30d321e6c2f62f791ec365a102733d60d15c394b252e3df35a0f4698ec4294b05285f04","nonce":"991700c41169507e6ee5607c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"54495f73a77d45394140a477965e9d2cc807fbe83f5232e653c57e87deb979146801adb3d60ced1e5890ee2c42","nonce":"991700c41169507e6ee5607f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"59ad5682e968f7d7586c48da771906d21b914687e3a5d50ed7375b3610381249449ad1f045d5bf32303de2e2b4","nonce":"991700c41169507e6ee5607e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"e75a8a02d388bba9a7ed1b821ad716c4a1b635a38887354065661023bf1ef9eac2f2328a5ca2aafd862d9199d2","nonce":"991700c41169507e6ee56079","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"fc62afda0766c40e78ab2987b61ef3389228151362d416ff8e18c05d94abbd46767ecccea3b728a4d36a46f041","nonce":"991700c41169507e6ee56078","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"2408bcdbdba03ef309b59f3f80465bae0d02e9a1e9c4f354503dc7dbf60e26310fc1833f5023f0ff9e7497d62e","nonce":"991700c41169507e6ee5607b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"e9692fe939c557ba894ac9bb0f3a1e4d11b77294f6c6fc0f9fa2a9031e769e48659df874ae779d64d9f079599f","nonce":"991700c41169507e6ee5607a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"224f908dc885e2fa8239079fd38e2fb1cd1b0f4cd67448ba020e7d32d7891acfb5431071bf05dd26ae40f81022","nonce":"991700c41169507e6ee56075","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"6306af60095a6f73d7f56910024dba0dc511e03909bd3e9e4dcc046d1f844264b7626eedd506d88a12ab0c6953","nonce":"991700c41169507e6ee56074","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"ef4d7bd39418305b295402684f42ba258254a8671769725429342fa95aed2f1365dc0f672f4440a92fdcf34b2e","nonce":"991700c41169507e6ee56077","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"88c57d45643ce4a9eee3cf5516139c272703672e2695a6c17c06baa5996a9f378ce1600d638a5c25ce55e92833","nonce":"991700c41169507e6ee56076","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"77c47bc378fb43ef4de29ebd6c6c5bd138ecfb41fac518f267b3deb9191e3bb438f88c7aa76c3a268fcd0a03db","nonce":"991700c41169507e6ee56071","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"6ce39135f1dafa3780e7b969729e84cd146711ec0254ca2fc2cbd8fafcefac5229c3a58f9675841cd0deb9ed64","nonce":"991700c41169507e6ee56070","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"17918897436d96bd3c0e8d9f92ca1e8250bd0cf21bd01a1010505ab753207e2e3722b77c42bf366c1c242addbc","nonce":"991700c41169507e6ee56073","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"38161302b51be95f39eb622cfe614500147ea77963035bcf22f00062b7792ac9e624c7b6887fcf44e51cc1f39f","nonce":"991700c41169507e6ee56072","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"ba1845b27945a2f6540083868dcedcff038fa3f1349f9af41db64489de9160fd47934a6c63ddd0a4480785d7d4","nonce":"991700c41169507e6ee5608d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"1ea5e45bcc298a42e14752c8861ce6f7d9dc144348e317da4d710fecf3c32c73798a703ac739226d52d80382b5","nonce":"991700c41169507e6ee5608c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"c724ea86363179a8358408923983a0d274d4dcc3a6251fc378183b1cc3cf60f3d8b10b649e68a9a9c2a368d055","nonce":"991700c41169507e6ee5608f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"1b7bf41ad19a7d697376698a5fc191c974760a307a7645d01e053398d6ea0c8747d92ee0112a43167304f9c710","nonce":"991700c41169507e6ee5608e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"4c068f0811a50c3a1b599492bad5424334c818a564be221d5a20daa0970e5b9097ca8c7f02120cdb8e33199d08","nonce":"991700c41169507e6ee56089","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"3e53e6e7a7f0075e7f79978edefe1aa1699d8cef917a1e3fdf4f7bb90644b59e222a0776fbd9d63d95c4c7c86d","nonce":"991700c41169507e6ee56088","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"6a56cddd982f5dc566f26d21ede5c29dde2e22af12386fed52f680b08234a3e2461d757e9441467ee36e21e9ab","nonce":"991700c41169507e6ee5608b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"8b7a5719dcf7a1ddc5478bbc881521bde7631649f95819dff01d9f2530fd6cb096fdd0a8fab0a5cee6856c259a","nonce":"991700c41169507e6ee5608a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"59f3093bfa27a3aa6cf2da35fffffae9a115883610583d32444c4fde0cf1db1461184e31c690f0efc39f672262","nonce":"991700c41169507e6ee56085","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"4e30d20d3c55d8b626baf29ed1f62804fcd57febf64b1ec4cf3f545a3a96297e05bdac0c053ff78c93be672d79","nonce":"991700c41169507e6ee56084","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"d881e9895fd07141bf9e4fbbdc1cd74fbdf54b2ea46beaeb1411e0220273d412499e87c17dbf0302c53a98a02e","nonce":"991700c41169507e6ee56087","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"84e337472a10731b2a319e84e4e228719f6ebbd9bc6913c5d8281fbbbbbb5c9d66c9d140f16d17cd845e870df6","nonce":"991700c41169507e6ee56086","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"882a37665c091e714d632d0da9ad496600acde70a5df1ba1e589316c2c61aef10c5a2f3b3575ae6efa4b91ef92","nonce":"991700c41169507e6ee56081","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"04e2e0bb5664be4a2bc7c0fd7b8b073ef87eaa655b76fa58fc1f0f5d71ce2b9207fd82cc2023a32ee4f799d66a","nonce":"991700c41169507e6ee56080","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"d3070ce996b1ce4a0a2c30365ff2d40613f2ead0b7dc3ce84a5f01ebea3b42a61e55999ac86fd2b6b217a5dc35","nonce":"991700c41169507e6ee56083","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"b420a61f3026252011866bd569ccbbb781a2955eed5be358b9ea5f57df0bbf71979038a3b552faf047bf032b9a","nonce":"991700c41169507e6ee56082","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"433332ee1b72c99d36d02f1665bd35a4e26c0be2e0950c130e4b88000a7e7c3b83cc875e67675bbb3e071118c3","nonce":"991700c41169507e6ee5609d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"af4475abc8d46bdde79d812cd435820f8a6c808c3b68950e5a432ebed7d50166fdf6a6d3a3ea4779668ed3f73a","nonce":"991700c41169507e6ee5609c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"1dcf7a7892a34cb097e6b3c229ed4627ee7aad438f405ab7576089ef82b76017ab41382a889383bb80b1663928","nonce":"991700c41169507e6ee5609f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"d09d94ad56250ebb143c362fb35048530d7a1b7669bff9567cda126430bfc6598819ab2f33318ba3cadfcdf2de","nonce":"991700c41169507e6ee5609e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"29afa036e9fa56fdd35e77b203363dbba632483f0731ac1a05e5a559fd38430e991073ac3c2b42d2901cdbf74a","nonce":"991700c41169507e6ee56099","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"5a1519edd6e297aacdd14932955f1ad148637f8b2f161b6327c5ae3ec480cb138cf5d0062365f0fb34ba86282e","nonce":"991700c41169507e6ee56098","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"d2c016f1ec3384a551d4d1c8e10a1f226f640a570970b11354617dad482c1a78046c3f5458538747d9b2831bfd","nonce":"991700c41169507e6ee5609b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"2cf5cb5c80d8543413736e8b4bcc6fe8010687d24feb4e0973cbe851c0f1a5322c5ba5fc93b55c0ee95a44bd1f","nonce":"991700c41169507e6ee5609a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"c42aa2602d7674f237170c11b34d19d2af64f960d63b0dc9bd79ea07d232a19d7b0a3103a9d382fc8dd6cd4b01","nonce":"991700c41169507e6ee56095","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"3541740fefb40a3c0ba9e6ea8aa62b33c5d416b3a511d53ea8d32065f79353f5545723283247e18d193478854d","nonce":"991700c41169507e6ee56094","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"e284f7af4c6ce71aec0867c247d02f8feac35102644660bba15d7c061175f2ef9a0232b164c9c18cf28456a728","nonce":"991700c41169507e6ee56097","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"7d9e96be4b3f495259e48e2da7519c15a6d218606d34a69de30ff9d1d7d2e060735e962d25d3db28ac98b64c58","nonce":"991700c41169507e6ee56096","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"2c2b92aa7991310d6965cff4eebdddde09c64f0f2a3ec5fc9ba9f62efafe02e65de4abf5ded4653d667fdc2a14","nonce":"991700c41169507e6ee56091","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"1c4f36839db8fe08c90ca29856c68fcdf6ee79c8a8d30c19d323a31fd473f03679017d959b3bc406c73d3536a1","nonce":"991700c41169507e6ee56090","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"b85a4a3feeba78bb9dc1f416bdf2379288cd338257efd61964d148c1952e70936928dddb72695b59fdbbd66679","nonce":"991700c41169507e6ee56093","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"7abe03c847d418b552bfe234f645ea6587457727324cf84143a977cf897090cc5addcfad74e9396d1eae3826f1","nonce":"991700c41169507e6ee56092","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"49581c751dd64b14914ef43647cf4e897060280ae1fdb5c7a7f658bdfb6f5a913059ec8265e2c01b48278bf3ea","nonce":"991700c41169507e6ee560ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"e49695c5503aae0d81c37b2fba40ffe619cbdfe84ff84eab8229fd9e7bf1c68d3a91a8f1972de3484ec2290219","nonce":"991700c41169507e6ee560ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"5f8c4e19db131caa80ecef0943dd6dabc1382e5c90a077002a7cde504b7a41d5403b00a18c40fc4eb6d3cb4620","nonce":"991700c41169507e6ee560af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"4a3a0161d251450c0cec369ab4c618aa5cfca3d1f392aa568d1720dffccba5f265c18447df1b84a19c6b98e470","nonce":"991700c41169507e6ee560ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"3f76754588ac3a46ee8a14acd1175ddec9f232a90f3089e293ffab972de0b19a801ff6518d64b554da65325d90","nonce":"991700c41169507e6ee560a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"2415a2911443b1a82678ebaf19560aa77fa27eb21fefce4dc1247143d618e15af72624091895162bafedcf0a65","nonce":"991700c41169507e6ee560a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"084671ea5eb2d390e1e6dbc223e23e2af63d651c26dfa0e366edd18eea0a8423fb3250256183636a899211c76e","nonce":"991700c41169507e6ee560ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"47999fab524e7b7d88c5c589dd5402cf39d4f736ffea2e60e77970af26f5df14507de2b02db10ce5fb77a8a9f9","nonce":"991700c41169507e6ee560aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"ed6d34959d32d7f321bd511c3e79ccaa1909aa932eb7d9c7f243ed8266896733e60f61f54e320a053093b6846f","nonce":"991700c41169507e6ee560a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"e697cbeb106eda8db8cb64c073123ce5274e68a886d4b0716e8a4aa73275c369b2158272eaee8d8e6226ece95d","nonce":"991700c41169507e6ee560a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"afab4cc3cb1f31a8b5b9387c0fce81d6cbc2ca01464a02328f980278fed595298785a911fe5471c8e0c75909e0","nonce":"991700c41169507e6ee560a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"0d1e2ee93f709de22d40ba0843e3fa6fe1035073c13bc3bc88122720f1cad758a51e75c6af4786e0daa14679ca","nonce":"991700c41169507e6ee560a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"8e00790de97286e8ca8b94bcd980267095eaae05a816e5bbb24a3908ef927c00918f333cbacc691b3aaab63f93","nonce":"991700c41169507e6ee560a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"fef641466b9e90cbf12f46bf1c6164b60b97181bdb61c57b0093140d2c958cc2ce0aa81244a1f42bd60b92ce37","nonce":"991700c41169507e6ee560a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"e1acf9c88827a201f8d3e52ec1ead93c1f9e40f62bf4b0a88f5b7db7d61f3c4645b9018af44ff5b890ef4a66e2","nonce":"991700c41169507e6ee560a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"e2bc1a56f7edc92eeb6270fb9a5db3b5f398d22b5136138a30c7db4e529805c96881a67646f0597ed36c177a15","nonce":"991700c41169507e6ee560a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"abacfe8e7d74d4aee2ad1fdab1706537a4246e286d950cf302f69cf90db5c56b0a5cfd4c38eee10765556073ef","nonce":"991700c41169507e6ee560bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"83a377c3bdc8b30b0111230286561dd06de606672c2d4023565d4026e52365d85169183ee04e301fe5fc245495","nonce":"991700c41169507e6ee560bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"59106e41ed0dcfebf69a6b3413be664d1cdf45c2a7f02af354a72d77412b088712e65984dc611cb540dfaf5699","nonce":"991700c41169507e6ee560bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"201d00b5aa05adc7d1c7c01cc57f149fc4415059c24cb3d04deb8d7b6f7f1f9e81e6d6002cbdb6cff32e281bd9","nonce":"991700c41169507e6ee560be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"61871f90b37ae9326e571368bdf4d142b0fbf801da8b526921f5215c454e73c5187ebe6260929f2742cc8cc8a7","nonce":"991700c41169507e6ee560b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"a0693471ef2473a389c0d4fb542eda9fbce78e16f8ecf54b1dfbd6e3569743c4defbe24c5c36daaced90b1ffea","nonce":"991700c41169507e6ee560b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"8dfca9c9f35e656b51af4170dd13adad3398b23709dd57b201059a05272e69cb3c9f3f15be80fa33d99e585b86","nonce":"991700c41169507e6ee560bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"fe50bc3f168be013b83cce3482a60afdcee3d615b612ec7bbaab2e1e7e91f320ea2a44822e1819d982017a85f1","nonce":"991700c41169507e6ee560ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"4fd0293b897d1576d167c55ba62518f70cc2e85943049399adb73d1274362d06b47ab419107cd4f4da01409945","nonce":"991700c41169507e6ee560b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"ef7123d363b467b95acc40d6c86879e0df2e2ac74f1f6b4aea7b6ea1b05b6557d1b74195a5ff15bcf42d4f3ee7","nonce":"991700c41169507e6ee560b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"d66f363b0cecc8c04bfff8dd84eac9bb105b15af92cb37bac078a228eb495bdee65f839c5349779665145bffc4","nonce":"991700c41169507e6ee560b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"4588da5acb984f115ac5dce56ab16bc117d9a734862e753e93a71d678deec5d17a7b6a6be3dd1e4e9c89b2c42d","nonce":"991700c41169507e6ee560b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"f384c1afc2ec9f576eaebfe07a14173f8dd077de0b51960d4c956de83e21db9305518279d81c9cce383d28b983","nonce":"991700c41169507e6ee560b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"789de766969dc104fb895334b900313f986c68381f870326773c25caf8920b91480d1fcdebd75ab0e791ffc7fb","nonce":"991700c41169507e6ee560b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"c662d7bb0d9e4562b9b7f5732a4c233c1d830dced9a7032f5f24a17a5f7c75f99e0afb1fb162541a9b7782595d","nonce":"991700c41169507e6ee560b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"831e4873cce089736eaa22f913a1d2288b13c67c149fd0e95f99fffa62fc626c788bfd08eda0d95f4014eef342","nonce":"991700c41169507e6ee560b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"3d6dfe9360138d8206c5731b7e864c49379718349b2c8a56f115f382a9e072303a90233b7b3a2bde4ec6e97e65","nonce":"991700c41169507e6ee560cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"ac10b251778c08ceb69be10277b92f9d92d6ff1a00923c7ac26f68184c2a383c814c1e5976419431e6f262d4db","nonce":"991700c41169507e6ee560cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"0a8f79dab6871c916fc99985bb2befaf170902e692ba341a70fab7d124fe4d897d14f4b94488eb5f4d9e50fed5","nonce":"991700c41169507e6ee560cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"995f050720664bf65c284b700cdada65f1b62b0b8e17dc1a51b04b0ed46e352844040657a883d0a5cb0bfb97ee","nonce":"991700c41169507e6ee560ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"09c4d6e6d48b3084a8a33cdedbdf1d175dee0d4b09faf4ea1b1b64c01e5e0c40a86c8ca31d7e94e3be059ae7e0","nonce":"991700c41169507e6ee560c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"82ada54d934f90789b2a23499f1ed882082255d75fbe732fda64b581688fb85ebcc2d7dea4264b2b35efeb56c7","nonce":"991700c41169507e6ee560c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"2e4b62dedcb6b26560b5e5d042a50d2b834e60ac01fe01d9f9dc281bda38371f4d59d9f438cba56173df460663","nonce":"991700c41169507e6ee560cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"595294443ff3b11ea2fd351e73047fd4af1aff2e9e5be47eb11332d3af1a06fd64ba5352a191e0e7a5b4641684","nonce":"991700c41169507e6ee560ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"c970e898a119bf663024f6132044dbf1c5719c1ab74b3efc2323f064bb177c82587e2effbab3b0625bfb3d2d10","nonce":"991700c41169507e6ee560c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"cbbdc011e78b35acd00702e0557fae2cd17d9fffec84abbbafe9a35489f5dec72728622388411103c4b2223ab0","nonce":"991700c41169507e6ee560c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"15c58274701d2c66077c6dc0720a0b6d08df2e24a706d2c74fff37c5e3d9410543851514c3cd60158643fa0d93","nonce":"991700c41169507e6ee560c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"d5f8f974a27f66c0042ba6bcec172c6c33b4ef96f890a7d326365d2fcdc20afd0db8f0a7e5fbc09b3df344dcd2","nonce":"991700c41169507e6ee560c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"744fa795fffcf5fef5d5187e9f1743fac796212eae19c74130e659149efd0843027019489ef553a939327d5642","nonce":"991700c41169507e6ee560c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"cc6f372f27155f864df8bef5a74455d3661b5baeed2a101dd40a6cfc0cba882f5dad1e9862135b725692420059","nonce":"991700c41169507e6ee560c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"924eb9ca15da376dff9ca622cd18a2627a9e6dbda307b47ea737d7100752a147364569d138a22c2597ffa984cb","nonce":"991700c41169507e6ee560c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"c3c39a7e2b9fc637e4863976f4e60b2f8ee7c7b94533aba1931123bb686aba693d7f97a63a9fc4ae5d8d030feb","nonce":"991700c41169507e6ee560c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"4505cb7aae182e76cc04742a6e74dabff7bfb434ce3024033a11d0a7f69b2260e3ef8f9df63f5ae04896c6b522","nonce":"991700c41169507e6ee560dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"c8a33445c5882c69c7b8010262f3d100de245fb1cb31d591a7cd5619fe71b9caa78d20c1b272d758d88f6f9ab7","nonce":"991700c41169507e6ee560dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"5801358364b8f44893a0ef61a7959e0b01903524e9958c0113fe25cb2c6408dfa1623decbc7e9a26cb91d450b9","nonce":"991700c41169507e6ee560df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"a760f6973221c2af88da08c1fd22538a4a7c6489f377d18ec873f8f8361a2128de54fa3060823fccae7d032edb","nonce":"991700c41169507e6ee560de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"92ff6c2efea1fd2eb97d0e0b194fea36d0a06a9899a97d51c47b46c5f4b238fd63e49a0afa884b512dba6a107f","nonce":"991700c41169507e6ee560d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"44d040f51995cad3d175dd7c8d7d8c22e572a1cd6e1ef5daf42495999a5f339819176bae87634b7d0bdd04e339","nonce":"991700c41169507e6ee560d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"0e1bb2d8cbeb392e0ae728b055ead80b40c12d17c3501e9bfecfafbe47a54e368a5931f88ada6a86e62936ba43","nonce":"991700c41169507e6ee560db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"403a4de81da377080adb186d780e0524d7762b1d79f5748a0ed3418dab5be5b4ee7502873443f63d47e0673180","nonce":"991700c41169507e6ee560da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"d7740110d38f0e94943bce5a067d118d6d473a93fa29973310297018ccdd4122c069794bbaac9b2d426102010e","nonce":"991700c41169507e6ee560d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"0ddef977632d9f4436f634cf08aabfe373c9fadf57f643ff79760a8f75efa66c97cdf281c0c25324e3abd486c3","nonce":"991700c41169507e6ee560d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"abdc750ba47b124579cf495bd194acd00b9df80bcd2d9ff9d08d653b02169e13811060577fd5e44bb142ee42f3","nonce":"991700c41169507e6ee560d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"88eff0b74b50bb221d0fa199c5238677954acb96294ccc09f429c4ff0bc54882a1048e94f9565a6962d53b18a4","nonce":"991700c41169507e6ee560d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"73592963085f70d526701dfe5c0ddd6341e6448695c7805bff36f5c898ed07190f10177e79baa3e89e669c4783","nonce":"991700c41169507e6ee560d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"14f5ddaa828f5d88f98d839bdebac3a3754b9d42980d521950ed75bafa8260334a450367f10696260505201e36","nonce":"991700c41169507e6ee560d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"69502ea8b76324e5975c4328a7a56a2c5b393e499a3428596cf8dbeef99d16c1ca893950b95db7099a40a6151e","nonce":"991700c41169507e6ee560d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"df12ee88e5536a5694bc677c7b670b7a42ec93bcdbaaedfdea4137fe3cc3d0b6715460df73a54d2d9252ff2e3a","nonce":"991700c41169507e6ee560d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"afaac002bd3b6e4c94178a1d13bc625e9b01645abe1f10ca5fb9c793138cfd62759f7c617cbbca3560cf4c1bb3","nonce":"991700c41169507e6ee560ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"bd01898a5cd73abb69cc6e62d77de48add916c21abbf33b6d797dbd20c8db47cf1916d0f2b8b4006a03404306b","nonce":"991700c41169507e6ee560ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"378c0af9cd52b764c11760c8ddf073400e226a1bb4d014fae193165ff04b580f5173bf34436defd7b5ed1ea055","nonce":"991700c41169507e6ee560ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"44f0b7c3516d9194e256ac54911fed4ca7a0639dcd80ca238fb0f81a4e8fd753cd18f5e697954e4cae5ced1210","nonce":"991700c41169507e6ee560ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"f9317f722bc3d40c8b23cc40c9a1eda45d7d1d6d4bb0161efa500afeab66ea7e000717c465ef973242fc4ad441","nonce":"991700c41169507e6ee560e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"2e3f08fc9cd005cdffabc144af32c028ea163c102a7b907e2463949cb2d92865359a71e301e2c3083a7e4d3a99","nonce":"991700c41169507e6ee560e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"15fa0e8ad90da5c0f71be96bafb39b5aa128be4c36c02fb984e3ea810e7aaa7b320a7cafcacaee1f0db5990ccc","nonce":"991700c41169507e6ee560eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"3b5bb66a128dc2a8fb1c70c115eeff51f07011c8db1f1b1a2abcd6745111eebdcf4bd2e758f961d0583e8dd3b9","nonce":"991700c41169507e6ee560ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"114732a93143cd71aa7af4dcc703041b6674e488a7239c2475bc359c8846053c18ab3248c7c38a6430efdbb271","nonce":"991700c41169507e6ee560e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"4161a16d6f02c70fe1cee988d9833defa85ad196008df1d512b593aa800bfddccea2a43835314d19a84f5c8423","nonce":"991700c41169507e6ee560e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"a15820a9908f66dd54ce9e2a0ce2a2c46d497748d2c69bef7107d56fdc1b1c79e5e593fe32b1b309f3289986d7","nonce":"991700c41169507e6ee560e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"864109ede24ac46aec440a5a2bafde7dabbf3fd1282957818cbe6aac741b06fc922da48bbd81944027e1a93264","nonce":"991700c41169507e6ee560e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"40d32f16b68c8499ad00139b89fe3c5e7d0f2a9c6831b6931c813149c4fd64a5f7d912eb40d1ced6bc87fa5787","nonce":"991700c41169507e6ee560e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"e7447d579a9661ac2ccdb99f109617b38805c03d59557542343a4f40e801499f16181ec9547f7c1efa665c8563","nonce":"991700c41169507e6ee560e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"9f639511f5b05c33aab73cdbf853f364a77f1f1ab173d9fa549186744bc025ae4d46e3e1e6533260b9b3c2da53","nonce":"991700c41169507e6ee560e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"d66601983d424761bf8ed4a182aa8981d423242a580c4a56ad7028145aee1895d84fa9c1e07818a967e4360f93","nonce":"991700c41169507e6ee560e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"3c31075a68de97a6bb8e8fa6caeb6848f0b8e9b99bad1ce2cda6da0a2fdc8d56f9b28d93d57b5f779362d8056c","nonce":"991700c41169507e6ee560fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"8a23a0b4b5bd439b5a21616dffbc3a75b2ec878e1125105f32234f31a8769bcb1d85aed026905df285a6783d65","nonce":"991700c41169507e6ee560fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"8d43625a4b911f47abaf716d61c8a075def1a3224383b18b4d33c6de8b239e76a379c5238ceb460315992f9554","nonce":"991700c41169507e6ee560ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"7e7b947e849e43c9d0a9bfe36e749eb1b8f94a69ac3e1ba45319df61c9ae0bc3cc9045023542bab7b11f93e00c","nonce":"991700c41169507e6ee560fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"406dde2311374e9c62c94970d718f738863eaba892439b5ad1f6299ab9b98e8bb79c4d69fafde09c73063f2c54","nonce":"991700c41169507e6ee560f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"fdc9e54ac8ea68e6e85ec0bcdac48711e506ab8e87ea4d9551bb805422b6d3392a557e50274accf2d725823c20","nonce":"991700c41169507e6ee560f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"6aff469f1f2150d2f79028a6612181aff3affda2ceb6873548cc0a60a9d1c40c4e7b2f6091301710f6a75efabd","nonce":"991700c41169507e6ee560fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"e19df850b2e5d69c0b2ee75d8272920d891418eeab8ff4ba4716742531833c0177c503ad8b9591308836c9c4ec","nonce":"991700c41169507e6ee560fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"b7438bfedae61395346f4cc005b973f73ecfaf334f2bb588ef4c04db364a02f39506f1aeb3f5f670bf24d3c749","nonce":"991700c41169507e6ee560f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"227abcad2eb23c8b5a57888b1537b7f73592d3a14382824f91bed15ed29651a64a67e29d40c6eb77f2b0c12610","nonce":"991700c41169507e6ee560f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"79ef03e1e0e8851442c57874ed3d88941f03bb2c4b5584c30311a72a8eaa41971b83f4981fc18dcb00fe67cf59","nonce":"991700c41169507e6ee560f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"6b6595335b4f608084efba09ac17cc450e2325a3f85d94f280fd8318058b41a6249a0c8f8e77345f4be6ec8277","nonce":"991700c41169507e6ee560f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"29bc0ee08e8562b0707268f0dab33f8072d3837ca85b5e8b18651ac6bbe0c73a6dbe345382a5c4f4d819883d93","nonce":"991700c41169507e6ee560f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"3c68fffa5280f59bc284ac5678b5617867f2030c136d0c51da0df4bef3c805266fd3b8652cb473faa4c5b761e1","nonce":"991700c41169507e6ee560f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"5dc39b5c7b5b6b746f4c179395ab5c6b8c678a9c817549e5ca5cc97555dd03da04ca3967d3099e31c3daefa738","nonce":"991700c41169507e6ee560f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"706097d0fdb2485330b4f05e13b775bd7dca86c7023f2e4212e059b63c47d4a3e433d8e48ce4490048d61cdd9f","nonce":"991700c41169507e6ee560f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"11e683139b5061f3017e4ec0415c0d31ff94ed45a96e5a871a8a6e4b1aa6d667ed762ab393206270a29970d274","nonce":"991700c41169507e6ee5610d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"6d00e1d04e62a7581cc6ef222a85c505bc55fa366188d3d1f0dff0c7b5529130"},{"exporter_context":"00","L":32,"exported_value":"f85d328a79b510416f9811d29f2a73d64b52dfbd892e0f2c8b2040cd9a0c7eb1"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"52686bf245d640bc3e35a8c8230aa4e6765eedab049edb438f66e3bc64442708"}]},{"mode":1,"kem_id":16,"kdf_id":1,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"e6ea53d940abe2f08af1da06622e309396e4d7d218c41d00b9eb82e1c3637531","ikmE":"fe33f50c45015f93e3e37dd270c3c5b039d4aa01de88227afffeeb8c3c6166ce","skRm":"6e930d13d90ac31b5388e6409463b5731208882d738f67067060eda4e484655e","skEm":"8299a99a0d429530be5436c4730a016a99b96024a68d239a1dcbdfc5a4ebff77","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"04679e98f97235de2d538fcaa40dc1d918cf66e49843ee03858561087849592393588a041a9d3a213f349bfbaeb615e3e7a1c43bbd5685b826ac70b0d020efe947","pkEm":"041c2ff4daf657e6b98689468fc7e9d59f8099fdbdb472eae4f877fbee6a78aed652fcadb6858fc54b1026ff26c1cde00fa8b0266ed47bf127a3978371e94be85e","enc":"041c2ff4daf657e6b98689468fc7e9d59f8099fdbdb472eae4f877fbee6a78aed652fcadb6858fc54b1026ff26c1cde00fa8b0266ed47bf127a3978371e94be85e","shared_secret":"44eb1433b722fbe97df1df2dc40dd54b9057774cbf6f2bc2f14b889e6a808acf","key_schedule_context":"01622b72afcc3795841596c67ea74400ca3b029374d7d5640bda367c5d67b3fbeb2e986ea1c671b61cf45eec134dac0bae58ec6f63e790b1400b47c33038b0269c","secret":"28b21c7a59645e4cdfcc4c0e28b4d8777fd0ae25b8c60da9f25202df83e7754a","key":"21e540160f6bb520d0fd423e4f65e23aa09b859a0cc533df445452bc01a31e2a","base_nonce":"8d5058f6faee855e19fb6e40","exporter_secret":"465070d3afe9e5e6c3dc92b2ced7d2575f3ff6b8025c340795ea1ef24c182149","encryptions":[{"aad":"436f756e742d30","ciphertext":"fc2ec19752defa8eb833ffd9fa2528257387af4022685bd4236acbbfae9802333036d599cda9f9d2448475046d","nonce":"8d5058f6faee855e19fb6e40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"98fbea1c17fc7c3568b4c720b5fc83ffdc388e000179e76d4d9d48113e4f800b30d05ee098596b94e9d807e6f6","nonce":"8d5058f6faee855e19fb6e41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"b5b6851d940fcd02a6fbbe319e7f1ddae826ef8536a13c8cead1cd0056824e0a474a51e4ec4120ae45bb7e830b","nonce":"8d5058f6faee855e19fb6e42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"6f42702868112c1c64088a69eb5a1052315b09e6287095c323987f7dbc401e7f49f91830e7db94b6f15bd03c74","nonce":"8d5058f6faee855e19fb6e43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"9fdb6c9581abb2973b3674ce7881292ce01dcc014680cfc6740c2ca831c12b83c09647b55f7134b74809c1422d","nonce":"8d5058f6faee855e19fb6e44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"484ef08834a9d6743a22cb44b5fec1354326b25b6177451a4bbaee0fdda9963592f3091ea628bbeea4a8beb644","nonce":"8d5058f6faee855e19fb6e45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"b20161af9df6521054a0b218c4e32f54fad7bb31ea1b16793bc90a13f4f5cedf4a4e2b236b3367c2252f1e72d5","nonce":"8d5058f6faee855e19fb6e46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"046440cb89579714ac351b2a466252c1a541bd0897de906fe19016831d18433535af80bcaf5c5d52089ccf12f3","nonce":"8d5058f6faee855e19fb6e47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"8a392726a304e4b4b83f11a5c99d04468c2fb2c7a4d77e5bfc29e8b7a4254df77078df0ba4fb16a520e86f5363","nonce":"8d5058f6faee855e19fb6e48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"382653faf9643412c8fe8f1a70b050e7ff73803b4d3c24bab6eccca94c91bbe51f9437cf4bc167347b6c262036","nonce":"8d5058f6faee855e19fb6e49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"d9c5294302a96ba98f0063b449042b9176169251d36c5e1b4c309b0327aa9fe6c0ffc646aa8dedd7d08b85a24b","nonce":"8d5058f6faee855e19fb6e4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"4da0e03989f9803d590f97853ab6ddf517b13186ca2955ffc6e9e288736a33edacbbbbef874a30b970e3a5856a","nonce":"8d5058f6faee855e19fb6e4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"aab65f09ffecbd3ad57809d6dd91468109c161d9e19d7fffb8d5218635241af627b2826d3cb515a57ab57bf86e","nonce":"8d5058f6faee855e19fb6e4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"db2bd402412cee131529427497075ae22dc5a2f542e3e3c2941ca95ac0c2f5dc3bf80546c57a05948d9ca2e650","nonce":"8d5058f6faee855e19fb6e4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"40abb0e2e6123f915a19ea217996d0303538273a9d36fa7123e7830a47112a68930fba8bff87cbc5fa85713e74","nonce":"8d5058f6faee855e19fb6e4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"a2ba765a17bcda08be563204982c4afea6fb7e42fbb644ebea0a25d61b92acc59bb89dae17fdf29fa28f735112","nonce":"8d5058f6faee855e19fb6e4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"e7d1d22ee8c951fbd21ffa0d5d98793afd50b82e2d712c7ddeb689aedd570c8a2c1a3d7eec06147a3c5feb642e","nonce":"8d5058f6faee855e19fb6e50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"64fc87b17cd03b31241fced35e8c1f1b3507ddb40a2c21f5fec9266261f13637bbcd572bcbcf33574ef38861ad","nonce":"8d5058f6faee855e19fb6e51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"02612758b307616ac7b8e2f4351b7965d11033eef7e9489294d39511a495f3e278c513eefa1d11b02cc0ce8101","nonce":"8d5058f6faee855e19fb6e52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"f5cce7b55b141a6c56a788239cd35985cd5c26a0ce35f860674b55c5feb2b2d124025e4f70da31f7d44598fa47","nonce":"8d5058f6faee855e19fb6e53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"6b0b0c4fef7358e678d1c8b1364712e49cf51630522846b2784342c0dcf1efa650dca6ed0f9f82292f911d47c3","nonce":"8d5058f6faee855e19fb6e54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"ef47e93ed68f35de08fa9523dea0f4b01351351ff7be0c153394e7fd193474a715d01804c6383e6b0f02222c45","nonce":"8d5058f6faee855e19fb6e55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"5787b92ca1dcc52fc41185f0180e2cd7cd7b6cbbd540d298f7de6a62f497e1f9033bf79c491869550e53fadffe","nonce":"8d5058f6faee855e19fb6e56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"6528f626d1fca5bbd4429159786f2c1ee50896c2787ba8cc1efa5e163a48b00ae0590ce1e11662313914ddb6f0","nonce":"8d5058f6faee855e19fb6e57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"c86bf28310f2009c1cc2533485bfe3f100935d6bf94393e9b70466eaa96eccda28ae62610de1295cf501945f3b","nonce":"8d5058f6faee855e19fb6e58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"e5df840e86a6c084ddc3eaa033c0ed1d01fc6435382218fdf9e293b3ffc775a93da95e4acb2c3af839c4d547f0","nonce":"8d5058f6faee855e19fb6e59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"8355f7febae6532af3783fbc5e0eeeda4b44d480332131bc30346184c03cb5cc2b34eef49cccf214f2589b3886","nonce":"8d5058f6faee855e19fb6e5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"aefadcad194cb08031d47bded7b26d5db7791667c5fc981127de5ffaf596faf4b2c229cbdd71c678c6d98ad0f2","nonce":"8d5058f6faee855e19fb6e5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"eeb1a6662b53cec13b2a02f62cd184a1307d46abc11660a0b3eb1a21ab8f4adee3921590cc4c1645f054b6fa58","nonce":"8d5058f6faee855e19fb6e5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"27beb8ef045f54917b5e3e2e77daa75909258f55aa85f881a8178c9f8388c5d7070bbc86cf083e53a51f792feb","nonce":"8d5058f6faee855e19fb6e5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"5675b8d6816ae0fb4a3185b42420e8f0b16c1dff067c1886d86e85dec2057b4d7baea72542126928aee5d9aff5","nonce":"8d5058f6faee855e19fb6e5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"aca7c756264e5c63390f50039baf1b6190ac66b958e5170209b35c8e70c300305d91873e3b297d1aaaa24a87ed","nonce":"8d5058f6faee855e19fb6e5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"d7caf27e492dd6f3486b0acd1fba8d1599f2f4a7c5c48ff867b9eee47c0d8cbf3c7f78269ee984654d31c9b7d5","nonce":"8d5058f6faee855e19fb6e60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"143de4830b5ce7acd2b71c4e163c77fc79441be55a5b03fd1556eab1d521cd18c5df241bf38d6700b8152ebe53","nonce":"8d5058f6faee855e19fb6e61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"c7d8c9c662f06c53e9cd461355d8b2684ed92fb6438c331c3c102172b2c5ba2cb9f5f83f15803d0413d2423a38","nonce":"8d5058f6faee855e19fb6e62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"270e27b9704370bead1030aed07f47c9c6c3da57c9c2878d3aaff34103f30a890f234e259d65f2ab79852bfa5c","nonce":"8d5058f6faee855e19fb6e63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"c7cde1013e1ea4f67b291ea1051d09c49fa42ab10cce6578fd798b8fac79f154bffdaf3468551d74ca7b2f0c96","nonce":"8d5058f6faee855e19fb6e64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"2f956649f6b769bb66927bb2be5242e781a91dc45d621eb04b4f44384a7ec976ebd0a26d0faf84642671ac822a","nonce":"8d5058f6faee855e19fb6e65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"275e174c71bf796d6e56e1e51486802733be5b1bcb0e550e936b7e54e9483943a251fce4b9683c254f52f9563a","nonce":"8d5058f6faee855e19fb6e66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"988c115b9329d9f4802f893073fa91e5bbef8647504317bc3e244a6ca443a0753da414d1f5bc9a50c1ad1fd43c","nonce":"8d5058f6faee855e19fb6e67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"d4d876397185d49aa9473e38b65016b120eac2a71035b0b6fcd7212fa0b35f8cea89ec6ae7b3edd31b01f2266b","nonce":"8d5058f6faee855e19fb6e68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"65a761ef5ae9f3a3bca6e12e100663979cb42490ea1bf0c49591be70fc24c1ca34cf50ed1c3131e881d7b00c6b","nonce":"8d5058f6faee855e19fb6e69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"4e636d0260f5986c57a4aac89a305f818989bd81a02eeefd898f1ec591700b7a02f40293234517fb121a31d5a8","nonce":"8d5058f6faee855e19fb6e6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"0350e17236f2069bb961485905368ad7e27f2891bcbfdac6266b4ade01be831de838f7b1c6db5534359b4c526e","nonce":"8d5058f6faee855e19fb6e6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"6c8921a8057f7effadf81aed99d4d19ce36e097f8ae84ed3f9cae62c98c3007f5faade8bf2a0418216dc1874bc","nonce":"8d5058f6faee855e19fb6e6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"70411cd9cd34034340223fec8fa40b6bc4d9c30610bbf7f5c11aa64e08d7d77073bd83b40cafbe81b1d739ab2f","nonce":"8d5058f6faee855e19fb6e6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"adc44f1a7f8bd62a8952fa97b9c4cedd7ebec49ce6fa27f200003ca5a68eba54b59a625b34d8c863cddf4136dc","nonce":"8d5058f6faee855e19fb6e6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"59090ca55c5364d9a743dd13be5e3510f1872a49266ddf6ebd82bb4be8eb0d7d3a9b5dffc838faa40c606706b6","nonce":"8d5058f6faee855e19fb6e6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"1434e11a869b60281a89cb94a32fc282510cebeba799912dd9e501bb6d2057de01bfb1550c6823455dfd24d20a","nonce":"8d5058f6faee855e19fb6e70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"fa7a14e8c05dd94cef1a3ce1d2831da3167591721be95063891fa925be92940c70d89b4995e8000f0190efaaea","nonce":"8d5058f6faee855e19fb6e71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"a87f632097f3fd5235082dfe20234439c115f44dd58b0898a91f5db447535f59fbf7d26a17014b49ec8b88c3b5","nonce":"8d5058f6faee855e19fb6e72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"d38bcf8972bbd0a00ec2c4410805d3a7532562e8a52884a4b70370e4a1d3d61382a73ea2b5074dfbd5eea1b137","nonce":"8d5058f6faee855e19fb6e73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"a1eb66f85813b9de3e36f3dd444ea208ba84352e5fc25254344f0d5b9f3dd4b7c37671f25ad8cbd44cbe2ddf8d","nonce":"8d5058f6faee855e19fb6e74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"f9ae3bcf9006c054ca5dde9f6bbd55231f7f4ab3b03aeef3b953a24b2e3864d2adbc3a851cd5fccc93b1d7db13","nonce":"8d5058f6faee855e19fb6e75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"68e44bedc39099fde9d20d78a7cf23386cfe5cbc25b375709b1aee69bbfc4d0905a0e545955668cd3844d87b36","nonce":"8d5058f6faee855e19fb6e76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"b84ec0ac389ba3f6018865d81a84d91068103113fcc75e0bdb79d3834e917b17ea194ec58920109c6a35e62b27","nonce":"8d5058f6faee855e19fb6e77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"87417a5f316c9d2f1ffc3805e531126b4dfd6b27158639468cb08de049576790926fe6d9cee59db17a51f94f9b","nonce":"8d5058f6faee855e19fb6e78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"130da41303bafed5e211a527ed1ce045e2b6ae5c1a80cc58354431309b7c92ac53720ade1975dac83cb97d982b","nonce":"8d5058f6faee855e19fb6e79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"414cfad19b00b064ade6eaefd7fde2a7c8730c9b7f38ac4de0b4068a5b53d70bcd40aaa15cf0d5551d40e8237f","nonce":"8d5058f6faee855e19fb6e7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"7eb34975eedc680980eba1474cc77314cbfac0c109bc44e45450b4eec7853dfc38d447504de43051fc3b0778b9","nonce":"8d5058f6faee855e19fb6e7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"ec6380296df93a701229d9cc6678daf9352357846eca003ef9d021706ae94f4a7f405dc576e0a754e31a788f3e","nonce":"8d5058f6faee855e19fb6e7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"4aadf031bc0ba0d05abdbb066e28bb4125b86d0c01952a9d6159b84648fc476fa7886e8153de0036638fd84db3","nonce":"8d5058f6faee855e19fb6e7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"10a75a92268d536a116a0dd850fca8bf04b40b0bc62a338524fc05009f9d6352cf7a05e9ad3616f46fba578ff6","nonce":"8d5058f6faee855e19fb6e7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"bc200cc20d060e35379853930462dac8aae418303a14f007565a8ac1a93397ada7aa0431f68cce7047a3e5dab3","nonce":"8d5058f6faee855e19fb6e7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"f4c877d152eeba2ce7b5048f0551f62c62b9c6bebe3cdcac99efa951cadab35b78cc7ee50c9e44d2f3ee78bc42","nonce":"8d5058f6faee855e19fb6e00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"99b741c612c712825fae3c7f82efaea3560b1cd71b81020f5cbf71544dd54490c1c99237907c427c7d04203bfc","nonce":"8d5058f6faee855e19fb6e01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"0a5d7f9b00577dbdd23b9dca30f21d2d0a7a239af51c3b98bd5ccceed9cff2c7d4c74b17fbef9c07438bac725d","nonce":"8d5058f6faee855e19fb6e02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"cba7dc86e40e2ca6c0ff34b7e71c0708fede4bb16e74bf596c024169dbf66aa307801e43b3e7d0e83c59296b36","nonce":"8d5058f6faee855e19fb6e03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"e199aac84fd88fa09b5578d3d99fab7f3f4df445b0159b58ca6475df37d4b012ffda9d2a965d648dcf392c0d70","nonce":"8d5058f6faee855e19fb6e04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"03bf076383dcaccad7b8ec0dac7ec43a6c889e155a6bb6cc7a385d0dc7241ef5d172ecb4ca4164f87899216ea0","nonce":"8d5058f6faee855e19fb6e05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"05a5131552a9b50fc2afa52e3f1fe98e25cd520e57f37a3df3a3f271b3b1177db374ffab365ca77324fa952925","nonce":"8d5058f6faee855e19fb6e06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"8e54338337eb9a18ad1d644fce4a36165ff0780d51e37c7fabee89ee0735bdcdd6ad81ffb1f5b4a33c82fe8414","nonce":"8d5058f6faee855e19fb6e07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"c9b700dba788271be72f60bb97b2354ab33a50a5f46210e9821ebebfcf2bf758b0a0d3c56cd231c30a251692f3","nonce":"8d5058f6faee855e19fb6e08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"d9dff613efe62480e142505e34704f177581d8f233773de8ef8a02f9060c8de0d4b12e92bbe64502c4d6e4904f","nonce":"8d5058f6faee855e19fb6e09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"9d531d7d2b2bc8f71fc9e5551e7098a29561167b88cd39b3607d5d2f1ad144a2c86f02a34f18688b4175a5966a","nonce":"8d5058f6faee855e19fb6e0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"7fe3437831db6dd3c124728f9efeef1a806a7e76b2b2c71efaf8bd35043a06cadb727d95f20f21f8a13c087e97","nonce":"8d5058f6faee855e19fb6e0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"891e56c95902a1ad67ea344b8cf405d0b70fbf65a75a87c82d31487b9ac0e6dac445f34b5e7780990aedd5b6d9","nonce":"8d5058f6faee855e19fb6e0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"c1251b0924f6950df9e54771e0a0862b08848ad35d2f43bb5c43ad1a102e318defb62e0b4bc7059e4d8dc5221a","nonce":"8d5058f6faee855e19fb6e0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"5d554f2e936c018cc78de5a4922455fa008131893fda54a1cd6677a816607308a165097fe391916c60728f0bd5","nonce":"8d5058f6faee855e19fb6e0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"bdfb775f78935f990b61e566c57104b331ee5c85cf71282c00bb4b7ed43c8aa48cf6383c1876a335ae136c835f","nonce":"8d5058f6faee855e19fb6e0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"353184dd04cd187966ae4830a5be7c2e668bec1e610ba302a5da3e4f09b5f9134dead58ea0617da9a116618202","nonce":"8d5058f6faee855e19fb6e10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"bedd2842c254b234d12dae282dfb839994a76a4f8e8871b368947d68d29f7eeedbd75d5ca9a470ddf9f3db30c8","nonce":"8d5058f6faee855e19fb6e11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"5692b2b571f8e978a80f810a9e347b811c73e745ab702fc74e25a515a22187d28616923a9cc1e9b6d76f7708e2","nonce":"8d5058f6faee855e19fb6e12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"29ac923c56db748128261e048685000dbd38099d3e2c94a28590f3ba71a0c29fafe19a0b424bd598880f499496","nonce":"8d5058f6faee855e19fb6e13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"84b32dd5c4bf598800b1a4825027ded6c5886d124c08a58894caef4ca2e17cd94c162bf2ba858a17c5f6e5fe14","nonce":"8d5058f6faee855e19fb6e14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"07e51a8622f8be295a6c72f2a73f6810375f6e86039993544a0d7f8f2137a395ac182a05effd484954efee7f6d","nonce":"8d5058f6faee855e19fb6e15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"5042141cd5b20f32e44965be72e378d0928089075d0004baaf09235e308ea062c7a84cdf58f981be78adf0aec4","nonce":"8d5058f6faee855e19fb6e16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"7480d0af5b40f718de6694f3d2f0f5b072e2bbd217fe7dd4c0cb4a1c93b20c4b70a069b05bd96ea3e9731019a2","nonce":"8d5058f6faee855e19fb6e17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"9c4518bc85fa0b249234a2be8b0292c952c4b4a0041890a18c2c672a71558c517de79b1f0d974f54fb15b7483a","nonce":"8d5058f6faee855e19fb6e18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"a504f304f8813810f6450b2d10dea43a91d69df125b8e06c31341c8b8fd16398494750074bfcc25a01dc1e6390","nonce":"8d5058f6faee855e19fb6e19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"549816773565f1fb6eddbde921f091c796eb99a9008ddcfceea5b1337984eb8b4adc54710cfe57b7ae8aa5b33a","nonce":"8d5058f6faee855e19fb6e1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"5bb9df96cf09bbbb9cced72fd589897242e63a5589d2032b6b425d6fe50ea5f1b436fd5241c83426bee97b3d3c","nonce":"8d5058f6faee855e19fb6e1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"0614dede7998d9387ea729b24899401d5eed2f6605e3c67814805a9d6b80659030b0efee2c39fc9b2e5dc48fba","nonce":"8d5058f6faee855e19fb6e1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"e77b6e962e2ddc755fea5fe4c4ae6dd85ba200a82ee841859553e4dfe8455cff21b7a2e35986ade31af6b76973","nonce":"8d5058f6faee855e19fb6e1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"463d0fd38f870b54e9177bdc68c8fee3836c17bfb762bd25793b40785524d30f902bc9da033c0eb178b35572c8","nonce":"8d5058f6faee855e19fb6e1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"d0efda4414efc478abbcb88dcea4356d458a0ee34f0405c6b63970153f5fe3bbad8645aaf32235aad2a9c882a6","nonce":"8d5058f6faee855e19fb6e1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"dadf6314e9f6a1a3a664b8940c787796fb3866db27256963c37b58dc6e500c9346a9b6417c36099cdcae57f73c","nonce":"8d5058f6faee855e19fb6e20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"dbccacb631bde3a6a50ca5d7f2c371463ba621e00318b94ee6b1ceba30a40ec4c7adec37d4652b0d721cf40790","nonce":"8d5058f6faee855e19fb6e21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"9f04b670741dc67ce263028d0dcc026c574d77575f3fa9592442885526de97b62e2826d410df8ab078d56e3b85","nonce":"8d5058f6faee855e19fb6e22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"7004ae2a4891534285654a56fcfce09247a2ebcb1a34370fac93ef7c91559556140bdab2c5b130c2d91dd5ca33","nonce":"8d5058f6faee855e19fb6e23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"8c755c67295e488eb8fd24c2e30add1ae151681b2a0fe85acf371182c62f947b4cd708d8d5c0dad510003cfd95","nonce":"8d5058f6faee855e19fb6e24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"2e1ad11e5519147991c6c2bb7fcb480729b36d2c78034191e79a169cb8ad7a714d2ddd371eb21f1fa49fabea72","nonce":"8d5058f6faee855e19fb6e25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"029d30d9f045e0d71f7d6323126c8728a234f737628522698393950aa713b2cf93a96b7388d0fd3cabace14773","nonce":"8d5058f6faee855e19fb6e26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"977e754e4ac77a5ab21a8bd6a099dd31c193b0adc822ae8d3afd70080ff377db6acba81f4dded508f65a01b108","nonce":"8d5058f6faee855e19fb6e27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"97550fc9e78515cdd3af143b504f96d0de33cadd21deb64aa2234309496da3f63bf1786fab568924b6f81a4f06","nonce":"8d5058f6faee855e19fb6e28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"6870f249d7ed557119e5141258b4abee674fbfa9e5c0874eca13bd9740af618377aaad15c2359c8e03c92cb751","nonce":"8d5058f6faee855e19fb6e29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"4a835ef999cae0303beabdcd160ae32ede9a42d9cbc23323716816cf5e0499bdad28c54709a515ab01859a5c61","nonce":"8d5058f6faee855e19fb6e2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"aa61d07e029f7f50b38c79f280a22bf3969156dab476f840f8de6b42cf3223d102b77013d09add628def81b451","nonce":"8d5058f6faee855e19fb6e2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"4a62426c85075436153b3449fa0b04c70c49d139bd37b7a29fe16831b1903896dbd0599ac89f3c14fc155c7c9f","nonce":"8d5058f6faee855e19fb6e2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"2477ddd419596aef50208247d3b74e211deb0c0450348c7e70da3d57c692761bf64d932c54c8825c4a8f65bd17","nonce":"8d5058f6faee855e19fb6e2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"134d3a7384dba5cd02b90ad481082d38ed7a6b7d4e1b7b832d08fa5667f6cbb3602acdd9660775b50b6abe62aa","nonce":"8d5058f6faee855e19fb6e2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"c653dd4bf98b8e3e21da57567e87a3fe0f85b21c5a98ed37125e70e3696cf98c7f62ad48e56aba85adcbc2b7b2","nonce":"8d5058f6faee855e19fb6e2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"2b1ea7587347c25d95eaef1f014646204862ee480f2bb92bf41cf7480d0c36b06f0d2d7fec2f1182fa1e373f80","nonce":"8d5058f6faee855e19fb6e30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"7ab6a40a799b95decd97100e2d39c06741408813377bb92007fb52a2c40e59cd39af9b4a939a4165fcd2796eb1","nonce":"8d5058f6faee855e19fb6e31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"349ae0e0a991fe0c98144fac010fb47ca6cee30bf2bc72d9d9a30fe6636d95f4d052f63c124ece68255c4fd717","nonce":"8d5058f6faee855e19fb6e32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"649c51266bdbe8d14078481e91e8da79e987f6408e50b1ed2b429009071120a58d2ca1536b4569e7e0541d324b","nonce":"8d5058f6faee855e19fb6e33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"125f8b08be9654df3755bab4861968851ef337564bbba64b1983ddd62af329cf2328fb370d1d1385238edd3ae2","nonce":"8d5058f6faee855e19fb6e34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"ea98fcf887aa2f8175b1f9b826e7141f7e2eb0db47b63814791f6d20cad99d960aac83a614f4ff5fb3845a52af","nonce":"8d5058f6faee855e19fb6e35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"fd866dd18f52671ee50dca0f9ca727dfdd20d49e0400224fc6dc8826cb7d3f25e55fa17ee750b4b8ab8963b58f","nonce":"8d5058f6faee855e19fb6e36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"91d2a4a603d60e5220af42f17e06b36ea2a312b8a7e9b9fd1f07fcc18eeaed0ff1e0eb5bf76ea14f5f3e298346","nonce":"8d5058f6faee855e19fb6e37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"57daa06c2384bf52921428964f525fa3845b4bbbdb554a3a27632aa59e1bf4c869d3cfa5f65799b32bd5be841e","nonce":"8d5058f6faee855e19fb6e38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"df7c34c8a5623744ec5ae3ef41c3b37e3471c99ab2d7a5699b3d62971b6feaee757bad520f8d56258bd0a24fd4","nonce":"8d5058f6faee855e19fb6e39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"73bb00e1696f016e71002d0bc735240bed20f856081717cd3db6818490f4b3ecfa3c7054b6b834f82241dad32a","nonce":"8d5058f6faee855e19fb6e3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"dcabbef50408b026f309de1bab944c743b89828739a6bfb1b8c48ab12e29480c6169acd0412ccc1919965bbba1","nonce":"8d5058f6faee855e19fb6e3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"2ab915fcd5b402faded1d7b7413de404aa56ff9ba188544f145a0f27d3709dfb345c9e1ce601e1fa4359ee9ad3","nonce":"8d5058f6faee855e19fb6e3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"665269b41cd1e8b42da4526d295138fced281c4c2ebcc67130720a61f39b5b43a8c6dd5b68d39338a07476675a","nonce":"8d5058f6faee855e19fb6e3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"f9442cf973ff80b9d05bc91f565640035b467b555e08972d9d97b38a574f5b103464961e53273dc65f10087746","nonce":"8d5058f6faee855e19fb6e3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"3f721d3002e752ac403863e68992ead43199fa28d9c439b3959293ead15a4dfbb8307847ec7376fdc3c53a8a38","nonce":"8d5058f6faee855e19fb6e3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"ecf14467ff10e2a02944bf8757349ef64fd6a43bcb608b83983b2d833aa330b87e0513d213c0a9bce5e3d4346c","nonce":"8d5058f6faee855e19fb6ec0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"b4c742828b35dfaa45cfdfeae13ea9aa174b2cce4c397feefbbb9fb8da7d59b1f73605daf4c4978c3fcd555c36","nonce":"8d5058f6faee855e19fb6ec1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"26789a7ea15ab99bc967c6db7ca4ac40ae6ec0d143f3f31d96c43e2077b99961f2f1ff30ee3537ed62908f1e20","nonce":"8d5058f6faee855e19fb6ec2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"dfaae0328fecdacfdab247143fb7364c5f7d88aca8cf075a659adf33c3140bd2a174bf7c5177d862ff010f56ab","nonce":"8d5058f6faee855e19fb6ec3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"d38958be3978c0aa75a62ae5b0b63fbb30e92a38e175c228c77386e813a9ddebed9b007b9e73d4cdcf0ea76b71","nonce":"8d5058f6faee855e19fb6ec4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"09a038cedf66f01d3de7633b00537e077812872c0a318053b7edfd97a18b05c1c23de183ed3d72d33228707740","nonce":"8d5058f6faee855e19fb6ec5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"e0658ef0a8a80227706ac3793ab3b97dd508c8cd7930b2e08f0e1e3ddfb929384adbe66a329387374653463b00","nonce":"8d5058f6faee855e19fb6ec6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"563eb03033d5eb3782d4653a0b0ef7988f9e0cf6d9af3537862d5721c8e1c25c398d3b0f695a09a45855de1832","nonce":"8d5058f6faee855e19fb6ec7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"9e629531dacb9a2af4caf2fd15e96358337bcb237e4e1eca27c6a93c410bb6681243a10267f558f0101a66bbad","nonce":"8d5058f6faee855e19fb6ec8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"9d14e2129b62d39e66456d36c03aa5a688cfc35ffe2fcc1347489c0809f26a7427748e800dbd81c9b91586b603","nonce":"8d5058f6faee855e19fb6ec9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"c5a4524088b783a9ce7cabe41a0e7ab4915c279e5b1406c4b2aff0088d6ef405807151533412013256765e1907","nonce":"8d5058f6faee855e19fb6eca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"ac561d76d1234d1da21ebd7a520f258ae8905cefab5aa5deebd94e47c4aaf27c8d5db0966ad3825b37431bee2d","nonce":"8d5058f6faee855e19fb6ecb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"331a96d9dc6d83dbe236b06a226e6a73b82767618906f53669b5509678a74b93da4aa7cfdd0172671ea6dcb260","nonce":"8d5058f6faee855e19fb6ecc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"1278093bebec7307c05eac96621ef2d29d34d6387109ab5c6fd024ffc8fc3a90d6d8874b431857359ca0503574","nonce":"8d5058f6faee855e19fb6ecd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"05455d91290d90af72008ef907ff1893fc81f14f3891b9f61758447c606ffd59a34b7334d72bd16da0c3e305d9","nonce":"8d5058f6faee855e19fb6ece","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"d554d3cfd758da1577c2ff8aa01a2f8e1cb3c3054774ea32c72dc603abd17f69bf9f798443fc85b47c0b1f1da8","nonce":"8d5058f6faee855e19fb6ecf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"aa4dc1d3bacf30e4047dfe7bd710e0674babedf6dc0d12ebbea09fb885fecf0f0c0c947cb9fa9dcc0def42e10b","nonce":"8d5058f6faee855e19fb6ed0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"72173b38eafde28d2257f72ba092377fd10b15ee68fb51646f07288fcd100dabb53db2d2e73f0f689897908023","nonce":"8d5058f6faee855e19fb6ed1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"e6e958d1c00687c0dc190f531965bd50251d587039d27a1f053131fcd3d4b7064c15ab2871970691a4ab4bae1e","nonce":"8d5058f6faee855e19fb6ed2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"85c3b406d55570475b56cfe59d9e6c3465252fe9165d163a26568ced466ad198905b8e055cdfa2c4c1b4a7f99d","nonce":"8d5058f6faee855e19fb6ed3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"4846c6f55977cf0e18e0384ca9bae51c4177c9c20cfdbc426d3e7c60c6a4c6f6f201361cdf4932f61c9165a28b","nonce":"8d5058f6faee855e19fb6ed4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"e3ace50daed1a981ea74424da4ebd5b08e616a4a50073ae8307160145a8428d3a5fab2af4a499ec3cbc69b058f","nonce":"8d5058f6faee855e19fb6ed5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"46bfa251c40fed2acf6ef04a68b45a316f0b89d8234e6a850c73e570855a2437c47f2fec65e8953e198918adc7","nonce":"8d5058f6faee855e19fb6ed6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"f93bc265dc47e5cff73774b9e96b12fb1cd544d19fd0a4bc52aa376d6ff76f477b316d1796c3ef7437398ef457","nonce":"8d5058f6faee855e19fb6ed7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"e856a11510e6287c07f6b789e36b67d1180cf1a5bb7be128b7750d80401af4df579f58183244361c68477938b8","nonce":"8d5058f6faee855e19fb6ed8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"302a58fc0e1de3b2bdd17f68d1a62246989f64dabb07be17ab8fc5e99dac6b4b0906fd173664c8c75511d2be71","nonce":"8d5058f6faee855e19fb6ed9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"634709913dd6395f9bf1e5d2ab77d3e67aa92197484ec11931c799a35155a9bad1da33f1dda685fb56c641773c","nonce":"8d5058f6faee855e19fb6eda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"ad82c0ee4d01ec6c0782c2230a46472f644ab3497d6822c8be2809b93bb1553384907a181bb3cf44cde38eb363","nonce":"8d5058f6faee855e19fb6edb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"ddb28f7c729ae8eb2e936bd17a50240111465931af8aebcc6bf1225a4aa580fd96c64b47c1bae7167857c82887","nonce":"8d5058f6faee855e19fb6edc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"68b813a5fc575898d64688b2f3c6a8c1a64bb336eef45d0be3fb33f1ce0b905bc7a9e67c447f6aa614645a5d39","nonce":"8d5058f6faee855e19fb6edd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"15745b2a398171a0db842fac91169c10dfc70209ef5079d3f5f939e45f0ffd6f0b60ced2a61e5b8d4b3c037ff8","nonce":"8d5058f6faee855e19fb6ede","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"e4d22b4d6198b6a0a64a59cb552da3d9a4b271c8fed00620930453192ee87917645bedcb9ee445e33599cdac03","nonce":"8d5058f6faee855e19fb6edf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"e2794b777abc43fa62ad330214c320ddd727c60ad80b73b1e803890541903c98ca6be2b8ad6f5e43c676b1bcd5","nonce":"8d5058f6faee855e19fb6ee0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"028209b3634cc9255d77efc84512a6c9b8c3da2c0d1552a25cb68c2eabae1f8e34d1c83ef794a98f3951ca48da","nonce":"8d5058f6faee855e19fb6ee1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"625a611962f2a81cdf17b1eacc0db6c32b04ea9de1e2deb9579017af58852973066a90ec3133540bc5ed482213","nonce":"8d5058f6faee855e19fb6ee2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"9c3949b14193c619bf8c78be5dd02e782452a73567ac57abafff98c740d021979dfeac407a8ca3eb8571f679a1","nonce":"8d5058f6faee855e19fb6ee3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"4d981960b88ad02a4fb105a639bf5c93bb201f8c1adce82e2c4f93e21b841b1bdbd3c40796a6d255d08c5362a6","nonce":"8d5058f6faee855e19fb6ee4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"01fd24cbcf8ec46cc1c9d2901f8dc2b1bcf44d29995f299c65ea3167349b569ff5d64b361ffe4b59cdaa582b1f","nonce":"8d5058f6faee855e19fb6ee5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"3722689c6b2c132f660f1cc5015d24fe275dc9e8b39e9591a1c94a1f2d7a91026b312eb3278025d60eeb447abf","nonce":"8d5058f6faee855e19fb6ee6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"c8362d5721a95345e9f111c821164424bd1a3fd30c82451c9d201b93f16125bd0e8a7975400993ea64236bda44","nonce":"8d5058f6faee855e19fb6ee7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"7377e1860a9a56a0a82d536cf5f0d462faa4b1b530199697124c9e5ec5fb687502c555dd582b17c6c43b31e46f","nonce":"8d5058f6faee855e19fb6ee8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"7a7e73c86f6ca747e9373f1aec61ba1622d6093e08f9eccd1222081ca9bee4499d03237ffa32ffee84e31dd743","nonce":"8d5058f6faee855e19fb6ee9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"e0f2ea0cc5c2391352f423d865f7cabf21c2e344c9f8a313201c60e048b1665da110d14b32ce7f6c4693efe608","nonce":"8d5058f6faee855e19fb6eea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"b97e35e245639dd0e4b9e7b9a3fe58b486ba5849fcfaa12776ec6e21dadad3126ec5f0ecf08e0adecb67148ef1","nonce":"8d5058f6faee855e19fb6eeb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"cb1bf640dd284a52fdfa739e68c167b07e9a443b1baaddf21eb2858507e88935aa2d63457cbf49a57ca2f9e4fc","nonce":"8d5058f6faee855e19fb6eec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"c236b30e75ad8bebb79a8881c480cb988f644b2ac883b5ecf2496663c23f39ddd99a85d7bcbc0f88c3bb7bb7ec","nonce":"8d5058f6faee855e19fb6eed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"971a48369ce402037f47bc73a6ebcd3e4865e9590a110bebfa29a8df6d09bf8e6aba6300ff66689cc47358d8be","nonce":"8d5058f6faee855e19fb6eee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"1fa4cc79cdf1dcdc584cae2dd25db12add43c2c56cda5fa74a037cc587d1208efba469bc961a0093efa4933a52","nonce":"8d5058f6faee855e19fb6eef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"d690bcbd45949f46d0c6d0a34c94920fa77aa028e5ae308fe7405a16b1e002217e98e52bc27ee4e0c38ccc7772","nonce":"8d5058f6faee855e19fb6ef0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"3f8d79743e9ce8ada5bba03eb89cdd5edb3427d5beaa4338b8d81ca209fd9eb09d2879110ad70f34587ecc962d","nonce":"8d5058f6faee855e19fb6ef1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"96d7437cc8f42f4004be038ac576c9cc5210df3580a07552509e2acb641358b64ed62e6bca7faeaa06a6390bab","nonce":"8d5058f6faee855e19fb6ef2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"2f83f558bea5601ed26498673af7636a26be0f64d784aa5aa3ef40ddd6baf54fa9d30d8557807180806b0e8f34","nonce":"8d5058f6faee855e19fb6ef3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"5e7d2a190f694d4b05216312e43f6dd2ad519d158340ec26e6459c0d5880b24e256ea4fd3c030813ab1e02e282","nonce":"8d5058f6faee855e19fb6ef4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"42f617b5303117a51b3c663d30a2a011c0592dd52d30eb46c34e333560427e925142464c8b28504f282055d9de","nonce":"8d5058f6faee855e19fb6ef5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"a4859b879bd6b28f47f57275894e032bc7e58e7c234ec566b6a5d968b36996a9ed6fbd085f8a7a360f31769f92","nonce":"8d5058f6faee855e19fb6ef6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"163f76c891423b5ae4e20ad067df76af9c59ca1a068241411c0dcd451da7d3b321ae8ac40d1dacf4741929d2ac","nonce":"8d5058f6faee855e19fb6ef7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"d768230b7e1931541fd22449be26fdb888448750150dcd18acd95688c8c7dfaedd91d2075054e27d01addd8efe","nonce":"8d5058f6faee855e19fb6ef8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"7248d7717bb13c3149bb5baf06d70bdaf1b29e1250bb046b62b0aba7642ef6ba604118b8f5e79ff3a292cec8ba","nonce":"8d5058f6faee855e19fb6ef9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"756319501019a6d23caaa6b3b35455ba5b4580af1e8c46c215f8aea1674b654af0d9b4061fc756d1b521fd1d17","nonce":"8d5058f6faee855e19fb6efa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"8218f04cf0c9e22910154bab1614da9ce02ac75bb54412307658e92e67a2d4e792b2f29693ab41401980777748","nonce":"8d5058f6faee855e19fb6efb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"4b532730173e4a2a00d93ff8426c5b48f8deb2e59db99ee0751fcb26a6ef5f66fca25a980cd8eb99ce2be5cb08","nonce":"8d5058f6faee855e19fb6efc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"f42782567c951a2efd8d8bfd9517a422e903cdf2e013126b7a2eada7b2f5a16b3510ea8f28a9c11c363321daaf","nonce":"8d5058f6faee855e19fb6efd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"45c13bd3e074106bf8ad06e7668211e0779dabc31de4c60bd656e203ea0206ba0754d2aa5a20819f94e9751df3","nonce":"8d5058f6faee855e19fb6efe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"7925d4dff4c5c4a67b24ce72e6277a2bcefde463f0607e726735ab117b072222bb82a36ed237aa442fcfedd2e5","nonce":"8d5058f6faee855e19fb6eff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"fdd95e97cd8cc8249004d9d4d9e315769d918c6c102afc2ecdcce90bcb1eb87492378ef54256f36bd966be2b61","nonce":"8d5058f6faee855e19fb6e80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"620eb5e5e3837c84ab397032482a82ffa4921e694414acca414a4928c4dbdc1ec6174d8a9330d9feb0e37eefc8","nonce":"8d5058f6faee855e19fb6e81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"db7a8d9f8511c1475adb5873b8df212ad6821380b9c20913f04b16783d1c34362d3e42380614fc6644685bec69","nonce":"8d5058f6faee855e19fb6e82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"2d6ad2d41f0334755bd59e1be70b10719ffcefc3a9258c99e50af7ac88d718a6cb668f0ad7485384da3d8723d5","nonce":"8d5058f6faee855e19fb6e83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"e84ae085a97f358845b2da691b160232f4ba242be3335dd5c18f24a0708c346e7f535b511d791452a17ee9c31b","nonce":"8d5058f6faee855e19fb6e84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"b27fd5f84738fd96b2c7a9d9ab9c4033ea44105623ff447f167969e3a35ee8b0ccf7fd31308a7e62697897da0c","nonce":"8d5058f6faee855e19fb6e85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"e12cb247f91d085fde73a2a22320f1b7a0be6ac5aa18cf7a2979cffa0081cbeb7a9ef74a789cceefa4c52cde7d","nonce":"8d5058f6faee855e19fb6e86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"6367bc297b3687f48a8f227f8ab097482ac07b4a067225a91d825a1c18b4896ea79e46d7bf8cc3251a407f8515","nonce":"8d5058f6faee855e19fb6e87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"3d717f2e776f378b0199775ba30ed484827c00ae9bf3af8ddc6df5302b861477283e630a6b9aca7025efe7e742","nonce":"8d5058f6faee855e19fb6e88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"34cc462d4d3118827c653e4ba11a085976ff398296303a0c9d882bae8af72b79cc10691f5db50d83b98e3405dc","nonce":"8d5058f6faee855e19fb6e89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"e26ac3c3a235a33f0e2ed3b7cdecaad55b885f0955ebe236c8acc03dca7ccabe9afae9784432890d623ebdf4ba","nonce":"8d5058f6faee855e19fb6e8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"a249c599537f84fe6c3baf1b9f6b8c68840cf3537b50e28d6bd2565a2ba79fe83fe505a46c33daa69b46e1d065","nonce":"8d5058f6faee855e19fb6e8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"9f87a4641818cfb44fc36bab868784af6ede4511e63ceaf1c1639b646b7daf348dec14d7bad4c2d7cffe60cd78","nonce":"8d5058f6faee855e19fb6e8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"f194467d60d6945f82eed4f634477ee13f6f3883af3800844c176a5fd2115a59d1ab9267b4fe738f5516b50733","nonce":"8d5058f6faee855e19fb6e8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"ff6e2343f4095d0f205c82216bcfb7e56c55b3f652eba5947e07bb90949ff8206bfb0f2902897340bbdb9d62ae","nonce":"8d5058f6faee855e19fb6e8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"8ec245374444443166a1eb5484a4dde12d0bfb66f8f227a79720f9d97c518ca44287c8c81014411b65aa952311","nonce":"8d5058f6faee855e19fb6e8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"d59637a01e6990f488defc51e0e57f39536c9d84f69f04377a1e9b6f20850b4ab60bf086b6a54e0a0d17760499","nonce":"8d5058f6faee855e19fb6e90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"7657d38b09850c20d4dd563b02dccaa37d784a1d6bbe5ee0056853fc3c0a7382bf0c4090f485b93b9d14c2de13","nonce":"8d5058f6faee855e19fb6e91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"947b42d2a7cb47eaa3e7611f0678c009ad90e7431fa5445145ef7c4f46a47a1b2a436fe1a6159778a1db155b7e","nonce":"8d5058f6faee855e19fb6e92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"08aae2e968d6657e3d23664b59d5588ab5b04acaaad8b7251f86aca4e7fa04deb416c4385ffcc1a3b39b802e87","nonce":"8d5058f6faee855e19fb6e93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"c2b799f582cfdea47c5b1c1e0e3722e504fab390e45ba1eda05354db402203dc0d04fa76ec3f1518eda00ab607","nonce":"8d5058f6faee855e19fb6e94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"d6d55c1af5b02cc587675fe59bbfdf44aa0d5679e8e3c31bd23012fad73ad37a57f2e6cb5e288c426ef0006794","nonce":"8d5058f6faee855e19fb6e95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"bb9024c8cc909d0759aa26e40a2b7fe9f76b184fab3e2b5a9df20125e947c7d63f62540debb5b31890bc5b3b10","nonce":"8d5058f6faee855e19fb6e96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"ffc04cb8076ff0414b1bacbf98070fbe293fbe7e99c518ec479c452817499560e7179cbb0ad29d07f0d031299a","nonce":"8d5058f6faee855e19fb6e97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"a3b2bca2b09f87a195ff9df3e39f22f6f6b1afeab3f1c4e13dc112274f2421e6b1f963d37ada691e31d613fd1c","nonce":"8d5058f6faee855e19fb6e98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"cbe487a044c3bb1a6144279cee95bf0912f0815df317482da45ce010acbae32d946306e1d8f2e15970e842280d","nonce":"8d5058f6faee855e19fb6e99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"777e9ce31b4d1be253aae7867543edb594fe867eb4a92964628165754dc9d39270b4564cedf75f52e6ebcf8e18","nonce":"8d5058f6faee855e19fb6e9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"7ad33cea333ef9248d4e68bc37b604ba6e7a09fd472c27f5c04ba831eadabaec798a42e56576731e8ea93ddc4a","nonce":"8d5058f6faee855e19fb6e9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"c1a272654409e53e92009557c532bb5092379e57875bcee71581d81b308be3deb11ea22d8ade6499358e7ec66e","nonce":"8d5058f6faee855e19fb6e9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"609e92a087b568168e69852c34115549f66c728c6a8eae910e39ca7b52d6b09c7d26bb4a10c2616f4963f950b2","nonce":"8d5058f6faee855e19fb6e9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"6f46c5bf5ddb0be118c9e1627ab2943373de7e2252ac727d924175bd855616ef298f615d1a552b4124bdced10f","nonce":"8d5058f6faee855e19fb6e9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"a3b810450f1495ead6726de76a620b9bff506061e018122abe57bed939d88f83ff9fd9a8297630686e2a5b9f99","nonce":"8d5058f6faee855e19fb6e9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"f332463a554d238e2efc833e338039b87985f6e4522136278cbeda7b65fc70cb356493bb31f735125dba25e846","nonce":"8d5058f6faee855e19fb6ea0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"c70743c9af0f200b0ad99fa938e3577056319aa80a2022a264b3e024b22b97ad8e8e80ba97a7b1d5424ffde78d","nonce":"8d5058f6faee855e19fb6ea1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"0606cda50c14c97738df96bc0f42d6bbbff5cd43c7c8b23ca7cdc3de9ffbb1038603b3be2bbed79ef6582f9be6","nonce":"8d5058f6faee855e19fb6ea2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"9b6eab10e60258476cc3e70bcbf9afa1e79ee4ce7db47029ebb893fd19e6487aeca8d1828b438fd40b41ee40ce","nonce":"8d5058f6faee855e19fb6ea3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"98176ecc4a0f198a8cd5016c953ddb4f0033ccbf8a79fca95a16ce1542ef734e94a9f65d63207ce3f0d8625f85","nonce":"8d5058f6faee855e19fb6ea4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"a23d36de36c2be85443ea2b678ed08bd55970dc086bd2d4f84ef0cc03c6300d111329562fb910eba555f962f7b","nonce":"8d5058f6faee855e19fb6ea5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"afc5416a09376ce365e64f18afe93ae060b7915b24490ec8e17606fbcc35b4188e95f6ede63e28086924503983","nonce":"8d5058f6faee855e19fb6ea6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"18ba045e12f75a00f77ef2f6b80c7624ddd1f8e40b29610c2ccd7d3e452bb90175dd1b76b72eafda3541de06d4","nonce":"8d5058f6faee855e19fb6ea7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"8464cc07e199a02046b40465917e64b623cf0fb94bd31a02115cd32d170d66c45d6b291b0b7b027fcadb4652f9","nonce":"8d5058f6faee855e19fb6ea8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"e1ad4781771eb3f648534f56c3ccd665dcb1ef03b1e089fff39b412aca5eb2346e0a92724137137d1e55222932","nonce":"8d5058f6faee855e19fb6ea9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"d7fd1a181d3409598422832e07bcc81bb53dfe8ce0ce31e489c1f42703f0bbe08b0f1e71a84366817cb5a50415","nonce":"8d5058f6faee855e19fb6eaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"e022953200eb5eebf1d22429c5fc6218ef46f689013e8d909e5cdfc2d86ef6baa5ddc73c600417d1dc9edde25d","nonce":"8d5058f6faee855e19fb6eab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"46762cdd65c2a7d1db2ed2dc7a07ffd2adb1f98b63427e83d04a81a62ec440d0e817408440e84748e97eda00d2","nonce":"8d5058f6faee855e19fb6eac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"c8cbddfe5e96486fdf560b9fa1623a0b6a179a4c255470712c4e13f6a4a427debf743aebd0b8b111a0a40ca264","nonce":"8d5058f6faee855e19fb6ead","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"0466c1f5e912f8e17130bf00e9663537d63fb5b74ceff617e65531abeac12347bf853118fef3603332141f8476","nonce":"8d5058f6faee855e19fb6eae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"d4a75f9961f5902822d601a27242dec73c25367738721a9a414017bf96cb9c5da9a85e5232b61cc43efc4a3a48","nonce":"8d5058f6faee855e19fb6eaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"1b233209a31bd8645d76814d5f2582388e2e3c72515300f02f735304e6f07646258cc13409d536615670a9c41b","nonce":"8d5058f6faee855e19fb6eb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"a55a833de0ed35ffcf692d96959deacc1a17c63f3494864017d98ac32768def9c13018d5aa434c5a4f9d9fccb8","nonce":"8d5058f6faee855e19fb6eb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"4a706f35f6192dcf147c8270d9ecddf4f55886da86f187dcf1d917db0009a29b927c568b35f3e7f9bef78cebc3","nonce":"8d5058f6faee855e19fb6eb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"68dee3af4d55785073ad3d655ae49fcb60da6507584c1843f1a8e75f8dee5e4b07e2442b25e7f0f0fa492150b7","nonce":"8d5058f6faee855e19fb6eb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"287e276751f07d698689a321bc41fc449fc151fd93f0f0db2218b6870b6b5629f0b5ff40d5af654ba0c4a476ae","nonce":"8d5058f6faee855e19fb6eb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"1897d7805c59d3753288700023f799e2bb95d995a27ea043268ba25f83f49860620ea88e80e2ec6a640645a4f6","nonce":"8d5058f6faee855e19fb6eb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"7789ff728f84f996f9a5cdc8d2c80509861cd1136d81e890f6bcdb79aecb037f754becf48bbd41ff6672d1b00e","nonce":"8d5058f6faee855e19fb6eb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"6b41284aa43de3ccbc96fbc7041ea3906bc90e5047e32d60f658c2089aa77b8a7dc98263a5ebef70409a583e04","nonce":"8d5058f6faee855e19fb6eb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"c36d713aa1b602c5792bcaeb7f5c99dd0e5f38108f730a16ba0717fac352f11a7400e9ecd8196678ec4e1d9fdd","nonce":"8d5058f6faee855e19fb6eb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"f460028e57e727ab075b8a23217523b2da0407f64be5f32d7902357e0f4bcc9ae05377f4d56626572ce39d6d4b","nonce":"8d5058f6faee855e19fb6eb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"829b5cf172bcec2e7ef21878614eec3530cdc782b5464633836231573a206853429e0945baa806da4d341c13d1","nonce":"8d5058f6faee855e19fb6eba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"ce2498347b931d0dd7992fd1b2631576f3e4c8ac74f3bdc1e8074c7996d4947e4b515679138e73aabeb3b54355","nonce":"8d5058f6faee855e19fb6ebb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"499fd4b3ac71e883e28986151f3bf11a7874f8cae5a3a5db081f862530e7eb66a520ea1df9cf6a0a1a4818dc65","nonce":"8d5058f6faee855e19fb6ebc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"a2fccd3188bd0fc30e07340519a179b42213634ddfb1ae27d98c046f1951eaa8e6ef9bcddc6604d0b3392f1f95","nonce":"8d5058f6faee855e19fb6ebd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"726e4061f9307b785d6e998f621cdee940e409a9f3d0afa6a4ff8342edbac92e417d47dff375c90d5c588c5a77","nonce":"8d5058f6faee855e19fb6ebe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"415cb7cfcfe2cc289a0e9b1495a6f3ba823db29d296b56bdc444cf9ae9c4194f27e2e7f6465dc71e85ccb0c9ed","nonce":"8d5058f6faee855e19fb6ebf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"100632412552c3d8a61fb0a3143b6e17b3a3a97655cd02977ef4aa6782ca674b78c22b9e8bc6d59051c350e3cf","nonce":"8d5058f6faee855e19fb6f40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"fe1c70a1345927810fe4829074cce85f40a3d3ba730603d6c5c89b5a0819aace"},{"exporter_context":"00","L":32,"exported_value":"aaee3d3794b39bee27fdd7346b1ed0a9b4aa14902ba19f55a5a25d691837ddfd"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"276806c2d6bc889869baa6a5daa6c37061cef9ce18afd1da2db49e69527d1758"}]},{"mode":2,"kem_id":16,"kdf_id":1,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"d739aa3b63b5a4578d02f73e8c816e3d47a76e13c67f11424a43f16df804ba6f","ikmS":"bdae20856b3f57de5b6164899a9ee58d6a783768a15d73b600355e11010a41c8","ikmE":"b9ebf57515a283c9f07b008d595e4235e24d9f51b4ca122324d16d2d21105ca2","skRm":"3b6617f0adf7712ad9e703cda709dcf95f18c87ae7fcceed6e48a89bcfaddd7e","skSm":"2f6d391c7f58bfd0c6710f8f09e4dd212121ed2971092eb94a28431a371f60ab","skEm":"6735a602ebb7cd784a7c346e021f4dd751c0d75b21a22301eb2203e9767c13b3","pkRm":"04969eb48e5d51742b1b7b894a9663bf4d611a3b1e279b3eba770862a39d10beeda63ec435e24d2995d55a0c01ac721cbf7641b73d145fc71669b2223e16d65f2a","pkSm":"0475640437118869621c90d5a28d64d4ac54f60329f2df8ce24e6913de257e61948bfff5915339c616dc76096563250fb9b43096427dba1c59dc6c770a07bc660e","pkEm":"042a6f0d82e2a5b26221ab792e7a20cb5d4a00aaefb4b567b681eda62061f3b1f40cc030bf435c96ad84d2779f296ef34083f4a3c24e889b495d4ed39448dc00fe","enc":"042a6f0d82e2a5b26221ab792e7a20cb5d4a00aaefb4b567b681eda62061f3b1f40cc030bf435c96ad84d2779f296ef34083f4a3c24e889b495d4ed39448dc00fe","shared_secret":"d90c1f6591f0f280c081466103f743bb1a35edb167be9ae314f0c06349e75f04","key_schedule_context":"02b738cd703db7b4106e93b4621e9a19c89c838e55964240e5d3f331aaf8b0d58b2e986ea1c671b61cf45eec134dac0bae58ec6f63e790b1400b47c33038b0269c","secret":"db0ac5f766d6a76c205d6c03ab42c5720c57b1688d1d3f3eb54d4ce6318902d8","key":"2e2094c37bffcc58a4bfac89323aa4ddbd2625a146775ff02d6995fade6b5c1a","base_nonce":"8b12afe06aba01dbf3fb4a25","exporter_secret":"1f695d99b621169c6d1d05ceb65c1d071d85962cfff863081d630d2998bf72ed","encryptions":[{"aad":"436f756e742d30","ciphertext":"7d6ea96e48fb2415e2bff2923b93a68e0d27144b4af33c2628aba4844515282ed1159b258d086cf2b4ed9127b3","nonce":"8b12afe06aba01dbf3fb4a25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"224c5046b185cff41467a4cf7658e415ef17743b9a7ad2048bbcf05df79b7df1f8a35cc4eb18e1f4b8da5b0c9b","nonce":"8b12afe06aba01dbf3fb4a24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"57dae566c98c844526283fe1a264a3b0a0ac14bcb1e90ca7008d8aeee806c409a5ad2df3be59d6885d3c3ae800","nonce":"8b12afe06aba01dbf3fb4a27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"1c3f2f271c98ae2eb439b56688afc86e3e751eeb94e16c6cbfe1facced5111c066a517df93a1321dd5140c4ce5","nonce":"8b12afe06aba01dbf3fb4a26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"4931c9dbb1a59c76e07d3b4b2bb1d8df2c9700866253c90a938d4fe757e6d9c55fec82be11c78b6201d93d36c6","nonce":"8b12afe06aba01dbf3fb4a21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"3db5438511c97fd41274b0fa04c4111745a2eecd3936b495b134450b6003529d1e125661a6824d88165e61d185","nonce":"8b12afe06aba01dbf3fb4a20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"8e0a063fc878cba709a0b589e9a3732b4842eaf5f3aa57e5d24816903efc2fb61996bec28aebd3235ca2184cd7","nonce":"8b12afe06aba01dbf3fb4a23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"bee815742ea17560dbf3465565b5c6bc044cb7fa7781d6c80ecf3412df54a96b27d2aff542a657a7df954af3d3","nonce":"8b12afe06aba01dbf3fb4a22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"5a1bda68ff5d3a9916794877701ee2479bd7225826d88ef7d728bc2b7dde83dc0af9bce6e37af7a4b5f604de2f","nonce":"8b12afe06aba01dbf3fb4a2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"4ce7309153f3d64a6be9e62652f4c7fb0116ce08085f068798d83d9865dbd6b14202fdfb56d5605047c92ad348","nonce":"8b12afe06aba01dbf3fb4a2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"dd9702e50856e6b13435cca9693e7ba28a9219bfd730a95589264fd7a010d07e337b1b5bfeb20317cf2447fc15","nonce":"8b12afe06aba01dbf3fb4a2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"5f7d2d8fb63b5738a7bd61663f2d6b5cc0a8a8001b077cb8f53de205c9432eebb5a0e10fbacbcd3e3f06cd2651","nonce":"8b12afe06aba01dbf3fb4a2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"3d5b3db6361a6c0be8c725ee7cd9e2ac4a914112f8029eef53fe07d57c8370b735bce40d3d63634c6e09cd1242","nonce":"8b12afe06aba01dbf3fb4a29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"d6567c90176131a2c55a58e4d62ecaa3315fc766849648b54a0129889a5f3251d1a80a5beb357f26784b65a05b","nonce":"8b12afe06aba01dbf3fb4a28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"c6706a42414af3c2803ee7656fc944880fa9e550fc500915a0a7f27a2d5f14b7c05da4a7c5f39c3896c546bc6d","nonce":"8b12afe06aba01dbf3fb4a2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"eea4b8880da86f5e1a2034a895dc89a4370a6243f17a302e87acde49d6fae54a20a72924f13e0320e2491b8975","nonce":"8b12afe06aba01dbf3fb4a2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"7691e3a56f3d0e19fbe342c2d837e3aaf2f723d9f386aa2b884f41a2f930d89612eacae79055a02cf9d3705410","nonce":"8b12afe06aba01dbf3fb4a35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"160830de15725926a478529d4a0e444279595a4851e3e70a31f27f7cb59e6529c8e68bf129a30ecf4f921e850d","nonce":"8b12afe06aba01dbf3fb4a34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"5feaf3afd71c3e765073353f3ab39e4b980fe7c8dea79e3bc8f0871880d9dc987ff0a17007b7bb9c46305c88df","nonce":"8b12afe06aba01dbf3fb4a37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"a75da559247b7653e91a5ad1bde3e4f5070f420f0a79dce264a452bb595016a71ec087bff363689c1208567865","nonce":"8b12afe06aba01dbf3fb4a36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"eddac5510c7119d0a0d0f1f1fefa963776b3d3d4885138bfe20cd9e2cdea1f8e79d0748baf88b64a24d2a1af39","nonce":"8b12afe06aba01dbf3fb4a31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"6b6422bff973ae87a91bd9bb69996dbe59630e55f11c9da5df26997465b0d90ad4ab3ad0e31863109118d72182","nonce":"8b12afe06aba01dbf3fb4a30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"68e9697ee9145dc74463f44d0c91f0efacf84546e3d15d264f5f794df5aeeb3acfea3dcfc0bedb7722a01053e2","nonce":"8b12afe06aba01dbf3fb4a33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"cb0156978990b60fe47cd3b8186d6d5359a1b659790ecdae6359b9ac3c3fa306570a386b3e274e6fadf2577394","nonce":"8b12afe06aba01dbf3fb4a32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"ba10430ef451cc3458f2c7141426cb721978656c857102ec1c9a312779c6b9c721f9ea46ebc44fb564042e73c3","nonce":"8b12afe06aba01dbf3fb4a3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"5f50dcdb4c11016bb019061d1cad97484c000b675881634ff30f088662df2d28a8710ddae5866a0e1b6fa742b6","nonce":"8b12afe06aba01dbf3fb4a3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"0956c2e7dcdc4cb95bcf8d3c4b8b0c7546f8f018f772caf6009c4676b108342d71267ae498ae970722f6aec596","nonce":"8b12afe06aba01dbf3fb4a3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"b707469f8e0404371bfb52c8a5dfe2c71cc1ec892981098b43745c8dafb87b9a46a295a4e60809b65e4bc1fbf4","nonce":"8b12afe06aba01dbf3fb4a3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"ba1a71a601ec6e2e8f65fca425d2af7d23e0aa39d2162f1a649acca6aab71cb9d61008fb52878e51f8757ef168","nonce":"8b12afe06aba01dbf3fb4a39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"94d699aec1351a046d127b72eec603fb14ca80ed6bac2add3568e09bff4567d6cca45a1d194c0745c3c515e498","nonce":"8b12afe06aba01dbf3fb4a38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"1ae4539b7f8dd2666853dab0243df70baa87f898c8fa9847ee552e461f3d48db25f4967912c673f2df28789006","nonce":"8b12afe06aba01dbf3fb4a3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"c5896eb59ace5e6166d8e8b1202057e1034d2bfd5b5ec38d4a368bbd8569b8ddfe8b71b9f63e19736e1ac4700f","nonce":"8b12afe06aba01dbf3fb4a3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"96fc8cd37c46d0c0eb926e16dd1f7525409eae420070ca38e63f54bc9d8cfd6c7447e195416f1947b3ec3bc5c3","nonce":"8b12afe06aba01dbf3fb4a05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"3565b9f0db72e9edc64a68f97c1b2da3d4204dc2f419a2ed1073cae4ffdccfe9acf9752d142c2af4dc1dea27c1","nonce":"8b12afe06aba01dbf3fb4a04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"d4e68d2e53e674ad3bd1010bc85a8dd1c50af155bcfb9bac43860d24f1a768935e71e0d1ff36700705d235572d","nonce":"8b12afe06aba01dbf3fb4a07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"f0c9c9ea8a30c364fd75049d21eb719742576de69d0347e98ff35b002f9a9f21adeb0f3fe64d9d78da7b2e3f69","nonce":"8b12afe06aba01dbf3fb4a06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"14f30510e827eae64fb913d21ea057f5397d3d2209df9f823f7f6418ffed6900a8ab8f1325b42746aef633d9bc","nonce":"8b12afe06aba01dbf3fb4a01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"115f6ece3c40822e0a0001e55d214c4be3c4b286859289830f81ca9ace333839245f3b56414241e66a4a49639e","nonce":"8b12afe06aba01dbf3fb4a00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"29d446ae86556656c4c4893b46fb015f78db9dc970de2c1dffd808145d4274bf531531ea8f525c45ce129de872","nonce":"8b12afe06aba01dbf3fb4a03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"2b59f19999f8e8b8dd8bbf10df6f3e434557a5ffdd132c16a46352c3ba70d7b23b620679fc6fe18c8ad3a2b64d","nonce":"8b12afe06aba01dbf3fb4a02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"7c50aaa8118067ae7e2da962c69b2d2790780c3f7aa9a97ccc0e5cc4b89f655fb6a77251495ea4d14bb8cbceff","nonce":"8b12afe06aba01dbf3fb4a0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"66a26c3ee9d5b9d95fc22f8459a491b831a2d4edd06e9d2afab406e9250f4206272ab09fdcea44ce92545027e6","nonce":"8b12afe06aba01dbf3fb4a0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"3dd48a5a115650387cc45184f113f33614f79dfa9991475e7117a4ea796c704bdbd2ad8afc6d80322db11f951b","nonce":"8b12afe06aba01dbf3fb4a0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"24c9a59cea6378f13b654908c508853e3a8bb0c7f90aac963df9c491f7f2eb92c7e036f96f3444c3327f626e0b","nonce":"8b12afe06aba01dbf3fb4a0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"c6b07d16302c080837565b998e07ceccdca9c134103d55a6b610605dcaae350b8758cff791dfcc25a4441afa3a","nonce":"8b12afe06aba01dbf3fb4a09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"b7312a5116b7c1a435bb7c05cd504b0d30b90bbdbd5381ea7231f12bfe6b1ac4ac862538c3c9f895da8e56e00b","nonce":"8b12afe06aba01dbf3fb4a08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"269d5f8de0fa9a51645fb61d3ac3648ec4368654679017ddcd7801586c73935bd072dbb57a0e25e10f7aab85f2","nonce":"8b12afe06aba01dbf3fb4a0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"3714173c2177e9ebafe8fd2e2463dca6a5d61796842b754be1eb9cb49331039ca91bf0572a36da749abef88e79","nonce":"8b12afe06aba01dbf3fb4a0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"9da1b4ac96aa3649d6bf75b50e5d6ac992d14fb0e8ff37e8ac91ca9d4bedce8aaf035f60d88626aebf8553211a","nonce":"8b12afe06aba01dbf3fb4a15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"b2af5f6c9acbc7fc8fc796078cd7c18799fb75e004ecb23f24d6217b9851fd7faec94eb38257f540ce0bad876e","nonce":"8b12afe06aba01dbf3fb4a14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"bc84e99dd12f541a631e4de53e96932d6819069b2bff82a71cab69ab7b1ab289dfd2b1bb7c4c191c0e50afac2d","nonce":"8b12afe06aba01dbf3fb4a17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"d4c5426ca2dda8b1762afb58ec2e69509930a0ae1cc3553ba71ca7cbb6773d7c9ab1551213a7c61cee6b678ed6","nonce":"8b12afe06aba01dbf3fb4a16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"7e54eba9e9d24adbf78658a7ed1c6ff1d6ed4bcd1bb5668b3edbf46bb3965b2f2335fffba668f7462abb0ef57c","nonce":"8b12afe06aba01dbf3fb4a11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"91aa8042a95e235b3db5c84612b37cf0b99c81e44d798988c6c2c472f4c58c179c598a7fc5f160748bdad5bf24","nonce":"8b12afe06aba01dbf3fb4a10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"84b7ccc1de6c29b1d861aebd1cbc029c1595ad8f11fa267800a46c909503d3728e554b670bd671fcf7b585ef94","nonce":"8b12afe06aba01dbf3fb4a13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"d7e5bc5c4ff2d73efa23e820e633fcd656ca66cf230d020fb9e82f909471f8487a8c36b85e554920f7c83657dd","nonce":"8b12afe06aba01dbf3fb4a12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"0373d5a2e241744ac1e8044216bbed29d41073dfa9e559a72b628f9946b5f5c10e0bc65b871c9dacdd4950e921","nonce":"8b12afe06aba01dbf3fb4a1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"193219c579aec5f699927b257e78941d3c635dfccdd6fab8f07bcdbc732caa44dc9fedebe11c17bb7ce149d24f","nonce":"8b12afe06aba01dbf3fb4a1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"fc1c168e2dafe261e745e78af53b10c2a0fde1494006f0bc8380de481bee0a903ef6326d4c91349c3618bbe2a6","nonce":"8b12afe06aba01dbf3fb4a1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"5c357090b439f8d4b6ee0339177b62886f44cf2da7c536f2a2b1d9f7f22e4b8ffe57f1148d2d15832c13a96fba","nonce":"8b12afe06aba01dbf3fb4a1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"9ec6468b2cf109fbcc66d7c84ab6ac83e98475aeb23c928666d67dcf03646699b8bff24c5c3d16b38e5c73bc6b","nonce":"8b12afe06aba01dbf3fb4a19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"b2f22cbcc2f720850bc61a54588c88182dfde7a14385d474d0331322640e85bda8af474413392a8ac94c232acb","nonce":"8b12afe06aba01dbf3fb4a18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"ba1b39383c8721409e05de4fa943801cb575b5ee8a4b0e5ca98207ed991c282d9ac98441b15ed2890231ab9394","nonce":"8b12afe06aba01dbf3fb4a1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"59369805dc2aedc0efae17d5c575c46d402d6da8c59e05cf4338066b66c6aaeeb77fabc7726ffe57423cedff1f","nonce":"8b12afe06aba01dbf3fb4a1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"d5738b0c9d284d65bd6642c867bc0dc3d196b0bd9f247ac77c02ae58a7b276a4637e9eb6b036c53c5f66b779fd","nonce":"8b12afe06aba01dbf3fb4a65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"95403cc85060ca0317a5e1f35002511e57b91cfd1f63490567919fbd9cafab9937ffd32a0d837eee936be9e2a3","nonce":"8b12afe06aba01dbf3fb4a64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"4e48f9f7188c698395863a2383913ab45642790ed078a1c0822c529bd7acfac40e4bee5caecc807a279bd3b50e","nonce":"8b12afe06aba01dbf3fb4a67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"da57c69a7851598268a5fedf66c5440c951ef696629e843f60f03a14cde8b251f83400098fac8af61e40b9fbe7","nonce":"8b12afe06aba01dbf3fb4a66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"e74e4110f21bb821deabc23c0846fe5e7b6b2bc29017f0b4844286f56c213e560a0d03fca7ba45407388404faa","nonce":"8b12afe06aba01dbf3fb4a61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"511c0ea80d5504c00c56947fe9669312b164f047319d5b3ba28bf8f1c0d1bbf388e16d5766d7d004ffac3aded0","nonce":"8b12afe06aba01dbf3fb4a60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"2486b486734655bf73bdf8674e89704af9578ea2016d6a8583a51a23d8983df1ee277d90b39f98b381dba71f50","nonce":"8b12afe06aba01dbf3fb4a63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"942042e385dcaaac3b1a38fb862c23b5d2eac5ca27f70e534f262d6491800d28dcba16420aa813b216741e5c70","nonce":"8b12afe06aba01dbf3fb4a62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"0de62fb53292afba977693bad2ac91cf0a7d46fc7bd10000d458ed03f43f34750e1b43c8b6cc064b78dab37b3a","nonce":"8b12afe06aba01dbf3fb4a6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"0ca1f3be64b2d193662378075c615f7894bfea0d604106cfb3aa902e4372831cf01b4a2fd12705bdd9e16a6350","nonce":"8b12afe06aba01dbf3fb4a6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"0e2fcc56c2841bae4ebc695142f94e0526bf214a96af40840cf7537477994d7339bd7b9bb93305fa832f97d604","nonce":"8b12afe06aba01dbf3fb4a6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"6d772f6e6daec1b7831266303164a4c9431b75c4a060d92f6b0f772f2fd88acac9d27139ed430167d9091bb793","nonce":"8b12afe06aba01dbf3fb4a6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"1da47aa71d49debb862b401b57e065e922eae19c625da9cb4e37c3f75cdfa99a4c2437a8abb6e7995b3eb65fa2","nonce":"8b12afe06aba01dbf3fb4a69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"fb6b3c9e704fc63a5320a7b596f7ba50dc9697e8f96880f028ff0474f1eea60e3a0a3feb93a65c10934513cd38","nonce":"8b12afe06aba01dbf3fb4a68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"c7c9c2adadac1e532a102953b74ee5c6afb6f3fce147e14ec2323938b5612e3e7464c4476fbc57467bccadea6c","nonce":"8b12afe06aba01dbf3fb4a6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"aab6cba90e224c74684de2de1256e6779ab42ba3d109eb07bfa18cd3267f6ac9313072a7b6dfa6c696ffbcdb12","nonce":"8b12afe06aba01dbf3fb4a6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"c33c3801639a0807f3919bdb68993ef64c75ffaa7e376e809f824f046c183349d210809f92f58cee05f4407d83","nonce":"8b12afe06aba01dbf3fb4a75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"9db56593eee31d3729f1924675498f43f92232cc14f3c6f292b03474aa6a89a1c255a16c150db80d23d26ba2c5","nonce":"8b12afe06aba01dbf3fb4a74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"721aa9990c119a3040784f0a2fe39da9cd0f5fa1868a0cbf4d43dda234d7d604d451bbd984082d99c4fbc2a350","nonce":"8b12afe06aba01dbf3fb4a77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"da6fd50d003e9140ef84238c7f8699bba7b496c1a64af20062588e6ddeeca3ca81e5a393f313033cd954758651","nonce":"8b12afe06aba01dbf3fb4a76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"f379bbed21ca889d001fa10a50435c54608dd5e62b9cb520d173dfa9830d4841f7b446fa7cfae2b9dd670957b9","nonce":"8b12afe06aba01dbf3fb4a71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"0f42bf64300b39758045934a8cfe2392c486948aacadd20a80ea1416a5f2361c3175896c5a5d6b88fd12f4ccff","nonce":"8b12afe06aba01dbf3fb4a70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"9f85ab5f7178c27b456c9da1303bbf9ec4f93a2ef95d1dd9cda657b3ff611c6a87034cdc76ce89b82ad8aef5fd","nonce":"8b12afe06aba01dbf3fb4a73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"6754eeb17809eb06e0cefe5ebaf7c3c542c3d8e0d907af33a454303733deb9e8264257b3e1c0df6a6af6302cc8","nonce":"8b12afe06aba01dbf3fb4a72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"30a74f1832fc83477b67358d37b476cb91afe076c896b57b2d7afcef0cdf4d5582a234199fe850d66c30db7589","nonce":"8b12afe06aba01dbf3fb4a7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"72aafd27e596e12347211e0013cffbe471f2429b0dc39cb126f65dd025c086241001e3c16d22c6066d3f7bcd2d","nonce":"8b12afe06aba01dbf3fb4a7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"835669c22c61cb95b8a007619e4aca0ecb90a8f224d089a200829a1c1712173dfaddd3093276ecd4787e075724","nonce":"8b12afe06aba01dbf3fb4a7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"6251ec9444e0a058631f08902fcec5a52b8d9b65e97e8ddf148a720b22990a3517033d42b270ecb7c2fd3459b1","nonce":"8b12afe06aba01dbf3fb4a7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"5e792d3cf830978f4af7c310fa72a3b3ebe361f70bd6a70f4c65dfb500515b07dbe6868404ec9ec3ccc60e3871","nonce":"8b12afe06aba01dbf3fb4a79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"2ae738b891650878aab4ab719905e22afaa62d80d8d6f7e0bfb7eb8f9a4d372770155d257f0d62cc278067918f","nonce":"8b12afe06aba01dbf3fb4a78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"a62a49e34882ef95d769e946e424e9a734b7b610b6653faa5ae9de06b615063153fdfc2eb1591323694af06e91","nonce":"8b12afe06aba01dbf3fb4a7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"782f8bdc6cc8a67175acf6690752569a8afc876591da951de97671944ca29b85fd15e4e5a19fc0bcc6a1927467","nonce":"8b12afe06aba01dbf3fb4a7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"59bfe2cc7a803617e1a54a5964e96e1625d147f0c3bb09644b15304f234588a0760dcf4d790bdd6fc0aa24c237","nonce":"8b12afe06aba01dbf3fb4a45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"48dd0540fcf8c1e9c642d43e0458f599df2e23ab17fa6c505f4617409680c3991f91d35348ac710e66742844ea","nonce":"8b12afe06aba01dbf3fb4a44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"02dac0fb4286f24cff86d61bf3556a9481980d12c1ce9b5ae05bb288a35dbac3738deaa05c4f142946b6437b91","nonce":"8b12afe06aba01dbf3fb4a47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"1753b248cac46a20ab6257f35853f315934edc73428fb009c877704aebfb836e64a7933219a50b19e4565f74b1","nonce":"8b12afe06aba01dbf3fb4a46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"b6bc10d7aeadb0bbcd1312a400f368ccc6ca4b9ec0d8060a2b8c227d596e6b3f7f12040ca4ca748e032931269b","nonce":"8b12afe06aba01dbf3fb4a41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"14a1138342a1dae84d179f312fd2c0ee4699faa69f7432b22394fbee3a1cf807680755727b69d42f2d03b2781e","nonce":"8b12afe06aba01dbf3fb4a40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"bd718e04dc87ba8824fb9f56c82be01cb7cea2c703fe8f5e6d8b3b03aea755fcc1608bb86361945af970528da7","nonce":"8b12afe06aba01dbf3fb4a43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"1736d8e7bbd4c190158fc3316356b3441b0a4d3cf78679ec1e865d2b958ba6036c7a3e943f08a4b5c80ac5e575","nonce":"8b12afe06aba01dbf3fb4a42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"24a3036fc0bfd53b3b4e00876f747ed8e5a9d82039633d686390fa67f4fb6628dea7635f934ef118f0fc3312d8","nonce":"8b12afe06aba01dbf3fb4a4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"5b8e23c7dad3373a68b7c739bb94ac738328f2ecd3249b48f95af261b93eaef4ccd31d744bd2b12ca66fcbaaf6","nonce":"8b12afe06aba01dbf3fb4a4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"a3e7f0d55d399ccc2b865b68dadf445337b973a68a32d4bee87dd5c6d556a3c15516d12e5d6565ddb5aff1be1b","nonce":"8b12afe06aba01dbf3fb4a4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"a24ea74cfa70a703a88f7db2769eaf0f3e0590c32697b525cd2eb58168e5cd0d7947ec77731ba6448d338363c4","nonce":"8b12afe06aba01dbf3fb4a4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"d27abcfe127d013830f398b392cb69a8f9afec9a504a5aab8a6265b7f6765a585b8f6fb8763d53b82b2cbc2f7d","nonce":"8b12afe06aba01dbf3fb4a49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"e49e5f8fc855bdab3d7ccbb4c9ecc4be6f4ceaeb5ed9281249e8451935d4240189ef099f4c2249e9035e11881e","nonce":"8b12afe06aba01dbf3fb4a48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"0ea7b23b6001b2ed527bd15bf792497b16fcd089de540730babe09cd1be7917f27a001ac74e10dde18d64a602f","nonce":"8b12afe06aba01dbf3fb4a4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"41136fea5885a09a3c19018bb626a172c0dfbbe052cb4cffc238f6ffd4e1ac60aed9c1a57c5ff9f96358bee28f","nonce":"8b12afe06aba01dbf3fb4a4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"3eabb32c775154628ba6e3612992af6652cbbc3844a7db67e85de4a26b8423b73f8f25504768950b4c45aa6c74","nonce":"8b12afe06aba01dbf3fb4a55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"2fe542ff4284b034ad1063baa6a1e6301b1b38cc4f9b8308a23fe14eac5c60d0fb90b1f3e8b0ec6cb5c62a7f9d","nonce":"8b12afe06aba01dbf3fb4a54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"dfca6dcc4839a6da8c2ecfcf8559418b384fd4a7f7bc2af7e49437d376e8d116ec35c175de716869d88ff79cd6","nonce":"8b12afe06aba01dbf3fb4a57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"fbea0006599557649e84e49361f58e88e771c56cd10dd1594fb02ccb0ae3882632c751ac4284f70167c6737daf","nonce":"8b12afe06aba01dbf3fb4a56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"ec48ecdd32dd0c5cdffad23d579ed4dde3894cba44196e2249974d2dacfd73094db40d430586b9ad69f713d3e2","nonce":"8b12afe06aba01dbf3fb4a51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"eec6261e309193faa6ef680a4a3f6d15cebea3c20b8f5834e82d374af97a87c88ff27c58ca169a40096d0f8ff0","nonce":"8b12afe06aba01dbf3fb4a50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"06db05d1c3e84f3bf964c544b74bf4618231e3345ae9cd4a897710f7b2a2ed54c9834c558203d4df3f82281134","nonce":"8b12afe06aba01dbf3fb4a53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"1c4461d5a4ee40f2b18f56c6fae414f899976ba9d4a26d29612e92b7fcbfeec9acb07c782da6b9b7916272344e","nonce":"8b12afe06aba01dbf3fb4a52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"fd8d010b9d3b09a92410131c6ab47ca935a1ec73da51b229f5bb0276fea839286a0df8ec3f8676ec99fec5e942","nonce":"8b12afe06aba01dbf3fb4a5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"b899483f9dd844f168926264660c97f3182cb923470d17ce98c446066606b6d9f6c2011370fd714dbbcd504b3f","nonce":"8b12afe06aba01dbf3fb4a5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"c2324f986047f1c4834d8e60300afc91a04373ad2345cc8931f0496283d5f9a587bc3a97aa6e7cd1027594b8c9","nonce":"8b12afe06aba01dbf3fb4a5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"d055e66549efc4738c7cbd0ab4b5c7764ba9cf497483f749324af6f9ba0a5c0c59970cab2e77968da5b6b98770","nonce":"8b12afe06aba01dbf3fb4a5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"b7c75a12a598f0ec26614c70fef027ec6fbd2efb834ee34d6f0b0057004b5f193775f30a6e62f92d88e4a1fb11","nonce":"8b12afe06aba01dbf3fb4a59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"ff7a5b7a093cce04e36078f894384929636e7388b90c250abbd5bf462197fef9e6207d0a508171436e0fd78e1d","nonce":"8b12afe06aba01dbf3fb4a58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"8e969bb8a171345685d23f28e8c9a1588e0ee9745256685521d4df682d1428ff0c792c6a02dd56078becb8af43","nonce":"8b12afe06aba01dbf3fb4a5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"b392474fa8517a0f93db5971b50dab6254ced6358f5f07d8fa118a6918bd4c1ac4e29efc5601ef9eb023c3edcd","nonce":"8b12afe06aba01dbf3fb4a5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"b8b7a50d38a7cd3eb48ef3efc7cf101a7683ba57b9f0f19d59f09599e0886b2321b6551a123a15ee4c4f56d4f9","nonce":"8b12afe06aba01dbf3fb4aa5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"d6ae4e68570baa2b4e05d055a29cd25234af69734218d2e7cef4a80f499c8950c83d83459a481e67fb55459731","nonce":"8b12afe06aba01dbf3fb4aa4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"5423fc84ce8e50344bda8792cad755f162e65de542bd3cfc81b7554519b6459db00c4f6eb598729bd2e9808b2f","nonce":"8b12afe06aba01dbf3fb4aa7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"f658a454b2f20c1b290ae892425e38af8b6c2bb7786cee3895f13c173f878c63eb962c3def17f874342550f2ff","nonce":"8b12afe06aba01dbf3fb4aa6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"115ce45ab17b21c369f1ded0b942a329362c5e8a479be7ce04eecbdd323c2a1c2441d5dd9fb0247565702b662d","nonce":"8b12afe06aba01dbf3fb4aa1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"8f26f4938383980ae92f7f8e778a798d326bb7baa5b152caffe5ccaf24727de9aa62ca8f06804a90c1fc2fe3cb","nonce":"8b12afe06aba01dbf3fb4aa0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"214d09d0e468936c77931628cf46a7f3f20b95722551d730c982debf8debd25cb778f21c24d5c7dbf700b8ba2c","nonce":"8b12afe06aba01dbf3fb4aa3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"a759a407a0c275fd17bd63a86f7b473290b612cf52df725b05f725514e09bd441f4c3d7b7b66ef9c9734d31fb2","nonce":"8b12afe06aba01dbf3fb4aa2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"002fd807bcceff303755f4ef43bb16b68d61b3a4fe618e070e4afbc91c17157c74da4aab19b0a47be5c5f84d5c","nonce":"8b12afe06aba01dbf3fb4aad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"efb91d446fdf8701ef186caddf9f5b4e97566d33c0ff0622b859b863344b8de79d3e87fe1aa7ff421f421740b2","nonce":"8b12afe06aba01dbf3fb4aac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"09a8a68a8672eb56838af1389453bcc168ab21edbeacaf4606b77b3b04d0fd62d5d21f6d1c80a3c15f55c65f32","nonce":"8b12afe06aba01dbf3fb4aaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"0e9c179d62c7c1340790c8b01b979804b982fd871f3296fb137e72d7b288f3e5939a6110962d034a26ae4c14d4","nonce":"8b12afe06aba01dbf3fb4aae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"0e1289cce5f37ffe66fe41c2b18dcdc56af51c2585f416343b8c56b67edc34368c082c6f6a3799c149c8df2adb","nonce":"8b12afe06aba01dbf3fb4aa9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"360e55e511d55eed47bf5753152522108a31fe0dda23afdda0761b8d696e8ac9451d3ee98b8defbc51c5cb22cf","nonce":"8b12afe06aba01dbf3fb4aa8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"524373bb2e4e807145800c814247b067cc0f6739f67b2bab6917389facba7705d8d7e12c7a2f4c28ec2b66e7cb","nonce":"8b12afe06aba01dbf3fb4aab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"a7db8835462b556c2e9ea69cbe755ae850cee04d67d50dc8a943db51f171168ce625bfc5bf782e09fd202cef98","nonce":"8b12afe06aba01dbf3fb4aaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"5adb03d21047ccc57b0cc001e82fa61af6c2c57ec72c155b8ae31c25678fc98a39af14860014529431ee7ba387","nonce":"8b12afe06aba01dbf3fb4ab5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"b08a7efeee4d96607f273cd12d960d58fc77b485cf48a93859a3f36dca542ab5e731903e09317a2545b467a052","nonce":"8b12afe06aba01dbf3fb4ab4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"196e8bfe2a23c7d0fadcab1c3dcd40e398ced81ed1fc898f12c6d4bc1f543954d3608b341a337c1018e72026c2","nonce":"8b12afe06aba01dbf3fb4ab7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"991f0816791ba6916e3796db6a855147183339ae96e334a1e459f93648f0c0d89b254acae1e499ccdb3b21d8af","nonce":"8b12afe06aba01dbf3fb4ab6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"bf549e118de8c353fe16f46e81f4d1bcebbf1345c467c9234cc319005360972211ca1179117731ed127c84c4a8","nonce":"8b12afe06aba01dbf3fb4ab1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"f8cb03bffb01bb6f7283ed884e14dbcd8a837b465aa556757ee750cb044c32065d26d55a0f3a8f94460710a0d9","nonce":"8b12afe06aba01dbf3fb4ab0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"423a812f72d6b680d27d315e3be0d9bd1808c03d540d679fde563b5334cef5d2e4649d907b9b43852e1b7dcbb5","nonce":"8b12afe06aba01dbf3fb4ab3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"5aa98e3bfcb9fb3070c4ec1882d686ca6f7b87c02ceed2fba1eac576591da356f5921db938f63d14031a7f007d","nonce":"8b12afe06aba01dbf3fb4ab2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"c665b6e3617ca5f6eb1695cde78e1d8a0f8470c9af926ab8f16700ec72439aec6b51680e5bb430c39944b0d3b6","nonce":"8b12afe06aba01dbf3fb4abd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"6801d819725eff58a5a0c358797438b19dd3feae5328a7a9705dfd453bff2e485acc68f0336df89d9589f46149","nonce":"8b12afe06aba01dbf3fb4abc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"4cb941e027fc0e03ad7b5e5fc982be1bb3c0af2036e04a4f78ea79756b3f254f175bd30870049b08c152f9e4cf","nonce":"8b12afe06aba01dbf3fb4abf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"0d524b8b5f14b03c9f442b2c9bda7a92065199402a94366c4a12f016414c82f179312971c1f52aa51b968528fe","nonce":"8b12afe06aba01dbf3fb4abe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"326264a1c7300273918d829f31ae81b81566d651e445f44469507f2b3b1b61a4685f29eadc434f4a6c658066d1","nonce":"8b12afe06aba01dbf3fb4ab9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"1089e6d690e263ae545b860c386e96a962aff358f333e402de7faf4fb146659631a5f50d58b87514a821a36afe","nonce":"8b12afe06aba01dbf3fb4ab8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"54ee61869445f25d11cb96c0d1640709ef81536613a673a0ba4bba9eb9b25ce108b2aea623ea8dd8f361a815f6","nonce":"8b12afe06aba01dbf3fb4abb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"e712c5d34b737eb54269f0050656291759a8bc272a2800dfc6761ca1e25e43a240faeeceb582dc271d96dffd04","nonce":"8b12afe06aba01dbf3fb4aba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"7c83e683fddbc1544cc30ecd7ff82d71f3ea538a086ef9c5da812bdd3ac7d88b0442ca4e81173b1f1b77b3f91e","nonce":"8b12afe06aba01dbf3fb4a85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"1798d88caf96c4a137782c4258a73d83dc62bf5e3dc40a89547abf18d4dce0dcd5d8dcf08369f6ef1ed81f12e1","nonce":"8b12afe06aba01dbf3fb4a84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"bc2f723e5a545c2603d667fa62f7cb468cf36bb1c5a4195ce60ea16cbf50b11e02d90616e2e9a617fd8c8d4ee3","nonce":"8b12afe06aba01dbf3fb4a87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"10c173def18bb22fb94aed1e6c314093d2494c2139a905fdf988d73b96de60eb2a805bb18e51ab8d0dfecc7206","nonce":"8b12afe06aba01dbf3fb4a86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"968ca739e160dffaadc70f3c0e557fb2d97a8f59b70156aca4792cefa41be36aa2b79c43a404ad54e5cf30cabe","nonce":"8b12afe06aba01dbf3fb4a81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"4a4441011957ef10fd667452e85d311c994a6595890cd45d89e499c8b33b8f51580f28b09c27b2f4b8a546e6f6","nonce":"8b12afe06aba01dbf3fb4a80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"bf826219d1bb9b8850c4aee08ae0e0998c3ab4557e436fb49bde574712878f8177b05a6f34aa6f243235f63195","nonce":"8b12afe06aba01dbf3fb4a83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"be4bd61f5d7e0f20890410da22566c66bf9f013284abecb573c21738c5ace2af14497f0b5b8e3ddab1655e84f7","nonce":"8b12afe06aba01dbf3fb4a82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"66ff928969c645c6e7e38ee58ecce9abd2fc4d5cac00db8a84d46dc8a970f716658cce195d020a6c33cca2521c","nonce":"8b12afe06aba01dbf3fb4a8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"fa05033caf3deffc20c8a0cbdf12f7a091fa548d33cd4ad9c5f7a5c13f9ad28515c9292d3d2568bb8680df0dcc","nonce":"8b12afe06aba01dbf3fb4a8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"76e2fce825f1b8b42c258682277bfe36ea480b5189b9756625df2fb4e25eb77098da8783c5ff518bc2750fd0c6","nonce":"8b12afe06aba01dbf3fb4a8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"a9b4577a60a2f1012efbdd50de89ddf05a5d5561ab4132929f5f78e1ba273c43979077ea6eb4c11db72f2f929f","nonce":"8b12afe06aba01dbf3fb4a8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"74619985a9bf65704899447d7dc0a6b612f1595c1c45301da0b0407df39000fab9604cd0a1e63e182a6ced4579","nonce":"8b12afe06aba01dbf3fb4a89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"f8cf692fdf4c4f35c935b132f1b9a669b2235a6b7caf7f42780461bb8ec7c5aac61cc9467fb199d26a59bd54ed","nonce":"8b12afe06aba01dbf3fb4a88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"72ebcda38b550cafbf94221e66f3a917399d3aedd9b8c18985fa5e51ec98a494ffd26c2e02957e3759d7f34c01","nonce":"8b12afe06aba01dbf3fb4a8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"fc5422312772cb9563941034f59c89223ec75edbbde3c3d060cb24d9d8773098952697e970a32de19025e0c379","nonce":"8b12afe06aba01dbf3fb4a8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"7eeb77dcb10eaab86538860454f7a98964277a5bae957b27f50bf54bc6a1e4a67af4cba788a51940bc821cccc0","nonce":"8b12afe06aba01dbf3fb4a95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"383c0770ca2ad75cb6ad8caeb4613c8e31305219eae8c96c120bfc6f265aaa6dd5619c609f88dfded8e061782e","nonce":"8b12afe06aba01dbf3fb4a94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"8ab32afa9b45d46b60b5fd3cad7e825cb1e8a26ac1cec91d47f6808feac388a2b24b7f415940754ef8739e4163","nonce":"8b12afe06aba01dbf3fb4a97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"0ae999ad86708af0443d58a37d9851ad39b114e6842142fac155d78438442466a06649b3bd213dc165d3180e50","nonce":"8b12afe06aba01dbf3fb4a96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"c782ef5a2dfbba4c7ebbdcc178fcf101c1b383cd373ebad85922230f9b9e8fcd383ff995c86bbc830fc565f3d5","nonce":"8b12afe06aba01dbf3fb4a91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"145e40d7dee8a1dd1211ce9afb25c79d17012f7e40cdb7d74a6102f4124788e6ae93d48f393d630b1588a381d2","nonce":"8b12afe06aba01dbf3fb4a90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"c9ac4454cfa1949f40f1eb5973bb5bf5f494e919929a7c1eb144de19f3a66c05cd4d13c2c4a9fb2b79bb0353ce","nonce":"8b12afe06aba01dbf3fb4a93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"4131a8daf7140470460fe4fb356cdce6df1ad0c1d5bb758faf1313fe2d4bcb168c3e788d9df8f055cd48b302f2","nonce":"8b12afe06aba01dbf3fb4a92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"be179ffcdcc16b3af5c8a5ea7e668f9a9066b2c4a6f6d3be7ffa3eabb2892d655b9908a126ba9a8dd559cf270a","nonce":"8b12afe06aba01dbf3fb4a9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"999f095e1b36daadd4377e06659bb5eb2ea66c433a45c2edb63c34f7ed7c8a4a915b1b0703a7f43d54383d028d","nonce":"8b12afe06aba01dbf3fb4a9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"51773b7731fb8f8e9e68d2ba1ead94e89b7f5a9615754f97815c49c5fa2c9c49f6e6b189295b81cf0cbb6b3fa4","nonce":"8b12afe06aba01dbf3fb4a9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"3dd10eef0610ed8c756895e7da1628d66a659ed2761b571ed84117b4f7c82fbb924c94451eee9753f4340c81c1","nonce":"8b12afe06aba01dbf3fb4a9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"9a590ab08bb9d4821d93c5898ba11d3d7005de6a085e56d79ddfb0d80fb1fd1194ee78816d1f2e8956c7e5fc67","nonce":"8b12afe06aba01dbf3fb4a99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"e4c1709c44058dd300018809d42ce39769f7ae52c594135964224ec35ee5ceb436fe365733ec0857407f6c5634","nonce":"8b12afe06aba01dbf3fb4a98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"d51bfaf03d0032be571d8a7308f3e4eedd7f64519dd57e715a025f201005eddfea9701fb4a36337a455252056f","nonce":"8b12afe06aba01dbf3fb4a9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"bef38854cb91e2d0f52f295828489a9dce2506fbd43c7c9968e2c8c1cb626ea694814dd9c275cc8ba5957b2b7b","nonce":"8b12afe06aba01dbf3fb4a9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"8b63afef2d211e81466637779a775cd7e8ffb95b44c5dd7f7ba5090034a5774d942f53c4adf19a5c35caa54daa","nonce":"8b12afe06aba01dbf3fb4ae5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"19b3aa5b11785d8ec401ee6b482f3a6ea80721bb8c4eb67e2d59d7732683cdd4b231fa2cf7e7d2fbd60c7e29ef","nonce":"8b12afe06aba01dbf3fb4ae4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"50d15eeef69df2a6878b89adaffd9572a194f30f5bd597d7d2ff909bc2ac0ca07dfb28eefd4ea42287d4d71187","nonce":"8b12afe06aba01dbf3fb4ae7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"9556984ffd922c14b885826b39d95f148aaf2c24f2391edc671377ff46fbf4cb7386ed1f2da5c905f31a720746","nonce":"8b12afe06aba01dbf3fb4ae6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"db0a41579fa32efa8f84bc15b2342124e750fccf407e45ccf07d4c6327014984adfd3e4bdba8546e872fbd1469","nonce":"8b12afe06aba01dbf3fb4ae1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"109bc38e8d6b5378fb8ad721025f474f71ff29450378de9dbeda164b71709adb2509724745a33bfaa26973f234","nonce":"8b12afe06aba01dbf3fb4ae0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"07230702baeca76fd8f23ea7a0715bc30c528c9b29d563dc1a5aa4f1568b338ef9f0cb0b26dd1cae5b4d8970c4","nonce":"8b12afe06aba01dbf3fb4ae3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"825feda3167b9c2a459dde76cda794d3ee4f951419dd3bfc265f2ba80338dfb1a299eed9a586b94c25a7d350b0","nonce":"8b12afe06aba01dbf3fb4ae2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"3005da87c79729e9fdc25edf4b85dba34397b7e1c92dcdc2f0aedb0e76b0574ab5ad9be21e2182f8885830c660","nonce":"8b12afe06aba01dbf3fb4aed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"327ff6f97a72b5a59d41450b13c1e59a62fbd1440b6d1c2e39412b14084cad79aab814b22034c0dd5da5332d86","nonce":"8b12afe06aba01dbf3fb4aec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"1f5ad819b8fcacc0e26453111ab584d17ed23dce69b06039ab115240d20245be1e4d3402bb97c895799d12b28c","nonce":"8b12afe06aba01dbf3fb4aef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"77c1688704f6ff14e550ac0e826b0ba5efce81ed15309729c07e25c67872ffde25776fc735b79c84a598ba9808","nonce":"8b12afe06aba01dbf3fb4aee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"9bad82071227aca6346c1f8389b750af25b03fb6859e83e6a4c5311ce32c174ec78e4b7018d6503f943eea59af","nonce":"8b12afe06aba01dbf3fb4ae9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"d9df3430861380f8cca032739f9370d2dd3fef995fc441c0b69449be02eb00fe4c355bbeef2a0aee0ec1ad6940","nonce":"8b12afe06aba01dbf3fb4ae8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"ff16ea8c7d5f622e5261224bb088dd52233e283984b789ad39d2f52995dcb58834ba3cf5522841013b5e5f086d","nonce":"8b12afe06aba01dbf3fb4aeb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"df237e62dfe8f2bde26c7f3496ea8d61163917a104291c04197b8b794dc92c4b89adfbe2969076b7de79b76055","nonce":"8b12afe06aba01dbf3fb4aea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"b185a7c3164480b46324c3a81502ea178d1fd18b6a9fada60d1b6cccbb50b614e3fea9c563d93a4758b2138e28","nonce":"8b12afe06aba01dbf3fb4af5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"2c28eb7908252f2d012717f8e726ae46787c0ffc6ff6c8d3e02aa3f685a5ad31a56976919314bc0903d52a73f4","nonce":"8b12afe06aba01dbf3fb4af4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"894d45dd557d40cf842c4ca02ac3a32195b983ab217b6a154226c147508b6ae924092e94f3f7cf8ea6637cb46c","nonce":"8b12afe06aba01dbf3fb4af7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"2b33c19023bb052cdb1ed5181e101fbe972342834abc9d70c27ed39603df1db5de49e2614a06f8af400ee710dc","nonce":"8b12afe06aba01dbf3fb4af6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"690c922891a005de2a1969de90af01c3f974dd9732f60c64596d6bd116ece30f4585f0133a2b4c9b02ecf00c77","nonce":"8b12afe06aba01dbf3fb4af1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"450e031c0ecc903d23b5a8ce4c535773f941b51bfcf83f06400999f1ac57e15d7b6ba5b5c5737458ce11f71f2d","nonce":"8b12afe06aba01dbf3fb4af0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"817b9e356f4b84ed912f151045adcaa02e370878423a333b00347b978dd2792e5827fb2951f3428c7d5f94cc85","nonce":"8b12afe06aba01dbf3fb4af3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"4719e90c48202831a17116283942316c212cfe754eff5d2bd3107a4bfd9f12c6cf221d69ce152b6c7480d83bab","nonce":"8b12afe06aba01dbf3fb4af2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"f6356eb466fa307619ec9957f2b00c8766697edb875638a4d790748cf9528c76f9a552c0e790d3b1d36e0b1d3d","nonce":"8b12afe06aba01dbf3fb4afd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"07c357fcd2b335b7e7579f76d949b875306d1a39005a2cfb61d0da3b888835a9849b2bc1dbb6085a82a5973aaf","nonce":"8b12afe06aba01dbf3fb4afc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"16e60e2985f060259a1fac0dff5928bd1a7d5491157430740a76de130e8d389083f9d256e6eb9c968971dfe7bc","nonce":"8b12afe06aba01dbf3fb4aff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"c529bb1a29f284d28847fbb534708cca40cee0a18a4dbe0320bbb05fb6e571358ab1d64fbf87755d2e3f368ef8","nonce":"8b12afe06aba01dbf3fb4afe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"fee17c315f872363d168ce7c36d58b2fdcd59957b03514b983dd81c5a3316ec8df4e8768e281003ca9270dc68b","nonce":"8b12afe06aba01dbf3fb4af9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"1eb0b66fd3fd3589ebef2e495d790d792a4e6d9feec6871289b5fe4fd9f44b1e22e6780bdc460ef8377a54cb15","nonce":"8b12afe06aba01dbf3fb4af8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"eb174407c60ed69fb441ad8492e839f414896e0a117a28e6400aa7f8b2a95315533aff3695dc27ad2ba8d69597","nonce":"8b12afe06aba01dbf3fb4afb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"8613271871f8221d1f0b95772ad2960fbcbc5de9358919a222274d0b5a31aa06a740c42a10bb100c828337f29d","nonce":"8b12afe06aba01dbf3fb4afa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"3471d9105eb3ddf966c84195bdd17eef3edd5d8cfbff81b6bab72c9bec2c33e8ce31e7b09b4dc31cac69a529d5","nonce":"8b12afe06aba01dbf3fb4ac5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"5201ca472008e76a69c78224256419b713b4a352502d95784215db370a9dbac5dca940313ef3bf1c58d279e7b2","nonce":"8b12afe06aba01dbf3fb4ac4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"ce8f4d68897769ce0c418dbe783ddeac0d6ac7b3104376bb553557251dbd0d47ff3e6fac63fc14419f85089878","nonce":"8b12afe06aba01dbf3fb4ac7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"4cbc93a09439b111d746c2febfe99ed221adf8cefc184cde418a97a5fcc7d54ea5d6fa227ef34c6f40c4b42b1f","nonce":"8b12afe06aba01dbf3fb4ac6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"4422cfe8110d34c5976258ac7d66a4a598423f0aa0ebc61b2105f102a2abba6a8718a8659409c1dd201d6c574e","nonce":"8b12afe06aba01dbf3fb4ac1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"582e8cfe3bb155f86ef0cda349537b88275659d103640ccc2b5a3b30de900fb9f8f5b62d4ad07b33cb0d886ac7","nonce":"8b12afe06aba01dbf3fb4ac0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"d25db3d3fb49d3345ab8570ea2939878ca53a74a4bb29637da4bd924f45b0d94e1a1be72692a7ef59b25c26c0d","nonce":"8b12afe06aba01dbf3fb4ac3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"468c5233713320883cb467cbe61420267c369b4c0d10d3cf19eed8d34206f3533f24ba78209b7d981692d8f14d","nonce":"8b12afe06aba01dbf3fb4ac2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"396feb2371f4a8a158562166a034e8078cb1ef311f7d2ffa13dee3db2899b8feda6982ef9980626ec934c7c7e3","nonce":"8b12afe06aba01dbf3fb4acd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"23b6b428260e14dcc4fb790e7a7f8c44811759509e39bd6463c5a2cc270be087abf996ac3db43d2605b3b9d1bd","nonce":"8b12afe06aba01dbf3fb4acc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"150d3fc97f70297dbf4bfc20b4b47594b1e43ef746c8208314944b4cf2bd2a9b95eef401eb483c7cb47c062a32","nonce":"8b12afe06aba01dbf3fb4acf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"b637f4adafbd7668061ab4e6222e072294961be6a9ef5de8f86041e552dc8c33059b93aae91526991dbc528e50","nonce":"8b12afe06aba01dbf3fb4ace","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"65ac0cac50a3b431fee295b863c8e275e8729d9dd8c61926453d9199356bac28df6530fae3e3a385548c73d338","nonce":"8b12afe06aba01dbf3fb4ac9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"918be9583aedd3e4120e09fb15967eb2c1b1dd57f925055811f786fe91dacda9bd95e0f7e1d4e8dfccb5c4ed5a","nonce":"8b12afe06aba01dbf3fb4ac8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"fa8d16190e399c8bb7e28590f6e5078040eda463aff1a74db5a5b43141454a521f331183908a10bdb4011fcea4","nonce":"8b12afe06aba01dbf3fb4acb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"9bb25d0d9481f5f403b149f3091c0f5235ebb85b0b36c1c8551f359dd0daa6d9a7fec82d9246108611e25de72c","nonce":"8b12afe06aba01dbf3fb4aca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"be87d49b52421386bd2eedaa24cf8b249f281ff543684868addd8649a7bb216b1cea194ce781b485e397a18531","nonce":"8b12afe06aba01dbf3fb4ad5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"68af4e551f761dca8f88e070251cf90fc5201c8d3ac34947d6236954dc2c9fa576199cb2ac22f679dbcab13bc5","nonce":"8b12afe06aba01dbf3fb4ad4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"10129093652d9f983aa59ef5650595e26e371765486cc14d701ebcb3438f4c66ad03d89ffa3cc68122ff2a6117","nonce":"8b12afe06aba01dbf3fb4ad7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"bec1bdbfb160e8badf47c73fdc2c09f8fad3b20bebc37bd9436dca743e926325868ce216f38aefd0bee9a3b7b2","nonce":"8b12afe06aba01dbf3fb4ad6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"504faf9f290629e2237daf6c78d1ab38f8f126a73c09d9f3cc3705c9819276a4455f603ea09e76ca2b2b1b71f6","nonce":"8b12afe06aba01dbf3fb4ad1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"434df7133eaeef4968cb5f08740d0c68fe38b54ec420f8226dadae7465989ad9a4d6f223afe8feab7f54a3fa6d","nonce":"8b12afe06aba01dbf3fb4ad0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"76ee2da59b926b313e5ad99bf1a24219ca9d2511fcffb356f4eef7c96ec5581c3f400d873c1f4b92629e685509","nonce":"8b12afe06aba01dbf3fb4ad3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"994f3490b1829f10018c4ca3645bb40cb9a1daa885532a304b5a28f40f30675afb0dd428b2c4bf6b6da0395db9","nonce":"8b12afe06aba01dbf3fb4ad2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"fbe3ca566b82fe8c9e8d99fa5f4afccc41c4bb707dc930881169caea9d16c4d5f159871291736b86af9dbae244","nonce":"8b12afe06aba01dbf3fb4add","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"01d271b9a7a3a345e08d7bd2010fb3d70f1bd52e0adc2e6a0dc8dce5bc95d3b0c29df3a81ddb16e567db02671f","nonce":"8b12afe06aba01dbf3fb4adc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"e98a10fe120c6b1b248d30e3f3f76514d59fd2e5293ca192ab158704527e85bb15e06d8670f3e11e13568ab882","nonce":"8b12afe06aba01dbf3fb4adf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"9b35de2457ad985279c5a2f1c37ca9e35a6958c06e363db0d91858c8ae360f4c5112a2bee43f72bf07637b6acc","nonce":"8b12afe06aba01dbf3fb4ade","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"8fcf264d4b84f1c054d787bd3d1f3f5cb9cc59467d911a800b1057e7c9d682af13f2a87290532253aa31c2f9f2","nonce":"8b12afe06aba01dbf3fb4ad9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"3956ae3fc874c1108fe110b7b46b6088fb31542b594d6636328e6cfa0e1b573bdca5f3ca993213887d74087e2c","nonce":"8b12afe06aba01dbf3fb4ad8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"187c5ec87a92dc6c8a7a1e0ebd793ce17086849674c38b3950065ea1a12cc8d85f41528ecac22c86b8d2edb7f2","nonce":"8b12afe06aba01dbf3fb4adb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"9c85f47168932b7aeea2021d4ac4498a11f4c8f044abe138993d5e75de8391bf16755d3023bc62ac62303b1a84","nonce":"8b12afe06aba01dbf3fb4ada","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"1c53da0969b652a0e68487cd8a5c37924fb5bec3297cb1b76895e8aa0e15c8a54557b224e00d60a70b71ba9bed","nonce":"8b12afe06aba01dbf3fb4b25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"eba9e7b2561729004a41a63a0d0a8c0c32df6ac648bfaf2572921eb06bcdeab8"},{"exporter_context":"00","L":32,"exported_value":"bd197199251b848b7be9541642ea42c9923cc877617e21086abbb09a5744fce4"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"65c80f44834b083b6c03167ea18ea488e31d889fed20081c9bb621a086c8894d"}]},{"mode":3,"kem_id":16,"kdf_id":1,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"0c8f261cd3b28808a654626ad4c5a317b60b4214e2413060da887888b8e92044","ikmS":"3d54b26abc25308fa2afd191c70e061af37aba14680095e3c5f7d479edcc618e","ikmE":"0dab8c455c70e2b3e8aa005079c549808aa962acb883b9785be1a9dd8df74516","skRm":"aa852b071565f4377c61dfe1284b018ff95d9ba5f57fe00e062657f118bcce5d","skSm":"5a139206c68fb86dd348e809a4016171dc8cb1014e1930d805afd4ba65dda45e","skEm":"3c6be324b2ce4714afdfe35dc2a89080eea77fda921501319edeb60ba2fcc3e9","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"0418c1b436ff369770e1cb77f7714153a5e5813be25ae73a4087c5195388686e26d6c163796894481d049156477aed1f00f8bc1fc9d752695fbe04487c4cd6ef60","pkSm":"04d03feb9de4104308b301f1dbbe2fac0d9ca17a43ce6f77608202e3315c62969a40c5f5e1c8090233a1c875b929985388d75a86c49a9306392d1cd7bbf74f22c3","pkEm":"041f60c33669011334c7e381f62c5721880703c0f3c3e4f48fbbdcbf634f9c07c6501b15ae5f7769f5d322a7ef50568ae68042d7a1a446fcd5335f4b398a81bf46","enc":"041f60c33669011334c7e381f62c5721880703c0f3c3e4f48fbbdcbf634f9c07c6501b15ae5f7769f5d322a7ef50568ae68042d7a1a446fcd5335f4b398a81bf46","shared_secret":"99b4c46712a0b8743e8e0d64e565654a3cb00a010ca4b2075d6ccd8f2b975db7","key_schedule_context":"03622b72afcc3795841596c67ea74400ca3b029374d7d5640bda367c5d67b3fbeb2e986ea1c671b61cf45eec134dac0bae58ec6f63e790b1400b47c33038b0269c","secret":"67ede433394c24d54c79d344501b554f08b203757a5526be4e80ecedd7fed7a0","key":"adc8af7c821a748315c94801694f2b2dcd1ec2df8e7dafdb8a54b708eb8caa0d","base_nonce":"198f11ca53b11dfd8472dd1a","exporter_secret":"c5b58e033e236a420ec1ff056c8018dc77ad8eca6ddeab0e48f081d29fa49afd","encryptions":[{"aad":"436f756e742d30","ciphertext":"1036b955fa72326b07755abeaf034fb4e78513599b25928a84b61c593c3730e756458d37119b8f576976113e19","nonce":"198f11ca53b11dfd8472dd1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"87c25e56a88e802958fa2fc41f012971eedb6717f61fbe5aa1c513c1f23bac00357e9b19a6c3ec17f20b3ae7e2","nonce":"198f11ca53b11dfd8472dd1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"96d27aa40b0d71d76125e1d2d90e0602009638e4df7cba8faed64a632b4b1c08d5c6e1d542c76f667b82a5edf8","nonce":"198f11ca53b11dfd8472dd18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"13596aff4bd10d758cb67e200da110d969360ddad3fa1b7f21e0da8ca6c211e31437d4cc33bf3bf74e781cbf93","nonce":"198f11ca53b11dfd8472dd19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"ed623241d3265fdbc0bc8b2efcf1f758729819f1dc687e0a29b9eda1485bd410657511f0d5dd797d25c63d6049","nonce":"198f11ca53b11dfd8472dd1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"1f3a8986f3afec8a89d6b5b3fe9b78ee34bc4804483dd9ac5197cf3d2bbcaa7465afa1bf72281f0dd7e0b8c9e7","nonce":"198f11ca53b11dfd8472dd1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"7bfcfbbaab584cd0bc2bf40b7f872a408b951781d274602de1ddcbb787d0f9ad9e214ab18f455bec49712d7747","nonce":"198f11ca53b11dfd8472dd1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"f53cee7922540d8801f25539ff019e6af5dae31ba3f1eb8ccaea151c18ebec9cc97a360982841e4de84ad4ffae","nonce":"198f11ca53b11dfd8472dd1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"a61f200101394f3615556463023d39493b34a8010365c57fc611f8c5f0b3b2faf4c939b634e1ff1e8c6328cd27","nonce":"198f11ca53b11dfd8472dd12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"8167192c153f5d7f7a337c376f9b23d70164e18a623d14082fd8014706c037decd2b040712af2e6792c53c5e73","nonce":"198f11ca53b11dfd8472dd13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"05d44bdc5e027239f42b28d674692e3c6576dec1fac5523b6652c4ae159764063dbf45f5c67a5ddcce2f1cc24a","nonce":"198f11ca53b11dfd8472dd10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"39f1b6aa2fce613a2534db3b821ee37ba41a8f36cea6d4c6bb0a0ad85408e2e6460d27d350b412b71d2c61f2c2","nonce":"198f11ca53b11dfd8472dd11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"71d7bb4034957d9476ac1a5e2211a926d715f8545f4a04776dad30fb681213b6bd47744e0bcd7006b84f79dc98","nonce":"198f11ca53b11dfd8472dd16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"8f41f7683722afb8d8dac9746e4701cf0536e004d9e3f04aac6cd8323558c0a4b736f8b6f1576c95fde0c5d2c6","nonce":"198f11ca53b11dfd8472dd17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"ddea92b57da2076f6ed340622f6b3901b51c715751348c2dc2438568bb7ffe96b42a6f358782b933c7cd573c98","nonce":"198f11ca53b11dfd8472dd14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"8d36b8e29af3e9df1ece6354fd8a37f783f6e98167db88725dc9f41cc8d97c88bb2e273a8c04521983ee64e996","nonce":"198f11ca53b11dfd8472dd15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"432b4d9dd05d68ea3911633894ebc07156837de3ebc9954b66d6c71e3796b193f057b27efd99947227e267563a","nonce":"198f11ca53b11dfd8472dd0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"c5af8985fba9001fd370cb8571e30ee27e7b923a1d09f0f7081a5b5121a92d673152f391bdf1dcc3c9c45741fd","nonce":"198f11ca53b11dfd8472dd0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"b05f15e102d72797fd416914139a1b02dbcabc093c95a18c49ca9f04d5ad396226d77c0d2e410198807a08fe30","nonce":"198f11ca53b11dfd8472dd08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"3248fe46c0c555705ff03425667327e4808326ba0357095f24ce9527b7a254db1257fd8557073c11d1e3b047b7","nonce":"198f11ca53b11dfd8472dd09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"e7eb58d256fe9c24e7a74311e3a0c0a44524fe577fb37ae839d383cb35957bc0b2eab720e9adfa3e79f4b994f2","nonce":"198f11ca53b11dfd8472dd0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"ef2959d265dca5de979bdc7727065c6f5a2fec63f608063b45b6b7127860a1be5923747dcf0abc8534aeb8e7f9","nonce":"198f11ca53b11dfd8472dd0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"f955acb4acdaa2778b3a894747b7487fa8fe7aad471d42a61021220905c36f5d83fea5b71091dd1259994d407c","nonce":"198f11ca53b11dfd8472dd0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"d967f202c25f74f56b7d1c2ac29ffc311ba79fbe0f8372ff94ea270da675c649b6bf0e8b0b6b185ceb3640ab06","nonce":"198f11ca53b11dfd8472dd0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"d3c06f473231efb9388bd86c22c4e292f7ce6823c6ff0fc3355e5bcea29640f8b12b4c0dc93627131816ffebc7","nonce":"198f11ca53b11dfd8472dd02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"810ec31aa905c8fa8fd5bbcee614510368180db74b53ff15b52b7ab43907e3aea3d1bd84e1ee682407f67adb74","nonce":"198f11ca53b11dfd8472dd03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"c1b9924e064a070ec558e168ff81195b4cfc22f3884b56fe1f50f1e464b2c0bdfc87f0f105760f57241cbe34cb","nonce":"198f11ca53b11dfd8472dd00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"8f7063e65cd2f8a7fcbb5e56160784c5a40417433a58e7720650be3671742d25529140e07dfbb9b9b04ed19b5a","nonce":"198f11ca53b11dfd8472dd01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"79bbf771954f549c336ff7255c10b03ac4b776c7fe1514c5dd55f0b80860006ebb93bd1af49c0bfc852f2b1ae0","nonce":"198f11ca53b11dfd8472dd06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"a3ce06beea57260aa37fbb920d327763d0ca2efbba37e047aa705aff91e10116495b2797cff853b813786fc61c","nonce":"198f11ca53b11dfd8472dd07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"e692be2d8f5678a55dbb577cc50c8d8df82125baf4441fcf6d6b02624b1e2214670ef6b16535b24c5902f3e251","nonce":"198f11ca53b11dfd8472dd04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"ea4ad2ea0b8e72b9c64ffb0fef409eb130530d4de88d553a705c67eb99bcb9504726e7afd384bf664e8788dad1","nonce":"198f11ca53b11dfd8472dd05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"e11a12f605eefc9bcd158cbfd37e911c1b7ee928b11e12bc7bb6ad8cbb03ce84140e39116646ab89cb65b501d1","nonce":"198f11ca53b11dfd8472dd3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"a759cddbe7cc57348e05cd3839374869f4eff0dfceeb4389bce2b3f1a579d5d542f1ce4e6b85f78f84c94a17f4","nonce":"198f11ca53b11dfd8472dd3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"1839b1f418d8a5e980c2a200628ec38c6b6ee9b0a4cc7f63c26289a5fba5da89117fb8e28a27259a01b993b3f7","nonce":"198f11ca53b11dfd8472dd38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"d6e294f9ea3250be6123367eec4857132d7e5c6f168665a3c9768c8cf43c50f9ebf659bce0cdf7df306801d09c","nonce":"198f11ca53b11dfd8472dd39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"ca5a6cb4ab976b99ad04f30dfd6feded7daa70c2c09b0403aa77b137a58f6ae7612c4c9dcafdbec93266cd2702","nonce":"198f11ca53b11dfd8472dd3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"a9d8d35327fb8816c749b01f81df6d3349f61fc8459516a5262f462cc865d8e02a12b803c424cc6b27b354d075","nonce":"198f11ca53b11dfd8472dd3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"07ee92bb434c4b16f8a9980e5263d07a99432d863ad6feca3400957e8eae411c208344d1a168710109bf357a3e","nonce":"198f11ca53b11dfd8472dd3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"47d924364757a0909eaee15612d7aa3ab304ffed3caf674ee256564cf23e6ddff0895ea435fba8cab5ca50c2ab","nonce":"198f11ca53b11dfd8472dd3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"e00a71e6c46fdf6a8e2a5094658352d148f2b9199eb0ce846215703f1a6fcce4d47da8a8fe4e29df3feed49f9e","nonce":"198f11ca53b11dfd8472dd32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"e9fe242ab4583c42bae8a84e7e55bf87cb2b77ed9754f7caef73362cf3fab64b520e3220b7dbd763111026ea6c","nonce":"198f11ca53b11dfd8472dd33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"20cb2d8565b5bf31fc2b8a08077d5ab7f43f81a37d832daaf041f2540c1b1222f68fba104739580fe334dc4b6d","nonce":"198f11ca53b11dfd8472dd30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"d6d764eda13f6bb00b44c55617656cd5875ab745b077a6cbbec0925318b551ddc1e14043470fb3f35c08417190","nonce":"198f11ca53b11dfd8472dd31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"2c196527a92e547ab10acb22da551b0e56b9e931ef69052ca566c4f6cdae8b7fc53a26cd928c6097b02449a6c0","nonce":"198f11ca53b11dfd8472dd36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"5a62eb663f487c041397c05bcc9dcadd3ff1d6946c7fe8c0d20f2e2433eda6f67ea861173bb08bb338e5781773","nonce":"198f11ca53b11dfd8472dd37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"edc1ebe0614eacb60b129d77d8a91fe7441d38f9b07fd76e229de2dd0d660f715e4dd370900b66e971ef41a06d","nonce":"198f11ca53b11dfd8472dd34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"ab2ba89b4006a1a014cc8ac4fbb438644a06f270c6369996b61559c2779e80bdaf5420107446db881c33269ca4","nonce":"198f11ca53b11dfd8472dd35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"6b99e55ef7d4d035bf443aa5d203914a9aef021907b0b229d25b8e42c2c872bd4a078cb7e223f74a2cd076297e","nonce":"198f11ca53b11dfd8472dd2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"e02464bbfa138437357563c8b67633a8bc2a6dfebef63ca37114ad4bfe9fa8353d0e768d5c8874716b6d79f704","nonce":"198f11ca53b11dfd8472dd2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"cca81456f4ff0313947cd9524138e14710507947039e3450d98d3a4b1440cc45e85d5c4ffaa760da792be1faec","nonce":"198f11ca53b11dfd8472dd28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"cb306dad2f2595ba7858571b67f83c8efc5284b34c1337ad06d6041e60211b0e3d66072fcbbcc8763af2bb7b31","nonce":"198f11ca53b11dfd8472dd29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"a2f9303be28184f7f7dc934c9958aadd914bf08a06c90fbfac9fc82355baa8ea75948bf41ac7dad2b90b17804e","nonce":"198f11ca53b11dfd8472dd2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"d9ba5160c17448c4ed429fa0d1b24d9bde2eebdd0c7b837afa7e894a937c38f57fff0c37af9bc21f578bd86a51","nonce":"198f11ca53b11dfd8472dd2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"a2a94f43eeed5f216318591a8ce274b5dc50b5cd37a62d700255fb17eb9b4ac4a178dad89acf58f3cedd4f1657","nonce":"198f11ca53b11dfd8472dd2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"8772de7488b2d254811fa79dac859f5454ae090ecb86af829c023f8c98f192cfa3465ae6c493f5d6c9b212303c","nonce":"198f11ca53b11dfd8472dd2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"ce365f2ff2ce789f46c4a58a049f656fe0a7839a864fee5f7207afa824a3c989a260b3dc9295e8d6c4476672ce","nonce":"198f11ca53b11dfd8472dd22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"f11a76494ba37fe78c9c036bd8357c5b5ac1ee7224d6c2f7fdff952bc4eb0fa6ec500a72f39bce4ededf02c223","nonce":"198f11ca53b11dfd8472dd23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"09f9be399d69caf5ffce5db43f6217ea9a47b9fda6c6aaaa05d8d28f8bb3aff4ac40f4149fabb7b113d7006caf","nonce":"198f11ca53b11dfd8472dd20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"dedf84cc305a89941dc7865a71d5d039ea3c09bf6477b243ab54a7be89d3600a10c6c9856b4895141206a85a04","nonce":"198f11ca53b11dfd8472dd21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"251cfeac014b326223dc34ded078f0fe0e40b5703337cb63a25dfc2b2a96062372eeb15b8298c160230a9d23d4","nonce":"198f11ca53b11dfd8472dd26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"f715b678014c492afc4f905331d9fb2613c33bade91d6806a29bef0669e39cdcf7a96484b2651b28204a1f1e0e","nonce":"198f11ca53b11dfd8472dd27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"87abded80da78282e44fee66deda5cca9756f0913905e334771b38b975496bd78e76878e6f9b1dd92c3c6fcf45","nonce":"198f11ca53b11dfd8472dd24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"6a116f99984d3f44e95cd0aac7fcfbfce2715c11ce07764d1d84eab003b2061c9a1e5816f5145e2c5b96db70f2","nonce":"198f11ca53b11dfd8472dd25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"2cead73aa751d8f0cfbd29e5b17749c4fc05f57bba087dd320e0334b7d557f4238fc559ee06c021f131022769e","nonce":"198f11ca53b11dfd8472dd5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"680bf3732e222af0281a98d8808edf27b8d5db56c925471b6a2a256a50e7bf4acd66f13f62f1f2fe4cfaebbf08","nonce":"198f11ca53b11dfd8472dd5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"ee389d426971d77a892ccac24925f364351af4e29c3e2b958ba61a7644b2c718e84a4155260e68c9f81afc90ab","nonce":"198f11ca53b11dfd8472dd58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"12623cf68b53f0f369c0c5f156f78cb0148c1a0c5ae93b79c0348fbb14edd7c2ce38e5b6777182745d4dd6d689","nonce":"198f11ca53b11dfd8472dd59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"65e4187d23d7e670bbb5979d4d8bb50d8abc5c717a2230f5542dfc411ad833c63b7fb285cfaf4d8e32dd18ccb0","nonce":"198f11ca53b11dfd8472dd5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"2fe7f277b8931bd60d757487111768f511b54b4dd8b29f0ddc03c05f399a14601b913ac841defd0ee88ee1ea52","nonce":"198f11ca53b11dfd8472dd5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"11b3775f2dc10e8ddbff4bdbc34ee18a56d1a717584c0e9641e7f5b37ad2772b4183c058dd30b41d9d0f99d6b1","nonce":"198f11ca53b11dfd8472dd5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"9c33fcc9ed3db4c11f0941dde30c9682d98c57f281c251891de29ee066d67c74a3e09c734c2a2a80e10cff98da","nonce":"198f11ca53b11dfd8472dd5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"a391ed7258f84b7bd0a035f93de0fc30ee75f0db3ecb043565e941dea5ea289b2bc48fb9769360e6cdc97db8ab","nonce":"198f11ca53b11dfd8472dd52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"82f7461bbab51ea518eaf2e354b7afb75f59d377e00bf57c6a225d260e0cc0e94e9377ab42d22a21b05f761377","nonce":"198f11ca53b11dfd8472dd53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"7182ff51754ac76e3fefc315f77a4cc5a4876fdfe999404ab3cac16e5a29dd7881408e1b440777e213be62662b","nonce":"198f11ca53b11dfd8472dd50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"cb5f498b12c3df7c8690076e88af14f5e7f09f78dd3d39aeef802ecf074c667a06c53efdcc99c07069703966d1","nonce":"198f11ca53b11dfd8472dd51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"e0c5246e9725932b724c66037a792895119b462dfbb333d1a9241a50beb6c1c5315686ddf6deada7b8e6b81d74","nonce":"198f11ca53b11dfd8472dd56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"ae8ef30503908885e2c2c749977dcf1a3bf3524c3ed73a02e2e7447bfe27ed605c76924c7ca7963aa8826834f9","nonce":"198f11ca53b11dfd8472dd57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"d049cb63bdf9ed0f6a1cedceda31692225de94557e88f13eee9e09b435feb407e1a1b5518f70e00c514c7e71f6","nonce":"198f11ca53b11dfd8472dd54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"7c3b632086b0cba3245bb85094df84348eb4a4f9964421e1ab2e350ec327f674b29b16220e8b45dc8c06c4c713","nonce":"198f11ca53b11dfd8472dd55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"e45c6ff5397908aec5feeb80efe00f3a24b3f052f2f5e35a0928a44b8a2988e596c6ca10ea14ea61882b867227","nonce":"198f11ca53b11dfd8472dd4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"4cca90ad3dfc5940c3beb525bb25b954ed4cebf0ed0a8d61dbd7aee6428ee0a08e5907e07bc0504fd207813a4a","nonce":"198f11ca53b11dfd8472dd4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"4d4ce368b6702ab8a62c7ec4390559f8a710644f843a91520fdf653bc80e63985b7f74ccddd50f87c850bd3cf6","nonce":"198f11ca53b11dfd8472dd48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"38e59804ea25aa21cd66ef766c7bb51a5995a29b67555d7eb88f0b3c02145e592d981b5a96c1624f91453a9ad4","nonce":"198f11ca53b11dfd8472dd49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"e01a238f50da330c9e9570cd3b7d840122330ad3a0194b0d16c478c190c3c503464381d2702b28f4df3857e419","nonce":"198f11ca53b11dfd8472dd4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"5771a381a77a28e7ea1c78ca1e023c21b49834e168063c58d5613a379fa8860c953ca1540aa136f094a9672201","nonce":"198f11ca53b11dfd8472dd4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"bff0f4040a0d854c7573463c81f1a543434c664037477b5ff94bf1a1bb609bd7dc56dee52e6282881e6ed6a1fa","nonce":"198f11ca53b11dfd8472dd4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"a7aab6546b2a4b9f497e4d9399c20c2b63ac6a03cb8e7d737d2e02289e4c4c89d8dc5767fbc613e57c4e38bb57","nonce":"198f11ca53b11dfd8472dd4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"c9c3a799a59ba49083719703995afbc59231e3bd3374533e4248ad76435ea36977c5503b75dfa24173e49bb524","nonce":"198f11ca53b11dfd8472dd42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"62f5e3b4529edaffba07cc337e3df6e332a88f40dc84be039b76b767dcfc59c485000cea1a6cf523e51245badb","nonce":"198f11ca53b11dfd8472dd43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"ba02053bf876c76a809c622dd7930213bb4d7c5aa6ef6f2a2dd705d01910eaf038964c2a38b61d43a5b43f9d21","nonce":"198f11ca53b11dfd8472dd40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"a3c4c57c7c9f703ec8e29837e82c9afa58103b4834343e52961aac60141152effe62c2352aec5d49661c3a0ead","nonce":"198f11ca53b11dfd8472dd41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"8f66b33d9b884e65b6214e2f17a6f055190bab2f783314f7dad74e33181497b88ae341bfc852a3ed47901dd330","nonce":"198f11ca53b11dfd8472dd46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"2d1f1ff000780a8f0ecbfa1c228e8cb787f99f2750f7e8ca2c0fcfc4930bf41bf385d3a2ec1188605d6c956ea6","nonce":"198f11ca53b11dfd8472dd47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"f7fa098e4eb5612e8a93baa426a74bc52238e2ef235eabf3e05641d237615ded84481e6a6cde9f777980767a25","nonce":"198f11ca53b11dfd8472dd44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"ade5ff71e963cf70682a83a6db137a16fee3e8412982996422f4c33f87b54a65906b70569c57c56cb05564efc1","nonce":"198f11ca53b11dfd8472dd45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"394fa7ab962e7ec37403a10a4d3ef3505d9fcacabfddcb23f47695ae861cc924443166e1f2892bf7d49d0616b1","nonce":"198f11ca53b11dfd8472dd7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"dc6266a0ad89b9c54d0435ca0f4e2756be3aa17b4094c6af672a983d6776c58654b86391331446f1d946be36c8","nonce":"198f11ca53b11dfd8472dd7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"7eb97c06f5e7d1773c5d26775282044a60ae0564795403fbe68c52336a8ef8abcec50c8b0f8b59e64157a3771a","nonce":"198f11ca53b11dfd8472dd78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"598666b798281937dc52ec37337c063bab8befdc92020145eff26cf3e758b679a64f3eeffbc0d9716b93375620","nonce":"198f11ca53b11dfd8472dd79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"e844701b4c6d57d77ef0a99954cea536d0fb1bf5e9e1543ec73fd3028e10d890bd6287198b59a5beb3d6ca9ba2","nonce":"198f11ca53b11dfd8472dd7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"95a549eecf804c8f9a827e25b113c991e9e2575af3a7904b313feb34b5698775ece76dbc28611db8fdb50b4797","nonce":"198f11ca53b11dfd8472dd7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"c0a44942d3947330109879e9a70f261f9c6a6dfe48247b815526ea0f0a10b52644b9e6c5ccdfa8412c03fea215","nonce":"198f11ca53b11dfd8472dd7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"b94c30a744d05216bde22cb936b473da7a1107f1c2b5c81288868478a9fd8870b0e1d71af4428d6b148dc06a91","nonce":"198f11ca53b11dfd8472dd7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"9780b54ef45b126d66f28bd047ef3f74cb124f19025aeb7989deafb80f27906d9d927f56c139b06a994cca5953","nonce":"198f11ca53b11dfd8472dd72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"c1ddef37576ff727a24263a64c8816ea3cfc54f3fc36bbc141f4d42091d9d47b2786e1a7aebc2edecdab5bc285","nonce":"198f11ca53b11dfd8472dd73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"44ce458aa20f1571747589f0040cc5012973cef832a03728af0ef18cc912b9cf617800bdd54d4fb2e4f8204678","nonce":"198f11ca53b11dfd8472dd70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"2bd601fb365810923e38446c48dd240d3d907a75f70aa39d2f354811cb8383bdc4757880356373121d9455492b","nonce":"198f11ca53b11dfd8472dd71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"3c2f6ae0b6df3db25a6861dc43892cd3150fb7dcbfa5217f91648f127aa1f1e8873deaa892d80101b58ec0c633","nonce":"198f11ca53b11dfd8472dd76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"46e81d3ae05aee51174e4c363001f494d4faffa4f1beb91e5579114dae23cec4217ce40c871fde4243a9390891","nonce":"198f11ca53b11dfd8472dd77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"cbb9453008ecc57ab1ebe5b8def43384c5325d040f2e04d06772ae9523cfd577b67ad7a3d996bee94b868c02fc","nonce":"198f11ca53b11dfd8472dd74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"135df8182083dece4bd7adca228e11f3749d4469cfa252a5980d1c291488a14067dffc644dcad7504818547147","nonce":"198f11ca53b11dfd8472dd75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"edc7fdd2ce1073bd83b3acecdf03d5fc2a68fe4959f142eafaf18275d64da7afc0eba0c4c7924a9f6c2e9ab692","nonce":"198f11ca53b11dfd8472dd6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"3e1c498c5bcd1195efa95cc61476fa5c2893fda042797c18dd4592eb0a9fd208008008a4d0acfc0e498fa51e25","nonce":"198f11ca53b11dfd8472dd6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"66e1879dd36edf38601d5e8f02f1cf4c6fb3d14b48d274ba1c3193923748fc86b6af65b926b6b8eba8b0878993","nonce":"198f11ca53b11dfd8472dd68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"40b3ccd0634d5c3129a8062cec17da67289377ea801c1e9fedfc4816e16545ae438449e47c0f2c8f01bfcddf31","nonce":"198f11ca53b11dfd8472dd69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"2468accbd4a2859cec5db790afa5651bfd0537ef984b8c95f31902379489cb316abb3111c8ee4d675017c44b5c","nonce":"198f11ca53b11dfd8472dd6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"8d379d13418eba18f3e0eb3c3fe423269d3060b605f1d6075ccf063ca040eeb527ef366677357bd5fd9cdaa01b","nonce":"198f11ca53b11dfd8472dd6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"c5c6ecd99ee820b2d4691560ced433c486c2300d66d95622e635440e07593e826eb87ef6b593308b536ebc84a4","nonce":"198f11ca53b11dfd8472dd6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"23e981d8a3afe981b6f8c22c040c0ecd23e57729c3f4549281a81b1b46d05eeea52cf5755c3f2016d6f8dbd7c4","nonce":"198f11ca53b11dfd8472dd6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"4388b7cef35157a93fe8f7d8c420ed1875d957e08e59c1c318fbd60474ea5bb499ed7a82fea63ee68790e09464","nonce":"198f11ca53b11dfd8472dd62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"360fea03aba911dcc17ec45c425d40b047639604673bd4c6771c443a07194745c08ce57a8e1af3dc15b4e31816","nonce":"198f11ca53b11dfd8472dd63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"efe12ea28f78de30b11634c65fce9ff05ed6d0e42fb1c85102987ff5ba13b33649b01d5931350633d6cb5a264a","nonce":"198f11ca53b11dfd8472dd60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"8c5f27eecf8855f4e5a02d35336143af7224276d0f4ee56941e6dfaa423d6d2977224355bb1a55b28196c51b09","nonce":"198f11ca53b11dfd8472dd61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"e20d5b8d656b94584628a95778b92742207252c650c772045b6d09222b16a0e05739ab17ca8f4636a19f49c916","nonce":"198f11ca53b11dfd8472dd66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"2b7931b30ef3e276117a254ff615bd83a464a690056ab03048e0237e3b513edd3aa7895ff96ccbdff70abf4adb","nonce":"198f11ca53b11dfd8472dd67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"28f3394312af6cf093bcdb1e05be97b7df684f2f1ee4b62096c581402231fe38bfbfdf4a7ce232f6f35d51ece7","nonce":"198f11ca53b11dfd8472dd64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"b869eb348f01d5e13fc9815ce99f41a10e6d09aee12dbc045aa4ddf0cde8ccdf3d4207d786a2304c244ce8ab89","nonce":"198f11ca53b11dfd8472dd65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"eebdfbf641952b8f5017151770908e123a67c7b5ca4e2460fda4c49d59112bec053d03551141d0c07fdb5a2b16","nonce":"198f11ca53b11dfd8472dd9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"69826e2425dd4e51bcb2c6298873661f31c522825395d56bec747d0cc3984bcbb5b5fbeee995238a8b4fb58d9e","nonce":"198f11ca53b11dfd8472dd9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"1091831bbcb0590f90e6005f34076d6d3575af593937b674a99620160339dbd5041b78bac7f3b927f6b01cb811","nonce":"198f11ca53b11dfd8472dd98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"8089ba36a905e850ae1fdab63f10f49319f4b253fc46323945699a3766649d42e676bdb652456f1cab24e2f67f","nonce":"198f11ca53b11dfd8472dd99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"03f7622855875042f7c79362588c304d382b2d65db4ac87254978fff2d81aea616cd8806316682daaad955a2b4","nonce":"198f11ca53b11dfd8472dd9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"5ac9bd6c65e3e7ef212b6d07a85885ed1e7c08f11bca9b00497529b8c9aa204397110d13947f015c5648979b85","nonce":"198f11ca53b11dfd8472dd9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"960f302f079d2581e4b96a55cd7dc85fdb3ac2f5f5e9b564b671c833401464f0eb065be8b720629f951a6108aa","nonce":"198f11ca53b11dfd8472dd9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"26b16553af06a2725674fef270220bdef733f741524fe1c0b2f486e6ebc17b697c00ba9e3c0c697335e5f628e8","nonce":"198f11ca53b11dfd8472dd9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"34eba47bbd36bd934dfb556a41381236dcc01f150ecb893a3a23c117a448a34bca2f14603ecda3e4c0bd03497d","nonce":"198f11ca53b11dfd8472dd92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"b30d374b405e7df0406ac07b1589ce0e31410f307157d3bc8ae308e431f1548e21e8b00f261f3ccc12abdc8b2d","nonce":"198f11ca53b11dfd8472dd93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"7d79ac6fa8c25d3059ddf6cad16b17f0346187c3288c55076aea508f7cb983921166e0eb8447c73e3cc348e9ce","nonce":"198f11ca53b11dfd8472dd90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"44fb17b01678b68bd7238332951b5c27a5e7fbef1d95f1ae4287d9857286e53f9187e18007fb7fa0e97dcae2cc","nonce":"198f11ca53b11dfd8472dd91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"1c4554b0d7f1b26976037724befe727bfd891c36a20f148a67c0687a6dddab31402845d107dc8e60a79af11c3b","nonce":"198f11ca53b11dfd8472dd96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"f74c9b2525a5bcd9f2a6ffe588dbfa806786a5229af7c50045405f1b6667e2678d2722e0bb58ef0592cc8ea011","nonce":"198f11ca53b11dfd8472dd97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"2b93791d67b2ed4fd143ea13a07427771026e7d1f6c55b0e53f5cca2822aefa4591b55c6473a05e5154a272d4a","nonce":"198f11ca53b11dfd8472dd94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"38e207704a324b3abbad3bac9d9f8cc6547bdf0578438e7364883bf15c5708127b9e76cbe3796c9886063ad4af","nonce":"198f11ca53b11dfd8472dd95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"fcfebb9c4cb02e639caf4c7089810f36a05b08435a4321e0d5b440947f4ac52aa40f315379b6a878b6baa320aa","nonce":"198f11ca53b11dfd8472dd8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"e91f931826b6c7832fed0a93fbfe1babac0744ffe2d69a5f1bac1026e83f180f1f2437a03fec931bb5b74057e6","nonce":"198f11ca53b11dfd8472dd8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"6213eb36ddfbc65ef6b07fcecfac6f17770484000c91c3738eccb1b5248cddf3ff9cba491bd71fb0b9500aa8b6","nonce":"198f11ca53b11dfd8472dd88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"0e04543b3bf9051215c42eb10231fb62281e346c53b1034c37e41b60f344ee1a8e41578397c0257c33d085490f","nonce":"198f11ca53b11dfd8472dd89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"52010a30fac33ea8fe92fe7d2456f3eb2268eee43e3fffd464583fb8f866cbfe1f26cb1cbedf2773cf4879f3e8","nonce":"198f11ca53b11dfd8472dd8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"c55c0dd29752a91de84103c8dad576306218d5cfaf7779a1e940f2c0fb0f81c8441dacbb6f0daa2e23753aabf2","nonce":"198f11ca53b11dfd8472dd8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"9cf02c21dd6c6c322cf714cc4cb0f7788f5f0b3d770d54eabd732c93e8806ceb9f1fee955c3de64f5e22d3bb0f","nonce":"198f11ca53b11dfd8472dd8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"dfb46d46f178df3ab6c3154083660d772616e9f6de976474384b2d8b774b0362aa64aaf9819be27eded35e09d9","nonce":"198f11ca53b11dfd8472dd8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"a7086c2e4cc73e4de084d3e1c5dd70d58d5bd483963c594fb57790de50ffe5b28a9a75a78b9da8163adbfb7f78","nonce":"198f11ca53b11dfd8472dd82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"c4a47743e81442fa5ba50ea7ecd619f4bfcfd523ba0097435ca1dd04ed1b8b70995de0dd3d20f886676d2795b5","nonce":"198f11ca53b11dfd8472dd83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"06c3faacdca18943b87b96183cf00ad74435d5c894c8d21059a344bb83adb268f2ef4012fe611d2ccb1d5ccf7f","nonce":"198f11ca53b11dfd8472dd80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"f77b7f50bf60392ff5887245debb29b3aa6cbcad8a5dcbac01a2c6564c3214dd71eea02a3d6383f1cb4b2b6325","nonce":"198f11ca53b11dfd8472dd81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"128475e3aca8f79c922b05be6189d7aad657299998d794621d7aac6b62f273da85d57789652588cc034324985e","nonce":"198f11ca53b11dfd8472dd86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"a144f3677f55ffc706a6af310aa84f4f823b411233b262b2f71011bd15701c11a6e11a575c80bb265a5deba895","nonce":"198f11ca53b11dfd8472dd87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"277302b142f3a1e4db22a1c182dc23acc654240a8b87bf24f049c6bc32171af671f6f898c6db08161c4d9944b5","nonce":"198f11ca53b11dfd8472dd84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"0eca7a9d99db97a833c17862cf7ebedc2fae357f4c2732d45fff919fcfe16895d204bf8e9edaad0068847694f9","nonce":"198f11ca53b11dfd8472dd85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"c57965d5a58abefcd4027497736b009e4e7ccdc6e1ba4ccc579f2a017483a8ede077280b5a5ddbe88dc52c7af6","nonce":"198f11ca53b11dfd8472ddba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"fff89b50565bf8a49f266043f8a2a45a9dacf3d4e078162a37cffb15d2516bfd60bcf7fb32916f9c39b906adf3","nonce":"198f11ca53b11dfd8472ddbb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"50a849f0cb233ef57118b92010c300b658fb75f2effad05a07b07f539ec86684e5950c86bdd6495128b0cc8d10","nonce":"198f11ca53b11dfd8472ddb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"250f359a443967f6086cea7e8a5cbcae990c6c5a690e9e817125a909897cbcb32013b4e2291258e80973668fe9","nonce":"198f11ca53b11dfd8472ddb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"bd52a0b23362871f5368e583ce76abe957bdcd62ded3f3a9ccb6f09c3160d08c7c1a52c19178a5e11322e4f6aa","nonce":"198f11ca53b11dfd8472ddbe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"4cae8850099c0108161607a71163aafea5c4c5629b0099aedf1e0de15d19f9af17a5a9ccc53873775ec0bc759f","nonce":"198f11ca53b11dfd8472ddbf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"8219f7eae3394f5ad1896dabedb832f0966b890629c97c6e1cf276d66cbcf18304baf8b3898fb5e8dfff475ac9","nonce":"198f11ca53b11dfd8472ddbc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"64127a1f53522f3841108c223b4fc1f31fc9004835a2e884b1b2390ae5d90bd273730bada5fa3bfc97179cc43c","nonce":"198f11ca53b11dfd8472ddbd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"e070b3248d7a0ff34775f0ba6fb0114ab81e4ad0894a555a4e3319ee8afe90861bb6a436581cc58bafb5c278e5","nonce":"198f11ca53b11dfd8472ddb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"b2a236684c3f0b065527e5f45ec2e8f1d03b23217736fbf963dc09b9b6ce15d7ef1eb3383a2f7d458181d21aee","nonce":"198f11ca53b11dfd8472ddb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"8eb8030a0fc0967402b46f2a8b6a984ccc20a1b5e904a3485a376312c37c95548588fa3e885c5acb0e97f30d45","nonce":"198f11ca53b11dfd8472ddb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"4d149afccc0ab6af7425550657c87d9e8f3e00952e5992bc4517d5571097331498af765e1a49f144d44c9fe759","nonce":"198f11ca53b11dfd8472ddb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"554160eeb910cdc00caa6ba7d9b312bab36d9222b5c9e32f1a830b1a67fb0283994fa7a17d29eab47c91622bee","nonce":"198f11ca53b11dfd8472ddb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"71e2a943b060d8e9715ed89c5c04cca3e36156700a27cb099af810228b8f1e6b353daebf0822a313f0bc2dc0ed","nonce":"198f11ca53b11dfd8472ddb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"a302394b05ecd595eb615075066c2c6beadfe7e8a07e1b8b7675c56b42c170b49ca02835ad4aff8a0387b340fa","nonce":"198f11ca53b11dfd8472ddb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"f7224882d9702c8a0c14d37d94f64c72f10c04006d8bb9f95f38d97878c66f934b7cd6adc98b443f9d3376dd50","nonce":"198f11ca53b11dfd8472ddb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"0e4b832917985ff528ca4eab332d33d9cfd2d7f563a161877564a124c650fcd9ce538e653ffc6571fbe54e91b5","nonce":"198f11ca53b11dfd8472ddaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"4f2d60e3b48859fb493730b3d94e0afc44c7f72305f3a88bede006e9c1b4fcdd92dfe87c69694f8a4112bfc23e","nonce":"198f11ca53b11dfd8472ddab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"7f0182a51cb39cb7e1df1db94a5a4bfedf3acc3fd6a15f0b12f3044de625a97395267c7fb46dc0f36d7b9d7f83","nonce":"198f11ca53b11dfd8472dda8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"35cdeac3758c05153c7f0f383acb9bfb7d64b588afd728a7a8c124cd7131aae4c0613570f5f8c2c980da470931","nonce":"198f11ca53b11dfd8472dda9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"275e1f5a64273131f1dcb51d651bf59776d096e3b29f0340d237480c56f3f21ddf57630e59ceb0b27cf34034e7","nonce":"198f11ca53b11dfd8472ddae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"827c078593f1f0894673cfa6a731edb0e1821a49e84e85d069c6c0644b9c5a7bbc81074df662a409fb8aa265ea","nonce":"198f11ca53b11dfd8472ddaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"9c3e7b10d9ee8af180b53c72fcd3f85bf4bd966475e0bc63e9aaaa30d4832a8e944ccb1076f87d1b2f90849650","nonce":"198f11ca53b11dfd8472ddac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"03436636d80b78af5447d62200d18351aa96cb043c8fc343947c48594041d61872f8ff06da4df9250e89903019","nonce":"198f11ca53b11dfd8472ddad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"8f1bd59bc54432b3d2ea0be31ea1bb76905421d9a52c67d153ef155ff8166fd2eddb31278b1e79abd0f95c0a24","nonce":"198f11ca53b11dfd8472dda2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"6b008b7a37e633a4fb352174cf8e4ffaffb17bc0930e8b7b8a41c6c96d4550a7e533be9ad3dec1eb369939499e","nonce":"198f11ca53b11dfd8472dda3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"f41ce7116bd652d96d9e80a40afa24159156a8328b691865ef1ce84ac5cb3eb460e62620dd18374c3f0a143da6","nonce":"198f11ca53b11dfd8472dda0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"17b9a37d85e530e6e3308c9e4ffdfa8ed7120f6aa6772c04f0c00844014c87e3dbbe7ce5b9cccb602182a69e73","nonce":"198f11ca53b11dfd8472dda1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"ab7b47afc14ecd4b044a74b387a60a953656f9008159ceda042c32acdae6e8389dd8786c4201f24c266426bf80","nonce":"198f11ca53b11dfd8472dda6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"f3af7100a616dee222bb14c07cac5550e4999908cb6e22f01a4d6ce3fa9abfcbda41320aaa3392367edc74be38","nonce":"198f11ca53b11dfd8472dda7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"dc6ebce546d7a97f62afa0067150b4705582b89f58ff2a3f36e4e5089ce3d223759ed61cf46632c48b882f3026","nonce":"198f11ca53b11dfd8472dda4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"1886e2926e3b73a82e40034ae8deba7ab9e3fdf8f0e2f58c4957ea84cf7b783df9f34a3d78cf68c7f32c5f7b97","nonce":"198f11ca53b11dfd8472dda5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"a996959855ec4fa9531d81d02ccbb416a8a39748527ce38672e289f9ff5d9c6b64012bdbae8f8f082fdae0fe78","nonce":"198f11ca53b11dfd8472ddda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"4b06d277dd5fa3776f8c6ea6a42055cba0820196b1e094ed23f357076533bab7201b426aa4a4a08439d58e6968","nonce":"198f11ca53b11dfd8472dddb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"8d87f2dbe442fc9c8fa044705c22ce5e928bb9d50f5e9b0a2982d7d42d89a5c677aa191f4edec091e98df8d9c1","nonce":"198f11ca53b11dfd8472ddd8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"3ce60c21799e00958a929a5a1a16f5794388be75654205397cd9f0e42cc0fbea2b8f881f5529ccf7345c429731","nonce":"198f11ca53b11dfd8472ddd9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"4a9e4ddf3c8ca8393ad12f78cee8365d8e73d37c99c0c93f0de3b831b983dc321351f3bf5a964ed3b7e155c5c4","nonce":"198f11ca53b11dfd8472ddde","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"db7a0dae0f7e3aeede72cbe975a6073b02cf89b59a05220ed710ff16638fdad742ed520de20c90400d121c166f","nonce":"198f11ca53b11dfd8472dddf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"eba4d28869894b0ee0f16d9bd60566cc4c92dc866b3660830bd499acbb891f7700a0949616a0347e86e17cb54e","nonce":"198f11ca53b11dfd8472dddc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"a2d59c2f23efa7cc0e39cada4b1ca6e8679c3134b6d49ea34c2f35be8950f5995c456a3dee26706dbba29b3f52","nonce":"198f11ca53b11dfd8472dddd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"758e408da025aed980cce89c811cfe718b1997fb3b144121026b6532a587cdc095d6bcba842d005db43f47cdea","nonce":"198f11ca53b11dfd8472ddd2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"5f82801a3cfa593c1c226b16283ab838b442f2e8f5b655291470cf323d32e5568e6d7fc14c97c4e21e57453720","nonce":"198f11ca53b11dfd8472ddd3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"dec76248273b495505c421f2c1e5420155fd5212de03382fcd92c737cd50584f8ad920c1a657cb0dc39a4116bb","nonce":"198f11ca53b11dfd8472ddd0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"22c8d9e3030d64ae5c57055353e72cf34d77a2e65b6c68bf05989d497d151a337b804d3e7c4717872459345ce1","nonce":"198f11ca53b11dfd8472ddd1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"4d9fedd7cc2ccc384f57ebcb5a6d0a80e16ce59be1500e0b69536ba20223ce02c9ed567bb1f9162296b24cc7ec","nonce":"198f11ca53b11dfd8472ddd6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"70b0c809adfaded2c24553e6e58cd14725e406cb546b3aebf682df2b748dcbbf39c4a6b2f9e21842547abe952b","nonce":"198f11ca53b11dfd8472ddd7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"032e234a4d0aa660b381fc9cb39ccd6f9040450e1569e15827330060260204ce3afcf6847a32065e61f4013f3e","nonce":"198f11ca53b11dfd8472ddd4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"982410b373892b0d4f313607509dce2bf6974c78d0b4e28ee877560cd56d13426f4cd1f63d4283f3b4174c339e","nonce":"198f11ca53b11dfd8472ddd5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"99e72afeb15ade9adee2157127709df8f23996b35a3a3e7851a402f6d361730e45a85f49aae126e36d3cf2fdc9","nonce":"198f11ca53b11dfd8472ddca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"c85b323a087b0442837a9b6262355ebd136e7e023c0861793e333ac84205dc426537632ff8dedb504d82077334","nonce":"198f11ca53b11dfd8472ddcb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"2ab4e0819eb39cab02407884197356dff635056f66165eeb38d4a5cdbcc6fa18be50aa35946ef5f5ff23ecba98","nonce":"198f11ca53b11dfd8472ddc8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"b762898fee2b731cc5583c60d8ff29c9ee18a7f4494e9e2cf276934a88d9f426d2a9ee2a1051d3f016d33e87ff","nonce":"198f11ca53b11dfd8472ddc9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"c7846937df5e73c917fb1cfbf99dceb4f2288d3dc8535dcb3922e26feeacedd3b51432ff597061869c57c4dd7c","nonce":"198f11ca53b11dfd8472ddce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"ae3abda17a586158aa182f2f15b403c1d1585a396be07c340ae9860fab6b10e809054e2099def8ab9a33881c8f","nonce":"198f11ca53b11dfd8472ddcf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"1cf5e6d0ccd21388d9b93432d704a3a7c09ab7faed8388776c18dff771b84a825e339e4eeefb44609f03179e2b","nonce":"198f11ca53b11dfd8472ddcc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"153cb8bdb0182201654b13d657923d44e450ad8ff62b55e31754912fe364e6c7f8d6b8a3cc30ee0c90b0497bf1","nonce":"198f11ca53b11dfd8472ddcd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"7123ec1c991abb40eae9fc84d08b5a9d4f8c8140f9160d598e05c14c60d8404b05fc95665d27dd4c779c34554e","nonce":"198f11ca53b11dfd8472ddc2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"5d7d1ddecde51b1b0f1e2ddaa79d1084df6a93efd3a33ad271e25831d4ce45273c3e36e91f98615ddf3e850298","nonce":"198f11ca53b11dfd8472ddc3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"e340b282e6da577c74623916e9c91f8cd3168e4e5dc47a0c088ab27ebec4689d433fafc9fe72c3dc2f4d99bc0b","nonce":"198f11ca53b11dfd8472ddc0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"f243d50c326e922f9adab61686f8a701da65e88c3b7c4766a3a8e5aae0fc0ceb483a8bffffa218897a49a077fc","nonce":"198f11ca53b11dfd8472ddc1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"124902c5366b4cab772ff34c47608ae7dc9ea95906044aa082f6d9d811bf814867c87768c08c5ba25710761245","nonce":"198f11ca53b11dfd8472ddc6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"5cb92f913622db1269cd8b1c17c592fcedbc7b311a758f5a05033f1a8164ba67dd802c055b235c8f4d39770dfd","nonce":"198f11ca53b11dfd8472ddc7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"4b017df4b833bf29ecf105c2593aecf89b0cf5b442c76bf72d4ea61ef9ff84a8898bd09e16fdd71436b0d79581","nonce":"198f11ca53b11dfd8472ddc4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"42167c74616bdce9113c7518bd5e7afa9f7f190e0f312621ff78058c474445a69e25890bfe56924e4012c45cb5","nonce":"198f11ca53b11dfd8472ddc5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"1937fe0adc5a90fef6796a9be65fce95a9bd5d256e563dac3f99581b8b1561da9ae13d62246f1bb1746a9956e6","nonce":"198f11ca53b11dfd8472ddfa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"2c5c08c8dae32d4ff1a99fd6c1ce3a0a46525ac7d51161ec95da0d3bfb277d84f422968dc1825f1460bb497c8e","nonce":"198f11ca53b11dfd8472ddfb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"f1fd0682d34ba7b0be77a3f911cc18714bc5b19e97304d0b8493239793c534cc0c3ad1f4ff1032ae648fbe531a","nonce":"198f11ca53b11dfd8472ddf8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"201171a7d370d0525662123b3c754309f67f2a136c9e3e13c88994710ce2d6548fae19a7b2453bc7ca7a7c2904","nonce":"198f11ca53b11dfd8472ddf9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"3072d36a102906b75be36f5d345f4ba2253af6a78464a777c63bdff338743b9a397e20eab9ce7d5958b18d4327","nonce":"198f11ca53b11dfd8472ddfe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"7f70b0f628ddec320e087d7a4fd7d7c7344bed7e1a7e20128bae8c75ed1418ec2a427bf10caa68b6a19d504fcb","nonce":"198f11ca53b11dfd8472ddff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"907e9fa6258b90acf23d6501ee1acdf0bf918a95aa03d42dd88103ce36fcf3bb49a20d59125dc99817d57facd2","nonce":"198f11ca53b11dfd8472ddfc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"064c9cbea3e8ee9dc6f6d32b7a7d0ab63188adcdb8291522ce0b6ff00c8ffe6f3a66ebf65fdde109851c4ceec2","nonce":"198f11ca53b11dfd8472ddfd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"7efb1f2b302e9ecc6b826d3caa5eced34eddb26a073bf967ac2270971f95bde0814bb8b7028ae9c6ce1917cd20","nonce":"198f11ca53b11dfd8472ddf2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"8361924e2f5bb96bf67cf31e65fb3b6d409d8334568681549186b4f06d0bbb7531b30f07bd71ee0f637756f38c","nonce":"198f11ca53b11dfd8472ddf3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"d5b186ffa3db1264795f206639f09ac0d0547414035c014dc83d9d1c04f46a6a3044edd181b6049ed85b7b4f7c","nonce":"198f11ca53b11dfd8472ddf0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"4a6d1066f4b329e42b828bc6d05ae68951095e14bbb1c22df8ee85c82edf94a74818c6081720ca97d048175d26","nonce":"198f11ca53b11dfd8472ddf1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"1350bf4d6e3c4794de76a518ddda0533d44d0e1cf0efffbb561c6c85b4b09cf057e2e8ba8323c6c65df76955f9","nonce":"198f11ca53b11dfd8472ddf6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"6b8c1fb02adac8ddff906435e61a9ccd383efe54d87c18b990fa47dd683c758cbd0b65cb893c03dad8b161f3b2","nonce":"198f11ca53b11dfd8472ddf7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"c7e37f9ee5d0e0b16c39cdac9d2131db4c7f976c6ad9114feba7e30792837689663589cca8a62df5ef18b343c8","nonce":"198f11ca53b11dfd8472ddf4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"d3d6a6dd3b04081648ef4bc5fb35a73d710ad082e104c8a9c49b4ebd759abfd7ebe2a518efe5233f336818150e","nonce":"198f11ca53b11dfd8472ddf5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"8559f7f1c43b3b2efaf979dd554d7aba830a47d421b8fbc7dad0b6d9236c3c7d9886baefd4d19c9b8d485a5656","nonce":"198f11ca53b11dfd8472ddea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"e227776e438d594dffc6b90cc3dcc290bcdf0a275f70c6610dabf20b7d116fc02a9c6353bd73b5573857ac794b","nonce":"198f11ca53b11dfd8472ddeb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"d813bea4887d1aa6b17d03302ce1b13c8bb6ff52726416aaf0b0230c87fe44c29a95b72770f99c8c73f9b6900e","nonce":"198f11ca53b11dfd8472dde8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"3e317a0ff9ef67863f0ecc4a039d7fed92410b3efa8687541e6eda450927e0e43f4dfd251050882b2c61b03585","nonce":"198f11ca53b11dfd8472dde9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"7954a284d898c4ad87d0a5808e02d335167a168367eff890df160204de27700a936ff42e7f163a69fee89c82e0","nonce":"198f11ca53b11dfd8472ddee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"7c90bd8ff6ac93cf1ceb93d447c7e1f746a6241ad39d27433f3974f5ea49f9a26f6740ddd87f396cf1b4e4a15c","nonce":"198f11ca53b11dfd8472ddef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"c2da9ee3686778adbf575714db2f36ea110277b79dd181939fff682b793e377359019cc984df6d0490af56ed74","nonce":"198f11ca53b11dfd8472ddec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"15f4e4ad9a2c86fa3edf84cc4a40a9e01f839b5c12fb097a3326794e337b2b8989ffc6f6dc709691bfc7e3640f","nonce":"198f11ca53b11dfd8472dded","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"1df0eca28f94fd556b7ed27ee7c25ab2022569d7cbf60b157f598156d4f106904eeb5f4387bfac8ca0ad56e33d","nonce":"198f11ca53b11dfd8472dde2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"64f4037bbe2280defdf51031148f20ec198598189538fda14fffe56c6651fee0bd1273e7ace829b3b464ad2979","nonce":"198f11ca53b11dfd8472dde3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"8e6bc7d16181614dc48d4cda8d969f99d41fdd620858686f64fbc5e1d63148261a108b2a84b47c8bd653d67aa1","nonce":"198f11ca53b11dfd8472dde0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"496cd10b12f0c22993c7a434ce94722d9e7950b33114b9268adfb344adfe2bfbf682a58c41581ec4f024f0768e","nonce":"198f11ca53b11dfd8472dde1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"cf43c927e92c71c96e301aed4dd64bf29fcb8e8807e5644200e2399a706650584a27759309af834c6385ee4250","nonce":"198f11ca53b11dfd8472dde6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"05e15ff5902e6079945311425694763f005654435e0812e307e8f184cc75dbe659fe4e52ee23d9821043e4b143","nonce":"198f11ca53b11dfd8472dde7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"a50d92956b525f0d5764a0084700ad868dd3155581c3cf90b2eb6addcbdce11b788334ce201fb9ab9f64ebd879","nonce":"198f11ca53b11dfd8472dde4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"9d75b0f1b7e69cb8a0e2dce87705070ecb5fda34a45224a0e5841206a48acff4d529856aa14c92fce1484b6d42","nonce":"198f11ca53b11dfd8472dde5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"59cace8e1405fc3e21c23482711108842e010a29b539542b10449f0150800937d7a29a31d69c52920048df246e","nonce":"198f11ca53b11dfd8472dc1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"c8e0071643d846c1c8fc96c1dbde3f8b360ed4c7b751fcfc12ec8a608c8b1a68"},{"exporter_context":"00","L":32,"exported_value":"ffdf33b89269c9bbfe72e5884a14979ab9b75d12a9ab4d76eb8f0e37c2da86bb"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"4ffffc850b4fdf16a5055b82bdfc15862f2859d46bb1e1ce7efb00dc8463e58a"}]},{"mode":0,"kem_id":16,"kdf_id":1,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"9b9fd502f866712618a477f19e2ba9f303e6da280d02eba07d878cb117383f88","ikmE":"1efb859fa7888fbaa8e71e2d29d3a56a2d0e6ca6ed43e92db69d17edcd0f27fa","skRm":"d5f480bc7579d7c592581a319d7032b7fe26688e92d6bf6139e3c3ac19a030d2","skEm":"daa43c3b2398e626a2ddae2b6e02b99980ac25abf5629ae01a84051d9065b19b","pkRm":"0443463e63315858782b4e1d42838f4940fc6c151c479341c4e106e5c06319b9f5220322af76f9f367b8a2cbf93a67d9f7e9199ebb4aef13a51fe9e8788c8983bc","pkEm":"04c4536d017916ae1e6b7e99b253442436a71969388ebeccdbd07b905546bb53c4410fa81ee56dc8f2dd43c839c90978d609ce86ef2b7335d883d7e2f37c651caa","enc":"04c4536d017916ae1e6b7e99b253442436a71969388ebeccdbd07b905546bb53c4410fa81ee56dc8f2dd43c839c90978d609ce86ef2b7335d883d7e2f37c651caa","shared_secret":"7269d8d898b14c5f1012dd9102cf9aad6ef7cd9c2c122c8b892e951465520000","key_schedule_context":"00fbfdc9526168162fadfd17fe227356e9ffe3afbfc682ca8f7e2c2fa25fbc0879667157ef6a763236715d0cdfae0492d26fb4f02e2c8397d5fc765a529a167374","secret":"36bd97ff1dd9ab360b5f2ed02bde500b3c3eeb3547631d3536bff64b252f4178","key":"","base_nonce":"","exporter_secret":"1e930e914ef4a38d63ac2d35b3f5ff931673d76fa6dbc2c9992055199d0563b8","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"cf835b3ddf20ebe5ec6ef6ba79ed4e4f22c79360359791b23c714e0cc4d22478"},{"exporter_context":"00","L":32,"exported_value":"c6625f9f9372e249a6295215934f99c16e5ef12440661fecf15c3d7198d30726"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"1f97ef6605d71ceca7227964aec66c4abdd2bd94bf200a4bf4717b71bd5f1b0a"}]},{"mode":1,"kem_id":16,"kdf_id":1,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"4008cd5a4407c13996704b720f6bdffda2cbcd61cb8a8f409795cb15d913f727","ikmE":"b331e7df7b5ba46985d999475ab7597c5cf5cb0ac5fce1edb0a819218c900c50","skRm":"eb56f0eecd4cab6058d508d1ec3af6683ccf228f9c166ef66ea1642382a4f211","skEm":"841ba52c6c203a83280f6c12d7ac4fca94c922648cd926eac25ceb35fe4eb5c2","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"043c4faeb19553c2484035b97c760250b06a5d2eb675e675ffb767acf1b3c8fd404a090d7979eca1e31773e96823a137a3cf94ae8560c84b87f9c6db235635a702","pkEm":"042aacca444ddb0dc60add4218ddb1fca2f17a9c789199717539cec560a1344293dadcca55cf11d2dd3958b7ac80d857a5ee7def8c12d1d7dfdaefe3da246d319f","enc":"042aacca444ddb0dc60add4218ddb1fca2f17a9c789199717539cec560a1344293dadcca55cf11d2dd3958b7ac80d857a5ee7def8c12d1d7dfdaefe3da246d319f","shared_secret":"c55f0594e57698dcd312b8a2bafdd69d7496e05edaedcd2063b203b034932945","key_schedule_context":"01cd407d8e0d2de20a1ec8593c390eca58ea35f4e769917ed679892bf590aeac8f667157ef6a763236715d0cdfae0492d26fb4f02e2c8397d5fc765a529a167374","secret":"f5a19455fe67f2d319a1d265802b5bb3aaf4d1b26057d3316ea772da173d4475","key":"","base_nonce":"","exporter_secret":"c004bb9196064f640e0b8358b06798e1cb8a1f4fac3da1d0dc62f18bfed01fe2","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"b561dd20bf5a59c0632149982b658a802891b4914dc37ea198d12d53a35d6cdd"},{"exporter_context":"00","L":32,"exported_value":"559801d368e0feecd707a56c37e559c5b8cb1d2abe520b9f00d813eb4683edab"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"dc2f57e86f6a998c117dbe98373b4fc37080b84b63cc9199b244c95a07bc17aa"}]},{"mode":2,"kem_id":16,"kdf_id":1,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"802f7f1edb4c5f7adfa7e2a52e7ddfad01d8179696a39b9952fb684c108af9d2","ikmS":"b094b06456d9f93888a8ea65ec0645cd1264b2f3fabfc4f20efe9a2650d4d9ef","ikmE":"ce3d6ff9465dbc2538af0a57c742c7acc25cfd8ca5384aaa56358fda3201d3ff","skRm":"de60275ed46584ee7ca45db3cb310c1d1fbc093029e106f7214c0468529b6d57","skSm":"74eb94cb10f350b918e61d4bc7cd5d71381e0594c09df7bd83923e158134c4c8","skEm":"1615c45ad19081200d455f70a809ca7fdf1c05e491996f33190d3fe8b0fd7720","pkRm":"042533d7d75088923c9e4700a5834704d0fe003d8e0fcf2bef94a2864f6184e9d87732c8b329817d41ec512eb6770996d6944bff15d859ae2bfdf80b612d5beb44","pkSm":"0448d9b375ae00ef0fec38ada932ae5391bd9fd8244b26993383ca1f5b9bf01fd5cd14d8e54ed14425fd7b7d66566fd83dd79cace4d5bbd8084fd35d2921cbb143","pkEm":"04e6d353ac2d95637b90ffc8ba77550c6c9ad20978978e19dad16dbfe4501d198bf25a0eef008a39fcbe2ac8449f45b41332ea9a285ba2e395470182c15cfec3fa","enc":"04e6d353ac2d95637b90ffc8ba77550c6c9ad20978978e19dad16dbfe4501d198bf25a0eef008a39fcbe2ac8449f45b41332ea9a285ba2e395470182c15cfec3fa","shared_secret":"d954342bf910eb2b93c9f6314f895e0143c002f370dcc7e424b1356d89b0e002","key_schedule_context":"02fbfdc9526168162fadfd17fe227356e9ffe3afbfc682ca8f7e2c2fa25fbc0879667157ef6a763236715d0cdfae0492d26fb4f02e2c8397d5fc765a529a167374","secret":"09886b1c79db341b806d0a321157b23c2f63b79f565fcff6bf8e75462e7355bd","key":"","base_nonce":"","exporter_secret":"9a3b41e4a4c7a5fc40e389f59aceb35389522edbbe5f42e9dc06723492681dad","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"a98254d563ed5a60e398649a6c136b7bf36059780510be02609f1991f7b8e19c"},{"exporter_context":"00","L":32,"exported_value":"95c67e2a3d85cde49e2d61f1bff56d6c3bdb8052a4945fc4fb3672be28cddc0f"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"980fadb5aa7c28ca3dc59eca1fe2108d4305db213b905a9d6f5fab62adccc689"}]},{"mode":3,"kem_id":16,"kdf_id":1,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"322c0882e6e59af7f44b3d00155263aff4f4bdb2d5118efe26a6171e6d6decd3","ikmS":"9410ba56251edae181c5e0fac542f556e8694be22aec415d4d56d1346107a8c7","ikmE":"1b2881180e481270ea23885b78615154d180e34fc0a22d2c372ecd3dae81f136","skRm":"d345bc6943157521a697e4fbaf3dbec55b2991e725703af51470fb8ba3ed3793","skSm":"67e24d764bdaf0f8eb3b2fb78eccad574dfd16c7207885713be20e88f0590069","skEm":"a944cdcde1f4e9c66390564c3122b34d4d2bac0db3765d100eb7afa7a036df4c","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"046262a6785a482a544de2a2fb51d53268e56636bc0e35ee094682beea38a26aff73e5498f93df77d1b36c923da5558eae1a7d8fe5719667a9b196a4e7ae2919e6","pkSm":"0453356341a705b74e503f075c86317e65a707c997b1ace5bcfa4dd614785ebda17c63db8becd8c602fdbe27bbd6528a132d82062f699861925ed8f0bcab9317da","pkEm":"04d111d5456e85fb7a061e748876c314fd17a2794247e904a6e51c3bdce66a1a85ba56c3c351dfb0ea985f6ac67840694fbe955d47ca92fdf681ce5c95bb71c28b","enc":"04d111d5456e85fb7a061e748876c314fd17a2794247e904a6e51c3bdce66a1a85ba56c3c351dfb0ea985f6ac67840694fbe955d47ca92fdf681ce5c95bb71c28b","shared_secret":"c3065c303143b2fa0a9746ca5076a73b9836fe0f20340ce5a877caac4187b554","key_schedule_context":"03cd407d8e0d2de20a1ec8593c390eca58ea35f4e769917ed679892bf590aeac8f667157ef6a763236715d0cdfae0492d26fb4f02e2c8397d5fc765a529a167374","secret":"ee4bff80fe4ff970f24e3477111d8c8e4d21afd712fbae15ab4edf578bb7827c","key":"","base_nonce":"","exporter_secret":"c7a0b902df00c07efb4aba6bcfd6d8d0058e2ddf04a9091d2c6bdb4f01acb4d5","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"59efeae6ea47ceeb820aed4ae915d65a6a11676a9157514cb5561566488a3215"},{"exporter_context":"00","L":32,"exported_value":"ce41c7d40ab173798bf95b9a36752ae022b264fe9439250df1f5ace5bf7a7d91"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"e06fc07ab0fcfee5fa02474afeaf085a2a73cc1b58ccc073af298857b1f3c6cd"}]},{"mode":2,"kem_id":16,"kdf_id":3,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"04e157810f9ac6f41cd4f34f1bdfe976aa6d69197399a64865b9a05a2e377dee","ikmS":"a101bfa89f76c75127ab4a8e3163272d6b0e8181b2343befcb4d0f956c104500","ikmE":"1de4172bcfcea0613ed7901dd57e039085f7991f6cf5a4e5ff4f18db6cfd2f67","skRm":"03cca98e70145f2e719e78f3722dcaf469628eb89437bd91e11926a20ed550e6","skSm":"1d82c7053ba88b4029dfd57db0eb77ac3cf768644a70bb6e723c93d455530e1b","skEm":"db4e25e7e42523d00b3821a7c41af39bd51782944cced4575f4cc1bd7eb64b67","pkRm":"046a14182d61fb9f3a507f45cdc4b46c6e2d531ed4f34f56bcc0efc88556a457ade99e5c6ed8cecc65c9bcdb0838dce9e300c63e822854d1b719e49546574149f8","pkSm":"044bc49f888e8c531dc9f44416d19743c5827687a1223c564f284c646814f5845567e5a6075b6b90f366a6fe3b171e3a50108fed3804c5fa0f4be90b3383fd37bf","pkEm":"048eaea7f3b2f97a830a446edc645b45e1bb218ea4a53ad7715fae2a24e213f798dea05ca2d6bf4951b9263b7bd63bab010922ba7627c35617d75bcc16cbe66912","enc":"048eaea7f3b2f97a830a446edc645b45e1bb218ea4a53ad7715fae2a24e213f798dea05ca2d6bf4951b9263b7bd63bab010922ba7627c35617d75bcc16cbe66912","shared_secret":"7311fe0d7cca8e0dae7685133e0802bfdf83c1c68116b7ffb7d7231861c05e3b","key_schedule_context":"025b8a3617af7789ee716e7911c7e77f84cdc4cc46e60fb7e19e4059f9aeadc00585e26874d1ddde76e551a7679cd47168c466f6e1f705cc9374c192778a34fcd5ca221d77e229a9d11b654de7942d685069c633b2362ce3b3d8ea4891c9a2a87a4eb7cdb289ba5e2ecbf8cd2c8498bb4a383dc021454d70d46fcbbad1252ef4f9","secret":"c09564d17226a0d8d4cfeccf416bbebdf2e7ce87f1dc7f9cf7dda3d8ce6192ddb6a6179f8d3f0c060c5333ff97ccc22189b6bd7e33bca541e5d298517074d406","key":"f71fb8d0c28bd5d76a337f06607fdb92","base_nonce":"7fc03640bde39e9b173e6083","exporter_secret":"d54619b13e7307e1e5b338f420b967fab3aeed904aee3a1f68b447f575a63070d74e77a3494f7bb5d2db20643c7e127e9d79cec990cda80ce7dd714a535ad1f2","encryptions":[{"aad":"436f756e742d30","ciphertext":"8f1b32460349d0c595792cbab00320ee75c99a49c4593955a11714f1bbeda64a2a98a8d931b9715eae278d3041","nonce":"7fc03640bde39e9b173e6083","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"31450e2b97229cbdb0cd1aab1b06a1d705e78bd00a33bc55219570006c172cb26cc197fef8183b88dd6064c0f0","nonce":"7fc03640bde39e9b173e6082","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"6e19ed46a69d0d246d28fe69d1f5f16a7c31dced1afd0a19b91b7fda8222ae72083e9ef8054653fd0663501bd2","nonce":"7fc03640bde39e9b173e6081","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"203ad5d0511bdfa917b2e3d01cd377fffd7db835b0dfccd90ad9227c88712f3db0fce089cdccea12a11f58ebc3","nonce":"7fc03640bde39e9b173e6080","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"b9b56e290ae56752a4f32a05e59b94c85dae58d164a5f3736f542361f303d44f83e8b4f68b4bb0edb14dd011ff","nonce":"7fc03640bde39e9b173e6087","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"ae886d176c9b48f5a193df5ccea842325c0241d2a81b677a1e377e848d14a7ea6abbaa0cd7e9d3a7bfbbdddc02","nonce":"7fc03640bde39e9b173e6086","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"bc592fcedc5b53106fe191afc038eb9dbfcfd95a3ff7d0dbba208d1032d7108be6fca47c5af4597d6a7b5b1aea","nonce":"7fc03640bde39e9b173e6085","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"eaaec7d6a863143494a2af6bdae675b2fe0d896cf2f54fa175984eaea5eb8357535fd055b476bb47e5f4d5aa80","nonce":"7fc03640bde39e9b173e6084","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"b76b0673471b58b837a660d1bc01166df99d3f9835110e4c426dd70b6243426b3ee432d1d7750ae4d5da33a0bd","nonce":"7fc03640bde39e9b173e608b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"abf24b5839217708a3204443e201c46530fae6e4cebf43e8f85ef05ee31d79e3e24c25da4f31ed445b1ca77095","nonce":"7fc03640bde39e9b173e608a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"9ac014cb90eadeaa407ec52aa8537f96bddc130dbc71e5666c5ec898c3cf040a3964286d5e89404e27d46c0beb","nonce":"7fc03640bde39e9b173e6089","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"f67dfb29acfd6fcbf5f383a7fca20d6fdb0a810aed52def5321706a241ad87a595bda9aa64940fce67c4021853","nonce":"7fc03640bde39e9b173e6088","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"e6d974ff648def063928b24699ba468812e8f3d558e3d93006457c1b5b6b5be07b360e96591fb44e848af8c998","nonce":"7fc03640bde39e9b173e608f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"c64693b6b37026863d1161c2ee219f45d6cac7dc8a0b947d42185c6b2a1e0249180656b701c5580c2287d86d37","nonce":"7fc03640bde39e9b173e608e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"ff0926cdc4a55a704276ce729bcc88493fa0463618e2d0c2eab69134912eb8a94b0003acfd821f473358e49c1b","nonce":"7fc03640bde39e9b173e608d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"5b3e69f6ba549c48889194656d94479e9b495f98f2169a07ee48af423fbdb8a32facf0bc308da693486117d3a7","nonce":"7fc03640bde39e9b173e608c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"8be056e7eec4437f3c8953a90864f718a8aef0a61ab4c72756cefce7696b76296266d71eaa9030fa41ac6dd9d1","nonce":"7fc03640bde39e9b173e6093","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"9ecf05360663fb73f03d557ee34fd7a4ac6cbc54055fa8fad1a623b2980d655929dfeda97b979623fdcbc5c4ba","nonce":"7fc03640bde39e9b173e6092","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"e0a9869a83ab74def1eb0c5a0b9633b37406e308cb9585047a3b2f16e77756d5ad580e1137a6c08342e51a477f","nonce":"7fc03640bde39e9b173e6091","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"63e23a3df9283bd266a44f778b1c02338a596a3c0942d6ba4cc5d2f46deecfc3e71f021dfa01f40bfd6e3beb9c","nonce":"7fc03640bde39e9b173e6090","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"18036d64fa6f582000b9306c3769d0768d5a876caff80af2005dfde32d3607124e861e0605fa2815010e3a7d55","nonce":"7fc03640bde39e9b173e6097","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"f9404b7f694b3aef38bc34c276fbcb68e36f1930a4b11ff451f501baddefc493edc19854fe0fed9cd6539980d0","nonce":"7fc03640bde39e9b173e6096","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"f44aa2a2a0070a7fff6b0f04c7a39af9809e1cb7f7f313344411b6158d9089ed41cf335025118010d823b28d7c","nonce":"7fc03640bde39e9b173e6095","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"0ad32b9dabb69c37e5be952f17b348da4ac5e7114b3400886263721389c99bf8e472c5a2fc6e8f2b53442048bd","nonce":"7fc03640bde39e9b173e6094","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"935af08e9ddbc0450cb2164c13449d6646e5adaae230567b7a51e966a53a44a5d8a6671a27afe27ce5cc82ce06","nonce":"7fc03640bde39e9b173e609b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"f0b0fc4805e7bc668fb95c90a05cf4bd4056e2a6182ce0205bc8e21b86e886696e937dd97cb7dc614c2e792206","nonce":"7fc03640bde39e9b173e609a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"b453cbfdc3cf7bdb57d1165ebf4d56a646910755f35d9df3576fcb1d2602348ac24c9b200cedf77600cf8f4fcd","nonce":"7fc03640bde39e9b173e6099","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"e2268e3abe3db6fd31679dc18045c06a7b862418816db7cc9099df65d010a35204186440f59dad4eaa5b597a38","nonce":"7fc03640bde39e9b173e6098","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"6ecba9946fc7f877d0d0dc355217c4286a354f1013349a448dac3a1b4d6524f0b1db3dc9e176eee7f4673006ac","nonce":"7fc03640bde39e9b173e609f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"19867443f6dee8140c4ac93fa57a44e692dbbada714186b571f9a5183534f11d2341dbb28f1af4477285231a2c","nonce":"7fc03640bde39e9b173e609e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"d1d2a647ab876999380072f1c3637dd7ad448b7d04c0563413d1e9d3c1e2dbe30c9daf9ec293ac9046cb6968de","nonce":"7fc03640bde39e9b173e609d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"036999efb0b84844a1b6245d313d975cc501efa71036371d80675821db0673803b5b2b0bd5eaf102747e17e09d","nonce":"7fc03640bde39e9b173e609c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"3c4a0867ae9f19cb8604605484100955a87082f0eb7fafefef4270097bb4f9a5f1761c77d4002fcfd2aa026ecb","nonce":"7fc03640bde39e9b173e60a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"3ecc6a570f1770bf140d79d457066276308e17298562585f5d8374650450ae73884bd7b7e99e5c047fb31422ab","nonce":"7fc03640bde39e9b173e60a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"b6300fc3a8988ba77f094159038b99cb08f07f2d8c07a6415337068fef7e19e6c10f7d4efc78c52c43ea404d87","nonce":"7fc03640bde39e9b173e60a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"b3f62d87da390903298425530b16faaf931af8e566948fbc0d10bcc510c472293c696632447fc9342a91aa291a","nonce":"7fc03640bde39e9b173e60a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"2db9f632ab3e5c4eec6eb391b328ee809a596dd7c76f1b659e002439e915cbe1f1b76ed7510d89fd6dc948b491","nonce":"7fc03640bde39e9b173e60a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"f8a477004a3765e2cf48d8ce59069099e430d06244e97049d56d646dd8fa9ee4968e7cacda9425ca552fa9fc2d","nonce":"7fc03640bde39e9b173e60a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"9b83418335ef02d62418cf8323162f0a3ff231625b9f2ba9758af33058f22bf48bd63682506c90559d712bc8dd","nonce":"7fc03640bde39e9b173e60a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"d5e72bbfc49987b4e98f9159907d2603d8f5a4c17de0cad1f0c35a67c6871724dea9003297fa574bdd57ff76bc","nonce":"7fc03640bde39e9b173e60a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"d5b3880025fef7bed5b22e75b173dfff48a0f0ca22dbbee694b25c5f7dd250a5e18c66ddb29ba591984fe275fb","nonce":"7fc03640bde39e9b173e60ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"2ef3161d004ec6677044ccd9a0e01edfa0621ff20083cdf13822775bbb53162669f07df70da5ee4c7880e99c86","nonce":"7fc03640bde39e9b173e60aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"8bd66f7094370cd6323e9d42b28410920226857d4bbbe38a610117c15cbd17c7330516242c27e861aa14732692","nonce":"7fc03640bde39e9b173e60a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"e514b3a9e80047da5174c571c2ce974ac1e2c1281552d10b5f88dc3f7c5095a819430d0fedf23958ebec0e6d48","nonce":"7fc03640bde39e9b173e60a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"f79bc863e09beba52d14d6b529a96be5cf92342aa499ad70efee7c5a33f1c5896ebc3823f3e6edc6136a709b56","nonce":"7fc03640bde39e9b173e60af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"3b03f106834bfaa537a0a86981812756fe2aada21be0e667d116a8500368fdc74e59bee78e5ea043c1d13bad36","nonce":"7fc03640bde39e9b173e60ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"8426cc06b5231758005dec8c86031948423adb2cb97023396be13c33b6f92f20ae4eb1999a52e8e828774ba1a5","nonce":"7fc03640bde39e9b173e60ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"52498b7418cf0b270cdb92d04d364db3f44576f5f07b25d3c7e2e5354c869c5e7973706bc36013bfa11a6d95c5","nonce":"7fc03640bde39e9b173e60ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"f8758645076635bcc6bdcb1ba8b87072bf28a1d8140752cd508164b0c7c17ee867e36e14f3fc840f8e62599a96","nonce":"7fc03640bde39e9b173e60b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"9c5bcb66eeb8f151c6ba2de6ca435c58ae43940a788fcbfce14bf030a2c65ccef227c2f854a3d7b31731ca1da2","nonce":"7fc03640bde39e9b173e60b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"282e976fb5e71712d5b7567c70aa77756eb571633f6ed66f675c55edd63876e235bf39d9c64d0247f2ac457b5e","nonce":"7fc03640bde39e9b173e60b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"1f1d7aca4c2a312d16a408f8f079740d2b84ef507877a345ad95d7935480748ae2224c1b64f39a0c762d10f462","nonce":"7fc03640bde39e9b173e60b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"f6fc1b3b2985a9eb4821e4880e5355a7c20a837db3d1e66517ab6172dee6d1ac87537d0858b0bd521aa45307ab","nonce":"7fc03640bde39e9b173e60b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"c6812c2c4b12c175115b3cdeb19303ed056e473cc59df8c48d6ae97430b4303e5def457489299dd0b836fa7314","nonce":"7fc03640bde39e9b173e60b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"5a641476d2a2b7534fff329af9d50fef5440a9bf5ee6d769a6a76c8ac9bbd828fcc0474d7196e4f967159016d9","nonce":"7fc03640bde39e9b173e60b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"557663f4cbc5b83ff9c61505047af4e5c93e4d2d65f7e7d512511c24bb0d3ec2f1995a2e8f5704e16b10f31482","nonce":"7fc03640bde39e9b173e60b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"dd1590949723fad1b047894fa363f85a43df5f64fa55dcd6afd109c58cecb62f5f5d8e687c04be2d6353f5088f","nonce":"7fc03640bde39e9b173e60bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"21e6cf006dc1e4cc45098aa662ee07c8e16082400487a0a0c4e8f2221f10efa064c54f2741cd0698487c4ec656","nonce":"7fc03640bde39e9b173e60ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"9491dc6b847d61d43aa84a5a9f4609425fbcc83bb164b34a84d4dd650bd8b8a4ea8e1068f5ccf3c5a7c79dc85d","nonce":"7fc03640bde39e9b173e60b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"6c55ecb0b654eb5b58d87774a1f0b96d711fc2018d8dcbe11dd0050c00a6a7ee1c9f9106abe4510dff2806114d","nonce":"7fc03640bde39e9b173e60b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"81c302b5acd364fcff9b76caddbccb606bc67e7b8ce0f506aa393aa03590a84c4cb1b9b180d40ba64925e4c415","nonce":"7fc03640bde39e9b173e60bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"442fb8b495c593616fd8eb5648263d49ad833dc2ba43c1743462021d16605e0b943d881c377011bf86599c4854","nonce":"7fc03640bde39e9b173e60be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"5fb28bc2ded1f5b41f10a162e0c6462a20538ad3f5435cc208adc312fca568ef4a3c9518dd885f3c2e8d242123","nonce":"7fc03640bde39e9b173e60bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"177fc9e9fa94e8c22efc98c776a1dee7e5043bb6e777a7a1584e9cbc6f111f561a8ca27103543a187224a85c7a","nonce":"7fc03640bde39e9b173e60bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"6a6592c0d226e848101da98af64e3e2a3ca12b80f3f2c6360ed64404c675dea418f660efba81ac1c728114eaf0","nonce":"7fc03640bde39e9b173e60c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"6000afff01d2bf15539bb71be90997cc1a0da51fdcadef2ef70265e74fbf53d8c52fbe867e6bd39adff6c312fe","nonce":"7fc03640bde39e9b173e60c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"8d2dce02fc000f6b78335aa1c6e4401144fb2147360fe084564ff97f56b46a097ded4c3a111b367a0a4e7ff05f","nonce":"7fc03640bde39e9b173e60c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"38f86e8a72282e3271e80e436190e22b5fd6cba0dff9a5da20cca707a1e63434b116301ded780ce9cae6a8661b","nonce":"7fc03640bde39e9b173e60c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"558078f2c1996a09f892b6be3fecc1474f23c77312fd266999e5d0a845d3e25bdbcb7c55da96908800a9d96cd3","nonce":"7fc03640bde39e9b173e60c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"5999f2310ade47873dc1ba30b55a8b67c16ea3c23677dc88d2edd2578830db1a039c5e6b2d771c17cd8c238a2b","nonce":"7fc03640bde39e9b173e60c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"a78e08a4e641db40919ac32c140b651b416a7ab943c744251892286893ea924aa9f531a382311509f9ff59380b","nonce":"7fc03640bde39e9b173e60c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"73249e37de57b26e002fcb75f5d3957616ae19994fe9f570c37999d712fc41fb71afe22a159098150a32fe528d","nonce":"7fc03640bde39e9b173e60c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"d4c237a5a7b26a35482152b6db41e9a44ac80d3484b2447f7543562231f79f141607db74c5b1e43d8804764f2d","nonce":"7fc03640bde39e9b173e60cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"4a0ca920c4d590b3de2b8e804843f1fae750285b6b21ea8c4de5903f065a57cf1a18ed22bdd33a80686f20e279","nonce":"7fc03640bde39e9b173e60ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"d3eb41d4d246a3054de5773b6028ab84af63332f7cd7f57bbcccfb7e94af986b56c1203e253fcea7bc1bfb873d","nonce":"7fc03640bde39e9b173e60c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"efe01d622107a5f4e47330bf3aa4da12e948e1b2e4d534e0ad20046a57c5bf66aa7708d6764315cd05f375853d","nonce":"7fc03640bde39e9b173e60c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"4526f8827b9a1e30436512fa253f69aa9c17b00f88253e13aeb7d7d28f7c613f9a59e0582a46a8a88ccc076304","nonce":"7fc03640bde39e9b173e60cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"14574412a70c2c0496a210467809db535a51c4a7b115a02f58901dcaa06bdc72990da4d2716c3410a17a67458e","nonce":"7fc03640bde39e9b173e60ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"18fbbd14ea98c90bc27fd2c01d8bb521b137ea9a510dfbfede35e3a059328a884df4bda70860394d00944e637d","nonce":"7fc03640bde39e9b173e60cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"713aa97e37eee5b8b64f637ad8a4dd798d91908deadc71c9db05cd92ccc3d151ec778baaf4202316ea552bcf7f","nonce":"7fc03640bde39e9b173e60cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"dd23ebf2cc0301c45e309dae5a96373763cf4573cdfe4bc77dffda63882e07ed635176f4f1f83208ffe6584d93","nonce":"7fc03640bde39e9b173e60d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"3ac70a8fb3f0e272cc2f20d677bcae2403118acf317a01080332ed924d045dabd6e1d05ac129487d9f76421f3b","nonce":"7fc03640bde39e9b173e60d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"f7e2be1c5244c5ba91917495259a5a7d83de7a1cca14a784deff4422de4fc6dc91fbec94ac53ac011aa0723cb2","nonce":"7fc03640bde39e9b173e60d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"656437467dee71d2d3c207358b1148cf4b687e1d98c58f78e65f1a28b82a3011b91c5dc965602aa0c23600c724","nonce":"7fc03640bde39e9b173e60d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"9f694ee642ebdf0364c75c6eaab83778658451a81b3d4350d08f75a97929f52a5edb68a6c897939e81931b01c2","nonce":"7fc03640bde39e9b173e60d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"11e1d66462b18c1faaf44f0efae3070ef6f93e2e904f95fae6dfcae0161536a374d7b75d00f5bcd01aa73a9b15","nonce":"7fc03640bde39e9b173e60d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"4b15867d2a92ce97f62e61e7cffeaccdf42e9b2c6bb1bc1da06962a4f06a8316a27ac205d82f5391bd8d7ee277","nonce":"7fc03640bde39e9b173e60d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"ddcf71954128c0564d74962e366696b86ab4ed08e2e394bce41b5dd67415e69c7c7317ff716151bc7786472748","nonce":"7fc03640bde39e9b173e60d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"de60297d1758a9c14471f264825de1e9ff74cb8bfc9f9123fcfdae18b434c8044ed7755e5bcf9f1edfac9cffa0","nonce":"7fc03640bde39e9b173e60db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"0adbe78770676577b74a3987b01df5f1563f3021970184bd1032e465def12758325bd89cea31b7a081920baf32","nonce":"7fc03640bde39e9b173e60da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"f501206a163174eef7623f9685d414bf02e1f9d1b7eaaa4b73655a60f7c85cecce861cb7eb652f4bae07037834","nonce":"7fc03640bde39e9b173e60d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"a2da62f6e48e8476a0757f662cbe2c28740c03a52138bde442707fdcf3580d58c3526a38e0fbb12bc46760a9de","nonce":"7fc03640bde39e9b173e60d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"8447fb46e34587bda3259eec25c8d3bce9a7eb2efc201aaafdb4c6822d867fa72ef346ca5d9f940404e8293bc4","nonce":"7fc03640bde39e9b173e60df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"46f3ed5b1b2937f6f6c4eccaf0b980e77e9ac63dc46d54fb3cd4c384faf4716f17ce2df8beb3b2e3f71ab7b0aa","nonce":"7fc03640bde39e9b173e60de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"3197b3b71e46d37ab837bf8f9c2638f56efce8ee8b77f8f965d60b3cb1dff2d92fe94e26c46fb525eda097cceb","nonce":"7fc03640bde39e9b173e60dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"7ac9c5f4a3aa24bc92def17f164d46ce9c8e1ba0cced8b5a47c04440b8475b3999c2b3b7450c261b99dc4c9da2","nonce":"7fc03640bde39e9b173e60dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"177a562c0d31406cfad2462314ef35175403fef323e82c0097068be176de17081755e674a79776d31e066eda88","nonce":"7fc03640bde39e9b173e60e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"8177d7faaeefc1e98858711ea6d8e3e28630214617d10501aeae4c0e81da423709dc23f736884aeced67a8c577","nonce":"7fc03640bde39e9b173e60e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"80a1cb67d194f52d35d82be1a413eeb43a29f32d1c9b7d64110bde4ce27a4ca0d98f458bdac007f62a314f288a","nonce":"7fc03640bde39e9b173e60e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"8c4f870e2a08dd4a2bae6a58ee5380c141f8d02097dfd21e76903234a338e084898751c0d50dbb56bf66c26572","nonce":"7fc03640bde39e9b173e60e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"4f246530109c71a3e77ec0efb00e4875a347e989cf957a9821a456f83b1af2fca9f6eef6d86e47dbae5c7cf604","nonce":"7fc03640bde39e9b173e60e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"ab65d2049ab9b9e0b3bb5ca45f3dde4cbc98f72c22df53b0398d9e80cce0d8073b171ae12d88ccb112d173cf39","nonce":"7fc03640bde39e9b173e60e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"eaa620c48b715768bfb308fedf09979424cc31cbea4f60de7157730a81e2cd9d093795ae963ada54cdccb3e965","nonce":"7fc03640bde39e9b173e60e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"f835f9425a2c254e141ca9abd9f44b98fc78075764e20ea53e81449fe8b218a5da2685e555abeec19ff46c6091","nonce":"7fc03640bde39e9b173e60e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"7666725698c327507d5212143700c1f7ad03685d07cded6ee8a9f28f2d11762e4e0db87367f876f9e013e62580","nonce":"7fc03640bde39e9b173e60eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"81411f344a284b0f894eb5dead250efe873df2563448e3fba6e6f26d9d5c089a694b898c6ebe2d6e9ab2de0bcd","nonce":"7fc03640bde39e9b173e60ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"a98dc5feb9dfb27917b64d3c3b4842583c509baf3f8b99ec9772539df57e09c7f982cbff675659973235817e11","nonce":"7fc03640bde39e9b173e60e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"ba8e8cd7c81fd2322227feffd46d0fdbd4595c09db821e5f75fe7e7ffb1d0164627147c93a50cb76e6a4498fed","nonce":"7fc03640bde39e9b173e60e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"1bc1f6dfd7f14f4ef10d9f5d74146e6b94480fe231444b8520fa8e4c59e1ac66346ba6c19d84de3d000e81c68c","nonce":"7fc03640bde39e9b173e60ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"29cded2aef8bafbd16af3226e0acf3d8bb71070c8fb7bbb7f8294c0da1a4612360d92e66107c7abdf3abce3207","nonce":"7fc03640bde39e9b173e60ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"5d4b99948739904667be009a7f31b2a7a0321068f97d802284788286c6d3f910780abcb8f0b994c5fc1374553a","nonce":"7fc03640bde39e9b173e60ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"9f992c727bdccb895f36b7486434331198a93c766eb69529602f28191cbf8da01dedcd5f783a5e1655ff5ee296","nonce":"7fc03640bde39e9b173e60ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"a418483f8b02bbb5498228523411c3328ee642be782efb29722f4dced4a35f80a85f273e52f931177670f72311","nonce":"7fc03640bde39e9b173e60f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"0a6e123d7416f6510818be6d877cf968b94dc63c1be4b51a9ddf1e1ffac94bd82e3a5481dba39a3893126b182c","nonce":"7fc03640bde39e9b173e60f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"ae03e975be3db08887c770736d40c223807d10b23d76b04cd1bba623aaf97c8d9e84dcc6c30f3c3f0648ca4e41","nonce":"7fc03640bde39e9b173e60f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"3a4b71a4c62bc7999e6cd325a243a0aaf9cc5cd49df31d19ee7393f42ab0c9de81d653c099798e43ed265184ad","nonce":"7fc03640bde39e9b173e60f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"6594d860a55ea9e0a56a856e9c71a6c5a8c385a12bd8204fd3f7311df94211231b4223987743e7a0a43c3b95c3","nonce":"7fc03640bde39e9b173e60f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"bf96784655d79a6dda42125c8b094737934c487835b9561e5d3699bfb4647c4c96ceaf7a67699db6c14ba9fb16","nonce":"7fc03640bde39e9b173e60f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"0c89d4e1b30544bef7c2edb9d1a197a9f3051e19adec1179125006f4db2380b70248b533750258d9e82acae2fc","nonce":"7fc03640bde39e9b173e60f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"a5384b557b5dca196eb0a5ef28086c106375bcb1097efc44d2e1b9b9822577ca8b8be00a0b107d4e0aef02b183","nonce":"7fc03640bde39e9b173e60f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"a1b7596c63a958f26a6a65db21e5c8909bccc335917e77b3c0b61e32ca1cfa0b96d2f898a6514a4e904e8ab326","nonce":"7fc03640bde39e9b173e60fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"b1cf874e8a836bf339223cf46d4d09b5db41352a5943a328f60f4c9bb945d36a7828174b2639e9227fa7b0b941","nonce":"7fc03640bde39e9b173e60fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"43c80f313e98f2df1f388074fe16e8e4f0f8ad397bad36bd2d87879d6803482ce4dbc16f272fb0193ae1768933","nonce":"7fc03640bde39e9b173e60f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"06c152bbde5245944cf8548390501b5ae9aeb2e5eba9c4d2461f367a41135005b9fd10909cc971f61e209efe51","nonce":"7fc03640bde39e9b173e60f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"1b6a7fcdc64274280488516a36f62cb1837cee283daa43734a9e7778b9e511585f41fb4d76ed9330376b0be520","nonce":"7fc03640bde39e9b173e60ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"154b4c3fa272a7f2551d219f90d5334f9134ecb19332e969d7a74fc8c943fb580439ae5d6b37556799dac56921","nonce":"7fc03640bde39e9b173e60fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"681c5c8471a978abc70f13e00a681a92d55fa562c0c6b58aadfc02d5adc36feb50c29b9f9398a864b137d99197","nonce":"7fc03640bde39e9b173e60fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"f873bfcdc11de00363bc179b2769a04a8ace8084eb62371d1a926b612023bd64f44c403d588976f5d5139acee8","nonce":"7fc03640bde39e9b173e60fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"8f21182ea0c29945bbae422a3e725c4b6251d8e342b8ce671144f4ca877a4fea1241a0d6cb000625c6080e9cd1","nonce":"7fc03640bde39e9b173e6003","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"1fcb5e7e77689c055b885b65543bc7293ccbc7e24d0396e49fb0c8104f8474358ebc1a54b3b47cb9a48458350a","nonce":"7fc03640bde39e9b173e6002","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"bed12703469eb85235f66cf751069cd8391ecc5ead9904c296456bf242bc26b042abcf0eabf14ea6b077e95d95","nonce":"7fc03640bde39e9b173e6001","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"fece9a67f2789c8756d290277b0d15f6b7094611195459dc00cb3742bc63a81b000cce57895672bdd72306906b","nonce":"7fc03640bde39e9b173e6000","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"8977ee5948c379e8ab30c1cb12bb84e1f9ec3746bff3839c01e0468d69ff16b606101fc9ed353b8340abd52c89","nonce":"7fc03640bde39e9b173e6007","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"e23e884bb107d05ece1859de85df3b5ea8e81c4f42e781fd7ad00fc9c0ef24e3d81c86e600f728ae7916ad3438","nonce":"7fc03640bde39e9b173e6006","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"53fe711e138d6d1457d0f67c87b94d78a745c146f32ab2e7ce12ccc3eae1d9b038950069b1968b6963b88c94d9","nonce":"7fc03640bde39e9b173e6005","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"30c0799520df2c10c320d551a059e39b4eb6e5f34a46d96cb77f0e33f79693c7415c0ef0dcb177d8d30f6c9b84","nonce":"7fc03640bde39e9b173e6004","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"7a2ccc85b21f85e5dad1b8f3de71eeb2be54c2dce90c9505872a05dfa36817a8573a64036633954cf0427fc919","nonce":"7fc03640bde39e9b173e600b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"bba3508ed1564bec196cc99afa12e960725023d45c010ac712d3f6667269f9cf1f4bf288d9efb864079ed0b4ca","nonce":"7fc03640bde39e9b173e600a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"22e9a287e9b4267c348cc8b9452a4aaddfd82e0a9e8d80eb950ef8c439b2a0d8abf32b7790a2035d130a569c01","nonce":"7fc03640bde39e9b173e6009","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"1bf9ee809d2e865ff890c4717bcd92d6a087b47ec7919fa24d0ee3e882d07a6c8709f77edd0128eec625a1139e","nonce":"7fc03640bde39e9b173e6008","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"5b5dfd2a5f070881dc0e36b240b1b349bcb8ec3994bb485b574cd88319dc1c0ed1c3a4c0e2c2663b5a72eaca36","nonce":"7fc03640bde39e9b173e600f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"84fd94655cb26abf80740dfe206bb23829de7d3ce001d6655910cbecbf0a4e814fd92103164dc87f95e869976e","nonce":"7fc03640bde39e9b173e600e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"1399135a4139f758b194b6df0c54d8e895bc01863d8194ab5c842babdb631e4895d7864d09effa9d2181636579","nonce":"7fc03640bde39e9b173e600d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"f694cb6540c2565022ade75b9bb4c28f22708cb670a52a4d41c44fd8d3ec30033476b6ef85c0bc9204ff7bf2bf","nonce":"7fc03640bde39e9b173e600c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"d6f1361ac88f6ee1180f4b997c4180e4059a44c293ef619242003882106596aedb8ba0515bf7c0e0f0e2275950","nonce":"7fc03640bde39e9b173e6013","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"f263da5f136932cabce5bd6be296bab5fe97d9d04112cdf300eda50d5c339a52bd126408c61a2738bfc38b37be","nonce":"7fc03640bde39e9b173e6012","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"e524aa89a5a87165ea23808bd86f9a34387b5832f6840c2a7d9afb838bd07556c71e81c8c19c260eb47c1e1e85","nonce":"7fc03640bde39e9b173e6011","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"bb60c62ff82857871b161e7cb08b27a60fd2f1b140f2db81df4ea701adb69de2a763fb4bf91d3caf01b02aeec8","nonce":"7fc03640bde39e9b173e6010","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"ffa37e5ada31a7c1bb4cdd1870d3e94c17112a0d7f5527df6bf5bd9c03ca67fe3b361ea34742ba0e48c0154726","nonce":"7fc03640bde39e9b173e6017","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"c811d941d456d7bb5e8490d270571936334bc2383ea7458dd73eec0e6cb1a4fb35f1e1cad51b17766762f425c5","nonce":"7fc03640bde39e9b173e6016","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"5e7776dbee8bbe6e11c8b0516a0ac7ef952de7b731704e88771a4708dbf704f15be51631108b32aacb5236a7e4","nonce":"7fc03640bde39e9b173e6015","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"24f30576feb7be109611356d64ffad108014a8b92099b377d6b88e5b3bdf181c6c1c75548a9d16cd779a666641","nonce":"7fc03640bde39e9b173e6014","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"1f11fa53507d573f8bb7da5928c62145837ba7dd0a8ffa4c73bc3e0c6f756f91356017484846491c21bef0cf4e","nonce":"7fc03640bde39e9b173e601b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"cbced9a026ac13d969c0a1f3e6d9af26ac41d1bba364e33224cb3e8272f416f311ab61a48f7aa3c23d887a210e","nonce":"7fc03640bde39e9b173e601a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"a438a42b6881e11f0d92fe1912db5f5628dc07967ee0fa9f99251d755dd70d2e72a5e5af7d67cd2c9d39c681a4","nonce":"7fc03640bde39e9b173e6019","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"ace144052458d113c94999fc8737c9f3b5d1190178db03927f596ffcce1e18cc6ee3ce379b6437a2ec5072c498","nonce":"7fc03640bde39e9b173e6018","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"44fe64615e286a2b64bfe66521191fe85095f6365024b07b3cd58974e73542e55ee0abe7448953c19831d0b605","nonce":"7fc03640bde39e9b173e601f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"c599f96617a3a1dfc7d4deaf9a01d0f2ef6673b3de48a8d9e05c92f59c5bddf1339816a698b885bce8cecf3d25","nonce":"7fc03640bde39e9b173e601e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"5fb6ad999354ea603555bc99ce0c058b6d761d66396180e4d5f27bf2c233e374599a8368559642160af6a0fb09","nonce":"7fc03640bde39e9b173e601d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"d1bea72b23d9723cfa4e8e6f23f50d2ea85b9601873976314813f869e6487ff9bdee326d55bf67c2f143936967","nonce":"7fc03640bde39e9b173e601c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"a8c17cc25d1b5cb7477b291dda190277c5d3ad6dbfd7017cc5772e280dfeb76c4a51ab2e10a04decc2ed3562a1","nonce":"7fc03640bde39e9b173e6023","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"bb2b7f68cdd6ea9df46d788ed20fbcc8b8d91b9de144c4a3cd1abbd349ad5bb8c555d58823a5c8a6d3ae4737c3","nonce":"7fc03640bde39e9b173e6022","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"64b3e8d15a05464bd72b5aa04887029d9eadb26f48f4de1fc7ee441a245091e85be17304f4b20785f3d09ac349","nonce":"7fc03640bde39e9b173e6021","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"ac964f41875dc1d4956cb761cfd443161a540a62265bfc95e7a8fcaf4b3a33ffa53a85469b740efe65787a3a58","nonce":"7fc03640bde39e9b173e6020","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"a43ba09e846f5aaa4784aec58f39f3bc2f3746b4789ff0b15f6bcad2a1f50bfe5a8dc2411add219d51dd87940a","nonce":"7fc03640bde39e9b173e6027","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"56e44f54d55c1fdceee2fb414a243cb20ffbf7665c9b4274d760d5c9f720f9d0a599ec5f267af33f64ec5032fd","nonce":"7fc03640bde39e9b173e6026","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"832199432693d8daec9fe4eab43b5238f531c34327c2703f8b5712e121d2c7fcfbac2b67ee9cf2254715c59db2","nonce":"7fc03640bde39e9b173e6025","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"43bbb6be95a51f1b7969893503507613b407eb1a1c8a182dca53644bd1dc1f32342a656034a21792fe938002ff","nonce":"7fc03640bde39e9b173e6024","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"04d3a77d6c362e6031fc09c7af8943a0b64c5f1782e30ff9dc199bc71fea4720fa688ec1a267a9ad4572301ccb","nonce":"7fc03640bde39e9b173e602b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"8bd458ec58baf0f235c5517de52aba69df0a5a43246f6153f4f582c0dce3e6906e3e1224b58814198889718464","nonce":"7fc03640bde39e9b173e602a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"660813aaf6deee5ab95236e5e9271691590caa661d859ccfcb4477c1b23c46247a313287271644e98b4f031018","nonce":"7fc03640bde39e9b173e6029","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"d49ba5d765b8173e5ee90cc80b9db94581c3248bd6c26d65d37cdc531c093b42ba100c3ed8957c9259940e3ed4","nonce":"7fc03640bde39e9b173e6028","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"cfa6c62d9e0f0a9574e5abd09b00281311dd6acb4693412abc3ca9986ccddb74f308be7dddc2f37cbf3d80393a","nonce":"7fc03640bde39e9b173e602f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"ce0f223d078cdc49228f7eb87b2654f381380316c0ec8ef8d2079211f2d00833fabe28ed997eb02efad84d008f","nonce":"7fc03640bde39e9b173e602e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"5a6e71adf8b6423256a8905397fa962d36b0237c51d946f9b07f232ed09fd48b3a569507daabbf471d920587a9","nonce":"7fc03640bde39e9b173e602d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"4cb030f516a5f1f74042fff5dfea55077722491dc990803c764186a143db5cf9cddac66f8c9d25e01fec8bebb5","nonce":"7fc03640bde39e9b173e602c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"18652067a63174b803ba503b541574cadfce9b9addc34adf856693847e60a96c3bfa66dd7b03654989c63e0d39","nonce":"7fc03640bde39e9b173e6033","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"db7eb29485cd52850501b2c698b4bf665d586fd98564b3e7f2177cb0b7bf87a764aca9b995737cd7e270444c1d","nonce":"7fc03640bde39e9b173e6032","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"18eacd68cb214fb9239c1b6788e99890f254ae24b7529524977fb1b7891f01ea14e10d3e8135ad7921807408d3","nonce":"7fc03640bde39e9b173e6031","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"4137c7ef35ed1391ca0a7b1d746d4ad970331d8b3c707ce6e3277f633603f39428c9fd03da58751720bae4edbe","nonce":"7fc03640bde39e9b173e6030","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"f9b77ab12f8bbf12048297dc9382fde5dcee2b1ba8fa333189c845765d17b393aeba3a9399702e34e83c72289d","nonce":"7fc03640bde39e9b173e6037","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"206c24d6333670c21d6cf24a58dde7f5e9d202d6ab2e62ef50988f27eb486e709c7e59f7b64fce77091843290f","nonce":"7fc03640bde39e9b173e6036","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"4e42c208b185961060452111ace6a4424cba8cc9f74eef7214d0d809fdc7b050ee2c2df6e0340c47d4f8132dc7","nonce":"7fc03640bde39e9b173e6035","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"857a6fee8caf20c371c764aba4c8e098e04b7825c03fae9f19bd5ff2fc87167541e4d0c84222d837847576aee0","nonce":"7fc03640bde39e9b173e6034","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"fa503d560752fe4436ac58de179d33258d169117a6573c9556b5d234805629eb08fb9c9275e09c2327a7e9d65f","nonce":"7fc03640bde39e9b173e603b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"c972da9f30e6fa70bea35c9008207c3c7d9663d897bb367c8bf5f25f7dabb8089b75dceee31e70e9c81d412c9d","nonce":"7fc03640bde39e9b173e603a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"5ff1c73502d81199751730701f83c31c77ed89dc959e54c1c62fa0333d3cad3d6ca43d0c02ff2d7e3635922328","nonce":"7fc03640bde39e9b173e6039","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"4f8a9f6c7a35e5adac381efb511cdb6b37810ba97ceeb2bf4eb75236b5816accb9c15b9b8030370975a9bdc85a","nonce":"7fc03640bde39e9b173e6038","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"b422ce16fe7401f0c8c4438604a6dfdd1ccd2efd8db74b37a2dffe919391f45a7c120a0ff906d64fcb8165912a","nonce":"7fc03640bde39e9b173e603f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"d34dc0585ee136560d3ac422cc984c90da6633ecdc67bfbb3d7982ebb760125c536d83009d8a4a02830c9c4b3c","nonce":"7fc03640bde39e9b173e603e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"0507e9dc6052059cf4ce8d6cdd0f5d288c6013a99a8e05a73d719c25610d31733e793025bc5251a19227fb952f","nonce":"7fc03640bde39e9b173e603d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"0973b8e39482b5ce8201770957327b60d0c053fab1dca1257f8033afca778f39eb6e999fd02e6038ec284bced2","nonce":"7fc03640bde39e9b173e603c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"208f25bdba5b3b0874715ad92cd72941dd684d4a98a9a1a0de755565374ea2f166f56cb4243dfcf92a264d3668","nonce":"7fc03640bde39e9b173e6043","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"65911c7a876350f970dee5e88508e0e694b978c884a4f3f8429dcee3f245da2de4fdd82caa7f94ef371fe2b160","nonce":"7fc03640bde39e9b173e6042","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"f883281c692ce654ab4324203233056b6f7a2c5d5087426cfbd50f184a869719013b1270c9611b0b5856de31b0","nonce":"7fc03640bde39e9b173e6041","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"fc7fa68dc52a464bb44b3ee6366e20187f27fcdc84ed284b0c037b99567e171a9d3034b49c0389942e66c8afe6","nonce":"7fc03640bde39e9b173e6040","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"e3e3fb17a39e200ecc552f4356e35d96ea954521a9c56a4db698dd41a26cbca26b4ef748bbd5d5bb2907d9978d","nonce":"7fc03640bde39e9b173e6047","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"daff62425966f3e595678a8495dec614bc47a4811493641aa526fcdf7287e911aaa922f663879a1fe531c9b51d","nonce":"7fc03640bde39e9b173e6046","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"26c8d787157d9bf381583f06bc0e22d5386a3a3a38e10b0276838bfc506047371f7ea6b75630c37af33627dc41","nonce":"7fc03640bde39e9b173e6045","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"13de218cb025af32b1096d130054c157e14b90a45fa28d68cee6f2d6e637c2acb4236468e3ffddc3371cd3f035","nonce":"7fc03640bde39e9b173e6044","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"69b193d226eedc3d2db5aa55d493f38e9c479e637a6a5fcd38e1f7318b358773c3b455943825c42f35a3fb8bc0","nonce":"7fc03640bde39e9b173e604b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"ce4266726310c4acbce6201a82c4ce4a8452ae4a47a28683f305467a209f8d749e4c018299bb0089a82d78b68b","nonce":"7fc03640bde39e9b173e604a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"9451b56ec6d8d9fa742d4745c1fca85efd5dcdacde2acf6900f35a290ad6bd76589228d1632c58cb0065bb4cfb","nonce":"7fc03640bde39e9b173e6049","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"0bef7c765a3560c31adf952909c8f4d1718573cb6a916392db88f299797fe91c3a22b2e18c318a5bf39e64d4d6","nonce":"7fc03640bde39e9b173e6048","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"c3ea457e6d6529a6a64f6190d432414c6ae1ab19922e22e3309505f544b47283f9c5f67a784813140dbe7a9e54","nonce":"7fc03640bde39e9b173e604f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"7008e817d2032743e583dc6109befc9db5609f83df27316ab36f286bf8e36e4af8ee95ad366053d7699ba3ae39","nonce":"7fc03640bde39e9b173e604e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"ecb4251dc169bfe340af4638f17f11756cb2203735f195601b9459bc8864dff206de322c3d32e82d68c263d45a","nonce":"7fc03640bde39e9b173e604d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"9b22800c948d8fdf62adcf1aabc554145c6d13af1d116f566b7badc4b3057cc2458d7009ce5eb05701e5d0cc26","nonce":"7fc03640bde39e9b173e604c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"bfb00b7caea73c8005a0989dd60e826f3f1f3cb66ee2bbbac7d54e8526e5ed30d9339293a2419a6626da5e5ed8","nonce":"7fc03640bde39e9b173e6053","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"6e574df7b872339f21ee829c5dc1cfa2d5864f62fb271c1a83b9621df523a446810a5c8e95e7d312bae280654a","nonce":"7fc03640bde39e9b173e6052","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"bf94111800e4c5b5ab108f55d08344c674e4baccd13ff2caf1e2fc4639a660fe4b2e205a8b585f470a7ac95c7f","nonce":"7fc03640bde39e9b173e6051","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"403ec2ecd369214a007714773a7f68243d6a744c32c0f9c99c2e13a50428c2409d812e73605a3157ce092b1714","nonce":"7fc03640bde39e9b173e6050","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"83e633a837822f53339644888f0c60231ef304c37708add43d59abc19003244f3e58d3cbdd380e5e61e530209c","nonce":"7fc03640bde39e9b173e6057","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"9c573cf3ac28b088a7098ba8e33a4fa9491fef235b24d2872bcf0b1426d648d96002f92a892b7458643cfa52b3","nonce":"7fc03640bde39e9b173e6056","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"77e30bf69f38f633cb62027b0d89992fb80fe47ed26633fe3154480b14962bbb36df12a4a20cccbddf48a054f9","nonce":"7fc03640bde39e9b173e6055","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"3c3e5204ba7b24ccab24c9c30a2e51da295dcd6999809ad734938ace3bec5e0cd7eeda1ac66c9438828238e801","nonce":"7fc03640bde39e9b173e6054","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"41374a2b39c3caa798ad5b5570396d22ff442fb939a334a63c4b3b390cfcbc6b4ca6f53065342ee0b5face049f","nonce":"7fc03640bde39e9b173e605b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"0780bc9d5d7f9a2032db568f761ffa4b3d2e80cd4b272a3e53773b8271aa0aad833787a85dfb01f2bcd1f74f1f","nonce":"7fc03640bde39e9b173e605a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"01fde10aacec9d629edfe793da6e45b24426a7e4fbac39ca8b2dbc8328e6f1f19a7ba1a000b9be398b35ed2662","nonce":"7fc03640bde39e9b173e6059","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"2570f4857523ba87e1568737097d9fb3987fb0940bfbeca2a7bd02e1f68468606880595fdbffa370ec37ede46e","nonce":"7fc03640bde39e9b173e6058","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"3b0aca9cc4a0c2fe9868b6db0fa8af05856cfccdd0114bf6e1a01db468715bba3abac3c40b324893fd3cafe54b","nonce":"7fc03640bde39e9b173e605f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"b2b23e88efdc9e476e676dbf4e3bd606873a27e382e9a9f3789da2aef68e92b89358646b22378fcd59144ec1c7","nonce":"7fc03640bde39e9b173e605e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"7a558066ec5bf75a61e85abc651fd1effe79375c07483532a939f1fd25633fddc693418708f273179155b4fa1f","nonce":"7fc03640bde39e9b173e605d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"3b365ab7346e26e409344263a2fde6e57287e44cf058ecc92e9d482e8a879ffaa40c0da0babd80d4a6996feaee","nonce":"7fc03640bde39e9b173e605c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"4d9a3c7695fc75c407cd9248bb43dd75e09b6f7299b1dcc891942506a7f9d3e39a19937e83b7dda1022038ba20","nonce":"7fc03640bde39e9b173e6063","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"ab281dd2858f0c04fefbe8f61ae0f7e34de4b2982b41d3d404ebc2b135afa9ad18f1c13a882ef28d1ffc1cee3c","nonce":"7fc03640bde39e9b173e6062","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"3fbcc2d4e797da20206c9f2dfe53569cd954f19cd0e9f9fc0b12867aef465c4294835a0e80a16582311ff84ac8","nonce":"7fc03640bde39e9b173e6061","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"8c3e8e06a16db8f6c3243959053d99982da952114e2f2aaac45631712b53b9c6f87c5985306510e3740f7500f0","nonce":"7fc03640bde39e9b173e6060","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"52e7f2506acfe798c7c5797958e428f9816f8225019632bf6640d9f64d155c738649d198709c3be95adc3cbd73","nonce":"7fc03640bde39e9b173e6067","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"c8c087770852a5bc6c42543a476d7d9d55aa2d55e38b16c1e8ccfa70644ebf80006cb541668b4ad67f8ddb4a51","nonce":"7fc03640bde39e9b173e6066","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"5217a480c60186e5c142718b8f990fe9976df9a3ca0e1c0222c7d30a2179b30cdfa78e88a9bf2d3e85b13ff707","nonce":"7fc03640bde39e9b173e6065","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"83b148bef6a1f0d2022b31903289b01135afb0240db1c4d96bcfa64353dc3f5b316fdaace034c6b856272270b6","nonce":"7fc03640bde39e9b173e6064","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"d441f4df891176b076e376ba6ebce83f517cf4b48217714eb27a91f4983bac1733a0f2bc80a583814ee7b890f7","nonce":"7fc03640bde39e9b173e606b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"f16899ef165e61ba96f5d62967494989ab5a26fafe9fcab02ae820d02ab2565084e1ee8b52247febf05021df92","nonce":"7fc03640bde39e9b173e606a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"d1bda319db561acc1b27e9ddc29975e860aba2b72afa5216fb7424c96632a268d8675d796bbc46760642554a0c","nonce":"7fc03640bde39e9b173e6069","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"18daad15f64515212fae02bc34da53e33882236f77cc798ab358b5f938bebe75a273a5e41f6f80b677d554137d","nonce":"7fc03640bde39e9b173e6068","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"858115ea6b74e85c5f467b93dee4b8298e5aadf265ea584fcb90843d5981fe0355baf92d4a5c4653b4fe36c388","nonce":"7fc03640bde39e9b173e606f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"3c6fa7de086728f3c90f1113d7d9d8f4272cf943071ef8bca373d2e19fe284e8f5632df15a9a3f20ba55e66a64","nonce":"7fc03640bde39e9b173e606e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"78623037346651ae4aa5e1bb39bb2bfd7df706fe29f9a800cc0fa2dcc04a6fdf2289a4dfa72e0fd283af0123b1","nonce":"7fc03640bde39e9b173e606d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"4aa58e3c1e7337f9c1b055af75bc020e9e5d58a8edaba2d3bf79aafde8e80577453ebffe15d1a8884ea645a361","nonce":"7fc03640bde39e9b173e606c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"13c90cbe5e76eb43999d7202c772c183f89002ba56b5a887ce87e20066993ce8786a5b694fe1142ae00dcd0ccd","nonce":"7fc03640bde39e9b173e6073","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"30ea2554397deafad05987d24bf32628f0d11ee041f0b24e5c76ea9d4c714ac656928ed7a53d3618e85b48734c","nonce":"7fc03640bde39e9b173e6072","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"f15ec1d5c81999487accea34e7d3a39a5e4125305690fc1e20d58707af71d9093c9418ab55e747c87c55388e7b","nonce":"7fc03640bde39e9b173e6071","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"5407212945cba5bb94809c80c6d2291c31e2c46b456b7b5ec89eef2db9a87476717ad4eaed8bb39630b6be1e0b","nonce":"7fc03640bde39e9b173e6070","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"918f145fd0946cfcbdc029987f1223df12c50b761fed50860687f3b1eb4846097b21cc7d4682319ced06c4fecf","nonce":"7fc03640bde39e9b173e6077","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"b86dd973c5ed1cc2457b0651faf06d9324473a12307b047bcccba83c0ae17e052fe1b4d277563783e12384f584","nonce":"7fc03640bde39e9b173e6076","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"2ff55a44ae00b35399f2992af937891219d2bb905adbc12bb0721d2dfc08be30356d26186a8d29990eae37db5a","nonce":"7fc03640bde39e9b173e6075","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"1902ded0ca8dd78308976593e7213bca745a7c5dc84bf4c8f1776cc71b444a7c57735a2a24957916a74766c7e6","nonce":"7fc03640bde39e9b173e6074","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"3c016da11b8d8a63885aa0a2aa49810a06765a9b442b741f188d095d5fc40145d068f1affb56c2edba76ddbca2","nonce":"7fc03640bde39e9b173e607b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"a1c0cd6d403d2f4556c956565d429378a69b6db400002926d25f22759b690e793ed2e49d00899b149261b310cd","nonce":"7fc03640bde39e9b173e607a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"7b9d0ad2bc18311a637278ca2d83ef87c0717e829f2bad46ebd1394ada15e2186c3e1ff5060622846fce9a3247","nonce":"7fc03640bde39e9b173e6079","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"831097de5c7b71ce7e63b0e7794c04fcc6eb52cebe6eeccea0292d294801195646be98c00080956d864055ea58","nonce":"7fc03640bde39e9b173e6078","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"7996e082f6023faf8d97edafe5939db2cdd872fb8d76068c14a099be23ab47f4037b354fba8e6442ebbf18cd7b","nonce":"7fc03640bde39e9b173e607f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"a21ca94bde2a3d56eb0b94268172f650d78837970103900a9c95cee1c90cd0652b63ee1b874850306cab1981dd","nonce":"7fc03640bde39e9b173e607e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"ace1db26ef032f239b35d23b0c4ac40f9b046b21841ac1673ed7d3b07b83157fd65c85279ba86c963b0668e096","nonce":"7fc03640bde39e9b173e607d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"2353d612842f82fd7868b491d5f83f0a536559840baa38d5c64cc5c6e94d93e079c16e724389d494520536f4f3","nonce":"7fc03640bde39e9b173e607c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"c5ba37eec59e5da80949d76af3df1b1aac8afebeb92a7fb4099cfee7018f7a5dc6543cbb4ad85c95121989e27e","nonce":"7fc03640bde39e9b173e6183","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"15b8ca5bf226bf9924d4dd3c770d9e9f534e4069655e29d477f69a6fd983a830"},{"exporter_context":"00","L":32,"exported_value":"fbb906f58e73f64d6d664417a33be2555ce2019f96905b9e7a3a35e4bbd2488b"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"433012037ddd16977cce565e09a6d144d159903452c02b0910a6ec37fb59f400"}]},{"mode":3,"kem_id":16,"kdf_id":3,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"464ebc07ef77a6bb4199d29000c06daa56f3bb3edaec71eb196e4e6d3c217a4e","ikmS":"c8ea69798ad512161ed789fa8b6a84923796c6e6ec808001f50e21967e4bfd6a","ikmE":"ee2ec13874fece5f5d8ce261dee3990ffe0bca2c64ac43ea16a2a1f9aba67326","skRm":"f41b1f9aab1c994fb377ad3aab673e3d73fa8e96e5c813e66b67297c712329f9","skSm":"e2f65d9300a0d46ce4577652fd18c70c6b8c4a76c1dd4442830d4c4e747467cf","skEm":"1f0d98c09a4d87bfaa26b4b033ec35fabea3f8c7ac451a12e5a31d48dfb55a54","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"0489f50dae6951783eba36c3a547461c30008ff6622d9d127d110425784a8f8256138760e3912933aaedc5a150b989bc865c4e00ca4f65d5392362cf66678f0fad","pkSm":"0458b5ca140547123bdc9064cea10fa15e15f4f64c9e9304813ecd3b801fc7d64752844b2823c48590313e1a486621f7ab141f80c5b2c25eaaa4dac79bb6b67e75","pkEm":"04652f4ea1af053a798309dafbc6914c626fb4bd74b58e59626202616846ca5a14ad775625d7f367fbc604848abf6fdab5ebcc69661222f636e2a193c0495ec972","enc":"04652f4ea1af053a798309dafbc6914c626fb4bd74b58e59626202616846ca5a14ad775625d7f367fbc604848abf6fdab5ebcc69661222f636e2a193c0495ec972","shared_secret":"a9a1bdf17b345553038713662d613c4547cfb3b3ce1ba98571da4d3d1e40da1f","key_schedule_context":"03713f73042575cebfd132f0cc4338523f8eae95c80a749f7cf3eb9436ff1c612ca62c37df27ca46d2cc162445a92c5f5fdc57bcde129ca7b1f284b0c12297c037ca221d77e229a9d11b654de7942d685069c633b2362ce3b3d8ea4891c9a2a87a4eb7cdb289ba5e2ecbf8cd2c8498bb4a383dc021454d70d46fcbbad1252ef4f9","secret":"1e499a79ab8d4028bca025bcdd95264a39cadc37123af22ae889e29e82c7f28cc3138c8330df8d94a3729b341c727b313cb447c70a02112e95d84d7adbdf3076","key":"eec30ef9db6d0644f0554f5f82be7496","base_nonce":"4efce095cca5c3ec361b4279","exporter_secret":"b23dfc175ac2762266a3b83cec4f404189009076d0aa2db5041cdbffb6b0bbb5248523afab3c8183d7f32aa65bf3dea35329ed3c36c12bf30381626ba446bf3e","encryptions":[{"aad":"436f756e742d30","ciphertext":"c8c87b83059cd9ffd7ef48c3994383059c9adfadf9c3daf71c57e5f875a6d911725d601708939ffa639bef253b","nonce":"4efce095cca5c3ec361b4279","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"4c12ddee0d58e2a12daf92a3914e3a7640435a3e79ab153698639aa7315cb4ac7c69d30dc7b4ba55392ae13106","nonce":"4efce095cca5c3ec361b4278","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"66d6b14249225950ce08f63aebe37ff3fa928c4c2957c02ad557d7d441245f1c95ec2d0c16caf79661d3cdf32d","nonce":"4efce095cca5c3ec361b427b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"29cfccaa94d7691203f00c3eadd1f80a7e81d139e6c01df2b12a8561a243a34108ecba823fbb336cca84d20e5e","nonce":"4efce095cca5c3ec361b427a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"0dbfccf43ee2c2ee8dfcebd212a5bfeba171236931228b10f5c0aff7e67394fab97a98ef94022dfdb4b42ba951","nonce":"4efce095cca5c3ec361b427d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"0b2b6f296530be5a67d32ce5ecc4e9b390dcd6911bb5c89a919a1a3a166584aef0886b63a65802d5d7faded61d","nonce":"4efce095cca5c3ec361b427c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"54b6e50068bb7dec4825f86fd2f9b82e2e9c051c792754a2feceaa67b3e7d4e88459ccc27b85551e2ade0fdc46","nonce":"4efce095cca5c3ec361b427f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"602f351a30015b2025698e7d4aa25aafae796bed6aacc0fd11c486f2978af4cbedbd73b584a0929fddd42b9159","nonce":"4efce095cca5c3ec361b427e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"8b2a79ad21604f2c560009c7968e37f7a8699b04ee929da172fe380ed082a2657389bf20c6d16c4b6e38dfb78a","nonce":"4efce095cca5c3ec361b4271","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"b63d36beac5875024cfff765990acffd299993ebe6a29b501ed8cf3b3c11911d5b586a9f674c956f594a7a7219","nonce":"4efce095cca5c3ec361b4270","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"6846acebd0b01b953e0f2401014cfd746351a33ac8d44585f4103450a91fe0b2f658de188c422d694de3632330","nonce":"4efce095cca5c3ec361b4273","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"8457e5f9f44699e4172b456c2ca28582191ac29e75e4ba2298e563043339fc1c3088e667b2f66b24c64eaf277a","nonce":"4efce095cca5c3ec361b4272","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"b9f4c777377459aa9c5124039e254964825296af669a61d2569837774a51b2333214c9546c998ed98695da5300","nonce":"4efce095cca5c3ec361b4275","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"e2fb452399a6048b88db6684d99ada0962cefd9dfd1f998baedf3076b4b556a9f99fea3c8e93f7527e03a4a69f","nonce":"4efce095cca5c3ec361b4274","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"4684b6991da97efa1e9ef0ca102f4d58d79989c75e63f7dbdf5e3e7028614eb141af9690629ee658c000a37b10","nonce":"4efce095cca5c3ec361b4277","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"c0d2afa74bf4261fbad88025065bec6835a13282eaf59faf5d1f274c1f8b24d1708b23e08672357d681b245968","nonce":"4efce095cca5c3ec361b4276","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"a56583a6bad7004ea60eb03c0ba175a3894d3a36fbb668eac4fdf1debaa04a7a30f0f0b425d57d0ea39f607048","nonce":"4efce095cca5c3ec361b4269","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"196e0ee8dba03784cddce3094f1c2c86bc8f7846a461dc6e870dfc66fdd1552ab9b858277d58b2268137d0614e","nonce":"4efce095cca5c3ec361b4268","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"2d7f915dc764920ae707444dd8af4589810fd582a3b240f91ddcaad00a31bc07ac5781ba899489342c470187d6","nonce":"4efce095cca5c3ec361b426b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"613ace8d13927e24c99f6890bf0c49b93eb8d8b234f8c501c1c15ec8a7b7cdaacfa6cde95cc4ee641fd3ec9466","nonce":"4efce095cca5c3ec361b426a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"badb97e5dea593dc33f4692958785591d5432c0c173f6a560c6bab60edf50603ed240d86b7a676dd1a5372944c","nonce":"4efce095cca5c3ec361b426d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"e2afda9e4ca90607cc29115af885284d829efef90ec7c7ce4e59b0ccb7c3cf42d88009aed688ead192be99195f","nonce":"4efce095cca5c3ec361b426c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"f8cc5f841d38c9849883f411fcd06ddf5d63ebdb081b6c3752ec4f9fda0f3b8004cc606b428ef2a81ad9ec0ef9","nonce":"4efce095cca5c3ec361b426f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"eba14766ec9a16350ed355af057d59bba3ac3a8eaa2b13b145f45f773dbacdfa84da57ef23d54d0a45f484e6da","nonce":"4efce095cca5c3ec361b426e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"00e0981cd1e08bcc8dc3d4c96a66653ea55a548e169528533abbf45e52fdbb6a79e4e9742a9c104569f7e3a03f","nonce":"4efce095cca5c3ec361b4261","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"62447cd18c1ad569637a3b4eff3379df978debc958c373b6005374e81b8dbdb0daedff94371fd4507a3f4d08c7","nonce":"4efce095cca5c3ec361b4260","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"0be2ad6e0c0e926c3116cceaa87f25da61d5a238b25ce869139f935b85d735c181a8de8d585c9f6a4459c0b324","nonce":"4efce095cca5c3ec361b4263","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"bf1be4bd8787a70f63509dfbde4c76d5486bdb2fbb5f13be5be23b9391400ce9941e870fdea96dc8c9834bbbcc","nonce":"4efce095cca5c3ec361b4262","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"30e0819e1f4ec3a159dfce166e8f796638c05387b79e22a3ad010c7af2a870343ab8319a75fca0913d51f461ea","nonce":"4efce095cca5c3ec361b4265","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"26da2a4fdb21778f6baf862d9796748e128ed857c3b67c982e5baa1b055b21dba975b1ee9bc8358af947648d35","nonce":"4efce095cca5c3ec361b4264","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"dfa61e5aaa0711b505b584457217d5a4afcece95ad22cabf7ef956a63d5f91f1cc5b3d5c215c0acecbd1f01bc2","nonce":"4efce095cca5c3ec361b4267","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"5d9e3428150887c46ef184ad9da8afce72da44442f60453eac5d4da6fd35e18c6679d6dc8b8dbd3f6f449d0e2e","nonce":"4efce095cca5c3ec361b4266","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"d7c8a6b483b28ca3c882a766f8bd2a518ca3361c925096f9c3bc9ec935391aeabd680f2e2d41beed1dee4e9657","nonce":"4efce095cca5c3ec361b4259","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"afc2c5db1778f255ee2ce744370fba25b2f3e88b0b96fbd56a48bbc8238811ee24b0fd44541dd8791637c23f5b","nonce":"4efce095cca5c3ec361b4258","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"7176d663543c50d651165c48b30076c61d2af6ceca92fd6ab429a8c9f84ee86108a58367f24cc5ceac24df9bc4","nonce":"4efce095cca5c3ec361b425b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"abc7c94a00a1c9eca65c112406b711b0012f20ffd8576a5d8bcde7b9c26b6192eb53bfa506328a0e850126734a","nonce":"4efce095cca5c3ec361b425a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"5c717e9e7a6f057c9ae0f09c3b1ae47e161bef16261ba2612779216f42a5ae61b4f60c643af115d3b1ed1ad763","nonce":"4efce095cca5c3ec361b425d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"166ce484e7cd64eeaf827a65f39b00f061ff4772a0d2200618ef1aeeaf941ec067857831326e192de65ca53d2f","nonce":"4efce095cca5c3ec361b425c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"ccbd688853629caec3dc5eef1ebcaebddafc4975c3de16216171a97e3b3150f89607bdf84c264c130798cabb90","nonce":"4efce095cca5c3ec361b425f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"36958608f2b54c15995a110ed731d8c523d21081c7e0984629c2705bfe87f377e98d6c29c471afba7442127747","nonce":"4efce095cca5c3ec361b425e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"48c7dfd735447751483465230f96297aee65a6f6a845a3e0e28efd5515b61266f7410cc4229cfe6bce03cb13c5","nonce":"4efce095cca5c3ec361b4251","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"c2f972e0322a5fd9acc754499ae4d71a3c29b434edef5668aa8f6cf4a3fe3bc354b1ac870b9f8feab169deb2b0","nonce":"4efce095cca5c3ec361b4250","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"9163ed7b13e4e46b3e14315fdf3fb3252b9d81698d36fbc864ce77a9ebae23c4311ef3e125e7f89551e22d76d7","nonce":"4efce095cca5c3ec361b4253","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"7ae75abe40ac12aaaa25b3fec19bd1c4bb150bf5d136ac854f6a34835e0594c73a437ecd50e1ac4d9d558a33ce","nonce":"4efce095cca5c3ec361b4252","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"6cebce67ed34d4c9002b038b01ec75cf27489fd7e65db01cf44fcc74d8bf9994d763751a55425e610afc37ef5b","nonce":"4efce095cca5c3ec361b4255","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"30617726c0b6542b6369d2f1f27cd2d083f0978ea2cf11491ae48b1c87c941a69e5f273c2579a9a7d1f6a69ffc","nonce":"4efce095cca5c3ec361b4254","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"856c0566e41873857570a742b518a1514b9e2f197fad090be30322a5edf17366d829dbf1408141ec2daf0868a2","nonce":"4efce095cca5c3ec361b4257","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"ef5815ba252251bcb222d0bfd2d068ae0ebf7b401c298f006daf905bef8994d898922661f07e5b90174d4b97dc","nonce":"4efce095cca5c3ec361b4256","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"86e05fb6451ef74af293155977e06f6339ba5c731974088a57af1d44a3b71f8c21a3a63d9ccfc67999e12d9429","nonce":"4efce095cca5c3ec361b4249","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"ee14e11f4ff28124d95425b55118fafbea15e7c870e52612cd78d530b86e72f1ca6b70cd656ca0be403d17be44","nonce":"4efce095cca5c3ec361b4248","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"d9b2a5c6f27a410394b3887214bb9325077dfc5814df931d1b5eafb8d16b172301623a06750105a33e091c170d","nonce":"4efce095cca5c3ec361b424b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"4ff757ab8e67fd0ef2f87e7d0e8cab52b24010b8245ca3096d0479fc5c46f7e8999089a4ab287f83a1b162986e","nonce":"4efce095cca5c3ec361b424a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"f8de58e65f368e5e1fd733b2775e3505ed9747ac1036e6cc00b8324d5736544ef0e82871a55eaa82ffb24f0df0","nonce":"4efce095cca5c3ec361b424d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"e74c8fadc7845037dae1e9f5d9612d4ac4ec718aa4de347772cd93b3caa21eec7f736515685404450e8a5e13ad","nonce":"4efce095cca5c3ec361b424c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"94566545e78324bfcc244838b04120508150c8faccc746c12f11814f4bf3e9eac06cc4d9f4fcff2329fc456065","nonce":"4efce095cca5c3ec361b424f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"4c8229680fc4a2945349f1df762a347e131c8e249c96bf180de8d87218208471c9ea589d9536edb4e4a988814f","nonce":"4efce095cca5c3ec361b424e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"08ad7aeb6197f28c278a84b24cf6dc096c4d860c98b399ed321bfa2dba83fa4910a7b6347b05db430c390981ca","nonce":"4efce095cca5c3ec361b4241","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"400aa507fede547249321185447b5a65dfe813af09b2f8b95fc998a610d16f80001e7d9794d7a0b33dccdb7242","nonce":"4efce095cca5c3ec361b4240","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"6f02bac2d296d68c3a7fbd893436055fce6086b2ad9fbb11c1260d5f1c5d10d2eaf00d4186bb2d4b0ea0abf281","nonce":"4efce095cca5c3ec361b4243","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"2f36dafc6ec0ad5f00317332da38b3e01305f00604a717611ded411a8790ec08a441c73ebea53a42527a6512db","nonce":"4efce095cca5c3ec361b4242","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"932d6650b64341435d080b41286f9f3a6b254b2b7b1128aa2607ee17c33b5fc9ec141ecb59b18eb2da6d95c88d","nonce":"4efce095cca5c3ec361b4245","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"7bcf0b237b97573826b2d9e3171864b65ffae5d02082333b497f78eb673ca0fb9d8be71eef69194dc894e95efd","nonce":"4efce095cca5c3ec361b4244","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"fdc7ba2a908c40f3310cd8a2bb016263ab3a153101630b9469cf1446743cf0a5378efb6f089bb10e4f65ff986f","nonce":"4efce095cca5c3ec361b4247","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"336916ffd1503fe5cb45fb0b46070b8c9e5f21234aced75799ec55276da8ffc6b3d4573f3c8a98dfc997a42998","nonce":"4efce095cca5c3ec361b4246","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"dde3c9d7ae7b835de5ebaa8a335c7ac2d4407d7466419d045fea89607257ee0acaee8e2a84deb42e29f552af3c","nonce":"4efce095cca5c3ec361b4239","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"e5ede89a53d22c2320fd579ca747799d16f1c0f638947fae7f114c3aeba79834452eb69ed58d2ba3ae357e3791","nonce":"4efce095cca5c3ec361b4238","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"0f251001443b85d98a602b0e8b77801957e7ad68598207d49e458e0463038f92ed0e70929ca64bf161605a1a19","nonce":"4efce095cca5c3ec361b423b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"10afd592dee91ee2a40ab83dd8ee5281e585a0e8fbdc37f32f53eddaab4a0e9c0924861c77fcb5b44110c8b63a","nonce":"4efce095cca5c3ec361b423a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"00eaf7bfc4822a27f9b253861cafb018885ed9abacb6560b01fec364bea594b8250f3d13633e7aa669e7aa86dd","nonce":"4efce095cca5c3ec361b423d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"77ff64dfafa3081d6d456562e26dd2b22c0f452304a9ae91fd25bb43f950ebd5ab3a9436fc421e59dc475aae50","nonce":"4efce095cca5c3ec361b423c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"6476246618af3130f8641e556857b28561693ae58156252053d20e281a860b7313fa96c57179b5293e641ff3e4","nonce":"4efce095cca5c3ec361b423f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"89d9da8be109a98a5e8339f37bf65d62cb149207fce83a0319b11194ac1f52af6aacb315e7adfe96bf17fd7a6b","nonce":"4efce095cca5c3ec361b423e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"58ec2cda1e983d68753a0b20848fb6427e697173886b7e0e963250ffe97f4961502214eb2ac188e9f46a1d8207","nonce":"4efce095cca5c3ec361b4231","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"93f2523b76bb509f53aa84372a9e83427ee4db9d418394dd1801a5b26ae6b835e446def05494a50822945cd619","nonce":"4efce095cca5c3ec361b4230","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"978ce554cd24ab55b6d642392a2fae2bcfc4138df6fc4a186b06706a63ec32b10c4c351c050afd07f321b08b72","nonce":"4efce095cca5c3ec361b4233","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"dbe9f04e373269aa57e81e06b4172c6343b2b9c096f3c4c04ee127381c00e9afcb0c735921503f8d092fa0dc99","nonce":"4efce095cca5c3ec361b4232","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"5a421062deaccf9fe0e1b4e00a2324a48f2b14dbda3a6ddc1cad280c6d70532e7d4e1ae398acf3d591625f6726","nonce":"4efce095cca5c3ec361b4235","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"f655efa39744a51c57881cc9901bd50565cedadafa45f9d1fb5cc821e691051e107bfb96507f42dc9ef5066714","nonce":"4efce095cca5c3ec361b4234","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"4f5e92bae667e5361cb026df014aa795b696e3623d28a3be1e43e475594c18670248c683b8f551dfcfa7479c8a","nonce":"4efce095cca5c3ec361b4237","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"08d6a13c7d40e331bf5b5d22d4bf1ea23ae5564e2610743f422d8dcaba8eeb4b8766c72bd9f967f928a0faac0a","nonce":"4efce095cca5c3ec361b4236","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"81eb9f2f6d915fe59f6a4d13915ed7c1b90af2c759bf13473b9871b290ae2ab9c8a59f7a58bd1bf7dc53b6e4f7","nonce":"4efce095cca5c3ec361b4229","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"dfc71a2e453e8249b737a106dd07362ecf6c525da2c6b8c27ab509754f2fdead52617f56e3a04f63cd2f486e6b","nonce":"4efce095cca5c3ec361b4228","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"7fad6a6d021ff66ec90daee290937b695b9d903c3bfcc88f83e71a94472b8d06afec268fa606a8af142b0ae0cc","nonce":"4efce095cca5c3ec361b422b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"df44f8f422c70023e0cb2f525606e53f270f2654e469ce02314813d1f961bd1955813cf324175635afaad4f399","nonce":"4efce095cca5c3ec361b422a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"22c9b464da9cc9b9cc4aafac0e062712932d0ee7b2c6a37cf29017aa8cf47801e5a4cae2139e6f80b978b79a70","nonce":"4efce095cca5c3ec361b422d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"ecf0d8750fa812a1c8baa0684482fc33a5ee403e728c1d560db62a284daf9c25217d04a3852989e2d62d8b535a","nonce":"4efce095cca5c3ec361b422c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"ce4fcc5f57726bce80a4a89a5c6437ad68a9047f2d7079ca4f33b6325ae1d660d0a07a701f47bcda3ae5524b2d","nonce":"4efce095cca5c3ec361b422f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"dba5a19aeee369363639f47fdc82a3fa802c5f6a2cd1a6be2125baedbf1f34ef0c07220d29fc8f6e6d61153212","nonce":"4efce095cca5c3ec361b422e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"98ecea60de7db444be359993843b19ea78d0b1386000349f8f8fdce09ba4d602943f8d18d27e892bc0e631eeb4","nonce":"4efce095cca5c3ec361b4221","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"24b0781fea3c8ba6c9486e6ecaef061738c89236422a3125ea9b3d443ec093718647761cf4738d9da9bb9d9a92","nonce":"4efce095cca5c3ec361b4220","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"50bb0b21a988b3987fbdc9f5fa4ab679da5f354629c9510fc88a4e08d1c10c3057be6ecc1739bc23eda4beb326","nonce":"4efce095cca5c3ec361b4223","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"01834d268f58cedd02f59e00403d0b91e5b6973960aa1fc46e36ec04b905165e5f29d174586653ae3d4c908576","nonce":"4efce095cca5c3ec361b4222","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"354e7bd3e3e2eb186cc8ed4d5234ba1911c46ae6664e5310b1741402b09394584fbd35d30ec05c91e3ce711fd9","nonce":"4efce095cca5c3ec361b4225","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"36939f30c678444a346744d69d29398cc20efa0428e8b98450c06696597c8d6ff4c0ca1ac76a2574697b3133a3","nonce":"4efce095cca5c3ec361b4224","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"9dd5daee1d1828cff8ac02e0af3f41766999dd6642e684128c9cb9dc6d52ec96dc9c7c952e046547f069f1306e","nonce":"4efce095cca5c3ec361b4227","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"87841a2bebb816b2b0a6d59311a464c0550669e52c0d3d6616efb2bdd6ff05793285c54fa282183271e840ec90","nonce":"4efce095cca5c3ec361b4226","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"f9486918723428c01d25011a0d01f1e43bcbbaac05674bc591db77b2bf2a44a33101ab0a22e468a2549d7078fe","nonce":"4efce095cca5c3ec361b4219","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"fd3d24f041e2c0972010bb4660490cabc5facf11d482009fb557682d1ebcf21ece7d4c620c1edd055978f4b407","nonce":"4efce095cca5c3ec361b4218","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"7413d02205f41df5407cc6205351da4238f4dbe72f5855eb506bcde6e65127e5c47cb976f0d3e8d1ab40510e9a","nonce":"4efce095cca5c3ec361b421b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"28f0752912c08bcc5d3397b93fd5695aaad5574e925820ba31f027205a12b86747e52030ad352ed74fb1ac1a98","nonce":"4efce095cca5c3ec361b421a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"77e571be6a744b6a27e08ad2111faad571502d8f581c20fc79623cc93770be549580f16498cf22b6a0cd8edf73","nonce":"4efce095cca5c3ec361b421d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"f3852fc1c9b1ce8f5245220dffa44ce69ea24a1d9aa007f3d1956d021d4bb8f294f3eedea2841a5891ccfed628","nonce":"4efce095cca5c3ec361b421c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"67268795c0c914e473931e6da5d755efc2739747fb96f64e10e31eccc83d4c6e12d94ef4f8e4dfa0d515b1481a","nonce":"4efce095cca5c3ec361b421f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"c47d826866dc9b835d95ae739eebd50dba8062ac4c139a93a3ad93d3ab99627caa49a6a9e646517bdf0d11be41","nonce":"4efce095cca5c3ec361b421e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"a793a7701c804877cb0c53aaed2552a68dde43fbc10a23aa7e7bb88ac4fc897507518e78d35d9d5bc6f491530a","nonce":"4efce095cca5c3ec361b4211","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"d02c94bd72f4c6729edecbd7ada147e5445291446f3afc569d735e23a73b9e8e8eda8566fe41b9aa9873924739","nonce":"4efce095cca5c3ec361b4210","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"d73a54f82b5f4ba9bc569b902b4d8a028d4efda3b27992caaafad72574c8b4641beac850c0034c4619740c6fa8","nonce":"4efce095cca5c3ec361b4213","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"9cd031632fc93d550be9213fd34ae12e5e86120c51ad516489278269734cd3a3617f196a0892ac0d3110e1471f","nonce":"4efce095cca5c3ec361b4212","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"d5f14eca51dbf91314c7ed91740266d786e1732b28ef48c0ed313aee3ec06750a171cf9a72d3fc1ef1360cb652","nonce":"4efce095cca5c3ec361b4215","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"b317c5bc087d52e536e355a3d84922474053f617c2213068693a88fad85bba570b8061a376c4dfeea21c9a2be0","nonce":"4efce095cca5c3ec361b4214","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"02a85a9abc4179117916599eb0c42b6e506c840108e25a4252f129dcd9885d55be90d7591062149475675e26cb","nonce":"4efce095cca5c3ec361b4217","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"bbd5154a4dde4771e805242dcbb1452d26db4e437a649c7657ded7b90c1ef2e12f427008ebd7a99dd91eb63276","nonce":"4efce095cca5c3ec361b4216","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"fcddce4df382516c2f4d291fa463ed46e2904e7835b07e820f6cde5fabd7d9d5851aea19de2c14be63d95882fb","nonce":"4efce095cca5c3ec361b4209","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"89489774779fd14994ae13c1ebe401d4adead0d19d16ab3db45d502c16f5d5bd06cb0a4c8e81da28c300fbea20","nonce":"4efce095cca5c3ec361b4208","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"adb9d21472c85d7cd4c82c3f348dafac8eade27ed00fca6908851341332b1f11492bfa7a7e729c9d37929bbfda","nonce":"4efce095cca5c3ec361b420b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"b1015fd2e6fa25f993645ffefdb32a49f774de0c238838591a6069a006e3e2f4ad34ff6ed58ce3f3ec36a6b84d","nonce":"4efce095cca5c3ec361b420a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"5fbbb227b68bdd80c1ffdb18db501cf52497903c75577bb27de02da880b823d25ac91b4610fc2aa0fb66eda4a5","nonce":"4efce095cca5c3ec361b420d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"94bdcff55b0289de27fa6a37459d1555a32a7106edd6e29b8f0a94363baf40de3afb0a33b46b2fb9f37138b710","nonce":"4efce095cca5c3ec361b420c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"a2d8c0977749d042cc53939a52adb35fbb723df48a6ddc2287e9267babb882f2de13a82f9c15001e0d58662fc4","nonce":"4efce095cca5c3ec361b420f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"f170f39248fb36734cbe025f5b6a3d2923cfdff86e89b9e58252aa5024329ea88e8210cfeea204f5266f09f93d","nonce":"4efce095cca5c3ec361b420e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"3efa2b36a7dc8b3ad084ddad2294a5504d4f131c55d25eb3ec9e903d561cfe0ead9e551449cc715e94d77121db","nonce":"4efce095cca5c3ec361b4201","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"b3ac52a0f7dcaef86dfa5358f4c2fe14a0d59ca0bda785046e4c4c499d3bbb019d41f68ac123efa46e6f38fc64","nonce":"4efce095cca5c3ec361b4200","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"96e227a24bbedadbfee2a5bd77ae221e93509f95d22e7f915bccba9c7b20b4c7af95d8f7f295b146fe007da3dc","nonce":"4efce095cca5c3ec361b4203","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"37a8461f9ff4ca6d7cb93f543141af4b439a7244f55ffed43742dcb498636be208e942f3b49a52fb3a1efc8118","nonce":"4efce095cca5c3ec361b4202","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"e88b2c899448038b3200fda70e8bd73db0bf1387673148152c8fa2ede5a20dbed6b050acec67c1224276d52a78","nonce":"4efce095cca5c3ec361b4205","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"15f9ecfe01446df75933a245f922dfd53e07f28615fecc90949359cd70000a7c9cb1804612c55632da7cea0ca4","nonce":"4efce095cca5c3ec361b4204","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"638fedd3565d63ecb06ec1d41cf0f4dbae68541dfbb3d352a99379204453bc3c2c8bbfee7c46826f8f95ae0788","nonce":"4efce095cca5c3ec361b4207","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"b7764b7e35abf36e59dc98c27dd350f2a0aa3641a5c3d2b510999c7e44a8636694edfb256613d54d34be2dd6a7","nonce":"4efce095cca5c3ec361b4206","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"132f9c53ed48a5e501f606c87f8e8c40f528b9953fb6a7eb17d764162ef641f9168e6c3e9486b5af4fa6b3c0ad","nonce":"4efce095cca5c3ec361b42f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"6992ab61f4e9b3d877fc279732a02364f586d8d7dd05884a5810eabdd0dcfaa7eba5d7463b277b8c1e4d36ebdf","nonce":"4efce095cca5c3ec361b42f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"d35c70e36520a0921849887d60946bcccde2a62d9138813a4547feff184704d0638724aa96d465423ad5ef2a47","nonce":"4efce095cca5c3ec361b42fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"c13caeb2eec1a6f20c5fb6f7efe82156ab66836c75cb50e36c308935c4aab5267e14c509fa3eecc74ba37a6a34","nonce":"4efce095cca5c3ec361b42fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"09057aa82609023e73552ff0fa46f0be91b6e6be783431ac2e7210ca1445e2e5b8944fa6739e9b1a80ae1ae595","nonce":"4efce095cca5c3ec361b42fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"d01c0b4b5e50309e2d22331b2f4cbd22a892d81f6d2afe255068efb81208b96250921d0df715e616b504ece6bb","nonce":"4efce095cca5c3ec361b42fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"db729874cbb1653592f17347922087a10cc758458ed2741c71aa8f5eb3537a387f4ef0831b49e608f7675c77b6","nonce":"4efce095cca5c3ec361b42ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"8469b81485c16e3085b8ee39cf94a5ff79c603c8ff2cda93a1d7fa8b6a207a98692bc203f8ce34b56cd309e498","nonce":"4efce095cca5c3ec361b42fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"3f4ff68cec86f8cceebc6eae876ec4305e072c2629c092cfbbebb53f8838c8f2af70ba8fb2830012c3aab4c3a7","nonce":"4efce095cca5c3ec361b42f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"57b7b68871e6f718afdfa299a7735ae17a0fe661b1809a1c7a90ca0f2a2df635764a057ca0eb6629ab2e308330","nonce":"4efce095cca5c3ec361b42f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"91b26d090500ee866e25d0583f5903afdcc4a941ffa696795e5e2ea7f4310d1807e71ea17924e56ef1b0514346","nonce":"4efce095cca5c3ec361b42f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"0aad27779384f3025aa64405219c2a78c0adad65bc8f4523348a33894c00f00bc66445282df93e4ae36cc58dd4","nonce":"4efce095cca5c3ec361b42f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"2e9eadbdb3987a298f634995eb844b91140d13f42f7f3c4bf0b614a2615578a7184ba100939122f1b919524edb","nonce":"4efce095cca5c3ec361b42f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"581a6c7e477c64e937e1e470ada8005711b43fdaa2a6d8ac1576b19270111ec359d8fc80b39da18125b2ac937c","nonce":"4efce095cca5c3ec361b42f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"22abcd4a1f6d80953a561f4691ada1902e0810696c98aa4b486bcbe410452d2b6b39cbccf09483e9ec161efc5d","nonce":"4efce095cca5c3ec361b42f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"7ce3d366f4f714f701905b66bc8f5a032031bae09bae68617dea32d72e138c77a1fd9781e55415040fad0e9d7f","nonce":"4efce095cca5c3ec361b42f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"3ef8c86d005600999f71b7eb4c9eb95000b49d17bdf728bf0d2a51daa2e612a152b2097424681cb9184a6eb56d","nonce":"4efce095cca5c3ec361b42e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"8a99330bb537083c8041f7dc50c4498e76586713fc08ac912bd53441aa7623f199399988ab405a6eb005830278","nonce":"4efce095cca5c3ec361b42e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"f44fab0f7e8f2a8cec3f233c2390d3adaad8912e350b6826582803c9af07dde6519785a5bc2fa3678d978f6980","nonce":"4efce095cca5c3ec361b42eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"dd54c444a875e3809253372a19ad7f4994bab7ef6dff2a9fc8772c12582081f734d06f248de76d065f6e7e6e4f","nonce":"4efce095cca5c3ec361b42ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"0c8f4569264054596be309979aa9b86d8cab1bc4806503e3b16e1a1b0c42d47dfedb321643eba244f7954c50d0","nonce":"4efce095cca5c3ec361b42ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"fa8d5b82495ed54e1af27fc03019bf2b2302af0504b49ba34350f3d4a1dc094c1e02d89f850dfe4fcf13f52229","nonce":"4efce095cca5c3ec361b42ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"554beac5a548e3ea4ea6eb7ffe4e55e8f4211a5bc235ad6d84ee2846ebe2eb908a9c87e2fd878034dfd7317f74","nonce":"4efce095cca5c3ec361b42ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"9c6a93561adf0d93cb8fe8dbb9341a373adc1d3296de9e038ce03a366d3bf10869380c18f21a7c76688c9f3258","nonce":"4efce095cca5c3ec361b42ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"59a1197520bdae2f83a3a9f8c44335ea0d05cffe747da6586947669102b4de7516896928bcec4bfbb9d359254e","nonce":"4efce095cca5c3ec361b42e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"c8b832621d76c682ca5519550c7bade540393125d4e9d0ad7dc1c506784571fc05b955cac5b5257c95db65b481","nonce":"4efce095cca5c3ec361b42e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"0f9ce4253369c8005d07c5005ba16b056594fec59883b2334ca4c7fddc8cd0b8f42cd9b8c926fb4b61215f16c7","nonce":"4efce095cca5c3ec361b42e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"d6f596cfb615847e3e13554a450b5178cc44986c0c8b6e201a0cf9451d05b75da46a3b2968f112e57bf6d76bf0","nonce":"4efce095cca5c3ec361b42e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"14543f8d4fd8f655a87dd12602f80ffe1f8aca57c5a1bb7572a8a865934fba104bc0d91edf55442f9067c8fcd3","nonce":"4efce095cca5c3ec361b42e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"e2ece98aebe5b78dd4a888b31aa13a61582c1e822d10c58317a62f7e368dd0232b9913426c5a4f0ca57680ff58","nonce":"4efce095cca5c3ec361b42e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"721a6f8fa94a1315620fa278723fb642982404901da7c91c4e9f62f3c91da91bfb6b7c867c13092e77e97b6d36","nonce":"4efce095cca5c3ec361b42e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"883ff8713416ea8e17f2cad6e9096b8006ed63ce172490e7f3fe37fb2eceefb9db1d106976682216bb63e08b6c","nonce":"4efce095cca5c3ec361b42e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"67a97b37566422d7c37607158c355b7863ae7539a9ab3b83b483a9398bf8cc7660d11758fb93f0da6bc391fb01","nonce":"4efce095cca5c3ec361b42d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"b71d1536a54c5acf9e0b4069daa52017a0279a89f0d5b9df4121a5681cbe372c50fb30bb5542d33d1b91dd5d5f","nonce":"4efce095cca5c3ec361b42d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"36e06abbc37b7783cc42f778a6fafcc040f993269bc94c58bb758186a79082311ad6050f681eb2bf6842d475d1","nonce":"4efce095cca5c3ec361b42db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"59ecea60907b5d4937c437940deadfaf7f1882d72d0148d8597d0e68f40bf39143b1ff0fd588cd39cf07f5cffe","nonce":"4efce095cca5c3ec361b42da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"c8d24c9b48763978026ebf5c327726578f8898bf8865ce843cb985fe7df86ba5628121fe95cb80ad30252c2615","nonce":"4efce095cca5c3ec361b42dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"1975ebcc1e8391fedf77e507c24ce597a6463b0938d053ef4e58b45625a1c8049e01609034c72fbc3266ff656b","nonce":"4efce095cca5c3ec361b42dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"21f0f95b5be3740c57dbcc827531e2e549be1ad6134c47b5af6de2c8b1fb94b62a67605b6562ddf8de4a5995af","nonce":"4efce095cca5c3ec361b42df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"1cb5dfc2a0d944341928df4b5ff5f7a411f886324d2f4a6226076a36e122a2e7990fd957e748acf6580658e4f9","nonce":"4efce095cca5c3ec361b42de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"815357fedf3aabcd143e53d9942f35c3c5832c3f286319f6b15170c84bdc601545ecbabb5430ca9e47c5bd6da7","nonce":"4efce095cca5c3ec361b42d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"1231369cce32a5e9903ebbec5dd686da1d6dbbd39f740ac369d78304cddef01d77993f475986c1e02eeb2237f2","nonce":"4efce095cca5c3ec361b42d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"8b32add1aebae4be669dee6754661c923a9846b3264c616ae0aab6bd707766778bcc8e9687e6925b3aef2794cd","nonce":"4efce095cca5c3ec361b42d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"dbcba7eacf19d05c76c141c48479c03fb424d9479a3b4a3d9d390a2904b869df8d253e24484f4e533df16946c5","nonce":"4efce095cca5c3ec361b42d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"59d2de5e799b9971b08db74402965493950e076a2c3880c7587bdd387d07f3b8bea2997a1414544c6e2d70d834","nonce":"4efce095cca5c3ec361b42d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"067a8a9b4ab0c2ed49cbccc939c83bd1f80604dfb0fd35375943be48c7f90da7966bd777ad8d0b658f1ccb4ec4","nonce":"4efce095cca5c3ec361b42d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"c36453d7ae5a2beca2dec8f3e87d410a6241a1b6d5495ca52c538210ecf5a20a9dafedf0a4bbdcb2504802740e","nonce":"4efce095cca5c3ec361b42d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"7c92dce108363898c45a994d1c6a8498602576e6e582e84672d8bd61bde66e393dee57b6d052ada161e55bc7be","nonce":"4efce095cca5c3ec361b42d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"1a4a6a2f7876523d40ed1da949c81026ea26e02141b03119eed614fcf0431ec0f149f645b77d81a4ad81f2d2c6","nonce":"4efce095cca5c3ec361b42c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"fd7109666f2733fca429e1c6398329cc84bb6ccb48a7325dabd15cdf68e19fd5c46647ba41b5bd7a1b9b13b519","nonce":"4efce095cca5c3ec361b42c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"a6b5c6d41c699f7b450e478b7597ab23fb19d9a35ea23f1257f714e5fbe7bde603b6dd2bcb69a54a17085e8b9f","nonce":"4efce095cca5c3ec361b42cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"edd6c7cc4a5010a8437107f805d261339fc0a55f22a3aa1ae7c4d7852bc1e2b39578d1e5bdb3613c34cc72a6e6","nonce":"4efce095cca5c3ec361b42ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"a17f32880ef0a69111d418c1d645cc847e8d4a3e399c7640e30a431fe50297714cbef82ad50f2be2f9b1b0b81a","nonce":"4efce095cca5c3ec361b42cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"b24ecd8a1c1079d61e26c98a79dcb539221e6505bec3ef095a027a6c57b125b532d935fdb449a677bc2337e884","nonce":"4efce095cca5c3ec361b42cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"321d284e58bfa02beb078d871b6f8b61a7e20446b4f1212453822e377ab1906fc2d751db5201fe77bbca331417","nonce":"4efce095cca5c3ec361b42cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"f7adf26fe087f8d0ecb7ce0e2b2b96cf89f25b10624ef7a794f76388d05d499d1d9f7dc0058fc943bdf4312b23","nonce":"4efce095cca5c3ec361b42ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"a5bedaca48cad4765bbfcc885befecc51da53baa224cc6798b9d27ab130aad74e70f792c423d7615da8961b184","nonce":"4efce095cca5c3ec361b42c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"5176743361de517212cb93d4e533bd6fcf40c5fb097037ef355c8487fdd5044bb7edb6d0e2d4c9b758e1cd6bef","nonce":"4efce095cca5c3ec361b42c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"e06f028b62475f4f9af01155e7de30015b988d205798f00f98b8e2ea4615fe17a468ff09f103337962727ebabf","nonce":"4efce095cca5c3ec361b42c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"74119b2d72c3c0c9ca92d717c04d6859a3525ee32dd16f798819fa4cf78075688d04784ca09824bfd50f3a2dc1","nonce":"4efce095cca5c3ec361b42c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"18d136ee4de50f1dbb126ab944fa4f4a54b6cb483b2beb2a868f37e6e3214e1e107bba635f80d4e7738b733434","nonce":"4efce095cca5c3ec361b42c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"c76e5b383c88fae6b128bcf43a4bd7d17935cfe5c344d3d1d5e03ccc4e77ec0b0a4bfb66c99f820da9a5d2e20d","nonce":"4efce095cca5c3ec361b42c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"e2200e5bae3b45642685d61eb2ff2fc3c097912c021c8be3afe0899abe700a24c672ab1e540d68a6d0eb053bf8","nonce":"4efce095cca5c3ec361b42c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"5743804205562f0d7bdb4069186cfbf332c0216c8fc5537ad16445f61e4401c01581949e36974f7d9feb996cfc","nonce":"4efce095cca5c3ec361b42c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"a81bd51928aa8e21cab2e2747a14f827c8c58da1dd5fcb06381a0da97999c15627096c4690f7453424ba08f4e9","nonce":"4efce095cca5c3ec361b42b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"5e67acd508da2161c157bc522411cd5ebe9c51cdd7fca20abd0368215bc6f31fa022784b04b96bce3dae84604c","nonce":"4efce095cca5c3ec361b42b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"3d7d1f18fde60220b1f4c729e45a36f05fc818aaa4ec961801babce8abb71966bb4fa9b7d55613add9f944240d","nonce":"4efce095cca5c3ec361b42bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"260f109348c27c00b4a0ca167c4019c45a5f302d03c668743af9627f8a2e237b71863afe5422d920207258b1de","nonce":"4efce095cca5c3ec361b42ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"335f921ebc45470f5ae4b739c60314f485cbf12ce84794c1887be002da8585f80af4a0c4a0c9d0162c63941027","nonce":"4efce095cca5c3ec361b42bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"6117b884914abcd87e44df30f061f5abc29bac8cbe9aaa172fb4877087a28db9889b72eee79068abf285be8f6a","nonce":"4efce095cca5c3ec361b42bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"8446141514b304084136b8fe677c6a6a003286fc35ad472010dc8aa0bb4fb57927b37e00d3424832cd9edcf4d2","nonce":"4efce095cca5c3ec361b42bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"b291dd2b151a2fb59f157c91fab105afd8718a70e0ad0f04dd0ad7e7b6652a348024ddf25f1ffe12d34716b149","nonce":"4efce095cca5c3ec361b42be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"b345e2668b4bc9653ba71b2ce7ff7619c28c024dc1fe9b33a91de28b3cc311cf7579b3cc91e5cdbf6035f0a614","nonce":"4efce095cca5c3ec361b42b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"a5413f3525c45d79920ad16edd28ce3d95bbec22858078ae3f7e5e95f1e19f852b2ada014d98736ca3f8afd095","nonce":"4efce095cca5c3ec361b42b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"0e9eef95e2b74cb55c5f103a9fef9828c4cfd53a80efb58bbf50eac62824072669c8fbb35c1be7e5d13066cedb","nonce":"4efce095cca5c3ec361b42b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"3d57b58e6ed79a75d44d4a8d4bae8bc8b9728870a74d45f168696a7eaebc6fb475557a1cb45818422108692217","nonce":"4efce095cca5c3ec361b42b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"866ebb73745c69e7429c38eb374d985922aebe6ec34ec90e43a356c0e9a0da04be72b076d7469e0a1369b2a1de","nonce":"4efce095cca5c3ec361b42b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"8481acc12b905aea091b940ce4662da3677a36c2e24669780cb146b668f3f2693e69b6a2c23128389b1c660f10","nonce":"4efce095cca5c3ec361b42b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"4727fbdd16d1ccce46c45b3f5d5a4af8efc444bed5123a7ff5ade1ed022b2844e1e5b66758ba566069d3737e12","nonce":"4efce095cca5c3ec361b42b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"c4717c34ff5b635d65cf6d4a682c93661131e4be18f8549d855bf29c94c56a0dc0879f2960a88f3179e8ceb450","nonce":"4efce095cca5c3ec361b42b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"e21c6d560ebea576f0c570a8ee04ff84da4484dda37985223f6c04452ddf512a834ac20732e66e492d46c05257","nonce":"4efce095cca5c3ec361b42a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"38b26811a894be1f3d28ef6e5ac7c8c6f2582b4f6d2ee96cc4d8a2708ec1da777a364d9dc9b7f6779bc6f222a3","nonce":"4efce095cca5c3ec361b42a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"7d1dd2827ae07ea4a5e96370e373f55dbf3e09f8456f05791d921d5b69ef2f33c3d8730e58762907fbd72da635","nonce":"4efce095cca5c3ec361b42ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"e383a0069a6dcede8a6bd6a3e5e429afa84d117384e4ad1b30be83b88f7c9ac1f8e3810d6005c43a05afee798b","nonce":"4efce095cca5c3ec361b42aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"bbb3bc91dd3879be0aea733116f4ba0248f632d6b25c599d7017cd25c5b71f4316e32614647a2e511b23477388","nonce":"4efce095cca5c3ec361b42ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"1d92d178dab67c06a391948df3c75e6015e42e48b647e89f0beb6ad44b05ed5918568466a01f9f085bf48ca37b","nonce":"4efce095cca5c3ec361b42ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"5a910bffe2ec039da7c786e56faa4f8d0bb8019d365ab48a33af3a188601a3470dfc63fa5b861d232d9a5cd88d","nonce":"4efce095cca5c3ec361b42af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"336a39b0be221aa7f33bdc592f14af7630f012ec58f34ed7622706199b448263ac6613e7ad987bf1551ccec37f","nonce":"4efce095cca5c3ec361b42ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"95ec0840137a96ea23bd88b31b130be4b465b5b4478ae29e7d40fb6d94507b687ef8f3dea15f36ad371fd64267","nonce":"4efce095cca5c3ec361b42a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"7f45c105b8ddbae383e8158394dcea48a6fd8bc2b558026a45aec08fb7c84f1040c68fc308899aeb4d6a66f46a","nonce":"4efce095cca5c3ec361b42a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"bcdf4313f3b989e1231f97a912e7eb72ff38cf532d527c03d0c1ee85842b12330928261469e71a06f3469446dd","nonce":"4efce095cca5c3ec361b42a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"51eb71986e3676005f8d21984a6bdeb057d509d6301dff386670e0f5d6dc72851ce0feb8cfdf6869478a8940f0","nonce":"4efce095cca5c3ec361b42a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"3b9ed117f2d2449384f6f5bcdecc9f90420a2d4bbc6f5f5d624cdcaa0084ca082c4ef2f4819acf87c1d4d543da","nonce":"4efce095cca5c3ec361b42a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"fbeabef1b32bf1418fdf337853cc5bcd2a87b99ee22bbdd22cd927bde30462b03b921e3b6048cb909e60175ecb","nonce":"4efce095cca5c3ec361b42a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"4063ac01dace3bbc20f3e0c8079161c58ac610bc87ba9fdd5d5474c7e6eff51341edf7189edddeff7996c7a1b5","nonce":"4efce095cca5c3ec361b42a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"8ed25b5206441311450d8d803d4bdac75e3d1ef1e788929806b1f64530ddc6f1323d8b5af1be2b4b8d7f4f452f","nonce":"4efce095cca5c3ec361b42a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"fa813da93003c0219926334142d9dad8c0f939034fc9d120581ad3816f8c1f4d671ac4c0079f465b38aba26928","nonce":"4efce095cca5c3ec361b4299","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"e6359ae633959ebfeafd14192d5e8d3c214f1e1d0d1ec26729de1b151460214f6aaef74e45a02f0862de15afdd","nonce":"4efce095cca5c3ec361b4298","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"9b0ac27b59b3d6582397a0a71104606ed09624d4dd01066fd5ec827e49d32a8ffeb588cdfbe46a9df977d2bfef","nonce":"4efce095cca5c3ec361b429b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"f52e10711dcb87455d613b1fdad50af0113fdd1e9bc12b82628d7dd16fba4349819acf6d933b9d63a433455783","nonce":"4efce095cca5c3ec361b429a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"31e476b478102f37c00d5699fc20bf87eb534bcf489814f8971dd0131c89067ecc9fdabb089ece212f58871af8","nonce":"4efce095cca5c3ec361b429d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"f03c91280359cc2e9ea9e40c7b2ae7cb4383b3942b49228d17de88817f46eb4f17c44dd4645ea94138bd4dac52","nonce":"4efce095cca5c3ec361b429c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"ff581d8053fe4f3c14aada9d81865561c4770d45bb432d24ced2538bc85ecee25556bfe41c12335855d136de32","nonce":"4efce095cca5c3ec361b429f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"8ecb61d6b3db5dccb081ca635142a6da8a23a20e1180bcd8be229763e0a22e101b34b39ca0d9e53b1c87fc6897","nonce":"4efce095cca5c3ec361b429e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"fe4c3335b0cb7abc35246b996fc164b8bfdb948d849c6996e6e66025b1ec07b12ebe2193296518245bdb2663fc","nonce":"4efce095cca5c3ec361b4291","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"3f8a6ebffcc0f00dff2207bbea95b2d8d08c1a4d7cdfa41eb0bf4f19cbf68b48af41f47f1663e62de8232c9930","nonce":"4efce095cca5c3ec361b4290","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"e145f9f8712230b6c8cfc33c75ce986e04dc69f8c5333b3eef1dc199421e3d39a63724de1344997a32da6bfee5","nonce":"4efce095cca5c3ec361b4293","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"f2d3f0aba009ec364216ece0373cf8490ae0cd303b146fc18b98d2ea5eab4b0469a881404a5a3bd1e40b2ce336","nonce":"4efce095cca5c3ec361b4292","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"e4fdecd66bf0e458969370870cb533aa90b5fd4b396f4cc83cc4d957f86d8856411c34fca3c4f6236518d3ba5e","nonce":"4efce095cca5c3ec361b4295","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"f559debeeab316d291eedefaad5a1b04a5b17c8d585518c182fa3dc0566fa2074b19cf465e2e5fd3b5227678d2","nonce":"4efce095cca5c3ec361b4294","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"06c0008d251bbd7df448a3c2cf1475e755e96b2a0af87a548518c1034d60b302a3cf8be2c72aaf7fa095e63185","nonce":"4efce095cca5c3ec361b4297","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"dc99ead7c3acb41b34ec6274df70c143a1d4e542e8e855ba758928c4e7ccf0adc9dc942c797afec633afb5d240","nonce":"4efce095cca5c3ec361b4296","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"08e50b092f1818247aa5f0c8b82d6e5b56fec5cf2868d76ce2fd1d88a0306d2be7eb2e51337d00f4f96b2f90f4","nonce":"4efce095cca5c3ec361b4289","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"f4f9c53145df3e55faa404f7cfca8576c9aaddcd23c36a00a4e09fcd66496e7992d1c69ad35206611b2e3b4c1f","nonce":"4efce095cca5c3ec361b4288","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"5c67422f700632308c3fa2b4e2c44638772ef7500fd5dd1a816cfc2d82a824d5078c8c3004fd1bd410ac7ed0ed","nonce":"4efce095cca5c3ec361b428b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"05c131227fc90469af40528013a5d9679ab50be918c4808072876110b583ba5a1818606d458cca8d9ca2d4505c","nonce":"4efce095cca5c3ec361b428a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"c028e3872db8cf5df282d5f2dc558685668809c228bf65cddb72243874abfa12839a543d4abbf1eff2cca4a260","nonce":"4efce095cca5c3ec361b428d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"892b9fb727c1c3c7e209faeb34000ebd87b5f72ce657d5d17a224b578387b80e01397eb6f2fd6b5fe7ef5254d2","nonce":"4efce095cca5c3ec361b428c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"24f1b42258c07ea5df5b9951ff247c3153f3b678ec8fb74c269f2ad3cdabc1e5635eaf3e02e34e9ed51d9ef796","nonce":"4efce095cca5c3ec361b428f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"b09abaf2e0cd08c70e4ce98ffd708dc6c118b0f28541b5c841c9bc2e429e62c3d218081a12f101219bd6317129","nonce":"4efce095cca5c3ec361b428e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"cc19b069b19c69cb2b0535c262f4b5ddb3f0c382ce8c36357d842e4463da446a48ebf73ada70206742d080818d","nonce":"4efce095cca5c3ec361b4281","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"70ad1e5d6ca6494859ed330a25859b52af5ea8c8f3350499b47b7e8adbf13cb02180b4f9df71e17cf28e627348","nonce":"4efce095cca5c3ec361b4280","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"47c8c1487d4b52db5e1087e179cb6ac14fd701c800029f5efee288925fd26027409666ea02cf4724779892fa32","nonce":"4efce095cca5c3ec361b4283","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"f638df9e7746ef97f4d282a9b6c5c27d943612f171e7b0b59494d732314128866d1f348d291fcf7f86d0453dfb","nonce":"4efce095cca5c3ec361b4282","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"614cb7ced85bd9bed04f001351262c2209f5ae5001cf7b9fde426e4d67c2b2b38b6b4e4d7515bf9be7341c67fc","nonce":"4efce095cca5c3ec361b4285","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"a4a3d77fc3c62b26e827e7079a78e5184c1015aa6bec5d6b920b3fd3b610d1ade586520e5be5ec51bee8d3da5c","nonce":"4efce095cca5c3ec361b4284","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"ed3171eaee327be0d0230038180c21afca854a7ac075ae2fcea3ab90fd5a25ba1f27546c76700964d38b589949","nonce":"4efce095cca5c3ec361b4287","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"526a2dfdd4fe51764b1e2383970d82576cb2d7911bfcd20e7e05e143aec4181d837c9bcfde8072cfd8089f20a7","nonce":"4efce095cca5c3ec361b4286","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"255f576f0be7bbe08acd09d228e3783b16b4388a0e3cfd450cd6f68cc6f0b144829430977a877104121b53b177","nonce":"4efce095cca5c3ec361b4379","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"6ad40ac5e73b9136646d91edabd3d13bc0f10f550276cf1e52ab013ab10ae48e"},{"exporter_context":"00","L":32,"exported_value":"ba058dff7765a1734ea0bda12fd59c50ac2a28d727448881fe19305904fe1af1"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"c4663c3044c52cbbfeb67391423ae29c17caf1bcbfbbb6e0f53826f4b29d8cf2"}]},{"mode":0,"kem_id":16,"kdf_id":3,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"f3323a6b1967c7e8e707fe7629b54173e74df5c691a1942aac5fffc9ac64eadb","ikmE":"92a0ed70a2adf2c5ad46064017dda7bddeff4dd7d221766117bac27d01064eb9","skRm":"91daf60bb3ce8a8552fe055bd7d2fe8a2cdbc8efcde552ca568ccf3f501d7674","skEm":"e5077ab32ccc956b2162b713003b26d31eb608142cb549b715cbcdfc6657c3f3","pkRm":"047ce5de52af235ae850760ec5d0c5a47d7b54dd8813e01b9b71ee2af75c596fe7e4e4102490b042f01cf342987a89bbcae74d84d37d7d87f8bf00d729c4846eda","pkEm":"04feca0581199c3e379378e66b2723b4f276b520a91edc4719b0445f02b6527dfe07f4b858c4592468dbfd04bc740476c9bfa2f51a4e1cea48de419182297b038e","enc":"04feca0581199c3e379378e66b2723b4f276b520a91edc4719b0445f02b6527dfe07f4b858c4592468dbfd04bc740476c9bfa2f51a4e1cea48de419182297b038e","shared_secret":"f7d05af8a43048aab05305e8163c95f9ea5f5632bd91a7cf23cf7539ca168421","key_schedule_context":"005b8a3617af7789ee716e7911c7e77f84cdc4cc46e60fb7e19e4059f9aeadc00585e26874d1ddde76e551a7679cd47168c466f6e1f705cc9374c192778a34fcd5ca221d77e229a9d11b654de7942d685069c633b2362ce3b3d8ea4891c9a2a87a4eb7cdb289ba5e2ecbf8cd2c8498bb4a383dc021454d70d46fcbbad1252ef4f9","secret":"2bc978b799460b17b6f9794a0bc651b174aa4923a5f8ec2d149b713ae3834cb710590cdff49a0bdbad6ae2d81a26bea15ac6e613c09395f1620ea1a14613ebac","key":"c0c0a3473b841724d11e6d50e971e23c","base_nonce":"16de467068dbf5560c0c290b","exporter_secret":"ad8bea7e3a2eef94820aef8588c127c48a3b8e4bd48088391ed3bfd702938e56f387583df84174f86e336ac85de582582189eecfd3cb20fb9c0118e3c98a9078","encryptions":[{"aad":"436f756e742d30","ciphertext":"b6e48055fd0d5fa0a806c3c6b6078f3e12bdd9922e4253114f79eda31619473b11ee4b6202d4880a3198e7d430","nonce":"16de467068dbf5560c0c290b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"f526d2914a2669f80252295e9b5ce0ed6b0bd946b0da5ff1b82c289ef1b93d05b66c3459add57952c02fbdfd57","nonce":"16de467068dbf5560c0c290a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"dea8d5f2b523d43a6f5d61277b1102205cbbcb0b9fd2469013e66e2fec9a90585306b967efd2ea1877fc6f6f2b","nonce":"16de467068dbf5560c0c2909","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"482d4f333e1f8b0d7b711867a58bbd92e15f74dd7e68fef16b2a37b20100575efef71f12d5e2667b2d041e5546","nonce":"16de467068dbf5560c0c2908","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"1a02c1bd2adef2c3bb9b4abd8a389fb9e131cbce793a34bdc1bd75fee1251808afff68bce3ce3845757e937f1d","nonce":"16de467068dbf5560c0c290f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"12b8d6f7075b6199f1e988569e6f093825078248d54ac708afb2b0e328174cd504398091db1194dc25f2c7e1ee","nonce":"16de467068dbf5560c0c290e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"6930b68533d0327817bda0799f46ab0d7b72e084b5cacee5d1a283614cb214d13690d8a0d3f4414b2fe9d514be","nonce":"16de467068dbf5560c0c290d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"fbeb54fed35bc4217fee584e13eb82fcdf3f3d334e8709a045c0259a6014a972df4124e3e24d4e6928d9684f6d","nonce":"16de467068dbf5560c0c290c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"51bc866da7cceee25cda8d7bceeb5d70befac3fbbb66573958774b7a077831def2f9881ce18c1dcc197f168931","nonce":"16de467068dbf5560c0c2903","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"bcb448f4d7583714d5217690c88cad786e89b0c0c86bd3db11e00f18ceee85123541496ab5aae38f87bdb9d92d","nonce":"16de467068dbf5560c0c2902","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"ad18c80ceb89b64fa9dc8f3cea5d707e52c0873ee00ea987de9c187c724b009aea948d47fe9023452ebae60d06","nonce":"16de467068dbf5560c0c2901","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"5000ee999af367548d573c2d8e6ab8a27c15c69394ca1cf95655f5f9cd937523d7117df6c659d3fc44169855a2","nonce":"16de467068dbf5560c0c2900","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"9c82ae08ffe37c95aa8210d582740e6ffa26618b2d01c6ceefe38c032c6d4993bacc356f3b950d2c6ccae53e73","nonce":"16de467068dbf5560c0c2907","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"db2ace52e0e68684691f6e45399d75f882a0f81be48e67395dc00ea16e7f1812a0da96a64d769e3f8fac80e37d","nonce":"16de467068dbf5560c0c2906","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"83f31d6eaee2953a76e6ea7a1d4c343c6cac01bf4bb0ac02aba87b4738bddc7f0f4bf8bda4b50b5ac41fa5d3d1","nonce":"16de467068dbf5560c0c2905","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"465dc5fd2aacdfa5778aa64f11f7cefe9e8179096fd82b64576b17b2aa233c3a5c1a12842a52554f9cba48a2d0","nonce":"16de467068dbf5560c0c2904","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"f886f06b7670730861baeb0265571a6b4483c5089e2cec4ff60fa5a6b3fd3b28d178b8def34269810135f6abac","nonce":"16de467068dbf5560c0c291b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"fffc28497d4260994de35fe347fabd26844de1815ca836131e3505850a03ae7ac1da18dab9d7a25d53758e6f98","nonce":"16de467068dbf5560c0c291a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"c4b09c8be482dbf003ed90bb227c9be8390a31f2a626de6d11df05658b8296c84e4a81b048a0362d1260859196","nonce":"16de467068dbf5560c0c2919","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"bb6c7bba07164937ddaba024d718244206a6a80ae572a041651d6727419dd9c2bf76370d5e94a135dce1b11158","nonce":"16de467068dbf5560c0c2918","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"6724ffc42c65f3a8fd29a079512d583debff044bd7a5f7d9c5ca8936196f9d332b3e4917b9792845bccc9ae8d7","nonce":"16de467068dbf5560c0c291f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"3c0ff41b2e88300f33359bab3135c46399a397a31cd0c137e07addf14d3f4e1c0dcdd87bbf9981cace7c6ef123","nonce":"16de467068dbf5560c0c291e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"1aebbb586c963bcd15c99989cc122ebb528744758b27d86357b01925f3a6d93062372f2fc76eb584b03eb20595","nonce":"16de467068dbf5560c0c291d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"2007d66c777a644e6dc324342f95e26072d7b318e2dabc5e89d693bb4fb5c5460a49dabee3716fa622451f7a7a","nonce":"16de467068dbf5560c0c291c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"594e6990eed432afa3765a64a302704eac42c5fa1e009060c6e9a42b664ddb9c587a2f3a1ee28a9b0bcfdd658c","nonce":"16de467068dbf5560c0c2913","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"9ee1f662bf485ec394b247d3df6f8a5a0501a03474a92420a502490f232b398905f1de4a182c69fda0b1aa550c","nonce":"16de467068dbf5560c0c2912","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"49ab908cb2340c45c4fd11b7aa0164ca973ff1206d15491b7a723a8fe3809cb59addc79785392d36f48ac78a96","nonce":"16de467068dbf5560c0c2911","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"56559f30210ddd38e90980ef891162c1c59eda893718b51aec465b0583dfb78e4eaf5ad018b25ca9ddf15f5944","nonce":"16de467068dbf5560c0c2910","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"6254fdd71783f74c59e0149448e0c27156130868918a5bc2725fbdf36451d54ba29b07b5d616b4cc0ef96ce08d","nonce":"16de467068dbf5560c0c2917","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"2ba73cb56cc836f60f4f0ac9ebc199eccff38eede79655ee2bf7500e6f99b707f9522f6a91385e30463731fb70","nonce":"16de467068dbf5560c0c2916","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"bb4eead34746a09c672f731299df081ba8463e571228c1a11c4799e9f0b9467b1a7bb473bf2346b0caad106fcd","nonce":"16de467068dbf5560c0c2915","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"8e43450a4105600d40f84d31dce68bd0124a9e5ecf942b41c6b993a60839ccde9a107efdead2a1c7b0200a5cc0","nonce":"16de467068dbf5560c0c2914","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"73003ca90278a7871c27d1927839b5796b58781c17449abee0a08a72f9ae24d3384746cfdac0a8f7991cfe8447","nonce":"16de467068dbf5560c0c292b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"8b810d13c9313e26ca1cda229dec8d68a31818cff3f2eb1367852a623e3584338eeb0ed7a7a550874fb3cad169","nonce":"16de467068dbf5560c0c292a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"c212165bbe87056c52ff96ce34834a210b571a0d62c4585041852eae13fb331b4c99113fc4daca1dbb7c36a909","nonce":"16de467068dbf5560c0c2929","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"b0ec2ce17c77f3169c86071ff907eeb97393d70f746317b91b4dba45aa67b6d3526e1517f6c1fc8ce3c833332f","nonce":"16de467068dbf5560c0c2928","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"e23342b0e7062ca765371136627dff103d96ed45a91adbb3abf51d42ac47d4558eb0bc263f3785efb670e6d146","nonce":"16de467068dbf5560c0c292f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"00f9504b9a349756287016958a6132dcf8263921b6cf275314befa3fbbecef5a66f24cd8988bdc5e4577f2fee1","nonce":"16de467068dbf5560c0c292e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"48fd61cab4ed58d5b5f4cd018acba067b1a0ad203cfae02efeaa3a2b644cc5306bd4bc210d8c092a79b332039d","nonce":"16de467068dbf5560c0c292d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"3c130998dc2b8909da6a1a2b375ccdfaa770aa5a4a57ff4a21386a033e320c7b3ddabeae5412a5bcfd480bfd49","nonce":"16de467068dbf5560c0c292c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"a9c5dea0c079b5c7a218ac0f9a16ba0724f196529f60d505916acd5a2254f8c4c97c9f75287a7612d4182ef72d","nonce":"16de467068dbf5560c0c2923","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"6953242d6d2f7c9a38e314394eb8a41a0a08a95636ea60f41302c7b5eb1d6f8d69a40d04b454cafb2f1fb7b5f3","nonce":"16de467068dbf5560c0c2922","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"85d1fc1dd93890015b310237f465b1e1b4e8706a54e5180d7a7a2ed8763ea797f833cbbb4b9241c5b0c03f7f57","nonce":"16de467068dbf5560c0c2921","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"859f409d9b4c44663506132817ee98b715bc7ff2402892c9b537fca9ad73d9304e148b085b77cefb15b05de834","nonce":"16de467068dbf5560c0c2920","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"458f0169097b74dab2e87b8c3b78cc99d582615055f191890d45c3e8b6d4d1d9881cb0af73329f59185bed8d2f","nonce":"16de467068dbf5560c0c2927","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"8637708afe7208447441dea0389c543f112d139ac716b966ff552271194a44efc2b906d0daa23ac7fccb48bca6","nonce":"16de467068dbf5560c0c2926","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"6fbd202d4a43cccedc627d506482771f85fdc3cc3722c4fe73585f152969fd21254ecbd4899cb2830e9ad92ca8","nonce":"16de467068dbf5560c0c2925","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"f8a9e11d035589e564d30872fb8b20f9813f4ea2b96756b5c172cca0aae0afcb27a7fd5d29874ae10541289fa2","nonce":"16de467068dbf5560c0c2924","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"acb4e32624293d04fd8395439c2fcd695b0747b240d08b845d79cdb7d6e2041b7f73ad6b0ceb545bc34c92bdb2","nonce":"16de467068dbf5560c0c293b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"531f8ba0417affd70ffe69a763e4681ffa830ed32be4ca52d4262b79c58cfc4696a017dfd858fe3141d5a329a9","nonce":"16de467068dbf5560c0c293a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"f67847ff62aa2b942e0981c4ca33535de68f6493822d253c8bdb57de110c7408200f03ae4a05ac7a00a1685d08","nonce":"16de467068dbf5560c0c2939","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"e0dbede86e02652d2d72a5243236a302e257b8a144c0742ed47a667c8eadacd6973ef7d6f913bc22c847b751a3","nonce":"16de467068dbf5560c0c2938","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"45c682c2eecd1e95869aee02fa6e8a58ce70852a5a9223279529d49fc885c256a759e407e667cd027b0fe72b12","nonce":"16de467068dbf5560c0c293f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"21e6299ddd824048411d57c5230687380664685451556471c3cac83dad0ab1599bd8af199721b4c0183d3e2843","nonce":"16de467068dbf5560c0c293e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"23c076a599fa894d7663951a9a27d76ee8744f79d2034c2507b40e6cc653c18a2257a0061a57b88388cb322dee","nonce":"16de467068dbf5560c0c293d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"1625e60eaaa5fa2ebbacc8595011e046f8c3e9dbaf92ff51043a81662e59f52657e40cf78d7a5ba64cde42dbea","nonce":"16de467068dbf5560c0c293c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"bb2d24f1e0dfcd17c372a9a5c7262845ec08f457190c153c69b6c613da597e1ccb0fe70c6aa28e68979ca03e6e","nonce":"16de467068dbf5560c0c2933","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"050395ef1b7574d615314ec4a0840267e74a702961757e6682f2d34f9093f0b16526ce19203e5592fe02a2b0f3","nonce":"16de467068dbf5560c0c2932","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"2b7f4d2ff9d8b5b311bc363d69e1ba580776f78aa7be9230acb1cc1b0f35a2641211c66ada531f6b5d1b4e5598","nonce":"16de467068dbf5560c0c2931","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"f3e2be129b73b52704e6ed1bc9094e5fb9ad823265d1a825cbe3c9ccaaab911e2bdf60da31fc0dd7f07a445d6b","nonce":"16de467068dbf5560c0c2930","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"03db38a8bc371fcb7062673c67dcb7eb5fb130a1a35a29731ec301a259bceb21d24b58e4bd3f81010d1c72a279","nonce":"16de467068dbf5560c0c2937","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"1c49962c59c2f9bb076b93cbd11f63b238eeacb52bf17306a5fa5382c49a891df2c6524a83a1a203a2daf80227","nonce":"16de467068dbf5560c0c2936","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"8823820aaef5b86c8008f9236093c8936a8570c0b870a08f42d9774569b9178fa7f83f92e79d6933e1b6cdb19f","nonce":"16de467068dbf5560c0c2935","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"01edb5e2f3e273de8899dd51419c6f954fed9c208c2945cef7b9279abbf4d6a8e7ab737c7d36a587e39c2a79bb","nonce":"16de467068dbf5560c0c2934","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"953db17378a5c2fa6ade595a252acc6e4d5004c353727589e16fd4837ca0b264407f6bcc9f7aa290f48e3be692","nonce":"16de467068dbf5560c0c294b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"63070404a8f96c436588593ce05532e116aa70ec3c3acc7a967d8a344691f1f4c72637721bcf398084d9f0eefa","nonce":"16de467068dbf5560c0c294a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"aee237b53efead00238402bf008d8579885eb403e58ca7eefc2e4d63aee6c28130b3b649a9321ef7d7362ef75a","nonce":"16de467068dbf5560c0c2949","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"f4f3a33b41f7a8da10cd9c4c9d98560081ec96a2d61385103288a2879c990cd91cb6d101f813544c9b53523d2d","nonce":"16de467068dbf5560c0c2948","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"1aa7cd1673dbf42007aaf9d25a0bcf8fd39732de2e23c5447c3ac4f883f1e0023a543f9cf83c1c446f7632c146","nonce":"16de467068dbf5560c0c294f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"b8440e26507122c683af93f8049d86ce2772983c5950d7e05913cabcbeabd7e8396c1c66d433e17357f9417aae","nonce":"16de467068dbf5560c0c294e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"5251ac7420d40bb524b12dfa0fab62309a5f32fbe2ee57b646269381c3c0e44944ac5df004bddd1ab5adca0e12","nonce":"16de467068dbf5560c0c294d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"4dc2906395e9024394654d84e2a591bdbe3e915e5e15b87d5b97ccc93464ce8ec6c984b4e1827448bd7343bce3","nonce":"16de467068dbf5560c0c294c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"c9196a80978dc2cd92e475d968bc9b5d9d73d077498c523c846151207378fbdddbaa83aae38a4cc4d6526c09e3","nonce":"16de467068dbf5560c0c2943","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"903d3b6fd4c9632652e25f33af269c674f7d36e0a5bc2c7ac6bcdd35317d17fd0e615be4ae9e5d9f7b84994eb3","nonce":"16de467068dbf5560c0c2942","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"126713111943898bc151ac48a584778a2fa3e6fd9f2dbddd13b9098300f583dedb205b89542910747f4bf57c36","nonce":"16de467068dbf5560c0c2941","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"48fd1c0d962875be33fdd533476570545d456fcf797d2b974b86fe9dc312cab08a8603f1dcbf8d367dc8a19316","nonce":"16de467068dbf5560c0c2940","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"3ce563ba4038f24bd9d683a616ab86960c8c29c77021b63b7c4218a058496578db35430dabcae75604ddb21a6c","nonce":"16de467068dbf5560c0c2947","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"74bffd75413a9d465f7c5bfb789a261d32c712329a5c8f6be9c5d31ed570821566448d9f82df8ccaaa80749f4a","nonce":"16de467068dbf5560c0c2946","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"409f5e2b869c4a2097a53f09717e3f32a5c30954a8bebd63520af4729b6fa4b17419061ac18d401425c51bb2df","nonce":"16de467068dbf5560c0c2945","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"a42db4ccac3b4dbad701c17e2de04525e54a46f43eab42d05c5db86e00d3d9d6bf45e8970935a58af03b3ef89b","nonce":"16de467068dbf5560c0c2944","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"3937685958f36c9fec17e8b23e627c7d4738ef1d749c2b7dd12a7167cb195b82257a160ad9307fd20a78ad8726","nonce":"16de467068dbf5560c0c295b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"30e81916ef51055a21f9af880da4dcb105cc0632b19b2a985f0cf576271a8fda1bd9997d8afe61f5e2049e00b7","nonce":"16de467068dbf5560c0c295a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"6f4b6852abbd4403325ac1bcfc1aa63d1f90bc451262984d20640d5206545dc5eeada83ec30dbce73590d82beb","nonce":"16de467068dbf5560c0c2959","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"2e4398d100048690f7d604a7e4b9563132077912bd356371e3d3bdfb3cc32edfe200391690ec68422db72937bd","nonce":"16de467068dbf5560c0c2958","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"35ce821e9f87e4ed6b5d5fb71b05605c055e4ac2ea488e25882d4367ae2a4133af29307b31ef8c553b05651f31","nonce":"16de467068dbf5560c0c295f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"6603f3f96b5f8c8e5f294b53f400c62072c019cdefb2cb8b84d466c6edca666ca47abfd5b9ed577bcb06c9e05b","nonce":"16de467068dbf5560c0c295e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"4f137b5ffaa93fa10f8cdf7b61183c27dcb1efb0f6931212793d7340e71add9f6529eed82fbde648d3b27d33e0","nonce":"16de467068dbf5560c0c295d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"b836c4744810ad03901efa0326ba6df49ced1b7fe7309726143dc1cb621ac9a6fb2ebf1d2b0f71ee7d2f7b1e72","nonce":"16de467068dbf5560c0c295c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"468a04fc18d85bddf588903d95716e3b6c6bd1ca05bf5d9b15bf9f21d99fdb473e717edaa4269082cf2f96df89","nonce":"16de467068dbf5560c0c2953","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"3747f6032a39a53ba58455dc8f361eee10e7e9c131c10298ff79aa30a08f33fe1a1090e5063ca7abee70f173d0","nonce":"16de467068dbf5560c0c2952","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"7634770a71a562145001913ad277dbbbeb732f3eb53c81093961cf0b9432497164ee5d7cc48b6ffcae37c7454d","nonce":"16de467068dbf5560c0c2951","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"517c3740fd8a3a4bda92af87783fdc74452c7127ba3eb957bd835d6b0cf4cbb531a02ff2a0e6e32ee431f3624e","nonce":"16de467068dbf5560c0c2950","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"8eb244357d2dec6e9c3b7c194d55962eb2d709dac7967d2ec469170d64202652606171604bfe5218bab1b6c8d3","nonce":"16de467068dbf5560c0c2957","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"99367deb2f8ee961d4763933f33fe6b48b2f409f01581e5e68d4e0a42b8052a920959d4090e682ca7cd2062c6c","nonce":"16de467068dbf5560c0c2956","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"379bb48ca564ef5cf9bf9cafabdcee99b64ee0816fc0b84076a550d401b1f7147187ac887161e0ccb4df369437","nonce":"16de467068dbf5560c0c2955","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"1d0c006da171a1470e7e9b3f503225499ead1720759bd750cef07f7bc8c2e4c9301a3e666eb8edaec597638223","nonce":"16de467068dbf5560c0c2954","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"254e6e62e7a1289e47ed3841f76f00382f533ab80572f5db10ec784debbfcb8f8eff3b05ad3940929716e454c8","nonce":"16de467068dbf5560c0c296b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"7d61a313acc956e4db438ae1c4f101e2dec6bbc2864ae522e94492507ec3bda0da0373467930264ab5c55bea1f","nonce":"16de467068dbf5560c0c296a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"7bcb97693d948c688e4d6dd4e10c0ab5fd24c725be355b6ab60ce6f1ed9f9c864f791a99f57273f3513e66f17c","nonce":"16de467068dbf5560c0c2969","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"8a553303ea93d8555b70b2acc91c23fd1314f4ff1009f6f10328831691a7448f5b0cc1aaf7c8569fa5dcf50ecf","nonce":"16de467068dbf5560c0c2968","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"027455f45c2fecf6cbe8f29f784965e3236e09a86346bc125076166ba1ff8c66c5d35d2971d209444dee6fe7d7","nonce":"16de467068dbf5560c0c296f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"ded5772197d45d60cf9c293c465d057338b12c8560930883048fc2cd9c83ee5e55f678355adc50b3e45560ae93","nonce":"16de467068dbf5560c0c296e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"37ea384a4a3e05da7c00b8a7fdd24e5f354f1e99cffa541d6111d9725247103af5a81cc5d8a88c5e1fd5379555","nonce":"16de467068dbf5560c0c296d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"ed365f66d7a71a4d866ed248422c4de17d4227efa7cd37942ed86b1eea9f715a4b581b749623069f9e808e43dc","nonce":"16de467068dbf5560c0c296c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"4daf3ccc53ae4e0ee9206491bf2c046e5cdb50661dd470fa91bf819a3c9153906f101c4b907cb2f9f953858088","nonce":"16de467068dbf5560c0c2963","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"338922e6211e10cbd529f6619496dff0b30746ae64142e16bbe871dde8d199a1a6324308419f9472e9057314cb","nonce":"16de467068dbf5560c0c2962","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"1fa18e766cdd5159d09a42a5b8ebad302f835a315debecd4c96c86f21c3476291b14a92f755066ec5212e805b0","nonce":"16de467068dbf5560c0c2961","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"174ad764b23064d6fb0bf0c469c850d7c2764919621e8746e58cb2e4408ab9e8af6f1825450051ab599fcaa7fb","nonce":"16de467068dbf5560c0c2960","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"01d359218550a0df273066b36455a9d5bfe2602014e93e1c8c1f8b8d5978d22017f38dcbdb6d80422831ec5797","nonce":"16de467068dbf5560c0c2967","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"470e3154530533a88f51ebb6d90c3ebb7104ce19728e56df1978b509f7b046c04c9877f26a608d5d289d579f5f","nonce":"16de467068dbf5560c0c2966","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"c756e1dad9449430c622e094298079dd7320442132a073c2c82e8de6444cf50948245cebf8046f33fe6f39d828","nonce":"16de467068dbf5560c0c2965","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"b841d8d5cde33126346cb5cf83352dbaac67a634fe8c08838fefdb4cac12f8122c4d8d694f1e21adec48a267da","nonce":"16de467068dbf5560c0c2964","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"c3db48657c5916bebe0a15a4d2b24a0fb287baaf4bc61dcebd0869f45f913a73df88f86826d37940dcd8cdd14d","nonce":"16de467068dbf5560c0c297b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"545a3f8a358fe0b5d28900719e92097f071a1c4b4199ef008d5891f41735a3d176b82df2d79a3dbdd0894eedb1","nonce":"16de467068dbf5560c0c297a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"801cfc643b906eea801650f528aed19774ce5d27eda72c9a65a8d6cbfcb188cd27a3da622aaa47e4ce6b0c4cbb","nonce":"16de467068dbf5560c0c2979","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"1a9540b5605d7ca374ca467e5c0e325ed86013894dba8b6f74358cbc9a62278601dd58086f5ed404666ccd4bd8","nonce":"16de467068dbf5560c0c2978","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"68b72a986770bb1c23eb021f176b32fdaf880649bb9a23984acf02da3c57e26895459883cdb1ad3758d043d176","nonce":"16de467068dbf5560c0c297f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"3384fb2e22f9376f593528814110274ba8cdf332e5a1abaeec64c2f904e8a1f4733742f7b676016cd9b70cf174","nonce":"16de467068dbf5560c0c297e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"c0de56aff08871a9db4867b59102b3339cb4414057549042a80205e9fa4ac8102a1130bd17f966affba2bd8c03","nonce":"16de467068dbf5560c0c297d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"8ae14083a0fab91837f518c512e2f708e2e7616db3725982d1caa0631215415841d4d96b66c0682068a7ef8a7a","nonce":"16de467068dbf5560c0c297c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"0d0fc244990da340fe801eaea297270d0eb40cfee6d98092e318f3734af6614d8d743f56b19313a7d650d37b51","nonce":"16de467068dbf5560c0c2973","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"0eca14dd3dfba6f88206d0ad42dc8af9ef1a8379673cbd15a881b2cfb6821dd25efbca3b41d692c0ad2297789e","nonce":"16de467068dbf5560c0c2972","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"9db9b37a9f420e57d14bc37e7f89b675c5c4e8aea2ec55498aebe763476cbe1a0aed1e75dd30fc2beed2eab2db","nonce":"16de467068dbf5560c0c2971","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"01314179b346c1f989178c30ad2d2eeed31ab5e7a05e317a8ecb5efec8c1e1253ebd9faf14a7448171fb76a621","nonce":"16de467068dbf5560c0c2970","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"6c80d5e7ff3ecf1adfb3a799e51db1d1938e633f08d2056f2da744a2d3d19385265bb7178d90448ac5f7b0196b","nonce":"16de467068dbf5560c0c2977","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"db6bceb8ff9e7727fb32dcb313a65b6eb2ab74737173570c18986a4bc94c3117552d92bd9feff2f7e7de23f090","nonce":"16de467068dbf5560c0c2976","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"72d67f1f3149cdf96f69cc8e40c847828e1036824e86d2b8f2bc8ad265fae3fa8ec2a2e64d83191215b73dd371","nonce":"16de467068dbf5560c0c2975","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"98dcc47f89ecf32cdebc408b154bcd2c7879c3d74dc0828fcc00caedc28faaaeac918f2441328f68b742545c50","nonce":"16de467068dbf5560c0c2974","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"f7422f06b247615812373929a9a17d781900395c9910975ff3e6f586f7adeb0542ff08f376ffcc776bde73ab27","nonce":"16de467068dbf5560c0c298b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"261a3c2e3c7cdfa6d08678a5eb03e5112e921ad9f5665e73968d0c7e004ea1f5c0f590865b1e5e9d0788ffdc29","nonce":"16de467068dbf5560c0c298a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"9df7fe97e76f6c26934c2517fc8c743a769cdeccb8b74d77524289dc0d10c5d7ec8d16807bf138ca457ea4f397","nonce":"16de467068dbf5560c0c2989","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"953d39f508e05cea8ee4e425c1b7447b8594d98fdbf0a8964f86a12001009de7a853f58261771085716a1f5676","nonce":"16de467068dbf5560c0c2988","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"8ed24bfc7eb1057e0de1804e28fb8d997f59bd9e8fc90da84136a135905a3a283b9e3d3bf0408621c875a01fdd","nonce":"16de467068dbf5560c0c298f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"d3d435232e00f916c29bc04d2d1008f34d9c88712a3ab8953ce9848ce886973356f228a481918121c543af8feb","nonce":"16de467068dbf5560c0c298e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"f959d0d494b1c9ce9b72b5733ba1f91795f7d7b9a9bb358daa2c9db9bb30d5e01f5444b2bbb84d9e07740d93f2","nonce":"16de467068dbf5560c0c298d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"779e6024c446b3c91f1d7515937d13cad8d6df8a601576e111ef6794b811abaa4a431c29eaeaf0ec1bbb8097bb","nonce":"16de467068dbf5560c0c298c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"c87938a209e27cf9019fbc550560866d9b79a9ba1ebcae732142861fad33db9fd32bc3d66505cdf8d53adc106a","nonce":"16de467068dbf5560c0c2983","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"0fb9b9e283edb0affda9cf16da64178db607c841323b4b8c12b22a03c28fddaf464c6f8cfed5b89b507d6f62d9","nonce":"16de467068dbf5560c0c2982","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"07ca2a306b04548f3721e21e3f0dd5f02cb3e9d666966a81a8fe4b5417351d1628891988fb70259a1a2a712049","nonce":"16de467068dbf5560c0c2981","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"7771c54e27702977baa73c0ec9a966072838ec295b4eeb5f8781f3a19796a9420f388509ecdeda615d00cffd86","nonce":"16de467068dbf5560c0c2980","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"b9e97f9135c1defb7d8358fcafce15c0afbf2ba2f482d979da7e6132a0d41e4b9585b396268931deac38aab49f","nonce":"16de467068dbf5560c0c2987","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"781c707afbee735207e9f1510eeff3427f88cc9299759b4e141e4cccd549d1ab3a56fecad3c3e4a1eca8f257a8","nonce":"16de467068dbf5560c0c2986","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"4780d0f1a08657e88409717bc2410c42014ac2aaadb77ecdc3687c65f6c902583518d903c9dc4f1efe8f045aca","nonce":"16de467068dbf5560c0c2985","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"c2d28d388af8d8015f7ae4b6c21ce7e4b21a34686e76cf3e51070ec3d3e27d48bc009beadd304cf372176e7a35","nonce":"16de467068dbf5560c0c2984","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"307c9c33b3ad02dc79a63bc2be2e93ea5e57f9f8236fc33aea5f49c673411e40081f3ffb4c89d88d9c45fc18fd","nonce":"16de467068dbf5560c0c299b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"c9b42796136832400fdf9b5ee83672841661689884d7b2c84f26158b599f440b83c8ba788bc39c2c4826d7dd45","nonce":"16de467068dbf5560c0c299a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"97b86cb73bc54a5596cc35dbf0453fe15c5a2c359d43e3092d19582c18d611d7ae9cc1e16a54214becd33714a9","nonce":"16de467068dbf5560c0c2999","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"a71ce8302de14caaa64bba92ff14e6bcfbaa81f89f6f4e31a68ace683876fb3de62a9ef961d9b5ed0c0e216baf","nonce":"16de467068dbf5560c0c2998","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"c4acd34aeb05c5ccf2dd8b87071452fcb188ea3dc9adaecebc28dcead4529057ed25fb0ed3d41b10565c266cf0","nonce":"16de467068dbf5560c0c299f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"eff2fefe6a5940085a946cf2cb3302defcfb5c08aca5250d29fc3af3a037acb26a90ebade4bf22e36a2f09ddb3","nonce":"16de467068dbf5560c0c299e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"f51d8d6127d467ca6d7a19ee8c186f14ee06a5ed2ffe5b9342a5ae79e229eeb74041c5f48f6071ac4ec00d9496","nonce":"16de467068dbf5560c0c299d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"d0cb0eb665648f17d921f2cf14300fe47be265b37646674ce5a362361d1a1ef0a6979824132ef1c46d6ebbd885","nonce":"16de467068dbf5560c0c299c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"c60219bf430a6c1ecdec3da3232d820566076b45c46d00846323611cf5dc214c7421a8ceeaff457999ffdf9b0a","nonce":"16de467068dbf5560c0c2993","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"6fbb7d0b9cc1f5668ae507fd551ea0f321a6a2a49078269b544425400ccc820594515fd0f8bb3116d2921e364d","nonce":"16de467068dbf5560c0c2992","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"14feb4bd98c87a962799e4abb5b7f3fdace828fc58b2594960eb1ba606dde469152d015275a06c40a7b161d2f3","nonce":"16de467068dbf5560c0c2991","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"e52097e606a748f66f08c759d969e5538528366826d740ae629392d18507caad1726d2909d42f4e83f38470811","nonce":"16de467068dbf5560c0c2990","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"061dcc306b935a40258e484a8ada1efa659bfcd2cbcdaad8ff9ee9898a76884a204b4c0474f38391e8f56d6571","nonce":"16de467068dbf5560c0c2997","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"229005a41e4c98c0f2f2276043faef6b392456c609bb0df9e92bd2d0509f854d50d3506967a79ff7995d0bef15","nonce":"16de467068dbf5560c0c2996","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"77e0669108cbfd45be130d3f58fddb2b6be74b2a583c2754164bce285b9b0a539dceec3e2ad6a053c13082bc37","nonce":"16de467068dbf5560c0c2995","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"55eccad84b6351db8710ff135f8fbe9128a7e42f91dcb39623891b9f749d4432daeb9c8f60db5b79856c62ba9f","nonce":"16de467068dbf5560c0c2994","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"314ac687f5b224cf350eadd725db203f7ab22c8c02888bb4f2e3d2d5d9df5dc9e235713cfd8455a1ce1aab63a0","nonce":"16de467068dbf5560c0c29ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"79ffb3810d281bda3aa678490e48372048f89966f717ddffe5954ef3524e6ca4fa7d385a99ea61f674ba904194","nonce":"16de467068dbf5560c0c29aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"42297243e90256df262b33337924dddb9878c28c49960555b792e11c04056cad211b58bc4c8a66bbda2720172a","nonce":"16de467068dbf5560c0c29a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"e6100e633e547be68aae9de279b050f892c28be6f44ca1b73d689ed94c2228d9923afe7bafe3551876550832cf","nonce":"16de467068dbf5560c0c29a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"18d60f359ffef90222d60d6b85edc7fc79a36ffa311ff18a0d54d8e63092d9b4790956b458722321c911f3e5a8","nonce":"16de467068dbf5560c0c29af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"1fa81bd475a76bcb428866e550fb638e30341ffccd2b9047f25d84874b76542bb1b2318b5acb426f0f7782b6cd","nonce":"16de467068dbf5560c0c29ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"8583112666a410b6bb9d36b67d49fe52250f7a34486a7aa6b2a18997b756682bafc8be35aa11742163ba2c2b45","nonce":"16de467068dbf5560c0c29ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"9c4c0dca6cf56a7cf1c3ef89c70125205090b7fa318560cf93a5db5297d00135b79b3462c2834244b904c652b8","nonce":"16de467068dbf5560c0c29ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"2e354dae367f8822afd8ed142a66d3d44d70f605f04b9c950ebd851f156edd83ef395029f44fac3f1815097562","nonce":"16de467068dbf5560c0c29a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"9ed83fe34824fc470f86a700cdb280aa2c313d42c220086015ddd1f72434046233d60a50742824fba7d1ef3d76","nonce":"16de467068dbf5560c0c29a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"5d13435027292249df80ae85dd9cf14e06a17a698a5de849e9eca5f36cd90eff95b1fc4d35c5638ee93ff5d464","nonce":"16de467068dbf5560c0c29a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"253d69d0a63ed4e35c07cc984c67846745a31454898de19ec6ccaa32baa6103171ce520d667f1283270c325896","nonce":"16de467068dbf5560c0c29a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"47eaf26804b43fd6646bda962f231368d12becf126a5f303cdfa247ff44cc613710b4b2f42e2c1d898c68b9f0f","nonce":"16de467068dbf5560c0c29a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"726012ba08774195bf7f5909347e2abbed5431ac1fee72d45bfc4c7734896c434ed044bf2507518ceac416f18d","nonce":"16de467068dbf5560c0c29a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"e901b593331e3ff8a8dfd6e51191172a5fb8a31b5a70c7f2c7d94de3cd864c84816485cabd672ceb43d166829b","nonce":"16de467068dbf5560c0c29a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"92e269742d938bd77dbd83254df5737ec531039bab8dee23746aa7123eecf5722ffaeea4618fe514bc20af64a4","nonce":"16de467068dbf5560c0c29a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"26636ca684a9f509059ebdeb83f0fe97d3f40cd90448585c7ce7c31f2ffdfca2720306e4990f6ad87df7ddb057","nonce":"16de467068dbf5560c0c29bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"159513d3db81dc564c2c213c503ff1bb3f95d96ebae7bd5810461d4bb0d1a1b2caa234e760e3c4e1ccb5664fbe","nonce":"16de467068dbf5560c0c29ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"72a5747cc4f18cff760c7621455dc0f9b9f9b64877033f79041101f26af4c93f30d540dde1b9161f6eef8f84d0","nonce":"16de467068dbf5560c0c29b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"da0a89ba713c7d13c6be956bd7c1a97c497575fdb04815008ea886767d5f4c1328b88f9b4bc92e1e8b5d007e1d","nonce":"16de467068dbf5560c0c29b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"ea35896bf3f4457ff434c84f480240788de6b21e7f2cc47a061f6c69c66e9feb143ca1abcefc2e66316a171802","nonce":"16de467068dbf5560c0c29bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"82014d169fa67d4380b201332dc75ac98f46151cd9535ee601085eb53440f96fba0ce7f300d9732e16ab0b6217","nonce":"16de467068dbf5560c0c29be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"b716d90e6e401b5fe66e590f35abb9858c5e367b0a50979fe2d92ef28d5803c623b4014827c00e1313f2dc9107","nonce":"16de467068dbf5560c0c29bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"247b3fc9a01c5a39d89d86974e731088ef803a2059c47c6233d0b32fe320fcb1b7568553d60af72948d4e291b6","nonce":"16de467068dbf5560c0c29bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"1edcf982eda034e70eb3a941af92a64a2ea491d553f60a12747268939fbd6dc65632ef65cdd044be58d3dfbc78","nonce":"16de467068dbf5560c0c29b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"ef95de56d12c93710d554c098fd529861dff41694c10ba1be50cc8d55ccf8cc52537f97429ad303095c2f5bf28","nonce":"16de467068dbf5560c0c29b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"5368e03de5ac91b673c8e5682f9f5170a1e1277ba455057ee3c85b5ae1c9e7747e7eebbfcc962a990eef77dbdc","nonce":"16de467068dbf5560c0c29b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"a1546371cff95b6e1ed43121271d48eb7dc6cf81e586d684134b1f2cc2dd6c5b3290cef4887594f15ea51c6272","nonce":"16de467068dbf5560c0c29b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"5c3c9ba71e908fbe3dee4c6f587d19fad5db266a0467a676a22bee824fe9d90b6ec81f4250ad66c37492075e72","nonce":"16de467068dbf5560c0c29b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"2f4b33f34af97b58f89f57dcc7d32efa84099e53fce5c52ef5deedb1089b998d3d959d66ce27cd5348bdca2c04","nonce":"16de467068dbf5560c0c29b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"ad321a68889df918fc6a03583a362174acd99a678bf3e87b47a31b694c15fd4282dd7d20b5a84d14ef0895cc66","nonce":"16de467068dbf5560c0c29b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"86efe6fb92589d8ce5284029c59c3aa5236b16fd28a8bf8e8b53bc5458664154668330e4e1f96d4e3083c75b18","nonce":"16de467068dbf5560c0c29b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"adc8ca28da96c5537f52514438ebcb646c1ec1c2a61c5b86d2f5848c1a5653c38114884d52e313e88828b2b30c","nonce":"16de467068dbf5560c0c29cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"b73ce6ecaa78efe6d56f2fbb1032fed246e1f8196c13cfb2c944615a19ada21baa93e3a17acda59d5b148a60e3","nonce":"16de467068dbf5560c0c29ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"488ca60e840841cb3d3611943e1126d66ba2cbdbae72afd9d8a0b615f8f9e71852c7d39e4cdefd15e35f4ec389","nonce":"16de467068dbf5560c0c29c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"81c810a483296d536352bbfd256c9d30650b6c2f6e276b5ed862726bc8fca4c631bc9f373fe9d206bde4d53bbd","nonce":"16de467068dbf5560c0c29c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"27e41870e9a11812795657c1ef1be8a95ffda433ea03685e265ae24528e42069fdcb6d0a741a15dbe0a8dbbcab","nonce":"16de467068dbf5560c0c29cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"9cb809270531db4b40b1b2d01d410e88e7a4059ab9967be0896f2290ebeb1e67d928823cfa54a56da4c7df7039","nonce":"16de467068dbf5560c0c29ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"458ae6b0098b5197fbebaac6b82f738bf2ff2956c0c25ce77e2a468d86e169cb48bdeb248a39c18b592d80a321","nonce":"16de467068dbf5560c0c29cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"cc2f069dad6c5ff608f4fab9222adbd6caa46f3b27f89ba871772beae433d84ff2df83a709ba542e17324d4d5f","nonce":"16de467068dbf5560c0c29cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"274f50c179b51a4eee4110b16fbf35569580a2c71e6003c870b783e3b2b854805586cb43eebd076ca00d912df3","nonce":"16de467068dbf5560c0c29c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"024c6cf71009d09b5806e77e325bdfb583d4b91ba1a5a3fdee43256af9bf19a87b97bf7ed18e64cddfe0ccdf32","nonce":"16de467068dbf5560c0c29c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"772318bb4a1ef7819f61c2c9baaad7f6cfa8643a8ffed693664011afe3773f041c5befaca870ae267e25a89592","nonce":"16de467068dbf5560c0c29c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"cd91a2b30e9dee50da9795f7e1fca5113632102dd5fe164ae71a60dabff917b0f9b117dd6bc0f489f623c525a5","nonce":"16de467068dbf5560c0c29c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"f2542d654384a992df60c9cf4479042ce6d01761eb01072c7e221898946c9fdb0fe5311fd67b333e479d32611c","nonce":"16de467068dbf5560c0c29c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"5495d9d9305b1eb422b48f77e1fa3fbdd8a7a1fdebd9607a40ef6d02e1ed42046633fad3bf64586b1d868a4dd2","nonce":"16de467068dbf5560c0c29c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"04b99e6663de95bec561728e6940a761be9784575987e9bde497907bb4ccd368823fadb63f17268d4ffb8b61e3","nonce":"16de467068dbf5560c0c29c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"516a80a5f26f4b090f6102ab8efe9d14e685f23ccf1fde419829fdae164d251f22afd6a9bdf37b9a9c10b6f5c5","nonce":"16de467068dbf5560c0c29c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"4d921afdd96a4146a9f412ee255a5c1551d9176579a28ab9371ef7837effabbb0ebf186075caa8152302ac3363","nonce":"16de467068dbf5560c0c29db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"a02f057515e2adcdddc55a820112d7e61f95a48026e7f5ae03515e2fe9dd4dd9e1a7df089151e9ee4c449da375","nonce":"16de467068dbf5560c0c29da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"453b66df47ebf6b271684e5c9eb1219ff2a2fc71d8d2b8ac3727c8e77db1f0b692306f105f5980b847d19b6f6a","nonce":"16de467068dbf5560c0c29d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"212fde3b5221f736a72c0ce88823d9dae3a006561685c4245569e2f98f892949c7697690ba11c412c4a9a5729b","nonce":"16de467068dbf5560c0c29d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"b7402deb44afca71271bd5838dbde91bdd10199d52ebff861c7b75e6b41bdfe96d3dcbdd29eb31240530541518","nonce":"16de467068dbf5560c0c29df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"80ecdbd233c04eba2776f60f527a2e63db5d320d3169b83752c45e4519d3015078f8a64f6194ddc5aea5794663","nonce":"16de467068dbf5560c0c29de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"2e75444d2f860dfbf35613bca0df96f12ee3d377c66fe5b98de830f31f97a2a574e88b17ba69b39085a642ee9f","nonce":"16de467068dbf5560c0c29dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"e9f1c7b66cda5c7c31c7e81846b95bbf010d5a3810d575adce9465add0b1c8808de9740adea7b8b5e8292a7934","nonce":"16de467068dbf5560c0c29dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"399429f209e21d6526f1e89d8466bb1cf5de102c461436a3e37ad6921150a66b03fed660164573e6a526be5698","nonce":"16de467068dbf5560c0c29d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"1ec78e71935c2ef22e47122cdf28086d2f1b47088f272ffa68f593c3dcc1a64f8353c972b8960efbb5c35e8b7f","nonce":"16de467068dbf5560c0c29d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"5efaf0888d59cf216d08d58ed5061e783b649ef61eb240958bf496a08ce52b1c88d0a97e180a9a3ecff2a55f83","nonce":"16de467068dbf5560c0c29d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"d9712ad23f3359683e307ffcdcd176aef3257307b4518ef633a188552f39a0ffc45a43f11467468c78e6d009bd","nonce":"16de467068dbf5560c0c29d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"8f96f2553c24ce20868aba4c7653367e25ec70bfdca6b198c61385ff662eb316e6f360198292519b6b38866926","nonce":"16de467068dbf5560c0c29d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"0c904bb5125a2b5efd4de1131de0ed9c08899eb96f8081e98956b1786e73fa916cf500258a6b73918849d4f9e7","nonce":"16de467068dbf5560c0c29d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"6140bca7966091c28520c1de310e6225f9d3767eac60ed91352663f3a9ad213e497b6b4398454d7660c856783f","nonce":"16de467068dbf5560c0c29d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"9ec0e10a622261ecf4add8809ff873218288fab1de08ccee94dd7d7b38d1ccfbca6c27bf2949417239c7e3efb3","nonce":"16de467068dbf5560c0c29d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"1190127dea97e1b21d8f3454522549b454a573ef0482203c05530f12d458f86bcaf72d4d885ba66ce8250f182c","nonce":"16de467068dbf5560c0c29eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"46af8f186ad8fe2aca94a5dc8f7f56853d6f231ff8a18a482a56fdebfd635e33aec4b08f9abfdc7043ad93071d","nonce":"16de467068dbf5560c0c29ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"b94257463ff0d3b2f1fcc69ceb4ff0ec8c1eb2e901974e654e916d354b0e9a8de563c73b65b24a1aa64a73b135","nonce":"16de467068dbf5560c0c29e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"39618d4b0a47671d56e2737b2fefa5ecf7ff85558b8e1605f4979ebed1ec5c34ded506265957cba9043ae1bb5a","nonce":"16de467068dbf5560c0c29e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"b58921b3ffeb9d8c76ae10eea4284e4ac1688929d8b9850d00476b6b12c556b6bba70156d13d1aa67d7155d911","nonce":"16de467068dbf5560c0c29ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"8b07add1f38aab6cdd561d32ad1e071378922e7a28983733965a31f6428bb3c91dba8b92105f867422b845a61a","nonce":"16de467068dbf5560c0c29ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"96c0903d7d3a99e727319276419412bf2ce6fb2a1f963549ee726bb73b272f9057e64bf7aeb0365c3f5c3a2286","nonce":"16de467068dbf5560c0c29ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"2c535fea4893495dc5883eb8878ad8a7fe367a3a91e7ce993fd1484f673853c809fa8becd745c569e3523e4b50","nonce":"16de467068dbf5560c0c29ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"e69a25e54232ba64dae85ad6aa59a5f26ec58c7c5eefa72df784223fb573d40a71cd8bd64512002a79df5bcbfb","nonce":"16de467068dbf5560c0c29e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"5374bb7b74110bc29aff44046551a8bf102937ab62365de036b9a8b70e62bae20f70b0ca35d45f07b6259f6da5","nonce":"16de467068dbf5560c0c29e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"0867b01adf7df46f820694a00359a776feae7ad48f98132947087337365ebc3d814b1c30f28fdef2ec02e7ee37","nonce":"16de467068dbf5560c0c29e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"30503fee2358febaf767d317d914f5859339e925fac86c573977a1030eab5a8ccefdbf9b0f598c4b3f4b87aa1c","nonce":"16de467068dbf5560c0c29e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"7d70754b183c1395804b26b46d27227e6d0587fd2a1104ee7aec1db7826bae8d37f44d5e910bdd50600af2d4a8","nonce":"16de467068dbf5560c0c29e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"b58c051488891539f11e33c6510fb8346df13ae8deb3b48d79cbe7a622c7406fe62369b01bbe829cdc65f166fb","nonce":"16de467068dbf5560c0c29e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"33392316c1d3f8a96e2abe680721f38807772983345575f0b459070a3dc3860e292c95f0d60e02116696c1bba9","nonce":"16de467068dbf5560c0c29e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"dbba2484effeb9f39a7f2c30f02dcff098beb0ae01446502b8893dbac643ad18e49a21a9ceceeaecdfbef49142","nonce":"16de467068dbf5560c0c29e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"7e167bf49c0e87e0d79d0518be78e618a842068f19ea0e1341d2a223b95aa0d46522bb35646d4e45bba6f144fd","nonce":"16de467068dbf5560c0c29fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"8f3873ae8aab16756ebb20fc5ee66700e119e38d7bdebb7aa4188b1440a3700eac3f515ab607b622e0d0f79fe9","nonce":"16de467068dbf5560c0c29fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"c3cfbc5e9a24a182439bf0314cc8b7c546da7db60d1c89265bf4833046fdddf15f7497b6dfc5f85fff2630cdd1","nonce":"16de467068dbf5560c0c29f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"a06638784e61a6a87854ecde4c63b1add1ca3e418074523f0c87f70f919fd4317e7d943eb3095149e79727982e","nonce":"16de467068dbf5560c0c29f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"efe7425482720bb108ea44e8565da443b6e0f0b64640166879b7c564e25e131ca6f718a40e8a801ffd419e0c41","nonce":"16de467068dbf5560c0c29ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"c46a8cde46081e44997aa3f78430cd973feede589a3b8b9ab4032d4655c4bef8042aa36ca08f68b4f7188bb52c","nonce":"16de467068dbf5560c0c29fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"61284d5f660e8493d2e6db75adfcad4e6708fd5dca0908fb4c9f9ec6983b8b69787d0fb8822e1f36f0aa90c47b","nonce":"16de467068dbf5560c0c29fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"390aa9c87b52cb9eee9a39946a0689294dc8bc36f5cb77ffbbe6ad457144996ecda5c4f23bceba2e86b99e6727","nonce":"16de467068dbf5560c0c29fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"554e039b3f3a44bdf1aee91c527ff6b8cb61b288d6975c271f0f6cec2a252abe211f490ef5fa54c0cdc88edf80","nonce":"16de467068dbf5560c0c29f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"c7296a1bb63efe74a466a3f542879a164aa447d7bb22e8a06cf708c9a9f6790282eb2fa1f28ff4e66cbb7db527","nonce":"16de467068dbf5560c0c29f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"bf889e60be457c4b37479fda56a84140cc48dea45d2d22a7d857d56661d8fe1079764455c98fe6ea1344208127","nonce":"16de467068dbf5560c0c29f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"d95954f26fa094215d658dc9ec37bc5dd65e13057bd9c069be30775402d73b55ce34e33fb24a5bfaffc4c43bcf","nonce":"16de467068dbf5560c0c29f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"96dce3c0c82e3caf4d43f3bfb66c1bcc0cde7f43ddeebe99e5870f2fe1834bfcc26855f3fdbc1aae7647eae1e9","nonce":"16de467068dbf5560c0c29f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"f5ba5145c5e8c5dc88d9859d933b423ff0dcb7bbc3a3b592bb890dcf75cf73055a5e7441194f3a4b3ffd2a84e7","nonce":"16de467068dbf5560c0c29f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"f3cdd2e074540420a818ebd37c3f978244e1423efd92f8e8dbf7eff7769a9fa0431e6538baef34f55f9898e5bb","nonce":"16de467068dbf5560c0c29f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"b88db5d66c77a6e8caca5ab43e903d8a73be2b8cec889ddbbca7c605d9b33340dae47d0dd1360db8850f598f9f","nonce":"16de467068dbf5560c0c29f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"f54080fc4fd660169febeeb50e5557f412b2ba2d084becac2cdeceecf262630e3e02e6f06aba9d04216e9d4c3a","nonce":"16de467068dbf5560c0c280b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"13d3ca2708596af36f9d83f08957d53603d7ea8f77c7fb29ac287e5f34900b2e"},{"exporter_context":"00","L":32,"exported_value":"52dc47db68f44adc4c65d16b704a0a3b6294b63186bc3390903ed8e09aae2059"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"f33267be2971d68f05bb299498b3bf8753b4f9f38b4d57808caafc3e32c6ce85"}]},{"mode":1,"kem_id":16,"kdf_id":3,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"76005b73e0b0ba475d951f59336172011d958a3dce3281ce664e145637d582cb","ikmE":"ed7102804ecbc4b341c38798df8abab74a10315b6e121b0be17b7f1284d10b87","skRm":"a7f9b4af9b3f0b4b4c2fc9f53bdcaf993774752a47c1399faa930b2a399ec878","skEm":"443fa787757dcfbe3bab663722bc6e2be5cd807379c8196808bfe55296fd99f5","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"04172f1359e661ffc33c610d480d6dc34e9462ca2f5794ed74e58691240fd5fef1848cb9c649ac17e2a7bc9a1333736a859089162132fefe0463a5f8157774a9ba","pkEm":"04a1e571da552292859a5fceb9f2389a5a1e4a25acdbd23605532645eba3026a025b278254cb0cccf311c1a30a7ddf3fe64a963288326ed5e8fe9979fe81068728","enc":"04a1e571da552292859a5fceb9f2389a5a1e4a25acdbd23605532645eba3026a025b278254cb0cccf311c1a30a7ddf3fe64a963288326ed5e8fe9979fe81068728","shared_secret":"89ba3cfeab0c167317ddab5d0dfae577d119d292dda323dcc56967f630331408","key_schedule_context":"01713f73042575cebfd132f0cc4338523f8eae95c80a749f7cf3eb9436ff1c612ca62c37df27ca46d2cc162445a92c5f5fdc57bcde129ca7b1f284b0c12297c037ca221d77e229a9d11b654de7942d685069c633b2362ce3b3d8ea4891c9a2a87a4eb7cdb289ba5e2ecbf8cd2c8498bb4a383dc021454d70d46fcbbad1252ef4f9","secret":"844bccdfc2f658d6ad8d7fde0cbccc80d4717c776ffcf099c0a5c8274edd3e5b64380ba0cf7cc2d1f069481af490847f2cf16cc5b6b745e1083adf5698dee8b5","key":"b5b03f9572b39518ac955c9c447f64ac","base_nonce":"55e771c657aaa0c3d1ca31c9","exporter_secret":"705dff024cc41ca90021af1a086ac050614884fcfb59ecfc71556d6d84453912d3e4bca6b4b3a6e433db01ea39968303754ae0aac95e96a6d9ceb44d6cf7676e","encryptions":[{"aad":"436f756e742d30","ciphertext":"57aee54fcdc5600b2499c65a4e846958b09fd33e7b11a2f6411e5ec7679237495f66711395bc75d737ccbf138c","nonce":"55e771c657aaa0c3d1ca31c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"78c44cc4824cc7976911f83ffa2e28464a61f4ee058dce4b131f0b0d58944b439c535ab81b3ed7bfd518baddb7","nonce":"55e771c657aaa0c3d1ca31c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"e45f01a429fe17107f4276cfb17375602a8407ddd239a8b33b3a072871b6d8fa7cb12e1701669df8004e9bcd34","nonce":"55e771c657aaa0c3d1ca31cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"5984b2b7efb7748885048b4e91a59c4466dc5847a17d7a522888215cca0daba5099175747908644bfb4648a9be","nonce":"55e771c657aaa0c3d1ca31ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"e9559781b27e48665044c6c6967671cf4e48386af6b65c3024997e00d8b12233eab7dd4ec0f43673500c849839","nonce":"55e771c657aaa0c3d1ca31cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"95cd9bec9fa1dacdf5cf8bef9f393ecf528194bdf3cc288ac6dc412ff727df5659eb72b72d3fa451f023a57d7b","nonce":"55e771c657aaa0c3d1ca31cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"fc8764de1c2dd3450df249542b30caec560fc4f7b09a1e5fb89b02aed4d87d39f40cd3f3f4ff5710803b3b45d1","nonce":"55e771c657aaa0c3d1ca31cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"93699758e6c43fd444098aaf43efd09730a0560975d18fc28c03e25b86f98a05eefe4ca1a3689eda3388fd238e","nonce":"55e771c657aaa0c3d1ca31ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"48daa284e2e63895ddec295a7176a0cdad7771a17674ed9a8483b3abdbf32fdce3aae964aa2872773d0175fec5","nonce":"55e771c657aaa0c3d1ca31c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"9627be332b4b0c3e636dd068256919ffe2040d9324bd6248e1e95f018a0e7409c2201da18db853310e4a26f146","nonce":"55e771c657aaa0c3d1ca31c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"1a8d666aec8dc541954a6089e645de458841029b41972498d6782b6a5bbe081470c6ceeb70cfa701ca1b745557","nonce":"55e771c657aaa0c3d1ca31c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"6dcd3c333b616fe30e1a76fae7e1ee42f8df0e6e94a6e5b80a6ca73b733303595a47fff5a4f6ef8a3322475714","nonce":"55e771c657aaa0c3d1ca31c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"070bab5f32017dac334fe33cfc7ba7e64a4f4e0c4dff9b68be31a81151787fb520f22a72bf5fb7fb6cc05e872b","nonce":"55e771c657aaa0c3d1ca31c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"4336ab3eb314fdfdb176f2c9c532ace8d74bef5e8f712debd87aefb9653f6a7da62271d8e2ee60a9f5941c245d","nonce":"55e771c657aaa0c3d1ca31c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"0d2253d84df914c593ed6ed57ccf1213a06ba967be555713185cd7cfec073f974b7613a4af811f92ba620b2e3d","nonce":"55e771c657aaa0c3d1ca31c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"10c738d2e92c32f6a11981e059c6d43ad7b6d743e5ac4026840df809c001fb8724831c9ff587620029cec91344","nonce":"55e771c657aaa0c3d1ca31c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"c1982b2098ef5ffc03e2527ca35a1d8d5cd1a97bfad8ef3b74706a742f7af5f936bf3089de810be0d0c57d78ad","nonce":"55e771c657aaa0c3d1ca31d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"98dd13e1c9a5dcaed2fa2cd739e44063081a9ce53129675c9e76ca6b0594ba73c5ed7287bbde7e6733fdb9bfa5","nonce":"55e771c657aaa0c3d1ca31d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"bbdb14e92d7aef7461ef3b35c62ab4a1d724d1b37e0fab13d1ffb15e18aee72f768a9f2f272b2c61f6dded7baf","nonce":"55e771c657aaa0c3d1ca31db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"863280d37cea1393ddcc89acee356448373e45b976955eca8ec43995a49c682f1ea1737df57c136f96483d6dc9","nonce":"55e771c657aaa0c3d1ca31da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"f5f6531f456d73518bc496ced0abcd82ab41f17851d43577f4a7b0db9d459b018f894e4b784cece6e287e32b7e","nonce":"55e771c657aaa0c3d1ca31dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"39177f4e2ff64b60e214ef8103d1f20417549ddfc6712b3911b148a049daeea903f0ec2fcab430cc25974e0a8f","nonce":"55e771c657aaa0c3d1ca31dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"d050728f6b6b7dee9ce4f40e75e20d0b11ecc418cc7e8407e5ff423f43cde8ade8849e727907b81e5712b440f2","nonce":"55e771c657aaa0c3d1ca31df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"801cbca6288bd42cfaff4053c28a9fa23d265a81ef3d85daa1d710e6c106a85318ca8240166d3cdb1942ef4ef1","nonce":"55e771c657aaa0c3d1ca31de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"615b6acfcba4e8ce8e88a0021075a655cd31d4eecb9e27f726f87b790e8448532c3d58935ae038a786dd7bb354","nonce":"55e771c657aaa0c3d1ca31d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"c012f64cbc91e4807f481de3ead3ea9ef4481975d56379c4597dd876aec4a187d55aa3bfc81321cd9758dcb2d0","nonce":"55e771c657aaa0c3d1ca31d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"f6fd466d741a9a5870d4d80b501e98e56dd2f29f19833a4c9d2272cfceca83085ae1bd78a1f7a342775cc84640","nonce":"55e771c657aaa0c3d1ca31d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"074a1f53631fec5596e30c0ab742468bfb105422c5d3a4a86cb198d2e49e90b23b403ad15d633cf3f4bc7a51c9","nonce":"55e771c657aaa0c3d1ca31d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"2d12cd8098cdc28fc118dd83d7f2bfd098cf59c836aef2cf4024625486dd93337cf2ce67c22a27a134244c22f6","nonce":"55e771c657aaa0c3d1ca31d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"b067e843ebe777452b77f8c175139514fa282d1d5179bad80b57c33684e5c1347451ef13bbb631c66b13180f24","nonce":"55e771c657aaa0c3d1ca31d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"2756518909996e15da7ca3058d4d44ee5ae3b79529f3de568f3f755f5903057ec50e0a5c46394bf4ba6eb580de","nonce":"55e771c657aaa0c3d1ca31d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"05f257855abf19d3c2da6dae9eae613a3523f81d81a041fcec672d2063af25214ef2ba5a487e8fde7c31462261","nonce":"55e771c657aaa0c3d1ca31d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"2e150fc572773f8e1084d506adcb91e1124bfd5731820586ff4f3584be512bf5b26acf52177e30701cb2915538","nonce":"55e771c657aaa0c3d1ca31e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"38cdab1b59f0e62cb920b7ec50293664532a76c99ece251eb04d8a272070b8199f26e532c75518f302507cd328","nonce":"55e771c657aaa0c3d1ca31e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"315d4c61b5fbc53134e945c62c9ff3330d624d2ee14b6760035530d2cd13ec7f188dac0056a750da88699cda99","nonce":"55e771c657aaa0c3d1ca31eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"eda0634098b8fcc98cfce3c3637322c0a62d680fa75ce02cc3ae6cc736146b4ac7b08d939f58c9527b4b0e16f9","nonce":"55e771c657aaa0c3d1ca31ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"f9426ae0b2c91168a6cac0d85b95b7e68f8213d28e5fdb67bd785a2336979504babee443827183e81ebf519340","nonce":"55e771c657aaa0c3d1ca31ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"c6fa7a367c37773eb13c902b3294ea813050a46535df09ba7f1c7f8553d92455658e2075d48327a26b79f137ff","nonce":"55e771c657aaa0c3d1ca31ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"efd14d6e295ed93e32c1ffe2c47f9c91df424169f8e3d9f532b5e490fad58f327bb7093c971631973c51a2f02f","nonce":"55e771c657aaa0c3d1ca31ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"31169c662b0e1471195cd9196a91a940d09f85269c7d6ce7e7a778e475350a69f263a06ef14e4a7ad25458045c","nonce":"55e771c657aaa0c3d1ca31ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"3f56c69a1b74ca090f5cfe94071169193f2522614bd192ed03d867661c3bf26821ce29d1c98224a1e8d1ff3876","nonce":"55e771c657aaa0c3d1ca31e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"9db979d8b09662980da95d52d47d59091a890e11b807104f982d51334af509cd28cf88260743bfd1aaedd0f173","nonce":"55e771c657aaa0c3d1ca31e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"4505abcb0078a1d5f8bd846ddc0cc66f0fe8e10251be1d5f8d6b32eac53118c950e9865d5b0eb8ec09b13a6f2e","nonce":"55e771c657aaa0c3d1ca31e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"f600055d2e5c2a7a97fa96c1011af3e66e59548b8ce174ef73a00eefe2d7f3ec66d075b138cf1807ee847ef123","nonce":"55e771c657aaa0c3d1ca31e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"bb67698070f9f77d4c746eda525ef8ff685aaacb8b801c9acca191e7ba97b2ae61306f88f86d9a00d8cc2a7537","nonce":"55e771c657aaa0c3d1ca31e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"cc293fb5dcb989311cd9b5cfd25308ef9f09f5deb23f4f7a25bf00b5050dafdd5d7e975e8fed6899bc267e37dd","nonce":"55e771c657aaa0c3d1ca31e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"af90864e650bf7a735a2dd8f28894901c9acc932e06b691dd82d6ece6586dd222f37c22d49367a75dc965793bf","nonce":"55e771c657aaa0c3d1ca31e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"989c1e8d1027dc616b1d658fc9a968afea37279edbb1c5fbd1e3b7a74fd752fdc7dad2e2c58408b7081d1c926b","nonce":"55e771c657aaa0c3d1ca31e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"ba7ebaa548b02a85169117ff7da0dfa2799c71fb638a3980853e0bb4969143c1ccf02f392be80d42b2ecf1990f","nonce":"55e771c657aaa0c3d1ca31f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"9f7c3d4de99544be1717ae531a8481705b79d07e34bd413a6ae9b5e8b56581f3a032029c9140dbbfc500428ad2","nonce":"55e771c657aaa0c3d1ca31f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"36f624566de1e1b2d792726c77b477b34e12f9c118dfade4eb3c46916e46708b7f6cf0c2d34a5f3c76032d9571","nonce":"55e771c657aaa0c3d1ca31fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"0fbcc8b4790362c0a8dd9b6b6320ad85b3b1b30c09f334b15ea07681c6002c323b67af50d342db60acc2715ec4","nonce":"55e771c657aaa0c3d1ca31fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"b148821fe6c2cab9b4533b68af009edaf1db1586566542e08f01eacf9da649587a433bab12f7a149e3d1ffcb63","nonce":"55e771c657aaa0c3d1ca31fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"8516dc5152a159f9038beedc62ad8158b8880ca8ea426ce5da0db5c5cd435abf1fd523219e0c779ca29f445891","nonce":"55e771c657aaa0c3d1ca31fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"ba800cfc2decb77dd41b8e0655c0fd511723a5e08b0eac9b9d05f02df07e7be4f5d62b781b56d427a9d9827f42","nonce":"55e771c657aaa0c3d1ca31ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"01a0a888ab5a606b0d90058be880a5bac53187317188de452d3f2e54bb4aeb87e464a1746fed4bf8909d3e23f4","nonce":"55e771c657aaa0c3d1ca31fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"1efd692fb9e8fb6be60369849677ef40fe0ab9dd870eef0d91c7c63839633c0e77d814f3dd51da584d90b208a4","nonce":"55e771c657aaa0c3d1ca31f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"740a6a76a292c628978b8a59d2f46f9ace5812be1730c1fc4ae1b1f83dc67394b3e09b9c05a43247fdb93ed212","nonce":"55e771c657aaa0c3d1ca31f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"9da12559699dc8f1348a081c16d317f08e1355e35cf38da3488824e9c166257e3242627ff2308d38576b59c4fb","nonce":"55e771c657aaa0c3d1ca31f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"f862eae0bf0936bcc92a317d6e8513dd1bc79e796939c19d83d8776ac47a163b66510a2bf88c2330a457b89385","nonce":"55e771c657aaa0c3d1ca31f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"e6c558566ada1a10b640faa016ad2b99e148a53d85ed090a33a09e802369c258d405a92a5be86939e2c9633571","nonce":"55e771c657aaa0c3d1ca31f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"96e612511925c96aa87e24ebb25c531917f18b105e8bfda3b0124676b5446651c5427920ea164f07b510210f76","nonce":"55e771c657aaa0c3d1ca31f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"6a90cbd1e4b3f3b7b9a6790b5208366e9ebde3dbbb8a65c77cc9213c89783032eeadb3b860eb957b169c613b52","nonce":"55e771c657aaa0c3d1ca31f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"cd7b51b9455dccc66933fe2f8f06f800e1461bc4d45c59d67054757cd83a126221c30071472ca3cec2d620bda8","nonce":"55e771c657aaa0c3d1ca31f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"4428e2f8be2b3d39ab14146e4373bfa464026ae68316e95d0ccff087136eeeaef80aa7a36dda078fe941185216","nonce":"55e771c657aaa0c3d1ca3189","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"73c3b165bb671dd84b19d7076d8278943f1347875a23f12cfeae9a992f6777853b93bc0a4677893cd6536e0577","nonce":"55e771c657aaa0c3d1ca3188","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"b746f7de593160c92aa660a26f3894715484a1dbfe42cbcc4255e351404a6cfdb02047ca88a47952d0b39ce3d3","nonce":"55e771c657aaa0c3d1ca318b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"1963185627774b15d398512a4a4b52c3d95f7d208e000ce4b3b16a9c062db062bca80d380b13444bac2d7eab53","nonce":"55e771c657aaa0c3d1ca318a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"9295c681c89cc39962b5c2c3fe903f660744b7205465c6da01f3ce27625e790b9baf2252994695f7efe078cc7f","nonce":"55e771c657aaa0c3d1ca318d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"df97a4f59c0ef048b6a7c4435079f4770860762fcd3fbedb77040280924d8903bfe31d15694addd0329a3c3424","nonce":"55e771c657aaa0c3d1ca318c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"8d4ad03f8bf098e9e3a4f4224289d7fdeaa77b94bd408848bdd4d5b69fcbb6f574ce5773660fdb23c8689c85f8","nonce":"55e771c657aaa0c3d1ca318f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"8ce2257319bf3645990c66f142103815045e0732923ce022ff3284f573a7c972faf6b4fcba8e1b8c442f48d857","nonce":"55e771c657aaa0c3d1ca318e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"c3e5245a068e2645a8da963c8240a6f7913c9fae977c1e2fe6bdd5a051a946ba71841dcd90a52f041b090ce6f8","nonce":"55e771c657aaa0c3d1ca3181","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"78cf1b477a9f67749af25d72cb2d2b9d34711f7e7a49b91be8fab6d051be891233e8c719769ec94d02cc4d6c9f","nonce":"55e771c657aaa0c3d1ca3180","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"83d506c97da255ed49cfc3037b746601ee5a3304af83a5b05f8570438c3ab370ccd18167225e0de2cb87e8d7d8","nonce":"55e771c657aaa0c3d1ca3183","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"ead22ebc31b84422c74d013701c7f2d89112321ab6e84ee0b3dcff37cab961c7ecb47a0bbc33130eaeabeffeda","nonce":"55e771c657aaa0c3d1ca3182","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"59112b21b49ec4881a4d1437651037f4870d79b14b2d58021fc7ce0fa814298da855e2f95e54e5b83a762a7a37","nonce":"55e771c657aaa0c3d1ca3185","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"e8628e44a160dc6b6801793ce3b68587e0373dc40600a3a3bb60545f10cbbaa58418fc7d0a8d2a343d189d878b","nonce":"55e771c657aaa0c3d1ca3184","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"1bc0a30c213e49f078207116e545d9ab89ad77305957a12cbf1636932c7e25708b9cdacc3d297a316118feb104","nonce":"55e771c657aaa0c3d1ca3187","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"cd20277fb847d1226646eba05f36a5fb3c69571a028c208a6350778e0297597e95ddd485a92310cfccf950b223","nonce":"55e771c657aaa0c3d1ca3186","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"9837073aab4fbe6be22b68b12d3ca6a8c5c41bb1485ce4a4cb85f674853b5f1853feaa997fd0a1b61f75731bcd","nonce":"55e771c657aaa0c3d1ca3199","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"04c3f2e4e5ef73a0cceb8e3ce32bec09cc256be6be9fe462121653bbba5ad6691a077ccea11131529fcd2a7159","nonce":"55e771c657aaa0c3d1ca3198","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"8ab90edce474a922855bc788ce8f373f75e7ac08ab262c6d8121646d87329b5d83536af3721237a3322afbd986","nonce":"55e771c657aaa0c3d1ca319b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"148e32077976676316b18218a3be5cdd0d15ef6bfba75e59a1785755d5a02cd1f4b77611c024013d97e2ebcc1e","nonce":"55e771c657aaa0c3d1ca319a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"9b0f13f29d3467cb7f2cdbeaf122bc85fdf1bbbca0fa3976c79490f86b6893a4132a4a05f82659833cfa7097c4","nonce":"55e771c657aaa0c3d1ca319d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"465d2679f473f07a1252e14ec54f1ccd6201a9385edea95edca2eb33ddae37d4fd642e52400cc04c4d943ec35c","nonce":"55e771c657aaa0c3d1ca319c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"17032b2384aa4865c8fd9b2f93de6b4f08ee5ceaef9ef6bd73f1ae7a41f61db4bf24e21ba6a7b5d627c2dd3ba9","nonce":"55e771c657aaa0c3d1ca319f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"f06efff39e867e1d6c660d844aacc2e057e3a1c06a8104116e4f729ee13a1c575a0fcb4b6048c20c58732013bb","nonce":"55e771c657aaa0c3d1ca319e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"7273f6473e2da3ef344b654b0b28f33995284e5a8cba7c995ff79683613430d30e8d8c9e23c8f94ec9d8a054d3","nonce":"55e771c657aaa0c3d1ca3191","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"52228e0db4538122c9bfc007b876322c99f04f920fe9bf5c98e81ec2c595e867c6947f100028894fcabf3658b6","nonce":"55e771c657aaa0c3d1ca3190","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"f5116a9ff18eb8ea82d9808e87401488d4d123c43f109e7f6f9fbd72a1b19cf2eb3514e3d61896dba37a4a50f9","nonce":"55e771c657aaa0c3d1ca3193","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"08335f0e1017c8c1dbf374e7d45e8bfcb673716b4295246c565f1093922aa0ca1749d51d95ca674ae204c3eb5d","nonce":"55e771c657aaa0c3d1ca3192","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"871e3e2d3117b5af073d7bd5c3f001f8bddf8d46f099f0313f2d1deb0198a7275b1a529c3f04809937bdb81ae9","nonce":"55e771c657aaa0c3d1ca3195","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"1b35673804ca1971ddf12a0aba44281e23a736809e4461c91e60e9dd8d3a372a1c9ca0e03f088c22e15ebae40b","nonce":"55e771c657aaa0c3d1ca3194","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"b402804224dd5a1b93b59fbeb51945490e1346f545de37f53cade143709de98ec20ac429552143b0f8210e79b8","nonce":"55e771c657aaa0c3d1ca3197","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"e09ef28c678efd93f14a3448ef8ea8fd5d6ad558d737317ba9399bcbaeea81b54a4ca2cb1276828efa3ea8ab4c","nonce":"55e771c657aaa0c3d1ca3196","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"665a0faf7528982318b86d2697d274e7f09f5475f9e9347eabe5e6c890b04d62775f00c9ac0fcfe320bd366a85","nonce":"55e771c657aaa0c3d1ca31a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"a7994d6c2bffec1cf4c19fb10fd40698e741ce7ee591571ba834e0308d31d209d8798de86ae984ac473d1a219a","nonce":"55e771c657aaa0c3d1ca31a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"c671f954753799646396400c6da47a61f22fe761d0864a43fd96b1e780f1bdec60cdb599ec4b253e132205806a","nonce":"55e771c657aaa0c3d1ca31ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"8eeb52af124b3b71e38725dce504680a43f8c0bdc346d148dd842d8a1a2c420de357b5426c544cf5535d0bd2fd","nonce":"55e771c657aaa0c3d1ca31aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"eb4870843ba74b25dc353d628ba9e156e4e73833abd08874849bf08d7e3e48988c7b6265eb2f72e6aac8b401bc","nonce":"55e771c657aaa0c3d1ca31ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"1539f863538b3cbe2b397e186a51eab76774aed237baeaab7c6a0ffcb921224aeb8b1f49fb4336e8d2737e3c00","nonce":"55e771c657aaa0c3d1ca31ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"76c32db59658a62839421355699208dfefe4cbd169e6f0ff0d28fd9815c9f045c8c26d16302d8f6c6685f985d6","nonce":"55e771c657aaa0c3d1ca31af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"3a0aa7b3e981fff35ba060c086cb77ad3f815f3d6c6c602597c5a04b4c1d681dc3948d733a33c0ad3b20c5a99b","nonce":"55e771c657aaa0c3d1ca31ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"b8fb12e6682fccee6408114f058e7e29ade73e23c2aed5bb473accef6a8a4870aad3fcd2bf8de49399d3fcc154","nonce":"55e771c657aaa0c3d1ca31a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"746825cb50d2db1e5e9fe4ae6b02c369b92f4d40ff9f311faba85c625015f25d5450f928fad2ce520c6e9d5139","nonce":"55e771c657aaa0c3d1ca31a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"e0f138774e0cd6c578d0fcd9edf1b55b448e79a0acb74cdcf88d3deb26ec61ca8cf09f1572d6cff09453931737","nonce":"55e771c657aaa0c3d1ca31a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"587193e5cb636b110705a6de70495141f8cc5d0f98ef71971c059883c15e9db7659d06a78c8d3c02ce6ae6d05a","nonce":"55e771c657aaa0c3d1ca31a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"d4fe408fa8dbb323ff49b5b16e051e2628a7cdfd29c61aa1444832df79fb270badf73dba2ceb8f948899f16eca","nonce":"55e771c657aaa0c3d1ca31a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"0e49ee30d6d3db128daf2fed9b35e20da38acd52247d67d9a08f6bafdf43bad02af10a6209ab08fa803c70c1ec","nonce":"55e771c657aaa0c3d1ca31a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"09c9cfa64491cac746c3b8c45aa8add70783c51ba8ce0374f40ddcb4638d13898897fbff4bd9de7eeb20a7e08b","nonce":"55e771c657aaa0c3d1ca31a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"6560da9cf9fecc24b28a9022d2d4aab2a611e3690d15d68b469ae3ef12478be1842cd9d4281fc817c56eaeafad","nonce":"55e771c657aaa0c3d1ca31a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"f27923ea5cfc1bf807858d9105c6d535a14a7cd00d14eca1e5131ec2ff9b37fd264376ad800f984eb6affb3dc8","nonce":"55e771c657aaa0c3d1ca31b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"26d59f2ba23db06de333c11c553a9a44f7c82f2f2b18d6c29df1e8e56556e40c56bf4c27fbf725b1a19966f14e","nonce":"55e771c657aaa0c3d1ca31b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"9303421a4ad527e3bbe78a6846e794a51c7c93cbf85a300123a7189fb19a7998f5b56ec3be4fd8ed1cf255c101","nonce":"55e771c657aaa0c3d1ca31bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"780eae751eb058b1445bfd82687b1238237a367e02e76b343bae6cff5f3f506512d0a476600cebf586503bb894","nonce":"55e771c657aaa0c3d1ca31ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"6b5ba0ac830d8566ea5c647af78380e5f4102239c0a5eabb844e3c8ac82dc37676bb7fc9d34d74679dbd2c7311","nonce":"55e771c657aaa0c3d1ca31bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"23bc817f74cca2def6c7b83278b2eaa37912bbbbf88598372e077eecc160ccb02d1e6415cb7ec6b991923e6a5b","nonce":"55e771c657aaa0c3d1ca31bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"358c38cb77a4cc4421d27057e8f50e63bac6e12e909ea7380a6ab0b9cf0dc1092a0a682265ab721f8749d3b330","nonce":"55e771c657aaa0c3d1ca31bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"14a913712ac6ad541e32ba1365399002c8640b8543b032efb6ba7f3eb2fdc063a33ba735ad6f4c23a468fb6ecf","nonce":"55e771c657aaa0c3d1ca31be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"96366137ee1dec05db91e99fd4882f2b34da0dce73490c7d687a56a9646d0c075fc8003229fc93a4fe84b146c8","nonce":"55e771c657aaa0c3d1ca31b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"da3500565ab6229ae6d75fde35cef3d687138c0cd4cbecdd40945a634762877e7ecc4976d41e0ca7e0d16b23f4","nonce":"55e771c657aaa0c3d1ca31b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"b54edd048d667a249b9bd2ead6ed8f2b21d2805ead95e792251eecd8716f50d4aad2b3814ede2ac1f43a8a4881","nonce":"55e771c657aaa0c3d1ca31b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"f1c89293f117f37de451989aa6a1d10ca4b0fb0bb18e2ea923c43c67951a7cdb2192f85a9a5ecd512ca091d329","nonce":"55e771c657aaa0c3d1ca31b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"c3986d24931877ff323c22d30b5f7d42ee2c605c45ed3648762336b1c6f9e953810a80cc600f5f0d73f0f769c6","nonce":"55e771c657aaa0c3d1ca31b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"48d5b294bfe0ad1a5f0870c6b0c91a79eef373839ec16d1ea0d14dc1da8ad753da9f2b15a82609952cc5cf98ed","nonce":"55e771c657aaa0c3d1ca31b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"7e117c06b54bd8c6f33be7b97465429a86095ac6b8770276bd32f557477bc868af00b1d18ee56c8cb2cfd146cb","nonce":"55e771c657aaa0c3d1ca31b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"26c865599b363e1b581abceb8098072e3c38d75463b9f40d6eef69cefc051ae00e4b7cc671f631dd73a06a5e04","nonce":"55e771c657aaa0c3d1ca31b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"03d334f57f0904a111799681a9b568d2f122d1047a4d84d276b65824573e6f50c94e1211b1c3fe517a8ec8770e","nonce":"55e771c657aaa0c3d1ca3149","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"4f112be3764b423c2c58e5517b8583e0c7dc80e005e0b1809d35a1d1a7bc2a7dab8937adb9bced83eb11708ddd","nonce":"55e771c657aaa0c3d1ca3148","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"29978766ce2f4f72ad73e01774bc510e27f1b59acd523e8932c755902eb5d473ab8f8b9f463fe2abd1c6496df6","nonce":"55e771c657aaa0c3d1ca314b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"52f9f16eb30a6f8c25cba2759af20be3b83f499db792d1b8c7a4c9b78886d7211382a5f5bccd86919d18e92cf5","nonce":"55e771c657aaa0c3d1ca314a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"0b84207f1411a981bda9ec739e919492e363d37dd7726de207907d9c80f43894b3e9906472219c919620d9ee5a","nonce":"55e771c657aaa0c3d1ca314d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"880efaf8261848086c6f700bd63f4e7752f76f0063ad6f423da0fb7fb328e754ae2d4507a17dce66cb56f71ea6","nonce":"55e771c657aaa0c3d1ca314c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"c7528d7ebaa70c3f00b2b52726c5309ca625ee834d434ab2e30179484384e8cedfbf4fb577b0bad8a153a12177","nonce":"55e771c657aaa0c3d1ca314f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"ad0d808fa51e1ec276a247760d3bb7066daf177aef4b45e0bc2210f788eee15cbc9a301617dc45323f0059d7f9","nonce":"55e771c657aaa0c3d1ca314e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"69f9057270395d520214a26c445c617c919fdd5bf5fdc24cd7d30c998510643271356416de99e5cf1341a81511","nonce":"55e771c657aaa0c3d1ca3141","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"04d6b2abf0af12341a08748efc3875f73e73aceaacf26e2004e8e527e7fe9712ca4e3cd885a7e84923b6863af3","nonce":"55e771c657aaa0c3d1ca3140","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"4f6be7303009bf85440d745bec9f72e0c730d1bee844e7804c1cc208b768aa0904ac7dd09e316d74ee33b7cd4f","nonce":"55e771c657aaa0c3d1ca3143","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"19ac56091385a45d8b3b944fe0dcdc2bbe358c621e4458868112a19f0ab6841e6130ec1722bd7b84baa4acc96d","nonce":"55e771c657aaa0c3d1ca3142","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"a922ab9284dd424736bc0d65f61d3c343a942948a1eb52cc34d97ec2751168506167539c9e2a4f6ecf6435fffb","nonce":"55e771c657aaa0c3d1ca3145","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"c3795ffaa463b0cec66ad13ac01506bda12ad5fcb43148d2584437d4004dc416c0e28955c04acdcf9bc1f34ebe","nonce":"55e771c657aaa0c3d1ca3144","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"713260cb5c39e54d53c827b096c51cf6c942ea60ccc3d2c6a2d44e95e9aae4762f2de97da5106d0415b5a5e6fe","nonce":"55e771c657aaa0c3d1ca3147","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"77f15ae38891fba8517de98cd7e9ca13621383cc89673d75b6fee85fed034b230ceeadbe64d5b1c1c5ab93c48b","nonce":"55e771c657aaa0c3d1ca3146","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"9238685309727dfa2e97c13b0a7ee01c451411e8d29b72a6089cec349f75c587540c453cb93991aac1cc8571e9","nonce":"55e771c657aaa0c3d1ca3159","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"a3d95ed4f7f384ccb5033cee65c52f7ec10317178f9a30ed22de4c2b92b6e8e6dd9a20e8461afdb1d84228e2d3","nonce":"55e771c657aaa0c3d1ca3158","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"fa30a70ec52fa98e1d10f12a85cbe3ef202b1a618d408a7a46d7fb591a6c28ca1dbd71dab88ecb25567e54fcf5","nonce":"55e771c657aaa0c3d1ca315b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"65ab0af31c7c540facf33969fd8f1376985255f38e8806f2b8f7349ce3a34860b0640fc7d4c271728f89478fd6","nonce":"55e771c657aaa0c3d1ca315a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"7e68858ddc389a97855b500263f3ccfc6e1350f7e85defbc1b25518729aef149cc707398011dd8393b21dbdcef","nonce":"55e771c657aaa0c3d1ca315d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"13dcb63c4d7ab2ab9ef660a3297423aff2370bc9bd8a28866530c3d720aa63d5001ad823cf49a2bbd8de07e8f8","nonce":"55e771c657aaa0c3d1ca315c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"96158de073a80aab283e3cfc36b6e7fbb3162f2de7b5266bb2dda7593029df0c55d04b76199d9db54502dd2354","nonce":"55e771c657aaa0c3d1ca315f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"f7327b64f69281787111168d30f92b8965558794612104769f50632dcc81dc17f5dcb676abb8ae4ab39858cb25","nonce":"55e771c657aaa0c3d1ca315e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"df188a5f04098a4202bfdb7e1123d386540c5c14f18ed85e044da1e0c923878bd63bd753ede1dabddefe46acf7","nonce":"55e771c657aaa0c3d1ca3151","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"b3be73b4e3dedc92dfc30af85b9df11c742ca4f76d9b14f126eb5849d48e5cc17abd97bf3cef120120c639dccf","nonce":"55e771c657aaa0c3d1ca3150","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"a93b52be1849d27f39eb088f23976711878a1f13c465972aa08e87b8f4502e9c99b7b1518259399d6bf546e241","nonce":"55e771c657aaa0c3d1ca3153","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"a31552e218cfb3e4276c5c860e0cdb44ef2dc345cb9e6553928ba4583c9896b5f6261cec013794de074b58c793","nonce":"55e771c657aaa0c3d1ca3152","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"f540617dba99352f00d37a30b1baa17d62f0980cf4195ef15cd822140ad5df5bd6c97e8d53bb57690390dd6784","nonce":"55e771c657aaa0c3d1ca3155","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"fcc3d5c89a10223265ec43e5da2c6d7f27bb1b598a4a20a5f1f2befe1ed51f70db13bc19742dfac37a02f5685d","nonce":"55e771c657aaa0c3d1ca3154","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"c05e7eaa20f39bf9e34181e82ba97f4bdfc2250257ab9362f27d3c5c4e059b89c433a99b781ec49e72d8cf9374","nonce":"55e771c657aaa0c3d1ca3157","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"e6a5053285a6adc45abd3c6c6aa001ec97b7a0f8a5a32092333f8520c85573dcd5c49e6ad70a3460dbc681693e","nonce":"55e771c657aaa0c3d1ca3156","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"906ebd884dabfdc2949375b100838ee3fb62891ae736041fd5b5ccd8d701dcddc750a13fbbbb804455e4c5b574","nonce":"55e771c657aaa0c3d1ca3169","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"11485004c5ba44a284c48e1e1ba988fa9560d860c1132200e942a4e32e30ce8d195bc698dbb321abbb896e0521","nonce":"55e771c657aaa0c3d1ca3168","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"99819d07ef6a0a904206fdf0dcfe4de23632e57e9911a73b6b0dd5ad5b002a553567209083bb40f347c818803d","nonce":"55e771c657aaa0c3d1ca316b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"a3eb755329cc209d4e734729d92827e352c796b535552d4cc3b6295d80f454b7c34b486ddaee1788b90f71911c","nonce":"55e771c657aaa0c3d1ca316a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"5ab2bf33aae626b553f95e20bbcf74a7efa157db8f2676becbaeae3207c192c53a84a63ef2792a08448d490f23","nonce":"55e771c657aaa0c3d1ca316d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"c25f52eb086538998f2773bf874c0c3c65a00e4c388ee4b7c985542389a8969b42baa3eb550879f5c85438740d","nonce":"55e771c657aaa0c3d1ca316c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"a5693c564e44abc9cdf4cfd32c8d0d7474a72cffa8b1fc6653e350ad22a7aac800cd696976dab89b97fdf357cb","nonce":"55e771c657aaa0c3d1ca316f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"917eec28fc3192c8f0d2167bf99d47ce4a8c63966b0205c923911675b0b68d15f844a5188b5763798bafaf0aeb","nonce":"55e771c657aaa0c3d1ca316e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"c2483e1846af18ccf2a1457864005249d7bfe90eebab9c271f8eda21779d0d8a2146bdaf3eda8e6efafe2d5ee5","nonce":"55e771c657aaa0c3d1ca3161","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"b8345385aa619b748dac3ce3f7bdd6a2157c63d2366648334589d2e14a0e36918df6e73234c5e5c5071b12a041","nonce":"55e771c657aaa0c3d1ca3160","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"5a54616f703943b24702c6f5cf359b3bb52211ae87a572414f9be75c7e43b89a48766ef17df2af821bf5d5b438","nonce":"55e771c657aaa0c3d1ca3163","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"81f2013c98f4932bcbb9af170cd636efcb3c467ad348e4ee5b8f21ee2600ee9e005a34d4759b224186ba3e126f","nonce":"55e771c657aaa0c3d1ca3162","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"b21dafe4787ef5146b455800cb9fed058a527b3366896810884eb20781be31a91bd615308c93ddef4d21341cd0","nonce":"55e771c657aaa0c3d1ca3165","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"2f6fc130b22ac09086f851722dd88fdda29aaa51f64870f8da7f62c17214b4afd79b120d8b828de1222f28c2ff","nonce":"55e771c657aaa0c3d1ca3164","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"8e9a2954b4bf09120b0f9a3013dda806816497e84d79d6d4d51e420a55305151dbcbff07d9aa1728bd86e8d683","nonce":"55e771c657aaa0c3d1ca3167","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"1d75eb758294fe0cef44dccb7edbb8126629175ddcb7ba5382bebc3ee0f9551b8b0e251e1ffe5a4c21267447c9","nonce":"55e771c657aaa0c3d1ca3166","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"e34debfc900fbe3e20024c52e00998e8016615133059c9b3d6e16c12c8a9b0c7e2b39c6a412b150e4ac66464e3","nonce":"55e771c657aaa0c3d1ca3179","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"e010ad510980f5fe1fb99230fda2d44e86385cf13e3ccf8928a86bded2130da12d2dcf60b4e65bd8279efb02cc","nonce":"55e771c657aaa0c3d1ca3178","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"a9a28b79b276420019c6b9a4742c0e52cff0862bc0531eaaeb4b1b4a47f5dddfb355363bfb0e5fee0c40d1f1cb","nonce":"55e771c657aaa0c3d1ca317b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"f10b7391b2d31d4cf200f60fcf3095126ceef417013d5428859a7d73352f1559cc34bebc86cd6e5834f165a114","nonce":"55e771c657aaa0c3d1ca317a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"21b8f7b721732327493d2dba5a990b9d62447f2cc87dd84e31ebce80a583a67cbdf3a216d026ab1a24f335cae8","nonce":"55e771c657aaa0c3d1ca317d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"7ffa550f88074308345463d1b387ab8845bd31b56b2b25504d20ad3a334e0960c3df439e4c6c7ce9112388fbab","nonce":"55e771c657aaa0c3d1ca317c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"1858be91fe4522e8e199087b9f7bac1decd45c8c9538f180a7f75a05b0e48e8b4f422a37427fd7f2f02d4ea9ba","nonce":"55e771c657aaa0c3d1ca317f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"2ffc601b07a8ee32593615e712a08bad40ab40e57309cf7396f65d002306fbc68070c97363218deadec4f14d89","nonce":"55e771c657aaa0c3d1ca317e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"113b848b035e81e850358ff428d779811048166f374b38891b3ceb1e7ccc1df049a797c6d02257771da8f19795","nonce":"55e771c657aaa0c3d1ca3171","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"437529c14b608451c33498cbe8f5fb160d71b56579738a05e1d182ddaf89a3dab6e4d32ff344d3ff6c026f06fe","nonce":"55e771c657aaa0c3d1ca3170","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"29ac1c7aae5966245dac1e461d67c189546e15a1c52f38b7ea47350fb18cf77c7b401b28ad606e108cb6a99718","nonce":"55e771c657aaa0c3d1ca3173","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"f10bd09f1afe7b88e8b9ada9ab3d503c118b126f9d18250491310146dcb9a55a9b0a2257f5c6f6fab1df9e5a93","nonce":"55e771c657aaa0c3d1ca3172","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"b4bfae8c296f7408f08d9309dccbacdded3ae1d92e3e65065a2235fd43144be015eb698b8ffefe41b0f7082c47","nonce":"55e771c657aaa0c3d1ca3175","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"f5b21c05be232f120a3bf2fa7b93b7bf78aed418a577f6c890df8b79e03b94608688713c600ea93a84dd22288a","nonce":"55e771c657aaa0c3d1ca3174","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"0fcfc6c224df615ea58f3e13d9b3ddcdfdb4771b378be6fa293cca820e528d46d74d5540c8273cf53b0a0dbdea","nonce":"55e771c657aaa0c3d1ca3177","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"29872b32ae8bb528dc451d01007682240eed3c2cda2418429bca18571029c62b29f3c080694192c34fc416f190","nonce":"55e771c657aaa0c3d1ca3176","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"3929a6a7bb8a25e715378ab45ee6d861d8ba9b6604b3d8bfdc7b44c00f464c609d6cd4a3d5006a475bd7340d01","nonce":"55e771c657aaa0c3d1ca3109","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"9aa2233f74392ca28f4cccc12d93adcc32df4b0d798b6b8f962fe6177dc98a0b70b43e5cef7cf9440b6417402f","nonce":"55e771c657aaa0c3d1ca3108","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"89befed9c7bc57afc1bc06fb2bc92f51864a30893de008c141f57027e8ed9b17da0f177cb90097edbeaf8d6308","nonce":"55e771c657aaa0c3d1ca310b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"e3d15110c0c64950dcac21c8b77b66dd568f2c82c8f86c6d702606e837e0e5ca207cdfcaccf546accf89157d38","nonce":"55e771c657aaa0c3d1ca310a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"b44e195660b361cc1032f8c6a5d3417a3bc53db4a73b4349f27b6f4e7a9b7977156e91c544f97ce1efdd424ed3","nonce":"55e771c657aaa0c3d1ca310d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"0ab66332a66cf5d51294bdaaaa62ae8e0a3857499e9374ab5af011a6862215fd6a942591b1c4a339b0eae5b2dd","nonce":"55e771c657aaa0c3d1ca310c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"50b1b8cfe664a082c2a206d00815929a438af060bd54c7a49ba35c429364b84fe7fad91e6d4ac5a68f3fce126b","nonce":"55e771c657aaa0c3d1ca310f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"50df71241ab20a003f7a46112e3eae8dabee881a37746ec124a89ccd566e15f55a3d2470ef89771ff8a790ac4e","nonce":"55e771c657aaa0c3d1ca310e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"7d9458968ebbbe7ae3a9e4e8c5c532994b2c8febcbaf9f1488b0665f7d5d35f538ee46b497e76f5090fd5a7182","nonce":"55e771c657aaa0c3d1ca3101","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"52e0b534a8df59cf36c9b4ed04338b783b486b5e77360987f7f0206aff7505ab0f2f1d8d048eae3b564cb7464b","nonce":"55e771c657aaa0c3d1ca3100","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"4f7c300cbaca42189a7ba5e45a219099308f1ddd39976f8a0d6e917dfa4987201878784a576f63f325c85225ad","nonce":"55e771c657aaa0c3d1ca3103","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"a627cc508a6aa1304c3aa855208974e671be2259c9e360bb1a01a1ed93d8d4c5b2efe31e0d9f7905049b877c13","nonce":"55e771c657aaa0c3d1ca3102","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"31eef7b6cc8b2c15f4296934233d18c2be6dc8b80ce4617b131247bd312e7a409e54e64f3ddeccd272b4a5dd7d","nonce":"55e771c657aaa0c3d1ca3105","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"78d5858971d13d3aa134b21968916ec37bf18e28c3d612c371748b6c37e72650303e562e2ddd01144252f60660","nonce":"55e771c657aaa0c3d1ca3104","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"314463dbbbeeb92ba86e94a9f8c5ee614146a6dc07c353700623a0355c3cfd371bbecdeb213116e065c961c587","nonce":"55e771c657aaa0c3d1ca3107","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"d19f00ed8fddac45f35dd6f5b535b074be355402d74c1896d248cb4865b4a6903b2095ca82e7ae5cd321914241","nonce":"55e771c657aaa0c3d1ca3106","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"6c87f2667c11f3cf7aa24100c01a2740b3ac0c2d12f8e436f21b653e0a08853caac08d82f388ac02d0e75ecf5e","nonce":"55e771c657aaa0c3d1ca3119","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"30d959672ec279a5b4693dd9743cb342529242f53f7c5ab4a1785b02c58593cc23982a8bbd24079200d1a357eb","nonce":"55e771c657aaa0c3d1ca3118","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"5d5d0915c5148d2f29839dc62704cfceb179eda229debfad8ad7f5ebf95f27f22e20b0791b9a375b36f2d899f0","nonce":"55e771c657aaa0c3d1ca311b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"18bcb036c82485ad75eadc8caaaacd49f91ea6ccc96c68aac982ab5d9c666a1a786b1932008b1debb439000e7a","nonce":"55e771c657aaa0c3d1ca311a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"1705d00aaf5e5a1b2d5bdefd70f9f19cdde3a367aed8dac91a6a043650224672dc6cd042453cc4d566aa6215ab","nonce":"55e771c657aaa0c3d1ca311d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"413c8d69fcfea258b1d8f5602be79760e2b89cdb2fdcac3ccb7c9de0a517a83d478b0da3ee8d7f0f12b610b0ef","nonce":"55e771c657aaa0c3d1ca311c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"8f6757dc52d711c4a90865797e92948a563cc1d1b76eb526bc4b86376951f0a66488715b737f0c9b705f4bf5f0","nonce":"55e771c657aaa0c3d1ca311f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"4e4dbb94415d807a4646ce145971a307beea65ea14d4a07f185ef26088f07cbfffe6c6199b0e488bbbcc1dadcb","nonce":"55e771c657aaa0c3d1ca311e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"e2e3d0a127e856962e7b6047d81df6ecbec9b1345494d761dbda23940878a39560c91398f489934c4ceddefdb2","nonce":"55e771c657aaa0c3d1ca3111","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"0c1cc7161f323e92bd6ba95288417184bcf8652efaba232ba4d1b9c52b6c66492f951b9bd2a26dbab079e268e3","nonce":"55e771c657aaa0c3d1ca3110","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"d125b959d2669fd08083477c8217b81816a43148630d252981b76b677c2845ef5e63d8122ff68e303079ac4763","nonce":"55e771c657aaa0c3d1ca3113","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"a7f57f23a724083a0cbf35278954a4c372aa5335310cfae9e43f58dd600ab58f812683a3be527a294f80000bf0","nonce":"55e771c657aaa0c3d1ca3112","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"0e5685f323210b4f5a939e77bc3e0b0c6e39bca6ff4317112378fb022b06240262c1a68bc18e86477d8643993a","nonce":"55e771c657aaa0c3d1ca3115","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"d7d8fa834ca23799b0b559744543956ba265be2a003fa1dc753a89addd7dce07f474e3cce272164402c7bf9ab8","nonce":"55e771c657aaa0c3d1ca3114","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"d8827c319b7c4b227fb0bc5367b8860878150bff3c8a569d70e93ad3cbd8935fe612e071ab210fe0a15b0250cb","nonce":"55e771c657aaa0c3d1ca3117","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"2e9bb570039ce0bb0c8ce16f2a0f966a3178674ed78438154743097097699f7ef31c2f566546c727ec8fec0a22","nonce":"55e771c657aaa0c3d1ca3116","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"503181ae3b8f9b5bbbe991ad451d6dc90566d40f53f0eda50c898c0b1060e1e1055f27befc7ebaf8b5e0197de2","nonce":"55e771c657aaa0c3d1ca3129","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"761e6bc2870e9a9493bb10f1c43f0d759cc8b006a2a088e8b40035aede3d9b19f30804b2f37e4f9c0af92c740c","nonce":"55e771c657aaa0c3d1ca3128","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"dfbe1b87810efff4d47dd90959c0f5cc883c591e1ea8dce8de36039cd43d4d2e3718ac42377c53f385fc75e029","nonce":"55e771c657aaa0c3d1ca312b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"96d282f74ea722f735cb596ff3f804dfadb63facab971bf59fe5ac2d6331d5ff1c46e7bd69edb71fd7f5548abf","nonce":"55e771c657aaa0c3d1ca312a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"48b10720a40cdd0548472c6618a7dd60d394a1f78cc4311c8dc1e72d8ec791d59ae2d51fde7510a2eb53cb957a","nonce":"55e771c657aaa0c3d1ca312d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"1606f1e326349862831fe264817cdbf2f83bc6793cfb7f140f887d5022097be9d5051a2a65731edbb440ecb130","nonce":"55e771c657aaa0c3d1ca312c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"f5015f0ee094f581c1bf4da28ed4687b3cb54c48f10881601220f1c685692392f151c184cee3c66f19f5ff0a16","nonce":"55e771c657aaa0c3d1ca312f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"1ac29c0def377e72cbed9fbcf24e8eeca377ec92418c0a53330a301e86623d6f95515426647a2cb1a081936102","nonce":"55e771c657aaa0c3d1ca312e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"747c553d3500c8e301f0516af4d8d6c883f8a589ff222b42931e4678f32a341a060824750e954ca7e60620a783","nonce":"55e771c657aaa0c3d1ca3121","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"54fdb14ac75bd8fe593d5ff68f8076a618aad903ec3a603c8d3f5a93292c85ef52322905324a694d0513c550a4","nonce":"55e771c657aaa0c3d1ca3120","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"dc288b2e9cad9600b0192fd8b4ee2f6f71a9818d55ee32a7b16db7226226e3a0aae551e0de95dab47e925a07a5","nonce":"55e771c657aaa0c3d1ca3123","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"35b180cce264930758f6edf3c13385880fd3f220a94838aab541de4bb07660ed8ec83f73f93ce757b4b8a6a8e5","nonce":"55e771c657aaa0c3d1ca3122","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"67b02ae150a0a74d8fa55d797327e7521349d24fc36219ba7b8075afcff06d4b47ff1316dc20875b79a4897586","nonce":"55e771c657aaa0c3d1ca3125","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"ae210103b7fa86f4b6443ce5a2b89f855dd6b349639d28f93e2ca7d8ea961d359c37abe1d020ec6ec9ab4b6348","nonce":"55e771c657aaa0c3d1ca3124","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"59ae3ce18efb85b7222d73c47ed35ae862b007ec26cc7e9eb511753ac7ee9dfee6a710ce0728af40dbf0b612e6","nonce":"55e771c657aaa0c3d1ca3127","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"1175e2e93282cc354ef51bf0ed2cf1f77eb2ca29721a0439ecf205643ef31b2d11619bcdc0d8b5d86f57e6d0b1","nonce":"55e771c657aaa0c3d1ca3126","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"e665fdac995e0a933987ed1fc5737f1a36c230416a234f85dce387a9900566b0c85c635dea824dbaf5c0321abe","nonce":"55e771c657aaa0c3d1ca3139","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"a73e0554fe418b28b41d8c27c61a124e56ee1e08c655d4bf0f0705a298fc789750e7eb98a98eecdd99dc14afdb","nonce":"55e771c657aaa0c3d1ca3138","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"73e57633c18fdc95161fd665e99dcd360afe6f942ba4201d84a528b2f1150fe5c90f5e640b870e7356c2702484","nonce":"55e771c657aaa0c3d1ca313b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"1c2711df53e3cb767fdac07938a8160a5cf64677e3c8abdeb388cacb2b250a186d3835d98500ebd23783cde050","nonce":"55e771c657aaa0c3d1ca313a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"f3a7f4f37f6a9b2a88ff3c676b8f5cfc6f8bda4f76de33e14113141fb389a1af947d1568e66f9e176719829005","nonce":"55e771c657aaa0c3d1ca313d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"84b90e269cf23040b4d8976eeb8e08befef1d9da01c707ae8d8c24a7a8b775e0793e6f95b97b43e05ed240c18e","nonce":"55e771c657aaa0c3d1ca313c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"0afb2b0b0592da8967d6c3eef7d383b1ebf95e4531c0f1b7da50aca3c39102a9b45a27b9d9e6f8e8a84297cd0d","nonce":"55e771c657aaa0c3d1ca313f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"54870a907b8112d2dc7771816f34f9d90445ae5c6b51c27855132652839dd06ee7f4683a102513975b2f676a2a","nonce":"55e771c657aaa0c3d1ca313e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"3f1942d48a1b91579be0e56556d5270371cb3ccda0ccb198bbd7f3e59099624f44de5002fe6a3f459259def76f","nonce":"55e771c657aaa0c3d1ca3131","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"d5904921981e3c69e65a5abfc41eafd112ca4a19f9ff01d9c8ff01eaa589329be0e79b4130fe6e8c93ed8efa93","nonce":"55e771c657aaa0c3d1ca3130","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"6f7a614f212754b2b3ea5ccbe518068aab2126c8a490932e0699b0889d2e28633888294c44f8dbb7dba24b9654","nonce":"55e771c657aaa0c3d1ca3133","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"1c3287f63970daef419009979d5ad7a56ae3adcfe8b8d648817787c4b346e3cd348599c18431c8292939c2d2b5","nonce":"55e771c657aaa0c3d1ca3132","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"7a9a406f876bc39505316af6c6e2cb781afc3847e6e589038c28a310bf0352c6d28961d164e721bc342b3487c4","nonce":"55e771c657aaa0c3d1ca3135","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"8324cbc839825173e07cd03e677149a7c0222f948cf95675785a43621272604e90efc678adce2fa93590b62e2e","nonce":"55e771c657aaa0c3d1ca3134","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"b7928106a8325e1a0941db513a8c3241171108e7f2e540e261ad95e0f09ec116d6ab80ed5263d11cce40029b51","nonce":"55e771c657aaa0c3d1ca3137","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"3154a0771cac2511f5a3e54a8050215d41400b6de3a3edbab401ad80d07f894953848d4d19cf155b6bc9a3afcd","nonce":"55e771c657aaa0c3d1ca3136","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"8c507ca5cf5a184b659b5c5581e8bb23fc41b75b89608b64a03a49fba4db679eab7db07652f2d8453638c1e85f","nonce":"55e771c657aaa0c3d1ca30c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"db6ff89db59370a4570ef50705539529b5bb29328e245db9aa4b7aa36a9a9d59"},{"exporter_context":"00","L":32,"exported_value":"3f0eb5ee334e706e821c6ea8200b488cceda8a250dfae18638240afff35fb944"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"cb26bec375cedcde8210d4937d76136d749c84e892f42ca7bf41a3f6ac980298"}]},{"mode":0,"kem_id":16,"kdf_id":3,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"4ebbc24e10a5cf5b05e2068ce9f1a90bb8e1a543e5722223746ef9939e70ed83","ikmE":"b8208ed1ee4111645c63b3bd23a48fc9152dfa2dac23f62999b29cf1fff15f2c","skRm":"794842c7ad329ee43fa8650e8fd48045155a7fe7a43bedc20c3b4f8cd2b83912","skEm":"6c7bbbd33ee879fae592272bd32021183fba338a165a6cf65d2881dc73be28cb","pkRm":"0414134760875b2157814fab97212ceb65e285e03fe88dd2080aafeac26a6464324d7a3f3f649a1af4d1b53f80f5ec6dc836fa37345d46d884448aa8100f89371b","pkEm":"04da69e237c5a9531dc05f40433443db4f9571d585aad9a405c8e76574f268f7115c0e7f71dba6e6aa58d94b324a33b1aaf69850a5b432ddd8c57c15a19d29fac0","enc":"04da69e237c5a9531dc05f40433443db4f9571d585aad9a405c8e76574f268f7115c0e7f71dba6e6aa58d94b324a33b1aaf69850a5b432ddd8c57c15a19d29fac0","shared_secret":"ee335a2892696a00929533361e14bbcd2d4c6bab251f99b1c740390a8a1b66ec","key_schedule_context":"008af8c8585cbab503908a747f5b6e6facb58a8eb7d6aee84875f8e4fb97a6baba74330d080c6e518d29f18589d731ae505f746529747c9d25d75013d5f8f2f7280da9817afa84fe836a2afb21fe34bee379586120ef91d5c0432c32bb1d1d6dc7923282892f781147d97bd9e353465a35023868db7b5c0fa7a73b1ee212161f04","secret":"fd00c38122e2ebb8f9108c27f972356a33cfa896c8b5840fe48b1aced07dcf685437c7fd31e513f06b5166a40c429fab6b4cbb1da2b769390e4b6f79b053f82f","key":"1fddd630233d05a9fdd9c86f09b9ff2742e65ff24ddd4e26b7551e10885409e9","base_nonce":"fcfb60594fe00e94cdf9c6dd","exporter_secret":"c9dec0d169a782c99df32ada3b4193f5b1db9db14add484ae988f585966c5af8c5a1d3ccffa291e8c6c83fe0a289f7fa261569408523e4a4807922424674b539","encryptions":[{"aad":"436f756e742d30","ciphertext":"5cee4f495dc1f3cbf3d0ec60d2f6f5db32ed3ce318cf01603df7088d7a71d53c9dfe0d5bc835646893caa4f6cf","nonce":"fcfb60594fe00e94cdf9c6dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"7e5ee22eea704c7b4d3ee2467b1bc0686c50923da0f703f2f5f6f4730c6b40b342a880146472daa299fc2295fc","nonce":"fcfb60594fe00e94cdf9c6dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"a1566334a200d0cd63d6909c3ee5c2ae65b7a4f5499ec44d32395d59cea084d484424d92d0c6734764984f9572","nonce":"fcfb60594fe00e94cdf9c6df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"59bd548f6ab377165a53e51cc26995657d055ef550686278cb5ac7fbb1ec4360131c46eb40ca03ea2d9b60bd84","nonce":"fcfb60594fe00e94cdf9c6de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"5e1248ae8f3bf7ca5301513098e7fa40d105b9c89d4f8438db5f8a2985c9c4da3c666a6fccb8d08d015c211533","nonce":"fcfb60594fe00e94cdf9c6d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"44b6ab9e69f33fc78e43be4879899d8343957a22c57152be9e1077a482fe905fbe70a88df47d913f49d33bf118","nonce":"fcfb60594fe00e94cdf9c6d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"83aec4e0711cbadde4316635bce568408423b052df533c551928af399e6731c6c2372a1856d10417bc9300ff95","nonce":"fcfb60594fe00e94cdf9c6db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"9953a2ab43249cd46cd84bc5efed989a506d09aa4cf6d72129b9485d82b207d2f0f4ca08918cc6aa36d891ed77","nonce":"fcfb60594fe00e94cdf9c6da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"1216187d1210305e346fb40a674890319ec76a1b27eb6b760b595902f68396855840d9a75080a3f19f8cc2e3d1","nonce":"fcfb60594fe00e94cdf9c6d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"92ecab717578e7773c5a47cdfa6cc5b0224979d1d896e9c415908df2e273262b793119c891930f1c9f8b3c51d9","nonce":"fcfb60594fe00e94cdf9c6d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"96b1badd207a76afb16529d69f25a98dd8f421d7ec2c4f19ee97f81ec04a7e33a752027a850d083a531e3ebd8b","nonce":"fcfb60594fe00e94cdf9c6d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"4259e4a2b56adc9612e5900798469b15880097772f38721a8d7b9ad925435fb220230479964281855557dc00fa","nonce":"fcfb60594fe00e94cdf9c6d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"f14eceb2006d03bd7c12c5d0d34862948dc70aa88c18e65967526e3d9206299508979b398fc748afa2ef0d184c","nonce":"fcfb60594fe00e94cdf9c6d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"24d37e58cf6866000f2885c782827c272b8ee8f55b75becd405877e4f9986fff25adc651e2d272428dda41c388","nonce":"fcfb60594fe00e94cdf9c6d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"74616c030f1fe842ea8c70d2f62176642dedaf36135c4e692b1029ba3ac6dc85c1296036446fb1de08b5544cd5","nonce":"fcfb60594fe00e94cdf9c6d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"0633bf739c549c61ad47282ba2071f1e076f28cde03917c49a37a19eef2e6363c149c7eebcfa1a6f25dfcd6429","nonce":"fcfb60594fe00e94cdf9c6d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"af896a25edc61eb4b75685e80b799c0f59cae996208acbfa6255d0eb63f751b92d57ffb10ffb99d6e8a4bc7ba6","nonce":"fcfb60594fe00e94cdf9c6cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"8b62d8e8a890d7f018385e07dc48895b995db287d08a314f3426865cbd6b360a62ca6f59d1f8b2b93b255ff8cb","nonce":"fcfb60594fe00e94cdf9c6cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"ebd1e50859e32e1bbe5acefc2d01564c3d26aad0cbe9d928f6539b06730a4dba827c5b34997ff10d68e7238c57","nonce":"fcfb60594fe00e94cdf9c6cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"ba9e3556feef6db07c4332a5b19bc81b6e80b9f9176cc7173b203a826123d8f0db4601bfe5f4cf8591dcdc2d6e","nonce":"fcfb60594fe00e94cdf9c6ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"c3c80601fc518023c42807b2dfa848cda60b12c48a28d16f845df8853891c39f5bb639f517d56cf6143ef74a97","nonce":"fcfb60594fe00e94cdf9c6c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"88073c935e92acb61024d7e8295ece629c3b60f5938d24d46945bf7b6264db253e59ca38d63b3d39e2cf80c403","nonce":"fcfb60594fe00e94cdf9c6c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"f0c997cfdaf28746e2e322431b56292cb0df460b4d8109a85051d1892bd9eef7707b0bd6d11baababf3fb35fbc","nonce":"fcfb60594fe00e94cdf9c6cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"f9191da4772f11dc0f30d407434d2d8580037b991ad2fb142e50a633b9f153acd6449dfb1e6b15d7ab74246214","nonce":"fcfb60594fe00e94cdf9c6ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"5b7ddf7b73f45ee8f56ce1e4c117666b85fbe539554972d623be976de9e5eb557e9787664079e9081168252fab","nonce":"fcfb60594fe00e94cdf9c6c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"548895378bce2ad4fdf5fbd8c1aa660e62e678b07381e4f6c82faf12d4bd6bb8bc26f9f308947343a7fbd91c10","nonce":"fcfb60594fe00e94cdf9c6c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"f05b4306b483378339b0f72cd92a43bbe268d4605b285ece5a5c14811a1a9038750f5f06413a06526ddb92927b","nonce":"fcfb60594fe00e94cdf9c6c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"c5018ba9a888e9d980f87367d86d852ad269055c71485fa1fc06862595d1deecc983cdda16031337a4df2b54b2","nonce":"fcfb60594fe00e94cdf9c6c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"86bfa93e3a14a189e16875a9e3d6994de2141bdfef334cb2db439144bb1390ffa279d85d25de47c43bf3b29bce","nonce":"fcfb60594fe00e94cdf9c6c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"87b545e02d3ecb8d6fe5dc4b2c01f8e2ddb044d217fa214ab962acc96661e3e5784ed1457b142cfe547c7ae2a9","nonce":"fcfb60594fe00e94cdf9c6c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"0050a95e82e9c5709b63232ce65fc3a1d3ec3983fa87c0f571c4996945b184a656370230c737a4756ab1af8907","nonce":"fcfb60594fe00e94cdf9c6c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"71953f9eaa127b59c45df99e1aaa261f4197b88fb5d7abcd697005051b74fc8ba2c65e91475c296dd1a801be64","nonce":"fcfb60594fe00e94cdf9c6c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"ac7a8e4294b78b15a3a4b73a196b3aa48e4f55e1dc202efb6d183f6b4d8f884d24bda6cd3981d7b1f5741cfa30","nonce":"fcfb60594fe00e94cdf9c6fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"905e9d1c733442e81c2318298437f0b1bb0d10ac4f52244e982f6a144a02ea3331331c13cacb48fba7adf3a8de","nonce":"fcfb60594fe00e94cdf9c6fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"02b7329f0a41fdb3831911aed95f9533787efb46f9dd1342b2e1e369b1e2661d8bef5fa8f220fd5fa203448018","nonce":"fcfb60594fe00e94cdf9c6ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"07987291b1f58655bc5be68b4f918c35f9f17ab44d6ded04832f200ec7d722b61fbbb157c2b333e86fa80018c7","nonce":"fcfb60594fe00e94cdf9c6fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"028df81c85baa7d950da47bbc594f4cc21913e7f7129b11b55ad71f6125d4cd35f98701966dc3ded4bbc50ba05","nonce":"fcfb60594fe00e94cdf9c6f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"ee65a8ebf213719ee082e086cb0a94cdc0f2a9d1fd3dc5ad8d9765bdc631fb1dca238d68f033033ca4dadcc358","nonce":"fcfb60594fe00e94cdf9c6f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"02cf841a60cbdfe084fffeb1487f4b181cf1e1bc8c0311aceca73c86c4aec9f819039cb7317ac2759b309e3285","nonce":"fcfb60594fe00e94cdf9c6fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"b249e26fcbf0d5d77e14e8fd2dbcf10b16eea1320a4000a89bbc143221428938669ad8ec05fa3250e877a419d4","nonce":"fcfb60594fe00e94cdf9c6fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"b38d08829d40d9ca2aec712134302e602b6b4a485305ceea1d689a98b3db36f3dc4173fb1a8ab5cff6c6e7f83a","nonce":"fcfb60594fe00e94cdf9c6f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"c88975fc3d83b54b5d85cc055764b68608fe4fcb23d77d2c646f07eb5ef1dbbd8bb73eb4ea718a0a1c06dd3b6c","nonce":"fcfb60594fe00e94cdf9c6f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"56a92a88e74274c49a21c4042b1159f711f11cafea8ae6667cb8300067d9eb007932ec5f4fbc6e2274042061fb","nonce":"fcfb60594fe00e94cdf9c6f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"8536ea7fdfe9bdb8a265e9497f82f9dfe19b55a58835932087591466e762c96d7e8432521214237e2fa8697ee2","nonce":"fcfb60594fe00e94cdf9c6f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"7db1ba04bd09c95375d1f10b294c257b9df3307c59eafe76e3125b390a836f91dce3f1555643455a7b1681560b","nonce":"fcfb60594fe00e94cdf9c6f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"6481bb05053f0a961cdaeae793f9d5766bdfbff350c7ecf39a3fb30ecc6a702ad25835bc3ec56a3d971f1c6ea5","nonce":"fcfb60594fe00e94cdf9c6f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"210fb02b759f386feb98eb4fdc8f41ce036d9ddb0045a48e19239a93a27cdf77bc3a84b934b2de43fca41bf872","nonce":"fcfb60594fe00e94cdf9c6f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"03705972463646be0f40b77dfdbe9a2ba4894cbd8bfc8bee547ee97de93769aac84f566eb37c6aa5e4a8a6ac46","nonce":"fcfb60594fe00e94cdf9c6f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"22e218cae6001e1c73de12c12f8c5931a29ba6bb306d75dbf4c2f81ef6d85cdd376990a4d34200afea4887e120","nonce":"fcfb60594fe00e94cdf9c6ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"3cd683c550b8d916f6706e7a47e8d027775edc5d08e2cc75aad94dc19c9f60cefb0c6d6243b1c519632b66ecb8","nonce":"fcfb60594fe00e94cdf9c6ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"af75f5e7f880920a91c8aadc3c3303b984ea933a6aab680ab727d5c011e782f361d4d81f1a232ea1ca32dc4669","nonce":"fcfb60594fe00e94cdf9c6ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"7ef8097956c33bb8ff22ed8f06896e7aca7b396f1ef4dc0d76ec41ef439d9c48571c92a4fab49b940d52c23081","nonce":"fcfb60594fe00e94cdf9c6ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"67162d658c2675a5550e85c9cfc2f59a88feac23b8c83f99c9dc6f7b496a85076fa7fd0c6cd5e371a1c68963b4","nonce":"fcfb60594fe00e94cdf9c6e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"d0792732fad681d9f429339c0445cf3bbd0c59a8fece56f4660a4dfe6da2b8638378c1c489b909c9f69f59c4a7","nonce":"fcfb60594fe00e94cdf9c6e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"031276271a7e95933394d15a2839ab9c8655afb29fc003b4c8ebb653adc91789430f9cb8b11bfc3a51f44fd4b1","nonce":"fcfb60594fe00e94cdf9c6eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"dcf962814f63aa3ab5b8a170b9170b910becee8e4b1e247746802c9b038c8890335a0c5a579a43d6d710b0c756","nonce":"fcfb60594fe00e94cdf9c6ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"5a0c4187bbf43658600ed5ad2bb1029f42c1237f8ba24fc63226dd94c3d508cc85843b34c6870f024596921ae2","nonce":"fcfb60594fe00e94cdf9c6e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"0922f6cd9a2c6d81279ee308ff8f737b3efa12eb9f3138a6ab89f33d77c406b4fbb2ba5160a4032af320caf79b","nonce":"fcfb60594fe00e94cdf9c6e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"dddf096be3ee0776bf1e37e353e5e769e91c4e572d01319c664c6948edf19d6fe1574cf3fe9149531b79aab01f","nonce":"fcfb60594fe00e94cdf9c6e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"df2cb383df6cc143181a0c0cabbb01348495925591c4b2ae57a209c2c9c08b148f8ed52ee2170c2818df629a6e","nonce":"fcfb60594fe00e94cdf9c6e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"541ec24b38d3695a99aa99e59b7626d77029b5788ffa6fa29876ed5ed040d43a063e27eab9ba901cd06efed9a2","nonce":"fcfb60594fe00e94cdf9c6e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"daf14f7eda2eb707a61fcd040d2eb2acd348d36c32e17e4e62e74790e7b22a6f3dce55a00598a4c5bc072b79c8","nonce":"fcfb60594fe00e94cdf9c6e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"4cfed0924af12986eefd7f9ee07e380257b5a01aab7a96f3a35b9343e100618113113e2829c33cab24a24a8725","nonce":"fcfb60594fe00e94cdf9c6e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"b761cf31d9e2e90409d7a650ae78f7adea373750ed2a73f78e28bd72ad7f73bbbf74e465e75ab9e5b7d8e60d00","nonce":"fcfb60594fe00e94cdf9c6e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"688facc9bd9a55bee13c9214d5d3da67f0f2468d6ca22861c3a91351b9488a7ab26833c9ed617a2dbbfd723be8","nonce":"fcfb60594fe00e94cdf9c69d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"8c9a1df6fdb2262b401e469c478465a438c12be9012952c35b56baef24bb4e87cd97571c0ea210bc4d1412c115","nonce":"fcfb60594fe00e94cdf9c69c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"097136c5fcf76d38962283fd9cdc1bbbff9752c4739db62885b106468eca9f051c890048b2c7e2f11ac2377abb","nonce":"fcfb60594fe00e94cdf9c69f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"a56e42e17413b642dbafe56036d260d9ed239b656ae0b9f2a2de342daf601f6492f0d73755d97f29594fd0034c","nonce":"fcfb60594fe00e94cdf9c69e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"f5c7a1bc0822daed6ad51da1012d01dd0d63e6c66ffd52749697038465fc01b5101618d62a9cde683e80bd26bb","nonce":"fcfb60594fe00e94cdf9c699","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"31705910149a2d8d1d765470031163e9b012ec6960c9819886e45d1f800f4bcfe32362166e77329dd866c98201","nonce":"fcfb60594fe00e94cdf9c698","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"f6cfb21ad5c4e4030e7c22757a72a073b7685cc6034f4bd5c851919eb99283e305b48b6d81de5a6b0dcf29b68f","nonce":"fcfb60594fe00e94cdf9c69b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"9cd4ab2b224afe9d95014591e69d51d7db78684c3f12b7a1277173c243d3130b401c6fd5b0aa31089098d08755","nonce":"fcfb60594fe00e94cdf9c69a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"7a734c19ff03c127320f86103f8877ed20f7d55275734ab3f13c134eed53aeb2b6ce7e027ad7c3ad4d2cf1fff6","nonce":"fcfb60594fe00e94cdf9c695","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"3127a1898b09c9e3d50b6f2774e92883fb0fe27c1e9ecfe03b7b032de1231e29ba1cf6b8b580c414a6ec2f598e","nonce":"fcfb60594fe00e94cdf9c694","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"ea48e5ba91097d8dcc453e4779e021e729a669724e8764934f9f0e65f16437fb133004f75b368eaf0a3057702b","nonce":"fcfb60594fe00e94cdf9c697","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"97142e863d6a7eae10e7541d266a9a34c6b183f157ec9afc6bf850c441682a9ea9d72f8fd9e284a98669a17ed4","nonce":"fcfb60594fe00e94cdf9c696","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"454e8d32dc5449e3e3cb233efdc2071d07af0dffced77721a59b45bf309346c3d1b672ba28518d1a10709fbcc6","nonce":"fcfb60594fe00e94cdf9c691","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"7d23d46b38118e230bf9e2e8f9a3ff98e6364cf9569bce7a7a6c371fed64e1bc625d29fadd2ee9f540db893107","nonce":"fcfb60594fe00e94cdf9c690","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"840cbeb85175c6303bb45ba4827c6ae95e916a937acbba9af0ee6ad77da8a1bece88d9d156e11fe5c17a4d565f","nonce":"fcfb60594fe00e94cdf9c693","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"e60c6e0dad8ad6a5ebecff2575e6399a1fb14b122ee748d54e553240f3843dce068e335dadf1f4db1069a71d63","nonce":"fcfb60594fe00e94cdf9c692","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"7d20a722b98cc94b355ff5382dc4d0fa3ae978c546319e70574a7758fc4a294960d95744dab30c2acac2de9751","nonce":"fcfb60594fe00e94cdf9c68d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"5cf17d54cd033d99bf453cd052bf733d7a34e8cba10222009adde068089104573504fea41f9e971437eeba5644","nonce":"fcfb60594fe00e94cdf9c68c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"07bee12109e04191a3d46983a949743f6b6b9c1e6bf537a951b61637e386e365a343a6ac05130f9f7d594ed49e","nonce":"fcfb60594fe00e94cdf9c68f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"ac3ec6201bad230520171bbdcd2e9c2d1537ec208e40d166de12e0f0ff0e4ab700620cee6fc729e3de4d740bd9","nonce":"fcfb60594fe00e94cdf9c68e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"71d556372c51fa46399d068e0adac1c8a943f69528f2330d5616887dd900e04a5e811a9ca4fbdc3b0d6e3f229e","nonce":"fcfb60594fe00e94cdf9c689","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"66b3b5a09b0fda2d769f3df552deafc6ea7723bc7201a971b0d77c28b5d2d70b4b4e6cd5b451a1d9252375b19c","nonce":"fcfb60594fe00e94cdf9c688","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"919d5a597d7e38fdd66c4f81cb5fd22e0e14167e2b31fca9f7a0e7c55f947f8c837244ee18cd59d4dc04f004b5","nonce":"fcfb60594fe00e94cdf9c68b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"d0447fcad64d397af25515aa243f837dd076bd5130e9bd313485ec026491599339c5a49b1bf2ecd521ca364412","nonce":"fcfb60594fe00e94cdf9c68a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"3efdfc2c194f49021d1a8ed5a4e8383f4edc0d6c77630ecef016a53307765b935649c447320afee32d28597bd7","nonce":"fcfb60594fe00e94cdf9c685","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"d5d44d4d8bcfd038f0d0031d5ff5ac640f711eb57c67be70786309ea76007ea336003a48372360a3f0325ddbf1","nonce":"fcfb60594fe00e94cdf9c684","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"fa25ceace5462914c411ef11ce4001f3397beebc281662950e2f33dc9740eabb634ebaeadcbabedbdfccae80bd","nonce":"fcfb60594fe00e94cdf9c687","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"9602f0fe6b48d057e23bce80d0ceb25e94e2a08f5c138865dea9d7e775e08608968ae08b27b756babd77a9db27","nonce":"fcfb60594fe00e94cdf9c686","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"3cabab9c7368caf34a96df4fb9258bb047d80fbf77f4ea7d3e13236f7aa223167d7bc50c62aab820c114e1a1db","nonce":"fcfb60594fe00e94cdf9c681","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"5bf46ce79377689a9b4553da18d8ac2201262f192c36cafdfc7c0248def60c72a66506765075f6c15ab3ef8bc6","nonce":"fcfb60594fe00e94cdf9c680","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"813f5258392f40bf4863d05bb4cdc1a7b265600afb633e4bc08abcb50c6b36c80baae4b8614a3c9d8357060f88","nonce":"fcfb60594fe00e94cdf9c683","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"0bd8dc7cd885c0e0cc690de237bfa00bc29cf352936dc6f4c6897d91d5415a6d80190ac06966bcd705bc68209a","nonce":"fcfb60594fe00e94cdf9c682","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"f3f4848be67ab8f598a6d90956b9abb21be4cc4a3c1c776a724ea8128299f0a1897b8c29057019fec9b5692e21","nonce":"fcfb60594fe00e94cdf9c6bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"9f09fe6a32a5713f3595aae52a5fb041bc7fa252e9ccaf75153fef38f7059c9bade10304a4418948fa8e300205","nonce":"fcfb60594fe00e94cdf9c6bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"dee5533ffd878fe7fbe983405a8d80b36a6f69bbe41fc7ba87f0f67f48747fb01ed8bc7b1d84d3fa765204e2a8","nonce":"fcfb60594fe00e94cdf9c6bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"a99caeb074321598ac08af00cd0acea904efc94ea9c0e0ee81c3e5e1e33eced8463ded7d3f5f850d291a73d21b","nonce":"fcfb60594fe00e94cdf9c6be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"88b9c44744d9194a48be06b7ed818ff40637956f4a2367b0daea9c7dd23b3766a833cf22a2adfa731691af87da","nonce":"fcfb60594fe00e94cdf9c6b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"3baa5fc80dc3374c9aec1a12cb195eb29b21d688c320346389a944407c991576cc1c833079f85d231f579d02b9","nonce":"fcfb60594fe00e94cdf9c6b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"9a9af02e90277c6bae84e5d44b1ef50646e994c3d76cb949bdbe8353c047e53c9cd4b388debe0b25869fc7a946","nonce":"fcfb60594fe00e94cdf9c6bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"6092ea545f8fabe92ddfa48da8707f1ed4942aec78245e27682019490376def1e9afaf2d47bc353aa7e710dade","nonce":"fcfb60594fe00e94cdf9c6ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"b1e4ebd3a5e7b76cb508579abd88abf77a5c4877fc982965fed7c6e62dd31794f1642d72d72161fc4af4a5cec0","nonce":"fcfb60594fe00e94cdf9c6b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"c16d864fc90aa91339e49cbe1377e7a4ee54c7f32a1186289d6bbe77bb6463c84dfa51d91fb7bb97d7e4d4a517","nonce":"fcfb60594fe00e94cdf9c6b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"0627d857f2584f1c2a8bc870f520ff790cb5090a3ffc207f2adb5c33f4337ab45318e465c170140f45beab4f36","nonce":"fcfb60594fe00e94cdf9c6b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"a60a6103b682e5972a099af630f9e32e2e310b6c7b3367c91eee86db3f64c0ef48fcf30a90530fa476cf670463","nonce":"fcfb60594fe00e94cdf9c6b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"4e5ad3becde866294e8bb7c0f0ca9b22701e89f5588170d6e37b63ba09ae04432a0d493df43743cdb0342c4a7f","nonce":"fcfb60594fe00e94cdf9c6b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"25913b024234957ed2451e1391696d607f394e41023fc5d86cce5e8356713c237c3d8e310daa73783586098e1e","nonce":"fcfb60594fe00e94cdf9c6b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"9b14326cfc3ddfb6d7a0d7464c4a9be19b38859804d10755727e09d61d2d68913aac154aea6f1d8733f1fd0511","nonce":"fcfb60594fe00e94cdf9c6b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"dcc25bf7cc7b2e2e770c84bc007efb9dd5e7f10d273d656b1f7476e3edba9d097c270ae85bd9d89f6d79da6a52","nonce":"fcfb60594fe00e94cdf9c6b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"ec37ce6aa32a5e627348d6875ea04a06138731e479f40241d86bf5b4ee23eebb4bd0c9c3c4b7b4ed2b892ebbad","nonce":"fcfb60594fe00e94cdf9c6ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"982f8338b866c366e850d7d55333e2356b52a09de77951bd00fc5d6963e0fd34c6735bf4f1ade6ae3946913a65","nonce":"fcfb60594fe00e94cdf9c6ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"6ddf1f35243bfb4646404aed215b19101bcf10beee7143506bf587870c8a65da5dacc572303f16f71cd3823641","nonce":"fcfb60594fe00e94cdf9c6af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"84b1051b0177368046376302cd83116488409dc37f14d4aca041f74b323d246b2db4e8c1ee101ac2617920fd0d","nonce":"fcfb60594fe00e94cdf9c6ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"409f9f4c11b72b1bdf5c83f9b21d49f816eda5e0dae76f6e8c790b8c1c6558be2c8deecaf803212925c4596cac","nonce":"fcfb60594fe00e94cdf9c6a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"e3f21d241391b9a726def60fbb890fa3ea1432aae8c9d2842da50a9008513005d1281f359b2c5bceba0634fc50","nonce":"fcfb60594fe00e94cdf9c6a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"0da3016169a68562f39eb2acd2bad7c5cc84e9ac9e4ba85b682b0c4e78614cc145c4cacbbdd74cde93fc4acda1","nonce":"fcfb60594fe00e94cdf9c6ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"de44e8d6b876c3c515ba8fc41929a3cc3138a44827b4a7b4ea03cdb4284751443dab61ea1c576ce9938a985cc3","nonce":"fcfb60594fe00e94cdf9c6aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"06b45144aafc0c1b0c2221aa8f2a377ffae3251ed64f696bfe37f42fc112d52122ac8f3a0b36de7a2cc289876e","nonce":"fcfb60594fe00e94cdf9c6a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"b576e092269245a7dae1cad25051d7f785f6ec0b159f5871256b860f3f993ceffe419bb065e6deafb639ebb2f5","nonce":"fcfb60594fe00e94cdf9c6a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"2dee3f04a975bf7bde13aba64b81dd428b6e57f2af5b3afb7e480b00eeefdc23e4aa9283d9558e3f238577b17d","nonce":"fcfb60594fe00e94cdf9c6a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"bedb0c906710ec041634a2569001d51358288de2cf9dfe7939709a9c64179782ae6aedc7b3f4976deb92e17f6d","nonce":"fcfb60594fe00e94cdf9c6a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"a4527031a226e1f2869c95346922cbe56345aac94a0609461ce46dd04cae39c47498ce3f9ce4460ca4924b5bcf","nonce":"fcfb60594fe00e94cdf9c6a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"7be31b2ba99a05318b6d7b84e60fffe849594a615bb30edd49d6665d51b6ff9878defe6a380dd35a6debc6661b","nonce":"fcfb60594fe00e94cdf9c6a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"073ab884469ce409242ad3ff52101205c37ea88c4b02b18e0a5ccdc926eee0ed7292e3bd6f9c63534023ad39cf","nonce":"fcfb60594fe00e94cdf9c6a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"8115d05b105609c6ebf4226bb3e553e0b787766456a2fb6941cfadc63474986a3466fa7af12108d82eff89280e","nonce":"fcfb60594fe00e94cdf9c6a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"2aa62d3849cb6c03e95a9009c8c6f7e072274b4076679105dacf030d6d276f6fbdea600299882c2a294e8f8f40","nonce":"fcfb60594fe00e94cdf9c65d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"a60171721331ae089ff0399cd882b21b47ee3211f2ec647f10756403eb2151c7d9e3fb14fd16d111ad0aefe194","nonce":"fcfb60594fe00e94cdf9c65c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"2e4ccaf6d1d85d44d10d880109ea50fc708b3ef6d1eca91a3a129a50b1c4ba869bc8014f987eaf0c8ef15dbe36","nonce":"fcfb60594fe00e94cdf9c65f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"148cbcd0fea723fa6195d1ca01b4d2b7fb010b130d56895943c8dafcbaf0630c6583e355c3d209e63fd6f5e265","nonce":"fcfb60594fe00e94cdf9c65e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"e0b65f82aa506a6e5b7b81280754478189d6d29c584cb3a88e96e8b6b34548422dfb4b1f3d3b63e66704de55a4","nonce":"fcfb60594fe00e94cdf9c659","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"ac76db3324ec0072719d19e4826d6ca6235609d2cd9d8bec8a6d91801bd8c0ca96b9f469f1d7e2237bb09c8c06","nonce":"fcfb60594fe00e94cdf9c658","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"cb99c49f21548241cc9cd4eaa00c0b394f2c8aad3af8fc2267c938cc681c68d600eecdb636b815dfeaa3da6bd8","nonce":"fcfb60594fe00e94cdf9c65b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"15b339c092633862e88b83d1fa3a9e043f8e21248cba7e9d6ea1a1f493692f3de0b41f3406b7be267a24fda625","nonce":"fcfb60594fe00e94cdf9c65a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"49fd392eb43645cad1b661341ae4b013f4f6179d3e28c9b29045a3ccb2d4412b59b50f2e13b2ac271259e63a78","nonce":"fcfb60594fe00e94cdf9c655","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"46646de6cf186261d60714bcfff517aa0963d82289b5e55be7cef98d474766964fe1deb38af789f6afa5cf0234","nonce":"fcfb60594fe00e94cdf9c654","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"7a79a7ca4d9fb5892fc094a65b96bc1052839109451bb399d121ae342b266df8aee721f2067cf1e58265f378f7","nonce":"fcfb60594fe00e94cdf9c657","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"df0ebe91af42d82adb5c9f390fa66084444f2ae89503d2ae0901fe09bed335b86c6fcefa79d98fafe739e5d3bf","nonce":"fcfb60594fe00e94cdf9c656","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"0396ff92e434bb899f9c1498fb01748e4bdbd22918a0f5eed0c6af26b6561a3c66f30cb9a67275705df8974968","nonce":"fcfb60594fe00e94cdf9c651","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"864cc5a3166f6f0018c3b68f77425bb77fa0173e6e8319042ca09e4d29918628f292cb475cc97bf512a143a242","nonce":"fcfb60594fe00e94cdf9c650","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"e6820bfa8352a1ff2446c62a23ea9189f6b4724983e4f8e149c24cd408dccc64b7ff187f836500727c16dfa68a","nonce":"fcfb60594fe00e94cdf9c653","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"9e703f644539e4355a8882ddc3c2bd8484b145f5b110ab824a3d009f3f7a35a568b2308b077086266efff7aa27","nonce":"fcfb60594fe00e94cdf9c652","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"c74800e0ae09f29d1fe32f4ceef0214560325b2a35883644be9fbb248e398270abbe37bc1bc3e98bc7489a36dc","nonce":"fcfb60594fe00e94cdf9c64d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"28e87deb72b1630238d0bd1d74343fc0778c560f6e13afb41467d230ff50dc6af6862ab8130e7a62a6c20b5aa3","nonce":"fcfb60594fe00e94cdf9c64c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"48877a32df959c01ce514705a27473d66797750a01385ec8e2311eb6d22dcd3f5c026b00ca64251401511c6a0a","nonce":"fcfb60594fe00e94cdf9c64f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"4ddd7880e94dc012b888889c249d7cd4cfabc621da8293df3ca39b36d1695e5ec7495a452b2c37095bef887d39","nonce":"fcfb60594fe00e94cdf9c64e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"b51f5a893022ebddbea4fc1ba6ae0ceac7bdab802e804863c1a49ddd78f9c025aeed910ff9d01fec6800f0c06d","nonce":"fcfb60594fe00e94cdf9c649","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"72d3e759bb599f690f3ecca2f689100c9cae74d5566298d0fdbd8deead8f59c1f5563e1c2010c45e628405ec42","nonce":"fcfb60594fe00e94cdf9c648","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"eea55dd6e3e7708605ca1191cbe89980246e0acd0aa081f2513b89fc375ae7513a982bfb0ba6dce70b5d69f321","nonce":"fcfb60594fe00e94cdf9c64b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"81ef9adc7f76b20c9ec115f7c7b65d2bd7d58dc9bc0a514c739a0f8e99b6be587a8d5194eda97a89b6e46e0042","nonce":"fcfb60594fe00e94cdf9c64a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"6ac5a6ba9e899b4bcd13a8bf17432f9a61c1c0eca3765df1af1de317c1310334fd2cd71f38401856b59f13157a","nonce":"fcfb60594fe00e94cdf9c645","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"412b8bded19a999dd5eb53f994671b66639d170d674f7e67a491d746b9476c2da5716b3bd2ceb989af13ceeda4","nonce":"fcfb60594fe00e94cdf9c644","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"f60fce146dfc7f396e8b853ffb05bbd4acf6b7f8b7124b45baf2129e97ac4845e228a657146b36d510deb16787","nonce":"fcfb60594fe00e94cdf9c647","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"860597e7b97b0d9013efcbc2c843c1c02de46c5ae9f06c2949abf25ee4c4a2eadbc06d266913db5aebb7765b2f","nonce":"fcfb60594fe00e94cdf9c646","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"7d89d5eebf5ab1a28b442e232aa0a432a496ea1699f25bd11b13880e4636e658f3a573f60d948fb3540a9d7ef2","nonce":"fcfb60594fe00e94cdf9c641","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"bf5da49e56dc1cf442b89df651da218ebc8563e6cc64989b7440036bae64d76caab9b446db690f67ab3bab91da","nonce":"fcfb60594fe00e94cdf9c640","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"89bfed3d7184837e4b1243adf5994f6223bd538bed11e682c261e18d3c4f1b7a4b1aa19bcd430f59b01b557a6a","nonce":"fcfb60594fe00e94cdf9c643","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"1ed03a7ff9a81dde8570fb422b6c525afd1421beb811c802403d833cbada4b40c4338eb3fa57b2a8e864e9540a","nonce":"fcfb60594fe00e94cdf9c642","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"9238f9863cb2aa13f04bd7b60a204bd1237731802cbc0026cb9a8bb17bb690ea00674b64d374e9b0b5ef2f7c2f","nonce":"fcfb60594fe00e94cdf9c67d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"0c8fe24b446ab64cd631fdd636e90443b9f2a2a00adb49cdc805b0b34daab70b414da36a82fb31029c760774c0","nonce":"fcfb60594fe00e94cdf9c67c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"836114be399e98b5d9195d150608940a8e2d8752865f4e5d9dadf57491b8045c33fa745de3648fa02004a5ef4e","nonce":"fcfb60594fe00e94cdf9c67f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"ab7681314f02b383a7bd8efd8f13fb6caca4d8389fa7bce4ca5b9ac1e1a6b8d474338adea393053682b59fe75b","nonce":"fcfb60594fe00e94cdf9c67e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"f45dc95a1a25b5059ec41399b48aa460ead4069a01bdcf4ab24325490acdf541c49c61a1049094c06255b942ee","nonce":"fcfb60594fe00e94cdf9c679","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"cae8b1ebca74f93176502f9147b59c394cf6e45d5bed5dc02e73ef749dca37a666919e02054027edbbd82b1534","nonce":"fcfb60594fe00e94cdf9c678","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"57cec511beef945f2e1548850b8e71e8b43c2fae1bf5af12d94ada40794583f6b126b0b2d6095a27a541bc2d6b","nonce":"fcfb60594fe00e94cdf9c67b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"92ee128180435d7543eafe5cca6ae5917d6da1e3e093ce42a11011cdc4499554e52b84abc52700838c25cde50b","nonce":"fcfb60594fe00e94cdf9c67a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"a6434cfa3cb1200b5cd69af3792777961769f7cb52a5630e89cb7c8f0311654ae522b4e99d4dda191cd9b07ab4","nonce":"fcfb60594fe00e94cdf9c675","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"51c341c3d03879bad45ee29ab9342f055ba7f02b1ef1a8e43ed5f8568989f2c3e88f8c62e0c65f2d85963bc3e7","nonce":"fcfb60594fe00e94cdf9c674","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"ff78a0def2970866005b41c83cf7e887ad0606d6b0fd7618ce6c37ad95cead3f95c533eabf3fe9918622878be7","nonce":"fcfb60594fe00e94cdf9c677","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"644751ec637fbb0d0dbba1aa49a699c14fde0befefedc2dc864e1f085c2a60705e00321e6887dff1e4f9b196b3","nonce":"fcfb60594fe00e94cdf9c676","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"d87af7826db2334452aa3c2d3fc0675342243c6ddd7f4480bfb49199dfcbe646d030298dde1e02f44dadbba3df","nonce":"fcfb60594fe00e94cdf9c671","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"346a5c4e99cd5488aae8b53a75a49904956514880d57b0b10030e0000f98d1372f2b07d21187b0738de7fa1106","nonce":"fcfb60594fe00e94cdf9c670","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"d9247da0f6e5b038c7ce8a29cd28f168ff1147f6ab125ede9ba022f747964e2338e621e62d8dfe9dee2507d289","nonce":"fcfb60594fe00e94cdf9c673","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"a4df36bc5ecc23ba2d8a5981b7867e3745c62ef54ff2e1aa66f4e2e8b2c531099195969dad67e07e72b8319f7e","nonce":"fcfb60594fe00e94cdf9c672","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"71df230ca40e2cf87344e1b277ee4dcb54030a380eb15496622c188510a62928a22db494a8515a15d246268f04","nonce":"fcfb60594fe00e94cdf9c66d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"bac3b706eeaf6358a86fedde14ba654cbd27907bf1a1e673157377925af1233384da23aafea66d685bd6a40e5e","nonce":"fcfb60594fe00e94cdf9c66c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"a2973a198399328acbc7275811371a2a6ca7daa057912291a4f6a30194463c1f5e5c2ac7910495da5b82c830e0","nonce":"fcfb60594fe00e94cdf9c66f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"210cf3d843515e44bae90528828737918a0e54dd98c67f0deddc1e6bcc476e8ed5e0a967534f59bca529cab947","nonce":"fcfb60594fe00e94cdf9c66e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"933f861f53d5282a984d752842549b628e83b05cdf5f66803c1d4618233f040e6f89bda57d53121d99e1ba8428","nonce":"fcfb60594fe00e94cdf9c669","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"437a6c5aacb7b8c8d33dc1f07690d7496b0a198e1c70959afde57fe71b9750ff7dceda08d5f174c46a1bcac3dd","nonce":"fcfb60594fe00e94cdf9c668","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"c4364a3a728c2b033da5997da0a2cc35de25a66e561668bc7c53bd20283d24ad56c034fc41b00d465b01b366b4","nonce":"fcfb60594fe00e94cdf9c66b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"0b3a708bb94c697cc7e5ba8c04a6da7f43ad4a27a65a0eb9a8c1eb409b982b67299b7acca4ee62c902fe98a60b","nonce":"fcfb60594fe00e94cdf9c66a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"ce8d45bba837c115fc1b157bad91b24228ace2e5ea8f7978973c93156578d621035085267c27efaf8ad710e57b","nonce":"fcfb60594fe00e94cdf9c665","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"8f0091d92086ec724f31c7befbb9c8f9623d357810804690b411a769388937876fa1c941cd7133af39bd38a289","nonce":"fcfb60594fe00e94cdf9c664","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"575a38ace9be0be89e74db21ee90facd491fc1aa40d15df30fb55d9efb9bffbb0e590841fb757feff8f03e114c","nonce":"fcfb60594fe00e94cdf9c667","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"b539a1b7af56339aa10125318be638e0ef4134c1cbd2bddeeb64a9453cf6aba8f70a2589a95877b10dc1869f5b","nonce":"fcfb60594fe00e94cdf9c666","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"54e16776d9dbf18af0c9113f909f85cdee01c0f5230ed939d06a688caf9f0b0332449f9093a5163bf52bc8f2c7","nonce":"fcfb60594fe00e94cdf9c661","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"ccc2871186deeeeb6e4a438fe6487570a8d4330c1d65759f9e4644d0a75b09fc261df49d8974a63abd7e045c7e","nonce":"fcfb60594fe00e94cdf9c660","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"bdd2dda6ca1d3220b93e29c1044a00e73dfafd58c30771f81d1a2baa699c8764616e1c5cb6d721a07f6161ec58","nonce":"fcfb60594fe00e94cdf9c663","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"9547fa63d5d26440bd7d67f632ac8de785b71af685011ce6e7355905717f67abb73c68dd50764cda14ca7ef0d2","nonce":"fcfb60594fe00e94cdf9c662","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"99f7581389bb43678d01d23ebd89c538dc48c8d2d7379ef96c583b562f54eeab401d047f6aff48f8972a8cc15e","nonce":"fcfb60594fe00e94cdf9c61d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"7c0c35f232ad1139552cd5422b5693475f93e9615ad7fd758ac0edbc17ec02d0db34db08649e9d004927ee6aca","nonce":"fcfb60594fe00e94cdf9c61c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"dea3f772d9dfc8626c9c521c69788d6446b988381a4e0545d44ab489e92ed0ebbefdc7e7eddb4d62fc93947e1a","nonce":"fcfb60594fe00e94cdf9c61f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"5e87830202efb1343f992e505b5c9d202f8783ab3e4177ae093ddd4aafaec8f0e5cbd7148cb6c0e5488df68579","nonce":"fcfb60594fe00e94cdf9c61e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"5f9c29a7fcf199dee2f23a939e1cab2ccc891c724df5ffd963b3af73f1063f99064662495f41e9322b294b1a71","nonce":"fcfb60594fe00e94cdf9c619","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"8f9ea5171c726ca6ec38347a4983fb8c5006b844e849c5966c875279479bc99de46766fe236405358ef2744b7f","nonce":"fcfb60594fe00e94cdf9c618","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"a42f59637d7535f51b794bf093275d5ac2b60893b428abeb9a3c0d11f0fb92727c8b39d64a9c565e3cb36e6839","nonce":"fcfb60594fe00e94cdf9c61b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"a97df5c422de42ffb18582d79b92f461a46d243f06e8702911a2deb8c60dbb62bddd7613686dd613afad66a7e9","nonce":"fcfb60594fe00e94cdf9c61a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"fd0d6ba2b8b893dcdc26a3227780322aeacc9813c9b78034982f89148e6884f612ff76382b8e555db776e28a13","nonce":"fcfb60594fe00e94cdf9c615","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"2a544d511cc301eff739ea43cc43a3cd8ca43a228871902731d567219132c76f992563986fda6eac3e7096240f","nonce":"fcfb60594fe00e94cdf9c614","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"02cc92c00eab2e0131429feeca5a7e9b2a2e98ecbe84c68ce85a045363f24b02c9373980d83a493df570a2a9ae","nonce":"fcfb60594fe00e94cdf9c617","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"4581c3d3a731b3e28a6c8be477d069f928613e5d896d00249be100c717a24400f34212ef7a3a4b851f865608dc","nonce":"fcfb60594fe00e94cdf9c616","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"a51bf390c22e1c22308b399cf2efbcd0ee1cca1bc75ee811c39f85e635b0879d1d28fc245a7cafc58c834cd3b7","nonce":"fcfb60594fe00e94cdf9c611","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"42c33fcdae73e9150d3ed0383396d000308df37a8cb9e0337cc9d19b94e558490670043672eaf4d0bb92257c97","nonce":"fcfb60594fe00e94cdf9c610","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"bc0c43bd237c330eb5683f2e33186cc22fd114d6e85c54cfec9ac5d117f2245e5428e091eb41501a99959197ef","nonce":"fcfb60594fe00e94cdf9c613","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"325ee6373b4993d8ff1cae75de9ef4b66ea51484d7528676c2ebcbe57534d939775768e151a4948362badf409f","nonce":"fcfb60594fe00e94cdf9c612","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"1b7d674fe5aa1fda4ccdf60243190cc5dfe528d3dcf5c447bde559808085e0aa6590f2bcb275e7122666b1c59a","nonce":"fcfb60594fe00e94cdf9c60d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"8e6db37c0e46fbc67bba63e523109513c590003c77a30ece439258c77823e48c361fba4a1fdf3d92daaca5fa07","nonce":"fcfb60594fe00e94cdf9c60c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"c2d4e9e5566070bf7bc6d9bbf84eba7ff3c8821475526b89226d7b0a9c0bad33bf92f669f92a0a49a0a2ce59e4","nonce":"fcfb60594fe00e94cdf9c60f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"64f1c24dc3701240bd2417f2c31c9920cd74ef058f062301c957cd06cd26000f2928dfd1db47daab2546b26729","nonce":"fcfb60594fe00e94cdf9c60e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"68ac3e02b152cdd2262d608e4ca51da2ba4297a551f58e54a894c8fa409118440ddb6ba2f1e2b3e594e28be3d2","nonce":"fcfb60594fe00e94cdf9c609","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"d02825f972413f1d0c7c6ab68380d426c136aa38fc75a3927d5fa5ca2f821075504b4c9c0d5ed70177061a34de","nonce":"fcfb60594fe00e94cdf9c608","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"334857fbc33151fcbd02151d4ddbf1c4cd71a9ec65ad4cbfa30d21facb7467d1f242e824c376b5125f41cdecbd","nonce":"fcfb60594fe00e94cdf9c60b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"5ec4621dfc060e48e8de0a6b08023620f99181efaa1644d427b39ed5da8ebfc0dec1efe9385973c253f0bf633d","nonce":"fcfb60594fe00e94cdf9c60a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"18c6f601f597da0d87f0eface8ecd14764a06b8be8fbdd64638d51004d379a2edafb121508603de4bfd9feab20","nonce":"fcfb60594fe00e94cdf9c605","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"f163cc51a35bd1b4b16c19fe0bff8340ab5fd309495f6a4508dd0141423edf6e5ae85b99adde51f90ea336a7c5","nonce":"fcfb60594fe00e94cdf9c604","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"6e540c05cb8098a669aa8491e17b72b5f5178128563482cea07c3d4e93b7bb7c2a1850cc1b650c960686e8083e","nonce":"fcfb60594fe00e94cdf9c607","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"64489b88860a63ea02723dc796cf8e9a63e359a82a8f23903739d75abe254fd9856b8e8f13b61f0c0698e83cb9","nonce":"fcfb60594fe00e94cdf9c606","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"9ba44d0b57203fdcbafa6312986be748c52518d60ae4eccbfa559808993d9952bcbafc146ad244aed71234f7ab","nonce":"fcfb60594fe00e94cdf9c601","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"fba03776131186e998fe24d195b9b333db480baa54e9687411017284321b62196cbcb9a0dd20a5076720765b55","nonce":"fcfb60594fe00e94cdf9c600","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"0b79227247f0058ed49c85b43754de53988f263010bda625e57bcad4824f120fc6fae12a293293243846d683d8","nonce":"fcfb60594fe00e94cdf9c603","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"7a532d8c0a3e6747715322790fcef892b86ebc2f742bf9481749af893565032303a626d2b0afe7a0cfaaa9ecb4","nonce":"fcfb60594fe00e94cdf9c602","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"1ab201471135cac52209476813d43877b612a1c014e08f20c0fec7c6f2ce9e06a1c5bd10d797f2c3f31b9c3806","nonce":"fcfb60594fe00e94cdf9c63d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"087a879edd0b1120d90d72ebba1b1d4233635c19daad5b8ceded0c9560ee666e06cf65c576fb5875d8000eacef","nonce":"fcfb60594fe00e94cdf9c63c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"3ae1dfbd1df27bcc718156da023154f865c192583d7d30baa2204096c71e7a9d209308de767c96595b903c559f","nonce":"fcfb60594fe00e94cdf9c63f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"87e51a688993544366a740f95ce300b60e763861c36e8ec4cafd105e56c2b8529dc3543bab8a14a44df37efcda","nonce":"fcfb60594fe00e94cdf9c63e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"e0d227c50265832f66d2e717c7b1f471c362b1221df88b40a084fe7477d444bf7461101fa75cffefeed3f0dcc2","nonce":"fcfb60594fe00e94cdf9c639","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"e562f5e0b31cd9c386eadd602cea39b146470226800de3353aa5343736e247f8cfe196fd141b2512c92d74e30d","nonce":"fcfb60594fe00e94cdf9c638","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"8b35a484371b2b2b25e8f07e3b93f0585212f30458ffe1a97809de1c9ff190d66ee51c5e842da99efb139f67b9","nonce":"fcfb60594fe00e94cdf9c63b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"171d0482692aaa8c2c4a0cc304c94e173e52134216c0c273e3361c2b22f0c6a50c3c8bb8f83f197894f3f18c9f","nonce":"fcfb60594fe00e94cdf9c63a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"d55b7e47a7de8683453bad793845810ebfd811cbe1cfcca284ba65b156c7509aea0fec9b84ba09ae8c1b50f387","nonce":"fcfb60594fe00e94cdf9c635","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"c5194bbcedc0fdb8dcc5a460c3e767df780643063829f23e0d15833e34fba9e74f1b1a511852f4c9b5953f4199","nonce":"fcfb60594fe00e94cdf9c634","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"980d567178ecab40e2f6c8a2a404a6ec0d201bb56bb880c4ce643b9d3ed10a0f626d5f35dff57f4cc1c4e1717c","nonce":"fcfb60594fe00e94cdf9c637","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"986cc85c4e329a16b60e3c2116e41303b8b0b4475ec0dbbf20829aac9ee4596cb4047dd7d296b1cf5d2590091b","nonce":"fcfb60594fe00e94cdf9c636","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"110f81797dd768eb2b7d29d90f40f347d713d63c17284c2df755d51bffa4babc246830a86b204809d3cf123f11","nonce":"fcfb60594fe00e94cdf9c631","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"67a05ba76863a7edd8ad21081e0f3238b8b7feb3e1edd067ee5f71d0f2ffaac385019a1ec2a8ab4913cd6d09f1","nonce":"fcfb60594fe00e94cdf9c630","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"d1ea97611fdc47c2cbeb80afdffe0bbcad19a7ede2080ccf61890c2c6c0a4fdbdf6f5d4e50d7ead6126ae9163c","nonce":"fcfb60594fe00e94cdf9c633","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"ba574c18abe45cca3f32c35dd008f8e082277acd70806c246501e98fc6cd12207ba32acfa259b335741a2d2591","nonce":"fcfb60594fe00e94cdf9c632","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"50a35ef31cbb426b358d1451c645003680f7864e354ada41af0e8867153bef3b2076fde6af154db1118a858cba","nonce":"fcfb60594fe00e94cdf9c62d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"c0d0ef66deb6529e67a092c730a78939a58f171ca240b0f7900fd7e3b65b2e464cf84716dbc36266f6d8bc0b85","nonce":"fcfb60594fe00e94cdf9c62c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"0e6cf64fd3a72bd24dfa1bb9b22caf37d2c03fd86f6330b71e636197b8bbb9843a444e9595519ae48e0a65b1b7","nonce":"fcfb60594fe00e94cdf9c62f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"273b63db371ad91f56bbcc519148f75bfc04ad0e902598125e2b76a1ea5454746c21736312af2e69eafe3201c4","nonce":"fcfb60594fe00e94cdf9c62e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"27949edd5c5de9fd66db8cc4327d60655e7dd8901041b773f3ba48f3cca291acb24c8199e27bc08b2f4edfb702","nonce":"fcfb60594fe00e94cdf9c629","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"f9acf38a1751c93f389cb26d189d306691bb5bf4423ef8ab5725eead68b977744f10ab8887253747efee8ec7a4","nonce":"fcfb60594fe00e94cdf9c628","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"836830df6ed3625e4c1a946115b244a88699e5af378123a718088f9823911decc04d692287188836269851dede","nonce":"fcfb60594fe00e94cdf9c62b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"169b08185c9fe660f5461647515cf9300202c1145b19676df7b0c7100a802150a631ed915392bdfb17c296afe6","nonce":"fcfb60594fe00e94cdf9c62a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"5375af70f57925dd8b8a3f273fee667bfc013355abb791e00b4dff5a0917d836900bfc51755f6319a19be2e1f6","nonce":"fcfb60594fe00e94cdf9c625","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"03d22e84e2276584139e013c7fff59315ef6eaef564ff72ae66f0c6d99bad38daf01154d20661b345e2ba7dedf","nonce":"fcfb60594fe00e94cdf9c624","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"9d240ed4fc458fa6bd0599d3a119b3ebcb0fff9b6f4ba9c22cdfc5f517bbf8f85bbbf8a2aa94410640cf96410b","nonce":"fcfb60594fe00e94cdf9c627","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"4ec2a378bd4bcc62584d820f21715934a5f7edaccb240dd3e20fff8a0c4bcef2c408936f06857e5a34c1045159","nonce":"fcfb60594fe00e94cdf9c626","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"7bb8681d4bef37271cdbd88f084e77b691f48febdc7a76a258cd58dda1e9b02f456ceb8fa91d0942e60acf9977","nonce":"fcfb60594fe00e94cdf9c621","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"e84384f6a021539a202455ab0235705fa0a8482637d28073c1848c8c82c13f01e9b5f932cc1bcc4418747ac21f","nonce":"fcfb60594fe00e94cdf9c620","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"d611911e225d16bff029c5344a3588a7cde7a52283da15fa9291db720ab65a839eb7d8beceb1536251981ea506","nonce":"fcfb60594fe00e94cdf9c623","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"fafd4faea1a177f25d3f85accf292d2be2746a1b106192c1461850ec8584be207919122d81b6c2899f02750e43","nonce":"fcfb60594fe00e94cdf9c622","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"d6fb9d278c5df2c14ec332f9551009ae9f4b78b720cc9033716c4173252eca385dbc354a7565267b4ee03b4d55","nonce":"fcfb60594fe00e94cdf9c7dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"120087ee96548707ef0eba9fe68f0925fa9d1d221632c33b211d7fc913867601"},{"exporter_context":"00","L":32,"exported_value":"8f4eaaeb0f01b8ebafbba55a85f838d17d869feb63059e22836958b178ea995f"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"aaaa40af965f55ce2b7861b1aa62879036312fa5d46eb547e357db365ab1d5cb"}]},{"mode":1,"kem_id":16,"kdf_id":3,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"f7e6d1f0ebe3ee5a0eddd5f41a52dfebece43ae49db668fad6221af81007f6d2","ikmE":"4acff5be963190e0f0be753b479932fc1e45d6c5f16e103a9c97c5b58daef289","skRm":"feed6a56da6617c1e37e81b919aa209f77e5671052e3fa15a1f3477a0f6e3b4d","skEm":"7a598fabb8a10ce376ea86eb851f5f9a1e6e5ed2ada4c19a5d6b997f130f8ec3","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"04bbce653220ead2f82b535bf894bb6ef696144c26429b8acfa085b9ba9452e7cc7f7153e1505ae8f4a2170ee5726e0d453ceb22ec7fd3760d950beefda8bacb7d","pkEm":"04486d0833be2c61894a72882277a6351e530cd45b0dfede32975b1527a55bfc39f2e258cdd72d8e07e5aa835adea91ab16ae8b38f1aec30e52b2bbb4bcb84fa15","enc":"04486d0833be2c61894a72882277a6351e530cd45b0dfede32975b1527a55bfc39f2e258cdd72d8e07e5aa835adea91ab16ae8b38f1aec30e52b2bbb4bcb84fa15","shared_secret":"2c77982deaff007ed25fbe32d26f32ad483a88bd429c87097befc8648b4d19c2","key_schedule_context":"0141db1e5b07a041a0eeada5439a3f724a79fee39919f2c964570e3bd4ae296e728d0672b77f6d53fde449bfc9c0c24f0b899abadffa161b5bd14bd99c0b5586da0da9817afa84fe836a2afb21fe34bee379586120ef91d5c0432c32bb1d1d6dc7923282892f781147d97bd9e353465a35023868db7b5c0fa7a73b1ee212161f04","secret":"fda06122bf67e380bd5c6e946f7f9a04950a25b943e7585e5da8c407492e3490f9da7783cc8f57c4555a6372da36e8203b8f83523c1d3119ac8614e76f8ea6c4","key":"e0dadbc65a5a4bb19aa8f62965cf3944c00fc55ad74cb9538c878d0295f30c5f","base_nonce":"9c6858cd30c3e7b478aa14fe","exporter_secret":"85775e2240d301c8dd321b2e4f9730bd1964dc2567643924df41e1abcecdc3b679ac9573237d4a956b0265420496593d88c887675be6c5e1b9577f0d3ece784c","encryptions":[{"aad":"436f756e742d30","ciphertext":"5ac5f5293f18c01e96188033e2de9fe98c71c5633f3b2ed9b14209fe5e1bcd60a03a84cf5fb055ef5996cdea65","nonce":"9c6858cd30c3e7b478aa14fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"8c8b24cadfb584e67e4c7b6cb6dc200d79926cbd633f31118c62d9feff4a7b8d83a14e758764b219a2e732b6cc","nonce":"9c6858cd30c3e7b478aa14ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"720c97198fb1123827472a5d22ab643cc13ab962a6a37b59e76e627b4b2242287c01fa2194718f358d39af749f","nonce":"9c6858cd30c3e7b478aa14fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"0ee15b215e03ac97491ca336cc36b127e18ca3f089080583c0ed4dc11957c6e6b6198d45e0df1c10f7a782ae5e","nonce":"9c6858cd30c3e7b478aa14fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"6a91260533a1fc8905148ffef069658520241103dde6b83b1c4684851b2b51a9d417b05345bef19a966cb9670b","nonce":"9c6858cd30c3e7b478aa14fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"b1ea590cb73de82c79020947e6549225c58cc3ba71034d70ae07b6d06f808eb00b52d59a843ba077152b76963b","nonce":"9c6858cd30c3e7b478aa14fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"273a51fdf094e3821e228559212e7b2dc84a6eed09d4e3b6fe81d0fed137bf1cc88559ae6a122372f8a9ea44eb","nonce":"9c6858cd30c3e7b478aa14f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"c2b3b8329d60183f92a38f589d8b468e6766ea1221f9e28b540e1828a69772328307cd8e72b14e69d04353c0e9","nonce":"9c6858cd30c3e7b478aa14f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"d67bc7019a5d054f736d8b24b8ae83ee1854a782f36dba4970d2a0d8e72bdd61756042dacd27c15221b44445e5","nonce":"9c6858cd30c3e7b478aa14f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"b6a4cd83039e02983d24babff36d1d4f9645e76ad84921e8548f0b635c99b1f654b2a1d00d0a25788c948e9cf7","nonce":"9c6858cd30c3e7b478aa14f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"736bc624cff9e2a92567ded9414e77fde4e128024d22f6c7287cab7defdc8bbf6ae3b55f902904ffc1f6ef566a","nonce":"9c6858cd30c3e7b478aa14f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"cf015f7addfbaf37f08f531f62cfe2237872e31d63710d98a20d92c1dd3a105c7276dc629cd6e66fe931f18a51","nonce":"9c6858cd30c3e7b478aa14f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"f1282ff128a3bb39bf08034ce97933ac6830e4753e47d58903aab96b969cc27c87f95a09a673831fde858dc624","nonce":"9c6858cd30c3e7b478aa14f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"e34b9ca295f216fcd97e8bc58d41af7a737cd23413956cec4adfe65d3268810e1e34ce2100bffffe767c542e5c","nonce":"9c6858cd30c3e7b478aa14f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"45f6d85a053c5affacbdd95129e5863b54e7a4425688ed23b9df0dc10d003b325defdc86bfd2db68bc37de2eef","nonce":"9c6858cd30c3e7b478aa14f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"41a10dac3b8e38d004d64384e930634070266d9cadc796b9456e362984d84ee3f4cdd97468ad441af2fdccd2b2","nonce":"9c6858cd30c3e7b478aa14f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"a6d03ffc976d581fae6c4969d0862a410ea64cc0dc4fbc0686e1217dfd34b4189d2737e10fcfcb5d8922ccec5a","nonce":"9c6858cd30c3e7b478aa14ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"2eb6893d20d823740c8301914cc8bb9bd154e6ec79dd654514267cc291bb9e1886c162e29e10fb3169ab5aead5","nonce":"9c6858cd30c3e7b478aa14ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"763a668eb1f40c9257811092ffbf88a3bbcc1712a3f6284e9a8f2168c52829ff3cf987a1ab83914d823182fae0","nonce":"9c6858cd30c3e7b478aa14ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"03c8fadbc938b84cd2a16b321553b96e86fe99e4c50b44916d8810740926d09df0b440a07dd4fb05d509896ba0","nonce":"9c6858cd30c3e7b478aa14ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"408eea326893809998d5ce2a3d0436f31b54d88af5f2d4aac29cfee04686132eefd6fc21df6152b1f5773a3f77","nonce":"9c6858cd30c3e7b478aa14ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"bcba137f8efc3874ff9857f7defd8d8f6fac539ff6113ec10b869f007fa803d7912f7735fb2918ec523b6aadea","nonce":"9c6858cd30c3e7b478aa14eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"d515de13a22a0b174b845ad7189c85536853d944c48100ed718105dc97dc71d9a2400d1b4d07e4d85a88bb1143","nonce":"9c6858cd30c3e7b478aa14e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"93332726fc91f906e5c551119f62a5a2945a13f3c3985912111ceaf007bf5cd269f3e4aad58ff847b7b680776c","nonce":"9c6858cd30c3e7b478aa14e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"35e5550f75bb97ff0f3cd209f31421d91b1facc3fd6f35c95dfa1587d20abcf12dbc41f5817d7fe5c737ed1ebb","nonce":"9c6858cd30c3e7b478aa14e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"2ac3a80032cb6ec60f43b28794f83c579cf7349043c5f38c12cb5492fccdc92e0cd9a6f71dc4fe7c777476f728","nonce":"9c6858cd30c3e7b478aa14e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"f48cb69b9d078bd1de95487ded7ff306b2e5694bbd11f0122ec29168b13b4caea4e8820a354656081c3d087fec","nonce":"9c6858cd30c3e7b478aa14e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"b07db4c53864cf4bb0710873d57b38db1faa8e1d393c8f8faf7e0d36bd967058b7377684d7f420d875849f02bc","nonce":"9c6858cd30c3e7b478aa14e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"b14910f104fd80f72a3532f4e65ed43127b840d681e0cc19a3d2924f4144bbd9f91fcf3b4009fb25917edd0615","nonce":"9c6858cd30c3e7b478aa14e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"6983ec815b6d17b693b96b49bf28a07f971eb0cb59a93848819caed0339cb0a1c88f7837f6023aab3c838aa92a","nonce":"9c6858cd30c3e7b478aa14e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"70146b488195eee87007d8a3989c115ee6e8c28c13d20e238c77c68301fb25ba13026417176d9cd8ea73d70a8f","nonce":"9c6858cd30c3e7b478aa14e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"aad3f91577d30e4a1cb3c3f15383d627e742b2f34e642bbbe4766b4a62d06f8706e88ccb40a5c16b5175aa3c9b","nonce":"9c6858cd30c3e7b478aa14e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"8742238647a2b3977dcc02a5cdbd38f19a71a072f3f3892d6e06e771119b1ca722bfc154b143c733a6c8ab8f25","nonce":"9c6858cd30c3e7b478aa14de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"109f858bb01047257bd877cf832c16fb72e7638ce25522d454e4fb3f4a08e5c527e2c0079c819d8ddc158d9b40","nonce":"9c6858cd30c3e7b478aa14df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"b6d5e50c96e87079518cf858996d68d1ad05bc04918f651cbfbff75f2a5bb96c32e208399b7028b268cac1dce7","nonce":"9c6858cd30c3e7b478aa14dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"6d471da155f455fec94bec60b2e420881615dd3d139f88b35a28cb8d069488abd543442a1f7dc6ec2675d52b9c","nonce":"9c6858cd30c3e7b478aa14dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"3848c1fe9aeafc700249a33ad4c8f6b2c36606087dce59bf7c79e41dc9bf1291cf83b096050a27ea1c4b7597dd","nonce":"9c6858cd30c3e7b478aa14da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"798c11a8e238d737925c16a8c04e56194a161b319638999bf1c15fe986431fa17e59f07eae306335c2ea8d488d","nonce":"9c6858cd30c3e7b478aa14db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"871657dae9e47dcca46be92229d6b6f6f70b226cd2085cdd470238b09f31e889b84d21903f99dd6f42bbcfbabd","nonce":"9c6858cd30c3e7b478aa14d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"309e372d4e5d2ebd5115c50803eb48dbbc0cbedd942dfe01964fd9107102383cb57a5f2cad6c03f60dadc6d99b","nonce":"9c6858cd30c3e7b478aa14d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"3274c273784b6e9191816419f25e393767d730a109d5992b3db67d5ff9981a7e5b66315e2f0b8ee68ef1c2b197","nonce":"9c6858cd30c3e7b478aa14d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"a2a0deaa4f9c4fe758e7ac9e67d00f714285aea69fd827b7b4db675f5262996e3ca60a2c536e03c60d0dada1a6","nonce":"9c6858cd30c3e7b478aa14d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"305ab373bed5cf764856fcc3631f734d6085db02dbf2aabaa2b399e5f3938fdfa3a5bfa5812c05e9ff6d15f224","nonce":"9c6858cd30c3e7b478aa14d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"938b3de9f458ae707a90d482c2f1834df5a7459c9ca34f417fe958208e0d0e476bad7bf07e09c97aa5a2ffca54","nonce":"9c6858cd30c3e7b478aa14d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"355c8945dc7ef5b934c204c808e98d34b60d7b8c0cb12faf9e3b1fef7fe48864b8e4bfd9d87c7459476b214772","nonce":"9c6858cd30c3e7b478aa14d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"5abe019b197171cf9d6f6774a3de4ce55a53791612753b21b3fc8be9f808d2130fd7fd311fce17386b9fad76f4","nonce":"9c6858cd30c3e7b478aa14d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"b0a59f4b2f9f712a114e4687cfe1f10321a0f309a3a93cc1260a5def3bf44a7fc60be1e9f98457180368ff4afb","nonce":"9c6858cd30c3e7b478aa14d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"be0da57bbddeb3bbfb3b3383a97bb7ce1c84d3847da523b81a1fefbb475a4e9044f28270f49f784efce0c26002","nonce":"9c6858cd30c3e7b478aa14d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"6b1c63d4bb277b351768859aafbd2ed2ead706ea9e7c80cdfc879f6507dc416bf63fe5c369669627018181b4f4","nonce":"9c6858cd30c3e7b478aa14ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"e6b1cb5bf77002f3825d7860fd9763d1f7ba0efe5e83d88a28195f4840d309918fe1e3cc51733e99bb39ce4b78","nonce":"9c6858cd30c3e7b478aa14cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"c92a24dbfb9be467e23660300ee9bc50f7ab52a32907783645d3220e730c921a32848132411b9590acd540a100","nonce":"9c6858cd30c3e7b478aa14cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"deef52693edb4a9b9219493a18646c62966cdc692536267f80b0d2d112fdff23d54e98cc8c27e8abef9a4a5c97","nonce":"9c6858cd30c3e7b478aa14cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"4e35c2c82f6762997605d38ea05a9da1f8042210516f1d792122928d49a4a2fd8e9f9741e394d3be9a5256b094","nonce":"9c6858cd30c3e7b478aa14ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"ec2491fab95700b3e57361218b986825720017d556a759caf5dad3358c7b736646d8e29b6fbdff9e59017d363b","nonce":"9c6858cd30c3e7b478aa14cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"89682fc345f4d81d3e5a26fb8ce63df0255fa793967f2bc5dc22ae55880c9bae498c46c8fe950c20c3f1231226","nonce":"9c6858cd30c3e7b478aa14c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"78f7200cf988a4fab0b8bbaa56cc8e26b578dce3809ce132032e1ee72cf94a7f4ecadf6814c4de85ffb9e9baf8","nonce":"9c6858cd30c3e7b478aa14c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"b22716a0a9f034eba9df5e8b22e34464ef25846f75db9bbc6e57b1a577c1fc5e77f839646cd463f648bc5f1ecd","nonce":"9c6858cd30c3e7b478aa14c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"d2e45bfd6fe797a6487f8f73794ba67d9001fead2aafb5ada25e72a64786c232e86d6985d902e12084af6b8389","nonce":"9c6858cd30c3e7b478aa14c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"d74595b8af22adf773a61e897c0687d16a7328fedb918cda3d2c7b15ce64f5f1d4a1b9d6ca941e5036297258a3","nonce":"9c6858cd30c3e7b478aa14c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"74183cd1b9bd481625bc52880ec5ce4732a96e17ba0f97b50936c5706503dee12448778df5161fd37fbf0aebee","nonce":"9c6858cd30c3e7b478aa14c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"f2949a59bbf7af2d1133174edd7248c2f7265d146e29814cb0bd860c427605f380fc2bc261a143c33de9f2b75e","nonce":"9c6858cd30c3e7b478aa14c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"7ba32459d5fcdc9c7167e6e680b8841bdf46697cdc5eb8d7acdf00e20dc2125a3acf8f9bd7e1f5c844cef4e77e","nonce":"9c6858cd30c3e7b478aa14c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"a2c93f4653146db1033eb771bee276c89e7f34c57e48848081e31e6d8d5f284977cd2acce529280c558a951d82","nonce":"9c6858cd30c3e7b478aa14c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"9b7b71650259e8f918dbde2c5dafbb5dd845e21b8ffd8522450ce18c6704983d890172c7fe41eaf0a791e695ee","nonce":"9c6858cd30c3e7b478aa14c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"a1eafe4b712c64972ecbde53f94d935ccabcce0f9c7e04a9835c832b7e15b40626358cb5988e958653ee7efdd2","nonce":"9c6858cd30c3e7b478aa14be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"646f6df2b4fca373a9aee3d70625e9dedc1d58fa484893233eb050b852ef5e20fb2e2adbd9f6bc53cc185c43aa","nonce":"9c6858cd30c3e7b478aa14bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"3f9b91da367a934496d04a9db43e52b4bf0fd2974da38a087e0d5acec127b1931cfdfd22b6baa099161479b0a9","nonce":"9c6858cd30c3e7b478aa14bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"244518a1e7f4b39115978f61da52e5c779b1f62b6f484957900a48606571a68273cc81887607864495cd9a35fd","nonce":"9c6858cd30c3e7b478aa14bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"60d15969f7b8c7221e6387026ccef750b0e6c1412f55295885761407834383f2cd5be1a42769cfe7e56bc5f145","nonce":"9c6858cd30c3e7b478aa14ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"94f417e4d83963b02a74af669ec1e166a028cc1c15e92ff92f3c4af1e650e00a447c6ced71229d1899899f8977","nonce":"9c6858cd30c3e7b478aa14bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"a6c92a5e26c1ba2a484aaebe90b031f13c93b4505e52a2d5c779750f823d8340b2a86db8c21b3c9e036de72f1a","nonce":"9c6858cd30c3e7b478aa14b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"f416047bc8d168b6c3d59243451ec91996cca7b205a17cc698029801ae1eabe173f09a980efefd37fa1ac90a40","nonce":"9c6858cd30c3e7b478aa14b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"c3c58d7fdb03df0c95e493acc7c73c3da3ef895c825094d47b0487ecf44873857725ff867d62c880e5f40006c5","nonce":"9c6858cd30c3e7b478aa14b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"516a17115d82b9993bf116c008f2f871437ba70112a5de7e1a74ccd085c0e72816e6e8fa97af1b16a80889cec7","nonce":"9c6858cd30c3e7b478aa14b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"1f325df1b491b86d2cfb0b296679233dba395c2590f4ff57c41407b32218fb1c7b8dfb93bb472e85d567856634","nonce":"9c6858cd30c3e7b478aa14b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"1daedaaf583927f67e0a25cc45c9fab3c433b2887c4a64c61a343f5488063dcbdc9a103f1c5c44637f5810a370","nonce":"9c6858cd30c3e7b478aa14b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"ad8c2072d6f4fbede42d8e5023d196d6b97d1754bab0c5e79017177acc9db9dfeb5aedcf3a739ebac2eb830911","nonce":"9c6858cd30c3e7b478aa14b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"2cc20c4c801c2aaf38f41af5bdf7ecdd2689a7076cc445d65f391e84c32f5a011d91b96d9e66097a3c10229488","nonce":"9c6858cd30c3e7b478aa14b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"4dc3a59267cb4527f3d0c142c6ae9ef478c3a6f1dd9202edb1d4f6cce0e62926ffa58ce711f8331b1d86ae70af","nonce":"9c6858cd30c3e7b478aa14b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"ca9194c298eee008beb41698cfc45086b84ce74d1afa8ac7bd7f1be369ad93be4b98a316eac27c8bac81bbead3","nonce":"9c6858cd30c3e7b478aa14b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"5510fd5c8494f47106a2dc6ff1f550f5a5126785e26876a58e4a10ea0b9611421de8b00b32951130b225ac0faa","nonce":"9c6858cd30c3e7b478aa14ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"7c0256111b9a3443c47ae2e6145184282b81702112457ffeb0fdc150dedf4aa85845624bb8f52dc50863a0644c","nonce":"9c6858cd30c3e7b478aa14af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"6217eb04c5748052559345117458b10f4006a19531a1fd2d89f31fcbc514ad035b2b90745c6dd402beae713cfe","nonce":"9c6858cd30c3e7b478aa14ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"9babf230e62db5aae8c269df2f8e067f3be7d47f170cfe00e177574fabb7b63cd8db0b3caeffc3ddc4a83f3390","nonce":"9c6858cd30c3e7b478aa14ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"e7f0dd4e8503f87142d6632312d7611754741106e05fcfabd3ec5d0f2caf9c35947905157ad75dbfa1e63dc366","nonce":"9c6858cd30c3e7b478aa14aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"3a2cf4176927cc32bfcc3f9ffc5c545ee017579a0e58bdb826c7b61534a086ef8d37c997dcf84413107f38cea6","nonce":"9c6858cd30c3e7b478aa14ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"9d8ab44a7651d9056a0dde1efcb48ac73c033ce1efeea893422d0a5e541d2882316c73e935b06f3ff00c26f0c8","nonce":"9c6858cd30c3e7b478aa14a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"eda55fde34df6eb2afe4ea523cf1f3b98d8fc2bf26418b7eae0f19bab1464050ec593e1c5c17789ecec7667734","nonce":"9c6858cd30c3e7b478aa14a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"bf714bdb45c84ac9939475f8c04f0622b306e12d0b629ad074c0a8ceae17b9d0c25ce3c10d4d348da052856f67","nonce":"9c6858cd30c3e7b478aa14a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"a9a9dccbb673fa94324653e99b6541b63b5d6eca7dba492529663485f285dd48f2629d6810799380931439eb22","nonce":"9c6858cd30c3e7b478aa14a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"6c83f516235b6c25e44ce4c440b9269391fbbb1f587ad4f9b1ad3d344e0f597beaa133c43e59c99d5362f37a89","nonce":"9c6858cd30c3e7b478aa14a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"59309e45937dbe502f8a30aa054f814a5df9c944dee048ef6eb53d516839f4fa684dbd0479f64ec5c5fc8a1271","nonce":"9c6858cd30c3e7b478aa14a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"8ffd4c501409ab23035ecf2993949a6bdc2d3003e5ce4f7424cd8967b0d01915f80eafaf52e654f1044c4c758e","nonce":"9c6858cd30c3e7b478aa14a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"67dbcae559c2ce7791e85bc70f0b9be15341a4ed841aac4c0a916d21335d2741aa311dae952520a1dd637d7ab6","nonce":"9c6858cd30c3e7b478aa14a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"e1b493e7b5d15042248dd7f14e3dd1391b3b423bfecc2b111179363a797e95ac2ddcdb973b23a65289e0fb2cad","nonce":"9c6858cd30c3e7b478aa14a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"139a8049612374f8caf91d458f87e62ba9cd0f36b2c98c3372ee9f4c35a25ba0c83f19ebc5816babb4bfa1668b","nonce":"9c6858cd30c3e7b478aa14a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"a49244810c9f7bb9c6f4834d3ff34153eb537d81fd1dca64c1943d4dee8cf0d6bab0f79c0b6c9867e2b5e3b2fd","nonce":"9c6858cd30c3e7b478aa149e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"970cddfb981387f83a4f2d9afdce3c8e8ab6b9c2cd17a78ffbcf49b7075fd74831b9ec965465b0782eab5413ca","nonce":"9c6858cd30c3e7b478aa149f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"709fd7b13d4f2568788500ddb98c1030d6c8975878ac1f8dbfc3101066c64b6d64ab70c5b57501cd5e284a7533","nonce":"9c6858cd30c3e7b478aa149c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"6d0e87c96cc0f84ca6633442338aa16c91e542a3b78bd604182b8f4871a2962ef92e9bad4f144e7e2a8c698a5e","nonce":"9c6858cd30c3e7b478aa149d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"ca4c82dd4c710383e90f8f3897909981520ed5d79f4cbb5277cde489b070ef45f56c5a133073a898d6cf75be10","nonce":"9c6858cd30c3e7b478aa149a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"bfb52390411b7eb85477ce627042aa341b7a88e20fbb4f61953a91885f00ec8a99921fa374b17d0e3f23100dda","nonce":"9c6858cd30c3e7b478aa149b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"fa16b4432f7f0beebb840b5bedb9ca42a0a855d69456eeb2aa3df5e04e1708907a98f7caa6b058a2968d9984c5","nonce":"9c6858cd30c3e7b478aa1498","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"5c4287c67caf7a6aff1b768b5be8523a743893df28d72bf77a808088100ad57490d39b21807dd6f66958a4c604","nonce":"9c6858cd30c3e7b478aa1499","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"236dc08fa626d3578f0feb9fd9c96acdf101b77bbd17414ff16fd58279b9c7f98ac6ac1430d215d2ae8c6a0e7e","nonce":"9c6858cd30c3e7b478aa1496","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"d19747629c59d2a47955c1d466d998e26a9baef083e2f7925613eaa3ee1f2c661b55f5a7d4601c39b5314f6209","nonce":"9c6858cd30c3e7b478aa1497","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"47a9560f534d979b536bb74dc6279463fd7faf4739276f78646d8c9aa4a0d3d58c9f7217a6c378eb3cd649efcc","nonce":"9c6858cd30c3e7b478aa1494","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"2f53c89c5e9a497c5bc59d1d747bc7149fc9ca522b873a4b6afdfe4778e5167631bd7d17b8d52d593285eded5e","nonce":"9c6858cd30c3e7b478aa1495","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"1fc9bae891d047a627f26740c3e251ae98750adba19b70d5e1bd5bc47735122f03b6f4e3a09d94f3a342dc93a4","nonce":"9c6858cd30c3e7b478aa1492","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"2daf0f9e93ae8e4965932875e1db08daeaf2cb5eb556ce9e5078fdadb09ee0067afa7c2ab03667b4680a91ed85","nonce":"9c6858cd30c3e7b478aa1493","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"9413999437334b2c649cba1e362025c347cc12dc7a53ea8abe80c02afb43aa0c54d63f0f0a8f8af08ae69d791b","nonce":"9c6858cd30c3e7b478aa1490","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"43f816e41be8d22a55e9e36339b2a9abd2da4c96dec077657b5abcee476dd233ded153249a0f2566864bec6236","nonce":"9c6858cd30c3e7b478aa1491","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"ebaec16f32fcc906508570b354b64449473cb7ef74b99b94e11faee75203b7c0743f23009c4439b6e75a121e68","nonce":"9c6858cd30c3e7b478aa148e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"58080e24e8a0e2c8ddd035ee78243ec3392d3d53bf663cb3b1d59c3dcb57db6c972fe7bb0e28caeb6d3e8aabbc","nonce":"9c6858cd30c3e7b478aa148f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"7885709f17b62d148dbc8495385e6b8a1ac02e52a466a9f8cb697b7d9b1d5c59a95d498a4e7aeaca0726760a2f","nonce":"9c6858cd30c3e7b478aa148c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"a671ccf9185f7730f119f8f015a7d7277550cc6dda769c83dbd5e553fdea1c2e815c6392050dfd8f259e5a8247","nonce":"9c6858cd30c3e7b478aa148d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"d04d08a70cb7e65c54ad62eafd9806b8d1c16454715de14b09056dc10a3322368ecaefb89b188d91ea15508ec9","nonce":"9c6858cd30c3e7b478aa148a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"c3ed0e9ff77b6da0e246bbedb7efba91cd4bd914abe4c9e74d19fb7bd84fbed002a144a974eb4edf52822ed73d","nonce":"9c6858cd30c3e7b478aa148b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"1aa6d24563ff0b3a4dc5b952c1cd2e64e225ec8fa8585e28ab17ef8195aef9ca881dc38a79e80c4c590c723f29","nonce":"9c6858cd30c3e7b478aa1488","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"983f4669cd2159cac228f49f87cb6293d20c1abf7b2d0df049b017a1b1b9594a5e99dcea7ea53a80e572f9f96e","nonce":"9c6858cd30c3e7b478aa1489","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"f551a135d21b9920b0656e6b1a972d562a2a1d1ca2bce40de7ef146f686c908c04bec2994e4f9e139c1f72648c","nonce":"9c6858cd30c3e7b478aa1486","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"d2fde3530a79334133cce80d3e0d9addd22a5d2ca29608350399bda8c96a83462c614f57481c7341b67cc8d1e2","nonce":"9c6858cd30c3e7b478aa1487","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"2c49ac04b8cf06cd2e0ee195361750d9a885f0471eb3b6770976a80eded1b02a67e3bbf718d401ba1f978ca8bb","nonce":"9c6858cd30c3e7b478aa1484","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"3f97ca1d5bc512d45152143d1e1ad4693f16180262a26122c3357d080e130e8d793bd7ad0d45fbefc200655726","nonce":"9c6858cd30c3e7b478aa1485","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"885de21d46ca3745223335c5b90e661f755c1607fcb3f98833bb340d732ab7755375222bcba55c7faa5d5c8aa6","nonce":"9c6858cd30c3e7b478aa1482","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"2e312a39facb25f6ed46b9042da820ac8c10f0c21e7200696bbf6aa84b4dd32a9b07d877f70e683da54bf932e5","nonce":"9c6858cd30c3e7b478aa1483","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"b186825d1c0400167bb0afacc30a53c77a1b7df8e8966b81509def1e2823d5637649aa7c4a46dea3451a8b8f05","nonce":"9c6858cd30c3e7b478aa1480","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"13b12556fac8ad75c0ed33e6bd61fa4aff1813d52328bbcb61e5a2d74250433341fef4d79b01a26e61c5ee953b","nonce":"9c6858cd30c3e7b478aa1481","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"73f8f4aa01502c4642e150033263daf89624752a12cb346636311a6ea70d4ac55e76e98903e3f03700d261197c","nonce":"9c6858cd30c3e7b478aa147e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"e0c6c33b3a8b5d7fa0d18387e7aba4a884b2ed717634893cf346f48aee8335a2e06222099e7e18ccebf2e09343","nonce":"9c6858cd30c3e7b478aa147f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"ee2442403be732c9b4155d918c21417c1fae815910a1f6b399dd53641f2a34bc3bda91c8ccf42fa1fbf104600b","nonce":"9c6858cd30c3e7b478aa147c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"6d33f939f49f0e516c35196569bdf828fff0d1d39242d7dcd02f47cff7f4cf61ed0c01366c3da8f7bfa598c1be","nonce":"9c6858cd30c3e7b478aa147d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"495490ef0118ff576ae7d377ac93af98a233ef68c73f9b46966b2b1d009a025e1861f127decbe7919dba156f0d","nonce":"9c6858cd30c3e7b478aa147a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"ee9bb5bda1db129f57dd3bc88e2e4c9a7c4e7f9c904eedf8a34014e576ba28a00a91489ecaadba43778997b86e","nonce":"9c6858cd30c3e7b478aa147b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"8abac0a8314e47e180ab3903f415bf57ce49202c5d31821da6ee754c7f8f160def322bc6cd1485df60f7a1b583","nonce":"9c6858cd30c3e7b478aa1478","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"a63cd82965ee7ec66776151a666950e99985099eadae15097d103123216b9a8e4f3f3c82dc456c1ee9b676296f","nonce":"9c6858cd30c3e7b478aa1479","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"d3100b19e53118ae3b37c93145df8a50a80b741b6408f07c3165090d2e2e3778c5c69256d5e6b6ae89c4ed33f6","nonce":"9c6858cd30c3e7b478aa1476","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"a75a82ca5bdb007f214e92b8eea0a81476c31a98a6bfb1630776a348cd16926b3736857ba354e3ad43aa3ec9b6","nonce":"9c6858cd30c3e7b478aa1477","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"d709aede3952ac54b0257d02ecfe28af8cf4255b0b28645a924ad30e66fda2104e88d9e55ab4e792e51e19a3ad","nonce":"9c6858cd30c3e7b478aa1474","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"db11d5abff0fb5865315bd652d682112a4b4818b1e8ebb5c531524885e5ea863e976b2fdf59195314ae867172e","nonce":"9c6858cd30c3e7b478aa1475","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"7fd8f0d33b0b414099c9fcc54c2a250866276f1cd67e7b361d44701533a602640ae0cfce090dcfdc3b9669b9cf","nonce":"9c6858cd30c3e7b478aa1472","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"47ace8983fda78dd7931c5f8d4a5b5a78add3241784d3c6ed66cbf1b3070562566d447d8f57401278f33f9e506","nonce":"9c6858cd30c3e7b478aa1473","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"fda5b31c7b77181cb2fbe9fad053ab19d6541fa815ffe7d63f9054011c235a452b02851091c9590a1c7e08663d","nonce":"9c6858cd30c3e7b478aa1470","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"1760cd2a43c40ab3466e06e9051882a225d6233f4abb04f996a81f54baa7df2f8daba04619ff47babac076b76f","nonce":"9c6858cd30c3e7b478aa1471","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"159370c96dfb05b6324a9b8349b65a1e9527c714d2270c00d75a56c80b5da9417679caf182da150c320c2346e5","nonce":"9c6858cd30c3e7b478aa146e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"d3b900dc6972945959f78d806165c8fef52a9d5255c2cf702a91546fdcbdb8a6b15350761eda411ace93e7dd43","nonce":"9c6858cd30c3e7b478aa146f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"2560acc09c6209f5f2c2538a82916667827e881544a90acc88ac3eadc1fee31da69411ad31202a3b6e51bec8cd","nonce":"9c6858cd30c3e7b478aa146c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"e9c9c00f5d847e0aa38f19894c997af69f9b5050367cb9dea9177615f0322a4d37850b75de00732644b8749681","nonce":"9c6858cd30c3e7b478aa146d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"49497c7cbe89494c8aaea9d9b56c4b1612b68cecce4615c541b91e43643505455dedb49349485698fc21d81703","nonce":"9c6858cd30c3e7b478aa146a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"5971b184f27e8b750b5ca2b21412ca6cbf5b76dc26f3574dabad56e3608ed7a5ca6b71f4156e8d7e18df967611","nonce":"9c6858cd30c3e7b478aa146b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"0bf6ca9ff8dd483b986e1313462ed31b74827b6183c63639e4a81319ee13d99c38d524bf08ffd8ac9f1d10d136","nonce":"9c6858cd30c3e7b478aa1468","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"94d22a920924987ae28b794dd6ec6affe44c8bc4673e33e2a1a141110d689f5d5a77af9d6ce3f456410ba9a07b","nonce":"9c6858cd30c3e7b478aa1469","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"a3d665fb762bff56ff363de51f2eafe9fc6a0a60e02ebadec76e6d7ae6e3c2b11fe609e643db53738e744e4188","nonce":"9c6858cd30c3e7b478aa1466","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"9d79895d07f15c69dfbeaffbbe93b9f0ac3cf4ad66b613c44644d190eb3db36245eebab0c8a527483520e90d56","nonce":"9c6858cd30c3e7b478aa1467","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"06531fb71edb44331521ddb5eb801b9ba584126414b7c381aaf5d13d07ec585dad5a8995362b5e9aa4cd242c9a","nonce":"9c6858cd30c3e7b478aa1464","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"aa5c486f88f1f1fd930042da263b699754fe5e07d4dbf42dd323f70b7cbbb04e85d186a9379e6134f6c77cf5ca","nonce":"9c6858cd30c3e7b478aa1465","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"1de2242acdfe4a0841c9a9ac31dc47882ed44b8a6ade386b1c3f640f544657b16186ed5405e08203a0aaec8921","nonce":"9c6858cd30c3e7b478aa1462","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"aff5636a675b627653d8346d28f7b69142c11dd5abc0fe25b6f0588f3be916396cb87bf0fef1f2e92c8a1c4488","nonce":"9c6858cd30c3e7b478aa1463","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"06cc22d38b195ccf5dd9ef1eca8677d16ed7b6ecfe3b0f2bcdfdef3f64700e984704390322e4052dd0558332f4","nonce":"9c6858cd30c3e7b478aa1460","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"f017576e17a46a513212bafe99494280c0539d592044ea85b02d71bda42d9784f0b8c273712db6810f8cb8bc2e","nonce":"9c6858cd30c3e7b478aa1461","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"233cafbba03aca00c02b2b9ee44afda6bebc6ec6d987e1f05e0b88b69192ad4d1b6af18eed687832495490aa1e","nonce":"9c6858cd30c3e7b478aa145e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"bad835967d0f4187f06d09046cec3e71d03af8c501c1047d751805493ae6a13fdea0a1917f0d6f11c8d6458c16","nonce":"9c6858cd30c3e7b478aa145f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"595ec6503a379eba8e8cd9b5342a343962cedab7d8b4f5bbab1d0423735d03e490751bcef4f5ab49048ef520d8","nonce":"9c6858cd30c3e7b478aa145c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"e664e3341da985f72a2bd01cd2c506b89320cc28bee493420803518a4733bd4add5252c9c073bdf5c118a2dc25","nonce":"9c6858cd30c3e7b478aa145d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"90555468fce95e66c750d1b98f692370580e7180b0e867625c1a18e22eb1eea700d928cea04d1d0512411df0ad","nonce":"9c6858cd30c3e7b478aa145a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"529b6a53ed8a70bd14570478bbde955f8e869d8380fbde6ac15ed24f8d95756597341234a8f40d2ee9c0e63ad1","nonce":"9c6858cd30c3e7b478aa145b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"8c752c6d70a7ba822535409755a6277e975bf2b8c6b483499ac11c88ba9dd2bed80a59979fd308cf3c51f2664a","nonce":"9c6858cd30c3e7b478aa1458","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"03c5bf21d058ad70568aa8342e5c6acf9f3967f156c866b7420b827e5c68ec94a353af6be1160b115300bb361a","nonce":"9c6858cd30c3e7b478aa1459","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"515c9de72b81ffbd4f527f557fa4c4a6a3a939d2bbdcaee910004d75c117a7b4c77df91f64f980b4858f96b16d","nonce":"9c6858cd30c3e7b478aa1456","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"6cc3c9859b669425df69f783254add110fd62adb5b135508e4ea74c3eefbfadc4c761aec2bf4fde8dd6572aca8","nonce":"9c6858cd30c3e7b478aa1457","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"d4102f9618bef55b7cfe5bd8efe97f8fb1304184eec887b10ed484318da2dd25504b451d3515cc76be2c01c6ac","nonce":"9c6858cd30c3e7b478aa1454","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"7fa2a3a51d442667492f02276d7601cee801d1dd0896363de0dc8b693352835a24321e7a3e8974ab42210cad2f","nonce":"9c6858cd30c3e7b478aa1455","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"fd98a5a8e8022e4b9e5bce4c28423fba858bb9ba9afc0820eb146c191251e93ad1388f5710830ee91bf61dac0d","nonce":"9c6858cd30c3e7b478aa1452","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"bc005ed2752e1cc11d63f3b82b1b328e41a14a60fe75980fe51a4f02ffd192a9c9c74b1495a334e15715ec7c02","nonce":"9c6858cd30c3e7b478aa1453","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"cdc47f7279760defb84d8a48fa7e4ea2d8772a58b804205c03384342d6771a78d171a21af419e43d49393b255d","nonce":"9c6858cd30c3e7b478aa1450","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"3793f0cdf0cfee27cc6741ab02b79d293d0e4b5f0f16dbe27c63185e8fc067f7eed4c1528a80e38adc493a1ed6","nonce":"9c6858cd30c3e7b478aa1451","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"6fed00c31f40202146bf282fa098f366a8d3152888ec84ca56b5d84ab641dd3ba33262e6273564c505afb8a6e7","nonce":"9c6858cd30c3e7b478aa144e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"a2c48368d1269938f8f055819b07d64c734b73329ab8b24798fea36f6bb3dfcae75acf492592c5224f499c6e76","nonce":"9c6858cd30c3e7b478aa144f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"2026b2016d6a0a61a49ca00e3afb5eaaa2246290f120204d2ffafbc1aa3d4cb578ff07d808c4fb5de3bc9b97ec","nonce":"9c6858cd30c3e7b478aa144c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"5fc8125cfebb561fa42a436683c12f10da44b9f4672becce36d51d8881af388861d0b25902bee6b8452c474565","nonce":"9c6858cd30c3e7b478aa144d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"d234e5525567a473c1586bef9332417c1d5a8153ba32470e0aaee7d401673ccda61e40ab0f703187284bd4d196","nonce":"9c6858cd30c3e7b478aa144a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"cc535b7c501fa50667c2c1dd6bca8f4c946604c37642a4c5f433cd3d630401a1b664fb3415a5fc0cc4c15b5ec6","nonce":"9c6858cd30c3e7b478aa144b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"620c70ae7c9915b3d2571e3182c619e202c857b047c42bf3df450b71ba44edbc633a13d62e64be830d4b86cd92","nonce":"9c6858cd30c3e7b478aa1448","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"c6186fbafec48d2e6edc6888b90b1f8d9509404f2c2478c9aec6756ce30164e2173d7abd6479a5eeb2d0787ec2","nonce":"9c6858cd30c3e7b478aa1449","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"eedf5ddf6f4daa154867e8dbdbb4f7b73c62ef7de54676d64d42cec4cc9c4cbf52f1c28dce0180b76503e7ba3b","nonce":"9c6858cd30c3e7b478aa1446","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"0acc5c0ef32abe0fdbded68f5e6141635ba26072a22fd1e7075e60badf3935ecdf64ee0cdc47b51b6b2697818d","nonce":"9c6858cd30c3e7b478aa1447","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"1e2efbce986b66b9748ee83c4be2e21e7b9cd7c68006bee57431afd9755aec017a242da88c3b62f6ec462e5b41","nonce":"9c6858cd30c3e7b478aa1444","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"3ca0dece71225750093d7168498da4e84b04f80cc97205dfbadcb7c571696c3793c9d290203b4552ec01621ec5","nonce":"9c6858cd30c3e7b478aa1445","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"69e312facc9dbc4875f3112f49ca268468eb4b008391deb3f8462d4b7014216b97462ab8ab144f8f3d15ee74ad","nonce":"9c6858cd30c3e7b478aa1442","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"cd9e8aa46d7b0c789fd60c6e523bc3e1edac4407146b07fc44909af14c532098961f389d8385b2bfd1b860bb69","nonce":"9c6858cd30c3e7b478aa1443","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"6d6369b7c4bdcbc3dac444c9f350a494aaaff6766bd78ecd262e14d9018b7fe353c3dea9443c6f31abd7bfb9a6","nonce":"9c6858cd30c3e7b478aa1440","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"b0d9430f7c7a521f3ce5925acb58329cd8dd8f025dd46d51de0f9557dc09d738dab0dea7bf87c37e644b0ceb0f","nonce":"9c6858cd30c3e7b478aa1441","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"e90831e10f191cb7a108dd12b89bb762e4ccc1c237893665153e65bbf5a953dd17a1d1818c322890c44ef780a6","nonce":"9c6858cd30c3e7b478aa143e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"ed738aea4d3d9f9cf81978dcce68058436c88803c47f1a925ce6300f28d871443e1559669b27e67a31796a9cc6","nonce":"9c6858cd30c3e7b478aa143f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"cbc44ddd1ab16442c8eda3454411e3436b443332faa679990fc54f0e0570f7dbbb5f51cf49c34ff253f064c996","nonce":"9c6858cd30c3e7b478aa143c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"36f9280a504827a7c577729fdd8015257b89ff8ebec4be71f4ce89b320cdf08261e6948da6c3bf23ba21de435c","nonce":"9c6858cd30c3e7b478aa143d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"17cca2cc542a4ad4c0308622d21bb8ac9635cc1cef2f6738581040ae64f83d7071de7294d47d6e4b670ac9aeae","nonce":"9c6858cd30c3e7b478aa143a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"48f6ff9fb7c7cadcf8f9a14cfd9b75b1f83037900de0b0a1052865fd07e246b4cc9b175de822c19f98e8db0dd7","nonce":"9c6858cd30c3e7b478aa143b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"c71500e277ecb186895433111c1facb9f70c6587eb64d354bba7590493a8f60f81baf8ae78083436900aa1ed87","nonce":"9c6858cd30c3e7b478aa1438","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"47fb48464c3200be6db247c7dd0d8d7e1186146965aa9d8fc1a14f8db829d86ab3eab5baf2622d7c457429215f","nonce":"9c6858cd30c3e7b478aa1439","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"57c692f69b778047805eb671e74a849eaf3cf4c9d1c22407fd24016d31dd2ee9424d89a280e49351b4b72c2b50","nonce":"9c6858cd30c3e7b478aa1436","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"91cf2ecb4171f88be42ac549e0813f2cc2f192f18659beb4d6715936b3cd76848167c2ac4d239c15d8e694be58","nonce":"9c6858cd30c3e7b478aa1437","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"7601713d50d5cbeb46757dc09e5f1bb5fce9dd37d95daafe81be6a8bbd705cbe3e6c3b03cc3d7854de541aaa1a","nonce":"9c6858cd30c3e7b478aa1434","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"07e1b49e31376978794036c6b76adefa4f4bca8036c79f50c0fd2725a7345f818e8204faa47a632a3fd74454ec","nonce":"9c6858cd30c3e7b478aa1435","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"878a115c05a24b1314a4223ec2bbc7ddea4f2c522357d45d7a0cad061447676a5f64b660ec3043451cb73b199c","nonce":"9c6858cd30c3e7b478aa1432","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"16d74c2e6d101158b30821b05846ff83ac62e3c43ec4abe7447827c891e26994cf587cbc8a356ae92649fcaa66","nonce":"9c6858cd30c3e7b478aa1433","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"a839fb87cfc81275cb7c1e69be5c7754101698aea1a1c3841ee5816a53835817a9177b763468b47ff65fd3d3ef","nonce":"9c6858cd30c3e7b478aa1430","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"70b3769e1ada29a151b943d1689b335471c26fde313889e3003e4a85d094e785ca97b55154f158da2d48d811c2","nonce":"9c6858cd30c3e7b478aa1431","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"1c5f498bd434c6781e09c390108d802c6a8d12243804d80e46769b8fe2ae8403b9a72ed917fa68ae98b7fc2b5a","nonce":"9c6858cd30c3e7b478aa142e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"f2b6f92e3709eb448496ba75d4b7b872e1abed385591751252885d27522cd85c69fdad675d3666cb5fac002391","nonce":"9c6858cd30c3e7b478aa142f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"328a5209e5ef926ad441f1f746cecfad9c479403f50f735a4590d76c9bd937eea16ccbd2acdef5c1b59a6a41bb","nonce":"9c6858cd30c3e7b478aa142c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"5917cff64bac8c205d0cc2cfbd395631b22494e8b3110dac4cdf035041b674e56057f1fde79bc241665ba2d345","nonce":"9c6858cd30c3e7b478aa142d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"2f5f22e371ca76407964b50050a487d891938a4ce08cd2fca824131880858247f402f3fac44d3f37f4efa29581","nonce":"9c6858cd30c3e7b478aa142a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"ac0c56a03ca4cc569c87026487413cf1bc84fe3e054048e7bd6681b662d3347c81f391aa4791276db39c70df83","nonce":"9c6858cd30c3e7b478aa142b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"f91d6a5a2959c63d28b1f2202252fe47afb255bcc78f92982cb8ed9c8e0f99fb0aaa757d9aff024b2b5333166c","nonce":"9c6858cd30c3e7b478aa1428","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"a887c905a0712bdd8b71338341ee6ef94058523258276e9bfb54adc96ac8cc0fcba6ba32f6782ee443cf4ca063","nonce":"9c6858cd30c3e7b478aa1429","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"5c6f5fd1fe90dacf4285cfaf477aa50a4cf69be02af4bbb57b619432bfd70a0e4058cacf817d6d90ad4669d9d2","nonce":"9c6858cd30c3e7b478aa1426","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"b209e502361e9af1ab069902cb300377431fdf1de6a3062e7439c19425807c136d2a202b467f8c0f5d96962d2a","nonce":"9c6858cd30c3e7b478aa1427","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"90d44b3edb96d0332f255dc73be6ff04ed42cb987187e5ed5abf1a39476f87739115c24b9906d6e872be632344","nonce":"9c6858cd30c3e7b478aa1424","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"06e2613d163407452bd33851ce163e3e64e065b392bbbea440f66d1d4900202e2ddef91f79a9672137b5b6fd9a","nonce":"9c6858cd30c3e7b478aa1425","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"8f2ba2a3c455a0e53b9a396ce42d9e824d13e1d8468caf65ab2793a55714f1c9e4ee207abbda808219ba8decc2","nonce":"9c6858cd30c3e7b478aa1422","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"a512a1304246fa30fce2df65de250a008a3adc6ba74a8f69849da6e7e5e2e4a664f99b25de44ac412c83c2ef36","nonce":"9c6858cd30c3e7b478aa1423","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"a31580022e4f07cc8e121cc61f36e93e086a5dfea18fe934dd2afcef425a0e25f4ce1ac8f3f2842a2182677a62","nonce":"9c6858cd30c3e7b478aa1420","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"2c8e23d02feaf23d81fe1116e57c08c3d285780103ff95797b69bd6ef0af563b8c142104ef267bf5d48c953d05","nonce":"9c6858cd30c3e7b478aa1421","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"1277b7509254034b8cd277bb0a1ed30b744792f4df7520b8020ab31db723f05a2da4aadf65ad9ded6251add7d4","nonce":"9c6858cd30c3e7b478aa141e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"1d98e475a6ef249b99336dd675c209eb6a39a54d5ea492cbdf4be517cbd6fb1c14f5bbca1e1a0fb98755e7f80b","nonce":"9c6858cd30c3e7b478aa141f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"c3a27d9dfadd3ac0fe8aef80f080a9170c0d96da3c1c68a7a11aed90e26765d0a57b8ef94cb2cd0d3881ef4f47","nonce":"9c6858cd30c3e7b478aa141c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"a9cd55393e5296ccce6f80094084d0ec446e4b17d2918a726fb8a25feae6d5d17c8cc715405a41e69795ff6e4f","nonce":"9c6858cd30c3e7b478aa141d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"41a3b055329e9a1eeb151432ee528e74f742becea232e164c5f63aa5735fcf1814253a8b1251df77008ebc2980","nonce":"9c6858cd30c3e7b478aa141a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"8b5bf116a3e40d910e87917c9a86a35b788c85f95c407f840a3efdadab91dd32d331e29a09ef5674b1ef1cf256","nonce":"9c6858cd30c3e7b478aa141b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"b94d30b2995d2d2dcf57282466dcad1ecba35c2fb4a7c7d5b114e17d7b8e4cb85d95f885354c2cf63898385aac","nonce":"9c6858cd30c3e7b478aa1418","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"f688a506c755530b937a8d8f417dadbfadb2910721098460036ac4a77cf506fb3c30b7397c2ee6954dadf88e4f","nonce":"9c6858cd30c3e7b478aa1419","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"649b2437f4c4dfc5192dbec270ece2e1317e2ea2282e57cfa77b1dd0a06d68e95a51207511104b1c6d80bfd061","nonce":"9c6858cd30c3e7b478aa1416","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"f9514b6c6bb893dd8c9026cead75019b6c1a3a6b0463a9b8996e71766d79a85c000870762c055254169d847bb1","nonce":"9c6858cd30c3e7b478aa1417","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"0364d17047e806f48c35a873c2718715f15217963c3fe555f7df016d21707eaf2407d7c37c7ac57f2d026a898d","nonce":"9c6858cd30c3e7b478aa1414","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"d5dd7643697dca47f147c515839f7160c3348384dc6a3589b5e0b93404ec9170b14b5dd99f46ef7b1da3a73555","nonce":"9c6858cd30c3e7b478aa1415","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"77deac63eeb5554fadf78e80ec109a92b83dd29f365cfbb23a5d41906d8bc061f51458ee14e68fee99538c46ec","nonce":"9c6858cd30c3e7b478aa1412","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"de64dcd3af89f215bcf5f92eb8a027866520bf62eab10af1f9b0733c6b239bfe305d6f12a47ea783d136f3e7c8","nonce":"9c6858cd30c3e7b478aa1413","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"ee17e3c39ff1a3f3cccd7309e71a25c1300b2f3f53fb24a9ca59befee8178c10c97ab997b3ca548b279c91ee7c","nonce":"9c6858cd30c3e7b478aa1410","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"262fa0726c01630be966f1bd98be2b7172be52b6f322b2d444f432f8749d47e17ac8564971ad54e805ad45980c","nonce":"9c6858cd30c3e7b478aa1411","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"80b71c0606c6ed16b2c3cf255a761603a090b9241909333da0e1a8459cb09799a965047b445a145371957a7508","nonce":"9c6858cd30c3e7b478aa140e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"0270707bc879cafa44c5b36fd0c8b7b7ed7a870362e20baf61d087afe4b98c8a796c56775946ce5129d4ed8399","nonce":"9c6858cd30c3e7b478aa140f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"329095f3cadc904eb358254d37127f1b83267ddcd92f4aed40288d4a5f8939bf34af7c99634c49b0891eb6961a","nonce":"9c6858cd30c3e7b478aa140c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"937140064785d2ba2e781f0d0e5e41277a8b0eaa63827c88915b441e3bff6990116a87f0d3d96326897925c9b3","nonce":"9c6858cd30c3e7b478aa140d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"072233997848009d29b382e933a9a7e8637a8dca0463d9419f78f4041a3109a80d0944deff51be5de06006ab30","nonce":"9c6858cd30c3e7b478aa140a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"72f9334532369bf0d9ac79f86a24864261c4cc692605d7e5ce30f647468b502f4bca9866047b99c31f49c336b6","nonce":"9c6858cd30c3e7b478aa140b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"435ef7496063e7f1ed113ebd6ddde643efeb6293f8fe08efa819d6f35e9de8afce9c0ac209f21b5b332eefd9bd","nonce":"9c6858cd30c3e7b478aa1408","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"9e5cf27f7ea482d1209ee7ecc2468e2fa05159f365d44a43478253203433dcebf9e87ba177dc5cf1ee6a8cb1b5","nonce":"9c6858cd30c3e7b478aa1409","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"1c22d54d556a1f0a19fa636e80d9c071d33452768fb0c2ba1475f326f9c7f75814a6b15c45a2ef9bcfd504ceea","nonce":"9c6858cd30c3e7b478aa1406","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"7867ddfa534b9057d3167ff2b8688e7145872022ac68f5314b283b8c3b6b81614e419e04d1dac1c5451ef79691","nonce":"9c6858cd30c3e7b478aa1407","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"3936f74e2595483011cbc13cc558ac619f823dec898bb8dea222fc561182aa0efb39031292c13c05a200cdd361","nonce":"9c6858cd30c3e7b478aa1404","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"78bdd58529fcd802da6284bf26f5cff6382a4960d733acc9dfa4657d59c31c684bcf30602bda6810b746830966","nonce":"9c6858cd30c3e7b478aa1405","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"1aa98d3eb6d7253e8b6a76fd7598706ef63e34e58679100a915e56b500eab8d25afb2f1a81717ec15a886dd93c","nonce":"9c6858cd30c3e7b478aa1402","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"8e4622f390c8b7bcd797b239398a0a18b5e5fa36bf379c3867b5d45135a0931988464f961f6db5f13c9f2c314f","nonce":"9c6858cd30c3e7b478aa1403","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"80854b0cb27e97241165f48b2d429a3584775249e1e9793dfa4b1be6e36345552738f0646fc3631db83de6f814","nonce":"9c6858cd30c3e7b478aa1400","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"d61debf1898541506ed1128fc754abeff1f86eb8df2d950f1021d099e4125256998a42d0179b46988ee4a13365","nonce":"9c6858cd30c3e7b478aa1401","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"4961b41418e4b4260fef2b23f1a29ea039b0ee599a3dce30728694968603fd10bdb85339c980c393019eebca4e","nonce":"9c6858cd30c3e7b478aa15fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"a35174da0a49a525791cd8f08022f896f4116b1f85ed6ce5bfeedff574e43183"},{"exporter_context":"00","L":32,"exported_value":"3179ed3ad11a3ba10698e5a1173102948b17efe5adced5a487d6c20217aa37c7"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"9085216a0cbdd2aec1d66dee4aacc4e9aac951e835ce01074d878c666c168204"}]},{"mode":2,"kem_id":16,"kdf_id":3,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"0e8a346ffc2c985bcaa2e2e3745175c35f4c25f9872440fd79bd78c776f47b7a","ikmS":"ea4220ad15a4450bb9f541ab25bf9ba220eb9cd1c75c05ca4746139416bda1e9","ikmE":"e2dfb90545281ca91ba71fb74e82668004a6cf65e3706261c89c756aec6123ed","skRm":"a334ce351443935d977d7bd19c353a66444a848b5b07299d68ca60ea2717ef32","skSm":"30144a4e09947fdc9ad205847bc8bbe6ed4a5c3d84894a512661d7734faad2e5","skEm":"d0fe2a04830086e9dc32db2338c18a2fda2958c002799a410fbbdc0154e924cb","pkRm":"044315359f91b0ea6bfa02415014f97b475ab2a86a9c97d293823a2eb6924826011daba124d425f02a7b884392b3aeadd0dd2feb621125fd084d4bc05ca19a62ff","pkSm":"0448901cacc801a4527e313a7cb2a6463e9167a5a7db56c89b87b5e14742ef0ab4236f6b650cdea335fa7e0441b5e8becf3bf387c8d1cf16fd08355d9141cb8b6c","pkEm":"046ca9b7f8af072605d7eab718cb15334c84017158031525f3edc1ad2573b59e3bf86007d416d0040cbf6f81d7d98b149cfbc06f4ac1231722c0b491b516b5a28a","enc":"046ca9b7f8af072605d7eab718cb15334c84017158031525f3edc1ad2573b59e3bf86007d416d0040cbf6f81d7d98b149cfbc06f4ac1231722c0b491b516b5a28a","shared_secret":"d3ce50b2230bec08d5f17ca0a5457b5a4cfcc35248ade714997c52a3e88f6251","key_schedule_context":"028af8c8585cbab503908a747f5b6e6facb58a8eb7d6aee84875f8e4fb97a6baba74330d080c6e518d29f18589d731ae505f746529747c9d25d75013d5f8f2f7280da9817afa84fe836a2afb21fe34bee379586120ef91d5c0432c32bb1d1d6dc7923282892f781147d97bd9e353465a35023868db7b5c0fa7a73b1ee212161f04","secret":"0edd0bbe6d1754d5550a5e0f478ea41d4f18d88133cb7b6b1cfa078de86091182b47839a8644331597ffbe029d1de17b8d1c47a8cd987b58c231cabbec67ce89","key":"cf40b9986eba3e99add5dac72567f9fd13d800042ae598c6c07b23112074de9c","base_nonce":"3cae83f2f7027d190a9ed1d4","exporter_secret":"3d30f80b9bb84a36ec24fadf928468a357d41573fc5137cc94759dcfbb5ab6b6300262a53c237820e94c894cc1cd6cca555e0e89e2b433578860ae914815fbb7","encryptions":[{"aad":"436f756e742d30","ciphertext":"efc6a1b8d40443badf38a967e75ff33bb5d10d98aff860bbdb83fa3c92696063cf0b1aea39db46d18eafd43241","nonce":"3cae83f2f7027d190a9ed1d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"28c59d8336506735ce407cebb5015f949c0af002d04067923c65d993e9e55015218b787e260e531a65c5cb6084","nonce":"3cae83f2f7027d190a9ed1d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"a710210d0f416ed9c3a2a366d0384f63ad37bd5fa0f85a401cef588bd8f5a0ed6dbe203a52430676f58d0a732e","nonce":"3cae83f2f7027d190a9ed1d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"d8e55bcf4096f123ae8b12ec81aac04d2f6b561e9e34c596055a027877ca8179caf4b0063c227f6ea84d6424cd","nonce":"3cae83f2f7027d190a9ed1d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"e6d57fbb3cdd2a2532fab423f7018e1976391f6f179024ef698353da3e70ffbc01f84c33d44c3385e12eccfd17","nonce":"3cae83f2f7027d190a9ed1d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"a9917a4d96b7276198921502687556b75d9ffb4f7c6a14776dffdd60276c56b4e3bc9458eaaf1b535ef642b54c","nonce":"3cae83f2f7027d190a9ed1d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"1caad6cf133c48d485bbfbc5671d70be34f7999c2603319ebc45a8f9b99497e67f6067ac39d2c31ae864fd8b68","nonce":"3cae83f2f7027d190a9ed1d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"51fead8ba98a22e6d850e2dc3fc3e0c95c465db4ce470a3256e9569b6046c23941138de5779f44ad4dcb92a5c3","nonce":"3cae83f2f7027d190a9ed1d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"3142e8a19340f47f2aa2e1057077340e9f4b5038608124be9fdcfeffa255a917a32db21ddccce8f8712011976e","nonce":"3cae83f2f7027d190a9ed1dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"d3bda0ae634b69929c98df099a2f2362aad4497ad845404b5630bf27abef270bdfa022c4593338c4ce3e2e4014","nonce":"3cae83f2f7027d190a9ed1dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"719f0b9ac21497be6c2df37c7b48e05fd55f7686e88f8237fb0f56bdf73de9dba1b2a16d11eb5c9f1f77626110","nonce":"3cae83f2f7027d190a9ed1de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"5f92e66e6d26907b9953510362f0430e45d25703ff18a95a3a866ddbed01e00d78a00e49d2bd65eef0fa404b03","nonce":"3cae83f2f7027d190a9ed1df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"f8130116d4c98e1e501beeeea9d8347fd994e3c55b4e6e5ccfe6abd4dd7843fb6c1a7316b19ce89c63cdaab6b6","nonce":"3cae83f2f7027d190a9ed1d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"d37534d61b0a2e12e059a028fd5d553b845960d6e905732dc96daeb6116c167769815e4245b3b980c699f25c3d","nonce":"3cae83f2f7027d190a9ed1d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"9b3ba2bfa4148880038033ebabf4af489ba666c9497c2caa64671d951ffdd1419e13bdb3f0e044f7735875ddf2","nonce":"3cae83f2f7027d190a9ed1da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"df23da1bc72147fb88e157f901a333a4f518ace1ba75c7509951b3e3637d3fb877ca1acf3de776e8b670b9d404","nonce":"3cae83f2f7027d190a9ed1db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"151857e2962b82e0d57a17797499c5dcc4c01442d9364833e5db5fd68f731e04e8489ca0c44731f63a8aeaa24e","nonce":"3cae83f2f7027d190a9ed1c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"e284f404d6ab0b86f0fd060b514b79abe8db26026301a0740dd69880197ac97f99d9ef9631ca71542008890289","nonce":"3cae83f2f7027d190a9ed1c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"5d0b408d6f0a9c06af306c774406c33490a988e6178b3871b33f0d14fcaf39dca3db385f2860ab105cbb9e4096","nonce":"3cae83f2f7027d190a9ed1c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"9020aaa6a831f7edf867e086126e46b4cc757ed87a6438f806d9753ff834b93fa47d8842127f826549fe0d1bc7","nonce":"3cae83f2f7027d190a9ed1c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"7963c138f6967f9a62c3eead9ae183f7a92bd5f3f2681952d495fa77524bfbe67493920d8eaf9ba473cf398d1d","nonce":"3cae83f2f7027d190a9ed1c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"1e69a4483fcd86f795a2f8c7e50799f2769572510294765376d26f2e21397941ae5d03f334b3ebcc9cbc5a5bba","nonce":"3cae83f2f7027d190a9ed1c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"029dafb12973f20bb53ee4421df24d494521370cfb7d1fcb44b69a15d2020d052798dd38745b1cdce99e9ad793","nonce":"3cae83f2f7027d190a9ed1c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"e52f5ea959b5c71518efc363005d5f5957d6cd6eca819de7b0f94c3bbe0507284c2a0048800b10bd50c1d82801","nonce":"3cae83f2f7027d190a9ed1c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"52cab74c87b746ff1da1c630beacef42ac3f1c4d45bc458b396fca23b549960f4ab3c6e64d03b99716d049dad8","nonce":"3cae83f2f7027d190a9ed1cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"32f3cbcf5c886917a1d074b096838c67a0170434f3366a3e0c6c3a6ee1b72b0251c8f3746ac156319b11ae4764","nonce":"3cae83f2f7027d190a9ed1cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"63be0fdd5b825d88f6568cb685e9c98a6c85d320161df26dc662cef6d5ddb2424a189759590d8fee8be128bce3","nonce":"3cae83f2f7027d190a9ed1ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"716e9cdd1e530ad202ef80dc50fa156336aab36044396a65e1351885c030ac5b82d5c683d71fe2b506e9f46839","nonce":"3cae83f2f7027d190a9ed1cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"1f60008da0d6ecaf7c1d578697afcbbb121b6547330d504694e759350de5b449c2933346e0346975a7434c5c2f","nonce":"3cae83f2f7027d190a9ed1c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"c1ee1e0d1a1b493f71d6fba47c887b2be6080460a7cfb6bf04013c3468cad815c270f9cd6a5ec3300c884375de","nonce":"3cae83f2f7027d190a9ed1c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"e920513352b364b8aa939db0bb55af4d038cb5f6b435ff6de19341132de4d38de386740d4c5467e477fb1182e7","nonce":"3cae83f2f7027d190a9ed1ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"f7407b17b296f680ecc35e5659c9c261a03f9d02178c200cea5287d0d4c1a839c6aee8e875879b1523508f4f8b","nonce":"3cae83f2f7027d190a9ed1cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"1b2b6fdab319eece4c52fa3628a65640f2a193e6ad9300ced88bd14f710147ca6835bece376e9a867815421db7","nonce":"3cae83f2f7027d190a9ed1f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"9fa952f7a523a65bb2e9c253687d1ca97ff12cddb085d8a88c87ba956cd75c57070dda62093ecedf604b287bfe","nonce":"3cae83f2f7027d190a9ed1f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"4e9142cf32938f6a405698383c653b704707d79b63caaa4c085ddc1ae1bc39670758987c8bf602080172527aa6","nonce":"3cae83f2f7027d190a9ed1f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"a834ce8931114063454ef295a7089c68eca8fd5a250773b12c41231c2e55daf951a4a1e4797c83915ef693242c","nonce":"3cae83f2f7027d190a9ed1f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"5db419d1db61e80203a8aa55158ba82e1f3cbc8ac5de3f544b00bff532aec432b54f35dfcc2b8111b0bdee1df1","nonce":"3cae83f2f7027d190a9ed1f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"8400a50b67e8195862c6e2ea3741c3f19e6588870bf0fdf78b4e27280aef310d9266a434427e0f47a1a782459a","nonce":"3cae83f2f7027d190a9ed1f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"2a2f86a82d17b6acec498a33af19369e4d2c5e30ca47926b89e6d9948a44b54559a7d637766438b2f414abe0f5","nonce":"3cae83f2f7027d190a9ed1f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"017b0617016ba8fb15ebe0dd6c65cf6c6ea4b95284ddfb5d90a396bb66351d1c2c993cb1aa0cc818d01ee2e996","nonce":"3cae83f2f7027d190a9ed1f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"77079a12559054b4726f79effa7626b7de9d3511e1cd0ee8bf255547047a1b8d696d4e7815212bc6540a3c54dd","nonce":"3cae83f2f7027d190a9ed1fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"1c9eff6fc38741077f26ae17f84c0ba82838925fd2fbfa5e34433605ca3723a722658f5da5b65eb0a3a026bdc4","nonce":"3cae83f2f7027d190a9ed1fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"9d266bab66686cfb353f0e34f9c6712715bb539d2b92f408dead4a0b7e1d89d6741fd9764e50aa41769d424a91","nonce":"3cae83f2f7027d190a9ed1fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"c26c6ff9d89e5fd691770b4af4ea4b2b913fee7c8ed7590119c80e570608e8830e0df57957effe868c47b94dac","nonce":"3cae83f2f7027d190a9ed1ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"83c82a77cbdeeedce8b557e0494dcae6b4039f0653a23f4fdff3e53d7ddfd1fb22112bcce021091ebcc4a4bedb","nonce":"3cae83f2f7027d190a9ed1f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"38296c1e8c1821a14693a605fc2225a8db963a0d7bad73f56d2ad7458dcccb83604c393f9b652fdd0f588d2eb3","nonce":"3cae83f2f7027d190a9ed1f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"72d5fbd821bda8311512cd6aa47bfe652a33bfa749629aced0a6835df0d42759de10e05144e3be2e2047c8dfa7","nonce":"3cae83f2f7027d190a9ed1fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"b01291fbc4506f360d5481b5b5a09a669a6ed16fec40b0c936d632266293df3c6e869c4953bb859217bfd966f8","nonce":"3cae83f2f7027d190a9ed1fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"20244c29ee86dbe82019af83c938c5c64edb2833ae3c4857cd8290e0e4d1c83dbdd398c0f0ab5c927e8e821b74","nonce":"3cae83f2f7027d190a9ed1e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"f33b4a88605b1ebf8a9193686e1bb28b7aa4f47564bbc5ca2e1551d66900d38793bd3ac6a840c33acaaf32dbea","nonce":"3cae83f2f7027d190a9ed1e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"38c82094b52094f6c73fc670b7523bc80ab949fb96d7bf0b3d031f9c78944384aa69c460feae4ad00b3c84a7ae","nonce":"3cae83f2f7027d190a9ed1e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"5eaa19d170e093a282d76b5bbfc312ca580a6ce684c09d2be64688ddec91c8274f5b06d4854e443d69118235cc","nonce":"3cae83f2f7027d190a9ed1e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"76b1938272cfad5f4ffe6284e7a5c38500cb77ea329c6e3a62aea66f5c413b959f2aa2613b8ec57362d6939082","nonce":"3cae83f2f7027d190a9ed1e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"dd116c214ddc05043ae5039cfabbfc2cbafa23b812914d08c8817840dd9730076a1b0d506a444cfa1d2e1a14e6","nonce":"3cae83f2f7027d190a9ed1e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"81f0a0149695af3b9119840151ebd83a5410ff2da7f7c216aaee10d1e0ff31a826dddd9cef704214846b26fcc3","nonce":"3cae83f2f7027d190a9ed1e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"66408014802aa8f9956a161b5792633dc1a8318240d8862f12f91cd4a23ee313fbc8644dfb5718ecca2de15a07","nonce":"3cae83f2f7027d190a9ed1e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"1354fd10226256189c6e37c7671481f6794a154418ae27979ec225832416f10fa6c0b312a90879bb3f190746ec","nonce":"3cae83f2f7027d190a9ed1ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"0b803c14fe921f6aeb20e21149aaae80f7a5d67702d6173bacef23e2ede185a52639cfea33c5142a96b1775d8f","nonce":"3cae83f2f7027d190a9ed1ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"4cb471344c28b98be05f4beddb059e81a3fde9a764c7cb26419cc9bfecb127b9cff35194338443d1762eaee02b","nonce":"3cae83f2f7027d190a9ed1ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"bc7bf1264cbe847b0588fe5696fc7f0f1dbd934adf7aaab91adf91dba57dcf6097bca457fbc6bbb769a826b905","nonce":"3cae83f2f7027d190a9ed1ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"0ac3cf648c573d0bbbe4f301f7b20e2d6f09ae50a7f08ccfa0c5294dce9164d295b86d408cf8c7177cf4a3efa0","nonce":"3cae83f2f7027d190a9ed1e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"9c7536649c8fb4b83a1ada65d04be45c86b4da2c874758411c69274bf726a1f983afeba8377e5bf44700d00dd3","nonce":"3cae83f2f7027d190a9ed1e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"f4ca874a1912c4e6516a3c1d21dcc0485b51551006b25a00149af5679937087c8bf4b7508e72244ab83b8c2376","nonce":"3cae83f2f7027d190a9ed1ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"12ed79085dbb4fc5675ee93e6abe3d0b347240baa6519588cb40a96fbadd3f109a035822e95db53c039bb3e86a","nonce":"3cae83f2f7027d190a9ed1eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"2aefa439535e376d667a5c9f8c1b36dc685ba509a22c52ba52a400e71caa5608f2ba5ceb3ac7fa631b8147aa25","nonce":"3cae83f2f7027d190a9ed194","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"7b1ac4fa961a731e9fd03a3657b9d385c8199245e5a6b7f2c856f65f6099af05bffc4992eb8a8e0b0e73e3c6d6","nonce":"3cae83f2f7027d190a9ed195","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"7cfec0ab0c5c8af5553bc58ffbe884e2aa932c7bae19af7d15fbddec034aec43c9e63e37c7f2a87fcbd5fb8242","nonce":"3cae83f2f7027d190a9ed196","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"334d3e964e0eebf8ee424842413f138513d545ea191e329588e8c05686be7789671d96d8b5b267c20f2d7540f4","nonce":"3cae83f2f7027d190a9ed197","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"58a758cccdbab91c7fca8389d13b552d081e1f7b006a4aaf14c09078173f7278581e80c56db04f3cb6dd6ac006","nonce":"3cae83f2f7027d190a9ed190","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"95f66dc6ab177311f5ad8d6324dec4adaafcc5e5628350ad30655de1df798f1e8eb0e605e7858c6813475cad39","nonce":"3cae83f2f7027d190a9ed191","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"9ed99a07cd59d852e62ba91eadcd80a93ad6647419613aad40afdf1aa6730d7c9c0129e263cb88edd1554df181","nonce":"3cae83f2f7027d190a9ed192","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"c43d7d0c669fe8b0b7ca70c020a19c1395473c77c7f7bdac2fde227f8ff1002c4bfe15114709d1984e312a5931","nonce":"3cae83f2f7027d190a9ed193","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"d17b889b5b892df3314c4cdb106ac0437b45003a188f7ce4d8dcc9e557542c6fc2b2e21bb2a1a1712db6277533","nonce":"3cae83f2f7027d190a9ed19c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"397846cbf65722d71e8d0b1f885e3a32e7fc8c0a5708815f46449e9bb2330de67bc86e09d98688ff1f6bf4082a","nonce":"3cae83f2f7027d190a9ed19d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"b67003b09657514c2b7b22805baab6f16ebac569b9a6158a10bed3997e6fa79c0a594cfcb530ecaf1c143f365a","nonce":"3cae83f2f7027d190a9ed19e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"ca4b66e5548f6bb243d426661699b90c9ff59de16ce0dadf3b99491b40e5892f9a8625ae1a7d85992d46a85790","nonce":"3cae83f2f7027d190a9ed19f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"f9df0c7c163b7056494586d5a0dc73d13a10a47bdbc305f11862206408e0b0dd80add64e805095ed3893809f23","nonce":"3cae83f2f7027d190a9ed198","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"58e594234e7c67a3a64ec550459c612e5dd17e9779f63be985f21ffc751a36a78a16d632b86de8daf1cd945841","nonce":"3cae83f2f7027d190a9ed199","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"688274b01968da0c5c1e751be6d9a58bcd87e2f805f2a69578b712c5f6bfc647ab90ebdb91fe05fdfbb328d9da","nonce":"3cae83f2f7027d190a9ed19a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"689251a43a6a72930487b0701b3e8754e7ed73c21e9c67479c9e0aa9cdbd5f953a91b7be9b00a3fac5d16aa3f6","nonce":"3cae83f2f7027d190a9ed19b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"f09c13e16148c5e4e17a40fb5b2056f5ca9b3df1dde359828fd7fe851fe9aa99ead481438a41b9834fc42542b4","nonce":"3cae83f2f7027d190a9ed184","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"5e5b90cc605def3edcee7a48d0beb1797c569b3f2bfe63d65235ae7693aa7cce001442e9e718a0fe4cb13b9861","nonce":"3cae83f2f7027d190a9ed185","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"970c47386c439b3b0b1baa259352a7d217986fff5726b58e6ce18a120d9d175138a31d9a946d969c902bfdcee6","nonce":"3cae83f2f7027d190a9ed186","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"001a54e6df9b677277ab2b53319f37342c467d1024984cb1f9e298a3a05e8ab8feb7e91a61a84f9c757087c776","nonce":"3cae83f2f7027d190a9ed187","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"3cd09af9265ce783ee841c80ccd0481634e3c7373f32417eee12d881efa976eb4ff20d2a49c078c701c8f3381e","nonce":"3cae83f2f7027d190a9ed180","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"9b0452ff65527bde67398dc57e180fb29d9543ab80920e3d3d99fa96475b634c8b3279f41daf34075f36db52b8","nonce":"3cae83f2f7027d190a9ed181","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"42dc5d1800bc08581561c72fb72ce0b8a70e55343df93295fd21602949dc2d98a49732efcb61e8ddd1ea33c578","nonce":"3cae83f2f7027d190a9ed182","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"fa7ee8f5219a02f110aa75637766f123d10648b460395e5c213096063188fc024de4891d239026dbc6d73921a8","nonce":"3cae83f2f7027d190a9ed183","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"6fe8c3abab9dcbeab23e777c26a79fa1cabab03fd5879a541b8efd0a20ce5eb040ee017f0e4a0e3559ab45b78f","nonce":"3cae83f2f7027d190a9ed18c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"3a8becac83c2051145c09dbe7c38b6666ecef3c897ccaa2f1a3754edc22e76b987b508de9adf20522890d5cbd4","nonce":"3cae83f2f7027d190a9ed18d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"750a57947605450baa09984bb17aafe4217f49dede7f001a97ca96728c7bc4c6c8328d0a0ef26f540bb3084602","nonce":"3cae83f2f7027d190a9ed18e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"cbfc69864f56442982a19e59791b1aacc4ff553245e9f41297292130a32111d20fdd625a519a1b2c4a6b457487","nonce":"3cae83f2f7027d190a9ed18f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"54794db610e914b072f63211cd2b22ded11c5cfc916bc646e9f7f8a1474d4029b071cf3b5df45e74e8c5f8c7e5","nonce":"3cae83f2f7027d190a9ed188","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"acf4a825f1634e5d2a285c0ec2a2241a5a255abe35f0e62fe61e00b9378c92d2f241e660a00b5b5d9bb077e6af","nonce":"3cae83f2f7027d190a9ed189","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"5249f6f30ca5737958af4106942fe04853256485ae9e17ad04f65bd9761cc28b0c0982d410e9effb6d907cfb43","nonce":"3cae83f2f7027d190a9ed18a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"4444a19c43509e75dd36dcd0a0d4d9265ff4c76ccf3496df51b3b80659cf62415c1f2093f3e52aade555ae764c","nonce":"3cae83f2f7027d190a9ed18b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"94d7e6c1413dfdcd6dfcaf0502ffb57d03d8b365b885bbaa06d8ba515c93c36371ac885e68d077f07c848fb6c4","nonce":"3cae83f2f7027d190a9ed1b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"e60ce07bd7453e621e5e5de415de0149d327e45b0573dbbc7664ae14027251c0b0d3f1e2a1adfd96c6df8ba727","nonce":"3cae83f2f7027d190a9ed1b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"05ddf7549f4c781467127047dbb700fa2052abca2c7deb25b11dad1c8f56150f897e202af9f9415c588ea2392b","nonce":"3cae83f2f7027d190a9ed1b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"63520ebb2e64650ccdc046f664c3773e8b0d9fa18016d97e20aa62328d48a8424fc36fbc450f4a14197c8f2626","nonce":"3cae83f2f7027d190a9ed1b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"928ad28e7b9c5a4f9830a12b69c6a3a312a2c3139b5ee4d6661514a037a45b9f5981957d89693a1655a9ab64f4","nonce":"3cae83f2f7027d190a9ed1b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"bb10e859776e49f4e443c60b50caa0fa8c8115263fec115f025fce347d78e26e9ec74b1361cacf4d24c52d4bd7","nonce":"3cae83f2f7027d190a9ed1b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"78cbb368c99526d65e66ca93e3b5cedb7a9f76b5f39d098fa773e1180883aada8ac4089528ca5622852f1efcdc","nonce":"3cae83f2f7027d190a9ed1b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"43744ac67beb6fd413b4b838ad921b9c245c2543d156b105bdac0444295bb8e4e48f6d11aa1a897284be6fed50","nonce":"3cae83f2f7027d190a9ed1b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"44c0643a8467ba8afa4d28a5a0443084643cda404ee8098c8f7e3fa907a9cd3281af888b72db9b01ee7e74b515","nonce":"3cae83f2f7027d190a9ed1bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"be8d85efae6579ded5d9cfdc5baf9d62d4e9fef5baf5d466ebc95f9770812ccf6e974bb48056b306395c3f5823","nonce":"3cae83f2f7027d190a9ed1bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"8a314e2e955d1be46b1f708b2951c58384972319b167993cad16196e72f0e58286558e49087668df2897fde24e","nonce":"3cae83f2f7027d190a9ed1be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"7a9c065ce6cf6008fe010cb9f1f718d80cb2e9ded0a819eea5cdae7c287517d37a63192fea330ae9ed6c858e56","nonce":"3cae83f2f7027d190a9ed1bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"cf86ffe59202ec12ddd5f4b336e15c736940ab5e5e7e884a7210f10438b59a8d28af2e33565cba935452dbad86","nonce":"3cae83f2f7027d190a9ed1b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"857c293238601d89cd9c10907e9d5800dd59e731faf1ddf8aaa7f47f518f9e401392855c9ba785b8f8be091c23","nonce":"3cae83f2f7027d190a9ed1b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"fc5e142946b8a133e334601010d7f4466a2b1ee9bb4515c138e43cca79c06246faf4b323a87bdd4a906a96e754","nonce":"3cae83f2f7027d190a9ed1ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"ef61e3981d2c686db3482e758940a746c79c8066f8efaf452848a06dec31b4c507f9beb6fffbbc24e347bb0af6","nonce":"3cae83f2f7027d190a9ed1bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"a7949faf81b66589b653b6bb1bb8d4e4dd2c6dbf6a2d7c9d8615cb329defe954856123456f60b5fc2349b1973d","nonce":"3cae83f2f7027d190a9ed1a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"b8eadf1a827aa4fd70906a3db1da1e19745b1d488a5e1e9525116e7445ddefb8f229697a55c7992ae1fec9670a","nonce":"3cae83f2f7027d190a9ed1a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"7a4462601326a5e2b49b887b7b25fa258262e04925888dd6ea4fe90c0f21ff5f8902c47d944dee22aecb7b8111","nonce":"3cae83f2f7027d190a9ed1a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"619daf4fedae72588345c17e358d7d5d57a6555828c801ec7460218531d7bef915c2577fe96688a0a23461d67d","nonce":"3cae83f2f7027d190a9ed1a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"524aea6a3d4a26159f647ea652728ce11cceddcd9213913a215b9431183cb8f9b3931d2f9f3a6b35cc4746006b","nonce":"3cae83f2f7027d190a9ed1a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"9d27b5e4b17f08ebec865145f50b2ec3d53df638c75f3eb262ebbe91800ef0a43f45e0c605c5738ab65651c2a5","nonce":"3cae83f2f7027d190a9ed1a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"3e4d0c17857b62dd66cd62ef9c0529ff98737fdbcc5bfb7b918b837647f833ebd1c4ea09b54d94bc4ac5c1615f","nonce":"3cae83f2f7027d190a9ed1a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"59b3da37f80a25ee798cd0fe92635dddbbd99e5f684c67ed856abd31402900eba69134a3af7fe2fee8d1a09c1d","nonce":"3cae83f2f7027d190a9ed1a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"df89fa7bded44bedc1a91d8e2caef498f12e11dbd4968e8c02c8414747ca578a13ce36beac8da1136e30835c51","nonce":"3cae83f2f7027d190a9ed1ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"044e9daeedd4ebad6cedaea450e5d1060a0c63d5c292c765acdebbce0665e4fbf645119112354446126ee5f06a","nonce":"3cae83f2f7027d190a9ed1ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"4ec8fda9c5dbe43efed1050b94f163487c2941eb8fd79111f9bd3f8aa3024385ebb8dd4ec34a0a4a31e9b1d260","nonce":"3cae83f2f7027d190a9ed1ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"d0009caf4d84381ebb9833635cedf236287d559c16a6026c16de4b09a1d035ad428528bacb9c534dc888ebc3ac","nonce":"3cae83f2f7027d190a9ed1af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"1cd17d060e18fc724bdbfe08fbac5af89d5e193bf4211bc83467027e0672cc36a3466857d9d237eb32aef146c2","nonce":"3cae83f2f7027d190a9ed1a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"b902f2cffe748faa777a90c86bd9553e370844675f7bf6c19104881e4b90529aeabb4d93a3459623fcccfacdeb","nonce":"3cae83f2f7027d190a9ed1a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"357416fbfb77cf547fdef4b8eb38a6b10607c5bcf709888d634cffdc28083df2b467a9ad7504f16c32f2db7911","nonce":"3cae83f2f7027d190a9ed1aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"943722e611585c2de556ad58c6080e98b98f2b6df213f0c6dd03429778d569345f90ece0236a4d78296139e197","nonce":"3cae83f2f7027d190a9ed1ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"c855607ffd2acc62b5b3873c5d074cf4026576337e78dfe12edcb5c1184544a37f23c30e4f3c502c437683506d","nonce":"3cae83f2f7027d190a9ed154","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"eb72c884af3aefc40ba738b1c3f33ad4b3fa1dea9f8fd83ad7d8da67f3e336cb1be47e648eabf2edb1558a2210","nonce":"3cae83f2f7027d190a9ed155","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"d47e172d20e78885ee2f519c14cc8b077908fe929748aae0d76e6fa0bb2cdec92c473fcea5f2e8c57fcaeb1e41","nonce":"3cae83f2f7027d190a9ed156","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"71b69afb9561a1f924b240a1c6491f69e4887467057f3d83fd26e641cc536eee17e30b62042c1daf17abc99da6","nonce":"3cae83f2f7027d190a9ed157","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"2df54f76a702233a7ddfae8f10191adc6ce2ae47af0925f4d77d77cc940d7ee56f45a7adb67c9c251e10ac6d79","nonce":"3cae83f2f7027d190a9ed150","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"716cb454d8d0dd7db4b266c12302d2de9b11f30da54cdd009c9ded8573059c89c6ad012ae02a9474fd13d54bbd","nonce":"3cae83f2f7027d190a9ed151","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"3727398ddb251fd982e4e5436b781e59b28e5be4f0e0d3d1984aa5708d999f394928c93288eb805a4d0b64ca6d","nonce":"3cae83f2f7027d190a9ed152","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"bc636ba3cfc4635d52eb309c18eebded9b47564fd2fd15d3f3791db3bf618ae3affb7bdfbf8397ce989a6b95ad","nonce":"3cae83f2f7027d190a9ed153","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"37dcfe3ae28ab38529508ebaa662f47c6ee80c95ac69c137b6ef7980fb4360a5bc4979e26db7d025b81c101818","nonce":"3cae83f2f7027d190a9ed15c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"c5755ed39c6d281a8be66d1f60775bee0004f22c4143395ec2bee0ce457b1f40dca0cc212722c31d3f97aaa96f","nonce":"3cae83f2f7027d190a9ed15d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"339f628e0aecb3959da522ef7956ca41b2185166077742d0f2fce492b7c6a9bc050c90cd18efc246bae03ba822","nonce":"3cae83f2f7027d190a9ed15e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"7a29e75edcb2e1c31314f939aa71ba14466d2a7204c35163b8433c123a068d86c5999f40aa2b6e01767b30ee95","nonce":"3cae83f2f7027d190a9ed15f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"aadaabb5010831b88b141229feb0a7f6b64bb73e0bd40afa6626b41c0b40e30ace02d3c65f25fb58a623e40d62","nonce":"3cae83f2f7027d190a9ed158","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"6c68a135de84d0fb4918760b6d8dd0ea14ffcfbfd63f67ee5afcca53e4cadf081ec5c99d12477db9df420bff9a","nonce":"3cae83f2f7027d190a9ed159","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"0f960f6a2d7882575e71d4df348e78eb7af708f14f08a4143dab41678a84a62af68bca8cad9b27f539b39816d6","nonce":"3cae83f2f7027d190a9ed15a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"d5c4746c6d67a1646b9e7f82d50954c03721a1f1395efa884d1da214d5ce242bb39b552ec9b16d56cea3018fa2","nonce":"3cae83f2f7027d190a9ed15b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"cdc4182d688a28fa552f6b655b2f140a08b2325b4aa4a15b6ee8e9db15cb636c751a299c7523b9f0cdc4b792e2","nonce":"3cae83f2f7027d190a9ed144","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"82171966c41563b49892d1f12625cfe0d63a48b4f9d3adfcb6c68bf2d326c9a1148589ca8ce13e5a3f3eeeaed8","nonce":"3cae83f2f7027d190a9ed145","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"f6afe892e6a45f77569ed0d9556e992e5efaf30365c69283cda79f90ac45844c73592437f7d5a7c585326d704c","nonce":"3cae83f2f7027d190a9ed146","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"9cd3ddc101731101831cd4f93af3a4297ee37bc40025a27f5f162818eae525e77ef62a7d42eb1626cf72f4b6c8","nonce":"3cae83f2f7027d190a9ed147","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"dd7ad342357e18a17974ad13eaca988317bdb6c34844847f5d58c1e3d27db07d4310e33ac12e91e86631e5e4e5","nonce":"3cae83f2f7027d190a9ed140","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"cedbeafa54517069aa13bb1e5249c0e6e03e0fc233ff9e77bc3222f82fa01a0fd919fa925a6d6437e15e4cada2","nonce":"3cae83f2f7027d190a9ed141","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"3c32fcf3725bc49fc6bd67d3f0d6bf1488543ec3a553774fb07b9b4cb39bb3a941676ba42e48ee5b7a28c0a865","nonce":"3cae83f2f7027d190a9ed142","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"58b697c126f98437f199c97549dcb5987ea920f50677782d1bddfdbdded01c466f7d7c2967d1b0e465d41725ed","nonce":"3cae83f2f7027d190a9ed143","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"475bd901a210760c6a19989bd33e0c5b01dd5fadb6d636222befa1e8b29df3dc267be79da60a15e44fd22f983b","nonce":"3cae83f2f7027d190a9ed14c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"8a047ffa0a78669b9338bcf61048ea6667b7f320f4b1122228c3139971ab96de9889d1123c064a7f867246ff5d","nonce":"3cae83f2f7027d190a9ed14d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"d8f48e088de439721788238fbd08cd5128197ff6bc7947830d99381425596abc5e1136f4a004e4c0e46f6cccc7","nonce":"3cae83f2f7027d190a9ed14e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"c7eef4b74118f4c2ad3cec92b2515afeaf5dbed7f0ef84414423b02e99045dcaacfffae39b48c8f9daf20a4bb1","nonce":"3cae83f2f7027d190a9ed14f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"bf7421e85e4f447184dbdd8394d0b026b37bbe5a8e6422dd914a6d395fe825b1d0fe134c5d92cd3bd3a2965f7d","nonce":"3cae83f2f7027d190a9ed148","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"428942dd87214222370c3728e97d2e2cfa33d7c89f9022abd34a476c4e0fe64487d193de4c991f35411097da78","nonce":"3cae83f2f7027d190a9ed149","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"e8dd8d8487e607158456b69306f4268b956fe40e6aa29c96610c1d0631109b55ed4dd4147cc368cd313a79c301","nonce":"3cae83f2f7027d190a9ed14a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"60c4e68be3b8edf0f83a47a889df02329b58f3f8705cf51d4ad244ec46b64b5f323834dcb66d332d4760c153e9","nonce":"3cae83f2f7027d190a9ed14b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"40b4aa23e0949c0152afa4b67a4a73791017702fcde648aa2ca0dabf016a225f8aedbaa3e44fb85c0ba98f8d22","nonce":"3cae83f2f7027d190a9ed174","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"fc025361707671629c1a70f8221ecf9f28c680bec50d9fcc29ed35f2a81fcb099c3f53b411006926083a529f19","nonce":"3cae83f2f7027d190a9ed175","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"e56958956cef3ca88028decfc9a9c1528d190aa41e3644f388ef4975ed08a3f734b19404c6efad08e18cfc85db","nonce":"3cae83f2f7027d190a9ed176","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"a99b6772c398ddd89868de3d4228b3c17201e305a80a397734be4a5475c095a2506b3d23420670f9392e9b04a1","nonce":"3cae83f2f7027d190a9ed177","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"0d034552174905a5a4eb577e2a671b617ff2a9b093a2f24a152dd2a96f04110a974fd2493c3c1f55607610d70a","nonce":"3cae83f2f7027d190a9ed170","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"7bca8a6df0afb4c23b70c7cb2125a70b7df419abbb6c56e48076e5317e6e8b4b965319944ea3eb538df6684c7b","nonce":"3cae83f2f7027d190a9ed171","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"cfc2feabb6c0fb0b88bab2ddd44f480e3c01eeb177fcfb77ea893c4abe96d9e976b12caabc308eae433db8b95f","nonce":"3cae83f2f7027d190a9ed172","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"1e3033680baf2abbc5ce5e7e2fb229af24ff9c804f76d5f8ee90980519f678b2648ff26588a091f88dee7d5aa0","nonce":"3cae83f2f7027d190a9ed173","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"17c5ae3a1cb63bf4303e2264875f5ad8a43447763977cafe7bce711aa766730bd86b467e3c482f132c159de673","nonce":"3cae83f2f7027d190a9ed17c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"b4deb06db0b8c0586cfc9444c304b4b9523d37e10d774f9e67bae1159c3925e24cde13f93fba9b4687c6902871","nonce":"3cae83f2f7027d190a9ed17d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"727ef422e8ec36ca6cff8426a8fefdfb36ed00d379fcaafee90d4789ef94ace6cb3b7b8421bde0f7a6c6c10722","nonce":"3cae83f2f7027d190a9ed17e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"78bdeea9d34bbd1ce4e14fe527c0293f3e43d80c8e4128c31eefd32de4377fe6c4d547e7ab0f8bb0c67aad0f50","nonce":"3cae83f2f7027d190a9ed17f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"a75fd0fa318ff14aa3e838a5f6ad4dd2a01d94b0e0b916b023b1b29e3807f1c94b1a382e7e20695b9d0a390a29","nonce":"3cae83f2f7027d190a9ed178","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"f0a2213b653b98698e97c7ca8d65985487f745019909bf842f7d0cb05864081d51bd766a6a9f6c544bcec05233","nonce":"3cae83f2f7027d190a9ed179","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"be2c25c4887333e53711a1f345e9ce30899431c2241bb89a239dacce433138f062a86baa1a0e22dc6715ff8a0e","nonce":"3cae83f2f7027d190a9ed17a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"af3693156ca848a101d285293171d4d8c909968d1f4252ea831f93b537b982ec175e71928ba7e7557cc1d703de","nonce":"3cae83f2f7027d190a9ed17b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"9bd8af039341d7822cae2df6321a4fc5afc87b0acdc2dee0fa07687a89ab96d5999c5aa553d3ecab159423581d","nonce":"3cae83f2f7027d190a9ed164","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"bc0684aa04de69c3fb65810d6e82628bb20259182cdc644ac3e92801765efe743f7c2b5526cc79c37b807ae377","nonce":"3cae83f2f7027d190a9ed165","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"cce6d0e7d24dde859c8a4abb207f2edaad687d612fdd6ce0d8d839b412dca04023a1a8e1ac360e668c40713864","nonce":"3cae83f2f7027d190a9ed166","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"90daafbcef12b54147ab2af5c6ed5d80d6b8d56b10e7ad10fb8a2e4d75a7922b16b51d6e6ee1f5e12c59ab4b9e","nonce":"3cae83f2f7027d190a9ed167","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"9440354afce2101e72074690fcf138efd302162c6a999c7c7ef82efdd83d4b4499f6a4c2150455fba00c935026","nonce":"3cae83f2f7027d190a9ed160","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"5af1300a284ec1af5460622f289d691163b3c524b5eaf3aa97aa8742c8d05b599c072667da4d14f8e1a8f1282e","nonce":"3cae83f2f7027d190a9ed161","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"9687ecffe896529db79a955c1b712570d58c288a2adb76238a748098f3d844480ea81fd4e5efda19fdf85b591b","nonce":"3cae83f2f7027d190a9ed162","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"5b59e2af6c164f18bd8f11945dd9d9aed1fe4df02b3175b730b40d161346edf7847dd7de52bd45168095e6e7c8","nonce":"3cae83f2f7027d190a9ed163","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"9bfc2cede92fce6d60c74064c8aae49ec985ec5721a62f86ba9da9e4ab9d39871ad085dff073e639bdbfa88212","nonce":"3cae83f2f7027d190a9ed16c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"d8c4e41cb9ed26568e0171d4e2d67a3d02bb663a01af400e594ff0c362a0d6842963e6b842d97606e87bccef39","nonce":"3cae83f2f7027d190a9ed16d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"b08a7092416f3d12cc0d9103b3499082c2c8de929ecda8c4e068a761057515de2d18e95233d45b85be84863b3b","nonce":"3cae83f2f7027d190a9ed16e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"7f36f66b76f47f7b49f57ab608a4778dba88e1d2f2ca480b5de907d6a10cbe6f58ae1b5842291534963ac1495a","nonce":"3cae83f2f7027d190a9ed16f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"4cfd07f4d48a464ffab9e5107835bb3f71ebb7f68cad26ba756fc374fc04d16ac451e525aa7e12c7464106fe79","nonce":"3cae83f2f7027d190a9ed168","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"da58edb373d72c90c4fd917ea917b45508965d6f03807ede80064e8e0573edb7cf669b9f893e969dec32f72d3c","nonce":"3cae83f2f7027d190a9ed169","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"f52341cc0dda7c33922d81c553c6ff6a958b9056a1c682f98e4593bb5180006d9761941724603b4d2d721c3f29","nonce":"3cae83f2f7027d190a9ed16a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"8ec7ca9d9f10160cdb10a12d134416f74b530808f1b019122eb51383688615388bf372cbc52669a82a1fd12e79","nonce":"3cae83f2f7027d190a9ed16b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"dcb67ceef68477641fa274de5f70f0626f5d0abc68cb8554a61d2a07061b7fe4226a4fa20c2e4326aa9008c9ce","nonce":"3cae83f2f7027d190a9ed114","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"6d8bb7f3a2f849cf4020043314a32d5b2ddf1169ea3982da0f9ad8156c5449847892918e0e4fa6a730982d478a","nonce":"3cae83f2f7027d190a9ed115","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"44ee1f90e8f60a024378ebd6d149fa9dca14884ea264a523e6061d847efb8231af444e9b424fee0a46c90763fb","nonce":"3cae83f2f7027d190a9ed116","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"6c9f1e8338628d2f72242ddacf2858ba78a4bb32825880c68a10388550ddc2fe02c44089f523abe358b4556761","nonce":"3cae83f2f7027d190a9ed117","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"8539f6771fc9bc168bd4d144687063f5cd06f62c290f804cd88918e839548cc43a26042e69d231c35fcdefac35","nonce":"3cae83f2f7027d190a9ed110","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"c11fd10b8319e293b2242b814f6a756a2949502d53527a76af049b6da60d72b6c5f4277493675bca20ab76c0db","nonce":"3cae83f2f7027d190a9ed111","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"f11e00d789a12cc388469f68c0d2fc7c461a4758859606e36792de603fe6f1a7648e7ce200183b173e6a702dfe","nonce":"3cae83f2f7027d190a9ed112","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"7de107284ea2579ecf0716d5ba6d0e94a94689cf011ced613fbabc64d64cfc0db9171e8a820f8add361f62b1f0","nonce":"3cae83f2f7027d190a9ed113","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"8f57a446d1e80d95fe655bbb17ee76e3142841094d14c554ed30259a25ce30303d07560b100e94a625269a946b","nonce":"3cae83f2f7027d190a9ed11c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"1b5658c164708f64019136c43a7da590b4b54e28a7f89b76ed43273f69e61cf197b85517bcc4bace19524e1858","nonce":"3cae83f2f7027d190a9ed11d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"5a1212fc6706f2b157bc9e68cdbad36c6423bb006f132cb5a247f3865e6c9542515aaad4add63b0f0805507d49","nonce":"3cae83f2f7027d190a9ed11e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"7ff9d4796cb6cd55ccefeb267693946c8e8e609c62664f58ce1b2a2208f1f6051ed66a214b31076c8c259c3c8e","nonce":"3cae83f2f7027d190a9ed11f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"6b564f588db0e5bc9bb57152f5cc45e92a6e42c98207eab581d7f00d0248fc84374b9221c9aaaa21000f9c6541","nonce":"3cae83f2f7027d190a9ed118","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"f25512d0880d876536d4a68f4bd92dc722c550c36af55955c6fbb93e54a4fa0b06be014fa0170d00734d723646","nonce":"3cae83f2f7027d190a9ed119","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"e7800377b51b30d0b15ecbe95af0f46da031c321f558e060f508b15ad70862446d6983ee22a5882736b5f51e41","nonce":"3cae83f2f7027d190a9ed11a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"e1bf1182b5c7546f3cd331be57f7568180d5cfcc17c93ceaafc3a44ce946d54a91672a1e24c85f7d3e682c92a2","nonce":"3cae83f2f7027d190a9ed11b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"e799da30be9fbadba25312e759576d8882665c595ac26914ff9e130c3a06457b69e4ef92f62cf411d8bc844c39","nonce":"3cae83f2f7027d190a9ed104","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"ee699947ad1af84c8c015a035c5181fe174da40e0fb54f51cedab2268ab4ef32a61c8333c2ce89703c3cfb1c6e","nonce":"3cae83f2f7027d190a9ed105","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"4bbc854ef4be454a94237d8a75a77572656ca4bcac04c9aba4be25f6cb0171d622ab1aca019341d1d592094263","nonce":"3cae83f2f7027d190a9ed106","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"64754da1814dd2f57b579979d1564f81f4c3fd9deb14b12772848e8f8657424611d64a81cf0653c0d015d5669e","nonce":"3cae83f2f7027d190a9ed107","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"e0351fe5be9be752fc632d315f2a0895e67f8c0544f91d451bee1fdee848c287e78f0f0d8c442a00a1465350e5","nonce":"3cae83f2f7027d190a9ed100","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"b10b9f8014b1b066bec1bfdb214638eaa710e0efcec2e52b5f8eef1baf2be64a2b79e58c3c1d362f1eabac5fad","nonce":"3cae83f2f7027d190a9ed101","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"b65b500b4df38d5e9bf0d50b02b9e95c8648f7ddc8dce79cd25acfa84d6673b90c5be0ab5ce9edf89f17c75c51","nonce":"3cae83f2f7027d190a9ed102","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"2dbd909e9add8d70e849791fe519521c2e32ba91dfc94ba85a41674e8f879343c69ca5ca37382d974ca95b6c12","nonce":"3cae83f2f7027d190a9ed103","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"18442b4366cd7c1f0ea80e1fa9eb475590e84dafd1b9eaa43f11836f01491755efc7ff283788fda9001f06f103","nonce":"3cae83f2f7027d190a9ed10c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"56eab7a239b6bb99a3945ae8a3be69898ab7daded9bcbfe09a64d10d728e5e941ec9633dec780e6a7988815848","nonce":"3cae83f2f7027d190a9ed10d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"b493433d38a37388bedfb44e2040a7e3f3a92bfb5d61ec89609733fddaa8bc42d179ea353a2be4c3ebbb1d7424","nonce":"3cae83f2f7027d190a9ed10e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"46ac983de1cd1d7814c1d250da0aa37ada17206c7b2da356320e9f80255788c7089f2e0001800f8a59d119ca86","nonce":"3cae83f2f7027d190a9ed10f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"e6af42f01b8466806e855601dfc3679e83e2b9181156a0b75d4a5171a864d15e1a77e1aee9a8cdf800562c077b","nonce":"3cae83f2f7027d190a9ed108","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"1e0174ec7837d54f489d95fa5f12561a1c762bd3dc9e1e2c91a566a2c52660703126ceb8249671a26b6a7bc6ce","nonce":"3cae83f2f7027d190a9ed109","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"a3909874ab7740d0fe4c73e14aa7e98b98c74c4aa5318a3cebdcd9221b8015c18c9b2ad7eed5e399a111ad71e4","nonce":"3cae83f2f7027d190a9ed10a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"78018965906f2c15395e6569e83bc994b6fd6c0e62065b10b02f36e72d0214568fcba3cd68912eb5d3507e7bc3","nonce":"3cae83f2f7027d190a9ed10b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"790ddc07f99c7a33a6f7ed0a300de816287bfd37c5b2d1467102d75e3a3cf965a26b66c634dea181200f4b09c7","nonce":"3cae83f2f7027d190a9ed134","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"ba702e5e15380dafe1af687458299af2c216f9fc7913019122345cf31736355c71b86841b7a1509cabb806b9a3","nonce":"3cae83f2f7027d190a9ed135","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"c506f71c8ccb17cf4dc4f129fbb79afe3b5aa700d5081cec56ceb73060bea8721ca41089631a2461974ced2d6d","nonce":"3cae83f2f7027d190a9ed136","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"eb20b642665e0af7fd2353bbebd898e727f8e8f0e1f30e5abd41f78509df77d8444ddea0f760bf01e5b302f44f","nonce":"3cae83f2f7027d190a9ed137","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"d3c544bafaa565037d6bf425e33ec90498978d3aa7bf8d4ed1f70611e99074a42c867ff4f3c202be6d145f7d5e","nonce":"3cae83f2f7027d190a9ed130","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"d1de5d2b998305dfa58f8942ea81790f7e9798ade93038839f7eb214dffcfdadea5f952da1fe818fa76de96e23","nonce":"3cae83f2f7027d190a9ed131","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"a06fb3268fa461761ece4d832dbc67dce9120f44d51e369e09c27e86538b327480e3462c29c2f72682b8a26c3e","nonce":"3cae83f2f7027d190a9ed132","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"f587b0e373ca039238a0d1b9c1a3706d7e1c99d6d86333f12271ebbcccee36daba0e7f992131d38ef01f18255d","nonce":"3cae83f2f7027d190a9ed133","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"3fa97fad8cf192e53bd0c62f0cf8d481cceec96b57c00a0ac360c18661c5f61e9cced4785d8cdd3803100e338d","nonce":"3cae83f2f7027d190a9ed13c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"b8e793d0d43bf94d4e75e4bb9beb4ab14b287577310757b1f01340c463f9a28be4bf3f2a0362314010698a121a","nonce":"3cae83f2f7027d190a9ed13d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"035bc75cc1b79c45aa1585dfb5ad2ae4900b4583e1daeadc11f0339aa456ce6cd4e5e0e4f855636d211179cd40","nonce":"3cae83f2f7027d190a9ed13e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"8790ac2d0504893a5bcf35623267ad683d32b9e5f559716c7d545cb52d3ede9c2179c9bd1ab880cc80812f8fe4","nonce":"3cae83f2f7027d190a9ed13f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"167b33bd50e1846aece552bed3d57e29a81f3d39e862c6d5cfaeb49c364b4b64cd71b7c67d4f2cedd22a9d572e","nonce":"3cae83f2f7027d190a9ed138","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"9158704e554a39a88e4eb0f6b459a5fc2490c4108d2f500ff9e30c5d28bd6e3b1c8f6371dcd1e03005f7037e34","nonce":"3cae83f2f7027d190a9ed139","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"e3ff6a6a25e907b414f5e6193826b9d50ee901093ec194af2bd621f90367c0d5d8a975b88e0ea2af668d63ae6a","nonce":"3cae83f2f7027d190a9ed13a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"de3c6d36224c8235bdfb41469b8209b9a50af13b49267c75db85bb7914e03e7a4389b798a612666e97c5ce4e0b","nonce":"3cae83f2f7027d190a9ed13b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"4a89af153337a0868ed129e543b1082096589355caffdbddbafcd95d79139060ff8997867f76051c51c7554b48","nonce":"3cae83f2f7027d190a9ed124","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"aeff8301a90aa95dbe465faec9232f318a1fc46402b1840f2e54cfe6ade328cb3b01450a1f0a93d456697e8639","nonce":"3cae83f2f7027d190a9ed125","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"eb852b58fc8d7d9bc7965059735936f4d03f415e7eca8d21aff59fbd1aac921a76b16951fdfa7b3df7607bd4b4","nonce":"3cae83f2f7027d190a9ed126","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"8f376f86316e6bb547758c48e5d2e63afd52f1a2864e008afa38f3ef5dc2bfff4e3fde60dab0d4d7d04fe56c9b","nonce":"3cae83f2f7027d190a9ed127","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"a13c3c4565765d9c370b0487e99b3abf0acc481446c5aa702192f1ba41ad6909aa85f0411fed309b0d131b8775","nonce":"3cae83f2f7027d190a9ed120","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"ca2b2578bb441ce49c49c7bfe5834738a5568a89d85f15ed98e814c0492ceec015ead0f3d632d70db05026d9ea","nonce":"3cae83f2f7027d190a9ed121","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"eff7cbd0095f34d7ee11a3d4802f5110c8f42ca7c8f2997860dfa44170e6f2215b8d1b112702786df211d812e7","nonce":"3cae83f2f7027d190a9ed122","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"464ad6672462836d44f05284d41b4c25f96f788f028340d503f86de2f2fe9ef4f5e9b3af89141ff3fab9500bcd","nonce":"3cae83f2f7027d190a9ed123","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"0b4ba2df996924e61f29343d84eeb6684756329253682321c6816d83e06835147030a253668a32e85db1ce81d3","nonce":"3cae83f2f7027d190a9ed12c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"d3e2e52c759807dd53f42e709c6541c3e54ade37174f9ec2b143f2b7af86f622af5fb3638200de1f7273d76f7d","nonce":"3cae83f2f7027d190a9ed12d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"e15cac3fb402c1950c4ae065cc25d7e8374cc2f21fd02be12527cdbdde7ec188d3374bda517fff0ab95c4ed1a1","nonce":"3cae83f2f7027d190a9ed12e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"3570da5831bcf87aa12d1c37acdaa3ae82ffd06363f4a1f54c320e4e6c103def8e0dad98cfe4ba65a3fdef3178","nonce":"3cae83f2f7027d190a9ed12f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"34151154b8fa36494438c5a57b41fe3b095cba417f57b0e83f373e8dd3123d37242324ac08bdd733579cf7773c","nonce":"3cae83f2f7027d190a9ed128","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"cafd68ab3ebdbec3c2f4f23abcdc5e21b99df25b6dd0b61003592040b8495847d123042e05dd16d1d12cf193b7","nonce":"3cae83f2f7027d190a9ed129","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"0ed45dd2e9c3b0a8c9940d7438ff153f61145a2ddbc9bcaf30823fe6e59fb9767ec088b5f30bb3da31cb8b1c0a","nonce":"3cae83f2f7027d190a9ed12a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"21de14822a1f67aac5c0433e7615e740b4de235af3b63298442e5e20530d5d76176ad5976fda77e856d3d914db","nonce":"3cae83f2f7027d190a9ed12b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"995ecbf6a1568f6814347c7559cd1b42fa5cec9d928e737dfffa98dfbbe08cdd36e14673ae8ce5007e5ba7335e","nonce":"3cae83f2f7027d190a9ed0d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"4e30603203516cde099931a359e209f8cd90a71d8e298a7654de782ea8bb60ec"},{"exporter_context":"00","L":32,"exported_value":"717da569a4bcaacc5cd926afa6b3a47a0362c7b63bcaca68ea027fc99e63c47c"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"34ef9c7bee2d01ebd2d982272938518ba87c833eb219f029d76e95f74f2f8122"}]},{"mode":3,"kem_id":16,"kdf_id":3,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"40c386b04b4dd7064a1f0e664557c6e22605943f89c91beae500b7bc1195594c","ikmS":"d0b12d22ca5b373d162d1cabee2771fe7911cd0c8f89929b971e17de1129ade0","ikmE":"e18e3d2fe92ce8542f14b6ca36dc8b19c21afe32425cbce8eeffbbfd8334bcc6","skRm":"3d6e160fd54d5b051aac0b16e496b27cd5ef4e4ed689ac241e9b8497222da664","skSm":"e14dfd1d4dafd4013ab1b5caebfff17ebce29bb704abadbd4d672bf8152476ef","skEm":"2bb6e471b175d68ffcb3dc6dfe5eb5779202ce25dc87e8912243c3a0f25204fd","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"040b132719c913c6fec01bdcb421a2b548850083a45a05b5c6e27df423c920dcfb140eac06c5bff73a144b5d634423f388949f9ba5a730511213bd2d5684ab440a","pkSm":"04f1237013480579505710cc4eae0626d41f8f12eba6ad9569c96a703ed8fc8272f4e081c880ecb0e59b193bb713c2d35656cec3cd99b3c81a5eff9544a8e141d3","pkEm":"0460f8d2121b48ad11281492f51e4dee0a5ea3969d372c4f1efd45a4479a00467cff0431a549240e850630601e8e2e8df9e375616cba999cb81c8010694ae1e26c","enc":"0460f8d2121b48ad11281492f51e4dee0a5ea3969d372c4f1efd45a4479a00467cff0431a549240e850630601e8e2e8df9e375616cba999cb81c8010694ae1e26c","shared_secret":"41e2da8798e917ade131b57f70aefc41a519096ccdce0e933aaf882215b5d94d","key_schedule_context":"0341db1e5b07a041a0eeada5439a3f724a79fee39919f2c964570e3bd4ae296e728d0672b77f6d53fde449bfc9c0c24f0b899abadffa161b5bd14bd99c0b5586da0da9817afa84fe836a2afb21fe34bee379586120ef91d5c0432c32bb1d1d6dc7923282892f781147d97bd9e353465a35023868db7b5c0fa7a73b1ee212161f04","secret":"0bb99e3e50b3726be36cdce8fdcadda74df08f4f6cd55eec15b7e0816515533af5c0dbbc534208f8e6876650a0177e558bb9ccbeae55b513831483afdf5cb094","key":"d9a64fb7c160606c260bf1f6a1319dd43daf572a6b0581cf8c2a4b81f6a1a03e","base_nonce":"717abed166c56d1fddcdda35","exporter_secret":"c9b3f3ad904f35822a6c69f83b3c231c1252f78b29baca65fea1a1d778a334266c6ed64e38fe758a1529685e4204e42158069a7c207c878c55030440ee3c7ac7","encryptions":[{"aad":"436f756e742d30","ciphertext":"d5bccded204408c1fb8be6a968acf6322141ea589352349f90c9d0b23afaa3667203490c407cfa08c59e4d725e","nonce":"717abed166c56d1fddcdda35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"3fdd8e8ff3587dbd2bdbb246b84d5e8a824ed2a3c9b5e13dc29c753d13c4706cf14ea8e6697e592a7ca3760c70","nonce":"717abed166c56d1fddcdda34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"8fc35ae4725c01df6fce37dd52f0a85a67a19cf69dff25f4fe5e4b6a6c83c861b50070180b483cdb0368898c4a","nonce":"717abed166c56d1fddcdda37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"5bcf0830492ff5ffdb1ed3e0384e4745481efd745c45976d6891e37d355ab35426fb03e168aff63a05f045bfef","nonce":"717abed166c56d1fddcdda36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"bce1c64a8a6bc1db2b2eaf128ff3589a212da34081f1bca17d1313407c1551f170fa13856b2779c7b49ae2124d","nonce":"717abed166c56d1fddcdda31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"bfd5a46a5055e5a4cb27b7e07490a89766fabef69753c902ccc7084b9eff62a1f0580523b518542515e7d92876","nonce":"717abed166c56d1fddcdda30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"73da8add059714c5bcf5054ae4bb0ebb8cd6e33ae1c6fb02d143a7fa941be4fbb4421c3b18eff8f428c259e941","nonce":"717abed166c56d1fddcdda33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"ae5a9831a40f66216b5b2ae6ad1f917ba4837d342982838804f2bc913bf4475932603899734caaa27a827ed358","nonce":"717abed166c56d1fddcdda32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"0bd07d64de87b2856d5c86633c57fe226e0b88afae68a6ce8d40ecea489a18608978c9b75bb4ba84ed7046ccd7","nonce":"717abed166c56d1fddcdda3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"95bc7caa9b53e8da2141145b009b2a5536a70868b9144043ca11813a12d7eb7eda24e814b18951d43dc110d1bc","nonce":"717abed166c56d1fddcdda3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"192207b8fe1caac281b5a08e583d861f5d7c248e9e1d97672a37e94d625528a53a1c263fe9e386cd5f38d5494e","nonce":"717abed166c56d1fddcdda3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"4507250ca5aa0c518746bcaebfe72ecc1fb32a66c971f7da56432fc442355cfe35ab00bb2dbe60540dfc2da4d0","nonce":"717abed166c56d1fddcdda3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"eab6e3c07ac06edd2e7756d5140fb0f64940dfcee2a6fafee944f58b8748ea2d4e4bdb4d3a842174d29212c94c","nonce":"717abed166c56d1fddcdda39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"1cf1e60e16c858333a95a82480108d69f41d11bfa654d8b4f933d730ec9e8f33425d375451354156ec96429db3","nonce":"717abed166c56d1fddcdda38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"03f61c0e3fee24828c34bfde5bc17eb5ad0f9c9b5221c15a47f029d3e049ff851459e25801ed1409e708c291be","nonce":"717abed166c56d1fddcdda3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"b9142287dedeb38f00276516b0239db6719475083a45ac21eb2c085bcfb2446214911f5f55237212dff1afc9bf","nonce":"717abed166c56d1fddcdda3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"fa2f44befe3919a714e6fd36bfc0380b0539668e0e0d9dafb8ca01fecc8028e38f0b943e120ffaeb1e8d6f229a","nonce":"717abed166c56d1fddcdda25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"d6f9a1ae300dc12ff8ffb75f612bd83fa6c08ac012b8581cb49fdfc0fcc5bb6d86cd566360119f44516a86652c","nonce":"717abed166c56d1fddcdda24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"dae5bf874a568871348f195768ff0e9564bbfa7cc6fc68f97b283a7bd35920e610f8075bdf90c10b05a9671c9e","nonce":"717abed166c56d1fddcdda27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"e3c630fd2a48ce3370cb68927e362c2a3db6119f0e13d6ed567515ff6547b7722cd81513df8ae8e6ef2d4e2722","nonce":"717abed166c56d1fddcdda26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"602ba7ddbfaf04c7edf526d43f6f4918cbd5bfb6f5ba4c3bdced40c524d26e98b6abef394b968272bc7fb192c2","nonce":"717abed166c56d1fddcdda21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"d41a1a169ec9cd071969820c5fcea5c8b7fc7b23d5275fa228650cf0399e57a8a7d99e29f3c2e862b784b7ecc9","nonce":"717abed166c56d1fddcdda20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"8e6a320a603b12e1d554b16573ad54d893c69779f95ddfb655da18eccee618bd90fdccb6fa960721322c62f2b3","nonce":"717abed166c56d1fddcdda23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"8de4df3b199d816d1b36c0388f0cc2205278a9dc527fa4c210052db16eaf2573b2516b30b74461e082c99d19c7","nonce":"717abed166c56d1fddcdda22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"ffe77f65ff03b1e372d10c05a3e7eb321676e5fcb247ff74f3e2d667f1770624657f92fc2359375c34d1856401","nonce":"717abed166c56d1fddcdda2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"9ceb327f3bc67c705ebade971775563068fde397ababfb2aadad3efc0fc06c937955d945179a4bb7e09341d561","nonce":"717abed166c56d1fddcdda2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"9e322675e3d0c8eac5237d128155db6cc023f6e5286de0df712595333a6175dfdad7fadf573d81b226a68eb25b","nonce":"717abed166c56d1fddcdda2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"00d81930b3a5b8c46f5858ab8e2d36db710f6fe614283580c32c958fc617e1466b0e7699b421bd75280988776b","nonce":"717abed166c56d1fddcdda2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"f6c13cf82fe661e549380c69513c62d79e6b23449a2a0f467572e391902be7e2204c501bbd79de334817808d73","nonce":"717abed166c56d1fddcdda29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"ab678e813d13fedf5da276b2fdc596854c401f0ca75fd24b28f601739a3edddc685291ef914beef685bb2c4097","nonce":"717abed166c56d1fddcdda28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"89a5acbdf2dac3688d4635b8bf886324e6a503f25acd00c9a0717a3fc5be821a80ce0b8adfbc1823f6fadde072","nonce":"717abed166c56d1fddcdda2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"f3a736b0f89de373fed9ba6b409056cdf356e8adf724a5b8cb17c2657f9cfc654ccc9ca27119632d2ae067e5ff","nonce":"717abed166c56d1fddcdda2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"363ce35f08d6e630a3d061b787b65dc2940fa63b25de8785538b5b15463311e82a155a93e63fe4b000e4328b5a","nonce":"717abed166c56d1fddcdda15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"0dde71b7af705925c1aef7668b6b69e01358bced6ef267cfe59cf1db7a625099dc6f607ac25622726a05b8d2bd","nonce":"717abed166c56d1fddcdda14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"d6b3383fa2a0023e6c6a0354908dfd5af244a082574ce469ac236415fae13f5c6962708292bde4edfd52354f91","nonce":"717abed166c56d1fddcdda17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"8d7af6fa36e74f216036d334cc69f8fb0e01a115463118ed77662d15c52da47bdb5552391cb32ec4e284589d31","nonce":"717abed166c56d1fddcdda16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"e33e1d4eaf5d2cdf793699d9cbd891815dc37ce5559a80679dc4227b6a1852036f2a4d09895bee973f129afead","nonce":"717abed166c56d1fddcdda11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"497a42557d8c59998ef7af4d6bc4cda53f78f61d8e653365ebb8a1c897459b5a25e05ce7d29f691a4447dde07e","nonce":"717abed166c56d1fddcdda10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"5238ec46949076634d6f6b0befdbabca5da6f7842d9ce541a4caee848f7ba06cdb09095d53f78012e34ed88774","nonce":"717abed166c56d1fddcdda13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"8145143c346cdab778ac01b1dbd7c4d2b77c1fba1ed9455d6c61e860492ebfe307b29274acb6ef1b0a572d1805","nonce":"717abed166c56d1fddcdda12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"b47ec20cfee8d827c87805de586103fb9c7d412bc328ceb767a992730caee8f0def11f3f00410bd74522e8e1f1","nonce":"717abed166c56d1fddcdda1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"d4c9b7e4a2f99fd0b2dc6d75db3b47fbf5bc7895875ddc73b8ae53fc3d96905d250c7fc9d94c63a23cab9f2b51","nonce":"717abed166c56d1fddcdda1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"c9296bc5eea6f878cbaa39454f6b3c9349c227b3a2408a0a11898339f1e64ffe766b9ab5afc3f45eef6a443d72","nonce":"717abed166c56d1fddcdda1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"2cd7dc374c867ca8fa9dd029a36dc99203fd65e23f33c4738beb7d24da999ce3b47ec9369ae71c47d4f61afc8d","nonce":"717abed166c56d1fddcdda1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"ebe9c5eeb76ca7daa4269c7dee4d1e50a9201d55a20f8b5e7a195f2db60a4aff1d36281b7d5e409f2806800bc4","nonce":"717abed166c56d1fddcdda19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"548a83dfa4896d93457f25827f2a4b0df573a8926fe44b185010ba6b5a484c8f688f599d938f9fe129e3984370","nonce":"717abed166c56d1fddcdda18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"5fb7926a584d2dbeb9c888dd0011789393357ca3ac161d195f2402abd6180d94e1027706274496505f00671307","nonce":"717abed166c56d1fddcdda1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"6136da3c3e1abbdc830380337e5a1947930a4e92310273ef882210771c67f30c7d763231423ca24d26fcb24f60","nonce":"717abed166c56d1fddcdda1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"a22c7f3006e874d21c187e2eb5ec57f56f52f69aa4b209a5596fd8739d93a3029b9f9de41ceb892b7975d3dcdf","nonce":"717abed166c56d1fddcdda05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"5b3c710c4d71503442f865baad410cf160aec714091d398207fff3f160717641bf3d650daef2c8740a62bbefda","nonce":"717abed166c56d1fddcdda04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"7e833cc22b63cea11d66ec9d1bbaed772c12a3b2d128ed0ba4364230e14a85b9cc49c21d2330010430132db4ea","nonce":"717abed166c56d1fddcdda07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"c8998cd27aead6cc02f67ca0be90a066ab56c48b4a5b3ef3f3d30f0f4d1aaf820b16abe65bb7578303bce8b33d","nonce":"717abed166c56d1fddcdda06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"f4ca72ef2b96ec9b53661d28d1e5ad62e34845e030c2970ffc3068fc6e0c91db99885e76f8072832fc5ca66266","nonce":"717abed166c56d1fddcdda01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"fc91cf29b56a9ff1a42b450804cc3618b2e41d5333c1d71ae6e82794296a55f8c580df4bf1e348a9e5cc29d812","nonce":"717abed166c56d1fddcdda00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"a00e7e1ac364f8f6d928c11257d7227b1ce2b9efcb296fd2fcff1d9520179d7808cc1bca22b11dd5f8372cef71","nonce":"717abed166c56d1fddcdda03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"000e20ed5fc628e8ab09be3e5bdca188e3169dd36f43a8328c33e6eaa4c5fe04c94241036a81412deef85fb943","nonce":"717abed166c56d1fddcdda02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"811d464afdf08fdbe6e104c4eb2b2422fb91baf2f97af4171dcb512d4c62f0e68394a318abf66fe7abebd6d723","nonce":"717abed166c56d1fddcdda0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"4e41f9dda7664a8b14e3bf193993991b2a082e72f488b718300bc31e7a0b66dbdf58d433a8ea4aa4c8bf6fa45e","nonce":"717abed166c56d1fddcdda0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"a2e5336ebff604072cf650a2075f2bb22af81c92b978f739296db93c053b2715a0efbec8092de067cb5cdaa7b4","nonce":"717abed166c56d1fddcdda0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"62414f0aa192c89c7c6e1454ae2b38a1e4e6f31aa7e83fe886a69a1616626179a1a191351f68138e205ceaf8df","nonce":"717abed166c56d1fddcdda0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"8c323f8a67955075f5a216b6f3d9d9250aa9934df8258db4e0592b91c79b482d0a18516f6e907071593a666141","nonce":"717abed166c56d1fddcdda09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"ae70d1441ec1b702ff2ba1588003f5dcb7337f690f459831c42dbe9cf771be10f60d8ee4ffe85136f536bb63da","nonce":"717abed166c56d1fddcdda08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"b1894e784e169fbaabb38027bcb287e1212ed3331973222bd3fae6bc06eedc607a83f1c86b61adba3e73ba9cc0","nonce":"717abed166c56d1fddcdda0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"f9184110698581ff5b3c187963ea68891e85aadd756a326b7c2dbba6c16abc11d1087ac8306b2abc4e3d6ff393","nonce":"717abed166c56d1fddcdda0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"cd000679af005b227fd1635797a9f8b552ef49158260e6d7d266a035db7c55183f6fc116a06522fdded3c8a103","nonce":"717abed166c56d1fddcdda75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"09648be5664155a74e07c4f8009da6d9774086e3d50bb3a73cf96cfa7fe925d7ea156d3bcde883b098a4964c5a","nonce":"717abed166c56d1fddcdda74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"81c4d1c33d09ab8cd6c85619b9955f8fa8dfa729e22829a541c7c1e16571b69d979c31a888c02c4d85d1e0c906","nonce":"717abed166c56d1fddcdda77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"627ea90d3325924315b1744363a6e673017a5920fc132aafd922cfbed1f92321965844cae14826be0a5c4ea721","nonce":"717abed166c56d1fddcdda76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"22e673bec6209b06e1633d66e61cdd14683148a4ad6ebee18dfa5a1550dab5ed217f65e1b3b27ac2738b98b3b5","nonce":"717abed166c56d1fddcdda71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"b71ab03d27b25614b5cc2bb056871de562c51c2a2aa3f46c470eee4341edf879d0fe961b8f4294c4cd3a2ce261","nonce":"717abed166c56d1fddcdda70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"b36865ca0b6c90581bb5be29fb8f1b417adac6464fc6f0d5c173c33f68b65657754d94e756a079e954b910d681","nonce":"717abed166c56d1fddcdda73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"01fe9d3229894641dd2224ed6b24de0b15e7f23e07db804e7a1193fa1838b408fbe80b34b7fcd33520375d4a27","nonce":"717abed166c56d1fddcdda72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"d26ecedd126f20dba90992ffe1aef7c4b5c89b859b26d07fb1021f0513b5dcfdf11038de4cdbaec066d0f0c8af","nonce":"717abed166c56d1fddcdda7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"f89d341acb84b7f37a26f07b9a93ab23b87d1d53df79f4a39127f69869904b28da040c8b1fa28212245fb7aac7","nonce":"717abed166c56d1fddcdda7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"a147f9355a3fe31574e301b66d6bc6634c49b135b1b2b482a641550d30c680e3649e723368f4b659573885cc61","nonce":"717abed166c56d1fddcdda7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"86e598e33c5ce36d7ea55e9ae6e553e4d63e128e7aea108f01b7102f467d5458dba6aad5b1bab8ce18300a2b32","nonce":"717abed166c56d1fddcdda7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"7563f3af5e25d83d3fb71b237b745e44a304dcb0e539e288e7cbaa1342868f7d46cddb3036adbb6061837b7a6d","nonce":"717abed166c56d1fddcdda79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"75868e14f0285ebff16a53777728a35a93e4b2d4adee143c77c1b3db0221183eb42081c8dfe2e3cf2c112de571","nonce":"717abed166c56d1fddcdda78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"07de13a3d9c79363239e0c7b7089f4eb5f8bdadd510520731c39cb12b3d4572a8bf242b73b478ea90edb606b56","nonce":"717abed166c56d1fddcdda7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"4649988f96c129358d659b103913590def3bb7c56b3f9f477494591619e4e0233cd848b556541cb795b194e74d","nonce":"717abed166c56d1fddcdda7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"af1f06b2addcebd95fb06977dc60f507de7d36571d8866bb44a9f77b721fde9e3de7bba7d332bcceba10715100","nonce":"717abed166c56d1fddcdda65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"ed97e4fa5add01f3d498bd4f17e0d3429f6fa8a6588618cb8efcef0b928c7e56f70f71cfe5fcb37287caa8846b","nonce":"717abed166c56d1fddcdda64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"8be169d60a883ae9b9585b495b9388f0c2ffcf864327a7179670cad85317d513c174b7580febd49234b3dfc4ea","nonce":"717abed166c56d1fddcdda67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"3ef2fafb94cb7d6d2cbfdeffe989dc45ee73b4ab6864190ce0f92981fc78ee4ecd571d676bda56623e7da68dd5","nonce":"717abed166c56d1fddcdda66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"a40c896b6978d4261cbfca73929ba6763f73bbab254c079427a5996300a13fa457787b2738f3cf01509cedca34","nonce":"717abed166c56d1fddcdda61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"35e3f57df4961fe24a3a10a002ddde99461efb0aa9419e7bb4516cc65e56b0ac4ad5142c1bd1d345e6803f52e7","nonce":"717abed166c56d1fddcdda60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"8b870d74f4c64e88f0d1a1f12ed654c11521410df06fa1d70831f4aabd1135bac39c426cc96ad70157fb65456c","nonce":"717abed166c56d1fddcdda63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"4a42c398f5e4e1051b8808dcc16386c9dae0f442eea1494a4c59903f2fcd519480b7344895ae6766ae6af2b995","nonce":"717abed166c56d1fddcdda62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"58a0256d37dbb545867705c6e14801268b382b1fba8903e6689e2c579b4149409ff0cee6b932f30e51ffbdf076","nonce":"717abed166c56d1fddcdda6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"ebeff2623969730648b59f4594316992a663e69ba680f5a9aa4d71e924ec07be68dc5ad367b14c377790b398b1","nonce":"717abed166c56d1fddcdda6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"aec59682fd52a0d12446bcf33a98a73147a5cf2e715589d12982e254695b31e0a3867afd646721d1bfc112cd16","nonce":"717abed166c56d1fddcdda6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"58eb6599b70e89be921851464bf7fd40b9bf03ed7d7df31c979021b8520c9f69dad374fa35366ef86df11c9335","nonce":"717abed166c56d1fddcdda6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"48f3062c2f95747dce1780af79b35571d981614a2477e7be2d193be823b9080e5a873b4089e218d2b757d607ef","nonce":"717abed166c56d1fddcdda69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"189e70b3aebaaeb5641f6400d666fa60ca315a44977f737eb9775debdf3f355474f210091ff2e352e4248f23e7","nonce":"717abed166c56d1fddcdda68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"90b6a5bd3bb2be005ec5aed67a8a30f5b608440a1bd6e4fdcd26b970ce5a87e2fc4f2234a40a4c824ecd590783","nonce":"717abed166c56d1fddcdda6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"a59e8316070518dfd269f7a54aed4a41523cd40f64667f778a7bbf5da29fdc366f7dc052781550c5b311cc9e1e","nonce":"717abed166c56d1fddcdda6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"57c639a025a7bb8abd0a51de2bf8619e35205c13cfa31cd54ea5bbd6d1d451489a35ed37f7657529cc8455cbc7","nonce":"717abed166c56d1fddcdda55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"296ce8b6e06d50c4aec01f57aa82e6c6913bf15193b95128515dc2910a3c487136ca55011a878e712fce6520c2","nonce":"717abed166c56d1fddcdda54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"5814b2ebcbbf0ecf416266fed5161e2d4fbe42026c4b152e8d1e7645be69a18b8a6d80316bae331c7dfce7acc1","nonce":"717abed166c56d1fddcdda57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"7eeebe0769d3c5f0e047aeee42d518abc5ce6de8fa151d4a8adde27809e5f3ad70af4ef5d2c20ebd9480404dd5","nonce":"717abed166c56d1fddcdda56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"dc534f814c1e6459f678d08d4265cfb53e9d3d1795157eb7205f14fa44867f246e61b8094c4533aebb75bd2c55","nonce":"717abed166c56d1fddcdda51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"62e6c199e90e4773a77291561005ef13bbb6ef0160de0ce746366ccc2bcbdf76818b3bf27b709819b82ca618e4","nonce":"717abed166c56d1fddcdda50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"2d910bac559ea7c11f963be1acca70d33db202ac187e1fea0fcb3fef6ad1dad9c5d3c324ceeebf30b2ead6378b","nonce":"717abed166c56d1fddcdda53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"b381de33ba4540c7f4d544346f28b7cd024d6dd0e4cc0fe899ae34aa540ebe959adcacfc0940d7b3e28e2c09af","nonce":"717abed166c56d1fddcdda52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"f9850edf21d1b4dc0a46485fbbe0e63d9d25af6eea7265fc7e7ec4006288d8b3374ace876aebe9d100da95ac7a","nonce":"717abed166c56d1fddcdda5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"b6e63dfd036153cdb23ead796774380d80558d47ad0d8f28f7fc87b34cb143ddd620dd18765bb5dc61040ed662","nonce":"717abed166c56d1fddcdda5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"008fc5ab119d4372f2b55d6f46229f7e7416279b754fe56642a888cb08367084768321cb6fbb6fe9310ddeccee","nonce":"717abed166c56d1fddcdda5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"a4f40814b5bdd8988e18d47013daad135ca7f3e55ddf4718f23d3749b20eed9559ba5a098617d13cfad5940e44","nonce":"717abed166c56d1fddcdda5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"c044c4f03ee319ed0526c071dfc6dd89b33071d8c3930ca6bc4e82ef6d517f477977529798424a825e6e615887","nonce":"717abed166c56d1fddcdda59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"fd331a57d48f60a6bfd673d2c24372866e869e319c6e6a131d70cfd9d7d85b6191b2d7434ea15ace434a49faac","nonce":"717abed166c56d1fddcdda58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"9d7a0ae2df76e7b5c09a37ef7402d888e8fb8f065e52c8e3d39ac0bf186947cc4bffe040a0af37ac26513bf7ef","nonce":"717abed166c56d1fddcdda5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"1a26044890d52e44c2d5ee26a13bed8e267cefc2fed16712f1e6368834b0c0dafd260b041e7fcff990fae6f811","nonce":"717abed166c56d1fddcdda5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"4343f2fdad90d7b0d83abfecad74cb80de341608b374aab6672186c7475ac6aa1a71453a802cb58d478d724e84","nonce":"717abed166c56d1fddcdda45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"12f22757de374d252594cffa53e8cc5173711c0fa27af7034575ad4b0b476753424a5f943fdd315f762581b60e","nonce":"717abed166c56d1fddcdda44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"651b94ac5afe347efe414bdff597d2574c3a8a630932d0d37db657eabba66fe5184b3f3c463eab9c365856a1a9","nonce":"717abed166c56d1fddcdda47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"a0927415ec39caddbc2ee30c28066fc53b7f334288dcc4c6e5f4d9c348c0a40e9ea582e09725efcbba48740c31","nonce":"717abed166c56d1fddcdda46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"4e5cd72061c872d70ee9858a5f18b713a3a2f84b5dacf0733b16afaae494cfef02d97c8308095bf65885285c22","nonce":"717abed166c56d1fddcdda41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"6c031a59038642e20329114eb6e7099bf8c045ad392ad590f8a6fe4fff6256e142f73274257e21eb3819e64f3e","nonce":"717abed166c56d1fddcdda40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"6fe64b8509fbd2abe7235514fb5dbaa7d91fee4ec7116d3f395558ccf3f6634c25b2c161c59414262da57315ee","nonce":"717abed166c56d1fddcdda43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"29100bbd15ea99156bb651f33e3d02c42db58207e501cb6c771e442874cbf0e5bebbbdc75c11a854bb7ea18bb7","nonce":"717abed166c56d1fddcdda42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"574e23ecd35cffe5e7294189f066486e2d52dce8354a8497a2c70903efcc8016bdd7449c51b89994a6d1462785","nonce":"717abed166c56d1fddcdda4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"800c476f30850ed8569a704e833cfc153e13a515b74e38cedfc5441e0037a6ed61f03941cf88a63d7f9dff7553","nonce":"717abed166c56d1fddcdda4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"7e50d840c4be77146909d8a046c8eb3158c11c4d323d0f03e8e341186449c4184357bcbc5bc5b5da5004ed0c09","nonce":"717abed166c56d1fddcdda4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"cd915629d1262234f563d2f3f095bd22d206a8f5586b7fdf1d355cacac11ea9ad43630659909e71466257313b1","nonce":"717abed166c56d1fddcdda4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"51de90705bdd54fd9ecd85952a1cb026d57600c5f03a0e9e5c5f2bbb68ec0927d291c2157bc2b25041dd695384","nonce":"717abed166c56d1fddcdda49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"164ea3c8de875808e5a29e47b6d08ef66056fe1ef7dffb4c0a0b36ba4ec93bcc66debf89a66b654a9983981ac1","nonce":"717abed166c56d1fddcdda48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"e3d969b499db113535ca2b58f7551b8ad470bbb988abf40324af52273d0a99468b8829fc1663f743cc24720fe6","nonce":"717abed166c56d1fddcdda4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"112394c1c0e494d7e3693a758646374ce11bbd5d67880d85b40fe7c2958a16f67a12fda460c8e1f676c93172aa","nonce":"717abed166c56d1fddcdda4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"ae959bf2ddb9b2518ea296f797e5866c170093a96803480fbed0aa0051d9fe6478f992fc8889be348fb787edce","nonce":"717abed166c56d1fddcddab5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"6e17c549d162d546624fcac8c32fbc6ed9a70414f54a5bf3b724b9dbad570a68b5bfca4dc22bc8e1c79a298255","nonce":"717abed166c56d1fddcddab4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"bcccec14400b8159cf5e15c4e2ee8adcc01888f906d3f6a046b5b6ed661dede162dfc02c4b00ee5133b4e21768","nonce":"717abed166c56d1fddcddab7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"bc99c62f79dd45d611d53b7f3069915c106c8faebcaab5648a22414632aca42e0818f0712596f85beaac9ddc71","nonce":"717abed166c56d1fddcddab6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"6e5eee9a440074f7e23168bcaa79e5ff5b19ec3ee0b0fd92a2657979fb31a2aab34099c1de9b151c61a969fa2c","nonce":"717abed166c56d1fddcddab1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"72bc475aa6aae0a3941d4ea1d477ce26290e3b9be8531f1d755b9b5272dedb018c02d71be37a31a1be993f820f","nonce":"717abed166c56d1fddcddab0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"f26293aceb1d9c815cb6702773025315bd935bc0e2e9456d504b3ddd38a0f71fb77f9839ab7e168b1b98e38ce2","nonce":"717abed166c56d1fddcddab3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"3e613c8ea3fc31bff5da008ce2b1b5e44ff8f572f670c19df9fd9c7be375f1e0863f5389c49c08a131b52cbe8d","nonce":"717abed166c56d1fddcddab2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"2f46f187f29f6d55c5b1d59d335ad90334d8472f2243880ee5380c53708788a3b6b7c57c2a1b9894e338261be0","nonce":"717abed166c56d1fddcddabd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"08bc94c40468169629e634917597319b309d1b794a0815eb5347ab6510eddce8a6bf3fd601a41493b0eb25070a","nonce":"717abed166c56d1fddcddabc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"e07af1da5710d418ec0d48aa62d9c6f2eab121bf9c27b68963942a4525b9c62297c2868027c9998ac0eefb9ea0","nonce":"717abed166c56d1fddcddabf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"d295e2fff0331cda68c51baa5d83779a895706d8820e84e32a9aa9cf9d9d2c6fe5c3873ffe8e98cadf57bd9187","nonce":"717abed166c56d1fddcddabe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"e34e054775893b05f9ecd19c9b4ea900df2aecf8e71ce4f61ac5660d249217234b026f4d6b3f57e5e3f061f98c","nonce":"717abed166c56d1fddcddab9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"67d817bcf4e3cf2d3cf58d5d8ba43ed89825d19736344e5359413e1b35b67876fe9c84bdc00f80b9592f6e49bc","nonce":"717abed166c56d1fddcddab8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"a950dcf53aa04f4c415f084db853c1fb54d688d2cc57b27358fcb2b5ad1aaeb75000f16b644eef71e1e88aad74","nonce":"717abed166c56d1fddcddabb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"d15d764215d1558ea4c54cfd2fa42f1a762744ec55e641df8e9438fbc80a2a46e0c2a03d3a8e0741f1b1e8c2c9","nonce":"717abed166c56d1fddcddaba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"0b1d82c78e4bff5227faa6605daf123e746c9a99174f4d70ef87a133ee9820b7e5184ff2b7771a6ec84e59829c","nonce":"717abed166c56d1fddcddaa5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"f4284b1c7698c07c22ebd908a540969057cdec368fa15261f66cb0b8cb7b43107f9a9998d2eda51b2142832d12","nonce":"717abed166c56d1fddcddaa4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"6772da8ac4d8a8a2e56030a0406dbac96e2bc9992bf58f45cbaca04c115c672c973a9a9a0fa56e8f145c2a7d28","nonce":"717abed166c56d1fddcddaa7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"831ad4b0b0743b555c0ee160b30964a06fe36a0bfbf8091c007504d6ce1be8d53cf05ab549ea7747f116851747","nonce":"717abed166c56d1fddcddaa6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"11cdaa4a3121275d41defbb0f25252a8b998085d3b5ec999b60d74918b51e17f1c225d7d22703eafb7670d9b10","nonce":"717abed166c56d1fddcddaa1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"fbbd00986af59435ec0fcd0efbfcf75c3d2da3b07da9b1d0d1aae0b100e9fe2230e3e2f91d1a57b4560e9feb56","nonce":"717abed166c56d1fddcddaa0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"7e65bd863b941c631819b499e67ec3fb2804b4074fb05ee635365fd542807aa3f7facdcabfad3dd34f1976a505","nonce":"717abed166c56d1fddcddaa3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"68e095408c2419981937c7845670ad1af88b7d22c6bb8226e0164ca937127dbc65cfe0219792dca3dfee712555","nonce":"717abed166c56d1fddcddaa2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"e77cf5b1ebdd68f40166e3d4e92526d4374d847c8137d268b67c5792ddefa06862dd729f0c7df53d5ee8bf2a73","nonce":"717abed166c56d1fddcddaad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"c53a75e65e261355183638ce81adc7068192d1fca5fc6325bfeca667fad36bc32cd74782558418f9bcde44a464","nonce":"717abed166c56d1fddcddaac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"de2fe5a18547ee7fbd79a3b388ffad9471318dae7c89465e8e75c1fd25536e4a6c5ac5bf6c056512d42dfb8044","nonce":"717abed166c56d1fddcddaaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"e2581723c593d5e50a328f7cb85dff54f30776c1cecb876b37addfd0cae995c81694b1f0bf3f8ea882dde6acf8","nonce":"717abed166c56d1fddcddaae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"99c36ac07a2fbadb1f8594c099d48de15ba6c2ea8b1c428126d5e60891e7905258e0262f86c3c1cf444eb0400e","nonce":"717abed166c56d1fddcddaa9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"afffb17120d1873d391248a5b417cfb3edda9a74beef3f9ec51ee95b2e76fe7a18237f8fc231fa7b7ef6bbf6f9","nonce":"717abed166c56d1fddcddaa8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"84f3ef2ce4fa13a943a73912c4e277ef6c2928d7d9a2bdffc242c6f44f42008dcc3ffd5cb6fd12b48c64ef9492","nonce":"717abed166c56d1fddcddaab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"bdfe25b36862b59c19fe9065b501d84789ce8933f734021f301eed5fce3c2fa5828a0c523f6fc24a405502f963","nonce":"717abed166c56d1fddcddaaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"75cdbeec69ede51578a28802aabc4623a90c4bfa8029869e154a95bea524c876566fb2f2c77a97afee5dcc8462","nonce":"717abed166c56d1fddcdda95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"dd82a9c857bb0cc8599090d47de54924011db6261df3efeb883e1e736a9a7701da1f34f52ef04a1add874c6254","nonce":"717abed166c56d1fddcdda94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"8ec0f0048078c5ce050bf662233364f118e79d40cb394a7687e27c4e61a3bc81f760ce656bfb360284d48fae32","nonce":"717abed166c56d1fddcdda97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"73151138f68d1598c4c0392d8ac1a589a24d0f7d92d0780d7ad7f2c80d6d9c8c999fc8ac108f860ac3bd088014","nonce":"717abed166c56d1fddcdda96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"647384ce9aa16362cd01ed7ddc87c3fbd97b321c77b9132fc702ebbfccae686c64419dfe3bfe2aa71a3303328c","nonce":"717abed166c56d1fddcdda91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"5dae5e365beabb2abcb22b37a392887322b49d81052109257d4f1378ec11b964e910044df84bf422f82f70afc0","nonce":"717abed166c56d1fddcdda90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"034be7beec582ef230fcad83b5269717c82f4c0e6a1bcd2249672617f3c5e338010ee9ed018d0f86ede0bf31eb","nonce":"717abed166c56d1fddcdda93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"c2166e8de94ddbf399e3c65819b077b715a907059b7665c96506a3be276309d37d71186c5a8fffff717dcf026f","nonce":"717abed166c56d1fddcdda92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"de191841b437997b1495c82db77a0532044aeb002469296a5720414d175a25e01d2f0776095680645eb7df4f5b","nonce":"717abed166c56d1fddcdda9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"db6468e065c809e5bc4fd6c72cdc83ffc360bd4009c756507bcb2b7be193e73949bb0b48970dd5841adce607ca","nonce":"717abed166c56d1fddcdda9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"b06e329d9e1101e2d734f831db009369935226e79dbf17f10216327e73099f6d5f74a71adf7b9c17dbdb4caa0f","nonce":"717abed166c56d1fddcdda9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"cd217a4deedfda2c8391dd21f3dd21f0770626b5c7ff8ae235a2cee8e49bb43cec078a4d9bbf8779f56c75c0b2","nonce":"717abed166c56d1fddcdda9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"813d8be0e4b662cafa2b86d3955276a44ea462c2077e647f91fb4e465259459cbc797c841ecb76ac66ee604e45","nonce":"717abed166c56d1fddcdda99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"aafb626a031da30779fdd4382d1106aaa91a8ce363927d1bbf521bb7dcc55ed215ca32ba490a1b59541ae4c48f","nonce":"717abed166c56d1fddcdda98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"089520cde473bdf8c90d8e9a23933bce4dccd9c9913fae573435390e25b33f145addf2d6a254e5915188de678c","nonce":"717abed166c56d1fddcdda9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"6156f7727437bac6b2af2180b378a171e4637c132898b8c3614ecb165ff8cbde4294e2683b4572160d522c5d16","nonce":"717abed166c56d1fddcdda9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"c9b365d3c118e0c5260711be491401833375b553075c65c3ba0fb2205732380f10478b1e0187a889870d22b295","nonce":"717abed166c56d1fddcdda85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"a9a1286acf1275b42b5117ccf29b2a6a0706fdef03f28543c76d303f763d956a71b3c52e95853c351d7b478ada","nonce":"717abed166c56d1fddcdda84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"52478ec488d166bee05f2856c1cdeb6a4875dc835b89da607361a5316178b12d3566a6a5d2cac1c4e6691f41ce","nonce":"717abed166c56d1fddcdda87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"a39005f556130e5263401b76e3b4555efef7872af0f95b27f247da5369ea0aa6d5ffa01b46e343f8658e7ddcc3","nonce":"717abed166c56d1fddcdda86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"886db4a1f15d6c7f7da6daedc67f38f362d1819dd4384f74f9647c26ae99f9d24b807e1591c98be4bb9ac9b812","nonce":"717abed166c56d1fddcdda81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"efaa3f14385e2119c4fcef2a07c4819066c59ee319c55c030631e36f560725e9f1143793f573ca5c3d29d9e461","nonce":"717abed166c56d1fddcdda80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"5403c64b16caea7cba9ab09a61943b365fede084ccbaf3442f8622f4805ec5278340533d079b3b8531c42e5144","nonce":"717abed166c56d1fddcdda83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"e598e5d0b5f34d07be33eba0351c9da239c0ffebeb31188dd8536d8c22c566f3abdc8906e5c7b220f2c42cfa31","nonce":"717abed166c56d1fddcdda82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"d61af0c7ba06ec7cbe0f928ada472f4a7413f4a6222d1c84b648cda4b9299f1082c2101ef34222786a0b7f2339","nonce":"717abed166c56d1fddcdda8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"54763cadeb56df8ecb68357cf2cf81655742e9d486768bec2e663abce3550b07acbc491adb57a616e947009379","nonce":"717abed166c56d1fddcdda8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"2f2d7421cba19a84403e4d35a8c06a4245b2ad99e0015b438387b2311a2cedd36d1920f6ba2482c0d81d37b80f","nonce":"717abed166c56d1fddcdda8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"0ad7a9eb32aadb4bd45c62769bb90bd98c371866b05465f46a29e4bac304ef71b64c98ef999ad7e3fe9647f513","nonce":"717abed166c56d1fddcdda8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"9dd3427e67a0e7e2c29afe02b68f4b5a4a23cb2e99ac6436a03a59ced0b8809ca6eb20fdc8b0846ec2d816b285","nonce":"717abed166c56d1fddcdda89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"0356043b51f2d84a25e6ce9425a191a123d3ce0cb1a65dafd418b5804ecffdecf2811cdb945edd5579bd5f0a74","nonce":"717abed166c56d1fddcdda88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"b0cb1186c62b6b63d54b8733dd6f496b47c16bfc63c875e41445b12f1dd3bee0a71327574f8d728197f375e18b","nonce":"717abed166c56d1fddcdda8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"1c7809b877dd2e728360f4b7ac658e43c3cc23adc559e9623a76f5b2029796e805ea62573d0b88131c66e15c30","nonce":"717abed166c56d1fddcdda8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"6388f23ab008065226b96437e990bbc6c791969493f43daeaa5d8c399a825cdb4a6c030a877315615767d8855d","nonce":"717abed166c56d1fddcddaf5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"8966b4b231134b132d6ffe0a0aac8c6ba0a2d57b81dd19f94b5fa5ac211ce1d0a2c6a5241159a7b5b38275f560","nonce":"717abed166c56d1fddcddaf4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"813967417ac48688d57c3cd3b10d3becc486e8b54c167cb695b16b750cc0c54c1202dd5904a3e125922563d66f","nonce":"717abed166c56d1fddcddaf7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"858707d7f38110cbae2d1cebbaad80330851e5ef2b032c9ad9bfe77d83b4190cb7e73492dcbaca3c0f02dbe607","nonce":"717abed166c56d1fddcddaf6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"34d085d1bf67cc0418fd8ccbec69b534d3d53d96e5b1592fbd8b6428c9af56f76704f217213d6e73538cd0f16b","nonce":"717abed166c56d1fddcddaf1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"580da26100acdfb82801c9c1647b609558ccaeb4e143638c791a8aa73f686790c4c83d7cac6265c73e333b5527","nonce":"717abed166c56d1fddcddaf0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"69c8ff0306aba2c5a0fe779fa3f5c1fe8e78e4c35ab3628e3d41bf0c14c89dfdadc34a281c5cd32f3c5e66f930","nonce":"717abed166c56d1fddcddaf3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"95def399fefc8098baad318b48ff7e0de3410a7a346a0c28df83a6fa00c9c7a6c1745501765d5f28e6ae467012","nonce":"717abed166c56d1fddcddaf2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"ecfa003e3af54ce289236f60ba9be37fb42082be68ffa09280badd9b73ec3ad8e60ad825c8bfd168e0b92e2bb3","nonce":"717abed166c56d1fddcddafd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"046d55371055180bb5d2aab3f9d43e7acdf508ac7ae4035420591bcb15d97151f0b90c5dd7f6e5cc0fdb8079f8","nonce":"717abed166c56d1fddcddafc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"22dd6ac09f85f4f2ed0d623a591bfcefe9f8479471e368fe08f1559672c27d00e8816783b9e9b9676cd7888f41","nonce":"717abed166c56d1fddcddaff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"1c93802e9283976c9963fc54421b55a42d9144e9c053365bc26f3697be7217a2c75edb459179febe887582ede8","nonce":"717abed166c56d1fddcddafe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"a27c37d8ac12650f48029a2ef33d740f507cdfba8d8811d7c87b27ffa7e2f9cf15e7fab0ec442651be431f782a","nonce":"717abed166c56d1fddcddaf9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"94e7a8724db3e69fd0c1dc4d221ef08e1fec1382e115138b4f93fae0fcc27100be21b455cd78df0543304b6da7","nonce":"717abed166c56d1fddcddaf8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"4a25d7a9f784936c977d9f6ce9bab87b4172d2493ff25d584bcb9f0ced619f3aae5c08056b1c67de31410ca4d6","nonce":"717abed166c56d1fddcddafb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"0e7bd3d02d36209066cbeb38b48b3e76e30e2cc0b6694604318180467e1d84dda440f20b11cbf8e6011d7eb58d","nonce":"717abed166c56d1fddcddafa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"9329ea5931c9f9ae34660663fe4c763a92334d238ef26fb87c72fc9664b3bafcdc9127a425835e28bb3dd21893","nonce":"717abed166c56d1fddcddae5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"a710192d6a9f37e66be06dad20bb80ffb175689cc85b1082ed70057d16eacca74a17dad3fa3c238cc82cc6291f","nonce":"717abed166c56d1fddcddae4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"cdc720225df40bd905651e132ba1c0817a31978675d2e8adf77ff0607dd0be703b8db01934c78bfc0a3c305534","nonce":"717abed166c56d1fddcddae7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"cbe6d4c4fa512d963a99a7b0ea4644d2a74d93e8e42a525913eda840728053cf0a1a930c1d63e7e6cd394fb618","nonce":"717abed166c56d1fddcddae6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"f52d479d614a94dda141636dae1c1b55db490b397e9d8f8cb9509e267338a04e484eabfc432e96cb7141ea6f84","nonce":"717abed166c56d1fddcddae1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"810697c0d979db79fc745a7d9c679f77d2e6f9429efa0df30d7529dc1a60a44c54107008034a96ec69badbbb9d","nonce":"717abed166c56d1fddcddae0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"318423326ed5f1c3e11e1c9c1b489d1dec83e35759f960506478d3357539a163879008ffdccf7fa6e38d7162b9","nonce":"717abed166c56d1fddcddae3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"d0fc7371112f71e1ff4bfffbf567d984e4a8f7ad544e9bffd7eb12b3049df297642d171c78bd0c7da32d146e33","nonce":"717abed166c56d1fddcddae2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"3b7c675dc785c151cae7632993be37301c489ae1f8b1a269ac6d4ed1e616fb7d798f39a0137852556de9ce1796","nonce":"717abed166c56d1fddcddaed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"d8762eafb22c14e41213715f83b439db502e37ea3980ab87e63f6121aae644599514871aa8c7d0a8322c6ea5c0","nonce":"717abed166c56d1fddcddaec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"3ad30d284c4a50e707fc60ec160e38cbe5890ac3a0d3ed028a2aa5b91097ac37c5d1377455caef64238961fb9e","nonce":"717abed166c56d1fddcddaef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"21354e530a0c3d9eebb3f79580d1eff45bbe9587f6816797dec1334970c18bd9766b417ddc03104b5d057a282a","nonce":"717abed166c56d1fddcddaee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"f8aa091999ab48b5eff6ffbeafd34bd9f127c25f29a26683b5699c703cffd0192c6b19c6842449ec9bf3b9877e","nonce":"717abed166c56d1fddcddae9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"270a75cca1f817fa34433420bb7912e9ff405119cc161146f56965547ab1976ffe19c026b09cfda75a48e6d176","nonce":"717abed166c56d1fddcddae8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"d8ef8cf3cc1d2c01cc1cde9076ccce75473cb212feaf0831f1563f6fc47b433c3ad7a50722af373901ed9843d2","nonce":"717abed166c56d1fddcddaeb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"fbf386dc51fff637d57a34a9699634e23f0e6b16e6744385c2f265870364454ea24e673736f78b1ba2c0a75c3b","nonce":"717abed166c56d1fddcddaea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"fc1b187a50ca976db1f69810246ede514e0ac794b409da2b4a1500b1f91067ffee7325aea3912324a5006a2ae4","nonce":"717abed166c56d1fddcddad5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"84f454f012ee1c46bee2e19b2aff6b655d29a271c79616f58f8f9ca116bf90f18cb473a7e9ed1a7edd7de43b2a","nonce":"717abed166c56d1fddcddad4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"c2a0da5771d1d448b2de522d93019f39853c4c1473bbc10b22291043e384f3635da618e49b529bfa18d1bfe6db","nonce":"717abed166c56d1fddcddad7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"084b745bb3992da8cf35c417bf23b77c64ed52f4d0e0365856b12063f5d737f7119d3f86c9af8d3330344ff0b2","nonce":"717abed166c56d1fddcddad6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"a10c023473991fc5693d0d9947a970fffdee945bd9e87b46ffc9d7410ad30fba984333435c16c9310530730fd6","nonce":"717abed166c56d1fddcddad1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"15f9a97b3e7ea4d824a52616137b4bfc4abb8f43fc0369774d10444db6ffc07af3e63457111c9212634654d860","nonce":"717abed166c56d1fddcddad0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"cbfb198a4cfac8885f5304a59b6db6112477aa294956e1ac183b7884902b086475ce1afa2eb0ee4dd78eca7bca","nonce":"717abed166c56d1fddcddad3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"a7badad5a9eada7363ad750dd8e3f11dd71b7b574cc345f05c5f41c6a7b6f605f2486e8e7583824cc6b7a54b3e","nonce":"717abed166c56d1fddcddad2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"a7e34dd32e0990a6a9a335e6376be837fcdaa8ef8d57fcfb38435e0fcf8049f90bd3ffcf9b92b6d8744a268c07","nonce":"717abed166c56d1fddcddadd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"f32e6910d422674d25d6e86a7396f8421d9d9cd802a93f91227874dda8829e72aa55a67cfcdebeef299daf0117","nonce":"717abed166c56d1fddcddadc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"38aef613f5b67a894c03a08f2745b77fcd421c81e32153c2d73912341187bc44334e33bdeb6d60817045f5c296","nonce":"717abed166c56d1fddcddadf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"0bc06bf390cbcccf0851777452e776b291b404b22ebf64eea48d7afa670e19f778b63c425dc8915b5724d52469","nonce":"717abed166c56d1fddcddade","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"00d74585c2743875bcb56b98d0ebac498cd2e664289f4c80eba02ee722bf4ee0924988cc570ccb3e52dde81dd3","nonce":"717abed166c56d1fddcddad9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"23a22c6ff7d696909b3501dc5ffeb6dc3ef6737565df99d12bfa6cac5659635e0df7973ee447c6581b69e1394b","nonce":"717abed166c56d1fddcddad8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"da2f662e2be9718c85163ab85ea5e76a0571df37a2445ec6b6c6dcd13aef48d70ca7fbd7ffbdc398d904ccf465","nonce":"717abed166c56d1fddcddadb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"89850380180af7cb39e15ab34b0b7d76f91b9144f1f06964afd628b9aeb9a1d841af16e2fe90ecd43f02f63e38","nonce":"717abed166c56d1fddcddada","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"e99354a1312ef64efda3285ea81b1a0fbc39253243be3f1dabb288726e68ad1e1924c33451c5e72f5dccaedfce","nonce":"717abed166c56d1fddcddac5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"0cb3054b5a6fabc9f93d49c13c64ea759473427dece9c28caed74ccb82428c862ddd340a4ce9045b060a8a8be3","nonce":"717abed166c56d1fddcddac4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"690b482fd3d29fe7c00ccd2758984104a423e134a8c507fbf4dae5fd3c663b8260e248c07699d226123f1d22cc","nonce":"717abed166c56d1fddcddac7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"a232fce9bb13c031e001a129254404bc765ba2d76f26166c60deb4aaaec6b7d29dd1cd712212d32ae977ea5d40","nonce":"717abed166c56d1fddcddac6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"44e62508cb51b1edfecc30ae9cf534c102b5a0ae2f391531605d5b8d403fb1f5b94957007b1deafe2531165629","nonce":"717abed166c56d1fddcddac1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"0b7c5a000cfb019d9a56a00e929337bddc4777fdedafd58c7b6ccb18b377054a4196911dd2b7471d6738eca054","nonce":"717abed166c56d1fddcddac0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"188d73f4a6b6fbdc4eb6da55e5711bbf486753da0a45319c4fdee3aeb379ee1ac8cc9ee946e3ad9b9192aa1bb1","nonce":"717abed166c56d1fddcddac3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"e04a682bc37ecac08210d97dbb3fdae34533624778d866d058953d00275141509e417c015231abae183680891a","nonce":"717abed166c56d1fddcddac2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"68d24e820a3e725532ecd44fd03b272614e22b9544bffd98b06cdbed59408fedb26292330c55aa65b459029e0b","nonce":"717abed166c56d1fddcddacd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"1825c3ecf247410bce9c2f3ac8c8051a2f008f84ea6bc0930ef84fea0a23bd39e478fa90e3f031836f9c99fc1a","nonce":"717abed166c56d1fddcddacc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"1ea57147369d014da8852ab2664ecee1e91257b41924b1e83ca04127326a5e6d9f1a38c4a41d74f9c082ffab69","nonce":"717abed166c56d1fddcddacf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"d9ad1123f74b86a9c2c65d422dfb40f804b102c2bde7a74dde7ab3abf977545446e9843ff44a3e28a4bc4f0cb9","nonce":"717abed166c56d1fddcddace","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"c4f08b36a74f3ec43e6f5cb8e3481ef08aed98d5ed5bcb9e03826d148f9a2d757bc4d72a6083f5bb58dacb5fdc","nonce":"717abed166c56d1fddcddac9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"159229205d0c042af8fb59f830b7be8a7a06dc470312e33ee94466b9716695472f8af2df051c9d1611118aaab9","nonce":"717abed166c56d1fddcddac8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"4a8913a9d2464523d79e676d5d0c5c71c7b905597b5691fed0109fa722288309550f44a78c81aca758427d0631","nonce":"717abed166c56d1fddcddacb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"45f5db5031fe65e55a3b2827e827bb8fe332faad22fff747122ead289d06a870787f38dea1e9c3146757e12b07","nonce":"717abed166c56d1fddcddaca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"8fb25056e9c244f7d71740ce921e9f6d535cc1862e0bad8e9653a26da675a893da8a1b05520f7ba17b30b68892","nonce":"717abed166c56d1fddcddb35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"80f8e93089b537ee16e5a7f91d24fdbf25a59be1edf23c3baac1d1c61d575bdd"},{"exporter_context":"00","L":32,"exported_value":"80a38c0e041d70528c099c1a80ba0ff9a5c7a863c06204a7169502980ad0cbbb"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"727d60277c989e769f7b0b756fb53876577abcce4ded9ae7e78131e9521a9a8c"}]},{"mode":0,"kem_id":16,"kdf_id":3,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"00ce2efe8126c7e8d34ebc534236ac12349c5e7f447ec0366d2407310064f090","ikmE":"0054c11ef3b76a2be6e5f52aef83f177926e958238feac7cd32cd858a0fd6921","skRm":"54273b41f2bc4a962587ecad85253b6a950c3d954faa853f317e308b8feb78bd","skEm":"a7f0d7fd1c803fc17168944911f0a0fe6046badfe7220d13a337f2eadd3eb381","pkRm":"044e67f37522408dbf7ba777936156b26dfdfe10f9aa1ee917597bfb99a50945fd408b2cc84cf17893ab78a73492c537dff1074d3155037ac26bf65c52e0c9225e","pkEm":"0439aa3737c462e078499c3890227ad3c07266aa3f774cb8133ec33aa63da5c6bbb36c5b55872f4c4958f58b98c3c20be23f7c39b6b83201995c44f4d2ce2ec50d","enc":"0439aa3737c462e078499c3890227ad3c07266aa3f774cb8133ec33aa63da5c6bbb36c5b55872f4c4958f58b98c3c20be23f7c39b6b83201995c44f4d2ce2ec50d","shared_secret":"5e09b8a2d1520f3b95a3b7ce1a2e1bd7241f94173671890cd2f0a5e26395beec","key_schedule_context":"00bc71466af15b2cc51961c551d1c006f9dbdda3be795ccbb980f169ea6fb31003474b10dc797383ffb0325aff5f75701a7bfd781c6298a5637f7a8fa2e6b5f624ef4b8a36b914c26820d53e83a9dfb742c7811a526e9dcfb2f19f895c68c80dd54c6e836af7133e4b89418b17bdf4c1d32445ee0bc0f40063a0dfc0e0913cc37f","secret":"d806b29b3fc52685c1dc3614f396de35cfbcd434f2554b089728f125a06e1f2e3c1775c7e4b867e5dbafe796a64d7a0bb2734b7e4473d17e63cc37e4618eb98a","key":"b021da92b415c8e34f9bd5ce5aaf5d035370efdae442d27904d77cac8998db2c","base_nonce":"5b5bc32ee9f048e30b993821","exporter_secret":"5968080e2d97de466219a015b275e1e472bc07a13f9235a31f885330de37cc09825c50c1aad932a279aeb331175b530ad1d2b50ae08edafd58fc64100398d366","encryptions":[{"aad":"436f756e742d30","ciphertext":"360e9bd07bfee00047055d53bac45ccae7d5bc343d026e2650bb4d4768899b80a692cf231835609da16d0a7093","nonce":"5b5bc32ee9f048e30b993821","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"356a0f404ac3ff9d33791079f129715e1fee87030dc6cc3ce406d5d99c6e61d4f2e54cbd2bb38edf9f89ffb07f","nonce":"5b5bc32ee9f048e30b993820","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"0555a829ed5afec69f3d1d188ce98774fab474ebe55eea7a4f857953ae6c0a6cf9ffd1d09d6dd10cb4a5f9dc49","nonce":"5b5bc32ee9f048e30b993823","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"53a8c4ebdb72aed4f73c3a2efb9b53b9058e9d3988044d962d29eff7ee043afa6977780dfd58c57d786605f2b9","nonce":"5b5bc32ee9f048e30b993822","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"9ccc5b648491019ca622193027fa4d578209d5c3355d6056e96b908eb2476b6b8d2d86a0da6eef90aa0c7d32dd","nonce":"5b5bc32ee9f048e30b993825","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"f85741b2aed028ba9aca822c075706c48623842eb8004e237fe05415c02a8cde0ba232576486d885a5ade6cdfa","nonce":"5b5bc32ee9f048e30b993824","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"0f2443c611ad1b7258753295a0b54a019d15094694add726a4ccb0bf60cec84b11024769cbd9ae5b1f2bceeb4f","nonce":"5b5bc32ee9f048e30b993827","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"e48cda5d612c0f2ca17826692313dd19fca21f322d8285e608c304b6ce213709edde15832495830d3040f8ffb9","nonce":"5b5bc32ee9f048e30b993826","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"fd3d474c5dcabfc4507ae90257979753579fd976f0e9395bbda538d5c878d9c97e4be3a79a1c3e8c26bb8d6f63","nonce":"5b5bc32ee9f048e30b993829","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"b9509f131415d00781a4c8904da5c4bff36c45a94c3c2b4ee171adc12ef7d62944f6c4ff2a8bad1a6b2aa03aa1","nonce":"5b5bc32ee9f048e30b993828","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"803cc841eac25d020d9f853b6aff8ff528180b8624c56ade849a6c5c024110bdc3f96411cf097e74ffc7b5894b","nonce":"5b5bc32ee9f048e30b99382b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"20ad0534c516b4fd9024a52b3e56fd4c35c6ef7fae14f114bb65c4cad5cc4ec2cf77a0c56ba88989bdcefd04e6","nonce":"5b5bc32ee9f048e30b99382a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"33e84ce46f01d634cf261295e7afbe2e466215578da878f6ee81986118e402c7f65c519148a20569986c16e6be","nonce":"5b5bc32ee9f048e30b99382d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"0e2acd1cc964d5563761e182fb4e38b896d4fb338a52f80ca5ffb59bd5ab4dd1075ad02041ae0136e572b86bc7","nonce":"5b5bc32ee9f048e30b99382c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"841abd0cda11500613ae9a14825e12c78c45c16da68cab77f54e6838cc5ea478a1dd085a03765a3b074417fcd2","nonce":"5b5bc32ee9f048e30b99382f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"fec985a08ce78e4ff9423aca78f709cb39bbe243664bd6b069844dd385d89ac0c30e93bc4c2a03166d958dd0eb","nonce":"5b5bc32ee9f048e30b99382e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"32132be4737259bcd3dd4801ea93a0f4f276a2d3d10ebd0d85d4e268426e3d3aa4805f8be431a28ff4f5d5e6eb","nonce":"5b5bc32ee9f048e30b993831","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"a04fb46f6412fbac991e8f9fc2ac8371682a308eaeb6403743f2720df27cd8bcd18fbc124c0afc1cf26075ced3","nonce":"5b5bc32ee9f048e30b993830","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"2c8eab2d0c17c37d2615d7c5b5c9276c53b5d86502b4d872db3febfd8af38813dcbf8878f47bc5b36218b0116a","nonce":"5b5bc32ee9f048e30b993833","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"56d0702b7ee5ca1fd9254e78160cb800f8eb0eaf87335f0c7952755b3aece91114fa15eb810e5bfd000f8d515f","nonce":"5b5bc32ee9f048e30b993832","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"7e3506c7f2e582112795ad8a2ada4e1443e241a84caa1f2233e1dca6760e4537055153f04ee7c9e7162a1f6032","nonce":"5b5bc32ee9f048e30b993835","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"e60726649583cf628cfed51598c51093245c14a6dc5877fac5d00ed022d2cbe0a437c6cec8fba0939defec582c","nonce":"5b5bc32ee9f048e30b993834","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"64a6d54b5c29b4a97d678d20c73e5816692d33c2f0609067c7c5377438e97a101fab9f7cd0b24a8cc0bd57df25","nonce":"5b5bc32ee9f048e30b993837","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"0236b0bb66ca7c97c3efe1cee406e059c314482985d208f1371c3598cea9febbbe14779d0c7de90758faa18ba3","nonce":"5b5bc32ee9f048e30b993836","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"14e40b3d6fcfbd67d6ab6ce62e7e65cde91919683d2c17d8402dabfc1c768635552d43b5f7557ce6cfa7f5521f","nonce":"5b5bc32ee9f048e30b993839","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"26cb21eeb180f2332602ae5170e88e0efc0356db3414f262b57b2581d8c41843511800a6c9c92ab4e38f5ddefb","nonce":"5b5bc32ee9f048e30b993838","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"bc1d1e6908d8d8c3fd5a9851e7669ace1e0ab1d265cba1c3c0fc8ba7d331e6380e9c6791fbd8623797fb0333d0","nonce":"5b5bc32ee9f048e30b99383b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"c0f5116ded57a7332f34a81d1a84f13ea6a0bb468bedd4755cac0479b8617caf9b2fdbaab8f88633484dd4be4b","nonce":"5b5bc32ee9f048e30b99383a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"0bff540a1e396ef839967e4027501696417aba7512ba0ed94865e5292b29acd27986b1ca5870da5f026c47b325","nonce":"5b5bc32ee9f048e30b99383d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"5eb478e4a942635e4289ec2bf1578764385d58d094a75076f28bbaae899712bce6fb45e31d7b50bbb334e7c212","nonce":"5b5bc32ee9f048e30b99383c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"58b5a31f1b14f73bac5a957a16594cdb902dee73cffffc6ee6c5fb6cb23d196d6363e73f9974f208ca1cef2bc1","nonce":"5b5bc32ee9f048e30b99383f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"67ce3e46a8b360a5dd2c87da68107233af53c61d87f356c5196fcf692a662f9dabcd4219164d255dc4b98522e8","nonce":"5b5bc32ee9f048e30b99383e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"eb3c0b70c1f978386174bb5173669b5b317c736a936db9fb7c846e38a9a813fed5b3975e4b0faaeebf2e0c4ded","nonce":"5b5bc32ee9f048e30b993801","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"e2083f7b5bc5cb4557c3e788e2debaba631873dbaf69e11e6171b2a71615533fb00c792af7ce1df9f31602a096","nonce":"5b5bc32ee9f048e30b993800","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"a967549ef49e0b11f73580a0383975cb87364b619824c254a32163479ce01aa728791ef3ae68e396cd2358d70d","nonce":"5b5bc32ee9f048e30b993803","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"dacc85c3e6164da975a18d5a5814a84473a37dd76be4ccb3e1998107486fd3bc7eb6ecc2ee364d386caec9ee0c","nonce":"5b5bc32ee9f048e30b993802","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"1a51445da0d3d8cda050d5b919346b5110533b7920f609f532314ed93a0fc728c451d0ac787e96dcb5ebe36d8b","nonce":"5b5bc32ee9f048e30b993805","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"1e774e1b6d66ac1b6a441b9f62cd9cf6641f81f4e8599847d99fddf61aef8a9bc21316e78b8e62373ee8514a5a","nonce":"5b5bc32ee9f048e30b993804","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"59edc5380bc015a80ba73b7d96fbc72f9b3d94eb2dcc4ba953704275bfeadd27fecd5604431450f696e3700e51","nonce":"5b5bc32ee9f048e30b993807","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"c0a69c7ab9257a4479a4fda97334243573eadfad52fc745f40ee5774a5f35f64a2f7739d0515becb2d1c6e68c3","nonce":"5b5bc32ee9f048e30b993806","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"c4c8116c2128137ad88d6933423a7c01dceb13ddce90d091cc686f99fbe44125f6bd1b0b20f8f1bd73a4ebf8b1","nonce":"5b5bc32ee9f048e30b993809","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"2246c7292f7523a0868697af395143ee199f4be406d11ef28e66e4c6604b76ccf84e1926fec041a0a5d6a116ac","nonce":"5b5bc32ee9f048e30b993808","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"d94f751ba936ab8beb14f9196ae0ca9a4749c279ec3185f840fbe0bf54c2563e130789838516a01e796cc53ab4","nonce":"5b5bc32ee9f048e30b99380b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"49648025582bd03da05492938f4a2df2313b335b4aa2f6c8d5f28dda45255354c69df9d6e7995ae48b65b626e2","nonce":"5b5bc32ee9f048e30b99380a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"763948ed61fe56371171f6cd4b1065d15929ce45dc43095f10594f4c526d56b00a78860b26bb63e6346dfba7f8","nonce":"5b5bc32ee9f048e30b99380d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"a913ce6cfbebdacfe15463aa6f519bd33410a2929e05bd1e7d7aaaf5fb0bd924a5df20d9abc93d15621486e72a","nonce":"5b5bc32ee9f048e30b99380c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"ffc5f8bc2d3d0248c4be82ee215f3f449e237fee63a3ea59afcee3b55b022740e27476b3691338264ea6bcfabc","nonce":"5b5bc32ee9f048e30b99380f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"452968384e519dd7e4fb76b199237ba7d7f264a9b6efcd50b6f356e630c5988d2cb7e9faecbbb396631b94c1ed","nonce":"5b5bc32ee9f048e30b99380e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"ca7bfa9b88a798fe61148eac9a1604813c2eee1934846ab5bc2572fee9a03dceb24f5229c40af591deebcdba77","nonce":"5b5bc32ee9f048e30b993811","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"80e5bba6598fa3e6a78cfa74e5e52c2682e2b1b835ab4ebf5c299d7581fc413b09f4509a48ce94a71330170f03","nonce":"5b5bc32ee9f048e30b993810","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"057f119da75208ff547f9a55215a360e0b6f7b2e477a49fe2d053d5f6e91a4d131b60c073da60b7e41721d4531","nonce":"5b5bc32ee9f048e30b993813","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"dae8407e9cd1e9d467f156a2e131613818eec23cea347c15fd642b4c05107d8ab0a2ce627aa14a28bee3c2cf7c","nonce":"5b5bc32ee9f048e30b993812","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"40a4fec867388262386ed2913b81c1a59c1161430c02abe3c73044b48ff814d88ef692b5fba34c10b097300a0c","nonce":"5b5bc32ee9f048e30b993815","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"47266232414c2a80a1a83a6099d346683f86110efb841d17664eeceb59e361c102e77184f3dc45c9263f0cd330","nonce":"5b5bc32ee9f048e30b993814","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"5c489d50e4c4be9ba2cca975d03fd76659d811f57afaafbbb1299f589ca013109f58ce9c0e4f96919d4393731b","nonce":"5b5bc32ee9f048e30b993817","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"bbab7ce79ac3bd357160fe8518407af90d8d589b92040881fef65a2c25701af98d7dbf04d87fd3a121a1d6d027","nonce":"5b5bc32ee9f048e30b993816","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"75ed619d0ff5336a24e5588365d2f4fdde6f8c28304c47ac07bfab503ed3d33d48b88dce37036906872f72cbf9","nonce":"5b5bc32ee9f048e30b993819","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"fddc20c3c6692743dcb7571932f802fca27fe2e8a59e0b65ee0fb4fb6c9478a304d7b6b9ab3b450137422d7526","nonce":"5b5bc32ee9f048e30b993818","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"6e33e3c226aa590b857e5b23afbb8da0cc68c0d7e95a8caebd60d7c2c7b8707c49d974dc6801ea7c9aa6566e44","nonce":"5b5bc32ee9f048e30b99381b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"989fb5b49bdba8d3a088a5c0ce7247efdb0eff09a0167e71ce488dea87283d7cea94a7d2615503dac67aa8ccfd","nonce":"5b5bc32ee9f048e30b99381a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"bbdf58dfca3d993d8788ef0a13e59c43a848c9bf69bad81d07d1bade16d51205440e429bf1bd0e1ef4d99c2a30","nonce":"5b5bc32ee9f048e30b99381d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"4384207c8ae67c202ea8cb14e103ced9b9b8b318ced952340db7d6abef4ce413696a73c281c3a4474696ebde9b","nonce":"5b5bc32ee9f048e30b99381c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"76a498874488f283aa080fc14fca2e2c847be3469f152d388e6307107ed6e6094a47a27c694eb78ba62aa55ed7","nonce":"5b5bc32ee9f048e30b99381f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"56ded774f38d20c1bd66f3b30c7744bd9c444f1e6f58752b55db73719610031d657c37c2a26d6d875cca83d4d0","nonce":"5b5bc32ee9f048e30b99381e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"f7ef6484597c969cd75f71a0c166a269a3d2c3eca71f4429679eec8caaeee1d33007d33d3e76a4deef15013fe6","nonce":"5b5bc32ee9f048e30b993861","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"4d094c3a69133952bbe6ae0dd7f0465f4cd178850a65f0264f44198e51b56c27b53630839e9e2afc88b65a1b97","nonce":"5b5bc32ee9f048e30b993860","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"235fbfa5b236d74aeda4f453eeecaba2001d00feecf8b4921656619639c1bc34a0b2f8abd402a751d553e1d0f8","nonce":"5b5bc32ee9f048e30b993863","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"0b38d35bc089f2723f739d5a4af5679c833098bc8e1f5a5986c672c34866fe1e2ff37c5f1d5798ffea4b9c6ebe","nonce":"5b5bc32ee9f048e30b993862","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"04d6bd0da82e18dc9dfa821fafbb233a45e801a42005cf5c67b2ba3ce89900432bf18152548ab0fa1cddbf2e26","nonce":"5b5bc32ee9f048e30b993865","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"4c2e5d33abf58d3e15f0fd2c82d00189fd4e977acb2876dc0945928065a78cc92e15cc68f3e4bf692724696bd9","nonce":"5b5bc32ee9f048e30b993864","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"001c8b53121aeaee5902b2596eee709c8027794120b18be37891d1acfe08f2d8b56907e22b6cd64bcf2fa4d33c","nonce":"5b5bc32ee9f048e30b993867","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"9991806f683f12dc063a0bd3235fc0ac1aa9e34457b307fda5b4de4ab323238a88cc4ca1f09bf776b469b1195f","nonce":"5b5bc32ee9f048e30b993866","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"d930f5111af2b9a7f688c42ef5ad011e615e8d819637844cee3f47a255ea8e36ad2fc78247c45d50af5e92549b","nonce":"5b5bc32ee9f048e30b993869","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"4b6d90715cbfa169b915d15934cf0a51f993da26ab140ce6ecf4b1975a1e804849778161c3065f25542c7134cb","nonce":"5b5bc32ee9f048e30b993868","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"a808588b2d381541fbff588c0c1701fdaee8281ea16dd5839c2334ed088de535fbe48f3aefb18097800da0944f","nonce":"5b5bc32ee9f048e30b99386b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"44b4e2e1a550cae65a3b6baa1ffa4b6f3693fda51416216da91a5f57abde0f0ae7c4522ee70fae0e349520880a","nonce":"5b5bc32ee9f048e30b99386a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"1d9657c5853ace53182436aa0c9f37c7267a96c127513eecc812849f8fe58484b1f1e948d2a50f660a1e67d5d2","nonce":"5b5bc32ee9f048e30b99386d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"4084624f5c6d4f2c6e21cbeb9794854e816eeb22dd76e173df164d385c50aa45603754ea982d9a5c5aecb4d34c","nonce":"5b5bc32ee9f048e30b99386c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"9358e19782d3b43bf5642b363984a5f306022e6777ee1f2af937135910fe414713c72bf2c01e9b24dede62fba4","nonce":"5b5bc32ee9f048e30b99386f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"bd25a8ba84c51ab7f2513c5230de49b1adf22f19aaa287e76140d075f7e90cb52f9d68079f25662c5d8b224cd5","nonce":"5b5bc32ee9f048e30b99386e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"6c1b23b4b144f1f63131c497df09b5dadbe3af105d5a57b263fce7b3f5cc08a2e3bc22e200cd24bf47953d31e5","nonce":"5b5bc32ee9f048e30b993871","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"2a435bf162518b55fb29c05428cedb0fe121686f339426b979c60984644170591fbaf1fe4864586c24c22720cf","nonce":"5b5bc32ee9f048e30b993870","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"bfc543cf6f634a9e12b4d10064c5ce21d45519ef7189b700e491d3e3b8aab57d66caaee674d892978a32d85c6b","nonce":"5b5bc32ee9f048e30b993873","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"75d39ba3db61089bd5fb7e31a6b5d43c6443a43f647ef71b171adb3a452bcf9201cc00e15ee29ea639b5209568","nonce":"5b5bc32ee9f048e30b993872","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"f7500811bd5bd54ba2b745ade6fbc057fa5727c09ba02e8f2e08ff95c675548c123f3ba52b0aa2cf52d8539709","nonce":"5b5bc32ee9f048e30b993875","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"4a1bd4365d30e50c5ba755eb5ed9bdbeedee53786bfbbb9429aa430ffc03aafd4a7ae6e671d78d769061e7e447","nonce":"5b5bc32ee9f048e30b993874","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"2cddc172fa05b292404103797572fcfe570225be192ae62987db9a6ddbda3ffaa01d5d3a94846a4520a180fece","nonce":"5b5bc32ee9f048e30b993877","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"c45e4ade373d951838a6a980a81ac0050097935771dcce5df9fa512b829fb1143a87871671658f4e7cd1fd0eef","nonce":"5b5bc32ee9f048e30b993876","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"3c228c1053ececc953b3d084ddd6103e75dd5beb108e1c42cdb7eb097818d0a7ba688d6a461f395f71e2c21002","nonce":"5b5bc32ee9f048e30b993879","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"5d82d8df2abd99c9fd937a17afe7b6029a8f440677aac02bf1efd64c9414f4997de599d55d77aab1ae2169af66","nonce":"5b5bc32ee9f048e30b993878","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"d5f0a01d06ba13afa89e41f4d4a51b6cd7bac5ec46a861bb38689e847c56c5f17a5a1aa76b50049f844414873a","nonce":"5b5bc32ee9f048e30b99387b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"5d2331ba0a8274cfb483cd3024daa3c3b26f5f2124e8e2c844090ee8045299b084acaeb0aab04b7efc3c53f97c","nonce":"5b5bc32ee9f048e30b99387a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"0ddfb83d5ed1bdc596e29ace947c4f250e516c329115df808306062c43d946de6055bd00a484c40f56b968cdb5","nonce":"5b5bc32ee9f048e30b99387d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"52cf312c8a44b285e1cbb681987bd829af52dd469c84d5c18c9b520a2e7be3cd412f3c139581dbdcfb944de95a","nonce":"5b5bc32ee9f048e30b99387c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"90e24e3e9ff39f50fcf98bf4841439b33210a5cdf01c3eadb537b25836acbe94b16403ccc9ada8de4024341008","nonce":"5b5bc32ee9f048e30b99387f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"cc14f23f698de79f369523b613c90a34438629860e33b58dca1ed2df2103370e5b9e843a00bc85ce317d981847","nonce":"5b5bc32ee9f048e30b99387e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"ff05ef143268722b9fb796d162dd310a76e4ca8373fc041db771c90da13f056818149e300eb32d510affdf135c","nonce":"5b5bc32ee9f048e30b993841","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"3048952914d58b96d6ceb691e4b2cb72ebe038e69a0b97b98998d47263da5fea98500c62ee62ca2411857642bc","nonce":"5b5bc32ee9f048e30b993840","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"114eb6d39cb7bcd8f145adc569c896cb7cfc637410ccd5b481ed2c344aaaf83ee2b0f2b083816999a63c8c3b41","nonce":"5b5bc32ee9f048e30b993843","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"2ca7a57619c953999a9c7bb13eaad9b3ca1bace610696742a4bb00fa4a85c0e676828889c5e94f3a1fa3a34fa1","nonce":"5b5bc32ee9f048e30b993842","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"95109b916da623edfc7346a2bdd992d0d5d7fb9063bc0b2eaf3301b726875223c96b68a3566ed9f303b3627c0f","nonce":"5b5bc32ee9f048e30b993845","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"610fbe0ea13d32942bded5d6cccd4499abbd965eeb4f3b14413ee3edd1cdffc116d9d0659f9d14cfb395adf5ac","nonce":"5b5bc32ee9f048e30b993844","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"57f5b4e2c161cbb2a55e27b6a6d5e3ac4966c33caa0ac98169e984ba5682980197da68b0353ad84f831578ce5e","nonce":"5b5bc32ee9f048e30b993847","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"21cb8a508a1abcc6a6db8b1ed2d4b8f3f005aecc3a5a9468e20cc989ba00b75c8da163b7e4c8e04c11ee05d100","nonce":"5b5bc32ee9f048e30b993846","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"1e72d04810a7d191f1793d190a0431bffa77bca822a1ecf565f70793b4834da8e291e3599a255bfa226757ff04","nonce":"5b5bc32ee9f048e30b993849","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"c24e0face2fb0b2c364b676640b10bbe6a158cf80b30f2ca1cec76e7e64230365f9ea7b1f55e0b2a11a9bc0f78","nonce":"5b5bc32ee9f048e30b993848","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"6803d88caadd575887dff265ea2aa0ba897f8312afcee6edd3d8e3d6eb8ed96c788d5b3d169fcab9b12ad892f9","nonce":"5b5bc32ee9f048e30b99384b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"00ec7077746a891cd0b26726383a48e8d7a4adadb24c4d6bf8762c2186b24891a16a70ba31a65c56dc9cde3612","nonce":"5b5bc32ee9f048e30b99384a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"c4627202fd3c728f4230b25ebe85379e8030b9a5dd101797f1ac1d072d66d2727cf451507258ed81ff612d4ceb","nonce":"5b5bc32ee9f048e30b99384d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"ee997f82bcab9f691acbbc72f418f76201570d7c79f2715da5a157b865a8346eb0503f302c199826064f508d70","nonce":"5b5bc32ee9f048e30b99384c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"4faec9288e6ad4c313c99317518dd77048bdfb46d8d640e79a1da1447331bd1ff54e1e37975fe13f70e892d212","nonce":"5b5bc32ee9f048e30b99384f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"a1f9b5d984c2053656e4e3e1b69412f1ca888224581e5eac6234767d23b6cf5a2c0304881964bf9f94cd087cce","nonce":"5b5bc32ee9f048e30b99384e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"881687d0f7ed7e587f026f3217e39afdb376b657f7476a0086e544015f8b7441fb0d8a36c66e23596e22972441","nonce":"5b5bc32ee9f048e30b993851","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"aa36c524a56f2b2a73ba731d4da727596d04ed5e97c9a7257290123a73c5ed428ef8123022fd386b1a7f8b0900","nonce":"5b5bc32ee9f048e30b993850","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"7c3b19a7a0c29138ef63b1035d2acbc0eadc8fe97f501c038ca3517e1a23230832f2f485ec7cd4327ae99ad95b","nonce":"5b5bc32ee9f048e30b993853","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"a9a5beee0aff5906a075419d74b3f58efaf29c1ae39e57c928bfcb27557b4d095154061229faef4ca94853f101","nonce":"5b5bc32ee9f048e30b993852","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"4adaa1a13827bd6a6996816d94cf665aab7334eb20a618c97d298c71dd50cbe1dd5b1086b878353ae456a51fa1","nonce":"5b5bc32ee9f048e30b993855","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"1e8170b945d4f520c418a9c403083f25c9884e8b30e4dd643b56f872e3f20b4dc1020e83727d3225cca3ca2d5a","nonce":"5b5bc32ee9f048e30b993854","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"e49650eb14be04e9aa9037a7cbba3c3e7f1b74f87e732094101b6c1f93eb783690e0ce4f6e3a2ed9ed89bebc37","nonce":"5b5bc32ee9f048e30b993857","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"7a0b57a57f271874bc4060ce797c3812c22cd8622ee4480f9a00bbdd9982b573227a6b2f2f5b1406adb7ebdef2","nonce":"5b5bc32ee9f048e30b993856","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"7dd8d95851f3d7ae6ff35eaff769ff774582d39d995b8e30bc89e5f6365cbab51fccd8dd41b59b06f28838393f","nonce":"5b5bc32ee9f048e30b993859","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"5566a2ef3be00e94929bd07553cdbe33131450ec028c7be9a703b1387293e6e8fb9f314408690e480240a04c34","nonce":"5b5bc32ee9f048e30b993858","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"26d1b2bb8d54ac23ed2a9977bc435908aa5cd40a8686bb95e4d87d9e84ad0f4f05bdb05c62eae1722067a1bdb6","nonce":"5b5bc32ee9f048e30b99385b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"6e4d553b91a579431bff9509d7093277ab4f3338e4a14f47f7d6733718bc59410e7fd8238559131867429043b0","nonce":"5b5bc32ee9f048e30b99385a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"0789310248b5b5fed7c2921007a5d73176e80ee81b49819020db234cb84f5c19f3effa7f754cd78115e2c5f6e9","nonce":"5b5bc32ee9f048e30b99385d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"ac11a353383f7a543c21202f17732087681c91e0a915de25adc6b102afae08b348eeb32090e229b782bdfd0e8d","nonce":"5b5bc32ee9f048e30b99385c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"f19989ab116280802f39324c163d285b0f4703adaeb6d13a74a7fea7d5a5a61491a387a983a8c234f62707bfd0","nonce":"5b5bc32ee9f048e30b99385f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"1ca348aac8e626a20e53099fcd5368aa65523fb09f762be42a9d8ef75c79987f5576f2a84cf206a26eb009fe50","nonce":"5b5bc32ee9f048e30b99385e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"c5be2679cb51a4313e636020ee4da5f6b94a329e5e4188cef47fd3bce1bfbe3a9f0249b6463d20c88c7a58462a","nonce":"5b5bc32ee9f048e30b9938a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"b454a4d372364bb314bf57df09ca7adcb17774b830d567f3b5cdb96ca1702103d5a584d4d066cfd1c3003b17a2","nonce":"5b5bc32ee9f048e30b9938a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"cb82ec5230407168a42deb0e711d3d0c999f4d3b5caec593ae79b65a52fc93e84f98d7dbedf87c088ddb6d4e75","nonce":"5b5bc32ee9f048e30b9938a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"ce172df8b2e6000f62b803b8e210a2e8e3267f1706dbde0f6f0ba06add1967109f64b5c5c98eb812508c1935b9","nonce":"5b5bc32ee9f048e30b9938a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"9de608e715c541766b3b3618e8f0ab3ff487a98a0fc0499da50e9f387da26ef238c427ba2c08d3aedf2dd86b14","nonce":"5b5bc32ee9f048e30b9938a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"b1fb5e99c2b4230cf548aa047993bbd714ee1a044f1cd6f35711deb82cde901c6d57fb3c753926a90e16461e51","nonce":"5b5bc32ee9f048e30b9938a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"db68621e3cf28843b95d5ecfc7393258793fb1f2b304cb57a7e8a891565ce42858ece146053b8535477ef24d16","nonce":"5b5bc32ee9f048e30b9938a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"0c3b86bf6a8b950f217ba3a3cc8a03c6f30f827cf3693b8c21a11d32d259fdb3719e34c1054f68d4238d81a1a7","nonce":"5b5bc32ee9f048e30b9938a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"eb4c3f559e5e55cf428827237c956d3e978ab60b7faf27bed423b2de400c07e1e3dbd1aaee9615b8980a54b7a3","nonce":"5b5bc32ee9f048e30b9938a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"d1d540103937826407625adc8c79068d814736e8d97557c0501b11c4bed3340b5cf02f4a8f04065a103e342275","nonce":"5b5bc32ee9f048e30b9938a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"2235a10263f5a5f995d0e44dc61a6d34acacc6c1efcb1ff5944f5775f72f41d62e650ac8e80271073e61226de9","nonce":"5b5bc32ee9f048e30b9938ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"a14fc3c65ca2b6a9ae7f4f1baf2a8786b15c8ed2f80305ed03142658bb58cee8c537b1a61ed84c09a4addefff6","nonce":"5b5bc32ee9f048e30b9938aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"a46c1a64710217ee2a0aec2acc41ade982243e3ece69f09a6393244a9e1846a24ddef932bea6954baba54882ff","nonce":"5b5bc32ee9f048e30b9938ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"dada12727a5c34299d834df0f376008dbd297c5d5d8e47b9fde7bdfe85819452d1f84cacfa691eea56c9bba46b","nonce":"5b5bc32ee9f048e30b9938ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"2a7b7e72b4fbf4f588e00bb20a7d06b46d9cf59317971efddda6091c541de97eff287fc010ce3a0994e519d16e","nonce":"5b5bc32ee9f048e30b9938af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"284aeb1164dd31cdc884bdea13803c7e7c6cf64091f70f947252cca9b6a1150250b5c70f3f05c3dd3358bc86cb","nonce":"5b5bc32ee9f048e30b9938ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"8ddb699551dd8bcc1f953119cd1d67007713a642cb62ebbc86e3843744e3177387bf7b309fb91637cc2b0a906d","nonce":"5b5bc32ee9f048e30b9938b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"dd1cae00754d0382edb9a1867b0b4957ed53cf2fb06833e07e778add13d5f85f4a1a9065d36d3ee39b7fd68026","nonce":"5b5bc32ee9f048e30b9938b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"b2aba593c18ea272b12497f4fea63741e88a11e433b3da3bbf5b135a6315f733c8de936e13375528c8e833f69d","nonce":"5b5bc32ee9f048e30b9938b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"57ec0bb71ccbfe5d5a469679a7477a33401755fb1d366b681f9a1af3c0e2e5ed60f5629cb82a897d39a5a1cd51","nonce":"5b5bc32ee9f048e30b9938b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"a146619c3b638e71b16985612ca38c07cd5cc7f3bfcd4504268850aeb5dde5d0453d6a095182f29febb76476ea","nonce":"5b5bc32ee9f048e30b9938b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"ca93f5d493e858bfe3086aa5da0a2828ddf5edee9f7837e2027881b0406e524e223c66202a41275d9c7773b1cd","nonce":"5b5bc32ee9f048e30b9938b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"b9daf1e5bf2d4059ec3f30d2147971ea0dfd435f9ef6d648c18922d8a5aeb6300f8a45f1eed944507aa8629eee","nonce":"5b5bc32ee9f048e30b9938b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"cfd37512a67b50224eea79fcb5b745909d36f92cd967c0cf69e5df7a1219d035993df8ab9ffae7439c33de2c1d","nonce":"5b5bc32ee9f048e30b9938b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"b3c8d4f49f5cacbc9d468e8569ca597423029c2d10d1ad6dc16b2519dd3343594c543bc8dc1ace70b3aeb00abb","nonce":"5b5bc32ee9f048e30b9938b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"69dfd761c49eee696675071eff99e50ac72bdb6d03d49192ad647d5d907e09a43a99b2669dce92057ccc1736cf","nonce":"5b5bc32ee9f048e30b9938b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"2addb2822c726f79da9772745b1b7b4863c5b3508912f506f7fd4cc577b6baa000d67f6f8633264ce2c18f9ea9","nonce":"5b5bc32ee9f048e30b9938bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"2b28e683d20927d90105eedd5422595c920803a6ef36fe5f7a29167817549427b113508f913a615e3d110a0fca","nonce":"5b5bc32ee9f048e30b9938ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"5cd49db21314518d6acaab77761dac2856aaf6f205c18f79da821bd2fd104e5c831e0463affbc007afae1dba32","nonce":"5b5bc32ee9f048e30b9938bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"fb09a51ad5fed3b05e95dae83fce29a17914573d4c978bf1e4f077c73469be9f5e7eee14d80e1962b87afa099b","nonce":"5b5bc32ee9f048e30b9938bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"4d138fd4875fc06028e2a3dc096f0328336a23df43dd288551bae093b89e40448cddfa0de4cb8ee5eb15fb45aa","nonce":"5b5bc32ee9f048e30b9938bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"f3afad23c96a72289743dd3b94cee8d0c09a4c3e14d41357fb7853985ba623e32a545b774c66ebbe5fb1b5b220","nonce":"5b5bc32ee9f048e30b9938be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"d94029a9b25888454364ecc3d3e6efd457543cf008134de467520c78396eb91aa07fe98f19e74719d03e260020","nonce":"5b5bc32ee9f048e30b993881","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"b0e60355a3ccd34de3b8107fe7dca9d1bdb470e2c8e20df4928348baf83bc6a18e8170bed415a50da5db70ff68","nonce":"5b5bc32ee9f048e30b993880","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"2a749914da96c169f7c355a746acde974e57aa47966e75291b0f7e064fdf006c917db6d89b3b6e519802309247","nonce":"5b5bc32ee9f048e30b993883","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"8060cc73541d281ece89f76b8dba0468965f734ba499fb7c1216631cd13ba5ab23acd3a31eed5b93bc5a91e1d7","nonce":"5b5bc32ee9f048e30b993882","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"30738c4eb2fb49017230365fe860d98a12aa1c613ebe13e8da387d550ad89308a7d36fcf211aff5f404e7d215d","nonce":"5b5bc32ee9f048e30b993885","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"d06e1afec0c716092bdec0b7b4e9233299cb2725966eb64191ae1ed458c20ffeac0d24a21a2f153090082a69f0","nonce":"5b5bc32ee9f048e30b993884","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"8f4bd981695623c404a3bba0436134942b3d9efed12d4f8f80517ac90a94e85a15c5a060788ebc3db59a4f1c9d","nonce":"5b5bc32ee9f048e30b993887","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"dbdef427a5a52578e675ef9a075538f8e535e99243004ecd840a289809bde551efeaded37f1d329f279fd0515d","nonce":"5b5bc32ee9f048e30b993886","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"a19925f2b0d155b438da5a4044bdf795d0c8ab4fc7d14fa9f9a69190945900a4ccd2a33d46308130b32ecbf8a8","nonce":"5b5bc32ee9f048e30b993889","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"9b3fcbd2c171defe7fa2e740ff313268c8392e525b8b917eb9e37bc06ff3c1088dffe62335580a4846a25a06ff","nonce":"5b5bc32ee9f048e30b993888","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"ddd5ac7b3389c9ef540bafd0c6baaf8f9ed574efec3c080bc9f902837917069091707ddb47d7404d5e1eed21e1","nonce":"5b5bc32ee9f048e30b99388b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"f096c70cade66aee8b3941f445acc5af1fef3697c47d08b8f88fe2fab1ac67a777a567d216b2fae8d97356ebe1","nonce":"5b5bc32ee9f048e30b99388a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"b85799803e5b969105016c98154e2763482484b8f3b5e7264bb9b34dfeebc7926d5f14bbeb9b2454da1a8e4456","nonce":"5b5bc32ee9f048e30b99388d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"059dce2955852b15d17c419be83a0bce7c301abcdc536d47e0eeeb7b84e883d843bbdda4435d575ab36d0adbb1","nonce":"5b5bc32ee9f048e30b99388c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"437c9389c72f7a96dced8a2fce3e755695aa1e4cc938829e372f16d622d1339fd831b54ddd516e80c0490b9179","nonce":"5b5bc32ee9f048e30b99388f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"9f33bbc0a677fb9dfdea688a2ab9f8465dc4eeff614d7acf6a374c21d5986ba234deb8d3f19df171c3f6b0fe33","nonce":"5b5bc32ee9f048e30b99388e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"53f79e0f0bf62ea904016e504ccb05d694e22e3ec0f4afeefb583ccdb5b010b3bdfae63d6b321dd33cfe2e6f14","nonce":"5b5bc32ee9f048e30b993891","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"d43f12344b79a1365886aeb55591e196b1e9506161638dc86eb90208e393d5b98b0ae5bd00d9e28a4a6cca9657","nonce":"5b5bc32ee9f048e30b993890","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"82dcc3bfc962cf5a0e6b88d71a4ffc20ce12ee08190e7bdd8a692a8dea708a6615cd4347753489e938481b70c7","nonce":"5b5bc32ee9f048e30b993893","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"1fcfa9b1d9ad7c20cee6a8d3f9242d6191362f280ff64f326955de9e7bb70399cee95da74807d76fe32e833c20","nonce":"5b5bc32ee9f048e30b993892","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"bf2c49d994de10561ef36801e580fd508d92769f617858e293117c603a5adbdad8fa775e6e506ef2f7f650d41d","nonce":"5b5bc32ee9f048e30b993895","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"93657965915536382d6e9a7429d61f54a765346d75b41ab5e6a3256f6d8ea76578a8d4c9e97c8d2265a50129d1","nonce":"5b5bc32ee9f048e30b993894","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"0cef4f92a71bb9e34816ae12e662af5ac869376ac8aeb02a8f1306bfb3e18913fc303680f893f78848b1910e58","nonce":"5b5bc32ee9f048e30b993897","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"7d4fc07310a1227c5ee6cd32f37ac68c9a5ff233733b5b14a73a7946d6ac213dd1cf835f2e7c2ed5ca1a115b55","nonce":"5b5bc32ee9f048e30b993896","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"4ec6d40c95590fab37b38759d0f2edd7908169cee49d7110bb6e99630f9e335d5ef9436e2037a142985668e33d","nonce":"5b5bc32ee9f048e30b993899","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"47afb4fe596fbecdafb65491a937ea4f7017e97fae12eb8da29e626ba4603c29ec42d9f4ff1e9af508be22a238","nonce":"5b5bc32ee9f048e30b993898","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"faf2acd47adfa58cea17f5d36d9d5a52d3381078e70fc2099b20bb7b8c75e9c364ea43cbf0c9af6399830e0b72","nonce":"5b5bc32ee9f048e30b99389b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"4ab972ba2339b6d135095cde9c8fd790a8546fedfbaa2b87413fa1c5c15a4cc1b58c2cb3b0278a78a4487cf463","nonce":"5b5bc32ee9f048e30b99389a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"ac1b8cc4f7ee2884f61bc196737a6bb3c4a450191f9a9abddd8c44e9262843ba6f7e38aeab972de4d8acc59601","nonce":"5b5bc32ee9f048e30b99389d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"4b84044a4c1f563f3d7d3a0d4bd0cc4666dcdbd2263d0d0353ef32cf0916ce1850d655dd26324eb10852aa315f","nonce":"5b5bc32ee9f048e30b99389c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"25d25360c8086086a3344d1339ee31d0bfe248c816ed4d1fc590784ad56a75505e6629da8467be982fecca1101","nonce":"5b5bc32ee9f048e30b99389f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"c94b267f7fcc99f7d27babe20f7cc9a66d6876617e374b2908602f938341ec019b3de59c24e79eebdbc2b7677f","nonce":"5b5bc32ee9f048e30b99389e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"fe05907de918b1fb7af60fd7d6ef25df91abcbae97f1b2e03b5afeed2ecb78fe6d906226dba82fa2c8e5477a7c","nonce":"5b5bc32ee9f048e30b9938e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"8f3ee45a2b97a510066d1f2f006606ced12e3e7b23bf4a7d6b1a48e9e0630fb6eabf6a3b023135e773a1182259","nonce":"5b5bc32ee9f048e30b9938e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"95df39ff437d1df255de3a91bc01b3f18a1ce768e18c9bbd68aa5136c8f3a1354d9e42d3822b40bf66b853614a","nonce":"5b5bc32ee9f048e30b9938e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"9ec887539e2deb29b6c8efe5381f9ae486d7a3d2f5377293b1faee308d2dcd5af87b869e3598833e901d7d6dce","nonce":"5b5bc32ee9f048e30b9938e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"61951b902e1c35bc1468e2bbb757392a0365c501dd8ceaf7f1006ee521d855b286904cc2ac541919b07ceb4e47","nonce":"5b5bc32ee9f048e30b9938e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"10e271534fc89d649cfda117b8c7d7bcf0095dbd25dd65edae116f510f219a4743c04190995245a76a885961a6","nonce":"5b5bc32ee9f048e30b9938e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"7c8ed90e7bd04b4ce0ac48350eb3d14ef203d599b31193d840386740acd160ee07f6d724c9e150fb1d1629fe52","nonce":"5b5bc32ee9f048e30b9938e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"7326cd271e2b89eda2c649788b42ea595e690f2641233344ef761004f0e5c8270be4b3847ae7eca49dbbbe52b4","nonce":"5b5bc32ee9f048e30b9938e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"547feff0d0f59a874d9c8d3a49af9b421e76ce524a77f8e8ae6a4b906695b28f325f70f20938635a27add1fa87","nonce":"5b5bc32ee9f048e30b9938e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"00b55d0f1802d3018791ade449d99de1457a8c5f6aaf31a36e6179389e8fca222bf5c89ac45337c32472d5a703","nonce":"5b5bc32ee9f048e30b9938e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"7e020891eb8507c1e9d2f3e6720ad856ff640be052ec2930c08c77c0ce5740f9f986c017402d3d7db19d9da15a","nonce":"5b5bc32ee9f048e30b9938eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"0a4bafa8d76083d7ccda06d23a67f0238043613dab1b2694fa5015a5e96493ee1b47895999301a74ad439880d2","nonce":"5b5bc32ee9f048e30b9938ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"769bbca6b9152c49db58ccb6598f7876dd4fc0c6c037a0dcb93067f8b9a63aa97e978cbea2af0a8bd6c41d2662","nonce":"5b5bc32ee9f048e30b9938ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"37f84adf92b756720e5b345e08f376fdf7a69b1b48302d79c77d45c96c5c7b25ab9784a6cc2f9d5fc8f7887daf","nonce":"5b5bc32ee9f048e30b9938ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"6d199ea21f5c2e53feb3b1b36af192068b8d39ff6683d733dc6c8dfdee08fe9534c6de0c52700fd621abc07e08","nonce":"5b5bc32ee9f048e30b9938ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"05d4d4e9c2f497c339e9edb1ce85fdd3c1848a0e4ae44d1ea64449445b17849d1427f71d17f0f39997efb97276","nonce":"5b5bc32ee9f048e30b9938ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"54ed7c6899f2b9b5a594058cfdc545e80240aa069eaa1e723ce17fc968e9ed908a4eb0201ed02fc23ca45eb6a8","nonce":"5b5bc32ee9f048e30b9938f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"c416fc63f9723f10c703ef4cbef8976ffaf7f37381b5f430b3815382a5d4e2ead75422437383d810645706e491","nonce":"5b5bc32ee9f048e30b9938f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"4aca58f3413ea6da8c1872a1397496370fbc6d69b55f01c02665e4de2eef73267a59b52674b8ab100d75da343c","nonce":"5b5bc32ee9f048e30b9938f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"21c815e567771e1dc26989030262051a8c172f7679610b6daedd1e439f3bbf758c66de440e9a38129250672fbf","nonce":"5b5bc32ee9f048e30b9938f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"36034a7ceda11dbfc357b151981e7448d27312ce662c8bd63772da7181f5559d09778bbfec3529f41e238edb51","nonce":"5b5bc32ee9f048e30b9938f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"5254faaebb30d7fcf188bfebb34f76d90cb119944b8c49c9813e4b2e02481f6a78df97607659f67798070426e6","nonce":"5b5bc32ee9f048e30b9938f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"7992f1bf696d64581a0ab6985147347ab8ddb23d833cb4530afa46ec012ea19380bcbd99a30453d09fbad91f2a","nonce":"5b5bc32ee9f048e30b9938f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"e1d85b94e321836213947b67283e5c73de388cf02425f7905580bb3e8723708b136fe92d285525414b66f48ab1","nonce":"5b5bc32ee9f048e30b9938f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"3614f0955b1ed701f395c1860cbac355d7f35c91d70f068c62989a998bf79f91eba0bc1c72eb2f620a5d643feb","nonce":"5b5bc32ee9f048e30b9938f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"0f3593448ef0895973728d3951ae2a2fa5446df6fa8aabb929219647d44fb8584673b6d47d8929d047e6c841d9","nonce":"5b5bc32ee9f048e30b9938f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"9af3a94b28d30d88c5e4e04bb52f1241962a530f6e04c6df7c07182e792119035ee81087e354e22b9bf239d85b","nonce":"5b5bc32ee9f048e30b9938fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"c7e3cca65378c579596c321722bb85c6ef63792318b6a1ba49877a5edbd2d19dfdead8cde15fb84af716817a24","nonce":"5b5bc32ee9f048e30b9938fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"e84949b1bf6d660d767ca58b83b38ab66ca363df8938524e10a87e9afe44297234aa271ceefc67dc78142f31ce","nonce":"5b5bc32ee9f048e30b9938fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"fa64896729188a23405dd5a89979e4ff39d43acb24292bf065ca61ac1c1abd1ff5f8d1ba372171a49e9a7fe450","nonce":"5b5bc32ee9f048e30b9938fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"0e316c7ff2846ab413f79e15a2707b541bfb0257709f9cf827ce1ca59a88a7d35800f71d4342bd511acd6231d9","nonce":"5b5bc32ee9f048e30b9938ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"2da106f645cb7223c009535937d930499ec291456320d371e097a5586feab91caa240c6afacb8adf36af914f73","nonce":"5b5bc32ee9f048e30b9938fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"53d630557f3ffc0ad23b714ea7060dcb8cbac06c34b8b36ba9dcb4984ece3649ffc558d955a21bf6c56aa3a521","nonce":"5b5bc32ee9f048e30b9938c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"b47e51dad746deb4ff12faefdaeca52550a249aa3a0a16b545e48665571336f1c6e57bcba44b2213a6c075e9f8","nonce":"5b5bc32ee9f048e30b9938c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"96d54aafc8f955128990bfb71348fc7e8a18f1332e8dfedb56f610c69c2934d37698f9ca065e9bf85c5a3ffeea","nonce":"5b5bc32ee9f048e30b9938c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"2570cfaf99e53f164b8e338344f58fd759ebdbbd8637b7858e4dfee1a9947e57fdf934e0b135b3a2dee21cc364","nonce":"5b5bc32ee9f048e30b9938c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"f0662a66dcc88797df7805de6a463d22e1d2259518eea067d8e111175f5fff47680c503cb0ca1baf6cf14f064f","nonce":"5b5bc32ee9f048e30b9938c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"06506a304e8cad7f7c881627a9b9ef221ba7ebf46c24943edc4ce69d05ff3c89606cc8dd6392c6f1a774f8bccd","nonce":"5b5bc32ee9f048e30b9938c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"fb93416e0a4d6e8393e04f155ea2e0d20bedcf5a160ac2ebf02909b0bfc42717484737c86595167fbe2b340072","nonce":"5b5bc32ee9f048e30b9938c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"71b5a4d286274a7f6253c53974e1aa60b2788791903ec187eb97f7911145e4b8a477985031a29af4f6da44f89f","nonce":"5b5bc32ee9f048e30b9938c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"2a0fe1c0da31aa8b6f6a2cc5e2db6249c23881e44900d820b5e44d8c360fb18f511bba55b10e5362ede9d36a31","nonce":"5b5bc32ee9f048e30b9938c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"f41757640ff42d6eb12e4d2ab88e04d6156074cb6a2de5a769e85c29b57ca7311e3a98c2188667d6c749f27280","nonce":"5b5bc32ee9f048e30b9938c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"6dbc54f9feaf9e426235592539430077a6da725354e892934f22a53051b2cb19feca673ba867b1d3e001b527b2","nonce":"5b5bc32ee9f048e30b9938cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"0907603ff0f3572cdda9c1f65a25dac8901690caeb13a23f3f30742444f1c1307222c2a25529eccf63f8c16149","nonce":"5b5bc32ee9f048e30b9938ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"ee7233b44f5534ed99a2b31ea32fff41e95498d5e033b119d871bf8737ac62d9d4982750bd16eb9bbf3b07c7a7","nonce":"5b5bc32ee9f048e30b9938cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"e857bd019f7db24a73e51591b2c11270416626f619a79e4ba36ab25a3a2cafea5103972a8429080bcbfbab9f2d","nonce":"5b5bc32ee9f048e30b9938cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"f1479a48dfa9327600e63719c6175a2b2a5bb0642ab6ae0637495dc88243d60d7c7b75d04701242ab9fd1c5747","nonce":"5b5bc32ee9f048e30b9938cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"2bf56275b3a6be5dd1995f90d5e19862c75f870fa699c58f4d882f9d4dde625acaf0854c6dd050e58ac1c9a692","nonce":"5b5bc32ee9f048e30b9938ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"f887dcd4f0025301d9e3c1daa00a8eda9869d3aa5587eded8fa0d3efdb2d49581d4fb03b7fd6a213650d3f986f","nonce":"5b5bc32ee9f048e30b9938d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"5526e1eb48f4610a38a1d38f35f933fd18bbb2384a869bb99c6ceb578d319b6cdb36f03aeb3412778e1d12fbbf","nonce":"5b5bc32ee9f048e30b9938d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"0e640f90ce25214eb9e553896adb7e228ebd16964b9dc67eb8f6248e79542319b89cb17a9f6773f5e7139da740","nonce":"5b5bc32ee9f048e30b9938d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"6e9bc9a1b5d6eb9f093ea89a828efe1667ee971ea4ccae8bf7c20bc2b05251f59768b3202b48c7d685381e5f73","nonce":"5b5bc32ee9f048e30b9938d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"2a7b5aa76dc6f1d79896bb37deac9f01b2fd9bd47689a490f0a218cf862ebc48a1ddd5fb4a39c2e678fdcaaec5","nonce":"5b5bc32ee9f048e30b9938d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"58ef400373345f6fe26682cfa642f96cd3743fb8900fab172d9b2d3c9d86fe12120ced8c03a83e4b8d4a7481b6","nonce":"5b5bc32ee9f048e30b9938d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"2614e6fa2883a2b52507777b1c7c6e703af9c9baca4f100e142e2ec0b03b8cf229293c31e05e24c34380bf5027","nonce":"5b5bc32ee9f048e30b9938d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"6c393a62e197da8c0d6eabcb2c4f358da06d79c351d5bb100c0a3eb756d6c78a3d28d340f6e3129ad9c8407a8a","nonce":"5b5bc32ee9f048e30b9938d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"a3a4552174c5a98a4b77e7d632d552f08df17f260cc5894714463547cc0336df98a37dc8a366375198e71fae9d","nonce":"5b5bc32ee9f048e30b9938d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"adb4f0d8d0a862c520d01db9085a22840dba57c6686d757e379c2c342f8ca8cb4bf94c3daa113373e7778e02e8","nonce":"5b5bc32ee9f048e30b9938d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"af66740faee26bf0752203ffb56d24f199d542eb1f0e3a1f396ab527e51297653bf46e3a2a5a406bf7a2316b6d","nonce":"5b5bc32ee9f048e30b9938db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"27bbfd78d9f53f67d3fe5985f2f3976c7265b0d3ac121e8e95bb7cd36806cd2dbe3139624587a706b22d546687","nonce":"5b5bc32ee9f048e30b9938da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"ad742f422754e77c4d2a2fc7c7db8f5b8a107a1b467c94fcb3ea7eed3a2189bb325defe21b43ec4d6decd280d5","nonce":"5b5bc32ee9f048e30b9938dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"1ce97a61f5b27191de23bb54185b911b591f719fb903df011f2d26939980032fe9622df0e44e8f997602c18aa3","nonce":"5b5bc32ee9f048e30b9938dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"ce7e1a34bf1dc916f7708671b2feceafb6bd4ad398e03187c989960140b3a0dcdcac6cd11570497e44c065a2e0","nonce":"5b5bc32ee9f048e30b9938df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"eab0f991dcd4e202955cdf052372f137603ff68e810627bc447e572d6d6bf299bafd07777a0864d6eef17c92f9","nonce":"5b5bc32ee9f048e30b9938de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"a86c7f41ce6e1957d0acc896826558690fa9073730db39749bd6680dd94f0af8fb9c1688f5940d6b284bbb2890","nonce":"5b5bc32ee9f048e30b993921","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"81ccbb87815c2038d2c33ba3fb5d5345031a5bcedafd0a31b4a9524cc5ba971b"},{"exporter_context":"00","L":32,"exported_value":"6d36ba6d897b670cb8b0ceca682bc556b7f1a03be643a0a2527e68858728bad8"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"1727d160d25d5ddc6a114c1f8483514b52b65b85983bbba7d3c1fd8d480c645c"}]},{"mode":1,"kem_id":16,"kdf_id":3,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"d8c031c3f69e2ae578753da5105e5d4f7a05965712cc7c3e066494f1e4a5cac7","ikmE":"d0408d30303dba8d9b2ad8626c2c0d16a58514c78dbc55f77f4eb9b5932987b7","skRm":"4923fd1cb55921c6b5694956d20fa51571d2f73b1bdc68aecafd09da111e8ce2","skEm":"8f4c30aa01dde0268fdc723f296109d1e34492a508461ea2eb1f790fefb09431","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"040630bb6cd1754999f7c1edf41a5c711b73b38f7d9a1e52477dd1043ff648fc67f47cf45b0d114e120ea2b30ae729a86843803e8cf7b215c1d45c3413294d389b","pkEm":"045c8b21c089f949509c4094e0575f8c586d32a2707be602da36d0dfa331ae7484c681b062d4801dde2e4aa99219a9a138418c0cee330e7ae3e2951e6f40d68d95","enc":"045c8b21c089f949509c4094e0575f8c586d32a2707be602da36d0dfa331ae7484c681b062d4801dde2e4aa99219a9a138418c0cee330e7ae3e2951e6f40d68d95","shared_secret":"d71e6a5e91ac36b4810750f045f5c2a08b403e684d0dcc9c9860978912274ef4","key_schedule_context":"010d17104af65412950b881d58878238fdc9f980d980945e2897b7bcd44b67e27a61c2a1c2e32dd0197004c59c6df6898f7502a62f33ee399176b24ba94a1f48b1ef4b8a36b914c26820d53e83a9dfb742c7811a526e9dcfb2f19f895c68c80dd54c6e836af7133e4b89418b17bdf4c1d32445ee0bc0f40063a0dfc0e0913cc37f","secret":"7af327f6ed3eea782003b3b02a7f7fb7ea30939ced0ff2f5d8e0befbb10d026466bdfff15f43f383d70bb75231aed24aa3fc7a08915b9a4c7b160f704222222b","key":"bedac77b655bece05cc040560ea7115c33af77ccc12780f13d5fd2a8e62a3836","base_nonce":"88c826f8049cc7ab2fd3b88a","exporter_secret":"30970eaebbb0d0a757fabcfef69082c18ff50f8e9968bf633d66bed36ce1a0c5ec9d249bb8267deeb8d3dcfe0370737528f656a4ebd4df2d2aa281ffe9d63d52","encryptions":[{"aad":"436f756e742d30","ciphertext":"ce38a20b537ee3771251b279dc961c96fc4daf20deba9c285ed6adddcb983e38ef9828950fe174afd9a496ad22","nonce":"88c826f8049cc7ab2fd3b88a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"eaeb7d078d9ae57e66a8e0d36d5ddf0513e6f6ca75dae2eacc96b94ddc0bdc73f442759a2a227c5fa0789748b0","nonce":"88c826f8049cc7ab2fd3b88b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"fc87147912860ac568a56725912020a6e648da83b30d37559afa722d1e0d7ab403e32e8f92a6d85564db1d0da5","nonce":"88c826f8049cc7ab2fd3b888","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"ec4608c96ad7b452fc1053f6089684b08b3ca0b99370199035594d53d2a21451918650e1b266174c60c2cb1168","nonce":"88c826f8049cc7ab2fd3b889","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"b0412be12ece850e7bed4c28728ad931891298f099d64c2c60d9483040645eee9293192df114a5858d2511cfdc","nonce":"88c826f8049cc7ab2fd3b88e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"3405b51f33cbe44ea069193bec72387ad44cfd83f49cecef9da6148689c1dc2b7474f0359a1e18f0401a8af2ae","nonce":"88c826f8049cc7ab2fd3b88f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"14de6a8846c35b58741cbc56a20aa6c0c4feb4197fbda9693b834a7616615b97173f6e8c09ff054d40cf60f8b2","nonce":"88c826f8049cc7ab2fd3b88c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"53eb089104de806a0161621c36f793ef5e9e1105621ee430ff5160863c1517eb404991f2ab94789beb70454e64","nonce":"88c826f8049cc7ab2fd3b88d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"50246d7d8907a7987e916b0fc977ac9a01c973558329b30fa427e8ca1feddd0ecf01d36f19ca44ca4a236d1b82","nonce":"88c826f8049cc7ab2fd3b882","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"b85d646d54c3c1735739ab42107ab123bdca1273f6fa8f45775361cf75d4db7e7df4dcc8506a0d4570ca02d67f","nonce":"88c826f8049cc7ab2fd3b883","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"de6e66cd03d7b23f0c72a5f8640430d029f34e09093a3a2d56520b4433cb79ad0a42a39885012c39326fe6b4c0","nonce":"88c826f8049cc7ab2fd3b880","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"655e358bd005bee3ab453508626a8dd4b940549a159555b6fa0203ce5a5aa8564f07fa6bdd9d5ecfc2b16ff709","nonce":"88c826f8049cc7ab2fd3b881","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"9e078a06d40b615f4bbb07549113e098ab84da1f249e0ce3b5ccf2a8cb9ec29245e9ce463efbadb3012f44707c","nonce":"88c826f8049cc7ab2fd3b886","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"f2345c73866c27d42c1e96911717fc9687aa4dd0ae21bfb076ab1675e3cf89a173d92007aca283e3b97ec5fa15","nonce":"88c826f8049cc7ab2fd3b887","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"b79f0ddb04c0d087dbc980ae547d8d19ccc1f825d7cea22baf91357b49205f6117486a7f5a046e2f522aea303b","nonce":"88c826f8049cc7ab2fd3b884","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"aaaac16d4bb30079d6505f56e43ba23118981a374ba812c910eb5d152f2a1d302cecebca17d68c0e2fd2059228","nonce":"88c826f8049cc7ab2fd3b885","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"4391658a8d0731fb7930d80443e86bc630d5fbbca60c75aef40f4bd3d6de8bff313a978afc8e78f918b5e47715","nonce":"88c826f8049cc7ab2fd3b89a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"e7965c91ccc5132b3c6d9813686464fb8416a2b39310ae4dc4b57701efb6cc6dc9b6c49818b7b7f2ee4a4904a5","nonce":"88c826f8049cc7ab2fd3b89b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"8b3dfc158a62352182de88b679674b5a78c4c519197e8f52d02df3ce61ae53dd2ce61876961cd00206056cbf19","nonce":"88c826f8049cc7ab2fd3b898","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"9b76cd849890753ad63eb9bdaadfb9b9dbbcdd2977bf8ccdb3e326262d152c38f5928512e2ab19627a911cadf8","nonce":"88c826f8049cc7ab2fd3b899","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"6b86b4d7c0d6077221542be2db59f54dd25be6252acc9c00a5077f8a9e4e5d129d3ebdf49b47e46755e4ca8ae4","nonce":"88c826f8049cc7ab2fd3b89e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"57fc6bcf9289e7f8d4b70717420e84d9b1e5203d8d5f8181dea8cf348ced5f0f4fb9594f4839c5a333c1ca3351","nonce":"88c826f8049cc7ab2fd3b89f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"f84b433c380ad0fe19bc3f1d9c38deadf84359623d44d3e56f8d303c7c6b33018f97d1aff2e5d5ce85d7fc4fc5","nonce":"88c826f8049cc7ab2fd3b89c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"df337c68ed63684e095a3ee1150607209947737c2f9f6655a03f247d10f8881d5e0a61c57c39881244848d32d3","nonce":"88c826f8049cc7ab2fd3b89d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"c6f7cba0ea671725e4e11639c634d93e2a2abc768fcb3d978458117b0ca6e0454174798539daf512847934e021","nonce":"88c826f8049cc7ab2fd3b892","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"1c72a3f1d530a15243d655bec1365f806a94a53ae24d070cd0c1e3c2c66ed5da4cdcd52832dec94989740aa6c0","nonce":"88c826f8049cc7ab2fd3b893","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"b7314f0449e922817d7304127bfd89d24fb930099ccf67b66ea1efedf08ef74860c661285be685fd7f5cb2331b","nonce":"88c826f8049cc7ab2fd3b890","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"e6035ca2359b264835618a41192ccc91ca18719927ed19ec580d8edfc3faf7096977d9c8cc7c87d9bece0335d1","nonce":"88c826f8049cc7ab2fd3b891","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"e1f00f0755ef3b03240130bf44b287393ed70066d3c3ab0719f5291c62ee6efe20e3f06b90020e14d02e5e5b93","nonce":"88c826f8049cc7ab2fd3b896","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"5f8c1e54da6a25a3b41edb2f3277f06d25e2cf37770d00094e2ea23ae746db1dc34b1713fd0573022117897dab","nonce":"88c826f8049cc7ab2fd3b897","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"21fdce5cf8a0e9f4708e467874f895d30dc124570c4ec46149fd4e7c7176137a956ff9b66a8dfa2f72a6aa9398","nonce":"88c826f8049cc7ab2fd3b894","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"0bf43d9af1edae4052c75eed7a88c00fbe6f2544fc306fc9f3b50eddb51e9d7c3dc59bd75053495d3786a848e6","nonce":"88c826f8049cc7ab2fd3b895","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"c480b64cf4ac70f44cb4ab542b76ef6e66d831db4d8a6f38d4d95dfbd701e7cd2f846a21c42693ca55f72f438a","nonce":"88c826f8049cc7ab2fd3b8aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"3bb024ebd6afd98b9d409ac8abd0407b179dbb76d182314c9760181312b387f80208ad5f5d9476e046246b8681","nonce":"88c826f8049cc7ab2fd3b8ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"5f781ea2f268d55f85cf78dcc20e96290482ec3f582f24901a4f97c2dc91ad3d6b675bb51c130e3e00e157314e","nonce":"88c826f8049cc7ab2fd3b8a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"31924567efbd3c87799f6412a2e13b6398aa1a1b95ffd2a3140ab604ce3f47f75e1a7436afbe90b7e764b7579f","nonce":"88c826f8049cc7ab2fd3b8a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"210812ff52e51798c31d081b7a2aadf3a4dd793a09dd5d2795036fbbeaa4a341a868128fd4f86a7cf4cbc047d2","nonce":"88c826f8049cc7ab2fd3b8ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"3924d96363df68398ef0347be56409fe97ae4fbc449ab4978766e5b0c0b7cca28a6644fa58600e8dfbef748c1e","nonce":"88c826f8049cc7ab2fd3b8af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"bb214bfe010d696724166853134b95bd44a93442f9ec80e39dc1b6baec192c3471d8f407a882700ea9c4ebbcea","nonce":"88c826f8049cc7ab2fd3b8ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"4ad587b8f7559616cc051344bd0b42b25cba6acfced3b1e9c5899c3a26473a1c21e35a23194d7525c9aaae532d","nonce":"88c826f8049cc7ab2fd3b8ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"b5137226c445c96f587b30c4c4aecff4fd6b4d0594f6af1726f0b96e9614757a213a57cd66e97ca5e682a2133f","nonce":"88c826f8049cc7ab2fd3b8a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"d910e98e2729b6a181ad771af18b855a68c6679914c7bdfa721e4981ddd9a88c213fec5fec39b664aa17c84654","nonce":"88c826f8049cc7ab2fd3b8a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"c6c1b1c955c185c51609919ea02a9b494638ad7b195495f87a6e5d7aa7831282c11e35b25c003c7e3189af817e","nonce":"88c826f8049cc7ab2fd3b8a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"9c00bcf79922aefec370696b7cb05a891200aa97d334a77bd03a4e498a1990d48743610664f64982f4edbb675e","nonce":"88c826f8049cc7ab2fd3b8a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"41e75f3e0ff4c07e3341b6fe455756825e1429c753fd6de7cd5ef5a2e3bfac6895582bbc78493a05b8f2b0c425","nonce":"88c826f8049cc7ab2fd3b8a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"2e2c2e8cad113c3eb121cca4f498a9d190f37a0a50be01b4dc566320428c270dec002beedf673c831e24bb26fb","nonce":"88c826f8049cc7ab2fd3b8a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"f7683963334fb8d112ae6f565dc6808e8b0ba7a3c38694487187f8a52ccb22b2d47e0a1112baa4ac4b73c3a105","nonce":"88c826f8049cc7ab2fd3b8a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"703299ba1f4a38273b653165daab79a70cf56a0d45777440aa0ef4899b7ba54b93bb82ed7a1a8356a84f6c81b4","nonce":"88c826f8049cc7ab2fd3b8a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"04a34ee6b338474e5254bb0c38ec5addf1288780a3aeb926805475753460e8e941180331374fa42c86d2dfa12b","nonce":"88c826f8049cc7ab2fd3b8ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"25cc0b8da2478c82c60d06cdac880402542306575f161f60222b8f5d5ca2791ad291149e166d37e5c5543db3a4","nonce":"88c826f8049cc7ab2fd3b8bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"13c0d1ae4a02f06b1e9938838a040f61824480f843b36481e3497a09c0a1c17f5eb27cde219e849071a160b6c3","nonce":"88c826f8049cc7ab2fd3b8b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"aced15390a9ea874113dc804671d1ec82fe462c275065a5e57bdf6ff005950576d17c86d16edf1639d452deb32","nonce":"88c826f8049cc7ab2fd3b8b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"ab5468fe66d5f052513c237a2c69060ad9a79d5271ba3a6c6e4cab95d77eeac9f07fc2fca81b4dae8360d33e88","nonce":"88c826f8049cc7ab2fd3b8be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"94185521f8ad4d7ac75bfe704614333e08af53a0a9b1a83df361e17c9f5127023433f7ab71db70dc353a2511d1","nonce":"88c826f8049cc7ab2fd3b8bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"c2e4467c60b1540c7b439ec6b0b2245923b48617079cc01280d319c013c214a3c36f94d32ec98e2b2d61fc8397","nonce":"88c826f8049cc7ab2fd3b8bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"b36dbbb6cf108efcc8059b902a6a6f87b7c804aac66a2feffab6cfd237592388b2ebfb41be4f54705da7a06429","nonce":"88c826f8049cc7ab2fd3b8bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"cdf928d8e5ae0e08a77b2473bc61e3dd6e50c3e9463675549f8b848948ea24aa6cb38f00b1787b27f68a319ba0","nonce":"88c826f8049cc7ab2fd3b8b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"fe4d3497e38f07a2161ea711c6c79b1802e665fc08a12f273535a9cd9fc19e3e744aac50dc1d80dbd59dcf7caa","nonce":"88c826f8049cc7ab2fd3b8b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"95a3136dd9d2618e37fd0cbb79e4f69790472edeacbf6554d9cb15fcc750ba02b61a7ce5fa918da46eef1e32ce","nonce":"88c826f8049cc7ab2fd3b8b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"4f76a11c4a40fd56416baf3b0424cb5ffca2eef2d16a5b72b2f4b61b528969c45ae7b4d368ed193d22106434b9","nonce":"88c826f8049cc7ab2fd3b8b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"080cd53c4aed24142d055cc81a43d36fd581ca5fe32dfe6a68411af062d93548c963ef286dd928dc95a87c7cae","nonce":"88c826f8049cc7ab2fd3b8b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"d3ec1aff0580da3549441f8ea8402dded759062353174c154b6b5ceb75508c5f166fb4bf3e05a0cb47905df0ab","nonce":"88c826f8049cc7ab2fd3b8b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"a6fdc396da1f04ebb98bbd4fcbe29dcce4ddc7471e80f6b5ad11be4fd1725e3535b979c7a02f946bd7dd737dbf","nonce":"88c826f8049cc7ab2fd3b8b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"51e10691fa38850202fdba41f6f172413cfa24033c5ff64e33ab1622900a1df123dbe94634e50ea91400fcad5b","nonce":"88c826f8049cc7ab2fd3b8b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"0c542bc67888b1b115e120f9940a2907bb5e099802b2386ea25c6d973f28848cd439c89998b9a6e580cfc27ae8","nonce":"88c826f8049cc7ab2fd3b8ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"3d6c542426ceed879c2833d8484d60b3e6f6bd7758583f399eefd915362fb1ec2f24c3e3ed9c9b7b8d923d9dd1","nonce":"88c826f8049cc7ab2fd3b8cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"0f157fd8f126835e18f2a6fc0332beb920e80f60264db74eaaf600b4a033b00c15c3bfd59bdba1e69974275960","nonce":"88c826f8049cc7ab2fd3b8c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"02d0f90971c040b8d271e05e8f72041f88cb97682ae489ee66a979a08ed835b4608c6259587e2dc8e592e2d4fc","nonce":"88c826f8049cc7ab2fd3b8c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"3c708777f0b9502471167b25b03cb79ac9b0a76547c15741b31a304936c6dc0540c2466d94741cb20cf0d4bc3c","nonce":"88c826f8049cc7ab2fd3b8ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"d6bce5bb90983e1ec95c7a7c62a207701a283f96bb0c4849bd4dd7297f0458375721b8899afb5a6b3724aba024","nonce":"88c826f8049cc7ab2fd3b8cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"e33344b8e9d1c2b26d1e0e791225f777190f52f11dab192150c71e278fc13d1d5c6f79cc3780803d8d4121506c","nonce":"88c826f8049cc7ab2fd3b8cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"cb92ecb16f7f28bd0fec029adc1c65d618e066431860790ef360297e45f22bbefd98303ede4093b46e29f7bb2b","nonce":"88c826f8049cc7ab2fd3b8cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"af797b43e44aacee77a85077e08e5ce8c388180fb33dac48118104959ed87fb41e58e4e391acc7d50072379f40","nonce":"88c826f8049cc7ab2fd3b8c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"d684eabc7816762ff2356fa3ac910066a04be511c8c36132cb93e8be022bb8e9a3b4f383d701e1412d285b3f6e","nonce":"88c826f8049cc7ab2fd3b8c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"ad49165f3c82107cb091e4553716ef8e2b709bb9b4b207614eefbc53f8cfbc2129177688dd015c4dcc8eebdc9e","nonce":"88c826f8049cc7ab2fd3b8c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"ca0ca36546e16d02902624347a1323c7b2610459525bddcacb6b00c42f94fe52e39ae0f543c76c4341edb421a4","nonce":"88c826f8049cc7ab2fd3b8c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"043039483b003ff3b54518a4830fd66e6242364c7c31df373601b42fe9439ce7cec6ad0297862366259280aa3c","nonce":"88c826f8049cc7ab2fd3b8c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"3cc479e4605654cbb56e481efd754ac5c73fbe340812f9b03a142b7120dd340edc7d46fc1cbe75571810ea78b6","nonce":"88c826f8049cc7ab2fd3b8c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"4a2338cc4781192ff8f9bcfe426670f594bd2edc985b9a99db133a127cf432f6b9e61ca6e0e0cd6636c02db797","nonce":"88c826f8049cc7ab2fd3b8c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"21ce85e3991d900995a94cba68dc84b80777037b161db8f06b4fa0787d4ee01da6085ea868e6d172b5f3b48e9c","nonce":"88c826f8049cc7ab2fd3b8c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"6dea549dbf767478305c754f33e019304e77eea5ab2fe894ce506215d5254acc7bd73f6421f2a12cbc2b1b3564","nonce":"88c826f8049cc7ab2fd3b8da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"14ec6a5c5861ebcef690bb2e4d5d194bba3d255b5d8e26b5cc4b5c113973bdb5e6d564033855f93b47ec56c011","nonce":"88c826f8049cc7ab2fd3b8db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"0bc01ec9381c30309264a58c18acc820f7150a0561a1538f5354bb7c66de6241cf69e13cb1af7c618eed7331a9","nonce":"88c826f8049cc7ab2fd3b8d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"09b9ddd1306755dd3dfea97a6e75d4b828fc68c7137d4fa405733412f02e3d9a75adc9e66c8ea0c59eeede31ae","nonce":"88c826f8049cc7ab2fd3b8d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"56304f943ae141c48987d8ba1cb62eaa8863e1c1d5a6af4ccb717a5ece5bbe9c92f1ce7780a925079be3392dac","nonce":"88c826f8049cc7ab2fd3b8de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"3d4bc65fe0d932c6823ddda737e06e27c58fe2d9d1f539d59b76b0df2a8bfb8988cb29679e1942b0a9078743c7","nonce":"88c826f8049cc7ab2fd3b8df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"c39e1298bf30592e8cf64912fdcbeda0dcfccef537e3be527cd3b334089ce310d18852a484add49493e506107b","nonce":"88c826f8049cc7ab2fd3b8dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"5dc7662e97f94cb6981c0b7361502975e49c141bc7a5d072a318d726b3046c90a2ac817860f6b20dfc49b7134c","nonce":"88c826f8049cc7ab2fd3b8dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"ad789def420e0739b162fab1c772e9b269cfe849476a50f1b4322f9c3050b8a71fd47424fcd7dd2d83fa7f0861","nonce":"88c826f8049cc7ab2fd3b8d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"bbaabee5a1db91d196fd73062f5f0814dd4cd488e0df79d141237d1d1a9bf2b71f00f9fc4a00f7b802e75ed21e","nonce":"88c826f8049cc7ab2fd3b8d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"69deb3188a25da39e0bda89cac2448e07ec91ba3f8e51c6b273576b03ba843725d3104633180868fac7f74f3cb","nonce":"88c826f8049cc7ab2fd3b8d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"e229c49ff8bc0f87494c31bad44362866a9a24ee16e4b092103b42b706fc07e03218c30e8d2978bf8d37ccd5d4","nonce":"88c826f8049cc7ab2fd3b8d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"73968978d4e3e550b212ad063214ad2283254d41f0acbde82fe243ef7e941d61e3c5e0c83ae47ed52592f58c6c","nonce":"88c826f8049cc7ab2fd3b8d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"06a4eda7c477ead592da8adbe71eb6aafa6c32edf1a81565c8270ec61e1389ecd116611725765fef20776ae3db","nonce":"88c826f8049cc7ab2fd3b8d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"44daf0db9a9a219ae5afb4552adec631b64e1c6b53c5abfc169d77b994e239aa2595764ffec1b42ec9e02192ef","nonce":"88c826f8049cc7ab2fd3b8d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"49ff3ade637a334840aa5d0b07b8fd04d02ac8f2927d5750d94497a75c71955f991c20c486c3fab6731bb3b24d","nonce":"88c826f8049cc7ab2fd3b8d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"300a8d13d38f91ea801e574f721df1ac335ee774ab49c863c5f1823405eb650da27190e9f5d65df8aaa6a7d698","nonce":"88c826f8049cc7ab2fd3b8ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"d8d1b5f1d6862c2ce1f56489c3fc6a82b829226f1e58bd56458f1096fcbe894d99823b597a21faf04263764073","nonce":"88c826f8049cc7ab2fd3b8eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"46898ccea16f24b0f0777c7292e9b2a59b3b0f02afdbf432900b0c793a145d5db486e2d122dcd583785fd2f62f","nonce":"88c826f8049cc7ab2fd3b8e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"2ab5933a825f2486d2745b828b75f1db96dcd8edce16689cf7e6d0795aeafc9738385a99b8dee519eff4a49edf","nonce":"88c826f8049cc7ab2fd3b8e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"54f0a3e903c9aae38b12b50ab0bca87a63261dae14d9fbbef19e8d3375956ec2ff3408e233e1ca5f33633a2a9d","nonce":"88c826f8049cc7ab2fd3b8ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"38b731010226c6be2f2220fefce3536850e395b7491d6b44bce35f39a78757251f89250f093a7e6cc08f2d1319","nonce":"88c826f8049cc7ab2fd3b8ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"a121009621d2522f8785c0bfdfb3916a20baa48083833ba43cbc60488b5e17d4e8652d90d61cf442cb1ba4c80d","nonce":"88c826f8049cc7ab2fd3b8ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"13600633b3a80668baf964deeae8c5267423f343da225ec1ee5269fecb8ce3f6084539c670b2a888ea9fa2dbfd","nonce":"88c826f8049cc7ab2fd3b8ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"3f067221d629ab387f05bf5bf78c5bdbb2da5a94fb2262ae036074f4367149f2ad32c59733fd9da5ed60af94b4","nonce":"88c826f8049cc7ab2fd3b8e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"a092970f99dca2d464418a2afef92ea8e529753f09f9d7f823de138f5688b36ddf9d4548e744f0ef23eaf2bc4c","nonce":"88c826f8049cc7ab2fd3b8e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"9fe893c11d8d642ee44a3da44d528ef7ba0e41baf6ba45222fc7a57edbc2c4e6a144cd863d90bd81d453ca6946","nonce":"88c826f8049cc7ab2fd3b8e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"e0fb87012d7e78a3546d68f0b3b4a5f9e0e5e3bca02c07ba2906554cea442a992efdf9624f74c31b917fe5fd7f","nonce":"88c826f8049cc7ab2fd3b8e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"799583f4ec31ffc4bc9850c3fe35ede17448278d2eac724d18aae2706b68f4550154f0629f96955fc649bda2d1","nonce":"88c826f8049cc7ab2fd3b8e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"41e1dd4dc63eddde24c8fd98d99d0f50fb1bfb8d4a433a2bf17a2865f3e3fb765dd60919503a2f4a8c11d707d2","nonce":"88c826f8049cc7ab2fd3b8e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"f4011c7ff0272dbf5a2424f9170f65c3831a08fd1cee04edf2b8c2b2f171ecc55d8648a30147cd0621ca44dff4","nonce":"88c826f8049cc7ab2fd3b8e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"62ee29b40511592e907e2c27b47bc54db9217fcf3dc787c5123cfc9614a3a56849d7c8861b6eeb00fd9cbeb432","nonce":"88c826f8049cc7ab2fd3b8e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"44e2a15cb0ef6b3255dabb3c680a3ad141c013087ad44d78ddee8e390c463bfdc9279f50a2df34c83999d72194","nonce":"88c826f8049cc7ab2fd3b8fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"239cb6c48e2a6540d9bb8db9cbf62adb0355a6513bf4e50b05e41032fee13be1499fbb3e37e9d899b446cdfb93","nonce":"88c826f8049cc7ab2fd3b8fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"ba4e8a53787c73115cb9cdb1e3a46f68016ec41c840331d41a02fbc58a8114ee2cdc9704c8a1657c9634ed2c3c","nonce":"88c826f8049cc7ab2fd3b8f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"8a31f0190f66969813d5b2761c8b8eeebbad75867a485f486a99c92faf91175811483a70dd1ae2bb0422094289","nonce":"88c826f8049cc7ab2fd3b8f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"d92f2a258da32cde40dc0a6db236b417a81cb96b7338ede819f28be05ff8e085d62c9a70f94f6722b65462d2e8","nonce":"88c826f8049cc7ab2fd3b8fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"403cd15d2a7175d3b5a60fea7733059f14bd4f7dcc21230f77211b95ea2f1ff92eb9377f9b1cbcfe7ac5d8ea00","nonce":"88c826f8049cc7ab2fd3b8ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"56aabcd3bff6f0a227394789320b481cd6dd3ef53de85e0ac89df80b3108863c26f3773b433df4442847731b68","nonce":"88c826f8049cc7ab2fd3b8fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"ab1c374f3bb54d731b0dc3f790033ce67ae39dfea24d3e897980a46ad1376becdf8020a700db1f83fe95bde71c","nonce":"88c826f8049cc7ab2fd3b8fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"ccc8f12123da82917e1ecf07bf1fcbdb228cf3a5519535f3acd6d4bd04d833e70e645122500076ca4dc3d5e155","nonce":"88c826f8049cc7ab2fd3b8f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"75b8d637946ae26e30b923d9e2cf9ab0862fa20f1b740ce28cd73a94f1ed36f34e7a880616720abadad1c7950b","nonce":"88c826f8049cc7ab2fd3b8f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"cd12e961c5ac273de0eea1c217e6ef47b513ec918e04415a29b1c529df162cbbb0003e55fa2deea5f3112d2654","nonce":"88c826f8049cc7ab2fd3b8f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"54d9b5acd1a10178b4fa33595c04dd13561e4a6aad51e461e09e5f4f8b5c97eed1d065a5ae09f94af8a11b1fbc","nonce":"88c826f8049cc7ab2fd3b8f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"0f8594d4d2484f3eff712bf7fa920b62e1385485b57470823e458cdb27e2299296202b33f7dc189c44f459b20f","nonce":"88c826f8049cc7ab2fd3b8f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"b392e7c308351351abb01d9c29fe300e8457c2ea080444dc20f272692f591ef58748d92570beb8612d8978d8c7","nonce":"88c826f8049cc7ab2fd3b8f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"97aca638e575da90e06a420f68e3290acaba1ede958ba442a956c93e0207deee124382ea627dfda65cbadf3019","nonce":"88c826f8049cc7ab2fd3b8f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"bbd1442afe42cd395ff426730f9475623ba1b25b900151efea9a1fa3f6504d9fa4fe1754b86a54af3625aec18a","nonce":"88c826f8049cc7ab2fd3b8f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"5dd8a0e099547a0fa219769fd01160d8d8ece7ce68d52bccfb660014f897f3c11771554e05eb4603ed8f13145f","nonce":"88c826f8049cc7ab2fd3b80a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"592b9684db9da1b4ea50cf15a6f2615545558c10dc68447f489da4e1987350bae9d49efb21a41a1b78de21e676","nonce":"88c826f8049cc7ab2fd3b80b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"f7e1684e79d8c121517555f5b339bf34ced0f75144f9afe1f93560e6e8e7e03c8c890c1285764691bd547c24d1","nonce":"88c826f8049cc7ab2fd3b808","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"33574ccd6fdb60fd4b5bd16cfbe52c76bd5491bcf98f670d1e4d4e8c0005913f6d3f527ee7fb116053a701e040","nonce":"88c826f8049cc7ab2fd3b809","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"f4ad40911e49aba49e50ccc862365583a02b636fba921858b63c72fcdeb36c465b7bc677d1835073565737c7b0","nonce":"88c826f8049cc7ab2fd3b80e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"4f288aa90d7c28468487825be21adcba3e3077cd2cbdc4f6d0bd277201193e8d3600932bde5675e8ea2f1daec1","nonce":"88c826f8049cc7ab2fd3b80f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"809ff740d4aeb8534fb2a1bea6ab323bf86cc43056d95c681e83e4eef3f1ed5ba2b5081e10ec639059d7974ad1","nonce":"88c826f8049cc7ab2fd3b80c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"677f4fee7c6361e241d909693d5d66c937885d3b93e67448ff97296682ad06ce7612fbf69c6050b1e51af5ac2e","nonce":"88c826f8049cc7ab2fd3b80d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"237886cd93dc021a63b2cd06e1d82c449fb2c6dbcd985d403ecc8acfe6b577f1076aafaeab6b84464a8dabf8c2","nonce":"88c826f8049cc7ab2fd3b802","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"7cfa033e69e45a34145b4bb94aa3e6c5d0f9e26fd2315310f8ba0bdc0d240d1cd005b7fad418cada9a82cd0f3c","nonce":"88c826f8049cc7ab2fd3b803","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"b8f8f4c7ae70a2bd6d2495c5023edb4f4301313491f2d4c9dc04e546cca9eddd5c619befb020003dededa72bb0","nonce":"88c826f8049cc7ab2fd3b800","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"777ae094d7f50b835aa75cc55695b9c9c3f2221a4321b7357220bd5c6f7ba97fd9ee74487ec8081b00d9a632e5","nonce":"88c826f8049cc7ab2fd3b801","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"ec18f444d24fa6d8df43a437fc269c3d4bf837af859aa92ad46bfd30b24be586b5970b359d77d541dfe86de113","nonce":"88c826f8049cc7ab2fd3b806","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"74fb0be1d7e88ba916175b724673d01f88bf1ebd0f8eb987592c856a89a47be483f40e681b9ac8b547e0d381c9","nonce":"88c826f8049cc7ab2fd3b807","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"a2f94b8ac1f960da708774b16c2c68b2f8f1c265c0ca3fa3a9f36608462b8c8ca7d76a9ab4f00252709941d620","nonce":"88c826f8049cc7ab2fd3b804","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"285431b8f0d16aa9445845a70de55731873ae473be22fb9fe06a7b49c055addded7fd0acaf390703d48afdc094","nonce":"88c826f8049cc7ab2fd3b805","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"2b81c784ad0d4cb7247c6d6144af9bafeb691bd73bc245381cb29040c87407f2df240d9eb8cb7bf78650b537f2","nonce":"88c826f8049cc7ab2fd3b81a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"e69a81d6ebc86d141f6b82897e5903261f57528303dfc962c9a8678997f2cbcf364a37a1511ae5f64b7da1a7b7","nonce":"88c826f8049cc7ab2fd3b81b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"9091aa74427a51b3f71187a9bad17206b857fa26d186f6bd893c655ef1a11d23d8ab323dd5b59eba5ee8547d08","nonce":"88c826f8049cc7ab2fd3b818","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"903ed1eb7439bf124c2ef9fd8e42be1c9d85080b5cb7d0151731c5343ebded053122aedabbf7d1f7df39ada4f3","nonce":"88c826f8049cc7ab2fd3b819","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"e26739bfddc90181884cb79275a51cb409c30578af1b02c51e2963edbf0488cdd35aab7528adc67d6fd7ce3f34","nonce":"88c826f8049cc7ab2fd3b81e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"a49829ba6ab5ee825098e77cda540b6776f6ce80017c8f119f18c6b734932c94efa0342d5c6c824d7dee5d0042","nonce":"88c826f8049cc7ab2fd3b81f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"49e2e44611b45e8c3103d2caa4517b32d859170f0ce78330c6bba9ecae8f7b175c04c2d50bc1b084a5512916c4","nonce":"88c826f8049cc7ab2fd3b81c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"ae1a4e172e8f3d5550a0f000ab76c2349d17772eb9a2d9188b776c57d2f25c11ac131b48110026840a9c68e115","nonce":"88c826f8049cc7ab2fd3b81d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"7f5da72e9a5e30a1baf320d211fd9a0870051cdc417d2b2b967e199616c2ea4fdc044058370a00d2a78f987690","nonce":"88c826f8049cc7ab2fd3b812","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"23f6bb4a9b9d5f9c4d2a2acb962a3730db7048c8eab653cd9ccd54e5c9c9712a05e9e2e57811649db8ff14266f","nonce":"88c826f8049cc7ab2fd3b813","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"d4d2a672ed93bbf8742ed8666887152c340b7643a8ac2b42995dfec59e5d13debef587c87b30e5aef411a5c06a","nonce":"88c826f8049cc7ab2fd3b810","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"7b3ba4ea8eef554ce394143f60d365e8c32af8395ea7c187ba3dc4238b81af2bbe6c1dd08ee783295e631d6d91","nonce":"88c826f8049cc7ab2fd3b811","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"2d0f43406d43e23be77969588e7c3a8578d6800af1e50870db706aa1e1873562db3d9653ca59266b13c7007739","nonce":"88c826f8049cc7ab2fd3b816","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"309a0a83a83d0e17982642726826d60737c846a66e767815124e4e372d8e92147c25a9f37cc20b62337032ff27","nonce":"88c826f8049cc7ab2fd3b817","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"37c3336dcd045ab081fe36f62a891c97690ee40fce509ad2a174012b923aed84457d87711f5bce803f5eaae8c1","nonce":"88c826f8049cc7ab2fd3b814","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"1e9b7fbd334a04da7e4747ecf0e298b961a985d99a88ba8a96c733e7b0c1a19d42499319cd744612bf4807aa02","nonce":"88c826f8049cc7ab2fd3b815","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"ffabf471621a8117d2591bc3d913e01b47cc36b6734b94e51164764b04e263c39968ee259682a396819b4d3121","nonce":"88c826f8049cc7ab2fd3b82a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"51c2c09a92a00ccb337875adf86a10a7bbcb6eccd9de6bcf6f7c2ee5af47f94c5cd8282f04db0eba38d5da1a38","nonce":"88c826f8049cc7ab2fd3b82b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"b0b5deb35db73180376c268f4f9133c735b4336bbd71afd586763cb788ce659cea099ab09f1e99115077ca4ca3","nonce":"88c826f8049cc7ab2fd3b828","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"8ba1d810dd5b70ee9ca0faae59d3c33aa66d639fde368587b88205742fe9548c68d1f32d53c3f22e18e6b06cb1","nonce":"88c826f8049cc7ab2fd3b829","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"b509f8a9d60e2b34cca2a802ce558dd7843908780069350a2da5aba04f44cc68e0d8765c6a43fa98b69838002a","nonce":"88c826f8049cc7ab2fd3b82e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"547cbdcd65d11b4c2f19df56df636d3a6fbf217f0a7954eda46d29887da47178987aedbd4e526d165fd7d5f575","nonce":"88c826f8049cc7ab2fd3b82f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"529788ed3e08f98ae08d457d7f0809a1a1a39ffb1f26209a39a6ca09291ce183daadfbe206ceb84ee15dda62db","nonce":"88c826f8049cc7ab2fd3b82c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"99cdee7e28f8884e7572fbc1123977594bb6c75444012ab720aebb01ea334ec2aaccf3dc2bfaf64178275a28f4","nonce":"88c826f8049cc7ab2fd3b82d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"7d3a844d219d148bb21ce2fe2dee61a3cf7e6f9bfa2a9951e8afd827a98c783a59906384794de1faf0e4f36106","nonce":"88c826f8049cc7ab2fd3b822","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"e0f595cdf5fff30e50fcd8b2885ba3e1c20206410240bb67c361afa03a0ea8b7e40daeb6180aaa952d841ce0c9","nonce":"88c826f8049cc7ab2fd3b823","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"69e47dcf02afcd8da1335a09caf4f74590024f1120259428757c8c9404c13a6ad002d6eba8d9ebbebda55cf299","nonce":"88c826f8049cc7ab2fd3b820","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"ce3c5f39e09c5751499aa417a5dbc665e0b5ab6bc38a10f5bb90d60b8383c4c490f798373ab788ae77c3761c94","nonce":"88c826f8049cc7ab2fd3b821","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"a746e0f05825def4928cc6d8d1654063ad1d207ca5d4097a70b3d3d7782efc1ad27ff0d49a443ba8780149eb80","nonce":"88c826f8049cc7ab2fd3b826","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"f7b8867a465ab3a9870165a89d751b5fe0c69b41c703101f65c404c7aced3248631cd991960ce076f8c34c7331","nonce":"88c826f8049cc7ab2fd3b827","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"807c03ccce4f16f633b5942585a1f06f1a28e29a375970102e4f23c04aa981ccbc0cfbf6753e48cb6482570631","nonce":"88c826f8049cc7ab2fd3b824","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"f7cc91f1180564b10f5cf4f4bfae80e2f6f99ce8dfb0f0b12b0718ed19fb4e4174889a462e769f00f6311ba467","nonce":"88c826f8049cc7ab2fd3b825","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"52091f11a26bb86abb17d7b26d2cbe77271d5c626ecbd2ac45ecc46dcc0c195fe65cd9d1d30c9bf9da361a9393","nonce":"88c826f8049cc7ab2fd3b83a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"d0e394994efb8f35034b7428338be9ffb077000ab12ec31b640c3bfac171f86e9f52f98fd2a563682d3ce86161","nonce":"88c826f8049cc7ab2fd3b83b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"fac329bb632fcfcb6bfe6647cd95c1cc3a2168915f00098922f51ecdd28f00b2cec0ea05681268ac4ff4d20302","nonce":"88c826f8049cc7ab2fd3b838","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"0de8576ac769a34829a01dfd60b080fc4919f30578c2769f923c8f45938cd07f6346d1c47865afd8cef3c7fac5","nonce":"88c826f8049cc7ab2fd3b839","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"fbfc5b55edc274a9404f6ac22f93fcc24244cbb1bd9fee54dac85cdb85e1c9caa05e1a050d7a908647e39094dc","nonce":"88c826f8049cc7ab2fd3b83e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"f2c5c102886b2d624fc16e896d918a11c3b1abd7ba762d88f81a68ebe6c0d55b8f9cc8b6c0e167bdc3758ebd14","nonce":"88c826f8049cc7ab2fd3b83f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"bc99c9fd4be204817a62000f496d55628dbcc366e4dcaf06fcc72fa72da50274339c656f2ac282492803d506f0","nonce":"88c826f8049cc7ab2fd3b83c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"a29177205118ec4b26a28a1c5038ec4b9a60f405f465237ad8dd615b0aa45dcd6c0baa7af82b5f605584c50e49","nonce":"88c826f8049cc7ab2fd3b83d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"b899c1e7d608a00475800a906722d0dd4356c244508c2c75e80044721d54ee62266bd815c3b69c35ab253d2783","nonce":"88c826f8049cc7ab2fd3b832","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"26dc1af9d937b5e4f84ab52f31ab6dc4c87a4b1382c60b402524f50bad58cfbc2405caf141f41b583cbb2a3f28","nonce":"88c826f8049cc7ab2fd3b833","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"e89d2584d7479ab1baede0f78c4729c835adb03cf3a8d6c54fa06860ceb2aaeeceee6cdbf074692d3a2d8a49e1","nonce":"88c826f8049cc7ab2fd3b830","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"7f35902f2c1103e97ffadaf6e568448e63dec3cb2e7afb345cd25236e734198db2a212bd961f2ce6ebb8fc8a0f","nonce":"88c826f8049cc7ab2fd3b831","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"faaf0245a2f4aceb1242994f933868f1c7f94b3f3f1b07deb0eaad88a3ac2b273e419cb11eaf68b0849f42facc","nonce":"88c826f8049cc7ab2fd3b836","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"bbdab7a9f157387e3a0a0f187bd205831b0130ee1021057abfec7276e0c48d362e287211f712b2945326e98405","nonce":"88c826f8049cc7ab2fd3b837","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"d538db7d9ad4760c7ee6afb15e1ab761815c48afbf69390ccb1e0908c6a7d9f32e5959c732d4f2c904abad8dd1","nonce":"88c826f8049cc7ab2fd3b834","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"5c8e31a821675c2bc3155ba59e48017a1eb3350ecb2a33ed2489642c126aa29b12fb8ef8b5bc50c854dd352617","nonce":"88c826f8049cc7ab2fd3b835","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"151b672d5846b8a44ea90953cb836bd37b08fc3522c70178b8e975b106f802960e0cec0a678d20c990c0e18906","nonce":"88c826f8049cc7ab2fd3b84a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"f38025ab56d98843fa620c1a7238ad7fa16e12f7381fd7c56234027bc360c07f611250fd102f1e6531cad4b2b3","nonce":"88c826f8049cc7ab2fd3b84b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"b2088dac2bdfa87914d8e34f6f9784c386b0290ae84c7bb8414f1e7d77a2385d9f3cb850b490d249de107d80fd","nonce":"88c826f8049cc7ab2fd3b848","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"1a918b9018335ca7f9af40fd14809693a6d4e69a51f67c831647e698f1fe291ab365225a19cfd46effecc2cc79","nonce":"88c826f8049cc7ab2fd3b849","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"7c143f40d415f5905bcce032ccf4a8e75ac033fc8e611cc3342ea911d9eeb9adab1c081c53d06586c4a5f78a5b","nonce":"88c826f8049cc7ab2fd3b84e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"e7c25378c68a5e140766db366fd12e8555c34145ae13384c8e617972bb1d8af3f9899792ca5ab390700693ee52","nonce":"88c826f8049cc7ab2fd3b84f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"c1497ddb2c0575d5a3a33a3f2c0426229b16a4fbf88ab5b1272c768e653cbb2e4964665fcfc492b8d07650ad4b","nonce":"88c826f8049cc7ab2fd3b84c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"47ab2506d1e0f6e7839b250ebc585174b9b4f38fb1c2619a2b45b0addc9fd889704b767bd3396b0880764ea6f8","nonce":"88c826f8049cc7ab2fd3b84d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"d3494db6f3f3ad238eab29659ecebf96038eadc89116c47b94bb2bb25d5d647c20a6ccfb9665b4c4cae4fa5b08","nonce":"88c826f8049cc7ab2fd3b842","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"d3aed68de580a63bd82107283ef1b72d17f3ceb228d76f395c3135b3ac79443f4bae052db05ded98ee45c284f2","nonce":"88c826f8049cc7ab2fd3b843","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"8bbd978a066458a1545807b13ba5223c360e1c0e62dc784946c1a4ee1846ed0e15b88c783772e3cbb1799da477","nonce":"88c826f8049cc7ab2fd3b840","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"039b682d98a868b9d1082e6712be6ae3cd02dcd3dbe2e76c9ec5aa6e18e5ee9228bf61a6987e57687460f49dfb","nonce":"88c826f8049cc7ab2fd3b841","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"8e6687669a7d7a0d4258358bb4ac70a21c71b1d1c17d72c2f111a1175cbfb5b7542360c5491822a098f39d001d","nonce":"88c826f8049cc7ab2fd3b846","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"36fba715670877d7a6eb5ed408382ef776488bc0d7944d680f57b580b7fc5b41714d3047580e223aa8c7d9f50b","nonce":"88c826f8049cc7ab2fd3b847","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"f5cdb6c16dd6004b5166f077f9c790fd927b3ea01a2f33748f0fc6e435dba91aa0d3faf0070a483dbcc892ac80","nonce":"88c826f8049cc7ab2fd3b844","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"acba36e718d32050bd96de96e13ec3cfab0b50445b044ccc1e47e9bb0118c57f7259d06c17d81cc4fe1a032e1a","nonce":"88c826f8049cc7ab2fd3b845","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"15397620499328a75fc46b8f1f6fa535bb06308c36d9e19d7ab403246904bf9717f7212a14d5644fcfd19db8dd","nonce":"88c826f8049cc7ab2fd3b85a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"6ad679232f46914aa666f6d92ad0c2d3269f35ad82b7813fc35801f9f067ef09d5f705e2fcdbdc26afd6738fd4","nonce":"88c826f8049cc7ab2fd3b85b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"1ba49027dba0679fcaadefe04ce2e14bab67455f7ba623a3a7acfc10a9bbe83eb7f175a27de508e2f6f75ca92c","nonce":"88c826f8049cc7ab2fd3b858","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"5e33800ab429e402c04d22f245baba1b48994021f6c4c85dc28423291e1985ba097cbea39c27e209fdb2b88797","nonce":"88c826f8049cc7ab2fd3b859","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"9c3a75c23e801c28c6efcfdcc37701a8181e922b982caddefab4d06cdac89e510b3d711a3a7738fa5e205c124c","nonce":"88c826f8049cc7ab2fd3b85e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"a42d459b0b9443f12be8f82674493fef03a8002a3e4ea4fd7448605a882f91c9ee3db805a0675c62681c67c23b","nonce":"88c826f8049cc7ab2fd3b85f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"a1b43aabd186cb1de8cf675ffaa9e0083ccc756b843ac6faa51517fd81b116a22a666abc6f4a281a1e831affeb","nonce":"88c826f8049cc7ab2fd3b85c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"e43acde3a87badb53f19db8cf662ad3872ce216159bb996e0a6c8b176ad94b81f596d8f39fb1891e37eb21a237","nonce":"88c826f8049cc7ab2fd3b85d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"43f7625a6d1bc9e39d159b0feccd7d164f71149c3210301da671c15b6ac3633a073290d5c1b344f180d118c41f","nonce":"88c826f8049cc7ab2fd3b852","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"169f88b208f8167d473fe25c2d9d7aaddf24d70989b264021d1e127f2831dbbe042aca436cddc2422e4f48258e","nonce":"88c826f8049cc7ab2fd3b853","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"509f673f2b812ea24ce233661498761a885d52a54a231f6d5e173434ef9d0300b351410347194892e7a6aa90e5","nonce":"88c826f8049cc7ab2fd3b850","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"cf2e71d541f794d448c3ea023cb7ce1529f1d004074ca4d641350eaeef5149978c8dcd7f351cc424bb38561736","nonce":"88c826f8049cc7ab2fd3b851","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"88277bbf987539664f3c72ac44c34be9881e34ddbd3002e9ca0f126e4264e1bfda0be0badaedbb3b2de69d3310","nonce":"88c826f8049cc7ab2fd3b856","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"140d345bfb2c6ae0d0fe691f3b1c3797336df5bf31ee9739b4dd83bf70553748af28411bb84b15b5f33dc5abcd","nonce":"88c826f8049cc7ab2fd3b857","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"9684efa20680b745fd86d35c08b5185459692977dc4cd410f198b08dd1a8677f252de04bf27698ec02bcb1f649","nonce":"88c826f8049cc7ab2fd3b854","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"ce33def22e057e591b3e98377634bb80816503f70be1ab2d8aec3f2ea53565b90427b143c49ff9a284dd45a04a","nonce":"88c826f8049cc7ab2fd3b855","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"09093a44ce2577f866c7c86e5b387fd4c77e34120ac6edcf1c68b8c597430017cbd5e18f47fa3fe4e474424a84","nonce":"88c826f8049cc7ab2fd3b86a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"9c04e065b833c4def69950a3fee5f48d4212e59cdfcb35f610e2865402d93ac383a59e8f341a3fb9778a9d651d","nonce":"88c826f8049cc7ab2fd3b86b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"de18a0bb446834c78d9c33f12408f056d9b7ba0f6011e5918476a7c7d4450876ced5fe765e324bd7993abfb4a2","nonce":"88c826f8049cc7ab2fd3b868","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"ff828ca6f23ec28246a0e1918f4b7ccf5160f0b6b9390de79871df17afd501adf73780756105f13c7130d9e830","nonce":"88c826f8049cc7ab2fd3b869","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"122a1c2795b08f50be3933e7b4dd98859413e7e18b60426759aedc72e0239b83d3f8461ea92b685ecf09b3b8e5","nonce":"88c826f8049cc7ab2fd3b86e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"58427b38a34ac05f6e51a3ff74996c37f9b74fa1ff212867b96bf034f9f12b00ab8873d49e3505d80cd304ed37","nonce":"88c826f8049cc7ab2fd3b86f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"bcb4eb7ce38fe69311c6bf33c620d19843f0585382fdb8418018f3ddc2bb509c2e13f22c8f9eb3845f1e07ec01","nonce":"88c826f8049cc7ab2fd3b86c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"2c67a730c2d38795fea8bbc3da763ece41a08674086702e41db401f112456f42cb5f6aaa5a748baae8a8218815","nonce":"88c826f8049cc7ab2fd3b86d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"96472b4aeef4e15430b1554a9da51d1f0a6f64f413ab2e82910afdc46664e273884a2cc244c56f96fdd1616ac5","nonce":"88c826f8049cc7ab2fd3b862","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"75b0a50966acc6be37067c048f71f21c8e30bfa50760fbbd7ebe5b2e0f5643a1233653e82f63a89f92386625b2","nonce":"88c826f8049cc7ab2fd3b863","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"1335d3c0b2c83a72b13b0efaef2070425749b6b58a5bb1b7de8a80dafd2142bf5fadfb2301e7981b536f0531bb","nonce":"88c826f8049cc7ab2fd3b860","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"788c0baa48ce8c042efc5eb81c97bbcd02bdb8e24b5caa45c1851af2f36b9f2b51352d535e605767789693313f","nonce":"88c826f8049cc7ab2fd3b861","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"bf26434dbac865a5ab944c9e785e784f617c5e841306b77e6d8a271a447caacadcb2c040cd71ad83b6d1ff2812","nonce":"88c826f8049cc7ab2fd3b866","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"dd1ed864828b7c685a32c8649f3cda0491ffea17f184b153987a619fdf092b660d26e2a25a1cda3fa6745473f7","nonce":"88c826f8049cc7ab2fd3b867","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"68a42023ae2350dc434d9cc328dd335040294aca8555e8396828bcb345c94c66b1d3c348a5b8d8ab26025591eb","nonce":"88c826f8049cc7ab2fd3b864","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"6c80c6aed543c2f6d618399cce3b244a3c7ab85ebb0296538c08fb1c678b3c6e362b0a338f007a4aabfc976438","nonce":"88c826f8049cc7ab2fd3b865","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"d9fc3e8ff1622dc521269f7b0108cd52b2e7b78f680296d0c87190a4a6d891e38aa6c9785b812ebb83854a4b13","nonce":"88c826f8049cc7ab2fd3b87a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"065c4b8d96fd71aad9dbdebb092f97569be2dfb49682f622ed71a668604be50353a60945281a20ff1d50b6ea39","nonce":"88c826f8049cc7ab2fd3b87b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"59ed1753c399c5dc6c7d8b2c1663120e9b26edc41f32512d99fbc15cdf7b0e7ee87e04cccf32b0fd4e39595ed3","nonce":"88c826f8049cc7ab2fd3b878","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"4f09ab14bac37b7b956a3864e16eacd2f9b4f67edeb0108047040ed6e2c2483abc9cbc621ed9582c911736cda6","nonce":"88c826f8049cc7ab2fd3b879","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"2f7f69eb4ec8e611c44574b77b4196d3ab4196d0a878148335f1efb0b04459e86b317a42fcd6d7929d8c86b117","nonce":"88c826f8049cc7ab2fd3b87e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"2f3a6ab3f3796c4ae8272db51fe0ad7e03085052b9faaeea549b3c8e9420e9040b8560fde3bb07cfc3af1ba590","nonce":"88c826f8049cc7ab2fd3b87f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"32d3aa009c651a73a44febe6587e880fefd0e855f50e9e2ee67d1c699406a46401217140333e75fa663993be36","nonce":"88c826f8049cc7ab2fd3b87c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"8866c91285bc82074a1657b63d5deb41b95505fade6cddf5ac61e0d5c7c39926aee98593ded0905e3a8e22476d","nonce":"88c826f8049cc7ab2fd3b87d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"3b8cba5e4a1185c85d2e0481179288983926a998ea4f76e949b6b7d3c9a88a6de799b486fe5f6788684cc08770","nonce":"88c826f8049cc7ab2fd3b872","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"fea82d24850940428c31f3539e329344f0efd7bb8fe79f75cf7d24d4fe03abfeea8b35c1b60d5adde785164a2e","nonce":"88c826f8049cc7ab2fd3b873","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"a2abed0158f3dfe30e776009f080cf5a5db04391bf4f5d95d536cff50959b33ca30701011a5353c9617c0a2634","nonce":"88c826f8049cc7ab2fd3b870","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"033f35969b7c3ed4ad82402fc15bcc5d5f9336ee20196db2aa42b819ba8ee5efead9546a6f777f58fa469ca39c","nonce":"88c826f8049cc7ab2fd3b871","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"a12fa227aa72b6390264dc86e5217436094839b27c0052bfe8640bd214d3e488ec4c5852c73136bf6d65277e94","nonce":"88c826f8049cc7ab2fd3b876","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"bae75fdd1940b5accf56313ef6d9f6778eeb5049611d1652dacb5ee5dc0ddacde7d11646a120d7167bb35e6942","nonce":"88c826f8049cc7ab2fd3b877","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"730c005d5f3ebbec72d6519b99af0cfc5c9a261cf8ddbb5344ec348ea98be912a68807ae00a7cf976f1c969d29","nonce":"88c826f8049cc7ab2fd3b874","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"9db7a15ec38385b6f58d2a2cb7ec942e754f74e80025f4084ed7d89ad4a492fd6b728eb0224949e8e9c9e66e73","nonce":"88c826f8049cc7ab2fd3b875","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"fe9b0a87eaa7b14ed016e2425979e81383fbaff925d91c88275da4409beb9b4adcc39392cd4c503f71d74cd05a","nonce":"88c826f8049cc7ab2fd3b98a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"40330ee3541db14e055a07115a8aab51500128d12c0ee338c017957d08f49f7e"},{"exporter_context":"00","L":32,"exported_value":"3c6e34fad40b253321520439fd78c86ad16c0d2cd8aef8141be66b3452e349ab"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"06b41fa02f8d74aaa1f8b64d1da79c2b86afd3379abf75c47cb1e1dff55ea491"}]},{"mode":2,"kem_id":16,"kdf_id":3,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"4e4d6e3f35165f3f05c2b8fcb65747e9470c8e25435e6186edae5b06641269dd","ikmS":"be1f40c6444fa5520d4d33596801df8c0fe68b555e0b7e18b1f10b857a948050","ikmE":"83839def513cce8c39bc2d2b49f65cda16ef8c42a7710e4d2c1459abad9d8224","skRm":"91fca332930124c01894a4532f003e3f3ed83f38df0648a8fb22056afa043788","skSm":"80846a61b6ca6e01c81ceb01c8ea32a0c0fb7c7e3ca112bfffd8236a07c0767e","skEm":"3e91dde1e66124f16c6e1812687a67ec2aaa6605d1abf34774a2698a77067d60","pkRm":"0494de2db63f175aff8d0decd8eb7a707571e7c5eb9cc4ce01d4a284135286f0a0016277785870fa7228811c7faa817174f58c13baf833321eed6ff59a5ccbdbfd","pkSm":"04d54e0ac959ec088b21ffcb1beddc37221c6a8e9b9f24ccfa85f4ba3c6025ad3d603588d9e00ceb628e8ef812c7b6bf68a48d7c3ba2d0bdbbd9f933f87afa9019","pkEm":"04425c69e73b01202562a1505da73134f9c78c9643523ebeb77193b2579dabccfd264fa23b37447726a304c9d530346d87eef2b35e1f01568c5229cdf5803da5a5","enc":"04425c69e73b01202562a1505da73134f9c78c9643523ebeb77193b2579dabccfd264fa23b37447726a304c9d530346d87eef2b35e1f01568c5229cdf5803da5a5","shared_secret":"a06efc7a0d33145c11a3a80eef77e459dded7f65b25819877706fd7289befb14","key_schedule_context":"02bc71466af15b2cc51961c551d1c006f9dbdda3be795ccbb980f169ea6fb31003474b10dc797383ffb0325aff5f75701a7bfd781c6298a5637f7a8fa2e6b5f624ef4b8a36b914c26820d53e83a9dfb742c7811a526e9dcfb2f19f895c68c80dd54c6e836af7133e4b89418b17bdf4c1d32445ee0bc0f40063a0dfc0e0913cc37f","secret":"8b146b3f17db5d0b9aac5cd921e66f40eaee5450d8fa244503f57ebc36e413d6fee97d332f1e154dc7faaa7d211b25ce599cf8d3a649c77431d3bcbee9d408ad","key":"ff776958c8de8a442ec40e46faeddd566f781a271e4db1342e8239708d7975c5","base_nonce":"d505fc3904839c7a29fda4cf","exporter_secret":"f0ee7dbe877ceb26b5e11938ef244fc0500821cd864fa21bb7304dced216c03ee7af4b1069cb23d3b88e415e4edadf1fd4716e929464d1b237d7b878b9773e44","encryptions":[{"aad":"436f756e742d30","ciphertext":"6dee1ff3da54a47faa7bdd2ece4fe1f38d10cfb9137d6d7028947d7f62984fde60f7f1ef05c726d19e2edea775","nonce":"d505fc3904839c7a29fda4cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"678c0131bb00bd7bee09d3056691ea566a902a6c00ca5036d941de873fb996fb5767a3e6519f496e94c0063228","nonce":"d505fc3904839c7a29fda4ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"be87eafe90cd25eb7c879ce021aa0dbd86b370a5fb5eb46286e8a843759fc89e29b1796cb2ad993dabd99b43cb","nonce":"d505fc3904839c7a29fda4cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"a32cc80ac0260255ecbcb3fc1ede50fb040a364741d14d73b0909a5da4897e8d3046ba0b28205c846b435cdda9","nonce":"d505fc3904839c7a29fda4cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"b02ecd51f4cf42ad90baa777b83fc421a22059cb9c17d82f121a452c55b3cb9334f131abaeaeebe6e29588ecc9","nonce":"d505fc3904839c7a29fda4cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"12d8962087f8a75423fcf9f42c816e0fe5e49fb471cef00a927e6a39d1415b5a84bd49a013a066219c608a58ea","nonce":"d505fc3904839c7a29fda4ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"e3fa626bd48a7bff6072722716aca016a52da85d298f6c4acbc8d066717c37a01465a21e49e4da2adca91ba2e6","nonce":"d505fc3904839c7a29fda4c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"45663e2e6cacfa798b94e654a9043940e9ed8451f44028cbc06fe73950a1730f8c16754bb9802f60bf21aa7470","nonce":"d505fc3904839c7a29fda4c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"634aad0ea8a20e9e25c2020c51318d67c442c5a182edd68ca0b09f1f59dd7c3970b471fadfd47878f749f1ffb5","nonce":"d505fc3904839c7a29fda4c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"3ce6ae812a4749d3ed89c7bce42e6873d52fff1b676d5a2e1571b9962e4b321d4a4c819ba6b325e6404f33ec5f","nonce":"d505fc3904839c7a29fda4c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"621b694b7ec4034f1f5a5ed3c0de63f50168eb1ca8fbc2942e77ef00748163a97a5111c4fb1a3b5354e49a8a2f","nonce":"d505fc3904839c7a29fda4c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"e47820b7f6253fa759ef635aaf7556e3c288775563c5a9a151eea4a76b32f4228595f59e62c49d6c0562acb0aa","nonce":"d505fc3904839c7a29fda4c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"f076298a4319c52fadbe1252e46af0854f6e5010d1fd3b3e19aa4f08d316bae7622457bc4c38a2294937e84d98","nonce":"d505fc3904839c7a29fda4c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"b4ca3bef2a3f9a07737069f920309bd35eab69833c5bed2bd1dd997bca4687e120bee03080800d49d326673300","nonce":"d505fc3904839c7a29fda4c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"a8c534e9a9b3c921ea2d8c867b69cc29a9a0d5268e4f76d9bef2b97e5083b0ec05e7c3f3597c40baecb67d8c15","nonce":"d505fc3904839c7a29fda4c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"9286cd7dd562a5581368643f1cd66f687fffc2d20617488954c0fad16744b94e7fc4a99e9549892c592381a6df","nonce":"d505fc3904839c7a29fda4c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"8736e09335274b65a0011d99392a401f7da169a7107cc69f31e8cb2a7822ba471950728c2f298f55051b467b22","nonce":"d505fc3904839c7a29fda4df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"a5affd94dbbbc26a187e45390e958d345e7c9e4e574ad33dbd0e01bcb1e9c9ada3f5f86f9c4e2107a3f856b2c0","nonce":"d505fc3904839c7a29fda4de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"a8c6f8d8375d58fe6e290f36d004e282ee6d3e702b48ec7ac73aa67b705de8e675b0b7bfe895db3c5ae6c8b17f","nonce":"d505fc3904839c7a29fda4dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"bb84dee40b4de02e69a915e6d816fba0e5044251644c5288cd82cff5acf313f8306cb06f96ab57150b6a480895","nonce":"d505fc3904839c7a29fda4dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"dc1088688e77d16ba4bc275703c8f2ca0262ba3d7c233861ec3a96c1107f5e1efaf656928fdcf3b75683d10df2","nonce":"d505fc3904839c7a29fda4db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"09613ac6cec28098f754cb160569da20fa28ee3d47d2d752ce23e958e40a680cc0ed73d3ae20b2107983b1c6ed","nonce":"d505fc3904839c7a29fda4da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"4eef5ce85dd6d227e20b1189dbf2c68c3fdeb5e5c7f5d3367a48ec26ed47d47659aee2f8a5448c630a9ce2c8f4","nonce":"d505fc3904839c7a29fda4d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"ced9ab254d21282b1c25bdd8087776645a93f82f115187e73825640363020caa933eecac200f0d423c82f9b9f2","nonce":"d505fc3904839c7a29fda4d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"c3624d39d3ab9d102b9749ba1c28aa0dec26e279542cf677b22e260fe941cbb3a335d191e58a9298d07eb504c4","nonce":"d505fc3904839c7a29fda4d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"0306dde553abe41148b37e74c484f1beab5910001ea9e1e0c91ea9fb03c109420123445171364f0ed34d271537","nonce":"d505fc3904839c7a29fda4d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"fa7b8610f1b4812c2bd2abff964d82968b1d00874551be8a4ece0d4519e20dbf6a2931dda3ba119a1117160295","nonce":"d505fc3904839c7a29fda4d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"6bf8941c68d78568a3b2d7c20b308f9aa5576003f19c9adc168a022df7ad9180aa4a4c9f6b3102b37b0e161aa0","nonce":"d505fc3904839c7a29fda4d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"7131e68388eac4b2d8f4e8846ed8bcb13c121ee41bd4304f093ba925a01f38176267098f0d1d7b491d3128d5bc","nonce":"d505fc3904839c7a29fda4d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"453c26c2d7e504865794d4a0d8e5215b3f2de156bb217f8ec1fa92f12ec9de33dbf9f93744cf1640a16e1073e4","nonce":"d505fc3904839c7a29fda4d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"2b98e005c0517700ddd5d44c0705e0130aeb1ae59b20617e42b2dd638c624eb14ca82aaab3bb6594ea91ccd7ae","nonce":"d505fc3904839c7a29fda4d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"05bb73cf7358e6c72fe1f2182031bf18a025a7e4be47e91314abc88e058d9335400190f1203feb5a28a33a7d8f","nonce":"d505fc3904839c7a29fda4d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"85b0093679af1764216743095c61b86781f38383d61f8ae02dbdd395034de6662d4022b99da4c89bbdb6f21a98","nonce":"d505fc3904839c7a29fda4ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"38fbbe4fd4a7cef1c0f0e7b012b099a833985dcb7ab302b5d94aa88e0d62fccab59be7a634e8b63294cd20790b","nonce":"d505fc3904839c7a29fda4ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"a06cac8ded8e8e63f1d8805d788f35926f013131501b2d9daacbd40fcbd287f97940b2352d24c09f07aa83dfc0","nonce":"d505fc3904839c7a29fda4ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"6ca3e386b596cc5ac7db82a27b3328155afe5fdbccf69f16dd3b0588d751cdd8fd7a6b4f0fff8408a7acc23de1","nonce":"d505fc3904839c7a29fda4ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"fdcb69d0d5b6f209575d6f58e19086f9dc986df7653da943aeb1707b004da94aa1678ea2c0228ebd164da49acd","nonce":"d505fc3904839c7a29fda4eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"52c8f6d177e8a4cf715c0f16f1b7d0735a787cbeb8882e3bdc9df31b8c86e57662c264f589afc90c360c2cd19c","nonce":"d505fc3904839c7a29fda4ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"ae6c9bd2ee009f31078f027bb91f986402cdb83c4ebabf16157c09c7a4ff212bef0e5996a736be07108d59ced8","nonce":"d505fc3904839c7a29fda4e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"6a388cd6d4e043bf6495708b44936efc55760f44660fa10f49931ecc225b98bbab952dc3e21edac19a709756e2","nonce":"d505fc3904839c7a29fda4e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"1f85ff52a321f7d3c6dd058f4c244d219e0e7809b54b5f7b42977f6b6fe452dda4cf56e005dbabbae8b857ff5a","nonce":"d505fc3904839c7a29fda4e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"b732b6305d758a52eb441a5826cecbb756b89a3efa23fe7d4716ba241bd8645f5f2e5caa0706eb3f00cf3e4c15","nonce":"d505fc3904839c7a29fda4e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"c1a8dab1ac4ecc3974d5b0f52050f0fffce7c5c0c41b6e86c823265071a526b020690899eb81f28d79611b57d1","nonce":"d505fc3904839c7a29fda4e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"36b128ca3ac5aa9ac0b93a78a5fef3af61124a8dbeabfac35834c16b8e7b544778f42b126d2936b5fed8f8956a","nonce":"d505fc3904839c7a29fda4e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"12e651a61b629b8c633ad0ed4162c61679d2258c4c37fd64f338c6eefea01b6ff3e7b0a78e8c07b617e32251ee","nonce":"d505fc3904839c7a29fda4e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"1c65e9a24afcd58b91dc8a1d5e089570f1ec41a42aa3ca577353fe3028bfcbb33646eb9846d3af9cb29b9bc9b4","nonce":"d505fc3904839c7a29fda4e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"d1e36531e642a3f4953c46b1fdde6f369472b6b46cf6fbafc8997df5379ebd53541e080838639a5412612275a0","nonce":"d505fc3904839c7a29fda4e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"f4613516e898f19645babe7e3588a0388ab2ec7018096d62af29b0dbbad527b53359e5a2afaaf1b482018c8e81","nonce":"d505fc3904839c7a29fda4e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"d19abe90654e36102336694672ef1f4c6291b09e60c16945bf7159eefd2052d059ffab72b1b829a119589904ff","nonce":"d505fc3904839c7a29fda4ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"218837c8c7f055efcc5850576373a96920f8a9909aff3d8125c5c3cc64f29d60efa8e915ca9b67b897ee850db2","nonce":"d505fc3904839c7a29fda4fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"7101b5fd7d61ad99f4f430856add5519cd91daaa240b147854de8ebd58c92ca8eb5d6dc396a2eb6636e06431b8","nonce":"d505fc3904839c7a29fda4fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"e29dfc6e220a70ad17fc22c1ac9d7ca9a36414bcd7a63ac7f3fe7ea3b9e3231faf93c71e393ef4dd8eecb63d62","nonce":"d505fc3904839c7a29fda4fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"e6900bc2ef731aae9180092fcde1864df8df01fb667f61d210ed54991a8f83c67dc82aee7b816dd45533147688","nonce":"d505fc3904839c7a29fda4fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"35887a996aa24230eb99dfdd3cb15d49d05ccc6cdbe8f7bc81a3bc4416be9e16607dd5ceb0d4fea392bf28c43c","nonce":"d505fc3904839c7a29fda4fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"a8f5de6c614b806ebc8f6fde20ca4d6e6405ec38f4c4f27ae5f835d9a24cb3f6362c61d29650805524e8696163","nonce":"d505fc3904839c7a29fda4f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"84405accafeeaa2261cfa7f274690c28e0d6be39accf87a17957317b8f629460db3ce63c3fa1d6ef5bf8054efc","nonce":"d505fc3904839c7a29fda4f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"782b385e6a66dcc667e3aef09e42763da89c8b4f5632d67379e8dc1f721361574bcd6279bc99b8685da52234e4","nonce":"d505fc3904839c7a29fda4f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"02c26dafa9a3aa0e2519bf706656c27e95efc8a62f9c1ae670c7622eae2378b1d57251e6eac8d6536e02001c3c","nonce":"d505fc3904839c7a29fda4f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"e95b72dd86e1950126c7ba2186657beab1a66acc3d89529d9d526be5e3cf768076c633b055ca79f73444647ab8","nonce":"d505fc3904839c7a29fda4f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"58bcebaef6071a19fe75bfa88b31ea45b2e5c9180a5a571bbaa7c50252efa66b62365ef11c5157eb47470c0c6d","nonce":"d505fc3904839c7a29fda4f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"1062eec2a55db95799628ac84ba45c6745966c183ee12b55d6ec09bfae786c085430a1941998d07add430a05b5","nonce":"d505fc3904839c7a29fda4f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"51b9cec309e4864f1186d8f922a9d03ab0b07465d425568c7c8791d1c820ebef6d3e3671975a0dd431e636f767","nonce":"d505fc3904839c7a29fda4f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"5334a6753fb752f3c3fa23a491692f834a24b754ae696901189828bf4e3dd6b51bc7a26a204d9114144771dbca","nonce":"d505fc3904839c7a29fda4f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"1ecc457d37dedd955cf8df82d644493638683266c2fe140006dc4c91f3e48cfa02e0a181d9bb22213210046f7a","nonce":"d505fc3904839c7a29fda4f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"c3b8c63cdcda27ebfa2ed1430be49d0d32f08880e0e1d8f354843831bfd5f70626331bdbf878f861e43342a744","nonce":"d505fc3904839c7a29fda48f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"1438f84aaa01ff5a4c48425928d36ecdbdf5d1506ade7c6029771ea9479112bc6b77afd5b53fa0bc7d7287b613","nonce":"d505fc3904839c7a29fda48e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"8723133a427ffa416ff37e2b11386382a90a2b2bf1456cb303c03149e514f7934f176e26fa9db39820986c45ed","nonce":"d505fc3904839c7a29fda48d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"fb5963cf28a6fcc17bf65d361778ac90c7c42190ff1c580004757b6ddc089e5c1ef66fe41d7185058e0b8665c0","nonce":"d505fc3904839c7a29fda48c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"a0d8de75771b84a33962c1919edf8268ad6d7090fd0cfcf2a78d7c59e1231bcc3dab278c5a6099ff25fdd4f172","nonce":"d505fc3904839c7a29fda48b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"3cd1dcd1d2d15f9ff9ee3baedd416754d243deccf63d1a3c04fb8362ee59576e6f21f4068ac7c99448cd854398","nonce":"d505fc3904839c7a29fda48a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"be4e43729e6b029d6ff41702fbb2875f9eb4ca71088595fc3b40b522ff8c1b4e81c28806bfd378a4f277194c0a","nonce":"d505fc3904839c7a29fda489","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"150f5554098ff21d6df59bb1bb1c906713cd2446b19dca1fe57f3c707e78fe4201847ef94c01c411d338279f2c","nonce":"d505fc3904839c7a29fda488","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"1287be23690e827bea415992d10329e376067a2800b2b74e7e0cebae6b3f3330b530cc31b7f95e77997112ceb1","nonce":"d505fc3904839c7a29fda487","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"3a64c3caed2bf0fa1677d03d6671cf92ace5ec7f52ee4fc4a6b6fa219d28249960cadb70a50396e9d744160a37","nonce":"d505fc3904839c7a29fda486","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"d325eed5585fa019c0d86181364822006048dd1bd2bf859ca5d4b0e4d715581ddfbbd1175c8ac9d28aba83c07a","nonce":"d505fc3904839c7a29fda485","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"b9263bc42579911d9e28837e74025a9aa4e97a7a910c2ea6070b06494e93f343210642ab0b990995d44e32e5a9","nonce":"d505fc3904839c7a29fda484","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"84850a718dc1bdc3df2f37d3cb25aa2b55813d46ef74ac05ffdfdc5cbf57fe0820fde6fcf48cffaa8a4deabee1","nonce":"d505fc3904839c7a29fda483","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"1232ca3420dfcdc451d1c764d502467999ab6d14a2bb8bbf17d1df8e225cb90d7303d4cb3abf66622f83c334c5","nonce":"d505fc3904839c7a29fda482","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"5f81f36d132219eef4435cce8d5e4c1dae8f7e3e65fbcc49ddfd63b50f27e4abbaa54f606e15784ee4a5b73484","nonce":"d505fc3904839c7a29fda481","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"b0727e8f19b45aa9d7500fde37df1ac48e49f73bef9294d45b1c53e5883420a474292c1f8663897df85fbc3c7b","nonce":"d505fc3904839c7a29fda480","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"066366a98522e7f3e7e74d9a512bfcc7d2e1a4e62841f49c964c65d3c42586173e88417bc98971bfee5ac924ee","nonce":"d505fc3904839c7a29fda49f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"18cfc5e95a12a713088eaf5f38583a457ed0913e0ea215af3a17fd0cede94a3f36145db8319300fa2100240630","nonce":"d505fc3904839c7a29fda49e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"65c03fdcfe7cc33a97ceff1da98ce4275b1795828cf64c4c881c821b0f89fb2bd525c2e230f7d4ac30739828e9","nonce":"d505fc3904839c7a29fda49d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"1ef7152b0a8e99ddd255a883395919e47061cf333807682b104edeb6ceee421c4a4c0033045c63c7312ece1be9","nonce":"d505fc3904839c7a29fda49c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"f900fb95953f259931c566006b03455d8c0afaf8e191675531dabd784f9333e4c4fef42fe9c64127fe7378aaa9","nonce":"d505fc3904839c7a29fda49b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"5c6c119b618bac7f212345f6b2e5bdb092e2dc367f49bffccbe9ea536d39052f397b7595a0871258636a3b67bd","nonce":"d505fc3904839c7a29fda49a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"b77e7c3d194dd3bfa986d7848ec6d7d5927818e035c4077cb17aad35f8a6709848910bb3bf613e379e49c79832","nonce":"d505fc3904839c7a29fda499","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"fc672e4792a8ad0911bca8925094d8f539fc78d51ca74dc3ddbc348faa7a01be2cc78157cb0f9d58baed1eea31","nonce":"d505fc3904839c7a29fda498","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"07bdf8c14400ccb5e571af30ede45d45aabcfffddc12bb8822becfc484f8b9480df780eb0d8234a3fed94ccf2d","nonce":"d505fc3904839c7a29fda497","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"67d5fb2b160cc6289733a089466a4570a619f7df849f85bc1282a98c16f11bf77eeb5aeb98b5aaf6c9849f2867","nonce":"d505fc3904839c7a29fda496","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"c2e6ff483d57f9f6fd150d787f8ac0127b990a5ab65635dcdf90c2df8e52199b425cd48585d8777537ee5f8346","nonce":"d505fc3904839c7a29fda495","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"cab90092e1eccc03d664af211b6d27521a5d1fefd6b2950ad6f51e97a6117a49831dd9b8ae09a520c21a77ce5f","nonce":"d505fc3904839c7a29fda494","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"3ceb5ab3a22ed5f5be019a5248dea77bac93af37c2e2674c33a664c61686bd6491bbd504f3a0834af948801618","nonce":"d505fc3904839c7a29fda493","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"40b24e4969477fc29aa34fc1080a81e0e478bec4f96ae6f601c3b0319caa6e9b79239ec3570f7d64d50efe3f3a","nonce":"d505fc3904839c7a29fda492","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"5c97f8ec8043fe257c680030873a4bdc7ae7402c674f3b682d4d779dc95e22abb653578ce6cb823b27e0c4ab57","nonce":"d505fc3904839c7a29fda491","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"02faccadb9257ca8252feab600f36c687e5e7d79c02bafdbd59548155fc55a64622565657bb83877a94c8d0121","nonce":"d505fc3904839c7a29fda490","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"968d0754ec598f6931a8e8879af9c5d7d2ed92a8efc4eabc2598d90e33e9964d6a3ea6fcd50d038332ad9a0d55","nonce":"d505fc3904839c7a29fda4af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"dbdb91a28be47728eac2ae17ae87c78bc202c6cbfc3baa69a23c7180ac103f15b9707f217935935a902fbc1603","nonce":"d505fc3904839c7a29fda4ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"fdad05ce338c9888be919d8f541ef762d2ed2a010d6cc9de684ae0ef1828f0687b47f331437bf729fc1e1efcf9","nonce":"d505fc3904839c7a29fda4ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"6ec9c4686e49a11ebcc5fb1a77c9359ebee8309e946c85dbf25d7983c526713c042a9f9698f07eec12fd6df3c8","nonce":"d505fc3904839c7a29fda4ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"6261c1efa7524eb51ba6ba211b9a3e0595d493ef313c41f9113e9e0bd00b8393807b908922c7a51dc6075f750e","nonce":"d505fc3904839c7a29fda4ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"96f25cfa3e5db8cd0b6f112bdb1d4054b2719f3e37c0a058a15b7e196d57ca0464af4db79931e50a0941e33551","nonce":"d505fc3904839c7a29fda4aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"7729c35d4cc14000dfc3cec4a5d74515389e4adadfe2bc4e0a12ffa629f79b613ce787ce44bb3f7473d4f93ce5","nonce":"d505fc3904839c7a29fda4a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"0dba5d3c5a9954b78e3991c99c2493bb5956d76aabccc2734945dab007935b41365a7991a42103aaaf79023e78","nonce":"d505fc3904839c7a29fda4a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"ba9a9b66737f3322a58c731cc4550947d4ec72cca1e96505e0ebe2b5a32d39297a58dee763a6c0b47534c85377","nonce":"d505fc3904839c7a29fda4a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"2ba0e3698b433fca6940e8c77e3b940001b8fcc69272a9f559a15bdcff873952c6de0225f6db7002e1438e408e","nonce":"d505fc3904839c7a29fda4a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"c8cf1539e6e4b757377f7ae1daff52346a600f0a2ed0c360bd9a60474f5735bc1f89acb3575fb483e2b1e90529","nonce":"d505fc3904839c7a29fda4a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"c3ce22ac3c39fd488d61a7eaae0d01932383a7bac440535e70f33015df3ecf5e26bc2364158ad737a8afad99d0","nonce":"d505fc3904839c7a29fda4a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"e41a04a3d001ac6c1040f52f5102ac1196556cce5d92fce74d27e5c446882c9cbc1cb60e899edf61caf9f03df5","nonce":"d505fc3904839c7a29fda4a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"2db4489094af3792ae9d3b977679b34734bda031c3a75a8cbe00e4cf39c0ef30cb7df0dbc76cbe0b0fe53880f9","nonce":"d505fc3904839c7a29fda4a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"b10b5a1f0231c1b2af3656d8b4f5fc0bae336d02febf3a3c5ea724c530ab3af1dca978cd6ee2e30da122dc53a1","nonce":"d505fc3904839c7a29fda4a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"31234f0048fcef109f11687619b6a0b85d13a883e067f9500438e46edf9dbefea59bbba1a000f2c26057d36d61","nonce":"d505fc3904839c7a29fda4a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"524b8e96fdb6d5956f3676667ed70433d47714f935de53d01b174893591ae2ec237e670a230f921abbb6d97b4a","nonce":"d505fc3904839c7a29fda4bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"6b92e0bf25b76e35b4a6e8db75b0fb5b18828e7c2d8234d42486729b88b34073b5d1efd3267c81a77cb6fc42f6","nonce":"d505fc3904839c7a29fda4be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"0c7dfa65da2929152b3ad63d6e8894a7dc3b963e8c1368c3595df81ded12f83a2ed2950bf28b2e273f8bd24ede","nonce":"d505fc3904839c7a29fda4bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"0a1c2d5388aebd0c099dcf36bc1e72dca3939df295e7933f992e36e3b31ef1993fa6b6041dc8972f44192497ac","nonce":"d505fc3904839c7a29fda4bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"01aa3503aab5246c1f122ae9563203fee8e85162cd5cefb645c0dfea050579bc9e2a51e41f82111c0f8b118388","nonce":"d505fc3904839c7a29fda4bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"dc38f7dfa4a85952b3f8016c98867e8954e5a54af26b2818fb43d0db055d82b3479cd3643ccd4d373a380c106b","nonce":"d505fc3904839c7a29fda4ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"98dd64cad80405d4cf4fac23e7f3328d181e1cc06b7f40c58eeed9e7f2de6447674bb91b5ead03bee0580c596a","nonce":"d505fc3904839c7a29fda4b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"fc1eab13dd2b2f43410f03b7cfe79a3ce059e84985cf39c505a36ff23b5f14dd5abf6fbb3a3567fba1177d403a","nonce":"d505fc3904839c7a29fda4b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"5e58075389a8f4e5b3311df1c17070204f2c408ec9652bd0798668e92c14b3a4822f2be7cb67117ce6101d5a1d","nonce":"d505fc3904839c7a29fda4b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"b5c1077d1deb187cbe5be12f5b0f88012bf496ff291526d8e094790fb8f14f50febe4b3d5c57c69e09e6e6ab24","nonce":"d505fc3904839c7a29fda4b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"35bde92880c51a3704251b770bc6e09e4e3f1eba4a277f9c4556e2fc6a89196f2f2626c786325877e4592718bd","nonce":"d505fc3904839c7a29fda4b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"316d80de282420fc2ab002ac2166df13da06b5d0495b620f1db4a16046d6b463ddf229e876b710cd42e8c8a73c","nonce":"d505fc3904839c7a29fda4b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"5d37b5c5c1d9baa30a0b9296b79c3161c230f83fd81dfb5d1a88e2cac5037a54ba975c628de3165a1ab138229e","nonce":"d505fc3904839c7a29fda4b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"e8e294debf803043e6024e2a66aebc27774bbb136592848cc9b87070a1867dddcde5050737074594d494e57697","nonce":"d505fc3904839c7a29fda4b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"fa2abd4f41e6675d9b8c6e524f074cb6c5e0b2f8b4427cfc6618c4316cdd27566e1a9a5ec01cf9dfeb6bc17916","nonce":"d505fc3904839c7a29fda4b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"89cf89e9128eb489bea20a793f0b0ccd437c62fd3ae39ee08ff2ae45afdbe9b28694ba964448edef3c4bede71c","nonce":"d505fc3904839c7a29fda4b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"ae14b4643bbf6d99b1ee297cd8f334160cea442519dfc0f2794665009cd1c4ea72bbcb07776fd8ae254dc55223","nonce":"d505fc3904839c7a29fda44f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"eecaded4fe972ad5dfbb7fa1afaa932e63e43e00bc7556efc6dbdee34ff16b92c58579e8ccc1ed218c911a34a4","nonce":"d505fc3904839c7a29fda44e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"6b9a63a6698562ae4ab8be8f804e9a335b51a9e3bc5d1b6e8eeab455d975c7f8c055c15157dd5ef4388a257146","nonce":"d505fc3904839c7a29fda44d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"4245eae206b56a5311f829bd78c80c6b060ae4a2d408f550c443df1277d8c25e0ca3f99e64f5412a717288a081","nonce":"d505fc3904839c7a29fda44c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"4e4497185a59f73967321af2c5445978592c360be1560c07ef898994e805932d019722d94c92bb68f9021cc8e9","nonce":"d505fc3904839c7a29fda44b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"8400ecfe5ef84e9f2f619aaa892985a8fda3dc397d18a8058d61c13d2645dcdee2e14fc7d20739f0915e90b1ad","nonce":"d505fc3904839c7a29fda44a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"af4abc76cc10136536ed7f5074d81efdfac3ddbb6ceaedd323a3a8a649696612f01769415d43260a944c1dee72","nonce":"d505fc3904839c7a29fda449","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"2af64ef01affaaddae861183c12b90dec9046e3fed382e5d413def73ef88ff18be9d3879d554e1f4dd2882cce5","nonce":"d505fc3904839c7a29fda448","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"679fdec972f54ad7ec340587b2542ed5488dccd663c7f70a99208ee41fbe03b0e35bc045d2d21a89bfe9f09c42","nonce":"d505fc3904839c7a29fda447","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"2d6af004de014977f2b79fccc97e1061b80545b4a839324f2872443963ae107792f9c5dfd6aa6629821da50562","nonce":"d505fc3904839c7a29fda446","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"cec246f04df0c9fa415542fbe5b534b1a6e2f9dbe45996eb5a7476f5777bb906daedab771954dc4846f77e8317","nonce":"d505fc3904839c7a29fda445","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"b713dfc2e10f9e435915ac10bd24c4b613614f94eeaac47bc0ff217691515ff63196795ca1707f837b6fb25701","nonce":"d505fc3904839c7a29fda444","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"13cf90c0dfe0118b92a626ff7df6b5e58fef29f4d55e4d8bbd6d0c2d2b3cac26bca423e977a6fb6e1f69028ab6","nonce":"d505fc3904839c7a29fda443","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"e5d7aff879a6d0a8ce9f3c5a4582b68081b146fda1ab3fcae043ae289b3cc044e046e3763ff00d475a84076135","nonce":"d505fc3904839c7a29fda442","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"140ba3e8d24979cf287a5683cccc18dc25930b45acfdc152a9eb0f6f049d25ef9f672de4fec9017ce1342dfa29","nonce":"d505fc3904839c7a29fda441","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"ebf6531b2e87eb74d3b62e5bcec539300a7e94b650a922ec87710401cd03a81d875b5819faae9cdcc216875c5d","nonce":"d505fc3904839c7a29fda440","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"697cacc8d74a27d559fb08005c31e5a942a0361c433cf9bcf472008c1773324e0b766fc60aa209d5e7d51e7757","nonce":"d505fc3904839c7a29fda45f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"d24fb1addfa57ea77bea22d3e3bbe81ad41ad6d6bb370959baad80b83b91eb971565d8420458d8f3306161758e","nonce":"d505fc3904839c7a29fda45e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"938e338e686a8e97ab83e61586db4f84450c331f3f378b99a42fc138aea0982dbe41435428f4aafa21c3535719","nonce":"d505fc3904839c7a29fda45d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"6643953112ebb94988a5a880b3ca113bd54334507bd1f87fc099239e644eed1ade4600a692ebc0f45a904fe804","nonce":"d505fc3904839c7a29fda45c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"e5cecda24680f769d478c090c24e47597e5ec4c01f52e9b925edd97e3593fe522e7616940815d91175ffacfa38","nonce":"d505fc3904839c7a29fda45b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"a6efaa6a10a15dc65234d52178bb24b8d18517c959418740f18de7f5d92450bf3d11082e7d698f5ff812c370f8","nonce":"d505fc3904839c7a29fda45a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"e9f04305ce7a8372c632cc40c5a4b191c7318a4a9e5eb2009ae21ecfcaec6e07cef42503004506aab0da97e618","nonce":"d505fc3904839c7a29fda459","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"7ade3e7f5ca853e6ae668f29d246f784f252858da1ebfc36671ef7ba57918a1b4517784708027e9ad55752b132","nonce":"d505fc3904839c7a29fda458","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"278bbefdabec3b3126f28ae18a64177807e6bfde49c8fa2256144a950973cccea9c05d82a62afa18f2c5c3c6d7","nonce":"d505fc3904839c7a29fda457","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"3e41615c99ae11f7829c530b7d63407458c03cbc9a929bc2a1ce7c1d4fc2a2c03ccf2c9dc3af34b9d648faa63f","nonce":"d505fc3904839c7a29fda456","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"be1c986d8dc71db6f1ed43b93bb883d56a80d892a824c9e42ee49b89d13ac75ce3ac6f7fd54d4dcf52f640eb59","nonce":"d505fc3904839c7a29fda455","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"6fe7f117c7ab564d84593de7d93204f18257a07a94a450b0715c4e822db24436c5422d7c8aa96f01785b2000ea","nonce":"d505fc3904839c7a29fda454","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"47ca629ad8e5f151d0a90706e8be87002d8b43a1bd7dfa6f97cf54110ca02844e840d333ad04eb0afb12552453","nonce":"d505fc3904839c7a29fda453","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"2c4c1a3eca3ef4277ac6e39efc0307a39fbd846063808e7463ed1e83498271bf49eea33923340d332d16748e47","nonce":"d505fc3904839c7a29fda452","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"f82881df099e26da9b0adc05e0d909b11a4cb3dbd1fe0fd389b5aaf7faf38ad32330523c069acd6bc1856e3244","nonce":"d505fc3904839c7a29fda451","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"b60dca7bee4954549cec7b128112946684fecedfb8a895e5b0bfee145311a112d46684b3e6bd40302c860fa92f","nonce":"d505fc3904839c7a29fda450","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"72fbbb41bea05b104c6dd50d377bbc8739dba6d8bec3e9e887450e585306a258cf82c57d071b3c7b9e99a3e1a2","nonce":"d505fc3904839c7a29fda46f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"88b8913aff244e309b95853e1f7c575dd949ddd4705557fbb9814b733cce3fadbce035620c03087376e4019220","nonce":"d505fc3904839c7a29fda46e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"869d25c860847a0cb0e2a86ba64c1997d98555e1eec3aacdb64d0d9b1dbefe9f77fdef56c0a1c971110b978dca","nonce":"d505fc3904839c7a29fda46d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"cf1da866986c9d444e5b0a6a2e3f13fe4d06f010932eb9581268eda5797fa5b238342404f02733dde6b6f1db84","nonce":"d505fc3904839c7a29fda46c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"83a1630399839efa46d26468bf87f9b51fc1634ad7870ea67946eec6e04106d32bfa24241629be2eba8684d05a","nonce":"d505fc3904839c7a29fda46b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"17096ebe3b26569dc2fc309d83ce694aa851aa3d8fc8245a7850c9829c0371613aa6cbcc6fb639df0b2f9a5e8d","nonce":"d505fc3904839c7a29fda46a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"99b55dadf0e60fe793098fe6af418b392958a27a5ca2f156ffd2651f1fe53d53dfff9bbac16a0468b87dd86533","nonce":"d505fc3904839c7a29fda469","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"795f7ba2ccbc03dc655dda3f56e6a1f20733c257b717a5c56962ef1c7a15f32691816da1354ba188a305526295","nonce":"d505fc3904839c7a29fda468","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"e1822718058204619ddb31c7ba2fd73219c90f2a50f7b8a08c1b66a093ce0dce4fd8c39a0237284e16cee8218a","nonce":"d505fc3904839c7a29fda467","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"671ae4dd531525558cf5a0ab86a98b528e572810d6b33d18224f959609664876fefce22530edc7cb95228ebd19","nonce":"d505fc3904839c7a29fda466","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"c6b85851e5ac88d1cd9f4a927e8cb22083855154d154167392845b88dd075522d30d1a4c97084377f57ca214aa","nonce":"d505fc3904839c7a29fda465","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"b327f72e31bb79f7cc5ff037008344c8e22228bf3a2fad8752cef7982f1badd39196406ee3878f4118042ecb05","nonce":"d505fc3904839c7a29fda464","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"94e7f46e68cfc999d080595fa6b49e0abb1bdb1637aab04984156d5bf707f79399991aa6a006eb9fc0a70b70af","nonce":"d505fc3904839c7a29fda463","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"96d8bfa6038721830f469323c5b9c709fbbfe6e28e65ec86dda1d4eb3c13f6909960be091d85e10e0d8f177e48","nonce":"d505fc3904839c7a29fda462","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"b2d40804775eb0840764d14d13d30787d88962c802b77756120dbfa59481be88b86b3fefb1726dafa47d2304e6","nonce":"d505fc3904839c7a29fda461","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"c129ec34be7c66ef64bb1c62ed05d2cc64ed55fcb980b87ad9d6c939462a52981fdcfa596e2543b1526e2531c9","nonce":"d505fc3904839c7a29fda460","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"082057b7df6c8da2afa9d027d39704f12fd7124e13d0b554405dfbc0ec0e74d2b769ecf3788295587cd961ebb7","nonce":"d505fc3904839c7a29fda47f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"c4aa794e140e02a51e918b430db41b68c9f461eb7326a0981d1c09b118d9b6804db49832320d7d47c305ec9d34","nonce":"d505fc3904839c7a29fda47e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"11c14088c23d0e96bb8d82796b98aa9700355ced7e8bfd7cf78c9a98d2bf6652d2544c48afab8793e63d3ad6c7","nonce":"d505fc3904839c7a29fda47d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"a8d89d408d8006361b4183bd476bd131ad588559b55818337b093f349869ecec55e60a94006f9e8d0efb92a6dd","nonce":"d505fc3904839c7a29fda47c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"2234cc5acf7279d8ddb6e0a25c22faad06b2f9b5f96ec6ca538bf41132c3153d7b52ab863bd4ff73a1fed3c8fb","nonce":"d505fc3904839c7a29fda47b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"89e6c7653c7999543187c68887065591df4b1b6d9c1b908de606fb11ac69985aa19d44d05d5215d033580bc7cd","nonce":"d505fc3904839c7a29fda47a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"cd6ae53c0818655578fb8aa24aa5956cd0ae5ceb4468ce5f998f6d550645f9d3f4d65ecceef3930c7087c4aacf","nonce":"d505fc3904839c7a29fda479","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"aeeb62b61bd1c509ce80a73b4093209096fbcc9be967160f17172d0a0c3c69d4547c3e3c7fb981cf15abb57f5b","nonce":"d505fc3904839c7a29fda478","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"fa57f2018be96365de8cd0bde5bb466f1ecdf6184fa91c1a15d5c72b0fe2c9b7554b87efbd3b1a3a820a78b9f7","nonce":"d505fc3904839c7a29fda477","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"f0dbc6d581e7937915b3194ff8fb405e67c97394da90b8ae09fa253411e1ecd5b9cab4e489263b51ad0d9a3346","nonce":"d505fc3904839c7a29fda476","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"dfd8421e3c769aa0ef7fd21c71511a27965a796733724584cc10df98cc9a92e86d3722393176006fc4f66c5ac6","nonce":"d505fc3904839c7a29fda475","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"a7c1e7230a84896ec467f263e1837f6d3b4cd7353fd7be160ef97ef5ce0f0988fdfde470890a659da0f2bc5eef","nonce":"d505fc3904839c7a29fda474","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"a1eeca635af6ecac15b7f5913e46846b2a2b1b9135140297dba4f4fec7b5879acd8c46af7d6cc958a9144bf775","nonce":"d505fc3904839c7a29fda473","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"e624255b7ef0228981c8efc3c61d03f4121e502a053601cf28d520d837f584da2833ab328e020b6ac7a54c362e","nonce":"d505fc3904839c7a29fda472","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"68f448699d5f574bc67aae2e7d6c89fd8972229161d08d1d21b5d3f9d49d4a322e8a2d10c0113bdb9d4c45c833","nonce":"d505fc3904839c7a29fda471","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"fa2d1df6e39141639578d3b4f63ac57ef4867f50466c2d413b79d9d9cb96f97d877122c2eb863cd5ba62d73056","nonce":"d505fc3904839c7a29fda470","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"b37647eca7dca93cdde50d516e4c0c3594ee64787e0e20bc15ba5031428a7768d41744b9122a0372f53d994d01","nonce":"d505fc3904839c7a29fda40f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"5489f5c0166d971cd3791153fd6f7d065ea03892294b48207aeb16e3158198dc9a69999bb83ffa9f7bec4609f5","nonce":"d505fc3904839c7a29fda40e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"e9771d17f12c7197f240171eaa139cc15d627e5ea5501f7fc5005ec8aeadebbc4d1dbeeba277aa32fa0241e169","nonce":"d505fc3904839c7a29fda40d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"3a76f0267f6c04c5aeecaf83590ed430013bd72f5e1d46c3e371acb5b612ca0c07c2a5a026cbd55704a851ea7d","nonce":"d505fc3904839c7a29fda40c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"998f382339066967e6c76c09c1b97241ec2ba7ef744646e32f4af6ba2591fcec381c89115b905d6e7c80bfcf56","nonce":"d505fc3904839c7a29fda40b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"b992d060d6759806eb8f9145f650f896e4224ca48efbf63f06cc1386eaf136b640666c12c66ed240f02ac3c70c","nonce":"d505fc3904839c7a29fda40a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"a729d9800c43ab51ba3e0b6d3443fab5112c0e9868a6c5ac24945a93be58ec24b6fd050ebee7e436a442b6bed0","nonce":"d505fc3904839c7a29fda409","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"8d9bc9b6a489bd41a12db7aa35264fb56615f2b047f32d09ad294943d77ac127f475b66ebaee06c413cd528119","nonce":"d505fc3904839c7a29fda408","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"5acd1c667fb1d293fda25d101d990d15ef80f7ad0e357badf60e011d65cdc0b9023ec0b375028d25d8a60c220a","nonce":"d505fc3904839c7a29fda407","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"d1af35fe9f61a0b3cda8854a5b148881587142f953d4b66d9d3dde2e2f6606d8e2d691259f44a92066b8bb37bd","nonce":"d505fc3904839c7a29fda406","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"2588ac45f4de13eafc096c624193b77baf5ddce46fcad9909c23a1df7eede21ef8b90cdbc9a31c140cb0e83b2a","nonce":"d505fc3904839c7a29fda405","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"e5b4d9821b4625d427094a7d40757c338250ccc68a24d77baf91a297b9a7459ba4f0eea17632a27999f1d91ff1","nonce":"d505fc3904839c7a29fda404","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"9c9fc15ff140ef5eb0c6e69f8d3ac244cbd9febe0a3a480ad54caf44ba03535bcc6fc36827e9f7636e611f27da","nonce":"d505fc3904839c7a29fda403","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"288b7fec96e8f2519ea63e2bf5bc01b21e64842b519e035567e32792fd31d802777ab9322db50411589636302d","nonce":"d505fc3904839c7a29fda402","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"e481b2e638001e0ed2bfa335e4807436af1d4f493ebca02e3af5e75fc25e2c0aa38e97323410d804a3ae7685ff","nonce":"d505fc3904839c7a29fda401","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"acbc54fbc9c855af61889caccc5373c1adc66140c2e01ab39c0114d1a646fe6b79849b4ebe16e9a90c1dd47d77","nonce":"d505fc3904839c7a29fda400","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"215c16d0d65e65ead79e27bce27339936cd0ed0270da96cd95410961a44c62a2de87a21814efc22a1ff81ae690","nonce":"d505fc3904839c7a29fda41f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"9afdf9fd8e638e0ef41b14bd2e09d0729a95e4827481afc5290d12351b0b3afe29663d7b753ea2d09324ea948f","nonce":"d505fc3904839c7a29fda41e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"5a3615237c3680dfd12f238ee95727735e485f0fc848e890f4aec09c03cc157bb1d2b27b2be2161780391c837a","nonce":"d505fc3904839c7a29fda41d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"b8c1ec596f3c88151cea86ed97ba5eb162a083be99b15b53c11aa699bbffdc10e247d7bf5312e0a739ee7e1573","nonce":"d505fc3904839c7a29fda41c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"685f5e405baf698b0e8974ff962f79e07b71cb10451238660a9283ce3bb6bfefa8c3e120c20685f65571236783","nonce":"d505fc3904839c7a29fda41b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"be245437e1f427f6d849dea084904d8b765226344268872e70bf61150dc004d24a3ad55d4235ef1bd167dd5034","nonce":"d505fc3904839c7a29fda41a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"84242773975f800adab733ac3d7687fde4fd76033401f5e60f9cd37103889991cc600718eb13c3fb4e50b31ce5","nonce":"d505fc3904839c7a29fda419","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"0d30d525c0ac7da8a0c334d8fde687185dfca4fe0561f7e1e3fc85a42139e0863a38c71406ed02461aa76b9f63","nonce":"d505fc3904839c7a29fda418","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"0adf2a82638a1ea6d5bfc717f05bec2662929acc7ad5b392609d1c8c0e180179cc87008b5b459855c718c6ce19","nonce":"d505fc3904839c7a29fda417","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"ca99185e239b9850f980967caf9f557d7842ae62cd3ad04c645cab2e5fb10b4e4739f95411de2434359491c97e","nonce":"d505fc3904839c7a29fda416","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"a722aa2a29db3fc61a7ee32262178a0c4524c29682dfe7bad627147f747fa9008a9d20ec89b5428954f2fee8c0","nonce":"d505fc3904839c7a29fda415","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"4a553921bd86c2c76546161353b7aac097bbb23cda27fbfdb3277c872608447fd63975fb400e3f6bba14b3fe7f","nonce":"d505fc3904839c7a29fda414","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"d7f76c342fb1c7904c8a42391aed178dd2864ff534bd4b2f23d30aa25ca90e7932953c012bf06f6b3d2acc6d64","nonce":"d505fc3904839c7a29fda413","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"59c6773f88b4347805d91bcbbfac66bf6d0eeb868665c130b79b25bc670f7e289431bb2ad3899521fd623ececd","nonce":"d505fc3904839c7a29fda412","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"47cfd0fe26660f48c257c6f5b1a00abab94a57a8d11da695ba9fca26c2fb1a951bb19abd67e24b3a5d9cdacada","nonce":"d505fc3904839c7a29fda411","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"549205a575fd7f5c12a2e00b20d21c745634004e23a5ab2e00d10c458e65da31f727315d86addccf86271665da","nonce":"d505fc3904839c7a29fda410","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"b1f8e8beda384189c88ed5ad466493cf770002f52fa1c1e261c612831ea3d721e790fb97982f1bdd3f68abf086","nonce":"d505fc3904839c7a29fda42f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"73143b3bb09b44ca7baf3ea979de26556a0e15611568c4da96c99792e6e1003014c19eeb8218244e4788b52ab3","nonce":"d505fc3904839c7a29fda42e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"5df30be9767803fce1b6b180a4335bd53e6372618f406755104fb2505339bb53d1851d6f29de50460bb1dae499","nonce":"d505fc3904839c7a29fda42d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"0e6ef827ea4f4b3fdf4da12d6fe4f66c32350893d2f24902f8f900c82a707cff7a9f49ad1653feb20cea9148fd","nonce":"d505fc3904839c7a29fda42c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"a44de95ed91e71182fe7ffb09da515e55a66df4e541932199dbc40bc3d6640cbb9f1954cfee77cb0df395e5d56","nonce":"d505fc3904839c7a29fda42b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"a4c834c8516b0b8edf5a1dc5170c3bacabc788dfe1e5724de7ab6e8f02e4213abe73affc1d55619a4d4a421d90","nonce":"d505fc3904839c7a29fda42a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"a700af7613e9c86d7cdd0a356bb454f21a331d14bec756c370d6e87f0945fb6b1ce7b0fa30a78cb1f7e6b94626","nonce":"d505fc3904839c7a29fda429","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"4d42371bac9bb8f52e33387dc6c6af9f0a8a2fc7ba638299fc935f7f8780f67001982b8b80f60b7ae109e2e19a","nonce":"d505fc3904839c7a29fda428","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"2de40bfd25a6bf0ef421089395ab039c2bae49b192e96b5200ddd55368b4eb5d59789a06dc858e31d3409b424d","nonce":"d505fc3904839c7a29fda427","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"2d791a2b2bb5ad54f4859287595f5004c78b7a6ecb14787a834122893d200f01620dd159a3e443277732b1cd39","nonce":"d505fc3904839c7a29fda426","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"85ac212bdd7ba58c3767a6c85f3fabdb73693049eb9edbefb9f5ae254d5771902e424f01b9246c0fb34b0f2619","nonce":"d505fc3904839c7a29fda425","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"b935d01e18e3a3f9d3998ddc2cf6e9fae4c23182ecc736e7eb43bf1b6f77623e0caa2d1d0911986600391fd297","nonce":"d505fc3904839c7a29fda424","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"91ad5fd73425e1c5b9d20da29dfa33de30f593313635a1ef66fac1dd0bc15e8b751faa4e141979ffa937616e93","nonce":"d505fc3904839c7a29fda423","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"2de9c934a8bd0af9a851d2471830829b8da0862b1ed24cad56a54500313209303f05b9f8c00ecfc7705422c37d","nonce":"d505fc3904839c7a29fda422","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"64c1e831d3c534720e795e18f62e1b874fa3d721308ea7089c8d0cdfd6fecc7a4205c44ffe0f4d934b4334f1b7","nonce":"d505fc3904839c7a29fda421","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"c53f144831caaa7097e7e7d1351a19760cd4afeee8573de979f8ac19396e63e0b695a76dd9b0b5c8982054281b","nonce":"d505fc3904839c7a29fda420","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"e7789663b6951702c03134ce7da427d5c70231be156bf9c483a3b72facb2d026a894cd82148eb6c660809bff61","nonce":"d505fc3904839c7a29fda43f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"5906e99390c0f4be4c2fff92306106f1031c59ed22f7e770ef788a3975b659b15c4f0a7a4cede44ee17a2689a5","nonce":"d505fc3904839c7a29fda43e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"91caf3c2d77c0595ea1959e44f54e6a14c697d0e3d9aef70e948a6c6e01d4e3562d2a99dfa7b10a257a56a8f56","nonce":"d505fc3904839c7a29fda43d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"e3df679ac82f155b635894ec69a7c3e19874249b695cd3f604bb0751624eaa3924bef18f30927414e0b774824e","nonce":"d505fc3904839c7a29fda43c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"2d0bf21579c17e38d4c9fb340e1c8b9432e72813c4e198e26fe7aec42df48dfd4985555d68d7b346637ef33093","nonce":"d505fc3904839c7a29fda43b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"e758f815d8d39a098230364829ac6978a1ee5b2ac5cbb37f507a7311f02f6c4db3a7c5885ff40a0fd64625d706","nonce":"d505fc3904839c7a29fda43a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"baae3861b6216bafa3bc5929f67209205b1b4aff12c725f837ab1d280bf55fe9e7e9f79813513a6571ebc6124e","nonce":"d505fc3904839c7a29fda439","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"c206b5b10172d88fde07ec882188a5a12b8157ea8254a5890272de1309464281e1f853a1d80130ab64a7e55065","nonce":"d505fc3904839c7a29fda438","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"9289ee79e84e7c285679f3afae166fb20e8ee5ba1f2e1ca873415223f41282e9f9a613776ae1f043af17cd330c","nonce":"d505fc3904839c7a29fda437","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"1fbbcced201ee18244f2e964aa85fe1dd397a6a81c69c1fabd53c2f21b81b36230c9a5431d9119be93601e2c05","nonce":"d505fc3904839c7a29fda436","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"f25d0e975143eefea1dc918dc85e1b2c7039897440df514ece0ff9be856ed1fdbaa8b55d521f78e8e5ba245663","nonce":"d505fc3904839c7a29fda435","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"7d87c7a4aa3df2811199f4496d8bfb99ea955e24e9f0dc1ae3b9e8292c4ac05e0e0075a75264a6349d8c913b4c","nonce":"d505fc3904839c7a29fda434","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"b4580c4f43ee40561b68a639472550c10e0b6010a678ef5a6dfc5c7903424c8e4edd0f8c479341c131540a5bfe","nonce":"d505fc3904839c7a29fda433","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"cdb0542e1e968ce1de45c0c764ae2c7a769d6aaca3509869a63098c1a8d1c8ba1cd79f3d0fb07b9057e6346948","nonce":"d505fc3904839c7a29fda432","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"add34745f2f7566e3d0f031a3f4b1c33e393975e4a69729f620dc8a79ec6a053860755548e5ba088613a8abf03","nonce":"d505fc3904839c7a29fda431","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"26f19a81ad65dd0a5f4eb0b841666964ea40f1e74482b5aac6d763e79c272c88c8488596abc7ec6f77943ade03","nonce":"d505fc3904839c7a29fda430","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"eda3b4d94d59363f68cf7422327ca04ace06080d9e60267c6f2c938f231f8eb0bbc77ad0cc9b6716daa6085e5b","nonce":"d505fc3904839c7a29fda5cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"d7dc0daff938155c00c51c31475e7ce77c8004532c3a108a359c72e454a8095e"},{"exporter_context":"00","L":32,"exported_value":"2b5ac075511e8d837a501044556cc8030195f6dae5dceaec59c1b18109bb6210"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"d071654943f945e02b2d7d481d5354df1ea28e8c719e3a1711b1e6fd48696406"}]},{"mode":3,"kem_id":16,"kdf_id":3,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"bfcb5fa84861e9fd5f3f48457d25a82c04ca76c1623260500a76bb6fa86f2380","ikmS":"2c0cc3981dda9b730056327b385965ff8d716406b9f31af189ddd701f3c04d7a","ikmE":"146a024e3b41a23357420850f9a7b3d0164f58132c95d808a10a2a33a163f3b3","skRm":"c0bb5171fb5fd3e25b654f22b3e7dfd16dddc96719659fdac5ca3b6e414eb493","skSm":"d88bc3fbeae01be678b996403aa4132d50eebd92ebd4c5242bcf0a676607752e","skEm":"f5c6c151ef819c3db67c7584ed6d3326080359d5bfb2c8a12ac3faeb4301a875","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"0440e24e035f3ebd028dc0bd28d9cd07d16b192f7cdad29985f3dbd6b571460ae7c6305961e8e9e2d7336bfbfc35ca7f6c13c413f51451b57c5516c7d346b16338","pkSm":"04d8c860a17cd4aafeb0322dcd20491ea7eb8bc74d04449178f035472a631b29c6a809009ab14c36d392caace8d45d91d3315d22c1e2f671e88be1cc39347d00aa","pkEm":"04222c91eedcc9da098ec9316cab35d456516f13a496696041424e167499ea94d10169b5a61caf261dd896a4f183c7d9feda1003b5ca306659fa052d8fb6670650","enc":"04222c91eedcc9da098ec9316cab35d456516f13a496696041424e167499ea94d10169b5a61caf261dd896a4f183c7d9feda1003b5ca306659fa052d8fb6670650","shared_secret":"06b353a72886ad0e7f38b0a74cf0324fe4c533232e7783bd238d07d0392c921d","key_schedule_context":"030d17104af65412950b881d58878238fdc9f980d980945e2897b7bcd44b67e27a61c2a1c2e32dd0197004c59c6df6898f7502a62f33ee399176b24ba94a1f48b1ef4b8a36b914c26820d53e83a9dfb742c7811a526e9dcfb2f19f895c68c80dd54c6e836af7133e4b89418b17bdf4c1d32445ee0bc0f40063a0dfc0e0913cc37f","secret":"958546b561ed50f7880b7efb4eb7e936aef588ef184f0d792230a02320aad619b76b822a833f16490443c89ef732f8550b1b81ab04930836896042151728c4a7","key":"543836b4ee4871e4ba860b5e8bb6d77a36c84b98c9cfeb55f9ac30f96d4033bc","base_nonce":"56ddbe296e355bd3e429ee7b","exporter_secret":"8f155b4fe037b7174fa74f54664a72c1e54a99cc0e0157bf41e808c4b15c174f87f7d6dc58b25e90a108bcd6306b604de4050b91d7ffe2341dc3d90bf2443ac3","encryptions":[{"aad":"436f756e742d30","ciphertext":"a5633375d33fad5752c0dfcd55d2d8f45d80d9936444df8a91afc1fa821dbc159545985cb981e17283de81e9c3","nonce":"56ddbe296e355bd3e429ee7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"004cca9953806009ea4cced9d10bb5ed7b8ed06fc31a37e20828db98760764d1d4baaf1b1ebfd849f757f4b019","nonce":"56ddbe296e355bd3e429ee7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"84f244ecfe9f4e91f0d2ff46c484847941bc33999afdb25a319b6908831c16f122eb12ada4edf7b793a6842e6a","nonce":"56ddbe296e355bd3e429ee79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"6d1e062d18590ff4598f16ed400adeedb763d2cfdc5b62aeec9d86c16ec8dcb9e78d95f9b2c011dd08ddf5b5f7","nonce":"56ddbe296e355bd3e429ee78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"5c5fb8d61337df2458d50df035d11ad5465f13a85497bcb1b22543bcd7da3f32664e403d6cfb3e834e407bf4a8","nonce":"56ddbe296e355bd3e429ee7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"3ea594b8db82ee7e82a3792b4bab9ec0f2c6f9584649db5bb106bcd79ec6683e790b88ad51b8dbfb7fa2a8bd57","nonce":"56ddbe296e355bd3e429ee7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"a7f0053ace441e60861b7fab867566aba9f14b9ac41d7ddc64ca4bfce98a885aa0e0dee5d413dd0be7ac1f3a16","nonce":"56ddbe296e355bd3e429ee7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"5282e5abc0d561a912e1cdab75a95df79899f95d03a52bbff51c9f4b75f6ed904a162f891e3bfc2431ff810969","nonce":"56ddbe296e355bd3e429ee7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"afb0db9dacc3ba9924e71481c69af58408cbfbb0c24a7107e92bc16c156524a4d028847294eaa0829305452870","nonce":"56ddbe296e355bd3e429ee73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"2c31b7767bfc304b95738e89b93d56bde35d20e1f38ee7cfa071d77597a51545078eabd1eb1931148ea4ac40ef","nonce":"56ddbe296e355bd3e429ee72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"80cd4ed4d8ec4000d7835e125f022f3e7248f8df44526d6ffd8fa9d4a0af586573aa7e9ccc8e486f578eb11ff3","nonce":"56ddbe296e355bd3e429ee71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"fbf7aeee4eaa2212176f62d7bc987dde30762e653f1311efaff8dbe49d886b8be6ad81446b138eb60a50603d18","nonce":"56ddbe296e355bd3e429ee70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"71b35c4ab59110a2d105843224ec87d39c5f9ef90d56d3a5f7c7e050973a0c12ee4c49b0f1dfef6f31b9ca2880","nonce":"56ddbe296e355bd3e429ee77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"61270d9e9e34019c27e28b885ebd9448c200beccc341da647a321570b943d614a23a4fe6a2eae0c64133d26a4a","nonce":"56ddbe296e355bd3e429ee76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"4b7c1aa0008e32df75a2b6bc302156b454375174f77508439a4f5f673377b48f40168008a5bed30b53dcc4a80a","nonce":"56ddbe296e355bd3e429ee75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"70df9e71024cd52f72422d15f3d35e541e40c9770c2e3b2a64c0bf1f5241c467e39082dda52bf169af5f02ce06","nonce":"56ddbe296e355bd3e429ee74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"c87be898544e8337e94d2c55f764a46d5b65f85802c4e0d532217ef383b618bdee595e5ffc64a40b8e3f2c4ef6","nonce":"56ddbe296e355bd3e429ee6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"bd0bc41cace614de4af262c924ddee5d0085c65ff8e5a9bcc4fd8221915bcf23f5a3e149c733f79ab27541fb18","nonce":"56ddbe296e355bd3e429ee6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"b4a33a7244fbd43e753a48a6425ddef01a02690e20cd87007c659792fe2c5b9a8ce683a94df61d472683be0229","nonce":"56ddbe296e355bd3e429ee69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"0a01914d43626e8f490c8acd30156f085debdfcdef3e4ec5dd055fe46d28322c9c4bdcda61c086d317bbdb15bb","nonce":"56ddbe296e355bd3e429ee68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"05f4b6cc6629f44bb2bd7cb602806228d4181a1012ec751427f5f64844225a02a62e914e95e0189f2c661e54b3","nonce":"56ddbe296e355bd3e429ee6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"7575a3a12b25b16bc6f891d6fe0337af054831d2831db156f36a34d1a0e4593e36054f29b6d08cf9ca44777c66","nonce":"56ddbe296e355bd3e429ee6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"3df27b6b0bc78e4b83346d62962c7a9a0a13af719143bed2b396e6d129286e0c76d17f32e25a320c70d1368a47","nonce":"56ddbe296e355bd3e429ee6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"18ec9efd0e82d8a6012411506435a3a871a75d131a72c3fe9311a4cada32a1d5bc10b76a2685a70a2006eb9bb2","nonce":"56ddbe296e355bd3e429ee6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"6312afbf3c3ba26b927f8b7e7f7e893d4e333ac0c448cec7165b41890cff7daaa12b3c0e192cc3d4b313a02d37","nonce":"56ddbe296e355bd3e429ee63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"be54bbf3a3d075b1d7871303ecac055000cfb12da18b5a5ea92bf04af6475061a2679f8884a10d7aa05e180b6f","nonce":"56ddbe296e355bd3e429ee62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"0522222a821f3b8b95205d547fdaba8a37eb389554b45cd04b782b2168d98556ff7a70d7ad1e3a7bd2d5590f00","nonce":"56ddbe296e355bd3e429ee61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"2475f5aa4258190a450b6dc71fa97a0065a18bc291597aaad3ffda467488f8e4af278cf048e4835a0e7e0b391d","nonce":"56ddbe296e355bd3e429ee60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"08d5b868fa6d66309e9481f1a8931420264611347d61c478af6d9f283658c0b78927485b43c0297dc494d4d3b9","nonce":"56ddbe296e355bd3e429ee67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"cab52f3d7c4afa07875d037b7f2fed4414b3ae7336dd72f277f2a5d3884c3128fba74fb5536960585a487f627d","nonce":"56ddbe296e355bd3e429ee66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"44710e0542c57d96b6f42d9b67516dfd26952d44ad0ece5611b0ce319165714a6c1e0b9d2dff2a642b5222a54c","nonce":"56ddbe296e355bd3e429ee65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"abe405802eb997574a6a0b552f1e3e17f96f1fa0f748797e6fc8efb1d940484d57f0c10bc18f5a839d4cc06d3f","nonce":"56ddbe296e355bd3e429ee64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"02271ca268256248f7a8de1a3050ac076b358a8abcc9d0a46843f52dbeb0362ae1d381e135a6bf97efc5328ed6","nonce":"56ddbe296e355bd3e429ee5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"da5b17463b714b0655592450cefa976620c73e55bd3d16ef8a5d56ccec75870b378f291c25cf2284528a18527f","nonce":"56ddbe296e355bd3e429ee5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"2abe7d0d091bfcc7f59dc1fb49cdc4c70f65d9e49af5c1213ecfc1bef0cf87af99d7e333dea16962b252647ad1","nonce":"56ddbe296e355bd3e429ee59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"d7db13b374f92690dca01178c8649c5b454458e0b83523dc377c821f84909937930bc2aeb011264ce5ee0d80d2","nonce":"56ddbe296e355bd3e429ee58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"57555441950eac43b4a30a13c0d07d85eefb17af80bec1541d690f790e9e41d8dcf19590bf4b70d2c010fc62bc","nonce":"56ddbe296e355bd3e429ee5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"9446fe62c3d4a3ae9cadb018e7bbf6506c4abcb082f6ae7c4e860fcb57f6578fb336ef9615bb7fa25a11158dac","nonce":"56ddbe296e355bd3e429ee5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"f1d8cd808a079e2770940265314b0d51efb3ecba771f0dc92f0c83c47593b37fd29fbc70eb09a6a36a74214c26","nonce":"56ddbe296e355bd3e429ee5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"e821b98af9b7b2e0600f8666cbabe85b8dd73e992e799a2805c8efb0231c1d3f9f21af90a6d0336d79e1d68c13","nonce":"56ddbe296e355bd3e429ee5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"de479549df97561470688c3fd3ca9635d750558862204f2e045d8756990ac056788d1dc4a54a159336887c4ccc","nonce":"56ddbe296e355bd3e429ee53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"35639cb5d8cbdff434de87f84b781e30c201ae5a5c56df1589d00dc1d4506eb14d9ae2f3aed2992ee021bea05a","nonce":"56ddbe296e355bd3e429ee52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"5cf49ca2b5ce4197bc353d47dc9c820b28c5d80a22148d9c0cd4784e68e964929a4f42d96da1cb46eea1b7b388","nonce":"56ddbe296e355bd3e429ee51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"396907504c8293d1d7bb49c491df06b92045a818b074f23c2e78cb502b02997c49841da63bcadc7f584291e532","nonce":"56ddbe296e355bd3e429ee50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"d44ac099b88e55b804a1d3143b07a00cee173e6145b7b19be53652b57d02977d1b4c43fe7fda0d820855ddcce0","nonce":"56ddbe296e355bd3e429ee57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"3134c2faf5b2da3ab884b3414be50139fd9b3500c9570f0b6012f6d93d6b2d638dc6aa3fa6b16b35d464c37c7c","nonce":"56ddbe296e355bd3e429ee56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"2bbfdb1ea20291e0f30259d700cc06f96bfc41f2371989ff0788fe4bf2d473ec93400cb04c6316b3060096be8d","nonce":"56ddbe296e355bd3e429ee55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"a64c4ca806cbf86d09768acff4bfc5ae225dd4dd1066e8b51993d6165ec1c57811179286613db4298099e3f4ab","nonce":"56ddbe296e355bd3e429ee54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"7ae86a826d119d9356f70dba19ca5c53a519163cddf4b1598964c1f3dfda274d13eda908adf7d8998f58d1b7e1","nonce":"56ddbe296e355bd3e429ee4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"471f52af8eb605aaa50ec2c17e8b30f8b2e1dce1d5d0abb72b893b350db8550137c36cac8d061797d2f2468e37","nonce":"56ddbe296e355bd3e429ee4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"6b3fffa9cb1073846ab43ef14b4e7c86ace106b9dc1cf5a3ea0aa9e1cfea2f02c718ab1d3ca4f68fd1b6212767","nonce":"56ddbe296e355bd3e429ee49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"8c5f013a95f4fc618df5899d47104524b44f591b1700e48d4e206c8051e727ada8e7f51287b94896c00bba6581","nonce":"56ddbe296e355bd3e429ee48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"5c4a6880188976a1acca218bcb2d20ea12bcdfb48e045d7ba1f80aaf2d1a8ea301ffb658c1f758d9ae758a74eb","nonce":"56ddbe296e355bd3e429ee4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"68ceb30b5ca2d3b75354d2f798f7612d2b7ef40673525b1514b3bbe05257be3cf8c3891abcf43648361c727712","nonce":"56ddbe296e355bd3e429ee4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"5ac5768ce5820ac779e187647a9a5cc45b7e4e88f4fafe2cdd50a8d0d58f6d92192be3d831bcdbb759e9949d98","nonce":"56ddbe296e355bd3e429ee4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"edfd5ad39fe9a67a065263beb9997752e84ee84b91fb0057d2dd2765457fa0f6a5b703ac6da6d996f95eeb4abe","nonce":"56ddbe296e355bd3e429ee4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"8aa905f02f857a0089e1b41ba21631ccc8b61cdf50cd033b939da729da3a8268ec514c4bbb0d4ccf8585ce0a3f","nonce":"56ddbe296e355bd3e429ee43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"49ce8c9a16bd22fce0b5e2d925974c6c2a4fa4d42de915e1d6f9b2b0a3dff4ddd13c9b53df8e3c0367fd40da70","nonce":"56ddbe296e355bd3e429ee42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"14ee0ceafaae5d8fe59aac9c53265969d2f406a5344429ceab7b01d14350f90a086a2c23d43816fae0d42b3e6c","nonce":"56ddbe296e355bd3e429ee41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"d5fde176b1726d98fa0e413c4c49b87677287f9837bae28cb2da837b4dcb0c1f13d814b265db5d672d5e162713","nonce":"56ddbe296e355bd3e429ee40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"88dac7551aa4ac5925c50f80c36ad13af7769d224cc1ec7fdbe02db62315e02ae66d315638c02b6d1481000216","nonce":"56ddbe296e355bd3e429ee47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"2f16321329499d7e146b45bde61b3c53bbf6cfa72a578f77f189db8d90f875843995c86c71d9b22e2bf15c9174","nonce":"56ddbe296e355bd3e429ee46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"a494b73fae17993e0feaf564e6bd8bd417c1caa37dfea6b3e350c77f12cfeebca5b7e930687984a6cb5c43f5f1","nonce":"56ddbe296e355bd3e429ee45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"13eaa048cdf825ec9c231a0c01e24314b591871f73a294686ce76d9fb45d1314a6d91a40aec316a2e7abaacf44","nonce":"56ddbe296e355bd3e429ee44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"7d5c0b804e9aff343a394a115f34583333a5be1cb2386f57beaec7765e4a36d85cd8170e80f7f4881e3bb7e1b0","nonce":"56ddbe296e355bd3e429ee3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"0fb6145b2344e6800a342c6d69ab4a39c21e664adc21ea4c7045dea7d551714e438162710e01af51dea959b747","nonce":"56ddbe296e355bd3e429ee3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"56909e2698bb7de4f10826e59c22dcd0d86df9e4eea9fe555c4fb7c42510ffc09a45071456e90de6c689dcd46e","nonce":"56ddbe296e355bd3e429ee39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"d1c7c0805aca1f708dc59209f192466079e5b43386156d9de33053adfccb796867b43e73754a71c13650c47f4f","nonce":"56ddbe296e355bd3e429ee38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"b7a22934ab7954fc05d1bb1569ac8230779ee6c6ce472c027e208a87870245093cacc18e0c20ea5f149d5b6cbb","nonce":"56ddbe296e355bd3e429ee3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"c6c21615d135632540fd95e84f8068cc8fbde721da0051fc6ae5ebc3ee1e2135e366faba8658647662b0ab0129","nonce":"56ddbe296e355bd3e429ee3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"36d9678a3a0c6ce3fe1a45372b30ad672b71f5f903a9d81fcec00a06bd5fb1137d6ff8ef1415bb44de71637873","nonce":"56ddbe296e355bd3e429ee3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"f2a1d3c31bc43ce160ece67979b0e0e2e7c056d2ee7a2ed7b116090bbaf67d11ea18e49f078408d9d8ac1fecf0","nonce":"56ddbe296e355bd3e429ee3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"b4ebfe254b4ab952a922175c50f37a98658daf7ae84dc6662d4ee1edd7165c44a1d8b865ff8f895076a4c3eb6e","nonce":"56ddbe296e355bd3e429ee33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"9e80fc28b5408b927c9c521a952d2b78ac416e823e10fde097421d065a837f96f4ecce458b67b20dc238b9f662","nonce":"56ddbe296e355bd3e429ee32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"b7330457be52151a1ef3b5c0d50dd4fdeba7ffb0fb9c0087906b056a8d3e9f7e8fac37ffb2397280586eb7800f","nonce":"56ddbe296e355bd3e429ee31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"29d9b8da03f4eb00c8ef28cc8e8ee8d2d29af2d6fe2699e36969e647ee4862c327ef715aaaeb9598057c7284e8","nonce":"56ddbe296e355bd3e429ee30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"2ba86ae7796f4e53d664a16d367fbb8fba7d93498b76e88926052b2a1ded8d6e3fba3dd3255a1bd3fbfbfd1ffe","nonce":"56ddbe296e355bd3e429ee37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"9091c92ae41be0a2f1b5488b643ce2cade0bbc02cae458eeadb78aee7201c496e38292f9c572fdf8730efba4a0","nonce":"56ddbe296e355bd3e429ee36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"65fa831553aac8bcefb6972b3a68cfafdf1e93492f1ba8e7d27888ae19f80948e0b3a050ebe9b08a80bffbfa76","nonce":"56ddbe296e355bd3e429ee35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"477b46f13116efa2c8a68c7218c11a99d88b53a0a343f9ab4210c4fab71905e2e69f9188a75e6953bcccbfabc1","nonce":"56ddbe296e355bd3e429ee34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"71718f39076d58d421ac119a068c2ead41d61ee9580591930e370a3316c485b2f28d694dd2591bd9f845281747","nonce":"56ddbe296e355bd3e429ee2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"fa5d9e524775a482444656d092cfda764a9661c2ea87559aec3e0bf0b0bfa9c3cd3b8932ffdf09f36e1ed4919e","nonce":"56ddbe296e355bd3e429ee2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"bba817ff7a74134ec1930c00078cc2f1f7067c0c056bfb4c09cb740e6cc37bc3e2c52ef4957c5f851dcbb12915","nonce":"56ddbe296e355bd3e429ee29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"a1103f3f5dd9a51c4b5bdc07ab5663e01a4b256f0256b2c329f29a3b81c0f3df741456c3bbb3ec3cd3b8563a1a","nonce":"56ddbe296e355bd3e429ee28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"616f12d4981709e06c4aef4b24ffe705054f425117d1b6e2f048a17232bdfc5f956e61c0328d57028058c4e3f5","nonce":"56ddbe296e355bd3e429ee2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"7f1db6ce129eff94b2787c688bb5070544d11afda4ce5b0cd68330359afab0eb96309c01cda5fa55e378c5e272","nonce":"56ddbe296e355bd3e429ee2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"4213612f73b6bc02f012c73271977bac9e8992b32b07c7cf27bff3e33871d424e418c55b83a75bda9441255395","nonce":"56ddbe296e355bd3e429ee2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"bd21900c0dbba9358d1b531aa2f05a40e56f2a4a9d9eabaf9a1d837cdbfd8ae74ccba2c533443a4efa3e80291e","nonce":"56ddbe296e355bd3e429ee2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"fa2badf71be6fb47e5b7c0402cedc7a5e1617659dbc22aefaa05981c1c87b481b1a855c0ab4ee605be6a04a9f9","nonce":"56ddbe296e355bd3e429ee23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"9c06cba11e04b3ee8746374e253c60ca03321ec551f435bcc2e2ac49521e4cdd7cfd24f1b67a2dff0882714a89","nonce":"56ddbe296e355bd3e429ee22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"0fdcc272d2e5a683be147de1bcd9e75d6a5581848dae75e9bb944a33ee2a21ffc89eab0f9ec62897cf58c791c2","nonce":"56ddbe296e355bd3e429ee21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"a9e67901ca616b630f7c50126864531978c1f1923598b79843a40dc5aa52b1844d720fd5fd8a2ea46fd4108e4e","nonce":"56ddbe296e355bd3e429ee20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"40a534e2b334dacd99e8155d524c92dcec7da268bcf73f7b220cf37dd6d2994bb733c123583792f0e2f13ece05","nonce":"56ddbe296e355bd3e429ee27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"b7ab2f67e7d8be61e8362291e8db955e68cd5b74b3cd090067e3b2b2850b7c0e5013628d93a214d259ab69268c","nonce":"56ddbe296e355bd3e429ee26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"b5d09d2c2b73ff4fecffc107f63d193423f940ef023b2af8a8e048e94e94848e1afc8dbb9a7b38f5d327ff67d0","nonce":"56ddbe296e355bd3e429ee25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"0bffc7fedcef3f577c35c1de1824cee73a250d4c833c20153b6b9ba63701e4b7d46bbcf393a5da2c70bc70acb7","nonce":"56ddbe296e355bd3e429ee24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"00da215efd5e16e090252db27f34df8686adec8ee87b23da91d66017cf5fc46bbde65345e597e8d743f2d2ca1f","nonce":"56ddbe296e355bd3e429ee1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"2484ab021f115d5d45ac038799880c3b1d75c98549cca09f2909a69df67cd389c70ade3ea9db77c584446fac8b","nonce":"56ddbe296e355bd3e429ee1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"75005b662727c9effcdedd0d3f5e520c4c50f3b8e7163c2429328f281bad6942013c531229d2b834f2f9f2bea8","nonce":"56ddbe296e355bd3e429ee19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"32ae781a64aa51d552ea713cffbd747c90079667d5cfe72f3fae52e3af856a36296b81b832483cd1ab3420fbb8","nonce":"56ddbe296e355bd3e429ee18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"5b7cbb2b32e4431cf2a541f83471fbf232f6ccd3887be01635f8b65b26eaf369fbe0d13c262413efb766cd2e82","nonce":"56ddbe296e355bd3e429ee1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"f66225c7a6a9d43ec02d2ca5c08d551eef314ac1d0335bbc97bcf4e9a20b13d2e0394fb8e836827bbde5ea0eae","nonce":"56ddbe296e355bd3e429ee1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"76384df48bfd407ed7075c1fbe011702494ae1612a3cd9a040c7d3654a65233a416b9cf7791dfd20ae11ec3fb5","nonce":"56ddbe296e355bd3e429ee1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"26c5966679dceb9a2d9f76579c76ba2a2d73b89a992ecd6ff4f2956e8cd02c07144d7f19ef3a90def49e30726c","nonce":"56ddbe296e355bd3e429ee1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"3e1126535df198af2dfc72d2de0676e071df48db65e76cf74d18811f37fef5841176076a5c07b904679ffa8bed","nonce":"56ddbe296e355bd3e429ee13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"e0d380bbf47b528ede9a578a42fea02187893154e5fd3371f19afda3518650d21691760a2bab9dee07fdd1b1cd","nonce":"56ddbe296e355bd3e429ee12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"ddd2c2ebdad2184c6ffe9e0bd0fa63f6a19da2afe9c266d28a1edc1753905816ea7f049bf3246bd0e6a8812d54","nonce":"56ddbe296e355bd3e429ee11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"9c1872efb0b5e46c6c8bf6d0f38acba69d3072e7b7ef4f93d439c2df4e72c7d20900445cf33ca8f8050c7b5ccd","nonce":"56ddbe296e355bd3e429ee10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"354d9c9e912d91307eedbab8c7802da475fc46cc168f53b45dbaf4ddb86fa8303567863ce1875c1df5d3e049fa","nonce":"56ddbe296e355bd3e429ee17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"24c246c5713da8190087569e18bf92047edb93771578ecfe25ea44474207f3268ad55f4285cc966765ce6bc602","nonce":"56ddbe296e355bd3e429ee16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"d55c87cc3ee392962795a273faeb2f3cf676ecd88352dd6963ff663fded2f84e9149ab4ad115bb76a9cca986b2","nonce":"56ddbe296e355bd3e429ee15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"7c68ff134688119eb37b568493f4db92c3085fcad019b3bf6df01f88de0f1c2c0f0c9d1e5cb5e72147d2af861a","nonce":"56ddbe296e355bd3e429ee14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"eb76a9942b4e5a53971be342635b5bb0cdc174d0a4cf2dfff76be473bfdb08ac12bb04b9808f9c4aba4a08a1ec","nonce":"56ddbe296e355bd3e429ee0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"5a45a308402ab95617c3662d43d9858ca823e8958ceddcf48b904a32b078d56fa33b18a9d3b007486fbcfac956","nonce":"56ddbe296e355bd3e429ee0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"46cb5595a40b52774b0e371d27a79a82de36af8afbd24761ff2a13f1166461eb8474c952a40ae2b8d2c97cf5f3","nonce":"56ddbe296e355bd3e429ee09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"1d86ca361bbbd2f6323a563621e17bb369643355392e316c514f7b3b0ad27e2c44f2769a83662a71fd2079e3c5","nonce":"56ddbe296e355bd3e429ee08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"3494ea8aae1ea9cffa1cb3c1bf0aa052686a2d629bdaf4ab2c084f6ea0de8c3a3db4d6be80f832c0a8f76a034d","nonce":"56ddbe296e355bd3e429ee0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"d289d4aa5953de1202214c1e4263be836b017fd4a552efb4463a0d175dd3ea6da8d97202382fadd4f8b15fc5c2","nonce":"56ddbe296e355bd3e429ee0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"e1e54a8653f99e2d80d48782862a5474735d38551e3090e6a5a196b7b296ede34d4f7c632780b5f132f8927088","nonce":"56ddbe296e355bd3e429ee0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"028584ba7bacc6c99e503a1c031bec8c7e230c6460dfcae0a8f12db35d97233483fac32b164e5d36a2dbd9db12","nonce":"56ddbe296e355bd3e429ee0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"bf443ed9bda3577e4cbb247bdf9d341753d00e518c20326f2118eb638759b2877d5bb94530ace5253ed72eb319","nonce":"56ddbe296e355bd3e429ee03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"48457fb5be70873b3ebb82eaff5635b593a966506e82fa0efdff63bc6118a76f0274e5065ea5714539c36a3bde","nonce":"56ddbe296e355bd3e429ee02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"2192ca1d096de9205638cfa217485c3c8dec37a0090cc18fe695a054b8a5a77e43fcb3fe6db9a7b85fb46fcf01","nonce":"56ddbe296e355bd3e429ee01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"548fe5c3aeeebaccdd933cb3c31b93ab0b551535084dd63a78a19d128888d7eb49951b0096f70896a3776dc7ff","nonce":"56ddbe296e355bd3e429ee00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"f930b82705b86ede9982d8432d7f77817821c9ba755f9687bb7e9201edc259ff75e4f4b9dff6b8c04733c6c954","nonce":"56ddbe296e355bd3e429ee07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"08267b61d38c941d991a09e7e5c9474d8e47b55ddbc6ecc1ea67e83dfbd8b7df72887cb024b908d1225f9f75fb","nonce":"56ddbe296e355bd3e429ee06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"521fdfde61a456957df3acac8046929b1a2cecfaddf5d92b15e47fad932ac86d328f7df45216377eb2c3a0e7c9","nonce":"56ddbe296e355bd3e429ee05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"27c334f69907b8207f33993f677a038ca4c0b6d5405cbf0d9806f5841599eb02bbe9eec2d049adc64669a683a6","nonce":"56ddbe296e355bd3e429ee04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"f3c6bdd20395ee067a53880d1bc12deef34ea4749ae92dcf043f6db44ad3e44555f58d3d0ec8356fba7f48fd16","nonce":"56ddbe296e355bd3e429eefb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"2d0b631bc2fdce81c684b29832f0ed6a33ae3a17cad76362602bc3e165d8ee038752e316a999281502eb22c958","nonce":"56ddbe296e355bd3e429eefa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"e0abbc3b4d0d671219df67103c99b90b6d3aea06c05f4698be91dc8dd7951e4c5840dad5da101e20fb4bf2e374","nonce":"56ddbe296e355bd3e429eef9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"06292ccff825d959f94dad16053103914a47a84b0050b93baeac7d9ec8d71ca927d03d0ddbb6a6a6426eb6ee06","nonce":"56ddbe296e355bd3e429eef8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"f46cdc32b502a232eef7b54804ff826cf03d72d25a1e6b29ed8bec551d5b1eccd24ab41e1ef6375085f0121c8e","nonce":"56ddbe296e355bd3e429eeff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"4bf1fc5c40b77791c3f2ae8a8fc55b785cbe83f8ce683e96d978acc2229f3c24a4470df7ebcf5992f95c4d484a","nonce":"56ddbe296e355bd3e429eefe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"e7c09c8aa023d4c393898a5ab07d30e6f512c6d421b9d47b0c54e22ee6104bf6d395efa216ad254d9ad6012e86","nonce":"56ddbe296e355bd3e429eefd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"baa0ff0c616440bf9a384d18ca6a83b1efdf4631f75d49a320a393216abc3b74a60037beb82f0b08e032e86c82","nonce":"56ddbe296e355bd3e429eefc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"83dd16be058ce2810082cca8fd410a9ed60e75efa5ec29c09ddc2c06eb4519541943952fd479cbf58d13ce518a","nonce":"56ddbe296e355bd3e429eef3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"ec96f785bf220f347a1eb63d590e3b2490470c002c58bd9bf3c67cd279488f43ceab1a4aafaa0f1cbf2e795f6a","nonce":"56ddbe296e355bd3e429eef2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"b69ee212da880e72dd93dd103b9bfa263b2727653051aee5efc2d2852765f9bd9ff2275b55bf7af7db705464a9","nonce":"56ddbe296e355bd3e429eef1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"141e1d53c02bd2ea8c3394c9ff5d63a9ee240da45cad9061acb56678cda514839d35cabbb6c26ede925ba21fdc","nonce":"56ddbe296e355bd3e429eef0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"32010717f7cbba575a8e33286a8744ffd6a588d8c64dcbbf863a7cd9e88fea1b9e6ea5a7cf2e4ce6fe7b84cd61","nonce":"56ddbe296e355bd3e429eef7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"db05e6de2b456b3eb9fef5642e4c2ef8cf2085f888994b17568586e388992e71edf02a615ccc9858014a72b759","nonce":"56ddbe296e355bd3e429eef6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"d94db5ef7db1f7d9d5ad5789d145e31c3c9664cc402a8f4d9509b67fa2a5f3cf63eb8b8fd699db68c2a7d5838f","nonce":"56ddbe296e355bd3e429eef5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"6fab75007904e36ed1432758c3040d999b504e9f6672bb5fba1e3b805bf51711f617e4cfe1ffe7ec5ac669b61e","nonce":"56ddbe296e355bd3e429eef4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"e53fc4b9c43cbae63585c17b6a40ea53a79ab13548a5ee473c07d7cff066374cf92a4040343027ad7d0d29032b","nonce":"56ddbe296e355bd3e429eeeb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"2a43e3c22853eecd6bb31658ff0a0b4e3177fc2a1b98865ea075a5bcc8a4d7a8ae281fc4df1adeccae026688a0","nonce":"56ddbe296e355bd3e429eeea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"80c24a2bcc33d24469a14c8306542e0a37cba40033af88ce87a23bbe3222d2556a064afa59890161649f99f9ed","nonce":"56ddbe296e355bd3e429eee9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"249e1817a126fc036c4bad2c72aada8cf96aa49087e388d3581646a01ac83e8060842793bcd66a04c9d4a59dcf","nonce":"56ddbe296e355bd3e429eee8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"1c50c72e5f264c4e146544411d0118af20c87eaddce877c6b43bfa472acffb1e0c44fe17174ede73c2b997413e","nonce":"56ddbe296e355bd3e429eeef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"4761fd864acbebd02e346d42ff4c36e7351c38ee2160a45176dd48fdf74e589e7c40c5ffb8409297019bc92fe0","nonce":"56ddbe296e355bd3e429eeee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"0c555880f469a3f67c5ddcf670165a5129224983232ed8cf2a63a2a1cd7043b8ec01161e558043c0ab0df3f276","nonce":"56ddbe296e355bd3e429eeed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"bb47813ca0564651c0600f6719d136f5fa5d4106b933149c5c231ba7a9a21a903e39ed0bf5b652222ff32574ec","nonce":"56ddbe296e355bd3e429eeec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"dd1ba7fe6bffe488fc28a94dc790079e560ef92b06b9f2723112d0585b32b2dad46e29e58eba0cda11235d502f","nonce":"56ddbe296e355bd3e429eee3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"c5b2ba4d13209454f8d52bb0e29cbca7b5819776b04b16d0acbe577bb547a4b86e943dbf524a7aa37588312ebd","nonce":"56ddbe296e355bd3e429eee2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"8916cc26cfe11cef5eeef159913a2541922e1712cd6cb55531653520c726b62ec99b845153a00fb1e57269eeee","nonce":"56ddbe296e355bd3e429eee1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"fcbee04eb63bd2762b334053405f35eb7ae55130a72b14e3378c036598e3e53b1d24abaec91b53a3037f75ff85","nonce":"56ddbe296e355bd3e429eee0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"bcfb780dd8b58e6de71201898cb5b285d32c8b2acda176b05b27dc0d7cae6197b7529240c5e96938d434d60bf6","nonce":"56ddbe296e355bd3e429eee7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"9f6b46d0e62d3593efc9cb672b7262580a0d42fd7b216f80c0f3d8eac942517bb411c1d4d17d90f7480c400cea","nonce":"56ddbe296e355bd3e429eee6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"ee618fb01d61fa508456c360fcac403a93f49c2a23c6ab3307fb8a511995725e1a4ac5b16459fcdce948854442","nonce":"56ddbe296e355bd3e429eee5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"dd515c72f91de2f7ce9e0ed11f0da0d2efcb952df90e55ca08f3cf74f0d7b520bb44fa1608518cdc11ba3c5d4d","nonce":"56ddbe296e355bd3e429eee4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"5c88d096570f9acd66fef641e855f5c39bdfc8c87568c0e0df0aa5a30d7a46e17ba0d20074e76b4dc9c51870a6","nonce":"56ddbe296e355bd3e429eedb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"797ec6032d6ae1a6df876ad881e6da5379e7d61acecdd35a9580d87ce07d1d59746002871f72c66de875bd6138","nonce":"56ddbe296e355bd3e429eeda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"086274e34d028579db98672637ab2f9090f1552120366ca50217102f883855756367a7bc619d67f9245472decb","nonce":"56ddbe296e355bd3e429eed9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"36125250d29b7aa98fdd2c8a7dc7ed9e7168004d1f5622afd8a1baa6000455bcbc2c68925105ec5f3c8b866aa1","nonce":"56ddbe296e355bd3e429eed8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"e02b5548e29c0bba768c9babc148893863b61c5388473f4feb8d2263789dfecf7276c897a2710dd4d622b14d2e","nonce":"56ddbe296e355bd3e429eedf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"2e9080bf3851f32376462bcab8343d42ee811b212e8e7f871362d9dc4c9e907d0ea66f605c3bb7158d5cb37d9d","nonce":"56ddbe296e355bd3e429eede","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"4c7518d7d2c4097407591a0d0ae0fb57fe84839f150423d5fbbdc0fe9e83e2867780003e48cdfa1e01079b1fdd","nonce":"56ddbe296e355bd3e429eedd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"859ebca864aa83a08bd74f4b04c237ca9fbf48b660fa7dbb9529d9c1779edd503129e38c30c76a7cc860c4ed60","nonce":"56ddbe296e355bd3e429eedc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"2cd9c9734e68e649b6845da882907f8bf55ed526b8382d5cc19951fb5c2057c2c683c5db7e9ef4cac641e4e536","nonce":"56ddbe296e355bd3e429eed3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"689c3b65b7374062fed0fd4e363ab2da93779e537469cf8df5eaedabb3f3636ca21371d9647c654671c21612ba","nonce":"56ddbe296e355bd3e429eed2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"f9f74748aa6e00fb58e441cc3659efcaf5903f402c1ba271a4466ba8fb0cf979d6d83735631d5e78f8a748a2d0","nonce":"56ddbe296e355bd3e429eed1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"b2fde92ea86bf726a1ed67d85d67f127c984b36849f254ffa8ca467a6f956039307df531c6974e3ca5eda12f12","nonce":"56ddbe296e355bd3e429eed0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"8d9649dad1758a061ad07a1e409a3e8977758b9c82f9fd8123ed837d0c99a22f92d7bb733f3738ae4b53084e6f","nonce":"56ddbe296e355bd3e429eed7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"9e8aa50ff0b37a6f6305777a4c0f1c832c325331b62d4ab2bb601af0db8e576c4e35ac7908149f1654b3aad522","nonce":"56ddbe296e355bd3e429eed6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"219f9dc35e3303f20be24394e6667a9fe0dac0ffa4f79fb9585eedf4c178fc4af6aeeeb006581409c8c8fec65c","nonce":"56ddbe296e355bd3e429eed5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"85263ae7cd6aa125d8736c2758de2adbb8a936d82b2a3fd6cf9ed57cfa7f66fbc3305fb5f03416e573b16e862b","nonce":"56ddbe296e355bd3e429eed4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"0257337e82e407450e1fd2cebb5be2363325c429d3901d42b0a30a05edafb6a7ffa3e7e3724d686ce52f100e09","nonce":"56ddbe296e355bd3e429eecb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"86b8da92d0204d5f7436464c5de79d4d6804188c68fa69edf31127e41d692d28a37191cc481ef49b029d3573d7","nonce":"56ddbe296e355bd3e429eeca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"1891ee551de01bb3ab56b0daf4e42e41132ab4149c963863aa300098cd61acaff4c0d900c4db811676bebf10f9","nonce":"56ddbe296e355bd3e429eec9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"256bf4d63cecb82737a46946ed9bbf566484c83546045d97b38d2b682e385861a52cac7ecffe8b637433e39ec9","nonce":"56ddbe296e355bd3e429eec8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"2ab2895e9fd28d8a93f2fccd399b181d8441a477243997068035bd88613547eefa2743a678b57cf54727cdc486","nonce":"56ddbe296e355bd3e429eecf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"b17905703a8691140e0806bf3dcc6b26cd81a48e49ce67fd8bd192c2858683df25cefdc195d4005b5600d139c2","nonce":"56ddbe296e355bd3e429eece","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"497c9394c1b586e2c6bef109cef811f68c3684bdf7afee9f825d1222de71aebf816c5619e1d598efbd9ccc6e72","nonce":"56ddbe296e355bd3e429eecd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"2b14e892ef69cba07f22304f76519f44424f066bec4e49ebb8dfc655cf9e1baec070af123d7763a4e72f2b5392","nonce":"56ddbe296e355bd3e429eecc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"1075133418908baa2a5ee4f5b53429eb1e6aec5663d9b8421bcce153904977ca88640334d4e4e8de586b137442","nonce":"56ddbe296e355bd3e429eec3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"11d7a921c2bd0f21d009e58bc89bcb0f365539a461e50e576c29e23f72f29ff40de91405e717bd36b5fb60b00f","nonce":"56ddbe296e355bd3e429eec2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"11ab5578d2c48e0140aaac110ee97acecb86156aeefc9ac63ed0f215184b92a742fd349ca872f67ee7292898ab","nonce":"56ddbe296e355bd3e429eec1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"b2a30e2c3702ac6b364e373637a31504283bbe740f2464eb18ff25ad4676fc78742249f52e6899531f93c82eaf","nonce":"56ddbe296e355bd3e429eec0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"5ab559e79cad8bb3eb95030ba66079cf4c177f122cfeb9d189cbd998000d970e13afa19ae14842b8b4f5131f0f","nonce":"56ddbe296e355bd3e429eec7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"be49a13c11103a53502514d2be29fd79702a001aa73d8f54f2ac8e222fc94b56272a086a5f77efe5f4e7e98b96","nonce":"56ddbe296e355bd3e429eec6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"7eeedcdefdde0398fe7960f979372a8f9d803ea725632f05af75166988c6ad0616b3ba85efe71aac70bd81e8d1","nonce":"56ddbe296e355bd3e429eec5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"de5b7682caf1fb7db2098516f5607fb5775af8f9324aafb2613444454e4ad904ae188f47673d0860ea48683baf","nonce":"56ddbe296e355bd3e429eec4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"6b9c0e8cafbea2155750788375c969e76c470f9969a9d7f4cfa87a8a29e8c3b8d356df5aad31de7e28747e22e3","nonce":"56ddbe296e355bd3e429eebb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"fd2793f4f1c9b07df59122c4b2533d1068e786bdf7bc836a3f36579f29454f147a9d85cd5bc86f823edf3e3b49","nonce":"56ddbe296e355bd3e429eeba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"533895e942385661de5c82eba80700aaf17d6d3295992890a5bf66850c4c363c7459da5752f062f5d8770b1ac2","nonce":"56ddbe296e355bd3e429eeb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"ddc409a0f5788a16e3fa250cc40c67cda736a18e0c5e5e27d01641817fcf68cf13a3dd3adfedd8c3ff7652f80b","nonce":"56ddbe296e355bd3e429eeb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"27ad5eac4c84441fb0360eafcdca6391e90edaea52235d9818c5d3e65eeb9bc9112785796cf3a6eab8d60b4124","nonce":"56ddbe296e355bd3e429eebf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"520523b15e050ffdae06a6e44a31429a48b7cd4e34aa897ba0c63a30d054892cf790268803ad0b1b92fd6a36e5","nonce":"56ddbe296e355bd3e429eebe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"c3133ccb6c19fdbdc6ac93dc7ec239fa4e67601b8342fa778e577244f4b88e63455283e8cb677028e386d7ce20","nonce":"56ddbe296e355bd3e429eebd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"f938c0b02ea38071c1eaa370a3807b70634e066d5f027c106e38ad4c0dbce344c340fa6eee2ad532b672dc800a","nonce":"56ddbe296e355bd3e429eebc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"99f9c48a94fd3f5404003bf7c92cb402f8b351b4d727dcbfe93b03f66a6da1ac3af95e6f2940eca6c04fe7fc7b","nonce":"56ddbe296e355bd3e429eeb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"f0989bf4cf6786658314397637fc6aecb898db65f03b9e7ef984cb2c5e14e04479dabfcceba4d9ebbe5f14a362","nonce":"56ddbe296e355bd3e429eeb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"3e98d9430ff3f178a2a0e92ba8ea5b087cbc17c534911439dc556181d9bb1fed7e4b3fb8f3a06af6ccb64d3f03","nonce":"56ddbe296e355bd3e429eeb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"dc1300cd2c307f41d83b94743121bad84c17b5ec8139c6bf49b259c1308de8f1fd3fd65574ecc385fd5895b112","nonce":"56ddbe296e355bd3e429eeb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"18782f851879cfed859c006735bf57b9d8c267fd29a00fab582c2036f889eb94d7aeffd9845276b4978461d331","nonce":"56ddbe296e355bd3e429eeb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"1b999c0eb28af49d4b23d2e86cece67d1cb2004b918333224e549845f4feeaa731eca2d0b12f52df8d4c5d67b2","nonce":"56ddbe296e355bd3e429eeb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"0ea17fce0b8f8a2835480471ba0500794399b91f315a4b2d319d1acb5bfd6a994f0b204b077480ac293fd1d06e","nonce":"56ddbe296e355bd3e429eeb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"161ebe0e8ea6263479a1b2faaaaa0bff12dfd22af6fde3144f42add316d64b3725f14f9947527d470b8bb9fd07","nonce":"56ddbe296e355bd3e429eeb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"ffbb1c8a33ddf848e8d795eb206da5037e440c924fb7e4789035bea1c6b6a419ce79a85409939fab96e234ce3f","nonce":"56ddbe296e355bd3e429eeab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"ea1af2b2c234f5af687fbc38367b086aa4f1d1fcbec2d039b0f5cc1f61d5379197f15611796847f628354bc48e","nonce":"56ddbe296e355bd3e429eeaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"f2b911babec1e4ebcb1a30b81965c43b79cff1c9116c7f890ed075caf50ae6287e540270ffdbea9ea8747504fe","nonce":"56ddbe296e355bd3e429eea9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"f930ac1c4d6af562287957efe93d38dcabf68e886b329d3f78e1514bb1565d73fe77507e4795d7bcf94f71f8d7","nonce":"56ddbe296e355bd3e429eea8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"ae1f6b817c23b00f92aa8bc53f377c9681dd89c0680e35ae438a863de9caa95dfeb927bb483d32e1a589535649","nonce":"56ddbe296e355bd3e429eeaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"d404fed6e7e2c7ae3fe1cc1f6d4b5f179ab98df5f8b1e7a2424a4a9bd3c771dee60325e7284c844061fc25951e","nonce":"56ddbe296e355bd3e429eeae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"d8b0a99bff22a70337e36ceae378ce27c8e77a3d3838a185b03ddc58892ea1b1d09a61b675925042ec46cd29b9","nonce":"56ddbe296e355bd3e429eead","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"94b3cb944a288d7753e9bb0aefddf2e1f63166b3d58e6c5dd391b73b23b6f65b00a71f9f7050bbc97042df2768","nonce":"56ddbe296e355bd3e429eeac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"c2f590e640c2b3c2a2f9bb88b806deacc8c54b30d9cc5aadedb8089a8af98869249d25b12f32aa6721ceb505c3","nonce":"56ddbe296e355bd3e429eea3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"1aeea6cd4a019e2f9b68f2bea7d44a2ddd13af3523ca3b4636c381cde0ff3889c6dfac40300847963f8fbf2eb5","nonce":"56ddbe296e355bd3e429eea2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"21b12960e7f76d3cbd3359714ad29b8d58ed7bf39446428c5a88d43b007322515685de0e067ba0292140d33afc","nonce":"56ddbe296e355bd3e429eea1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"901cad696b10530c0ffb781c447041e9dec277c25b8f54d8b3eb58956b379c3850c72e1ceaa9c6d9e8828628fc","nonce":"56ddbe296e355bd3e429eea0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"de3c1f7c448398b89a874b93eb716da6848bda923fe29cb693997ef99d230d1bb74996fdc9fd5b5bedb41c9a52","nonce":"56ddbe296e355bd3e429eea7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"d57e6fbf43486fe1657e52da46244834e4c7e73aa4f3b24e83c1a312c36a80d41f8a3bc3b06cf9183c21eb90f0","nonce":"56ddbe296e355bd3e429eea6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"32ea13add27359078fa52b82352a2147974158ff9f3e1a81016876830de4e27286104bf35f646ec31cba63ed27","nonce":"56ddbe296e355bd3e429eea5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"826e34db36f4b5abb70954f9f4ce76c0ff94f67fa5d6fb09a74dae44c8fe6d54604c65122565596f2d412d82a7","nonce":"56ddbe296e355bd3e429eea4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"82f91d282d411848f5abe8287ac6e16315468f7033bee5308159d985e446452ede6f8da4aae8726f3238e07a77","nonce":"56ddbe296e355bd3e429ee9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"1bf011c02ef0731630e7f2c43417fcd060a283a81447a338f4907d699ba980f1207b2382a186010692f1f57bab","nonce":"56ddbe296e355bd3e429ee9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"2cb970fcde545e255ce4095f088abb48b4b0ec56617850fc12d3067dd37eff5170f26943b4d15cc72ba6698d38","nonce":"56ddbe296e355bd3e429ee99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"332a13959316ef5d04e1cb1ffe798b47f5b45afc94ebb8ab95701d765463f595ef990bed2c6102c1bd78347ce9","nonce":"56ddbe296e355bd3e429ee98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"2a11f5b10abc38f3b7c230cd2f3494d9014a2c999ed5e0293692862c364ddd1177bc9c10bd76d646f83c2fc64e","nonce":"56ddbe296e355bd3e429ee9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"53d091ed284b96d5bc7e5fb6a29e10d45d02feae99c96c54c847f7e377ac121419ed8a9b30ddd6e0c9b7f7e8a3","nonce":"56ddbe296e355bd3e429ee9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"424de0768c701653349681f49d5bb6a039b3e07f1c7569d6a3b7bdf83952c886fd92cfbf2b5ab27f9336195fc8","nonce":"56ddbe296e355bd3e429ee9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"b9b52f0745cf1f28d60dc2283e5b402b67a468671aac0ecdf045f33aab9294d1f5d9221644fad86ec93aca527c","nonce":"56ddbe296e355bd3e429ee9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"ca40922f13fd27f3e5893816bf3f763aa1a4e7c87b15b2a27f00ffee1810f6457f567ad75bf2ed2f3eb15ab3d7","nonce":"56ddbe296e355bd3e429ee93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"8d977965ad292108a277d1b7e923ca8537a95e728a33ae8a4ea2ad7d558ce7fc505a77b70241e6825d358d2190","nonce":"56ddbe296e355bd3e429ee92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"a5e6a40c4efc60049d903b02af77b005c679d0424ff436150d74d02dbebeea54969920d8ed5ef9da0ef5c9ad03","nonce":"56ddbe296e355bd3e429ee91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"e34ba1c722f8996bf99f8b846551481b27f543574d3b999ba9e2f0763b51172de3d4edd416bcfb2c58d84182b0","nonce":"56ddbe296e355bd3e429ee90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"1904921faea6f6517a1650e8cfa96dd4a962fe6641a80b2a454a3bdc13a05c3406cc7a870c85b9ce7822a4553b","nonce":"56ddbe296e355bd3e429ee97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"513fecb905f665dde8c30b93c013eba72fb981a5f96cd1d10d063fbee46b8f3debf1e6007fe3fa8183a99430b0","nonce":"56ddbe296e355bd3e429ee96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"3cedbe5ca7cf8469025a79ef2d62cc76c963b869e594f5810f36e41e87fdefb5b79b4cd2a156a576e8cd9229e0","nonce":"56ddbe296e355bd3e429ee95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"1760ff1faa0fa7941ae8f9852acfb50cde2ab00d1e61289d9b843203f1097824be2453ae2358cad8b643c8ec7b","nonce":"56ddbe296e355bd3e429ee94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"d31b4cd6316e22289d1831fd7002726be2a29000aeccd7159e29335821092c5a14a4fb2f587108d50d1a401931","nonce":"56ddbe296e355bd3e429ee8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"31082889cc262f2a2bac827e1598bf062e31c6504e31a9bed0143599800ba0e4f388516d35b2733560d456f628","nonce":"56ddbe296e355bd3e429ee8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"058031d54592bf2d31edd9db2b670cecad08e564b6ea2bc605eb274b7b34efefa93e5759e4749b0a3dfbae1d1f","nonce":"56ddbe296e355bd3e429ee89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"91b08d5b1428f46d1e963e605d62a25b382c33a2e2aef739e7e809e5f074aa1593b1ace7bdffcafe1af846c65f","nonce":"56ddbe296e355bd3e429ee88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"468bdc9a1f79ae7a11825c5832f5152299886c7979ebceaa14baa5fbfd19f38e56fd8d5ccf3845022f611e1902","nonce":"56ddbe296e355bd3e429ee8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"a6b6fc66b314481da1e1395f7e14499a76bcd9786c348212fb19b731ea1a4794004cd116998da64a9e52aa23fc","nonce":"56ddbe296e355bd3e429ee8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"e53ea98c716010da99fc950e331fc1487774835cfd634676f8f106b13eed79a0476c124a8af9e9864a3e3e214e","nonce":"56ddbe296e355bd3e429ee8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"1159a8c0cdf8edf21c0a988e90461c9f84190e149632d73c26601c258b2f44ab342f180e2b7f55886dddabfcb3","nonce":"56ddbe296e355bd3e429ee8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"ac1939a8a40c67d5d8f6722100c1750ebe6f4dd0304290bb5a8d5262749d70c37d9f60bb4d2b2ada0d0513d287","nonce":"56ddbe296e355bd3e429ee83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"c2466d86b9b2c01e76166afd50b4cf1faea9366cd7f3c4dbb3a025a264ae2e4691ec283c96f83a5ce7c83f2999","nonce":"56ddbe296e355bd3e429ee82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"30e16e32f455f69f0754d72b2d49b9a57f8f24aa03ae5f2b1ec17ad7a60c9ce04b847dad7e2d85406c96bcf1ce","nonce":"56ddbe296e355bd3e429ee81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"8fd27ac8056f86282814d5b927080ccd73bd5b5b4c52569ceef34f2aa7431ec4392aa5bc1f30da5b54c1483771","nonce":"56ddbe296e355bd3e429ee80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"f7be1b77a6d07252e6194b106adabc457947ee21008ab3afb48fc96786f2380437c962ffbe666f59d6fb46f8f9","nonce":"56ddbe296e355bd3e429ee87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"6dd2aeaaa9bbc4a7d819f8d06b14b856e970c08617c80e561932e2e1eab2ad618cebbea137fae920e1a9e3b4f5","nonce":"56ddbe296e355bd3e429ee86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"9445bab7dfda5b0f850caf7021f5bcdac65050867283d3ef46a1ac195b3f29c484d90a5fcce08c7da6c92cf054","nonce":"56ddbe296e355bd3e429ee85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"2f7308faa24994c1f879743f2359ce9746eac0209eb76f25364e0820d50f0bb8e31aa983556cf4ee8986777d99","nonce":"56ddbe296e355bd3e429ee84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"d00bacfad1568914b40a1eee1a7fa224b90e7833d518e1eba576acad6dcc58138ecc9f2dffb7e942a53ff06f0d","nonce":"56ddbe296e355bd3e429ef7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"4a64f32f424bf6f99947382ce1b9407e3d06aa69372b9f2ccc8d30ff9bdcae1f"},{"exporter_context":"00","L":32,"exported_value":"d624af2a6029b92084ac93d6f7feba90e86dfa29534ff7ea7ca5be3349f3f7d9"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"1cd0366e7c9e440e82e0ae702acaca6326c0c16f6c21d40d62fa5cdb219a4482"}]},{"mode":0,"kem_id":16,"kdf_id":3,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"6ebde05d280592c7a8eb6b5e8b585bc440b501b25e11c0a9d74c0065fe6b7074","ikmE":"7e2492d3d12a07bc7a6170f94081a2b5f27d886cbe8a04cad56809ed05bd76a5","skRm":"0c830e8f9ba0e9b71d1101a7f0fa5663fd5b799356320d90a140d42cb4465922","skEm":"58d008d63f6f51010d55ae7fa4993327c7e23592a6132c1d6290ce8f2151b08b","pkRm":"04b5b1fda6d970cc31e53c65617403910241814f3795c0969aa3f474137a00ef6f9f9b2eb427e946e4989210134b403a92ed27c7d8be912ecd6e138d15fec601ba","pkEm":"04ee70c76ff84057dfdd4b36d98f515a896b4445986b6ebae6db85655874e51fcdf55958335532d35117e1e47152f7327a3d2da9d9e041cce6909ebea13bcccbb0","enc":"04ee70c76ff84057dfdd4b36d98f515a896b4445986b6ebae6db85655874e51fcdf55958335532d35117e1e47152f7327a3d2da9d9e041cce6909ebea13bcccbb0","shared_secret":"c2489b18d5e4893d62cd60ae66589c33224de3031c1122dc640a1fd59cd105a6","key_schedule_context":"00348df0879d37b2abc03cbb090b26b7856d998d2e1d2b6c4913ca1d1a15f8d02f8ddd20ee5a3a5e35efd67a36daa5e549d08c33c7ca402da2edf2676a0043a166126d2283b8301d36b48ceb2ad0e3cdc9c830a0de1fa6be934f1e16cd7bdd92c3db68c302c9f0692107fa96713cd8503e2844199970ac9f3f3afb2c0606a47c7c","secret":"f386880f66133e56aea7217b17ab18c628c06d3756b3cfd7e9eb27eb1216f9a35b4371039e37838848bdbc0beb619c2fbe82419bd97f8dbaf7ef213bfdc7b4e2","key":"","base_nonce":"","exporter_secret":"5b195486b06ede3bab6e65634025026350d02bfea8e19716db0279c78b4c7c93ab7d0b074e03a5b3d9b144641d10bf0d446154408801b24a3bbe7fc23ba0c3a2","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"f26af0bb6129657f9ad298e8ad80d66c370113c93f266744be1a5eb51d986f9a"},{"exporter_context":"00","L":32,"exported_value":"9cee8f868cb38cece5d5755f9d2b3c481f166d9aafa74520dffe3f4844a2f4c7"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"357f2b2019d51179be24d8d7a8a9ca2c78b7a647c900458a4f32342688b4c32e"}]},{"mode":1,"kem_id":16,"kdf_id":3,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"ee991b5a628b2d3f52137f38d00d02d5189862d25cd56d6a075e0a31649439a5","ikmE":"1c8d0ba28e80514ff76e19330eb0ed529b31460f6a2e67f630e15dee3708b178","skRm":"bbf28cebf86e104d96f5146fbb9663c35316c0dbacb8d35ebfd2eb2162ba220d","skEm":"5235753afd4bbefac8a59d8a30a08f810fbc8791774dec2689f4463b018bb17f","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"0497fa2f0a4b97095419088203c4bc5d7fd029b203a744493c7adcfe25883f491b41a5bcc2e93421a2574570b2367572d0947689a53090010e9402299dd56f13c3","pkEm":"042feed5a0ab8abab0dc13bb953582ee0c4bbccc75f3fa77df04892962c94911fcbf942e7cdca493dd4974e5989569d26ceb01e2776b8f85eae90a4f4a1c367ea1","enc":"042feed5a0ab8abab0dc13bb953582ee0c4bbccc75f3fa77df04892962c94911fcbf942e7cdca493dd4974e5989569d26ceb01e2776b8f85eae90a4f4a1c367ea1","shared_secret":"f61abbf11288f7ba0bc308ba8261e0432caaf9182ddac42e837f0e32df57900b","key_schedule_context":"01bf79f0cd476b163da0552371ed2726ff677cb56d40e4670c448d858ff167b9495c71f7837dc40986891dc6db777d3e0e19be3180991cb9f922b6b0effbaa4f9d126d2283b8301d36b48ceb2ad0e3cdc9c830a0de1fa6be934f1e16cd7bdd92c3db68c302c9f0692107fa96713cd8503e2844199970ac9f3f3afb2c0606a47c7c","secret":"5162748a0b734a98802577738955eb442e8a750647a053e104b7a690ceef42505c1920dbc8f972227b6ae9cb402844694ca0d544bfd120b00d199efbb5e2f068","key":"","base_nonce":"","exporter_secret":"266ed5e18dd83b99c70c7e176e98a9380aa7047a6a10c0ebbfbdcd52fb7d9459e74501eee085a124a1e414507ff8c508a23bf2de2f8adffa11cd448d5c19ebeb","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"4167360ee909986eaffb3755b3b47216f7b858e10d00a57a27ce337b19d6e887"},{"exporter_context":"00","L":32,"exported_value":"7eedde01dba92e66c25e3e5c9ebd74a10d3a41d03900b5173b5e3357e94b279d"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"b65dc7f943b882979e9a120bf2314549a754da581ad008794cb7a5f85e9622c1"}]},{"mode":2,"kem_id":16,"kdf_id":3,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"309613c25bd29ba9962aee1f0040bfc0c041cb0b85d52c15a5de0cf77ee9ecfe","ikmS":"275322331360c71f0b7036ba8d927cbde3609b4fbe90fe37461681dc4900f712","ikmE":"65a842c68426e448e615e0eba4152e8cbe6d817f3fcf4c81dae6876d1997aeb9","skRm":"4e38ccc89df8217eb903735cf39b3de32856993ef77dfb550ef96f77aef26801","skSm":"85365e4543ae9afab9c795a85e8a6916a0d8ca413e9cc70ac063c59a2734c856","skEm":"d4b00205143020b0f47559fae5bd7a9c0698ed55a7dd2a7777952a8f1e63ede8","pkRm":"045fe156b4966662e6c4295942d1ce280dc004805a79ab0e3ffac0610e299b8205773e03fb8055aa515567e8b6f1f3e463526febec9d176d8d0fa27cb507f3dc39","pkSm":"046b92ef977e834db95656c6f53c10bf07338a6bec594a8e6295f0ef4fd87401c230785b154f54e9d9769df0ac7f190e6f1eafde0ba699e89b5ef316fc9976619c","pkEm":"0480876d006572cc72a10f30eb9f1ca15a563790181fe380a6564f5fb26fc9b38afcbb00225ac50f64f3e2d58a46385d2a468b1479e6a30e7eb96f4b26bb77ecaf","enc":"0480876d006572cc72a10f30eb9f1ca15a563790181fe380a6564f5fb26fc9b38afcbb00225ac50f64f3e2d58a46385d2a468b1479e6a30e7eb96f4b26bb77ecaf","shared_secret":"cd6fd24d37d301b257164bfe30c363eba4740bd3fecc6c25ab48124f9b291586","key_schedule_context":"02348df0879d37b2abc03cbb090b26b7856d998d2e1d2b6c4913ca1d1a15f8d02f8ddd20ee5a3a5e35efd67a36daa5e549d08c33c7ca402da2edf2676a0043a166126d2283b8301d36b48ceb2ad0e3cdc9c830a0de1fa6be934f1e16cd7bdd92c3db68c302c9f0692107fa96713cd8503e2844199970ac9f3f3afb2c0606a47c7c","secret":"5d9874ef2b08aae664f9dd63ba7537091034e7a9bd30ec602c350ea435f010796e864202953e875be96b090d02d5797739c9bf15c01c13b3fd7c02637c43f1ff","key":"","base_nonce":"","exporter_secret":"c61aa19e3842403bc6afd6b0d98bf81617d93c75b1d60ecc139647c73c0c9c4b068e2ec0880095d7718d43da043df906889a50f474324c45c4c46ba2ea3ccb9e","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"51651ef6830127e8098e8eb47e2aad3aa7157b77bdcdbf48453ff9b57dfc8679"},{"exporter_context":"00","L":32,"exported_value":"0b118d3fee571ad2f58a7b28807c7aa078e4cf69f16044e3ab06bda83376b247"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"392045d6efea0e36bbe14955250e6535eaffd08f1c6113c63592762928927830"}]},{"mode":3,"kem_id":16,"kdf_id":3,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"78a66b2fee5e8ae1cfc883ba5e3bc9cb648877d0347071f0775f3a1ac615c1eb","ikmS":"cc0846a1b7d6858239f2729b025062967a256a45381bf7e91f54af5583059975","ikmE":"591e22abe467c3ffc6822636a5fc445bb471dc3a9e3c20f66137ca0a115ea893","skRm":"c083eb9aa56bbc979ceb825743b5d1459d026dea66d369f2bef75ae0b0735fc3","skSm":"a60097f911364d00a63a6c166e3b4871c8a4b6f516ce83a78aa0019ba1974533","skEm":"8c5cbf9aef5a7cbbe40d01c61f41df969fb618b4ccd75c1fd3cd3d3facec7198","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"040a68bc050b5883beb099069a155cdc3dc4aa3f0f342b39d0c1a80fe8d9958b897c3aba79e7dde9c1e3d01e38be95dd3af561a2b8519b1108220310c31b1cc03f","pkSm":"044f8ab59dd468edd2ea9fa40d04261f6777ad1fb886b42626b954f04fadfcdf32bf9949ea90cf030da6d346888c35b38ce34aebf15b6c08114effe13c4f177bbf","pkEm":"040b8827eb748400af31621a4f58aa0dde45821531d80d7ce851bf60c0cffb3128cebd806411892e8dcd0ba02634d4c3a4df5c77ce7caa22419b993995a840b12f","enc":"040b8827eb748400af31621a4f58aa0dde45821531d80d7ce851bf60c0cffb3128cebd806411892e8dcd0ba02634d4c3a4df5c77ce7caa22419b993995a840b12f","shared_secret":"ba88ad68e4e8e52b23772d52aa8d2d5ab31ea4e7813e0e1d1d41fd3951ca8fc8","key_schedule_context":"03bf79f0cd476b163da0552371ed2726ff677cb56d40e4670c448d858ff167b9495c71f7837dc40986891dc6db777d3e0e19be3180991cb9f922b6b0effbaa4f9d126d2283b8301d36b48ceb2ad0e3cdc9c830a0de1fa6be934f1e16cd7bdd92c3db68c302c9f0692107fa96713cd8503e2844199970ac9f3f3afb2c0606a47c7c","secret":"070d1faced2ca73b036b1fac2d705199d6f8b672e2a363905472487c2e9816ee44218ed529f813eadd3b5fad30ff0ba5252efc50c1bf1b81a0913143ca9ae9f4","key":"","base_nonce":"","exporter_secret":"14bfa906c00d0775ebe2fc5d0db614fa5c3f3233fac6f2b369fc3125ec074d6c14d4063f1a39ac809bc4ef5684fc43e632d6c1801adf9ecad0879365a3e93edb","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"2eb01040721842cda444a0b866d7f182ac371956da0296748c750000d58869ab"},{"exporter_context":"00","L":32,"exported_value":"3811c57d30eea944a47647344eac1cc54ea947dab1ea94c83f482f47f827fdd7"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"0ee444b0fbc008ec6c1464e6cbae20b9a29f7df5a7e162d7d9b72644402a83bd"}]},{"mode":0,"kem_id":18,"kdf_id":1,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"48330f7976f13f1e9dc796a5942d824187c0c4a37e36cdbbe7b943c80d7f8f959d1ca08147f9f1349cc14a150f2f8f17eadd5f402f42c24357f3dd6d2f020ff9e455","ikmE":"83ac7e73514c903f80bdb934437ca55e90437158889705ab3540a8743a42501f2b8dcd9bb3ff4b36f8d139cee5a6da08b74df2c9453ae4ca30403cd453dc6169a54b","skRm":"01d20da05fe4a47a6b1270c320348b12b31ceba0b753a87a8b74fbfdc052d029ec75be8074b0128674d0fdc5c7a0ce224e6a0d6e8ed25d2868772a9f3da13c67c027","skEm":"001547ed59c2103abc0e9bdd851116c0007b1823463858d745aef0c87169128ccc1d3210f578992517359cf8dd1c5d0e7a508dcc9da5371359414fc106c0db16f805","pkRm":"0400e1e7bb25a258125ed41a501a4a786ab11640072c5dfd3f2cf8edd6c6b0e2f2f5b555b63f1d0bc4db5557a6c47a480579cb7411002b27f156d9840daac7818e8ae300de90f9e2049c7b57ee642cec285286ae54ec57479e7c8bbeae5675614523b38ec95be06e8a70e17785092613d73b19b0a556b0e1ae809eb7806d084959f360d357","pkEm":"0400845e0dbf278071ad5e567ca4c0f73d8cf4644d31bdad28c5d9ea1b0a08ee3086be0ad769bf2845294e262367511419128d19b8154c8f47570285decbbb4cb739d101589b78d93558b2beaef20fd2a2341ffa9a081ac3d5eea6e671a5ca71e3bfb1b07bee1aa586276670e90fc71227c652213ca59f6e5b3bf37bb72d16a08d4cd43649","enc":"0400845e0dbf278071ad5e567ca4c0f73d8cf4644d31bdad28c5d9ea1b0a08ee3086be0ad769bf2845294e262367511419128d19b8154c8f47570285decbbb4cb739d101589b78d93558b2beaef20fd2a2341ffa9a081ac3d5eea6e671a5ca71e3bfb1b07bee1aa586276670e90fc71227c652213ca59f6e5b3bf37bb72d16a08d4cd43649","shared_secret":"667aa1dc4c185408193c8dd9f0d82cec80b31ab0bb4942f3f89ca7a053f201427ef4c96271e31b99bcf085622ed02c2df941be07fb30a94ce3457d2bc296d485","key_schedule_context":"00a0f09fdb725155fff851d16495e4a128f92a4332225913d832a5b87e19a5552b2c567eba65d69b8f94f5dd45f30ba15730e09a0ca1bab72cdd2606fd3e4a6c69","secret":"6127f109689dfaf5720d18a38fc2dc28b3dd70593133c27e3c7ac8d4383aa433","key":"5a10a40aa2a0b6b49fbc04e7f223add8","base_nonce":"4a530fc506ed6f16ed5a7556","exporter_secret":"b561a79137782e821f39459ccfe1baca891d19c00ea1bc046d31b30886954fe4","encryptions":[{"aad":"436f756e742d30","ciphertext":"db111e0c170f739ec7a73a992a4745c8947bf7c609cd961a2bcd2f20f44b6549d4a84a466929405a3a002a05d2","nonce":"4a530fc506ed6f16ed5a7556","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"a3ea70657378fa451b77f22b2021fc5d172842e7c2ef6728f41b57b5d53e2ff1e4453123581232b8c51628e2bc","nonce":"4a530fc506ed6f16ed5a7557","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"9e396042bec223725aa0b93dfedda9a748847fbf8757cd15a1bcf540cbcd2df186d044708ebf7984320a0c4f03","nonce":"4a530fc506ed6f16ed5a7554","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"63432df3d65aff0982c05fd8b7240ac4b9c5852fff6725d1144021ba185b302bd4c06af38eb2a1007776245cd9","nonce":"4a530fc506ed6f16ed5a7555","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"d5d608c7258b46187c3f01f04bc5ed76997184b302d3d9ffd35d39395928125694a6983f3e3be11acc2757f92c","nonce":"4a530fc506ed6f16ed5a7552","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"fbf7c115dfc73f4f7086da702ab73eb3039ee4d33483f95cb7777221afc0e42f0ae8d681057c39eaa216583679","nonce":"4a530fc506ed6f16ed5a7553","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"1e87887b592499071f609067a56e3b934e45215106b7e4b62f3251fcae9b691464adc1feba600d19b194a074c9","nonce":"4a530fc506ed6f16ed5a7550","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"73c93d274f19c23b5974e8a795c761581d65b0de5fb4625d914f4d268a8fb1d228d3a3dc1716c46b3f903fe255","nonce":"4a530fc506ed6f16ed5a7551","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"105ffbe882e04a177494424dddb5780d501d58f2f9814cfd3568babd347834fee45271400c927fa44c25025d14","nonce":"4a530fc506ed6f16ed5a755e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"c86a0d677f1eaccee7a3b264d1a154bc57431cc67c2f231437ad5490ff6c5098ff0b6bd53a86eaeb3f27ea14d2","nonce":"4a530fc506ed6f16ed5a755f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"09fc38a571f4f1c2e33f2a930126a1a209a8ffe54083ed92a474f5139f914bd649aed6efc2a3f528477829e74a","nonce":"4a530fc506ed6f16ed5a755c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"80e21af729c1582e2329498c0e6b41734cca6a2615e6b67475d3675c3a5b6011d77d45cbbff057ac710ac42ab7","nonce":"4a530fc506ed6f16ed5a755d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"8a04ea75c4906e839a03804e675ac09b74272c6e0c23e6e17a65517a66cdf2326035d5d5cbc785f5fc11ebeb96","nonce":"4a530fc506ed6f16ed5a755a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"18c5861062ded3c8a9b695d01a165f9e8864373e7bdf66379bb1a188fe0077cec43876f58007dbfc9db089b3fd","nonce":"4a530fc506ed6f16ed5a755b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"20c43a92df6d7f9e89efba31109353ac4f9e581fc4e477a6aeee8ca811a5279dc25e67c59d6f68d32e93973997","nonce":"4a530fc506ed6f16ed5a7558","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"428e292f3c6db23ac7d7d69e17f65187c8364d607250440e97dd8888741ddd6ee5182b9cd085f32c76d8934325","nonce":"4a530fc506ed6f16ed5a7559","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"4f5dd6c25a4743a0a42d955b16b6f82d8b8740039f4edd4a89cb5f192b710a7b72041f26b4fa56a46a3de4d5dc","nonce":"4a530fc506ed6f16ed5a7546","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"67516dd9065605bf4796940f793a5af25da3b0236f4e0c20afb8ae2dbe7f8ad8f858f5b2028217c450bb11bb43","nonce":"4a530fc506ed6f16ed5a7547","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"104845b78ad94ff2da3c4bd7b1dd5f70f5af743d084ea842bed74f460d1b64c4a1c365b0a905fd994d64892cba","nonce":"4a530fc506ed6f16ed5a7544","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"72508f710432fc24ae3721e5b50f7bd86b075b942439f0b8e115ed546b9b4b16aaf21d34a0e113919188de14df","nonce":"4a530fc506ed6f16ed5a7545","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"cbb00169dfa83ccdb5ceb8254da65857ca9d353f2a9cb027ac377a82b00e7ab585561505733ce5daefbe609719","nonce":"4a530fc506ed6f16ed5a7542","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"fc108cfa91782d66c05fa667273f7f166d4a042215b0d258cc73998258549b5d6ba42e23d10c3405672f4869cd","nonce":"4a530fc506ed6f16ed5a7543","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"fdbe2aa14d85be05a897a1f5e4b88d3ecb6648564c21d5e8bcdd76281063c1e37be5fe20b79b6eeb8e1e23f007","nonce":"4a530fc506ed6f16ed5a7540","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"38b312225e7f87c78374f00e48253e1157ed04d77e698c15455b1751bea9fecc5715e87a3babfc497f1de173a1","nonce":"4a530fc506ed6f16ed5a7541","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"9f5abb743bad28402ecf474f0f0c21d7769a8b3f9467cdcaae82d2a3cb8e39beb5c804d8e738ced4ae4a37c060","nonce":"4a530fc506ed6f16ed5a754e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"e5095b9f138ec07812f7e5cd97d0cacf23bc9557dab54703b4debcd56f2cd4f8c663a22a78c567e25bebb1bf99","nonce":"4a530fc506ed6f16ed5a754f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"af976cda1d668ad7e44f1dee4ef25856b39b89904f2432814e0afc0b3573b22f2ca5d7dc53705f698ecbfc95e5","nonce":"4a530fc506ed6f16ed5a754c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"487331a3efcbb8a86fe460d05de0e851b9333785c11fe69a85b296dfd36d14c5c89e0f9f9ed0d17f69b8cb91f5","nonce":"4a530fc506ed6f16ed5a754d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"a491829848292780122b109f346f6cbd7bdd4463b311df8ea4db25413649ac78569f92f1bebe69fc955ed3e9b6","nonce":"4a530fc506ed6f16ed5a754a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"d86a654d4cd1570c385c61d8c65d51800fa72933f5ffc9eb5c355c62edff9090287507ca297e8f8ff7f99feadd","nonce":"4a530fc506ed6f16ed5a754b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"d953fd301fdea6b9060654c8294f3cf05ea4b2985d9eae1ef9c905baf6c6430b61592a07887e23b62aab8a0ac2","nonce":"4a530fc506ed6f16ed5a7548","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"0a38e763ffc0a8976467dcc165506ccb0b12b7983531106c2a9ecdd6d6e94d035689698bf3794a4e4b0d46eb9e","nonce":"4a530fc506ed6f16ed5a7549","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"ebf313be4953a17d915dadc24bf6c0b03dd8e6dbc6a68203a77d08bc1898a871f96faecc436aed370d8dd2c926","nonce":"4a530fc506ed6f16ed5a7576","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"c5404b4377c9a521a9dffc144d119c892db57828e2a9bdb19d7634274bd810557124b5039a4f8938de35751492","nonce":"4a530fc506ed6f16ed5a7577","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"d719a4fc9995e73940f63cec40b3a81156f7d6f8dd7c521276060f13caedad75bd44c76643de6b4ec920e0d0bb","nonce":"4a530fc506ed6f16ed5a7574","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"48561539574b4597e9f8c493ed10f7320eff7b2c1b751dc1d33080cd3f887ecbe7693668bbd36f132b2103080c","nonce":"4a530fc506ed6f16ed5a7575","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"3e18262ca5dd46f6eed95b5f633d4efbdda501600992cef8cd52d440e817d707f5a659136c74cbac727e2fc447","nonce":"4a530fc506ed6f16ed5a7572","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"fd75a70b163da9a337dfa8fd669dcb796689f40a9de06b7ec310c51469bf5763c045e766ce1107140bbba2eae6","nonce":"4a530fc506ed6f16ed5a7573","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"beb932adf2012ac11cee517d34a74e3123bc3b513a80def20f4ccac500288b977e4f0855d616c50c88b0c345b4","nonce":"4a530fc506ed6f16ed5a7570","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"c136f70742f211704e4c61759a5d954d40f538d2bf7eb357a29faf4af036cd82442ec519e024ce3e61440f8e19","nonce":"4a530fc506ed6f16ed5a7571","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"9071fd35f76d8e0c51a8da1c0451830fff70183bff7b1790fad593ea301ce5bb242250f9df7ec586767806c4e5","nonce":"4a530fc506ed6f16ed5a757e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"ffdd9bf85e23d460969a91f6971b0f0ab690ecb0f2c1262d7003e28b97974057da234177fcb7a8c1f0fb250fd4","nonce":"4a530fc506ed6f16ed5a757f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"571c35a1c7f49e4c1740675c6a042a17a673d5bb8a992b1692352af49579ad06b6346e9a8c3520dc234ffde78a","nonce":"4a530fc506ed6f16ed5a757c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"020d17e5d768e362ab62f5645b248111eab5299172e3f31185103d5e33aea88851068e65034db8808d15b61c33","nonce":"4a530fc506ed6f16ed5a757d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"a2c9eef4057abeb4b6d45bb35aa41d0e6aa624d9e42f04159056cb7e38202a754c48d7490808e111460e87e9d5","nonce":"4a530fc506ed6f16ed5a757a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"4127d15724805735dae47f22d8491d0ffbdbd44651ca4b5fe382c9f82e0ac844503d65d6951cbb91ab7e2df024","nonce":"4a530fc506ed6f16ed5a757b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"5b1c56253a4110efbcb93637b9e1ae5b82416dc43ad7bb942475cd52bf4f958a25767670801f4f9316f8f2edf5","nonce":"4a530fc506ed6f16ed5a7578","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"0135a383db2969e62e6dbb3dede35adc448f848ddf0e236733252849a72e1f2802ff33fd113d3896d66e7c2317","nonce":"4a530fc506ed6f16ed5a7579","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"aa6ab4f1151245c54e23c1058dea4b8959e68875e5bf8064a6c140d2fababe2cc398aeea82f90ba8db049b9b4c","nonce":"4a530fc506ed6f16ed5a7566","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"5a9e1854af317ed09c327d7d0681bb8fd834ff40b7769dfbba72d0f9613483a75df41be7746f1421d4d5eb46fc","nonce":"4a530fc506ed6f16ed5a7567","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"946794a0a0ca8cf35e6d4c895bb2a9e8b3d4b50acf01e29b8c8aaad51ba45e8f1544dc0d09884a6589dfed8884","nonce":"4a530fc506ed6f16ed5a7564","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"59dfacc376dff565412a898d0cb89e7000b24aa9e541e080a99b3aa30e497271605102e6239ff867254d326fa5","nonce":"4a530fc506ed6f16ed5a7565","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"96cb7b9d2e72153404dc8ab28154ea202ffb7d3e60893f122232be6c91d2d271d9da12a88e37b03cfa50b1288a","nonce":"4a530fc506ed6f16ed5a7562","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"da78a68001d88e0002e3286f2a75d5fc60ddbe47407b2af6ebb044104111af862fd22d78d7bf8deb5bffcb3fa7","nonce":"4a530fc506ed6f16ed5a7563","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"be65ceb6e2ea78b64035c28f98c0b46ff6ca89f3d65610a1bbc94dcb7cbd0ab34aeac0e47ffe5cadb5e088d412","nonce":"4a530fc506ed6f16ed5a7560","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"1da294a1bba75b9c7008d481719f152a12cb81b9c7ec457de22adbad2b4a9a6c67c109e3d709ac50a1d8615553","nonce":"4a530fc506ed6f16ed5a7561","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"62c7bd83db7aa395ac8e37da249f0226a5fd1075d85260eacd5e6c3e173a7f53a79e1526a08925e023b693e360","nonce":"4a530fc506ed6f16ed5a756e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"481af88d13509320c920eceed8d65a3e9c45fee83ab4c57783c120429c816145e55a0d434a2367cabf65f3787c","nonce":"4a530fc506ed6f16ed5a756f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"6c4b43b446c7f5860a5150af6d920c09067ee00e5a2b3ec9b0d48191a685e15e0bbd352f36fe93045a26026074","nonce":"4a530fc506ed6f16ed5a756c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"15eb4d4d25aa77754c1988f0da9ae5b28279401db621504337bbbfd5ec12fa2909932503e1379f80b4bc3abab9","nonce":"4a530fc506ed6f16ed5a756d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"c09e8079ee69da67fac3d02dcaecb029659d1b53bf1dbf00a381d10f14140a825357706774c9f7bc198df6eac5","nonce":"4a530fc506ed6f16ed5a756a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"936eb7e7e4c9ec346bd6a0b6607a924a20b66b57d6f46f9545c815bf4b8a33ee4dc6c214043a1a203583b20175","nonce":"4a530fc506ed6f16ed5a756b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"86d912ac3e9af43ad4cb8e77c8960231f74b48902d3eba6684dc5dffaf969919534e79e374628af8222501c276","nonce":"4a530fc506ed6f16ed5a7568","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"d31f43b10f57a991db5092463a038fa1825e91172531a9143577422ed0cff2e6f2bc77c5c27ed699c3a1f4c52d","nonce":"4a530fc506ed6f16ed5a7569","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"b999a3a18593b72e900335c1104b6ca8c9cb25a39bbaa4ea06fb82912f99319a5c7657729d83b21d7c0a07819b","nonce":"4a530fc506ed6f16ed5a7516","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"61c160449622e774dc97847fe8330f1c2f1eb6c3a501b548cfc7f8474cd0ecd1dc6c9c0069def046d8094ab76d","nonce":"4a530fc506ed6f16ed5a7517","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"69d535ff38980fb4a5c7441ff94d87c24abd943948b2f686cfb8f74c9a093c567771e329fbb6cba6ec81a0e30d","nonce":"4a530fc506ed6f16ed5a7514","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"251e944166ea630cbb0f4d622b843235e4b226c2ecba73a1f46fa935603650dda200911b2bd5f2e09538ddd423","nonce":"4a530fc506ed6f16ed5a7515","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"77ec479859828d7e644ef252eb631b9d6bc569fb72208a397f51b5f177fafc044f764bf258405a5b53617cd1f8","nonce":"4a530fc506ed6f16ed5a7512","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"19e99980aad8e27aa96567d3b90035b88c17cdf1ab072908bea4ceb8bb3d993f2f9971b10ce9061c29254d0e20","nonce":"4a530fc506ed6f16ed5a7513","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"97825584a43bdf062eebba0b709989c1f23f88d7251743703ba6b4da9f075658e230372056efaeb4072a3c5066","nonce":"4a530fc506ed6f16ed5a7510","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"f329107faf7c51751d5babdaf482dd3952a879e3eee7591fc1c8614a959ff8e914f874dc74351e1740d523da2b","nonce":"4a530fc506ed6f16ed5a7511","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"c8458e9ececd813751296c8b0bb78debb8134d98d9bf254cda9f5dfff2f5875aab4c30c7cb646794358e868c41","nonce":"4a530fc506ed6f16ed5a751e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"3d85219b65f0099d3a949449c1580ffad9cb42d07d08e2897bdcfa397684a48355e59d8df4c65a967469caa646","nonce":"4a530fc506ed6f16ed5a751f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"fdff9be6f5d6f170960e962fde0bb98a8130c4af54d6a9f41e52fca3c8ca679246437185093627c365cde854c8","nonce":"4a530fc506ed6f16ed5a751c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"84526a46a385a968259861a34ce82097d5531103b2f14e55382627f61323778b0471f8bf8acba02a10081c6e7f","nonce":"4a530fc506ed6f16ed5a751d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"46dd82ff2e45b1ee7d1bf6ebae1a489c7ea4cc88552df1b434e94d3eb6c28aca8cf26c198b5289fccab0eb0694","nonce":"4a530fc506ed6f16ed5a751a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"498e64a3bfcfec59dbde5fc639f31bffb8b69c9bff8c371df9e28a88a9f7dad25a42187d1d11915f102686bba9","nonce":"4a530fc506ed6f16ed5a751b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"77a31d51b4f7a2e65e0eb1211ca6cae9967a2507ed6ec40a9fb9bbbe1f582df79701181662f86893dff56f54b9","nonce":"4a530fc506ed6f16ed5a7518","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"369655bc2c7ab760bd3de6208a9938c43db1febc7fe711bcc9543da92075ded5125667dcf1c5a6d2f263ad86af","nonce":"4a530fc506ed6f16ed5a7519","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"f2ad84e28319f8fc66aad5328c86bf6f3e6252db2d5d5b32f0d54f7961ccd5e3aaed68fc1e65ec652f4538c9e1","nonce":"4a530fc506ed6f16ed5a7506","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"8efeb1c2b3a3a86486dc67649b9a7b397e5e50edade6f63a287b712f770ccb3c99af0bb42feab7df45e4709e46","nonce":"4a530fc506ed6f16ed5a7507","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"ba0f60518b90f4622b12de97007271518816f192a2120313f17994c79e1cf35c9adc72728a884e50717a26e46f","nonce":"4a530fc506ed6f16ed5a7504","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"dbf09d3c0bdaa61113fbac84b15d53f995cf2647f3b5386f1f9b576493b2b860fe35aa171fcb4ea00f7fad2d59","nonce":"4a530fc506ed6f16ed5a7505","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"ba818238245fa2fc1eef9e2a76c18769b71af061afcdab63dc15e6c9200de8db96b4d5018c608380e1c543f280","nonce":"4a530fc506ed6f16ed5a7502","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"14ca9d6881a0cd31fe04d0d06d73fa241aa5a2a8f10fc401acf4f17d24891be61c3193d31f62ff3be1402f383e","nonce":"4a530fc506ed6f16ed5a7503","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"9a3de4ec2687717a1f0801504314d4d17b130f0d64a93e4a7e2a21299c2d459678e32402d9ecc89c39f522686b","nonce":"4a530fc506ed6f16ed5a7500","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"6fb8a1de0404618a504863844a1d50370ed420186be1630a2f5a31ced030064e8f128f02e0a6cd09925cc3171a","nonce":"4a530fc506ed6f16ed5a7501","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"8f39fe77d1060f993152fab4c701ae5b7a8ebf1b91d6457a8dab37777d795e510c83019a948a604412e8f4d6ca","nonce":"4a530fc506ed6f16ed5a750e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"f85cce7f2fe0115b64b6f28fb6839c29788407a61573936beb8741c46489dc6ac946c59e736b8c66c23f41629c","nonce":"4a530fc506ed6f16ed5a750f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"423ad6d52fd51dce4e58066a47ce683dc222ba817d0ec36f82196a3f90275638e6e7d2de19aba079c15ab6cce5","nonce":"4a530fc506ed6f16ed5a750c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"0a3b32ee12dc564d62e489e4f046aaf7897b6a6292dce01f1fc531d821e66703f6ec9bf52d6e8685ce60f1ad1d","nonce":"4a530fc506ed6f16ed5a750d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"e433d6f55afc520863bb570f17e76ccaf206acc4a0f3c4ca39346503c8024552e28e14e1f709cb933ae8b36234","nonce":"4a530fc506ed6f16ed5a750a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"7135fa208690793ad315f870341db3d1d36199dc7584177c576f3a2e7200eeb3bd420facb888774e616cf6438e","nonce":"4a530fc506ed6f16ed5a750b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"31bdebee196a0aaa7967ff8355eb5d68bddbdc4cd81c54030ead9e7f2a8eceaf66f49d33ef01bda108b76d704c","nonce":"4a530fc506ed6f16ed5a7508","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"083de00947dc06a0a9d39e20956ba38ec3c67859e2197a47b0d3407ab4cdc5df892be476f66b556a6dc15b56d5","nonce":"4a530fc506ed6f16ed5a7509","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"b21412071e09c8c2d3157ff564527af6f7fcfc47acd1fc1f143cf692ad9c0a83b23a54976e0e65ca926fadf222","nonce":"4a530fc506ed6f16ed5a7536","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"277c371c18988de8ab9d62a44288f27e559a697f666c1108a761d29538cd20de6a549a5f4fcb6e8726c43db023","nonce":"4a530fc506ed6f16ed5a7537","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"aeb807dc0ca4e68c768c7b72f1c687d76e67dc149e48fef9c1af084a6b131ff4e06b7da8b02289558e1fbb1abd","nonce":"4a530fc506ed6f16ed5a7534","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"565000240fd4916816a89e73f05dfc0e58a01a422ef790026e0e2d4b2ed4ec4bf814669d4f4f2b8d0e16cdf7a9","nonce":"4a530fc506ed6f16ed5a7535","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"11bcbaa306343e2e78c39f240cfae3bf9638049c29d65ead01742cfb032497df207e2652d336145ead7f1612e0","nonce":"4a530fc506ed6f16ed5a7532","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"362431d76e4cbdd1a9c64aaf6f8103a83ce6af3104ededacb00ca1df5a781e5478260e9a12f6f6158f75024451","nonce":"4a530fc506ed6f16ed5a7533","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"f26d4764359fa735b4f068f2f77fd8812435c8dce880df7e54e4a248994746ac2a2e025c978e602a4700c8db89","nonce":"4a530fc506ed6f16ed5a7530","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"87abf27ef3066724fa2d1e805ed3a3aa7816abe911502a2d4cdd3ba0dd43f5f0d0ea89d0dddd053d93da031a70","nonce":"4a530fc506ed6f16ed5a7531","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"3ca8e6677e6dc43af7bc98f935443587fe1b601f2b51b1e7afa3df9120464d88bba91aeea9ccab3d57bfa5dc3f","nonce":"4a530fc506ed6f16ed5a753e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"5e7f859c661ac30fa30eb6532d1f8b154a5f124055f3ffe8e8a4f5d38cb03e45a1c040d595b5c6ff22aeb0cc84","nonce":"4a530fc506ed6f16ed5a753f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"4f83d1c1de8b1d76fb93347642ca807e9a214a24b68d97c01bbfa13bba918eea1b0183763897ab3dcdc770e0d7","nonce":"4a530fc506ed6f16ed5a753c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"00bc7187d43241c145b0318c1d3950bb0a33aec0f6c55a91507c5d2b6e17a683ff57fee98579a330d21427fccc","nonce":"4a530fc506ed6f16ed5a753d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"5ab5d17d6855dda0faffbed512e0794ef227cb5e624f54b15adfb0da93ad2dfb909df47c67c830b538c10076d8","nonce":"4a530fc506ed6f16ed5a753a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"d34101baf4ce672e2630be956e1579174f2b2ae486c6716654bc78c11b349406f62a09119312f52bfa3648b626","nonce":"4a530fc506ed6f16ed5a753b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"88f445cceb73747e00ad2d9baf1436ef9db702b772bf2519de0079718ad6fe4d67221f659f9b72313785a1681d","nonce":"4a530fc506ed6f16ed5a7538","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"28e87ec52052fb5513e00774d7ebdeeb5f21041abf94830893c287b7532890a917c109ba0b8fbfb170ff7f3c5a","nonce":"4a530fc506ed6f16ed5a7539","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"e2b3744fcaf38e26a7df0ef7933bef195a7d68d495f72691cbb23d5b4171bdbaf5b963aa0e4391ef678588a99d","nonce":"4a530fc506ed6f16ed5a7526","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"5ed3924d9258b847a158d75ada80dddba53a856abb1989d1ebdc92fcae04e55e98b1cea3dcfac8fbb6cbfc5483","nonce":"4a530fc506ed6f16ed5a7527","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"c592162ca679f1f2405ffed7443e39f70e7fd8a4c3c4e4fd2e6218b437b6c124815cc99587b3119c0121e06c09","nonce":"4a530fc506ed6f16ed5a7524","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"6fda006cae43e8b038558c6d29026120f42eda41081961e3c3c1eddb3d17fe2ea4c66e396884941eefff4b258a","nonce":"4a530fc506ed6f16ed5a7525","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"22bb74dfc25637800076f6e1e2dc3a08297b6bd719ff40dda7275d3adf01f8114d057fecb70b6482cc7913ff4d","nonce":"4a530fc506ed6f16ed5a7522","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"4ec485998d431b2591bd79b01920828b1717c46f3a17adacdd7e91f6d5f7324b58c1e8e32c3db8d68d670c7f00","nonce":"4a530fc506ed6f16ed5a7523","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"a604401b7f5ddfc5e234b7113b2952742ee62f6bc0fd19a44807b15ee827a50d61f30c8062c11376128de9b28d","nonce":"4a530fc506ed6f16ed5a7520","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"e3494c9fc41743d4f170e676564840cfc4c83d9d8a3bac5b046fc0cdd4d5719a39087af717066f7bbf0d6b7f17","nonce":"4a530fc506ed6f16ed5a7521","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"098e57eda415af49028105442987b0992542e5660c78f33e7c412123346aa30ba3b8cff51276a1b97814d1071e","nonce":"4a530fc506ed6f16ed5a752e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"aa41ae16c0d8fe730a46e29e9c5dddc2a88ca331fd71d9eba7ed41102a28760e1b73d617d1d7fc2c987fa5a578","nonce":"4a530fc506ed6f16ed5a752f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"07d78287c1604170f95fd3797a747e23dc72274c22c4254599352c220f1e87f09748c019e2c455678c503c3a64","nonce":"4a530fc506ed6f16ed5a752c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"d4b76f36f520be13c1b7bf3ff3b1d8657f32d9d2a7508627e140208e82186f4cba86d1b7d62a395a9faa9fa344","nonce":"4a530fc506ed6f16ed5a752d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"5a62fa9711f2ec3543457866e70354b3d41f3bc0f20588a3164fcbbccb3f08e89efa1e7199022ad9ffd8e475b3","nonce":"4a530fc506ed6f16ed5a752a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"02b317070a4693b0ce98538da4a922911f5d22d3282d974a47cfefa16abbe5306ff6a4b8eb65b54d996db7d219","nonce":"4a530fc506ed6f16ed5a752b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"9d9b4ad901d7fc75986624ac4816589308b8c2a1656d56488bb5b41c13018e07ebeb00c9946b7833879fe89d30","nonce":"4a530fc506ed6f16ed5a7528","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"408b71c57505106987b4d2f1285d4f078a74ec1242f425d8a3ad408c6b1e8420ee256ba685fe92edd4e7155b0f","nonce":"4a530fc506ed6f16ed5a7529","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"5a584a3d590305e3f8ec98b65fe38e009e53bce608b846221ea9b6b6724a1a28fe6b39ac085b934512a8ce9fe9","nonce":"4a530fc506ed6f16ed5a75d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"1ad5b7dcff1e3e3b25a098ea85a747204767e0c8af6674750c45b23245dd3cc69bf74bd47fde77fe1b42f5040b","nonce":"4a530fc506ed6f16ed5a75d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"59f6183a925925f70c106348edaeec8ce7d035044e247d257b615665ce1ad3666f04cad8c8ba08a0e236bccb1b","nonce":"4a530fc506ed6f16ed5a75d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"74214d5368d0db4f902cf4782f3a7288296369393e8e83b5e1828c7980f5e5c87a87efb3cc6cd9f5d9cc739cb4","nonce":"4a530fc506ed6f16ed5a75d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"4c950965448e50bd0abb676cd30b706fa593bede13e66042934220f5c12a92ac4b10b68b6ca11c0afc1a8a99df","nonce":"4a530fc506ed6f16ed5a75d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"1db6da13ac9d515a9d357a19dcb27b3acdfa3d8a5abded6fa2689370528f9eabd6cffed667685118b948b23e38","nonce":"4a530fc506ed6f16ed5a75d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"43ae90c361e5de2bf3fb4bb56a09f399260db474c1c30ccc4c151f38683a829a843b562a3eaca5d7f4301ee251","nonce":"4a530fc506ed6f16ed5a75d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"68e3156dc955357297be6bc88e23ca99b66a1c832222f1e5f6ad88f54ea3c5acf111ad020b99b72eeef33b2441","nonce":"4a530fc506ed6f16ed5a75d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"bf741807f1aba975084761dd09fa3cb7d48f4b1716d3ad7a44f90af0110c5dc31bd3e4cffda5d02f72a26a0404","nonce":"4a530fc506ed6f16ed5a75de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"f7a514a76f3da373223957c29f938c985970c29ac54f203dccecaad650d8913d8ab38e188f244b922d273bc544","nonce":"4a530fc506ed6f16ed5a75df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"4d852d70f45d35f0b5b79dc902d14d178838518fefcd083cb9f464e297a2422dcc53d455c1574ab5cede5d2dbc","nonce":"4a530fc506ed6f16ed5a75dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"32bea7a404f3defdaa88be865573b53e5aba636e9815a4aaf007b0ce0619451710512e7d7479fedf25563a2745","nonce":"4a530fc506ed6f16ed5a75dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"b6dc9956a0818aae9555731bc1023b812a4379893ffae2b9aa5d9294e22511719675dc859917d5395c7062cb92","nonce":"4a530fc506ed6f16ed5a75da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"c16684b6c844b8d6488b9c8e1e20e4de12eb176bcbc424d1a7bf9b02e2abb65c1da13201ad2cf6b072ca6bbfca","nonce":"4a530fc506ed6f16ed5a75db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"021a361ad36d2ae64ad6cea6fe2cbf1027c0c51ed14a29a3094457cbb3cfa89301b04acb4217ff1cd46cebe219","nonce":"4a530fc506ed6f16ed5a75d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"994d71ac285da0f1fcd801a88e01edaf8dc757c1aec7fe9cbe555b36bb37c344ca603aca91d6eaeb63d305420b","nonce":"4a530fc506ed6f16ed5a75d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"93ded3d79eebf9ff569da82388d6e573e7fd1e6c60371ebb16499e6a0ac54f69553775cd81dfaeda41d30da7e4","nonce":"4a530fc506ed6f16ed5a75c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"f90b7ed3a0dd91ac1431291b9d1af0d3b0ebc988d0ff3951b57f395c89b8764ffc7e2c279fc9570043a5aa33f9","nonce":"4a530fc506ed6f16ed5a75c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"44a8500e603e6059888d4ff64c32e56f1fff37a1e27df0fb5280032ebb6d2463a55e8b49afe3a593fa25f52d55","nonce":"4a530fc506ed6f16ed5a75c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"faa8b627355a3f4e3905f99e47c2987b02f7aa1c71eda39f2bda038b920b0bfb06987149c6ffd9db3c0a88d7d7","nonce":"4a530fc506ed6f16ed5a75c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"18eab31909751eff50f0f670b90651cda8fa0811c6576310d8a22b1c3b734d17f198f4555a9eb132c0c99c0d9e","nonce":"4a530fc506ed6f16ed5a75c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"5e737b9a6aa9bef679ea295341957db1a5b757ae147f79879b32ec709293520aaa059b809e798000a735cb451d","nonce":"4a530fc506ed6f16ed5a75c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"d83980d64ff95550fa16969113ed7fa9b59a13ffc5828e21bb240bd7f08d7cab2e51b9079610d6480b982afd37","nonce":"4a530fc506ed6f16ed5a75c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"c0855239bda8704d841b07a8f4a9c7f427a1db95544b818a32f898535f57a22c821bdc97973f5e4865ed3a915e","nonce":"4a530fc506ed6f16ed5a75c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"38ea5597c3bc376e2526daf99bd578a6b68348b21ccbe1378ea20596b41bf8c3ba13ba1483c3c0b672216bd7ed","nonce":"4a530fc506ed6f16ed5a75ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"ade41ab28711b3fdfbb08f08b703270091c97067f4d938c596b86c867aaf297940d204b663a21fc84f3db6488b","nonce":"4a530fc506ed6f16ed5a75cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"e2a9e23985cb8bfffd28072d8d754d523a995331cb03ce58c002391dc054fd1f2457e47218e90bb526d1fbb4ca","nonce":"4a530fc506ed6f16ed5a75cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"3842aff13646774977cc2291a9be7c2a4ce9cf5b40d28a07dc93ec7b23e077a0dfd720facfa1785c9ee28648f1","nonce":"4a530fc506ed6f16ed5a75cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"ad3adeee53887e669d0375e592b79e89b325ad4028804c33c7e39238dcdaac2f9f172cd24044077708e0bebdf1","nonce":"4a530fc506ed6f16ed5a75ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"ab9d0f4f0324fa007e241e18b8ec8044c84c1cfb20e99ef97a4aa534dea15f869ac674fee5a9c4f569dc4c0749","nonce":"4a530fc506ed6f16ed5a75cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"4ef136ccf7b7804e72fc0a6037879dfc3b6b69435e6a393bb17e5d326252385c6518328c695fcb317d74e1ba06","nonce":"4a530fc506ed6f16ed5a75c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"b9d2a86df12b6af704fe16171a606d6d30d52d57761867fd0272ab58dddb7b19dd795e7bfe0a52e4e3124033be","nonce":"4a530fc506ed6f16ed5a75c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"79b401f7143d506d9d3d82b15053b6b0f42fa57cdb8e1b7e5c54d2d1bba76b01705ae9cbfb409698f94944b9ac","nonce":"4a530fc506ed6f16ed5a75f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"49fefb02712938a22b4a72a16fea4b27d635b99a633ae28f875e504b2d1eb537779e7c4f2a01e909200ba9872f","nonce":"4a530fc506ed6f16ed5a75f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"9e91d899991dd4f4cb774f40ef52901816e80f16198120a8859140084d8431141a69bb4f05d92d7b24339a020b","nonce":"4a530fc506ed6f16ed5a75f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"022a652a1465cb70086f32138de8133c0157d06dd701937acc267aba298b1196079d2adb75e2bee1adf4240bd8","nonce":"4a530fc506ed6f16ed5a75f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"489121943b0b06390bdda0e2fdf0b728dc4614811c8917ecd4f901e18656e450b496d48cc6f545dd33467c99de","nonce":"4a530fc506ed6f16ed5a75f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"523ada84c6fda437f0a7a1becac0e2b6d349a61cada8cfa18140e178ac39aa2a159b3b66f8129791f363787ff6","nonce":"4a530fc506ed6f16ed5a75f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"4e9a9aa5546860cf18106e2176ab99ccf07c7eef658311cceda544d10d1f2d55e3f0e2bfea596e57cc9662bd2d","nonce":"4a530fc506ed6f16ed5a75f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"cc7bf2f2c961a7e21725372045b9142e824b4848a84f48b3103c511b85c3c5832d0c1868a7d736f9ffc60bf3ae","nonce":"4a530fc506ed6f16ed5a75f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"0e545d658bb0d4f30ac7a3a5a6d5051d035ff708ad4428a61d4d59fd1ea7eaf0a28ab4dc5892d8ec724d6f8a10","nonce":"4a530fc506ed6f16ed5a75fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"d88f49ae31eae19bf2cb3500b671e7bc447d215f89a5d1a5c65908c14d4ac971497bb7d36c53a0044b5e62dfd8","nonce":"4a530fc506ed6f16ed5a75ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"e0e929a0838ec26c8a84de750428011b949b5fe4baea2add65ad981e1ea9eec6082aff0a7d658fa977cf8e04b9","nonce":"4a530fc506ed6f16ed5a75fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"8d86b4e29e6dbab5e8b837b7c35b934bb8d0091f581dd3796f034b6d7792c49b932472ffdbd291a7d4daa69ab0","nonce":"4a530fc506ed6f16ed5a75fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"848daa42c5dca6b1132355e9b4c79607a633235b35f4d707a247bb0960a6a51a36af6647729f16640e5767a850","nonce":"4a530fc506ed6f16ed5a75fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"22c9f47f8bac58e77ebfe5358a80413b57f017fe048e71b60532eb50ab3a83f5c3dd29e54f48abc57575e69d22","nonce":"4a530fc506ed6f16ed5a75fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"d1b26fe2add5a7ff14104b015e581e7c4e29518eb044088ac5046baf07d7b4afd553a4718a13aa89ac13673954","nonce":"4a530fc506ed6f16ed5a75f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"02e0bcea36f8ade9a31d73e483f4dd15bd7427fc19c06cf02f847123cf75235661ca9aeeb3d5d20b26a6f43107","nonce":"4a530fc506ed6f16ed5a75f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"1ae076fea3a25c66235037dc4b3d61eb1c6d05ccec994b64009ae1b85a74a17218511ce36eec008c014bb4a426","nonce":"4a530fc506ed6f16ed5a75e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"0d5bee31ec62485cf45fe5d15e31baea41df0019b5a83d4e1d94df8ee5e5e8f05931f1519492ea896b94ba5a2b","nonce":"4a530fc506ed6f16ed5a75e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"1da5e443bd3ef0b641c336df3c6a18425b4d9c48ca00138c3497f4faa569b245baeb58abc99a0f09e1aa155c00","nonce":"4a530fc506ed6f16ed5a75e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"c2d2f210ea57de5eeb8f4056d9c69a2cd3a5f78828cfb6ae85d87668583e9978d44510f002e9e8caddccd8e18a","nonce":"4a530fc506ed6f16ed5a75e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"ebe1cb54e83c968b4bc8fa9fe55951193a625333bb3eae36088974c8b8f515fecab783e8c830eec2ebf977bfe8","nonce":"4a530fc506ed6f16ed5a75e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"0beeb4b77b7874626e24f90db0ed18ef3d95719ead1a78753ca2f88db2d1059aec4e6a41408fafddbfad023d85","nonce":"4a530fc506ed6f16ed5a75e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"d5ee24d60adef41d3f7b587cd7fd2444aae4e74bda7a94a5e9b477082f2221ad0ce32d7da4baeff9ada33c8081","nonce":"4a530fc506ed6f16ed5a75e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"7845d9b7ffae54eae4c02dd2e537ccb6b481756e9a01a726e9f1aa9fb80cc43fd0d6c9799fa27d1862da0a0cdc","nonce":"4a530fc506ed6f16ed5a75e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"4789438052b0eb35903ac09cefc8f019a512261fd5762cd60bf7fe78ecc9670b95288dae57d368db66130bcdc1","nonce":"4a530fc506ed6f16ed5a75ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"9f64ec1b192f3f66f5c6e9d98819842f86ef67adbc0786efabf9de47c5a54d8bf867c9e306799dd95af8f6c263","nonce":"4a530fc506ed6f16ed5a75ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"d18a9a454ab1ccce4c05130269d3becf9d558dc87eed406217b4f41b4523707c0a6245cc8c4190615577231aea","nonce":"4a530fc506ed6f16ed5a75ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"b2f46a8dc3de2643a5528bd3f74088ffc7bc1594b9d15d50fd0a4bb1b37d6ce7d1d2efb7201bc796fb8b1d4acf","nonce":"4a530fc506ed6f16ed5a75ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"7e13327a0b2a8290942b2510d85863075b1bc4fabeed7738a685a870b60e2fba8aa200af1f647ad48483fe83ef","nonce":"4a530fc506ed6f16ed5a75ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"58eaa9d581545248a18b9294c80105e045a0143c5c8dcc15c7987cf8120ace4b91b8a0898ad44b2547550fc19b","nonce":"4a530fc506ed6f16ed5a75eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"54917255f0a58e5bddeaa291a50108715b473ed70716cfd59cc842f3d339229229364cfe70788d66f65ac80e1a","nonce":"4a530fc506ed6f16ed5a75e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"73409ffbba59d7f724ca5fcb4a4c6c2d26de2d8148acee0db0b1a0b0d06fc02a0debefd6b5abf27af588e9052e","nonce":"4a530fc506ed6f16ed5a75e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"b83e2c67a5a9df19624db2efb383dc7ca0f15a5087655faa719014c44302e35aa70280098a067317d36dfaf222","nonce":"4a530fc506ed6f16ed5a7596","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"36aaada3c0755a72218afa97183e673ebd96ca8eaf13c9fbb3573e23bab1c70e00bd5d3fba093d60598dabc35f","nonce":"4a530fc506ed6f16ed5a7597","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"7523c723497be7677bdffe365df4ed0cfee9987dbe343c9fbe82aea1d44fc0622da5f4f3565a550ac8bb2771b4","nonce":"4a530fc506ed6f16ed5a7594","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"d5e7b000b8b68f212899c9bdef785e6f780b65f152a78e8b8242132f7221979a728be16d972741f6c50766faee","nonce":"4a530fc506ed6f16ed5a7595","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"1532aecfdfcc9790eeda2edad04e6478d42b7274ba08974f96e3bc3dfb1e1b85d2afc31a0e606689fc96c7583f","nonce":"4a530fc506ed6f16ed5a7592","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"5764aa081e8b708c146f5fb3392900fc7383ac4f3233f08fa9bbb4504b6783cd8bd9856d2ab5844c605f731020","nonce":"4a530fc506ed6f16ed5a7593","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"8f30b5a52f67639ca7540b0b39149cf78af93e041d652efe87dabd010200ed3c51f5c55635e3f915591b61b6c7","nonce":"4a530fc506ed6f16ed5a7590","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"d67ab7de63d77d1166e8cc9efee45fad3d35d534d42af0074a6beffaae87988539beb85832cda9e5815ee5a4af","nonce":"4a530fc506ed6f16ed5a7591","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"7ea8942bd1ddf0bb931379135d624eb6a78d828a42ef6349a2723302243613b7d4f75bb18d7eec1dae69368b3f","nonce":"4a530fc506ed6f16ed5a759e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"04c8cbf35bf1628a20d7bcab6ba9b0987a74ecb755125ef87175d261c15ad2fdea88aa0fa6077e2e31bc988851","nonce":"4a530fc506ed6f16ed5a759f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"a26c76a19d9f3fb556c5911acb1b1f9911e7d89f86fc30db59e0683b2d52d318daa59f0ecc21caa070e29dc659","nonce":"4a530fc506ed6f16ed5a759c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"408633a2f98192192d8af34ccdf1415f28046b600b0a7fa45a3f3d31763cbd6979cab991dca03f1afeeb63f535","nonce":"4a530fc506ed6f16ed5a759d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"4f6645790598b334b884cb18138477be2a96899741aa885d4ce10635ae939e325e6bfadf036624dff261a29083","nonce":"4a530fc506ed6f16ed5a759a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"1c8d64f9a46a6fdccd140a82c01bd3d68b3ae863e4a05cd89ce94df2d2e089db53c85c1ebd202b1d1c55d3adc2","nonce":"4a530fc506ed6f16ed5a759b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"e46da225f84ae4ba5c2b3c5701e9d4b62c95efcf1e7ea702f189f30074e02effa5bc38c1f181ea4ed58d8d4f05","nonce":"4a530fc506ed6f16ed5a7598","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"fa0870e32f5235102b611ef9a40c3d2808900f9924fbbe9b0565bedd89033b5fa5542f65b4fa0b629ee39a7cf7","nonce":"4a530fc506ed6f16ed5a7599","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"90c2043cdc180930bfcb42a97699e409cd3a67aae6310fc29207452552b14118fd2ddab5fc52aff3b7c09e6d0e","nonce":"4a530fc506ed6f16ed5a7586","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"05cb77829fe61b6234f996cc8c46aaaa06509a17c264999b39eba04d643090c18d12c312de33e2cb85383deaa4","nonce":"4a530fc506ed6f16ed5a7587","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"29cbb615d0ade3c5c0b36a94a5dd59599960d39787b76498a5ee4ca1b4d93cd2c9c772c5c246c5df59049ebce8","nonce":"4a530fc506ed6f16ed5a7584","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"e4b16e63041f910c3cc92bcbb0a0a59e51bfe04b387f4b39014da820e029d42cec3ffc0aa0c7fea9730458d199","nonce":"4a530fc506ed6f16ed5a7585","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"8fec3f857a96dd028a52c340ca45d5943c80bc6e8e3e7d7d117a0b8e1b6a51699f8204ac05c16dc26b661508dd","nonce":"4a530fc506ed6f16ed5a7582","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"a34850df2fd0b3a2abf4688e953d9710fd75d08a8cb6b20c434d1bd358191db3c04392182e376bef43badf6baf","nonce":"4a530fc506ed6f16ed5a7583","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"2ccc75dccba289fb095ec0c5d9b06d72d25565e790b686c15241037c779d4c9e0130a941a2ae9474477f64fdfe","nonce":"4a530fc506ed6f16ed5a7580","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"d8db9555c621315f18ae7c40773e9bf103a33c57bc84953a6c3a695a20b9853a65fd9e668db538b4e5b0f320ad","nonce":"4a530fc506ed6f16ed5a7581","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"af3d7bb731fb090a634d934e7501d139844fa561ee0b35e0f69022ac97c16065d2fa73ecb26fce70e767c30ed5","nonce":"4a530fc506ed6f16ed5a758e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"97b29ba55d0dd9a0a516b4f1f8c97ff9873ea88ff04cea442af1daa2031a0ad23e50aa6ef52b265695dd35834a","nonce":"4a530fc506ed6f16ed5a758f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"b0235cb635974c84dac5991f19d9e9b54b54b4076d9561e040c8e268bc3193b1e73c5a7dfc7152f9916b4e80ed","nonce":"4a530fc506ed6f16ed5a758c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"9d58d405e0cbb8a41ee5197a5a69e460d93cbb76bf824786275f92623ddde06cee7f13c2d0268d6c5ccbe71b1f","nonce":"4a530fc506ed6f16ed5a758d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"ccd8f812c78ec0d677e39d75d55b5bf692f5097a035ef74e440de17cac61ac31b45a1a7b634cf08a12da339265","nonce":"4a530fc506ed6f16ed5a758a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"9ab1de9a7eb50d8cd069d9d0586bbeafd5d0b4beb979928c105e7f1b383d8105b17252c8c2b332d59da27c101b","nonce":"4a530fc506ed6f16ed5a758b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"db36caf091eff0fbaa544399fcb3daa507b0fd9eab2df9ec2502c1b2b1322a051dde991e73a17bc5935cb7ed8c","nonce":"4a530fc506ed6f16ed5a7588","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"bfce91f37831a7ddcb5831c3a063d2fc6c0843332d0f429e4138d9aa62ddf5d3cb15eab8f9fb6d50c655eb8316","nonce":"4a530fc506ed6f16ed5a7589","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"74c1e981a5716f19f02b6633d98c01152f1927d32480937b339e9949a200d1e44216ecaa5e24467189b9f03f86","nonce":"4a530fc506ed6f16ed5a75b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"a7de7ca3a16c940f208060e5ce8ff916f088595bd7d9561cd7e8cb65f732ab538fb9d0a3c52448f97ea19e7353","nonce":"4a530fc506ed6f16ed5a75b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"4fd9583bd76f4d0e49c6644d4d087c9df966c87a2756b9e5b3da1fdbf22b2015b9e70cb9c3861ff9b2b36794da","nonce":"4a530fc506ed6f16ed5a75b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"6296f919c0d30ba23e437d8df066e042d606ed211550448e5d4008735c701c49919c3a02664916f73001d8084a","nonce":"4a530fc506ed6f16ed5a75b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"a96d5a596172629b981b362a877449a003c19ade5840f09eba03a08ac215b38677d3ac326630dad5b5a31d585a","nonce":"4a530fc506ed6f16ed5a75b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"e6cbc03c5fc9ba1ea31205f41224634ceac309051f590eb6064d423a984423bc467d0660f2e4e10171f8a223ee","nonce":"4a530fc506ed6f16ed5a75b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"68dd7f6925d1ff75b9af3b380c7605321dc7a4cb47bd5f7a60096e3b4f80c6d9159412e12b37590bf193f9b668","nonce":"4a530fc506ed6f16ed5a75b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"2f60d4bf1606cb4e1a597230695a2cc9f786b95c3df1ddcda4c6fb87476fa75fe411c1c1a5e36c3350d0d5742b","nonce":"4a530fc506ed6f16ed5a75b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"52cfb7dedcaaee4016a6fa958dff1aad23effe2e77e3a24c6130dc44af9d96288213ae4b57aa3ea415e7b4056c","nonce":"4a530fc506ed6f16ed5a75be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"f7521016e3fd29280ac56608f1fbbe4f55b459a551b48e974910ca1cf30c9ad70537fc79479d5ecae95e21c2c1","nonce":"4a530fc506ed6f16ed5a75bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"ef7077aa06d67a80dfef8cb54e93c9085558f86009c05370e425df1462fd6222288fdc83abb985a84e8aea6e4c","nonce":"4a530fc506ed6f16ed5a75bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"f698a816c01a1af5797c178ae49d9180819732f94c100acfef03de449a5fd1b131ea41c452cc13b7b85a3dcd73","nonce":"4a530fc506ed6f16ed5a75bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"ed4246d1d734fa14ce937f5f95a6e6c60061afa5f3a05848dfb49ac9df77f5aadf89642072755dc93f659db925","nonce":"4a530fc506ed6f16ed5a75ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"183df04fc43019ff20fcc977cb010c01438521578bb542e190fb73bf59e56d12e5a9ee6892965d94e6846f7b22","nonce":"4a530fc506ed6f16ed5a75bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"99e38d2445f94777da381c23ae46b3d1d40ad3dbfa9de5b4e61eb7b905dee3fceb8765af8d3ed7277b4fdf1113","nonce":"4a530fc506ed6f16ed5a75b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"f9d5361598d7be737c1b676aa50f1b35f78f87e1141dc0c50cfc37d6e95c974bea8c57da002e0e78fd7b564bcc","nonce":"4a530fc506ed6f16ed5a75b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"46c06410db4d9409ebae0bb3201f7bed846005c65a34314808cc71161cf05cf17ab14bd8a40b0d13c957a13238","nonce":"4a530fc506ed6f16ed5a75a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"29d95d407dff3300a6262fa374409f4c9de6a20a8fdae58a8d9e7afc1733f65c0357085caf1fe44ed08fbb4bb9","nonce":"4a530fc506ed6f16ed5a75a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"666639f98e23aea551d28c66cb5857b33042f11e1dcab5c38b68167dcd489d85e41bad785f0fdfc07e72b580e6","nonce":"4a530fc506ed6f16ed5a75a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"c5a37b6786814131ed702ddb54d7ef688790146530861e702cd236e61c745a4cc81f66ea6e31ee12dfe5d4e2cc","nonce":"4a530fc506ed6f16ed5a75a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"b66afa9b40b90604d84ee4fb8af2443a00b367ff80d6ae963d86f786a62706d4728fc7e7791cc8196f507a9e25","nonce":"4a530fc506ed6f16ed5a75a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"f907557530f057cbd7075f0a3a24bdadbebd141a09a49419804cad00edfff6e4ba6d61853e600e81b8284d6ee6","nonce":"4a530fc506ed6f16ed5a75a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"1eeeba36ce377ab0bc9f97007790f454629e108ea676fbba04af3632df7e4dbd94b1d815a6a339639bb52402d9","nonce":"4a530fc506ed6f16ed5a75a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"0e01f488c0adb999d821c1365badb4572f604d3ccbf19f81a66bf931b2bb608cdb21953400465c607e2b7be090","nonce":"4a530fc506ed6f16ed5a75a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"0be3f57cff9e62e15f8164be7be7146354d9d0dc04ecf241135fb4a3ac92925cf48bc711ad3a50fa5c156fa867","nonce":"4a530fc506ed6f16ed5a75ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"42089adf8790ccbe7131746adeccd7874d9015dcaa266af71a64a71a80db63c7fa1876880e6b7eccb01d78b178","nonce":"4a530fc506ed6f16ed5a75af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"6964eb695f7074f5665f0d0c6425ec4c743ee2a5c45e45eed2370721a618349923e3bae5f38d79055670b9a1fe","nonce":"4a530fc506ed6f16ed5a75ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"a3f1c8968ff7ac7f81430e03e18549cb3936ca482600ea7a61801b8610865b484201ede894b32ae574a935b7d8","nonce":"4a530fc506ed6f16ed5a75ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"24f84c2282ac27223e00133d7c6a91279d5b50d91945c9162059ae81b41261f1ef06a2e44969437d9d9fd36e42","nonce":"4a530fc506ed6f16ed5a75aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"69bf548960ff6390a5319e6465f81649ff6f30166c61b6421a9bc1bd6a3bfafe9929ae877587cf3c86832e7d9e","nonce":"4a530fc506ed6f16ed5a75ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"d4a6b770e399d99d85735bc42c70d1e6ea89876a06f6d0c27c4f215549fbe70354bed528030410ad79066f7cb4","nonce":"4a530fc506ed6f16ed5a75a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"110dab990304067d5779009b01226747932debfe1449831b65ba4b2b045c716e9eaf5c17ae156c3c828bc76a39","nonce":"4a530fc506ed6f16ed5a75a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"b808c14540c2dfd186b1431125f10d6ed33ef4b08c5ff4eb7ff5f6a306d0a808674a0ca67a94bda0ca6098d871","nonce":"4a530fc506ed6f16ed5a7456","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"0c30841f8f6be883f2256a19747ec691aa1a90958499935505afb0a37e3b6e36"},{"exporter_context":"00","L":32,"exported_value":"5b5b11e926098f13a3bf26e8ffc4e811b4b6176505e51068ce82e4ef2cc4e4d3"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"bb4f01824841975d8f394b484b104f921254eda931cf694e8b1352c3f94435d6"}]},{"mode":1,"kem_id":18,"kdf_id":1,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"9e211144c35f92b52d0f63304918605d9606ed3d08fbc5f6f0421e38d15d5ef3572ad1aabdd8f190823b5af49725fdffa6aeff3d893862c76737c58fb81fc21339ad","ikmE":"9f451d78e6929f298c8c5fde41fe7447aa96045965c2bf2a21cc7ceaa8a5a808c7438f4fe3c99f716e02c1e5b2af2be0de0d9ab2d133677896a3929d4a8f8973b950","skRm":"01d7a4dc4862e6cdf171de249449678a7f49c8d21a5094e1e368e6858d431b4aa1ff1b683c369428065e1364b49a72f7fcf48d7d363e9b599e66f448b4313442fee4","skEm":"00d2d072160d5beab8a85ecc7b457bedb7498538ad8b5e9660f5c9e40beda476135b13bc8330fc28f8b4dd9a9d132107ac5538c4616ef9f783ebefaf7046d976c6ab","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"0400d02f4a326374a27731f87fd225d17287e6101b2cf26acb8d9752026eafabc82209b89a1db18657f09456fce4a56a05d3cc55698c36437e6d27c94fb0eb1bc7081900c51a597f8bde81bb68f532fc67c9419956437305bac9934ead952e13bfe581e641668771959dde0d9f8a315ab6e361bdf3983512992d14055a5b974c1cc60f327a","pkEm":"0401872e5a71afb87476cd2b395d41c27566526a75da4b4c13ddee9f3a3d584197c8ef154065513f9207ce5ee68a76d7395b2fabd080f34df45684f7a48d06ec19f0f901eea3c81a91c89aa5222aa9d706d35dc5b7a6a2472e0301983d7be818602ce8623a8359014654cd1f2f837d0d4385c1e0c516da8a469f00b4b3b8c75355710bb9d1","enc":"0401872e5a71afb87476cd2b395d41c27566526a75da4b4c13ddee9f3a3d584197c8ef154065513f9207ce5ee68a76d7395b2fabd080f34df45684f7a48d06ec19f0f901eea3c81a91c89aa5222aa9d706d35dc5b7a6a2472e0301983d7be818602ce8623a8359014654cd1f2f837d0d4385c1e0c516da8a469f00b4b3b8c75355710bb9d1","shared_secret":"46c79271e62120a2ab9d6ebb24df0d302db3f634da8168c16baafab9939c002d319742e350831bbe92364ba65ada37582c0f6a9b41493f2fe35a2dc001bdc1a2","key_schedule_context":"0185f941ad2fe19e65926871f90dfb5e99425bd648b6a9d0cdff515181110e0dd02c567eba65d69b8f94f5dd45f30ba15730e09a0ca1bab72cdd2606fd3e4a6c69","secret":"747040152b264fbab5fb79fb457fd9022bfd7250e1c23a6d6aaeb5f9f453f96e","key":"63e63b59f05ab8df538d34f327f1b41b","base_nonce":"8d1c3fb2ab77f607b24bed9e","exporter_secret":"1006c279c9031cb9661cbc85706cd97d5a8e9483f88eae714d23827e618793e7","encryptions":[{"aad":"436f756e742d30","ciphertext":"cd4644367273569a93454fdfa4f4e4b9b714f60639e4387622f6874510244abc8f93af1fb4a1b28af90599d215","nonce":"8d1c3fb2ab77f607b24bed9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"c00b0a514e8dda802f68f74044bf4a1bb00ce8cb000dc922d77b0e3f71742325d205062e7f616da10fe26e7b6e","nonce":"8d1c3fb2ab77f607b24bed9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"13ed88f4cac5d22e72a2e52275693424177d189bf794fc4e9d3c5fab223c09bc677383892afc86860b3f3a11b7","nonce":"8d1c3fb2ab77f607b24bed9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"dd409eda40006aa91e32f195f6df9d094bcbb77084ada525a23bd2bc06e590bd6528b0a0ffcc440a9c9644caf6","nonce":"8d1c3fb2ab77f607b24bed9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"d819dc28444823beb44dbb30ac193bc8fd07e2592e6363c5d958e6d76fc171e1209209a6dce35e52fe09e1a9f1","nonce":"8d1c3fb2ab77f607b24bed9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"fc532eaae10ccde490d837a471caa0806567350fa432a6c82eb470bc464c6af182fab8a7325df61b22ac83689d","nonce":"8d1c3fb2ab77f607b24bed9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"12270108396acbf4b37a54e0f2a5ca43080bcc4e6a32b5f6e65489eb31492ffb2adc8087939afcfc189419bcae","nonce":"8d1c3fb2ab77f607b24bed98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"5cae0c7623279d5d46c023a8503c060bdd5c644876130216321b5bfd187512270713764dcc21d7568fa32ab0d9","nonce":"8d1c3fb2ab77f607b24bed99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"4ffd756b98ebdf851b9c2ca9c85ed7781fbdfc86966ba5aba55696c5db7f2c7e7de664425b845ec89bdbe49e94","nonce":"8d1c3fb2ab77f607b24bed96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"ac937bc1ee57c0b593d3194d25b58f82f470e568e1ea4243519d885153836836750c162e486540f6a7b3af5e85","nonce":"8d1c3fb2ab77f607b24bed97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"12dd40a6e7108f2b70289d0e05b069f8fdb12cab1a911f7813e0179fc559f4d0a3d43a206dd6a5b3874fa7da5f","nonce":"8d1c3fb2ab77f607b24bed94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"04793fb28d2d1ed77bb908206fc5b35179fd85c9c2f07ba8a154ed4af44370b211bc3cf51d4fe8686c38ceef0b","nonce":"8d1c3fb2ab77f607b24bed95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"6a32c790a62b094cea81eb3d7aa5a676a1ef546c2f51f92cdc35403fb688afc0f089f36e02e7cb5fe5fe99974f","nonce":"8d1c3fb2ab77f607b24bed92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"80ab7a2adc0de04dcb9eba2f9479f1b56d5c0c3ea4b3c7ff1076ecf9b6b28d7efcfb48396bff1c3b17a1971139","nonce":"8d1c3fb2ab77f607b24bed93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"595f8f6eb915b73470eb58fd6502cd1132b48e0470106050816498ea1716171b3e17b45c4715931ebcca49c49b","nonce":"8d1c3fb2ab77f607b24bed90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"307f1b0e6c8301582cabc4b2a81000a6c282176529c1e29e92fc0589460f4b4703b581b98c865d3699abc12d54","nonce":"8d1c3fb2ab77f607b24bed91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"cd295ac40d736d909ceb7d5adc31de512f1ee1e84c5058df16e15a4fefed45fbba993e4c3b6c9c0f705b171eef","nonce":"8d1c3fb2ab77f607b24bed8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"3cbcb90acf1c565882ec645247c518f9742770c56a3da9a873c35d88575f026e87450240588edaea106d916545","nonce":"8d1c3fb2ab77f607b24bed8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"feffc7fce025dd9456df9eba5417b76e64d031e085959ad06796b49c03c727d4a486cc722c28378183b03b8256","nonce":"8d1c3fb2ab77f607b24bed8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"d0fdc532ef5bb99d49f990e8e21a48e0b26ceaa5eb5f20e47d27127193ea717d274c15ea3337a9ea8ca7d78e20","nonce":"8d1c3fb2ab77f607b24bed8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"d3a15bf9167ecb5e56f3ad6d83228418875fda7023f188cded06f8a8e04368d51782812f3a45120a1c16ac0c5d","nonce":"8d1c3fb2ab77f607b24bed8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"f7a64effa7179c391185eb8b91a14f9196fbcd1098e7ba3f092649dba0036085a46b90e62d65bfdccd406cb52f","nonce":"8d1c3fb2ab77f607b24bed8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"2bb090aa49431c3d9c93bd4d56e3c98811ab7009e790eb80ccf3cfafde91307a323cc751ed4b5e5d89f1803aa8","nonce":"8d1c3fb2ab77f607b24bed88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"e074e486c5cf42a6384941392354a6b2480ef40a9f440b8b4a72c3f81e2fa51c29e8adf09e7c4b4a1a8aa96830","nonce":"8d1c3fb2ab77f607b24bed89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"92883b03daac22bc794df5b77d92ea1c0efeab06436f31a4a4916c85a787fa436c800e206ac62b742098387b70","nonce":"8d1c3fb2ab77f607b24bed86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"de696e3b26b8fb16d712e8e71ef104f556b2ef4237d2706c36fe45f57fbbfde42422bd1e0bb2b3f9764de350f3","nonce":"8d1c3fb2ab77f607b24bed87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"cfd315b3b4fa85eb587d24cd178197d7c1e331349d2f73659d2a22f5f75cb0a47b77c935ac89c9295b9b4077c5","nonce":"8d1c3fb2ab77f607b24bed84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"fa805b534b68d87d14501334fc49ba8724ed4fbe6fadcd7245d1f4b33546bffcb31e5c3fb0e25a6fa848d15c9e","nonce":"8d1c3fb2ab77f607b24bed85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"1be7d6f01c3dded2a51d2536d7fc5d0afbea326993d6d9a54b09387da445f5a0b445a74553f3bd4b9277ecd955","nonce":"8d1c3fb2ab77f607b24bed82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"46d590fc768c93d121199de9e50420d02df4aeed06477a29b60209879773866fbf68aed065c6379983b80dc548","nonce":"8d1c3fb2ab77f607b24bed83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"7250a5ec5a70e6ce9489ac0e88b33d2cb5402d545c705f8b94334599fa0941ad794f63eab0de7838aec95d7932","nonce":"8d1c3fb2ab77f607b24bed80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"7026cea61ad5196d362f03ad638be0c707dec6ed755efec17797a617af37e0aca1105438c8446c42316dcb376c","nonce":"8d1c3fb2ab77f607b24bed81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"06b857baf7e8d6887e67935e0e3ff8c415329e330b210d06e15ee10e73800e9f95770d626019678b69d2852c28","nonce":"8d1c3fb2ab77f607b24bedbe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"be3b472a189f1871335818affee156b56c554c3bab938c2cb7d77df709dfe1716a7abd4819ed84b4862f3d5e4b","nonce":"8d1c3fb2ab77f607b24bedbf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"6682488af194c43c54025067eea934b98540bc638ee1c67f70d92c8704ddf0063dbab02ad8b377cf878cd62d7e","nonce":"8d1c3fb2ab77f607b24bedbc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"bb2101c0d4cab761a802a35ce4dfcba48940e14720ea94bd89c6cbdbdfd1e52555ca2891e21a348457e330c179","nonce":"8d1c3fb2ab77f607b24bedbd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"27788634eebc5f8049e425a8915c91450ef22384367d039259c0bedb0c8d2f040f2a1674c85961242467a3907a","nonce":"8d1c3fb2ab77f607b24bedba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"eb2e8cc28922a81bea21dfc7979004683e4f7ee8da2e874205aedbf5bb292ba90d5745c665d74c40744f7761cd","nonce":"8d1c3fb2ab77f607b24bedbb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"6998ec99944e1173d9278f6dbc68b4946bf3f50908fee51ea5bfbda2acd4cd93c168f4595e242fe8b6b51eb73d","nonce":"8d1c3fb2ab77f607b24bedb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"92f6a6f9f2704850171cf577bf4eb7bad9c0d5848a94813488d6be31a6eebe36f4fa4134cfe9dab1e4667075fa","nonce":"8d1c3fb2ab77f607b24bedb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"850dc28af11dbe3218821184279466ae75d7b2827a0952ccfc09b6428e74b80fc891bcbcccfbb5fe31b3baf1cd","nonce":"8d1c3fb2ab77f607b24bedb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"fc328b6875b630531a0239a72c1fd91d9a04f69e0f50ccc8cc07d8b665d39a42f62a707454afdcc5a43be6d280","nonce":"8d1c3fb2ab77f607b24bedb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"26d2731fd9686d74fb0857cec895d876b7a1f46349755f5f647fdf53aea47efb4e98b11476d86c687db086bc4e","nonce":"8d1c3fb2ab77f607b24bedb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"f0e855f2c7eea993f48f520f3bf034974e6bfe83a66dcee19ff4699832446dfb1be454cc1c2dfb118e93654a73","nonce":"8d1c3fb2ab77f607b24bedb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"e541e6c6d8f6216742fd81f781486f88322fc49a652f582b783b334e5de0b87fa637357acaa29b6fd91b0a471b","nonce":"8d1c3fb2ab77f607b24bedb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"a40114cf31a146914dd314f2fd013ec1d8887be34fa167dec5a69b4863aefc258f7442780d00be40411abe4373","nonce":"8d1c3fb2ab77f607b24bedb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"3e3cb2c45809a9d2b34671df25f5bfe9f28b78eb826dbf6ab62a6292f72aa7b482dfd0c808b3bb3308ac0f11f6","nonce":"8d1c3fb2ab77f607b24bedb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"489f065b4834027e5a7b8d4e19e497dcac421cb08fd527ac1760eadd53ea9fd9a70835c9d95ad24f2cf9789046","nonce":"8d1c3fb2ab77f607b24bedb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"d476bb5644cccd1f702d010a8a4058d8767be20be811896c524f4c2b43c825241842ce35c32569610a4704dd00","nonce":"8d1c3fb2ab77f607b24bedae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"bc5e88720c7d4e3e04a65ef0c9fa99d84436113d31e7a2de0f8ace227d14372c564d1da8bc323233cdbea2b61c","nonce":"8d1c3fb2ab77f607b24bedaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"9e883ae1ec9160557663bc4b2c4cfd38cc8b3ae7d04aced73ff39d519fb742e1be4c9545997ec2eef078f34052","nonce":"8d1c3fb2ab77f607b24bedac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"809adb9873f6bf110793a218086150c78ec95ccd0c835ad30e0dc4c57780b39c28272e51d1ba7aa920f9f467cc","nonce":"8d1c3fb2ab77f607b24bedad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"a2c47c797277f500022a6efeab52919e158c9cf500dad6a24d1e2f1028fa904b6df50d6ab5d904977914d2b04a","nonce":"8d1c3fb2ab77f607b24bedaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"e38cc035659c1118ef3ddcaf75bba8f211f1301a04c13f40e796b63db6b27c758ce09afad4026a24f29a9cc61d","nonce":"8d1c3fb2ab77f607b24bedab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"f98001e01a85fa39740f56e350e87c5a662367a9b98103659a595b33b30de66685a01c6eb4e5c47f0a4cde5f9b","nonce":"8d1c3fb2ab77f607b24beda8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"241ef7fe6eb070473f7c77b61eaf518ce4612be876d46bae7deaba07d47e46f5dbf49893e2bba8fd48b9f28057","nonce":"8d1c3fb2ab77f607b24beda9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"e12694f3c4178bd6126e94d1deacfb747794d51a8934a8069dc87e6846655d104bc8ed4c265feefacc15a7761d","nonce":"8d1c3fb2ab77f607b24beda6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"85118a36da73b1db1aa86dc2c22264aae816eee984c74c19a0613dbe6bf31d9a05918ca78061b353582c787ef2","nonce":"8d1c3fb2ab77f607b24beda7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"47b837f75d38dc33965bd87a7bbb647120d8ab2fd96864d94520020e0086c06a556a4912c4d0f7d6cb1c4db008","nonce":"8d1c3fb2ab77f607b24beda4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"ce9433b54a3a45507fc976583d65b4bfd2bcfca88bbdceaab8bd59c263c1ad3ce29d39911578fb9c385a90765e","nonce":"8d1c3fb2ab77f607b24beda5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"afd636d630b9d154da9489f2f8450371147663d9fcccc52f2c1dc6961f6f0924ff38b789e860707a8f6ced09c0","nonce":"8d1c3fb2ab77f607b24beda2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"8a43995ae5a649247be761436a7af80238c953c6e763749ec38da38890d1eb3f2892217ee399de63a4f6cf822e","nonce":"8d1c3fb2ab77f607b24beda3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"eaa2c329d27f3b4e0a6e7310f3e56d1e5a0f17d318772ac759b5761e118fc189189a7aea8e7924d0dd8793076a","nonce":"8d1c3fb2ab77f607b24beda0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"e7201afc6e90f80d7b0ef6aeb927432f41837eaaf974a14381c851ce0ffe425d8c304ac63ce890e6f478e38a4c","nonce":"8d1c3fb2ab77f607b24beda1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"591e51ebcf75c8e368fe32039faa7e5aba53f0b6c67a0a90c1e3a9a59e81813e4a8c1af30cb314917ba9f8fcaa","nonce":"8d1c3fb2ab77f607b24bedde","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"97109393e620ff1b8d6be77525019d94591be72fae7d7cc5e8275dad521afc01742311c2380e33af10356a405a","nonce":"8d1c3fb2ab77f607b24beddf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"19db88e9eb9beaebf34df8d1c64de940df3266b005c0b0f7981dabf07a6f6ce8c7499b96a910e2e52ce1eecae0","nonce":"8d1c3fb2ab77f607b24beddc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"1f2c3db16b73ea40ebc4e42ce3ed2caecf2f7927a5f926ef7379b31ec3e9b3a92103e898a5f1bc74b28c324d63","nonce":"8d1c3fb2ab77f607b24beddd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"aafe24cf9aba3740ed34816edfbce16b59d340c3a94e97bfb3668ceb63a3743d6ad1a1bac735e34bb94e107b08","nonce":"8d1c3fb2ab77f607b24bedda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"77f938299727e6e06e250a59c3c0032539e08f9a158b30c16d3ff0000bece68e48641ec240931b67c1e2bf7023","nonce":"8d1c3fb2ab77f607b24beddb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"36910e92618320b22b4f75d8f79646272e46ee29edfdab6347bfac51dc72971beb1198e2a87e926ae0127b2f8e","nonce":"8d1c3fb2ab77f607b24bedd8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"80d60b4bff84d34f607f6257bd7c639d28f9a1236a19bc87f668f94a17008e47911ec4e50de27895a7ab9a7708","nonce":"8d1c3fb2ab77f607b24bedd9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"f88143f946d6150abf9617a562c57b610d17c11afbec6ae6c9bd1f7c41f5e28c7e6109bb064d597d411fabf31b","nonce":"8d1c3fb2ab77f607b24bedd6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"817e9a2c02e724df3341dc6f46afd980ed17e0b9cf306d453d571804a17121e88414b22b78a6bbfffc193d740b","nonce":"8d1c3fb2ab77f607b24bedd7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"62c852c790eea712af2f4e26facf532839e7c219692f8140c14a00211b4ce9957a5184135b4a90c73367f4ec1b","nonce":"8d1c3fb2ab77f607b24bedd4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"208875bcc65bebbe8922201a20050df0901c167119ab7fabb0ae0bd4d88b6fe4b312803cb71507fba3c012e761","nonce":"8d1c3fb2ab77f607b24bedd5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"11fcbf9f942c605806dbfc2c1c1bd148ec82c6f9e3f7baa1de000d62dc91aee6e35e6d92cb2f3706a8b7a73ac9","nonce":"8d1c3fb2ab77f607b24bedd2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"0549fb261db9b2da05662b336e9f8230912aeb2098ffc1ae59c8d6c50853f4e25e215ed60670b0cc0b0d920c62","nonce":"8d1c3fb2ab77f607b24bedd3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"94a0c0a09df63963a46974fefbfcf745330cec91ddb931463f6fb09acd9def24bf3ab911a10e4dfc0b4ca12487","nonce":"8d1c3fb2ab77f607b24bedd0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"27d64248e141417bdf1188791398f6d4645753083d4aadf456517ff9feeced5f74192f2d30fc18bfcf477a5d1b","nonce":"8d1c3fb2ab77f607b24bedd1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"f705a59c47b6ccf54b174e944ae7242a3dc2d4c25c70fe121bc15834d235844697520ceb97025c4acb3ec2b9bb","nonce":"8d1c3fb2ab77f607b24bedce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"83bad7bb8ee6b1c035e73abaf6c5e7f93defc20fc77335cc583565ca0deae3b14b234ef73de124cab7473b3be4","nonce":"8d1c3fb2ab77f607b24bedcf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"1a3f4b8f46658c876f42668fb662ffb0d6d9c0f40b06f1d1e800f0bef30a8adf395a04583d12c44ffbb72eb436","nonce":"8d1c3fb2ab77f607b24bedcc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"5cb982425a4e1bfb48f5e15eb7135494ee38286c9464664613bb6d6ac68d4f622325f3c45cb579b7f80fd9ccce","nonce":"8d1c3fb2ab77f607b24bedcd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"51fa5059ed8c65cb6be39ba37beb9f0d393274738eafedb1c35c36ffd7c73a4372b204132eb5db81bc79d315f8","nonce":"8d1c3fb2ab77f607b24bedca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"7a67a44919ffd6a71f09854b5933fc50b668528ffdaf1331f06a09985e7abebd0e1efa0ad65399a7bccae51799","nonce":"8d1c3fb2ab77f607b24bedcb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"5227a900daf755140e505a47aedc5d7b7db340f0f178e47fd0934012fdcccceb97d123903ed30feb6c546d954f","nonce":"8d1c3fb2ab77f607b24bedc8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"ddcab664c8139327c52c193ac0078ab4250625c24d1d983bca5138bb8c9ddf2a58ada8f6634b8eac30ec8f0c7f","nonce":"8d1c3fb2ab77f607b24bedc9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"36fc8fc067eca1c7230af71934d2492ed4fb1914d44dd7f9e0b71ce8de85a400f8283020bbb791473a88f1e709","nonce":"8d1c3fb2ab77f607b24bedc6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"3953b48a3daf7aa782e5edcb3208d1ea90ec7ebfd316159c51a85ce8c6842f0e5ba9a40b3618c430a9fa8bb342","nonce":"8d1c3fb2ab77f607b24bedc7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"ffae0d02e0eafb46dda68ebe5b2e5537276f93554bf0d9d33daec5a72f04e31bc6825ddbda1e2b8f4c80a4726c","nonce":"8d1c3fb2ab77f607b24bedc4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"2bcc89a94b7ecec2637a0b8710335fdccb6dd76d0c75ef1a15965ec0444c205985f3d04ec3bedb8ab923d92130","nonce":"8d1c3fb2ab77f607b24bedc5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"b6a3c555220da6c863e696dec436c87360d309f6900415a21e0d14a30d6c5cb4745ce822a219ff90bdb3af26b7","nonce":"8d1c3fb2ab77f607b24bedc2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"1cf6beb6ace7ac49c757e9deb3c005e29e99e72826321088c70d6ee0c8821365a7da67b4fa19fe82c6877e1432","nonce":"8d1c3fb2ab77f607b24bedc3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"9fae060c5c697a603a2512666b5b8f364acd35f48b0845b9cf07873a598f8f0b1fc0a0f3f94ba03149695fa5d8","nonce":"8d1c3fb2ab77f607b24bedc0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"77f656aa75173a5c8df4f1593923064fccac112b05d688950c2092967dd9219c11db05be91234caab0b9264062","nonce":"8d1c3fb2ab77f607b24bedc1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"4cf3fe3f1d2511eeae6fa78e27e722a68f2b6d1994562a52d9244fa16dff04e0bd26403020614bb2e0d6f47766","nonce":"8d1c3fb2ab77f607b24bedfe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"8e1cb5cfb0182a90abd217b91911934c152d48daf970232e14ab46a31080cb697188b08eabe57717bf1a23bdc9","nonce":"8d1c3fb2ab77f607b24bedff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"665019b923297ef94a48d74db65e826054642ebe80690dd3ef6e256ae23da02d5e2d02723b46ef89846dba38b1","nonce":"8d1c3fb2ab77f607b24bedfc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"232e13b84ef0e28300fa79c769aab3cf0559c4be9f63d0247e853fd69ef45f4b8b33bfbda3c104a77a34763e6a","nonce":"8d1c3fb2ab77f607b24bedfd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"bfe4e5ba746c1e58e3a1b165e3963a964de7797e0723518e7da8aa53a55c0c62d975e149436f66385bc4ecc398","nonce":"8d1c3fb2ab77f607b24bedfa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"5c5a3b0726db38c917d36b0e839613e774dfb4ab250f9473d143bc1bea6842c0a801fbba9f95453b214daa0d44","nonce":"8d1c3fb2ab77f607b24bedfb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"b6a85db79cc998ca8f24fce2403b61954c907ea610724f2580015ecd79b4b60c5ad4d540bd2652dd97185db253","nonce":"8d1c3fb2ab77f607b24bedf8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"e386cbb22a65fab59ec3bb1952243546c2008b71395a01a4ab761f840a3fb798e95c341b74408416d07b602757","nonce":"8d1c3fb2ab77f607b24bedf9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"a4e1359cd9ae7a81b478b1e70c2467e47f3227160ae8ac5c5c7f0af522e3e37eef3241cb5726a3defaea328e2d","nonce":"8d1c3fb2ab77f607b24bedf6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"c65ac9d91d627087841819cfb457c249b239207e74eb2c5885cc30aaae8401a35a9f77d3ad487c7b7eb4b53434","nonce":"8d1c3fb2ab77f607b24bedf7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"c33f4620f5791866e2363857a89504a7e5ca44c01cdf83dabefd0d7ce4f34a55830701950e42667ec35676ba9e","nonce":"8d1c3fb2ab77f607b24bedf4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"b972872f91620fc60718ebad96201e24069303b7f81b6a27dd7b389e9ed704fff29007d124d3b323cae0bce5bb","nonce":"8d1c3fb2ab77f607b24bedf5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"071e4a909e08685e997a1044f6a2bdff8633f8624b4e3c74ad3e2170c9fc6f85b7a27964f37579db61cc9770df","nonce":"8d1c3fb2ab77f607b24bedf2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"32fad47d70e8802cafc2b0144caea4cbba9cf2b59708ebf0ea52f45f2b226ead06234469dfa5343194229a7d45","nonce":"8d1c3fb2ab77f607b24bedf3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"e76de66d0913fce41497c1457b3e9e010fc43907620df04327e306edd61da0749a54da5bfbb78e212fc7bd03c4","nonce":"8d1c3fb2ab77f607b24bedf0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"769ad2f81085dd839490129dd2f85aebfbed8fbfc22c26a637285a8603dfee2f64bef07fbfc6a2302173245bf8","nonce":"8d1c3fb2ab77f607b24bedf1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"3304196f0d646ecbc1d00fb95564bbafb68fa2707f2bdf882b3c6c76047554da7305715be50586dcf73442590b","nonce":"8d1c3fb2ab77f607b24bedee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"990bb57d7c15ac198e8d13b1ef2758afd3a313f1c90ab03025e949cd16f9b08aad771bde8b3d742a0732b1843b","nonce":"8d1c3fb2ab77f607b24bedef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"cd48eb657786eab747c550e0f47c8b3e982aef3bef6d965607ca45d86088e3a6a7012edd7c14fb8b559f65dd4e","nonce":"8d1c3fb2ab77f607b24bedec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"8486e44dba7dcdafcbac384b798f033bf8381a3540007431be9db1dd322204648b62d00fc26dadd09deea69a8f","nonce":"8d1c3fb2ab77f607b24beded","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"1355980fded49a3e8a34c7bd6599fb2b66dfdf543d185bbd31abbe33e903dbdc0d85b4e6e5d43dfc8ee4150081","nonce":"8d1c3fb2ab77f607b24bedea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"55e7ae420cf8c6241fddc557d571876f24ac74c2e89a99008abc9c29f50fb302b47cbca86cdf257af105dd0303","nonce":"8d1c3fb2ab77f607b24bedeb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"d88da3d1eb9ce8b52197d1701b64e669719d34b9b4760d396423029ff5b9c7d671f72db8514da74fd8fb409dae","nonce":"8d1c3fb2ab77f607b24bede8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"0742b33aa53df93e116d7e3d64737ccee04fa224163e3f388e8decc4788595db54977239f964929e613632688d","nonce":"8d1c3fb2ab77f607b24bede9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"b3c1975cb5b7e50acde41c7cde9b7e3167159896e3508e100806bb0296d21f0a2083abf37dcd9ccc4ebbfa4453","nonce":"8d1c3fb2ab77f607b24bede6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"acc7e70f84df1ed85030cd2b7434dd1fea1144b3c739d6f26f795e5a520bfa2dbecd97783d89ab5264086428d1","nonce":"8d1c3fb2ab77f607b24bede7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"bc8794dd9bb1d1315a7f7f76006949a597a36c26fe2e10a7ec906160940f699d26e6b06d6f6a618b15eeec335d","nonce":"8d1c3fb2ab77f607b24bede4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"4767a1cae73932a48c226277df0a5ceb3e9a5bc8bc50e231648df1929606c88f2024ad269fe2ec250dd88eca9b","nonce":"8d1c3fb2ab77f607b24bede5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"e9eda6b4c7195ac85c6cf57cd5a61918b0537a81f45ac886273faf3e62214368c76b497d1c58be2658b8b5c664","nonce":"8d1c3fb2ab77f607b24bede2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"4970f90221dceb88d89237d64d3e7fb8842e65d20602129d8478e7d9ad94d77aa0459a6154c25cf3f9338300a1","nonce":"8d1c3fb2ab77f607b24bede3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"2a272882bdc53681ef6fdf306917536b21e2dd994366ec136cf1fa5014136b2b99250e1802d904ebf6338fef9c","nonce":"8d1c3fb2ab77f607b24bede0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"086184109c8b525a3cdbc0ae685f27f40a9568e457294c0e1891a985113e1d62ff31e8e156db41f8cb37f462a9","nonce":"8d1c3fb2ab77f607b24bede1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"3414b739a92679d8efe1e566f6f803d0dbb014deb22685e28c042e8d628d4ca07ef7c6cd17de053ba8bf040009","nonce":"8d1c3fb2ab77f607b24bed1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"8a6cf6641b234baf98940d48266ab044eaa226902090ccbf5602c49757a3f9bcb1e5ed423facf26d20c119402f","nonce":"8d1c3fb2ab77f607b24bed1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"a6906a534b4c44a74bee6771991224316f10fe5d1ef86d528056cdd3115fa2ff86f70ec42849359e7cd9dd4173","nonce":"8d1c3fb2ab77f607b24bed1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"56cfbe96396e02d901ec25695526e1e2f2051dbef3d64658bc671784c82c80347e81c23ab52192c7409ca89855","nonce":"8d1c3fb2ab77f607b24bed1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"5fba52e365a2adda6dcbed314c4ac5c9be4af368ce9aa0eaa721f63dfe09333906acab7d27fbf50dc375c48a86","nonce":"8d1c3fb2ab77f607b24bed1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"79f971626b88f646df726c317b6157640d39700714b50fe88ef2402b5b2b81e95781b65536981f4c5fa462a621","nonce":"8d1c3fb2ab77f607b24bed1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"0891d4310fb2ccde30a34c86a5db54b6add7e84fc447161ae3814be0c80291d310ceff1876ccf6f679e11ba23c","nonce":"8d1c3fb2ab77f607b24bed18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"6c1e614cbe2e2d5d1c02d3c0b8241917d29d2a1ed641d1e87a6abbdd53be4a362227890ea238b9030addc133f9","nonce":"8d1c3fb2ab77f607b24bed19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"d5f14f35237054a9c9b94d73fc8e720c59d0e097e82f26abde257494260524527893b52f10f6f9dde415abe4c0","nonce":"8d1c3fb2ab77f607b24bed16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"ce8a0e1ba0c8df78f2d20a3df75a4fe3581fd032c81ff700170785531b93bae2cd4dc9e4902c1b660449ca895f","nonce":"8d1c3fb2ab77f607b24bed17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"5194cd6c5e54cce062e757b003faacb8fd7c5467edc9d230dc92b21a5e291937cfedb662736e468326d311b629","nonce":"8d1c3fb2ab77f607b24bed14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"338d12854d5bb1d64bb0924b3816995deb9083ccca5f50df2fbf5602237006744d19796e3ecabae60943afb44f","nonce":"8d1c3fb2ab77f607b24bed15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"9e6ed5c06bffcbd12acf2dd87e84da562ae42f339882882ac7ff991595a231c03e35fa26c598988f439015097b","nonce":"8d1c3fb2ab77f607b24bed12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"5ce8ba30fbf85e8f0f4db0247329ab36f4d4df96386a51332d1e82c684944fcd0bfcb2a1b4cdf04664d9bd61ae","nonce":"8d1c3fb2ab77f607b24bed13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"c87c4341dc61e1f265941e8ad49eb142eb5e044dd78aec1247b5c6529c667fc624fe1d1e3dc40420a1a0d8aecb","nonce":"8d1c3fb2ab77f607b24bed10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"dd2352a539444d3b1fcee3a8d4c535ece72b0bbc93f2510c66c2efd92dd9bc0772ebe2a3e804ba7ffa825f94a4","nonce":"8d1c3fb2ab77f607b24bed11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"b4280761e62616876114c6e6d8fec703eaf817bdf47a1b70975892854dcbbdd064a8136b0b904241d5a2133cbd","nonce":"8d1c3fb2ab77f607b24bed0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"d1bfad6473e7e091f776cc01e886f378a86585069a3350317e6324cdca7c0799fba50a9d7fca8608ca277cc4c9","nonce":"8d1c3fb2ab77f607b24bed0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"89b670fa808d386339c2a5b4483b96fd62fb470556ffb80ca5907779262fea6ab47e7f7a3456696e396c621f7d","nonce":"8d1c3fb2ab77f607b24bed0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"b1545096fc7c90640c73c71db88b4db98bb41b1bea4a34b42c18210f29d82a698c1beb562467f6c54e4e2c1687","nonce":"8d1c3fb2ab77f607b24bed0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"8364c7a648e33c695527bfdc34ebfa1bae6cb39b694f31dc8f5984db641e97eb6f8f5fe2674e84bc9a9058533f","nonce":"8d1c3fb2ab77f607b24bed0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"8e4ba1a884f768bc9c4308c686a68ddafe96cfd5442b5b23cfa770aefb9e0062bee009120d279e8465805f4f73","nonce":"8d1c3fb2ab77f607b24bed0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"93085a1a82d346547df130569b4fe1c90efaa790e86cfd17724ba9fed63b36ce628333d5b5d133f88bd62840fb","nonce":"8d1c3fb2ab77f607b24bed08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"2ebe9dd751e78a00e043616f24e537703b40d992ddc43bcb74826b897161404f6687a326930db56bdfeaf21510","nonce":"8d1c3fb2ab77f607b24bed09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"3170c1f3fa9e90f3439bcd504f3b00d6ce197585bab636645e312ee839aa671449140252e716ef56f544780200","nonce":"8d1c3fb2ab77f607b24bed06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"1177c6544031555609d1edf25119ff4d1b82bac876e752af714c35174a45d0e20cdcc8b4a825ac3f9b5a2f7d5c","nonce":"8d1c3fb2ab77f607b24bed07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"90faec46571daa3b65f2b0a35828a28fe62a5fd0f8fd25ba5d980a4dcd61fc60bb3378ba372950bf58ffeb239d","nonce":"8d1c3fb2ab77f607b24bed04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"176fcbf9e7e9c7c9c800a43eebd57463abcafdb0720f8f8d40510601682955edc45324145280c98c56830e1ec5","nonce":"8d1c3fb2ab77f607b24bed05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"a8a88927c28932ad9dce1740824fc1ef31925325e6efed453a17558146774a0230b91eb8cf3f4c81efd0b1ca41","nonce":"8d1c3fb2ab77f607b24bed02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"27db02c1681426f302cdd9d54f2d2e64e2ff128292116e9e14f86ea78b758be2c68ba9191a36d5969213bee6b3","nonce":"8d1c3fb2ab77f607b24bed03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"55dbfd2141e42f8d7b0048babe1709924c7c0cf44a9ddae05e9923c8fba1ca9cd6eb3f76cafcc253ff0b9f0af0","nonce":"8d1c3fb2ab77f607b24bed00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"e106743d5abbca4293efc0417142bf5505c180ea0629564df622dcf3035dc7660aca2bd20a91b19f0e89c7246a","nonce":"8d1c3fb2ab77f607b24bed01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"1397324ecdeea87ecd60643084129658218220269a1a67ef67c7fcad5b170dc26b81535c5b15129d5f0b5914e8","nonce":"8d1c3fb2ab77f607b24bed3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"18084929dd3c30820c6fe049077678357b6adb80e9e79121a76040b767fab14a29713e16d3dc6bd89843dc9673","nonce":"8d1c3fb2ab77f607b24bed3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"0a93b5be094a722af3c5c8a8713bbbaa9ff89e79096e873e2bf4f62f9e8abfd3b4f1104e777e30687ee546a9d4","nonce":"8d1c3fb2ab77f607b24bed3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"2d2a04599a866ef3bcf4d0c0c5bffecb0624b22d87a25a9459bf34577ec2bfeb309d2ac1cf9d9bd71ca5452421","nonce":"8d1c3fb2ab77f607b24bed3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"56e358c5ea27d23937c2d4c3aeb9330511b19e8125a4ab9e77ba57d02db6e6404f13226b5b3820eb1538f25bf4","nonce":"8d1c3fb2ab77f607b24bed3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"0c843659be84d98db72f6333f0b906298c9a6158e6b78dc03724a65a49d141a2e8eef3fe2d5434f49ac1f77819","nonce":"8d1c3fb2ab77f607b24bed3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"0502124a9ac1f4b4aba2f8b1b913535f344c39a2f0605b1431347374cab7c2384694e7334223295a0d67773f7f","nonce":"8d1c3fb2ab77f607b24bed38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"77dba216634f21afca6fb006b6ff764f5202351b37f12bd149c862453d7bb9ae417208addda29618b382646fba","nonce":"8d1c3fb2ab77f607b24bed39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"3e0e18993d0e92a956fbe7737ec2e85979b77bb2dbbff7af02af394a41137388651e11fed56fb064151c191cde","nonce":"8d1c3fb2ab77f607b24bed36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"878308edbdc441d15fae1b67e0a86dd8de26d7e9dc552f1154b0dea4e0e5b77d4f7fd5909d7c5f42f58dd306a6","nonce":"8d1c3fb2ab77f607b24bed37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"debbbd2d1c352ab3f189f37e51a29ea5e376e56004fcc0ee17bf6dfd23b66b87d51a0d212d76b2a76b64c83f4f","nonce":"8d1c3fb2ab77f607b24bed34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"765d21fbe1ab4015eb4421310d26c50faa651828fa30e422604ceff60f7947c17c50511486479ecb9614108d65","nonce":"8d1c3fb2ab77f607b24bed35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"6a7a29b4c94213f2f42f057481de792a91c40bcdbb26e650c0f96fba2620b9d4acb5c094525f59c3dc1299ef79","nonce":"8d1c3fb2ab77f607b24bed32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"7fff7e0ad7ab73ac577629f5fb671f2712c4d3ee9ed5bd71a69f072fc58c2cf4b4003d70d746d314d922227497","nonce":"8d1c3fb2ab77f607b24bed33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"8b9f7f6038bce3a9b0cd7ab49e9cb18bae8bdb58425132ed0bb627f084ba3b6a1a4b7a99bc1d7768ce48703d3a","nonce":"8d1c3fb2ab77f607b24bed30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"df5d2fea5e42bb551f6549b14472308cd99e7cded07c01e48cb2bd2baedfdae976147f02becb18ffdce7bbf767","nonce":"8d1c3fb2ab77f607b24bed31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"0fc5055893cc437b4165802d33bbab4dd1e68d42dd1bc34efaab9bb690e6137103c3ed21db91aa395f09d89fbe","nonce":"8d1c3fb2ab77f607b24bed2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"88e065ee9b2c7babc0581452999af012598b57a52cdaf231e1bac64bc07a49a26d2604622f4c48e6e035521902","nonce":"8d1c3fb2ab77f607b24bed2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"d9e1deb232418a2814fd4e0132ecf0413b4836a59b93180664706ed74db00fcedf560156b1201ef01d6b5d1a50","nonce":"8d1c3fb2ab77f607b24bed2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"eb52806e746de09045d13025f82c5cb8270029a166db3a5cfc5d5afedcfe0e0db0bef5ac776dbb5a42861b549b","nonce":"8d1c3fb2ab77f607b24bed2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"01dae495657d4833cf00e2337ab13ba4452da3ca0986bb1cbe48cbe89b83830fa93ce23b59a502f31180e2d2e3","nonce":"8d1c3fb2ab77f607b24bed2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"57fbb74f4482839e21bb8938c1c6c61c69fea53bca4e9b52847bcc8c28373554d9060638bce7a1a1052607fa0c","nonce":"8d1c3fb2ab77f607b24bed2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"1024dc667f5f7c66789878afdecd09cab81f4cff8458f33c2eb8902f140b0dd786a005838fa78a8633d15caeb6","nonce":"8d1c3fb2ab77f607b24bed28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"21599f2d940516cfd25eabc612bf532a992d2e88c2587aac8cb7c25c452ef07ff8c4d7e89e6ff2b03e473a28ee","nonce":"8d1c3fb2ab77f607b24bed29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"32f1971869f2daab44c073732be463e6d64918c0f6a336bd762ebb0026590cfbb580785578204fb9ec8c95ceab","nonce":"8d1c3fb2ab77f607b24bed26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"441a06d4999c99465ee117865485883cbabf9721df5ca0321424d73f93532bdffdcf4044d11afcf79d486470d5","nonce":"8d1c3fb2ab77f607b24bed27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"065f08028f4f2f21845eb17f9cf0c8de8542be017265b8493412dfa84f0d94886052a6c9256a09284dbcbd18f7","nonce":"8d1c3fb2ab77f607b24bed24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"2c2954dca8a33b5b8befda54ddfc3700c5c89c480c5a2bf1a8ecced234aa70cf66f97576c3e8fb178576a9678e","nonce":"8d1c3fb2ab77f607b24bed25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"da007c8e8797b29e81e136077a7760e43e9446a58dae62f1f9a0f44b743eab5c32a65134bdfd038ea360e81baa","nonce":"8d1c3fb2ab77f607b24bed22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"c7b3bb5a4e6dfbb903e9d158c195bd94c861e82a4874e8956e331dd5a6b81c8e52063b19ca73f4cdd0f055511d","nonce":"8d1c3fb2ab77f607b24bed23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"fe88d7206c99d56a32b1e0ff6da4fa96d89b83671880acabec2a467c78e347aa97e8f440d432b248d8c0bc1d72","nonce":"8d1c3fb2ab77f607b24bed20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"aeaa40aa2b9be38ea5d459a8da095a61628df713e8559db3aae8876b337f5236ebd8178cf0438b645ab20fa21d","nonce":"8d1c3fb2ab77f607b24bed21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"12e29d710510958dbacbd8fcc1b5dbee596255c64e6aafd382ae2c9f83f38e1a7305b6f7000d73acef2b1e802c","nonce":"8d1c3fb2ab77f607b24bed5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"d95c0562ac0b554a9f9be238af137106556746b12ad47950d4503402ed28bfc9e6c3054e64b15e55a197c237db","nonce":"8d1c3fb2ab77f607b24bed5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"2268b2312344738d922e25f36ebd6e42a80a68dfb8ce395295f8fba29711ec118c68d14f59b6d1c55d27ed7038","nonce":"8d1c3fb2ab77f607b24bed5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"5f957dd6df285293b7f4a1efa2f6888c7e42b85839d30b9eb17e5aaa07a751f1fc5b8d986800e23927d20a0ef7","nonce":"8d1c3fb2ab77f607b24bed5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"f05fb1c365ea63fbf838155a0c3013d0b615bd79ed81454559739757451a94aa206105c64c96e61a9b2fd27ae0","nonce":"8d1c3fb2ab77f607b24bed5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"4893c6123d24e5e424a95c056ee0301ca73cc685c8f371fdb527a82120df31d756112c6fd4e6b946f8b05faf09","nonce":"8d1c3fb2ab77f607b24bed5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"efa6f611718113d870fed0feb0ad8dbb2aeb257b739bff86c00eb5c0bf4c6e85ec38525037f37bee0122becb21","nonce":"8d1c3fb2ab77f607b24bed58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"a3cad87724abe7a7f51bf99ee05e93005708daf0e3a03512214c1ed59ac2e56d5cbbc0ff8ebe046071bda749e3","nonce":"8d1c3fb2ab77f607b24bed59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"90c76dc7829b25886bb2b311b3f66fe4e55094790dbac5ef334f08ef5815f6f76ea77947d7b2c630d8e7f878b6","nonce":"8d1c3fb2ab77f607b24bed56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"ca4deb88286c6b8c84d9b80f4250d89f0f886f3fa74d047026fa2c84f7d14600ae278f00fecbb2a3afc07e26af","nonce":"8d1c3fb2ab77f607b24bed57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"9ad71455bde964c37da464b74bbcde4725d1d78cdf410e8d78625d6526c2e5672d7d758c696849c34b1bde16e9","nonce":"8d1c3fb2ab77f607b24bed54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"bf2229a23a7c6f795e4364268dcca903f4083aa4b4c09aba5c1feb71f5a70efc82692fd3f08008f580e8c27860","nonce":"8d1c3fb2ab77f607b24bed55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"4c25df63f4fd394a33aaeeae67954c0d9888c12414cdddcef16a208e332905813bec874296ec47f348067ea096","nonce":"8d1c3fb2ab77f607b24bed52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"701d8fd375fc68a386cdae7b66a24f85f8353e92c9a616a80e9fc37d106d8aeabfb8e0a176bbbeb88203368062","nonce":"8d1c3fb2ab77f607b24bed53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"f65bc66e390143f2dfab91672cb8c36b58272b93e1d7237246b5f8c91c37b09fe432d8a195f8840410fb089f73","nonce":"8d1c3fb2ab77f607b24bed50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"a3c0eb461c07f7b178f5600473ecab5d0d0faa44d53dfe7324e9a5e494560ac8d24abf6d733c9b35b694544c95","nonce":"8d1c3fb2ab77f607b24bed51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"7391a3e05f066c977bf7d3415118fbf86d5972e5259a447a03bf7283fb41109f971d7ed45209fe996d0582fc17","nonce":"8d1c3fb2ab77f607b24bed4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"0e570c3fb6179cfcfb32a8276e4677675346180c3df1921056a524d3dee0a1e0a3e879057750aa40992f91f483","nonce":"8d1c3fb2ab77f607b24bed4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"d5b724ff9b034951914143113f4b54bf9ff87feaaa33cd1f33543469814ec43cbeaa91cba2596106205b21a2a6","nonce":"8d1c3fb2ab77f607b24bed4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"10112aaf56a6f24b2ed7fd1229303cea72d815143890ceb1e5d452c9d6999d64a7b0927b2a4e4a17a622005793","nonce":"8d1c3fb2ab77f607b24bed4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"03b6f9ac8d933610b01eeab46d028ccde3cafc3e3d3a6045fdbec202819c871f11bab60f03c674052f25009cda","nonce":"8d1c3fb2ab77f607b24bed4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"a156ee0fe23e06c517db211b08315b88b03f7b304882af46888ee2c81d0544f46c35bafae7c5eb44f425c12bd9","nonce":"8d1c3fb2ab77f607b24bed4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"4e86f299041ab02756a8a552f1b5fa9e08679ed3184870df65483e7040cae18e5c6494790f4775ee151c4c6f48","nonce":"8d1c3fb2ab77f607b24bed48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"1599ab7abdb46c5e4d321403907d805456875054103bef295d953e0daa2a72312d7e778f80f28720d8c51dde3b","nonce":"8d1c3fb2ab77f607b24bed49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"c0f3e4989774cc55a299234c5398209dcc082304355b9b391238f5713313eaa211c4fbc672407216f9415b6972","nonce":"8d1c3fb2ab77f607b24bed46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"7b677cdde0d01cd817d20ca0b8189e42fd8b9bcf4e5d38fb664a5e4b31b80d9760bd77c9ca3422aeeea203b688","nonce":"8d1c3fb2ab77f607b24bed47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"b8baca3ac37c195b5565d7f5a6e4fbebaee9c4c17f89259ec146b4bfdc8bb7772901dd92cc78e34bad334ea4d5","nonce":"8d1c3fb2ab77f607b24bed44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"a4c28fbe1d662e711009962e7b66071ebb84d69f7775b2e03e91af3b1df18e01258b90f8f39d6eda1d6fe1b7f3","nonce":"8d1c3fb2ab77f607b24bed45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"57e5d11f77f797832965bd7277181edebb2c912fa2e71302846d6558c86c734384c51590b2a5dc4d338eac9218","nonce":"8d1c3fb2ab77f607b24bed42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"f39f0997f0334cca97f7a163e4a74a28518838dcec683e7d7ae33749991eec44214afb62d8244fb9e5b8f3a4c9","nonce":"8d1c3fb2ab77f607b24bed43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"84527af4f5ef0e87a2fb2ea3d7de68c3036057f2dab3d669e39dd0047fe386f3f58214afb603ebfb6879e02b67","nonce":"8d1c3fb2ab77f607b24bed40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"ec09c7312ef490abd8dd00f7c680eadfae344084cb7e3e35f3565b9f29388a505616f1edd937ebbaaae9cecd7b","nonce":"8d1c3fb2ab77f607b24bed41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"d464bd75405f7384f5223c07cb3d536a14b997c88cf3c194b2ff50402cc4801b975c6770a189c35c3896a1e592","nonce":"8d1c3fb2ab77f607b24bed7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"0b6b2cd5d2f6de66c25fcae36cdc439c451f219bf043ed15c60e3fe2ba795fab67d6ae007940a3335573961b1d","nonce":"8d1c3fb2ab77f607b24bed7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"53768ba4284a53510ad2fec7ac122b39c39bc7514e4bb1168f48db4419c0d32c0cc50c345583d8fac317f83899","nonce":"8d1c3fb2ab77f607b24bed7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"a8b8c289c1903f4cc204a4c179fc8a634f373ae6e102fb9b3105f7372b65a0774ca7c0c86616c4c1e5bdfa3ea0","nonce":"8d1c3fb2ab77f607b24bed7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"d66997bbd516fc24d49dbf1b93811746f90e5ef21f71665c338df3e20d9c673055e3fa31184256eeef2a7d54ca","nonce":"8d1c3fb2ab77f607b24bed7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"c557da7730561d9c7e3555ded2fdd734e2e04447195e84b1f0a6c427d4a4167bd44257eb88abab7b6f2fa7fb28","nonce":"8d1c3fb2ab77f607b24bed7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"28156b668062e1207c213932e80ccce6bf523c3fa61a0d1c14e5fa6a1bf5abc4277ab3ce67af164f8e7b876335","nonce":"8d1c3fb2ab77f607b24bed78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"0a2587becedc231a4a839cb95c6f6a2b58be77d92272f2c3197ed6bdcc5ae3582b2311709cc4d8e8e87ed60e83","nonce":"8d1c3fb2ab77f607b24bed79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"883393a563abeaac6284df7822ca9b5b4c6c89932641a9bb96b454ec30d0563a5bfc37a2c53d907478fc8feb6c","nonce":"8d1c3fb2ab77f607b24bed76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"2a26c2a19e698b463012e01af587f4e657f900ffd38d6a2038a6abe43a33c4509dbfefca07c0463910a814eec7","nonce":"8d1c3fb2ab77f607b24bed77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"8861692f9ddc76a3fba56f9a1bee6ad685f9d85ad9d4241e1d485df06139b24b56be4fc1f3aa6e3e366b0e959b","nonce":"8d1c3fb2ab77f607b24bed74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"5d5215e93e34c3c20f69a73a3f93209776be2c68ca69795d0183ab950e6b59e9a70c4754e9c16fee36961000e4","nonce":"8d1c3fb2ab77f607b24bed75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"599440ad905951c6268801fe6c88a88e5d56e9db3831288927f8035861e9ba28709a88e4d73c1f06d2dab04720","nonce":"8d1c3fb2ab77f607b24bed72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"b7b51f1c8b02c3954e674080e6ff54e4497418ba7ed93ddf8a251165234feae93042790b4ef2be3fa80e6a8f3f","nonce":"8d1c3fb2ab77f607b24bed73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"2889f59ae20652c2f979b53d6bba8ee90c4daba8d00f863ee428e46af3844e139888de704a315fabbb1df8d2b1","nonce":"8d1c3fb2ab77f607b24bed70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"1ff097c0da19aeb31f34bf08b500ca6a82d928fb03f00f2aa35ba72d7cab292bffce702a0faad650041c6da2f8","nonce":"8d1c3fb2ab77f607b24bed71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"57f6a319acb53d3b4a930ca519d55737685d05b8ea2160fee8c38d7503d61c42cf464c6b2b8a8aa176facc1237","nonce":"8d1c3fb2ab77f607b24bed6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"c6d1ac31944a6248fb2e81a7801f25aba6d46e1e8eda8aa3a79f72c921a30eb50b55558d69cad7585275c994af","nonce":"8d1c3fb2ab77f607b24bed6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"303f7027c163b15f1925c3d0da4125619a7345858b708f8935cff78e7cee97b5e5e822792b743fe938b786a488","nonce":"8d1c3fb2ab77f607b24bed6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"2338638bb69363d370e29f1adc58e3c1e86d75b0b43b056b29347c0ff8d408ddc6fc088200e1dcccde49c4ec88","nonce":"8d1c3fb2ab77f607b24bed6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"558d24ddf6f2d407cffe3daa378a3332dcdc62102ac2ca0e607151f13edfaf537951213425b06ffb1e43323988","nonce":"8d1c3fb2ab77f607b24bed6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"f33e4f4afbd6687c54c479b9183ec7d07c376b46a3a7bc670f52bd930417f08158f56aa532a19b1eeee2446e8a","nonce":"8d1c3fb2ab77f607b24bed6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"094e3072a6be1169b4f2bc36142dbdaeb5554d2309a7812e6449af49ec0422c4af753c59c81ad2fb7b1b936bfd","nonce":"8d1c3fb2ab77f607b24bed68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"19e79c16de3de759374b9da05faa26b254f6d872f399a636e44036ff90b03a9b68ff3e165adb7eaa4947122bb7","nonce":"8d1c3fb2ab77f607b24bed69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"4968dc2c14d9680cfcb74b1b095d75db481a8e0cfba2ff0078f2a23a6b98ce71b90c9436c2ced394c79a1d1535","nonce":"8d1c3fb2ab77f607b24bed66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"107c200cb2c741569dbe4f6dc31b07d0904944c3163f10f784bfd3f0a0cdcb4834a1e590183aca3eb20e80b2f5","nonce":"8d1c3fb2ab77f607b24bed67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"ea53070c934bf6194acb6c0eddd3133b52d8ef8c8609c118d48abef4b625b499515618271e63ae139c4ce43ae0","nonce":"8d1c3fb2ab77f607b24bed64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"f98a2ce11017194dc0988afe7f8b53205443a671dab3e03415d0459cd3008efa46a5e66b77923d2769c6d3347a","nonce":"8d1c3fb2ab77f607b24bed65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"d13ecb3e929d0a26af7a8ce439d5ab7cad2cb5e517ad273e0f172312143c494955d55a69f1735b06177fbe1efb","nonce":"8d1c3fb2ab77f607b24bed62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"48e7318dc4c75aedf96b8738108a751490bcb47599abf7f10fbfbed4de0dcf3ff4810e828e0c4d14db2ab8586a","nonce":"8d1c3fb2ab77f607b24bed63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"3e235ebf34ae079a87e104310b4b8d7eef79523710a4e4113cae5588273879f63086af622e5a635bd370616836","nonce":"8d1c3fb2ab77f607b24bed60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"cce2b387ee2c916b012607eaa3465149280ca37947e2f97aa7ef76d51c39a60d2c1043b65e398a592ff7870b3b","nonce":"8d1c3fb2ab77f607b24bed61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"19c844c11137a479e193f28e0ecdfccb0beeefebf10a312821a13fc5fbff9943eb2857ca81d954b9b9305e2b4a","nonce":"8d1c3fb2ab77f607b24bec9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"f6484c609d61b8868629baee1aff544f9142aca6390bbc79ec0146dd8b578012"},{"exporter_context":"00","L":32,"exported_value":"098fa6fc35254380dc7848ca86e6ed32c79029bcd8355905b97665e6d0cc218b"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"ba42e9a834c73ac86acbb6c604ba4e506a3e83d1ce4e5d7ca14ce965b044acca"}]},{"mode":2,"kem_id":18,"kdf_id":1,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"c3bcac89a3f2e3418c85ca4943e182ffe25335a59489c7e2439089f3ea2fe109e8a443a05e5f50b24bb5c813a34f3f72c62a073975ec1a695c46225982a80b428e5b","ikmS":"814311a57e81c643b713a12407ed99b24beff31bca84b1c55c7e6b4f0f443bf7413b83c79726a786f66d91fbf97d8ad7f65e33e151b091c1924cacc47a46e7983b00","ikmE":"c7cf8ca2c79e9a3d05e7074a3732c6bcff89c01727b75ea82f7fd35eca380932e2b1846b7d2ce692724df02a5cbd9f21f02aa3722668010b05edea9ee1ef3cc8dc3b","skRm":"00745354af19660bb98082fe557674b3c4c8276df4ae8574e4aa93ec3ccc5cd43d51c30e726d182074a368df6911230ca64e1ca6ebd8fd2635b694da262e33128b2b","skSm":"00392721b5af4c3af5c024e9a40482b4b11c1370e561311086c0c8a7a1b868f6d642c27f7f675e4e0cb3e64c1111dab80d3e4fdc2c708b052ed134770a6e9bc511b4","skEm":"0014d618208c065c3abab743b7d4f867e1460e73489cbeb707ed753dab9bb01f3ca54e1fc61d73a0134d1e2f33c89b1ab67361563e5903491495a96c4d9e99b66dc3","pkRm":"040199783d366cc5c4717a677472c16c3e4de6fb689fc9dc14309583971cefc10aa6cea7fe60628bb66198f01173bca5f34a7b8414901489334940c3428c5d90b9039700f0d34a9ec7b6e713fe88e66af2248e666aad3b3526247f453d6a52ae6a09f17ce9685825f21a74045aebb3564a8a7f67e95aee926c6c88f4cdaa617c75e6c66bbf","pkSm":"0400e4c25222733ee29bc1a3acd2e081a041e8a6e057d957f13b77a524eb8df5d1387fe8bac4e1acf720b64cf145e781f0233956bb1dbec441786f284987d47b512896005b5d47bcf219e15a4232883e57a80dcef9d7d826fb582dd03bb3588c0337250fed41d8659e5cc933614303387cbd6b4f1989dd6756284970d4776c0995038e2436","pkEm":"0401c99d7e9c4a5f77f583794051d8abb5b224a8fbe5a913ffd8581fb46b715076ad9c78f343788158afa4bdfc1c11ae1d897b7f297456670a391c93bd8365c4b4f0cb00db3e95ec7fef6114d6c5fad22b87c010bce49181c7927fcb7728fffb5c85150bb97626a16303e521ac14d9e8f5d56ffe0461e5c309b9df5adf04f20ec45c7f225d","enc":"0401c99d7e9c4a5f77f583794051d8abb5b224a8fbe5a913ffd8581fb46b715076ad9c78f343788158afa4bdfc1c11ae1d897b7f297456670a391c93bd8365c4b4f0cb00db3e95ec7fef6114d6c5fad22b87c010bce49181c7927fcb7728fffb5c85150bb97626a16303e521ac14d9e8f5d56ffe0461e5c309b9df5adf04f20ec45c7f225d","shared_secret":"f447032a6f60c634a554b840de9aed396c472c7d958e4d32709acbf1de0ca325b540325dcd405836e73ca713402b4116cc584ec494961e962a79e728e21d9670","key_schedule_context":"02a0f09fdb725155fff851d16495e4a128f92a4332225913d832a5b87e19a5552b2c567eba65d69b8f94f5dd45f30ba15730e09a0ca1bab72cdd2606fd3e4a6c69","secret":"d00e4f80ffe75737a88f3311218513716af2cde465c300c2fb1126d4d9785007","key":"c1eb0890a74a6ef1a0678fda982c1859","base_nonce":"2ddca1d3c6846f03f66a4503","exporter_secret":"7b225167371d47bd158f10a0eec03283ab867a3589639a871f4f851faa714f37","encryptions":[{"aad":"436f756e742d30","ciphertext":"64843c141014d191d3b238266b84724672c1f458d166ebd9cb0614fb3bb6f582275c0cace2fc43df0b8c87c575","nonce":"2ddca1d3c6846f03f66a4503","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"c44f75198f40cffdb3c2b8b6bbaada41a058d45e24f24fb783b4aa83ceaf8f2e8593e0c7eac63b70dde1ab583b","nonce":"2ddca1d3c6846f03f66a4502","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"1208ded00fc8f4ca13bb5aa44f825ccf8d665b15c382cfc3150125e65e7e6a8c216925257ede9f8614929e324f","nonce":"2ddca1d3c6846f03f66a4501","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"aab6bac418289ade062246dedc4325696721f7be7ed725ae3c5ba258c07861f253549c3ac5128e09e4c34e6a83","nonce":"2ddca1d3c6846f03f66a4500","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"6b5e7b13f91e6c21cd8f6c42a2d699614f53a992dd1cc1d586f485ba455d5a5da2783ab7323c0e500b43aef439","nonce":"2ddca1d3c6846f03f66a4507","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"2acb477ddb00ca2817322b35bc06b386f3dab28736abf96ec76e9c7aca7e255213f66920da6693f74fc7f26b24","nonce":"2ddca1d3c6846f03f66a4506","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"f3b64299cbc65ed0283ceb050634d37caa4c3176d7aa6f992324c2f14736f79c4ad2d8d520544727aa2bcd2490","nonce":"2ddca1d3c6846f03f66a4505","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"71b704a8b0dd1b511e4a53b6b4a9fae9632b96f3c4d2ab55e0b50d3e558f89bf5efb2fb4d4d74c2c086a9e9cd3","nonce":"2ddca1d3c6846f03f66a4504","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"351d5048ce0d9f3384dd537cdd9a0318993992e1aed6836ba134f37c9fedc0bda7d01a269d9c3ce56d14d6fcb5","nonce":"2ddca1d3c6846f03f66a450b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"019c843b3a6372a7b1c88634436009a16448f91c96cd0222d9e9f07d9aed837040ef6342d73014d7097a3c4846","nonce":"2ddca1d3c6846f03f66a450a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"ea66a0bfa19992b8d67db518e8fb9d8f2414818264a078835ee96f46ecf6d52671dbc40c119acfadcb077d79e9","nonce":"2ddca1d3c6846f03f66a4509","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"2018b6baf91a0373831af91361e5f65167c9dca132e131da62f4a2a983d5f8c4470c425702dddda4e6dc010ca2","nonce":"2ddca1d3c6846f03f66a4508","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"8100d24f76106f2bbc0ba1c510907b0c62e00bcd743e82120920255d470ce5e484da981709dfc463af5df65b06","nonce":"2ddca1d3c6846f03f66a450f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"818612452c0be16eacbea5d0b0fa8e62ec899f7749ee7548e3f63fef7cdfa4a86568791c78576bd3471b7f20ab","nonce":"2ddca1d3c6846f03f66a450e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"6fa77b871df8d7bb5bc7d4d68971d5a96847ea55c408b5e3d6399fb3a95a732c57cca329b1a1837a9e56a4284c","nonce":"2ddca1d3c6846f03f66a450d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"ea8f2021aa81af62aeb2fcf7c69c1b81564eeaef8fab7b4c5e6ce9fe1a5d0b39413aa06d166cc8c1fef64f19e5","nonce":"2ddca1d3c6846f03f66a450c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"80b1893587a90520852c3bb22acfc135bbc1624c29cce5e5b4dfc9b7b8bd29977da73c0019b4fc8c8751656127","nonce":"2ddca1d3c6846f03f66a4513","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"be8ad5389bdd8bf43d5aa488c4f1d7c90f917659f120b66a08d91bc481e7b4162dd6eed893373487b674a842e9","nonce":"2ddca1d3c6846f03f66a4512","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"1fc6e97a66be354612c5a01391689ba73d6b922d4d5d0eb39537250a4ac845274217a2de42e107cedcfd5dd099","nonce":"2ddca1d3c6846f03f66a4511","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"223ec358a761e1930d0ea43f36a512a7fd557dda2e596c45019bae7abfa93f08e2c104729f7bdb7f50db9bb0fe","nonce":"2ddca1d3c6846f03f66a4510","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"8ca0dbc8d5309e42732cbbfd60abc9c058cf97b0808c05363b7792b54e8716ec178d42e7562f8e064fe2b825e6","nonce":"2ddca1d3c6846f03f66a4517","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"94007f225770b4c63eebefd39e2f866fc76ba003ecf347bbbd4cb2c7abc1a880c8ec80857c132e60527a9f7b41","nonce":"2ddca1d3c6846f03f66a4516","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"a544478ae7491b32f88f34864d5d603e313e44b986fea438ddc480be71e67bf5382261b36ac050dcb09a4d750f","nonce":"2ddca1d3c6846f03f66a4515","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"c6a78ca946571965c35a07be61d1832032376e31ce690c0468271b27838766b50bc076d30dc17fdf2ac2ae8401","nonce":"2ddca1d3c6846f03f66a4514","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"24a285e28797836f91c1e84d6233be9942bc4799af6b3e3e28eb25fe515f7031beb8aa9b99b8a478d39470167c","nonce":"2ddca1d3c6846f03f66a451b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"6763abe074711763e6c242afdbf5ec21216dbffd76d3266e0ccb130724e92a8753098d06c4ee461a457d54d25b","nonce":"2ddca1d3c6846f03f66a451a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"72c6b5a5fb4511866e96258b8537f9386f620325de6e4370fe626b3d97b14c04eed492ca02aa219a1560b0d7b8","nonce":"2ddca1d3c6846f03f66a4519","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"70c98adf4b387d2898f7b28646f1acda6cb616555ee49200ffb9d81aeb8c8409260a9603a1dcaf899ac17e25c7","nonce":"2ddca1d3c6846f03f66a4518","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"e55bac0789d8c1c99149edd91e3e43be61cc8431eb3020e43c2c082c7e81acbf2ade32718f9fd2db3750a674f9","nonce":"2ddca1d3c6846f03f66a451f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"36c9ad303e800cc8479822f480847c97208d7d01c11b3b9518e451e687b491c03411b9ccb6faa7f198092355e7","nonce":"2ddca1d3c6846f03f66a451e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"d8c84f6c5be57ee085a4c9a99345b031e951c6312100508c20ceb576571cd5e0b12f75ee316b86467163a32aa9","nonce":"2ddca1d3c6846f03f66a451d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"48a12d8592a6e3fb81412ada9901ec36754143dd91503b75c594b1fba4c13f444f9fb4a5916c2fda64ed14385c","nonce":"2ddca1d3c6846f03f66a451c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"325b09c1363b5b41d4c9a90f405ead75cc681eb9159cb7de6e1f5c3a01270a08614dd8b83460530f50445974e2","nonce":"2ddca1d3c6846f03f66a4523","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"b1321fd3c8e83b85a4bf10eeb7643a70eff1205ce4f8776859442eebdb259a64c9367de8707dcbfba60583590c","nonce":"2ddca1d3c6846f03f66a4522","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"86eb40a2ce6b1641bf75efb37e5d89d0b12c6c009b09c153717b0d322301b78aee27b3f09e695a79fffdb5e9c1","nonce":"2ddca1d3c6846f03f66a4521","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"18df115e054653c735b0cfa7311a73e7adebf48852fc3142272d9264e309ae69c60d32682b13720266406641f7","nonce":"2ddca1d3c6846f03f66a4520","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"7c7e4cb5a5c6cfb09f0caa4b776728c8d1fd7961ea53c74f03f004348d3119d4f14baaaf04b02936f201e4715f","nonce":"2ddca1d3c6846f03f66a4527","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"ba078401c88addf565927943e55400db15ea551770be36c74eab9cec14a2dd2a173b947d6250e793b9b6e284ce","nonce":"2ddca1d3c6846f03f66a4526","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"e6abb5b0246943acde3d036685a5ae4de58e9da91bc88678bec9608b070b02e6af1abc61190d592426f17c9e40","nonce":"2ddca1d3c6846f03f66a4525","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"1e1591b01826877a45240d50c33a9f3bab84c85bcad45b243a8e1003233d9deda88f373ca349126829b6782094","nonce":"2ddca1d3c6846f03f66a4524","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"6ab5e59c1454ac276b327ccc669dc4808b0088717f66d298b222ed3207f60717158f0b1130a45914a092a778f8","nonce":"2ddca1d3c6846f03f66a452b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"96a42a5958c55bf795a1683def09fecdcd8e761fd97d17b0e195e28861c7b7bf11d39fb81cbd2df00801275d70","nonce":"2ddca1d3c6846f03f66a452a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"18aee60dcd72022b948f1e785a9e6519914b57680bd22bafe8f8a7d18cbf096b8ed28bd0a86856d5779e10c98a","nonce":"2ddca1d3c6846f03f66a4529","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"248309bf49e01bfd86f5661138e043162a55b17757571fb8be4399d98c68116416713ffee9021cf863337bb691","nonce":"2ddca1d3c6846f03f66a4528","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"0e0d7a8c55636cf57208430a10c21961869cdf3b6d00d3652a329ff1d389f0f4f46b8595055afe924d833846df","nonce":"2ddca1d3c6846f03f66a452f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"dca120216b145749a451ea2dd82d25ae6bee10c176240f79fcfbac4038c0e6d44a695c1050b706ea12ccd684c1","nonce":"2ddca1d3c6846f03f66a452e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"0a4fd18461e55c182b921c0c9ea41cfc01eb5f64f83f87007ea6e4f6ec9499f40d169356d0f1c6fe1452cceb1a","nonce":"2ddca1d3c6846f03f66a452d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"a84c2eb4d3bf241a3923822d22070fde81693f9c0cab183ea9d2bc916841820b8e24cbb883ea0dc041d758beda","nonce":"2ddca1d3c6846f03f66a452c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"71075cde42468118ac3ff6037728d8e1eb5aa680cd2415562a557af5b94219e63c1fb29b073f3758c36529233e","nonce":"2ddca1d3c6846f03f66a4533","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"93d4b9415429e4705b7ce72b3a0fe21f99aecfb6a21114e3fea89ec674f2edeabbd3c2b37414fdc4930ada563c","nonce":"2ddca1d3c6846f03f66a4532","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"2ecbfec52e2f66a58b9f291e36652ae67ed2785e3c4f25826fb1898e6525a03ff19d00810355beb6da1f81a7f6","nonce":"2ddca1d3c6846f03f66a4531","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"700d9522264e5191fb06706417387cf62139b503c7ac07c307c056402b5d6d825566988121a85c1bdf0e8fd7e2","nonce":"2ddca1d3c6846f03f66a4530","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"5c3bc7a51c494813ac0232fdd1642929bf2f81453248f325e35a2795b409256b8a654fd25442756eb8b78353b9","nonce":"2ddca1d3c6846f03f66a4537","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"838fc082bb601678ed836123e0b7c6fd4a0ff42928892e95f8dc1dce3c5738d1c4926409a7c1578cb910abfddb","nonce":"2ddca1d3c6846f03f66a4536","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"05709bbe0e0db14657cb207978ad5113b4ddcacbfdd6b340fccdc08ec7ecbfba72fb9563912d19d13613c96dc4","nonce":"2ddca1d3c6846f03f66a4535","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"07234af9dea8421b7bc7783ecb70b2c549794713ec06394da255ff71b5cb6e07a3e97efb1ba35f4f9ab5ab6b58","nonce":"2ddca1d3c6846f03f66a4534","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"da72a3deac6cbe5ee5587daedd50733a751043ef39084c70dbc4918f2f72394a7349e9430ad7cd9c603571ce6b","nonce":"2ddca1d3c6846f03f66a453b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"869f9d1c73847066206dcaf3fc45145f4854ec5334f37c885f866652c74fdef96056771366fe4f31ae796b41f1","nonce":"2ddca1d3c6846f03f66a453a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"958f24cc4d66302e34e6ae03e34dc1ab69f01d81674d2665e36b28c460de0fbd89297bdf70cffc8cbbc3fd09b4","nonce":"2ddca1d3c6846f03f66a4539","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"c36c9304ef79fd5ca5e033382ea683031751fbb3de0e331052836a5f8b0b1ff374f1af49787dedee87f8c31d2d","nonce":"2ddca1d3c6846f03f66a4538","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"44fee299266fb6f4b29d769a86b3a3bd7bfac1fadc7f6762cd55bb56de3dabb4a2f10b61d91d3fee5e9d1f5ae2","nonce":"2ddca1d3c6846f03f66a453f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"824debccdd4586ddc67b6a2b22da106f38b7e193352f2afe8a59d6f49ff2523c52a5f5e7bc48c09eebd4e188a7","nonce":"2ddca1d3c6846f03f66a453e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"e5ec34bc9d8a1c67edaccdb6520817bff87f7dc953f27f5433676e3c650f313e84b761711bd87a911430196400","nonce":"2ddca1d3c6846f03f66a453d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"cce341d81ef2b0115c999cf1b8e20aa3c40f1482869b7eb8b6b953ef8c0b1389162a47fa778298aa01cf2e20b3","nonce":"2ddca1d3c6846f03f66a453c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"3e73cc5f8b61c9df6d62afd651f480eb9c4d1ffd670e9057f81c029a396169cdc415dddaace4292602ac2dcd9e","nonce":"2ddca1d3c6846f03f66a4543","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"04a33fec4ebb62084166b57e89d91c1b7a3c99a336c10b8f7ccb5b9fc733bf1b206861abfe7f202755df43e08f","nonce":"2ddca1d3c6846f03f66a4542","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"1f82d33cc08ad98bd70b7258288d6edff49851f048c6a6ff8367bb1093e0208b73fa302543f10f6dfe35c90732","nonce":"2ddca1d3c6846f03f66a4541","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"2314b87c6427d792ce0e6f24f1418b5464d882bf7174ec44e16f51ac4244e225291d7b7ce07010979619b6f764","nonce":"2ddca1d3c6846f03f66a4540","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"b7bb153321cd65c477ecee59fa69efc0e39dc1ff56079b3855631468b4e0050c0fb9fa064af957c96529598429","nonce":"2ddca1d3c6846f03f66a4547","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"9a9db5d23106829de4e25f2ce3ab81c55e599ea57e133de7c425040080165f1e731fe87b89c464e86d44187c22","nonce":"2ddca1d3c6846f03f66a4546","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"e1579e0dcd452d46227010f3efae1a18c736816619ace55dbf1faaa9919bd1ed3c9776739d0eae4858558ef5bd","nonce":"2ddca1d3c6846f03f66a4545","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"d1925fd3fc05c89ba75ad193b2811c1ddc8846a3d72d9aa9e40376a3a77b5e1fd44294af6a4e5261d99112c4e1","nonce":"2ddca1d3c6846f03f66a4544","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"0b2caca59b8ff5aa8d62249ce43a2be79df31b9442ea2e8de9ce941fd765db589effd013e220430538216e4369","nonce":"2ddca1d3c6846f03f66a454b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"954c26a2a0935d9f549b15a20c06370bfb3a4d7b9089d4a04b4c42ba804f316c718d1aa9221a351b9d5a567142","nonce":"2ddca1d3c6846f03f66a454a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"62159398522ad92a025207d32e4185c272fbece3a87663a07e43c1da76b307d3e29bad8e8bcf5c941ed26a8acf","nonce":"2ddca1d3c6846f03f66a4549","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"66b0f9e112e4a622c8a03d28a262b898e7489d495cec33897a8047eae01f7c964785fcc3b7946f8fcb8c8ad773","nonce":"2ddca1d3c6846f03f66a4548","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"ff5e3a7ab2da301946ac8fe879c365b2345af1ae2603ee3d38b4c8a96f2035a5ef2e0404c84b0db82c9505c781","nonce":"2ddca1d3c6846f03f66a454f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"b42318efe77c07c68d2c7989c5a33cc0e0c1364ed9cc58e44bf11bd4037c791d438a4b54db44bb032e9a7dd7b7","nonce":"2ddca1d3c6846f03f66a454e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"029bef0359bbe1122ac97ad702e9558eaebebbcf89ecfb6fe5f63579d35c981f457949a07ada25138768283a19","nonce":"2ddca1d3c6846f03f66a454d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"46e8f199588ec4c882b57a3c37e14f7da764f4c246a3bb11fd7a41bdae35ef50cc7ddea235a82532dd51e1a785","nonce":"2ddca1d3c6846f03f66a454c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"449d5caf29696cfe442601d77407951be440e2ca342808c9761dda37e439c381bb1811eddd0dcebe8ffd625ab4","nonce":"2ddca1d3c6846f03f66a4553","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"080410e1c104f30ecb234112f2ac5050f581d938c8c2780cc2d725d99af94aa7e8486830cbc9475bb668f06f84","nonce":"2ddca1d3c6846f03f66a4552","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"3ec8ad1933c5bfe83a135f47d4d3cc24f565bc463a74e1837c1ac28d524f644b913b0525985d4fe546831e74be","nonce":"2ddca1d3c6846f03f66a4551","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"42bd794374195a075930bfd868c557d9b0489784a7e5f0e8dc3d38a1fb5a88852169dd5c34cfecabbaaf0f8161","nonce":"2ddca1d3c6846f03f66a4550","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"d6f671131f8a18ab7e5a4cdf13ed108a66030b4cccfd64112a3fde7330403b431fc321ef1353e7315c90c97579","nonce":"2ddca1d3c6846f03f66a4557","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"6b7fc2b79b453e3049015ae96aa2329e097e439ea53f85888f148dedcd3444b05cdee52b647433b560618500da","nonce":"2ddca1d3c6846f03f66a4556","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"eafe20545983943cbdbf61878b7e7f7b7350f4d9523f3c4322b70aa631f4b7a6df45c16b41220131036ebcd2cf","nonce":"2ddca1d3c6846f03f66a4555","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"aa152c473ebd92a5996f59b0ad27d093840a56a1f8708beeda9cecc2340e3e51908f495a8a8fea0ad197da14aa","nonce":"2ddca1d3c6846f03f66a4554","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"aae118fa97446e38a82aa20325d9522697c7f9559f1db606fb36b785e7d302b59ce76f4bef0268f44bf5223fd7","nonce":"2ddca1d3c6846f03f66a455b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"6ed5f1b994b5b6cd19472d26075d15b91f30ea34003f764973c9dd9d709815549a83eac60c2c2477cd27a5cd27","nonce":"2ddca1d3c6846f03f66a455a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"f8470f2b2f070eb77b70cea4cc51aae49d413a0b54f03c13478a53381f414d5069e73edf844ad856bf7eeb2721","nonce":"2ddca1d3c6846f03f66a4559","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"62558ce1749b187b23fdceee7ba47eaddcec64276ce023afa8bfd6374d98507098c54996542cd36bab83d74ca1","nonce":"2ddca1d3c6846f03f66a4558","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"1b5c9133ba9db1e1ed198e90ecc16da0e5e183c5bc0ed76beb1c10e01cf566f0df474dae4955e31b1853f925b7","nonce":"2ddca1d3c6846f03f66a455f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"65850cc287ac7d8be063a372b1477ea27f84c82af34bddf96d8f9c4e32a1165bcbd9cbdfbe369991546a5d49d6","nonce":"2ddca1d3c6846f03f66a455e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"cb48cea5a44cb419ee8895e58b0ff96dd87bc66820bb8851351f1bd9d261f28ac07e948b311db3a9e4b40d463d","nonce":"2ddca1d3c6846f03f66a455d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"1f1ca39a85439fe75a6f133a99a8f27e809cf46e3f727ea8a2219ef1b895c30192a2ef5171f85c6d4900476478","nonce":"2ddca1d3c6846f03f66a455c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"6b39f310cfb1ba3e32673ef0b799d684f6cfad35e9c624df0be45fc537aeb4c3ccfbcb7e0f3b770b4f8b1d8ceb","nonce":"2ddca1d3c6846f03f66a4563","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"df131b957eca596fd1ff25f6aeb3fb2436562df75d5bf3e01dcd0710e6802d3da7ef6c5edab8b82e7740e6e778","nonce":"2ddca1d3c6846f03f66a4562","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"b010fda35f3b9e4f57b696d7f73e564d3f4c7ea9fd4ebab5157381c0b7eeb7bac73ca39030ee2b949974ff5517","nonce":"2ddca1d3c6846f03f66a4561","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"2c15bdeb180f62b1040e9083381844885bf993b0b4991d141bd3e6cf72fc75f3a0e1e9e7129e0660dc929b2ec5","nonce":"2ddca1d3c6846f03f66a4560","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"cec8bed503b9c4b4690b113317fd5ad91f70c0c797faf840aa5ed05a5338063c00681054a52b0837ca9245d084","nonce":"2ddca1d3c6846f03f66a4567","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"bafa02ad37dd75d91644727b4548dee083a5528d39a94c3c8c2bad0c1bb0bcf7cf5939c2d7e810880d0c7d8197","nonce":"2ddca1d3c6846f03f66a4566","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"0446bdfc92ec34721424850a0350fd1af8461aa1fa821d937b733e3ec79fc4c5d4c40015a0b32462da90040430","nonce":"2ddca1d3c6846f03f66a4565","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"9bb67f4ce81f5c63b610f9770d003ccb4747df0acb6fbf0c385f8611f4320ebc3b39814beb7a77e980cbf36d4d","nonce":"2ddca1d3c6846f03f66a4564","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"e9a7d6da0eee8f4a78e872fc7ef9100f12683eb5617800dec3d709a8bfe553033c0fa19fe3c29b052647293d00","nonce":"2ddca1d3c6846f03f66a456b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"042b4e1cd8d0245292c74bbb8533f73cff76954df73bb135e370d33f3a6e3c4e0802968085cde890d8111379da","nonce":"2ddca1d3c6846f03f66a456a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"9c18b96d9172216665000981e217f80a8b0dfd5727666bc24ede0e7b10c8a5f453a95eeee14674b6ec48640fcc","nonce":"2ddca1d3c6846f03f66a4569","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"34157e5b3b7a9c9124d785cf534ec713258c1530440016a1adb1751ae954696f78978f417c82e462ece0502e61","nonce":"2ddca1d3c6846f03f66a4568","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"41dcc13f97ee22f143b8a9cd0f647c08b2eaecc8ec75a5404af7ef5bc73504253ff45be1f320382754a2faf3c5","nonce":"2ddca1d3c6846f03f66a456f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"1478ce40ef73aaead069010ce6f5c2aa4388c19573b029fc3e863dec6f25426c6cce7bfdd6248b4d387a7130a7","nonce":"2ddca1d3c6846f03f66a456e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"cc1e9225289842e8b07a69a0909b55668f620db3d4d7330a11efcf7983eb9201ef5534c03427e3aba88ef55905","nonce":"2ddca1d3c6846f03f66a456d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"1867c6b08c0930dc12d6785a06e78a2b1e5973d5485f9a375ae5bee8441d710d276e030d687697f0299cc8b21f","nonce":"2ddca1d3c6846f03f66a456c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"8352e02ae3639514f507cedaa14c7784f077eab4737748df3e9efa2a532f20d5206194e42f62f3902f5f6695b3","nonce":"2ddca1d3c6846f03f66a4573","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"d0170090f790e834fee3ffb8e08bba8b5ddbae2620ca78ac70b5b8327f7062fafdc297ef1f683216c16184df2a","nonce":"2ddca1d3c6846f03f66a4572","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"2c97351098ca0f5c06ac4c595ccc5c73c083e8c18700e32bd834b9f13f6ee34e3330bc1d3949a1b0414c4d5b30","nonce":"2ddca1d3c6846f03f66a4571","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"179173fb2c62481f3a8d9c95314f66a4bd7e8ec600b0fe254bb6f60720ffc5012e7f3892faadf16c0925aa122a","nonce":"2ddca1d3c6846f03f66a4570","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"823e5cf7d92661d12b9283374a0cd472939d5463b52605c0ac3b38f645ec8adb1c87b083f81545c30867d67ee2","nonce":"2ddca1d3c6846f03f66a4577","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"db641a588912c5de0f57cb3335c3d35c7012d7a8f9bf17a1e8604c503ec598d55de846c506310cde9f1d571c34","nonce":"2ddca1d3c6846f03f66a4576","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"3593f01dd18810ad3efcd37e1305ae73810bf12779db2c0a0ee4e0d732bed62b5178e932e69f3a18625e287497","nonce":"2ddca1d3c6846f03f66a4575","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"e2aa29cdb157a6d32881f2218a234d33b6aee7e172b6d1599e484c34f367a284a627e5145d3309b5cb6263be47","nonce":"2ddca1d3c6846f03f66a4574","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"38448fd44863089eeefaf2444890500f1ddd4f8c1fb157b88ec9e480b872b020c63772d0c2ecda1d0c3a3166bd","nonce":"2ddca1d3c6846f03f66a457b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"42f4291598cc8803507763e4b1da340540a610e2e2faec01dfb8a465a42377171ec122e31713610ce2e01143a5","nonce":"2ddca1d3c6846f03f66a457a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"00a84b849ab469726b292712b3db9c55c8d2a696f8afb81829dd59900eb210c301ab9e94e97ed32c4f12aa5688","nonce":"2ddca1d3c6846f03f66a4579","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"a56446e14295ce9c8bf41a1d0aa1bc362c7923cc30d8361d10fa711c32d1e07f120f3eb1ca7af2ef5e74f17ffd","nonce":"2ddca1d3c6846f03f66a4578","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"2907db0b54303562b517c15eb6071fbdcb0213621991cec71e3c1457dce6a4b9b9d390e12175a3e2dc66cf4693","nonce":"2ddca1d3c6846f03f66a457f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"4fb41b4377545c4fbfef2e404b8650d9f2e757f10128fbdfffcf4ab9f77a64bbd585ae3482cd708a392cb357bd","nonce":"2ddca1d3c6846f03f66a457e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"72f28394b3bb699d5c134b683e18e1326f1442bd5a3f81d133faa75aa042080d4a5d7d03c7ba9f9259721b0690","nonce":"2ddca1d3c6846f03f66a457d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"519ebe31ad10d183d5ae412328499b717998cb96307e9d23291ada38229a00ea87f204a55abee1c991a48dd64c","nonce":"2ddca1d3c6846f03f66a457c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"18d2ec0ac72bfd33cf270d29e474744b556431dcff35f8db2d86b6b67c08b8d9d806fed7f9317b44a8fedbcd31","nonce":"2ddca1d3c6846f03f66a4583","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"4ccbf713d8178c7503e0c89ae2308d42d6bddb4d285e747572b59d4f7dd1bf457c8fac2dd1feceb6115d3e930e","nonce":"2ddca1d3c6846f03f66a4582","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"74a614f612bfc46110a15ec3b0ae73566d6f77970ec1098f2975e7464b306d6cb703b7f83d87fc8c8617b7cded","nonce":"2ddca1d3c6846f03f66a4581","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"e97e1e96afbdab804b743382cb60bf43c3c316bfd072c6ab51c4d48a62f8cbc3d29f104a583e058b651c03ed2d","nonce":"2ddca1d3c6846f03f66a4580","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"210bb8bdc8b48c7b4f612dbfbae4f5aa77a15a22ee38852116c2c422512d0d65034be951915892a5f04624b4e3","nonce":"2ddca1d3c6846f03f66a4587","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"be7ea5a6d5857845c651a49d3868dc06d3b1058bade3edaf973a4540188be5d456226db298333666ed8178c6df","nonce":"2ddca1d3c6846f03f66a4586","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"e951724b8068eebb12f7138d0c66a5cfd63335c440f4d176f594ad8f4f7a60652f3e2e9858a0ba0d5dc3f3b5b9","nonce":"2ddca1d3c6846f03f66a4585","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"a32a91e3cab27d2afc4d2493e8c38e4f14fd6c5e68f1adc430cc2bcf1aef4581bab2de1178c181cea5eb0f3411","nonce":"2ddca1d3c6846f03f66a4584","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"d323358d67003a6ac47e31d879ae68387a245760492535c0b35e5b2b83215ab8040de8ecd5faa10bf61adba2af","nonce":"2ddca1d3c6846f03f66a458b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"bafacd2775415387479817fe3e22f5c79fa118b8ea51f33e9293381d97d328489900855fa9f7b12fa5615ca3fc","nonce":"2ddca1d3c6846f03f66a458a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"9953f135927420324262f1be7c1041189e6d1d76104e4387ac1a02687f3d158bb705e1059f3cdf31c902336afa","nonce":"2ddca1d3c6846f03f66a4589","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"ed5724064de37dd5c68976c74200f816b220941e2c4cccd3926fa111d41368ebc4636112a4e591b8d2a9d49368","nonce":"2ddca1d3c6846f03f66a4588","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"d14ef999bb72031c29ce4169ad4bed4da82b4c1ad03f3818c38f726d63f16147727483100ac972b140542f1537","nonce":"2ddca1d3c6846f03f66a458f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"c2b1796cc44c4aac96f5e472c9f0bf8edea7b7504dbe9ee44a86d84a59b1e5dbabc6bee27455cb36e7cf91f37f","nonce":"2ddca1d3c6846f03f66a458e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"c8d4c9a8a3dd079aa5c815271dace6b7b90fd7c5ab99f2d7adfb4cabd4c704f68a6727d26c153a3dfee9fe0c03","nonce":"2ddca1d3c6846f03f66a458d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"7501d3f8f230aab774b65d5c0e910dc11db8eeda8d26404f8d9fd2498dc4a001afa7d117c6e2d5457885e04857","nonce":"2ddca1d3c6846f03f66a458c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"47499fcf8f501fbb98e11639b7ca31da7a036f6af54eb7cec31408efc79cfe2452fee90fd71c27c978f3f4dd2f","nonce":"2ddca1d3c6846f03f66a4593","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"dc5297a38077a0030c56a850f26ce6e62931b6324caabb1fe5ce48d605d34591f6d97c39c118053a9c6c5819c9","nonce":"2ddca1d3c6846f03f66a4592","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"d47ac91e66862c49eb53f54e3aed0795774a59552d45f14b1779c71fbdc8c2c52c86fe4f97d93bf93abda0b054","nonce":"2ddca1d3c6846f03f66a4591","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"60cf23b0c18f60bce6b5de677f12bf8b63eda3aa4edd6b084d7cf4bba80482a360dec4b1ba4fa9ef49050c2abb","nonce":"2ddca1d3c6846f03f66a4590","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"0326d372f7dbfdb93f836d60fd65f1e64a5fb90aea2d8b57cf7f51cc49e42f08a4906f30fcc597899d44d2751a","nonce":"2ddca1d3c6846f03f66a4597","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"a0fa0970c529021061f433cc5c516d9854658b2dbd0f61647bff02928e9334e064e99735b96396fd809b575472","nonce":"2ddca1d3c6846f03f66a4596","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"3aff4257e0490478d1fa03ab30ba50871997cdb91a3c5ab34f713ed4b39223d670fe47d98bdb0974339d1f9273","nonce":"2ddca1d3c6846f03f66a4595","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"f342416909056a693e2d8066693aaee17aa8cf646b3d63bb38c5b684713fa075d4872eca473c8ea9b8f46fa32b","nonce":"2ddca1d3c6846f03f66a4594","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"2ffa2ec4b7f6838bf12831fea4f4c3acf2cd415c98896b8bf7adb9757ba62874c0482d9db5e13d994b2e0cbeaf","nonce":"2ddca1d3c6846f03f66a459b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"e0a51bab81d13ee094eb025578d71d913083a552e1a40fd3e0ce7caac128355a303e27a97c5038dcc63d349c50","nonce":"2ddca1d3c6846f03f66a459a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"26ae3e2bd4564a944f6ddfb40e91b3847378a7b407fce92ec05b05cdf7fdc4574ff6abe0bf2706e02316d7fd3a","nonce":"2ddca1d3c6846f03f66a4599","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"5141d55ed76e30afeebc51df9722485098c377a15fe223a6603b9ac28e35d8604740f746b4daba01e5d06c3cd9","nonce":"2ddca1d3c6846f03f66a4598","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"2e556256462ce7ca938327151174ae85fe65ef8ba23351939aeb105120b4cad599f936b808d4d75924b01508d7","nonce":"2ddca1d3c6846f03f66a459f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"3f53406ab7b35e7cbf696c43e8ef672311ecd53708932e64413638fb530828dc6d0003655187bf0ecbd624be3e","nonce":"2ddca1d3c6846f03f66a459e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"f6ee30de0d5f7e54e161fe61df6c9180c9e7b833506531f154a503f4db03d3ab410a6bf807f070cdffe875680f","nonce":"2ddca1d3c6846f03f66a459d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"435c54d01bb16c3024c299a2b940e299a01cedd7eb46fe49edfa96b09b459ebed19612362f4b88fa5e3143344d","nonce":"2ddca1d3c6846f03f66a459c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"4fcc76153bdcdf3605dc83d84d6e0000e6196cc4edf3001b5af7ffcac16231c8b126295ea08798358f14a4dba3","nonce":"2ddca1d3c6846f03f66a45a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"0208e64ee3e7961943133a0004ba6b4459cb822bba7622dcaa126622f689607cc8f633f610e6f65b228715ed1b","nonce":"2ddca1d3c6846f03f66a45a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"308d1eef42923005a9f80580b28a844ca1a759b10f404f47e3d7d7c63ea86491c9028be6391881a0b45b0dcb7e","nonce":"2ddca1d3c6846f03f66a45a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"5aa58d2e8cdaab3f13c9ca509264bcd38eeab2766f7bbacaf6c2fafc9bc1796c4966fa85be44641313a096e2ff","nonce":"2ddca1d3c6846f03f66a45a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"f7e65e0f627f3ffa5eedd02a1dd9e957565d4adf2fe662f2a3e8881ccf37036a945d3747d41aed0d085a5fab22","nonce":"2ddca1d3c6846f03f66a45a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"ba6f1c3b50bd2d6c32704da307b763985688e476485737a3f9a92482639c9668d0d7e6f755df59bba72a145f7e","nonce":"2ddca1d3c6846f03f66a45a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"47b0da2a587239a45a21471402f0254d053f31c49d21286b391d985a42288ee92b63500b997f61ac9ed1405b0e","nonce":"2ddca1d3c6846f03f66a45a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"fdef989ed302525b45bd286f96577b05e2ef75b0ef8d8733bb8ec3a7817b0c92dc5a68f56c61a39bf77c5a3781","nonce":"2ddca1d3c6846f03f66a45a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"bc97072143a6ac8f1d6f99cb9a07448640692a03effbf37ca081620b5501a39fffddc71bf52add2f33c7c511ef","nonce":"2ddca1d3c6846f03f66a45ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"19a965178427e310af4d7778ca79e94940f5cc043d007649f3d0156c6fce8dd31d27b88943720e8a538a3d7953","nonce":"2ddca1d3c6846f03f66a45aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"44404a928b9237c00de2ae5dcedf3cdd88440193346b396caff7d7af7f4c7a20703359d3bc116068ae00852b5a","nonce":"2ddca1d3c6846f03f66a45a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"1004faf9cee094b8feb25be40344e063850f9f3ac365c84c78901eba6376855a261d5cfd65cdb1b70d7ca262a9","nonce":"2ddca1d3c6846f03f66a45a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"20ec95724bdb4c914683db13de858a87038b2a6850194e7c63144318374523c45232b9aacb337a479709f65c53","nonce":"2ddca1d3c6846f03f66a45af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"b6f4ade0c63ba54379830b4557d91cc835d991ebd85853fd8c62e2eb92e571b03779fea6f7a41cbaa3cbf0efa6","nonce":"2ddca1d3c6846f03f66a45ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"7ca29b4a289baed4a29616259eddd8fbf4f7fb232dc16225795a4c5e52af6deb333763ae089fc74e4d45c3458d","nonce":"2ddca1d3c6846f03f66a45ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"2c2f51b530bb927243c19d0f6540c40bb55e7af546effccca071d95f6cc797e574d3af171ec3b9f4e1b0c02fee","nonce":"2ddca1d3c6846f03f66a45ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"e2b786acb203460e8a8b807a81c8c935f751250e50492a5c65ed82b63fa0331f8cc210e37d4235b186a2e54714","nonce":"2ddca1d3c6846f03f66a45b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"5d845cbde7ff70395c9a61278f359581b3765f1d22993281745016332f8e711ee49b1914de9a02580d2b2189d8","nonce":"2ddca1d3c6846f03f66a45b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"e6efd453f32e5acc39393c5d7ea5bcffb1c6ca1d810116755e954e26feb07bb23a6b9b92867e86dd323c29d8ac","nonce":"2ddca1d3c6846f03f66a45b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"8d918272fbaed162efa2f6d44560d53e0911fe60ad48759b5e6fe810e2dfa4315520556c1a9063fb9cf151bfe4","nonce":"2ddca1d3c6846f03f66a45b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"66fdb5d0f60e5dcc369162888be2bb57dc2325aa646f49e1447755210a3e7c19903997af6b0e3a1b7989364f2f","nonce":"2ddca1d3c6846f03f66a45b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"7dad7c3c22118e46038069bf278814b40ff8383804fc0d61b152c5f4dfe4f970eff0a06e73d435d246953cb649","nonce":"2ddca1d3c6846f03f66a45b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"0c63d7c2b4e8e151aede88e653066285589f747293e30742bc4ef758787460c11ffd5862e88ea48762dfec974d","nonce":"2ddca1d3c6846f03f66a45b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"2eb582c0aeb199b1f77e952d30a0d05111282e47c8737d370738c16b532ccea2e1a56a770e06da750c63ab86ef","nonce":"2ddca1d3c6846f03f66a45b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"b9c69b3757e7ec4d64aae8d3ba09df6de40ab5d3a69d2b801104e3c5c9e21732adf1cc6c4916a7c30970adb79f","nonce":"2ddca1d3c6846f03f66a45bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"4f6085317cff1ccffa07fe668c0f22692edc7c6db09c9abe88bd4624c1a417dddbee0e799cea957a129405350a","nonce":"2ddca1d3c6846f03f66a45ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"8b2e5960e1af86d597f5cba94ea014942e32fe6f5ab7e1550afd21864f6eeb2a0a978dfc80ede3c4eee7772e7f","nonce":"2ddca1d3c6846f03f66a45b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"807d171ec0a7fed91a3a1e39bf4669354be7ef13adc6c9c2e633e5e87e3c2ab7adbf104943ca84e60afe3c42cc","nonce":"2ddca1d3c6846f03f66a45b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"3240de27bb9481fcfd464d8bdcbd213df3867ff0cc54a63d66484e74d43f47275a86e90a7337c068a045afe75f","nonce":"2ddca1d3c6846f03f66a45bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"cf71254881bdbf351a51b12a6e7aaa31fc9f8094a09326743c0b8add42e6a6594c08472bb77a6067cf17fad825","nonce":"2ddca1d3c6846f03f66a45be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"eac0986964a71dbcf3366dd88346ffe8ae4fafeff113c2bd87790cd0af0c9ad843d30cc29c2e9807c2b7c0409f","nonce":"2ddca1d3c6846f03f66a45bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"a6f6ccefb0b487e072735425802cbf5029caafeff60f125ab31c92b89ecf48f05ec0e9aca5eed5d8fbbd737e51","nonce":"2ddca1d3c6846f03f66a45bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"909f487d303e22b1d0ecf0afd4f6da4ad485903404e7b476fafe59a6a8b78a304029ac874875492a2e87a7de66","nonce":"2ddca1d3c6846f03f66a45c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"a077b4a7f6aa03fdfceac66ae9216804a5621aa2bcdd0f7544cf3855018c5facaadfea1475c59fd3a39e10c727","nonce":"2ddca1d3c6846f03f66a45c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"8d76c57520c62ae9e9500f246883815f4f34d73140e083d8e1ca368051949ca574b3ac40a9cc1cad725efc7c9b","nonce":"2ddca1d3c6846f03f66a45c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"59aa6eb2174807bf6e1e15f45e58d983c06751af6bd79bb285c4a4aa16f218cf845544ef76016dcb7c97fe9648","nonce":"2ddca1d3c6846f03f66a45c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"10a42508f466ee2b5f1836ed5d4c0c9fc2be6ede09b0081e1e703eb0c259950f073141d5df51e39280f04015fd","nonce":"2ddca1d3c6846f03f66a45c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"5c793bbf60b16e862efea20c15372a9b8a9afbeac1379c42cec0fc594d28ce7b2f5f367a5042daaaf246f8fe98","nonce":"2ddca1d3c6846f03f66a45c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"6fe76ac40adc052c7d6354848e8279c563b423e874af46b55d3f448950fa1a6622f7f9174306ac76fb653a128b","nonce":"2ddca1d3c6846f03f66a45c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"9d6b6fc9ae34987e83f02a61856a396b8c5d0539aa0a9c2ece3aff1d4d92c200fca114d7fce1a15c793dfbbad1","nonce":"2ddca1d3c6846f03f66a45c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"b556c5eb8de4140bf098c13c92b11df660843a01f0d7c55ac93d083f19191ff4c674b2d583cd3b6a12716a7406","nonce":"2ddca1d3c6846f03f66a45cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"0bf9cc5fffdb90cc07f7a7bd56978a9aefae1fe82718f55a560935aae358017033a951e67df35d8aef63565593","nonce":"2ddca1d3c6846f03f66a45ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"99c6231eb0eb2f74150fb97adfdf85d429f9f1e1415fc63008ea6b747145133d3fa12095ab54824841bbb4515a","nonce":"2ddca1d3c6846f03f66a45c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"e41f90c383343f08c4a905c71cdfd5c80bb844f90c27b9cf60c8cc91c6e94e57e64252620f5ebb6886b2678b6a","nonce":"2ddca1d3c6846f03f66a45c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"f11116ffcaa6b04b14218a394e6d80f784e45bbe2aa17aa9ddb9fa8a1909f2b2f0632528ee95aa77561981ee2b","nonce":"2ddca1d3c6846f03f66a45cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"4c956875f00e931bf25afccfdd61e304b7159d08a74cf74d3db2640b4256ac9713f70e4f3aa0482c95d19b6908","nonce":"2ddca1d3c6846f03f66a45ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"f51c3bbe56bc80c2aff785d4b328916232f2dc78f327402eabd8bc80737c7ae9d37873a37ad5d84331cc6c1452","nonce":"2ddca1d3c6846f03f66a45cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"f0d43480c9695c7cf83746deb7228494cd92531b143734e2114997726363da15c0241abcd642f7a12b0301c5be","nonce":"2ddca1d3c6846f03f66a45cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"7d9f3fd21bf29b8791f044daf1178a5cbdb31fb94d498533412da0b4709637e1fe8bba629a0af82177b27351cd","nonce":"2ddca1d3c6846f03f66a45d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"14172ecee1afec4f3f0f81075fe07f87231844e792a24d45bf040c8f3d448981cd60f1fc345295a47ab027b217","nonce":"2ddca1d3c6846f03f66a45d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"ae169e717bea9be34c037271217926bc657883a14cfb201cb395199f14cd06d3d57c1f115b10e38badfa598f08","nonce":"2ddca1d3c6846f03f66a45d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"71ced568eefc52ce3ee1dafeacebaa9d312508fd04b4f2bc48f5580017336acb80814e1329be8192d9bedf058a","nonce":"2ddca1d3c6846f03f66a45d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"7004e95720d2115e59884ee9aa126044c2297e7659f7ad36fa50d1f5b9d2109d29e924c11a32881c1cbe9ca30a","nonce":"2ddca1d3c6846f03f66a45d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"c7a67a71fac25312a88264bc95993a89f3eec3451c46fbc3c16b37ffbde84e00f254ef62035c8f837e5a6e5b7d","nonce":"2ddca1d3c6846f03f66a45d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"d365e9f21a968b024e64384ec985edb3dee13486f82c6f9fa117914fa8562cce71616a4062d01612b8d17539d6","nonce":"2ddca1d3c6846f03f66a45d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"237d7fc872707fe434cdfdf9e2ba9a1ba289f494d841d57ae9b8d9ed10fc733b93a2eb046a95949049e1a81cc9","nonce":"2ddca1d3c6846f03f66a45d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"e611dfa17008ca43cacdbba4fa4647ddee4e55d639cfaa468982984939c13ddccc0971f89de136f0cc2b8bbf0e","nonce":"2ddca1d3c6846f03f66a45db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"d3c21c3776548c3764825828863d6b8ba70c371b65027f751bbf551e32ac552595f6fb56927801a3bbd6b71dcd","nonce":"2ddca1d3c6846f03f66a45da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"7d8fadcda181ad414bc6377d8c8f37d6f316cf2800e294a922d1db7f8d84d3b9a21a0ecdec5db851d8d94e3e55","nonce":"2ddca1d3c6846f03f66a45d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"a81a95a025ebf157350744de99ce4d6fef7bdaa3bc0d56a7e1cfd2f4ef7d89ac58038d3a5c2e92aceea236b883","nonce":"2ddca1d3c6846f03f66a45d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"1a4f66ad1a5f76b531c3d6956ab3be04fe259e71e4ace96cd73fcc6827be60603bd00da91c25c44dd9b23d496e","nonce":"2ddca1d3c6846f03f66a45df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"a9f022dd6d5f5986aefda2669425ffd9af392ba2c51d821d18112a82627e6772d39443ec0961ad02739de7f5fb","nonce":"2ddca1d3c6846f03f66a45de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"f2dcf81542533811d8248d566ab74dcb90201a8d44a4fb1aaad0be6a7419287638054163fc543c4efdb846e668","nonce":"2ddca1d3c6846f03f66a45dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"5027736ac08fe7a6021a8b3f019676bac6e6389bcdb275131fa2f7058e5df9ba94adf0c3a5c2155e05272fdb93","nonce":"2ddca1d3c6846f03f66a45dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"abe89244258433e066809ccf2b96a7e88efadee89aeb73a4b48778b55c12a85ed8419e0ef454b913785f1c1873","nonce":"2ddca1d3c6846f03f66a45e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"868fab4ec1d833c4ff907c07fb9fcb28ee7957c0a7201a6a5a8255eba7c4aee5c1c63dbd7efd16748711c50abd","nonce":"2ddca1d3c6846f03f66a45e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"cbbc600e47ba566180d996e8a80d6615e7f5636dbcaf508b9fba55bb376fdf3a9450644ca998ff03321c1e1b58","nonce":"2ddca1d3c6846f03f66a45e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"ae38c6f649be543e900c55ba78392e7e7a5518c36040c03ae6ffbc8413b0eb74d2dc25e72cc710ee2562feea8c","nonce":"2ddca1d3c6846f03f66a45e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"362f2e21f0ecdbb8ca55dc34961e454483c026a999f7bdfb3e154bf1f27d9142490f1265a7f715f5924baf2472","nonce":"2ddca1d3c6846f03f66a45e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"f48e3d14cb72d6ea600074d2bcc5a94b968eda2ae70a3dd4b012dcabfdc705cc56eedc7e8642a2d84edae08a59","nonce":"2ddca1d3c6846f03f66a45e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"4acbacece7d403473dc50d85afd71b3a5f50170ab4a004b16104cb857332d2d43a65879b872fc368e03393d7c9","nonce":"2ddca1d3c6846f03f66a45e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"3d0f15d870dc5c6a3bc54518ba85881f4c97cde5c2317c76a18986a5fbdb3402478b688061d662ae7a36ae4529","nonce":"2ddca1d3c6846f03f66a45e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"1694b8ab13d6308c17de871f600e4c3158a4f34516e0f299761ea93e008b91c6d178b1a5a3a4ad54164819a326","nonce":"2ddca1d3c6846f03f66a45eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"6a5750a12238c535229511d7c04ad94407fbd5462fcbfba15ef101a447ce5d82ee48e52c87dcba17168857cacd","nonce":"2ddca1d3c6846f03f66a45ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"e1906ee4376774e0340c45ed8e9c1cc33a993be2e373d65fa80b1cc55215f7f8a96e2a721efe52860fb8158117","nonce":"2ddca1d3c6846f03f66a45e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"c8c31b8b859f32b87fbd5829ca6285843b0c040b79fbba82e02f290b7084063c2274881c9e9dcf4e4acc30e59c","nonce":"2ddca1d3c6846f03f66a45e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"5235351da18b011991bb5d25ae04244143d5e98e9b3ce2b11dec1aa142ec686d2fd7777fd02aea5ee38041cfa0","nonce":"2ddca1d3c6846f03f66a45ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"3025dd7ea6a8209b96ef18da7c0f3816b454d3c4a6d92503b82b986033a69efc47260e320abfeba40d3005b1ea","nonce":"2ddca1d3c6846f03f66a45ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"a167d6b058fe5d83b4dca0f45c12ffe8afbdb330ab60905421fe03973d87b6cf39c89b384916632de7990112a0","nonce":"2ddca1d3c6846f03f66a45ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"b601b4f31ba36fff043fea36f06d5aa7c75996a608ac114dcc06838f825662e16b2615158407601cc3c201c8a2","nonce":"2ddca1d3c6846f03f66a45ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"6cfc1fbcd180e5e72e728da502cb743f97390b7ddec6e3665c505edd4e78bb488bda84ffb1d9f14aeda2bdac4b","nonce":"2ddca1d3c6846f03f66a45f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"480a02e2ff56e604f59925e80b2147a2120f9993fe1d930a41bc97589e70a8e9657ff4a84dccf9980b5d70f1af","nonce":"2ddca1d3c6846f03f66a45f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"0ad0f7489807a17ecdb8048bec1319d1838f72972edf9c882d941adb0768b1e4a71dc5a079e88fe3cfce13e82f","nonce":"2ddca1d3c6846f03f66a45f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"3e8f18bcfeefe5538173162a35eecac71ceb98ed0f434618903e690c84d63618d1b4c9e3d4b4fa3fb5ca3ea7e8","nonce":"2ddca1d3c6846f03f66a45f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"1ea9911141b4395a93c5a57f668cbb5dd99c72754b80c4d5d6f1b6f37ea11a30adaf9a012cb67a216217011315","nonce":"2ddca1d3c6846f03f66a45f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"352118c2b6907b5699b99c1ca856d9b43caa8a88d6ef59a8c8e479502849938efc352575b12789c6ad3bfb9591","nonce":"2ddca1d3c6846f03f66a45f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"244a0533162247e9db59089ad82c7569e172ddd6da02464ab85985ae46fd31219e2153cda8c170b5ff7d170585","nonce":"2ddca1d3c6846f03f66a45f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"586d9b94f8d6a45b00209591f50066545ccc9cdd62c479eebc2c85f692e8394a2c8d2e4eeb35ad6f94bf7f7214","nonce":"2ddca1d3c6846f03f66a45f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"6673d43c16f8ede800db6bff2dd69ec07b642f884cd82cc5333997401eae186032c67fb331615763ce5e68e542","nonce":"2ddca1d3c6846f03f66a45fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"bae8388f544735c929f6da86b0638d602787526c3547291bf37a8d9a2edc1c0672498297595f80fd7689ab4737","nonce":"2ddca1d3c6846f03f66a45fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"91442d4051cb762e629401b1d1254d6554f336e4f8eddd438ffd6795e5bb7a9c083e5babe4e235c39348439dc1","nonce":"2ddca1d3c6846f03f66a45f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"ad8cc9226fb969dc2ec9a38db2fbf617debf3e24b147459761e570d8c093b3a80a9cce299451d19fb27740eb16","nonce":"2ddca1d3c6846f03f66a45f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"8bfdf2718a79d224e55b9289a7eb54ddf7c36eb4890a00b3b1ebba6e73fe78b6aae29ad7519153612220c5ed28","nonce":"2ddca1d3c6846f03f66a45ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"6b8fff05a09a4d95c530f9f29f286d5eefe8ced41d17d0dba121129e516b8535a2a95dd6d2910dd30a95f884b9","nonce":"2ddca1d3c6846f03f66a45fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"94d8cc406c9d4d39398a74983a3159ac538b3ff1c03db35673bfb82442343192f6f07523e53d97705e89af26c6","nonce":"2ddca1d3c6846f03f66a45fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"751f9205fa6276649bfb1770588e2c7a57f643b9c7f23a269ad16559fca56c67918e89fb52cf977ca9ef059b81","nonce":"2ddca1d3c6846f03f66a45fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"c2e45fc76ceea3377276b5d30f8c1c42c5efe032e254c42602f6184137a760e397e0b5306f1eca9480dc686228","nonce":"2ddca1d3c6846f03f66a4403","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"9aab4cb4ab07161c830e88aa0351d6b25732321b1be3d859ee4ec00f5f7c2556"},{"exporter_context":"00","L":32,"exported_value":"7714b48d3beebf16e4682bf98092750cdc70c0d7d2cbf55e5829a567f1f5247c"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"afaf8461b1460680ecfedcf51155775c63798066ff50e61fa28e7e3b304202c5"}]},{"mode":3,"kem_id":18,"kdf_id":1,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"7c83700a0fcd4f4efd59ca899168c4ef63c1246845329fbc8838e3aad1f0b04cd1ba714a006ce1ca1b76163a6c1825f78ac8e92ad3404c02ecfe027aec3ba1b58d27","ikmS":"0bae6b01ca3867bfc11726c80102211b611b83b2de0147dd469fc470f23d27d57fda0c2fc1cd1b70d138151e3220fbd8c35ddaaa7ace669cb68a610ea679fbfba752","ikmE":"d51a259d700a4528d8644fc61ae4ed30a8008c785dc9388a6e3faf2b279c96de37a151584bfa56a9d17be6165c5343b41eb64102c051395c21ffb7ea6e936095c36f","skRm":"00cf3f8808113c596be659a60d708c5873af84669e6604029a92d0954cbbec6933a6854d4aa26a130e7d9a273a2c336b53bea8d1f0655e84e6610160a808d2de18f1","skSm":"002654cac99953f43f2529ff166d6f2833fac01ec912a1fb3d01bf31e13dae94ee4161909e0d9235da4cf09216edcf62e7a0f8d73ebf294019cc6652bdc87a4bc0f8","skEm":"00a436f504e74a62197e6cc6c68bc0b22b9ad0df64cb87b6fa2b40d0814e91bf45aa0dc7ec0d0b54197329ecae724159100b90b53aca8fb99f85cebf82c86c36ead3","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"04019bf860261d0e1feb68cc724e1f8d5901bdd7a01ebdbf9eeae8d0411ad7cc21be12a47347f23237d06ca3e84f405699ba90f97756f790ee6259c4c0d5daabae7c1301e17f3df53f5d0fc2c1e4d2fb2626bfe34705b31848ae60ed351ea33f019186d860b4c90311e3ab933158316b823a4f828652f79c71715f6491a0f8b455557acc6f","pkSm":"0401c9183c1ae8f140aa4f1a48c6565233ca10d46aa8aa50b7e914cabda4508e169352f4e7622335cca0ea6c64ebffa42c9bd290bf153c7b9db6d5321b2dd2f79ef9da017100f9b252a964c11833483d93a10fab2bdf7caa02aceace405d9adb27cefd4a12a8eddaf8e204990fdd703d443f598dd8c556a171e2143bcaafef458279353842","pkEm":"04019f3040fc9dddf33bf0dcd5ff9b24a57736f332eab2a7ba3a2531c4c32f52975d7711210be48ef711e715b97ab26f27d64dd34f2d167f31c181189b711128d3861001ec4970c1643daedd88ad78e0ab29326d2ba09b988c2d4d7535571206fd6b2c0f853681ba752a91a37789b6c42e3c42cf22f8af94a5d6b59ad6b124128300a884cf","enc":"04019f3040fc9dddf33bf0dcd5ff9b24a57736f332eab2a7ba3a2531c4c32f52975d7711210be48ef711e715b97ab26f27d64dd34f2d167f31c181189b711128d3861001ec4970c1643daedd88ad78e0ab29326d2ba09b988c2d4d7535571206fd6b2c0f853681ba752a91a37789b6c42e3c42cf22f8af94a5d6b59ad6b124128300a884cf","shared_secret":"bc05d79d27f7227646460a4ec21eea05b01684dc9e96d636096003e2849714504782243b77ed42425e00f431221e059dabb2b63ba0dee75280b43b1fe12859d5","key_schedule_context":"0385f941ad2fe19e65926871f90dfb5e99425bd648b6a9d0cdff515181110e0dd02c567eba65d69b8f94f5dd45f30ba15730e09a0ca1bab72cdd2606fd3e4a6c69","secret":"a392cf05c0dd2a5aa6ff56380e33bd6b28c2aed3be2629e062cba7047155be64","key":"caad86ad4f18c1cee3e6280f5197df09","base_nonce":"040eebc252fea626a3db54c4","exporter_secret":"79c0a6564cfcc713c7a8bd183e477a4be2794d136bc661d0f00c58d00c5c00e8","encryptions":[{"aad":"436f756e742d30","ciphertext":"18d6d232e2562a767d8ecab1ddb5ad1cf4182a814ce0608c7d6cfd8e9f5836602093f30a6a448c8ec05bdfe58d","nonce":"040eebc252fea626a3db54c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"9d069168d97fa1c5765042ab97c4baf0d8ec2c88979807015e102df9ee6fed570f920ad8411217c537317a656a","nonce":"040eebc252fea626a3db54c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"4fcd01c9a14a42bba5a29aa250455b6a065e4df658cebda61c453a75a3711e963aa4de885eb979669363c19b4e","nonce":"040eebc252fea626a3db54c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"bb07bb8a935605191b5d008d3c5b8edab810b481191f4d81d06d0a88751c46a29e265f3913c244547d563a4b29","nonce":"040eebc252fea626a3db54c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"d3844bd42e4795ecaea05923b513c9c853e45f2f8eb1622ca36ed03ddbaf1e15392197b9577804ceda0a7c32b1","nonce":"040eebc252fea626a3db54c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"f54eeb3a0f2344780cade36466e8bbdac0d9d77d0a9fd502c3f83fe9f0de0972443275bfbf05e0a06fb37c70c6","nonce":"040eebc252fea626a3db54c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"cf7940a63aa6c858a2888559c6cdafdb4587bb6b2afcd0406a3b80d9c3f4be4cf3a40c34a6836bf82d3e27c3c1","nonce":"040eebc252fea626a3db54c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"56605464c04a0f7e295889cd895e30544217339df0921c7225b50c45d75e8e7dd2448d06ca0a75ab479ac6a502","nonce":"040eebc252fea626a3db54c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"dce3ecbb89a5d9ff2d790d168d0d4b0c6a12be23d07c8839ba77184f3491aebea241e4df20be44c9808d553061","nonce":"040eebc252fea626a3db54cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"83c2a61a715d028179873c5b2f8475c719a0d810e13206e9526c5491835310c234cbecafa136bd24364cd768dd","nonce":"040eebc252fea626a3db54cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"8122822f2eea09737fc0ee9595a35016922e8fe0a7ce71a66fa22d22f8658ccdc40883283f5b5f66203655eaf6","nonce":"040eebc252fea626a3db54ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"bcc425b5379f983c122b5ae22b1d17f2f1d0a0fd2009b4082c55d2af958a74707867eb38cdda83c110e9bdba3e","nonce":"040eebc252fea626a3db54cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"316b2552b4532d6582541072b35541b21dee9c8220dd71194eb492c2e04a2a0cf8a76c6669eae8220530110fd0","nonce":"040eebc252fea626a3db54c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"8adeed65c994d7ad41fa412f07cd13a258be9aca7b48ba5ee943e80985ff993d67403f031b657eb33a71194154","nonce":"040eebc252fea626a3db54c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"5c86d5f9d257b40e254282444daef621d150bc3e7042162f9f23ee05513f721cf2e4106d3dabbd900c11fb61dd","nonce":"040eebc252fea626a3db54ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"af06fb321fddc023c6b60ef1abbdae263d9676f3cef1df19154158f8ba1c0d80f6378e34e2a04c008034478b18","nonce":"040eebc252fea626a3db54cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"9c9d322e0bd817a040d7c43697844bdfb0b09edb2dacf8f0c0f79fd8cf9d76bf26f92ff8e1c057745d78e8b557","nonce":"040eebc252fea626a3db54d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"acf2e2c0896c7d4bb2a4bd3376432fbcf6d6207419f9bc0062cd91c4ee572f218341a7952cc12a06b6c452a561","nonce":"040eebc252fea626a3db54d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"4706c4effab60927e1a5c97df9e1fa22e5cbf802c423c0b780574539c383b746ec15b27481d297f6dbd42a0fd5","nonce":"040eebc252fea626a3db54d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"3236576f8bb3aefcfb2b7e30d451fb308cf3c4dbc3ff36c36271d54bcbe62a19d73d17b4aeb64482cb35200681","nonce":"040eebc252fea626a3db54d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"ade0756ea07bd7a40ca5273a5b3c0e9dbc51dfb42f68783147a402c36a54aea8928d7f39a0f870ad7255e93fee","nonce":"040eebc252fea626a3db54d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"c5d3d05eebecfc1f65d8f87fb2f575b0a5258f807df98e6a9f0417cd9c9b45f16f40db400616c1b280d7d45fce","nonce":"040eebc252fea626a3db54d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"e1e6a7b480a93a76a0ecc5116164b147bbad7c7795f5fc657b866113d6a3d9a0f8493a7301cf02c4f5d71a7030","nonce":"040eebc252fea626a3db54d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"220c6a4cd4b4638a6747c74c58dd0d22aed500a23731fb5e62e161f7205f79f1f82cfbd04883194751e1e130c0","nonce":"040eebc252fea626a3db54d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"23681437479282c48823a75afdc635def3933f8fb1366563097f6b13e08dc76fe8862f0dfec48ac51904df9bd5","nonce":"040eebc252fea626a3db54dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"9e4edde8800fdb61471df377610ef49633f031170914a1b064451fb25b817fa48457596a72895737680e038762","nonce":"040eebc252fea626a3db54dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"fe20d5286cd5647086494e639b9af35bba0491f44e5cbc18e12fd032f5556693435c59f8c7ec78b222382f0225","nonce":"040eebc252fea626a3db54de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"91fe9f2ba593e82ae736fe6f64fb78841fd1d09bde260dc0140dae39970feaf824ec11767e14cc7405b4b8d339","nonce":"040eebc252fea626a3db54df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"31443c4e5d970f3a58d0cd92c9f4e652e16cb13b438598c008798d5ad5052fc9a622ab9250c46c961eb0b44e49","nonce":"040eebc252fea626a3db54d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"71660b59b9442eec465f841ea07611f2062f3df40791e8a81220652df09c986c17a5c56264204c8de4c4d92f2c","nonce":"040eebc252fea626a3db54d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"a39ca8c7fe2ceda0bcf88dc92db009473746cbaefd4b5d280c97ae36591ba4c5b2113cead54d662f9614f480c2","nonce":"040eebc252fea626a3db54da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"26661be80fb9b8f26f7904301cb7ab26b91b34cc88ee16bfff202df8c7dae89081a96dc91b6a55e99280a86ab0","nonce":"040eebc252fea626a3db54db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"0add7cb4978d013a7f2b299a76b80779485edb827058673e12d3e6160d1570961258d4ff821b7fbff1fa4701be","nonce":"040eebc252fea626a3db54e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"4523240799d7d8f5097551ead37604ec05c8229fc02835f0e58395d5c0dfee30fdd9c41b908c61ee3034c61ddc","nonce":"040eebc252fea626a3db54e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"2eeca90b2cd27ef5c868bf82755f8fb5848c927ac3dfec207248282d73450c540ee491a9dff15b0ec2878b66f5","nonce":"040eebc252fea626a3db54e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"b519fdb08a1c89c3649a97b676b01fd468d0925473b28773abef1c0b2c1d7982e2d232f1ca933f156fbd30f252","nonce":"040eebc252fea626a3db54e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"110a0c45c6d8b73a9af316decd9f89720713224a77a63155cb48ab7188251c1057720d99653651ce9efcb394d6","nonce":"040eebc252fea626a3db54e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"5e299d0184106743a49ef4c43192c124f7c2763ba4927de0c238663b076a23d53cdacd5b5a569360fec5e3621a","nonce":"040eebc252fea626a3db54e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"5d0f922d2199e4afdffff6f62707533f70ffb87363a4ee9d2f80b155e3c242c93bef3454acd6d5d8856c2f1bc1","nonce":"040eebc252fea626a3db54e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"56a7284bc9d9cd9f70e6e73c6a0f0babf90eacd7a8fe4fdb47b9236b607907641bb31eeb3c52df167e09e1af0a","nonce":"040eebc252fea626a3db54e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"62b9612ea1dd7f1000ed2da70b0fce8917253dd5a54a67f13fc73527b1326725b0b82d7b0acb3c8cd4f91cb206","nonce":"040eebc252fea626a3db54ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"8466b3993862dfaf672dcf3fc7f86ddf990ccef2eb3e83388b9af6f443abb77efbbd6407fca291d79d26f3c160","nonce":"040eebc252fea626a3db54ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"24acccc49132a494ee353dc71392c257e8648c69e279a810ff7d4737067f47048958e408fae1771ad83463be5e","nonce":"040eebc252fea626a3db54ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"d626c628669675255008c64fd48b4040a333802d7b0d47a5f034d6160ef4d5e41dd0af4c1a64736202a9cc0667","nonce":"040eebc252fea626a3db54ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"3273c31e28f72d59405ebf5f7a22034d74384ff4caca6bd0559c659df24fbc3b0397075f0b2c48c94878a3b55f","nonce":"040eebc252fea626a3db54e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"c4911f8681a43866ae7f30d6a381eec4d513756989126ab4f3a6fd1b9cfacb7f3644650646f61064514cd2f805","nonce":"040eebc252fea626a3db54e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"44a5058001e992859f01428462990595efceccd4a5eed380b5515f86215008c32c7b36e6f5b454d91e08fe4ccc","nonce":"040eebc252fea626a3db54ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"8c6ac1a8a6e08397e9625a7cc32f0fdeb24c3d950cad70c281d60a03183c81a633110e52a3db4466732845ad5a","nonce":"040eebc252fea626a3db54eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"6404a37fb5e063579c83d5fc56034053126475bf3fa20d6fc42c2823cacc0d99fe9a63cb151dc97a8a5a53f6b3","nonce":"040eebc252fea626a3db54f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"3c59181070b0d1f605bec5f8f7e0e67802591ee616b3bc36a4b5f6082ecd02f5d0a0e92175f25091cae9235291","nonce":"040eebc252fea626a3db54f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"cfcaee0aa06811af46d8816ce2b37bd3a97858d61620b6303a8dfd55a920019c469bf7224118e0610291138441","nonce":"040eebc252fea626a3db54f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"7e9cc72d1488c569bcb104061994f12104c007dc8ebb34fd883e62416eed4e95f954b7829f3b5d2608c4ee95df","nonce":"040eebc252fea626a3db54f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"54f2ae267d73160db6a594eef51365b2f0ea13531ac0ce35537b740a4ff7aa866461e6271454185ca4d2059469","nonce":"040eebc252fea626a3db54f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"a84b438fc23c6f2cad914116f3d7bb6328b39dd7bab6d1ddb28fa2c87d2c4a72542a9391a8f651b87e6c93e67f","nonce":"040eebc252fea626a3db54f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"98f9d4708dfd30249cd327734980878117659a3a48869b45d0e2f164f28a98e2bc6055201b0f5f35a16a2d3434","nonce":"040eebc252fea626a3db54f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"e29eab495439ea648a0b3448af29963b34855668fe7d1bee1a5cfa65adbe21e0f1357233bc290318992fa943b0","nonce":"040eebc252fea626a3db54f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"42f7208fce5b64948ec0702c58709e8a22112379b309c0a71b7a352ed44a0f9c3f0ee2d2ad27a81526c430714e","nonce":"040eebc252fea626a3db54fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"3d109cb8cd1d2ed774d791241d04def130cccfee37b6104e971cc4550a5874461ec13cf8073d6bc66c1768723d","nonce":"040eebc252fea626a3db54fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"8dce10b0c74bc6f1deadb6c9646b3883f4467fc3a239aac988e9ff54b97b888e0247fdf175486e57f3f6939d34","nonce":"040eebc252fea626a3db54fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"bcce2eb3e69fcba68e71b5cfa530c2d12327edf68aa9022e5b162628fdc8b54086935c4a6495d0712d3c1c0dea","nonce":"040eebc252fea626a3db54ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"b847cde549ef478f9051b8897d3de7a4f02ee7841b0d42fd5cc51e4080c3f82f5a2ee78a8cad57406b3d04bc31","nonce":"040eebc252fea626a3db54f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"d26470c431a35f97e1e127b33fa3c13f73a576661728256eddefc8167ac0006374d060cb30c9169e0f419f9cfe","nonce":"040eebc252fea626a3db54f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"5ccdd76bb23e2d6f302d4661761e4056f2627382b819f86d55f6dc2ac750a4a872ef5a889f3b9e0c6ae7837d0a","nonce":"040eebc252fea626a3db54fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"1bd3ac232033d2fdf768828dbb970cca757e818769d4d9b2b8d9ee7674becfaa752eeeb90cbc40e5abda1258a7","nonce":"040eebc252fea626a3db54fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"17ae7878a39625a3296c560066e963d8bdb6c234f77712bd27050d139b7a25550ca935d457438ccdef5ce77590","nonce":"040eebc252fea626a3db5484","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"d7037f261cd4c5bf829622e62bfa606a8643c1e2688530f0fc5f91818fb07c3bed38362f93d6f15b7649b03414","nonce":"040eebc252fea626a3db5485","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"678b3718d32dc0327799091f16aa8fd2afc2745aed055d59e24c1209d2206eaf8ccdbb6f3b832e3a2ceebc83c2","nonce":"040eebc252fea626a3db5486","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"4968bee8620fc10a95034eee22c8eb26f34bf963129f57b717430e112384df8509a745d17db039c73fb9c45bb2","nonce":"040eebc252fea626a3db5487","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"5a25233061313d8bb6d4b96fcfed578346340b03bc64e9c05ba1e0ee898da40683dc8e65750c34dfb01df8a7bc","nonce":"040eebc252fea626a3db5480","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"8aa78b66af687018c05e1f1147f0eef630ea8c9f21954db8e06ba3d0d5e328fbdbbceece383221db97ddddf3e2","nonce":"040eebc252fea626a3db5481","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"77428afeef9775f5678e42ea053d2b2210c9bf23a59fec9632df65b6fa693aefbf4035cd80baaa102bef44b9ce","nonce":"040eebc252fea626a3db5482","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"c13a531213e162964be3fa5da19691d9912e1db28c56f6ac3ea0afb777fde44ea803eda80d5989656c8a76ec20","nonce":"040eebc252fea626a3db5483","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"4f237978396f505df1bd2e81d86071fe62efcce600bfa6a008301682b6226644d8d9d6d93028f1251baaccfe15","nonce":"040eebc252fea626a3db548c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"5a2aa8949ee7d12ec561ed219335d3dc7e7608d6c20c708f455335b851c28b2118f6d00be8767f213073faba3d","nonce":"040eebc252fea626a3db548d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"6a3c6ba45c87b4a7d1333e19ba7de2aaf017a926441e78ffc6ab78f91ed9779a532f8ec4a1989b306fd0436756","nonce":"040eebc252fea626a3db548e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"fe436abff026e0c390145e94d5edec07cec8a44742b8c968ea106bb8d59e5c1de3d2465d8db27c7cb5f208bd52","nonce":"040eebc252fea626a3db548f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"f0e1b9b1ee55d53622849b19442ba8b4c25717251e8b3df90897b2d29be5eec93e3f9e78b931e2d975c04ad08f","nonce":"040eebc252fea626a3db5488","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"a9df44ac6f7c36f1137c0d4e78faf99bacf69d617d523836d2ecc3cc9b4912da3d0c236c2d8ff8d97ca9ba9af6","nonce":"040eebc252fea626a3db5489","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"3c491d7fdfcb80afc91022d8e27bc36c842941a2d8f94e6372308e59e7bafbb519fb0501b1e1d6f568e3a4e45d","nonce":"040eebc252fea626a3db548a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"f300a1ca5afd0b1e4e77436c036528e07d8888fce3ad04697e399e1f845a6d05c5101f19cffa0e2c25e4f0ed76","nonce":"040eebc252fea626a3db548b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"23978771a733f25dd9f243ed7cd5e88819ad59bd8d6be82173d8102bf804f90841078141318110ff914503a979","nonce":"040eebc252fea626a3db5494","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"701f526284754b0b7e49b3b376116f9839c7bcc8b4557c9b8d82a6d122e6a7b05d6eeb3dfb55f12234b7230fda","nonce":"040eebc252fea626a3db5495","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"d491f99f7bf69ede52493cd3300be674ec3ea9ccb5387ce69e9c0814a73a80cc4b5974d3d4f2bc1a98d20bbbe3","nonce":"040eebc252fea626a3db5496","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"f29fc74d991ffc30e0219833270f4c917c215a82627877468a9ad60399be3a53ab361458a8d130aa4d3347f8db","nonce":"040eebc252fea626a3db5497","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"25116eb89ac3e98d9a2709311ff80a991474f78a2f95ecd5d4be82f21ddcd3835f2cc860569a05015c0229cf18","nonce":"040eebc252fea626a3db5490","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"5b0b65512522cc28bd60f555b2478ab413de627570599472e15e409d390acf527010f51a4a52138ce9b356f8e4","nonce":"040eebc252fea626a3db5491","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"f23f3f24ad37c5901101dd2d9983e185440eb3bf2e25d4d5cdc50a6c889d8ee33ab1ef12cb1fc0e4822b826f37","nonce":"040eebc252fea626a3db5492","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"34497c0cc539946ff74adcedb0034a1f3afb0f2dfa22eac7564aa63c6218f7171de24338e6cdfe7029983aea5b","nonce":"040eebc252fea626a3db5493","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"9d404f7f925419a417003c30d5b86e3f8f8538f64b49271a7d17b36b91b1d40182d45eb9ff542c262798d9b413","nonce":"040eebc252fea626a3db549c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"eeecfb9a7a13376e25b2504c3e41b68287f33d4a3e84b582118401bde90de50578926f7f56f8de6eec425bdb79","nonce":"040eebc252fea626a3db549d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"358bdea1f1f0b19a07a9736b6cf2cf6af64e6a2fb3498b5091c1a3316d6f7f95cad6e5526725d812a007049be8","nonce":"040eebc252fea626a3db549e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"59de71cb125bf9eba08ab8b30465b617b77b353d4311f8349f5effef608eb86a07fe020d7fa936549ef24696aa","nonce":"040eebc252fea626a3db549f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"88a93be158c77b5b2832cbd5a6fb40a885e467f4bd9acfd6e90e48c727014295aa53b255f1e61f8c4aa7d39eaf","nonce":"040eebc252fea626a3db5498","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"5f8f5d418d0f2e4017bd1b599efc8705e506607257dfbea4e4b4c1c6f871d5a4b305f32efaff1e6f97f0323ea2","nonce":"040eebc252fea626a3db5499","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"e76352459ee125cc85d24d5ab5f65004a613ee400467fc21e897f48a454cb82f29612cad1638b3c5f6e19ce587","nonce":"040eebc252fea626a3db549a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"cb1d9c9648d782ec632d8ed1e5bc9b0fb4edb11d5e54eac4cfe74b73fdfaca5c4cce649411a092910e6b67f286","nonce":"040eebc252fea626a3db549b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"152bc3e2bb4e24deb55639dfb43919e2f41755046dd5a2ce588c8644ed21126472393c54f1c3eafcc5fc46b66d","nonce":"040eebc252fea626a3db54a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"5ea001304b3a946dc3f928a05642ac5717568b27c4aa75833cc73e3ce9eb579dfe684248da30cff980e27ce676","nonce":"040eebc252fea626a3db54a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"eccb8eed2532e1ddfa417a7e8ad23ba4c0059e4464d4dbdf48a24464e9e83ef25a553c656660bd57e0198fcc73","nonce":"040eebc252fea626a3db54a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"06373f160c58fc8df5e7dc3d62aaf1fc9ac207ce3495a06a98b790a0531ca429e13313bddcc74a9e71d17c6213","nonce":"040eebc252fea626a3db54a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"8e9c34f80d9acded8337c17537a4e0e9e2562ed6386a753c3ad9ce8af668553c8f7edcbeaa51227e0e4cdee5a7","nonce":"040eebc252fea626a3db54a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"b388aff4b80ac487cb9492437249096cf2b77ebc0c08bb96b3bb9bed04a6e222bfc3acee22500f36672b8f293b","nonce":"040eebc252fea626a3db54a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"d10edbc852fbe71b6045d944c0de56c5765f5eb52c73c03e39f2867aa1d0e0e15e990a7ad555295b8b3ad13e95","nonce":"040eebc252fea626a3db54a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"acb6c1f17b4c2bbca9a5ca5fe3b6b0ed967a3326dff8b623654a9bb8386d30162e5050b11c19bf87450a5ad5e4","nonce":"040eebc252fea626a3db54a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"d05b51b2e1860fabebd99017242055b8b82cf74d75d021fae3a54ee2892f16c6aa75178caf4bf0de7bf704e2cf","nonce":"040eebc252fea626a3db54ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"c811230345b0a1a08e660d2d10ea18d286dda904b621b8d0a38fc7a961e516984f3e14dbe79bd40cef000b5513","nonce":"040eebc252fea626a3db54ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"582867640044a03ee964aa6f4b59cfa629a4a06d9c5fe2a477cd8d4c8da6694f0714bae993af9f97ac9c409fe4","nonce":"040eebc252fea626a3db54ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"3f63ff53eb015117ad2e36fbca32c1fe34736f2e775f63ae936910d5bc7ec52e2d246425587156c63f006a1d93","nonce":"040eebc252fea626a3db54af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"d728cc6c95e0232301548e5bf39077d54573de791b64594e82bf57160a588c03f194bfa8f79dbc648c680b77a2","nonce":"040eebc252fea626a3db54a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"6883e488858d4a6650f8cc06e87bbe657ef01966cb9cf15202dd8a0845eef036d47b4a71ee87094d88e44a8d1e","nonce":"040eebc252fea626a3db54a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"15092c59665761a4b9669539f4d9ee3079270b48f2e4c2cb437eeb8ffeca866d7362c23cf2a81013a7ccbc9f40","nonce":"040eebc252fea626a3db54aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"230db4629868150657ee4675e0d88e1e6505f2ce496b3b53e088f100ddbcb661530a41922a47c295f339274768","nonce":"040eebc252fea626a3db54ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"a427d2e46ee1f7ed7cc3ca8ed617d6ee557716da71054a5613ba710949d7b7e574dda4b4a8e37d65c418356555","nonce":"040eebc252fea626a3db54b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"150e636c1b5d2e0abf7d110c78e87bcc1613b04ecb43a74199d7611bc21dc55b7ddd701cf68e5ff8997f89d5e2","nonce":"040eebc252fea626a3db54b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"77324dac26f52903828ac748e78ad9ffe1cbd115e505925f15f945b210e268aef3f4779016bbabe1410139a91b","nonce":"040eebc252fea626a3db54b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"782687c5aac1a10e603d25f5f2c685eb79cdec31e2ae0a33e1c4545c4f7257dbf1bc8bdf648debda7958994bd3","nonce":"040eebc252fea626a3db54b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"c2548c2878533489dbbdf598196111032a17a7b0a88bafe9a01ce07d0e52e4baa60cb4e53b644c4177059d511b","nonce":"040eebc252fea626a3db54b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"2651233de4beb69bfdb8aa96d272ba079c11a708b60ba30a8c3cf400032ad84a54cdb14c7ead532f94a532b8e8","nonce":"040eebc252fea626a3db54b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"f277d2e059e1447b89c4af756f65d50f43c7279ea033f2fe2936fd969e010c8693e52d14046305f3678380ea16","nonce":"040eebc252fea626a3db54b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"aca24c1a4bf43421439ffc878924d3a0a73b484145c5c47232a84d280ee7cac9aca1ec9bd8edf219c0efe38e4f","nonce":"040eebc252fea626a3db54b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"47fa4824be0474c34a857ceb4594e80dc9b55394b9e2f5d9ad5697f8af2a031f1c97395705f487cfb8417bc8c0","nonce":"040eebc252fea626a3db54bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"269ec9807d225a25777489ccc61cfd4a95e9328aa0976439fada44d257870ad551fd514a8d80bb926ce246c09f","nonce":"040eebc252fea626a3db54bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"eecabffcc4e28ce5ed145293ded8babcf0007486a8563dcd48a0c6b22fa159d676b8049e8411195f8a62f5e621","nonce":"040eebc252fea626a3db54be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"aa803a6d6dada3a68ad32a2cc4ea120cf9b962802ee475d6eb919a6e6f6db6319950593fe2544e7c313277ac2e","nonce":"040eebc252fea626a3db54bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"efdc78bea3e5707044d4db1acce0db11858d803ab9f84af2ba91444754ba24591fbb24f671120879eb94b68c72","nonce":"040eebc252fea626a3db54b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"5ee59178f706e7728baea4ad59fc34254a0871efd0431e6c7b9c1bad20a7284bf63e1059d771c790965c28dfe5","nonce":"040eebc252fea626a3db54b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"7b344b98599aaf8b114b79989a7c2be584a5e5fe9ddaa2ed2e2429e3a811f8ff78e456e6579e7dbd769aad6ad5","nonce":"040eebc252fea626a3db54ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"6f4b0403436ffc511ac7d746e5a58c57ab37b46878debeef3bac9d09e3c8925eab728d161831a1be7cbb699dfb","nonce":"040eebc252fea626a3db54bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"85e374c975c5b0b294f8db72fbd933e1539e14ee83a72d0176501e80bee6c4ad07006ea4002c5bcd5c09e321f6","nonce":"040eebc252fea626a3db5444","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"3757cb394107925169515665a94fb310ef95108c95194582edf7e4721fda9ef12369369125ee349116c6bd685b","nonce":"040eebc252fea626a3db5445","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"ea9737368aa06de4611661d324b2db9af8eee9cd43cedfa884c2969471e920a4c1ae0256ec2821bef70676cd6c","nonce":"040eebc252fea626a3db5446","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"f5ec7be3e7ba4713c918b3131472700585e9e0506adbfdbfa7025d8d83b42d5df1913564119af703b53fbf4246","nonce":"040eebc252fea626a3db5447","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"b3a60960bba63e0667a5c5455780ff7d75f2f7f90fe18f8319bab81217c56d88dead1b2ee5ad0aa2b85385dac7","nonce":"040eebc252fea626a3db5440","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"fe2f400d2e53c209ae0dbfd759cfc37ddeac3fabc2bc72d42b60fb25da0ac3588cc49dff34a2261869f7189b7d","nonce":"040eebc252fea626a3db5441","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"ab70d587b2e9565e5a3c70ca666d4f22e9b825b83e7ccba2c84c596f4bc2cd1d1b3708102a6b4dec5929ee69ee","nonce":"040eebc252fea626a3db5442","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"e2b815f2ae4b9f2c071892b4b76538171fe9b876bbaef1f44ee2dbcf7e918e48abdfc30bc810c7316cdbb6bcae","nonce":"040eebc252fea626a3db5443","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"684ab42f2aef3d5740677efeb7a229564640ad08e43b76abf2dc340d4162ce7472ccd76ee3c01cf1e450c30f0a","nonce":"040eebc252fea626a3db544c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"b6f1a53e09d0cd1f1b5cb5c0e6e5031dc73321637de8f6be64c8b85e42bee2e88e8446052ce0eda5ddeb231a25","nonce":"040eebc252fea626a3db544d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"0b4c154fc5c152d0e9da457071f469bd2b01fad52996ecb1ed62b7e3e360e1b6066755f8a2ec784fd41f8457c3","nonce":"040eebc252fea626a3db544e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"5b154717cf44600c3922aad22ec196bdb7b4674a9dad7d6b60cda6f031a7bf9bf00a6999ac0ee39df3f11f05e5","nonce":"040eebc252fea626a3db544f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"5126467ddb58f0d4ea54aacb4bc387f7949ef12d183f2595be50ef3be5f2d05d3ce66ec397c47a32b35c142a90","nonce":"040eebc252fea626a3db5448","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"160986f7efb4dc86edc5f695e5b97f2994b28d9930f9d28ce56e1bb1bda7cf82c15c2929d573fcd2e99dce656b","nonce":"040eebc252fea626a3db5449","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"79bc75a96f9cd986dd6b04061c0f3361e254e22c9068bb7f5d92a8c6a67adcd3cc397447ccf21936540e28ca3c","nonce":"040eebc252fea626a3db544a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"3b35a28a1e2989690f11ce36662bdece5b965647aacb92f6695bbe460447e686004b37d64017e660a7fe6075cc","nonce":"040eebc252fea626a3db544b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"eb03870840fd7ce5cdb7c3acc2fb5c11d3669cc7000e3d178a5617aa57c839874b03b97ee5fa02c8317638bf74","nonce":"040eebc252fea626a3db5454","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"1832219d68130aef2954b2c7cb21e95ac3f87147e585311c5f14d35c08e9d3c7614281f7117bea8a010cd20a23","nonce":"040eebc252fea626a3db5455","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"d086469e05c45f719e06dc6df0ac8749956bd90f01653c31e38617ff3056bfef182227e346506b0cabe9f7d6d2","nonce":"040eebc252fea626a3db5456","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"ac8be0bb071a51fb41a1d129e616a82e43169fe9e3757c83d2252febeec31fd6a5e56919177b5b822388e5b04a","nonce":"040eebc252fea626a3db5457","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"62bfdd170075962b9ffe0c99557316963919a5768e194de7471bb3f193bc581f11ce8bda4872449177289216bc","nonce":"040eebc252fea626a3db5450","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"5d604171d2ce52d04b99447c457b05d195f3c5df0c923049b729f61ce173b047451e825f95b8579d59bd3d5cb1","nonce":"040eebc252fea626a3db5451","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"dedaa9d95ac27ed1aac33afe59c2203468747f9a0ef5de42e7b13242391dc7b5bb7289fd7e96ddd9ddcf5c0e77","nonce":"040eebc252fea626a3db5452","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"369c2b73b0f75df51d48a5bfd8ac0c6d9b948d2f52f6c725c239d5647edfa635bd1f78d8e81fe07859c1a5eb7a","nonce":"040eebc252fea626a3db5453","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"fa33171fd432be1da3c27db712ff5dd0204948d9f71dd837576a17ab353e900e579e6ddc2add083ade36bdf62b","nonce":"040eebc252fea626a3db545c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"2dbb8c8e6bdaf5f6ea05577cd683ba434353ead93268ed066a9f824755125e8a0ad411b966a37ffda2a19fc2d0","nonce":"040eebc252fea626a3db545d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"5029d97efd779c2b46777d4a5f1f1cd95d9db645003bfa6035029b568907c7f10fcf46eda3931f0cd27d32fdb3","nonce":"040eebc252fea626a3db545e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"9654156eda5c7924922c8c796b86b15eb57b6efd7dfe6d9055537d765430880a4fb158f20997bae99a8499bb4d","nonce":"040eebc252fea626a3db545f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"7b02ecf3aecf14bf5dd39b735bac81c97aedf804e1bd8a3ca749777478baee6281ba851ec56cf7c4ee63f05f23","nonce":"040eebc252fea626a3db5458","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"6aab8304572697c0c07de43fa4f78aa93460c230f6d0837f9ae91f42a3dca207b68ff1ccc82db7bdcae0a1adc0","nonce":"040eebc252fea626a3db5459","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"037edab0aa4357d12137c9278e1392b05e9a54b835e02aef775d5dd17cd19b74232060b189ef05f51f20d0db8b","nonce":"040eebc252fea626a3db545a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"2cdd78c737be44cdef5394b15c8858796727dbef859c98fa390a7290e7355c6cb3c28d2c9d65c14181fc6e85af","nonce":"040eebc252fea626a3db545b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"998a483628b53a2464d49177f8a2228f313059ce02783e4f0672ef05cdb59f8f72e098b0aa5d3064fa1206a3e4","nonce":"040eebc252fea626a3db5464","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"e0133fb6b0f5d56d7d58138bfccb30ed11221bb0c066f1388c29a58e3fde2690ecd78271ceb85df8325a4f6ee5","nonce":"040eebc252fea626a3db5465","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"e5105f8f02cf18d2459e25de00891002d056335b1be2d00a4f0377c95868ef228b29b7ce823fc8cb6d1de4b920","nonce":"040eebc252fea626a3db5466","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"4e263996fd6bacda4706830865ad386619f0b7bf101895155d8eef68e584d76ce5e92525fd65ded79d9bec19ae","nonce":"040eebc252fea626a3db5467","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"bbbe651e415b78c927b5b6b45d157102ab884a5e878ec27d9e30c4651e79fa3db92a6e31071343d068ce7bc0d7","nonce":"040eebc252fea626a3db5460","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"3491a3083812863d8e62d52198e8147078e0c46003cb7208ada83bd5783bc8c0026c17556ad8e60b3e9f853def","nonce":"040eebc252fea626a3db5461","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"7c16b6661af327e0a12073c8eadb1797a09d82d7ca1ea9760dc085d0b608e4fdd6edd12c42da1bf7cb92f4f15a","nonce":"040eebc252fea626a3db5462","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"6316da1f29a1571a50370f84135e697b9d30935a5a691d9e371e55c665c1c9d2769267e9be1ce3bf8b22076fb2","nonce":"040eebc252fea626a3db5463","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"b7f59eda4f4a2a87376d787687c8b3b1d25983f1ecd82a54a30158dfb83e9d169961179b3b71cbd5a571fda816","nonce":"040eebc252fea626a3db546c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"75ed52389805bb702709125133337e0adbea214ba4abf19636b71343f1af536d2f98f34706bcc06e258b6c0d6c","nonce":"040eebc252fea626a3db546d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"ca3956caf0d8c14e6ee911cc33d9d8010a9182629a192b69d98f746d788ba9f86e1497ddcb50fa34443b7c42e7","nonce":"040eebc252fea626a3db546e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"f7ef7cf967626b15c0bf982e105581c3dad5e78d559622ac032b1f22921142ed1f40263a72c87b8ef7daf316bc","nonce":"040eebc252fea626a3db546f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"0397944d66964f76573a4d1901e6408716f3dd557b4c83bee82c2c0a3f42419b63933eed6ea068752678dfb0f2","nonce":"040eebc252fea626a3db5468","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"1ea3f759db797e6351e8ef89583cbb4e95994f1d039db47154b87c66e1d4de3176c42f8752e3d3c75fc7615e6d","nonce":"040eebc252fea626a3db5469","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"8e69f3b66355d1b175ab1e2280875c46fdc9225df2262e73fbe4441bec42bee257e6f25f0fe573dd4a5b4652ee","nonce":"040eebc252fea626a3db546a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"2c76e6c182afaad240263679ed4fbf07c5077400be628f10485f5118c3c2aae4fe0f21bbe7bb0e9ca84400b043","nonce":"040eebc252fea626a3db546b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"b9b51f94e0282ec4e572d703e3ad83a9cddaf2479657b91893ef2bc9a561727b6f597127019cf5cc772c359479","nonce":"040eebc252fea626a3db5474","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"2c5ed92d693b523f25821ee2f93b1aa6949d29e544535d2953552490e7428ce051e8b85842aa70ab540cf90369","nonce":"040eebc252fea626a3db5475","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"d0baeadfbfc93d95505044062d9b22a011c944362c57fa105ceac4ba363c6f0a1db0b0243b2c93a1b77376d48f","nonce":"040eebc252fea626a3db5476","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"a664f69ec0f46f10b3154ffb8042c0927952544a0beb80226b1c8a239719d6f5d26fcb67a283a7fbad21ba53d7","nonce":"040eebc252fea626a3db5477","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"0d118404eaf63b97c6acddbe3152e9020a13f57906a93245d1d026e9524071df8904d99119c15da69f5ba02a65","nonce":"040eebc252fea626a3db5470","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"c3fd9f338ade65f52d32cde777e5a305e6cd93baf86a4f1bc9c5594957564f0c790624d1a6f033e9ca5b99a6d2","nonce":"040eebc252fea626a3db5471","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"d1e4df7cebf4d7c4cf50265f0cb17fb73ba2fc9a45952c156b054d02c922878604c95628cc9ffeb6ef81650a37","nonce":"040eebc252fea626a3db5472","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"1e5aedf33aff3f8fa96118e675c0c5dc1d1f830d0014d2e837049dbd9615ad770a6f2a77d1752e4470c272102e","nonce":"040eebc252fea626a3db5473","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"d09e7be9cced6382a532efc5fc7093f35447025473b9b524a78c5c6960a8a37bf102cdef1caa935268cd1c2f86","nonce":"040eebc252fea626a3db547c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"735bf45f50860a93be6f8d9c7ef4c237efc6d0f6fc686b95937697e53f7980b2f45a666602f464496a26183990","nonce":"040eebc252fea626a3db547d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"4cd60c250c09d4dc65844dcd8b53b5c071b27d022b34486958235d0ad9ee5101824c207632c8ceff5a8f5d9afe","nonce":"040eebc252fea626a3db547e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"71434cf1a77e87d22681bb7b4cf9bed5b8218af9f6a836add47075afd26d06ad624beb5e2c9fb0fb9e77f471a8","nonce":"040eebc252fea626a3db547f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"e9ac1cf56896e35df3e359c0e2efbcdeebe16d291c12bfa50cc1395e33609d4ae1d99241284ad3b5d523f6ff16","nonce":"040eebc252fea626a3db5478","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"011407b500cbb77efa56096de7b96759822e162f620ef59d26db26c02fd3db3cd4c447786754078da62bd2cc77","nonce":"040eebc252fea626a3db5479","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"902793efd62f1c1b68f77b56a71b49902f6603a14a935adff7e9818bf8d630a283afc4852f7a4b6ec483d3411b","nonce":"040eebc252fea626a3db547a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"26738ee404bc09471da35e446a88cf749a9c39c3f02a8b1c84f77ebe119698c4dbd853f92f7403c26af3f6e1e9","nonce":"040eebc252fea626a3db547b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"b54bce415dd53e6dc1128c01f44298dc8d402ea1253212df9cd660c9545c285a2674341324fa748c1724202a06","nonce":"040eebc252fea626a3db5404","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"c776b80e32f63ea153707b4e2524ddf257c6103b9f6a236262de851ed41045a93e0ce7ab265a20f9492bd685ea","nonce":"040eebc252fea626a3db5405","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"4ef957bf766decea28b1c6d8d5626a62715a407dd835c8834473c1763d08bebc8589379028dccdd283540c6cfa","nonce":"040eebc252fea626a3db5406","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"4703a759b355b09359415aab2efed27c4ab2047fe85dc5ec0298ad7813f1d66d48c9c6897338722cf1c66b0e8d","nonce":"040eebc252fea626a3db5407","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"67f67e4fd2c2eab05e58d6cd40dec9a5236fc7767837d990f8dbf7011882e4d84b7efdf7f81b66c955bb1f5037","nonce":"040eebc252fea626a3db5400","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"d678362d2afb53397e10f621dd968da1f9814f94621e9f6c88335d548d1fcd5351ea4adab35739778f963d8fca","nonce":"040eebc252fea626a3db5401","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"905c74c25c16098cc164608842f84e70fe5d2337334cdc857cb2de0ba2d434d30ef71efbe672bb74da7202bbbc","nonce":"040eebc252fea626a3db5402","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"f6fa8757149df38dec66d7a82b45e458b03d812a058244d78f9e281ca73d7f893e9c6132eeeb2bb2842448d58e","nonce":"040eebc252fea626a3db5403","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"2d297c2614c5682b0d5e86125a27a7fdc42428554021a5cd0c8278bd223bcf4e888828ffa6ddb2c2e93d2aa851","nonce":"040eebc252fea626a3db540c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"ef31ad6e20aa760376984493a8121458e5c8f52bace87d650e5cf100734ab19806a2894afd7c3a7011baa5ddff","nonce":"040eebc252fea626a3db540d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"64ff1a8d34312ae37ab66822945d84a0753972ceab417a7909915860c4f0844d7aff519472d2534dfc4ea6eeff","nonce":"040eebc252fea626a3db540e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"3934b5d95df3bf6b95161cbe414c80be472efaf1cd256bdbf643b5c24dee5c3e2faa57c6b3fc138b874051a9a6","nonce":"040eebc252fea626a3db540f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"bb99c8263e891fefb65a689f63f7b4e5b527990c4bcd195be6b422f3cf0b78fb8db3c84b3d268201fbe970d755","nonce":"040eebc252fea626a3db5408","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"7b1cc7de48cb0add5a4bf3e5c0a218dd6fefb53cb574fc7683b606bfc3bd905d06f3fc93cc2d394745cbcbd342","nonce":"040eebc252fea626a3db5409","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"eea8ac56ffa681326ec01c64db48fb997576d8edfda80d415d58416f0cfb289f75fc963b949aae16bb3b8bcc41","nonce":"040eebc252fea626a3db540a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"846ae226ba482a3a9566b72e6fc46c9fcdf5594342583941dded66fc7925952701f29ac1256b4f0eb58010cde4","nonce":"040eebc252fea626a3db540b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"f22931716a6942c76da4719d8aa19fe25aa9833c53c6a90c19906f0259ca05106adf398c9cb32e9c953f65a81a","nonce":"040eebc252fea626a3db5414","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"630152acd2c7ab922b999c5adf1b7f722720b8b25721fc2338db352aa719f08c3207189df1ad29b5fa2707f137","nonce":"040eebc252fea626a3db5415","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"9a3993268fdfd630670ebe6daab27babee408cbef3cae2114a0e6fe1d539099e7a3441790b512c5c6208aa4d49","nonce":"040eebc252fea626a3db5416","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"bef2eb0be65a6956469d2eea9f2afcc42ac7f120bcf660cd529517162301c3e1726bf3ee718033ce4416c5cc86","nonce":"040eebc252fea626a3db5417","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"3b870fc1d568ed0a54d50cfb86552e8b283d971cb1a7cd0e933dbdda881b5ca6258fd6a2579dcf353e58f5e7fa","nonce":"040eebc252fea626a3db5410","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"8a1ae94e7229f75ca08414dbf916a8476c1fd912e07eb08c03f2a61b59e51cbb498289796495456bdf08cf56a5","nonce":"040eebc252fea626a3db5411","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"0d095ddc9b2af76faa8986cefce2b3fb83c25651531bdfed66b6e7f97106e79e3f32003b74ef2ae0e31dd4a492","nonce":"040eebc252fea626a3db5412","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"630c4e6c0ae3199dc940e846d9d3432e2d2facc0826b5517f475b2c219f1682387cf158f2f747b37d5a34ec194","nonce":"040eebc252fea626a3db5413","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"ad77a91abff8fd237e7cf41b3682bfbf73594205ce200d81a24d7cab7a30cd5c2d5c6ea4ec0d0343a1eb5f6854","nonce":"040eebc252fea626a3db541c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"364683b41776367c737b3e9560c81785b0cf06a12b85f906f07c169326bb5bc4eed767e7624750d521149ec844","nonce":"040eebc252fea626a3db541d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"13eb1ae812a1313722bee27c892cd49bcfa271c79b59f7db50b92e2efddb952d4707d75f81a99519d192e03200","nonce":"040eebc252fea626a3db541e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"bf2fe592ad1d3ddcf70f1256d10144df9f2ec1f4a3912b237323a7145667ece8861b079981d27a1076ee64d6f0","nonce":"040eebc252fea626a3db541f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"8099b5d7fea46ae7931f4543fe81f63bd737ebff730e2358742a036aa45ff6d7599418d9f4fd23d155c081f859","nonce":"040eebc252fea626a3db5418","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"628f5b4b9d85d11ea8f4613792a88388b0cea444a8329538e3855ac458130060af14c93acc473bea5e2cacd940","nonce":"040eebc252fea626a3db5419","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"979ef4edbee76f7b5df6ba2ea137ade8649fc8c805321051312974dd44463746346d844b4a1fa9d3f7313e2143","nonce":"040eebc252fea626a3db541a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"1fedd7ef87ef2399eac260c34a973e3c64fe7f85a2e3cfdf823bd6005d362783d053ae894faa6bfcedea54c984","nonce":"040eebc252fea626a3db541b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"2155688d15d0a92c6331c6bd78e6576fecd3b07cf3da9b86fab54fb40958c19ba6fbfe4bdcad1105e20c8db137","nonce":"040eebc252fea626a3db5424","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"7d6ae7093acac0c57558389e57733807f8672365643a73a1b493c837dc90a98d821c2606c136eae82b0986f5ce","nonce":"040eebc252fea626a3db5425","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"24111ae969dab1a213473c8aa91e528bc1f82486f3cddd4a3c31df93dcb4107bf76e0b5f99810b45eb2e4d37b5","nonce":"040eebc252fea626a3db5426","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"f864dc3e2b5fddd962a4c350c040b01aa156fe189fffeed980663fc56052f3c91b5fd9e623d2bcb8671a2350be","nonce":"040eebc252fea626a3db5427","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"794a94a0ff1adb7400bc56ed7bf62e857895358641bd500c283df78805077d55c98e1aab2e457dbb7e190da581","nonce":"040eebc252fea626a3db5420","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"04c387db5dfffec44177783656a9c039271fbe7bd7b61fc60d678ec3c2e45bba2b36fa3a0bf347941d08499505","nonce":"040eebc252fea626a3db5421","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"4000aa3d1e260a10a140b79c6c832abf34c60d56bea755a7fff4f0047671b1b8a59ad351acebbd65d755c72cf3","nonce":"040eebc252fea626a3db5422","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"984ff4ea5aa31058e4fc8d58274286f8d1cf4c9f892dd7b9ee6383f3eea9cb6fdfe82e2ea9ce84eaf0fc7932bd","nonce":"040eebc252fea626a3db5423","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"117defc738be3096bbcf86b820ee027feabb774740eb64c81cbe29edf4da1b4fdd6eddbb14d17e52d2e4297704","nonce":"040eebc252fea626a3db542c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"3e78a0ca7a8365fb1e5910bf8bcf08a2660725e1c9fecc038ab0ac34dabac30dc710d78700dd16055f3f4b8d21","nonce":"040eebc252fea626a3db542d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"6318a1f3751b52d0c39cf7e71e648e8381ed16aacdd544d60eb8416321b943ba8f8afb057faeed6f0f1d1b4ef4","nonce":"040eebc252fea626a3db542e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"898791b39cbeee78841933aa4ccc94dc6351449a208a920de83e83aa0592d62d2443d82f0428ede9087a21cdf2","nonce":"040eebc252fea626a3db542f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"4fd2dad6d7b86c69be03147a8b47b1b686baf2a0b8d9afcf3e064751849ee40de1f3285e03b851b1e3dea82c3d","nonce":"040eebc252fea626a3db5428","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"b727adbeeb6053a4be33d497f575b4009956abe499a497a21e2f73f1a6f4ba975e9bef654bac6f1db54eaa61d7","nonce":"040eebc252fea626a3db5429","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"5043023ff9612ede586ed1d11ec18d26cb4a87e217c0bce5d29e625ca3052e749a3a2ba6d8917387b4d4f61060","nonce":"040eebc252fea626a3db542a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"9c9663fba32eaf06c53bcf4d7636ffe8650661745a30069695134778f76fa9ec38868d3318312e42aeac8d0756","nonce":"040eebc252fea626a3db542b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"b0ff52ebbbae5cb99237a549ff075e459223bd279cd4c6f01d2ffb8451b18c6b09b4576158a2f5dd3905c0a1ad","nonce":"040eebc252fea626a3db5434","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"b74a18806060a963e51f0ffb9307ebcd332ce1fdf5ac6a3ef41fafef329bc14af945b99544080c5b42647dc8be","nonce":"040eebc252fea626a3db5435","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"55dd2bf4d4070bc0c51f6eedd3addf5d19ec26568cee3191dfe413e352dda49e1940353524d0a830892b70a75f","nonce":"040eebc252fea626a3db5436","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"6a93e517478cca6de9e1fa1108f1818fc99633055105714257ce607693e39322c5e423f94c3ce1425c67035303","nonce":"040eebc252fea626a3db5437","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"a1cf6932ce304e90d96729ed10c4468fc115c81261efb419ed040aa20ccfa3aaf204bbce9873d0707a7e87b6ff","nonce":"040eebc252fea626a3db5430","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"895a042cef8e240d6245476abd64f425a129c1ba716a483e44e5a5d5436702ebd0c7d9ffb5e693a44d258c2b65","nonce":"040eebc252fea626a3db5431","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"96f6ab591a6d58b8d0851d77bec1f1cd1e4bd43c9cea99fe04693160c72b679deb068833a7d7d13625d7c75abc","nonce":"040eebc252fea626a3db5432","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"3b2bf980d511ede95c53cc9a1b6454fa8d6ba041c64d7968a118f9b7db3efaee72965c36b36433e364500b468f","nonce":"040eebc252fea626a3db5433","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"737276adcb987564f4b8043f2b1a63288d78e7fb7908334f905b90903485f3966504d19c5925923e5f06f6ee24","nonce":"040eebc252fea626a3db543c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"10225542c9d99af4eb9711b5e6aca70928b254f25b1fc75ce645c8ed0d9de9148d20d46e8521a607ee5a7000d3","nonce":"040eebc252fea626a3db543d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"e1abd5eb98d229854e6d0543fd72d764bc07990fa72c0e872e76aef2ddaf08bd252be6b0647af8cb1c4f3207f9","nonce":"040eebc252fea626a3db543e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"22d44ead3065c27c12829cefc48b02df27013b44b302fd78755d86b4b32e285c90ab0194824f4af0114836d17e","nonce":"040eebc252fea626a3db543f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"dbc406abedbd69cf2da7a31c003e9eaae1590a5bb4940b78542db6204a38d9dc816169aa57457a8fa447b674b1","nonce":"040eebc252fea626a3db5438","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"7c00b9b41a4100cac3969cb364b1d1bc644b4508d97d21a6aa8bf711b45de18eac27bb16d23e90ad171c13fe2b","nonce":"040eebc252fea626a3db5439","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"1859c615fce9329d31985058bb0888cd0469c34957ffcbb35583f10f599940f4bf5a98e8840196b4648189fabb","nonce":"040eebc252fea626a3db543a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"c551b59c929f1fbf10d5455b23cd1d4a4697fc3e3502721d237b4bdf0e6c1baa3545e2c16d400bc613abe8d291","nonce":"040eebc252fea626a3db543b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"c754bb9449a65ba5b588d9ea62c0fe6eb2f5bbdcf59bec7380d1b02a78785d40b3e3f5003877fea7f5f44de845","nonce":"040eebc252fea626a3db55c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"0f13c5e87431ee3c203861535a3dc4b3c4efecfb11b3534ab600f34f603d92fd"},{"exporter_context":"00","L":32,"exported_value":"9820d10ab023dd11d54b91e5d65ecb01c32db9e26c26ae675f34dbaaa148bbaf"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"f2a8b6690ffb8f16d94c22098e8780662182c53a3a98c27ace7bcba5af981557"}]},{"mode":0,"kem_id":18,"kdf_id":1,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"1b4a4c8b4a9e9d6329bccd08d9cf10f76b0b68166d86d57ad40bea1a6cc7d641d013976cb794f7e455fa2ed93129cd21fd0aa4e3da9a77efc56b5d1376494305b856","ikmE":"40ef2692df15046914ec5bbfa6cf195a0b40a478590810b2d8178a7040c13385eb7bb81f798bb3394f73bc5f58f06500a3ef31f2be9ee53b7146d6badf55d6fdc3a7","skRm":"01c4dee8ebaffe3273de51cf7eb2e847dc29165758302a01e1208f1e4f47ddf6001fe9d9e7e89b6d2185c53233f67ccbe6d9395dc59e835108d62fe1d64891a32cae","skEm":"01fe5bd733a153f35cacd37e85504ffc854905c95b31f24066a167f371056b9708002cf356def5c5a126b8ade7de15d8d0976ac988436898a2d47243bfc26cb71689","pkRm":"04007167484e491004c532f2d0d386c223d338e913ea3379e69d907a753c0a576001573b4e840bfc7e214ed5b488311cc01b568c09cd651679770fc4366445133e3d6000ce36778a8dc267af196d3f52bae86303a87284961a0e0c4b6dc88ecd3933ec3ffb0ea626ce6bb903eb03417c94136ba84aa5185bdf8f1a985201ece12dfe571cd0","pkEm":"04019ccc03c6c4c9a3d9b8d39da8e00342b6d61655c7aed6805b62bdb94096aa821c5204aed39a2f28bbb217cd122a0b0728f5dc19ef172c3c3adff9472b174c76eee501478a762a8b34c227055ba4afcf96ed9885c1a102f0c4ad3cd12895baf95bf4c7fe5b7a505906f2479c50dac5e697abde43d0e8e38e50a56b3097a048d751d09996","enc":"04019ccc03c6c4c9a3d9b8d39da8e00342b6d61655c7aed6805b62bdb94096aa821c5204aed39a2f28bbb217cd122a0b0728f5dc19ef172c3c3adff9472b174c76eee501478a762a8b34c227055ba4afcf96ed9885c1a102f0c4ad3cd12895baf95bf4c7fe5b7a505906f2479c50dac5e697abde43d0e8e38e50a56b3097a048d751d09996","shared_secret":"8a927d423e6479e8f79bda5abc3f7ab767042c7671dc2e00ce59ddcbf3ac2a58aecaf3faa8b64f236505ffcb018450300f5741b491835da5693a3cff411d57e0","key_schedule_context":"0075e4033f8435ab2e4351af456d3d0e48d88f048993b59a50ef846d88fcce0f81424d5fd737aae133d36f3904a06750412f8aceccf0b84181f9bd44ed7735e65a","secret":"8f51165e5f2d8a94669e0c7b92772dccccc4eb1bff1eb4de6ff00397c281455d","key":"1b659367e1efccb1442694987f55d8c5a4826c84e126d52ed27a8a67ec46c256","base_nonce":"848330bbf6e3d1aee0c04888","exporter_secret":"084d252162829c0bdcc36ef0c738fe9a555ad9ccc7b4d424a24bc96988a998e5","encryptions":[{"aad":"436f756e742d30","ciphertext":"0bbb4abfe1223199ae9a71bf8f426df5c2cc3614fad8f8393c2c66257dc3af7f0fe2f35dc4a6fdf64fb9a78c0e","nonce":"848330bbf6e3d1aee0c04888","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"be740c08ac263feb22d4a9eae6c4611b022ef57ac4689e7d01e2f8b002bdae9b35cc5583e1f02ec3bdbeac63e7","nonce":"848330bbf6e3d1aee0c04889","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"b656eb0cdb82d08c583bdb2fd020d23943a60d16e04e5ff219333e71ee68d3246d23a2c12036fef0297d0effe4","nonce":"848330bbf6e3d1aee0c0488a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"643f7a68c701c0f15fba0b26fccf43a7c23087fa4558cb441e4a95de67acb4a8e277bd760c7542141394ea966f","nonce":"848330bbf6e3d1aee0c0488b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"f328e5c802a2e0c98561863cefc7d75595fd62e0aaed50440b528d4e2acff796a7976bf8db2bc0bf13b6177390","nonce":"848330bbf6e3d1aee0c0488c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"7b4be6b143808a61e04a37a9aa4c082be41ad58cb82d96aa2490f6fb7b60be9c507e98f2e621ad9887d6116aaf","nonce":"848330bbf6e3d1aee0c0488d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"a76b4adf162a3779b129eb53bb6d05438386127a02da9daec2cb1d86953af4d4c4c206319012d6a3f917d9f04c","nonce":"848330bbf6e3d1aee0c0488e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"6b2890652c086cec67026713d25135504b6048e33b6504f616c5a4c8f9edf5cf9cc11857660d7cd205caab7377","nonce":"848330bbf6e3d1aee0c0488f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"6f267c0d701516e324d5179f2962a417cad55149d3edadf4c3f35b8afd90a2dfb3206c278b895e555cae676adf","nonce":"848330bbf6e3d1aee0c04880","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"91756293afaafc33d51b36a14aaf0ee1482b2179cba04af3eff25f20b4626911791d66e61830e2eca5ab72461c","nonce":"848330bbf6e3d1aee0c04881","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"291469dfa3063e4ea718fbab8058312db23fe0e9e5726084bf0e8030a7f0637619926c74ad2c00e8edf3ad0cad","nonce":"848330bbf6e3d1aee0c04882","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"f698f3b222efe75a572987cd110b52737c6ae4103fae53c76f7968d0f70e9bbab72c3f4445233989a2ca94065f","nonce":"848330bbf6e3d1aee0c04883","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"7764ede625cc7eac84acbe013fd7da37af2eb818ad42034458916e535e09bb4c2b178994de6efa0d6b320024a5","nonce":"848330bbf6e3d1aee0c04884","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"2fcfbb3f70d15ea29a5a508b27d3ae403414ba1897ba1ffbda9ec3f05fd3ffe8d493eb15131549984f51c20f42","nonce":"848330bbf6e3d1aee0c04885","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"e5b8de55906c126d3d0dce4b6735f8456098ceacc4ef887d3df2055c3f3541d6c5f9ef6a0b89ef530ca5ebfe18","nonce":"848330bbf6e3d1aee0c04886","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"c6db6deef91cf23d59f7b2084960466b9a6a0d68ac8c18f7703021364d348092245b1cfab832e0c17ce02749ad","nonce":"848330bbf6e3d1aee0c04887","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"6ba9b374dc33bb63497eafc8e9976e317e2eab7e20e1419c274763d5084693105432c977a6d138a71dd90add2b","nonce":"848330bbf6e3d1aee0c04898","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"d22641fc9fac4a5f75afc3104fa3b21eed21e364d26048f4b6b67adec3fdc0b8688c5589d469cde7f7c5df8983","nonce":"848330bbf6e3d1aee0c04899","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"8880eab103b118b59fdb6ec51d351816fec7dbe1f8b59cd34a647d5ba8e68bce06fbff88b54dd183306e6a3812","nonce":"848330bbf6e3d1aee0c0489a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"5691be25a8699d0f5d56b9281248160edda356b9e20e53a4a16a146bad2216a1c9e73be25e53ae337a59430044","nonce":"848330bbf6e3d1aee0c0489b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"4610ba9a929ca8a61afae04709227fa69625c06c0bfae5fe81b6e0b1ac5c89cf165af4fbfb88463112c51e344c","nonce":"848330bbf6e3d1aee0c0489c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"455662b299adc4c2887bdf34a5a9e76d417a3bebb2978a69d6cab394bc1d04ef03e1d969f21a4ab7c1832c35d6","nonce":"848330bbf6e3d1aee0c0489d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"fd838919b227beb413900ca2de81426b68c90e6f0e784398d294cc050f69d393e237452aa4fbc75d3f3f658c8a","nonce":"848330bbf6e3d1aee0c0489e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"ad70752ded80c3ef3c7157dca4c7b8763326606dc1f0e547f5a72b7d552e8199b359353bb7aadb58a71f98450f","nonce":"848330bbf6e3d1aee0c0489f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"4f76f9c41f953265cb5ae5cd67b3896deb1e1cba5a2f3d6f37e0c519682c962cdee2c568ca43f90bbb84ddf7bc","nonce":"848330bbf6e3d1aee0c04890","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"9372031308b2067e67f93d22138a211f4860414bfd15f95a0ccbce3842f136d8e4a275d840bc563bfb7e0bd7fe","nonce":"848330bbf6e3d1aee0c04891","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"e9cf00237149082287e3f409b64037c1f569095d930a1a5af3d1da971c34348781e338bdfbca87382163cb6c9b","nonce":"848330bbf6e3d1aee0c04892","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"353af930b903738830f222ef3d02e3dc0d47dc4df73e3cfd43338d492ad584f46ad046ca1e1c12891d23624a46","nonce":"848330bbf6e3d1aee0c04893","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"170b73b235eb947aa2a18443a5bb7d4bfbae7e46cc4835196b04c89d776bad92b10244a10f0c4ba3f711423cef","nonce":"848330bbf6e3d1aee0c04894","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"048371d4c7d413c7dca8e9a757dd7098767f9ab3256874124db2180b285e7e761b81f8b6457d53dfdf48f167a1","nonce":"848330bbf6e3d1aee0c04895","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"8c16301551e9f934ff24b305c522924c9deb38c6bf32c8b5fd047ddb1ab85fc50a7d90f1a712b2238bb8a8ce2d","nonce":"848330bbf6e3d1aee0c04896","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"cec4854016172697e17b5455ff8e4c9a7bb0ce6ed1530154e3a91315aa91c99036794b666099e45a3be4938f8f","nonce":"848330bbf6e3d1aee0c04897","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"12f9c93bb382338831d16ca8e98d078fc9034dee153e7221e281229b3559dd76d3485135b9f49d69873520e080","nonce":"848330bbf6e3d1aee0c048a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"6addcf1915bfd127437644e010f205919590d82354a287b48f46ac28e01fad0a749171e9265de1ae0c1024363e","nonce":"848330bbf6e3d1aee0c048a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"2810cf755d3416e498f45ca9c502d39088f92e5c676c598b7f3e9ddebbf32236348f4902cdc14660c8569eb478","nonce":"848330bbf6e3d1aee0c048aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"637aa5c034ce73439789f9697c947adb312c328fab1c7d9cd5ef5ca7df03c0a8858be382af9486ef6629cc9609","nonce":"848330bbf6e3d1aee0c048ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"25f2ad0c581b01dfd58efb71d566a68fa6f414a7acf91a2e5eef2dba9c798d53f7de21508f5d3e06150c8c020d","nonce":"848330bbf6e3d1aee0c048ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"37b1e5521721465ae3c57ebcf53289725ae0a708626e01d031d4147b67d67549fccd6468360ad99e4042c1896d","nonce":"848330bbf6e3d1aee0c048ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"b0e25b841819574c97fb0a27884d7919e77585288827db25acbb8ffb48a66a72808ba8ead221a908d946ccb17a","nonce":"848330bbf6e3d1aee0c048ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"b3ba5f3fb58443bc035a9897436cff18e57eb973c9ea9f50aa221b90e553bfe974099fdc0c0d2cec4771e91a2b","nonce":"848330bbf6e3d1aee0c048af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"581a863f285319c8c6073715efe80c2c3c78ec24761870b62c4c66ce81f0b6a221a28216593d685eda68773da4","nonce":"848330bbf6e3d1aee0c048a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"3c363a2fb72a62ee86b2837ea1a34f2468df2e49c1ce56b9fce24f68ec4947db4ab9a0d2f0258261e541e79625","nonce":"848330bbf6e3d1aee0c048a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"3feb8bfad0ada7d6e0b07149c09cde700614ae5bd334da1cf859766ba4991451e581143de4b38068d1a83b867d","nonce":"848330bbf6e3d1aee0c048a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"04f6c0f4e20fde06635267cc6823213d71b9c0827d11ab8b77ca2e72b32282b8f0b596314a923e3b44501cb529","nonce":"848330bbf6e3d1aee0c048a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"66c51b1fb5cecbfc69b5bede785865ae63e24e210302e9bcb6c128be50d16a8a9294e73077624749c78f530c06","nonce":"848330bbf6e3d1aee0c048a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"de624c6b740617457e891b03ce1fc70a7063d359bf3bbaa41d8e31eb517ac7078261e54cceda54e549d4b8bfc6","nonce":"848330bbf6e3d1aee0c048a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"3a9fd89b565972e0b7bee0df86ba353a7f145af49040a01ae7e725fbd712e4246df162064fa0d2f2b6e09a7551","nonce":"848330bbf6e3d1aee0c048a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"44ada8164275325475528fa9aae8e535a023287dd151152c780fcee7f97677dafb2d416b3d0e2dea91e5c53312","nonce":"848330bbf6e3d1aee0c048a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"49ab336dea7b17e1c1b6748486156b1b9b8ec02b3bbece99a5db389c1821486ddc2b1d47385623de7022c9a5d6","nonce":"848330bbf6e3d1aee0c048b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"5e927b307c6796e8bb84f5cb350207e2efdefc15f2f5845e48c6a75a25c6fb7b08ebe252f4e20981d292c5e0fa","nonce":"848330bbf6e3d1aee0c048b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"6a854dfdeadac4c6a7f9dc27151cea60b1cd4133227feaae7a9c496e634d662ff9142d155a1afd4b1ff5611e95","nonce":"848330bbf6e3d1aee0c048ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"67fa017e32225e00be0753d7300fe8373b9f3a1222a54b472ed6e1343943a3da8cc147eba293e69c5e118d1fab","nonce":"848330bbf6e3d1aee0c048bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"e0e31e103b2a021fa02897c14e1c599aed54fe4069ff5bbfa37cf77309e6ba1cc55019fd5ab7693daa5edee2ec","nonce":"848330bbf6e3d1aee0c048bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"92e5b86ee61b49407a43b0c64a8d93fc44ebeb6e3e907351a79834ca6ecdef6a1c0c809c1c3577efce5f4c4fc3","nonce":"848330bbf6e3d1aee0c048bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"4069ca33d7ec89416d743ab5ac137edcf646c4769f7781954b2fe5162868ab133bcfabe31e4a3958c04e125c83","nonce":"848330bbf6e3d1aee0c048be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"83fc2ec23e0266015956bc9c13e7c310489adbae38f1a1c00f40a1f44f71071eeac31c9d2e929475ddd8c6641c","nonce":"848330bbf6e3d1aee0c048bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"da618350d0b95a6949c919207a49fccac2622dd45fd035d135c04d11e29580f34344b387cefb14d47392d5b546","nonce":"848330bbf6e3d1aee0c048b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"746b82ac65742e8c3438e0bd8f23869bf2c2cdaf334b48ac1f7aed6012f42a4ac959d19c0febcb4252b088aae3","nonce":"848330bbf6e3d1aee0c048b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"050b171762bb6c5b3f8f6b35d684c7a8adf9b28a4896d0b869b5bed6f59e5b227169299860c52c29da118841e4","nonce":"848330bbf6e3d1aee0c048b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"8ae2e05403685222fa2061258880249e1751e236b4f1a0de843d7e08f63ced82ea5be4a086260892c638a844e0","nonce":"848330bbf6e3d1aee0c048b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"f7282d20c160d5472fb82cd8f63240db00d11b30f65feab4c1fce2bec28193ba5e875aad3f3a1365a419a89dda","nonce":"848330bbf6e3d1aee0c048b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"36dcadb520cdd8ed0efd8a31efc051b3d2a166ed16255f014355996fa9c84557515d5b6ef43edbfac5ccaab18d","nonce":"848330bbf6e3d1aee0c048b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"7a43755225f0895837fc86cd2a9586461f520373fcde55d38735bc3edc64ad67c87eae3142669daf3da70ffd76","nonce":"848330bbf6e3d1aee0c048b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"a618d77857ca2e9918107ec24ecbe00db2973591495d86c2fc17a3306d7823ec106bcaff271a06d5a0cf9e4e04","nonce":"848330bbf6e3d1aee0c048b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"b6eaaaa3bf4a68df833e9acc58953f4f83979aed43b2865fb499793cb9872dc15073c8113166e94e50f46737a0","nonce":"848330bbf6e3d1aee0c048c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"677594ceeb37a3b48c6e37aa1c3b8a21fa87195bcabb3190c829434c68ae68feeb80692dbbb1f149cbf94301f5","nonce":"848330bbf6e3d1aee0c048c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"4aa1cfa617085999875cc5c4f8bb0f21598168bcda103c390cf3ff9bc9e789b5267f9ea64e078835bcc741da82","nonce":"848330bbf6e3d1aee0c048ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"16003342e19913554976ba7b712801393550be1846e1bb2d85be1417a774eafb62acaea76df1b21f286926fc63","nonce":"848330bbf6e3d1aee0c048cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"61f1e8b35913e8ddab4feefb725e01ccb0ab2ccebba9ebe09a0ac4496c5d6f5d941f2693adaf5a038adf32a536","nonce":"848330bbf6e3d1aee0c048cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"dcb1f690312d1b732828c55d786bb14b26df9210b06f07983c83ecae3968369c47a59f3a926762d057a6474641","nonce":"848330bbf6e3d1aee0c048cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"aa4cb4c70ef9b7215176605c437a3fe0776d5d596a69f31dc5b137381bf986323ed03078f55c1ae0cec4f01938","nonce":"848330bbf6e3d1aee0c048ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"3ef53d9005bfe2a7b7be239897175d3a8a097893d7af3c637c808f2c8946e5df7a0f428b4b63eade086c69c36f","nonce":"848330bbf6e3d1aee0c048cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"602d01c64112a255fe60a3c8bcb44ec11b4c7c6eb288eaa579852cee1680f94addfba92457ea3b03f2e0eb1e65","nonce":"848330bbf6e3d1aee0c048c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"737c8288a0dca2e65a80b0a9d8d453986da1c630f44ee912690dcaf318e11c95dd2366030c5d8fcb9076ba73a2","nonce":"848330bbf6e3d1aee0c048c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"10d5c1be26a630028edfbb510aad56fe4cc17e217002bf2e379f8cb25ccaf125d026e8e0dd480150c4ed4ed523","nonce":"848330bbf6e3d1aee0c048c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"de00c49ac239720cb927e45e036fc3c04c03e1beb80b3d447c4f6479d36319a2b7a71ec75619012cce2e521690","nonce":"848330bbf6e3d1aee0c048c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"2a5875f40e7e2ffd4700c004899b4fc8db57a4d15c5a1e56d9c9de5f8979ef4978849dc29dba0af3a0598e2134","nonce":"848330bbf6e3d1aee0c048c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"7f22d5cc9248ad0c87f7b5cb00bc1347837377b3786f4e743b63a98d0feb9d9531fa6f5326951fb423a4fa7c83","nonce":"848330bbf6e3d1aee0c048c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"1aac23078f5b3d43d1d5d30a68f7d735f91e49138e92283091b0c3dbb7203b5b792faaeed8a991c07d228061c1","nonce":"848330bbf6e3d1aee0c048c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"f682477c0daedbc02c81431aea5afae23c2978eb495ef122bffe8e0b3f51801a8b41ba769fbfc103f6698f4a82","nonce":"848330bbf6e3d1aee0c048c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"25d98d061ce81fd0b5ca982d529d9f98012cfb5958154983fd1f2c1df332866b9a09f33d7490a3744055c01759","nonce":"848330bbf6e3d1aee0c048d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"ff9edb6ce23c17b41f25af0c9deca5741444368fad9725b6c6db338163e2753014dd813b69a823c1c5fd0182c9","nonce":"848330bbf6e3d1aee0c048d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"9a3f3dd70ee57c7751693edbbfbdb36a80f766f6e8994a1edbf49b870ddf059df30d5322bb9f25e8079d27f15d","nonce":"848330bbf6e3d1aee0c048da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"6a48e2766722c1c42f987183c901ea939e4a292b43162aea233fc82252837b928b312e4e47fa6a4e1bb343dacd","nonce":"848330bbf6e3d1aee0c048db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"3bce8d47af5149c84ef6aad4193ccb2c5d7bf54fb5e2a27a47904ab6133b060d29a53087ca285d2330a0386403","nonce":"848330bbf6e3d1aee0c048dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"5c440eacde8e93a599d90d2ea94fd0e7321e419e663476d41c4f61ec2f9f947bcbe5e387211390d81073015594","nonce":"848330bbf6e3d1aee0c048dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"48159f31442f42623946fb1b41dd4cbedee0ed126c330111b6209aadb913e78f4649a719476cfba5381587068e","nonce":"848330bbf6e3d1aee0c048de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"37cf96d1a2be94d0d7449b4602f4a9518be08426601d814622512683a17f8f1f4fdcea3537becb5f4dcd2082e9","nonce":"848330bbf6e3d1aee0c048df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"4c6b80ed248896a111410e1815d38d39a6ab2d3e2688c1a6dffef0c2ef5db38ff2a4fec56ce0d8669ddb0aa463","nonce":"848330bbf6e3d1aee0c048d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"75dbdd4dc7fd61924e9db90c908423e28ef448fca91ef7d66099545448f9aa3d4d48d18512b2b0c203d6d21df2","nonce":"848330bbf6e3d1aee0c048d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"0924e0db6dc17dc0aaea7226259cbcdb178f1cbdc31adda2350e4839e8f4a0e92b984412ee6059b277638ae055","nonce":"848330bbf6e3d1aee0c048d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"58536527fe62fcc51ed7007cf63b0899fecb0f807ea9f4080cb1bff4ee564231db429c4425f39553e92062d715","nonce":"848330bbf6e3d1aee0c048d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"a7b7d12faeecab2ee466c5db46c73c15ab0416e2c794ae41c2426c5910ca319b89be3fcbba6c5f2e259e3b80bf","nonce":"848330bbf6e3d1aee0c048d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"8a80eebff0a8a5dd07ea2e7d314bac175bc77a79aabbdf418219dc03f7a991385926d724d6293c3f1e69f03e75","nonce":"848330bbf6e3d1aee0c048d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"e6db834187dbc89e87f4b71bb4c441f367df8172279f265a220754c0d0dcbcd66619f68b753ce8ee54188974b7","nonce":"848330bbf6e3d1aee0c048d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"9e4b09881dd2524bed4f548fa7b42155e314db1def5f8874904905fbc7c1b38b426e59f71d74d8bb5c17d18082","nonce":"848330bbf6e3d1aee0c048d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"87a0e73fcc02553b5d17c89bbc6ad9660ce590b29ea6436d54a3324c0f3617f560026f52925f16094fd93d294f","nonce":"848330bbf6e3d1aee0c048e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"bcf87600602e859f073cf3c8a18a2cd0efb9b2e184b32ec509621f94cb09e754e34a1684fbe5ab1e6a4bf1ab0b","nonce":"848330bbf6e3d1aee0c048e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"89ae0890467f65287b45ceba642eb90413916a32fc74ee2fe67e0320453741d189209374ce6668e2adc4518a56","nonce":"848330bbf6e3d1aee0c048ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"f37390fbf0e30b3cf366a169487d4b7b4a51c90211fa5ef28f62e55a448dfecf6f6c3f597243b4e3b7eea175d3","nonce":"848330bbf6e3d1aee0c048eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"8e67d909831e65530a4dd8b5f5fd669382ea5bbcf2c598fb47b81b45d486a3ee152867f5df4c62526d3e7cf784","nonce":"848330bbf6e3d1aee0c048ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"e4834189a2d8b126c2106dc74d9763cc5fb1143f67c5098976a5c26720e3d64f7a4908db0d0e02422e81a9cf05","nonce":"848330bbf6e3d1aee0c048ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"25709d1369241678fa3e01db2903a968f6f92d298738a3caa893a220fc616529a8e0abaa4a0f78c32511750109","nonce":"848330bbf6e3d1aee0c048ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"18378210a3e67a1f88907bfb74c4ef2af44df02fd4a7d4e06a01e46be99a32a0c4510fe0f0cd9829f8f45ac1dc","nonce":"848330bbf6e3d1aee0c048ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"f9f69008ffe049ebf069f52f6c982e493329aed47a19b1c04d2372fd01055b1ec1b62511b9844e7a4b70d536f8","nonce":"848330bbf6e3d1aee0c048e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"594024893020a07050286a22443a79b2bd4efee8e48a1574c1d6852c955f7d20d05e76d56af6de1c846039a737","nonce":"848330bbf6e3d1aee0c048e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"6fab5da58e488c59801160800cd68847b99de3e09e1d1e32e4e682c44c8a10c1f7fe54eaac4a8c8a0cfa1fe2dd","nonce":"848330bbf6e3d1aee0c048e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"b1ab8c6cc2bc709202499292c1c54ddfb411d340f815b5edbc80018598b9b5fd94caaca4d359415e77931305f9","nonce":"848330bbf6e3d1aee0c048e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"f48e9760e29da7c9ae1bf2eb43078403f55ace4bd53447d02df11ee6a148af28bf9409d0076209513a99001ff1","nonce":"848330bbf6e3d1aee0c048e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"194f334fbfa8382a7bb2b02a64bacedf65d48937d41b87eb6dc3e4d96389fed89f827ff1a6fbcd5f256bd99fab","nonce":"848330bbf6e3d1aee0c048e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"5c9b286494b51ce8102135bedbe5b7dbba7b9836e596a8b63a30529f642527cb9a92bf280c0eae263ab5942449","nonce":"848330bbf6e3d1aee0c048e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"da7cce676fe2c9497dd941381eec387d3e7a131bb56ecb23230e55ee39ed503b209d14e1946e2c20d5c45fb3d4","nonce":"848330bbf6e3d1aee0c048e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"18b6e5762484316719ccdc1c627f7b527c66c27d59bd5273e278726aa3f2c95f770a411d10397088e3410dfa91","nonce":"848330bbf6e3d1aee0c048f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"7243b9c0cee214d17c1bed52269bfbbbabff13a68a1c1fc4a154ba1a6042317e944debb852e3be3ec2fd41f2aa","nonce":"848330bbf6e3d1aee0c048f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"1deb27113049dcb23c24cdbe5baa084870720f4d8ac71f471973cc06648b10add74b4a4fc882b719567392aa79","nonce":"848330bbf6e3d1aee0c048fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"45960e2d525e4732ed7834e510d7c50fb9f2d9c2ba9011eb962632512105b7f70cdf3c7b019adb046e70f96502","nonce":"848330bbf6e3d1aee0c048fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"b29f2bb5df14165df1fa329c245ce75b337f27c669eda42ecb6cb1639d2074f3285f3e0e029291e321b8f35047","nonce":"848330bbf6e3d1aee0c048fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"ef28b64e3749fab79738f7ebf9f1d72d7be500327947264770076c2429def6cf66386b0f59d9aa73947f3ad24c","nonce":"848330bbf6e3d1aee0c048fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"d1479d054dc360cf26e02c08ded3fe26aa4e238859a62298feba9a54a0b45404e2373f9b7554d606bab873bf4e","nonce":"848330bbf6e3d1aee0c048fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"54a76e98bd0d7792605e3e6efa5d5a346aaf1c3b65c1413ebdeba859eae52adae2efc6063419adc80376f68094","nonce":"848330bbf6e3d1aee0c048ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"7ef40c319619c8429fe3b613052efd47c3ee1b299b28821dea47a7ba8b62431ec60c2024901e7b4b4722b1c569","nonce":"848330bbf6e3d1aee0c048f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"4189b4ac1be51801f67a97a43c2ec08d143085caacab674c8a1e140237a27b80a221ba10ca79e650e087184f21","nonce":"848330bbf6e3d1aee0c048f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"59b009a3af8d9b26263c4445fe43c1f275afa0535f7505870562ed8cb0d5056f4790ff751ab812143a94cd1a35","nonce":"848330bbf6e3d1aee0c048f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"e7c7c7f55f4a8befed0da51158664b5b81aaee87f748db13593995e9d48f754e0c99261df7be9998bfb3a52a9d","nonce":"848330bbf6e3d1aee0c048f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"b01e0bd67ff9f25091e4a2c5fe05518a1e256dcff13ed02bcdac9019a6879dd546d791eeea2598fd59e6d67925","nonce":"848330bbf6e3d1aee0c048f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"df3a04c319771a6030da23876a2c3312eadf4828f948eff974e169f37f9fc06a44c16690d4e10e05875149742e","nonce":"848330bbf6e3d1aee0c048f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"dd8da2980e8cead74c2be4180a27a367ab9ed06f2992e26f3c12268f73e1d28d3ae8fee2ad8e85f416fb124b4e","nonce":"848330bbf6e3d1aee0c048f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"81e94607ef53a226f5ebcd325b184f57a52b707b5cc321d65bf035502b366f6c3e167bc54c9ec01e1c3d3f2bc5","nonce":"848330bbf6e3d1aee0c048f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"3ba2924806de3b3ba39c74c1102112a3552eec51e54041f0bdb12a4a2fa1bc7d516e54cd360fcfe2c4c92c480d","nonce":"848330bbf6e3d1aee0c04808","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"0a785fe63ecfb772d7cd5a365d192c0de0cd18b52ac62c38af0c740f7492c03b207e623179eb4159a832ce2563","nonce":"848330bbf6e3d1aee0c04809","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"173fafed8a7c871a6f1a17d12774cf1fa6a357305ad546516ccf1784575600cca5122e8c02a9da175dc774434c","nonce":"848330bbf6e3d1aee0c0480a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"c808c3e2274361cb7dd2141285e87f4759675e35f998177e9960e8a04c54a7ac3f00ae4dddfb9b5f2d5c0e2a3c","nonce":"848330bbf6e3d1aee0c0480b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"29fc4903d304efe096c0254295b604310126c84f48011b5cd4d6027db6908efdda9fb0a336bbc56c88ca1eae06","nonce":"848330bbf6e3d1aee0c0480c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"b877acfd39b28b71415ee065dd1c357dce97a5a0716c0c1c554f3026794ee97fee990a64911df4428c85097527","nonce":"848330bbf6e3d1aee0c0480d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"10e07ddf4f974641f1dffbd36dbf1035c175d02ce39ee27b1cfb1c38554f4fd230c8ac26f7a7c6f4aa52dd018b","nonce":"848330bbf6e3d1aee0c0480e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"44e3c18c330b25fa269267580a127c5a8800dc34661b06d3719840e5caed6af24017a69ec6f1f48b6eaa687162","nonce":"848330bbf6e3d1aee0c0480f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"fd80e2b9c5843c8bf822a607ebbf8794b14de85f4a7f8904d6d4e7996cad2bba764830f9f55688801702d87387","nonce":"848330bbf6e3d1aee0c04800","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"4c0a517e39e41741d12592545214cb1ff14a33ad84fad1bff667b1be66437c64997c60a291cbf5c68b0a0f7b34","nonce":"848330bbf6e3d1aee0c04801","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"e1caf1d20a6330fe5798e1975b71c1f37f3d0ae07f11bf4be4394508032934f0de1ba81da8bf452058d176f61b","nonce":"848330bbf6e3d1aee0c04802","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"2861d66a36b9ae66357a35639054f50748e51279850718c719a355ebf96f99ecfa971d2dae13b0796728105b96","nonce":"848330bbf6e3d1aee0c04803","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"c4c02831e7bd2ffc9bb42ff932570d28c8905624cc44828b317ebcec381df0f8ad2c7cea8b6fc543ed6a98ba50","nonce":"848330bbf6e3d1aee0c04804","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"d6250f8bb3e7eaae571ae76056c5e0aa350c3678ac63039a4dfcdbead0264e19e99e0eea4e8c48fc6c40b0a74e","nonce":"848330bbf6e3d1aee0c04805","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"3ff19401409fcee05c7cc552c4619ab4d1c76c0a449d1b2e61cc863c1374b9d2916b9d6a2fc42051c3c0b5babc","nonce":"848330bbf6e3d1aee0c04806","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"cfb24c76da747ac2820532d069edb656318cf8911a4b221ec5f1d0b3caead3238a8be8e2a552057a5dd787ce93","nonce":"848330bbf6e3d1aee0c04807","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"8f4769d5e6189ddc7f71efb107911a444ef6dd0bc0c662e06b03e5ccf2f71c53dc51a517212e5df91b54b83c35","nonce":"848330bbf6e3d1aee0c04818","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"3927c86daad0dca36d48f9a1e69e65b477d47925e491fba9c2df43877346c13e1d61f2ea46ce7b5f9619aa15f8","nonce":"848330bbf6e3d1aee0c04819","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"4d0714cc10d3a514e7e1107e165468f6e18847556afbfa06d78592c4d68987d6295f3a28efed4779c386a24dac","nonce":"848330bbf6e3d1aee0c0481a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"98d12efde1437de16f78f68b291bc7cb39b4ccc67b0aaa39015449203a2fd373186351d9169e43e9e3b4300f57","nonce":"848330bbf6e3d1aee0c0481b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"fc53cd960e31c5852809fa68e17291326a213eaa82ffbdd45392a87f4533c3c5ad85b12ed6e1ed362050578b95","nonce":"848330bbf6e3d1aee0c0481c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"58ace1122473524bd41c8ce6eca01992e39817ba18a603241dd3efebe62f487cb1eaa508f3ede09a25ffed8383","nonce":"848330bbf6e3d1aee0c0481d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"368a29348c6c8344be6a06bec01c7b5f430a1277d8061cc36f36ed3c779ec181cc7f6c849904fb0c6b80de0c22","nonce":"848330bbf6e3d1aee0c0481e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"20da695f4774cfde9a84aed1a27d310c40fbb9233429d48cc55685ee33e57bb7429119dda4e2d9fa6aae07f1aa","nonce":"848330bbf6e3d1aee0c0481f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"da0a7cd8ecba30c7d35aa8f00d810a2e584d8d94e21d3119292d6a2a7dfecfed7b78d8be911e8c777091417998","nonce":"848330bbf6e3d1aee0c04810","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"23cb8284d5967669b2c30f2283217ec157a77f9cd97217f15dc0eb850af2d64b5f76f24424da1a205828444f32","nonce":"848330bbf6e3d1aee0c04811","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"57b4d6461580760c859142fbd14cea6cdd251e73a887c46e1e94a4739c6e891ca05205885aa30fc7972694132d","nonce":"848330bbf6e3d1aee0c04812","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"9ba5bedfcd5522117c2aa99de283673b2d208d8b16220de2d55503b670ad6fa615994afe4c296d4880e4bc5de2","nonce":"848330bbf6e3d1aee0c04813","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"eac5b00302bb4e59b7abc4232dfaa660061659b9570ef722207e45991059a6da1e38b5f8dfce751fe605ed071a","nonce":"848330bbf6e3d1aee0c04814","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"e4dd9cd741addb29379d6163b9323e1f8d4f814ce5bb9bf8770ebcdc944c1b76b6e3c90e1d2766844d1889811b","nonce":"848330bbf6e3d1aee0c04815","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"2b144ebdcc2eaa9823df00dbfe5cffaff9ac62575e9981ec02d221257122acb6cc716b20f619ff5d8bdd9acda8","nonce":"848330bbf6e3d1aee0c04816","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"c6ce2cddee28c488a9699ce9d340eb59c4f8d113f71550b48bae828238030720e9c7f8275e72d8d5431dc10e9d","nonce":"848330bbf6e3d1aee0c04817","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"6d43ebdf14696b16edf8d6997ba8a059c22e39f8ba3853b40a449a9f0e7c2db186c22e3e728b8278ecdd96ef7b","nonce":"848330bbf6e3d1aee0c04828","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"7c55666f38cbf83478d1eb4fb71b25922a3e807ace7de0d11f9c245cd1ba846678e3a9df0273d5328fcd6f1964","nonce":"848330bbf6e3d1aee0c04829","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"a0434cd8dab4c122baa5c446b39115c8b2fd1ad6f03718d3ad3c378f316d4edeb0d29dd3488cb6d1f026bcd7d4","nonce":"848330bbf6e3d1aee0c0482a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"2df75aca1bf3f51e17521e2a6e1e12da774af26415b20717dd25e9f2079e2284a71b72ff8f54dbc709e794c13c","nonce":"848330bbf6e3d1aee0c0482b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"2272d2e798df7dce7715a95bd65177123341f89f53fd82d9083cfeefdea7189c1b94ac036d5fda08a9553eb8be","nonce":"848330bbf6e3d1aee0c0482c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"59e3ce957ec63b863056685c10e86bfbd6acb9b72a4e0c17734ed19cb9ba14e217d62123e567ed1790ca75f9af","nonce":"848330bbf6e3d1aee0c0482d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"464993038729c091da14b1c40798ca3ab687cc3e8997a418fe0b40ed07ef90e4f6cc7d460ed19f608788141b88","nonce":"848330bbf6e3d1aee0c0482e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"dbbc9ff4e0a2a3e94490695341f12b7f93586fa3c61edf52779526702f37aaeaefbaa4a23d011ddcabee6ed5a6","nonce":"848330bbf6e3d1aee0c0482f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"9932090f9714467c5c997a092480f094fa9262e1899bd64a54102beaa19dbb8c25c554f977d062efb65693137c","nonce":"848330bbf6e3d1aee0c04820","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"5c97ce9f82df42fd19b38677ad440d42794ebc573107921ebfafe1e1cbbf2ab480a927c5a97c29b21e87067268","nonce":"848330bbf6e3d1aee0c04821","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"c8c264c6e1ad289b1fa20309fceb7548cace3c5004adbc8985f5d80364aac5d9597b50433ce4c7f560009a8144","nonce":"848330bbf6e3d1aee0c04822","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"3efc263553d317c8db6c7f247f962b893e47ebb352d8cddeabf764d5a979ef32ca2adacf5d50f641153c7c816b","nonce":"848330bbf6e3d1aee0c04823","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"72c5e93b776cc8b1c78654fc75e9f9d05330d4973d882d4ecf05cd209e4ae3d250cdfa68b3cb0881cecf58bb42","nonce":"848330bbf6e3d1aee0c04824","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"6748767394fd653081f833b2a36d64868933acda5f53b3242ef67e92a91953f65dee9b74ea3f9f845214482db0","nonce":"848330bbf6e3d1aee0c04825","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"b8a356de96f318434f083eaa0bcacd66c7ddd37bc785dd12373a98658ded50d66c9b72df643a4bd03f639d4745","nonce":"848330bbf6e3d1aee0c04826","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"dcc436d6d3a2cb9e6b62c03c3beb7a61f1ebfa6e937aab933d7da4b5dee2cd382b948175e421a57a7789299694","nonce":"848330bbf6e3d1aee0c04827","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"3b8aa861b354916e5c43113dc5120d202f1c9954acd98c1a5dd86406f53a697274d1c1fb1f959e48fe13afbea6","nonce":"848330bbf6e3d1aee0c04838","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"2e6466f04558cbf03c901fc1e2ab989d599e999c013dcd6b1d282276518e0dbb099a0c77c4cf958902d2cae328","nonce":"848330bbf6e3d1aee0c04839","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"6bf1e5b1ccd0ad3b16661eafb74d9ef0c568e4bd66dc8d1c26c58713bbd9be4d0d325c73e4297a5d0647ca128b","nonce":"848330bbf6e3d1aee0c0483a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"a481a63b319e95e51fee86ca9e4efed478a2c68d669fddaed35e5b5fd8bc2ab5d7a709486cd2206e9d6cb7cf84","nonce":"848330bbf6e3d1aee0c0483b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"8055c2ced38aa32bf56b0facd35684f8f0f713931e0949b7775d3ce140881744131de7506d9b507be7de9cfcaf","nonce":"848330bbf6e3d1aee0c0483c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"424e935d4953ead6ff3817acf58842cef1c0477619d3103f1cc7da5dc8494054ce3e8fb3083b0ebd652f44c5c9","nonce":"848330bbf6e3d1aee0c0483d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"d1b918457632b801c90a955e083c6f15c138942d1fb6953058ef1b5a369456dc93cf4290d328e2080dd2b613a4","nonce":"848330bbf6e3d1aee0c0483e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"344b1e39d316e38c617208a06987081f8fad52f0f44e4043ceee9419140a2923f7e3b868f4fe3b943429e76e87","nonce":"848330bbf6e3d1aee0c0483f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"e939dbb539a2e85386ec5a49d39f3d3d1e4f6820337924d48d2dc4c3caf8fab77ace12a1b145c326d4986febac","nonce":"848330bbf6e3d1aee0c04830","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"a35136c881101ad84592421d441626e501414b7a182476a780e570d3ec29e12c6122f6f49f94b0338ca30f926b","nonce":"848330bbf6e3d1aee0c04831","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"d7ff6458daee7798dad93ad1853924499741d0f05c88c7e83137d1489982adcd386afb14d555a56b4e3668b89f","nonce":"848330bbf6e3d1aee0c04832","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"4fdc58390f00bfeb0ee530e59fa16e0ed559d85374d7938295000c635c9f1d2a5fcf3c0d03df17bdba4233b408","nonce":"848330bbf6e3d1aee0c04833","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"16aae438774c2762662ecb0fc4a1d168bffdfb364b981845fe589332994af38ab1470f0b5be67937b74f2a20a2","nonce":"848330bbf6e3d1aee0c04834","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"26f735395c7128be44b706f14047158acf591a6b5bb2f4d0759c06d058f2d91ad08c88d9babdc8c8e858e5c7ee","nonce":"848330bbf6e3d1aee0c04835","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"7a81a49302bf22af97cb872edbde382534559f2185cf86eee8f5662d9655c8076f595692cf50047fb75e59e6e5","nonce":"848330bbf6e3d1aee0c04836","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"9df7b8b30e03e8db5056cf0e3425dbea68e3f022a8324e43817a6766f4e895a352952a0e42b3f9b0d0268887d7","nonce":"848330bbf6e3d1aee0c04837","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"5f8892ae3701ce116033d82b78c5a6ea61f3123147b6746c4fa0fed030c71b100edabd0b95675e7002bf385eff","nonce":"848330bbf6e3d1aee0c04848","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"0d037c2f7462df22865e4cecb6826d3f7cdb094cabb58cd24dcbc94fcabb7d7f967f2d269173c125efc04d52a7","nonce":"848330bbf6e3d1aee0c04849","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"0d52d5772f8769de8126b35319463429d5fb35a6d26c4438a5e14600c7483e9e9e13bdb06caa6928aa08f9aebf","nonce":"848330bbf6e3d1aee0c0484a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"2331abe3aeab390deff387f5e04a88ebb0da51aa310f852f584604b19d06cf85814cce6a81e2f5f26f6d913e37","nonce":"848330bbf6e3d1aee0c0484b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"7c12ed97bf1da932a7bbfa2824996f3c832576b881b5d80f873955c0c5a5bb99a2b54ef51441b100c730517e3e","nonce":"848330bbf6e3d1aee0c0484c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"f4693b65c3defcd44a95def42475b2e794aff69292df629a7acea9a555457acddd509391fe3456232e81cad69f","nonce":"848330bbf6e3d1aee0c0484d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"446a0c3c7b9a498929b143ad02ee1833d90bbd4767efafa5cadce9a6dbb28a9c1103f4ff2676f77bf98cb34430","nonce":"848330bbf6e3d1aee0c0484e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"219216a466398f579ba7942797c2bfd4f089ce52684457280e42e18f2a1d79525304af6fc401c463b3b93af6a3","nonce":"848330bbf6e3d1aee0c0484f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"e3c35bbe2603f69c6dd5e4dc054fc354f916f4a7f556f00e65f58fb8f947ec332d67530d74cd18f4dd2fb74108","nonce":"848330bbf6e3d1aee0c04840","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"eb6e5913c7197ed19f90f14c35308ef8d5d7a48764939b36abfc3686be13abfb6c18ad6eed297e6f6b5b3c13a6","nonce":"848330bbf6e3d1aee0c04841","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"702cc97e832d980d8cccbdd56b395134c320b5e16e2762febcc26cf04e9b622e0eddaed60010b13478fa50ff0b","nonce":"848330bbf6e3d1aee0c04842","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"dd88ae1a9a6a6267a8a14e6b5402d3b6a84de5f8d4fa1e2aeea722377f629287689eb599a81c472156f9ff5f5b","nonce":"848330bbf6e3d1aee0c04843","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"e05841f289d612e6f2690ef4886c5315feb616ee4905e17e765f171c0e79aa9950aded371d4c3062d0fbd68dbf","nonce":"848330bbf6e3d1aee0c04844","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"d45d6625d82e661e7cae6aa81162bbc395de7f4bb58adb0abb3a4f6073df940d4a6a90226a3586a793b9daa197","nonce":"848330bbf6e3d1aee0c04845","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"e1beb1a885b027bdd7ca9843b78c40151631dbcbcb6549e0fd0037109516acc2e2db2c74c53cee0a5649f5ec72","nonce":"848330bbf6e3d1aee0c04846","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"8d988b7c6f5cbffc7f32e01f03ad8efa2170392801b91cbb1158ce00558401a5e5331c1483bc443be9548fcdcc","nonce":"848330bbf6e3d1aee0c04847","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"330356acea51843cd87a6a2ccdd58682087b66230afb18949855dab2e3b130d12584c29050cefafe0a489704c7","nonce":"848330bbf6e3d1aee0c04858","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"4094c2703dce9bd7c1b801506177b6ca6c48b9346454e90bad13d9a5e969e635472ad7a44c8238caf7a4ededb4","nonce":"848330bbf6e3d1aee0c04859","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"483896ba1777221c8da905ea54855eba5c5ab41311f4a31b722b1df5e4987ab29b62fc75333d670eb82bea787a","nonce":"848330bbf6e3d1aee0c0485a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"5c059af771c6449617eac7ba4aa6cd0a955f9150d653f3291ff9e9a84d3dcd493ef79332b46e53fd42852c0857","nonce":"848330bbf6e3d1aee0c0485b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"1cb4a4da72c38862ad6778f3bce0b25d5f49bd66e355fadf6ffbb6cde0bf986b1190a3871cd363ba027c7d71b1","nonce":"848330bbf6e3d1aee0c0485c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"43138a0811a900ed22556925ac6761456d3ee1f43e87ef02b063fb4655f3a53835abecb225831a7d01bc141dbf","nonce":"848330bbf6e3d1aee0c0485d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"cb2f9225691a44bfc2df7ca5f22bd7221329d2070a70c466d5f3e6ea76afeed04d613e8a29926c10b8d1785fe6","nonce":"848330bbf6e3d1aee0c0485e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"4991b0cf3aaba729a76626f11e9beaaa439687ef60cfae7e86823c383abb81a16a8f21ed645a542bd9b7b46251","nonce":"848330bbf6e3d1aee0c0485f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"9b34765e31def76f685a53d3439c352f09244e814dd75c42f8535edec7bc68409bf857d856901f4127fee81d5e","nonce":"848330bbf6e3d1aee0c04850","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"b206a882c59cf6d2feeaf0e6357c32d9c290e611cc57fd46f7aa931f4328e4521d0e7e46951d0a7d393a716bd0","nonce":"848330bbf6e3d1aee0c04851","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"8c8c1d2f6a846d158f16b47d0251154b20415f0d86adaee1e63b3dd1e65c57abc4e7b52c40a5a6df16e433e66f","nonce":"848330bbf6e3d1aee0c04852","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"7d104c581db3c5b0e4b1135f0e69343b7d3bc5683bc8ef47837792c4a644eba6274af4ea19cb04df0dae3d6331","nonce":"848330bbf6e3d1aee0c04853","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"1233c6952b701c16bc1ace014e891403a7fb5b0d66f2faffb1b2d443d21fcc9629295f77e620acf1ea02ac587a","nonce":"848330bbf6e3d1aee0c04854","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"b38df32689e1994ff41b112ef0b6d3418c6c06e154853ee8b9c65c592870024ee4f1d02b3dad82edca7c647f3f","nonce":"848330bbf6e3d1aee0c04855","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"c81e14f35e1f55dc7aa9dbb934ab0056330e286a4f08104e4739dc6713138e2835ac77607727aa6ddc71d2bf5b","nonce":"848330bbf6e3d1aee0c04856","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"8dd364a6c947780c175e1233c3b040545d6240eedfb56dc0d4eee22e54b695a96af9039fa5300f1926836ebfeb","nonce":"848330bbf6e3d1aee0c04857","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"42b3540b5ed316df82c41f977a892f1854d9df385f76c0b8af5b020c0481f883ff079bb270bb373363aff6c272","nonce":"848330bbf6e3d1aee0c04868","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"f877e608ddf154093d7d3f20ae40fe15afc5ee7225607c1242e5c450afc91d1101cd38d7d54da5d5d52016cc09","nonce":"848330bbf6e3d1aee0c04869","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"2103ef3ba7367f10659521e92542cdbd859d357012822549ef6e620e665c0001298a7d4b1571755dcfa4451c0a","nonce":"848330bbf6e3d1aee0c0486a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"44a97c78f193d15f0129fe5394401968d309c807c855190cfe622e7c5c7c421d2071843c962e8d34f6a3fe42e7","nonce":"848330bbf6e3d1aee0c0486b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"faa426f9976b6b795ce0dcf22dcf08d459687ed1c41359782a7e345df8f25f4fcccae80cda3613fe33c35546e0","nonce":"848330bbf6e3d1aee0c0486c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"bcc0f0e97eb3b02c17c08102af14a47125809795c4e69cd6e9d4e2ca6ade975cc082249dffec4a51a60f7f79c1","nonce":"848330bbf6e3d1aee0c0486d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"b0c37e156d23b8f4b73ae3efbc5c7544c73018bd1fc42a7c0bc8b10eb647e7ef7f571faf0122f194410dd08153","nonce":"848330bbf6e3d1aee0c0486e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"6bd49fece91076ce788564fc7ac15c5b54c13463fe968ce5c25b2b0892e5dfa54b635bae41fc666a7488edc1db","nonce":"848330bbf6e3d1aee0c0486f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"2ea190e5eaa7c143227a31f420adceb57426673cc77fe275be9feb196262ad5630f1b23f72b004a6e28d5cf7b7","nonce":"848330bbf6e3d1aee0c04860","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"e389843073c682b2c2c030f5dc0b1cd99612e38b92750b41bb530eb2f205d56161ba2b051bba3a4bc470fb2b22","nonce":"848330bbf6e3d1aee0c04861","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"abc6e54adfb4d900762a8dda89d5a51ab38480e689602c868b6dfb1618d78078c88ffa433d0bdbbb1e882c93dc","nonce":"848330bbf6e3d1aee0c04862","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"d1c25ec5d5cd69ebd6a54ab44bf896cc04281036208ac7179455758272c8972559f567be98e90af50bbbed8766","nonce":"848330bbf6e3d1aee0c04863","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"2150b9a9a10948183d4de8d5e5c07e4d33109f13ac6ae99e52289e35330cc139d38876483b411c410b7adf97d7","nonce":"848330bbf6e3d1aee0c04864","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"877d3ffa47157cfbf6ab984d5a920137125045abbe7ec1cd370cb171c8645952cdab30230fc71329e67f96ac9e","nonce":"848330bbf6e3d1aee0c04865","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"aef316eb45a68e723e56f91c06d04bf7cb01c83d2e52374ae300033959c2e95d85c98a4514403043d9a40ca65d","nonce":"848330bbf6e3d1aee0c04866","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"f2488e58841cab3c3a376f5cf8a847efb04ba3e70d926aa2d54edcbec31273efd4fdafabf6fc0f938c87f385f5","nonce":"848330bbf6e3d1aee0c04867","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"195e10e54c6fc76db90538778d2275031f6da51408a681525ef272a12792b7c17b0bcecf0f1a600fd182ffa21f","nonce":"848330bbf6e3d1aee0c04878","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"d7c7ed9d8f6d9260a4f810bcb7179345864670bb8e7eee7ff35940323ce8aa66187eb3db0bca2f8365ba1ab67b","nonce":"848330bbf6e3d1aee0c04879","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"64432d32643f48cbe5d1a95248b6d6bddfd405f6264e938b92782b0cfd8f4fc890151908be8a58eb83164d8323","nonce":"848330bbf6e3d1aee0c0487a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"4f44f52afa7f490c097ccc39cffae785cc93dfe8bbfffffb1953901ccf2c2b144b699a4e88a6f842649b902f61","nonce":"848330bbf6e3d1aee0c0487b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"ec0c0554cf9a111c62246009cf217c1877968f44a2d3e81d19991a9fdbce66d82ee2132dc9d00032fdd2bb6d5c","nonce":"848330bbf6e3d1aee0c0487c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"c63bb1f47d554b79e0d9557e8e7bfa717bdcb814f8a534d55bcdfcdc05c6831830e3d7943b2856af40252ccb0a","nonce":"848330bbf6e3d1aee0c0487d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"480d881afcc8d8e875b8796cdc947c72e6edc1c28de59bab2aa8de3bc667e9b206e4c4b8a70dbc82453461c272","nonce":"848330bbf6e3d1aee0c0487e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"565c316d477b12e70f158ac33eb540a4895c0c76c9379d5c941879acdec5e3821433d47a3f3d143382c1f1036a","nonce":"848330bbf6e3d1aee0c0487f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"f060d11eb5fc0bf0aaea5ebf1561d65cb8183c67d04cf0b3e1f148ade895278cb9ac074ab6524973a9a12f6932","nonce":"848330bbf6e3d1aee0c04870","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"a343557aba961621e5804889fb12ad6306c9c1a5d5180cfa87878acd02c6dc801f961f5d413739e83d8020e207","nonce":"848330bbf6e3d1aee0c04871","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"0af2d7439d2af435554c73ed9d54790cc6a75566dbdb7370e60458848398d615ca258666ce4015732013e631db","nonce":"848330bbf6e3d1aee0c04872","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"de3485a68273195a911e56c39575968292d9ae25e8efdf5c6c2f6d403e91991892bdd0e33fcc15cb24fc1323f5","nonce":"848330bbf6e3d1aee0c04873","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"5e86828671b965fd06fe7106f99f710d2de60a5efda6a515fdcb5739d66d9d56d75d95a4a762526edd11454fc1","nonce":"848330bbf6e3d1aee0c04874","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"3d3c781b2fdf0937d952e89f6e5268db79354f5d6055fd4804ccc1b9dff8997375b33fb2f22504c45d9dc57975","nonce":"848330bbf6e3d1aee0c04875","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"6715f3916ff775640f391c196212258bbfd9694c4054eac8b3d1500da0282657c2741e2abed5ed13dcb7ccbfbe","nonce":"848330bbf6e3d1aee0c04876","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"8994444e46622e0a12d9b393c793855bca20d9d4193ac80af67fed3e9481db226639ca4d0e42363377a4370cb2","nonce":"848330bbf6e3d1aee0c04877","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"44cc42ed78bd30a4233ddab5d1298832dc9443d8e10daa95f21916fb88af5e9140a4e36c92404265f76b534471","nonce":"848330bbf6e3d1aee0c04988","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"8dafcb08e6fff9de47c01ccf0fb9e3858d0d087d7619b87333e5247f9a824121"},{"exporter_context":"00","L":32,"exported_value":"216c0d6e4da0387cbf0c440b5ed7ae12639defd43562d958e4452a5bd360f7b6"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"29ae3ff93205dcffead98946629504ee9f64388783739595fdc5e967de69016a"}]},{"mode":1,"kem_id":18,"kdf_id":1,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"8670f2441b4bd44c9c29f5c676b2f0c65e54efb6baa791eaa99a782cb9236cccb9b615210456e588fb453a95fef38de22508cec5d04e6603c3585486f2bf68e8d13e","ikmE":"940990be09a2d74d7f26303e661ffd6448968856c8290d3c558b7655731b772b9222e2f89ce49ec9f393be3d594d9f330a8f575fed21a7a4b5cbd8b57383c0aaa507","skRm":"01b7e0cb701b2383b4c948a3b74516da25ba903a29a87a6fec50c54cc17caa5c70d43ec95a72a816ff3ef4c1028bcab53fdd2423f23e9f19a0d937b1846960c19700","skEm":"0083fcd9ecfcbd930c12e25638cac4e9b396db4f7f7c5347f8139fb6c2ae750cede0617acf4f750e6f090e33769ace9b869b064580a9f9742c03f5827381f8b2a7f9","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"0401e0f83fe31900f26a536c48ed2c6fc2b3de99f9b0780bf088c942ebd4fca9a9e56a0a31e6e79276f87ecfa5f7dcb285dcc635a5d84b301d9e03ddc60dc09e4b6e6c018574bb0ab0b4bd9ce40669386266cc6e76e95bd23601136965e111dbf8cd9abbf6485e251ae43225dddab6ad4055312a50acfa547863ecef7c31889c3897b22bac","pkEm":"0401069cd6d34098d9bbf7e634bba61ffcfc420b77d79faa2980b0d26a258469ad72768b9d9b83e494c7cf4387bf2cf7e96bc196a9983f89053b46b1c431ca6f3cfb9f00ca588a0556c2c6c9ba3a6a09250d67db6389355d297752577712027084126e76e182f91b3d20d860797ef0e644bff77e57504dd50396bfb08da9d867ab0218f655","enc":"0401069cd6d34098d9bbf7e634bba61ffcfc420b77d79faa2980b0d26a258469ad72768b9d9b83e494c7cf4387bf2cf7e96bc196a9983f89053b46b1c431ca6f3cfb9f00ca588a0556c2c6c9ba3a6a09250d67db6389355d297752577712027084126e76e182f91b3d20d860797ef0e644bff77e57504dd50396bfb08da9d867ab0218f655","shared_secret":"1b0412347bc38ac220c2df149d3f17e14533bef01438e55765e9c4b7d2191fa02ae7387279b52a9c5f4864ec8c6aa97164c3987c76094ff836f01d5b11028758","key_schedule_context":"017975ec11c02e4c49238a6401423b9d3a4192da190ee5e64da5b6e06df3c5e82a424d5fd737aae133d36f3904a06750412f8aceccf0b84181f9bd44ed7735e65a","secret":"0db132f20be77080f7b08243eccf28d0110f3e748de91d2240363f80e3f7624d","key":"a0887182b399a28779c04e3c58ac47ee5a3ce676d0b76282c3f53c335e07f2f9","base_nonce":"93175a9d05332bc19f89e1c0","exporter_secret":"060f8e2719ed33b03f6d21ea764de43ccb59e9f4d9f14c75b47b2a3fa2329906","encryptions":[{"aad":"436f756e742d30","ciphertext":"965e3f2728f9b6aff37ab31552e06ff71fdf6431e632661df04c02fb1af0ec696c2b2dd05789a26a934d7b00c0","nonce":"93175a9d05332bc19f89e1c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"d4d22a3c93b73c3f71ea985cf6946e7ab939346eda87f90dc8f24d79734a815c21a34b18adec946000189e6ded","nonce":"93175a9d05332bc19f89e1c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"023616db54e68037dfa02aee94607f0c97c5e05328b9c1e26ae4a0afba69e15d83980591e2705a054e760d1d81","nonce":"93175a9d05332bc19f89e1c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"e5d06e01bb30f02510d9af154d1f85bb81fdf598bf924c81e1d4caf029e63e1510c0888907ade20a61e32c427c","nonce":"93175a9d05332bc19f89e1c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"204fd637cf4498a1eec78bfd053fc16fc211da409c0cd54fd4a049df40ab1f8b0c647afd03515c988c4024e9dc","nonce":"93175a9d05332bc19f89e1c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"161d8271f167616fb9a3af7e73431665b6b0a3b2efd98e38340bdef64afcbb9fa585ccede3ed6e0328e8d6016f","nonce":"93175a9d05332bc19f89e1c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"6cda188e3207923ca14d0d872493af6605ebdd9e2ac9f63c9ca76d4438ffc8d33f9eabfb1290fe951b217d2b0b","nonce":"93175a9d05332bc19f89e1c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"2f6ccc3a89900c779de604b7c9e03e0500705a58a69a2554aefa56e4b05f4dcee7999f1738d1aedf9bff7271be","nonce":"93175a9d05332bc19f89e1c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"b28eb08d291c34e61f80beca32d844c9d8e13f188d9a155d949e72b11006c2b2f1907ce19e3d5a1d5c7dde46f8","nonce":"93175a9d05332bc19f89e1c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"54afb2dd5727345f53f140c0dd1bfb984ae86851b780fedd97c64fafc4510a3647b71bd270c2b91d5bc62b2d87","nonce":"93175a9d05332bc19f89e1c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"f574cc7a265bb7694aebb70235a47c3ac1ba8b638e018878a2d4572faf706d7c4232e94cc0fe84b5241edfd1ec","nonce":"93175a9d05332bc19f89e1ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"53c197f276322ddca3f128b5b899acc7cca4fa09c2281210fc3c636c74889a2ced1e13c8c22e8888abff1dd6e5","nonce":"93175a9d05332bc19f89e1cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"2415aef6f7d77797938ad1c5f76350ed555564fbad72ace638db93126640a9d5f5656fa0f5abf7748089cfa0b0","nonce":"93175a9d05332bc19f89e1cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"88c2dbcd4e8eb9cdaafc166fa7dbc2b6509fe27c8afc95a608fd1ad6e05bce8957295513e2982228bd8525d41c","nonce":"93175a9d05332bc19f89e1cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"0af74af247191c67c8e03aadb49bd567b8dc94e6aabd10f75423f301db0d31cb74b6c0fb9078953278bc911d7f","nonce":"93175a9d05332bc19f89e1ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"728221715248e0534f098bdb71a48471c0ef4410f807f2f78a5d907218f74f7c34645fb0255e2352bf3392f5a5","nonce":"93175a9d05332bc19f89e1cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"8723f0060f836ed2ee7197b4228cd8b71704ff1768c91768b716a65f4387672daee6cc12b76b95497af2800a7a","nonce":"93175a9d05332bc19f89e1d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"ccacd11525aa8c5f2f9268910bcb2c1135a51afa00593f32ee7970503fdb9ad7e81826750ec28a08a790e7fa09","nonce":"93175a9d05332bc19f89e1d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"0d77d1d3373f4ccbf3e3af4967a0ee49b78ecd45733afb1aeef5e828878d8e4e138b19dd627f8430fc89b3738e","nonce":"93175a9d05332bc19f89e1d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"6129e57e45252050efa0057df11d7949b6bbe9a88219ee43f796b1473d906b3048d3d9830fb3e12e1f98b15eae","nonce":"93175a9d05332bc19f89e1d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"ae2e96097b498bb9d85d79288f342ca8de13a35a90ede96e72951c827beb5f26cbe67b67af243458eb052b86b1","nonce":"93175a9d05332bc19f89e1d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"82e334866150022e3f69ae3fdf3adcbaf06b19b818fbfa00f5644c60c1625830d88aed8595853fbae25fa3bda4","nonce":"93175a9d05332bc19f89e1d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"69639db88b751cae6fea6669e962a1cc41e5028db093bb55b81b48e793ba339975bd1b719ad2b8b7d6b26e1457","nonce":"93175a9d05332bc19f89e1d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"38afaa7e912287a24c51a2f7ab44749f109a4a82f18834366254ff6d284f488d6d41b405816032d7bea85650e9","nonce":"93175a9d05332bc19f89e1d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"fbbcd20fafad1b9417a81e07b26d40111630c220915bb623aca0eacfec62cd0425d276dd1a8384e9f99e7087e4","nonce":"93175a9d05332bc19f89e1d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"17a330bff59135e8506ec74d39942a7aee0653b3ffe364e7d3f79f6e4ca2d4459a692937b469a52b6bd6c1cc59","nonce":"93175a9d05332bc19f89e1d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"1a5ff8b103d9318ff99c008566f8f0747a59d61d0d0cf3a856f0963e6d5cb763d3557a8e2b194adb14ee0f2e05","nonce":"93175a9d05332bc19f89e1da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"568109cca430ee46a299d32a5f3266332c9c496be3b957ade058853850d6ddbd66c1b97ba2be6400be90dc370e","nonce":"93175a9d05332bc19f89e1db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"e453fbf9e80d401981bd6436366dfb2be405cf3e7be70f11232c9fd69aef11748a06ed07c0062bbad8744431d4","nonce":"93175a9d05332bc19f89e1dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"23db1e30a6c3fb5ac0cd96154f8450d66267e1dacf4b65bf636edf17478e133924ba5ec9b4c9e606b6cdeb5eaf","nonce":"93175a9d05332bc19f89e1dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"1de6f313a57503afd5a1d6d28e5d06acbf34c1f9ee220177fb353644174ff4aa0134afe1ef4ee18471b2ab9431","nonce":"93175a9d05332bc19f89e1de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"d56a90139ef75858616f9f1a9db2380146f0cd5f5b568a1b5bda20db0e3a28924f4ea2e901f7d90d3c4e2ac24c","nonce":"93175a9d05332bc19f89e1df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"2ad282b312d0c25a816971200ff9cfb447b8f5a4e2766598c304bf526acc569981b4ded90edbf9dc2b28b8c7a4","nonce":"93175a9d05332bc19f89e1e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"c4355ef5f2345d7e17c11bd99ff4caf6864d98ef2bd2f158e66d3f6408b0fbd57d316e0829c634064e951f35c6","nonce":"93175a9d05332bc19f89e1e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"9ecd8a67cc024addd799087bbef5c0e950e5cecfa2f6fbbb9e8f678930177e0d3f8e60b7c70c4caf4d4d2500a7","nonce":"93175a9d05332bc19f89e1e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"37a4d17e43dde1d4b902f427e1324db74e0ea357e82aecbbca6a80e8ca4c8d780a5291a5cc904cabe869772cdb","nonce":"93175a9d05332bc19f89e1e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"608c13ff4de4f1c299aed82364bb1ff6fe4dd15a4f61c7e77fa35890e1db194259d377c780e5b19e9d845d27ca","nonce":"93175a9d05332bc19f89e1e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"5e8f65ff53802fe25c052a5f420ba17d30448127807870caf0ab9ac7a40b9b0a1291de18e725c0f0ced2f5b3a4","nonce":"93175a9d05332bc19f89e1e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"72732cc3ed39b79426fac524df31356ec8b26aaa3728c4429e46759980ee6b77e4ce69e86a05d93e62b6eb96ee","nonce":"93175a9d05332bc19f89e1e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"0fe393621481ff320fd0c4e03dd4d3e6b4f8117865c0ce39c94760c610f3f60da531ea753f2622fa94d6c6e312","nonce":"93175a9d05332bc19f89e1e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"39601acd95a4c53008d33b310f3cffda23d911765857882e9c3a97054bafbaf79d4bda89be92666d4962435dfe","nonce":"93175a9d05332bc19f89e1e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"1a845ee2a94381e975c5520fabf6816eba4b7e135771562fbb414dd2c27c5d7bcd02c67fcf8cecc49215d8cf1d","nonce":"93175a9d05332bc19f89e1e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"32dcdb5f5b501089edae486b77faaa96a1dffae9e59916c59d03cc2a8d0972b3b7117bd754f53a5a6e7861e76f","nonce":"93175a9d05332bc19f89e1ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"5b3aca00d878f4d4054886879b5e2bef9a0d3b80fc01681f733edfc5a5e0efdd525e7405444b723b682487f099","nonce":"93175a9d05332bc19f89e1eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"83fab2bb7057569682fd4a2164310bec8ce993bcfa37486ccc38cb5ad691af5c0c1072c23864a3d071220d155f","nonce":"93175a9d05332bc19f89e1ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"d228548a248ff4af5977690d6327da8f4456a4bff545ef85014c88bf4c8a9accee50df1ae61a9b265bebd91442","nonce":"93175a9d05332bc19f89e1ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"16cced8a582f3aaddf55ca6476becde8f0d74378ecf92de0f19a63da89cb749f0dc38c957771347b7c34e688ab","nonce":"93175a9d05332bc19f89e1ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"05b3ed26dc0c58a745ca42491958de6ff0cc68cd71d4c0aebb5e8217ac0a4f404a63fdfd12411a02f5a562b8a1","nonce":"93175a9d05332bc19f89e1ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"219aaf22566871b2ff72c5bc4c0beec22146d2a6bad85e04dbb018357d1445a25610f04fb418ea058dc0c9fada","nonce":"93175a9d05332bc19f89e1f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"8749dd0ce60f51125a668b5726505dca3ab04ce7146f62776519dad2258aad991dedc2ccf99ef4ee99d1c4d7bf","nonce":"93175a9d05332bc19f89e1f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"3397c7711b755a821d7ec0bd172c9b31313645e9bf0d731e9da34b6f5c4d3cf8a3242b4065dee4d2a798032bf3","nonce":"93175a9d05332bc19f89e1f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"3d98801399c882e8f8c6e8e57a233ec84c14b13b175ce0e7ce624b708a086700ada82aa04f0bbac69d7ca4231d","nonce":"93175a9d05332bc19f89e1f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"b5e433d290065c1e98365e4fa0cd1735ae8b20a5a12ff6df2bc9cd806eb8b24477336b94ab7887ca99adb799e6","nonce":"93175a9d05332bc19f89e1f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"e3774acc431c1f4766a77b7b42523f6dbdb7bf0b1d0fcf8bf5f05cedcb7d5a96173bc2145c576316592ef94d62","nonce":"93175a9d05332bc19f89e1f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"8949b22be5b751932bea15e89f5b1ee32b39e56685e14ae0e37c7638921aed506de8ed2b35517c2433956e5477","nonce":"93175a9d05332bc19f89e1f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"4b52b48d1ef6d20e48806d632a93ec6d6ff0ee907341106c4794d806d151c1ffb4593857ff1bda2df3d2f36ee0","nonce":"93175a9d05332bc19f89e1f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"8501592b6751088e2490a2a006efca56d77e63fcecdb126a91dc4b0d028d9299fc7d131ad4fd37af9fd3fdd0d2","nonce":"93175a9d05332bc19f89e1f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"93d499f43f3c6d02fb275014e95b40121288ad077ad7d481530544e5f41151d3cd16ce562cf4b18104e08f88a5","nonce":"93175a9d05332bc19f89e1f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"753257f93c597db1b0c380711330d66d056bbf90f06794ab33be019c52d53d0661f62b41be22e6aab929abee4c","nonce":"93175a9d05332bc19f89e1fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"b8647187f51f01cb4a79083da48d25679f7dd156ed1f6443d9f80cec6ac7b3f3d4f2c72dc926e6462880972781","nonce":"93175a9d05332bc19f89e1fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"e79861b221f57125d1e98d3afe0be4a543e83e2ac6dd43cb89fba8db2ed073c8344c53e2cc81165980bd8693fb","nonce":"93175a9d05332bc19f89e1fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"99aa585fd08a0d80c73d3d440ba0f3722c75fa80edb54df1681ec82a6355308436271e56d63835a0bba3421bad","nonce":"93175a9d05332bc19f89e1fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"534a297095a25ee593c397ea8172e81ebd040499ad342f37bf43e5cd3d13f82e1e94c053b62025c97596f0aa24","nonce":"93175a9d05332bc19f89e1fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"c4813f2db4ad190c5be912b03b03bf1f11c52b857d0eb4213015f7204b93d86a00e16ba09bcd7744b093212d95","nonce":"93175a9d05332bc19f89e1ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"50d2c9fb52ce8b1dd2c57b498d6123010b4f8baca6e03fa65533bbe248858df20267e8fc9e1512f244eede1cbb","nonce":"93175a9d05332bc19f89e180","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"1bf1a67caba044ac7b940c268a72da1a07da57ac34bcbce14a37dfa99dee324fbdd10815957ea7c7f256adcbd8","nonce":"93175a9d05332bc19f89e181","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"bb615c502cd2d06353f99bd292c569f6eb9676327af5f5110331b7ac7f186e6291c90a0c998a049edb909b5100","nonce":"93175a9d05332bc19f89e182","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"1eb2570af11688493b0ca0bbbd727f6137f3b39cc2638dd19e5623f3cfc8cdf32ee418879b836271735eb8c38f","nonce":"93175a9d05332bc19f89e183","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"e5b166dc7a91adb5ebef3d0666cd37c83bdbef55b82246874f075d660b0986590b87ed9590cf05ebb2b4e88ce6","nonce":"93175a9d05332bc19f89e184","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"5da93d8bb775141618c6f71c384125f50667d9ba71f5197ef187272c2f8f20f0982267aa4d2998e0671ccacd63","nonce":"93175a9d05332bc19f89e185","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"ad2004129d07870635caf0174db64fdd9aa96f27bd59af70cbf4d44043cca01ff52af0000c9b3c04a2ca9392fd","nonce":"93175a9d05332bc19f89e186","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"0cc83fa697ca861e2ae0ac5f5f08021904b4573d0667ad65904b441e1a433a9e53f0a8df24acfa09d1125077e7","nonce":"93175a9d05332bc19f89e187","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"dec50d34b2a853f0f4c95f73816644353e7d4ff76f5f390bd6d628c4ef0f0609bf0c32e503a8b071e07f7f9fd8","nonce":"93175a9d05332bc19f89e188","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"3165903d5c68e725647b51bd90d8c0e8437f04438d99f96afb4a79aacd9ada1d2a3781cdb51ba3df4508f2fa8c","nonce":"93175a9d05332bc19f89e189","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"10f7fcee66e0c33d922c034bd670e6f0349f69116c3132b5a4fce244d9b4c6c0f5fca1df3a44bf8474f54e8430","nonce":"93175a9d05332bc19f89e18a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"900c885d22426d995218e4869459d2cee04c30bf6b619297c8c20df6bda3670a78eb4e10fd6da16ad4d4754021","nonce":"93175a9d05332bc19f89e18b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"97202af120144ddc0319705459788c8fc2c447afcfa295962138925a151fff9bb25453ff42740b3121449b7eba","nonce":"93175a9d05332bc19f89e18c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"4580f1c255d95e2b24f2e4e8d8a4b3d765cc2c873aadf1af783851a000365522a73691154e4e1beef78374f0b8","nonce":"93175a9d05332bc19f89e18d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"7c6cf409d37223ba09b7f5f10232d3459efbfdd5ddf5e05869e1f3d912e490d29169aacecc564fa93163b66b8a","nonce":"93175a9d05332bc19f89e18e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"9bb415f52ae416e002519df554d8171aa43d5b2e5d624705536733aa825e5fe27647453572348d3dd1e906a88b","nonce":"93175a9d05332bc19f89e18f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"1b5a8d4efdef161ceb35fd616442fb8420c22e628f78d8f04b53a55f101ec14834edf6d9beba058ca2b02a68fb","nonce":"93175a9d05332bc19f89e190","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"daa5c43a3c61537af799546b1812450a50a7e1bf61f7b29af909d096dd94632e8a81ee51ec7ace41602d3a41e0","nonce":"93175a9d05332bc19f89e191","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"7bca264a453a4142b3b2bb5da614dcd39fbdbd23de225a677f82f721df16eff845d9ae239111656f4771c3565d","nonce":"93175a9d05332bc19f89e192","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"6005e823ace34503d551b6176d8c94d484c602f3ff88333c620253fd313238535ec0af405c87fdcb074b268b29","nonce":"93175a9d05332bc19f89e193","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"8aa30ce25f8389384d03c42baa2e34281db61f54fa3f80a79d18064a310a08b8d2c84f4cfc6a79ea0f4c354b78","nonce":"93175a9d05332bc19f89e194","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"bf6d3678e4ec128875575029c398c16b13487b819f431d25228e76d7d2ce931242e12488745b5cf80283c8c510","nonce":"93175a9d05332bc19f89e195","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"ed5f38b2f862adad70c2952693984f8930f1daa60a8cf605f42cd20850fca8998985420f034649edf8c090fedb","nonce":"93175a9d05332bc19f89e196","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"86e73d75f3bf798ad88c7caeb48304818cba8802cda13866375809a847891c1bf7f4ec1f0d6dd24c1fa339bd21","nonce":"93175a9d05332bc19f89e197","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"7d84c8844ede582f4df48073d835fb1072855ee19ad6a61824fc118d956d0209783f35826fe8759c8b2161c59b","nonce":"93175a9d05332bc19f89e198","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"f00bc758be8d376d45e54b1f2e7296635a36789059e4b4403d739a55e7d833116efc58c8a614015fdc15f5c5b7","nonce":"93175a9d05332bc19f89e199","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"8bdf2ac2c2dcf91fb401962857e259751e3350464ee0fa50bfe0aa603013a6d3d6c5f840bf893a0ffbf90cd2f5","nonce":"93175a9d05332bc19f89e19a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"8ee841bf6cd58daf28ba0205cba6a0733cf2dd691120401b9f31f5b2e873dcdd078002f161ec9764999aac40d1","nonce":"93175a9d05332bc19f89e19b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"f30213088f7c5778a3b5cbeca4f215549358748571bfb8658bc266c0252e4cbb32e08a4dfc70c2ca0553ec38a2","nonce":"93175a9d05332bc19f89e19c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"9535cee89fb7784979fe2aea49029e43eefdee34beb19ee989a70f339f7e7624e0718ac69da2e1c393d730861b","nonce":"93175a9d05332bc19f89e19d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"fb2488eb56bac3b49de7098ab93265d544ff42166e2125177d286781b37141235208c91eca6c1c1a26fac3bd95","nonce":"93175a9d05332bc19f89e19e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"62d97a89f6047455d985ba93a8c1832774338b02f8a9b56fd69c15a00a0ae18cf0d0e0c63119802524db0638c7","nonce":"93175a9d05332bc19f89e19f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"57157d412a1a3a9d47b0c7973ac10d8de4bc3789cf1a838b4cc6ec5233bd1b50936961e252ce209cbd28b74a74","nonce":"93175a9d05332bc19f89e1a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"5ecaca1ef8208262485247c9dd3900162952fec89ad919c2154409d624c0e061c94f2426d9058a5225957e87c7","nonce":"93175a9d05332bc19f89e1a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"8b4d37be075f31bfcf2ccaf56ed00e25a089b27b29eef5da6fd49813280e5790ff04821d5469d31ec8b9d4e5c9","nonce":"93175a9d05332bc19f89e1a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"216782cc5a63910300b9cab0d423dd4b88c6e504a96c468f73f54405947fb04a9afb2d0f419ccd607cb76adbe7","nonce":"93175a9d05332bc19f89e1a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"0ea454f119bd14378c55866051d8173c79b96b7bb41557a22fd959c27d29f558b24fe4ee315823ffc6174a3b93","nonce":"93175a9d05332bc19f89e1a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"af25b61d95024c27a232f9b92d747d8cfa6a83af4e8d9559b126fd5f62fb731eecb5870d725225f4b8cd8b3d55","nonce":"93175a9d05332bc19f89e1a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"5aee8d3550ddfae634b55bf941f3278f1f1ce7d65bd9b0b1b9e13690c3f90f996345846a62cca441946eddc8d2","nonce":"93175a9d05332bc19f89e1a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"ad3b473d54b46575c03b4687e356daa6b43afd2d1501661444b6e4f72417450f82427773ceb579fd6bf525ed51","nonce":"93175a9d05332bc19f89e1a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"e9a2cd0dbad737aa0e1cfe4c04f0a56ab60d948691d30616fa9129a1ce8d2ed86f509adbd5ad87dc5294646911","nonce":"93175a9d05332bc19f89e1a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"22e5e34f0dd87874386248ba6657bd3ac958d33c39cff34a72816ba1338324b161cdb3d137aaea99e899493d36","nonce":"93175a9d05332bc19f89e1a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"0e3cb40ab6947bc808f742b4c0251c50bdfa07ea5e6765be76fac3fd6551c183171e74a0557de03bda6a188c40","nonce":"93175a9d05332bc19f89e1aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"850fe0c2b660e9be4f80a52fa5b43b22bb5c520a9bcd943ab7f66d720ba650b708f5d49feea3784d8080d01852","nonce":"93175a9d05332bc19f89e1ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"bdaa83f4b83b7ad2f715a5573768c7b37d2f53629afffd90046d1362b657b0c5a30a3d2bd0d1ec14930ee5611b","nonce":"93175a9d05332bc19f89e1ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"547c771c6f3257e498967cffffff13ee6aa55df12e8709d77227f490cf8c7e6cb32d80b5a5413282e8a53c9cd7","nonce":"93175a9d05332bc19f89e1ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"4952e751682918bd35bf5638a88128752f323c346e6064185afcdc02a5d7eeb209432ca69746cf1f231239fbb8","nonce":"93175a9d05332bc19f89e1ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"a508ea21c23dcd722803eb713fe57efd14b7dc9daf5c6b655577a9ca419a029dd26a8026f9c5b8ef6b4c706a22","nonce":"93175a9d05332bc19f89e1af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"17788e622d3b50d3f0eafc6ab824c0464254dbdaad5883dee28c9b0b25405c2335768812bcae97cfae5788a8f4","nonce":"93175a9d05332bc19f89e1b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"653aaa45f7c395136c89be1863a02a29569d54f714a572c97f67b9e4956b10c9895ad53cb06ecabcda49d509ba","nonce":"93175a9d05332bc19f89e1b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"a05fdafe5b476b4762076d8679649dbda820cd4e4c0c181bbe978a0e5ccdc9797292cfe9708d41f731ec164d57","nonce":"93175a9d05332bc19f89e1b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"a967dc725451f5141152ae7750b84117113f5c133b36dc765f914d053a774b1bda93e61f38d7ebf8577c7f6b0e","nonce":"93175a9d05332bc19f89e1b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"53172b409d85ddca6d8dac3cb3eaaabac562549a551f3330810d64003399ad18c74b8188a59dcc4f8b57eec3ae","nonce":"93175a9d05332bc19f89e1b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"849056930fff9cee8da7967d906345bd146db215c24b01bb54491db6a80a010d071f5cc5a72dac9539b3336f1e","nonce":"93175a9d05332bc19f89e1b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"43a235a1163efcac98a0742ee87c4331d94cba0c0282b21c0b46d8c2d0b0b04447cdef00ab8a04c4f56be2a35c","nonce":"93175a9d05332bc19f89e1b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"7e9293a22825fe96323ba51d166cf12b54de303a635d002bbcab8cdb7f8a25ee1f8d556411f15466f1d118bad3","nonce":"93175a9d05332bc19f89e1b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"a4f407599ea453e6205e151631fda8b494e9aaa3627154e759f341aa21567e07f9469a0b1a32c8571e222937fa","nonce":"93175a9d05332bc19f89e1b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"00dce37863581b97a57b12c48f493adc0533e5f89fbee7a9626338912f3e87a3bb9ba5990c2c64a9cd1444acfc","nonce":"93175a9d05332bc19f89e1b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"a4d793d09378f65105e5b76cfed6296721559826cdd179ec316a385efb184fa89f41a67cc6f5e404eb6b245f78","nonce":"93175a9d05332bc19f89e1ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"e33494dbf49bfdafc078ca6c8eb3cdf74591a4b9ccf5b9b9b7ee396a9916ce4fb0674475f858b8f918f79abfd8","nonce":"93175a9d05332bc19f89e1bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"604bd48f6939a2b03f3580d991dafb0d0eb5f3db505270538998adda6c982713213c51d3db525c60a8234c2617","nonce":"93175a9d05332bc19f89e1bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"6640bc5d4234f932fd90f658103794804d92081b4fbc1b689cdc8e0cfb1ffbb5b8f9eae452968c6cadf367445a","nonce":"93175a9d05332bc19f89e1bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"4fdd8b035c343ad330a809f90207c101647d1db77149389890206f5c91f2f7508d3878b7ad3e944b7704a7d378","nonce":"93175a9d05332bc19f89e1be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"dbfb7fdda7b980fdb102be46fef305a189e8b889ce43e6dbb77dd3ad616e822213f626e7b5578841c05a38e16f","nonce":"93175a9d05332bc19f89e1bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"8f7cb47b5b89c74caccf108a3228f75ec92688b80caaf23745612467d3c967824d7bcba7d19ceb38f6c0933487","nonce":"93175a9d05332bc19f89e140","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"91a63b59619ed1de31538c6457913d5181b4303849b39ac65ce8a3aef9ad420d0f99c9091b967775a3a828e983","nonce":"93175a9d05332bc19f89e141","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"f90c7b38e93f71bf813c5ce077afcfe40a902b2ab9f3041d59d846241cd29f77bc97dac759b179231d40d7ccb1","nonce":"93175a9d05332bc19f89e142","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"bc161be0cbb408a01240e5af68cd46ee28161d461786c8585cd7f6e0eb633bf39b01f64e2dc2a0f09e5d36ca8f","nonce":"93175a9d05332bc19f89e143","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"fcdeca91778e873fac3cab0ccbf1bd7e6f8b584da40d5a1a5c859a12b4cac9f3b90c84b62f1df279895f67164c","nonce":"93175a9d05332bc19f89e144","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"08c2b5c83118bba08af3bf130432034a56cd8fb6901e25f0ec30b203d195cab3bdb26e0ab86f2eaa9cbd40a100","nonce":"93175a9d05332bc19f89e145","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"04b61575e713f0debcc199468b466d3cd16a2250aacd61efa375c57da4635675a2a5e0e29d715b8e04b56e386c","nonce":"93175a9d05332bc19f89e146","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"19d674f483ffba5eef0a87f25d9f5dd5b34b97f214a9054cf27155607eeb7ac7812b12ca510198cace339496e1","nonce":"93175a9d05332bc19f89e147","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"60e362b7fd9a93bc9ad2e9026fb889c99186c1eb513e44a723496d7d82fc512f39f211c2affe678baffc07dcba","nonce":"93175a9d05332bc19f89e148","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"9110f13967424474fb5a07172985e53f5eb0e1b333e4a36c274af715f7f0faded1f3c5fd2c21c1707717c14e2f","nonce":"93175a9d05332bc19f89e149","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"2d8b49f796cfbcd168922f761feb74ee9c7f9ccb497af7cdbc13f732e245fa9dc1327f8edfc7376bb80e53e139","nonce":"93175a9d05332bc19f89e14a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"623d5c1c03975aa9650f717bfb66dc61e143061298da9dc50eae5c940b1a3038417644410c35ddc6402130fa26","nonce":"93175a9d05332bc19f89e14b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"d0eb961646854a57205077666eb179ca3aa86c0fdede094b380f96673499eb0d1ef61ff851b0fcff83ce4a1e34","nonce":"93175a9d05332bc19f89e14c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"32dc834b334c4c549dda33a0031a413aa40080f1d0532b88f65bea33f1f7c59b7b4179606de059c45ce073d0b2","nonce":"93175a9d05332bc19f89e14d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"64c28b3cc2e3f5539071fcd846d580d53c38e62df506f3fb50f296338357958066ac3993dd38be6d02d5c8cc86","nonce":"93175a9d05332bc19f89e14e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"d2c488f85e03d219448ed92dca2a0af2558ffa560bd627b3a73623bc7be763b029e0d78221510b99cea4fffade","nonce":"93175a9d05332bc19f89e14f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"14a5b6cbd3f2a0ed79b6ace77cb997331c9e83d1eade60e2dab5696f9014f28d8aa70d2c06c98a98bcfb4593c5","nonce":"93175a9d05332bc19f89e150","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"5bca756f682cad370cb5671bef4135130a507d05b9b91d9f91bc61656e868f4f7a5d3c4daa3b00e60ed0300306","nonce":"93175a9d05332bc19f89e151","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"833d85d0ab2f7136b3024f6aaf9e228b395d2c545906c0dd15af0014d8ca25c19388e24cd1ad159c9e2dbbb95e","nonce":"93175a9d05332bc19f89e152","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"2d4bdb81a549aa3891c8c15b945a1efa676f6a0490d4e9fda79baddb726a199d4c7a4ae2cb6880794eb6fd6c7c","nonce":"93175a9d05332bc19f89e153","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"d6cb445a063a59f17393daa25dbb5704249beefa3842a37fc65eee5f4c5a14b46091684045dbc585036dd3fc77","nonce":"93175a9d05332bc19f89e154","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"ee4ce328a84ea3b8db845968e3eff965afc5368a86866146fc9895c35234a180d131b22bb62f90d91ad5de5515","nonce":"93175a9d05332bc19f89e155","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"6a1328ff704348936a5f9d79bed642a297d1a781c1335638397d96f1cb619813fa486e91d17d9cb1b2f809b2cb","nonce":"93175a9d05332bc19f89e156","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"6a793f3dd28c7c02299d2d1eee60c75dd0c29c4d6a768bcdc2428a9f850345a0016f6a53f00bbafbb80e9195b0","nonce":"93175a9d05332bc19f89e157","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"73a7f8c3fa2a236a0468962646e34e72bf89d93374a1f6dfcfac3c5d5dbbf456f57b6a2026eb8c594f0c429156","nonce":"93175a9d05332bc19f89e158","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"3370ab6c1a231447d32a61fc93cb30c14034c3143ebbdc475b5d56a14e60fae97cb825ce3a091651713b60f11c","nonce":"93175a9d05332bc19f89e159","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"3360edeebeac42e4d54e9ed4828adff7c7d6a88a09429cfa6df8d9eab56b2f19a4cce53452426b73f147fff8d6","nonce":"93175a9d05332bc19f89e15a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"5eb0917f10411851939882f542d23ec7ff10806d535cdf98679fb022efa2fe9d8df4a7fd22cd0021568596ba7d","nonce":"93175a9d05332bc19f89e15b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"fa9f3355866973c2d5e017ba54444a2ef823ff7017fcfb588c60802449317103382bc49703f7a4794e5c029653","nonce":"93175a9d05332bc19f89e15c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"7361d1613d2247f9e568a23f81e7d23e65d269159ca9b7e30aca53a3662ec688db2ce559691ef18e48d30c42fa","nonce":"93175a9d05332bc19f89e15d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"86fd5118acbeb4d5b40dcd3b45f2a9ce00698d680f4e1dd8002afadc60f5d44c077cbdbc62bd08096ceb848aeb","nonce":"93175a9d05332bc19f89e15e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"881b9debc4ad6cdf9d3d38c661994516edb4690859959d3e7c467bb92ad514a1575498ae38bfeed65766180728","nonce":"93175a9d05332bc19f89e15f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"664db755dd20f3f717998ada87215b6abe086f58f41c2ba4d4f1545d7e7f3665ba20db81674f123225593ee48b","nonce":"93175a9d05332bc19f89e160","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"7f4a42a32391810db6615e92c35e74d3bffba64629576f54a49920f73d75d61038c36961e999776ef42d106cca","nonce":"93175a9d05332bc19f89e161","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"8c021ba5ead207dc9e841f0734e9a8ef90b0077cf3725e1360e4843b8cf86866097a78bc8334c19282800b4202","nonce":"93175a9d05332bc19f89e162","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"89cc555c2750671e36913ad2114f87b04be7ca2683aa7f10b2a87502862b041c92470d4b8e54c5b9315b543a19","nonce":"93175a9d05332bc19f89e163","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"24502b52a541dee8b52c03b8cfff86987f7e6c09df8d22f8d73a7344a59164c2edbe0d7b7897be3973a508957e","nonce":"93175a9d05332bc19f89e164","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"33536cd6e7492db0876d44b5a05572a38b2853bdb4041f2231cffeb74b48735dc52a83579f34c259d53869c91c","nonce":"93175a9d05332bc19f89e165","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"81912398a5e2cafbdce57cc1ee169792459741de33e88c97f965a31b071307b5e73db7eeb11907674c53d92050","nonce":"93175a9d05332bc19f89e166","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"b8034091cc05165571fca0156fd1f09ce9dc76e4aae4116dfbf923863e234b746028a18a9aefd8f4f30641f998","nonce":"93175a9d05332bc19f89e167","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"3b63ddc146e95ba3daa0d9e6b9f8a7ebc135908b7627a61fc62560d0375d50cbbb38170f276a556eb7152873a3","nonce":"93175a9d05332bc19f89e168","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"740fcba821a47fd9aaf9bcc1a5c8a367afeceeb6ad448f6ec126400d78d98bee64dae4f0ebd9a0d2ef23dc367a","nonce":"93175a9d05332bc19f89e169","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"8f76e907ce581976c98597b85e4536c4bcf85efea3bb0bbee48a6bf9edd2305d73baa874554aed201040cc45f5","nonce":"93175a9d05332bc19f89e16a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"10b461e8852fd24c5a6c3ada4831f9e624679e6703ab83f060fdbaf9113042c76dae68d1731ecb692f987270cd","nonce":"93175a9d05332bc19f89e16b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"ecdad7fe3ef8c34b5f15f57a727bfdc74cdc23828390052d17a90aaa85d09654d664f8336312dac6d836cf8785","nonce":"93175a9d05332bc19f89e16c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"84ef84eaa1052d95a37ecd1ea60d905a07d5af7f3c7c76ef7465244863ce6a194a16863a6e3f5db3230304d48e","nonce":"93175a9d05332bc19f89e16d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"07bdb764126d4d8e2994a406ad46080e9f32b7a65d8df46f544d888dff0cfc92e5b0cd1de6e67fe715e1087030","nonce":"93175a9d05332bc19f89e16e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"af9208fabf28e17b4805f0cdebbca1a28d935f541edf261acfaab06caf5b68131fd53c62d56126d1173a160270","nonce":"93175a9d05332bc19f89e16f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"c1e830188bf6ba815ec1be57ced9713a14ab3a0f4eded7fb25f729d6c581542da5d1b6c4892a62f43550e07f27","nonce":"93175a9d05332bc19f89e170","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"f43424d0b450b95d6975f6300df8fe3421da97ee3ab22ca2b56e449ed3222b88a9cf8b37496b7ff1ed57439051","nonce":"93175a9d05332bc19f89e171","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"e3376a22ca289fa77e53afcbe2eb934fe4b16251e7a2c62c19aa9ca73d4f623837d9bc363d2ab57af8741083b8","nonce":"93175a9d05332bc19f89e172","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"2bc291f5c071a36fefac4714b91af6b191c6b6f8fed8227a9d3fe7341ea38c64d6b786907857bcd76380600114","nonce":"93175a9d05332bc19f89e173","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"f325db58e510124835b5c6de7713cb895877e7b1408826c6ab70f074a667a99762bff23f087e25bcddbb165494","nonce":"93175a9d05332bc19f89e174","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"95401be59f6a5ba68d986efbfc16843cc7841b89f34b2a77d29d0c9c022be1709152402a4aec7dd330971a1892","nonce":"93175a9d05332bc19f89e175","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"eb8ba2ce58dcc2efe26f54008f557ea5dfdbfc44c3edc7ed7bf6067ac0d78693e70edd79952d6153c97da6af0f","nonce":"93175a9d05332bc19f89e176","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"c0fa914da3b9a35e2bfac50c326f146636c8f44bbd3d5c9512b5f56d8b60d8af427b987293e9b8fe80754d6e5b","nonce":"93175a9d05332bc19f89e177","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"5ce3027906e51cc3fed760d240c06d5d5346edc97b7312ae1fca59bfea2a82984b181f4dd845aa16efde8a0d4d","nonce":"93175a9d05332bc19f89e178","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"8b9d0ecd26642f2717d3b8d2911ef833fbc504e3d623ae32a0ed0a36aea3b8444eb54d215641a42bea483a300f","nonce":"93175a9d05332bc19f89e179","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"dbd9c3a82c4de60da00cb4810c14845954beb128d06ab2f837fce981844b2f10e8fac07ecb639957c9973365bb","nonce":"93175a9d05332bc19f89e17a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"b02028417e9814be4efbecb7b751991f36025a0e5bd54d8163cddc4dc9c7fcd72f1859c36f99c7854cdc7993b5","nonce":"93175a9d05332bc19f89e17b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"f87310221af2d05989d999e4654ebfef0bac9cbeed7c25a0a79837cc9d92a4667770cd798e39660d4f01e41a06","nonce":"93175a9d05332bc19f89e17c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"cc4890fffe0a84917521a09bd1f06357abadb1a7379f85dffead72c98a1338b553f8169121eb23bbfdb22ec576","nonce":"93175a9d05332bc19f89e17d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"21be820b680bb17dd2774f3e5bc71ec7792b13129484335435e65a91a0d5fe81a518d7630d369e3cd44e2a057a","nonce":"93175a9d05332bc19f89e17e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"33a03f7cfb9ea1b1c599160c1e902bed154e239ba70a345927fb53065415988ffee35af0a6b016645e8ca11fde","nonce":"93175a9d05332bc19f89e17f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"6f330f3daabd65cc6c4a048ace2ff817ab0d1360794f72f6dcf21081d4306a2fb25eedca4b6dd629c5768bc3d5","nonce":"93175a9d05332bc19f89e100","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"ddb899bae6c1d314bc5adc9b5cac1408660e65cb6b886182049c26fdd483ee7cf75d913737713b7df60b845589","nonce":"93175a9d05332bc19f89e101","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"4445f65278ce985b79b13c69f12710aa4bbd19e09b336509da83b58c4b650a6435fcf53ee0c59d5a133286d5c1","nonce":"93175a9d05332bc19f89e102","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"9b6fd77136f2ec6d2f7fb884b39357589e60ea80d16a63c748b6465b0ab9591de069598c9a42a8672c621ff5e5","nonce":"93175a9d05332bc19f89e103","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"f699b6dd1c92a0f4a7b8cb25ba69007275cf23136165c83205a7515ec43663258739df653c4d0d60c927a353d9","nonce":"93175a9d05332bc19f89e104","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"ff5ca4ba96d29895176e439b55ca5bc538cc40ead2e7de5e4c5a65ec7684d83a42765c49da91a820f40ebf9031","nonce":"93175a9d05332bc19f89e105","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"f1d9e4634056dd9f034a614f5b2e05236d9bf06f617af30513f6278ee50baf86b7647a7eb543de52bc43b5f0fd","nonce":"93175a9d05332bc19f89e106","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"d38b014f78b0d3138f57d45090744c3008b9c86b1aa59964fc96b0a47fb1db51f5c8a20609f05950594037e1f6","nonce":"93175a9d05332bc19f89e107","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"2dd469a7117fd102b02159e8cd6fca734efac6e5bf7bff89698416e74237cf621a02d9c584f08d7a3816037340","nonce":"93175a9d05332bc19f89e108","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"8c21bac4b885318fbc8c5d92915be12124fb753fead8bba6d0b90ec7700ba8b18a4d4bf1cf5a3a4f98ccd7e0e6","nonce":"93175a9d05332bc19f89e109","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"158100eb273bb2a03472c48f42b0f6120bf24f93e4c81e3520838dc6a2559d0e63c11c3db9c1d54b76b143556b","nonce":"93175a9d05332bc19f89e10a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"bbf07224b3fc134a6d6254447bcb1c561602228c47680a47aaacc9d0f37215973d12d9023e75930ce02d00b4bd","nonce":"93175a9d05332bc19f89e10b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"595bd66173d6e6a18a7dfd9cacdded9e9c504f0839fdfffe7b1c05834f59a3e4d8659eb801ed78fc4ad6b858c2","nonce":"93175a9d05332bc19f89e10c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"dd55b96c784ae96e0d2bef4c64fd0788558f2b074e33e703101011a1b9964db0522cac22c5fb641aeed49d7901","nonce":"93175a9d05332bc19f89e10d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"6e84843b630e56fab95dbe5cba73d32b534d84191310106cfbfba0b5c611a376a344dc558ccf1886eb941f2daf","nonce":"93175a9d05332bc19f89e10e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"b2a591a0f915cc46c399ed6444f9549cbca4ff3787aed89a2d179efaaef2531d1deef001a2a8840dfbbbe9ac09","nonce":"93175a9d05332bc19f89e10f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"2e32cf8d8eb036d01dcde1a7776eef2eb4bcc4b240036e704af1d45633c65044190e0a4262c426b81a160bab45","nonce":"93175a9d05332bc19f89e110","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"bf308ad7ab2043d8f7e0eea9d9d643a5fd02b4e19253810cc60f86538bd7e62d0a73072ae0c6528a54a5ae0de8","nonce":"93175a9d05332bc19f89e111","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"93a7bc56e2734fe05f50ee8efb4b61620d43e265b3cf78776291de8a17c0390e722028811dfe33f49202acc979","nonce":"93175a9d05332bc19f89e112","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"a6697b96bdba798a3c80b05dc7df54ee0442d4efde7c1b6d10b2e69381e3560c1e50608d8314df8d33608fb965","nonce":"93175a9d05332bc19f89e113","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"54a1fe24db149cd07663e984f3027d810a6192894f45dfa87fb573f743d8b95fd4cf5a59e667e1c5810db61cfd","nonce":"93175a9d05332bc19f89e114","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"99c482858073f73177b3ba90d5799349380a8d57b6b9085c2fff95769c737c6b1999fd87fe4791ad2c65a63311","nonce":"93175a9d05332bc19f89e115","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"9ff8e81ae828cb001fb7130e71ea33d8d253645b6c54be25ada4a88e8ffa35d0821b1af315015a57c232f59110","nonce":"93175a9d05332bc19f89e116","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"007b4ca7fff06c16262192bf179469e0751cf047ddc4ab547a5d433331af4e21aa226212768072961400f48fe6","nonce":"93175a9d05332bc19f89e117","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"f084b256d2da378de27356ef4393fb96de8c779c951457179043153bb72a99e80e78376307f18f8206354db648","nonce":"93175a9d05332bc19f89e118","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"1eeb77c0e7b7c6c37221269dd98056e283d7e34555a3f8d91c812d20770218fc154d21aaedd43b5027e23b2df4","nonce":"93175a9d05332bc19f89e119","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"072f14f2910a8e357935bb488f5591bcafde39bbad074fe80fea7b53687ce61a3343f158a7c3528ce9a1370557","nonce":"93175a9d05332bc19f89e11a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"8fdce317c12c701091fb524de715b67cd5312925871a482ea714e872ba12f56dd5bc802f3f3a3909613f0307da","nonce":"93175a9d05332bc19f89e11b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"3d5428a77a8149bc9f6b33909b5a0fbc41cda4638a48ec139cdde91d9e6cce69e29b960db5eea6eff6a08bf5fc","nonce":"93175a9d05332bc19f89e11c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"6f0f79e75341ebe5d4cce1cc0c45616edf21f6021f7a7c74bd3c150b52ab96f66bf97bf84fc9ac96f53a0243dc","nonce":"93175a9d05332bc19f89e11d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"f65a461dfb37ea7ae67e5095143f9a0a80b663da522c53a1178f056ed569094e1f81009c22bdad2d023f714ac5","nonce":"93175a9d05332bc19f89e11e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"07344b98a1c8556503656ea0d2b27ab72367e24421e4f88dc808779aed18afdd9cb3bac4455db3d1586dc76b8d","nonce":"93175a9d05332bc19f89e11f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"8bd692acc163d489c4df2e5fac2be2d7b8d7d9fb3188c547ef69bb3c0ff44e1737c45eeb2506035289d5750d9b","nonce":"93175a9d05332bc19f89e120","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"9998ae00fa17c057b9dfdc7bf2e72446ba88f7b548b1154b999da7ef0d26c2b189e8c22371a9c72d7a4ad14124","nonce":"93175a9d05332bc19f89e121","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"f7579d56e29a065b1b9128d1287803cff21c8e1292455bd6af3b0f3094810f18beb88a2691c1bea560f5502ebc","nonce":"93175a9d05332bc19f89e122","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"5bdeca1b8f67a83b3139a8c825755ebf5a9bb38d2dccefd12ed874a36a1d05341a168bbce4549d6ae6fa8368ec","nonce":"93175a9d05332bc19f89e123","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"79f921f8d4c6028efc4e084afb14cf473a5dafd2a2ecb61da718b8a6580ced841ae78c301a403a6863cd7eddf2","nonce":"93175a9d05332bc19f89e124","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"19386b9b73b27044f91ba1a6f5623bb069059d81807c1422c5f5294beabecffe6409cdd77ca73a02a1de86bc31","nonce":"93175a9d05332bc19f89e125","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"02843b2e5919814c1de7f76fcdb83b814a9dc71620e4ab919eb98084d2b02d457b8841ebbf24d4df73a9c2b454","nonce":"93175a9d05332bc19f89e126","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"8452af3df8f554797d4feb827907b8c31843e512381e2bf382fc307d689a86908d26b2ab644553f4a5415a4ff9","nonce":"93175a9d05332bc19f89e127","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"81330ec64717d7993e7953ccc0a79dd3efb4dfa35c8c8541bc9643ccca7c7a2c9bcde97a6699ae0f7e1a4ade75","nonce":"93175a9d05332bc19f89e128","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"46c8b7340e61552b69fc652e1996e71753ce2d76c7b3b9b9afc03fe55dc89e1d2df01b3f5b1e15623b1c6daecb","nonce":"93175a9d05332bc19f89e129","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"2b4b0cbaf9d2d5b5efa874b0643d8c98fdaef0451315b3cfe7c6cfba90fa1e7cc2dfb256eee68fdea013bb01e9","nonce":"93175a9d05332bc19f89e12a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"15a676bf4780a77ae3d7fdcb88784facaa74962485f6852b4d55b98e812a04114247ebe6fc6446fc911a2f0058","nonce":"93175a9d05332bc19f89e12b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"fbb4821ff1bc32c9aecb5c70e2b76faddeff8177dd29129a7d74d33e72486a6aa1ec695a824b0234c37abceb44","nonce":"93175a9d05332bc19f89e12c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"bf0f2f8fdcc00486bca214e35cb4402fcacbbfa039c4dc5e7bf3d4a430f3b14c99f69dfe9ed1523441237f3d2f","nonce":"93175a9d05332bc19f89e12d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"89c4af6101b76291fae1e6ec9a27c6d72038f8680f6e6750b5aba8aee3a7614ad11b94276510be9ecf6cf88cc4","nonce":"93175a9d05332bc19f89e12e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"f71a1931c20e8c9bb7b496027de3a23e25389a6acdcb6ec7ff9ae849f30cd0b697d085655c58cf2a3f4dc3b8e0","nonce":"93175a9d05332bc19f89e12f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"74f0d443397a1f3b2ef7357271e87e8148468c32a899eb9ad4b26273fc6f58df0a0988a29a6ab9ce9e56911079","nonce":"93175a9d05332bc19f89e130","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"161098a4ae1fbcbfe0ac35c310aeba7dd58fdecc09bc0b55a75b5a15f1e4a962847b544aa5ffdc9f3b12d012c3","nonce":"93175a9d05332bc19f89e131","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"97c4b8e4319e1b2667b923703646c1b55d064f89794c49faeec05bf4c33b72b0ca28624febc10235f04cff711a","nonce":"93175a9d05332bc19f89e132","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"1fd4dd3540105f38c204421296a226e9a0e24626382a097c226237ec4e60fa5197d0700554a2cd352b1eb95ad4","nonce":"93175a9d05332bc19f89e133","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"7607d9ec9229caeb593304a64d2a6de1f6727ad0b6813938282d19f5e225588fddff679fc6c0ee82f6e70ff088","nonce":"93175a9d05332bc19f89e134","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"83931b6769e3c37fe674e3bb1d70f8bdef48cad616e43c2823fde9ff72567062cfa3ac35e4083f35a1a3f5a25f","nonce":"93175a9d05332bc19f89e135","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"82b1ac16377bcb0d9a7cfb23fc837dd30b5adc60573525406f3075c860f0f7747e5f6bd0fc2c624954dbe7d196","nonce":"93175a9d05332bc19f89e136","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"008872dcada49d74558eaa16b6efe839bc0a774d447851318fc03e2cf730d411ee98c7d7c099a97ade745e337d","nonce":"93175a9d05332bc19f89e137","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"535215cf943c8da45a09a52d5d969ac6ccac409cdfd7f0df34bdd140820488cc4591d30cf86b9d77b4c8018e19","nonce":"93175a9d05332bc19f89e138","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"9f4bc40834682e17251782186b5165dcdc5cc3efa897754379f511a6c128c218702b4ea9e1d537c73c9a67ef72","nonce":"93175a9d05332bc19f89e139","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"6aca55de7868df3e2f6de6b3d493b41c00ae594ca8d74fb9a52d0f5617286499a613a4ed5714b49b8affec2526","nonce":"93175a9d05332bc19f89e13a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"c75bda098c82942a22e1f05de2660b260c6d2d6d9b496cd4e9a78564a1ca93a4d86370e8f053005e8cd9de20b9","nonce":"93175a9d05332bc19f89e13b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"bf91867074525526d9a6cd8c2b425f9b66f2c2464ef40972d916ccc2ad63d68edf0b3bf57ea69df2edbe39555b","nonce":"93175a9d05332bc19f89e13c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"f1a54ac9056964a24717c8c0b52b97f564742ea06587972f8093f382b908fc8274bc5bc843450f82389ddf315b","nonce":"93175a9d05332bc19f89e13d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"934db61501deb83a5f06e937728ca3e1370b0559ef3ea1bb7ed0a90d0a0c1d8d56a8fa925eb3b636f041d79dac","nonce":"93175a9d05332bc19f89e13e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"3628fc701d3d122c30eb43b4c07e81e216b9d6959f35eb15f758661f1e7188fcfe7114beb581c30aa01eae352e","nonce":"93175a9d05332bc19f89e13f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"7a27673321b6ea07c89db3c838624fa2ade072cd14de6e9c496923554e7c3ab427ba9ad206c4d5cb3020b30b59","nonce":"93175a9d05332bc19f89e0c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"d021085ec546512b464ef3bc4f67cf211365e92e03888ac0459d12cad3ba46bd"},{"exporter_context":"00","L":32,"exported_value":"ff5267b272d7bdf9fdec14136a56022374a6c3fcee3dcb28d71179427755b995"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"6cdcf8e90369ae99c5fbcd32f42603051d0ac615f25414a8a51a9a68315b25c3"}]},{"mode":2,"kem_id":18,"kdf_id":1,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"1688b129d15c3f323054d4f8b7fce5427e578ec04d596fa4a53a2429f71af8189c813f5f005cd806c13bdee7eb46f0497aa8b93ca0611d1cbb63fe284e3e07191d6c","ikmS":"f3728e485d599bd47af4558b65ce6c97f3d79200653902cdca3d17116af3b78e59946291a88dd90ba47a7f1250caf2dffe44aee92a8b5a9fd8a8660cfc1019f222c7","ikmE":"b0ee4c09e71487d5fc0945acc8fd0f16d3676810586a069074753f580ac62cc2dd905caf39014d6d2328da2c57da63f9511804c8ac2446aafbd496a055b78f34c5c2","skRm":"01983b7150798a0a8a77fe4100d77e6e3637a50010d6e2fadb69637b69b42a6f90fbc417be289ee406a48be9b97ae376a2fd01373815ac488de3e74c508715112c4c","skSm":"003aef973786767095362f62eb79caee601f403128747aece01e1e90ec20a575dd49dc723258d898cc2ab941b1d3cf0ab620d7f746bd507dda513a808aa0df32ab2a","skEm":"01df9b7c8adae968971df96b17eccf34fdca58bbb6cdd6cd52dfaada4f156c226044f39026af9874c38e22d5d5cd32c9b43a2cb9c7ad5ecfd7b449c862bceca13b8f","pkRm":"0400f0964244103623f767c53c5930c2575ca12c1bf6e19f73e05b02899450cde7b0b1bf90c2421b532bd0437d4ad321d8e9392d755e01de7562fd6ac73c162f580c3e002ab8d2f2fd2b67f9e562f9294aa3210ad5b0b107b243c0235e6f0f96755449280cbbde19f9e4affe6b38211bcd4c74b84686c76fca9349bd39746ee67a33f6f1bc","pkSm":"04002199e6b09d2ac3aff6bb621f03b9f1b8ddc797deed9c75a982e9faea1c0e68647da48b82d981d6cf6fdb38b7e9cf648e350549d88eadd3d066c1a15cdb276d34130134902a5a4f11096696ada52a5a5e100cced8341a07fde5fd23886fdeb13105600d74c5ea7a2a0f7fa4b8be84c75aa0dc49381a734fcb37293b864ffcceb12d1b53","pkEm":"04004bdf989f3c870610ad8e6f7764d30e0b377b7330d7217a5f84ab4f10687f8b80e665c35be863d522dee3de42f2b67d268cfd1ee0ab3f99219477027ed11804f7e20019be2d3fe27e3b724689dd73f66092ac7e668e562567b943ab64ae3ebc00c9f3414f357309fcf4c476ca13df9d19092b202edc5208fc9e8f0dae07868197dcdb80","enc":"04004bdf989f3c870610ad8e6f7764d30e0b377b7330d7217a5f84ab4f10687f8b80e665c35be863d522dee3de42f2b67d268cfd1ee0ab3f99219477027ed11804f7e20019be2d3fe27e3b724689dd73f66092ac7e668e562567b943ab64ae3ebc00c9f3414f357309fcf4c476ca13df9d19092b202edc5208fc9e8f0dae07868197dcdb80","shared_secret":"716fef32a9b2a22be82d8fcc969e3fcf84e747e50218b0abbaa5131fd1063b84adea80a69866939da0b7d4a5cf7622a18b364b1212d8982f11e5f002391f471f","key_schedule_context":"0275e4033f8435ab2e4351af456d3d0e48d88f048993b59a50ef846d88fcce0f81424d5fd737aae133d36f3904a06750412f8aceccf0b84181f9bd44ed7735e65a","secret":"970df0a1e1a5215823fa0fd6851e4ae0e0747c16adb19fcfdf52320629f7f6dc","key":"46124056419b123f512336acbea449417bd0e3685d2463a9f0987a03aef1daaf","base_nonce":"e1ec88c8b632734eb5443f11","exporter_secret":"c47456aba23e2c557c6da37d1d02a98e840949d84af50063656867d83dd378de","encryptions":[{"aad":"436f756e742d30","ciphertext":"661e17cbbb6d6472e903f5a132b43ff1fbe4e2108efef80812a6e2ac1bee0090f8d5ce074fcd9924e4f03b3247","nonce":"e1ec88c8b632734eb5443f11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"c77c908deacecd7bdf7691338885b95b4e61af543ef0ae08ca7ef46d0032df85426673d3b8e3ed8c4f4ff279a6","nonce":"e1ec88c8b632734eb5443f10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"42fe89a4dcc03883384761458a566687c65fb87afa9ec9a20a508033cb4864cae9ed1765ca0d10a5b12a86551b","nonce":"e1ec88c8b632734eb5443f13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"62d72bf32e79fc26dc5b31b34f197765451d3259baae4c5088e9434f9ca2d66af1efed31df190425be426842b5","nonce":"e1ec88c8b632734eb5443f12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"b418830608fe3e5aa2ccd7282b6c252747131483149726be8a1d34366ce4b1cc688659275314b4f19d3bef9efd","nonce":"e1ec88c8b632734eb5443f15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"731b347b649b3703daec82a88a1be6e1032a2af1cf44e92cfc091e6ef6ef71f96135b1fb5ad63911628e95d051","nonce":"e1ec88c8b632734eb5443f14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"8a6c73be392a9b368a131d2c91c60802edfd1c295dd01961c1cf3cf518adade0a729d5d447199b1f6012754d82","nonce":"e1ec88c8b632734eb5443f17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"4fba37e00acfce382e816d32041cbc665b1126cb245ac0c7e817054ef0fed8c66980f86a28e2ff99f8a7e50cbd","nonce":"e1ec88c8b632734eb5443f16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"d2d61ee92858c349dbff2a90c82679abf134b7899ccf5fe16e273422be8f7a90d10451130f998d8e58d1cfdcd5","nonce":"e1ec88c8b632734eb5443f19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"503e55d4b4c5166b08c6537dc0e1521b0b87b29af9cec02062a9bec208d6cc434c8b4870d63fe0cb51ae6504b8","nonce":"e1ec88c8b632734eb5443f18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"5161462a8b58a77395561755f21e98bc8c2cd9f317420165d1814c4cc3af70c9493f5fbcba5efd82980150dfd3","nonce":"e1ec88c8b632734eb5443f1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"c1e7a9677890d4b9823c8cea0bb8d5b615c60835a2b376503ae4b3b971d35066431389a2c62cd390a538d13a3e","nonce":"e1ec88c8b632734eb5443f1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"a2f4fb390de58b1eb06098982ee548229f70f54bb14e4c8ec5355f1db318b802c12dbf24142bab148a9e70f366","nonce":"e1ec88c8b632734eb5443f1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"c83ce82624e8a55011b8f3635c490c007fb735d04a60693a69bd1e2c1d5538a68edeb4e6708ba37fc925d03652","nonce":"e1ec88c8b632734eb5443f1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"ada625ac6eb9ded7ee2a0b10a39f37b49c3b0e90c57e4ce09d4d8e748ef2b44766516ed7a0ae77e8635a955812","nonce":"e1ec88c8b632734eb5443f1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"a690b8280eb5c25bf8ecb18347a8a8b6d88de47154045dc08bcfe2170c7c1233fe238a7866c78988f3c65a1c01","nonce":"e1ec88c8b632734eb5443f1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"2c96156e5b6a45ddf1ab780e7ac2cdf0839b6f18b056df2cc8290d31fd90a3082bb9107573dafafe2fd63da148","nonce":"e1ec88c8b632734eb5443f01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"7d7520abeb02ede2088f97fc0a15558a7110294b9ab8183c6673cb8940a3a8898618033aba9c368f8bcb9e50b6","nonce":"e1ec88c8b632734eb5443f00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"b84010c523fd7146bab5a3519f5630c891da1399cc39bd40debf41f8fdf6e305d45c6eda95d2fdbd876c72189d","nonce":"e1ec88c8b632734eb5443f03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"93f9385fcab2860e1dae6281cf78e0fc7cc534a357d091a99bc3b15cf7ebbd260aa0f2850dba9faf00457e596d","nonce":"e1ec88c8b632734eb5443f02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"806f51f7067c877fab4d33870c9024c2c64a7dadcd3f75e41bc7834129180d85c01e4d25e56597edf3a55872c5","nonce":"e1ec88c8b632734eb5443f05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"fd6805245dfa035abc3fc4e38f495b9a4d9279b7b4529b18e581f28b11584aa06a809398d84294ac1e0d776c2f","nonce":"e1ec88c8b632734eb5443f04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"ed35d6dd958f39a8a4e593a794deeb6b1762c31de209f6715e32bbbbbaf55f94d4db83d8ccf33fd63177a25c4d","nonce":"e1ec88c8b632734eb5443f07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"a1834e5367f950f88c05f92c0b31b3c0a420ce278376f71f3c2f33cf50fd718ccb80803cf98ac627c731f86b34","nonce":"e1ec88c8b632734eb5443f06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"784acdf39bd78d924e8b6f1e8ab13a23235c6765454eedde0d61aa6c062fdda73067114b890a3e4901881c0ea2","nonce":"e1ec88c8b632734eb5443f09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"56204ba095636ee150e052a941afa256ead401f5b0b7e4caf4e1019b42c55d9475c2f7d93e5867237887a92e74","nonce":"e1ec88c8b632734eb5443f08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"dfb7c49473f0f537db9c83c0bb464cfb55dbcc7503e7ba0312949a12e083f8d753b187e5da0b97182a277ee23c","nonce":"e1ec88c8b632734eb5443f0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"5dea15db528cbe7b6cea3438a334dca286b59caac29d098ec8c063b8cacaa50ff335a59cf2691775701e6e51e1","nonce":"e1ec88c8b632734eb5443f0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"f26d141ebd3bfee9f59cb29b5ef271685fb1ac5999f487320c168db4b16b2aad92aeff578edc16f8398142b6b8","nonce":"e1ec88c8b632734eb5443f0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"6dbdf7bf18da47e17252986673eb00881e8b04f78af5ed41f69ae552bd0f9c2e29599c4f0eb0f1b214c143dfe9","nonce":"e1ec88c8b632734eb5443f0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"26ad593d8f1f690d16219cd573d19361e6356eec1916e2dfd9ce8cb27731db9929fddfb1e76f918df576ba422c","nonce":"e1ec88c8b632734eb5443f0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"a171d03b96fcf4e10c265039b0e9c1c291b1f6ac0e566030a97e2bae6c1f92e893b0cc82ce4e27718eda9aa9c9","nonce":"e1ec88c8b632734eb5443f0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"443560f3c618215ecb1bdfe60be709856708cfe3256cda01b4344dc45f5a99fdc9ec3b76b27366d1f7428c071b","nonce":"e1ec88c8b632734eb5443f31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"15764ed032f8ee62c253ced84ebeb6a46ee6abcd2f55fe2ba1367093b13e09d177aff582054163b3d5cc5ffbbb","nonce":"e1ec88c8b632734eb5443f30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"281b0cf8bf6714146b1d97a2ff77cec826f92dfedfec80199db0c11bd632feb48e5eae75233b07e3bfe1172d83","nonce":"e1ec88c8b632734eb5443f33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"2c8854047284c362a2afbdc1ea6c02d7d4a3aa29071f327f3f8afb507b4dbe0436540d261f543996e5bc9b3dd9","nonce":"e1ec88c8b632734eb5443f32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"1d71409162dafc42d82e3af51a4abe34961351ac0b440a69731ddea43ed987b1183bf1ac281a8bbd11997fa749","nonce":"e1ec88c8b632734eb5443f35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"22ce66334f1217b91217145198b8a94593509888f9b46e65b68a24a0f1c628a1f4a9a6117d8a21958834253e12","nonce":"e1ec88c8b632734eb5443f34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"ce91f39459cbcbc1afe3c85ec19fe65c82becb9efa8543d6c7e25c81e243b8fab265b02889842507b664384ef4","nonce":"e1ec88c8b632734eb5443f37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"6ba0bbde6a41675b06dac058001bdd0a0ad8725a0c13a1890d0a0ff68071ca0eaf527256170fcd9a0d8c1f1676","nonce":"e1ec88c8b632734eb5443f36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"c7868c56bcdf28136eff291c892583d85abb65323c8538d394e4b59b3ccae63af18865633f8632f1123ed6862e","nonce":"e1ec88c8b632734eb5443f39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"b6b2ab9e2300a88b959f954273ac9b986af2cc4dacb3566959aad16d61556be14b5269b7bcca00293d1e8ddefc","nonce":"e1ec88c8b632734eb5443f38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"6dbecdfb57148a9687eaae0d04ecef837e6ffe94cb82df735ef98f95b586428667f3176432010d798e0fb082ed","nonce":"e1ec88c8b632734eb5443f3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"f3aabc93f73c771a3690a7a107dded6a49494dae9f8f76b97e8718028b38b86d0f4a243c400ee47077758f4721","nonce":"e1ec88c8b632734eb5443f3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"9acc5c82b7476b5f25825ebb7a232a753eb129658257fc2271ff66dd230b4b0b4a62c86f08f31836ed8d511e51","nonce":"e1ec88c8b632734eb5443f3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"a753c235604fe16d8711be7c28e7ee61b9c357d812cc7bc762931f87fa77702ce8cc50092615f4f00e35e66e18","nonce":"e1ec88c8b632734eb5443f3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"0c324b2feadf8b762f8ee3e011937cbf3cc58f0ef1fa23af4f8cbf190be9db7f0bc2b9378b7ed9eba4a2a41c46","nonce":"e1ec88c8b632734eb5443f3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"e1f26ee37cf4cd27bff82c199f1d07221779f85cf9a81a1328cfee815391414a26b0445d44e15d3c442b939c02","nonce":"e1ec88c8b632734eb5443f3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"e98add80a8395e6e6cbdee37c07912bab2c3a6fe01988386443db8a791c5a025f52cef09bcdbd9197a0e097e0a","nonce":"e1ec88c8b632734eb5443f21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"c6cf228f75e22e2edadf6fd33b982a1d4c27c01fecfe7176f63bd669aeeeb623638b9bd4671cc9e5bda9f1e4ad","nonce":"e1ec88c8b632734eb5443f20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"56b6d88a78d424c1f3b0bbb187d167b4ae12eb61698aec62d669b6a41787755195c4d0f177294d3c10b6f7108d","nonce":"e1ec88c8b632734eb5443f23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"b0901e0d81e90c4650403095213c29da8e32521bae84328b62b4e7848f2b3dd1dffe6816992d8892a9d5bb9f36","nonce":"e1ec88c8b632734eb5443f22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"e58c5f68049f003eca96bce8adb56d0992092785d0207d69b251fca2c16ba3171dc2346b5baecf0c54264429bd","nonce":"e1ec88c8b632734eb5443f25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"4d7ab039fa235cf369076fc342cba8b5a9dce3876f433af90516cb60e37330869a01d331a5fdca1deb3084b861","nonce":"e1ec88c8b632734eb5443f24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"d57542ca3b52eb214349f5193347a3541ee2f15b18fe4e1d923e840e68e9d1db589b07132998df73f0103bdf89","nonce":"e1ec88c8b632734eb5443f27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"0cf1ead7f8d4034879869177ae57721238828abb49f985e32bc82dfc0ea1d6f880524bb4c4eccd408438e4d6cc","nonce":"e1ec88c8b632734eb5443f26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"8d1f6ebffaf671a3494c88f26ca8c618fd22afce04c305863dc412190e31ffc57fc37940fee6fe735d774d3797","nonce":"e1ec88c8b632734eb5443f29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"b667b02ba96b79bb6e6dc6ddeff1f74c9839cd8c0669615120a156218f81770275a9e9e4326675f383e4ef6d51","nonce":"e1ec88c8b632734eb5443f28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"e8f1955fb96d08ccae9ef61aa1d37785090ffa856146b78a4706bcde14fe7d5f0530d6bbf1b6409f022b60e1b9","nonce":"e1ec88c8b632734eb5443f2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"6364f1d2c44261f231142f51a6ac24c595831bc8d3dce7126940bf6f3079c58ea7042f1e68fb52d3ee8c50ec58","nonce":"e1ec88c8b632734eb5443f2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"c6d22a2b974a46b2aa79de84ca74a39a4bdca14bf7cfe46d2e6b01bee283365d4e99de7ef686602bc35f1a1e04","nonce":"e1ec88c8b632734eb5443f2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"eb848482695a6e102cf805f1ce60e41cc79a9fdfef2f1b8348a8d32c7140409d4aa05e0eda42a70bcab15c6ea8","nonce":"e1ec88c8b632734eb5443f2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"bbc9f7bec23effd22bc581303468fa504e0afd1017272d4797dbb17c991fe2c3f7595b0fc24818332f0be52aa4","nonce":"e1ec88c8b632734eb5443f2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"cad7717c26255eee2c809564f0615047a196be12d1e48ea47577513d663186f3b058250d4f98491f4f97feeea3","nonce":"e1ec88c8b632734eb5443f2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"b91be14ba54659bc9e712ce2cb8b6a4b486df7b3066dbc3cea2a10ea9e62d8132d0a14b32da1bf9589434f6b25","nonce":"e1ec88c8b632734eb5443f51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"c02f8445aaf8a25190739bb4bffadf0384bc2fc9e60e679285561fe66426e38439531e0be9e0bf365c1e5d35e0","nonce":"e1ec88c8b632734eb5443f50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"6bb937f9ed06d3e1d1f2207014fca7c757b4cb653b1a23f072b6c023b9b79b885194952c188ea4c9a0d2c30211","nonce":"e1ec88c8b632734eb5443f53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"419c9d4c4d172ac4b52abb21a23d5fb266f4cb4e0fc7ee9657a849e498ad530e9919804ec26eadd3dc501a2a54","nonce":"e1ec88c8b632734eb5443f52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"6236c4e989a513e7c588ff2331f11e1492e4d011811ba3ae6c48d819e8b920cba5a44c5411d185b9e90f4e9d8c","nonce":"e1ec88c8b632734eb5443f55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"84bdc3dd4d5ae9fb8a461f7815f2a5b7b1786fcfbfd36b26c9efefefa650b6089b5e474c436d45412611519528","nonce":"e1ec88c8b632734eb5443f54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"85f7ca13b3ca97f2a6621ccbd007bed03b70fda776b9b6f6feb4600d9dc1d9116742594de6608619edb424255c","nonce":"e1ec88c8b632734eb5443f57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"8aa4cb200f3af7277e121fe8f3263a297a070ecd40d3cedf6dd44eed82e7c3908c8639461b1f43672679192a84","nonce":"e1ec88c8b632734eb5443f56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"d3a1f797cd189050b692c35c06a9fa0134acd4dae4c3b24e5fecafcdb3cb7e70f8c52e8fa2035bf6e232ccb984","nonce":"e1ec88c8b632734eb5443f59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"c99b606eac433f0bd700b06a89d770b9dbb7c2cabe7f025a81567ea2d1affc7df7656c420ac2e1672a9f2f856a","nonce":"e1ec88c8b632734eb5443f58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"73ab19848dafc71931e4274a25a8fae5368f6af5f97871ad8c979f15e922a08b2c42fcba5fdf73e67bbaf299e9","nonce":"e1ec88c8b632734eb5443f5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"c65986fcfacf79ed744545dfd4de75de1d316e2ccc5dcf86374b13a27f4e5d72ae56b3eeefe828d34711a3614b","nonce":"e1ec88c8b632734eb5443f5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"091f733d65c8d163bd9195f334ac38a12cde9f4965f575c4d9d6377b6390336d5bb35066dece9a680186c090fd","nonce":"e1ec88c8b632734eb5443f5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"92f161812da7e53db09a09d7bbff2eafcf889ff68680320984d19680fb3305928b4718d894474f76fb2ff1a064","nonce":"e1ec88c8b632734eb5443f5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"5f5817daf5b04cfa4333d7d70a9eb6fb1961c387eccb731f6449de21c9f4924b7dee9663d8bc68388a4ce389c9","nonce":"e1ec88c8b632734eb5443f5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"3385ce4766a79b2b61875ce4c8c213680e8864301c738857cf5d55bf2fd74bc9aa829a075e36794c961c712963","nonce":"e1ec88c8b632734eb5443f5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"efe142536dcecbe9ebc38d6e7c15ffcd6a4e48aed945a9416ff97c5d68568afbce44204d1e33d76a983a9b7ca6","nonce":"e1ec88c8b632734eb5443f41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"18d1fd64e83e49fa07e925f8d60a14002d227047f75ebc506c368c35f16f552b84412f9e9dfee024938bbc518d","nonce":"e1ec88c8b632734eb5443f40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"58ac5bc03d7236413dbef99d4b390e3864c7c0c2ed88fc6348d8425f35ea40ee7f0fb33cada6d600508b625a63","nonce":"e1ec88c8b632734eb5443f43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"fca80bd632c79aab7299eb8177de774ef0adfa036320d4a8d3ece15ecd9b251dbf2b85e7c24d39e586499743b3","nonce":"e1ec88c8b632734eb5443f42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"310ca4e589747445060da78182eafb667baa2236372672b2c42b19237ea7cbae398c96db014e88a8efab9a7bf4","nonce":"e1ec88c8b632734eb5443f45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"79e98f5a01dce25ca475f3a2bace9841bb8f3a171722e89d99836c1717c08b30d900a8fb0e8dda40b1e55c494a","nonce":"e1ec88c8b632734eb5443f44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"c0f7b69bd1d19709e84193ce2f4031b835ff611b8b0e5e612e2331094398c4faad2574908a5f5efde74ab3234e","nonce":"e1ec88c8b632734eb5443f47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"8251f3f3add01372950f9bb5a89312218e8a5f46af9f2894efb9c8ac45bad465f4a15baf22395477f19dfbd1ac","nonce":"e1ec88c8b632734eb5443f46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"92dbb524fc64337b235f1d64bcb650b1f04f5db0c08bf3f770fb02707862dd8d2de345f3aeb218b5959a7588af","nonce":"e1ec88c8b632734eb5443f49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"8cb34f0fd099866e1e13e38e35b98931f88e72dfec4378ab89f972059978df8ee2dff163401cbed2c90c7c3754","nonce":"e1ec88c8b632734eb5443f48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"78a9f8b01638bcc0954e1e81db6703aedd09b78eead5a4ac95769d48a8da20b35f7dc337eeada214a042c5c608","nonce":"e1ec88c8b632734eb5443f4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"0d88bc005d3c4a32488d953fa13b0ced7764987190e0a3a64345759e916347763c7edb289dbf43a30127466289","nonce":"e1ec88c8b632734eb5443f4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"9ad6c619819a47eff078df40ef4e913d72f358e1c0acb628a14a73265ebf28a19afaffb18fd881abf6d1d256c1","nonce":"e1ec88c8b632734eb5443f4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"f81c29feadcabb2ac9d47035ca2b252a06c1df7e2b282de33a76a562f34e6e1a59961a52d493509e296d5fd32d","nonce":"e1ec88c8b632734eb5443f4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"413efa47488b19f9b3cd5c1b7b34b58ac8b1432daefba65db295ab05f531ea214384ed0cb72f3075b61d969206","nonce":"e1ec88c8b632734eb5443f4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"baabba2b6dc6a3906c0b3c8e626ee64b78cc8ba05bc683a28d1c89c5765c3f3856d868809af44ed345eb7df2db","nonce":"e1ec88c8b632734eb5443f4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"9c5eccf3de416c4473abebf708bf3702c1c0cf229221cc3a88623688231ce749b03657718dd586b0a97acaedab","nonce":"e1ec88c8b632734eb5443f71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"349c0fb9187ef4f5faba7dfd72b1a350d9b0c77bd24e4c2eb65e5f6b3b43dd57b1c26f684838241da35c3f1890","nonce":"e1ec88c8b632734eb5443f70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"b4a6ac21d712f340671fb4f1661e172c302f6d6cbd6458b0380adfd9f94bd2c84124de1a0cc3d167d991aad575","nonce":"e1ec88c8b632734eb5443f73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"f192a57081209350d21f5f3c1eec5b7f9a6a977118c92c62b1d7c0fb0087c3c2c4763360be86a6a433f121ed01","nonce":"e1ec88c8b632734eb5443f72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"7f0c89bc4999202d4015cbda41a666aa54682903c66f14c322de2dcf0293d9dc017204dc784012b51a99521dba","nonce":"e1ec88c8b632734eb5443f75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"6e7692999417c7d03ecd04bc0dca334ca1dd77f8ac5a83d080052fa2115bb4bfd0b7252d43aa34675dbd8871c5","nonce":"e1ec88c8b632734eb5443f74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"d5b67c5aea13311e3c06abcb40b55335dc8280e25abf1f8944597b18584b40108a8509a84aac88ffe393f4a192","nonce":"e1ec88c8b632734eb5443f77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"d8292db91401217ec4c53a3b8e85b1f2dcb95ce88d3dcf10e397a4d488b000f84a9c439921698df70b9ef67c44","nonce":"e1ec88c8b632734eb5443f76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"ce6af3aaa97d86944d2b45082385f5a0b89c898c780aa8efc9948c933c8ab422057f075f80af2ed4e2e4570287","nonce":"e1ec88c8b632734eb5443f79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"a2fb813c9cb34df2ba4d280eb7cf864bd6494f16c733c763e179d4c9fbd5450c10f7fdb72b2ae6863e5774de15","nonce":"e1ec88c8b632734eb5443f78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"0547f2981699746d09fe10295f8ea9d208253c8bdcc9d5bfbc6fc2a6baf55164fdfba310e5d7f652718432d7db","nonce":"e1ec88c8b632734eb5443f7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"e1c35d0a763a5580cd5a7302cb07f7258521255e5eb30fb021f07c1b6c5ff513d6ffb1ec47e3df98ab3aa80efd","nonce":"e1ec88c8b632734eb5443f7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"a8aba251076a5d2f3dff747aea89fbef3f50ad6e24698365dcd2e61dd4fdfab08785181bdf0f0510a3e06d733f","nonce":"e1ec88c8b632734eb5443f7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"ef45240017e8f9cb9a76133ffd7f5d79f710a2da920068324bca61a5d33e26d5bcce14670adfc1a7d396d3bb53","nonce":"e1ec88c8b632734eb5443f7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"863fe833dc7210e0fc67265e2490e8a865d526ab2cd2f3a907bcde4da1dbd7e53b513e87984c4cc9cf51d772dc","nonce":"e1ec88c8b632734eb5443f7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"d5e4d3ed9299f901eabd048120cc91d9b73da70610cb260de1f98e7129b54b0dc5420cd77a67547edc703a97fd","nonce":"e1ec88c8b632734eb5443f7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"ef3ba154bcfdf1892a776d2bb34230673196189eb974b8c99c135af6362e96140b5dcff0a7a4df2831c5959ec7","nonce":"e1ec88c8b632734eb5443f61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"e4d4355ccb58fe13f7c32c4987700bac624f5d10fba0666a48de29158fb1babb4e71d6f9dc2f57d99b7dbd0431","nonce":"e1ec88c8b632734eb5443f60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"3e03fe57def8f2f3e27fb4962d21169e236f63f9b134b1c77b72c4733a8c58362f41d08e7c843537fbccb88a04","nonce":"e1ec88c8b632734eb5443f63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"d25e018b43a5027086039f7f4b5f2e4534d6c1aa3e0e77cde6859da6db58713780831a95282e6023aa9d4a0d47","nonce":"e1ec88c8b632734eb5443f62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"0b96f6da5c6882cb80f90c65627e5146d553ae0a4fa5b139c6746e817e1dcb2d2a08806ffe3b2fbae813bca0ed","nonce":"e1ec88c8b632734eb5443f65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"41f79d215be66958d2f1f7427aeaee245b9896484bd93eecbbfe41b196e917115e0b0c2d7efdd0dffcbfa90207","nonce":"e1ec88c8b632734eb5443f64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"98584ca0e0896e6a72199b9d71571fb202949d151696ac579cf44aa09197753817c378df2d29a6f665f52c71a2","nonce":"e1ec88c8b632734eb5443f67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"6b68fe6019fdd5e526fd19c97cdc6cb11c2dc68ffa1b68a95c59da3dcf43218bf9b08a2a15d0403deddbb6229b","nonce":"e1ec88c8b632734eb5443f66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"2d4e3cdd9d652ba1a2355607d65a89d27b1820abef930daebcb2c608721d0c7958017e458582ed1984f1f5a54a","nonce":"e1ec88c8b632734eb5443f69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"4268df15b78cbf0c3c9c2bfab0e9e0e93af6a4b4a4b5d026e90309630a285274fb14e6aaa74ac058a6db3148c1","nonce":"e1ec88c8b632734eb5443f68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"2bf8a41af775d6258f4312304ecec599e869f92ff843a21c88dc937dee53ac0ce02b517804e9ce606740029601","nonce":"e1ec88c8b632734eb5443f6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"7b62c603c9d68602fc90ad760e1fc15a628765ad7981dbe60f889d85a07099d0701a7584c146e7a87d2b11c362","nonce":"e1ec88c8b632734eb5443f6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"375c6d2683e85f5ffe75311426ec175166f167b566aa0d66c8b0143d8d6d80359c5ff555d0dbd65ad7cbd95c8a","nonce":"e1ec88c8b632734eb5443f6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"af0bd80bfe9a60fed193382a9d0802fe06a2894d135ba87e9262d1da264f76e7e7a9cd0fd5e448fe2fc4fba25b","nonce":"e1ec88c8b632734eb5443f6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"24e4bb61812173fa1dd9ba394864ca458e2d28f73cdf28524d1c6e7f6f75584d285a1fd7f4f0288e0599e5ff2a","nonce":"e1ec88c8b632734eb5443f6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"f7347d7316713b8a3a6e467e6a8fb7378eb8fc3736a729b2512cab37e8e6f8b43810654bb4f9124ee43f3967ce","nonce":"e1ec88c8b632734eb5443f6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"0c31d1e264137d9df61c0d18909c09af356f8884fa695c9301292e9c5a4e66eb5379b421193e4222b8a9eda276","nonce":"e1ec88c8b632734eb5443f91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"adb6bdeab1f7447ba0b5df31fc187f728b59ba0b754e035b8773359cfd0d5165d9334d58fee211b34bb603e841","nonce":"e1ec88c8b632734eb5443f90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"c00629d1e624c9d4f419f730b6184bf827d08f62e7d7feeb03af86f895a064c132e869a09ad01cef898d64b9e4","nonce":"e1ec88c8b632734eb5443f93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"f10f75e086374149592bc87089b3b6ffe87825a196aa64390d1c9095c66c7897737b4bf0048b5aded54573d3bc","nonce":"e1ec88c8b632734eb5443f92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"3baa088cfd6f1777cf0cddcde39fc76a2003f03b55627b3bd10db295b423c9d28fb0e3df0d1485600806ba6f29","nonce":"e1ec88c8b632734eb5443f95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"f34153b79d9c64fdac93e72923d93f688c674fa57a81fb454d421cb17629b08dc74564242f16f3fc7841da0c5f","nonce":"e1ec88c8b632734eb5443f94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"e031660780309e3ccdb77f477c7b015996529820b3b132358950a1887e3d4893189052dc111e19a93e02b4a521","nonce":"e1ec88c8b632734eb5443f97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"77b8b93cfe0c1f1724a067a9c1d61f8bf5b400e629ad2b3e50078245aead8b356d82120e60e5769f446b230230","nonce":"e1ec88c8b632734eb5443f96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"fbe95b0c1121913d94718a716bcaeab5d234e14320a11f141763bd3b874a3a56aa8530caa66c740fd0646f6e66","nonce":"e1ec88c8b632734eb5443f99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"abb44ce80a2edcbafad51a28adf280963084da515381d2924f83fa31ba117356d44435814910b67f62a919704e","nonce":"e1ec88c8b632734eb5443f98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"e3e73c3a1a2b21c7a05585041646afa0cf340ae17a1cff4a52b15c37cf6f0c52fb111a81ab5cf355c95ddaeb9a","nonce":"e1ec88c8b632734eb5443f9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"9f2e8dd140f8085c59bb42fc8ef3ff7e4ab4aedac02cb36212e3c23642ed4a8caaf0708690a935e2da45322aea","nonce":"e1ec88c8b632734eb5443f9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"ca7b83101cdb10dedf5aa8aba6e33a70a46d92d40dd1a2cacff004ff19237780eff711017a1ac297734f83a8fe","nonce":"e1ec88c8b632734eb5443f9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"d58f160c9b7ac84ddcd09563e9bf11fc395482d0b4c05bcdc388c7a0273d4fb9b49383decac971cb8e7172832b","nonce":"e1ec88c8b632734eb5443f9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"6dd3f5c32b514121c4767f376b144a83c8b334d7d4dae556d3e917d6e7c8204a98924b8f3ead5074d3c2c3884e","nonce":"e1ec88c8b632734eb5443f9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"1943e8ebee0c1f909e2fc99636e5c4bef049684c769800d30c86144bf69e1b3c10eb77335a3be3281bc05451c9","nonce":"e1ec88c8b632734eb5443f9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"72e42a8f24a4d9dfdc4c0809c5afbbc69d3915aeddb006c6f88a848b239a1e41430d19bad5f100438effb06007","nonce":"e1ec88c8b632734eb5443f81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"eb69db56d8014a5898e947a0b298596beba48ed5f54506efdecf0593bd0909f88ac055e103c4f8124ce6f8bd32","nonce":"e1ec88c8b632734eb5443f80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"70b476a0f9d2d81bab271b602eacfd2632df179f142d2628e49e1bad5ba6386944d6a509bad92f252de5f66d87","nonce":"e1ec88c8b632734eb5443f83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"93fac7372227d3c70fe0a43615f34b13e0d46c3b5dfa0ad6c38d99b5da4e1b540642715379f3e46e49954daf49","nonce":"e1ec88c8b632734eb5443f82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"8d57ff0ca47dff6a83ed2bd218d9fe1f874f9d9c9e7306c5bc18f7e5be0d89eff94bf8608a5bdfd3d63663821c","nonce":"e1ec88c8b632734eb5443f85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"b831b8ded12a7915faa81708807e90e8d3520b8981abb75f9cc11ff09242052bdd525e3e53d08b16e1794a3ae8","nonce":"e1ec88c8b632734eb5443f84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"b8304aeb06721c163e6d1b48b7df31ac153adb3d94812dfcd26b118343b1575e9b508a4671db7a2102d240fbdf","nonce":"e1ec88c8b632734eb5443f87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"c107d8c249f0e6e411323ff18e447775a965fbd5d00b7a49afb134eb13e150bb7b10a63d3b5a0b673561a69523","nonce":"e1ec88c8b632734eb5443f86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"d25b1c481884109fe6e878394df4db6180e837fcf8aa16abb5579873ce1c16e9861745b548f04c63f5d931c10e","nonce":"e1ec88c8b632734eb5443f89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"51623c14950eafc529d9bd5cfa2ef2209c1966c95a77354fff500784c9bdf31668d73efc750952430352da52b9","nonce":"e1ec88c8b632734eb5443f88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"3bd74c4b0a8035e8143e535bf2f4c41e5f77dec76fd181285fc1b34177135bbe2b24463fd25abbef4e3b9ff896","nonce":"e1ec88c8b632734eb5443f8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"d80fff2582848f391e834b507a43e557a280e04bfcf433fb81dc0692f7ad7a223899ae5c5f452d274f34fb9e4b","nonce":"e1ec88c8b632734eb5443f8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"37d1e3cb95c74192b3cd50b2b98cd1f56cdecaf90fb2bc48cd06b44335a99aceb15b9886d566e637aa44a58d45","nonce":"e1ec88c8b632734eb5443f8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"1f0396e7451ba9db1cf40ba686b263fb76b19352c014e18480d80018f2b120d0e4785b2397d28e371e90a68122","nonce":"e1ec88c8b632734eb5443f8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"9a346e517c433a5310d2d6336aa84c1067570d1c54147db1d8d7471283665e76368a67bf5a2940731cd5af99ad","nonce":"e1ec88c8b632734eb5443f8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"a7dc8f284b13aca062621696cb5c5bd4cc4b5db39678b6f81482b086c6dd1d99f87d4a5175299032bba22fcb6a","nonce":"e1ec88c8b632734eb5443f8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"0d6bddba48753c486e2fec3b11da4bc274cc22f84e6817c57184b5a478d555102cd004fb605121084cdc5022c2","nonce":"e1ec88c8b632734eb5443fb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"0f6e97d68f89c5508e69054f4596763f31c689fa5f3c1d6e62d655073e17e545322899b74526cbb01b1b80fdf6","nonce":"e1ec88c8b632734eb5443fb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"ebfd5d88d54803eafb2cb55663a6a981f27e1a21143b83db8c22862644b6a4943a0f0d47d36ce23ae6e48d168a","nonce":"e1ec88c8b632734eb5443fb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"28e5a9396882ea483ed561205fe369b3b9fb818a88dc437648938954411e2753f1848a595b934430e86844f7e5","nonce":"e1ec88c8b632734eb5443fb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"6ea9724001c46f23aebe892176079ab5966e2684e712af5edbdf930be1d2e1435a576b84c8533668283165b256","nonce":"e1ec88c8b632734eb5443fb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"c1e3b85714e9ce737373a97e6fc93a4f5030eecb70ed4377f869266dbd5b57155b272557187ddbd578661ec99d","nonce":"e1ec88c8b632734eb5443fb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"96f277eac7434e1b11993e14e14a25523226752fce429963de32b92e3596a921162e6969de666f8638609eab6c","nonce":"e1ec88c8b632734eb5443fb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"6958921135004eed4b856c4eb38fb9e199abc1853cb53fb0873dca8f0cb08b95be66a6148a082d526266969ce1","nonce":"e1ec88c8b632734eb5443fb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"d3cc22295b99cf4d70efd2add29eea612fb8ef66270cbc3fccfb1a09a0f69b9597211ece343e3ecba4612e0812","nonce":"e1ec88c8b632734eb5443fb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"66eecdeba2a9f4897b5eea143dae22e94706280427288f4ae97586d10610e64a2b3b128da1ce63e952a56350c7","nonce":"e1ec88c8b632734eb5443fb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"4c3c229ced4d15dc950a2730e90b72c97afe187c398723ed26f27785199f1425f3e394f865e020d5db349e186d","nonce":"e1ec88c8b632734eb5443fbb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"d1b56286bd896faecbffbe07d8b115892cf816edf2becfe3e106055311c4b690b1ab53c1ca24027d8e77c65416","nonce":"e1ec88c8b632734eb5443fba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"4c1d65f5989c773b3601b3f020f71e4c088325502c2c4a8aa7d740af355bfb85b7f35b2a88d9abdc0eb4f908e1","nonce":"e1ec88c8b632734eb5443fbd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"0907d52838a8b75ba40a201342f3c292b5a94ddacb1ca226af4c2a4329bb2e8d54dff0a9c53796edae9f51ffb9","nonce":"e1ec88c8b632734eb5443fbc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"5723f8f89affa0c1d8bf2499d61327e79e6530fcb62f723bd6bcad06f145b9926d7df5321b5e420f4a52349646","nonce":"e1ec88c8b632734eb5443fbf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"2eaed04bcc233ed83f55bd70cc4af90b3f390ce4185c9e3e32c23a636920817ad5ef18044fa51477b54cf539a6","nonce":"e1ec88c8b632734eb5443fbe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"df67bb65bd4c33766b79594235eb07bef21d2e566781b4c36cc477fd49caef176c7a74d00262e4e9ff83d01f12","nonce":"e1ec88c8b632734eb5443fa1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"6b443e285c4523ae828b1e054fbc6ea7fe16e5a627b24db9a5fe985a0fe09f7d285a2dc2b655a7b7156f36bfa4","nonce":"e1ec88c8b632734eb5443fa0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"65a2352acaab969e747d4d1bfe2dbf5a1abfa0039049f23d90701e0cd48ad04060ca134a10b62350cef94e04b0","nonce":"e1ec88c8b632734eb5443fa3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"85c60005099008640b3a843cbf5374f199f9e8d06c873280384c46a0d3c203ec26a06c2431833e07983ae91239","nonce":"e1ec88c8b632734eb5443fa2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"4fd7e3cf4b3e58baf3d5777b997be37b2d7600c94ed4360a1303345e0b74b822b77c52add45e5b9c9f4d50f235","nonce":"e1ec88c8b632734eb5443fa5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"fafebe25702f09538a1c4281fc2f9c80d98eadfcae55254683534e95c0e00280231eb1f5c225bf345d6a97d73a","nonce":"e1ec88c8b632734eb5443fa4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"daa1855f4c7cf5d11216ccddbc8ba6d98732b387939c758038fd3be44af5aa4abebc5fc09f1c290ce179ca3f4d","nonce":"e1ec88c8b632734eb5443fa7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"90a425566004eb2490bf25a886e05eafa0c83fb1586f8b6273a61472d631745929bd4a151162eb5c49d58ef056","nonce":"e1ec88c8b632734eb5443fa6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"cc9466edad9359d25b7b92e8fa04d10841be2d427a4edc3fc7759d04e7e862781beb45ab8ff2cb5c49f260030f","nonce":"e1ec88c8b632734eb5443fa9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"9849df387ec1506b806a6be4c3d095b32630b81da11feae39968f69c521244eef6ff090dfc4fd27acc01e00df8","nonce":"e1ec88c8b632734eb5443fa8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"7216aca484b45843bd82bd9fe0fd1be3aeecf45c5d8731163dbea2bcda7ef534c4118eebfd991c0b091ba0424c","nonce":"e1ec88c8b632734eb5443fab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"2aa4f0c2ed75d9c7e0c0553279d0840a2d8d23d0cdf53ad5a78a9d4291522929f00ae5ffe03247621d5fbc18be","nonce":"e1ec88c8b632734eb5443faa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"4ddd3762bd4abdeab8256f655f9638a560f24845c2932e0515557ced2f52bfa5c07c86a71208073953205a32ac","nonce":"e1ec88c8b632734eb5443fad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"9467ee02db7aa87a0e14400dca8c729b167b0d8ba45ec00d7752d0e383fdeb6390cb98a2fa7bdb1bcf02fc77e9","nonce":"e1ec88c8b632734eb5443fac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"4cd4723ecb4ddb51a93f90e784ed1a06bceebd0f51ec268aa0ee684e9bb3e9b79b0148da1a6c4fd7dc6e804c35","nonce":"e1ec88c8b632734eb5443faf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"5ac8859f801e7b3e5c1edeb1d89c25e4b1b51e3311b49472cf3a7473eebc63b7c91cf8ba9b77681e133e8bf4ec","nonce":"e1ec88c8b632734eb5443fae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"ad5ee6d988b164f96f726e502217dfb6cbca13960ac44a4db88da13e6853860cb2df2c7cfdedf3ee896765d0ee","nonce":"e1ec88c8b632734eb5443fd1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"86dede502721324f817ab62de4cbc32d87ea448c14aa89309b7a3d888dedaf29d49240e05c28e264c6e210f236","nonce":"e1ec88c8b632734eb5443fd0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"28be02d628482da2be07c50abeb8b22d9ad1b13ce8b428479eb96f276a39b23e697a6d68057e9f181f1e71af10","nonce":"e1ec88c8b632734eb5443fd3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"9fc5d5e56d07a7fa06c3f1e1a1ec3bf5902aab32458abc82c8822ec353eff867d9080fe1eba6a26d5eb45d55fa","nonce":"e1ec88c8b632734eb5443fd2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"fcf709aa0607b31b1da195a642a83dac09219608bed9d2dad039c44cb5ec710cd2f2909cf89cd9a1c9fc9b438a","nonce":"e1ec88c8b632734eb5443fd5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"49d13803044d2ca7208f78cf5a1b27a8e358defc49cc75bd06e167c5f04688b82c919a0ff728d75cfddf44792f","nonce":"e1ec88c8b632734eb5443fd4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"aa27c6d7cc4af4199eaf59c75d382c5a828c3aaf9bdd1246f7fd186e0ff21ac4153548a886834e27d4630c8a71","nonce":"e1ec88c8b632734eb5443fd7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"b4a5d36bd2f26d2cdc0cf9136e4d46310c550744dd1b86a0686bc66c4e18d0de842aa30ecbf74d9f97cdc1b656","nonce":"e1ec88c8b632734eb5443fd6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"a883a121c74f66afcf165efa3483e13714a754a01fc1a677805222a18d9f11a3f3e6c95ed2955f8251574c4327","nonce":"e1ec88c8b632734eb5443fd9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"9a1b14585a20727a5ab2d2681885fe377d7a009b64424d2fdf603034497a1af7879ca1925bc2698b638bd56ce8","nonce":"e1ec88c8b632734eb5443fd8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"5726a74d970d441c0b04264e681ff83a6efade2c6483e5fce666ed3e53f83a529c6a91e312b8b57c25ee8b8dc0","nonce":"e1ec88c8b632734eb5443fdb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"4c175d6c8ec9a81fe865c82dc7baee860556d9acfa8758a655751735454c8862df166053bb7226ab518291cf5d","nonce":"e1ec88c8b632734eb5443fda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"20f22fec0e662806d63d2aebb43d4570c2f5f9b862872d7d17f920ff91d589434a8d662ea6e2380f236272c8ad","nonce":"e1ec88c8b632734eb5443fdd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"d418f00f987af67c3815e7c56de3cb5f3cd5b30124d9ec470757d31a4d7a30aa1011c84d580939d7fb1da95233","nonce":"e1ec88c8b632734eb5443fdc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"b9631d3539dde257004947e9547fde176571977d3b5ffd04da6043dec2fda87b3338f7c9feec10023df096c582","nonce":"e1ec88c8b632734eb5443fdf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"e8e31285b02cc56dad5e1b4d537ff7a442c9bb97184550536632faec66108ef48132d0f109beddcdb3b8c21eb1","nonce":"e1ec88c8b632734eb5443fde","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"c20b58f780b6ed06ec283451c0c369aebf8595fb1725b4488e33c24af84c82c1b9b785cfc5b45f03d49660eafd","nonce":"e1ec88c8b632734eb5443fc1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"678b93a1cc122afd96e9b7f1f66bc636e2ab29690b2be8122b136e6cf8f70bc2129544428b30cc6b4009b4e831","nonce":"e1ec88c8b632734eb5443fc0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"57880a66ae8f413c2b17e5a8345b8fe8ece28810e3be1841e673d5227dc3deb248403188244bf30f10c9eeaec9","nonce":"e1ec88c8b632734eb5443fc3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"54fb155e866345bf52863f4fe8b9d7bef03e9ce90e57969b53ffe306e3c804e43f3ff0f78890508eae9b141588","nonce":"e1ec88c8b632734eb5443fc2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"66ab118fa7ca9d8bbecbe5c030918bf44c20807c7656e799ba93b15b0c95e5a51c81daecf788e11bd3fe1ab0fa","nonce":"e1ec88c8b632734eb5443fc5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"f9f0b0245ef3c5a213e5f602da2920c6a2183ead074b746fdc8fb8cb00a18d391d31d1615799fe6751e11ad70f","nonce":"e1ec88c8b632734eb5443fc4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"a81e5d38ed8347843c452f2fa2959938f7e3c702171d734897e1fabbf06562673a114286bf941bf3609d71d28f","nonce":"e1ec88c8b632734eb5443fc7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"06f9c5c9128434973cf4d194e9655e7243f87971fadad840457fe8cc86bee9a205996768f46edb2a936a3ca80b","nonce":"e1ec88c8b632734eb5443fc6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"0efdcd3de8679c3e6dc7720db0ed81f700121182bf4583dd3f670b0be840d25dd82064e15bd64f2de4938987aa","nonce":"e1ec88c8b632734eb5443fc9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"06e9fd4724e52271d8f07ffb6a20015cb159f6ad29ef97863cb1ed86984132ac20ed80dc603447b839eabe0391","nonce":"e1ec88c8b632734eb5443fc8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"6498f066553e01e1a7ccea4d3c010b63e47d5afd39490ad05feba25452e3882a023d6df5574afe4b3fa8b137b7","nonce":"e1ec88c8b632734eb5443fcb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"6d546a6f6d282d4c3e9a4ddb3075574f0166d22b8d19a145982a47a6c660d83d45b55045a807b42922992b4aa3","nonce":"e1ec88c8b632734eb5443fca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"ffa42cff1d87e8e7ddaead2a600bf565e8687252a419f9923841de6a3f471a935da4e9b9cf7b47a94317402956","nonce":"e1ec88c8b632734eb5443fcd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"029d74de47f38d6def98d7f0c8c1efdac7fdbcfe130b7c0548588b79dbf9373f5845f6f777c9cadcf0fe973322","nonce":"e1ec88c8b632734eb5443fcc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"3ae0e01b16a57af3a7a135d2f550bf36adf7ee0cc4eaedee773bc2fa8728110f9ea6372a2a75f2e58824381fba","nonce":"e1ec88c8b632734eb5443fcf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"47270908981cd6e61543197883231db0144cf8d6738e0fdbb1467516cc159afa7976537b420af1f6be64444ce6","nonce":"e1ec88c8b632734eb5443fce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"5f4e077993a372009250eb893c89cdd22e62dad6d5bde85985ad10bede47b28590bbac47cd617f16d1dcaeacc0","nonce":"e1ec88c8b632734eb5443ff1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"29cc36db4185709473b4e6cb07451e0e8a9752da0e0aac5765927c3b10727b4e1e5903a0489e8fd10dd6c1aaa5","nonce":"e1ec88c8b632734eb5443ff0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"7a917d26465f9fa553256a96b483f424252c02306d09dc3220367309d48057d62390dbf7dfc7ba246cc992f31c","nonce":"e1ec88c8b632734eb5443ff3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"ae2a57ce56668013dc419bb904de67bad1e5970e749d46b11421b4d16a2f3393f5a3617d09d1e19d373f835997","nonce":"e1ec88c8b632734eb5443ff2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"0a5dc3e8d91eeea9e3b05b3fafd158c95618e4a94b50207aad6675d51f54d29f609a273c604e36a0cb2f1c6e3b","nonce":"e1ec88c8b632734eb5443ff5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"919183a43b42c51b912fc5c86c62e2be5f13514dfb05e4c34d36073cc31c9d6e8a88e5f5760544ed63dbd4481c","nonce":"e1ec88c8b632734eb5443ff4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"85fc0a7281cc5fa6dbb606e3076f7bca3477f4b5ce039bf7fc6803c954d8195278cd30d2fb3e21d819d8b0b8ae","nonce":"e1ec88c8b632734eb5443ff7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"2151a8258c56433c8009490b86b995af9aa0cd5e94f38ded98677a95814ca5b7c7fb6da0ba29ae9a168ba30048","nonce":"e1ec88c8b632734eb5443ff6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"07ec6bb94252dabc5acd3dfdff8fa1686d08991548fa09dd6baac58cec7cf128403aedaf6891a5cc8fd95e97c2","nonce":"e1ec88c8b632734eb5443ff9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"4c2c23bf1b868eb8f0720eb8626338aa9dbc8d4935181642d709ecc4d57413f57d764ab2f5b83d5a52287eedc6","nonce":"e1ec88c8b632734eb5443ff8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"44ab8971c3ff2f91b4f4f33454151a710434ffcc721d6b3cf37ab02d2b13dfec3d3cbd541304d596d9799399a8","nonce":"e1ec88c8b632734eb5443ffb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"8cc670ffd5ebd6911a7774bac538ad6e21ed95beceab17ad775eee0a04d6428282e2eec3923a7d6d43100d3e1a","nonce":"e1ec88c8b632734eb5443ffa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"f841336ea34443ab7b8af112e6584e1d1f3893c6744b3070c91e6ba7692d7e8e7854cef02cca563d3d1b85a507","nonce":"e1ec88c8b632734eb5443ffd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"6a9e29f3ccae0962aea494213b6c8dddc3997da912dad5619cbe86fea30cf1aadb4b0040329ebc4d80a9ead549","nonce":"e1ec88c8b632734eb5443ffc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"9294fd108e47a33f830c9290d0a1b242b0aea9a12629608d904a9b6ae35e1186bbe0b80fa9bf80515f1492eb23","nonce":"e1ec88c8b632734eb5443fff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"b5221d8227563c3f457496217fe76eed3a5b85e419bc63384a99fb22bc1b0f9091197901b6764b9b795701a45f","nonce":"e1ec88c8b632734eb5443ffe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"0926d9418caa9779e8b4519ab7d97f6f60a6ea8180f88a178622aa77fe9d9655fed877a7345ebc42e037938b80","nonce":"e1ec88c8b632734eb5443fe1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"7a79f20b994cd8288ea71c009e18c88a7c7f8451673c4eee3eec02d681f0b87840520ab130d310a33898834754","nonce":"e1ec88c8b632734eb5443fe0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"7b15b93a359851b116239ac37abef9fc7303efdaf831f416cf025e197a05baa5cbfd179929677241d8bb1d9f21","nonce":"e1ec88c8b632734eb5443fe3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"47e29408e1d725583f4f742380cafe48099a68707a129e2bf8eea09d15eb5c9cee8b92ad6e30b77e57a3b3d52f","nonce":"e1ec88c8b632734eb5443fe2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"09ffa1c0425c66a52b144c452e62838e3c2937d4dd1332e90832e8e898375bedd5ed6335bbd806b22b74070d58","nonce":"e1ec88c8b632734eb5443fe5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"98be04fbb580c4bea8573f43b0bd5d5e39ec128ba68f23ccfda3104e79c25bbce3bb5c0c8b301a1e76ac04130a","nonce":"e1ec88c8b632734eb5443fe4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"602fec0e30ba6060979b2c733b77d785105376a62e68594124fe0ab1ddaac74f87b16b2a44b3f85902051ec6b4","nonce":"e1ec88c8b632734eb5443fe7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"71d2b3561a2cd6ee3388802222de447a8fff9e0a3a03312e392fcbc72521220e7446df62fd3c1972a7891f27ef","nonce":"e1ec88c8b632734eb5443fe6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"f5b8992492a8fd375e002805faa6e608ff33eb7b76f5aa30f3abbf70730975bd89b4ff4c32f15d276930accac5","nonce":"e1ec88c8b632734eb5443fe9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"3833dd2bc096570807885281e8727a36a2a414b3fc16957bcdb0faca9a9b17af00ab381c08fa32abff2ed7b3c9","nonce":"e1ec88c8b632734eb5443fe8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"25fc8b48596685a4b1d5b710aee6b39d10bd6b2783a3e866fe3d270ec71581820f22b3d4d6e750b424fbfb5135","nonce":"e1ec88c8b632734eb5443feb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"fcd38f824d4b7f78fee45f94e567d9a5ad5671bb29c31c6e0d4176e7462cb1218c849a0533dcaf83dc9c0e9849","nonce":"e1ec88c8b632734eb5443fea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"800a788bc3ae3819fbcdc8fbc708411c7a17ed6388746d531894d8f5fbc848c7e02e3c0024fe12f59ee18a4d8d","nonce":"e1ec88c8b632734eb5443fed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"a637f03665578dfe0d9e34a438bb47a36d891100a6f31504db070d72e7e0a13292b1c71a184134571ae4dfa98e","nonce":"e1ec88c8b632734eb5443fec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"cefc9061ca0430911aff2c885ce3d71aaccac31e28fa9b6c1dae7e01a3d7341ee42e399e5813ebb866411ecf3f","nonce":"e1ec88c8b632734eb5443fef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"a962bd0605bff64d5f5ce43218b4717b3ece4904645afd4aae5dc446695502745f3bb2d8b6a63a030018267435","nonce":"e1ec88c8b632734eb5443fee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"266e439bf6c298d45480975150ced04868ad872061a67b2ab59ed95618085bdda50f7f1b980684e622771db948","nonce":"e1ec88c8b632734eb5443e11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"2199a1a5e2fd399761e17a6e69affa25ba6a5fab99613b82495c22dd9f49fef8"},{"exporter_context":"00","L":32,"exported_value":"f0a8ad5cfda12a49c8d867cc31079571c05984795f9b39930175b6f73102b9e7"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"e107130a0ff5b97ad04c32e87023025ce41565cad696170171e305b6eb885627"}]},{"mode":3,"kem_id":18,"kdf_id":1,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"fd65b72f8439df7df0d08b0769d71c2c4b0735b3a81a99f77d93a2cf5aa0f3b240ca4a12b589303afaccfe2e34533dce48e281440b24a4249b495e5e932e166b126a","ikmS":"7d86deefe62f972860c612b17258fa612ce67f8ec24f99fd10a300f7c1c7985735b880bd6f1afb434ac543d12ccb4e1f40b7e23b725a33cf9d9a2377f1a022e744a2","ikmE":"494ff701ca8e1c401b032a51f57f0c051d121afe0a84f184976e52458ad2ed3bffbf02be7073fc46353a3f32d4a67357f9462e7204e7a3e54012fcbf95a25eaa15a9","skRm":"00ca09f965d693c96e5efbfed4b2d91e58f00b317f35e96061f7e2abebb4fa34f6d35c6910fe77315fc31310793d6ace95cde5174ea1d27b07cbf3c7e98f2913cdf0","skSm":"014269764777005d040ddf9ff121c608c6a4838227fbf4df0aa6ca241e3859ec40e314c88d430ddfb2d171d37e70bf35a94380d149029c62d57404d0b9747eab97b5","skEm":"002cdf0e34b0a73160ccb276254f00ec31499353f58bacd50f836af9e3c005b6f937cf12c7b96f45656db3a9c4e992b66d727dc0da0bd69a5760e848132db9d96619","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"040090e5a2fec9f6c1357f328e40564eedeeaa2b5126827bd3be1aee227631715bcd588bdb3170e463597674a571d3df45122a0792453caf30baa7ac3e9692e727bc860012e13fd7abae180706cf22cf2d916c27d01b3826b8f431815c50c7b5cb91172f756ce45d06b09fa42a17b3797deb4c6aa7af176dfcd55366645648cc9039912dcc","pkSm":"0401081224575503b33f08374fb66b6af1657f9e8dedfd2883723660b05b7646bc2e9a807f705402f65fac677c70f5a4739ecd97ec2a7c2acf872493de2b4e121a9d6300dd66dc6f824e1c1399b5eecf48f02954ad526f420ac3c62a7b0e597ca59f53b9105cee22a8c4db09e8f3e5f4d09aee0cac62b5fbf09001778712ad96c85f500692","pkEm":"0401d064a5c3a5a3310447e050ff32e9f1d71ca87eb40a97d44118e1d5136176fa21f7cccae96110f21911b3f3227b64aa9d1d3278cb0e2d966f3b056542ef59cb3ac4009932cbbd1879a1613371179e3113e5846856013ac08d8f5383e0120aaa07d98acc650bcc536e482dc58f0fbcdc7880b274ba9a1c2aaa43946d8ee475901045e168","enc":"0401d064a5c3a5a3310447e050ff32e9f1d71ca87eb40a97d44118e1d5136176fa21f7cccae96110f21911b3f3227b64aa9d1d3278cb0e2d966f3b056542ef59cb3ac4009932cbbd1879a1613371179e3113e5846856013ac08d8f5383e0120aaa07d98acc650bcc536e482dc58f0fbcdc7880b274ba9a1c2aaa43946d8ee475901045e168","shared_secret":"18f1c631c83ed9688c85c68c76dedd1f290e4ed8119cbd106c9874a30fe0394e977e73589ee3b362d82673da3b231e6571ad74ae019b6b2cb4fe01bd61af797c","key_schedule_context":"037975ec11c02e4c49238a6401423b9d3a4192da190ee5e64da5b6e06df3c5e82a424d5fd737aae133d36f3904a06750412f8aceccf0b84181f9bd44ed7735e65a","secret":"2b482fb201da1c603a9644ea7aac475315e1ce25e923a3b0827b8e0b2d49f104","key":"4c5214f03ea026b9d7c603dcb07a1da3aea50139b5b40e0015cffb78e80dcd89","base_nonce":"b137203a0529329d4ab920f0","exporter_secret":"861236db28a2e4b399ec17e043ca62748cdf459b3f39d27ccea4a5931f839213","encryptions":[{"aad":"436f756e742d30","ciphertext":"24fc8139a9d0335b70856ba8ebc8b0d3b702ab1eb429985bd10a8a7efe4621f97aa86ac67dbb1a40794c83ec60","nonce":"b137203a0529329d4ab920f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"13b689f764ff7e22e531596b169a366af73ce1ffb59cccbd07f2845a38264715b7b4eef5fddf518479be5ee5f5","nonce":"b137203a0529329d4ab920f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"3dbe02317c30cd3e0a73b0c7a90c64fe3685a0113022d2e78c08099306251de0848b531421b8b8a5e36f528d2f","nonce":"b137203a0529329d4ab920f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"91624e06ca9375c8dad994d6fab0deae0ff7c9bbc2c893f8b2369de0f5992e92305d1196b6929c704a768b3b57","nonce":"b137203a0529329d4ab920f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"01f14857d145fba4fdd95d566bd4d238b149c6ceb357251627198c9a9afc8eae44d86a5a09964a5618f051ae5c","nonce":"b137203a0529329d4ab920f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"0aa99f21349ed6b8ba61957162500e50e271ef1e9f029dd069a59a8383e798e301f9fe1ddd6f16ed809aab00cb","nonce":"b137203a0529329d4ab920f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"ace7aac5c882d7da06a875161501e5cd7a0375d6147f160f07d979f943861fd7f2ca91cbbe40dab852fe235a59","nonce":"b137203a0529329d4ab920f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"b0e923cf76feec30a7b831f9e6b7249f4ec4de445ab43a2fb922393b600fc281cbdbe0f9a27f549407dcf422a9","nonce":"b137203a0529329d4ab920f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"0be69fc2d49c5429a2527bc8774d8aa5102dd6e562c9dc9061448bb6527fe6283421e411a43fffbbe6de70b7a2","nonce":"b137203a0529329d4ab920f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"1a0a23959123a807807b77e37b6910b48bc76dddb3d8525b9cdc1506380f56b7981ec9533431a3b4b67b1c666b","nonce":"b137203a0529329d4ab920f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"52e80f16f160e3a9eb6780816e6b28f6ea191caa9bbaca06f2ab4421e465d2addc69a2404ce4b98bf5fc8c8d49","nonce":"b137203a0529329d4ab920fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"8771a143af4ff910a3eac21a0ee5418964c835e3f4c3bb6034a40bb7305c1e185df83a835ffc915f0506e2b040","nonce":"b137203a0529329d4ab920fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"60fd21f2cd97af895b0a95d77d5f56bd3d0852feca589b0a471e01a2d95b8ed590f0c28a1caba99f6c2d2cbed2","nonce":"b137203a0529329d4ab920fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"ef8a9ebb1913ceee57502a0d350b5f8fba1b4e36675a7ae4cf886549016d0a0d183894ed7d0b4fae9d9ff03db4","nonce":"b137203a0529329d4ab920fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"3a5a702f4ac0f19d6526df80b4975fa4546a5ca433a9062fe419b9e255b0bf04bd22e6beaebde89b425cc40ebb","nonce":"b137203a0529329d4ab920fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"7d994bac9a8906fdaf8e8ad999b8cc8a9c4f96f21c1b7a9c5538b62871fa63f11178de8f542c3567169ae65280","nonce":"b137203a0529329d4ab920ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"fd98b1e508048993288c662ba46edaad5aef93f2136da606f327db5f934924ada0a638bffee3660d374035fdf5","nonce":"b137203a0529329d4ab920e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"3ce857672ae44166ef8972b4610164882d61ff5c3f5638679ce4870d7183f76c5f1aaf2dbf32d99831f9e069eb","nonce":"b137203a0529329d4ab920e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"a8270b5280c8177377fb2c0f350a36afca0491f961e65c56e57540c69f0e87886b177da181e5b08639afcdd0d2","nonce":"b137203a0529329d4ab920e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"6beba82f59ff65ec70c1e605d1b9f0a7b8b73cf9f11d1197add0ce28e7c834b6965a24da9fa7c24c8998f620af","nonce":"b137203a0529329d4ab920e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"00335ca20ae7795ac5f8c9f0c064f4144e488872bfcf96b7aac2c860ec44b5f857c2aeb4b883e4e18179a87c2d","nonce":"b137203a0529329d4ab920e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"a0435564c10a53139a6bbb811401e4108654dc9ab961ab2f173d6737078c7591eb56d2c2687049231365fe1f07","nonce":"b137203a0529329d4ab920e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"ba8e6bdc3758533bf923a10f21567d7aabf75638ce127a58dd6f50453fb99ea946c2ddc3967ce19c84057a2f72","nonce":"b137203a0529329d4ab920e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"910cdaeda43042db927f49e5746b9d5141657f678af2f1f0db450d74da444ff2af19dae3cae3094c89775f71d1","nonce":"b137203a0529329d4ab920e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"454311dc092ff08b188b04ae32bacd9d7cba346a2e173514acf9e7ee3fcd738679ff0901d29ae5167aed6e2316","nonce":"b137203a0529329d4ab920e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"0f631d142559f840aecb5eead6df130e80235a9dd315fcfded6bba187f35bbf906307d01125767344ac4848f69","nonce":"b137203a0529329d4ab920e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"53ad0bff9be38b81d66cf33af08b4d4f0a4308eec59c40e21f4604135a77bfa07a558ecd25d80e55f328a12a5a","nonce":"b137203a0529329d4ab920ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"bc6267de41223bb388d6e5212d8e9433e9a4dadb85d618e30a78fc577139f39c9f2a246ff9d98e60cd248588a4","nonce":"b137203a0529329d4ab920eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"2947c66f0863f7d112d9d57bef0a0ebe604abeb766f760d51c66ab33b7071fd4124cf5ea10c9d71af50003010e","nonce":"b137203a0529329d4ab920ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"6f4a39526db94f92188cbc60d80f07a3102b4aa59ec05a0b0491c793e19b68f567ec470ce1ed4ecde66f81b730","nonce":"b137203a0529329d4ab920ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"895faa3811fe83c531819b83784d637e946b186e9ea9b2566336f9b5e9c01e290d3a2c7ed00339ff328052b1b0","nonce":"b137203a0529329d4ab920ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"973db0065d6656f77b973c4ec8d2192e388562e797e0222a46d06b4d64ab5ab7c4e2c151d00f550dc930469e05","nonce":"b137203a0529329d4ab920ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"f851a294fe036cebb86c16951d1f0acfe0b06237e571c1f3707e731e9a75b65aa7bb265d42d139983582b7ef87","nonce":"b137203a0529329d4ab920d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"f994eba4a4cf01cf4cc3172986d6e5974c5c313621732c52a05128af5dafd2389f4e8744420866b168f149aecf","nonce":"b137203a0529329d4ab920d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"cf13ad5ae3a1c802f955d54883fa68273566c7bef139321eb98719260949c1fd2ee45a09edd5f1e3ec0ff37639","nonce":"b137203a0529329d4ab920d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"d9d0f3dba5f9b810651290ec3b59ce3c2c6b0b2f0e7b3188b55b66a2299d606d5e8c244be404442636089e33b7","nonce":"b137203a0529329d4ab920d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"80c6363abb4e51c878029bef87f19607000cf3ee84fbd183f9f7333eca2d27723cedb351876d99baa9e311ba54","nonce":"b137203a0529329d4ab920d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"279d866ce36fc393c762d170025adb9a7b5afc0e7e773aec5480df2a293d5344fb0625eddea6796c253913bdb7","nonce":"b137203a0529329d4ab920d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"e290b31440984c6142b6669a7c11e6cd78e4e0d850a01bbe53531a229d06a57319bcabeecc1e60c72a69bbddd8","nonce":"b137203a0529329d4ab920d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"11bff6cacc5f0b4dae3f1968db0b33b3d5c859089e2af9a3ea855ff069a9d414c5fee74332f6dc9d596afe0ea1","nonce":"b137203a0529329d4ab920d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"8d9b8e80a5f7576067fe7f1ec2d714dbbc4e8f93b9d26c69194bf5fb3a0e7f986093dc38efefdcd126af2e2b61","nonce":"b137203a0529329d4ab920d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"016296a7e17feaac09316c26636cd496800de56422674a8c3c81858d6a98cc7ccb8b855bf322412b28dbc99523","nonce":"b137203a0529329d4ab920d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"92cc86a9bf95963f79b378670436a027b0992a5a4ed2db122131ed282e37696d8930a13ad9500dacf4319dafd0","nonce":"b137203a0529329d4ab920da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"46ff73425f565ea53ec41daa65a87c84674c515d046c855206ba14cc4c1fbe428004e00474fd262ed9b10add65","nonce":"b137203a0529329d4ab920db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"9594cee237f514ac5d1056c9f38a06bc1b3ef9c12a607025b4255f69bc66c6a0bdd97bdec8a9f3ad4522e365a1","nonce":"b137203a0529329d4ab920dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"2ef94e648da2199f36ce6ddbdbe9e1460f187c33aa77f00eff042bfce67932a011c3b3e7074996b96459ed2dbe","nonce":"b137203a0529329d4ab920dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"794404a94a50c18c198a1e8a7e15d419611d64410011b2c297270d635e35e8de4bbaee9d3a69179f6e4533eb4f","nonce":"b137203a0529329d4ab920de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"f7221f229a86aa073c90ee53ebad509c93b0a6796c6a1ac8ece8dcd5b5843f1932a53a341883eeb7ddcce6fd62","nonce":"b137203a0529329d4ab920df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"e7caf41c5dbe6751251a6a369ae6be17991293e99fb7609c712171de5ecba9821c034a1a9f1a67981deee48656","nonce":"b137203a0529329d4ab920c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"29c2b14bc9b575b47b8870be5f37d7d6d8c523985fd6afd1f8cbcb68fa65dcc408d11e75f67ce7742246c2a7eb","nonce":"b137203a0529329d4ab920c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"2096d5c1993902f0fe9bac35e109e090a7a7f8e2a82b422a9994db68b90c6e1da139967577c9501348514b9eb1","nonce":"b137203a0529329d4ab920c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"2fbbdfff0afe392ff69a31ba0f2b25d5e8ecec569e9636a50c10a07fd98258d6e57200b47be04629e1c146941d","nonce":"b137203a0529329d4ab920c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"67f84dd20685bb60f78cd0479700eda8bdce29277f7313d95502e9d2f8c952afef653a680a281951b9ce8996fe","nonce":"b137203a0529329d4ab920c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"c5b5ece42ebb4a4ff8f1d54ab536c5b865730e742f2947ec60db73d74427689cc33ff4988a84b807721791d648","nonce":"b137203a0529329d4ab920c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"f824baefe64a900b7276b4e83e890473409cae7a8f38f7dd48e3c9bb3127eea66154f13d971b0609c46649d462","nonce":"b137203a0529329d4ab920c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"9a8899a7822e25d81a2c7bf8a4f9ebe19b819855341b355b6fa29a7585429990ed440eb44a8d7c9cb6db02dffe","nonce":"b137203a0529329d4ab920c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"30a70a72ae8abc3465e52f2ac1ae709f6f67db99bc482a1ab3df96f99ae7e45b81cd84f6d51bbd9d3ed30821d3","nonce":"b137203a0529329d4ab920c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"3bc8f273a95dd2da6daa9c1c77c5e5b23ff748c1471bec53795bb1719cf538cf3f3e2651adf601062e05752fff","nonce":"b137203a0529329d4ab920c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"33ec612a1b97de7424818aa60262d7ac97ac6c5a10f3fbb0c638857a2436b25d5e22a87adc5eaae50ff34494d3","nonce":"b137203a0529329d4ab920ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"7cff1711296c3729854fef29965380744078f7a897ab7ccce12bdc9731923cca9aa9c9cf130bb96a04221c70bc","nonce":"b137203a0529329d4ab920cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"4b2c3011ecb0e1fcfcced1ff46f3e7aa1ace4e0aa201fe9ace452b27aa7222b2fd6393f60830f85e33d021151f","nonce":"b137203a0529329d4ab920cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"a5bb74f399a5460d3dce79e9f5ef485c5f4f2c53732aae37dee68a119ba2ebc33bfea5df2ebe8d7a1678ad3a2c","nonce":"b137203a0529329d4ab920cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"cd76bf9e43b457cd7fc3bcf05b83fdff630515a110936021832ab248524992fa174566785b25481fcd847fac71","nonce":"b137203a0529329d4ab920ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"4fde3d2f5a497e391176f6e5b2bf63266523d8375f2d1d08f312dc178ebc4f329faa39fd653b74253c4ee9c7c4","nonce":"b137203a0529329d4ab920cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"7ecd2e01d267ca45dda024db0a6acbaf95b706a09af2d740ee462aefe6312af0de1dbd7c8f1e0c50cea0637876","nonce":"b137203a0529329d4ab920b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"e2780b81026cf56a8e9dda25b9e973633ea527b6fb2f2723554564a36aba7cc5236556ec69ddd9db61f0488f76","nonce":"b137203a0529329d4ab920b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"2bc67c5090a364d0f139a10f28841c35e08fb87fa86a9aabfcfbd6996db98809e5f98be9ab8fa7eb94d6436778","nonce":"b137203a0529329d4ab920b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"fdd0253a32bb37a327facfe80f6c82eeb403ef87a7b6230a1123b33fbfc65ed235124003cd8c925dd2447a06cc","nonce":"b137203a0529329d4ab920b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"fcb010980e01b216d6fbe1dff9eac2cfc73766e91a00bfed17c13e9abf23ad0dd2c26f2212a274a774a3c8911d","nonce":"b137203a0529329d4ab920b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"5b213bee17fe8c481c62516f149cee92b6c6f248a3c3deff81d3f1a9f96079d897eb231c795582513b38bdcd51","nonce":"b137203a0529329d4ab920b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"37d4b2f379f33a77fbbc4acbf7be1fbf2352bc1da4fea1400347889544988597c24e94db71e76cdb32c303502a","nonce":"b137203a0529329d4ab920b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"05501d994eab98f4764270066f5023f4340926d7ca726ce61ba021335f114295f95506c4eeea07b26de0a0083a","nonce":"b137203a0529329d4ab920b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"b3eca41ec3aed0059858d92b7225bae51e714e8c11742558f472e397bea451f509ce1ab89b19eae89cdbf17d28","nonce":"b137203a0529329d4ab920b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"d1b2e01c94015f5d242d29d54737edc2506e32e83ea7eccd4bb4bfd54617b2aa26971c77f5a160b31aeae80a68","nonce":"b137203a0529329d4ab920b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"429b4712292da8e5bc51ff385d06b6c0fbc476ad3d72ddc0f22e65cae37c1242cc3aad3fa0123dd67f91bebbeb","nonce":"b137203a0529329d4ab920ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"8e0e51d2c2f8682f093336d5b1aa6c8c3e61d2b0250461baeba8ac3dc17e31e9e510b23464d7a95fb6ae0f0bc3","nonce":"b137203a0529329d4ab920bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"31929894143e115f19437b42333940f2de0b8505c5eeea3094f51c81ddf43b6ddcebbf14ff617b879d482a0e71","nonce":"b137203a0529329d4ab920bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"9eeac676574e2a6ffb8f909cf6a90012d10a7b38d2818cc6957704b1f39770231c6e6bf9772a2ce34bd2545be2","nonce":"b137203a0529329d4ab920bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"fe79ff25dbd87d9a37ab836647d7e3e210412aebc3202888af011653572cd009203a7ad52ef9a5d2dbb98bde90","nonce":"b137203a0529329d4ab920be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"37b241d1ba61c25226c27d09e324bc14cebb8692ce045ef753ee3ac8a9b4071e71ec399f267fd9588660ed69be","nonce":"b137203a0529329d4ab920bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"4238a1a41a18653c863ba72fa90a33fdd3fc2699bb6fd2157b76185f825ddaf5e6620c10e33bb5274e5235d9c5","nonce":"b137203a0529329d4ab920a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"00ab615a45e520ef89931b35038e36a10987e424259cafb649634c6d171f5459dfde711007ece9788be2af4252","nonce":"b137203a0529329d4ab920a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"9aabfe8f26c8a3a5dcd41dd1ab92fbd1a4b110856555ea9014f42a02e1793a0a4d1917692537a10b72c8ee44c7","nonce":"b137203a0529329d4ab920a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"d167a322964c0ea06931ba96b9b7ac643ea08b779d3f329727e78ae3cba09232db544980b545d5e5a64820e197","nonce":"b137203a0529329d4ab920a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"c5be27f4adbe615b1413cd9bd4a1a0200cc0265c8027e330b8474dcddd05ea6c2baf92d2107d77b1683d286da8","nonce":"b137203a0529329d4ab920a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"1c663494fffc1b82009a119149669b1795526c4000159e9269fecfa5c423742e82c84aca016c5c0a58640dd273","nonce":"b137203a0529329d4ab920a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"66b0a87572f54af08874105fe6e3d58f44b81264828eb194a19b403ee98d69b52bc73fb155df997fcf058bc76d","nonce":"b137203a0529329d4ab920a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"1c970cd862fe341bbe968a9a4e0915be6ae04c8ed42911946e7cc389bd8356b10dfddfa22b905a5e8dce3df03f","nonce":"b137203a0529329d4ab920a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"1e679408a45e0b7f847b71f18b26d5f799468067b8503ec7dc2f98358099b00f2c171a1624f04a6361c6945be4","nonce":"b137203a0529329d4ab920a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"ababd3e8d2398d23e52ced7fff28db9c2dd3747bb534658c1348a0511ef08c50bc98d03c015c31347328afca2e","nonce":"b137203a0529329d4ab920a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"69457cd2903cc06283e9f48f72b5ff970d39eb26d4e0837e0a76e4bf4500faeabc5f28e77e97845642093481e8","nonce":"b137203a0529329d4ab920aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"3f4e10147ea599ba2ad35997470e9489aea112245658027fb7627dcf0bc456b9a0bf06801d0566752ceee3718f","nonce":"b137203a0529329d4ab920ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"a11cf999497db6cf1b3018e9bf4530a9957ad21c9479194fe26ce4cb79db0d54f2ffb3626942958f28649022f1","nonce":"b137203a0529329d4ab920ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"324d054772b628f333301f7ade1edc28784a469975dc99f6c62c3f3a8e284deed0913f523dc5646181f9cf2f33","nonce":"b137203a0529329d4ab920ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"4a80494f0c148dc60af8c6d8485620e123f3b16963b70176f1b02964a9b0b6b97fc1c556ff6027148876e69f67","nonce":"b137203a0529329d4ab920ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"684d3df712e5b45de6a60479b83027570c54bca55d6e633f712adb0efb564fe19769b43bf92b4230aa675bf3da","nonce":"b137203a0529329d4ab920af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"58660356c68ad354a497f8cda5544a5cd26163f854ef5d96e85db82b539c7b65dc74c7128943d7574050c03673","nonce":"b137203a0529329d4ab92090","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"dc07fdd04791cd3b5a37452f9dcf6ed48593c56821deae4cf322f41e9220605e269d4be019ca6dfe969509d15f","nonce":"b137203a0529329d4ab92091","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"fdf6e1855f88b8afcb5e4e385e9a6a4609e407d680c118de8fc566aa32d85be0680e350fd66fa59e97b6764daa","nonce":"b137203a0529329d4ab92092","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"259500df658c3fea6acff7b5cad950cac9c79b1bb5bdb2c2ea17b144cc13c4ef5c67c2bc39b43419dc1140393c","nonce":"b137203a0529329d4ab92093","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"1295eb15ae286b066338489507d983e7bc47a76982876b51120be89888de8b45d4b46686dc8f4c319f6412829b","nonce":"b137203a0529329d4ab92094","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"27e88ae578c1538e8d23e6625d2cf570b0881579ea52ff71ef837d5a6461b6166452881bc14ba6b899c1554a37","nonce":"b137203a0529329d4ab92095","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"d50f07a5f806504f819abe403b0ff3ef11b76b8c8ca030cba9b362c477de832f5212ce143ea03ba1499a5b0173","nonce":"b137203a0529329d4ab92096","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"1e87b7ed3977c3fce6492298ce02a715911d685a10af722643688b1097a65d184722bd63b944f54694b8cb173a","nonce":"b137203a0529329d4ab92097","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"ec102c606922af6f538abc71b37953722e5f3df6525a988b6679bef3a98f14229337c62327ea1b2757170d2dbf","nonce":"b137203a0529329d4ab92098","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"7a0f96d3866cd88e2ba204720d4d03c98822b267360fc4bf31f72735432ba77751afe41b90c46e5be875276877","nonce":"b137203a0529329d4ab92099","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"5d0d1a493570d4da9f583f4db9e183f0cb8ca940f8f98b567ab6de560afa8223d9113d6a9cd2270f76b5448a33","nonce":"b137203a0529329d4ab9209a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"4a5641bdac2736c626d87170f12731a519c2eb605e0c76dbf7e88a59ef2cb5f02aaec4fea8af0df3ac26ac8a15","nonce":"b137203a0529329d4ab9209b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"4c7043d3d45db04c3b7631c1a87053104dd35db48acd8101f52ce33f5e80bdbcb7c29ab0db7c7a376a41b8cbd9","nonce":"b137203a0529329d4ab9209c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"37ae63636cfa07aae2adb2f120238824bafc3fe4144589d8a134dd1072251ef6cad349dbf27d0c3e8ada979fb9","nonce":"b137203a0529329d4ab9209d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"939b2093320a3a8d06b307a571d453cb08b213914abbf7e9ea39b618f87f6bdfad09f00eb83bb4c882980b5f83","nonce":"b137203a0529329d4ab9209e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"09d08afe4a9bc65bd5d6d34635c61bd5e6b0f4c5c66a189e73d95bea45f6cc90cbf254130980f9748e8b5a14b1","nonce":"b137203a0529329d4ab9209f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"13b128f5ee3bf9825d0af67c833eae8c9a7c7b83b49c008624c33942b436ffc8aead02106b152a57ab059dfbc6","nonce":"b137203a0529329d4ab92080","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"e88d0a75d9f84d02a1d1a6227d3adcc57a2c195728e41e611b79e48c3f7d0178cef775f96cd64750e7b72cc7e7","nonce":"b137203a0529329d4ab92081","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"2cf294340f6d5de1518e59054170c296e490c661d6052a03c89e022ccecada799d94538f32d673fd920c5f0e39","nonce":"b137203a0529329d4ab92082","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"5948eafe41c3d483a5db5308358690e9c9456d0f726a6a69bcc1d08ec478d960ca3453f7cbda8f7c54931ea13c","nonce":"b137203a0529329d4ab92083","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"b3888ff69b8ddf4d9b219659787fa4a3e93fcda4a469d95e494274236d20d56adedc17dc2ef560ea27c0dfc4cc","nonce":"b137203a0529329d4ab92084","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"c541b14d60bb58757fab8d395b664d4ab48f02103d8bace91574760d64f2a30175055aff1517a02a8ed654e4e4","nonce":"b137203a0529329d4ab92085","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"b4d2e4ae25da6938a22b3d8a7071e1026d9e6136255655bda261ffbe7f51ddee53fafecb57a14c9c248d121d89","nonce":"b137203a0529329d4ab92086","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"c991c8f4a8e2a2f669f04be32a92fcbe763db2e3867b00aa99b52a78548ce6a08c2593a2d033b8a8d074770251","nonce":"b137203a0529329d4ab92087","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"091fd97317ee038b7880670447adf29db91fadf1a3ae1ae4438292c26a6b1740c7dff5633f81231e2285f6b06c","nonce":"b137203a0529329d4ab92088","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"ff2c76c1086d256d78cc5b5ece5c53b7c82b2ca3dd57a9be84ba7585c5be9e50504637163af693a71566d85697","nonce":"b137203a0529329d4ab92089","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"c6913c56c1f59e3408896cd8172159445eee1034e99ae101cbb5f78b578ee38d25fc860161ffcb2e082185f552","nonce":"b137203a0529329d4ab9208a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"07b03264ed672b7b58eea7453bcad08681d4c0e9f8b32ac3170cd5303f22eeff634d52b402106c67d2d22e1e1b","nonce":"b137203a0529329d4ab9208b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"dba7bf3b17254af318cf6863a4e44dd26341df0570a415be01c2ba8e908bc19223f75fd496f44ad876a7c1f977","nonce":"b137203a0529329d4ab9208c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"8a9f0d59cd3e35bb963deec6f388e6efb2efb1bacd874f7ef59b5805dbba32180f568dfac127a31ecbca6584a5","nonce":"b137203a0529329d4ab9208d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"2c0f244dbcef191eaea32310d426003cf10b101629f99f3fd273cd8e23a9ae149a28688e3ee8ead907b1830ea8","nonce":"b137203a0529329d4ab9208e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"cf39b6cfe9af78df2b27c73db3710970b357a98be0a1822bceed475ca5974eaae0e69f3e7a8d6626dcdd78340f","nonce":"b137203a0529329d4ab9208f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"786cc3973044302a51bea8936b0c867e0649bc1c502d8102e80752f5c20d628d089218f366de660a9cd1c556ae","nonce":"b137203a0529329d4ab92070","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"162d80e7aff865fe8809309ef9e3e730526ef2c326b78e6dbc913a7189f78bc2cbfbf4065baeba5da97daa1869","nonce":"b137203a0529329d4ab92071","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"d7e09aaba442deeb8a0bc64d579aea73856360d52795fce0f9cbd523c26cafd2a2d12b1dfc7d44118819a40cbc","nonce":"b137203a0529329d4ab92072","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"f37e2f2ed4d03dfebf548e5044f6787947681f875d42d86b6e3df60c790980ee7c858b3d288f22ffea873d3920","nonce":"b137203a0529329d4ab92073","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"cfa0bdb6303d4b38cdac7feee361818c69e7980183ae3a736811580f679a2c4523e24788486410926884c0ce43","nonce":"b137203a0529329d4ab92074","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"22f821027803cb54e7f141208a28c5197c0d50906c9952a3150f316f85515e9128e8a71d4b1578e53714030445","nonce":"b137203a0529329d4ab92075","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"0b9dbb7cd57f647e4b9c0235967e462f495a56303747cf8c8409f62f149b315344ea49b2f9e24859482b368377","nonce":"b137203a0529329d4ab92076","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"1e903b6cc9114d4372717900dabe0f7e92000c46f942d5a99ff1aa1eb35b103304df4c353ddca217155d492026","nonce":"b137203a0529329d4ab92077","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"e9206d64e03f04f8ec2161e19328470bf972ff0f91d82eeb90dc5e63ec528830ec8e772ca1b85bdcea9f135657","nonce":"b137203a0529329d4ab92078","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"cd3f0de1844315b441a5f6d340bfd6c9965039ab12a8627eb0200315923123d8197e7b6fa4d31d2537f6fd8100","nonce":"b137203a0529329d4ab92079","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"59f485955197bd44a5129f1f6ca681d0f5622a994485b25013a159fda7a12f8e60e6503b58eb764b09f19ff8ae","nonce":"b137203a0529329d4ab9207a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"6f71465eeff03b48aa5f1b637b150b3763382064beb28d3743217ed6546ca42208c43d82077f80c4abc78e971f","nonce":"b137203a0529329d4ab9207b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"6eecbb568e62213b2ce7f37c2c61a67a1af1618925612a4f8d29b2a60054e268eabe986b350717c9e550ac767a","nonce":"b137203a0529329d4ab9207c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"549d94536b6895f7b114b064986927cc24469cea1049ca07faa3cd28d2acc8e5f42e125e7c08d7296c3279b13b","nonce":"b137203a0529329d4ab9207d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"a59103efe10550286ea86b9ec377192e1674b0e18cfb1247dc6a2bc2d949f0c7f7de4476bed2a5a3c65f1fd639","nonce":"b137203a0529329d4ab9207e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"71fc55a2e85d5b704452ba66c8bebefb7eaf29f7d24f58b94197ee2d500343028c6d7bdaab711cdab4d153fd79","nonce":"b137203a0529329d4ab9207f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"bc33bd03290052dc04c4b3906b60f5bdfdca50310c515ea164988491e26e0b5a23a2e61d2f4d36915f9221608f","nonce":"b137203a0529329d4ab92060","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"6f0778f56600e168fb6142fa8cd93f8f7a40559c8d0ebee6336a81a5705abd8a608b05038c0023451c5d89c0d5","nonce":"b137203a0529329d4ab92061","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"1ed69c21c5ab7774cabfc6bf0ab7cc2e4108553b7bf36c09130c34b2e17b6cf90f8dcc00d3adc26be0e0f55bfd","nonce":"b137203a0529329d4ab92062","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"0361c7cfd06c02bd6f45746e6f4cdb54c316e97f4cfe62c61ae5433d4380f083c0ac3ddbf0310d6df6e4ebdfd1","nonce":"b137203a0529329d4ab92063","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"149ea6eac95d43219a18488763d60c4a6b314118e966221d18ba09184ef62915a19924c8282ef0a78b79694965","nonce":"b137203a0529329d4ab92064","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"3065e6961e7e7af48f1ad986d06530df6da4e3a4ecbc03a53d071883c4023fa629ef56ebe32f428b805f3abe39","nonce":"b137203a0529329d4ab92065","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"9a75f8015711c386a1449977beecb3093c4fa81482d87d044a0c94a332ceeadbb647144c00c20b0cc893300b6f","nonce":"b137203a0529329d4ab92066","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"56980c0e5cd0e7348bd210f824d937d6fdc6e9e5e9c693af7045b3f04ac48ac05b7f2dbcd043b59fdc1129d4e5","nonce":"b137203a0529329d4ab92067","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"52283d05e3ca36b75d8a89af37870f0ded761693f22a1a17cb5c69238094f9345ba870d8fd1db16ab2d1d0f556","nonce":"b137203a0529329d4ab92068","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"071ad62defaddbd469fb9cca2f1d52c47f07c858347113b46c6129575a2da3810b717fd16ef3df5a3b23135ac4","nonce":"b137203a0529329d4ab92069","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"06db937154a370e07455a9fcdef843d4b0cfd8c7f7b10f9825ed67d8c2c5f0a2a273433107103e0744c357da64","nonce":"b137203a0529329d4ab9206a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"e62c769ec28a9ce0458dcdc231b5443db804b60c297ba83fb59a72c5ecebaad62655f6d8fafe531b29882402de","nonce":"b137203a0529329d4ab9206b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"2d2d8a9fa89c9d59c669fc9fc546e088c6a18cdf3c31dfda14a53b74a3e1cb77bcfcfe9cd9d1b6c35e982738b8","nonce":"b137203a0529329d4ab9206c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"fd8b91fbda64244ef8b297c1f490e5a8cb449e74bbe88ad3ffb8e800c3a161dd4bab757f6f9c761b0787118c8d","nonce":"b137203a0529329d4ab9206d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"3c9079a6b78656d6805a13f975a33bbebf7318da659b9616581f0cd4f555105a20c319759c39a6220437c81606","nonce":"b137203a0529329d4ab9206e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"29aa3d081d8fc2361a7a33bc53d420112ca2b03b18c599f29b438210074cb2be62b5ffcfc282d2a07ed7b08425","nonce":"b137203a0529329d4ab9206f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"d92e1b2ba550f8fa464b3f9665b7e9e5993c2b1a55af07fc1f56e2f2aba84acd74adedbd9f732623bbe8f81ce1","nonce":"b137203a0529329d4ab92050","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"2e6007adc3a50153415af22fda096dcb2538d60f5183f0f8b08a5080d7282b4213aa3b9ba8e9e321ca0b1dbcac","nonce":"b137203a0529329d4ab92051","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"028cef50b37e623a02485f25ae4bb779063a4f23496cd383d42606408c22c50c3ef6b8f7890185e26596c66af3","nonce":"b137203a0529329d4ab92052","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"00c7f355290cd2aec50337c7d7f39cf2bfedd1f712fc73cfdf1068b54c9d3e66fa63624f17126f2abba2f0ed2d","nonce":"b137203a0529329d4ab92053","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"be05d057771990e4b6164c5546496d67ed23a28ab31d3d90f2e1360ef880ac0b0c583afde370af77587b734ccc","nonce":"b137203a0529329d4ab92054","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"a07e60026cdc6a38589d38c9287db51df3e10f3049b85ec240247435fbdb4f4d2000a3841553e9c48fd77f1b97","nonce":"b137203a0529329d4ab92055","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"1ad35e14c71048e7175683bebc0ba2e93a4f3f4a4d0195d9fcc0f8aedf6f530aba97296cc05494659b4c6e8cf2","nonce":"b137203a0529329d4ab92056","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"360256d4e40d803ac2f51e299c99e9582cf99b7a6c163acc3354f15968d1f8f3fbbdca5d198c9ef6e84e357223","nonce":"b137203a0529329d4ab92057","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"71a205ce58f24ded970755e128516026e9a82b06085095e4275ff8c8f52ec7c053838761a904de00a6d6b00f72","nonce":"b137203a0529329d4ab92058","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"be0b6b3cf95be41fc2a9783afc5dfe47e010aba4403d23b7bcc1ceaae015597f376cc9081e61adfb100d67e5c3","nonce":"b137203a0529329d4ab92059","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"d94cec71665d58a9e29d50447179b44f23a6dd710caa17a05572d95c163fd33d866719994f8ab7b1c17218e701","nonce":"b137203a0529329d4ab9205a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"ccad6554a55d4100130f3623c264c080fd6c165637cf9af50241d545d7e713fa4840d7d16603844fde3670869d","nonce":"b137203a0529329d4ab9205b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"a82c14d25f64586cd4bf45aebcd4451778cc5eb0ddaab31496b27d76c08bcd233dafa139a3fd4b7fe4809e09f1","nonce":"b137203a0529329d4ab9205c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"4092e47ca5f8b1fbafd5581bc26de4544765376e7b82667a7861f0dd97cbaf4201f62cd094afb2c101b1ea04d3","nonce":"b137203a0529329d4ab9205d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"52a1be6c7cc2d930c6a3c544f0dc645bd6aa8250ad1cb4304a73bf97e60fb96d5b2a23c390275fcd381e260115","nonce":"b137203a0529329d4ab9205e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"e2bcf05cb27579ebcdeea56ca4669819d2c608311ab53ac8ef474b42ec8e506179481369e23ea72e6c664fcb8c","nonce":"b137203a0529329d4ab9205f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"371a24b413f24270b67ecd9ca795a2cde3a0219d63202b52eaef6eeb74bad1a57aedfa7b27492bd92efd5a4194","nonce":"b137203a0529329d4ab92040","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"3e7eb80c7f8fb4a9825717e8023d3baa50bcb93c66e96378f0550212c7860408cfff5fda363f88c7fb1e80a634","nonce":"b137203a0529329d4ab92041","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"7af0ed1fbed074c7964791a9c63c765fd9930e8ca7491a7c5cc132db1ecd83ea803bac9d53feae9ef39f48e40b","nonce":"b137203a0529329d4ab92042","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"1bfb8cecc7be8ff2c115060e933f2d8fd2aaef63ea8e1162173ba1fef80346db9145fd45d8cfeefe2dcbf814f7","nonce":"b137203a0529329d4ab92043","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"3ca4511607921e67f0744005c16371e514502093a0e01d58d6dbf43f6e457ba6af496f831f658e3a7b9e3baa61","nonce":"b137203a0529329d4ab92044","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"ab006779e4aa8c57290e2961d1da9cd65a808f7a4937f3dbed2bb03e76be3f92848cd5c30da1d328c219eb875b","nonce":"b137203a0529329d4ab92045","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"6bd146f7f56ed655ebfe432d46585b51d157aa4c73af56c275dec2ff199a5cca339395d58adb28397fb69cda0f","nonce":"b137203a0529329d4ab92046","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"94ee2f7af7a4286bc081611c83214338c43db5991804071f177ea00206d3a3cc0b057ef62626c7e2a4a125dd64","nonce":"b137203a0529329d4ab92047","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"b7d8c12b603b8df9b6b8c4a8bc4a24a34c5f4f2f9f2dbad629e0736b401ffe04fb3c2a843e0c07f9e9791e43a7","nonce":"b137203a0529329d4ab92048","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"b829adbdb6e948820a8f6b4493a4c55a32e515ec03bbb4a3008c417b239c82bced6893eb588d6c83fa1d1b160d","nonce":"b137203a0529329d4ab92049","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"642862fcec4c311de849ee4cae034d9455d41f78447b4b601f8fb0afda32bf6145f9fa0ecff9479e21b71b1343","nonce":"b137203a0529329d4ab9204a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"75000cf48b4684a2f583d197d92c5de61af931cafa248d8b1793dd4b13dc8f30b22c42f1e2890688be6389df84","nonce":"b137203a0529329d4ab9204b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"f3f77410447d8dd539efb1b2e4aefe532034247fcc56004d7d5361821b9df7ebf8083de00d73d4b3d128d72da8","nonce":"b137203a0529329d4ab9204c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"fa96cb6830bf9f9f01b4c36626c05df73b115e0c23b245cd6ca9d748a070357906c449d1d3b6ee1d65d45033f2","nonce":"b137203a0529329d4ab9204d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"90ae273173c399bc284727c9f9ccbf5ae67b27cd962bcde46df556d1d16e9b2706ba149fa64473ac2fb67835b2","nonce":"b137203a0529329d4ab9204e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"827c1c0164fe6aa6442bd98f00b02c8c51a1553f799756ab284c4dfe903dac2a05e0cbd5ec5069041120d36e3d","nonce":"b137203a0529329d4ab9204f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"25b0b2a675e5e05682b6b07188ff5c4747f6019a934804beb0d1876f5a01ce4f12e2bdc85c4b21e3fe031c0470","nonce":"b137203a0529329d4ab92030","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"1e9ed1b7b606a2d73155619bdbe9ba4c312db3a50cca62c5299c04af6c6bd63a70d38cb43d8b4e81834915eb79","nonce":"b137203a0529329d4ab92031","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"3763c58e107392cb5f415cd74731071b1907a22263ae0b12a03dd446c251379a69b2e1bab26434ab55deaf85c5","nonce":"b137203a0529329d4ab92032","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"c9d0f8ee7348867363ad70bb8d3e05820591ca01c71f52cbcbf78f61b031ed98bf31c4ce41df68e17575de85cc","nonce":"b137203a0529329d4ab92033","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"4bc4e5315c6c84f48313a9179d513ff47df446120ab10c9550de2b3c8ad0958db00884d2c351bd2c7dc3b9da9d","nonce":"b137203a0529329d4ab92034","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"3d96399c8ce24154b3b089779478cedad151d4579a1559cc4b91ad73fe460ab3492d25e066e0569cf8db2a2d94","nonce":"b137203a0529329d4ab92035","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"0bcf2a78700115cb0b7a8fb1b3957a042d37da5f6e80e9e38eedcd9ddc47b54b021c4c5491a2fe4662c82dbc98","nonce":"b137203a0529329d4ab92036","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"12ea822e75ba4b347466781f5cf240ff0575743f98b408fcac1cadb3ae20c05068f471d79be351f7eba4bd1318","nonce":"b137203a0529329d4ab92037","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"e83cd6aa6c89bc340956706055c92ada444ccc07db87522af0bce21a257168c7099938c6103e52db7ef6fc4541","nonce":"b137203a0529329d4ab92038","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"0cc75c4af8081c2618386fd131de88db6861c323b52873dad7bb2d4b56bec905b4eb8be4d83e142f0687fe31fb","nonce":"b137203a0529329d4ab92039","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"3413fdf0059437ea56efeda45b92700f697f68d00fec2353cb339cb9341e15fae14554bd068d523e1449a48cd8","nonce":"b137203a0529329d4ab9203a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"72cb621d7b26135cea055637fda921b9126b331c431ba09ee274dd95956826ef9d7990c382ad9ba9f18a2cf322","nonce":"b137203a0529329d4ab9203b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"6a6f37316b93249795c5428f2ca2e11d5f84d2aa062a1fa6ede60ccbcc15305e346a01a6c595f441c6a3440856","nonce":"b137203a0529329d4ab9203c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"4f6c4a28eb5b486013c0844fb94cfa925ea955a22e80abd4ec58dfb8ec2e653c93becbf62de38ac5a355cebe1e","nonce":"b137203a0529329d4ab9203d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"23b17919aa105fab5eb94d1f3aa336cd59f9e953157ca80ab73c7a7a9bc443950da4cacab500c13fbcbbad8241","nonce":"b137203a0529329d4ab9203e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"3898f76b0c1f053f802a040b7aa533c0cd9728bf6002474b4c9012dc5c9872671747ea742c3ffca524cb745df7","nonce":"b137203a0529329d4ab9203f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"9cf172bb279112a7c28f0a88d12efa878fc3ee8c2013735c36e85cc1b49d6b25330b7e35472041e3c58a8d9172","nonce":"b137203a0529329d4ab92020","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"7ac4cde92fb711a9782bd0cb1f1ba6d603fc63beb922e89c0cffe61bb745cfa9a1214dd8a4ece8318d0b073125","nonce":"b137203a0529329d4ab92021","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"cfce0fa30122df529b0087a30131c0800aa03fa9912fb1e9d91a9b94dba1af159759307bfd8125d9cde6a30fce","nonce":"b137203a0529329d4ab92022","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"6b163c7cb52848fb8c679ca71f9a4d3334fdda1d38700abc6370a2efcdfaf4821585d4b144f863f8e5bf1b324a","nonce":"b137203a0529329d4ab92023","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"40f8bde05a9f6e3aa99c61d2dce83c836e9cf01652750301aada0f1c527aafa83e8504243a402605550ea64506","nonce":"b137203a0529329d4ab92024","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"e40b1cbb4ff5244643f2082109b4087fb5f48d82ab75596f818736a8d37a99e17ce8881799634a5abe174fb488","nonce":"b137203a0529329d4ab92025","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"676e5d1f8f12f1a85a56d2900fdd2e9760ab24566b3eb832be256e05a85b1b6980ac8859d0a60c31e2d3148bb7","nonce":"b137203a0529329d4ab92026","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"5746392deb9f829c4967a3a06affc3340d2de24dd7662f4b55c87007eb1f42804abe9d3bea2255c7e94179cc3a","nonce":"b137203a0529329d4ab92027","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"934c3aa99374dfb2d9b28caebfd6a04328b3ffca0b2e00f7972e53a90691d7757147041624c77d6cfa1c6935c2","nonce":"b137203a0529329d4ab92028","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"8539d239f928c35f52b0934af66ef5f390067a5be40294c630918c04568942e1f86f4170935ecb005974f4a09b","nonce":"b137203a0529329d4ab92029","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"e8b77ab57260d52722671a46847b4e0b21055b776e972e97925b3347315bea2398bc9ddcb4c67821f84bf9468d","nonce":"b137203a0529329d4ab9202a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"d64f44de94a2a8746d0d1e4371114ba018c1e17241e4421314e234e0d062667a979b6ce7fe2fa77f9666982127","nonce":"b137203a0529329d4ab9202b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"8dd6240811a1e87b94cf140351a14cb07924b1465da92f93f2bf844cb3b19cc445c4caf11be12bbf396b8fe826","nonce":"b137203a0529329d4ab9202c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"67cd7ccc1b7b62169f4a3054bb05c6b31a68217a86184097d2c693ac7fae5df3db4e3d2a3339e6664c4a5ff9b2","nonce":"b137203a0529329d4ab9202d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"2ce268fc9711765a1c1b532e2e6478392224c4db46f8161cc93aab98845ba26a6734b83fd8655faac652f8db93","nonce":"b137203a0529329d4ab9202e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"39e83f39b921269a9676409ad859f45007ed617af6265a38a7291e1a6acaa93f46e96c01deea6bad69957de24c","nonce":"b137203a0529329d4ab9202f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"47f08d318855abd2807e5495428424f3c9273d01adb0bd32ca88acfccb19cee02bc566361940365de1756454b5","nonce":"b137203a0529329d4ab92010","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"75fc8b532809e0094a14ef5d3d4f60ed5ebcea7551cab3a79dddb218206b4a80023f516152f169dac60d4a88d7","nonce":"b137203a0529329d4ab92011","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"29231b86b5b18111867c28da09b7e282e7736bc7b5d771899dccbb90f80cefadca671504bcf361d32ab0c0ed4c","nonce":"b137203a0529329d4ab92012","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"7c0bbdf5ef460729acf7b224f1fa0c845a8a0a1cb9593cf0c7ab668942cf185fc31df72ab6bed33db273f9ebde","nonce":"b137203a0529329d4ab92013","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"f9fc95d11016996faa693e522e1c84d36a3b9295db6d745604945cf8ed0bef622e04043d48337bbb248a8c5464","nonce":"b137203a0529329d4ab92014","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"eb5a748b41269696cc2bf9b620bfef312990479e3c11344dfa0878f9bae5d9bf491c62225aa4b503b8332a150f","nonce":"b137203a0529329d4ab92015","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"08595ac6dad20c8c91183216e2bca44fcf063a894cd34667b2a074184af8aa787023dc7401048b633d116955ab","nonce":"b137203a0529329d4ab92016","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"4ed20c9678d266c8c8ad74bc00aad8da485dac701fda41e6897ee55e8ceff56800819481ad12e1787452f96ceb","nonce":"b137203a0529329d4ab92017","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"6baeeea797f09d5435d66500947370b89b2f6b4b0ddff887de9b634173cbc621decee0cdb98047341b87dd6d88","nonce":"b137203a0529329d4ab92018","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"dca68f8e0aca56bcc542db802cdc63565dd7206cd63279f9c17c1a236c77029289dff45725c28529b87517ab67","nonce":"b137203a0529329d4ab92019","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"aa94f4f0391c5dfb445c403721793e3b275c0b1be9fffd2c5a629b52a84197eeb5bda37f6dda6d995dde78a6c5","nonce":"b137203a0529329d4ab9201a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"e555c452f3db21640565ffe0d2e27f3a4233f6e43782cda6d9ee16de67ccaa12ab9e6bd56970c8c132a5d967d3","nonce":"b137203a0529329d4ab9201b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"7a7be6aea3773014979dd9196cda1570345a1513090b57d9a61c3e60e9ae4ce776c3f019961da3c3931d020f05","nonce":"b137203a0529329d4ab9201c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"5ac8f919951d0ea56409f7fbfeda86628651456098fa10c66868bdb339fdac1af306a8c8bf9cd57e47b3d3b0d1","nonce":"b137203a0529329d4ab9201d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"bb8c03570314508665b0cea6cc1f1fa4ea898a149ac3690e28bab649218ff8a8c8645a232bff14ab469f853456","nonce":"b137203a0529329d4ab9201e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"5590397bca806286a494f385b477f1c6753a3099642c39466fa660ac9d4b76b872ca1d95813456eccb5ad50a81","nonce":"b137203a0529329d4ab9201f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"1360b38aac6557b92a1451e36592a1646c229381ad7de610510f373b81460b1f485d262d9b2280043e42bbcc68","nonce":"b137203a0529329d4ab92000","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"427213525405d28b60980f961fe9c2fcb5b93b2eefaf24bf885d43855b940552793ef1cdb8242ec54f964b14e6","nonce":"b137203a0529329d4ab92001","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"89f9927bc448aa66a9b1334134a1ec2f8250de4f5fc1840216ae12786d4fc22b4585b4537c7b600d6db946d32c","nonce":"b137203a0529329d4ab92002","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"cc5b93ba96e336c8ed1b960a4cc89ff51be9283b2fb093f654cc9eeac454606b58c6c4ce96432fdd50f7869dce","nonce":"b137203a0529329d4ab92003","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"0e818b20886f35389849a661efb9cc043caacda98934a9f29c2ff22a9148c0cddb6283ccc9c33c1a2b5fd5effa","nonce":"b137203a0529329d4ab92004","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"d74c5cbdd835751ba44c4caf00834cc1dda3619a4bb837b83f6ca7c99829a45a3b48f9f33777dd0c124c777da4","nonce":"b137203a0529329d4ab92005","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"9a2cf266b21143174002b3a5b9a6cc61741081e61b5ac2803830911444c04eca8d5a8db0dfc4d272c70cc5ee7c","nonce":"b137203a0529329d4ab92006","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"368137cacafcbd56f98b91a559a670d4b22bab6a03a62308b6426ed8f7b25430d3a402fa910479c2b26f33c0ba","nonce":"b137203a0529329d4ab92007","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"7404d75311b10fbe71cac7e5e836ebb0c22c3e13f114bf3d786f795d742e2130c968aa1b81bbbcdd8529010785","nonce":"b137203a0529329d4ab92008","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"0811a8aa8850452e7c7089379777d163803919ae45455a7fd78ee10d492bebd88d1ee75746867da3382b047748","nonce":"b137203a0529329d4ab92009","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"fa0fad5beea4df84baabb93283e8e2cc3a213104db7ca0a5f74583c4660a0d26eeb578cc7a5805bf09534853ce","nonce":"b137203a0529329d4ab9200a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"2610344729909106d2bc00a1660ed9603e669ce925bb2ff0fd0af166f11327fce3e5b6b0cbdd5ef507ff630a76","nonce":"b137203a0529329d4ab9200b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"94b8dac39e6474d84832ee3739a455c7eaab27915e541f48d99bf3c9dd97685ffb1cd5a3c91ec63409135c26c6","nonce":"b137203a0529329d4ab9200c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"bc864cfce9b5d6d56839e4f5e4d05a74211faf28c97b85ffa551e86c23505b7624a0fa9624a9456c47baf5a04a","nonce":"b137203a0529329d4ab9200d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"cb53ce61ec10f20298e0e27d6ee769b1fe735e5fc5d5cd14f22355c1494497c535b75d02781f4701dc5ae84eff","nonce":"b137203a0529329d4ab9200e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"7e5f8500f50c2eca58ca08ee8a597409a73e8894f97d92643681f4afa86ca4398a46c51f3e4b6e9e3b866c6044","nonce":"b137203a0529329d4ab9200f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"e4013279cbcf50c7542fce1feda9a24a822bab54e366b4f3bc24eb0968b262cc6ff26d39467ead32ba9f6292ba","nonce":"b137203a0529329d4ab921f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"29f4e041ad322b06c8fa5c7a16d0d6beae28a099a10a1f2961426c6b77586bb7"},{"exporter_context":"00","L":32,"exported_value":"e6bb2492bef9bfee2719ccc4950ae4a61eac109cd76e0f88c9249f67f1a7dff2"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"d288960871d7e614c90a8d0d31085e41eb193a4aec204f38939aa0e34c228131"}]},{"mode":3,"kem_id":18,"kdf_id":1,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"9056dade1b89d9812d35c9af12f0fd044a4ceb87cba8cc41894c8757c755b3d794884f6141a9a041510271617f1902bede3b06c3a904d77b6884e1aae161aa420ab8","ikmS":"b1b2f1762065776ff5f32d93b95269a64c2bfc4142c0bd2d2a8308d75bed13c05e9027820f1145a9bc4f9024577e91a3b4360849031628b299860b131b2a87098239","ikmE":"2218ac55754f8f611c2b9c13db75ca798d9310416e3f83e7a37fb48a4887bc0b47fc6464f835621f028af34542d89a2e67ee59d263148b0b84a3ba18bfd439848031","skRm":"002e66cfb76c9bd705dd897946a31fe89e75bc4ff94c34f27bb049c3b7ad945f58ff385c5654358ecd85cee67fcd29040cd28b5655eb1140644766960a8c5e6e5c40","skSm":"015da973a141a974150bd6c2655cecc23579a4f5f504aadf47dfa34cff8ec750de4e11ffb97e2c69b729a8fa94ed4c9bd5ad50cd6dc6f35c34aa41f9b7d46218e588","skEm":"019bab66ebc2c160187679d39ce302bcc70cb3087f9a9218d5859878be37ae0e707c6725b411dc738d4af00a8d9f3baa0a9b6344ccc609ce6b50f7db38ded9f156f3","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"0401ce91e65ce6590b0b623bc36df1aeaf0558661f6f195d160b42f46626ced52870ccfd37a181f1cb3c32d0deae31b44df378d916e5759aa581451c2e33cbebe74d1500e38cf6ae06f343ba5b5adb78bf3ea0b2b1a4f3efd9ca7a9b23ae1ef570dc07bfe2a7d640712a8bb7f298befd46df515dc670f3d9f7c5d0e9723a6bd27ca5866b5d","pkSm":"0401e12544ffd0e131d0786527ac565e835184b82306d8f92c9d339139296948398ed37aa2354a234278d8d09f2ee76688ff61e54e5463ed399d0f1aa3bbb58645afbb01b2907e5cd92591a54392d00bbae170bc863fd7532d6c3b3ecbcc9a1ad2545afb84252de8d547822ebd881b9855956eb2e931f0ca69b1c0c58a74d3a70569151c8b","pkEm":"0400e9766f33e4586731ba864814f999ef4ad8e915c1bced2e025f0bb08d19f0c33f3427c7485f3b0c00d9d0afdf45bcc8f290152b01eea4121e79daeba7c94d9894c900a158b08817b2f1afa751648c49de0baf31fc4825362d13f2c1d129bc3b6ad96338b953dc3df18e203a440686ae76417a956b4dcd1794079d8f60979b59ef11dded","enc":"0400e9766f33e4586731ba864814f999ef4ad8e915c1bced2e025f0bb08d19f0c33f3427c7485f3b0c00d9d0afdf45bcc8f290152b01eea4121e79daeba7c94d9894c900a158b08817b2f1afa751648c49de0baf31fc4825362d13f2c1d129bc3b6ad96338b953dc3df18e203a440686ae76417a956b4dcd1794079d8f60979b59ef11dded","shared_secret":"8a24dcbb35bb50281a504cc4fe84dd1c4256986810abc9459abc88d322a50164c1455b4fa43de2d3ce8518dfc1002447250fca68b230242cf715d9769d61ae4f","key_schedule_context":"03a5aa7a15c37a7f4d7cdfd2ccb134e4c19b3f782db2da917f6020ce2f1fd62b4497e18b628ea977f60a69bfa0647402182d019d3a0b59d2dd03624d028053dee1","secret":"fab08612897e53b86900ecc081560be0f65ffd756b44d6e8702602840fa8696f","key":"c7ee8887935ab0aed3b385c756a6946f9cfe00401265d076c3b4ba4a72cc6b2f","base_nonce":"341e18fab96647218d577aa5","exporter_secret":"55d1274a6278b811bfbc814074cd1f63988cced093f75d14188b1e007d65da9b","encryptions":[{"aad":"436f756e742d30","ciphertext":"80ab80edae1ef03034ef8e87a3d8ec32d95a5f4c365d69df0f3e1fdc39fbb2a8b65fb17e46f791c0ec9d719c32","nonce":"341e18fab96647218d577aa5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"3e2ca1a555c366c26fad80c40b6891c4fe3249d31eec4d3a38ea1f18258c66cb7aebbcbe8e53270885a2e07974","nonce":"341e18fab96647218d577aa4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"f404939fc04811062f5bce0880aa100c10e09689a9e27d5e0d9ca77987bdcd36aeba5604ae433f8663271675b2","nonce":"341e18fab96647218d577aa7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"92b4ce0b6ee2258fb3ca32ceb4f05cc7220459be908a2688808b34b46673fb30a27d0087de93277a32272929e3","nonce":"341e18fab96647218d577aa6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"8a9cd816386549c512cd10b45d0ebf65f3b2d37bd0e681e2390ec008139086abe67a86db108bd9fe9d99c36e4c","nonce":"341e18fab96647218d577aa1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"174548081cdfbbcb5479ba1fb006e55a445a8121bf2e56e536805d1c98ff037cb45f53a3b8b375ce2b458c5f0d","nonce":"341e18fab96647218d577aa0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"5f83fc619ba1eb19da36d62d83984f2c54423cfccf2488337f9a43b737151fd29308fb08a87e373a5f7f8ebe1c","nonce":"341e18fab96647218d577aa3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"05ec2da0126e24a4ff207c59aa9a0c3dd1b449cc7db5432131c9b7a67cf0f325f394d9d33449f6f5574c36dd27","nonce":"341e18fab96647218d577aa2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"c4834f2984683dc93e4686b883c0cefab56e292ffab81b553e42e9490b3ed985863a31e29381c6c17309160cf8","nonce":"341e18fab96647218d577aad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"c7720b82a22e0056be2576f6cfdd90e9f1e58c88cf7b1398601797bd5d7ffbf255c218512d0a37a4fe51defe8c","nonce":"341e18fab96647218d577aac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"4ee9573278154fe32aa00d8a16f2acff07160a35a8dfd4f24f5d3afe6dda205bfdc62262db0ec2c2dbac6b8ae7","nonce":"341e18fab96647218d577aaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"7b3c52aa5347082cfe6197c23d0ae72a0ee192b48702e9879de1479a641e17e579641c599b32777cd94f709018","nonce":"341e18fab96647218d577aae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"35bd3aa1c71aad8466243daf4f80383a140a4726b2d332f731522f565d933ae6e9a1660c2ae53e0bb9e579d364","nonce":"341e18fab96647218d577aa9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"6e4f1dbf8d6c4ed46940736f4738f9ca6f239a13e295de1769862de79fa3de21e8ff1d154e0ed7116a696d2b0d","nonce":"341e18fab96647218d577aa8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"3219896d20aaca73b1f347d5b439c82747585afff296c02f5f58e985bc333838bae134240733d4a7e736ff2d3e","nonce":"341e18fab96647218d577aab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"0f2492cc47b02543d52311bc1c67418ce7924d3cc8ac6a5ba540ac617c29f8d9a5d2f27ea14843c39b4ec90e7f","nonce":"341e18fab96647218d577aaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"8a268a790a9579623bca94d042fe7b7af10ab58ddef21e6b3463217b8f4b5bba37c7de94b72bc75c8ee7f5882d","nonce":"341e18fab96647218d577ab5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"74ec975a264f35442bb8cd08256665052ec2425c3550d1a79c636874974b74a922d0e424d64d5cc0813499447f","nonce":"341e18fab96647218d577ab4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"56ea3f34496f385b931b19c1ac27be5dc79e640722f47a13c5d78caccef8bc4aae66fec37f1cb86b474d3a8eec","nonce":"341e18fab96647218d577ab7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"830d647dfc47cd09d253f819f11fa5db25794581c438d4ffe2d21f403910bf6f9f0f94e4e9aace7ba271e42582","nonce":"341e18fab96647218d577ab6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"868445e2cd9b3095cb9460cccd14059b1978178010f71854eb2303f24a5e2e4ccca64cd86dfce946f06071ae58","nonce":"341e18fab96647218d577ab1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"a3952932477a21bb85b96ae45cc6bc500418d56b35cf01fbbbf2cf31a4edc37d10b6a3fee754931d5a23f17a72","nonce":"341e18fab96647218d577ab0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"c0a0fefb24ccc5493dfd74c209acc2ae6371deafb4c2a2f675b6a43753aaf5666349af3e27bd9667815b429a9b","nonce":"341e18fab96647218d577ab3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"e4ca2e00259b073d218995f952ea8afed268aadcb67a7ba4ccc09315e1bbce8a3986131a84b08875dafe5e858c","nonce":"341e18fab96647218d577ab2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"da0c4eecf023057890e89bbdede3a13578ad890f77d1703b3e68c057837298a2f90343d1f2ba9d7900dc168f8a","nonce":"341e18fab96647218d577abd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"5b6f2bd6b03447bf84b5f5a94a9d27fb45cd116ff366ebdf7261d6fe479c667560606938dfd228ce60dd2bcf21","nonce":"341e18fab96647218d577abc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"6f5411f5a7e1b10fc0afddebcdbf57873965ac8be03f03ca23afa828e8ff3a61ad7ffa71377a6cc06d1b3add2e","nonce":"341e18fab96647218d577abf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"15894143391179d2d19d910269726f515bea120d5df8a11dcacac5c320eb7eb87142bc668e06f62ed126343658","nonce":"341e18fab96647218d577abe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"9223970e1980602b1d07e837a6236307fc3cb6c077a9cb92073c470632bd4f0cae6985d984011c743bbe295ecc","nonce":"341e18fab96647218d577ab9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"b7ec69699037cb33ddbfa45991fba7daf91344490f22164eeb617beace268549847988d1b235f56eb0d17dcb78","nonce":"341e18fab96647218d577ab8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"4686cac2e2deec91201c725dcb8259f5d1fe7624929e60a8729503abf27a85e6c0c9e1a48508fdff64e6320abe","nonce":"341e18fab96647218d577abb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"6054df104c50e325bb6dfab43c22cc4e1f639ace6d57241c55ee2e3e6778d0378274b93523aef8d79ba406b59a","nonce":"341e18fab96647218d577aba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"e143512c9ea87b95339597de40c57a48d3ec9bfdbc1e58a7f7212e6eb2db0b00e85b59b2835300ff7be0a0a5aa","nonce":"341e18fab96647218d577a85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"a24d1d7b7fc63c25bb3af63e7dcd3eb885aa24a0ecbd97c5472623db6b753882ed83bbb6916c762ed46540980a","nonce":"341e18fab96647218d577a84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"77e850973486f871e74fd7b5277143fe940c0a8da6b63d0c3980100146f5a201dea6a6599a61376523776199c7","nonce":"341e18fab96647218d577a87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"3c2416244b4ed43a1499136ee5d59c1b859ba24f45a729953173c5e85b131e3670a797dd4b1d7afc5705d95e0a","nonce":"341e18fab96647218d577a86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"ba604852bfa35a97c16b25a62a2ea4d83c446630dba52907277c9f9df15f2cf679a99d5f92f7f1d7cff838ba39","nonce":"341e18fab96647218d577a81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"eb6c4b9ea18e16e26405b6c18d25ff58bda84529ae219996c2c8f3888ecb17d390b78c22562879972bbace81ad","nonce":"341e18fab96647218d577a80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"dad2e4e7ea1de76765103c2ffbc0d22752e6a084f77d7146e8a2da094855e651596042f76d62bd52b973a0b7ab","nonce":"341e18fab96647218d577a83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"b22a429112acb5b666f4787199c39f3d197ad78ee142a15bf3908173100d0629a33aa30a993598eccb7375b343","nonce":"341e18fab96647218d577a82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"b3cdfea95e75112affe897420e57b05c28163d155df38dd8a29ae34f327cb5c924e5a5180dd481111f43e45247","nonce":"341e18fab96647218d577a8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"e924259a62a08f3244ecd060478595c999f34b5b214ef36911a9bfe27aedcdf4411b505135503a0fcf869004e4","nonce":"341e18fab96647218d577a8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"079f737efdcff713d5fe89c9d84aa52ff7d4fa04f836e8c641d900a4db35d130d94ec0efc4e0fbe12d468cdf4a","nonce":"341e18fab96647218d577a8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"6ad5d9facc1f1904f8383a37fd8d9d67e6a84951170f035944195c1a6076ac7ab97968f2efb61d9f7ee4919465","nonce":"341e18fab96647218d577a8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"3ec9a1c1c1fda9dca1f5bf297ac032ca805814fb9603c7100977ac859bbce88083b92da7c9d12b4c104feb3dbd","nonce":"341e18fab96647218d577a89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"98068c959106d92eb7099a4472dc829cfdeef62abc23f929d8e2c9efc4088276fc310964824f593737a3b4027f","nonce":"341e18fab96647218d577a88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"3e49d60369ab142c47a645e841e60189c9592161809ec77d53c7e8191c6e939ea1e5e1594de8eba2976ad30425","nonce":"341e18fab96647218d577a8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"501cdae593820452b97835017809432943f32a0428e90ec04fa31298d09fec050b0585f0d01479bc62a812d4bd","nonce":"341e18fab96647218d577a8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"0f1867267501af93174b7d28ae290f68c84acacc71dc80d96dd64b90f76b546d1c81fe7bf30547d2d5fd327746","nonce":"341e18fab96647218d577a95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"d3a61607e4ffa49d8c84ac04c8973cdec9d8c48f48b5cebd8c6846b9b5d92bbcd8bec56cd4fd1a5c8b02a9b666","nonce":"341e18fab96647218d577a94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"a343197b196423328acf1a94484c26073a8dcc74fe18713fc6291d3779b0648eb2186cc8cf22fa287c53d45d81","nonce":"341e18fab96647218d577a97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"6cbcf00c18ef40190faa43426023687f8abb7d6a36aa28b3ebb62cb64141e854ed6f088abdb552b0e52f36f6e5","nonce":"341e18fab96647218d577a96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"19b4ca3fa04b33fe387ee361fb609f0f14ff88651508e27aefec9d76b684df08e965f27cd509bc8e0ce3a531ec","nonce":"341e18fab96647218d577a91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"69b70243ec60f3e7e656261e7825c61447b50d497aa3ca79eadcdc371ec3edea78ea08b4e4ad51851845b6968e","nonce":"341e18fab96647218d577a90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"4eca6f328ebd236b0f2c1ef1d079276eeb4a1a53707ccec6373ed7a52fdc7560749c18d3e26db8084e221a7fce","nonce":"341e18fab96647218d577a93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"ee94c56895a7ef6986fa4433b7b1f879b91bcf19c1bafb9c12976331b51ee76a8f8174633e2b25e2219ccaf317","nonce":"341e18fab96647218d577a92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"9fbe985edb2ae3f914439bb1bff983d27f03a17288d39099b7a11bf572e38d8b31a6b19a7d0e8b970863395837","nonce":"341e18fab96647218d577a9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"16b3472cda5a4a2cf3390c7b09800f7038105b7c1933443ab6ecb8d8e8f1cfc310f6580fa095b28ddad4779bdc","nonce":"341e18fab96647218d577a9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"ca1a11131aba1cb32a8e4bdb53e093a59ed50406fbba76d99500f179e7dd41a8273f23861556c1116818fb510e","nonce":"341e18fab96647218d577a9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"af74b88be5937a2303879ecaac4afb49603b261827dc5cd4b539d7485b86c6761d77e063a8169f6748308b8cd9","nonce":"341e18fab96647218d577a9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"7f0d23befcd7245222eef419a1e7dbd32d7514e77f7255e806ef754be31dd446f7707d2d2b8f9dae885f3f4d4e","nonce":"341e18fab96647218d577a99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"e96b41361eb6b1f6fcd6b06b7ad281cd0826c15b68cfb72a46b0b46ed4b926851f8f302d67b7ad396258928473","nonce":"341e18fab96647218d577a98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"794bc5d82c5959cbcedbd56ea3a04cfc1cd60400f87b88ebd5c3b2937f20e7bf4e06a082dccbf68e6f4bf9b148","nonce":"341e18fab96647218d577a9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"43e46249b8ae2ea116bf3a09b5063eccb16c47c7ff4a1553b0f87d23d721cc2753fd8da19b344c5530df10a8ff","nonce":"341e18fab96647218d577a9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"feecb0c6701d19c3efc26120ecec0ed78f95abbcac2bf450bec44dce27fc4f1034d4d4ab6748edf32a5338cfd7","nonce":"341e18fab96647218d577ae5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"c0092b7b1a2e1d0ec40af030e51a4ac8b8ea201767b837743d4b0e61bacef7cdc0aff1f787730c6ae8eaf73ec3","nonce":"341e18fab96647218d577ae4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"883ba52cd5ca63b9c7abe06a5d3a29cc43e45ba7717cd6727a7f77e93e834413399d691636d981bc90d90f4c49","nonce":"341e18fab96647218d577ae7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"be91575cd9c3d5457aeaa316957c9f72750175ad0dafb9394e9b6b48c18e76fb8c825b5ce15d713ff9bbe2ae63","nonce":"341e18fab96647218d577ae6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"53dc67b05c52815136400ba551b6311269a0c0de889531e81aa822bb1fde5959ca596f13cb2714b47f6c7ca8d2","nonce":"341e18fab96647218d577ae1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"5ee25936b7caf7e73efd5d2f7b58ae51ae68c816cf46f82b97e1474a0bab5dac4b87a88441e159758c502ce17f","nonce":"341e18fab96647218d577ae0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"3169da9a066149c17c11fa4c34c542c6440350343422139864b68154ff543ed0f813a874a68b79f242b196f378","nonce":"341e18fab96647218d577ae3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"779b90e16c6b87083a68f823e65534607c271cd2682e0009a44a5f4518b3f795db84ab780610e107420d01a485","nonce":"341e18fab96647218d577ae2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"d3f02bbd9a17d84423823e408d670d895b78613c49491974b0caf42e09665738e9d8876a9e8a7c64428e6577ae","nonce":"341e18fab96647218d577aed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"38cb1db850729761adf2bac94f1f8183ae7fa7e12f7a83e5b2264d989654aa91cd7f564f3d1e2a662a23a9e7f0","nonce":"341e18fab96647218d577aec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"bb92211bb180c3d3c546a5892aec91d658e8e8ae0bdb48c3a19a8b2429e62c9015da85a6e579148d456a3e7bbc","nonce":"341e18fab96647218d577aef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"917b88a9e56e24ffc63016163e74e1247862563b1e5ef62392dc0a9a7fa835865f588ea14d9e1106361ea4aaee","nonce":"341e18fab96647218d577aee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"ff0679e4ee0279c0f6e774547c58b69305f5212d186b0c787c1cfe1110c2c4b68346dd176cdbb069874d68ad4a","nonce":"341e18fab96647218d577ae9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"cc8936b749df79566cbaedcef5df3c2d97e2d28391ec1f7c18c7c6c8cd87712e7edd40a473137ee1dc82d45ff0","nonce":"341e18fab96647218d577ae8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"7c0cd9d52e07744f5751e52a86306ec208f67c575d62b2a7336a59711b68edfd08eedefc4941e55defe974ab31","nonce":"341e18fab96647218d577aeb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"0faa395dade0d4bd0677e65989563d4c8fb6bf9b1cef624cadce7d77f0e1981cdf54656463788837f9197de46f","nonce":"341e18fab96647218d577aea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"2acc58dbd5a158aa43e1b082df6e70f20a9ac95b08c611dc32c10d6fa2b06a8fab117c1c4ccc6931509dbd4817","nonce":"341e18fab96647218d577af5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"7059b99d24e84e95dfb5e5db412c16abf2a0bbdec8c23815ec12972b26748629985da6465b0b741bf9fc3c861f","nonce":"341e18fab96647218d577af4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"50057a197e3e634badb0b77bc09c68d6b9664afcc3006ff663288abf08c8fba4b192b09b4a239dbe5aede72007","nonce":"341e18fab96647218d577af7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"c246ac1931aad837fce120a7defe2435ecd5311150753cf24ffb494166cc88253d89cd577d885fd50aa7068b90","nonce":"341e18fab96647218d577af6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"513518a7b3661ca6e9b61499d903687aeb69969ee13a303f157064b26a2de7a882e3480b4e5b2b9e904bda05d8","nonce":"341e18fab96647218d577af1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"b3ead9681adc4bbb05139c3da368b1935898e42bc09751d2b16f334edb06d62b07d0b8d238838b19a422633c81","nonce":"341e18fab96647218d577af0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"44a88547d03adb42305b17e3a6a5de4da0f8fdc2af9dcb82ad2dde1923be42fdf93120b0795bb3555851609839","nonce":"341e18fab96647218d577af3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"c41e04d94cb7333159f1af65df0de5148f14ab234e61a59fc4c75c7406195745f7e339e5c97eec1cc3bff65c77","nonce":"341e18fab96647218d577af2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"18df6bef0c34ffce48f653e6f832671c33f1c847f5eb43ba2ff63b6d01c2a1b927b2a8c85f18979505d8474370","nonce":"341e18fab96647218d577afd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"b36ae6b9f141d3cb66cf6c20355e35019dcef5e016e7bd98ae7299ef769189de13039a805faceb11390cfbb3be","nonce":"341e18fab96647218d577afc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"b322121af5d4e41a9120b75b912684da7af298679f14e886d77aaf98a9be586309ef4124826889eba41d78fec9","nonce":"341e18fab96647218d577aff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"b3adeea3e95389661a014dec5ae41b2ef63b11ddbee20018aa1b1501aaf8433184dea1249b0b1f00e815868a40","nonce":"341e18fab96647218d577afe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"75c74123100e4706a543744852553f375d1728ab6f3fead6f684c717f5035c1f707d5aab73a3da62b9debb751f","nonce":"341e18fab96647218d577af9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"8e24364b8a6a397a4d944523342009c999b8a4aa1fed25fea776715ede1c0c8a1dd699b1ce3257d4012501f6bf","nonce":"341e18fab96647218d577af8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"b735ad71b0e49ffa514be2d493ed7ceaaf35941a68512ae6fc73d54f0f9266f7631a5f980cb014fc9eee901fa1","nonce":"341e18fab96647218d577afb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"f7191a01fc54db9d15f6ca20357dcc9699b0427ff359be3f90caf80697648ff7215bf4f55049397b56ccc23f2e","nonce":"341e18fab96647218d577afa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"b9f4f2d36c3a3f3c80a8a5e4b6691cd7e6c575fd51c988c1ebffb9ff841e98f32d63d3bd4247a1870e61d20743","nonce":"341e18fab96647218d577ac5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"a400372181e7c0b8e146eee8b0abae530a233c109d9bb40eb8db4379594ccf0f34eec77aa720ed84bfd1af24ef","nonce":"341e18fab96647218d577ac4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"f7d29d6c57ef74ae064340c3a758706993d34e2213592c8cc777937ac2f35f696dc1c55b965306bdaffaa36181","nonce":"341e18fab96647218d577ac7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"39ca48d4f944d9e938e0da0615cb86739fa3a025d4fca1086a224251d0d7a6153891a66d4555875ab46710ef08","nonce":"341e18fab96647218d577ac6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"0bf86a4db61d8df7b006539b51ff5cc3281b7fc18052a6506f0e369a29ceb1a03980c39855e76ae3e481dd739f","nonce":"341e18fab96647218d577ac1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"9373b580df8638160a50ff89ace9f13ab571e8c2f280a90f4d155da6acb138c4443d43ebe39d5ef961df340c83","nonce":"341e18fab96647218d577ac0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"ce88fe4ce7db963a99f69dee7f2575ba26cfd55cca382e9857ae9a67007346cd110855cbfb45f10ce2a6d165b3","nonce":"341e18fab96647218d577ac3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"832280504890e96d522188028b78a80c0e6428982808a3591cfbc610b7b305b35a5e550347d48b77e1f9381f8c","nonce":"341e18fab96647218d577ac2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"a0a9e974f32a9ce6ab1353be003b53b7c73ffe18d8a248efd157ecab3d5875e383da144c84d99c745493edb16f","nonce":"341e18fab96647218d577acd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"d4c87e3c250f84d2f358cbafb5fc1ebdae6912e57e5f3c9e829d02e580b361cb95fcd4d11a98f4a79c5c2ed7e2","nonce":"341e18fab96647218d577acc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"281eabfee4c7eaf1e9f50d48d41d6eb8893a17c65db9fc509e524389c172ace2f05c6159d5d5c29f834982c24a","nonce":"341e18fab96647218d577acf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"864b4d1c27fcc441ad28c5c17431396cf6e8e971a5991d8a138b7c9780b056c1b3b8408ad810d7a236b0bf790e","nonce":"341e18fab96647218d577ace","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"5004315411915b75cc57f309ba535348cdc376f1cf31941d2cdbb7f84557bd249743f8ff44f2076edfe70f2402","nonce":"341e18fab96647218d577ac9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"6cd36b94db2083b1f8289e4a8a35badea3a5a6a7b1357d91d85a8bc72a30aa1952cd157b2fd135033af57e9889","nonce":"341e18fab96647218d577ac8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"859f75c3884496c770483725f60ab2f217a251b25f62b7c7891559143057a41e6430d0f6e3e6bd22ec2a34cfeb","nonce":"341e18fab96647218d577acb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"0bf427903a52f7ee182f67fa60d45705c8634b3765c672951271485c93426e10c60e1c48237929b76889c4fe33","nonce":"341e18fab96647218d577aca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"ae721844766abcc26590f380918f29510ceddd004c2e36c7daf63cc06d1a78104db2f1def24799ecab971e60c1","nonce":"341e18fab96647218d577ad5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"9d11cb90aad869535643fc330decbdf99911e2183d6921deff543d9191db0c2087e890d23d80a25b2124daafb7","nonce":"341e18fab96647218d577ad4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"4da24b2006c35867984b61c6b2ea8be484505c3296f7e4f38c99489fb8c99ab3fe8538b77884db8cd8a62c88db","nonce":"341e18fab96647218d577ad7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"b4ef0c2dd71b292449d34596e7569d14a793c436d8b39a921a22a4e6ac87c9f9c2c90007b6e58724757b4f27e8","nonce":"341e18fab96647218d577ad6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"66d25deb44f24178f11c0e01722918cc53b2730b56e3cca2267bb8d831349522ee0dd12f9713022f2e0645f11a","nonce":"341e18fab96647218d577ad1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"fee8caea59beec2ed1a0de45891a3e22f480dfef1863377fd06ab6e26c73ebed235d39669f8954dcce0ee39529","nonce":"341e18fab96647218d577ad0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"200b824c0a31d441a2f4e921f9262b726d265d10ea6f67f716f07e22bc34463ca54d6f9d8f55d84d6423b287cc","nonce":"341e18fab96647218d577ad3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"c7575ef7db4e05d4ca23547c4a88cd697b5be7bb07e1ff90aae1222a29edc5778c842dc12c17dc6acad290ae24","nonce":"341e18fab96647218d577ad2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"46e62072e7724d716225b2d947da21250ab39b8443c05369bc2d4198435470c602fbbb2e89153f8790f5cfb7fc","nonce":"341e18fab96647218d577add","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"f84422524cbb0238fecb7452aaaf4bcd1230ea4979595607d888d265179ed51b76150d91b120bb15d3b6767c5e","nonce":"341e18fab96647218d577adc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"11a1abb30be8e0e51ee12c6b12ca6470723c7fa17876802af3fa2a0c505576aedf3d276d4184de56f350108fab","nonce":"341e18fab96647218d577adf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"82bd07aa69cbad3db18de73a38471694b4ce0aa5f646a51d985bb231dede63e4487d90baa67bd26dc04a2c9220","nonce":"341e18fab96647218d577ade","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"e1e54138220b7eec8dc24cd37387951c7a2a83776d630c65dec916d9ba38334cb49a650160650458005c75d708","nonce":"341e18fab96647218d577ad9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"4d92651bc870a6119ad33bd428cc19648fa96e68ac90edf2d922fbb4243a4246ce114c56508ec0621764de89cf","nonce":"341e18fab96647218d577ad8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"aabcddeda9fba59a686801f49dd5df9d093c1c2d45b7879964b90b3c695407fcf916ca7d7f2fad39c6d150c544","nonce":"341e18fab96647218d577adb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"7de30af8f2dd635e8a83a06c32108a5c7604ca5bf8f5ef2d2e49005e5a97b3822ea650668434869049f64c8d00","nonce":"341e18fab96647218d577ada","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"12b57b0c5241ada68b1a257c6ace0cb189692f765352094b89316388dc3fe46b37e4deca1ce84c2b370e2b30ae","nonce":"341e18fab96647218d577a25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"2dc83089270632bd4c3d26101732d8f5238a42afe4de6ac5e4153f1b4ea8f6ffc16771b5dc6c1b46d92784ba1e","nonce":"341e18fab96647218d577a24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"2b08476b68768699336fc98b6359c3db0b9175fc3900d4d852bc34026b306594a47b23f029d7a38f699acbe8ff","nonce":"341e18fab96647218d577a27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"4a4c975c14acc480ad18ab47791843d7eed86c4eed819bddd65c785664549349dd939ab9346846f7e590403139","nonce":"341e18fab96647218d577a26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"d1b2f984ba4fea5a947170c5a680906d0caf80621df286aa610c6e0ec787e73933b048726318f1fa6dc2816a00","nonce":"341e18fab96647218d577a21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"0a876b30ef8970386a808128f0302c67e6fa8d62dc745bff0543ebaae6816decc920561125c644de1471b53d48","nonce":"341e18fab96647218d577a20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"d6d76fe1194b72b65bbf16baa738468ba1936f41806bf8bb326f30a088bdc807a0125107d88dcbcc70fbb373a6","nonce":"341e18fab96647218d577a23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"f910d995f6cc7d44a1d66ff138a527a8788b43633173bc3d2d9f2f3ea2f8325459addcd60a1c290c9cec23e724","nonce":"341e18fab96647218d577a22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"07a87607d7dcfbdeadc40a35bc506b65a438e63ba71b61ad80e75df1279d95fd8e21b6d62580eafc2d71707d02","nonce":"341e18fab96647218d577a2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"7399348e6ca006caebff1b4fbe77deb930414177aa636d164d4af9182b6af6876881cde2ab200c8ad3ed092662","nonce":"341e18fab96647218d577a2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"b2cd66f7373b42fa557f1c33f7c88e3b2dea110952f9dd38960159946fc25847e81fe883532d19983d91ab2458","nonce":"341e18fab96647218d577a2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"f42afa8107f513e916e5fe2fbabb670d346c74c787cd44165c0fe3adf13bf7f38b359fb322242dba89ee432567","nonce":"341e18fab96647218d577a2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"df5fcac429b0be37e6d4e2799ab371787f37553585ac982ee2830d33d9a4fff727e0d63208b0763127bdafcf25","nonce":"341e18fab96647218d577a29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"1d0c894a1095071e8ed500a6f6c24959a9f751e1736b29318e698c60d577050111f0c22d6d9b60c915976746bc","nonce":"341e18fab96647218d577a28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"06ec6a547426d81dae14b63ca3e9d11e0c611c3a054067a397fc07bea4c9593482827542c6557c0747ef927b19","nonce":"341e18fab96647218d577a2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"5e9b3b65bfa9e71f04be860d4217ace2a57b96c7d68e7b808a16ba231d4ecc0fd423b99f907dc07a562cb34b94","nonce":"341e18fab96647218d577a2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"1077cbab36d31d09a6b388056c1d4ed0fdfb8ab4b81623332d8b195230402b8e86f8239b4cc7378bcdfee5ede1","nonce":"341e18fab96647218d577a35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"f9fab8764d0b7fbff820c38c282e12a1c3a0c28ae4448a410b6220615c0a7f55466244b4160dd7a80835ffa932","nonce":"341e18fab96647218d577a34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"2941739ee9e08951bcc73e654ffe63c9e2e0776b66a74708fc3c0b1547753014281826dc093f1cf91e55ed583a","nonce":"341e18fab96647218d577a37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"e22965a8d0c14c21ca6b4a7f9d5c16400af85c13168a760166ae855f71aed96198804655984bbbd148f4116f88","nonce":"341e18fab96647218d577a36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"fa4dcc7a40762cd7b8740b10d16338f7dbf8291080d35fc515ec7e06a989976d8f0226a018b3bab3179a6ffbe7","nonce":"341e18fab96647218d577a31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"21c75a063c5c9309dbabde89606b7fa27144dcef7e2a1232d1f040d19f1e79e2a36a9fb8407ec57edf909aec98","nonce":"341e18fab96647218d577a30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"ddcd9ed4fda7843626b60fe92fd4c9dfbf59f4401074852bbdc272e652c70ee2faf4a4c91c502e1832f7108fbd","nonce":"341e18fab96647218d577a33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"2b245466dd12fd223aee4c06614b04c2e6ff100a5399e7180408460393354f7ec234c211031937b0bbd9543c6d","nonce":"341e18fab96647218d577a32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"e50f90a850dbda2dc112dc21774b3d528b527083abfa609bf8187ca7e4516c1b76e8cf6be0edc190d50e8f1516","nonce":"341e18fab96647218d577a3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"a40a2956f8c75cd095701dc0d1f578c93688225dc71ee8671d7582de51ba99694e19210491888b40cc0ec439b8","nonce":"341e18fab96647218d577a3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"9f0594e96a9a78895fa9917d456ec8659fae27b82d3f15823a20cb678454a3a4107149084156ab0a8c98ac5b58","nonce":"341e18fab96647218d577a3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"270136aa7e6810312b43b80d3e7c41f2a0e5f022f4b2c7e6f8a80a32eb25ab354d79ef25a0b8332e15be360fb4","nonce":"341e18fab96647218d577a3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"b9b21d2ae19bedf3fc77cdd9f713f90a723c85e5c3d28eb0d5db6c12265e583a49abe4466748a3775318c06782","nonce":"341e18fab96647218d577a39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"23ceb7748b20aef76731f60ff30c1e3230f821d193b381c8074c36b3e99190e91745fba1389794020157ec1e4f","nonce":"341e18fab96647218d577a38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"47cde704c569e28e8af3f1bcdc10f7416553fcafd614d816ad24fd01528f38bead2b022a7f927b946d1b0fc4e0","nonce":"341e18fab96647218d577a3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"ddb920bc75d86fa0b4825ff65c270e747ce15233a3ac4e7d0498cb2b0d9b05a34c9dae717012a8f19eb712c6f3","nonce":"341e18fab96647218d577a3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"ce54c979494e65aa53e1397563a63f3a455976c757ebab15a4ffb123a23e28b70af38887353a5e0cce8e29822d","nonce":"341e18fab96647218d577a05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"e4c30c39b19260d1423c76f8ebea9d90d19579a52028fd676938545a69d8901877325fae86ace36b107bdbea6e","nonce":"341e18fab96647218d577a04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"0a0dc14a6e388337725996594c50d63d1ad2d6eb07e9e9a964b0bca6260800a327165e97f2de1b6a67dc0407ff","nonce":"341e18fab96647218d577a07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"c35f2ae15ae5c19b563b28a89871f30d7e2a1c6946067d87cfb6266440e63946cc065b05fc52cd775bc350dba9","nonce":"341e18fab96647218d577a06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"5acdf625cab35e9c8de8aec636e399947b8b7a3793273864c9e96b350860a126e90f5acb166a35fe97299aeb70","nonce":"341e18fab96647218d577a01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"e0d42d45aefdd0b4c4075c9641c251326217df560896be5c3cc5d225cf1c5efac1996549f50cd843070df3f7bb","nonce":"341e18fab96647218d577a00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"34f9ceb9c1a7c0ef893dcb2b28789324dff01b226a0542aea1b45388e5b5a140fb0545574e8a0921e353c92d72","nonce":"341e18fab96647218d577a03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"7fd2233d39fccc49feb0076a9f1e108e574e33922a485184f71f01179d368a182a7208dfc95f2221b1472a31e3","nonce":"341e18fab96647218d577a02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"8071b7b0e713e9bf75b8e933228dd1d1edc13665c498597b0c65de69342b0bfe8a4278e39dc7f4bd7d9fa44b54","nonce":"341e18fab96647218d577a0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"fe1a828f48ad288263c29bd8e8d50efc84be19a51c59b8a300f165e43d5d5838543353c4e024f96d6b648a5826","nonce":"341e18fab96647218d577a0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"058178e47a50f5b45ced51f7f3ba973e5740cff46815ea71d5d2341f63693f195cda8ea58095683e406c581b6b","nonce":"341e18fab96647218d577a0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"0b36abc22926121f057ef01f2a7f170d169a0d8c8f599485166bdc48772b6df118c67adc56cf0d56fc75e9a2d9","nonce":"341e18fab96647218d577a0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"af3b2c67b54f03d387c6c14151b7a5d0eea9e44b54644ef8f17b195034041db0ceb2c52b7cc9fdbb416699f903","nonce":"341e18fab96647218d577a09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"960c0485aa46d24c3a40eb97682de08e7c0b669dfd6053d52e8e4502f3bca0480b4bb15b00efbc6b9139ca31b0","nonce":"341e18fab96647218d577a08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"c57d0fdc63953422264a7e401f1cfc4b44d23f20c57fbd62ee2fd1a759ba704903fc2d7e95f24165ba057ab6d4","nonce":"341e18fab96647218d577a0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"2873a8b5b86cb31b92bb631e33211f3a88c2950eedd23139cbceaaf4ed08aae97da663e82467dee72fb975a4ec","nonce":"341e18fab96647218d577a0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"d9fd7644bc0a3ff3be0344bc353608cb195b0f04f3d6ead5cf8f6cf2d96145bc26f6b074ba06e41d3c70c52874","nonce":"341e18fab96647218d577a15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"99fee2d27db53bae4b578dca2649c45348c9d4409d4bb71765134564d7c708aa1598d9532f165e36a79e2846a8","nonce":"341e18fab96647218d577a14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"0d5b33b3853a9982979ea9c57d261b967ec4bd603e63ba524aabf4f81188c78d08585099aad5882c24cec90b42","nonce":"341e18fab96647218d577a17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"1eec141a9715401a113a6698dc9c6873a10483910287af0a0a32c0d7fd8cbf7923b73cc850c953ae48addb2133","nonce":"341e18fab96647218d577a16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"64563633a2cedd95bf9d08e3285ef9188ef6bf5672f06b9d4561f30acbd7c7b703db84d04d50ca5fc580dbd244","nonce":"341e18fab96647218d577a11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"09006ee0f0bc8288f81d625ab13bce4cf88181414cb2c4582b3ad7255f23881082fa84d3f391b18dfef320ce41","nonce":"341e18fab96647218d577a10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"cf191cf42b049cc1b82cb94b0c97e145517e585a6eaf2407b7e56c534d1dfb76fa624aaa1be5d1d608b4d7ad29","nonce":"341e18fab96647218d577a13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"e29ff9968de9551bb46bfc4376ee535b6402c2c46494d2cf57a098f15a5fc6351bb264f80a9d0426e9d0739301","nonce":"341e18fab96647218d577a12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"da542242f075ccb210af24b62c6b81be18490162b92689422c60f73724d24528092b34275e9918491e538d3d61","nonce":"341e18fab96647218d577a1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"c434e49492fbfec14845c836cd4e356873337dbb78e65e855545ecaabfbdaa99378cfa060f8f6036cf0425c5fc","nonce":"341e18fab96647218d577a1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"a2df5fc2f61d611026449ec5d25d804460c01b454eb41a7eb6d0d9dbc09207e9c1756168afa3881d38f8a46b43","nonce":"341e18fab96647218d577a1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"5ce96af0e6caf2d273799b74c6c21d0027a13c7214a23b0391886099c2a4199af7dfda025368e888fb54154dba","nonce":"341e18fab96647218d577a1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"a20ab333b11a9df26849cdcdd028b3d709fa51d6557927c443aec20149664a64983e53f3182af4efb3bff9803b","nonce":"341e18fab96647218d577a19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"03be1335e06ba0cd3a00547de75fede2e21089cda02f805c5b48009b8dd9475fb3464cac86acce3938044e1f4d","nonce":"341e18fab96647218d577a18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"d126a97440c509eb1ff465a580b287e39727a16d428a47e0b7b9141971f2a667b14bb658cf95202a69a0349e18","nonce":"341e18fab96647218d577a1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"bb5e2e5c43314045d8fc88f4bcf7f5339d4ce6b6c8100417520cf517d4564c2ee16fc78fc56fba54c2f52b5071","nonce":"341e18fab96647218d577a1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"19002c8aae080fd0e18b006220115cf95eadf6776e043aaa8b6622521a8a068be464f8a036f2a14546a628daf8","nonce":"341e18fab96647218d577a65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"906ea932fb625d115aeb08210ec5ade100ac4084ac7d3657a0eca8c0a4744861c6ecd906f3fa2b32b0010e827c","nonce":"341e18fab96647218d577a64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"f9c238efe7b151d44ab9ab0c83f6f3e04a70a49f02c8cc26cd18ba23945d8ba7c3c4b81df3ee9099cdd4228c10","nonce":"341e18fab96647218d577a67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"f2796a8d8e52e1375f304a31a7cfc15282772174435376ae27efe087550cda6309a5dfe99f4b31bc619fca2325","nonce":"341e18fab96647218d577a66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"f1f85e7aff7d885e418849e2ee095d50273c537e22e100556db62ae5910674724c81819691908bd1f8db9308c3","nonce":"341e18fab96647218d577a61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"5c0f20548f437d39e309f48da86243a86ad88ac49f5b3453e8f651cddfab8398720415e4c4cb06490ec9e85b9f","nonce":"341e18fab96647218d577a60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"f672fdfa715635f6f1bad151b0b7fbbb16cba74f33d0d0f845bec04be9931b7b9c31a1ba1e6b6578955b061d94","nonce":"341e18fab96647218d577a63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"28b8b78ff78731400df0bb0c2dce01e24eb24d26456517e48c148b964a5e660f5e0bcb70c6c7fc782be91027e1","nonce":"341e18fab96647218d577a62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"d005b11407ec63ee3d357d277df89c78445f30fd8d521e2cc46f96d19c736d35cb578f1f75f77b6de4c1315b1d","nonce":"341e18fab96647218d577a6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"0cc43640905b55f49281653a1e1d039d0eb7ac2e8ae59371b0ad13c2927ea5804744e52fac7252fe2e7cd8070d","nonce":"341e18fab96647218d577a6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"c070dd488c89829dd879433c61d455831d2b9f08924ee6bbe5efbee748ec6ef30ffaf63fbc4fa869fc49a71f8c","nonce":"341e18fab96647218d577a6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"ced81b40fff9a522c379bf6f70642c9be852689155cb8795e3574b5c41a79bf529940dc90b0b4f8314e8f1b281","nonce":"341e18fab96647218d577a6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"2a3589006021d40a1bfebe94cde97c6a755f97d995eb7abe23023db99907f295d889b162a5109d4f87fb83a317","nonce":"341e18fab96647218d577a69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"953cc1ac52f187437a57dd285dcdb984f8d3ea8a5f0d10cecde0cd50c08e3702665a32b1dfdbdb44597df919dd","nonce":"341e18fab96647218d577a68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"90076ed9fdad65667b90f00908ae3b573175fc97fcf0afcf7ab3372d3e66fd31ea0cf22a119b5b1859d98b22a4","nonce":"341e18fab96647218d577a6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"4c30d5cbd6ba02ff7c97b7b619cfb93fc65f6e17b5658a5273f135d75a3b7ce56193869c73cea3682caf0d7ede","nonce":"341e18fab96647218d577a6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"6d97ab9c2de7322e68d96b0ce0404ebcc8fb2cc5a3c592bf0bb11d3421ae527a37d0f83c4436a22342c00bae18","nonce":"341e18fab96647218d577a75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"9138365912d553b46c759735009fbccbb96b922abbecd71c3f10a90eb62dbf66a3882ecf10a577f10a9546b26b","nonce":"341e18fab96647218d577a74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"8a018d1b14db40d6b39e96286d30126d7ad691d1499d6af841f8e139c30bd7c741f5485d00974122a2f39b47b5","nonce":"341e18fab96647218d577a77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"ed9e0a8dd559dec4597b3a04430c4fa33d192cf10ac9f887fcce04d2c7a72ccd55fc628d215b98b6bc417b3edf","nonce":"341e18fab96647218d577a76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"b8363a6ac357e2c8eb82875c6d4e013303e27e0964b50af720f3071c3271d9b13f2c1d7b91aaf5f57f6424687d","nonce":"341e18fab96647218d577a71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"617856a1cb5c96d822ba13b7aa458a85658be1097de7d510ddda5a17046b7d108732de14d4891e50c11874cfd5","nonce":"341e18fab96647218d577a70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"c8b920e1530da9eeb3a7c11a2622893afb947f6b9f0197750c1320839ba531d7eca83dc97810b6099a5cf30a17","nonce":"341e18fab96647218d577a73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"ad5f1a181f9646ce6f7495e28e7307265db776d5139b9e48f37113483165c498f8804f44490629bf4d6ee8f571","nonce":"341e18fab96647218d577a72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"9919a8ffeccf0b03d9152f9ca6664e21ed0d3f7968b24c5530754949d6a10fd125a1a9436c23b753b121ed60ef","nonce":"341e18fab96647218d577a7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"9dfbe16791d23214cec84100d6a84d082ca3df3aa1e28a978e9b9e0c0f14637c55f0df6d695e96990a5193c959","nonce":"341e18fab96647218d577a7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"182081e4432770e680ed6e3cd841eaebf3c2bae5f08407f0c7871f6b8bbe0f701482e062546991fbe7978aafb8","nonce":"341e18fab96647218d577a7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"36a15b51bc377cb96917277492e2c406cbe9525d0d6edc93e03eb628abc293a82613a8c0e89c51252e26388e91","nonce":"341e18fab96647218d577a7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"264b0b87dbfe811785cc39be79c6dc724eace0355dcc4b55f5f91672f6fcedc4dfff935befa0e010a1702f2e1c","nonce":"341e18fab96647218d577a79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"0e1185f63b090604fa0933cf930449184ead6179ff27d91be78f901778a3c2fdd10dcdf75c0f4394944209558e","nonce":"341e18fab96647218d577a78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"a666cba94ca6484e14a2dd77318031603bad928604a80c1fd1c2c84e47d667f85f6234dabcf37b4db3736e3efd","nonce":"341e18fab96647218d577a7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"e63756e0fe61ab7f0bf9a232c3626f5d407d56c8d6832ce3873909089e1e1b0ec9bdb1c1dae3d9d7d957ae0a3e","nonce":"341e18fab96647218d577a7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"8685a4c20f44505d8edec9f7f0d6ff60df745df1884dc1e0b697d76d6a16e0de6016785f75b8577a5b558f9081","nonce":"341e18fab96647218d577a45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"564eb7feca1b56cd9da9804ced55554b3ec865691e19bfbad324a181c10fe42fb7db1c9f6dc4d5951d3e168630","nonce":"341e18fab96647218d577a44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"b857bec7a90f1abef07625fb387d988c01903039738d5a8e345c58e0785f54ba94d1e4e7b5c943cd98f9201cfc","nonce":"341e18fab96647218d577a47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"94c3adf4d269934b5eee5e68cda5da12c198e33bfda7a3ccaa26eebbbac12c80b155a18153e0131aaa4b7aa911","nonce":"341e18fab96647218d577a46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"2fd88ab2ea00e4b226c98ffe66d83ee5a38388c3b8409f91b3e5760c1c2de2666db9e9a53ed4f44bb9289f501a","nonce":"341e18fab96647218d577a41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"3ffee8b781259d35d4a8b4fa39549bbc273ae74cbfa5f5189fbade1e750bf7e08e195a3609ed3b4c62909dc466","nonce":"341e18fab96647218d577a40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"103d825d5675d5b99d564aa04a734122ad4104d1be44bbf7c76f7cf577a29fdf9bf2408e23bbdf0cd3a66f3fed","nonce":"341e18fab96647218d577a43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"eb972f9405cdec596b99ae4306d3b929733dbad0bf5f7d3878e64fe2800d6dbc6ea433651bd2c410767f0f2212","nonce":"341e18fab96647218d577a42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"833de7fed656fe78869f442c9efdd443d7b4cc3ee17b72662af87868fc84c7ddfb095d6ff3485d1b7a69f7fd51","nonce":"341e18fab96647218d577a4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"8a2ff2d1d4f842c10f9b635add65742a5cf0b4d9c2e19c3789bb44e07b7a170a8eda5d341328f23608479b6fe3","nonce":"341e18fab96647218d577a4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"0e943af974cb4fb5b5d358ca8d31dae15643b3e37c8a3119279b15b426f9b55ad3ae334077f6c71d03c7a8c3dd","nonce":"341e18fab96647218d577a4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"c14ed2886c3be34fd6f802551ec98cdfe996afa978035a93c4b3078531720a6d9129ebb08d88c891d421daadd9","nonce":"341e18fab96647218d577a4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"582f1a3e6c15bf14d5a8afdb4e116e08f95b67d4b593e1a0be5f7a15244e5c70100685afec7a88dd046c300a18","nonce":"341e18fab96647218d577a49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"8d4aab298befcab95c46844a07cf6e960f67b19bd60f9abd9fac81a4fca771b04c2bbb4f4e4da08e1084abe9ab","nonce":"341e18fab96647218d577a48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"0361b056136cb0c7084dd56c905ba6ac899c5858b819568060aaa599b5dc1a3c9e0ec64b335b404ff055c27170","nonce":"341e18fab96647218d577a4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"b46fdfbf10c8b15f25719b66c2a95913dbd7cb853d942cd6407d2cef4870c78763fe5427989234e371b3d16881","nonce":"341e18fab96647218d577a4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"bbef992582d903683e5707db8250176a29b65cf073f308e9831a6a9c50d5d1f220c7084371bd98a58a829523be","nonce":"341e18fab96647218d577a55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"390c3859cfa1246fdb489c7d161581180152ad34a1f4d3a59aae87266037b2dfe5532aab32f9317c883b9b485c","nonce":"341e18fab96647218d577a54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"63e5bbd7ced8301c20d780bb0b6357d417ef627fa4be8ddfeba4a358d7af41351ab9afc8700d8ba951115d237f","nonce":"341e18fab96647218d577a57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"945db61b80c4ca44a5c99c7f5ecce364214a3322a0770db848041ad630f852137bad82eeb03242c544a8954b77","nonce":"341e18fab96647218d577a56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"bedc1c28051301cac6a3585aec30f6aa29c412d31f12a8a0caa82ff361f7c7b1c98070196e0c03c227c13536aa","nonce":"341e18fab96647218d577a51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"e10eaa24ea0138efcc5156538b4d2c3a45bd087b023331c01d4e3bceadb65685a154053e168e7606c6605cb877","nonce":"341e18fab96647218d577a50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"be7555ab726614edb9d4c6eedb3cbd8a70debd51a1fe505a666fa60bdad5d91d60e69b60912b573bcd1e0203cd","nonce":"341e18fab96647218d577a53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"1f7d301572d1efe48395dafd3c7231af9b03c89798ed57254dccec92c6373176cb5f07db155162623fec872f2f","nonce":"341e18fab96647218d577a52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"c8dfd94ba73d3bdd70b5c5901b659e559fd8bd48d964cefdf9f8a11c6a6c60ce7eb240eee825a00d837e66f9cc","nonce":"341e18fab96647218d577a5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"14def56a79e2812e657454bca615a3e599200940f2dedc6383841d3ac8760c15cdac03e9583c249395502af56e","nonce":"341e18fab96647218d577a5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"8f19885ac4c75a7f0016f9c713e1ea3d738c789a532d3f45f7a0c3f916d525984364b3c3e9f7a3112fd0cc7af3","nonce":"341e18fab96647218d577a5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"7fb8d62e7366342ca3d7fd1b04bc660ce748a4966e0ab4dae44b2df1696369d4611a99cf2878380aab2b85f7b6","nonce":"341e18fab96647218d577a5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"2c9d78458a34517061904628eeeeab750c1bc4323120776f642a3d9e262306a6538ea49861871d8a2bcde65be9","nonce":"341e18fab96647218d577a59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"3f3357ac6676907d64c85382bb73e9a1f59dac0f41f42849b5451d3a50ed4f08df8e4da28bcd3d5f60ad6ade47","nonce":"341e18fab96647218d577a58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"3c25be20ca4ca72ac5574b97b400ddc985d004b2990e0f938d0d102b7ace5b299cbb1bad3c2a577af82c55716e","nonce":"341e18fab96647218d577a5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"d1a664fe58e56ddeb1d1cf88db9d85b3501f2a9820c55e7d0c5242f337e6f621ca2a3f09880d64441e5f5a2cbf","nonce":"341e18fab96647218d577a5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"7bbb570a44572285f8c8378b5f12051578fa3c400f076ff03f7200c9280674efbb11f965ef6838425ff7475322","nonce":"341e18fab96647218d577ba5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"70c5e509321b56c40c40ddc4bc102ed78693da5e66cd9aa12dc92074202b299a"},{"exporter_context":"00","L":32,"exported_value":"6a4ea42f1356465887865b634df5111b70ddcef67e5d7f626641c03b6007bb51"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"acc0f7207b16cbb3f9814d5408a57300b445dbcfaa7142cb94539cfcfbc1558e"}]},{"mode":0,"kem_id":18,"kdf_id":1,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"60f9f3887a1654a039b247306180a9ef282b1e3fde3063c66ee4c8f896d662dc8e1f425e5de290da6efbab40242af8b6a95653b536d1784b1693510af60ae83cc597","ikmE":"a90503b35b1e73f01a02464bc47b25d6e3d395e8003f95e181e42fc485abca2ad3ab6532976491c4c0acf1d24458ab1a7a12f82dc0c3253dab378cb270cf6db6a228","skRm":"016ef32d03503adb2639acf0453a6d9b04bff192cf30080720ff383d4831e10e4c7a76a6a00b13ad38db6fbf2de9f05721b8ee0315991a63e40b605a5429d672e6c1","skEm":"0118766e70c87dcc0f69877d07c486cde0077483f71f5d9616c8e3dfe0e2253bf16ddccc2eebb76dc710f09e09a3fa9386fcf9af40de5b9db810e956da33dccf839b","pkRm":"040189d38c94ae31bf4ec367dad0cf49c7b0d43a3d1c140ffb44635dc41c231175390de233c76e4de6b024bbbef89af3367c8e4f2c1ecf449fb7261a3a68553bb3ca9800d292d4d1847c1e78f64a8226b4986880b3e2178323ec63a9035c18cb95025cdbd30c0d48eb153d08b99309100a703ab5fb3bfa94ecd5dd56a8c5a0acdfd0b8cdcb","pkEm":"0400e5cd75cf0a8d183945552eb2059beeaee75fce647ce45c63f47826f5d6e84a976b0bb4d7a252968c3d7feacce7e1d34ba0f54ed85e15e6d39344aef05bdc04c28b011f79379c09603c99784805f7552b6f63a2d45f252b969665cae5a2244631eef22a1a420a1c34fd512688b5e0b17e04c20ce6bf37314597b17beed1e6b0844fc60d","enc":"0400e5cd75cf0a8d183945552eb2059beeaee75fce647ce45c63f47826f5d6e84a976b0bb4d7a252968c3d7feacce7e1d34ba0f54ed85e15e6d39344aef05bdc04c28b011f79379c09603c99784805f7552b6f63a2d45f252b969665cae5a2244631eef22a1a420a1c34fd512688b5e0b17e04c20ce6bf37314597b17beed1e6b0844fc60d","shared_secret":"7c7fafbfc74558f448cbde0c4ebb06e1ab7efe5c7f1e55c163dd6712c7c40c0a235d24090c9408c718969e08230db61427624969c75cc2fa4dff23959b0ad4a5","key_schedule_context":"0032e749440c54987db01af606efdb4d140f0148ee254795838e2d23d4366e1fdd97e18b628ea977f60a69bfa0647402182d019d3a0b59d2dd03624d028053dee1","secret":"4e8413a5f7f189776ea8a81ce38a65f8e13929b7aa1a77f9b157cda072e8c4c7","key":"1688f85a2143bbd4a3b579f59a4cf004bb5bb876e8309fefccacc640ece2c6c5","base_nonce":"6f1e2e1cfc737b3ec001f73c","exporter_secret":"5b36dd5ce4bcd9c6ce0f7e45460288354cee5bade74981939a243eb81c313c19","encryptions":[{"aad":"436f756e742d30","ciphertext":"17e50b46e095063fc350d0b15ee082f3e39a68f2659a68aec7e33d83f22b6bfb231dfdea2778e6c6833eecd4a8","nonce":"6f1e2e1cfc737b3ec001f73c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"daae4e4f88550d6cc2998d4880f3215cca1a90fffae83be761d0d2d8ccdd534aa77a634bfae063f02541d03d36","nonce":"6f1e2e1cfc737b3ec001f73d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"66bec388eb2615c8639336251bfbdf29dd3781e9e3d41e24c60d0140949b16a9b3bc409451414a9fdd5179bf86","nonce":"6f1e2e1cfc737b3ec001f73e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"bee3e32f80ab9870e81984e859918d0edebe30e285a20c8cea3296c49597b5788c6a0806357fd301b9a81a2832","nonce":"6f1e2e1cfc737b3ec001f73f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"b726af744e1d1cd3dcf68c5147d6bdc5db4a6653cdd10254031c531f4e4352d574b28aa3847b9195f24ffb5c95","nonce":"6f1e2e1cfc737b3ec001f738","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"a9cad63a714cd0711f3de2e45aeb3d3fdedf55f57d1d26a499fb196975b4a38fe754f032c4a4c5b7c44274b4b3","nonce":"6f1e2e1cfc737b3ec001f739","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"2f162452e1d3bd1e5fb7692d22e0b8985ffd7d2bd1beabc4ddd5c99d7e11133acf155774959709b08d51033fe4","nonce":"6f1e2e1cfc737b3ec001f73a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"d7e20276d0bd925fb5d5119d4762b3fadce346e083d26c6473e64237c2ccffd54268df09cf13823ef56109f950","nonce":"6f1e2e1cfc737b3ec001f73b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"c35b0a7ae3c497d2bff671c2892420bc506acbd23e0d57f8180ab1250b1d534cf534f3367e82512aa3b9da8782","nonce":"6f1e2e1cfc737b3ec001f734","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"f1959a98d5f5299fba4bdeec585fa212cee9c76e1e9a3694e0a5fb5c6d026ef5510e68b72ecba75cf12ddd57f8","nonce":"6f1e2e1cfc737b3ec001f735","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"8aaf6d33f641c4d083468efe93a7d98adbe8fae7997e4f994b6f87d1d269ded3237da6c31e4bcf8415af079043","nonce":"6f1e2e1cfc737b3ec001f736","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"62e3a06d21cc95baf604880f9634136c843e5227303d2496dddf2d10d9d07b00a90d8618be98f43cdb8e84cacf","nonce":"6f1e2e1cfc737b3ec001f737","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"d205b648db7525998203312ab11356702caba1d0043622489545e773db9f26f1cb819fe6e654d5009c12e42b9b","nonce":"6f1e2e1cfc737b3ec001f730","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"6e457e70494bce831e4da22a385869eb9b9f09a41e952128744ce27229067f99994daf318febd206983fe89271","nonce":"6f1e2e1cfc737b3ec001f731","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"c01d3bd5646b25c3e6632b1b5f87321fb8f4bbe505e70865fa0fdccaa860af7f677a01e84d7004327f7d4ffdb3","nonce":"6f1e2e1cfc737b3ec001f732","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"48ebd2734531624d6f8c89a0456b8902c9384a71391d5f2c5fe549ba718dac9e9306fadbfd432516362190116e","nonce":"6f1e2e1cfc737b3ec001f733","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"69e5bbf8a67954b87b48d05211bb857ee926563b0fd5b08bbeeab867f1dad2e7bb554ab9e0114430cc7a617d31","nonce":"6f1e2e1cfc737b3ec001f72c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"33779a20e807d1ffe6e9370f35814fa6e7b02e1f51b5ee028aee1daa381acad02cbc79ea44e2747aea42ce14b9","nonce":"6f1e2e1cfc737b3ec001f72d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"ce0a4548f470c189bd95cc19b23be6e5b4dfb812f4eced17ffe4349d85254c3fadf8c253b5ae9667a89a337e1c","nonce":"6f1e2e1cfc737b3ec001f72e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"c150e4d3557dd7d0df32b30f4bc84a0b1dcc4f8bfed31526e2c753ccccbb37a6f644611b0fba6eb4757904f9be","nonce":"6f1e2e1cfc737b3ec001f72f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"c8a40cc1a69c1bf265c67d144fcc041dcdca86b6d0fb05b1f87241a9189e56cc2c409e22f623ec3b4fc0858b9d","nonce":"6f1e2e1cfc737b3ec001f728","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"588c6571c7c1ee9571dbadd813a2eab9937769c1fb8d2dd1790cfe4113e90ffa16b69b16c5154a44503dad8232","nonce":"6f1e2e1cfc737b3ec001f729","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"91a325778b2fee5ddda069f6e25698f9c433a12a28aa8f7d7d4b375caacd5599011b4027964c6dae2833890eab","nonce":"6f1e2e1cfc737b3ec001f72a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"0ec1b2d312afad6470a5b3652b85930284993fa281b24650deb485226a90df2e529a10e685d67c67c98ae6f528","nonce":"6f1e2e1cfc737b3ec001f72b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"a33366841792722414c051ec0f8ce84c66d1d8d1b19dc682566a4bb0c8f298d3efc6aac235dcf5353d265e7a59","nonce":"6f1e2e1cfc737b3ec001f724","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"cacde43699bfc5e4b31a4a30e7182ef4f40dde7a75f28e96d8b1209d2136c9ddc1bc9d7849e35efa9ecae4ca61","nonce":"6f1e2e1cfc737b3ec001f725","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"4da0e1277a8c9421ec4960f29301ca5d95fb183c65938d3714a5a6e1911d6202f7b72ca421a2df47576d86cd6f","nonce":"6f1e2e1cfc737b3ec001f726","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"a2492586b34b0a184e8987c67c778a47493cd5bd55fd122f26c1c50c67764ad56bc00c2e0991a3508890a82248","nonce":"6f1e2e1cfc737b3ec001f727","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"e9c1c249128eed8b992ff1c3a00ddc23f784ffc479d7ada0ce139e02dd25fa9b294c283410d6372b78f6d8cf3d","nonce":"6f1e2e1cfc737b3ec001f720","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"f64c1c609bb99257077e8ee05e378b3a2217d1bec920f6ec071d03bfa7158cd975f5219a270a756854992a6b11","nonce":"6f1e2e1cfc737b3ec001f721","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"90a66e61f7de7f437dfbd24c6e24478afff917534b540f8d630212d84378ab62f14a85e62ed5ea30c96c7d5b09","nonce":"6f1e2e1cfc737b3ec001f722","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"892b1c0c06a2a35f8a4cbc782d92963d1feb340be77068aa4dfb2d1dde90a29e3824129e170770d8a2629711eb","nonce":"6f1e2e1cfc737b3ec001f723","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"aabe9f5c68d8945734fcfc2dd976fa381e05b8c13423e4fce494f1940f3da19a790c4c11502555bd6cbcbf82c0","nonce":"6f1e2e1cfc737b3ec001f71c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"9b7fe400b875872122bdcb88da5501a61a919efc7351a544d2f823f07545df934a6d75d905bfdf904ad987fa1e","nonce":"6f1e2e1cfc737b3ec001f71d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"d44651e583c155526dcfd45a9f1934945ce835d4d610141d3d9cae715b4ec11983a9bbfda4bc83f49a1f9ad271","nonce":"6f1e2e1cfc737b3ec001f71e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"43d5efb3128cb408b487bbf27d70b8aededa18a25e9115562e3bc9410ecb580dddc6bec160bf42bd21f77efe79","nonce":"6f1e2e1cfc737b3ec001f71f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"08be0551ef0e1586b95be0dd4844e892ac92bb02beb23341e9aa434690c9ad1f8b10ddc8b8db7d376e1b528a23","nonce":"6f1e2e1cfc737b3ec001f718","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"42938c85dadd999533b50962a6e000c46a9dbf156d2d42b04b5cee2f5f26743ec6e1edaa45138b01ddb691062e","nonce":"6f1e2e1cfc737b3ec001f719","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"87cce0e7d8c199687d9f3d741d89760ec90d74384b5cf4b36e1da54078ac58510c30e3eac4fb2b4d725a496f2c","nonce":"6f1e2e1cfc737b3ec001f71a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"37fea0c6681fccc811baf47c9e8cbe366362b00f573c1b76f87c96c7d6f63cc3bfaa5569a31e85565f13f060fa","nonce":"6f1e2e1cfc737b3ec001f71b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"81af552d76ec7f544ae6f774c0130bf1e370df78532fced71ffe16da4944b822fcce5da26b7f821e806f083c85","nonce":"6f1e2e1cfc737b3ec001f714","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"81ba108ec678c204f7f19ddaa12c1b0fceab845c27cb19d41773b50e1dbd266670e3e010379fb284c39496968f","nonce":"6f1e2e1cfc737b3ec001f715","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"0aca2bb9b9bcaf416795be00f45a9310be681116f168044b4953b15ee834974155f1314448a9a4438c551cb44c","nonce":"6f1e2e1cfc737b3ec001f716","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"9262787f11682b465e8df7f070cea647a166261d3a94807f1926bca511ddbf553fe427146f0ae4ec9eb8c89bf5","nonce":"6f1e2e1cfc737b3ec001f717","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"a2ca94c01687603102a81945211d68c9bad38925de5b80a4e838d081088b03e2117aa8befcedcccf8e455e2b1e","nonce":"6f1e2e1cfc737b3ec001f710","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"a3359038362fe3819bdfac8bbc4b617e7181c54944ac11cf02c6297d80669cb1dfb0ec9aef5e07464d32464cd0","nonce":"6f1e2e1cfc737b3ec001f711","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"5b36b0dec52361dcaee57c61360e06c47dbaab8688eb23c7ec3e6a5b092657a79f3d41e553cb394901620f2865","nonce":"6f1e2e1cfc737b3ec001f712","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"131b188efd9169e7cf45c4b74e0912f3bf0220e0b311f1b0824a4ffadaf2fe278d07ee86a07e57d8744c883ead","nonce":"6f1e2e1cfc737b3ec001f713","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"e1972ea4e3218c80732dec1feb3c57397e96740dd291ac94d3b74c00038e60880d39f40e5cbc508a8fdada4068","nonce":"6f1e2e1cfc737b3ec001f70c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"225fa690b746c9955ab00b2afdb39986043f7487af7429430c7d5b6c7e96040ebb561466c47fda7d331d565fb1","nonce":"6f1e2e1cfc737b3ec001f70d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"f420c8e55202197c3542d323240652fca5a81784d19011aad70ec2110306c664f8e0bade7e0adaef53ea8b46ba","nonce":"6f1e2e1cfc737b3ec001f70e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"4c49f333fac3772fcb6b7b6ef5aafa3d51e4684447a33194fdff74c3f4dd26d091bd2a6c03c7349229eb392b1d","nonce":"6f1e2e1cfc737b3ec001f70f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"e03f5d6c8b3c2738ee46cf48cd06654d41892b87d2b9d5bd316bb4409c10a5c928b619d128ed8d163e5fd9e61f","nonce":"6f1e2e1cfc737b3ec001f708","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"452cb222463abddc8355d918a57c0ddd15888f9987fe7707b3b89231e6110d6c31a9617f09ad37b78966de2d4b","nonce":"6f1e2e1cfc737b3ec001f709","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"e18b11623da0a1621a4f95d3634f597f8804d3ba4fd894dbdea78d4ea09e9298e913c6ed4449783ca1b9ffc478","nonce":"6f1e2e1cfc737b3ec001f70a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"e1400e6e86772a4c008b504e0b7ab928bf4aaa92a04b04e22465c70567dc139d57bfc95a0e68f51c8342ba171d","nonce":"6f1e2e1cfc737b3ec001f70b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"3656d401b6ecc997fb1d53937daf031085b5e3ec65383a71956c1bcad8e800352f6947c290cd9f4f6030d5a6a6","nonce":"6f1e2e1cfc737b3ec001f704","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"582055ee92b8d2eca33b4597dddc65e226bb423c6e9b1373f2dc1b829f19137c0f3142b36701d8fe7e820482e5","nonce":"6f1e2e1cfc737b3ec001f705","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"908cb958efacc84006ace5d49b7a5773e5416ddc3aa642adea86cf57acd338437a6aa1f98f4ae9d06021dcbdfc","nonce":"6f1e2e1cfc737b3ec001f706","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"fdf6d9db5800a7c18c80136559e9a5accb2c9d742ea2232492719b8f65bf535611d525539d66991adca7f623ba","nonce":"6f1e2e1cfc737b3ec001f707","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"7e91d6f6d5e919e5a9bca0d443e68c07d263e12747d569ae97af31905e6b055ed743bbf9f96c20ac28e0fd77e3","nonce":"6f1e2e1cfc737b3ec001f700","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"4306c8141d75fcd1f9ffe4460a8a236a2e131157f653b48be182d0c55c6f8dda46243f1ddf489d92cb263f26a4","nonce":"6f1e2e1cfc737b3ec001f701","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"b89f0e036c42d1cf922f78229c326f8439232c5752fe9ea75419233c9d2e3881a9cd40785e7a9f39277ef21e96","nonce":"6f1e2e1cfc737b3ec001f702","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"9ee3f7f763160fc13059ddbb75ea166812023c149a579d3352557eb4a54b44483709d5bc587303d1509b1781bd","nonce":"6f1e2e1cfc737b3ec001f703","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"4318ecc67d1edfbb2296964b38401f5b3a04d77e62979c3f6d8fa7a874483bac5083ec927316f79dc80784ca11","nonce":"6f1e2e1cfc737b3ec001f77c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"0cb2db2861a1a2cae3623e842ef24bc5e4ec2f7553b79b14fedf21209531ba785ee84a4b00ff4e3ac759d632bb","nonce":"6f1e2e1cfc737b3ec001f77d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"1ed573f7e544e6b2d9f10b273ef983c0c233f5d62ad7ca74a8373055079ba4f0a7ec6632d7e8108743544c8d1c","nonce":"6f1e2e1cfc737b3ec001f77e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"125d031c462a17324786771b464abfbb9390d371a0c017342f6d5b73c353d97978af750531080ddef36ebd4780","nonce":"6f1e2e1cfc737b3ec001f77f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"8f78b28f23073f51373f1fe7bbd8dd936cb95f49a93a30a67244970024886079ce7896eb2536648a872b9d69e8","nonce":"6f1e2e1cfc737b3ec001f778","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"45b4dbbfcf70c0296bfe620871d39d912ca52d58f066f959b2854556cbadaa4fcdb28dbfaef0400789cae557fd","nonce":"6f1e2e1cfc737b3ec001f779","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"c0c33a88a631b71af28a2565e75538e678273786cd6f3b25a9388a15c05a58c959efb97b9c222f4119919bf754","nonce":"6f1e2e1cfc737b3ec001f77a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"7b7da7239797c99689c89c347ae731e0fbbff35989c97186608f817314b70eee4a7c22092fad7f6a80dd9701fa","nonce":"6f1e2e1cfc737b3ec001f77b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"83d7de8512d086f33aaf16735a249169a3b00e4bcddb96965d46710135dcb9675d2e74fbe3978ab3d6e0114f9e","nonce":"6f1e2e1cfc737b3ec001f774","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"143710b05631c4b2dfe69ad2be0f0c93a6e6a5e516a633d9b478148f5ad7b38e88f64bb06d7d1eb5ca82ac706f","nonce":"6f1e2e1cfc737b3ec001f775","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"4c3b360a0b9322edc824df511460121f2e0f5e80d7b75de8f2ad88e14591fdf23acdf3d21578384c8d15212e6c","nonce":"6f1e2e1cfc737b3ec001f776","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"a2e2faad6502809e6811c1886949d44bb2f966f25c6a27d93e1303ea752407b282b01b74d6948ddbd9c8b7e835","nonce":"6f1e2e1cfc737b3ec001f777","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"657dde7f4120fcc35692ec0e1d7327cceb145a74becfc570a36985e3f10c76f0286dcfe58f98419bf7945e5878","nonce":"6f1e2e1cfc737b3ec001f770","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"a252633b39f778bf2591933809857c655967c7d76409b44d3435ebc6621790e019873e5d09b48b988cb5daf80c","nonce":"6f1e2e1cfc737b3ec001f771","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"b553aeaa79730e26ff15ad6f8ace70788f1be838924163730b1866f4232b0071dc9e00c69f3f40a02d44472b75","nonce":"6f1e2e1cfc737b3ec001f772","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"0e4bf151f8e2f5a7e9abe2be50a3a7e87a0ae2f390360826467b3db258fcf9f9525c70d2f130fc6d4dd43c7fd1","nonce":"6f1e2e1cfc737b3ec001f773","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"01b11d968b18ae6e919f614f6a59e3be61e56021b5bc7610a5387993df9afa2e6039287833b9fb6fa8be40e1e4","nonce":"6f1e2e1cfc737b3ec001f76c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"e2ff6dff72abd5f1a1cc21a53f1d98ec47a7ba7ab7804ba931ee75a5f72069c61ba75587ff3c8cc0c2729167e7","nonce":"6f1e2e1cfc737b3ec001f76d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"614a6677436adb40b4ad898d1543e4cbae4f687e018f2bfce62c015042ba063132d423acaff955d6204c4ee0a0","nonce":"6f1e2e1cfc737b3ec001f76e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"303cff562fd95cab7dcb171de26a6dc1a51749e0b779c8a6cfa483c78123493772e70b87b28f555f3f5b91cef1","nonce":"6f1e2e1cfc737b3ec001f76f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"e12d6c1c71eb85823a20ec67d1a1a2235663e6d049760647d23bba5e246742fda25d1175d5c8586bb4a532a19c","nonce":"6f1e2e1cfc737b3ec001f768","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"597a24fd73e799892cfabe0999de01b1e91274a21692d8ab8635df02ec84d771599416aff687c66f7c4d587388","nonce":"6f1e2e1cfc737b3ec001f769","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"422205ca873c9d278a62e3cbb101b27fd54f15ffee3e8c6d17a77f600f7e340c14621589abf23e7f0b80f1ed2b","nonce":"6f1e2e1cfc737b3ec001f76a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"0a67d36521e8627b0ab83c8daf7853cc6cdaefc7e838e8680de89fa76171b56cb7d51bec491e0aabb3dc579d80","nonce":"6f1e2e1cfc737b3ec001f76b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"9c9149df3df6010ae576c72c85748ba8c5a9666e8de36d585b13244638a29f0470063167d6a826dc6107261488","nonce":"6f1e2e1cfc737b3ec001f764","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"93a23ff3a35efa29f38fa8b06df532fe80968843d83728649c0e67b3267069002b8998187aa46dfd49d9d06c6c","nonce":"6f1e2e1cfc737b3ec001f765","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"2eac80c7a965378c94ada6b7ff00a5d1d575807ebeb9deb7c566f2ae4acba47519a816acc3e7aecf1a2328fe76","nonce":"6f1e2e1cfc737b3ec001f766","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"219a1a1db84a53e06c6b5a61ae4709e502c6471842f44a86108435d6aa0b6b3fc88a414c46a8b9c1a897cba483","nonce":"6f1e2e1cfc737b3ec001f767","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"980539d35210b49781e30ce67e77a89f250f6d0ab43b0af7eb4ee218dbdb99153c1e92fc3b9b8c7a2e4a9d468f","nonce":"6f1e2e1cfc737b3ec001f760","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"33dd2a8c816d3594a18d710fdd5d3f748cde22fe154492ef0b8472ee57433ad0c21494d3f4257d1a31187812d0","nonce":"6f1e2e1cfc737b3ec001f761","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"38360ce02551a8baf87bc6a8196e95640ecca4595b4640a0284ff60f54633a17f18fb3b31dc9ac29784e869a87","nonce":"6f1e2e1cfc737b3ec001f762","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"4dee7ea02bd4c72193b4b8c6b0f9bdf8ed7bb59fd09cc5393f20936fdb8e4b3f7dd47f1ccbf0b0a7c4aaf4fb73","nonce":"6f1e2e1cfc737b3ec001f763","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"302fee6f747453e8bc69993a383a9ec492efa449c4be1dd061f0c069011f3f919c5083ab04486593f445e8fcc4","nonce":"6f1e2e1cfc737b3ec001f75c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"0bebdc096588f9035394c818095f7e81399712474f95a1fd233bf589c0040f362bf71383eb7690b13057044826","nonce":"6f1e2e1cfc737b3ec001f75d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"0e2bdf64249043faf41d75a50d645c6c258c5d5bba543219024994bac765a11a156f7117a4e588b8915084a6f9","nonce":"6f1e2e1cfc737b3ec001f75e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"601c2a0a161d2143920474d66894336e27c10a730dfcf5d2ff8f2568b1a8f124d1c6a264359e9835cfde1070d5","nonce":"6f1e2e1cfc737b3ec001f75f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"bd93ba4be2a35305cdce71b4161e7fac408acdb3efc128ffc96b659a9d7ede7934f5b2c4bd9b7c3e30f3ecb888","nonce":"6f1e2e1cfc737b3ec001f758","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"9b2a8f0a408252a7865b8e37c6a12ddc6e27e7f52463f5022e1705a12410bc605a1b2352494ddf0790d358d60f","nonce":"6f1e2e1cfc737b3ec001f759","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"126bdddda4141c9f98b9c37c0f6df12eaf4c9f423cd42855d009045396d451c0a836fac1538c594f90423e1dd0","nonce":"6f1e2e1cfc737b3ec001f75a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"95fce68130383f88e05739d9d6279d735e028b983b4d31db183a257425191a12e3cd48ced27f22efc3d159a93c","nonce":"6f1e2e1cfc737b3ec001f75b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"65191f2e7b5b2ce59a58e41a1645b9cedda504732b250de931ee61aa1590c6fce49d68c5bc1d52bc98bc4f359f","nonce":"6f1e2e1cfc737b3ec001f754","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"b4cb40738dc5d320261cde87d064cf725ffa8f654c42e43ccbc2104c2684049b5cd4e385ea23c9c6d22d91db3c","nonce":"6f1e2e1cfc737b3ec001f755","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"1160f9b585a73e81db59521887e5746aeee3ad5f94343a6f37c935fcded92e0d28212c2b9c6115950005f7a673","nonce":"6f1e2e1cfc737b3ec001f756","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"79d4af2253857e18131eb0ca3c4f40faefac70cf32d7ce2e03349e0f0face82a0c7038794222c2d8d975f4cd35","nonce":"6f1e2e1cfc737b3ec001f757","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"ea865a2fb04a85f93c2175c5c0627b62c0306087801b98f707155ee793d3015c5e747a4eab7a6f8955dcea28f4","nonce":"6f1e2e1cfc737b3ec001f750","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"c997aabcadfa9a9bfe8c3b511ffaf49b57ebc919ab7dc236ae861f89e33a7ea071c343daa33934d32ba9a9efc1","nonce":"6f1e2e1cfc737b3ec001f751","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"31ae0c79886518b304789a34816bcbcf946b137609464429d65eb410526d5a5981548dfdf670761ae1e02aae47","nonce":"6f1e2e1cfc737b3ec001f752","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"bc40559a9c2b87655cd6dadb750a05d187fc47ac2b6bcc11ce036c9bc1ff48279d84879b7232828bb8e30111a4","nonce":"6f1e2e1cfc737b3ec001f753","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"bd333e7fe49a571ba7b81a6e7408eea06c5035f34e8471e051995f1764871e02000449c2311af1e5373abf9099","nonce":"6f1e2e1cfc737b3ec001f74c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"e1df1b6ff13fdf238638fbfc8fe294bb13a130ed722e19122bfcf200679b39f232b0133bbf49d5527310ab5ad5","nonce":"6f1e2e1cfc737b3ec001f74d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"de919490dba08ec0e3bdf670a48e35ff635cc76b05cc11e83a9b8e65061e8ba644525c988f361773b57b805c74","nonce":"6f1e2e1cfc737b3ec001f74e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"01a55a63a2a22330296dfee82a36466ffef052a5b8b02373ec0b55536666073319598204b60061b8643a9fd3cc","nonce":"6f1e2e1cfc737b3ec001f74f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"941931769b42e048141a995772217c31785e74e0f060e37b9133404c44d2638362c7c81d64492a432ae7aa9201","nonce":"6f1e2e1cfc737b3ec001f748","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"38428cbb18f07d14ca0c9614734f2af40730516eb89cbf9a6cbb8502cc6eac9d7d21c1e42f4b168d553c5f18d1","nonce":"6f1e2e1cfc737b3ec001f749","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"4146ba7ef5aad8b0776e3e840516c22895adb4ecca3eab69415a2a6a0b86014c133ad956d7c5c40c52c7db3d03","nonce":"6f1e2e1cfc737b3ec001f74a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"94b5f1819d90d90694c037ffe34df45f1852e3df7c0951ac28f6d2ff667e67dc6063fa459383af961a2516362d","nonce":"6f1e2e1cfc737b3ec001f74b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"dcc2914e2b642c9a1b53b67b98f3071271cbf116df214b061c250ca8c26bd814f2614ab0e81ecd02295562ada3","nonce":"6f1e2e1cfc737b3ec001f744","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"e3996f091fb7c2e30cb34b4158ab6350709eefcc5dc125d4728fe33df21f6c39a9533d362467fe5d5da099aacc","nonce":"6f1e2e1cfc737b3ec001f745","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"8a40e08eeb50de097424c44bd8f5e9dcf6ccbe000ac3063b2a8deabbea7d68eacf8d0a285fc40f87ee76ba7886","nonce":"6f1e2e1cfc737b3ec001f746","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"208e94b5d74a72579e6a9ce15aa7be4163a7d52181febe1fbda463f3486cf4ca11fb34c407cf435b7416431586","nonce":"6f1e2e1cfc737b3ec001f747","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"1734828dc8f08c24c2f65d292963972a603dc12c4491f7ebc6e5c81f850788d3c65817f5a3c2f39cb7d58f278b","nonce":"6f1e2e1cfc737b3ec001f740","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"7b6377a53313fe4b664c8b4375af435281f6fe3858b52648c1b4236fd4d0bfee5ded7ffbc4e1990f3d1e553b87","nonce":"6f1e2e1cfc737b3ec001f741","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"105578f28149c161a58a824d236c04fc5895f67030e7c3cb96812060303bb4baf3b6fc9cb881a43de417873cbd","nonce":"6f1e2e1cfc737b3ec001f742","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"969b30cfcba472da738be25e4fd817a6cab0e792d536407909cf3b22918c458635fff396cec3c6a324ddedc273","nonce":"6f1e2e1cfc737b3ec001f743","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"988e39755f7e6d3c04487828c1b872353b6da43d3a6805d956de85b8ab03e8eb583bef9beab91928f1b5a62dd0","nonce":"6f1e2e1cfc737b3ec001f7bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"84671a90a4746ccd70de09a0436c9f142f92505e9ce73f38a15034c0d868ec007d873f6699b3618f3ffa98a963","nonce":"6f1e2e1cfc737b3ec001f7bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"bce1dec5ba3bbdf34f0dcce6a18884e4e963b665a24a4295269f27e31e12cde1195485429ae6ba7c8d8c404626","nonce":"6f1e2e1cfc737b3ec001f7be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"ce3b068d106a3a1d468b6bcb711bd5044b19c3ed07b7a5046455ce9e31a467320db387847bd9349ffe6709618b","nonce":"6f1e2e1cfc737b3ec001f7bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"f11b444cd6a72c683c8c67ca0ce04eb1165935c0c83d63dbbdba6666caebbfe6fdf0bcc2a9bd3aad3ad761ee79","nonce":"6f1e2e1cfc737b3ec001f7b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"2c4545c56d70de34fab8bde0e3f2f9c0e4f17c0b82e3257fbf49dfbbebdd549f0d58fe4ebe837f76e43f8dc544","nonce":"6f1e2e1cfc737b3ec001f7b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"0e767879dccc67d535133822195bcede28e872b653f750f64eb461bb3c94d124a042758586a65a9eefeaf2fb56","nonce":"6f1e2e1cfc737b3ec001f7ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"32be082832a2a52633a334795630e02d4c68e3f55de5e19256a3294e59e6e342988e43a1a899b81ad33360a4f7","nonce":"6f1e2e1cfc737b3ec001f7bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"f7a62c9a223197e37cd1da1a014f531f93b443e8ddbe2fb779487d8f80ef777b6688fcead7f0bceebe02ffed04","nonce":"6f1e2e1cfc737b3ec001f7b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"333f033948e4dbbe27797d06604ad91e76978b340ea92ff868b0cf84466c7ed20dd1eda499f9e7022879a7f7a1","nonce":"6f1e2e1cfc737b3ec001f7b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"8fc6324b5157de9fa125ee243ae7258d56a98bc332e24b2ac3be35079f5d2735dbe63925032efcc019d6778ec7","nonce":"6f1e2e1cfc737b3ec001f7b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"2b3697dbef035a2add07dc0b2984d2824aa4c5da744846e770cbc9c4fc4ab822a0713df773247b4e0aa51443e8","nonce":"6f1e2e1cfc737b3ec001f7b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"7974a712b9d165934e15f447ef6df68fd0a46c72bf0c28bd2bcbee842aa0c0f2e2ffd686a280c1a29aac10c16f","nonce":"6f1e2e1cfc737b3ec001f7b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"0663326cae3d6907306c8367840e06487128b1f2dfca81178b57f35355c1c20741f6ff8ebaf6162f663ef11b4f","nonce":"6f1e2e1cfc737b3ec001f7b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"7cf745476232509677f3b68700045d241b61e23e4535f42149725cc11647744a81a70164352f8ee48fb76a8a21","nonce":"6f1e2e1cfc737b3ec001f7b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"1e56a047c2fe2d7b2da4e01e7c826f31846944cf2321e1b45661fb0955b7fa054e2bcf43092b5917cdeeaf472f","nonce":"6f1e2e1cfc737b3ec001f7b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"c9d45bdf39bf872f84f4e95fa8dba0334db0358aad5085fbb6c46bcb413296d809e3f12c4dfe6df6b3df29c918","nonce":"6f1e2e1cfc737b3ec001f7ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"139d961597cd01b76eebfa70cbcbb6ecc8515e34d6fb11e6eef245391d43dcb489c1c7f3a9bdac35230668a987","nonce":"6f1e2e1cfc737b3ec001f7ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"b83a93e5f447e4ea3a4d527dc83023f1281928491704b0cac28b00247aac5930b56e6a2cf5b25b40f641b594f8","nonce":"6f1e2e1cfc737b3ec001f7ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"b6aa87a3258a93f02a06d9d6ad9f20d1bae75437a2bdd95f6506adfa76f00d2044c9659d8ad5e4ede250655930","nonce":"6f1e2e1cfc737b3ec001f7af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"aa26a8d711a3c0b6b69a694374b6d30e93e1471bc190c5c76707afed61b9475703fe7beed0f3e5e22420e365d4","nonce":"6f1e2e1cfc737b3ec001f7a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"4f3bfa906b37cfe15b1b7409d67e8bb380fd0d38c52f56b96e18f6b6d2ddba7bbedc9266f2d974ad3906362a9f","nonce":"6f1e2e1cfc737b3ec001f7a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"3d5723a9b10de007d5c56a89be22fc9106ffdd99c37c673d989f3be5e4799112bedadcf7957d51e875c6128f53","nonce":"6f1e2e1cfc737b3ec001f7aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"c2739ecf40cf3f48ab9d019c15534f8122e1ca000721ffa1797e4d07c4bad408e7391725cb651a276a998d6b9c","nonce":"6f1e2e1cfc737b3ec001f7ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"42b9962b2cbb28400ac42e9cc0c2fd1aa4e479df87e1decf4f8d47988de9c00aa1e000338e741abc061767a689","nonce":"6f1e2e1cfc737b3ec001f7a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"4c068c3eb7a1958527fce280bbb07c04a3e90204a9ac46053df92e9e23b51f62f5825aaaaa5952d505e25ca166","nonce":"6f1e2e1cfc737b3ec001f7a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"bd9b69cc75fd5115b5586fd055f37f69a9e0b6f32916bbc9d14a7ae8dda8e28897b0ed2f31397fbda06fb297f6","nonce":"6f1e2e1cfc737b3ec001f7a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"40fe9c369d308a6b40267f9b32848236078b9e0a0eda11d82cd77328bf7fd27d2bdd2766faf446b6cc2d83a7a4","nonce":"6f1e2e1cfc737b3ec001f7a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"a6d928556428beb25e49ed281c44da3e3d6af1e1c6345afe9d6455029a5616d44b285dd47938d57987ad4fa0a5","nonce":"6f1e2e1cfc737b3ec001f7a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"00a3bdd5b693681cea5341994c35023366909e85fdd38e1b002391388862f397fad242150bc99be0970b3e3987","nonce":"6f1e2e1cfc737b3ec001f7a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"862cfcc6517bffdf11a9a53c1321d85e1ec5ed4362eb23783ef7d0eb39bf9fa4a8a0ea770164b18fa6a721d035","nonce":"6f1e2e1cfc737b3ec001f7a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"69377de6ae1ff9ad791ba9205285e6221ff0e5dc3c5f7e2d678a0f3fcea83727a8aa2b04a834198fb31d8c3d5b","nonce":"6f1e2e1cfc737b3ec001f7a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"3469c1e3444c7ad0e639714c35c91adb38a9b9e0e76e23e818c400c615a8d3f4158a3d7b6e1307fc1e59e9d8ee","nonce":"6f1e2e1cfc737b3ec001f79c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"4b28c09c418f83149c5ec7695dba5d314c332d276482406402589b818bd437a17b723986e48b2735ec6449709d","nonce":"6f1e2e1cfc737b3ec001f79d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"42fcbf245ad3e3e77904476434fb1015a20d508e0e1cc06b4c4b9299c431c218fedd7fcb44735831f8dfbfa66e","nonce":"6f1e2e1cfc737b3ec001f79e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"8821744b403928e20a1cb89e33b4b821de3f49cab398a475b2226de32e58addf7515f416392b3025484ae41bda","nonce":"6f1e2e1cfc737b3ec001f79f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"278f3efb8f705468902fafd834d736a8bf0be1e03b6391880386b925fd3a8b5145f61090aa540b9c35dbae7273","nonce":"6f1e2e1cfc737b3ec001f798","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"32d6d27ad3d78dddc1140dc5d906fca592364f5a4b2c2404958e03a6612cb0ccadff32a6d862af8eb2be252002","nonce":"6f1e2e1cfc737b3ec001f799","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"8986feedbede8ef1a7263fd1de8020fbd198707f29cf0e45824b9956f9e7564246a4486629d98514de766611ff","nonce":"6f1e2e1cfc737b3ec001f79a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"f3e83e53f67a7e2e44d4e61ac9c51c005f6f0be0a4752b227353126fa3f14c34103da785687c6e55c72634284e","nonce":"6f1e2e1cfc737b3ec001f79b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"d820e05e19df4279d3c0e52ba8ed13f1066b1fddbbb2594f6238b2e1bc9c6aa8928c378294c74d26343bc94241","nonce":"6f1e2e1cfc737b3ec001f794","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"2e6e34dafabc7e4908f15a369f682a7c84c15a1b0a47bae2fd4fb922f042c1d0c9084d850c1efe326e64543904","nonce":"6f1e2e1cfc737b3ec001f795","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"62305e2ff259fd58af130fc355f94f034bd86401d00356363ddda7853ecf2c6e7850c4149ee97187e9ac54ea2f","nonce":"6f1e2e1cfc737b3ec001f796","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"07283c357da7a7b97c21a8686597cdaa8b3a4fa55275876d80d47ff15c37efe4fd0b991231d1dfee21d538dd3d","nonce":"6f1e2e1cfc737b3ec001f797","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"77ec0ecbe3810400d99cc9b25a70c05d3b5f9a579087641ae088af9ac8d7ebe29c5d95a686ee5453214a145ba4","nonce":"6f1e2e1cfc737b3ec001f790","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"b639024fbc5b8441fb857c9974ae7f531613f02c0e07e6b59959b813df53b8c66975023dbafb84db2949551c86","nonce":"6f1e2e1cfc737b3ec001f791","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"132d12d1001f03dbbbe1e0ab28a2e28a81cdf9469b655f83ba57852dfa693d0aa22cd8610bc6444e34abdaa5f4","nonce":"6f1e2e1cfc737b3ec001f792","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"4a3ddbe2bb3a000f92d0c94e0f0bf457781fff713d1e2cfdad2469b64042bba85790889a0a286c5786aa137557","nonce":"6f1e2e1cfc737b3ec001f793","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"6b5ca27904f21408cb1ea2415229d2efede815481b9b512977144a8dab8b9069b9e4f2e39e835c4dd20aeef638","nonce":"6f1e2e1cfc737b3ec001f78c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"b826a0d9cf6d907e8497bf29b3c64c76dbfc8c9114788ad2d0a94b6fe27183140a0af0f64d53066939fb0038fc","nonce":"6f1e2e1cfc737b3ec001f78d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"229b047fbc83fddb36d43f967316d2bd8ca8aef1b224d0767c29b0e277d5ae56bf6f3dbf69498b9caadaa5b5a2","nonce":"6f1e2e1cfc737b3ec001f78e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"4204c6dae028ecdeda46f4e438ac3ff492e2547e88ac51171407327e530aefa575eaf19fe97986284e767202fc","nonce":"6f1e2e1cfc737b3ec001f78f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"4310512a495927b489f20222b1c7e9a05cd224ba5bb4473f27ba224093c02590ce55c8316154baf6393a335e6f","nonce":"6f1e2e1cfc737b3ec001f788","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"7dda01289c082c9229020048af71a6ccfeae787184583318fc81aafca07b2b657fd98929b78232169d65645eb4","nonce":"6f1e2e1cfc737b3ec001f789","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"08673c6c6c93567bd1ed8acc7864cec93059afd61258893212198001fce33ff7e3f047d22d5b67e548ba3cdcc2","nonce":"6f1e2e1cfc737b3ec001f78a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"4283f1dcca63f7b4813a8771756c31e172d610c15ff0ea51791bb47034b790cc38eb4f0a4903aacbbb371ea56e","nonce":"6f1e2e1cfc737b3ec001f78b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"6f663c761dfac6ce0c009ec287e5cfc25b967c6d8c38e1cc9425812ab9a77afc855a3b640ae4a54901c0d0e270","nonce":"6f1e2e1cfc737b3ec001f784","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"eb2efc1de5476b595eb9ec57b361da0622a7378a58b01ced86841593c0585ec80506743cc420403804f1c81ad6","nonce":"6f1e2e1cfc737b3ec001f785","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"19d64764ef93d9757de9e9f941cb34eefc049b006331c5dbe61248dec4fe0f42e1c96d505c8568f961fb063aec","nonce":"6f1e2e1cfc737b3ec001f786","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"c727c74949d759a4c7c913cac374453b3cc7994d7785ef1e5b9f271390f892bac4a203bbe4d4fda677baa4d3de","nonce":"6f1e2e1cfc737b3ec001f787","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"5329fc4927099badbbd116a842131d3795c600a47719b47710ef3bc250b2dcebc3ca0befb2d766c907643ae09c","nonce":"6f1e2e1cfc737b3ec001f780","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"ed9d7ce0c05f961ea0a772189162bd8fa5d3c7096b67187eecf1c93a9b04be517e2b9aef45c7df9485f77e4ccc","nonce":"6f1e2e1cfc737b3ec001f781","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"2fde1c91fbfafd0e54b4b6bb3df4484a7d68c539e4e41b195f962ec6c694db6dc2d6ae4c86ecf33fc37d64491f","nonce":"6f1e2e1cfc737b3ec001f782","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"f4eb85cf87907bd3d00f4d5acc9e1280acd2490025e4046caf151e24c29ce37180688ede32cdb87dd33de61630","nonce":"6f1e2e1cfc737b3ec001f783","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"aa2226c2faf934cb0a7debf46d4ab113edfb4727dc877676799594261e0daf0bdd169e6284284ac5f00d9abfef","nonce":"6f1e2e1cfc737b3ec001f7fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"422435cb96e367b9595a1805abbe2cdd3ef3201ba3bf6fbadc3e7b6cf8a4cd48bfb09dfde8205a1783e0ef32d5","nonce":"6f1e2e1cfc737b3ec001f7fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"896a4411c580712fce099dcd03bac9e9cba2d889f85cba674d58062565d7bebd2bea886ac784083b5f9c8f5ae4","nonce":"6f1e2e1cfc737b3ec001f7fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"afd56d1ce952e14be01f93aeaba79a9fe4e6274716d2c2542cfb0d1747e37d49005206ae8fa03dcf67b5fc4026","nonce":"6f1e2e1cfc737b3ec001f7ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"f1947aa614c1dbce49c65beebeaec29a2a10f2a6436c7dfd79d2d66ed2e6ef3ed3d4d1bd8e5f5f96268e27ddf9","nonce":"6f1e2e1cfc737b3ec001f7f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"7da8c4109091beae344603818568ee8da3b08a848a42b70902ff63c20ddba0acd85e74c3b5865a81a5ce9f6da1","nonce":"6f1e2e1cfc737b3ec001f7f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"6f6d4b00faf43376aac2eb06c56cf6ae9e8aeba8831a06f88e0e157d89cc9872b5392ce796ad54689e9739e5b0","nonce":"6f1e2e1cfc737b3ec001f7fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"073dd28937a2f70d9ca27ed7d885b2590f91ff62207397d1eb6c1d7fe7743b627e3dcbe7271547f239c108f136","nonce":"6f1e2e1cfc737b3ec001f7fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"28171c6aecf9dcdea0a69c249285d1f3149af1f0361ddd365dccd6a527fe6495ffdd89e660b4f4ec18dd2e1740","nonce":"6f1e2e1cfc737b3ec001f7f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"0c775e6d3bedc11173a59fc9a80713e4d46b887f8e2527597243693c71f2a44c468d8d9c447260a71421caa272","nonce":"6f1e2e1cfc737b3ec001f7f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"d315a7b777f959e2e2749ac126c625c4195d301ae4d40d0d5aa866a94510b947b4bed5e199f79582f3dd5509ac","nonce":"6f1e2e1cfc737b3ec001f7f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"5d6bc470507f21d5fd0945bfea989ef5ec62abc4d4b47287b27849a88f9f38a4079bafa11e448d69d031c421b3","nonce":"6f1e2e1cfc737b3ec001f7f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"ab768326950db962ef58fafcc1884b24c4bb7fc21c951eec80c4d82f48e741f7d0991fe93d91f0d4de57024566","nonce":"6f1e2e1cfc737b3ec001f7f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"8e952102aa526924cf3e6ae0d2d642a85a04f690d43efb802aabd0aba0cd9c3fb5fc3dcbb84226bd7c79e75399","nonce":"6f1e2e1cfc737b3ec001f7f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"5dd00397e0ecc887cb21ee19e00531b8b865ce2db7f9060821bfd1d2c2f3043555c21815bd0d3398baacbbe9a2","nonce":"6f1e2e1cfc737b3ec001f7f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"2a3ce6530b14fc6c904dc18b25ef73f67caf172f8c7823d0dd69a03f7dfcdc1392b3acdc1f16a8fe0176355377","nonce":"6f1e2e1cfc737b3ec001f7f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"c42460f2d1c9c9c0e4255fc9778eb6d87ced80f170c3cad8db97283eefcca7fb8f0809e2b68d2fe16909799aa5","nonce":"6f1e2e1cfc737b3ec001f7ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"72ef8288d08108c17373783cc11f82a19e275371d8da84e68fef8508f2db8975e4aa6c0e1bc4c34a4547109e39","nonce":"6f1e2e1cfc737b3ec001f7ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"068de4e8a7caaf3f5fa741d0d2e963e61adb20b7effa4d0e4b355bfece01d43a26a41166836e3ebfcaff3de9f5","nonce":"6f1e2e1cfc737b3ec001f7ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"fdfd05c9a62136ae5d3eb8c8f40cae6fb989e4ea6d6f57a23ac058589854d2e28f1028b85430f81e782bd32052","nonce":"6f1e2e1cfc737b3ec001f7ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"28e389bf0f7d81e249788f061f823563e6b7f003784401569cafd818b22321f3b3ecb3ba1729681ffcc071a43e","nonce":"6f1e2e1cfc737b3ec001f7e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"83001b9dde057aaef18b9adc1ac729d4293f535b2a9a6ec71a9a1d269247bea7a5063860a2bfa851fea27b7e94","nonce":"6f1e2e1cfc737b3ec001f7e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"2321793c7ee9a861b49c368cc85af5e2fe5dbe8f3e765daea29a70e43278965e8564fb12a412073fbffb3331e8","nonce":"6f1e2e1cfc737b3ec001f7ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"6d967278333cde6ffd9bb7ba44c3c209565e6281d044ea353e2f4e780c322dbb9ca32bf2f58d6292f57696ef16","nonce":"6f1e2e1cfc737b3ec001f7eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"ad63f63f653e9268c51cb3daf7f2a2c0b709e9873d51a773f3a7d2029c399e66987046ba8e702d308db6e51eee","nonce":"6f1e2e1cfc737b3ec001f7e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"cfe5f30fabd7f3ee5d5ab4b80fa4ca74d516f5247ae848d1b50223fcb90de4ab3338f9527ae93e14062a49f743","nonce":"6f1e2e1cfc737b3ec001f7e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"d8da375f97faa78da973eed5a4617d2706c0f3451c13fc3c7b54617bee6719ecd399f17eb9d94d2bd0b7de07a6","nonce":"6f1e2e1cfc737b3ec001f7e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"7fe453bb6a089855e96c87bd339ef39499fbd9f5c531dadaf55ed429bbc4a9202afeca265e02b43ebdc8a43672","nonce":"6f1e2e1cfc737b3ec001f7e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"7e8554c4f44beef039e3d2cbebeae344ef6c6d76b05997856106a1149731cdef05b4443a0481e06f2806c7e0cf","nonce":"6f1e2e1cfc737b3ec001f7e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"4de9b7449adf7568797386f4c12bfd900ba02dcf5d4bc8bd8f173cf6b17c0e6f8788f554381b345af24d5474c7","nonce":"6f1e2e1cfc737b3ec001f7e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"4960eb7632dca937e1d0535fa35e5f258c2ec92aa428382665af7271b512bcd4aa6de583c9b3e1c9535aa6b96c","nonce":"6f1e2e1cfc737b3ec001f7e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"5dceff6e702fef20e3cc32d214eef63efd54b38328c0209e69941b92f71d0f392f5312ff10693e5c31218e3edf","nonce":"6f1e2e1cfc737b3ec001f7e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"6d9a9757d9b6862a221408b320534923b3b9908298fbd9e8362e62c040d4e16c99fc5af64aefb3b7478735d4d3","nonce":"6f1e2e1cfc737b3ec001f7dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"3586835be25ffaabbcd8f79d424d1756be1cd712a8b755e0f56c642b5a04e56e44dd2f00aa18d5e0e26bce8540","nonce":"6f1e2e1cfc737b3ec001f7dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"18be8984ef8cbf6638fc77d2219c959301f3b9e6d099784fa48f9a90ef3cb9103dd27abb879782a98fbedc5a1e","nonce":"6f1e2e1cfc737b3ec001f7de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"4762ab5d3852b79189c8b86055fbfb7dd32cadbdd5b08a75cc4c514e67cbeb6c2186ab035209abb770a622c220","nonce":"6f1e2e1cfc737b3ec001f7df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"e34b8ab81f83dc725edfa2b053248f4534a01d7f91e8ca1f22e01e9dc0cffeb6170ddfb20aa5b91225a2f2804c","nonce":"6f1e2e1cfc737b3ec001f7d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"cdeb9ea61fe271a62b5cad6d7902894a3edb37462203917b4788a7dd8541b5c907eee251c8e531ba7bed32c8c0","nonce":"6f1e2e1cfc737b3ec001f7d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"1899526ea3cb00b1f8c363cbb005e474fbcd19d85efdd1dd3772c72fc30b13332f1a901a75dca12f8a66957cf2","nonce":"6f1e2e1cfc737b3ec001f7da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"cd398ee6bbd1b8740f02bb937f770cd1b25d1f3525967bf00dba1c2e75affe1ca60c2741c754775fb1c09c4557","nonce":"6f1e2e1cfc737b3ec001f7db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"6ab04cdbd4e3ec0b6c81d21d13fa6736b1f5940163853e41ab0e1be22f141e3b7f4e87dc7bd8b7d394c5bee9da","nonce":"6f1e2e1cfc737b3ec001f7d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"5e62737411fe445409709275be340084d964cd74c84047479db84e8f3705bca788bc46001759ff9cf357ceeca3","nonce":"6f1e2e1cfc737b3ec001f7d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"9d14307b8b52de7acaf346bf96ef66c8988d570151cd9b89c1a3a7fdc08ff4317996036248b16dc00f0b52ff3f","nonce":"6f1e2e1cfc737b3ec001f7d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"abbbb7998fc31ae9005b5ab9c9b5e647d9bf15f993d5470cd152fd36d716ef8321ed0f0efbed4735916385302d","nonce":"6f1e2e1cfc737b3ec001f7d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"14d3435687a15f1dd64af71c1d481243fe260d2ff7a931aa071af1c95cf8a1388dc8717a1d0086cff1f2f4ad4e","nonce":"6f1e2e1cfc737b3ec001f7d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"4c730220ff4e2102b1fbedfe47d9dae03406cd86947f644da92ef389226ed28bbdf9f559650a7e1a135555d572","nonce":"6f1e2e1cfc737b3ec001f7d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"8fb0f4f630167d2bafdf14c347ebe13943bc8b8af9e12dc0bcabdce10d35143f0b58b67c60c9fff1afdf90dd01","nonce":"6f1e2e1cfc737b3ec001f7d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"ab9c56cd31b0025d8e632f503ec4d01e495fdd103f7a5b27fcba67c2c54122d1b3a21eef08e898255e34cdc666","nonce":"6f1e2e1cfc737b3ec001f7d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"44b0a3a9a7bb330ffaa557bf36f29e53bcc46c60b1f4f0052fe8fb730b4b184ec25b501cf99f704ca008ae3180","nonce":"6f1e2e1cfc737b3ec001f7cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"4d50bdbabf7505c2146e57eff523c511ccec077a6150104b783570407b15f69a772407fc2929bd196493ba3a09","nonce":"6f1e2e1cfc737b3ec001f7cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"2d3e5ad5c496678b1b59ea0d9d56e50d580e9262e59d94309e8905ecde71a3b065727eb51bf0ae71a4f31d3ddb","nonce":"6f1e2e1cfc737b3ec001f7ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"9288c30baa1cfcdcc1669ff318f45c39b81b30213277b5723bbd45a41bc78e39799a37b8b3fa9a1c0fd516d85e","nonce":"6f1e2e1cfc737b3ec001f7cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"9a6cf66c0ec6271f8238cebe7fb6161872511249b72f2a9a9cbb306612b074bb4c12dd8cb08ff9e613ed2d3aa3","nonce":"6f1e2e1cfc737b3ec001f7c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"dd5e8235e75d8682b66321924a6541db7112d49996d16f370c12d90bf4b57f63a8d2b8304f701d10574046e915","nonce":"6f1e2e1cfc737b3ec001f7c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"a2b0c4430f48fafdbf310d3c875b1011bdfb2bb09717a69cb18a851ea9ca921756e1dd177376121528b2e6c69f","nonce":"6f1e2e1cfc737b3ec001f7ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"381238127859d0f9938d10ff44fe249d54dd9bbbee2a3af7719e6a6f73a7661d6bce4c2ed40861e55e7233c199","nonce":"6f1e2e1cfc737b3ec001f7cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"8a7e6bcbfaaf98281ec22fb9d1e655fc56f81e9a6fff3d4696a9c5420b72c589443bf6c7667fa1db79dd2538ba","nonce":"6f1e2e1cfc737b3ec001f7c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"75e12c406883cedd78951e26ae5234ce16e9b95302d36d99d28b077a8ae8144ed56f17bd7c05052d6728ee4f0e","nonce":"6f1e2e1cfc737b3ec001f7c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"4841fb91e443ae558055454016fc0381b314f923f5a0eec12dcdd6dec93e2f60366858764ba4d61ad656dbf5cc","nonce":"6f1e2e1cfc737b3ec001f7c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"47b306ad193308c070276d1029d26b4ae20007a0e73aaa6e7757b9e67698734dc8f29ccbfbda9f8fd06804f9c2","nonce":"6f1e2e1cfc737b3ec001f7c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"44086655ffe63c7583873b739a8de9e43296d9de68b340bbc6f6dc2d89ce7b37b82945e1ed4e5252f4d234a0aa","nonce":"6f1e2e1cfc737b3ec001f7c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"6047a12a7f11190bb96da2d56052b9ec2eb0dd10632910195e761e05b4e119d3748e2975e20fd030c569486ea3","nonce":"6f1e2e1cfc737b3ec001f7c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"879644d5cca3c564f373ab462e846ef3b8d23082ed1a56eb220bc98f84c305010131b38774c903ed8a66c675ae","nonce":"6f1e2e1cfc737b3ec001f7c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"98cb524260bdd216c704107522b21a92875e8e29d101ecdf7b16f736af96704a1b82dc0cc12db726d695bf4f99","nonce":"6f1e2e1cfc737b3ec001f7c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"3bf94e9ccceb63d6e62ac7a32f3c92d63979c821cf5e17885e458d644d7fdfb19bbb99c034c00597638dfd1bec","nonce":"6f1e2e1cfc737b3ec001f63c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"a70bdfb311eea226f73a309a3bde5e907a525857f341eba0cd080f22cd7d836e"},{"exporter_context":"00","L":32,"exported_value":"808c81e18ab1a2e1a95f6be22ef1514778ea1882bc221e84ecf29409630900fd"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"8455b51f54c4d0bc7336c3d8580c0951f4847138cc4ddaa032d86a02a4ac304f"}]},{"mode":1,"kem_id":18,"kdf_id":1,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"9711eda8b47b13bb5ef167094d763ee74b753c11eaac07b47b633b148933b710500bb9a44973917e85d3a8d5ff5c97417a0220e19ed44ec10a3dd5b666cc36a7ae3b","ikmE":"092dca168a339edcd5f6572f85fd42c5584fd8df7a5aaf2f016143bd0cfbff751e723446d80e101cf04c79bef47cb790923824e0f7f7ee324c5d7cea9eec01eb1662","skRm":"01b76b5e8774176f7cab6db01d2102da6a1482f57c954db7754b00d6178a54ef4ebb274047738ecc81d317daa21aa5a582576b56aa80b29f218b68746d58c3fde5a5","skEm":"018a29eec0f8978b1d28931548f5ee3f9d3a2e34cc1cc628075c724f9be0a4da92790a4995c20115b4ae610a0338eff889cceeca707d6931f944489abdef26b35396","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"040025f7d3136cac295a96a1527bcbbbd7ccedf9008d3bae96699262717516b8b7d0b5e5e5ec4eb85640586a11ab66ddb76205eccbc98ad7296a420fd73eabb918dea3004cdf530b411d4567c6359db1eccdfeb941e1d12d2cd03f50a7749c66da318c1189bbca2ca1e4844c086deac2eee9dff7231b3d2800f007d44851e9ea15ed01ef92","pkEm":"04011f962b2ae5951d9bacd696f700a8ac9cc0c563ff0c000d2ec996c5d97bcb08d83935288440fad8de38c01d59128bf53f305aa55a27ef24c9279d3fcc082b06ed660138c4f92fa0c7ab8c2e051440b64900666ee2f1917106a27201726104004d81b5537ff6d8baee005361e32c5d5637c429bac5a6f369b976b59221749cf341a0cb71","enc":"04011f962b2ae5951d9bacd696f700a8ac9cc0c563ff0c000d2ec996c5d97bcb08d83935288440fad8de38c01d59128bf53f305aa55a27ef24c9279d3fcc082b06ed660138c4f92fa0c7ab8c2e051440b64900666ee2f1917106a27201726104004d81b5537ff6d8baee005361e32c5d5637c429bac5a6f369b976b59221749cf341a0cb71","shared_secret":"998f69b65f81e06e8092f9eebcef9e64d6115e23967fc09b76a6e48974211aa88fc82313227547499d160b0cebf1c5ec35b1902e49396164f47498a64ba5a4d7","key_schedule_context":"01a5aa7a15c37a7f4d7cdfd2ccb134e4c19b3f782db2da917f6020ce2f1fd62b4497e18b628ea977f60a69bfa0647402182d019d3a0b59d2dd03624d028053dee1","secret":"807c3ed750c022294b76e59703c2e8e2ec421b5663460e35e75b3145907d3ec8","key":"2bd399779c6e09260a6a5a296b8f770a764da9a0ed150822fb117ca4da65fc8d","base_nonce":"7da19d5120e43a5d2b4bd323","exporter_secret":"91347d10576b353c60f1bc41847a724c2e747622918a3bfa643fa6f55f62a290","encryptions":[{"aad":"436f756e742d30","ciphertext":"dd5d7a963529affc8fe9f8d10a0ce3b5c5a8b91baebdc5f53b4cb0ccdb554dac864cbe17d154b26fd890ae6aae","nonce":"7da19d5120e43a5d2b4bd323","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"6d87fff57aac3310a8003f772c6b6767157fd075796bbec1636509668bb9c337c9dcd24a84ca572eb7d00f96b6","nonce":"7da19d5120e43a5d2b4bd322","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"8056ace3dec5593a8264950a6071a3195e00728fbb0ef5db5f94490a13ebb57f8123f9cb67ef71de6ceb3ab008","nonce":"7da19d5120e43a5d2b4bd321","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"3a189cc1c285f3a3f9769f0cab2053a5941778f14062e49f3f5fe5fbaa1b09c930fe818253652f6f4a16019650","nonce":"7da19d5120e43a5d2b4bd320","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"2663b9c6a167afa6cb87f6306aa2f3ae722f2980259bed89a9352dc774b5600e7f55a25af2cc9f4e87d9065f6a","nonce":"7da19d5120e43a5d2b4bd327","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"f2ce9d43639dce783b5664b026d8191fac785274937c5790facbbc412faac139f3d33cd1dfc0034b26abf9d985","nonce":"7da19d5120e43a5d2b4bd326","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"efd047c2fe14f45a1a70cd7185204e8aad68b4c564bb78762ac02501af5c0251dfdc57626559b9285dfcf77a65","nonce":"7da19d5120e43a5d2b4bd325","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"8607aaf2605744101abc4788773b8ee5c2cefe84040bbe0d354cef1843318f239a479d7f47b24f0ee5aeb056d2","nonce":"7da19d5120e43a5d2b4bd324","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"ac7507260d78a1bed74c782822fce707e67c884053a5db61e19afda0c9092d430ad84736225735b968097116fe","nonce":"7da19d5120e43a5d2b4bd32b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"d547e1a03c26ef2097b0b3f6dc772b5fb372855f055187bed17ceee5dd15e8f6be9073dd56a362c10ccd6693ca","nonce":"7da19d5120e43a5d2b4bd32a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"ed352ca390185f00f29372bdd103746e2e205098b10daf5528713366fd1e042e4a703139e4c0ffc800b4e91db6","nonce":"7da19d5120e43a5d2b4bd329","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"6cdf54b84c8cc0c3af143e7326f656af19981017de7c070a892fb7c6482e460576b9ddcb406345767680ecbbb4","nonce":"7da19d5120e43a5d2b4bd328","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"2c2a1231b13f845240c47cea6d69ed837c6683c2d08b4a6babf4829c045bcdaf127a669a654c07b72f57e8a6f1","nonce":"7da19d5120e43a5d2b4bd32f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"56243896e454026f4351819327059a6186c573b4ed14052f53f7f7d3e196866b71cb5bc11a6381c43e22e42713","nonce":"7da19d5120e43a5d2b4bd32e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"4a7fb83907aa16878e94030c2fc99575e814f05474cd3a5ad4e49e5398c340fc01200f9281253734c731ae481a","nonce":"7da19d5120e43a5d2b4bd32d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"7d7e4d86b530c2b0012f5a87752631aa7486a0c94754c182bb8322b5448ec6e16e0a0a9b5eb924008fe91a7a81","nonce":"7da19d5120e43a5d2b4bd32c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"060c84a139e69dbfa211e3a637d2a367e634dbc5ec9b86b25a8197b407aeeeace867f4027c021de3d4aa873580","nonce":"7da19d5120e43a5d2b4bd333","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"9aa2fbdf669801df5681186dcdf242be6c77b346748a1f28eaee8eadc80aae4a1029f065ebff85d8ef6f70e497","nonce":"7da19d5120e43a5d2b4bd332","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"660070a59ea6bb8cdecbf1547e73000e9cda765bd8115071fdb5f9ff80c5df933a00e2a5f48696f6342b835768","nonce":"7da19d5120e43a5d2b4bd331","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"83e9198a6cbd547b9552c5782caa0f0ac8a5a354b6755326a40410383c49467cc59bcd3acd3c3db0fb512bef89","nonce":"7da19d5120e43a5d2b4bd330","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"a06af52bad02cf6afc7495649a11b20d52a3f694036870337c9358d1422eee58dec085a10ebc6fb319416e75e6","nonce":"7da19d5120e43a5d2b4bd337","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"ef912e6a0c4b26b6a1f65d5ca49dba7f8278b73e9f3394881430d5c1776aa54691924d35b208d2df619255b86e","nonce":"7da19d5120e43a5d2b4bd336","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"2e19789519d1a1e18e1195fab30f4ee8fb45ef2b2438b1bac4b2debab3d11ff85e257eb5ebc5ea489034032167","nonce":"7da19d5120e43a5d2b4bd335","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"e904a66f7de246f032d69f1585888a28b818a7b9b4e2cd3cde4f175bb0aa71aeeef93fa891a3491d6b58d7f104","nonce":"7da19d5120e43a5d2b4bd334","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"bcc97c3eaf47bed9be9bb97271c603068e818315a7e57343781a5315d0fbb1d6e402c3adfb10ec9d2ef20e20ad","nonce":"7da19d5120e43a5d2b4bd33b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"d8df5cf161fd122f50ddbc59f61535f0deeb131cc2cf52b6a29bea069e60e9349b756f602a3b32b531b1187abf","nonce":"7da19d5120e43a5d2b4bd33a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"5328fbccec33652b51e7df6a9ed2b1e80c4969f231dcd3b60dc290251ca7d379268d47e4982fee9539fde3e947","nonce":"7da19d5120e43a5d2b4bd339","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"bf0cc4c2e7efda00980f5b7dc856c4a3aa95038086739c6befa0505101dd47bb6e392c19e1b21e156802cacfca","nonce":"7da19d5120e43a5d2b4bd338","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"7dbcbee44dbad8fab10bb79d9dcfe37460f75c6ab71911da0f5c050e32e1b224b43847311c1ba02070eed950c4","nonce":"7da19d5120e43a5d2b4bd33f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"2fe45ad8177f9ef6718edb50ead17132c65e163dfb1469604e06fd3acd3e8ebd6300d8bf631a2c01dbc0644c56","nonce":"7da19d5120e43a5d2b4bd33e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"4a7e3aa2c8d030218b3ac86b4a12df807adcaaca6467b2e130f0d29a1ec2f4b9138a207ea9033bdc4e59828130","nonce":"7da19d5120e43a5d2b4bd33d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"86f7124077af0199828c201a89d2a425bfb0912b225b7f8025efa392210abf90e2838c066b82b173ef7abdef38","nonce":"7da19d5120e43a5d2b4bd33c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"9537ba5fd80cc4ac9463bd1b0998963bb987a069b758891e53d704171a35e3b60f94fb2e76f04f0346d7b5085e","nonce":"7da19d5120e43a5d2b4bd303","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"9c7dc4fbbb5025df2dcd3dbc306daffd8cc841d5c56f04149bca85d25dcf4bf1944ee62461085bdb4be09a51ac","nonce":"7da19d5120e43a5d2b4bd302","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"708b3af5704109fd2270a884fb368b6b011f03568f8df054531ab544ed26071c802ef686f27f411f5d34ce1ea7","nonce":"7da19d5120e43a5d2b4bd301","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"2e4fe5b0b9ac4d3adf11da14641196766bece2ce319aaa5d89ef215d2beaace4eb14d6eee6cf62f247dd95c201","nonce":"7da19d5120e43a5d2b4bd300","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"cc6506e1a67232aabeb14a683d3a6cc9400a27dcf00c9d222a4a436da795addabe2226befe08db3ae37e32ebea","nonce":"7da19d5120e43a5d2b4bd307","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"a880b87744753037c18e53c64d1cb2eb76f46458b59a46a9f2f047cbb412abaf990083b8f6b3f241571fb81b94","nonce":"7da19d5120e43a5d2b4bd306","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"ec85316a89b496f89be6cafe96cc1baf6c866b0ffa5b59c6c2d93573438aa88d65a7916ea2b33b333e600f949e","nonce":"7da19d5120e43a5d2b4bd305","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"f4c8b19fb6b7b1db6ef76fab66e399cda7d0d31f27f52ad27fd76b84c9791baa7ff7c65df2ad228394ae035cae","nonce":"7da19d5120e43a5d2b4bd304","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"bd2f92bb35676cb0fc4eb72a074a7f95ff081c14ece66ca8a5aa8e4e96b36b65001e410da0adaf6ccd13b6c568","nonce":"7da19d5120e43a5d2b4bd30b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"df5860fc5b92932c77d3af67aa9adfb41aec726f89bf464353cf31b0ba2d6538617f8de7151c1cd2a4ad2ce82e","nonce":"7da19d5120e43a5d2b4bd30a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"fe5d2e5c05f4d2544a7704fefb271ac9bb233020837c0a658ad3dca05bd67e0bfa6700c08611af2daec57078e2","nonce":"7da19d5120e43a5d2b4bd309","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"774453a0ae28bfc203d5a5970fee4c259d5036d0900ea5b958f8ea1c3f695078f4bce4e74204d1b203e5f8f237","nonce":"7da19d5120e43a5d2b4bd308","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"ca94fbe8553196e82be3c58d13e97b8a4ae150180b7f844861aa57aedcf3e19bd0fd5f18196d54efe0f1236fe1","nonce":"7da19d5120e43a5d2b4bd30f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"d3ec2abba51202c4ec409f69d2ff3babe834bcbef232b7ad2e2fd33bb2c7328ea27cc41ea3ee2aae260529b859","nonce":"7da19d5120e43a5d2b4bd30e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"d3a093bb9bbe0117fd53dc4ffb0bbd77feb4dfb1d9b6920c32b4aef3646d9d340bce28dc04b3542efafd4da172","nonce":"7da19d5120e43a5d2b4bd30d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"a9b47236cd3e1995b5dcb414a09563fdd65b00d5fad8308b132e56fc105675619c212064ab096a1b6c3d80f20f","nonce":"7da19d5120e43a5d2b4bd30c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"cfc068670967c9f385cf2fd9ffaed7d716220521fafc5bed52024e39b9edcd52900973563bb3964b6eb3ca24aa","nonce":"7da19d5120e43a5d2b4bd313","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"deed40e44bfba9833accf87351ce8e68d032ee97bfdb74b9714bfd705efab2a1c8652c2d7036a332928a690116","nonce":"7da19d5120e43a5d2b4bd312","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"34fb8360086c9dd3ea1d79a965d3ffb54b15f60473f66a6edd5eac351ef56d1104369112c9f41a005f68136a6b","nonce":"7da19d5120e43a5d2b4bd311","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"4cb1e209fe9977d8bb2f2906827976a44a0a55ce62d9caa3941f5187b2ee68235288ef0d121adc75e7930e1da6","nonce":"7da19d5120e43a5d2b4bd310","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"dadf270b1d0f28371181d998595d07431a0a3442a2b61e8a7d33b510cbb707d72c43293b2a74b5b0bd8d1ae1ed","nonce":"7da19d5120e43a5d2b4bd317","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"0cefa00a944684abe90b9c224f5ea7b3a53677d982e5471b3a4e7349deb43e9b997c99717413532fdaf9cd284a","nonce":"7da19d5120e43a5d2b4bd316","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"336b38bb4fab19a74a812542885bdb9f3005bfa155f31a18eda17e0117556ae1ea613a87d642f67122483ba459","nonce":"7da19d5120e43a5d2b4bd315","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"ee4e8a12d71818ca2a9c996104d0930a38227258072cfff31a71924b0c8e3f329c82c2db9aa2f8b33d0758f0bb","nonce":"7da19d5120e43a5d2b4bd314","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"cd181599ffaf7a781362af234760b2456c52f3e3771d6d850faaaf9423016fd384a82aac412d3c8f889fd74a29","nonce":"7da19d5120e43a5d2b4bd31b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"643358c7dd467664a0764a3ae4382e06e7aa3412165cd9e19ffb225d6fdee0859512b65e6d7e73e5639be9fdaa","nonce":"7da19d5120e43a5d2b4bd31a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"60ebd6de1ccae431911a28ebd0aba929775cb1c635bafdb36b65f3190d83e62c6f64cf6e70cdc7b53b6486f0f1","nonce":"7da19d5120e43a5d2b4bd319","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"7510fd8f9d850f3dbc976c5d32c06d2c9b66173fb3893529268460196eeab91006dd045734fb43bbba167e3f83","nonce":"7da19d5120e43a5d2b4bd318","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"34f84453def440af752cbe69efb78a3483c185a6707de41eaec9622bae91b7fec1597e99d16c26b2510e553158","nonce":"7da19d5120e43a5d2b4bd31f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"38dcc3aebe59c8a7905bc94bc220b0fe7117be08a74b4034d63f3716482ea87088ceefdc414073303e7223d6ab","nonce":"7da19d5120e43a5d2b4bd31e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"651976a057e92fcd1c95de015a223aeb8a1deeeb9b5e9cb652202fb806ace0ae53832238e1cdac6579d45f75d1","nonce":"7da19d5120e43a5d2b4bd31d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"3a4e2cd792509a28aab82b02f521baa40363c39656c34927c0997e14d1ea303f76e6f8a88a2a55b2afa73bcb65","nonce":"7da19d5120e43a5d2b4bd31c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"4d5417fd4e4dbeea66ab643b9e11fe19997ae7443785ab590a0b8ae2b648b339209c050942a4c207953f3b8b94","nonce":"7da19d5120e43a5d2b4bd363","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"8938dcc3bccf70604d45bd244b3042c3fa586ebdcf556371c134cd010b2e04c4ab09e8bfbfd138ea900c7cbcf8","nonce":"7da19d5120e43a5d2b4bd362","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"9a4e20b77ea4be7e03877018f09e3f9c5bcabc111da336cd4c50f21667296354c75e595ad6626d6829ee2d2fec","nonce":"7da19d5120e43a5d2b4bd361","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"5f2f8483e54f25d15f220b11c62dd28b35e55d8278038260a34bd9d6b8d4b437b1564ff2f3d99900be25d40f4a","nonce":"7da19d5120e43a5d2b4bd360","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"995f527b4ec9ea005547e1c40b8ff8eb9e6ea0611de80de335aa4b42a81529e314fb469c0c8f21994ad1ea26ca","nonce":"7da19d5120e43a5d2b4bd367","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"d395b9239ef0ece9e1fd7e3b45b92c8dc8e6321d42d9807067f4019bbc54c69d23e18260ad504fd19d3cc4d99a","nonce":"7da19d5120e43a5d2b4bd366","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"7cc7e4cbd572434c82755788f4800c1cfc3cb0df7235fe2804803ddfa34e6fde9e26a2eb6aec46446fb955bb99","nonce":"7da19d5120e43a5d2b4bd365","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"15bdb79de50fce2a18549107c8d3a0452bb5fb3cc55388f5391d5bd896e1b51eff22745cd6256e23012644da3b","nonce":"7da19d5120e43a5d2b4bd364","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"aa05b6f2ca7945a7434adc0d45949bb7bc5579331d40f7de14fa8512a2ab811767e5c5bef295697e2def7abc2f","nonce":"7da19d5120e43a5d2b4bd36b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"9140b41d42d820370acc7c644a882671405cc5e7ca3b3ae39377d347a3dff929056f05bb54ec9dbabc74e2380e","nonce":"7da19d5120e43a5d2b4bd36a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"5e71d7aa6bef2059c5f59b8ab043ed3543e03fd76a446b98b2fa2b8522be9de44168dc3a974278ced94fbfc04f","nonce":"7da19d5120e43a5d2b4bd369","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"72d802249efd3bdcd4a6c6be38013baa28ee5b4332658ca33cdee057791101d72769e1e313b53714bb3c0fdcff","nonce":"7da19d5120e43a5d2b4bd368","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"58ff6dc44b38fa383c56f4f842d5526ecc04b8bd07b8535abdce76464684de0a4b194df31934d31053401a6079","nonce":"7da19d5120e43a5d2b4bd36f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"dec84d115dfc5f4979f57f538752de9976fd173224671b1695b4a2bcf7422ea635da92035df6d05cb106ec0b49","nonce":"7da19d5120e43a5d2b4bd36e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"ec214d1627c7daac2ba4be5c42589b2006692340b5be059eb70f10a14b1b6ef4e69d56c72a6e37fcdf0c682833","nonce":"7da19d5120e43a5d2b4bd36d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"0ebe212650fa430f5cfb160c0f25d5bf09180f509dde1fd069f82097ecc2123df4d70b606b58441449c602c0d9","nonce":"7da19d5120e43a5d2b4bd36c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"fc514665c9946cffecc5a266aeea433741f4965914ce52697ec89969472e6cac0205ef444714125078721b159c","nonce":"7da19d5120e43a5d2b4bd373","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"a37f41932bdfa464507d8b99c201a962c16011c7b1f2e91798b8880c0bdb454fc37f14a083540194f5d5df6f7c","nonce":"7da19d5120e43a5d2b4bd372","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"8e4650449157e4c13fca66bad9fbb81eb4aac9f9eccdb3dc215dccc51ad76c981e3388f77f3a76f6f2ad1067a1","nonce":"7da19d5120e43a5d2b4bd371","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"dcb6c44d270779b673fe642ce0c0434117de9ce2c6b6150f7f71717fddd05c1a2676e9cad563f8648c32440c2e","nonce":"7da19d5120e43a5d2b4bd370","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"591a687dd368de936b87efa492612c06debe2bd162ba397e625cdcc4ab9649ad1e7b24638c15a0c50878676430","nonce":"7da19d5120e43a5d2b4bd377","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"a282ede576eec578ff3121ab801c4882b3820519dd6fb1770df93bd5350edb29e0b9d27f78b66f540bcd4d2172","nonce":"7da19d5120e43a5d2b4bd376","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"c133248f30158cd9057c5302a3d1289a35336a60458d8108f258c4d3307feb9cce327e2fa136ebd9e9b8c091e4","nonce":"7da19d5120e43a5d2b4bd375","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"d1d3920f826c023a6bf9a033cdd2835278f32615fe65931434c2797237d70ff2440b34f962bc7bac7f98869514","nonce":"7da19d5120e43a5d2b4bd374","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"4dcba933f37b21d0286084015e8a95fb8364749ae314d7bb78aace86727df71e0deee7317579766d2a548f464d","nonce":"7da19d5120e43a5d2b4bd37b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"c053075caf3db02cfdc9ebd42792f701e99b4c4ca25ef2710c96cb35cbcdf19a01a0cef685a895dd485845d306","nonce":"7da19d5120e43a5d2b4bd37a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"4681a3d93ff829080a1ef1b1e94eb8e24c7ccaf6bd12e57f941d90c3996e0185794fdf597803a31126db0ce27b","nonce":"7da19d5120e43a5d2b4bd379","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"1a7442e7fcc8930ddf8c7fa7fadea4ed193200ac1b212f4dfab83569a0fb864852d7f7e89c1fae5ea14dfa4ff5","nonce":"7da19d5120e43a5d2b4bd378","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"93dd09e4ef42429a6bbf13d64d29d16d244c185fabc214b063a3dc3834ce965e50c225824a8941a49af6448502","nonce":"7da19d5120e43a5d2b4bd37f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"826d94acecdc72c578a3ba8af3f90d053785de281c153665141a2c9a5d1d398342994a4abd748027957a487450","nonce":"7da19d5120e43a5d2b4bd37e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"9b68424b8be0d9f190961018fbbfac229c23303013b27c863a4ce44ae9da24c605faab2a795c59b608c6e90ab0","nonce":"7da19d5120e43a5d2b4bd37d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"5246d255649730c2c2f87d930262e56179b6316d3da949938fa400e9b1d2d6f16d8e4260bdc3c6cc9a2ae2ab37","nonce":"7da19d5120e43a5d2b4bd37c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"00bf463d7518937690de38a0a275cdb8e39a3fc0711b49781937fc7a8ae24b74857666683d13f5abfc7855898d","nonce":"7da19d5120e43a5d2b4bd343","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"83cd44433ce6b01fd211523133a0410a4badea89fc3374201533b81ba71b6d31730a5942adbec743c8780d7dc9","nonce":"7da19d5120e43a5d2b4bd342","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"ec2a2c40bab0285c0d30e461d0e0289ca8d921d465508eeb31c5ba393e16d6176d902a482d7cefa307cf0de6e3","nonce":"7da19d5120e43a5d2b4bd341","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"9c66500f8da5c3b4a303493c942297085ea68d3c6701b0075858b9ed21df1c6ec51ac8153b9dd649c8a56de144","nonce":"7da19d5120e43a5d2b4bd340","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"a2b7f7a2b30f92c1d1bfde1132d736dd942fb41792f740ff71bcef66f90603ecf19120307cf8a45f9b5a626b4a","nonce":"7da19d5120e43a5d2b4bd347","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"3ccc6242583b1e2df22c4b6ff5a3c3ef4de551f3a6a0cfcf4dfc87664986ac5aee90467f1cee38fdaf788a2eef","nonce":"7da19d5120e43a5d2b4bd346","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"9dcd7da5b52120b192bf45e024d927518c20e3cdaf20a90f2e6f2939c1d1e811afa3fad385510819d2de78ad7a","nonce":"7da19d5120e43a5d2b4bd345","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"708813406942b8b762c8fc15a77df8cd6c0853bd3b6f5cba80744363c09b8440abc930e2f7d2bc09d22541c2f7","nonce":"7da19d5120e43a5d2b4bd344","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"ad33a68f913035cb674e6416de4b5fb59c68a4b9e5eeb539c6f8dcd10ef0536038307855e0dc33094ce125108f","nonce":"7da19d5120e43a5d2b4bd34b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"f16268656ff24a182f6ded9d70c29e8a8dc6be8c6a44d4b2e22de615135166d6530c08af2ca6164ddad57effa5","nonce":"7da19d5120e43a5d2b4bd34a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"fd63080c3db38d4f6c7a9ee2a099f4cd7882528fb11ffeb01b4b4b04a56343d39d8479b5a41cdca96c8d9514a9","nonce":"7da19d5120e43a5d2b4bd349","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"cd0b7af8a32595acc1f9f9b868341abab79fd662fba8fc18739c4131ca17f4137206d311235aa1dc380c97ba91","nonce":"7da19d5120e43a5d2b4bd348","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"c9c1a9decc13df6436baf510d267523fe2244972cd141b1dbe2e6dfc7f2eee0670b499a8c013782030555f8df8","nonce":"7da19d5120e43a5d2b4bd34f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"419a29adac796f0b4a0e96a9a165c918ddeb37b8c8bf0c7c21fe25eb4e46c880d1ea1b292828e035f3b9e74bee","nonce":"7da19d5120e43a5d2b4bd34e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"1435c153b07d9aa7a61c1467a5931d7fababecbae499639c1fb4109f28bc3cb3fa9c9f8043cf044df962fbb5dc","nonce":"7da19d5120e43a5d2b4bd34d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"5f3b87499da21f5f02714bbdbff9e33fca2063f93b8c8478c160816c73ed64a15ad2c45f1057b033abbbf845bf","nonce":"7da19d5120e43a5d2b4bd34c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"570bc6675fd08ea54f14bf5bdcd8d6964cfa8498876b836388c6880cb467d9fdaa4b60fa5c2693642fb54b52e1","nonce":"7da19d5120e43a5d2b4bd353","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"b5aa3ef9f62bc6a0919372a9b9c7706ee6ea1bf650eaf4b1863109c129f9082188570c372763a60b3359d48a69","nonce":"7da19d5120e43a5d2b4bd352","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"1d2aa3c5d8bdd1df294e440d5ba5103836ecfc11b99076479cd71f79a125e31fdabff078f5bea0ff9f72854a13","nonce":"7da19d5120e43a5d2b4bd351","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"9bdb13cd0b95d44f6ab95c72e7576fae6ae0f6be9edc4a1c179f4a466d60883c0363c20a5cf5516dfef5b3c4fe","nonce":"7da19d5120e43a5d2b4bd350","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"8e60379839e1bbac17145646a90f67ee21d45b1156bea21d0ca468be566b1121c05c0cefd7bc2045cd36e57c66","nonce":"7da19d5120e43a5d2b4bd357","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"e946b09e2fc31650dbb854a54289eafcc078b0c83a3184cb9bcfc08a7dc98dfbcba377352639d0bad0554f5025","nonce":"7da19d5120e43a5d2b4bd356","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"186049c1879bbd17c0e9940c940d195ed448f265de6c784a2cef9cebd1053cd042a409e4af4946df0f6b3edda2","nonce":"7da19d5120e43a5d2b4bd355","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"af0dd65df54a2d3b01b96496dcef8025d52f5ed6be73a2156e3dd1c68940c24a0dab9aea688e28b677fb7cf1ba","nonce":"7da19d5120e43a5d2b4bd354","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"b9eded4590c7f62115ac0ae1451a60f618e7476355d56ceb5d54ff0e89facf7e1b7dfabeaccc5a34596b56ffc5","nonce":"7da19d5120e43a5d2b4bd35b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"6de2c6b755755149c141eb591100fd4449413d7e19c7b0874cf2f82dac8431de37d7e143579900d6cee3f5f9dd","nonce":"7da19d5120e43a5d2b4bd35a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"1582448574a037876d28fd67bd26e708412d6c0e5920df10db660fc7d6e82c66dfd2f601deab07b08d429dfaac","nonce":"7da19d5120e43a5d2b4bd359","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"8cd40b0e6506016d9367af5809b10416581eee983ab0c9ea27931156d5be919908ffb2ac555010c388d8734cc3","nonce":"7da19d5120e43a5d2b4bd358","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"74b2fad3437f4ff26918a60199b7fb3edca8a87e3927d5ca1c277ac5367731b2d0d85c5d3818ac3c360d2697d6","nonce":"7da19d5120e43a5d2b4bd35f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"6019a6a31119b3dd9b90cf540496d94e4d7320dea7dfaa5e40173be04a454d4fa051fefc0e4dfdbff1b1ff679c","nonce":"7da19d5120e43a5d2b4bd35e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"c90578f6a64f2a665e8a14bd7fc6f817abd849d721838d5d425e9c0c5ebabcf46317a371e29a0a669c3533bb75","nonce":"7da19d5120e43a5d2b4bd35d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"c7fb485bfec72f0f3cd17fce2cbd6f3626bf46208319064808acb4d7f1648f9abdc64fd34137ae58bf24d108a3","nonce":"7da19d5120e43a5d2b4bd35c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"1ca1a1cc16ed3d8628a26001848bb510e76a6406692021c788bfe2db3de5de86ded90211980691c251a3613049","nonce":"7da19d5120e43a5d2b4bd3a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"d7b3437d280ec306180f288d4dc3edc3c80c921eb396e8724b47c566fdc943e32e0e6f8c37d6c9358975457d60","nonce":"7da19d5120e43a5d2b4bd3a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"a97dbc102d810760717663021b069c4e071733aeb33441afa3169e68c213b690b21440406f94f89c3894fee98b","nonce":"7da19d5120e43a5d2b4bd3a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"fdcc303d725b0660af42839fb59cc50171c426f641c2e6c40b14943d203e2cc98e208872aa51fcb56abd581812","nonce":"7da19d5120e43a5d2b4bd3a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"741e130a6bdfbf68bee2b8de91a5ae83d7af0d1e5ee8e65af59b5da6c3a649e3d462e31e610b43b0bf3b351f5d","nonce":"7da19d5120e43a5d2b4bd3a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"990d7a4f0bd820213619e61630205bbf52ff388010d99914bdf67037d9789cf30ee5b283d1d59fc140f14d417c","nonce":"7da19d5120e43a5d2b4bd3a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"4499643e8faa5730a4728d676eb76e3ea52940e90370491a4befe70fe9c86529dc33dced72c8165563deaeca3b","nonce":"7da19d5120e43a5d2b4bd3a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"c36b89dafb82f55df4957ca862ff50c7531a7366fa119e9f47f4f12edb7361f55894eeade029ad6b09ab10ac17","nonce":"7da19d5120e43a5d2b4bd3a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"f577b3990f6517db516932ee3864c0d8b5833340f275ca3eadc7273479e3dbbe8a121a676d7ff2d9ed5e15be47","nonce":"7da19d5120e43a5d2b4bd3ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"3dec443ea37aa13e3fa186afcf02dfd1c2add80cbbb920876431b3cc751ad66bbba8d30471d6f687b202040816","nonce":"7da19d5120e43a5d2b4bd3aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"c2bb9df2f3c2b6d6b873de6a61cba6a2584c0a4e68af2598ca9e4de3806418692b2aaeb505c164fe102c6bd550","nonce":"7da19d5120e43a5d2b4bd3a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"3bb916477da876b0d88b834a4c62e2aaf30518b4502e15c973ad747aa367e75b62107a62b08c933d336b7fb610","nonce":"7da19d5120e43a5d2b4bd3a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"1678b2d9eae37132c068ebaa284c3965fdc615bdb6027f1223d085b37dd7c54fc74d405550b56b25d9bcc50481","nonce":"7da19d5120e43a5d2b4bd3af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"0ae4567d136b41b938da336a58cae3ead2e96f68430a514e2ba7fd9e4560786df43e15719f0b72fb74f65543ad","nonce":"7da19d5120e43a5d2b4bd3ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"b33a0ac1fdc3f6176c6f95ece4abfed5da2210c8638af7f1efdbd62b1b3c9779673866ddf836e4b70893a26478","nonce":"7da19d5120e43a5d2b4bd3ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"3954c32befd2c6dc2a090a3c857135586fa012c10516098bab40269234cbb82e46ec255c489e0bc8b894f949fc","nonce":"7da19d5120e43a5d2b4bd3ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"c63a8d703cf11e6a171ff31bbf65220acc1764b8433562cac4642128d5f214143cd22901aa1924dddc96bcf4b0","nonce":"7da19d5120e43a5d2b4bd3b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"5c8fdc3a1e9f3a90fa09cc83121f88a2abdcd9e1845f5ab3975f20f651de746794909c7f91d2b54ba2952329be","nonce":"7da19d5120e43a5d2b4bd3b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"b430bedfccef69edb73806a9709100cc272cba75f510b6d61d93b8c4a009ada7e23965d6519e55eada7c518883","nonce":"7da19d5120e43a5d2b4bd3b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"29cc56e8cfb823eebf692105e4fd2e321a92a207baa64d34258e2e1696ef8fdf4f6634de1b8c6002f649254ed4","nonce":"7da19d5120e43a5d2b4bd3b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"f8a1a07fe24bf6b9bc59b5e06ea001e1521c64cd891f16cea876e139e238c21f80d132ec786d0bc80e34c95f41","nonce":"7da19d5120e43a5d2b4bd3b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"3d220634507a7a4ddb95aec3e0ffe50dce9c09b9ff5b7b4375309516e6a16fb3d6fef3c2b4735ee2ff85eb9e2f","nonce":"7da19d5120e43a5d2b4bd3b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"46b583b48e56632b0731dd463ca95b74058ea5c87a44471fd2e2172b017da119d37e257829d02a77e8c917e665","nonce":"7da19d5120e43a5d2b4bd3b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"7515dcbbb043ae31a34cad1ad62b723de0385083ea7619a43e82c548865a59d40a05575573ba940a8b44aa3b8e","nonce":"7da19d5120e43a5d2b4bd3b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"e356995051a7259ef51dea97f73f7e6dbcfec206fac369e87eac85e5483cb225320c8f50c13268ba477525f187","nonce":"7da19d5120e43a5d2b4bd3bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"65d8c5a1015fa38dc0e83358569b7fbca03a65565065d393827ec0cad7301237f7af6866bafb6d3868b3d19d52","nonce":"7da19d5120e43a5d2b4bd3ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"4f58b9c7cba7491ddef1cb9698379bc8df31e263ccdfbf8cf12a24d41727114e8333ec4235450b836dc919a355","nonce":"7da19d5120e43a5d2b4bd3b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"9daeeab608cf2bb2b232fcd02a40b42cd10675e8fe980cff686c585e31a74b8e88ed44a3c46b68a386469daef4","nonce":"7da19d5120e43a5d2b4bd3b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"1e9c672ddfd3d02ec40726a6bd44ff7fc97f7028a72d11dcdb5882c1c00a4ab0222bd84c2bb3ca09ff874f4461","nonce":"7da19d5120e43a5d2b4bd3bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"212cb7f782bb8dcc0fee7b9cf4679cb99db9601a40c6ef051edb2d7ad5d0d7601b54ce8c21cac619c10505a3fc","nonce":"7da19d5120e43a5d2b4bd3be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"3150b0089c6ff7a2beec33b663c2839c42ec7a1568e08162b70e6d38ab92cc7711ef4eff9cda2aae0e7f97cf0e","nonce":"7da19d5120e43a5d2b4bd3bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"b08f9b386a1dfe14e3da4a7c033b49f23e3ad4ed7670cce6b0ef327e5dc9fc7cff8c96f0d0d28628658c3eccc5","nonce":"7da19d5120e43a5d2b4bd3bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"80ae4c585fb7e96a30813de3f1b1bfce635ef571102c1b331d0fe7963de398ef13133204ff468f78f8480f00e9","nonce":"7da19d5120e43a5d2b4bd383","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"fb64b4a5fab7ebce91788f77afb35e365d4ea4a5d8e94c7914a2eba5ec8403ba80b05a481dbbd97daecc069e2e","nonce":"7da19d5120e43a5d2b4bd382","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"d1c15be6781b314e0f176742d7e2c392bf15f6949e649b5416bbfc345c70211a6bdd54ea728e34663219122ebe","nonce":"7da19d5120e43a5d2b4bd381","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"e14f558444befd29f53dd1bf973dc1d5a64426b8983d1d5895b8abfe410ea8746a17dc4e3897563e4aa35dc104","nonce":"7da19d5120e43a5d2b4bd380","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"d832fe91227019199ffcf3416f2c39d1c24f8466bd918c30eae7f3450f3c59d624157c57dc22e60016a52955ec","nonce":"7da19d5120e43a5d2b4bd387","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"a83363605a13c705d9635b59d46c301775ab717136570e391141a1ac50fff2f4e343a767f755c2d60c0c7ca83f","nonce":"7da19d5120e43a5d2b4bd386","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"36c4ab43592ab1ddaa8b113d984ef36d5ffc78ada21e881c595e45d6be3a6238ff4fab48beb10c44298440bf45","nonce":"7da19d5120e43a5d2b4bd385","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"34f7740379bc342cc4c075225af529e1fdf500a2ccc19b7b5a5cca91f77bf21aa9216ff9d0aabc3c17aba97836","nonce":"7da19d5120e43a5d2b4bd384","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"99d4913911bdc04863b699ec113f86535f54e3ef22195ddbf72069003e407ad74945a0f3b64f4a95e5325162c7","nonce":"7da19d5120e43a5d2b4bd38b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"60b78abb96d64e08adac1bd8d1b9750fcea795315a5e1ad6b578a605f289debf9ec0b6900e31c2963f53fe9951","nonce":"7da19d5120e43a5d2b4bd38a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"7cfa46de859db6f590c9747118c56ae61d8fcade515b5fbfc198180943e6ee2f4f2a4821fcbcb6982a119187ac","nonce":"7da19d5120e43a5d2b4bd389","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"9d3fde2a133196493fb6340f1a83a7501ddaecb6bbc0a5a54768a81cf548b67ff0dba04a10bdee741462337826","nonce":"7da19d5120e43a5d2b4bd388","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"4c75925272cbc147b2f2424ae3e01d02659a69da779e68de9d3725eb76612ec28768bf6397170bc12183bd0d93","nonce":"7da19d5120e43a5d2b4bd38f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"18ca2c16f3c42e7381a142bbad1ee88100ea48bde19e005bfe6710365bd51500e2faee7b8f196d03c349d036c9","nonce":"7da19d5120e43a5d2b4bd38e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"9cb151d4e8cc08dfe1042ba6eae0036cdd6b73e29a6bd5278e19462ad09c7b6e551fcee367f7e2a453a4a8e6f0","nonce":"7da19d5120e43a5d2b4bd38d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"621b9238f4766f96135bef7af0ef41471e1d8bdd87791dcbd98ef563d1ca156b34d0e403b45f8419f120ec422a","nonce":"7da19d5120e43a5d2b4bd38c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"5933d24f722827d6b63548f3547b8ad8ba84bb00e49bb411631657a50a4644015f408a4f027976b558895ee7fa","nonce":"7da19d5120e43a5d2b4bd393","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"40b6bf7615838d146d3a0fe5eae4bf5e2b2a46774f487a4f3f091b9fc9d3676881282427fddf4c850578700fdd","nonce":"7da19d5120e43a5d2b4bd392","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"8b6930f91fbf8e65f7353660c0fe51dbc41ff1f47f681d1ff36058c44dfb166f46f0827541973d354891bd4fd5","nonce":"7da19d5120e43a5d2b4bd391","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"32a56bb89cd1b852cffdc89b7f6ceeb455bda1acf9f7e55939056166adcc53b42edbf79f816a92b6b9571a8f9c","nonce":"7da19d5120e43a5d2b4bd390","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"c78f01731acc4cd047f24f4617758cc953f579573372cffdb0bdb3a83c865cf1062c239336bd0b672d59bc0fb9","nonce":"7da19d5120e43a5d2b4bd397","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"1e5357ebebef7d1dc4de56c87822128331006517a31bef157bb6679c9cf4bbb73b47329b957d15af3b3599a047","nonce":"7da19d5120e43a5d2b4bd396","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"8005e1f6c2fa9065fd68e731a725097cbe4bf3034b92eeb86e32b0c620039c0d32bbae36ef64632dd407ac11cb","nonce":"7da19d5120e43a5d2b4bd395","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"446dbb7f0831500d8e51c16477172c814f91ac14df33087cde46ddd5483e0edd8784e5f1a3fcd8e5b8782c1f20","nonce":"7da19d5120e43a5d2b4bd394","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"4468a9c0fcd306ec114a1e71ed4437d8236244f385e8357fb2a46ef34f8c70753082fb207daa9e8c1bfe062c63","nonce":"7da19d5120e43a5d2b4bd39b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"32e756f6bab81537b6193d1406d1cd2a093d95153444f3718e89203b44f8a99137665db53362e91b2efd872d00","nonce":"7da19d5120e43a5d2b4bd39a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"9b069bf68b2502d32fe43cbac993ea1dd792bb3ab98623133e0a08d6425860ba9829e3eb373c7076823d5911e0","nonce":"7da19d5120e43a5d2b4bd399","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"6575e17f7a514c2ea9e97e24fb846bca00e2a885e49b47578a37ca8270f339d9eff29ce3431ad62db2688e301d","nonce":"7da19d5120e43a5d2b4bd398","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"12215de4015d3e7d3a69c3c8325b23ed8b59651548ce15fb55b81e6ad972f90014a34d70cc241b17fd875e348f","nonce":"7da19d5120e43a5d2b4bd39f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"d8349544cb327a43816c0ef5c1e9c32f93e5c52df67aba95fe1e877d1b0472dbda77f0d4ef00fd4c65052d1aa7","nonce":"7da19d5120e43a5d2b4bd39e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"1e6020d95564d9bff00883ad555b211b54c817d14f8bd54162cbbd4ea2b119c6683689c17b9f7a5f20a2c2b422","nonce":"7da19d5120e43a5d2b4bd39d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"d8a331870e6abc9d1a15d21ab2864a4d78527b7824c2ecc67cdad2b9facb53cffcf8a93aa953d1277df2894d60","nonce":"7da19d5120e43a5d2b4bd39c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"93cb5b5e00b7a5bfa0c28edf70f57aac196993fa95746dca139389a147cb2a9b46126b370ebb63605e921008cb","nonce":"7da19d5120e43a5d2b4bd3e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"8aeba0b5c5349796e53d6926a3155916be31d5086432c277beff32ed2e77ec6d545ee7c8c78c560e89f8d839ee","nonce":"7da19d5120e43a5d2b4bd3e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"3f220e86e90e7d48d6ec19af33ebe3dd4cf538d4d446e90a53dc7d70afbc77f807cbc5c32426608b90daa66277","nonce":"7da19d5120e43a5d2b4bd3e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"d0020009eb609f4fe942cff883d8fe535cc313fb3b6efa497620adebc2a1f7b3f8fb25a1822c393ec1dd5db3c5","nonce":"7da19d5120e43a5d2b4bd3e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"07535338d816a3159b3ec7b9f9f38a8d28f9e80199969037af71c4ae7cae8f4a913faf0395bfb910e235a178a7","nonce":"7da19d5120e43a5d2b4bd3e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"2d0dfa0fe8938ce43a866fec67eba5b86a543d7fd29b4eda5de9074b04b4f5d35d645ace4418d38d9cca66a79d","nonce":"7da19d5120e43a5d2b4bd3e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"de7a9c95d1aabe376d169b1f269d61c5877cc54b84f72588f5d323540abe035dd122a5ff3a6427f60a9cc80793","nonce":"7da19d5120e43a5d2b4bd3e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"3c9b5cf26453c1245ac877f57c173fc08197664809c1c90a8c5ea139a5b05027e0e156111984a6408cfa625099","nonce":"7da19d5120e43a5d2b4bd3e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"9964435dcc22d4dd7c086020eed7eeaa7d35225e050de2a4447f805b18abd3440be64b850518eb9cdb89efa33b","nonce":"7da19d5120e43a5d2b4bd3eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"808e2616f6e02634ec01814c4959cc87ba9c26603b8ffe97d23d256ec101a0bbaf667e2dc9a8541dc2b5177fea","nonce":"7da19d5120e43a5d2b4bd3ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"b02182bd2cfa166058e83749f496203db6d4c62dee2c641a1e0d3f0f28c382f1b91f7aeb92847736702ea9f0de","nonce":"7da19d5120e43a5d2b4bd3e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"400726044595de308a346d964fa997e6eba740fa464a0763428bad44fd9fb2eb902dfd2b26111ebb1fe16af233","nonce":"7da19d5120e43a5d2b4bd3e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"5061fd11d3f6d39b96154072d12a1554d62a242f317df1372258a696a839140cfd643145ce86ba139cc7270cd6","nonce":"7da19d5120e43a5d2b4bd3ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"99467df013ad19c142a51e0b0c267694284c100b0570fc379cc02e67b8408d190960d1b3cd0f44bb61d1b2591f","nonce":"7da19d5120e43a5d2b4bd3ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"9167a185d1387fca8551e5cddf07950dfc54eefcfe00a36de7d4b2f5cb4c89f0fc1361c2fbc789ddce560d59b7","nonce":"7da19d5120e43a5d2b4bd3ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"0d9d18e39d5d193b957eceec1c6d6f9ef0af76cd22a803920ac20461d08f68ddbbb8c28d2ea332cea2faed4d5c","nonce":"7da19d5120e43a5d2b4bd3ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"7f41469846d963218a14f8b2d8c97e757ff9e5883147615aa6cdf5e54f91cb01708ed78fe4da69aeaab3791c0e","nonce":"7da19d5120e43a5d2b4bd3f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"a29c4ddde70ea99a82f84eff86778ad97fca67d40231680f339b553df534f0c70ba96ba921f1bd373c45b0191c","nonce":"7da19d5120e43a5d2b4bd3f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"26256497131ebad71812eefb94f2900357ad55a5fb1a04c6fe364db2fc42dc1e9aad5f207d96cce9dcbb3693f6","nonce":"7da19d5120e43a5d2b4bd3f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"f3635a1a1eb1b5f14651f254d0589c9fd0632199884c4bb9f48808f8d86964c6d64b80c37a743e1222f2be2210","nonce":"7da19d5120e43a5d2b4bd3f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"ae2857a1b4701a445500f66773c597cb311eb6906b40bb6789b20302bae44a6d894fda87d4adb8443c5e69da5b","nonce":"7da19d5120e43a5d2b4bd3f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"184c174ba7bbf225b2d3fb574507b62aa17a107fc629fabd3137f76699a365c95ce12c4599a6c8f66022ca30af","nonce":"7da19d5120e43a5d2b4bd3f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"e523728324917fab4ed1b3b2b014ae76ef8daadaf1f6b0f862ebabd6c4cc4a8b6ccd341294f782d7987202f4b9","nonce":"7da19d5120e43a5d2b4bd3f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"bed320cc2d3c3301966d6e200e716d745204f3c4c1ba7b69b66d2aab50257a6211aa2910dfc99bbf8f011a8681","nonce":"7da19d5120e43a5d2b4bd3f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"5338f7cca2aabe2b636f49b85fa7bc73d2978bc6e014c2578a4d65ae2633c35a9aa5075963210a219f5122c45f","nonce":"7da19d5120e43a5d2b4bd3fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"c783d1fa20f7cddca4fe46dc0cc5ed6295286ac0d293a394e0ec7644e371877d8b038038ec74efc0f34a9185e7","nonce":"7da19d5120e43a5d2b4bd3fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"fea39a590ad1204b793ab27fedcc87ac0ce64b342b15f95308c4afe4e2c7f08ab00ce46501105ee473a21340f1","nonce":"7da19d5120e43a5d2b4bd3f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"8074f2c4fccb343af170ac634faab7dc7652b0a7c1689e99005713c9c6e4473be53a058ac637341f7b689d2d36","nonce":"7da19d5120e43a5d2b4bd3f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"5009d4ec24e076ede3dd3d5477a9db168a117234e61481d8d7b99f6eba9abf897555b82caf5ee6ce8ee27fbe26","nonce":"7da19d5120e43a5d2b4bd3ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"591ef9d17a1176d45d8eb916e98e5730d0b0e1ce753489c65617bd166394f1e497abdd091795081ba002325e1e","nonce":"7da19d5120e43a5d2b4bd3fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"23aae30296c484def1e4e8e9f6a675c98885bb1a01ce7f4b61d12670b77620920b0f717292e411ba3ae91fc653","nonce":"7da19d5120e43a5d2b4bd3fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"b7674e63a11679979d600e28243d5757ac6753b5e8cc59598fa97d1f0b57f73dd1e941773aed1fa1157985ccde","nonce":"7da19d5120e43a5d2b4bd3fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"de4378964d55d5e7a3521f50a5460f26a4dbca56d932765b22dbd048ebc288e2648451ab9b8657df062a324e52","nonce":"7da19d5120e43a5d2b4bd3c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"cf78bb996023dc1184fe45ba7fdc2da76fca9899b56d228602c10a70c08b2fec4558165fa291a65245a832b034","nonce":"7da19d5120e43a5d2b4bd3c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"4b15d43249ca8d094a6b4904a6857c3559a79a94b7a61c0e9132bb551dcf20d5c33d7fa163543782c05e5915a2","nonce":"7da19d5120e43a5d2b4bd3c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"50a2a061ab76c3a6b5f5ab180dd8b41925033bce3f882e41a54290c9b01f44c71b901798fc90448ad6d892b032","nonce":"7da19d5120e43a5d2b4bd3c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"546f1abb7e5f843ae87f86215a00b5e2cdcef5b28ce6f83032a8d2b86cad2861dae2b303403a6a08d66234c0f8","nonce":"7da19d5120e43a5d2b4bd3c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"468ea43f3c3d7a90e1b2a99533ea91a692631de894467493976f96010e11787e7dcca80fd715586388db2b04e0","nonce":"7da19d5120e43a5d2b4bd3c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"c4981e76fb443acb1e0f5475d6cc97bf7fc71da7e6ae90ae74b223d0f5ad8725bcfaaa9a1d72654ce00f10162a","nonce":"7da19d5120e43a5d2b4bd3c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"0b272552f1516465a53c86028516bc02a3f6c1deae3734002b426680428955d83c6abdcd960ef8fc61a03e84bc","nonce":"7da19d5120e43a5d2b4bd3c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"8194bfc1b8114f096734950eee42f415ce21466f84fd19ed6f9e1d66cf1e509f755363bd8a8e9a9fc2c67ccaa1","nonce":"7da19d5120e43a5d2b4bd3cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"c1f6fa77bba786d49412d98d999aa65fa6cca8576ddc15f2d52ae16b0a8a3d62eb74e3dcef77474a668e695521","nonce":"7da19d5120e43a5d2b4bd3ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"f56e3dd4a7c34af45e8fcda6e5b5edb7629f7d0a8ed4ec81b5ffeb382600c6fdf9c28869e1a2b0bad0ae7f0945","nonce":"7da19d5120e43a5d2b4bd3c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"2ab5d775b192234754d45d0fbf6d53ac55cd5b2e958c0ee57262f62ba874896bc354578fea347becf69945315c","nonce":"7da19d5120e43a5d2b4bd3c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"63f501a6c9f76a50c963462efd96d89a9a267f476532e0e915b6efe64324ab12f86e6c0d8663e69c1fa0252331","nonce":"7da19d5120e43a5d2b4bd3cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"85af6b61f68118fe6f2916bcef66a06cd313f01db86b5b557d71648df561e8b979afde448278eabd304f233c80","nonce":"7da19d5120e43a5d2b4bd3ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"ecaecafdf0a64bc3aba049a35c64fdca448b2512378fa61bf11768468aeb35e63191ffe6a258e84d00a9c5a776","nonce":"7da19d5120e43a5d2b4bd3cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"59444d8734ef18c41660794d2326d32af507b61af3187ee4223a5bd2fc9172737739a56d7d1446f5981b99d2c8","nonce":"7da19d5120e43a5d2b4bd3cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"d8311c4b49288f8ddb89befce3b35011a3327c6d3cb4cb23ee15da8c6f43ec8e94f1779bec4d335b5efda2e75a","nonce":"7da19d5120e43a5d2b4bd3d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"58f6a7cad16e594e5778042bf57536eb1dedb7e3cc26d7add715313c7ad511ee08101fac7c71de2178897755c0","nonce":"7da19d5120e43a5d2b4bd3d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"17579e9071388ad51d3fb9bff34afc5d7df07543c6cfa2030a619adc66e86f8b04358cda7a8fbcefd78d96bfb7","nonce":"7da19d5120e43a5d2b4bd3d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"47cf2f265bcd7b6a1adff4edce0af9c7df54861b39c27be9cc03e6a0760c8c8ee0a27b542f8bdf9a2b5546c9d5","nonce":"7da19d5120e43a5d2b4bd3d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"22705e373980c2f6b64cf6af98f391277c634138e2e3dbca8133f1f37d96692573425c0b75da5647bfb89991da","nonce":"7da19d5120e43a5d2b4bd3d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"d3487af0b99e39b61169fa5a5b5c2779454032c15f0ab4c87c43dd43dea7ad3502de5f774ba0069d82d9b9cf55","nonce":"7da19d5120e43a5d2b4bd3d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"17bff0f9d7f58e1b9e56b2dd0bc824203322b37a454eab338a8bc34a9ec24bd46c4bc598ab7bfa5370ba16ac7c","nonce":"7da19d5120e43a5d2b4bd3d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"89a7f3ba24e6bbb67e4a6cb1a9e1dbaaca908f65973296ce741b88dc8d37fd0954ce066941881ca71280540a66","nonce":"7da19d5120e43a5d2b4bd3d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"bc677aad9194723a0691232e379ac20235693fb2a9ec1ad8904f9b1203f7377a1e98001f431a230f515b4e2dbb","nonce":"7da19d5120e43a5d2b4bd3db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"0f5ff92543f526a312ad02fe1eb53abda3cc8cbf3825c8e31df6a2368d23a84504556e02497817178b6aa01880","nonce":"7da19d5120e43a5d2b4bd3da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"904a9755907f6eebac7a22be0cccad4439a47c99e17df3b947891ac36ed3a6961c2f4b0d90bfe5b6c3380df8f2","nonce":"7da19d5120e43a5d2b4bd3d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"60161484f9b8969e1b88c72afc5314fb4662f161116e6145108352ef13d4836003215dc67fb16da96a6afcc29f","nonce":"7da19d5120e43a5d2b4bd3d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"da4166f9ff35fa7f196681218c4007156dbb9d5174322267a7178fc7343a9328c8e228ab7b2690b8d3f37848f7","nonce":"7da19d5120e43a5d2b4bd3df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"f89f4a5d330c764dc0a6d27640c124d6b8fb721f9ee0b908fec759669e9f9695edc234576d2690768481735aa1","nonce":"7da19d5120e43a5d2b4bd3de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"35f0bdf865077d32e9500e9e5e025b195aa88307cc1cb32945ec75fe773b5a71b8b342f10b169b8b6e274e6c48","nonce":"7da19d5120e43a5d2b4bd3dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"4cf9f236e23c766b7a72aa5b50a1459de65be230482d4e3033daeee3f2d5c423fdf5ec92fd31c407b2de51f2ac","nonce":"7da19d5120e43a5d2b4bd3dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"689a6a42638dc90e04dfc4fd50229441514661a786a0ba9ed5e29c7a94385c135709d80098d57ef124ce45198d","nonce":"7da19d5120e43a5d2b4bd223","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"4f96318417124085b593b372ecd9eccd782d8c83e3b56292de465c3a8bd39ca7"},{"exporter_context":"00","L":32,"exported_value":"77dae58534315ccaaf4fe4867e7d0ca952b4a3b2b1e8a3f115228124710c5217"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"1b6d7614dc4a0bf5098f6b5cad86921d63cf20def7fd367cd3bf66dfd0c1c8f9"}]},{"mode":2,"kem_id":18,"kdf_id":1,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"6dd4e24d25651dce8bee68b64b43019823a02b407ba96dbd4e956ec3fe52888b1c02b670224870952e54c241b38c3a5e6bd5288387f42ab63d2125331019397ecffa","ikmS":"f66724005b3b9391f6be5a1ae1ec4d92a242a2f936257f45970a67f024764f45a23939dc0339847d214638afe0f56b090020083019340ed6a59c8ee2f992bba18771","ikmE":"cd5b426f74903baf5817e692b30edc58a550bded32084ffba9d09c2e24c1b4bf2238895fa77a39b8f115ddf1ef510090cd2313276cbeef21c6963f789162afe328c6","skRm":"0146183cb00fce21f248806940247421574348bf0397be4600ce3f8643b7b40931f6ed6b4af6a8096c0238c999a58cc49a8b2004006baaf803d278da5a6aef077496","skSm":"000d14cc07c10eb09d2d1c434fa3f2ef6530be89dbb6f18e457853fb6b0fd5a3e3c21e97ff7e58576f8549b76dd99214f51acdb29c59a7bd5ab35138d082478b628b","skEm":"018f677d1902e0ab6788d721182da986df75905691b8e2cf611bcba05050844c833463ed9e5a38c67fe6df1e8b83d2ae12e9fb152e736490a722a576d2a7e062a031","pkRm":"0401d47df677648dd3d2883fb3dcf5a4a82eec36072c2440e1c7f1bd286e3dda59f15c4d93996a42aeb6a4773417b6dc7d3a868a89f994188d2dbe0e6f4d036346ff750142216c824077b3b86ac744ceefbdda2a0f2e0fd91222a89a843ca86bda532dbd963ab7b20053d4d8e7d0e1f4e890dfca8c3e04a86143a53cca0cc193d13851c918","pkSm":"040035edfbd9a037e1c46fd5f2c31844b742200586297a9b6c0649181494cb0075944b005f86ee586f7f516936b3eaca190d5715a4ce63ccff6a101a529501b50f8dea0100fcabe77d987ea26ebfe95339d97002b6395393c650d1eec60562b21a85518cc60034f43da44b81c9d6aa87c565c8839fbada35412b2df959e9e2bec16fac8f32","pkEm":"0400f9777c3c20be9755a082f297afa3fbbff0cd98cf79300946b65ec3ea6dd18fc983da77fe9232de43eca5e8bf3a73515d03c992ae88a60f342246f906de6895ebf901bc798a00137e8e680ff74deec532d0fdff3b4b6d6ffdf2ef7488a43e3fad9eedd20567561c28589cec102d552715d1bd20ba1ec794b51f62171801aa7adf9bd811","enc":"0400f9777c3c20be9755a082f297afa3fbbff0cd98cf79300946b65ec3ea6dd18fc983da77fe9232de43eca5e8bf3a73515d03c992ae88a60f342246f906de6895ebf901bc798a00137e8e680ff74deec532d0fdff3b4b6d6ffdf2ef7488a43e3fad9eedd20567561c28589cec102d552715d1bd20ba1ec794b51f62171801aa7adf9bd811","shared_secret":"897673ada42b326ed74d39dfca70b46a1c879fe1608d5f58c7930d318828547b057ddc78964d8c29fd66720d3512211b0c8553880004093dbc3798426d8e2c4f","key_schedule_context":"0232e749440c54987db01af606efdb4d140f0148ee254795838e2d23d4366e1fdd97e18b628ea977f60a69bfa0647402182d019d3a0b59d2dd03624d028053dee1","secret":"c4a7d6f1af9390d86bda887ec9e5e532dc7f65a2c136fc9e8562561954e3bb4d","key":"53a233bc51f888c8b12c63d773166056f916e6b52ad6e12c7b8e6743229a9464","base_nonce":"ce22cf03922cdb969cc87453","exporter_secret":"a8bf2c9bc7771794e855ab355cecfdef87f9b5073c03f56dab5cd98acb3115d3","encryptions":[{"aad":"436f756e742d30","ciphertext":"2657e8ad51bb2f19b333920984971f1768e1c4fd3548c079e836a1e8c5f4afb04dd8d88884a401491605af7dbf","nonce":"ce22cf03922cdb969cc87453","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"df2c9f11be4f199a253818fd8f6865fb3a5f143de0a75af7f0054ab42661006d3eb7faedace310bc1fe6b4d0a9","nonce":"ce22cf03922cdb969cc87452","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"e1f9c272c3d7e86dad017d7b3cbd8fbcfb23435d133aa8fd6c405bce8f268cfc742625f081c7b41657f885baea","nonce":"ce22cf03922cdb969cc87451","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"7facd6304c02b7675fb1a8043e77150662caa74fd56bfa785d2c1a9ab682128406860d5c47ff338ad79ce66551","nonce":"ce22cf03922cdb969cc87450","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"60660eb194d4be570821a0b00e8bd8ccaa48b2c4d9c1c7f3393abd6361d49fc2e0c368a0c6644e7d6ac482500e","nonce":"ce22cf03922cdb969cc87457","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"1d18e307e8d3411eb3114678b0fda86b00de5857fd2542132d6d4bc758cad29d7c2557abd8f8ff92f7a997e7a5","nonce":"ce22cf03922cdb969cc87456","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"b9e7198ab6a7957557376670880d9e6b64b9c6b8aff62da57f62fe5f98a81ba48c9f5b40ef1af641307aab7b9e","nonce":"ce22cf03922cdb969cc87455","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"14a7e91a243f41d501658eb543254b5575cbca11bb95cdb399e0b5330110170ec46e2f7b5dd685b9fefd392b99","nonce":"ce22cf03922cdb969cc87454","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"08753926f5c0b3666a7b7e0215c79529965e0a459c3331ebde5519543861cee8576e0a932024f5535211b18644","nonce":"ce22cf03922cdb969cc8745b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"f192d44e640d7251c99ab25616f78da75d8f8f8e7f41c67761cc32d78a23dfd5a34fe6718e4170c94c9ad82df3","nonce":"ce22cf03922cdb969cc8745a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"8115152e950aae030a19af2554a5b5bad6dc242a30a48d8a0d82c9cccd442794f994a81c0200cc9d27d98e5a5b","nonce":"ce22cf03922cdb969cc87459","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"c86076378d5290b2510a82d82f56fa78c8b434e33b0479e73187b962c2da933b2c949dbb038e100f4f202daa54","nonce":"ce22cf03922cdb969cc87458","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"9f9879585c7c83db0a9df5e5c303abefe954b46230fcbe7ef0ceecca47fba980518ff4acf3149a89ba93606a75","nonce":"ce22cf03922cdb969cc8745f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"998c85f828b309fe13811b7a059cb53a3e34fa8de9676967ad4c63a555a3d51ed99e093d1a32de8bc1bfa0554a","nonce":"ce22cf03922cdb969cc8745e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"a6967130bed8e8103802fd7a634bd0cf0bb8a1335aa9a52a0abbc7873a29c4f8e01e6f0a4f440f2dbc29b9d6d3","nonce":"ce22cf03922cdb969cc8745d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"48a8ef176a3c7c9c0b7b29564c6273e57a63a957f1acc5fdaa964afa545acf2686189aeb51c12b3bf31cc798fe","nonce":"ce22cf03922cdb969cc8745c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"6fa40f9ac491f099be780ac5fced143acd50e8da085e10f125c4e3de628604035be9c24070fb609178f42b58e1","nonce":"ce22cf03922cdb969cc87443","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"c385ea1f610788e45314f4ec4ab807395ae05e863b2918a225df3078c889aeb4443f2fa2ddbe79c2113179aa5b","nonce":"ce22cf03922cdb969cc87442","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"68ea7be4af181c5b3fea081872e2dc8ab2fbc1180ecdaa92a347fab31b9cc05364793223736ef51ba67c5b40b5","nonce":"ce22cf03922cdb969cc87441","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"d7486b2425b40b0fce5b27d1a2ed26b5d0a217718f8a87e6f2128a42007aceeb25d127a5a986d2d73e6e86377d","nonce":"ce22cf03922cdb969cc87440","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"5a03f1fac13a9dbea504430ca57c4a318593baf61921773a3f73b34e35ec288dff5ef56e408ad6beaaaa7724ed","nonce":"ce22cf03922cdb969cc87447","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"7531ca544c92156e41db800c7af48ddd680876b55e6b65a3cd3ac538206df6e1a7235effe65bf00efc78d815b0","nonce":"ce22cf03922cdb969cc87446","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"d0e469940d8f8b5c887e21c5c7d0304bb4db56e282e06d2ac38f1c4596173846226262e39a01ee31dbd073a027","nonce":"ce22cf03922cdb969cc87445","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"3fb862a32875d87a0f62039a7baab163188b2dcf8da31934aabd5a45798e5ce7871457bd0ce0a50f5e279b9c68","nonce":"ce22cf03922cdb969cc87444","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"5f2b2544cce88ec72d8b6db0693cedcbbb47a2c6327ec711baacc2eee5218652006e505bf7b57cd9e1ccab2612","nonce":"ce22cf03922cdb969cc8744b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"7e027a041e701b4237740a275acecfd72f768fdc5cd4aa7540e54421c022cc4f52167d048381db79441c5c7280","nonce":"ce22cf03922cdb969cc8744a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"519e755e87557740db7753fd3bebbf31766a79b0137ac47f406f7fc839f49a6fde3e3330309cd6d036e684f23c","nonce":"ce22cf03922cdb969cc87449","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"bfed129dfd3a9a3f866144b46414c785eaea6eb2433da38dc478cdab7e632b635196ef04dda2ca6d44b829603d","nonce":"ce22cf03922cdb969cc87448","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"b14b97a751329c688420c9ff647116d4a66a6d9ab7cae2c38f8c56e2186fe9274cf27857e6a237225ef2dc1d4c","nonce":"ce22cf03922cdb969cc8744f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"8864a0c297435cd5c79414cfad8ba2d0592c24174f7ec3fd08da2747864851fb2f5458c51fff7041cd32175dc6","nonce":"ce22cf03922cdb969cc8744e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"466df74cb795da27ffcb4c6a80f795dcb2ab2184bc51f674adfe118ec107509ca894fb2aa1957546cefbaeab3f","nonce":"ce22cf03922cdb969cc8744d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"714ff3023a216d380f92b9371e6541681a33e5ef1200b3087b962c3468682cd71ed4f783ccbca4c6d5f5a4cba2","nonce":"ce22cf03922cdb969cc8744c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"4062bf094b1a4a6ebd4ce19c90e904b906b5916908e298cf168192847b9e3febb687c749fa0559fe8d8be970f0","nonce":"ce22cf03922cdb969cc87473","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"9f23c891b0e3cfa6342115ef2bb33176d6a57271ad001d7a3ca1468ee36efb3d4bbd125164e0cfd28a57ed4987","nonce":"ce22cf03922cdb969cc87472","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"77c3fad03d185e1847a989b937fc0cb37d4f4cc8674b97df07b8d339be3f18b66a040da2f2ed2f030d50f384e1","nonce":"ce22cf03922cdb969cc87471","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"2e552fc34688f559c5a37491e8f171f67463fdcfba58285ee6c321a7913dda648edd2fe411e8a16994a9c92a98","nonce":"ce22cf03922cdb969cc87470","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"c8fe6aa9b9c1ec850fb5173928417e4ad6263d492ecaab80fa4982be97fe2574b32162834ee5d4aa5f952e9b6d","nonce":"ce22cf03922cdb969cc87477","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"cd9f26ac5ca680ffb36abe446e5bf5ca4d21ace3397f37ef89a1fd807c4aac2e27c735d40bdb87c84cdb77cff2","nonce":"ce22cf03922cdb969cc87476","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"f2ddfe22d3654a90efa75242d1bddd39ae8e5ab633d11ee6d81797059b5ece8fd646e4e33147b4b7ba1214dfac","nonce":"ce22cf03922cdb969cc87475","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"e9e33ebb6f307e2fd906372800e621c390b985fc15f61c913b4f07dec10d88529b9eaa075c5524cbaf56bbf10a","nonce":"ce22cf03922cdb969cc87474","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"66d848e264a8157526f638fe453f589512819a19960928b7282fd4237f8284facbc354edc1f6b2ef4231d22acb","nonce":"ce22cf03922cdb969cc8747b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"d36cdcc3084c736c2d82fa2f3cf3b67d5fa5438055f1d52a48886def006d893e43b449bd444b77a2affc2a7e1d","nonce":"ce22cf03922cdb969cc8747a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"d374fca9a5d72a261f682d9c880e5b916bd86027c83644ee9970e587cea87692d26bc8edf511715a8317cd0dda","nonce":"ce22cf03922cdb969cc87479","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"79c2753b2d3f45f1ff69c9e9128eb83a199ea2093bbf424c91d94ef93df900877a9ae20b6858870c2b514eba27","nonce":"ce22cf03922cdb969cc87478","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"5924a8f3eedf4676c929eac1e16442d4e046da3f02e83c36d801c6e0f8f46322bb8cd9a20baf507f7bfccdf510","nonce":"ce22cf03922cdb969cc8747f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"c376e1de8b0ee2e41c9391cbd0870eba17c090d2b5c8b640df186df851b3a5b940959ce43a8fd937c039afbbbe","nonce":"ce22cf03922cdb969cc8747e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"38655ea9cead7c3057b0826e5b6b49ec3cd2e9c95812eca3e5bfb8f0e358176915b358dfb7a04da9f303c3fd4f","nonce":"ce22cf03922cdb969cc8747d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"65609f66bf63bde05d5bc14db1f1c5ccb2603d13b4ac3c5e6f07cfbec42e6dab3937f2bafebe26d89741384aa6","nonce":"ce22cf03922cdb969cc8747c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"10d7df6584ec9bf20a65b1fc52ea4100975efabd6d870b4158ab5b1efcbd668b4b7fc0ee1cfd6bfe4e932e9413","nonce":"ce22cf03922cdb969cc87463","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"e49792401d81441de071072c19db87560939028d53d868ce79dbc815f2afe41161b6d987f8439d6b3d233b50f9","nonce":"ce22cf03922cdb969cc87462","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"7b64d919c9bd540388c9173b0f949a70068da95d41e22f8aca9c2c9538845443f120d63853581383d43aecbd7c","nonce":"ce22cf03922cdb969cc87461","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"c8a951c6bf60642e414804f0e589ef756883c05e559a6e77b092d61891fb772f50a5c8a3c97e53dba6f9ce62fc","nonce":"ce22cf03922cdb969cc87460","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"aa4fa63ee7259c723c249f4091e301a85376fcf3a00c210cf0a99920a634ddea9bc89d94e6c773e780c7ff1676","nonce":"ce22cf03922cdb969cc87467","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"11b11930f3b62d6e50a33818219ffdc8cd9c7b3a950134950fd41b27600b3a9e44c25e6bf4e4eaa3bc18151ca6","nonce":"ce22cf03922cdb969cc87466","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"59f28818cd288cf29a9f82e69708e63dfcb9c0c7b30559c8086340e740a61d6538a65891fa7e3abd2ae8b7f225","nonce":"ce22cf03922cdb969cc87465","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"de7f033ef61fc8d174fc3748086e7e9428959f45b6d9d50bf26be5f87a924be6fc4d11532ef2127ae7e2142248","nonce":"ce22cf03922cdb969cc87464","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"91b4a0a82facb089e00221f0b3a41df0f49dca62a0666b59fcda98d65f799853264c02fdb64f67b34c79d35bac","nonce":"ce22cf03922cdb969cc8746b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"e9715c06c3bcf4f18ffc06ef1291db6a733909bc26bc6747124494f159a76d26a40649470914ca5b1d32854f32","nonce":"ce22cf03922cdb969cc8746a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"c891231e752d717f8e24a0e7169a64788760449a825184855473b632b7b6441e18ed19c13e89b7990d2f15d167","nonce":"ce22cf03922cdb969cc87469","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"8b79ac1f3caf255dbe58dc5de07455cadbdbe6fd8bd58c107f989c231ae318016c5295086e73d41b4229ad7118","nonce":"ce22cf03922cdb969cc87468","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"6519f4ffabd4cdc39e041c64ecd82a90ac8b9c3036178f2f031d352a9dc47549157c1f0893f472324f32725371","nonce":"ce22cf03922cdb969cc8746f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"fe62a6b18d9b16b0534a14e2687658d94db83ec2f2ceac89124ff11556cfe44f433bd20371e641cd2da0ecf4f8","nonce":"ce22cf03922cdb969cc8746e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"351009706bfbfb8b623dcddf6f7747a45b04f33587f26972bf4375d3a7d81af150dac1de43e1480080204c125b","nonce":"ce22cf03922cdb969cc8746d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"e1046a8785c558785b7a1819a5608b7ca41fbb9a88823f86f91c3034e3b442444ff28971b4d1f4fcf5520147e0","nonce":"ce22cf03922cdb969cc8746c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"53c2a3e593337b25592fedc9a18446b556a1519d37e9cf6550b80b96e4b095e6b71c955492c6b9ed40425cc5ef","nonce":"ce22cf03922cdb969cc87413","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"eaf56947531b269821ca35d209c7ecfe4c769711e4b2a3984a59c95c04bf76bc7906171b80a0abb98af71562ec","nonce":"ce22cf03922cdb969cc87412","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"e6c472251d5d3db4c993eb6bd6b176bb0b40767f674f9a43b9290d0491af52285e8574d7f78924990bbebbfbf3","nonce":"ce22cf03922cdb969cc87411","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"e793af307bd1727d649e9c02b368bd1c34313c002418dca5df34eb2afdf3af0caab616e359e877928b82e9ae18","nonce":"ce22cf03922cdb969cc87410","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"e21731626dfc27c1a31b907af189aa3f91ebbdb9dcf3cb05d371de54ab0633e887b0e0e6d67d7bca1cd47958c5","nonce":"ce22cf03922cdb969cc87417","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"1a3ec9289b4b247c23a3611a158c97440896e03e1d7ce7cdc38c7f2e9a89b298c3c4581d4d3b4f0ee24cb771d8","nonce":"ce22cf03922cdb969cc87416","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"38f265c2c44e8d3066ea31b224af532dd97a29e11a3cd0ed9a7e0b704cca4ba854a0b13ca54a4490c043603da0","nonce":"ce22cf03922cdb969cc87415","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"fa1e84d53829ab1fde1c6066d8770f0a968dc6f286c9a6e8e9e0e36bec0ac5419f7c0b1056b0f8f332be13af1e","nonce":"ce22cf03922cdb969cc87414","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"c0d03f581b0ce8b29f7a5194d715135c02a0b13cfa7026f6b6cc66fee2566d29f99722f5ab3650083f960924b2","nonce":"ce22cf03922cdb969cc8741b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"5c6ee653b4ceb78232e4f97120f1c7e8509ecf6f7a1113fed866651e3286bad2b7f6e099dbadea5444daf9d117","nonce":"ce22cf03922cdb969cc8741a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"d35aa65bfb6ed44f239bc7bc036af5370823869d0cc7da5b693ee529af6744abae2982047389a04cf28b6838cb","nonce":"ce22cf03922cdb969cc87419","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"c564525df9b4c400735ad3230843daccf842873ca747d89040b70eab222ead63efe00b7e04e254c3879653703b","nonce":"ce22cf03922cdb969cc87418","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"6b2813cbf67419ceb23bed8ece31847e808ea0e9414e7db67fa3622a9789eacffd0c169352c82e558c3c89538d","nonce":"ce22cf03922cdb969cc8741f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"d1ab1847e513bc20aef3796c1cdce86005b824d693e8a08cae0930cd43225113cdc9c0a28e64fa89e9d28f9c7a","nonce":"ce22cf03922cdb969cc8741e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"3de5d2fa379824173fd7227fb204e88d94e13aa4e6601f9b2510a3fab649dfee9dd5f3e1328fb0c14f10027ffd","nonce":"ce22cf03922cdb969cc8741d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"da143dff3b6c47cb222b2484ac8b691d725e0c083b03b308a5ba48487c9680255fb814b04236659579fe71d3d3","nonce":"ce22cf03922cdb969cc8741c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"e80f63657df119ff78024e8b15090e06e6b7cf78140b1aeed17968c3fd04f01e7fb99435ea1185694db8bed6fc","nonce":"ce22cf03922cdb969cc87403","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"c5b65d95b524b5f673de4393e44ebe4368d3faf7897ba16e2f2febc8fd94783fde0a4e8a18f84c6e66463682a9","nonce":"ce22cf03922cdb969cc87402","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"4824a3b2dd9ad0400ca04e9b443b7cc0e1020220cc951acb355d27a2329ae69f3fc857c0220f95276d157081f3","nonce":"ce22cf03922cdb969cc87401","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"1e5d6e443e94802bb5d61149b1254c957f25a8e97bcb502c03dbd0cf601a0df378441a1d6274d1a2ee03d767a9","nonce":"ce22cf03922cdb969cc87400","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"fe17114f20d6e2768f40af3a6d52fec406f01d59a7d816757316611e5682a6e93a11ebfc172a17a53565ab5988","nonce":"ce22cf03922cdb969cc87407","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"367316cdd55fe6e5852ac996a4a6e341552b2aabac2c2ef2c858e7e55b32a740944f3ac16e6dd6110b03ed9aad","nonce":"ce22cf03922cdb969cc87406","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"2a580adfffc0fe0268786040c08494194a85b7739fc57bac2af066d05b972a5eddb6f2ae65e6e1513d5709bb55","nonce":"ce22cf03922cdb969cc87405","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"36005a7be93d78c3a5740cb0715331b369599e22d03ef0eed929cd2e2dec1924e0999234b9e1d6ff6a8609c47a","nonce":"ce22cf03922cdb969cc87404","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"7dc59a769ceda7f7398309acd7ff2cd828b253e8390f1f1b6fbd42bb4e2fa2e5ec557dd7392a90f18c221a6034","nonce":"ce22cf03922cdb969cc8740b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"235e8cd3cda8ec6b40bb5b43c71580c31b050a9b36e96e1f730ea254798f1e9b5e6b40aa35c70615c13d31c292","nonce":"ce22cf03922cdb969cc8740a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"6d1c77e1b4a57bdd3f6940fa385ae745ac2f526832530e37c12a0bc7560d27842ff9e0735935550e94e4bc78f4","nonce":"ce22cf03922cdb969cc87409","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"a3ab04620c4d39cf37bd52877c18ee6d9a3553a15fe3b37d9edb60a35122e4ec87719264aefb6a049df7ecea9e","nonce":"ce22cf03922cdb969cc87408","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"7792e1d77112f55139a5777e466b2070fb66798f9d0edc808ff3daf3a1b0b37ea9cd03411761d68927a09be544","nonce":"ce22cf03922cdb969cc8740f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"97b4f07610884693dda9076f0bf7b1db3c73c2daa33fc2044b7de98fdb70867b5c86ea100d2876f97c2e7e7a24","nonce":"ce22cf03922cdb969cc8740e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"13526cd66769bd304370316fcf324ff8946af8e987917b87239e042cb2b1c98de0e65ceda657a08f86336a919d","nonce":"ce22cf03922cdb969cc8740d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"9b8b4462a7e12eb4fd8573d31e41a40c09e22c91a9dc076952e6f8ed8b5e93c5ada2c8767757e74035ee16c880","nonce":"ce22cf03922cdb969cc8740c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"57f0dc24278c8c45a95ce992027feb3057139b3a700f690df2aaee32714c9fcd127efdecd6e665c746eb067e95","nonce":"ce22cf03922cdb969cc87433","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"982db2ce4eb7191aee2a0b3267429df03aebf85754965dc3556d96259ab880d9d7aff47b4a0f89df6e55cfb702","nonce":"ce22cf03922cdb969cc87432","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"ec7543cfc39990fc086ca61dc6dcf7da8ef9e95c9a0a4ed1fdb41f4f99d943d77681d9ae711cf50f4d9dbb91c6","nonce":"ce22cf03922cdb969cc87431","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"9a0af3e7a34bb3daf982798b184841dc4c47d72e48a1f6f2e6625d402352bbd21eb256bcdf5b29f37228ba0b2a","nonce":"ce22cf03922cdb969cc87430","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"652aba7811f6e5cd8e2d35d68ed84a98e456964e0887c518ed7eaabaa8e89ac0ae045856d7258e93ff1c3a6a61","nonce":"ce22cf03922cdb969cc87437","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"fb4ede8a9a215fdc95a100a5652318827723df1eb5a938116a4481f3fb3bf5a254d43ae85b88d574e8c2066151","nonce":"ce22cf03922cdb969cc87436","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"5257e3f4698211da815e5a0f6a6262ceb85e4a52b5b2b15b2c98cbddf4466f82882735943e5cba48ffe0cf02cd","nonce":"ce22cf03922cdb969cc87435","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"834f3e8938fc3f800b3ba2414538c78855e6fe7cb82317e245b3a1c4fc7ce24fa191656eb6cc9c96c02b98bdc6","nonce":"ce22cf03922cdb969cc87434","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"21ad8744d8788bd39e2c17dd2296dec82d1da323b261ba8afadfec43f49e8d4bad8c6793f4ff076a0b979c051e","nonce":"ce22cf03922cdb969cc8743b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"633b32fcd998330044bdf4f940a4c1069965da4465a979177c1b66040da81300d0c0312ff3c277edb5a5799357","nonce":"ce22cf03922cdb969cc8743a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"f9a6abc0a77363a70264be62ec7add86bea3be32e3458d6af1f87e1ee900b701ae414a8b0d6ca13cd731a6a17e","nonce":"ce22cf03922cdb969cc87439","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"b5b6e7ce1306eb2aa8563e316510591dcfe9f3986c6e2ed570d1d6511132327f0b9d66e9a8fcee2b2c4fbb1bcc","nonce":"ce22cf03922cdb969cc87438","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"b6069d7918d2fe0845e93b32333e137c562d8519dfad17e0c5059eb1d4cdaf28eeaf791154ef0809c78bf5f7f1","nonce":"ce22cf03922cdb969cc8743f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"621d6af42493ea3e038343565c8f09626acc980c3cef2fcc3e83770ab65ef9e32c9e949889595b29db752637d2","nonce":"ce22cf03922cdb969cc8743e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"30e1b360970391a0e5ba7e3bfe7ec1d5dedb3b93b4cc7353d71a2cfa32073ec087e7562924ec030f4b98bc6d6b","nonce":"ce22cf03922cdb969cc8743d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"99f22c14a5299c397a41e5f8217ac8be322c5a7564ccdbe5a6a8d40e215acbd7f956ca5a7024b6c5ee335960a9","nonce":"ce22cf03922cdb969cc8743c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"81c583c10c2368de3a607d4fe31d3143f27191303cba7fb716997928a92f97fb56acf677b40c891f9d6cfed1d8","nonce":"ce22cf03922cdb969cc87423","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"82d0f35e04602abd6acdda6791fc7cb4e3bdfeab01696d13675ce7334dd5dce7e5d06cbbedb8b49e049f3486a0","nonce":"ce22cf03922cdb969cc87422","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"56d8755601a1b0828693e951b35107047203d901bddd3595d8bcb733b0b0022f60c5c1e6acf40af59a24ed2f8e","nonce":"ce22cf03922cdb969cc87421","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"211a6f0f2413afddacdfc99f37e3ea62a9a02a14df72149e92c25e1e4dd52949bbe67601ddb65e7cfeae73b8dd","nonce":"ce22cf03922cdb969cc87420","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"aedf99c7a35518b1d746b2a6214242b0114aa48d8db18f6e50c8ed3c5104ae07c9ce75f1bf113deb51b58f7513","nonce":"ce22cf03922cdb969cc87427","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"c794031e85c7ad7aead515d4dc3fb0d56ec53bf4e8e7a37518c795ad25611abedebd5b4e8b0182cfa7b99df080","nonce":"ce22cf03922cdb969cc87426","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"3021f7ba52015299f58b4e31eda05f6a72d54b44ccb225263681821cb4512fa6d66c58e9ce942f5186f548312c","nonce":"ce22cf03922cdb969cc87425","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"c614892937943004fc45a9ac33d0c27b5638a22a8e5373b86cda258c1154f8887f1253f7fe5e58fdf9fceaf054","nonce":"ce22cf03922cdb969cc87424","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"99b74b489aecbc5ea9428cd9f1b7b978efbe92bf5a3d46c8e55aabe735d0ae8d23201a1d2bb1556b3f0076d35b","nonce":"ce22cf03922cdb969cc8742b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"fddd0121f16dd166122e34e05e25afea5ff49da4695aa29766991843d0cc96c26fd63a27fa0d7b0bb84974483f","nonce":"ce22cf03922cdb969cc8742a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"19b93ec2742b7ef67b1ae1a8134c4e6a68fbd98d1e9a15fcc2f04456e8a80ec8540c2fc41a698304a66309a578","nonce":"ce22cf03922cdb969cc87429","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"7a32087a0e19e8dae92a3826c028ce50ccdb8d38ebb0893b74147929ef51272d08f325cfae3aba6363d7826509","nonce":"ce22cf03922cdb969cc87428","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"2816c43f83d340f7ee5244f0dd30999eb537745dd4bac538224c515849163726810bb0d48c32a873e2fb8ec9b7","nonce":"ce22cf03922cdb969cc8742f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"598ced8fa9836b9df33e647baebe94b98de37c670eeecb248134fad44ed69d8b26b7aa3893ed17c271f18357c6","nonce":"ce22cf03922cdb969cc8742e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"3be9808dcca4c1430891eea3e6ec166b28b4c408bb4db7de8e52f28718ef1868654457d1d639a770341ef0147f","nonce":"ce22cf03922cdb969cc8742d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"379f45bb3453fbe201ac282be43e392f5e16af977c41cb85a2faf74e19a5585004a434ba6cb9777fc6f54bf051","nonce":"ce22cf03922cdb969cc8742c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"627f6bb1a12bbeb96fa517eca18369d3eb1b63b18f05c0ae3748d0a81f63b58028d1579ac7cbd254645d8c32ec","nonce":"ce22cf03922cdb969cc874d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"64ecd6bb2346e6e7f01e0fc8a8f6c335ff3086f702ac9bf88f41a7f19bc77e3083a7b71a79906435887f22dd15","nonce":"ce22cf03922cdb969cc874d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"0c9e2f616f390c7f83566d780a98472116bd6d4edd3bf25b881c843fda6635c9bef52d006fa0a67ca1811c5b28","nonce":"ce22cf03922cdb969cc874d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"d531982c7f48ac517157f6c9003673e0cab4e800a0127c5260c1c97b7c4f34afb2c8ffb7f236ce1269823f69b1","nonce":"ce22cf03922cdb969cc874d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"f5d54a5d0004e44e73cca8466a26634c93ff10e3a6fb0c5e49f372fae087dd128258d53c2f7b7b4ab035019880","nonce":"ce22cf03922cdb969cc874d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"c6f56894a7012941e8ddf0ae20e92989d3cc7b17b46a3250a17eed167282371175df717c88b781a685b2d1e6bd","nonce":"ce22cf03922cdb969cc874d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"5e6c50781d4dd7e4e6ea25db9320f4c2721a8d8aafaee8ca05989cda815830dcb96d68c4ff852305b02e67afd3","nonce":"ce22cf03922cdb969cc874d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"947a729fd6ad424cd30bd1aa05b34bf1ad5eff17487d4125bf9c2162ae64dc7161bbcba6a92d3755c763b16ee6","nonce":"ce22cf03922cdb969cc874d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"da012e1173e4b8b7e59a12614ff87a642c6101647e3f9729516f418431bdbebb7f8d8afd2c4631a03fa3fdfee9","nonce":"ce22cf03922cdb969cc874db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"c39a2054417d242006328a03160cf6f7ab3bcf24fafd17554e94ad10486a1b9d04df94e5747d1e5dc2ed120149","nonce":"ce22cf03922cdb969cc874da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"1beb4447635b7726e82f6554cb4273c3cb306fa09c3216f564c64c48189ea2d20f9cfad7b970fd2d901e078235","nonce":"ce22cf03922cdb969cc874d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"51fd0d3dcd668703b1b42ad8a7c33de911071fa787bfc0ae60c5e6fe1be32f581955db57e24fed003c90685d87","nonce":"ce22cf03922cdb969cc874d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"34a4ce63cb10c95b23babb08a20176f4c80a741d4469fdc4707dd18f4a43a2264b74785ec9adeccff22098901d","nonce":"ce22cf03922cdb969cc874df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"378be5f581888191d04fcbc885e53b38b939fdd685a278fccc13dadfeb950e09f736003ace3c4a1b20d4c1e244","nonce":"ce22cf03922cdb969cc874de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"800f24c11f1529b118838ad3abf1c89d23cb6f581d56b2ffc846bcbec2307caefe1a1af1cc69f860f204d0a29b","nonce":"ce22cf03922cdb969cc874dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"41aec3ea509f5b502db132135f08a30073cd456f561611c133000928feb6e9369fe50b5f920586ee972908f10a","nonce":"ce22cf03922cdb969cc874dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"d3131d815906f50431904af008ae95ae8e6392da5debd5abbded977daff9691ef7e10826514c7d05fe41c6c242","nonce":"ce22cf03922cdb969cc874c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"2e396bc615eeb08ebdb6adeed7e3df464b2d7b188507fda1046cd1dc45a818fad40889854f3a79bd287827cef7","nonce":"ce22cf03922cdb969cc874c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"9328c80d358f0afacac36f9b3f92ac352720c6c59d264b94542e69d51d15cb374e4569d4c7ab4206b1f90e5776","nonce":"ce22cf03922cdb969cc874c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"1076230a37c510600aa89e898105d29a32bc63ccf8075e150359037f5b8ab15155caba69f6ba66726d9ad2fe35","nonce":"ce22cf03922cdb969cc874c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"f3a9f97b8fab74c7900e5f0ae6c0c1ce6ce8461368205cb77ce5ee53111536752821641f1984c33e623560bea2","nonce":"ce22cf03922cdb969cc874c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"d0bbd55aca5e90bd9688d107e9621f0126de01f5494959b2c186a96ff1ba6e10cc9ea58294274ec3b54ce8e4ca","nonce":"ce22cf03922cdb969cc874c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"2ea41939bbe562a2453a555afa97912b148f21fd22d811675bbd6d889d8ec88c38a34d2bf9ecc7005889255a5b","nonce":"ce22cf03922cdb969cc874c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"ace382fbb64bbf037cbff1de871a4d1468ee687eaaf7de6e5c1eef3b1a1f116b37c9275147c9717bac565df9bf","nonce":"ce22cf03922cdb969cc874c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"cd65ab91581d925229be1a8757944507166393577b5177b63bef8795d99a87fc170b13a92e57bcbb7f25a65512","nonce":"ce22cf03922cdb969cc874cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"e2da9fa207386d26afd3cd71f9d2defb9b5e8a5fd24f86e88a942fac7da421a53f60348422763d38d2a98e7626","nonce":"ce22cf03922cdb969cc874ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"7749fa54df407d808bfb2e6d721a768e9f8df208f65fa02f67aa8b2d54f4b19bdf7dd6dea620eaf3b83fdedc5a","nonce":"ce22cf03922cdb969cc874c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"6b2c43d9493c98cfdecad4c6bcec437967bda731b1c161e7e9b231734e9fb360868f10727e2663478a22d942fb","nonce":"ce22cf03922cdb969cc874c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"b27ec9048a0b8dd656c96aa1f3ec523b061d66fe1be3d919a288a580b314f17b6a781910df29d862604a578b3d","nonce":"ce22cf03922cdb969cc874cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"22d60cbd33e561eae63e00f48952eea4e2f27ae5c6dd450e9299fbf30037169f25704b2d51c648ae267d4a3a0a","nonce":"ce22cf03922cdb969cc874ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"68c3fc5f2ce1620e707dfeaf110bfb8f9daad0f28f0a74b77671eaaf9168062a127cc71481865edc385d3cbcd9","nonce":"ce22cf03922cdb969cc874cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"c3df7fac3bcc0db9baa87d2c82bd0296f62a6abbb8daeff696636ced1ecdc0da37938fd638c625ffb2cedd50a4","nonce":"ce22cf03922cdb969cc874cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"e41ae9a8b772d78c901a25e9d72a08bca838d17441606e10429d87d6cc11d80a273da03029e7afcd1d849bfdaf","nonce":"ce22cf03922cdb969cc874f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"08e055808a8d586cbae47dc565039332223a3b077cbe2aac494b62390cf1780d3b42db8c3393d6205572455c0d","nonce":"ce22cf03922cdb969cc874f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"01af7baf1dc691320b4a71655e9fb27ea9522b852a71f48d41f62c7001e22aff24a7b79ba4c8d0d99254d4d437","nonce":"ce22cf03922cdb969cc874f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"ddf8c167064c58a92870adea63d91cfd16950b9676ff02ba966a18f513ea79b2ed1f1a382921bc55c0ae123d8e","nonce":"ce22cf03922cdb969cc874f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"72a2813ab2ab4e950762cc2e5e0f3942302e8875195be33faeae4afad3b07636cf66c95f8851ddde33633a69e8","nonce":"ce22cf03922cdb969cc874f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"a166a065b544a28fb934a605fef6a86307ed95c9a45f0a44e667ce7e8791b6dffc8d951214933879a3d0516ade","nonce":"ce22cf03922cdb969cc874f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"37f2570e09a6d0bee3b72656cb7ca811964f48350cd88683435c68824aa42d9849834c5102a4d2781ac818c317","nonce":"ce22cf03922cdb969cc874f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"777cffb85f5885e356827158450cdad1b10340a28f649650d2de3fbcb0b2e1ab0f36886a4fbcfb964fae804183","nonce":"ce22cf03922cdb969cc874f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"e542ed89e89a36a238e80eb8e6d3a88807ec49afc007625e2c67563f063cc0860ce5ca6f66130a6bdc80279f2d","nonce":"ce22cf03922cdb969cc874fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"6d4daeae66bd95ba78df7fc72d0ddc9c81e4ebe36065f57c9df76185ca6b07622947dd89a485b2479db82fc0db","nonce":"ce22cf03922cdb969cc874fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"94163e7ce05e8b702292dd0b6e7b52776a7322ada4d2bf51f4c163f743cfb2cab846e309f3d37cc073e84e8c87","nonce":"ce22cf03922cdb969cc874f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"fcb1d25dc912339ff3964df74e68f99734cbe89fd117259c0c82e2caea78157a95699d15ee4004ae0af8b1b913","nonce":"ce22cf03922cdb969cc874f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"77222c4c658d455366cd930db3275193f4615712b45c4c60671e14e745aeb0b7f03def5a976df0dc6cb531b785","nonce":"ce22cf03922cdb969cc874ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"811077abb07238135ed1debb7ff2e6a6b88685b7ad92974ed8d79ed667da711f47774fa87d722635e105c281bf","nonce":"ce22cf03922cdb969cc874fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"c3ce2da62c41ac4a63a6c932386c5fea5f5b7d674ecbdcd0699cf4497c975aaacba61b47ba60dadbb4cfa0d4ba","nonce":"ce22cf03922cdb969cc874fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"0833781ff3703364fe1d14443955300b98b6d9b9b1fab0f322e28ea9cc6a830a864605d52c0e4ae2a00ef10ce1","nonce":"ce22cf03922cdb969cc874fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"f2ff6b7cbc112f2558239bb1fe1a91e92af767bccf552230f02bb67cb57937d7ff9e8503bff3941fdfd757be92","nonce":"ce22cf03922cdb969cc874e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"070a4c59166cddfb6bec1c1cd13e5b89e4a1c098b157d43191cd6b368d464d3a04881191e81a8f42a39a9604d7","nonce":"ce22cf03922cdb969cc874e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"56a71e85a6da61be923eed1274c65bf710a670a30cfec688946528f877dc725a1c1d77d464711ef9524328ca17","nonce":"ce22cf03922cdb969cc874e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"647ede0eecaafc044848153937714d5dd1ca513506145c3fbceda35bf4950619dd21d9a83ff18cda60716b2537","nonce":"ce22cf03922cdb969cc874e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"95d6d4349e5956418f77f476f32700f45e5a3c46ebf36812bb598f626b114117bcaec6ebda4c9db444a936f8a5","nonce":"ce22cf03922cdb969cc874e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"e58c294d82f41f4267c264bef5a7096efa22b696a53133ca7d7d39b9b2596b6c3a35cb2afc79ec11b6bf9347f5","nonce":"ce22cf03922cdb969cc874e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"25eb5c7141dd43a1ec303b84cc219f01e84937cf77a605088655f6edc542f434c8d18302d082c5a8d0a009fe04","nonce":"ce22cf03922cdb969cc874e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"6acbc1f89d4179acc4ee3bb352d231d3d2e76e8d5b5c2f710bc90937a2c5b35d7b8fb9043a6187a0055cfd8562","nonce":"ce22cf03922cdb969cc874e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"a7a24f90649064e21c4e61030b9477fadf9f9b8c99806216368f0d8b96f8d37de6d9d4f32b7675e0e6e4f2af68","nonce":"ce22cf03922cdb969cc874eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"06e26bcf4febbd43ce0645aac0ae35ee7f85096379c08c2cb2a396dd65810fa0c3b66f247c6e76e76dcc36a66b","nonce":"ce22cf03922cdb969cc874ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"059e8c8bb05949ffda6abafb5ef45d0abc3b7cc9686dc669552e40d394093f204c36b76cbea025c4a917296ade","nonce":"ce22cf03922cdb969cc874e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"e822b6c4c1960af83854dc5d1d031c005157082bfe3c2a6fd24787d645efbbc05a99c6fd9adf1e09619f5021a1","nonce":"ce22cf03922cdb969cc874e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"af85cc4a636a0f766127562f246c43c4121b2fb3c4337c178c7e74c38b481e9d20a445528683ecec5015988e25","nonce":"ce22cf03922cdb969cc874ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"ed4930bc7360e538add05cf8b9099a47ba5ae43fdbd64ddf079f045ea1bd3b8b305688e012c4d21481b7b83b0e","nonce":"ce22cf03922cdb969cc874ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"8aa5a8011ac7c0b496f9d1ed88796e56d4e2a59c099b5081a9cc76cc9047dd57f4fbe506cf138414cb853f0eea","nonce":"ce22cf03922cdb969cc874ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"0929b49cb50711e2f958b94b57a3384fb63f13ca0e48712eae6d6a0bdc6bdba933db20647b3f597ae041bf719e","nonce":"ce22cf03922cdb969cc874ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"89ad9b783246323d462bb19aebedc0f6cee4ceb23251017633fb9935f9ce29a8578787ee4dda1d909604c2f9df","nonce":"ce22cf03922cdb969cc87493","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"01cb5cef0c0f3f7d77d0001a4b13f1fa9107b0d9f71a4f1df05bf6de4d2fe34d19426944fef18044d550135fbe","nonce":"ce22cf03922cdb969cc87492","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"6bcffdb913ce1dea9fb6cf0f4924543116e5239c810dcef3a2477fa2966cedc3429d90e41a96b4b4b99ff78381","nonce":"ce22cf03922cdb969cc87491","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"e21437dd59ffa9dcba783a336898f68cd01d8491d09e453b4a0069281b089d6e8ec8b5063c3df6480299e880ff","nonce":"ce22cf03922cdb969cc87490","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"05fd9655199ab41869ba11920dbe8a7fafeae970bf93de9e3329abdf9d1d116316d243cc9c32d9efd509c0d0cd","nonce":"ce22cf03922cdb969cc87497","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"166804c615a4a68a600b05d5405a3ce8099c23a5017b4f543b0cc8735830f566245a5624a2fc64881270b51b14","nonce":"ce22cf03922cdb969cc87496","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"c6e191f1ba37005da9c5f19717b49482a0eaa8fc16f42cadab543edc1089db4364ecccf568d2d8a1bc0101feeb","nonce":"ce22cf03922cdb969cc87495","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"9f861b87ea66b94f57ced107e985450372e5b6a09858afae32aa660937e9e13b1be1331b426748207518be7f99","nonce":"ce22cf03922cdb969cc87494","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"6a996d594988d7f430bee736d1517fec6ac8790f28ed707057886565e3687f52d9d7039c9bfab98a59672d1c87","nonce":"ce22cf03922cdb969cc8749b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"1ebbbb9e2cb604487938a19d0647dc6a197f094092e410929f8a36ee5bcfdffa59fbbb721965fbdda7676ceb90","nonce":"ce22cf03922cdb969cc8749a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"2eaadb38dd7e68df64603c0775a2dafcd752c9da9866ffff131b40c9c4bd31e733142f14422db135e3cf770a07","nonce":"ce22cf03922cdb969cc87499","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"b99d68bdf2141e3b0fd0177b79f8bbd22338fa0b1d3edf8b4b7182adc51d029873ba8d5ef88a9572d0cf211593","nonce":"ce22cf03922cdb969cc87498","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"31905531f271276db3935675dd80ea60ce94b8ff4084fe5cc67ea1f19e82667afb76bec014b04da62757e68baf","nonce":"ce22cf03922cdb969cc8749f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"b8a3951600f159f4f1f951df6da766b7c151fe5a001fbc104a71d64ec4069b061fff59bb97d4ce3148f0ff3dde","nonce":"ce22cf03922cdb969cc8749e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"f563a78caa921bb1368024071276ee8ae4c5f67ef50f57dae4f5c3479c105295a536426859b3cbeb14602372e2","nonce":"ce22cf03922cdb969cc8749d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"55e42dc34e57e1127f52c0f302bbfeea3a21d048e328e74bf64754f8919eabfe1aa9eb507caa14bbe21b84403b","nonce":"ce22cf03922cdb969cc8749c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"3af42671120877aca5b2bc4653bafd6c92924abaa0a23991772870a2211d2c86d2cf8c30501bf64396b2d4c220","nonce":"ce22cf03922cdb969cc87483","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"5d58cf85dee4a8df9d477ad867cbd940ab2a4737460c0df783b31feab2e38b956f02c68b79998412323c04644f","nonce":"ce22cf03922cdb969cc87482","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"0645201fed5128024a949f60b319a08e1b79e68fac18304b18910c20d7cef81e0cc5f9a5387dc2a084297554ea","nonce":"ce22cf03922cdb969cc87481","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"79a30568316cfe7e2a9f49f78df56d0855fc705a2d17de5ac99e580f2b8e6f21ab26a85aaebe7e3d92dd4e8fdc","nonce":"ce22cf03922cdb969cc87480","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"c75de42ec51bc5d1f7961a186fdc6645dd6af5f4a674e849024a597df9aa48a268a35513cf8dca8c672791adc3","nonce":"ce22cf03922cdb969cc87487","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"b15d2375a58add012bbfbb288e64f088a1b68ed293bb363843332de5c9ba6886a3c8d4697fe31aefa57f2cc70f","nonce":"ce22cf03922cdb969cc87486","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"23087b8fae7535c3d4b005bd348aeb42af5091465f15ad2e5cc7504faf60e0b7b4793069f6e4c91b551a0eb7b1","nonce":"ce22cf03922cdb969cc87485","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"6fc1753db14825e937639d23cfc355f84178b029a6b2b64304de4ab5ca2f070ee93585a7017f0f62cb3527e56a","nonce":"ce22cf03922cdb969cc87484","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"acc43d531a15d4ecb900d78b86e112dee953fd1d31457696c8640d91887a6758a602c0471af204a4efbd98cd79","nonce":"ce22cf03922cdb969cc8748b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"a92d570455070086ee6c9391ff5b44614ba707e5874d5b405b1d88a6f1c3c50e55405e155116f735969828271a","nonce":"ce22cf03922cdb969cc8748a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"1491762230808bd2ef6fcb1db667a5d9c81b109ef98eb4bd38325a63fdde291506aab57120cc175f661d2a6cfb","nonce":"ce22cf03922cdb969cc87489","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"532ae90788a446e073b006a15853c4daa246aeeae0b7d6e7d894012e769c2ab935cdd2653a373df42104df2d82","nonce":"ce22cf03922cdb969cc87488","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"82e63e9ae0ec03d0df73144b78f8471bbca70e7ef764820607d092238020d5b30f8c80b35993e36540656b2ed5","nonce":"ce22cf03922cdb969cc8748f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"0a5d89e71a186a1a342486b0c0367200ef92c19343baa6bec88c916f25644d747b365f843e0de585efc5e45f36","nonce":"ce22cf03922cdb969cc8748e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"fbac46c02de9f6fb39960c8fcb6fb6ad1e0e9514b10c624ce7af2669c8976167329f824cca85bf3c26bee23196","nonce":"ce22cf03922cdb969cc8748d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"253aa78e17c5ea9a12845d0ba4944a914529ec8d2178f845b3755317b545bb6eabe809912e1acf064dec056ed9","nonce":"ce22cf03922cdb969cc8748c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"8cd8b768ded9c17c633ed3d10eab0e7b48611aaaa219719c5b855bb7a7e96ec40107f6601a98cedf6207e856e9","nonce":"ce22cf03922cdb969cc874b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"b749ac391b64fb617a439584c570de96a93af5184cf7206228e31f5258e5fa35b2b261877291b715d68cca0b8a","nonce":"ce22cf03922cdb969cc874b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"ccf79ce294f991d7cb487b9c0601b3a75cfb6736a71bae107ce18390cbb6eba96519faf4036f7eab78839fdfe7","nonce":"ce22cf03922cdb969cc874b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"c259d2c46624ac85c1e329cb79b939b9fc93be7f86a8eed1e9ca8bdc958a152f114fecacba620cbd62c6dd3c46","nonce":"ce22cf03922cdb969cc874b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"3dd17775b15ce1d325b7a2e31abd1f48e53cb98aa2d13f2a1fcb8eed8f4bc5a90713ca8fea6933bac356ccfacf","nonce":"ce22cf03922cdb969cc874b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"b0ad33a5d15fa1b646194cbbf48cb5bbba16129e01a050257ac41993ff1255910441d3fa212a979a674a9d06e2","nonce":"ce22cf03922cdb969cc874b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"e45dd3e24ed9f3d62ce193431e9ecd1c365dbd8fffbf665b2aa8d64f77a863b2bfb22f74f76e591497a17da144","nonce":"ce22cf03922cdb969cc874b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"f710a79037fabb4cb684ec59f971d29a2bf2b1324b2c3dd498ed1c1c36332ae08cfb0a10ebfc83a0493fa570fb","nonce":"ce22cf03922cdb969cc874b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"ccea16069feff7c2db188604f5972c6e11808e07a4980941265d3f8e68d16b0acde33c3bc5ebb1cc4f7cfb2bb3","nonce":"ce22cf03922cdb969cc874bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"c40cb2bd841f6a141b13fce0ff1c5a0ccfa02d1236ec1c3ad54e88f7cf7bf9d06eac788387fb4cfc1b7193d2ba","nonce":"ce22cf03922cdb969cc874ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"548a1ab2eb113d069feda7e48e5a752b4ec5fba5630bbe7cefef78e6ef8f733f8db90c281fa977a57987eace4c","nonce":"ce22cf03922cdb969cc874b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"3381286ce0ed4ec53417ac368e63c77f55af89a9e9925ff558f1731ec11d506117cf33dce327e83100c4319ff3","nonce":"ce22cf03922cdb969cc874b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"74039f2de79aa89da835bc19a682c4d9540faf05f4089401349ebe3f2d895358a21c096181be8d97ad11c34f8f","nonce":"ce22cf03922cdb969cc874bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"2f0274e0d43f3529a1748b0e177088e2b14e65f36d6ad8d9d2a996aa6471b371ff7ba470219cfa881edee07c7d","nonce":"ce22cf03922cdb969cc874be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"db815f76a2943aae58cc505101efdad574d93f5058ef9304a1137537dd8d508339b643105128736f85b7b6845d","nonce":"ce22cf03922cdb969cc874bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"5313b63aec9306450412a3da7b3726570a68b9a6e9352f1486ed72a4ba0f04318116099ab2370d47ce868def04","nonce":"ce22cf03922cdb969cc874bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"3e54c3b866e72f831a4483054f209cd782f72a0625909d82758d96a4f96c5bf345822f634e87b4f61091578b15","nonce":"ce22cf03922cdb969cc874a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"e0f009899c2aa71518bc35628a257d0f5b93daec7b6845172c4a7c8aa388174ee5413982eff7438e8ce6499d4c","nonce":"ce22cf03922cdb969cc874a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"9847d654b374252b55daa987b8fc49fbfa20f614b4f72f34fbee23272ffb2629e0c06d7264254916da95ed031c","nonce":"ce22cf03922cdb969cc874a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"2b869cab0d25fba84369d522beb96ea22aeb44b39709347dd612240adc0459a45015413eb40a971741da490870","nonce":"ce22cf03922cdb969cc874a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"b52e46251728977adad5a25aca36b5104a2b5d97381fbbca4ffe52a9511a5cfef87820a40a862cf987bc5af736","nonce":"ce22cf03922cdb969cc874a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"ee3970774679f820232eb02d06b1ea0b87d5d43b947ee0c7cf93e22042fdcca6b49802581a40fd63687a10a8cf","nonce":"ce22cf03922cdb969cc874a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"b9e07bd6dd198fdaac93bef598bf36a4ddfb91ca07c78105fcee84a6d8d460679899ec59415c46e1e5461edd42","nonce":"ce22cf03922cdb969cc874a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"9ffff1c59a69a51b88913017fdd1816a4ba985a40ac1fe3338dc00a2843f3f59f574590759ce7030a312181d95","nonce":"ce22cf03922cdb969cc874a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"9f25acf3e8a1bc7cd769155b22603ee99d8eba074abb627e3ce986fc2ff8cd0761830ea55b3bfde4a7d747b16c","nonce":"ce22cf03922cdb969cc874ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"6a9ec4faf53d0f72d387b96442d35ada222af45211460c8e438766a7d583aec9467f461e8dcde33de44c75bac6","nonce":"ce22cf03922cdb969cc874aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"f198605331d1cba1d3f165f796d2832dc76db4a2d1599b652fa56f6664a8a07a0536f2e326badbd31cb084a1c5","nonce":"ce22cf03922cdb969cc874a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"edf2fa11f3e42a33247588651931da13146ec734a19d23e9ed270a303f3d9b9ed2ef1da94842e5ac3c61e16cde","nonce":"ce22cf03922cdb969cc874a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"49b70291ce75fb929912ee91071bfbac5412962469edfb58ba457b41d88520995a326028f67871d56dec3e46ce","nonce":"ce22cf03922cdb969cc874af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"e977c9eefc89952b8e222d661054e9236ae50398bb66a5b4fd69cb42ed05c042e390eb158244a274ab1f16d9f9","nonce":"ce22cf03922cdb969cc874ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"35a74b3cb6641356d46a7a4d3a2f1d790816dc00e69f2abb1bcd6e298e3931cbf1aa787de4220fef50bff4762f","nonce":"ce22cf03922cdb969cc874ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"f2f446c62e83a403f306c6bfd2efcfc2d72c14204b9f23a486908c12905bb304d916454e3751c5daf53349d940","nonce":"ce22cf03922cdb969cc874ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"16c8cbf3db8d715161f3aff2840f7cbd4a94282ae2c5af11a4fd02686a844c9bc684c7a4b62c72ec24bce96dc6","nonce":"ce22cf03922cdb969cc87553","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"8fae81fd422baf00182f6c252da550158f74f6e9eeb6570a260502a346b9e88c"},{"exporter_context":"00","L":32,"exported_value":"95936a6a607d4d9f6d4a3eff44f302c59498bb1b569347ef606e14c01d269c99"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"f516428272d159479d5ba05e0eb687960ee27acf0f4ebfc59d816d0fe8666fc4"}]},{"mode":1,"kem_id":18,"kdf_id":1,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"b7fcb061d882eaa8db86fb8da13b6bc88d8e4e678c7fd5708791b1fe27c03b4b6b26b11ad81d7507386ae5ab704f9fc437d6dc383872f1b22908827693a5f9ecc851","ikmE":"3d4aabe13ef7925271acc8bd3a3919c829573b5e98cc4c3468e06a6543ce365d5c19543257ab8ee9933997a19e01fe29a3426937151371d00066ac80f252a2c21388","skRm":"016ab73f3ae857adc9f05a7f921f137db2d35d16197d322b1d122a835fc826e668e5e9a3d49e7e3af1854d656a19244068ac1294435c743cfdc9b1b00ce155498953","skEm":"00ac6fea4b1b8694c4cf4a8cfc283a61aa987e531dd5da95bb48e875b09202474a105db916abb8018177f5a8546490bc3a7761cab8deaf0550180fd05e7d0c4052ad","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"0400dd4410c082b0d31b35fceca4a6ad60bf43de6a02bb7c3da75d369722be05718673f475c043f4674d0d6df35a457df08df78086caee5188ca5f80c6909014cd15bf01cbf7157ba4f1d927188170466123fe03fba11b9768065f76ba1c3ca480fe6a2ff23b143f111fa8c2f337304084287e66cc89a94765e211e1ea5a5ceb447f5d6a82","pkEm":"04010318810f42137df0ccea38aeb2fe8de5b39b9ef264173b4c7e95009fbd24771672ed303739b46cdeafb2b977d0baab042f9ca0767b52e69b2c7d9b8a69fc01ee0901f431633bbd0ffd3671eedcb5de8823a79f70f48fef3725f27b900c4d24000cb50429bc3cda949bd07b4aef57d6753e96a04d3efbd53cf50bd41918eb5d142c6651","enc":"04010318810f42137df0ccea38aeb2fe8de5b39b9ef264173b4c7e95009fbd24771672ed303739b46cdeafb2b977d0baab042f9ca0767b52e69b2c7d9b8a69fc01ee0901f431633bbd0ffd3671eedcb5de8823a79f70f48fef3725f27b900c4d24000cb50429bc3cda949bd07b4aef57d6753e96a04d3efbd53cf50bd41918eb5d142c6651","shared_secret":"c00536fd8db463c31cb4ebd21bce53c2910a2470c8278ff6479b21ac880df462704440e7d82fff1add3ed7f35a29aa3070e978df2b2ccfe798c91ca9f391bc37","key_schedule_context":"01ab31ed2d887339bfd8a7ad54e4ec3f3b351c17624d343eba1aaa55a6db40dee976dd33e8a4bcafe1a77744efec0a9d2a78d2877aac000f33f7257304a97c1d01","secret":"be8a73512491a066c9d0933fd963afb0bf932d0316268b91f3a50df468754dad","key":"","base_nonce":"","exporter_secret":"07c996bd5bb7be7bebace675b67708ec693c555b3bb8f2aa765983c944403235","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"215cc384bfbe64a0187b3928c4cf7e7104dd380fd40de0814de22982a94fdfaa"},{"exporter_context":"00","L":32,"exported_value":"204998e433c176cfd2ff45faaf40a4677132c36627a0e6f97c59a466580b88fd"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"827af038dee6b40b6b71aebc83aaac9bef8281a1cf746eb06eece909415c01ab"}]},{"mode":2,"kem_id":18,"kdf_id":1,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"612a6aa17bb4f533578dbe614f764b384b7087cc29f56da6ffa155e463ba50bf0173215116f19476dcfe00e61c4e0951afc0f5aa36b9d73bc091324c36a9c98df00a","ikmS":"cf72f87c43f846cf0afda2bab243caa26954c444812aee4ab48dde9d67b6dcf6b867f4dbf7365819a3986c49e87bec2f75ff74d6b0c5ec30a1040ed305b73f44549a","ikmE":"dd0414e1adaa6da0b4650cf719cb665886c600984b214e98425983accd6712f4f94cbfe5924023fb6d2ab94664f9bc4ea900626e25880715766d36d4980ef04a7265","skRm":"0063222a8dd1470d022be647729c0b4417eebdf8e2a498ba7c1131dc7296465d4461bd0715da3c25a162eab21e2a0abd142ef99918a53f8dfb466c45e72eac1bac0a","skSm":"01635557c41a89f1298b1f9212a716f99985f0f5fcb2eaed51f5b7868238a11674a80c4dfa48465dcded44668a01f0f7bedba8023858790a9ae72f28559d5bae0100","skEm":"01d687859152e10cff3657e1026cdaebe76a27e56b62e8b91478f90d48275d960535b4668093adb78feb78628634b8eb9d09aba3f2c9b16ba52b93afd06e8ddf25f1","pkRm":"040008c8215452d4248149d6a126d8f3d42bd743b611132d61b63ccb018cb212e79f750405c2878e1148ecb375a1080d35ab795285659e0d683ddfa4ad107799fd402201249106d26828935a22b3b4f3bdf3f94ef2c1143d8237210a860274b31b5692fd5cd6a85e89cf216f288455c25fb88b86b4311134e2935193b1f7638d3316e35a4b","pkSm":"04004af9d30c236e62acbfb1bff49d06eb84d15db1f59f27b5abf1d162ad5f7a3144a0a21a5a7721d50d486699f609500d50933e41abd74ac1e7c6bef124343a969f7200b916ab6fa1ea6cceb1a6ee3f97942515b4853414e07186ad075d8624bd6836c54cbb44f4ebe6df0f060e5a0666e4f206e5b1835088092940a70176a281e36e4269","pkEm":"0400978e2a4c39ff6e54b482a5ae13517e4c53c19689367ec4a77f6327da70c7b12690f97f5305c7ba1e1ffdf030b3607b21669e23c669e9f68ced2016f6ab6226f5f8011839924dc25d9797e54b2a09323653c6e221e51ce33bf053988c19e48a638ae11428d3e6aef76ea14c262bcc005db2f5ade558eb5e219d0312fffff0724695024e","enc":"0400978e2a4c39ff6e54b482a5ae13517e4c53c19689367ec4a77f6327da70c7b12690f97f5305c7ba1e1ffdf030b3607b21669e23c669e9f68ced2016f6ab6226f5f8011839924dc25d9797e54b2a09323653c6e221e51ce33bf053988c19e48a638ae11428d3e6aef76ea14c262bcc005db2f5ade558eb5e219d0312fffff0724695024e","shared_secret":"d8c39be6a2faa16619809157d6cbc6bd4b78c157dc91c1bdbfc3af36021efd612117365e623d5872e7328ef90e2eee556320125367b0c033a684d13804df7d8a","key_schedule_context":"021d414f42bba6f51581cb25399a4c5cbf299dbd3396ef8b60783a888d8ad71c6676dd33e8a4bcafe1a77744efec0a9d2a78d2877aac000f33f7257304a97c1d01","secret":"8b1bcecd1343b194e49e1a8c8e5c03d1c0d61bf8a64180bb13dbd463c35f3acb","key":"","base_nonce":"","exporter_secret":"e19e8b6696e3532983dbbd6de3bf9b16bb64258414da6b729d971e5ade03546a","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"0fdb874bc7fe76cda621d91e7d43546acdf454d7ce5dac4a5671da87f122c3dd"},{"exporter_context":"00","L":32,"exported_value":"f6b49f9e4358ea4bbe00d086b5025106b517f5dfa259e2118de3338d7568f450"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"8f3017ee2a960c8a971a0b44c2adf28bf242b3ad7b2f34cc9585e54099d00d39"}]},{"mode":3,"kem_id":18,"kdf_id":1,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"70efcc55d47d1bbc67379785c9274358e78046b9bfcefc3f0acb2067a27e71286aabe59c73199427c09f5f4f8e358345af8c961aa9730ba30f06ac852bc3d0600fbf","ikmS":"40de10f7e9fffbd8dd7edc370e870028cf67f0881fed871188b8d9db802152ac21e5ca282601440035b716fc0b885aa5e9c1cd286650aefc426c78083d9c3705b374","ikmE":"61411879e5eed9946ead031f349ca3d8b4711e7459e808538b64c259832503a42de112c74a0148a07a822324ebd1b65c5579868bb51918d91d891d32dfec1fff1c9d","skRm":"016d773120432f612b22a02024d626c00fe53529c1903e153fa589663d953755999c25a0387f52465d8e02247b0ab00a515d91336834909a80bc8be3cd2a49328308","skSm":"00d7b0be5a5cbbd0a8e25d491e09d5826a6e0841901569c1e8a57fc08aad7b36258cd4a0cc37a9a8f9d5d9c970c38bbc01a558f36a59f67078940db583d04f25f077","skEm":"0062972bad11d07b1e5da95102403afce6e4fc23d915aacca392e670cdfdaef275cc7e75a5b385e626fadfe6e4a047a084ddb769ec4dea1d2e76ae1a4ad59706cdf4","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"0400e83f92bd6bfbb6be44b03dcea857f9eae0bfd5bedb98c1ca95825f6b89e8bbe42a3674d4cf500d504eb49bb74c5b911b23e964339b8b3fcad3e22089c5e52c64620081ce0d464fb14134bd98a55db644add21d1f1ae61c4a956da5953da2ca116c3bbb1a9c4643146ca1eeebc3b35591ade63f65964ec71645d3492f26d8efee409193","pkSm":"0401b27d3c1323159d82c6c2acfd685c576f74c0b83a09a8b46252ff4956760d5a1876512e5358cb694fbcd76569b6df69957c10910dca44c70a41bc2e1c646c3e3008009fa2612fea4310b28aaaff84d007ca3798639077b2ca6a4c555323ae063330b20901fb8968b037e082cc2dd19d51e5fdfed22f125cf1164ff0e468d26f69d68431","pkEm":"0401e3b825a1495a29917cc5fc81b9b7d407b9393de1ce8f2a07493e0043554c36dd842f6bd05c1fd5a27034ec33af118f5a65df51fedc83b606825f952a0d3ea728c701ec7578f14a0013183ed2e554e31ac95bb39961217b65327490857618e0bce317855ee538e02e73f4cd364f4966886b1a5e30fa40d2de4ce48b8b98a8cb819e175c","enc":"0401e3b825a1495a29917cc5fc81b9b7d407b9393de1ce8f2a07493e0043554c36dd842f6bd05c1fd5a27034ec33af118f5a65df51fedc83b606825f952a0d3ea728c701ec7578f14a0013183ed2e554e31ac95bb39961217b65327490857618e0bce317855ee538e02e73f4cd364f4966886b1a5e30fa40d2de4ce48b8b98a8cb819e175c","shared_secret":"c433b108bb280fa806cf0ad945140dc90d3c6200ccc750800e56a991c243f8bb8c7736c680cbf79343ff92e8840c1dcb03fe9693fb57175d7a8fc99a405d5c18","key_schedule_context":"03ab31ed2d887339bfd8a7ad54e4ec3f3b351c17624d343eba1aaa55a6db40dee976dd33e8a4bcafe1a77744efec0a9d2a78d2877aac000f33f7257304a97c1d01","secret":"2166960b708a5a654633c4d58905c9971b73278726d7467f8961bbda6b7990ec","key":"","base_nonce":"","exporter_secret":"ce194aeb4706294c622ca2e867eaf685b61a95bd88ff72c7df4cdb4bdeafa763","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"21b4f5d13148ba72b80fcdab6580304fa8661c61476427b2edcd5c477aff0e07"},{"exporter_context":"00","L":32,"exported_value":"c803583d758bd98ba5b14f14f30624184771ed8404ccd764d03f8bc1a9cc8a80"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"5726575f527f4d2e633d3174b2628a2902d7cf0fe5c55e75c3d28227b314e3e5"}]},{"mode":0,"kem_id":18,"kdf_id":1,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"0fc4d830d8d47a07b373dc5f746ef33bc5ca883b894180aa534b6d5015e04773703c61651c80cd4d30d23b26c749c6c201d5ad9495f5ace6cf16a0ece86dfff9c0c8","ikmE":"d6d28c7fd0770c54fb71206a19a31c89370a7e7fd0a72e294b4518b53d6f555184af95acfab9360d862bcae1cccb2be7193fbbb82a9b36f7f7422e6a62cc3dbdd26e","skRm":"00cbb9807613ee8443069dab5a9ee3bdcae35b55cb3b4b76faa8ea15b23e23cf5ebe17876d8deefb8e548079922c7ac730f8f91dba0384467ace06f015a3e2d72389","skEm":"00053c983375fbe246c3ec51116aebbfc1b9076d4d2f3f4e5415383c3d3a985a7ecd55e606d7e65fde83ef80893e659f1c2cb95369929b293d2a0edf45c955454962","pkRm":"0400156f9a633aba18251f614323322ddb9a52f5986e0316b0477d089f6767fd5b80e9a3ed3ba14efbbece71f73e03e70a25e0e3ffa38ea0b626644e605d1edff3d9f300fdd3727e7b9242ffb2292131d35091e9a7a2c23117f2d660822ee961d580ab84da56559edf02068f18cac72e838a96fd0ae29bb769899b36e6b739a2f20d7242d3","pkEm":"0400d6d2277eb1106cd9b00eaee3fceead74a8861afff442f6a1bdd071d0868b5ee373960dbec83cbae16ac3340a813322d8b64825af613b2bfad52568c568d2cbe927002647c5350f16151876776aa8a9b7018614b61a9a8362bd522ddc59d17d65f0578745afbcb9bcc207ef119ddc98de846eab783f353075961ed6522ad229ced21ba4","enc":"0400d6d2277eb1106cd9b00eaee3fceead74a8861afff442f6a1bdd071d0868b5ee373960dbec83cbae16ac3340a813322d8b64825af613b2bfad52568c568d2cbe927002647c5350f16151876776aa8a9b7018614b61a9a8362bd522ddc59d17d65f0578745afbcb9bcc207ef119ddc98de846eab783f353075961ed6522ad229ced21ba4","shared_secret":"62dde24ec1cc7c049b5e8c98b477ea97f82c17bbf7011136be577413f3c290c8b9690c15e260384a8f3499db8acb7d5744fa7bc12b3e89907e096cf945d310b4","key_schedule_context":"001d414f42bba6f51581cb25399a4c5cbf299dbd3396ef8b60783a888d8ad71c6676dd33e8a4bcafe1a77744efec0a9d2a78d2877aac000f33f7257304a97c1d01","secret":"5ed07f65065b76c8ff73d4aaa28d9cc453c3326602e60825ab7ea55308f77829","key":"","base_nonce":"","exporter_secret":"a83bf7e292937982e76393fc9d9af62ded33d0b66e56a02ba59ca89c560538ea","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"ac13187c48985d10f143954d5939deed6d6e55c7bcd5e0b04b3778d2f586e795"},{"exporter_context":"00","L":32,"exported_value":"4a8b93fd8397df0c996a59d3980d264816643be1e6dc657c689a7671ddb622f7"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"0dd069723d537a2400f5113734d28a4a733640db845ebfeca43ea7cf9c7f5fc0"}]},{"mode":2,"kem_id":18,"kdf_id":3,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"af2aa8c7417c4296478e2921cba20b666ba36ab14c044af2b7bd5cfeeb27ae8c58c0b5127da3c6d1c2ca2f5bbdd3639dada5ae311428867fb4cffb8776c5ae5809c1","ikmS":"be99689c52b5f6efa2f6a0eb26e06a051836129249989559c794abdb47be1b866e07b64154410dcd268a6772098adc69eef783315c197ac1d4a02166d72fcf0b05cd","ikmE":"35a63c39820ed6760e09d565e2ad00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","skRm":"00f8684541cefabe5558790bfc741ce3b43bd777e88332d4bf92ee50e267c2b19319864266b056cd8beb01cdfd63b12284f5ebc035fc1c13bb47d9fb7b641b10a3d1","skSm":"001b2dc5cf393476b245eaf1f796b802dd9960c3bb4137caee8af3790801c4c1e7abbd557705b833993c2abc45ba71158c0bafd06f323c47116f7bd2ec400aa6484d","skEm":"00f9be2359475bfba5b63511c5775bbf22e4af70b00e1f747e6415e2da9bfb7a785c5c30c527293095fd4e344733184b199ffa7a0511c2b849202fd7bd046b3c3c60","pkRm":"0400b04fba4208332fe8cd1586816a434608363ec7a2dbf0385b025ff4600b4f372c2eed2c5ff361900353819384bffc51d921260a270b21b37d0446dd598a21ec59f400712a4bf873b55fe132b1a08efcf93cc81f0814db3c2b4906f9d270ba1341c958f8424b928a17d70a6e0fe426cc3c61c09e557c96ee207828588632c24157a2056f","pkSm":"0400d690447c9a6fa03eec16aaad1e26cdeba02322e5c6b24306a68412ae05eeb46b7d9dff6af741fe1006549d56285b028e791193141b7af231b4efde34a549c5c17d01c1f60714f0d7418923251fe9f9d7f1f37fa60bb2a69e0bf3916029f876787a9187b9ff2522ec92dc9a600cba3df6edae5139717f0d9a8eb22a1bdc67248275959d","pkEm":"0401ffa86a94e5e6f6ed21fe507935f400b80cfbbc060b7b9ce9f8f6b1204f7edf33f01c793bfe73054d7674d7f923d9075e1204bc1c891b3851286238d0037fb10cca01993dc5017b5a854ab8784ab58e53e2fde6b97f30298dee5ad1113089e6ac4a9ee2ddb747088a3cba4c26bb7ed1e93c080549b0eec73f30cb7f693bd2e9b1da6964","enc":"0401ffa86a94e5e6f6ed21fe507935f400b80cfbbc060b7b9ce9f8f6b1204f7edf33f01c793bfe73054d7674d7f923d9075e1204bc1c891b3851286238d0037fb10cca01993dc5017b5a854ab8784ab58e53e2fde6b97f30298dee5ad1113089e6ac4a9ee2ddb747088a3cba4c26bb7ed1e93c080549b0eec73f30cb7f693bd2e9b1da6964","shared_secret":"22d00b4a85bdc63872de3eae4a12d275b5125f8bc28b8e535c17c8c60d6d4d08b327a8d4c38d0fcc8386113adddf3070d4f8a6d3075d3f1b34666a058ffeaa7b","key_schedule_context":"02cb1fc46c5aa4127c3739c63e1b145be49aa816a560fadbe8512f79ca62004b8b45ca75ad4274b4c03e9dbab8ac3a0324a800d89777115638ce77c92eee21a767cdd87b0281e692a99982979c39757078bd10f16f51a609804bec7ea73e6df85d53e5b21081fb76ca400113c07723eeb59281dc77544497e8f8a683106eca75ea","secret":"2225dae311f45013932d7a082be78492652980a064fa2365a6f8a186913613477eac79d25ab5022a21435209a450b6e21276ede50644c26aca6961996d1143c7","key":"ae74ce00917a2fd3324ad3e91f66ae9c","base_nonce":"1528227cb7b58338c824a329","exporter_secret":"aa6dc38b7cae6a10c65ab1b06d9f35f9555929011aa401d970d680dbd49ac63d0c5d11756095c725e83802ae3e9c927e84d439cf38500b49088538a08dcc4cd5","encryptions":[{"aad":"436f756e742d30","ciphertext":"2fa2de3cedb43c7c94a62ee3241eb677999dc81a7afeebe6b4e7694047e749f28b1dddcd21bf16ad8d5accbb79","nonce":"1528227cb7b58338c824a329","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"2cd894af4f8e8e129d88b08ff5bf307b0c277d00a750825456058567c922397e5a7d05dfc16019b4187a104855","nonce":"1528227cb7b58338c824a328","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"8ab8182afa0afd9bbde7e94fad57463a51fb41684d147093343ad6de5177e40f12ac44b4cd58a7d95500698950","nonce":"1528227cb7b58338c824a32b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"875ded69d083d7419a95cacd911075545e889a4f1dcfbbf9a38037279daf2da1613d053586b62ad3daf03fb271","nonce":"1528227cb7b58338c824a32a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"f35732f3806e0f82a0882912253dba4e2834ae1f92e211096cd71561e27a50c54b079b8518552503bf2b8ae406","nonce":"1528227cb7b58338c824a32d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"d486d7d1915e563bb92404e3fa354272f6d9f716602d26781013eb42e323423b2aee069c618fdc1fe1fb27236b","nonce":"1528227cb7b58338c824a32c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"6347fefd464ded6370b7cd887ec85f3f5b170a6df1cb1d69a47d658e1fe00d3351e773d895416132ca658edae5","nonce":"1528227cb7b58338c824a32f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"825bb43e0dc54c72bdfbd24fe5767c05ef7bbc7fbc161be144861212004d0132368288249bca72d4c3aa690649","nonce":"1528227cb7b58338c824a32e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"144a5329f3d2b7351c1a1ecd46066e97c5256d3a4f3ce49bb94f897f1a3d645e059316cb8595e2a96cc323c6f2","nonce":"1528227cb7b58338c824a321","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"eaed5acc9300beb10a26fa34a7af9a16ba6465f94f69934e78849d06be1078a2ccc6ce00b7eb4fc9159a815a6d","nonce":"1528227cb7b58338c824a320","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"bc4c2e28f09eac3020688a7a7773eda163ca9f544cb5aa0dc506a00c878e111920e14f89bb4958ed7fc38d7ba6","nonce":"1528227cb7b58338c824a323","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"1e04c154e8fee78ecf87b3d897b1f65e3711be8dc330e6ba863b15c5c397ac067f92cb69c64e9087e9c2195ad6","nonce":"1528227cb7b58338c824a322","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"71117392fbfe872e736438e663f9a94d0937196a000d3648ca02652a240984dda09c4289e2d17eaf3691815952","nonce":"1528227cb7b58338c824a325","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"f64b03f19a60ad19d126bc587d73dd93c6b6aced1875d7f560ae772794cb41badc5217bdf2ff8d3a355207a280","nonce":"1528227cb7b58338c824a324","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"2d8645e3c7024936688a51898d2a2866fb2f2cb90897f53083edb73c6d97907a3977000e31155e983d2092be62","nonce":"1528227cb7b58338c824a327","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"41ec86b4e45f8fe413492a96785c7a0161e7ba0bc43c03573033e44cda1b1aab73e2f38ecc6fd2c0f498ca41cf","nonce":"1528227cb7b58338c824a326","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"0e7566885db8c7e973ffd95b2470a0a158aa360e1b3ade6f16473f93eb403c940a8c59c8bc503d92683c232d51","nonce":"1528227cb7b58338c824a339","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"3f0b04ebca8e4cd877a31eae5766ba75694818dad6b9e2fb4af50286ebd80301cb34aa18f9b0d2e4597f576258","nonce":"1528227cb7b58338c824a338","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"fb176b7be7a27580a87c3540603e9bfb15db62d9ec648f2ed5cc1c4c6ec2dcda03c6a1ef1b6523524f30c99300","nonce":"1528227cb7b58338c824a33b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"56ec2f0141f82e2ff13d6c955b5d4811eab4b36d4fbf80c2074613cc252ba18a66aa61665e17970a140cb629ef","nonce":"1528227cb7b58338c824a33a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"7ced8c48c3c036c7f8340799b421add594706857e6dbc37937c88399301f31227f4d4419724ee06b1caa531859","nonce":"1528227cb7b58338c824a33d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"665f77942c5ed99e58ba7ab4c28dbe1d77f59428ecb7461bda18a1f27e04b09f42a7ef370b4815b9417837721d","nonce":"1528227cb7b58338c824a33c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"9c5f7488263019e49ccb9519e384e57e57b0735646e9b8e3bc9fd8f249161b55d619ae686609387468c71bac13","nonce":"1528227cb7b58338c824a33f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"a0434a8cb227b6865d1ea9531c94b0369ef7bf81268e7a1c9f16b608750bcb47b38de5183b6a865a98fa3acc9a","nonce":"1528227cb7b58338c824a33e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"9119e398e99f3657de5fc070ba9c7bb06c5d4b8e800ae83d2d09cced7cd6d56f4067188f1429351f937312d991","nonce":"1528227cb7b58338c824a331","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"b078a12561cc3f77bb60e83993ac7298000d37ffdd05293b6426da0336eedae94e2bc236c926cce49bfad39cbc","nonce":"1528227cb7b58338c824a330","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"74bcce0e33e33327a228e6b3bdf5215b1cb735af28f071af54d2b82e267f31367b4c66658a7a882354657c1527","nonce":"1528227cb7b58338c824a333","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"aac86b83eac6f2f5626507d38188aaa4bde81979956a4370dac4ba4a6fc1f93cc63b3f2d4433d9995ff78bff57","nonce":"1528227cb7b58338c824a332","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"9a0620689b2d06e04a80de1c40d2e3701cc0d631224a96184f61f38667bd744b81fd6215e279f044b6c17f7d8c","nonce":"1528227cb7b58338c824a335","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"0c2732cfd5aaa988e43dd3c443126c854afe60abb331c65ab6169dae1d1b58fe2bb69975229d6724ba8a7aae79","nonce":"1528227cb7b58338c824a334","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"003870cee0d9fc2f4294b6f17b7d7132f5f3d8c66e31267ce9e8075974d40be745639b0e23de5571bdf92a59d4","nonce":"1528227cb7b58338c824a337","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"82f75199f8afe3cd5d563b3e15a340a511514b5e9c5b4d8d091f5b7296b5556630dc25db86f659de16111cc639","nonce":"1528227cb7b58338c824a336","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"18120924c76a3ceff3f5e4a343f22e7f96f32f32ac9ec1618198b65d384fde6f1cddda07072d24ffc4ed545a8f","nonce":"1528227cb7b58338c824a309","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"df286677ffe3e5fc9a72c42b4ebad5031c712edcd6cf06441d4f2fd87d4ca7591af8aa90989e6a951245d510fd","nonce":"1528227cb7b58338c824a308","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"a59a37a442e3c365e9c55202ed323049205185dfc35da9df594f856ef95b3e3b3e8011e2d58c415eb18393abfe","nonce":"1528227cb7b58338c824a30b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"9aa7ad014e388e8ec24d60db026be00cec2dccc6b1236e61230d96c9a8980e5afea5880e007a135d644477cb98","nonce":"1528227cb7b58338c824a30a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"712187df3a55c6c8445de3749504813361f69e94a900f32f503951a68e23b1aca7169b3a9fb03199b1fec30831","nonce":"1528227cb7b58338c824a30d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"8172381d9e2965a48bb0729fbde9f9aca23bce0293aab94d88699b1ffbb8f11cedd9301ca5da10583bc3a79d04","nonce":"1528227cb7b58338c824a30c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"43bfb91342038f89b138e321cccedb0b524aa7943153d8bc27d69104b7eac6c81a0a05dc841e40669fbb2fe281","nonce":"1528227cb7b58338c824a30f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"202500bfd1a235f0e0883ef79ffcead76b81c3d8395bf41b8b096b4961b6d774f05513cc860043dc895c87345e","nonce":"1528227cb7b58338c824a30e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"899a6f9dea3ab1139cb9ff3cc957f6b0ce54aac8d48a94110a62f052d7b78ec4d7d51b80a1c81da604d279a930","nonce":"1528227cb7b58338c824a301","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"ba4be6a444b033002a9011861cd359f758cd29fa0f6ae2291a272eb9acc64429736b4eeaf5d139fb664d8591eb","nonce":"1528227cb7b58338c824a300","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"d4beda9a6687bff69956ce1cf291712cec7db62c7aa61fc8d69ee90c0d44122f894fe04f3bfd102f7da12450d8","nonce":"1528227cb7b58338c824a303","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"d3e695f9458f8462a065e680b1057e7ea182359ac59f78b7a1c252724e736dc35ef81b0dcbcdb95583ea65f6db","nonce":"1528227cb7b58338c824a302","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"d52d116a536cae68d57961e6555c1afb5021809ecf1df5cb856bc4e05367b287e0ed7bd4250458a3de6badacfb","nonce":"1528227cb7b58338c824a305","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"70b533f7e84a32cf8718863da859cde2ebef48bf4ae188eb8d3705200013960b4a576f14b339364ff789bb63ae","nonce":"1528227cb7b58338c824a304","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"d4176fb97960d3f9774e994159cfba423b0b2be4e4fdce5f5a7bfb1af4d64a7911d49e1fb835a3b9dcfa32a54f","nonce":"1528227cb7b58338c824a307","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"240692be43ca5189afe74d04eabf3a6979540c802c9c749f430c6747d2fa3eef0904250c7907018080771fcc48","nonce":"1528227cb7b58338c824a306","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"042698e4d7c8399e167b2c94df607c9a906b29c0cc0416405940b56aba440300e00df0780356e3c86d47ce5416","nonce":"1528227cb7b58338c824a319","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"1b1ba7d709d6a35ae54cb8c3fd30c51fedb49dfc99b74f85afe0889369002ee9cb8036c0a596f7d6643288a53f","nonce":"1528227cb7b58338c824a318","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"8aaa7644e2728e67a003bd9f6cb39cdf68483fe8b2b049772c415eddb2a32b7168c5c2c84e7d58240b3b585b0a","nonce":"1528227cb7b58338c824a31b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"777fb4c63358e47e8a3a6226da1c4e6d110afc6d83593a9b8bb1416df6ba2e94248798aa69febd35a637a8afaa","nonce":"1528227cb7b58338c824a31a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"d5a7f77ca13db18748c5b259da5682c62a4b14b8c9302c972408c5b4c0c118e9ce51473f49c0a49a599d11deb1","nonce":"1528227cb7b58338c824a31d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"58d3d578857a1c4016da3a8b28d11065ec42d4e4324fefd16f0eaccfe71d0af73cc252c171bb10e832624f7fba","nonce":"1528227cb7b58338c824a31c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"99a57efef9d87c5c8d3d70dcc3de77ba7642fc6cdab92ee0c86e8d053c47f947b07f276cd8089c966506aa4c4c","nonce":"1528227cb7b58338c824a31f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"b7805aacf2bf5917ac1198e729a06d8fd5bd23f508f25bebbbc45442b05f21338e71ca2c9ecbebd0302b9404ac","nonce":"1528227cb7b58338c824a31e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"ad019dd43385241fa11d3c2b863a0cd521d8e7c73a91f118dd6d4fbadb059a7443ef0042e57394f175d9813c4d","nonce":"1528227cb7b58338c824a311","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"5a6bc40e8a23ccc30a20e52769e7db732d5a1cde0369e4b6334f64e6c51c31776f8d944be0e3e1b1d26686dd3a","nonce":"1528227cb7b58338c824a310","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"75b7305c0df964cd585fcbacf1b6d044c366dd16f55070b0bab9eac0c9f1084d5a99d2f64924c9e930f9619d56","nonce":"1528227cb7b58338c824a313","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"de98f39b659d8b898477ea06fea23988e854eddfed2412b178b1fb16897c0e372eac92239b30911a6019700643","nonce":"1528227cb7b58338c824a312","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"83f7ee14058c7035a9f1cd5b31f88e59ad7897df1ee43f3dbed0a8622d9cc825d9c9d25639f963e8880dfd2ef3","nonce":"1528227cb7b58338c824a315","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"d35572295336e1fd58a013e7840389da775e1b6e900844c91a5d02aaea3895affce2d2873486f38b77c9421e59","nonce":"1528227cb7b58338c824a314","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"2d21a73effdf5861c62bd6654e92d4c24221ed24fcd66e11327ea2864104586a90c9a93a041fd6d2df460414e8","nonce":"1528227cb7b58338c824a317","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"529e73c46bcda13872e6634646c7617d94294cdf05c8d6a34657aa803678881ea719f7ba52d82b18aad04939c9","nonce":"1528227cb7b58338c824a316","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"b93530aa975acad1a0e7af98ef7b873a30d120c39b8fc1d18f7b3b232f65a58a0785fcd48f131263bc6125ba64","nonce":"1528227cb7b58338c824a369","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"f352212ca82f8d98e544409e82f0bff12bb012066e292194c88a1b2e6d897c30e08195c6d4daeb4773a2a70580","nonce":"1528227cb7b58338c824a368","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"a39975dd2b9cd0a595c9c380f94e85ba831db742c1b16e378a1e9c97bfdfb3c7b8f4dfe1cba6833de0d9f3a3ce","nonce":"1528227cb7b58338c824a36b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"bb92a41d97d58dcc334c3f4a7a025347f1b32b3004158fc598553ee718914372d77a9a789f7a4eeccd297ebd54","nonce":"1528227cb7b58338c824a36a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"5bf7a23496e14017b8572d94967c15b3fe4fd07bcd848fb89e9e44e024efd37fe78f517877e8016a87728ada09","nonce":"1528227cb7b58338c824a36d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"4f2e06f98b9ab3696514d1c657e721f7cabfb7f6e6b9908545369f6171955e28516437afb27b5aaa6da209af1d","nonce":"1528227cb7b58338c824a36c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"d22ff511a9d19696bf2864160b89ad0b56c0f6a5228785a4f097428043916aa360b292752a10bfae5722b17988","nonce":"1528227cb7b58338c824a36f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"96bb1993b788b32acb962929034743ba70c9db715f66a91d1ea0f2d85eeab6dd75854186429b083934a26bc080","nonce":"1528227cb7b58338c824a36e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"a439aae65d338018e88f8d59b9c4378f073cf7db303e665149c3c81bfa945aa81b8692dbea52bb13ea4213c0f4","nonce":"1528227cb7b58338c824a361","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"07f23317006a1b548612b6db58413cc07cec0482f3ec08e42cac289d6fc6fd07fe0e1bbdbccd76e5d33e9bc37c","nonce":"1528227cb7b58338c824a360","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"a9aa305b8304865f9fa1783e350b5e798b178e24e5a2329ef67bae927102e84a4f279090c55607da28b52983de","nonce":"1528227cb7b58338c824a363","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"ec794601bdb61ea933c4b124cf649053d2400c498c3610620ee6ab388711c375ed8d2f959dd4630f6575599528","nonce":"1528227cb7b58338c824a362","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"8d7cf5f1feaea994e13602a3bca4b9f49dab300a6f202e7f99dffff57665b6b2ffd9ad4bef7a409b5d97dce887","nonce":"1528227cb7b58338c824a365","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"235339d2d1f4c22a23c643e1ed71d52e3a606509c93348761f32394f871914ee0fe3e1ac5b3502e964fec0ec61","nonce":"1528227cb7b58338c824a364","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"dfab19e8fa2926ae4256f343cd8540e05c07f4cb32b3fc0a9b069296e7ff27c964fea3feda48f289ab7c47408c","nonce":"1528227cb7b58338c824a367","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"1d7a61dba1f1d6c79abc540abe4973e44448426d1b5c37252dd910d69322f74567ea1c8159187dd9d47d8fdda6","nonce":"1528227cb7b58338c824a366","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"3d32548ace40307d8ad719e71013f850fe0b3ccc1d67497cad7cb2ecbb205a45b847976cd63242c7fcc2199beb","nonce":"1528227cb7b58338c824a379","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"026cf0931a5f75225ab35984ac0f91a85b51f7dc485bd9635b1fbc4cc70fbdfa00e7e27163f5da70c8142fc46a","nonce":"1528227cb7b58338c824a378","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"3861707c1d11acbf33f66355f01dc46288edb397bfd0f5e7f6dd8d40ef7fcde4c62a5048fc82c2389a32401f50","nonce":"1528227cb7b58338c824a37b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"1b0391ea476b870596c4e460b8dc1e82fcfc0d5cdcfb0071dde9cc171c87123a9bb5ccd0c72dd6a5c9c1a991c7","nonce":"1528227cb7b58338c824a37a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"b8045847b1dfd119498dfbeae68adc4de6775fe1a313934b38d1e4f369beba53b17cdb0e8455bedc1813a42579","nonce":"1528227cb7b58338c824a37d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"e6bb7ae28f29c4b4d3d7d2410e163c21b9383d26395efa693c45cccff74d874c3e37134e67aa914390fec9fd7f","nonce":"1528227cb7b58338c824a37c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"185a9ce4f0cc6599a8230f8894b45718b591f59f832498a3e2c1305d8c6fbd5ee1c5727ee6415daba6f976fb25","nonce":"1528227cb7b58338c824a37f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"2e6630d2ccb58e73e48ff4ae1a62d0866fb3b96bb790d55ccb9d50a3c162cdd5b5179528244cf612343da7e924","nonce":"1528227cb7b58338c824a37e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"d6b9d03bcee50fb88ce5577a40eb777c4fed72a979dabfe936be7c017fc250868e9c61a5d349be29e813896d24","nonce":"1528227cb7b58338c824a371","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"271f12178cecc0bc91cfad5ceb5b6e079484acceba429645696ad4a7c328076fe49723fa93cd726432e1818fe9","nonce":"1528227cb7b58338c824a370","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"f89c75edac72b9c20b21a7c027541c28fa93a5d735fd6d091ce9a689817c15d239b4108a1a4b0580f0646ab829","nonce":"1528227cb7b58338c824a373","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"f6bb57b658a28208301ed0c525d32c0fc91f478162059f4af6853ce0e9cf9ff006c7ffdd5621506dbce4bb94e1","nonce":"1528227cb7b58338c824a372","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"937f9f38a561391bd3d1a941a663b3bea45fcbc73cbb5d5221f5e94ac1db01977ca3d1b0ef36ed0aeefb4ed324","nonce":"1528227cb7b58338c824a375","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"679fc1edd1718bf01e6caabaa269692ac23b64a836e7654507ff9eae71c965966835e4e34dbe6e8ea83218982c","nonce":"1528227cb7b58338c824a374","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"cf5b4d124561699a1434b2ec91a40af5a968214d2f4a7af63d3a829781e802f7535e184355f111641e67efa357","nonce":"1528227cb7b58338c824a377","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"1d87b78a9d4b54bccca46c35dc66729d417ef6845790d487047ba9c67f89358ac66a50e763cf30020302d5e9a3","nonce":"1528227cb7b58338c824a376","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"b808fe753adf23c7a738d33197ab3d11b0325a83242e80438f6b640416dd72241c2c1431c2d33423a514e89c51","nonce":"1528227cb7b58338c824a349","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"06eb255aa3c532992245f4fccc6421f2b020d8a3f1231ed198fcb45f9fa2ced3861e4dcf06404a530bb3dae3de","nonce":"1528227cb7b58338c824a348","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"330ac25e4b3d45803451248468c79cb45937962d535764fd37783172a048d7c26c1c6ca7881c8bd23ec2c84b44","nonce":"1528227cb7b58338c824a34b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"c4550607958343cd9f5ad6298a03730784a0b5036bc085478a9b81ac86cc1ecb601508e63694088198c5aa439f","nonce":"1528227cb7b58338c824a34a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"a1adf3060f7ce0d0df91f6301bb0ffb24bbb96c7449fc2c8d723b84977330facef2dcad0c29a79e504ffe53293","nonce":"1528227cb7b58338c824a34d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"9e057f4cedbd6ea6f72913d70e122074128b1571f4a6ee6482829b1644d031392d33a8a17fe84e5247014d7231","nonce":"1528227cb7b58338c824a34c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"4d0c2dde2fd75ad75159ae37958d0375641b2d557c14287be858b14a10bc7eb0925b2aec7ebfd8f93dabd26b77","nonce":"1528227cb7b58338c824a34f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"a4bd9347b11c8160027643f3bb30b69cb16c41c7d627347aa578f5e4da18951cb6461a04c7f25d94d07951465c","nonce":"1528227cb7b58338c824a34e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"9f20e36386b72cc992c8d75d7cd843f778847729983953fc622d6e2b8c3efcfc51af5ab03b8abdac7750c25a0d","nonce":"1528227cb7b58338c824a341","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"465833bc534e4a903495ddf96cbf78615bc6e856dfb88a9432ed6149f814e33a8afde09828022e7934b743ecbd","nonce":"1528227cb7b58338c824a340","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"8cac85077c39eab8f911054d0de2d737dee65f392009ce15512b244da9fed9194e5e976bf3596595536bcea6f3","nonce":"1528227cb7b58338c824a343","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"9b96fac1d6673c6e90ba4ddac74f4858ee715ffcc94b3caf9e19166c38a070ed589c4ee03ed93086971bf97bf7","nonce":"1528227cb7b58338c824a342","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"959346a5a3205e62b399c856b5613635306029233783787154d859cada8068b9de639895f3506f2bf162e8ce58","nonce":"1528227cb7b58338c824a345","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"041fb58ac93930b73f29a60452ffe3c4004b6280c3bf8f0377459063f29288cc533f57481d548cd187e442f66c","nonce":"1528227cb7b58338c824a344","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"32d814554263bc0e1b9f97518a17190cda39c65bdacc09fd6a158b34f7e7b949fd89fbc52b8ca14fae93f3b7d7","nonce":"1528227cb7b58338c824a347","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"43af8df0b66e9234283a51ef5d0a8f2f6458d89f2c610501da850f754623142e06121883fb342dedf699d90009","nonce":"1528227cb7b58338c824a346","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"7ef80908b80d9eeeb782880601ee56e67be3a029712b8f56dd4bf77c70eae0d3f2f3b80da7bdb7dd929dd82e9c","nonce":"1528227cb7b58338c824a359","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"010979a1cc43784b661ce791c38f45304c6e87e6d47a8ab15ff76e56e11b8d9de18965e58bccee887ca3c6d05a","nonce":"1528227cb7b58338c824a358","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"26eac497d8bccee208f35053102cddd33ec9e59730be003ba42dfc14de6a5d0ad6c798d25928d9c774baeb4937","nonce":"1528227cb7b58338c824a35b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"9df3ab42b36758bd7d416a254911462ae3253da8a88aedd31d44cb0221ef08afce31f7cf56dd1d96596d7d5782","nonce":"1528227cb7b58338c824a35a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"8237bc8b42eaef3b73b6270a2fe5ece08f961822850fea7d88cd4f1d4e305af9223f7d42f51e4e423b59014eb3","nonce":"1528227cb7b58338c824a35d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"4c2cfeff4aa257f835939731bc308e07672f90c7d6c7945310395124ebdbbd598fc0406c64482455bb95099e16","nonce":"1528227cb7b58338c824a35c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"8b4efb1ef869b4397fc60823582919fa468c6a26aa097210af301208669036f16412d18b3733dc6141ccd0d2e4","nonce":"1528227cb7b58338c824a35f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"de841294791244b51c1cfdcb5dd9a92eee638d5fa1f01340afc05b5d4a9325bbba753a592fbe94af8af2b8b680","nonce":"1528227cb7b58338c824a35e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"2a42276e202dcc92ca7a5a661dfb4e2e619a9efdd933b63a3f2bf9e3c79532a8c30cad87a4275183d7934fcca8","nonce":"1528227cb7b58338c824a351","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"f15a087d50e9f922eb543e4457fa37d48b6c0c7702b8d3617177c75e88fd14a5305a2014dff18b636e59916825","nonce":"1528227cb7b58338c824a350","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"0b977ff7dba66478e87200441668bbb7fa8f6a1f0d9d5bca678553dec5e4fdf19e721a8fd1b9b27f2688077231","nonce":"1528227cb7b58338c824a353","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"350d06885baf5752d3c49b4f3f6924f83dcf065fda96d6e6a6e67fd96672190defab6e464d213c59808c4bf77d","nonce":"1528227cb7b58338c824a352","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"9d179854d4df5452cd22acce52f7587a24ed41976f002a295a130f9fc5d7b34ec9621682591a20c57c94d3b6a4","nonce":"1528227cb7b58338c824a355","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"3d0150977fef0f1e80da9e2199960d549939ea8d7080a9f853a90fae95a2d3424a57565a9c8a7d0bfc7c965c0e","nonce":"1528227cb7b58338c824a354","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"f7f88b4d8e59faf0d7d1f553bd967738cb17f3cb6624f3d5e160f2603aba604e1bcd4677e62eccd6c8bd5861dd","nonce":"1528227cb7b58338c824a357","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"b51d64780ffbd718ce6ceae2a8f713219d9de8c5ed759eae0ce894d0d6d46905c0b3b832b28670ba69c81ccd64","nonce":"1528227cb7b58338c824a356","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"c932cdfba9c3b0e7534ebda57a1bc4ba2ea36ed63ed6634419f392eb7c42561b69269c8b59a7ff7f46706d56fe","nonce":"1528227cb7b58338c824a3a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"cd4f97bd44f1d8e2f9132b2b779e3de344bfe81cb622cd8ac39fe330a71846df2dc4aee95d29485aab2cf5d1a4","nonce":"1528227cb7b58338c824a3a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"95fde98de5680e7e7103bff307bb2cdc43579b646da26a02c20a1183bd80f6559b012aa33bddb8158c9528f463","nonce":"1528227cb7b58338c824a3ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"c05db27bcab58a733d05a49ee67cd0c1e8391b47f4079a396501ce40ff4e1098a99d0c96be31a844001fb7ffc8","nonce":"1528227cb7b58338c824a3aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"b4c1b65af052aa837fb7c653eb4e5d9b0e8e78efcad53f28e05f423f9128ecfeaee91b01a34d0a3132d14f7a48","nonce":"1528227cb7b58338c824a3ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"4ef6b3919ff8d3de03e05291d5b6a63d992a9e016e5275ab4f4edc7960dc7c3f8d11a870a040942097dcb7c22f","nonce":"1528227cb7b58338c824a3ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"58e5c30ec50f60bb147386cdd6e1a9dfb32e19155191b727497e9190d8627d356e012fc2ee364c8524650d8ee3","nonce":"1528227cb7b58338c824a3af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"10b9f7c140e413115d411547665416c3d5e76157f21d671425b406105935b8f134fd0d46f556b3f58c51d06b19","nonce":"1528227cb7b58338c824a3ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"0f4ed80f99ea4f6b0ccf6be383db81747fc25fb2c23ec22bb55faf2ed4095329db803a1e14f04910236d2fd3bc","nonce":"1528227cb7b58338c824a3a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"52aa3d329f5713c7cccf90a08c73e537d90683f233805c10144a8762db10e11a1a180d791d5616dd50a5afc612","nonce":"1528227cb7b58338c824a3a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"82b915f00c28e4475c08add0db8dfb9e370d89ce02956ae7faeef1d5c628a95ec498c6fa232c2c1e84fa3dfb2c","nonce":"1528227cb7b58338c824a3a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"ec45076678ec1cd3412b1838734ba2f681d3bd8f65b577a8b76124302622eaf3ec42936f7e3c95023ea953402f","nonce":"1528227cb7b58338c824a3a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"92b78fd2451b32e128b85d64e496c094fcad0982b324f19f293f03f56f2534e23c8b71a0a9f5c8b12890be4483","nonce":"1528227cb7b58338c824a3a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"51d5f4190e190725c72f157d84644cb7290ab677be65906006137854d4e5773d76e4a255aefba9d1500a5026f3","nonce":"1528227cb7b58338c824a3a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"1894a5b24ed7f79052f265a9e1b45b827b16aeef4320f9e8506699f7b8840ea84b472e73f43ca2f9377cda667b","nonce":"1528227cb7b58338c824a3a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"1adfc55f606e33ff77e73cc1444f8789cd7b453768c89689e600d0d991e23b49871647cf11c8079df620de53a5","nonce":"1528227cb7b58338c824a3a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"087c5fbde9fc8700d525905d0e436d3232ed7c20a4ab8622be3b8a8a360bae26b992f34485e6eccce5e569c9ac","nonce":"1528227cb7b58338c824a3b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"a1bf80c9eebbc804ebc569f4607fae8064c941e7628b00cf181d769a9a64f85a0476ec437940f1e1e5c4d4b239","nonce":"1528227cb7b58338c824a3b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"50a1dd680c24ebe502b265155c2fa30d455974524bc4bf50b56a6bcacad0d14e30633617b2f05125aa0c7b2c51","nonce":"1528227cb7b58338c824a3bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"13120c47939e4fec77058b8db0944e0dcf531882170e13fb01004e638eb2bf679f22bb11f30e02da8711e8cdde","nonce":"1528227cb7b58338c824a3ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"d186c003e3b0ce5dd4be87799e145f788bf274af49d587bd2cb929ab2fc4251aef70c1a6e9cd7cfaaffeba8756","nonce":"1528227cb7b58338c824a3bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"13700a659895f7d6c2a7f85f481a586377530a7b70592e6d306076c0579e4c44f3248bbfaf6b8630f34cb8e4a0","nonce":"1528227cb7b58338c824a3bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"178a2247aa4c7a9a9ba1194a89d3a86b72af6d13a12077d229d89b35370c62c54e39a0f7c9fcf2a9d0d77c31a6","nonce":"1528227cb7b58338c824a3bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"c138371ee2e44fab5982767fc6726ab0590100f4b4be2c7d889e1fd3125a25f9f5711f710e946944252ee55bdb","nonce":"1528227cb7b58338c824a3be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"54c3f3f66caa6b3c946545a6bb658acb5594e951fbacc3d0f6438e5dd69d4431f89d265dd63623cbe703b8ca76","nonce":"1528227cb7b58338c824a3b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"2c86d8f0018b4cad1ba362cf8051278f5b98e04296dab906ade59519b886ae37695871dd26d192ad3c39a532bc","nonce":"1528227cb7b58338c824a3b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"a81ae621a0a322c10ea845b3461793bbd659821aead3a43687635e0f7040989f21477f2aa9e43706ae03062817","nonce":"1528227cb7b58338c824a3b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"3aba5c59898ed000137defa4ca78bc74c91ca846d58308374cec7aa8063d616eb0b899707abd047d67cda2618e","nonce":"1528227cb7b58338c824a3b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"23d2060617c102d98dfafa30ed5f35fb3b43b25ad8253c455dfe37355885d732e819070a811dac743cc94d1e6b","nonce":"1528227cb7b58338c824a3b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"a31441b4bf6fcf3c4ae2019a7e460873a18611f019f8ad8655e7d606b6da199b47b4b90db0c9e551fe1410c96b","nonce":"1528227cb7b58338c824a3b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"80807c2670666025cde5617a720ed31a39e0e2792af90ff20bdde69352f1fefde05b474f3a647bfa6ca06eb1b1","nonce":"1528227cb7b58338c824a3b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"470a17dcecf7a2c96593e46a494ed02b0c8eed9014f2d8f0680f325ea5cb684df95b00f3c7401a517c01b18aa4","nonce":"1528227cb7b58338c824a3b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"f896a11e7a1fb8c1f21f5dbf974760a13948504467395dc5bf767c0fbf5d63f291a37cdeefe350064b9f3c6bd0","nonce":"1528227cb7b58338c824a389","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"8c0a749a50652f7e7a17005501833b7b31c83de81d5923200c98fab3ba742a8479b991272fc2c2d0fcd508aede","nonce":"1528227cb7b58338c824a388","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"89c2b478a21479029c9f72ead225bdf4f11b650c5e9211daca0636e54715a028e29369e909dd764aff9b4a81e2","nonce":"1528227cb7b58338c824a38b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"1132df2529dcb4e80a7deae764a216194d5e21b077ba67805d3d22331984498fffe785aae3199907ed1e52f691","nonce":"1528227cb7b58338c824a38a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"b26c22c9656d3d6430d5d044d6dd084b96006621e549c783b3a53826a0548cf065c0bb759a9c91103b688ba21f","nonce":"1528227cb7b58338c824a38d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"38a2c9502ad2a4c064fe0b04b9070969cd07e2463235ded6cab37192991314957ff51482a9089dd6f8e3a61728","nonce":"1528227cb7b58338c824a38c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"c3a43bbaef3b240bbfb9ff83a37efbf99ea1de4147ca60d3a1b9502c45754237bc0ca80fec507f4477194d667e","nonce":"1528227cb7b58338c824a38f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"b8c2e776d8fc075549bfae95ebdcd4eb6f5615215b0f149583dd93f36034b4372bb8b62f9de5c3aafd1f8e7fd4","nonce":"1528227cb7b58338c824a38e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"004aa52d4dbe3e5eac2acd1ce6fa6b7d7ab748508e4ee3bf793dc6f850b39c846a7b37100c79f6235a198f9a9d","nonce":"1528227cb7b58338c824a381","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"2c142d824186b1028d4e05f0507037b3246b9b755103ab74a2c97e617e32c7d1fb456a38fbb9da310824e5efb7","nonce":"1528227cb7b58338c824a380","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"88cbf0e2d73b08b17f3b9aa5b5ba508bf887e2dad2f61e5e87fde82bfaf8ae2b238d569c242dba64ce07dc53f8","nonce":"1528227cb7b58338c824a383","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"1c4c75e4046bc2ce684de13a840b3379d1fbc4fe41003ae79d92a67501aed433481c9d440a6b591668096fc1d7","nonce":"1528227cb7b58338c824a382","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"8e9984b66e5cb7ca4df57b22a8190efc47a136d11dcd1dcd69f6b40d3ba796ee8d30fc452e8eb04511091572d4","nonce":"1528227cb7b58338c824a385","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"a45b615fe03cd93935dfaea24070fbe658fb876a876e37ad75d799fe8ae9642dda1d1da662994881f5582bc2fa","nonce":"1528227cb7b58338c824a384","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"c9c6f10922efff56b5c831ff82f5a6aa828b29b16f6973aec249d1ffc484e60ac1726fc5542583de5576820df8","nonce":"1528227cb7b58338c824a387","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"dcb4b94d7d08d561d66f928c353f37deb5d6d01b021f26ce49d4034af4ddfde52f2f1a0137fa2ac773abefedaa","nonce":"1528227cb7b58338c824a386","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"279be116981d31009fc10c32476c219bd4861128c76f331333623099d87ad0ff3ff4d68ab3a7e86712ead37b25","nonce":"1528227cb7b58338c824a399","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"b8528afa424316a76aa18ce4ef710cd978f0c951d46f1c9001b75e15c89439fdac7cc31a57898939f10d5f35ee","nonce":"1528227cb7b58338c824a398","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"198a36fba051f6e34a9c4388d4748db4d03732fbf7c81e5900da54e5fed4e4b87df7a525f6da9db1d03b6743eb","nonce":"1528227cb7b58338c824a39b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"ed5aa4d0f9a9a559c92bc9658826033acd825dbe01b4dad1ede1b2eb2f0d8a687ee65199c987731bd88a02c1de","nonce":"1528227cb7b58338c824a39a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"c30503e5819e19741aa9ae7d445051aa447b0859916f383b8d4d5ea1cda3031037309a798a92b71e43dbdd6011","nonce":"1528227cb7b58338c824a39d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"85547c332d436780ddb001b23a8e663a8ce0be433f436dfdb100127517dfb5a89d89f972ab924a84bf58ca7986","nonce":"1528227cb7b58338c824a39c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"18bcacc5171eaab283599c36470b8c0c8553a4ba2569dbb68de69ac87d35af438ab818275b764bfb4bbc7b7d4e","nonce":"1528227cb7b58338c824a39f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"19b415007c520323aec8073f11e21da52a0c4bded5bf2aa80a68159f59580be46242111f29f7858daa45819e99","nonce":"1528227cb7b58338c824a39e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"9a0901b6e94d47b3e03405c4355ba192bed2859eefa6989ec11c2adf0a5d17620785800c0b25c18ddff605528d","nonce":"1528227cb7b58338c824a391","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"3b42587a37be9f6e8dc0cf84f93c18696def504a9c1444045f44abf761ca32d395aa885b8dc92f0222c3a69a14","nonce":"1528227cb7b58338c824a390","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"a1cbb8592a923d5034344b9b275bad5d8871c61560448b0795a13c14e6d7cdd381168a8e6fce02b43ba3c54594","nonce":"1528227cb7b58338c824a393","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"7949aeb4bdec6d39d5631a72fae86106d86847f71ddbb4b4806da8f2cfc75eae75c34c56167a22f9022758ea59","nonce":"1528227cb7b58338c824a392","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"3c00c1643933fcc690772c3979fbe2d7b5221dab8778a4c24cf9640ed1e888d930f4ce8e3b6b8383e4f40e7342","nonce":"1528227cb7b58338c824a395","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"57c587e25c7d8d2f63ad2514f1036fabcc919669a3bbb23a53955f6c64a4991d4ea6e8391222db6572f35671f4","nonce":"1528227cb7b58338c824a394","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"9026b1fc7ed54a24806a689362a9bf8167f724fa2a4012e5b7b0148b0613e5af115ae40b3adc779c3b464a1610","nonce":"1528227cb7b58338c824a397","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"d92b742f11df5b7f2a142b98c3b9b39bad6c22f0889c68d770e70469e673049b58fff76774b4c0e9bb6b1a0677","nonce":"1528227cb7b58338c824a396","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"ad9f20b8aa2642b4013a7260aa5d6d4bf629710941606e35961c342d291bb1fced352897cf247ae56501589147","nonce":"1528227cb7b58338c824a3e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"273c5a429b1944d6d93feabdeb76504fa25b6ef305c11519094a32801eb62869ab51dc0f91d3571233d8a479e7","nonce":"1528227cb7b58338c824a3e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"582aa69c36f70a2f90bfdbfc0f701d34333fbfeece96878d4c3646fe515da278b5be69bf231ff95941e07e0831","nonce":"1528227cb7b58338c824a3eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"2854be4690a0dda6b6439f79b3643d22a953133d8d409ccf65576d96446701c6f5a151d46e6826645af8fb1add","nonce":"1528227cb7b58338c824a3ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"276c0629bf541a168cb08dd1d9318094e0f94cf8a7507cd71a34df054945f16a46d28b9f80240618054d0901c6","nonce":"1528227cb7b58338c824a3ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"34370505bee832761b4e28d2278fbfd16934be925952cd11ce888206e9afe738526c8cadc3a4e69d066d1965fa","nonce":"1528227cb7b58338c824a3ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"bb71066a67c97c7d0df222a6c76e133fa7263536988f99a8da84a5aac979dfedc40182954fa9a23b48d9e7648b","nonce":"1528227cb7b58338c824a3ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"516fe7afceff7ec09578847a30e3bed2bdbbff28dda0fc242f445885e675e1f16a53456440b8ba1ca6636c238f","nonce":"1528227cb7b58338c824a3ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"ce5d569dbc0945af441e093667bdc43e89e6b958e8b4ebe8e37e0bf667bdda5fe911bed61fa69810534d461a14","nonce":"1528227cb7b58338c824a3e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"fd9020f6051d2dda7abdba10d4b80569f221c69817eb136bf64e447b91564b49d7848b2a57eb65bba72a92af7f","nonce":"1528227cb7b58338c824a3e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"3841120c4cca7e6fc0441430d9ac55f6410db8d217b4486a9754c9dd3a10ce8fd5cbf58cbbc576a7d9f7006d32","nonce":"1528227cb7b58338c824a3e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"8e7f0882d8eb2deb8755ce1edd6b66f615fb1f3f40bf29283cd75ed56916bbe58ee60a9e192a2860271e76ae8d","nonce":"1528227cb7b58338c824a3e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"85f595f6a9b7550be1c73acd5aad4850ab58ba017b8ae9099f1f770373b2b0dfc0af0778de5c92578428adbde0","nonce":"1528227cb7b58338c824a3e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"c8db80370a3c3ca367f3cae1785719ef6180c68a36adab9827215fbf586f39bebdc0a02d4de8bc1c0e46d4d753","nonce":"1528227cb7b58338c824a3e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"397925fafa3c0709353e0b8dd0e2dbc122330b531b0e00ebdc941df648081496f2f0f280bdaa2ca84acd310e3d","nonce":"1528227cb7b58338c824a3e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"732a6781cb39ac3b30a49dc72643a85463c1f3729a4592391ca117928b9e8b567825e34629bbc791f2b3d41570","nonce":"1528227cb7b58338c824a3e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"04ee672af0c9010be80f0af05ff9665eba697fbebfa0b342411f5335963558552b796e4e259cdb31ca9131709f","nonce":"1528227cb7b58338c824a3f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"cdb917114fd97d2e4cd0385c54ed3da06e1533d2cfee775a537a4fd791af541513c06d7b5a787815b502b1afb3","nonce":"1528227cb7b58338c824a3f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"d74b60a5793bd36e51e0b413f9efae6da1825dcd1a8f10a3c28a59db8bdfa1cc86544dbf73fb22d427ce695730","nonce":"1528227cb7b58338c824a3fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"b5d4300ea1f4431e049debf08b8d0624d5d060820b24b3cdc1d38f094e3e525556fb16ba1b4670e6d5e1d80a92","nonce":"1528227cb7b58338c824a3fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"3cc1a57fd42a4a0f330fc18de78b11917c9ba785926b96adbe1993c2e9f880513dd8e5188308ce3cc1dad90c8d","nonce":"1528227cb7b58338c824a3fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"afb4aea0da3da4508ff81084da5ac8469f3919cae217873e04cc386fc9e6f32e5d577576417b2f095cae4a1c37","nonce":"1528227cb7b58338c824a3fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"11ae6748714bbff8e357ff37a130f324907364b8cc5490534ca119846e2286efe3df61b8e819290de7a3e1a905","nonce":"1528227cb7b58338c824a3ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"3bfad485d7ab9165bdd3de83fefa8619a083be4c68e2ed823bbf3f0b7d3ea32235975a8b45a29fa679292ab9ae","nonce":"1528227cb7b58338c824a3fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"2f47de252dc9ef6749bd46844e9a0af2748e53aeef853fb97d642f3da657b264792fd82ab96d8c97d1268512c4","nonce":"1528227cb7b58338c824a3f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"00249df376f62deae70adfb93c168e4abd2dfc786bd6dbd7d79c7c86831f44dd650f6ae12fda64ccef92ba208a","nonce":"1528227cb7b58338c824a3f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"ae9c1c9106555f220d939b184abdcdde2427ed50fff73cbf450b4fb6f500a2c323dbc2e19e25b95f144ba14bf8","nonce":"1528227cb7b58338c824a3f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"59d2a0364b56a1182b2754b494410aa8c2f3589e711cdb556a2260ada7916e349bee9faf3bbbdfc5cd0be8a006","nonce":"1528227cb7b58338c824a3f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"b1a71f59ebf2eadc179fa401adaeee3ec21aa1e5bc7a8eac9f2822b7c592ed64691016b6cf1e2fb280f6d8003f","nonce":"1528227cb7b58338c824a3f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"0e479931947837703d63f136a33713ca375f0133a8ea7aae83527251f3c78d7e884a371c453fab58ca13ad6cfa","nonce":"1528227cb7b58338c824a3f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"b5dbbee9affe26d300f87824ecbfafc76dba96ed1262639692ad2259625daa6db04b4e6d72c63d95ab6d8424e6","nonce":"1528227cb7b58338c824a3f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"c63b09e2627f633b2d1eca2d168e0500b67a531e1acc0c2ca0418d2a62ebeaf547fe7180d4fcba1de66b2ff42c","nonce":"1528227cb7b58338c824a3f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"2d872cb0b0c496dc5228f1d19b8b59e344e1f9c098966118a85f1df49569bb2245914d4ec00e6141d0d086b1c8","nonce":"1528227cb7b58338c824a3c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"6c6cc791a1121dd5e82b573b5db65e9e17627e777401daa7ff4bc551683e162cd99b7901e7f1b76068d8afef7a","nonce":"1528227cb7b58338c824a3c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"4919424bfe224f40d36d1fe8749bdd570953417bc8e1fc4e77b3a6ab72d945ceca96568446cf06c4c5ad169f88","nonce":"1528227cb7b58338c824a3cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"1a1aa8b6637e1618b5b9e0ed18d31ef5b189f7fb85aa0a29e807578a9eaeb22c4a2b75cf64beb31311e4986e2f","nonce":"1528227cb7b58338c824a3ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"de282200132e4f8da1c849e863bbcda9259ea1a9776e89deab3f4cc3a60e5322d0049f4788a086b9b93ef10b0c","nonce":"1528227cb7b58338c824a3cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"9207673e4b3841c398339ee64f74ca8a27ca64ff589f8df5fac834a364ef37b4897852e00cd4ddd252858e8970","nonce":"1528227cb7b58338c824a3cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"5bf9e67383c9e522028e238874da78a967d987b8ce959a0ee8f6eae1716507698da94abd51ac4d3d1f331ce8b7","nonce":"1528227cb7b58338c824a3cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"0897beb7ab8ee96a9fa12d3c8844aa64bf56dcef903484ee2d0da301ddbf6df33f31b1f5024d6704eb12620367","nonce":"1528227cb7b58338c824a3ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"90a3603b038bbc60ec0901dac2536e2fd28cb51d8a48cbc6e822a3c04437d05e47b087a29c04815d032a3b0d88","nonce":"1528227cb7b58338c824a3c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"5f4e8fd4fbe087491369094149cce708071e7194b14b8a8da7b3a9b2708bd7114c2fffd6a7a9f30b89109011b4","nonce":"1528227cb7b58338c824a3c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"30668f249a84ec9ad875eceecef8e0b617c127bb1f8a45b3de91560fa1813a2cb8015e35f727958d978cd3d477","nonce":"1528227cb7b58338c824a3c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"1cf1dc0f6ee930cdac2a3e5e1daf75ccdb02c2846608bee295e33d16d7b8878cc8e72fdc4b7eec64e6de50b19e","nonce":"1528227cb7b58338c824a3c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"5eaa57cedb4401981fd4f33608f23bc966ddf30eca06483a1dc635e5c2e6aec863d0cb5b0969c586fec7cc52b5","nonce":"1528227cb7b58338c824a3c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"aba8086b3794d26a8088d8574ff26255f11dec6232beb745e5331f77fee5e29154b342ea5aed08344107f19eec","nonce":"1528227cb7b58338c824a3c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"de2f1607b977bc1fb4fdad6ce96a9da36c3950a3205c572d06a496492c10c582a236fe2754343a5c83ba7f3d28","nonce":"1528227cb7b58338c824a3c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"31fd081d8996ed6ae1850fa713ba841bbc364994ff18071c862f123fca806293ada9705a60bae8e84c4409975e","nonce":"1528227cb7b58338c824a3c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"c5425c8207c11d0577a02bc43c76377f80a3cc9cf461106501c1464ad257517742cfcb0f9dafd3b265f307edbd","nonce":"1528227cb7b58338c824a3d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"a7c5c88e34eee79adc354b0beefb5c705fd2448b31fe8b4a53c227e3ad9b8fb5831570259e37054e43c20eacfd","nonce":"1528227cb7b58338c824a3d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"9f1da65a4412d7f6ea24a9703d12aae77844f30a7a3d3e03c652dc7e507d4a26693f7476a19df54a72f36d8491","nonce":"1528227cb7b58338c824a3db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"67bba2dab89d6ea48234dd6bfeabc330cb53302bc002081989ef3d2165994bacb2007dc98120d69aba067ba53c","nonce":"1528227cb7b58338c824a3da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"a72f769717b8d762264e50dc45c62f42c06c598fd5416c54f1309b1fc7517ae5e7b18c9293481a2f433ea4cec4","nonce":"1528227cb7b58338c824a3dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"ff95fe6441dd3eeed321f0d22a21a320653db4f4f34f24de91c8921a3d73a005dd5c0e9605f5f70ef3ecba704a","nonce":"1528227cb7b58338c824a3dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"cee5804c239af8378030879d02737d08fa1eff64280076d28c6bce9626ca51ab27615283de15942d7d20747fc4","nonce":"1528227cb7b58338c824a3df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"5c2f52efb3fbb8a7091510643c7c039f5d410939cf581267b0e3ffebbe0685336094261e36c859da197fe9966f","nonce":"1528227cb7b58338c824a3de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"f3f8cf09bb8a4e9ea7355e47d48ec3b9bf7c64df8e2ec2520c6856d8a7211fbe9a40bcb18338e036c4c74cfdf1","nonce":"1528227cb7b58338c824a3d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"af3b269a3008a3535c36deb464f7a86f204ab11c3d6e6083a84bbde19ec120c1c5b1ed8eb3d8b7d40fabbd371c","nonce":"1528227cb7b58338c824a3d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"39eb314a45eeb04e2d717e699da9cbda942d075f96634f25e31d153739096142800a77fb221be96b9c57425b21","nonce":"1528227cb7b58338c824a3d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"776eaf0e13eb721408eff0b9aa368361c05a63dbfd7d356b4dcdcf3696fc102368549c1a58cf4a112e4551ed84","nonce":"1528227cb7b58338c824a3d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"3f267c54cd800d3977468d1e5376d35c5d26c7580cc5b4d41d2586008e66998e8d692cc4917f10863591dbce1d","nonce":"1528227cb7b58338c824a3d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"c290236fded85fbca79ffdf70d66964c4965f908e17d75c3833e1fbda596527d9e67efcd46b4dba7366674700a","nonce":"1528227cb7b58338c824a3d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"94f887c13862294ce83816c3c17d5cf8db2f611ac4f0ce46821596afdcbba9d13d43a012db3a27dc0e6306bd3f","nonce":"1528227cb7b58338c824a3d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"e6d6d270d7f7a4bbf8093b88f5a8346ab11c4fae1f0ccf2b85c534471ce20c2f343d959f54baadaf2b9e89442d","nonce":"1528227cb7b58338c824a3d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"d30423c68b58952e27a96f2ff2a9d9af8be03b7668dd10a869421fbfe5cc3e07720442cd5d79df1e7a454f8dbe","nonce":"1528227cb7b58338c824a229","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"fe31f2d25db352bd8a6513a91bb89a80c4ec0dcf38416343825f0092ec6e7cc0"},{"exporter_context":"00","L":32,"exported_value":"80ff70091564667ad4ffa88ee2a59b1377b4708d8732b8a3c997a99616395666"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"8854a458caa953d9c0989cc54499c82a26887f10d896e003fecc85fb197dfe2b"}]},{"mode":3,"kem_id":18,"kdf_id":3,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"734de51c4da1a5c78b3102b45388136bd589e743b9a0f9fbc855c11e252869f67717deb5bd186e081b89292ea5dcd9b20c28b44cb6ebced20ab9cbbc9cf4d8ee0529","ikmS":"2ecec07ca0aec8dddcd1aefb76a2e8c88973be7001cfcf2fca2add91eb6b0f90355375ab3b33d5ab96fc87bf403e9462fe6f746b1c26053d52e58646b1eafb9fbfb7","ikmE":"7128f0daf084a3b7133e08e0c72d0ecd024aeed9ad1d5552206318921a0da30c4b7d9c9843050af8ecfebf20ae9a1c6720030c43e4ad7c0170d2e7714fc9e4c3e867","skRm":"01a177f9517fd3cd7abe143d54842d0a69701a9735f09e8ad70ef403deb86102060aedf68906a1ea092c2eed996e90b7d69ee2e6377d14c3598d28502889c8b77091","skSm":"00f89c435fbc21be4e462cf1e79d39c4db7683fdb31ed1221296245f7d4b5148b7942a774a44c1f178461dddc0892720d6365415011d53ce78235012d488712adff9","skEm":"018ed7e366db633e5eeb09195b89c30b0a4a5dcb46cf5e06172e13e5a0671ac650ab6f13e74fa965b715907688cd1e5b59e27aa232f12a5b2e2b7688b038acf3db8e","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"040033ea908e2be71862818d1dda6c53af9beb9c12fb8f32be42ba7383dff2cc5abc197b63ed640dcb3f612eac30d94f9a719cc528ece89680b76075bcdd32d3712aaf006a4bcdfe336643302c0496b12e7367ab5037c5cedc27827d301e904e3888f96ea9616adbf84de41df1c13bff290f1e2ec2e65a4555104604100bd62d634815a904","pkSm":"0400b8cf1b6c1768fe495c751bb3113ee586999cc1eb7778acdc093f5cc7129becef45411f6808d87b6600c5595d8ff186bbf7d06e661aa87acfdee9be034805ed9159016f070236b0fbb7f7bf50543b7eeff1268af1cf194be7cc4782c3d1e3dc169dfbb7f973563f3f66df7f00ed15b884cd4e4ce050f694fbeb91095f2c836868c454ef","pkEm":"04002ea0073e9058ceb6fa3b74cbb33b1f6363fcbfbd736ae23641f068ac0c3f1a6abb60c58afc36965bfbf602e289308697c2b13b7730f28a04c835f13631bc8f7719013e4ae148fb4934320ee2b80c01a7443264f1cb84563228fec34b4c24b56b9f235995de00377b18bcc5331f3c5a809b87a37c02898630171bf3db01358dc8ba699f","enc":"04002ea0073e9058ceb6fa3b74cbb33b1f6363fcbfbd736ae23641f068ac0c3f1a6abb60c58afc36965bfbf602e289308697c2b13b7730f28a04c835f13631bc8f7719013e4ae148fb4934320ee2b80c01a7443264f1cb84563228fec34b4c24b56b9f235995de00377b18bcc5331f3c5a809b87a37c02898630171bf3db01358dc8ba699f","shared_secret":"24e3824c5ab44c412892b6ef9ff4916f1dd534315118fbaeb11c466a275d3d7b21966972831bbbf9f06d90800f59c81dd6d8efe4f17cd05d9973d03420e2fb3d","key_schedule_context":"03c208fd0a0b5a080a7f539f59e422ca4e818e634e12a8947f0dc95d4315990d38f86322f9fdbabd010f1301dc6aba400a053db66487c59de1a557d1eb4b5fc9c4cdd87b0281e692a99982979c39757078bd10f16f51a609804bec7ea73e6df85d53e5b21081fb76ca400113c07723eeb59281dc77544497e8f8a683106eca75ea","secret":"d00bfb2724aae502a3ae9f13af16455086e20ca8e2e684f28e7425e679f59edcc4d40cedd3b4d3495460baf3f300e67df4afa55ddc3562432ec4468aea7e6a32","key":"c9b0221e8b14477c99ca77ee9d65b2d2","base_nonce":"861de820f46b4002387cd2df","exporter_secret":"4e392dd010362e550b7f2a2579ae52f6bb9d1c34c6d948c05d9b5d18af05bbc94804cc674f7b1b999f5259a459e0c223e8b77c2c32fbde2214a133e8089eaf17","encryptions":[{"aad":"436f756e742d30","ciphertext":"54b5deb0658fdc514d7db3086f5b732a677656e0c0bff5c2ba60287cfcc5d2b967874738db07f2fafa1ef0b415","nonce":"861de820f46b4002387cd2df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"63d0abc31c798345e18da8e291301f0d06a22be35b88a4b02f6e9bc46f9e95dc010bc8422e2d1ca401b02c8331","nonce":"861de820f46b4002387cd2de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"90d690ef9e5c740299c199f309360103d0e1aeac3df7fe91116669f4f6cbdf7eee8fd14905f88ff8f145420af0","nonce":"861de820f46b4002387cd2dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"6958301827fae8ff4ebf2edffe4a86f7ec51fa8c8b7ace22001cd9c8470c89e930ae599a255716d62e02a31679","nonce":"861de820f46b4002387cd2dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"4f00d4ccc042bc8ac48aee264356977506686503f1c6f60ac107505479f5125d8b0cd72b37dcddad6ebebca231","nonce":"861de820f46b4002387cd2db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"58b85223056d198c9dd092d1d2ce8151b5a055dba46b1093d944256d470b15b58fd384eaff71a883216ef337a2","nonce":"861de820f46b4002387cd2da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"0455aee142a77f4648e34235d73152f9baf376a83ccf82c452ceb50b1ba1b511f7c62b649b893be43d27a38618","nonce":"861de820f46b4002387cd2d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"ddce9068c981376bb3b2aae4ee60b21352b34a22654757d58d38414144751942b2eca3392366a86c48bd87c3d3","nonce":"861de820f46b4002387cd2d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"2c89f540c3329d643f4012696ceac5c216893c9e6fd09dd3daad1139ec021a9a476e616b8eaf966f6f8755f571","nonce":"861de820f46b4002387cd2d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"1850e604d62775356032bedd590c4b0f3778b8bc4fd11d20f22ba5c90332614e37c7839ee9a198b99c90fc7c88","nonce":"861de820f46b4002387cd2d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"8bde4d8ca72796efc76767e17ce352374062a964b3b3504b79ab8d9729782c7077db6295b65359357272d3763d","nonce":"861de820f46b4002387cd2d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"2b4265b1aa10867a5ac0e6c6a7231ec8b6b3d1b6f7d4bbfcc4c97ec5b6c8b2e462dcf11e8355d7aa343b512e08","nonce":"861de820f46b4002387cd2d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"f87e729f0ee8b04fc9b2b5f3a7e1668b11f3d3ae69ea7dc5970cd6d4e77752c414f795d5817ca9b8cee3b257f2","nonce":"861de820f46b4002387cd2d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"029cf306c9665230e5a0f1e61f6080efe219a5ad9bc592e6c1ac8377101cb63205e9584f0cb654f7e4086d8506","nonce":"861de820f46b4002387cd2d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"f0425185c96ff91eb681396049aa79cfbcb343b43785a4d5dfd557971e0908b2160a96d5b2d4ede15625680fe6","nonce":"861de820f46b4002387cd2d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"35c2fa093e21f1e79c34371cf66133e4e5e703dd66a76971d71b119d449614625a0035034299e3d11862070a3d","nonce":"861de820f46b4002387cd2d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"d1ae8c1c0049eabe07ea56aabc141866f599f5dcf57107b45d03ca85533f3b954cded4940d35babdfc467b909c","nonce":"861de820f46b4002387cd2cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"9e645f49fb483828834e65d66e6544978358c6cc4e4bbd33e46916dae70c05b4ff7020a42f0a4d7343024be1b6","nonce":"861de820f46b4002387cd2ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"7e17f236b4858bfce415db4791d244e1eae9e4045d8dfbdf51efe8bfe2b524a92d7b3208a52ecb0acf2282442c","nonce":"861de820f46b4002387cd2cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"3e0c61bc222e2c60c7d64e0946c9fc95b14be03762dc3b77895611372a389367aed34ab9b7651189fec8e80e89","nonce":"861de820f46b4002387cd2cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"0bd4ba1dfdd6196cea57db685c2b8d5947dd87ce5940dbc7c82968e6ffa9852bde896bdc7f367a6771a437937b","nonce":"861de820f46b4002387cd2cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"676989fb6a6a9de19ab9c97520e362c9f058783278e394630257eed99a1ab958e722701f496e12c54183a7a9a6","nonce":"861de820f46b4002387cd2ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"d41909a8b7d91a2752435eac72ad00dded623bba9aa05b7b47cf77ef5fb2b3c3d36e75c60df9ec4e9951d5045d","nonce":"861de820f46b4002387cd2c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"5a965b6f43533faba6f1d34132614de02598831fcb4e9bfd7939b0d46670ba4535f5f0b64e967cedb5b55527c1","nonce":"861de820f46b4002387cd2c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"2d072ddc516763f3a691bb092fb30da109fc27d23b520ff6ebe2bd8260e635a29f41bb1bb9f31f473e7f55439d","nonce":"861de820f46b4002387cd2c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"554cbd3c9119fb79995041c42f8e21d9144165485dfc729768d806c9f825ebf81e51c3e015e013b86ae1e9ab54","nonce":"861de820f46b4002387cd2c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"a6d82ca336d30db734e1c9cd9a296d83ebb7c2c557fd0afd1e2798fdc53c06db2dc5ce326d2545221f5c4263ed","nonce":"861de820f46b4002387cd2c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"47a9ffdb1b978a40fca83c00cac188ce06ee35e6f6a92d08a7a5ffa2b6329a9ecda09516681b5c000bae604c4f","nonce":"861de820f46b4002387cd2c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"de8f7165f9d399126be2e56bf91ba4a21c6b9829d393034bf97b5291858854cb4458cc4f9ca2ae3e6bc17a4c99","nonce":"861de820f46b4002387cd2c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"bf5e2b13041f65e6ae2edacb33fc7058d789713c047cf4c643c3922e10790cade790656bf29af5d5f328d7c8e0","nonce":"861de820f46b4002387cd2c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"7a4523af047d5bd56db34eb623b882b33c6f2ad995fbc348cc298fe379330b5cd0d64160b69b1e650a6f362091","nonce":"861de820f46b4002387cd2c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"41c6e45a63281bdbb57ba0ed6a8ce6fae9417102d1b353f8da1f1a0c658f9fbd16cd5c47549a6dcc3eaf72fd0d","nonce":"861de820f46b4002387cd2c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"508f65252af387f0a94884d0ae4b78204548b2990eaf656bb352201fcf6747c699b33d30e5e2276cb1d4f21ae5","nonce":"861de820f46b4002387cd2ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"f15d939e88ae550a47ebf8941bc362037499b71460c36775ca7c7e952f8953f6be42cbc8acc1189096379099cd","nonce":"861de820f46b4002387cd2fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"e3b957d84fdd0908c80793a5d07d4f2543d81229f987f352f63829c1ad903f321a8397e81df0cb63502971ea91","nonce":"861de820f46b4002387cd2fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"4af9631fb428169610c4dff2474883e4944bcb6bf1ba7ca09f70bf17b143db843eb60c01164a29d1a9aa085cde","nonce":"861de820f46b4002387cd2fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"6a44b2898d76fcdd7beb8913d979a542fa7010f93a552e5f097416e9abed64f673c03fed99c86ec8304eb399be","nonce":"861de820f46b4002387cd2fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"28c4cd5e21fc86165b5508a0510f24b11688466c182ac005d65377a74a9f3ee8c2a01a50ecf68482077cbc34cb","nonce":"861de820f46b4002387cd2fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"e1f3037ecd17dac218fcfcf72b9e7f6dc6330b5ea3e272417e656abc7d14c81e262197c385766e699f941f1316","nonce":"861de820f46b4002387cd2f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"7b937ebd7e5d71afe172a45760bc495dc746c16d90e7ef0ee74265493c98a5605a0aefed107b2579c991669feb","nonce":"861de820f46b4002387cd2f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"c1ae062be4c4e6aaa0bd0432c9af9b5bff39749ee0d6f1a7ade92b38fcf05a44e73387e86998f7d7a0263b5ca7","nonce":"861de820f46b4002387cd2f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"38a44425cee0c58047339423610f611c9eba16e0fc0b0cc7a5a1a08e20f4805f97ebec5fb70a608a367de3036d","nonce":"861de820f46b4002387cd2f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"54572093c19993ca780b5aff90a62af94d2a2f29e63217099f99295e746c3a45b28bfd929e55809b86a008ce72","nonce":"861de820f46b4002387cd2f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"9532a949b4e7ca29dbfca5439114643dadf9803c03471c3af573a5e09eda072460939884157784b36fbb260e2a","nonce":"861de820f46b4002387cd2f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"16f21f1ba2a5f48ecca2184816ec88116d8f6be9988853e6952c62d1f0a0d0afe87007c9ce1faa89d4ddcf07c9","nonce":"861de820f46b4002387cd2f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"410b4c497a7566e0d64142acbcc7dff5f740a6f317b369dba379d93a9006c8bfa2144c14e810575cad081f218c","nonce":"861de820f46b4002387cd2f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"632ebd619484e172c32faee06a755b65ab48565617d3c4f4cd206d40b8721ccdae9961327e4c3e8f27ba880934","nonce":"861de820f46b4002387cd2f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"54dde49cf8930d4723499fcdf86a253ad82f5cb6c147b265da2e948f4e5c9d0032e7e694a4ba285406863f269d","nonce":"861de820f46b4002387cd2f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"053fcd6ce331e4a3462ed80595e655d14fd470dabbdb2a19406fb27e0a602624595784ab903cf8717f83bf9e94","nonce":"861de820f46b4002387cd2ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"de9b110454b27eb22afa00d26d86b362e9138e0ba5b32117c393ed88ced20dc40fbff62af5626deec30ae0cab0","nonce":"861de820f46b4002387cd2ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"e5264dd267ea45ed7ba783e5f3122c81b64ffdd90d290ffa55364079e895280b271765b20be316b50483838b95","nonce":"861de820f46b4002387cd2ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"e0336589fd0fbe474879536c0bef0de0c03ead8422cdb4ba600cccef1702fc13a18267bfa5c8118595be98902a","nonce":"861de820f46b4002387cd2ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"120dbe8b681b54417aaa5fe2cd9c0d93a6a97a74c334d6446733896a14955e4a732b6263998f8853107a7999f1","nonce":"861de820f46b4002387cd2eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"3d78d82333a214dbb93f525e5a2d9c306257fd42c0d3d38e7c8c3dd1c7e8f51465355b5a1c44b398f57ff722df","nonce":"861de820f46b4002387cd2ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"2b5974cf3612e4297bc13460511aa40b9f87e49b2fb9e0991bb90e8719670b648b3d2626dc4385a5e29ba88e6f","nonce":"861de820f46b4002387cd2e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"89a01c4619c5640a3c7859c10bc13e48d4e177f8638f1cc2e1396e26a71f0235c1a6a6c68ca753e25e8c29859d","nonce":"861de820f46b4002387cd2e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"8522ebb44dcf5a8488330a7b0428519307af331991f7f301e1a83165fc34ae6b92ad861fa66c2ed9c7bb8c5fbe","nonce":"861de820f46b4002387cd2e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"3599fc3088aa6807e958335f849c22f2870a7b9de4b431ed0cfc6db2222d6a6a9438b0fa3780df87ff3ace3f33","nonce":"861de820f46b4002387cd2e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"ac729ce07d224becb28fb6d6fdaeb2e8e87c622153a69c129759789b93b064a7597590580634f44cd7a25b678b","nonce":"861de820f46b4002387cd2e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"df4aac9c5653fba3e85db17da0116834fc2327aac85d55752d77a33a9d975da97391349f345d392e86c3e17a5b","nonce":"861de820f46b4002387cd2e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"ad5628f4bb2aa704ee940aad1bd05c278387c16941d7e41c35be050ecb9db4e817686101ef302bf97ff7f72299","nonce":"861de820f46b4002387cd2e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"e1053840d7bb13903a51527443fa15bddac86ae2b9c4beb43320425bd6e0d63d171fd6f415d25681e70590c594","nonce":"861de820f46b4002387cd2e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"d457142fd4d8802ed32e8d1b9d679e2a17749c762f5a323e1094b2e84a23d0d4895b0e36975d3dcd5538b62e62","nonce":"861de820f46b4002387cd2e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"4e0360ba2d00adefb7f8931614fa81ffdc9ad93cfe9eb1ed493a910d1fded94a814e4e7320335d8539a135a461","nonce":"861de820f46b4002387cd2e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"ba6c81b66e5dab5c47703ed06e7b57ef817e8ce45fa487a22b856864c368faeee3468daa114d21ee8e0933fa0f","nonce":"861de820f46b4002387cd29f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"84109360a5c181033f8857112cfa46a8bb09d3850cf5621b5922f2d3f08ad012c2340582bc5773a790a17ebd3e","nonce":"861de820f46b4002387cd29e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"bcc29fa816a6ab996f66b6503625c1fdac834fff9c4fb0f9d380107e8d947de56773bb78f6a0225b64cb37ae58","nonce":"861de820f46b4002387cd29d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"51af0dddfdcec4079aea642cd4da9880b64d2b5ce43d3aaca5ba1bfe6d1e360b6f9f004d99add5dadfd36934f4","nonce":"861de820f46b4002387cd29c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"8b37a9944d3059300f3dab975d04a4e80fe43d0ba69fe0fbb0e3a6323d448f9a08d323c34b78a0a38357fe3bae","nonce":"861de820f46b4002387cd29b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"6635a654ee9b09f9bbfc9b20a9d4a0bb282bc0682b40c86ebd3e35829eae2916b0d66572a9b993f388a0e39b06","nonce":"861de820f46b4002387cd29a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"5af1692ab3a063ccfa972ff0211b4be4eda5a117e6b5d6f0e340e04707fe0db7d96e5cb72c9f33df4d054e0494","nonce":"861de820f46b4002387cd299","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"a9ddd6f2b11f0bbe06392db00d7255d54b42aace475526e436ba6065fa188d526309e3b8b5a1d2a5af80afa73f","nonce":"861de820f46b4002387cd298","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"690ed026b63a9fa4aaed578204b08529aba6dff40e1e1d72b4d85bfc3cf66012c6d7c9e383060f65271d68e218","nonce":"861de820f46b4002387cd297","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"3f451df818a52d5fe105209fbb29f78f4ac9e8df0795a76e118ebf85ee75cadc3cda32df2228bc0d3109ab09e8","nonce":"861de820f46b4002387cd296","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"c79193468ad0d8f049ff214d934cff74af3061e77eb564f10ea36ca58917ef3ddfab3b58bb64c8916c5c5ec76b","nonce":"861de820f46b4002387cd295","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"f614c59ab6e1bf56a3248d78e0aecfc0da6bfc2c572aef9f2e91ada65c72145e5d3303f317a0d466abc6c7a88d","nonce":"861de820f46b4002387cd294","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"b7d11494049d865e688078695b8e22a40c3201d5145c7eae2f3b1b84c058764948b21cc9e466dfb30842392c60","nonce":"861de820f46b4002387cd293","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"4df36dd5ca35f4cae689b070374066b1b4acf2a4bf8a5d6fdaf45c79b11041e7caa982cf707f0bb47e1a3e4013","nonce":"861de820f46b4002387cd292","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"60cfeb4b36493fb16891f44a3fd185195686855f35a693027512798aac752813553810071089af1523c037987b","nonce":"861de820f46b4002387cd291","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"5b14787b9117b6fc8066ba490f59c6226e14bff892b3b8060cb47ac8d5f250328de1218205f87908ea9e9ce32d","nonce":"861de820f46b4002387cd290","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"e8c0b13d79e26a70aef4bbc0e92762cea72450934353dc4d00755958d9b5a583a820c075efd2020e0685e078d4","nonce":"861de820f46b4002387cd28f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"fc41d1e6ed31bcf92a584f105b18301164989de80304c46e0c84fddbf064accbafadcdd4debfc9e228c63139aa","nonce":"861de820f46b4002387cd28e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"b8baf7071e23373a76d34a4a68a0edda438bfbc3cb5995fe71aba5b2d151e184815cd93c8e1463b1e2d9cb3049","nonce":"861de820f46b4002387cd28d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"d87fb4be0091834a5025c784a073fe814df3ec069cbc512714fc343dbbb9fabaca7f7d19349309c3ad5fbe75e5","nonce":"861de820f46b4002387cd28c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"ce79040aea0b793b09f2a2ede81762a2085fcfe4c04be60c47f0ac88e96abe9d507997d8a9e07255d3f72b6852","nonce":"861de820f46b4002387cd28b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"62d10cd925b3af8a8445a0af93ad0d9fb8fe397d0bc122fefd7c0e2932fb34dfecc177a3863bb55595c084967e","nonce":"861de820f46b4002387cd28a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"8a5ced52d5547b7e03d9d823d6299ff97948f03292b3248c9af7584410c3bb3880abdf0e1c1138046d636b92de","nonce":"861de820f46b4002387cd289","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"472ea009ced49a957432a979fd7b7c90449ad6727781a92435fed7b83fe993cf696e53b422dee3bf597a6d6eba","nonce":"861de820f46b4002387cd288","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"534282d2f303f6f7bcd162b36b794fe2349589ec41704c90f0a15f008a04c0bf66dd3ab48f5e095795aac42403","nonce":"861de820f46b4002387cd287","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"654805246e196ba70a7ae660f039e7d04dee7c8ff1f3a3ce70bb2a3567f46a1dd248e8cd34773c7b5505e86da7","nonce":"861de820f46b4002387cd286","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"47a0934d86c02468fde55743489721c963af59688642c623a8b3170b558cf8ab7a9e00a0b4a81aa95641bb9a79","nonce":"861de820f46b4002387cd285","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"22681f69f99ef91c6cd6008cdbe54c2b6f75375fb53b73a105ca0b0b198f8b490bf3ca2365d488e94c1f73cf45","nonce":"861de820f46b4002387cd284","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"db967bc8764a02f0f84c25dd031862fdd2267035d05a2e8e596158936c6a0ae5efae2fe35fe81570d38843c0bf","nonce":"861de820f46b4002387cd283","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"3ded52beb46182e404f455e2a184d2b81089e89dd135374c137f2b9da8354525b123e5354098022f5c5d94e589","nonce":"861de820f46b4002387cd282","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"c5e719396fd9e9e02c83ac4c54c8da0b0a64997c73e6088e7fc8e31a241ed2f76616f74d951c346a23494c34ba","nonce":"861de820f46b4002387cd281","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"960e5a45ecf5d4a06588feabd4b855ee42ac8b869f0ef9c8137abe4fd68bfcc0d43c49c7a985e536ab7f9922f8","nonce":"861de820f46b4002387cd280","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"04a02977859c15cded23f67b58862b93bc51f642303a18d9a1a83f2c7e4e0e4b4428fc427050bd0a692ea1914a","nonce":"861de820f46b4002387cd2bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"1981e8bf07f0d330d7b148ced18466f232dbeb9b3d373b633895a37cc244a8ef952548c6ba834e8586daba3b1e","nonce":"861de820f46b4002387cd2be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"778b9b2764149536916de4f6591d4989e1d2e93e03a86f0b04c30a4282a7eb19a69682bcaca4e0d2df34e177f3","nonce":"861de820f46b4002387cd2bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"5c51edc53e2e920519f8be48150256c85e7cc5b0e528bc549e63d582d26123ac9faa4edf785341d89e9bece2dc","nonce":"861de820f46b4002387cd2bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"48631f2b0a504a8c0e4879fd34f03f9aae8eee247565bf35b7db27e76ca7a1f37ccb6852a1281304a4a75cdacf","nonce":"861de820f46b4002387cd2bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"b31524c14f1311d12e73a29dc2fa5e9b50037816fd31f87e3b05337804a2a407dfd179e7ada351f89a93daee43","nonce":"861de820f46b4002387cd2ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"69739cd8c75fa6a62436885d74bf10608c1201c621edb9b863a06bd5afbc5134546e22ec98689e95ea97cab250","nonce":"861de820f46b4002387cd2b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"fd039b461bdef2357ec655cf694f2d1fe7caabcfcbc55649e552588f34b9d9125122cdb334f92f7f32b92bce46","nonce":"861de820f46b4002387cd2b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"d40f8dd5f19e8059fb55e138c36f1d20a07c71c34f19ed90cd8df6e2610dcca062318c9c7f6c052efff621dddc","nonce":"861de820f46b4002387cd2b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"ee0fbca4c5062af211ed2f6d6f6bf2521ebdebb82418a13001e13bd6639f0c75519a59e092f840bf7848c66d91","nonce":"861de820f46b4002387cd2b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"1ff1de8b9843f3c9da39f08efe056a25c7b165cc7926ef34eb5c1744ccc9b6d4667d80634e8de06d6e4933c4ea","nonce":"861de820f46b4002387cd2b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"f1a8d47e482ce4199424f864aee1230323fdb70dc52299aba484fc346f1915fb626bdf59d5fd6332b6a86a6bb0","nonce":"861de820f46b4002387cd2b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"89af4abd925bc06f40fed8bdf476786d1d68461992de76322300f2c56af1d71880f795337d6141246610ef5e61","nonce":"861de820f46b4002387cd2b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"cc7c441a02e103e119d0a0965d698c9839ae2f34b0e606d1a00c4df7f4e8dc2d41095a64e3254e58e062e82fd9","nonce":"861de820f46b4002387cd2b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"1392e340b7f3c86d18e58218c3477ae0af8a7d7a5f49535af94d0a9fae060421ea1cd3d32c8e30b6e2a99dedea","nonce":"861de820f46b4002387cd2b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"ffcf557c7771d43b6725179fd6a12c65e608073fb38d7554468dabeacf00aecfd193f568ef928b68a73036b705","nonce":"861de820f46b4002387cd2b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"65b9aed9eb1225fed3914ea8f655d647b2436ed70d95911ccd3e425f01ec4691b5509f793498f35a16fb3a95ce","nonce":"861de820f46b4002387cd2af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"4eac0f75920feb709b16bad508a8a96f41b049c237b89e6652fd73ee5ea2f1870a89470daae2c0207726e3d231","nonce":"861de820f46b4002387cd2ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"2ea355f5b4b9a994982c2aa611418dd12aa33dd9a86b1ab9834ffbcde745ebac84e80be0b424483889fc57288f","nonce":"861de820f46b4002387cd2ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"e463d9f50ffafb05834373f51020c43fd160a0a2187accb4d050d951a31552aef98b4627cfdb936642b4ea432d","nonce":"861de820f46b4002387cd2ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"1832228f7c98d54c89d5faac19ee3c916710ec690ed3bfd885a1f8a8cc919082d91bb4a4e3f0482de48994a1af","nonce":"861de820f46b4002387cd2ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"db232aebfccd560fb5731361e242c3d347c6715c91959710d536bf6d7b00f2ff62fc3a4aa84bb154b5b9b5a215","nonce":"861de820f46b4002387cd2aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"9c2c533d04db5e915d7734eebaa129d9911df7378a8ae7e15e5f1435b62bb37d1ddcf6fdc5253399c30b7b854b","nonce":"861de820f46b4002387cd2a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"40d9c4785b060fac3ad82e66fd966f31ed7e9d480951d9d816d41fb80bf388d82dde5a762edd3931ade5846a5d","nonce":"861de820f46b4002387cd2a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"1c0af28a63dc080da3e10ef7d4b5457133654fdd669c135679266049dc9987795275dba1825135190702c21b92","nonce":"861de820f46b4002387cd2a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"dc31eef8f33f3b4d12b7f82220d1a9e6f95ddbef7c2f7e773b3a3783f9976362d71213248207b7abba4f4a7b73","nonce":"861de820f46b4002387cd2a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"3dcacae0714b6eb207e88bffb6d73340f554c3f957a67f3f1c309e9281138b16c9ff05419ee5dcc9a7b2b2c29a","nonce":"861de820f46b4002387cd2a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"53cd7e213cbb163f64a219afcded7e65c19e6d4eae09c2c682f4543014c0fe790a72bf8184fc8ce14713755680","nonce":"861de820f46b4002387cd2a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"d2326fbc8ec1f15da5da4c69448fe9efeb6636f8b2320460c4e69ca18733e5467d65ec5d08fa1f991e8e2e29df","nonce":"861de820f46b4002387cd2a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"0d04a2887a620b242ddcb5ea7607f502678ac2fea8141d46c12c40909ac18cb59786eca0a60e91c1a6f0db9e8f","nonce":"861de820f46b4002387cd2a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"1c6cff5cfd9faf8f465496a666f06a77ed40025b157cd1e1e85a4c9f85fd10f64fd0ac2bd83aa12539774a7069","nonce":"861de820f46b4002387cd2a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"2fdc7fdc0b9c35149a1ea9fd316e33a2e5c5fd58ad5f11f926f1dde6d3ef2f7699228ea6c880d6cec8a800aa8d","nonce":"861de820f46b4002387cd2a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"5cef28e9fcf2432d31f3cde9d7425be0d465b9c52fd78358da8d05ae8d25677996313006c8ceeb2ae87a3a416d","nonce":"861de820f46b4002387cd25f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"2c4cffe0ba212d0dc807733139c01e6fe5b487bd5f6c3082856495bb4414f87aa8421825542b7f6d2e6fab7824","nonce":"861de820f46b4002387cd25e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"ae1a6f1adbdb7c9a9804d3a27afa242d75f0f784f29989834733c068a186607d14fe45b1aba13e384cfbed51aa","nonce":"861de820f46b4002387cd25d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"953b0a1f1ee3bae9ba830f53a5d71fe7b1ace4646fbfa2daca47cdbd4db81452e7c841dd890ed389c77045b7c8","nonce":"861de820f46b4002387cd25c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"0e23db986a86709dd3529507814169402e94a5e6acf16f89e1585f3fd0ca8445e0272a1949501a740942b163f6","nonce":"861de820f46b4002387cd25b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"4510af5eedbbd28caff012eaa18e7e37811b3a8fcc709522628042ac91e3a530ddbf3a206448239d73ddad4555","nonce":"861de820f46b4002387cd25a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"7962fd6b0b5a3426db06abc9e0500a882ad1b3a8e175acbe36a5212307e0454246fa7aeee5aa3025070c3a2003","nonce":"861de820f46b4002387cd259","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"b60e947f0704501efd11b961880d94a9fb09907c7e62702ab0efcb9b5a1ccdabac6c41cdca194e2068af93ae73","nonce":"861de820f46b4002387cd258","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"dfffb9d3aab9b3a9ef0cbc870282d6c430f933f0fe60e4dcd303517a9583833ea1395dc4473a979bbfeda4606a","nonce":"861de820f46b4002387cd257","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"54faa63692bad0af89b24e65fa6aca3f3cb964a7357982fe3c79e971190d2eb79593e4f243427f484e2f2c9530","nonce":"861de820f46b4002387cd256","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"776865e10f322a21b8dfd1d15d8392e4bb2b23e22d0bfc61ef16e86b34f41c9fc78ff5ff7352a084efc1c20f50","nonce":"861de820f46b4002387cd255","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"2bfe707e3c8d5e6ca192d925f0cf830c5df13e9db72b0389925337eca570f58a04fe138829258f39470234262a","nonce":"861de820f46b4002387cd254","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"f506e7ed09bbf53d99f5e86b35f11937314c67676ea77aff5e25673845cee1afcb99b07d18e846f4d611c69102","nonce":"861de820f46b4002387cd253","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"1d3304c16e1349e34adbdc3fc2c08959b05b84de7f00557305a099af2ca9615aba9e03d82a1e3a68b9265c254d","nonce":"861de820f46b4002387cd252","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"2c1dc447b2a9812cc42d289e9c64faddd8153386eda5b1c558d5ccd6ddd69a53dcd997ec3b4a525be910ca6588","nonce":"861de820f46b4002387cd251","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"f90ffa3cd757291eff3ed8a1720140adebf0ad8955db810ed0fc11c7cfebabae947d6d01bfe205e6bec375234f","nonce":"861de820f46b4002387cd250","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"a8efbf4fe87cea71aaa23fa4c9363f44788bd1eb5c558b00d942a0afea28e790aa6aaf5d0d532da31d422e2f57","nonce":"861de820f46b4002387cd24f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"0410c9ef89d14bbdb530fb679b41677030b20c4ab1c4ffe984b39788a37a2a98679364161db937468186406874","nonce":"861de820f46b4002387cd24e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"998d2600e9676cafecbc00218f26d8186d24a1d8e8a1d496ca6a4baed883d05ea7208f05a4272074663001fb8d","nonce":"861de820f46b4002387cd24d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"52eb6fe4ddad4a350f8f951539f069d3c684b689d591ae94c17771edd81ab8d7f627a5ed393edfb59b6f99a967","nonce":"861de820f46b4002387cd24c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"e9255e747310992563daa7656277ee6245441980cb53e6c81e27cf1a21a1537535954f3b7d6bf2e8082ff7f506","nonce":"861de820f46b4002387cd24b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"a9b18a115b5dcb754f4350e9cec8370de5c65ccb0418d9f182e61c23818fe81ba779dc2593e56cb8113cf5cfde","nonce":"861de820f46b4002387cd24a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"9012f536380d2121130bacf711e471797af84034826267b912198e2028482ba83ba691c4abdafd0b4a29c54900","nonce":"861de820f46b4002387cd249","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"93e8e973463def1b5c9834ad6d17e5839e930ba96a37f38964ebf96617c60ab28ba266ba531d76114ba9455cb3","nonce":"861de820f46b4002387cd248","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"917b7e7b178f4fcbfa3ebd5795833c1a0981eda7ef320c6031fdce3e376d8cdf3f903419cb9bce25712b9dcf66","nonce":"861de820f46b4002387cd247","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"b1bbd2a44504fd5b6767e0feae2f02f082e96c0af834e52333ecd3c64c260209be7b8fbb9d9b2e0cdca3d3ef0b","nonce":"861de820f46b4002387cd246","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"90b6de726f4a155eabdcaaf5625634ce7939d50530b826f335551887c25393f62723b7824a9edc765cef478bcd","nonce":"861de820f46b4002387cd245","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"193eb8c6a371bb5dbdff2feb79f57921972edddda7279a2c3a953b0450814c1ef9ab6e9f284f8449c23c30a35a","nonce":"861de820f46b4002387cd244","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"b562d4472f452fa06ccb93dd079ce8875fed9c702ea63391f6d278f410cc4ad457f861df603ab16ba6fe086f16","nonce":"861de820f46b4002387cd243","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"ffbe5f503039693063b8bfd9ecbfa12b157f6ca8c919499501cc5c5ce78b7bd12c88b6a2e99350f75c5ac67990","nonce":"861de820f46b4002387cd242","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"bd04f3b1de726e62413e5e85be288be4626f232f0cacca1dcedba0dad9174c3f3f5de9a1528757f2db2c52051b","nonce":"861de820f46b4002387cd241","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"63c413591274fb55e941638683829ae8da60cd75c35bc1f37c83338fa305cf31b27474f498ebbfa7b1dc2d7bc3","nonce":"861de820f46b4002387cd240","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"dc20da10f4ba86b2f9298c6e923ac79644f74c9dded93300ef63ab721fbdfb712942010abbacb8bff158b5eb41","nonce":"861de820f46b4002387cd27f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"2fb4484546371990f26ee1b7e4162fca47864dca5ae369945d6cad100b229387a2219bb3c94ffc7edefe492d05","nonce":"861de820f46b4002387cd27e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"deef0782a4bba4ff604af492d5a3ea73cf5a21e8123c84de281471fd4ca527697937e75f6a9eacb237be90a9d5","nonce":"861de820f46b4002387cd27d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"f3bfeebe5302acce534592752b91f614d00eee3bcbd126cd34b912f8085dae0583fb2f3ccad38580369053e0f4","nonce":"861de820f46b4002387cd27c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"e3d54c5a414ee4a7d0f3761d542bdadf55947d93cf2ebb29dba990ca41915b9f0a8ab84714523655885f44b442","nonce":"861de820f46b4002387cd27b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"9a71f6d86e3c06e046cab60ba7ddd7e8f8b03004fc5349f94a5f6b6ad459354f3bc3750bb5651f10afd76491a0","nonce":"861de820f46b4002387cd27a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"acf20445c88add034851bc28093bcaface844a3675cf535d41d183caf05611c63e625bce73033d61e5cf97657a","nonce":"861de820f46b4002387cd279","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"abc682e7270ff4534be2eade3ed97d864850c3b01a1bde42bdd13849ae7ac1ad27e3e0d8d78e79a8b4c1ac12ce","nonce":"861de820f46b4002387cd278","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"5e4e1bfe3b1c7bf65b5e999d8fa7b373f87ff1c6d294098c55820c47320f3df0f35f338d538ea6b199559932be","nonce":"861de820f46b4002387cd277","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"8dc7bde16987100e2a6593c8aa77f676d976b257f8c58f83efebef5927d2b86760b02515a827550508debcde00","nonce":"861de820f46b4002387cd276","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"60afbaf499b9a0f1775d3890f0c600e1f4936e3c6eefb824773cc45845e76fa36133cbefb1609ccf493fb4d8a6","nonce":"861de820f46b4002387cd275","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"654a345166d38c2a1d6467cd977945a8973a566963beb9fd18bfd13c5f06e4d73b31005b4aab63c638535e4522","nonce":"861de820f46b4002387cd274","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"9cd894e4e1a49b5e158902bd4be00d218d5f925ad0fee28ee3491024022e6c07c1c7215ecad99507c94edc68fc","nonce":"861de820f46b4002387cd273","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"5ec1769343824abf28372e034dd52a095cf548c7c78dfb23432bc0e5445c9e74667a0e986943bc45d2cf07c934","nonce":"861de820f46b4002387cd272","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"a300039d95fadad045411596ac4244e025d0b0fff07d4cc40fa49711b9c3d46a1487ed59b93deedd908e3ee38d","nonce":"861de820f46b4002387cd271","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"164e63d739ea6ba790fa1e2d9bfc296dafcb589920ef1320c1cd184e2d6b14f2d16c743a2506a07cfb2069a151","nonce":"861de820f46b4002387cd270","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"da3dace98a9c3353aaa7fb2ab3ff2b407874becbd90a8ac9e8a02965283c9f2e712186efe714e4171f32ad2341","nonce":"861de820f46b4002387cd26f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"bd1d5ca9f2c9a2ac91b873ceeb309db870354719fe8203f9fe63d184fcb5de273c47b2b2556a5596e6193a0978","nonce":"861de820f46b4002387cd26e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"7d59366c528efa1c3591100e78907fe42f57537a0c60260032e45a6631fa5e9ea6b7d74fff9961e858371cb975","nonce":"861de820f46b4002387cd26d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"1d8ff4f7287dd341de129915eaa86038c22bd692476aee52f0fb62399c0b5bcd82f42278c3c999c3a0490908ec","nonce":"861de820f46b4002387cd26c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"d2b6260b12c27f41b2f2b382139a558cec1c4a456792cec5f35a8b5aea7df6c1719af8fe5027156676ec307889","nonce":"861de820f46b4002387cd26b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"cde7998e601c1af62856bdd953602ccdf624fb1d56b0ea31402ee62710539b9f8701e2ea4611b2e4f97ee06016","nonce":"861de820f46b4002387cd26a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"a9078d88fa5e5f5977df62abd3f07672a7e2fdfe7b4dcc20ffad6b0fe35389c5e20d75cd75fd6ddf443a058508","nonce":"861de820f46b4002387cd269","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"bd08d4fe34a54526b49161d261d82c0fcf627bb56280fa4af1225e87d25a7d54d04441451d1bf52b936ac70443","nonce":"861de820f46b4002387cd268","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"e86903bdb0ea395b94fb0b612a5a27b181b7a2caec340657a857235bc132d28173b6eed36f06716054775e03eb","nonce":"861de820f46b4002387cd267","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"85d982083be04bb0304761175e2d1e3d142e3e8ca7e613ee51a844bf28cb4aa87819a06847269872c189e78bf1","nonce":"861de820f46b4002387cd266","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"ca1acdc04c798fd178017d4e21a0d64119f9b37514b13cf40630d19750a065d7587afd0b992aa5f946cb8c5863","nonce":"861de820f46b4002387cd265","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"fa9a99133bfc172df6aa638fd3fdd11af4b6811d86725e065ec6958d531b51fba53a2db843688348438d61d1dd","nonce":"861de820f46b4002387cd264","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"7dfb15e650d461201ee868bf63e18565ad331b7b46b250510310da8843c9d85b72bd3c63b80724a01353e109a5","nonce":"861de820f46b4002387cd263","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"c13ec260c91bd054111bc218c31c0e4cf63fe6879a65b2b32b5c87b4ae9b08ecbe43754ddede82cac85a2406f6","nonce":"861de820f46b4002387cd262","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"778573b9e4cb28eac326d088593c195133b9aa3cbc3b5be6497de7927d676809e2a93949d6d27bcdc9c47ea59e","nonce":"861de820f46b4002387cd261","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"3473c82a30302d54d0f28c44647420ac5404ceaca9ea7e3b1af39a97b41a99e17f4bedcc0c51aecaa62c402776","nonce":"861de820f46b4002387cd260","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"7e13e1ac8e9dc2fcabfbbb326df300bb5b65c99ea458dc7a7ef53b14d03a7b588004078120312a673919b6651a","nonce":"861de820f46b4002387cd21f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"28ca8dfded8928bf98b076741b83362bc0d692acf662c582ff7e23ada36cfbd671ab2ba59d526aa59155371eaa","nonce":"861de820f46b4002387cd21e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"1fd5777c285dbf4e23573613208198495234d0f71ed60468c6b32d83b9f4202bba01a625932f96b36e0ba2e5fd","nonce":"861de820f46b4002387cd21d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"f07cec75fcc0930aa384abc07634ff89a637ac111d5cd67636d7faf94c2fe2f6600eeb97f1da82de2c2a7302e5","nonce":"861de820f46b4002387cd21c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"de0f94915ecbc4f5c9a8fa94b6b1aa4816e29b1a95791eb39c14c86b78c7cfc8e4a6f4913d134168fb70360a52","nonce":"861de820f46b4002387cd21b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"3754f7a28f63093f4f7be5409a66bc29c56e7b299f8f425c813582cd8ccc44cfb6824b731a44be8a9057ed1b7b","nonce":"861de820f46b4002387cd21a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"6952f25b90103a60b72dc264f3b5690319ff6d2b9d384878723eb58e0fbb25381eb22488efd07326e0bd199fc3","nonce":"861de820f46b4002387cd219","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"75ff94889b85130193fc8d4704c23fcbaff1b0eda227892c1e3a8b46e141c51a5f241ae6d07b67b2c27141468a","nonce":"861de820f46b4002387cd218","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"62ced93765fb525b097dda2d9ed73209c9354092c3ea1f61afb2a9116089f5d6ba51f72e850be7da9db4989c59","nonce":"861de820f46b4002387cd217","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"29066909ba3674f7a1127dc62f9d88df3406461ae4ae402a8280e344254c810d65679ab5dd101e3003d7f88886","nonce":"861de820f46b4002387cd216","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"d16cfbbc758d2eb5f19a404b0e3ce0e74af0e1dc06d38cc0329624b344b69ae9dbaf68de3183cc61808877dde2","nonce":"861de820f46b4002387cd215","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"97e4322325055f79289a899ea87080e66960ebb4295a2b1ecb00b3cc466bc00f094a96993113daff313425c17d","nonce":"861de820f46b4002387cd214","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"939ff877dc9b815b92241cef509e24bfd8abef8ea7e556c12508a25bb98d05c17b0e57ca81afa29e4fbc341aee","nonce":"861de820f46b4002387cd213","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"a1a7b19aa5e831a6264b0eae5b0a637f2432e56ebb621553f65930fd7140863c34496390de64c8964a54b4fa81","nonce":"861de820f46b4002387cd212","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"12b9ce8bad6fce43168d15024fea76a52cc6054525fe661dd76e07e2b0609c7e06ec49e7ba8f12c4c0506f3f37","nonce":"861de820f46b4002387cd211","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"d76db3022a414dadc05c4d4f673f1d551f34b6ae68dbf124f5e625792d97e7b93ffa4df3ec817bc64df0257ccf","nonce":"861de820f46b4002387cd210","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"d1a61ede3bb0ed878538a54e2877e322f437f57b0594e7d93b15f37e4fa7abc8dcabf31d34e8ee7a6a58f0bab2","nonce":"861de820f46b4002387cd20f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"37ff6b7f0eb6a577f2fb4af46a280d37cbd0366546af3ea077e7db3177421e46770ded4be71399324cc8839738","nonce":"861de820f46b4002387cd20e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"a5bba1a30d1bc870c8ce3d027a73c4541acd4013dd0e16f05931028d9745886676320d494a809644ff805c6326","nonce":"861de820f46b4002387cd20d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"d56ee1d6bf1073c9121855c498d773c106516fa26cae372e7f87860c785f2203276f6f3f9498bc9ea32dd3a0de","nonce":"861de820f46b4002387cd20c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"cf9fd7f3b99d0f1ddfdb69449d180fa8b804f39c715feb4c2075a3b79fe35d6a864375bf9011ade72f80bd9a33","nonce":"861de820f46b4002387cd20b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"dd718ad477f48f7f459623dee7ffcb845b390eb9d222a7dd3d5c931945a9fd4e12022195fa8f759c1f33166d8d","nonce":"861de820f46b4002387cd20a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"6b84aff45540554b332ba97617e77d6d1d2bce0dc2d0cb90b47d894e8669d00b16131605f5cd6fb32a5667be1f","nonce":"861de820f46b4002387cd209","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"9d63ee094c14d0e20859ed1524e80b957b668ab2837d212c1772c6a746616e680ecc7572dd29c1a8da59fde980","nonce":"861de820f46b4002387cd208","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"a2da91f46559437822af19a7c49c00f56a5d93eae0fcf05534bb3ed1850a53f4601c979053367591c57d4096ae","nonce":"861de820f46b4002387cd207","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"2c9ff53e2bc428b6668a5fbbcebe53650080a6eda16ce549375ea0bf31dbfededc7f2e12488c66dbe7bd461d12","nonce":"861de820f46b4002387cd206","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"f17ca9bfe7ae48a10e48d01f676108798a08cbd2b8412224fed5623cb96b9590c44d14ea54413ba92f0a36eb06","nonce":"861de820f46b4002387cd205","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"7923616b6a589f13d01ed75cf2d8972470dc19043997dfcc97364a6cde10052a29caf8ecfc20fd9d2a26eac00b","nonce":"861de820f46b4002387cd204","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"fa5f7206ac717119aacc28a4535618f3643b0ccba0715c8cc98c0b8d19194feee22c641140776027d42180bcff","nonce":"861de820f46b4002387cd203","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"d6cba6c67ff67c17da244831d5bfd90743d21a258fe635a512491088739db072dca51b1cf707834244b001aa63","nonce":"861de820f46b4002387cd202","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"d22af4b69ba076a30e400fb0a367bddb30e7c53befb966006e9e66231f359d5751555f2baa9a13ee573e3d0543","nonce":"861de820f46b4002387cd201","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"db51a274c5d64afc845d5371191e0d3222555bd082cecff01444d2c5df7bedb36fd0378b32dccb2ffa4deb6e55","nonce":"861de820f46b4002387cd200","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"df44319bb49f2dc3700101ce25ad28948bb7011da5ba538b633c66777c0bb971e7fcc14143f984419a7a525731","nonce":"861de820f46b4002387cd23f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"405bca94c205bac9e5adca0b921977903e33ee02a85a75a2c9125778ebfb87a36f78a6ee42e3ae07f3248a0263","nonce":"861de820f46b4002387cd23e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"d2f51392223d3b9d9debf3fa4f378c3130be079d30b3fe875b30cd13ece11ed0ca8cdeca1bd2d09bef6b938f2f","nonce":"861de820f46b4002387cd23d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"fbec98d69cf05a93fe7bc96e144954f436ff4127288179d2351fb6f1de2301d84d843e4651a0693007ee2c7b8b","nonce":"861de820f46b4002387cd23c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"7459882af16bc3e6e8f9c54b1d396c24c0f4d3dcfe90d89816d237bb5e1adf27341d465cd514341fe685582ee2","nonce":"861de820f46b4002387cd23b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"a95f59090bd0a1051987eeb6bd52f99b2fcce9f72173af9c690256ee536df803f1bd8307eef800bcf43fcd7653","nonce":"861de820f46b4002387cd23a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"6d9a68d524c5dd8f92708b2b0ff760e3edb6050d532942eebdd8f86b5076e9f4d8a96052fdab0c4affa82123dc","nonce":"861de820f46b4002387cd239","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"1717b60158f01f256222e7f004e661a190e0435d3cdf640b23c8a73188c24ae7d588a2b9538aca370dd95da19f","nonce":"861de820f46b4002387cd238","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"5b536c76b9e71d686c42731253c9f89221c0dfcfd2b655a4f2648ad01a004a14eeedb74059b4cc1405c55dcca9","nonce":"861de820f46b4002387cd237","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"5c4625db13111c6d050b60df5d58cf6397a490726f7cbf5359864f8e5533a93211a5b3b8f72cd629e89a8019c7","nonce":"861de820f46b4002387cd236","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"4701aa96e19911f6a3d933ddfb3789d67bc8594e269a69d3377b4c20dbeb9860801225270ff8af8d2a668ac104","nonce":"861de820f46b4002387cd235","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"d7aa89037fa6744ed5e8f54c25b0cc61680490b198f7760c6f2f150dca4022aee4cfc402640327a0537a7942d0","nonce":"861de820f46b4002387cd234","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"6872de55975e968aa15597d78d5a53ca990b7bf173b69d5f5aaa8e0b0ee4654337ea180a392a2d0b8429772861","nonce":"861de820f46b4002387cd233","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"c88e178ea4a569a01c4e693047d2d963dbdce188c98af401630e26c5a28c71b4b7a34e6a6360016deb274a26da","nonce":"861de820f46b4002387cd232","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"494522881482d671b9f094c004a56f7ad9c02a92699eb236f52cf8b7cd51b25e95e01ec5216f5e855fbf6d5932","nonce":"861de820f46b4002387cd231","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"5e773252120a8a797eecf937c18c0701bd327a1aa5cdc9b372bc620bfbee3086b1bc66995cb3b3068f8f9a3305","nonce":"861de820f46b4002387cd230","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"71a9f805522c56ae93c718d61a3270fd4fa03c2cbbc0e78527f605032a7a773c8184029a4a15bbf72fa1d6d67d","nonce":"861de820f46b4002387cd22f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"91d520397ded5440757996ea609cea21472507ac0ac6829fc216e80310c3d059e2c153f7122ca53099c2921162","nonce":"861de820f46b4002387cd22e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"ed10f01429c05e6aedbc7f8f30309da39f0d16aeb8fd94015bc34c2874e1c008954feb6e80a404caf312497c04","nonce":"861de820f46b4002387cd22d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"f12163db02a28647e8b25971676effd4d4626a74dfcc0609cd44a6836494587587c8811d7de011329dc5127736","nonce":"861de820f46b4002387cd22c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"c104276d96bebeb12e0a773eb85ddeb80663e7ae556d9b1fd3f7956a54dd40826a2a57950e36c61153a2ab1bff","nonce":"861de820f46b4002387cd22b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"430ddf3eb2af837dacfa8170c8802ccd1cfe4063640e0607f939ebe6c2df2300a469f3098588de15093c9c6b28","nonce":"861de820f46b4002387cd22a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"5abe15a51d98d80bf4ae02a4dfadc5df2173b1cabea2a6fbb401a7b53b6fb0ac1ed0e199051e758b731de82ae3","nonce":"861de820f46b4002387cd229","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"93a88ad6b30ee699cd10ad9726058e1bdd46527cfaa52ea80464b5aca924d9957b3fc29ede8c7b00d1ce110b9e","nonce":"861de820f46b4002387cd228","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"6d0d042f558302c92d8f3b18235ce35b5cc148c8f300a8c84b38e6bf8174d9c7ed9cf6c5d348358b14b0c8f03c","nonce":"861de820f46b4002387cd227","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"05d4486ebd25d63009a9d83fa29ea9be906363e5737635fc67cceaafe7616533dbe86e21f41831658c97597f14","nonce":"861de820f46b4002387cd226","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"9b77ec71009633cefa149f6c11361d5dd604125fa6d8d21c3d4e41f0fb567fed1f3309ea2b1a8f7be8a5378984","nonce":"861de820f46b4002387cd225","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"df02595feedf01e88dee5a630c8565d0037599fe8d960a9ff3b6eb84e0570a06cd5f437dc0fdb1c9caca7116d3","nonce":"861de820f46b4002387cd224","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"ffdc44116f997603048b217988fd1da98fbe1cab2d84cd211d8d5564fd6a751b3824ff96d5c071be374b7c3107","nonce":"861de820f46b4002387cd223","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"37359cdc6edbb2e077866b4b662fa5f4317d2c01c43d6283fd1c72e4f8321b8bd8ce7bdd349ec9fa27b93f816b","nonce":"861de820f46b4002387cd222","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"738c058a082a4f9f72ac3731d0da25e1d57f5c2b5de084ca881bf1aa8442cfa3c617a5e3d1aa250e220e45f631","nonce":"861de820f46b4002387cd221","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"2bd78fb4c348711ad3ed2c0d2d48b351abaa4e2f7d4f5f6a2f7f8eabc83cf55a2d4e04a070912e8a1291280d9b","nonce":"861de820f46b4002387cd220","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"fcf074430b63451401a7d69e14fdc83c5d4e8c29add46af2d6772d3d65c777836df8822fa0e13d05569c498797","nonce":"861de820f46b4002387cd3df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"fed322b0800c55ac6d9d33dba6c67ae15d416bb939e5958a1bf4d76b31e76a95"},{"exporter_context":"00","L":32,"exported_value":"ee178f69b07e341f6486c326e3f1d988daf95d3626717ee85ccd63d0bebd9c14"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"e29c03881ed61d231501cdd7c65d6379bbb201ca0880f731b8282cebcbbde55a"}]},{"mode":0,"kem_id":18,"kdf_id":3,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"65de09cea209db882b3300be0c0151a01aea07f07e881f1bec6e02e00227f4a6edf86d3962af2a006d7d2b12279cd87b395b97fc9de5da516122029657dbcde79a9f","ikmE":"5650befec686e40ddb7844031f7744531289e36c29b8a2e9c1fa890900ffb5504bd947295147c9cc9608c4427e269677eeae8ad8a71904c26e77ea0da81aa8db008c","skRm":"0119fb0643a0fe553642ba02dd79cce9c8fbfd6dd0776ef9d4aca3f63e687b29eceeb7b163aee15a500e431a0cce7988b36c9c80d77d5a8894b3086f46ba76867e48","skEm":"00bc36e462d997aba177843c4c977f0bc8f03ddb9c903a13bdf800a3d1e487374194a89e5280e0f0f27a25b1d86573a0cbc518aa2d747e517cd77289b92c7142d94e","pkRm":"0401a94469f44ab81a53648a4f6bffa9e97948574895790ef22b5c98354e2aa4b13057a4955522e6fb685e0d46f94fb23fe5e7e3cce032f6560d70fcb32c8fc16a626a0052c6f4c7f3e0541a76e68707ebe5b2d765ca08cd85b139a5d6e78a9175d2690ff55d5b91a8ca4ab03970ffc61dbbae5327aa730d489dbda240eef64d86153967c3","pkEm":"0401c46a4623b54a99e813e66a776e0fcb05452ce84003a02f5927659751dbed9cde7da76c2e22141b32f1f41372495314324d012f980022f95343274596851456c18d001834f04c5d6545729cc63b6e990f7e2326a69586bb363a68d49a88ea84245879589b14ede4966b1fbf91106f17fb272bdc5ad96010bc9d7d22cc6a9453f89ef793","enc":"0401c46a4623b54a99e813e66a776e0fcb05452ce84003a02f5927659751dbed9cde7da76c2e22141b32f1f41372495314324d012f980022f95343274596851456c18d001834f04c5d6545729cc63b6e990f7e2326a69586bb363a68d49a88ea84245879589b14ede4966b1fbf91106f17fb272bdc5ad96010bc9d7d22cc6a9453f89ef793","shared_secret":"6fcf0789b2caa0930f287409f954fcc22bcc9da990a14d5859be797776b5a8a9e79f32e8e93dcc4aef6a73db9ec7c4129adb6fd8e9f58db28c10354e1b777205","key_schedule_context":"00cb1fc46c5aa4127c3739c63e1b145be49aa816a560fadbe8512f79ca62004b8b45ca75ad4274b4c03e9dbab8ac3a0324a800d89777115638ce77c92eee21a767cdd87b0281e692a99982979c39757078bd10f16f51a609804bec7ea73e6df85d53e5b21081fb76ca400113c07723eeb59281dc77544497e8f8a683106eca75ea","secret":"278c05c6e52b619cb0e7d3ceaff2fc0f503cbd6a339225bcb1596f5787d2769088035ade2dacc9da8aad3dae7d4da0381b8ca642ee894b7ab844190d36373b2c","key":"36a382a0ea60efd4140596303c053be9","base_nonce":"8c88433511a83e672706c878","exporter_secret":"52d6c5ca50039386143557f8c5b4484c049d54c4c4d973628c2488ca8f84d3dc24e0757b12865b59c68ffea0d0a9393d663418919da9ebf712f02c395b77c58b","encryptions":[{"aad":"436f756e742d30","ciphertext":"80cbe025d0a5ed9f5c06e7ca1066e0f79c34c48a85ef55c3f70d433a1063bdd79a1787643c6857e26982c04a2c","nonce":"8c88433511a83e672706c878","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"f9a25c9edc4228eb084b303804132bc16b9a76f1c1a5ff8c1723a2a0b511cf7bde453fc42fcd0f835496ec3f5f","nonce":"8c88433511a83e672706c879","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"67abc9786d0cbacb20e13f794b30659abbdcc7f6a77bdb5b1b92c382a47fa21e529f3e120ea78fbc9974950c10","nonce":"8c88433511a83e672706c87a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"c5bdbf5eba07da202c3240a019dc66d564d0c2d8b406076bb07bae62c4beca5f7165270484e40435851f04472b","nonce":"8c88433511a83e672706c87b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"c51a4216e0f11d0fa89a6a8836fe32d5b88abf91cfa99d0ed4ba1ecad83524a0dfc488fd131aa50f0bb185c637","nonce":"8c88433511a83e672706c87c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"8a24087dcbdde892509036818dab3ace16dbdced3168524578ced1909b7aef5ac908c7f9fe78440ac54b534aba","nonce":"8c88433511a83e672706c87d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"a26c1259e888b51f5b894dd22e7e7ab20d8ea42da6888b800cc58a03d9720fc2d0a105aad6bf8183b599e14f65","nonce":"8c88433511a83e672706c87e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"f256d627806b50a9ae24df4df52443dc162d81799906b0fc86f7a4f010efb4be0d5a552e4e59150341c2a97013","nonce":"8c88433511a83e672706c87f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"d69505115c3983f74c2e7d08ba1c2edef554fba6d56da48663d358c00b01d895562c083ad37af511060885f340","nonce":"8c88433511a83e672706c870","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"d4d86be6e9e64bfd1767d138986146cccff44375386b5a81f3e0d6101821a8e6eed4e68207cb2ee594db0060be","nonce":"8c88433511a83e672706c871","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"add803a882445378278c64c4af2de4bfe43c74ffc8740c984dbc5bbdf05c7f5bd17061d0662cc2840be8e02a7a","nonce":"8c88433511a83e672706c872","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"504d97122dba8e742bad7d5b783aad9fd39110b34c0fcad1cc87aa791c9585f6b3759d4a35d3d5feea5a715baf","nonce":"8c88433511a83e672706c873","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"5b6c7a10d41ebe4d76f173e8589137ba78ced792824dc47940eed0791384b8f6c4c4ae4ca2c8262d4232271af7","nonce":"8c88433511a83e672706c874","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"19ae102664e5f60f6e181ef8c2ef8ea66e6867301cfa7f06ab9f328f813bad88b8884a7145847790063506de90","nonce":"8c88433511a83e672706c875","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"f17ade8d32e7e37267e6cf335feaddff8e40a87cfac8f6cf054dcde31449cb061b0a603988ae1c7057807557de","nonce":"8c88433511a83e672706c876","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"74b13857567b746d232688ef1ccafeaa7bc602c2f3bc2bfb85f5e8a1c812e39b30209b9da750038ef1a10d043b","nonce":"8c88433511a83e672706c877","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"02690a058114b171c089fa5f8b26f5e2360315ee98d8844868d35af9ed99d206528faff9a72c8dadda6074e226","nonce":"8c88433511a83e672706c868","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"8f3b869f9a0b234a10f5f81d8bce646491204ef5431e76b9f31727b135c7669492e4940c37de1491f36d3beced","nonce":"8c88433511a83e672706c869","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"ef66f0400666be56318a5120f54d053896263776e36b4ee2db7bc1cbee07b93373e0bea4f32c63c874813850f2","nonce":"8c88433511a83e672706c86a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"6757676535a2997a6b5281ec52da94bd263d86aba781a46ecb5684dd6ba09383b8aad10853d6af4e6d6808c9fe","nonce":"8c88433511a83e672706c86b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"578d163ea55e63120032358d4dbc005b1b70d28024558831a23d6b9e39292d071ec012b9a2254f7a4b9cd3c687","nonce":"8c88433511a83e672706c86c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"a3e7ad9703406d3de1a6711fac25ed0a00ee9d4fbe528475ec8b5617c790abf9a911cb60b1eee5b576cce08a93","nonce":"8c88433511a83e672706c86d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"9a8e809015c1343568c1002a233d1dbb9663ba92194d8b652c90fdbd689ecfc859c1cf56742d9b266f5b139187","nonce":"8c88433511a83e672706c86e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"1753fce98b3696f348f6a6c9dfa178ce75f9a82882debe787ca2db3088a835ae0785fa5b4781249520936eb290","nonce":"8c88433511a83e672706c86f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"aa210e2f4a57cf020304fa5461154a58f8c7c7a1224228130bbc184424e14a7e477c0d7cd2c9d2b3634ed752fb","nonce":"8c88433511a83e672706c860","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"52159e610789d1c5b999d50eb34ce424c5bf38b41bbd569049e63ec78838a28249fd5b9c0b3cc0f34fb6a171b3","nonce":"8c88433511a83e672706c861","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"e1b5fd214404d5210ff3fec67695ff3b9d63a22b2770dfd454bff8cd9336405b02c23de979a70711e30619ce09","nonce":"8c88433511a83e672706c862","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"eab0b65827ceef774619f51ee1a000f9f019b7067a96c860cd98a55bc20dcef39fe0f3fa517adb7c61051d27c9","nonce":"8c88433511a83e672706c863","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"72fdd56d625fda9313f3eb2ea5af0b0278b60eebc401896911bf709bd711acabc0d436a4b75669f02fd6d958a3","nonce":"8c88433511a83e672706c864","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"15199a8eaf2ad890c2909f7fe0c896bb6cddcb2a8f77b453b33d5bf551615eb9ec831d47c68f345ce98b107b22","nonce":"8c88433511a83e672706c865","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"34243fb8d9c60b2fb101d66816be59de32894f18b8b04d6e135796b97277f4955f6b3e1890d4980d6fee1e52df","nonce":"8c88433511a83e672706c866","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"a01aa03b8969da8e22f4f9db77c5173a3ca72cd5daf9df118b86d7abe6149ef9b9616510656895ee7ede02989a","nonce":"8c88433511a83e672706c867","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"0de0437de01269589a0c53546a554de5f8baef3bd8b575f76442a4ad8c24f071c4a801f14f3bc68f416cfdd58d","nonce":"8c88433511a83e672706c858","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"502efdbbded311be56d817b7ecf50bae90b0242b4295a3cbed87ea5212e0a0eafd72818ff2ec4a465d0e44a6a3","nonce":"8c88433511a83e672706c859","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"b6e825ef2673db9eddec5090d3a11b72cad35e35396a4698ca9a330b6e4ec7d6f2f39c41a3eb66917d2a48fb15","nonce":"8c88433511a83e672706c85a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"f145649088fa0259259187b5c99b56c90182afe967dc47d9c6ed443fc5c25f5c595675e1d9e4c7a6096052d3fb","nonce":"8c88433511a83e672706c85b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"2872718fe15d07ad7cf88f8c3c72940b272db6860920fa85b8437e10ceb081cee7b105e21ecfb265aa6456236d","nonce":"8c88433511a83e672706c85c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"7ec5a72570660a5d51b966e72a94f0029cc73f1fed159fa19742d63eed4f71c186b91abaa03a7447c58fddec6f","nonce":"8c88433511a83e672706c85d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"83a36bc2ca17d1034bcb95575454402238be5c9236d177c5fdf9d3dfd5d26510cb8ca622c769fd96e0f9fee460","nonce":"8c88433511a83e672706c85e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"d72736193c0fd1c197065eee1520fd4d68de5e41029acc00f52eaf1d50d7347999c46a4f5bf298c2cfa2672308","nonce":"8c88433511a83e672706c85f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"3de56491852a4bbc99596559e662158ec1827b1567efed5b8d8e9d6a6393002bf533fcc0cea95b4fc1bebf2368","nonce":"8c88433511a83e672706c850","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"fa95bdd4cf1b31ad0ce830e14a5ff90fbd5e6a960c94f940ef796bc629a900e4bd34939883d93c18b32afdae97","nonce":"8c88433511a83e672706c851","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"3e262650f279874c6700e69e2ebd508d641d9d503a387ccf88fd97285c2337699ef9481232f84d1edd19964768","nonce":"8c88433511a83e672706c852","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"c31f68be9a9683a6b609d12ce5282b6e4dcfd234c35b38a22a57c3485bf2b4615c77bfae5dc595ce224ebe5267","nonce":"8c88433511a83e672706c853","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"ac1df82e536014517a753dbf8d52fbb88878f420142b2ab6ffb9686a5cf2acdeefc9a0ffff983d22f193910d15","nonce":"8c88433511a83e672706c854","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"191649868955ede2cc3ee20a3066639f7f8fb7ffd9e3e5622a11a995fcefae8b60d202bbd3bfad59d9a9f5d3c2","nonce":"8c88433511a83e672706c855","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"4fe0733b472083d991ac85679eb01228e259d603ff283d55fcd3a9ff92a07c1d066f6ec50cc52f2f4b7571b606","nonce":"8c88433511a83e672706c856","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"b50ba6864a53a4ba4f9205be8ab0fa35b36863cf31e79031a73f3e638ae9ab1c091d72edd7c07bca73620e480d","nonce":"8c88433511a83e672706c857","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"5a2bdeb6a02f84bf4113a650694f288a5f8486de452b842140fd5b19d7d3ab789ed1bc66360fffecf17cfc3a85","nonce":"8c88433511a83e672706c848","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"bc15452426dbccfbd79bd1ffc3e56a25365c1329b3fc5b2ab6f058b8df9b830ca6f189c5bb8d16ac837431e219","nonce":"8c88433511a83e672706c849","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"9cc5e415dfc43fa410482d3252a5b2cc86a49bc5ac2ef88b5572d6ac04f1ea7e283bbc2fa83e4e97cde716e084","nonce":"8c88433511a83e672706c84a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"9bd4f351fa1e5ffeb56095f58e3dc5f3a02e0b7ab73ad49d1fe077f7b9d25b8ac55ed3d605476225964122b6ab","nonce":"8c88433511a83e672706c84b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"a02bae635142416445948d7f6446d1192c46771497d21a691ec82a2eabb55eae120c2a277575ef96f9b8e7d23f","nonce":"8c88433511a83e672706c84c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"d9a2c79cc2074832564e282b1902332ce3890fa0cbd329a4923a3d2ae2218ae8393ddb543d9e8b42d9261f5d4a","nonce":"8c88433511a83e672706c84d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"ee6a2efd007894bf1c03b5a408eb33da4dd6c89246e0f5e299baaf37798a50011266dab9baf0662ff4fabfa63c","nonce":"8c88433511a83e672706c84e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"64e289244cd7beac486e56c9435adf5e3b783a981b89c04e5391cde2f1240944d54eac5e8f0c121c87aaac04e1","nonce":"8c88433511a83e672706c84f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"ca1e4702e7f586af02777cf8201e361fba6090b476450bb81c2df819940abebbe921f5a8fb1beea8c3fb09cf8e","nonce":"8c88433511a83e672706c840","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"88b8cdcce4e443bcd6035b25ac16a82c483297b08d54de89e271781a8a5a5214e4a35404042cb6c527276dfe33","nonce":"8c88433511a83e672706c841","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"486136fa2184458a5464f88dad9c727b86ece94d15a7b4da27c6712605e79f6c558f412712f6d9d56650a98b5e","nonce":"8c88433511a83e672706c842","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"7eb941a25f71ec8f1b79e26c00b979cea5f31e90e79d7330af12e4817ee5af2f167de5b7fc76eceef72af2aac8","nonce":"8c88433511a83e672706c843","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"3c4526f997b2dc9131d8160d8e66eb8e51559a9052b494836efb82733e6b83452fd05063a41436c0705f932d7f","nonce":"8c88433511a83e672706c844","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"de933786809be0c99a9eb95fc1d8a5849a237134c9772bd90313b0140c7bf7384997edd41e602d05574d771ed1","nonce":"8c88433511a83e672706c845","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"c6467baa052e8ed14d703e720bcb13bc63dcc98f40e72c65816ef7b2b15eb711c83978e091769596180cba0c9c","nonce":"8c88433511a83e672706c846","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"bf351528fa9b2ab4c70acbd85f37b27774c2fa118adbe206d758a6bb723e581944a7c9daba555239eff6bf3aa6","nonce":"8c88433511a83e672706c847","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"23921cf5b66d8f39a16a1558838a4c0641b21eb958a30f86b6ae3473312190abb79229487e07d46dc41402fb6e","nonce":"8c88433511a83e672706c838","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"418826d8b3570b4615c6bad28906610b85ba4e72970a392f64cc03a022d11cf07279fab3de08f266c5a0ad9890","nonce":"8c88433511a83e672706c839","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"42fc60d63b7863a1ce06f1116915dfab974d52c28dcd9f82d58275e0a2c3976231b1fa3d1018b4dfd0042e47f9","nonce":"8c88433511a83e672706c83a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"a43ba71d890ad6efb3a9c4559941b05c3f9e1b88cd3a44d76c10a86d664db6cd6d3d24514cbe3e7bde79b86420","nonce":"8c88433511a83e672706c83b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"c22146e7b86f56dd9b2d93cfd92ed0e7e3d37677481f6441b56d3ab6dfc5225bc40fc6a91c54455b7fdb5ebc5f","nonce":"8c88433511a83e672706c83c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"9dc1e175863d88055407a55046f04799beca9f9f8ea45cae60cf51e3128d129078399d18c3f5da4d1e6534298a","nonce":"8c88433511a83e672706c83d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"1f67647f8d7b729522903334266f9adc753747db5da0b3aa7c8c9bff49e71c81f3a52c1682bcd2f718897c6ab6","nonce":"8c88433511a83e672706c83e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"557573242546c41553b0f61815bcb28a1e041df872fc00842797f1992dd348d0099807f803e0b24728c697faeb","nonce":"8c88433511a83e672706c83f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"178d19d927b29c278292e05f049f33a76364967b76b731a4a38188ca4032ca9c34012689214ff7fe7b1a7f4cc0","nonce":"8c88433511a83e672706c830","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"2c13a7560ea45c23be09f4c3f8c7c47427ce5c2428125f384353c6e4fe806c4b5dd06066d64ae3c1d9596b99ea","nonce":"8c88433511a83e672706c831","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"0673309e161aa120590c30d9630c9a3f99f41418722f192b9983a4efa4d66b409f1b42d946363ffc511fd8d155","nonce":"8c88433511a83e672706c832","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"37a7443fcb9853d6c85b445d056fc467a34dcd6f93be52d981f2d2792eb1d2ced2a30ac6e1b3ea0f58175c31ab","nonce":"8c88433511a83e672706c833","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"f9ca35adeea69e4e97ec9ce6125047c260eda81c01496a7cdb008b82ce8dded91bddf115a4002942776c48595f","nonce":"8c88433511a83e672706c834","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"1f191b76e8c35b7c869520a7b8801d900615d3e45e2b45dc131f0dfac518813c05499e815fb273d4ec158b904b","nonce":"8c88433511a83e672706c835","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"ace414b7081a6542e9bd87071fbc39365751a1ad4a877e555af0bca84e2a5e907276e3b353aa3cdd8205eab805","nonce":"8c88433511a83e672706c836","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"df5943ec0cb89d0b43bc8f688caff802a66433088c53db31d4c38042a6cf51dd7911650d780c6d6efac7f156f6","nonce":"8c88433511a83e672706c837","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"ad6238c9638279d39057807c2487fe46a923eb956d5fcbb4ec9dbe4cce41a6c819a887a1cdc78c852cf1e01dea","nonce":"8c88433511a83e672706c828","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"e84380b2384d3b01e658f8be123b07ce3d08ccc86620f0ed016f1ef22c78c05aba68314150c3cdfe5418b039aa","nonce":"8c88433511a83e672706c829","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"412f0695545fc6a6b4880262c4edfcb80e3100f52493f36b8c296595bcbb9c43f3034897b92a3736cf6ab2c5cb","nonce":"8c88433511a83e672706c82a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"fa649e44d2d9e2771802be5d163801e9a7562a03064889059ee09b22d705b31e28ac835c4ce30936e85fb20924","nonce":"8c88433511a83e672706c82b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"3a782e25ee94778b6faa2ebfe5f45b48cb3017792d556e8de2df4aa6b50c327463f5dd9d9686f757aeccfcc11e","nonce":"8c88433511a83e672706c82c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"3bb61f0d29b3f92fb08f53857c6e127ae87b208df91158bb73ca1da37a2abdf8ab305178722bfaa76bc6009822","nonce":"8c88433511a83e672706c82d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"8792f3b0db59b2001efda5dee4c411d02afa79c9da008ebaf24b583f785d2098b75c51d4cd4b9c2cff5db8fc80","nonce":"8c88433511a83e672706c82e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"ae50bac5a5e6b4035b2797016d6a95cb2a7e88bdc0c9869eec9aecfa65db5d7dc5d7750242b6a9241d99112b8c","nonce":"8c88433511a83e672706c82f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"f38ffe56f990a08052cb7fe4d42363545761c7e65a20b41c09dc63e466e0854b6e71be84177e19e35a82b7e3fa","nonce":"8c88433511a83e672706c820","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"36ff830f8a318587d626e0e260e1520dcc42eab7c738dfd4e444f0b54d9b8f08582ec1bdc5c88110e12c186a22","nonce":"8c88433511a83e672706c821","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"69d05aa513cde82674efa7432826e379802bd3bdacaf5b48ce03ce2f2a7b0616861daccbdb7233f11b19d26e6f","nonce":"8c88433511a83e672706c822","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"989faf87f64f31aa3a7d4bd9be75647a9cd7be1641973d602adf65df7f4709ffca27e7139e45214ed2af746cec","nonce":"8c88433511a83e672706c823","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"582dbc71d7ea89a86df856b84f632feaedfb809db82fa958c4583166c09783db13f88ea267038e895e529de599","nonce":"8c88433511a83e672706c824","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"b7f629407f4b6c2c407ad31dd6e2c5e42755d9cf24cd447ed63664ff444c4a844d679c7da28892f13bdbc291c6","nonce":"8c88433511a83e672706c825","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"659b37732aa86648426df5729b89b1cb5ad2f9e296f8d47b6e692ecb55f3961c6860f115c8e4b9741a5b2e346b","nonce":"8c88433511a83e672706c826","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"50fc288213c9a695ae3e1a8bcc488bf3791124db16c4d4f90725c2c8fc13f53783aae133eae995f56c41f76cf7","nonce":"8c88433511a83e672706c827","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"e192921d10a74f1dd58f352f1e84522d1f9ea4952a3c64bb9cf727abdb342fb0d0a713268c608c1c38f0367c26","nonce":"8c88433511a83e672706c818","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"6dbb50b2b410a5689bec181416dd832e2b54b6662adcfdd1b53bd8e9c593d2cfbf1af824d4bac80c535f992c0d","nonce":"8c88433511a83e672706c819","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"21541bbb8d74de3035639e9ee32cea910ab7f88144c61702578d4dbc506895baac5d58fdd47c2598b2dcf6a2eb","nonce":"8c88433511a83e672706c81a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"23dfb579222ed7eb0a5436257812d3118d95cf0d0b200cb348fd04361d8470e9b1aca3c258e61eaeae13c1dde7","nonce":"8c88433511a83e672706c81b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"04a15b7c60b818e93769f737208b5235330951d7ba1d6edb96d2f2835331b96a3035714a3a34e8ef02e25b2007","nonce":"8c88433511a83e672706c81c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"0421bef94275f44a64e431c14f9a7ad1bed3b2b521a32ccd5d97f7cb452c49b9f3d2f6a58fb20895cc0bb362c8","nonce":"8c88433511a83e672706c81d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"2358c7dd6b8c5eac70de7e36ac071900dfe8418bc8bd7052fefb9bed44ff1ef723cdf423917f1103c2ac50f0c4","nonce":"8c88433511a83e672706c81e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"e0ad7b4c3f5c670b66f39bdd2f76e2c7b3cb4047e0e1aa348ba29f3aaa90e9caed5f02b7f6ff0f6c39fd24cc62","nonce":"8c88433511a83e672706c81f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"acc837f1a6b6be589f1a5b4c2856ff396b762825cb628bc7cd7ec8461722b67fc13c8ef1a46bfa8e991596c4db","nonce":"8c88433511a83e672706c810","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"4252e4092a99efb8eb0b3decb3f22693660d99ebdbbeab142e9ca5042c1f180fa334bfc436f7ae31f04692d5cb","nonce":"8c88433511a83e672706c811","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"f956e8ce66329e505993a663e57a0ce67bff8cab65b3d3b262c63cd21b2169e27c1ac728beac9ef9ba29e7599d","nonce":"8c88433511a83e672706c812","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"86ab80b7e64f12330062bd7e2773ba4da6529d1f609e6d94fddc9adc6ba34ab1bfd409df00a635f81f59b06df8","nonce":"8c88433511a83e672706c813","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"6784f622a4f64430bd5f8d5ea7eb40e00ca78572b9963d8d6c5852ae506fcd290731d8758438f61a0f59b9a5ad","nonce":"8c88433511a83e672706c814","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"68969e4e26094bc72927a343190f81f2bf015977480193da7598879d378b0b8a695003cb35840fec20be2d8846","nonce":"8c88433511a83e672706c815","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"47b81e4ab7553f2ebf767fbcb76d29cfe1bd87935bea77ff18a7dea853b160784f596d8a9d0eeeeb1f2b03755b","nonce":"8c88433511a83e672706c816","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"ee572116dd7a54532556d3193e4c4224bf502cdfa18963c25d3afb4d22b1e5009949c31eddc03cd7d44d49f03f","nonce":"8c88433511a83e672706c817","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"7ebf12ed6d184c3d2891d444453b0d1be7dc21e7b94dde5a1dbb57bf2aa4eedd9d2f7ebe20bd70f0c6b1ad8251","nonce":"8c88433511a83e672706c808","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"f84aaee0d7aec952d60e06c37d616669f926cb7af8d3fce2137b5c3561bb70b46fb930591130cbfea1cf3a4453","nonce":"8c88433511a83e672706c809","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"1f15d374189d3aecb023cd7d276c3ed1f7dda3015db72bf8813a4e8e5c8ec68a7700ea2318f4209ee5bdfbeaa7","nonce":"8c88433511a83e672706c80a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"89211d6c0af4fb757459d598c75ac68e17052adf539e908bb3f1ed6be1e30f4e03b5f5e83e1466d8c3013a9daa","nonce":"8c88433511a83e672706c80b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"9d7cc576b71ca8cc372708f9e3b8cd7e0d9f2a7e15d40b6cc5cd281189d680f021161831cdcbe7c7596eaab569","nonce":"8c88433511a83e672706c80c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"29b6e38535100726c37ec818da5eb72d413b3e85b922cc2ccbba6d82a1c43e24c0bb93e0d5f70cf924c12da89e","nonce":"8c88433511a83e672706c80d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"6a311826a7d98d3af41d56099d68461b5782019d84a0eba6885604f10a4eb6eddbb024163d2def2a956230354b","nonce":"8c88433511a83e672706c80e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"615a98c9813c43174cbd42365551fd54b2e9232336de68fbb6b0a55ff0ffaa21bd1fc8133977b5cbec412cd34e","nonce":"8c88433511a83e672706c80f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"0fbb4e7b49f85b07e8a44281b6577e556958da06b4bbae8e324db52fe0cd4116454fdd867840ba2b6b7bc0a679","nonce":"8c88433511a83e672706c800","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"0d8d6772c1d1250f287979b7225aa003b53d4054f43c8bb8dd39fa251884491a1412f6ab2a19570bf18877d000","nonce":"8c88433511a83e672706c801","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"16008b432bc6fa59d1cc3c73459da77765d4d518f988068a2dae73158bbf37577b0a70525fe755a27cfdc1ca68","nonce":"8c88433511a83e672706c802","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"151f471b5850ab8309a66e09acab6e06494b80ce544ec0cf0270138ec8736a46850e0c1be3d6dc4b5bbf2cf83c","nonce":"8c88433511a83e672706c803","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"902ca60cdb447c77529947968c2722b6c7a60c0c3fcfd3e9a50d2f62d6e15d5ad8498c3eacb6895be08441f287","nonce":"8c88433511a83e672706c804","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"d2e52aa73fea9510a55f09f052191d570c77c80ad81d058919fb4e52ce9d83aef6bda0c2ffe46fc85dca53aaf0","nonce":"8c88433511a83e672706c805","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"41baf12e41e38cdbd8308ef311afb68561f47c651ef4ac0f9d0bef9106783546d46c10297112a803d4baa7071c","nonce":"8c88433511a83e672706c806","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"67b7af0441da6e379ecbc01872d1a359226d6eca23aa131db36942e3a75285bdb397ac9a4aa15879ea151ad337","nonce":"8c88433511a83e672706c807","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"4104bfd80ad12a516f8aae79abb1647e9e9e1515c847ebc4a1d1d991e2a6625a410ddc817d0083db949c47263e","nonce":"8c88433511a83e672706c8f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"240e91a4cc0baa61306aa8f72e34958f4f6f62845ecfec512cb6cc139f0d034ce76d646d5457dbba80d9570791","nonce":"8c88433511a83e672706c8f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"c8d5b66cbaa52e3ae727eada66fe5845073e498b8351a7da1d5bc66b59f4fa168ad31d848f1b5956724475f1cc","nonce":"8c88433511a83e672706c8fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"b2febd0e9ffbbbcab971d1e8456fd9213158d825c932b76708c3806e383c6f8822bb5a09e7c60ef1d030e62a71","nonce":"8c88433511a83e672706c8fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"53788b321fb60148c937ea828257349791ca3ff460b77aa3efd267faa12edfd407d599d711912602a3eaf70e5b","nonce":"8c88433511a83e672706c8fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"de3af7d7ce4287d9aad04382143fbbd48a40ee52be299d1a2783c393c63e283fee4e3ea10e30767b4672daccf2","nonce":"8c88433511a83e672706c8fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"4c85e69f698bf5da77d8703a32e2faf450e8518113d53dd8dd8820e14c393ca0d5d9c441e362edb2cb4aee2ce5","nonce":"8c88433511a83e672706c8fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"7ad10696e3b1344a8b6ed346951e05a9b342abed2019bf9daaedd7f81ff22038f808ac9cbd49d3131bb21529ad","nonce":"8c88433511a83e672706c8ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"dcb72734eeb9c95f7d7dd2687af246939b38452a82b90bf987cab8673a3a8c114de6b60577ef2f7cca5d883144","nonce":"8c88433511a83e672706c8f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"614f27b063c5ec394bb37322c3a577e1e84b6463f8f0f667528d5b00ad59f42b604bdf5bce52b177e7a82cee99","nonce":"8c88433511a83e672706c8f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"e1cd57f15e547de01f878baf16b83d93e8aeaa649f077f3545f600648369f9da8b80fb6d096ad6c026540dcfb8","nonce":"8c88433511a83e672706c8f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"ed0d405750bb67c6d9da35b9a12d49d8a893a6f977b51ada932c03078e79cc0e33ea7fc4db68cf302eabea42b0","nonce":"8c88433511a83e672706c8f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"76ee81f05e8304c804506f5c7dcb05c0f4a80a282b50d38454eb716d3fae6328b03d9b7758f2f274f5eb652467","nonce":"8c88433511a83e672706c8f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"50364a96238afd340a4c8450633ade63736839f60505768279d51a16e200cd692e65e5c96d5363f009eb6d9cbb","nonce":"8c88433511a83e672706c8f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"a9a1ec1bdfb7d169f0bbb20c25e110b923dbda1809860e21cb516924cadd322a27f746620216c9c53201394e08","nonce":"8c88433511a83e672706c8f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"613377c2adb71b04364a4218c6ae1f633b189cd35d59b5a62340c524d45e73d6b37f9cd001bd9dd693521d7778","nonce":"8c88433511a83e672706c8f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"7b64e6cd319c6c8a1e1270676d8001da17b12c65bbf00e3b07a578d9d641a6c917d8e3023039b8e69e982971ec","nonce":"8c88433511a83e672706c8e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"de337e9284973d3a4d65e3bbd1a585fccb4550d366d51f30f0b4b50ec7d04a4354bdea10adf4f2ccb1b67c3aec","nonce":"8c88433511a83e672706c8e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"c9ca11daf90ed7bf5316240d3d207e6b27a37366dbbe5dfd0447f02216700c50693ae71ce05658dbff53e951fc","nonce":"8c88433511a83e672706c8ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"d73ee61703f98a95a3ffe8947441338164681b95d37c87f6e63311a47306e0b02e9edb397abb600f68b09ff0e4","nonce":"8c88433511a83e672706c8eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"757e1cb18a3c4572fd541d4430943047177438219b8e70e59f496cef1099d8bf1c1485af8ecbfb52625bc82c15","nonce":"8c88433511a83e672706c8ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"4bffaca8c734cdb3db313adcefb79821d9d344355bc1b468cceecaa65c9214da845f86d30deb78bf88ea266df7","nonce":"8c88433511a83e672706c8ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"1f192a69cf14547abf539f44c02f9b28a75a37bf105de5e6cdf936f48e1b35cbfcb24ce695f0651eee8c782572","nonce":"8c88433511a83e672706c8ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"9ae885776b22393df2d7a1869284296079192290b8e51caf0386d7c093c088dec680b392f95cbdedd1289d3f42","nonce":"8c88433511a83e672706c8ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"7f503e2221ef9856cd1ad9a07625973ac48109adcea864158400a4d8e1451c9146bf4feb839087e7988b4cc072","nonce":"8c88433511a83e672706c8e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"40f73e2f486dde227a007ddd69fdc781647390938fb266c397677eaa92f60fbe03f7f3a68d40c46bbec9e9dfca","nonce":"8c88433511a83e672706c8e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"495c3504cf2a2541cfe8bfcc163ec2d76a2b1d013b2d8f9b604e43fabfdde349278ad4982a41ef4a2a67be8e84","nonce":"8c88433511a83e672706c8e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"6612fdccf778545ca1d06e6c2922bd0ad01bf8258fbea57df983db0c4c4645e1319b86c7f3a43ad40f633dc17f","nonce":"8c88433511a83e672706c8e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"ec863cea9d856d9f3b56ee1d9c0cd6a9f152c1f568311b3f099b19b00ccce8092f06648eb8120118e980b75429","nonce":"8c88433511a83e672706c8e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"f6a9f0d5d3de9a65762d9a5eb9aa2ba78d5e32f121ff4e49def4ae8e7ca69bad3f1e063c744729e22684403761","nonce":"8c88433511a83e672706c8e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"2acd093ed1a8279c17216c724052f54af0cd4999933925191fbeae90b172d7a02140d35a98f0e0e6ab9d6abe76","nonce":"8c88433511a83e672706c8e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"d086bd3b96ac92d26fa4b60876d19233808297d1d73e0b59cf9e40106db82ad36189253ecc0354b7f842bff73b","nonce":"8c88433511a83e672706c8e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"18c7eda8235d4d876675c5879e9d74a30ee2d73b1f86e94bdd6940c7384d03348f6cc211ddb3e77206cd4bb0c6","nonce":"8c88433511a83e672706c8d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"9824a161f3b1b2515fe5b3b144b80933688547acea970d0b656aced8eb8da7e12c93bd11acecb675470f6b3b21","nonce":"8c88433511a83e672706c8d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"3067d8174ecc5713eddbac9af2fa819b97be32db337e318f704fe782d7cbe7db9473f29b0f5ea827a002e95150","nonce":"8c88433511a83e672706c8da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"76b3dbc8172a712ecb60f1099143748197519d18ed99b81f31de8ac86f299c832d9eabcb903827055223b831a6","nonce":"8c88433511a83e672706c8db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"f3aed140db0e604f858a94aebee1695b48f96e59bb31ea595d6131a63bf716c6b6c23652f26ae4b39839da4074","nonce":"8c88433511a83e672706c8dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"dccf0284cb4995117506b1454fd1330b2ea69b4f0249e3f39a41c775dc34732a6712ecd0892ead9387af335b86","nonce":"8c88433511a83e672706c8dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"606cad460b41400ac5fb3f70838b82cb88748b849e0bb9f2bc5a53dca7ecd55989e1c82eaadb516959fa8670e9","nonce":"8c88433511a83e672706c8de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"426d1ceb240e5d0a6436d8d9a9e49526774b72258363bac7d58e39af87833fdd6e79fc410bc54a71fa1d028007","nonce":"8c88433511a83e672706c8df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"5a60cd7d6a4af022351e0792316c618b6a4114a0123d31a5f9c6a451fde77e0c2fdaa4c243276716451e0978ab","nonce":"8c88433511a83e672706c8d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"0f62e57157f042ed7153ac2ddac313a98429b49dc190a3156433d5ce42ada98f59a9c2b5302372f6dbbf3034d0","nonce":"8c88433511a83e672706c8d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"956f0febdf7e91c8f2a4adc3631ab821322d751dd8b8c8c396aa659c7cb1af09c5a25599524484716e74f6d336","nonce":"8c88433511a83e672706c8d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"1c8655a8ebc724c4d376a3d75c2dd07d4d908aba4f03dbe87767f55a08db0da03d117bc32246d8a32258182268","nonce":"8c88433511a83e672706c8d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"5d2da87391f127895dcf2438f69f737c8b8ce017a10401d645888cfcbc634151da6e9982ed43c621619eae888f","nonce":"8c88433511a83e672706c8d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"64b84bc59f213a0f3eb8cb2801a7355ee9c6d3c5a5c3d7597d21f41d93b876e5bb5be0c8796cdb0804bdc03e7b","nonce":"8c88433511a83e672706c8d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"dc7e485149c8910216a94cf7eabd45110f67e7dbf2b4d1bbb6334faa324bb34f62b9d6fb55915d6ad28ae2bcd8","nonce":"8c88433511a83e672706c8d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"cc68d1dd321f3c34bddbfedda30b20178025cf24dd12daea73bbeb7a79557d61809bd754907118550b80ac0d0a","nonce":"8c88433511a83e672706c8d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"815727c700bdf2685485fe166172bd3ea3a9e969d72b209d74b7c05dd349b055651f71a3ccc08b853b288534c7","nonce":"8c88433511a83e672706c8c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"c5c49978a215c27b9212b261412ad79ff21e0acc1ae08c7e5d5bbe9d6041805c6d4180d9fdd196760a7bb4fdae","nonce":"8c88433511a83e672706c8c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"24e2628b428b38cc73c4bfcb6cd3850d642b40154bdeb7bd30a57664dd662d85d14f4db6c3f79f49c58f71aec8","nonce":"8c88433511a83e672706c8ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"f88ef825196930053bef976e7c1a07dfd9bb23769c8bb388c81b39fa02230acf612076c1277b5bccb773e5bd22","nonce":"8c88433511a83e672706c8cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"49f838f51ea75055f8da5d32c68a0a788308f7ab3ed107cc6de8c55cf6442e219f42f75606cacfa17f2b6d381f","nonce":"8c88433511a83e672706c8cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"c3af590d8a6cfa95d1190e2ba5b08815a5394f837a16b26ba43d639f48140edabf1d075ff5ff658d0b76a7c128","nonce":"8c88433511a83e672706c8cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"b95e4a16352e2a514e824f4e76fc100787e2a37b872cf541648b7ea3cfbbe874ec2afee048bcd422a4999e2d8d","nonce":"8c88433511a83e672706c8ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"5aa80a934c0f9d053013b44ea103261bd1daddec8e5ae63995a94ea2a115cf3bd2dc6dbf65552f8b18d5b72f4a","nonce":"8c88433511a83e672706c8cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"1989911328040cff99f2c9bf50f1a01bfad02deaa074737267893628cd2e1991464a4caaa518d3d83d830c848a","nonce":"8c88433511a83e672706c8c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"ed99c4e03ed44ab46331673d46941f3ea0f5d492cbd70b2eaea674e8cc8f90ac21448256283a5a3f16d0d19ef1","nonce":"8c88433511a83e672706c8c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"6a0e58be4324cd9b0d8854dec0f550da457f6f5930f654c1ca9128c63901c167ffc09c7891ab9d8e4d50b10cdc","nonce":"8c88433511a83e672706c8c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"509537740194a80b634fb398937dcce2c68a96205bd8b7800450ac359a33177f2cc2e9dc7360a95693263a6b9b","nonce":"8c88433511a83e672706c8c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"02cb90ca5f346fd85aa6b0e60220768f9d1d794b9ecfccf5404b6412e76bf921480a7b89e0458591ef3059ba0e","nonce":"8c88433511a83e672706c8c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"b482770632ac6df97bee8b2ef62803e96d8f9b61513ce78f31eef7f2e1622f383fc35db6e91aa7bb6f6d25c581","nonce":"8c88433511a83e672706c8c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"612875af1e02759128fde61738f7b0d593273e8e5051636f99fb9e71e18cf1aea4194718f220d420f8593570d6","nonce":"8c88433511a83e672706c8c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"642f514e8a1c1909032103ad66cdfb2277e83a6a74f47124cd35da13e1ecac452d5d7ec96018d476eca820641b","nonce":"8c88433511a83e672706c8c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"d82faabdbe2e03a6f5da0f30db8f33de2f39565d9b9f49318c348523eb440adb7c5e121470edbfd7e3c1bb6c61","nonce":"8c88433511a83e672706c8b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"76ec6143616b2e995ab247f6ffd0152e620501373f9a92f1b501dd4fe07ead86f13f66415ad864128780206bdc","nonce":"8c88433511a83e672706c8b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"d3376d5c877c2d4864c795911639773f166d2a652b9a1a5bcf5b3f0b99850441d36a4abc0e0dfaf9f34cc68e2c","nonce":"8c88433511a83e672706c8ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"f7d4daf4770fc03f6638c7855a55706aff22be087186a7c75a4caf6092e57949e4b516a6a65639b96a37b91bab","nonce":"8c88433511a83e672706c8bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"309b5f0f16f93045e12ede33e1d88169004e49487918dd764111c2abb23234810b983f78ce235824581c7a9420","nonce":"8c88433511a83e672706c8bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"4d742151621446d6f5044f83c0b7fae3c2ae3444cfa5c1cfe98e493f0878218e68601d37d26e46a6ce0d01433e","nonce":"8c88433511a83e672706c8bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"159d4b7a519e8c5b81854ae13621f05c2de1e038c9c9bcf89ee478f0ae0267a1ee5fbaebea8eb38f14127c1c1d","nonce":"8c88433511a83e672706c8be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"a1f4d7b7003733e79fa5fdfbb6d362550f3cfb92a82255126f546feab89abb867f1de80a70751275397445f6ea","nonce":"8c88433511a83e672706c8bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"53738d6ca447bd9a4981d7db673594ee464b2089c56f5e367d1bb9a461099b8896002e9903604ca15aacb91b89","nonce":"8c88433511a83e672706c8b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"c8e413af659163d20c8b7240ce2e8555210b72cefcb5f22ab58b0e913b450a3023598cc509ac9d093581d60ce9","nonce":"8c88433511a83e672706c8b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"ec4f8e74edab1ae88321c2b4f1f5463ae559ffd38e2a5b9cf579ebc75d8b6ab43827ef02032588272da39e4e9c","nonce":"8c88433511a83e672706c8b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"dd94ce930aef34b87c9336ef5945cedaaf5d07064edc694e67564724cbcb25e7beb976caf191cedb3628c98884","nonce":"8c88433511a83e672706c8b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"ebf2cf8de667f30eb1e7b1b04b2acac7acd0203279949e0d064fb49df2d29e3c98b8b438b5d4e67e55ad230fd3","nonce":"8c88433511a83e672706c8b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"0905682e69a46754f0c1419dee1a3f6dfd1bf9bdda46d9c3b14e5c37bf27f6e474b311302aa47ddf1188cc95af","nonce":"8c88433511a83e672706c8b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"777a5ae29cad53b6c02165402d7619a5ecebfe34caf6d53969286aa31c94c25fd60dcf00a00cb96d06d69198c8","nonce":"8c88433511a83e672706c8b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"0bfb22590688b4970e6baa516f0c5c41a5a4e1dc0398ecd434acd8ccbb969b937d48d75fa19110f154b473f441","nonce":"8c88433511a83e672706c8b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"c6290ac1d65b859126814c2ebc9aa9719be81e242e94103f88e55c894b1f23d5cf5b11c6f8a89dc19fee41891a","nonce":"8c88433511a83e672706c8a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"00e9952e94177766f6aa0b3278805f695783f928e3cbea75632d248f414dbded01d529dd8267509f9c5b7b5ca1","nonce":"8c88433511a83e672706c8a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"b391941256f12c60862367dc83848631c14103cbabdda8233470e78d45794c8dbea54898741be4405fffa8c6ce","nonce":"8c88433511a83e672706c8aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"39ec03b45b35f031eb4870fdcfd65906a7473d216c4f2428ef214bf2ce6f73bb4f01901383477f8dfb17a104ad","nonce":"8c88433511a83e672706c8ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"da4e81c71d011a39a933d3171d9a467ee6b6de393aa53be95d1fb4db9e47120de590ed8f0b5583e442cb84e3e9","nonce":"8c88433511a83e672706c8ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"ba69c9fbabbc5e5fa85be6eb294102746a519505e05f57cbdfcaeadc2de109b7c5ff4ed2724cb800831df9d27c","nonce":"8c88433511a83e672706c8ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"0f7c9468e4905fe2e2afc09797b5bf872b10f9bcece64b767601d304f3ba4fd764e098333ea687a51bdc2f9e27","nonce":"8c88433511a83e672706c8ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"978f928187f835fe1b36cae9d2c86407113c85d6d0b7cca7eb642646263ac527a257b2b826d34259e93af7aef9","nonce":"8c88433511a83e672706c8af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"fd71aceed1aeb22a20952d90879f2ab3b90d29961dcca283580ed9aa9cfc3bf5ba58e6ecc0095a5efa4fa74ad2","nonce":"8c88433511a83e672706c8a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"5c8c3a22204048dbd862f302e6c768c3333a27c5d3eb6b328c654a586f7ef54b082e7460db18d3dca969cc4003","nonce":"8c88433511a83e672706c8a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"98946abe594b93a0695545fffbf5677b2ef389d02ace95950277493bbc4922db4803d2da62ebf88ef80eba3af9","nonce":"8c88433511a83e672706c8a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"8fd50d383f9d7b410dfe137c1f087333f4fe60c7bbf19d2b61fda11d140d616abf3c41bed4131c239f7b828d5d","nonce":"8c88433511a83e672706c8a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"71e10f84c6e8697f89cb5a010ad89b62222fc9944e3ae73515fdcb622b5d46338aef6da8e19b43bfa9db7d7e2a","nonce":"8c88433511a83e672706c8a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"ccdbf944d8aa96dfe7530ef8cc45933e6baecf882518e8b7b05433f0f3ee257cfde88907b60340fcaaef5c0abe","nonce":"8c88433511a83e672706c8a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"0906f4c77f93e83791e0889a5c2816244777d5155a10dcdbecdc8b5381723febc96d5adbfaa6d30184c18ac2ec","nonce":"8c88433511a83e672706c8a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"a607794b8ac9d92f26b40349c98b0d9338889dc0263beb5618af0f72673e67b0097c5069b52c16e09b02ea3ecc","nonce":"8c88433511a83e672706c8a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"6dc649e3b3f9e92294557e94a3d86d9f1187226ed4573ef632fdb95bdf940e1eebc4eb6e0981b365eb5fbe1794","nonce":"8c88433511a83e672706c898","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"21d675428d26d49db0aa324719ef5e59a8f8117e960aff4da7809b6d66d32902168ea02e119c7a139835d273a8","nonce":"8c88433511a83e672706c899","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"001e8c514d92e2f4a8ff56db0b06ed9267910cb56011dd7ec0ba580c60cbffd077027bfede9910327b902f18b3","nonce":"8c88433511a83e672706c89a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"89ab174f292ddb19a1f70f2f874751ea6f78fbbf2e2cbbeabeba840e71c85f1911c820fa07989269fbe7caf61c","nonce":"8c88433511a83e672706c89b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"9106065a06b43ac7cee61964fdccded170da3ffd2fb46833c74641539abc239040feda586ce22a30e9a403e3b9","nonce":"8c88433511a83e672706c89c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"37bfa53288fa8109911c3443236becdebf6e94b9d7278ea76bcbfaaf18065a954ec8c619c2b676710dbcf318d7","nonce":"8c88433511a83e672706c89d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"cb87affd40310fbb075ccf103763a3f34a26cd8c94b7c90b3a599e31c62fecfdb3823b0c8afd6371a246c0374c","nonce":"8c88433511a83e672706c89e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"c460b153a232fdc9ddc9d5e4c5e670fcc91b37c151b9bfdcd4a16dda657b332ca590c9ff0ca7ac0c0732741cce","nonce":"8c88433511a83e672706c89f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"c22f499361b476df7c507e8987ea1ac105f4ff3dc3cfaa63a91a5e9596fda6afb873275cf4e8520cb73ea57332","nonce":"8c88433511a83e672706c890","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"7fefbaa047d483da6dc9d22394178d05c261ec7647b0cfc6a16060920e319053c49b8a1ec48ed221f8c2100d22","nonce":"8c88433511a83e672706c891","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"632ae626d65cf651be1dd8ec6e04f6ba6f3a574dc07d4674d2ede7c3c97f3f5b57ffa5648d1884505025c8986f","nonce":"8c88433511a83e672706c892","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"9fe9a0d41f1fc2ed8f4529383a1b791763850b5185b3bac52f1025f11674e9f21666ac2c7116c2b91ed59772a4","nonce":"8c88433511a83e672706c893","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"b64fedfe1969bb0cb5d77dda70be0e754c2eaf76df9ea664bb04aac7600a1d7679930526c7922e949b5d76a54e","nonce":"8c88433511a83e672706c894","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"29b4d55f826289df1fb8422f58dc9d471048c9b4ef87b1c621bbcceffbf03542a6e0cc072e09d65f2fd39919fc","nonce":"8c88433511a83e672706c895","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"848e1189090474819c026c725f3fb53cb3ecbf4fcefc07a09197523af53e0ba1cc0025d729a707a94fd335cd8e","nonce":"8c88433511a83e672706c896","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"fe3f7a13fa6a1e74cafb3e1ba5720eb894d41da7a48816a303bc3111d803a44fe455eb06d67291c68590ee7654","nonce":"8c88433511a83e672706c897","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"202b57368fa72171f884eac57d2f99fcab81672bc77f03dd1feb1ad74e3d255d8c3802b3758419a5099498fe5e","nonce":"8c88433511a83e672706c888","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"2f17a78c06b32eb0d0cf435d5bdfdc138655a08fb47db65384902c350478285a6491027b5f81c11fdb1a183b40","nonce":"8c88433511a83e672706c889","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"f589c21519ea125541ac1ed3ed3624eb1f0db6d9946311a2ae2a35fc8cab3051ca1886619adb6a9113eee521cb","nonce":"8c88433511a83e672706c88a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"0cdf06ee45750bf5e5dabf248af5519b5638b33c528bb17ed6a27650562313b39bb264568bd0ebcd35ba3f24cc","nonce":"8c88433511a83e672706c88b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"4f78e3f2b27bf0c171303aaf84223d3b22fbcc930dee251d80881b8c8323cd05bf49aa329724969cc9257389a2","nonce":"8c88433511a83e672706c88c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"83266888e47e7da4c03daa70a13453745e014c5c8d4cbb22e695ac00ffdf0a466ed803ccdeaee0574f239779a3","nonce":"8c88433511a83e672706c88d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"a5a84a3ccc11c4b8e0aa0a0bec52d802bf97357881e7b345b26375eaf77a70b8fcb52061b7869228b8fa0a4a8e","nonce":"8c88433511a83e672706c88e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"3dec7051c4f8c9caf78b1a614264e050b3305ae3319c6b9d46a57b18395969ec69a8ac33fee4a96dc90f7c0f14","nonce":"8c88433511a83e672706c88f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"8d135c6709d7b4770f210c8130b1969f53ecd03b18817b96eb181ce7eb960543900a315dbe2177e152fa8d1b51","nonce":"8c88433511a83e672706c880","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"9100202a7a0bbdf6b8b0220c31fb2405585bae3e4dc35b63d21f0ad3254adba88eb20e973c73f6d7f45c96b86a","nonce":"8c88433511a83e672706c881","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"a7e37cd469ba9ec0adb9c2794cce30cb55517825d6089aea5cd9bb3eb3b5ded7d5efb6dcdd2a05263dd2b9b256","nonce":"8c88433511a83e672706c882","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"56a94aef6ef9663d2a7f2ddfa1f4b30be1eb45a2058070e04367ed6ad724ba8c1b053104b9a256aa8672f6c6fa","nonce":"8c88433511a83e672706c883","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"aa66c15461081d883a90c0e1794d5a4d699ce6f6816e32eb5d57f9432ac3bdc2b9f33c3f6540495634992e2b14","nonce":"8c88433511a83e672706c884","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"099e23b9a3002e31fa36063949cc6bf020b97a0c21f46d0a4ebe5f3c1cdef735bbdfa6f2121d555568bc9d4e68","nonce":"8c88433511a83e672706c885","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"0346c9d465f8aeaa637f1411c963a51a6231a48d274f6b43e8aac6c680803b33545ed55ad2ab8b224724df5ea4","nonce":"8c88433511a83e672706c886","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"d57868610fdd15ae8f0b58f0949d84df19fe542846a869d8f03b24130a9c50d1db81d2175d6d5e19d89a7a8abc","nonce":"8c88433511a83e672706c887","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"4ea75327265e31062df06fae9a5816b50b36ae835b1602fcf613ddb87754f109706c0aed07aaccef5ea030d3ae","nonce":"8c88433511a83e672706c978","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"8f6a77e6fdf2f90fab00ca05f35677f1140a635492f6fdab5587be8e6d0af0c4"},{"exporter_context":"00","L":32,"exported_value":"fcb9131eb26fcb6b1984e40a5ecc7240ea89f062a5d48138c794a418b23134f9"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"5da0b98a693be1dde9da4f64730e1ad2acfb2cef9b23ce01719c12718d6fbfa2"}]},{"mode":1,"kem_id":18,"kdf_id":3,"aead_id":1,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"245b4678d8100df80f10d2cb39fea3049aab3367ac46530c88d656c76788cfe0e0663d91a27019d8a5af3bb8fdc38ad734a6a18d7fa7cb57b198dc9c6925e8f5b829","ikmE":"7553db4d0a2edb51e765d4a5eb91cf8764fd64db02e74b53ad7848fe00d1ff1cb7d1420c86818bf4cab617cfc6654fdd162ead24060ae8b3c424eb632f5a4d02e75e","skRm":"0191357afdeb58b98a1068ffd1abbf87a72a64804f56d1381d4415a07e4870c54228237268eb10e01934c074ed0e6bfe5129bd5a26127abab78824a45b7cebe234f1","skEm":"000bd8383d429a61f8dc2df3fd97bcf3f13134143a4942593f6fa30c8f8a3cca119583463a382317d25104f7ccc25a9ebc7b4349c15f3e838b8ed124364ed5932cb0","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"0400ee7b85f7c4202948ba68dca4839068b0dfd0a0480c700230a8e1981463ea15316f60444cb7240d0122de0741c0288748152daed09fcc41b550feffe8225207ce3a01d957629bd09cabb3aaf4cff8194ad69afce38a01e36d9fc2e359bbbca558338000e3221a4284e7aeb40dea0b08a2e6774a86f8ae0edf2134cee28e45ab097a5168","pkEm":"04008244e9810fe62088a441c4c5f6c8d5038eb4ce805066b7d1e8dc7fb63a64ed12ff49f97931ef61e43a3b233386ee6b1c0d9252e20ec51ad88edb2dbbf8f7ba3d8700e28abd62540763c86b6cd91cb245d778dfb3ab314d7d42730c9b6951bb4f1b7fa76b1e968f8129b09cb7a0e0f4dca7987dfae342915e87ac756b61fcab500832ff","enc":"04008244e9810fe62088a441c4c5f6c8d5038eb4ce805066b7d1e8dc7fb63a64ed12ff49f97931ef61e43a3b233386ee6b1c0d9252e20ec51ad88edb2dbbf8f7ba3d8700e28abd62540763c86b6cd91cb245d778dfb3ab314d7d42730c9b6951bb4f1b7fa76b1e968f8129b09cb7a0e0f4dca7987dfae342915e87ac756b61fcab500832ff","shared_secret":"b2479e365e9660f18c4064331fbdc0f0ae122d41e89fba44f222627db5610ae3fbdb545010a353e4d00c572944bad9e4ceff3e6ef02af83ac77759324975c108","key_schedule_context":"01c208fd0a0b5a080a7f539f59e422ca4e818e634e12a8947f0dc95d4315990d38f86322f9fdbabd010f1301dc6aba400a053db66487c59de1a557d1eb4b5fc9c4cdd87b0281e692a99982979c39757078bd10f16f51a609804bec7ea73e6df85d53e5b21081fb76ca400113c07723eeb59281dc77544497e8f8a683106eca75ea","secret":"a82a06abc2f5035fc406bbe931c05765af0d28de463b91ad25c9cb9fe64a31afbe6f3e8ba9da914abce2dea4e1f8a4d19f35fbb151086ca6852952f521c878b7","key":"065029f3a49d925a13bdbdd6af3bd520","base_nonce":"99de55204f797a570ce29eb6","exporter_secret":"41acfd33b77f9d9c5bf9ac6e9ec33bc41f36e1512e771d4c8130bcdbb402a6dc35fb9d3bd1243e21ff5faf288562c2ef2a49abba227b47a2387678706fb8cb05","encryptions":[{"aad":"436f756e742d30","ciphertext":"b1ab87de127836b0ddbcd971ce9c70780e03e7e369af358a6280a10ec0e815f565eee8bf446f13f55ece7df12d","nonce":"99de55204f797a570ce29eb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"7e5e0294b5e18e0e276e43dfb490ff2807929b7e423ed1bcb269c06fd3fbf28302625509d534cc28b953a3bd0f","nonce":"99de55204f797a570ce29eb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"4d7e13ba492f43f8b251ea7fd9f4f746fc3c165e30119a498946fa848fc1a4c33d7a326cbe8eeb8046d6b43355","nonce":"99de55204f797a570ce29eb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"c5114bfe86d07083dee94c0519a3c730345eddf23db705cc9c11c62339634060ce8cbf5cacd1846046fa12b009","nonce":"99de55204f797a570ce29eb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"4d27198cc1ffad643974b99c4be7c4932317e7e478b833192eb88073346810251836de451035cc1f368e273ad8","nonce":"99de55204f797a570ce29eb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"7bb5315ab75b1d44e81515f004991012aa5f0364d7c0256b796c482d22432b2badd8b1c285c5bd2d7abf200726","nonce":"99de55204f797a570ce29eb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"f305b2ba9c01dc42c74ad08d6b7a7cc8d187fbff1fdb86ab14244cac6abdfde9c623c1c1fc503648d2c3b357dc","nonce":"99de55204f797a570ce29eb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"fe55929d17374ce73485c42d30e39ec3ad1da7811d44ef71c5bd0ac3fd9c33c258ad76386a19e8bfe16d5b190e","nonce":"99de55204f797a570ce29eb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"a02c613288f0b72d47890d93334577ed2e4fa425503d4c1d892a1546274d50412b12b0ffe530b37b36d8ac542c","nonce":"99de55204f797a570ce29ebe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"7564e88dcc45718c6833d5aa012421bb266669228a01aa98174196849f85dd1877bd89a574c8e833c50b62329e","nonce":"99de55204f797a570ce29ebf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"cd8f209c335e4254964e46bf2e15744bc2fb8a696ad057763d01bb8d696b22e46053faae9541a79ad8617c0929","nonce":"99de55204f797a570ce29ebc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"b5fffbf90425a199e48f01a7a1a391dfc5e092d1003cc0f45d9a54d021ae299bfc0b5ff1b157e2539e9aba0361","nonce":"99de55204f797a570ce29ebd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"0e4a2aa66191fb14c6f2dbebdaf7549daa76b6c902fc3b825ec592a6a66e383ad7e3fe26c51d213b086e40e4eb","nonce":"99de55204f797a570ce29eba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"f45ad60b119822e69ebb1230e9040d8a6d01922965ab73fb77877f78f23b83e66116b0242dfa64544951b9465c","nonce":"99de55204f797a570ce29ebb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"28cdcfd5c4df350099603a11a1c82cc1a7b8b83e8b1a07fd2292f0a94de86fc3cb4606339711cdf1aef8961c38","nonce":"99de55204f797a570ce29eb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"abd489cd142aa9f1a2a1bb783c288b0f4eed5e21ea2fe5e02564dccf6b32f92a4b0b61af5f7e30f198b22f8a8b","nonce":"99de55204f797a570ce29eb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"50dcf5938f398c49db81379b11cc7bae5c119ba0eb85ac51870e20e028990a999e630bdde1290663c685947273","nonce":"99de55204f797a570ce29ea6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"6117f9fef61c2a16bcbb9f6fe4de6374d8b8ee72a8a1d0c6c8d12ca4a0e736b8d0bde337111a4b727e65ccb6da","nonce":"99de55204f797a570ce29ea7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"f024e8b392ba7de6057b5c1ada4b0a8e421789d4b747fb2542173e1dc4f5019564b70c5ea2a0692716a529fe81","nonce":"99de55204f797a570ce29ea4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"966e2081219d19666541d48c24462fbd76fb274d5e60d1dab7ded564087d11aac09b66ed63ac835188b72644b6","nonce":"99de55204f797a570ce29ea5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"6fc88fcc099870fa5758d80cd7e900b6472c0022ca75d806ff8e630ae092aaa4254dfb5e41854ab932005b40cb","nonce":"99de55204f797a570ce29ea2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"70e9a1df7dad98daf67a2ed9aa9007ee89389ddccb3ea7ef8a1efd8e9da2699f666cbf7872eb5f5a130d35430c","nonce":"99de55204f797a570ce29ea3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"e5560656f18a6f0122686c676fe062dff5f13fe2478685b8f248d2d5435fe68610304692f4f7163946d67149be","nonce":"99de55204f797a570ce29ea0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"6ffd81f041a488072cfa3a8cbce7b8e9865b9d5e8cd6497dfba0a3f8fd5e60fc59b651d452af6bd55d63fd481d","nonce":"99de55204f797a570ce29ea1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"5e6f2e42e8e6d610e8f3585176594bd9948652430233d414a91a078d1fbfb83726b83999adcbe9a55911ed878e","nonce":"99de55204f797a570ce29eae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"e836f1748cef51d24b86753817c9d2cae879a0a7bd938583c01b6d7dfeb0ea6dec5f7ba46627e553a8f0dba105","nonce":"99de55204f797a570ce29eaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"f43734553d1026d68131cce3e797dbf8e4e80545247c4936daf91cb2bf1749b266acce4ce2226ad2d616cf15f8","nonce":"99de55204f797a570ce29eac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"a17a919bac2a8cdb0e23765c83699a4009bc63eed6c388267f24121ad712531cd52871fe7a207d3f910e51da7e","nonce":"99de55204f797a570ce29ead","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"fe3fe1a0fb265cfe95cb2f9e1548850a3bf536791dfe51ddde19ceaae027789810a1be89c59e57e6507ad1f6b0","nonce":"99de55204f797a570ce29eaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"038fbc26bf3c703ce94d59b7d1529caad9b1305e6aeede59008a3ad434d546cb47367c4f3c309f551550adf52b","nonce":"99de55204f797a570ce29eab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"5a7ecb71cdde6290785c57333b6809d607a2c9590355c74e7c612b17bbabbb4b56432b746d25702d69ac1031c1","nonce":"99de55204f797a570ce29ea8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"1eb393e800622b7957c573a8318bc4761c81324f554dfcdf9fcdcdeccb36b6d11ab79c84f9b6609a874e75f4b0","nonce":"99de55204f797a570ce29ea9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"327d32173520bc151a9fa70a01b915531797e06856eabe9dc5d124e19881462ec762c95aafe5863d55912b9f99","nonce":"99de55204f797a570ce29e96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"1941f0c94b6cb4a5106a6338857e2baba288babccf990cfcf586799222cdd0c78f37f876e3b7bd9f189b0deff4","nonce":"99de55204f797a570ce29e97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"942a7db2f10e1c42d7aa028a83207388b73e0af404ceab2edac560798038587b17a9bc5006c79c7d3e49d5a0b8","nonce":"99de55204f797a570ce29e94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"368e8b36c0222797ce7923d8b34f5fd85ebbefaff1bb48523a631645fd4c716c5f8a1b9ebf84f68fab0a2f7ba4","nonce":"99de55204f797a570ce29e95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"806ebc1a346ec947094cf0362eae1a485faf173fc2cda0d8fb74f6f4dbbdcda342d08d2f8bdb95743a86360c29","nonce":"99de55204f797a570ce29e92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"2efd55f916ef100249b5ab8ebfb4286c8be49760b666e803889ba9338b037703db0c5be20e31c8a941a8a6b652","nonce":"99de55204f797a570ce29e93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"406d56474c5fdba2f7389ef2c6c9563c9a7b3b6cb102b79813bee317a3584bc3219d094d51fd7929e9fd7ff16d","nonce":"99de55204f797a570ce29e90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"ef8737ab12f533a1bd4042a407ad155c43d11a48bd4ea5ec95dee09465b8834729d6cd4d9f94cf62636aea62d4","nonce":"99de55204f797a570ce29e91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"fecbf6317845b109f79c7ff857690adfd86ac9aedfdf0ddc9c65c7b5b53b19af94190acaf84b2df6835a11977b","nonce":"99de55204f797a570ce29e9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"52e1ae28b37941d1dc920c57391dfa92097ef65071a212382041df5fa7462ec65816a48bb74d99a0206f26d512","nonce":"99de55204f797a570ce29e9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"9c06dc4a416938b679d206bfa13276ef01cd09632ed77f0271afd6051ec2cf6c35c1c5273185cb154cac41bd02","nonce":"99de55204f797a570ce29e9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"fd46219eb30c3080a4219d6365b5331ec98855cd02d4a2b8e11de1be648e210c8bb1f389806b58d701dbe7fb8f","nonce":"99de55204f797a570ce29e9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"5c7207cf1b4007ed21e602a9c833268bd481aee165081258550d3931ff5550c1eb7a41fe35746c43c9b34aafae","nonce":"99de55204f797a570ce29e9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"8bd33044627ceb9c8f831a7bf3ebedd15522ebff239a71c7685444ef4fa68fc0ab21f65bc717668d973683371c","nonce":"99de55204f797a570ce29e9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"61f1aaa5d0021981b95745a4e14aef158fa5c7e6946746ecf2b7d92aaa425abd8ba0a7bd4c56cfb08c2e3d576e","nonce":"99de55204f797a570ce29e98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"4de9ff8c11a0f6bffd3de1f7a68a60e67f341dcf5b2fb8af8676c38709c9e7df48179c175672fc731c64cd89de","nonce":"99de55204f797a570ce29e99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"2364efa785c36a72d5f698df9a7fb8c5134a855d66bc0900824b958caf1401920cdd133889d092cdfa44930aee","nonce":"99de55204f797a570ce29e86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"63801adcdca04e6717d20625aa66e000b483b5790856d2d991f16073d41d4bd99fb65d0c3fffdc25dd2de14186","nonce":"99de55204f797a570ce29e87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"3e8868edf4d383a7b471784603a19a6eb70fd755c51c00f77136ce198d76fa5a2753c202d01cf73e5ab0a26836","nonce":"99de55204f797a570ce29e84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"70828030a257b1e19f7a169d9dd6972205e5b6f0e17a8ec7e6dd191541bbb316b78a83774f9dbca106c05b4813","nonce":"99de55204f797a570ce29e85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"0df39aef9f8b7c36b7e563b11995992fb7c19558265a1896bfd7525dca2a141e233b0bb53758108b9c97b9c4e6","nonce":"99de55204f797a570ce29e82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"dea2306b55b9bfcf794d1888f789bd7fb37408383beb286c37e32e613b7ea161f45688cb48d6278e6fcc2fd591","nonce":"99de55204f797a570ce29e83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"99bb524c1f73e7dc8132c9659e4894cd2a9af21587535dba9ac5ef59e4917e6de9c9bf9b4df85d21ce9171768f","nonce":"99de55204f797a570ce29e80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"484e285f075b4bf710df4205c0bebfb4a322782f0298352b40136a7776b82f7de37912859fb274a54749880296","nonce":"99de55204f797a570ce29e81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"85f92e8058a5acb7fb309cc399fb333629d956bfb01c24ed0597535aa8911674eb4f1fedf41e42b29c496e78ce","nonce":"99de55204f797a570ce29e8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"8d750319d0c2ea61eae69f0655804d609c7e6350a33bac00daba6e7d86be7150cc1e76df1d6168adb360a0bb93","nonce":"99de55204f797a570ce29e8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"be12d8ab1397cb41845dc1142ca64d2ba057edb8a86dc38ca8e59001359159af914651135a3797d31d53cf17a7","nonce":"99de55204f797a570ce29e8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"0dead065be647ca217848f5615c134bf6582e002a109bbd8e70b08f57461b71d0514653021926ee1197b3d4950","nonce":"99de55204f797a570ce29e8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"5fd3736b0b113de3672b8db28c1ef117e71999efd7f2c603cf9746f8e7416f6ec3ec0fd25640d9ef88c74d5d52","nonce":"99de55204f797a570ce29e8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"1a354df6546e2498587e3f18b4e1bd0ad9f61ff991b413b95b67aab66ac7b21c18078f772e8c1252116f64e865","nonce":"99de55204f797a570ce29e8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"4d41addd124b35e791e7ced6e7b0a585d1306d2aa80ff2a327731fa219a56b98cf6515635abfbb5739671528a3","nonce":"99de55204f797a570ce29e88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"a789cac37549c105edd7bc55e57508680bf3ddcab1967f59566b3bf1699badf6c031d8932cde37fb4ac8deaa72","nonce":"99de55204f797a570ce29e89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"42742eeb17dfb7350e1e8f0b3e1126667cbd37f2e9a27b82bc3cb88f2468e74d4218dff63dace244c588cce00e","nonce":"99de55204f797a570ce29ef6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"90c51c1403f687fa776974117149548623693b9ddbc63bb88284bab44b2cafb20830a17e4fbfb7bef1df01a1ae","nonce":"99de55204f797a570ce29ef7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"f0190b292981d9bfac28d6fcecf210b6f3746a0e43dd57ff0eea63237ccab55916269cb9823f86c49e4cb743e1","nonce":"99de55204f797a570ce29ef4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"28ded2487d7593ce0f70fe1c1c256fe14ca1d19922caf569d574e2c0be96903104950f1feaff5209e411cb3b93","nonce":"99de55204f797a570ce29ef5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"bf9a735cbaf16260182fae546747209c17072c7fc1d5bf5fee9755eb24cfa512ff1d19a774e501dfe67aa30495","nonce":"99de55204f797a570ce29ef2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"69da781c9fdd58e81c29de86f6d99b81691bbe7380b9dea94d91482468a8856514c81743e56da0d51bf768e6e9","nonce":"99de55204f797a570ce29ef3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"c059773f8fcc351be6b450dc7a934befde640fdccb2236148c94f7b3d9b48b8a65c896dc475c36a9ff9dd11694","nonce":"99de55204f797a570ce29ef0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"6f6ab8a7ca68e681e63caa8cba44daa4f8483c2c6862746b62052f4cbdc83454e71ab06f94e815359d98fb531d","nonce":"99de55204f797a570ce29ef1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"1d3e41a58ff8a520162d51cf30dc7beb27fc02e9f2cb74128fb416968b48d42fb511a2870440bdcd0ccd888862","nonce":"99de55204f797a570ce29efe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"74cea64868030138c5be9175bd3d4ed681aceb4fb5c114199df54c8870c6f10e65483b7313abd84571fd3df2fd","nonce":"99de55204f797a570ce29eff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"7522e73530f837465ab583f685f0d3c771fa7f2bc097d801d898c75ed5a0ddd1a377a3eae39dc6938697af4c03","nonce":"99de55204f797a570ce29efc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"86f0e5d0bd204fa144252f815376accd3d7c04f42c8a65a9c703d977343154f33349a1a0f2fe78fdd165f5b195","nonce":"99de55204f797a570ce29efd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"b5bc63dbee31cdd9e0c70bb3c14e94f45abb48de7a9653c664300ce673d55002b19f819da9c3d563d6d0cd4afa","nonce":"99de55204f797a570ce29efa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"9431ec9e8ab2a9f157941e98328da9739f528b7a4ddb384e866419984eb41ba4c295261ecce2f23777b18d0270","nonce":"99de55204f797a570ce29efb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"74066dfa9073da01a5930b524793c273e1aa378c8e8221db9f4a27b137c9d67f5bf5e087b4bf6edc5764ac8ba9","nonce":"99de55204f797a570ce29ef8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"462d08c0fbcecf7b244d8f0ba6a49be794c8136d11094cc3dea9c019a8d1195715e345503999af00393cfc94b5","nonce":"99de55204f797a570ce29ef9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"0389928a1d41d774bb332375a1950e2a570181f30074aa17b5cb803e1a47e1af0bcd8d40b47efcb85b3dbc8c22","nonce":"99de55204f797a570ce29ee6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"0017bf8dce8769ac87cc10f5cb84716014cd091393bc60b91010f76e1f742e7d246dca0b2681a90f3aedc3ec90","nonce":"99de55204f797a570ce29ee7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"4ec0034dc5f0bdc1e602a04eedd992d4153f954983513e6893d87b763f23e78a50a00f50efb89affbfa9f27530","nonce":"99de55204f797a570ce29ee4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"aac9b10522c1ca7b422cc291e214421c1847b3eb0598caa7bcb373e4eb30b6161c152ecf1f737b385f303baec9","nonce":"99de55204f797a570ce29ee5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"65ade14d3d229a6248991efd6dee1e9c1237c9ab7a5e579822426fb2f4faac4dac2bc225274b4479fed863a606","nonce":"99de55204f797a570ce29ee2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"b6cd7126bb463f0f9de7d26a90ca2e5ac4f4393c4df1409661268213aba865bd231d5a326692f15d75eb142d9f","nonce":"99de55204f797a570ce29ee3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"46ee65452a2386c5e166d32371fb2647a0605fdd06aa0d421e7801b2363bfb66135bf5afeb07c2ae7728a3dcc6","nonce":"99de55204f797a570ce29ee0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"89985261e98b90e12cbdfe0ec324d11b56ddcf92048676183f622839e570d6daac2f6fc87e79ec390f622ca1fa","nonce":"99de55204f797a570ce29ee1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"345ab5846f3e31847ab6a9cb3c3ec8445e60f646a796a1632c4decedb15ad403912b3dabef0692b38dbefbaf79","nonce":"99de55204f797a570ce29eee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"063c23be5e1f36e2c814fe7d216c8d252500176737c3f0a85279cd29160ea80b7665db5439b9df7fc3fcf3e61a","nonce":"99de55204f797a570ce29eef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"6d3db8d12e3b0d8b2bcac4ce43b8434175cc61523b73255b2acf186b740bc8f39a286422c5f03bd1c1b74f25ae","nonce":"99de55204f797a570ce29eec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"9a793300f7019fbfc5b2d3dfbff52ca9430090094588d791ad5a3f50ad6bfd44c8fa777ce518770ccff7dec463","nonce":"99de55204f797a570ce29eed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"ee595bf892180f6f358f2bc87742cb469802a459a749e5c53f3dd482ddd15410726e7775044b4c8f5bcdc04474","nonce":"99de55204f797a570ce29eea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"e43fcb5d2d309b91feab009db40f2d103f3e75d8029c1ec96a24d282e4374e61ec34c4c3d1bd85ead6703674a0","nonce":"99de55204f797a570ce29eeb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"a85679d4fc415743e732b6895e7f217713bcc199fcde2158af7a9105fea1d51b2c14423c4d2cb44078babff86a","nonce":"99de55204f797a570ce29ee8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"7849555a3a0cdc2e75470950a7eda3fb0d529c5c7d17172178d8e0f3240361b4ed63d5febab849de5d27c51a17","nonce":"99de55204f797a570ce29ee9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"a74cdb18dcb6e5da2c053dc7fd433eb73cc67ddd558c93500dd889bb9b416852473fdb49aff09edbe9cd247f56","nonce":"99de55204f797a570ce29ed6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"d8b14dc82236a3f324d758e81a3cdc4fc043bdd057d8f7fcc9c5eb3d8b9b3c547346993d7ad434309c9dd3bbe5","nonce":"99de55204f797a570ce29ed7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"b9c8ecd3f29e942d77f06e360a8a59a62a851582bc0a3f21070331523ed0dd98b4fdc1e6d731c0dff2fa3408b8","nonce":"99de55204f797a570ce29ed4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"b71f34166de1842fcf5490b80cbffce6d0907456cafe8375cbfc714c255bab0f3aacca2aacf9dae8570eec5e0a","nonce":"99de55204f797a570ce29ed5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"a8c056f859d4a23b29aa17e5a4639ce1cdd8f92c277c07eb7e31e29fdfd7903ec0471618a3774b09c7e4e44423","nonce":"99de55204f797a570ce29ed2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"d70480293c088a151487c50ef4bdcd2ffdb99dfa2df55e8ca26abc317c4843f99077f8f42ab7b7794daa839046","nonce":"99de55204f797a570ce29ed3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"61611f73af9924796900a463e42adbd0b0c48cbaae34fb19b8d55d9e4529b08023c3ccb47d3cc517301fffba4d","nonce":"99de55204f797a570ce29ed0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"e86364bb52e97410dd5a773f6a92e669a583a29bb58d1f23b9e33452332565cf6c909b987335eb016d848ebbfc","nonce":"99de55204f797a570ce29ed1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"7e60a04807caa72a61a5f58982bb2092aaf3353b16f3d9f23b2af0567166afe9b4dd18852f3f532f280e3394e1","nonce":"99de55204f797a570ce29ede","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"9dd30ca910d75b54d2e5a55fb98e53b2736c0704ade423cf695bdffe461862261e9b0f4a83374d16eab186e507","nonce":"99de55204f797a570ce29edf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"df543feeb8181215fc00067c35e11a655c2f90218a58c8e31f6cecba8adee38890593799749c37a1bf8c993f2d","nonce":"99de55204f797a570ce29edc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"1884dd8bc7ed5b6b7705e9748bc002bc556b4d27232cd86992ef07ea9aa4cf74905d726b68df70e64ea9935770","nonce":"99de55204f797a570ce29edd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"3e681ae3aea7e8c75429d99139e43861393c24d26b65f3ae97df9321f3228b832251a0e216ec1357dda80689d7","nonce":"99de55204f797a570ce29eda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"84bf10201259e0444af0567b86232d56f9c379a7a4c84826311459c816b2df1a5d22582578e1c5b41172118e3f","nonce":"99de55204f797a570ce29edb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"8ac8bf0f3c204e30a1ddbae2ce41153f2d833631e59463590e681d87fa5e1dd318f51ef300107c61434093d5db","nonce":"99de55204f797a570ce29ed8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"9e529f2f055bf00aaa4b3d0abb4d1fd13da142df96f4b474cb7e1440f523b82c6bbcbb922e5ee56c979598827e","nonce":"99de55204f797a570ce29ed9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"3c1cf538ad6df21f468186d90a1fb88b1c45c643a2a4767a7952afd05d4e6fe76724d79a224273b69d03078c00","nonce":"99de55204f797a570ce29ec6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"5adc0cf21d9364b8e3634c4d666fc970e431517faacfece0f047a79dfc1393c4d7e753576b956de85ccdefd6fa","nonce":"99de55204f797a570ce29ec7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"0f653088333e684f1e3f98b71ff3042b0aff90235c48a742896b3f0e0f08da4670ea9bde4dcd7155d354235fc9","nonce":"99de55204f797a570ce29ec4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"090b6914e03090f64be269785455b447e0c8e91d035fef720d239b58375851db354f9b10d446b997e3e73da2e0","nonce":"99de55204f797a570ce29ec5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"bd6b0030cf22f6c9d8b1d7ceb07851e00c5729ad43a794e826b21a2f9ea1a3a1c0b8d550f28e37da6aaea846f7","nonce":"99de55204f797a570ce29ec2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"3a1a46bc27ec9b5da088369aee549a1c91090ce843f0a09d8fe6c130cc9dac617568e906351532c104ff5b85ae","nonce":"99de55204f797a570ce29ec3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"5f490ea9ed9581589b6f82540a2fa90c326f0c5a2884fd6c6b5656806eac77c3093c6ecbf0b0d149ec24a4b632","nonce":"99de55204f797a570ce29ec0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"94c976c2231bdc835e0c46d89832af081af37f5a610642116f25b34ad2126020954604b07ca46038272ce11f64","nonce":"99de55204f797a570ce29ec1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"d45d7911168b3f8e2562dc461cd75eb7c444c32a0d7900b2498db9a5f99f39b6823374af1aaffe9ef89a71eabf","nonce":"99de55204f797a570ce29ece","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"c2b2ea4f224ffae30264c684c5b33d680fd0f3bc45838794af371ccb2ed6e065cdbce06079bed8c5ddd5b8b577","nonce":"99de55204f797a570ce29ecf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"01d552fd7f7d655c0c468d9f55dd140fc00746d57ea9f7b7092a54083721365680d061e38a9320bfea22fa7542","nonce":"99de55204f797a570ce29ecc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"e82f053666bcbffa5081511d99c4b7b356319d6b90e191bf80a1d12c969178485f35e34500380958962f280dc7","nonce":"99de55204f797a570ce29ecd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"c35cb1c009a2410cf010c7ab9da873057ff7123f151f70ee1fda392128235a4ae7e5ce480966b7bc6df4a66034","nonce":"99de55204f797a570ce29eca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"e769100150e9305ccde692ad35d649a603d890f28548fb26d7f06bc85bff4d8810f76d36153b641d84cc684fcc","nonce":"99de55204f797a570ce29ecb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"619fa428122a2d6dcfe8b876767fa333db8a93e5061de4b86d48b40f9933fa3f596345aa849778c3e05de98679","nonce":"99de55204f797a570ce29ec8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"c8b4e124e5886731ea1acae0ca7c6aa5f5dea8110f3c11e20f149b9a3b819b67e997f004d874251df25e934707","nonce":"99de55204f797a570ce29ec9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"bb6675a2cd0e1ba51984aa474e94d729cedbd2e32eac0ec4e9774104b453e0f8c837b4d531f8afca23eff12e09","nonce":"99de55204f797a570ce29e36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"59fb83308c3663a58a86ee221c31465b8aa37b983c71397ea7adb677c756fb2034b2a6a44f9c3dd07f008cfa62","nonce":"99de55204f797a570ce29e37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"f94f989c0d2f09647d7298f4ea1131bc3c6fef10cb5b6fcd43e6cee816956be1acc39acd657c08b121935483ef","nonce":"99de55204f797a570ce29e34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"e8313f28637935cd904c4e3c2fd038dc89d0465c3427578e2b614ca77a66b91195dbe5bb0ebfb3a086c1a8bbb3","nonce":"99de55204f797a570ce29e35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"3f0cec34a66e021c89bb90e2153ef489037efe2888a432c4a7e4b0404ee7933389ee4225c7c4a62ef5682eb3e4","nonce":"99de55204f797a570ce29e32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"b0200a74d89ddda4128bb4af2e9876ef20d5835aadf00efd13cdcffc0abf91668f547c26c5efeb25d1bf40fcd5","nonce":"99de55204f797a570ce29e33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"4b20a42bd241c8cbb895c35f6aaaeadc04d711433c484a51418f4319068857680b0c2e3838f14afcd2bdeab38c","nonce":"99de55204f797a570ce29e30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"d40ea9561e96fa6b70c57c15e82c81aa3f8af1d6a68ddfeaa408ef41e5ab9c8f2e24324dc27d5e68cde885a206","nonce":"99de55204f797a570ce29e31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"9090fd1461f1a73f1541328159f6f102dbddc74325d6bd2da15050949ac6c4c58ac94b46ab671fce6dc8d88c76","nonce":"99de55204f797a570ce29e3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"234bec2b823a1df699d9c9bfea86e3a124afb59710704a849dc9b777ef22e7cd60b4ebadddfa94a08fa9ad840b","nonce":"99de55204f797a570ce29e3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"c7d1a9a1500236799e49d3757014ee7de811b513bd828557966f43a3b1f8c52677e2d19610d2e203b8f21966a7","nonce":"99de55204f797a570ce29e3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"180add6eb71c8ce7fcc010e9b35c2a1e80c04bc7c552bec643520be22068c41abc6202de6e540be7161524bf32","nonce":"99de55204f797a570ce29e3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"5970b9dcf65aa805e91a4cd5a79c43353c6432c5dc3416ff01179536175c07667acea2a04a8ccdcc0c6bbdd914","nonce":"99de55204f797a570ce29e3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"8cf2b7863cbfc03012b1edc3ef1e58f09f2494700b59819067a435864e9da69db08c0d7cd474b1528fb4c35b10","nonce":"99de55204f797a570ce29e3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"2f91ee1d8d65b12125e7913d01d9dee705a1d651a9cf4d33945e56563e6f582c5a5498e453a2f67fb4b829890d","nonce":"99de55204f797a570ce29e38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"d3ad8a2574c9ce2adb4976c21b7984609b9f1c12892fbf8ebd9130bd89891641f93af19447ee91cd6556e16188","nonce":"99de55204f797a570ce29e39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"da6fb9f5e87f391bdc1d46e73dfd8b79544b0767585019f49171f57a726ca5f7e0be54d2104c06139b77c8e6ef","nonce":"99de55204f797a570ce29e26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"eb8344abf221b30fbbb1ccfc3305eed15a656aeede670479c1fe0522c60b3c59c373786e5f96b9896f3c286acf","nonce":"99de55204f797a570ce29e27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"f982c3b33e7cb965881e46492080d5c0adcada5ca93c3833d2e8010135f7191702efac47ef716049e1606941c6","nonce":"99de55204f797a570ce29e24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"931062ffdfaa939d3d878f1a4552f1809a8ba2d11368f2c0e3b7cdaad7c853c34732d639815ff3f86321285a2a","nonce":"99de55204f797a570ce29e25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"be1a07f5d7d0d5ab0fcb869206097916881186d58db0a53d1942b1874c57371b6b474a9d22ddfbeb86460d175b","nonce":"99de55204f797a570ce29e22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"e200bd1bc94a8878a25cddddd5dabe7d8acc1e2ee850c006f94cbaab265de52273c9eeeb65bb5b8947409696b8","nonce":"99de55204f797a570ce29e23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"5c615ad67375ea546d17b0b2b5a42791418cfe2f630f3ce53de717cf47917274c47b8f1e86a0a67cdbbd983158","nonce":"99de55204f797a570ce29e20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"dbb43384564512e30b4c0e90dd027937769b6b683def99169df08699fd5365bd11346a5f4720ba9189306d025c","nonce":"99de55204f797a570ce29e21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"825e352eb15adb4356fcfdca0430d6b66a36377799ce5c81c4757b12a11751e6388a3968e442a71b16268c6396","nonce":"99de55204f797a570ce29e2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"7e0285e2b3520f8bf71f6c89e79207b4798637e09d0f41ff06cf27974f68092cee70dc81b5a3a51cce743ae77c","nonce":"99de55204f797a570ce29e2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"b9190a031a79fa9899adabd0603a438bb3366eae1071c6a80cd81ec9d444b0b9ace34604b1436ad014803c9777","nonce":"99de55204f797a570ce29e2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"5abdf47084088584f4741ec428fda99b544e507352a73be0b2d9396f9401d91b34dc9b7dd7319d905c90944509","nonce":"99de55204f797a570ce29e2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"1cdadbdc4dca8b7baec4d86363f4c249673af52c4175153d89b744226e2f98304b8b5e94b62585a77697fe5490","nonce":"99de55204f797a570ce29e2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"453aad01a3ae3d6e1a2b108170d23727fbb6aa34b98eaa857d2610714a9213f874ee344982484bef2c13862131","nonce":"99de55204f797a570ce29e2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"20335b48f3896fa7e0aa074211a8321e957c1f19c9a4fa3b7a88d7b157466dceb130e3c4c06d67a5e0e5d611a6","nonce":"99de55204f797a570ce29e28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"104e48eaaf9861986a2656dbacd19b61b811a06160938d19027f40e50c7e2a5fe7ec778d7cf50bb27b007a44cc","nonce":"99de55204f797a570ce29e29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"15c8c4cb9d512c3e451e61dae392d2dbf30bd06351e4e360ca15ae56b70631f0e376f4421b2d7d4274828e6412","nonce":"99de55204f797a570ce29e16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"f3a0e0989d4900979fd8c03eccf28ddb7a858cd0611e28dbd8288f87d3ffaa38ec6cc303ad034ca5d68abc87c5","nonce":"99de55204f797a570ce29e17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"82cf5245a0979767eb742ea6610a22ed6be2333de157d967d2dc80de348ec98a8f9d939ada6aa992d2c3d99dda","nonce":"99de55204f797a570ce29e14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"bed6f580faf5a334f976407705c7ededd9d4126afaf0bf5219a6a020fdbb18b53f871d0c8852cc17aec7e8badf","nonce":"99de55204f797a570ce29e15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"b4ac4fd02312357e75f476294f8a269ae937bbd6d016125b20e4ab000e0f16095c57c54b56108553154a8ed581","nonce":"99de55204f797a570ce29e12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"b842e3de86fc5dcb00f6a6e5bdcd2ebf92a88f1f390ed7a495cf15e3b38798d47399f8c4d704429caf041217ca","nonce":"99de55204f797a570ce29e13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"b060e1888f8c579ec0be9862ac4105a826f964a0f49504609cfbc8466c54621faef4f41843086026151f5b4fcb","nonce":"99de55204f797a570ce29e10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"91609aa91c62f800907dc580ec91cf74d01a7e53cade35c06424976fbc0a1bbe74a09614565d6934c0d006c6b4","nonce":"99de55204f797a570ce29e11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"f88a1668a1aa50bfd74b250606df5112e35ef8384033335f343bfff1ced9c3d4e586bbe2cf9e4f3748238ea7fb","nonce":"99de55204f797a570ce29e1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"023b7644a86d3b7bf500ad753156064fc548bebd66b4ce9a3ace9a6b68fe017250c29f64e629bcbd6bb9f3cb1d","nonce":"99de55204f797a570ce29e1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"793a3cc8a61011dc5089a2dca5509cc043ac3a63fc1efa22e8d2c354794db4c2042ba01bbabe0d389e1ae98a25","nonce":"99de55204f797a570ce29e1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"96b0a176c9aa806f6d48a7dfc993ba8f56d868a9072749fa7387a5d016e252c63d95f78fa209cf63bc118ed48c","nonce":"99de55204f797a570ce29e1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"4dfbad9a8f4d13f7306e0b65c713e59544548e4f6b270387fff0580ef7590dbb3c452114eac7717c3db7f4c82d","nonce":"99de55204f797a570ce29e1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"11552f445a88979a56342dad91a2a8121409409a99b21ade50a23d498f2f2659e6e4c9758ee48927e80e450354","nonce":"99de55204f797a570ce29e1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"fb3ec7e8f5dbf001868abe8ed871256ad6fc12f6b32a4950f7530729f088cdbd576f4fa5271acbfe30baae57ed","nonce":"99de55204f797a570ce29e18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"cd3891de38ab1cbd8b49f7762dfd18257a0ad0c1d3b8759574de5301dc8df315415cae9b4353d938ec27fbbc67","nonce":"99de55204f797a570ce29e19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"0ee5cbde78ff73305fd292d265bebeb00a37a350385e33d0bbae2c70a70499456b38ce946618a402e1cf33fc4e","nonce":"99de55204f797a570ce29e06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"c1542836d9d8ed2d2f8f8efb25cea331ef37dbb2cabfd2e0280d573aa7ecce6da78b6f3032a2b2e7909a3960c5","nonce":"99de55204f797a570ce29e07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"ab6d72b14693ce2b4f4ab3c4513b93d7a4a4fadd821bf6cbb5b741db4662b07efb12c2a10ff07d23b1748fa6a3","nonce":"99de55204f797a570ce29e04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"72b60eaceabf7970787d502424c5b74cac2d4bfdf5c31e7469c3e82eb8716fd9dd2e1eb0e197bb996509aed2da","nonce":"99de55204f797a570ce29e05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"5c756f8b344f4355deba3e10fe9ad549cfdbd95ea21bbeadfe0ea9cbbf679da22fee977f319ce3c8ba120cd1c9","nonce":"99de55204f797a570ce29e02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"eaa9b4a51771f333c1d6c7998c3e2cbddfe6ef02fd3f11564d43cc7af1b054a1ee4edadd76c8488b2c205c7d9a","nonce":"99de55204f797a570ce29e03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"2ed8513bf7d5292e0677f4acb218267b53f7abb34fd0024e2827289552fcd4b7673df7596d679d1494f32a3c61","nonce":"99de55204f797a570ce29e00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"73fa6b0f188d011f7083a7407dc4b6c02280d2ffb268f966edcb3bfe09a58756612a38168bad964867afddb840","nonce":"99de55204f797a570ce29e01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"68beed107f1fc9906cf33a16cd7df493c4bf9fd96c6957d336d440f9ae3da93833b5dc3d53b9acde589427d289","nonce":"99de55204f797a570ce29e0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"0d59bf9d59dec887191493767e0c1d5eabaa969038180fe471372f2b5b499fdca33f49fc97f611a94b96930607","nonce":"99de55204f797a570ce29e0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"dcdeb750c7074c618e797bbd2df074a4207ec31ab43b45791567ddb3f19bd551f7be2dffe5edf288c21d8f1b3b","nonce":"99de55204f797a570ce29e0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"4c18097335a2957dd62f101da06504afba913fe0cf76e40e6c2aab542378c785f5afd48f045c5a5778c86405ee","nonce":"99de55204f797a570ce29e0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"f6fb307017dcaf69472bcc5434963ba0a132a2df6dbf8fa764ac4bc28959e051ac5bde0a1afcb379243d8eb964","nonce":"99de55204f797a570ce29e0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"383922f34b7ea6993ba1b66c3ef4d6651343356ec97a3f11b7dd57ae5b499f126987bfe9340d1d13e5dc09edcc","nonce":"99de55204f797a570ce29e0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"f2a148bd98388f27f95fb6f40bcff0157003cd9489146487f92e724591330ec6f840cc631e41f35baf98d20ecd","nonce":"99de55204f797a570ce29e08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"3c6f7f89a039ac1feed808528b39ec8fead8f0af0b801c59e4ad9e61a18e3854c1b62d441711ca8a7cfd0514dc","nonce":"99de55204f797a570ce29e09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"2c4a85da6a314b087f55a7d354bdb3bb6b1282853c910d0de6e52c4da7f30b2d5cc7ea79cd3d6a6bd4249f5540","nonce":"99de55204f797a570ce29e76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"33725e5918dbab6c72ce457430f6db49ea043b07d162502d3f37171324436efed531babf7fa35b4affc49fa1df","nonce":"99de55204f797a570ce29e77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"61ad273a5b3626352ad90eafaa2bcd4008dc33e555f62c463235d4cc8a13354768cf4c1b1689b086917e142282","nonce":"99de55204f797a570ce29e74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"2bcc2b884bf565bdb4fbd193a747b7cbf5218164729119fdd2fab09b2ffff60273cfa205a0d16d7e5beea6aab1","nonce":"99de55204f797a570ce29e75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"bd149547c197b0d919d07d98da2be1752842b73ec70526e57d700c0363652e29720186c44eded600e26e338324","nonce":"99de55204f797a570ce29e72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"3c028eb86b6cd45f4aa02eda48719f1015708608f7d9fbc96b54e7524b1fa14f2770057d1c6b67a29dcaa2f651","nonce":"99de55204f797a570ce29e73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"35b42a60dd36755a1a05c86b340f0ffd67d7c3789da7ca25223a50cc34a3c18e147aa14a99609c43ba5c2f9a2e","nonce":"99de55204f797a570ce29e70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"58754c0da5b6f84cfd93174c067a94cb2602030f7b99e4b796a0d513228cd0215636621d3375774a0b29ecd32d","nonce":"99de55204f797a570ce29e71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"28cc1ca2e71db0bf3cfcfacf8c517041ad2ac65f5a26f6837b413a56a75b8124d1b40eb9832f3a0ecae8f52cf5","nonce":"99de55204f797a570ce29e7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"0a181dca3395fc2dd866d32555f7767c35d67d5a0fff08dd63262c95057209b0345141b3aa3e3a1281b7e4b71f","nonce":"99de55204f797a570ce29e7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"e4311a902d34f36a82f6e1d307d956846fe5f06390ba0766b9dc2c211d6bc4800929c6a3350cb642fa75e97824","nonce":"99de55204f797a570ce29e7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"5ca380216a64fa61424c9abe4b72123bfd75c15e0742efa910a10aecd1892a054622fbe9eae98961272e530282","nonce":"99de55204f797a570ce29e7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"2e27649f669c5e133531684b8749fa07f2338267c750a106324c4a3ab5668ebf76e6adc414dfeaa9fc08068b92","nonce":"99de55204f797a570ce29e7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"067bc2cacc1cafc2158c151304b636828269de9480d5fc7adb21fa2f53176d7d1d1a7f02682e5b9dafe3bd8d14","nonce":"99de55204f797a570ce29e7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"245f73c4433b7c7f2d6d04b12568bfa211865a9397a0cdac6065cb1f16cdd99efb5a209cec739956414877b35a","nonce":"99de55204f797a570ce29e78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"679bc593b6aca643d6b69a3dcdc91024ed5dcedd3c9a8cf886300be443df2ca6e7ceb5f83062cfd685a29cf45d","nonce":"99de55204f797a570ce29e79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"558b1dc1195b6d1fab152d8786f1c6e7b8c10ded0380357d2c6bd7e71109340e41bb726af460a968e9bdb8931e","nonce":"99de55204f797a570ce29e66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"a24c942b6257e47243c24a99d02dbed121e09422eef784ef39f90a95ed45bdb0701ea31cac91cd4833ab47e367","nonce":"99de55204f797a570ce29e67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"1c09e4f97240f6b9b639556008a63aa1baad5d7a12ab85e9d468eb493661e9f73ffe64c5fb718e0ccff11afb68","nonce":"99de55204f797a570ce29e64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"4ce5f20b689b7e6cb96f5e3c41b24f3f17502c77840f23b41b11e80dac415c7ad77b3ab60ef13f3adfda5cd04b","nonce":"99de55204f797a570ce29e65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"ebee38ef124240d9043187fb52b274c3954475c0b54c72671a653a5f605e09da65c4811b693925732d524c46e0","nonce":"99de55204f797a570ce29e62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"5b3d966525315d38a4458452579338a3e723888b0453e0be7c017c70ef7390d55f407c8c44ec515bace53ead47","nonce":"99de55204f797a570ce29e63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"867b5f22369c6dac27091ce421b4fe908e9d016f059cf3d59f419434045c420403768b2312111bd781662a2dc1","nonce":"99de55204f797a570ce29e60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"86ce973a68069333d9082fa20eed1445b4330b02c3f68c8473c46538e31e1d91243f5c6fa9909fc9343acb4337","nonce":"99de55204f797a570ce29e61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"6ad0f395b91ad4f4b7f1a159a54aaaf48f30384573404d870b83aad7173d85cfd24528056012d13b4234dbea9f","nonce":"99de55204f797a570ce29e6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"70c52a2919d1471925d22089cdfba5b0bb5412d91e94425d036bcd48070886e957b31ed8d9cb476c33ca874151","nonce":"99de55204f797a570ce29e6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"740f36ea56cbba2a773ae57aab25317ac66251e9fbb0dec399f8c79b3d93327d069bba041fc03337f291635bb9","nonce":"99de55204f797a570ce29e6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"f1fa1ebbefb370ea9ea6e08681ab1cb912c9b4db36b0699d6f64629919f51ceacab6267e787cadbe5e19fed582","nonce":"99de55204f797a570ce29e6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"da1e4347077f16cde51197de8185af25517bd813a3f0bb0f3f4118aab98e989fdd3b5c67f20d2421c710eb4ee4","nonce":"99de55204f797a570ce29e6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"2ac9bc7fa2a0b6a5e4a12fe16d2604008a95632244b5bab42a59c3cbb17f7fae2fac86fd86fc15aabc51bafe13","nonce":"99de55204f797a570ce29e6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"23b878a172ce1c989efaf020f77597a379392ff7ffafa47d011c0740663bad5429e4c2ff93e546f0bcf29095af","nonce":"99de55204f797a570ce29e68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"0f594b8731747d071b987146b34bf009841a8b12f9690a68dc5d3aed60017bc9e242bc2ef7922df95a48ddf9b9","nonce":"99de55204f797a570ce29e69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"d77b9ae37cbeec98f6198c86ad071667e6ae3a367037aa1a11cbfcc554548b5ac12257ffbab3dd8569bc8669f6","nonce":"99de55204f797a570ce29e56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"436ede10406df67c60969786e2af37b3a10bd0350babd007eedde77df51878d41bbe82f44b2280dac22449f9b8","nonce":"99de55204f797a570ce29e57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"9eb1e06281300722cffe7c02315fb04800966c4d148e1ef26b0d8842aea0bd71aecefa4385d65f4a22c0f5c649","nonce":"99de55204f797a570ce29e54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"af485a20cb9f2c3d3350f2aca1f2d7d0eff29c835cc4c24bbf615adcd49d152bbe8e511e885a0c5d88115f10a2","nonce":"99de55204f797a570ce29e55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"62809f74354656e0057aa06e9adc1786844cbedb4d2711da653012f4e8cc772dbc42844a92943de16aecac1692","nonce":"99de55204f797a570ce29e52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"a70cbc3942775ebf15647079c8fdfa6eb5e4b83116c7c33942c3e4c4159d254beb70748c6aad0e8744185319eb","nonce":"99de55204f797a570ce29e53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"e2f11fbfea062e082ebdc47d72e27a3a852a99ba1a5344f25cea3e10dffede65eb61272f924b04668385b9b99c","nonce":"99de55204f797a570ce29e50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"4f158afbd7606c7f2465c38f3350a92be2751622c90d6840b5dc119bef4ad5a9bd3f5b0efdc60bb326bd242d3b","nonce":"99de55204f797a570ce29e51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"a89ae2aad6d9649a51448a3d056b78aebe14e59fff5fd10f32088e2f1839a634b5dd7c0b5d4678f5ade31c4a57","nonce":"99de55204f797a570ce29e5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"27e9f254c12eabd3637f74b3b828c227e2d5cff26716379a16d958326c532ea83f981a3dea37191f75a12d74ff","nonce":"99de55204f797a570ce29e5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"cab2e684077c3cc3681817f401b5efd9d91b517f2ac898333c1de08d5c2fa990c4de690fda5224fc2633fc82ac","nonce":"99de55204f797a570ce29e5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"21a2f7e1f56630a8ec8cb9cede4065c6bd464b5f27e4590108afc08f7879242d0248973f281650124691e996f5","nonce":"99de55204f797a570ce29e5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"09708530a419d789f8c601c9c220f84caac826b0117e320a982e7d000b6acae0084c7dc880addd83e919ca669d","nonce":"99de55204f797a570ce29e5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"2fa8f7050bc5ff3a22667ba78efa3fee82b05ed06c75798cc0251075b7a7e6136864cd465efa77fd8576e9910b","nonce":"99de55204f797a570ce29e5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"bc23e4b6efee7b994d16c74bfa6a2d27ef1977ec6381b6c567e0cbc7e6defac1e6da805bd64fbee2ec61219806","nonce":"99de55204f797a570ce29e58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"99e827121adcdf3469190ed1f77544bc396edae7661dc0aa2fca072fecdbf91d0a676213ca3613b2a0f054a9ed","nonce":"99de55204f797a570ce29e59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"d64c33f61c8c6d9446ba74466c259fa4b63f96da4402d58d68374829fdaf0e4ba4dab9be890a2cb58b08c4c904","nonce":"99de55204f797a570ce29e46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"7bfa0ecfb0e61589312b93cb653b900d8cc1be15b7259134604335dfc9b33bed348379eefad38ff9fa62972b54","nonce":"99de55204f797a570ce29e47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"d13a405bf3ba4afd163a456eb225caa8e5276b7d3f9909425324799201d5b64a93c4c5d29faeceb12048546335","nonce":"99de55204f797a570ce29e44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"8afd9e55d1b5ca2e1a64ce802735949942bcc080bb341a7bac1368ab6cde83728faf238738e14c349157d2509f","nonce":"99de55204f797a570ce29e45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"e182b327f42a8014b6b96adb138d298d003afcced5e9de13ec16bc35f4d0f20ca050286fd9a3a49fa6ebb3b11d","nonce":"99de55204f797a570ce29e42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"c317c491cbeb957f98074d964055bcb05ba62ed07e1ecb39b84dd210844c6f33cb0adbf7ea0ee922069bfe9e70","nonce":"99de55204f797a570ce29e43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"4181200273fd7d3011dd5bd574d48019bb2e25c6a9f5b25b4f2747eacf7829b1db2a3ee38e5a0b7a06162bcfde","nonce":"99de55204f797a570ce29e40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"4d372bfddaf0c6b9c233d273b09651cfaa0f2bfb75bddc60fcdd4df802250abc7e550ac81eca85f60420a3ec85","nonce":"99de55204f797a570ce29e41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"7249312fc97736c73c24408df8b24ee6bc6e12873c097fa900aa2242877df467a757f9b8fce7870aca679da9ca","nonce":"99de55204f797a570ce29e4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"c9f12f2633c996dde5d71a24a808e045d43ea26d855e3e2b9682543e57b6d1420634d0c632babf3aa39e920eff","nonce":"99de55204f797a570ce29e4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"e7a33d48670648b97fec8cc1feb11bcbcccb1d0f0d4f286cb911faa616a5997ebc6bdd83eb222fd2b0e044a21e","nonce":"99de55204f797a570ce29e4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"fe1ff738fcfaac21bea9155dd0e2911f7d29eabe71caca057bf59a1d35d34a88b3871844f43c0139fd2b1aaf0b","nonce":"99de55204f797a570ce29e4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"40f4d0474a7b9f57205dd98dc909099f5d58e3ad008c0ebea3a4279dd4be57dc8ada96ba1c73e343c7a5671b53","nonce":"99de55204f797a570ce29e4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"08a887ac90c9ed85fd076e2e3ecc9bc80acf706275aabe020d9f217da41572a6eb53e0900fc924f20729c09625","nonce":"99de55204f797a570ce29e4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"a6b546ee2e07ca183c683a20efa8dcd5a8020fb399c248aa04a1b7b9b74ac07e5b98d2705361a025b8a7189a3b","nonce":"99de55204f797a570ce29e48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"d8b9423791298caaebec820b88d6ec1b5bef92bcda4a0e9c411c02144917f42a861e90ed94e512b7007f7df77c","nonce":"99de55204f797a570ce29e49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"aff593d03ac363dfc45a32f2fda1d8c62c3216a86e9c68bca44cd56d9d11d65db93d247e4f06680a4798f8d3f1","nonce":"99de55204f797a570ce29fb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"f161d54072f7218fddb41e1b25973a58fb2142cbd545aeb29e61085f04868a65"},{"exporter_context":"00","L":32,"exported_value":"e563b4e8d7edcaeb756af621d699e8fdc9638aef523e12101f1380f40db852b3"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"cbe63cec255084df2977902b9bb85544498c9fe0538afc543f748cd58e8d7694"}]},{"mode":0,"kem_id":18,"kdf_id":3,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"28b1403adcf3d2bba7d7c733df4ef8ab9f4c2cf92c840beb7de3fd139611a95be850589a49825450c033b2e1f6cb66127c83827d5464fca1e427c2bb31bf18e857e2","ikmE":"bb8f0c6c0d81a0a54d6084e3d7d8001875ce2b4831400075246ddeabc3f62d065d91fa8f2ca0cfee3a94f1fa6f43f53a2e39241ccd5ad9f0d889aba103e78286ca17","skRm":"001926452a313ec1ffb91ec82081e0c2c900594cfdfd0f83391d1574e887fa9e9e49fb1f3cd9dae4c230c932d043d4def44bc7a68780a7c94ffe643e692245fda188","skEm":"01a33bedb85d1993389a3e524477411c8c088572e2b3e160eea59b1a074626262d0409e48ce9fc7ed4af8e298669e20646895a6460666b23867135c549ac8ef45c96","pkRm":"0401cf0f6149f3c205096fb29d415a38a3a10c5e882822b582220ae74230f78d183b92824fb2b1d9b005b8af49c43fe2341f210d5262da9b97bb3ae750292656f63d39001b4b39296e906399e82a2b4413a3b2ff2b2657a166c1b85926d33190ad79f7bcc8b0a80092e93c6998088c87bb5bb372e596b902fbf100f2fb0a24f6392b4a444c","pkEm":"0401f1f6d9583bcdaf771212a996542e370a73e9e36a207eed1168f4142a139832f9ef2f8fc87664f3d9074dedca1b01c2d46b5095e3f0d561ca9d364dff041ca6f3b400f782800038ea8e52a752f5ffaad25df0e971c53803199c7f0ec96283d874d9184c6d6f74d5bc9533b91d6b7183a073ffb8d0d1d2006deba12e10529fc64ee025bf","enc":"0401f1f6d9583bcdaf771212a996542e370a73e9e36a207eed1168f4142a139832f9ef2f8fc87664f3d9074dedca1b01c2d46b5095e3f0d561ca9d364dff041ca6f3b400f782800038ea8e52a752f5ffaad25df0e971c53803199c7f0ec96283d874d9184c6d6f74d5bc9533b91d6b7183a073ffb8d0d1d2006deba12e10529fc64ee025bf","shared_secret":"3283c13d50bea6519df780c0724eaea0d6cdd3e4d28f0bdd6e9be331171f2db39a9b02167f0dba3fc3e7df4ccd9dfd02fc8ac67d535ee08ff5a287884198a960","key_schedule_context":"0083a27c5b2358ab4dae1b2f5d8f57f10ccccc822a473326f543f239a70aee46347324e84e02d7651a10d08fb3dda739d22d50c53fbfa8122baacd0f9ae5913072ef45baa1f3a4b169e141feb957e48d03f28c837d8904c3d6775308c3d3faa75dd64adfa44e1a1141edf9349959b8f8e5291cbdc56f62b0ed6527d692e85b09a4","secret":"56cf3fbd135b2c3608795e6ca3fe7b70dcf787cf7923cc573e66883d33f0217de29149cd536b615666ab46384e8dd1edc43c9c0f28ae84fd31bd9a913114fa3f","key":"862fe13e4860e0673e31c9f3e19a7190faa3a170b3aca6042e1879687890db16","base_nonce":"a6e3f71000879a06930a7e10","exporter_secret":"fc45ac88c7b8e3d498a5e4f704b864de5832c15f80d0c5fea9e4bb52de4cff821b2f25b8d52e93852524be6a751de6144d659758f85aba6639babacd325bb8d6","encryptions":[{"aad":"436f756e742d30","ciphertext":"554474e2bd659202052be4a523a85b323ba8f79368794b03d9a737c9f0515945fd420bfae77098cb69f1c7c167","nonce":"a6e3f71000879a06930a7e10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"168e20a7c425ef17e90dc57c9f2a66273ac5487eef7cfac9e5013791dcc6c27a163acab4e1fe0adf35792c8327","nonce":"a6e3f71000879a06930a7e11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"50afa46d709c5f13a29534b2f4e5401c42780c0ab59c564e37e1bb7a04f7af4a6ec3da77ff499b459888d39709","nonce":"a6e3f71000879a06930a7e12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"6a2c1a8bdd659f9d22b16841de453accad75ab7d29442bfdf28e63659374e4a844cfb92cdd02776e7a401a5892","nonce":"a6e3f71000879a06930a7e13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"94a72b9d570c131173cf4228d53e8ad55422cd55171b6f117d636bd7d069fda14376262790e0db47e6223d78a9","nonce":"a6e3f71000879a06930a7e14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"0fa4f06e45822fa1d90e6b4fb5bf5738281157cbf2492ade8a36c1d3a5f00c5251ad8e35ab7a522d58193e2e68","nonce":"a6e3f71000879a06930a7e15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"817737caef23402bfb1d8451a7dca09f16adf8cf03c0bad0cd1efd1bc8a7a539d0577ed386b3e6eddb3ab5614a","nonce":"a6e3f71000879a06930a7e16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"4947dfbdc4702db2029925d3f9015f73e0b2e56e43ae689be60f8727bb3981dc27217d730340b4b9cd2c3d69f2","nonce":"a6e3f71000879a06930a7e17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"b2866a8460c03e8b850d6f4dd7de4c953a42a32819998d115280563e732c119a7219b17d2be9e648b114ac1fb4","nonce":"a6e3f71000879a06930a7e18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"8f1c7a24c19de384a602cbf16d220da7e5e7b536f6bf8259b28e4f9aef851ee7ff42123ff5a4f729faa515ad5f","nonce":"a6e3f71000879a06930a7e19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"169392aa14fabef6b525ef1fe7166c0d5e084b60f3bf713042264ebd1e81dd2c5dd977bd2cd8b9696a22ab2797","nonce":"a6e3f71000879a06930a7e1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"28be441ae7aa8333f3866350b33f6e96a1cad612d801f3b2947c73b0ef1427c2917a0fb53898bfbd97064cbc95","nonce":"a6e3f71000879a06930a7e1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"c8b486b39f1451b4d0bc1d48b9570eb4a6f01651c045b6db79da54e15dd07df4676c3bc95b86ac6d3f84ceb95a","nonce":"a6e3f71000879a06930a7e1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"2f7be11566908e9d713f4caf0d9432f35ee4742b772086ddbc18a417d841fbc9efb8549d02b539ed885b315c5b","nonce":"a6e3f71000879a06930a7e1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"e1c0475bb803bc8002575bbfad54474b7867196ba88c69705035acaba06ae75e2d2e954f11aaa02629716fd2b2","nonce":"a6e3f71000879a06930a7e1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"d6b05be4f0bc39032c918a8c70aeaee167319a877cc23ae9fd6736a271ed8f6d6e1fb04504966c82cd1303487b","nonce":"a6e3f71000879a06930a7e1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"7c0cda044e3f8f1cf16477b8db921077d1836ff6c547da927236cd5515e7d06f2aef246dfd4ae32adecd399f57","nonce":"a6e3f71000879a06930a7e00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"ad292de98965b80b6f1684c8ad5a8cb6d885aaa7f9ab7cd914316952dd1f1f65f0636c7407be076a9396125871","nonce":"a6e3f71000879a06930a7e01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"ce4a88c34f05818c4fb2c366b9249cad9665473b74f7e362953cc0097afbea80dbcb749cdebec1d9e1f73118c4","nonce":"a6e3f71000879a06930a7e02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"210209b5e233a5e9cbf9bc5b97eaec786d19d082f0e87c6c788111df4ec12266d23f90d7f37569a09c62442e84","nonce":"a6e3f71000879a06930a7e03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"dd7ef359ce3bb7a5978d74e45c27d30a33e2dc6c1e1d82e49d570cb22b1c92dea992f77592385170038f499206","nonce":"a6e3f71000879a06930a7e04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"7363f31d6f26d5c838eb34cd0df78dd698011a6edb93077296ff23d3c7259ad48dedd5a82a1a3aaa6b6109755c","nonce":"a6e3f71000879a06930a7e05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"9cac7dc520cec8dcaf75c221108b3c063454665220433e9f25c2d26dd6c53ac9482fd08f4ac24da27f9fa31c8a","nonce":"a6e3f71000879a06930a7e06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"d8d94f2109117c85c9f7c2110680b3d3fe032d958552c2b2f035dc4c328fe492f9545f9bdcb1d2cc47dff3ca2d","nonce":"a6e3f71000879a06930a7e07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"6b45b0da2196ec61ff97684706ef04e9d4b2ac62dd6217bb43b9d3446f961cfd71ea48c668ffb671f050d85b26","nonce":"a6e3f71000879a06930a7e08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"9149ffbbc03a22d2489cd1ca7fa5a5039edb40c1831933bb19d681c41e263a9ae51ff1f680c44754fa65f97aab","nonce":"a6e3f71000879a06930a7e09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"51a3c24f646735d50971c30ee61dea4794de7c6c27320d988305ef00a18d3ac8efec90c61b476681491830164a","nonce":"a6e3f71000879a06930a7e0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"fe20dd608cb6a9276eee4c67a2f5c916feca6d5903ead796219699c0d167c9aec69f439706647a709e31f79564","nonce":"a6e3f71000879a06930a7e0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"e88d1d2b7274864dd75384c2f2137ee7d34aaa3987d9fbfa7c2fe15a549adfe74842001009d2080f15cef18f8d","nonce":"a6e3f71000879a06930a7e0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"d3f8285bcb52a585f790add67e3f1fdcb96e9d9ced314e6d9f9c70dd5fe19a0f389b6221fee5c8f3adb2317c71","nonce":"a6e3f71000879a06930a7e0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"097ff244460200bc15f2ef37fb46697156324075b14c8730c667041c4fa3f09092de75d2ff185b1013cad9b923","nonce":"a6e3f71000879a06930a7e0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"8916b289b0231d3f57b1f9647205a506d23165bac327ba87e98386da4282f20b4b5e31a7e4773ee76ae4a6ad74","nonce":"a6e3f71000879a06930a7e0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"c749cc2d14101cd84f2f952074a4f8d30e0d10e72d92904f5c61132c99e87ac37910a1df4138c287ad6d9c1699","nonce":"a6e3f71000879a06930a7e30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"2b33f7b1613d6ebc9dfc71af41cf1c4f69065366fccd0717e9b77971d6988998180443869a408491c76c1d593e","nonce":"a6e3f71000879a06930a7e31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"2374328f037d0d3822554312536986ade7b922171f96b478f0bacd5630e4fb885841c3b1cbf278741de70ec486","nonce":"a6e3f71000879a06930a7e32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"3e8f866bb8b0737e37c7d2cd58cebb311115c79ff5c407647d4a565de7c7c5868b9c153a9715664927c54e5a21","nonce":"a6e3f71000879a06930a7e33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"a44308223f400c32e455571847556abba1f19f74572bde338362b8eebc9015efedf6e89ae5c414a03ccbeefc09","nonce":"a6e3f71000879a06930a7e34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"6fab731437514c331ac8d3a2037e3d620348173c2f530850ab2ae3cf25d19245ec074e1e93a2046e1125796464","nonce":"a6e3f71000879a06930a7e35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"9f1696eb3718d5842b8f56cf308fed8debb637fcaf4565d30f3f4dfe002d2ed3f5af25fc80fc61006b2f0cee52","nonce":"a6e3f71000879a06930a7e36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"581d81a163b527c551d65a1539b9cb31fe540ee4773ac3eb91ced38afd0f8fb7064b1aa81cb85d9f9609891692","nonce":"a6e3f71000879a06930a7e37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"31d9516b833fdd5372b675b5c8bc595fe861ba44261b8d0da595bfc739175d0b840a7199c3a20123a0cf35b4ca","nonce":"a6e3f71000879a06930a7e38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"3976841084e208eda50f3ca5ecb6ac1c38eca8ed5c4aae6429141c662cf5e0577045f164fbdd676c9e05f277a9","nonce":"a6e3f71000879a06930a7e39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"e393cd6a2ff3593424772b0f961ef9d9dc027fe420b272db897c4e370024dee3fc284192b510a8a11100c1a514","nonce":"a6e3f71000879a06930a7e3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"83e5e4b474cfafac6ad8c040242a7d4337a3310c5a4d0ff990ce21eb12c587eb5e0c7f847908a593ec29b6cdd5","nonce":"a6e3f71000879a06930a7e3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"2228519119fe1c893b8a62a629c2fe8b7aebf247c5acebb7e9780399a043758c5a76e7a39df23458808c3339b1","nonce":"a6e3f71000879a06930a7e3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"66a1f6ee937a54ce1c3b33a8afca8229acee3d0fc636b335644c3685306a4c1520280c31bcab23087734e7658a","nonce":"a6e3f71000879a06930a7e3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"3550aba8c7802b489081eda7457d31360213ed22ab89f411a8c3c4af6ceb10bdd4add63225c103e8e3d6fea3cf","nonce":"a6e3f71000879a06930a7e3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"c682c5b6d57ac8403eb34b3a175ee14f987e8ecffaa7292c75c4ee3267d441ff71ddc3bd2c4febc484f8355e02","nonce":"a6e3f71000879a06930a7e3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"2106da3d3887c357d54f88e056c7f903727c717de110f221d5629485417859c2c3e5009f8736455590184a2350","nonce":"a6e3f71000879a06930a7e20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"1984a17ae28e0f2a373a7ef1a9800b9e5bef7d879a9988cd0dbcf1352feebb68c2467dbba659749c122f3597fa","nonce":"a6e3f71000879a06930a7e21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"7224071728708bcaefb0da55b7167a9b0093077b7365de4a59187d5cce88c640c30c1a1f8340b66f6b3a01a642","nonce":"a6e3f71000879a06930a7e22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"e80a2caefdfaee14542efb76779aded747488cb293d9275cbb9555ff6e77469a8aaa5b1d689a26e8e39d6d19db","nonce":"a6e3f71000879a06930a7e23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"16d954b4cf4e68e69eefac2b3634c9d24dfec2585eb08bbaebc2033e3fe8fb659fe3c3f215d515f6be3ea15eb7","nonce":"a6e3f71000879a06930a7e24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"cad833a8024a65841187005b5eb130d137fd98e990aefdce130eb6a09f2b20dd889e28f1f9eeefd5ab4181111c","nonce":"a6e3f71000879a06930a7e25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"a250cd0c4e27d441f124330173927a7550304b2684709a7bde2f7364678a240478a5114ad0ea828c391c181362","nonce":"a6e3f71000879a06930a7e26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"1cb4cc0f4b18b64206644d01e5e4fa6b14a97b33406f15ad625332e06f0589e309c363554b91fe5cc950a327c7","nonce":"a6e3f71000879a06930a7e27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"2714110273ae010f06b771b422d2c7ec8c2c32f7cd4ac81be9751bb19543722ea199666dc5db4ca81ab445f49c","nonce":"a6e3f71000879a06930a7e28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"6f654703e3c6322b37928c362c28d68fa15258ed92660e70a2784eca84f9981b611dfbc135b7c9c5709f56e62b","nonce":"a6e3f71000879a06930a7e29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"c07ea03a3d1e73c62f91411ac9f59ea34bc611d0d3b223d6fda77a6fb5fd4e3cf3767a5c659e16eadab03001df","nonce":"a6e3f71000879a06930a7e2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"d5852a80da1d2c64e4f88c42938f2a07e91d358fd3c03d86163353cdf3c677c6db83a14ccd68b9058d29f0d6c4","nonce":"a6e3f71000879a06930a7e2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"ab8a94dab7eac257e4b775fac339eab31af1ff876aa071ff0b98b07200b5336835e83451f4048c558013c7604a","nonce":"a6e3f71000879a06930a7e2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"f873ccc12a92ce063f2376492bba8d0241fe013d66cf9367010ac29738d0aa4270575963fc40720e0cd5ad3be2","nonce":"a6e3f71000879a06930a7e2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"5e8a0230288221dd91a57cf28911eb335da428422d264ba6849ca3bc74e8cbd387daf5065c71ad826fa9359c75","nonce":"a6e3f71000879a06930a7e2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"415e101c1e7a3d13d0cab94bafebc66c4c2573fdf0e0852be0559b42a2f25ef86c28e00202323788ef45016dfb","nonce":"a6e3f71000879a06930a7e2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"b8a6d7cc5adb31bc68504cccdf26089bce059cc97c7b1ad475f379a94ba09cbcb535acf99375f9f5bd7fa277d5","nonce":"a6e3f71000879a06930a7e50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"e591289c7891b7a38b7070148e9ed1a98859d11eb046b0f6efc533d96264e0b06bb2aa96a33de1de3f49e2d125","nonce":"a6e3f71000879a06930a7e51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"bfc0de409e485740ab36f45fc89f54a81164e2bc8bb4133a1c9e9e67fdd69ed724b688f9620bdd77ec9f827a02","nonce":"a6e3f71000879a06930a7e52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"db26839fb7f470f6b0ba235908d9df9f7471bd6f99059ead36b73ca1da15cba98502e7abc06a267c40d7cc9096","nonce":"a6e3f71000879a06930a7e53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"61e99a14832d1590d9ae6951f0ba3aceb40d6b306c8400d9328d87e99f2f97b9523ab827dc5a0ac0acdcc7e7e1","nonce":"a6e3f71000879a06930a7e54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"222721fe7625f919ed4b895d9a190ed07d9ee90bab2ef3d0e20144962ade1b83641064ba252006279c06e9dbb9","nonce":"a6e3f71000879a06930a7e55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"a151be3d6288bf71c03f1b6f1774f3683da58532e56b381ecbe1b104b0e777d0f255c83df7bbc7f5114f6549fa","nonce":"a6e3f71000879a06930a7e56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"48e8f19bc34336f88b354e2959a7854d6987b7179b6b3d80ff4e25e921f2172bde7a176bc7f464f7e741198998","nonce":"a6e3f71000879a06930a7e57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"00f90c65e628c986fee3f3f4f5750c22746dc34146de782ec7ce89398b7f43036b66089c45bad641ace8911de9","nonce":"a6e3f71000879a06930a7e58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"33b0f80b18b9545a5a421b2b3734098f5652026b89b96a7078289a28668e3b5ef7027f3e7592f21da4832b7e29","nonce":"a6e3f71000879a06930a7e59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"e43416313aa9fc854462fdec5a45c809df04459a57d1789f36e7f7742388cf05c04d856d7bac2a97da1a61d6ad","nonce":"a6e3f71000879a06930a7e5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"79c334525f9673725d75e5187f9ed674b2f9680f81e42b4ece8f8fa93eeae76679b5149bdf6afa289cb73c7550","nonce":"a6e3f71000879a06930a7e5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"8eda9061eb477753c6cd9c3d35ad1846b7f1bc6c83e976b6a70f051bf7ff719548bf09ae237f76315c6548981a","nonce":"a6e3f71000879a06930a7e5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"161add292bbd6c5ed78ff85b91851793ded2995e23f200c445a81e88fce36311f7e215ef2ee73913782ea90038","nonce":"a6e3f71000879a06930a7e5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"fa501098ee2bf549d5187df9323e78a7b76fcee9f1a761d116827048fc2eea283a122d682eb64c0fb20e952933","nonce":"a6e3f71000879a06930a7e5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"c637071c7b894ab5d6e58ef205f351532753052cc4b101ba9c956bfb6e1689fe77748b124400ca4c513580495b","nonce":"a6e3f71000879a06930a7e5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"c227d97ea3ec0253755ca9e17c813dd8f5214eb3314202689f45b99e9487f09898ab96c9f0b5934085d4157373","nonce":"a6e3f71000879a06930a7e40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"5cb4453188032a7a47719afd62011bcb09da7cd400a113771a943e507f45b957fe89169b501e83553fbab0d65a","nonce":"a6e3f71000879a06930a7e41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"857b7db240670b3e2d510f9d69d96b2ba649033f8a9586a4f94774da532a430da02a51c89c4964f972584e19b2","nonce":"a6e3f71000879a06930a7e42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"80594071ebc9b8890c331f6b3fc0c565d28924cc0feeab9852eeb977697c065901cccbaa376ece3791c24bb59f","nonce":"a6e3f71000879a06930a7e43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"0a079d1ef5676b08384e4e620daa29a563c2d505bad3282385d5a7e4c0804db17c5ee011ef1cbba53fca07a3fb","nonce":"a6e3f71000879a06930a7e44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"e4acfa8b577a02c665e177615402e3c5b29b4a965fa1d8ee76635e22f89e8eecebd82df2c066f8a5850fe89c35","nonce":"a6e3f71000879a06930a7e45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"2624fd5c60af73256155a6863fa008bf457db5f167cce7a0d319a2ecd32bc25ee6ba5947c7dec588a667c10b3d","nonce":"a6e3f71000879a06930a7e46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"92524e754e53c8483eef7d33216c14bea5efbd1c7893bc5c4d25e161cc5dceafdc0d3febd8eebb4e8b633e9626","nonce":"a6e3f71000879a06930a7e47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"dd84c862371c566c839b7df3b18af9e3c9c4e0270289ae148c354746d775536a2130f84fd8aeafafb9c13fa70d","nonce":"a6e3f71000879a06930a7e48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"5fb1cc621c0c8c00239b8d070f9b34df77b1a4e8d02c773fb2d2d72cf59dd2153b866f424e257ec52592f536f8","nonce":"a6e3f71000879a06930a7e49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"2dfb3fa9504aed43d1bb311edd48a9d940f8ee1449bda08784633bb6716dbc58c68a600540b088e1ff54321b7a","nonce":"a6e3f71000879a06930a7e4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"0bed8fd9df40366a7563549c01ee93d8f0e2ab1c9c108019a1bd36af4407c618279d4f0319108e3729e5dccb48","nonce":"a6e3f71000879a06930a7e4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"2788f22dbdd4a980bde92ef4f5d5460cde2c5700d0762c2359ad2c8c76a64e3914e25f1c0c45a72e1b6dd5e15f","nonce":"a6e3f71000879a06930a7e4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"d80fe76b50cfa99a2f33cd3bf447d265b84f0fed688928a168cf88dc638ef6d86fa4da4abaa2b905f4a0c9fbdd","nonce":"a6e3f71000879a06930a7e4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"6781783d37fca9cb2d060b0e9f14f4c44fc82b31b47e3279c3da4df147675e9c3ddeb6a756d815a88df533656e","nonce":"a6e3f71000879a06930a7e4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"a6d0bbadd66aa12b6feac20eb3bf8a38972cb35f6861fdac697aa7318ad7c1a04c2c1c38bf0e6ae430fe93679d","nonce":"a6e3f71000879a06930a7e4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"9a3d5296d1e5dfd01c8bd230490978a149faa5690fc1694f9107e61235ac21e223ec8aeb0ebb0a075d8944a47a","nonce":"a6e3f71000879a06930a7e70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"38a38e82eb93b757f39ad3e9a16cc4aabe4dfbc21f19ec49b60cc889748a90bf7a9a505714a9eab9c8aa157723","nonce":"a6e3f71000879a06930a7e71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"623b95029427ae877892fd4b1e596bc5a81d0bf90302096b9db1cff9d5847fa712eb5ec18c509d178cf5a8f30a","nonce":"a6e3f71000879a06930a7e72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"4d5bde40c2ad8080ba934ba578ab77c2e8316e5dbff68907f17a2938fd09ccc57fb1fed53f21b837cc1a0ecd6d","nonce":"a6e3f71000879a06930a7e73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"e8a700be8d026b76dedfcd7857e29aedf589e18f2450ca263e1fa717eb9736869dc29e47fed9879b76468807a0","nonce":"a6e3f71000879a06930a7e74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"bfba233420894c03294f45a9ebf5fc18088fad6d7f14ee93ee7eafae5a17ee48ed56656143a9ea14a77796d4fa","nonce":"a6e3f71000879a06930a7e75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"325a1c25f3366abe3a1e1da0fce7f6b9dfecdd174720dbde2928fafdcab6012533ed3162e6ac2fdc8bb01d2809","nonce":"a6e3f71000879a06930a7e76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"3d87fb29cebc93314e82e6bcf28a25f95e86a42bed11b9d2a4bca1ffd198fd15ace5a1b12003435ff46195e680","nonce":"a6e3f71000879a06930a7e77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"5a0b55d2af1320125746cc844875b349da7c48289a51ef7950e49f5888fb19ee4bc9c6dc6ac4fea3a1cd17e1dd","nonce":"a6e3f71000879a06930a7e78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"9c940e0c007734510a83036b6585afafb1afd82354e5181e1f729571f9bb7155dcd45615da9b577d8f3d572dfb","nonce":"a6e3f71000879a06930a7e79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"6388c667d47792c805f63cae47f642997afa550925c3ac10e35d366aeff4de60d87d33bad5e8de0f669624c8e5","nonce":"a6e3f71000879a06930a7e7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"9e57eb821847bb8962be2a4fe28477a248e37e8a2002f77b7397ecf7a14e87cb4d168f947e504aa12ab3e839ec","nonce":"a6e3f71000879a06930a7e7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"dc5cee22a2b7ce8a7889c739f61bc60df7348e0871c609fc90611f31a1a8391cd8870a471a62a84c16e6f99ffd","nonce":"a6e3f71000879a06930a7e7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"577a4a5ec11f85e123cfddbdf186910d7948f2f4ee2c32b6ea90f0d303f7fb0061180d28c4a7d363739cc91e2b","nonce":"a6e3f71000879a06930a7e7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"b57a4470411ad11491cfe2bdc5347ab84ac65dad22bf2401fb5a87c0f476260ad587a36cc4fea4730a4b2c9525","nonce":"a6e3f71000879a06930a7e7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"97b0f971446b8240d545b1ff85cbce6bfe9e92f1cfea8f9c8cd1c9a82be139de222b21c2bef6c89e61c226e9f6","nonce":"a6e3f71000879a06930a7e7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"976f985ce3aa91e61b16244aa6a6c3147b507d02c5573e5ccbb48c87cc08fc9e02055283280e74e9a2b15af665","nonce":"a6e3f71000879a06930a7e60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"4b3671b11f540cf34960c42f2ac4ebe7bd038862f6165ed23fb3e054f0a59abb30e5c8ec634b0f85dd39ffab57","nonce":"a6e3f71000879a06930a7e61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"1b895e1b0622f1fa9872bc764e6b1b2f6cbe61790c56771d1dc20bf5bb2d60ba96767122f39e5ee1689a5418e4","nonce":"a6e3f71000879a06930a7e62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"8b900e9d0377d0697bd34353dcd370780fda8a316369143bc3c797c967cf010fd78dd264296584c49214e3eb8e","nonce":"a6e3f71000879a06930a7e63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"c6be6d32b7f484af3c8e0a86819a8afffa951882cd8ca2d25b4159e879f36248929eb9e0bfbc997613e945bee2","nonce":"a6e3f71000879a06930a7e64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"dc0e336081f462777d35a3034c33d901b2b2df99e264ab86f5e78993d434727682f5bef0f5f79740b692e4a6c3","nonce":"a6e3f71000879a06930a7e65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"eccce966e7831adf3a94dcc743c4d7094cbc099a595912ef5a8b262314333a835942347469b540bc35faf25219","nonce":"a6e3f71000879a06930a7e66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"202d101834316c46c576a9e3af2ddbdb6c3a7a319be750812d3f92c82c82a3b19ca30e8d1f3a369ca74b2c0a57","nonce":"a6e3f71000879a06930a7e67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"ba2fe9968da0d1b5e85993d5c2d1c6f4184837ed444ea83727030e381174438f46ef1f8406346679c9f706e6b1","nonce":"a6e3f71000879a06930a7e68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"ae7b2f0cf046096cbf3a431251af757b00d3ebe61825cb40520ea0086e4f8479e934a1578ad1b372289de5182b","nonce":"a6e3f71000879a06930a7e69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"27254941314fb0688dae3092b280d187daa9bbc19ee92fcd9eab152c97746f7e3042949a65af5f66fd374e2f24","nonce":"a6e3f71000879a06930a7e6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"5d758a3799a3d9dec15e58e23810f346f05a8e93368c9fd20f60e4544b3e4f69e710a6986bfab4fb6169b695bc","nonce":"a6e3f71000879a06930a7e6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"bd66e4bbe3cbafe3a36f9fdb7d0447894bf24dbfe87c4be10be98a2bf8875abfdc8be6c0366dde969a1cf934dc","nonce":"a6e3f71000879a06930a7e6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"3d039b0076854adc21972d868f6b5b77221a215d08d358cc9c09f4f657c892b91c7471adbc1b0f6f732f38f0a2","nonce":"a6e3f71000879a06930a7e6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"94d1ff6be1555ddb46059979e68ace9d4a9d63eef0825bed198a5abecaac2c84ca4d2a055189c14a0b3984fb0b","nonce":"a6e3f71000879a06930a7e6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"6515bd562e735169c5619e1a42578dfdedcc5302764a2a0f222da0f8ed31869d806a216593c0e7149d6ab22f00","nonce":"a6e3f71000879a06930a7e6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"f2184770a2c82000c74ec424eb7857b82db8b31fa0b0a65771329f5d703cb888dddd95cfefad82b51b0793a826","nonce":"a6e3f71000879a06930a7e90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"ca825c14937a0a9f35313d775e5e576adf25b4359c03dcdd03136f2ce253226a59757edead37aeaca6379179c4","nonce":"a6e3f71000879a06930a7e91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"6f7729caec360afe67d89b4430177c3bb5be2baa0cd0030b3d313cc992bf768613db9faeb9ee9962ac13a292be","nonce":"a6e3f71000879a06930a7e92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"f9704ab2277f0f1b63aea76a983ed7eac7f5d024d7a3b9bf1f0f2dce2b0f1dc6b0871e27a2894dc644b5c6c6ad","nonce":"a6e3f71000879a06930a7e93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"dd7e5ee4445e5aac2088739f49c1ff98fb202ba71210b8c1eb8628b802ef07098a4e530c47311a0d18e42f60c7","nonce":"a6e3f71000879a06930a7e94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"05385c51f5f00d6027fa09ab9058f96d12e7a8b7327e5cd8176ffc2bc0c990cd759e460ffed0b3f0f9422ea2db","nonce":"a6e3f71000879a06930a7e95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"d1b90d11e7cfbade8d963b25ac1a34c5dd7be49d04577fd45151a9ed849b3f0075da78314bb922b0074e92fae4","nonce":"a6e3f71000879a06930a7e96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"bf292a191e5fb62a02852d92b10f2d0a8f49950cca5dd9a91caecdb00712384c06a3f17777515069b4a065ee5b","nonce":"a6e3f71000879a06930a7e97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"bbb941a8957f2721c13b7ae01be2293f638e4ac670f947b8f81e9ab77bb6404884dad17882300c1c022de4d90b","nonce":"a6e3f71000879a06930a7e98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"991bdbeeb4a3b40ba2e9f8342d6121e301d23b623cc4152f438c903bba4613a6eba1be21fbec0aafa3e1261bdb","nonce":"a6e3f71000879a06930a7e99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"b4686c6fc43e632626c5c96c021ce61f54747fa2a5770c8d2fe74827a833cc048c674a3d106e6004e6a3b72612","nonce":"a6e3f71000879a06930a7e9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"b60a9fe86f2f7441b4c4b45fa041fc059139bd1dde931a4da98ab9de0aee4b66c4471aa8e89dcc993c0a30ac64","nonce":"a6e3f71000879a06930a7e9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"1ec66fc9f2b94d9b3333d1c2d122844b513ea196b87113d7a5ef566c6326789d4774324b4587d1f90bf9002537","nonce":"a6e3f71000879a06930a7e9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"197595777e6a6ae53ca7fc93b00f43595b005554ce4b0522e554bb536f9477da6175e9ec72f6730380ac99cfb7","nonce":"a6e3f71000879a06930a7e9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"73aa29497c9ad040141f2e3fc5052c9278ecfe13140b22dd885106bd277b6a3717d8df558619031776394e317e","nonce":"a6e3f71000879a06930a7e9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"58908c31b0c7b9d5477dc17ffbeba844af8134ea731c3ce0b227fec006527b2ae5ef59023899f35109553d9313","nonce":"a6e3f71000879a06930a7e9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"6edb143ef6a3c4c9cec403618c1215e6ead2c12e153e7ad87e2194221ee0462dc4d937e512bb1c34e7ec08ee19","nonce":"a6e3f71000879a06930a7e80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"39a1ebd6a7261fa617f9cd465e35b98bdf7e677b2d714be0fd17e0b79091eefe4d7d88f36936514312a3810e00","nonce":"a6e3f71000879a06930a7e81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"ede767d7b308c98f05feaa3f5d26f6a934fc0ec0cbeb54daff4b49bf65df852607fefb44404ed9bc623b9c4205","nonce":"a6e3f71000879a06930a7e82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"00721142bc9ea81bf5b296ff0bf4dfa680577de1239e3e49b89d9c624e5c399f2f1e75093fd1cd00bf78e5da0e","nonce":"a6e3f71000879a06930a7e83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"aab0a0b8db7b108cb39f9134064d3293f99154221dd51ccebafaafc0b88b707be6a4154c4f553728d535220e82","nonce":"a6e3f71000879a06930a7e84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"94cdb9bdfae3c294125164713f02a921e9846f574076e3e7638de29ffb7e035985e5aac1df1b4e6ce3e61a09c8","nonce":"a6e3f71000879a06930a7e85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"8214925cb9fc658c30dd378b78f083cd4e30ac327c99f6bf82bee2178a8d3ae100206d904bb5a8ca3be5603e18","nonce":"a6e3f71000879a06930a7e86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"9055088bf30881196c4a7fa2ac7b884c1bffa3cb1eb6632c4e65630c6b643e90b5eb9b132753a6d322ff6c2764","nonce":"a6e3f71000879a06930a7e87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"77f3443e791840c721dabd91364ff03736b874d4275c4dbca3111f7c1d760aa21e4b86cb37a9ad51a94e0a9535","nonce":"a6e3f71000879a06930a7e88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"76eea5be68dfbd8ad2e8fafb59395910a619da8c69f874ad179a1e423d6b0476befd6f3c2eaaa66f41d4b0689d","nonce":"a6e3f71000879a06930a7e89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"7e613fb091d82288f41b09028f7fbc7480e7ae69e6ab6c36e2e558a4691a272856c171a7ae71912c790d51d49a","nonce":"a6e3f71000879a06930a7e8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"7b1915aba9c0c0fb6d503c62919b61378f9bda606b376d0bf015cffb5957a06190980c6b1707013cd49b48b69c","nonce":"a6e3f71000879a06930a7e8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"7786e2a6f17ebd06f212deba98ebde6913550b65d89a2e4e3f7d1c42101029f2dcd2070543d45ec41eaf27c197","nonce":"a6e3f71000879a06930a7e8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"b0093a6aee466acafae596a6441ad008882333eb59e885dce8bc11f6a8dcd93aad043bb0c8a86cd06148d4581b","nonce":"a6e3f71000879a06930a7e8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"81ec35647b3d36527cd8f7f7813a55597a2a1fa3d99f8c396cb7f0de396e611dd7d173b302eea5c98edaa8bafc","nonce":"a6e3f71000879a06930a7e8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"5eccd90443f8af55803446c3803d38d7f93f88906a813a75f0ce304547f7412a8aac3617f5d9a275d791341957","nonce":"a6e3f71000879a06930a7e8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"ffe95458ebd56cf19e52a9faa828c957a18206e72d7ca16d01b45294ec6433628fb6e199c985889fad6c16b7c5","nonce":"a6e3f71000879a06930a7eb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"853bd31baf3407aeb2a90945caea2e6c7ff47c379d81ce3a218a3268ae82782b765c6a25a7622e1acf28e5e1dd","nonce":"a6e3f71000879a06930a7eb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"36da2d72975f3055a9b4f18f3439b472b9293d39137f8ab2be20121e3e25cb702d120327923f6c0a6613704a56","nonce":"a6e3f71000879a06930a7eb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"41c952ee5999e35cb63c2fce1a64921aec07041c18072673d91bd42f11f52144c64b3f575c3e2a69823de23ff4","nonce":"a6e3f71000879a06930a7eb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"8ba19ae317eab5d1e06423e8843791efd58d54a0fb7734abe217c009bf3429c328bc177c9032ae868acea2db07","nonce":"a6e3f71000879a06930a7eb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"6ba8f657c73b7d65356fdcd0fd51fa9337178edf0e0b5b711052eb640ed97e0c1545badf4192eac877f2af963f","nonce":"a6e3f71000879a06930a7eb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"44c272a06516c02273c6fb0b436abce2b4eaf07caa7473bc2ee3cc5def6921f639e8aa049f9c2527554f7551c9","nonce":"a6e3f71000879a06930a7eb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"4a02589e57b23dd725c1645864126732d742cffa0b1d7766fd4d1a253a400890ea06d85b92865b6064867b984f","nonce":"a6e3f71000879a06930a7eb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"1b08136b80980e0fd70f82901a2a67f1d9050c533ec1bdd9687b1137741de6bffba653d79df7006bdcb98df289","nonce":"a6e3f71000879a06930a7eb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"9cc490c124f5bf323edecfb721352eb6a3dc853b792af994d57979117311edd9c0c09a34d31ab385d66d1c615c","nonce":"a6e3f71000879a06930a7eb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"e8be7c1f0588906b21eb7f841116560d79646719d5bba6f4a172e559f575439d9c2ed1c60b6ae25788070bd69d","nonce":"a6e3f71000879a06930a7eba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"36dc42ab0bc04edc7f7535f141a29011d41d7ff1a28bb0491f6679ba3480f2ca0b896d4b65b83e4d717d4e5128","nonce":"a6e3f71000879a06930a7ebb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"e0c01bb2d3d615ce762a9b4dc223abf95ef9031de2b70e90d56fa42745c579f503b2dee1456b170061a89d6cde","nonce":"a6e3f71000879a06930a7ebc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"2ef669648e351496dcbfdeb232bcc45344aba9da398cd13d0a7b815b97e5249fd45ee6b815e1d07fcd8a53e204","nonce":"a6e3f71000879a06930a7ebd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"dc62e5618a532e653b7efea9f45d5ba299d964e133de4ce63a3ab2c66225e7ea00cc36d52720bd6efe6e54637e","nonce":"a6e3f71000879a06930a7ebe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"3527afc2b745c8016c48d487709f28807142cfad735d42621202dc74df27f012ec0f49e2f6168f6fc583f19fc7","nonce":"a6e3f71000879a06930a7ebf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"8d7e1b6559e74c51bfac7891d366b5392642477c8d4bf870e9acfcaa40963306e30857a0082b828abe138895c4","nonce":"a6e3f71000879a06930a7ea0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"de2faa758c96f8f55a3561e15c390e8b9d6ed72d8cd160802b95c211290cda142f56c2c37836a7eabea85caaed","nonce":"a6e3f71000879a06930a7ea1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"53ebf1df5d2fe4e2795b5391a423a06639f55aa9e04400980294451b92cd75158a43dcf28a7dac0fa241b126a5","nonce":"a6e3f71000879a06930a7ea2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"06da7164e26629d7e837904b7fe858b6c7040265104436a8ceed3372205c9a050ec5c258506b641bea34967314","nonce":"a6e3f71000879a06930a7ea3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"864505a7331beee8fced358f22c4866198cc70ba932a315eb6581559c041692f0efd8597afb0542f3b43a7f064","nonce":"a6e3f71000879a06930a7ea4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"01828682274faf325cb34571b495fbfd3b55b3acca6e1320a9a6f9dcb6697ff98303348cef9f44bd4da57fe285","nonce":"a6e3f71000879a06930a7ea5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"93b0dfcce91a29fc24e0e3bfe0930364872f64ebec68d858135ba4788d173ad2497cbde9271880ee941105b8db","nonce":"a6e3f71000879a06930a7ea6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"fe446403c18b4ee075017338f0daeff94cb4bb5903c635378cd4c750e3e6556733e4ca28847de8ecee71e23bb1","nonce":"a6e3f71000879a06930a7ea7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"054c65410b13c6e4822745ad1fc68dcd0c0e58e05bc053313734b78d57c768e281ad81971d37809c73ac34a9a4","nonce":"a6e3f71000879a06930a7ea8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"f87af49957cab2fdaf6ec9ed2d01c2918869380da4d9398054709775b1a4d66e5c2bc3324074c27a5d68d01d90","nonce":"a6e3f71000879a06930a7ea9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"2b1efb2c6c4c744d58747e769541d3978e76c4f437ba34d8a363bc168acefdbc06c40488866255c584644ed9ee","nonce":"a6e3f71000879a06930a7eaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"d01cc428d438d0123c2d503b0395ed83266a3d429a4674401f71561ddce19feb215cbc00168e9c9bfbae0a8e69","nonce":"a6e3f71000879a06930a7eab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"8034407c30b99bb6f1919f999c98d1c1c09e2164743cce79e766264307a7260ecc2239410104543da3ec96f283","nonce":"a6e3f71000879a06930a7eac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"e63ade38a901ffe6a7cb88ab2b61695d5b44ae7267c14da36f528209e3cbc116359e45f97b4e48ae1b3ec95223","nonce":"a6e3f71000879a06930a7ead","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"901caf16dd59e36ba053516884d829d3a73de49976dcef9a6733bfc2afc27d8d08168e119cce5911fd76864b40","nonce":"a6e3f71000879a06930a7eae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"68e53ebccc099fcc9703989f6027c69e48dece5a34b0e5ac3dc9b58c728191fff3f0de505bae817bfc2128ec4c","nonce":"a6e3f71000879a06930a7eaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"1eebcc0729a60e7f573a97f355a31d502dad3325c1cbcf54cf4a58a16a5b1b957f73f7e05ceded99ca3d2ad2f3","nonce":"a6e3f71000879a06930a7ed0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"e4549bb8e81a3aea7d66e0892deaeded2194a2a12fa74b6bd30ebb6dcc10b7b08a18352a8578cbcac759b9fa1b","nonce":"a6e3f71000879a06930a7ed1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"2c566d5bdaf2e0e495400fe67936cfbbda1dc40fa4c93ed150a0cb911c5c1169ac3864af74a86c4153fdaacccd","nonce":"a6e3f71000879a06930a7ed2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"9895db3c9645ab8849b71e76072c090fa45a592143b53bf9f21226bf2346107febc80ed575e602f893c162b3d4","nonce":"a6e3f71000879a06930a7ed3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"b36b9fb9aa706a99b1b8a5eb43ca2e90568205dcbcd6fd6ee7f34088a7c36c79babb8ef1c69c97c19378b127a4","nonce":"a6e3f71000879a06930a7ed4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"3428b867d73da9d4ebc3d67d0db8383434286291eba3e2a6f5eaf7c5df582494de50494b6c161005234a69cdbb","nonce":"a6e3f71000879a06930a7ed5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"a20609bc86f0c3834c318e1a61e7e1e56829095439bcea8555798ee301d6113fab71e0ffa3d0470d8fa89f808f","nonce":"a6e3f71000879a06930a7ed6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"5f0e918e9896bd7f8c58c78b0f2fb33535d12c6403c42e191a6bd182b98a4e8d95ff5cc549f4141d52106d6736","nonce":"a6e3f71000879a06930a7ed7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"61c24f7ddaa622397a14724e67a04d61d8dc502a806404b3b66c6a52ef301cc9eb529af3091736f6c9d77b13da","nonce":"a6e3f71000879a06930a7ed8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"330e5a3a86578a86a0a0a100575c653411496fc0ce6bae7957dc755f1936cb7a2f1bb110099e88944d71938c8c","nonce":"a6e3f71000879a06930a7ed9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"ddb11472a6b22f2a3ebb18e922cea064ec3a71fb5a2aef0571947e83287fd33ca809c393e7172a8477493ad0ef","nonce":"a6e3f71000879a06930a7eda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"56e7173488679ebbf1b93161cb623121e4ec87a441e1ce3dadf8424ca0f6dbd99d20c1d3bfdcc659c83bd6fab1","nonce":"a6e3f71000879a06930a7edb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"a6d7459a46c151a78e146b89a0aca94cea7e5e80c0efcadfec63d544f6fef3a78e6a66efff8e7178987983c0e4","nonce":"a6e3f71000879a06930a7edc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"a4431262b9c9882c4767d9dd25174237868cae1dc71557644717bbd6e8a4dda26c99b0b6442e1ef7454af93582","nonce":"a6e3f71000879a06930a7edd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"62d0779eeb6066b5a43617fa880f9d7fe731ae8eb46b1105b62ee447469da90c29596798ae832e499c0b3f8eb0","nonce":"a6e3f71000879a06930a7ede","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"1e3b671d6136bfb3e52d91f69710b82077221b467802504a060518934c6b14ca005883661a99074bbbf68821be","nonce":"a6e3f71000879a06930a7edf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"8d39d1d121b564b0305aa669f5b39dd4b60b76bbf85e0b075e603e1f5f12dccf68aab6695bb9b94e9af83742ea","nonce":"a6e3f71000879a06930a7ec0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"0b721fad45bdfb6756d0de0c9f916bbbee69e21ba529867759eac1c78bff3f1c1550e4e7e23f96f6e61631a4be","nonce":"a6e3f71000879a06930a7ec1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"fd388ac0bd063c801e7336c68508f70b26155a0d23bc84e122c0a1753f373f9a828c31f592a4c4d5ebd7863d25","nonce":"a6e3f71000879a06930a7ec2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"9851ffb08ba724f4996e7efe7f8241a471ba33c91538338b0ca97314d2d26fffc959ca2e042b616ac95e37c39a","nonce":"a6e3f71000879a06930a7ec3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"7e17f26e007f26c1adfade02ef9f345d12eb5e93566d5b968f076f24a4449a3f9dca090c9f13488bcff9f2836d","nonce":"a6e3f71000879a06930a7ec4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"76c196a737d8156e13543fbbe5ca0ab457f5e3daacda73087f1a2401eebe6d4585dcfa9e1d1068127b3212f5f6","nonce":"a6e3f71000879a06930a7ec5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"7b182835bcd3bae51919f93719d066dbead1f4ef03bd8167eee5d29891a4470d8c29bee7b0de7d01dec357bdf8","nonce":"a6e3f71000879a06930a7ec6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"a4ed1ea549822a9a2e9cb397fa468b195d670beaba2be985881a68471362a1d0df92ccf3285ddbc67b613b129a","nonce":"a6e3f71000879a06930a7ec7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"6bfde670ff90db8766e171f69e281513efe535b804873d6f907757cbd5c3ab5120979950dbefab060a77c01d9d","nonce":"a6e3f71000879a06930a7ec8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"d165bca79e38a6920b194400f8bd4148092013263793a79ddf15a5b0c8dc85d4d6b93ce28d8b7ffa332e59de4c","nonce":"a6e3f71000879a06930a7ec9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"634687de9f86d3f9cb0407fbc48625b05f33c08e1d94c034f8347a9ba8545d13f7ab151e2fd9d873598b63d3b9","nonce":"a6e3f71000879a06930a7eca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"098103f124d4078ed185d17259c8d834b0eb73d0a7a95d12f9638c03d3999aa72f9b02b3467d1f94300ffa3265","nonce":"a6e3f71000879a06930a7ecb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"3ff3075b434eab8a57155a1fe08398f118f25a70e1f1ceb89ed90e834d9ea6a43a5f37bf7413f9aa87c5bcd1fc","nonce":"a6e3f71000879a06930a7ecc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"ec00092726d997a747b1c4832c86f7b068011d09d2d6e4eb4845d87e5bafbf2fcd5a3b1250ffcfb2e11ef9222f","nonce":"a6e3f71000879a06930a7ecd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"00d8650defd6760541a30cae3a74bdd15b28b1c58b1a85edb428daef33176085dffc4c11d4ae07facd09cce1bb","nonce":"a6e3f71000879a06930a7ece","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"83f5e22a5ed1e25e64cf351cd38cacf339b6049d47786327d980888ca091f767b043b51f2008bf4716dec6a772","nonce":"a6e3f71000879a06930a7ecf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"49bf04ba3ab9b4e814367c9e19d80cedf9db0d3ae0b1caa3c28dae68bf6a5bbc0f3dbe0f25d3863bd603f553e4","nonce":"a6e3f71000879a06930a7ef0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"ec8c1485b52d161b16d30dad3b4f2e915d7dc6d90f3711444664e76e9b265e06b8a122780bcdbabb42f31266fd","nonce":"a6e3f71000879a06930a7ef1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"396576842b65d762b736d6712deebd031b05882bc49d1da5817ef535e1ccaf635317917e6e242fc14eead91304","nonce":"a6e3f71000879a06930a7ef2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"1d13465930d322b97c78d7017d22816c8f2a794ecac48b0a31b17918cfd531109851037be553c565d9f5677e61","nonce":"a6e3f71000879a06930a7ef3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"b2b926a819ab18f8e99ac45cd127a0acaafedfbf8a2566779f540c040a931a4040b1e64c1ba75e68c7ceb952ec","nonce":"a6e3f71000879a06930a7ef4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"f2989d3f8bdcb05a93d8a301ef313a5446fb0511b1c9108f0144e72244b3d298369ec9429a38ed31eed3165741","nonce":"a6e3f71000879a06930a7ef5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"51510ebb672551a81e1b7b708ca99018e9ee2021aa2f9750d6a8e1f981fa67b9dbc042b2afcd6d53461f6d32a3","nonce":"a6e3f71000879a06930a7ef6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"cd26c40e03eb09127d9454a2a73e1cd9abb2ad63075bbdd7c7fe828585fab528ef15aece1c9c75b84658cac6df","nonce":"a6e3f71000879a06930a7ef7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"152b07f0467cf7de3dce0241ab7cc202b2c7eb8e99b5a5d1cf2ed0999ffcf3cd0098c7629caabf50f28d06a3c7","nonce":"a6e3f71000879a06930a7ef8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"cf54068af029304d4dbbb9c91d1c492d9b601fe4279f089819307c0726378339540a921ff7bc30540b59c934ef","nonce":"a6e3f71000879a06930a7ef9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"a30cf95ca05367a1d16e99d65febe174c8825dbe67652b44b61f878e82834d36c910cbe8984ecf937729059e95","nonce":"a6e3f71000879a06930a7efa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"2f839f3b8411da92a9518d49e235830952388cdef9bbf9340e2247662ec6d88e9e884d7daaeb1282423e9f9c18","nonce":"a6e3f71000879a06930a7efb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"08a942cb3987efee1f454e71e60d6103a311b02fb5176cc638c47eac0293e5e430d42720805b4e38317097c99b","nonce":"a6e3f71000879a06930a7efc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"e3d0a03d97d8497ad59dedb539b24c7df08027d0873f03aad579496a33ca86e7ccc8004f1434d2d693ecd9f5fb","nonce":"a6e3f71000879a06930a7efd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"633f1be25223c8385cde63be4045f756dbc1b329be2cc391a44dd6c85c521fbdc194e3db512a2cb0cfae43426c","nonce":"a6e3f71000879a06930a7efe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"86fe5b23218b7cf8a0d90f8c20fe5227ecf18a57cd09548614dfce35c2252c2c176ebe34957bf6050f3ccf094a","nonce":"a6e3f71000879a06930a7eff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"ed7e428ea99ee9a225947ea7edc723ef80968a7a8eab86589d5aa5a47f575ed54ecf71cf8f2d9ebf6ef1233ff6","nonce":"a6e3f71000879a06930a7ee0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"a9233594076c7a9b2792ff3dacbc29a5e377cd2f4aca9d8c3f92f99a1ed4ddf47f277d574924520db71569a481","nonce":"a6e3f71000879a06930a7ee1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"c8cabe99b0965b63f71b1c981dd6d4af029b901b6115c0cf9627603227c7e108b2b37ed0a4ec619f205bc4e643","nonce":"a6e3f71000879a06930a7ee2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"8018d41928a824a353224ac75d5b5ad0ce8f5adec5f93b6c67d47d67295989b44f74a155e86bb98f3067641377","nonce":"a6e3f71000879a06930a7ee3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"63bf44def15019ec1f781dacd9bbade2cf4eeb9e9938c8659d4d40a73a31c9051a945449d803e9262af5b1d7c3","nonce":"a6e3f71000879a06930a7ee4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"601cb18f16e6de5c1155c3a8d8cb524438b51ae0c2eb14ed873390ea5ebd1aee50250b218f2ee8fff07b633a0f","nonce":"a6e3f71000879a06930a7ee5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"aec7bacf0a9e13e09a2debce5405e87864880c31aedcdc3f24c1c5033bbb7e02def7532a0040ea0d7b75faaca9","nonce":"a6e3f71000879a06930a7ee6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"114284969caec8ebf9f722844d23c71a119e800e8fcc62629928f0c1e1b02c399421bcd0e0bbe77d2fc49794c3","nonce":"a6e3f71000879a06930a7ee7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"459fd56fc4f563841eb3083247c59edc530344fe6df81b7ce38bde5061cb145c9af346deb7bf047a714da823a2","nonce":"a6e3f71000879a06930a7ee8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"29ccccb61811db414c1dd099e5ba8e20f96771fc50535bda7308d183e25aa0b6705893f4ba8bec8357dd688645","nonce":"a6e3f71000879a06930a7ee9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"776d445f0555ea9f06e4417de517a56f0d206ba12a1023069a565cb5d3125d26d99d9f1917d5dcb4f1e7910a26","nonce":"a6e3f71000879a06930a7eea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"458cab7a7cddc8bc460e5879f657b84bd6a5ce0c9f660a18f167d461a2e2703ddb126b72315e251f1ab0722014","nonce":"a6e3f71000879a06930a7eeb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"33cad4142f6036e9ab6b8baecb6a20a73470a5e4c033c5935f61047224f2df19463e3bb6f7a96f3f7453120367","nonce":"a6e3f71000879a06930a7eec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"6e5ec47d0e96f8e9bfa930ecdbfb70d4e66cd8668caabefcfd2727d2700403097462ddc91b2863fb0f272a472f","nonce":"a6e3f71000879a06930a7eed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"c14322079baaad609b57a757901e9283742b1afec4c348e0246b915fe00b83a40e7ad817097b4eae3fdd3fc3b0","nonce":"a6e3f71000879a06930a7eee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"aef5c08d51466cbcd5161ac1f94febccfad6915752f47c525f4a7164102c5250fb6ecc89892c5463d33daea754","nonce":"a6e3f71000879a06930a7eef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"49a82248f2c9c834227a824dd6c8acb030f9f53b5fdbb7710116bf9908cdecf6a1924bf3cac67c23b83ddd2345","nonce":"a6e3f71000879a06930a7f10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"3b57330cc3d9a6187011d50fcb29587f588b1b906bd0572bd952f2d6370b9a91"},{"exporter_context":"00","L":32,"exported_value":"09aaf1ca160ce21cd25a45c78ec9033ff41da87b0a026f28a853b1dac8e5def8"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"654ee749178b028efe413321ba83453faa4d95b61550000b74f727e94a111e6b"}]},{"mode":1,"kem_id":18,"kdf_id":3,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"e9a016952866c33da399e64ecd629cf32826285698726f2c22debd4799b8fac112ac1a546ce39452406396a389fb10f51036c7022dc1cdde177b54d005731fb79ce4","ikmE":"bd12d21f5a36063ec0242aa26f22144aa7d24c3cc2e6a1805868250d8e9ce6fb2a04f8852cd6ec3241249fcf262b8f245d179636fcfbf275a75539cfc756a4dd3f53","skRm":"00435ad3bc01485574a909a79b60cd839ec53ed4c56b7f4677e56253c9c4d0e02ab27c27e072961ba2d4473d4a73a3dce0b585c2b5d61caf9b5d89bed7b32bd5481f","skEm":"002a7455582d9757faa99131bca1401e30eb17ca38354deff31dc4d23c4adb7f372e5e484f40aa048ad763583b4095a14d57a29a0c6491a4c150972efaa8bdf91e74","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"04017c27b164b369382597e1e3f4d5e4f4bee43fb95d39dc09fe8f9b6c2ee342b2523bbf30238518dbc338cdd140879f12a5b439815e8a8662008f77198e80a33936db012901dd36d837faaa995cfa014b0439ca25a0ce1200140ec43b482226beefd1086758940c59e34994737827df08b34affd812554c26d6449fb4dda9a249d0ee6a7d","pkEm":"0400e7b838035aa5a1ed5c405fd0d0c24878b95dd69f21a838c7eb74255eb9564bab5ee9d85200e233cc19d6c879318631973160a978c218e5477f1dd4114e2cf932eb01080401d3933f56f8167db6ddc922081750fa2d93b5f853f202dd7c9e0dfad662079d464974e1042623a4aa4925e9f8ec0a1c7d6b66273825929bcf5669c0ea4f68","enc":"0400e7b838035aa5a1ed5c405fd0d0c24878b95dd69f21a838c7eb74255eb9564bab5ee9d85200e233cc19d6c879318631973160a978c218e5477f1dd4114e2cf932eb01080401d3933f56f8167db6ddc922081750fa2d93b5f853f202dd7c9e0dfad662079d464974e1042623a4aa4925e9f8ec0a1c7d6b66273825929bcf5669c0ea4f68","shared_secret":"8c32977bc310e95106ba15ef64c7dfe17fd3ed3879f6430cb2d1fcf11bae1cd8107dfa03dc8c54f20206c07ca03da3c30705a660f82d080e62a6a69a15460931","key_schedule_context":"0124497637cf18d6fbcc16e9f652f00244c981726f293bb7819861e85e50c94f0be30e022ab081e18e6f299fd3d3d976a4bc590f85bc7711bfce32ee1a7fb1c154ef45baa1f3a4b169e141feb957e48d03f28c837d8904c3d6775308c3d3faa75dd64adfa44e1a1141edf9349959b8f8e5291cbdc56f62b0ed6527d692e85b09a4","secret":"db776cab2c066a8147d8778a456b748d8b4881cb22cebb674474c8e9bb17c12366a1bfecd62e297f3f715ddd3e4b31772284f02c8a943d7da9fdec8c1ab6f694","key":"0cc4c3fe74377465899ed383739be3ca3a9927a2bc6cc81909adc3ce7ca7ac6d","base_nonce":"07eaf15d8bfb9104fc2b851d","exporter_secret":"4e8f1813831858a3ea10f4c088bbccb8f01a44667d97071ad04e391b74068e045dd3cb2fa224dd4e64d76176a1541e7108db8a986a345947fff855976080f65f","encryptions":[{"aad":"436f756e742d30","ciphertext":"0ead36e9a07a606bc0cd3b12baf8b6dcf279df41d68ecac35a05301c8cfbf60e62693f92356d9bcdfbf7a19920","nonce":"07eaf15d8bfb9104fc2b851d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"891d0ce19337e650fc7e3442e084cfe068c2371f0052b8203b0c9baa6df2aae1c06f697e74df612da850cef6c1","nonce":"07eaf15d8bfb9104fc2b851c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"3e5b960fddd28c38c906c512d11359288c1c764e88a857977991827b85ad41d570c92661ea4b231d1e95b7f346","nonce":"07eaf15d8bfb9104fc2b851f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"bde151d6a17245ca13995a15f3e13a214b31e6da44c899e9aab1b9ad5445b488b3be7cc6788a4d51177e46e357","nonce":"07eaf15d8bfb9104fc2b851e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"0ccbec29295faaa05020a95204c161970d4f2c27a411d04cb8fac373e7e80c400cd1c6cb34cd15332085583b7b","nonce":"07eaf15d8bfb9104fc2b8519","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"2ad5a94ae4a3a96476178a71c4dfd4a58da40694f4c3ef5d23de9f81e1c04380bdec9355bcdd25033ab2a8c2ff","nonce":"07eaf15d8bfb9104fc2b8518","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"3a5c11697bd16594b2fbb110f65754b1223ccde4b06bffb65b403fd4461d8b7be5d1e2f24d85cf06fc6ca56a12","nonce":"07eaf15d8bfb9104fc2b851b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"dc1c02abe59b7e64fcb92f3619f19865df77c9ccef66efb832088ec33bb1596c06a5aa32879835ffd7d5d16f58","nonce":"07eaf15d8bfb9104fc2b851a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"5d447689cf8351f272d5562c817341514f7757cf59ae90e0e1e58134d4c0e39baa3950b4255c62a63aae058f9c","nonce":"07eaf15d8bfb9104fc2b8515","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"012c637ea3e529361256f0d4f3e90ef4f44d1c05abb549ae242d07d1a3a489770f90ab7a07955e973f4f3cbd26","nonce":"07eaf15d8bfb9104fc2b8514","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"6cde7f618e0e81a03c514abf5fca708c10d755e323c6cabd911fe776e1a15ee9f511190ef0c35053c0d6c7d0be","nonce":"07eaf15d8bfb9104fc2b8517","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"ec7018caf16cf5230734839e957fbdad7637566acd34e1c30f5a7149c6b94c8b91c731122b3ce9da909ef5ce8a","nonce":"07eaf15d8bfb9104fc2b8516","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"1f20f1990103deeea3cb261927a691de6e4ed404bff3e6bdf97e21ece0febc6705b8452fcc07cef495f0960b43","nonce":"07eaf15d8bfb9104fc2b8511","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"cff74e97a8b296bc4b6a6f9995add96b080091eaa373733928ac8a2b437149e415b082bfd33eb02a47189d6847","nonce":"07eaf15d8bfb9104fc2b8510","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"58d992df42c11fe33e9db7fc4c8e47abc35fc96028b47bad7bffc507545a17ab9c9baaca619bf4e04ebf800be2","nonce":"07eaf15d8bfb9104fc2b8513","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"4910a25ffab86275942cc06c1f0f58ad1f55bfdab3f34345b240a0a178f6063f29704748efd7fba911525a59d2","nonce":"07eaf15d8bfb9104fc2b8512","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"07774b03e34eb01e9c07a00c142ad2c2332d051b2bb08ed1b43f0ba92bc17fccf61534829bf006bb61cd20e9ac","nonce":"07eaf15d8bfb9104fc2b850d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"a8684040073e0375092de7d9b3d8ed5f6856e9d521ec25d0c7e89974383027891c0dd8af7fd899c9b67fb635cd","nonce":"07eaf15d8bfb9104fc2b850c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"2b6152dab7a372815d22e13b0fb3f2384811690b0e498542ac3786bd90030088669b499330a859a6cf45df2c08","nonce":"07eaf15d8bfb9104fc2b850f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"b81357ee89271d25e31ead3bdc5111213b74af03815f24ad37451a1ab73b83261c91075e673e73515e5f2ab9e5","nonce":"07eaf15d8bfb9104fc2b850e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"a6803dc88002134d3e759d96e21d4264c74f09fcecefe2d4383e8580dcdd50e92a20cbcf82727b36d7fabbb3de","nonce":"07eaf15d8bfb9104fc2b8509","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"3b354b478bc29ab919bef4c246b7ba9fe3df80b1fba29b6bc4d0d7c83c63947c07684c4979bb33b234d8a9b5e3","nonce":"07eaf15d8bfb9104fc2b8508","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"dc517d2a78c0c61e95a61b9f8d24a321be6c4c36648575ef2ceaafcb59d5d0df6a186b8eddc16efb8fdf047b4a","nonce":"07eaf15d8bfb9104fc2b850b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"4ba62612ff9ffd300bb37a25bc1e955b8948f0eb0d03a282fa45054e0029f350a4f3c2871ebd87a8f5bc88385c","nonce":"07eaf15d8bfb9104fc2b850a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"6a20cbe547d8ce03e9ef6b78c51a3a8ad6ff5aa1b9c56947da0dd58d9ab8a8f986cdb914cb3333b0ae3e6627cb","nonce":"07eaf15d8bfb9104fc2b8505","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"ed883fc3791311708fe3a5a65d14c8254e51e4e14bc0e514574f46fcc34dc7d4af9ba37b9bd1f3b588b2be9ac6","nonce":"07eaf15d8bfb9104fc2b8504","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"a93b597739f7049ac8628dfe75f4d4e2a5a98b37d3b2ed65da93c51bc76edc18b2b01d6c53242f9ec85bf576a8","nonce":"07eaf15d8bfb9104fc2b8507","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"776f20c3124f0eda5153e2a4417925b453c79907d8999acd5b70548828aea085de614fb517471053ace7fff39c","nonce":"07eaf15d8bfb9104fc2b8506","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"90dd4c2736fe3600875ca32defc60e96b52a9289b00f48bac80f23663b076a7bb16335f07bdb74638e9597d55b","nonce":"07eaf15d8bfb9104fc2b8501","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"d0107f3deec56e8678ebfcd2c9fcb83a7de497021e97c0b770ad20868c5c680f96bb3dd7d190d6988bab4e99d5","nonce":"07eaf15d8bfb9104fc2b8500","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"3486de218b10b67c3f3625586d805d738daf2f05a81ca8e8fee29217e877e23764941d9d2cf2a2c5a0f24a6ddf","nonce":"07eaf15d8bfb9104fc2b8503","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"e4ec02ad447157695380062750e7c7ff2f52c52071cc30dcc363554852c86614ceddc47e7caacb50faeaf76f82","nonce":"07eaf15d8bfb9104fc2b8502","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"37795e5267dc1839d90fd84542f20cb25a38d088f9d15ec04f30a02fb124ff96585a306b40b8739684eabb22ad","nonce":"07eaf15d8bfb9104fc2b853d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"da4e104b60e311e060959c7d5b38d2e26e6f504635041734c859bce9d8dd304b9ede70fbcd37c0e45a5cbe576d","nonce":"07eaf15d8bfb9104fc2b853c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"fde1a173523db0608c9efe9060e3116a2f4d1e6542637e4137a375754853c7d071147cac40661081414cb22172","nonce":"07eaf15d8bfb9104fc2b853f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"81a235bda9478f0799f9e469724f04b9cb1b99c44764c1789de2972bf9e425198bcfa145545301e9ff77971d4a","nonce":"07eaf15d8bfb9104fc2b853e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"561b837bc6861fc5bda565ea5a76af629a75df60a36b5634f035da6af321c9e1f78adf88a7e07274d761e42460","nonce":"07eaf15d8bfb9104fc2b8539","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"9d1d1dbb78d6c9e9ac7220b59e914fe70fd873945be0bc2a7f7bc34240f9817a4e1f9adfa89fcab97b71b3358c","nonce":"07eaf15d8bfb9104fc2b8538","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"86ca125dece38c6cb5f15c69807f99871a84a87d866ec669f1eea0ac1e012e61133c53118993acf8103c05a49e","nonce":"07eaf15d8bfb9104fc2b853b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"0fe0fd4ac63790c9916ec58d9fd4da9841ef1894503423fe188263faad070d0a83450c7dc009e76399b3626065","nonce":"07eaf15d8bfb9104fc2b853a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"16231fa978aca64627f433cc963494a0c2acff455b9adc5f5396030fc26ff7920df9043afb9daa9e33179f287c","nonce":"07eaf15d8bfb9104fc2b8535","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"f869ac23f5b91f29c8931abc039c47f5eb491aa79c968b7ec49f4e35cf1b02fda09d42a8412b86e8e42ba6baf9","nonce":"07eaf15d8bfb9104fc2b8534","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"e37d1286baca5f278452db60ad36f136360b0feae540f985b1bdb10634c0131a638042a3b042b0059abf01b246","nonce":"07eaf15d8bfb9104fc2b8537","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"f6c0b991ddc437356818dae2eb495afe0ec3fa8500b99763db1a72c3cad953a83ca924af9653e42373a493771c","nonce":"07eaf15d8bfb9104fc2b8536","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"e89887dde8bf0e8bbfd2125700aa65cefc9554a218ac643b7396745044503f32df9a6aaff5422b42a1c31ff43e","nonce":"07eaf15d8bfb9104fc2b8531","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"6196c96d63c59a9257314e0de14a06164be2cb417904471da962d1e38c1d1a37d2af558182f6a7b5bee511839f","nonce":"07eaf15d8bfb9104fc2b8530","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"0166a3c75574d4b7cc052ad6b1c0552f727914ab7f3802cd52c60da06cb950dca0ca7cd6357e5a54eaa31bc82e","nonce":"07eaf15d8bfb9104fc2b8533","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"1f4455e458a0934d59c8eac0ce2a33df9c626f87e4aa22cc3c1edb815725c1f07d63d0526e53d487f79c11fcc7","nonce":"07eaf15d8bfb9104fc2b8532","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"5bd780836e02bc4f25749065042df3bc413a5344441ed93459671c8d29c193c2216ca02ae2256e06dc368a8dc6","nonce":"07eaf15d8bfb9104fc2b852d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"9d1dcf7af9063156c56c25a6421bd485de7d81b7c5c70df3a104edc62afee6dbcb9266c00df2b9ac1edc21f8c2","nonce":"07eaf15d8bfb9104fc2b852c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"3094eadcd9b34f03243976ae5cf8faf16fd8f3cc6d20367d390c8652fbdd48e4aecc473a3c4704877ebde18cd2","nonce":"07eaf15d8bfb9104fc2b852f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"b056190d56618456f825042799535a51ab5f1a0cb31513aedba03c8a72ff8e5d5acb48bd57335098abc6276ac1","nonce":"07eaf15d8bfb9104fc2b852e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"633fb2c49c0d296ac0d54186ec675d5c44f9b0f506fdd54f64510acc44492b1607dc904df77d687683cc5cd9ed","nonce":"07eaf15d8bfb9104fc2b8529","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"269d381eb4da5fdb559d51aae808a83574b84e52134397dbbfc09bf06671d2655f307173b2a345632dbaf3fd41","nonce":"07eaf15d8bfb9104fc2b8528","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"5fd6e5ebaf2cd8df4b2bd13391ba642e932ddc24a708f31731c94172348161cf9f524d3ad594a81e5534bcf58e","nonce":"07eaf15d8bfb9104fc2b852b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"fbfd5e482121c8f23048e4d996b801e7f3635540fa3ae30293410ad5b414ab09deb25e7df007d7f0c8112f1a40","nonce":"07eaf15d8bfb9104fc2b852a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"4657aea2fb145d03182cef30ccc6f393167e3235f16404b6dc7d2061e7a92703c9c0c92564770b23f0ac52d397","nonce":"07eaf15d8bfb9104fc2b8525","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"2bf8c875cdd7a37c1419ae7186ad0d8d2d1ed982c234852f419074a0d74a20da807d3d8f785e9232467cb80d5e","nonce":"07eaf15d8bfb9104fc2b8524","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"0cc09ad7dcb59d06ffc8a305b3779b4ee067d4f906b1e24996ba785ec40d681a23ad8688612e43dc96c430d794","nonce":"07eaf15d8bfb9104fc2b8527","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"9547a9f37ff08205ad3f153ec4ccee126858d28376d23f46c1773f69b8799551e999da24312a22907b5df3055f","nonce":"07eaf15d8bfb9104fc2b8526","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"9e284452da72cbf280f5d97edb8f9def3120b16af1f5fc10a4f08036535aa1f370f6e209797faf31c38d34b259","nonce":"07eaf15d8bfb9104fc2b8521","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"e884da35f755bf9273e3e5b81ed7aab1ceec06afafc0614cfa7189bcae1e2f9ee699079aa976cef4322c2a094c","nonce":"07eaf15d8bfb9104fc2b8520","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"300a3d3aabd7d1d4b827a4cf0dcaefadc69452d070f685cc916f0fba3da2f5e1aa890cec27e24a88129d634eb3","nonce":"07eaf15d8bfb9104fc2b8523","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"fe464ed8fd5b5990e7e427e2f509a2b7ffe699b6548de4cbde1e2a42f85b7ef9ae7010ad562910871c037a451f","nonce":"07eaf15d8bfb9104fc2b8522","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"c76b47ef33463495e592c61973336a3c6ad896ab54d9c1ec9ec5d845f7b10c15b6ca261e7b11fa05a6ba62eecb","nonce":"07eaf15d8bfb9104fc2b855d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"6d809ba36a8307113c9f7d8b7e89184c1144327fe334d2570dab584a371f32818305f4bf91881677b3ca29d21a","nonce":"07eaf15d8bfb9104fc2b855c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"e19e7f405e827535378b07065cd1bc0131bad7a3677601b99f6cef106001de3a03bfba5f507a1740ba963475f8","nonce":"07eaf15d8bfb9104fc2b855f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"a97a488fa28df78166961c7f73c1bd8d1f97dccfcc3301c05694038fbeef887eb9c725a59b71a040d5bce37197","nonce":"07eaf15d8bfb9104fc2b855e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"d5d06ab04dea825bb52564a310464cb66fb3bf474253715d9c141f5d14eb25e269dc87c7f7d0685a60bd2fa8f4","nonce":"07eaf15d8bfb9104fc2b8559","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"b37a10a8220e9234982c83428368a0d614094e7e43a36a13ccda5ae3cae489c59bfd332bc82374a66906688ca9","nonce":"07eaf15d8bfb9104fc2b8558","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"c0940d57d4c0d70d4f8250da81b489deca4d98d354f19f71e7bbb3f3d362ee9357b8c601cfe0768c4a02f87fb4","nonce":"07eaf15d8bfb9104fc2b855b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"3993c60feeb6e443a1d55f5ae7819437772e0fdd674ae61064a1392b1c80788d4ddfbbb342836f85c8f33b6c55","nonce":"07eaf15d8bfb9104fc2b855a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"6198cabd16471ea588b09894a780ba2208233f96cd5388cf895e8ce3ddd0c6ab56ebcb54e8f957f20ac9bd11c1","nonce":"07eaf15d8bfb9104fc2b8555","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"e984c73d597f0cf72c75f5bbabe81f355120e08e1eab0a8d34878508b0710a607f8285fc1452439e9cce4b3a63","nonce":"07eaf15d8bfb9104fc2b8554","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"6849d34d561105b6945ed3a9ab0efd5528061452ff1a73bd235920867436c7fd768871b66e442611dbe40361f5","nonce":"07eaf15d8bfb9104fc2b8557","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"090b203a7562f9b6994c37375cb3d8b39f0c1c2fef01047849a8018c7ae2a2c03226071a1f386edea8e9ca45f7","nonce":"07eaf15d8bfb9104fc2b8556","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"7cd3ac70e5ada6c095d632a9fb758f6beac516ab76fc3e6ea138790bb4223557c634667db94b2411aa5ff4f57a","nonce":"07eaf15d8bfb9104fc2b8551","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"a4bb0709b431e35ccc99fe5267ec9d1fcfac8c5d071b379b2e96e319a005c50c35a78ae27bdf4e6373c17aae6b","nonce":"07eaf15d8bfb9104fc2b8550","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"d76657abbbace1dd594d85ef420e9601fff10151efcaad10cb04c482ebebce9632a4fdae85bd4851777c50e5b8","nonce":"07eaf15d8bfb9104fc2b8553","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"1fdb1ac24e0c8ca05adbda4e4d6fb67b002bbb18df4788a465d6e0d2573ff31cfa10359da236502342d9652daa","nonce":"07eaf15d8bfb9104fc2b8552","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"ac0645b1260d00212d6f272f823632cad60d689ac28bb300897185b15414001a364823905a3395941e34e0c48f","nonce":"07eaf15d8bfb9104fc2b854d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"0f6e1574508e413144305f7ddedd1212eccd0d4e338604a520c83d6968ebc724586079bdd395a41497cabb89e9","nonce":"07eaf15d8bfb9104fc2b854c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"ead2af84e73a4bf3a37b0d52ade46f5c45ff472fac9530d61379de8bb84ad05d66161fb9088111b6eacb7a34b9","nonce":"07eaf15d8bfb9104fc2b854f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"37aa50e0fc0d6eb17959809c4089c330218fdb101ff7a72b7e6aa0b18c31adf9bd679d330fb07895115323058e","nonce":"07eaf15d8bfb9104fc2b854e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"81d38cea82895a426e3e73782f94e8c9c9e02e28ff4fa5c0e797d1475f5fc0424dff62daa475fc355b31b9fb47","nonce":"07eaf15d8bfb9104fc2b8549","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"09f05335502010dd042b03ff9496fdd274c6bd38704449171a131257175daf7a6e945e334666dfc13df04edef6","nonce":"07eaf15d8bfb9104fc2b8548","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"2fce4bff7816178dd1de7d7f30c0c277657ba9824db6c5926d1fa5e6de360d64976a2d2fd327c15480125d83cf","nonce":"07eaf15d8bfb9104fc2b854b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"c4ca8bd2b69d7f995f2a4afd262372ac028ee5381b36add30cebd473b03fa729b9b62711eac668f4772b33af57","nonce":"07eaf15d8bfb9104fc2b854a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"1c5aaa63e820282c463609cc9ab78e274fa881ecb95fadb662c56491faf472a599a68408759e50e59cebbc4a69","nonce":"07eaf15d8bfb9104fc2b8545","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"be0cf802dc34f3aae42339322bf1005b7936150cb4d37733a39d822e5f45e30fd867c3332d9dfbc90b59563774","nonce":"07eaf15d8bfb9104fc2b8544","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"a45b1de9eaf232d6b367e10cd16ac82f0cee10d0f093f30b86f94ee82d477466c68cfec1e1e8bc00112d949086","nonce":"07eaf15d8bfb9104fc2b8547","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"91b71ce2db59da616851df2b1cb8579e645fdc82745fc7f1a380fa4e4ed2df8879a4d3ea64a5c0aebc2c7d4797","nonce":"07eaf15d8bfb9104fc2b8546","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"543c224081b0ede306b0f2cbe005842a1b897d32bfee70fb5897e528a0b3fbc8acdd1418abf249bd8a8539ebcf","nonce":"07eaf15d8bfb9104fc2b8541","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"798f7491b7f6575c616c9fd9999a2e1c3120cd326a2d736450c89bda2d326894702c030fc60844d45488f5baa8","nonce":"07eaf15d8bfb9104fc2b8540","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"eb06692f7dc471d25a9e6b67612c99b20fbc8ff2aede7e7bbd209405b38fbd40f97dd521f62c13f50d07e7a63c","nonce":"07eaf15d8bfb9104fc2b8543","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"8b5be0728c8ecbdf3cc74e23f4ac5cbc59c72b472cee878a2a9a3c7f1ce5e840cecd424591214504ff3b7b8215","nonce":"07eaf15d8bfb9104fc2b8542","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"4ebd4e7e7ee03408af37b48f7213cc66b860cb3e89e366a0c48c03eb4872b38c1561d31b50e6b0d98f8e86830a","nonce":"07eaf15d8bfb9104fc2b857d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"7eeccf12c0e86bd55f3b50a2e1e95d7eb958658b3e784741dda4f98fd0c7f7a46c154d2a9bfefd8b520866582d","nonce":"07eaf15d8bfb9104fc2b857c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"fdbbcaf06b9b221a4c2fc8984fe15ab677491fd78284f9070e38389fcc0eebbe2c27e43cc208566e0541a9208f","nonce":"07eaf15d8bfb9104fc2b857f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"340031cc32054c2821b712fab894b8832a736fc0ab817e8e1e5d6f832265ff7e959febfc42391d10e6fa619552","nonce":"07eaf15d8bfb9104fc2b857e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"f949e4f69cb3754d807d6b0b603eba951dc15cac40e2fa45d0d6c14c99de82c06fb88740c4657704b9591c76cd","nonce":"07eaf15d8bfb9104fc2b8579","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"240fc4f152765d9d53d1a77b1a8b7bd8df277a7627431bb1c465799082c52c96747bdd8f0e5611cb8971f722b0","nonce":"07eaf15d8bfb9104fc2b8578","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"33e634af888586e91e69d28519a1949c602b2cf32d696021bc3db66579d5eb97383bce92adf5f65283678d0bd5","nonce":"07eaf15d8bfb9104fc2b857b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"024d9d24d9c11ec4a0d7123037f089144321865200843ac1c1abb9fcd2e330842390a4066cf264c2290fbdb6a3","nonce":"07eaf15d8bfb9104fc2b857a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"50c33edb26c910ecb713bedf063f1084cc0c955bb17fd67cd8602c62cf52380c549b2170eeaef3bb0799e69d1a","nonce":"07eaf15d8bfb9104fc2b8575","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"89478dd6ba5782cd37aa2ee0889a9249ba9ac701efdb2c0bb92cb563a34f5d557ff2c1f68f54109a6cbcdcb419","nonce":"07eaf15d8bfb9104fc2b8574","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"56cd67d26a3a290826e636835d05ab5d202499366b9a0a594f21d40514d6a6714e62ad644211d7587e590ed768","nonce":"07eaf15d8bfb9104fc2b8577","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"f0f84193b0ea62151bef2fd9c863f38cc9c3d4426682a0f4b51b9b7fce9ac5ede1f72ea5405a2cc88cd3676bbd","nonce":"07eaf15d8bfb9104fc2b8576","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"4543849dba7b305c44ec278f69eca5ae75f2125fc8ab40b2bcb14e125c1273ffb45b94e10008de3483f40a72e4","nonce":"07eaf15d8bfb9104fc2b8571","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"1164d7236146d3e2a47a3cea1d44add1dc0d5286025053ff09eca2464677c6c29abd52f0a1d8af2049dba7bcc7","nonce":"07eaf15d8bfb9104fc2b8570","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"2d7b5595e60f69ecf1bc38d4883a06f495a01fcbfde315409d9305f0f612bcffd3dfe6abe8b9186ba825e21249","nonce":"07eaf15d8bfb9104fc2b8573","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"c57a08feaae317da067b8f32a6d46f2e3e757c1f3052dc306edc91518ca15069301f7ec8e958a3fbcfa8a2ba98","nonce":"07eaf15d8bfb9104fc2b8572","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"5f8ee2b141829d75f74fe77df1befc08ed98241fb34e08aac54dd599f42777c8601435ee7644d0d5038299ab9c","nonce":"07eaf15d8bfb9104fc2b856d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"b00ac974f55ec4e29cce4017f545af2c40cd14ef12718fc6f6cf16b5c5a5f32c4313db2ebccc64e591506b807e","nonce":"07eaf15d8bfb9104fc2b856c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"b6158f6176d84efa3acf8bf24e8b452b70a908ce4270f0ea80fff88f1acf07c2e43a8ae361290bab1c51b610f4","nonce":"07eaf15d8bfb9104fc2b856f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"bbd6b7b7c9ad36e90fa33f9499b12e80f99a93f0de6c4b483ce7364804e7e106561e141167a7c954f7c72ed494","nonce":"07eaf15d8bfb9104fc2b856e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"d3d93ead7fcb5a0c9d726c293ee109dae5fe76eaff557aa0161caced36455f6f47892523d3667e7926aff02a4b","nonce":"07eaf15d8bfb9104fc2b8569","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"3a840ece3526d37eef5cbc1d8a37144bf7e43a39a412c6228a103b9f0c1280cb43f69087fa02cca36f8be536cf","nonce":"07eaf15d8bfb9104fc2b8568","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"234a5309afd63768104f9b02c9be430d627aefd146742469cfcbc7c16f6215320c61739165e56e4bdcdc7c3d3e","nonce":"07eaf15d8bfb9104fc2b856b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"e3f455a31a2482559cac73b9b68ccab85a1da787b473edec5c02cc1f711be32e03226726792198e28f31fdc7e4","nonce":"07eaf15d8bfb9104fc2b856a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"dc2d53ef87859b971708f55bff6a04032899c0ce4e9325724fcefacc932878b8a75466157679f0e6fd7082540e","nonce":"07eaf15d8bfb9104fc2b8565","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"91c63ead1bd425306a856cf59a29c57152ad5d564769ff9dd4e2d70cff42405b9105a5e6edd1f6210dd1b9359c","nonce":"07eaf15d8bfb9104fc2b8564","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"d6e8eea0ea9da88a7a165ed8631556baf79e94f0bfff118f5b94b684c94b255ef18ab077828517f12f4c5a11e7","nonce":"07eaf15d8bfb9104fc2b8567","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"e2429138fb455e03301f95e2ccec5fb4059fb3c820b671e17d294fe64959a5d3f73224a18ce010570308a6c73e","nonce":"07eaf15d8bfb9104fc2b8566","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"134e6c07203f130be6615fc413744446add751819bb65ac8c4b7811ea3f5fa70f4188c941a6be705d717716632","nonce":"07eaf15d8bfb9104fc2b8561","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"8c0e26271d276a128f686152f75f8ab6a80b89cceb2f735055a7b426c092bde1360fa8a636420880128bbec494","nonce":"07eaf15d8bfb9104fc2b8560","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"4a9d9603cbc3715d9bd48916ffc1ea7ea10b86f763b7ecf5c3a47e259112c058f79808d4b75816d8f731ffaf32","nonce":"07eaf15d8bfb9104fc2b8563","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"3cc1545a06492cf3784437dbf00b3b04dfbb8b5edfbd8f6eabd8666a158110f8bdc4165a16fb66d91bf991b1be","nonce":"07eaf15d8bfb9104fc2b8562","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"07ce293de5cbe975d873b5c7530bfb754ab70e02f016addc7b2eb341e9e649f87e69038a96f446b651662a474e","nonce":"07eaf15d8bfb9104fc2b859d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"ec7d152da32361d0060d6a907ef14f695e2fe4e8f079d3e68a13ef6872d17980b9a9c505e27f781e27bb86f6a8","nonce":"07eaf15d8bfb9104fc2b859c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"ecfa847193657f0fcb14833547bdcb4bb6eb8dbc866f74b65e453750aabbf41c22a25356e8eed53fc04aa3668e","nonce":"07eaf15d8bfb9104fc2b859f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"0e631b81dcf1b2fc03bb1f5fcef9f44a51955b94e3bc12fa4035638ee338b7a77afe58edeaccfb067bb60f484b","nonce":"07eaf15d8bfb9104fc2b859e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"0161106a7e7410b7b9484cff4a5b0fa8528bb7142fa1c309f4cdc9927e6b35216a14b0e7ece92839e650c5dc30","nonce":"07eaf15d8bfb9104fc2b8599","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"744ae7e719dd05fab121debb49bfba60f8effce8933170a724c7134623fc1645760fdaac307f85d1a6c26d99b8","nonce":"07eaf15d8bfb9104fc2b8598","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"f92348c2b8c31f3744dca7d564817a925c42a3de9a643dd1e926fa77a73cea6df143836a2fdd7168a6399f9cf5","nonce":"07eaf15d8bfb9104fc2b859b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"9960b4841462d0161a4e62080039b1d4c9862416a0b43c5a6c2c2f282578b03d2e6734bdeefdd3c22737be4d80","nonce":"07eaf15d8bfb9104fc2b859a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"acd04714d1a668f61a7f534b1bbbecf104c7348e43e32c08efdc881ca8931b4c37db3622dc6f161b5a60c8b295","nonce":"07eaf15d8bfb9104fc2b8595","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"a2abb5da1253b8bba855667654725f615f359cbfc8a3e6b09ea1c6afebfa112377b9891f00f45d6a26503d099e","nonce":"07eaf15d8bfb9104fc2b8594","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"d7d60387f6f0255ac318df5f4f2614281f5388ec8863242f937a3fc5a126f1d2c9c0102c83cb8af40d3d50c43a","nonce":"07eaf15d8bfb9104fc2b8597","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"aaf0fc22e7be124c5098b31d9234ddba49322b527f3f43659b3cb81b2beafb9705e9405e2fa3b416fc53d1ac3c","nonce":"07eaf15d8bfb9104fc2b8596","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"966db3b960c39252f2f9962eee42987c5da1ebc27bcffce5151897e55e71001c68d4394c543069f170ca88c0eb","nonce":"07eaf15d8bfb9104fc2b8591","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"f77b1f3a167e7d0293032d0d1be313dee45e675ad92983004a911d9f0138b99711128932a8174ac3019de499f6","nonce":"07eaf15d8bfb9104fc2b8590","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"31818762bd1d964c48d731a5246224628b3892e331feb28fc1bba2800d2186638273ef060d3bf2302826569b80","nonce":"07eaf15d8bfb9104fc2b8593","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"14db3da354588a809ff3c8a34667a9708cf778017799be7543dc6a58dfc3d6bf8d00af2255dcf0fd7d54514fcd","nonce":"07eaf15d8bfb9104fc2b8592","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"e2b356b0e72593536e3ac0afca48b9d0cc0e4702916d14fb0a18a46760f942842e8e39e0f0349b3bfbd1fddf41","nonce":"07eaf15d8bfb9104fc2b858d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"f58e8ccd3bf40de9a2df91d301e9ebccf21eeed303069ca4666aff585785e2007004054a46c0fbd9995bbd1f84","nonce":"07eaf15d8bfb9104fc2b858c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"f326fadbafbfe9e7577e812d3503cdea0108973e62f058349cf52bd5eb117f646ba29f6936e669802d574cf6f1","nonce":"07eaf15d8bfb9104fc2b858f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"153c5f33d6093eaff4a5250cc0a19e6f0836a96f88568255b54d44b4699ab3560a9ae29e307512e1afc000061f","nonce":"07eaf15d8bfb9104fc2b858e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"d1dc8be731c44386cdcee8ca68c92258686c1ed6d08e7fdd726c0455cfcf4138158d81c4770fa901d66184d16f","nonce":"07eaf15d8bfb9104fc2b8589","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"9080ece5f3297148c2034c0b20e9b6ba5433fbba8d00984035506ea88f05f0b66976f518327df43fc558342c55","nonce":"07eaf15d8bfb9104fc2b8588","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"b4c6a2c235e85b34234886231e39275d7dcd38949824dccb74dd4155101c276245ebfa1fd48251e2c28d9c9777","nonce":"07eaf15d8bfb9104fc2b858b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"9d0924d3b01b0e62cc1a9ae3eb57bdaff2e287eb17901c348afdbb5a0526d3ee1a30581c6e264f1a347e8b0a4a","nonce":"07eaf15d8bfb9104fc2b858a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"d93beb2ac1ea8e9ea0385fa2395d94f814b4aba7cb2643be6357432dd9cd7cde4c12bdfb0a0e7d983a56561c57","nonce":"07eaf15d8bfb9104fc2b8585","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"108e52d90e2ac6ce3b09dbc63c72dee6331cb7fd87a938691ae492a452fa4a7b4ada60b38d5a9fb08c714af453","nonce":"07eaf15d8bfb9104fc2b8584","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"ded9056eaeb83b5521ae2f455a88e2445d4f011791c4c859b123cbdfb8755efd551549a6ae467854503aea7af6","nonce":"07eaf15d8bfb9104fc2b8587","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"bd29636f55bb9b34b0d07e33de5845763e7f4d514ee363129c481910fa1b5669e7ddd02646dd9e40d8bcafc1b6","nonce":"07eaf15d8bfb9104fc2b8586","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"3e6878ea08c9f6d34534712d879166c8b1ced2555a7892ea613892a262abcc85f39791604302be7aff100f6803","nonce":"07eaf15d8bfb9104fc2b8581","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"fe26ec3773db2785954363354f2b12c0596a7a1c3eda03f71135b3da01d16fedf691f2fb7f2a53f6fc697fd348","nonce":"07eaf15d8bfb9104fc2b8580","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"40d1338e3488abba53ff9db1f90b7f29fca1fc86bc7bbcff938e31edd5f97435a5befc2d303de454c5ff85cffb","nonce":"07eaf15d8bfb9104fc2b8583","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"9edfb88f645cc8a2f4a953d77d01ba584cbf2bf9d20546a1e976861b55c475ac253105e53028ed53ea40c779a5","nonce":"07eaf15d8bfb9104fc2b8582","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"7cb97debf86d0ae0f35a8c84d5da9aa47cef98c37bacbc921b360468112d4d2da8de5212892257e0e3ca920fa4","nonce":"07eaf15d8bfb9104fc2b85bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"1d07c8f4453420691dbfee2e46cb866a7c5902007deae4128db028fbd7dbd7d0a135aa6a2f75e4db87cfcdd6b4","nonce":"07eaf15d8bfb9104fc2b85bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"48978eb9b48e79da97480f729b5123253f454fc4d7866a6702955ce86f487770baf394f85c7b95c863656e701b","nonce":"07eaf15d8bfb9104fc2b85bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"1bdfed88a559b15c59641467f5baa4a8652f3095bf378e94903139c29f1e69c694b16d060f68db9dfba10cca0c","nonce":"07eaf15d8bfb9104fc2b85be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"879eecab20748e382c09a1daba19a0a492f67544f6d42816cfc00dfcecdf9a666db5bcb6908f73d54f6d43eec2","nonce":"07eaf15d8bfb9104fc2b85b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"9ee9794bc3fc0a3c58e05471e265ff005f6774202ff6a3fd24f4b4b225d900d5675c7d1892298e074e9b38b13d","nonce":"07eaf15d8bfb9104fc2b85b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"aad1f2c09b84cb9d37ed4f28f70165cad1aed0a3d0c7c999edb8535e2fbf1221af85bf3ad7f629e824c7c8a7c5","nonce":"07eaf15d8bfb9104fc2b85bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"6c353bfd347507393bd6496c22e4142a3a356fb7d7db09d4eb2859f6d98134f9e0b74f9326e28f06627638ec10","nonce":"07eaf15d8bfb9104fc2b85ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"209961b4ca837d612c8d6e9c176279b8dac695317f8821f836743d130053d7e3dd87203db301eacc096a1da95c","nonce":"07eaf15d8bfb9104fc2b85b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"eef6fe2a529f58ac8541835e6a5cbea4c7d8f23ac3f4d49958a38d03b988eefa4e15821a6c90fd04b4fd7456ea","nonce":"07eaf15d8bfb9104fc2b85b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"947e5af5cc71fe6317206ccfce7c89248634448a82e99302440754fe941809fc4c378021c3959ab47e8a4b13a9","nonce":"07eaf15d8bfb9104fc2b85b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"e3751bc7038df52202137d8eb20b2b7d6e316eb40c8b2a10894d197f17d8a870c7431359bcbdd6f0a1cc87d77f","nonce":"07eaf15d8bfb9104fc2b85b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"9fc8c39781365626b43000479236700733509764f6fb8e870f806e5bfb211ee5b904d6860c516f46ebb1b4c68b","nonce":"07eaf15d8bfb9104fc2b85b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"a43d92c052f5d77a2db25c3703086c7e600d03422a41e0f759e545421753634fd2a831d7c47794645f6e57d580","nonce":"07eaf15d8bfb9104fc2b85b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"74bcbeaa993dd904ed3c026f1144e9687dc58b2253238171bce1b1bda513a4dcfb3cee74d3b9fb6fa19098b5d9","nonce":"07eaf15d8bfb9104fc2b85b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"faa0fe35f4232d21642f8e6c50d84ed3ebf7834f9c039f53be34c587fc7f8d1f55b416a0e4e289ee2694bf8f9b","nonce":"07eaf15d8bfb9104fc2b85b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"783fd1920c7b0715b4992ed5077d7733a73aa97b3d543f6c7f078f8785cb1467318bff9fba1a67faf11cc2e185","nonce":"07eaf15d8bfb9104fc2b85ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"2d1dd1f2a8b18bba7abd9ff303c5ed0f194754563f592a204083144a428fe695d4a67cb767a4cdc07c6ba4142a","nonce":"07eaf15d8bfb9104fc2b85ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"a9a8e40237762e183bc929da3489962390313f6ad245caafefadeae5ac4e1c9debef4127c3249468cc81b9f2d1","nonce":"07eaf15d8bfb9104fc2b85af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"3852cd066a5f2677231fe07883039bf749e6aa45b972df5f82b6db9bfa92c76fd47ef21b186cc0197947d46707","nonce":"07eaf15d8bfb9104fc2b85ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"d1df273f139938d5f4c63c2703d18da4384d916533ecac168f8b281f34794317c1ddec693db0224a2d0846f9b9","nonce":"07eaf15d8bfb9104fc2b85a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"7d9a7089ef41b41412f799ff561573e5411a1ad138c488a9babd0669d1e9606bb6c920c7bb92e4e293a1454e4a","nonce":"07eaf15d8bfb9104fc2b85a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"a9d66575c3f64f79339a007ffb7b856bbe2c9da6ded8f3487ace8cb79b64dd2afaf1b59c3e86f9ebd290869de1","nonce":"07eaf15d8bfb9104fc2b85ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"ec42b83633d9376a99aba02b4e0fe85b557658782169065a074231078fbf7635182b866d9e58a36eebe4020f87","nonce":"07eaf15d8bfb9104fc2b85aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"13ab874860d09b83d621c7e1028674f964480e0cd343b879e69b44b806fc0ba47a6ccfd038716437df8e82aca9","nonce":"07eaf15d8bfb9104fc2b85a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"4eb2d56fa1476514b7675b39f7f9483f133a5b11bfc69d047bc28305d3eebe51cf150526b03098378cf1c5414d","nonce":"07eaf15d8bfb9104fc2b85a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"1e99c99ad338f5ddc167dadd038cf36823fd948e125664f5d1e744d10c9ac1bc63940b6aa32428ec6b3fd62c5b","nonce":"07eaf15d8bfb9104fc2b85a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"855de732e2fe1476152a98b5f520a75454c3c4e69f76342d8179e3a619b8b38b0403da0b386be1e3cb1105ae01","nonce":"07eaf15d8bfb9104fc2b85a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"3268ffd277720dfa00ffe246fd06dac18fbf0497052f2af7b4bcbcb30bb7f8a806fed1051a1e4e54fe5171d0ef","nonce":"07eaf15d8bfb9104fc2b85a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"bde3c48cb0af04aa1e16bfbd7b70c5db3f5ab8e2e3deb87cc9ce46f6159672644d593515dee5e7bf64522654a3","nonce":"07eaf15d8bfb9104fc2b85a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"e2bca7d451f84f45e092e2cad1c7324d93cffd9058e50bbf312c8efe4deea0e664dc65fb45735c35536222564c","nonce":"07eaf15d8bfb9104fc2b85a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"23942316ccfaba40f959e27c2fcf96e6cd1eb2797e5ad6631303360e55e367e4cd100b1c0261e91f6dc6d8a069","nonce":"07eaf15d8bfb9104fc2b85a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"9e6364550507b275fb4855f4c83365f232a21631d843430213b80ed381fc9d5666c437c13866a73446ef504f19","nonce":"07eaf15d8bfb9104fc2b85dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"a5c45c29d35671b237942cfb489d71bd1002636be963abe8f7693ab6cf3f6bfcef21e7fa1a77b0d670d54264a0","nonce":"07eaf15d8bfb9104fc2b85dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"2c85b483531e00f09ffc04578b66386f5511e68ad34e411bda4861ff4f50386743086c59334be51f47838edcb1","nonce":"07eaf15d8bfb9104fc2b85df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"3c070015fe78670dc1382a3603c3d9df8876448847aa23855b7c94ce9b1c08d9af0c8b550335d6565a0cc5796d","nonce":"07eaf15d8bfb9104fc2b85de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"8dbef886c5982fb5081fc2c7fe830e82a6d34c19fae914c9f48529927c0c03c5a75c2782a15dc97d15ead6673d","nonce":"07eaf15d8bfb9104fc2b85d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"afa3ce22da4a8e1883b8f99d6c1fa3b59055916c226e92a020b4e1f3a6d5e15524becdb30754622cd27143fc44","nonce":"07eaf15d8bfb9104fc2b85d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"62190e87cf0c6712aea1ba1b6c2b582391da8a53dc768d2cd01acce73cc57a1be3e25fa4e0ce3cb457123b0e91","nonce":"07eaf15d8bfb9104fc2b85db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"ffc017de974afb185eede4aa6071f3575cb486fbc23554238ff0a1ddc1a420ef634e9103e3875ece084fcd6610","nonce":"07eaf15d8bfb9104fc2b85da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"ad6abb113a5dc8d48850f865c229bc71152a59c6b5f350ae73fbfa2db3fedf6276bb5bd9d5fc3c0a7b55203f98","nonce":"07eaf15d8bfb9104fc2b85d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"37b3c0bee75e782c26a94c66f5690a426ca4c89385635263e75b53267229f7aaea79699957c3378c4a793a8716","nonce":"07eaf15d8bfb9104fc2b85d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"e2ac97a3d39743469305004682ef5ea2da3fc261f217b66d8fc93330225f195ed2131f14c1583590db1d98d11e","nonce":"07eaf15d8bfb9104fc2b85d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"9dce879bc0fb5594d46882126a09b1d3e7d9ce638eb92e9d94ee110adf818abdda8926de5d8ed8ff852af6372e","nonce":"07eaf15d8bfb9104fc2b85d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"5576a4fd3f6f828caeb2a9ac887e5669edadc80fc6f503615ed39a16e1df62b3a096ead7c921dac35dde01f085","nonce":"07eaf15d8bfb9104fc2b85d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"1d468e0f77ead64847775101ff9e09e3801ccb886414164da254f7f12bfec24a5fd63da8e8cb9b29408e4c5f6c","nonce":"07eaf15d8bfb9104fc2b85d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"7d8d1231b9fe5b9e744eaad9f3da64979b21f2990185fe16e8f158536f362abd701f82f9a83c30e05985ef93f2","nonce":"07eaf15d8bfb9104fc2b85d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"f84b7dfe54b0d9c31d72403158387ddcac2720645759fe7176d5a9a14f2d3d9178092decbcb2836ac720ed9872","nonce":"07eaf15d8bfb9104fc2b85d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"61a01e63c64e87d736d9a2fa26c9b556c76512c9e708f0d26a1a4583c173419e19592a0c26c382a405fdef3750","nonce":"07eaf15d8bfb9104fc2b85cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"d3f685b5be410731b2963ca3d9cfc9d2d09331e2949e8ef4d8797ea3760f87155118e1f946df78a04e08780b38","nonce":"07eaf15d8bfb9104fc2b85cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"a059c58b4a3496274dc6e717eb6545838f637a785b683ef428689d4c4c095cca6dcc7072e966ce1a20269f80a6","nonce":"07eaf15d8bfb9104fc2b85cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"36b4f37a5ac0908cb358b2343a3dded1730658eb2214cd5bbddc2876418b4dd78d99a5d63719a2618f68f5701a","nonce":"07eaf15d8bfb9104fc2b85ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"a57c6b76b329273e430268335d4f417d99560fb9f45bb36a305def1501332167c551c123aef08a184f85b348e1","nonce":"07eaf15d8bfb9104fc2b85c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"0e853cd1feb9cb02112097702f5ce8d566cb9f524f5b6fd8a84fb13ab17a306ac030097bb8131862f49005f419","nonce":"07eaf15d8bfb9104fc2b85c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"2ac27c8e2217b4779bb429c85cfd4286327be8719a22771d6596c570f2c555fa6a636be1197cfcb1eea994ae8f","nonce":"07eaf15d8bfb9104fc2b85cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"5f625053e5b6beee97e5da16a70721844e519cbbb652fd6737d8359c8abe04f8316b28c7b41b27851728a14647","nonce":"07eaf15d8bfb9104fc2b85ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"ee89079482fe1be0fe6b6af9816b2fe410ce10bcd3bc7256306bd1af2df63f7b92abad5726349c43009e7a959e","nonce":"07eaf15d8bfb9104fc2b85c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"52622f9987401bfbc7df9edaf9c7b280962ee8bff5c798d8fe11541ad4d513fc66d3364bc4c544fd875a83cd3f","nonce":"07eaf15d8bfb9104fc2b85c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"29f378c16d22c5c1963e4d947d95dc225cc6146408fb18d52cf06c4eb4c66d37ec489c1e0084b3f179adf896bc","nonce":"07eaf15d8bfb9104fc2b85c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"34ba2b86e3f5817f9a7cc87428e3bf9328a8aab6a72c16e03357a10ff0ca537a133ac6a227f85adfca0fa0149d","nonce":"07eaf15d8bfb9104fc2b85c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"645a13b3f51acf07f89a3a84e2f5b5dc880a3fba389be7e35ac99732595892e832cd7d04e6583265486b90cf0b","nonce":"07eaf15d8bfb9104fc2b85c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"6d2c6d4290b8430f1881f87b12cbdc1800f9ff489b4ac5cd8c8b3919a8fa215dad4a16dee8c600db3abcf4f8f3","nonce":"07eaf15d8bfb9104fc2b85c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"faeb181da79ddda2e472e6ed9ba4682d734bf642d7ae67e5393c35bbc3a138210f6648a1fa88b5fe76cbd8d692","nonce":"07eaf15d8bfb9104fc2b85c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"798b15e1f21482af392d95fa4e79c8c9b7f9c57317642c20292f5f5a367472db7cb1b48d5df770b32b15b7e8cc","nonce":"07eaf15d8bfb9104fc2b85c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"8151892b3c6aab0c241fdac0e026d8dd637cf953a9948ab136e569ea1213676481ddf5bfd0b1d9c99b9e02c8a4","nonce":"07eaf15d8bfb9104fc2b85fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"3d897007f48035eb5defb28f36363d87d0fd86ba4179876c5d969eb4547393baa2116007237131560e6cf9ad2a","nonce":"07eaf15d8bfb9104fc2b85fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"626e4fc885fffd2fab5a8727ab3b2a71f4bc1208094f2c13177ed0de894c26b36b2c6fabd1e26a06fc6e88ccc3","nonce":"07eaf15d8bfb9104fc2b85ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"1852a0f1645002f7f07f2c4da55e87b0a489337ab4686b12847672554d8d3fc908995375a24ad115a7bb7ff731","nonce":"07eaf15d8bfb9104fc2b85fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"32916f816e95322de773adf6110b558ed7dc7df3836f7b716931425299d12603b8667a9213bc98115168db9d6c","nonce":"07eaf15d8bfb9104fc2b85f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"06f103c90723eae0ca8eb8b778756c5a74f0bfad4b830f811633c1dc2903dfc7c2701ff6465cf5aca69d6302b4","nonce":"07eaf15d8bfb9104fc2b85f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"97d9c9920c70ccdd7e077d78c67901166d89822b1531e1665abaee6c9fcfd9100a56f73ac982e83fe0ae43a47e","nonce":"07eaf15d8bfb9104fc2b85fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"d465b8a5ea76c859ff1fcf70e748db54f316296b65d4660fce473a6b65a359da38f7fff012f9870eb9411157f1","nonce":"07eaf15d8bfb9104fc2b85fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"46366dc1526f071fe426a2bf21710850a9bd838b8f2afd6bd5ec790415b713f16204759a580691c0e2e1a785c9","nonce":"07eaf15d8bfb9104fc2b85f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"1ec6854f5520d3fbc0fd2a6311e6a9096a708e7ec43925bcda52bec9dd5e54fade81653357398a736c44eb5da4","nonce":"07eaf15d8bfb9104fc2b85f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"defda2f8ca5caf4c6466e9f827b044ca59c1182728ff67d0f443ca139ca5e83a806a705a4005ca99f75f6f6986","nonce":"07eaf15d8bfb9104fc2b85f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"f8128491ef8e908840ddf17d44b24278f2c10cb19af92587ac15b2de856b8e13ec0b92c87174e610583d2ce12d","nonce":"07eaf15d8bfb9104fc2b85f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"af1d02b5ecaaaaffed3344ef62cd4f9043b5ad317c27cb3651dfd131d86a8f10d2b174aeded3166cd37fe58022","nonce":"07eaf15d8bfb9104fc2b85f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"7dca4d071cf7d96b3f064994a9c486550f2787e591c880a0dddb31e9c7b9e336c2b94b572df62f97fe43a889e2","nonce":"07eaf15d8bfb9104fc2b85f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"32b2526ac986d612e3a1eec530d51be3d9ccecf3d0f72fc85eb7d2a5dbbe519faaf45a2820612fbcb720fd5e50","nonce":"07eaf15d8bfb9104fc2b85f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"47e4f5dd23fe510b60e10ba4db6251abb334757cf7c57173886165921e75008e2d3bc97c4ce7356816d22ec751","nonce":"07eaf15d8bfb9104fc2b85f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"30b6d41b0f90d8646785c530b1f83c52de98c102e7f361283c0c4e33783ada230bb6c5182aa0e342184b93be6e","nonce":"07eaf15d8bfb9104fc2b85ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"779415b929aaa0b8c663a3b80891bebfd9d71e4e243f8bbd69df14a8be10e87bd85d39f63566ebf8cfdaa7ce12","nonce":"07eaf15d8bfb9104fc2b85ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"47e609432d2543326c5db7744b843ebc7123b62ba1e13a2789005934b88169370debac70067671633331a2c66b","nonce":"07eaf15d8bfb9104fc2b85ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"ee9cec82e6b62fb4f2ced9546475d6b5c76eee5106cf3e3b11729a54c37c5169a951e282dc7dad4bf43ce58ac9","nonce":"07eaf15d8bfb9104fc2b85ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"30ca0d87492ca208fe411909ceb02785a0d681c4c0c242b5d8ff3259adc93c87bdeadbc3266c57c6f725bc7850","nonce":"07eaf15d8bfb9104fc2b85e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"2bcf8f9bf6ff5f518e4368ac7ff9e2ca737a34ca7cba23359123d36b305058809a95c2a285fc3d2ee93c999c5c","nonce":"07eaf15d8bfb9104fc2b85e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"ebf87d10c8c0eaee6e90ac8091fe264e5d83fd71348f8b77d4716daa58378e387f771214da9242d1fe28333182","nonce":"07eaf15d8bfb9104fc2b85eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"c9899f5d755aa7ad37e5a91ba2f3b627fe2229180f4d9af26560aa5018d2af4bdff962e72d4bcd686f108b13fa","nonce":"07eaf15d8bfb9104fc2b85ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"88332c7f55fbbe5ef94b6b8030474f197ced676edf68d524b98bcf2fe47d1a65fe7494873a2096def9fc20008f","nonce":"07eaf15d8bfb9104fc2b85e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"c1f494f6514ccb1cdd62c81fabb69929d9e788093f5c5e6936a5293e5163c3ea88b3f29d90c4468778ffd7fdfc","nonce":"07eaf15d8bfb9104fc2b85e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"732d6b255ffa7e9b487ac825a1a1893fff72608b921dc44d7e35b69a1d93ec467bed42038206c55d8d3ffd6b2d","nonce":"07eaf15d8bfb9104fc2b85e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"0c485c3cff74e933d83d95cdbe67d48f6bfc4215f8aa04a9ec12ae57db538fb6217bd6837f7fd2d9b4282605d2","nonce":"07eaf15d8bfb9104fc2b85e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"cde33f0e16a6fcda20384925a3fd8c94fc61439b1c690eb471f4f862d6be554bfc7e55fb3223bc7451819218c9","nonce":"07eaf15d8bfb9104fc2b85e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"c748f5555c8fababf7f6cf7d8515be2132d7569ea6cfb6d7c434e7a29bcfa5a5d4f47d72112b2ac55464a985ac","nonce":"07eaf15d8bfb9104fc2b85e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"5c9cccd2276f992c179ef89c541ad5fec5e0427b62d00d2cf147802b32e19cd51271b1ca32e066754b7b8ecf72","nonce":"07eaf15d8bfb9104fc2b85e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"13822dc8aabe3b76c61c771b154c39bd75af9cabb402b7232495a10c2694742f0de6e47258ea94201f256c592d","nonce":"07eaf15d8bfb9104fc2b85e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"07a99443b34e8e182c881412783081513507f1b762520304b1d1599ae377b92893522640c25444ada2245c7f7c","nonce":"07eaf15d8bfb9104fc2b841d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"d9d957949e909a759151226f3fd56b83bc325383f21b37b87d42e81fa02b7887"},{"exporter_context":"00","L":32,"exported_value":"8081a897cdfc12ee2a6b77665644348fdd52024ab6df23ba3e332b1dd410c69c"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"0316e7c7228d4bdaf0ed5eeb62e85b46b24d784711a175c377186d1807a9899f"}]},{"mode":2,"kem_id":18,"kdf_id":3,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"3f3c12492eee6f1f8029a89002b6539ea9754b48412c14d2fe94368cf1fa473f0171cdb1117aaa447ad6914bfb794ead14a9cd22cd83caa22bd905bd7d614d401ddc","ikmS":"02d1581b120d0415bda1fb2cbe6a3c81edf28209f0fc1460745ad9018747c31e6d42a36ed1734214312311db80bb3f88c2da6ea7624cf2915d32f2993ebeb92c2934","ikmE":"0e5ec115c172744e793ef333abfd5d9838fd31eef595f0b77a2f5623404aa42f0e77198c2ac78defeae75cc79cf5dc5c7587b6eda733e48f3b17d5e3496482f19cdb","skRm":"003057de4eea0c3d69d7adb681725840a6b12993d01fea25f77fec0152e9cac6e2773d50be68d32ff8ee91e199e108dfd9d1a339b13a12cb391fbbf6002e246ea727","skSm":"003cca20fff091ee720d27962c16df28c00b1eedbc9ffa075cd803633480bb67b27eb7f51d9327582979ce2564cb30d554d3f38e20c1c2b4800654e335a16a097b65","skEm":"01821ed9d92632a1d419d88bdc2183659ad469bdab6b5a02ad4b0fadc8fb7f7d4039c035a5d0dd10e74f1147bc881f38fc9b128afe24c1dd126d28dce89aca0c6bf8","pkRm":"0401045406cb181897f1dc5d5df704abfc98f1362a5d10767ab662305c994e57c6a7778b640873feb12d1324936bc8fa9f1ef611fafb67e959fe9d150d6171d9839c9c016686a75d943b99294cba531457a21db66d32a857f6be1465d25ef91a3dcab2c19addca3a0b7c0c55b2b85ab52d9e0bc7f652bb8a0035bf52070ba6eba1b1587935","pkSm":"040130fe47be7e02492934f677133cb674d2937de86d1760312cde59381360203883ced55deb54001b8f3ba04b208aac6debdde298df8564d2a643503474a7359126c70107d12509f35982aadca5dfd1ba3901a9e7c5165fe6f9fdd84df6530be060d1e69456eea6b9dee8ec4ae6e548f1f8f6f3f6a37ff30baff0566e955f6b124d402a1a","pkEm":"0400a9607fbf96874b3f004e1655c497b3ccefc6c0881cbf19a58f801a572904a0f1895c55f4874293e730909c615c7d772f0f264d3ade79628768639e09bbcf48842501c35aa8b265c848705c0f44325e884596266746c75a5b577013e061f9c2c894ed9b311711c7b80bf11dc552cb8d6b1101e8fb7999e56abf3626cc07c1bb5c1fb562","enc":"0400a9607fbf96874b3f004e1655c497b3ccefc6c0881cbf19a58f801a572904a0f1895c55f4874293e730909c615c7d772f0f264d3ade79628768639e09bbcf48842501c35aa8b265c848705c0f44325e884596266746c75a5b577013e061f9c2c894ed9b311711c7b80bf11dc552cb8d6b1101e8fb7999e56abf3626cc07c1bb5c1fb562","shared_secret":"c5fb6471c9b8d5f03579664cf04ab831c1ec97265e7c3ecd9569fbdd886f689586668d40271e10e1ab867335be404a8d46feb76c0638b1e7338d07ab32b98a2f","key_schedule_context":"0283a27c5b2358ab4dae1b2f5d8f57f10ccccc822a473326f543f239a70aee46347324e84e02d7651a10d08fb3dda739d22d50c53fbfa8122baacd0f9ae5913072ef45baa1f3a4b169e141feb957e48d03f28c837d8904c3d6775308c3d3faa75dd64adfa44e1a1141edf9349959b8f8e5291cbdc56f62b0ed6527d692e85b09a4","secret":"4a59a771c67da727b1cd17178bcaecc3b85b8fb90298bcb7b2f55dd89143efe33939731b1b6817fa8332d2a1bce7f9ac3ddb4a6d320228c11498e9c8d1496def","key":"bb4784ce90885ac815d16e0fe5a383f884832709081454bfaa995a2f88381cd7","base_nonce":"b11485b497a8deec191e7b53","exporter_secret":"ecc1e48df1e954fa0895fe596cb2aa590c7561148107d00dfbef02d41b2a0b8b6daa7fb3d4a5697e30a736a14f35e675d090726d0105fc99c2d5214fc082e0da","encryptions":[{"aad":"436f756e742d30","ciphertext":"4ee6c1e2b7fa65f5a6da8d6711d1fb88f85f633459041361cefed80d9461052e7ed50ac68dc006b0b72e8fc9d0","nonce":"b11485b497a8deec191e7b53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"e3776a04ad5a72583da06970c6e492b16f2b6352f3f61c7b442feb75c291ed659073595e9f5810e1250e489c4f","nonce":"b11485b497a8deec191e7b52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"38f82aaaf1435e7a1dc716a594f359983734a150467858cb8db1745c0bba1b87eb646dbf69f852f121b8a030fb","nonce":"b11485b497a8deec191e7b51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"0e3113a50833f6b2fd57b64db463b68bcabad2cf5744edf2612d7e330edab6c78234ba239bc92cf3f8c94db4ad","nonce":"b11485b497a8deec191e7b50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"7b218dd6a38559a7b1970038018e5a680896e44f3f84c3e3def263e48a04c70b05d6abf4210562e0c3b75927e3","nonce":"b11485b497a8deec191e7b57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"20c2350a09656a42ba3a4facc55bda821ce67e39db5e2f5d099ee3e4877f0d209eaedd395ccc5ce4238a910de9","nonce":"b11485b497a8deec191e7b56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"f475f4b76470b34960e7b76c5a40824b4c4e16c4eb5a894a77129fb4b2d5334174200c99069c75c0118bb7341f","nonce":"b11485b497a8deec191e7b55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"f8d004c12296df4d8f34b3e74b0174c7de57cb5176675fb81c1177b13ec6114c03c1ea68a06811b3e8fc2d4caa","nonce":"b11485b497a8deec191e7b54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"6d3e103efaadaca3eb19e5a5bf2abf2a27655e6131b4a71603056a67480bbe0de8a9e8849c6cc3ca80a23fb4a8","nonce":"b11485b497a8deec191e7b5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"f52dceea23b0fae805b7b5ae96514954ac45dd4af01216e8b01f6e5d265f3eb9a70bd9d1b582244f916d13e300","nonce":"b11485b497a8deec191e7b5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"05ad15b554ef30b714dfdbe5bf55d82ad52dcc54c3212d6a08e85e5753a1f334cf8b2d12cec7ee393c5b56141c","nonce":"b11485b497a8deec191e7b59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"63f6d5a31fac6105adaece960d85674952bdd5c0ce0040b168bd24d4faa5836f46c1b10e6160f14a20aa33c43d","nonce":"b11485b497a8deec191e7b58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"8114f6aab04434dcb19c598485b23a69bd712d20ae8ff30f9a2244fd664fdc760f19517d4ad419818463f9e704","nonce":"b11485b497a8deec191e7b5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"232492265f2c38ba384c83daea5382f17d7814e83ed4dda2e6ae3de7dc456f204a36419349861144c543b88e96","nonce":"b11485b497a8deec191e7b5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"289152c9f55b3662cd413f98c16e40b2da1993cbc8afd267f07f4b252d428e122c8c045aad0cb230c989da4aa4","nonce":"b11485b497a8deec191e7b5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"b6c90563fc425a5591c6c47f7852f62437993ad534d148b9fd3dec8ff6394dea7dc8c0f767d78c391a5837a807","nonce":"b11485b497a8deec191e7b5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"3ce17a80b40ed85eef92981ee2521b5f59664cf5788203f5388c00f3939cb53e911e23452e374d3d521288770d","nonce":"b11485b497a8deec191e7b43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"0c73d7afdddb8d15f1761a33220abbb7ba9e799da3cbe6d71592b22ff1fc16a16c1a01aa81206b0ea35433531e","nonce":"b11485b497a8deec191e7b42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"df042cd9f8a227e4190f193df3f7e2c4b9852348f07dd9c6e4750542790cd8e87670f9c19f1913370b76ee52b0","nonce":"b11485b497a8deec191e7b41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"7dd26e60d911b1d7181a343cf2460014ef635307c3088a1372a0dc417da6540811b1beb405f187e3164c7c8c97","nonce":"b11485b497a8deec191e7b40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"7ad9e1e350efdbdb770cc35238335e0d064e0bc6988c32de8290895193541a4dfd85bec9857d2af0b4559a5348","nonce":"b11485b497a8deec191e7b47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"8ca3502ec6f73dffd2542dc8a81bab1e840f678472a88a905584d0f1242b09ee37538e9234d1ec8bf94b20db78","nonce":"b11485b497a8deec191e7b46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"de4a38a1a1269323412951d0e1bd52741478885b834c1f324436c37daf322b9fd9d160fd9904a64a7524331ab0","nonce":"b11485b497a8deec191e7b45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"262dbc66bb62f0f2f6cb12a21116a20b133c20fb50e4063faeddb1b73fb680a45da6b36fd9e9c151c6294c71e5","nonce":"b11485b497a8deec191e7b44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"bb490756ce6182204b848edc0a96d03fd93586575aa440b7348604382ddeecf08a7635437703c13d2424ced562","nonce":"b11485b497a8deec191e7b4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"cd0cd97913c55c27a5548042ae366d1ed95900b664c0aec49b0d916cda4f8cbab6cb27e519a85e7a95405aa90a","nonce":"b11485b497a8deec191e7b4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"d8dfbed1a71e404b5e24b0b4a743e2349ac7f7f51b224079404ae4465368ad9e5387fddff0f3550dc8379cc6be","nonce":"b11485b497a8deec191e7b49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"cff5c256e4956a4f56ff21cf44837015ffe950eb5f1ab8cd3ca1d570006bea1aa666a9b96d782468cec348cf07","nonce":"b11485b497a8deec191e7b48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"93f81fbc240f5c80ed2464a65bc91893153b2aaf03e0c79cf3a8a5bb1fef37ebe1f8055dd1910bc6ac05953981","nonce":"b11485b497a8deec191e7b4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"83b3bf3e94295f8b724f65ce588b659817edebd4d8774fc018c76e30669ea2060563038383e684a5beb619f944","nonce":"b11485b497a8deec191e7b4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"2240e23469136d220b86f2d80acdecad016524027c67583f84276de0bebbc8540aef661121142da516bfec2c9c","nonce":"b11485b497a8deec191e7b4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"61c487fd7c829f4e39a2c4eed84265389331aa1d505ca0542c47ee8ed16fd3c426b167f79136b52488cb26d11a","nonce":"b11485b497a8deec191e7b4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"8092f671d62173163806f8cb273294a3099fc9de4dd3d439947d692063b2b63b0554df0eb0f15c7861e2741e6a","nonce":"b11485b497a8deec191e7b73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"7efc6f09c52d4a639b73fa278a9b0b678961a6f5397a33ad22d610572167ceff9b9e47d50928e01a68d1bbd40a","nonce":"b11485b497a8deec191e7b72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"dba90a08f225e3a08289196c82b0a40ce44c71136fa96fcd6f367a7bd6ba17d54f7f557fa19af6662f64ad3d66","nonce":"b11485b497a8deec191e7b71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"b25c54ca27eabec2df9b33aeb2130a03a6c471076602406f0d58aff9d6a84e65e0921e5effbac6077c8706efc7","nonce":"b11485b497a8deec191e7b70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"f5772ef9182a5676bc20f61b397b27bec73df9f606a712ccd7a6d8677a787ccaa44c07d3545ef407fc6499166d","nonce":"b11485b497a8deec191e7b77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"b6ffb94a30300d39536b87c54b04e164df797db8ae6ddebdaa394d568813e9618f8b6ef059459a0dabb47c0905","nonce":"b11485b497a8deec191e7b76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"d4d5290708b672cf38135ae13b7a44dd5aa3b676628a8faeeb7acbb626ecd926a33b82db697f4c595ada1c4682","nonce":"b11485b497a8deec191e7b75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"61692cefa091106673b321e4407811b179bca3cf7c4372bd62422107297d9f5347d962bf1fdc2545b26b062e42","nonce":"b11485b497a8deec191e7b74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"6daaa32bb390f0cebea3bc62c4737f743e5ab15dcabfd10f41e8b44c6d61c8f46f825c71ce269f236ece40472e","nonce":"b11485b497a8deec191e7b7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"63a252dabd70d7e89164a05f8b0010c61c2ddcd4df98fe3e6d49717411204ef1453bc53f0d4c1c95c8078fbe17","nonce":"b11485b497a8deec191e7b7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"b5dc13f95dc63222f2e76e475d489ea6369ef9d32dc317519422c9f404fb08801cae2207aab1d77b489d6c3fce","nonce":"b11485b497a8deec191e7b79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"313407315ef5d0920c360367156961649ed86c12ef79141ae24aef2ac4c0911a892919cc1934e3426b62944ed0","nonce":"b11485b497a8deec191e7b78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"563ae848157c209850038923b9445b22c8daf5ae30b845cc395245f53d00c09cda18393fd6da5583ab32d12207","nonce":"b11485b497a8deec191e7b7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"e6e4a0c1b92d2ba8a32ea06bb3c849ca840b363287e0bd9586cd957cddc56b63cf05b7426bb1c3ef9c5ef83173","nonce":"b11485b497a8deec191e7b7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"73ac69673fd1e4dc08fcdf641e89ad215411a6ec1e037c0cf1f51010f4c3b975563faf6395274fa93fadb17e94","nonce":"b11485b497a8deec191e7b7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"ac5270a95192df60ab1258131e0294b732695314e7d259eddb276efb8d6166233f2bf14be0758612ab0b566136","nonce":"b11485b497a8deec191e7b7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"f31ad74b72708e907e303c0f5ec8610ff67d57fd7ffd905ee6544724449a24ef28bf11848cc456a2a0996c51c5","nonce":"b11485b497a8deec191e7b63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"31012397a3cd72367d4995ad6cf0ea77620adeb70def1c47274caec2476f9c161ec0e6252e0cb46b33497f4836","nonce":"b11485b497a8deec191e7b62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"3cc27bd07a4432942fdc7f06bba4ab1cab7361d7d6de7dc8de739c87449a50668233e5dfe1530e6fc3311a7995","nonce":"b11485b497a8deec191e7b61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"cb62fc8dfae91fa8ec9ab92d629b4fc564f87ca437f9782d0f6b7b635e3d16bd296fafa002b2f48ea55ba32fa4","nonce":"b11485b497a8deec191e7b60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"16d45bbf6ec5afb16f8517f0f2f222e28805e54991c2bcddf1ed465b1d016d705129f9c8265bceff737b6219b6","nonce":"b11485b497a8deec191e7b67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"58d9654c31b7adf322c4bf84d829616174fd87ee5a46b31cf7b3a5e94366174ffc1b4aee81ab851b2fa32dda9d","nonce":"b11485b497a8deec191e7b66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"8b6ebd812ec5a022b22c5469de9428193984a98502768876167676f259b1457783680a571ce68ecea39b5837b6","nonce":"b11485b497a8deec191e7b65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"d5bf270173ad4d12157a28d46f2764f157ed33174970b9bdaea85952621f3efc029f811ec98853b66ff2f01ee6","nonce":"b11485b497a8deec191e7b64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"97a9a2ca9b5b4f58eef2963d3eec564af98f9572d8c4638885ebc4dcb4c75bfdaccc8ae877e13085abcacc9894","nonce":"b11485b497a8deec191e7b6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"fe71a84265e494e142f7052d5042a4bcf391c18537922b15b4c108b4bbe2ef6cd582a4159c3af73dd8eb804dbf","nonce":"b11485b497a8deec191e7b6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"394116511533eac6596e720be76a58a734cdeae6cfd540f4ef4ebb2f10c64bf284c23964c8a86188f090443b00","nonce":"b11485b497a8deec191e7b69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"a75442ba24a43522f39f1e314dfcff545c595b38c5a31f4057464a8e9f438c1af0cc61dfae872e1396f1f6c0b6","nonce":"b11485b497a8deec191e7b68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"5320ba3f8fd1d0714a0f63d1ae9d558387ba758e368b1ee431857008b88c94896e03b706703d79840ba3771f0f","nonce":"b11485b497a8deec191e7b6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"54ae6310b474339683c4ca95252519e5fc4b192f2fee3b0cd6aaf7d70048e64e34130b5911ae6e2e9cb0793cfc","nonce":"b11485b497a8deec191e7b6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"a4a0fe414c560c4ceb543f3d47fc9c7bc45cd63e8134ffec17613bf2c8888661c73e8ff6d06e7b9f1c55025879","nonce":"b11485b497a8deec191e7b6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"a999ca20fd87ec8e28327a111f01c0aa1bd5e2c9f5e04bf8fa113b92dc55681d44ac532a05bc68bdb97ce2afad","nonce":"b11485b497a8deec191e7b6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"959be20ce20108dc94308d4807ba11ae581b051ca52a82b28f2e4c474372c50d8d011fb13a9e52866134ba9014","nonce":"b11485b497a8deec191e7b13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"73461b26a5dc1cba17ff9a50c01e6f96dbdaafc7b6853718d95a6901a495d24a2e34cf139e8d032f9522861e1e","nonce":"b11485b497a8deec191e7b12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"ee835fbb45593b23e931fd2910a76038fd7f2032225e5cdd82a9c3c360787751b7c8d3cdec71b622a3661e3183","nonce":"b11485b497a8deec191e7b11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"e30457538d52c496c46c944c954b1898fd8c1b88a9bb593cd93cbcb80fd7aa85a07fffec53f49af0e990036170","nonce":"b11485b497a8deec191e7b10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"4d087011ede657a6489e1a09c54726603b9379c504e7af9dca15c54206afc05238284cffe0cfcec4a00d850cb5","nonce":"b11485b497a8deec191e7b17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"a7080b65e73a40483c2b034c838e7d1f7d30a8340048bbefbcb6819f206e2b5e580ce8a6565788389ee0d837bd","nonce":"b11485b497a8deec191e7b16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"139a384d30e695cface620af7c729b034314b03d360d80d3ea1db271c0208257c72ea7dd2aaad7333fe94c8a5c","nonce":"b11485b497a8deec191e7b15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"8027bb9ec9dbbbb7c6d60b903c7450e979f27dbe31478b37a18b6e096b1298e4361c6ec9edf812f70692b9a66f","nonce":"b11485b497a8deec191e7b14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"f37feda89f83cb115d33ccd5708da162733c86ac2235b89369abedc1e28e5f03e5b5d6f5d65cb680774dea45ff","nonce":"b11485b497a8deec191e7b1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"5e12b8fd08e8f74bbd9ede6cdd9db367b7e23f83e22bbd0bd29ba629aaaa798857e77cb9750dd6c207bfc3d571","nonce":"b11485b497a8deec191e7b1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"0c43f888779a246cdeba2bf4a25af7074d9d785a3ee59bc1e200ca51c8213c844600e792489e7dda1c87c890a3","nonce":"b11485b497a8deec191e7b19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"b4b0c124ac969b8db2e29ff199d18a6ccb950a8efc16a4540ba2e4a0ff3bac287a26112e8bc96af91dd23d71de","nonce":"b11485b497a8deec191e7b18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"21e7fdbdc242e04263abb0dd2cdca3dc07d01cbe48b40d35d0e7b189955e29c0465918715f405ebdf51d51d822","nonce":"b11485b497a8deec191e7b1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"b545c86bd66aa4c222b21dce9b467ca597f5900e8a0e1783701026ee655aa3a3a1331a6f59f0f5941b9ce124f6","nonce":"b11485b497a8deec191e7b1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"44bf03846613a693c29602a20baa526eddf60a4aefd1fdbf5ca0567b87b287d8c2eff75fce41f67f7aa7000980","nonce":"b11485b497a8deec191e7b1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"43360e5c980f9f99afa98841d541c34bcf39649cbb29a6597fadb668fb2e3a579e2ca09d43be7e8bf5ed62a4b9","nonce":"b11485b497a8deec191e7b1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"73ab6d1bbc33b4ace61c36f5b0aa5213a0e98105ae751fbb64f1b6ef21cce96ec708dcd1122f6742f1ef59ad94","nonce":"b11485b497a8deec191e7b03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"5a9c124fb26d80aa2fab8b8c9b1850796d1f359f8e587117d7c1db423d73e042de1b8f5bff0a4c941fc935dbcc","nonce":"b11485b497a8deec191e7b02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"4885c52c946a2779ad5a59cfb4f1811a74ddb9c3199e2079987a6786a31b16d96535d5799f554f21689a8ee1e1","nonce":"b11485b497a8deec191e7b01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"29ee6dd8e8e316389b3f517ef3d4d4e9379c743bc0493fef7d0e8a2e7ddec9c4fe96a852c93863fed09431f0c0","nonce":"b11485b497a8deec191e7b00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"86bf537b1a331f6cf12764973c7893243a16c2e6fcd350f5feb78313f818b616fd671452529c7d21adf506ec0d","nonce":"b11485b497a8deec191e7b07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"961de18e44ebc74e6086ad47fc5886d7e08fdbf2f76eed3e7d44559eca7101a8a92c432472812d577a7af60a40","nonce":"b11485b497a8deec191e7b06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"c8e04652263b666f82172d7fd2ed1c9d91e6ab19754f0c6bab6beb2b996940005d2d74dcc46cb45abfbba8fe98","nonce":"b11485b497a8deec191e7b05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"79466a09e2b967de928179c65fa76e1e177948c6fcd995d6656ff93bff192b07186262f50a8a4b7ed6f9bd5160","nonce":"b11485b497a8deec191e7b04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"c39af42063c0957d9d7ccb1860d588ead89f32d1795e2296fa8255f0d1b9f88bb925c956d56f1b6e0885eed6bf","nonce":"b11485b497a8deec191e7b0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"abf2c225de0f62447eeec81e6da12ffa836595e020b6fab38ab9460044eb7f676a460c3d600d1a015e859fe511","nonce":"b11485b497a8deec191e7b0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"274ab3b2549fdda0ba47fb3b229231d8afe9cdc14fccd2f709608773942421557a7c4055ffaef08bd8a60b967f","nonce":"b11485b497a8deec191e7b09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"05b7fca956425f945abdf6379b2bd7f7433e5173be0aa7ca1d6ff055e74fa5dad47d8a4b6ffb38f401e4ae4e6d","nonce":"b11485b497a8deec191e7b08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"e834b4a4a62f4f91f89aa3bccc612db346aa6a787d1b583773cd1304ff8fe0ae7bf5d2dc24aa06ddaea0ff55a7","nonce":"b11485b497a8deec191e7b0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"4afa7096ba07484e0288ac575a2fca9c5f6d06e02affe18f51136faa2f4dc5256ea0f352b0477e7bb707c07f66","nonce":"b11485b497a8deec191e7b0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"6e618de2ea0c594e0083dac30808b8001fea7ff2ae029ad4eb46bff97d013c8c8ce47be221e495b43e9b455026","nonce":"b11485b497a8deec191e7b0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"d4b1a5a510a6b6f1bf4bdc3857eb7d120db0b337e421e47036eaf48ec672d7eedb7ae0f2af6e4e04f6671dc704","nonce":"b11485b497a8deec191e7b0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"7ffefad6d3de4d89e636468d9c9e36e7d598bc64e0f249c8ed911a84c59ccbb14be9e9cb979acdc23829b7442e","nonce":"b11485b497a8deec191e7b33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"33fe12899f2cb61f0498dd2dea9ac79fa3b009ad576856db909b913b5307eda07b3a3352f5d2ae4e4d2b1210cd","nonce":"b11485b497a8deec191e7b32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"dd74b528679693cb5e23cf7d47a8a78a6fd6adf3168f6dab405b9020051a4e2f228da8cc0c8a1e64081106c9af","nonce":"b11485b497a8deec191e7b31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"4f4b4dbc911f1be4d61275a14012685f685f83031d0be05075254fcb7f853a065896b69413260f24d507e50c6e","nonce":"b11485b497a8deec191e7b30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"62742ba5464cd6271a8424358d06dc72cc7edc0468b5dd4d0ec605c6571f470d51800274daccbb3ef12ce59dbf","nonce":"b11485b497a8deec191e7b37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"1fa9aba4f7021d1afd76c4e2f04c9cbc02411d809ae90ec00b4644c4f0ef052590a71008f614572648a1b50cd5","nonce":"b11485b497a8deec191e7b36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"5aaddf35293217ef12bc546ad5be3eaecee7404d796e64f5016996c2a21140829dd405f714951f351275cdc41c","nonce":"b11485b497a8deec191e7b35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"2df1eab970bba924516790c67c03dc734ee883018415252611aebb889967d17e602a5c5cb85893492f6998b0b2","nonce":"b11485b497a8deec191e7b34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"345d58211174d91aa5e7907144d74516bff617ae0519e5cadb295388361ccf2c77b1be824eb253c7a6b4de1ce8","nonce":"b11485b497a8deec191e7b3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"10d306a7a8c2e2a7ea9e80ada1670398d3e00d2e42559c5435edc61f6ab3d9ea0dfe53b2195369899752081a9a","nonce":"b11485b497a8deec191e7b3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"084669245c4530824796db6340bd777ee01a8e152c7159550a54489b752c601f2a6a897552501c49837fd56b97","nonce":"b11485b497a8deec191e7b39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"20f0579eb78989e6a2ed30575d8059217257eccc62bb7452c8d7de4adc64c0d78f3e68b07bf0661705e73bfe98","nonce":"b11485b497a8deec191e7b38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"c15378e936f215cc735cebefc3ceb35b3da56c6ead1c2cde7824862b605bc42b982b8b79aff5d6f79889c184c0","nonce":"b11485b497a8deec191e7b3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"482a8af3e82749f7f50089bcb14ac66a32ad1678e67ca14c956c6c54686fe99ab0ae034862f9e57351b3aaa758","nonce":"b11485b497a8deec191e7b3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"91984cc72f402665032ce35f3495fbc620619f4fe0c8b135a854da4e63f084831543a2354dd4c1edd2c6bdff11","nonce":"b11485b497a8deec191e7b3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"c7d3839f5ad1eec2b1acd6eadeb2cbc28043fe5d9b1dc779d2f2de7a0adb80235fdc19c9480d7774447296c212","nonce":"b11485b497a8deec191e7b3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"444ebf4ea19b0738a7fb512fcdd02810acb51afd1fc10bcfa71748d1b03fc9a4f71edf4f7d29fc84f005360b33","nonce":"b11485b497a8deec191e7b23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"688f113b3aa678858aa102b1b7cddc06cd2314cde5553a535fc0d47daa8b8977cb7a3aae63183511302f9e2050","nonce":"b11485b497a8deec191e7b22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"13894cf923cdbdf5f17d4f5db8bb67404579222a07a7dfed85847877364ff7d1e45111fa2e6eca1f70d221aac8","nonce":"b11485b497a8deec191e7b21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"bc7826cb7a1e5932787a0524dc09406a510eaea491e7e06dff3195046b1dca40bff7c7e29315f89ece1624f866","nonce":"b11485b497a8deec191e7b20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"88e0068a77d21b8ae64bd3a4896c678521ab961e48bf5121f909d5faf2edfc53d971ed37bb29a9ed1f2fabd836","nonce":"b11485b497a8deec191e7b27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"d7254c23199de59626e25b5e2aff083ef5841bc3f3eb7f0ff3a0793b6642807da0afadd4a899a3377390548fda","nonce":"b11485b497a8deec191e7b26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"d9498ea3c23afb8fc2f51a83f92d16989db298cebcd400a64de47cd2d25e927727917a7362dc4b9efc389bf4e1","nonce":"b11485b497a8deec191e7b25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"5c18b5320e3739ef7dbf21c5e2db2e137ad42a1b68346e38e2633e217f9d2d47b5dcd019fb0de1715a3c5d10dd","nonce":"b11485b497a8deec191e7b24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"2006f7b4342971704a55f070df4a62cf07e11c388656634507c9974ab5d21d00d6372edfa7ddb018b4e061e950","nonce":"b11485b497a8deec191e7b2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"9aa92439512f42b7790b9b587cd2f51c3f796137e3e853b53573ef3984a3a1498485030bb882817bd58931faf3","nonce":"b11485b497a8deec191e7b2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"c3cfef224a066c919efdb47f0bd6aad6c58c10be1b35cce74018a29366fdcdef354159eefb1693f041a19e3be4","nonce":"b11485b497a8deec191e7b29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"68db77aef9ca47d260b6747c2ef55c428fcc66e9ee82cdc579b91ebe4aad7a066f2f0fd29a447b93653b620f5c","nonce":"b11485b497a8deec191e7b28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"2cf9c572f3450bb4ad4d6f3f472bc17eda8244eed774593ef5114100aab7de5e8e2f5f9fb9619dff84908a8917","nonce":"b11485b497a8deec191e7b2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"bc27d2e3977d6c6997a58aa4d5457c3f3223a26820c237aecdfc212d499bc32e50b345f61dbd8b424e217eb133","nonce":"b11485b497a8deec191e7b2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"c17e2b15bfcbd688ec95866231ceea681d2669e3b42ce6f8288b01f24e86bf3a149ad4ede9f49c9025ee3451f6","nonce":"b11485b497a8deec191e7b2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"0802d0dfe17903611d4aae95cde9b537e70db2dd42939f6a2dc4697c62ae0419a9a151ee056dbdfbefe0b8e54b","nonce":"b11485b497a8deec191e7b2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"e18133cb1f77e0c9894b76519c80d6867bb2a8233af40029296e0d8cb2df8cd618b92530a238c833b5f668b8d2","nonce":"b11485b497a8deec191e7bd3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"2dc6c5ae90d181b8098d134b4d0cedaf2b149cc187d8341c8462c91b0d6143de2a3df2747e508ac509c5ab9c63","nonce":"b11485b497a8deec191e7bd2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"680a23adc5de809651d0c56427dd0947f5f0502ddfdecc451383ba02e6524f2a8426f75834da99fc3f6c52f0bf","nonce":"b11485b497a8deec191e7bd1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"8e1d94103554fed4da405b4e7ba8973ec56e8e149c8d050799199ef39fd57822ac63b1370b250808f5b62d8c1a","nonce":"b11485b497a8deec191e7bd0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"d322ddf29e0afc5ec79103482ab996e8fa4008d7fa3df52bbf2b1e1dffb50e629ed8bc3cdc5ab1dd0cde5d773e","nonce":"b11485b497a8deec191e7bd7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"31d0ed2b43a8fbb8983e3defc86ef45bb5218937439e3ad2a0f4b5fcf84314b6fd73a2a663fa99404531c4e6d6","nonce":"b11485b497a8deec191e7bd6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"700afdfe09aea920445624fb9b9c61bd849d271689d9521c138bd283d5b1edc2f491cd283995b0e76568825c05","nonce":"b11485b497a8deec191e7bd5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"1ab9c70767071ab6df8d0f8c698d94c7ba8843ac36dc7039242c33944f7b6005b8c8441277d97d686b4be71ac2","nonce":"b11485b497a8deec191e7bd4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"9a34265e7794ff01afd6a9a5791200d29905e20f7d90f9ac4a3aa53dc3b709c8812520ae3cae4c452e835e9a99","nonce":"b11485b497a8deec191e7bdb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"5834255d587ee18593b4b4ea5d6cb928c3675c846e3d206e3caf5f8ea174f897c35ac71de9bddde5a577461fd0","nonce":"b11485b497a8deec191e7bda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"268389ec83acf59aa93ed33c98f1593ed8ad5db9860e10d2567b7ccfed9c42cb1c634575990d4bb46f16a4fd3e","nonce":"b11485b497a8deec191e7bd9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"d742075eed2869e1748c8d12424f9316267e2899c7cd201d00ba488451492a601ab7e11f0221bb3c003161c170","nonce":"b11485b497a8deec191e7bd8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"864a350b0b45a0c5a3383da94307b464b6d2a15dc0bab9c4ffcb87a232cc29a0a68764d13fd48636c4c50dfa5e","nonce":"b11485b497a8deec191e7bdf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"55c382fac831e675f8222de7060a9ee234b6f0c3c174acd7e2e6d5e505a2003eac48f2ffee92831e33f13c3113","nonce":"b11485b497a8deec191e7bde","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"59f1bc1ea9c2819a0c42bd0e9b717a1520bd7dba0a1e9a006619e5c5b20b56ce5b9e7f2cae17f72f03b73989ba","nonce":"b11485b497a8deec191e7bdd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"deefaa786e66a288ed5017901891da5c5466524b9b850639a5b7a024b24f3e4a39d46dacf699030eeb3975a41a","nonce":"b11485b497a8deec191e7bdc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"f2a3548770fa9cfa6bd42e8b49b4643bd351fae90fc46b917a585922855a82202a97902a78e150616f7eba45db","nonce":"b11485b497a8deec191e7bc3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"a8773e40d91a0ee9a488ca700a81298cdbbde6a7f97f58d4aa1ee10b06704293e68baf755592ff0c7a0ae413ff","nonce":"b11485b497a8deec191e7bc2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"309c5dcf319f3d9bb8a24ba160f83f1b8cef12ffa7b0609439c30e10994967a5ac53dd7efa774baf590a6ce977","nonce":"b11485b497a8deec191e7bc1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"3deac81d4594106281f434f54012a1583c86a3599c2cf7f1f2b8fec6413239342eb06ad09d14b0f2d5bdb073d8","nonce":"b11485b497a8deec191e7bc0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"daf5668fcaf6bcec24271332e1bcd25beadb3338f626a81008d224d22759522ada5d494a82c836bd7158549fae","nonce":"b11485b497a8deec191e7bc7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"aaa0470c759e0ee3bfa1067a9bc299fda1de00012dc7fd9bc571264232c3e8762ee987a3a4a7bc49b1f657eb54","nonce":"b11485b497a8deec191e7bc6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"fd30452de53633ced55628baf3009b5ed3391ffa7db96a7ae916eb72e30d22d417b1f78f2e847b3ffa635a0d0b","nonce":"b11485b497a8deec191e7bc5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"9dbfd724742fd559afbe2c0d57fd0a66ab8dedb75aebc76a642dd23c9a245f6377f67b6f92fe6b6918c311296a","nonce":"b11485b497a8deec191e7bc4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"bb3baa97c966d768902707c4a8e14552bbb6091282d90008d9699edded90a75e65baa059afbe8bc5e3c58d4464","nonce":"b11485b497a8deec191e7bcb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"5d5df37f56a5b4ccf42e0595c636d4bfb737dbb16ca1f0ca8d00f6e59f9e3fe2bb83de927e731923e151e00059","nonce":"b11485b497a8deec191e7bca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"ef51af91f562465425d316ef50405280595a1473f53796392435eb5335b5a287f36d397b064e301fd70f9a9251","nonce":"b11485b497a8deec191e7bc9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"667340c339361555e6efffcf51ddd15322855eeaad837e45ecf603afa34468240927ee78a32d1ff86b9a6ba633","nonce":"b11485b497a8deec191e7bc8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"afaacdadaa43ae3ca20286ca7a40ca1825bb272b17e52c03245eacc576f251af01176400428915e781df12acbb","nonce":"b11485b497a8deec191e7bcf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"f73a7140be2dccb50a66240878ef1b4afdd8388df2766aca2e12a64e1d07390449e352306ef36ca9cb98de7f5b","nonce":"b11485b497a8deec191e7bce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"80e7ddc767379d553fadb9579a5cac3d94ce68a52f9df6cd6fe36a25a4c43dbbeb77833c416f4458d40cb30ad7","nonce":"b11485b497a8deec191e7bcd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"186afbc90ed158e779bd95ace8ec43cc6d46b65ec4525a45c0865ce45c4b540b7e1780aa10ce087edb2ed27e6d","nonce":"b11485b497a8deec191e7bcc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"1a60198c528de914c1d7e8193463940f4f206a1ec16c2daa997ee8ca68cb453a85dc97f90681cd2874c9771ef9","nonce":"b11485b497a8deec191e7bf3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"afc7324148d6bc9d27bc5f05514d2ff588a8816b06f4bb83115e8f23e63cac0245139915c3da99d08fe2b9e557","nonce":"b11485b497a8deec191e7bf2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"33a78eeb01eeaa0439d84233fc7054cf769cd840e07f316db23e6994defd4a74c631a7f11ec36f70bf8ae78f73","nonce":"b11485b497a8deec191e7bf1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"0c7e05f568d04355d471bd3286e779cb2f288106ba35d518ee747c5d1e29003f8d4f1968b838186379f2299c35","nonce":"b11485b497a8deec191e7bf0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"53645969632fa1ca7d82aad78eb269295cab46f5d828ca6e7ada7b1c495d8103d42a278670e8e1e39cef38b728","nonce":"b11485b497a8deec191e7bf7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"3ca717daa2498aaea229ab627a0c16d660e6a750a682bb279328ca09a680d128cf65b4c395e711bdd028759c14","nonce":"b11485b497a8deec191e7bf6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"95abff3293ff42729db04947542d1ad4e2a37fad2e08ba2f24486dd9caf4cd1bde01e22400161589c744be683c","nonce":"b11485b497a8deec191e7bf5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"d4bbeaa5f097a1ff72acb1094a1bb6a95f891b2b8723d15a23830f372061e971c4f2a032b30913c264421bbda6","nonce":"b11485b497a8deec191e7bf4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"c679854e1b782fd66cb134fd4697a9fb1f08744104c44e37ec09d287b8ccfab30748e9a5bb6410dde403ca2adb","nonce":"b11485b497a8deec191e7bfb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"e9d6adef7ec112e5086fdc3d8b3d705f0ec6efac16fab57fc854847ec0679127cbfef72817779406bb0ecd1d7b","nonce":"b11485b497a8deec191e7bfa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"e5c4177eba41a0aad8780830a0de8a266bf4b4288fc64c72c256e81e251bf13ead026aa20d558bcba463cd0e25","nonce":"b11485b497a8deec191e7bf9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"181046fe321b4ff98cc1d00c298c78b3de75eb1a7d6533ff6bb72598c7c8eac972ce5d97d50cf638368d0c1038","nonce":"b11485b497a8deec191e7bf8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"509bf19b638a80848e52285f1e05acd5a4924416aedce04815273ea3a7d9d0c98ca6276483312c0c45307038de","nonce":"b11485b497a8deec191e7bff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"61934fe7b5e93480416813c099f48a0b9cb3a8fe90a6e0cefe6c9957eec8df81c052e46c18103134caff030df1","nonce":"b11485b497a8deec191e7bfe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"bc7c886597d4fd8c692b70a17a406f51a97f75d107a4a5d1bb92c31317141ce55039be7fbc094239b1cd725a2a","nonce":"b11485b497a8deec191e7bfd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"cff76c939c49469e3b6df6943ac0f6d41928ab2f9e1ce6c2aa0f0748f77c9df41bf1902e2f8178bd55d02db0ae","nonce":"b11485b497a8deec191e7bfc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"f52f7220ad811c2d1b98a24667932793cb2bca021acc785be0ddfe7dfd9f3392d1f36a325f3164115fc333ccbc","nonce":"b11485b497a8deec191e7be3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"98304ca038c6affb812c71edf1d5205051d74c51705391dedfda9d587ac061dcf0539e39781a0bf6c4a86713d9","nonce":"b11485b497a8deec191e7be2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"ffb1348b2c0b0687ea65fbadb9d751dc408b04f33c607d4594d04816ec91dcabae574594eeb0635f2091a5d157","nonce":"b11485b497a8deec191e7be1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"7c62fe8314cbf26d3e0b047d221d37e92f1ab5e48aaf22690f0b6df02e13ca74b4f648d3bb5c9b1a102d548daf","nonce":"b11485b497a8deec191e7be0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"ab7e700906b979d944c2408105523b6a2cf2c0cc6f1c05ef92d71b69a748768b1787699ab4f5bc6833a186d7fd","nonce":"b11485b497a8deec191e7be7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"a31748344d01a350f9b60a7866f062f8411d7ac277936dfb882a5004f5453ed71fa2ec6bbe74172d048fb1d400","nonce":"b11485b497a8deec191e7be6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"9de231d36386ece1ced9ab48ff689c253c0fb5906a890264e97d34dd29c753047f3e43e6596c34eb329af015b3","nonce":"b11485b497a8deec191e7be5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"95426daf34aae07d0fb41bd108ec2d5de092bb5191e05afbaa6c20d00d333c9aa00753e1f3bf611d3ec0ee4e25","nonce":"b11485b497a8deec191e7be4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"e73512113d1ec148020bcbcfc5fe3060d0077627cef8b99678dfe776032713f611a349a9d8790747b0a75e30f4","nonce":"b11485b497a8deec191e7beb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"83f42795a1b5ba1583c3fac5c9a693c11d7d0306d90bfec560c4df2534c08d0c89fb224e95437d72d63be833e9","nonce":"b11485b497a8deec191e7bea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"640e03431f8a7477bfbc86a95d94b415db62ed492a5b6e2623fb982a2dc0eeff3b988d7d2fbc80496ad3d2348c","nonce":"b11485b497a8deec191e7be9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"3e327ab292e1e15a8ee3d8c3d2a661f52f199cb58aed89144411b569bedf369708f307fef58064e22d7e13448f","nonce":"b11485b497a8deec191e7be8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"716ff01cf9c69191bc0fef59bfdd8c0c54c4266927030156703f47f0e887657ff31b98e1b4e12852b2f7c80f27","nonce":"b11485b497a8deec191e7bef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"f43deac94a7fa1bbc6436aed1115fc7d793acac3af397763f688abcd7f86abdecd84967386b25c2562255f35fc","nonce":"b11485b497a8deec191e7bee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"0f129c619be9afb9f55534b9106db948f7676fbd281b6091aefa635419b585ee819ca4cf968a29e21b5b307510","nonce":"b11485b497a8deec191e7bed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"15e002a96f8050ec73fb66d8b96770161ca689fa98db0982eaeac1254817b52f8b7b7b6849a9a6838e52a530c5","nonce":"b11485b497a8deec191e7bec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"2b3a558010c8d94ac2e1c9e463a2ddc869cc4c431ec55ef6c4230ab393594b50cb31679a5fa83b1de0f7e19a26","nonce":"b11485b497a8deec191e7b93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"a01f89c26eee34b19f8b7f8519128f78af09a7efe3402ffab3f9a7d821c40dd0a73311958a30dc3f82fce03895","nonce":"b11485b497a8deec191e7b92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"64ebc8891bb029d3043b0667711432a76c1412816784cbaf5402d80a8c78deca6a54e41c36997b0d4d0497c5d6","nonce":"b11485b497a8deec191e7b91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"d499ce8234a62f41bb3fd53a2cb322de0894f7d5b3c703702816a38d1ac674612d96b134af42d2dd863142694d","nonce":"b11485b497a8deec191e7b90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"181b25aac0bc8fb6faad245334f2c684e1a5814d3aeace1344858f746a920d41427fb89ca9c05a342efb048c9c","nonce":"b11485b497a8deec191e7b97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"0315c345fabefc1b714fe8853b7680f736d40b06add47da291dcc4574a5b5f7121eff9e021c7306db6130ebf04","nonce":"b11485b497a8deec191e7b96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"42b29e7f955669e55b9620a288017ed0e6b9512ed5d7e3d7d60fcf761c24cf8a136c9510f4e74531bc22714285","nonce":"b11485b497a8deec191e7b95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"abf67462c8d48f5e4daae9ec471b326ed5280281fbbc69035d5e52b2575cabdf6f0f12f0e17608eecdddd7195d","nonce":"b11485b497a8deec191e7b94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"2ba37d22dc4598065f08d297ed0827c1acebf1c541bf07b2736943f7beba3c799c3e132af332bec32a37e473ae","nonce":"b11485b497a8deec191e7b9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"a6d7db5385c7148666f62fb458aafbdd6a0aa356033f858cc5c91392c5c541dddc009f23329fdd7d41c31e54f0","nonce":"b11485b497a8deec191e7b9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"e1c14066eea3e40e9585d357deda9f3256b92f401883fb3724dfddd0ccc0709032816bd7c57aabe908b37aac3a","nonce":"b11485b497a8deec191e7b99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"2916e321a1e7ab9b1508a157e2289b890a44a65c1c4f655b801ae0da058e2ed46d46558ac63befab1358ba0507","nonce":"b11485b497a8deec191e7b98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"83abd9ad08682430885840057ab88b6b2c0bf26281d43d07cdc8f6b5b585d56c908eb1d175f3ac18c81db9c015","nonce":"b11485b497a8deec191e7b9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"ed604a3f5f6abeb6ba394663331735a8f810ff88bc79b42a96d96fd732f3d4953c2bfec040f2e28bd51afbe1bc","nonce":"b11485b497a8deec191e7b9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"4b08a19697a2aa2d61e8048ac90adf98c9fbf31316b840e27a3e997d8ddb4efc05db8acbd777ef3bd0d8da1ad5","nonce":"b11485b497a8deec191e7b9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"2c0753368cfc99fb2be6b9ff4e459089b537eab086bb676985740a90b960f7c7d8090aaea421af32e0ad05de48","nonce":"b11485b497a8deec191e7b9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"d7cb2dcbe24e21f11d421f2f889293fb63f0c1c023ce153b78542dfcb8a3c54efe43672fedbc799f34749f56ed","nonce":"b11485b497a8deec191e7b83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"27f31bec2a67f95d663c829f03a341d6628dfae4b4179d74d45c9f4dbc189f05f6b482d1367ca5626262e9684a","nonce":"b11485b497a8deec191e7b82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"0b886572c890d9c8c9fec14657f703193570f21fcb2b181677126834b6ef398183cf6de8975354fe3e2f80b3f2","nonce":"b11485b497a8deec191e7b81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"2a28b12f4b5bbef3c86966210b5a5bdc806ef010ad7ab8b4442bf75834eca17896a279072c0f43b7631af395fe","nonce":"b11485b497a8deec191e7b80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"be4115536eaadbfd8570b2ee7ee88121d1b6bbcdb49ac971cc6fecd222e5843e00762494550b829fe12dad6728","nonce":"b11485b497a8deec191e7b87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"e4b87893d95ec8b8c5687eaa1d4e8f14cd85f12c77b1b90167422bc4499de4dc27823fd1d75a8247d51046e21b","nonce":"b11485b497a8deec191e7b86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"c9d4467fdc5cbec70da046a36d5a427be951d870fda1d85fffc5c61d007e7627a1fc1f2666f4c415246f2bbeef","nonce":"b11485b497a8deec191e7b85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"9bff95f514d778f937d09bcce5ef5ca35b3dc1438dea8138a198d049f052f08801abaa7b7a83a49b180521a718","nonce":"b11485b497a8deec191e7b84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"3399f6fc95cf918eed7b515de8c5bed254e35e0adb34e3a814e042ba568aaa99df92e558a6379a66abdc0c766f","nonce":"b11485b497a8deec191e7b8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"9b0f1a9d794673e4199cd2977d83f8a770cc9167c4dbb0fb5163cf467c8a7f34637b593730ece36d5d0d569ee4","nonce":"b11485b497a8deec191e7b8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"cd159ebb9a4fcbcc6a81f79374f28249a26f106bcfd40e5bf32d8d173518e8ab2efda4a111d162e72ee33a467b","nonce":"b11485b497a8deec191e7b89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"32ab85bd2cbd17c040739e2ecb318cf2b295e9d641164eaf7227989121339a1228b5da5e83d59084d887d39cb5","nonce":"b11485b497a8deec191e7b88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"05651e941ca2982f58ee597c7d15b0fa91a23d98e01b7166e285cab0f0a215d55e1a2bc83b2b152eba45b9ab69","nonce":"b11485b497a8deec191e7b8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"784b108c73dce6b3410934aca57e452e5fbbcaabf59358bdf6c0fb96eb15df6a13dd4abb11f7175c875f18bd95","nonce":"b11485b497a8deec191e7b8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"3d0622abae77a35bab05e51ad92adf026de7de7b52815ac09cf691b9002545904c3ecfcec8f0bb109bd64eb910","nonce":"b11485b497a8deec191e7b8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"a670a79cd00089ceca5ccc6a5a5cce3d32ee2b8c275ffb325b566d0e89d111d07e4f0625ca690bc47e45c8c880","nonce":"b11485b497a8deec191e7b8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"953e192972cba229c62a92493a4557083b33b678bbc410100664140dfa39e70c5d8232308e3faa937fe1c2069f","nonce":"b11485b497a8deec191e7bb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"01c2b7aec5a0daa651560c92af0c2a37191c86f660995235278770afac5739d43ef194d746bae0c8b695a1c9eb","nonce":"b11485b497a8deec191e7bb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"c142bad9328552c1d73b025c740351e05a3766442a016b15cb48ad23db3d1771db3e986c35cc0b1de1f1f2167e","nonce":"b11485b497a8deec191e7bb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"09eac4b573992e5594fef544521c380f92e76f284a98cfb3196619f047556b438f8cf05c0cc6f2ffd4cbde55c4","nonce":"b11485b497a8deec191e7bb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"b753a185245af89ba5089d200261e6e85fbf58db39de181f6b5fa3e259d59dadd800dffd9a3badffece7cbbb17","nonce":"b11485b497a8deec191e7bb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"77ac9f6dc460475f2ccd92ed26b71b2d265e60465a1852b21d0b478b1599c023a20918d9fdaf4f3490a8a3270e","nonce":"b11485b497a8deec191e7bb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"74155fb0746c0b77b1f3b57910ca1f881d19e610447445fb83b06407e27fd9e476532a9b82a405eefa67927697","nonce":"b11485b497a8deec191e7bb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"fc8b3ebcb966cc1c2694399d5bbd983447a19d463b1157644c1f2c1f051045f18e9da36080b22d8cf952013281","nonce":"b11485b497a8deec191e7bb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"04cf004aaffb81e9b86e0b06445e8592a8b449a4696ab9be88f5ad7572a2ea7c5c84c59d675e618df9b0aa015c","nonce":"b11485b497a8deec191e7bbb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"adaf11b0f829c4c6cea3f9996551b97ab7f49b59a2354572cbb1eeaf252d9355e03ea9c810bf6e902819af204f","nonce":"b11485b497a8deec191e7bba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"9f432b62b5869602b05968b66d54adb457f12cf1ac2654e794ce0036d9ec76e9e10a4ec92f503d4010d245c6ac","nonce":"b11485b497a8deec191e7bb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"ba8fa462a2b5fe5e42074200260992c70ba156a6cefa5f5f75f35c12e7ac29ca1f30a15e1c6ed8e8225dd611f8","nonce":"b11485b497a8deec191e7bb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"1df91b6b3161ea03db9789016b7d4e57c91c87b396b54516efaa7e9a878740058a175853a72d6a1f4d8df6c978","nonce":"b11485b497a8deec191e7bbf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"46300f397fa1e262b1e932f4ec73a992fe31d7f70cfe73bf9a8abd9256e79d0ee0639acf18aba105619ee54b7b","nonce":"b11485b497a8deec191e7bbe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"2361fcc04db5b0422da0eba111b7626914c66a73e51f0a4c317a190a6ead3d78e68421d6e7db9fd96a79d6ae7e","nonce":"b11485b497a8deec191e7bbd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"2921036b0d98c8d5b6051d706abbb3385b60d0a79f3f25cfa81db1c60f6a6ade10bc701680137fa89248d89c31","nonce":"b11485b497a8deec191e7bbc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"a897de667d0a3ddd8439fcd5dc3c3a9e6126ca6d6041d31df6a4e3351a7132dd232998435dc1f1d81dabba68f1","nonce":"b11485b497a8deec191e7ba3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"79c06ebb075a35de5a343ede53689c217b12f25202862c5aec554c3425066477e60251a242b88f68e4b44399cc","nonce":"b11485b497a8deec191e7ba2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"13df34dc7ede8ec0d258ab3ff85ee528c712b46a1d124e1ce88b180df3b5f39793a8d8d5cf95b33bad6c1e2732","nonce":"b11485b497a8deec191e7ba1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"f9abef5c2df2872024553c937421886135df3c11cf02a4550ff48e6706d4d201157e20b0b603b7c0282ad48208","nonce":"b11485b497a8deec191e7ba0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"62d0ce6c07b7c88aa82b23e4b2cea63ce34b326d4a64880c3cb429eda083ca57d4c2ce6861c8c92baec974f5a6","nonce":"b11485b497a8deec191e7ba7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"c4730f052cb1bedfd3a1462f988f48a670f436b1f9d969fe12dced7b2d37d110610d2052530b53076ba677d3b5","nonce":"b11485b497a8deec191e7ba6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"2b17c973cddd66c1672181e1706e8c8108ea6e7d0da86711e0654f85252f2363b51e4e4fdd9c57c37e3fddcdc8","nonce":"b11485b497a8deec191e7ba5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"ab0c6067541d5c49395993e30cd560841cd809a6bacfaaebe18eec14f0c0dc23a057d7a9c93d43316156caccdf","nonce":"b11485b497a8deec191e7ba4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"2358147675a4de9b4c21b14a6a04dda7445e6aee0948b814c462fafdb33dc1d2477642f5bb5325d9d6227d91d5","nonce":"b11485b497a8deec191e7bab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"a4de77670e46ee156fff5ec7d2c40d36de3611939b408e7990ecc77fcd033b9870feeef2cdcc48c86f5d45769d","nonce":"b11485b497a8deec191e7baa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"4427af5bb6d5a9589ee04d333997873241984ca37dc9ed09464ca3a73cbb36d2073dff65952b48c5da7c42a79e","nonce":"b11485b497a8deec191e7ba9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"0a2d07d0b32f4f64a2942f9da7ec9f10e993412939598175ccaac4f5782bfcddf869c2346bfc20f4f749945d1c","nonce":"b11485b497a8deec191e7ba8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"d2c2134bba2abcb05a99b2d9b8c809bf0cd95b23438d28b10cd6bf5eeb3526f8bde59f0e89e56977f0ef3569bd","nonce":"b11485b497a8deec191e7baf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"c188646cd0a6e95ef0aa4b17719aa76446bc50eda9930decf38a0541b5f9978dce0dd5bca70fab4ea2cab13cdd","nonce":"b11485b497a8deec191e7bae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"b35d5093377f7e9d8a4a7fd576e997add951af8c8201484c9e8ee42c049184d60ae6cecd0fc6c143bf4641c724","nonce":"b11485b497a8deec191e7bad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"fdabf6a84e5b9f66b12ff30dff7a0b3649445467bed6fd9e67c26b7991e0b5732421298315d67a9d52dfc7bb41","nonce":"b11485b497a8deec191e7bac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"34226ccd6c612382fb96c5c11832073dafcfe25ce49ba8834738582b64c3e05416470d94d0fded20a993db944d","nonce":"b11485b497a8deec191e7a53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"d5541537e029f9044889b522bf0f85dfd8c31431cc75322ed2964c433b935a6c"},{"exporter_context":"00","L":32,"exported_value":"3e12d526ad95b7648594d093f838209a6780f71d775b12a5fad16f4546332d43"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"646c979d94c8d2814d3f9f5f05e2bfc2e3045bd74ab6ca6377b377ce539c1e0a"}]},{"mode":3,"kem_id":18,"kdf_id":3,"aead_id":2,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"e7fa07c9938a3d9d883d256abd7fb5777ed7c4195a8d244c0e682fd1a08fdcce58ab1aa7ba31b1fa120f03d9df438509a1e31992506dbc196ac4489079b3b64bea9b","ikmS":"403e8d5ff0155c71232a887f542df221c385956eaca3acceffdc4681b99c7e9613f90ba03b0c03c0c57a90b2dd31effc6278ab6dc059f3e5389dff6495bda12b4da4","ikmE":"c393a0a0cab3313f0526d72b8bef55b26a156493263fa1a653069ed5f2f3637f371b15704778c89a6e01c3fd958dfee5f85613e2d4b2eb17a152810690d8252df44b","skRm":"0021b5ef4db61b4b91d3c6d88141b605c258397366222b350294463bdebdbe0036852486810a2fd9453aec333907de2c7581d946003337c7ba584ec23cfe832bb61f","skSm":"0071246eb324a0d343614abc4f6053ca7bed89d65b37183a14b49023826d28bcd92365ff317012ea0b4ce2a02af6dc4e2903aa12f7140deba1d8260a412afc12ff57","skEm":"00054bc38331e6fdef87a0569e20382d65575293b5854d705cf4af30fd6a8cf33c39201d95a5a88f8a0d7aeb12d58323d2d700fef00aacea80d4fe6e3195b7b96782","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"0400cddaa5efdded3ad07444b153f0d81dc7e00adfb8e9db9433f81878b5fc1bce46d73f209ccd9bbeb8e7666ef6e0a2579bafd19c2d2ee6a007fd2fa4fdb26e72b401012dd6b9e771740c8356e3362ad42c35d16cbd3a9c928775d912a7cec7b0ed21cfd9e7cfe8982790b5ecec0865db3c0d4f7fb8da6358308d6d3081b5e0a7c0ed433c","pkSm":"04000a76a0865d1cdd11370b523d2a021b11b60f2896735b7257ebcd9810341775ab86df3a4fbbe35788116331b88112515cfe02c551a74e2b1172f1fb275e18602db2013fd046bbc404c4f742b663a6766b624e7b1b554bb083925c5501ebd460f0c5a2f22013c11d2a5d8c8b4c00f676673f72a643a898b0dc063e68d04520fe4f60f202","pkEm":"04010a0d92e86189e02810958da08f1c5265cdc000ae80d96b3eb8582649a5b640a5d1642f7d6be0d89251cdfc3c65a6eec16b2144867410440ff9f700c24087265787009814e7d54549ea1b680c891cbf87e70b4d5b22f3dadbe092f085e09f27fd034342e3bfd98f33094b7feb00e9e237376594a410e84ce0350d70f38217b0d466beb0","enc":"04010a0d92e86189e02810958da08f1c5265cdc000ae80d96b3eb8582649a5b640a5d1642f7d6be0d89251cdfc3c65a6eec16b2144867410440ff9f700c24087265787009814e7d54549ea1b680c891cbf87e70b4d5b22f3dadbe092f085e09f27fd034342e3bfd98f33094b7feb00e9e237376594a410e84ce0350d70f38217b0d466beb0","shared_secret":"b4159baa2f2b745a8fb7660693c8e01bb248fce102a1b171a475c2e38ecc4c3dbec5381817cfc0d0ec19dc007a6ea7933c00a8f9ab35adfffa7c220966c975fb","key_schedule_context":"0324497637cf18d6fbcc16e9f652f00244c981726f293bb7819861e85e50c94f0be30e022ab081e18e6f299fd3d3d976a4bc590f85bc7711bfce32ee1a7fb1c154ef45baa1f3a4b169e141feb957e48d03f28c837d8904c3d6775308c3d3faa75dd64adfa44e1a1141edf9349959b8f8e5291cbdc56f62b0ed6527d692e85b09a4","secret":"c53588ac939347f934b9d1aa14d20f7adbe770006b687da6a1336a8d403ea856cedbb4553649c3adc3e1a7816ca9cb5bdff6d9ea7aaf346c8f5f1a76568ce4b5","key":"b4f8d530bd73a4fd4cad439d000ab2597fcec2566b7724a9192d9570457481de","base_nonce":"15bbbca1da3014f719666d1a","exporter_secret":"0590c71d26e4d72f70abce80f1d4bc74b6a296b92c7d766671ad5155e9265b7adb45f818177bb36b97601b30f70eca1587b690c710da90dc1b5b33436891eb97","encryptions":[{"aad":"436f756e742d30","ciphertext":"3ec4207c64fdc69bae26e1fe16d5b6d7718ba85464aade6570d5dfe4711acf91b639d03515304308c6c61e9a83","nonce":"15bbbca1da3014f719666d1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"2cd09c9cf81da78928ec9e2311aea6a2ac7e22354d858be8a1895c53ec36e1fcca75eaa140d3696aac46faed74","nonce":"15bbbca1da3014f719666d1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"86956df21daf7224c8386316d03a8943daf5e9aa9b068a6fbcc7c767bb95ff28c4ff68283c33fc80af6296ce9c","nonce":"15bbbca1da3014f719666d18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"ed05e54b9a5fab04b6afdf5a58f5efe353f8047ed4b84b2161493ad223f53b2269748dcf1ff668b66af1fc3fd2","nonce":"15bbbca1da3014f719666d19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"4553f172fcb1df84624a79a73de39bd8b5dc6922b3798c1dc2750c3b9ca0da59fc7cd8a4223b9fb85ac9eb9fa4","nonce":"15bbbca1da3014f719666d1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"5d902a5badae107b240daa4e82115da2b8ac97163de990136f4458a1a3390361a60f0e0eee0e30fe449a3dd341","nonce":"15bbbca1da3014f719666d1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"be0dabf9e4abf992bfb9d50c4913caf5202d7793cbdb84fc93b5c422a3504c0b3a1943470c3a1d4a843ae367b6","nonce":"15bbbca1da3014f719666d1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"b6b87f189bebcebb849929285f37beb091465aa7709dec3b714cbf64fa1c10b7c0299050282baa7112f0943444","nonce":"15bbbca1da3014f719666d1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"5a4f7d619688797de9c513d2c90b77638e82f7c1ed3443d8f04cf31b1a6e024dcbc0c87cfc1c274b328b710eb7","nonce":"15bbbca1da3014f719666d12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"ac89dc0301925b0d87f6150d9f9f80db98d7963a82fe1e12b8a7301e42a4ce7565e12c25fc902aafab98f5750a","nonce":"15bbbca1da3014f719666d13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"77a95a9d085bcbad590daad7f38dc87422fc32201409871b099192f5f7c9deca572cbc562bb52a25fa1329dd31","nonce":"15bbbca1da3014f719666d10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"7fdc9a6eee9b908c5bb686a5528f1c943da69e9e71706508db883b21aa3811ce570f191c38ae75eaa44615a1f8","nonce":"15bbbca1da3014f719666d11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"0919f9b6c4fa49b0e8943c79182e6a0e9a07fffa8e2806f7d54347ccc8a2e87fe3a2172387897997ec836a0522","nonce":"15bbbca1da3014f719666d16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"30e1d0af11844f954bd88b2e35933b98b6b98d16b2164f3f3194b865a21f2a9fc013adff473cdb3d18632bfbf7","nonce":"15bbbca1da3014f719666d17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"6c8935eda43f4325055fe1ee16c708198badbf04cea912c446deaae484212eb10618dd125aaeefa6a5fef6d4ec","nonce":"15bbbca1da3014f719666d14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"ebfa2b4df495cb5c53eeeb273268b0009d6d69004c04920d4bd70e82f0345c31f5f272469a013a63071142795e","nonce":"15bbbca1da3014f719666d15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"d3d71d8e75e60f7c2754f1787d0a48e7c1d82eb0d440bdfd707914323a54b304610b080d4ab910eee524006ea0","nonce":"15bbbca1da3014f719666d0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"1b5cd687180e75c7a844407e34b3a70aca01ea8c0f53cf50d15d58842b2f8892db200456988629c0504ec157c3","nonce":"15bbbca1da3014f719666d0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"30a44ff996b83c80ac971a0c345ba8049dfd73f181efa69ab32f8fd49f26272b9e1cdf627b6dbc022acec5d4f3","nonce":"15bbbca1da3014f719666d08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"493d46eeff448ef3de168a3b87b6bdb7ec689f952d84b4266c1d037bf68d1a20699b9425d3ba3d47c3fbfe139a","nonce":"15bbbca1da3014f719666d09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"428d0f0df9a070a026ebd60bf19130e29c769021ad10d9f530dc7e82fe6de060441da8efe2f5758b67f7f0b934","nonce":"15bbbca1da3014f719666d0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"207b8b0687a758f8adbfe7a83e81db6b71c8343f36b12d758373e5ecf488bddea85922ddd5c1c227e8cedd2059","nonce":"15bbbca1da3014f719666d0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"34c0dbfadd230d964b232aa4f17e3db26d401e1d16eb322d8f692f9c2cba15e1e467628c6352df50afcdf4fa3c","nonce":"15bbbca1da3014f719666d0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"552c5fbdda78d0ac558ecb303b0154ca1f6da730da920be930577f4fb1db275aa7e6730ec20ca99ff91d7ec423","nonce":"15bbbca1da3014f719666d0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"d703eec3255b096e4bc7053a800bc2c08b93dd66a284b07ff320771ca79302ee2dfda717b0d93e3fbf460c0206","nonce":"15bbbca1da3014f719666d02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"378a2295b5297a57375b03e94bf68d6bf2d4a2f70300fcd65648506d1ec502ad845840c6fd0c653c2528ef02d8","nonce":"15bbbca1da3014f719666d03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"3e7e04873557f09204cab3244b732f1d7bcd7fa0bcd455639ea1f2b9f4578a8c8b22fa0f964e4976a84897b463","nonce":"15bbbca1da3014f719666d00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"356f37d40ae6f4f8ed9abae960b6cd2ff8a28b73f299697d9dea8aa3fa0730d2e5b0d15bd270f36e47e558bc41","nonce":"15bbbca1da3014f719666d01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"e698c0d89b71ed251a11c8d37190a74a0809cfd88fc47796d34d9d1f96f9138f11836220533b9f28d39f24733f","nonce":"15bbbca1da3014f719666d06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"b155de1106544670f058e11439b84551eef22f4ea5089ab0cf1a9db6a8faf62d4861db5f5bb7119e975892467a","nonce":"15bbbca1da3014f719666d07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"ace031593e42e00a8081db14572995dfd1959bfa25bb3373cc69ee5a518b97f10249fb4d72614ac845b7237a04","nonce":"15bbbca1da3014f719666d04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"70a4b71b7aaf2cd8a265ed3859083807630d4506e6fdbea7d4a10788143a62f064f20d338bfcf3cb5f5c52b83c","nonce":"15bbbca1da3014f719666d05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"bf48bc9540a7e954890156ca66a0f300e5a09ff30412c5f37dec579b0feecd7d690623d67ceaeeb53c37e71182","nonce":"15bbbca1da3014f719666d3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"5149f154a05d97ca986708118eeabd4bc01449bd3abe7223ca1829cc24fb4c4520ecadfc50153df33858afd3ed","nonce":"15bbbca1da3014f719666d3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"63a722fa7d41b77ffe25d101b4dc575be7127b547b129949a42b853a91dc235f005c22416115706ce80c79bf2b","nonce":"15bbbca1da3014f719666d38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"6105707e38a0c4bdeefe6607abaf81cb5552295f4d369da1ca858e3888b653febd54811a32e91e962c10fc2c60","nonce":"15bbbca1da3014f719666d39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"f61953abb6cc7f04ddaa7b148f775104c76ee5a1f5c954d74ef20b09ec363f2bdcc5e3890e724d18ef1777c1b0","nonce":"15bbbca1da3014f719666d3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"94da29858f6e4a543f77e0d4798c8c67f4b7e11c63befb2ec57f739561c7efa4739ad0a9aa7e05e23078cafb10","nonce":"15bbbca1da3014f719666d3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"892bf68952b1435dde5df6ba6d3404469cacd2affd474be03fb0298d3cfd5639639a0ae6cac84a09d92f5d5c1c","nonce":"15bbbca1da3014f719666d3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"7c7fac81989e70daaae3ecc1c7d451b38624ca9a12fcacda93fc7f1e0d87434662905b2d4578826139eb07b267","nonce":"15bbbca1da3014f719666d3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"837c36c91050f4bf391e6b73930c5aedd9a2059ca44be61b1a528d2001140df6c2b308e068bfb4b5b35e176ba8","nonce":"15bbbca1da3014f719666d32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"90db9a5ab679de85c1a3e335b0d00205e22321f0b3174560954d0ecaf636ed40c538312c7793b8c680d2d688ea","nonce":"15bbbca1da3014f719666d33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"3d3f7ef80fdefdba2a4b2d18513b5f2031cd474cb65da3f988bb160b6d1bace4e7f8711c4891c8c04eabe698ed","nonce":"15bbbca1da3014f719666d30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"92c5fd4c65c897ecc572b041d35414b0062eab09539460654f091f570ceca89b6f62738254f0de610a918c18e6","nonce":"15bbbca1da3014f719666d31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"d6e65e82b70dabceb0c6b0965e1e0d59f81a8d1b73d0bfb858c640e400841640ee040247235522861ab68634d1","nonce":"15bbbca1da3014f719666d36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"a1c676556fde72f77db6bceca792226ecf5d43908a529a9b05ce8ffca30f406e301410e28d662d664bfcf84b6a","nonce":"15bbbca1da3014f719666d37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"78b22f20c57d0d8b53d718ef672c0bd220eb47284adc280d3cd1f7127758d5f6149a6f6e210bce537600cc8a33","nonce":"15bbbca1da3014f719666d34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"0403822c7f998ea90f744881d62a622acb8b82de0b3820409d422ac1ebe173614a8b0cd27534d8a65eac23b4df","nonce":"15bbbca1da3014f719666d35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"10466b67e28223413ed451a6861726870e756cb332d321f8a1051ce0d6b176c0da4c430dc8281b7868b8019467","nonce":"15bbbca1da3014f719666d2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"e62b922c5c697ffd3e2d263c0d2a90213c675b3eb6a65c0c42a488088cf70d0a2c0b06e313e9d16498facb139f","nonce":"15bbbca1da3014f719666d2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"b43a1e31727001cf225db87762dd8a9e885449a832ba026ce40167cda9ca691274313fd33bd8b75936a039a62e","nonce":"15bbbca1da3014f719666d28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"d144d41e797afae4822f7768b384e6ee1407fca59a9ea6fb33795c1ae27f8f2284c8d34b333898b570b14ff601","nonce":"15bbbca1da3014f719666d29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"2532f6e01b0092317779a5789e0c8afe8c70ffe864b5d359534f85e9db72cf931ec7bfb2a00c98fc9dcce1d740","nonce":"15bbbca1da3014f719666d2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"1d7f0a92ad10eeed363c367c160617f84a84475c8f6a04619a8c76e4a1020351096ff700128bcb5dac35d10423","nonce":"15bbbca1da3014f719666d2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"f29580ef311a3067650a7c777b681675cd029b629d82ad9897ead6e36d0bef6346a8a8b93e4f24031868afd174","nonce":"15bbbca1da3014f719666d2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"64ea34ab751d303fb6b784e7c7b04fd48e26b4ab79a476c2bbe78998ded2835bd5adef2f2351b4eb9b7a4c9921","nonce":"15bbbca1da3014f719666d2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"bbc5b4a4c9b9a7096785fcb4b52466109851572d152223060f18ba55286d994aa20e753656b0a8ab8832e721ca","nonce":"15bbbca1da3014f719666d22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"98f7949fdf8fccddd3def0ac5e37603f7f773d1ee23215b0e4afdf9ef3fc9e6ffdf6d90df9f2ccf6c749e9e1f4","nonce":"15bbbca1da3014f719666d23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"8352ef47fd7a79bc487837e63c6b657ca4cb69f4b6237c543a51b557ccfe4d1910d7bfb4bc14d0fbe4821b7b9a","nonce":"15bbbca1da3014f719666d20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"09108038ae2c83fd82d1046c6af204161dd92b4b8a6a222a8a35031aa28ee4f69b6fcae6099024d718f24f0a67","nonce":"15bbbca1da3014f719666d21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"9f45999b0251221c7f4b80f2a5d41ef8af4f3591f81bcea88429ca043c7f868b3187a728eef5d15eb7e04e1af7","nonce":"15bbbca1da3014f719666d26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"0a7614cef3d9f46630079d49d28604c1cf03eec066b282718ae56bfefe89c99fa8312b074971bf0276bce715b1","nonce":"15bbbca1da3014f719666d27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"2e696ab1e1da46d67a9bad8fa6ebf85345d6aa781686418b06e82a1a3ca4d1d96b67ba2422d5c85ab8bc083ba0","nonce":"15bbbca1da3014f719666d24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"d9b4557ab7b22e10a1c91f716c80412dad772e94c216d975a44372d7dcd7cfe1df970fdb93b1e412c563ed6ecd","nonce":"15bbbca1da3014f719666d25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"c232aab8f69f7b2d5f048881acd7d8185466faa0949a52d57b729688eced58a542c0bb29381273fbb06f719a81","nonce":"15bbbca1da3014f719666d5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"2ffb48a2a7fc7fb51ff89f1e7f7705d8c03d358e79d739c7abf68e108dd15822ca228720a623b71a29694cc34b","nonce":"15bbbca1da3014f719666d5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"ab2b96b594b72a4170235ae7f04c67db78d4a324fe7efd23305bcfc39d538c3c230ba10ccb1eff0ca41d8053b8","nonce":"15bbbca1da3014f719666d58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"94adb2851629319c1e3b312d096d20cc21bc9a688738d5f373e913dbb7edfee2344ac2ca31c856ade61c588923","nonce":"15bbbca1da3014f719666d59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"0566ea009d68b9bbca64151c9976740983b8b92236e96b12b5708105b4066aef6806e4e50e05026e1c4b0cfdb7","nonce":"15bbbca1da3014f719666d5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"2f0a3d184299974a248fac6cf7ba517b3514df75b13b023fad4eac4652d189a97a48f5bee31ae8b3cd3771ae7c","nonce":"15bbbca1da3014f719666d5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"60ccab2f1ab968ab4508e078894153fa12a0c0bc11825e5a198a3d44dcdb5bcaf1e806d1561ffb00effda517b5","nonce":"15bbbca1da3014f719666d5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"9fdd5f48665167a1d361c5a4a36fd1e58cb1565a9e8cedf796a5e3db9efd6605248088e02071db7f9b6e7e17ee","nonce":"15bbbca1da3014f719666d5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"f52fb516297c559d6667ef689945d5fa1f54075c3d0fc68b36018ea1d00e3ba5ad2bf2763e1eba05df33c192f5","nonce":"15bbbca1da3014f719666d52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"6617d4239c18c7edacf2f4c63d068b113fcb6d0d1fedb4daf57c9fb1de42cacef01b3b5c7d3e9c1525077a3106","nonce":"15bbbca1da3014f719666d53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"e1084204557dea62219f8b9be0cc176cfd6bd4327ff9f658e1cf7ed0a047b2c4070a0752525029b5fe48d3952e","nonce":"15bbbca1da3014f719666d50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"92c53fdf0986137da3bd59408c24f6772c29ca372231214ad44ddf13c0806973ec4bb447e1167e65b55848ce57","nonce":"15bbbca1da3014f719666d51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"c08338b4747257943f576486d2020a1d65c4cba6dcafa95177d3a5d1a9638e632ac72512811defafef864dafea","nonce":"15bbbca1da3014f719666d56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"676c0599e27ed1e9de16f3fba7d5bacf1b710e49a2cc1d4302928f5b9496e1704fc3837410fd899cf798e286d6","nonce":"15bbbca1da3014f719666d57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"11f45cf77567e699fd8a8c58eb293c44952a32fb8bef271e5b2981e583777944624afa4b5afc50a9a240c71fe9","nonce":"15bbbca1da3014f719666d54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"a98e2e12510ac1d2c16e629ee375c10bfd6d005bac8bf817a13f9b8f7a9034f4d4f27bb62af7291b6e6b19335f","nonce":"15bbbca1da3014f719666d55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"98d4f23ecc409c99d3dd0164f8b56d933ef74f8f7dad9ef09c240c1aa475504b3a4c6a9a9ae9afb250da91243b","nonce":"15bbbca1da3014f719666d4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"509867802acd3ca36f4f14c5d536e85961dd47aa47b3fab7b5d4d5d55517b1f5a1d501bcb5f286967a01c0a6e3","nonce":"15bbbca1da3014f719666d4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"47b1e58965018205d47c84271e426f7f5660bf7ccac4e36c29b48517ef6d416876768802c786571d18f8893e3f","nonce":"15bbbca1da3014f719666d48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"b69644a73db2501777ecf26c68754cfd1138cb806e4f26ff69b5b3888bd89e64dcd1fa0fa210907d680ff4604f","nonce":"15bbbca1da3014f719666d49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"b86d3d23c2a09e79a4872ef35d97c334b39e711d8030cdea8d82b952067474cdafe80d59a5fcb20e8c302bc0b1","nonce":"15bbbca1da3014f719666d4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"d3c823b676f0f44aebfa4698cc223088044a6b607230290ad2c57915bfc2759fa07ed825215a377a96d9aae849","nonce":"15bbbca1da3014f719666d4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"60b1d75c98f0674c4f7cb1fdbee711f5f54f1cf74bec6be2383de5c4dcddf21438a33bad504b6c43fffca17dd2","nonce":"15bbbca1da3014f719666d4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"1ab401bd0f4b9f8c058d3f1a1624d774c30a159b03b28bcceb9c798aa92b57c2c4c80cf016b4c83edb4a6661c4","nonce":"15bbbca1da3014f719666d4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"f57c304d0c998200e0d263e1370c751822fc681b297a2f385503536ccbec5256cfcd793c2e32c849b7b49c4dfb","nonce":"15bbbca1da3014f719666d42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"35f47aaa8d62428de86a035bb85226bea5e96320096e3c8ce11b82b22115f50b3db8cbad00bd334adaa901b356","nonce":"15bbbca1da3014f719666d43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"e5c2b01ac0707e7a55c27b78b0fced603bd34e5f98a1e491edb50d21c196de198be7879292a4f0fce31162ccdf","nonce":"15bbbca1da3014f719666d40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"c5e87e908601c6aee16fa94a7f6c165bc687546a4d85a310f0a0f11387f4ef5b7803ec1a13b06a02b8147b5d52","nonce":"15bbbca1da3014f719666d41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"edfffce4ea1f25f99d0d899215e99989b616b8bca45ccc41427399cf040dff64f5caf2763e0314ce8dd771ed20","nonce":"15bbbca1da3014f719666d46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"efbd6bf5879623a6ff818a276afc890e6b54b055a14de3ec7f4b8f30f3cddfe181bdaf8a3507308c591a173278","nonce":"15bbbca1da3014f719666d47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"3957df970fec70204ece5c74cc1182f9cb11c169bc888cc3dc7e226ecdca57ce5433e5d96c6d892805b436546e","nonce":"15bbbca1da3014f719666d44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"5fedf6dfd394c121f7779554cfe77358d707e61f93ba737b00bbe57200384ffdbfe16238d580211244472175b8","nonce":"15bbbca1da3014f719666d45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"f71a765cbf906e2d4eacf990dfaf4046797f05c157660ba2b6da86d2e04486ee2aae64bce5913eb923c86da3a0","nonce":"15bbbca1da3014f719666d7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"93a6e2370298b6c7cb254d003f94c67b723ccd1757253be6c2493c3482d21609c9a3eef1d5274762ea82e023be","nonce":"15bbbca1da3014f719666d7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"28df7ada22844c87ea8de6a84fee9dd26bb5305c18a775b32b9edc5577fe3aeced9a2bb19100307326395a3e0b","nonce":"15bbbca1da3014f719666d78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"88e8467477e2b7045531340cc91eab50f40b8739ac8de6567bd2ec2e97a425aaceb97b99549e15e977ff5ca666","nonce":"15bbbca1da3014f719666d79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"1a5ce9fd0302d4a9efc6d91bec03e2129108cd44762154ad824284e1246c44b7f8a173f7d096b2d2f3669c748d","nonce":"15bbbca1da3014f719666d7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"9a8c913a9144229813513525bb4c8ef8249e7120d0e392d33ed08c5014b76f937183cbd0ac4b7a95a4509a16eb","nonce":"15bbbca1da3014f719666d7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"bd4c66d0e5b6f6cd02f46daad6b758b99c36b04d25404f46a3fedf1439584f5b32a96ba78968e439cc4a9747dd","nonce":"15bbbca1da3014f719666d7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"7a3356144f88e49a6ad967cf448733fc6674d56a7bff3d0aaea3b6b0ec0e063c95f28874a8f69bed2ba550a4fb","nonce":"15bbbca1da3014f719666d7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"fcea3960eed6b9c6ff18d6863d3333ad95990433353def658d7eeb06b4ca8e2e5cf50d9597073e42f96536ad28","nonce":"15bbbca1da3014f719666d72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"42cc7541c9632dc4a808feda86e70743e7b551537a4b5e0d080b56f26b36b61f0190ed64f42bc07b67f2eb17b0","nonce":"15bbbca1da3014f719666d73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"87a73b99d59564982f9462445451e56064de248e60d37e1177e8806203ff512c815ec38abffb92645e1e37a143","nonce":"15bbbca1da3014f719666d70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"c7980e2471ae85159f5ad71076036471d0bb6f6c5db72a60306358517bed2cfd5f0f02e2203628b18f1111d4a0","nonce":"15bbbca1da3014f719666d71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"6f7eed5c262eebcfad8485443e504aa97cfdf1595cdd894e4c3585abc459c42aa6728308bf49ca68f55e336207","nonce":"15bbbca1da3014f719666d76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"d1fc9f2682b8ef996ce7734ba6bfd740b5ae5661e53cb63849b5c071489fc42a487af8762908df27e3bcdc19b6","nonce":"15bbbca1da3014f719666d77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"7f2678fae39d7fe23913aee7b0a666a1d2815a0cfca295244dbfbb776bc473332c74b661f869d1f92125d4b9c6","nonce":"15bbbca1da3014f719666d74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"60a7ba0b9c674ecae779ead93b1516c9d4788c8f2f1169aea48aa2133e46d2b59e7037eb9adb071e30b3957607","nonce":"15bbbca1da3014f719666d75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"d91303b87582d249284198182a84ff3b05c6333b7eb2b253346b6bb066cb92dd9ef8a44b11a91573cd4b1dd584","nonce":"15bbbca1da3014f719666d6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"a357176f4845597264693143efc44ff54f302cb2abe9c30eb115a3e741e746265c99d859451dadc94a9092e0f2","nonce":"15bbbca1da3014f719666d6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"b62504f1491be518843a2634e84cff2687d6920a46a54883fdf5fee6531df8070bfb2c6946d5441fd8458e3792","nonce":"15bbbca1da3014f719666d68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"4dd4af056eab81f3a4addd701a693cddbc5530a36a378c7c543fca71c0beda493ea858879d94c7d905909ec6a9","nonce":"15bbbca1da3014f719666d69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"3f37304eedb8a5db76a49834d8ecd085fa2d3fff0ff32bdbee31e5e9a7afc15c0732ba57112b21300b4258b9e2","nonce":"15bbbca1da3014f719666d6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"9f5468974405401dbedc05fb8d804b2a893958d6fec1693b6a67282a5c1b8b56f9682c5b6c5321b13f5308c146","nonce":"15bbbca1da3014f719666d6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"b790ef9d99747b3e573f898150a611c846584da5d21640c7f620c2b8fcd396f9ecaf4bfc1c85cc149764fe372c","nonce":"15bbbca1da3014f719666d6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"512ed0d789a7fb73a5fd008024b72926ad61752ef9de4c4062657071bd94c0019919f36b93b4b2204f30013f36","nonce":"15bbbca1da3014f719666d6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"3f1a8537c315f8893567be17edde0ecc953598f2d2b83f4eeee09bed8a4d3359d77122f331c1b83f6aff382930","nonce":"15bbbca1da3014f719666d62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"2a9eca7b4bc6fbe662beecb6c85fb0bd5772d4a0e8e81a074b2eb269d9957c78c25857d6544e8949a100edfe15","nonce":"15bbbca1da3014f719666d63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"5fb920e9be36684976f2670667ff86a204abb139b79d8b1edb8187f0a8d1602670e52249e0b21ae31b391e3c9d","nonce":"15bbbca1da3014f719666d60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"26fb0ff990cef5d62640599e6e2b03f76b7deeb23b03dcfb70f11a24b2ca7270b0ca2f9e7d1bb93222a8d6e4ae","nonce":"15bbbca1da3014f719666d61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"6b68d1940857fb6e4cb573dff81626767170e16dabf846fc17c491fdf1a6e54440ff18fe130d970b1d0c9439e1","nonce":"15bbbca1da3014f719666d66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"0483d262246d2fb5817a2158bc59168628005e26e2cad97e8b42bb0d6e95fc9ca71d2dca96f6ec320c96b51263","nonce":"15bbbca1da3014f719666d67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"e9431056e0fca80e815e2d504ecd5cff20d7c1f1a4d7c4ff729240782ebcdfe5b23168576de0fbb2d38906d423","nonce":"15bbbca1da3014f719666d64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"49db5438b0ea81399ce1e86bccbd9955af22299756c39402cc67c400d54cfb4acfa2c82c1d180abf870447f04d","nonce":"15bbbca1da3014f719666d65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"b342b7b4ae774f7ebdec44db53af18c42769803c6d7636468d5226df320ea1209adcb1f0365ea98f0f855d689d","nonce":"15bbbca1da3014f719666d9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"ebee478e72e1fd2d7314c6d770563aefb2d8061dd62a85033ba5285ea975b0755d90bd7bf3ca816d012f2c2f5d","nonce":"15bbbca1da3014f719666d9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"48ee1a406bf9f42279e084b772d7df1edb884318fa525c8185eadbf85c91697ea1a8c60cb87d67b878d0d61e40","nonce":"15bbbca1da3014f719666d98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"5c2cb276b430facdd2bc9748cc2954aeea5a1bbbf75caade8ef9997736b8444fe411ef87e6337c79d1c870493b","nonce":"15bbbca1da3014f719666d99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"72333a85a421aff76c06327b18cccb79e3ec2e8f059f252e317dd9e94461232aea1cee94a5ab1c92e1d4549ec6","nonce":"15bbbca1da3014f719666d9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"4846ff33540cf702968ff0a8f9e2e851ad602d4b82e5c5db836026c9dbc3b21f9a9c9d2308a70204e48547bf7b","nonce":"15bbbca1da3014f719666d9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"7fed353d48aa819bae8229643811cb7390e73a0114c810f3e96dcaafbb2f01e98474e5a3891e6abc37ab79ad5d","nonce":"15bbbca1da3014f719666d9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"c952f3e97c4df30ce18b499e8eecb7754d22eba90a2bcf59d1e9a6958087ffb9be71e7bbfaf705a276eb740fab","nonce":"15bbbca1da3014f719666d9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"7b7034317c8d9b9e8396a0c12d3890c70d5819d48987451ada286c573039c2f4b2046cd4b6e2533a45b12ad2b3","nonce":"15bbbca1da3014f719666d92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"e61871461b1321ccbb197eec99c5980570938fb83872d268528fb59bb3e4cfe6d5fe3c4ce606d1ab8a0af19cc1","nonce":"15bbbca1da3014f719666d93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"0d15e4fefd9dbde14d188142b33ca0068638cf7aeec717ee105bf583d7cf5773ed186ecd4da5463d92df4fc6d7","nonce":"15bbbca1da3014f719666d90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"4433dd28de416602d3fc91e9c8818b868cbceee795fdbe3310a7fcfbdc9c4451e5136ffe054cabe749bdbf8333","nonce":"15bbbca1da3014f719666d91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"dc8993122ca54f233364c3463ba016882b8f31b8fe2baf9c97df30d92f321198c3fe80f46dcccaa9540acb6f78","nonce":"15bbbca1da3014f719666d96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"c18d8575b31d99682033b837331eaadb60459bb019e99c0e6a6234517681993a269d7ec89f779fb82bccd3bd92","nonce":"15bbbca1da3014f719666d97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"d910e6d38cf15038c07bb5275ca429bf073d6498d760b394fb148ce3260d964c15891f5d78b35df433cd312766","nonce":"15bbbca1da3014f719666d94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"ad188164056fba833d14efd72af26dd35d755d2820338c15f3558ae6a963c23770995f9a2f02fadb97e8091b9d","nonce":"15bbbca1da3014f719666d95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"10aa49e8b2f0334fb94bf1cf7307894d637f61b6f996bde3538e56399dba8768e3ffbaee401613cda04735fbb3","nonce":"15bbbca1da3014f719666d8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"e1dc345bf79520d8c7c22268d0602e5d450f74f6d8022b206e3f82483f22840f058c2b32bdf2efd89b0c464478","nonce":"15bbbca1da3014f719666d8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"076b5c09870a7c10a0cbde401583b08a07fe20865268e8f665aa4661ae901f8ed89f313abc68e5c9670217ef31","nonce":"15bbbca1da3014f719666d88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"5c10b4ba1c73b804027ab34fd1cd833ed539b893f30029d03f84258d03f8e0af9b41c4a92f9efa1abec8ee3a82","nonce":"15bbbca1da3014f719666d89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"47ddb6e9483c06f89daafe72333da614fd0bcc0aa74ba8f5d15263bfa4a45f7e5879657ea447f370d99ed9a735","nonce":"15bbbca1da3014f719666d8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"282df03ea289f7396c5ed4de7bcdeede15bcdee233ff6d4be04187150269984cdaec53f05c9103408b883b6a69","nonce":"15bbbca1da3014f719666d8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"b7b6117475db2efe951e17c4739f444a9cace87db4ce5cd2dfcbda499b533fb1eaf404303a7069cecde4ba3f43","nonce":"15bbbca1da3014f719666d8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"8d6a21c4e3a6374cf1560b515f299fd15d677be686329fd8ec901abcf19657ab18a205a2dc06119ee23f7bd31a","nonce":"15bbbca1da3014f719666d8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"bb8ef651e48cfbe5eaf57afa36d4dd74411ec947c38bd81d17e2e002a5d6f5c3a61371ad7b2a11cc13fc4d9467","nonce":"15bbbca1da3014f719666d82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"59e9fb96c49b1320610864a7b802b8f5c16923a8d664882f54e8e202c350cc4ced0d83fd7fe0d138a12a16c058","nonce":"15bbbca1da3014f719666d83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"8dc0dd74fb9cbd7d182c35b492ac097433e77f48045bf359b90f94a8dc16077dcbebca4acb5824ad60276cfb74","nonce":"15bbbca1da3014f719666d80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"eb9349fad4e56278596840253134a81fc4de28a766433851c1a314820558a8a3c447ad51e911ee1f9672befb2e","nonce":"15bbbca1da3014f719666d81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"54ff3fa31910a5ef3a507e9e4eafd2ad1dd9928189679e977c5f3c5e6744ab0267958153a098438c4577e24edb","nonce":"15bbbca1da3014f719666d86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"80ac9a5f7b2b4f88cddf3ad8876b8df01bf09f9d73ba18c3fd4561d0b8b67ee61e624741dbf5b8372fa9cd9345","nonce":"15bbbca1da3014f719666d87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"d957d6e4a1f8d42fa37b708a6c28910a607450c4652e51bf243cbf96fa8c29a9dfcfc64581cb2b5a79754c33ef","nonce":"15bbbca1da3014f719666d84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"912842358f2a26cec0617f067d2506b32be7bca739b7488408ccbed5960a5f6c5a82260bf80f8561d4051e402d","nonce":"15bbbca1da3014f719666d85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"90204fcc2d5cbead0ba15187b037592e28225e72607735e5db8f05c4e53a386e1e087fa8be70dd50ba8228646a","nonce":"15bbbca1da3014f719666dba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"4b268927ae5d90ce2cd34d61b7786db420a98368cf4373522b14fa003171807e8ade4149b160e95bc64fa8b20d","nonce":"15bbbca1da3014f719666dbb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"1285bc4e8720b179882254d7f9d919b4da325d12dcb1ae60ea435a2f84071acd5a6049c4d64dc8584cd7d46f3f","nonce":"15bbbca1da3014f719666db8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"a517c9971add1510107bfa4701e4f788e884bc17b50577f7d2506f4623584ca4c15aa77198a1be912ac8bd2ac8","nonce":"15bbbca1da3014f719666db9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"130b4628c1cb0064b3bd695210c502ede6167d3d0787698afed0ade03397ab7d3967c75c32acc900971b1d1932","nonce":"15bbbca1da3014f719666dbe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"4bd288bdef1e5ace3de729bab80b75ce2078e6349ad37704a12026de4442daeb5852cbec4ebf98f7d7f9c5c710","nonce":"15bbbca1da3014f719666dbf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"adaa1932d6c2ff93281c8d72df7420f7e309b9391921804fbdeef0b90b96ea939e84472b848cddcf29955731fb","nonce":"15bbbca1da3014f719666dbc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"e46219bafe216acf003583dc14fc5da9919d9474e9447d4fb0f7381c962f0775d1dbaa56e8260495abe9c4716a","nonce":"15bbbca1da3014f719666dbd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"a1ae3473e8eb8cf428c54215ba7a446c92b31eb3ec9cd51cab36c434c57db695a3272cceaefe7648f25093ecde","nonce":"15bbbca1da3014f719666db2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"e4f7bb5b28b11cecddf4e24cfa62bc3956597a460e4564bf73a3bca35d1052ce525f4f3138228140bf8931208e","nonce":"15bbbca1da3014f719666db3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"d89bb688469de6bc0c68b2da4dbc135a61ecb99b2462a08653c977606e5eb4df7329e1d8c0ac9605093d76062a","nonce":"15bbbca1da3014f719666db0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"b0e20ba0c5a7276da7c1edb2d48c02a0dda0f878e794b915f064ab838aa4f9f63da2fcb39d2310e7dfc32cae66","nonce":"15bbbca1da3014f719666db1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"fc7f9899e894b07d4dab5a9b189c7a9694b1d0478c0267842202a104bac41f7df57e14867f8a3ea7ff0ec1a685","nonce":"15bbbca1da3014f719666db6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"dce04e8fd78061e4f709b14adcadb285972df96391c00abb3088d967a22a473aefb98514b4eec736ef9b4c141b","nonce":"15bbbca1da3014f719666db7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"abdf464639f8926981a1c5666e0bdbae77a9560764b19a93916ff5708e7e7fe6a0a63b5ca9c35e9eb2dda3c269","nonce":"15bbbca1da3014f719666db4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"72738d99465af7804f7d87b2de4e6231ebc2568f46c4088830f9e637ff30b7e6033ddf524110d6321b528d576d","nonce":"15bbbca1da3014f719666db5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"7077ea357e7f8b969300244b98a45346fc1ff6dad76e342251798b241d9a2bc5a3698049c9167412a9317718d2","nonce":"15bbbca1da3014f719666daa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"26faebc8dc2d9b18d9050639709e58fa27e7f455209c3d14286f9a7f953253e1d745d9f7d5b90f676bcf329a9f","nonce":"15bbbca1da3014f719666dab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"80ffddcb8e3dc2bdc5fa344ae2e1dd05bcce6a371e9fe574a617509c3421c26b2bc489ac1f7e6371e8816f05be","nonce":"15bbbca1da3014f719666da8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"6c04246279e70939ffc0ceaa9971a0eb42c9e0b8f719bf1cc528823777a43daf32ed76e9fe2200b021580721bf","nonce":"15bbbca1da3014f719666da9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"26e555ac570ed4266322ad2d948f634d7afeb87b62dfce8ecb10d28961ffb738b2dd88d0053c10efb531985c9b","nonce":"15bbbca1da3014f719666dae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"d654ba52df8d8528aaa3ccdd0ded5b4a9db96288a438b2280714d459a7e1b9c2133c3841ce95e2b513cf0091b1","nonce":"15bbbca1da3014f719666daf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"587c1c3b59f98be74ce67d8f9c439cb7940f165f0d15b24f40bfd054885a1915671f760df0b07ab3d52510ca9c","nonce":"15bbbca1da3014f719666dac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"1571faeac43dafee9ebd599112f3878c1a6509f958b39e9c4906055084040a3ec775fe55e3b5882787c5c48b73","nonce":"15bbbca1da3014f719666dad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"41dc4c44ceabf96a47ebc25fb144d9fc977d3a3bd0d16eaeb76e93a774f72413ebb2b76fc7d8d124a429019ac4","nonce":"15bbbca1da3014f719666da2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"736d212fa3fe45efc8affb5d8cf1a462364f15865cfb11e731ef2704ffb0e76e1d180d646cf9ddb760dfac143e","nonce":"15bbbca1da3014f719666da3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"64261d178ec8e581ab83b4ee05671ecfb5214a6cdf5c78519bfed75be75f05ae32cf3fb054877da03c9f254929","nonce":"15bbbca1da3014f719666da0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"6c5ecae20a73d2514bcb3ab590f6c498cab5314bb19eb61fdc62b6150f97b6f3690628faa194b837c67de39e14","nonce":"15bbbca1da3014f719666da1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"81bb62a9e6004397b6ca9ebb691a2cc90cdac3a9f278a0391d28bf82d178405c03f74584bde8b47dd4c3969eac","nonce":"15bbbca1da3014f719666da6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"1f4c72cccd5d697e2b1c7e11908e82c2e9e9ce8862cacbd2dc6070e04515e24f030f576b332a7bd7979f219338","nonce":"15bbbca1da3014f719666da7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"993b2dae240e138d0901860933d7a27e83c517ea04205094e5e23910e450811b7454a6cd754864f157ca5d9d0a","nonce":"15bbbca1da3014f719666da4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"6bca922f382a9fdb8d39c5e05d10b91b7044ea3edc01369ef4fb1a534b4f02d78ef125445893ce435653d748a0","nonce":"15bbbca1da3014f719666da5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"3b6d5503271e3e8d814026a007f2fcc7456a536b9afc4d9f473e7d641d84509a57c93d674344578da2ce858112","nonce":"15bbbca1da3014f719666dda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"88dcbaf63aae946b857c6362919104919a22346132934e07ec45bdbebc30681ef14bfdf11d544f170f9cd41c72","nonce":"15bbbca1da3014f719666ddb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"dbe26534e524bdea531ee1c7eeae6c0cad57cde27160a013c238c770d3797f57ab8e02d64d538a9f860154cfe5","nonce":"15bbbca1da3014f719666dd8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"4e7bd3a5b13fc81d15ffdb7181afe6831474764bee04f68a069a5948b18f19247d0a2b0360b9d428a13c0c8b84","nonce":"15bbbca1da3014f719666dd9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"321c536e0ba2b22410ffc31ca8eec7a2468e75958aa53a81000973676bab80f37527b21faf8f38e04e20550223","nonce":"15bbbca1da3014f719666dde","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"57e2d03fd6d901db158a376728be645ef63f28b58ff7b8f321a55ee3a59269ff2308d7941ba1034a1da8f1bd4e","nonce":"15bbbca1da3014f719666ddf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"6e6083d6b24774d1da1bda9f815960385182212f43aaa1987dc495bf0eec9c93a428c7425af35f8a831273568e","nonce":"15bbbca1da3014f719666ddc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"e62ab7e2d1f7c25bfc9b401616df04f5f8921680970c9d4631d4df5e1b95c3fa89fdcb82582b0160bf4b14ec71","nonce":"15bbbca1da3014f719666ddd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"de94bf616509b385b1bf3cef1f09aa3b9e963e44778b1dd731d87afdc7de28d1e7d0d7603dbc8b119b17e3694a","nonce":"15bbbca1da3014f719666dd2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"98a4c21492f784809625620bcedd912330b841dc6f317c8c9ee5ec50c4f88d3ab1e14832b084f912bd7ae06aa7","nonce":"15bbbca1da3014f719666dd3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"fc3cda89a0f648030fd5407d4cc03a05d542bd15b021389fb52d3baf647624e19acb29b9a0c046d68d493a4c01","nonce":"15bbbca1da3014f719666dd0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"ec4c08e6e4d42a9ba710a23917eaf52b14cd92e4917b65d27a955b3a9e495f48464b9f42e4f0e41288f87af410","nonce":"15bbbca1da3014f719666dd1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"7a93f56e6666572a86f47afbd7b97a22b04e6d82fd80a80901bb10f7453ad5df37bdcc97490d1abced5e3c18f0","nonce":"15bbbca1da3014f719666dd6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"cfb4406b1f62d97f875c30a337002fac664e32a23ce2b76847d013ff9739a67344ac3babb2dca59b1e3763c470","nonce":"15bbbca1da3014f719666dd7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"c08a9901514bc96a9297d1a3f8179b3fc167cd64b5f3562f4c5601d60f495ee5c6661c97276641f7a0b994e0a4","nonce":"15bbbca1da3014f719666dd4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"5a90e82394ff8244e151a3e9f0ded816f9b8beae47f48dc3d7c75f8a8f650e39a5cc52240d35fe4c03375d7207","nonce":"15bbbca1da3014f719666dd5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"6438bc15b4173281a17d401d521dfa07105fc215c7f3e0e64ff6afb695ff3cbd4df2bd9567a8c7a35f9a121fea","nonce":"15bbbca1da3014f719666dca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"6101ea3e609c21d80da7097cec9f229fe8db423a5e83f8ceb11b4e5b99f3d44392af70c3225f7b44a0c62b8690","nonce":"15bbbca1da3014f719666dcb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"71b9b571473512cf0435c8fd12a64266d592693b8e1b5205aa3a7941a8a3a3d426858b6ebd55fb98017fa0d6a4","nonce":"15bbbca1da3014f719666dc8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"a0689928a8ca7bf332f5ac80f1f8ffa54fb730a642956f4feb2da88ac0e67a4479c5fc7831a5de0fdab49ca089","nonce":"15bbbca1da3014f719666dc9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"d2c04b9b5b37f4e0dfc7f1dccc35105e0ef6f25f62939088ee99c2c3753c11d80750e008316b2bd03082bb01ff","nonce":"15bbbca1da3014f719666dce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"a4d0bc72d0d83b622097ef56fe421ce35bdb603201821466713354d9bd853aa869c2b95e18fc2d165ea1f713ca","nonce":"15bbbca1da3014f719666dcf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"5d34ec3878dc70e5696efcab330417ddeb2adefcb374683a58f21db69c80df586c27be0463e06a7f9cf0c6fdb0","nonce":"15bbbca1da3014f719666dcc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"fe29349153d6ffff5f418dec37a8e1dacc75e5289521eb4e84603c957a56b411b0b62891e7787ea329b2922043","nonce":"15bbbca1da3014f719666dcd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"08d21fdab52db191d1f5565eef6fcd5b13d0055609d68dbab6c68b8b08a28892176e1c5f06d9bae63965bf6525","nonce":"15bbbca1da3014f719666dc2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"1f0cb0f19fca743c859e2a79a8ed1aca526e441335621c01ff7cb600bfe9850017040ee1669acce2021a319955","nonce":"15bbbca1da3014f719666dc3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"d69dd0bb3e6475e11a8b0691f282e98999588f229b51d215db4f349b98d13daa8c9cbed5429aa4e049fb16bce4","nonce":"15bbbca1da3014f719666dc0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"b6df2af09ea838a22cd01829af7e76da14e21d266a4c9a56fb5f74bbd0639ae6c53d9d9cd3d0226d65473f6610","nonce":"15bbbca1da3014f719666dc1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"0a875aa5a020f644fdb96af543c09a0c2d8f910d8e8f12f8b772fbcb030c3b2fcf5bd24af5212bfdc98047e559","nonce":"15bbbca1da3014f719666dc6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"3c2542911a7f7f34d630cdf72b34dd9677b89006bc520a1c1c82d6ddd74df581a6d3ffb63fb3a77f908eb5ae20","nonce":"15bbbca1da3014f719666dc7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"de1d6cda21f06072421f1b2e18b0378064970293c40fb6d473f63f59032a65e01764cd2b6abf44e2f3447fc72b","nonce":"15bbbca1da3014f719666dc4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"3dbd8a23ca12df780404a9c05875b2110b4fd6b033fb09eb6617f38431ebc40120661b8288eb112871d9b5ad22","nonce":"15bbbca1da3014f719666dc5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"3bfd224fb0c1ab6454c6151bb1833618f66577ce5b7019f9dd2b233f04a29d17e996461db00fa18d69fc3b36d3","nonce":"15bbbca1da3014f719666dfa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"6a93961f43f348625170161a527be3dc6232ae58b3a34ae846a41a7cd6ed32b56107cb46bf8a1872a50dde4495","nonce":"15bbbca1da3014f719666dfb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"4be95f331b6f3332606fa2a64376b3cda320b067db84f4e7870122ff94a26dd77cf4c4c255a6f85a4a014ab0fa","nonce":"15bbbca1da3014f719666df8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"f486508f552b59569604b255244dac7f2a1fdbf040f26601305861894ab89dd5ec546b0d840766a0c4489bc28c","nonce":"15bbbca1da3014f719666df9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"bbaa2e279dd1fb9c60d4b93f52ebe198b5bad1d37d4dd480bbf4dcd9ddddd032b837073ea382d5a44263abfff0","nonce":"15bbbca1da3014f719666dfe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"9536f683d7d67e48c10c6f082698797914643bac3db65fb1188572705f48ffe0e80688c845d3d078e1effb1dfe","nonce":"15bbbca1da3014f719666dff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"cc49508aae63e6995f82973636adddff5f6a94eb8308a45b59e1a2d47410bec339b73f040d1894fd6afbd3cd07","nonce":"15bbbca1da3014f719666dfc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"d34c5b680c0a5d4296921cefffc8337d373d91cfdf6ae10eb92746a50dacb5833a04fae789987246a10aa55c22","nonce":"15bbbca1da3014f719666dfd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"ad24bb7e3a32dacf2206c70890a5368f6157cebdc3a7ab0b6650b497ddb79ae5f777cd970b568f5377bfffd54a","nonce":"15bbbca1da3014f719666df2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"91fa6a81f062dfe77b34884bcd980fab789b11dc8dee322951fa35169785af29bef4c1f46e0e881cfe3eb8db98","nonce":"15bbbca1da3014f719666df3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"3aebfc3ff1fb4429b23755c7e58e098ffdfc1e428d78c87274d8cbb50ba401c8bd4e0361b49b598ae323c8e1c4","nonce":"15bbbca1da3014f719666df0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"36705a128252a80f841fe8c79bc4b25b47a04630a4c604eace6b6594dc70126360c2bcf7a64f44d4c7d44d516d","nonce":"15bbbca1da3014f719666df1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"b332919a1f3bb2e5a4322db3526cbd50378e7966ed145c5d7742da37ec9b7c4252e28c084e1d08561bcc7cdb38","nonce":"15bbbca1da3014f719666df6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"ca95b8bfcf1b3bba57b41357f23c1ac7c4b89da8c9600084b1e5f8335e6cdfc1ffc526e5705bff4ca327689750","nonce":"15bbbca1da3014f719666df7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"72c40d10522003becf8c93403b0ddf7b51fc3705c5543c20c1538c421d021300368be9b7e7936e4b29b733a107","nonce":"15bbbca1da3014f719666df4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"cf6492aa2761c969948f1395549a87e9ecb0374e20ce4e4f1185a08bbd99717f1dff7924f68efe5fab7b9d022f","nonce":"15bbbca1da3014f719666df5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"28b46a5c45c8d7ba9b7b7ecc6c60dc5e6ef0699efd9ef60bd585be723e0c37c5d94f847658caae663855fa3461","nonce":"15bbbca1da3014f719666dea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"c48a570b84bcfdc219329aee79d3a67021bba871e235882ff6f4ff9399d3933bb7cb50bebf25f1b9b287f74718","nonce":"15bbbca1da3014f719666deb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"a637a6403423882d9efd2ea0416be1bc6886571137cc6b7911bc94bd73c9f43a90389d11bd20617c35709c99e5","nonce":"15bbbca1da3014f719666de8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"bd5f77d6fae2a5caa6f637aa3fbc756dd111097665f87dec445486092cde03ed054e13900b497b2a5f15a1dbc3","nonce":"15bbbca1da3014f719666de9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"0ac78a4b309587c5d04029700668cdcc6f625b989c4f56e3325b701b7d4658fd9d090747de3d136fb4ca8faeef","nonce":"15bbbca1da3014f719666dee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"733a058e4c745ae7a62a3df75901cbeb36f64daddd607f3f3374e8b172de45a7cdaece25a4bd38c61560cc38c7","nonce":"15bbbca1da3014f719666def","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"5bb7889baaa757012f79661eae77e99c7430130a31162b74fd887fe7197b5586d89fa0f40d410b6c2f54e170c4","nonce":"15bbbca1da3014f719666dec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"5f26ab97f1741aa175434912a01339733be82fe142fc6d51369c5fe692b52518858459e387d877bfc8a47d3d45","nonce":"15bbbca1da3014f719666ded","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"050f132d0a593dc8b455b73c4ecd4284f8b5b33f8988242a0a192d27f973dd603b552077829bb936d39958df84","nonce":"15bbbca1da3014f719666de2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"7aad900d496c67f83b1b16ee62ef48dbe4893253e97e25776f879eb344e7fa18d42827dc8ccac56278e354755c","nonce":"15bbbca1da3014f719666de3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"fb3a71c9c76084ce8a1befef72a815f4c3a0a398a42f0a7a6f523ed7c5c5638775876d48f0b5cd1bdd3c3dc65b","nonce":"15bbbca1da3014f719666de0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"5ec50b895fe5189174347c8f92d2cadb056c5bc9a861a6e1ceffc1784b3681581af08cfe1b197a3e1a90ab925a","nonce":"15bbbca1da3014f719666de1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"6075114ac04755a683db5e78769373046b0e60ae465cdc2e42f21447eb660fc52a52915146ab18b7dedc027452","nonce":"15bbbca1da3014f719666de6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"17603c8d4a358c8f3ce7380b99f6f33d881146eb6249f4e25c4ae96c6ab84a10038e3c03c2ba929cee6212fade","nonce":"15bbbca1da3014f719666de7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"e9894117a7646ca1bc898e1d7efcbc17fc610cbedfaf801e86d098a29f20c2e64377ea53bd9659280c0d84fe5c","nonce":"15bbbca1da3014f719666de4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"26f491ac3c21e6b6da7087e8f3bee2cb93f05b289b31cdba96314f502fd799df3dfcf8c3f1544ac3fb12c27d8a","nonce":"15bbbca1da3014f719666de5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"1d1b175ee55a95ec796808afaf7530eccade222e7ebffeb6aac823a01730fce7f75e7df526880e17b6086d5413","nonce":"15bbbca1da3014f719666c1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"cc48006e0b6a981ef700ba3fa7c5c1d439a9513026de4de15f09f2720bb588b3"},{"exporter_context":"00","L":32,"exported_value":"8956126b1c0c52a6117359b42fada73e66492080adcf8bfc1bf6c07e0883d0de"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"3e336d66841cd35f9543c58e6965db4cb3caf877842d8e6b8231e15cbdb2237f"}]},{"mode":0,"kem_id":18,"kdf_id":3,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"83edfff9d3c280f5a40efddd0a321ae1c5b682572ce5f70afc66d07640eeaba64651379b61c3d34fbae725e0d05af754efe235f885fd97bbb37a5ada02b5f3e484da","ikmE":"00473b28aedf1d9de36a1860959fcc9a9bdc3eff7f0349d5165a347571855256e79829107a8e58281906be1cfd10cb7c887b7c61b16254bc65c35ea8a8c75a5634e8","skRm":"00a5babfecf17d2b6f659c15f51be5d3546da1763c271fe96a901600e8965f64346fc4e5d5d7a8e41b92ebdb740c885aab7cc96af540655d372d96f79fa3c0a35512","skEm":"01eb9bf817b8ff3ff9346c91cabaacd081ea19654fca9afaced27044c3602ea23b5ab28b70234f0573f65b78d88b79c102d2d20d634adb4dfcf470228b36e0dce301","pkRm":"0401ae0f25b25f4a6204d6266fa3340cdf5007ddadf3fab45a21bc8fd63a6c81a89149236cad289b02e2de57f8ca4d8fba19753a2bb0e56eda413026fd9565fd094507015506a4e37ea8834119f1c2e980cc9419f78d0997e45a911d9995f295a3d19984cc1993abcba25f910d52fa1a4e66b83b96a54ce9174daeda91cef6fc4938d7124d","pkEm":"0401d99606a8e9b5d2c1c92ebe2d626890159dfbd04e867a2a7c21833f77bd0ee8201964099d1ce952e7891f53836055b60f63d7335b9129d3be481dd0fbfece3872b50166c79262f0be05f87066a9838f8f1180f164003091fc738cdf0258aa0fab32539bfa649c8c0416edfca2ca20e3debc2cc40a168435386ec91ab0cd2f4cbb9073be","enc":"0401d99606a8e9b5d2c1c92ebe2d626890159dfbd04e867a2a7c21833f77bd0ee8201964099d1ce952e7891f53836055b60f63d7335b9129d3be481dd0fbfece3872b50166c79262f0be05f87066a9838f8f1180f164003091fc738cdf0258aa0fab32539bfa649c8c0416edfca2ca20e3debc2cc40a168435386ec91ab0cd2f4cbb9073be","shared_secret":"df04b9bc8eb9f624bbfdd620f05cdd044764f5e7cd22fa651c4828747cb22c8dcce0bd4ab8712d41c3b156307592fb4cf897ca73ba0ef6486cb2cd2e7d231d2d","key_schedule_context":"001c32c098a411cf1afaec805bdbb4126b85caae458c62f8d8fbb24168b37930eab113e91348e59600e38ef02667015f5811559278b5daf69cbd8ebf22861e112922f3bb3f4a73881979994c3c83a46628434a24f6fba24b7cb79b65184480612f921684dd1abdb948aaa07637b3944e6ec7bf5089bc9e653f702dec2b8ceb1e0d","secret":"073da19ab0f961550c6af89d252f6ebf60984277263935d4b08e2bf65653cb50091fd46ea0e795a777a2ce82a8ebd7483453ce673ddaabc89609e889679dd2bb","key":"e04ece9067c69436193e19ad3a2cb8bbf8bf0c524a538435623bf7873e866b46","base_nonce":"f981e06430d7d612e96cd980","exporter_secret":"162cce53709b9c9eb5033f3efec9dd1454bc9dbbaffd151a83dbe9c633d2956663877fce6c51aff5306a0de1ebe8ef9fc5388f2a125be338d73005770ea46d45","encryptions":[{"aad":"436f756e742d30","ciphertext":"fb4801f64e8c0819e7651f97a45acfeb92c399191701e83ae640d13ee0ff1609cd68033a7a36b544d441ad5846","nonce":"f981e06430d7d612e96cd980","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"6ee6fbd69d791175276e29116de593039c15041ef0a268e45581adffa16632ccdd24f7136ac8eaf76b3d4448cf","nonce":"f981e06430d7d612e96cd981","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"762a830384b74a32d0373799dd5bac16e70e6ea125ba58e059b68920802de9e09b26ed8c69bb1e6f2518120428","nonce":"f981e06430d7d612e96cd982","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"a83732ab862590ec8681341fd5eeec18e8efb50abb54c2453bf65147331a84e9c0db969e1af24376b332e0cb0c","nonce":"f981e06430d7d612e96cd983","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"b8b5978de1c5e1b177fc26ee83bfeb3e55079d195d5f7c67c27275d8fa34934c15f5ff99a2f6eb1c4ea1dab508","nonce":"f981e06430d7d612e96cd984","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"66b376a0a2b2f1c7f56d7cc5293b2edfbd520a5558904fb5125d403e096bd09330453ab7090c6937403d521582","nonce":"f981e06430d7d612e96cd985","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"5e3ff03d209b511fbda74892b08848d96cdf0615c9925cfcbdc9b19b5606c936a1ba81f3d6bccc74dfa79d9e14","nonce":"f981e06430d7d612e96cd986","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"9c9e07369b84cef001396f09deaa746e1b83f4c410f21c2dd77c47168a435d2328da1b01c4f5b70eaf1fc1bdda","nonce":"f981e06430d7d612e96cd987","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"724a38abc4fc8d162db0c02716a641f78b86ca917e6ada34e0eb17347a1a1c17c12d2c30c13b6c8e9e218c2ebe","nonce":"f981e06430d7d612e96cd988","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"b5fc5d2f3cb762f1363695c5966d8d79beaf904f6ec7a4fdeb1e40f9eb732075ad38dd1cc04bc8acc28a914229","nonce":"f981e06430d7d612e96cd989","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"7f5fecc25bb402c558f1e8d5a124b8f0d7285f95315d04fe1845630b56e5b7cf22b73787ff1e39c2874b6d817c","nonce":"f981e06430d7d612e96cd98a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"01054f765096f1b7187878bbb068befa03920f1611efc961303a8b71d778e794a3e030331e34898704302135f1","nonce":"f981e06430d7d612e96cd98b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"8d52f068110312f9c7beb6d1c7e615e80a720d4e95bc58c7935b402751e8e700e9d93648a3527d2c78cc7c4bf4","nonce":"f981e06430d7d612e96cd98c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"9535f6101771714680f7e7eb3c52e764ab0a005cc3a1e11303d2d345b62d705e4ab8d94edb61c3b5aa0fc3d40b","nonce":"f981e06430d7d612e96cd98d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"26f66133fce1ee056d2f0156aa6dcac6cc89f0392a47a9b0bea4dd99251ed3ea2710ab3b693d79c57c29e22e4c","nonce":"f981e06430d7d612e96cd98e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"3f6b4d9ae6756ffd9f57dffaa1987bf7bbe6f634be00702907cda5b55dd48455cc6b45ea4bb636e8fc1146b094","nonce":"f981e06430d7d612e96cd98f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"c271e73eb44ed5944cccaa1aee8ef1affc7c41baf402993c2f2093b8fff015bd557a426aacaf8a6038885da2d9","nonce":"f981e06430d7d612e96cd990","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"033910dd56d2f649ae85d17bae3765dca7818bc7d7246f46e81319adaaaa1fce0a2a9bac5c02b9a57a58b4bac0","nonce":"f981e06430d7d612e96cd991","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"fc0169cd34370cbf22f061df8116b7abc27a4ee34ee13251259615099845912628c7ecbaeaaf4df5d79bda0bf4","nonce":"f981e06430d7d612e96cd992","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"d5b3ced36c471ed77053ee023accbc5909bfe2c5f31d2d53b3b5e47e105899bb4587fd96cc2042f328c958de70","nonce":"f981e06430d7d612e96cd993","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"b17e705cbb939bf6a7d455a94993feb39b5e28560814d8d161895303f51212fb5f7d19909aa623659653cd771f","nonce":"f981e06430d7d612e96cd994","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"2245e5c7667ab1a53ff86e6272d75cf8a94785cae551e8e92daacbd61a8efe08b007d5140ebb67b6c4723cc91c","nonce":"f981e06430d7d612e96cd995","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"ba5e82a6346345a7db8db8abe81e17282bac9da35ff1f2224ace4a4e77b8067d093bca51231bfaf99632ebf592","nonce":"f981e06430d7d612e96cd996","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"02239e63ea733bd1577b5efbe518a687c63cceec28ccbf020edc8e0ce3ca8d1c5609da5934a8eaf4b87a023e0a","nonce":"f981e06430d7d612e96cd997","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"915176f34ae12523924da20b14db50c6b4ed6a763f9cf7a2dfb202bf3becc1a06a969380f1bf5abaf69256958d","nonce":"f981e06430d7d612e96cd998","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"01773307bc420e27365cd47e01cedfb3ff7cdf7c96ab7f231fe1ec9801db78584f62c7e614208e1a02266de7f8","nonce":"f981e06430d7d612e96cd999","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"86c8c54e65c8e2cd0fb18a2a3dc5b043c810f4b71e1a90912e9221a5a1c60231084c357038bf47286093fa22c6","nonce":"f981e06430d7d612e96cd99a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"d96d8bd3bad8ebdca5c2097396e825cc6018d194a7baec014df5ac9dd943dd86dfc4981a8a11ad84cc8b6c898b","nonce":"f981e06430d7d612e96cd99b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"af214ca0db7211ca84525b5b526d63969c6019ae75d297bb17f98ddb91847d94db889ca43358c6da19c2441df1","nonce":"f981e06430d7d612e96cd99c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"cdc69d367f11e121e2303d4c8bd80af6cb80dd4fcf1a6e931ad22fa78e00efa1d889f87660609a96dfc922d276","nonce":"f981e06430d7d612e96cd99d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"125b7e3aa32a127fcb176370e14cd7367f7693bc5f4bd47cfbecf5d9a29e8be15c66774bd4f314943f0affe72d","nonce":"f981e06430d7d612e96cd99e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"66e36f4f68930736780d8109dfbd11f42beee1a10234fe4e3d0bca8cfa092e3dff8bef4471311071a737b965d3","nonce":"f981e06430d7d612e96cd99f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"7ca3758e04f4d6f3b280413ad8e121250eeea487de91ec4783665c8c35f99ab3bc068ab5a3f33cb0b2cf2c8b31","nonce":"f981e06430d7d612e96cd9a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"58ecfcf168cff4f3a1d9740f8bb26abca34e1465e1873af01741d6e800d76e7585dce3186c4c04c6a3aced8c67","nonce":"f981e06430d7d612e96cd9a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"6884c0a05d3e9197a2d088f563d8cad3a63d82f2a903755384fefaa872ace7dc63885eaf30ab8a0f1fed5b28dd","nonce":"f981e06430d7d612e96cd9a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"1a1d8059376a570ebd5809b9f4e8b75f838f8f20be0cf2f6c3df2e486eb5db4a66f98afdfcbe20d26e972d1677","nonce":"f981e06430d7d612e96cd9a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"d1d37ee0e61e97e5e64a3042a0371ea4a40a770e80b4b83840a177d35fabb80e0e0467f960abf82cfd53839ec4","nonce":"f981e06430d7d612e96cd9a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"f34390edce1d26f812e30972497db350b169e87ff8b19a1502454a58d03b9b75d8d643a39ff5a9c5b2d95d4d63","nonce":"f981e06430d7d612e96cd9a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"72e76ca20a8e0ed192391b1388b2dc4cb97623bfdcf59453ba8bbdd5f0f47de0b58d50f804896f0d67b50691b3","nonce":"f981e06430d7d612e96cd9a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"c23178978d50b5900dfbbc266f27414c12e40d0d3e2f21c46910a9599d2dfedbbeb4ab99bc8d1da02bd5dfd8c4","nonce":"f981e06430d7d612e96cd9a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"eaa821402e09b7caa5f7a3250c4149df7d0753a6426f7ffaf719a08bfe4de76bec459883a2a53719ddec4cc2de","nonce":"f981e06430d7d612e96cd9a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"5c4246998d88ebdb3e545cc802feeb7aadecfc940e45d69b81115212bffb2173d396e32fc3b1ed98587e95de02","nonce":"f981e06430d7d612e96cd9a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"1daab506ba1d553a92d7b5357dab73cddb2e30dd0ba3dc3f0be7182efc155d2c86af4ae765cffc125ef0818f2a","nonce":"f981e06430d7d612e96cd9aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"826ad39508b3c1f900a13e89df43b7707811d75d275e6e65cec46f05ea89cce0e2f0d186eb21c1cfc849475576","nonce":"f981e06430d7d612e96cd9ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"5b0600a60de61acf4083347b86506a7f72eebcd1d07a8ded26c48e861bf8b6ee24a85f01895dcf3f4ac7e3ae9e","nonce":"f981e06430d7d612e96cd9ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"8a5b9e4d7a38b73099340c56204db621ace84e940143cb624cd36ada6126b41a3f0b2e22f7c567c028598b558e","nonce":"f981e06430d7d612e96cd9ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"b27b3948bd59abcc848df517306c2ba93aa2b628796ae1ed2e7aa7bd6c6414b020d047863222abbde6f636e87d","nonce":"f981e06430d7d612e96cd9ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"dcac687450ac0b6f4e3ba1f3d01129b5eb14d0317d256d0ba0d3ad3a38c46e6a86abf7aff200daa386ae5b87e8","nonce":"f981e06430d7d612e96cd9af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"3beabd5d3429323bc59f4ae77522384e4bac2fa262a1f94db84a8897adc4040ed91228c14f73e5d70323d0e347","nonce":"f981e06430d7d612e96cd9b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"46e802532f5b435b2a3700c7e27a9b94d76d2147a6985fba90c4be9d65acf4f4099e8ded03ddaddc3f8bc40970","nonce":"f981e06430d7d612e96cd9b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"56e63719bcbd25e0d984d45bfdf209a16672dc0493d9d3b6941c5fcaf4fc45d07b0eee61c910246a7b1874b14c","nonce":"f981e06430d7d612e96cd9b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"f0941d199653bab29fc59fe32f705119e454d5858685dc24faafc2adc85a7fda01d3dda8d7b26dd476e1505d27","nonce":"f981e06430d7d612e96cd9b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"aad569108e013e50a520ef4a91a7592f4b38d9d24c2d53316b7a355dd7743a69997146132f41e69c8aa3cdacbc","nonce":"f981e06430d7d612e96cd9b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"abe4899922d9fc531f18a89e686c1f6f17ce82813ef6b47c720e0419241400e6ef643fb9c68db05d97713331cc","nonce":"f981e06430d7d612e96cd9b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"8de21a4e492af0c498e6b95d74196da9004d743cf6c48afb98a2a4cfe95c103edfdad4ff7ac58579add4f03962","nonce":"f981e06430d7d612e96cd9b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"50a30ec53a624a5bcc670a144b8cb1900bd17449edee70daf759451eae5066fc7466deff818e518250a0f2e0d0","nonce":"f981e06430d7d612e96cd9b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"fe76286d76a48a81d0550f810567e58878abfc63f6235354f1372c6206fef559220a482259b617ec9167ef3b16","nonce":"f981e06430d7d612e96cd9b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"446f0fd5b50d8c33053388934e8626dee6ab4d90a1da0348e799fe4e0bb8a6af2d349a342b0b0511a163b6b9e9","nonce":"f981e06430d7d612e96cd9b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"55fb293c8f1dce0893562d3563c52826f16347b5703ff6b284d5a4137a0ea61a6e7cf046d91da9c545e3c5beb9","nonce":"f981e06430d7d612e96cd9ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"3eb48e9d757168ed9e4ba05369dff8e5f00d6bdb03d308fea27814281906dcf8bf1284f138fc819fa51e3c6b18","nonce":"f981e06430d7d612e96cd9bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"766c703e025c9433da6ae48d2c3d37ffc9814edb97a539717f8c8711205f07935c0249486716baabcd9def1d51","nonce":"f981e06430d7d612e96cd9bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"2ead391a90e3132bead6aecd29ecd394af474f924ed76736ffa42881b709931ad79f18c44567fa2052524f9191","nonce":"f981e06430d7d612e96cd9bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"27cfac52fd7a285e0f64de1f080915a148c0960d6b3bb32c5f88d7dc054f477d0a127313e2e12a5044a8847df2","nonce":"f981e06430d7d612e96cd9be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"11aea042799464918d5e09a5afc5198365ab97c40d758c009851b0e5df6bb5a1fa5477adeadac7ba3bc68f40d8","nonce":"f981e06430d7d612e96cd9bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"3d5ed14f83b4009cc262c2d9f0c4c138eef34a3f0cb76cf46d98cd18782207cdf362de56e4f093a6cb6d617364","nonce":"f981e06430d7d612e96cd9c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"f6c1834cadf53659be929640b3945a585a9e0a1fe9015be00628e68fdc6afb6e8ac1762ad70fb94ce53966b915","nonce":"f981e06430d7d612e96cd9c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"8814b8d713e13565c854da98d41ccf08f119552ee10adcee3013fc058a2276520bb53429b31eb9f3b50d6051d0","nonce":"f981e06430d7d612e96cd9c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"8f96505490b9f604f6481a6e502c4d629ebacafc2e1890799b289b6a5b213b4fc436dea1083641c8ca3fe00707","nonce":"f981e06430d7d612e96cd9c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"bfd8278af3b1cfbd1b2c873f2893f705f870e9b392fb67e1350a8e3d7f75a96def1eed496ed28167bd6e411a20","nonce":"f981e06430d7d612e96cd9c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"0f8372868998317edcd02e193eb011db56b9b9b6aa268dd8ca0a12605d69651d71ea11945a3d1a5ab64c26d1f7","nonce":"f981e06430d7d612e96cd9c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"9921c71273e296b16a1beeb2a04e120da5c1acfb28fc11fb6dbad47d65147f71a744761a7b795b5be63c2103f9","nonce":"f981e06430d7d612e96cd9c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"1d218be7451b73ab6494abfabde57af914fb3ac341dc6d62a265587e3efb431aa3cbff62e50787cf39ce4afe85","nonce":"f981e06430d7d612e96cd9c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"b7b21d8e744464d22e9b927847ece1e9f55f6925ab74b07e834e6122e291c3268b392a47253ed7028520c57a6d","nonce":"f981e06430d7d612e96cd9c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"c8a130a355e2cb57cb92a06e6871abcdcc0d8600ad0249701f61c23df9634aa61cdd564073f78384ea2a8ca19c","nonce":"f981e06430d7d612e96cd9c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"a3fb41653427a1c211bc0c79f33d56af46c748281de6677a68a36949505ecc116a7849408270548f43ea92b087","nonce":"f981e06430d7d612e96cd9ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"8be8e5d9cc1db9c0c6f920cfec0dab9f8da6686035b6f39bd365e1c9fd614e619fa5a3e431b82fdc93b1c60598","nonce":"f981e06430d7d612e96cd9cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"148e9156aefc0b02c442210f0048236e03e6d5285da7ee63a2af2181e0b55d92f927f3e51a0a4b253084ea41d0","nonce":"f981e06430d7d612e96cd9cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"885147b0931f3b0066bd527839ec2c3adc3351aa3a65234092d76910ddc6bb0d9c62b120ff26182a81a8c8bee2","nonce":"f981e06430d7d612e96cd9cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"5576368b76ba0e720b8a15a5ca583c6980c6a0a0450fc8fba3d2ee129183207082fe33dcadf2e0ef6fe3b86e39","nonce":"f981e06430d7d612e96cd9ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"57f0cbfff6839ef8bf9195a96e9fc8a598c3a56dbe6a9e1cf905dbf1dc7e12ad7af2cc007c12a4aa4dded243e4","nonce":"f981e06430d7d612e96cd9cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"cf75f082246fad9d69cd38d8f7e11cc48978aef03a81e2402e089aa2404bbd9b148e6e89f7f515d915b45c3416","nonce":"f981e06430d7d612e96cd9d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"313335b5f946cab85630b4ead91336f350d4c02ed80ebfdebe7b7218af18b034f3c264734fe3635f884cc18595","nonce":"f981e06430d7d612e96cd9d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"ae469c07ab1975b59cde826d84ef14db3d494b5223a3fb4f51523775f1a6879fb439f48c462f38c09df02fb27c","nonce":"f981e06430d7d612e96cd9d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"128807080c75c807798fae91d25536ecd8c041bf0bda3700e35b6c520046581fafb1d65375f0d47d9ad11bab50","nonce":"f981e06430d7d612e96cd9d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"a381b73e607c7040da5b0e2f83e467c8178ad4eebfc0e4d10ed31893c14544560bb92fd880d3ea436766e26c20","nonce":"f981e06430d7d612e96cd9d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"80c11878701634cbf409939334b94da8c3541622be548f0ee889d7d1ff5cdef602806e1697d3d5d6240f2fd7cb","nonce":"f981e06430d7d612e96cd9d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"4bdde6b4f67787d31bccca678833fae998cc8ae0141d7a9430e8d2552bfe2d674f84c34db03f0b2518893c797c","nonce":"f981e06430d7d612e96cd9d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"38b805d6e24bbd760addbfb76e8435c43d25e357e793af127b485f11fa85c866ac8aed132e473893cfc698f7f1","nonce":"f981e06430d7d612e96cd9d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"6633d6a68a4ab54642b12886a650db4e67f023c7af2a29c12acb3130a4e711c5b13e6cfc1cf3ff81d6e1956bbd","nonce":"f981e06430d7d612e96cd9d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"935c646da24560dd9c6c419950459cb2f5ee7db047de2bf1bdf7b01178177a6ef00ee9fd2f75f68f30580f369d","nonce":"f981e06430d7d612e96cd9d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"2d1e785154f66d8079445a9e53b8f228009440252b24d0a57c8ae4aed5ac5f7b957b2f73a6732cb3da5abfcd11","nonce":"f981e06430d7d612e96cd9da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"5857b128971809414942ce1b7b8f6c2a4489a92532a76b2204960aef7ffd171db254b2da449643fa525c0ac37f","nonce":"f981e06430d7d612e96cd9db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"58b3887bd05f918d06a72d1c1ae6494044f1f57d2ad055d0a16ec991d1877fc928e23c818135c6afea3b41f07f","nonce":"f981e06430d7d612e96cd9dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"98684feff8ac6c427a951bb5f5fe82acde62fd7a956393e9b43c6c6170d42ee7fb84e727b3b1caebad9c20b86d","nonce":"f981e06430d7d612e96cd9dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"cf0c6198616d370e0c3c5c310d6487ee8e89b06a23fad0274c50fa389e30154ba8b6c8c0d0996bab8a7f3debaf","nonce":"f981e06430d7d612e96cd9de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"712798a037d2dfbac20c8b97b26063efa27be7af964ef154737cf0726b1a2bc9b8f2928d52de5b78c52bb214de","nonce":"f981e06430d7d612e96cd9df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"f00f463316199534e83f6d7b9d0d0e271ce926209df2557964a61a59920ffda7c5bd0e6c7660088f34e845b01d","nonce":"f981e06430d7d612e96cd9e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"e9c2397c3c7f84a42a09f7095bb3c147f1ee6830181ed44f0128b0456bc3382fabbc71596e2daf05d0c108c280","nonce":"f981e06430d7d612e96cd9e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"a1b964e297a03318e36608017f6910075ed1706035db83cbb78295f3bd69916129a2b7fc3bd053f91fb1a52094","nonce":"f981e06430d7d612e96cd9e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"34f8fa9788d63d3ab766face05a9def5d623d47457c41fb463586c777e44dbc35c965480ac3afdaccf17828efe","nonce":"f981e06430d7d612e96cd9e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"5a0b8f11807e0a1769b75a3fc2dd9ae23c5cc71a2370954ddd5cc305a6b6004927430b044ff1337f05c42adb5e","nonce":"f981e06430d7d612e96cd9e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"c4c7f65601bde890ac737516d84005d23992558e1363cf89fd8268c2393a5f36545c499e4f05b8d511d0cdf221","nonce":"f981e06430d7d612e96cd9e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"233cf8d2f429b3d4f56abf658a65c535e20b1df0491e3d25bd77ba44b3a4b637a3d8aff74403bfdd3b9a0dbeff","nonce":"f981e06430d7d612e96cd9e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"0f162ec2d25e55c3be278136a05c315affd087ebd8c0c48ef1504c02d9830595c8ecda15faffe0580ae8b9700b","nonce":"f981e06430d7d612e96cd9e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"798c8a91b13591cbc310c565679170199b2ee5509e396da8b3116d5c0290ed5b7cb69c8712c3489bda3b75a824","nonce":"f981e06430d7d612e96cd9e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"68f467c18511091dbe10a9d58e2ab44a04e430f0cd8767ba85ddb5ea3410043ee86616615dafa3b91d19f73415","nonce":"f981e06430d7d612e96cd9e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"5c4cbd3b3b089e22ec3f56eaa3bb57f1386ea0472dfee64eea4b15de959e8a78002fd14ca2d943bc061eda2087","nonce":"f981e06430d7d612e96cd9ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"7aff86ed1af5adc170b933a3e1301886aca80d52aabfbd947840411d0967196aca1de3cb473dedc6372a68792a","nonce":"f981e06430d7d612e96cd9eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"56e1d890e832b557ff6f4b2b839602f748c05db189fb958fdf44bdc5d7e1a34ea727440b69e10e6b446e87620f","nonce":"f981e06430d7d612e96cd9ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"6059cd3fb1556f898defd4e3bcc590d5d6a6bdafbdaaf1a02f7d271db22036d2a3050d6f169fc954aaaa036d77","nonce":"f981e06430d7d612e96cd9ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"95669ad1645b25fec8e3f957a425d38151e55a8a3ffc1e9ef7744e72d52fcdf7250254a2408c78c20cabfb1466","nonce":"f981e06430d7d612e96cd9ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"6e023870fea318f8476cbfe47f63e9f712c829b5eb3f3695e53db028360becc71cf6e6c7736250966746f751fa","nonce":"f981e06430d7d612e96cd9ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"8aa3d9008811c4f3b5729f781642c98355562f38fd109b81c03cd8e472d580f85db58a292b2b184c30d6f24d11","nonce":"f981e06430d7d612e96cd9f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"2069c763a5abfd3dc334d81bce035c1dd3ec20f2d6d6bd1a0f4cdf0855fe08b45c3e354aa8e035ea0adcc96699","nonce":"f981e06430d7d612e96cd9f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"dfd402683635931bc9734a307b7fbbcd29498655b6205319833cfee9099b3acd0861a2407d4c413d8b3d889d9c","nonce":"f981e06430d7d612e96cd9f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"050f9981f5948c92287279c106632384d7ca010a62375778a7b39377922d9718aceaeda3e03e03b79bafaa2d3d","nonce":"f981e06430d7d612e96cd9f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"1e11d63457a3be0fe1d5d842fc706d70377acc58b001cf6dcb7e205c58c80677fcfaee8345409c8f5f953879a3","nonce":"f981e06430d7d612e96cd9f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"205e79121acd62c24476b5bfad3408ae43ebc78ef55813e95828cf8bd3c952413e4c169147c41c173d94702527","nonce":"f981e06430d7d612e96cd9f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"12c5dce7cbef34c472990b9132a4c52972187ae26d0340d50a4e5e4cf9c0328599f1bd32d6c16862766ab66b9e","nonce":"f981e06430d7d612e96cd9f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"e605f18aeaa7650087642f5c5ed7f0c2d13975d39aad60c77808016f6782605cdd081e6cf7771ab4dd189a0e1e","nonce":"f981e06430d7d612e96cd9f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"701c67408f1af26da51ab103a5e1412fa4d00bc7b4c4594710b71b7fc530fe94b6e1275a40174fb035cd33c80b","nonce":"f981e06430d7d612e96cd9f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"bb0581bef362acfd107982becc8daedb624d470d027004ba2d5388332497086a891d40bf52053034902a0da09b","nonce":"f981e06430d7d612e96cd9f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"c328ac0a3012d8a7a12c5b76cf734f33d3808470564d3cc72bec4b1ef01b405284850c40ce92a25a1f81b71ef0","nonce":"f981e06430d7d612e96cd9fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"9129505f410d756c0a369ef109547cdd8107140c99736e8e802e4d6e28b8bdef0b81222328ee644e335fc24cc9","nonce":"f981e06430d7d612e96cd9fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"cbe5698d1346dc0389d689a22609123a5b45d223900f8607a0449cf14bebcc33b139a8cf9d14956b587e12b673","nonce":"f981e06430d7d612e96cd9fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"40fc7c8210c6a9f9d8419c90a802803632f14bd76a780b0aa19d9ddc4c4b8b17fcbbad2b454975f0b8be57516f","nonce":"f981e06430d7d612e96cd9fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"5de2f72294122409678ce015fd6a1ca8b8a5df7cc0605d18adbc102386e1de676adbf9223df63e0a2f4efd146d","nonce":"f981e06430d7d612e96cd9fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"87015df5bac1803270348e64d1f60588581d629ef8a8e140c7297d4aa00e2729d0b3c72c1936f29c3611c5a0b4","nonce":"f981e06430d7d612e96cd9ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"6aae90b67aae0c7bc169bb3668687d8e9b4acbb3e184a046661e910ee62b59a33c4b0ea70a327f4a9b9f29084c","nonce":"f981e06430d7d612e96cd900","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"ee84783b5a3e4645dd5391312440439a3d5cc1e16114a03ae0f7a6ba16eb46c7bb99280bee6eb09b9f4e53acc1","nonce":"f981e06430d7d612e96cd901","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"72ca67aa0b8b200d281eb4cc16da216b80a226de35e8a2b16cc6538bd244272eaebe20a003d9d40b2537dd4da7","nonce":"f981e06430d7d612e96cd902","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"5853b8f4dbfa2ce2967672bcf3f442d46403d0433e40cc3ece697a0de6bad4230081f0f2f8a52a67153563e205","nonce":"f981e06430d7d612e96cd903","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"c2771e3e780ed14b89adb672af25badacb45d9e955eb2df13a13a8fff6d26633c11d64777b33d419087b099e5d","nonce":"f981e06430d7d612e96cd904","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"98bf3b1fe2353ef617625cc02090d79bcf436aac3d73d20b28aa953b85807373900eaa2e26c4bfabf220aefd04","nonce":"f981e06430d7d612e96cd905","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"7b657de8aba2aa85d3b8411d4945188b4f1da99f07cd8154dc8679d486c5a954deb120d2811bf6242a6571f382","nonce":"f981e06430d7d612e96cd906","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"ede292103cb6661dbc832db7e704468aa5184b88756352c1bddd52510e3f1d6838aa62d7c7b6e5a7bdf3dbc6c9","nonce":"f981e06430d7d612e96cd907","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"248265ff3004eef132fe52225b0847b29ac908fd8de891b5e9f1949e430f057c7dbf12d5bae521529066f20188","nonce":"f981e06430d7d612e96cd908","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"a5ea71b608b9e968d8237b5d913107466f79cb270ddacab00ebd39c3316ce14d1dca7ad15889f49941ff096a6a","nonce":"f981e06430d7d612e96cd909","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"03f68ac0c9283f4154e9bbea553e23f69176ddba5fd2b0b9c92eb0eeddbcc6ad93d7c82c515b2e00bba86489a8","nonce":"f981e06430d7d612e96cd90a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"24c297af64839d2391cc2e320f9dca981e47eab8dc71db390fcd1071d887604e9b1b9b8973f1b70d96ec2c6747","nonce":"f981e06430d7d612e96cd90b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"261ac7c5694235cffc38cc469b8971a6f6da472b70f15c68bf17da6057ef5aeff7c817926f5f67c61edd30bf73","nonce":"f981e06430d7d612e96cd90c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"d28b0d5b9a4d256c842cddd29eddbe3a446547e8ad71d534c34d82feedf756a8d9d1720d6002b965f1da6034de","nonce":"f981e06430d7d612e96cd90d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"bcd41d23e7455786869e943be2f976f7999cb9d82a450f73cc319428a084c49152eadb6054e413190e3df2029b","nonce":"f981e06430d7d612e96cd90e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"d4b43cc86a5e26b3230df3b446d02be6214fa9799bb725557a381e3c09ba3e337177db9bb6436a1da70ea01225","nonce":"f981e06430d7d612e96cd90f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"7ae46d5d712c3555ac8098c4f56edf35e66975b90e4bbd2ac2c85df95c8b6e89a2456a46f737722cda5d136b5a","nonce":"f981e06430d7d612e96cd910","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"cfb6784e6d9e5b45a8caa59420e78bae3765d6fd324712ad234ed2bb07e8ffc8432a1194482ef9b2874d205d94","nonce":"f981e06430d7d612e96cd911","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"37015a5d4fd7cf567a2808347ae9b942cb9b1b3a4aaa13dba5f7329d4264bf9dd2042f3484924a53ffeb8020fb","nonce":"f981e06430d7d612e96cd912","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"34295e0c568545638a137a3ec850125ab750b5cee68020f8ff2c980921c73e17c75e09047a24210ee4bb07fca7","nonce":"f981e06430d7d612e96cd913","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"5ae7761104bc5e6bde3cb11c9fb1398cd2e8a659b32994a9c6540b19a29dd5f2846f61c674a87a6c5258320516","nonce":"f981e06430d7d612e96cd914","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"206f680d6411cf8bfe5d744c4aa5a42a38b46e6c5924f41e302dd39dd8219549a881612bda023cac5f1e5e0707","nonce":"f981e06430d7d612e96cd915","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"5865b5f8364285ac7bff155f82cfc9aa7c4a9ce12f15801f78d14b69859d9744aa91534e124c99d9e75f2ffd2f","nonce":"f981e06430d7d612e96cd916","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"f4544382f2d534b8091b74813e2c710a77b30b50f635826890114621515ce742dc1d8f804915653948582c3c16","nonce":"f981e06430d7d612e96cd917","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"9eca7ea8e1d43631f517dfd389bb3b684a7daa8cd7635897ea91d26251ef95e4a6c41fe365411b34d6c72a949f","nonce":"f981e06430d7d612e96cd918","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"0a30c30bf30d877cfe0f8560d53ea31bb716c22ae2449da3444567c3382eaa74664bf8ea7e65d58192f0291102","nonce":"f981e06430d7d612e96cd919","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"7fee1b2c602a29ce353778b62fb19dbb813a303ee5d8b66ead75f3153f4a6c0ada46fc881665d579fb9aace489","nonce":"f981e06430d7d612e96cd91a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"8f4bd3f69bd4aa99d18fb99bc8806bfac91e39bacf34dc606196803640ae982aa006c0f2a679c271375fe103fb","nonce":"f981e06430d7d612e96cd91b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"37a9c153c4d9c72d644c7fde3232bbc4aba0ad174b20cd0209defd0989bc5b47226c4f7afc83664e8831c30dd4","nonce":"f981e06430d7d612e96cd91c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"82e11987afe71709e042581800def4d4385653f04dafdd0013d0dccfba837aa03e585e1ca64e6dd40ef3d53277","nonce":"f981e06430d7d612e96cd91d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"785448d0e461b2f14f9b9229a1b2380371e09ac4ca9f4ec4f2fefb252b25899b981bbb8fd2339f5d87088c1341","nonce":"f981e06430d7d612e96cd91e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"352f48191d5792c6c2e97b2d4fdc1e7faf2eca0024556a1ce499a5cc836763d9c094e4087cbb79a31394008986","nonce":"f981e06430d7d612e96cd91f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"229ba76a1da0295b2fd2d14eed6afd453f6f315a0a1e2e12c66805ad794683a5cd3686f98934643b9559cc98d5","nonce":"f981e06430d7d612e96cd920","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"1614fda958c10a8ca2b243dfdce922ef595d14689b21fa01d40ad8e4e897de46ef5cd3072f01389b3f61618cd0","nonce":"f981e06430d7d612e96cd921","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"2e313f6229d89140eb85f585b0b899e695c4eb2150fbd43433273460425741642a47bf9743f16aa9cb4795bef5","nonce":"f981e06430d7d612e96cd922","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"663d5efb8ceeff7d6cf57ff1ba1c2b50ccde68233973e1becb4b87fc65d6d63dec172bd4d21e94bcfad0501c15","nonce":"f981e06430d7d612e96cd923","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"36f48c63805203a9e32f0b284b4fa7fd50e607f49563e73f84ef5d4ff812116e5e294997fcb35dd02d628796e4","nonce":"f981e06430d7d612e96cd924","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"ceaa237c548d5db000dbc59679a3e503f7bd31d922244cf0fa8c5e04f03d9223d9d9cefe93f4fba2e71a76dae2","nonce":"f981e06430d7d612e96cd925","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"d331f339bb919210b8cc5cf4c34d245d57f929415a9fcc451e3ca43e44c48d8b09d2c953b137f8a62daf907dc4","nonce":"f981e06430d7d612e96cd926","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"7f8d3919be6a67e3f9f9bf6cf006da26f01ef82280b5dff2cffc5548d21c6f1c2e4c1cb7b9978917a726bfe267","nonce":"f981e06430d7d612e96cd927","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"07030cd085051491f5beaa06efe68b8d072e86483a31c67a60d90279a011b800da2bcef438eb43743829f3e9d7","nonce":"f981e06430d7d612e96cd928","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"184ee9a48970dd911f7b8350f4ac5d69e503d1aa28a525e9be8bd394b9f24677bcc82c71085eee055fc1f951c1","nonce":"f981e06430d7d612e96cd929","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"1e7245f7a3c73e408f87b1c343ce3632aafd4779b66a47c98ff5afe1c0a848a4759faf86dccbc4c6c9f331c499","nonce":"f981e06430d7d612e96cd92a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"f3395355ee7872cd9f64c3d2f8c6e8b356c1c099baabad3e82a5830eca5f098b16b6b9bc67f988153fbe86d18f","nonce":"f981e06430d7d612e96cd92b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"625b8257816fb597ae7b68fe4fb9f69165747f8f9fe84ac001afdc8ff24c5e5e65654f4ee74f9123fdb6fa0c9c","nonce":"f981e06430d7d612e96cd92c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"58dbd69cea57fc2ee2e5bab64ad8f97bebb3aa7cf7fb8d62466b5b9b5020574cc755b9d7222a1c53bb103da5da","nonce":"f981e06430d7d612e96cd92d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"29f07ff7ef54a8fbe032953b6f5ad8eba98e56536f4f2bbd303e72c0e75237c5eafb1c75b82789913b31a8a5d6","nonce":"f981e06430d7d612e96cd92e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"4fa728588d6ab3e1dc291f4bb735674835a941fda4fde08a9d8dfb1e041f3f847c3a50a57f3e5eb1064a5b6e02","nonce":"f981e06430d7d612e96cd92f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"28ebf74d38f1bc22653220e60d375bf2b77ca737ce6f8af99b1f54b6fe347e6888021ac1bdb60e5f554f68e1f5","nonce":"f981e06430d7d612e96cd930","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"039426d2caf8e34ff571f2d3b34ced538c62c48a6bc2ea374ca9a24a1557831bb05fba85a0595f6f0dd5e625cd","nonce":"f981e06430d7d612e96cd931","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"72af3c5e720b4b0b74c718dae458bdf89035881df2e156e57298fe888a6cee9d85f8072681b50b9c788dbb35af","nonce":"f981e06430d7d612e96cd932","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"7a10ff05d34b5eb1ffafd9517fdf87ca138f7391ae49ce434820b6b3ec2c2663080ad0fd13c9cc71830dc6ab29","nonce":"f981e06430d7d612e96cd933","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"88adfad030950602f4c66776e43bb322090ba81fe7ab7928971864ce1b78b55094a1a242ecee03cdf9427dc9f8","nonce":"f981e06430d7d612e96cd934","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"5b296bd91bfb4d0069aec8ce993653e485fb0c98c7d9c591d225bab2e674e47193c95177bdc5cb53fdbea29234","nonce":"f981e06430d7d612e96cd935","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"73952e5a9740c406d9d5cbda473863cc451f522d3dbbcac0cfd91c797efafb42cdd9ed0aad8b0a9e9254affc93","nonce":"f981e06430d7d612e96cd936","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"30ed552a6abf1addeed9878d4578c87f978d04cc0ecf7e78e61cc989d43e0bee6f6f1fc7eb9d675523c6af2470","nonce":"f981e06430d7d612e96cd937","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"429c2ae6065e7bc214c097956ef443c2de003bd40bdf1f0cdb9e09ce282176b8d6917239da237decbd503b728c","nonce":"f981e06430d7d612e96cd938","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"9d4d199e754062263f36df1f4737d6db82544c033b4b108acf29545074cbde60319cfa3c71fdc574d23aad8b5d","nonce":"f981e06430d7d612e96cd939","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"48771616216b5ef7598d867b5c323bc47c145c4b27386d42d1d821eaaa094f7e23ec5549744a9827cedeedaab6","nonce":"f981e06430d7d612e96cd93a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"9d37a9f17b569408ddc77ea1d775bd9508ba6d602104d097af002241fa93ae82dbd02ee51c838c07778de66285","nonce":"f981e06430d7d612e96cd93b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"5d7c2e67cf185815df4b48d05ff58f32b494ebe39e73d2d0f0c0968ca57feb87f51b3544e4138c9deb700f856d","nonce":"f981e06430d7d612e96cd93c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"d732f93956a3093c28afa1de0eb3158e423d786e5146c15c353db79127eb688ce2d424b37d40ccd723facc9422","nonce":"f981e06430d7d612e96cd93d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"621e10d0bbfb0d11745ecd76503fee01bc9a1056ca17539505950356edbd6b34df68a06f4f04282eaf0dca2f4b","nonce":"f981e06430d7d612e96cd93e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"be97aa3f914f408e4f910e7576c4cc893b7e4a22524e19c124435568b4031f098c83b13b8fc058b5ed2a01cfb6","nonce":"f981e06430d7d612e96cd93f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"51a0d98efc0d134aad478e040ca50ff0e0490f050a4402959146b90f83c4c0e028282b6386a0e982eb82b96d9e","nonce":"f981e06430d7d612e96cd940","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"47228955c8cf9dcf76a610a4d87df3f7801ec982c3bc524aa26b622abe20368d4b850939cd8168f9200a13c0d5","nonce":"f981e06430d7d612e96cd941","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"490b501a6578e52b11a736a602135aae8e571848143c6762609538e257f6fc584eb557444d86082d4b5d8a8cf4","nonce":"f981e06430d7d612e96cd942","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"3efd2e4858980aeb2c8ee0f3bd6f8163510bbc39c9e3c011afe8f9780fbee627cf75ea4602b41f9d1ced5535ed","nonce":"f981e06430d7d612e96cd943","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"93ec1482a62c6fb46f5b8df273702db9128b71a18016ae8464895ad578e1ee11ae66ceeb4ac5bf9da706eb485e","nonce":"f981e06430d7d612e96cd944","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"eff6f12bc32731378bfb9219168cb789b840d98b41c11ce67956ddcca0b6318dc6778ff985454db3cc5b4a24e9","nonce":"f981e06430d7d612e96cd945","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"146c7e5b01d40bf9d69f126257a4bae2c1dce7155b9258e2daa885415c22d78fd3ca7c4d3056ce0254db1c15e5","nonce":"f981e06430d7d612e96cd946","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"0e8412b1302fc0962f130dbd2e27a92fa76dd9d2a00d6c4c3f0b9a93158d1b909d1d6d5e8867165f6806ace6be","nonce":"f981e06430d7d612e96cd947","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"2b2812913fc99156692e4eed0411704c39b0a98de2e093a7b856e7a8705cbc13196b29408fa6a63ee89d2a98e2","nonce":"f981e06430d7d612e96cd948","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"6067700e56f9c3ad3ae62e2551aa3758310b85710d763ad3c6dc7fecbb738224ec00a0b1aa73102321994edccc","nonce":"f981e06430d7d612e96cd949","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"ff7869ba098ab103861551672b0f1b86c124f088f7bf04bfe4b04a91bbc2836fd4c39a9731a3523c938c97080f","nonce":"f981e06430d7d612e96cd94a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"184cd577ce5e560dc7020f8951ede28a69ec6802ab4cd817a0db082293b3688512020517ce09303be10815c9fc","nonce":"f981e06430d7d612e96cd94b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"bf204f696779e6d9030a02ca33102d0f8d30c8f28d2ce6ec90629d071076e222ba12fb34e94e4609803beb303a","nonce":"f981e06430d7d612e96cd94c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"ecf0a3f409d51de119625ed4eedd4ccc0da101d91b241c3797dd70be8843a4aef0127e2f66b9d26cef593b7ffd","nonce":"f981e06430d7d612e96cd94d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"462418733180847a2df718f920b57dfa0ec3ede994a6a43b80f92ed2233eb50035fc73cf0372b771e6e70de6a9","nonce":"f981e06430d7d612e96cd94e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"82abdc725ca59da90d02f579cdcb824d367ed5b191edf9235518997c5fda9061bb2668166f7e04cab8018e7a4f","nonce":"f981e06430d7d612e96cd94f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"0ca993576897c5754e88d0fe2eb907ad8f618d3dde4ce8bb9d95638b16154067db18dcf048e33c439aa1076af1","nonce":"f981e06430d7d612e96cd950","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"bf8faebe94ebf4ccd400303a3681d5fe87e6fdaf0cfca6a01dbf72317c00bad58b840764cba5f8cf9c42c3d7a4","nonce":"f981e06430d7d612e96cd951","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"02fbd9c685e611c9315877ea8b9aab20e778df7e7dcca84033632054333fd04161cb0d15e148f7d41c252cdddd","nonce":"f981e06430d7d612e96cd952","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"b1b193c27d08f0fd21e3e7bb8b7ff66e849c206f413f72aa4c0ba3be7672ee2a4f6dcd8b296fe628f1bb8e1306","nonce":"f981e06430d7d612e96cd953","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"30cb7e471701b273c052299c455f0a2db4cc916b293c21440488f3f8ba80f1c2828551b9a95abb44c5ff44a389","nonce":"f981e06430d7d612e96cd954","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"b743b4d724ee6aad2cb2546f5eb8376b76233034a0b98d49a3361fbccb100cc83b2079289cb4d8d7c3696ac3ac","nonce":"f981e06430d7d612e96cd955","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"194bdda15a1c131a2e5d3abf8e72104010927ef227227b817b612bbd621e657e03f06d882e412d18e40e28c002","nonce":"f981e06430d7d612e96cd956","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"b582b95ef52cad420c21bcc6e7906479b4a2dcd05eeab31ab49e8e975141a0e257204c8b3a2883f5494d269395","nonce":"f981e06430d7d612e96cd957","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"2792ae86ad90ce1fa3aea4da40843302d4b2e954bdb7dcd7d6c7177b69b251beb295dd7b09c08dd97525e39ddd","nonce":"f981e06430d7d612e96cd958","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"c6585c9633312a6e8d4e655b323ddb1549245a5f33c2179c81d2806a818abf4d0c16ac48d516bede7a737561a9","nonce":"f981e06430d7d612e96cd959","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"40d12d7e03e7c385b718526f78e7f55a54457bd2b24a653a4572b12c09cc49e8b78687c801c8bbee0af2606805","nonce":"f981e06430d7d612e96cd95a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"a786a8195f5f556e090027c4555c6038208638996409e0a980d2b397ef351316e54589ae66febfd560ca401720","nonce":"f981e06430d7d612e96cd95b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"831d54a11ca5a3e6e03ac59fc9cc82a0bcf0493ec53b0c030f3fde72955503da107d6abd823e66bdaf13decc03","nonce":"f981e06430d7d612e96cd95c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"bfd1182a7a8a85e71de912153ba1efc05cdfefdea8f79ca4bba578f9345bce4d1ac66285faf5c29e6ee2df0efc","nonce":"f981e06430d7d612e96cd95d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"59478f7a3394ebf56a7023a369b50779a4b7475a329492e724e67b5e4509164f570ca15337c10e8f91b5c069d3","nonce":"f981e06430d7d612e96cd95e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"ab3f53386b65fefd697aaa973072ec14bddaaec1d458737096942b958ef382699a56754ff25d6ab612f9ff4a49","nonce":"f981e06430d7d612e96cd95f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"d2bf7ce65f14b008a15f4dff42a431938f4909a6957cc9095c8dee5bb32a1f95160bc421231edb81d7fc4a8c5c","nonce":"f981e06430d7d612e96cd960","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"da79dda73a4caffe139fbd0ba1de100c512b9c5fc239e02fdd2bc13707235916ead562f3630ff95429fe28ca26","nonce":"f981e06430d7d612e96cd961","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"76f1394f1db8f2d012a45c30f0c97b868a73bac85e7ddae6ff95e50f9141f1f08856508bcce5e93948009e196e","nonce":"f981e06430d7d612e96cd962","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"dc73f1ecdef25f8f97f0bdd96abaa20d4305ce5261026f13c36989538be49f3f35145bf160c356134f960f3785","nonce":"f981e06430d7d612e96cd963","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"f22a7df6c799fe97aae44b29d61f8abf2db4d299ac8b748a9e95100e739994bb5d0cb670659d7cdbce527c0f20","nonce":"f981e06430d7d612e96cd964","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"476675b833bfbc6a5929442d0a6cd547a807490bea73b36fbdad19fcac5a2bb0450101b0949568e89a8b973872","nonce":"f981e06430d7d612e96cd965","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"ec8f391732d0b1986abf3e349b30280ef87692948614f23d0a524828cedfbffd371281df5d34fd670de66407c6","nonce":"f981e06430d7d612e96cd966","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"85b10e7a8f7b5e9d875a2c682faccb35c582e4c09483c9bb782483bd5cf2cf6713164d14decb0a677f990adaff","nonce":"f981e06430d7d612e96cd967","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"10b0d47da40cebfb1b4bef35f7bdf061ed3204a55cb585c3b9a824f6392702582e2fcfda9f7e14f936057fe20c","nonce":"f981e06430d7d612e96cd968","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"3a7bff36c223a42866bd79c65cc846481b6547d76c33a8a35fef8505ed6888b72598367b6746d249c8f8104d15","nonce":"f981e06430d7d612e96cd969","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"7e13bfebba3df26294d969da149e15b845c25ef99628d707345a3b40736c9efa16afe849e34f5d0266665ae9cb","nonce":"f981e06430d7d612e96cd96a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"4e5e9e4e99e93dcc5722ff8a42db680fa6db123c83f2f8f0df5d0998d436ecd8bbe68bb80b252c3246fa861068","nonce":"f981e06430d7d612e96cd96b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"0f3cc88f6af6bc07c07458e153bd71215d4f8b3bd938d9943af9d6c54c9ea15a2e16415bd1db68e4536b58c2c5","nonce":"f981e06430d7d612e96cd96c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"ba9048d0d1cee3cdf6a04cfc6a97aa12d8295a3b627aec17adea29c9ba66359d1f1d35e95ea3a51abc8ef4408d","nonce":"f981e06430d7d612e96cd96d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"c118f57433e3ea06d2bd7de92b6c023e82adc223ccd9b6311f6e854bbff94ff92763eafd07b792be85ab17465e","nonce":"f981e06430d7d612e96cd96e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"2c3dfa0ba51b051068ce80617dc660de199d6c0a113d8745ea19b269dbfe762e0784d79d15c7c5d4ac90cea982","nonce":"f981e06430d7d612e96cd96f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"2906f648fb628178319ccb18513ce5ff99f19405e1e11c98490b8706487924bdbf9706bf19075561bb2beb9a16","nonce":"f981e06430d7d612e96cd970","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"92108f9929fe863364f3263e5250531b55380a79f3dce2279f60560a717abe64798a41718cc18f7dac94597a33","nonce":"f981e06430d7d612e96cd971","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"aefe102f65ce7a24eb7027b941bc48b5e8bd77a6fe2ed7c2e99ac4bcb7eb8dc2963ce6f9e323e0e85404af40b4","nonce":"f981e06430d7d612e96cd972","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"0ed9738cd3419fd8d02ce05c49ecf0a2faf5f29de90eb78bbc018667ef71dcd6684b96139415b3070f3249fd69","nonce":"f981e06430d7d612e96cd973","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"f9c513d301a956581cab8a999942e6c21bed9725996e5b59959f04dcfb9a14066b1f574381054ec2512e97aa74","nonce":"f981e06430d7d612e96cd974","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"204a24c6e3c61314578f38a6a65795732555d0fecc6d11812fac1c0a6d339ed44c8f98031a49670eb2e297bd29","nonce":"f981e06430d7d612e96cd975","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"88f1c4e4f3e43de0545c64b698ad9f569b5710dc91be203aa8679a22ffaed3b5160da26b15ad1616fe5e17b730","nonce":"f981e06430d7d612e96cd976","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"2d73c9599c403678493806b33ce48a929a8801aa4ed25f1be49d8185659b5c6d645b4fa693fd5539eb061bb287","nonce":"f981e06430d7d612e96cd977","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"64f9abad23802d7571273e381ae2f74ae27180c1b63d5544311b763216b226c3494ae973087eec55ee5e7b313e","nonce":"f981e06430d7d612e96cd978","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"fb6b94cfd9f6dea5b7b3040b383653e408d4a749192c8f427a8308b136548ae073ef434e712662a07eb969166a","nonce":"f981e06430d7d612e96cd979","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"429151fe3d5501b9874d9082dc8cb89d49ad3ffdfe840166f1d2c562b0765adb229dad70b191c9bfa6a4e79ae6","nonce":"f981e06430d7d612e96cd97a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"1efb9c7946152a4cf024ed7b244f80783071260a4ad2b3ab9bae1fb93b7037bcba0fe2702b8efbe12903834ec3","nonce":"f981e06430d7d612e96cd97b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"2a40be8c6bcd9e42f8a8030d89baed5c55d028e0b7caf2d65d1e30d0f6b35385d6984c2f5c6c2f56b7a11005ce","nonce":"f981e06430d7d612e96cd97c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"b343f0cdb2ec34c966123ff93690921eb9308d93f9f5aa78e3ddb185576c791633930aba8173e157805f0e134f","nonce":"f981e06430d7d612e96cd97d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"3a3a4c0072eefa4efe0675fb5c892ca74d26bfc3691041bd0ddd166e3e27395dd5675046514e7ea9a1e763a5ca","nonce":"f981e06430d7d612e96cd97e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"4e7fdf14276d0be470883b8880032848e09f4e91470d3c0f26cbfd89986a438afd896d0e66d56bb3394f2b24ee","nonce":"f981e06430d7d612e96cd97f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"997edf70d202988f6a31751a142f2dbcf3e4db993f8d8a361ce340257ee75560b312e6da71a2da0cd6881c5a48","nonce":"f981e06430d7d612e96cd880","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"492203215edb6843834f783c452ac69832ef4fa9d05dc3a0c83280fceaf816c3"},{"exporter_context":"00","L":32,"exported_value":"8e93dee974e191512a0ffaae7699dd9ac24baa70b5eda925e9bcec663c71d853"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"5e0a9ec9dc8a59bb9cf28f0030b74882e9d44285efa372eba2f08338d93350eb"}]},{"mode":1,"kem_id":18,"kdf_id":3,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"80aa4a56cdee91bb0af75230a93cc1a7302a751ad37e13f6bea199d340e71dea76873b86a39c048fb04da214e9d8ec601f574f4d23871c9706053806459bf26fb5ee","ikmE":"e232504e4722e55f41f473dcecfba7365cbbb8388f9c7cc4ce70611e41460128939acfedf39171cb659df92c1f56999c3a74a1cc1180e8efc5c8daaa3f9e9950a9fb","skRm":"0121c392c3f58c2d2b9362fe9d2eef518a80ba62741c1d9ed6192dc73889490b274cdb72fcc982fb56d7b27387048f64531eccf4bb32e06d2d6728d87fbc3f93c6c4","skEm":"010d778a0c514c543dc13904d89dc3a2f46b82918e20646db7329af7008756600530f609c7fc70a658435afdd121cad82f3e01d92d84d40b0ad37d2a62e44a726255","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"0401fc77d166ea7fdefcdfc1c620bec6bad0eb4f0d35a20698000ff115efa57b81e97d68f3e3e92c692b63f8a9ef588ed53258c36f382a79776a25b8f8238451286c3e01a2dc0985dec9e6ba2fbfc3a9d98187f8a07965a53ab241b7102858c6b75832acc4eb517fdc5f75273d9983b749e83702566f03ca0a7929c0966234f425c4ee08b8","pkEm":"04019a6762c9fecb5afe4f9d22a1be9016d074cf80cc6737a20320e0a0b1452a77e1f9c84a5e841c3decd07045f0d030ec8e6d56acf190d7256296b03de978c02f0dae01494029ff473d34e119ea24fe672432e754bcf2cc85986745efb6e62cbe40ce4419df107073776574bcd9e9810b5eae5f6f1f2dbb6b248debd1e58326b1c3e98e2e","enc":"04019a6762c9fecb5afe4f9d22a1be9016d074cf80cc6737a20320e0a0b1452a77e1f9c84a5e841c3decd07045f0d030ec8e6d56acf190d7256296b03de978c02f0dae01494029ff473d34e119ea24fe672432e754bcf2cc85986745efb6e62cbe40ce4419df107073776574bcd9e9810b5eae5f6f1f2dbb6b248debd1e58326b1c3e98e2e","shared_secret":"6131f994625d4ec7e0bfc90ef5560521d2903a3b5115db4490eb48e058f67d2bddb929c1aecdeebb6572cf8b478bdd82f38635b1b41895bd1db543bc438624eb","key_schedule_context":"01c6a8e57593eb61a144a1e20bd4b48deda0008bb0207407ab5679de9543b80a1f5db7d872c1f8f0db384d4777aaeda462baab80c5bf406281bd6d73bde8be20ec22f3bb3f4a73881979994c3c83a46628434a24f6fba24b7cb79b65184480612f921684dd1abdb948aaa07637b3944e6ec7bf5089bc9e653f702dec2b8ceb1e0d","secret":"32738a99f233707e1832972b5f277681484547e801f42a20022d4480fc881eef17661fe4c1399bdc8f4ab7de1a94fd9b8aff9c404a335a57cabf4837e76ac58e","key":"50755ae5dd1b8442d8a1774226ffa6e995540997cd608e2153e0db7d6b9df4a6","base_nonce":"5c6891dbb9d12ec4fea6ed72","exporter_secret":"95d0fcc78b16acb30580470c298b111f98c379ae43806cfef7a832a25127e95e11f0f4363d4dd01f0dddbd7dbc193635c89a99da1ccd801da94d8dca7348425c","encryptions":[{"aad":"436f756e742d30","ciphertext":"a995ec1c514097bdc642990b556e8c6e58821264556f0074cf1c9e2b4a34ad5945b90db01222714b6e9db6ce6c","nonce":"5c6891dbb9d12ec4fea6ed72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"a901c32ca36829ff69038d32aff79e05e9014be206d2e01fb243d5dbb520384b7c12485c14a3de329980790bf1","nonce":"5c6891dbb9d12ec4fea6ed73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"d55d5ce3807d4230ef05b4df059172690967f7ce2cb71327a455448a76039dcadeaa701b39cf47f1da2dc16c14","nonce":"5c6891dbb9d12ec4fea6ed70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"085a191559817531f219b0dc308fe536398acf37593741c738e459d4ff2b6610c0a88edead6d331ff975522348","nonce":"5c6891dbb9d12ec4fea6ed71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"eea9ba3f5d11b2fea118dbaece213bc3c268cf20a11a91eef9392bd48976f2fe81c4f39718879faca5c5f39557","nonce":"5c6891dbb9d12ec4fea6ed76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"6ec25d514d930317bb78b477e5111cd3b6a0c6293810b5f9e17be49ab88accc6557001c5720e5c155c2d21a5d4","nonce":"5c6891dbb9d12ec4fea6ed77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"79e73e50fb69002cca0fb2df34a178916bfced0cca04fe4a8bf1743d4a6312229703829045720b37a3c15362b9","nonce":"5c6891dbb9d12ec4fea6ed74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"727764c3e18d3eb4f4791ee8cb3df1a80b80ebebf7b46d5af9f8e8854945dde4cf2a81dbc89e04a79389709838","nonce":"5c6891dbb9d12ec4fea6ed75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"723a532fb303dafc309283cb25de736d0479f90ad10e769bbe1f3ee91ed30eb4dcee5276d7adaf9a77166721da","nonce":"5c6891dbb9d12ec4fea6ed7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"aae9f2717bea3b5995e8696f084249b1a9cbd61a300821381373b0882f5144512c5eaf16dfa0a0347aac3c0fdc","nonce":"5c6891dbb9d12ec4fea6ed7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"758f92e598fe1635dec1eb3aae7c145ab9872b0820961360072e7f1cd13d251345ebc5ff639e2ea08f60bcbb20","nonce":"5c6891dbb9d12ec4fea6ed78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"64ada7c5f047dc74dd74eeb570c828d0e516253631c46900925402d78d07a8a657761e4707aa8b5ccb045cfd18","nonce":"5c6891dbb9d12ec4fea6ed79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"02783333acf2432009cf8fa9d2858c606383324f4a20d0493495564cfa7cc53d645fa0f9504ae2a54e03f58113","nonce":"5c6891dbb9d12ec4fea6ed7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"6dd23ce79e7c5d5e08249138e495e3c68e2d8afdb2dda043c72a47f1802d3352b8e26a48683efa810d70660d78","nonce":"5c6891dbb9d12ec4fea6ed7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"4df4ee8a54221884e55dc4af6bcfaf3f06d5ce484e9eff976709d58b63cbb87ff2eb98b046a7919adb62becb44","nonce":"5c6891dbb9d12ec4fea6ed7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"938b8f35ba217f2c595506dcda4a4f059a5486323c3aa76a471d85c816858aa6c07daeb46dc4edc42e402be4aa","nonce":"5c6891dbb9d12ec4fea6ed7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"3ddaaecf6daca2c812c13cf1fbf89214d63a17c92762d8a4fd70d8d8189ae1df60b0dd3a8939d11870ac10b868","nonce":"5c6891dbb9d12ec4fea6ed62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"da3980d225716e892675bedc84c9c4bb005abc8992496a28135192e1121b6324b50ab2d7c7f0ef128f0003dd12","nonce":"5c6891dbb9d12ec4fea6ed63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"f59712cae29e7a60eb5db95d15d3049d9aa81397b0fb369ccea2991359054a37795fe5e03e79e3d1fbb34349bf","nonce":"5c6891dbb9d12ec4fea6ed60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"32f5442568026df6593a42525be75be4ac69e48a6bb561596540ac29b29e7292776804b20a896a94285491cd94","nonce":"5c6891dbb9d12ec4fea6ed61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"065f7b4637b3130515cb944354d8206ad2385cafe6f8607405534567b5fc5cc9684ae725800ec3f091ab0ccf06","nonce":"5c6891dbb9d12ec4fea6ed66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"a67efb6e572bfd3c5f064796d7b47bfdd11f90ece2b4842752f4f53fe7c77eef6d2dbf9b42bcf6bc7c23e20a74","nonce":"5c6891dbb9d12ec4fea6ed67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"c27191c5eba9451314ed466a570a4bea61eb0af1e07044a8a868802563bcb2758469cce505de7d39f3d7ba7565","nonce":"5c6891dbb9d12ec4fea6ed64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"455abe6004a770d65beb56be597ef4dd95879822c501870ae8cac76ff064081fd32b3be0f5d1a43b87f1af8561","nonce":"5c6891dbb9d12ec4fea6ed65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"40264f43a9afc3d18adefe67c08d35cad967387069d1132c9f77ccd5d1b38a80c0a0ccf77894865261ec2694c7","nonce":"5c6891dbb9d12ec4fea6ed6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"27567021d35daf074252b6d9cb83beb75fa2d11a732cb74154a2970fc3d509f6389197fe7baec3d1676130c2e2","nonce":"5c6891dbb9d12ec4fea6ed6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"2337b2faf6093cffd1b38914783a9081b1496d1044f808e8e03c0233cc1b6142c942599920a86ba3d08aced6cf","nonce":"5c6891dbb9d12ec4fea6ed68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"40458a180d0977559c79454a894342d66ddfde2b952c9c2fae85906125011078f7fe88e7741daab49285d17c9a","nonce":"5c6891dbb9d12ec4fea6ed69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"04d5dad65560f5d5e637a8f77c4e038c7c7bde052b414c4ab1ee949a629f771b0b98890763a8641c46b375a8fb","nonce":"5c6891dbb9d12ec4fea6ed6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"52873be931f3cdf4c2e1ac2e0a68cc183bd3a94200a7b85a5da10b17ca413400f7b312f2c20c4d08b73d4e6bbd","nonce":"5c6891dbb9d12ec4fea6ed6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"a9ced2163fa53f162fe3afa42576f74fa5022eb92dd8d503a489b55f11070de185559fa739dabc0c7e7a68d0b3","nonce":"5c6891dbb9d12ec4fea6ed6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"febfb84263155d54cf9e27f65b7f340bcaf45eca8fefd1d5ac32ceaa9cac82020a13b9f16b95be157afd07276b","nonce":"5c6891dbb9d12ec4fea6ed6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"81597155520e8459b9ef8142cd54a8b4ddf6527e4b1a63f59baa45257fe9fa2301728635b1729db42da1a6bab8","nonce":"5c6891dbb9d12ec4fea6ed52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"2544ee8b71aba2ade4ee807c9fdc3cf48f9c1540e18f12a2cf46ecef2d6fdb9cf24fc2afa1f239152d10667773","nonce":"5c6891dbb9d12ec4fea6ed53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"762aa00a45138d974b509cc85ecd2d7a8d114f5770cff18740a55a85914ba01ee115f8e926e8f484374ded4065","nonce":"5c6891dbb9d12ec4fea6ed50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"e49fbb7b4793826915f8a96eb5598e754187ce56ad17f7c4f8fed8ce5ee75ba2eb58506db61b6b21703b5acd44","nonce":"5c6891dbb9d12ec4fea6ed51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"a6862d45740d758b383d1cdcba8f1993ca558bb592b57fccadc9b7593990698b7fe836b95da57fe5df4aa696f9","nonce":"5c6891dbb9d12ec4fea6ed56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"3f9ba7a94a7db6a1646546526982dd3a60bd4e3a11a8a9923218eb654e1efd2c593554527f3e5dfd0d7af528a9","nonce":"5c6891dbb9d12ec4fea6ed57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"6f4b089a87e59938541c21c7eac3c866f0db3889b50a811e9d1a95fed56145e4ed8baff1e3f2232671f7396fb3","nonce":"5c6891dbb9d12ec4fea6ed54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"9810a6a84e9ec8dbbf627fe2813ba200c97d1e33433282730916b3a2bf518a62dc81c9cc19d786d44431e15f1a","nonce":"5c6891dbb9d12ec4fea6ed55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"fe06bbd2ac974ef3a93ecd1a6b9cd71084762b07c8287c5f67885875ced2c5f6cd57b7eb4f4f85fe7457e5b085","nonce":"5c6891dbb9d12ec4fea6ed5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"06419656c8f90f73bd119365e86c3b71f6149e13c0b15428213593ca69c609884cd545afa3cc1cadb9aef39300","nonce":"5c6891dbb9d12ec4fea6ed5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"8ea8c8e2ec0b6e7bc17ac6a8927d5ff28d35f9a421beeb5569e27764c9dbb94dc741630c8e7c812d8a11102d28","nonce":"5c6891dbb9d12ec4fea6ed58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"3e610925a6e7a37d536a9f7020cd4a591e64dcebc93b28dcee6d1746441678083ea407ffdde4c62e66e792fb48","nonce":"5c6891dbb9d12ec4fea6ed59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"1da7dd73d30c1fb009f44dca808432d271a29908a93a5f264c55f5190b13323d9140bedcc2c81ca86c384568cf","nonce":"5c6891dbb9d12ec4fea6ed5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"db89aa1d8c09bb3ee76fdf1da0fce5936cdd2137063bae50b79f38939c386a8ee2800c0965d5420156a4f733c7","nonce":"5c6891dbb9d12ec4fea6ed5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"3b1c28729c94f0b33c3f60724fdf2ad722ef1017e536b8f24c29c1bd3d29d305e6c9907fce2bf0625b2d0a3533","nonce":"5c6891dbb9d12ec4fea6ed5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"b6ae6ad2682116498dc6bb2444f6f343484e24555964b33f0710d2481c9af68f0efac33815dcfb50d66dd7b59f","nonce":"5c6891dbb9d12ec4fea6ed5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"e0a75103a73f2fcefc48d0d00a9f8abc3794496efdd3f84a114448fb318a4832884477bacd1ca33337b05823e4","nonce":"5c6891dbb9d12ec4fea6ed42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"5e0dbd0b8ddda825c3935f57c6e3e022a7f2f7db1250726c9e4cc25e80f7501e24885db18d3ba32d6b773a5eb8","nonce":"5c6891dbb9d12ec4fea6ed43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"a13e321ab4ce9fec70e65b053e66af73d6ea5f8c1232a0ee052f1533e9f4c04b4462f432f4b71eebb954bc024e","nonce":"5c6891dbb9d12ec4fea6ed40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"329857bb87062a4d5bf64aeceac412a92a26913728bff868a01ee4c218ca8c2d736bb247a1f58da9250cba778d","nonce":"5c6891dbb9d12ec4fea6ed41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"461ed98f5aa6d4e1cfc4e67bbe7ab042b5b50700f4c9a0270c3bd928fd713e4b40f005543524f82f093b1808e0","nonce":"5c6891dbb9d12ec4fea6ed46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"d208aa3c8ac9e823186f94cfde6ba84b4fd6486984086513df5f542696abeb6bf4051070a335c032fe24dc3a63","nonce":"5c6891dbb9d12ec4fea6ed47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"24f7f394e38bb066d16cd570d1d8dd11ba666cd1718d87bd2236f657608935ffbc4fdded486c944eb32836525b","nonce":"5c6891dbb9d12ec4fea6ed44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"525b0fa159450c0d6b5f2d45b9f512522c139a4f56eb217d655f40961d51d227c4d423c2bc8bef3eddf9364e61","nonce":"5c6891dbb9d12ec4fea6ed45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"4640c2b4c4ee0ca72ec3520bb3b00dd25e53ee9d960530f7b55fa1ebc747de35c3b2663f42365432a9db0b2752","nonce":"5c6891dbb9d12ec4fea6ed4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"8ee008fdea421a415af840d29087b41544f1938db610dff0fafa7a7474a057b9006f3a18058080b07f268bd7fe","nonce":"5c6891dbb9d12ec4fea6ed4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"e27edf605012dac6fa936ddbe9651b26d15ebc396ca5685496dbee725a02b31aab34cc11d036224e6631914888","nonce":"5c6891dbb9d12ec4fea6ed48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"d6913ea6162536ec52e9cb21b41a4481b26ac3057682593b1d888a160e81a23296f955eb18785f465344682c15","nonce":"5c6891dbb9d12ec4fea6ed49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"18151990d28dd2d3cfea4ee92b0196fb68e1cff1f9b84da6843d30b77160ce184fd8da88bd448cdb95ef9325af","nonce":"5c6891dbb9d12ec4fea6ed4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"a7ccd61bb44fc370be74d09232f5750bfc9632b9f24d19f8250a72a61d0174869f0918e766924693b3815ad62d","nonce":"5c6891dbb9d12ec4fea6ed4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"e3a6101b58d8339528981fc1871fe4a4be48e6370b6fc926868711160f5f612d3b5b99bb8bab432a55fa9ee76c","nonce":"5c6891dbb9d12ec4fea6ed4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"a82de8c33535512087920d9d98af423cc4beb7ca86d18c3713254b5d202bfee9a3469eb3d8422bc8c725b6fc5a","nonce":"5c6891dbb9d12ec4fea6ed4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"4e003392affe7a9613c2581a480402905770b1b92ae2c0ff807f6b002cfb8733c3baaf815af90f262e1dad5f9e","nonce":"5c6891dbb9d12ec4fea6ed32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"b3c44780d864db1fd58c327aa08cdbdeb33386c2faf68cd0b02b85b3722223ab66ef0bdff9a778e9cd81e3ff51","nonce":"5c6891dbb9d12ec4fea6ed33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"dd78e8920199c36712fc962e3eb2e72c865a3415bb50a4c76f13ddbb0ed75146f6668f085d4489f71db2e10d02","nonce":"5c6891dbb9d12ec4fea6ed30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"d4c497479a3ee47577fd47b38a3ac46f21b0ca8a4bc2c612173a34e26925e004010d39f4e5576502badf946e07","nonce":"5c6891dbb9d12ec4fea6ed31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"fb11af161509c8d24fcc072f2b7ecf5f135bcc6145c0a26940526eb91dee4d813e1e86488e4c9da3eeeed7a691","nonce":"5c6891dbb9d12ec4fea6ed36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"16a0f1677931f97e6dacce3a50fd3481ac67cf4651b889a4d10b452fde822381fa777f20d65d2dce4ad21e496e","nonce":"5c6891dbb9d12ec4fea6ed37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"e3de7c58f8a91db676d4b066fe44b6b77a18c360aa5b47f265df799bd2a30a2a9e6c687ec936f228c8b774d993","nonce":"5c6891dbb9d12ec4fea6ed34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"3536cb4651b80a3d12519fb449768111c4732202117b9f0e20973e6950d9215d259ab0872458d38cdfc8608691","nonce":"5c6891dbb9d12ec4fea6ed35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"cf2de79b18c6bb96d0c380a88756f1cd068f0ca605553cf1f09de83d66e96bf3aeb1c1f96549c7096cf5af9cb0","nonce":"5c6891dbb9d12ec4fea6ed3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"890d304c6049bb5110adc43a6264cc0f24d0dbf0417b6660ca10faf0ecd70fc62603e704ebf0bd32bef910d284","nonce":"5c6891dbb9d12ec4fea6ed3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"398a49701c795ea36525280339fa1039685a7efc5c51f23cea3a71c1a8cffdeab148ed83e2234a68c39ec47177","nonce":"5c6891dbb9d12ec4fea6ed38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"9dd71d3c99edaa99d7b7aabf98d8f639b4789689e0392fb8a012112c72065c623af0681afcd18a2422dd0218d4","nonce":"5c6891dbb9d12ec4fea6ed39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"593556345a40ace3362b5848fd4b728489abf2bfe2a9a8cc3d9e95be76f60ea1bd434ea4aec17b6c65f2778e5e","nonce":"5c6891dbb9d12ec4fea6ed3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"e6a91d43a0f9a3c418dd7abae05216a03c1f8216e2d4f7e0c1255a443abae1ea0ebf71bf5b462756895ee98081","nonce":"5c6891dbb9d12ec4fea6ed3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"fc534028724663e6028f5f6d1c35fc7bbd903c5adff957c53ab34775138c660515616733f0cbb712d391bf9ba0","nonce":"5c6891dbb9d12ec4fea6ed3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"e16895c245341b5755728678d56e9d7a40f2cbf49387cb7ffc371257c75e7e7853940e74932f65ed785d152872","nonce":"5c6891dbb9d12ec4fea6ed3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"258b6fa6c889f644038ddd7e214e4c317dbed80492e00e6f846a9294d51e9d2b208ba5e8923d14b668d0d98171","nonce":"5c6891dbb9d12ec4fea6ed22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"2ef617f73087e5f62a1996b4a70fb2a9acf5e7f74d27ae25aee4b28b49e609cddb89bd8aadfa4e6b0794a48c17","nonce":"5c6891dbb9d12ec4fea6ed23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"94a54532b0366c1e689b11b63bd28c8468c8a7dac4d771003435fc55faa67512c9eccb6b4c74cd34aa96d2e8c4","nonce":"5c6891dbb9d12ec4fea6ed20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"b8eb20f0b3e406208fa0b6aba5acc2a322d8590486f3ab19d84a23bc57e4521dcf5ef988600690c60be79e4663","nonce":"5c6891dbb9d12ec4fea6ed21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"930b1fa2114cad9ad41dcf3b1e079fcb19808cb1fe89e2db2dd8e3b57f0152f734fdaccce81e4668a1774fc602","nonce":"5c6891dbb9d12ec4fea6ed26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"cf55d68f1bf1c0e71799374faa2bb060ff8a3d79462f86ae425e76365d9251f199c7cdcf68d4a70e4c17dfc6a0","nonce":"5c6891dbb9d12ec4fea6ed27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"c1c1269ba3d59af5882cdfb0e55daf81d2bf27c85c89076f20c8fa132194529cb2d5c14bfd2ddda0aeec405e0f","nonce":"5c6891dbb9d12ec4fea6ed24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"a2fc7070b326727edb06d9518ddb6826f626f0499561c33f4394dfb457416fb4ba7b319f0dd6082cb111f0343b","nonce":"5c6891dbb9d12ec4fea6ed25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"3f75ad9b6368873670d9b0f98199254728c5a057f475f5af3a8d75c1f11915aca7267f624e4c7406896ec12491","nonce":"5c6891dbb9d12ec4fea6ed2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"308b60fad024a59e3e5e2aad266f64016f2462efe6a3ed9626899c505740fa72e29e6006b72f9686ccc850bd7c","nonce":"5c6891dbb9d12ec4fea6ed2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"b8461b22a5fd9baf4554798a6d058ebd19557e0bbed818e576f5f3a9d85a1aca38ca7308fe37068d8e373d7f69","nonce":"5c6891dbb9d12ec4fea6ed28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"b39640c80d6403451a3a563092c70c809ce55b5dc97f67181ee44630962bd8fed767695851ab34570f52898c26","nonce":"5c6891dbb9d12ec4fea6ed29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"af9c72f42d4e7ba4c5c7dbd0d314ebf5d430ae4bd52bd7936d7acd0647c08b56c8fb8f068ef9cd18b02a0dd366","nonce":"5c6891dbb9d12ec4fea6ed2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"4954e3ecb03bc297a919a83bf68df93d1d2fe3e060dcc1a1ec094644f01c1e290f08c7aa53b0580378d5004cd0","nonce":"5c6891dbb9d12ec4fea6ed2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"8f2df097d14e66f533f74dcdb6aa13534814d6c17cbde8779d69c4fea84ede1be07863baf1e0bc96ef47c633ec","nonce":"5c6891dbb9d12ec4fea6ed2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"48b00fd14f8fc8d5d0a5760226197245383691adc041bd11e2832cc294f799a8a8842beff7bd4c32eb6daf64b8","nonce":"5c6891dbb9d12ec4fea6ed2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"32deb631652e084f037954a6f05a0506bf51e2546302a981b57b97a9948c0b3f16d92886d2ed793164a04a2c9b","nonce":"5c6891dbb9d12ec4fea6ed12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"d69e90a9a9f21daf5d6055874ac9392dd9a6b0e0acc92d5c2f1e2f20ba90553001f17e3aa77a425a3de78099f2","nonce":"5c6891dbb9d12ec4fea6ed13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"7a72c665bfa31e955bbeb1d2229485efd49c09bbcf6bb1f9644259331fc2a292371da9cb438ff361f732af3ed5","nonce":"5c6891dbb9d12ec4fea6ed10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"7838a7bc9884c2966dab535477992f18fbf802f7fb534d2298de241dd8d7aa0fa50105eb1ad76fa9859aad26da","nonce":"5c6891dbb9d12ec4fea6ed11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"0fd49efef0fd37029a08c0502f142d0b30df312a25117dd5df8a95ab37aaad00804c92401d7a68551883caaad1","nonce":"5c6891dbb9d12ec4fea6ed16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"0b85073170eb0174512b6357a4e2b77df803b422836c813187435f821e8c138f996cdc23e306e69d0029d2cb60","nonce":"5c6891dbb9d12ec4fea6ed17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"cf2d1c36d7fcb0d9110c3adb20764f2a1368227f1b2a679f2fe66dd558207b0d099d0ba37326804d80b5d2fdf7","nonce":"5c6891dbb9d12ec4fea6ed14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"b11470e2f96ca91017a5316cb214a128b84637dcfea4fcd3aa11335d29533129798d9713e4f236c52633e51f84","nonce":"5c6891dbb9d12ec4fea6ed15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"608e10d16f55ea0a45f53e805fb01300bb670b69e7cfa38ff50361f54831fb93d9af53e5de27c8a40b9263ae1f","nonce":"5c6891dbb9d12ec4fea6ed1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"b1b9b1f6071927adeae29d70911e715fac110f3dcdbeabb6438a2736ff76dce48b4cc1865211293238b7fac1b0","nonce":"5c6891dbb9d12ec4fea6ed1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"631b039601b39e60b803233348d7658b9ee10b388781a9ad0002eed96414bd89149fad1fa366208f803a63cbed","nonce":"5c6891dbb9d12ec4fea6ed18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"9b136a67f449e8a51f022f43b4ce11b198e03da473e09043b795fae410aa0e2f884d671ba261a4d35a0151d30c","nonce":"5c6891dbb9d12ec4fea6ed19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"f1db754de135a8e945d22d788bb1162bec164879ebd54fab810fdc67a716b8352c13c2514a163db05a2e264eaa","nonce":"5c6891dbb9d12ec4fea6ed1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"0e4a8dc7612239cd55fa707914a7eb318a3d54cb241b1e71a9774fd9f405b52b5d5df2f2f4f3d187803329654d","nonce":"5c6891dbb9d12ec4fea6ed1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"37441e465768b900e2bd6ffaf5b57e0425a36d96aadae1f853d445edc23407dc082c0a935d52a427544bf2d26a","nonce":"5c6891dbb9d12ec4fea6ed1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"cb3768a0d5b1ab39c8c6441e10427a21066e384feb8923fdf0a752b16512e79f1d813cbfad22db1b25b1253bc3","nonce":"5c6891dbb9d12ec4fea6ed1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"896625a40c90e37f21583bf9857046275de966548bca61fc008e0435903df556091fbd9eb1bea784cac3212ae1","nonce":"5c6891dbb9d12ec4fea6ed02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"72bcdcaa4c599f683a283dc0d26bc1cc09611b28c99e571dc89b99e464eac53bea43871e379c38987742e8913b","nonce":"5c6891dbb9d12ec4fea6ed03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"b17946f5f96730f092037cdbd8a84c159c5cee282395062ebedd933532e0fa8b3832e91b8ddbfac8de286e446c","nonce":"5c6891dbb9d12ec4fea6ed00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"411c056151c1f23163efb41d3c587b19feda1203176387c384525d89d1558a4b79b8cbb8619458373b4e0f2fee","nonce":"5c6891dbb9d12ec4fea6ed01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"c1416433c97c31692fe55119aef544e30baa37bf3b7ebc4a21ee4aab333e23bc2ea1e0d6e3c18fba05751a3534","nonce":"5c6891dbb9d12ec4fea6ed06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"dd56cb42a4a5795b8c9ad5f0a98820886cf77617840ebf0522240701a55ccf21026bda48864fdf45cc90280779","nonce":"5c6891dbb9d12ec4fea6ed07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"825976d42cbc2bc4a4afc4973dd7064196e35c6c8931d1280b0e3e768fd5e6551f4668e2313e1632d61ccb8a2b","nonce":"5c6891dbb9d12ec4fea6ed04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"9b15660d93abc745633603ef4d57ff6573364b575ea6491c30bc2ff474b0a0d67dfbaa372a14576ee63f157574","nonce":"5c6891dbb9d12ec4fea6ed05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"3426ced68beb6f9590ab9d59b1564374123675b0927fb8153f910686157b4df18805d61c2a36e6d5b2e76147e1","nonce":"5c6891dbb9d12ec4fea6ed0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"fc10be558e7d451d6fdf68bb505a2a8d2d8f09155101c76ab37f7a27d1e5fd585aeb86dac7eb347e21ccc4b8f5","nonce":"5c6891dbb9d12ec4fea6ed0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"80d0d4543f2a896a81a6348136663c994754721bd20e5bae2cfccb7164eef8b5af3b09508d1e5bb6b3fd625356","nonce":"5c6891dbb9d12ec4fea6ed08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"73169d6a19e2a262d455c291b1f471fa0bb117c60712800add842463c88b322a0f4b2e0e705b8630cc6ca473fb","nonce":"5c6891dbb9d12ec4fea6ed09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"705f42912d28793b18c68c498702317a170287dfeae7a9ae7c96115ee300664905845c46c48666fe7dfb30f2d6","nonce":"5c6891dbb9d12ec4fea6ed0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"ed4507368fde63527b25cf4db12f1418ffcb9f1f910d7dbd2b28c3ba97388b2b42f8f43eebc2c565b706f04596","nonce":"5c6891dbb9d12ec4fea6ed0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"9c2565984f9ad2b290dd6a49a1fe4de20f98485b17e98794679b1d328af19c6982295e486adb1a31a1299a3ebc","nonce":"5c6891dbb9d12ec4fea6ed0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"c5ea3b9ea5de50d168577bcc0b2eeec5842e31080b8a5be0ca739248575288c7d72e4b6ad3d98ee476fba001d3","nonce":"5c6891dbb9d12ec4fea6ed0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"b8353d0965b139efbd15e408972c42a253da29e88d971313da8e253062ebfa997fb1391b1287e50a6e4f9eeacd","nonce":"5c6891dbb9d12ec4fea6edf2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"5097d4d813e20f4528e63a5df268c4084b361ad618faa6a0deab26ad0315b9b933b92a1b6f73b2f6bb16897041","nonce":"5c6891dbb9d12ec4fea6edf3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"a8f10bea6a6da832ba84914e554bb25c2205c0ab0a92f4411d40b025ea4a0507a8f8f6e15e75e205b89f581fac","nonce":"5c6891dbb9d12ec4fea6edf0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"a78eea009ac8376ba3d32dc708bbdb9cfdc9efa6329ceb67cbafafad8faeaeb2652ac227d350fff60587e6029b","nonce":"5c6891dbb9d12ec4fea6edf1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"35b7dc726a39faeccc1ead8a5d3fc440a5b1e5cb1bdf98718f83c8648a270bd0259b734d594118624acce05af0","nonce":"5c6891dbb9d12ec4fea6edf6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"4876f84e36be810cb897342412f0d97af2c38bf443c159c1c6d448673a0797abf340e2fbbe9efddfbe55074fb0","nonce":"5c6891dbb9d12ec4fea6edf7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"8a794198fd433e9d87db6ab642b5b6e75f867774aec522a2cb0e97e4cdade5e05a7173168fddb2ad78d7d61562","nonce":"5c6891dbb9d12ec4fea6edf4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"4ceeb0011c5d7a7d08b4e0ed6a390a2f9efd89b142e69e524e0ada2fda11e9cf0cffa3004f3fb86586d3f07605","nonce":"5c6891dbb9d12ec4fea6edf5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"df81684c8869138d19b8f79f3ba87cc20d0b79fd89761c9aee8829383249c2bc10fced7184dc0ed0d905c6b87f","nonce":"5c6891dbb9d12ec4fea6edfa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"f9bd68d346e8f5707e204d6f8c9ac538e06b20c0f7925ac2aca978ae1e3d22fb0bbea5cacdf07b8bbc4707b43b","nonce":"5c6891dbb9d12ec4fea6edfb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"14c2ef1eb0a08bcc18ad1421240c7d89d2676f6a1b2b3f535990a40b6441d0f74ce9fba3ef5aa8609c9e4ec2ee","nonce":"5c6891dbb9d12ec4fea6edf8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"6d767996c772263d59213979364f4faabfb3e443b39c12837082d2e86b1309dc86839a060cfe59720bad6c2ac5","nonce":"5c6891dbb9d12ec4fea6edf9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"24b9eaa1f115e22b1e3c32730f8cc56cd74257550f7275583b15e7ab5ace7f0f59697f4dfa414031f62f061f4c","nonce":"5c6891dbb9d12ec4fea6edfe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"067c6d7dd71011dbcbc677ea95d525aad5922c9d1fa547c37dc4c4348f71c554c4b1e83dd1f68acc6fc60b4654","nonce":"5c6891dbb9d12ec4fea6edff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"9ef79502c1f6cd3046084c0929c8af9750ffe2d32191ed2efe3da045af20f95be97003235aceb6069f4472d592","nonce":"5c6891dbb9d12ec4fea6edfc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"0c64d52028f40c7ac2bd262b41305ebb69da08c3bf357020aff304bf8475ad6be7ad877a7ee8dc14728d396cee","nonce":"5c6891dbb9d12ec4fea6edfd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"30257c59679b3b9e363d58cadfb8a42911e104e79f469a5e88475e71859b919412f1dd0126b239beb4dfdbaf8c","nonce":"5c6891dbb9d12ec4fea6ede2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"f58db7ee7774781e1f2681a420acdb2eeedab436206dab6864280047a27cb6ad2ddd34e6337d7916b499c9ad04","nonce":"5c6891dbb9d12ec4fea6ede3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"c881f2375e03458a89fc422704cd746774667862d25aa2f51414f8588ecd36ac46ca3a2ce625e96805545ecdbd","nonce":"5c6891dbb9d12ec4fea6ede0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"2e4ae33b0db237d5acb29c1425767a21ef731c5db211726bb7e796a81814aba2fc5cfd00cd092ccd8ae749e901","nonce":"5c6891dbb9d12ec4fea6ede1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"9b22c7b4486f952ae202ea935edfaa6d44f30a1b7f1539173cc54333bfebf7ec73b3bc322c972a6dd16165eeae","nonce":"5c6891dbb9d12ec4fea6ede6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"01aa08912fca920a5807cda6d1cd04e4f44397df949cc50d9e95d38c90408cb59289f88830e4e955d00e5d7904","nonce":"5c6891dbb9d12ec4fea6ede7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"5eba32661f9e0e7c8a0925883a52118526270102c00427d1ad4fe5de67305a77e9cf17fbc7a18768c2d55dd8a2","nonce":"5c6891dbb9d12ec4fea6ede4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"71fdeed739a8c4a899d9085c90d8d57f670c9d7161053f9d9fa9cae6215552f59e01eabd2f949446ff6c110541","nonce":"5c6891dbb9d12ec4fea6ede5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"f521a722da850ca24ddcd2201ade38e08375c8384c4c341a2a1c0003e2fd1ffdfd49b99cf35dd7c841663e0965","nonce":"5c6891dbb9d12ec4fea6edea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"11655861578bc674fd7ff2bb4d45044d7471ec7c090a68cf57b9f27b87a3ace50b179af5becc3c9d756d839855","nonce":"5c6891dbb9d12ec4fea6edeb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"26cc11a73a205d9d8db99372b93c9aea541a1dd962227e7936ce653928338ab97d2a73e1a0e9fb4846aaa156dc","nonce":"5c6891dbb9d12ec4fea6ede8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"72b8b05841845d37077442a44261cfc35a7ababb97289b308ed877b1d41103186b1556b135932383b9cb689624","nonce":"5c6891dbb9d12ec4fea6ede9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"b5b58a5fed6896e80dda01dc962de4ce930bde0dce1a61c1558aa55a9dc7a1fda01796f2fd5fcee83c0f6f3452","nonce":"5c6891dbb9d12ec4fea6edee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"ca951a77b927e2936e6a0d52c5514d9e199630b9cdb971896dcfa1cdf8bbf99b17a6eb8e43b0e8d8102c019b31","nonce":"5c6891dbb9d12ec4fea6edef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"72ab0a951ed04220f9fc038f30fff62a03e56c3b7f3687e401f94616a977a3aad3a10a1e984de6225575a67023","nonce":"5c6891dbb9d12ec4fea6edec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"c3641c081f477872f806aff3a80e82126494a3c5088279113ec2aaf6936689e6ed6ef13368b6bf0b1a876c1446","nonce":"5c6891dbb9d12ec4fea6eded","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"d2a297777a0300ccb5ffa44358da2123df847b82ce542f8221654c03c428393b769e972bddb7d7bd08d12f4201","nonce":"5c6891dbb9d12ec4fea6edd2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"89691370042217af68ba7e5a809c00e67695912e08fa328fb93f76852b90872d7b0837a2dc6f59ffc9a082fd9c","nonce":"5c6891dbb9d12ec4fea6edd3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"e0033030e30947152041adbb0e76334381d31e4542d98bce1e36d649c8e81555bff2f8438724284375b8917c41","nonce":"5c6891dbb9d12ec4fea6edd0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"9844f3fb301f6d6ae43f7a3468d3e907be8f6949586f86c3d2984b1c0ba43dd657a3ae1f554b319610426cd502","nonce":"5c6891dbb9d12ec4fea6edd1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"3f1918b9a1a1727b4ac21902390048f251d85749437aaba9133dcfdad2a0773de00c2eeb9851803399c3bf07d0","nonce":"5c6891dbb9d12ec4fea6edd6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"a158f0c95c56001554c8ee83bdd220649896c4a13d45e2788030a127bb3cf2d118bfc7ec9120e1c5dff0afc936","nonce":"5c6891dbb9d12ec4fea6edd7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"ca8b743c4a8fab2407a3652469f5f7db7d22cb4f84907cd072b1a2fc5b5d7cff8c168dccd73ac23b89a46e70ad","nonce":"5c6891dbb9d12ec4fea6edd4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"12e90af14f627d3f248453ee4548c9d71dea4d29587fd9d9152b20aaf827e7d780e03960635bbc2ed53a54dd25","nonce":"5c6891dbb9d12ec4fea6edd5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"a48f051308d2b73b67f30270601d568b874fd4ed226baa77b71cae69d941c42eb9a3a7b168ff7862b3e235edc5","nonce":"5c6891dbb9d12ec4fea6edda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"695c77010ea04c566bc404df9f28b2516b2b1f005a812576c701611451152a2b7d206fa1ed49b4e4671222b751","nonce":"5c6891dbb9d12ec4fea6eddb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"d930ec3646727b62b412c07c76115eef8b71bfb20d92a0dbb57a5d72944e12c34b07e64e5371e2b0ee1c45b007","nonce":"5c6891dbb9d12ec4fea6edd8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"3edd8989c93585e9a3300ca0909565113f4beacc3650b0d762380cb602e448a6edfb8e678eabcdb96bb925262e","nonce":"5c6891dbb9d12ec4fea6edd9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"ee729023f61fea9f6e1f35b249a46ce430df129a8d058dc9ec9b002e36522d515818263352672884af50f8f168","nonce":"5c6891dbb9d12ec4fea6edde","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"403b964fe92d87330abfad93ef121460e27e6717726b4d3a6a8b44e1b24e0d924f5956aa33a445786440d0895f","nonce":"5c6891dbb9d12ec4fea6eddf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"7643c0446a9c02e8bde0102edc2f2cd04867214c9b46875b7d1e3f22f747f9e9079633bd76b9e7bed179c5aa87","nonce":"5c6891dbb9d12ec4fea6eddc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"3db2a703bc23f2aa117d5f6d561018014e24ad83aeef6eb4f409b8e00ca2c212258e5b758d649822bfe2094f0d","nonce":"5c6891dbb9d12ec4fea6eddd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"3032ae79952279b208095f600d03603325796369bce1de70c081a7af93194afd653bac46c644c213934c9c2e26","nonce":"5c6891dbb9d12ec4fea6edc2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"bdd08f7106f8f39a7982f887b735826d1c62cc4eac73f3c427604a89af1260d8745e630a07a39f38c4a72fcb55","nonce":"5c6891dbb9d12ec4fea6edc3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"7a0db6d0f786e3d4b49d3d49956c183842cdab01d84ac89401cd9b0d79cc249f83fbb498f540b3d54af286c9b2","nonce":"5c6891dbb9d12ec4fea6edc0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"2ac660e6d4451e1615eb2bd4ed02d3d1afeaa32fd6486b8f094a1f0ad9bf97ed3516cf7a4ef0adae8d477a8592","nonce":"5c6891dbb9d12ec4fea6edc1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"92253bbe79df3aa1ea38720bcc9f7d8b0405b8d460730ea878c3f51a5abec727eb8099ce3883123d68556746ef","nonce":"5c6891dbb9d12ec4fea6edc6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"c3f6109f418bbde97e0da596d21948b7d73ae62f6cf5ebfc9e9e28615882d0a4ead3e849c1284abf0dc57e8033","nonce":"5c6891dbb9d12ec4fea6edc7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"26d83959b5021455b5025b533dd645be570abcefdca71c085e9567267eb1cd985c4031737c112b0163dbfaa583","nonce":"5c6891dbb9d12ec4fea6edc4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"b57eb6f078094ef783053f1ab0ad2cf25c09ad50847526294500ec07b8319c86db02d664793356cd24e7fe87d3","nonce":"5c6891dbb9d12ec4fea6edc5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"764bc11f8e3ea05f62606ab90dfbd9bae2c5dd452f2692150e2ad21799e46a927b8a1e39ca9b4b6cd570a4b4bb","nonce":"5c6891dbb9d12ec4fea6edca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"887587e318bf6c4af3c8544975b0a6ec86dc82b34a62af0e752be56a7516a51d393be8a039ea52a62145cf7af5","nonce":"5c6891dbb9d12ec4fea6edcb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"39ba927c77ad524cd1c3f764cfa5ef2d17b00b9c18e7faf5ededc7303489566ce993937036b723829e1d85bd33","nonce":"5c6891dbb9d12ec4fea6edc8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"1a6f4a0d4acd34fa00eda41eefb6792d8c2c5424fd46ed6471b52dc0bae9dd9aec4c67b10c6dffc85bda473a75","nonce":"5c6891dbb9d12ec4fea6edc9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"ce509ccbbfe84a8b1c6932e917fda2a8bdfd18a7b4a76026db5dac6d0e5cf123cdf738e4016d4deec4ba382a72","nonce":"5c6891dbb9d12ec4fea6edce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"7d0b5bc1e969e10a102ee18ed73f8799ce60cc6817e81840ba9d4de64c84507bca1818dd53275452e6c388f027","nonce":"5c6891dbb9d12ec4fea6edcf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"56f8d87c5671f0a42f003737bac9f024c9067ceb240aac13411f80ae2b233d53f58130758d2e79bb1662aac26e","nonce":"5c6891dbb9d12ec4fea6edcc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"d3143f374ed1ddff89439c7f09e491570910badbca64559770a8eac28f5fb1ea501d8a8f906b9a093d9269906a","nonce":"5c6891dbb9d12ec4fea6edcd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"871c2b4d613564bc622658d99bf243929c5aed86e0000c78c522fc374cd29d68b9127b12488e5485a0ae7f2b18","nonce":"5c6891dbb9d12ec4fea6edb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"8d0b33d599c1c2b255b8f3b010ef9ceaf1a45ad69bf71502d82daf65bbf357341dcd536441685014c4244eb6d8","nonce":"5c6891dbb9d12ec4fea6edb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"536cdeec9b94df5f073e2fd5193cf934d137c95cea5235d15e7ce2e08281f61d15a9625d0eb3f4ce700b10e528","nonce":"5c6891dbb9d12ec4fea6edb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"d45fc81e76857d1ced1f87bfc0c36072f1e088954503ba1bcccc24ce4ea8971756dcd534fa6c81ed75a82fc983","nonce":"5c6891dbb9d12ec4fea6edb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"dbd8e08f9c50c494b0fbaa70c2db790396aef39abd5802623b402e9502dee0bdc4a25c9edaa016bdf0eb1a434e","nonce":"5c6891dbb9d12ec4fea6edb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"3f607c0cf55410e2827ed5671e8f3cbc264bcafd122e66ae6d494b412d42958473bc7f68de48b89bc8b367e484","nonce":"5c6891dbb9d12ec4fea6edb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"e90aec61080fed695fb5d23ea1000df018570b747f3b344f2a86d6cf569d6164e280722f23fb2aa9540213805b","nonce":"5c6891dbb9d12ec4fea6edb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"44e6fb8260a3afcc306fea1c8a5ab048de0b5717c0fb2acfe1717e0b86e89b0136f93dcdff0a6fe9b6e4388e02","nonce":"5c6891dbb9d12ec4fea6edb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"5c569dda19a73e881e5c9a69cbddf9aa0b4540d91384be1d1b802bc5b4b40666935d6373f8d03404c6495caa3d","nonce":"5c6891dbb9d12ec4fea6edba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"1ef6556f1a86ee6d0d56592535dfb7ebe15fb129a2a43cc20af098516ac69f3170b77ebbcd336c56b4daab01ac","nonce":"5c6891dbb9d12ec4fea6edbb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"58d504ca0af6c18900a5fbe5658310f9626781ebb691a2282c416fb4f5af3f360805d0e34d0850cce67721e69b","nonce":"5c6891dbb9d12ec4fea6edb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"b6699b53a3aaa0e644fb6ce793fc543ea31869d4515975cc875a760de39bc683004dc7378561c3e40efd3cf081","nonce":"5c6891dbb9d12ec4fea6edb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"450e2b9c435b2eecb76012152a0fde9658245d909cfae21b19cd45a36da732bdee18036aaa5067873c0c37564b","nonce":"5c6891dbb9d12ec4fea6edbe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"78b2e20aef4ba394ff1b4a099a587f44c12147f33f16240513f20949f14af980f26b5c53b61f0089eadc9f9e87","nonce":"5c6891dbb9d12ec4fea6edbf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"53a18d16193e898430a4dba298181f676254c14cc820de9b44aae1cf01ee931263050a03e2bdef359d9ba3e00e","nonce":"5c6891dbb9d12ec4fea6edbc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"6cef6baed6b3dcd62aa750df4ee5d2b0a46f820a57c70b77473b2582b525fbbc432d5af30ec68961a55d3e5bd3","nonce":"5c6891dbb9d12ec4fea6edbd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"58edcb3c1cf7e9156d82bf11d419525317b62d93120dcf5f1bb815262881026a27879bd9a074e0beacb3c45b9b","nonce":"5c6891dbb9d12ec4fea6eda2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"bd6ad7458d141837b43496f7c417f1394a4f2bf02e3759de23b2d90e0b665fa5450705cf35810bd465dc5ed3af","nonce":"5c6891dbb9d12ec4fea6eda3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"7743c4d94e5aff1c3899a26517478519b2663fd3d69b9e782caa5f64f50ae4db26e131ba3720650b61f81c36c7","nonce":"5c6891dbb9d12ec4fea6eda0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"4865e06b7da024f0f521e2e83519d81e0762b678c05e1cfedba053e85e876fec825e8d01f7f8c9df8a67e65f29","nonce":"5c6891dbb9d12ec4fea6eda1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"26ac849fb9c16002c4aa670919b86c559cfa92af120feab9a287d550b210cd9a6394f8c535750d0369abfc92dd","nonce":"5c6891dbb9d12ec4fea6eda6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"aa32dc029b6882061098664efd27c1315f275bb5df7e5ab038f3c4eb0801aa7e1c89579bee2abfb30c2306541c","nonce":"5c6891dbb9d12ec4fea6eda7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"dece66bd1350949bd903e9f0a513bd45165cf1329762af5f8fc34ca5cbeb629ab615bee97c3c8c18ca7cac0a25","nonce":"5c6891dbb9d12ec4fea6eda4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"30ad806b1037f75cbbe511aea4db49d60cc4c442474dddc5c3c66b38aa7117a081939bbfdd0b0a59c878510e96","nonce":"5c6891dbb9d12ec4fea6eda5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"405033d728ab01a502b74ac9cfefd637582c6fccfc886cc601b58f33950ec8f9a05557d53df6cd813b82dbf799","nonce":"5c6891dbb9d12ec4fea6edaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"dc27e6413cab74ddf0d496107da78ab42631b020ecb146b0f490637abd48d6b81b2c3443e1467b14466445322d","nonce":"5c6891dbb9d12ec4fea6edab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"93c3178c627adcc16dda387ce1392376bd69fbbd72be8a172960ada2315f9919c2726796efba10f235abcc8d28","nonce":"5c6891dbb9d12ec4fea6eda8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"ca030213574b852d1c24e030b0af940947dfb8a00ccb270cb080e87849575bc77d5b625dfaff03c5f94a956cd4","nonce":"5c6891dbb9d12ec4fea6eda9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"6605644f2f1378544009c21bddba2303ca662ca85170c20e1942b168e7f3f3c36c49d39bb06566fcdbd7efaf5c","nonce":"5c6891dbb9d12ec4fea6edae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"5ece694e2bf09c166012a147f24cb4d205c0b046fb6de2a1cf7d7bbd5733a4ee7548221fac582888fd633b7339","nonce":"5c6891dbb9d12ec4fea6edaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"b16316fc58c0cb933b2a738844f108f6cf4651ce7a8d6d6ff876fa956adc31de66d5482c5d480fb3ad1140ca23","nonce":"5c6891dbb9d12ec4fea6edac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"e9d3d3f57a55919bed80ac4a5ec6096948279c0ac334a99351995e76ed2bf93eb5868ec676006d29c66456a30d","nonce":"5c6891dbb9d12ec4fea6edad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"6e2a5b8b454f7ad3368f9e23628487ae79362a2a7730de42aedf40adca64c3cd045ea28384a76ba911b1943d08","nonce":"5c6891dbb9d12ec4fea6ed92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"a01bcf5560d3fca3ac0971ae311bf8c4b600678c0bc2d9db45ac8cf8044165f69163fe1d31aba710ea8b91148a","nonce":"5c6891dbb9d12ec4fea6ed93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"702cb3384b05e5ec17f0ed5da5176ca46d8d71f75e7455cb59ebdce314d091332c24b511ae63077f158b300e24","nonce":"5c6891dbb9d12ec4fea6ed90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"50d3167ee402d8c438ebb0bb450a1ba181c512642dbba7b865cd8ddd8666a022c1066ecb7996682023dc9203cd","nonce":"5c6891dbb9d12ec4fea6ed91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"733f678266b6352d17c345fc7f3fd721a83834dd6af28eb05286bdd163e0d815a600f445a8965d434497fda52e","nonce":"5c6891dbb9d12ec4fea6ed96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"c3997650a9d327df370be5c02c13d75e148df4c4ba6fcbfb8c7e6ac9d6db1b1004bdf371c805e954cfe7dc5a44","nonce":"5c6891dbb9d12ec4fea6ed97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"ae232a335a4fcd785d5e02dbeecdec907d1af0e869a39463e451eb4aff0352c3b06620033be17353900816298a","nonce":"5c6891dbb9d12ec4fea6ed94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"b0fac78716b3add9d2387d8053bf305894b6cd9eaea81cf789ae94770ddc4bad2ded127f962339a3382c2f5f8c","nonce":"5c6891dbb9d12ec4fea6ed95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"6f1eada3d54dee940d5cd2936e2cbdaea1fb8d528a4006898b0100ac5f61496a6b4a484444f72de88eb286bf56","nonce":"5c6891dbb9d12ec4fea6ed9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"8ea270c57de5b65ccfd6653a7990e7e489d170cd8d07fdd40ad333cbda46ccd753ee73948243f7964c2299c385","nonce":"5c6891dbb9d12ec4fea6ed9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"e4f8bf81ae6d65fceddb776650b461a4ea7fa0a84c5c49371a82b1904f16fa4f79bda35e8cff8b4d58e39ebc7d","nonce":"5c6891dbb9d12ec4fea6ed98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"674d50c0c39f681cb450daf731ea7501f38ac9c444dca2b31c613be1007057f72249aea9190e5cc04e291a099a","nonce":"5c6891dbb9d12ec4fea6ed99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"8df62878f79ca53e7784d6c73001697c28c18454bda0d6c166ee41969f5025c49c3787b1820540aaf61973ec66","nonce":"5c6891dbb9d12ec4fea6ed9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"f3fe27b7e3b0e60b81b32f04302340cf56679658e481ef6bfb69a624671753dd7d2113e1eced905d0b68ab5114","nonce":"5c6891dbb9d12ec4fea6ed9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"7993b1f2b60a2f722d7f39ba389438847260b02628ea0d25d85875112b2e1933530b8bf33c96c5624101e4ca19","nonce":"5c6891dbb9d12ec4fea6ed9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"1a2e13292aa1c6826a87bb2623746c23d389a4b71ee5cfe2c3b09fee608ce50777a639939def48722da9c7b149","nonce":"5c6891dbb9d12ec4fea6ed9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"f310232154debd16a0207099a8fcea1f11c7e3f0d1fd135ad3b7c67c7f109c1d0a5736fbba9f1af15c7ab48be8","nonce":"5c6891dbb9d12ec4fea6ed82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"75132ff9ad629e6f17a6c6c5b1db9b73d22007bf836d20172991235dd713b52e6496b19c50c9d20c27a2752285","nonce":"5c6891dbb9d12ec4fea6ed83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"1953562a5bfb4064284f1efd5ef16af0e92ac963949e1c17ab1b4167ac62074fe1ed2a35c98800a338ecacfdab","nonce":"5c6891dbb9d12ec4fea6ed80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"3eb11d3508cdf80bb05d7f4a14c780cdecfa019ee7ca00d915c59dd2efa2eda2c5af36ed38fd050b25a78a9163","nonce":"5c6891dbb9d12ec4fea6ed81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"d2da267624c5a7868da2b9cddde8870fe18640e40651d4cb739a12d1a923335c4c5505991e2b0279e6b907fe0e","nonce":"5c6891dbb9d12ec4fea6ed86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"2970ccc834c37303d1ad3e2637c84802e31d9cfb2f9c6ee32dcd5c2a46da2c19347325628a2727f634a82efcaf","nonce":"5c6891dbb9d12ec4fea6ed87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"522074be21a3ad6158441db7a286315fcebe50211366b059d1dc158dc8eac226c11788203f3872084057d5ac8e","nonce":"5c6891dbb9d12ec4fea6ed84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"1a413da2afee92ae6ec4774583acb60dde1694eb296eecd5c51497558f8b80cb07b60a22b423639f79501d3d2a","nonce":"5c6891dbb9d12ec4fea6ed85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"f613339f46117d29e22d2536a28e406d5aa47b29fef1cab8a97785e1d8246a29ad4594fc8e21607fd873771909","nonce":"5c6891dbb9d12ec4fea6ed8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"01d36f6cbff86e86c1c66519e9fbfc94a80e20c2c00120521bdf8c110c96abbb2040d6bb3979b59d59a6b04424","nonce":"5c6891dbb9d12ec4fea6ed8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"ed91bac6096daa2a5fe29382711a6d722586c3c4e0ed6366d55f9c9adda8386b110897eb71e58cb35d7aefed02","nonce":"5c6891dbb9d12ec4fea6ed88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"af3ada9d6c61bcfbe156568c54bfe34b526bb165604881c8fe7b9afff0b59eddc3fafcfe30786c09612171b780","nonce":"5c6891dbb9d12ec4fea6ed89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"ac897811ccd7c5b490ddb2ebf2fbfadc7dfa471a165a2f5fe5f88fb809b48c778cba2c5ce37cb4ca92f5c696b6","nonce":"5c6891dbb9d12ec4fea6ed8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"32eeae85dd6d46896d469f2e30345bc3bb1d20c5a58ba2e317f311ae8701927d572830a502e290b19350cab8ad","nonce":"5c6891dbb9d12ec4fea6ed8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"de4026ef0780be829e615da5535249b2e11da4395a53eb79bc1eaa23dc5568bf0ce0f2317397fc81513fe1bac5","nonce":"5c6891dbb9d12ec4fea6ed8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"7063be9351a592c59cc8ad0855824e3efa96c6abf1932d25f2d3af9a75594d370c1dcc42719bf0091533eee202","nonce":"5c6891dbb9d12ec4fea6ed8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"a362d56ae6261f3fc2fed84130ed08bd6f82ce51cff485cd4dbbeab90345bd276ac99e997f9d0a454f9f28c39a","nonce":"5c6891dbb9d12ec4fea6ec72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"0cfb5a012839568c25463cc7936d1f538c1222cb384799a729fe11112f525d7d"},{"exporter_context":"00","L":32,"exported_value":"0cf005f4ec8c471dc9cdf9c5291ecb3c1da30cfe96ef525050016f73fbc7382f"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"9e86c2a1f27d3d3c13eb8bb088148307080602fc674f17a2206745eb2d5b60c1"}]},{"mode":2,"kem_id":18,"kdf_id":3,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"f47f2247648c4151d348d3c69b61377091a924aaf8f8d8fa4014177267821e8a1bccbb7bdc7b8f77dd6bfd3210f616f023736cd74f46f77daca6268d2ce90835900b","ikmS":"04fe8b6f81e244061f97e43451110d056fc548d91f0378168cee93f948f0b7a7dc12e550765a2a4516ec802e22773de3bb2e8ad4e608fe0cec683a6adf4ec61f8be7","ikmE":"a44871b1b44ba24ff7590423ec6473fc3a5986cf2cdbacc7691bd8e2c2398869d5627b1d3241cd33d9d045da1264d1b927892ae16967e4dd1ed159c04231d28b6d3c","skRm":"007d643921dd60a09c3f562f8ab1fb76629345d370a738c2ca3d71a1e56c0b7acbe904bb65bf1bced3d02ccb653fe1eadd52f260f2444c09c04d979ba9463efed354","skSm":"00a6869f3cf8b7e0ac931a82accf988020d605d8ba51a2417a7d6b942c097b95846156b2b0141a3e130553c53187be20a0fe14b5fd8be62a7c3ac3ae569c08600541","skEm":"01141c8a1a32b007a9597fd2c4429911d68c522045e0ccc6b6f62becf0d3cab70ce1be9b765ca7ee25181f7d01174d2613636f51239835ec055de2eec8bc9a78e6d7","pkRm":"0400994f7d0346e350c763d60e4f10ee5d009c42c199d83b86a936bf93909a1403be3a1cb0e64930563bf062c2cfe5e07aecb31811ccc1d79dee3ed0436561fd9ae92d01c70d35d7de3ade4031500576fd159aaf064ca58f307b204f1e28d44309dc7a5528c4aa09c442c21e5b1e2f46d2f28153859be4260f62d238e28ad91e830d7016a8","pkSm":"040134dc837cf1799bd4d1ac23c0c06188dabc646c72562cf71caa2b864593425de773d5ce5fa1c5e54b2fe34f31e66445e65c26d972207b3db750a49cfb69e2ae863f01265df34c9eb58d94880276083b87d6828361031d0bd7495acd457a4ecb2f5776e76e25344197643c2bbaf7ee0a4c1e5ac580d1bafdbb95612a4be0cb88da8e8f0f","pkEm":"04000a2cea92e1487e2e1c2e5d88534126b5feec16bbc38921f1f1d1b3a3ecf49e230c2f288b62639b0910de61b3be5134c39bf98cd6f82f01af684f276b0d3c01989400a2f15e981be5073d30c6e5456cbea1c5fb47b27a016ec55e0de743d343b8fffabefff19575e88e184985bc8ae53d793d477978b94317d800cbad1b06a1a7188cd3","enc":"04000a2cea92e1487e2e1c2e5d88534126b5feec16bbc38921f1f1d1b3a3ecf49e230c2f288b62639b0910de61b3be5134c39bf98cd6f82f01af684f276b0d3c01989400a2f15e981be5073d30c6e5456cbea1c5fb47b27a016ec55e0de743d343b8fffabefff19575e88e184985bc8ae53d793d477978b94317d800cbad1b06a1a7188cd3","shared_secret":"ac761cf0f774691d9e2afe1903ff45ad1bf592301236b641a10293b97e242180ace3b99db4c37af8a33bbcebcdceecf46948509799e7091abf256dc33eb7032d","key_schedule_context":"021c32c098a411cf1afaec805bdbb4126b85caae458c62f8d8fbb24168b37930eab113e91348e59600e38ef02667015f5811559278b5daf69cbd8ebf22861e112922f3bb3f4a73881979994c3c83a46628434a24f6fba24b7cb79b65184480612f921684dd1abdb948aaa07637b3944e6ec7bf5089bc9e653f702dec2b8ceb1e0d","secret":"0fb1933fd9ea55232b9b1b41c33bc9007533b001b4bec12ea1136e96968645edcec2bd4ef11890428449849dd23a43b20f6b9d30aa50707eb2fda90d8945c02f","key":"1ef79f0fddd3cc23b271f6d78377546db02933d21aa8c0d6fb835ed3457edc0a","base_nonce":"51c86b4be9d18e3159853026","exporter_secret":"b4475c29370934f91765bb4b2f9595e8807fbde95fafca159b7bc6c4b09a01de599470a00af6e20e90e49ff877cb5dfb58e50b4d8e76f33317af52f71505e534","encryptions":[{"aad":"436f756e742d30","ciphertext":"3c0ff2ef5eb3e9f69838291c4bf5906e1f5528ec5871d09b84e8c75d91966b1b84004d095d9f9d6741a7ae3a3d","nonce":"51c86b4be9d18e3159853026","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"73ac3b28038d0cdec2d75d64edc112eb76be5aaccb10eb8f24d285e9400c2a4584406a0d7ce872f1eeb374464b","nonce":"51c86b4be9d18e3159853027","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"dd420fd5f0f40e64203f91f562a7ac60695b891962c56e4ba93fa122e7f57ad8ba424efe49e24eddd97503a806","nonce":"51c86b4be9d18e3159853024","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"f3c4ee50f321cfdc63896c1bdba0d2e71c5008bbec23cedc3fdb90129f376bb1222a5bbf88744413379398d5ce","nonce":"51c86b4be9d18e3159853025","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"1c4ca3fb75b4c3a4122da58164c947ac6a2585f0d0aa79b33a85ea2abda0a9d58f528e88fd5f9a171e87d6dc11","nonce":"51c86b4be9d18e3159853022","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"ce23759121693283a5a53a312607c97ff41d80d56af5bdb007a01075802b2542cd791c8677805df4ace966f21f","nonce":"51c86b4be9d18e3159853023","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"adcf962161aa370178ea7a018ed18634214dfb9832aaf6e40b49518b98c870e8879376fada81eb27c6674003f2","nonce":"51c86b4be9d18e3159853020","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"6313f7f1407f4c264d7353d72a22f28803e6503ae1a8976f6694242e3f3daf83bedc91b07edaa7d9e1c36d88d5","nonce":"51c86b4be9d18e3159853021","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"e3bccc90e339ce2c0b4ca0e2285dee3351a112a56c42f459c5d13e70ffa7a1d4bae5bfbf90f627361ed513e889","nonce":"51c86b4be9d18e315985302e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"5c5891ea62d5a78b8622962ff1c0a5136e39cca345af6ca0b52b9607357ca0fd8b2056f31d85a14121af4327d1","nonce":"51c86b4be9d18e315985302f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"64ec6f3fc7ef0e87df3848f7a3b36cf8ad9c4e0a5a337c32e093bc2b2f0e0be5dedcfa0d288a44e79f288c07ea","nonce":"51c86b4be9d18e315985302c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"445743a33010145337c514cbb35b9580b3efac7e86f01e7667f9ffc44697303812cbf68249c7db609859296672","nonce":"51c86b4be9d18e315985302d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"60884d2a929ab11e467d9c21fa8412ee8b73d69458071a1ae9a8ecfd53ae4bf1c2aefcfcc7e564b25081ff66db","nonce":"51c86b4be9d18e315985302a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"d366661ada22caa52214926ce33761a32e85c079390ef39691e9279664c94736445c1cbb89cdaf522197ba650e","nonce":"51c86b4be9d18e315985302b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"f5c8d68e48ceb3c915823e1f25572abf27fbcfb2f8bd7a8c3cbf736cbd1f3d8d381c096993e5ff30403b82469e","nonce":"51c86b4be9d18e3159853028","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"398a1872095a28529bcbd20089304bfea74d86f11c445cf7c6ec8ee77228375a80ac033a0dba27469d8297e9b2","nonce":"51c86b4be9d18e3159853029","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"e9f9c45921261848135a9650dc93b85d0669ea01d72b4d5be7070faf2defc0494d3b4233ec72525f254b96167d","nonce":"51c86b4be9d18e3159853036","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"4815232d8d6513a4ce46bc1d2bcbf0d605e4eaf5161c7819de7f07ce97f3bf26d2e248a95e94e0e5fb14311a36","nonce":"51c86b4be9d18e3159853037","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"3e154d769d067cd964ea8976b7447c1921032da7513a13e7c82811ce7ab4d60c6541e4481950deb7a67272ec3c","nonce":"51c86b4be9d18e3159853034","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"37d465d7d821fe29d929704cb049245abddb0b550f3e73ae1510c10712508d47f5b8fa4b59f76d00a6aeb2bbcc","nonce":"51c86b4be9d18e3159853035","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"4bc4a7c537a60204599b53a63b506491772ec2c251e77af70814bc96ee37235ad67e1fc96126c8ee133b682457","nonce":"51c86b4be9d18e3159853032","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"19328e35375c45e6d5de8bf0d89d4974982ac3475fc052301fe298d0af392c96f5c805e64ddc60ac1bd847b99d","nonce":"51c86b4be9d18e3159853033","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"4fd68e43bb4c3690ce42e4e8cbdb98d23e6f661e014b418cd9273623390b3dd02b2290d831d00dd3b35c84f56f","nonce":"51c86b4be9d18e3159853030","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"063a457aa93fe1024fc642b606d3259bb7a4d53e50d7266b0100932818aaee1755f0d274a63b5a39e65cd312c2","nonce":"51c86b4be9d18e3159853031","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"b03948d76399697712af9b8a18c2eb96394d4e8a452f5c94b58531c77a27b89a27607275447c39dce024070a8c","nonce":"51c86b4be9d18e315985303e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"fbbbb7f065dc36fd2975d0acdf163f4a204390643e4a8d3324b5f44e068443ee255c9a4d56aa4c222a0c0dbc1f","nonce":"51c86b4be9d18e315985303f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"b232292109806cfbd0363080d2aece45487dd902adc1b03fe6840e670d9491b77f658ceb9eea129767018b756a","nonce":"51c86b4be9d18e315985303c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"3430df52a7700dbff4e462d6dd8ca802f69ca75fe902d70a5dec625ff3541af4ef9fefa57a6972e09bcb9bf1db","nonce":"51c86b4be9d18e315985303d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"9b32846a4852f9d8f1a44f02a971176e5fb888a0273642beb572a21997811cfd4816fe161b61e1224a177db749","nonce":"51c86b4be9d18e315985303a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"fd3a6ba408ddc8377cf5f43e0ec23ec97e66fb1db2fdf6db57b0f4a997d79be273cba704831b90d02f5d6b3886","nonce":"51c86b4be9d18e315985303b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"725ad238702e61d10f24192f2b54c9ecedfd07d7732b2a8b662630a98abd92816c5b55c133af4e7fdbe9333eb1","nonce":"51c86b4be9d18e3159853038","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"c12e6412f52bd9fbcdb02f14ee74afdcaaa011a4f01a3395abfe36a6a4b46ba3fff1345dff2d4c5924ac101f97","nonce":"51c86b4be9d18e3159853039","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"900c8b86ba9e28587cde476f7126092c87db5527ead0ffbd39b47fe7ecbc3361ed91df1125bdd5459dec96ecbe","nonce":"51c86b4be9d18e3159853006","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"d34f305e1fe6d88682cd33db5fdaded37e2a7a4e55cf6201cf67f5cf7c9bccc0193bbc4f581d3a91645b74cbaf","nonce":"51c86b4be9d18e3159853007","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"33b12ea229dcdc89dbf1527cfd0a16535c482c361de9579bac7966933396c0d06d469e17b607fec9d653b7657b","nonce":"51c86b4be9d18e3159853004","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"aa266612679f5da23a43b10a6cec2b49d6a1ef60f123941c85486bfd3daffcf273a873d937ad55d9e8031585c1","nonce":"51c86b4be9d18e3159853005","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"3c4c57bfadbeadcc09cfbb746033b57511c898e3014964a82b9e7b0244f80c43ec07d64d590e713326b2c99196","nonce":"51c86b4be9d18e3159853002","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"cd4ea63dcdcdc0102c4cbe4b4549d40b5946526df33e0506453b491e7063e7e51295344db43b6d4aa7a310d0fa","nonce":"51c86b4be9d18e3159853003","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"08669c605747ecba007b2ef9ed74c0f834d21c00e72de4e72a75b4f3868120ed0751dbe6c2a213766f725eb119","nonce":"51c86b4be9d18e3159853000","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"ad624b47ef1e3e6d846dad29df6e6a9cc5b6a68c9807622222be2595e61d5ab1b990e62f1425204b02d71e554f","nonce":"51c86b4be9d18e3159853001","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"65ef292d9963e9f59bd80c764e6f021b9e11915a5a8ca1f0b5d30a5399fa5e039b788c49b15339070d765d9d37","nonce":"51c86b4be9d18e315985300e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"b1ce3e49ba9947336626b6db2a47b0b94e29b08c6718d2ae5f2be4a30d2b8d96ac800deefaecf0a40d46a17eef","nonce":"51c86b4be9d18e315985300f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"9e5f0968a0eb392df3c008fb17aa53496a190f1d96a0e8db7417dbdbbeadf017a57945baf9684184f7ee7dbda2","nonce":"51c86b4be9d18e315985300c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"bd03381cdc2eb325fbeeeec5fcad39dde5e043a18d4f64ec0a6bbfee17c30dc298593133dd672d99dc92783111","nonce":"51c86b4be9d18e315985300d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"c69af33bd0984d15aecdfb3bd0edfccb1292f8f20b4798ef71092b995b046dd699b944098d32965139a9d6ccf1","nonce":"51c86b4be9d18e315985300a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"ed71229542e8d8b87b0d9566948ae588d4f1dc3e8080086da745a7dac0383cdb8b2c8e69a0525351e7ab3b0d49","nonce":"51c86b4be9d18e315985300b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"95fe4148cc7f023d38c590d44b1962a40c91941e3fa14885c1f764a7bc1d745fc78f7bdd42b4f3e7b8a1157f6f","nonce":"51c86b4be9d18e3159853008","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"39dcd113b7689b43be15eab6e31c980d81d7879650b37ad9226a138e924e15ad47bf5d50b5df44722d63f1c1fa","nonce":"51c86b4be9d18e3159853009","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"9987b049436350fca9667ad7f2d4744883c17c7765c2933fab28a0219c2e522faedf5160f7f095dd93874bc4ca","nonce":"51c86b4be9d18e3159853016","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"f0994625f4f131e1c4b90646019368f3c3f898a78b727d9b314861698e178dc8f28eff880846b7c20a6166c5ee","nonce":"51c86b4be9d18e3159853017","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"37ff9622f1feb03cbf83870ab3341d9b6de181506fcc1563b6e032842b5ff4335ece46d04556b99a20576322fd","nonce":"51c86b4be9d18e3159853014","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"681f050d67a974d192e77e87f3b7ebd71c3e573923361c1cee2d917cf87503a8c678dba6368f24ab0ff74e47f4","nonce":"51c86b4be9d18e3159853015","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"3a1a6d7763d9d5480889ef70da9471599a8e16d194ea56ee21bd371aebb10de6b62086b5bd5f4d221e067b3eb6","nonce":"51c86b4be9d18e3159853012","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"5e3c97530acaad055f2bdb661e441f6748e9f1c63531b8659c0070c6549142d9b610da8474d4054ce0a9a3e8aa","nonce":"51c86b4be9d18e3159853013","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"0416b3e46fa293f85a9189ada414aad2827e33d2315a8de4ab6514d2f8e8caecd2cad3de6f972d7c497fe8d7fe","nonce":"51c86b4be9d18e3159853010","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"26b692c7ea40730eaa7bc4a4a26a162ba29e1b825528784dc8fc2799f40e0e2d689806ffdd1f52b5eeed97c8d8","nonce":"51c86b4be9d18e3159853011","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"6dc1e4c436a8656cc2a38c27e08bfb925b0a4d0a595e802d81e94f3e933dcfdf264ff7453a4757f53f59a2b62b","nonce":"51c86b4be9d18e315985301e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"7cfcb72e49cbb67da151cbd3ae5fa85bba708ed885582abe3b86c5e373eb9629f58b391c43ab9c568b607b9656","nonce":"51c86b4be9d18e315985301f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"394160c1ecc92c1f067d38712815d5ab010c736ea7125de531b716b4bc471bb47464f664eee16994e677b93c38","nonce":"51c86b4be9d18e315985301c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"5a75717a9e29e564b61f80b883dbed83e639fd5cb7f8913d58cc6371b8a5481abea49fdc05a45e08f0f2b81326","nonce":"51c86b4be9d18e315985301d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"c5839e5a6eb4108754cf73767da4212d6342fd5d6fac4b843576cb88187eeaca776192fca2953c12ec2b7f7849","nonce":"51c86b4be9d18e315985301a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"64ff39143c1bd58bce7b21f1267d6273eae12632d635e89b2535595749be1eb9f4af5d63729f979d354e3fc12e","nonce":"51c86b4be9d18e315985301b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"0e7ddabf6599e38af1d3be4173bc26099dfb7bbda349807db8e69dd74637280190be7f87a84a25fa14e11ce14a","nonce":"51c86b4be9d18e3159853018","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"31bf74f2663efb049fa474b0e5ca77e2c1e33debb1d60a56b25262c1888d53d6dc126449790e1229de774585d9","nonce":"51c86b4be9d18e3159853019","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"0b0b4a1ac7fc18ae759705435599cd81f053e40b1e660b09990177cf796e95a7750084ab6fbacc1bbfc0bf416d","nonce":"51c86b4be9d18e3159853066","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"87139105833cae4c73230f67ffce42f05edda4ff5a82c6ce39969a7c84fe5651b88d50214c5f06df1e86bcfde2","nonce":"51c86b4be9d18e3159853067","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"185cbc8d7c91dcc55a490b443138d7bb6299a95f682fea0b8d3fe5d0457bafbff8a27348da2626c2b9cfdefaad","nonce":"51c86b4be9d18e3159853064","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"02c376e52996af02470d50b53f8c6111a34e440f1f439eed52d2117619999aa09034b935c113e4c6a7f159b418","nonce":"51c86b4be9d18e3159853065","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"b6b95fd6175b299f1eaf2cb1f9970866c10d00126534ca0f74b15b07808f4aca8bd8a950e5d2f0b879e060320c","nonce":"51c86b4be9d18e3159853062","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"6d1c494884dd8c969548df46a2b2ab3b49ebdc819ed02c755e72257d221ad64a45c0ebd5971f3f2012e34f7bde","nonce":"51c86b4be9d18e3159853063","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"b8dd6d509a491dc092dc1f95e78a9d42aab73778af288d8021600c423feafbcfc6a5f08b4c83a29b6334f8ad50","nonce":"51c86b4be9d18e3159853060","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"cbe7bc6343e96b6838cf742362aaccec3ab8809d588bb1331385d0e9679eb1d062a3bb3ad848f6613692dea473","nonce":"51c86b4be9d18e3159853061","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"376a15aa789bd03ba5dbdb21efd916f45d7f63681a29b9958f2829d0941fa581c26e2a5702690a3c897d3f8283","nonce":"51c86b4be9d18e315985306e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"c2718784a8db9b6d47d8a9773ee72e0ebf9bc456a038aa390cc25152220dc0eb8163ce8ad1a00eb0d28d4670d2","nonce":"51c86b4be9d18e315985306f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"699b66da5343e26443fb0ebf1addac364d74e8c1afbdacf4b1695767a4c1212fec04778bc0fac4f5d4684d9768","nonce":"51c86b4be9d18e315985306c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"c8d58a4e773c4dbf84a54a0c0fa25084b8c2274c9fff820a82f28aca1e884593f62cc8d596f59c41eb2ba2556a","nonce":"51c86b4be9d18e315985306d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"1d0928672d956d7a46669c17139973c42437d0a94be43b65b5b22132bc54a7520181d388c9ba3c52c3fa93a327","nonce":"51c86b4be9d18e315985306a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"5b52d0d4eb9798576a22a409e10f5414c5acc5c6d4efa427c646a72b980819427735748cb1d222b665fddcdc17","nonce":"51c86b4be9d18e315985306b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"cbce11b8a849e72bbf11fe6dee1e7028afa304cd056cf6dee29e2b2846df5058974b4d6117c783a56950a8014b","nonce":"51c86b4be9d18e3159853068","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"fa0bfe350eec26e42a3858023449e0e607af3d7889c4665f4571fa8d35335b534e18ac07d92c60801eb0cec3c5","nonce":"51c86b4be9d18e3159853069","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"effd8b2ca12009268d34827d2973c0e14b153bfc1bcf381f594f9dc710d1d437d13f39eaaf5ed9cc124499c276","nonce":"51c86b4be9d18e3159853076","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"7fc14ff3fad638ef6d7f0c033236ccb8271181e673ec1f4f812f2c0e5574ce0fcd73dbcdb7296cbc7568c629b3","nonce":"51c86b4be9d18e3159853077","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"447462dfb442a340cc3d9aaf36209bbd860529d0ef3f16b52f68962b2736e3ea6300cb0ae7f83cfed372a1b9c7","nonce":"51c86b4be9d18e3159853074","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"34eeadfa9f3c62d7b99b3320261e86a0d1562a5a7634d501fa7a2b450c8a04f3ff1dc75d94c3ff4740e53b5840","nonce":"51c86b4be9d18e3159853075","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"1c9dc5bb856a0acf312e41569071bfa7c2bf83bfa3363ad73b404d61a65856aa1df2a00eabcf661f92b85d7aad","nonce":"51c86b4be9d18e3159853072","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"f83d656722b7946f01773e1df9babec9c2ed4bf611a24dd54f3ea881349ae9aab98c4c39e2898c857a9642e95c","nonce":"51c86b4be9d18e3159853073","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"e6907eb4fcab666dcb3c62801ca442917b3d6c5abf9cee66c222c88077a7a19ab7d35c4c09d80a988e297fd25d","nonce":"51c86b4be9d18e3159853070","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"8df1bc95b27f0e6e8ba0892642b755bc2ef6ac658b35ac94f0d591b09c5236ef28d40bf7dfdd0264921fcb9b81","nonce":"51c86b4be9d18e3159853071","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"44e2ed17f6324f066557a6591c46e08b946c62b59b6f441319eef5316e5e738631ab298091556c378742a423bb","nonce":"51c86b4be9d18e315985307e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"ce6fd6811e4bbb01697eb77373f439872e3b9e764a77b46e2f7961056b30e934b71cc841611f25237418a066da","nonce":"51c86b4be9d18e315985307f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"f3415869ff87ce1dc204cc7773b3481038b0e922a69c93c1a9cebd75acfb6f2bef9789fbbc2f3aac2c8bf783d4","nonce":"51c86b4be9d18e315985307c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"f600eb63b056beac50abce7b5ce3f2636a6d1b8ef7b9b2a6c6947c7bb1f30612e3f05cdfcc9d3e5e694324ffc2","nonce":"51c86b4be9d18e315985307d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"5c0b152718a61e78b6fe374c41fb655c92f4853f80825057a3493fdcee4539c05966bd246fccabb096ad7ba5ff","nonce":"51c86b4be9d18e315985307a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"f8d28586b05e5efd7f4380861fa65d9ea1ae38d9ea40fd2cdd7c5787583e96b424842da131137be0b24bc40967","nonce":"51c86b4be9d18e315985307b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"56aefea3b8d8e92eb035c7dc3de8a7aaea93c60d334ddfdf2c8823bb3cc8226488c4ff9a68c0e52af1da4fad18","nonce":"51c86b4be9d18e3159853078","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"d7e7100e0b95b1ac44861ca3d9d4bf0dae33cfd57962f280112beab83c00332a29ce2af863744f03504e7b46e5","nonce":"51c86b4be9d18e3159853079","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"5cabedd977a611009b6063a5937dda4b6d64bbe1a8897158c269ace64077ef14016a7a84c748200c718479ab30","nonce":"51c86b4be9d18e3159853046","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"daab0aff287b9f763a46a85c40b5f037c284bc0ecfbc3059254ead4644a582d1cb29768959fe13bf919dfcb3e2","nonce":"51c86b4be9d18e3159853047","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"74aeab8f18873a5b95f579fe9c0507c41b41e5d922c245a867feca6e3e19f22858f368423fe0325c87c64384c8","nonce":"51c86b4be9d18e3159853044","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"d2ad4d6b4998dec91fda93807c8987fa18a398602feef8df28405162d61f15fe4b9690c2baa8e80505a49d58c6","nonce":"51c86b4be9d18e3159853045","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"0edad57b0d2c52245a0770567eac5b98e3e978b23cbf42545eb10b9ee4c4b7bdc4e9dc4718ed4892fa021e1373","nonce":"51c86b4be9d18e3159853042","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"1bc6240c33855e66562f7c568cbbc7c7fe0874b9d1528ef10ba71354b8e690a315b4e8b42124b0a6d44f8caa20","nonce":"51c86b4be9d18e3159853043","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"a1f2016104e9f71fe381575a66b9389ba6cd368fb4219e42d1007550047154220f68d68db707326022f7f4115c","nonce":"51c86b4be9d18e3159853040","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"4d119001741d4d1276a6d9d34dee8eb5cce34554efe8e6ecb62f4fad5758829df844c152048ade737d25bebd02","nonce":"51c86b4be9d18e3159853041","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"0af16b86bc546e480244e981bc7889ab35e838976195b71f31f6f9a28b5a13d9a58830fe89cf75621761b0e889","nonce":"51c86b4be9d18e315985304e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"cab61e36c0e5a70bd1386973f10c10e52fd9c13197c3a3a2e7f81e91a92de074fe6ca60d15f90a563189af0156","nonce":"51c86b4be9d18e315985304f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"5c69b1b09e332805282fefdbb4f1cd49948287d3cec3e18cd4ad9c8a6d3650906c73184d2df6cba3ff73c6997e","nonce":"51c86b4be9d18e315985304c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"f4ae154da9d2875b8d2bf0a410396b39cdf699aab6ebc36b27a78c9932f7dbee663a864a33d8745b42feb0bb4e","nonce":"51c86b4be9d18e315985304d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"65e989dcf02b78e5c4f6f3539705f47265e956c8474bf2c14dceffcd8e1d83e42adad13055d9dbbb5f9b6ca8df","nonce":"51c86b4be9d18e315985304a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"68d3f78dad5e39cfcb6c6c08fc62edd8f0589572690aee3268c206520cba0a1e6403e9484fc04a29c6ae373fcf","nonce":"51c86b4be9d18e315985304b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"27b4becf95ce88a4d9a8f483f158fe70db3895815a988910705a6cad308d30637d7c92cef882223e19aeee555c","nonce":"51c86b4be9d18e3159853048","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"eed11f18f616360f3878da9c4180658a97c933e1276014eb7f8847982d7913d5a680455720228ae2107a4f1ab0","nonce":"51c86b4be9d18e3159853049","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"d9b7b94a8b23991779d176bfeac468e079700131a950de32986a2b6b2a30044f9db4596ac4011196d92aede957","nonce":"51c86b4be9d18e3159853056","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"efae27f4fefc845929ddb1f0677e5008d13e15b43ca27d19a53036664cde8f493382ddf7f6bfcde661f9bee8dd","nonce":"51c86b4be9d18e3159853057","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"d43774483299c83793a28731882394da6f6a5b6d2c74e2728dc7f33274aa64b1790976f46c8fae37e01beae514","nonce":"51c86b4be9d18e3159853054","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"a450a1864a9d4a0c36aab624c4d83e56c4e1540dc502b0306cd397f4df4db0aa4f9167041a379fd2f5ba0dc8de","nonce":"51c86b4be9d18e3159853055","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"9ebf9861e1b3bf2345674cfc99dfbd26542cdc71eba5ead9098b55f02964afe07d98951bda0f323a91aebdc438","nonce":"51c86b4be9d18e3159853052","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"b3ce184a9d4cb667427500488d79cb4897369ac8c3eb6a81a1d7a8015a5f8628623ea1d88920e289cf5f210082","nonce":"51c86b4be9d18e3159853053","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"f114b37780c1da2058241332769eb579c777d6b68662da82c99feda59783eeb78b56e8e84d3e30a59c4e12e965","nonce":"51c86b4be9d18e3159853050","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"5702c2af2593668561f6e06544863e36403da00fc0ba2a5226c8ba9960efb70b3d38b74f83b9c74ffd0cb886c9","nonce":"51c86b4be9d18e3159853051","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"d8e7a91f93638aaaf4cda273e81c18bcd6b95784a3ec14411eb5c0dc2b553dc581cc6cdfa9e1d8cf930deb50fa","nonce":"51c86b4be9d18e315985305e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"7eff36dd904ec65af7e4b94ba4621debbd4331231ce002d168c11638efac6b3a788e79db1194f9ceaf26e9ecd1","nonce":"51c86b4be9d18e315985305f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"a6b7aca44a48b157b2ca7108b925d19d96d215fea459373a245a9c15cee57f1f92ed65855347fcfb5a54ad75a5","nonce":"51c86b4be9d18e315985305c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"d16da88e2d820f42b94dce5a0c2540b5dd22e91e5d9091a7a32f9c1a3c2521d22b29960fcb406f31240d6b4c75","nonce":"51c86b4be9d18e315985305d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"572b9aeec2ed58d20bd50870994b27789a8c1af1b239ec704528d55de73e5717f63f653f978dae1c522aa7e946","nonce":"51c86b4be9d18e315985305a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"4a6f537cba0774450ad48cd5f319d7284e3c6332c1f765fe91d4a35bfc03c7f5a4ae39bc360265c0d6a20869d3","nonce":"51c86b4be9d18e315985305b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"f173f55e109a0188270aaa44d9a2ff5c2c7a6d4732434b0b6a388e790f200ca452bf0a0a237bb37ff1247c5d6e","nonce":"51c86b4be9d18e3159853058","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"8e90f5f4ac49392c787e13adc850a48d85c88c7aa4ecf8680e70c28438c2b0c48a23c9da46af7f531313de0b5b","nonce":"51c86b4be9d18e3159853059","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"b71218d9ee97ad7467035b4942d2cb41461571a01e01dc29318a46826007263b97cfc6f09eee38cc69a8aa0957","nonce":"51c86b4be9d18e31598530a6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"af56b8259d360e1ccda182d85ad8f7a0fca2ebcadd3696751ba098ca37e16d3a3e4aa4a5ab88a76a34c0f4dbd3","nonce":"51c86b4be9d18e31598530a7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"9dbe11f5421891eefbb5f9c45af4d38c804a73319088aece8bbf1f89137bd90528eaa6787e3333d164e7b50310","nonce":"51c86b4be9d18e31598530a4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"d3a896a9c95bb577ddc911a543d42e3d22fafbb42c363c388bcb32f8b546f0c89091727e97b0b237b7ab1c0333","nonce":"51c86b4be9d18e31598530a5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"b1cd3ea5d54e9d9f22bb2222df0afbcb569c6652a2bf54a6bf6f03f9b67bef9de68d403a977960a235104acd9b","nonce":"51c86b4be9d18e31598530a2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"0a74243c9ab9f65cdb06c230aeee8bb99f9bd8dbe4bfd52879cd71d968c56b2fdbd00bbd67e0b4ce722eb04099","nonce":"51c86b4be9d18e31598530a3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"a01d27382c8870aacac4e445c6c76fd0aae6c58651cc83fd9e2c9dfded066b4fa76670f1c852de42857601c42c","nonce":"51c86b4be9d18e31598530a0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"b9f8246ec3bf9a1fa0770725c352dd7dedc6bb06f67af5122936e9ce8603f8235f50385facb3fbd56428b01a60","nonce":"51c86b4be9d18e31598530a1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"02f10491be1a70a5f00885ef814320aa6bda42576d780a08d4350798313522d89f7751d33eb10801712882b6a7","nonce":"51c86b4be9d18e31598530ae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"5b562172cc27f625b0e9220a54cb61f29c9f7072fd4f5f201aa4ffa8c8d18ed762e0f6b9074746603e93985d09","nonce":"51c86b4be9d18e31598530af","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"dc92bed2c2d8298d82276b75f9302c6a02b6e279ac4569e4b97acaba9a49f6827dd3cced22994a7d47c8455fd9","nonce":"51c86b4be9d18e31598530ac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"6bbede64c3f733be7cb43d87f44ec9941b188415a9996d08d67cbe03dbd6f5bbbe03ffeec73f2139dc76447a16","nonce":"51c86b4be9d18e31598530ad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"42808f825be721bc3e0881189526eeb913a5c5f21952c5d5795f715999eb23d98003220bfa0d15bfba8d90501b","nonce":"51c86b4be9d18e31598530aa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"8e3891c9e7700d969d72c8b6516e11166f9ccec082e865bb1d14a1e98ea3de37bbd8d4e1c54b3cd45b926cc4fb","nonce":"51c86b4be9d18e31598530ab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"74765e0827f769beba7aabd61d481e57898216108f35ed52787793fcaf103f2bda6e7def77b428d3b47f4d9b0f","nonce":"51c86b4be9d18e31598530a8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"cf91afdd9a0c2fb3478f7f2a94bc2c5a21bd2be2bc6b77c1bb57d46f63c1e5b8572041b26a98a2dfdaa2be5521","nonce":"51c86b4be9d18e31598530a9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"b67590cf4f193378f2f98dcf6d59585609f6cc743f1fdd7cc1f7473e384454a9342807b523c430d90d678c6121","nonce":"51c86b4be9d18e31598530b6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"27ab84fae7c787efab44c0e073a17eed066543a27c68531d3e21e90a26c34680f6b207005eeea60c7bcaefaec1","nonce":"51c86b4be9d18e31598530b7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"ea4063ee421ab27a44394ce7d372caabf9a4753bf67019a2c427f34684998af8e3fefeb60720f7a0b9c1d74d35","nonce":"51c86b4be9d18e31598530b4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"a4ed1bc86f448a57560b0e2ca270228a72c6dfa85953c06a781acce91ff8647abba869ecbfcfa8ebe1f09b9600","nonce":"51c86b4be9d18e31598530b5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"2184068709e14d9527784c3492d3bc34ece6aff6a6c65a051980ad8c454ba40d642f298000329d04354196061a","nonce":"51c86b4be9d18e31598530b2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"2a55b4121009401959ca8c6fb72fed9da8d07dab5a38df1dac12e84c84bf6ebdc7f1d9ad9f9a6b1dafa1088103","nonce":"51c86b4be9d18e31598530b3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"537767af7b4ae307b766fa3875f239dd7b3e14db8cc1c0d3066f0ec99c44bbf05f2b8e6c695d28dfc321e2e957","nonce":"51c86b4be9d18e31598530b0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"9c0681970bdc2c96877b5ee53438dd872cd0885638b40a4f3341526922fc73c0bea5ab276ae15ef4864b7060f9","nonce":"51c86b4be9d18e31598530b1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"cb597c67bc190b9b872b37574f732e51b929f7fc4e86088aeb8ff0f13c3c020605ed5b184c8b342a8e1b947c7c","nonce":"51c86b4be9d18e31598530be","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"ca8e75722983f7b18d6643a00d7364b1145f08405e5632ab36d9001c0e98b84247b649cc7c15d8cf18fef6fd4b","nonce":"51c86b4be9d18e31598530bf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"de4b615536fe5121e85860a59d3e62b567449f66f358395e8d16618bd3cc2d8267643093effc874179f2f7d8b6","nonce":"51c86b4be9d18e31598530bc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"92d54bac3bd378a3fa0e201340fb919f6f37ce97d21c683569fedbaa1a2cd91239f1b2103b20015906b2e95e19","nonce":"51c86b4be9d18e31598530bd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"d6b2a46c49d1ba4a7c9b4eeaaf616896d52406f6e37047f9608215b8672527c40fd99f8d817a36044318075e24","nonce":"51c86b4be9d18e31598530ba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"50a9c398ca0a84b6948c5abc8241621ed29b7b25b8fb1b0050d9a62741ec910dfac1fbf2bf21a64976bff0a1ed","nonce":"51c86b4be9d18e31598530bb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"9f151cf5a8760aed2550861bbb4a758bcde4e7b23ec346d4a389cae868e2650bea2a99f50342b0dd17fcc1f4ff","nonce":"51c86b4be9d18e31598530b8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"4ee4cd03113d7d4ff7351514b4be5c1e4697042cf56c10135b9923328788b5e30453a02514e83cfa2e9a44d6f2","nonce":"51c86b4be9d18e31598530b9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"da955225d9a8372bb079cdf53ebb1c1e4fb4b76d4362d071fdf4e5f2959f0cc3ff2fb4cdc993ed93912edfbeda","nonce":"51c86b4be9d18e3159853086","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"3b925f95038231f208944ec1ad649f0dc47f7d34370aa9605b55e1cff4ee7f47a86e2f8d64c0bbc41c6926820e","nonce":"51c86b4be9d18e3159853087","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"3f262b27c1257dfe5fe00414145c58ab596b5a4252748025a765677d5271c1d80b615b07a90d394a9317507f93","nonce":"51c86b4be9d18e3159853084","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"133c3fdf88cb9d48c6d75402598aa3d1af9857fccac07b07e2699054d862ffefeccda72f182e54537b137634c2","nonce":"51c86b4be9d18e3159853085","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"5c92e0a1d75eedde149f4dbab5b90b73b53bd564a8b24876be6769bd4f5e27cdda5f4a001659e0555dcc7f9e3d","nonce":"51c86b4be9d18e3159853082","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"4914151d186aab8abce6fe0f52918eb47565c6ea2d14cdc9d31e6ed9d1cd66f76c622437d0fc41bf957727c461","nonce":"51c86b4be9d18e3159853083","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"857b4a0e39bfaa6ea70149d9bcb5e7348e25d42735b1ec097d8354c9040b90e1dba92b24e7a7c059d70e9d5457","nonce":"51c86b4be9d18e3159853080","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"41a0e1451db2368bf1406378e37b21d0702c9cebee6f8c169a94de45bb7aae0b59a99478b9fd99a6dbe8c9bcf5","nonce":"51c86b4be9d18e3159853081","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"cef07c658134214f0b268b49a67bfe2af576639eaf0fdedc40c2a9cae3ed07e7d558bd08d7a6ef76c011f94920","nonce":"51c86b4be9d18e315985308e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"f4fd7fb85a5f2f639cf74d721006e22c73a32958ea4722a340ed6cddce5d97178989153effc9314dac2d3b87ee","nonce":"51c86b4be9d18e315985308f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"519141d3699bc42f25aceab214b04ca274f3cf0c94b8b773998a208e6fc1712800031cde317b7dd32b756d9b8b","nonce":"51c86b4be9d18e315985308c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"438809c44cd09a6767e5748e2c4c5a4f91377f44607034121e3adc720cbca5a6f60252a65d0fd59b6213c344e1","nonce":"51c86b4be9d18e315985308d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"7dc6d136c380c964b371dc065935d74b9059792b79562a75a3580f59f4757a6120301a115a00a963cdbb2b4214","nonce":"51c86b4be9d18e315985308a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"4106b778b3dc7796723bcdfd6379e77cedcd6b8a2299dc59282858479b61e847b127f268fcda65fc5aacf75935","nonce":"51c86b4be9d18e315985308b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"62d3203c2c449da972692b5aebd7c31f80dc9ade47b7294625ad3946b3ea73a0ff774937f445a7d2d317f436cf","nonce":"51c86b4be9d18e3159853088","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"e776f90b9c9bca1e1927bf03e31ef60b520b7bd5c9fa4500f392fd78b09a39ee60b7153ea75fdcb0eb9b564e05","nonce":"51c86b4be9d18e3159853089","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"fa32a0dfcf16294daa6f323441fcaf5dad07644d1465bfc7efc551f5a071b3ea64e66e6a8064017974f219aaa9","nonce":"51c86b4be9d18e3159853096","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"51c6048a0bf99deced7e665dc7f18e776e6582298f9b30af2cc93b8ec8f8d8272383c47155f2547797c20aadda","nonce":"51c86b4be9d18e3159853097","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"4b73223a685e7e21873793a5225494f09da217b3b7abff6e3bc4786031aafcd979c3b63e8452a7038707b16d4d","nonce":"51c86b4be9d18e3159853094","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"357edfccd60e9799d93312b3cdea70e55ea98be23d35a5a5bbb14d4cfa5a1ec0357762e5534ff86affc25c081b","nonce":"51c86b4be9d18e3159853095","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"271782ec7b746a4c573cb4d5c42db79d2ed0bf4bc08f8c05aabeead5cd8fd685b85ec07e64ac948aef2c7ebb92","nonce":"51c86b4be9d18e3159853092","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"2509fdfb1c4a2eeaa08ef54ef53a0081863160af656b60d1c676cadb5c5003a3f08d20923ccefaa881a6e12f60","nonce":"51c86b4be9d18e3159853093","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"57d28ff04d69443d46e37bfe0d1c5daa35ba2b95340b7be65defdb57b72888dea591afd2ea74fe3a51532bffca","nonce":"51c86b4be9d18e3159853090","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"78fa1caa7fa13e57e8ebb067ba1936f799f44ee0d969cbbb89553a4cfe8ae33ef5446bf8aa289dbbe202ad49f4","nonce":"51c86b4be9d18e3159853091","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"7959c4b45ea12f3c45b3c2ddc7b0dcbb46da8a9664b95269fef97cc1c3df432aeda646fc647eb7451da6559891","nonce":"51c86b4be9d18e315985309e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"2229173cf090f8d401e05b0089caf8e05c6218873ff871e2f8db95a875981b93c3fb36fe0e27bfbb1c1757ff44","nonce":"51c86b4be9d18e315985309f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"ddd7bf9e444e79c15e935b0c320f1790e86b1301ee61e976bec4e5012e47fad14aa1013c590624d30173d15b48","nonce":"51c86b4be9d18e315985309c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"c0527973f2edb8635030fc46da8fe7523ed7a9edaddc184d18a063e9153d9d619b92d0644ad0d4361119e8d7dc","nonce":"51c86b4be9d18e315985309d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"370e0c00c860db942aa76ce09387976c986603944db9804c471bc57a8cb945252b371b53ddc341d74c24e3f9b2","nonce":"51c86b4be9d18e315985309a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"02dc00d60d1bb7f0b1253a69c37810536ce1991b82cf6a563ae8cb6f1e3b340472451302076f5e38713f3b338d","nonce":"51c86b4be9d18e315985309b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"b07bc05c42d962dec4f40723ae22f019f83e5dd3be2d9d0a08e322d88196074c710299b26d3447c04944353794","nonce":"51c86b4be9d18e3159853098","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"978b66dc1835e4ac9e1e97ea64d1cb6126ef642fa522251267b5b9cbb8465b11da9a62fa139ee579d964110b84","nonce":"51c86b4be9d18e3159853099","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"b8d74d3d4f1bdf54eb6c55cd851b0213c84b843c97e20208510b70b381acde7782dbe5b44418d3cc4c8c6701b0","nonce":"51c86b4be9d18e31598530e6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"76639f754bf730207195116c9ef80407236e0f4f911e841bd6a97f81b9c92f005ddc1650c4470e4d9c773270c6","nonce":"51c86b4be9d18e31598530e7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"8ce9949d7154ccfa8d368295b3ed226231c984ce11bcaf9fbfd9d002f08e9593ddce9c70edbddf58ae7c6f46f3","nonce":"51c86b4be9d18e31598530e4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"fd6846c4e37c478490e78f95ca904108853d702739c6f2512df585fc4cdde0a0afd0bb1e7c7d26e610c718cde4","nonce":"51c86b4be9d18e31598530e5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"5a95efdba264bef10a26990b42727698059a16e381981003f11d48e7851c20756fc4eb03cef40959823498dfab","nonce":"51c86b4be9d18e31598530e2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"7d9f0af3c176da716cd18614e9f5e3010053658e6895356c7a8ce56f0da95c5f6561d30353598002a373de1ec5","nonce":"51c86b4be9d18e31598530e3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"c71d372446b85aff45d93772772a3bc0b39f6908ecfa97bb73c969f29c3b77a10cca9216032a630c90904afeaa","nonce":"51c86b4be9d18e31598530e0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"3b0b355d6474dde651dd14bc7a3ee3136ec10ad753921f9c864abb3100b9c2e41b732f9b59b928637a710eef35","nonce":"51c86b4be9d18e31598530e1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"e49197349e2fb2c0097c941f825bd83a1a4f545e29bd5a4eaf0c7a299625f34d91dab1cdfc83f9177f458d5289","nonce":"51c86b4be9d18e31598530ee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"a949b18932222ee45bd9c775ba24e730f06af052d6cb3964360afec4e3e814ea0d95ef8ff6a8b18c6cda979160","nonce":"51c86b4be9d18e31598530ef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"83cbe0604b852b5483b929313d346072df6c384df126d769d4957781652338d2bf36cfcc442d2dfb12d9e06313","nonce":"51c86b4be9d18e31598530ec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"202a99294e9eb7e6a79eea14066645f058a762539a3359ec81b0e27b3b6232f38df7802928567010c50f5a58a6","nonce":"51c86b4be9d18e31598530ed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"4c0576fcb57dec1e21a3758420088c6138d31e6dcc1a15120d800acfbd7e92a593e1b9d04891f153c4b4f661a3","nonce":"51c86b4be9d18e31598530ea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"d58905a1e66e2048b84a069be82e66cc9f7dff9b9f8e1e5fd8da8d7f4f95ed3c24f9c069865ec9cb86cb4057e6","nonce":"51c86b4be9d18e31598530eb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"3a38de0f0899910b5912482be821a484468534639528166d3203496f6ba0cb933a8985dd0ba338acc4d612109f","nonce":"51c86b4be9d18e31598530e8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"9f2241481499f281b51c2c81cae6f74d4bc2c4b788943fdcfdce125b6217bffa19467202b3b20ec8d78669b497","nonce":"51c86b4be9d18e31598530e9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"e49b6477f6be4032269b3c4af7eb9011b32a526bbf9a13f4f459b2b6c9f976494e105099a46b9095a029d4cbae","nonce":"51c86b4be9d18e31598530f6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"5150ccc6a48ed03d773f24ceb2ea41ee46984924dfd6979b63d6f571545a4d67ff6c737caab5501e1cf8ea925f","nonce":"51c86b4be9d18e31598530f7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"05d952a8a86fd63384f862289681c54048ed951d8d669bad9310b973d1764dd01f43aeb9e30652a40cc9dab4da","nonce":"51c86b4be9d18e31598530f4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"a795df9cd78810da4781c58f130c2c5163d8d53c92dd2e6bd7e09072e4aafb4c82f61196a0bd6bc844481d5468","nonce":"51c86b4be9d18e31598530f5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"8cf64da939943fa46c46b4c530f70c6a21c3455214ef323827a6adb2fe60c191986c6f4822fda4601ea36e99e5","nonce":"51c86b4be9d18e31598530f2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"95e16692e082f639e658952747979e7802f2e6864d44703003026280737fc50abcbc18e093a6cef58cd5ece4c6","nonce":"51c86b4be9d18e31598530f3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"056f74073622f33d1e2c3543e30d329758a35dd6dc295aa0923b4c6dd80c201a47af9181d6d045c417edc9243b","nonce":"51c86b4be9d18e31598530f0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"dcf3cffd46d985317e0625a871f15fc6653535ea87f344e5d770bdefee850b986200062d59e56aedf73897cc4f","nonce":"51c86b4be9d18e31598530f1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"de017022c297d0cbdcf73328c0672c7aa391affccec8f43bd5a5d8fd5b1320fd21562954db99eab4032c72e28b","nonce":"51c86b4be9d18e31598530fe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"625db0a0f290174cc427156162a978d6cfe74ef4aeb2b0cfd93dd9bbe1547d79ebedd4b11e972cb5e89fd34c31","nonce":"51c86b4be9d18e31598530ff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"2bc69ceb7a17fd93380038d3823a328d452bacf32306f256bc6c15729f255417d05519c50efa34cda9a02cda47","nonce":"51c86b4be9d18e31598530fc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"d07541c72f768b1d3ae9032b8a542f1f4d15dda16983fb645ffd65cbe7f330deb13932f3b81904cd8c335e418d","nonce":"51c86b4be9d18e31598530fd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"560ef0619f5e023720564b9eeae0436e819444bb75ac93afd4cd70b23faedad4af16a0b10627fa4cfec86bea4b","nonce":"51c86b4be9d18e31598530fa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"7f8aa0df1af6c8ae7a11fe4e1af5930c8a16f810ca21067d14facad83e461cf33260810998e07a3ea613d62c4b","nonce":"51c86b4be9d18e31598530fb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"efc65d9aa6402f53d24730e88f097f1b0ec211212badf6a09870d3aca16a3765db90ec833ca7f1d651015815c0","nonce":"51c86b4be9d18e31598530f8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"8b1d1e275b7d8b44f4918ebabfa21897b312bd50de6c6da75dea4b50f97dc6173d13fcef3aa4c4e616bdfef33f","nonce":"51c86b4be9d18e31598530f9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"ae6a06bbb6de7be3736294055d8c9fdcdf55384d3e59ceab5fb905887a3d94f5f25f972ad3a3f3061269566a83","nonce":"51c86b4be9d18e31598530c6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"eb9d08f0142d41b4ec538444fa5861d2fd8fb5d763d6d455348f1ec4f5bdb099f56de228e086da12567d35444e","nonce":"51c86b4be9d18e31598530c7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"04564b49e59a536b15d69ff1cc8c8fd53dff64bc2d825298c0342aa2ab8918d70ec6adc87224a1bcf79736f66e","nonce":"51c86b4be9d18e31598530c4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"abd8d3fbea124a733c3b6e226951d4a406d497da4f75b811274a05728263682a2adc6c60179487249fd3475f64","nonce":"51c86b4be9d18e31598530c5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"e87c427d0ede41466dbb4b4b44d49fb334c47cfb1af7d1e9e5c01d33320cc31caf35d844b5260e1795e95ab4f3","nonce":"51c86b4be9d18e31598530c2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"518d088c37bd35504cb18f6f96801326a09115337712637ea5bd37bed93bfd37d6598abead693ccd862544f53f","nonce":"51c86b4be9d18e31598530c3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"2551106a07bbd722aa37590510ce3a715b498cd1753ed47ae048467d19b24c7ab1a20486db38fad03772c7357e","nonce":"51c86b4be9d18e31598530c0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"a750a0a413fa9af12e63bd861249fa7aee2583dbfbdb0ad4ce802dd844f709b11e1b4afb34525b9aa92f642222","nonce":"51c86b4be9d18e31598530c1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"127bebfe93093a9df8723ed52ed3c414c8f0cf305c014f6bca0a21507ea9390cd26044081f27933e01515d4898","nonce":"51c86b4be9d18e31598530ce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"7267a3a77a97515a85a86fa0f681205177d25b9c36b3e284623f6ce86ecf12b20b7ef16b297265acb88ac1f427","nonce":"51c86b4be9d18e31598530cf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"e5ed12a9fb3794455d1fce42c78d28b1137d9663db9ef53884bd0becf36080e4cc936f27e984c560288c9a9a5d","nonce":"51c86b4be9d18e31598530cc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"e31dd834b6d084c3e090f3aa746b8ed24575c0a1e49b4e97c6405634250dbdcde3a5667d60b578748f47ba51ca","nonce":"51c86b4be9d18e31598530cd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"54b7295f2e1c6f9b714be2dd5bbd5c30277d1271eb8075525aa7672d14e690f964f2ffd7f830a05a5ccb166a86","nonce":"51c86b4be9d18e31598530ca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"910d684b2e0c66da40cad1ead2078d617ec37585ecf0165af6f9604cc819f962ae13a672520b26897b86d9f0d3","nonce":"51c86b4be9d18e31598530cb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"d086685ac7e47c475eff9f49b9233c0fe146f6e4fe293c0d0a12c0507e2c623f5325f87a44b37f12c0abac1d8b","nonce":"51c86b4be9d18e31598530c8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"32551ac261c4539a595851f3e80c49ec59fa3ff4a93aa936829d4bd6948b0f1f154b12dbd86117b6660bb59e7b","nonce":"51c86b4be9d18e31598530c9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"18a7d99f0042da48d95c26f7911809a98f466d827b43f3245b5c73d9910903e52b40050c273e5a05ac2a0c611f","nonce":"51c86b4be9d18e31598530d6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"befecd071dbbde36e4324cd55ff94fd0a4ea306d8935376839b66ccca317e5c393890df62ebfd05381e7859a13","nonce":"51c86b4be9d18e31598530d7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"2104c3fbba2d48f3400fcedc17071e1df57099ba7814e165fc946c8517dbec25de93e768dab9e9004de3adeccd","nonce":"51c86b4be9d18e31598530d4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"c3d93c599084f2e75e53f300481d02b594b8780e2d583beb9278c8f008757a62a93cf1e571a34a9fcdba8174bf","nonce":"51c86b4be9d18e31598530d5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"965cb297d1d4a5d0f6809e1fb3a43ed58acaf8c311fa72536ee5037ccec7a8dc6fb570cfd97e5c06fb2252d2cd","nonce":"51c86b4be9d18e31598530d2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"9116b4e9023bdf1c52034d571a948315ffb362056971a1c526b2686862130abae5d38af351f423eebb905f25a8","nonce":"51c86b4be9d18e31598530d3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"8212bc70531dd124541b0d5e7729272252af7be7d84002b8608f0856c152add4df7f0799bdd1fe6a61a0636fb2","nonce":"51c86b4be9d18e31598530d0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"72de001a0c8919800742c14e424efe43aa573a180b9b9ab63e3cd42e80c83a05412ca9cb7d746c09eb68b3962c","nonce":"51c86b4be9d18e31598530d1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"9af473501226ad0598341c91623eee4c69f44ee10e49d9ce478a639b8045128f48014df2f39f57db0f3ed542f4","nonce":"51c86b4be9d18e31598530de","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"de68db0d375ce4cd32943add64d4b743618af2052aaf39410035491380d2308ff6ec958fb86b2cdbf2220bec27","nonce":"51c86b4be9d18e31598530df","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"11ce2811e5bdcbaf140b04a695419847bca730b8fac4cefb3a594f543ce0c33cc8a9f12a035aefbcc32b5d56a1","nonce":"51c86b4be9d18e31598530dc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"2d3327b80c9455cb25a373a9710704d0138609b9c1776da859b9ed6bc1799b944a703781a1b7f8b109546080ba","nonce":"51c86b4be9d18e31598530dd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"88341a53d7ad6b181ea94c4aaa1481fe50f7e8702a757061fecf0fafd1cfc05a9b4fb9f9ffdf4885b2b33a3df3","nonce":"51c86b4be9d18e31598530da","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"4752f906320920b89759ea63338e489bacdca63bfe835e56c3336771175dbb303567a389b30f674b0a2fc95867","nonce":"51c86b4be9d18e31598530db","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"dc13562a115286bf9c7a978656b9938ef6a7e7fe0517409fc59ccbf8872a9008e6d5a6b0b451148c6cd98784c4","nonce":"51c86b4be9d18e31598530d8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"4c41c8f8deb5104e634773970bd34b49ced97f5fc00b0bb9a49ca05c5cf08f520e285dbd3b9b100c116a4e51d1","nonce":"51c86b4be9d18e31598530d9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"38bf18a8d72a6621fc23796ca7cdc9628fb080017dc7916652e4c72214a82f303c7e019149e66fbec8c028e23f","nonce":"51c86b4be9d18e3159853126","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"fdcb3c7392bcd758f5239b8ca2bc21a95ff93430c4642a323b38368eaf47a3f6"},{"exporter_context":"00","L":32,"exported_value":"f28e22bbe424a5aaac3fda5c9a6e5642bd6b1532f1e3021dfe242dea80d134be"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"d16ac829cd30eb0dfce180c1b28eee0d29c74093e2c15adad52f502f282bdda9"}]},{"mode":3,"kem_id":18,"kdf_id":3,"aead_id":3,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"5701dc72314e9def83319274d1415d6ee194ac1c8b952cd2b374729d1f695990a1474872300e0248d2d09400e7f5783d362fcdf6e3538e75c14809325574f576bfcc","ikmS":"b1cb294dd9b3a46b60dcacbe4b380cf6d2cabfffac216ee5392cab21f8c67fe79df05e1b904029fb345029b0cfeda000da00028b7e132a26c99bfc1946f871892860","ikmE":"9ea58919508ed2f70dcaabf44f2689efb8cf540fae9b0bd732daeab786ccec9e248ce4ee900904bbb98ad4c5346c0f1a742fc0a2b9b9cf62dbd8ee7090c0d37ba043","skRm":"01bb990989955e3b92e36aac153df5e1a0c0041bdd05867f9ed81d05eb9f6c0778ddb83a29e6b570b5c9ebbcfce378e523c75a048385219e23c9002fd9c88bed852d","skSm":"00f7921f05986f8ba551d08b150acba8b8062e19567ad5eee0de1c98cc4783018697534fc932fbca9dbdc0b1e292b30f9e27005625bdf6084c2c5687c81320c00359","skEm":"016893aaae68a4d359330245537410e9b24ba407000aed4eba2062bfa0702ba2feedac69b3d1f87c7557ac8ec322f03c9306ca10550158e5675326cebfd784cbfeeb","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"0401344de7a7044e681f732f8f05a6721be921be8740af5833e3df78c3f73a821f5bbbb8b12ef358f39b8029fd65ef15669437ef98621749974e40abea24891fad1541005a4f16c224863bd50cd82fd4172a2b9bb434c8e99736eae3a332ca0a7e3c20448d3f2b0186c39ad206806e51bbb820e81971e6a4596a27343369977c14491d6fba","pkSm":"040049d797dd81ed838a319bfaa269eb058aedbe657294f23389a9b68e396df38378edb05f2262129696d6e4bf2b14d0c123a0d4051944be93dc16b03475fb730d90ad008141313fde1682ceaf6e80c8d4f1c0efc1c2fe915aee3b83d44645ff621ce9491fd50b91c49acbc0a6f1a3008313ac5597d39860a7a38028d32013a810699423de","pkEm":"0400905b41974e370f0d3f12a5e7e1cff82ec90c65f35ce3f9adc4c9c29e27c41dd7d7ea2746d99f3e2397df3b9ad37a2d55deced501dfc92064e8c266aaa7c4a422c80139222a4759b64a70bcdbfe71cc08ce01acddcc4d0bb5f96313f9e04debd3f8ba171ace7ee5ffeb2e27530b6baea19b0c18759509163a39e24721f334d18e0a0544","enc":"0400905b41974e370f0d3f12a5e7e1cff82ec90c65f35ce3f9adc4c9c29e27c41dd7d7ea2746d99f3e2397df3b9ad37a2d55deced501dfc92064e8c266aaa7c4a422c80139222a4759b64a70bcdbfe71cc08ce01acddcc4d0bb5f96313f9e04debd3f8ba171ace7ee5ffeb2e27530b6baea19b0c18759509163a39e24721f334d18e0a0544","shared_secret":"f3f15b70b1ab7b3c8624527c49481ea9d8668396946dbb807fe66d6198b8036a92a6ef465065341bb4f43785d4e28807d075b5f13d1955719f000e88ae95a3b4","key_schedule_context":"03c6a8e57593eb61a144a1e20bd4b48deda0008bb0207407ab5679de9543b80a1f5db7d872c1f8f0db384d4777aaeda462baab80c5bf406281bd6d73bde8be20ec22f3bb3f4a73881979994c3c83a46628434a24f6fba24b7cb79b65184480612f921684dd1abdb948aaa07637b3944e6ec7bf5089bc9e653f702dec2b8ceb1e0d","secret":"a2ab08fb3d3606bbbfbd1629a5276647bf333fecc5fd2dba7a5c890168addb69feff6320f2a1f49b41870830cdb46181fdc29ed295ba298e9791016e2a35b57a","key":"fecb9aefe0602e8ef6608c5736dc39db46d080511c21438e362b7ee73906be79","base_nonce":"5cc3fc6a245a1540baf6bffd","exporter_secret":"56cca7832463c7b77ca5d3d31ede14b192d50130a99cf9bdad828dde864cabdcd35f2aa8a01a26cdbad58c1a061ceb09b43d2c8aeabc88cc01c2e0b805667c9c","encryptions":[{"aad":"436f756e742d30","ciphertext":"e19defe0dd9747d3f8e8c95b9802223d6cc0ea291493ac0e032d8aab642b09785ac9982411d03030d43ffa7941","nonce":"5cc3fc6a245a1540baf6bffd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d31","ciphertext":"49a294b99488a8b76d470dd9a76058dfb37000bf494462f226d76e14f9668ba051b222397c6ec4c9537c1da026","nonce":"5cc3fc6a245a1540baf6bffc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d32","ciphertext":"f9f90c87f05a23dfabb615b74a1eead9c38168db8e70aa98da2e14c95701dfe464faf9a17d3c5a5a81ff387e67","nonce":"5cc3fc6a245a1540baf6bfff","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d33","ciphertext":"9be693670571879d74e3df80959ad6c176c8f75712220c97fd22af7258c001629f9f8032aad112f13f3a35c97f","nonce":"5cc3fc6a245a1540baf6bffe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d34","ciphertext":"0498e3bda9599fcecb756351ad5cc514536c77202f55ed9c8cc227491d2692a6a412f8f6eb5707a945837822f3","nonce":"5cc3fc6a245a1540baf6bff9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d35","ciphertext":"8994d259f21d4763069de79348c9d6ab12f41ecb92e1a936b050a6d7a0d4d5ac529e91823a928a8dfdc128a409","nonce":"5cc3fc6a245a1540baf6bff8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d36","ciphertext":"32bf5f6c2150610cfd60755f181bbcfd56702a99ac70cd0020e9046f4739a1cc4b65860b3c63da02141f7dc9ab","nonce":"5cc3fc6a245a1540baf6bffb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d37","ciphertext":"50d2c8d4f70f0d21f791e9e41100c758600341b82b5f08f626e0289c7428ca04351948f1484b78c9636b0b5210","nonce":"5cc3fc6a245a1540baf6bffa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d38","ciphertext":"32f3c2500f49218366fac8e3c515f4c29ba1e78cc019ce34a89c3ccf8b0e0b0613a8ba6dc3c4054b969f2b6e7f","nonce":"5cc3fc6a245a1540baf6bff5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d39","ciphertext":"5f7d948b2e5cae30b496ee5d76511669469183e2bc58406b1a8576ce0ec4cc5814364996691f35b07e5b51b6e3","nonce":"5cc3fc6a245a1540baf6bff4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3130","ciphertext":"97a87e92c6f79bbe63c2c63cba4493e38757a262d0ef51fccc0000106a079aaa3faa5ca93d3873193dba4b588e","nonce":"5cc3fc6a245a1540baf6bff7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3131","ciphertext":"531386c4153c286fc539bf33dbca7921d2be85479a8e4ac276a03ae156c5119373a9e44bb7ce30cd7434d85a69","nonce":"5cc3fc6a245a1540baf6bff6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3132","ciphertext":"7247b85a9048f73433ac9bc5baff0d7eaaee88ce5b42ebc62682cccee580fe48ddef5962d1b1aa35a6aa64eda0","nonce":"5cc3fc6a245a1540baf6bff1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3133","ciphertext":"b289988891a193f8e0b614e1b43e8175ffb2a75572ff86efad608fbe9a4562576daf3a425f84d43e075e20a822","nonce":"5cc3fc6a245a1540baf6bff0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3134","ciphertext":"e52491aa93f1e284a15274959b5b986246d245a47a53365bed1e5f3ac98588d3ecdca3a97962e0bf10f86b9344","nonce":"5cc3fc6a245a1540baf6bff3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3135","ciphertext":"a1c1cdd1a0e31202803b532022383f8955f67284217e0eda2da90f417297fb1ecc39de9e4d42a23db09b20243e","nonce":"5cc3fc6a245a1540baf6bff2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3136","ciphertext":"6c845bfd0bbaf3846bee66c87c0452466264855f92c093ef6c81e76fa164ef01cbe032aab32077b826d4652120","nonce":"5cc3fc6a245a1540baf6bfed","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3137","ciphertext":"6ce4e6ca05b5f7fbcd0592dca56712f27a8ecdeac9acb33c1b379e057e381b45e9d2b9bef8f6249a028a4076d6","nonce":"5cc3fc6a245a1540baf6bfec","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3138","ciphertext":"74882b185999870bcd2698582199a32742a827bfe61b38e7470da7b0a5f1305c10782d2a2af1789c31720a08eb","nonce":"5cc3fc6a245a1540baf6bfef","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3139","ciphertext":"6385278581be736e0cedca9d0c3abd9685719987883d136fe6cc6bf6980d4114c171b769fadf818d8f9e0703a6","nonce":"5cc3fc6a245a1540baf6bfee","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3230","ciphertext":"f4e1e78b9a50320e3effcab35cad65ef66730f72991d6e106b3fc72c5aaaa85207859de66d54815439218cfe9b","nonce":"5cc3fc6a245a1540baf6bfe9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3231","ciphertext":"ac00d6e643157e812f9e9f0e7996b36d2b58179bae4ab220312d37c205472710d54f03db00ee9005bf96bfebe1","nonce":"5cc3fc6a245a1540baf6bfe8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3232","ciphertext":"1fdb84feda40eadb1955d3a266e021fbf0d447336b12723a8ea6c7069570aabb35c2c8328586aaf6678c87bc01","nonce":"5cc3fc6a245a1540baf6bfeb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3233","ciphertext":"de58cf7bffec56f4b250af8ae20aba3b2b2fe5d6d70b24864b84211d43290dea478811ae4c02a6f98fbec27ca5","nonce":"5cc3fc6a245a1540baf6bfea","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3234","ciphertext":"9e1cd8b3a54f0203615e4d7ba26cecf39976829d359ce5e1cd69756743addca14da4d782790b577f0e33f2d6a2","nonce":"5cc3fc6a245a1540baf6bfe5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3235","ciphertext":"667ad0328a80f8079f37ca4e7b0995b001f41ffb1a7400238a52c6d4cb70dc875193c5abd3933415470df42b3e","nonce":"5cc3fc6a245a1540baf6bfe4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3236","ciphertext":"6e8c7f8619f72212d84a8cc10d9d8a453fca9242fadc45f5c3c2d08679ec43d432369cfe09b2d1ba977c68b727","nonce":"5cc3fc6a245a1540baf6bfe7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3237","ciphertext":"94135a3b426c2db048bc30f7810895911737cf0f48671908b170a2bb234554897cd8877e812c1f5023b4cfd07d","nonce":"5cc3fc6a245a1540baf6bfe6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3238","ciphertext":"28f5ae9a763f32ee93643ac8e2de131a0f7a1821e7c549a2bcbd0302061ec8b4cdb2fab3f9f923dadd8214cb28","nonce":"5cc3fc6a245a1540baf6bfe1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3239","ciphertext":"9cafc5f6edb2491eb956435e83a8e1c6aeaaa3256ab1af360530095cafafb079725cec28f01c3b21eab2a568f0","nonce":"5cc3fc6a245a1540baf6bfe0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3330","ciphertext":"dd690da0698558d84c0e9366c07bda91ad16f0f829ba1fa5ed5efa698ca07db0250ec80a886fd2545cf3a939e2","nonce":"5cc3fc6a245a1540baf6bfe3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3331","ciphertext":"efd1f8e728e6e119c09a3e54f33540e6712b0f31f1bcd5c614ea45300d35630b704e96f0d12395aa97598ecd2e","nonce":"5cc3fc6a245a1540baf6bfe2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3332","ciphertext":"aa9ee3122df034f2322941853755abd9e07ddba16d02939257ff464a6a6cf2e2ecd08660f002a8b82d1427fc9d","nonce":"5cc3fc6a245a1540baf6bfdd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3333","ciphertext":"2c3ca7d62e064ba9813e1afb2cf5040ea4ef764dfbbfdd28d5e2cfbeaa7e124a599d5829f2f4d2125693800a50","nonce":"5cc3fc6a245a1540baf6bfdc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3334","ciphertext":"eab3cc69b3e40f1192af48c3a2e7862db01df80ad0ceb2907db7d8eef1d60f6df5eb72b7d94e4a78c4d251092a","nonce":"5cc3fc6a245a1540baf6bfdf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3335","ciphertext":"9ec56e70764d5a6b8a7f541a51fc0d0e00a1cd50520e8367755ad33b00fec660a9c1d0b7cb6a2101258ac11759","nonce":"5cc3fc6a245a1540baf6bfde","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3336","ciphertext":"e61e04ceeb33d5964f21ad2361971489c8a24d4218ce7a2869014f7792956b374d82c04d30f80de7302f3e0f9a","nonce":"5cc3fc6a245a1540baf6bfd9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3337","ciphertext":"9efbbee4bea3dce58efe96d67bff50ff1f35a44cdd228638115ab7f422272616f90f649400ae7cd9d1f590c927","nonce":"5cc3fc6a245a1540baf6bfd8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3338","ciphertext":"bbdbc2ed9fa65e3b2962f02f8a397f0ab9345cfd61088a65e9c2ae3372f27b927b78ccf0efaafc5fcc85b09a34","nonce":"5cc3fc6a245a1540baf6bfdb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3339","ciphertext":"1fba8f1a1a1988c91cff7947d5eccb29f0188578d252e94d70e4da57af77c5a78bd8ca50d1950fdf2f300fdb14","nonce":"5cc3fc6a245a1540baf6bfda","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3430","ciphertext":"a3715c0c90c2b226f14a9cfc9e14e982c9ddad189dcad797a6792088141c3695857eb590581f1fd6e6468efb67","nonce":"5cc3fc6a245a1540baf6bfd5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3431","ciphertext":"3e7e020822845c8b4c2d5db6dd1f473dda73eaa2eecbb36a856563ed00076623d55685de39a69b7a3f3b0363f8","nonce":"5cc3fc6a245a1540baf6bfd4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3432","ciphertext":"31fc771449d76d563681921e0adf2fd80b7f482d22156c48eacff7ffd4fddc1fafe00dcd96e5277d92df6366f9","nonce":"5cc3fc6a245a1540baf6bfd7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3433","ciphertext":"1fa2ac6c29a423d5930a84afb8432ba5e4882168a6a92bf77cc1b6c01c2c76dab339e3cb842ffde9cedc10f321","nonce":"5cc3fc6a245a1540baf6bfd6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3434","ciphertext":"d28e88996208d7091254d75d604dde722aadb9ac90728b3fd7f12104da35f12dc0b1c7173277bb5b45a4207c23","nonce":"5cc3fc6a245a1540baf6bfd1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3435","ciphertext":"342f179aac09227d1715060e8f4e808ceb0ed3f342c6067307985b838b3304ab50ab5f083bb3359d8f87c6974d","nonce":"5cc3fc6a245a1540baf6bfd0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3436","ciphertext":"592c915113e75f583a5d22942cc6527f161498aef3eff13f51d4bd27e519a0b094e1ce9dc072d066d1a47c692a","nonce":"5cc3fc6a245a1540baf6bfd3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3437","ciphertext":"fc3af2af38bae127ec55334e29ab476cac48cdd9a57218ef44b5c89a1c368cd28544b13c896982d8d639b3b919","nonce":"5cc3fc6a245a1540baf6bfd2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3438","ciphertext":"5bfdedb58848e3d0a6d3190a829e46558e253561b1041c183e9ab4c01a8bdb400a76d6fa40ff579130cd244e5d","nonce":"5cc3fc6a245a1540baf6bfcd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3439","ciphertext":"281a0d44686068433ac6b2e1cde8330e99c7434461172b7e7eba259227a1237d9d5b75c21a2875aa03ed8b8149","nonce":"5cc3fc6a245a1540baf6bfcc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3530","ciphertext":"8f63f2b48206dc97a4559e31136a8f72b163a009cc562db9324aeeda277251a282f6eebf0c2cae698f2536888c","nonce":"5cc3fc6a245a1540baf6bfcf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3531","ciphertext":"f6b178b3764df4ddd4fb1b447d77f8c2cf8b37b782a93443d848f9c2b6b0fa60c59dfc906ede6675813e0f7407","nonce":"5cc3fc6a245a1540baf6bfce","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3532","ciphertext":"85ce32980f981bed9fe3672925412cf5149f10ad4a8970ed17a6c3f4d9d123a270d223fe3628d5f3d9b0e01f22","nonce":"5cc3fc6a245a1540baf6bfc9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3533","ciphertext":"c3c73b776ceba5e3fd39b54236bf6d8cc996ad2041e747b0eb66c6a731568937311e8552e6ec7ad5526f4180e0","nonce":"5cc3fc6a245a1540baf6bfc8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3534","ciphertext":"7e15a95406dddfb2e432c8ba76c1818c359cb7b39c4cae2af16dec658077eb36804dd3d70fc606034de4f93b4d","nonce":"5cc3fc6a245a1540baf6bfcb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3535","ciphertext":"a052fb5b5e6eeb8d496a84c233b9d591c45bdd61a857969cdc1091f2bacc4c2391dfa17603df035f1b9a61b936","nonce":"5cc3fc6a245a1540baf6bfca","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3536","ciphertext":"5e1f0dbca0d33698fc246a4d37d884500948f2edfb9aa37af10d514d825272c4131174ef8e4985894dac313443","nonce":"5cc3fc6a245a1540baf6bfc5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3537","ciphertext":"0db31d573d9990ea4f2c781a1acd4938f4505d615c83611cf17ba0d460c91ad09588b64a6e41fbf404c284c995","nonce":"5cc3fc6a245a1540baf6bfc4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3538","ciphertext":"9dd6cb8aa8e64ef6ba027d14f5c6188b0bc301fa34f8e2cc9aa664a8536c52d30b0b7c097b4bc2e3341a2fb76f","nonce":"5cc3fc6a245a1540baf6bfc7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3539","ciphertext":"d39bf39935ea0662caf6713f7d3d0170df9ec4fbc320617d5d79a3be86b954265dfab9666884a3fc2777a52d39","nonce":"5cc3fc6a245a1540baf6bfc6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3630","ciphertext":"86a62c3f098d02251640cd56e2080612f0f68b448e10d1b184566af024158c02ab18bc6b454ee90bf7818916d1","nonce":"5cc3fc6a245a1540baf6bfc1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3631","ciphertext":"12ccf8f98d23b50ac3a492459a50605f4f2183e5a697936447c3379adec9f598f55177cc038eb5de5a46de7a8d","nonce":"5cc3fc6a245a1540baf6bfc0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3632","ciphertext":"1ffa5c6297f5005890da2a521cd9ffb47787369404b246a4c4ca0b4633658496bd6e84653b22c9758490558010","nonce":"5cc3fc6a245a1540baf6bfc3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3633","ciphertext":"ca52f99e2da1f86ed22a72f5712f8b3c1df7798263231ab927348142133a50c14e7477a2a2d3e9d370d7d23564","nonce":"5cc3fc6a245a1540baf6bfc2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3634","ciphertext":"e6b76eab9262361f7b18062747a7fae1e9b014b83484b678534ea8cc1c674557d379634901906dc5d592420c71","nonce":"5cc3fc6a245a1540baf6bfbd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3635","ciphertext":"b5a6658c7ea4786658cf0b0612f83cecaa209bab1c757410d3ec5995f5c002417da08c4ecf9283fb968152ac50","nonce":"5cc3fc6a245a1540baf6bfbc","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3636","ciphertext":"96fa92dbc8c8a33bd4467dd0fa653f0332fac891f884db4e381a58a0ab5453c2f2b124ffb8a4bdcc280b9b71da","nonce":"5cc3fc6a245a1540baf6bfbf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3637","ciphertext":"fa9089924d92057bb35652f08fa172abbfdbc5e17e092ca8842c3fb7e09e3766c29c896d71b8206fd268bacbfe","nonce":"5cc3fc6a245a1540baf6bfbe","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3638","ciphertext":"4038462e61ae310aa49fac839d68c2588089da18726873c3e2d33e6da84e3f1a677455bd4a0e546d3e8754ed73","nonce":"5cc3fc6a245a1540baf6bfb9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3639","ciphertext":"69ae03f0b13f02099e07ad062bcf8796689f0221e6c3ad2b2694fce1c61c4d406859a4de9521bb5a36716566f4","nonce":"5cc3fc6a245a1540baf6bfb8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3730","ciphertext":"880c68cb57e18e631608175c8f636bc5543202eba2b35d56f188717deed18c355e2965c87de63ff30b2ddf857d","nonce":"5cc3fc6a245a1540baf6bfbb","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3731","ciphertext":"8fbacc6ae0078301c3387e5bea5af442e69953a0140993d6a4387c68d110ae4897e65c84ed2390052b06a137bf","nonce":"5cc3fc6a245a1540baf6bfba","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3732","ciphertext":"60bc09ed0af3ec3d344d131ccae369b1810418df3f2e77ab036a0fa85ce32dc3b95fd6f3b1b61b0a26f9a1886b","nonce":"5cc3fc6a245a1540baf6bfb5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3733","ciphertext":"b447a65a70da215c90c108313bb64436af35a3ecf9698b660021b36be4f7f5b36e00d52ec22d8e48678c980b0f","nonce":"5cc3fc6a245a1540baf6bfb4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3734","ciphertext":"8af71038fe82f05b8225c67ecfd00345973080075cdede638dd4f03cac3ebf2927be415f0ce17e0d764e8b2f5c","nonce":"5cc3fc6a245a1540baf6bfb7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3735","ciphertext":"fa3ed660ecdd875b2db532e2b0465dceb81bc964ffa0b0e5cb5662c6b1a84933dd6d3fe0a103f91bff2931f8c3","nonce":"5cc3fc6a245a1540baf6bfb6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3736","ciphertext":"75612a8087d7999311a69b561b09e0bcfd8fa82d3bbf851691b8864f4c541a730af190d2e42f48f86d4bfdf496","nonce":"5cc3fc6a245a1540baf6bfb1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3737","ciphertext":"cbea02c4c9d6cbe19eeba95628c94f9c8852d1041862b482039beff7aa94423e7196495548a2517639a511253c","nonce":"5cc3fc6a245a1540baf6bfb0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3738","ciphertext":"19967ac6f51f52210ee0d481fb910b6b8e5ee9455d9005b9c08467450b1d60d5bffe0ff8523379b4257ec3e78b","nonce":"5cc3fc6a245a1540baf6bfb3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3739","ciphertext":"49a6e8925493d4983248048bcf03ccd4df8a174d7aed6d7a38e75a75ec0934bc9cb3306e6c68f94c7f1d3339a4","nonce":"5cc3fc6a245a1540baf6bfb2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3830","ciphertext":"cc16adecc9dbb102b3ee897d0fd3f3ce28844897971dccdbd36fae5ebd7aa34f41a3dd62fe207816d478f2dbbb","nonce":"5cc3fc6a245a1540baf6bfad","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3831","ciphertext":"27f3d7312ce2e7d4358c16564aaad24629204f0885a081a1d7a85bbccd951d9a9bed2929bb3b6a2d3f5dc68a8c","nonce":"5cc3fc6a245a1540baf6bfac","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3832","ciphertext":"af5dbdec1977e485ec1f029a771fedd38da41a46202bf669dd52359eca9d79456b59c215817c4a198b9507405b","nonce":"5cc3fc6a245a1540baf6bfaf","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3833","ciphertext":"c5ca9f82f6a0fdb882c9d8fb6f9ff5004a1b98a3c8f0d41c09bf0547b2f91b1f6260dba879435cc9b1e08c28e0","nonce":"5cc3fc6a245a1540baf6bfae","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3834","ciphertext":"1c8453b258264f54dc51b353d232aa7fdacaf164e93dba6c10abecbc47097c0c69dde897a0e1869676d7e4bcec","nonce":"5cc3fc6a245a1540baf6bfa9","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3835","ciphertext":"c24e379d260ec9bce4ee281a21bc4d8b4805815079f734317d76ee02c271747a501304294777e2e22d7d6d6924","nonce":"5cc3fc6a245a1540baf6bfa8","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3836","ciphertext":"e221dea40087483d1ef3b3ca95f3e8807096e9329760397fc1d3de840fa7086cedb709f94a05f2a498ce18ffcf","nonce":"5cc3fc6a245a1540baf6bfab","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3837","ciphertext":"8e43be1a3f1124d4104c515d639dd94819e4c7d4f9eeddbb8ac0c893938d63037c2942db1b4ed82141bd0f6ec9","nonce":"5cc3fc6a245a1540baf6bfaa","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3838","ciphertext":"8d90ad8b06c140d5b3d838c6b38acd5ea8598f01700ee5fb53c00d19c10c5e20da1326b429df7ae4b8a828c4fd","nonce":"5cc3fc6a245a1540baf6bfa5","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3839","ciphertext":"cc78e3f8edf5fc1e6d2ee17c30ef2c05ef4c47b71738c409a427ee345d05d5da25bd89bc16c005a753da46f5c0","nonce":"5cc3fc6a245a1540baf6bfa4","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3930","ciphertext":"b864300180d64d8a31360e56bbe479b7875e832a9b069f42fcc00cbcebb50e6c1440454014c064e38162202ab3","nonce":"5cc3fc6a245a1540baf6bfa7","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3931","ciphertext":"89383e5ab87b2af27ea1b75944fe51fe94ba661b3bd5998c319c7edae5a651c92b8aeb7a7451a85d666d031be5","nonce":"5cc3fc6a245a1540baf6bfa6","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3932","ciphertext":"8de0763e150a7e12ff0357ba95e767ed4948800251ec8d604d12179ba48714188e11ae9c7658250362627051e6","nonce":"5cc3fc6a245a1540baf6bfa1","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3933","ciphertext":"5c07e9591c118bf69261edead60100d5f59c21124fa88b909fdc7dc4c74ec7dbc5e91f4ba677a41185bccfbb11","nonce":"5cc3fc6a245a1540baf6bfa0","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3934","ciphertext":"8ae213072ba48493b4ae25d682042fc48102d3cc77fe4907a6c33f373370228c9ff2b13225be477e6349858e8f","nonce":"5cc3fc6a245a1540baf6bfa3","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3935","ciphertext":"ddaae7123bf2d2f28ef865889c65bce5915440b587e3a6d30a1a9d7e27c5c26ec49d3b9255ffce6ba5f6c80b24","nonce":"5cc3fc6a245a1540baf6bfa2","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3936","ciphertext":"87eb384480b72fc6be211a863a2b23d0962849f12f88ba62b39ce33179ff43ce379255fd9faa5156ac2345842c","nonce":"5cc3fc6a245a1540baf6bf9d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3937","ciphertext":"308d871a1181dcd58f6faa42d1c624b5952a47c653dd4ce834b9f5f71827b950c89f79b7743a474e29796511d8","nonce":"5cc3fc6a245a1540baf6bf9c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3938","ciphertext":"a82ca583694ff0a5684cc1f23a2015e8c394d52236f1d85ff86c69a015f9e4c52d09ff46d697ebf40f29dcc2f5","nonce":"5cc3fc6a245a1540baf6bf9f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d3939","ciphertext":"52d9e71d4d7eee63c2e4879252e8e5e363b96143ea401bb6a7387b55f8e95e097273fb71162347ad86a91ac4e5","nonce":"5cc3fc6a245a1540baf6bf9e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313030","ciphertext":"4ccd7c35f0e18dbce58146cdbf1cf1eb6fd60a75fea1b01e5115550705fafd32f56d75ed59f13f76a10c235e12","nonce":"5cc3fc6a245a1540baf6bf99","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313031","ciphertext":"4446e5bd38334d9abae9f095fb5e5df105d0512dc856411b92a1b645fdc3038410b5fa530cfb26da780ff61c07","nonce":"5cc3fc6a245a1540baf6bf98","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313032","ciphertext":"1f8fa0b8535cb56738109c9cc3b0d3dda81d10ea301b9aeed7dd867f3a350531a6c32b8ba110569bcb4e748bdd","nonce":"5cc3fc6a245a1540baf6bf9b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313033","ciphertext":"9f3c9ff98696645322e0aaf1e74d6e298897bb570f9942ebd78a7443d547e2af0c3bc8d4b44ecc27fee77a9813","nonce":"5cc3fc6a245a1540baf6bf9a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313034","ciphertext":"744db1ee3c64151d9223563155e1bc513b7750cdf33d8fad4621cfae7c6083f2cfe43f6b72f1339519b9023528","nonce":"5cc3fc6a245a1540baf6bf95","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313035","ciphertext":"6c51501de74d944007dbf8a7637f9c358a16dc8b675bdef5828066826c4924bad329065ad52c7164e167b74a88","nonce":"5cc3fc6a245a1540baf6bf94","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313036","ciphertext":"496fc2fe882596708553cb7e4151dccab8940c194ae49eb317edc95b83e64a65a234f4cbd6857f5b93ea578adb","nonce":"5cc3fc6a245a1540baf6bf97","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313037","ciphertext":"7a2d6d0cbc536c747dacad7ea0f6acca424ff6680578609b9d2fde99d4dc9c202f05f63203b4142fa285d935c5","nonce":"5cc3fc6a245a1540baf6bf96","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313038","ciphertext":"ab3195d5109470395b934a51a7ce22582de2f889b66c63e9f2a166fb2ddec19b05bca691aa67ee30ec3f3962eb","nonce":"5cc3fc6a245a1540baf6bf91","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313039","ciphertext":"6d5960e4914c6f1c598792e86ac85a386c3668c3a516e50743d2f68d49c972daf75619820d6ec2abed6d4515f3","nonce":"5cc3fc6a245a1540baf6bf90","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313130","ciphertext":"a2ff031b42d2e627b1c846b52230a728d74e92b40940b1f8a7e1b629fabd542183060e2af6af785e796ba131cc","nonce":"5cc3fc6a245a1540baf6bf93","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313131","ciphertext":"17755c6aaa5e218df18c9f9256db8bb478724cdc2d679512720c8315a91c08ebfc4e5fef93691525ae4e2319fb","nonce":"5cc3fc6a245a1540baf6bf92","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313132","ciphertext":"c6adaa5510921eedfa685baac0454b492fe1e5daccd2439bcee0a6eded377821f4b73ec748609dfa3983b481a3","nonce":"5cc3fc6a245a1540baf6bf8d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313133","ciphertext":"1f0f2bdbf2993c3b34c63aa4f85123c22a15454ade8ad69a46ce8a3e14e1defed4023cb743674b1cb6acbea318","nonce":"5cc3fc6a245a1540baf6bf8c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313134","ciphertext":"39acd71467ae43fdf7c3d1cb0824c0e11647211e73142c6a8522a12d78956eaf3db47e72d5a452562670f58ed4","nonce":"5cc3fc6a245a1540baf6bf8f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313135","ciphertext":"d04eb5769bba68b2878f2292bc0ea8c3c50c0e1699cb09b2e2e25351e30cf091c6070b34d1d9d9a9cea00022cb","nonce":"5cc3fc6a245a1540baf6bf8e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313136","ciphertext":"0f2deb4ebd6d70be13fc38b26c7d421ef527a67d00985f80a4c665a4792bc117c970067df8f8566bdc12a8a868","nonce":"5cc3fc6a245a1540baf6bf89","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313137","ciphertext":"6463535e0b7cac474f0d8b8935dedf363f02d0cb801c9d4717f835549d9b938ba5410577c7b553cc958e8cb790","nonce":"5cc3fc6a245a1540baf6bf88","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313138","ciphertext":"202cdc8f704b126a21034be00b5b698c3045cfeb8de2a82f5316e25547a916ef0c94afd52d5c4b7d60d29c521b","nonce":"5cc3fc6a245a1540baf6bf8b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313139","ciphertext":"949ddff86f6c3ccb80fd5642d55531593b94387536a17dbed33e3fd7746253d424e0650f8e8bccc657af867b51","nonce":"5cc3fc6a245a1540baf6bf8a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313230","ciphertext":"06d4bbd8d67561b0772b7c17e5e8d9c5a9a9faeba0bbc149f065681bb5d745ba07e97c855d4aa8a09e9e1f1bf9","nonce":"5cc3fc6a245a1540baf6bf85","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313231","ciphertext":"9881b4748b22bac72b0f3f9c008b6a7f5c81a419deb96b24aeda114a470d17335be4421d5e42593f0b07dcfbcd","nonce":"5cc3fc6a245a1540baf6bf84","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313232","ciphertext":"b0b7f273e2ea21b8789c2f2c188113e03de5980dbad31e202d3c36a235e556daab6dd3247403c3011107621dd1","nonce":"5cc3fc6a245a1540baf6bf87","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313233","ciphertext":"cdc1ba111ed4c12cc718edd99eea28ed6496d909cc05913ba4130a46da553d98fd451a6727abdea2857e1a0250","nonce":"5cc3fc6a245a1540baf6bf86","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313234","ciphertext":"4e8e2573095c21f0f3e72d973033c05c1810e538e74c7e412ad152b1dde8164e857d46c85a73314e05b9ee585a","nonce":"5cc3fc6a245a1540baf6bf81","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313235","ciphertext":"f1b660fb37cbd1a80a526cc8e1187a21d184c1a0033ebb4b6167d51f6b8f16193ef4eb43377d442728ba6a25c6","nonce":"5cc3fc6a245a1540baf6bf80","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313236","ciphertext":"90ef169942e00ad4417d49cf1f553fe1e54db3ed1a5fb74391701c898d58444ffde9d1de8920b84288a51a756f","nonce":"5cc3fc6a245a1540baf6bf83","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313237","ciphertext":"a2f37bb95bb5864ac05277c71af439da70b91d677863e67e1f65ef577e284545dbdac7bbe99ef22b6786ba72a5","nonce":"5cc3fc6a245a1540baf6bf82","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313238","ciphertext":"c426ee40c12974c5130d5cacaa430a49bcc1d91c8371d32a3240c8d59e4547ca0f003bce4fa06e6829b8f8083a","nonce":"5cc3fc6a245a1540baf6bf7d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313239","ciphertext":"01466b33b670f32c721d52aade787834f1315c71550048de6478f4d0ee01875912b1e908984146deb3c167f873","nonce":"5cc3fc6a245a1540baf6bf7c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313330","ciphertext":"e8812403c3b954616e40904a357f50138a5ebf09c8101240a1af9ad74c085fff50cd886f800d577451bcdc1efb","nonce":"5cc3fc6a245a1540baf6bf7f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313331","ciphertext":"67d668ce5f48c88f7569d16f3ec85db86fdcaa97584716185080d6154dde7216893e6b6be7ae037f6d4115c5f1","nonce":"5cc3fc6a245a1540baf6bf7e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313332","ciphertext":"f372c941606b0432aa1b3a051e3da1d5f69b684e7495607773e278bc5d28c3d05c8564c1d92b59577aeb67d18d","nonce":"5cc3fc6a245a1540baf6bf79","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313333","ciphertext":"f2ad93354695466e46988d8a32dea6f2abc56529b59bcfc14b9e1ac4ab18d4bf7d5270003ff1d6dbd1cc0bea94","nonce":"5cc3fc6a245a1540baf6bf78","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313334","ciphertext":"9e6ab8b2e540e870aa2bd4be2a12e1fd37b43dc49276aca1451fb57059c6d4fcd114ac5f3dea7c700b18e1cd98","nonce":"5cc3fc6a245a1540baf6bf7b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313335","ciphertext":"83ea651f5cc242bcad1b5272f364b00754c33ad3adb56e6e04f8771029a0a7094eeaf74274d098b91ea10d3880","nonce":"5cc3fc6a245a1540baf6bf7a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313336","ciphertext":"eda4a8dbd39a7f70ac24234218bc6b253243a550df1c1c93a05ae6a2c246767042c357ba3c84c7c9e636c93d1e","nonce":"5cc3fc6a245a1540baf6bf75","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313337","ciphertext":"e697e2870f947cb60632cf559b8048da26c81193aff1dc88a900e33ce3a5a603a4a79429eb33e24ef3b4b729dd","nonce":"5cc3fc6a245a1540baf6bf74","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313338","ciphertext":"3709a19e17cb5a0a49ba1d2f647d84b61416efcaedd78e196385741e97e349d048c4b2751b34723e8ff693c1c4","nonce":"5cc3fc6a245a1540baf6bf77","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313339","ciphertext":"eedbae14823dd61aa123e2a36792333be2edd4a2828794dde2039025094b072ea0e127aaa23252ec131944ae2d","nonce":"5cc3fc6a245a1540baf6bf76","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313430","ciphertext":"3258d395121f3e0063f83de08c230c0dbffe19502711cc24818eac0dcad1f08531e645f32f3a6a7cd79df2b40c","nonce":"5cc3fc6a245a1540baf6bf71","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313431","ciphertext":"ba945bad2dbe8053ce97174dda70a979810b1c2d60a5545431bb62fbb26597f8394ab79fad3d882b45bc552a2f","nonce":"5cc3fc6a245a1540baf6bf70","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313432","ciphertext":"c2d0e66342ebb3618d24dd2a18d160ef7f12dea34cd06c33b454044910113dcdfcf4adf1de3c5431f7c0233de8","nonce":"5cc3fc6a245a1540baf6bf73","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313433","ciphertext":"941cfe6d9ea9148e1d98461b57a219a381b238afd4e116159a9e3a1d70e046d932d0deacf30b1ebbdcc47aa571","nonce":"5cc3fc6a245a1540baf6bf72","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313434","ciphertext":"15ad86186052d8523ee295d31c083d1e47d73479648257483eed6984a64e3aa1acfd048aa03905b5610f444e45","nonce":"5cc3fc6a245a1540baf6bf6d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313435","ciphertext":"68028c4def89168a69ae83fb10e708408ce035bcb60eee9baa08baf4b982faf81725e9676c96bcb41c05cff3d4","nonce":"5cc3fc6a245a1540baf6bf6c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313436","ciphertext":"f55aaf751edf99e4f4a298790eef34e4998a70b04b51fcdea4846856fa9faff35fe59427eea465dbb208443453","nonce":"5cc3fc6a245a1540baf6bf6f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313437","ciphertext":"f093968afb65b1c5bb8304d3cf50056f44a3893c1d55b451a4c7248b4f466674b79bc9cdea74bb7b7250c40710","nonce":"5cc3fc6a245a1540baf6bf6e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313438","ciphertext":"dc76668f27cddd524dcc667806d47712133d7b6466315ff9785183822c371f5b95bbea8fd0f9c156220d945dd1","nonce":"5cc3fc6a245a1540baf6bf69","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313439","ciphertext":"6158cdb679c3851aa8d38b36bb12978e8e026da3ff71b45dd6f771e12a95b6931b28b3d3c068e6ad33ceebe45d","nonce":"5cc3fc6a245a1540baf6bf68","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313530","ciphertext":"1022b106a0c5d12bea97ab849ee38123ee7a6460e3ae1f3ed8930636cd48e3920f088c6189b39f6c914f7548b9","nonce":"5cc3fc6a245a1540baf6bf6b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313531","ciphertext":"0b784c5e25a6018313c2cf0f37511e2aa9e165418e02f0af333c167b2377965fac0f741e2b219726ac0c68ae07","nonce":"5cc3fc6a245a1540baf6bf6a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313532","ciphertext":"88392ced798e1025d19b5cc10824c787369f412b65777996fc6836cd4405dcb84d5784a8bac843b7a8aee5a5b8","nonce":"5cc3fc6a245a1540baf6bf65","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313533","ciphertext":"bf64b0819de42b7d0fad0bf882c6d2dc4a09b7fbc7c5c3fdcab78c1c87261e02154ddb00d6543827216764d567","nonce":"5cc3fc6a245a1540baf6bf64","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313534","ciphertext":"b374a295e539d911122aa69c6ca7680b09e190f7c818c05ba183d0acf89600c5bb88e2e15b1d8b2542299e5f30","nonce":"5cc3fc6a245a1540baf6bf67","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313535","ciphertext":"d968cc6e281081588d220f6716330e26097721608efde58a39d2bae4df81f5ed5c1d682a5e29ecf3ae398fd985","nonce":"5cc3fc6a245a1540baf6bf66","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313536","ciphertext":"e464267611b23d2c989b048fdb75645cb8ad39a30d88620fe2ca8d1153c269514f8ea88c5bdb4bc1a3cc5844ee","nonce":"5cc3fc6a245a1540baf6bf61","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313537","ciphertext":"04e54e65984412da8b6573576719c875058aaeed049aa08d26302f3327ec55a6153e55c5cbf78e57785d63bb58","nonce":"5cc3fc6a245a1540baf6bf60","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313538","ciphertext":"9e9e2abfda84ca3c5c3ebb96f587881198df8f16581ebbea08ef43f0ab0e1cf8470f1aee6172620c039bdc4523","nonce":"5cc3fc6a245a1540baf6bf63","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313539","ciphertext":"5ea763293a22716245e55c39bd6df39a244e429951ea5e00a0b18b130312c81c1c7c1256415c8c878c108d1c39","nonce":"5cc3fc6a245a1540baf6bf62","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313630","ciphertext":"3d9e701da16ab49f60dd3621bf7808cb3bd263f8f32e7b358fd0d3127a2fa13323d65e29edcf74f8995e0e365b","nonce":"5cc3fc6a245a1540baf6bf5d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313631","ciphertext":"5ff8ca6fb69df97d2b928a29849977b4bbe70f714799c719d37910a6214a7d10fd403fb446d80fdbb3b9353cc5","nonce":"5cc3fc6a245a1540baf6bf5c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313632","ciphertext":"cf9bee76d58e0528256be365382141a6696e2cb5f5103e870d2acd9061b43dad1c756e796755175ddcb9b6e3fb","nonce":"5cc3fc6a245a1540baf6bf5f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313633","ciphertext":"e75121ed50325d8067a60a0ebc34aba119d1fde27fbcb7cdfbc3fef0c4f49eb480d78313ac6f0c6f28ab8a8b7c","nonce":"5cc3fc6a245a1540baf6bf5e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313634","ciphertext":"04861708c791cdcd4241f91ccf4a662a4db0048cedc588eb79bf130fda42e670e5eca3f3c95442e80b20d684ce","nonce":"5cc3fc6a245a1540baf6bf59","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313635","ciphertext":"a1a39c4a6ae8f74aeecd2c6877a1dcada5bc2281a4310ac7467b513b52641bac87272b23ff64e4033377c8f95c","nonce":"5cc3fc6a245a1540baf6bf58","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313636","ciphertext":"16ec202ded2204cf419e7072d3f56e1e50bdb5605b22e7a2567331508feb7bb3b2c746b860b1df513aca4c474f","nonce":"5cc3fc6a245a1540baf6bf5b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313637","ciphertext":"d85dec7d15413c79ef1768bc0301c6cfa9f84636acf431fb217e00916786fb8c8bdbefa17a0897be5ebec8379b","nonce":"5cc3fc6a245a1540baf6bf5a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313638","ciphertext":"923f58e1349f37e7b0685f83b5468695314921d0b1c612551d9a8bdc0f278b4d8b6eb82b000fb9bd2ea95a74cc","nonce":"5cc3fc6a245a1540baf6bf55","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313639","ciphertext":"3732ad9771a2d1ed869d4a6da6625bc58e479bbe5732a3479fbde8d3fc1c9786f16785591c2ea067e650acde0e","nonce":"5cc3fc6a245a1540baf6bf54","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313730","ciphertext":"0e0b3eb549b2685e16e5cc45b69e112e615137e3b641aa43269f044431527bf71af7eff9e711bc0f3babf7db62","nonce":"5cc3fc6a245a1540baf6bf57","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313731","ciphertext":"99fb7b6c6e539608ec8bc4eeae7a6d82087502826ffe4dbafbca3c3b31d35bed18d346a2291d7af34d6e3e6015","nonce":"5cc3fc6a245a1540baf6bf56","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313732","ciphertext":"9a6fea7a11a14fac40fab4da094a9a245d49781ef5e82d1a2b7aa7cf0b1afb255439924a9d002fbb1490e31ec9","nonce":"5cc3fc6a245a1540baf6bf51","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313733","ciphertext":"eb3b0dabf4b4cad37711d3f3524dc4daef964e474bd1819a6e95d479a9818c4be7be2f2fdf20a1def0de396880","nonce":"5cc3fc6a245a1540baf6bf50","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313734","ciphertext":"19e1b116e7631a8cced99a4057be75ee4d484a8a2a4582bd26ac5692e57046889752a31c18bc51b8c892b37be5","nonce":"5cc3fc6a245a1540baf6bf53","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313735","ciphertext":"9324f8d82871b64a07d6578cd93aeea60e03529100e259c16cbf34ec9206426db060360bff2cca57612ca06b1c","nonce":"5cc3fc6a245a1540baf6bf52","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313736","ciphertext":"565b35c04315322e4d7c8148e7f9feaa183d6168f39e662b3e88230581f34d36c6bfb92df2c67fbf61cbdc7b06","nonce":"5cc3fc6a245a1540baf6bf4d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313737","ciphertext":"ceebec800954b803eee38a10fc98c548482902e9b621d1f102c466a46f9358ad812ebbf4f71502336aba82868e","nonce":"5cc3fc6a245a1540baf6bf4c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313738","ciphertext":"2a0563a8ac8873f3fca2aedd239fe741065b273c1c7080baabf5fc09095c794030feee006f81f50799d2079121","nonce":"5cc3fc6a245a1540baf6bf4f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313739","ciphertext":"9713d092782069975af9ff7dbc0a8f4014f2c9aa3a2b44ed5cde59b4eec0b94c3aa553e7f429ea7671ff4ab66a","nonce":"5cc3fc6a245a1540baf6bf4e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313830","ciphertext":"31df356dfa731f8b67f045a9e9bf2856c38df4c36f9705d9781c42282a3f750836c2cd6a25211f3e44bff05261","nonce":"5cc3fc6a245a1540baf6bf49","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313831","ciphertext":"67719b1eb8f90af872ba3ffb132f15cf8edf95d7e97e35c864e0bd5662c04840b2c44c42c0ce0683ac6e6451d4","nonce":"5cc3fc6a245a1540baf6bf48","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313832","ciphertext":"4923d40028a1fdad391d3f5bedc4a00386e0ddc526b2f122311174175999b67383edd5b74f5150248f73c543d1","nonce":"5cc3fc6a245a1540baf6bf4b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313833","ciphertext":"1057b094bedafab1528c72909764f8f7a903b6365f4fba414999821b14de56b67d32072b5f48199ae7d0a8da4c","nonce":"5cc3fc6a245a1540baf6bf4a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313834","ciphertext":"4d46bbb9537772277af9cef3c1608224c587e4ebab6d6c6642844b626aaf653c9fb3107a49cc4f56eff41da0a5","nonce":"5cc3fc6a245a1540baf6bf45","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313835","ciphertext":"cab9da63acd8d08503e5968e54166ed19b90906a14459d93793ccb01ea84e1581869ff1fdf5aeaaa20039bcb83","nonce":"5cc3fc6a245a1540baf6bf44","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313836","ciphertext":"51a9317e71c3e91ebc85446d635d06e46163eb3afaeb9db4fc3d5a9a01aba30d59649b5b3a72a9f41e799f07e7","nonce":"5cc3fc6a245a1540baf6bf47","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313837","ciphertext":"dbe8aab4f4585835ae868e2c329b221a54e49e9ff8b420a3987b668d57aa8bad4b8559c02b76f0aef960b0a6bb","nonce":"5cc3fc6a245a1540baf6bf46","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313838","ciphertext":"d8222b45f508a0fd77c6171841098abf16d20771c0b26fa7d9d0bf49797e36244ad64c1a9f2312aa9303fbc08d","nonce":"5cc3fc6a245a1540baf6bf41","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313839","ciphertext":"f1aec9e47887fa1bd3a8a9c93634e393a154194545695c76e3f2bcffd523c9fefbdc9da58f88d5ee06538cae60","nonce":"5cc3fc6a245a1540baf6bf40","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313930","ciphertext":"a96be02ff98df4724a76fa33a5a6c2fc669d9d1df6aa031fdffedd4f61106ddb330f25a0dd80c3bf778913204a","nonce":"5cc3fc6a245a1540baf6bf43","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313931","ciphertext":"56bc74e820c1f9fa94a4994c8867a24c97ecafcb8493e888bd0c267e4ff125d044f797d01db80d334547104e43","nonce":"5cc3fc6a245a1540baf6bf42","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313932","ciphertext":"d71ef56b9f3e0b1ffb1007a899f71199178f2999ac28a7b39dd023ee5d19c0a88dc8085a9f085cd210e768b035","nonce":"5cc3fc6a245a1540baf6bf3d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313933","ciphertext":"b4fafc8bc319d216bc19cf31aa324fa8b96a960930bd82562f7d2f42eec7e76a04321c31d0101858e825954311","nonce":"5cc3fc6a245a1540baf6bf3c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313934","ciphertext":"b73f61ef9cd17768cff763f07198e491d1b7eff9216945615a2c5a17a98895e826939f6c9f7d2d3db386decdad","nonce":"5cc3fc6a245a1540baf6bf3f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313935","ciphertext":"55a638813f28a6256b729c3199b72412a8dd655f7b4ff82bdda188c18b077ad39f47c1d170631fab0fec3cedde","nonce":"5cc3fc6a245a1540baf6bf3e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313936","ciphertext":"bcb9c5b30ef5cd0cad05337d2403fbd8fc87c70a9f92f70050e7544e238fbe7d87f025397dc928b0e894f5b195","nonce":"5cc3fc6a245a1540baf6bf39","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313937","ciphertext":"f577ea6b432913eb07f3ce5aa4e2a5d5e03308b06fd1160bd44f7fcbf5fc522a336bf61b21300d55ff407130fe","nonce":"5cc3fc6a245a1540baf6bf38","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313938","ciphertext":"3720c54d514ba690d0e10ba553db184213fc22d6aa1f263361b36a3e53897374a6393eec9f440cae6700c88c9b","nonce":"5cc3fc6a245a1540baf6bf3b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d313939","ciphertext":"ea4fdf3be486d8cdb2180d0a771b178bbb43fc122fc2b663695b22b2a147bfcb5af3297d9a57cdc58314adc215","nonce":"5cc3fc6a245a1540baf6bf3a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323030","ciphertext":"11afc4190190c8501c3685976dd61e4a4a779faa24dfaab70ef4f9e31999e3cb05550d18a4df4dd79f5f652bc0","nonce":"5cc3fc6a245a1540baf6bf35","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323031","ciphertext":"7880af7fda19129ff155d9d1e2101b2bcc1cea1c473b923f3080fa1b2236216158b86919e894988b94900a2a0c","nonce":"5cc3fc6a245a1540baf6bf34","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323032","ciphertext":"7727a2f13963eeb6d1a2a3dc37b09c5c84c88c2e85841347d536b2e793fca6835ead23926edf6b3140d10cec53","nonce":"5cc3fc6a245a1540baf6bf37","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323033","ciphertext":"e93e112778861e795554eef85ca881eda32269051c3c67d2f55593eb5446a8899e99172d5e2c26e123b484b3ef","nonce":"5cc3fc6a245a1540baf6bf36","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323034","ciphertext":"b3834486e3bc29d6c7940216e162cbcc13cef132f764245ffa3e9a5334dec0a4048dc24a21f3a162152ac79f33","nonce":"5cc3fc6a245a1540baf6bf31","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323035","ciphertext":"d3403a28912d4c046aeafd750fb4c7ab5fede3681f5c4331e664ee3d15db58b1b3db1e3d7611aa6a40fb7e27e1","nonce":"5cc3fc6a245a1540baf6bf30","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323036","ciphertext":"caf612ca90ef9acf100e7254177e739daed7f983b530614cfe958c5e695bdbc037fa93eb0cd2bde91bd5cb3a55","nonce":"5cc3fc6a245a1540baf6bf33","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323037","ciphertext":"a4384537b741cb77f2a4bbe5081512b8c06171ac84e979025ddedf1822a595014da1baed13658686fe9159636d","nonce":"5cc3fc6a245a1540baf6bf32","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323038","ciphertext":"dc9bbd8dda9db90ef5c6a55495e04230153fd0e2af460b76c3e3c5c99f000d5459b59fc778b6348156c2f4186e","nonce":"5cc3fc6a245a1540baf6bf2d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323039","ciphertext":"d67e11e311e3df7b54446c16a5036ecae157f60c5c6f759156aaf80a7263c9e0a539d1951a42cc785831b2eeb2","nonce":"5cc3fc6a245a1540baf6bf2c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323130","ciphertext":"f14e4676b6de6a1c5ee4ee7eb2ab0aa84f19ce3b385f3d85eeb7d4db5c14bbe164f9931dd646b0aba131325d36","nonce":"5cc3fc6a245a1540baf6bf2f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323131","ciphertext":"0b35cfba5822ed5dcdd8467fae314d0e38d4b6df5be3fbaf565f42474da3312c0f69396b95a6d7b21341cee500","nonce":"5cc3fc6a245a1540baf6bf2e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323132","ciphertext":"6bd2c81cf275b92b358cf6908e260ab2f133a5e0b3dc20b52ad1310c7b44ed33ac164d94f78c65ba73785c6713","nonce":"5cc3fc6a245a1540baf6bf29","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323133","ciphertext":"26a3d888839362d1c8c7de418e3b57e9bbc3a187b430d0f0056a9c6849708d69cede109e22bf3e1a4dd0e3eb1b","nonce":"5cc3fc6a245a1540baf6bf28","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323134","ciphertext":"7d6bcdbb323a0c13c86766b56c0d77e9d144638abe7bed8bbdf0eba3873a19cf36590062914de989cb3c762ecc","nonce":"5cc3fc6a245a1540baf6bf2b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323135","ciphertext":"5ecd38ab8418e35fc605cfe6d2b9adc08001eedfc77ec13fe422d69c9902dd68b6ab64e90878b0d38251361289","nonce":"5cc3fc6a245a1540baf6bf2a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323136","ciphertext":"58fecdd76ebc8c51cc90b5705b0e0ff540429dded92359b863f95e1031bccb74920dffbba7641e1242240019bf","nonce":"5cc3fc6a245a1540baf6bf25","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323137","ciphertext":"d37003b62df7e78740078106a2e24e7212b6b5e3d01b135b4fb21bcfff11d7b8cad9f8d9559ae0acf2be1f941a","nonce":"5cc3fc6a245a1540baf6bf24","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323138","ciphertext":"4f0819af01bbe7658814e44b91794c6a67f0dee26f75d6ad913d98ee85a4f02e7e898b8d61cbd9771a338cfe80","nonce":"5cc3fc6a245a1540baf6bf27","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323139","ciphertext":"635e0c4af941c1e84b7ca880280300b0e60e76731884639621bff67e9c17b8ddb3980acb61377dc6d3c159a4a2","nonce":"5cc3fc6a245a1540baf6bf26","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323230","ciphertext":"dd75c072eb2deb730ecb82283f8d446d58ef7d058dbb05647f35873a3afc1b246c1307cbb963b84834b35b8123","nonce":"5cc3fc6a245a1540baf6bf21","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323231","ciphertext":"33c1f6bda42b64d5c6f2a258133d75f5845f1e23f82dee9411108090c8be39e72509ec14e9e99b886c282252e2","nonce":"5cc3fc6a245a1540baf6bf20","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323232","ciphertext":"122807583d28fab290d93ad15f983f6bc60af219a0e98fa75079cd0ea6da069f352bc4eda1d0e3b0b947fea492","nonce":"5cc3fc6a245a1540baf6bf23","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323233","ciphertext":"4a8f981b8b991dc74e93fbde4827313a44b32ce15aeb3d232f8da251a25343ca6141178004c9c728f5804e05a8","nonce":"5cc3fc6a245a1540baf6bf22","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323234","ciphertext":"4d458b683ca233ea9a7cfc2f5beb1b3d560ec450ee59abd9c3587c50b2d4f19997ee185930c98472ddf40827f9","nonce":"5cc3fc6a245a1540baf6bf1d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323235","ciphertext":"3a9c2ef319ce120e30bfd074adc5e8bdfd9a4e12312d4818b3e2bc6ff5141c057810d3cfcde6e13057f3ad9925","nonce":"5cc3fc6a245a1540baf6bf1c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323236","ciphertext":"87a3df10f5229432a0fb91bedaec0933fe55f93fe7a359ad6bb1598a2e30a2fc0bdfcebdb38b659df1216223df","nonce":"5cc3fc6a245a1540baf6bf1f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323237","ciphertext":"e6397d7cb845473c4e93fc473a9cc5abc3f90f9fda77236803e83a905d68e002a6455cb1c8c7c6ec5e39bba84a","nonce":"5cc3fc6a245a1540baf6bf1e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323238","ciphertext":"8d715bf1366e09af16a8a4ff81975be5763282888215d7db7ec9840b06ea471f66b08cba2497db1ded40e83592","nonce":"5cc3fc6a245a1540baf6bf19","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323239","ciphertext":"637221019b87abc1509b62ba6f92c3829b42120a4f66c24e469c4f0228116c16e51cc4446ac7795efad4b5d04f","nonce":"5cc3fc6a245a1540baf6bf18","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323330","ciphertext":"226f808262ca542ca04529836603d9e7dfe6db5275df5a5568526379cb59324cf51a26ff528d036acd58c14709","nonce":"5cc3fc6a245a1540baf6bf1b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323331","ciphertext":"65376e0645056775352f80b03f9a87dd8764dabfb81855984304a45bf4c80fbd7a588a7c57b23a749ebecd194e","nonce":"5cc3fc6a245a1540baf6bf1a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323332","ciphertext":"089b78b2b1e0b5384c780a018b60b7849e42f834e7088ff910aa609a69026657624abd3fdb8112cf9172d45a79","nonce":"5cc3fc6a245a1540baf6bf15","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323333","ciphertext":"7a914f7c1be96bd191e16a46775569312afdeeb1149f30655f1b8f778a728d5c107cac74bb5bc25b32990d47a0","nonce":"5cc3fc6a245a1540baf6bf14","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323334","ciphertext":"794efcf5010224b24ddddb0085cee8f7594da01fa81420f7052550bf79fd0e2d90034d57f9ddc53a6389f85af4","nonce":"5cc3fc6a245a1540baf6bf17","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323335","ciphertext":"c7aaec73b2184d11be4d9ce0eb4809eb423209e371d505f0c359dd8cb5eaf9b9af401e6ea4747158b5b3206437","nonce":"5cc3fc6a245a1540baf6bf16","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323336","ciphertext":"4d4142a33dea73db006e1b65dd596a112baf42d58e759bfd7efd467ea0188ba1015eb8d91e61dbcbb9cf22061b","nonce":"5cc3fc6a245a1540baf6bf11","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323337","ciphertext":"f429c02c706fb2c7deaf13bf78a40a10f249897044f9a9176a814c9551b3858fc1d8f64670246e474f8a43bb14","nonce":"5cc3fc6a245a1540baf6bf10","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323338","ciphertext":"c8ffa0fa098fdd924d39d53b55c586ea81d23f34e3450ddb737f85794db064c29546435afed95e82cab064225a","nonce":"5cc3fc6a245a1540baf6bf13","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323339","ciphertext":"a42f0c138f085a31987f9950d123d3fb963b043c3492d0d0b0be5ab0ecee3cb2722eefa3ae1362bf5ae81752ed","nonce":"5cc3fc6a245a1540baf6bf12","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323430","ciphertext":"281781650b67734af57a5ddf3f77312dd3b1e9fc5f16a04127a58ad2b15f5b8f6bef11cca5bd11c8cad2a9522d","nonce":"5cc3fc6a245a1540baf6bf0d","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323431","ciphertext":"732f974f6686d24665b1838b5ac4c96713ef3c664b87c918971c8cdee943b58ad89951a14debf44491cb450f54","nonce":"5cc3fc6a245a1540baf6bf0c","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323432","ciphertext":"608e3962495c554e6089277c75bf4c6e966371c050610c778a12fba6f5e416e96671b9eb5a3649762bbfa50556","nonce":"5cc3fc6a245a1540baf6bf0f","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323433","ciphertext":"5fb4d4e9bfc172d9df883daea04005062558a0269679d0b304ade2bf406c76e1a336f42bb7df0db024a13041ac","nonce":"5cc3fc6a245a1540baf6bf0e","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323434","ciphertext":"e63826be7c1c72ef3293b2225dd708ca04f5ca9d23b1b1e9471db0f930c5ba78c8057c4f45510d1acff9a7eaf0","nonce":"5cc3fc6a245a1540baf6bf09","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323435","ciphertext":"6047af551e1b3df632d2b073025c1ffa75f3d6cc7957f1967c8670e4118e60ae0cb914a9ff7948915ac2acd31e","nonce":"5cc3fc6a245a1540baf6bf08","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323436","ciphertext":"ba9095f23e6c228d2a92ed25051e64d0a87e1e6e81b06347d138052571b4918e1ff126d0f3e73b757cdefe97b7","nonce":"5cc3fc6a245a1540baf6bf0b","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323437","ciphertext":"98f6d089dec8f3092c24f9c00a67b332cb2707c68fb7fad8f61fa2fa872bcbf930a04077973c5125aadfd1a908","nonce":"5cc3fc6a245a1540baf6bf0a","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323438","ciphertext":"bb19ee7c52613e792dd4a82e404e237b6f34d7fd661ce4f800e1a51b787d89e52b31a02dc1cd823f9c5f40837a","nonce":"5cc3fc6a245a1540baf6bf05","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323439","ciphertext":"9654c4ce2bea61636f1f66c5a5a73cd4d22eff06443369c6b409102812356737f9266df485a1a55a7274aa0072","nonce":"5cc3fc6a245a1540baf6bf04","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323530","ciphertext":"183d26704468e4b4035b4891aaba5caf8306555fec77b03a4df428964d6285511ec747154003c27373eb33e42a","nonce":"5cc3fc6a245a1540baf6bf07","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323531","ciphertext":"95cedede4524a74b37d1de7a0b329267499eb90322894920cc9255e39cdba0f25ff5d7e437159fbb6b474f816f","nonce":"5cc3fc6a245a1540baf6bf06","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323532","ciphertext":"3b329e22675bab92bcb5f59ccf4939e5434e83dfaef73df4882e4ddf6d8a85cb3897f7e51754f6fee97d1f2934","nonce":"5cc3fc6a245a1540baf6bf01","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323533","ciphertext":"b8480dac918c1702efd6d9451b6407e1367e186021a1ebdabed4be1e9726d2bcac4195c127f189212a3cbdb562","nonce":"5cc3fc6a245a1540baf6bf00","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323534","ciphertext":"017cbd30b2d4bbda5a706947eda476a3ca211c5b90774f7ef917de47e0ceda6dfa4bc196ae419c8906d98d4b85","nonce":"5cc3fc6a245a1540baf6bf03","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323535","ciphertext":"44c6d977ad3c4b21aa61cf4f7ab43f68a2ad40a8c90cf1aed7ab55fcc94334090bf4068ff7ee67100487025ba2","nonce":"5cc3fc6a245a1540baf6bf02","plaintext":"4265617574792069732074727574682c20747275746820626561757479"},{"aad":"436f756e742d323536","ciphertext":"ca7967fec7573b5b9a5c048c5b3ccf9e38603cfb59e4532d6ea0de9ae2a3bfe71414ad8abd098832ad413a2c4a","nonce":"5cc3fc6a245a1540baf6befd","plaintext":"4265617574792069732074727574682c20747275746820626561757479"}],"exports":[{"exporter_context":"","L":32,"exported_value":"388e62a8bc273fffa2c5cc029aec065d85477b76d1284c78dac1c058dba18b39"},{"exporter_context":"00","L":32,"exported_value":"981476f837a66804fe79b5b0b75cdafb79586b86305d772d42cce7f28a709255"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"3d997e9d631cfdad97b4c4202bbb1bf50a1124f32b6d0d62d6be8f49d0f60e53"}]},{"mode":0,"kem_id":18,"kdf_id":3,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"27ccf7cfd7e4f484f562e1749d43a1ad40482ba7be8a6984c888f9e216e129b02b39394abf90f4e64652ac9c7059900d71b77c6e35a030c7ad718adf398358ab9f8a","ikmE":"7a2e07a886511dce76d4f91cce69080713bebe7cb37cce118e18f15c0d1e0a6e0cc84043aef110c8506b2e6f83ba946201c7edb960a6ea61d7365736afc1555dd035","skRm":"011d1b47e44e75fe11b77fed23168155dbc3daa11630911fd7f791610220ea78760012306cac3a47c7b8438854ca35d7b4aeb2eb78ff01a913896dfd34a621ee39f8","skEm":"00cc3450071e3c521657d17032d6cd3f4868e773b5576e8e300f0e1f90ae707107ab4ad2b4e510df9c1216bdb49cd887a7f9b6e8f379000f06ab6d2ce83ce2fd461c","pkRm":"0400137162861f18ef7daae6b0d5d67bdff9c49f0b54e24eea94bcb2846ebf40e628a20d131910abbae857f051c94844abd6c657b4695e5eabd7e582d3aea65ec19c3500dc34eedd5c5fbe447553a621950bb86b6e7528faa0242f6e48638d6dd556f4add644208e7ec5369869f8a3efd66c48630340fc9b8c7ad1feb10a47a207ad3e6785","pkEm":"0400aa9330c24ac5993a4a593dd9b7b48ba4c0b8367c298b0c9f2762d9289ea4e9b21a97766aa29aaef6a1e602aefdac1c5ae86b754023af0730f7de4d7050a490838001d3290482ae33f4613d616071beedc5300121de4183f15cf0ebb092fec9876f054c5cc9a0d5b85f06b0e65bf0f68fd0bef717540b25e82012e05f543cbf825f0f2a","enc":"0400aa9330c24ac5993a4a593dd9b7b48ba4c0b8367c298b0c9f2762d9289ea4e9b21a97766aa29aaef6a1e602aefdac1c5ae86b754023af0730f7de4d7050a490838001d3290482ae33f4613d616071beedc5300121de4183f15cf0ebb092fec9876f054c5cc9a0d5b85f06b0e65bf0f68fd0bef717540b25e82012e05f543cbf825f0f2a","shared_secret":"06f2e4495a94a9b5e7893cdd65f5da2d1ea24a6c2c3bd2f163fca4316a1fb371f64482eb7808d75ca72e013b8a8f71e7fcbf799e91aa2edb73b6542e2c5ba197","key_schedule_context":"00e61f42c12d5c0c82d55c04b7352e7e6c6e958c77f5e6634997eb731b73acef61057b2dfa6f9f246c24be60685edf1a525c8cc473f6f3cebab5abdd73d01414d1875ca98065a7ca3f2be4e8b6c32ebcfe5e25c6f0ed8d6723cd6f24cd0dc258d80ee0c9339696e1eef5fd9337f77057357273e5a8fc62afc59761ce830cbec4f6","secret":"bf0e591bd2dabe5a07f1671cf215742b81c0949ae42aa56d82d419e7f7e885e198d4b1ce8c672f3261e133ecbdbfd18586bcbc4b62f8f441e9eadd75cf0d3ae5","key":"","base_nonce":"","exporter_secret":"0a2e2ed89f4a556fb0949d3f36c9e789e8782c9d3d74537354b984b5051aa2178a87d068c99163ca1951d8488b01edbb1a6afaa46df9d33e7e5308fb02b3e963","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"baa93ce84fab65a17c26efcdd09337364a8ae615e43c158d0d20957d7fa7a236"},{"exporter_context":"00","L":32,"exported_value":"e40faac079b9c76fec99a6394bbe787058358cb12078665778894c2637429c1f"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"d55cb7a587e73b42ca6fe636dfaa53898a576d5fdb50a0a53b0950125eea0f60"}]},{"mode":1,"kem_id":18,"kdf_id":3,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"2ab4c553f75199a81fe3e177ef2247154a7cfc0833d091759d224740d9360a295faa376e105d5c795e050a3a56665265f698c5c6743a9caeb809f4e41e18f9a7a691","ikmE":"5b726ded6ce117a4f2c12de53ac2e93fe4f177deebe5f61d544cd672492ada887c6f628e9e56ef6b360bea5232a630622c015ecdb494c17dbf90edc64e061f185dd0","skRm":"014a2f7a31fdebc8f09e909554a539ac6929e28726783bbfc2c261a1c63651e2bba7ce530112ddfa36a3a4fc6357ed817e0e72bec5f39c063b370b64066362f89cff","skEm":"0147dac4102f89c2bee0448c6503980ed2fc3a4f08aa0b865bc48e1235995c9eed143ac4840a3f1f4989b58e07e8545371304ec72f393ef278303ed9c88357858212","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"040025474ccef041523b621c43887f1baa7a009f5c9d06e9a0be5d1ac511ca9fed92e03ba372c7d40212e015156967cd0144efb26a20a3caedc948a565c7c109415fdd009e8a835b78f7afbb2674710d807e6fac1853ae40b64e97a39eef48039cf2b8bbef857b2db831d7762735093048f5d11a6f5ed642e4c9119bfdc2f01bc15229568d","pkEm":"04012b7f56e517620692dd0ff559257079599f27225d9d8b81d7505925eba1319997bea27cf460a0187eb148089dff883b3946f75e0ffca90c85d6699b7d5103fa2ea301864a49506ef4b64d88a1c23be0065cbe858c4e2fbddcd55d63739430846788924cfae86d576f10ff5432825d877c67082dbe4cf04c58da0685ab4126221159dc1c","enc":"04012b7f56e517620692dd0ff559257079599f27225d9d8b81d7505925eba1319997bea27cf460a0187eb148089dff883b3946f75e0ffca90c85d6699b7d5103fa2ea301864a49506ef4b64d88a1c23be0065cbe858c4e2fbddcd55d63739430846788924cfae86d576f10ff5432825d877c67082dbe4cf04c58da0685ab4126221159dc1c","shared_secret":"dfa481cc11f8fef01204cf23b92989e18f725e59af5fc6a61fbddb5547705e4bb78dfa31a0f35b50591b58a11294a2da8b4ebba0c22d5788766a97dcf856ad7f","key_schedule_context":"01c812270f9eefe05d307a98ba602a3428bf46753891b005db953c031c2e27538557a2f6d972182bc516aaeec4e6b57fad3f65687a5f17d70ad3fabbab45be339d875ca98065a7ca3f2be4e8b6c32ebcfe5e25c6f0ed8d6723cd6f24cd0dc258d80ee0c9339696e1eef5fd9337f77057357273e5a8fc62afc59761ce830cbec4f6","secret":"57c9b09bf912704f84effdb491984cf0b66b0b336775f2b810eb9a1220ce0e574d441b59e6662bdd3c778cf98717162edd072889cd2a3a2d9e460f857b002109","key":"","base_nonce":"","exporter_secret":"b7febabb3928140260418aa75b8e3edf354c00085733b85b13fbfdb8b129a59de2b0c6d20c4812e8fb212d6ec9e8763383ac5568435e99d5151cdfd8b3e50dd8","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"b113cb55c8f9fe5fc81f59f35b4657410294059c583c088af72e2666dba16657"},{"exporter_context":"00","L":32,"exported_value":"ef0238451a366f3f6d0315eb03de5e94d1ca3ff7f418c90f1b856e9b980cec75"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"5d650b9fb302476ffcf89a7b9dfb2f66f9e5430ed33288b924f98ae7575b7129"}]},{"mode":2,"kem_id":18,"kdf_id":3,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"2d1d9a5a5a4768481e0f056a10359edd5571299f991c9ae23a01b662ec534848a2c54989b9f102eb06306e73b9b152fc03b7402c34722e688c28ad4798213980d6b3","ikmS":"4e49d5f40a6c23d890ce8c84979a8841b4d9d55fe51891cca58a04534530c3a1a88041127ece277dcd6397518cf3e44f3e451ca26dd7ab094b97981b4a3c56fbc1cc","ikmE":"01107d4b1426dbceae3d41443090ebbe7a4c8e4583745b4c4467c91eb660917bf9db9f27274cee3bee35b8c4225a8d55dc25e07e6e5f3866326c1c546b79f0f51f16","skRm":"0124b67ff12a0acf4484809029ffc52be801f731186f5659f275a86fe2b75039f6283f71f86d60f8ba89edaa50a2322e7fe1a89c8b0ebac3818b0a6f4a45396d56a7","skSm":"012a6a5692e290fed174f962601514ab75c7bb0762b230e03982d7adda5cb20d79c9e14ed0f0512b38cb229ae4696eec9666d9bdd6072794fd8826d7be0d7722b33f","skEm":"00bab1083f8217e0a4bc9afa6e19e519821b36cc6c85aaa12a640ae932ab2a8d2d6c53e2386fa917bcce9ddc9d80abfbd5fa9552247a940ff0bd4bfc25c77871b815","pkRm":"04007f689613c0f624a31b078178097200c45a39544bfc7069bf4834d36a43452a870abe34a7da11c2324288fab16c5378f55627ebd3071991d218ea5254b4df545a8801ff2c5b40accd4db49773f50e359e099f832a968a22bbfca0b509089d8866466ffecf0a587921a4abd5aa2c2d58d888671e3bc4da0b5eb3303025896b60828c5291","pkSm":"0400de0ef3bbaa46c6d38b9dcb07294b2e5e41523a20acc793af6b16f954feea51d0a520443d1ad02e4c42158a16bc682908084e5efaa156ee8ef94976673ecb9b814700fc3382dd3fca6334b0dcd2a4e52b63a2a46aefd9d3a9d5a81c7c9f89261565d2a3fdc5e3ec45718e3fc521246e40d707edac7952d45c48c0e31a483ccad5215e69","pkEm":"0400e1c8770b1b7663e00cd79e4dcdbe760564018a766d32262de010129cdabce994fdbbd4150753a50871f2798ef91c21c8d11372fc7833678cb75bc126bc996b9fd601cc629f88f6df75d4db9be01b2e3c2242c73c295b5f41a4cf0ce75402d480de369061ce9fadfa2af41876d4af57b65744ce09dbd9671e3762fb74eca6d6b45af35a","enc":"0400e1c8770b1b7663e00cd79e4dcdbe760564018a766d32262de010129cdabce994fdbbd4150753a50871f2798ef91c21c8d11372fc7833678cb75bc126bc996b9fd601cc629f88f6df75d4db9be01b2e3c2242c73c295b5f41a4cf0ce75402d480de369061ce9fadfa2af41876d4af57b65744ce09dbd9671e3762fb74eca6d6b45af35a","shared_secret":"265d0761e30e11ef0e366fbb8cccc9b94301f3744abbea7b59d22578e2fa8fe49fc2e18cb1b4292ec955dfa660c5e2b0464a5cb5817ef670ae575d7ac225af67","key_schedule_context":"02e61f42c12d5c0c82d55c04b7352e7e6c6e958c77f5e6634997eb731b73acef61057b2dfa6f9f246c24be60685edf1a525c8cc473f6f3cebab5abdd73d01414d1875ca98065a7ca3f2be4e8b6c32ebcfe5e25c6f0ed8d6723cd6f24cd0dc258d80ee0c9339696e1eef5fd9337f77057357273e5a8fc62afc59761ce830cbec4f6","secret":"703170ea39a9624b450cd210dcea04cb13d8c1cf2b868dbc4ef66fa13876fc24156005c5b7c493ef07f8d5ea8226cb8920966e53a649a88ad664e0750b70eba6","key":"","base_nonce":"","exporter_secret":"21a154b97dc8e70ebed4f6807a38e7318f2a44a5d966d6f4947e586df13cda044bd9fbae519144607f1ac2dfc87a3d16c3d0036c01193c02110c3a74f771151c","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"d805fc03d37c95a94c4311c6ab7d573cad6f73e29bbb502c494da6f585646180"},{"exporter_context":"00","L":32,"exported_value":"6e493812c32bee5c1ac702b22820df4f729f9fc09d631d311058e175a7d715ac"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"d7b7ac2cfdfd7de191b215ff86c74b45103e2e863e25d9434c093054a75831ab"}]},{"mode":3,"kem_id":18,"kdf_id":3,"aead_id":65535,"info":"4f6465206f6e2061204772656369616e2055726e","ikmR":"eebbdccfe8d11c88c64d51e55710f4346e1185f9ccd14fbe47c5b84678b03e5eaf336ddb588a269beaf198d1bc4dfe49944a01e0914f8ccd444bc2d0414687c01f21","ikmS":"76806deae181596dd23d40cbb4f2460d59d952be4725dc2a66a4b70e365cc84d35751d1ee315dd6c20553136ede75202a4451c876c523163ffa5eb14125b5b36a51b","ikmE":"9cc41b0c23da5b71cd6bff7540ccd4c9c81d7f7243b2c844f0ab21bdb8ffda0d014669d442ec87df0a8bab78fa0580ed58910a1051d25c63a0acb5dcd9026e0ac591","skRm":"012f1b17f1b36a3bebac1f7949eee08bf57a940dd2a13921ae61078044e98bd45c7edd5cddcf5345916f82d2a5c1ef0c1ed3cf569ae4211d4f4f2f907d68b42242af","skSm":"00f08db5b13dd58bd6ba1830341be3368160bb381f37cc9739fd68cde11fe93f1ec7f7c6c9c1eaac42bed1764762b0b3119d932e34b302aa6cf81bedd4a2abe2baab","skEm":"003c0cfb065e444b16cdc34fa644d3e349472766c87157bbbfe0187e578dfcc381fbd30376ce8c4a0a3604b30a097cd33a4d6a0de51953453813267f1148f2a79188","psk":"0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82","psk_id":"456e6e796e20447572696e206172616e204d6f726961","pkRm":"0401480ead916fd2f2476a7608a4325032fb791abe30a2952039688b815999a80058f3cb78b705b9313249502390871e38188d56c59be7286b2280a62e9e8786cff23201eadee29ab4b6e8380bbfab4ade9a505c0306f06bee83bc8dd0189b7042c2f980a9bb9d4e2b4c9bf4f673869436fe993d5b1291339ea5fa933f3c132ba4e1c49e7c","pkSm":"0400891829ab88e9fd851960e85c42c06d8fc3c79950f0ee81c318274869115fbd997e13ce29500a82291d671859ed31e9916a42102dcaf364bd53dda789b20ec4eaee0063a136e371910a00edf490dd83fd19530e8d72c9767b646be3a301740aa8a63f4ee3ec5c33611b09049e4faabc2bcac0ca9c46617c56c9b2ab363f5a0f06bc6c48","pkEm":"04018eaad9a5d43d830ac630026c5d208b720758893786164c9d83e02228295cb8b2ecd17d32192ab4c6f446dc47a1ba324a50c42984a22d9706c1a22d717886137c8500f9a669bf554187fc8171faff77c186e1c4326d96772a2d1e03137a8fb0dae0a9bd6b29f7cd1d6f9a9edc0af270411d8684b193b0027cc0c9166e84b12f8fb74a3c","enc":"04018eaad9a5d43d830ac630026c5d208b720758893786164c9d83e02228295cb8b2ecd17d32192ab4c6f446dc47a1ba324a50c42984a22d9706c1a22d717886137c8500f9a669bf554187fc8171faff77c186e1c4326d96772a2d1e03137a8fb0dae0a9bd6b29f7cd1d6f9a9edc0af270411d8684b193b0027cc0c9166e84b12f8fb74a3c","shared_secret":"2150eb49200a2b5911a78254ac79062f2ee40c8c09ce19c40525bc08cde2a7b3dc561af67bf6946547c504e2b6e99886d82c0eb52e3457c7e72db57d25490fe5","key_schedule_context":"03c812270f9eefe05d307a98ba602a3428bf46753891b005db953c031c2e27538557a2f6d972182bc516aaeec4e6b57fad3f65687a5f17d70ad3fabbab45be339d875ca98065a7ca3f2be4e8b6c32ebcfe5e25c6f0ed8d6723cd6f24cd0dc258d80ee0c9339696e1eef5fd9337f77057357273e5a8fc62afc59761ce830cbec4f6","secret":"a5b6042f664538bc79731487392b1e06ac2bed27ba84a21bbac06c6085f0113137fd097b22a17ed6af35ac30ad3e3d49eb05b26143c1b0d6a28254f79b97d126","key":"","base_nonce":"","exporter_secret":"49705dc41ad22f905c3e8ad27ada15794ee2784fed2eda3c39d56bbbf7b61d804a0e5ff4be8c0a813de27afcfffcaa36f4099e7cae880fa4800f4f52f757027f","encryptions":[],"exports":[{"exporter_context":"","L":32,"exported_value":"4a15bbbefbfb604162310895932eebb8699a28257d35159a82937d09bb8ae152"},{"exporter_context":"00","L":32,"exported_value":"e663ad095a7f50afb9ed8fc693530c776559913cdb8abec1a908ca8fcaf9df09"},{"exporter_context":"54657374436f6e74657874","L":32,"exported_value":"5196a75c2b228802b64ecdaf5db3dc3286f5a65b191d04b4297d0cb38c0d0691"}]}] ================================================ FILE: go/testing/fakekms/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") licenses(["notice"]) package(default_visibility = ["//:__subpackages__"]) # keep go_library( name = "fakekms", testonly = 1, srcs = ["fakekms.go"], importpath = "github.com/google/tink/go/testing/fakekms", visibility = ["//visibility:public"], deps = [ "//aead", "//core/registry", "//keyset", "//testkeyset", "//tink", ], ) go_test( name = "fakekms_test", srcs = ["fakekms_test.go"], deps = [":fakekms"], ) alias( name = "go_default_library", actual = ":fakekms", visibility = ["//visibility:public"], ) ================================================ FILE: go/testing/fakekms/fakekms.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package fakekms provides a fake implementation of registry.KMSClient. // // Normally, a 'keyURI' identifies a key that is stored remotely by the KMS, // and every operation is executed remotely using a RPC call to the KMS, since // the key should not be sent to the client. // In this fake implementation we want to avoid these RPC calls. We achieve this // by encoding the key in the 'keyURI'. So the client simply needs to decode // the key and generate an AEAD out of it. This is of course insecure and should // only be used in testing. package fakekms import ( "bytes" "encoding/base64" "fmt" "strings" "github.com/google/tink/go/aead" "github.com/google/tink/go/core/registry" "github.com/google/tink/go/keyset" "github.com/google/tink/go/testkeyset" "github.com/google/tink/go/tink" ) const fakePrefix = "fake-kms://" var _ registry.KMSClient = (*fakeClient)(nil) type fakeClient struct { uriPrefix string } // NewClient returns a fake KMS client which will handle keys with uriPrefix prefix. // keyURI must have the following format: 'fake-kms://<base64 encoded aead keyset>'. func NewClient(uriPrefix string) (registry.KMSClient, error) { if !strings.HasPrefix(strings.ToLower(uriPrefix), fakePrefix) { return nil, fmt.Errorf("uriPrefix must start with %s, but got %s", fakePrefix, uriPrefix) } return &fakeClient{ uriPrefix: uriPrefix, }, nil } // Supported returns true if this client does support keyURI. func (c *fakeClient) Supported(keyURI string) bool { return strings.HasPrefix(keyURI, c.uriPrefix) } // GetAEAD returns an AEAD by keyURI. func (c *fakeClient) GetAEAD(keyURI string) (tink.AEAD, error) { if !c.Supported(keyURI) { return nil, fmt.Errorf("keyURI must start with prefix %s, but got %s", c.uriPrefix, keyURI) } encodeKeyset := strings.TrimPrefix(keyURI, fakePrefix) keysetData, err := base64.RawURLEncoding.DecodeString(encodeKeyset) if err != nil { return nil, err } reader := keyset.NewBinaryReader(bytes.NewReader(keysetData)) handle, err := testkeyset.Read(reader) if err != nil { return nil, err } return aead.New(handle) } // NewKeyURI returns a new, random fake KMS key URI. func NewKeyURI() (string, error) { handle, err := keyset.NewHandle(aead.AES128GCMKeyTemplate()) if err != nil { return "", err } buf := new(bytes.Buffer) writer := keyset.NewBinaryWriter(buf) err = testkeyset.Write(handle, writer) if err != nil { return "", err } return fakePrefix + base64.RawURLEncoding.EncodeToString(buf.Bytes()), nil } ================================================ FILE: go/testing/fakekms/fakekms_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package fakekms_test import ( "bytes" "testing" "github.com/google/tink/go/testing/fakekms" ) const keyURI = "fake-kms://CM2b3_MDElQKSAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuQWVzR2NtS2V5EhIaEIK75t5L-adlUwVhWvRuWUwYARABGM2b3_MDIAE" const anotherKeyURI = "fake-kms://CLHW_5cHElQKSAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuQWVzR2NtS2V5EhIaEIZ-2h9InfZTbbkJjaJBsVgYARABGLHW_5cHIAE" func TestValidKeyURIs(t *testing.T) { newKeyURI, err := fakekms.NewKeyURI() if err != nil { t.Fatal(err) } var testCases = []string{ keyURI, anotherKeyURI, newKeyURI, } for _, tc := range testCases { t.Run(tc, func(t *testing.T) { client, err := fakekms.NewClient(tc) if err != nil { t.Fatalf("testutil.NewFakeKMSClient(keyURI) failed: %v", err) } if !client.Supported(tc) { t.Fatalf("client.Supported(keyURI) is false, want true") } primitive, err := client.GetAEAD(tc) if err != nil { t.Fatalf("client.GetAEAD(keyURI) failed: %v", err) } plaintext := []byte("some data to encrypt") aad := []byte("extra data to authenticate") ciphertext, err := primitive.Encrypt(plaintext, aad) if err != nil { t.Fatalf("primitive.Encrypt(plaintext, aad) failed: %v", err) } decrypted, err := primitive.Decrypt(ciphertext, aad) if err != nil { t.Fatalf("primitive.Decrypt(ciphertext, aad) failed: %v", err) } if !bytes.Equal(plaintext, decrypted) { t.Fatalf("decrypted data doesn't match plaintext, got: %q, want: %q", decrypted, plaintext) } }) } } func TestBadUriPrefix(t *testing.T) { _, err := fakekms.NewClient("bad-prefix://encodedkeyset") if err == nil { t.Fatalf("fakekms.NewClient('bad-prefix://encodedkeyset') succeeded, want fail") } } func TestValidPrefix(t *testing.T) { uriPrefix := "fake-kms://CM2b" // is a prefix of keyURI client, err := fakekms.NewClient(uriPrefix) if err != nil { t.Fatalf("fakekms.NewClient(uriPrefix) failed: %v", err) } if !client.Supported(keyURI) { t.Fatalf("client with URI prefix %s should support key URI %s", uriPrefix, keyURI) } _, err = client.GetAEAD(keyURI) if err != nil { t.Fatalf("client.GetAEAD(anotherKeyURI) failed: %v", err) } } func TestInvalidPrefix(t *testing.T) { uriPrefix := "fake-kms://CM2x" // is not a prefix of keyURI client, err := fakekms.NewClient(uriPrefix) if err != nil { t.Fatalf("fakekms.NewClient(uriPrefix) failed: %v", err) } if client.Supported(keyURI) { t.Fatalf("client with URI prefix %s should not support key URI %s", uriPrefix, keyURI) } _, err = client.GetAEAD(keyURI) if err == nil { t.Fatalf("client.GetAEAD(keyURI) succeeded, want fail") } } func TestGetAeadFailsWithBadKeysetEncoding(t *testing.T) { client, err := fakekms.NewClient("fake-kms://bad") if err != nil { t.Fatalf("fakekms.NewClient('fake-kms://bad') failed: %v", err) } _, err = client.GetAEAD("fake-kms://badencoding") if err == nil { t.Fatalf("client.GetAEAD('fake-kms://badencoding') succeeded, want fail") } } ================================================ FILE: go/testing/fakemonitoring/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep licenses(["notice"]) # keep go_library( name = "fakemonitoring", testonly = 1, srcs = ["fakemonitoring.go"], importpath = "github.com/google/tink/go/testing/fakemonitoring", visibility = ["//visibility:public"], deps = ["//monitoring"], ) alias( name = "go_default_library", actual = ":fakemonitoring", visibility = ["//visibility:public"], ) go_test( name = "fakemonitoring_test", srcs = ["fakemonitoring_test.go"], deps = [ ":fakemonitoring", "//monitoring", "@com_github_google_go_cmp//cmp", ], ) ================================================ FILE: go/testing/fakemonitoring/fakemonitoring.go ================================================ // Copyright 2022 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package fakemonitoring provides a fake implementation of monitoring clients and loggers. package fakemonitoring import ( "sync" "github.com/google/tink/go/monitoring" ) // Logger implements a fake monitoring.Logger type Logger struct { Context *monitoring.Context client *Client } var _ monitoring.Logger = (*Logger)(nil) // Log logs the use of a primitive with a key with `keyID` operating over `numBytes`. func (l *Logger) Log(keyID uint32, numBytes int) { l.client.addEvent(&LogEvent{ Context: l.Context, KeyID: keyID, NumBytes: numBytes, }) } // LogFailure captures a failure. func (l *Logger) LogFailure() { l.client.addFailure(&LogFailure{Context: l.Context}) } // LogEvent stored on each 'Log' operation. type LogEvent struct { Context *monitoring.Context KeyID uint32 NumBytes int } // LogFailure stored on each 'LogFailure' operation. type LogFailure struct { Context *monitoring.Context } // Client implements a fake monitoring.Client type Client struct { Name string eventsMu sync.Mutex events []*LogEvent failuresMu sync.Mutex failures []*LogFailure } var _ monitoring.Client = (*Client)(nil) // NewClient creates a new fake monitoring client. func NewClient(name string) *Client { return &Client{ Name: name, } } // NewLogger creates a new fake Logger. func (c *Client) NewLogger(context *monitoring.Context) (monitoring.Logger, error) { return &Logger{ Context: context, client: c, }, nil } // Events returns logged events. func (c *Client) Events() []*LogEvent { return c.events } // Failures returns logged failures. func (c *Client) Failures() []*LogFailure { return c.failures } func (c *Client) addEvent(event *LogEvent) { c.eventsMu.Lock() defer c.eventsMu.Unlock() c.events = append(c.events, event) } func (c *Client) addFailure(failure *LogFailure) { defer c.failuresMu.Unlock() c.failuresMu.Lock() c.failures = append(c.failures, failure) } ================================================ FILE: go/testing/fakemonitoring/fakemonitoring_test.go ================================================ // Copyright 2022 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package fakemonitoring_test import ( "testing" "github.com/google/go-cmp/cmp" "github.com/google/tink/go/monitoring" "github.com/google/tink/go/testing/fakemonitoring" ) func TestCreateNewClient(t *testing.T) { client := fakemonitoring.NewClient("fake-client") if client.Name != "fake-client" { t.Errorf("client.Name = %q, want %q", client.Name, "fake-client") } } func TestCreateNewLoggers(t *testing.T) { client := fakemonitoring.NewClient("client") ctxEnc := monitoring.NewContext("aead", "encrypt", monitoring.NewKeysetInfo(nil, 0, []*monitoring.Entry{})) encLogger, err := client.NewLogger(ctxEnc) if err != nil { t.Fatalf("NewLogger() err = %v, want nil", err) } ctxDec := monitoring.NewContext("aead", "decrypt", monitoring.NewKeysetInfo(nil, 0, []*monitoring.Entry{})) decLogger, err := client.NewLogger(ctxDec) if err != nil { t.Fatalf("NewLogger() err = %v, want nil", err) } gotEnc := encLogger.(*fakemonitoring.Logger).Context if !cmp.Equal(gotEnc, ctxEnc) { t.Errorf("got = %v, want = %v", gotEnc, ctxEnc) } gotDec := decLogger.(*fakemonitoring.Logger).Context if !cmp.Equal(gotDec, ctxDec) { t.Errorf("got = %v, want = %v", gotDec, ctxDec) } } func TestLoggerRecordsEvents(t *testing.T) { client := fakemonitoring.NewClient("client") ctxEnc := monitoring.NewContext("aead", "encrypt", monitoring.NewKeysetInfo(nil, 0, []*monitoring.Entry{})) logger, err := client.NewLogger(ctxEnc) if err != nil { t.Fatalf("NewLogger() err = %v, want nil", err) } logger.Log(5, 8) logger.Log(10, 3) logger.Log(12, 3) got := client.Events() want := []*fakemonitoring.LogEvent{ { Context: ctxEnc, KeyID: 5, NumBytes: 8, }, { Context: ctxEnc, KeyID: 10, NumBytes: 3, }, { Context: ctxEnc, KeyID: 12, NumBytes: 3, }, } if !cmp.Equal(got, want) { t.Errorf("Events() = %v, want = %v", got, want) } } func TestLogFailureRecordsFailure(t *testing.T) { client := fakemonitoring.NewClient("client") ctxEnc := monitoring.NewContext("aead", "encrypt", monitoring.NewKeysetInfo(nil, 0, []*monitoring.Entry{})) logger, err := client.NewLogger(ctxEnc) if err != nil { t.Fatalf("NewLogger() err = %v, want nil", err) } logger.LogFailure() logger.LogFailure() got := client.Failures() want := []*fakemonitoring.LogFailure{ { Context: ctxEnc, }, { Context: ctxEnc, }, } if !cmp.Equal(got, want) { t.Errorf("Failures() = %v, want = %v", got, want) } } ================================================ FILE: go/testkeyset/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep licenses(["notice"]) # keep go_library( name = "testkeyset", testonly = 1, srcs = ["testkeyset.go"], importpath = "github.com/google/tink/go/testkeyset", visibility = ["//visibility:public"], deps = [ "//internal", "//keyset", "//proto/tink_go_proto", ], ) alias( name = "go_default_library", actual = ":testkeyset", visibility = ["//visibility:public"], ) go_test( name = "testkeyset_test", srcs = ["testkeyset_test.go"], deps = [ ":testkeyset", "//insecurecleartextkeyset", "//keyset", "//mac", "//proto/tink_go_proto", "@com_github_google_go_cmp//cmp", ], ) ================================================ FILE: go/testkeyset/testkeyset.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package testkeyset provides for test code methods to read or write cleartext keyset material. package testkeyset import ( "errors" "github.com/google/tink/go/internal" "github.com/google/tink/go/keyset" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) var ( keysetHandle = internal.KeysetHandle.(func(*tinkpb.Keyset, ...keyset.Option) (*keyset.Handle, error)) keysetMaterial = internal.KeysetMaterial.(func(*keyset.Handle) *tinkpb.Keyset) errInvalidKeyset = errors.New("cleartextkeyset: invalid keyset") errInvalidHandle = errors.New("cleartextkeyset: invalid handle") errInvalidReader = errors.New("cleartextkeyset: invalid reader") errInvalidWriter = errors.New("cleartextkeyset: invalid writer") ) // NewHandle creates a new instance of Handle using the given keyset. func NewHandle(ks *tinkpb.Keyset) (*keyset.Handle, error) { if ks == nil || len(ks.Key) == 0 { return nil, errInvalidKeyset } return keysetHandle(ks) } // Read creates a keyset.Handle from a cleartext keyset obtained via r. func Read(r keyset.Reader) (*keyset.Handle, error) { if r == nil { return nil, errInvalidReader } ks, err := r.Read() if err != nil || ks == nil || len(ks.Key) == 0 { return nil, errInvalidKeyset } return keysetHandle(ks) } // Write exports the keyset from h to the given writer w without encrypting it. // Storing secret key material in an unencrypted fashion is dangerous. If feasible, you should use // [keyset.Handle.Write] instead. func Write(h *keyset.Handle, w keyset.Writer) error { if h == nil { return errInvalidHandle } if w == nil { return errInvalidWriter } return w.Write(KeysetMaterial(h)) } // KeysetMaterial returns the key material contained in a keyset.Handle. func KeysetMaterial(h *keyset.Handle) *tinkpb.Keyset { return keysetMaterial(h) } // KeysetHandle creates a keyset.Handle from cleartext key material. // // Callers should verify that the returned *keyset.Handle isn't nil. // // Deprecated: Use [NewHandle]. func KeysetHandle(ks *tinkpb.Keyset) *keyset.Handle { kh, err := keysetHandle(ks) if err != nil { // This *keyset.Handle can only return errors when *keyset.Option arguments // are provided. To maintain backwards compatibility and avoid panic, it returns // a nil value if an error happens. return nil } return kh } ================================================ FILE: go/testkeyset/testkeyset_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package testkeyset_test import ( "testing" "github.com/google/go-cmp/cmp" "github.com/google/tink/go/insecurecleartextkeyset" "github.com/google/tink/go/keyset" "github.com/google/tink/go/mac" "github.com/google/tink/go/testkeyset" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func makeKeyset(template *tinkpb.KeyTemplate) (*tinkpb.Keyset, error) { h, err := keyset.NewHandle(template) if err != nil { return nil, err } return insecurecleartextkeyset.KeysetMaterial(h), nil } func TestNewHandleCallsAreConsistent(t *testing.T) { ks, err := makeKeyset(mac.HMACSHA256Tag128KeyTemplate()) if err != nil { t.Fatalf("makeKeyset(mac.HMACSHA256Tag128KeyTemplate()) err = %v, want nil", err) } handle1, err := testkeyset.NewHandle(ks) if err != nil { t.Fatalf("testkeyset.NewHandle() err = %v, want nil", err) } p1, err := mac.New(handle1) if err != nil { t.Fatalf("mac.New(handle1) err = %v, want nil", err) } p2, err := mac.New(testkeyset.KeysetHandle(ks)) if err != nil { t.Fatalf("mac.New(testkeyset.KeysetHandle(ks)) err = %v, want nil", err) } data := []byte("data") m1, err := p1.ComputeMAC(data) if err != nil { t.Fatalf("p1.ComputeMAC(data) err = %v, want nil", err) } m2, err := p2.ComputeMAC(data) if err != nil { t.Fatalf("p2.ComputeMAC(data) err = %v, want nil", err) } if !cmp.Equal(m1, m2) { t.Errorf("MAC mistmatch, got = %v, want %v", m1, m2) } } ================================================ FILE: go/testutil/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep go_library( name = "testutil", testonly = 1, srcs = [ "constant.go", "testutil.go", "wycheproofutil.go", ], importpath = "github.com/google/tink/go/testutil", deps = [ "//core/registry", "//daead/subtle", "//hybrid/subtle", "//keyset", "//mac", "//proto/aes_cmac_go_proto", "//proto/aes_cmac_prf_go_proto", "//proto/aes_ctr_hmac_streaming_go_proto", "//proto/aes_gcm_go_proto", "//proto/aes_gcm_hkdf_streaming_go_proto", "//proto/aes_gcm_siv_go_proto", "//proto/aes_siv_go_proto", "//proto/common_go_proto", "//proto/ecdsa_go_proto", "//proto/ecies_aead_hkdf_go_proto", "//proto/ed25519_go_proto", "//proto/hkdf_prf_go_proto", "//proto/hmac_go_proto", "//proto/hmac_prf_go_proto", "//proto/tink_go_proto", "//subtle", "//subtle/random", "//tink", "@org_golang_google_protobuf//proto", ], ) go_test( name = "testutil_test", srcs = [ "testutil_test.go", "wycheproofutil_test.go", ], data = [ "//testdata/testvectors:aes_gcm", ], deps = [ ":testutil", "//subtle/random", "//tink", ], ) alias( name = "go_default_library", actual = ":testutil", visibility = ["//:__subpackages__"], ) ================================================ FILE: go/testutil/constant.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package testutil const ( // AEAD // AESCTRHMACAEADKeyVersion is the maximal version of AES-CTR-HMAC-AEAD keys that Tink supports. AESCTRHMACAEADKeyVersion = 0 // AESCTRHMACAEADTypeURL is the type URL of AES-CTR-HMAC-AEAD keys that Tink supports. AESCTRHMACAEADTypeURL = "type.googleapis.com/google.crypto.tink.AesCtrHmacAeadKey" // AESGCMKeyVersion is the maximal version of AES-GCM keys. AESGCMKeyVersion = 0 // AESGCMTypeURL is the type URL of AES-GCM keys that Tink supports. AESGCMTypeURL = "type.googleapis.com/google.crypto.tink.AesGcmKey" // AESGCMSIVKeyVersion is the maximal version of AES-GCM-SIV keys. AESGCMSIVKeyVersion = 0 // AESGCMSIVTypeURL is the type URL of AES-GCM-SIV keys that Tink supports. AESGCMSIVTypeURL = "type.googleapis.com/google.crypto.tink.AesGcmSivKey" // ChaCha20Poly1305KeyVersion is the maximal version of ChaCha20Poly1305 keys that Tink supports. ChaCha20Poly1305KeyVersion = 0 // ChaCha20Poly1305TypeURL is the type URL of ChaCha20Poly1305 keys. ChaCha20Poly1305TypeURL = "type.googleapis.com/google.crypto.tink.ChaCha20Poly1305Key" // KMSEnvelopeAEADKeyVersion is the maximal version of KMSEnvelopeAEAD keys that Tink supports. KMSEnvelopeAEADKeyVersion = 0 // KMSEnvelopeAEADTypeURL is the type URL of KMSEnvelopeAEAD keys. KMSEnvelopeAEADTypeURL = "type.googleapis.com/google.crypto.tink.KmsEnvelopeAeadKey" // XChaCha20Poly1305KeyVersion is the maximal version of XChaCha20Poly1305 keys that Tink supports. XChaCha20Poly1305KeyVersion = 0 // XChaCha20Poly1305TypeURL is the type URL of XChaCha20Poly1305 keys. XChaCha20Poly1305TypeURL = "type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key" // EciesAeadHkdfPrivateKeyKeyVersion is the maximal version of keys that this key manager supports. EciesAeadHkdfPrivateKeyKeyVersion = 0 // EciesAeadHkdfPrivateKeyTypeURL is the url that this key manager supports. EciesAeadHkdfPrivateKeyTypeURL = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey" // EciesAeadHkdfPublicKeyKeyVersion is the maximal version of keys that this key manager supports. EciesAeadHkdfPublicKeyKeyVersion = 0 // EciesAeadHkdfPublicKeyTypeURL is the url that this key manager supports. EciesAeadHkdfPublicKeyTypeURL = "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPublicKey" // DeterministicAEAD // AESSIVKeyVersion is the maximal version of AES-SIV keys that Tink supports. AESSIVKeyVersion = 0 // AESSIVTypeURL is the type URL of AES-SIV keys. AESSIVTypeURL = "type.googleapis.com/google.crypto.tink.AesSivKey" // MAC // HMACKeyVersion is the maximal version of HMAC keys that Tink supports. HMACKeyVersion = 0 // HMACTypeURL is the type URL of HMAC keys. HMACTypeURL = "type.googleapis.com/google.crypto.tink.HmacKey" // AESCMACKeyVersion is the maximal version of HMAC keys that Tink supports. AESCMACKeyVersion = 0 // AESCMACTypeURL is the type URL of AES-CMAC keys. AESCMACTypeURL = "type.googleapis.com/google.crypto.tink.AesCmacKey" // PRF Set // AESCMACPRFKeyVersion is the maximal version of AES CMAC PRF keys that Tink supports. AESCMACPRFKeyVersion = 0 // AESCMACPRFTypeURL is the type URL of AES CMAC PRF keys. AESCMACPRFTypeURL = "type.googleapis.com/google.crypto.tink.AesCmacPrfKey" // HKDFPRFKeyVersion is the maximal version of HKDF PRF keys that Tink supports. HKDFPRFKeyVersion = 0 // HKDFPRFTypeURL is the type URL of HKDF PRF keys. HKDFPRFTypeURL = "type.googleapis.com/google.crypto.tink.HkdfPrfKey" // HMACPRFKeyVersion is the maximal version of HMAC PRF keys that Tink supports. HMACPRFKeyVersion = 0 // HMACPRFTypeURL is the type URL of HMAC PRF keys. HMACPRFTypeURL = "type.googleapis.com/google.crypto.tink.HmacPrfKey" // Digital signatures // ECDSASignerKeyVersion is the maximum version of ECDSA private keys that Tink supports. ECDSASignerKeyVersion = 0 // ECDSASignerTypeURL is the type URL of ECDSA private keys. ECDSASignerTypeURL = "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey" // ECDSAVerifierKeyVersion is the maximum version of ECDSA public keys that Tink supports. ECDSAVerifierKeyVersion = 0 // ECDSAVerifierTypeURL is the type URL of ECDSA public keys. ECDSAVerifierTypeURL = "type.googleapis.com/google.crypto.tink.EcdsaPublicKey" // ED25519SignerKeyVersion is the maximum version of ED25519 private keys that Tink supports. ED25519SignerKeyVersion = 0 // ED25519SignerTypeURL is the type URL of ED25519 private keys. ED25519SignerTypeURL = "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey" // ED25519VerifierKeyVersion is the maximum version of ED25519 public keys that Tink supports. ED25519VerifierKeyVersion = 0 // ED25519VerifierTypeURL is the type URL of ED25519 public keys. ED25519VerifierTypeURL = "type.googleapis.com/google.crypto.tink.Ed25519PublicKey" // Streaming AEAD // AESGCMHKDFKeyVersion is the maximum version of AES-GCM-HKDF keys that Tink supports. AESGCMHKDFKeyVersion = 0 // AESGCMHKDFTypeURL is the type URL of AES-GCM-HKDF keys that Tink supports. AESGCMHKDFTypeURL = "type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey" // AESCTRHMACKeyVersion is the maximum version of AES-CTR-HMAC keys that Tink supports. AESCTRHMACKeyVersion = 0 // AESCTRHMACTypeURL is the type URL of AES-CTR-HMAC keys that Tink supports. AESCTRHMACTypeURL = "type.googleapis.com/google.crypto.tink.AesCtrHmacStreamingKey" ) ================================================ FILE: go/testutil/hybrid/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility = ["//:__subpackages__"]) # keep go_library( name = "hybrid", testonly = 1, srcs = ["private_key.go"], importpath = "github.com/google/tink/go/testutil/hybrid", deps = [ "//keyset", "//proto/hpke_go_proto", "//proto/tink_go_proto", "//testkeyset", "@org_golang_google_protobuf//proto", ], ) go_test( name = "hybrid_test", srcs = ["private_key_test.go"], deps = [ ":hybrid", "//hybrid", "//keyset", "//proto/hpke_go_proto", "//proto/tink_go_proto", "//subtle/random", "//testkeyset", "@org_golang_google_protobuf//proto", ], ) alias( name = "go_default_library", actual = ":hybrid", visibility = ["//visibility:public"], ) ================================================ FILE: go/testutil/hybrid/private_key.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package hybrid provides HybridEncrypt/Decrypt primitive-specific test // utilities. package hybrid import ( "errors" "fmt" "google.golang.org/protobuf/proto" "github.com/google/tink/go/keyset" "github.com/google/tink/go/testkeyset" hpkepb "github.com/google/tink/go/proto/hpke_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( // HPKE key lengths from // https://www.rfc-editor.org/rfc/rfc9180.html#section-7.1. hpkeX25519HKDFSHA256PrivKeyLen = 32 hpkeX25519HKDFSHA256PubKeyLen = 32 hpkePrivateKeyTypeURL = "type.googleapis.com/google.crypto.tink.HpkePrivateKey" ) // KeysetHandleFromSerializedPrivateKey returns a keyset handle containing a // primary key that has the specified privKeyBytes and pubKeyBytes and matches // template. // // Supported templates include: // - DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Raw_Key_Template, // which requires privKeyBytes and pubKeyBytes to be the KEM-encoding of the // private and public key, respectively, i.e. SerializePrivateKey and // SerializePublicKey in // https://www.rfc-editor.org/rfc/rfc9180.html#section-7.1.1. func KeysetHandleFromSerializedPrivateKey(privKeyBytes, pubKeyBytes []byte, template *tinkpb.KeyTemplate) (*keyset.Handle, error) { params, err := hpkeParamsFromTemplate(template) if err != nil { return nil, fmt.Errorf("failed to verify key template: %v", err) } if len(privKeyBytes) != hpkeX25519HKDFSHA256PrivKeyLen { return nil, fmt.Errorf("privKeyBytes length is %d but should be %d", len(privKeyBytes), hpkeX25519HKDFSHA256PrivKeyLen) } if len(pubKeyBytes) != hpkeX25519HKDFSHA256PubKeyLen { return nil, fmt.Errorf("pubKeyBytes length is %d but should be %d", len(pubKeyBytes), hpkeX25519HKDFSHA256PubKeyLen) } privKey := &hpkepb.HpkePrivateKey{ Version: 0, PrivateKey: privKeyBytes, PublicKey: &hpkepb.HpkePublicKey{ Version: 0, Params: params, PublicKey: pubKeyBytes, }, } serializedPrivKey, err := proto.Marshal(privKey) if err != nil { return nil, fmt.Errorf("failed to marshal HpkePrivateKey %v: %v", privKey, err) } ks := &tinkpb.Keyset{ PrimaryKeyId: 1, Key: []*tinkpb.Keyset_Key{ { KeyData: &tinkpb.KeyData{ TypeUrl: hpkePrivateKeyTypeURL, Value: serializedPrivKey, KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PRIVATE, }, Status: tinkpb.KeyStatusType_ENABLED, KeyId: 1, OutputPrefixType: tinkpb.OutputPrefixType_RAW, }, }, } return testkeyset.NewHandle(ks) } // hpkeParamsFromTemplate returns HPKE params after verifying that template is // supported. // // Supported templates include: // - DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Raw_Key_Template. func hpkeParamsFromTemplate(template *tinkpb.KeyTemplate) (*hpkepb.HpkeParams, error) { if template.GetTypeUrl() != hpkePrivateKeyTypeURL { return nil, fmt.Errorf("not key type URL %s", hpkePrivateKeyTypeURL) } if template.GetOutputPrefixType() != tinkpb.OutputPrefixType_RAW { return nil, errors.New("not raw output prefix type") } keyFormat := &hpkepb.HpkeKeyFormat{} if err := proto.Unmarshal(template.GetValue(), keyFormat); err != nil { return nil, fmt.Errorf("failed to unmarshal HpkeKeyFormat(%v): %v", template.GetValue(), err) } params := keyFormat.GetParams() if kem := params.GetKem(); kem != hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256 { return nil, fmt.Errorf("HPKE KEM %s not supported", kem) } if kdf := params.GetKdf(); kdf != hpkepb.HpkeKdf_HKDF_SHA256 { return nil, fmt.Errorf("HPKE KDF %s not supported", kdf) } if aead := params.GetAead(); aead != hpkepb.HpkeAead_CHACHA20_POLY1305 { return nil, fmt.Errorf("HPKE AEAD %s not supported", aead) } return params, nil } ================================================ FILE: go/testutil/hybrid/private_key_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hybrid_test import ( "bytes" "testing" "google.golang.org/protobuf/proto" "github.com/google/tink/go/hybrid" "github.com/google/tink/go/keyset" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testkeyset" testutilhybrid "github.com/google/tink/go/testutil/hybrid" hpkepb "github.com/google/tink/go/proto/hpke_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) func TestKeysetHandleFromSerializedPrivateKey(t *testing.T) { // Obtain private and public key handles via key template. keyTemplate := hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Raw_Key_Template() privHandle, err := keyset.NewHandle(keyTemplate) if err != nil { t.Fatalf("NewHandle(%v) err = %v, want nil", keyTemplate, err) } pubHandle, err := privHandle.Public() if err != nil { t.Fatalf("Public() err = %v, want nil", err) } // Get private, public key bytes and construct a private key handle. privKeyBytes, pubKeyBytes := privPubKeyBytes(t, privHandle) gotprivHandle, err := testutilhybrid.KeysetHandleFromSerializedPrivateKey(privKeyBytes, pubKeyBytes, keyTemplate) if err != nil { t.Errorf("KeysetHandleFromSerializedPrivateKey(%v, %v, %v) err = %v, want nil", privKeyBytes, pubKeyBytes, keyTemplate, err) } plaintext := random.GetRandomBytes(200) ctxInfo := random.GetRandomBytes(100) // Encrypt with original public key handle. enc, err := hybrid.NewHybridEncrypt(pubHandle) if err != nil { t.Fatalf("NewHybridEncrypt(%v) err = %v, want nil", pubHandle, err) } ciphertext, err := enc.Encrypt(plaintext, ctxInfo) if err != nil { t.Fatalf("Encrypt(%x, %x) err = %v, want nil", plaintext, ctxInfo, err) } // Decrypt with private key handle constructed from key bytes. dec, err := hybrid.NewHybridDecrypt(gotprivHandle) if err != nil { t.Fatalf("NewHybridDecrypt(%v) err = %v, want nil", gotprivHandle, err) } gotPlaintext, err := dec.Decrypt(ciphertext, ctxInfo) if err != nil { t.Fatalf("Decrypt(%x, %x) err = %v, want nil", ciphertext, ctxInfo, err) } if !bytes.Equal(gotPlaintext, plaintext) { t.Errorf("Decrypt(%x, %x) = %x, want %x", ciphertext, ctxInfo, gotPlaintext, plaintext) } } func TestKeysetHandleFromSerializedPrivateKeyInvalidTemplateFails(t *testing.T) { keyTemplate := hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Raw_Key_Template() privHandle, err := keyset.NewHandle(keyTemplate) if err != nil { t.Fatalf("NewHandle(%v) err = %v, want nil", keyTemplate, err) } privKeyBytes, pubKeyBytes := privPubKeyBytes(t, privHandle) tests := []struct { name string template *tinkpb.KeyTemplate }{ {"AES_128_GCM", hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Key_Template()}, {"AES_128_GCM_Raw", hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Raw_Key_Template()}, {"AES_256_GCM", hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM_Key_Template()}, {"AES_256_GCM_Raw", hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM_Raw_Key_Template()}, {"CHACHA20_POLY1305", hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Key_Template()}, {"invalid type URL", &tinkpb.KeyTemplate{ TypeUrl: "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey", Value: keyTemplate.GetValue(), OutputPrefixType: tinkpb.OutputPrefixType_RAW, }}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { if _, err := testutilhybrid.KeysetHandleFromSerializedPrivateKey(privKeyBytes, pubKeyBytes, test.template); err == nil { t.Errorf("KeysetHandleFromSerializedPrivateKey(%v, %v, %v) err = nil, want error", privKeyBytes, pubKeyBytes, test.template) } }) } } func privPubKeyBytes(t *testing.T, handle *keyset.Handle) ([]byte, []byte) { t.Helper() ks := testkeyset.KeysetMaterial(handle) if len(ks.GetKey()) != 1 { t.Fatalf("got len(ks.GetKey()) = %d, want 1", len(ks.GetKey())) } serializedPrivKey := ks.GetKey()[0].GetKeyData().GetValue() privKey := &hpkepb.HpkePrivateKey{} if err := proto.Unmarshal(serializedPrivKey, privKey); err != nil { t.Fatalf("Unmarshal(%v) = err %v, want nil", serializedPrivKey, err) } return privKey.GetPrivateKey(), privKey.GetPublicKey().GetPublicKey() } ================================================ FILE: go/testutil/testutil.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package testutil provides common methods needed in test code. package testutil import ( "bytes" "crypto/ecdsa" "crypto/ed25519" "crypto/rand" "encoding/gob" "errors" "fmt" "log" "math" "strconv" "strings" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" subtledaead "github.com/google/tink/go/daead/subtle" subtlehybrid "github.com/google/tink/go/hybrid/subtle" "github.com/google/tink/go/keyset" "github.com/google/tink/go/mac" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/subtle" "github.com/google/tink/go/tink" cmacpb "github.com/google/tink/go/proto/aes_cmac_go_proto" aescmacprfpb "github.com/google/tink/go/proto/aes_cmac_prf_go_proto" ctrhmacpb "github.com/google/tink/go/proto/aes_ctr_hmac_streaming_go_proto" gcmpb "github.com/google/tink/go/proto/aes_gcm_go_proto" gcmhkdfpb "github.com/google/tink/go/proto/aes_gcm_hkdf_streaming_go_proto" gcmsivpb "github.com/google/tink/go/proto/aes_gcm_siv_go_proto" aspb "github.com/google/tink/go/proto/aes_siv_go_proto" commonpb "github.com/google/tink/go/proto/common_go_proto" ecdsapb "github.com/google/tink/go/proto/ecdsa_go_proto" eciespb "github.com/google/tink/go/proto/ecies_aead_hkdf_go_proto" ed25519pb "github.com/google/tink/go/proto/ed25519_go_proto" hkdfprfpb "github.com/google/tink/go/proto/hkdf_prf_go_proto" hmacpb "github.com/google/tink/go/proto/hmac_go_proto" hmacprfpb "github.com/google/tink/go/proto/hmac_prf_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) // DummyAEADKeyManager is a dummy implementation of the KeyManager interface. // It returns DummyAEAD when GetPrimitive() functions are called. type DummyAEADKeyManager struct{} var _ registry.KeyManager = (*DummyAEADKeyManager)(nil) // Primitive constructs a primitive instance for the key given in // serializedKey, which must be a serialized key protocol buffer handled by this manager. func (km *DummyAEADKeyManager) Primitive(serializedKey []byte) (any, error) { return new(DummyAEAD), nil } // NewKey generates a new key according to specification in serializedKeyFormat. func (km *DummyAEADKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { return nil, fmt.Errorf("not implemented") } // NewKeyData generates a new KeyData according to specification in serializedkeyFormat. func (km *DummyAEADKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { return nil, fmt.Errorf("not implemented") } // DoesSupport returns true iff this KeyManager supports key type identified by typeURL. func (km *DummyAEADKeyManager) DoesSupport(typeURL string) bool { return typeURL == AESGCMTypeURL } // TypeURL returns the type URL. func (km *DummyAEADKeyManager) TypeURL() string { return AESGCMTypeURL } // DummyAEAD is a dummy implementation of AEAD interface. It "encrypts" data // with a simple serialization capturing the dummy name, plaintext, and // associated data, and "decrypts" it by reversing this and checking that the // name and associated data match. type DummyAEAD struct { Name string } type dummyAEADData struct { Name string Plaintext []byte AssociatedData []byte } // Encrypt encrypts the plaintext. func (a *DummyAEAD) Encrypt(plaintext []byte, associatedData []byte) ([]byte, error) { buf := new(bytes.Buffer) encoder := gob.NewEncoder(buf) err := encoder.Encode(dummyAEADData{ Name: a.Name, Plaintext: plaintext, AssociatedData: associatedData, }) if err != nil { return nil, fmt.Errorf("dummy aead encrypt: %v", err) } return buf.Bytes(), nil } // Decrypt decrypts the ciphertext. func (a *DummyAEAD) Decrypt(ciphertext []byte, associatedData []byte) ([]byte, error) { data := dummyAEADData{} decoder := gob.NewDecoder(bytes.NewBuffer(ciphertext)) if err := decoder.Decode(&data); err != nil { return nil, fmt.Errorf("dummy aead decrypt: invalid data: %v", err) } if data.Name != a.Name || !bytes.Equal(data.AssociatedData, associatedData) { return nil, errors.New("dummy aead encrypt: name/associated data mismatch") } return data.Plaintext, nil } // AlwaysFailingAead fails encryption and decryption operations. type AlwaysFailingAead struct { Error error } var _ (tink.AEAD) = (*AlwaysFailingAead)(nil) // NewAlwaysFailingAead creates a new always failing AEAD. func NewAlwaysFailingAead(err error) tink.AEAD { return &AlwaysFailingAead{Error: err} } // Encrypt returns an error on encryption. func (a *AlwaysFailingAead) Encrypt(plaintext []byte, associatedData []byte) ([]byte, error) { return nil, fmt.Errorf("AlwaysFailingAead will always fail on encryption: %v", a.Error) } // Decrypt returns an error on decryption. func (a *AlwaysFailingAead) Decrypt(ciphertext []byte, associatedData []byte) ([]byte, error) { return nil, fmt.Errorf("AlwaysFailingAead will always fail on decryption: %v", a.Error) } // AlwaysFailingDeterministicAead fails encryption and decryption operations. type AlwaysFailingDeterministicAead struct { Error error } var _ (tink.DeterministicAEAD) = (*AlwaysFailingDeterministicAead)(nil) // NewAlwaysFailingDeterministicAead creates a new always failing AEAD. func NewAlwaysFailingDeterministicAead(err error) tink.DeterministicAEAD { return &AlwaysFailingDeterministicAead{Error: err} } // EncryptDeterministically returns an error on encryption. func (a *AlwaysFailingDeterministicAead) EncryptDeterministically(plaintext []byte, associatedData []byte) ([]byte, error) { return nil, fmt.Errorf("AlwaysFailingDeterministicAead will always fail on encryption: %v", a.Error) } // DecryptDeterministically returns an error on decryption. func (a *AlwaysFailingDeterministicAead) DecryptDeterministically(ciphertext []byte, associatedData []byte) ([]byte, error) { return nil, fmt.Errorf("AlwaysFailingDeterministicAead will always fail on decryption: %v", a.Error) } // TestKeyManager is key manager which can be setup to return an arbitrary primitive for a type URL // useful for testing. type TestKeyManager struct { primitive any typeURL string } var _ registry.KeyManager = (*TestKeyManager)(nil) // NewTestKeyManager creates a new key manager that returns a specific primitive for a typeURL. func NewTestKeyManager(primitive any, typeURL string) registry.KeyManager { return &TestKeyManager{ primitive: primitive, typeURL: typeURL, } } // Primitive constructs a primitive instance for the key given input key. func (km *TestKeyManager) Primitive(serializedKey []byte) (any, error) { return km.primitive, nil } // NewKey generates a new key according to specification in serializedKeyFormat. func (km *TestKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { return nil, fmt.Errorf("TestKeyManager: not implemented") } // NewKeyData generates a new KeyData according to specification in serializedkeyFormat. func (km *TestKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { return nil, fmt.Errorf("TestKeyManager: not implemented") } // DoesSupport returns true if this KeyManager supports key type identified by typeURL. func (km *TestKeyManager) DoesSupport(typeURL string) bool { return typeURL == km.typeURL } // TypeURL returns the type URL. func (km *TestKeyManager) TypeURL() string { return km.typeURL } // DummySigner is a dummy implementation of the Signer interface. type DummySigner struct { aead DummyAEAD } // NewDummySigner creates a new dummy signer with the specified name. The name // is used to pair with the DummyVerifier. func NewDummySigner(name string) *DummySigner { return &DummySigner{DummyAEAD{Name: "dummy public key:" + name}} } // Sign signs data. func (s *DummySigner) Sign(data []byte) ([]byte, error) { return s.aead.Encrypt(nil, data) } // DummyVerifier is a dummy implementation of the Signer interface. type DummyVerifier struct { aead DummyAEAD } // Verify verifies data. func (v *DummyVerifier) Verify(sig, data []byte) error { _, err := v.aead.Decrypt(sig, data) return err } // NewDummyVerifier creates a new dummy verifier with the specified name. The // name is used to pair with the DummySigner. func NewDummyVerifier(name string) *DummyVerifier { return &DummyVerifier{DummyAEAD{Name: "dummy public key:" + name}} } // DummyMAC is a dummy implementation of Mac interface. type DummyMAC struct { Name string } // ComputeMAC computes an insecure message authentication code (MAC) for data. func (h *DummyMAC) ComputeMAC(data []byte) ([]byte, error) { return makeDummyMAC(data, h.Name), nil } func makeDummyMAC(data []byte, name string) []byte { m := make([]byte, 0, len(data)+len(name)) m = append(m, data...) return append(m, name...) } // VerifyMAC verifies whether mac is a correct, although insecure, message // authentication code (MAC) for data. func (h *DummyMAC) VerifyMAC(mac []byte, data []byte) error { want := makeDummyMAC(data, h.Name) if bytes.Equal(mac, want) { return nil } // This is intended for test use. If it fails, describe what MAC would be // required to succeed. return fmt.Errorf("VerifyMAC: mac = %x, requires %x", mac, want) } // DummyKMSClient is a dummy implementation of a KMS Client. type DummyKMSClient struct{} var _ registry.KMSClient = (*DummyKMSClient)(nil) // Supported true if this client does support keyURI func (d *DummyKMSClient) Supported(keyURI string) bool { return keyURI == "dummy" } // GetAEAD gets an Aead backend by keyURI. func (d *DummyKMSClient) GetAEAD(keyURI string) (tink.AEAD, error) { return &DummyAEAD{}, nil } // NewTestAESGCMKeyset creates a new Keyset containing an AESGCMKey. func NewTestAESGCMKeyset(primaryOutputPrefixType tinkpb.OutputPrefixType) *tinkpb.Keyset { keyData := NewAESGCMKeyData(16) return NewTestKeyset(keyData, primaryOutputPrefixType) } // NewTestAESGCMSIVKeyset creates a new Keyset containing an AESGCMSIVKey. func NewTestAESGCMSIVKeyset(primaryOutputPrefixType tinkpb.OutputPrefixType) *tinkpb.Keyset { keyData := NewAESGCMSIVKeyData(16) return NewTestKeyset(keyData, primaryOutputPrefixType) } // NewTestAESSIVKeyset creates a new Keyset containing an AesSivKey. func NewTestAESSIVKeyset(primaryOutputPrefixType tinkpb.OutputPrefixType) *tinkpb.Keyset { keyValue := random.GetRandomBytes(subtledaead.AESSIVKeySize) key := &aspb.AesSivKey{ Version: AESSIVKeyVersion, KeyValue: keyValue, } serializedKey, err := proto.Marshal(key) if err != nil { log.Fatalf("failed serializing proto: %v", err) } keyData := NewKeyData(AESSIVTypeURL, serializedKey, tinkpb.KeyData_SYMMETRIC) return NewTestKeyset(keyData, primaryOutputPrefixType) } // NewTestHMACKeyset creates a new Keyset containing a HMACKey. func NewTestHMACKeyset(tagSize uint32, primaryOutputPrefixType tinkpb.OutputPrefixType) *tinkpb.Keyset { keyData := NewHMACKeyData(commonpb.HashType_SHA256, tagSize) return NewTestKeyset(keyData, primaryOutputPrefixType) } // NewTestAESGCMHKDFKeyset creates a new Keyset containing an AESGCMHKDFKey. func NewTestAESGCMHKDFKeyset() *tinkpb.Keyset { const ( keySize = 16 derivedKeySize = 16 ciphertextSegmentSize = 4096 ) keyData := NewAESGCMHKDFKeyData(keySize, derivedKeySize, commonpb.HashType_SHA256, ciphertextSegmentSize) return NewTestKeyset(keyData, tinkpb.OutputPrefixType_RAW) } // NewTestKeyset creates a new test Keyset. func NewTestKeyset(keyData *tinkpb.KeyData, primaryOutputPrefixType tinkpb.OutputPrefixType) *tinkpb.Keyset { primaryKey := NewKey(keyData, tinkpb.KeyStatusType_ENABLED, 42, primaryOutputPrefixType) rawKey := NewKey(keyData, tinkpb.KeyStatusType_ENABLED, 43, tinkpb.OutputPrefixType_RAW) legacyKey := NewKey(keyData, tinkpb.KeyStatusType_ENABLED, 44, tinkpb.OutputPrefixType_LEGACY) tinkKey := NewKey(keyData, tinkpb.KeyStatusType_ENABLED, 45, tinkpb.OutputPrefixType_TINK) crunchyKey := NewKey(keyData, tinkpb.KeyStatusType_ENABLED, 46, tinkpb.OutputPrefixType_CRUNCHY) keys := []*tinkpb.Keyset_Key{primaryKey, rawKey, legacyKey, tinkKey, crunchyKey} return NewKeyset(primaryKey.KeyId, keys) } // NewDummyKey returns a dummy key that doesn't contain actual key material. func NewDummyKey(keyID int, status tinkpb.KeyStatusType, outputPrefixType tinkpb.OutputPrefixType) *tinkpb.Keyset_Key { return &tinkpb.Keyset_Key{ KeyData: new(tinkpb.KeyData), Status: status, KeyId: uint32(keyID), OutputPrefixType: outputPrefixType, } } // NewECDSAParams creates a ECDSAParams with the specified parameters. func NewECDSAParams(hashType commonpb.HashType, curve commonpb.EllipticCurveType, encoding ecdsapb.EcdsaSignatureEncoding) *ecdsapb.EcdsaParams { return &ecdsapb.EcdsaParams{ HashType: hashType, Curve: curve, Encoding: encoding, } } // NewECDSAKeyFormat creates a ECDSAKeyFormat with the specified parameters. func NewECDSAKeyFormat(params *ecdsapb.EcdsaParams) *ecdsapb.EcdsaKeyFormat { return &ecdsapb.EcdsaKeyFormat{Params: params} } // NewECDSAPrivateKey creates a ECDSAPrivateKey with the specified paramaters. func NewECDSAPrivateKey(version uint32, publicKey *ecdsapb.EcdsaPublicKey, keyValue []byte) *ecdsapb.EcdsaPrivateKey { return &ecdsapb.EcdsaPrivateKey{ Version: version, PublicKey: publicKey, KeyValue: keyValue, } } // NewECDSAPublicKey creates a ECDSAPublicKey with the specified paramaters. func NewECDSAPublicKey(version uint32, params *ecdsapb.EcdsaParams, x, y []byte) *ecdsapb.EcdsaPublicKey { return &ecdsapb.EcdsaPublicKey{ Version: version, Params: params, X: x, Y: y, } } // NewRandomECDSAPrivateKey creates an ECDSAPrivateKey with randomly generated key material. func NewRandomECDSAPrivateKey(hashType commonpb.HashType, curve commonpb.EllipticCurveType) *ecdsapb.EcdsaPrivateKey { curveName := commonpb.EllipticCurveType_name[int32(curve)] priv, err := ecdsa.GenerateKey(subtle.GetCurve(curveName), rand.Reader) if err != nil { panic(fmt.Sprintf("ecdsa.GenerateKey() failed: %v", err)) } params := NewECDSAParams(hashType, curve, ecdsapb.EcdsaSignatureEncoding_DER) publicKey := NewECDSAPublicKey(ECDSAVerifierKeyVersion, params, priv.X.Bytes(), priv.Y.Bytes()) return NewECDSAPrivateKey(ECDSASignerKeyVersion, publicKey, priv.D.Bytes()) } // NewRandomECDSAPublicKey creates an ECDSAPublicKey with randomly generated key material. func NewRandomECDSAPublicKey(hashType commonpb.HashType, curve commonpb.EllipticCurveType) *ecdsapb.EcdsaPublicKey { return NewRandomECDSAPrivateKey(hashType, curve).PublicKey } // GetECDSAParamNames returns the string representations of each parameter in // the given ECDSAParams. func GetECDSAParamNames(params *ecdsapb.EcdsaParams) (string, string, string) { hashName := commonpb.HashType_name[int32(params.HashType)] curveName := commonpb.EllipticCurveType_name[int32(params.Curve)] encodingName := ecdsapb.EcdsaSignatureEncoding_name[int32(params.Encoding)] return hashName, curveName, encodingName } // NewED25519PrivateKey creates an ED25519PrivateKey with randomly generated key material. func NewED25519PrivateKey() *ed25519pb.Ed25519PrivateKey { public, private, err := ed25519.GenerateKey(rand.Reader) if err != nil { panic(fmt.Sprintf("ed25519.GenerateKey() failed: %v", err)) } publicProto := &ed25519pb.Ed25519PublicKey{ Version: ED25519SignerKeyVersion, KeyValue: public, } return &ed25519pb.Ed25519PrivateKey{ Version: ED25519SignerKeyVersion, PublicKey: publicProto, KeyValue: private.Seed(), } } // NewED25519PublicKey creates an ED25519PublicKey with randomly generated key material. func NewED25519PublicKey() *ed25519pb.Ed25519PublicKey { return NewED25519PrivateKey().PublicKey } // NewAESGCMKey creates a randomly generated AESGCMKey. func NewAESGCMKey(keyVersion uint32, keySize uint32) *gcmpb.AesGcmKey { keyValue := random.GetRandomBytes(keySize) return &gcmpb.AesGcmKey{ Version: keyVersion, KeyValue: keyValue, } } // NewAESGCMKeyData creates a KeyData containing a randomly generated AESGCMKey. func NewAESGCMKeyData(keySize uint32) *tinkpb.KeyData { serializedKey, err := proto.Marshal(NewAESGCMKey(AESGCMKeyVersion, keySize)) if err != nil { log.Fatalf("failed serializing proto: %v", err) } return NewKeyData(AESGCMTypeURL, serializedKey, tinkpb.KeyData_SYMMETRIC) } // NewAESGCMKeyFormat returns a new AESGCMKeyFormat. func NewAESGCMKeyFormat(keySize uint32) *gcmpb.AesGcmKeyFormat { return &gcmpb.AesGcmKeyFormat{ KeySize: keySize, } } // NewAESGCMSIVKey creates a randomly generated AESGCMSIVKey. func NewAESGCMSIVKey(keyVersion, keySize uint32) *gcmsivpb.AesGcmSivKey { keyValue := random.GetRandomBytes(keySize) return &gcmsivpb.AesGcmSivKey{ Version: keyVersion, KeyValue: keyValue, } } // NewAESGCMSIVKeyData creates a KeyData containing a randomly generated AESGCMSIVKey. func NewAESGCMSIVKeyData(keySize uint32) *tinkpb.KeyData { serializedKey, err := proto.Marshal(NewAESGCMSIVKey(AESGCMKeyVersion, keySize)) if err != nil { log.Fatalf("NewAESGCMSIVKeyData(keySize=%d): Failed serializing proto; err=%v", keySize, err) } return NewKeyData(AESGCMTypeURL, serializedKey, tinkpb.KeyData_SYMMETRIC) } // NewAESGCMSIVKeyFormat returns a new AESGCMKeyFormat. func NewAESGCMSIVKeyFormat(keySize uint32) *gcmsivpb.AesGcmSivKeyFormat { return &gcmsivpb.AesGcmSivKeyFormat{ KeySize: keySize, } } // NewAESGCMHKDFKey creates a randomly generated AESGCMHKDFKey. func NewAESGCMHKDFKey(keyVersion, keySize, derivedKeySize uint32, hkdfHashType commonpb.HashType, ciphertextSegmentSize uint32) *gcmhkdfpb.AesGcmHkdfStreamingKey { keyValue := random.GetRandomBytes(keySize) return &gcmhkdfpb.AesGcmHkdfStreamingKey{ Version: keyVersion, KeyValue: keyValue, Params: &gcmhkdfpb.AesGcmHkdfStreamingParams{ CiphertextSegmentSize: ciphertextSegmentSize, DerivedKeySize: derivedKeySize, HkdfHashType: hkdfHashType, }, } } // NewAESGCMHKDFKeyData creates a KeyData containing a randomly generated AESGCMHKDFKey. func NewAESGCMHKDFKeyData(keySize, derivedKeySize uint32, hkdfHashType commonpb.HashType, ciphertextSegmentSize uint32) *tinkpb.KeyData { serializedKey, err := proto.Marshal(NewAESGCMHKDFKey(AESGCMHKDFKeyVersion, keySize, derivedKeySize, hkdfHashType, ciphertextSegmentSize)) if err != nil { log.Fatalf("failed serializing proto: %v", err) } return NewKeyData(AESGCMHKDFTypeURL, serializedKey, tinkpb.KeyData_SYMMETRIC) } // NewAESGCMHKDFKeyFormat returns a new AESGCMHKDFKeyFormat. func NewAESGCMHKDFKeyFormat(keySize, derivedKeySize uint32, hkdfHashType commonpb.HashType, ciphertextSegmentSize uint32) *gcmhkdfpb.AesGcmHkdfStreamingKeyFormat { return &gcmhkdfpb.AesGcmHkdfStreamingKeyFormat{ KeySize: keySize, Params: &gcmhkdfpb.AesGcmHkdfStreamingParams{ CiphertextSegmentSize: ciphertextSegmentSize, DerivedKeySize: derivedKeySize, HkdfHashType: hkdfHashType, }, } } // NewAESCTRHMACKey creates a randomly generated AESCTRHMACKey. func NewAESCTRHMACKey(keyVersion, keySize uint32, hkdfHashType commonpb.HashType, derivedKeySize uint32, hashType commonpb.HashType, tagSize, ciphertextSegmentSize uint32) *ctrhmacpb.AesCtrHmacStreamingKey { keyValue := random.GetRandomBytes(keySize) return &ctrhmacpb.AesCtrHmacStreamingKey{ Version: keyVersion, KeyValue: keyValue, Params: &ctrhmacpb.AesCtrHmacStreamingParams{ CiphertextSegmentSize: ciphertextSegmentSize, DerivedKeySize: derivedKeySize, HkdfHashType: hkdfHashType, HmacParams: &hmacpb.HmacParams{ Hash: hashType, TagSize: tagSize, }, }, } } // NewAESCTRHMACKeyFormat returns a new AESCTRHMACKeyFormat. func NewAESCTRHMACKeyFormat(keySize uint32, hkdfHashType commonpb.HashType, derivedKeySize uint32, hashType commonpb.HashType, tagSize, ciphertextSegmentSize uint32) *ctrhmacpb.AesCtrHmacStreamingKeyFormat { return &ctrhmacpb.AesCtrHmacStreamingKeyFormat{ KeySize: keySize, Params: &ctrhmacpb.AesCtrHmacStreamingParams{ CiphertextSegmentSize: ciphertextSegmentSize, DerivedKeySize: derivedKeySize, HkdfHashType: hkdfHashType, HmacParams: &hmacpb.HmacParams{ Hash: hashType, TagSize: tagSize, }, }, } } // NewHMACParams returns a new HMACParams. func NewHMACParams(hashType commonpb.HashType, tagSize uint32) *hmacpb.HmacParams { return &hmacpb.HmacParams{ Hash: hashType, TagSize: tagSize, } } // NewHMACKey creates a new HMACKey with the specified parameters. func NewHMACKey(hashType commonpb.HashType, tagSize uint32) *hmacpb.HmacKey { params := NewHMACParams(hashType, tagSize) keyValue := random.GetRandomBytes(20) return &hmacpb.HmacKey{ Version: HMACKeyVersion, Params: params, KeyValue: keyValue, } } // NewHMACKeyFormat creates a new HMACKeyFormat with the specified parameters. func NewHMACKeyFormat(hashType commonpb.HashType, tagSize uint32) *hmacpb.HmacKeyFormat { params := NewHMACParams(hashType, tagSize) keySize := uint32(20) return &hmacpb.HmacKeyFormat{ Params: params, KeySize: keySize, } } // NewAESCMACParams returns a new AESCMACParams. func NewAESCMACParams(tagSize uint32) *cmacpb.AesCmacParams { return &cmacpb.AesCmacParams{ TagSize: tagSize, } } // NewAESCMACKey creates a new AESCMACKey with the specified parameters. func NewAESCMACKey(tagSize uint32) *cmacpb.AesCmacKey { params := NewAESCMACParams(tagSize) keyValue := random.GetRandomBytes(32) return &cmacpb.AesCmacKey{ Version: AESCMACKeyVersion, Params: params, KeyValue: keyValue, } } // NewAESCMACKeyFormat creates a new AESCMACKeyFormat with the specified parameters. func NewAESCMACKeyFormat(tagSize uint32) *cmacpb.AesCmacKeyFormat { params := NewAESCMACParams(tagSize) keySize := uint32(32) return &cmacpb.AesCmacKeyFormat{ Params: params, KeySize: keySize, } } // NewHMACKeysetManager returns a new KeysetManager that contains a HMACKey. func NewHMACKeysetManager() *keyset.Manager { ksm := keyset.NewManager() kt := mac.HMACSHA256Tag128KeyTemplate() keyID, err := ksm.Add(kt) if err != nil { panic(fmt.Sprintf("cannot add key: %v", err)) } err = ksm.SetPrimary(keyID) if err != nil { panic(fmt.Sprintf("cannot set primary key: %v", err)) } return ksm } // NewHMACKeyData returns a new KeyData that contains a HMACKey. func NewHMACKeyData(hashType commonpb.HashType, tagSize uint32) *tinkpb.KeyData { key := NewHMACKey(hashType, tagSize) serializedKey, err := proto.Marshal(key) if err != nil { log.Fatalf("failed serializing proto: %v", err) } return &tinkpb.KeyData{ TypeUrl: HMACTypeURL, Value: serializedKey, KeyMaterialType: tinkpb.KeyData_SYMMETRIC, } } // NewHMACPRFParams returns a new HMACPRFParams. func NewHMACPRFParams(hashType commonpb.HashType) *hmacprfpb.HmacPrfParams { return &hmacprfpb.HmacPrfParams{ Hash: hashType, } } // NewHMACPRFKey creates a new HMACPRFKey with the specified parameters. func NewHMACPRFKey(hashType commonpb.HashType) *hmacprfpb.HmacPrfKey { params := NewHMACPRFParams(hashType) keyValue := random.GetRandomBytes(32) return &hmacprfpb.HmacPrfKey{ Version: HMACPRFKeyVersion, Params: params, KeyValue: keyValue, } } // NewHMACPRFKeyFormat creates a new HMACPRFKeyFormat with the specified parameters. func NewHMACPRFKeyFormat(hashType commonpb.HashType) *hmacprfpb.HmacPrfKeyFormat { params := NewHMACPRFParams(hashType) keySize := uint32(32) return &hmacprfpb.HmacPrfKeyFormat{ Params: params, KeySize: keySize, } } // NewHKDFPRFParams returns a new HKDFPRFParams. func NewHKDFPRFParams(hashType commonpb.HashType, salt []byte) *hkdfprfpb.HkdfPrfParams { return &hkdfprfpb.HkdfPrfParams{ Hash: hashType, Salt: salt, } } // NewHKDFPRFKey creates a new HKDFPRFKey with the specified parameters. func NewHKDFPRFKey(hashType commonpb.HashType, salt []byte) *hkdfprfpb.HkdfPrfKey { params := NewHKDFPRFParams(hashType, salt) keyValue := random.GetRandomBytes(32) return &hkdfprfpb.HkdfPrfKey{ Version: HKDFPRFKeyVersion, Params: params, KeyValue: keyValue, } } // NewHKDFPRFKeyFormat creates a new HKDFPRFKeyFormat with the specified parameters. func NewHKDFPRFKeyFormat(hashType commonpb.HashType, salt []byte) *hkdfprfpb.HkdfPrfKeyFormat { params := NewHKDFPRFParams(hashType, salt) keySize := uint32(32) return &hkdfprfpb.HkdfPrfKeyFormat{ Params: params, KeySize: keySize, } } // NewAESCMACPRFKey creates a new AESCMACPRFKey with the specified parameters. func NewAESCMACPRFKey() *aescmacprfpb.AesCmacPrfKey { keyValue := random.GetRandomBytes(32) return &aescmacprfpb.AesCmacPrfKey{ Version: AESCMACPRFKeyVersion, KeyValue: keyValue, } } // NewAESCMACPRFKeyFormat creates a new AESCMACPRFKeyFormat with the specified parameters. func NewAESCMACPRFKeyFormat() *aescmacprfpb.AesCmacPrfKeyFormat { keySize := uint32(32) return &aescmacprfpb.AesCmacPrfKeyFormat{ KeySize: keySize, } } // NewKeyData creates a new KeyData with the specified parameters. func NewKeyData(typeURL string, value []byte, materialType tinkpb.KeyData_KeyMaterialType) *tinkpb.KeyData { return &tinkpb.KeyData{ TypeUrl: typeURL, Value: value, KeyMaterialType: materialType, } } // NewKey creates a new Key with the specified parameters. func NewKey(keyData *tinkpb.KeyData, status tinkpb.KeyStatusType, keyID uint32, prefixType tinkpb.OutputPrefixType) *tinkpb.Keyset_Key { return &tinkpb.Keyset_Key{ KeyData: keyData, Status: status, KeyId: keyID, OutputPrefixType: prefixType, } } // NewKeyset creates a new Keyset with the specified parameters. func NewKeyset(primaryKeyID uint32, keys []*tinkpb.Keyset_Key) *tinkpb.Keyset { return &tinkpb.Keyset{ PrimaryKeyId: primaryKeyID, Key: keys, } } // GenerateMutations generates different byte mutations for a given byte array. func GenerateMutations(src []byte) (all [][]byte) { // Flip bits for i := 0; i < len(src); i++ { for j := 0; j < 8; j++ { n := make([]byte, len(src)) copy(n, src) n[i] = n[i] ^ (1 << uint8(j)) all = append(all, n) } } // Truncate bytes for i := 1; i < len(src); i++ { n := make([]byte, len(src[i:])) copy(n, src[i:]) all = append(all, n) } // Append extra byte m := make([]byte, len(src)+1) copy(m, src) all = append(all, m) return } // ZTestUniformString uses a z test on the given byte string, expecting all // bits to be uniformly set with probability 1/2. Returns non ok status if the // z test fails by more than 10 standard deviations. // // With less statistics jargon: This counts the number of bits set and expects // the number to be roughly half of the length of the string. The law of large // numbers suggests that we can assume that the longer the string is, the more // accurate that estimate becomes for a random string. This test is useful to // detect things like strings that are entirely zero. // // Note: By itself, this is a very weak test for randomness. func ZTestUniformString(bytes []byte) error { expected := float64(len(bytes)) * 8.0 / 2.0 stddev := math.Sqrt(float64(len(bytes)) * 8.0 / 4.0) numSetBits := int64(0) for _, b := range bytes { // Counting the number of bits set in byte: for b != 0 { numSetBits++ b = b & (b - 1) } } // Check that the number of bits is within 10 stddevs. if math.Abs(float64(numSetBits)-expected) < 10.0*stddev { return nil } return fmt.Errorf("Z test for uniformly distributed variable out of bounds; "+ "Actual number of set bits was %d expected was %0.00f, 10 * standard deviation is 10 * %0.00f = %0.00f", numSetBits, expected, stddev, 10.0*stddev) } func rotate(bytes []byte) []byte { result := make([]byte, len(bytes)) for i := 0; i < len(bytes); i++ { prev := i if i == 0 { prev = len(bytes) } result[i] = (bytes[i] >> 1) | (bytes[prev-1] << 7) } return result } // ZTestCrosscorrelationUniformStrings tests that the crosscorrelation of two // strings of equal length points to independent and uniformly distributed // strings. Returns non ok status if the z test fails by more than 10 standard // deviations. // // With less statistics jargon: This xors two strings and then performs the // ZTestUniformString on the result. If the two strings are independent and // uniformly distributed, the xor'ed string is as well. A cross correlation test // will find whether two strings overlap more or less than it would be expected. // // Note: Having a correlation of zero is only a necessary but not sufficient // condition for independence. func ZTestCrosscorrelationUniformStrings(bytes1, bytes2 []byte) error { if len(bytes1) != len(bytes2) { return fmt.Errorf( "Strings are not of equal length") } crossed := make([]byte, len(bytes1)) for i := 0; i < len(bytes1); i++ { crossed[i] = bytes1[i] ^ bytes2[i] } return ZTestUniformString(crossed) } // ZTestAutocorrelationUniformString tests that the autocorrelation of a string // points to the bits being independent and uniformly distributed. // Rotates the string in a cyclic fashion. Returns non ok status if the z test // fails by more than 10 standard deviations. // // With less statistics jargon: This rotates the string bit by bit and performs // ZTestCrosscorrelationUniformStrings on each of the rotated strings and the // original. This will find self similarity of the input string, especially // periodic self similarity. For example, it is a decent test to find English // text (needs about 180 characters with the current settings). // // Note: Having a correlation of zero is only a necessary but not sufficient // condition for independence. func ZTestAutocorrelationUniformString(bytes []byte) error { rotated := make([]byte, len(bytes)) copy(rotated, bytes) violations := []string{} for i := 1; i < len(bytes)*8; i++ { rotated = rotate(rotated) err := ZTestCrosscorrelationUniformStrings(bytes, rotated) if err != nil { violations = append(violations, strconv.Itoa(i)) } } if len(violations) == 0 { return nil } return fmt.Errorf("Autocorrelation exceeded 10 standard deviation at %d indices: %s", len(violations), strings.Join(violations, ", ")) } // eciesAEADHKDFPublicKey returns a EciesAeadHkdfPublicKey with specified parameters. func eciesAEADHKDFPublicKey(c commonpb.EllipticCurveType, ht commonpb.HashType, ptfmt commonpb.EcPointFormat, dekT *tinkpb.KeyTemplate, x, y, salt []byte) *eciespb.EciesAeadHkdfPublicKey { return &eciespb.EciesAeadHkdfPublicKey{ Version: 0, Params: &eciespb.EciesAeadHkdfParams{ KemParams: &eciespb.EciesHkdfKemParams{ CurveType: c, HkdfHashType: ht, HkdfSalt: salt, }, DemParams: &eciespb.EciesAeadDemParams{ AeadDem: dekT, }, EcPointFormat: ptfmt, }, X: x, Y: y, } } // eciesAEADHKDFPrivateKey returns a EciesAeadHkdfPrivateKey with specified parameters func eciesAEADHKDFPrivateKey(p *eciespb.EciesAeadHkdfPublicKey, d []byte) *eciespb.EciesAeadHkdfPrivateKey { return &eciespb.EciesAeadHkdfPrivateKey{ Version: 0, PublicKey: p, KeyValue: d, } } // GenerateECIESAEADHKDFPrivateKey generates a new EC key pair and returns the private key proto. func GenerateECIESAEADHKDFPrivateKey(c commonpb.EllipticCurveType, ht commonpb.HashType, ptfmt commonpb.EcPointFormat, dekT *tinkpb.KeyTemplate, salt []byte) (*eciespb.EciesAeadHkdfPrivateKey, error) { curve, err := subtlehybrid.GetCurve(c.String()) if err != nil { return nil, err } pvt, err := subtlehybrid.GenerateECDHKeyPair(curve) if err != nil { return nil, err } pubKey := eciesAEADHKDFPublicKey(c, ht, ptfmt, dekT, pvt.PublicKey.Point.X.Bytes(), pvt.PublicKey.Point.Y.Bytes(), salt) return eciesAEADHKDFPrivateKey(pubKey, pvt.D.Bytes()), nil } ================================================ FILE: go/testutil/testutil_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package testutil_test import ( "bytes" "encoding/hex" "testing" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/testutil" "github.com/google/tink/go/tink" ) func TestDummyAEAD(t *testing.T) { // Assert that DummyAEAD implements the AEAD interface. var _ tink.AEAD = (*testutil.DummyAEAD)(nil) // try to encrypt/decrypt some data data := []byte{0, 1, 1, 2, 3, 5} associatedData := []byte{3, 1, 4, 1, 5} dummy := &testutil.DummyAEAD{Name: "name"} cipher, err := dummy.Encrypt(data, associatedData) if err != nil { t.Fatalf("DummyAEAD.Encrypt(%+v, %+v) gave error: %v", data, associatedData, err) } decrypt, err := dummy.Decrypt(cipher, associatedData) if err != nil { t.Fatalf("DummyAEAD.Decrypt(ciphertext, %+v) gave errr: %v", associatedData, err) } if !bytes.Equal(data, decrypt) { t.Errorf("DummyAEAD round-tripped data %+v back to %+v", data, decrypt) } } func TestDummySigner(t *testing.T) { var _ tink.Signer = testutil.NewDummySigner("name") } func TestDummyVerifier(t *testing.T) { var _ tink.Verifier = testutil.NewDummyVerifier("name") } func TestDummySignerVerifier(t *testing.T) { signer := testutil.NewDummySigner("") verifier := testutil.NewDummyVerifier("") data := []byte{2, 7, 1, 8, 2, 8} if err := verifier.Verify(nil, data); err == nil { t.Errorf("DummyVerifier.Verify(invalid signature, %+v) succeeded; want error", data) } sig, err := signer.Sign(data) if err != nil { t.Fatalf("DummySigner.Sign(%+v) gave error: %v", data, err) } if err := verifier.Verify(sig, data); err != nil { t.Errorf("DummyVerifier.Verify(valid signature, %+v) gave error: %v", data, err) } } func TestDummyMAC(t *testing.T) { // Assert that DummyMAC implements the MAC interface. var _ tink.MAC = (*testutil.DummyMAC)(nil) // try to compute mac data := []byte("data") dummyMAC := &testutil.DummyMAC{Name: "Mac12347"} digest, err := dummyMAC.ComputeMAC(data) if err != nil { t.Errorf("unexpected error: %s", err) } if want := []byte("dataMac12347"); !bytes.Equal(digest, want) { t.Errorf("digest = %x, want %x", digest, want) } if err := dummyMAC.VerifyMAC(digest, data); err != nil { t.Errorf("VerifyMAC(%x, %x) = %v, want nil", digest, data, err) } if dummyMAC.VerifyMAC(digest, []byte("other data")) == nil { t.Errorf("VerifyMAC(%x, %x) = nil, want error", digest, data) } } func fillByteArray(b byte, length int) []byte { result := []byte{} for i := 0; i < length; i++ { result = append(result, b) } return result } func TestUniformString(t *testing.T) { if err := testutil.ZTestUniformString(fillByteArray(0xaa, 32)); err != nil { t.Errorf("Expected repeated 0xaa string to pass: %v", err) } if err := testutil.ZTestUniformString(fillByteArray(0x00, 32)); err == nil { t.Errorf("Expected to fail uniform distribution test for 32 zero bytes") } if err := testutil.ZTestUniformString(random.GetRandomBytes(32)); err != nil { t.Errorf("Expected random string to pass randomness test: %v", err) } } func TestCrossCorrelationUniformString(t *testing.T) { if err := testutil.ZTestCrosscorrelationUniformStrings(fillByteArray(0xaa, 32), fillByteArray(0x99, 32)); err != nil { t.Errorf("Expected 0xaa and 0x99 repeated 32 times each to have no cross correlation: %v", err) } if err := testutil.ZTestCrosscorrelationUniformStrings(fillByteArray(0xaa, 32), fillByteArray(0xaa, 32)); err == nil { t.Errorf("Expected 0xaa repeated 32 times to be cross correlated with itself") } if err := testutil.ZTestCrosscorrelationUniformStrings(random.GetRandomBytes(32), random.GetRandomBytes(32)); err != nil { t.Errorf("Expected random 32 byte strings to not be crosscorrelated: %v", err) } } func TestAutocorrelationUniformString(t *testing.T) { if err := testutil.ZTestAutocorrelationUniformString(fillByteArray(0xaa, 32)); err == nil { t.Errorf("Expected repeated string to show autocorrelation") } if err := testutil.ZTestAutocorrelationUniformString([]byte( "This is a text that is only ascii characters and therefore " + "not random. It needs quite a few characters before it has " + "enough to find a pattern, though, as it is text.")); err == nil { t.Errorf("Expected longish English ASCII test to be autocorrelated") } if err := testutil.ZTestAutocorrelationUniformString(random.GetRandomBytes(32)); err != nil { t.Errorf("Expected random 32 byte string to show not autocorrelation: %v", err) } } func TestGenerateMutations(t *testing.T) { original := random.GetRandomBytes(8) mutations := testutil.GenerateMutations(original) seen := make(map[string]bool) for i, mutation := range mutations { if bytes.Compare(original, mutation) == 0 { t.Errorf("Expected mutation %x to differ from original %x", mutation, original) } mutationHex := hex.EncodeToString(mutation) if seen[mutationHex] { t.Errorf("Mutation %d (%s) matches an earlier mutation", i, mutationHex) } seen[mutationHex] = true } } ================================================ FILE: go/testutil/wycheproofutil.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package testutil import ( "encoding/hex" "encoding/json" "errors" "os" "path/filepath" "testing" ) const ( testvectorsDir = "testdata/testvectors" ) // SkipTestIfTestSrcDirIsNotSet skips the test if TEST_SRCDIR is not set. // This is necessary when not using Blaze/Bazel, as we don't have a solution for referencing non-Go // resources that are external to the repository with Go tooling. func SkipTestIfTestSrcDirIsNotSet(t *testing.T) { t.Helper() if _, ok := os.LookupEnv("TEST_SRCDIR"); !ok { t.Skip("TEST_SRCDIR not found") } } // WycheproofSuite represents the common elements of the top level // object in a Wycheproof json file. Implementations should embed // WycheproofSuite in a struct that strongly types the testGroups // field. See wycheproofutil_test.go for an example. type WycheproofSuite struct { Algorithm string `json:"algorithm"` GeneratorVersion string `json:"generatorVersion"` NumberOfTests int `json:"numberOfTests"` Notes map[string]string `json:"notes"` } // WycheproofGroup represents the common elements of a testGroups // object in a Wycheproof suite. Implementations should embed // WycheproofGroup in a struct that strongly types its list of cases. // See wycheproofutil_test.go for an example. type WycheproofGroup struct { Type string `json:"type"` } // WycheproofCase represents the common elements of a tests object // in a Wycheproof group. Implementation should embed WycheproofCase // in a struct that contains fields specific to the test type. // See wycheproofutil_test.go for an example. type WycheproofCase struct { CaseID int `json:"tcId"` Comment string `json:"comment"` Result string `json:"result"` Flags []string `json:"flags"` } // HexBytes is a helper type for unmarshalling a byte sequence represented as a // hex encoded string. type HexBytes []byte // UnmarshalText converts a hex encoded string into a sequence of bytes. func (a *HexBytes) UnmarshalText(text []byte) error { decoded, err := hex.DecodeString(string(text)) if err != nil { return err } *a = decoded return nil } // PopulateSuite opens filename from the Wycheproof test vectors directory and // populates suite with the decoded JSON data. // // When using this in a test function, the function should start with // SkipTestIfTestSrcDirIsNotSet(), to expediently skip the test. func PopulateSuite(suite any, filename string) error { srcDir, ok := os.LookupEnv("TEST_SRCDIR") if !ok { return errors.New("TEST_SRCDIR not found") } workspaceDir, ok := os.LookupEnv("TEST_WORKSPACE") if !ok { return errors.New("TEST_WORKSPACE not found") } f, err := os.Open(filepath.Join(srcDir, workspaceDir, testvectorsDir, filename)) if err != nil { return err } parser := json.NewDecoder(f) if err := parser.Decode(suite); err != nil { return err } return nil } ================================================ FILE: go/testutil/wycheproofutil_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package testutil_test import ( "encoding/json" "os" "testing" "github.com/google/tink/go/testutil" ) func TestPopulateSuite(t *testing.T) { testutil.SkipTestIfTestSrcDirIsNotSet(t) // TODO(175520475): Test the HexBytes type. type AeadTest struct { testutil.WycheproofCase Key string `json:"key"` IV string `json:"iv"` AAD string `json:"aad"` Message string `json:"msg"` Ciphertext string `json:"ct"` Tag string `json:"tag"` } type AeadGroup struct { testutil.WycheproofGroup Tests []*AeadTest `json:"tests"` } type AeadSuite struct { testutil.WycheproofSuite TestGroups []*AeadGroup `json:"testGroups"` } suite := new(AeadSuite) if err := testutil.PopulateSuite(suite, "aes_gcm_test.json"); err != nil { t.Fatalf("error populating suite: %s", err) } if suite.Algorithm != "AES-GCM" { t.Errorf("suite.Algorithm=%s, want AES-GCM", suite.Algorithm) } if suite.TestGroups[0].Tests[0].Key == "" { t.Error("suite.TestGroups[0].Tests[0].Key is empty") } } func TestPopulateSuite_FileOpenError(t *testing.T) { testutil.SkipTestIfTestSrcDirIsNotSet(t) suite := new(testutil.WycheproofSuite) err := testutil.PopulateSuite(suite, "NON_EXISTENT_FILE") if err == nil { t.Error("succeeded with non-existent file") } if _, ok := err.(*os.PathError); !ok { t.Errorf("unexpected error for non-existent file: %s", err) } } func TestPopulateSuite_DecodeError(t *testing.T) { testutil.SkipTestIfTestSrcDirIsNotSet(t) var suite *testutil.WycheproofSuite err := testutil.PopulateSuite(suite, "aes_gcm_test.json") if err == nil { t.Error("succeeded with nil suite") } if _, ok := err.(*json.InvalidUnmarshalError); !ok { t.Errorf("unexpected error for decode error: %s", err) } } ================================================ FILE: go/tink/BUILD.bazel ================================================ load("@io_bazel_rules_go//go:def.bzl", "go_library") package(default_visibility = ["//:__subpackages__"]) # keep licenses(["notice"]) # keep go_library( name = "tink", srcs = [ "aead.go", "deterministic_aead.go", "hybrid_decrypt.go", "hybrid_encrypt.go", "mac.go", "signer.go", "streamingaead.go", "tink.go", "verifier.go", "version.go", ], importpath = "github.com/google/tink/go/tink", visibility = ["//visibility:public"], ) alias( name = "go_default_library", actual = ":tink", visibility = ["//visibility:public"], ) ================================================ FILE: go/tink/aead.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tink /* AEAD is the interface for authenticated encryption with associated data. Implementations of this interface are secure against adaptive chosen ciphertext attacks. Encryption with associated data ensures authenticity and integrity of that data, but not its secrecy. (see RFC 5116, https://tools.ietf.org/html/rfc5116) */ type AEAD interface { // Encrypt encrypts plaintext with associatedData as associated data. // The resulting ciphertext allows for checking authenticity and integrity of associated data // associatedData, but does not guarantee its secrecy. Encrypt(plaintext, associatedData []byte) ([]byte, error) // Decrypt decrypts ciphertext with associatedData as associated data. // The decryption verifies the authenticity and integrity of the associated data, but there are // no guarantees with respect to secrecy of that data. Decrypt(ciphertext, associatedData []byte) ([]byte, error) } ================================================ FILE: go/tink/deterministic_aead.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tink /* DeterministicAEAD is the interface for deterministic authenticated encryption with associated data. Warning: Unlike AEAD, implementations of this interface are not semantically secure, because encrypting the same plaintext always yields the same ciphertext. Security guarantees: Implementations of this interface provide 128-bit security level against multi-user attacks with up to 2^32 keys. That means if an adversary obtains 2^32 ciphertexts of the same message encrypted under 2^32 keys, they need to do 2^128 computations to obtain a single key. Encryption with associated data ensures authenticity (who the sender is) and integrity (the data has not been tampered with) of that data, but not its secrecy. References: * https://tools.ietf.org/html/rfc5116 * https://tools.ietf.org/html/rfc5297#section-1.3 */ type DeterministicAEAD interface { // EncryptDeterministically deterministically encrypts plaintext with associatedData as // associated authenticated data. // // Warning: // Encrypting the same plaintext multiple times protects the integrity of that plaintext, // but confidentiality is compromised to the extent that an attacker can determine that // the same plaintext was encrypted. // // The resulting ciphertext allows for checking authenticity and integrity of associatedData, // but does not guarantee its secrecy. EncryptDeterministically(plaintext, associatedData []byte) ([]byte, error) // DecryptDeterministically deterministically decrypts ciphertext with associatedData as // associated authenticated data. The decryption verifies the authenticity and integrity // of the associated data, but there are no guarantees with respect to secrecy of that data. DecryptDeterministically(ciphertext, associatedData []byte) ([]byte, error) } ================================================ FILE: go/tink/hybrid_decrypt.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tink /* HybridDecrypt Interface for hybrid decryption. Hybrid Encryption combines the efficiency of symmetric encryption with the convenience of public-key encryption: to encrypt a message a fresh symmetric key is generated and used to encrypt the actual plaintext data, while the recipient’s public key is used to encrypt the symmetric key only, and the final ciphertext consists of the symmetric ciphertext and the encrypted symmetric key. WARNING Hybrid Encryption does not provide authenticity, that is the recipient of an encrypted message does not know the identity of the sender. Similar to general public-key encryption schemes the security goal of Hybrid Encryption is to provide privacy only. In other words, Hybrid Encryption is secure if and only if the recipient can accept anonymous messages or can rely on other mechanisms to authenticate the sender. Security guarantees The functionality of Hybrid Encryption is represented as a pair of interfaces: HybridEncrypt for encryption of data, and HybridDecrypt for decryption. Implementations of these interfaces are secure against adaptive chosen ciphertext attacks. In addition to plaintext the encryption takes an extra parameter contextInfo, which usually is public data implicit from the context, but should be bound to the resulting ciphertext, i.e. the ciphertext allows for checking the integrity of contextInfo (but there are no guarantees wrt. the secrecy or authenticity of contextInfo). contextInfo can be empty or null, but to ensure the correct decryption of a ciphertext the same value must be provided for the decryption operation as was used during encryption (HybridEncrypt). A concrete instantiation of this interface can implement the binding of contextInfo to the ciphertext in various ways, for example: use contextInfo as "associated data"-input for the employed AEAD symmetric encryption (cf. https://tools.ietf.org/html/rfc5116). use contextInfo as "CtxInfo"-input for HKDF (if the implementation uses HKDF as key derivation function, cf. https://tools.ietf.org/html/rfc5869). */ type HybridDecrypt interface { // Decrypt operation: decrypts ciphertext, verifying the integrity of // contextInfo. Returns resulting plaintext. Decrypt(ciphertext, contextInfo []byte) ([]byte, error) } ================================================ FILE: go/tink/hybrid_encrypt.go ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tink /* HybridEncrypt is the Interface for hybrid encryption. Hybrid Encryption combines the efficiency of symmetric encryption with the convenience of public-key encryption: to encrypt a message a fresh symmetric key is generated and used to encrypt the actual plaintext data, while the recipient’s public key is used to encrypt the symmetric key only, and the final ciphertext consists of the symmetric ciphertext and the encrypted symmetric key. WARNING Hybrid Encryption does not provide authenticity, that is the recipient of an encrypted message does not know the identity of the sender. Similar to general public-key encryption schemes the security goal of Hybrid Encryption is to provide privacy only. In other words, Hybrid Encryption is secure if and only if the recipient can accept anonymous messages or can rely on other mechanisms to authenticate the sender. Security guarantees The functionality of Hybrid Encryption is represented as a pair of interfaces: HybridEncrypt for encryption of data, and HybridDecrypt for decryption. Implementations of these interfaces are secure against adaptive chosen ciphertext attacks. In addition to plaintext the encryption takes an extra parameter contextInfo, which usually is public data implicit from the context, but should be bound to the resulting ciphertext, i.e. the ciphertext allows for checking the integrity of contextInfo (but there are no guarantees wrt. the secrecy or authenticity of contextInfo). contextInfo can be empty or null, but to ensure the correct decryption of a ciphertext the same value must be provided for the decryption operation as was used during encryption (cf. HybridEncrypt). A concrete instantiation of this interface can implement the binding of contextInfo to the ciphertext in various ways, for example: use contextInfo as "associated data"-input for the employed AEAD symmetric encryption (cf. https://tools.ietf.org/html/rfc5116). use contextInfo as "CtxInfo"-input for HKDF (if the implementation uses HKDF as key derivation function, cf. https://tools.ietf.org/html/rfc5869). */ type HybridEncrypt interface { // Encrypt operation: encrypts plaintext, binding contextInfo to the resulting // ciphertext. Returns resulting ciphertext. Encrypt(plaintext, contextInfo []byte) ([]byte, error) } ================================================ FILE: go/tink/mac.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tink /* MAC is the interface for MACs (Message Authentication Codes). This interface should be used for authentication only, and not for other purposes (for example, it should not be used to generate pseudorandom bytes). */ type MAC interface { // ComputeMAC computes message authentication code (MAC) for code data. ComputeMAC(data []byte) ([]byte, error) // Verify returns nil if mac is a correct authentication code (MAC) for data, // otherwise it returns an error. VerifyMAC(mac, data []byte) error } ================================================ FILE: go/tink/signer.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tink // Signer is the signing interface for digital signature. // // Implementations of this interface are secure against adaptive chosen-message // attacks. Signing data ensures authenticity and integrity of that data, but // not its secrecy. type Signer interface { // Computes the digital signature for data. Sign(data []byte) ([]byte, error) } ================================================ FILE: go/tink/streamingaead.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tink import "io" /* StreamingAEAD is an interface for streaming authenticated encryption with associated data. Streaming encryption is typically used for encrypting large plaintexts such as large files. Tink may eventually contain multiple interfaces for streaming encryption depending on the supported properties. This interface supports a streaming interface for symmetric encryption with authentication. The underlying encryption modes are selected so that partial plaintext can be obtained fast by decrypting and authenticating just a part of the ciphertext. Instances of StreamingAEAD must follow the OAE2 definition as proposed in the paper "Online Authenticated-Encryption and its Nonce-Reuse Misuse-Resistance" by Hoang, Reyhanitabar, Rogaway and Vizár https://eprint.iacr.org/2015/189.pdf */ type StreamingAEAD interface { // NewEncryptingWriter returns a wrapper around underlying io.Writer, such that any write-operation // via the wrapper results in AEAD-encryption of the written data, using associatedData // as associated data. The associated data is not included in the ciphertext // and has to be passed in as parameter for decryption. NewEncryptingWriter(w io.Writer, associatedData []byte) (io.WriteCloser, error) // NewDecryptingReader returns a wrapper around underlying io.Reader, such that any read-operation // via the wrapper results in AEAD-decryption of the underlying ciphertext, // using associatedData as associated data. NewDecryptingReader(r io.Reader, associatedData []byte) (io.Reader, error) } ================================================ FILE: go/tink/tink.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package tink provides the abstract interfaces of the primitives supported by Tink. package tink ================================================ FILE: go/tink/verifier.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tink // Verifier is the verifying interface for digital signature. // // Implementations of this interface are secure against adaptive chosen-message // attacks. Signing data ensures authenticity and integrity of that data, but // not its secrecy. type Verifier interface { // Verifies returns nil if signature is a valid signature for data; otherwise returns an error. Verify(signature, data []byte) error } ================================================ FILE: go/tink/version.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tink const ( // Version is the current version of Tink. Version = "2.1.0" ) ================================================ FILE: go/tink_version.bzl ================================================ """ Version of the current release of Tink """ TINK_VERSION_LABEL = "1.7.0" ================================================ FILE: java_src/.bazelignore ================================================ examples ================================================ FILE: java_src/.bazelrc ================================================ # Minumum C++ version. Override it building this project with # `bazel build --cxxopt='-std=c++<XY>' --host_cxxopt='c++<XY>' ...` # (Both -std and --host_cxxopt must be set to force the desired version.) build --cxxopt='-std=c++14' --host_cxxopt='-std=c++14' ================================================ FILE: java_src/.bazelversion ================================================ 6.0.0 ================================================ FILE: java_src/BUILD.bazel ================================================ ## This file is created using "create_main_build_file.py". load("//tools:gen_maven_jar_rules.bzl", "gen_maven_jar_rules") package(default_visibility = ["//visibility:public"]) licenses(["notice"]) exports_files(["BUILD"]) # Maven jars. # DO NOT USE FOR ANY OTHER PURPOSES. gen_maven_jar_rules( name = "tink", doctitle = "Tink Cryptography API", manifest_lines = [ "Automatic-Module-Name: com.google.crypto.tink", ], root_packages = [ "com.google.crypto.tink", ], deps = [ "//src/main/java/com/google/crypto/tink:accesses_partial_key", "//src/main/java/com/google/crypto/tink:aead", "//src/main/java/com/google/crypto/tink:binary_keyset_reader", "//src/main/java/com/google/crypto/tink:binary_keyset_writer", "//src/main/java/com/google/crypto/tink:catalogue", "//src/main/java/com/google/crypto/tink:cleartext_keyset_handle", "//src/main/java/com/google/crypto/tink:config", "//src/main/java/com/google/crypto/tink:configuration", "//src/main/java/com/google/crypto/tink:configuration_fips140_v2", "//src/main/java/com/google/crypto/tink:configuration_v0", "//src/main/java/com/google/crypto/tink:crypto_format", "//src/main/java/com/google/crypto/tink:deterministic_aead", "//src/main/java/com/google/crypto/tink:hybrid_decrypt", "//src/main/java/com/google/crypto/tink:hybrid_encrypt", "//src/main/java/com/google/crypto/tink:insecure_secret_key_access", "//src/main/java/com/google/crypto/tink:json_keyset_reader", "//src/main/java/com/google/crypto/tink:json_keyset_writer", "//src/main/java/com/google/crypto/tink:key", "//src/main/java/com/google/crypto/tink:key_manager", "//src/main/java/com/google/crypto/tink:key_status", "//src/main/java/com/google/crypto/tink:key_template", "//src/main/java/com/google/crypto/tink:key_templates", "//src/main/java/com/google/crypto/tink:key_wrap", "//src/main/java/com/google/crypto/tink:keyset_reader", "//src/main/java/com/google/crypto/tink:keyset_writer", "//src/main/java/com/google/crypto/tink:kms_client", "//src/main/java/com/google/crypto/tink:kms_clients", "//src/main/java/com/google/crypto/tink:legacy_keyset_serialization", "//src/main/java/com/google/crypto/tink:mac", "//src/main/java/com/google/crypto/tink:no_secret_keyset_handle", "//src/main/java/com/google/crypto/tink:parameters", "//src/main/java/com/google/crypto/tink:pem_key_type", "//src/main/java/com/google/crypto/tink:primitive_wrapper", "//src/main/java/com/google/crypto/tink:private_key", "//src/main/java/com/google/crypto/tink:private_key_manager", "//src/main/java/com/google/crypto/tink:public_key_sign", "//src/main/java/com/google/crypto/tink:public_key_verify", "//src/main/java/com/google/crypto/tink:registry", "//src/main/java/com/google/crypto/tink:registry_cluster", "//src/main/java/com/google/crypto/tink:registry_configuration", "//src/main/java/com/google/crypto/tink:secret_key_access", "//src/main/java/com/google/crypto/tink:streaming_aead", "//src/main/java/com/google/crypto/tink:tink_json_proto_keyset_format", "//src/main/java/com/google/crypto/tink:tink_proto_keyset_format", "//src/main/java/com/google/crypto/tink:tink_proto_parameters_format", "//src/main/java/com/google/crypto/tink:util", "//src/main/java/com/google/crypto/tink:version", "//src/main/java/com/google/crypto/tink/aead:aead_config", "//src/main/java/com/google/crypto/tink/aead:aead_factory", "//src/main/java/com/google/crypto/tink/aead:aead_key", "//src/main/java/com/google/crypto/tink/aead:aead_key_templates", "//src/main/java/com/google/crypto/tink/aead:aead_parameters", "//src/main/java/com/google/crypto/tink/aead:aead_wrapper", "//src/main/java/com/google/crypto/tink/aead:aes_ctr_hmac_aead_key", "//src/main/java/com/google/crypto/tink/aead:aes_ctr_hmac_aead_key_manager", "//src/main/java/com/google/crypto/tink/aead:aes_ctr_hmac_aead_parameters", "//src/main/java/com/google/crypto/tink/aead:aes_eax_key", "//src/main/java/com/google/crypto/tink/aead:aes_eax_key_manager", "//src/main/java/com/google/crypto/tink/aead:aes_eax_parameters", "//src/main/java/com/google/crypto/tink/aead:aes_gcm_key", "//src/main/java/com/google/crypto/tink/aead:aes_gcm_key_manager", "//src/main/java/com/google/crypto/tink/aead:aes_gcm_parameters", "//src/main/java/com/google/crypto/tink/aead:aes_gcm_siv_key", "//src/main/java/com/google/crypto/tink/aead:aes_gcm_siv_key_manager", "//src/main/java/com/google/crypto/tink/aead:aes_gcm_siv_parameters", "//src/main/java/com/google/crypto/tink/aead:cha_cha20_poly1305_key", "//src/main/java/com/google/crypto/tink/aead:cha_cha20_poly1305_key_manager", "//src/main/java/com/google/crypto/tink/aead:cha_cha20_poly1305_parameters", "//src/main/java/com/google/crypto/tink/aead:kms_aead_key_manager", "//src/main/java/com/google/crypto/tink/aead:kms_envelope_aead", "//src/main/java/com/google/crypto/tink/aead:kms_envelope_aead_key_manager", "//src/main/java/com/google/crypto/tink/aead:legacy_kms_aead_key", "//src/main/java/com/google/crypto/tink/aead:legacy_kms_aead_parameters", "//src/main/java/com/google/crypto/tink/aead:legacy_kms_aead_proto_serialization", "//src/main/java/com/google/crypto/tink/aead:legacy_kms_envelope_aead_key", "//src/main/java/com/google/crypto/tink/aead:legacy_kms_envelope_aead_parameters", "//src/main/java/com/google/crypto/tink/aead:legacy_kms_envelope_aead_proto_serialization", "//src/main/java/com/google/crypto/tink/aead:predefined_aead_parameters", "//src/main/java/com/google/crypto/tink/aead:x_cha_cha20_poly1305_key", "//src/main/java/com/google/crypto/tink/aead:x_cha_cha20_poly1305_key_manager", "//src/main/java/com/google/crypto/tink/aead:x_cha_cha20_poly1305_parameters", "//src/main/java/com/google/crypto/tink/aead/internal:aes_ctr_hmac_aead_proto_serialization", "//src/main/java/com/google/crypto/tink/aead/internal:aes_eax_proto_serialization", "//src/main/java/com/google/crypto/tink/aead/internal:aes_gcm_proto_serialization", "//src/main/java/com/google/crypto/tink/aead/internal:aes_gcm_siv_proto_serialization", "//src/main/java/com/google/crypto/tink/aead/internal:cha_cha20_poly1305_jce", "//src/main/java/com/google/crypto/tink/aead/internal:cha_cha20_poly1305_proto_serialization", "//src/main/java/com/google/crypto/tink/aead/internal:cha_cha20_util", "//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_aes_gcm_jce", "//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_cha_cha20", "//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_cha_cha20_base", "//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_cha_cha20_poly1305", "//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_cha_cha20_poly1305_base", "//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_cha_cha20_poly1305_jce", "//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_x_cha_cha20", "//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_x_cha_cha20_poly1305", "//src/main/java/com/google/crypto/tink/aead/internal:legacy_full_aead", "//src/main/java/com/google/crypto/tink/aead/internal:poly1305", "//src/main/java/com/google/crypto/tink/aead/internal:x_cha_cha20_poly1305_jce", "//src/main/java/com/google/crypto/tink/aead/internal:x_cha_cha20_poly1305_proto_serialization", "//src/main/java/com/google/crypto/tink/aead/subtle:aead_factory", "//src/main/java/com/google/crypto/tink/aead/subtle:aes_gcm_factory", "//src/main/java/com/google/crypto/tink/aead/subtle:aes_gcm_siv", "//src/main/java/com/google/crypto/tink/annotations:alpha", "//src/main/java/com/google/crypto/tink/config:tink_config", "//src/main/java/com/google/crypto/tink/config:tink_fips", "//src/main/java/com/google/crypto/tink/config/internal:tink_fips_status", "//src/main/java/com/google/crypto/tink/config/internal:tink_fips_util", "//src/main/java/com/google/crypto/tink/daead:aes_siv_key", "//src/main/java/com/google/crypto/tink/daead:aes_siv_key_manager", "//src/main/java/com/google/crypto/tink/daead:aes_siv_parameters", "//src/main/java/com/google/crypto/tink/daead:deterministic_aead_config", "//src/main/java/com/google/crypto/tink/daead:deterministic_aead_factory", "//src/main/java/com/google/crypto/tink/daead:deterministic_aead_key", "//src/main/java/com/google/crypto/tink/daead:deterministic_aead_key_templates", "//src/main/java/com/google/crypto/tink/daead:deterministic_aead_parameters", "//src/main/java/com/google/crypto/tink/daead:deterministic_aead_wrapper", "//src/main/java/com/google/crypto/tink/daead:predefined_deterministic_aead_parameters", "//src/main/java/com/google/crypto/tink/daead/internal:aes_siv_proto_serialization", "//src/main/java/com/google/crypto/tink/daead/internal:legacy_full_deterministic_aead", "//src/main/java/com/google/crypto/tink/hybrid:ecies_aead_hkdf_private_key_manager", "//src/main/java/com/google/crypto/tink/hybrid:ecies_aead_hkdf_public_key_manager", "//src/main/java/com/google/crypto/tink/hybrid:ecies_parameters", "//src/main/java/com/google/crypto/tink/hybrid:ecies_private_key", "//src/main/java/com/google/crypto/tink/hybrid:ecies_public_key", "//src/main/java/com/google/crypto/tink/hybrid:hpke_parameters", "//src/main/java/com/google/crypto/tink/hybrid:hpke_private_key", "//src/main/java/com/google/crypto/tink/hybrid:hpke_proto_serialization", "//src/main/java/com/google/crypto/tink/hybrid:hpke_public_key", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_config", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_decrypt_config", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_decrypt_factory", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_decrypt_wrapper", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_encrypt_config", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_encrypt_factory", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_encrypt_wrapper", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_key_templates", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_parameters", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_private_key", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_public_key", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_util", "//src/main/java/com/google/crypto/tink/hybrid:predefined_hybrid_parameters", "//src/main/java/com/google/crypto/tink/hybrid/internal:aes_gcm_hpke_aead", "//src/main/java/com/google/crypto/tink/hybrid/internal:chacha20_poly1305_hpke_aead", "//src/main/java/com/google/crypto/tink/hybrid/internal:ecies_proto_serialization", "//src/main/java/com/google/crypto/tink/hybrid/internal:hkdf_hpke_kdf", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_aead", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_context", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_decrypt", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_encrypt", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_kdf", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_kem", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_kem_encap_output", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_kem_key_factory", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_kem_private_key", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_primitive_factory", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_private_key_manager", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_public_key_manager", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_util", "//src/main/java/com/google/crypto/tink/hybrid/internal:legacy_full_hybrid_decrypt", "//src/main/java/com/google/crypto/tink/hybrid/internal:legacy_full_hybrid_encrypt", "//src/main/java/com/google/crypto/tink/hybrid/internal:nist_curves_hpke_kem", "//src/main/java/com/google/crypto/tink/hybrid/internal:nist_curves_hpke_kem_private_key", "//src/main/java/com/google/crypto/tink/hybrid/internal:x25519_hpke_kem", "//src/main/java/com/google/crypto/tink/hybrid/internal:x25519_hpke_kem_private_key", "//src/main/java/com/google/crypto/tink/hybrid/subtle:aead_or_daead", "//src/main/java/com/google/crypto/tink/hybrid/subtle:rsa_kem", "//src/main/java/com/google/crypto/tink/hybrid/subtle:rsa_kem_hybrid_decrypt", "//src/main/java/com/google/crypto/tink/hybrid/subtle:rsa_kem_hybrid_encrypt", "//src/main/java/com/google/crypto/tink/internal:big_integer_encoding", "//src/main/java/com/google/crypto/tink/internal:build_dispatched_code", "//src/main/java/com/google/crypto/tink/internal:curve25519", "//src/main/java/com/google/crypto/tink/internal:ed25519_cluster", "//src/main/java/com/google/crypto/tink/internal:elliptic_curves_util", "//src/main/java/com/google/crypto/tink/internal:enum_type_proto_converter", "//src/main/java/com/google/crypto/tink/internal:field25519", "//src/main/java/com/google/crypto/tink/internal:internal_configuration", "//src/main/java/com/google/crypto/tink/internal:json_parser", "//src/main/java/com/google/crypto/tink/internal:key_manager_registry", "//src/main/java/com/google/crypto/tink/internal:key_parser", "//src/main/java/com/google/crypto/tink/internal:key_serializer", "//src/main/java/com/google/crypto/tink/internal:key_status_type_proto_converter", "//src/main/java/com/google/crypto/tink/internal:key_template_proto_converter", "//src/main/java/com/google/crypto/tink/internal:legacy_key_manager_impl", "//src/main/java/com/google/crypto/tink/internal:legacy_proto_key", "//src/main/java/com/google/crypto/tink/internal:legacy_proto_parameters", "//src/main/java/com/google/crypto/tink/internal:monitoring_util", "//src/main/java/com/google/crypto/tink/internal:mutable_key_creation_registry", "//src/main/java/com/google/crypto/tink/internal:mutable_key_derivation_registry", "//src/main/java/com/google/crypto/tink/internal:mutable_monitoring_registry", "//src/main/java/com/google/crypto/tink/internal:mutable_parameters_registry", "//src/main/java/com/google/crypto/tink/internal:mutable_primitive_registry", "//src/main/java/com/google/crypto/tink/internal:mutable_serialization_registry", "//src/main/java/com/google/crypto/tink/internal:output_prefix_util", "//src/main/java/com/google/crypto/tink/internal:parameters_parser", "//src/main/java/com/google/crypto/tink/internal:parameters_serializer", "//src/main/java/com/google/crypto/tink/internal:primitive_constructor", "//src/main/java/com/google/crypto/tink/internal:primitive_factory", "//src/main/java/com/google/crypto/tink/internal:primitive_registry", "//src/main/java/com/google/crypto/tink/internal:primitive_set", "//src/main/java/com/google/crypto/tink/internal:proto_key_serialization", "//src/main/java/com/google/crypto/tink/internal:proto_parameters_serialization", "//src/main/java/com/google/crypto/tink/internal:random", "//src/main/java/com/google/crypto/tink/internal:registry_configuration", "//src/main/java/com/google/crypto/tink/internal:serialization", "//src/main/java/com/google/crypto/tink/internal:serialization_registry", "//src/main/java/com/google/crypto/tink/internal:tink_bug_exception", "//src/main/java/com/google/crypto/tink/internal:util", "//src/main/java/com/google/crypto/tink/jwt:json_util", "//src/main/java/com/google/crypto/tink/jwt:jwk_set_converter", "//src/main/java/com/google/crypto/tink/jwt:jwt_ecdsa_parameters", "//src/main/java/com/google/crypto/tink/jwt:jwt_ecdsa_private_key", "//src/main/java/com/google/crypto/tink/jwt:jwt_ecdsa_proto_serialization", "//src/main/java/com/google/crypto/tink/jwt:jwt_ecdsa_public_key", "//src/main/java/com/google/crypto/tink/jwt:jwt_ecdsa_sign_key_manager", "//src/main/java/com/google/crypto/tink/jwt:jwt_ecdsa_verify_key_manager", "//src/main/java/com/google/crypto/tink/jwt:jwt_format", "//src/main/java/com/google/crypto/tink/jwt:jwt_hmac_key", "//src/main/java/com/google/crypto/tink/jwt:jwt_hmac_key_manager", "//src/main/java/com/google/crypto/tink/jwt:jwt_hmac_parameters", "//src/main/java/com/google/crypto/tink/jwt:jwt_hmac_proto_serialization", "//src/main/java/com/google/crypto/tink/jwt:jwt_invalid_exception", "//src/main/java/com/google/crypto/tink/jwt:jwt_mac", "//src/main/java/com/google/crypto/tink/jwt:jwt_mac_config", "//src/main/java/com/google/crypto/tink/jwt:jwt_mac_key", "//src/main/java/com/google/crypto/tink/jwt:jwt_mac_parameters", "//src/main/java/com/google/crypto/tink/jwt:jwt_mac_wrapper", "//src/main/java/com/google/crypto/tink/jwt:jwt_names", "//src/main/java/com/google/crypto/tink/jwt:jwt_public_key_sign", "//src/main/java/com/google/crypto/tink/jwt:jwt_public_key_sign_internal", "//src/main/java/com/google/crypto/tink/jwt:jwt_public_key_sign_wrapper", "//src/main/java/com/google/crypto/tink/jwt:jwt_public_key_verify", "//src/main/java/com/google/crypto/tink/jwt:jwt_public_key_verify_internal", "//src/main/java/com/google/crypto/tink/jwt:jwt_public_key_verify_wrapper", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pkcs1_parameters", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pkcs1_private_key", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pkcs1_proto_serialization", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pkcs1_public_key", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pkcs1_sign_key_manager", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pkcs1_verify_key_manager", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pss_parameters", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pss_private_key", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pss_proto_serialization", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pss_public_key", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pss_sign_key_manager", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pss_verify_key_manager", "//src/main/java/com/google/crypto/tink/jwt:jwt_signature_config", "//src/main/java/com/google/crypto/tink/jwt:jwt_signature_parameters", "//src/main/java/com/google/crypto/tink/jwt:jwt_signature_private_key", "//src/main/java/com/google/crypto/tink/jwt:jwt_signature_public_key", "//src/main/java/com/google/crypto/tink/jwt:jwt_validator", "//src/main/java/com/google/crypto/tink/jwt:raw_jwt", "//src/main/java/com/google/crypto/tink/jwt:verified_jwt", "//src/main/java/com/google/crypto/tink/keyderivation:key_derivation_config", "//src/main/java/com/google/crypto/tink/keyderivation:key_derivation_key", "//src/main/java/com/google/crypto/tink/keyderivation:key_derivation_parameters", "//src/main/java/com/google/crypto/tink/keyderivation:keyset_deriver", "//src/main/java/com/google/crypto/tink/keyderivation:keyset_deriver_wrapper", "//src/main/java/com/google/crypto/tink/keyderivation:prf_based_key_derivation_key", "//src/main/java/com/google/crypto/tink/keyderivation:prf_based_key_derivation_parameters", "//src/main/java/com/google/crypto/tink/keyderivation/internal:key_deriver", "//src/main/java/com/google/crypto/tink/keyderivation/internal:keyset_deriver_wrapper", "//src/main/java/com/google/crypto/tink/keyderivation/internal:prf_based_deriver_key_manager", "//src/main/java/com/google/crypto/tink/keyderivation/internal:prf_based_key_derivation_key_proto_serialization", "//src/main/java/com/google/crypto/tink/keyderivation/internal:prf_based_key_deriver", "//src/main/java/com/google/crypto/tink/mac:aes_cmac_key", "//src/main/java/com/google/crypto/tink/mac:aes_cmac_key_manager", "//src/main/java/com/google/crypto/tink/mac:aes_cmac_parameters", "//src/main/java/com/google/crypto/tink/mac:chunked_mac", "//src/main/java/com/google/crypto/tink/mac:chunked_mac_computation", "//src/main/java/com/google/crypto/tink/mac:chunked_mac_verification", "//src/main/java/com/google/crypto/tink/mac:chunked_mac_wrapper", "//src/main/java/com/google/crypto/tink/mac:hmac_key", "//src/main/java/com/google/crypto/tink/mac:hmac_key_manager", "//src/main/java/com/google/crypto/tink/mac:hmac_parameters", "//src/main/java/com/google/crypto/tink/mac:mac_config", "//src/main/java/com/google/crypto/tink/mac:mac_factory", "//src/main/java/com/google/crypto/tink/mac:mac_key", "//src/main/java/com/google/crypto/tink/mac:mac_key_templates", "//src/main/java/com/google/crypto/tink/mac:mac_parameters", "//src/main/java/com/google/crypto/tink/mac:mac_wrapper", "//src/main/java/com/google/crypto/tink/mac:predefined_mac_parameters", "//src/main/java/com/google/crypto/tink/mac/internal:aes_cmac_proto_serialization", "//src/main/java/com/google/crypto/tink/mac/internal:aes_util", "//src/main/java/com/google/crypto/tink/mac/internal:chunked_aes_cmac_computation", "//src/main/java/com/google/crypto/tink/mac/internal:chunked_aes_cmac_impl", "//src/main/java/com/google/crypto/tink/mac/internal:chunked_aes_cmac_verification", "//src/main/java/com/google/crypto/tink/mac/internal:chunked_hmac_computation", "//src/main/java/com/google/crypto/tink/mac/internal:chunked_hmac_impl", "//src/main/java/com/google/crypto/tink/mac/internal:chunked_hmac_verification", "//src/main/java/com/google/crypto/tink/mac/internal:hmac_proto_serialization", "//src/main/java/com/google/crypto/tink/mac/internal:legacy_full_mac", "//src/main/java/com/google/crypto/tink/monitoring:monitoring_annotations", "//src/main/java/com/google/crypto/tink/monitoring:monitoring_client", "//src/main/java/com/google/crypto/tink/monitoring:monitoring_keyset_info", "//src/main/java/com/google/crypto/tink/prf:aes_cmac_prf_key", "//src/main/java/com/google/crypto/tink/prf:aes_cmac_prf_key_manager", "//src/main/java/com/google/crypto/tink/prf:aes_cmac_prf_parameters", "//src/main/java/com/google/crypto/tink/prf:hkdf_prf_key", "//src/main/java/com/google/crypto/tink/prf:hkdf_prf_key_manager", "//src/main/java/com/google/crypto/tink/prf:hkdf_prf_parameters", "//src/main/java/com/google/crypto/tink/prf:hmac_prf_key", "//src/main/java/com/google/crypto/tink/prf:hmac_prf_key_manager", "//src/main/java/com/google/crypto/tink/prf:hmac_prf_parameters", "//src/main/java/com/google/crypto/tink/prf:predefined_prf_parameters", "//src/main/java/com/google/crypto/tink/prf:prf_config", "//src/main/java/com/google/crypto/tink/prf:prf_key", "//src/main/java/com/google/crypto/tink/prf:prf_key_templates", "//src/main/java/com/google/crypto/tink/prf:prf_parameters", "//src/main/java/com/google/crypto/tink/prf:prf_set", "//src/main/java/com/google/crypto/tink/prf:prf_set_wrapper", "//src/main/java/com/google/crypto/tink/prf/internal:aes_cmac_prf_proto_serialization", "//src/main/java/com/google/crypto/tink/prf/internal:hkdf_prf_proto_serialization", "//src/main/java/com/google/crypto/tink/prf/internal:hmac_prf_proto_serialization", "//src/main/java/com/google/crypto/tink/prf/internal:legacy_full_prf", "//src/main/java/com/google/crypto/tink/signature:ecdsa_parameters", "//src/main/java/com/google/crypto/tink/signature:ecdsa_private_key", "//src/main/java/com/google/crypto/tink/signature:ecdsa_public_key", "//src/main/java/com/google/crypto/tink/signature:ecdsa_sign_key_manager", "//src/main/java/com/google/crypto/tink/signature:ecdsa_verify_key_manager", "//src/main/java/com/google/crypto/tink/signature:ed25519_parameters", "//src/main/java/com/google/crypto/tink/signature:ed25519_private_key", "//src/main/java/com/google/crypto/tink/signature:ed25519_private_key_manager", "//src/main/java/com/google/crypto/tink/signature:ed25519_public_key", "//src/main/java/com/google/crypto/tink/signature:ed25519_public_key_manager", "//src/main/java/com/google/crypto/tink/signature:predefined_signature_parameters", "//src/main/java/com/google/crypto/tink/signature:public_key_sign_config", "//src/main/java/com/google/crypto/tink/signature:public_key_sign_factory", "//src/main/java/com/google/crypto/tink/signature:public_key_sign_wrapper", "//src/main/java/com/google/crypto/tink/signature:public_key_verify_config", "//src/main/java/com/google/crypto/tink/signature:public_key_verify_factory", "//src/main/java/com/google/crypto/tink/signature:public_key_verify_wrapper", "//src/main/java/com/google/crypto/tink/signature:rsa_ssa_pkcs1_parameters", "//src/main/java/com/google/crypto/tink/signature:rsa_ssa_pkcs1_private_key", "//src/main/java/com/google/crypto/tink/signature:rsa_ssa_pkcs1_public_key", "//src/main/java/com/google/crypto/tink/signature:rsa_ssa_pkcs1_sign_key_manager", "//src/main/java/com/google/crypto/tink/signature:rsa_ssa_pkcs1_verify_key_manager", "//src/main/java/com/google/crypto/tink/signature:rsa_ssa_pss_parameters", "//src/main/java/com/google/crypto/tink/signature:rsa_ssa_pss_private_key", "//src/main/java/com/google/crypto/tink/signature:rsa_ssa_pss_public_key", "//src/main/java/com/google/crypto/tink/signature:rsa_ssa_pss_sign_key_manager", "//src/main/java/com/google/crypto/tink/signature:rsa_ssa_pss_verify_key_manager", "//src/main/java/com/google/crypto/tink/signature:signature_config", "//src/main/java/com/google/crypto/tink/signature:signature_key_templates", "//src/main/java/com/google/crypto/tink/signature:signature_parameters", "//src/main/java/com/google/crypto/tink/signature:signature_pem_keyset_reader", "//src/main/java/com/google/crypto/tink/signature:signature_private_key", "//src/main/java/com/google/crypto/tink/signature:signature_public_key", "//src/main/java/com/google/crypto/tink/signature/internal:ecdsa_proto_serialization", "//src/main/java/com/google/crypto/tink/signature/internal:ed25519_proto_serialization", "//src/main/java/com/google/crypto/tink/signature/internal:legacy_full_sign", "//src/main/java/com/google/crypto/tink/signature/internal:legacy_full_verify", "//src/main/java/com/google/crypto/tink/signature/internal:rsa_ssa_pkcs1_proto_serialization", "//src/main/java/com/google/crypto/tink/signature/internal:rsa_ssa_pss_proto_serialization", "//src/main/java/com/google/crypto/tink/signature/internal:sig_util", "//src/main/java/com/google/crypto/tink/streamingaead:aes_ctr_hmac_streaming_key", "//src/main/java/com/google/crypto/tink/streamingaead:aes_ctr_hmac_streaming_key_manager", "//src/main/java/com/google/crypto/tink/streamingaead:aes_ctr_hmac_streaming_parameters", "//src/main/java/com/google/crypto/tink/streamingaead:aes_gcm_hkdf_streaming_key", "//src/main/java/com/google/crypto/tink/streamingaead:aes_gcm_hkdf_streaming_key_manager", "//src/main/java/com/google/crypto/tink/streamingaead:aes_gcm_hkdf_streaming_parameters", "//src/main/java/com/google/crypto/tink/streamingaead:input_stream_decrypter", "//src/main/java/com/google/crypto/tink/streamingaead:predefined_streaming_aead_parameters", "//src/main/java/com/google/crypto/tink/streamingaead:readable_byte_channel_decrypter", "//src/main/java/com/google/crypto/tink/streamingaead:seekable_byte_channel_decrypter", "//src/main/java/com/google/crypto/tink/streamingaead:streaming_aead_config", "//src/main/java/com/google/crypto/tink/streamingaead:streaming_aead_factory", "//src/main/java/com/google/crypto/tink/streamingaead:streaming_aead_helper", "//src/main/java/com/google/crypto/tink/streamingaead:streaming_aead_key", "//src/main/java/com/google/crypto/tink/streamingaead:streaming_aead_key_templates", "//src/main/java/com/google/crypto/tink/streamingaead:streaming_aead_parameters", "//src/main/java/com/google/crypto/tink/streamingaead:streaming_aead_util", "//src/main/java/com/google/crypto/tink/streamingaead:streaming_aead_wrapper", "//src/main/java/com/google/crypto/tink/streamingaead/internal:aes_ctr_hmac_streaming_proto_serialization", "//src/main/java/com/google/crypto/tink/streamingaead/internal:aes_gcm_hkdf_streaming_proto_serialization", "//src/main/java/com/google/crypto/tink/streamingaead/internal:legacy_full_streaming_aead", "//src/main/java/com/google/crypto/tink/subtle:aes_ctr_hmac_streaming", "//src/main/java/com/google/crypto/tink/subtle:aes_ctr_jce_cipher", "//src/main/java/com/google/crypto/tink/subtle:aes_eax_jce", "//src/main/java/com/google/crypto/tink/subtle:aes_gcm_hkdf_streaming", "//src/main/java/com/google/crypto/tink/subtle:aes_gcm_jce", "//src/main/java/com/google/crypto/tink/subtle:aes_siv", "//src/main/java/com/google/crypto/tink/subtle:base64", "//src/main/java/com/google/crypto/tink/subtle:bytes", "//src/main/java/com/google/crypto/tink/subtle:cha_cha20", "//src/main/java/com/google/crypto/tink/subtle:cha_cha20_poly1305", "//src/main/java/com/google/crypto/tink/subtle:ecdsa_sign_jce", "//src/main/java/com/google/crypto/tink/subtle:ecdsa_verify_jce", "//src/main/java/com/google/crypto/tink/subtle:ecies_aead_hkdf_dem_helper", "//src/main/java/com/google/crypto/tink/subtle:ecies_aead_hkdf_hybrid_decrypt", "//src/main/java/com/google/crypto/tink/subtle:ecies_aead_hkdf_hybrid_encrypt", "//src/main/java/com/google/crypto/tink/subtle:ecies_hkdf_recipient_kem", "//src/main/java/com/google/crypto/tink/subtle:ecies_hkdf_sender_kem", "//src/main/java/com/google/crypto/tink/subtle:ed25519_sign", "//src/main/java/com/google/crypto/tink/subtle:ed25519_verify", "//src/main/java/com/google/crypto/tink/subtle:elliptic_curves", "//src/main/java/com/google/crypto/tink/subtle:encrypt_then_authenticate", "//src/main/java/com/google/crypto/tink/subtle:engine_wrapper", "//src/main/java/com/google/crypto/tink/subtle:enums", "//src/main/java/com/google/crypto/tink/subtle:hex", "//src/main/java/com/google/crypto/tink/subtle:hkdf", "//src/main/java/com/google/crypto/tink/subtle:ind_cpa_cipher", "//src/main/java/com/google/crypto/tink/subtle:kwp", "//src/main/java/com/google/crypto/tink/subtle:nonce_based_streaming_aead_cluster", "//src/main/java/com/google/crypto/tink/subtle:pem_key_type", "//src/main/java/com/google/crypto/tink/subtle:prf_aes_cmac", "//src/main/java/com/google/crypto/tink/subtle:prf_hmac_jce", "//src/main/java/com/google/crypto/tink/subtle:prf_mac", "//src/main/java/com/google/crypto/tink/subtle:random", "//src/main/java/com/google/crypto/tink/subtle:rewindable_readable_byte_channel", "//src/main/java/com/google/crypto/tink/subtle:rsa_ssa_pkcs1_sign_jce", "//src/main/java/com/google/crypto/tink/subtle:rsa_ssa_pkcs1_verify_jce", "//src/main/java/com/google/crypto/tink/subtle:rsa_ssa_pss_sign_jce", "//src/main/java/com/google/crypto/tink/subtle:rsa_ssa_pss_verify_jce", "//src/main/java/com/google/crypto/tink/subtle:selfkeytests_validators", "//src/main/java/com/google/crypto/tink/subtle:stream_segment_decrypter", "//src/main/java/com/google/crypto/tink/subtle:stream_segment_encrypter", "//src/main/java/com/google/crypto/tink/subtle:subtle_util_cluster", "//src/main/java/com/google/crypto/tink/subtle:validators", "//src/main/java/com/google/crypto/tink/subtle:x25519", "//src/main/java/com/google/crypto/tink/subtle:x_cha_cha20", "//src/main/java/com/google/crypto/tink/subtle:x_cha_cha20_poly1305", "//src/main/java/com/google/crypto/tink/subtle/prf", "//src/main/java/com/google/crypto/tink/subtle/prf:hkdf_streaming_prf", "//src/main/java/com/google/crypto/tink/subtle/prf:prf_impl", "//src/main/java/com/google/crypto/tink/subtle/prf:streaming_prf", "//src/main/java/com/google/crypto/tink/tinkkey:key_access", "//src/main/java/com/google/crypto/tink/tinkkey:key_handle", "//src/main/java/com/google/crypto/tink/tinkkey:secret_key_access", "//src/main/java/com/google/crypto/tink/tinkkey:tink_key", "//src/main/java/com/google/crypto/tink/tinkkey/internal:internal_key_handle", "//src/main/java/com/google/crypto/tink/tinkkey/internal:proto_key", "//src/main/java/com/google/crypto/tink/util:bytes", "//src/main/java/com/google/crypto/tink/util:keys_downloader", "//src/main/java/com/google/crypto/tink/util:secret_big_integer", "//src/main/java/com/google/crypto/tink/util:secret_bytes", ], ) gen_maven_jar_rules( name = "tink-android", doctitle = "Tink Cryptography API for Android", resources = glob([ "src/main/resources/**", ]), root_packages = [ "com.google.crypto.tink", ], shaded_packages = [ # The following package(s) will be shaded, according to the rules # specified in shading_rules. "com.google.protobuf", ], shading_rules = "jar_jar_rules.txt", deps = [ "//src/main/java/com/google/crypto/tink:accesses_partial_key-android", "//src/main/java/com/google/crypto/tink:aead-android", "//src/main/java/com/google/crypto/tink:binary_keyset_reader-android", "//src/main/java/com/google/crypto/tink:binary_keyset_writer-android", "//src/main/java/com/google/crypto/tink:catalogue-android", "//src/main/java/com/google/crypto/tink:cleartext_keyset_handle-android", "//src/main/java/com/google/crypto/tink:config-android", "//src/main/java/com/google/crypto/tink:configuration-android", "//src/main/java/com/google/crypto/tink:configuration_fips140_v2-android", "//src/main/java/com/google/crypto/tink:configuration_v0-android", "//src/main/java/com/google/crypto/tink:crypto_format-android", "//src/main/java/com/google/crypto/tink:deterministic_aead-android", "//src/main/java/com/google/crypto/tink:hybrid_decrypt-android", "//src/main/java/com/google/crypto/tink:hybrid_encrypt-android", "//src/main/java/com/google/crypto/tink:insecure_secret_key_access-android", "//src/main/java/com/google/crypto/tink:json_keyset_reader-android", "//src/main/java/com/google/crypto/tink:json_keyset_writer-android", "//src/main/java/com/google/crypto/tink:key-android", "//src/main/java/com/google/crypto/tink:key_manager-android", "//src/main/java/com/google/crypto/tink:key_status-android", "//src/main/java/com/google/crypto/tink:key_template-android", "//src/main/java/com/google/crypto/tink:key_templates-android", "//src/main/java/com/google/crypto/tink:key_wrap-android", "//src/main/java/com/google/crypto/tink:keyset_reader-android", "//src/main/java/com/google/crypto/tink:keyset_writer-android", "//src/main/java/com/google/crypto/tink:kms_client-android", "//src/main/java/com/google/crypto/tink:kms_clients-android", "//src/main/java/com/google/crypto/tink:legacy_keyset_serialization-android", "//src/main/java/com/google/crypto/tink:mac-android", "//src/main/java/com/google/crypto/tink:no_secret_keyset_handle-android", "//src/main/java/com/google/crypto/tink:parameters-android", "//src/main/java/com/google/crypto/tink:pem_key_type-android", "//src/main/java/com/google/crypto/tink:primitive_wrapper-android", "//src/main/java/com/google/crypto/tink:private_key-android", "//src/main/java/com/google/crypto/tink:private_key_manager-android", "//src/main/java/com/google/crypto/tink:public_key_sign-android", "//src/main/java/com/google/crypto/tink:public_key_verify-android", "//src/main/java/com/google/crypto/tink:registry-android", "//src/main/java/com/google/crypto/tink:registry_cluster-android", "//src/main/java/com/google/crypto/tink:registry_configuration-android", "//src/main/java/com/google/crypto/tink:secret_key_access-android", "//src/main/java/com/google/crypto/tink:streaming_aead-android", "//src/main/java/com/google/crypto/tink:tink_json_proto_keyset_format-android", "//src/main/java/com/google/crypto/tink:tink_proto_keyset_format-android", "//src/main/java/com/google/crypto/tink:tink_proto_parameters_format-android", "//src/main/java/com/google/crypto/tink:util-android", "//src/main/java/com/google/crypto/tink:version-android", "//src/main/java/com/google/crypto/tink/aead:aead_config-android", "//src/main/java/com/google/crypto/tink/aead:aead_factory-android", "//src/main/java/com/google/crypto/tink/aead:aead_key-android", "//src/main/java/com/google/crypto/tink/aead:aead_key_templates-android", "//src/main/java/com/google/crypto/tink/aead:aead_parameters-android", "//src/main/java/com/google/crypto/tink/aead:aead_wrapper-android", "//src/main/java/com/google/crypto/tink/aead:aes_ctr_hmac_aead_key-android", "//src/main/java/com/google/crypto/tink/aead:aes_ctr_hmac_aead_key_manager-android", "//src/main/java/com/google/crypto/tink/aead:aes_ctr_hmac_aead_parameters-android", "//src/main/java/com/google/crypto/tink/aead:aes_eax_key-android", "//src/main/java/com/google/crypto/tink/aead:aes_eax_key_manager-android", "//src/main/java/com/google/crypto/tink/aead:aes_eax_parameters-android", "//src/main/java/com/google/crypto/tink/aead:aes_gcm_key-android", "//src/main/java/com/google/crypto/tink/aead:aes_gcm_key_manager-android", "//src/main/java/com/google/crypto/tink/aead:aes_gcm_parameters-android", "//src/main/java/com/google/crypto/tink/aead:aes_gcm_siv_key-android", "//src/main/java/com/google/crypto/tink/aead:aes_gcm_siv_key_manager-android", "//src/main/java/com/google/crypto/tink/aead:aes_gcm_siv_parameters-android", "//src/main/java/com/google/crypto/tink/aead:cha_cha20_poly1305_key-android", "//src/main/java/com/google/crypto/tink/aead:cha_cha20_poly1305_key_manager-android", "//src/main/java/com/google/crypto/tink/aead:cha_cha20_poly1305_parameters-android", "//src/main/java/com/google/crypto/tink/aead:kms_aead_key_manager-android", "//src/main/java/com/google/crypto/tink/aead:kms_envelope_aead-android", "//src/main/java/com/google/crypto/tink/aead:kms_envelope_aead_key_manager-android", "//src/main/java/com/google/crypto/tink/aead:legacy_kms_aead_key-android", "//src/main/java/com/google/crypto/tink/aead:legacy_kms_aead_parameters-android", "//src/main/java/com/google/crypto/tink/aead:legacy_kms_aead_proto_serialization-android", "//src/main/java/com/google/crypto/tink/aead:legacy_kms_envelope_aead_key-android", "//src/main/java/com/google/crypto/tink/aead:legacy_kms_envelope_aead_parameters-android", "//src/main/java/com/google/crypto/tink/aead:legacy_kms_envelope_aead_proto_serialization-android", "//src/main/java/com/google/crypto/tink/aead:predefined_aead_parameters-android", "//src/main/java/com/google/crypto/tink/aead:x_cha_cha20_poly1305_key-android", "//src/main/java/com/google/crypto/tink/aead:x_cha_cha20_poly1305_key_manager-android", "//src/main/java/com/google/crypto/tink/aead:x_cha_cha20_poly1305_parameters-android", "//src/main/java/com/google/crypto/tink/aead/internal:aes_ctr_hmac_aead_proto_serialization-android", "//src/main/java/com/google/crypto/tink/aead/internal:aes_eax_proto_serialization-android", "//src/main/java/com/google/crypto/tink/aead/internal:aes_gcm_proto_serialization-android", "//src/main/java/com/google/crypto/tink/aead/internal:aes_gcm_siv_proto_serialization-android", "//src/main/java/com/google/crypto/tink/aead/internal:cha_cha20_poly1305_jce-android", "//src/main/java/com/google/crypto/tink/aead/internal:cha_cha20_poly1305_proto_serialization-android", "//src/main/java/com/google/crypto/tink/aead/internal:cha_cha20_util-android", "//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_aes_gcm_jce-android", "//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_cha_cha20-android", "//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_cha_cha20_base-android", "//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_cha_cha20_poly1305-android", "//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_cha_cha20_poly1305_base-android", "//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_cha_cha20_poly1305_jce-android", "//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_x_cha_cha20-android", "//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_x_cha_cha20_poly1305-android", "//src/main/java/com/google/crypto/tink/aead/internal:legacy_full_aead-android", "//src/main/java/com/google/crypto/tink/aead/internal:poly1305-android", "//src/main/java/com/google/crypto/tink/aead/internal:x_cha_cha20_poly1305_jce-android", "//src/main/java/com/google/crypto/tink/aead/internal:x_cha_cha20_poly1305_proto_serialization-android", "//src/main/java/com/google/crypto/tink/aead/subtle:aead_factory-android", "//src/main/java/com/google/crypto/tink/aead/subtle:aes_gcm_factory-android", "//src/main/java/com/google/crypto/tink/aead/subtle:aes_gcm_siv-android", "//src/main/java/com/google/crypto/tink/annotations:alpha-android", "//src/main/java/com/google/crypto/tink/config:tink_config-android", "//src/main/java/com/google/crypto/tink/config:tink_fips-android", "//src/main/java/com/google/crypto/tink/config/internal:tink_fips_status-android", "//src/main/java/com/google/crypto/tink/config/internal:tink_fips_util-android", "//src/main/java/com/google/crypto/tink/daead:aes_siv_key-android", "//src/main/java/com/google/crypto/tink/daead:aes_siv_key_manager-android", "//src/main/java/com/google/crypto/tink/daead:aes_siv_parameters-android", "//src/main/java/com/google/crypto/tink/daead:deterministic_aead_config-android", "//src/main/java/com/google/crypto/tink/daead:deterministic_aead_factory-android", "//src/main/java/com/google/crypto/tink/daead:deterministic_aead_key-android", "//src/main/java/com/google/crypto/tink/daead:deterministic_aead_key_templates-android", "//src/main/java/com/google/crypto/tink/daead:deterministic_aead_parameters-android", "//src/main/java/com/google/crypto/tink/daead:deterministic_aead_wrapper-android", "//src/main/java/com/google/crypto/tink/daead:predefined_deterministic_aead_parameters-android", "//src/main/java/com/google/crypto/tink/daead/internal:aes_siv_proto_serialization-android", "//src/main/java/com/google/crypto/tink/daead/internal:legacy_full_deterministic_aead-android", "//src/main/java/com/google/crypto/tink/hybrid:ecies_aead_hkdf_private_key_manager-android", "//src/main/java/com/google/crypto/tink/hybrid:ecies_aead_hkdf_public_key_manager-android", "//src/main/java/com/google/crypto/tink/hybrid:ecies_parameters-android", "//src/main/java/com/google/crypto/tink/hybrid:ecies_private_key-android", "//src/main/java/com/google/crypto/tink/hybrid:ecies_public_key-android", "//src/main/java/com/google/crypto/tink/hybrid:hpke_parameters-android", "//src/main/java/com/google/crypto/tink/hybrid:hpke_private_key-android", "//src/main/java/com/google/crypto/tink/hybrid:hpke_proto_serialization-android", "//src/main/java/com/google/crypto/tink/hybrid:hpke_public_key-android", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_config-android", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_decrypt_config-android", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_decrypt_factory-android", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_decrypt_wrapper-android", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_encrypt_config-android", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_encrypt_factory-android", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_encrypt_wrapper-android", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_key_templates-android", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_parameters-android", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_private_key-android", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_public_key-android", "//src/main/java/com/google/crypto/tink/hybrid:hybrid_util-android", "//src/main/java/com/google/crypto/tink/hybrid:predefined_hybrid_parameters-android", "//src/main/java/com/google/crypto/tink/hybrid/internal:aes_gcm_hpke_aead-android", "//src/main/java/com/google/crypto/tink/hybrid/internal:chacha20_poly1305_hpke_aead-android", "//src/main/java/com/google/crypto/tink/hybrid/internal:ecies_proto_serialization-android", "//src/main/java/com/google/crypto/tink/hybrid/internal:hkdf_hpke_kdf-android", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_aead-android", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_context-android", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_decrypt-android", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_encrypt-android", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_kdf-android", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_kem-android", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_kem_encap_output-android", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_kem_key_factory-android", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_kem_private_key-android", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_primitive_factory-android", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_private_key_manager-android", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_public_key_manager-android", "//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_util-android", "//src/main/java/com/google/crypto/tink/hybrid/internal:legacy_full_hybrid_decrypt-android", "//src/main/java/com/google/crypto/tink/hybrid/internal:legacy_full_hybrid_encrypt-android", "//src/main/java/com/google/crypto/tink/hybrid/internal:nist_curves_hpke_kem-android", "//src/main/java/com/google/crypto/tink/hybrid/internal:nist_curves_hpke_kem_private_key-android", "//src/main/java/com/google/crypto/tink/hybrid/internal:x25519_hpke_kem-android", "//src/main/java/com/google/crypto/tink/hybrid/internal:x25519_hpke_kem_private_key-android", "//src/main/java/com/google/crypto/tink/hybrid/subtle:aead_or_daead-android", "//src/main/java/com/google/crypto/tink/hybrid/subtle:rsa_kem-android", "//src/main/java/com/google/crypto/tink/hybrid/subtle:rsa_kem_hybrid_decrypt-android", "//src/main/java/com/google/crypto/tink/hybrid/subtle:rsa_kem_hybrid_encrypt-android", "//src/main/java/com/google/crypto/tink/integration/android:android_keyset_manager", "//src/main/java/com/google/crypto/tink/integration/android:android_keystore_aes_gcm", "//src/main/java/com/google/crypto/tink/integration/android:android_keystore_kms_client", "//src/main/java/com/google/crypto/tink/integration/android:shared_pref_keyset_reader", "//src/main/java/com/google/crypto/tink/integration/android:shared_pref_keyset_writer", "//src/main/java/com/google/crypto/tink/internal:big_integer_encoding-android", "//src/main/java/com/google/crypto/tink/internal:curve25519-android", "//src/main/java/com/google/crypto/tink/internal:ed25519_cluster-android", "//src/main/java/com/google/crypto/tink/internal:elliptic_curves_util-android", "//src/main/java/com/google/crypto/tink/internal:enum_type_proto_converter-android", "//src/main/java/com/google/crypto/tink/internal:field25519-android", "//src/main/java/com/google/crypto/tink/internal:internal_configuration-android", "//src/main/java/com/google/crypto/tink/internal:json_parser-android", "//src/main/java/com/google/crypto/tink/internal:key_manager_registry-android", "//src/main/java/com/google/crypto/tink/internal:key_parser-android", "//src/main/java/com/google/crypto/tink/internal:key_serializer-android", "//src/main/java/com/google/crypto/tink/internal:key_status_type_proto_converter-android", "//src/main/java/com/google/crypto/tink/internal:key_template_proto_converter-android", "//src/main/java/com/google/crypto/tink/internal:legacy_key_manager_impl-android", "//src/main/java/com/google/crypto/tink/internal:legacy_proto_key-android", "//src/main/java/com/google/crypto/tink/internal:legacy_proto_parameters-android", "//src/main/java/com/google/crypto/tink/internal:monitoring_util-android", "//src/main/java/com/google/crypto/tink/internal:mutable_key_creation_registry-android", "//src/main/java/com/google/crypto/tink/internal:mutable_key_derivation_registry-android", "//src/main/java/com/google/crypto/tink/internal:mutable_monitoring_registry-android", "//src/main/java/com/google/crypto/tink/internal:mutable_parameters_registry-android", "//src/main/java/com/google/crypto/tink/internal:mutable_primitive_registry-android", "//src/main/java/com/google/crypto/tink/internal:mutable_serialization_registry-android", "//src/main/java/com/google/crypto/tink/internal:output_prefix_util-android", "//src/main/java/com/google/crypto/tink/internal:parameters_parser-android", "//src/main/java/com/google/crypto/tink/internal:parameters_serializer-android", "//src/main/java/com/google/crypto/tink/internal:primitive_constructor-android", "//src/main/java/com/google/crypto/tink/internal:primitive_factory-android", "//src/main/java/com/google/crypto/tink/internal:primitive_registry-android", "//src/main/java/com/google/crypto/tink/internal:primitive_set-android", "//src/main/java/com/google/crypto/tink/internal:proto_key_serialization-android", "//src/main/java/com/google/crypto/tink/internal:proto_parameters_serialization-android", "//src/main/java/com/google/crypto/tink/internal:random-android", "//src/main/java/com/google/crypto/tink/internal:registry_configuration-android", "//src/main/java/com/google/crypto/tink/internal:serialization-android", "//src/main/java/com/google/crypto/tink/internal:serialization_registry-android", "//src/main/java/com/google/crypto/tink/internal:tink_bug_exception-android", "//src/main/java/com/google/crypto/tink/internal:util-android", "//src/main/java/com/google/crypto/tink/jwt:json_util-android", "//src/main/java/com/google/crypto/tink/jwt:jwk_set_converter-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_ecdsa_parameters-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_ecdsa_private_key-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_ecdsa_proto_serialization-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_ecdsa_public_key-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_ecdsa_sign_key_manager-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_ecdsa_verify_key_manager-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_format-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_hmac_key-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_hmac_key_manager-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_hmac_parameters-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_hmac_proto_serialization-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_invalid_exception-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_mac-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_mac_config-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_mac_key-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_mac_parameters-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_mac_wrapper-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_names-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_public_key_sign-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_public_key_sign_internal-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_public_key_sign_wrapper-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_public_key_verify-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_public_key_verify_internal-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_public_key_verify_wrapper-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pkcs1_parameters-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pkcs1_private_key-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pkcs1_proto_serialization-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pkcs1_public_key-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pkcs1_sign_key_manager-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pkcs1_verify_key_manager-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pss_parameters-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pss_private_key-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pss_proto_serialization-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pss_public_key-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pss_sign_key_manager-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pss_verify_key_manager-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_signature_config-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_signature_parameters-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_signature_private_key-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_signature_public_key-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_validator-android", "//src/main/java/com/google/crypto/tink/jwt:raw_jwt-android", "//src/main/java/com/google/crypto/tink/jwt:verified_jwt-android", "//src/main/java/com/google/crypto/tink/keyderivation:key_derivation_config-android", "//src/main/java/com/google/crypto/tink/keyderivation:key_derivation_key-android", "//src/main/java/com/google/crypto/tink/keyderivation:key_derivation_parameters-android", "//src/main/java/com/google/crypto/tink/keyderivation:keyset_deriver-android", "//src/main/java/com/google/crypto/tink/keyderivation:keyset_deriver_wrapper-android", "//src/main/java/com/google/crypto/tink/keyderivation:prf_based_key_derivation_key-android", "//src/main/java/com/google/crypto/tink/keyderivation:prf_based_key_derivation_parameters-android", "//src/main/java/com/google/crypto/tink/keyderivation/internal:key_deriver-android", "//src/main/java/com/google/crypto/tink/keyderivation/internal:keyset_deriver_wrapper-android", "//src/main/java/com/google/crypto/tink/keyderivation/internal:prf_based_deriver_key_manager-android", "//src/main/java/com/google/crypto/tink/keyderivation/internal:prf_based_key_derivation_key_proto_serialization-android", "//src/main/java/com/google/crypto/tink/keyderivation/internal:prf_based_key_deriver-android", "//src/main/java/com/google/crypto/tink/mac:aes_cmac_key-android", "//src/main/java/com/google/crypto/tink/mac:aes_cmac_key_manager-android", "//src/main/java/com/google/crypto/tink/mac:aes_cmac_parameters-android", "//src/main/java/com/google/crypto/tink/mac:chunked_mac-android", "//src/main/java/com/google/crypto/tink/mac:chunked_mac_computation-android", "//src/main/java/com/google/crypto/tink/mac:chunked_mac_verification-android", "//src/main/java/com/google/crypto/tink/mac:chunked_mac_wrapper-android", "//src/main/java/com/google/crypto/tink/mac:hmac_key-android", "//src/main/java/com/google/crypto/tink/mac:hmac_key_manager-android", "//src/main/java/com/google/crypto/tink/mac:hmac_parameters-android", "//src/main/java/com/google/crypto/tink/mac:mac_config-android", "//src/main/java/com/google/crypto/tink/mac:mac_factory-android", "//src/main/java/com/google/crypto/tink/mac:mac_key-android", "//src/main/java/com/google/crypto/tink/mac:mac_key_templates-android", "//src/main/java/com/google/crypto/tink/mac:mac_parameters-android", "//src/main/java/com/google/crypto/tink/mac:mac_wrapper-android", "//src/main/java/com/google/crypto/tink/mac:predefined_mac_parameters-android", "//src/main/java/com/google/crypto/tink/mac/internal:aes_cmac_proto_serialization-android", "//src/main/java/com/google/crypto/tink/mac/internal:aes_util-android", "//src/main/java/com/google/crypto/tink/mac/internal:chunked_aes_cmac_computation-android", "//src/main/java/com/google/crypto/tink/mac/internal:chunked_aes_cmac_impl-android", "//src/main/java/com/google/crypto/tink/mac/internal:chunked_aes_cmac_verification-android", "//src/main/java/com/google/crypto/tink/mac/internal:chunked_hmac_computation-android", "//src/main/java/com/google/crypto/tink/mac/internal:chunked_hmac_impl-android", "//src/main/java/com/google/crypto/tink/mac/internal:chunked_hmac_verification-android", "//src/main/java/com/google/crypto/tink/mac/internal:hmac_proto_serialization-android", "//src/main/java/com/google/crypto/tink/mac/internal:legacy_full_mac-android", "//src/main/java/com/google/crypto/tink/monitoring:monitoring_annotations-android", "//src/main/java/com/google/crypto/tink/monitoring:monitoring_client-android", "//src/main/java/com/google/crypto/tink/monitoring:monitoring_keyset_info-android", "//src/main/java/com/google/crypto/tink/prf:aes_cmac_prf_key-android", "//src/main/java/com/google/crypto/tink/prf:aes_cmac_prf_key_manager-android", "//src/main/java/com/google/crypto/tink/prf:aes_cmac_prf_parameters-android", "//src/main/java/com/google/crypto/tink/prf:hkdf_prf_key-android", "//src/main/java/com/google/crypto/tink/prf:hkdf_prf_key_manager-android", "//src/main/java/com/google/crypto/tink/prf:hkdf_prf_parameters-android", "//src/main/java/com/google/crypto/tink/prf:hmac_prf_key-android", "//src/main/java/com/google/crypto/tink/prf:hmac_prf_key_manager-android", "//src/main/java/com/google/crypto/tink/prf:hmac_prf_parameters-android", "//src/main/java/com/google/crypto/tink/prf:predefined_prf_parameters-android", "//src/main/java/com/google/crypto/tink/prf:prf_config-android", "//src/main/java/com/google/crypto/tink/prf:prf_key-android", "//src/main/java/com/google/crypto/tink/prf:prf_key_templates-android", "//src/main/java/com/google/crypto/tink/prf:prf_parameters-android", "//src/main/java/com/google/crypto/tink/prf:prf_set-android", "//src/main/java/com/google/crypto/tink/prf:prf_set_wrapper-android", "//src/main/java/com/google/crypto/tink/prf/internal:aes_cmac_prf_proto_serialization-android", "//src/main/java/com/google/crypto/tink/prf/internal:hkdf_prf_proto_serialization-android", "//src/main/java/com/google/crypto/tink/prf/internal:hmac_prf_proto_serialization-android", "//src/main/java/com/google/crypto/tink/prf/internal:legacy_full_prf-android", "//src/main/java/com/google/crypto/tink/signature:ecdsa_parameters-android", "//src/main/java/com/google/crypto/tink/signature:ecdsa_private_key-android", "//src/main/java/com/google/crypto/tink/signature:ecdsa_public_key-android", "//src/main/java/com/google/crypto/tink/signature:ecdsa_sign_key_manager-android", "//src/main/java/com/google/crypto/tink/signature:ecdsa_verify_key_manager-android", "//src/main/java/com/google/crypto/tink/signature:ed25519_parameters-android", "//src/main/java/com/google/crypto/tink/signature:ed25519_private_key-android", "//src/main/java/com/google/crypto/tink/signature:ed25519_private_key_manager-android", "//src/main/java/com/google/crypto/tink/signature:ed25519_public_key-android", "//src/main/java/com/google/crypto/tink/signature:ed25519_public_key_manager-android", "//src/main/java/com/google/crypto/tink/signature:predefined_signature_parameters-android", "//src/main/java/com/google/crypto/tink/signature:public_key_sign_config-android", "//src/main/java/com/google/crypto/tink/signature:public_key_sign_factory-android", "//src/main/java/com/google/crypto/tink/signature:public_key_sign_wrapper-android", "//src/main/java/com/google/crypto/tink/signature:public_key_verify_config-android", "//src/main/java/com/google/crypto/tink/signature:public_key_verify_factory-android", "//src/main/java/com/google/crypto/tink/signature:public_key_verify_wrapper-android", "//src/main/java/com/google/crypto/tink/signature:rsa_ssa_pkcs1_parameters-android", "//src/main/java/com/google/crypto/tink/signature:rsa_ssa_pkcs1_private_key-android", "//src/main/java/com/google/crypto/tink/signature:rsa_ssa_pkcs1_public_key-android", "//src/main/java/com/google/crypto/tink/signature:rsa_ssa_pkcs1_sign_key_manager-android", "//src/main/java/com/google/crypto/tink/signature:rsa_ssa_pkcs1_verify_key_manager-android", "//src/main/java/com/google/crypto/tink/signature:rsa_ssa_pss_parameters-android", "//src/main/java/com/google/crypto/tink/signature:rsa_ssa_pss_private_key-android", "//src/main/java/com/google/crypto/tink/signature:rsa_ssa_pss_public_key-android", "//src/main/java/com/google/crypto/tink/signature:rsa_ssa_pss_sign_key_manager-android", "//src/main/java/com/google/crypto/tink/signature:rsa_ssa_pss_verify_key_manager-android", "//src/main/java/com/google/crypto/tink/signature:signature_config-android", "//src/main/java/com/google/crypto/tink/signature:signature_key_templates-android", "//src/main/java/com/google/crypto/tink/signature:signature_parameters-android", "//src/main/java/com/google/crypto/tink/signature:signature_pem_keyset_reader-android", "//src/main/java/com/google/crypto/tink/signature:signature_private_key-android", "//src/main/java/com/google/crypto/tink/signature:signature_public_key-android", "//src/main/java/com/google/crypto/tink/signature/internal:ecdsa_proto_serialization-android", "//src/main/java/com/google/crypto/tink/signature/internal:ed25519_proto_serialization-android", "//src/main/java/com/google/crypto/tink/signature/internal:legacy_full_sign-android", "//src/main/java/com/google/crypto/tink/signature/internal:legacy_full_verify-android", "//src/main/java/com/google/crypto/tink/signature/internal:rsa_ssa_pkcs1_proto_serialization-android", "//src/main/java/com/google/crypto/tink/signature/internal:rsa_ssa_pss_proto_serialization-android", "//src/main/java/com/google/crypto/tink/signature/internal:sig_util-android", "//src/main/java/com/google/crypto/tink/streamingaead:aes_ctr_hmac_streaming_key-android", "//src/main/java/com/google/crypto/tink/streamingaead:aes_ctr_hmac_streaming_key_manager-android", "//src/main/java/com/google/crypto/tink/streamingaead:aes_ctr_hmac_streaming_parameters-android", "//src/main/java/com/google/crypto/tink/streamingaead:aes_gcm_hkdf_streaming_key-android", "//src/main/java/com/google/crypto/tink/streamingaead:aes_gcm_hkdf_streaming_key_manager-android", "//src/main/java/com/google/crypto/tink/streamingaead:aes_gcm_hkdf_streaming_parameters-android", "//src/main/java/com/google/crypto/tink/streamingaead:input_stream_decrypter-android", "//src/main/java/com/google/crypto/tink/streamingaead:predefined_streaming_aead_parameters-android", "//src/main/java/com/google/crypto/tink/streamingaead:readable_byte_channel_decrypter-android", "//src/main/java/com/google/crypto/tink/streamingaead:seekable_byte_channel_decrypter-android", "//src/main/java/com/google/crypto/tink/streamingaead:streaming_aead_config-android", "//src/main/java/com/google/crypto/tink/streamingaead:streaming_aead_factory-android", "//src/main/java/com/google/crypto/tink/streamingaead:streaming_aead_helper-android", "//src/main/java/com/google/crypto/tink/streamingaead:streaming_aead_key-android", "//src/main/java/com/google/crypto/tink/streamingaead:streaming_aead_key_templates-android", "//src/main/java/com/google/crypto/tink/streamingaead:streaming_aead_parameters-android", "//src/main/java/com/google/crypto/tink/streamingaead:streaming_aead_util-android", "//src/main/java/com/google/crypto/tink/streamingaead:streaming_aead_wrapper-android", "//src/main/java/com/google/crypto/tink/streamingaead/internal:aes_ctr_hmac_streaming_proto_serialization-android", "//src/main/java/com/google/crypto/tink/streamingaead/internal:aes_gcm_hkdf_streaming_proto_serialization-android", "//src/main/java/com/google/crypto/tink/streamingaead/internal:legacy_full_streaming_aead-android", "//src/main/java/com/google/crypto/tink/subtle:aes_ctr_hmac_streaming-android", "//src/main/java/com/google/crypto/tink/subtle:aes_ctr_jce_cipher-android", "//src/main/java/com/google/crypto/tink/subtle:aes_eax_jce-android", "//src/main/java/com/google/crypto/tink/subtle:aes_gcm_hkdf_streaming-android", "//src/main/java/com/google/crypto/tink/subtle:aes_gcm_jce-android", "//src/main/java/com/google/crypto/tink/subtle:aes_siv-android", "//src/main/java/com/google/crypto/tink/subtle:base64-android", "//src/main/java/com/google/crypto/tink/subtle:bytes-android", "//src/main/java/com/google/crypto/tink/subtle:cha_cha20-android", "//src/main/java/com/google/crypto/tink/subtle:cha_cha20_poly1305-android", "//src/main/java/com/google/crypto/tink/subtle:ecdsa_sign_jce-android", "//src/main/java/com/google/crypto/tink/subtle:ecdsa_verify_jce-android", "//src/main/java/com/google/crypto/tink/subtle:ecies_aead_hkdf_dem_helper-android", "//src/main/java/com/google/crypto/tink/subtle:ecies_aead_hkdf_hybrid_decrypt-android", "//src/main/java/com/google/crypto/tink/subtle:ecies_aead_hkdf_hybrid_encrypt-android", "//src/main/java/com/google/crypto/tink/subtle:ecies_hkdf_recipient_kem-android", "//src/main/java/com/google/crypto/tink/subtle:ecies_hkdf_sender_kem-android", "//src/main/java/com/google/crypto/tink/subtle:ed25519_sign-android", "//src/main/java/com/google/crypto/tink/subtle:ed25519_verify-android", "//src/main/java/com/google/crypto/tink/subtle:elliptic_curves-android", "//src/main/java/com/google/crypto/tink/subtle:encrypt_then_authenticate-android", "//src/main/java/com/google/crypto/tink/subtle:engine_wrapper-android", "//src/main/java/com/google/crypto/tink/subtle:enums-android", "//src/main/java/com/google/crypto/tink/subtle:hex-android", "//src/main/java/com/google/crypto/tink/subtle:hkdf-android", "//src/main/java/com/google/crypto/tink/subtle:ind_cpa_cipher-android", "//src/main/java/com/google/crypto/tink/subtle:kwp-android", "//src/main/java/com/google/crypto/tink/subtle:nonce_based_streaming_aead_cluster-android", "//src/main/java/com/google/crypto/tink/subtle:pem_key_type-android", "//src/main/java/com/google/crypto/tink/subtle:prf_aes_cmac-android", "//src/main/java/com/google/crypto/tink/subtle:prf_hmac_jce-android", "//src/main/java/com/google/crypto/tink/subtle:prf_mac-android", "//src/main/java/com/google/crypto/tink/subtle:random-android", "//src/main/java/com/google/crypto/tink/subtle:rewindable_readable_byte_channel-android", "//src/main/java/com/google/crypto/tink/subtle:rsa_ssa_pkcs1_sign_jce-android", "//src/main/java/com/google/crypto/tink/subtle:rsa_ssa_pkcs1_verify_jce-android", "//src/main/java/com/google/crypto/tink/subtle:rsa_ssa_pss_sign_jce-android", "//src/main/java/com/google/crypto/tink/subtle:rsa_ssa_pss_verify_jce-android", "//src/main/java/com/google/crypto/tink/subtle:selfkeytests_validators-android", "//src/main/java/com/google/crypto/tink/subtle:stream_segment_decrypter-android", "//src/main/java/com/google/crypto/tink/subtle:stream_segment_encrypter-android", "//src/main/java/com/google/crypto/tink/subtle:subtle_util_cluster-android", "//src/main/java/com/google/crypto/tink/subtle:validators-android", "//src/main/java/com/google/crypto/tink/subtle:x25519-android", "//src/main/java/com/google/crypto/tink/subtle:x_cha_cha20-android", "//src/main/java/com/google/crypto/tink/subtle:x_cha_cha20_poly1305-android", "//src/main/java/com/google/crypto/tink/subtle/prf:hkdf_streaming_prf-android", "//src/main/java/com/google/crypto/tink/subtle/prf:prf_impl-android", "//src/main/java/com/google/crypto/tink/subtle/prf:streaming_prf-android", "//src/main/java/com/google/crypto/tink/tinkkey:key_access-android", "//src/main/java/com/google/crypto/tink/tinkkey:key_handle-android", "//src/main/java/com/google/crypto/tink/tinkkey:secret_key_access-android", "//src/main/java/com/google/crypto/tink/tinkkey:tink_key-android", "//src/main/java/com/google/crypto/tink/tinkkey/internal:internal_key_handle-android", "//src/main/java/com/google/crypto/tink/tinkkey/internal:proto_key-android", "//src/main/java/com/google/crypto/tink/util:bytes-android", "//src/main/java/com/google/crypto/tink/util:secret_big_integer-android", "//src/main/java/com/google/crypto/tink/util:secret_bytes-android", "//src_android/main/java/com/google/crypto/tink/internal:build_dispatched_code", ], ) gen_maven_jar_rules( name = "tink-awskms", doctitle = "Tink Cryptography API with AWS KMS", manifest_lines = [ "Automatic-Module-Name: com.google.crypto.tink.integration.awskms", ], root_packages = [ "com.google.crypto.tink.integration.awskms", ], deps = [ "//src/main/java/com/google/crypto/tink/integration/awskms:aws_kms_aead", "//src/main/java/com/google/crypto/tink/integration/awskms:aws_kms_client", ], ) gen_maven_jar_rules( name = "tink-gcpkms", doctitle = "Tink Cryptography API with Google Cloud KMS", manifest_lines = [ "Automatic-Module-Name: com.google.crypto.tink.integration.gcpkms", ], root_packages = [ "com.google.crypto.tink.integration.gcpkms", ], deps = [ "//src/main/java/com/google/crypto/tink/integration/gcpkms:fake_key_management_service_client", "//src/main/java/com/google/crypto/tink/integration/gcpkms:gcp_kms_aead", "//src/main/java/com/google/crypto/tink/integration/gcpkms:gcp_kms_client", ], ) ================================================ FILE: java_src/WORKSPACE ================================================ workspace(name = "tink_java") load("@tink_java//:tink_java_deps.bzl", "TINK_MAVEN_ARTIFACTS", "tink_java_deps") tink_java_deps() load("@tink_java//:tink_java_deps_init.bzl", "tink_java_deps_init") tink_java_deps_init() load("@rules_jvm_external//:defs.bzl", "maven_install") load("@rules_jvm_external//:specs.bzl", "maven") maven_install( artifacts = TINK_MAVEN_ARTIFACTS + [ # This is needed to add grpc-core while removing a circular dependency # between grpc-core and grpc-util. # # See https://github.com/grpc/grpc-java/issues/10576. maven.artifact( artifact = "grpc-core", exclusions = [ "io.grpc:grpc-util", ], group = "io.grpc", version = "1.59.1", ), ], repositories = [ "https://maven.google.com", "https://repo1.maven.org/maven2", ], ) ================================================ FILE: java_src/examples/.bazelignore ================================================ [File too large to display: 8 B] ================================================ FILE: java_src/examples/.bazelrc ================================================ # Minumum C++ version. Override it building this project with # `bazel build --cxxopt='-std=c++<XY>' --host_cxxopt='c++<XY>' ...` # (Both -std and --host_cxxopt must be set to force the desired version.) build --cxxopt='-std=c++14' --host_cxxopt='-std=c++14' ================================================ FILE: java_src/examples/.bazelversion ================================================ 6.0.0 ================================================ FILE: java_src/examples/BUILD.bazel ================================================ ================================================ FILE: java_src/examples/WORKSPACE ================================================ workspace(name = "tink_java_examples") # The local_repository() rule is used below because the workspaces referenced # are all located within the Tink git repository. # # To replicate this setup in a workspace located in a separate repository, you # can: # # 1. Load the http_archive() rule by using: # # load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") # # 2. Use the equivalent, commented-out http_archive() rules below as a starting # point. # # See the Tink Java HOW-TO for more details: # https://github.com/google/tink/blob/master/docs/JAVA-HOWTO.md local_repository( name = "tink_java", path = "../", ) # http_archive( # name = "tink_java", # urls = ["https://github.com/google/tink/archive/master.zip"], # strip_prefix = "tink-master/java_src", # ) # Load Tink dependencies. load("@tink_java//:tink_java_deps.bzl", "TINK_MAVEN_ARTIFACTS", "tink_java_deps") tink_java_deps() load("@tink_java//:tink_java_deps_init.bzl", "tink_java_deps_init") tink_java_deps_init() load("@rules_jvm_external//:defs.bzl", "maven_install") load("@rules_jvm_external//:specs.bzl", "maven") maven_install( artifacts = TINK_MAVEN_ARTIFACTS + [ "args4j:args4j:2.33", "com.google.cloud:google-cloud-storage:2.28.0", # This is needed to add grpc-core while removing a circular dependency # between grpc-core and grpc-util. # # See https://github.com/grpc/grpc-java/issues/10576. maven.artifact( artifact = "grpc-core", exclusions = [ "io.grpc:grpc-util", ], group = "io.grpc", version = "1.59.1", ), ], repositories = [ "https://maven.google.com", "https://repo1.maven.org/maven2", ], ) ================================================ FILE: java_src/examples/aead/AeadExample.java ================================================ /** * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ // [START aead-example] package aead; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.crypto.tink.Aead; import com.google.crypto.tink.InsecureSecretKeyAccess; import com.google.crypto.tink.KeysetHandle; import com.google.crypto.tink.TinkJsonProtoKeysetFormat; import com.google.crypto.tink.aead.AeadConfig; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; /** * A command-line utility for encrypting small files with AEAD. * * <p>It loads cleartext keys from disk - this is not recommended! * * <p>It requires the following arguments: * * <ul> * <li>mode: Can be "encrypt" or "decrypt" to encrypt/decrypt the input to the output. * <li>key-file: Read the key material from this file. * <li>input-file: Read the input from this file. * <li>output-file: Write the result to this file. * <li>[optional] associated-data: Associated data used for the encryption or decryption. */ public final class AeadExample { private static final String MODE_ENCRYPT = "encrypt"; private static final String MODE_DECRYPT = "decrypt"; public static void main(String[] args) throws Exception { if (args.length != 4 && args.length != 5) { System.err.printf("Expected 4 or 5 parameters, got %d\n", args.length); System.err.println( "Usage: java AeadExample encrypt/decrypt key-file input-file output-file" + " [associated-data]"); System.exit(1); } String mode = args[0]; Path keyFile = Paths.get(args[1]); Path inputFile = Paths.get(args[2]); Path outputFile = Paths.get(args[3]); byte[] associatedData = new byte[0]; if (args.length == 5) { associatedData = args[4].getBytes(UTF_8); } // Register all AEAD key types with the Tink runtime. AeadConfig.register(); // Read the keyset into a KeysetHandle. KeysetHandle handle = TinkJsonProtoKeysetFormat.parseKeyset( new String(Files.readAllBytes(keyFile), UTF_8), InsecureSecretKeyAccess.get()); // Get the primitive. Aead aead = handle.getPrimitive(Aead.class); // Use the primitive to encrypt/decrypt files. if (MODE_ENCRYPT.equals(mode)) { byte[] plaintext = Files.readAllBytes(inputFile); byte[] ciphertext = aead.encrypt(plaintext, associatedData); Files.write(outputFile, ciphertext); } else if (MODE_DECRYPT.equals(mode)) { byte[] ciphertext = Files.readAllBytes(inputFile); byte[] plaintext = aead.decrypt(ciphertext, associatedData); Files.write(outputFile, plaintext); } else { System.err.println("The first argument must be either encrypt or decrypt, got: " + mode); System.exit(1); } } private AeadExample() {} } // [END aead-example] ================================================ FILE: java_src/examples/aead/BUILD.bazel ================================================ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) exports_files(["aead_test_keyset.json"]) java_binary( name = "aead_example", srcs = ["AeadExample.java"], main_class = "aead.AeadExample", deps = [ "@tink_java//src/main/java/com/google/crypto/tink:aead", "@tink_java//src/main/java/com/google/crypto/tink:insecure_secret_key_access", "@tink_java//src/main/java/com/google/crypto/tink:registry_cluster", "@tink_java//src/main/java/com/google/crypto/tink:tink_json_proto_keyset_format", "@tink_java//src/main/java/com/google/crypto/tink/aead:aead_config", ], ) sh_test( name = "aead_example_test", size = "small", srcs = ["aead_example_test.sh"], args = [ "$(rootpath :aead_example)", "$(rootpath :aead_test_keyset.json)", ], data = [ ":aead_example", ":aead_test_keyset.json", ], ) ================================================ FILE: java_src/examples/aead/README.md ================================================ [File too large to display: 929 B] ================================================ FILE: java_src/examples/aead/aead_example_test.sh ================================================ #!/bin/bash # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ################################################################################ set -euo pipefail ############################################################################# ##### Tests for AEAD example. CLI="$1" KEYSET_FILE="$2" DATA_FILE="${TEST_TMPDIR}/example_data.txt" echo "This is some plaintext to be encrypted." > ${DATA_FILE} ############################################################################# # A helper function for getting the return code of a command that may fail # Temporarily disables error safety and stores return value in ${TEST_STATUS} # Usage: # % test_command somecommand some args # % echo ${TEST_STATUS} test_command() { set +e "$@" TEST_STATUS=$? set -e } ############################################################################# #### Test initialization and encryption test_name="encrypt" echo "+++ Starting test ${test_name}..." ##### Run encryption test_command ${CLI} encrypt ${KEYSET_FILE} ${DATA_FILE} "${DATA_FILE}.encrypted" if [[ ${TEST_STATUS} -eq 0 ]]; then echo "+++ Success: file was encrypted." else echo "--- Failure: could not encrypt file." exit 1 fi ############################################################################# #### Test if decryption succeeds and returns original file test_name="decrypt" echo "+++ Starting test $test_name..." ##### Run decryption test_command ${CLI} decrypt ${KEYSET_FILE} ${DATA_FILE}.encrypted "${DATA_FILE}.decrypted" if [[ ${TEST_STATUS} -eq 0 ]]; then echo "+++ Success: file was successfully decrypted." else echo "--- Failure: could not decrypt file." exit 1 fi if cmp -s $DATA_FILE "$DATA_FILE.decrypted"; then echo "+++ Success: file content is the same after decryption." else echo "--- Failure: file content is not the same after decryption." exit 1 fi ############################################################################# #### Test decryption fails with modified ciphertext test_name="test_encrypt_decrypt_fails_with_modified_ciphertext" echo "+++ Starting test ${test_name}..." ##### Run encryption test_command ${CLI} encrypt ${KEYSET_FILE} ${DATA_FILE} "${DATA_FILE}.encrypted" if [[ ${TEST_STATUS} -eq 0 ]]; then echo "+++ Encryption successful." else echo "--- Encryption failed." exit 1 fi # Modify ciphertext echo "modified" >> ${DATA_FILE}.encrypted ##### Run decryption test_command ${CLI} decrypt ${KEYSET_FILE} ${DATA_FILE}.encrypted "${DATA_FILE}.decrypted" if [[ ${TEST_STATUS} -eq 1 ]]; then echo "+++ Decryption failed as expected." else echo "--- Decryption succeeded but expected to fail." exit 1 fi ############################################################################# #### Test correct encryption and decryption with associated data test_name="test_encrypt_decrypt_succeeds_with_associated_data" echo "+++ Starting test ${test_name}..." ##### Run encryption ASSOCIATED_DATA="header information" test_command ${CLI} encrypt ${KEYSET_FILE} ${DATA_FILE} "${DATA_FILE}.encrypted" "${ASSOCIATED_DATA}" if [[ ${TEST_STATUS} -eq 0 ]]; then echo "+++ Encryption successful." else echo "--- Encryption failed." exit 1 fi ##### Run decryption test_command ${CLI} decrypt ${KEYSET_FILE} ${DATA_FILE}.encrypted "${DATA_FILE}.decrypted" "${ASSOCIATED_DATA}" if [[ ${TEST_STATUS} -eq 0 ]]; then echo "+++ Decryption successful." else echo "--- Decryption failed." exit 1 fi cmp --silent ${DATA_FILE} ${DATA_FILE}.decrypted ############################################################################# #### Test decryption fails with modified associated data test_name="test_encrypt_decrypt_fails_with_modified_associated_data" echo "+++ Starting test ${test_name}..." ##### Run encryption ASSOCIATED_DATA="header information" test_command ${CLI} encrypt ${KEYSET_FILE} ${DATA_FILE} "${DATA_FILE}.encrypted" "${ASSOCIATED_DATA}" if [[ ${TEST_STATUS} -eq 0 ]]; then echo "+++ Encryption successful." else echo "--- Encryption failed." exit 1 fi ##### Run decryption MODIFIED_ASSOCIATED_DATA="modified header information" test_command ${CLI} decrypt ${KEYSET_FILE} ${DATA_FILE}.encrypted "${DATA_FILE}.decrypted" "${MODIFIED_ASSOCIATED_DATA}" if [[ ${TEST_STATUS} -eq 1 ]]; then echo "+++ Decryption failed as expected." else echo "--- Decryption succeeded but expected to fail." exit 1 fi ================================================ FILE: java_src/examples/aead/aead_test_keyset.json ================================================ { "primaryKeyId":1931667682, "key":[{ "keyData":{ "typeUrl":"type.googleapis.com/google.crypto.tink.AesGcmKey", "value":"GhD+9l0RANZjzZEZ8PDp7LRW", "keyMaterialType":"SYMMETRIC"}, "status":"ENABLED", "keyId":1931667682, "outputPrefixType":"TINK" }] } ================================================ FILE: java_src/examples/android/helloworld/README.md ================================================ # Android Hello World This is a simple app that allows encrypting and decrypting strings with keys stored in private shared preferences. On Android M or newer the keys are further encrypted with a master key stored in Android Keystore. It demonstrates the basic steps of using Tink, namely generating or loading key material, obtaining a primitive, and using the primitive to do crypto. It also shows how one can add a dependency on Tink using Gradle. The easiest way to build this app is to import it to Android Studio. You can also [build it from the command line](https://developer.android.com/studio/build/building-cmdline). ================================================ FILE: java_src/examples/android/helloworld/app/build.gradle ================================================ apply plugin: 'com.android.application' android { compileSdkVersion 29 defaultConfig { applicationId "com.helloworld" minSdkVersion 23 targetSdkVersion 29 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility 1.8 targetCompatibility 1.8 } lintOptions { abortOnError false } } apply from: "maven_${mavenLocation}.gradle" dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' // This is already included in protobuf-lite that Tink depends on. exclude group: 'com.google.code.findbugs' }) implementation 'com.android.support:appcompat-v7:26.+' implementation 'com.android.support:design:26.+' testImplementation 'junit:junit:4.12' // Tink HEAD-SNAPSHOT for Android. // In production apps, please use a named version, e.g., 1.4.0. implementation 'com.google.crypto.tink:tink-android:HEAD-SNAPSHOT' // An artificial dependency to test whether Tink can co-exist with other // protobuf dependencies. Please remove from production apps. implementation 'com.google.protobuf:protobuf-lite:3.0.1' } ================================================ FILE: java_src/examples/android/helloworld/app/maven_local.gradle ================================================ repositories { mavenLocal() } ================================================ FILE: java_src/examples/android/helloworld/app/maven_snapshot.gradle ================================================ repositories { maven { url "https://oss.sonatype.org/content/repositories/snapshots" } } ================================================ FILE: java_src/examples/android/helloworld/app/src/main/AndroidManifest.xml ================================================ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.helloworld"> <!-- To auto-complete the email text field in the login form with the user's emails --> <application android:name=".TinkApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> ================================================ FILE: java_src/examples/android/helloworld/app/src/main/java/com/helloworld/MainActivity.java ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.helloworld; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Base64; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import com.google.protobuf.ByteString; import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; /** This activity allows users to encrypt and decrypt a string. */ public class MainActivity extends AppCompatActivity { private TinkApplication mApplication; private EditText mPlaintextView; private EditText mAssociatedDataView; private EditText mCiphertextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mApplication = (TinkApplication) getApplicationContext(); mPlaintextView = (EditText) findViewById(R.id.plaintext); mAssociatedDataView = (EditText) findViewById(R.id.associated_data); mCiphertextView = (EditText) findViewById(R.id.ciphertext); Button mEncryptButton = (Button) findViewById(R.id.encrypt_button); mEncryptButton.setOnClickListener( new OnClickListener() { @Override public void onClick(View view) { attemptEncrypt(); } }); Button mDecryptButton = (Button) findViewById(R.id.decrypt_button); mDecryptButton.setOnClickListener( new OnClickListener() { @Override public void onClick(View view) { attemptDecrypt(); } }); } private void attemptEncrypt() { mPlaintextView.setError(null); mCiphertextView.setError(null); mCiphertextView.setText(""); try { byte[] plaintext = mPlaintextView.getText().toString().getBytes(StandardCharsets.UTF_8); // An artifical step to test whether Tink can co-exist with protobuf-lite. ByteString pStr = ByteString.copyFrom(plaintext); byte[] associatedData = mAssociatedDataView.getText().toString().getBytes(StandardCharsets.UTF_8); byte[] ciphertext = mApplication.aead.encrypt(pStr.toByteArray(), associatedData); mCiphertextView.setText(base64Encode(ciphertext)); } catch (GeneralSecurityException | IllegalArgumentException e) { mCiphertextView.setError( String.format("%s: %s", getString(R.string.error_cannot_encrypt), e.toString())); mPlaintextView.requestFocus(); } } private void attemptDecrypt() { mPlaintextView.setError(null); mPlaintextView.setText(""); mCiphertextView.setError(null); try { byte[] ciphertext = base64Decode(mCiphertextView.getText().toString()); byte[] associatedData = mAssociatedDataView.getText().toString().getBytes(StandardCharsets.UTF_8); byte[] plaintext = mApplication.aead.decrypt(ciphertext, associatedData); mPlaintextView.setText(new String(plaintext, StandardCharsets.UTF_8)); } catch (GeneralSecurityException | IllegalArgumentException e) { mPlaintextView.setError( String.format("%s: %s", getString(R.string.error_cannot_decrypt), e.toString())); mCiphertextView.requestFocus(); } } private static String base64Encode(final byte[] input) { return Base64.encodeToString(input, Base64.DEFAULT); } private static byte[] base64Decode(String input) { return Base64.decode(input, Base64.DEFAULT); } } ================================================ FILE: java_src/examples/android/helloworld/app/src/main/java/com/helloworld/TinkApplication.java ================================================ // Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.helloworld; import android.app.Application; import com.google.crypto.tink.Aead; import com.google.crypto.tink.KeysetHandle; import com.google.crypto.tink.aead.AeadKeyTemplates; import com.google.crypto.tink.config.TinkConfig; import com.google.crypto.tink.integration.android.AndroidKeysetManager; import java.io.IOException; import java.security.GeneralSecurityException; /** A custom application that initializes the Tink runtime at application startup. */ public class TinkApplication extends Application { private static final String TAG = TinkApplication.class.toString(); private static final String PREF_FILE_NAME = "hello_world_pref"; private static final String TINK_KEYSET_NAME = "hello_world_keyset"; private static final String MASTER_KEY_URI = "android-keystore://hello_world_master_key"; public Aead aead; @Override public final void onCreate() { super.onCreate(); try { TinkConfig.register(); aead = getOrGenerateNewKeysetHandle().getPrimitive(Aead.class); } catch (GeneralSecurityException | IOException e) { throw new RuntimeException(e); } } private KeysetHandle getOrGenerateNewKeysetHandle() throws IOException, GeneralSecurityException { return new AndroidKeysetManager.Builder() .withSharedPref(getApplicationContext(), TINK_KEYSET_NAME, PREF_FILE_NAME) .withKeyTemplate(AeadKeyTemplates.AES256_GCM) .withMasterKeyUri(MASTER_KEY_URI) .build() .getKeysetHandle(); } } ================================================ FILE: java_src/examples/android/helloworld/app/src/main/res/layout/activity_main.xml ================================================ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.helloworld.MainActivity"> <ScrollView android:id="@+id/login_form" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:id="@+id/email_login_form" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/hint_plaintext" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="@string/hint_plaintext" /> <EditText android:id="@+id/plaintext" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/prompt_plaintext" android:inputType="textMultiLine" android:lines="3" android:minLines="3" android:maxLines="10" /> </android.support.design.widget.TextInputLayout> <android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/hint_associated_data" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="@string/hint_associated_data" /> <EditText android:id="@+id/associated_data" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/prompt_associated_data" android:inputType="textMultiLine" android:lines="3" android:minLines="3" android:maxLines="10" /> </android.support.design.widget.TextInputLayout> <android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/hint_ciphertext" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="@string/hint_ciphertext" /> <EditText android:id="@+id/ciphertext" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/prompt_ciphertext" android:inputType="textMultiLine" android:lines="3" android:minLines="3" android:maxLines="10" /> </android.support.design.widget.TextInputLayout> <Button android:id="@+id/encrypt_button" style="?android:textAppearanceSmall" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/action_encrypt" android:textStyle="bold" /> <Button android:id="@+id/decrypt_button" style="?android:textAppearanceSmall" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/action_decrypt" android:textStyle="bold" /> </LinearLayout> </ScrollView> </LinearLayout> ================================================ FILE: java_src/examples/android/helloworld/app/src/main/res/values/colors.xml ================================================ <?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#3F51B5</color> <color name="colorPrimaryDark">#303F9F</color> <color name="colorAccent">#FF4081</color> </resources> ================================================ FILE: java_src/examples/android/helloworld/app/src/main/res/values/dimens.xml ================================================ <resources> <!-- Default screen margins, per the Android Design guidelines. --> <dimen name="activity_horizontal_margin">16dp</dimen> <dimen name="activity_vertical_margin">16dp</dimen> </resources> ================================================ FILE: java_src/examples/android/helloworld/app/src/main/res/values/strings.xml ================================================ <resources> <string name="app_name">Tink Hello World</string> <string name="prompt_plaintext">Message</string> <string name="hint_plaintext"> The secrecy and integrity of this message will be guaranteed. </string> <string name="prompt_associated_data">Associated data</string> <string name="hint_associated_data"> Only the integrity of this associated data will be guaranteed. For successful decryption it must be the same as the associated data used during encryption. </string> <string name="prompt_ciphertext">Ciphertext</string> <string name="hint_ciphertext"> The ciphertext is in Base64 encoding. Try to modify it and verify that the decryption will fail. </string> <string name="action_encrypt">Encrypt</string> <string name="action_decrypt">Decrypt</string> <string name="error_cannot_encrypt">Cannot encrypt</string> <string name="error_cannot_decrypt">Cannot decrypt</string> <string name="error_field_required">This field is required</string> </resources> ================================================ FILE: java_src/examples/android/helloworld/app/src/main/res/values/styles.xml ================================================ <resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> </resources> ================================================ FILE: java_src/examples/android/helloworld/build.gradle ================================================ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { google() mavenCentral() } dependencies { // See AGP compatibility with Gradle here: // https://developer.android.com/studio/releases/gradle-plugin#updating-gradle. classpath 'com.android.tools.build:gradle:7.4.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { google() mavenCentral() } } task clean(type: Delete) { delete rootProject.buildDir } ================================================ FILE: java_src/examples/android/helloworld/gradle/wrapper/gradle-wrapper.properties ================================================ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists ================================================ FILE: java_src/examples/android/helloworld/gradle.properties ================================================ # Project-wide Gradle settings. # IDE (e.g. Android Studio) users: # Gradle settings configured through the IDE *will override* # any settings specified in this file. # For more details on how to configure your build environment visit # http://www.gradle.org/docs/current/userguide/build_environment.html # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. org.gradle.jvmargs=-Xmx1536m # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true # Preferred source for Maven packages: # "local": Local Maven repository (i.e. for testing without publishing) # "snapshot": Maven Central snapshot repository (i.e. for testing published # snapshots) mavenLocation=snapshot android.useAndroidX=true ================================================ FILE: java_src/examples/android/helloworld/gradlew ================================================ #!/bin/sh # # Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################## # # Gradle start up script for POSIX generated by Gradle. # # Important for running: # # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is # noncompliant, but you have some other compliant shell such as ksh or # bash, then to run this script, type that shell name before the whole # command line, like: # # ksh Gradle # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: # * functions; # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», # «${var#prefix}», «${var%suffix}», and «$( cmd )»; # * compound commands having a testable exit status, especially «case»; # * various built-in commands including «command», «set», and «ulimit». # # Important for patching: # # (2) This script targets any POSIX shell, so it avoids extensions provided # by Bash, Ksh, etc; in particular arrays are avoided. # # The "traditional" practice of packing multiple parameters into a # space-separated string is a well documented source of bugs and security # problems, so this is (mostly) avoided, by progressively accumulating # options in "$@", and eventually passing that to Java. # # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; # see the in-line comments for details. # # There are tweaks for specific operating systems such as AIX, CygWin, # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. # ############################################################################## # Attempt to set APP_HOME # Resolve links: $0 may be a link app_path=$0 # Need this for daisy-chained symlinks. while APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path [ -h "$app_path" ] do ls=$( ls -ld "$app_path" ) link=${ls#*' -> '} case $link in #( /*) app_path=$link ;; #( *) app_path=$APP_HOME$link ;; esac done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum warn () { echo "$*" } >&2 die () { echo echo "$*" echo exit 1 } >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false case "$( uname )" in #( CYGWIN* ) cygwin=true ;; #( Darwin* ) darwin=true ;; #( MSYS* | MINGW* ) msys=true ;; #( NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD=$JAVA_HOME/jre/sh/java else JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD=java if ! command -v java >/dev/null 2>&1 then die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac fi # Collect all arguments for the java command, stacking in reverse order: # * args from the command line # * the main class name # * -classpath # * -D...appname settings # * --module-path (only if needed) # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) # Now convert the arguments - kludge to limit ourselves to /bin/sh for arg do if case $arg in #( -*) false ;; # don't mess with options #( /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath [ -e "$t" ] ;; #( *) false ;; esac then arg=$( cygpath --path --ignore --mixed "$arg" ) fi # Roll the args list around exactly as many times as the number of # args, so each arg winds up back in the position where it started, but # possibly modified. # # NB: a `for` loop captures its iteration list before it begins, so # changing the positional parameters here affects neither the number of # iterations, nor the values presented in `arg`. shift # remove old arg set -- "$@" "$arg" # push replacement arg done fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ org.gradle.wrapper.GradleWrapperMain \ "$@" # Stop when "xargs" is not available. if ! command -v xargs >/dev/null 2>&1 then die "xargs is not available" fi # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. # # In Bash we could simply go: # # readarray ARGS < <( xargs -n1 <<<"$var" ) && # set -- "${ARGS[@]}" "$@" # # but POSIX shell has neither arrays nor command substitution, so instead we # post-process each arg (as a line of input to sed) to backslash-escape any # character that might be a shell metacharacter, then use eval to reverse # that process (while maintaining the separation between arguments), and wrap # the whole thing up as a single "set" statement. # # This will of course break if any of these variables contains a newline or # an unmatched quote. # eval "set -- $( printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | xargs -n1 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | tr '\n' ' ' )" '"$@"' exec "$JAVACMD" "$@" ================================================ FILE: java_src/examples/android/helloworld/gradlew.bat ================================================ @rem @rem Copyright 2015 the original author or authors. @rem @rem Licensed under the Apache License, Version 2.0 (the "License"); @rem you may not use this file except in compliance with the License. @rem You may obtain a copy of the License at @rem @rem https://www.apache.org/licenses/LICENSE-2.0 @rem @rem Unless required by applicable law or agreed to in writing, software @rem distributed under the License is distributed on an "AS IS" BASIS, @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @rem @rem ########################################################################## @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. @rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Resolve any "." and ".." in APP_HOME to make it shorter. for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! set EXIT_CODE=%ERRORLEVEL% if %EXIT_CODE% equ 0 set EXIT_CODE=1 if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal :omega ================================================ FILE: java_src/examples/android/helloworld/settings.gradle ================================================ include ':app' ================================================ FILE: java_src/examples/cleartextkeyset/BUILD.bazel ================================================ [File too large to display: 1.0 KB] ================================================ FILE: java_src/examples/cleartextkeyset/CleartextKeysetExample.java ================================================ /** * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ // [START cleartext-keyset-example] package cleartextkeyset; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.crypto.tink.Aead; import com.google.crypto.tink.InsecureSecretKeyAccess; import com.google.crypto.tink.KeysetHandle; import com.google.crypto.tink.TinkJsonProtoKeysetFormat; import com.google.crypto.tink.aead.AeadConfig; import com.google.crypto.tink.aead.PredefinedAeadParameters; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; /** * A command-line utility for generating, storing and using AES128_GCM keysets. * * <h1>WARNING: Loading a Keyset from disk is often a security problem -- hence this needs {@code * InsecureSecretKeyAccess.get()}. * * <p>It requires the following arguments: * * <ul> * <li>mode: Can be "generate", "encrypt" or "decrypt". If mode is "generate" it will generate, * encrypt a keyset, store it in key-file. If mode is "encrypt" or "decrypt" it will read and * decrypt an keyset from key-file, and use it to encrypt or decrypt input-file. * <li>key-file: Read the encrypted key material from this file. * <li>input-file: If mode is "encrypt" or "decrypt", read the input from this file. * <li>output-file: If mode is "encrypt" or "decrypt", write the result to this file. */ public final class CleartextKeysetExample { private static final String MODE_ENCRYPT = "encrypt"; private static final String MODE_DECRYPT = "decrypt"; private static final String MODE_GENERATE = "generate"; private static final byte[] EMPTY_ASSOCIATED_DATA = new byte[0]; public static void main(String[] args) throws Exception { if (args.length != 2 && args.length != 4) { System.err.printf("Expected 2 or 4 parameters, got %d\n", args.length); System.err.println( "Usage: java CleartextKeysetExample generate/encrypt/decrypt key-file input-file" + " output-file"); System.exit(1); } String mode = args[0]; if (!MODE_ENCRYPT.equals(mode) && !MODE_DECRYPT.equals(mode) && !MODE_GENERATE.equals(mode)) { System.err.print("The first argument should be either encrypt, decrypt or generate"); System.exit(1); } Path keyFile = Paths.get(args[1]); // Initialise Tink: register all AEAD key types with the Tink runtime AeadConfig.register(); if (MODE_GENERATE.equals(mode)) { // [START generate-a-new-keyset] KeysetHandle handle = KeysetHandle.generateNew(PredefinedAeadParameters.AES128_GCM); // [END generate-a-new-keyset] // [START store-a-cleartext-keyset] String serializedKeyset = TinkJsonProtoKeysetFormat.serializeKeyset(handle, InsecureSecretKeyAccess.get()); Files.write(keyFile, serializedKeyset.getBytes(UTF_8)); // [END store-a-cleartext-keyset] return; } // Use the primitive to encrypt/decrypt files // Read the keyset from disk String serializedKeyset = new String(Files.readAllBytes(keyFile), UTF_8); KeysetHandle handle = TinkJsonProtoKeysetFormat.parseKeyset(serializedKeyset, InsecureSecretKeyAccess.get()); // Get the primitive Aead aead = handle.getPrimitive(Aead.class); byte[] input = Files.readAllBytes(Paths.get(args[2])); Path outputFile = Paths.get(args[3]); if (MODE_ENCRYPT.equals(mode)) { byte[] ciphertext = aead.encrypt(input, EMPTY_ASSOCIATED_DATA); Files.write(outputFile, ciphertext); } else if (MODE_DECRYPT.equals(mode)) { byte[] plaintext = aead.decrypt(input, EMPTY_ASSOCIATED_DATA); Files.write(outputFile, plaintext); } } private CleartextKeysetExample() {} } // [END cleartext-keyset-example] ================================================ FILE: java_src/examples/cleartextkeyset/README.md ================================================ [File too large to display: 985 B] ================================================ FILE: java_src/examples/cleartextkeyset/cleartext_keyset_example_test.sh ================================================ #!/bin/bash # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ################################################################################ set -euo pipefail ############################################################################# ##### Tests for cleartext keyset example. CLI="$1" DATA_FILE="${TEST_TMPDIR}/example_data.txt" KEYSET_FILE="${TEST_TMPDIR}/example_keyset.json" echo "This is some plaintext to be encrypted." > ${DATA_FILE} ############################################################################# # A helper function for getting the return code of a command that may fail # Temporarily disables error safety and stores return value in ${TEST_STATUS} # Usage: # % test_command somecommand some args # % echo ${TEST_STATUS} test_command() { set +e "$@" TEST_STATUS=$? set -e } ############################################################################# #### Test initialization and key generation test_name="generate" echo "+++ Starting test ${test_name}..." ##### Run encryption test_command ${CLI} generate ${KEYSET_FILE} if [[ ${TEST_STATUS} -eq 0 ]]; then echo "+++ Success: key file was generated." else echo "--- Failure: could not generate key file." exit 1 fi ############################################################################# #### Test initialization and encryption test_name="encrypt" echo "+++ Starting test ${test_name}..." ##### Run encryption test_command ${CLI} encrypt ${KEYSET_FILE} ${DATA_FILE} "${DATA_FILE}.encrypted" if [[ ${TEST_STATUS} -eq 0 ]]; then echo "+++ Success: file was encrypted." else echo "--- Failure: could not encrypt file." exit 1 fi ############################################################################# #### Test if decryption succeeds and returns original file test_name="decrypt" echo "+++ Starting test $test_name..." ##### Run decryption test_command ${CLI} decrypt ${KEYSET_FILE} ${DATA_FILE}.encrypted "${DATA_FILE}.decrypted" if [[ ${TEST_STATUS} -eq 0 ]]; then echo "+++ Success: file was successfully decrypted." else echo "--- Failure: could not decrypt file." exit 1 fi if cmp -s ${DATA_FILE} "${DATA_FILE}.decrypted"; then echo "+++ Success: file content is the same after decryption." else echo "--- Failure: file content is not the same after decryption." exit 1 fi ================================================ FILE: java_src/examples/deterministicaead/BUILD.bazel ================================================ [File too large to display: 1.1 KB] ================================================ FILE: java_src/examples/deterministicaead/DeterministicAeadExample.java ================================================ [File too large to display: 3.5 KB] ================================================ FILE: java_src/examples/deterministicaead/README.md ================================================ # Java Deterministic AEAD example This example shows how to encrypt files with Tink using Deterministic Authenticated Encryption with Associated Data (Deterministic AEAD). It demonstrates the basic steps of using Tink, namely loading key material, obtaining a primitive, and using the primitive to do crypto. The key material was generated with Tinkey: ```shell tinkey create-keyset --key-template AES256_SIV --out-format JSON \ --out deterministic_aead_test_keyset.json ``` ## Build and run ### Bazel ```shell git clone https://github.com/google/tink cd tink/examples/java_src bazel build ... ``` Encrypt a file: ```shell echo "some data" > testdata.txt ./bazel-bin/deterministicaead/deterministic_aead_example encrypt \ ./deterministicaead/deterministic_aead_test_keyset.json \ testdata.txt testdata.txt.encrypted ``` Decrypt a file: ```shell ./bazel-bin/deterministicaead/deterministic_aead_example decrypt \ ./deterministicaead/deterministic_aead_test_keyset.json \ testdata.txt.encrypted testdata.txt.decrypted diff testdata.txt testdata.txt.decrypted ``` ================================================ FILE: java_src/examples/deterministicaead/deterministic_aead_test.sh ================================================ [File too large to display: 5.4 KB] ================================================ FILE: java_src/examples/deterministicaead/deterministic_aead_test_keyset.json ================================================ [File too large to display: 302 B] ================================================ FILE: java_src/examples/encryptedkeyset/BUILD.bazel ================================================ [File too large to display: 1.5 KB] ================================================ FILE: java_src/examples/encryptedkeyset/EncryptedKeysetExample.java ================================================ [File too large to display: 4.6 KB] ================================================ FILE: java_src/examples/encryptedkeyset/README.md ================================================ [File too large to display: 1.7 KB] ================================================ FILE: java_src/examples/encryptedkeyset/encrypted_keyset_example_test.sh ================================================ [File too large to display: 2.9 KB] ================================================ FILE: java_src/examples/envelopeaead/BUILD.bazel ================================================ [File too large to display: 1.5 KB] ================================================ FILE: java_src/examples/envelopeaead/EnvelopeAeadExample.java ================================================ [File too large to display: 3.9 KB] ================================================ FILE: java_src/examples/envelopeaead/README.md ================================================ [File too large to display: 2.0 KB] ================================================ FILE: java_src/examples/envelopeaead/envelope_aead_example_test.sh ================================================ [File too large to display: 4.1 KB] ================================================ FILE: java_src/examples/gcs/BUILD.bazel ================================================ [File too large to display: 1.7 KB] ================================================ FILE: java_src/examples/gcs/GcsEnvelopeAeadExample.java ================================================ [File too large to display: 7.2 KB] ================================================ FILE: java_src/examples/gcs/README.md ================================================ [File too large to display: 2.7 KB] ================================================ FILE: java_src/examples/gcs/gcs_envelope_aead_example_test.sh ================================================ [File too large to display: 2.5 KB] ================================================ FILE: java_src/examples/hybrid/BUILD.bazel ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/examples/hybrid/HybridExample.java ================================================ [File too large to display: 3.2 KB] ================================================ FILE: java_src/examples/hybrid/README.md ================================================ [File too large to display: 1.1 KB] ================================================ FILE: java_src/examples/hybrid/hybrid_example_test.sh ================================================ [File too large to display: 4.2 KB] ================================================ FILE: java_src/examples/hybrid/hybrid_test_private_keyset.json ================================================ [File too large to display: 332 B] ================================================ FILE: java_src/examples/hybrid/hybrid_test_public_keyset.json ================================================ [File too large to display: 282 B] ================================================ FILE: java_src/examples/jwt/BUILD.bazel ================================================ [File too large to display: 2.4 KB] ================================================ FILE: java_src/examples/jwt/JwtGeneratePublicJwkSet.java ================================================ [File too large to display: 2.5 KB] ================================================ FILE: java_src/examples/jwt/JwtSign.java ================================================ [File too large to display: 2.8 KB] ================================================ FILE: java_src/examples/jwt/JwtVerify.java ================================================ [File too large to display: 3.1 KB] ================================================ FILE: java_src/examples/jwt/README.md ================================================ [File too large to display: 877 B] ================================================ FILE: java_src/examples/jwt/jwt_signature_example_test.sh ================================================ [File too large to display: 4.6 KB] ================================================ FILE: java_src/examples/jwt/jwt_signature_test_private_keyset.json ================================================ [File too large to display: 459 B] ================================================ FILE: java_src/examples/mac/BUILD.bazel ================================================ [File too large to display: 1000 B] ================================================ FILE: java_src/examples/mac/MacExample.java ================================================ [File too large to display: 2.8 KB] ================================================ FILE: java_src/examples/mac/README.md ================================================ [File too large to display: 781 B] ================================================ FILE: java_src/examples/mac/mac_example_test.sh ================================================ [File too large to display: 3.6 KB] ================================================ FILE: java_src/examples/mac/mac_test_keyset.json ================================================ [File too large to display: 387 B] ================================================ FILE: java_src/examples/signature/BUILD.bazel ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/examples/signature/README.md ================================================ [File too large to display: 1011 B] ================================================ FILE: java_src/examples/signature/SignatureExample.java ================================================ [File too large to display: 3.0 KB] ================================================ FILE: java_src/examples/signature/signature_example_test.sh ================================================ [File too large to display: 3.7 KB] ================================================ FILE: java_src/examples/signature/signature_test_private_keyset.json ================================================ [File too large to display: 429 B] ================================================ FILE: java_src/examples/signature/signature_test_public_keyset.json ================================================ [File too large to display: 384 B] ================================================ FILE: java_src/examples/streamingaead/BUILD.bazel ================================================ [File too large to display: 1.0 KB] ================================================ FILE: java_src/examples/streamingaead/README.md ================================================ [File too large to display: 1.0 KB] ================================================ FILE: java_src/examples/streamingaead/StreamingAeadExample.java ================================================ [File too large to display: 5.3 KB] ================================================ FILE: java_src/examples/streamingaead/streaming_aead_example_test.sh ================================================ [File too large to display: 4.3 KB] ================================================ FILE: java_src/examples/streamingaead/streaming_aead_test_keyset.json ================================================ [File too large to display: 262 B] ================================================ FILE: java_src/examples/testdata/gcp/BUILD.bazel ================================================ [File too large to display: 389 B] ================================================ FILE: java_src/examples/testdata/gcp/README.md ================================================ [File too large to display: 361 B] ================================================ FILE: java_src/examples/testdata/gcp/credential.json ================================================ [File too large to display: 1.5 KB] ================================================ FILE: java_src/examples/testdata/gcp/credential_bad.json ================================================ [File too large to display: 1.5 KB] ================================================ FILE: java_src/examples/testdata/gcp/key_name.txt ================================================ [File too large to display: 110 B] ================================================ FILE: java_src/examples/testdata/gcp/key_name_bad.txt ================================================ [File too large to display: 91 B] ================================================ FILE: java_src/examples/walkthrough/src/main/java/walkthrough/BUILD.bazel ================================================ [File too large to display: 2.1 KB] ================================================ FILE: java_src/examples/walkthrough/src/main/java/walkthrough/CreateKeysetExample.java ================================================ [File too large to display: 1.7 KB] ================================================ FILE: java_src/examples/walkthrough/src/main/java/walkthrough/ObtainAndUseAeadPrimitiveExample.java ================================================ [File too large to display: 1.8 KB] ================================================ FILE: java_src/examples/walkthrough/src/main/java/walkthrough/ReadCleartextKeysetExample.java ================================================ [File too large to display: 1.7 KB] ================================================ FILE: java_src/examples/walkthrough/src/main/java/walkthrough/ReadKeysetExample.java ================================================ [File too large to display: 2.0 KB] ================================================ FILE: java_src/examples/walkthrough/src/main/java/walkthrough/WriteCleartextKeysetExample.java ================================================ [File too large to display: 1.7 KB] ================================================ FILE: java_src/examples/walkthrough/src/main/java/walkthrough/WriteKeysetExample.java ================================================ [File too large to display: 2.0 KB] ================================================ FILE: java_src/examples/walkthrough/src/test/java/walkthrough/BUILD.bazel ================================================ [File too large to display: 4.3 KB] ================================================ FILE: java_src/examples/walkthrough/src/test/java/walkthrough/CreateKesetExampleTest.java ================================================ [File too large to display: 1.4 KB] ================================================ FILE: java_src/examples/walkthrough/src/test/java/walkthrough/ObtainAndUseAeadPrimitiveExampleTest.java ================================================ [File too large to display: 2.2 KB] ================================================ FILE: java_src/examples/walkthrough/src/test/java/walkthrough/ReadCleartextKeysetExampleTest.java ================================================ [File too large to display: 2.1 KB] ================================================ FILE: java_src/examples/walkthrough/src/test/java/walkthrough/ReadKeysetExampleTest.java ================================================ [File too large to display: 3.0 KB] ================================================ FILE: java_src/examples/walkthrough/src/test/java/walkthrough/WriteCleartextKeysetExampleTest.java ================================================ [File too large to display: 2.5 KB] ================================================ FILE: java_src/examples/walkthrough/src/test/java/walkthrough/WriteKeysetExampleTest.java ================================================ [File too large to display: 3.0 KB] ================================================ FILE: java_src/jar_jar_rules.txt ================================================ [File too large to display: 421 B] ================================================ FILE: java_src/proto/BUILD.bazel ================================================ [File too large to display: 11.3 KB] ================================================ FILE: java_src/proto/aes_cmac.proto ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/proto/aes_cmac_prf.proto ================================================ [File too large to display: 1.1 KB] ================================================ FILE: java_src/proto/aes_ctr.proto ================================================ [File too large to display: 1.1 KB] ================================================ FILE: java_src/proto/aes_ctr_hmac_aead.proto ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/proto/aes_ctr_hmac_streaming.proto ================================================ [File too large to display: 1.7 KB] ================================================ FILE: java_src/proto/aes_eax.proto ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/proto/aes_gcm.proto ================================================ [File too large to display: 2.5 KB] ================================================ FILE: java_src/proto/aes_gcm_hkdf_streaming.proto ================================================ [File too large to display: 1.6 KB] ================================================ FILE: java_src/proto/aes_gcm_siv.proto ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/proto/aes_siv.proto ================================================ [File too large to display: 1.5 KB] ================================================ FILE: java_src/proto/chacha20_poly1305.proto ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/proto/common.proto ================================================ [File too large to display: 1.5 KB] ================================================ FILE: java_src/proto/config.proto ================================================ [File too large to display: 1.9 KB] ================================================ FILE: java_src/proto/ecdsa.proto ================================================ [File too large to display: 2.5 KB] ================================================ FILE: java_src/proto/ecies_aead_hkdf.proto ================================================ [File too large to display: 3.6 KB] ================================================ FILE: java_src/proto/ed25519.proto ================================================ [File too large to display: 1.7 KB] ================================================ FILE: java_src/proto/empty.proto ================================================ [File too large to display: 908 B] ================================================ FILE: java_src/proto/hkdf_prf.proto ================================================ [File too large to display: 1.4 KB] ================================================ FILE: java_src/proto/hmac.proto ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/proto/hmac_prf.proto ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/proto/hpke.proto ================================================ [File too large to display: 1.9 KB] ================================================ FILE: java_src/proto/jwt_ecdsa.proto ================================================ [File too large to display: 2.0 KB] ================================================ FILE: java_src/proto/jwt_hmac.proto ================================================ [File too large to display: 1.5 KB] ================================================ FILE: java_src/proto/jwt_rsa_ssa_pkcs1.proto ================================================ [File too large to display: 2.7 KB] ================================================ FILE: java_src/proto/jwt_rsa_ssa_pss.proto ================================================ [File too large to display: 2.7 KB] ================================================ FILE: java_src/proto/kms_aead.proto ================================================ [File too large to display: 1.4 KB] ================================================ FILE: java_src/proto/kms_envelope.proto ================================================ [File too large to display: 1.6 KB] ================================================ FILE: java_src/proto/prf_based_deriver.proto ================================================ [File too large to display: 1.3 KB] ================================================ FILE: java_src/proto/rsa_ssa_pkcs1.proto ================================================ [File too large to display: 2.7 KB] ================================================ FILE: java_src/proto/rsa_ssa_pss.proto ================================================ [File too large to display: 3.0 KB] ================================================ FILE: java_src/proto/test_proto.proto ================================================ [File too large to display: 1.1 KB] ================================================ FILE: java_src/proto/tink.proto ================================================ [File too large to display: 7.1 KB] ================================================ FILE: java_src/proto/xchacha20_poly1305.proto ================================================ [File too large to display: 1.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/AccessesPartialKey.java ================================================ [File too large to display: 3.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/Aead.java ================================================ [File too large to display: 3.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/BUILD.bazel ================================================ [File too large to display: 42.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/BinaryKeysetReader.java ================================================ [File too large to display: 3.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/BinaryKeysetWriter.java ================================================ [File too large to display: 2.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/Catalogue.java ================================================ [File too large to display: 1.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/CleartextKeysetHandle.java ================================================ [File too large to display: 4.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/Config.java ================================================ [File too large to display: 5.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/Configuration.java ================================================ [File too large to display: 972 B] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/ConfigurationFips140v2.java ================================================ [File too large to display: 6.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/ConfigurationV0.java ================================================ [File too large to display: 14.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/CryptoFormat.java ================================================ [File too large to display: 2.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/DeterministicAead.java ================================================ [File too large to display: 3.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/HybridDecrypt.java ================================================ [File too large to display: 3.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/HybridEncrypt.java ================================================ [File too large to display: 3.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/InsecureSecretKeyAccess.java ================================================ [File too large to display: 1.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/JsonKeysetReader.java ================================================ [File too large to display: 12.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/JsonKeysetWriter.java ================================================ [File too large to display: 6.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/Key.java ================================================ [File too large to display: 3.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/KeyManager.java ================================================ [File too large to display: 5.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/KeyStatus.java ================================================ [File too large to display: 1.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/KeyTemplate.java ================================================ [File too large to display: 6.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/KeyTemplates.java ================================================ [File too large to display: 1.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/KeyWrap.java ================================================ [File too large to display: 2.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/KeysetHandle.java ================================================ [File too large to display: 46.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/KeysetManager.java ================================================ [File too large to display: 11.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/KeysetReader.java ================================================ [File too large to display: 1.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/KeysetWriter.java ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/KmsClient.java ================================================ [File too large to display: 1.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/KmsClients.java ================================================ [File too large to display: 4.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/KmsClientsTestUtil.java ================================================ [File too large to display: 1.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/LegacyKeysetSerialization.java ================================================ [File too large to display: 3.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/Mac.java ================================================ [File too large to display: 1.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/NoSecretKeysetHandle.java ================================================ [File too large to display: 2.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/Parameters.java ================================================ [File too large to display: 1.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/PemKeyType.java ================================================ [File too large to display: 6.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/PrimitiveWrapper.java ================================================ [File too large to display: 2.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/PrivateKey.java ================================================ [File too large to display: 939 B] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/PrivateKeyManager.java ================================================ [File too large to display: 1.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/PublicKeySign.java ================================================ [File too large to display: 1.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/PublicKeyVerify.java ================================================ [File too large to display: 1.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/Registry.java ================================================ [File too large to display: 21.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/RegistryConfiguration.java ================================================ [File too large to display: 1.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/SecretKeyAccess.java ================================================ [File too large to display: 2.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/StreamingAead.java ================================================ [File too large to display: 9.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/TinkJsonProtoKeysetFormat.java ================================================ [File too large to display: 4.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/TinkProtoKeysetFormat.java ================================================ [File too large to display: 3.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/TinkProtoParametersFormat.java ================================================ [File too large to display: 2.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/Util.java ================================================ [File too large to display: 4.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/Version.java.templ ================================================ [File too large to display: 917 B] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/AeadConfig.java ================================================ [File too large to display: 6.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/AeadFactory.java ================================================ [File too large to display: 1.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/AeadKey.java ================================================ [File too large to display: 1.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/AeadKeyTemplates.java ================================================ [File too large to display: 9.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/AeadParameters.java ================================================ [File too large to display: 929 B] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/AeadWrapper.java ================================================ [File too large to display: 5.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/AesCtrHmacAeadKey.java ================================================ [File too large to display: 6.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/AesCtrHmacAeadKeyManager.java ================================================ [File too large to display: 9.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/AesCtrHmacAeadParameters.java ================================================ [File too large to display: 10.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/AesEaxKey.java ================================================ [File too large to display: 5.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/AesEaxKeyManager.java ================================================ [File too large to display: 7.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/AesEaxParameters.java ================================================ [File too large to display: 6.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/AesGcmKey.java ================================================ [File too large to display: 5.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/AesGcmKeyManager.java ================================================ [File too large to display: 9.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/AesGcmParameters.java ================================================ [File too large to display: 6.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/AesGcmSivKey.java ================================================ [File too large to display: 5.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/AesGcmSivKeyManager.java ================================================ [File too large to display: 9.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/AesGcmSivParameters.java ================================================ [File too large to display: 4.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/BUILD.bazel ================================================ [File too large to display: 56.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/ChaCha20Poly1305Key.java ================================================ [File too large to display: 5.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/ChaCha20Poly1305KeyManager.java ================================================ [File too large to display: 5.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/ChaCha20Poly1305Parameters.java ================================================ [File too large to display: 2.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/KmsAeadKeyManager.java ================================================ [File too large to display: 5.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/KmsEnvelopeAead.java ================================================ [File too large to display: 8.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/KmsEnvelopeAeadKeyManager.java ================================================ [File too large to display: 10.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/LegacyKmsAeadKey.java ================================================ [File too large to display: 3.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/LegacyKmsAeadParameters.java ================================================ [File too large to display: 2.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/LegacyKmsAeadProtoSerialization.java ================================================ [File too large to display: 7.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/LegacyKmsEnvelopeAeadKey.java ================================================ [File too large to display: 3.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/LegacyKmsEnvelopeAeadParameters.java ================================================ [File too large to display: 11.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/LegacyKmsEnvelopeAeadProtoSerialization.java ================================================ [File too large to display: 10.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/PredefinedAeadParameters.java ================================================ [File too large to display: 5.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/XChaCha20Poly1305Key.java ================================================ [File too large to display: 5.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/XChaCha20Poly1305KeyManager.java ================================================ [File too large to display: 6.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/XChaCha20Poly1305Parameters.java ================================================ [File too large to display: 2.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/internal/AesCtrHmacAeadProtoSerialization.java ================================================ [File too large to display: 13.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/internal/AesEaxProtoSerialization.java ================================================ [File too large to display: 9.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/internal/AesGcmProtoSerialization.java ================================================ [File too large to display: 10.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/internal/AesGcmSivProtoSerialization.java ================================================ [File too large to display: 8.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/internal/BUILD.bazel ================================================ [File too large to display: 30.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/internal/ChaCha20Poly1305Jce.java ================================================ [File too large to display: 7.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/internal/ChaCha20Poly1305ProtoSerialization.java ================================================ [File too large to display: 8.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/internal/ChaCha20Util.java ================================================ [File too large to display: 4.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/internal/InsecureNonceAesGcmJce.java ================================================ [File too large to display: 5.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/internal/InsecureNonceChaCha20.java ================================================ [File too large to display: 2.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/internal/InsecureNonceChaCha20Base.java ================================================ [File too large to display: 4.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/internal/InsecureNonceChaCha20Poly1305.java ================================================ [File too large to display: 1.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/internal/InsecureNonceChaCha20Poly1305Base.java ================================================ [File too large to display: 7.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/internal/InsecureNonceChaCha20Poly1305Jce.java ================================================ [File too large to display: 4.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/internal/InsecureNonceXChaCha20.java ================================================ [File too large to display: 2.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/internal/InsecureNonceXChaCha20Poly1305.java ================================================ [File too large to display: 1.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/internal/LegacyAesCtrHmacTestKeyManager.java ================================================ [File too large to display: 8.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/internal/LegacyFullAead.java ================================================ [File too large to display: 4.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/internal/Poly1305.java ================================================ [File too large to display: 5.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/internal/XChaCha20Poly1305Jce.java ================================================ [File too large to display: 6.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/internal/XChaCha20Poly1305ProtoSerialization.java ================================================ [File too large to display: 8.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/subtle/AeadFactory.java ================================================ [File too large to display: 1.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/subtle/AesGcmFactory.java ================================================ [File too large to display: 2.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/subtle/AesGcmSiv.java ================================================ [File too large to display: 8.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/aead/subtle/BUILD.bazel ================================================ [File too large to display: 2.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/annotations/Alpha.java ================================================ [File too large to display: 1.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/annotations/BUILD.bazel ================================================ [File too large to display: 215 B] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/config/BUILD.bazel ================================================ [File too large to display: 2.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/config/TinkConfig.java ================================================ [File too large to display: 3.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/config/TinkFips.java ================================================ [File too large to display: 1.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/config/internal/BUILD.bazel ================================================ [File too large to display: 1.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/config/internal/TinkFipsDisabled.java ================================================ [File too large to display: 1.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/config/internal/TinkFipsEnabled.java ================================================ [File too large to display: 1.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/config/internal/TinkFipsUtil.java ================================================ [File too large to display: 3.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/daead/AesSivKey.java ================================================ [File too large to display: 5.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/daead/AesSivKeyManager.java ================================================ [File too large to display: 7.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/daead/AesSivParameters.java ================================================ [File too large to display: 3.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/daead/BUILD.bazel ================================================ [File too large to display: 11.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/daead/DeterministicAeadConfig.java ================================================ [File too large to display: 4.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/daead/DeterministicAeadFactory.java ================================================ [File too large to display: 2.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/daead/DeterministicAeadKey.java ================================================ [File too large to display: 1.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/daead/DeterministicAeadKeyTemplates.java ================================================ [File too large to display: 2.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/daead/DeterministicAeadParameters.java ================================================ [File too large to display: 956 B] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/daead/DeterministicAeadWrapper.java ================================================ [File too large to display: 6.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/daead/PredefinedDeterministicAeadParameters.java ================================================ [File too large to display: 1.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/daead/internal/AesSivProtoSerialization.java ================================================ [File too large to display: 9.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/daead/internal/BUILD.bazel ================================================ [File too large to display: 4.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/daead/internal/LegacyFullDeterministicAead.java ================================================ [File too large to display: 4.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/daead/internal/testing/BUILD.bazel ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/daead/internal/testing/LegacyAesSivTestKeyManager.java ================================================ [File too large to display: 3.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/BUILD.bazel ================================================ [File too large to display: 28.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/EciesAeadHkdfPrivateKeyManager.java ================================================ [File too large to display: 20.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/EciesAeadHkdfPublicKeyManager.java ================================================ [File too large to display: 983 B] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/EciesParameters.java ================================================ [File too large to display: 12.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/EciesPrivateKey.java ================================================ [File too large to display: 8.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/EciesPublicKey.java ================================================ [File too large to display: 8.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/HpkeParameters.java ================================================ [File too large to display: 6.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/HpkePrivateKey.java ================================================ [File too large to display: 7.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/HpkeProtoSerialization.java ================================================ [File too large to display: 15.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/HpkePublicKey.java ================================================ [File too large to display: 8.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/HybridConfig.java ================================================ [File too large to display: 5.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/HybridDecryptConfig.java ================================================ [File too large to display: 1.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/HybridDecryptFactory.java ================================================ [File too large to display: 2.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/HybridDecryptWrapper.java ================================================ [File too large to display: 5.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/HybridEncryptConfig.java ================================================ [File too large to display: 1.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/HybridEncryptFactory.java ================================================ [File too large to display: 2.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/HybridEncryptWrapper.java ================================================ [File too large to display: 4.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/HybridKeyTemplates.java ================================================ [File too large to display: 7.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/HybridParameters.java ================================================ [File too large to display: 1.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/HybridPrivateKey.java ================================================ [File too large to display: 1.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/HybridPublicKey.java ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/HybridUtil.java ================================================ [File too large to display: 1.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/PredefinedHybridParameters.java ================================================ [File too large to display: 5.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/AesGcmHpkeAead.java ================================================ [File too large to display: 2.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/BUILD.bazel ================================================ [File too large to display: 26.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/ChaCha20Poly1305HpkeAead.java ================================================ [File too large to display: 2.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/EciesProtoSerialization.java ================================================ [File too large to display: 21.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/HkdfHpkeKdf.java ================================================ [File too large to display: 4.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/HpkeAead.java ================================================ [File too large to display: 2.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/HpkeContext.java ================================================ [File too large to display: 9.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/HpkeDecrypt.java ================================================ [File too large to display: 6.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/HpkeEncrypt.java ================================================ [File too large to display: 4.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/HpkeKdf.java ================================================ [File too large to display: 3.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/HpkeKem.java ================================================ [File too large to display: 3.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/HpkeKemEncapOutput.java ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/HpkeKemKeyFactory.java ================================================ [File too large to display: 2.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/HpkeKemPrivateKey.java ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/HpkePrimitiveFactory.java ================================================ [File too large to display: 4.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/HpkePrivateKeyManager.java ================================================ [File too large to display: 13.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/HpkePublicKeyManager.java ================================================ [File too large to display: 976 B] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/HpkeUtil.java ================================================ [File too large to display: 7.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/LegacyFullHybridDecrypt.java ================================================ [File too large to display: 4.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/LegacyFullHybridEncrypt.java ================================================ [File too large to display: 4.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/NistCurvesHpkeKem.java ================================================ [File too large to display: 7.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/NistCurvesHpkeKemPrivateKey.java ================================================ [File too large to display: 1.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/X25519HpkeKem.java ================================================ [File too large to display: 5.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/X25519HpkeKemPrivateKey.java ================================================ [File too large to display: 1.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/testing/BUILD.bazel ================================================ [File too large to display: 8.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/testing/EciesAeadHkdfTestUtil.java ================================================ [File too large to display: 23.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/testing/HpkeTestUtil.java ================================================ [File too large to display: 15.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/testing/HybridTestVector.java ================================================ [File too large to display: 1.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/testing/LegacyHybridDecryptKeyManager.java ================================================ [File too large to display: 3.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/internal/testing/LegacyHybridEncryptKeyManager.java ================================================ [File too large to display: 4.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/subtle/AeadOrDaead.java ================================================ [File too large to display: 3.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/subtle/BUILD.bazel ================================================ [File too large to display: 2.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/subtle/RsaKem.java ================================================ [File too large to display: 3.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/subtle/RsaKemHybridDecrypt.java ================================================ [File too large to display: 3.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/hybrid/subtle/RsaKemHybridEncrypt.java ================================================ [File too large to display: 2.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/integration/android/AndroidKeysetManager.java ================================================ [File too large to display: 22.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/integration/android/AndroidKeystoreAesGcm.java ================================================ [File too large to display: 4.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/integration/android/AndroidKeystoreKmsClient.java ================================================ [File too large to display: 10.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/integration/android/BUILD.bazel ================================================ [File too large to display: 2.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/integration/android/SharedPrefKeysetReader.java ================================================ [File too large to display: 3.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/integration/android/SharedPrefKeysetWriter.java ================================================ [File too large to display: 4.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/integration/android/internal/FakeAndroidKeystoreProvider.java ================================================ [File too large to display: 15.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/integration/awskms/AwsKmsAead.java ================================================ [File too large to display: 3.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/integration/awskms/AwsKmsClient.java ================================================ [File too large to display: 7.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/integration/awskms/BUILD.bazel ================================================ [File too large to display: 1.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/integration/awskms/FakeAwsKms.java ================================================ [File too large to display: 3.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/integration/gcpkms/BUILD.bazel ================================================ [File too large to display: 2.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/integration/gcpkms/FakeCloudKms.java ================================================ [File too large to display: 5.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/integration/gcpkms/FakeKeyManagementServiceClient.java ================================================ [File too large to display: 1.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/integration/gcpkms/GcpKmsAead.java ================================================ [File too large to display: 8.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/integration/gcpkms/GcpKmsClient.java ================================================ [File too large to display: 7.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/integration/hcvault/BUILD.bazel ================================================ [File too large to display: 752 B] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/integration/hcvault/FakeHcVault.java ================================================ [File too large to display: 4.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/integration/hcvault/HcVaultAead.java ================================================ [File too large to display: 3.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/BUILD.bazel ================================================ [File too large to display: 27.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/BigIntegerEncoding.java ================================================ [File too large to display: 3.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/BuildDispatchedCode.java ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/Curve25519.java ================================================ [File too large to display: 17.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/Ed25519.java ================================================ [File too large to display: 53.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/Ed25519Constants.java ================================================ [File too large to display: 4.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/EllipticCurvesUtil.java ================================================ [File too large to display: 13.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/EnumTypeProtoConverter.java ================================================ [File too large to display: 3.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/Field25519.java ================================================ [File too large to display: 20.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/InternalConfiguration.java ================================================ [File too large to display: 3.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/JsonParser.java ================================================ [File too large to display: 8.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/KeyManagerRegistry.java ================================================ [File too large to display: 6.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/KeyParser.java ================================================ [File too large to display: 4.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/KeySerializer.java ================================================ [File too large to display: 3.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/KeyStatusTypeProtoConverter.java ================================================ [File too large to display: 2.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/KeyTemplateProtoConverter.java ================================================ [File too large to display: 2.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/KeyTester.java ================================================ [File too large to display: 5.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/LegacyKeyManagerImpl.java ================================================ [File too large to display: 7.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/LegacyProtoKey.java ================================================ [File too large to display: 5.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/LegacyProtoParameters.java ================================================ [File too large to display: 2.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/MonitoringUtil.java ================================================ [File too large to display: 3.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/MutableKeyCreationRegistry.java ================================================ [File too large to display: 5.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/MutableKeyDerivationRegistry.java ================================================ [File too large to display: 4.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/MutableMonitoringRegistry.java ================================================ [File too large to display: 2.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/MutableParametersRegistry.java ================================================ [File too large to display: 2.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/MutablePrimitiveRegistry.java ================================================ [File too large to display: 3.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/MutableSerializationRegistry.java ================================================ [File too large to display: 10.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/OutputPrefixUtil.java ================================================ [File too large to display: 1.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/ParametersParser.java ================================================ [File too large to display: 4.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/ParametersSerializer.java ================================================ [File too large to display: 3.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/PrimitiveConstructor.java ================================================ [File too large to display: 3.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/PrimitiveFactory.java ================================================ [File too large to display: 1.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/PrimitiveRegistry.java ================================================ [File too large to display: 8.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/PrimitiveSet.java ================================================ [File too large to display: 10.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/ProtoKeySerialization.java ================================================ [File too large to display: 4.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/ProtoParametersSerialization.java ================================================ [File too large to display: 3.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/Random.java ================================================ [File too large to display: 4.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/RegistryConfiguration.java ================================================ [File too large to display: 3.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/Serialization.java ================================================ [File too large to display: 1.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/SerializationRegistry.java ================================================ [File too large to display: 15.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/SlowInputStream.java ================================================ [File too large to display: 1.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/TinkBugException.java ================================================ [File too large to display: 2.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/Util.java ================================================ [File too large to display: 5.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/testing/Asserts.java ================================================ [File too large to display: 3.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/testing/BUILD.bazel ================================================ [File too large to display: 2.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/testing/BigIntegerTestUtil.java ================================================ [File too large to display: 1.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/testing/FakeMonitoringClient.java ================================================ [File too large to display: 4.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/testing/KeyWithSerialization.java ================================================ [File too large to display: 1.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/internal/testing/ParametersWithSerialization.java ================================================ [File too large to display: 1.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/BUILD.bazel ================================================ [File too large to display: 57.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JsonUtil.java ================================================ [File too large to display: 1.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwkSetConverter.java ================================================ [File too large to display: 17.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtEcdsaParameters.java ================================================ [File too large to display: 6.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtEcdsaPrivateKey.java ================================================ [File too large to display: 3.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtEcdsaProtoSerialization.java ================================================ [File too large to display: 16.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtEcdsaPublicKey.java ================================================ [File too large to display: 6.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtEcdsaSignKeyManager.java ================================================ [File too large to display: 8.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtEcdsaVerifyKeyManager.java ================================================ [File too large to display: 6.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtFormat.java ================================================ [File too large to display: 10.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtHmacKey.java ================================================ [File too large to display: 6.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtHmacKeyManager.java ================================================ [File too large to display: 11.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtHmacParameters.java ================================================ [File too large to display: 6.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtHmacProtoSerialization.java ================================================ [File too large to display: 11.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtInvalidException.java ================================================ [File too large to display: 991 B] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtMac.java ================================================ [File too large to display: 2.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtMacConfig.java ================================================ [File too large to display: 1.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtMacKey.java ================================================ [File too large to display: 1.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtMacParameters.java ================================================ [File too large to display: 1.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtMacWrapper.java ================================================ [File too large to display: 3.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtNames.java ================================================ [File too large to display: 2.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtPublicKeySign.java ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtPublicKeySignInternal.java ================================================ [File too large to display: 1.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtPublicKeySignWrapper.java ================================================ [File too large to display: 2.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtPublicKeyVerify.java ================================================ [File too large to display: 2.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtPublicKeyVerifyInternal.java ================================================ [File too large to display: 2.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtPublicKeyVerifyWrapper.java ================================================ [File too large to display: 3.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtRsaSsaPkcs1Parameters.java ================================================ [File too large to display: 8.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtRsaSsaPkcs1PrivateKey.java ================================================ [File too large to display: 9.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtRsaSsaPkcs1ProtoSerialization.java ================================================ [File too large to display: 16.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtRsaSsaPkcs1PublicKey.java ================================================ [File too large to display: 7.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtRsaSsaPkcs1SignKeyManager.java ================================================ [File too large to display: 11.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtRsaSsaPkcs1VerifyKeyManager.java ================================================ [File too large to display: 4.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtRsaSsaPssParameters.java ================================================ [File too large to display: 8.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtRsaSsaPssPrivateKey.java ================================================ [File too large to display: 9.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtRsaSsaPssProtoSerialization.java ================================================ [File too large to display: 16.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtRsaSsaPssPublicKey.java ================================================ [File too large to display: 7.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtRsaSsaPssSignKeyManager.java ================================================ [File too large to display: 11.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtRsaSsaPssVerifyKeyManager.java ================================================ [File too large to display: 4.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtSignatureConfig.java ================================================ [File too large to display: 2.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtSignatureParameters.java ================================================ [File too large to display: 1.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtSignaturePrivateKey.java ================================================ [File too large to display: 2.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtSignaturePublicKey.java ================================================ [File too large to display: 1.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/JwtValidator.java ================================================ [File too large to display: 13.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/RawJwt.java ================================================ [File too large to display: 21.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/jwt/VerifiedJwt.java ================================================ [File too large to display: 8.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/keyderivation/BUILD.bazel ================================================ [File too large to display: 4.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/keyderivation/KeyDerivationConfig.java ================================================ [File too large to display: 2.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/keyderivation/KeyDerivationKey.java ================================================ [File too large to display: 1.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/keyderivation/KeyDerivationParameters.java ================================================ [File too large to display: 1.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/keyderivation/KeysetDeriver.java ================================================ [File too large to display: 1.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/keyderivation/KeysetDeriverWrapper.java ================================================ [File too large to display: 1.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/keyderivation/PrfBasedKeyDerivationKey.java ================================================ [File too large to display: 4.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/keyderivation/PrfBasedKeyDerivationParameters.java ================================================ [File too large to display: 3.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/keyderivation/internal/BUILD.bazel ================================================ [File too large to display: 10.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/keyderivation/internal/KeyDeriver.java ================================================ [File too large to display: 1.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/keyderivation/internal/KeysetDeriverWrapper.java ================================================ [File too large to display: 3.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/keyderivation/internal/PrfBasedDeriverKeyManager.java ================================================ [File too large to display: 9.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/keyderivation/internal/PrfBasedKeyDerivationKeyProtoSerialization.java ================================================ [File too large to display: 11.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/keyderivation/internal/PrfBasedKeyDeriver.java ================================================ [File too large to display: 2.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/AesCmacKey.java ================================================ [File too large to display: 5.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/AesCmacKeyManager.java ================================================ [File too large to display: 6.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/AesCmacParameters.java ================================================ [File too large to display: 5.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/BUILD.bazel ================================================ [File too large to display: 18.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/ChunkedMac.java ================================================ [File too large to display: 1.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/ChunkedMacComputation.java ================================================ [File too large to display: 2.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/ChunkedMacVerification.java ================================================ [File too large to display: 2.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/ChunkedMacWrapper.java ================================================ [File too large to display: 6.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/HmacKey.java ================================================ [File too large to display: 5.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/HmacKeyManager.java ================================================ [File too large to display: 11.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/HmacParameters.java ================================================ [File too large to display: 8.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/MacConfig.java ================================================ [File too large to display: 4.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/MacFactory.java ================================================ [File too large to display: 1.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/MacKey.java ================================================ [File too large to display: 1.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/MacKeyTemplates.java ================================================ [File too large to display: 5.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/MacParameters.java ================================================ [File too large to display: 970 B] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/MacWrapper.java ================================================ [File too large to display: 6.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/PredefinedMacParameters.java ================================================ [File too large to display: 4.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/internal/AesCmacProtoSerialization.java ================================================ [File too large to display: 8.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/internal/AesCmacTestUtil.java ================================================ [File too large to display: 9.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/internal/AesUtil.java ================================================ [File too large to display: 2.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/internal/BUILD.bazel ================================================ [File too large to display: 18.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/internal/ChunkedAesCmacComputation.java ================================================ [File too large to display: 5.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/internal/ChunkedAesCmacImpl.java ================================================ [File too large to display: 2.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/internal/ChunkedAesCmacVerification.java ================================================ [File too large to display: 2.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/internal/ChunkedHmacComputation.java ================================================ [File too large to display: 2.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/internal/ChunkedHmacImpl.java ================================================ [File too large to display: 2.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/internal/ChunkedHmacVerification.java ================================================ [File too large to display: 1.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/internal/HmacProtoSerialization.java ================================================ [File too large to display: 9.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/internal/HmacTestUtil.java ================================================ [File too large to display: 9.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/internal/LegacyFullMac.java ================================================ [File too large to display: 4.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/mac/internal/LegacyHmacTestKeyManager.java ================================================ [File too large to display: 8.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/monitoring/BUILD.bazel ================================================ [File too large to display: 1.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/monitoring/MonitoringAnnotations.java ================================================ [File too large to display: 3.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/monitoring/MonitoringClient.java ================================================ [File too large to display: 1.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/monitoring/MonitoringKeysetInfo.java ================================================ [File too large to display: 6.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/AesCmacPrfKey.java ================================================ [File too large to display: 2.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/AesCmacPrfKeyManager.java ================================================ [File too large to display: 5.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/AesCmacPrfParameters.java ================================================ [File too large to display: 2.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/BUILD.bazel ================================================ [File too large to display: 20.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/HkdfPrfKey.java ================================================ [File too large to display: 3.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/HkdfPrfKeyManager.java ================================================ [File too large to display: 6.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/HkdfPrfParameters.java ================================================ [File too large to display: 4.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/HmacPrfKey.java ================================================ [File too large to display: 3.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/HmacPrfKeyManager.java ================================================ [File too large to display: 6.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/HmacPrfParameters.java ================================================ [File too large to display: 3.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/PredefinedPrfParameters.java ================================================ [File too large to display: 2.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/Prf.java ================================================ [File too large to display: 2.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/PrfConfig.java ================================================ [File too large to display: 1.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/PrfKey.java ================================================ [File too large to display: 943 B] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/PrfKeyTemplates.java ================================================ [File too large to display: 3.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/PrfParameters.java ================================================ [File too large to display: 970 B] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/PrfSet.java ================================================ [File too large to display: 1.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/PrfSetWrapper.java ================================================ [File too large to display: 5.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/internal/AesCmacPrfProtoSerialization.java ================================================ [File too large to display: 7.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/internal/BUILD.bazel ================================================ [File too large to display: 12.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/internal/HkdfPrfProtoSerialization.java ================================================ [File too large to display: 9.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/internal/HmacPrfProtoSerialization.java ================================================ [File too large to display: 9.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/internal/LegacyFullPrf.java ================================================ [File too large to display: 2.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/internal/LegacyHmacPrfTestKeyManager.java ================================================ [File too large to display: 3.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/prf/internal/LegacyHmacPrfTestUtil.java ================================================ [File too large to display: 4.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/BUILD.bazel ================================================ [File too large to display: 43.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/EcdsaParameters.java ================================================ [File too large to display: 7.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/EcdsaPrivateKey.java ================================================ [File too large to display: 4.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/EcdsaPublicKey.java ================================================ [File too large to display: 5.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/EcdsaSignKeyManager.java ================================================ [File too large to display: 9.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/EcdsaVerifyKeyManager.java ================================================ [File too large to display: 1006 B] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/Ed25519Parameters.java ================================================ [File too large to display: 2.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/Ed25519PrivateKey.java ================================================ [File too large to display: 3.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/Ed25519PrivateKeyManager.java ================================================ [File too large to display: 8.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/Ed25519PublicKey.java ================================================ [File too large to display: 5.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/Ed25519PublicKeyManager.java ================================================ [File too large to display: 1011 B] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/PredefinedSignatureParameters.java ================================================ [File too large to display: 11.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/PublicKeySignConfig.java ================================================ [File too large to display: 1.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/PublicKeySignFactory.java ================================================ [File too large to display: 2.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/PublicKeySignWrapper.java ================================================ [File too large to display: 4.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/PublicKeyVerifyConfig.java ================================================ [File too large to display: 1.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/PublicKeyVerifyFactory.java ================================================ [File too large to display: 2.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/PublicKeyVerifyWrapper.java ================================================ [File too large to display: 6.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/RsaSsaPkcs1Parameters.java ================================================ [File too large to display: 7.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/RsaSsaPkcs1PrivateKey.java ================================================ [File too large to display: 8.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/RsaSsaPkcs1PublicKey.java ================================================ [File too large to display: 6.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/RsaSsaPkcs1SignKeyManager.java ================================================ [File too large to display: 11.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/RsaSsaPkcs1VerifyKeyManager.java ================================================ [File too large to display: 1.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/RsaSsaPssParameters.java ================================================ [File too large to display: 8.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/RsaSsaPssPrivateKey.java ================================================ [File too large to display: 8.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/RsaSsaPssPublicKey.java ================================================ [File too large to display: 6.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/RsaSsaPssSignKeyManager.java ================================================ [File too large to display: 14.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/RsaSsaPssVerifyKeyManager.java ================================================ [File too large to display: 1009 B] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/SignatureConfig.java ================================================ [File too large to display: 5.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/SignatureKeyTemplates.java ================================================ [File too large to display: 13.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/SignatureParameters.java ================================================ [File too large to display: 1.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/SignaturePemKeysetReader.java ================================================ [File too large to display: 9.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/SignaturePrivateKey.java ================================================ [File too large to display: 2.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/SignaturePublicKey.java ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/internal/BUILD.bazel ================================================ [File too large to display: 17.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/internal/EcdsaProtoSerialization.java ================================================ [File too large to display: 18.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/internal/Ed25519ProtoSerialization.java ================================================ [File too large to display: 11.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/internal/LegacyFullSign.java ================================================ [File too large to display: 2.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/internal/LegacyFullVerify.java ================================================ [File too large to display: 4.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/internal/RsaSsaPkcs1ProtoSerialization.java ================================================ [File too large to display: 15.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/internal/RsaSsaPssProtoSerialization.java ================================================ [File too large to display: 16.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/internal/SigUtil.java ================================================ [File too large to display: 3.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/internal/testing/BUILD.bazel ================================================ [File too large to display: 10.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/internal/testing/EcdsaTestUtil.java ================================================ [File too large to display: 13.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/internal/testing/Ed25519TestUtil.java ================================================ [File too large to display: 4.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/internal/testing/LegacyPublicKeySignKeyManager.java ================================================ [File too large to display: 4.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/internal/testing/LegacyPublicKeyVerifyKeyManager.java ================================================ [File too large to display: 2.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/internal/testing/RsaSsaPkcs1TestUtil.java ================================================ [File too large to display: 19.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/internal/testing/RsaSsaPssTestUtil.java ================================================ [File too large to display: 21.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/signature/internal/testing/SignatureTestVector.java ================================================ [File too large to display: 1.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/AesCtrHmacStreamingKey.java ================================================ [File too large to display: 3.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/AesCtrHmacStreamingKeyManager.java ================================================ [File too large to display: 9.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/AesCtrHmacStreamingParameters.java ================================================ [File too large to display: 9.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/AesGcmHkdfStreamingKey.java ================================================ [File too large to display: 3.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/AesGcmHkdfStreamingKeyManager.java ================================================ [File too large to display: 9.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/AesGcmHkdfStreamingParameters.java ================================================ [File too large to display: 6.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/BUILD.bazel ================================================ [File too large to display: 18.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/InputStreamDecrypter.java ================================================ [File too large to display: 6.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/PredefinedStreamingAeadParameters.java ================================================ [File too large to display: 7.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/ReadableByteChannelDecrypter.java ================================================ [File too large to display: 5.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/SeekableByteChannelDecrypter.java ================================================ [File too large to display: 6.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/StreamingAeadConfig.java ================================================ [File too large to display: 4.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/StreamingAeadFactory.java ================================================ [File too large to display: 1.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/StreamingAeadHelper.java ================================================ [File too large to display: 3.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/StreamingAeadKey.java ================================================ [File too large to display: 1.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/StreamingAeadKeyTemplates.java ================================================ [File too large to display: 9.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/StreamingAeadParameters.java ================================================ [File too large to display: 977 B] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/StreamingAeadUtil.java ================================================ [File too large to display: 1.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/StreamingAeadWrapper.java ================================================ [File too large to display: 4.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/internal/AesCtrHmacStreamingProtoSerialization.java ================================================ [File too large to display: 9.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/internal/AesGcmHkdfStreamingProtoSerialization.java ================================================ [File too large to display: 9.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/internal/BUILD.bazel ================================================ [File too large to display: 8.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/internal/LegacyAesGcmHkdfStreamingTestKeyManager.java ================================================ [File too large to display: 4.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/streamingaead/internal/LegacyFullStreamingAead.java ================================================ [File too large to display: 4.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/AesCtrHmacStreaming.java ================================================ [File too large to display: 17.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/AesCtrJceCipher.java ================================================ [File too large to display: 5.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/AesEaxJce.java ================================================ [File too large to display: 11.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/AesGcmHkdfStreaming.java ================================================ [File too large to display: 13.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/AesGcmJce.java ================================================ [File too large to display: 5.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/AesSiv.java ================================================ [File too large to display: 7.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/BUILD.bazel ================================================ [File too large to display: 44.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/Base64.java ================================================ [File too large to display: 24.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/Bytes.java ================================================ [File too large to display: 6.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/ChaCha20.java ================================================ [File too large to display: 2.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/ChaCha20Poly1305.java ================================================ [File too large to display: 4.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/EcdsaSignJce.java ================================================ [File too large to display: 5.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/EcdsaVerifyJce.java ================================================ [File too large to display: 6.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/EciesAeadHkdfDemHelper.java ================================================ [File too large to display: 1.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/EciesAeadHkdfHybridDecrypt.java ================================================ [File too large to display: 4.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/EciesAeadHkdfHybridEncrypt.java ================================================ [File too large to display: 9.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/EciesHkdfRecipientKem.java ================================================ [File too large to display: 1.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/EciesHkdfSenderKem.java ================================================ [File too large to display: 2.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/Ed25519Sign.java ================================================ [File too large to display: 5.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/Ed25519Verify.java ================================================ [File too large to display: 4.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/EllipticCurves.java ================================================ [File too large to display: 33.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/EncryptThenAuthenticate.java ================================================ [File too large to display: 6.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/EngineFactory.java ================================================ [File too large to display: 7.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/EngineWrapper.java ================================================ [File too large to display: 4.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/Enums.java ================================================ [File too large to display: 986 B] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/Hex.java ================================================ [File too large to display: 1.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/Hkdf.java ================================================ [File too large to display: 4.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/IndCpaCipher.java ================================================ [File too large to display: 1.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/Kwp.java ================================================ [File too large to display: 8.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/NonceBasedStreamingAead.java ================================================ [File too large to display: 3.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/PemKeyType.java ================================================ [File too large to display: 6.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/PrfAesCmac.java ================================================ [File too large to display: 4.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/PrfHmacJce.java ================================================ [File too large to display: 4.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/PrfMac.java ================================================ [File too large to display: 5.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/Random.java ================================================ [File too large to display: 1.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/RewindableReadableByteChannel.java ================================================ [File too large to display: 6.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/RsaSsaPkcs1SignJce.java ================================================ [File too large to display: 6.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/RsaSsaPkcs1VerifyJce.java ================================================ [File too large to display: 7.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/RsaSsaPssSignJce.java ================================================ [File too large to display: 8.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/RsaSsaPssVerifyJce.java ================================================ [File too large to display: 8.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/SelfKeyTestValidators.java ================================================ [File too large to display: 3.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/StreamSegmentDecrypter.java ================================================ [File too large to display: 1.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/StreamSegmentEncrypter.java ================================================ [File too large to display: 2.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/StreamingAeadDecryptingChannel.java ================================================ [File too large to display: 9.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/StreamingAeadDecryptingStream.java ================================================ [File too large to display: 11.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/StreamingAeadEncryptingChannel.java ================================================ [File too large to display: 4.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/StreamingAeadEncryptingStream.java ================================================ [File too large to display: 3.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/StreamingAeadSeekableDecryptingChannel.java ================================================ [File too large to display: 13.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/SubtleUtil.java ================================================ [File too large to display: 5.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/Validators.java ================================================ [File too large to display: 8.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/X25519.java ================================================ [File too large to display: 4.7 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/XChaCha20.java ================================================ [File too large to display: 2.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/XChaCha20Poly1305.java ================================================ [File too large to display: 4.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/prf/BUILD.bazel ================================================ [File too large to display: 2.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/prf/HkdfStreamingPrf.java ================================================ [File too large to display: 6.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/prf/PrfImpl.java ================================================ [File too large to display: 2.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/subtle/prf/StreamingPrf.java ================================================ [File too large to display: 2.2 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/testing/BUILD.bazel ================================================ [File too large to display: 8.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/testing/FakeKmsClient.java ================================================ [File too large to display: 3.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/testing/HpkeTestEncryption.java ================================================ [File too large to display: 1.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/testing/HpkeTestId.java ================================================ [File too large to display: 2.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/testing/HpkeTestSetup.java ================================================ [File too large to display: 8.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/testing/HpkeTestUtil.java ================================================ [File too large to display: 4.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/testing/HpkeTestVector.java ================================================ [File too large to display: 1.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/testing/StreamingTestUtil.java ================================================ [File too large to display: 49.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/testing/TestUtil.java ================================================ [File too large to display: 33.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/testing/WycheproofTestUtil.java ================================================ [File too large to display: 5.1 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/tinkkey/BUILD.bazel ================================================ [File too large to display: 2.9 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/tinkkey/KeyAccess.java ================================================ [File too large to display: 1.8 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/tinkkey/KeyHandle.java ================================================ [File too large to display: 6.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/tinkkey/SecretKeyAccess.java ================================================ [File too large to display: 1.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/tinkkey/TinkKey.java ================================================ [File too large to display: 2.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/tinkkey/internal/BUILD.bazel ================================================ [File too large to display: 1.6 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/tinkkey/internal/InternalKeyHandle.java ================================================ [File too large to display: 1.3 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/tinkkey/internal/ProtoKey.java ================================================ [File too large to display: 2.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/util/BUILD.bazel ================================================ [File too large to display: 2.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/util/Bytes.java ================================================ [File too large to display: 3.0 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/util/KeysDownloader.java ================================================ [File too large to display: 10.5 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/util/SecretBigInteger.java ================================================ [File too large to display: 2.4 KB] ================================================ FILE: java_src/src/main/java/com/google/crypto/tink/util/SecretBytes.java ================================================ [File too large to display: 2.5 KB] ================================================ FILE: java_src/src/main/resources/META-INF/proguard/protobuf.pro ================================================ [File too large to display: 750 B] ================================================ FILE: java_src/src/test/BUILD.bazel ================================================ [File too large to display: 21 B] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/BUILD.bazel ================================================ [File too large to display: 40.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/BinaryKeysetReaderTest.java ================================================ [File too large to display: 6.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/CleartextKeysetHandleTest.java ================================================ [File too large to display: 7.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/ConfigTest.java ================================================ [File too large to display: 1.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/ConfigurationFips140v2Test.java ================================================ [File too large to display: 28.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/ConfigurationFips140v2WithoutConscryptTest.java ================================================ [File too large to display: 1.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/ConfigurationV0Test.java ================================================ [File too large to display: 52.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/CryptoFormatTest.java ================================================ [File too large to display: 5.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/IntegrationTest.java ================================================ [File too large to display: 3.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/JsonKeysetReaderTest.java ================================================ [File too large to display: 21.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/JsonKeysetWriterTest.java ================================================ [File too large to display: 6.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/KeyTemplateTest.java ================================================ [File too large to display: 5.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/KeyTemplatesAsParametersTest.java ================================================ [File too large to display: 43.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/KeyTemplatesTest.java ================================================ [File too large to display: 2.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/KeysetHandleFullPrimitiveTest.java ================================================ [File too large to display: 11.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/KeysetHandleTest.java ================================================ [File too large to display: 87.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/KeysetManagerTest.java ================================================ [File too large to display: 43.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/LateRegistrationTest.java ================================================ [File too large to display: 17.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/LegacyKeysetSerializationTest.java ================================================ [File too large to display: 9.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/MonitoringUtilTest.java ================================================ [File too large to display: 6.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/NoSecretKeysetHandleTest.java ================================================ [File too large to display: 6.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/PemKeyTypeTest.java ================================================ [File too large to display: 10.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/RegistryConfigurationTest.java ================================================ [File too large to display: 1.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/RegistryMultithreadTest.java ================================================ [File too large to display: 3.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/RegistryTest.java ================================================ [File too large to display: 29.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/SecretKeyAccessTest.java ================================================ [File too large to display: 1.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/TinkJsonProtoKeysetFormatTest.java ================================================ [File too large to display: 14.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/TinkProtoKeysetFormatTest.java ================================================ [File too large to display: 18.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/TinkProtoParametersFormatTest.java ================================================ [File too large to display: 5.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/TinkProtoTest.java ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/UtilTest.java ================================================ [File too large to display: 13.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/VersionTest.java ================================================ [File too large to display: 1.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/AeadConfigTest.java ================================================ [File too large to display: 3.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/AeadFactoryTest.java ================================================ [File too large to display: 2.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/AeadFactoryWithoutWrapperRegisteredTest.java ================================================ [File too large to display: 2.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/AeadKeyTemplatesTest.java ================================================ [File too large to display: 11.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/AeadTest.java ================================================ [File too large to display: 8.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/AeadWrapperTest.java ================================================ [File too large to display: 27.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/AesCtrHmacAeadKeyManagerTest.java ================================================ [File too large to display: 18.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/AesCtrHmacAeadKeyTest.java ================================================ [File too large to display: 17.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/AesCtrHmacAeadParametersTest.java ================================================ [File too large to display: 21.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/AesEaxKeyManagerTest.java ================================================ [File too large to display: 12.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/AesEaxKeyTest.java ================================================ [File too large to display: 11.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/AesEaxParametersTest.java ================================================ [File too large to display: 10.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/AesGcmKeyManagerTest.java ================================================ [File too large to display: 19.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/AesGcmKeyTest.java ================================================ [File too large to display: 10.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/AesGcmParametersTest.java ================================================ [File too large to display: 8.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/AesGcmSivKeyManagerTest.java ================================================ [File too large to display: 15.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/AesGcmSivKeyTest.java ================================================ [File too large to display: 10.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/AesGcmSivParametersTest.java ================================================ [File too large to display: 4.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/BUILD.bazel ================================================ [File too large to display: 29.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/ChaCha20Poly1305KeyManagerTest.java ================================================ [File too large to display: 4.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/ChaCha20Poly1305KeyTest.java ================================================ [File too large to display: 5.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/ChaCha20Poly1305ParametersTest.java ================================================ [File too large to display: 5.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/KmsAeadKeyManagerTest.java ================================================ [File too large to display: 7.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/KmsEnvelopeAeadKeyManagerTest.java ================================================ [File too large to display: 26.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/KmsEnvelopeAeadTest.java ================================================ [File too large to display: 9.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/LegacyKmsAeadKeyTest.java ================================================ [File too large to display: 5.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/LegacyKmsAeadParametersTest.java ================================================ [File too large to display: 3.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/LegacyKmsAeadProtoSerializationTest.java ================================================ [File too large to display: 8.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/LegacyKmsEnvelopeAeadKeyTest.java ================================================ [File too large to display: 7.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/LegacyKmsEnvelopeAeadParametersTest.java ================================================ [File too large to display: 15.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/LegacyKmsEnvelopeAeadProtoSerializationTest.java ================================================ [File too large to display: 23.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/PredefinedAeadParametersTest.java ================================================ [File too large to display: 2.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/XChaCha20Poly1305KeyManagerTest.java ================================================ [File too large to display: 8.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/XChaCha20Poly1305KeyTest.java ================================================ [File too large to display: 5.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/XChaCha20Poly1305ParametersTest.java ================================================ [File too large to display: 5.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/internal/AesCtrHmacAeadProtoSerializationTest.java ================================================ [File too large to display: 30.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/internal/AesEaxProtoSerializationTest.java ================================================ [File too large to display: 16.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/internal/AesGcmProtoSerializationTest.java ================================================ [File too large to display: 15.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/internal/AesGcmSivProtoSerializationTest.java ================================================ [File too large to display: 14.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/internal/BUILD.bazel ================================================ [File too large to display: 17.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/internal/ChaCha20Poly1305JceTest.java ================================================ [File too large to display: 15.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/internal/ChaCha20Poly1305ProtoSerializationTest.java ================================================ [File too large to display: 12.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/internal/ChaCha20UtilTest.java ================================================ [File too large to display: 7.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/internal/InsecureNonceAesGcmJceTest.java ================================================ [File too large to display: 15.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/internal/InsecureNonceChaCha20Poly1305JceTest.java ================================================ [File too large to display: 14.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/internal/InsecureNonceChaCha20Poly1305Test.java ================================================ [File too large to display: 12.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/internal/InsecureNonceChaCha20Test.java ================================================ [File too large to display: 9.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/internal/InsecureNonceXChaCha20Poly1305Test.java ================================================ [File too large to display: 9.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/internal/InsecureNonceXChaCha20Test.java ================================================ [File too large to display: 9.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/internal/LegacyAesCtrHmacTestKeyManagerTest.java ================================================ [File too large to display: 7.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/internal/LegacyFullAeadIntegrationTest.java ================================================ [File too large to display: 13.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/internal/LegacyFullAeadTest.java ================================================ [File too large to display: 7.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/internal/Poly1305Test.java ================================================ [File too large to display: 12.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/internal/XChaCha20Poly1305JceTest.java ================================================ [File too large to display: 15.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/internal/XChaCha20Poly1305ProtoSerializationTest.java ================================================ [File too large to display: 12.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/subtle/AesGcmSivTest.java ================================================ [File too large to display: 17.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/aead/subtle/BUILD.bazel ================================================ [File too large to display: 1.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/config/BUILD.bazel ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/config/TinkConfigTest.java ================================================ [File too large to display: 2.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/config/TinkFipsTest.java ================================================ [File too large to display: 2.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/config/internal/BUILD.bazel ================================================ [File too large to display: 321 B] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/config/internal/TinkFipsUtilTest.java ================================================ [File too large to display: 4.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/custom/BUILD.bazel ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/custom/CustomAeadKeyManagerTest.java ================================================ [File too large to display: 10.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/daead/AesSivKeyManagerTest.java ================================================ [File too large to display: 15.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/daead/AesSivKeyTest.java ================================================ [File too large to display: 10.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/daead/AesSivParametersTest.java ================================================ [File too large to display: 4.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/daead/BUILD.bazel ================================================ [File too large to display: 9.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/daead/DaeadTest.java ================================================ [File too large to display: 8.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/daead/DeterministicAeadConfigTest.java ================================================ [File too large to display: 1.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/daead/DeterministicAeadFactoryTest.java ================================================ [File too large to display: 2.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/daead/DeterministicAeadFactoryWithoutWrapperRegisteredTest.java ================================================ [File too large to display: 2.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/daead/DeterministicAeadKeyTemplatesTest.java ================================================ [File too large to display: 2.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/daead/DeterministicAeadWrapperTest.java ================================================ [File too large to display: 17.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/daead/KeyManagerIntegrationTest.java ================================================ [File too large to display: 8.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/daead/PredefinedDeterministicAeadParametersTest.java ================================================ [File too large to display: 1.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/daead/internal/AesSivProtoSerializationTest.java ================================================ [File too large to display: 14.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/daead/internal/BUILD.bazel ================================================ [File too large to display: 2.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/daead/internal/LegacyFullDeterministicAeadTest.java ================================================ [File too large to display: 5.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/daead/internal/testing/BUILD.bazel ================================================ [File too large to display: 767 B] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/daead/internal/testing/LegacyAesSivTestKeyManagerTest.java ================================================ [File too large to display: 4.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/BUILD.bazel ================================================ [File too large to display: 21.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/EciesAeadHkdfHybridDecryptTest.java ================================================ [File too large to display: 30.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/EciesAeadHkdfHybridEncryptTest.java ================================================ [File too large to display: 6.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/EciesAeadHkdfPrivateKeyManagerTest.java ================================================ [File too large to display: 15.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/EciesParametersTest.java ================================================ [File too large to display: 22.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/EciesPrivateKeyTest.java ================================================ [File too large to display: 18.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/EciesPublicKeyTest.java ================================================ [File too large to display: 17.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/HpkeParametersTest.java ================================================ [File too large to display: 9.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/HpkePrivateKeyTest.java ================================================ [File too large to display: 13.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/HpkeProtoSerializationTest.java ================================================ [File too large to display: 30.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/HpkePublicKeyTest.java ================================================ [File too large to display: 14.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/HybridConfigTest.java ================================================ [File too large to display: 2.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/HybridDecryptFactoryTest.java ================================================ [File too large to display: 2.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/HybridDecryptWrapperTest.java ================================================ [File too large to display: 17.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/HybridEncryptDecryptFactoryWithoutWrapperRegisteredTest.java ================================================ [File too large to display: 2.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/HybridEncryptFactoryTest.java ================================================ [File too large to display: 2.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/HybridEncryptWrapperTest.java ================================================ [File too large to display: 15.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/HybridKeyTemplatesTest.java ================================================ [File too large to display: 8.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/HybridTest.java ================================================ [File too large to display: 13.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/KeyManagerIntegrationTest.java ================================================ [File too large to display: 11.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/PredefinedHybridParametersTest.java ================================================ [File too large to display: 2.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/internal/AesGcmHpkeAeadTest.java ================================================ [File too large to display: 5.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/internal/BUILD.bazel ================================================ [File too large to display: 15.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/internal/ChaCha20Poly1305HpkeAeadTest.java ================================================ [File too large to display: 4.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/internal/EciesProtoSerializationTest.java ================================================ [File too large to display: 50.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/internal/HkdfHpkeKdfTest.java ================================================ [File too large to display: 8.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/internal/HpkeContextTest.java ================================================ [File too large to display: 14.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/internal/HpkeEncryptDecryptTest.java ================================================ [File too large to display: 12.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/internal/HpkeKemKeyFactoryTest.java ================================================ [File too large to display: 4.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/internal/HpkePrimitiveFactoryTest.java ================================================ [File too large to display: 7.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/internal/HpkePrivateKeyManagerTest.java ================================================ [File too large to display: 9.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/internal/HpkeUtilTest.java ================================================ [File too large to display: 3.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/internal/LegacyFullHybridDecryptTest.java ================================================ [File too large to display: 7.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/internal/LegacyFullHybridEncryptTest.java ================================================ [File too large to display: 6.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/internal/NistCurvesHpkeKemTest.java ================================================ [File too large to display: 14.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/internal/X25519HpkeKemPrivateKeyTest.java ================================================ [File too large to display: 2.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/internal/X25519HpkeKemTest.java ================================================ [File too large to display: 14.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/internal/testing/BUILD.bazel ================================================ [File too large to display: 2.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/internal/testing/LegacyHybridDecryptKeyManagerTest.java ================================================ [File too large to display: 5.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/internal/testing/LegacyHybridEncryptKeyManagerTest.java ================================================ [File too large to display: 3.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/subtle/AeadOrDaeadTest.java ================================================ [File too large to display: 3.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/subtle/BUILD.bazel ================================================ [File too large to display: 2.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/subtle/RsaKemHybridDecryptTest.java ================================================ [File too large to display: 22.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/subtle/RsaKemHybridEncryptTest.java ================================================ [File too large to display: 3.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/hybrid/subtle/RsaKemTest.java ================================================ [File too large to display: 3.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/integration/awskms/AwsKmsAeadTest.java ================================================ [File too large to display: 4.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/integration/awskms/AwsKmsClientTest.java ================================================ [File too large to display: 11.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/integration/awskms/BUILD.bazel ================================================ [File too large to display: 2.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/integration/awskms/FakeAwsKmsTest.java ================================================ [File too large to display: 5.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/integration/gcpkms/BUILD.bazel ================================================ [File too large to display: 3.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/integration/gcpkms/FakeCloudKmsTest.java ================================================ [File too large to display: 9.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/integration/gcpkms/GcpKmsAeadTest.java ================================================ [File too large to display: 12.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/integration/gcpkms/GcpKmsClientTest.java ================================================ [File too large to display: 11.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/integration/gcpkms/GcpKmsIntegrationTest.java ================================================ [File too large to display: 11.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/integration/hcvault/BUILD.bazel ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/integration/hcvault/FakeHcVaultTest.java ================================================ [File too large to display: 3.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/integration/hcvault/HcVaultAeadTest.java ================================================ [File too large to display: 4.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/BUILD.bazel ================================================ [File too large to display: 27.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/BigIntegerEncodingTest.java ================================================ [File too large to display: 12.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/Curve25519Test.java ================================================ [File too large to display: 4.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/Ed25519Test.java ================================================ [File too large to display: 2.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/EllipticCurvesUtilTest.java ================================================ [File too large to display: 20.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/EnumTypeProtoConverterTest.java ================================================ [File too large to display: 3.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/Field25519Test.java ================================================ [File too large to display: 6.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/InternalConfigurationTest.java ================================================ [File too large to display: 14.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/JsonParserTest.java ================================================ [File too large to display: 26.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/KeyManagerRegistryTest.java ================================================ [File too large to display: 12.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/KeyParserTest.java ================================================ [File too large to display: 3.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/KeySerializerTest.java ================================================ [File too large to display: 3.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/KeyTemplateProtoConverterTest.java ================================================ [File too large to display: 1.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/KeyTesterTest.java ================================================ [File too large to display: 6.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/LegacyKeyManagerImplTest.java ================================================ [File too large to display: 19.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/LegacyProtoKeyTest.java ================================================ [File too large to display: 9.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/LegacyProtoParametersTest.java ================================================ [File too large to display: 3.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/MutableKeyCreationRegistryTest.java ================================================ [File too large to display: 6.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/MutableKeyDerivationRegistryTest.java ================================================ [File too large to display: 6.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/MutableMonitoringRegistryTest.java ================================================ [File too large to display: 3.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/MutableParametersRegistryTest.java ================================================ [File too large to display: 5.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/MutablePrimitiveRegistryMultithreadTest.java ================================================ [File too large to display: 6.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/MutablePrimitiveRegistryTest.java ================================================ [File too large to display: 7.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/MutableSerializationRegistryMultithreadTest.java ================================================ [File too large to display: 14.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/MutableSerializationRegistryTest.java ================================================ [File too large to display: 21.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/OutputPrefixUtilTest.java ================================================ [File too large to display: 1.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/ParametersParserTest.java ================================================ [File too large to display: 2.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/ParametersSerializerTest.java ================================================ [File too large to display: 2.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/PrimitiveConstructorTest.java ================================================ [File too large to display: 3.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/PrimitiveRegistryTest.java ================================================ [File too large to display: 14.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/PrimitiveSetTest.java ================================================ [File too large to display: 26.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/ProtoKeySerializationTest.java ================================================ [File too large to display: 4.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/ProtoParametersSerializationTest.java ================================================ [File too large to display: 3.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/RandomTest.java ================================================ [File too large to display: 2.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/RandomWithoutConscryptTest.java ================================================ [File too large to display: 2.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/RandomWithoutInstallingConscryptTest.java ================================================ [File too large to display: 1.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/RegistryConfigurationTest.java ================================================ [File too large to display: 8.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/SerializationRegistryTest.java ================================================ [File too large to display: 35.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/SlowInputStreamTest.java ================================================ [File too large to display: 2.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/TinkBugExceptionTest.java ================================================ [File too large to display: 2.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/UtilTest.java ================================================ [File too large to display: 6.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/testing/AssertsTest.java ================================================ [File too large to display: 16.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/testing/BUILD.bazel ================================================ [File too large to display: 3.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/testing/BigIntegerTestUtilTest.java ================================================ [File too large to display: 1.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/testing/FakeMonitoringClientTest.java ================================================ [File too large to display: 5.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/testing/KeyWithSerializationTest.java ================================================ [File too large to display: 2.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/internal/testing/ParametersWithSerializationTest.java ================================================ [File too large to display: 1.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/BUILD.bazel ================================================ [File too large to display: 30.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JsonUtilTest.java ================================================ [File too large to display: 3.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwkSetConverterTest.java ================================================ [File too large to display: 59.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtEcdsaParametersTest.java ================================================ [File too large to display: 6.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtEcdsaPrivateKeyTest.java ================================================ [File too large to display: 14.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtEcdsaProtoSerializationTest.java ================================================ [File too large to display: 30.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtEcdsaPublicKeyTest.java ================================================ [File too large to display: 15.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtEcdsaSignKeyManagerTest.java ================================================ [File too large to display: 28.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtEcdsaVerifyKeyManagerTest.java ================================================ [File too large to display: 2.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtFormatTest.java ================================================ [File too large to display: 20.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtHmacKeyManagerTest.java ================================================ [File too large to display: 42.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtHmacKeyTest.java ================================================ [File too large to display: 14.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtHmacParametersTest.java ================================================ [File too large to display: 6.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtHmacProtoSerializationTest.java ================================================ [File too large to display: 17.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtMacConfigTest.java ================================================ [File too large to display: 2.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtMacWrapperTest.java ================================================ [File too large to display: 10.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtPublicKeySignVerifyWrappersTest.java ================================================ [File too large to display: 14.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtRsaSsaPkcs1ParametersTest.java ================================================ [File too large to display: 13.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtRsaSsaPkcs1PrivateKeyTest.java ================================================ [File too large to display: 28.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtRsaSsaPkcs1ProtoSerializationTest.java ================================================ [File too large to display: 26.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtRsaSsaPkcs1PublicKeyTest.java ================================================ [File too large to display: 14.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtRsaSsaPkcs1SignKeyManagerTest.java ================================================ [File too large to display: 30.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtRsaSsaPssParametersTest.java ================================================ [File too large to display: 12.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtRsaSsaPssPrivateKeyTest.java ================================================ [File too large to display: 28.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtRsaSsaPssProtoSerializationTest.java ================================================ [File too large to display: 26.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtRsaSsaPssPublicKeyTest.java ================================================ [File too large to display: 13.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtRsaSsaPssSignKeyManagerTest.java ================================================ [File too large to display: 28.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtRsaSsaPssVerifyKeyManagerTest.java ================================================ [File too large to display: 2.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtSignatureConfigTest.java ================================================ [File too large to display: 3.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtSignatureTest.java ================================================ [File too large to display: 9.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtTest.java ================================================ [File too large to display: 10.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/JwtValidatorTest.java ================================================ [File too large to display: 18.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/RawJwtTest.java ================================================ [File too large to display: 30.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/jwt/VerifiedJwtTest.java ================================================ [File too large to display: 10.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/keyderivation/BUILD.bazel ================================================ [File too large to display: 4.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/keyderivation/KeyDerivationConfigTest.java ================================================ [File too large to display: 2.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/keyderivation/KeyDerivationTest.java ================================================ [File too large to display: 12.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/keyderivation/KeysetDeriverWrapperTest.java ================================================ [File too large to display: 1.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/keyderivation/PrfBasedKeyDerivationKeyTest.java ================================================ [File too large to display: 11.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/keyderivation/PrfBasedKeyDerivationParametersTest.java ================================================ [File too large to display: 5.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/keyderivation/internal/BUILD.bazel ================================================ [File too large to display: 14.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/keyderivation/internal/KeysetDeriverWrapperTest.java ================================================ [File too large to display: 21.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/keyderivation/internal/PrfBasedDeriverKeyManagerTest.java ================================================ [File too large to display: 16.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/keyderivation/internal/PrfBasedDeriverSecondTest.java ================================================ [File too large to display: 21.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/keyderivation/internal/PrfBasedKeyDerivationKeyProtoSerializationTest.java ================================================ [File too large to display: 27.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/keyderivation/internal/PrfBasedKeyDeriverTest.java ================================================ [File too large to display: 17.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/AesCmacKeyManagerTest.java ================================================ [File too large to display: 7.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/AesCmacKeyTest.java ================================================ [File too large to display: 14.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/AesCmacParametersTest.java ================================================ [File too large to display: 12.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/BUILD.bazel ================================================ [File too large to display: 12.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/ChunkedMacTest.java ================================================ [File too large to display: 7.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/ChunkedMacWrapperTest.java ================================================ [File too large to display: 18.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/HmacKeyManagerTest.java ================================================ [File too large to display: 11.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/HmacKeyTest.java ================================================ [File too large to display: 13.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/HmacParametersTest.java ================================================ [File too large to display: 19.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/MacConfigTest.java ================================================ [File too large to display: 2.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/MacFactoryTest.java ================================================ [File too large to display: 2.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/MacFactoryWithoutWrapperRegisteredTest.java ================================================ [File too large to display: 1.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/MacKeyTemplatesTest.java ================================================ [File too large to display: 5.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/MacTest.java ================================================ [File too large to display: 10.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/MacWrapperTest.java ================================================ [File too large to display: 25.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/PredefinedMacParametersTest.java ================================================ [File too large to display: 2.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/internal/AesCmacProtoSerializationTest.java ================================================ [File too large to display: 21.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/internal/AesUtilTest.java ================================================ [File too large to display: 2.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/internal/BUILD.bazel ================================================ [File too large to display: 8.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/internal/ChunkedAesCmacTest.java ================================================ [File too large to display: 27.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/internal/ChunkedHmacTest.java ================================================ [File too large to display: 15.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/internal/HmacProtoSerializationTest.java ================================================ [File too large to display: 23.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/internal/LegacyFullMacIntegrationTest.java ================================================ [File too large to display: 7.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/mac/internal/LegacyFullMacTest.java ================================================ [File too large to display: 5.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/monitoring/BUILD.bazel ================================================ [File too large to display: 1.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/monitoring/MonitoringAnnotationsTest.java ================================================ [File too large to display: 4.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/monitoring/MonitoringKeysetInfoTest.java ================================================ [File too large to display: 10.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/prf/AesCmacPrfKeyManagerTest.java ================================================ [File too large to display: 6.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/prf/AesCmacPrfKeyTest.java ================================================ [File too large to display: 3.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/prf/AesCmacPrfParametersTest.java ================================================ [File too large to display: 3.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/prf/BUILD.bazel ================================================ [File too large to display: 13.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/prf/HkdfPrfKeyManagerTest.java ================================================ [File too large to display: 12.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/prf/HkdfPrfKeyTest.java ================================================ [File too large to display: 5.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/prf/HkdfPrfParametersTest.java ================================================ [File too large to display: 6.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/prf/HmacPrfKeyManagerTest.java ================================================ [File too large to display: 12.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/prf/HmacPrfKeyTest.java ================================================ [File too large to display: 5.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/prf/HmacPrfParametersTest.java ================================================ [File too large to display: 4.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/prf/PredefinedPrfParametersTest.java ================================================ [File too large to display: 1.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/prf/PrfConfigTest.java ================================================ [File too large to display: 2.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/prf/PrfKeyTemplatesTest.java ================================================ [File too large to display: 3.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/prf/PrfSetWrapperTest.java ================================================ [File too large to display: 13.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/prf/PrfTest.java ================================================ [File too large to display: 7.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/prf/internal/AesCmacPrfProtoSerializationTest.java ================================================ [File too large to display: 9.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/prf/internal/BUILD.bazel ================================================ [File too large to display: 7.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/prf/internal/HkdfPrfProtoSerializationTest.java ================================================ [File too large to display: 14.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/prf/internal/HmacPrfProtoSerializationTest.java ================================================ [File too large to display: 14.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/prf/internal/LegacyFullPrfIntegrationTest.java ================================================ [File too large to display: 8.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/prf/internal/LegacyFullPrfTest.java ================================================ [File too large to display: 2.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/prf/internal/LegacyHmacPrfTestKeyManagerTest.java ================================================ [File too large to display: 5.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/BUILD.bazel ================================================ [File too large to display: 29.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/EcdsaParametersTest.java ================================================ [File too large to display: 12.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/EcdsaPrivateKeyTest.java ================================================ [File too large to display: 17.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/EcdsaPublicKeyTest.java ================================================ [File too large to display: 17.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/EcdsaSignKeyManagerTest.java ================================================ [File too large to display: 9.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/EcdsaVerifyKeyManagerTest.java ================================================ [File too large to display: 9.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/Ed25519ParametersTest.java ================================================ [File too large to display: 5.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/Ed25519PrivateKeyManagerTest.java ================================================ [File too large to display: 10.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/Ed25519PrivateKeyTest.java ================================================ [File too large to display: 8.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/Ed25519PublicKeyManagerTest.java ================================================ [File too large to display: 2.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/Ed25519PublicKeyTest.java ================================================ [File too large to display: 7.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/KeyConversionTest.java ================================================ [File too large to display: 10.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/KeyManagerIntegrationTest.java ================================================ [File too large to display: 12.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/PredefinedSignatureParametersTest.java ================================================ [File too large to display: 4.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/PublicKeySignFactoryTest.java ================================================ [File too large to display: 2.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/PublicKeySignVerifyFactoryWithoutWrapperRegisteredTest.java ================================================ [File too large to display: 2.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/PublicKeySignWrapperTest.java ================================================ [File too large to display: 17.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/PublicKeyVerifyFactoryTest.java ================================================ [File too large to display: 2.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/PublicKeyVerifyWrapperTest.java ================================================ [File too large to display: 20.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/RsaSsaPkcs1ParametersTest.java ================================================ [File too large to display: 13.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/RsaSsaPkcs1PrivateKeyTest.java ================================================ [File too large to display: 41.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/RsaSsaPkcs1PublicKeyTest.java ================================================ [File too large to display: 14.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/RsaSsaPkcs1SignKeyManagerTest.java ================================================ [File too large to display: 11.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/RsaSsaPkcs1VerifyKeyManagerTest.java ================================================ [File too large to display: 7.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/RsaSsaPssParametersTest.java ================================================ [File too large to display: 18.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/RsaSsaPssPrivateKeyTest.java ================================================ [File too large to display: 42.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/RsaSsaPssPublicKeyTest.java ================================================ [File too large to display: 15.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/RsaSsaPssSignKeyManagerTest.java ================================================ [File too large to display: 12.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/RsaSsaPssVerifyKeyManagerTest.java ================================================ [File too large to display: 9.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/SignatureConfigTest.java ================================================ [File too large to display: 3.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/SignatureKeyTemplatesTest.java ================================================ [File too large to display: 13.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/SignaturePemKeysetReaderTest.java ================================================ [File too large to display: 22.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/SignatureTest.java ================================================ [File too large to display: 16.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/internal/BUILD.bazel ================================================ [File too large to display: 8.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/internal/EcdsaProtoSerializationTest.java ================================================ [File too large to display: 37.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/internal/Ed25519ProtoSerializationTest.java ================================================ [File too large to display: 20.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/internal/LegacyFullSignTest.java ================================================ [File too large to display: 6.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/internal/LegacyFullVerifyTest.java ================================================ [File too large to display: 6.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/internal/RsaSsaPkcs1ProtoSerializationTest.java ================================================ [File too large to display: 46.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/internal/RsaSsaPssProtoSerializationTest.java ================================================ [File too large to display: 53.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/internal/SigUtilTest.java ================================================ [File too large to display: 1.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/internal/testing/BUILD.bazel ================================================ [File too large to display: 2.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/internal/testing/LegacyPublicKeySignKeyManagerTest.java ================================================ [File too large to display: 4.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/signature/internal/testing/LegacyPublicKeyVerifyKeyManagerTest.java ================================================ [File too large to display: 2.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/streamingaead/AesCtrHmacStreamingKeyManagerTest.java ================================================ [File too large to display: 7.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/streamingaead/AesCtrHmacStreamingKeyTest.java ================================================ [File too large to display: 5.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/streamingaead/AesCtrHmacStreamingParametersTest.java ================================================ [File too large to display: 17.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/streamingaead/AesGcmHkdfStreamingKeyManagerTest.java ================================================ [File too large to display: 12.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/streamingaead/AesGcmHkdfStreamingKeyTest.java ================================================ [File too large to display: 5.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/streamingaead/AesGcmHkdfStreamingParametersTest.java ================================================ [File too large to display: 10.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/streamingaead/BUILD.bazel ================================================ [File too large to display: 13.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/streamingaead/PredefinedStreamingAeadParametersTest.java ================================================ [File too large to display: 2.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/streamingaead/StreamingAeadConfigTest.java ================================================ [File too large to display: 2.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/streamingaead/StreamingAeadFactoryTest.java ================================================ [File too large to display: 1.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/streamingaead/StreamingAeadFactoryWithoutWrapperRegisteredTest.java ================================================ [File too large to display: 1.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/streamingaead/StreamingAeadKeyTemplatesTest.java ================================================ [File too large to display: 12.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/streamingaead/StreamingAeadTest.java ================================================ [File too large to display: 11.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/streamingaead/StreamingAeadUtilTest.java ================================================ [File too large to display: 1.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/streamingaead/StreamingAeadWrapperLegacyTest.java ================================================ [File too large to display: 7.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/streamingaead/StreamingAeadWrapperTest.java ================================================ [File too large to display: 13.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/streamingaead/internal/AesCtrHmacStreamingProtoSerializationTest.java ================================================ [File too large to display: 43.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/streamingaead/internal/AesGcmHkdfStreamingProtoSerializationTest.java ================================================ [File too large to display: 32.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/streamingaead/internal/BUILD.bazel ================================================ [File too large to display: 6.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/streamingaead/internal/LegacyAesGcmHkdfStreamingTestKeyManagerTest.java ================================================ [File too large to display: 7.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/streamingaead/internal/LegacyFullStreamingAeadIntegrationTest.java ================================================ [File too large to display: 9.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/streamingaead/internal/LegacyFullStreamingAeadTest.java ================================================ [File too large to display: 4.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/AeadThreadSafetyTest.java ================================================ [File too large to display: 6.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/AesCtrHmacStreamingTest.java ================================================ [File too large to display: 26.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/AesCtrJceCipherTest.java ================================================ [File too large to display: 5.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/AesEaxJceTest.java ================================================ [File too large to display: 18.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/AesGcmHkdfStreamingTest.java ================================================ [File too large to display: 27.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/AesGcmJceTest.java ================================================ [File too large to display: 22.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/AesSivTest.java ================================================ [File too large to display: 21.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/BUILD.bazel ================================================ [File too large to display: 28.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/Base64Test.java ================================================ [File too large to display: 6.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/BytesTest.java ================================================ [File too large to display: 9.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/ChaCha20Poly1305Test.java ================================================ [File too large to display: 14.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/ChaCha20Test.java ================================================ [File too large to display: 9.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/DaeadThreadSafetyTest.java ================================================ [File too large to display: 5.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/EcdsaSignJceTest.java ================================================ [File too large to display: 7.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/EcdsaVerifyJceTest.java ================================================ [File too large to display: 12.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/Ed25519SignTest.java ================================================ [File too large to display: 7.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/Ed25519VerifyTest.java ================================================ [File too large to display: 6.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/EllipticCurvesTest.java ================================================ [File too large to display: 29.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/EncryptThenAuthenticateTest.java ================================================ [File too large to display: 16.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/EngineFactoryFipsTest.java ================================================ [File too large to display: 4.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/EngineFactoryTest.java ================================================ [File too large to display: 4.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/HkdfTest.java ================================================ [File too large to display: 5.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/KwpTest.java ================================================ [File too large to display: 7.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/PemKeyTypeTest.java ================================================ [File too large to display: 10.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/PrfAesCmacTest.java ================================================ [File too large to display: 7.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/PrfHmacJceTest.java ================================================ [File too large to display: 15.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/PrfMacTest.java ================================================ [File too large to display: 5.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/RandomTest.java ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/RewindableReadableByteChannelTest.java ================================================ [File too large to display: 20.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/RsaSsaPkcs1SignJceTest.java ================================================ [File too large to display: 8.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/RsaSsaPkcs1VerifyJceTest.java ================================================ [File too large to display: 5.9 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/RsaSsaPssSignJceTest.java ================================================ [File too large to display: 9.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/RsaSsaPssVerifyJceTest.java ================================================ [File too large to display: 5.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/SelfKeyTestValidatorsTest.java ================================================ [File too large to display: 28.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/SignatureThreadSafetyTest.java ================================================ [File too large to display: 9.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/StreamingAeadThreadSafetyTest.java ================================================ [File too large to display: 17.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/SubtleUtilTest.java ================================================ [File too large to display: 7.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/ValidatorsTest.java ================================================ [File too large to display: 7.4 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/X25519Test.java ================================================ [File too large to display: 6.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/XChaCha20Poly1305Test.java ================================================ [File too large to display: 13.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/XChaCha20Test.java ================================================ [File too large to display: 8.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/prf/BUILD.bazel ================================================ [File too large to display: 1.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/prf/HkdfStreamingPrfTest.java ================================================ [File too large to display: 13.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/subtle/prf/PrfImplTest.java ================================================ [File too large to display: 4.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/testing/BUILD.bazel ================================================ [File too large to display: 967 B] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/testing/FakeKmsClientTest.java ================================================ [File too large to display: 3.7 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/testing/HpkeTestUtilTest.java ================================================ [File too large to display: 12.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/testing/TestUtilTest.java ================================================ [File too large to display: 6.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/tinkkey/BUILD.bazel ================================================ [File too large to display: 2.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/tinkkey/KeyAccessTest.java ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/tinkkey/KeyHandleTest.java ================================================ [File too large to display: 11.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/tinkkey/SecretKeyAccessTest.java ================================================ [File too large to display: 1.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/tinkkey/internal/BUILD.bazel ================================================ [File too large to display: 1.0 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/tinkkey/internal/ProtoKeyTest.java ================================================ [File too large to display: 6.1 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/util/BUILD.bazel ================================================ [File too large to display: 1.3 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/util/BytesTest.java ================================================ [File too large to display: 4.6 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/util/KeysDownloaderTest.java ================================================ [File too large to display: 18.5 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/util/SecretBigIntegerTest.java ================================================ [File too large to display: 2.8 KB] ================================================ FILE: java_src/src/test/java/com/google/crypto/tink/util/SecretBytesTest.java ================================================ [File too large to display: 4.3 KB] ================================================ FILE: java_src/src_android/main/java/com/google/crypto/tink/internal/BUILD.bazel ================================================ [File too large to display: 229 B] ================================================ FILE: java_src/src_android/main/java/com/google/crypto/tink/internal/BuildDispatchedCode.java ================================================ [File too large to display: 1.2 KB] ================================================ FILE: java_src/template_rule.bzl ================================================ [File too large to display: 1.8 KB] ================================================ FILE: java_src/testdata/BUILD.bazel ================================================ ================================================ FILE: java_src/testdata/aws/BUILD.bazel ================================================ [File too large to display: 461 B] ================================================ FILE: java_src/testdata/aws/README.md ================================================ [File too large to display: 935 B] ================================================ FILE: java_src/testdata/aws/access_keys_bad.csv ================================================ [File too large to display: 94 B] ================================================ FILE: java_src/testdata/aws/credentials.cred ================================================ [File too large to display: 96 B] ================================================ FILE: java_src/testdata/aws/credentials.csv ================================================ [File too large to display: 196 B] ================================================ FILE: java_src/testdata/aws/credentials.ini ================================================ [File too large to display: 116 B] ================================================ FILE: java_src/testdata/aws/credentials_bad.csv ================================================ [File too large to display: 115 B] ================================================ FILE: java_src/testdata/aws/credentials_bad.ini ================================================ [File too large to display: 116 B] ================================================ FILE: java_src/testdata/aws/key_arn.txt ================================================ [File too large to display: 76 B] ================================================ FILE: java_src/testdata/aws/key_arn_bad.txt ================================================ [File too large to display: 76 B] ================================================ FILE: java_src/testdata/gcp/BUILD.bazel ================================================ [File too large to display: 389 B] ================================================ FILE: java_src/testdata/gcp/README.md ================================================ [File too large to display: 361 B] ================================================ FILE: java_src/testdata/gcp/credential.json ================================================ [File too large to display: 1.5 KB] ================================================ FILE: java_src/testdata/gcp/credential_bad.json ================================================ [File too large to display: 1.5 KB] ================================================ FILE: java_src/testdata/gcp/key_name.txt ================================================ [File too large to display: 110 B] ================================================ FILE: java_src/testdata/gcp/key_name_bad.txt ================================================ [File too large to display: 91 B] ================================================ FILE: java_src/testdata/keysets/BUILD.bazel ================================================ [File too large to display: 937 B] ================================================ FILE: java_src/testdata/testvectors/BUILD.bazel ================================================ [File too large to display: 7.2 KB] ================================================ FILE: java_src/testdata/testvectors/hpke_boringssl.json ================================================ [File too large to display: 6.0 MB] ================================================ FILE: java_src/tink_java_deps.bzl ================================================ [File too large to display: 5.3 KB] ================================================ FILE: java_src/tink_java_deps_init.bzl ================================================ [File too large to display: 490 B] ================================================ FILE: java_src/tink_version.bzl ================================================ [File too large to display: 76 B] ================================================ FILE: java_src/tools/BUILD.bazel ================================================ [File too large to display: 352 B] ================================================ FILE: java_src/tools/check_deps.bzl ================================================ [File too large to display: 3.3 KB] ================================================ FILE: java_src/tools/gen_java_test_rules.bzl ================================================ [File too large to display: 3.6 KB] ================================================ FILE: java_src/tools/gen_maven_jar_rules.bzl ================================================ [File too large to display: 3.7 KB] ================================================ FILE: java_src/tools/jar_jar.bzl ================================================ [File too large to display: 1.6 KB] ================================================ FILE: java_src/tools/java_single_jar.bzl ================================================ [File too large to display: 5.1 KB] ================================================ FILE: java_src/tools/javadoc.bzl ================================================ [File too large to display: 4.8 KB] ================================================ FILE: java_src/tools/refaster/README.md ================================================ [File too large to display: 3.4 KB] ================================================ FILE: java_src/tools/refaster/java/com/google/tink1_templates/AllChanges.java ================================================ [File too large to display: 18.9 KB] ================================================ FILE: java_src/tools/refaster/java/com/google/tinkuser/TinkUser.java ================================================ [File too large to display: 5.5 KB] ================================================ FILE: java_src/tools/refaster/java/com/google/tinkuser/TinkUser.java_expected ================================================ [File too large to display: 6.3 KB] ================================================ FILE: kokoro/README.md ================================================ [File too large to display: 973 B] ================================================ FILE: kokoro/gcp_ubuntu_per_language/cc/bazel/run_tests.sh ================================================ [File too large to display: 855 B] ================================================ FILE: kokoro/gcp_ubuntu_per_language/cc/bazel_fips/run_tests.sh ================================================ [File too large to display: 1.8 KB] ================================================ FILE: kokoro/gcp_ubuntu_per_language/cc/cmake/run_tests.sh ================================================ [File too large to display: 1.0 KB] ================================================ FILE: kokoro/gcp_ubuntu_per_language/cc/cmake_openssl/run_tests.sh ================================================ [File too large to display: 1015 B] ================================================ FILE: kokoro/gcp_ubuntu_per_language/cc/examples/cmake/run_tests.sh ================================================ [File too large to display: 1.1 KB] ================================================ FILE: kokoro/gcp_ubuntu_per_language/cc/examples/cmake_openssl/run_tests.sh ================================================ [File too large to display: 1001 B] ================================================ FILE: kokoro/gcp_ubuntu_per_language/go/bazel/run_tests.sh ================================================ [File too large to display: 1.4 KB] ================================================ FILE: kokoro/gcp_ubuntu_per_language/go/gomod/run_tests.sh ================================================ [File too large to display: 1.9 KB] ================================================ FILE: kokoro/gcp_ubuntu_per_language/java_src/run_tests.sh ================================================ [File too large to display: 4.2 KB] ================================================ FILE: kokoro/gcp_ubuntu_per_language/python/pip/run_tests.sh ================================================ [File too large to display: 1.8 KB] ================================================ FILE: kokoro/macos_external/cc/bazel/run_tests.sh ================================================ [File too large to display: 833 B] ================================================ FILE: kokoro/macos_external/cc/cmake/run_tests.sh ================================================ [File too large to display: 809 B] ================================================ FILE: kokoro/macos_external/cc/examples/cmake/run_tests.sh ================================================ [File too large to display: 845 B] ================================================ FILE: kokoro/macos_external/go/bazel/run_tests.sh ================================================ [File too large to display: 1.5 KB] ================================================ FILE: kokoro/macos_external/go/gomod/run_tests.sh ================================================ [File too large to display: 4.5 KB] ================================================ FILE: kokoro/macos_external/java_src/run_tests.sh ================================================ [File too large to display: 1.1 KB] ================================================ FILE: kokoro/macos_external/python/pip/run_tests.sh ================================================ [File too large to display: 1.7 KB] ================================================ FILE: kokoro/macos_external/tools/run_tests.sh ================================================ [File too large to display: 1.1 KB] ================================================ FILE: kokoro/run_tests.sh ================================================ [File too large to display: 6.2 KB] ================================================ FILE: kokoro/testutils/check_go_generated_files_up_to_date.sh ================================================ [File too large to display: 3.1 KB] ================================================ FILE: kokoro/testutils/copy_credentials.sh ================================================ [File too large to display: 3.4 KB] ================================================ FILE: kokoro/testutils/create_main_build_file.py ================================================ [File too large to display: 3.5 KB] ================================================ FILE: kokoro/testutils/install_cmake.sh ================================================ [File too large to display: 2.4 KB] ================================================ FILE: kokoro/testutils/install_go.sh ================================================ [File too large to display: 1.7 KB] ================================================ FILE: kokoro/testutils/install_openssl.sh ================================================ [File too large to display: 2.6 KB] ================================================ FILE: kokoro/testutils/install_protoc.sh ================================================ [File too large to display: 1.7 KB] ================================================ FILE: kokoro/testutils/install_python3.sh ================================================ [File too large to display: 1.8 KB] ================================================ FILE: kokoro/testutils/install_tink_via_pip.sh ================================================ [File too large to display: 2.7 KB] ================================================ FILE: kokoro/testutils/install_vault.sh ================================================ [File too large to display: 2.2 KB] ================================================ FILE: kokoro/testutils/run_bazel_tests.sh ================================================ [File too large to display: 4.0 KB] ================================================ FILE: kokoro/testutils/run_cmake_tests.sh ================================================ [File too large to display: 2.1 KB] ================================================ FILE: kokoro/testutils/run_go_mod_tests.sh ================================================ [File too large to display: 5.3 KB] ================================================ FILE: kokoro/testutils/run_hcvault_test_server.sh ================================================ [File too large to display: 2.0 KB] ================================================ FILE: kokoro/testutils/test_utils.sh ================================================ [File too large to display: 4.2 KB] ================================================ FILE: kokoro/testutils/update_android_sdk.sh ================================================ [File too large to display: 1.2 KB] ================================================ FILE: kokoro/testutils/upgrade_gcc.sh ================================================ [File too large to display: 1.2 KB] ================================================ FILE: passing_test.sh ================================================ [File too large to display: 24 B] ================================================ FILE: proto/BUILD.bazel ================================================ [File too large to display: 8.8 KB] ================================================ FILE: proto/CMakeLists.txt ================================================ [File too large to display: 3.0 KB] ================================================ FILE: proto/aes_cmac.proto ================================================ [File too large to display: 1.2 KB] ================================================ FILE: proto/aes_cmac_prf.proto ================================================ [File too large to display: 1.1 KB] ================================================ FILE: proto/aes_ctr.proto ================================================ [File too large to display: 1.1 KB] ================================================ FILE: proto/aes_ctr_hmac_aead.proto ================================================ [File too large to display: 1.2 KB] ================================================ FILE: proto/aes_ctr_hmac_streaming.proto ================================================ [File too large to display: 1.7 KB] ================================================ FILE: proto/aes_eax.proto ================================================ [File too large to display: 1.2 KB] ================================================ FILE: proto/aes_gcm.proto ================================================ [File too large to display: 2.5 KB] ================================================ FILE: proto/aes_gcm_hkdf_streaming.proto ================================================ [File too large to display: 1.6 KB] ================================================ FILE: proto/aes_gcm_siv.proto ================================================ [File too large to display: 1.2 KB] ================================================ FILE: proto/aes_siv.proto ================================================ [File too large to display: 1.5 KB] ================================================ FILE: proto/chacha20_poly1305.proto ================================================ [File too large to display: 1.2 KB] ================================================ FILE: proto/common.proto ================================================ [File too large to display: 1.5 KB] ================================================ FILE: proto/config.proto ================================================ [File too large to display: 1.9 KB] ================================================ FILE: proto/ecdsa.proto ================================================ [File too large to display: 2.5 KB] ================================================ FILE: proto/ecies_aead_hkdf.proto ================================================ [File too large to display: 3.6 KB] ================================================ FILE: proto/ed25519.proto ================================================ [File too large to display: 1.7 KB] ================================================ FILE: proto/empty.proto ================================================ [File too large to display: 908 B] ================================================ FILE: proto/experimental/pqcrypto/BUILD.bazel ================================================ [File too large to display: 330 B] ================================================ FILE: proto/experimental/pqcrypto/cecpq2_aead_hkdf.proto ================================================ [File too large to display: 3.6 KB] ================================================ FILE: proto/experimental/pqcrypto/dilithium.proto ================================================ [File too large to display: 1.6 KB] ================================================ FILE: proto/experimental/pqcrypto/falcon.proto ================================================ [File too large to display: 1.3 KB] ================================================ FILE: proto/experimental/pqcrypto/slh_dsa.proto ================================================ [File too large to display: 1.7 KB] ================================================ FILE: proto/experimental/pqcrypto/sphincs.proto ================================================ [File too large to display: 1.8 KB] ================================================ FILE: proto/hkdf_prf.proto ================================================ [File too large to display: 1.4 KB] ================================================ FILE: proto/hmac.proto ================================================ [File too large to display: 1.2 KB] ================================================ FILE: proto/hmac_prf.proto ================================================ [File too large to display: 1.2 KB] ================================================ FILE: proto/hpke.proto ================================================ [File too large to display: 1.9 KB] ================================================ FILE: proto/jwt_ecdsa.proto ================================================ [File too large to display: 2.0 KB] ================================================ FILE: proto/jwt_hmac.proto ================================================ [File too large to display: 1.5 KB] ================================================ FILE: proto/jwt_rsa_ssa_pkcs1.proto ================================================ [File too large to display: 2.7 KB] ================================================ FILE: proto/jwt_rsa_ssa_pss.proto ================================================ [File too large to display: 2.7 KB] ================================================ FILE: proto/kms_aead.proto ================================================ [File too large to display: 1.4 KB] ================================================ FILE: proto/kms_envelope.proto ================================================ [File too large to display: 1.6 KB] ================================================ FILE: proto/prf_based_deriver.proto ================================================ [File too large to display: 1.3 KB] ================================================ FILE: proto/rsa_ssa_pkcs1.proto ================================================ [File too large to display: 2.7 KB] ================================================ FILE: proto/rsa_ssa_pss.proto ================================================ [File too large to display: 3.0 KB] ================================================ FILE: proto/test_proto.proto ================================================ [File too large to display: 1.1 KB] ================================================ FILE: proto/tink.proto ================================================ [File too large to display: 7.1 KB] ================================================ FILE: proto/xchacha20_poly1305.proto ================================================ [File too large to display: 1.1 KB] ================================================ FILE: python/.bazelignore ================================================ [File too large to display: 9 B] ================================================ FILE: python/.bazelrc ================================================ [File too large to display: 1.3 KB] ================================================ FILE: python/.bazelversion ================================================ [File too large to display: 6 B] ================================================ FILE: python/BUILD.bazel ================================================ ================================================ FILE: python/MANIFEST.in ================================================ [File too large to display: 575 B] ================================================ FILE: python/README.md ================================================ [File too large to display: 1.0 KB] ================================================ FILE: python/VERSION ================================================ [File too large to display: 76 B] ================================================ FILE: python/WORKSPACE ================================================ [File too large to display: 588 B] ================================================ FILE: python/examples/.bazelrc ================================================ [File too large to display: 259 B] ================================================ FILE: python/examples/.bazelversion ================================================ [File too large to display: 6 B] ================================================ FILE: python/examples/BUILD.bazel ================================================ ================================================ FILE: python/examples/WORKSPACE ================================================ [File too large to display: 1.5 KB] ================================================ FILE: python/examples/aead/BUILD.bazel ================================================ [File too large to display: 1.5 KB] ================================================ FILE: python/examples/aead/README.md ================================================ [File too large to display: 1.0 KB] ================================================ FILE: python/examples/aead/aead_basic.py ================================================ [File too large to display: 2.5 KB] ================================================ FILE: python/examples/aead/aead_basic_test.py ================================================ [File too large to display: 803 B] ================================================ FILE: python/examples/aead/aead_cli.py ================================================ [File too large to display: 2.6 KB] ================================================ FILE: python/examples/aead/aead_cli_test.sh ================================================ [File too large to display: 4.9 KB] ================================================ FILE: python/examples/aead/aead_test_keyset.json ================================================ [File too large to display: 291 B] ================================================ FILE: python/examples/cleartext_keyset/BUILD.bazel ================================================ [File too large to display: 695 B] ================================================ FILE: python/examples/cleartext_keyset/README.md ================================================ [File too large to display: 1.1 KB] ================================================ FILE: python/examples/cleartext_keyset/cleartext_keyset_cli.py ================================================ [File too large to display: 3.3 KB] ================================================ FILE: python/examples/cleartext_keyset/cleartext_keyset_cli_test.sh ================================================ [File too large to display: 2.8 KB] ================================================ FILE: python/examples/deterministic_aead/BUILD.bazel ================================================ [File too large to display: 1.8 KB] ================================================ FILE: python/examples/deterministic_aead/README.md ================================================ [File too large to display: 1.2 KB] ================================================ FILE: python/examples/deterministic_aead/deterministic_aead_basic.py ================================================ [File too large to display: 2.7 KB] ================================================ FILE: python/examples/deterministic_aead/deterministic_aead_basic_test.py ================================================ [File too large to display: 858 B] ================================================ FILE: python/examples/deterministic_aead/deterministic_aead_cli.py ================================================ [File too large to display: 2.8 KB] ================================================ FILE: python/examples/deterministic_aead/deterministic_aead_cli_test.sh ================================================ [File too large to display: 5.5 KB] ================================================ FILE: python/examples/deterministic_aead/deterministic_aead_test_keyset.json ================================================ [File too large to display: 302 B] ================================================ FILE: python/examples/encrypted_keyset/BUILD.bazel ================================================ [File too large to display: 1.9 KB] ================================================ FILE: python/examples/encrypted_keyset/README.md ================================================ [File too large to display: 1.9 KB] ================================================ FILE: python/examples/encrypted_keyset/encrypted_keyset_cli.py ================================================ [File too large to display: 4.6 KB] ================================================ FILE: python/examples/encrypted_keyset/encrypted_keyset_cli_test.sh ================================================ [File too large to display: 5.5 KB] ================================================ FILE: python/examples/envelope_aead/BUILD.bazel ================================================ [File too large to display: 1.8 KB] ================================================ FILE: python/examples/envelope_aead/README.md ================================================ [File too large to display: 2.4 KB] ================================================ FILE: python/examples/envelope_aead/envelope_cli.py ================================================ [File too large to display: 2.8 KB] ================================================ FILE: python/examples/envelope_aead/envelope_cli_test.sh ================================================ [File too large to display: 4.6 KB] ================================================ FILE: python/examples/gcs/BUILD.bazel ================================================ [File too large to display: 2.2 KB] ================================================ FILE: python/examples/gcs/README.md ================================================ [File too large to display: 2.9 KB] ================================================ FILE: python/examples/gcs/gcs_envelope_aead_cli.py ================================================ [File too large to display: 4.0 KB] ================================================ FILE: python/examples/gcs/gcs_envelope_aead_cli_test.sh ================================================ [File too large to display: 2.8 KB] ================================================ FILE: python/examples/hybrid/BUILD.bazel ================================================ [File too large to display: 1.8 KB] ================================================ FILE: python/examples/hybrid/README.md ================================================ [File too large to display: 1.2 KB] ================================================ FILE: python/examples/hybrid/hybrid_basic.py ================================================ [File too large to display: 3.8 KB] ================================================ FILE: python/examples/hybrid/hybrid_basic_test.py ================================================ [File too large to display: 822 B] ================================================ FILE: python/examples/hybrid/hybrid_cli.py ================================================ [File too large to display: 2.9 KB] ================================================ FILE: python/examples/hybrid/hybrid_cli_test.sh ================================================ [File too large to display: 4.4 KB] ================================================ FILE: python/examples/hybrid/hybrid_test_private_keyset.json ================================================ [File too large to display: 332 B] ================================================ FILE: python/examples/hybrid/hybrid_test_public_keyset.json ================================================ [File too large to display: 282 B] ================================================ FILE: python/examples/jwt/BUILD.bazel ================================================ [File too large to display: 2.2 KB] ================================================ FILE: python/examples/jwt/README.md ================================================ [File too large to display: 1.7 KB] ================================================ FILE: python/examples/jwt/jwt_generate_public_jwk_set.py ================================================ [File too large to display: 1.9 KB] ================================================ FILE: python/examples/jwt/jwt_sign_cli.py ================================================ [File too large to display: 2.4 KB] ================================================ FILE: python/examples/jwt/jwt_signature_test.sh ================================================ [File too large to display: 4.9 KB] ================================================ FILE: python/examples/jwt/jwt_test_private_keyset.json ================================================ [File too large to display: 469 B] ================================================ FILE: python/examples/jwt/jwt_test_public_keyset.json ================================================ [File too large to display: 419 B] ================================================ FILE: python/examples/jwt/jwt_verify_cli.py ================================================ [File too large to display: 2.3 KB] ================================================ FILE: python/examples/mac/BUILD.bazel ================================================ [File too large to display: 1.5 KB] ================================================ FILE: python/examples/mac/README.md ================================================ [File too large to display: 956 B] ================================================ FILE: python/examples/mac/mac_basic.py ================================================ [File too large to display: 2.5 KB] ================================================ FILE: python/examples/mac/mac_basic_test.py ================================================ [File too large to display: 798 B] ================================================ FILE: python/examples/mac/mac_cli.py ================================================ [File too large to display: 2.8 KB] ================================================ FILE: python/examples/mac/mac_cli_test.sh ================================================ [File too large to display: 3.8 KB] ================================================ FILE: python/examples/mac/mac_test_keyset.json ================================================ [File too large to display: 387 B] ================================================ FILE: python/examples/requirements.in ================================================ [File too large to display: 43 B] ================================================ FILE: python/examples/requirements.txt ================================================ [File too large to display: 16.8 KB] ================================================ FILE: python/examples/signature/BUILD.bazel ================================================ [File too large to display: 1.9 KB] ================================================ FILE: python/examples/signature/README.md ================================================ [File too large to display: 1.2 KB] ================================================ FILE: python/examples/signature/signature_basic.py ================================================ [File too large to display: 4.2 KB] ================================================ FILE: python/examples/signature/signature_basic_test.py ================================================ [File too large to display: 823 B] ================================================ FILE: python/examples/signature/signature_cli.py ================================================ [File too large to display: 3.1 KB] ================================================ FILE: python/examples/signature/signature_cli_test.sh ================================================ [File too large to display: 3.7 KB] ================================================ FILE: python/examples/signature/signature_test_private_keyset.json ================================================ [File too large to display: 429 B] ================================================ FILE: python/examples/signature/signature_test_public_keyset.json ================================================ [File too large to display: 384 B] ================================================ FILE: python/examples/streaming_aead/BUILD.bazel ================================================ [File too large to display: 1.3 KB] ================================================ FILE: python/examples/streaming_aead/README.md ================================================ [File too large to display: 1.2 KB] ================================================ FILE: python/examples/streaming_aead/streaming_aead_cli.py ================================================ [File too large to display: 5.4 KB] ================================================ FILE: python/examples/streaming_aead/streaming_aead_cli_test.sh ================================================ [File too large to display: 3.8 KB] ================================================ FILE: python/examples/streaming_aead/streaming_aead_keyset.json ================================================ [File too large to display: 405 B] ================================================ FILE: python/examples/testdata/gcp/BUILD.bazel ================================================ [File too large to display: 389 B] ================================================ FILE: python/examples/testdata/gcp/README.md ================================================ [File too large to display: 361 B] ================================================ FILE: python/examples/testdata/gcp/credential.json ================================================ [File too large to display: 1.5 KB] ================================================ FILE: python/examples/testdata/gcp/credential_bad.json ================================================ [File too large to display: 1.5 KB] ================================================ FILE: python/examples/testdata/gcp/key_name.txt ================================================ [File too large to display: 110 B] ================================================ FILE: python/examples/testdata/gcp/key_name_bad.txt ================================================ [File too large to display: 91 B] ================================================ FILE: python/examples/walkthrough/BUILD.bazel ================================================ [File too large to display: 3.0 KB] ================================================ FILE: python/examples/walkthrough/create_keyset.py ================================================ [File too large to display: 1.3 KB] ================================================ FILE: python/examples/walkthrough/create_keyset_test.py ================================================ [File too large to display: 1.2 KB] ================================================ FILE: python/examples/walkthrough/load_cleartext_keyset.py ================================================ [File too large to display: 1.3 KB] ================================================ FILE: python/examples/walkthrough/load_cleartext_keyset_test.py ================================================ [File too large to display: 1.9 KB] ================================================ FILE: python/examples/walkthrough/load_encrypted_keyset.py ================================================ [File too large to display: 2.3 KB] ================================================ FILE: python/examples/walkthrough/load_encrypted_keyset_test.py ================================================ [File too large to display: 4.1 KB] ================================================ FILE: python/examples/walkthrough/obtain_and_use_a_primitive.py ================================================ [File too large to display: 2.7 KB] ================================================ FILE: python/examples/walkthrough/obtain_and_use_a_primitive_test.py ================================================ [File too large to display: 1.9 KB] ================================================ FILE: python/examples/walkthrough/write_cleartext_keyset.py ================================================ [File too large to display: 1.3 KB] ================================================ FILE: python/examples/walkthrough/write_cleartext_keyset_test.py ================================================ [File too large to display: 1.8 KB] ================================================ FILE: python/examples/walkthrough/write_keyset.py ================================================ [File too large to display: 2.1 KB] ================================================ FILE: python/examples/walkthrough/write_keyset_test.py ================================================ [File too large to display: 2.6 KB] ================================================ FILE: python/requirements.in ================================================ [File too large to display: 89 B] ================================================ FILE: python/requirements.txt ================================================ [File too large to display: 1.5 KB] ================================================ FILE: python/requirements_all.txt ================================================ [File too large to display: 16.6 KB] ================================================ FILE: python/requirements_awskms.in ================================================ [File too large to display: 15 B] ================================================ FILE: python/requirements_gcpkms.in ================================================ [File too large to display: 69 B] ================================================ FILE: python/requirements_hcvault.in ================================================ [File too large to display: 45 B] ================================================ FILE: python/setup.py ================================================ [File too large to display: 9.9 KB] ================================================ FILE: python/testdata/aws/BUILD.bazel ================================================ [File too large to display: 461 B] ================================================ FILE: python/testdata/aws/README.md ================================================ [File too large to display: 935 B] ================================================ FILE: python/testdata/aws/access_keys_bad.csv ================================================ [File too large to display: 94 B] ================================================ FILE: python/testdata/aws/credentials.cred ================================================ [File too large to display: 96 B] ================================================ FILE: python/testdata/aws/credentials.csv ================================================ [File too large to display: 196 B] ================================================ FILE: python/testdata/aws/credentials.ini ================================================ [File too large to display: 116 B] ================================================ FILE: python/testdata/aws/credentials_bad.csv ================================================ [File too large to display: 115 B] ================================================ FILE: python/testdata/aws/credentials_bad.ini ================================================ [File too large to display: 116 B] ================================================ FILE: python/testdata/aws/key_arn.txt ================================================ [File too large to display: 76 B] ================================================ FILE: python/testdata/aws/key_arn_bad.txt ================================================ [File too large to display: 76 B] ================================================ FILE: python/testdata/gcp/BUILD.bazel ================================================ [File too large to display: 389 B] ================================================ FILE: python/testdata/gcp/README.md ================================================ [File too large to display: 361 B] ================================================ FILE: python/testdata/gcp/credential.json ================================================ [File too large to display: 1.5 KB] ================================================ FILE: python/testdata/gcp/credential_bad.json ================================================ [File too large to display: 1.5 KB] ================================================ FILE: python/testdata/gcp/key_name.txt ================================================ [File too large to display: 110 B] ================================================ FILE: python/testdata/gcp/key_name_bad.txt ================================================ [File too large to display: 91 B] ================================================ FILE: python/tink/BUILD.bazel ================================================ [File too large to display: 6.2 KB] ================================================ FILE: python/tink/__init__.py ================================================ [File too large to display: 2.1 KB] ================================================ FILE: python/tink/_insecure_keyset_handle.py ================================================ [File too large to display: 1.3 KB] ================================================ FILE: python/tink/_insecure_keyset_handle_test.py ================================================ [File too large to display: 2.0 KB] ================================================ FILE: python/tink/_json_proto_keyset_format.py ================================================ [File too large to display: 2.9 KB] ================================================ FILE: python/tink/_json_proto_keyset_format_test.py ================================================ [File too large to display: 8.6 KB] ================================================ FILE: python/tink/_keyset_handle.py ================================================ [File too large to display: 12.0 KB] ================================================ FILE: python/tink/_keyset_handle_test.py ================================================ [File too large to display: 12.9 KB] ================================================ FILE: python/tink/_keyset_reader.py ================================================ [File too large to display: 2.8 KB] ================================================ FILE: python/tink/_keyset_reader_test.py ================================================ [File too large to display: 6.1 KB] ================================================ FILE: python/tink/_keyset_writer.py ================================================ [File too large to display: 3.3 KB] ================================================ FILE: python/tink/_keyset_writer_test.py ================================================ [File too large to display: 4.5 KB] ================================================ FILE: python/tink/_kms_clients.py ================================================ [File too large to display: 2.1 KB] ================================================ FILE: python/tink/_kms_clients_test.py ================================================ [File too large to display: 1.8 KB] ================================================ FILE: python/tink/_proto_keyset_format.py ================================================ [File too large to display: 2.9 KB] ================================================ FILE: python/tink/_proto_keyset_format_test.py ================================================ [File too large to display: 11.9 KB] ================================================ FILE: python/tink/_secret_key_access.py ================================================ [File too large to display: 882 B] ================================================ FILE: python/tink/aead/BUILD.bazel ================================================ [File too large to display: 4.0 KB] ================================================ FILE: python/tink/aead/__init__.py ================================================ [File too large to display: 937 B] ================================================ FILE: python/tink/aead/_aead.py ================================================ [File too large to display: 2.1 KB] ================================================ FILE: python/tink/aead/_aead_key_manager.py ================================================ [File too large to display: 2.1 KB] ================================================ FILE: python/tink/aead/_aead_key_manager_test.py ================================================ [File too large to display: 11.0 KB] ================================================ FILE: python/tink/aead/_aead_key_templates.py ================================================ [File too large to display: 10.8 KB] ================================================ FILE: python/tink/aead/_aead_key_templates_test.py ================================================ [File too large to display: 5.3 KB] ================================================ FILE: python/tink/aead/_aead_wrapper.py ================================================ [File too large to display: 2.5 KB] ================================================ FILE: python/tink/aead/_aead_wrapper_test.py ================================================ [File too large to display: 4.9 KB] ================================================ FILE: python/tink/aead/_kms_aead_key_manager.py ================================================ [File too large to display: 3.8 KB] ================================================ FILE: python/tink/aead/_kms_aead_key_manager_test.py ================================================ [File too large to display: 4.1 KB] ================================================ FILE: python/tink/aead/_kms_envelope_aead.py ================================================ [File too large to display: 4.3 KB] ================================================ FILE: python/tink/aead/_kms_envelope_aead_test.py ================================================ [File too large to display: 6.4 KB] ================================================ FILE: python/tink/cc/BUILD.bazel ================================================ [File too large to display: 6.1 KB] ================================================ FILE: python/tink/cc/cc_hpke_config.cc ================================================ [File too large to display: 912 B] ================================================ FILE: python/tink/cc/cc_hpke_config.h ================================================ [File too large to display: 964 B] ================================================ FILE: python/tink/cc/cc_jwt_config.cc ================================================ [File too large to display: 2.1 KB] ================================================ FILE: python/tink/cc/cc_jwt_config.h ================================================ [File too large to display: 1001 B] ================================================ FILE: python/tink/cc/cc_key_manager.h ================================================ [File too large to display: 4.5 KB] ================================================ FILE: python/tink/cc/cc_streaming_aead_wrappers.cc ================================================ [File too large to display: 2.3 KB] ================================================ FILE: python/tink/cc/cc_streaming_aead_wrappers.h ================================================ [File too large to display: 2.4 KB] ================================================ FILE: python/tink/cc/cc_streaming_aead_wrappers_test.cc ================================================ [File too large to display: 1.7 KB] ================================================ FILE: python/tink/cc/cc_tink_config.cc ================================================ [File too large to display: 1.1 KB] ================================================ FILE: python/tink/cc/cc_tink_config.h ================================================ [File too large to display: 983 B] ================================================ FILE: python/tink/cc/input_stream_adapter.cc ================================================ [File too large to display: 1.4 KB] ================================================ FILE: python/tink/cc/input_stream_adapter.h ================================================ [File too large to display: 1.5 KB] ================================================ FILE: python/tink/cc/input_stream_adapter_test.cc ================================================ [File too large to display: 4.0 KB] ================================================ FILE: python/tink/cc/output_stream_adapter.cc ================================================ [File too large to display: 1.5 KB] ================================================ FILE: python/tink/cc/output_stream_adapter.h ================================================ [File too large to display: 1.8 KB] ================================================ FILE: python/tink/cc/output_stream_adapter_test.cc ================================================ [File too large to display: 3.4 KB] ================================================ FILE: python/tink/cc/pybind/BUILD.bazel ================================================ [File too large to display: 6.9 KB] ================================================ FILE: python/tink/cc/pybind/aead.cc ================================================ [File too large to display: 3.1 KB] ================================================ FILE: python/tink/cc/pybind/aead.h ================================================ [File too large to display: 969 B] ================================================ FILE: python/tink/cc/pybind/cc_hpke_config.cc ================================================ [File too large to display: 1.2 KB] ================================================ FILE: python/tink/cc/pybind/cc_hpke_config.h ================================================ [File too large to display: 1003 B] ================================================ FILE: python/tink/cc/pybind/cc_jwt_config.cc ================================================ [File too large to display: 1.2 KB] ================================================ FILE: python/tink/cc/pybind/cc_jwt_config.h ================================================ [File too large to display: 997 B] ================================================ FILE: python/tink/cc/pybind/cc_key_manager.cc ================================================ [File too large to display: 3.7 KB] ================================================ FILE: python/tink/cc/pybind/cc_key_manager.h ================================================ [File too large to display: 1002 B] ================================================ FILE: python/tink/cc/pybind/cc_key_manager_test.py ================================================ [File too large to display: 25.0 KB] ================================================ FILE: python/tink/cc/pybind/cc_streaming_aead_wrappers.cc ================================================ [File too large to display: 2.7 KB] ================================================ FILE: python/tink/cc/pybind/cc_streaming_aead_wrappers.h ================================================ [File too large to display: 1.0 KB] ================================================ FILE: python/tink/cc/pybind/cc_tink_config.cc ================================================ [File too large to display: 1.0 KB] ================================================ FILE: python/tink/cc/pybind/cc_tink_config.h ================================================ [File too large to display: 1001 B] ================================================ FILE: python/tink/cc/pybind/cc_tink_config_test.py ================================================ [File too large to display: 855 B] ================================================ FILE: python/tink/cc/pybind/deterministic_aead.cc ================================================ [File too large to display: 3.6 KB] ================================================ FILE: python/tink/cc/pybind/deterministic_aead.h ================================================ [File too large to display: 1019 B] ================================================ FILE: python/tink/cc/pybind/hybrid_decrypt.cc ================================================ [File too large to display: 1.8 KB] ================================================ FILE: python/tink/cc/pybind/hybrid_decrypt.h ================================================ [File too large to display: 1003 B] ================================================ FILE: python/tink/cc/pybind/hybrid_encrypt.cc ================================================ [File too large to display: 1.8 KB] ================================================ FILE: python/tink/cc/pybind/hybrid_encrypt.h ================================================ [File too large to display: 1003 B] ================================================ FILE: python/tink/cc/pybind/import_helper.cc ================================================ [File too large to display: 1.1 KB] ================================================ FILE: python/tink/cc/pybind/import_helper.h ================================================ [File too large to display: 1.2 KB] ================================================ FILE: python/tink/cc/pybind/input_stream_adapter.cc ================================================ [File too large to display: 2.3 KB] ================================================ FILE: python/tink/cc/pybind/input_stream_adapter.h ================================================ [File too large to display: 1.0 KB] ================================================ FILE: python/tink/cc/pybind/mac.cc ================================================ [File too large to display: 2.5 KB] ================================================ FILE: python/tink/cc/pybind/mac.h ================================================ [File too large to display: 960 B] ================================================ FILE: python/tink/cc/pybind/output_stream_adapter.cc ================================================ [File too large to display: 1.8 KB] ================================================ FILE: python/tink/cc/pybind/output_stream_adapter.h ================================================ [File too large to display: 1.0 KB] ================================================ FILE: python/tink/cc/pybind/prf.cc ================================================ [File too large to display: 1.8 KB] ================================================ FILE: python/tink/cc/pybind/prf.h ================================================ [File too large to display: 965 B] ================================================ FILE: python/tink/cc/pybind/public_key_sign.cc ================================================ [File too large to display: 2.2 KB] ================================================ FILE: python/tink/cc/pybind/public_key_sign.h ================================================ [File too large to display: 1006 B] ================================================ FILE: python/tink/cc/pybind/public_key_verify.cc ================================================ [File too large to display: 2.3 KB] ================================================ FILE: python/tink/cc/pybind/public_key_verify.h ================================================ [File too large to display: 1013 B] ================================================ FILE: python/tink/cc/pybind/python_file_object_adapter.cc ================================================ [File too large to display: 4.6 KB] ================================================ FILE: python/tink/cc/pybind/python_file_object_adapter.h ================================================ [File too large to display: 1.0 KB] ================================================ FILE: python/tink/cc/pybind/streaming_aead.cc ================================================ [File too large to display: 1.8 KB] ================================================ FILE: python/tink/cc/pybind/streaming_aead.h ================================================ [File too large to display: 1008 B] ================================================ FILE: python/tink/cc/pybind/tink_bindings.cc ================================================ [File too large to display: 2.3 KB] ================================================ FILE: python/tink/cc/pybind/tink_exception.h ================================================ [File too large to display: 1.4 KB] ================================================ FILE: python/tink/cc/python_file_object_adapter.h ================================================ [File too large to display: 1.7 KB] ================================================ FILE: python/tink/cc/python_input_stream.cc ================================================ [File too large to display: 3.3 KB] ================================================ FILE: python/tink/cc/python_input_stream.h ================================================ [File too large to display: 2.2 KB] ================================================ FILE: python/tink/cc/python_input_stream_test.cc ================================================ [File too large to display: 6.4 KB] ================================================ FILE: python/tink/cc/python_output_stream.cc ================================================ [File too large to display: 4.0 KB] ================================================ FILE: python/tink/cc/python_output_stream.h ================================================ [File too large to display: 2.2 KB] ================================================ FILE: python/tink/cc/python_output_stream_test.cc ================================================ [File too large to display: 7.2 KB] ================================================ FILE: python/tink/cc/test_util.h ================================================ [File too large to display: 11.3 KB] ================================================ FILE: python/tink/cleartext_keyset_handle.py ================================================ [File too large to display: 1.4 KB] ================================================ FILE: python/tink/cleartext_keyset_handle_test.py ================================================ [File too large to display: 2.0 KB] ================================================ FILE: python/tink/core/BUILD.bazel ================================================ [File too large to display: 2.5 KB] ================================================ FILE: python/tink/core/__init__.py ================================================ [File too large to display: 1.4 KB] ================================================ FILE: python/tink/core/_crypto_format.py ================================================ [File too large to display: 1.5 KB] ================================================ FILE: python/tink/core/_crypto_format_test.py ================================================ [File too large to display: 2.7 KB] ================================================ FILE: python/tink/core/_key_manager.py ================================================ [File too large to display: 5.1 KB] ================================================ FILE: python/tink/core/_primitive_set.py ================================================ [File too large to display: 3.6 KB] ================================================ FILE: python/tink/core/_primitive_set_test.py ================================================ [File too large to display: 9.7 KB] ================================================ FILE: python/tink/core/_primitive_wrapper.py ================================================ [File too large to display: 1.7 KB] ================================================ FILE: python/tink/core/_registry.py ================================================ [File too large to display: 8.9 KB] ================================================ FILE: python/tink/core/_registry_test.py ================================================ [File too large to display: 14.3 KB] ================================================ FILE: python/tink/core/_tink_error.py ================================================ [File too large to display: 1.3 KB] ================================================ FILE: python/tink/daead/BUILD.bazel ================================================ [File too large to display: 2.3 KB] ================================================ FILE: python/tink/daead/__init__.py ================================================ [File too large to display: 914 B] ================================================ FILE: python/tink/daead/_deterministic_aead.py ================================================ [File too large to display: 1.9 KB] ================================================ FILE: python/tink/daead/_deterministic_aead_key_manager.py ================================================ [File too large to display: 2.1 KB] ================================================ FILE: python/tink/daead/_deterministic_aead_key_manager_test.py ================================================ [File too large to display: 2.5 KB] ================================================ FILE: python/tink/daead/_deterministic_aead_key_templates.py ================================================ [File too large to display: 1.7 KB] ================================================ FILE: python/tink/daead/_deterministic_aead_key_templates_test.py ================================================ [File too large to display: 1.6 KB] ================================================ FILE: python/tink/daead/_deterministic_aead_wrapper.py ================================================ [File too large to display: 3.2 KB] ================================================ FILE: python/tink/daead/_deterministic_aead_wrapper_test.py ================================================ [File too large to display: 5.8 KB] ================================================ FILE: python/tink/hybrid/BUILD.bazel ================================================ [File too large to display: 2.6 KB] ================================================ FILE: python/tink/hybrid/__init__.py ================================================ [File too large to display: 927 B] ================================================ FILE: python/tink/hybrid/_hybrid_decrypt.py ================================================ [File too large to display: 2.4 KB] ================================================ FILE: python/tink/hybrid/_hybrid_encrypt.py ================================================ [File too large to display: 2.4 KB] ================================================ FILE: python/tink/hybrid/_hybrid_key_manager.py ================================================ [File too large to display: 3.6 KB] ================================================ FILE: python/tink/hybrid/_hybrid_key_manager_test.py ================================================ [File too large to display: 8.1 KB] ================================================ FILE: python/tink/hybrid/_hybrid_key_templates.py ================================================ [File too large to display: 5.7 KB] ================================================ FILE: python/tink/hybrid/_hybrid_key_templates_test.py ================================================ [File too large to display: 3.0 KB] ================================================ FILE: python/tink/hybrid/_hybrid_wrapper.py ================================================ [File too large to display: 3.9 KB] ================================================ FILE: python/tink/hybrid/_hybrid_wrapper_test.py ================================================ [File too large to display: 9.6 KB] ================================================ FILE: python/tink/integration/__init__.py ================================================ [File too large to display: 575 B] ================================================ FILE: python/tink/integration/awskms/BUILD.bazel ================================================ [File too large to display: 1.5 KB] ================================================ FILE: python/tink/integration/awskms/__init__.py ================================================ [File too large to display: 986 B] ================================================ FILE: python/tink/integration/awskms/_aws_kms_client.py ================================================ [File too large to display: 8.0 KB] ================================================ FILE: python/tink/integration/awskms/_aws_kms_client_test.py ================================================ [File too large to display: 8.0 KB] ================================================ FILE: python/tink/integration/awskms/_aws_kms_integration_test.py ================================================ [File too large to display: 9.9 KB] ================================================ FILE: python/tink/integration/gcpkms/BUILD.bazel ================================================ [File too large to display: 2.2 KB] ================================================ FILE: python/tink/integration/gcpkms/__init__.py ================================================ [File too large to display: 943 B] ================================================ FILE: python/tink/integration/gcpkms/_gcp_kms_aead_test.py ================================================ [File too large to display: 4.4 KB] ================================================ FILE: python/tink/integration/gcpkms/_gcp_kms_client.py ================================================ [File too large to display: 5.7 KB] ================================================ FILE: python/tink/integration/gcpkms/_gcp_kms_client_integration_test.py ================================================ [File too large to display: 5.7 KB] ================================================ FILE: python/tink/integration/gcpkms/_gcp_kms_client_test.py ================================================ [File too large to display: 4.8 KB] ================================================ FILE: python/tink/integration/gcpkms/_gcp_kms_integration_test.py ================================================ [File too large to display: 9.5 KB] ================================================ FILE: python/tink/integration/hcvault/BUILD.bazel ================================================ [File too large to display: 1.3 KB] ================================================ FILE: python/tink/integration/hcvault/__init__.py ================================================ [File too large to display: 967 B] ================================================ FILE: python/tink/integration/hcvault/_hcvault_kms_aead.py ================================================ [File too large to display: 3.9 KB] ================================================ FILE: python/tink/integration/hcvault/_hcvault_kms_aead_test.py ================================================ [File too large to display: 6.8 KB] ================================================ FILE: python/tink/integration/hcvault/_hcvault_kms_integration_test.py ================================================ [File too large to display: 3.4 KB] ================================================ FILE: python/tink/internal/BUILD.bazel ================================================ [File too large to display: 504 B] ================================================ FILE: python/tink/internal/__init__.py ================================================ [File too large to display: 575 B] ================================================ FILE: python/tink/internal/big_integer_util.py ================================================ [File too large to display: 918 B] ================================================ FILE: python/tink/internal/big_integer_util_test.py ================================================ [File too large to display: 1.5 KB] ================================================ FILE: python/tink/jwt/BUILD.bazel ================================================ [File too large to display: 7.7 KB] ================================================ FILE: python/tink/jwt/__init__.py ================================================ [File too large to display: 4.1 KB] ================================================ FILE: python/tink/jwt/_json_util.py ================================================ [File too large to display: 2.1 KB] ================================================ FILE: python/tink/jwt/_json_util_test.py ================================================ [File too large to display: 2.1 KB] ================================================ FILE: python/tink/jwt/_jwk_set_converter.py ================================================ [File too large to display: 12.6 KB] ================================================ FILE: python/tink/jwt/_jwk_set_converter_test.py ================================================ [File too large to display: 36.9 KB] ================================================ FILE: python/tink/jwt/_jwt_error.py ================================================ [File too large to display: 682 B] ================================================ FILE: python/tink/jwt/_jwt_format.py ================================================ [File too large to display: 7.0 KB] ================================================ FILE: python/tink/jwt/_jwt_format_test.py ================================================ [File too large to display: 17.0 KB] ================================================ FILE: python/tink/jwt/_jwt_hmac_key_manager.py ================================================ [File too large to display: 4.9 KB] ================================================ FILE: python/tink/jwt/_jwt_hmac_key_manager_test.py ================================================ [File too large to display: 12.7 KB] ================================================ FILE: python/tink/jwt/_jwt_key_templates.py ================================================ [File too large to display: 7.4 KB] ================================================ FILE: python/tink/jwt/_jwt_key_templates_test.py ================================================ [File too large to display: 3.9 KB] ================================================ FILE: python/tink/jwt/_jwt_mac.py ================================================ [File too large to display: 3.1 KB] ================================================ FILE: python/tink/jwt/_jwt_mac_wrapper.py ================================================ [File too large to display: 3.3 KB] ================================================ FILE: python/tink/jwt/_jwt_mac_wrapper_test.py ================================================ [File too large to display: 10.4 KB] ================================================ FILE: python/tink/jwt/_jwt_public_key_sign.py ================================================ [File too large to display: 1.6 KB] ================================================ FILE: python/tink/jwt/_jwt_public_key_verify.py ================================================ [File too large to display: 2.5 KB] ================================================ FILE: python/tink/jwt/_jwt_signature_key_manager.py ================================================ [File too large to display: 12.8 KB] ================================================ FILE: python/tink/jwt/_jwt_signature_key_manager_test.py ================================================ [File too large to display: 11.4 KB] ================================================ FILE: python/tink/jwt/_jwt_signature_wrappers.py ================================================ [File too large to display: 4.0 KB] ================================================ FILE: python/tink/jwt/_jwt_signature_wrappers_test.py ================================================ [File too large to display: 13.2 KB] ================================================ FILE: python/tink/jwt/_jwt_validator.py ================================================ [File too large to display: 8.2 KB] ================================================ FILE: python/tink/jwt/_jwt_validator_test.py ================================================ [File too large to display: 14.5 KB] ================================================ FILE: python/tink/jwt/_raw_jwt.py ================================================ [File too large to display: 9.2 KB] ================================================ FILE: python/tink/jwt/_raw_jwt_test.py ================================================ [File too large to display: 16.3 KB] ================================================ FILE: python/tink/jwt/_verified_jwt.py ================================================ [File too large to display: 2.8 KB] ================================================ FILE: python/tink/jwt/_verified_jwt_test.py ================================================ [File too large to display: 4.1 KB] ================================================ FILE: python/tink/mac/BUILD.bazel ================================================ [File too large to display: 2.1 KB] ================================================ FILE: python/tink/mac/__init__.py ================================================ [File too large to display: 774 B] ================================================ FILE: python/tink/mac/_mac.py ================================================ [File too large to display: 1.7 KB] ================================================ FILE: python/tink/mac/_mac_key_manager.py ================================================ [File too large to display: 1.6 KB] ================================================ FILE: python/tink/mac/_mac_key_manager_test.py ================================================ [File too large to display: 2.9 KB] ================================================ FILE: python/tink/mac/_mac_key_templates.py ================================================ [File too large to display: 3.3 KB] ================================================ FILE: python/tink/mac/_mac_key_templates_test.py ================================================ [File too large to display: 2.0 KB] ================================================ FILE: python/tink/mac/_mac_wrapper.py ================================================ [File too large to display: 3.2 KB] ================================================ FILE: python/tink/mac/_mac_wrapper_test.py ================================================ [File too large to display: 4.9 KB] ================================================ FILE: python/tink/prf/BUILD.bazel ================================================ [File too large to display: 2.0 KB] ================================================ FILE: python/tink/prf/__init__.py ================================================ [File too large to display: 809 B] ================================================ FILE: python/tink/prf/_prf_key_manager.py ================================================ [File too large to display: 1.7 KB] ================================================ FILE: python/tink/prf/_prf_key_manager_test.py ================================================ [File too large to display: 3.3 KB] ================================================ FILE: python/tink/prf/_prf_key_templates.py ================================================ [File too large to display: 3.0 KB] ================================================ FILE: python/tink/prf/_prf_set.py ================================================ [File too large to display: 3.1 KB] ================================================ FILE: python/tink/prf/_prf_set_wrapper.py ================================================ [File too large to display: 2.1 KB] ================================================ FILE: python/tink/prf/_prf_set_wrapper_test.py ================================================ [File too large to display: 2.7 KB] ================================================ FILE: python/tink/proto/BUILD.bazel ================================================ [File too large to display: 5.3 KB] ================================================ FILE: python/tink/proto/__init__.py ================================================ [File too large to display: 575 B] ================================================ FILE: python/tink/proto/aes_cmac.proto ================================================ [File too large to display: 1.2 KB] ================================================ FILE: python/tink/proto/aes_cmac_prf.proto ================================================ [File too large to display: 1.1 KB] ================================================ FILE: python/tink/proto/aes_ctr.proto ================================================ [File too large to display: 1.1 KB] ================================================ FILE: python/tink/proto/aes_ctr_hmac_aead.proto ================================================ [File too large to display: 1.2 KB] ================================================ FILE: python/tink/proto/aes_ctr_hmac_streaming.proto ================================================ [File too large to display: 1.7 KB] ================================================ FILE: python/tink/proto/aes_eax.proto ================================================ [File too large to display: 1.2 KB] ================================================ FILE: python/tink/proto/aes_gcm.proto ================================================ [File too large to display: 2.5 KB] ================================================ FILE: python/tink/proto/aes_gcm_hkdf_streaming.proto ================================================ [File too large to display: 1.6 KB] ================================================ FILE: python/tink/proto/aes_gcm_siv.proto ================================================ [File too large to display: 1.2 KB] ================================================ FILE: python/tink/proto/aes_siv.proto ================================================ [File too large to display: 1.5 KB] ================================================ FILE: python/tink/proto/chacha20_poly1305.proto ================================================ [File too large to display: 1.2 KB] ================================================ FILE: python/tink/proto/common.proto ================================================ [File too large to display: 1.5 KB] ================================================ FILE: python/tink/proto/config.proto ================================================ [File too large to display: 1.9 KB] ================================================ FILE: python/tink/proto/ecdsa.proto ================================================ [File too large to display: 2.5 KB] ================================================ FILE: python/tink/proto/ecies_aead_hkdf.proto ================================================ [File too large to display: 3.6 KB] ================================================ FILE: python/tink/proto/ed25519.proto ================================================ [File too large to display: 1.7 KB] ================================================ FILE: python/tink/proto/empty.proto ================================================ [File too large to display: 908 B] ================================================ FILE: python/tink/proto/hkdf_prf.proto ================================================ [File too large to display: 1.4 KB] ================================================ FILE: python/tink/proto/hmac.proto ================================================ [File too large to display: 1.2 KB] ================================================ FILE: python/tink/proto/hmac_prf.proto ================================================ [File too large to display: 1.2 KB] ================================================ FILE: python/tink/proto/hpke.proto ================================================ [File too large to display: 1.9 KB] ================================================ FILE: python/tink/proto/jwt_ecdsa.proto ================================================ [File too large to display: 2.0 KB] ================================================ FILE: python/tink/proto/jwt_hmac.proto ================================================ [File too large to display: 1.5 KB] ================================================ FILE: python/tink/proto/jwt_rsa_ssa_pkcs1.proto ================================================ [File too large to display: 2.7 KB] ================================================ FILE: python/tink/proto/jwt_rsa_ssa_pss.proto ================================================ [File too large to display: 2.7 KB] ================================================ FILE: python/tink/proto/kms_aead.proto ================================================ [File too large to display: 1.4 KB] ================================================ FILE: python/tink/proto/kms_envelope.proto ================================================ [File too large to display: 1.6 KB] ================================================ FILE: python/tink/proto/prf_based_deriver.proto ================================================ [File too large to display: 1.3 KB] ================================================ FILE: python/tink/proto/rsa_ssa_pkcs1.proto ================================================ [File too large to display: 2.7 KB] ================================================ FILE: python/tink/proto/rsa_ssa_pss.proto ================================================ [File too large to display: 3.0 KB] ================================================ FILE: python/tink/proto/test_proto.proto ================================================ [File too large to display: 1.1 KB] ================================================ FILE: python/tink/proto/tink.proto ================================================ [File too large to display: 7.1 KB] ================================================ FILE: python/tink/proto/xchacha20_poly1305.proto ================================================ [File too large to display: 1.1 KB] ================================================ FILE: python/tink/secret_key_access.py ================================================ [File too large to display: 852 B] ================================================ FILE: python/tink/secret_key_access_import_test.py ================================================ [File too large to display: 1.2 KB] ================================================ FILE: python/tink/secret_key_access_test.py ================================================ [File too large to display: 1.2 KB] ================================================ FILE: python/tink/signature/BUILD.bazel ================================================ [File too large to display: 2.3 KB] ================================================ FILE: python/tink/signature/__init__.py ================================================ [File too large to display: 966 B] ================================================ FILE: python/tink/signature/_public_key_sign.py ================================================ [File too large to display: 1.3 KB] ================================================ FILE: python/tink/signature/_public_key_verify.py ================================================ [File too large to display: 1.5 KB] ================================================ FILE: python/tink/signature/_signature_key_manager.py ================================================ [File too large to display: 2.8 KB] ================================================ FILE: python/tink/signature/_signature_key_manager_test.py ================================================ [File too large to display: 4.8 KB] ================================================ FILE: python/tink/signature/_signature_key_templates.py ================================================ [File too large to display: 7.7 KB] ================================================ FILE: python/tink/signature/_signature_wrapper.py ================================================ [File too large to display: 5.0 KB] ================================================ FILE: python/tink/signature/_signature_wrapper_test.py ================================================ [File too large to display: 5.7 KB] ================================================ FILE: python/tink/streaming_aead/BUILD.bazel ================================================ [File too large to display: 5.3 KB] ================================================ FILE: python/tink/streaming_aead/__init__.py ================================================ [File too large to display: 904 B] ================================================ FILE: python/tink/streaming_aead/_decrypting_stream.py ================================================ [File too large to display: 4.7 KB] ================================================ FILE: python/tink/streaming_aead/_decrypting_stream_test.py ================================================ [File too large to display: 2.8 KB] ================================================ FILE: python/tink/streaming_aead/_encrypting_stream.py ================================================ [File too large to display: 3.8 KB] ================================================ FILE: python/tink/streaming_aead/_encrypting_stream_test.py ================================================ [File too large to display: 3.7 KB] ================================================ FILE: python/tink/streaming_aead/_file_object_adapter.py ================================================ [File too large to display: 2.1 KB] ================================================ FILE: python/tink/streaming_aead/_file_object_adapter_test.py ================================================ [File too large to display: 4.0 KB] ================================================ FILE: python/tink/streaming_aead/_pybind11_python_file_object_adapter_test.py ================================================ [File too large to display: 3.1 KB] ================================================ FILE: python/tink/streaming_aead/_raw_streaming_aead.py ================================================ [File too large to display: 4.6 KB] ================================================ FILE: python/tink/streaming_aead/_rewindable_input_stream.py ================================================ [File too large to display: 3.0 KB] ================================================ FILE: python/tink/streaming_aead/_rewindable_input_stream_test.py ================================================ [File too large to display: 6.2 KB] ================================================ FILE: python/tink/streaming_aead/_streaming_aead.py ================================================ [File too large to display: 4.4 KB] ================================================ FILE: python/tink/streaming_aead/_streaming_aead_key_manager.py ================================================ [File too large to display: 2.8 KB] ================================================ FILE: python/tink/streaming_aead/_streaming_aead_key_manager_test.py ================================================ [File too large to display: 10.2 KB] ================================================ FILE: python/tink/streaming_aead/_streaming_aead_key_templates.py ================================================ [File too large to display: 6.4 KB] ================================================ FILE: python/tink/streaming_aead/_streaming_aead_key_templates_test.py ================================================ [File too large to display: 3.5 KB] ================================================ FILE: python/tink/streaming_aead/_streaming_aead_test.py ================================================ [File too large to display: 4.4 KB] ================================================ FILE: python/tink/streaming_aead/_streaming_aead_wrapper.py ================================================ [File too large to display: 6.5 KB] ================================================ FILE: python/tink/streaming_aead/_streaming_aead_wrapper_test.py ================================================ [File too large to display: 11.8 KB] ================================================ FILE: python/tink/testing/BUILD.bazel ================================================ [File too large to display: 2.1 KB] ================================================ FILE: python/tink/testing/__init__.py ================================================ [File too large to display: 575 B] ================================================ FILE: python/tink/testing/bytes_io.py ================================================ [File too large to display: 3.5 KB] ================================================ FILE: python/tink/testing/bytes_io_test.py ================================================ [File too large to display: 5.3 KB] ================================================ FILE: python/tink/testing/fake_kms.py ================================================ [File too large to display: 1.8 KB] ================================================ FILE: python/tink/testing/fake_kms_test.py ================================================ [File too large to display: 2.2 KB] ================================================ FILE: python/tink/testing/helper.py ================================================ [File too large to display: 6.4 KB] ================================================ FILE: python/tink/testing/helper_test.py ================================================ [File too large to display: 5.3 KB] ================================================ FILE: python/tink/testing/keyset_builder.py ================================================ [File too large to display: 4.2 KB] ================================================ FILE: python/tink/testing/keyset_builder_test.py ================================================ [File too large to display: 6.9 KB] ================================================ FILE: python/tink/tink_config.py ================================================ [File too large to display: 965 B] ================================================ FILE: python/tink/tink_config_test.py ================================================ [File too large to display: 4.1 KB] ================================================ FILE: python/tink_py_deps.bzl ================================================ [File too large to display: 1.7 KB] ================================================ FILE: python/tink_py_deps_init.bzl ================================================ [File too large to display: 809 B] ================================================ FILE: python/tools/BUILD.bazel ================================================ [File too large to display: 76 B] ================================================ FILE: python/tools/distribution/README.md ================================================ [File too large to display: 1.8 KB] ================================================ FILE: python/tools/distribution/build_linux_binary_wheels.sh ================================================ [File too large to display: 3.7 KB] ================================================ FILE: python/tools/distribution/create_release.sh ================================================ [File too large to display: 6.3 KB] ================================================ FILE: python/tools/distribution/requirements.in ================================================ [File too large to display: 21 B] ================================================ FILE: python/tools/distribution/requirements.txt ================================================ [File too large to display: 869 B] ================================================ FILE: python/tools/distribution/test_linux_binary_wheels.sh ================================================ [File too large to display: 2.8 KB] ================================================ FILE: testdata/BUILD.bazel ================================================ ================================================ FILE: testdata/aws/BUILD.bazel ================================================ [File too large to display: 461 B] ================================================ FILE: testdata/aws/README.md ================================================ [File too large to display: 935 B] ================================================ FILE: testdata/aws/access_keys_bad.csv ================================================ [File too large to display: 94 B] ================================================ FILE: testdata/aws/credentials.cred ================================================ [File too large to display: 96 B] ================================================ FILE: testdata/aws/credentials.csv ================================================ [File too large to display: 196 B] ================================================ FILE: testdata/aws/credentials.ini ================================================ [File too large to display: 116 B] ================================================ FILE: testdata/aws/credentials_bad.csv ================================================ [File too large to display: 115 B] ================================================ FILE: testdata/aws/credentials_bad.ini ================================================ [File too large to display: 116 B] ================================================ FILE: testdata/aws/key_arn.txt ================================================ [File too large to display: 76 B] ================================================ FILE: testdata/aws/key_arn_bad.txt ================================================ [File too large to display: 76 B] ================================================ FILE: testdata/gcp/BUILD.bazel ================================================ [File too large to display: 389 B] ================================================ FILE: testdata/gcp/README.md ================================================ [File too large to display: 361 B] ================================================ FILE: testdata/gcp/credential.json ================================================ [File too large to display: 1.5 KB] ================================================ FILE: testdata/gcp/credential_bad.json ================================================ [File too large to display: 1.5 KB] ================================================ FILE: testdata/gcp/key_name.txt ================================================ [File too large to display: 110 B] ================================================ FILE: testdata/gcp/key_name_bad.txt ================================================ [File too large to display: 91 B] ================================================ FILE: testdata/keysets/BUILD.bazel ================================================ [File too large to display: 937 B] ================================================ FILE: testdata/testvectors/BUILD.bazel ================================================ [File too large to display: 7.2 KB] ================================================ FILE: testdata/testvectors/hpke_boringssl.json ================================================ [File too large to display: 6.0 MB] ================================================ FILE: testing/cross_language/testdata/aws/BUILD.bazel ================================================ [File too large to display: 461 B] ================================================ FILE: testing/cross_language/testdata/aws/README.md ================================================ [File too large to display: 935 B] ================================================ FILE: testing/cross_language/testdata/aws/access_keys_bad.csv ================================================ [File too large to display: 94 B] ================================================ FILE: testing/cross_language/testdata/aws/credentials.cred ================================================ [File too large to display: 96 B] ================================================ FILE: testing/cross_language/testdata/aws/credentials.csv ================================================ [File too large to display: 196 B] ================================================ FILE: testing/cross_language/testdata/aws/credentials.ini ================================================ [File too large to display: 116 B] ================================================ FILE: testing/cross_language/testdata/aws/credentials_bad.csv ================================================ [File too large to display: 115 B] ================================================ FILE: testing/cross_language/testdata/aws/credentials_bad.ini ================================================ [File too large to display: 116 B] ================================================ FILE: testing/cross_language/testdata/aws/key_arn.txt ================================================ [File too large to display: 76 B] ================================================ FILE: testing/cross_language/testdata/aws/key_arn_bad.txt ================================================ [File too large to display: 76 B] ================================================ FILE: testing/cross_language/testdata/gcp/BUILD.bazel ================================================ [File too large to display: 389 B] ================================================ FILE: testing/cross_language/testdata/gcp/README.md ================================================ [File too large to display: 361 B] ================================================ FILE: testing/cross_language/testdata/gcp/credential.json ================================================ [File too large to display: 1.5 KB] ================================================ FILE: testing/cross_language/testdata/gcp/credential_bad.json ================================================ [File too large to display: 1.5 KB] ================================================ FILE: testing/cross_language/testdata/gcp/key_name.txt ================================================ [File too large to display: 110 B] ================================================ FILE: testing/cross_language/testdata/gcp/key_name_bad.txt ================================================ [File too large to display: 91 B] ================================================ FILE: tinkey.rb ================================================ [File too large to display: 556 B] ================================================ FILE: tools/.bazelrc ================================================ [File too large to display: 259 B] ================================================ FILE: tools/.bazelversion ================================================ [File too large to display: 6 B] ================================================ FILE: tools/BUILD.bazel ================================================ [File too large to display: 76 B] ================================================ FILE: tools/WORKSPACE ================================================ [File too large to display: 1005 B] ================================================ FILE: tools/build_defs/BUILD.bazel ================================================ [File too large to display: 387 B] ================================================ FILE: tools/coverage.sh ================================================ [File too large to display: 2.3 KB] ================================================ FILE: tools/release_tinkey.sh ================================================ [File too large to display: 2.9 KB] ================================================ FILE: tools/requirements.txt ================================================ [File too large to display: 8 B] ================================================ FILE: tools/tinkey/BUILD.bazel ================================================ [File too large to display: 264 B] ================================================ FILE: tools/tinkey/README.md ================================================ [File too large to display: 44 B] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/AddKeyCommand.java ================================================ [File too large to display: 2.3 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/AddRotateOptions.java ================================================ [File too large to display: 1.1 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/BUILD.bazel ================================================ [File too large to display: 9.1 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/Command.java ================================================ [File too large to display: 837 B] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/ConvertKeysetCommand.java ================================================ [File too large to display: 2.4 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/ConvertKeysetOptions.java ================================================ [File too large to display: 1.4 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/CreateKeysetCommand.java ================================================ [File too large to display: 1.9 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/CreateKeysetOptions.java ================================================ [File too large to display: 1.1 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/CreatePublicKeysetCommand.java ================================================ [File too large to display: 1.7 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/DeleteKeyCommand.java ================================================ [File too large to display: 1.6 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/DestroyKeyCommand.java ================================================ [File too large to display: 1.7 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/DisableKeyCommand.java ================================================ [File too large to display: 1.7 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/EnableKeyCommand.java ================================================ [File too large to display: 1.6 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/HelpCommand.java ================================================ [File too large to display: 2.1 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/InOptions.java ================================================ [File too large to display: 2.9 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/InputStreamHandler.java ================================================ [File too large to display: 1.9 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/KeyIdHandler.java ================================================ [File too large to display: 1.3 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/KeyIdOptions.java ================================================ [File too large to display: 1.0 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/KeyTemplateHandler.java ================================================ [File too large to display: 2.0 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/KmsClientsFactory.java ================================================ [File too large to display: 2.2 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/ListKeyTemplatesCommand.java ================================================ [File too large to display: 1.3 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/ListKeysetCommand.java ================================================ [File too large to display: 1.6 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/OutOptions.java ================================================ [File too large to display: 1.6 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/OutputStreamHandler.java ================================================ [File too large to display: 1.9 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/PromoteKeyCommand.java ================================================ [File too large to display: 1.6 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/RotateKeysetCommand.java ================================================ [File too large to display: 1.9 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/Tinkey.java ================================================ [File too large to display: 2.4 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/TinkeyCommands.java ================================================ [File too large to display: 2.1 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/TinkeyKeyTemplates.java ================================================ [File too large to display: 3.6 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/TinkeyTestKmsClient.java ================================================ [File too large to display: 3.7 KB] ================================================ FILE: tools/tinkey/src/main/java/com/google/crypto/tink/tinkey/TinkeyUtil.java ================================================ [File too large to display: 8.9 KB] ================================================ FILE: tools/tinkey/src/test/java/com/google/crypto/tink/tinkey/AddKeyCommandTest.java ================================================ [File too large to display: 9.0 KB] ================================================ FILE: tools/tinkey/src/test/java/com/google/crypto/tink/tinkey/BUILD.bazel ================================================ [File too large to display: 7.4 KB] ================================================ FILE: tools/tinkey/src/test/java/com/google/crypto/tink/tinkey/ConvertKeysetCommandTest.java ================================================ [File too large to display: 7.5 KB] ================================================ FILE: tools/tinkey/src/test/java/com/google/crypto/tink/tinkey/CreateKeysetCommandTest.java ================================================ [File too large to display: 6.5 KB] ================================================ FILE: tools/tinkey/src/test/java/com/google/crypto/tink/tinkey/CreatePublicKeysetCommandTest.java ================================================ [File too large to display: 7.8 KB] ================================================ FILE: tools/tinkey/src/test/java/com/google/crypto/tink/tinkey/KmsClientsFactoryTest.java ================================================ [File too large to display: 2.5 KB] ================================================ FILE: tools/tinkey/src/test/java/com/google/crypto/tink/tinkey/RotateKeysetCommandTest.java ================================================ [File too large to display: 9.6 KB] ================================================ FILE: tools/tinkey/src/test/java/com/google/crypto/tink/tinkey/TinkeyTestKmsClientTest.java ================================================ [File too large to display: 4.7 KB]